summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/softfloat3/source/s_addCarryM.c
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/softfloat3/source/s_addCarryM.c')
0 files changed, 0 insertions, 0 deletions
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
+ {
+ UML_MOV(block, SPR32(SPR603_IMISS), I0); // mov [imiss],i0
+ UML_MOV(block, SPR32(SPR603_ICMP), mem(&ppc->mmu603_cmp)); // mov [icmp],[mmu603_cmp]
+ UML_MOV(block, SPR32(SPR603_HASH1), mem(&ppc->mmu603_hash[0])); // mov [hash1],[mmu603_hash][0]
+ UML_MOV(block, SPR32(SPR603_HASH2), mem(&ppc->mmu603_hash[1])); // mov [hash2],[mmu603_hash][1]
+ UML_EXH(block, *ppc->impstate->exception[EXCEPTION_ITLBMISS], I0); // exh itlbmiss,i0
+ }
+
+ block->end();
+}
+
+
+/*-------------------------------------------------
+ static_generate_exception - generate a static
+ exception handler
+-------------------------------------------------*/
+
+static void static_generate_exception(powerpc_state *ppc, UINT8 exception, int recover, const char *name)
+{
+ drcuml_state *drcuml = ppc->impstate->drcuml;
+ code_handle *&exception_handle = recover ? ppc->impstate->exception[exception] : ppc->impstate->exception_norecover[exception];
+ UINT32 vector = exception << 8;
+ code_label label = 1;
+ drcuml_block *block;
+
+ /* 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_ISI || exception == EXCEPTION_DSI)
+ {
+ UML_GETEXP(block, I0); // getexp i0
+ UML_MOV(block, SPR32(SPROEA_DAR), I0); // mov [dar],i0
+ }
+
+ /* fetch the PC and uncounted cycles */
+ if (recover)
+ {
+ UML_RECOVER(block, I0, MAPVAR_PC); // recover i0,PC
+ UML_RECOVER(block, I1, MAPVAR_CYCLES); // recover i1,CYCLES
+ }
+
+ /* OEA handling of SRR exceptions */
+ if (ppc->cap & PPCCAP_OEA)
+ {
+ UINT32 msrandmask = MSROEA_POW | MSR_EE | MSR_PR | MSROEA_FP | MSROEA_FE0 | MSROEA_SE | MSROEA_BE | MSROEA_FE1 | MSROEA_IR | MSROEA_DR | MSROEA_RI | MSR_LE;
+ UINT32 msrormask = 0;
+
+ /* check registers to see the real source of our exception (EI exceptions only) */
+ UML_MOV(block, I3, vector); // mov i3,vector
+ if (exception == EXCEPTION_EI)
+ {
+ code_label not_decrementer;
+
+ UML_TEST(block, mem(&ppc->irq_pending), 0x01); // test [irq_pending],0x01
+ UML_JMPc(block, COND_NZ, not_decrementer = label++); // jmp not_decrementer,nz
+ UML_MOV(block, I3, EXCEPTION_DECREMENT << 8); // mov i3,EXCEPTION_DECREMENT << 8
+ UML_AND(block, mem(&ppc->irq_pending), mem(&ppc->irq_pending), ~0x02); // and [irq_pending],[irq_pending],~0x02
+ UML_LABEL(block, not_decrementer); // not_decrementer:
+ }
+
+ /* exception PC goes into SRR0 */
+ UML_MOV(block, SPR32(SPROEA_SRR0), I0); // mov [srr0],i0
+
+ /* MSR bits go into SRR1, along with some exception-specific data */
+ UML_AND(block, SPR32(SPROEA_SRR1), MSR32, 0x87c0ffff); // and [srr1],[msr],0x87c0ffff
+ if (exception == EXCEPTION_PROGRAM)
+ {
+ UML_GETEXP(block, I1); // getexp i1
+ UML_OR(block, SPR32(SPROEA_SRR1), SPR32(SPROEA_SRR1), I1); // or [srr1],[srr1],i1
+ }
+ if (ppc->cap & PPCCAP_603_MMU)
+ {
+ if (exception == EXCEPTION_ITLBMISS)
+ UML_OR(block, SPR32(SPROEA_SRR1), SPR32(SPROEA_SRR1), 0x00040000); // or [srr1],0x00040000
+ else if (exception == EXCEPTION_DTLBMISSL)
+ UML_OR(block, SPR32(SPROEA_SRR1), SPR32(SPROEA_SRR1), 0x00010000); // or [srr1],0x00010000
+ if (exception == EXCEPTION_ITLBMISS || exception == EXCEPTION_DTLBMISSL || exception == EXCEPTION_DTLBMISSS)
+ UML_ROLINS(block, SPR32(SPROEA_SRR1), CR32(0), 28, CRMASK(0)); // rolins [srr1],[cr0],28,crmask(0)
+ }
+
+ /* update MSR */
+ if (ppc->cap & PPCCAP_603_MMU)
+ {
+ if (exception == EXCEPTION_ITLBMISS || exception == EXCEPTION_DTLBMISSL || exception == EXCEPTION_DTLBMISSS)
+ msrormask |= MSR603_TGPR;
+ else
+ msrandmask |= MSR603_TGPR;
+ UML_MOV(block, I0, MSR32); // mov i0,[msr]
+ }
+ UML_AND(block, I2, MSR32, ~msrandmask); // and i2,[msr],~andmask
+ UML_OR(block, I2, I2, msrormask); // or i2,i2,ormask
+ UML_ROLINS(block, I2, I2, 16, MSR_LE); // rolins i2,u2,16,MSR_LE
+ UML_MOV(block, MSR32, I2); // mov [msr],i2
+ if (ppc->cap & PPCCAP_603_MMU)
+ {
+ UML_XOR(block, I0, I0, I2); // xor i0,i0,i2
+ UML_TEST(block, I0, MSR603_TGPR); // test i0,tgpr
+ UML_CALLHc(block, COND_NZ, *ppc->impstate->swap_tgpr); // callh swap_tgpr,nz
+ }
+ generate_update_mode(ppc, block); // <update mode>
+
+ /* determine our target PC */
+ if (ppc->flavor == PPC_MODEL_602)
+ UML_MOV(block, I0, SPR32(SPR602_IBR)); // mov i0,[ibr]
+ else
+ UML_MOV(block, I0, 0x00000000); // mov i0,0x00000000
+ UML_TEST(block, MSR32, MSROEA_IP); // test [msr],IP
+ UML_MOVc(block, COND_NZ, I0, 0xfff00000); // mov i0,0xfff00000,nz
+ UML_OR(block, I0, I0, I3); // or i0,i0,i3
+ }
+
+ /* 4XX handling of exceptions */
+ if (ppc->cap & PPCCAP_4XX)
+ {
+ /* check registers to see the real source of our exception (EI exceptions only) */
+ UML_MOV(block, I3, vector); // mov i3,vector
+ if (exception == EXCEPTION_EI)
+ {
+ code_label notwdog, common;
+
+ UML_TEST(block, SPR32(SPR4XX_TSR), PPC4XX_TSR_PIS); // test [tsr],PIS
+ UML_MOVc(block, COND_NZ, I3, 0x1000); // mov i3,0x1000,NZ
+ UML_TEST(block, SPR32(SPR4XX_TSR), PPC4XX_TSR_FIS); // test [tsr],FIS
+ UML_MOVc(block, COND_NZ, I3, 0x1010); // mov i3,0x1010,NZ
+ UML_TEST(block, SPR32(DCR4XX_EXISR), SPR32(DCR4XX_EXIER)); // test [exisr],[exier]
+ UML_MOVc(block, COND_NZ, I3, vector); // mov i3,vector,NZ
+ UML_TEST(block, SPR32(SPR4XX_TSR), PPC4XX_TSR_WIS); // test [tsr],WIS
+ UML_JMPc(block, COND_Z, notwdog = label++); // jz notwdog
+ UML_MOV(block, I3, 0x1020); // mov i3,0x1020
+
+ /* exception PC goes into SRR2, MSR goes to SRR3 */
+ UML_MOV(block, SPR32(SPR4XX_SRR2), I0); // mov [srr2],i0
+ UML_MOV(block, SPR32(SPR4XX_SRR3), MSR32); // mov [srr3],[msr]
+ UML_AND(block, I2, MSR32, ~(MSR4XX_WE | MSR_PR | MSR4XX_CE | MSR_EE | MSR4XX_DE | MSR4XX_PE));
+ UML_JMP(block, common = label++); // jmp common
+
+ /* exception PC goes into SRR0, MSR goes to SRR1 */
+ UML_LABEL(block, notwdog); // notwdog:
+ UML_MOV(block, SPR32(SPR4XX_SRR0), I0); // mov [srr0],i0
+ UML_MOV(block, SPR32(SPR4XX_SRR1), MSR32); // mov [srr1],[msr]
+ UML_AND(block, I2, MSR32, ~(MSR4XX_WE | MSR_PR | MSR_EE | MSR4XX_PE));// and i2,[msr],~(bunch-o-flags)
+ UML_LABEL(block, common); // common:
+ }
+ else
+ {
+ /* exception PC goes into SRR0, MSR goes to SRR1 */
+ UML_MOV(block, SPR32(SPR4XX_SRR0), I0); // mov [srr0],i0
+ UML_MOV(block, SPR32(SPR4XX_SRR1), MSR32); // mov [srr1],[msr]
+ UML_AND(block, I2, MSR32, ~(MSR4XX_WE | MSR_PR | MSR_EE | MSR4XX_PE));// and i2,[msr],~(bunch-o-flags)
+ }
+
+ /* finish updating MSR */
+ UML_ROLINS(block, I2, I2, 16, MSR_LE); // rolins i2,u2,16,MSR_LE
+ UML_MOV(block, MSR32, I2); // mov [msr],i2
+ generate_update_mode(ppc, block); // <update mode>
+
+ /* program exception flags go to ESR */
+ if (exception == EXCEPTION_PROGRAM)
+ {
+ UML_GETEXP(block, I1); // getexp i1
+ UML_SHL(block, SPR32(SPR4XX_ESR), I1, 8); // shl [esr],i1,8
+ }
+
+ /* determine our target PC */
+ UML_ROLINS(block, I3, SPR32(SPR4XX_EVPR), 0, 0xffff0000); // rolins i3,[evpr],0,0xffff0000
+ UML_MOV(block, I0, I3); // mov i0,i3
+ }
+
+ /* optionally print exceptions */
+ if ((PRINTF_EXCEPTIONS && exception != EXCEPTION_EI && exception != EXCEPTION_SYSCALL) ||
+ (PRINTF_MMU && (exception == EXCEPTION_ISI || exception == EXCEPTION_DSI)))
+ {
+ UML_MOV(block, mem(&ppc->param0), exception); // mov [param0],exception
+ UML_CALLC(block, cfunc_printf_exception, ppc); // callc cfunc_printf_exception,ppc
+ }
+
+ /* adjust cycles */
+ UML_SUB(block, mem(&ppc->icount), mem(&ppc->icount), I1); // sub icount,icount,cycles
+ UML_EXHc(block, COND_S, *ppc->impstate->out_of_cycles, I0); // exh out_of_cycles,i0
+ UML_HASHJMP(block, mem(&ppc->impstate->mode), I0, *ppc->impstate->nocode); // hashjmp <mode>,i0,nocode
+
+ block->end();
+}
+
+
+/*------------------------------------------------------------------
+ static_generate_memory_accessor
+------------------------------------------------------------------*/
+
+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)
+{
+ /* on entry, address is in I0; data for writes is in I1; masks are in I2 */
+ /* on exit, read result is in I0 */
+ /* routine trashes I0-I3 */
+ drcuml_state *drcuml = ppc->impstate->drcuml;
+ int fastxor = BYTE8_XOR_BE(0) >> (int)(ppc->device->space_config(AS_PROGRAM)->m_databus_width < 64);
+ drcuml_block *block;
+ int translate_type;
+ int tlbreturn = 0;
+ int unaligned = 0;
+ int alignex = 0;
+ int tlbmiss = 0;
+ int label = 1;
+ int ramnum;
+
+ if (mode & MODE_USER)
+ translate_type = iswrite ? TRANSLATE_WRITE_USER : TRANSLATE_READ_USER;
+ else
+ translate_type = iswrite ? TRANSLATE_WRITE : TRANSLATE_READ;
+
+ /* begin generating */
+ block = drcuml->begin_block(1024);
+
+ /* add a global entry for this */
+ alloc_handle(drcuml, &handleptr, name);
+ UML_HANDLE(block, *handleptr); // handle *handleptr
+
+ /* check for unaligned accesses and break into two */
+ if (!ismasked && size != 1)
+ {
+ /* in little-endian mode, anything misaligned generates an exception */
+ if ((mode & MODE_LITTLE_ENDIAN) || masked == NULL || !(ppc->cap & PPCCAP_MISALIGNED))
+ {
+ UML_TEST(block, I0, size - 1); // test i0,size-1
+ UML_JMPc(block, COND_NZ, alignex = label++); // jmp alignex,nz
+ }
+
+ /* in big-endian mode, it's more complicated */
+ else
+ {
+ /* 8-byte accesses must be word-aligned */
+ if (size == 8)
+ {
+ UML_TEST(block, I0, 3); // test i0,3
+ UML_JMPc(block, COND_NZ, alignex = label++); // jmp alignex,nz
+ }
+
+ /* unaligned 2 and 4 byte accesses need to be broken up */
+ else
+ {
+ UML_TEST(block, I0, size - 1); // test i0,size-1
+ UML_JMPc(block, COND_NZ, unaligned = label++); // jmp unaligned,nz
+ }
+ }
+ }
+
+ /* general case: assume paging and perform a translation */
+ if (((ppc->cap & PPCCAP_OEA) && (mode & MODE_DATA_TRANSLATION)) || (iswrite && (ppc->cap & PPCCAP_4XX) && (mode & MODE_PROTECTION)))
+ {
+ UML_SHR(block, I3, I0, 12); // shr i3,i0,12
+ UML_LOAD(block, I3, (void *)vtlb_table(ppc->vtlb), I3, SIZE_DWORD, SCALE_x4);// load i3,[vtlb],i3,dword
+ UML_TEST(block, I3, (UINT64)1 << translate_type); // test i3,1 << translate_type
+ UML_JMPc(block, COND_Z, tlbmiss = label++); // jmp tlbmiss,z
+ UML_LABEL(block, tlbreturn = label++); // tlbreturn:
+ UML_ROLINS(block, I0, I3, 0, 0xfffff000); // rolins i0,i3,0,0xfffff000
+ }
+ else if (ppc->cap & PPCCAP_4XX)
+ UML_AND(block, I0, I0, 0x7fffffff); // and i0,i0,0x7fffffff
+ UML_XOR(block, I0, I0, (mode & MODE_LITTLE_ENDIAN) ? (8 - size) : 0); // xor i0,i0,8-size
+
+ if ((ppc->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ for (ramnum = 0; ramnum < PPC_MAX_FASTRAM; ramnum++)
+ if (ppc->impstate->fastram[ramnum].base != NULL && (!iswrite || !ppc->impstate->fastram[ramnum].readonly))
+ {
+ void *fastbase = (UINT8 *)ppc->impstate->fastram[ramnum].base - ppc->impstate->fastram[ramnum].start;
+ UINT32 skip = label++;
+
+ if (ppc->impstate->fastram[ramnum].end != 0xffffffff)
+ {
+ UML_CMP(block, I0, ppc->impstate->fastram[ramnum].end); // cmp i0,end
+ UML_JMPc(block, COND_A, skip); // ja skip
+ }
+ if (ppc->impstate->fastram[ramnum].start != 0x00000000)
+ {
+ UML_CMP(block, I0, ppc->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, fastxor & 7); // xor i0,i0,fastxor & 7
+ UML_LOAD(block, I0, fastbase, I0, SIZE_BYTE, SCALE_x1); // load i0,fastbase,i0,byte
+ }
+ else if (size == 2)
+ {
+ UML_XOR(block, I0, I0, fastxor & 6); // xor i0,i0,fastxor & 6
+ UML_LOAD(block, I0, fastbase, I0, SIZE_WORD, SCALE_x1); // load i0,fastbase,i0,word_x1
+ }
+ else if (size == 4)
+ {
+ UML_XOR(block, I0, I0, fastxor & 4); // xor i0,i0,fastxor & 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
+ }
+ UML_RET(block); // ret
+ }
+ else
+ {
+ if (size == 1)
+ {
+ UML_XOR(block, I0, I0, fastxor & 7); // xor i0,i0,fastxor & 7
+ UML_STORE(block, fastbase, I0, I1, SIZE_BYTE, SCALE_x1); // store fastbase,i0,i1,byte
+ }
+ else if (size == 2)
+ {
+ UML_XOR(block, I0, I0, fastxor & 6); // xor i0,i0,fastxor & 6
+ UML_STORE(block, fastbase, I0, I1, SIZE_WORD, SCALE_x1); // store fastbase,i0,i1,word_x1
+ }
+ else if (size == 4)
+ {
+ UML_XOR(block, I0, I0, fastxor & 4); // xor i0,i0,fastxor & 4
+ if (ismasked)
+ {
+ UML_LOAD(block, I3, fastbase, I0, SIZE_DWORD, SCALE_x1); // load i3,fastbase,i0,dword_x1
+ UML_AND(block, I1, I1, I2); // and i1,i1,i2
+ UML_XOR(block, I2, I2, 0xffffffff); // xor i2,i2,0xfffffffff
+ UML_AND(block, I3, I3, I2); // and i3,i3,i2
+ UML_OR(block, I1, I1, I3); // or i1,i1,i3
+ }
+ UML_STORE(block, fastbase, I0, I1, SIZE_DWORD, SCALE_x1); // store fastbase,i0,i1,dword_x1
+ }
+ else if (size == 8)
+ {
+ if (ismasked)
+ {
+ UML_DLOAD(block, I3, fastbase, I0, SIZE_QWORD, SCALE_x1); // dload i3,fastbase,i0,qword_x1
+ UML_DAND(block, I1, I1, I2); // dand i1,i1,i2
+ UML_DXOR(block, I2, I2, U64(0xffffffffffffffff)); // dxor i2,i2,0xfffffffffffffffff
+ UML_DAND(block, I3, I3, I2); // dand i3,i3,i2
+ UML_DOR(block, I1, I1, I3); // dor i1,i1,i3
+ }
+ 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)
+ {
+ if (!ismasked)
+ UML_WRITE(block, I0, I1, SIZE_WORD, SPACE_PROGRAM); // write i0,i1,program_word
+ else
+ UML_WRITEM(block, I0, I1, I2, SIZE_WORD, SPACE_PROGRAM); // writem i0,i2,i1,program_word
+ }
+ else
+ {
+ if (!ismasked)
+ UML_READ(block, I0, I0, SIZE_WORD, SPACE_PROGRAM); // read i0,i0,program_word
+ else
+ UML_READM(block, I0, I0, I2, SIZE_WORD, SPACE_PROGRAM); // readm i0,i0,i2,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,i2,i1,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,i2,i1,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
+
+ /* handle unaligned accesses */
+ if (unaligned != 0)
+ {
+ UML_LABEL(block, unaligned); // unaligned:
+ if (size == 2)
+ {
+ if (iswrite)
+ {
+ UML_MOV(block, mem(&ppc->impstate->tempaddr), I0); // mov [tempaddr],i0
+ UML_MOV(block, mem(&ppc->impstate->tempdata.w.l), I1); // mov [tempdata],i1
+ UML_SUB(block, I0, I0, 1); // sub i0,i0,1
+ UML_SHR(block, I1, I1, 8); // shr i1,i1,8
+ UML_MOV(block, I2, 0x00ff); // mov i2,0x00ff
+ UML_CALLH(block, *masked); // callh masked
+ UML_ADD(block, I0, mem(&ppc->impstate->tempaddr), 1); // add i0,[tempaddr],1
+ UML_SHL(block, I1, mem(&ppc->impstate->tempdata.w.l), 8); // shl i1,[tempdata],8
+ UML_MOV(block, I2, 0xff00); // mov i2,0xff00
+ UML_CALLH(block, *masked); // callh masked
+ }
+ else
+ {
+ UML_MOV(block, mem(&ppc->impstate->tempaddr), I0); // mov [tempaddr],i0
+ UML_SUB(block, I0, I0, 1); // sub i0,i0,1
+ UML_MOV(block, I2, 0x00ff); // mov i2,0x00ff
+ UML_CALLH(block, *masked); // callh masked
+ UML_SHL(block, mem(&ppc->impstate->tempdata.w.l), I0, 8); // shl [tempdata],i0,8
+ UML_ADD(block, I0, mem(&ppc->impstate->tempaddr), 1); // add i0,[tempaddr],1
+ UML_MOV(block, I2, 0xff00); // mov i2,0xff00
+ UML_CALLH(block, *masked); // callh masked
+ UML_SHR(block, I0, I0, 8); // shr i0,i0,8
+ UML_OR(block, I0, I0, mem(&ppc->impstate->tempdata.w.l)); // or i0,i0,[tempdata]
+ }
+ }
+ else if (size == 4)
+ {
+ int offs2, offs3;
+ if (iswrite)
+ {
+ UML_MOV(block, mem(&ppc->impstate->tempaddr), I0); // mov [tempaddr],i0
+ UML_MOV(block, mem(&ppc->impstate->tempdata.w.l), I1); // mov [tempdata],i1
+ UML_TEST(block, I0, 2); // test i0,i0,2
+ UML_JMPc(block, COND_NZ, offs2 = label++); // jnz offs2
+ UML_SUB(block, I0, I0, 1); // sub i0,i0,1
+ UML_SHR(block, I1, I1, 8); // shr i1,i1,8
+ UML_MOV(block, I2, 0x00ffffff); // mov i2,0x00ffffff
+ UML_CALLH(block, *masked); // callh masked
+ UML_ADD(block, I0, mem(&ppc->impstate->tempaddr), 3); // add i0,[tempaddr],3
+ UML_SHL(block, I1, mem(&ppc->impstate->tempdata.w.l), 24); // shl i1,[tempdata],24
+ UML_MOV(block, I2, 0xff000000); // mov i2,0xff000000
+ UML_CALLH(block, *masked); // callh masked
+ UML_RET(block); // ret
+ UML_LABEL(block, offs2); // offs2:
+ UML_TEST(block, I0, 1); // test i0,i0,1
+ UML_JMPc(block, COND_NZ, offs3 = label++); // jnz offs3
+ UML_SUB(block, I0, I0, 2); // sub i0,i0,2
+ UML_SHR(block, I1, I1, 16); // shr i1,i1,16
+ UML_MOV(block, I2, 0x0000ffff); // mov i2,0x0000ffff
+ UML_CALLH(block, *masked); // callh masked
+ UML_ADD(block, I0, mem(&ppc->impstate->tempaddr), 2); // add i0,[tempaddr],2
+ UML_SHL(block, I1, mem(&ppc->impstate->tempdata.w.l), 16); // shl i1,[tempdata],16
+ UML_MOV(block, I2, 0xffff0000); // mov i2,0xffff0000
+ UML_CALLH(block, *masked); // callh masked
+ UML_RET(block); // ret
+ UML_LABEL(block, offs3); // offs3:
+ UML_SUB(block, I0, I0, 3); // sub i0,i0,3
+ UML_SHR(block, I1, I1, 24); // shr i1,i1,24
+ UML_MOV(block, I2, 0x000000ff); // mov i2,0x000000ff
+ UML_CALLH(block, *masked); // callh masked
+ UML_ADD(block, I0, mem(&ppc->impstate->tempaddr), 1); // add i0,[tempaddr],1
+ UML_SHL(block, I1, mem(&ppc->impstate->tempdata.w.l), 8); // shl i1,[tempdata],8
+ UML_MOV(block, I2, 0xffffff00); // mov i2,0xffffff00
+ UML_CALLH(block, *masked); // callh masked
+ }
+ else
+ {
+ UML_MOV(block, mem(&ppc->impstate->tempaddr), I0); // mov [tempaddr],i0
+ UML_TEST(block, I0, 2); // test i0,i0,2
+ UML_JMPc(block, COND_NZ, offs2 = label++); // jnz offs2
+ UML_SUB(block, I0, I0, 1); // sub i0,i0,1
+ UML_MOV(block, I2, 0x00ffffff); // mov i2,0x00ffffff
+ UML_CALLH(block, *masked); // callh masked
+ UML_SHL(block, mem(&ppc->impstate->tempdata.w.l), I0, 8); // shl [tempdata],i0,8
+ UML_ADD(block, I0, mem(&ppc->impstate->tempaddr), 3); // add i0,[tempaddr],3
+ UML_MOV(block, I2, 0xff000000); // mov i2,0xff000000
+ UML_CALLH(block, *masked); // callh masked
+ UML_SHR(block, I0, I0, 24); // shr i0,i0,24
+ UML_OR(block, I0, I0, mem(&ppc->impstate->tempdata.w.l)); // or i0,i0,[tempdata]
+ UML_RET(block); // ret
+ UML_LABEL(block, offs2); // offs2:
+ UML_TEST(block, I0, 1); // test i0,i0,1
+ UML_JMPc(block, COND_NZ, offs3 = label++); // jnz offs3
+ UML_SUB(block, I0, I0, 2); // sub i0,i0,2
+ UML_MOV(block, I2, 0x0000ffff); // mov i2,0x0000ffff
+ UML_CALLH(block, *masked); // callh masked
+ UML_SHL(block, mem(&ppc->impstate->tempdata.w.l), I0, 16); // shl [tempdata],i0,16
+ UML_ADD(block, I0, mem(&ppc->impstate->tempaddr), 2); // add i0,[tempaddr],2
+ UML_MOV(block, I2, 0xffff0000); // mov i2,0xffff0000
+ UML_CALLH(block, *masked); // callh masked
+ UML_SHR(block, I0, I0, 16); // shr i0,i0,16
+ UML_OR(block, I0, I0, mem(&ppc->impstate->tempdata.w.l)); // or i0,i0,[tempdata]
+ UML_RET(block); // ret
+ UML_LABEL(block, offs3); // offs3:
+ UML_SUB(block, I0, I0, 3); // sub i0,i0,3
+ UML_MOV(block, I2, 0x000000ff); // mov i2,0x000000ff
+ UML_CALLH(block, *masked); // callh masked
+ UML_SHL(block, mem(&ppc->impstate->tempdata.w.l), I0, 24); // shl [tempdata],i0,24
+ UML_ADD(block, I0, mem(&ppc->impstate->tempaddr), 1); // add i0,[tempaddr],1
+ UML_MOV(block, I2, 0xffffff00); // mov i2,0xffffff00
+ UML_CALLH(block, *masked); // callh masked
+ UML_SHR(block, I0, I0, 8); // shr i0,i0,8
+ UML_OR(block, I0, I0, mem(&ppc->impstate->tempdata.w.l)); // or i0,i0,[tempdata]
+ }
+ }
+ UML_RET(block); // ret
+ }
+
+ /* handle an alignment exception */
+ if (alignex != 0)
+ {
+ UML_LABEL(block, alignex); // alignex:
+ UML_RECOVER(block, SPR32(SPROEA_DSISR), MAPVAR_DSISR); // recover [dsisr],DSISR
+ UML_EXH(block, *ppc->impstate->exception[EXCEPTION_ALIGN], I0); // exh align,i0
+ }
+
+ /* handle a TLB miss */
+ if (tlbmiss != 0)
+ {
+ UML_LABEL(block, tlbmiss); // tlbmiss:
+ UML_MOV(block, mem(&ppc->param0), I0); // mov [param0],i0
+ UML_MOV(block, mem(&ppc->param1), translate_type); // mov [param1],translate_type
+ UML_CALLC(block, (c_function)ppccom_tlb_fill, ppc); // callc tlbfill,ppc
+ UML_SHR(block, I3, I0, 12); // shr i3,i0,12
+ UML_LOAD(block, I3, (void *)vtlb_table(ppc->vtlb), I3, SIZE_DWORD, SCALE_x4);// load i3,[vtlb],i3,dword
+ UML_TEST(block, I3, (UINT64)1 << translate_type); // test i3,1 << translate_type
+ UML_JMPc(block, COND_NZ, tlbreturn); // jmp tlbreturn,nz
+
+ /* 4XX case: protection exception */
+ if (ppc->cap & PPCCAP_4XX)
+ {
+ UML_MOV(block, SPR32(SPR4XX_DEAR), I0); // mov [dear],i0
+ UML_EXH(block, *ppc->impstate->exception[EXCEPTION_DSI], I0); // exh dsi,i0
+ }
+
+ /* 603 case: TLBMISS exception */
+ else if (ppc->cap & PPCCAP_603_MMU)
+ {
+ UML_MOV(block, SPR32(SPR603_DMISS), I0); // mov [dmiss],i0
+ UML_MOV(block, SPR32(SPR603_DCMP), mem(&ppc->mmu603_cmp)); // mov [dcmp],[mmu603_cmp]
+ UML_MOV(block, SPR32(SPR603_HASH1), mem(&ppc->mmu603_hash[0])); // mov [hash1],[mmu603_hash][0]
+ UML_MOV(block, SPR32(SPR603_HASH2), mem(&ppc->mmu603_hash[1])); // mov [hash2],[mmu603_hash][1]
+ if (iswrite)
+ UML_EXH(block, *ppc->impstate->exception[EXCEPTION_DTLBMISSS], I0); // exh dtlbmisss,i0
+ else
+ UML_EXH(block, *ppc->impstate->exception[EXCEPTION_DTLBMISSL], I0); // exh dtlbmissl,i0
+ }
+
+ /* general case: DSI exception */
+ else
+ {
+ UML_MOV(block, SPR32(SPROEA_DSISR), mem(&ppc->param0)); // mov [dsisr],[param0]
+ UML_EXH(block, *ppc->impstate->exception[EXCEPTION_DSI], I0); // exh dsi,i0
+ }
+ }
+
+ block->end();
+}
+
+
+/*-------------------------------------------------
+ static_generate_swap_tgpr - generate a
+ subroutine to swap GPR0-3 with TGPR0-3
+-------------------------------------------------*/
+
+static void static_generate_swap_tgpr(powerpc_state *ppc)
+{
+ drcuml_state *drcuml = ppc->impstate->drcuml;
+ drcuml_block *block;
+ int regnum;
+
+ /* begin generating */
+ block = drcuml->begin_block(30);
+
+ /* generate a hash jump via the current mode and PC */
+ alloc_handle(drcuml, &ppc->impstate->swap_tgpr, "swap_tgpr");
+ UML_HANDLE(block, *ppc->impstate->swap_tgpr); // handle swap_tgpr
+ for (regnum = 0; regnum < 4; regnum++)
+ {
+ UML_MOV(block, I1, R32(regnum)); // mov i1,r[regnum]
+ UML_MOV(block, R32(regnum), mem(&ppc->mmu603_r[regnum])); // mov r[regnum],mmu603_r[regnum]
+ UML_MOV(block, mem(&ppc->mmu603_r[regnum]), I1); // mov mmu603_r[regnum],i1
+ }
+ UML_RET(block); // ret
+
+ block->end();
+}
+
+
+/*-------------------------------------------------
+ static_generate_lsw_entries - generate a
+ subroutine to perform LSWI/LSWX; one handle
+ for each possible register
+-------------------------------------------------*/
+
+static void static_generate_lsw_entries(powerpc_state *ppc, int mode)
+{
+ drcuml_state *drcuml = ppc->impstate->drcuml;
+ drcuml_block *block;
+ int regnum;
+
+ /* begin generating */
+ block = drcuml->begin_block(32 * 30);
+
+ /* iterate over all possible registers */
+ for (regnum = 0; regnum < 32; regnum++)
+ {
+ char temp[20];
+
+ /* allocate a handle */
+ sprintf(temp, "lsw%d", regnum);
+ alloc_handle(drcuml, &ppc->impstate->lsw[mode][regnum], temp);
+ UML_HANDLE(block, *ppc->impstate->lsw[mode][regnum]); // handle lsw<regnum>
+ UML_LABEL(block, regnum); // regnum:
+ UML_ADD(block, I0, mem(&ppc->impstate->updateaddr), 0); // add i0,[updateaddr],0
+ UML_CALLH(block, *ppc->impstate->read8[mode]); // callh read8
+ UML_ROLAND(block, R32(regnum), I0, 24, 0xff000000); // roland reg,i0,24,0xff000000
+ UML_SUB(block, mem(&ppc->impstate->swcount), mem(&ppc->impstate->swcount), 1); // sub [swcount],[swcount],1
+ UML_RETc(block, COND_Z); // ret z
+ UML_ADD(block, I0, mem(&ppc->impstate->updateaddr), 1); // add i0,[updateaddr],1
+ UML_CALLH(block, *ppc->impstate->read8[mode]); // callh read8
+ UML_ROLAND(block, I0, I0, 16, 0x00ff0000); // roland i0,i0,16,0x00ff0000
+ UML_OR(block, R32(regnum), R32(regnum), I0); // or reg,i0
+ UML_SUB(block, mem(&ppc->impstate->swcount), mem(&ppc->impstate->swcount), 1); // sub [swcount],[swcount],1
+ UML_RETc(block, COND_Z); // ret z
+ UML_ADD(block, I0, mem(&ppc->impstate->updateaddr), 2); // add i0,[updateaddr],2
+ UML_CALLH(block, *ppc->impstate->read8[mode]); // callh read8
+ UML_ROLAND(block, I0, I0, 8, 0x0000ff00); // roland i0,i0,8,0x0000ff00
+ UML_OR(block, R32(regnum), R32(regnum), I0); // or reg,i0
+ UML_SUB(block, mem(&ppc->impstate->swcount), mem(&ppc->impstate->swcount), 1); // sub [swcount],[swcount],1
+ UML_RETc(block, COND_Z); // ret z
+ UML_ADD(block, I0, mem(&ppc->impstate->updateaddr), 3); // add i0,[updateaddr],3
+ UML_ADD(block, mem(&ppc->impstate->updateaddr), I0, 1); // add [updateaddr],i0,1
+ UML_CALLH(block, *ppc->impstate->read8[mode]); // callh read8
+ UML_ROLAND(block, I0, I0, 0, 0x000000ff); // roland i0,i0,0,0x000000ff
+ UML_OR(block, R32(regnum), R32(regnum), I0); // or reg,i0
+ UML_SUB(block, mem(&ppc->impstate->swcount), mem(&ppc->impstate->swcount), 1); // sub [swcount],[swcount],1
+ UML_RETc(block, COND_Z); // ret z
+ UML_JMP(block, (regnum + 1) % 32); // jmp nextreg
+ }
+
+ block->end();
+}
+
+
+/*-------------------------------------------------
+ static_generate_stsw_entries - generate a
+ subroutine to perform LSWI/LSWX; one handle
+ for each possible register
+-------------------------------------------------*/
+
+static void static_generate_stsw_entries(powerpc_state *ppc, int mode)
+{
+ drcuml_state *drcuml = ppc->impstate->drcuml;
+ drcuml_block *block;
+ int regnum;
+
+ /* begin generating */
+ block = drcuml->begin_block(32 * 30);
+
+ /* iterate over all possible registers */
+ for (regnum = 0; regnum < 32; regnum++)
+ {
+ char temp[20];
+
+ /* allocate a handle */
+ sprintf(temp, "stsw%d", regnum);
+ alloc_handle(drcuml, &ppc->impstate->stsw[mode][regnum], temp);
+ UML_HANDLE(block, *ppc->impstate->stsw[mode][regnum]); // handle stsw<regnum>
+ UML_LABEL(block, regnum); // regnum:
+ UML_ADD(block, I0, mem(&ppc->impstate->updateaddr), 0); // add i0,[updateaddr],0
+ UML_ROLAND(block, I1, R32(regnum), 8, 0xff); // roland i1,regnum,8,0xff
+ UML_CALLH(block, *ppc->impstate->write8[mode]); // callh write8
+ UML_SUB(block, mem(&ppc->impstate->swcount), mem(&ppc->impstate->swcount), 1); // sub [swcount],[swcount],1
+ UML_RETc(block, COND_Z); // ret z
+ UML_ADD(block, I0, mem(&ppc->impstate->updateaddr), 1); // add i0,[updateaddr],1
+ UML_ROLAND(block, I1, R32(regnum), 16, 0xff); // roland i1,regnum,16,0xff
+ UML_CALLH(block, *ppc->impstate->write8[mode]); // callh write8
+ UML_SUB(block, mem(&ppc->impstate->swcount), mem(&ppc->impstate->swcount), 1); // sub [swcount],[swcount],1
+ UML_RETc(block, COND_Z); // ret z
+ UML_ADD(block, I0, mem(&ppc->impstate->updateaddr), 2); // add i0,[updateaddr],2
+ UML_ROLAND(block, I1, R32(regnum), 24, 0xff); // roland i1,regnum,24,0xff
+ UML_CALLH(block, *ppc->impstate->write8[mode]); // callh write8
+ UML_SUB(block, mem(&ppc->impstate->swcount), mem(&ppc->impstate->swcount), 1); // sub [swcount],[swcount],1
+ UML_RETc(block, COND_Z); // ret z
+ UML_ADD(block, I0, mem(&ppc->impstate->updateaddr), 3); // add i0,[updateaddr],3
+ UML_ADD(block, mem(&ppc->impstate->updateaddr), I0, 1); // add [updateaddr],i0,1
+ UML_ROLAND(block, I1, R32(regnum), 0, 0xff); // roland i1,regnum,0,0xff
+ UML_CALLH(block, *ppc->impstate->write8[mode]); // callh write8
+ UML_SUB(block, mem(&ppc->impstate->swcount), mem(&ppc->impstate->swcount), 1); // sub [swcount],[swcount],1
+ UML_RETc(block, COND_Z); // ret z
+ UML_JMP(block, (regnum + 1) % 32); // jmp nextreg
+ }
+
+ block->end();
+}
+
+
+
+/***************************************************************************
+ CODE GENERATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ generate_update_mode - update the mode based
+ on the MSR
+-------------------------------------------------*/
+
+static void generate_update_mode(powerpc_state *ppc, drcuml_block *block)
+{
+ /* LE in bit 0 of mode */
+ UML_AND(block, I0, MSR32, MSR_LE); // and i0,msr,MSR_LE
+
+ /* DR (OEA and 403GCX) in bit 1 of mode */
+ if ((ppc->cap & PPCCAP_OEA) || ppc->flavor == PPC_MODEL_403GCX)
+ {
+ UML_ROLAND(block, I1, MSR32, 29, 0x02); // roland i1,[msr],29,0x02
+ UML_OR(block, I0, I0, I1); // or i0,i0,i1
+ }
+
+ /* (4XX) in bit 1 of mode */
+ if (ppc->cap & PPCCAP_4XX)
+ {
+ UML_ROLAND(block, I1, MSR32, 30, 0x02); // roland i1,[msr],30,0x02
+ UML_OR(block, I0, I0, I1); // or i0,i0,i1
+ }
+
+ /* PR in bit 2 of mode */
+ UML_ROLAND(block, I1, MSR32, 20, 0x04); // roland i1,[msr],20,0x04
+ UML_OR(block, mem(&ppc->impstate->mode), I0, I1); // or [mode],i0,i1
+}
+
+
+/*-------------------------------------------------
+ generate_update_cycles - generate code to
+ subtract cycles from the icount and generate
+ an exception if out
+-------------------------------------------------*/
+
+static void generate_update_cycles(powerpc_state *ppc, drcuml_block *block, compiler_state *compiler, parameter param, int allow_exception)
+{
+ /* check full interrupts if pending */
+ if (compiler->checkints)
+ {
+ code_label skip;
+
+ compiler->checkints = FALSE;
+ UML_TEST(block, mem(&ppc->irq_pending), ~0); // test [irq_pending],0
+ UML_JMPc(block, COND_Z, skip = compiler->labelnum++); // 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, param); // mov i0,nextpc
+ UML_MOV(block, I1, compiler->cycles); // mov i1,cycles
+ UML_CALLH(block, *ppc->impstate->exception_norecover[EXCEPTION_EI]); // callh interrupt_norecover
+ UML_LABEL(block, skip); // skip:
+ }
+
+ /* account for cycles */
+ if (compiler->cycles > 0)
+ {
+ UML_SUB(block, mem(&ppc->icount), mem(&ppc->icount), MAPVAR_CYCLES); // sub icount,icount,cycles
+ UML_MAPVAR(block, MAPVAR_CYCLES, 0); // mapvar cycles,0
+ if (allow_exception)
+ UML_EXHc(block, COND_S, *ppc->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(powerpc_state *ppc, 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 (!(ppc->impstate->drcoptions & PPCDRC_STRICT_VERIFY) || seqhead->next() == NULL)
+ {
+ if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP))
+ {
+ void *base = ppc->direct->read_decrypted_ptr(seqhead->physpc, ppc->codexor);
+ UML_LOAD(block, I0, base, 0, SIZE_DWORD, SCALE_x4); // load i0,base,dword
+ UML_CMP(block, I0, seqhead->opptr.l[0]); // cmp i0,*opptr
+ UML_EXHc(block, COND_NE, *ppc->impstate->nocode, seqhead->pc); // 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 = ppc->direct->read_decrypted_ptr(seqhead->physpc, ppc->codexor);
+ UML_LOAD(block, I0, base, 0, SIZE_DWORD, SCALE_x4); // load i0,base,dword
+ UML_CMP(block, I0, curdesc->opptr.l[0]); // cmp i0,*opptr
+ UML_EXHc(block, COND_NE, *ppc->impstate->nocode, seqhead->pc); // exne nocode,seqhead->pc
+ }
+#else
+ UINT32 sum = 0;
+ void *base = ppc->direct->read_decrypted_ptr(seqhead->physpc, ppc->codexor);
+ UML_LOAD(block, I0, base, 0, SIZE_DWORD, SCALE_x4); // load i0,base,dword
+ sum += seqhead->opptr.l[0];
+ for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next())
+ if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
+ {
+ base = ppc->direct->read_decrypted_ptr(curdesc->physpc, ppc->codexor);
+ 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];
+ }
+ UML_CMP(block, I0, sum); // cmp i0,sum
+ UML_EXHc(block, COND_NE, *ppc->impstate->nocode, seqhead->pc); // exne nocode,seqhead->pc
+#endif
+ }
+}
+
+
+/*-------------------------------------------------
+ generate_sequence_instruction - generate code
+ for a single instruction in a sequence
+-------------------------------------------------*/
+
+static void generate_sequence_instruction(powerpc_state *ppc, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ int hotnum;
+
+ /* add an entry for the log */
+ if (LOG_UML && !(desc->flags & OPFLAG_VIRTUAL_NOOP))
+ log_add_disasm_comment(block, desc->pc, desc->opptr.l[0]);
+
+ /* set the PC map variable */
+ UML_MAPVAR(block, MAPVAR_PC, desc->pc); // mapvar PC,desc->pc
+
+ /* accumulate total cycles */
+ compiler->cycles += desc->cycles;
+
+ /* is this a hotspot? */
+ for (hotnum = 0; hotnum < PPC_MAX_HOTSPOTS; hotnum++)
+ if (ppc->impstate->hotspot[hotnum].pc != 0 && desc->pc == ppc->impstate->hotspot[hotnum].pc && desc->opptr.l[0] == ppc->impstate->hotspot[hotnum].opcode)
+ {
+ compiler->cycles += ppc->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(&ppc->pc), desc->pc); // mov [pc],desc->pc
+ UML_CALLC(block, cfunc_printf_probe, (void *)(FPTR)desc->pc); // callc cfunc_printf_probe,desc->pc
+ }
+
+ /* if we are debugging, call the debugger */
+ if ((ppc->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ {
+ UML_MOV(block, mem(&ppc->pc), desc->pc); // mov [pc],desc->pc
+ save_fast_iregs(ppc, block); // <save fastregs>
+ 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(&ppc->pc), desc->pc); // mov [pc],desc->pc
+ save_fast_iregs(ppc, block); // <save fastregs>
+ 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)
+ {
+ const char *text = "Compiler page fault @ %08X\n";
+ UML_MOV(block, mem(&ppc->impstate->format), (FPTR)text); // mov [format],text
+ UML_MOV(block, mem(&ppc->impstate->arg0), desc->pc); // mov [arg0],desc->pc
+ UML_CALLC(block, cfunc_printf_debug, ppc); // callc printf_debug
+ }
+ UML_EXH(block, *ppc->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) && (ppc->impstate->mode & MODE_DATA_TRANSLATION))
+ {
+ const vtlb_entry *tlbtable = vtlb_table(ppc->vtlb);
+
+ /* if we currently have a valid TLB read entry, we just verify */
+ if (tlbtable[desc->pc >> 12] != 0)
+ {
+ if (PRINTF_MMU)
+ {
+ const char *text = "Checking TLB at @ %08X\n";
+ UML_MOV(block, mem(&ppc->impstate->format), (FPTR)text); // mov [format],text
+ UML_MOV(block, mem(&ppc->impstate->arg0), desc->pc); // mov [arg0],desc->pc
+ UML_CALLC(block, cfunc_printf_debug, ppc); // callc printf_debug
+ }
+ UML_LOAD(block, I0, &tlbtable[desc->pc >> 12], 0, SIZE_DWORD, SCALE_x4);// load i0,tlbtable[desc->pc >> 12],dword
+ UML_CMP(block, I0, tlbtable[desc->pc >> 12]); // cmp i0,*tlbentry
+ UML_EXHc(block, COND_NE, *ppc->impstate->tlb_mismatch, 0); // exh tlb_mismatch,0,NE
+ }
+
+ /* otherwise, we generate an unconditional exception */
+ else
+ {
+ if (PRINTF_MMU)
+ {
+ const char *text = "No valid TLB @ %08X\n";
+ UML_MOV(block, mem(&ppc->impstate->format), (FPTR)text); // mov [format],text
+ UML_MOV(block, mem(&ppc->impstate->arg0), desc->pc); // mov [arg0],desc->pc
+ UML_CALLC(block, cfunc_printf_debug, ppc); // callc printf_debug
+ }
+ UML_EXH(block, *ppc->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, *ppc->impstate->exception[EXCEPTION_PROGRAM], 0x80000); // exh exception_program,0x80000
+
+ /* if this is a privileged opcode in user mode, generate the exception */
+ else if ((desc->flags & OPFLAG_PRIVILEGED) && (ppc->impstate->mode & MODE_USER))
+ UML_EXH(block, *ppc->impstate->exception[EXCEPTION_PROGRAM], 0x40000); // exh exception_program,0x40000
+
+ /* 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(ppc, block, compiler, desc))
+ {
+ UML_MOV(block, mem(&ppc->pc), desc->pc); // mov [pc],desc->pc
+ UML_MOV(block, mem(&ppc->impstate->arg0), desc->opptr.l[0]); // mov [arg0],*desc->opptr.l
+ UML_CALLC(block, cfunc_unimplemented, ppc); // callc cfunc_unimplemented,ppc
+ }
+ }
+}
+
+
+/*------------------------------------------------------------------
+ generate_compute_flags - compute CR0 and/or XER flags
+------------------------------------------------------------------*/
+
+static void generate_compute_flags(powerpc_state *ppc, drcuml_block *block, const opcode_desc *desc, int updatecr, UINT32 xermask, int invertcarry)
+{
+ UINT32 xerflags;
+
+ /* modify inputs based on required flags */
+ if (!DISABLE_FLAG_OPTIMIZATIONS)
+ {
+ if (!(desc->regreq[3] & REGFLAG_XER_CA))
+ xermask &= ~XER_CA;
+ if (!(desc->regreq[2] & REGFLAG_CR(0)))
+ updatecr = 0;
+ }
+ xerflags = ((xermask & XER_OV) ? FLAG_V : 0) | ((xermask & XER_CA) ? FLAG_C : 0);
+
+ /* easy case: nothing to do */
+ if (!updatecr && xermask == 0)
+ return;
+
+ /* semi-easy case: crfield only */
+ if (xermask == 0)
+ {
+ UML_GETFLGS(block, I0, FLAG_S | FLAG_Z); // getflgs i0,sz
+ UML_LOAD(block, I0, ppc->impstate->sz_cr_table, I0, SIZE_BYTE, SCALE_x1); // load i0,sz_cr_table,i0,byte
+ UML_OR(block, CR32(0), I0, XERSO32); // or [cr0],i0,[xerso]
+ return;
+ }
+
+ /* semi-easy case: xer only */
+ if (!updatecr)
+ {
+ if (xermask & XER_OV)
+ {
+ UML_GETFLGS(block, I0, xerflags); // getflgs i0,xerflags
+ if (invertcarry && (xermask & XER_CA))
+ UML_XOR(block, I0, I0, FLAG_C); // xor i0,i0,FLAG_C
+ UML_ROLINS(block, SPR32(SPR_XER), I0, 29, xermask); // rolins [xer],i0,29,xermask
+ UML_SHR(block, I0, I0, 1); // shr i0,i0,1
+ UML_OR(block, XERSO32, XERSO32, I0); // or [xerso],i0
+ }
+ else
+ {
+ UML_SETc(block, invertcarry ? COND_NC : COND_C, I0); // setc i0,nc/c
+ UML_ROLINS(block, SPR32(SPR_XER), I0, 29, XER_CA); // rolins [xer],i0,29,XER_CA
+ }
+ return;
+ }
+
+ /* tricky case: both */
+ UML_GETFLGS(block, I0, FLAG_S | FLAG_Z | xerflags); // getflgs i0,SZ | xerflags
+ UML_LOAD(block, I1, ppc->impstate->sz_cr_table, I0, SIZE_BYTE, SCALE_x1); // load i1,sz_cr_table,i0,byte
+ if (invertcarry && (xermask & XER_CA))
+ UML_XOR(block, I0, I0, FLAG_C); // xor i0,i0,FLAG_C
+ UML_ROLINS(block, SPR32(SPR_XER), I0, 29, xermask); // rolins [xer],i0,29,xermask
+ if (xermask & XER_OV)
+ {
+ UML_ROLAND(block, I0, I0, 31, 1); // roland i0,i0,31,0x0001
+ UML_OR(block, XERSO32, XERSO32, I0); // or [xerso],i0
+ UML_OR(block, CR32(0), I1, I0); // or [cr0],i1,i0
+ }
+ else
+ UML_OR(block, CR32(0), I1, XERSO32); // or [cr0],i1,[xerso]
+}
+
+/*-------------------------------------------------
+ generate_fp_flags - compute FPSCR floating
+ point status flags
+-------------------------------------------------*/
+
+static void generate_fp_flags(powerpc_state *ppc, drcuml_block *block, const opcode_desc *desc, int updatefprf)
+{
+ /* for now, only handle the FPRF field */
+ if (updatefprf)
+ {
+ UML_MOV(block, mem(&ppc->param0), G_RD(desc->opptr.l[0]));
+ UML_CALLC(block, (c_function)ppccom_update_fprf, ppc);
+ }
+}
+
+/*-------------------------------------------------
+ generate_branch - generate an unconditional
+ branch
+-------------------------------------------------*/
+
+static void generate_branch(powerpc_state *ppc, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int source, UINT8 link)
+{
+ compiler_state compiler_temp = *compiler;
+ UINT32 *srcptr = &ppc->spr[source];
+
+ /* set the link if needed */
+ if (link)
+ {
+ if (desc->targetpc == BRANCH_TARGET_DYNAMIC && source == SPR_LR)
+ {
+ UML_MOV(block, mem(&ppc->impstate->tempaddr), mem(srcptr)); // mov [tempaddr],[lr]
+ srcptr = &ppc->impstate->tempaddr;
+ }
+ UML_MOV(block, SPR32(SPR_LR), desc->pc + 4); // mov [lr],desc->pc + 4
+ }
+
+ /* update the cycles and jump through the hash table to the target */
+ if (desc->targetpc != BRANCH_TARGET_DYNAMIC)
+ {
+ generate_update_cycles(ppc, 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, ppc->impstate->mode, desc->targetpc, *ppc->impstate->nocode);
+ // hashjmp <mode>,desc->targetpc,nocode
+ }
+ else
+ {
+ generate_update_cycles(ppc, block, &compiler_temp, mem(srcptr), TRUE); // <subtract cycles>
+ UML_HASHJMP(block, ppc->impstate->mode, mem(srcptr), *ppc->impstate->nocode); // hashjmp <mode>,<rsreg>,nocode
+ }
+
+ /* update the label */
+ compiler->labelnum = compiler_temp.labelnum;
+
+ /* reset the mapvar to the current cycles */
+ UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler->cycles
+}
+
+
+/*-------------------------------------------------
+ generate_branch_bo - generate a conditional
+ branch based on the BO and BI fields
+-------------------------------------------------*/
+
+static void generate_branch_bo(powerpc_state *ppc, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 bo, UINT32 bi, int source, int link)
+{
+ int skip = compiler->labelnum++;
+
+ if (!(bo & 0x04))
+ {
+ UML_SUB(block, SPR32(SPR_CTR), SPR32(SPR_CTR), 1); // sub [ctr],[ctr],1
+ UML_JMPc(block, (bo & 0x02) ? COND_NZ : COND_Z, skip); // jmp skip,nz/z
+ }
+ if (!(bo & 0x10))
+ {
+ UML_TEST(block, CR32(bi / 4), 8 >> (bi % 4)); // test cr32(bi/4),8 >> (bi % 4)
+ UML_JMPc(block, (bo & 0x08) ? COND_Z : COND_NZ, skip); // jmp skip,z/nz
+ }
+ generate_branch(ppc, block, compiler, desc, source, link); // <branch>
+ UML_LABEL(block, skip); // skip:
+}
+
+
+/*-------------------------------------------------
+ generate_opcode - generate code for a specific
+ opcode
+-------------------------------------------------*/
+
+static int generate_opcode(powerpc_state *ppc, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 op = desc->opptr.l[0];
+ UINT32 opswitch = op >> 26;
+ int regnum;
+
+ switch (opswitch)
+ {
+ case 0x02: /* TDI - 64-bit only */
+ case 0x1e: /* 0x1e group - 64-bit only */
+ case 0x3a: /* 0x3a group - 64-bit only */
+ case 0x3e: /* 0x3e group - 64-bit only */
+ return FALSE;
+
+ case 0x03: /* TWI */
+ UML_CMP(block, R32(G_RA(op)), (INT16)G_SIMM(op)); // cmp ra,simm
+ if (G_TO(op) & 0x10)
+ UML_EXHc(block, COND_L, *ppc->impstate->exception[EXCEPTION_PROGRAM], 0x20000);// exh program,0x20000,l
+ if (G_TO(op) & 0x08)
+ UML_EXHc(block, COND_G, *ppc->impstate->exception[EXCEPTION_PROGRAM], 0x20000);// exh program,0x20000,g
+ if (G_TO(op) & 0x04)
+ UML_EXHc(block, COND_E, *ppc->impstate->exception[EXCEPTION_PROGRAM], 0x20000);// exh program,0x20000,e
+ if (G_TO(op) & 0x02)
+ UML_EXHc(block, COND_B, *ppc->impstate->exception[EXCEPTION_PROGRAM], 0x20000);// exh program,0x20000,b
+ if (G_TO(op) & 0x01)
+ UML_EXHc(block, COND_A, *ppc->impstate->exception[EXCEPTION_PROGRAM], 0x20000);// exh program,0x20000,a
+ return TRUE;
+
+ case 0x07: /* MULLI */
+ UML_MULS(block, R32(G_RD(op)), R32(G_RD(op)), R32(G_RA(op)), (INT16)G_SIMM(op));
+ // muls rd,rd,ra,simm
+ return TRUE;
+
+ case 0x0e: /* ADDI */
+ UML_ADD(block, R32(G_RD(op)), R32Z(G_RA(op)), (INT16)G_SIMM(op)); // add rd,ra,simm
+ return TRUE;
+
+ case 0x0f: /* ADDIS */
+ UML_ADD(block, R32(G_RD(op)), R32Z(G_RA(op)), G_SIMM(op) << 16); // add rd,ra,simm << 16
+ return TRUE;
+
+ case 0x0a: /* CMPLI */
+ UML_CMP(block, R32(G_RA(op)), G_UIMM(op)); // cmp ra,uimm
+ UML_GETFLGS(block, I0, FLAG_Z | FLAG_C); // getflgs i0,zc
+ UML_LOAD(block, I0, ppc->impstate->cmpl_cr_table, I0, SIZE_BYTE, SCALE_x1);// load i0,cmpl_cr_table,i0,byte
+ UML_OR(block, CR32(G_CRFD(op)), I0, XERSO32); // or [crn],i0,[xerso]
+ return TRUE;
+
+ case 0x0b: /* CMPI */
+ UML_CMP(block, R32(G_RA(op)), (INT16)G_SIMM(op)); // cmp ra,uimm
+ UML_GETFLGS(block, I0, FLAG_Z | FLAG_C | FLAG_S); // getflgs i0,zcs
+ UML_LOAD(block, I0, ppc->impstate->cmp_cr_table, I0, SIZE_BYTE, SCALE_x1);// load i0,cmp_cr_table,i0,byte
+ UML_OR(block, CR32(G_CRFD(op)), I0, XERSO32); // or [crn],i0,[xerso]
+ return TRUE;
+
+ case 0x08: /* SUBFIC */
+ UML_SUB(block, R32(G_RD(op)), (INT16)G_SIMM(op), R32(G_RA(op))); // sub rd,simm,ra
+ generate_compute_flags(ppc, block, desc, FALSE, XER_CA, TRUE); // <update flags>
+ return TRUE;
+
+ case 0x0c: /* ADDIC */
+ UML_ADD(block, R32(G_RD(op)), R32(G_RA(op)), (INT16)G_SIMM(op)); // add rd,ra,simm
+ generate_compute_flags(ppc, block, desc, FALSE, XER_CA, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x0d: /* ADDIC. */
+ UML_ADD(block, R32(G_RD(op)), R32(G_RA(op)), (INT16)G_SIMM(op)); // add rd,ra,simm
+ generate_compute_flags(ppc, block, desc, TRUE, XER_CA, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x10: /* BCx */
+ generate_branch_bo(ppc, block, compiler, desc, G_BO(op), G_BI(op), 0, op & M_LK);// <branch conditional>
+ return TRUE;
+
+ case 0x11: /* SC */
+ UML_MAPVAR(block, MAPVAR_PC, desc->pc + 4); // mapvar PC,desc->pc+4
+ UML_EXH(block, *ppc->impstate->exception[EXCEPTION_SYSCALL], 0); // exh syscall,0
+ return TRUE;
+
+ case 0x12: /* Bx */
+ generate_branch(ppc, block, compiler, desc, 0, op & M_LK); // <branch>
+ return TRUE;
+
+ case 0x13: /* 0x13 group */
+ return generate_instruction_13(ppc, block, compiler, desc); // <group13>
+
+ case 0x14: /* RLWIMIx */
+ UML_ROLINS(block, R32(G_RA(op)), R32(G_RS(op)), G_SH(op), compute_rlw_mask(G_MB(op), G_ME(op)));
+ // rolins ra,rs,sh,mask
+ if (op & M_RC)
+ generate_compute_flags(ppc, block, desc, TRUE, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x15: /* RLWINMx */
+ UML_ROLAND(block, R32(G_RA(op)), R32(G_RS(op)), G_SH(op), compute_rlw_mask(G_MB(op), G_ME(op)));
+ // roland ra,rs,sh,mask
+ if (op & M_RC)
+ generate_compute_flags(ppc, block, desc, TRUE, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x17: /* RLWNMx */
+ UML_ROLAND(block, R32(G_RA(op)), R32(G_RS(op)), R32(G_RB(op)), compute_rlw_mask(G_MB(op), G_ME(op)));
+ // roland ra,rs,rb,mask
+ if (op & M_RC)
+ generate_compute_flags(ppc, block, desc, TRUE, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x18: /* ORI */
+ UML_OR(block, R32(G_RA(op)), R32(G_RS(op)), G_UIMM(op)); // or ra,rs,uimm
+ return TRUE;
+
+ case 0x19: /* ORIS */
+ UML_OR(block, R32(G_RA(op)), R32(G_RS(op)), G_UIMM(op) << 16); // or ra,rs,uimm << 16
+ return TRUE;
+
+ case 0x1a: /* XORI */
+ UML_XOR(block, R32(G_RA(op)), R32(G_RS(op)), G_UIMM(op)); // xor ra,rs,uimm
+ return TRUE;
+
+ case 0x1b: /* XORIS */
+ UML_XOR(block, R32(G_RA(op)), R32(G_RS(op)), G_UIMM(op) << 16); // xor ra,rs,uimm << 16
+ return TRUE;
+
+ case 0x1c: /* ANDI. */
+ UML_AND(block, R32(G_RA(op)), R32(G_RS(op)), G_UIMM(op)); // and ra,rs,uimm
+ generate_compute_flags(ppc, block, desc, TRUE, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x1d: /* ANDIS. */
+ UML_AND(block, R32(G_RA(op)), R32(G_RS(op)), G_UIMM(op) << 16); // and ra,rs,uimm << 16
+ generate_compute_flags(ppc, block, desc, TRUE, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x1f: /* 0x1f group */
+ return generate_instruction_1f(ppc, block, compiler, desc); // <group1f>
+
+ case 0x22: /* LBZ */
+ UML_ADD(block, I0, R32Z(G_RA(op)), (INT16)G_SIMM(op)); // add i0,ra,simm
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op)
+ UML_CALLH(block, *ppc->impstate->read8[ppc->impstate->mode]); // callh read8
+ UML_AND(block, R32(G_RD(op)), I0, 0xff); // and rd,i0,0xff
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x28: /* LHZ */
+ UML_ADD(block, I0, R32Z(G_RA(op)), (INT16)G_SIMM(op)); // add i0,ra,simm
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op)
+ UML_CALLH(block, *ppc->impstate->read16[ppc->impstate->mode]); // callh read16
+ UML_AND(block, R32(G_RD(op)), I0, 0xffff); // and rd,i0,0xffff
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x2a: /* LHA */
+ UML_ADD(block, I0, R32Z(G_RA(op)), (INT16)G_SIMM(op)); // add i0,ra,simm
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op)
+ UML_CALLH(block, *ppc->impstate->read16[ppc->impstate->mode]); // callh read16
+ UML_SEXT(block, R32(G_RD(op)), I0, SIZE_WORD); // sext rd,i0,word
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x20: /* LWZ */
+ UML_ADD(block, I0, R32Z(G_RA(op)), (INT16)G_SIMM(op)); // add i0,ra,simm
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op)
+ UML_CALLH(block, *ppc->impstate->read32[ppc->impstate->mode]); // callh read32
+ UML_MOV(block, R32(G_RD(op)), I0); // mov rd,i0
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x23: /* LBZU */
+ UML_ADD(block, I0, R32(G_RA(op)), (INT16)G_SIMM(op)); // add i0,ra,simm
+ UML_MOV(block, mem(&ppc->impstate->updateaddr), I0); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ UML_CALLH(block, *ppc->impstate->read8[ppc->impstate->mode]); // callh read8
+ UML_AND(block, R32(G_RD(op)), I0, 0xff); // and rd,i0,0xff
+ UML_MOV(block, R32(G_RA(op)), mem(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x29: /* LHZU */
+ UML_ADD(block, I0, R32(G_RA(op)), (INT16)G_SIMM(op)); // add i0,ra,simm
+ UML_MOV(block, mem(&ppc->impstate->updateaddr), I0); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ UML_CALLH(block, *ppc->impstate->read16[ppc->impstate->mode]); // callh read16
+ UML_AND(block, R32(G_RD(op)), I0, 0xffff); // and rd,i0,0xffff
+ UML_MOV(block, R32(G_RA(op)), mem(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x2b: /* LHAU */
+ UML_ADD(block, I0, R32(G_RA(op)), (INT16)G_SIMM(op)); // add i0,ra,simm
+ UML_MOV(block, mem(&ppc->impstate->updateaddr), I0); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ UML_CALLH(block, *ppc->impstate->read16[ppc->impstate->mode]); // callh read16
+ UML_SEXT(block, R32(G_RD(op)), I0, SIZE_WORD); // sext rd,i0,word
+ UML_MOV(block, R32(G_RA(op)), mem(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x21: /* LWZU */
+ UML_ADD(block, I0, R32(G_RA(op)), (INT16)G_SIMM(op)); // add i0,ra,simm
+ UML_MOV(block, mem(&ppc->impstate->updateaddr), I0); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ UML_CALLH(block, *ppc->impstate->read32[ppc->impstate->mode]); // callh read32
+ UML_MOV(block, R32(G_RD(op)), I0); // mov rd,i0
+ UML_MOV(block, R32(G_RA(op)), mem(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x26: /* STB */
+ UML_ADD(block, I0, R32Z(G_RA(op)), (INT16)G_SIMM(op)); // add i0,ra,simm
+ UML_AND(block, I1, R32(G_RS(op)), 0xff); // and i1,rs,0xff
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op)
+ UML_CALLH(block, *ppc->impstate->write8[ppc->impstate->mode]); // callh write8
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x2c: /* STH */
+ UML_ADD(block, I0, R32Z(G_RA(op)), (INT16)G_SIMM(op)); // add i0,ra,simm
+ UML_AND(block, I1, R32(G_RS(op)), 0xffff); // and i1,rs,0xffff
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op)
+ UML_CALLH(block, *ppc->impstate->write16[ppc->impstate->mode]); // callh write16
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x24: /* STW */
+ UML_ADD(block, I0, R32Z(G_RA(op)), (INT16)G_SIMM(op)); // add i0,ra,simm
+ UML_MOV(block, I1, R32(G_RS(op))); // mov i1,rs
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op)
+ UML_CALLH(block, *ppc->impstate->write32[ppc->impstate->mode]); // callh write32
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x27: /* STBU */
+ UML_ADD(block, I0, R32(G_RA(op)), (INT16)G_SIMM(op)); // add i0,ra,simm
+ UML_AND(block, I1, R32(G_RS(op)), 0xff); // and i1,rs,0xff
+ UML_MOV(block, mem(&ppc->impstate->updateaddr), I0); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ UML_CALLH(block, *ppc->impstate->write8[ppc->impstate->mode]); // callh write8
+ UML_MOV(block, R32(G_RA(op)), mem(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x2d: /* STHU */
+ UML_ADD(block, I0, R32(G_RA(op)), (INT16)G_SIMM(op)); // add i0,ra,simm
+ UML_AND(block, I1, R32(G_RS(op)), 0xffff); // and i1,rs,0xffff
+ UML_MOV(block, mem(&ppc->impstate->updateaddr), I0); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ UML_CALLH(block, *ppc->impstate->write16[ppc->impstate->mode]); // callh write16
+ UML_MOV(block, R32(G_RA(op)), mem(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x25: /* STWU */
+ UML_ADD(block, I0, R32(G_RA(op)), (INT16)G_SIMM(op)); // add i0,ra,simm
+ UML_MOV(block, I1, R32(G_RS(op))); // mov i1,rs
+ UML_MOV(block, mem(&ppc->impstate->updateaddr), I0); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ UML_CALLH(block, *ppc->impstate->write32[ppc->impstate->mode]); // callh write32
+ UML_MOV(block, R32(G_RA(op)), mem(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x2e: /* LMW */
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ UML_MOV(block, mem(&ppc->impstate->tempaddr), R32Z(G_RA(op))); // mov [tempaddr],ra
+ for (regnum = G_RD(op); regnum < 32; regnum++)
+ {
+ UML_ADD(block, I0, mem(&ppc->impstate->tempaddr), (INT16)G_SIMM(op) + 4 * (regnum - G_RD(op)));
+ // add i0,[tempaddr],simm + 4*(regnum-rd)
+ UML_CALLH(block, *ppc->impstate->read32align[ppc->impstate->mode]); // callh read32align
+ UML_MOV(block, R32(regnum), I0); // mov regnum,i0
+ }
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x2f: /* STMW */
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ UML_MOV(block, mem(&ppc->impstate->tempaddr), R32Z(G_RA(op))); // mov [tempaddr],ra
+ for (regnum = G_RS(op); regnum < 32; regnum++)
+ {
+ UML_ADD(block, I0, mem(&ppc->impstate->tempaddr), (INT16)G_SIMM(op) + 4 * (regnum - G_RS(op)));
+ // add i0,[tempaddr],simm + 4*(regnum-rs)
+ UML_MOV(block, I1, R32(regnum)); // mov i1,regnum
+ UML_CALLH(block, *ppc->impstate->write32align[ppc->impstate->mode]); // callh write32align
+ }
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x30: /* LFS */
+ UML_ADD(block, I0, R32Z(G_RA(op)), (INT16)G_SIMM(op)); // add i0,ra,simm
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op)
+ UML_CALLH(block, *ppc->impstate->read32[ppc->impstate->mode]); // callh read32
+ UML_MOV(block, mem(&ppc->impstate->tempdata.w.l), I0); // mov [tempdata],i0
+ UML_FDFRFLT(block, F64(G_RD(op)), mem(&ppc->impstate->tempdata.w.l), SIZE_DWORD); // fdfrflt fd,[tempdata],dword
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x32: /* LFD */
+ UML_ADD(block, I0, R32Z(G_RA(op)), (INT16)G_SIMM(op)); // add i0,ra,simm
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op)
+ UML_CALLH(block, *ppc->impstate->read64[ppc->impstate->mode]); // callh read64
+ UML_DMOV(block, mem(&ppc->impstate->tempdata.d), I0); // dmov [tempdata],i0
+ UML_FDMOV(block, F64(G_RD(op)), mem(&ppc->impstate->tempdata.d)); // fdmov fd,[tempdata]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x31: /* LFSU */
+ UML_ADD(block, I0, R32(G_RA(op)), (INT16)G_SIMM(op)); // add i0,ra,simm
+ UML_MOV(block, mem(&ppc->impstate->updateaddr), I0); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ UML_CALLH(block, *ppc->impstate->read32[ppc->impstate->mode]); // callh read32
+ UML_MOV(block, mem(&ppc->impstate->tempdata.w.l), I0); // mov [tempdata],i0
+ UML_FDFRFLT(block, F64(G_RD(op)), mem(&ppc->impstate->tempdata.w.l), SIZE_DWORD); // fdfrflt fd,[tempdata],dword
+ UML_MOV(block, R32(G_RA(op)), mem(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x33: /* LFDU */
+ UML_ADD(block, I0, R32(G_RA(op)), (INT16)G_SIMM(op)); // add i0,ra,simm
+ UML_MOV(block, mem(&ppc->impstate->updateaddr), I0); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ UML_CALLH(block, *ppc->impstate->read64[ppc->impstate->mode]); // callh read64
+ UML_DMOV(block, mem(&ppc->impstate->tempdata.d), I0); // dmov [tempdata],i0
+ UML_FDMOV(block, F64(G_RD(op)), mem(&ppc->impstate->tempdata.d)); // fdmov fd,[tempdata]
+ UML_MOV(block, R32(G_RA(op)), mem(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x34: /* STFS */
+ UML_ADD(block, I0, R32Z(G_RA(op)), (INT16)G_SIMM(op)); // add i0,ra,simm
+ UML_FSFRFLT(block, mem(&ppc->impstate->tempdata.w.l), F64(G_RS(op)), SIZE_QWORD); // fsfrflt [tempdata],rs,qword
+ UML_MOV(block, I1, mem(&ppc->impstate->tempdata.w.l)); // mov i1,[tempdata]
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op)
+ UML_CALLH(block, *ppc->impstate->write32[ppc->impstate->mode]); // callh write32
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x36: /* STFD */
+ UML_ADD(block, I0, R32Z(G_RA(op)), (INT16)G_SIMM(op)); // add i0,ra,simm
+ UML_FDMOV(block, mem(&ppc->impstate->tempdata.d), F64(G_RS(op))); // fdmov [tempdata],rs
+ UML_DMOV(block, I1, mem(&ppc->impstate->tempdata.d)); // dmov i1,[tempdata]
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op)
+ UML_CALLH(block, *ppc->impstate->write64[ppc->impstate->mode]); // callh write64
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x35: /* STFSU */
+ UML_ADD(block, I0, R32(G_RA(op)), (INT16)G_SIMM(op)); // add i0,ra,simm
+ UML_FSFRFLT(block, mem(&ppc->impstate->tempdata.w.l), F64(G_RS(op)), SIZE_QWORD); // fsfrflt [tempdata],rs,qword
+ UML_MOV(block, I1, mem(&ppc->impstate->tempdata.w.l)); // mov i1,[tempdata]
+ UML_MOV(block, mem(&ppc->impstate->updateaddr), I0); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ UML_CALLH(block, *ppc->impstate->write32[ppc->impstate->mode]); // callh write32
+ UML_MOV(block, R32(G_RA(op)), mem(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x37: /* STFDU */
+ UML_ADD(block, I0, R32(G_RA(op)), (INT16)G_SIMM(op)); // add i0,ra,simm
+ UML_FDMOV(block, mem(&ppc->impstate->tempdata.d), F64(G_RS(op))); // fdmov [tempdata],rs
+ UML_DMOV(block, I1, mem(&ppc->impstate->tempdata.d)); // dmov i1,[tempdata]
+ UML_MOV(block, mem(&ppc->impstate->updateaddr), I0); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ UML_CALLH(block, *ppc->impstate->write64[ppc->impstate->mode]); // callh write64
+ UML_MOV(block, R32(G_RA(op)), mem(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x3b: /* 0x3b group */
+ return generate_instruction_3b(ppc, block, compiler, desc); // <group3b>
+
+ case 0x3f: /* 0x3f group */
+ return generate_instruction_3f(ppc, block, compiler, desc); // <group3f>
+ }
+
+ return FALSE;
+}
+
+
+/*-------------------------------------------------
+ generate_instruction_13 - compile opcodes in
+ the 0x13 group
+-------------------------------------------------*/
+
+static int generate_instruction_13(powerpc_state *ppc, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 op = desc->opptr.l[0];
+ UINT32 opswitch = (op >> 1) & 0x3ff;
+
+ switch (opswitch)
+ {
+ case 0x010: /* BCLRx */
+ generate_branch_bo(ppc, block, compiler, desc, G_BO(op), G_BI(op), SPR_LR, op & M_LK);// <branch conditional>
+ return TRUE;
+
+ case 0x210: /* BCCTRx */
+ generate_branch_bo(ppc, block, compiler, desc, G_BO(op), G_BI(op), SPR_CTR, op & M_LK);
+ // <branch conditional>
+ return TRUE;
+
+ case 0x000: /* MCRF */
+ UML_MOV(block, CR32(G_CRFD(op)), CR32(G_CRFS(op))); // mov [crd],[crs]
+ return TRUE;
+
+ case 0x101: /* CRAND */
+ UML_SHL(block, I0, CR32(G_CRBA(op) / 4), G_CRBA(op) % 4); // shl i0,cr(a / 4),a % 4
+ UML_SHL(block, I1, CR32(G_CRBB(op) / 4), G_CRBB(op) % 4); // shl i1,cr(b / 4),b % 4
+ UML_AND(block, I0, I0, I1); // and i0,i1
+ UML_ROLINS(block, CR32(G_CRBD(op) / 4), I0, 32 - G_CRBD(op) % 4, 8 >> (G_CRBD(op) % 4));
+ // rolins cr(d / 4),i0,32-(d % 4),8 >> (d % 4)
+ return TRUE;
+
+ case 0x081: /* CRANDC */
+ UML_SHL(block, I0, CR32(G_CRBA(op) / 4), G_CRBA(op) % 4); // shl i0,cr(a / 4),a % 4
+ UML_SHL(block, I1, CR32(G_CRBB(op) / 4), G_CRBB(op) % 4); // shl i1,cr(b / 4),b % 4
+ UML_XOR(block, I1, I1, ~0); // xor i1,~0
+ UML_AND(block, I0, I0, I1); // and i0,i1
+ UML_ROLINS(block, CR32(G_CRBD(op) / 4), I0, 32 - G_CRBD(op) % 4, 8 >> (G_CRBD(op) % 4));
+ // rolins cr(d / 4),i0,32-(d % 4),8 >> (d % 4)
+ return TRUE;
+
+ case 0x0e1: /* CRNAND */
+ UML_SHL(block, I0, CR32(G_CRBA(op) / 4), G_CRBA(op) % 4); // shl i0,cr(a / 4),a % 4
+ UML_SHL(block, I1, CR32(G_CRBB(op) / 4), G_CRBB(op) % 4); // shl i1,cr(b / 4),b % 4
+ UML_AND(block, I0, I0, I1); // and i0,i1
+ UML_XOR(block, I0, I0, ~0); // xor i0,~0
+ UML_ROLINS(block, CR32(G_CRBD(op) / 4), I0, 32 - G_CRBD(op) % 4, 8 >> (G_CRBD(op) % 4));
+ // rolins cr(d / 4),i0,32-(d % 4),8 >> (d % 4)
+ return TRUE;
+
+ case 0x1c1: /* CROR */
+ UML_SHL(block, I0, CR32(G_CRBA(op) / 4), G_CRBA(op) % 4); // shl i0,cr(a / 4),a % 4
+ UML_SHL(block, I1, CR32(G_CRBB(op) / 4), G_CRBB(op) % 4); // shl i1,cr(b / 4),b % 4
+ UML_OR(block, I0, I0, I1); // or i0,i1
+ UML_ROLINS(block, CR32(G_CRBD(op) / 4), I0, 32 - G_CRBD(op) % 4, 8 >> (G_CRBD(op) % 4));
+ // rolins cr(d / 4),i0,32-(d % 4),8 >> (d % 4)
+ return TRUE;
+
+ case 0x1a1: /* CRORC */
+ UML_SHL(block, I0, CR32(G_CRBA(op) / 4), G_CRBA(op) % 4); // shl i0,cr(a / 4),a % 4
+ UML_SHL(block, I1, CR32(G_CRBB(op) / 4), G_CRBB(op) % 4); // shl i1,cr(b / 4),b % 4
+ UML_XOR(block, I1, I1, ~0); // xor i1,~0
+ UML_OR(block, I0, I0, I1); // or i0,i1
+ UML_ROLINS(block, CR32(G_CRBD(op) / 4), I0, 32 - G_CRBD(op) % 4, 8 >> (G_CRBD(op) % 4));
+ // rolins cr(d / 4),i0,32-(d % 4),8 >> (d % 4)
+ return TRUE;
+
+ case 0x021: /* CRNOR */
+ UML_SHL(block, I0, CR32(G_CRBA(op) / 4), G_CRBA(op) % 4); // shl i0,cr(a / 4),a % 4
+ UML_SHL(block, I1, CR32(G_CRBB(op) / 4), G_CRBB(op) % 4); // shl i1,cr(b / 4),b % 4
+ UML_OR(block, I0, I0, I1); // or i0,i1
+ UML_XOR(block, I0, I0, ~0); // xor i0,~0
+ UML_ROLINS(block, CR32(G_CRBD(op) / 4), I0, 32 - G_CRBD(op) % 4, 8 >> (G_CRBD(op) % 4));
+ // rolins cr(d / 4),i0,32-(d % 4),8 >> (d % 4)
+ return TRUE;
+
+ case 0x0c1: /* CRXOR */
+ UML_SHL(block, I0, CR32(G_CRBA(op) / 4), G_CRBA(op) % 4); // shl i0,cr(a / 4),a % 4
+ UML_SHL(block, I1, CR32(G_CRBB(op) / 4), G_CRBB(op) % 4); // shl i1,cr(b / 4),b % 4
+ UML_XOR(block, I0, I0, I1); // xor i0,i1
+ UML_ROLINS(block, CR32(G_CRBD(op) / 4), I0, 32 - G_CRBD(op) % 4, 8 >> (G_CRBD(op) % 4));
+ // rolins cr(d / 4),i0,32-(d % 4),8 >> (d % 4)
+ return TRUE;
+
+ case 0x121: /* CREQV */
+ UML_SHL(block, I0, CR32(G_CRBA(op) / 4), G_CRBA(op) % 4); // shl i0,cr(a / 4),a % 4
+ UML_SHL(block, I1, CR32(G_CRBB(op) / 4), G_CRBB(op) % 4); // shl i1,cr(b / 4),b % 4
+ UML_XOR(block, I0, I0, I1); // xor i0,i1
+ UML_XOR(block, I0, I0, ~0); // xor i0,~0
+ UML_ROLINS(block, CR32(G_CRBD(op) / 4), I0, 32 - G_CRBD(op) % 4, 8 >> (G_CRBD(op) % 4));
+ // rolins cr(d / 4),i0,32-(d % 4),8 >> (d % 4)
+ return TRUE;
+
+ case 0x032: /* RFI */
+ if (ppc->cap & PPCCAP_OEA)
+ {
+ if (!(ppc->cap & PPCCAP_603_MMU))
+ UML_ROLINS(block, MSR32, SPR32(SPROEA_SRR1), 0, 0x87c0ffff); // rolins [msr],[srr1],0,0x87c0ffff
+ else
+ {
+ UML_MOV(block, I0, MSR32); // mov i0,[msr]
+ UML_ROLINS(block, MSR32, SPR32(SPROEA_SRR1), 0, 0x87c0ffff | MSR603_TGPR);
+ // rolins [msr],[srr1],0,0x87c0ffff | MSR603_TGPR
+ UML_XOR(block, I0, I0, MSR32); // xor i0,i0,[msr]
+ UML_TEST(block, I0, MSR603_TGPR); // test i0,tgpr
+ UML_CALLHc(block, COND_NZ, *ppc->impstate->swap_tgpr); // callh swap_tgpr,nz
+ }
+ }
+ else if (ppc->cap & PPCCAP_4XX)
+ UML_MOV(block, MSR32, SPR32(SPR4XX_SRR1)); // mov [msr],[srr1]
+ generate_update_mode(ppc, block); // <update mode>
+ compiler->checkints = TRUE;
+ generate_update_cycles(ppc, block, compiler, SPR32(SPROEA_SRR0), TRUE); // <subtract cycles>
+ UML_HASHJMP(block, mem(&ppc->impstate->mode), SPR32(SPROEA_SRR0), *ppc->impstate->nocode);
+ // hashjmp mode,[srr0],nocode
+ return TRUE;
+
+ case 0x033: /* RFCI */
+ assert(ppc->cap & PPCCAP_4XX);
+ UML_MOV(block, MSR32, SPR32(SPR4XX_SRR3)); // mov [msr],[srr3]
+ generate_update_mode(ppc, block); // <update mode>
+ compiler->checkints = TRUE;
+ generate_update_cycles(ppc, block, compiler, SPR32(SPR4XX_SRR2), TRUE); // <subtract cycles>
+ UML_HASHJMP(block, mem(&ppc->impstate->mode), SPR32(SPR4XX_SRR2), *ppc->impstate->nocode);
+ // hashjmp mode,[srr2],nocode
+ return TRUE;
+
+ case 0x096: /* ISYNC */
+ /* effective no-op */
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/*-------------------------------------------------
+ generate_instruction_1f - compile opcodes in
+ the 0x1f group
+-------------------------------------------------*/
+
+static int generate_instruction_1f(powerpc_state *ppc, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 op = desc->opptr.l[0];
+ UINT32 opswitch = (op >> 1) & 0x3ff;
+ int item;
+
+ switch (opswitch)
+ {
+ case 0x009: /* MULHDUx - 64-bit only */
+ case 0x015: /* LDX - 64-bit only */
+ case 0x01b: /* SLDx - 64-bit only */
+ case 0x035: /* LDUX - 64-bit only */
+ case 0x03a: /* CNTLZDx - 64-bit only */
+ case 0x044: /* TD - 64-bit only */
+ case 0x049: /* MULHDx - 64-bit only */
+ case 0x054: /* LDARX - 64-bit only */
+ case 0x095: /* STDX - 64-bit only */
+ case 0x0b5: /* STDUX - 64-bit only */
+ case 0x0d6: /* STDCX. - 64-bit only */
+ case 0x0e9: /* MULLD - 64-bit only */
+ case 0x2e9: /* MULLDO - 64-bit only */
+ case 0x155: /* LWAX - 64-bit only */
+ case 0x175: /* LWAUX - 64-bit only */
+ case 0x33a: /* SRADIx - 64-bit only */
+ case 0x33b: /* SRADIx - 64-bit only */
+ case 0x1b2: /* SLBIE - 64-bit only */
+ case 0x1c9: /* DIVDUx - 64-bit only */
+ case 0x3c9: /* DIVDUOx - 64-bit only */
+ case 0x1e9: /* DIVDx - 64-bit only */
+ case 0x3e9: /* DIVDOx - 64-bit only */
+ case 0x1f2: /* SLBIA - 64-bit only */
+ case 0x21b: /* SRDx - 64-bit only */
+ case 0x31a: /* SRADx - 64-bit only */
+ case 0x3da: /* EXTSW - 64-bit only */
+ return FALSE;
+
+ case 0x004: /* TW */
+ UML_CMP(block, R32(G_RA(op)), R32(G_RB(op))); // cmp ra,rb
+ if (G_TO(op) & 0x10)
+ UML_EXHc(block, COND_L, *ppc->impstate->exception[EXCEPTION_PROGRAM], 0x20000);// exh program,0x20000,l
+ if (G_TO(op) & 0x08)
+ UML_EXHc(block, COND_G, *ppc->impstate->exception[EXCEPTION_PROGRAM], 0x20000);// exh program,0x20000,g
+ if (G_TO(op) & 0x04)
+ UML_EXHc(block, COND_E, *ppc->impstate->exception[EXCEPTION_PROGRAM], 0x20000);// exh program,0x20000,e
+ if (G_TO(op) & 0x02)
+ UML_EXHc(block, COND_B, *ppc->impstate->exception[EXCEPTION_PROGRAM], 0x20000);// exh program,0x20000,b
+ if (G_TO(op) & 0x01)
+ UML_EXHc(block, COND_A, *ppc->impstate->exception[EXCEPTION_PROGRAM], 0x20000);// exh program,0x20000,a
+ return TRUE;
+
+ case 0x10a: /* ADDx */
+ case 0x30a: /* ADDOx */
+ UML_ADD(block, R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op))); // add rd,ra,rb
+ generate_compute_flags(ppc, block, desc, op & M_RC, ((op & M_OE) ? XER_OV : 0), FALSE);
+ // <update flags>
+ return TRUE;
+
+ case 0x00a: /* ADDCx */
+ case 0x20a: /* ADDCOx */
+ UML_ADD(block, R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op))); // add rd,ra,rb
+ generate_compute_flags(ppc, block, desc, op & M_RC, XER_CA | ((op & M_OE) ? XER_OV : 0), FALSE);
+ // <update flags>
+ return TRUE;
+
+ case 0x08a: /* ADDEx */
+ case 0x28a: /* ADDEOx */
+ UML_CARRY(block, SPR32(SPR_XER), 29); // carry [xer],XER_CA
+ UML_ADDC(block, R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op))); // addc rd,ra,rb
+ generate_compute_flags(ppc, block, desc, op & M_RC, XER_CA | ((op & M_OE) ? XER_OV : 0), FALSE);
+ // <update flags>
+ return TRUE;
+
+ case 0x0ca: /* ADDZEx */
+ case 0x2ca: /* ADDZEOx */
+ UML_CARRY(block, SPR32(SPR_XER), 29); // carry [xer],XER_CA
+ UML_ADDC(block, R32(G_RD(op)), R32(G_RA(op)), 0); // addc rd,ra,0
+ generate_compute_flags(ppc, block, desc, op & M_RC, XER_CA | ((op & M_OE) ? XER_OV : 0), FALSE);
+ // <update flags>
+ return TRUE;
+
+ case 0x0ea: /* ADDMEx */
+ case 0x2ea: /* ADDMEOx */
+ UML_CARRY(block, SPR32(SPR_XER), 29); // carry [xer],XER_CA
+ UML_ADDC(block, R32(G_RD(op)), R32(G_RA(op)), (UINT32)-1); // addc rd,ra,-1
+ generate_compute_flags(ppc, block, desc, op & M_RC, XER_CA | ((op & M_OE) ? XER_OV : 0), FALSE);
+ // <update flags>
+ return TRUE;
+
+ case 0x028: /* SUBFx */
+ case 0x228: /* SUBFOx */
+ UML_SUB(block, R32(G_RD(op)), R32(G_RB(op)), R32(G_RA(op))); // sub rd,rb,ra
+ generate_compute_flags(ppc, block, desc, op & M_RC, (op & M_OE) ? XER_OV : 0, TRUE);
+ // <update flags>
+ return TRUE;
+
+ case 0x008: /* SUBFCx */
+ case 0x208: /* SUBFCOx */
+ UML_SUB(block, R32(G_RD(op)), R32(G_RB(op)), R32(G_RA(op))); // sub rd,rb,ra
+ generate_compute_flags(ppc, block, desc, op & M_RC, XER_CA | ((op & M_OE) ? XER_OV : 0), TRUE);
+ // <update flags>
+ return TRUE;
+
+ case 0x088: /* SUBFEx */
+ case 0x288: /* SUBFEOx */
+ UML_XOR(block, I0, SPR32(SPR_XER), XER_CA); // xor i0,[xer],XER_CA
+ UML_CARRY(block, I0, 29); // carry i0,XER_CA
+ UML_SUBB(block, R32(G_RD(op)), R32(G_RB(op)), R32(G_RA(op))); // subc rd,rb,ra
+ generate_compute_flags(ppc, block, desc, op & M_RC, XER_CA | ((op & M_OE) ? XER_OV : 0), TRUE);
+ // <update flags>
+ return TRUE;
+
+ case 0x0c8: /* SUBFZEx */
+ case 0x2c8: /* SUBFZEOx */
+ UML_XOR(block, I0, SPR32(SPR_XER), XER_CA); // xor i0,[xer],XER_CA
+ UML_CARRY(block, I0, 29); // carry i0,XER_CA
+ UML_SUBB(block, R32(G_RD(op)), 0, R32(G_RA(op))); // subc rd,0,ra
+ generate_compute_flags(ppc, block, desc, op & M_RC, XER_CA | ((op & M_OE) ? XER_OV : 0), TRUE);
+ // <update flags>
+ return TRUE;
+
+ case 0x0e8: /* SUBFMEx */
+ case 0x2e8: /* SUBFMEOx */
+ UML_XOR(block, I0, SPR32(SPR_XER), XER_CA); // xor i0,[xer],XER_CA
+ UML_CARRY(block, I0, 29); // carry i0,XER_CA
+ UML_SUBB(block, R32(G_RD(op)), (UINT32)-1, R32(G_RA(op))); // subc rd,-1,ra
+ generate_compute_flags(ppc, block, desc, op & M_RC, XER_CA | ((op & M_OE) ? XER_OV : 0), TRUE);
+ // <update flags>
+ return TRUE;
+
+ case 0x068: /* NEGx */
+ case 0x268: /* NEGOx */
+ UML_SUB(block, R32(G_RD(op)), 0, R32(G_RA(op))); // sub rd,0,ra
+ generate_compute_flags(ppc, block, desc, op & M_RC, (op & M_OE) ? XER_OV : 0, TRUE);
+ // <update flags>
+ return TRUE;
+
+ case 0x000: /* CMP */
+ UML_CMP(block, R32(G_RA(op)), R32(G_RB(op))); // cmp ra,rb
+ UML_GETFLGS(block, I0, FLAG_Z | FLAG_C | FLAG_S); // getflgs i0,zcs
+ UML_LOAD(block, I0, ppc->impstate->cmp_cr_table, I0, SIZE_BYTE, SCALE_x1);// load i0,cmp_cr_table,i0,byte
+ UML_OR(block, CR32(G_CRFD(op)), I0, XERSO32); // or [crn],i0,[xerso]
+ return TRUE;
+
+ case 0x020: /* CMPL */
+ UML_CMP(block, R32(G_RA(op)), R32(G_RB(op))); // cmp ra,rb
+ UML_GETFLGS(block, I0, FLAG_Z | FLAG_C); // getflgs i0,zc
+ UML_LOAD(block, I0, ppc->impstate->cmpl_cr_table, I0, SIZE_BYTE, SCALE_x1);// load i0,cmpl_cr_table,i0,byte
+ UML_OR(block, CR32(G_CRFD(op)), I0, XERSO32); // or [crn],i0,[xerso]
+ return TRUE;
+
+ case 0x00b: /* MULHWUx */
+ UML_MULU(block, I0, R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op))); // mulu i0,rd,ra,rb
+ if (op & M_RC)
+ {
+ UML_TEST(block, R32(G_RD(op)), ~0); // test rd,~0
+ generate_compute_flags(ppc, block, desc, op & M_RC, 0, FALSE); // <update flags>
+ }
+ return TRUE;
+
+ case 0x04b: /* MULHWx */
+ UML_MULS(block, I0, R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op))); // muls i0,rd,ra,rb
+ if (op & M_RC)
+ {
+ UML_TEST(block, R32(G_RD(op)), ~0); // test rd,~0
+ generate_compute_flags(ppc, block, desc, op & M_RC, 0, FALSE); // <update flags>
+ }
+ return TRUE;
+
+ case 0x0eb: /* MULLWx */
+ case 0x2eb: /* MULLWOx */
+ UML_MULS(block, R32(G_RD(op)), R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op))); // muls rd,rd,ra,rb
+ generate_compute_flags(ppc, block, desc, op & M_RC, ((op & M_OE) ? XER_OV : 0), FALSE);// <update flags>
+ return TRUE;
+
+ case 0x1cb: /* DIVWUx */
+ case 0x3cb: /* DIVWUOx */
+ UML_DIVU(block, R32(G_RD(op)), R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op))); // divu rd,rd,ra,rb
+ generate_compute_flags(ppc, block, desc, op & M_RC, ((op & M_OE) ? XER_OV : 0), FALSE);// <update flags>
+ return TRUE;
+
+ case 0x1eb: /* DIVWx */
+ case 0x3eb: /* DIVWOx */
+ UML_DIVS(block, R32(G_RD(op)), R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op))); // divs rd,rd,ra,rb
+ generate_compute_flags(ppc, block, desc, op & M_RC, ((op & M_OE) ? XER_OV : 0), FALSE);// <update flags>
+ return TRUE;
+
+ case 0x01c: /* ANDx */
+ UML_AND(block, R32(G_RA(op)), R32(G_RS(op)), R32(G_RB(op))); // and ra,rs,rb
+ generate_compute_flags(ppc, block, desc, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x03c: /* ANDCx */
+ UML_XOR(block, I0, R32(G_RB(op)), ~0); // xor i0,rb,~0
+ UML_AND(block, R32(G_RA(op)), R32(G_RS(op)), I0); // and ra,rs,i0
+ generate_compute_flags(ppc, block, desc, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x1dc: /* NANDx */
+ UML_AND(block, I0, R32(G_RS(op)), R32(G_RB(op))); // and i0,rs,rb
+ UML_XOR(block, R32(G_RA(op)), I0, ~0); // xor ra,i0,~0
+ generate_compute_flags(ppc, block, desc, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x1bc: /* ORx */
+ UML_OR(block, R32(G_RA(op)), R32(G_RS(op)), R32(G_RB(op))); // or ra,rs,rb
+ generate_compute_flags(ppc, block, desc, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x19c: /* ORCx */
+ UML_XOR(block, I0, R32(G_RB(op)), ~0); // xor i0,rb,~0
+ UML_OR(block, R32(G_RA(op)), R32(G_RS(op)), I0); // or ra,rs,i0
+ generate_compute_flags(ppc, block, desc, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x07c: /* NORx */
+ UML_OR(block, I0, R32(G_RS(op)), R32(G_RB(op))); // or i0,rs,rb
+ UML_XOR(block, R32(G_RA(op)), I0, ~0); // xor ra,i0,~0
+ generate_compute_flags(ppc, block, desc, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x13c: /* XORx */
+ UML_XOR(block, R32(G_RA(op)), R32(G_RS(op)), R32(G_RB(op))); // xor ra,rs,rb
+ generate_compute_flags(ppc, block, desc, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x11c: /* EQVx */
+ UML_XOR(block, I0, R32(G_RS(op)), R32(G_RB(op))); // xor i0,rs,rb
+ UML_XOR(block, R32(G_RA(op)), I0, ~0); // xor ra,i0,~0
+ generate_compute_flags(ppc, block, desc, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x018: /* SLWx */
+ UML_SHL(block, R32(G_RA(op)), R32(G_RS(op)), R32(G_RB(op))); // shl ra,rs,rb
+ generate_compute_flags(ppc, block, desc, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x218: /* SRWx */
+ UML_MOV(block, I0, R32(G_RS(op))); // mov i0,rs
+ UML_TEST(block, R32(G_RB(op)), 0x20); // test rb,0x20
+ UML_MOVc(block, COND_NZ, I0, 0); // mov i0,0,nz
+ UML_SHR(block, R32(G_RA(op)), I0, R32(G_RB(op))); // shr ra,i0,rb
+ generate_compute_flags(ppc, block, desc, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x318: /* SRAWx */
+ UML_MOV(block, I2, R32(G_RB(op))); // mov i2,rb
+ UML_TEST(block, I2, 0x20); // test i2,0x20
+ UML_MOVc(block, COND_NZ, I2, 31); // mov i2,31,nz
+ if (DISABLE_FLAG_OPTIMIZATIONS || (desc->regreq[3] & REGFLAG_XER_CA))
+ {
+ UML_SHL(block, I1, 0xffffffff, I2); // shl i1,0xffffffff,i2
+ UML_XOR(block, I1, I1, ~0); // xor i1,i1,~0
+ UML_AND(block, I0, R32(G_RS(op)), I1); // and i0,rs,i1
+ UML_SAR(block, I1, R32(G_RS(op)), 31); // sar i1,rs,31
+ UML_TEST(block, I0, I1); // test i0,i1
+ UML_SETc(block, COND_NZ, I0); // set i0,nz
+ UML_ROLINS(block, SPR32(SPR_XER), I0, 29, XER_CA); // rolins [xer],i0,29,XER_CA
+ }
+ UML_SAR(block, R32(G_RA(op)), R32(G_RS(op)), I2); // sar ra,rs,i2
+ generate_compute_flags(ppc, block, desc, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x338: /* SRAWIx */
+ if (DISABLE_FLAG_OPTIMIZATIONS || (desc->regreq[3] & REGFLAG_XER_CA))
+ {
+ UML_AND(block, I0, R32(G_RS(op)), ~(0xffffffff << (G_SH(op) & 31)));// and i0,rs,~(0xffffffff << (sh & 31))
+ UML_SAR(block, I1, R32(G_RS(op)), 31); // sar i1,rs,31
+ UML_TEST(block, I0, I1); // test i0,i1
+ UML_SETc(block, COND_NZ, I0); // set i0,nz
+ UML_ROLINS(block, SPR32(SPR_XER), I0, 29, XER_CA); // rolins [xer],i0,29,XER_CA
+ }
+ UML_SAR(block, R32(G_RA(op)), R32(G_RS(op)), G_SH(op)); // sar ra,rs,sh
+ generate_compute_flags(ppc, block, desc, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x01a: /* CNTLZWx */
+ UML_LZCNT(block, R32(G_RA(op)), R32(G_RS(op))); // lzcnt ra,rs
+ if (op & M_RC)
+ generate_compute_flags(ppc, block, desc, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x3ba: /* EXTSBx */
+ UML_SEXT(block, R32(G_RA(op)), R32(G_RS(op)), SIZE_BYTE); // sext ra,rs,byte
+ if (op & M_RC)
+ generate_compute_flags(ppc, block, desc, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x39a: /* EXTSHx */
+ UML_SEXT(block, R32(G_RA(op)), R32(G_RS(op)), SIZE_WORD); // sext ra,rs,word
+ if (op & M_RC)
+ generate_compute_flags(ppc, block, desc, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x057: /* LBZX */
+ UML_ADD(block, I0, R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, *ppc->impstate->read8[ppc->impstate->mode]); // callh read8
+ UML_AND(block, R32(G_RD(op)), I0, 0xff); // and rd,i0,0xff
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x117: /* LHZX */
+ UML_ADD(block, I0, R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, *ppc->impstate->read16[ppc->impstate->mode]); // callh read16
+ UML_AND(block, R32(G_RD(op)), I0, 0xffff); // and rd,i0,0xffff
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x157: /* LHAX */
+ UML_ADD(block, I0, R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, *ppc->impstate->read16[ppc->impstate->mode]); // callh read16
+ UML_SEXT(block, R32(G_RD(op)), I0, SIZE_WORD); // sext rd,i0,word
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x017: /* LWZX */
+ UML_ADD(block, I0, R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, *ppc->impstate->read32[ppc->impstate->mode]); // callh read32
+ UML_MOV(block, R32(G_RD(op)), I0); // mov rd,i0
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x217: /* LFSX */
+ UML_ADD(block, I0, R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, *ppc->impstate->read32[ppc->impstate->mode]); // callh read32
+ UML_MOV(block, mem(&ppc->impstate->tempdata.w.l), I0); // mov [tempdata],i0
+ UML_FDFRFLT(block, F64(G_RD(op)), mem(&ppc->impstate->tempdata.w.l), SIZE_DWORD); // fdfrflt fd,[tempdata],dword
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x257: /* LFDX */
+ UML_ADD(block, I0, R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, *ppc->impstate->read64[ppc->impstate->mode]); // callh read64
+ UML_DMOV(block, mem(&ppc->impstate->tempdata.d), I0); // dmov [tempdata],i0
+ UML_FDMOV(block, F64(G_RD(op)), mem(&ppc->impstate->tempdata.d)); // fdmov fd,[tempdata]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x316: /* LHBRX */
+ UML_ADD(block, I0, R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, *ppc->impstate->read16[ppc->impstate->mode]); // callh read16
+ UML_BSWAP(block, I0, I0); // bswap i0,i0
+ UML_SHR(block, R32(G_RD(op)), I0, 16); // shr rd,i0,16
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x216: /* LWBRX */
+ UML_ADD(block, I0, R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, *ppc->impstate->read32align[ppc->impstate->mode]); // callh read32align
+ UML_BSWAP(block, R32(G_RD(op)), I0); // bswap rd,i0
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x077: /* LBZUX */
+ UML_ADD(block, I0, R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MOV(block, mem(&ppc->impstate->updateaddr), I0); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDXU(op)); // mapvar dsisr,DSISR_IDXU(op)
+ UML_CALLH(block, *ppc->impstate->read8[ppc->impstate->mode]); // callh read8
+ UML_AND(block, R32(G_RD(op)), I0, 0xff); // and rd,i0,0xff
+ UML_MOV(block, R32(G_RA(op)), mem(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x137: /* LHZUX */
+ UML_ADD(block, I0, R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MOV(block, mem(&ppc->impstate->updateaddr), I0); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDXU(op)); // mapvar dsisr,DSISR_IDXU(op)
+ UML_CALLH(block, *ppc->impstate->read16[ppc->impstate->mode]); // callh read16
+ UML_AND(block, R32(G_RD(op)), I0, 0xffff); // and rd,i0,0xffff
+ UML_MOV(block, R32(G_RA(op)), mem(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x177: /* LHAUX */
+ UML_ADD(block, I0, R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MOV(block, mem(&ppc->impstate->updateaddr), I0); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDXU(op)); // mapvar dsisr,DSISR_IDXU(op)
+ UML_CALLH(block, *ppc->impstate->read16[ppc->impstate->mode]); // callh read16
+ UML_SEXT(block, R32(G_RD(op)), I0, SIZE_WORD); // sext rd,i0,word
+ UML_MOV(block, R32(G_RA(op)), mem(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x037: /* LWZUX */
+ UML_ADD(block, I0, R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MOV(block, mem(&ppc->impstate->updateaddr), I0); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDXU(op)); // mapvar dsisr,DSISR_IDXU(op)
+ UML_CALLH(block, *ppc->impstate->read32[ppc->impstate->mode]); // callh read32
+ UML_MOV(block, R32(G_RD(op)), I0); // mov rd,i0
+ UML_MOV(block, R32(G_RA(op)), mem(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x237: /* LFSUX */
+ UML_ADD(block, I0, R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MOV(block, mem(&ppc->impstate->updateaddr), I0); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, *ppc->impstate->read32[ppc->impstate->mode]); // callh read32
+ UML_MOV(block, mem(&ppc->impstate->tempdata.w.l), I0); // mov [tempdata],i0
+ UML_FDFRFLT(block, F64(G_RD(op)), mem(&ppc->impstate->tempdata.w.l), SIZE_DWORD); // fdfrflt fd,[tempdata],dword
+ UML_MOV(block, R32(G_RA(op)), mem(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x277: /* LFDUX */
+ UML_ADD(block, I0, R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MOV(block, mem(&ppc->impstate->updateaddr), I0); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, *ppc->impstate->read64[ppc->impstate->mode]); // callh read64
+ UML_DMOV(block, mem(&ppc->impstate->tempdata.d), I0); // dmov [tempdata],i0
+ UML_FDMOV(block, F64(G_RD(op)), mem(&ppc->impstate->tempdata.d)); // fdmov fd,[tempdata]
+ UML_MOV(block, R32(G_RA(op)), mem(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x014: /* LWARX */
+ UML_ADD(block, I0, R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, *ppc->impstate->read32align[ppc->impstate->mode]); // callh read32align
+ UML_MOV(block, R32(G_RD(op)), I0); // mov rd,i0
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x255: /* LSWI */
+ UML_MOV(block, mem(&ppc->impstate->updateaddr), R32Z(G_RA(op))); // mov [updateaddr],ra
+ UML_MOV(block, mem(&ppc->impstate->swcount), ((G_NB(op) - 1) & 0x1f) + 1); // mov [swcount],G_NB
+ UML_CALLH(block, *ppc->impstate->lsw[ppc->impstate->mode][G_RD(op)]); // call lsw[rd]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x215: /* LSWX */
+ UML_ADD(block, mem(&ppc->impstate->updateaddr), R32Z(G_RA(op)), R32(G_RB(op))); // add [updateaddr],ra,rb
+ UML_AND(block, mem(&ppc->impstate->swcount), SPR32(SPR_XER), 0x7f); // and [swcount],[xer],0x7f
+ UML_SUB(block, mem(&ppc->icount), mem(&ppc->icount), mem(&ppc->impstate->swcount));// sub icount,icount,[swcount]
+ UML_CALLHc(block, COND_NZ, *ppc->impstate->lsw[ppc->impstate->mode][G_RD(op)]); // call lsw[rd],nz
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x136: /* ECIWX */
+ /* not implemented */
+ return FALSE;
+
+ case 0x0d7: /* STBX */
+ UML_ADD(block, I0, R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_AND(block, I1, R32(G_RS(op)), 0xff); // and i1,rs,0xff
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, *ppc->impstate->write8[ppc->impstate->mode]); // callh write8
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x197: /* STHX */
+ UML_ADD(block, I0, R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_AND(block, I1, R32(G_RS(op)), 0xffff); // and i1,rs
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, *ppc->impstate->write16[ppc->impstate->mode]); // callh write16
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x097: /* STWX */
+ UML_ADD(block, I0, R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MOV(block, I1, R32(G_RS(op))); // mov i1,rs
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, *ppc->impstate->write32[ppc->impstate->mode]); // callh write32
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x297: /* STFSX */
+ UML_ADD(block, I0, R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_FSFRFLT(block, mem(&ppc->impstate->tempdata.w.l), F64(G_RS(op)), SIZE_QWORD); // fsfrflt [tempdata],rs,qword
+ UML_MOV(block, I1, mem(&ppc->impstate->tempdata.w.l)); // mov i1,[tempdata]
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, *ppc->impstate->write32[ppc->impstate->mode]); // callh write32
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x3d7: /* STFIWX */
+ UML_ADD(block, I0, R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_FDMOV(block, mem(&ppc->impstate->tempdata.d), F64(G_RS(op))); // fdmov [tempdata],rs
+ UML_MOV(block, I1, mem(&ppc->impstate->tempdata.w.l)); // mov i1,[tempdata.lo]
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, *ppc->impstate->write32[ppc->impstate->mode]); // callh write32
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x2d7: /* STFDX */
+ UML_ADD(block, I0, R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_FDMOV(block, mem(&ppc->impstate->tempdata.d), F64(G_RS(op))); // fdmov [tempdata],rs
+ UML_DMOV(block, I1, mem(&ppc->impstate->tempdata.d)); // dmov i1,[tempdata]
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, *ppc->impstate->write64[ppc->impstate->mode]); // callh write64
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x396: /* STHBRX */
+ UML_ADD(block, I0, R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_BSWAP(block, I1, R32(G_RS(op))); // bswap i1,rs
+ UML_SHR(block, I1, I1, 16); // shr i1,i1,16
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, *ppc->impstate->write16[ppc->impstate->mode]); // callh write16
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x296: /* STWBRX */
+ UML_ADD(block, I0, R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_BSWAP(block, I1, R32(G_RS(op))); // bswap i1,rs
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, *ppc->impstate->write32[ppc->impstate->mode]); // callh write32
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x0f7: /* STBUX */
+ UML_ADD(block, I0, R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_AND(block, I1, R32(G_RS(op)), 0xff); // and i1,rs,0xff
+ UML_MOV(block, mem(&ppc->impstate->updateaddr), I0); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, *ppc->impstate->write8[ppc->impstate->mode]); // callh write8
+ UML_MOV(block, R32(G_RA(op)), mem(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x1b7: /* STHUX */
+ UML_ADD(block, I0, R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_AND(block, I1, R32(G_RS(op)), 0xffff); // and i1,rs,0xffff
+ UML_MOV(block, mem(&ppc->impstate->updateaddr), I0); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, *ppc->impstate->write16[ppc->impstate->mode]); // callh write16
+ UML_MOV(block, R32(G_RA(op)), mem(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x0b7: /* STWUX */
+ UML_ADD(block, I0, R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MOV(block, I1, R32(G_RS(op))); // mov i1,rs
+ UML_MOV(block, mem(&ppc->impstate->updateaddr), I0); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDXU(op)); // mapvar dsisr,DSISR_IDXU(op)
+ UML_CALLH(block, *ppc->impstate->write32[ppc->impstate->mode]); // callh write32
+ UML_MOV(block, R32(G_RA(op)), mem(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x2b7: /* STFSUX */
+ UML_ADD(block, I0, R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_FSFRFLT(block, mem(&ppc->impstate->tempdata.w.l), F64(G_RS(op)), SIZE_QWORD); // fsfrflt [tempdata],rs,qword
+ UML_MOV(block, I1, mem(&ppc->impstate->tempdata.w.l)); // mov i1,[tempdata]
+ UML_MOV(block, mem(&ppc->impstate->updateaddr), I0); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, *ppc->impstate->write32[ppc->impstate->mode]); // callh write32
+ UML_MOV(block, R32(G_RA(op)), mem(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x2f7: /* STFDUX */
+ UML_ADD(block, I0, R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_FDMOV(block, mem(&ppc->impstate->tempdata.d), F64(G_RS(op))); // fdmov [tempdata],rs
+ UML_DMOV(block, I1, mem(&ppc->impstate->tempdata.d)); // dmov i1,[tempdata]
+ UML_MOV(block, mem(&ppc->impstate->updateaddr), I0); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, *ppc->impstate->write64[ppc->impstate->mode]); // callh write64
+ UML_MOV(block, R32(G_RA(op)), mem(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x096: /* STWCX. */
+ UML_ADD(block, I0, R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MOV(block, I1, R32(G_RS(op))); // mov i1,rs
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, *ppc->impstate->write32align[ppc->impstate->mode]); // callh write32align
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+
+ UML_CMP(block, I0, I0); // cmp i0,i0
+ UML_GETFLGS(block, I0, FLAG_Z | FLAG_C | FLAG_S); // getflgs i0,zcs
+ UML_LOAD(block, I0, ppc->impstate->cmp_cr_table, I0, SIZE_BYTE, SCALE_x1);// load i0,cmp_cr_table,i0,byte
+ UML_OR(block, CR32(G_CRFD(op)), I0, XERSO32); // or [crn],i0,[xerso]
+
+ generate_compute_flags(ppc, block, desc, TRUE, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x2d5: /* STSWI */
+ UML_MOV(block, mem(&ppc->impstate->updateaddr), R32Z(G_RA(op))); // mov [updateaddr],ra
+ UML_MOV(block, mem(&ppc->impstate->swcount), ((G_NB(op) - 1) & 0x1f) + 1); // mov [swcount],G_NB
+ UML_CALLH(block, *ppc->impstate->stsw[ppc->impstate->mode][G_RD(op)]); // call stsw[rd]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x295: /* STSWX */
+ UML_ADD(block, mem(&ppc->impstate->updateaddr), R32Z(G_RA(op)), R32(G_RB(op))); // add [updateaddr],ra,rb
+ UML_AND(block, mem(&ppc->impstate->swcount), SPR32(SPR_XER), 0x7f); // and [swcount],[xer],0x7f
+ UML_SUB(block, mem(&ppc->icount), mem(&ppc->icount), mem(&ppc->impstate->swcount));// sub icount,icount,[swcount]
+ UML_CALLHc(block, COND_NZ, *ppc->impstate->stsw[ppc->impstate->mode][G_RD(op)]); // call stsw[rd]
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x1b6: /* ECOWX */
+ /* not implemented */
+ return FALSE;
+
+ case 0x036: /* DCBST */
+ case 0x056: /* DCBF */
+ case 0x0f6: /* DCBTST */
+ case 0x116: /* DCBT */
+ case 0x3d6: /* ICBI */
+ case 0x256: /* SYNC */
+ case 0x356: /* EIEIO */
+ case 0x1d6: /* DCBI */
+ case 0x236: /* TLBSYNC */
+ /* effective no-ops */
+ return TRUE;
+
+ case 0x3f6: /* DCBZ */
+ UML_ADD(block, I0, R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_AND(block, mem(&ppc->impstate->tempaddr), I0, ~(ppc->cache_line_size - 1));
+ // and [tempaddr],i0,~(cache_line_size - 1)
+ for (item = 0; item < ppc->cache_line_size / 8; item++)
+ {
+ UML_ADD(block, I0, mem(&ppc->impstate->tempaddr), 8 * item); // add i0,[tempaddr],8*item
+ UML_DMOV(block, I1, 0); // dmov i1,0
+ UML_CALLH(block, *ppc->impstate->write64[ppc->impstate->mode]); // callh write64
+ }
+ return TRUE;
+
+ case 0x132: /* TLBIE */
+ UML_MOV(block, mem(&ppc->param0), R32(G_RB(op))); // mov [param0],rb
+ UML_CALLC(block, (c_function)ppccom_execute_tlbie, ppc); // callc ppccom_execute_tlbie,ppc
+ return TRUE;
+
+ case 0x172: /* TLBIA */
+ UML_CALLC(block, (c_function)ppccom_execute_tlbia, ppc); // callc ppccom_execute_tlbia,ppc
+ return TRUE;
+
+ case 0x3d2: /* TLBLD */
+ assert(ppc->cap & PPCCAP_603_MMU);
+ UML_MOV(block, mem(&ppc->param0), R32(G_RB(op))); // mov [param0],rb
+ UML_MOV(block, mem(&ppc->param1), 0); // mov [param1],0
+ UML_CALLC(block, (c_function)ppccom_execute_tlbl, ppc); // callc ppccom_execute_tlbl,ppc
+ return TRUE;
+
+ case 0x3f2: /* TLBLI */
+ assert(ppc->cap & PPCCAP_603_MMU);
+ UML_MOV(block, mem(&ppc->param0), R32(G_RB(op))); // mov [param0],rb
+ UML_MOV(block, mem(&ppc->param1), 1); // mov [param1],1
+ UML_CALLC(block, (c_function)ppccom_execute_tlbl, ppc); // callc ppccom_execute_tlbl,ppc
+ return TRUE;
+
+ case 0x013: /* MFCR */
+ UML_SHL(block, I0, CR32(0), 28); // shl i0,cr(0),28
+ UML_ROLAND(block, I1, CR32(1), 24, 0x0f000000); // roland i1,cr(1),24,0x0f000000
+ UML_OR(block, I0, I0, I1); // or i0,i0,i1
+ UML_ROLAND(block, I1, CR32(2), 20, 0x00f00000); // roland i1,cr(2),20,0x00f00000
+ UML_OR(block, I0, I0, I1); // or i0,i0,i1
+ UML_ROLAND(block, I1, CR32(3), 16, 0x000f0000); // roland i1,cr(3),16,0x000f0000
+ UML_OR(block, I0, I0, I1); // or i0,i0,i1
+ UML_ROLAND(block, I1, CR32(4), 12, 0x0000f000); // roland i1,cr(4),12,0x0000f000
+ UML_OR(block, I0, I0, I1); // or i0,i0,i1
+ UML_ROLAND(block, I1, CR32(5), 8, 0x00000f00); // roland i1,cr(5),8,0x00000f00
+ UML_OR(block, I0, I0, I1); // or i0,i0,i1
+ UML_ROLAND(block, I1, CR32(6), 4, 0x000000f0); // roland i1,cr(6),4,0x000000f0
+ UML_OR(block, I0, I0, I1); // or i0,i0,i1
+ UML_ROLAND(block, I1, CR32(7), 0, 0x0000000f); // roland i1,cr(7),0,0x0000000f
+ UML_OR(block, R32(G_RD(op)), I0, I1); // or rd,i0,i1
+ return TRUE;
+
+ case 0x053: /* MFMSR */
+ UML_MOV(block, R32(G_RD(op)), MSR32); // mov rd,msr
+ return TRUE;
+
+ case 0x153: /* MFSPR */
+ {
+ UINT32 spr = compute_spr(G_SPR(op));
+ if (spr == SPR_LR || spr == SPR_CTR || (spr >= SPROEA_SPRG0 && spr <= SPROEA_SPRG3))
+ UML_MOV(block, R32(G_RD(op)), SPR32(spr)); // mov rd,spr
+ else if (spr == SPR_XER)
+ {
+ UML_SHL(block, I0, XERSO32, 31); // shl i0,[xerso],31
+ UML_OR(block, R32(G_RD(op)), SPR32(spr), I0); // or [rd],[xer],i0
+ }
+ else if (spr == SPROEA_PVR)
+ UML_MOV(block, R32(G_RD(op)), ppc->flavor); // mov rd,flavor
+ else
+ {
+ generate_update_cycles(ppc, block, compiler, desc->pc, TRUE); // <update cycles>
+ UML_MOV(block, mem(&ppc->param0), spr); // mov [param0],spr
+ UML_CALLC(block, (c_function)ppccom_execute_mfspr, ppc); // callc ppccom_execute_mfspr,ppc
+ UML_MOV(block, R32(G_RD(op)), mem(&ppc->param1)); // mov rd,[param1]
+ }
+ return TRUE;
+ }
+
+ case 0x253: /* MFSR */
+ UML_MOV(block, R32(G_RD(op)), SR32(G_SR(op))); // mov rd,sr
+ return TRUE;
+
+ case 0x293: /* MFSRIN */
+ UML_SHR(block, I0, R32(G_RB(op)), 28); // shr i0,G_RB,28
+ UML_LOAD(block, R32(G_RD(op)), &ppc->sr[0], I0, SIZE_DWORD, SCALE_x4); // load rd,sr,i0,dword
+ return TRUE;
+
+ case 0x173: /* MFTB */
+ {
+ UINT32 tbr = compute_spr(G_SPR(op));
+ if (tbr != SPRVEA_TBL_R && tbr != SPRVEA_TBU_R)
+ return FALSE;
+ generate_update_cycles(ppc, block, compiler, desc->pc, TRUE); // <update cycles>
+ UML_MOV(block, mem(&ppc->param0), tbr); // mov [param0],tbr
+ UML_CALLC(block, (c_function)ppccom_execute_mftb, ppc); // callc ppccom_execute_mftb,ppc
+ UML_MOV(block, R32(G_RD(op)), mem(&ppc->param1)); // mov rd,[param1]
+ return TRUE;
+ }
+
+ case 0x090: /* MTCRF */
+ UML_MOV(block, I0, R32(G_RS(op))); // mov i0,rs
+ if (G_CRM(op) & 0x80) UML_ROLAND(block, CR32(0), I0, 4, 0xf); // roland cr(0),i0,4,0x0f
+ if (G_CRM(op) & 0x40) UML_ROLAND(block, CR32(1), I0, 8, 0xf); // roland cr(1),i0,8,0x0f
+ if (G_CRM(op) & 0x20) UML_ROLAND(block, CR32(2), I0, 12, 0xf); // roland cr(2),i0,12,0x0f
+ if (G_CRM(op) & 0x10) UML_ROLAND(block, CR32(3), I0, 16, 0xf); // roland cr(3),i0,16,0x0f
+ if (G_CRM(op) & 0x08) UML_ROLAND(block, CR32(4), I0, 20, 0xf); // roland cr(4),i0,20,0x0f
+ if (G_CRM(op) & 0x04) UML_ROLAND(block, CR32(5), I0, 24, 0xf); // roland cr(5),i0,24,0x0f
+ if (G_CRM(op) & 0x02) UML_ROLAND(block, CR32(6), I0, 28, 0xf); // roland cr(6),i0,28,0x0f
+ if (G_CRM(op) & 0x01) UML_ROLAND(block, CR32(7), I0, 0, 0xf); // roland cr(7),i0,0,0x0f
+ return TRUE;
+
+ case 0x092: /* MTMSR */
+ if (ppc->cap & PPCCAP_603_MMU)
+ UML_XOR(block, I0, MSR32, R32(G_RS(op))); // xor i0,msr32,rs
+ UML_MOV(block, MSR32, R32(G_RS(op))); // mov msr,rs
+ if (ppc->cap & PPCCAP_603_MMU)
+ {
+ UML_TEST(block, I0, MSR603_TGPR); // test i0,tgpr
+ UML_CALLHc(block, COND_NZ, *ppc->impstate->swap_tgpr); // callh swap_tgpr,nz
+ }
+ generate_update_mode(ppc, block); // <update mode>
+ return TRUE;
+
+ case 0x1d3: /* MTSPR */
+ {
+ UINT32 spr = compute_spr(G_SPR(op));
+ if (spr == SPR_LR || spr == SPR_CTR || (spr >= SPROEA_SPRG0 && spr <= SPROEA_SPRG3))
+ UML_MOV(block, SPR32(spr), R32(G_RS(op))); // mov spr,rs
+ else if (spr == SPR_XER)
+ {
+ UML_AND(block, SPR32(spr), R32(G_RS(op)), ~XER_SO); // and spr,rs,~XER_SO
+ UML_SHR(block, XERSO32, R32(G_RS(op)), 31); // shr [xerso],rs,31
+ }
+ else if (spr == SPROEA_PVR)
+ ; // read only
+ else
+ {
+ generate_update_cycles(ppc, block, compiler, desc->pc, TRUE); // <update cycles>
+ UML_MOV(block, mem(&ppc->param0), spr); // mov [param0],spr
+ UML_MOV(block, mem(&ppc->param1), R32(G_RS(op))); // mov [param1],rs
+ UML_CALLC(block, (c_function)ppccom_execute_mtspr, ppc); // callc ppccom_execute_mtspr,ppc
+ compiler->checkints = TRUE;
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ }
+ return TRUE;
+ }
+
+ case 0x0d2: /* MTSR */
+ UML_MOV(block, SR32(G_SR(op)), R32(G_RS(op))); // mov sr[G_SR],rs
+ UML_CALLC(block, (c_function)ppccom_tlb_flush, ppc); // callc ppccom_tlb_flush,ppc
+ return TRUE;
+
+ case 0x0f2: /* MTSRIN */
+ UML_SHR(block, I0, R32(G_RB(op)), 28); // shr i0,G_RB,28
+ UML_STORE(block, &ppc->sr[0], I0, R32(G_RS(op)), SIZE_DWORD, SCALE_x4); // store sr,i0,rs,dword
+ UML_CALLC(block, (c_function)ppccom_tlb_flush, ppc); // callc ppccom_tlb_flush,ppc
+ return TRUE;
+
+ case 0x200: /* MCRXR */
+ UML_ROLAND(block, I0, SPR32(SPR_XER), 28, 0x0f); // roland i0,[xer],28,0x0f
+ UML_SHL(block, I1, XERSO32, 3); // shl i1,[xerso],3
+ UML_OR(block, CR32(G_CRFD(op)), I0, I1); // or [crd],i0,i1
+ UML_AND(block, SPR32(SPR_XER), SPR32(SPR_XER), ~0xf0000000); // and [xer],[xer],~0xf0000000
+ UML_MOV(block, XERSO32, 0); // mov [xerso],0
+ return TRUE;
+
+ case 0x106: /* ICBT */
+ case 0x1c6: /* DCCCI */
+ case 0x3c6: /* ICCCI */
+ assert(ppc->cap & PPCCAP_4XX);
+ /* effective no-nop */
+ return TRUE;
+
+ case 0x1e6: /* DCREAD */
+ case 0x3e6: /* ICREAD */
+ assert(ppc->cap & PPCCAP_4XX);
+ UML_MOV(block, R32(G_RT(op)), 0); // mov rt,0
+ return TRUE;
+
+ case 0x143: /* MFDCR */
+ {
+ UINT32 spr = compute_spr(G_SPR(op));
+ assert(ppc->cap & PPCCAP_4XX);
+ generate_update_cycles(ppc, block, compiler, desc->pc, TRUE); // <update cycles>
+ UML_MOV(block, mem(&ppc->param0), spr); // mov [param0],spr
+ UML_CALLC(block, (c_function)ppccom_execute_mfdcr, ppc); // callc ppccom_execute_mfdcr,ppc
+ UML_MOV(block, R32(G_RD(op)), mem(&ppc->param1)); // mov rd,[param1]
+ return TRUE;
+ }
+
+ case 0x1c3: /* MTDCR */
+ {
+ UINT32 spr = compute_spr(G_SPR(op));
+ assert(ppc->cap & PPCCAP_4XX);
+ generate_update_cycles(ppc, block, compiler, desc->pc, TRUE); // <update cycles>
+ UML_MOV(block, mem(&ppc->param0), spr); // mov [param0],spr
+ UML_MOV(block, mem(&ppc->param1), R32(G_RS(op))); // mov [param1],rs
+ UML_CALLC(block, (c_function)ppccom_execute_mtdcr, ppc); // callc ppccom_execute_mtdcr,ppc
+ compiler->checkints = TRUE;
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+ }
+
+ case 0x083: /* WRTEE */
+ assert(ppc->cap & PPCCAP_4XX);
+ UML_ROLINS(block, MSR32, R32(G_RS(op)), 0, MSR_EE); // rolins msr,rs,0,MSR_EE
+ compiler->checkints = TRUE;
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x0a3: /* WRTEEI */
+ assert(ppc->cap & PPCCAP_4XX);
+ if (op & MSR_EE)
+ {
+ UML_OR(block, MSR32, MSR32, MSR_EE); // or msr,msr,MSR_EE
+ compiler->checkints = TRUE;
+ generate_update_cycles(ppc, block, compiler, desc->pc + 4, TRUE); // <update cycles>
+ }
+ else
+ UML_AND(block, MSR32, MSR32, ~MSR_EE); // and msr,msr,~MSR_EE
+ return TRUE;
+
+ case 0x254: /* ESA */
+ case 0x274: /* DSA */
+ /* no-op for now */
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/*-------------------------------------------------
+ generate_instruction_3b - compile opcodes in
+ the 0x3b group
+-------------------------------------------------*/
+
+static int generate_instruction_3b(powerpc_state *ppc, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 op = desc->opptr.l[0];
+ UINT32 opswitch = (op >> 1) & 0x1f;
+
+ switch (opswitch)
+ {
+ case 0x15: /* FADDSx */
+ if (!(ppc->impstate->drcoptions & PPCDRC_ACCURATE_SINGLES))
+ return generate_instruction_3f(ppc, block, compiler, desc);
+ UML_FDADD(block, F0, F64(G_RA(op)), F64(G_RB(op))); // fdadd f0,ra,rb
+ UML_FDRNDS(block, F64(G_RD(op)), F0); // fdrnds rd,f0
+ generate_fp_flags(ppc, block, desc, TRUE);
+ return TRUE;
+
+ case 0x14: /* FSUBSx */
+ if (!(ppc->impstate->drcoptions & PPCDRC_ACCURATE_SINGLES))
+ return generate_instruction_3f(ppc, block, compiler, desc);
+ UML_FDSUB(block, F0, F64(G_RA(op)), F64(G_RB(op))); // fdsub f0,ra,rb
+ UML_FDRNDS(block, F64(G_RD(op)), F0); // fdrnds rd,f0
+ generate_fp_flags(ppc, block, desc, TRUE);
+ return TRUE;
+
+ case 0x19: /* FMULSx */
+ if (!(ppc->impstate->drcoptions & PPCDRC_ACCURATE_SINGLES))
+ return generate_instruction_3f(ppc, block, compiler, desc);
+ UML_FDMUL(block, F0, F64(G_RA(op)), F64(G_REGC(op))); // fdmul f0,ra,rc
+ UML_FDRNDS(block, F64(G_RD(op)), F0); // fdrnds rd,f0
+ generate_fp_flags(ppc, block, desc, TRUE);
+ return TRUE;
+
+ case 0x12: /* FDIVSx */
+ if (!(ppc->impstate->drcoptions & PPCDRC_ACCURATE_SINGLES))
+ return generate_instruction_3f(ppc, block, compiler, desc);
+ UML_FDDIV(block, F0, F64(G_RA(op)), F64(G_RB(op))); // fddiv f0,ra,rb
+ UML_FDRNDS(block, F64(G_RD(op)), F0); // fdrnds rd,f0
+ generate_fp_flags(ppc, block, desc, TRUE);
+ return TRUE;
+
+ case 0x16: /* FSQRTSx */
+ if (!(ppc->impstate->drcoptions & PPCDRC_ACCURATE_SINGLES))
+ return generate_instruction_3f(ppc, block, compiler, desc);
+ UML_FDSQRT(block, F0, F64(G_RB(op))); // fdsqrt f0,rb
+ UML_FDRNDS(block, F64(G_RD(op)), F0); // fdrnds rd,f0
+ generate_fp_flags(ppc, block, desc, TRUE);
+ return TRUE;
+
+ case 0x18: /* FRESx */
+ UML_FSFRFLT(block, F0, F64(G_RB(op)), SIZE_QWORD); // fsfrlt f0,rb,qword
+ UML_FSRECIP(block, F0, F0); // fsrecip f0,f0
+ UML_FDFRFLT(block, F64(G_RD(op)), F0, SIZE_DWORD); // fdfrflt rd,f0,dword
+ generate_fp_flags(ppc, block, desc, TRUE);
+ return TRUE;
+
+ case 0x1d: /* FMADDSx */
+ if (!(ppc->impstate->drcoptions & PPCDRC_ACCURATE_SINGLES))
+ return generate_instruction_3f(ppc, block, compiler, desc);
+ UML_FDMUL(block, F0, F64(G_RA(op)), F64(G_REGC(op))); // fdmul f0,ra,rc
+ UML_FDADD(block, F0, F0, F64(G_RB(op))); // fdadd f0,f0,rb
+ UML_FDRNDS(block, F64(G_RD(op)), F0); // fdrnds rd,f0
+ generate_fp_flags(ppc, block, desc, TRUE);
+ return TRUE;
+
+ case 0x1c: /* FMSUBSx */
+ if (!(ppc->impstate->drcoptions & PPCDRC_ACCURATE_SINGLES))
+ return generate_instruction_3f(ppc, block, compiler, desc);
+ UML_FDMUL(block, F0, F64(G_RA(op)), F64(G_REGC(op))); // fdmul f0,ra,rc
+ UML_FDSUB(block, F0, F0, F64(G_RB(op))); // fdsub f0,f0,rb
+ UML_FDRNDS(block, F64(G_RD(op)), F0); // fdrnds rd,f0
+ generate_fp_flags(ppc, block, desc, TRUE);
+ return TRUE;
+
+ case 0x1f: /* FNMADDSx */
+ if (!(ppc->impstate->drcoptions & PPCDRC_ACCURATE_SINGLES))
+ return generate_instruction_3f(ppc, block, compiler, desc);
+ UML_FDMUL(block, F0, F64(G_RA(op)), F64(G_REGC(op))); // fdmul f0,ra,rc
+ UML_FDADD(block, F0, F0, F64(G_RB(op))); // fdadd f0,f0,rb
+ UML_FDNEG(block, F0, F0); // fdneg f0,f0
+ UML_FDRNDS(block, F64(G_RD(op)), F0); // fdrnds rd,f0
+ generate_fp_flags(ppc, block, desc, TRUE);
+ return TRUE;
+
+ case 0x1e: /* FNMSUBSx */
+ if (!(ppc->impstate->drcoptions & PPCDRC_ACCURATE_SINGLES))
+ return generate_instruction_3f(ppc, block, compiler, desc);
+ UML_FDMUL(block, F0, F64(G_RA(op)), F64(G_REGC(op))); // fdmul f0,ra,rc
+ UML_FDSUB(block, F0, F64(G_RB(op)), F0); // fdsub f0,rb,f0
+ UML_FDRNDS(block, F64(G_RD(op)), F0); // fdrnds rd,f0
+ generate_fp_flags(ppc, block, desc, TRUE);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+/*-------------------------------------------------
+ generate_instruction_3f - compile opcodes in
+ the 0x3f group
+-------------------------------------------------*/
+
+static int generate_instruction_3f(powerpc_state *ppc, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 op = desc->opptr.l[0];
+ UINT32 opswitch = (op >> 1) & 0x3ff;
+
+ if (opswitch & 0x10)
+ {
+ opswitch &= 0x1f;
+ switch (opswitch)
+ {
+ case 0x15: /* FADDx */
+ UML_FDADD(block, F64(G_RD(op)), F64(G_RA(op)), F64(G_RB(op))); // fdadd rd,ra,rb
+ generate_fp_flags(ppc, block, desc, TRUE);
+ return TRUE;
+
+ case 0x14: /* FSUBx */
+ UML_FDSUB(block, F64(G_RD(op)), F64(G_RA(op)), F64(G_RB(op))); // fdsub rd,ra,rb
+ generate_fp_flags(ppc, block, desc, TRUE);
+ return TRUE;
+
+ case 0x19: /* FMULx */
+ UML_FDMUL(block, F64(G_RD(op)), F64(G_RA(op)), F64(G_REGC(op))); // fdmul rd,ra,rc
+ generate_fp_flags(ppc, block, desc, TRUE);
+ return TRUE;
+
+ case 0x12: /* FDIVx */
+ UML_FDDIV(block, F64(G_RD(op)), F64(G_RA(op)), F64(G_RB(op))); // fddiv rd,ra,rb
+ generate_fp_flags(ppc, block, desc, TRUE);
+ return TRUE;
+
+ case 0x16: /* FSQRTx */
+ UML_FDSQRT(block, F64(G_RD(op)), F64(G_RB(op))); // fdsqrt rd,rb
+ generate_fp_flags(ppc, block, desc, TRUE);
+ return TRUE;
+
+ case 0x1a: /* FRSQRTEx */
+ UML_FDRSQRT(block, F64(G_RD(op)), F64(G_RB(op))); // fdrsqrt rd,rb
+ generate_fp_flags(ppc, block, desc, TRUE);
+ return TRUE;
+
+ case 0x17: /* FSELx */
+ UML_FDCMP(block, F64(G_RA(op)), mem(&ppc->impstate->fp0)); // fdcmp f0,ra,[fp0]
+ UML_FDMOVc(block, COND_AE, F64(G_RD(op)), F64(G_REGC(op))); // fdmov rd,rc,AE
+ UML_FDMOVc(block, COND_B, F64(G_RD(op)), F64(G_RB(op))); // fdmov rd,rb,B
+ return TRUE;
+
+ case 0x1d: /* FMADDx */
+ UML_FDMUL(block, F0, F64(G_RA(op)), F64(G_REGC(op))); // fdmul f0,ra,rc
+ UML_FDADD(block, F64(G_RD(op)), F0, F64(G_RB(op))); // fdadd rd,f0,rb
+ generate_fp_flags(ppc, block, desc, TRUE);
+ return TRUE;
+
+ case 0x1f: /* FNMADDx */
+ UML_FDMUL(block, F0, F64(G_RA(op)), F64(G_REGC(op))); // fdmul f0,ra,rc
+ UML_FDADD(block, F0, F0, F64(G_RB(op))); // fdadd f0,f0,rb
+ UML_FDNEG(block, F64(G_RD(op)), F0); // fdneg rd,f0
+ generate_fp_flags(ppc, block, desc, TRUE);
+ return TRUE;
+
+ case 0x1c: /* FMSUBx */
+ UML_FDMUL(block, F0, F64(G_RA(op)), F64(G_REGC(op))); // fdmul f0,ra,rc
+ UML_FDSUB(block, F64(G_RD(op)), F0, F64(G_RB(op))); // fdsub rd,f0,rb
+ generate_fp_flags(ppc, block, desc, TRUE);
+ return TRUE;
+
+ case 0x1e: /* FNMSUBx */
+ UML_FDMUL(block, F0, F64(G_RA(op)), F64(G_REGC(op))); // fdmul f0,ra,rc
+ UML_FDSUB(block, F64(G_RD(op)), F64(G_RB(op)), F0); // fdsub rd,rb,f0
+ generate_fp_flags(ppc, block, desc, TRUE);
+ return TRUE;
+ }
+ }
+ else
+ {
+ switch (opswitch)
+ {
+ case 0x32e: /* FCTIDx - 64-bit only */
+ case 0x32f: /* FCTIDZx - 64-bit only */
+ case 0x34e: /* FCFIDx - 64-bit only */
+ return FALSE;
+
+ case 0x000: /* FCMPU */
+ case 0x020: /* FCMPO */
+ UML_FDCMP(block, F64(G_RA(op)), F64(G_RB(op))); // fdcmp ra,rb
+ UML_GETFLGS(block, I0, FLAG_C | FLAG_Z | FLAG_U); // getflgs i0,czu
+ UML_LOAD(block, I0, ppc->impstate->fcmp_cr_table, I0, SIZE_BYTE, SCALE_x1);// load i0,fcmp_cr_table,i0,byte
+ UML_OR(block, CR32(G_CRFD(op)), I0, XERSO32); // or [crn],i0,[xerso]
+ return TRUE;
+
+ case 0x00c: /* FRSPx */
+ UML_FDRNDS(block, F64(G_RD(op)), F64(G_RB(op))); // fdrnds rd,rb
+ generate_fp_flags(ppc, block, desc, TRUE);
+ return TRUE;
+
+ case 0x00e: /* FCTIWx */
+ UML_FDTOINT(block, I0, F64(G_RB(op)), SIZE_DWORD, ROUND_DEFAULT); // fdtoint i0,rb,dword,default
+ UML_DAND(block, mem(&ppc->impstate->tempdata.w.l), I0, 0xffffffff);// dand i0,i0,0xffffffff
+ UML_FDMOV(block, F64(G_RD(op)), mem(&ppc->impstate->tempdata.w.l)); // fdmovr rd,i0
+ return TRUE;
+
+ case 0x00f: /* FCTIWZx */
+ UML_FDTOINT(block, I0, F64(G_RB(op)), SIZE_DWORD, ROUND_TRUNC); // fdtoint i0,rb,dword,default
+ UML_DAND(block, mem(&ppc->impstate->tempdata.w.l), I0, 0xffffffff);// dand i0,i0,0xffffffff
+ UML_FDMOV(block, F64(G_RD(op)), mem(&ppc->impstate->tempdata.w.l)); // fdmovr rd,i0
+ return TRUE;
+
+ case 0x028: /* FNEGx */
+ UML_FDNEG(block, F64(G_RD(op)), F64(G_RB(op))); // fdneg rd,rb
+ return TRUE;
+
+ case 0x048: /* FMRx */
+ UML_FDMOV(block, F64(G_RD(op)), F64(G_RB(op))); // fdmov rd,rb
+ return TRUE;
+
+ case 0x088: /* FNABSx */
+ UML_FDABS(block, F0, F64(G_RB(op))); // fdabs f0,rb
+ UML_FDNEG(block, F64(G_RD(op)), F0); // fdneg rd,f0
+ return TRUE;
+
+ case 0x108: /* FABSx */
+ UML_FDABS(block, F64(G_RD(op)), F64(G_RB(op))); // fdabs rd,rb
+ return TRUE;
+
+ case 0x046: /* MTFSB0x */
+ UML_AND(block, FPSCR32, FPSCR32, ~(0x80000000 >> G_CRBD(op))); // and fpscr32,fpscr32,~(0x80000000 >> G_CRBD)
+ return TRUE;
+
+ case 0x026: /* MTFSB1x */
+ UML_OR(block, FPSCR32, FPSCR32, 0x80000000 >> G_CRBD(op)); // or fpscr32,fpscr32,(0x80000000 >> G_CRBD)
+ return TRUE;
+
+ case 0x040: /* MCRFS */
+ UML_ROLAND(block, CR32(G_CRFD(op)), FPSCR32, ((G_CRFS(op) - 7) & 7) * 4, 0x0f);
+ // roland [crd],[fpscr],shift,0x0f
+ UML_AND(block, FPSCR32, FPSCR32, ~CRMASK(G_CRFS(op))); // and fpscr,fpscr,~crmask[crfs]
+ return TRUE;
+
+ case 0x247: /* MFFSx */
+ UML_MOV(block, mem(&ppc->impstate->tempdata.w.l), FPSCR32); // mov [tempdata],fpscr
+ UML_FSMOV(block, F64(G_RD(op)), mem(&ppc->impstate->tempdata.d)); // fsmov rd,fpscr
+ return TRUE;
+
+ case 0x2c7: /* MTFSFx */
+ UML_FDMOV(block, mem(&ppc->impstate->tempdata.d), F64(G_RB(op))); // fdmov [tempdata],fb
+ UML_ROLINS(block, FPSCR32, mem(&ppc->impstate->tempdata.w.l), 0, compute_crf_mask(G_FM(op)));
+ // rolins fpscr,rb,0,crf_mask
+ return TRUE;
+
+ case 0x086: /* MTFSFIx */
+ UML_ROLINS(block, FPSCR32, G_IMM(op), 28 - 4 * G_CRFD(op), CRMASK(G_CRFD(op)));
+ // rolins fpscr,rb,0,crf_mask
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+
+/***************************************************************************
+ CODE LOGGING HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ log_add_disasm_comment - add a comment
+ including disassembly of a PowerPC instruction
+-------------------------------------------------*/
+
+static void log_add_disasm_comment(drcuml_block *block, UINT32 pc, UINT32 op)
+{
+ char buffer[100];
+ if (LOG_UML)
+ {
+ ppc_dasm_one(buffer, pc, op);
+ block->append_comment("%08X: %s", pc, buffer); // comment
+ }
+}
+
+
+/*-------------------------------------------------
+ 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)
+{
+ static const char *const crtext[4] = { "lt", "gt", "eq", "so" };
+ int count = 0;
+ int regnum;
+ int crnum;
+
+ /* skip if nothing */
+ if (reglist[0] == 0 && reglist[1] == 0 && reglist[2] == 0 && reglist[3] == 0)
+ return;
+
+ drcuml->log_printf("[%s:", string);
+
+ for (regnum = 0; 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_FR(regnum))
+ {
+ drcuml->log_printf("%sfr%d", (count++ == 0) ? "" : ",", regnum);
+ if (regnostarlist != NULL && !(regnostarlist[1] & REGFLAG_FR(regnum)))
+ drcuml->log_printf("*");
+ }
+
+ for (regnum = 0; regnum < 8; regnum++)
+ if (reglist[2] & REGFLAG_CR(regnum))
+ {
+ if ((reglist[2] & REGFLAG_CR(regnum)) == REGFLAG_CR(regnum) && (regnostarlist == NULL || (regnostarlist[2] & REGFLAG_CR(regnum)) == REGFLAG_CR(regnum)))
+ {
+ drcuml->log_printf("%scr%d", (count++ == 0) ? "" : ",", regnum);
+ if (regnostarlist != NULL && !(regnostarlist[2] & REGFLAG_CR(regnum)))
+ drcuml->log_printf("*");
+ }
+ else
+ {
+ for (crnum = 0; crnum < 4; crnum++)
+ if (reglist[2] & REGFLAG_CR_BIT(regnum * 4 + crnum))
+ {
+ drcuml->log_printf("%scr%d[%s]", (count++ == 0) ? "" : ",", regnum, crtext[crnum]);
+ if (regnostarlist != NULL && !(regnostarlist[2] & REGFLAG_CR_BIT(regnum * 4 + crnum)))
+ drcuml->log_printf("*");
+ }
+ }
+ }
+
+ if (reglist[3] & REGFLAG_XER_CA)
+ {
+ drcuml->log_printf("%sxer_ca", (count++ == 0) ? "" : ",");
+ if (regnostarlist != NULL && !(regnostarlist[3] & REGFLAG_XER_CA))
+ drcuml->log_printf("*");
+ }
+ if (reglist[3] & REGFLAG_XER_OV)
+ {
+ drcuml->log_printf("%sxer_ov", (count++ == 0) ? "" : ",");
+ if (regnostarlist != NULL && !(regnostarlist[3] & REGFLAG_XER_OV))
+ drcuml->log_printf("*");
+ }
+ if (reglist[3] & REGFLAG_XER_SO)
+ {
+ drcuml->log_printf("%sxer_so", (count++ == 0) ? "" : ",");
+ if (regnostarlist != NULL && !(regnostarlist[3] & REGFLAG_XER_SO))
+ drcuml->log_printf("*");
+ }
+ if (reglist[3] & REGFLAG_XER_COUNT)
+ {
+ drcuml->log_printf("%sxer_count", (count++ == 0) ? "" : ",");
+ if (regnostarlist != NULL && !(regnostarlist[3] & REGFLAG_XER_COUNT))
+ drcuml->log_printf("*");
+ }
+ if (reglist[3] & REGFLAG_CTR)
+ {
+ drcuml->log_printf("%sctr", (count++ == 0) ? "" : ",");
+ if (regnostarlist != NULL && !(regnostarlist[3] & REGFLAG_CTR))
+ drcuml->log_printf("*");
+ }
+ if (reglist[3] & REGFLAG_LR)
+ {
+ drcuml->log_printf("%slr", (count++ == 0) ? "" : ",");
+ if (regnostarlist != NULL && !(regnostarlist[3] & REGFLAG_LR))
+ drcuml->log_printf("*");
+ }
+
+ for (regnum = 0; regnum < 8; regnum++)
+ if (reglist[3] & REGFLAG_FPSCR(regnum))
+ {
+ drcuml->log_printf("%sfpscr%d", (count++ == 0) ? "" : ",", regnum);
+ if (regnostarlist != NULL && !(regnostarlist[3] & REGFLAG_FPSCR(regnum)))
+ 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
+ ppc_dasm_one(buffer, desclist->pc, desclist->opptr.l[0]);
+ }
+ else
+ strcpy(buffer, "???");
+
+ 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");
+ }
+}
+
+
+
+/***************************************************************************
+ PPC 4XX VARIANTS
+***************************************************************************/
+
+/*-------------------------------------------------
+ ppcdrc4xx_get_info - PowerPC 4XX-specific
+ information getter
+-------------------------------------------------*/
+
+static CPU_GET_INFO( ppcdrc4xx )
+{
+ powerpc_state *ppc = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+ CPU_GET_INFO_CALL(ppcdrc);
+ ppc4xx_get_info(ppc, state, info);
+}
+
+
+/*-------------------------------------------------
+ ppcdrc4xx_set_info - PowerPC 4XX-specific
+ information setter
+-------------------------------------------------*/
+
+static CPU_SET_INFO( ppcdrc4xx )
+{
+ powerpc_state *ppc = get_safe_token(device);
+ CPU_SET_INFO_CALL(ppcdrc);
+ ppc4xx_set_info(ppc, state, info);
+}
+
+
+/*-------------------------------------------------
+ ppc403ga_init - PowerPC 403GA-specific
+ initialization
+-------------------------------------------------*/
+
+static CPU_INIT( ppc403ga )
+{
+ ppcdrc_init(PPC_MODEL_403GA, PPCCAP_4XX, 1, device, irqcallback);
+}
+
+
+/*-------------------------------------------------
+ ppc403ga_get_info - PowerPC 403GA-specific
+ information getter
+-------------------------------------------------*/
+
+CPU_GET_INFO( ppc403ga )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(ppc403ga); break;
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(ppcdrc4xx); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PowerPC 403GA"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(ppcdrc4xx); break;
+ }
+}
+
+
+/*-------------------------------------------------
+ ppc403gcx_init - PowerPC 403GCX-specific
+ initialization
+-------------------------------------------------*/
+
+static CPU_INIT( ppc403gcx )
+{
+ ppcdrc_init(PPC_MODEL_403GCX, PPCCAP_4XX, 1, device, irqcallback);
+}
+
+
+/*-------------------------------------------------
+ ppc403gcx_get_info - PowerPC 403GCX-specific
+ information getter
+-------------------------------------------------*/
+
+CPU_GET_INFO( ppc403gcx )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(ppc403gcx); break;
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(ppcdrc4xx); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PowerPC 403GCX"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(ppcdrc4xx); break;
+ }
+}
+
+
+
+/***************************************************************************
+ PPC 6XX VARIANTS
+***************************************************************************/
+
+/*-------------------------------------------------
+ ppc601_init - PowerPC 601-specific
+ initialization
+-------------------------------------------------*/
+
+static CPU_INIT( ppc601 )
+{
+ ppcdrc_init(PPC_MODEL_601, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED | PPCCAP_MFIOC | PPCCAP_601BAT, 0/* no TB */, device, irqcallback);
+}
+
+
+/*-------------------------------------------------
+ ppc601_get_info - PowerPC 601-specific
+ information getter
+-------------------------------------------------*/
+
+CPU_GET_INFO( ppc601 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(ppc601); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PowerPC 601"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(ppcdrc); break;
+ }
+}
+
+
+/*-------------------------------------------------
+ ppc602_init - PowerPC 602-specific
+ initialization
+-------------------------------------------------*/
+
+static CPU_INIT( ppc602 )
+{
+ ppcdrc_init(PPC_MODEL_602, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED | PPCCAP_603_MMU, 4, device, irqcallback);
+}
+
+
+/*-------------------------------------------------
+ ppc602_get_info - PowerPC 602-specific
+ information getter
+-------------------------------------------------*/
+
+CPU_GET_INFO( ppc602 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(ppc602); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PowerPC 602"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(ppcdrc); break;
+ }
+}
+
+
+/*-------------------------------------------------
+ ppc603_init - PowerPC 603-specific
+ initialization
+-------------------------------------------------*/
+
+static CPU_INIT( ppc603 )
+{
+ ppcdrc_init(PPC_MODEL_603, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED | PPCCAP_603_MMU, 4, device, irqcallback);
+}
+
+
+/*-------------------------------------------------
+ ppc603_get_info - PowerPC 603-specific
+ information getter
+-------------------------------------------------*/
+
+CPU_GET_INFO( ppc603 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(ppc603); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PowerPC 603"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(ppcdrc); break;
+ }
+}
+
+
+/*-------------------------------------------------
+ ppc603e_init - PowerPC 603e-specific
+ initialization
+-------------------------------------------------*/
+
+static CPU_INIT( ppc603e )
+{
+ ppcdrc_init(PPC_MODEL_603E, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED | PPCCAP_603_MMU, 4, device, irqcallback);
+}
+
+
+/*-------------------------------------------------
+ ppc603e_get_info - PowerPC 603e-specific
+ information getter
+-------------------------------------------------*/
+
+CPU_GET_INFO( ppc603e )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(ppc603e); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PowerPC 603e"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(ppcdrc); break;
+ }
+}
+
+
+/*-------------------------------------------------
+ ppc603r_init - PowerPC 603r-specific
+ initialization
+-------------------------------------------------*/
+
+static CPU_INIT( ppc603r )
+{
+ ppcdrc_init(PPC_MODEL_603R, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED | PPCCAP_603_MMU, 4, device, irqcallback);
+}
+
+
+/*-------------------------------------------------
+ ppc603r_get_info - PowerPC 603r-specific
+ information getter
+-------------------------------------------------*/
+
+CPU_GET_INFO( ppc603r )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(ppc603r); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PowerPC 603R"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(ppcdrc); break;
+ }
+}
+
+
+/*-------------------------------------------------
+ ppc604_init - PowerPC 604-specific
+ initialization
+-------------------------------------------------*/
+
+static CPU_INIT( ppc604 )
+{
+ ppcdrc_init(PPC_MODEL_604, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED, 4, device, irqcallback);
+}
+
+
+/*-------------------------------------------------
+ ppc604_get_info - PowerPC 604-specific
+ information getter
+-------------------------------------------------*/
+
+CPU_GET_INFO( ppc604 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(ppc604); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PowerPC 604"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(ppcdrc); break;
+ }
+}
+
+
+
+/***************************************************************************
+ MPC VARIANTS
+***************************************************************************/
+
+/*-------------------------------------------------
+ mpc8240_init - PowerPC MPC8240-specific
+ initialization
+-------------------------------------------------*/
+
+static CPU_INIT( mpc8240 )
+{
+ ppcdrc_init(PPC_MODEL_MPC8240, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED, 4/* unknown */, device, irqcallback);
+}
+
+
+/*-------------------------------------------------
+ mpc8240_get_info - PowerPC MPC8240-specific
+ information getter
+-------------------------------------------------*/
+
+CPU_GET_INFO( mpc8240 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(mpc8240); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PowerPC MPC8240"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(ppcdrc); 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/ppcfe.c b/trunk/src/emu/cpu/powerpc/ppcfe.c
new file mode 100644
index 00000000000..d7c2a5e81b3
--- /dev/null
+++ b/trunk/src/emu/cpu/powerpc/ppcfe.c
@@ -0,0 +1,1422 @@
+/***************************************************************************
+
+ ppcfe.c
+
+ Front-end for PowerPC 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 "ppcfe.h"
+#include "ppccom.h"
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+#define GPR_USED(desc, x) do { (desc).regin[0] |= REGFLAG_R(x); } while (0)
+#define GPR_USED_OR_ZERO(desc, x) do { (desc).regin[0] |= ((x) == 0 ? 0 : REGFLAG_R(x)); } while (0)
+#define GPR_MODIFIED(desc, x) do { (desc).regout[0] |= REGFLAG_R(x); } while (0)
+
+#define FPR_USED(desc, x) do { (desc).regin[1] |= REGFLAG_FR(x); } while (0)
+#define FPR_MODIFIED(desc, x) do { (desc).regout[1] |= REGFLAG_FR(x); } while (0)
+
+#define CR_USED(desc, x) do { (desc).regin[2] |= REGFLAG_CR(x); } while (0)
+#define CR_BIT_USED(desc, x) do { (desc).regin[2] |= REGFLAG_CR_BIT(x); } while (0)
+#define CR_MODIFIED(desc, x) do { (desc).regout[2] |= REGFLAG_CR(x); } while (0)
+#define CR_BIT_MODIFIED(desc, x) do { (desc).regout[2] |= REGFLAG_CR_BIT(x); } while (0)
+
+#define XER_CA_USED(desc) do { (desc).regin[3] |= REGFLAG_XER_CA; } while (0)
+#define XER_OV_USED(desc) do { (desc).regin[3] |= REGFLAG_XER_OV; } while (0)
+#define XER_SO_USED(desc) do { (desc).regin[3] |= REGFLAG_XER_SO; } while (0)
+#define XER_COUNT_USED(desc) do { (desc).regin[3] |= REGFLAG_XER_COUNT; } while (0)
+#define XER_CA_MODIFIED(desc) do { (desc).regout[3] |= REGFLAG_XER_CA; } while (0)
+#define XER_OV_MODIFIED(desc) do { (desc).regout[3] |= REGFLAG_XER_OV; } while (0)
+#define XER_SO_MODIFIED(desc) do { (desc).regout[3] |= REGFLAG_XER_SO; } while (0)
+#define XER_COUNT_MODIFIED(desc) do { (desc).regout[3] |= REGFLAG_XER_COUNT; } while (0)
+
+#define CTR_USED(desc) do { (desc).regin[3] |= REGFLAG_CTR; } while (0)
+#define CTR_MODIFIED(desc) do { (desc).regout[3] |= REGFLAG_CTR; } while (0)
+#define LR_USED(desc) do { (desc).regin[3] |= REGFLAG_LR; } while (0)
+#define LR_MODIFIED(desc) do { (desc).regout[3] |= REGFLAG_LR; } while (0)
+
+#define FPSCR_USED(desc, x) do { (desc).regin[3] |= REGFLAG_FPSCR(x); } while (0)
+#define FPSCR_MODIFIED(desc, x) do { (desc).regout[3] |= REGFLAG_FPSCR(x); } while (0)
+
+
+
+//**************************************************************************
+// PPC FRONTEND
+//**************************************************************************
+
+//-------------------------------------------------
+// ppc_frontend - constructor
+//-------------------------------------------------
+
+ppc_frontend::ppc_frontend(powerpc_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 ppc_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
+{
+ UINT32 op, opswitch;
+ int regnum;
+
+ // compute the physical PC
+ if (!ppccom_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
+ op = desc.opptr.l[0] = m_context.direct->read_decrypted_dword(desc.physpc, m_context.codexor);
+
+ // 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 0x02: // TDI - 64-bit only
+ case 0x1e: // 0x1e group - 64-bit only
+ case 0x3a: // 0x3a group - 64-bit only
+ case 0x3e: // 0x3e group - 64-bit only
+ return false;
+
+ case 0x03: // TWI
+ GPR_USED(desc, G_RA(op));
+ desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
+ if (is_603_class())
+ desc.cycles = 2; // 603
+ return true;
+
+ case 0x07: // MULLI
+ GPR_USED(desc, G_RA(op));
+ GPR_MODIFIED(desc, G_RD(op));
+ if (is_403_class())
+ desc.cycles = 4; // 4XX
+ else if (is_601_class())
+ desc.cycles = 5; // 601
+ else if (is_603_class())
+ desc.cycles = 2; // 603: 2-3
+ else
+ desc.cycles = 2; // ???
+ return true;
+
+ case 0x0e: // ADDI
+ case 0x0f: // ADDIS
+ GPR_USED_OR_ZERO(desc, G_RA(op));
+ GPR_MODIFIED(desc, G_RD(op));
+ return true;
+
+ case 0x0a: // CMPLI
+ case 0x0b: // CMPI
+ GPR_USED(desc, G_RA(op));
+ XER_SO_USED(desc);
+ CR_MODIFIED(desc, G_CRFD(op));
+ return true;
+
+ case 0x08: // SUBFIC
+ case 0x0c: // ADDIC
+ GPR_USED(desc, G_RA(op));
+ GPR_MODIFIED(desc, G_RD(op));
+ XER_CA_MODIFIED(desc);
+ return true;
+
+ case 0x0d: // ADDIC.
+ GPR_USED(desc, G_RA(op));
+ XER_SO_USED(desc);
+ GPR_MODIFIED(desc, G_RT(op));
+ XER_CA_MODIFIED(desc);
+ CR_MODIFIED(desc, 0);
+ return true;
+
+ case 0x10: // BCx
+ if (!(G_BO(op) & 0x10))
+ {
+ CR_BIT_USED(desc, G_BI(op));
+ // branch folding
+ if (prev == NULL || prev->regout[2] == 0)
+ desc.cycles = 0;
+ }
+ if (!(G_BO(op) & 0x04))
+ {
+ CTR_USED(desc);
+ CTR_MODIFIED(desc);
+ }
+ if (op & M_LK)
+ LR_MODIFIED(desc);
+ if ((G_BO(op) & 0x14) == 0x14)
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ else
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc.targetpc = (INT16)(G_BD(op) << 2) + ((op & M_AA) ? 0 : desc.pc);
+ if (desc.targetpc == desc.pc && desc.cycles == 0)
+ desc.cycles = 1;
+ return true;
+
+ case 0x11: // SC
+ if (!(m_context.cap & (PPCCAP_OEA | PPCCAP_4XX)))
+ return false;
+ desc.flags |= OPFLAG_WILL_CAUSE_EXCEPTION;
+ if (is_601_class())
+ desc.cycles = 16; // 601
+ else if (is_603_class())
+ desc.cycles = 3; // 603
+ else
+ desc.cycles = 3; // ???
+ return true;
+
+ case 0x12: // Bx
+ if (op & M_LK)
+ LR_MODIFIED(desc);
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.targetpc = ((INT32)(G_LI(op) << 8) >> 6) + ((op & M_AA) ? 0 : desc.pc);
+ // branch folding
+ if (desc.targetpc != desc.pc)
+ desc.cycles = 0;
+ return true;
+
+ case 0x13: // 0x13 group
+ return describe_13(op, desc, prev);
+
+ case 0x14: // RLWIMIx
+ GPR_USED(desc, G_RS(op));
+ GPR_USED(desc, G_RA(op));
+ GPR_MODIFIED(desc, G_RA(op));
+ if (op & M_RC)
+ {
+ XER_SO_USED(desc);
+ CR_MODIFIED(desc, 0);
+ }
+ return true;
+
+ case 0x15: // RLWINMx
+ GPR_USED(desc, G_RS(op));
+ GPR_MODIFIED(desc, G_RA(op));
+ if (op & M_RC)
+ {
+ XER_SO_USED(desc);
+ CR_MODIFIED(desc, 0);
+ }
+ return true;
+
+ case 0x17: // RLWNMx
+ GPR_USED(desc, G_RS(op));
+ GPR_USED(desc, G_RB(op));
+ GPR_MODIFIED(desc, G_RA(op));
+ if (op & M_RC)
+ {
+ XER_SO_USED(desc);
+ CR_MODIFIED(desc, 0);
+ }
+ return true;
+
+ case 0x18: // ORI
+ case 0x19: // ORIS
+ case 0x1a: // XORI
+ case 0x1b: // XORIS
+ GPR_USED(desc, G_RS(op));
+ GPR_MODIFIED(desc, G_RA(op));
+ return true;
+
+ case 0x1c: // ANDI.
+ case 0x1d: // ANDIS.
+ GPR_USED(desc, G_RS(op));
+ XER_SO_USED(desc);
+ GPR_MODIFIED(desc, G_RA(op));
+ CR_MODIFIED(desc, 0);
+ return true;
+
+ case 0x1f: // 0x1f group
+ return describe_1f(op, desc, prev);
+
+ case 0x20: // LWZ
+ case 0x22: // LBZ
+ case 0x28: // LHZ
+ case 0x2a: // LHA
+ GPR_USED_OR_ZERO(desc, G_RA(op));
+ GPR_MODIFIED(desc, G_RD(op));
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 0x21: // LWZU
+ case 0x23: // LBZU
+ case 0x29: // LHZU
+ case 0x2b: // LHAU
+ if (G_RA(op) == 0 || G_RA(op) == G_RD(op))
+ return false;
+ GPR_USED(desc, G_RA(op));
+ GPR_MODIFIED(desc, G_RD(op));
+ GPR_MODIFIED(desc, G_RA(op));
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 0x24: // STW
+ case 0x26: // STB
+ case 0x2c: // STH
+ GPR_USED_OR_ZERO(desc, G_RA(op));
+ GPR_USED(desc, G_RS(op));
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 0x25: // STWU
+ case 0x27: // STBU
+ case 0x2d: // STHU
+ if (G_RA(op) == 0)
+ return false;
+ GPR_USED(desc, G_RA(op));
+ GPR_USED(desc, G_RS(op));
+ GPR_MODIFIED(desc, G_RA(op));
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 0x2e: // LMW
+ GPR_USED_OR_ZERO(desc, G_RA(op));
+ for (regnum = G_RD(op); regnum < 32; regnum++)
+ GPR_MODIFIED(desc, regnum);
+ desc.flags |= OPFLAG_READS_MEMORY;
+ desc.cycles = 32 - G_RD(op);
+ return true;
+
+ case 0x2f: // STMW
+ GPR_USED_OR_ZERO(desc, G_RA(op));
+ for (regnum = G_RS(op); regnum < 32; regnum++)
+ GPR_USED(desc, regnum);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ desc.cycles = 32 - G_RS(op);
+ return true;
+
+ case 0x30: // LFS
+ case 0x32: // LFD
+ if (!(m_context.cap & PPCCAP_FPU))
+ return false;
+ GPR_USED_OR_ZERO(desc, G_RA(op));
+ FPR_MODIFIED(desc, G_RD(op));
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 0x31: // LFSU
+ case 0x33: // LFDU
+ if (!(m_context.cap & PPCCAP_FPU))
+ return false;
+ if (G_RA(op) == 0)
+ return false;
+ GPR_USED(desc, G_RA(op));
+ GPR_MODIFIED(desc, G_RA(op));
+ FPR_MODIFIED(desc, G_RD(op));
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 0x34: // STFS
+ case 0x36: // STFD
+ if (!(m_context.cap & PPCCAP_FPU))
+ return false;
+ GPR_USED_OR_ZERO(desc, G_RA(op));
+ FPR_USED(desc, G_RS(op));
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 0x35: // STFSU
+ case 0x37: // STFDU
+ if (!(m_context.cap & PPCCAP_FPU))
+ return false;
+ if (G_RA(op) == 0)
+ return false;
+ GPR_USED(desc, G_RA(op));
+ GPR_MODIFIED(desc, G_RA(op));
+ FPR_USED(desc, G_RS(op));
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 0x3b: // 0x3b group
+ return describe_3b(op, desc, prev);
+
+ case 0x3f: // 0x3f group
+ return describe_3f(op, desc, prev);
+ }
+
+ return false;
+}
+
+
+/*-------------------------------------------------
+ describe_instruction_13 - build a
+ description of a single instruction in the
+ 0x13 group
+-------------------------------------------------*/
+
+bool ppc_frontend::describe_13(UINT32 op, opcode_desc &desc, const opcode_desc *prev)
+{
+ UINT32 opswitch = (op >> 1) & 0x3ff;
+
+ switch (opswitch)
+ {
+ case 0x000: // MTCRF
+ CR_USED(desc, G_CRFS(op));
+ CR_MODIFIED(desc, G_CRFD(op));
+ // CR logical folding
+ if (prev == NULL || prev->regout[2] == 0)
+ desc.cycles = 0;
+ return true;
+
+ case 0x010: // BCLRx
+ LR_USED(desc);
+ if (!(G_BO(op) & 0x10))
+ CR_BIT_USED(desc, G_BI(op));
+ if (!(G_BO(op) & 0x04))
+ {
+ CTR_USED(desc);
+ CTR_MODIFIED(desc);
+ }
+ if (op & M_LK)
+ LR_MODIFIED(desc);
+ if ((G_BO(op) & 0x14) == 0x14)
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ else
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc.targetpc = BRANCH_TARGET_DYNAMIC;
+ return true;
+
+ case 0x021: // CRNOR
+ case 0x081: // CRANDC
+ case 0x0c1: // CRXOR
+ case 0x0e1: // CRNAND
+ case 0x101: // CRAND
+ case 0x121: // CREQV
+ case 0x1a1: // CRORC
+ case 0x1c1: // CROR
+ CR_BIT_USED(desc, G_CRBA(op));
+ CR_BIT_USED(desc, G_CRBB(op));
+ CR_BIT_MODIFIED(desc, G_CRBD(op));
+ // CR logical folding
+ if (prev == NULL || prev->regout[2] == 0)
+ desc.cycles = 0;
+ return true;
+
+ case 0x032: // RFI
+ if (!(m_context.cap & (PPCCAP_OEA | PPCCAP_4XX)))
+ return false;
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CHANGE_MODES | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE | OPFLAG_CAN_CAUSE_EXCEPTION;
+ desc.targetpc = BRANCH_TARGET_DYNAMIC;
+ if (is_601_class())
+ desc.cycles = 13; // 601
+ else if (is_603_class())
+ desc.cycles = 3; // 603
+ else
+ desc.cycles = 3; // ???
+ return true;
+
+ case 0x033: // RFCI
+ if (!(m_context.cap & PPCCAP_4XX))
+ return false;
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CHANGE_MODES | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE | OPFLAG_CAN_CAUSE_EXCEPTION;
+ desc.targetpc = BRANCH_TARGET_DYNAMIC;
+ return true;
+
+ case 0x096: // ISYNC
+ if (!(m_context.cap & (PPCCAP_VEA | PPCCAP_4XX)))
+ return false;
+ if (is_601_class())
+ desc.cycles = 6; // 601
+ return true;
+
+ case 0x210: // BCCTRx
+ CTR_USED(desc);
+ if (!(G_BO(op) & 0x10))
+ CR_BIT_USED(desc, G_BI(op));
+ if (!(G_BO(op) & 0x04))
+ return false;
+ if (op & M_LK)
+ LR_MODIFIED(desc);
+ if ((G_BO(op) & 0x14) == 0x14)
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ else
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc.targetpc = BRANCH_TARGET_DYNAMIC;
+ return true;
+ }
+
+ return false;
+}
+
+
+/*-------------------------------------------------
+ describe_instruction_1f - build a
+ description of a single instruction in the
+ 0x1f group
+-------------------------------------------------*/
+
+bool ppc_frontend::describe_1f(UINT32 op, opcode_desc &desc, const opcode_desc *prev)
+{
+ UINT32 opswitch = (op >> 1) & 0x3ff;
+ int spr, regnum;
+
+ switch (opswitch)
+ {
+ case 0x009: // MULHDUx - 64-bit only
+ case 0x015: // LDX - 64-bit only
+ case 0x01b: // SLDx - 64-bit only
+ case 0x035: // LDUX - 64-bit only
+ case 0x03a: // CNTLZDx - 64-bit only
+ case 0x044: // TD - 64-bit only
+ case 0x049: // MULHDx - 64-bit only
+ case 0x054: // LDARX - 64-bit only
+ case 0x095: // STDX - 64-bit only
+ case 0x0b5: // STDUX - 64-bit only
+ case 0x0d6: // STDCX. - 64-bit only
+ case 0x0e9: // MULLD - 64-bit only
+ case 0x2e9: // MULLDO - 64-bit only
+ case 0x155: // LWAX - 64-bit only
+ case 0x175: // LWAUX - 64-bit only
+ case 0x33a: // SRADIx - 64-bit only
+ case 0x33b: // SRADIx - 64-bit only
+ case 0x1b2: // SLBIE - 64-bit only
+ case 0x1c9: // DIVDUx - 64-bit only
+ case 0x3c9: // DIVDUOx - 64-bit only
+ case 0x1e9: // DIVDx - 64-bit only
+ case 0x3e9: // DIVDOx - 64-bit only
+ case 0x1f2: // SLBIA - 64-bit only
+ case 0x21b: // SRDx - 64-bit only
+ case 0x31a: // SRADx - 64-bit only
+ case 0x3da: // EXTSW - 64-bit only
+ return false;
+
+ case 0x000: // CMP
+ case 0x020: // CMPL
+ GPR_USED(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ XER_SO_USED(desc);
+ CR_MODIFIED(desc, G_CRFD(op));
+ return true;
+
+ case 0x004: // TW
+ GPR_USED(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
+ if (is_603_class())
+ desc.cycles = 2; // 603
+ return true;
+
+ case 0x008: // SUBFCx
+ case 0x00a: // ADDCx
+ GPR_USED(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ GPR_MODIFIED(desc, G_RD(op));
+ XER_CA_MODIFIED(desc);
+ if (op & M_RC)
+ {
+ XER_SO_USED(desc);
+ CR_MODIFIED(desc, 0);
+ }
+ return true;
+
+ case 0x088: // SUBFEx
+ case 0x08a: // ADDEx
+ GPR_USED(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ XER_CA_USED(desc);
+ GPR_MODIFIED(desc, G_RD(op));
+ XER_CA_MODIFIED(desc);
+ if (op & M_RC)
+ {
+ XER_SO_USED(desc);
+ CR_MODIFIED(desc, 0);
+ }
+ return true;
+
+ case 0x0c8: // SUBFZEx
+ case 0x0ca: // ADDZEx
+ case 0x0e8: // SUBFMEx
+ case 0x0ea: // ADDMEx
+ GPR_USED(desc, G_RA(op));
+ XER_CA_USED(desc);
+ GPR_MODIFIED(desc, G_RD(op));
+ XER_CA_MODIFIED(desc);
+ if (op & M_RC)
+ {
+ XER_SO_USED(desc);
+ CR_MODIFIED(desc, 0);
+ }
+ return true;
+
+ case 0x00b: // MULHWUx
+ case 0x04b: // MULHWx
+ case 0x0eb: // MULLWx
+ GPR_USED(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ GPR_MODIFIED(desc, G_RD(op));
+ if (op & M_RC)
+ {
+ XER_SO_USED(desc);
+ CR_MODIFIED(desc, 0);
+ }
+ if (is_403_class())
+ desc.cycles = 4; // 4XX
+ else if (is_601_class())
+ desc.cycles = 5; // 601: 5/9/10
+ else if (is_603_class())
+ desc.cycles = 2; // 603: 2,3,4,5,6
+ else
+ desc.cycles = 2; // ???
+ return true;
+
+ case 0x1cb: // DIVWUx
+ case 0x1eb: // DIVWx
+ GPR_USED(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ GPR_MODIFIED(desc, G_RD(op));
+ if (op & M_RC)
+ {
+ XER_SO_USED(desc);
+ CR_MODIFIED(desc, 0);
+ }
+ if (is_403_class())
+ desc.cycles = 33; // 4XX
+ else if (is_601_class())
+ desc.cycles = 36; // 601
+ else if (is_603_class())
+ desc.cycles = 37; // 603
+ else
+ desc.cycles = 33; // ???
+ return true;
+
+ case 0x028: // SUBFx
+ case 0x10a: // ADDx
+ GPR_USED(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ GPR_MODIFIED(desc, G_RD(op));
+ if (op & M_RC)
+ {
+ XER_SO_USED(desc);
+ CR_MODIFIED(desc, 0);
+ }
+ return true;
+
+ case 0x208: // SUBFCOx
+ case 0x20a: // ADDCOx
+ GPR_USED(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ GPR_MODIFIED(desc, G_RD(op));
+ XER_OV_MODIFIED(desc);
+ XER_SO_MODIFIED(desc);
+ XER_CA_MODIFIED(desc);
+ if (op & M_RC)
+ CR_MODIFIED(desc, 0);
+ return true;
+
+ case 0x288: // SUBFEOx
+ case 0x28a: // ADDEOx
+ GPR_USED(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ XER_CA_USED(desc);
+ GPR_MODIFIED(desc, G_RD(op));
+ XER_OV_MODIFIED(desc);
+ XER_SO_MODIFIED(desc);
+ XER_CA_MODIFIED(desc);
+ if (op & M_RC)
+ CR_MODIFIED(desc, 0);
+ return true;
+
+ case 0x2c8: // SUBFZEOx
+ case 0x2ca: // ADDZEOx
+ case 0x2e8: // SUBFMEOx
+ case 0x2ea: // ADDMEOx
+ GPR_USED(desc, G_RA(op));
+ XER_CA_USED(desc);
+ GPR_MODIFIED(desc, G_RD(op));
+ XER_OV_MODIFIED(desc);
+ XER_SO_MODIFIED(desc);
+ XER_CA_MODIFIED(desc);
+ if (op & M_RC)
+ CR_MODIFIED(desc, 0);
+ return true;
+
+ case 0x2eb: // MULLWOx
+ GPR_USED(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ GPR_MODIFIED(desc, G_RD(op));
+ XER_OV_MODIFIED(desc);
+ XER_SO_MODIFIED(desc);
+ if (op & M_RC)
+ CR_MODIFIED(desc, 0);
+ if (is_403_class())
+ desc.cycles = 4; // 4XX
+ else if (is_601_class())
+ desc.cycles = 5; // 601: 5/9/10
+ else if (is_603_class())
+ desc.cycles = 2; // 603: 2,3,4,5,6
+ else
+ desc.cycles = 2; // ???
+ return true;
+
+ case 0x3cb: // DIVWUOx
+ case 0x3eb: // DIVWOx
+ GPR_USED(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ GPR_MODIFIED(desc, G_RD(op));
+ XER_OV_MODIFIED(desc);
+ XER_SO_MODIFIED(desc);
+ if (op & M_RC)
+ CR_MODIFIED(desc, 0);
+ if (is_403_class())
+ desc.cycles = 33; // 4XX
+ else if (is_601_class())
+ desc.cycles = 36; // 601
+ else if (is_603_class())
+ desc.cycles = 37; // 603
+ else
+ desc.cycles = 33; // ???
+ return true;
+
+ case 0x228: // SUBFOx
+ case 0x30a: // ADDOx
+ GPR_USED(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ GPR_MODIFIED(desc, G_RD(op));
+ XER_OV_MODIFIED(desc);
+ XER_SO_MODIFIED(desc);
+ if (op & M_RC)
+ CR_MODIFIED(desc, 0);
+ return true;
+
+ case 0x013: // MFCR
+ CR_USED(desc, 0);
+ CR_USED(desc, 1);
+ CR_USED(desc, 2);
+ CR_USED(desc, 3);
+ CR_USED(desc, 4);
+ CR_USED(desc, 5);
+ CR_USED(desc, 6);
+ CR_USED(desc, 7);
+ GPR_MODIFIED(desc, G_RD(op));
+ return true;
+
+ case 0x136: // ECIWX
+ if (!(m_context.cap & PPCCAP_VEA))
+ return false;
+ case 0x014: // LWARX
+ case 0x017: // LWZX
+ case 0x057: // LBZX
+ case 0x117: // LHZX
+ case 0x157: // LHAX
+ case 0x216: // LWBRX
+ case 0x316: // LHBRX
+ GPR_USED_OR_ZERO(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ GPR_MODIFIED(desc, G_RD(op));
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 0x018: // SLWx
+ case 0x01c: // ANDx
+ case 0x03c: // ANDCx
+ case 0x07c: // NORx
+ case 0x11c: // EQVx
+ case 0x13c: // XORx
+ case 0x19c: // ORCx
+ case 0x1bc: // ORx
+ case 0x1dc: // NANDx
+ GPR_USED(desc, G_RS(op));
+ GPR_USED(desc, G_RB(op));
+ GPR_MODIFIED(desc, G_RA(op));
+ if (op & M_RC)
+ {
+ XER_SO_USED(desc);
+ CR_MODIFIED(desc, 0);
+ }
+ return true;
+
+ case 0x218: // SRWx
+ case 0x318: // SRAWx
+ GPR_USED(desc, G_RS(op));
+ GPR_USED(desc, G_RB(op));
+ GPR_MODIFIED(desc, G_RA(op));
+ XER_CA_MODIFIED(desc);
+ if (op & M_RC)
+ {
+ XER_SO_USED(desc);
+ CR_MODIFIED(desc, 0);
+ }
+ return true;
+
+ case 0x01a: // CNTLZWx
+ case 0x39a: // EXTSHx
+ case 0x3ba: // EXTSBx
+ GPR_USED(desc, G_RS(op));
+ GPR_MODIFIED(desc, G_RA(op));
+ if (op & M_RC)
+ {
+ XER_SO_USED(desc);
+ CR_MODIFIED(desc, 0);
+ }
+ return true;
+
+ case 0x036: // DCBST
+ case 0x056: // DCBF
+ case 0x0f6: // DCBTST
+ case 0x116: // DCBT
+ case 0x2f6: // DCBA
+ case 0x3d6: // ICBI
+ if (!(m_context.cap & (PPCCAP_VEA | PPCCAP_4XX)))
+ return false;
+ GPR_USED_OR_ZERO(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ return true;
+
+ case 0x1d6: // DCBI
+ if (!(m_context.cap & (PPCCAP_OEA | PPCCAP_4XX)))
+ return false;
+ GPR_USED_OR_ZERO(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x037: // LWZUX
+ case 0x077: // LBZUX
+ case 0x137: // LHZUX
+ case 0x177: // LHAUX
+ if (G_RA(op) == 0 || G_RA(op) == G_RD(op))
+ return false;
+ GPR_USED(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ GPR_MODIFIED(desc, G_RD(op));
+ GPR_MODIFIED(desc, G_RA(op));
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 0x153: // MFSPR
+ GPR_MODIFIED(desc, G_RD(op));
+ spr = compute_spr(G_SPR(op));
+ if (spr == SPR_LR)
+ LR_USED(desc);
+ if (spr == SPR_CTR)
+ CTR_USED(desc);
+ if (spr == SPR_XER)
+ {
+ XER_COUNT_USED(desc);
+ XER_CA_USED(desc);
+ XER_OV_USED(desc);
+ XER_SO_USED(desc);
+ }
+ if (spr & 0x010)
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ if ((m_context.cap & PPCCAP_4XX) && spr == SPR4XX_TBLU)
+ desc.cycles = POWERPC_COUNT_READ_TBL;
+ else if ((m_context.cap & PPCCAP_VEA) && spr == SPRVEA_TBL_R)
+ desc.cycles = POWERPC_COUNT_READ_TBL;
+ else if ((m_context.cap & PPCCAP_OEA) && spr == SPROEA_DEC)
+ desc.cycles = POWERPC_COUNT_READ_DEC;
+ return true;
+
+ case 0x053: // MFMSR
+ GPR_MODIFIED(desc, G_RD(op));
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_CAN_EXPOSE_EXTERNAL_INT;
+ if (is_601_class())
+ desc.cycles = 2; // 601
+ return true;
+
+ case 0x253: // MFSR
+ GPR_MODIFIED(desc, G_RD(op));
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x293: // MFSRIN
+ GPR_USED(desc, G_RB(op));
+ GPR_MODIFIED(desc, G_RD(op));
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x173: // MFTB
+ if (!(m_context.cap & PPCCAP_VEA))
+ return false;
+ GPR_MODIFIED(desc, G_RD(op));
+ spr = compute_spr(G_SPR(op));
+ if (spr == SPRVEA_TBL_R)
+ desc.cycles = POWERPC_COUNT_READ_TBL;
+ return true;
+
+ case 0x068: // NEGx
+ GPR_USED(desc, G_RA(op));
+ GPR_MODIFIED(desc, G_RD(op));
+ if (op & M_RC)
+ {
+ XER_SO_USED(desc);
+ CR_MODIFIED(desc, 0);
+ }
+ return true;
+
+ case 0x268: // NEGOx
+ GPR_USED(desc, G_RA(op));
+ GPR_MODIFIED(desc, G_RD(op));
+ XER_OV_MODIFIED(desc);
+ XER_SO_MODIFIED(desc);
+ if (op & M_RC)
+ CR_MODIFIED(desc, 0);
+ return true;
+
+ case 0x090: // MTCRF
+ GPR_USED(desc, G_RS(op));
+ if (G_CRM(op) & 0x80) CR_MODIFIED(desc, 0);
+ if (G_CRM(op) & 0x40) CR_MODIFIED(desc, 1);
+ if (G_CRM(op) & 0x20) CR_MODIFIED(desc, 2);
+ if (G_CRM(op) & 0x10) CR_MODIFIED(desc, 3);
+ if (G_CRM(op) & 0x08) CR_MODIFIED(desc, 4);
+ if (G_CRM(op) & 0x04) CR_MODIFIED(desc, 5);
+ if (G_CRM(op) & 0x02) CR_MODIFIED(desc, 6);
+ if (G_CRM(op) & 0x01) CR_MODIFIED(desc, 7);
+ return true;
+
+ case 0x092: // MTMSR
+ GPR_USED(desc, G_RS(op));
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_CAN_CHANGE_MODES | OPFLAG_END_SEQUENCE;
+ if (is_601_class())
+ desc.cycles = 17; // 601
+ else if (is_603_class())
+ desc.cycles = 2; // 603
+ return true;
+
+ case 0x0d2: // MTSR
+ if (!(m_context.cap & PPCCAP_OEA))
+ return false;
+ GPR_USED(desc, G_RS(op));
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x1d3: // MTSPR
+ GPR_USED(desc, G_RS(op));
+ spr = compute_spr(G_SPR(op));
+ if (spr == SPR_LR)
+ LR_MODIFIED(desc);
+ if (spr == SPR_CTR)
+ CTR_MODIFIED(desc);
+ if (spr == SPR_XER)
+ {
+ XER_COUNT_MODIFIED(desc);
+ XER_CA_MODIFIED(desc);
+ XER_OV_MODIFIED(desc);
+ XER_SO_MODIFIED(desc);
+ }
+ if (spr & 0x010)
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x1b6: // ECOWX
+ if (!(m_context.cap & PPCCAP_VEA))
+ return false;
+ case 0x096: // STWCX.
+ case 0x097: // STWX
+ case 0x0d7: // STBX
+ case 0x197: // STHX
+ case 0x296: // STWBRX
+ case 0x396: // STHBRX
+ GPR_USED_OR_ZERO(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ GPR_USED(desc, G_RS(op));
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 0x0b7: // STWUX
+ case 0x0f7: // STBUX
+ case 0x1b7: // STHUX
+ if (G_RA(op) == 0)
+ return false;
+ GPR_USED(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ GPR_USED(desc, G_RS(op));
+ GPR_MODIFIED(desc, G_RA(op));
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 0x0f2: // MTSRIN
+ if (!(m_context.cap & PPCCAP_OEA))
+ return false;
+ GPR_USED(desc, G_RS(op));
+ GPR_USED(desc, G_RB(op));
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x132: // TLBIE
+ if (!(m_context.cap & PPCCAP_OEA))
+ return false;
+ GPR_USED(desc, G_RB(op));
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x172: // TLBIA
+ if (!(m_context.cap & PPCCAP_OEA) || (m_context.cap & PPCCAP_603_MMU))
+ return false;
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x3d2: // TLBLD
+ case 0x3f2: // TLBLI
+ if (!(m_context.cap & PPCCAP_603_MMU) && !is_602_class())
+ return false;
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x200: // MCRXR
+ XER_CA_USED(desc);
+ XER_OV_USED(desc);
+ XER_SO_USED(desc);
+ CR_MODIFIED(desc, G_CRFD(op));
+ XER_CA_MODIFIED(desc);
+ XER_OV_MODIFIED(desc);
+ XER_SO_MODIFIED(desc);
+ return true;
+
+ case 0x215: // LSWX
+ GPR_USED_OR_ZERO(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ XER_COUNT_USED(desc);
+ for (regnum = 0; regnum < 32; regnum++)
+ GPR_MODIFIED(desc, regnum);
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 0x217: // LFSX
+ case 0x257: // LFDX
+ if (!(m_context.cap & PPCCAP_FPU))
+ return false;
+ GPR_USED_OR_ZERO(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ FPR_MODIFIED(desc, G_RD(op));
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 0x236: // TLBSYNC
+ if (!(m_context.cap & PPCCAP_OEA))
+ return false;
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x256: // SYNC
+ return true;
+
+ case 0x356: // EIEIO
+ if (!(m_context.cap & PPCCAP_VEA))
+ return false;
+ return true;
+
+ case 0x237: // LFSUX
+ case 0x277: // LFDUX
+ if (!(m_context.cap & PPCCAP_FPU))
+ return false;
+ if (G_RA(op) == 0)
+ return false;
+ GPR_USED(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ GPR_MODIFIED(desc, G_RA(op));
+ FPR_MODIFIED(desc, G_RD(op));
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 0x255: // LSWI
+ GPR_USED_OR_ZERO(desc, G_RA(op));
+ for (regnum = 0; regnum < ((G_NB(op) - 1) & 0x1f) + 1; regnum += 4)
+ GPR_MODIFIED(desc, (G_RD(op) + regnum / 4) % 32);
+ desc.flags |= OPFLAG_READS_MEMORY;
+ desc.cycles = (((G_NB(op) - 1) & 0x1f) + 1 + 3) / 4;
+ return true;
+
+ case 0x295: // STSWX
+ GPR_USED_OR_ZERO(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ XER_COUNT_USED(desc);
+ for (regnum = 0; regnum < 32; regnum++)
+ GPR_USED(desc, regnum);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 0x2d5: // STSWI
+ GPR_USED_OR_ZERO(desc, G_RA(op));
+ for (regnum = 0; regnum < ((G_NB(op) - 1) & 0x1f) + 1; regnum += 4)
+ GPR_USED(desc, (G_RD(op) + regnum / 4) % 32);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ desc.cycles = (((G_NB(op) - 1) & 0x1f) + 1 + 3) / 4;
+ return true;
+
+ case 0x297: // STFSX
+ case 0x2d7: // STFDX
+ case 0x3d7: // STFIWX
+ if (!(m_context.cap & PPCCAP_FPU))
+ return false;
+ GPR_USED_OR_ZERO(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ FPR_USED(desc, G_RS(op));
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 0x2b7: // STFSUX
+ case 0x2f7: // STFDUX
+ if (!(m_context.cap & PPCCAP_FPU))
+ return false;
+ if (G_RA(op) == 0)
+ return false;
+ GPR_USED_OR_ZERO(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ GPR_MODIFIED(desc, G_RA(op));
+ FPR_USED(desc, G_RS(op));
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 0x338: // SRAWIx
+ GPR_USED(desc, G_RS(op));
+ GPR_MODIFIED(desc, G_RA(op));
+ XER_CA_MODIFIED(desc);
+ if (op & M_RC)
+ {
+ XER_SO_USED(desc);
+ CR_MODIFIED(desc, 0);
+ }
+ return true;
+
+ case 0x3f6: // DCBZ
+ if (!(m_context.cap & (PPCCAP_VEA | PPCCAP_4XX)))
+ return false;
+ GPR_USED_OR_ZERO(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 0x106: // ICBT
+ case 0x1c6: // DCCCI
+ case 0x3c6: // ICCCI
+ if (!(m_context.cap & PPCCAP_4XX))
+ return false;
+ GPR_USED_OR_ZERO(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x1e6: // DCREAD
+ case 0x3e6: // ICREAD
+ if (!(m_context.cap & PPCCAP_4XX))
+ return false;
+ GPR_USED_OR_ZERO(desc, G_RA(op));
+ GPR_USED(desc, G_RB(op));
+ GPR_MODIFIED(desc, G_RT(op));
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x143: // MFDCR
+ if (!(m_context.cap & PPCCAP_4XX))
+ return false;
+ GPR_MODIFIED(desc, G_RD(op));
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x1c3: // MTDCR
+ if (!(m_context.cap & PPCCAP_4XX))
+ return false;
+ GPR_USED(desc, G_RS(op));
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_CAN_EXPOSE_EXTERNAL_INT;
+ return true;
+
+ case 0x083: // WRTEE
+ if (!(m_context.cap & PPCCAP_4XX))
+ return false;
+ GPR_USED(desc, G_RS(op));
+ desc.flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT;
+ return true;
+
+ case 0x0a3: // WRTEEI
+ if (!(m_context.cap & PPCCAP_4XX))
+ return false;
+ if (op & MSR_EE)
+ desc.flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT;
+ return true;
+
+ case 0x254: // ESA
+ case 0x274: // DSA
+ if (!is_602_class())
+ return false;
+ desc.flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+ }
+
+ return false;
+}
+
+
+/*-------------------------------------------------
+ describe_instruction_3b - build a
+ description of a single instruction in the
+ 0x3b group
+-------------------------------------------------*/
+
+bool ppc_frontend::describe_3b(UINT32 op, opcode_desc &desc, const opcode_desc *prev)
+{
+ UINT32 opswitch = (op >> 1) & 0x1f;
+
+ if (!(m_context.cap & PPCCAP_FPU))
+ return false;
+
+ switch (opswitch)
+ {
+ case 0x12: // FDIVSx
+ FPR_USED(desc, G_RA(op));
+ FPR_USED(desc, G_RB(op));
+ FPR_MODIFIED(desc, G_RD(op));
+ if (op & M_RC)
+ CR_MODIFIED(desc, 1);
+ if (is_601_class())
+ desc.cycles = 17; // 601
+ else if (is_603_class())
+ desc.cycles = 18; // 603
+ else
+ desc.cycles = 17; // ???
+ FPSCR_MODIFIED(desc, 4);
+ return true;
+
+ case 0x14: // FSUBSx
+ case 0x15: // FADDSx
+ FPR_USED(desc, G_RA(op));
+ FPR_USED(desc, G_RB(op));
+ FPR_MODIFIED(desc, G_RD(op));
+ if (op & M_RC)
+ CR_MODIFIED(desc, 1);
+ FPSCR_MODIFIED(desc, 4);
+ return true;
+
+ case 0x19: // FMULSx - not the same form as FSUB/FADD!
+ FPR_USED(desc, G_RA(op));
+ FPR_USED(desc, G_REGC(op));
+ FPR_MODIFIED(desc, G_RD(op));
+ if (op & M_RC)
+ CR_MODIFIED(desc, 1);
+ FPSCR_MODIFIED(desc, 4);
+ return true;
+
+ case 0x16: // FSQRTSx
+ case 0x18: // FRESx
+ FPR_USED(desc, G_RB(op));
+ FPR_MODIFIED(desc, G_RD(op));
+ if (op & M_RC)
+ CR_MODIFIED(desc, 1);
+ FPSCR_MODIFIED(desc, 4);
+ return true;
+
+ case 0x1c: // FMSUBSx
+ case 0x1d: // FMADDSx
+ case 0x1e: // FNMSUBSx
+ case 0x1f: // FNMADDSx
+ FPR_USED(desc, G_RA(op));
+ FPR_USED(desc, G_RB(op));
+ FPR_USED(desc, G_REGC(op));
+ FPR_MODIFIED(desc, G_RD(op));
+ if (op & M_RC)
+ CR_MODIFIED(desc, 1);
+ FPSCR_MODIFIED(desc, 4);
+ return true;
+ }
+
+ return false;
+}
+
+
+/*-------------------------------------------------
+ describe_instruction_3f - build a
+ description of a single instruction in the
+ 0x3f group
+-------------------------------------------------*/
+
+bool ppc_frontend::describe_3f(UINT32 op, opcode_desc &desc, const opcode_desc *prev)
+{
+ UINT32 opswitch = (op >> 1) & 0x3ff;
+
+ if (!(m_context.cap & PPCCAP_FPU))
+ return false;
+
+ if (opswitch & 0x10)
+ {
+ opswitch &= 0x1f;
+ switch (opswitch)
+ {
+ case 0x12: // FDIVx
+ FPR_USED(desc, G_RA(op));
+ FPR_USED(desc, G_RB(op));
+ FPR_MODIFIED(desc, G_RD(op));
+ if (op & M_RC)
+ CR_MODIFIED(desc, 1);
+ if (is_601_class())
+ desc.cycles = 31; // 601
+ else if (is_603_class())
+ desc.cycles = 33; // 603
+ else
+ desc.cycles = 31; // ???
+ FPSCR_MODIFIED(desc, 4);
+ return true;
+
+ case 0x19: // FMULx
+ FPR_USED(desc, G_RA(op));
+ FPR_USED(desc, G_REGC(op));
+ FPR_MODIFIED(desc, G_RD(op));
+ if (op & M_RC)
+ CR_MODIFIED(desc, 1);
+ desc.cycles = 2; // 601/603
+ FPSCR_MODIFIED(desc, 4);
+ return true;
+
+ case 0x14: // FSUBx
+ case 0x15: // FADDx
+ FPR_USED(desc, G_RA(op));
+ FPR_USED(desc, G_RB(op));
+ FPR_MODIFIED(desc, G_RD(op));
+ if (op & M_RC)
+ CR_MODIFIED(desc, 1);
+ FPSCR_MODIFIED(desc, 4);
+ return true;
+
+ case 0x16: // FSQRTx
+ case 0x1a: // FSQRTEx
+ FPR_USED(desc, G_RB(op));
+ FPR_MODIFIED(desc, G_RD(op));
+ if (op & M_RC)
+ CR_MODIFIED(desc, 1);
+ FPSCR_MODIFIED(desc, 4);
+ return true;
+
+ case 0x17: // FSELx
+ FPR_USED(desc, G_RA(op));
+ FPR_USED(desc, G_RB(op));
+ FPR_USED(desc, G_REGC(op));
+ FPR_MODIFIED(desc, G_RD(op));
+ if (op & M_RC)
+ CR_MODIFIED(desc, 1);
+ desc.cycles = 2; // 601/603
+ return true;
+
+ case 0x1c: // FMSUBx
+ case 0x1d: // FMADDx
+ case 0x1e: // FNMSUBx
+ case 0x1f: // FNMADDx
+ FPR_USED(desc, G_RA(op));
+ FPR_USED(desc, G_RB(op));
+ FPR_USED(desc, G_REGC(op));
+ FPR_MODIFIED(desc, G_RD(op));
+ if (op & M_RC)
+ CR_MODIFIED(desc, 1);
+ desc.cycles = 2; // 601/603
+ FPSCR_MODIFIED(desc, 4);
+ return true;
+ }
+ }
+ else
+ {
+ switch (opswitch)
+ {
+ case 0x32e: // FCTIDx - 64-bit only
+ case 0x32f: // FCTIDZx - 64-bit only
+ case 0x34e: // FCFIDx - 64-bit only
+ return false;
+
+ case 0x000: // FCMPU
+ case 0x020: // FCMPO
+ FPR_USED(desc, G_RA(op));
+ FPR_USED(desc, G_RB(op));
+ CR_MODIFIED(desc, G_CRFD(op));
+ return true;
+
+ case 0x00c: // FRSPx
+ case 0x00e: // FCTIWx
+ case 0x00f: // FCTIWZx
+ FPSCR_MODIFIED(desc, 4);
+ case 0x028: // FNEGx
+ case 0x048: // FMRx
+ case 0x088: // FNABSx
+ case 0x108: // FABSx
+ FPR_USED(desc, G_RB(op));
+ FPR_MODIFIED(desc, G_RD(op));
+ if (op & M_RC)
+ CR_MODIFIED(desc, 1);
+ return true;
+
+ case 0x026: // MTFSB1x
+ case 0x046: // MTFSB0x
+ FPSCR_MODIFIED(desc, G_CRBD(op) / 4);
+ return true;
+
+ case 0x040: // MCRFS
+ FPSCR_USED(desc, G_CRFS(op));
+ CR_MODIFIED(desc, G_CRFD(op));
+ return true;
+
+ case 0x086: // MTFSFIx
+ FPSCR_MODIFIED(desc, G_CRFD(op));
+ return true;
+
+ case 0x247: // MFFSx
+ FPSCR_USED(desc, 0);
+ FPSCR_USED(desc, 1);
+ FPSCR_USED(desc, 2);
+ FPSCR_USED(desc, 3);
+ FPSCR_USED(desc, 4);
+ FPSCR_USED(desc, 5);
+ FPSCR_USED(desc, 6);
+ FPSCR_USED(desc, 7);
+ FPR_MODIFIED(desc, G_RD(op));
+ return true;
+
+ case 0x2c7: // MTFSFx
+ FPR_USED(desc, G_RB(op));
+ if (G_CRM(op) & 0x80) FPSCR_MODIFIED(desc, 0);
+ if (G_CRM(op) & 0x40) FPSCR_MODIFIED(desc, 1);
+ if (G_CRM(op) & 0x20) FPSCR_MODIFIED(desc, 2);
+ if (G_CRM(op) & 0x10) FPSCR_MODIFIED(desc, 3);
+ if (G_CRM(op) & 0x08) FPSCR_MODIFIED(desc, 4);
+ if (G_CRM(op) & 0x04) FPSCR_MODIFIED(desc, 5);
+ if (G_CRM(op) & 0x02) FPSCR_MODIFIED(desc, 6);
+ if (G_CRM(op) & 0x01) FPSCR_MODIFIED(desc, 7);
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/trunk/src/emu/cpu/powerpc/ppcfe.h b/trunk/src/emu/cpu/powerpc/ppcfe.h
new file mode 100644
index 00000000000..b3209e4358c
--- /dev/null
+++ b/trunk/src/emu/cpu/powerpc/ppcfe.h
@@ -0,0 +1,106 @@
+/***************************************************************************
+
+ ppcfe.h
+
+ Front-end for PowerPC 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.
+
+***************************************************************************/
+
+#ifndef __PPCFE_H__
+#define __PPCFE_H__
+
+#include "ppccom.h"
+#include "cpu/drcfe.h"
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+// register flags 0
+#define REGFLAG_R(n) (1 << (n))
+#define REGFLAG_RZ(n) (((n) == 0) ? 0 : REGFLAG_R(n))
+
+// register flags 1
+#define REGFLAG_FR(n) (1 << (n))
+
+// register flags 2
+#define REGFLAG_CR(n) (0xf0000000 >> (4 * (n)))
+#define REGFLAG_CR_BIT(n) (0x80000000 >> (n))
+
+// register flags 3
+#define REGFLAG_XER_CA (1 << 0)
+#define REGFLAG_XER_OV (1 << 1)
+#define REGFLAG_XER_SO (1 << 2)
+#define REGFLAG_XER_COUNT (1 << 3)
+#define REGFLAG_CTR (1 << 4)
+#define REGFLAG_LR (1 << 5)
+#define REGFLAG_FPSCR(n) (1 << (6 + (n)))
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class ppc_frontend : public drc_frontend
+{
+public:
+ // construction/destruction
+ ppc_frontend(powerpc_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:
+ // inlines
+ UINT32 compute_spr(UINT32 spr) const { return ((spr >> 5) | (spr << 5)) & 0x3ff; }
+ bool is_403_class() const { return (m_context.flavor == PPC_MODEL_403GA || m_context.flavor == PPC_MODEL_403GB || m_context.flavor == PPC_MODEL_403GC || m_context.flavor == PPC_MODEL_403GCX || m_context.flavor == PPC_MODEL_405GP); }
+ bool is_601_class() const { return (m_context.flavor == PPC_MODEL_601); }
+ bool is_602_class() const { return (m_context.flavor == PPC_MODEL_602); }
+ bool is_603_class() const { return (m_context.flavor == PPC_MODEL_603 || m_context.flavor == PPC_MODEL_603E || m_context.flavor == PPC_MODEL_603EV || m_context.flavor == PPC_MODEL_603R); }
+
+ // internal helpers
+ bool describe_13(UINT32 op, opcode_desc &desc, const opcode_desc *prev);
+ bool describe_1f(UINT32 op, opcode_desc &desc, const opcode_desc *prev);
+ bool describe_3b(UINT32 op, opcode_desc &desc, const opcode_desc *prev);
+ bool describe_3f(UINT32 op, opcode_desc &desc, const opcode_desc *prev);
+
+ // internal state
+ powerpc_state &m_context;
+};
+
+
+#endif /* __PPCFE_H__ */
diff --git a/trunk/src/emu/cpu/pps4/pps4.c b/trunk/src/emu/cpu/pps4/pps4.c
new file mode 100644
index 00000000000..fc7bf665470
--- /dev/null
+++ b/trunk/src/emu/cpu/pps4/pps4.c
@@ -0,0 +1,454 @@
+/*****************************************************************************
+ *
+ * pps4.c
+ *
+ * Rockwell PPS-4 CPU
+ *
+ * Initial version by Miodrag Milanovic
+ *
+ *****************************************************************************/
+#include "emu.h"
+#include "debugger.h"
+#include "pps4.h"
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _pps4_state pps4_state;
+struct _pps4_state
+{
+ UINT8 A; // Accumulator
+ UINT8 X;
+
+ PAIR P;
+ PAIR SA;
+ PAIR SB;
+ PAIR B; // BU + BM + BL
+
+ UINT8 C; // Carry flag
+ UINT8 FF1; // Flip-flop 1
+ UINT8 FF2; // Flip-flop 2
+
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *data;
+ address_space *io;
+
+ int icount;
+};
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE pps4_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == PPS4);
+ return (pps4_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+INLINE UINT8 ROP(pps4_state *cpustate)
+{
+ UINT8 retVal = cpustate->direct->read_decrypted_byte(cpustate->P.w.l);
+ cpustate->P.w.l = (cpustate->P.w.l + 1) & 0x0fff;
+ return retVal;
+}
+
+INLINE UINT8 ARG(pps4_state *cpustate)
+{
+ UINT8 retVal = cpustate->direct->read_raw_byte(cpustate->P.w.l);
+ cpustate->P.w.l = (cpustate->P.w.l + 1) & 0x0fff;
+ return retVal;
+}
+
+INLINE void DO_SKIP(pps4_state *cpustate)
+{
+ cpustate->P.w.l = (cpustate->P.w.l + 1) & 0x0fff;
+}
+
+static void execute_one(pps4_state *cpustate, int opcode)
+{
+ cpustate->icount -= 1;
+ switch (opcode)
+ {
+ // Arithmetic instructions
+ case 0x0b: // AD
+ break;
+ case 0x0a: // ADC
+ break;
+ case 0x09: // ADSK
+ break;
+ case 0x08: // ADCSK
+ break;
+ case 0x60: case 0x61: case 0x62: case 0x63:
+ case 0x64: case 0x66: case 0x67: case 0x68:
+ case 0x69: case 0x6a: case 0x6b: case 0x6c:
+ case 0x6d: case 0x6e:
+ // ADI
+ break;
+ case 0x65: //DC
+ cpustate->A = (cpustate->A + 10) & 0x0f;
+ break;
+ // Logical instructions
+ case 0x0d: // AND
+ break;
+ case 0x0f: // OR
+ break;
+ case 0x0c: // EOR
+ break;
+ case 0x0e: // COMP
+ cpustate->A ^= 0x0f;
+ break;
+ // Data transfer instructions
+ case 0x20: // SC
+ cpustate->C = 1;
+ break;
+ case 0x24: //RC
+ cpustate->C = 0;
+ break;
+ case 0x22: // SF1
+ cpustate->FF1 = 1;
+ break;
+ case 0x26: // RF1
+ cpustate->FF1 = 0;
+ break;
+ case 0x21: // SF2
+ cpustate->FF2 = 1;
+ break;
+ case 0x25: // RF2
+ cpustate->FF2 = 0;
+ break;
+ case 0x30: case 0x31: case 0x32: case 0x33:
+ case 0x34: case 0x35: case 0x36: case 0x37:
+ // LD
+ break;
+ case 0x38: case 0x39: case 0x3a: case 0x3b:
+ case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ // EX
+ break;
+ case 0x28: case 0x29: case 0x2a: case 0x2b:
+ case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ // EXD
+ 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:
+ // LDI
+ cpustate->A = opcode & 0x0f;
+ break;
+ case 0x12: // LAX
+ cpustate->A = cpustate->X;
+ break;
+ case 0x1b: // LXA
+ cpustate->X = cpustate->A;
+ break;
+ case 0x11: // LABL
+ cpustate->A = cpustate->B.w.l & 0x00f;
+ break;
+ case 0x10: // LBMX
+ cpustate->B.w.l &= 0xf0f;
+ cpustate->B.w.l |= (cpustate->X << 4);
+ break;
+ case 0x04: // LBUA
+ break;
+ case 0x19: // XABL
+ {
+ UINT8 tmp = cpustate->B.w.l & 0x00f;
+ cpustate->B.w.l &= 0xff0;
+ cpustate->B.w.l |= cpustate->A;
+ cpustate->A = tmp;
+ }
+ break;
+ case 0x18: // XBMX
+ {
+ UINT8 tmp = (cpustate->B.w.l & 0x0f0) >> 4;
+ cpustate->B.w.l &= 0xf0f;
+ cpustate->B.w.l |= (cpustate->X << 4);
+ cpustate->X = tmp;
+ }
+ break;
+ case 0x1a: // XAX
+ {
+ UINT8 tmp = cpustate->A;
+ cpustate->A = cpustate->X;
+ cpustate->X = tmp;
+ }
+ break;
+ case 0x06: // XS
+ {
+ PAIR tmp = cpustate->SA;
+ cpustate->SA = cpustate->SB;
+ cpustate->SB = tmp;
+ }
+ break;
+ case 0x6f: // CYS
+ 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:
+ // LB
+ {
+ //UINT8 tmp = ARG(cpustate);
+ cpustate->icount -= 1;
+ }
+ break;
+ case 0x00: // LBL
+ {
+ UINT8 tmp = ARG(cpustate);
+ cpustate->icount -= 1;
+ cpustate->B.w.l = tmp;
+ }
+ break;
+ case 0x17: // INCB
+ if ((cpustate->B.w.l & 0x0f) == 0x0f) {
+ cpustate->B.w.l &= 0xff0;
+ DO_SKIP(cpustate);
+ } else {
+ cpustate->B.w.l += 1;
+ }
+ break;
+ case 0x1f: // DECB
+ if ((cpustate->B.w.l & 0x0f) == 0x00) {
+ cpustate->B.w.l |= 0x00f;
+ DO_SKIP(cpustate);
+ } else {
+ cpustate->B.w.l -= 1;
+ }
+ break;
+ // Control transfer instructions
+ 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:
+ // T
+ cpustate->P.w.l = (cpustate->P.w.l & 0xfc0) | (opcode & 0x3f);
+ 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:
+ 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:
+ // TM
+ 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:
+ // TL
+ {
+ //UINT8 tmp = ARG(cpustate);
+ cpustate->icount -= 1;
+ }
+ break;
+ case 0x01: case 0x02: case 0x03:
+ // TML
+ {
+ //UINT8 tmp = ARG(cpustate);
+ cpustate->icount -= 1;
+ }
+ break;
+ case 0x15: // SKC
+ break;
+ case 0x1e: // SKZ
+ 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:
+ // SKBI
+ break;
+ case 0x16: // SKF1
+ break;
+ case 0x14: // SKF2
+ break;
+ case 0x05: // RTN
+ break;
+ case 0x07: // RTNSK
+ break;
+ // Input/Output instructions
+ case 0x1c: // IOL
+ {
+ //UINT8 tmp = ARG(cpustate);
+ cpustate->icount -= 1;
+ }
+ break;
+ case 0x27: // DIA
+ break;
+ case 0x23: // DIB
+ break;
+ case 0x1d: // DOA
+ break;
+ // Special instructions
+ case 0x13: // SAG
+ break;
+ }
+}
+
+
+/***************************************************************************
+ COMMON EXECUTION
+***************************************************************************/
+static CPU_EXECUTE( pps4 )
+{
+ pps4_state *cpustate = get_safe_token(device);
+
+ do
+ {
+ debugger_instruction_hook(device, cpustate->P.d);
+ execute_one(cpustate, ROP(cpustate));
+
+ } while (cpustate->icount > 0);
+}
+
+/***************************************************************************
+ CORE INITIALIZATION
+***************************************************************************/
+
+static CPU_INIT( pps4 )
+{
+ pps4_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);
+
+ device->save_item(NAME(cpustate->A));
+ device->save_item(NAME(cpustate->X));
+ device->save_item(NAME(cpustate->P));
+ device->save_item(NAME(cpustate->SA));
+ device->save_item(NAME(cpustate->SB));
+ device->save_item(NAME(cpustate->B));
+ device->save_item(NAME(cpustate->C));
+ device->save_item(NAME(cpustate->FF1));
+ device->save_item(NAME(cpustate->FF2));
+}
+
+/***************************************************************************
+ COMMON RESET
+***************************************************************************/
+
+static CPU_RESET( pps4 )
+{
+ pps4_state *cpustate = get_safe_token(device);
+
+ cpustate->A = cpustate->X = 0;
+ cpustate->C = cpustate->FF1 = cpustate->FF2 = 0;
+
+ cpustate->P.d = 0;
+ cpustate->SA.d = 0;
+ cpustate->SB.d = 0;
+ cpustate->B.d = 0;
+}
+
+/***************************************************************************
+ COMMON STATE IMPORT/EXPORT
+***************************************************************************/
+
+static CPU_IMPORT_STATE( pps4 )
+{
+}
+
+static CPU_EXPORT_STATE( pps4 )
+{
+}
+
+/***************************************************************************
+ COMMON SET INFO
+***************************************************************************/
+static CPU_SET_INFO( pps4 )
+{
+}
+
+/***************************************************************************
+ PPS4 GET INFO
+***************************************************************************/
+
+CPU_GET_INFO( pps4 )
+{
+ pps4_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(pps4_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 = 2; 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; // 4 bit for RAM
+ 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; // 4 bit
+ 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(pps4); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(pps4); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(pps4); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(pps4); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(pps4); break;
+ case CPUINFO_FCT_IMPORT_STATE: info->import_state = CPU_IMPORT_STATE_NAME(pps4); break;
+ case CPUINFO_FCT_EXPORT_STATE: info->export_state = CPU_EXPORT_STATE_NAME(pps4); 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, "PPS4"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Rockwell PPS-4"); 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;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c",
+ cpustate->C ? 'C':'.',
+ cpustate->FF1 ? '1':'.',
+ cpustate->FF2 ? '2':'.');
+ break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(PPS4, pps4);
diff --git a/trunk/src/emu/cpu/pps4/pps4.h b/trunk/src/emu/cpu/pps4/pps4.h
new file mode 100644
index 00000000000..8a32f71a612
--- /dev/null
+++ b/trunk/src/emu/cpu/pps4/pps4.h
@@ -0,0 +1,28 @@
+#ifndef __PPS4_H__
+#define __PPS4_H__
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+enum
+{
+ PPS4_PC,
+ PPS4_A,PPS4_X,PPS4_SA,PPS4_SB,PPS4_B,
+ PPS4_GENPC = STATE_GENPC,
+ PPS4_GENSP = STATE_GENSP,
+ PPS4_GENPCBASE = STATE_GENPCBASE
+};
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+DECLARE_LEGACY_CPU_DEVICE( PPS4, pps4 );
+
+CPU_DISASSEMBLE( pps4 );
+#endif
diff --git a/trunk/src/emu/cpu/pps4/pps4dasm.c b/trunk/src/emu/cpu/pps4/pps4dasm.c
new file mode 100644
index 00000000000..51bdd5211c2
--- /dev/null
+++ b/trunk/src/emu/cpu/pps4/pps4dasm.c
@@ -0,0 +1,135 @@
+/*****************************************************************************
+ *
+ * pps4dasm.c
+ *
+ * Rockwell PPS-4 CPU Disassembly
+ *
+ * Initial version by Miodrag Milanovic
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+
+#define OP(A) oprom[(A) - PC]
+#define ARG(A) opram[(A) - PC]
+
+CPU_DISASSEMBLE( pps4 )
+{
+ UINT32 flags = 0;
+ unsigned PC = pc;
+ UINT8 op;
+ switch (op = OP(pc++))
+ {
+ // Arithmetic instructions
+ case 0x0b: sprintf (buffer,"ad"); break;
+ case 0x0a: sprintf (buffer,"adc"); break;
+ case 0x09: sprintf (buffer,"adsk"); break;
+ case 0x08: sprintf (buffer,"adcsk"); break;
+ case 0x60: case 0x61: case 0x62: case 0x63:
+ case 0x64: case 0x66: case 0x67: case 0x68:
+ case 0x69: case 0x6a: case 0x6b: case 0x6c:
+ case 0x6d: case 0x6e:
+ sprintf (buffer,"adi %01x",(op & 0x0f)); break;
+ case 0x65: sprintf (buffer,"dc"); break;
+ // Logical instructions
+ case 0x0d: sprintf (buffer,"and"); break;
+ case 0x0f: sprintf (buffer,"or"); break;
+ case 0x0c: sprintf (buffer,"eor"); break;
+ case 0x0e: sprintf (buffer,"comp"); break;
+ // Data transfer instructions
+ case 0x20: sprintf (buffer,"sc"); break;
+ case 0x24: sprintf (buffer,"rc"); break;
+ case 0x22: sprintf (buffer,"sf1"); break;
+ case 0x26: sprintf (buffer,"rf1"); break;
+ case 0x21: sprintf (buffer,"sf2"); break;
+ case 0x25: sprintf (buffer,"rf2"); break;
+ case 0x30: case 0x31: case 0x32: case 0x33:
+ case 0x34: case 0x35: case 0x36: case 0x37:
+ sprintf (buffer,"ld %01x",(op & 0x07)); break;
+ case 0x38: case 0x39: case 0x3a: case 0x3b:
+ case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ sprintf (buffer,"ex %01x",(op & 0x07)); break;
+ case 0x28: case 0x29: case 0x2a: case 0x2b:
+ case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ sprintf (buffer,"exd %01x",(op & 0x07)); break;
+ case 0x70: case 0x71: case 0x72: case 0x73:
+ case 0x74: case 0x75: case 0x76: case 0x77:
+ sprintf (buffer,"ldi %01x",(op & 0x0f)); break;
+ case 0x12: sprintf (buffer,"lax"); break;
+ case 0x1b: sprintf (buffer,"lxa"); break;
+ case 0x11: sprintf (buffer,"labl"); break;
+ case 0x10: sprintf (buffer,"lbmx"); break;
+ case 0x04: sprintf (buffer,"lbua"); break;
+ case 0x19: sprintf (buffer,"xabl"); break;
+ case 0x18: sprintf (buffer,"xbmx"); break;
+ case 0x1a: sprintf (buffer,"xax"); break;
+ case 0x06: sprintf (buffer,"xs"); break;
+ case 0x6f: sprintf (buffer,"cys"); 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,"lb %02x",ARG(pc)); pc++; break;
+ case 0x00: sprintf (buffer,"lbl %02x",ARG(pc)); pc++; break;
+ case 0x17: sprintf (buffer,"incb"); break;
+ case 0x1f: sprintf (buffer,"decb"); break;
+ // Control transfer instructions
+ 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,"t %02x",(op & 0x3f)); 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:
+ 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,"tm %02x %02x",(op & 0x3f),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,"tl %01x %02x",(op & 0x0f),ARG(pc)); pc++; break;
+ case 0x01: case 0x02: case 0x03:
+ sprintf (buffer,"tml %02x",ARG(pc)); pc++; break;
+ case 0x15: sprintf (buffer,"skc"); break;
+ case 0x1e: sprintf (buffer,"skz"); 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,"skbi %01x",(op & 0x0f)); break;
+ case 0x16: sprintf (buffer,"skf1"); break;
+ case 0x14: sprintf (buffer,"skf2"); break;
+ case 0x05: sprintf (buffer,"rtn"); break;
+ case 0x07: sprintf (buffer,"rtnsk"); break;
+ // Input/Output instructions
+ case 0x1c: sprintf (buffer,"iol %02x",ARG(pc)); pc++; break;
+ case 0x27: sprintf (buffer,"dia"); break;
+ case 0x23: sprintf (buffer,"dib"); break;
+ case 0x1d: sprintf (buffer,"doa"); break;
+ // Special instructions
+ case 0x13: sprintf (buffer,"sag"); break;
+ }
+
+ return (pc - PC) | flags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/psx/dismips.c b/trunk/src/emu/cpu/psx/dismips.c
new file mode 100644
index 00000000000..339ff26ff3b
--- /dev/null
+++ b/trunk/src/emu/cpu/psx/dismips.c
@@ -0,0 +1,360 @@
+/*
+ * standalone MIPS disassembler by smf
+ *
+ * based on DIS68k by Aaron Giles
+ *
+ */
+
+#include "emu.h"
+#include "psx.h"
+
+extern CPU_DISASSEMBLE( r3000le );
+extern unsigned dasmmips3(char *,unsigned, UINT32);
+
+static struct
+{
+ UINT8 id[ 8 ];
+ UINT32 text; /* SCE only */
+ UINT32 data; /* SCE only */
+ UINT32 pc0;
+ UINT32 gp0; /* SCE only */
+ UINT32 t_addr;
+ UINT32 t_size;
+ UINT32 d_addr; /* SCE only */
+ UINT32 d_size; /* SCE only */
+ UINT32 b_addr; /* SCE only */
+ UINT32 b_size; /* SCE only */
+ UINT32 s_addr;
+ UINT32 s_size;
+ UINT32 SavedSP;
+ UINT32 SavedFP;
+ UINT32 SavedGP;
+ UINT32 SavedRA;
+ UINT32 SavedS0;
+ UINT8 dummy[ 0x800 - 76 ];
+} m_psxexe_header;
+
+#define FORMAT_BIN ( 0 )
+#define FORMAT_PSX ( 1 )
+
+#define CPU_PSX ( 0 )
+#define CPU_R3000 ( 1 )
+#define CPU_R4000 ( 2 )
+
+static UINT8 *filebuf;
+static UINT32 offset;
+static UINT8 order[] = { 0, 1, 2, 3 };
+
+static const char *const Options[]=
+{
+ "begin", "end", "offset", "order", "format", "cpu", 0
+};
+
+static void usage (void)
+{
+ fprintf( stderr,
+ "Usage: DISMIPS [options] <filename>\n\n"
+ "Available options are:\n"
+ " -begin - Specify begin offset in file to disassemble in bytes [0]\n"
+ " -end - Specify end offset in file to disassemble in bytes [none]\n"
+ " -offset - Specify address to load program in bytes [0]\n"
+ " -order - Specify byte order [0123]\n"
+ " -format - Specify file format bin|psx [bin]\n"
+ " -cpu - Specify cpu psx|r3000|r4000 [psx]\n\n"
+ "All values should be entered in hexadecimal\n" );
+ exit( 1 );
+}
+
+int main( int argc, char *argv[] )
+{
+ FILE *f;
+ UINT8 i;
+ UINT8 j;
+ UINT8 n;
+ UINT8 p;
+ UINT32 begin;
+ UINT32 end;
+ UINT32 filelen;
+ UINT32 len;
+ UINT32 pc;
+ char buffer[ 80 ];
+ char *filename;
+ UINT32 format;
+ UINT32 cpu;
+
+ filename = NULL;
+ begin = 0;
+ end = 0xffffffff;
+ format = FORMAT_BIN;
+ cpu = CPU_PSX;
+
+ n = 0;
+ for( i = 1; i < argc; i++ )
+ {
+ if( argv[ i ][ 0 ] != '-' )
+ {
+ switch( n )
+ {
+ case 0:
+ filename = argv[ i ];
+ break;
+ default:
+ usage();
+ break;
+ }
+ n++;
+ }
+ else
+ {
+ for( j = 0; Options[ j ]; j++ )
+ {
+ if( strcmp( argv[ i ] + 1, Options[ j ] ) == 0 )
+ {
+ break;
+ }
+ }
+ switch( j )
+ {
+ case 0:
+ i++;
+ if( i > argc )
+ {
+ usage();
+ }
+ begin = strtoul( argv[ i ], 0, 16 );
+ break;
+ case 1:
+ i++;
+ if( i > argc )
+ {
+ usage();
+ }
+ end = strtoul( argv[ i ], 0, 16 );
+ break;
+ case 2:
+ i++;
+ if( i > argc )
+ {
+ usage();
+ }
+ offset = strtoul( argv[ i ], 0, 16 );
+ break;
+ case 3:
+ i++;
+ if( i > argc )
+ {
+ usage();
+ }
+ if( strlen( argv[ i ] ) != 4 )
+ {
+ usage();
+ }
+ for( p = 0; p < 4; p++ )
+ {
+ if( argv[ i ][ p ] < '0' || argv[ i ][ p ] > '3' )
+ {
+ usage();
+ }
+ order[ p ] = argv[ i ][ p ] - '0';
+ }
+ break;
+ case 4:
+ i++;
+ if( i > argc )
+ {
+ usage();
+ }
+ if( mame_stricmp( argv[ i ], "bin" ) == 0 )
+ {
+ format = FORMAT_BIN;
+ }
+ else if( mame_stricmp( argv[ i ], "psx" ) == 0 )
+ {
+ format = FORMAT_PSX;
+ }
+ else
+ {
+ usage();
+ }
+ break;
+ case 5:
+ i++;
+ if( i > argc )
+ {
+ usage();
+ }
+ if( mame_stricmp( argv[ i ], "psx" ) == 0 )
+ {
+ cpu = CPU_PSX;
+ }
+ else if( mame_stricmp( argv[ i ], "r3000" ) == 0 )
+ {
+ cpu = CPU_R3000;
+ }
+ else if( mame_stricmp( argv[ i ], "r4000" ) == 0 )
+ {
+ cpu = CPU_R4000;
+ }
+ else
+ {
+ usage();
+ }
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+ }
+
+ if (!filename)
+ {
+ usage();
+ return 1;
+ }
+ f=fopen (filename,"rb");
+ if (!f)
+ {
+ printf ("Unable to open %s\n",filename);
+ return 2;
+ }
+ fseek (f,0,SEEK_END);
+ filelen=ftell (f);
+
+ if( format == FORMAT_PSX )
+ {
+ fseek( f, 0, SEEK_SET );
+ if( fread( &m_psxexe_header, 1, sizeof( m_psxexe_header ), f ) != sizeof( m_psxexe_header ) )
+ {
+ fprintf( stderr, "error reading ps-x exe header\n" );
+ fclose( f );
+ return 3;
+ }
+ if( memcmp( m_psxexe_header.id, "PS-X EXE", sizeof( m_psxexe_header.id ) ) != 0 )
+ {
+ fprintf( stderr, "invalid ps-x exe header\n" );
+ fclose( f );
+ return 3;
+ }
+ printf( "_start = $%08x\n\n", m_psxexe_header.pc0 );
+ if( offset == 0 )
+ {
+ offset = m_psxexe_header.t_addr;
+ }
+ if( begin == 0 )
+ {
+ begin = sizeof( m_psxexe_header );
+ }
+ if( end == 0xffffffff )
+ {
+ end = sizeof( m_psxexe_header ) + m_psxexe_header.t_size;
+ }
+ }
+
+ fseek (f,begin,SEEK_SET);
+ len=(filelen>end)? (end-begin+1):(filelen-begin);
+ filebuf=(UINT8 *)malloc(len+16);
+ if (!filebuf)
+ {
+ printf ("Memory allocation error\n");
+ fclose (f);
+ return 3;
+ }
+ memset (filebuf,0,len+16);
+ if (fread(filebuf,1,len,f)!=len)
+ {
+ printf ("Read error\n");
+ fclose (f);
+ free (filebuf);
+ return 4;
+ }
+ fclose (f);
+
+ pc = 0;
+ while( pc < len )
+ {
+ UINT8 op0 = filebuf[ pc + order[ 0 ] ];
+ UINT8 op1 = filebuf[ pc + order[ 1 ] ];
+ UINT8 op2 = filebuf[ pc + order[ 2 ] ];
+ UINT8 op3 = filebuf[ pc + order[ 3 ] ];
+ filebuf[ pc + 0 ] = op0;
+ filebuf[ pc + 1 ] = op1;
+ filebuf[ pc + 2 ] = op2;
+ filebuf[ pc + 3 ] = op3;
+
+ pc += 4;
+ }
+
+ pc = 0;
+ while( pc < len )
+ {
+ switch( cpu )
+ {
+ case CPU_PSX:
+ i = DasmPSXCPU( NULL, buffer, pc + offset, filebuf + pc );
+ break;
+ case CPU_R3000:
+ {
+ legacy_cpu_device *device = NULL;
+ int options = 0;
+ UINT8 *opram = filebuf + pc;
+ UINT8 *oprom = opram;
+ i = CPU_DISASSEMBLE_CALL( r3000le );
+ }
+ break;
+ case CPU_R4000:
+ {
+ UINT8 *opram = filebuf + pc;
+ UINT32 op = ( opram[ 3 ] << 24 ) | ( opram[ 2 ] << 16 ) | ( opram[ 1 ] << 8 ) | ( opram[ 0 ] << 0 );
+ i = dasmmips3( buffer, pc + offset, op );
+ }
+ break;
+ }
+
+ i &= DASMFLAG_LENGTHMASK;
+
+ printf( "%08x: ", pc + offset );
+ for( j = 0; j < i; j++ )
+ {
+ printf( "%02x ", filebuf[ pc ] );
+ pc++;
+ }
+ while( j < 10 )
+ {
+ printf( " " );
+ j++;
+ }
+ printf( "%s\n", buffer );
+ }
+ free (filebuf);
+ return 0;
+}
+
+void *malloc_file_line(size_t size, const char *file, int line)
+{
+ // allocate the memory and fail if we can't
+ return osd_malloc(size);
+}
+
+void *malloc_array_file_line(size_t size, const char *file, int line)
+{
+ // allocate the memory and fail if we can't
+ return osd_malloc_array(size);
+}
+
+void free_file_line( void *memory, const char *file, int line )
+{
+ osd_free( memory );
+}
+
+void osd_free( void *memory )
+{
+#undef free
+ free( memory );
+}
+
+void *osd_malloc( size_t size )
+{
+#undef malloc
+ return malloc( size );
+}
diff --git a/trunk/src/emu/cpu/psx/dismips.mak b/trunk/src/emu/cpu/psx/dismips.mak
new file mode 100644
index 00000000000..a3a8da4d873
--- /dev/null
+++ b/trunk/src/emu/cpu/psx/dismips.mak
@@ -0,0 +1,2 @@
+..\..\..\..\dismips.exe: dismips.c psxdasm.c r3kdasm.c mips3dsm.c ../../../lib/util/corestr.c
+ gcc -O3 -x c++ -Wall -Wno-sign-compare -I../../../emu -I../../../osd -I../../../lib/util -DINLINE="static __inline__" -DSTANDALONE -DLSB_FIRST dismips.c psxdasm.c r3kdasm.c mips3dsm.c ../../../lib/util/corestr.c -o../../../../dismips
diff --git a/trunk/src/emu/cpu/psx/dma.c b/trunk/src/emu/cpu/psx/dma.c
new file mode 100644
index 00000000000..a877bb9a142
--- /dev/null
+++ b/trunk/src/emu/cpu/psx/dma.c
@@ -0,0 +1,421 @@
+/*
+ * PlayStation DMA emulator
+ *
+ * Copyright 2003-2011 smf
+ *
+ */
+
+#include "emu.h"
+#include "dma.h"
+#include "includes/psx.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 device_type PSX_DMA = &device_creator<psxdma_device>;
+
+psxdma_device::psxdma_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, PSX_DMA, "PSX DMA", tag, owner, clock)
+{
+}
+
+void psxdma_device::device_reset()
+{
+ int n;
+
+ n_dpcp = 0;
+ n_dicr = 0;
+
+ for( n = 0; n < 7; n++ )
+ {
+ dma_stop_timer( n );
+ }
+}
+
+void psxdma_device::device_post_load()
+{
+ int n;
+
+ for( n = 0; n < 7; n++ )
+ {
+ dma_timer_adjust( n );
+ }
+}
+
+void psxdma_device::device_start()
+{
+ for( int index = 0; index < 7; index++ )
+ {
+ psx_dma_channel *dma = &channel[ index ];
+
+ dma->timer = machine().scheduler().timer_alloc( timer_expired_delegate( FUNC( psxdma_device::dma_finished_callback ), this) );
+
+ machine().save().save_item( "psxdma", tag(), index, NAME( dma->n_base ) );
+ machine().save().save_item( "psxdma", tag(), index, NAME( dma->n_blockcontrol ) );
+ machine().save().save_item( "psxdma", tag(), index, NAME( dma->n_channelcontrol ) );
+ machine().save().save_item( "psxdma", tag(), index, NAME( dma->n_ticks ) );
+ machine().save().save_item( "psxdma", tag(), index, NAME( dma->b_running ) );
+ }
+
+ save_item( NAME(n_dpcp) );
+ save_item( NAME(n_dicr) );
+}
+
+void psxdma_device::dma_start_timer( int index, UINT32 n_ticks )
+{
+ psx_dma_channel *dma = &channel[ index ];
+
+ dma->timer->adjust( attotime::from_hz(33868800) * n_ticks, index);
+ dma->n_ticks = n_ticks;
+ dma->b_running = 1;
+}
+
+void psxdma_device::dma_stop_timer( int index )
+{
+ psx_dma_channel *dma = &channel[ index ];
+
+ dma->timer->adjust( attotime::never);
+ dma->b_running = 0;
+}
+
+void psxdma_device::dma_timer_adjust( int index )
+{
+ psx_dma_channel *dma = &channel[ index ];
+
+ if( dma->b_running )
+ {
+ dma_start_timer( index, dma->n_ticks );
+ }
+ else
+ {
+ dma_stop_timer( index );
+ }
+}
+
+void psxdma_device::dma_interrupt_update()
+{
+ int n_int;
+ int n_mask;
+
+ n_int = ( n_dicr >> 24 ) & 0x7f;
+ n_mask = ( n_dicr >> 16 ) & 0xff;
+
+ if( ( n_mask & 0x80 ) != 0 && ( n_int & n_mask ) != 0 )
+ {
+ verboselog( machine(), 2, "dma_interrupt_update( %02x, %02x ) interrupt triggered\n", n_int, n_mask );
+ n_dicr |= 0x80000000;
+ psx_irq_set( machine(), PSX_IRQ_DMA );
+ }
+ else if( n_int != 0 )
+ {
+ verboselog( machine(), 2, "dma_interrupt_update( %02x, %02x ) interrupt not enabled\n", n_int, n_mask );
+ }
+ n_dicr &= 0x00ffffff | ( n_dicr << 8 );
+}
+
+void psxdma_device::dma_finished( int index )
+{
+ psx_state *p_psx = machine().driver_data<psx_state>();
+ UINT32 *p_n_psxram = p_psx->m_p_n_psxram;
+
+ psx_dma_channel *dma = &channel[ index ];
+
+ if( dma->n_channelcontrol == 0x01000401 && index == 2 )
+ {
+ UINT32 n_size;
+ UINT32 n_total;
+ UINT32 n_address = ( dma->n_base & 0xffffff );
+ UINT32 n_adrmask = p_psx->m_n_psxramsize - 1;
+ UINT32 n_nextaddress;
+
+ if( n_address != 0xffffff )
+ {
+ n_total = 0;
+ for( ;; )
+ {
+ if( n_address == 0xffffff )
+ {
+ dma->n_base = n_address;
+ dma_start_timer( index, 19000 );
+ return;
+ }
+ if( n_total > 65535 )
+ {
+ dma->n_base = n_address;
+ //FIXME:
+ // 16000 below is based on try and error.
+ // Mametesters.org: sfex20103red
+ //dma_start_timer( index, 16 );
+ dma_start_timer( index, 16000 );
+ return;
+ }
+ n_address &= n_adrmask;
+ n_nextaddress = p_n_psxram[ n_address / 4 ];
+ n_size = n_nextaddress >> 24;
+ dma->fn_write( n_address + 4, n_size );
+ //FIXME:
+ // The following conditions will cause an endless loop.
+ // If stopping the transfer is correct I cannot judge
+ // The patch is meant as a hint for somebody who knows
+ // the hardware.
+ // Mametesters.org: psyforce0105u5red, raystorm0111u1red
+ if ((n_nextaddress & 0xffffff) != 0xffffff)
+ if (n_address == p_n_psxram[ (n_nextaddress & 0xffffff) / 4])
+ break;
+ if (n_address == (n_nextaddress & 0xffffff) )
+ break;
+ n_address = ( n_nextaddress & 0xffffff );
+
+ n_total += ( n_size + 1 );
+ }
+ }
+ }
+
+ dma->n_channelcontrol &= ~( ( 1L << 0x18 ) | ( 1L << 0x1c ) );
+
+ n_dicr |= 1 << ( 24 + index );
+ dma_interrupt_update();
+ dma_stop_timer( index );
+}
+
+void psxdma_device::dma_finished_callback(void *ptr, int param)
+{
+ dma_finished(param);
+}
+
+void psxdma_device::install_read_handler( int index, psx_dma_read_delegate p_fn_dma_read )
+{
+ channel[ index ].fn_read = p_fn_dma_read;
+}
+
+void psxdma_device::install_write_handler( int index, psx_dma_read_delegate p_fn_dma_write )
+{
+ channel[ index ].fn_write = p_fn_dma_write;
+}
+
+WRITE32_MEMBER( psxdma_device::write )
+{
+ psx_state *p_psx = machine().driver_data<psx_state>();
+
+ UINT32 *p_n_psxram = p_psx->m_p_n_psxram;
+ int index = offset / 4;
+ psx_dma_channel *dma = &channel[ index ];
+
+ if( index < 7 )
+ {
+ switch( offset % 4 )
+ {
+ case 0:
+ verboselog( machine(), 2, "dmabase( %d ) = %08x\n", index, data );
+ dma->n_base = data;
+ break;
+ case 1:
+ verboselog( machine(), 2, "dmablockcontrol( %d ) = %08x\n", index, data );
+ dma->n_blockcontrol = data;
+ break;
+ case 2:
+ verboselog( machine(), 2, "dmachannelcontrol( %d ) = %08x\n", index, data );
+ dma->n_channelcontrol = data;
+ if( ( dma->n_channelcontrol & ( 1L << 0x18 ) ) != 0 && ( n_dpcp & ( 1 << ( 3 + ( index * 4 ) ) ) ) != 0 )
+ {
+ INT32 n_size;
+ UINT32 n_address;
+ UINT32 n_nextaddress;
+ UINT32 n_adrmask;
+
+ n_adrmask = p_psx->m_n_psxramsize - 1;
+
+ n_address = ( dma->n_base & n_adrmask );
+ n_size = dma->n_blockcontrol;
+ if( ( dma->n_channelcontrol & 0x200 ) != 0 )
+ {
+ UINT32 n_ba;
+ n_ba = dma->n_blockcontrol >> 16;
+ if( n_ba == 0 )
+ {
+ n_ba = 0x10000;
+ }
+ n_size = ( n_size & 0xffff ) * n_ba;
+ }
+
+ if( dma->n_channelcontrol == 0x01000000 &&
+ !dma->fn_read.isnull() )
+ {
+ verboselog( machine(), 1, "dma %d read block %08x %08x\n", index, n_address, n_size );
+ dma->fn_read( n_address, n_size );
+ dma_finished( index );
+ }
+ else if (dma->n_channelcontrol == 0x11000000 && // CD DMA
+ !dma->fn_read.isnull() )
+ {
+ verboselog( machine(), 1, "dma %d read block %08x %08x\n", index, n_address, n_size );
+
+ // pSX's CD DMA size calc formula
+ int oursize = (dma->n_blockcontrol>>16);
+ oursize = (oursize > 1) ? oursize : 1;
+ oursize *= (dma->n_blockcontrol&0xffff);
+
+ dma->fn_read( n_address, oursize );
+ dma_finished( index );
+ }
+ else if( dma->n_channelcontrol == 0x01000200 &&
+ !dma->fn_read.isnull() )
+ {
+ verboselog( machine(), 1, "dma %d read block %08x %08x\n", index, n_address, n_size );
+ dma->fn_read( n_address, n_size );
+ if( index == 1 )
+ {
+ dma_start_timer( index, 26000 );
+ }
+ else
+ {
+ dma_finished( index );
+ }
+ }
+ else if( dma->n_channelcontrol == 0x01000201 &&
+ !dma->fn_write.isnull() )
+ {
+ verboselog( machine(), 1, "dma %d write block %08x %08x\n", index, n_address, n_size );
+ dma->fn_write( n_address, n_size );
+ dma_finished( index );
+ }
+ else if( dma->n_channelcontrol == 0x11050100 &&
+ !dma->fn_write.isnull() )
+ {
+ /* todo: check this is a write not a read... */
+ verboselog( machine(), 1, "dma %d write block %08x %08x\n", index, n_address, n_size );
+ dma->fn_write( n_address, n_size );
+ dma_finished( index );
+ }
+ else if( dma->n_channelcontrol == 0x11150100 &&
+ !dma->fn_write.isnull() )
+ {
+ /* todo: check this is a write not a read... */
+ verboselog( machine(), 1, "dma %d write block %08x %08x\n", index, n_address, n_size );
+ dma->fn_write( n_address, n_size );
+ dma_finished( index );
+ }
+ else if( dma->n_channelcontrol == 0x01000401 &&
+ index == 2 &&
+ !dma->fn_write.isnull() )
+ {
+ verboselog( machine(), 1, "dma %d write linked list %08x\n",
+ index, dma->n_base );
+
+ dma_finished( index );
+ }
+ else if( dma->n_channelcontrol == 0x11000002 &&
+ index == 6 )
+ {
+ verboselog( machine(), 1, "dma 6 reverse clear %08x %08x\n",
+ dma->n_base, dma->n_blockcontrol );
+ if( n_size > 0 )
+ {
+ n_size--;
+ while( n_size > 0 )
+ {
+ n_nextaddress = ( n_address - 4 ) & 0xffffff;
+ p_n_psxram[ n_address / 4 ] = n_nextaddress;
+ n_address = n_nextaddress;
+ n_size--;
+ }
+ p_n_psxram[ n_address / 4 ] = 0xffffff;
+ }
+ dma_start_timer( index, 2150 );
+ }
+ else
+ {
+ verboselog( machine(), 1, "dma %d unknown mode %08x\n", index, dma->n_channelcontrol );
+ }
+ }
+ else if( dma->n_channelcontrol != 0 )
+ {
+ verboselog( machine(), 1, "psx_dma_w( %04x, %08x, %08x ) channel not enabled\n", offset, dma->n_channelcontrol, mem_mask );
+ }
+ break;
+ default:
+ verboselog( machine(), 1, "psx_dma_w( %04x, %08x, %08x ) Unknown dma channel register\n", offset, data, mem_mask );
+ break;
+ }
+ }
+ else
+ {
+ switch( offset % 4 )
+ {
+ case 0x0:
+ verboselog( machine(), 1, "psx_dma_w( %04x, %08x, %08x ) dpcp\n", offset, data, mem_mask );
+ n_dpcp = ( n_dpcp & ~mem_mask ) | data;
+ break;
+ case 0x1:
+
+ n_dicr = ( n_dicr & ( 0x80000000 | ~mem_mask ) ) |
+ ( n_dicr & ~data & 0x7f000000 & mem_mask ) |
+ ( data & 0x00ffffff & mem_mask );
+
+ if( ( n_dicr & 0x80000000 ) != 0 && ( n_dicr & 0x7f000000 ) == 0 )
+ {
+ verboselog( machine(), 2, "dma interrupt cleared\n" );
+ n_dicr &= ~0x80000000;
+ }
+
+ verboselog( machine(), 1, "psx_dma_w( %04x, %08x, %08x ) dicr -> %08x\n", offset, data, mem_mask, n_dicr );
+ break;
+ default:
+ verboselog( machine(), 0, "psx_dma_w( %04x, %08x, %08x ) Unknown dma control register\n", offset, data, mem_mask );
+ break;
+ }
+ }
+}
+
+READ32_MEMBER( psxdma_device::read )
+{
+ int index = offset / 4;
+ psx_dma_channel *dma = &channel[ index ];
+
+ if( index < 7 )
+ {
+ switch( offset % 4 )
+ {
+ case 0:
+ verboselog( machine(), 1, "psx_dma_r dmabase[ %d ] ( %08x )\n", index, dma->n_base );
+ return dma->n_base;
+ case 1:
+ verboselog( machine(), 1, "psx_dma_r dmablockcontrol[ %d ] ( %08x )\n", index, dma->n_blockcontrol );
+ return dma->n_blockcontrol;
+ case 2:
+ verboselog( machine(), 1, "psx_dma_r dmachannelcontrol[ %d ] ( %08x )\n", index, dma->n_channelcontrol );
+ return dma->n_channelcontrol;
+ default:
+ verboselog( machine(), 0, "psx_dma_r( %08x, %08x ) Unknown dma channel register\n", offset, mem_mask );
+ break;
+ }
+ }
+ else
+ {
+ switch( offset % 4 )
+ {
+ case 0x0:
+ verboselog( machine(), 1, "psx_dma_r dpcp ( %08x )\n", n_dpcp );
+ return n_dpcp;
+ case 0x1:
+ verboselog( machine(), 1, "psx_dma_r dicr ( %08x )\n", n_dicr );
+ return n_dicr;
+ default:
+ verboselog( machine(), 0, "psx_dma_r( %08x, %08x ) Unknown dma control register\n", offset, mem_mask );
+ break;
+ }
+ }
+ return 0;
+}
diff --git a/trunk/src/emu/cpu/psx/dma.h b/trunk/src/emu/cpu/psx/dma.h
new file mode 100644
index 00000000000..e40dfc20be8
--- /dev/null
+++ b/trunk/src/emu/cpu/psx/dma.h
@@ -0,0 +1,64 @@
+/*
+ * PlayStation DMA emulator
+ *
+ * Copyright 2003-2011 smf
+ *
+ */
+
+#pragma once
+
+#ifndef __PSXDMA_H__
+#define __PSXDMA_H__
+
+#include "emu.h"
+
+extern const device_type PSX_DMA;
+
+typedef delegate<void (UINT32, INT32)> psx_dma_read_delegate;
+typedef delegate<void (UINT32, INT32)> psx_dma_write_delegate;
+
+typedef struct _psx_dma_channel psx_dma_channel;
+struct _psx_dma_channel
+{
+ UINT32 n_base;
+ UINT32 n_blockcontrol;
+ UINT32 n_channelcontrol;
+ emu_timer *timer;
+ psx_dma_read_delegate fn_read;
+ psx_dma_write_delegate fn_write;
+ UINT32 n_ticks;
+ UINT32 b_running;
+};
+
+class psxdma_device : public device_t
+{
+public:
+ psxdma_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ void install_read_handler( int n_channel, psx_dma_read_delegate p_fn_dma_read );
+ void install_write_handler( int n_channel, psx_dma_read_delegate p_fn_dma_write );
+
+ WRITE32_MEMBER( write );
+ READ32_MEMBER( read );
+
+protected:
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_post_load();
+
+private:
+ void dma_start_timer( int n_channel, UINT32 n_ticks );
+ void dma_stop_timer( int n_channel );
+ void dma_timer_adjust( int n_channel );
+ void dma_interrupt_update();
+ void dma_finished( int n_channel );
+ void dma_finished_callback(void *ptr, int param);
+ void write( offs_t offset, UINT32 data, UINT32 mem_mask );
+ UINT32 read( offs_t offset, UINT32 mem_mask );
+
+ psx_dma_channel channel[7];
+ UINT32 n_dpcp;
+ UINT32 n_dicr;
+};
+
+#endif
diff --git a/trunk/src/emu/cpu/psx/gte.c b/trunk/src/emu/cpu/psx/gte.c
new file mode 100644
index 00000000000..4b39732a08a
--- /dev/null
+++ b/trunk/src/emu/cpu/psx/gte.c
@@ -0,0 +1,2980 @@
+/*
+ * PlayStation Geometry Transformation Engine emulator
+ *
+ * Copyright 2003-2011 smf
+ *
+ * divider reverse engineering by pSXAuthor.
+ *
+ */
+
+#include "emu.h"
+#include "gte.h"
+
+#if 0
+void ATTR_PRINTF(2,3) GTELOG( UINT32 pc, const char *a,...)
+{
+ va_list va;
+ char s_text[ 1024 ];
+ va_start( va, a );
+ vsprintf( s_text, a, va );
+ va_end( va );
+ logerror( "%08x: GTE: %s\n", pc, s_text );
+}
+#else
+INLINE void ATTR_PRINTF(2,3) GTELOG( UINT32 pc, const char *a, ...) {}
+#endif
+
+
+#define VX( n ) ( n < 3 ? m_cp2dr[ n << 1 ].sw.l : m_cp2dr[ 9 ].sw.l )
+#define VY( n ) ( n < 3 ? m_cp2dr[ n << 1 ].sw.h : m_cp2dr[ 10 ].sw.l )
+#define VZ( n ) ( n < 3 ? m_cp2dr[ ( n << 1 ) + 1 ].sw.l : m_cp2dr[ 11 ].sw.l )
+#define MX11( n ) ( n < 3 ? m_cp2cr[ ( n << 3 ) ].sw.l : 0 )
+#define MX12( n ) ( n < 3 ? m_cp2cr[ ( n << 3 ) ].sw.h : 0 )
+#define MX13( n ) ( n < 3 ? m_cp2cr[ ( n << 3 ) + 1 ].sw.l : 0 )
+#define MX21( n ) ( n < 3 ? m_cp2cr[ ( n << 3 ) + 1 ].sw.h : 0 )
+#define MX22( n ) ( n < 3 ? m_cp2cr[ ( n << 3 ) + 2 ].sw.l : 0 )
+#define MX23( n ) ( n < 3 ? m_cp2cr[ ( n << 3 ) + 2 ].sw.h : 0 )
+#define MX31( n ) ( n < 3 ? m_cp2cr[ ( n << 3 ) + 3 ].sw.l : 0 )
+#define MX32( n ) ( n < 3 ? m_cp2cr[ ( n << 3 ) + 3 ].sw.h : 0 )
+#define MX33( n ) ( n < 3 ? m_cp2cr[ ( n << 3 ) + 4 ].sw.l : 0 )
+#define CV1( n ) ( n < 3 ? m_cp2cr[ ( n << 3 ) + 5 ].sd : 0 )
+#define CV2( n ) ( n < 3 ? m_cp2cr[ ( n << 3 ) + 6 ].sd : 0 )
+#define CV3( n ) ( n < 3 ? m_cp2cr[ ( n << 3 ) + 7 ].sd : 0 )
+
+#define VXY0 ( m_cp2dr[ 0 ].d )
+#define VX0 ( m_cp2dr[ 0 ].sw.l )
+#define VY0 ( m_cp2dr[ 0 ].sw.h )
+#define VZ0 ( m_cp2dr[ 1 ].sw.l )
+#define VXY1 ( m_cp2dr[ 2 ].d )
+#define VX1 ( m_cp2dr[ 2 ].w.l )
+#define VY1 ( m_cp2dr[ 2 ].w.h )
+#define VZ1 ( m_cp2dr[ 3 ].w.l )
+#define VXY2 ( m_cp2dr[ 4 ].d )
+#define VX2 ( m_cp2dr[ 4 ].w.l )
+#define VY2 ( m_cp2dr[ 4 ].w.h )
+#define VZ2 ( m_cp2dr[ 5 ].w.l )
+#define RGB ( m_cp2dr[ 6 ].d )
+#define R ( m_cp2dr[ 6 ].b.l )
+#define G ( m_cp2dr[ 6 ].b.h )
+#define B ( m_cp2dr[ 6 ].b.h2 )
+#define CODE ( m_cp2dr[ 6 ].b.h3 )
+#define OTZ ( m_cp2dr[ 7 ].w.l )
+#define IR0 ( m_cp2dr[ 8 ].sw.l )
+#define IR1 ( m_cp2dr[ 9 ].sw.l )
+#define IR2 ( m_cp2dr[ 10 ].sw.l )
+#define IR3 ( m_cp2dr[ 11 ].sw.l )
+#define SXY0 ( m_cp2dr[ 12 ].d )
+#define SX0 ( m_cp2dr[ 12 ].sw.l )
+#define SY0 ( m_cp2dr[ 12 ].sw.h )
+#define SXY1 ( m_cp2dr[ 13 ].d )
+#define SX1 ( m_cp2dr[ 13 ].sw.l )
+#define SY1 ( m_cp2dr[ 13 ].sw.h )
+#define SXY2 ( m_cp2dr[ 14 ].d )
+#define SX2 ( m_cp2dr[ 14 ].sw.l )
+#define SY2 ( m_cp2dr[ 14 ].sw.h )
+#define SXYP ( m_cp2dr[ 15 ].d )
+#define SXP ( m_cp2dr[ 15 ].sw.l )
+#define SYP ( m_cp2dr[ 15 ].sw.h )
+#define SZ0 ( m_cp2dr[ 16 ].w.l )
+#define SZ1 ( m_cp2dr[ 17 ].w.l )
+#define SZ2 ( m_cp2dr[ 18 ].w.l )
+#define SZ3 ( m_cp2dr[ 19 ].w.l )
+#define RGB0 ( m_cp2dr[ 20 ].d )
+#define R0 ( m_cp2dr[ 20 ].b.l )
+#define G0 ( m_cp2dr[ 20 ].b.h )
+#define B0 ( m_cp2dr[ 20 ].b.h2 )
+#define CD0 ( m_cp2dr[ 20 ].b.h3 )
+#define RGB1 ( m_cp2dr[ 21 ].d )
+#define R1 ( m_cp2dr[ 21 ].b.l )
+#define G1 ( m_cp2dr[ 21 ].b.h )
+#define B1 ( m_cp2dr[ 21 ].b.h2 )
+#define CD1 ( m_cp2dr[ 21 ].b.h3 )
+#define RGB2 ( m_cp2dr[ 22 ].d )
+#define R2 ( m_cp2dr[ 22 ].b.l )
+#define G2 ( m_cp2dr[ 22 ].b.h )
+#define B2 ( m_cp2dr[ 22 ].b.h2 )
+#define CD2 ( m_cp2dr[ 22 ].b.h3 )
+#define RES1 ( m_cp2dr[ 23 ].d )
+#define MAC0 ( m_cp2dr[ 24 ].sd )
+#define MAC1 ( m_cp2dr[ 25 ].sd )
+#define MAC2 ( m_cp2dr[ 26 ].sd )
+#define MAC3 ( m_cp2dr[ 27 ].sd )
+#define IRGB ( m_cp2dr[ 28 ].d )
+#define ORGB ( m_cp2dr[ 29 ].d )
+#define LZCS ( m_cp2dr[ 30 ].d )
+#define LZCR ( m_cp2dr[ 31 ].d )
+
+#define R11 ( m_cp2cr[ 0 ].sw.l )
+#define R12 ( m_cp2cr[ 0 ].sw.h )
+#define R13 ( m_cp2cr[ 1 ].sw.l )
+#define R21 ( m_cp2cr[ 1 ].sw.h )
+#define R22 ( m_cp2cr[ 2 ].sw.l )
+#define R23 ( m_cp2cr[ 2 ].sw.h )
+#define R31 ( m_cp2cr[ 3 ].sw.l )
+#define R32 ( m_cp2cr[ 3 ].sw.h )
+#define R33 ( m_cp2cr[ 4 ].sw.l )
+#define TRX ( m_cp2cr[ 5 ].sd )
+#define TRY ( m_cp2cr[ 6 ].sd )
+#define TRZ ( m_cp2cr[ 7 ].sd )
+#define L11 ( m_cp2cr[ 8 ].sw.l )
+#define L12 ( m_cp2cr[ 8 ].sw.h )
+#define L13 ( m_cp2cr[ 9 ].sw.l )
+#define L21 ( m_cp2cr[ 9 ].sw.h )
+#define L22 ( m_cp2cr[ 10 ].sw.l )
+#define L23 ( m_cp2cr[ 10 ].sw.h )
+#define L31 ( m_cp2cr[ 11 ].sw.l )
+#define L32 ( m_cp2cr[ 11 ].sw.h )
+#define L33 ( m_cp2cr[ 12 ].sw.l )
+#define RBK ( m_cp2cr[ 13 ].sd )
+#define GBK ( m_cp2cr[ 14 ].sd )
+#define BBK ( m_cp2cr[ 15 ].sd )
+#define LR1 ( m_cp2cr[ 16 ].sw.l )
+#define LR2 ( m_cp2cr[ 16 ].sw.h )
+#define LR3 ( m_cp2cr[ 17 ].sw.l )
+#define LG1 ( m_cp2cr[ 17 ].sw.h )
+#define LG2 ( m_cp2cr[ 18 ].sw.l )
+#define LG3 ( m_cp2cr[ 18 ].sw.h )
+#define LB1 ( m_cp2cr[ 19 ].sw.l )
+#define LB2 ( m_cp2cr[ 19 ].sw.h )
+#define LB3 ( m_cp2cr[ 20 ].sw.l )
+#define RFC ( m_cp2cr[ 21 ].sd )
+#define GFC ( m_cp2cr[ 22 ].sd )
+#define BFC ( m_cp2cr[ 23 ].sd )
+#define OFX ( m_cp2cr[ 24 ].sd )
+#define OFY ( m_cp2cr[ 25 ].sd )
+#define H ( m_cp2cr[ 26 ].sw.l )
+#define DQA ( m_cp2cr[ 27 ].sw.l )
+#define DQB ( m_cp2cr[ 28 ].sd )
+#define ZSF3 ( m_cp2cr[ 29 ].sw.l )
+#define ZSF4 ( m_cp2cr[ 30 ].sw.l )
+#define FLAG ( m_cp2cr[ 31 ].d )
+
+INT32 gte::LIM( INT32 value, INT32 max, INT32 min, UINT32 flag )
+{
+ if( value > max )
+ {
+ FLAG |= flag;
+ return max;
+ }
+ else if( value < min )
+ {
+ FLAG |= flag;
+ return min;
+ }
+ return value;
+}
+
+UINT32 gte::getcp2dr( UINT32 pc, int reg )
+{
+ switch( reg )
+ {
+ case 1:
+ case 3:
+ case 5:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ m_cp2dr[ reg ].d = (INT32)m_cp2dr[ reg ].sw.l;
+ break;
+
+ case 7:
+ case 16:
+ case 17:
+ case 18:
+ case 19:
+ m_cp2dr[ reg ].d = (UINT32)m_cp2dr[ reg ].w.l;
+ break;
+
+ case 15:
+ m_cp2dr[ reg ].d = SXY2;
+ break;
+
+ case 28:
+ case 29:
+ m_cp2dr[ reg ].d = LIM( IR1 >> 7, 0x1f, 0, 0 ) | ( LIM( IR2 >> 7, 0x1f, 0, 0 ) << 5 ) | ( LIM( IR3 >> 7, 0x1f, 0, 0 ) << 10 );
+ break;
+ }
+
+ GTELOG( pc, "get CP2DR%u=%08x", reg, m_cp2dr[ reg ].d );
+ return m_cp2dr[ reg ].d;
+}
+
+void gte::setcp2dr( UINT32 pc, int reg, UINT32 value )
+{
+ GTELOG( pc, "set CP2DR%u=%08x", reg, value );
+
+ switch( reg )
+ {
+ case 15:
+ SXY0 = SXY1;
+ SXY1 = SXY2;
+ SXY2 = value;
+ break;
+
+ case 28:
+ IR1 = ( value & 0x1f ) << 7;
+ IR2 = ( value & 0x3e0 ) << 2;
+ IR3 = ( value & 0x7c00 ) >> 3;
+ break;
+
+ case 30:
+ {
+ UINT32 lzcs = value;
+ UINT32 lzcr = 0;
+
+ if( ( lzcs & 0x80000000 ) == 0 )
+ {
+ lzcs = ~lzcs;
+ }
+ while( ( lzcs & 0x80000000 ) != 0 )
+ {
+ lzcr++;
+ lzcs <<= 1;
+ }
+ LZCR = lzcr;
+ break;
+ }
+
+ case 31:
+ value = m_cp2dr[ reg ].d;
+ break;
+ }
+
+ m_cp2dr[ reg ].d = value;
+}
+
+UINT32 gte::getcp2cr( UINT32 pc, int reg )
+{
+ GTELOG( pc, "get CP2CR%u=%08x", reg, m_cp2cr[ reg ].d );
+
+ return m_cp2cr[ reg ].d;
+}
+
+void gte::setcp2cr( UINT32 pc, int reg, UINT32 value )
+{
+ GTELOG( pc, "set CP2CR%u=%08x", reg, value );
+
+ switch( reg )
+ {
+ case 4:
+ case 12:
+ case 20:
+ case 26:
+ case 27:
+ case 29:
+ case 30:
+ value = (INT32)(INT16) value;
+ break;
+
+ case 31:
+ value = value & 0x7ffff000;
+ if( ( value & 0x7f87e000 ) != 0 )
+ {
+ value |= 0x80000000;
+ }
+ break;
+ }
+
+ m_cp2cr[ reg ].d = value;
+}
+
+INT64 gte::BOUNDS( INT64 n_value, INT64 n_max, int n_maxflag, INT64 n_min, int n_minflag )
+{
+ if( n_value > n_max )
+ {
+ FLAG |= n_maxflag;
+ }
+ else if( n_value < n_min )
+ {
+ FLAG |= n_minflag;
+ }
+ return n_value;
+}
+
+static const UINT16 reciprocals[ 32768 ]=
+{
+ 0x0,0xfffc,0xfff8,0xfff4,0xfff0,0xffec,0xffe8,0xffe4,0xffe0,0xffdc,0xffd8,0xffd4,0xffd0,0xffcc,0xffc8,0xffc4,
+ 0xffc0,0xffbc,0xffb8,0xffb4,0xffb0,0xffac,0xffa8,0xffa4,0xffa0,0xff9c,0xff98,0xff94,0xff90,0xff8c,0xff88,0xff84,
+ 0xff80,0xff7c,0xff78,0xff74,0xff70,0xff6c,0xff68,0xff64,0xff60,0xff5c,0xff58,0xff54,0xff50,0xff4c,0xff48,0xff44,
+ 0xff40,0xff3c,0xff38,0xff34,0xff30,0xff2c,0xff28,0xff24,0xff20,0xff1c,0xff18,0xff14,0xff10,0xff0c,0xff08,0xff04,
+ 0xff01,0xfefd,0xfef9,0xfef5,0xfef1,0xfeed,0xfee9,0xfee5,0xfee1,0xfedd,0xfed9,0xfed5,0xfed1,0xfecd,0xfec9,0xfec5,
+ 0xfec1,0xfebd,0xfeb9,0xfeb5,0xfeb1,0xfead,0xfea9,0xfea5,0xfea1,0xfe9d,0xfe99,0xfe95,0xfe91,0xfe8d,0xfe89,0xfe85,
+ 0xfe81,0xfe7e,0xfe7a,0xfe76,0xfe72,0xfe6e,0xfe6a,0xfe66,0xfe62,0xfe5e,0xfe5a,0xfe56,0xfe52,0xfe4e,0xfe4a,0xfe46,
+ 0xfe42,0xfe3e,0xfe3a,0xfe36,0xfe32,0xfe2e,0xfe2a,0xfe26,0xfe22,0xfe1e,0xfe1a,0xfe16,0xfe12,0xfe0e,0xfe0a,0xfe06,
+ 0xfe02,0xfdfe,0xfdfa,0xfdf6,0xfdf2,0xfdee,0xfdea,0xfde6,0xfde2,0xfdde,0xfdda,0xfdd6,0xfdd2,0xfdce,0xfdca,0xfdc6,
+ 0xfdc2,0xfdbe,0xfdba,0xfdb6,0xfdb2,0xfdae,0xfdaa,0xfda6,0xfda2,0xfd9e,0xfd9a,0xfd96,0xfd92,0xfd8e,0xfd8a,0xfd86,
+ 0xfd82,0xfd7f,0xfd7b,0xfd77,0xfd73,0xfd6f,0xfd6b,0xfd67,0xfd63,0xfd5f,0xfd5b,0xfd57,0xfd53,0xfd4f,0xfd4b,0xfd47,
+ 0xfd43,0xfd3f,0xfd3b,0xfd37,0xfd33,0xfd2f,0xfd2b,0xfd27,0xfd23,0xfd1f,0xfd1b,0xfd17,0xfd13,0xfd0f,0xfd0b,0xfd07,
+ 0xfd04,0xfd00,0xfcfc,0xfcf8,0xfcf4,0xfcf0,0xfcec,0xfce8,0xfce4,0xfce0,0xfcdc,0xfcd8,0xfcd4,0xfcd0,0xfccc,0xfcc8,
+ 0xfcc4,0xfcc0,0xfcbd,0xfcb9,0xfcb5,0xfcb1,0xfcad,0xfca9,0xfca5,0xfca1,0xfc9d,0xfc99,0xfc95,0xfc91,0xfc8d,0xfc89,
+ 0xfc87,0xfc83,0xfc7f,0xfc7b,0xfc77,0xfc73,0xfc6f,0xfc6b,0xfc67,0xfc63,0xfc5f,0xfc5b,0xfc57,0xfc53,0xfc4f,0xfc4b,
+ 0xfc47,0xfc43,0xfc40,0xfc3c,0xfc38,0xfc34,0xfc30,0xfc2c,0xfc28,0xfc24,0xfc20,0xfc1c,0xfc18,0xfc14,0xfc10,0xfc0c,
+ 0xfc08,0xfc04,0xfc00,0xfbfc,0xfbf8,0xfbf4,0xfbf0,0xfbec,0xfbe8,0xfbe4,0xfbe0,0xfbdc,0xfbd8,0xfbd4,0xfbd0,0xfbcc,
+ 0xfbc8,0xfbc4,0xfbc1,0xfbbd,0xfbb9,0xfbb5,0xfbb1,0xfbad,0xfba9,0xfba5,0xfba1,0xfb9d,0xfb99,0xfb95,0xfb91,0xfb8d,
+ 0xfb8b,0xfb87,0xfb83,0xfb7f,0xfb7b,0xfb77,0xfb73,0xfb6f,0xfb6b,0xfb67,0xfb63,0xfb5f,0xfb5b,0xfb57,0xfb53,0xfb4f,
+ 0xfb4b,0xfb47,0xfb43,0xfb40,0xfb3c,0xfb38,0xfb34,0xfb30,0xfb2c,0xfb28,0xfb24,0xfb20,0xfb1c,0xfb18,0xfb14,0xfb10,
+ 0xfb0d,0xfb09,0xfb05,0xfb01,0xfafd,0xfaf9,0xfaf5,0xfaf1,0xfaed,0xfae9,0xfae5,0xfae1,0xfadd,0xfad9,0xfad5,0xfad2,
+ 0xface,0xfaca,0xfac6,0xfac2,0xfabe,0xfaba,0xfab6,0xfab2,0xfaae,0xfaaa,0xfaa6,0xfaa2,0xfa9e,0xfa9a,0xfa96,0xfa92,
+ 0xfa8e,0xfa8a,0xfa86,0xfa82,0xfa7f,0xfa7b,0xfa77,0xfa73,0xfa6f,0xfa6b,0xfa67,0xfa65,0xfa61,0xfa5d,0xfa59,0xfa55,
+ 0xfa51,0xfa4d,0xfa49,0xfa45,0xfa41,0xfa3d,0xfa39,0xfa35,0xfa31,0xfa2d,0xfa2a,0xfa26,0xfa22,0xfa1e,0xfa1a,0xfa16,
+ 0xfa12,0xfa0e,0xfa0a,0xfa06,0xfa02,0xf9fe,0xf9fa,0xf9f6,0xf9f2,0xf9ee,0xf9ea,0xf9e6,0xf9e2,0xf9de,0xf9da,0xf9d6,
+ 0xf9d3,0xf9cf,0xf9cb,0xf9c7,0xf9c3,0xf9bf,0xf9bd,0xf9b9,0xf9b5,0xf9b1,0xf9ad,0xf9a9,0xf9a5,0xf9a1,0xf99d,0xf999,
+ 0xf995,0xf991,0xf98d,0xf989,0xf985,0xf982,0xf97e,0xf97a,0xf976,0xf972,0xf96e,0xf96a,0xf966,0xf962,0xf95e,0xf95a,
+ 0xf956,0xf952,0xf94e,0xf94a,0xf946,0xf942,0xf93e,0xf93a,0xf936,0xf932,0xf92e,0xf92b,0xf927,0xf923,0xf91f,0xf91b,
+ 0xf918,0xf914,0xf910,0xf90c,0xf908,0xf904,0xf900,0xf8fc,0xf8f8,0xf8f4,0xf8f0,0xf8ec,0xf8e8,0xf8e4,0xf8e0,0xf8dd,
+ 0xf8db,0xf8d7,0xf8d3,0xf8cf,0xf8cb,0xf8c7,0xf8c3,0xf8bf,0xf8bb,0xf8b7,0xf8b3,0xf8af,0xf8ab,0xf8a7,0xf8a3,0xf89f,
+ 0xf89c,0xf898,0xf894,0xf890,0xf88c,0xf888,0xf884,0xf880,0xf87c,0xf878,0xf874,0xf870,0xf86c,0xf868,0xf864,0xf860,
+ 0xf85f,0xf85b,0xf857,0xf853,0xf84f,0xf84b,0xf847,0xf843,0xf83f,0xf83b,0xf837,0xf833,0xf82f,0xf82b,0xf827,0xf823,
+ 0xf820,0xf81c,0xf818,0xf814,0xf810,0xf80c,0xf808,0xf804,0xf800,0xf7fc,0xf7f8,0xf7f4,0xf7f0,0xf7ec,0xf7e8,0xf7e4,
+ 0xf7e2,0xf7df,0xf7db,0xf7d7,0xf7d3,0xf7cf,0xf7cb,0xf7c7,0xf7c3,0xf7bf,0xf7bb,0xf7b7,0xf7b3,0xf7af,0xf7ab,0xf7a7,
+ 0xf7a3,0xf7a0,0xf79c,0xf798,0xf794,0xf790,0xf78c,0xf788,0xf784,0xf780,0xf77c,0xf778,0xf774,0xf770,0xf76c,0xf768,
+ 0xf766,0xf763,0xf75f,0xf75b,0xf757,0xf753,0xf74f,0xf74b,0xf747,0xf743,0xf73f,0xf73b,0xf737,0xf733,0xf72f,0xf72b,
+ 0xf728,0xf724,0xf720,0xf71c,0xf718,0xf714,0xf711,0xf70d,0xf709,0xf705,0xf701,0xf6fd,0xf6f9,0xf6f5,0xf6f1,0xf6ed,
+ 0xf6e9,0xf6e5,0xf6e2,0xf6de,0xf6da,0xf6d6,0xf6d2,0xf6ce,0xf6ca,0xf6c6,0xf6c4,0xf6c0,0xf6bc,0xf6b8,0xf6b4,0xf6b0,
+ 0xf6ad,0xf6a9,0xf6a5,0xf6a1,0xf69d,0xf699,0xf695,0xf691,0xf68d,0xf689,0xf685,0xf681,0xf67e,0xf67a,0xf676,0xf672,
+ 0xf66e,0xf66a,0xf666,0xf662,0xf660,0xf65c,0xf658,0xf654,0xf650,0xf64c,0xf649,0xf645,0xf641,0xf63d,0xf639,0xf635,
+ 0xf631,0xf62d,0xf629,0xf625,0xf621,0xf61d,0xf619,0xf616,0xf612,0xf60e,0xf60a,0xf606,0xf602,0xf600,0xf5fc,0xf5f8,
+ 0xf5f4,0xf5f0,0xf5ec,0xf5e8,0xf5e5,0xf5e1,0xf5dd,0xf5d9,0xf5d5,0xf5d1,0xf5cd,0xf5c9,0xf5c5,0xf5c1,0xf5bd,0xf5b9,
+ 0xf5b5,0xf5b2,0xf5ae,0xf5aa,0xf5a6,0xf5a2,0xf59e,0xf59c,0xf598,0xf594,0xf590,0xf58c,0xf588,0xf584,0xf581,0xf57d,
+ 0xf579,0xf575,0xf571,0xf56d,0xf569,0xf565,0xf561,0xf55d,0xf559,0xf555,0xf551,0xf54e,0xf54a,0xf546,0xf542,0xf53e,
+ 0xf53a,0xf537,0xf533,0xf52f,0xf52b,0xf527,0xf523,0xf51f,0xf51b,0xf517,0xf513,0xf511,0xf50e,0xf50a,0xf506,0xf502,
+ 0xf4fe,0xf4fa,0xf4f6,0xf4f2,0xf4ee,0xf4ea,0xf4e6,0xf4e3,0xf4df,0xf4db,0xf4d7,0xf4d3,0xf4cf,0xf4cb,0xf4c7,0xf4c3,
+ 0xf4c1,0xf4bd,0xf4ba,0xf4b6,0xf4b2,0xf4ae,0xf4aa,0xf4a6,0xf4a2,0xf49e,0xf49a,0xf496,0xf492,0xf48f,0xf48b,0xf487,
+ 0xf483,0xf47f,0xf47b,0xf477,0xf473,0xf46f,0xf46d,0xf469,0xf466,0xf462,0xf45e,0xf45a,0xf456,0xf452,0xf44e,0xf44a,
+ 0xf446,0xf442,0xf43f,0xf43b,0xf437,0xf433,0xf42f,0xf42b,0xf427,0xf423,0xf41f,0xf41d,0xf419,0xf415,0xf412,0xf40e,
+ 0xf40a,0xf406,0xf402,0xf3fe,0xf3fa,0xf3f6,0xf3f2,0xf3ee,0xf3eb,0xf3e7,0xf3e3,0xf3df,0xf3db,0xf3d7,0xf3d3,0xf3cf,
+ 0xf3cd,0xf3c9,0xf3c5,0xf3c2,0xf3be,0xf3ba,0xf3b6,0xf3b2,0xf3ae,0xf3aa,0xf3a6,0xf3a2,0xf39e,0xf39a,0xf397,0xf393,
+ 0xf38f,0xf38b,0xf387,0xf383,0xf37f,0xf37b,0xf379,0xf375,0xf371,0xf36e,0xf36a,0xf366,0xf362,0xf35e,0xf35a,0xf356,
+ 0xf352,0xf34f,0xf34b,0xf347,0xf343,0xf33f,0xf33b,0xf337,0xf333,0xf32f,0xf32c,0xf328,0xf324,0xf320,0xf31c,0xf318,
+ 0xf314,0xf310,0xf30c,0xf30b,0xf307,0xf303,0xf2ff,0xf2fb,0xf2f7,0xf2f3,0xf2ef,0xf2eb,0xf2e7,0xf2e4,0xf2e0,0xf2dc,
+ 0xf2d8,0xf2d4,0xf2d0,0xf2cc,0xf2c8,0xf2c6,0xf2c3,0xf2bf,0xf2bb,0xf2b7,0xf2b3,0xf2af,0xf2ab,0xf2a7,0xf2a3,0xf2a0,
+ 0xf29c,0xf298,0xf294,0xf290,0xf28c,0xf288,0xf284,0xf282,0xf27e,0xf27b,0xf277,0xf273,0xf26f,0xf26b,0xf267,0xf263,
+ 0xf25f,0xf25b,0xf258,0xf254,0xf250,0xf24c,0xf248,0xf244,0xf240,0xf23c,0xf23a,0xf236,0xf233,0xf22f,0xf22b,0xf227,
+ 0xf223,0xf21f,0xf21b,0xf217,0xf213,0xf210,0xf20c,0xf208,0xf204,0xf200,0xf1fc,0xf1f8,0xf1f6,0xf1f2,0xf1ee,0xf1eb,
+ 0xf1e7,0xf1e3,0xf1df,0xf1db,0xf1d7,0xf1d3,0xf1cf,0xf1cb,0xf1c8,0xf1c4,0xf1c0,0xf1bc,0xf1b8,0xf1b4,0xf1b2,0xf1ae,
+ 0xf1aa,0xf1a7,0xf1a3,0xf19f,0xf19b,0xf197,0xf193,0xf18f,0xf18b,0xf187,0xf184,0xf180,0xf17c,0xf178,0xf174,0xf170,
+ 0xf16c,0xf168,0xf165,0xf161,0xf15d,0xf159,0xf155,0xf151,0xf14f,0xf14b,0xf147,0xf144,0xf140,0xf13c,0xf138,0xf134,
+ 0xf130,0xf12c,0xf128,0xf125,0xf121,0xf11d,0xf119,0xf115,0xf113,0xf10f,0xf10b,0xf108,0xf104,0xf100,0xf0fc,0xf0f8,
+ 0xf0f4,0xf0f0,0xf0ec,0xf0e9,0xf0e5,0xf0e1,0xf0dd,0xf0d9,0xf0d7,0xf0d3,0xf0cf,0xf0cb,0xf0c8,0xf0c4,0xf0c0,0xf0bc,
+ 0xf0b8,0xf0b4,0xf0b0,0xf0ac,0xf0a9,0xf0a5,0xf0a1,0xf09d,0xf09b,0xf097,0xf093,0xf08f,0xf08c,0xf088,0xf084,0xf080,
+ 0xf07c,0xf078,0xf074,0xf070,0xf06d,0xf069,0xf065,0xf061,0xf05f,0xf05b,0xf057,0xf053,0xf04f,0xf04c,0xf048,0xf044,
+ 0xf040,0xf03c,0xf038,0xf034,0xf030,0xf02d,0xf029,0xf025,0xf023,0xf01f,0xf01b,0xf017,0xf013,0xf010,0xf00c,0xf008,
+ 0xf004,0xf000,0xeffc,0xeff8,0xeff4,0xeff1,0xefed,0xefe9,0xefe7,0xefe3,0xefdf,0xefdb,0xefd7,0xefd3,0xefd0,0xefcc,
+ 0xefc8,0xefc4,0xefc0,0xefbc,0xefb8,0xefb4,0xefb1,0xefad,0xefab,0xefa7,0xefa3,0xef9f,0xef9b,0xef97,0xef94,0xef90,
+ 0xef8b,0xef87,0xef83,0xef80,0xef7e,0xef7a,0xef76,0xef72,0xef6e,0xef6a,0xef66,0xef63,0xef5f,0xef5b,0xef57,0xef53,
+ 0xef4f,0xef4b,0xef48,0xef46,0xef42,0xef3e,0xef3a,0xef36,0xef32,0xef2e,0xef2b,0xef27,0xef23,0xef1f,0xef1b,0xef17,
+ 0xef13,0xef0f,0xef0e,0xef0a,0xef06,0xef02,0xeefe,0xeefa,0xeef6,0xeef2,0xeeef,0xeeeb,0xeee7,0xeee3,0xeedf,0xeedb,
+ 0xeed7,0xeed5,0xeed2,0xeece,0xeeca,0xeec6,0xeec2,0xeebe,0xeeba,0xeeb7,0xeeb3,0xeeaf,0xeeab,0xeea7,0xeea3,0xee9f,
+ 0xee9d,0xee9a,0xee96,0xee92,0xee8e,0xee8a,0xee86,0xee82,0xee7e,0xee7b,0xee77,0xee73,0xee6f,0xee6b,0xee67,0xee63,
+ 0xee61,0xee5e,0xee5a,0xee56,0xee52,0xee4e,0xee4a,0xee46,0xee43,0xee3f,0xee3b,0xee37,0xee33,0xee2f,0xee2b,0xee29,
+ 0xee26,0xee22,0xee1e,0xee1a,0xee16,0xee12,0xee0e,0xee0a,0xee07,0xee03,0xedff,0xedfb,0xedf7,0xedf3,0xedf1,0xeded,
+ 0xedea,0xede6,0xede2,0xedde,0xedda,0xedd6,0xedd2,0xedce,0xedcb,0xedc7,0xedc3,0xedbf,0xedbb,0xedb9,0xedb5,0xedb1,
+ 0xedad,0xeda9,0xeda6,0xeda2,0xeda0,0xed9c,0xed98,0xed94,0xed90,0xed8d,0xed89,0xed85,0xed81,0xed7d,0xed79,0xed75,
+ 0xed72,0xed70,0xed6c,0xed68,0xed64,0xed60,0xed5c,0xed59,0xed55,0xed51,0xed4d,0xed49,0xed45,0xed41,0xed3e,0xed3c,
+ 0xed38,0xed34,0xed30,0xed2c,0xed28,0xed25,0xed21,0xed1d,0xed19,0xed15,0xed11,0xed0d,0xed0c,0xed08,0xed04,0xed00,
+ 0xecfc,0xecf8,0xecf4,0xecf1,0xeced,0xece9,0xece5,0xece1,0xecdd,0xecd9,0xecd8,0xecd4,0xecd0,0xeccc,0xecc8,0xecc4,
+ 0xecc0,0xecbd,0xecb9,0xecb5,0xecb1,0xecad,0xeca9,0xeca7,0xeca4,0xeca0,0xec9c,0xec98,0xec94,0xec90,0xec8c,0xec89,
+ 0xec85,0xec81,0xec7d,0xec79,0xec75,0xec73,0xec70,0xec6c,0xec68,0xec64,0xec60,0xec5c,0xec58,0xec55,0xec51,0xec4d,
+ 0xec49,0xec45,0xec43,0xec3f,0xec3c,0xec38,0xec34,0xec30,0xec2c,0xec28,0xec24,0xec21,0xec1d,0xec19,0xec15,0xec11,
+ 0xec0f,0xec0b,0xec08,0xec04,0xec00,0xebfc,0xebf8,0xebf4,0xebf0,0xebed,0xebe9,0xebe5,0xebe1,0xebdf,0xebdb,0xebd7,
+ 0xebd3,0xebcf,0xebcb,0xebc7,0xebc6,0xebc2,0xebbe,0xebba,0xebb6,0xebb2,0xebaf,0xebab,0xeba7,0xeba3,0xeb9f,0xeb9b,
+ 0xeb99,0xeb96,0xeb92,0xeb8e,0xeb8a,0xeb86,0xeb82,0xeb7f,0xeb7b,0xeb77,0xeb73,0xeb6f,0xeb6d,0xeb69,0xeb66,0xeb62,
+ 0xeb5e,0xeb5a,0xeb56,0xeb52,0xeb4f,0xeb4b,0xeb47,0xeb43,0xeb41,0xeb3d,0xeb3a,0xeb36,0xeb32,0xeb2e,0xeb2a,0xeb26,
+ 0xeb23,0xeb1f,0xeb1b,0xeb17,0xeb15,0xeb11,0xeb0d,0xeb0a,0xeb06,0xeb02,0xeafe,0xeafa,0xeaf6,0xeaf3,0xeaef,0xeaeb,
+ 0xeae9,0xeae5,0xeae1,0xeadd,0xeada,0xead6,0xead2,0xeace,0xeaca,0xeac6,0xeac3,0xeabf,0xeabb,0xeab9,0xeab5,0xeab1,
+ 0xeaae,0xeaaa,0xeaa6,0xeaa2,0xea9e,0xea9a,0xea97,0xea93,0xea8f,0xea8d,0xea89,0xea85,0xea81,0xea7e,0xea7a,0xea76,
+ 0xea72,0xea6e,0xea6a,0xea67,0xea63,0xea61,0xea5d,0xea59,0xea55,0xea51,0xea4e,0xea4a,0xea46,0xea42,0xea3e,0xea3a,
+ 0xea37,0xea35,0xea31,0xea2d,0xea29,0xea25,0xea22,0xea1e,0xea1a,0xea16,0xea12,0xea0e,0xea0b,0xea09,0xea05,0xea01,
+ 0xe9fc,0xe9f8,0xe9f5,0xe9f3,0xe9ef,0xe9eb,0xe9e7,0xe9e3,0xe9df,0xe9dc,0xe9d8,0xe9d4,0xe9d0,0xe9cc,0xe9ca,0xe9c7,
+ 0xe9c3,0xe9bf,0xe9bb,0xe9b7,0xe9b4,0xe9b0,0xe9ac,0xe9a8,0xe9a4,0xe9a0,0xe99f,0xe99b,0xe997,0xe993,0xe98f,0xe98b,
+ 0xe988,0xe984,0xe980,0xe97c,0xe978,0xe976,0xe973,0xe96f,0xe96b,0xe967,0xe963,0xe960,0xe95c,0xe958,0xe954,0xe950,
+ 0xe94e,0xe94a,0xe947,0xe943,0xe93f,0xe93b,0xe937,0xe934,0xe930,0xe92c,0xe928,0xe926,0xe922,0xe91f,0xe91b,0xe917,
+ 0xe913,0xe90f,0xe90b,0xe908,0xe904,0xe900,0xe8fe,0xe8fa,0xe8f6,0xe8f3,0xe8ef,0xe8eb,0xe8e7,0xe8e3,0xe8e0,0xe8dc,
+ 0xe8d8,0xe8d6,0xe8d2,0xe8ce,0xe8cb,0xe8c7,0xe8c3,0xe8bf,0xe8bb,0xe8b7,0xe8b4,0xe8b0,0xe8ae,0xe8aa,0xe8a6,0xe8a2,
+ 0xe89f,0xe89b,0xe897,0xe893,0xe88f,0xe88b,0xe888,0xe886,0xe882,0xe87e,0xe87a,0xe876,0xe873,0xe86f,0xe86b,0xe867,
+ 0xe863,0xe860,0xe85c,0xe85a,0xe856,0xe852,0xe84e,0xe84b,0xe847,0xe843,0xe83f,0xe83b,0xe837,0xe834,0xe832,0xe82e,
+ 0xe829,0xe825,0xe821,0xe81f,0xe81b,0xe818,0xe814,0xe810,0xe80c,0xe808,0xe805,0xe801,0xe7fd,0xe7fb,0xe7f7,0xe7f4,
+ 0xe7f0,0xe7ec,0xe7e8,0xe7e4,0xe7e0,0xe7dd,0xe7d9,0xe7d5,0xe7d3,0xe7cf,0xe7cc,0xe7c8,0xe7c4,0xe7c0,0xe7bc,0xe7b9,
+ 0xe7b5,0xe7b1,0xe7af,0xe7ab,0xe7a7,0xe7a4,0xe7a0,0xe79c,0xe798,0xe794,0xe791,0xe78d,0xe78b,0xe787,0xe783,0xe77f,
+ 0xe77c,0xe778,0xe774,0xe770,0xe76c,0xe769,0xe767,0xe763,0xe75f,0xe75b,0xe758,0xe754,0xe750,0xe74c,0xe748,0xe744,
+ 0xe743,0xe73f,0xe73b,0xe737,0xe733,0xe730,0xe72c,0xe728,0xe724,0xe720,0xe71d,0xe71b,0xe717,0xe713,0xe70f,0xe70b,
+ 0xe708,0xe704,0xe700,0xe6fc,0xe6f8,0xe6f6,0xe6f3,0xe6ef,0xe6eb,0xe6e7,0xe6e3,0xe6e0,0xe6dc,0xe6d8,0xe6d4,0xe6d2,
+ 0xe6cf,0xe6cb,0xe6c7,0xe6c3,0xe6bf,0xe6bc,0xe6b8,0xe6b4,0xe6b0,0xe6ae,0xe6aa,0xe6a7,0xe6a3,0xe69f,0xe69b,0xe697,
+ 0xe694,0xe690,0xe68c,0xe688,0xe686,0xe682,0xe67f,0xe67b,0xe677,0xe673,0xe66f,0xe66c,0xe668,0xe664,0xe662,0xe65e,
+ 0xe659,0xe655,0xe651,0xe64f,0xe64c,0xe648,0xe644,0xe640,0xe63c,0xe639,0xe635,0xe631,0xe62f,0xe62b,0xe628,0xe624,
+ 0xe620,0xe61c,0xe618,0xe615,0xe611,0xe60d,0xe60b,0xe607,0xe604,0xe600,0xe5fc,0xe5f8,0xe5f4,0xe5f1,0xe5ed,0xe5eb,
+ 0xe5e7,0xe5e3,0xe5e0,0xe5dc,0xe5d8,0xe5d4,0xe5d0,0xe5cd,0xe5c9,0xe5c7,0xe5c3,0xe5bf,0xe5bc,0xe5b8,0xe5b4,0xe5b0,
+ 0xe5ac,0xe5a9,0xe5a7,0xe5a3,0xe59f,0xe59b,0xe598,0xe594,0xe590,0xe58c,0xe588,0xe585,0xe583,0xe57f,0xe57b,0xe577,
+ 0xe574,0xe570,0xe56c,0xe568,0xe564,0xe563,0xe55f,0xe55b,0xe557,0xe553,0xe550,0xe54c,0xe548,0xe544,0xe540,0xe53f,
+ 0xe53b,0xe537,0xe533,0xe52f,0xe52c,0xe528,0xe524,0xe520,0xe51e,0xe51b,0xe517,0xe513,0xe50f,0xe50b,0xe508,0xe504,
+ 0xe500,0xe4fc,0xe4fa,0xe4f7,0xe4f3,0xe4ef,0xe4eb,0xe4e7,0xe4e4,0xe4e0,0xe4dc,0xe4da,0xe4d6,0xe4d3,0xe4cf,0xe4cb,
+ 0xe4c7,0xe4c3,0xe4c0,0xe4bc,0xe4b8,0xe4b6,0xe4b2,0xe4af,0xe4ab,0xe4a7,0xe4a3,0xe49f,0xe49c,0xe498,0xe496,0xe492,
+ 0xe48e,0xe48a,0xe486,0xe482,0xe47f,0xe47d,0xe479,0xe475,0xe471,0xe46e,0xe46a,0xe466,0xe462,0xe45f,0xe45d,0xe459,
+ 0xe455,0xe451,0xe44e,0xe44a,0xe446,0xe442,0xe43e,0xe43d,0xe439,0xe435,0xe431,0xe42d,0xe42a,0xe426,0xe422,0xe41e,
+ 0xe41c,0xe419,0xe415,0xe411,0xe40d,0xe409,0xe406,0xe402,0xe3fe,0xe3fa,0xe3f8,0xe3f5,0xe3f1,0xe3ed,0xe3e9,0xe3e6,
+ 0xe3e2,0xe3de,0xe3da,0xe3d8,0xe3d5,0xe3d1,0xe3cd,0xe3c9,0xe3c5,0xe3c2,0xe3be,0xe3ba,0xe3b8,0xe3b4,0xe3b1,0xe3ad,
+ 0xe3a9,0xe3a5,0xe3a1,0xe39e,0xe39a,0xe398,0xe394,0xe390,0xe38d,0xe389,0xe385,0xe381,0xe37e,0xe37a,0xe378,0xe374,
+ 0xe370,0xe36d,0xe369,0xe365,0xe361,0xe35d,0xe35a,0xe358,0xe354,0xe350,0xe34c,0xe349,0xe345,0xe341,0xe33d,0xe339,
+ 0xe338,0xe334,0xe330,0xe32c,0xe328,0xe325,0xe321,0xe31d,0xe319,0xe316,0xe314,0xe310,0xe30c,0xe308,0xe305,0xe301,
+ 0xe2fd,0xe2f9,0xe2f5,0xe2f4,0xe2f0,0xe2ec,0xe2e8,0xe2e4,0xe2e1,0xe2dd,0xe2d9,0xe2d5,0xe2d3,0xe2d0,0xe2cc,0xe2c8,
+ 0xe2c6,0xe2c2,0xe2be,0xe2ba,0xe2b7,0xe2b3,0xe2af,0xe2ab,0xe2a8,0xe2a6,0xe2a2,0xe29e,0xe29a,0xe297,0xe293,0xe28f,
+ 0xe28b,0xe288,0xe286,0xe282,0xe27e,0xe27a,0xe277,0xe273,0xe26f,0xe26b,0xe269,0xe266,0xe262,0xe25e,0xe25a,0xe257,
+ 0xe253,0xe24f,0xe24b,0xe249,0xe246,0xe242,0xe23e,0xe23a,0xe237,0xe233,0xe22f,0xe22d,0xe229,0xe226,0xe222,0xe21e,
+ 0xe21a,0xe217,0xe213,0xe20f,0xe20d,0xe209,0xe206,0xe202,0xe1fe,0xe1fa,0xe1f7,0xe1f3,0xe1f1,0xe1ed,0xe1e9,0xe1e6,
+ 0xe1e2,0xe1de,0xe1da,0xe1d7,0xe1d3,0xe1d1,0xe1cd,0xe1c9,0xe1c6,0xe1c2,0xe1be,0xe1ba,0xe1b7,0xe1b5,0xe1b1,0xe1ad,
+ 0xe1a9,0xe1a6,0xe1a2,0xe19e,0xe19a,0xe197,0xe195,0xe191,0xe18d,0xe189,0xe186,0xe182,0xe17e,0xe17a,0xe178,0xe175,
+ 0xe171,0xe16d,0xe169,0xe166,0xe162,0xe15e,0xe15a,0xe158,0xe155,0xe151,0xe14d,0xe149,0xe146,0xe142,0xe13e,0xe13c,
+ 0xe138,0xe135,0xe131,0xe12d,0xe129,0xe126,0xe122,0xe11e,0xe11c,0xe118,0xe115,0xe111,0xe10d,0xe109,0xe106,0xe102,
+ 0xe0ff,0xe0fb,0xe0f8,0xe0f4,0xe0f2,0xe0ee,0xe0ea,0xe0e7,0xe0e3,0xe0df,0xe0db,0xe0d8,0xe0d6,0xe0d2,0xe0ce,0xe0cb,
+ 0xe0c7,0xe0c3,0xe0bf,0xe0bc,0xe0ba,0xe0b6,0xe0b2,0xe0ae,0xe0ab,0xe0a7,0xe0a3,0xe09f,0xe09e,0xe09a,0xe096,0xe092,
+ 0xe08f,0xe08b,0xe087,0xe083,0xe081,0xe07e,0xe07a,0xe076,0xe072,0xe06f,0xe06b,0xe067,0xe065,0xe062,0xe05e,0xe05a,
+ 0xe056,0xe053,0xe04f,0xe04b,0xe049,0xe045,0xe042,0xe03e,0xe03a,0xe036,0xe033,0xe02f,0xe02d,0xe029,0xe026,0xe022,
+ 0xe01e,0xe01a,0xe017,0xe013,0xe011,0xe00d,0xe009,0xe006,0xe002,0xdffe,0xdffa,0xdff7,0xdff5,0xdff1,0xdfed,0xdfea,
+ 0xdfe6,0xdfe2,0xdfde,0xdfdb,0xdfd9,0xdfd5,0xdfd1,0xdfcd,0xdfca,0xdfc6,0xdfc2,0xdfbe,0xdfbd,0xdfb9,0xdfb5,0xdfb1,
+ 0xdfae,0xdfaa,0xdfa6,0xdfa2,0xdfa0,0xdf9d,0xdf99,0xdf95,0xdf91,0xdf8e,0xdf8a,0xdf86,0xdf84,0xdf81,0xdf7d,0xdf79,
+ 0xdf75,0xdf72,0xdf6e,0xdf6a,0xdf68,0xdf64,0xdf61,0xdf5d,0xdf59,0xdf55,0xdf52,0xdf4e,0xdf4c,0xdf48,0xdf45,0xdf41,
+ 0xdf3d,0xdf3a,0xdf36,0xdf32,0xdf2e,0xdf2b,0xdf27,0xdf23,0xdf21,0xdf1e,0xdf1a,0xdf16,0xdf12,0xdf0f,0xdf0b,0xdf07,
+ 0xdf05,0xdf02,0xdefe,0xdefa,0xdef6,0xdef3,0xdeef,0xdeed,0xdee9,0xdee6,0xdee2,0xdede,0xdeda,0xded7,0xded3,0xded1,
+ 0xdecd,0xdeca,0xdec6,0xdec2,0xdebe,0xdebb,0xdeb9,0xdeb5,0xdeb1,0xdeae,0xdeaa,0xdea6,0xdea2,0xde9f,0xde9d,0xde99,
+ 0xde95,0xde92,0xde8e,0xde8a,0xde86,0xde85,0xde81,0xde7d,0xde79,0xde76,0xde72,0xde6e,0xde6a,0xde69,0xde65,0xde61,
+ 0xde5d,0xde5a,0xde56,0xde52,0xde50,0xde4d,0xde49,0xde45,0xde41,0xde3e,0xde3a,0xde36,0xde34,0xde31,0xde2d,0xde29,
+ 0xde25,0xde22,0xde1e,0xde1c,0xde18,0xde15,0xde11,0xde0d,0xde09,0xde06,0xde02,0xde00,0xddfc,0xddf9,0xddf5,0xddf1,
+ 0xdded,0xddea,0xdde8,0xdde4,0xdde0,0xdddd,0xddd9,0xddd5,0xddd1,0xddce,0xddcc,0xddc8,0xddc4,0xddc1,0xddbd,0xddb9,
+ 0xddb5,0xddb3,0xddb0,0xddac,0xdda8,0xdda5,0xdda1,0xdd9d,0xdd99,0xdd97,0xdd94,0xdd90,0xdd8c,0xdd89,0xdd85,0xdd81,
+ 0xdd7f,0xdd7b,0xdd77,0xdd74,0xdd70,0xdd6c,0xdd6a,0xdd66,0xdd63,0xdd5f,0xdd5b,0xdd58,0xdd54,0xdd52,0xdd4e,0xdd4b,
+ 0xdd47,0xdd43,0xdd3f,0xdd3c,0xdd38,0xdd36,0xdd32,0xdd2f,0xdd2b,0xdd27,0xdd23,0xdd20,0xdd1e,0xdd1a,0xdd16,0xdd13,
+ 0xdd0f,0xdd0b,0xdd07,0xdd06,0xdd02,0xdcfe,0xdcfa,0xdcf7,0xdcf3,0xdcef,0xdcec,0xdcea,0xdce6,0xdce2,0xdcde,0xdcdb,
+ 0xdcd7,0xdcd3,0xdcd1,0xdcce,0xdcca,0xdcc6,0xdcc3,0xdcbf,0xdcbb,0xdcb9,0xdcb5,0xdcb2,0xdcae,0xdcaa,0xdca7,0xdca3,
+ 0xdca1,0xdc9d,0xdc9a,0xdc96,0xdc92,0xdc8e,0xdc8b,0xdc87,0xdc85,0xdc81,0xdc7e,0xdc7a,0xdc76,0xdc72,0xdc6f,0xdc6d,
+ 0xdc69,0xdc65,0xdc62,0xdc5e,0xdc5a,0xdc56,0xdc55,0xdc51,0xdc4d,0xdc49,0xdc46,0xdc42,0xdc3e,0xdc3a,0xdc39,0xdc35,
+ 0xdc31,0xdc2d,0xdc2a,0xdc26,0xdc22,0xdc20,0xdc1d,0xdc19,0xdc15,0xdc12,0xdc0e,0xdc0a,0xdc08,0xdc04,0xdc01,0xdbfd,
+ 0xdbf9,0xdbf6,0xdbf2,0xdbee,0xdbec,0xdbe9,0xdbe5,0xdbe1,0xdbdd,0xdbda,0xdbd6,0xdbd4,0xdbd0,0xdbcd,0xdbc9,0xdbc5,
+ 0xdbc3,0xdbbf,0xdbbb,0xdbb8,0xdbb4,0xdbb0,0xdbae,0xdbab,0xdba7,0xdba3,0xdba0,0xdb9c,0xdb98,0xdb96,0xdb93,0xdb8f,
+ 0xdb8b,0xdb87,0xdb84,0xdb80,0xdb7e,0xdb7a,0xdb77,0xdb73,0xdb6f,0xdb6c,0xdb6a,0xdb66,0xdb62,0xdb5f,0xdb5b,0xdb57,
+ 0xdb53,0xdb52,0xdb4e,0xdb4a,0xdb47,0xdb43,0xdb3f,0xdb3b,0xdb3a,0xdb36,0xdb32,0xdb2e,0xdb2b,0xdb27,0xdb23,0xdb21,
+ 0xdb1e,0xdb1a,0xdb16,0xdb13,0xdb0f,0xdb0b,0xdb09,0xdb06,0xdb02,0xdafe,0xdafa,0xdaf7,0xdaf3,0xdaf1,0xdaed,0xdaea,
+ 0xdae6,0xdae2,0xdadf,0xdadb,0xdad9,0xdad5,0xdad2,0xdace,0xdaca,0xdac6,0xdac3,0xdac1,0xdabd,0xdab9,0xdab6,0xdab2,
+ 0xdaae,0xdaab,0xdaa9,0xdaa5,0xdaa1,0xda9e,0xda9a,0xda96,0xda93,0xda91,0xda8d,0xda89,0xda86,0xda82,0xda7e,0xda7a,
+ 0xda79,0xda75,0xda71,0xda6d,0xda6a,0xda66,0xda62,0xda60,0xda5d,0xda59,0xda55,0xda52,0xda4e,0xda4c,0xda48,0xda45,
+ 0xda41,0xda3d,0xda39,0xda36,0xda34,0xda30,0xda2c,0xda29,0xda25,0xda21,0xda1e,0xda1c,0xda18,0xda14,0xda11,0xda0d,
+ 0xda0a,0xda06,0xda03,0xd9ff,0xd9fb,0xd9f9,0xd9f6,0xd9f2,0xd9ee,0xd9eb,0xd9e7,0xd9e3,0xd9e1,0xd9de,0xd9da,0xd9d6,
+ 0xd9d3,0xd9cf,0xd9cb,0xd9c9,0xd9c6,0xd9c2,0xd9be,0xd9bb,0xd9b7,0xd9b5,0xd9b1,0xd9ae,0xd9aa,0xd9a6,0xd9a3,0xd99f,
+ 0xd99d,0xd999,0xd996,0xd992,0xd98e,0xd98b,0xd989,0xd985,0xd981,0xd97e,0xd97a,0xd976,0xd973,0xd971,0xd96d,0xd969,
+ 0xd966,0xd962,0xd95e,0xd95c,0xd959,0xd955,0xd951,0xd94e,0xd94a,0xd946,0xd944,0xd941,0xd93d,0xd939,0xd936,0xd932,
+ 0xd930,0xd92c,0xd929,0xd925,0xd921,0xd91e,0xd91a,0xd918,0xd914,0xd911,0xd90d,0xd909,0xd906,0xd902,0xd900,0xd8fc,
+ 0xd8f9,0xd8f5,0xd8f1,0xd8ee,0xd8ec,0xd8e8,0xd8e4,0xd8e1,0xd8dd,0xd8d9,0xd8d6,0xd8d4,0xd8d0,0xd8cc,0xd8c9,0xd8c5,
+ 0xd8c1,0xd8bf,0xd8bc,0xd8b8,0xd8b4,0xd8b1,0xd8ad,0xd8a9,0xd8a7,0xd8a4,0xd8a0,0xd89c,0xd899,0xd895,0xd893,0xd88f,
+ 0xd88c,0xd888,0xd884,0xd881,0xd87d,0xd87b,0xd877,0xd874,0xd870,0xd86c,0xd868,0xd865,0xd863,0xd85f,0xd85c,0xd858,
+ 0xd854,0xd851,0xd84d,0xd849,0xd846,0xd844,0xd840,0xd83c,0xd839,0xd835,0xd831,0xd830,0xd82c,0xd828,0xd825,0xd821,
+ 0xd81d,0xd819,0xd818,0xd814,0xd810,0xd80d,0xd809,0xd805,0xd803,0xd800,0xd7fc,0xd7f8,0xd7f5,0xd7f1,0xd7ef,0xd7ec,
+ 0xd7e8,0xd7e4,0xd7e0,0xd7dd,0xd7db,0xd7d7,0xd7d4,0xd7d0,0xd7cc,0xd7c9,0xd7c5,0xd7c3,0xd7bf,0xd7bc,0xd7b8,0xd7b4,
+ 0xd7b1,0xd7af,0xd7ab,0xd7a7,0xd7a4,0xd7a0,0xd79c,0xd79b,0xd797,0xd793,0xd790,0xd78c,0xd788,0xd786,0xd783,0xd77f,
+ 0xd77b,0xd778,0xd774,0xd770,0xd76e,0xd76b,0xd767,0xd763,0xd760,0xd75c,0xd75a,0xd756,0xd753,0xd74f,0xd74b,0xd748,
+ 0xd746,0xd742,0xd73f,0xd73b,0xd737,0xd734,0xd732,0xd72e,0xd72a,0xd727,0xd723,0xd71f,0xd71c,0xd71a,0xd716,0xd712,
+ 0xd70f,0xd70b,0xd707,0xd706,0xd702,0xd6fe,0xd6fa,0xd6f7,0xd6f3,0xd6f1,0xd6ee,0xd6ea,0xd6e6,0xd6e3,0xd6df,0xd6dd,
+ 0xd6d9,0xd6d6,0xd6d2,0xd6ce,0xd6cb,0xd6c7,0xd6c5,0xd6c1,0xd6be,0xd6ba,0xd6b6,0xd6b3,0xd6b1,0xd6ad,0xd6aa,0xd6a6,
+ 0xd6a3,0xd6a0,0xd69c,0xd698,0xd695,0xd691,0xd68d,0xd68c,0xd688,0xd684,0xd681,0xd67d,0xd679,0xd677,0xd674,0xd670,
+ 0xd66c,0xd669,0xd665,0xd663,0xd65f,0xd65c,0xd658,0xd654,0xd651,0xd64f,0xd64b,0xd648,0xd644,0xd640,0xd63d,0xd63b,
+ 0xd637,0xd633,0xd630,0xd62c,0xd628,0xd627,0xd623,0xd61f,0xd61c,0xd618,0xd614,0xd612,0xd60f,0xd60b,0xd607,0xd604,
+ 0xd600,0xd5fe,0xd5fa,0xd5f7,0xd5f3,0xd5ef,0xd5ec,0xd5ea,0xd5e6,0xd5e3,0xd5df,0xd5db,0xd5d8,0xd5d6,0xd5d2,0xd5ce,
+ 0xd5cb,0xd5c7,0xd5c3,0xd5c0,0xd5be,0xd5ba,0xd5b7,0xd5b3,0xd5af,0xd5ac,0xd5aa,0xd5a6,0xd5a2,0xd59f,0xd59b,0xd597,
+ 0xd596,0xd592,0xd58e,0xd58b,0xd587,0xd583,0xd581,0xd57e,0xd57a,0xd576,0xd573,0xd56f,0xd56d,0xd569,0xd566,0xd562,
+ 0xd55e,0xd55b,0xd559,0xd555,0xd552,0xd54e,0xd54a,0xd547,0xd545,0xd541,0xd53d,0xd53a,0xd536,0xd532,0xd531,0xd52d,
+ 0xd529,0xd526,0xd522,0xd51e,0xd51c,0xd519,0xd515,0xd511,0xd50e,0xd50a,0xd508,0xd504,0xd501,0xd4fd,0xd4f9,0xd4f6,
+ 0xd4f3,0xd4ef,0xd4ec,0xd4ea,0xd4e6,0xd4e3,0xd4df,0xd4db,0xd4d8,0xd4d6,0xd4d2,0xd4cf,0xd4cb,0xd4c7,0xd4c4,0xd4c2,
+ 0xd4be,0xd4ba,0xd4b7,0xd4b3,0xd4b0,0xd4ae,0xd4aa,0xd4a6,0xd4a3,0xd49f,0xd49b,0xd49a,0xd496,0xd492,0xd48f,0xd48b,
+ 0xd489,0xd485,0xd482,0xd47e,0xd47a,0xd477,0xd475,0xd471,0xd46e,0xd46a,0xd466,0xd463,0xd461,0xd45d,0xd45a,0xd456,
+ 0xd452,0xd44f,0xd44d,0xd449,0xd445,0xd442,0xd43e,0xd43b,0xd439,0xd435,0xd431,0xd42e,0xd42a,0xd426,0xd425,0xd421,
+ 0xd41d,0xd41a,0xd416,0xd414,0xd410,0xd40d,0xd409,0xd405,0xd402,0xd400,0xd3fc,0xd3f9,0xd3f5,0xd3f1,0xd3ee,0xd3ec,
+ 0xd3e8,0xd3e5,0xd3e1,0xd3dd,0xd3da,0xd3d8,0xd3d4,0xd3d0,0xd3cd,0xd3c9,0xd3c6,0xd3c4,0xd3c0,0xd3bc,0xd3b9,0xd3b5,
+ 0xd3b3,0xd3b0,0xd3ac,0xd3a8,0xd3a5,0xd3a1,0xd39f,0xd39b,0xd398,0xd394,0xd390,0xd38d,0xd38b,0xd387,0xd384,0xd380,
+ 0xd37c,0xd379,0xd377,0xd373,0xd370,0xd36c,0xd368,0xd365,0xd363,0xd35f,0xd35b,0xd358,0xd354,0xd351,0xd34f,0xd34b,
+ 0xd348,0xd344,0xd340,0xd33d,0xd339,0xd335,0xd334,0xd330,0xd32c,0xd329,0xd325,0xd321,0xd320,0xd31c,0xd318,0xd315,
+ 0xd311,0xd30f,0xd30c,0xd308,0xd304,0xd301,0xd2fd,0xd2fb,0xd2f8,0xd2f4,0xd2f0,0xd2ed,0xd2eb,0xd2e7,0xd2e4,0xd2e0,
+ 0xd2dc,0xd2d9,0xd2d7,0xd2d3,0xd2d0,0xd2cc,0xd2c8,0xd2c6,0xd2c3,0xd2bf,0xd2bb,0xd2b8,0xd2b4,0xd2b2,0xd2af,0xd2ab,
+ 0xd2a7,0xd2a4,0xd2a0,0xd29e,0xd29b,0xd297,0xd293,0xd290,0xd28e,0xd28a,0xd287,0xd283,0xd27f,0xd27c,0xd27a,0xd276,
+ 0xd273,0xd26f,0xd26b,0xd26a,0xd266,0xd262,0xd25f,0xd25b,0xd257,0xd256,0xd252,0xd24e,0xd24b,0xd247,0xd245,0xd242,
+ 0xd23e,0xd23a,0xd237,0xd233,0xd231,0xd22e,0xd22a,0xd226,0xd223,0xd21f,0xd21d,0xd219,0xd216,0xd212,0xd20f,0xd20d,
+ 0xd209,0xd205,0xd202,0xd1fe,0xd1fb,0xd1f9,0xd1f5,0xd1f1,0xd1ee,0xd1ea,0xd1e8,0xd1e5,0xd1e1,0xd1dd,0xd1da,0xd1d6,
+ 0xd1d4,0xd1d1,0xd1cd,0xd1c9,0xd1c6,0xd1c4,0xd1c0,0xd1bd,0xd1b9,0xd1b5,0xd1b2,0xd1b0,0xd1ac,0xd1a9,0xd1a5,0xd1a1,
+ 0xd19e,0xd19a,0xd199,0xd195,0xd191,0xd18e,0xd18a,0xd188,0xd185,0xd181,0xd17d,0xd17a,0xd176,0xd174,0xd171,0xd16d,
+ 0xd169,0xd166,0xd164,0xd160,0xd15d,0xd159,0xd155,0xd152,0xd150,0xd14c,0xd149,0xd145,0xd141,0xd140,0xd13c,0xd138,
+ 0xd135,0xd131,0xd12d,0xd12c,0xd128,0xd124,0xd121,0xd11d,0xd11b,0xd118,0xd114,0xd110,0xd10d,0xd10b,0xd107,0xd104,
+ 0xd100,0xd0fc,0xd0f9,0xd0f7,0xd0f3,0xd0f0,0xd0ec,0xd0e8,0xd0e7,0xd0e3,0xd0df,0xd0dc,0xd0d8,0xd0d4,0xd0d3,0xd0cf,
+ 0xd0cb,0xd0c8,0xd0c4,0xd0c2,0xd0bf,0xd0bb,0xd0b7,0xd0b4,0xd0b0,0xd0ae,0xd0ab,0xd0a7,0xd0a3,0xd0a0,0xd09e,0xd09a,
+ 0xd097,0xd093,0xd08f,0xd08c,0xd08a,0xd086,0xd083,0xd07f,0xd07b,0xd07a,0xd076,0xd072,0xd06f,0xd06b,0xd069,0xd066,
+ 0xd062,0xd05e,0xd05b,0xd057,0xd055,0xd052,0xd04e,0xd04a,0xd047,0xd045,0xd041,0xd03e,0xd03a,0xd036,0xd033,0xd031,
+ 0xd02d,0xd02a,0xd026,0xd022,0xd021,0xd01d,0xd019,0xd016,0xd012,0xd00e,0xd00d,0xd009,0xd005,0xd002,0xcffe,0xcffc,
+ 0xcff8,0xcff4,0xcff2,0xcfef,0xcfeb,0xcfe8,0xcfe4,0xcfe2,0xcfde,0xcfdb,0xcfd7,0xcfd4,0xcfd2,0xcfce,0xcfcb,0xcfc7,
+ 0xcfc3,0xcfc2,0xcfbe,0xcfba,0xcfb7,0xcfb3,0xcfaf,0xcfae,0xcfaa,0xcfa6,0xcfa3,0xcf9f,0xcf9d,0xcf9a,0xcf96,0xcf92,
+ 0xcf8f,0xcf8d,0xcf89,0xcf86,0xcf82,0xcf7f,0xcf7d,0xcf79,0xcf76,0xcf72,0xcf6e,0xcf6b,0xcf69,0xcf65,0xcf62,0xcf5e,
+ 0xcf5a,0xcf59,0xcf55,0xcf51,0xcf4e,0xcf4a,0xcf48,0xcf45,0xcf41,0xcf3d,0xcf3a,0xcf38,0xcf34,0xcf31,0xcf2d,0xcf2a,
+ 0xcf28,0xcf24,0xcf21,0xcf1d,0xcf19,0xcf16,0xcf14,0xcf10,0xcf0d,0xcf09,0xcf05,0xcf04,0xcf00,0xcefc,0xcef9,0xcef5,
+ 0xcef3,0xcef0,0xceec,0xcee8,0xcee5,0xcee3,0xcedf,0xcedc,0xced8,0xced5,0xced1,0xcecf,0xcecc,0xcec8,0xcec4,0xcec1,
+ 0xcebf,0xcebb,0xceb8,0xceb4,0xceb0,0xceaf,0xceab,0xcea7,0xcea4,0xcea0,0xce9e,0xce9b,0xce97,0xce93,0xce90,0xce8c,
+ 0xce8a,0xce87,0xce83,0xce80,0xce7c,0xce7a,0xce77,0xce73,0xce6f,0xce6c,0xce6a,0xce66,0xce63,0xce5f,0xce5b,0xce5a,
+ 0xce57,0xce53,0xce4f,0xce4c,0xce48,0xce45,0xce43,0xce3f,0xce3c,0xce38,0xce34,0xce33,0xce2f,0xce2b,0xce28,0xce24,
+ 0xce22,0xce1f,0xce1b,0xce17,0xce14,0xce12,0xce0e,0xce0b,0xce07,0xce04,0xce02,0xcdfe,0xcdfb,0xcdf7,0xcdf3,0xcdf2,
+ 0xcdee,0xcdea,0xcde7,0xcde3,0xcde1,0xcdde,0xcdda,0xcdd6,0xcdd3,0xcdd1,0xcdcd,0xcdca,0xcdc6,0xcdc3,0xcdbf,0xcdbd,
+ 0xcdba,0xcdb6,0xcdb2,0xcdaf,0xcdad,0xcda9,0xcda6,0xcda2,0xcd9f,0xcd9d,0xcd99,0xcd96,0xcd92,0xcd8e,0xcd8d,0xcd89,
+ 0xcd85,0xcd82,0xcd7e,0xcd7c,0xcd79,0xcd75,0xcd71,0xcd6e,0xcd6c,0xcd68,0xcd65,0xcd61,0xcd5e,0xcd5c,0xcd58,0xcd55,
+ 0xcd51,0xcd4d,0xcd4c,0xcd48,0xcd44,0xcd41,0xcd3d,0xcd39,0xcd38,0xcd34,0xcd30,0xcd2d,0xcd29,0xcd27,0xcd24,0xcd20,
+ 0xcd1d,0xcd19,0xcd17,0xcd14,0xcd10,0xcd0c,0xcd09,0xcd07,0xcd03,0xcd00,0xccfc,0xccf9,0xccf7,0xccf3,0xccef,0xccec,
+ 0xcce8,0xcce6,0xcce3,0xccdf,0xccdc,0xccd8,0xccd6,0xccd3,0xcccf,0xcccb,0xccc8,0xccc6,0xccc2,0xccbf,0xccbb,0xccb8,
+ 0xccb5,0xccb2,0xccae,0xccad,0xcca9,0xcca5,0xcca2,0xcc9e,0xcc9c,0xcc99,0xcc95,0xcc92,0xcc8e,0xcc8c,0xcc89,0xcc85,
+ 0xcc81,0xcc7e,0xcc7c,0xcc78,0xcc75,0xcc71,0xcc6e,0xcc6c,0xcc68,0xcc65,0xcc61,0xcc5d,0xcc5c,0xcc58,0xcc54,0xcc51,
+ 0xcc4f,0xcc4b,0xcc48,0xcc44,0xcc41,0xcc3f,0xcc3b,0xcc38,0xcc34,0xcc31,0xcc2f,0xcc2b,0xcc28,0xcc24,0xcc20,0xcc1f,
+ 0xcc1b,0xcc17,0xcc14,0xcc10,0xcc0e,0xcc0b,0xcc07,0xcc04,0xcc00,0xcbfe,0xcbfb,0xcbf7,0xcbf3,0xcbf0,0xcbee,0xcbea,
+ 0xcbe7,0xcbe3,0xcbe0,0xcbde,0xcbda,0xcbd7,0xcbd3,0xcbcf,0xcbce,0xcbca,0xcbc7,0xcbc3,0xcbbf,0xcbbe,0xcbba,0xcbb6,
+ 0xcbb3,0xcbaf,0xcbad,0xcbaa,0xcba6,0xcba3,0xcb9f,0xcb9d,0xcb9a,0xcb96,0xcb92,0xcb8f,0xcb8d,0xcb89,0xcb86,0xcb82,
+ 0xcb80,0xcb7d,0xcb79,0xcb76,0xcb72,0xcb70,0xcb6d,0xcb69,0xcb65,0xcb62,0xcb60,0xcb5c,0xcb59,0xcb55,0xcb52,0xcb50,
+ 0xcb4c,0xcb49,0xcb45,0xcb42,0xcb40,0xcb3c,0xcb39,0xcb35,0xcb31,0xcb30,0xcb2c,0xcb28,0xcb25,0xcb21,0xcb1f,0xcb1c,
+ 0xcb19,0xcb15,0xcb12,0xcb0e,0xcb0b,0xcb09,0xcb05,0xcb02,0xcafe,0xcafa,0xcaf9,0xcaf5,0xcaf2,0xcaee,0xcaea,0xcae9,
+ 0xcae5,0xcae1,0xcade,0xcadc,0xcad8,0xcad5,0xcad1,0xcace,0xcacc,0xcac8,0xcac5,0xcac1,0xcabe,0xcabc,0xcab8,0xcab5,
+ 0xcab1,0xcaae,0xcaac,0xcaa8,0xcaa5,0xcaa1,0xca9f,0xca9c,0xca98,0xca94,0xca91,0xca8f,0xca8c,0xca88,0xca84,0xca81,
+ 0xca7f,0xca7b,0xca78,0xca74,0xca71,0xca6f,0xca6b,0xca68,0xca64,0xca62,0xca5f,0xca5b,0xca58,0xca54,0xca52,0xca4f,
+ 0xca4b,0xca48,0xca44,0xca42,0xca3f,0xca3b,0xca37,0xca34,0xca32,0xca2f,0xca2b,0xca27,0xca26,0xca22,0xca1e,0xca1b,
+ 0xca17,0xca15,0xca12,0xca0e,0xca0b,0xca07,0xca05,0xca02,0xc9fe,0xc9fb,0xc9f7,0xc9f5,0xc9f2,0xc9ee,0xc9eb,0xc9e9,
+ 0xc9e5,0xc9e2,0xc9de,0xc9da,0xc9d9,0xc9d5,0xc9d1,0xc9ce,0xc9ca,0xc9c9,0xc9c5,0xc9c1,0xc9be,0xc9ba,0xc9b8,0xc9b5,
+ 0xc9b1,0xc9ae,0xc9ac,0xc9a8,0xc9a5,0xc9a1,0xc99e,0xc99c,0xc998,0xc995,0xc991,0xc98e,0xc98c,0xc988,0xc985,0xc981,
+ 0xc97f,0xc97b,0xc978,0xc974,0xc972,0xc96f,0xc96b,0xc968,0xc964,0xc962,0xc95f,0xc95b,0xc957,0xc956,0xc952,0xc94f,
+ 0xc94b,0xc947,0xc946,0xc942,0xc93e,0xc93b,0xc937,0xc936,0xc932,0xc92e,0xc92b,0xc929,0xc925,0xc922,0xc91e,0xc91b,
+ 0xc919,0xc915,0xc912,0xc90e,0xc90b,0xc909,0xc905,0xc902,0xc8fe,0xc8fc,0xc8f9,0xc8f5,0xc8f2,0xc8ee,0xc8ec,0xc8e9,
+ 0xc8e5,0xc8e2,0xc8de,0xc8dc,0xc8d9,0xc8d5,0xc8d2,0xc8d0,0xc8cc,0xc8c9,0xc8c5,0xc8c2,0xc8c0,0xc8bc,0xc8b9,0xc8b5,
+ 0xc8b3,0xc8b0,0xc8ac,0xc8a9,0xc8a5,0xc8a3,0xc8a0,0xc89c,0xc898,0xc895,0xc893,0xc890,0xc88c,0xc888,0xc887,0xc883,
+ 0xc87f,0xc87c,0xc878,0xc877,0xc873,0xc86f,0xc86c,0xc868,0xc866,0xc863,0xc85f,0xc85c,0xc85a,0xc856,0xc853,0xc84f,
+ 0xc84c,0xc84a,0xc846,0xc843,0xc83f,0xc83c,0xc83a,0xc836,0xc833,0xc82f,0xc82d,0xc82a,0xc826,0xc823,0xc81f,0xc81d,
+ 0xc81a,0xc816,0xc813,0xc80f,0xc80d,0xc80a,0xc806,0xc803,0xc801,0xc7fd,0xc7fa,0xc7f6,0xc7f2,0xc7f1,0xc7ed,0xc7ea,
+ 0xc7e7,0xc7e4,0xc7e0,0xc7dc,0xc7db,0xc7d7,0xc7d4,0xc7d0,0xc7ce,0xc7cb,0xc7c7,0xc7c4,0xc7c0,0xc7be,0xc7bb,0xc7b7,
+ 0xc7b4,0xc7b2,0xc7ae,0xc7ab,0xc7a7,0xc7a4,0xc7a2,0xc79e,0xc79b,0xc797,0xc795,0xc792,0xc78e,0xc78b,0xc787,0xc785,
+ 0xc782,0xc77e,0xc77b,0xc779,0xc775,0xc772,0xc76e,0xc76b,0xc769,0xc765,0xc762,0xc75e,0xc75c,0xc759,0xc755,0xc752,
+ 0xc74e,0xc74c,0xc749,0xc745,0xc742,0xc740,0xc73c,0xc739,0xc735,0xc732,0xc730,0xc72c,0xc729,0xc725,0xc724,0xc720,
+ 0xc71c,0xc719,0xc715,0xc714,0xc710,0xc70c,0xc709,0xc707,0xc704,0xc700,0xc6fc,0xc6f9,0xc6f7,0xc6f4,0xc6f0,0xc6ec,
+ 0xc6eb,0xc6e7,0xc6e4,0xc6e0,0xc6dc,0xc6db,0xc6d7,0xc6d4,0xc6d0,0xc6ce,0xc6cb,0xc6c7,0xc6c4,0xc6c0,0xc6be,0xc6bb,
+ 0xc6b7,0xc6b4,0xc6b2,0xc6ae,0xc6ab,0xc6a7,0xc6a4,0xc6a2,0xc69e,0xc69b,0xc697,0xc695,0xc692,0xc68e,0xc68b,0xc687,
+ 0xc685,0xc682,0xc67e,0xc67b,0xc679,0xc675,0xc672,0xc66e,0xc66b,0xc669,0xc665,0xc662,0xc65e,0xc65c,0xc659,0xc655,
+ 0xc653,0xc650,0xc64c,0xc649,0xc645,0xc643,0xc640,0xc63c,0xc639,0xc637,0xc633,0xc630,0xc62c,0xc629,0xc627,0xc623,
+ 0xc620,0xc61c,0xc61b,0xc617,0xc614,0xc610,0xc60c,0xc60b,0xc607,0xc604,0xc600,0xc5fe,0xc5fb,0xc5f7,0xc5f4,0xc5f2,
+ 0xc5ee,0xc5eb,0xc5e7,0xc5e4,0xc5e2,0xc5de,0xc5db,0xc5d7,0xc5d5,0xc5d2,0xc5ce,0xc5cb,0xc5c7,0xc5c5,0xc5c2,0xc5be,
+ 0xc5bb,0xc5b9,0xc5b6,0xc5b2,0xc5ae,0xc5ad,0xc5a9,0xc5a6,0xc5a2,0xc59e,0xc59d,0xc599,0xc596,0xc592,0xc590,0xc58d,
+ 0xc589,0xc586,0xc582,0xc580,0xc57d,0xc579,0xc576,0xc574,0xc570,0xc56d,0xc569,0xc566,0xc564,0xc560,0xc55d,0xc559,
+ 0xc558,0xc554,0xc550,0xc54d,0xc54b,0xc548,0xc544,0xc540,0xc53d,0xc53b,0xc538,0xc534,0xc531,0xc52f,0xc52b,0xc528,
+ 0xc524,0xc521,0xc51f,0xc51b,0xc518,0xc514,0xc512,0xc50f,0xc50b,0xc508,0xc506,0xc502,0xc4ff,0xc4fb,0xc4f8,0xc4f6,
+ 0xc4f2,0xc4ef,0xc4eb,0xc4ea,0xc4e6,0xc4e2,0xc4df,0xc4db,0xc4da,0xc4d6,0xc4d3,0xc4cf,0xc4cd,0xc4ca,0xc4c6,0xc4c3,
+ 0xc4c0,0xc4bd,0xc4b9,0xc4b8,0xc4b4,0xc4b1,0xc4ad,0xc4ab,0xc4a8,0xc4a4,0xc4a1,0xc49f,0xc49b,0xc498,0xc494,0xc493,
+ 0xc48f,0xc48b,0xc488,0xc484,0xc483,0xc47f,0xc47c,0xc478,0xc476,0xc473,0xc46f,0xc46c,0xc46a,0xc466,0xc463,0xc45f,
+ 0xc45e,0xc45a,0xc457,0xc453,0xc44f,0xc44e,0xc44a,0xc447,0xc443,0xc441,0xc43e,0xc43a,0xc437,0xc435,0xc431,0xc42e,
+ 0xc42a,0xc427,0xc425,0xc422,0xc41e,0xc41a,0xc419,0xc415,0xc412,0xc40e,0xc40c,0xc409,0xc405,0xc402,0xc400,0xc3fc,
+ 0xc3f9,0xc3f5,0xc3f2,0xc3f0,0xc3ed,0xc3e9,0xc3e6,0xc3e4,0xc3e0,0xc3dd,0xc3d9,0xc3d7,0xc3d4,0xc3d0,0xc3cd,0xc3cb,
+ 0xc3c8,0xc3c4,0xc3c0,0xc3bd,0xc3bb,0xc3b8,0xc3b4,0xc3b1,0xc3af,0xc3ab,0xc3a8,0xc3a4,0xc3a2,0xc39f,0xc39b,0xc398,
+ 0xc396,0xc393,0xc38f,0xc38b,0xc388,0xc386,0xc383,0xc37f,0xc37c,0xc37a,0xc376,0xc373,0xc36f,0xc36d,0xc36a,0xc366,
+ 0xc363,0xc35f,0xc35e,0xc35a,0xc357,0xc353,0xc351,0xc34e,0xc34a,0xc347,0xc345,0xc341,0xc33e,0xc33a,0xc338,0xc335,
+ 0xc332,0xc32e,0xc32b,0xc327,0xc324,0xc322,0xc31f,0xc31b,0xc317,0xc316,0xc312,0xc30f,0xc30b,0xc309,0xc306,0xc302,
+ 0xc2ff,0xc2fd,0xc2fa,0xc2f6,0xc2f3,0xc2f1,0xc2ed,0xc2ea,0xc2e6,0xc2e5,0xc2e1,0xc2dd,0xc2da,0xc2d8,0xc2d5,0xc2d1,
+ 0xc2ce,0xc2ca,0xc2c8,0xc2c5,0xc2c1,0xc2be,0xc2bc,0xc2b9,0xc2b5,0xc2b2,0xc2b0,0xc2ac,0xc2a9,0xc2a5,0xc2a3,0xc2a0,
+ 0xc29c,0xc299,0xc297,0xc294,0xc290,0xc28d,0xc28b,0xc287,0xc284,0xc280,0xc27f,0xc27b,0xc278,0xc274,0xc272,0xc26f,
+ 0xc26b,0xc268,0xc264,0xc262,0xc25f,0xc25b,0xc258,0xc256,0xc253,0xc24f,0xc24c,0xc24a,0xc246,0xc243,0xc23f,0xc23e,
+ 0xc23a,0xc236,0xc233,0xc231,0xc22e,0xc22a,0xc227,0xc225,0xc221,0xc21e,0xc21a,0xc219,0xc215,0xc212,0xc20e,0xc20c,
+ 0xc209,0xc205,0xc202,0xc1fe,0xc1fc,0xc1f9,0xc1f5,0xc1f2,0xc1f0,0xc1ed,0xc1e9,0xc1e6,0xc1e4,0xc1e0,0xc1dd,0xc1d9,
+ 0xc1d8,0xc1d4,0xc1d1,0xc1cd,0xc1cb,0xc1c8,0xc1c4,0xc1c1,0xc1bf,0xc1bb,0xc1b8,0xc1b4,0xc1b3,0xc1af,0xc1ac,0xc1a8,
+ 0xc1a5,0xc1a1,0xc1a0,0xc19c,0xc199,0xc195,0xc193,0xc190,0xc18c,0xc189,0xc187,0xc184,0xc180,0xc17d,0xc17b,0xc177,
+ 0xc174,0xc170,0xc16e,0xc16b,0xc167,0xc164,0xc162,0xc15f,0xc15b,0xc158,0xc156,0xc152,0xc14f,0xc14b,0xc14a,0xc146,
+ 0xc143,0xc13f,0xc13d,0xc13a,0xc136,0xc133,0xc131,0xc12e,0xc12a,0xc127,0xc125,0xc121,0xc11e,0xc11a,0xc119,0xc115,
+ 0xc112,0xc10e,0xc10c,0xc109,0xc105,0xc102,0xc100,0xc0fc,0xc0f9,0xc0f5,0xc0f4,0xc0f0,0xc0ed,0xc0e9,0xc0e7,0xc0e4,
+ 0xc0e0,0xc0dd,0xc0d9,0xc0d8,0xc0d4,0xc0d1,0xc0cd,0xc0cb,0xc0c8,0xc0c4,0xc0c1,0xc0bf,0xc0bc,0xc0b8,0xc0b5,0xc0b3,
+ 0xc0af,0xc0ac,0xc0a8,0xc0a7,0xc0a3,0xc0a0,0xc09c,0xc09a,0xc097,0xc093,0xc090,0xc08e,0xc08a,0xc087,0xc083,0xc082,
+ 0xc07e,0xc07b,0xc077,0xc075,0xc072,0xc06e,0xc06b,0xc069,0xc066,0xc062,0xc05f,0xc05d,0xc059,0xc056,0xc052,0xc051,
+ 0xc04d,0xc04a,0xc046,0xc044,0xc041,0xc03d,0xc03a,0xc038,0xc035,0xc031,0xc02e,0xc02c,0xc028,0xc025,0xc021,0xc020,
+ 0xc01b,0xc019,0xc016,0xc012,0xc00f,0xc00d,0xc009,0xc006,0xc002,0xc001,0xbffd,0xbffa,0xbff6,0xbff4,0xbff1,0xbfed,
+ 0xbfea,0xbfe8,0xbfe5,0xbfe1,0xbfde,0xbfdc,0xbfd9,0xbfd5,0xbfd2,0xbfd0,0xbfcc,0xbfc9,0xbfc5,0xbfc4,0xbfc0,0xbfbd,
+ 0xbfb9,0xbfb7,0xbfb4,0xbfb0,0xbfad,0xbfab,0xbfa8,0xbfa4,0xbfa1,0xbf9f,0xbf9b,0xbf98,0xbf94,0xbf93,0xbf8f,0xbf8c,
+ 0xbf88,0xbf86,0xbf83,0xbf7f,0xbf7c,0xbf7a,0xbf77,0xbf73,0xbf70,0xbf6e,0xbf6b,0xbf67,0xbf64,0xbf62,0xbf5e,0xbf5b,
+ 0xbf59,0xbf56,0xbf52,0xbf4f,0xbf4d,0xbf49,0xbf46,0xbf42,0xbf41,0xbf3d,0xbf3a,0xbf36,0xbf34,0xbf31,0xbf2d,0xbf2a,
+ 0xbf28,0xbf25,0xbf21,0xbf1e,0xbf1c,0xbf18,0xbf15,0xbf11,0xbf10,0xbf0c,0xbf09,0xbf05,0xbf03,0xbf00,0xbefd,0xbef9,
+ 0xbef7,0xbef4,0xbef0,0xbeed,0xbeeb,0xbee8,0xbee4,0xbee1,0xbedf,0xbedb,0xbed8,0xbed4,0xbed3,0xbecf,0xbecc,0xbec8,
+ 0xbec6,0xbec3,0xbebf,0xbebc,0xbeba,0xbeb7,0xbeb3,0xbeb0,0xbeae,0xbeaa,0xbea7,0xbea3,0xbea2,0xbe9e,0xbe9b,0xbe97,
+ 0xbe96,0xbe92,0xbe8f,0xbe8b,0xbe8a,0xbe86,0xbe83,0xbe7f,0xbe7d,0xbe7a,0xbe76,0xbe73,0xbe71,0xbe6e,0xbe6a,0xbe67,
+ 0xbe65,0xbe62,0xbe5e,0xbe5b,0xbe59,0xbe55,0xbe52,0xbe4e,0xbe4d,0xbe49,0xbe46,0xbe42,0xbe40,0xbe3d,0xbe39,0xbe36,
+ 0xbe34,0xbe31,0xbe2d,0xbe2c,0xbe28,0xbe25,0xbe21,0xbe1f,0xbe1c,0xbe18,0xbe15,0xbe13,0xbe10,0xbe0c,0xbe09,0xbe07,
+ 0xbe03,0xbe00,0xbdfd,0xbdfb,0xbdf7,0xbdf4,0xbdf0,0xbdef,0xbdeb,0xbde8,0xbde4,0xbde2,0xbddf,0xbddb,0xbdd8,0xbdd6,
+ 0xbdd3,0xbdcf,0xbdcd,0xbdca,0xbdc7,0xbdc3,0xbdc1,0xbdbe,0xbdba,0xbdb7,0xbdb5,0xbdb2,0xbdae,0xbdab,0xbda9,0xbda5,
+ 0xbda2,0xbd9e,0xbd9d,0xbd99,0xbd96,0xbd92,0xbd91,0xbd8d,0xbd8a,0xbd86,0xbd84,0xbd81,0xbd7d,0xbd7a,0xbd78,0xbd75,
+ 0xbd71,0xbd6f,0xbd6c,0xbd68,0xbd65,0xbd63,0xbd60,0xbd5c,0xbd59,0xbd57,0xbd54,0xbd50,0xbd4d,0xbd4b,0xbd47,0xbd44,
+ 0xbd40,0xbd3f,0xbd3b,0xbd38,0xbd34,0xbd32,0xbd2f,0xbd2b,0xbd28,0xbd26,0xbd23,0xbd1f,0xbd1c,0xbd1a,0xbd17,0xbd13,
+ 0xbd10,0xbd0d,0xbd0b,0xbd08,0xbd04,0xbd01,0xbcff,0xbcfb,0xbcf8,0xbcf5,0xbcf3,0xbcef,0xbcec,0xbce8,0xbce7,0xbce3,
+ 0xbce0,0xbcde,0xbcdb,0xbcd7,0xbcd4,0xbcd2,0xbcce,0xbccb,0xbcc7,0xbcc6,0xbcc2,0xbcbf,0xbcbb,0xbcba,0xbcb6,0xbcb3,
+ 0xbcb1,0xbcad,0xbcaa,0xbca7,0xbca5,0xbca1,0xbc9e,0xbc9a,0xbc99,0xbc95,0xbc92,0xbc8e,0xbc8c,0xbc89,0xbc86,0xbc82,
+ 0xbc80,0xbc7d,0xbc79,0xbc78,0xbc74,0xbc71,0xbc6d,0xbc6c,0xbc68,0xbc65,0xbc61,0xbc5f,0xbc5c,0xbc58,0xbc55,0xbc53,
+ 0xbc50,0xbc4c,0xbc4b,0xbc47,0xbc44,0xbc40,0xbc3e,0xbc3b,0xbc38,0xbc34,0xbc32,0xbc2f,0xbc2b,0xbc28,0xbc26,0xbc23,
+ 0xbc1f,0xbc1d,0xbc1a,0xbc17,0xbc13,0xbc11,0xbc0e,0xbc0a,0xbc07,0xbc05,0xbc02,0xbbfe,0xbbfb,0xbbf9,0xbbf6,0xbbf2,
+ 0xbbf0,0xbbed,0xbbe9,0xbbe6,0xbbe4,0xbbe1,0xbbdd,0xbbda,0xbbd8,0xbbd5,0xbbd1,0xbbce,0xbbcc,0xbbc9,0xbbc5,0xbbc2,
+ 0xbbc0,0xbbbc,0xbbb9,0xbbb7,0xbbb4,0xbbb0,0xbbad,0xbbab,0xbba8,0xbba4,0xbba1,0xbb9f,0xbb9b,0xbb98,0xbb94,0xbb93,
+ 0xbb90,0xbb8c,0xbb89,0xbb87,0xbb84,0xbb80,0xbb7d,0xbb7b,0xbb77,0xbb74,0xbb70,0xbb6f,0xbb6b,0xbb68,0xbb66,0xbb63,
+ 0xbb5f,0xbb5c,0xbb5a,0xbb57,0xbb53,0xbb50,0xbb4e,0xbb4a,0xbb47,0xbb43,0xbb42,0xbb3e,0xbb3b,0xbb39,0xbb36,0xbb32,
+ 0xbb2f,0xbb2d,0xbb2a,0xbb26,0xbb23,0xbb21,0xbb1d,0xbb1a,0xbb18,0xbb15,0xbb11,0xbb0e,0xbb0c,0xbb09,0xbb05,0xbb02,
+ 0xbb00,0xbafd,0xbaf9,0xbaf6,0xbaf4,0xbaf0,0xbaed,0xbaeb,0xbae8,0xbae4,0xbae1,0xbadf,0xbadc,0xbad8,0xbad5,0xbad3,
+ 0xbad0,0xbacc,0xbaca,0xbac7,0xbac3,0xbac0,0xbabe,0xbabb,0xbab7,0xbab4,0xbab2,0xbaaf,0xbaab,0xbaa9,0xbaa6,0xbaa3,
+ 0xba9f,0xba9d,0xba9a,0xba96,0xba93,0xba91,0xba8e,0xba8a,0xba87,0xba85,0xba82,0xba7e,0xba7c,0xba79,0xba76,0xba72,
+ 0xba70,0xba6d,0xba69,0xba66,0xba64,0xba61,0xba5d,0xba5c,0xba58,0xba55,0xba51,0xba4f,0xba4c,0xba49,0xba45,0xba43,
+ 0xba40,0xba3c,0xba39,0xba37,0xba34,0xba30,0xba2f,0xba2b,0xba28,0xba24,0xba23,0xba1f,0xba1c,0xba18,0xba16,0xba13,
+ 0xba10,0xba0d,0xba09,0xba08,0xba04,0xba01,0xb9fd,0xb9fc,0xb9f8,0xb9f5,0xb9f3,0xb9ef,0xb9ec,0xb9e9,0xb9e7,0xb9e3,
+ 0xb9e0,0xb9dd,0xb9db,0xb9d7,0xb9d4,0xb9d2,0xb9cf,0xb9cb,0xb9c8,0xb9c6,0xb9c3,0xb9bf,0xb9bd,0xb9ba,0xb9b7,0xb9b3,
+ 0xb9b1,0xb9ae,0xb9ab,0xb9a7,0xb9a5,0xb9a2,0xb99e,0xb99d,0xb999,0xb996,0xb992,0xb991,0xb98d,0xb98a,0xb988,0xb985,
+ 0xb981,0xb97e,0xb97c,0xb979,0xb975,0xb972,0xb970,0xb96d,0xb969,0xb967,0xb964,0xb960,0xb95d,0xb95b,0xb958,0xb954,
+ 0xb953,0xb94f,0xb94c,0xb948,0xb947,0xb943,0xb940,0xb93c,0xb93b,0xb937,0xb934,0xb932,0xb92f,0xb92b,0xb928,0xb926,
+ 0xb922,0xb91f,0xb91c,0xb91a,0xb916,0xb913,0xb911,0xb90e,0xb90a,0xb907,0xb905,0xb902,0xb8fe,0xb8fd,0xb8f9,0xb8f6,
+ 0xb8f2,0xb8f0,0xb8ed,0xb8ea,0xb8e6,0xb8e4,0xb8e1,0xb8de,0xb8dc,0xb8d8,0xb8d5,0xb8d1,0xb8d0,0xb8cc,0xb8c9,0xb8c7,
+ 0xb8c4,0xb8c0,0xb8bd,0xb8bb,0xb8b8,0xb8b4,0xb8b1,0xb8af,0xb8ac,0xb8a8,0xb8a6,0xb8a3,0xb8a0,0xb89c,0xb89a,0xb897,
+ 0xb894,0xb890,0xb88f,0xb88b,0xb888,0xb884,0xb883,0xb87f,0xb87c,0xb87a,0xb877,0xb873,0xb870,0xb86e,0xb86b,0xb867,
+ 0xb865,0xb862,0xb85f,0xb85b,0xb859,0xb856,0xb853,0xb84f,0xb84d,0xb84a,0xb846,0xb845,0xb841,0xb83e,0xb83a,0xb839,
+ 0xb835,0xb832,0xb830,0xb82d,0xb829,0xb826,0xb824,0xb821,0xb81d,0xb81c,0xb818,0xb815,0xb811,0xb80f,0xb80c,0xb809,
+ 0xb807,0xb803,0xb800,0xb7fd,0xb7fb,0xb7f7,0xb7f4,0xb7f1,0xb7ef,0xb7eb,0xb7e8,0xb7e6,0xb7e3,0xb7df,0xb7dc,0xb7da,
+ 0xb7d7,0xb7d3,0xb7d2,0xb7ce,0xb7cb,0xb7c7,0xb7c6,0xb7c2,0xb7bf,0xb7bd,0xb7ba,0xb7b6,0xb7b3,0xb7b1,0xb7ae,0xb7aa,
+ 0xb7a8,0xb7a5,0xb7a1,0xb79e,0xb79c,0xb799,0xb795,0xb792,0xb790,0xb78d,0xb789,0xb788,0xb784,0xb781,0xb77d,0xb77c,
+ 0xb778,0xb775,0xb773,0xb770,0xb76c,0xb769,0xb767,0xb764,0xb760,0xb75e,0xb75b,0xb758,0xb754,0xb752,0xb74f,0xb74c,
+ 0xb74a,0xb746,0xb743,0xb740,0xb73e,0xb73a,0xb737,0xb733,0xb732,0xb72e,0xb72b,0xb729,0xb726,0xb722,0xb71f,0xb71d,
+ 0xb71a,0xb717,0xb713,0xb710,0xb70e,0xb70b,0xb707,0xb706,0xb702,0xb6ff,0xb6fc,0xb6fa,0xb6f6,0xb6f3,0xb6f1,0xb6ee,
+ 0xb6ea,0xb6e7,0xb6e5,0xb6e2,0xb6de,0xb6dd,0xb6d9,0xb6d6,0xb6d2,0xb6d1,0xb6cd,0xb6ca,0xb6c8,0xb6c5,0xb6c1,0xb6be,
+ 0xb6bc,0xb6b9,0xb6b5,0xb6b4,0xb6b0,0xb6ad,0xb6a9,0xb6a8,0xb6a4,0xb6a1,0xb69f,0xb69c,0xb698,0xb697,0xb693,0xb690,
+ 0xb68c,0xb68b,0xb687,0xb684,0xb682,0xb67f,0xb67b,0xb678,0xb676,0xb673,0xb66f,0xb66e,0xb66a,0xb667,0xb663,0xb662,
+ 0xb65e,0xb65b,0xb659,0xb656,0xb652,0xb64f,0xb64d,0xb64a,0xb646,0xb644,0xb641,0xb63e,0xb63a,0xb638,0xb635,0xb632,
+ 0xb630,0xb62c,0xb629,0xb626,0xb624,0xb621,0xb61d,0xb61b,0xb618,0xb615,0xb613,0xb60f,0xb60c,0xb609,0xb607,0xb603,
+ 0xb600,0xb5fe,0xb5fb,0xb5f7,0xb5f4,0xb5f2,0xb5ef,0xb5eb,0xb5ea,0xb5e6,0xb5e3,0xb5df,0xb5de,0xb5da,0xb5d7,0xb5d5,
+ 0xb5d2,0xb5ce,0xb5cb,0xb5c9,0xb5c6,0xb5c2,0xb5c1,0xb5bd,0xb5ba,0xb5b6,0xb5b5,0xb5b1,0xb5ae,0xb5ac,0xb5a9,0xb5a5,
+ 0xb5a2,0xb5a0,0xb59d,0xb59a,0xb596,0xb595,0xb591,0xb58e,0xb58c,0xb589,0xb585,0xb582,0xb580,0xb57d,0xb579,0xb577,
+ 0xb574,0xb571,0xb56f,0xb56c,0xb568,0xb565,0xb563,0xb560,0xb55c,0xb55a,0xb557,0xb554,0xb550,0xb54f,0xb54b,0xb548,
+ 0xb546,0xb543,0xb53f,0xb53d,0xb53a,0xb537,0xb533,0xb532,0xb52e,0xb52b,0xb529,0xb526,0xb522,0xb51f,0xb51d,0xb51a,
+ 0xb516,0xb514,0xb511,0xb50e,0xb50a,0xb509,0xb505,0xb502,0xb500,0xb4fd,0xb4f9,0xb4f7,0xb4f4,0xb4f1,0xb4ed,0xb4ec,
+ 0xb4e8,0xb4e5,0xb4e3,0xb4e0,0xb4dc,0xb4d9,0xb4d7,0xb4d4,0xb4d0,0xb4ce,0xb4cb,0xb4c8,0xb4c6,0xb4c3,0xb4bf,0xb4bc,
+ 0xb4ba,0xb4b7,0xb4b3,0xb4b1,0xb4ae,0xb4ab,0xb4a7,0xb4a6,0xb4a2,0xb49f,0xb49d,0xb49a,0xb496,0xb493,0xb491,0xb48e,
+ 0xb48a,0xb489,0xb485,0xb482,0xb480,0xb47d,0xb479,0xb476,0xb474,0xb471,0xb46d,0xb46b,0xb468,0xb465,0xb461,0xb460,
+ 0xb45c,0xb459,0xb457,0xb454,0xb450,0xb44e,0xb44b,0xb448,0xb444,0xb443,0xb43f,0xb43c,0xb43a,0xb437,0xb433,0xb430,
+ 0xb42d,0xb42b,0xb428,0xb424,0xb421,0xb41f,0xb41c,0xb418,0xb417,0xb413,0xb410,0xb40e,0xb40b,0xb407,0xb404,0xb402,
+ 0xb3ff,0xb3fb,0xb3fa,0xb3f6,0xb3f3,0xb3f1,0xb3ee,0xb3ea,0xb3e7,0xb3e5,0xb3e2,0xb3df,0xb3dd,0xb3da,0xb3d6,0xb3d4,
+ 0xb3d1,0xb3ce,0xb3ca,0xb3c9,0xb3c5,0xb3c2,0xb3c0,0xb3bd,0xb3b9,0xb3b8,0xb3b4,0xb3b1,0xb3ad,0xb3ac,0xb3a8,0xb3a5,
+ 0xb3a3,0xb3a0,0xb39c,0xb39b,0xb397,0xb394,0xb390,0xb38f,0xb38b,0xb388,0xb386,0xb383,0xb37f,0xb37e,0xb37a,0xb377,
+ 0xb375,0xb372,0xb36e,0xb36b,0xb369,0xb366,0xb363,0xb361,0xb35d,0xb35a,0xb358,0xb355,0xb352,0xb34e,0xb34c,0xb349,
+ 0xb346,0xb344,0xb341,0xb33d,0xb33b,0xb338,0xb335,0xb331,0xb330,0xb32c,0xb329,0xb327,0xb324,0xb320,0xb31f,0xb31b,
+ 0xb318,0xb314,0xb313,0xb30f,0xb30c,0xb30a,0xb307,0xb303,0xb302,0xb2fe,0xb2fb,0xb2f8,0xb2f6,0xb2f2,0xb2ef,0xb2ed,
+ 0xb2ea,0xb2e7,0xb2e5,0xb2e1,0xb2de,0xb2db,0xb2d9,0xb2d6,0xb2d2,0xb2d0,0xb2cd,0xb2ca,0xb2c8,0xb2c5,0xb2c1,0xb2be,
+ 0xb2bc,0xb2b9,0xb2b5,0xb2b2,0xb2b0,0xb2ad,0xb2aa,0xb2a8,0xb2a4,0xb2a1,0xb29f,0xb29c,0xb299,0xb295,0xb293,0xb290,
+ 0xb28d,0xb28b,0xb288,0xb284,0xb283,0xb27f,0xb27c,0xb27a,0xb277,0xb273,0xb270,0xb26e,0xb26b,0xb267,0xb266,0xb262,
+ 0xb25f,0xb25d,0xb25a,0xb256,0xb253,0xb251,0xb24e,0xb24b,0xb249,0xb246,0xb242,0xb240,0xb23d,0xb23a,0xb238,0xb235,
+ 0xb231,0xb22e,0xb22c,0xb229,0xb225,0xb224,0xb220,0xb21d,0xb21b,0xb218,0xb214,0xb211,0xb20f,0xb20c,0xb208,0xb207,
+ 0xb203,0xb200,0xb1fe,0xb1fb,0xb1f8,0xb1f6,0xb1f2,0xb1ef,0xb1ec,0xb1ea,0xb1e7,0xb1e3,0xb1e1,0xb1de,0xb1db,0xb1d9,
+ 0xb1d6,0xb1d2,0xb1cf,0xb1cd,0xb1ca,0xb1c6,0xb1c5,0xb1c1,0xb1be,0xb1bc,0xb1b9,0xb1b5,0xb1b4,0xb1b0,0xb1ad,0xb1aa,
+ 0xb1a8,0xb1a4,0xb1a1,0xb19f,0xb19c,0xb199,0xb197,0xb194,0xb190,0xb18d,0xb18b,0xb188,0xb184,0xb183,0xb17f,0xb17c,
+ 0xb17a,0xb177,0xb173,0xb172,0xb16e,0xb16b,0xb167,0xb166,0xb162,0xb15f,0xb15d,0xb15a,0xb156,0xb155,0xb151,0xb14e,
+ 0xb14c,0xb149,0xb145,0xb144,0xb140,0xb13d,0xb13b,0xb138,0xb134,0xb133,0xb12f,0xb12c,0xb129,0xb127,0xb124,0xb120,
+ 0xb11e,0xb11b,0xb118,0xb116,0xb113,0xb10f,0xb10e,0xb10a,0xb107,0xb103,0xb102,0xb0fe,0xb0fb,0xb0f9,0xb0f6,0xb0f2,
+ 0xb0f1,0xb0ed,0xb0ea,0xb0e8,0xb0e5,0xb0e2,0xb0de,0xb0dc,0xb0d9,0xb0d6,0xb0d4,0xb0d1,0xb0cd,0xb0cc,0xb0c8,0xb0c5,
+ 0xb0c3,0xb0c0,0xb0bc,0xb0b9,0xb0b7,0xb0b4,0xb0b1,0xb0af,0xb0ab,0xb0a8,0xb0a6,0xb0a3,0xb0a0,0xb09e,0xb09b,0xb097,
+ 0xb095,0xb092,0xb08f,0xb08b,0xb08a,0xb086,0xb083,0xb081,0xb07e,0xb07a,0xb079,0xb075,0xb072,0xb070,0xb06d,0xb069,
+ 0xb066,0xb064,0xb061,0xb05e,0xb05c,0xb059,0xb055,0xb053,0xb050,0xb04d,0xb04b,0xb048,0xb044,0xb041,0xb03f,0xb03c,
+ 0xb038,0xb037,0xb033,0xb030,0xb02e,0xb02b,0xb028,0xb026,0xb022,0xb01f,0xb01c,0xb01a,0xb017,0xb013,0xb012,0xb00e,
+ 0xb00b,0xb009,0xb006,0xb002,0xb001,0xaffd,0xaffa,0xaff6,0xaff5,0xaff1,0xafee,0xafec,0xafe9,0xafe6,0xafe4,0xafe0,
+ 0xafde,0xafdb,0xafd8,0xafd6,0xafd2,0xafcf,0xafcd,0xafca,0xafc7,0xafc5,0xafc2,0xafbe,0xafbd,0xafb9,0xafb6,0xafb2,
+ 0xafb1,0xafad,0xafaa,0xafa8,0xafa5,0xafa2,0xafa0,0xaf9d,0xaf99,0xaf98,0xaf94,0xaf91,0xaf8f,0xaf8c,0xaf88,0xaf87,
+ 0xaf83,0xaf80,0xaf7e,0xaf7b,0xaf78,0xaf74,0xaf72,0xaf6f,0xaf6c,0xaf6a,0xaf67,0xaf63,0xaf62,0xaf5e,0xaf5b,0xaf59,
+ 0xaf56,0xaf52,0xaf51,0xaf4d,0xaf4a,0xaf48,0xaf45,0xaf42,0xaf3e,0xaf3d,0xaf39,0xaf36,0xaf34,0xaf31,0xaf2d,0xaf2c,
+ 0xaf28,0xaf25,0xaf23,0xaf20,0xaf1d,0xaf1b,0xaf18,0xaf14,0xaf13,0xaf0f,0xaf0c,0xaf08,0xaf07,0xaf03,0xaf00,0xaefe,
+ 0xaefb,0xaef8,0xaef6,0xaef3,0xaeef,0xaeed,0xaeea,0xaee7,0xaee5,0xaee2,0xaede,0xaedd,0xaed9,0xaed6,0xaed3,0xaed1,
+ 0xaecd,0xaeca,0xaec8,0xaec5,0xaec2,0xaec0,0xaebd,0xaeb9,0xaeb8,0xaeb4,0xaeb1,0xaeaf,0xaeac,0xaea8,0xaea7,0xaea3,
+ 0xaea0,0xae9e,0xae9b,0xae98,0xae94,0xae93,0xae8f,0xae8c,0xae8a,0xae87,0xae83,0xae82,0xae7e,0xae7b,0xae79,0xae76,
+ 0xae74,0xae71,0xae6d,0xae6a,0xae68,0xae65,0xae61,0xae60,0xae5c,0xae59,0xae57,0xae54,0xae51,0xae4f,0xae4c,0xae48,
+ 0xae47,0xae43,0xae40,0xae3e,0xae3b,0xae37,0xae36,0xae32,0xae2f,0xae2d,0xae2a,0xae27,0xae23,0xae22,0xae1e,0xae1b,
+ 0xae19,0xae16,0xae12,0xae11,0xae0d,0xae0a,0xae08,0xae05,0xae02,0xae00,0xadfd,0xadf9,0xadf8,0xadf4,0xadf1,0xadef,
+ 0xadec,0xade8,0xade7,0xade3,0xade0,0xaddd,0xaddb,0xadd8,0xadd4,0xadd3,0xadcf,0xadcc,0xadca,0xadc7,0xadc4,0xadc2,
+ 0xadbe,0xadbb,0xadb9,0xadb6,0xadb3,0xadb1,0xadae,0xadaa,0xada9,0xada5,0xada2,0xada0,0xad9d,0xad9a,0xad96,0xad95,
+ 0xad91,0xad8e,0xad8c,0xad89,0xad85,0xad84,0xad80,0xad7d,0xad7b,0xad78,0xad75,0xad73,0xad70,0xad6c,0xad6b,0xad67,
+ 0xad64,0xad62,0xad5f,0xad5b,0xad5a,0xad56,0xad53,0xad50,0xad4e,0xad4b,0xad47,0xad46,0xad42,0xad3f,0xad3d,0xad3a,
+ 0xad36,0xad35,0xad31,0xad2e,0xad2c,0xad29,0xad26,0xad24,0xad21,0xad1d,0xad1c,0xad18,0xad15,0xad13,0xad10,0xad0c,
+ 0xad0a,0xad06,0xad05,0xad01,0xacfe,0xacfc,0xacf9,0xacf6,0xacf4,0xacf1,0xaced,0xacec,0xace8,0xace5,0xace3,0xace0,
+ 0xacdd,0xacdb,0xacd8,0xacd4,0xacd3,0xaccf,0xaccc,0xacca,0xacc7,0xacc4,0xacc2,0xacbf,0xacbb,0xacba,0xacb6,0xacb3,
+ 0xacb1,0xacae,0xacab,0xaca7,0xaca6,0xaca2,0xac9f,0xac9d,0xac9a,0xac96,0xac95,0xac91,0xac8e,0xac8c,0xac89,0xac86,
+ 0xac84,0xac81,0xac7d,0xac7c,0xac78,0xac75,0xac73,0xac70,0xac6d,0xac6b,0xac68,0xac64,0xac63,0xac5f,0xac5c,0xac5a,
+ 0xac57,0xac54,0xac52,0xac4f,0xac4b,0xac4a,0xac46,0xac43,0xac41,0xac3e,0xac3b,0xac39,0xac36,0xac32,0xac30,0xac2d,
+ 0xac2a,0xac28,0xac25,0xac21,0xac20,0xac1c,0xac19,0xac17,0xac14,0xac11,0xac0f,0xac0c,0xac08,0xac07,0xac03,0xac00,
+ 0xabfe,0xabfb,0xabf8,0xabf4,0xabf3,0xabef,0xabec,0xabea,0xabe7,0xabe4,0xabe2,0xabdf,0xabdb,0xabda,0xabd6,0xabd3,
+ 0xabd1,0xabce,0xabcb,0xabc9,0xabc5,0xabc2,0xabc0,0xabbd,0xabba,0xabb8,0xabb5,0xabb1,0xabb0,0xabac,0xaba9,0xaba7,
+ 0xaba3,0xaba2,0xab9e,0xab9b,0xab99,0xab96,0xab93,0xab91,0xab8e,0xab8a,0xab89,0xab85,0xab82,0xab80,0xab7d,0xab7a,
+ 0xab78,0xab75,0xab71,0xab70,0xab6c,0xab69,0xab67,0xab64,0xab61,0xab5f,0xab5c,0xab58,0xab57,0xab53,0xab50,0xab4e,
+ 0xab4b,0xab48,0xab46,0xab43,0xab3f,0xab3e,0xab3a,0xab37,0xab35,0xab32,0xab2f,0xab2d,0xab2a,0xab26,0xab25,0xab21,
+ 0xab1e,0xab1c,0xab19,0xab16,0xab14,0xab11,0xab0d,0xab0c,0xab08,0xab05,0xab03,0xab00,0xaafd,0xaafb,0xaaf8,0xaaf4,
+ 0xaaf3,0xaaef,0xaaec,0xaae9,0xaae7,0xaae4,0xaae0,0xaadf,0xaadb,0xaad8,0xaad6,0xaad3,0xaad0,0xaace,0xaacb,0xaac7,
+ 0xaac6,0xaac2,0xaabf,0xaabd,0xaaba,0xaab7,0xaab5,0xaab2,0xaaae,0xaaad,0xaaa9,0xaaa6,0xaaa4,0xaaa1,0xaa9e,0xaa9c,
+ 0xaa99,0xaa95,0xaa94,0xaa90,0xaa8d,0xaa8b,0xaa88,0xaa85,0xaa83,0xaa80,0xaa7c,0xaa7b,0xaa77,0xaa74,0xaa72,0xaa6f,
+ 0xaa6c,0xaa6a,0xaa67,0xaa63,0xaa62,0xaa5e,0xaa5b,0xaa59,0xaa56,0xaa53,0xaa51,0xaa4e,0xaa4a,0xaa49,0xaa45,0xaa42,
+ 0xaa41,0xaa3e,0xaa3a,0xaa39,0xaa35,0xaa32,0xaa30,0xaa2d,0xaa2a,0xaa28,0xaa25,0xaa21,0xaa20,0xaa1c,0xaa19,0xaa17,
+ 0xaa14,0xaa11,0xaa0f,0xaa0c,0xaa08,0xaa07,0xaa03,0xaa00,0xa9fe,0xa9fb,0xa9f8,0xa9f6,0xa9f3,0xa9ef,0xa9ee,0xa9ea,
+ 0xa9e7,0xa9e5,0xa9e2,0xa9df,0xa9dd,0xa9da,0xa9d6,0xa9d5,0xa9d1,0xa9ce,0xa9cc,0xa9c9,0xa9c6,0xa9c4,0xa9c1,0xa9bd,
+ 0xa9bc,0xa9b8,0xa9b5,0xa9b3,0xa9b0,0xa9ad,0xa9ab,0xa9a8,0xa9a4,0xa9a3,0xa99f,0xa99c,0xa99a,0xa997,0xa994,0xa992,
+ 0xa98f,0xa98c,0xa98a,0xa987,0xa983,0xa982,0xa97e,0xa97b,0xa979,0xa976,0xa973,0xa971,0xa96e,0xa96a,0xa969,0xa965,
+ 0xa962,0xa960,0xa95d,0xa95a,0xa958,0xa955,0xa951,0xa950,0xa94c,0xa949,0xa947,0xa944,0xa941,0xa93f,0xa93c,0xa938,
+ 0xa937,0xa933,0xa930,0xa92e,0xa92b,0xa928,0xa926,0xa923,0xa91f,0xa91e,0xa91a,0xa917,0xa915,0xa912,0xa90f,0xa90d,
+ 0xa90a,0xa906,0xa905,0xa901,0xa8fe,0xa8fc,0xa8f9,0xa8f6,0xa8f4,0xa8f1,0xa8ed,0xa8ec,0xa8e8,0xa8e5,0xa8e3,0xa8e0,
+ 0xa8de,0xa8db,0xa8d9,0xa8d6,0xa8d2,0xa8d1,0xa8cd,0xa8ca,0xa8c8,0xa8c5,0xa8c2,0xa8c0,0xa8bd,0xa8ba,0xa8b8,0xa8b5,
+ 0xa8b3,0xa8b0,0xa8ac,0xa8ab,0xa8a7,0xa8a4,0xa8a2,0xa89f,0xa89c,0xa89a,0xa897,0xa893,0xa892,0xa88e,0xa88b,0xa889,
+ 0xa886,0xa883,0xa881,0xa87e,0xa87b,0xa879,0xa876,0xa872,0xa871,0xa86d,0xa86a,0xa868,0xa865,0xa862,0xa860,0xa85d,
+ 0xa85b,0xa858,0xa854,0xa853,0xa850,0xa84c,0xa84b,0xa847,0xa844,0xa842,0xa83f,0xa83c,0xa83a,0xa837,0xa833,0xa832,
+ 0xa82e,0xa82b,0xa829,0xa826,0xa823,0xa821,0xa81e,0xa81b,0xa819,0xa816,0xa812,0xa811,0xa80d,0xa80a,0xa808,0xa805,
+ 0xa803,0xa800,0xa7fd,0xa7fb,0xa7f8,0xa7f4,0xa7f3,0xa7ef,0xa7ec,0xa7ea,0xa7e7,0xa7e4,0xa7e2,0xa7df,0xa7dc,0xa7da,
+ 0xa7d7,0xa7d3,0xa7d2,0xa7ce,0xa7cb,0xa7c9,0xa7c6,0xa7c3,0xa7c1,0xa7be,0xa7ba,0xa7b9,0xa7b5,0xa7b2,0xa7b1,0xa7ad,
+ 0xa7ac,0xa7a8,0xa7a5,0xa7a3,0xa7a0,0xa79d,0xa79b,0xa798,0xa794,0xa793,0xa78f,0xa78c,0xa78a,0xa787,0xa784,0xa782,
+ 0xa77f,0xa77c,0xa779,0xa777,0xa774,0xa770,0xa76f,0xa76b,0xa76a,0xa766,0xa763,0xa761,0xa75e,0xa75b,0xa759,0xa756,
+ 0xa753,0xa751,0xa74e,0xa74a,0xa749,0xa745,0xa742,0xa740,0xa73d,0xa73a,0xa738,0xa735,0xa732,0xa730,0xa72d,0xa72b,
+ 0xa728,0xa724,0xa723,0xa71f,0xa71c,0xa71a,0xa717,0xa714,0xa712,0xa70f,0xa70c,0xa70a,0xa707,0xa703,0xa702,0xa6fe,
+ 0xa6fb,0xa6f9,0xa6f6,0xa6f3,0xa6f1,0xa6ee,0xa6ec,0xa6e9,0xa6e6,0xa6e4,0xa6e1,0xa6dd,0xa6dc,0xa6d8,0xa6d5,0xa6d3,
+ 0xa6d0,0xa6cd,0xa6cb,0xa6c8,0xa6c5,0xa6c3,0xa6c0,0xa6bc,0xa6bb,0xa6b7,0xa6b4,0xa6b2,0xa6af,0xa6ad,0xa6aa,0xa6a7,
+ 0xa6a5,0xa6a2,0xa69f,0xa69d,0xa69a,0xa696,0xa695,0xa691,0xa68e,0xa68c,0xa689,0xa686,0xa684,0xa681,0xa67d,0xa67c,
+ 0xa679,0xa675,0xa674,0xa670,0xa66f,0xa66b,0xa668,0xa666,0xa663,0xa660,0xa65e,0xa65b,0xa657,0xa656,0xa653,0xa64f,
+ 0xa64e,0xa64a,0xa647,0xa645,0xa642,0xa63f,0xa63d,0xa63a,0xa636,0xa635,0xa631,0xa630,0xa62d,0xa629,0xa628,0xa624,
+ 0xa621,0xa61e,0xa61b,0xa619,0xa616,0xa614,0xa611,0xa60e,0xa60c,0xa609,0xa605,0xa604,0xa601,0xa5fd,0xa5fc,0xa5f8,
+ 0xa5f5,0xa5f3,0xa5f0,0xa5ee,0xa5eb,0xa5e8,0xa5e6,0xa5e3,0xa5e0,0xa5de,0xa5db,0xa5d7,0xa5d6,0xa5d3,0xa5cf,0xa5ce,
+ 0xa5ca,0xa5c7,0xa5c5,0xa5c2,0xa5c0,0xa5bd,0xa5ba,0xa5b8,0xa5b5,0xa5b2,0xa5b0,0xa5ad,0xa5a9,0xa5a8,0xa5a4,0xa5a1,
+ 0xa5a0,0xa59c,0xa59b,0xa597,0xa594,0xa592,0xa58f,0xa58c,0xa58a,0xa587,0xa584,0xa582,0xa57f,0xa57b,0xa57a,0xa576,
+ 0xa575,0xa571,0xa56e,0xa56d,0xa569,0xa566,0xa564,0xa561,0xa55e,0xa55c,0xa559,0xa556,0xa554,0xa551,0xa54d,0xa54c,
+ 0xa548,0xa547,0xa543,0xa540,0xa53e,0xa53b,0xa538,0xa536,0xa533,0xa530,0xa52e,0xa52b,0xa527,0xa526,0xa523,0xa521,
+ 0xa51e,0xa51a,0xa519,0xa515,0xa512,0xa510,0xa50d,0xa50a,0xa508,0xa505,0xa502,0xa500,0xa4fd,0xa4f9,0xa4f8,0xa4f4,
+ 0xa4f3,0xa4f0,0xa4ec,0xa4eb,0xa4e7,0xa4e4,0xa4e2,0xa4df,0xa4dc,0xa4da,0xa4d7,0xa4d4,0xa4d2,0xa4cf,0xa4cd,0xa4ca,
+ 0xa4c7,0xa4c3,0xa4c2,0xa4be,0xa4bb,0xa4b9,0xa4b6,0xa4b4,0xa4b1,0xa4ae,0xa4ac,0xa4a9,0xa4a6,0xa4a4,0xa4a1,0xa49e,
+ 0xa49c,0xa499,0xa495,0xa494,0xa490,0xa48f,0xa48b,0xa488,0xa487,0xa483,0xa480,0xa47e,0xa47b,0xa478,0xa476,0xa473,
+ 0xa471,0xa46e,0xa46b,0xa469,0xa466,0xa462,0xa461,0xa45e,0xa45a,0xa459,0xa455,0xa452,0xa450,0xa44d,0xa44b,0xa448,
+ 0xa445,0xa443,0xa440,0xa43d,0xa43b,0xa438,0xa435,0xa433,0xa430,0xa42c,0xa42b,0xa427,0xa426,0xa422,0xa41f,0xa41e,
+ 0xa41a,0xa417,0xa415,0xa412,0xa40f,0xa40d,0xa40a,0xa408,0xa405,0xa402,0xa400,0xa3fd,0xa3f9,0xa3f8,0xa3f5,0xa3f1,
+ 0xa3f0,0xa3ec,0xa3e9,0xa3e7,0xa3e4,0xa3e2,0xa3df,0xa3dc,0xa3da,0xa3d7,0xa3d4,0xa3d2,0xa3cf,0xa3cc,0xa3ca,0xa3c7,
+ 0xa3c5,0xa3c2,0xa3be,0xa3bd,0xa3b9,0xa3b6,0xa3b5,0xa3b1,0xa3ae,0xa3ac,0xa3a9,0xa3a6,0xa3a4,0xa3a1,0xa39f,0xa39c,
+ 0xa399,0xa397,0xa394,0xa390,0xa38f,0xa38c,0xa388,0xa387,0xa383,0xa380,0xa37e,0xa37b,0xa379,0xa376,0xa373,0xa371,
+ 0xa36e,0xa36c,0xa369,0xa365,0xa364,0xa361,0xa35d,0xa35c,0xa358,0xa357,0xa353,0xa350,0xa34f,0xa34b,0xa348,0xa346,
+ 0xa343,0xa340,0xa33e,0xa33b,0xa339,0xa336,0xa333,0xa331,0xa32e,0xa32b,0xa329,0xa326,0xa322,0xa321,0xa31d,0xa31c,
+ 0xa319,0xa315,0xa314,0xa310,0xa30d,0xa30b,0xa308,0xa305,0xa303,0xa300,0xa2fe,0xa2fb,0xa2f8,0xa2f6,0xa2f3,0xa2f0,
+ 0xa2ee,0xa2eb,0xa2e7,0xa2e6,0xa2e3,0xa2e1,0xa2de,0xa2da,0xa2d9,0xa2d5,0xa2d2,0xa2d1,0xa2cd,0xa2ca,0xa2c8,0xa2c5,
+ 0xa2c3,0xa2c0,0xa2bd,0xa2bb,0xa2b8,0xa2b5,0xa2b3,0xa2b0,0xa2ad,0xa2ab,0xa2a8,0xa2a4,0xa2a3,0xa29f,0xa29e,0xa29b,
+ 0xa297,0xa296,0xa292,0xa28f,0xa28d,0xa28a,0xa287,0xa285,0xa282,0xa280,0xa27d,0xa27a,0xa278,0xa275,0xa272,0xa270,
+ 0xa26d,0xa269,0xa268,0xa265,0xa263,0xa260,0xa25c,0xa25b,0xa257,0xa254,0xa253,0xa24f,0xa24c,0xa24a,0xa247,0xa245,
+ 0xa242,0xa23f,0xa23d,0xa23a,0xa237,0xa235,0xa232,0xa22f,0xa22d,0xa22a,0xa228,0xa225,0xa221,0xa220,0xa21c,0xa219,
+ 0xa217,0xa215,0xa212,0xa20e,0xa20d,0xa20a,0xa206,0xa205,0xa201,0xa200,0xa1fc,0xa1f9,0xa1f8,0xa1f4,0xa1f1,0xa1ef,
+ 0xa1ec,0xa1eb,0xa1e7,0xa1e4,0xa1e2,0xa1df,0xa1dc,0xa1da,0xa1d7,0xa1d5,0xa1d2,0xa1cf,0xa1cd,0xa1ca,0xa1c7,0xa1c5,
+ 0xa1c2,0xa1bf,0xa1bd,0xa1ba,0xa1b8,0xa1b5,0xa1b2,0xa1b0,0xa1ad,0xa1a9,0xa1a8,0xa1a5,0xa1a3,0xa1a0,0xa19c,0xa19b,
+ 0xa197,0xa194,0xa193,0xa18f,0xa18e,0xa18a,0xa187,0xa186,0xa182,0xa17f,0xa17d,0xa17a,0xa179,0xa175,0xa172,0xa170,
+ 0xa16d,0xa16a,0xa168,0xa165,0xa162,0xa160,0xa15d,0xa15b,0xa158,0xa155,0xa153,0xa150,0xa14d,0xa14b,0xa148,0xa146,
+ 0xa143,0xa140,0xa13e,0xa13b,0xa137,0xa136,0xa132,0xa131,0xa12e,0xa12a,0xa129,0xa125,0xa122,0xa121,0xa11d,0xa11c,
+ 0xa118,0xa115,0xa114,0xa110,0xa10d,0xa10b,0xa108,0xa105,0xa103,0xa100,0xa0fe,0xa0fb,0xa0f8,0xa0f6,0xa0f3,0xa0f0,
+ 0xa0ee,0xa0eb,0xa0e9,0xa0e6,0xa0e3,0xa0e1,0xa0de,0xa0db,0xa0d9,0xa0d6,0xa0d4,0xa0d1,0xa0ce,0xa0cc,0xa0c9,0xa0c5,
+ 0xa0c3,0xa0c0,0xa0be,0xa0bb,0xa0b9,0xa0b6,0xa0b3,0xa0b1,0xa0ae,0xa0ab,0xa0a9,0xa0a6,0xa0a4,0xa0a1,0xa09e,0xa09c,
+ 0xa099,0xa096,0xa094,0xa091,0xa08f,0xa08c,0xa089,0xa087,0xa084,0xa080,0xa07f,0xa07c,0xa07a,0xa077,0xa073,0xa072,
+ 0xa06f,0xa06b,0xa06a,0xa066,0xa065,0xa062,0xa05e,0xa05d,0xa059,0xa056,0xa055,0xa051,0xa050,0xa04c,0xa049,0xa048,
+ 0xa044,0xa041,0xa03f,0xa03c,0xa03b,0xa037,0xa034,0xa032,0xa02f,0xa02c,0xa02a,0xa027,0xa025,0xa022,0xa01f,0xa01d,
+ 0xa01a,0xa017,0xa015,0xa012,0xa010,0xa00d,0xa00a,0xa008,0xa005,0xa002,0xa000,0x9ffd,0x9ffb,0x9ff8,0x9ff5,0x9ff3,
+ 0x9ff0,0x9fed,0x9feb,0x9fe8,0x9fe6,0x9fe3,0x9fe0,0x9fde,0x9fdb,0x9fd7,0x9fd6,0x9fd3,0x9fd1,0x9fce,0x9fca,0x9fc9,
+ 0x9fc6,0x9fc2,0x9fc1,0x9fbd,0x9fbc,0x9fb9,0x9fb5,0x9fb4,0x9fb0,0x9fad,0x9fac,0x9fa8,0x9fa7,0x9fa3,0x9fa0,0x9f9f,
+ 0x9f9b,0x9f98,0x9f96,0x9f93,0x9f92,0x9f8e,0x9f8b,0x9f89,0x9f86,0x9f83,0x9f81,0x9f7e,0x9f7c,0x9f79,0x9f76,0x9f74,
+ 0x9f71,0x9f6e,0x9f6d,0x9f69,0x9f66,0x9f65,0x9f61,0x9f5e,0x9f5c,0x9f59,0x9f58,0x9f54,0x9f51,0x9f4f,0x9f4c,0x9f49,
+ 0x9f47,0x9f44,0x9f42,0x9f3f,0x9f3c,0x9f3a,0x9f37,0x9f34,0x9f32,0x9f2f,0x9f2d,0x9f2a,0x9f27,0x9f25,0x9f22,0x9f1f,
+ 0x9f1d,0x9f1a,0x9f18,0x9f15,0x9f12,0x9f10,0x9f0d,0x9f0b,0x9f08,0x9f05,0x9f03,0x9f00,0x9efd,0x9efb,0x9ef8,0x9ef6,
+ 0x9ef3,0x9ef0,0x9eee,0x9eeb,0x9ee8,0x9ee6,0x9ee3,0x9ee1,0x9ede,0x9edb,0x9ed9,0x9ed6,0x9ed3,0x9ed1,0x9ece,0x9ecc,
+ 0x9ec9,0x9ec6,0x9ec4,0x9ec1,0x9ebf,0x9ebc,0x9eb9,0x9eb7,0x9eb4,0x9eb1,0x9eaf,0x9eac,0x9eaa,0x9ea7,0x9ea4,0x9ea2,
+ 0x9e9f,0x9e9b,0x9e9a,0x9e97,0x9e95,0x9e92,0x9e8f,0x9e8d,0x9e8a,0x9e86,0x9e85,0x9e82,0x9e80,0x9e7d,0x9e79,0x9e78,
+ 0x9e75,0x9e73,0x9e70,0x9e6c,0x9e6b,0x9e68,0x9e64,0x9e63,0x9e60,0x9e5e,0x9e5b,0x9e57,0x9e56,0x9e53,0x9e4f,0x9e4e,
+ 0x9e4a,0x9e49,0x9e46,0x9e42,0x9e41,0x9e3d,0x9e3a,0x9e39,0x9e35,0x9e34,0x9e31,0x9e2d,0x9e2c,0x9e28,0x9e25,0x9e24,
+ 0x9e21,0x9e1e,0x9e1c,0x9e19,0x9e15,0x9e14,0x9e11,0x9e0d,0x9e0c,0x9e09,0x9e07,0x9e04,0x9e01,0x9dff,0x9dfc,0x9dfa,
+ 0x9df7,0x9df4,0x9df2,0x9def,0x9dec,0x9dea,0x9de7,0x9de5,0x9de2,0x9ddf,0x9ddd,0x9dda,0x9dd8,0x9dd5,0x9dd2,0x9dd0,
+ 0x9dcd,0x9dcb,0x9dc8,0x9dc5,0x9dc3,0x9dc0,0x9dbd,0x9dbb,0x9db8,0x9db6,0x9db3,0x9db0,0x9dae,0x9dab,0x9da9,0x9da6,
+ 0x9da3,0x9da1,0x9d9e,0x9d9b,0x9d99,0x9d96,0x9d94,0x9d91,0x9d8e,0x9d8c,0x9d89,0x9d88,0x9d84,0x9d81,0x9d7f,0x9d7c,
+ 0x9d7b,0x9d77,0x9d74,0x9d73,0x9d6f,0x9d6c,0x9d6a,0x9d67,0x9d66,0x9d62,0x9d5f,0x9d5e,0x9d5a,0x9d59,0x9d56,0x9d52,
+ 0x9d51,0x9d4d,0x9d4a,0x9d49,0x9d45,0x9d44,0x9d41,0x9d3d,0x9d3c,0x9d38,0x9d37,0x9d34,0x9d30,0x9d2f,0x9d2c,0x9d28,
+ 0x9d27,0x9d23,0x9d22,0x9d1f,0x9d1b,0x9d1a,0x9d17,0x9d15,0x9d12,0x9d0f,0x9d0d,0x9d0a,0x9d08,0x9d05,0x9d02,0x9d00,
+ 0x9cfd,0x9cfa,0x9cf8,0x9cf5,0x9cf3,0x9cf0,0x9ced,0x9ceb,0x9ce8,0x9ce6,0x9ce3,0x9ce0,0x9cde,0x9cdb,0x9cd8,0x9cd6,
+ 0x9cd3,0x9cd0,0x9cce,0x9ccb,0x9cc9,0x9cc6,0x9cc3,0x9cc1,0x9cbe,0x9cbc,0x9cb9,0x9cb6,0x9cb4,0x9cb1,0x9cae,0x9cac,
+ 0x9ca9,0x9ca7,0x9ca4,0x9ca1,0x9c9f,0x9c9c,0x9c9b,0x9c97,0x9c94,0x9c92,0x9c8f,0x9c8e,0x9c8a,0x9c87,0x9c86,0x9c82,
+ 0x9c81,0x9c7e,0x9c7a,0x9c79,0x9c75,0x9c72,0x9c71,0x9c6d,0x9c6c,0x9c69,0x9c65,0x9c64,0x9c61,0x9c5f,0x9c5c,0x9c59,
+ 0x9c57,0x9c54,0x9c52,0x9c4f,0x9c4c,0x9c4a,0x9c47,0x9c44,0x9c42,0x9c3f,0x9c3d,0x9c3a,0x9c37,0x9c35,0x9c32,0x9c30,
+ 0x9c2d,0x9c2a,0x9c28,0x9c25,0x9c23,0x9c20,0x9c1d,0x9c1b,0x9c18,0x9c17,0x9c13,0x9c10,0x9c0e,0x9c0b,0x9c08,0x9c06,
+ 0x9c03,0x9c02,0x9bfe,0x9bfb,0x9bfa,0x9bf6,0x9bf5,0x9bf2,0x9bee,0x9bed,0x9be9,0x9be8,0x9be5,0x9be1,0x9be0,0x9bdd,
+ 0x9bdb,0x9bd8,0x9bd5,0x9bd3,0x9bd0,0x9bcd,0x9bcb,0x9bc8,0x9bc6,0x9bc3,0x9bc0,0x9bbe,0x9bbb,0x9bb9,0x9bb6,0x9bb3,
+ 0x9bb1,0x9bae,0x9bac,0x9ba9,0x9ba6,0x9ba4,0x9ba1,0x9b9e,0x9b9c,0x9b99,0x9b97,0x9b94,0x9b91,0x9b8f,0x9b8c,0x9b8b,
+ 0x9b87,0x9b85,0x9b82,0x9b7f,0x9b7d,0x9b7a,0x9b78,0x9b75,0x9b72,0x9b70,0x9b6d,0x9b6c,0x9b68,0x9b65,0x9b64,0x9b60,
+ 0x9b5f,0x9b5c,0x9b58,0x9b57,0x9b53,0x9b52,0x9b4f,0x9b4b,0x9b4a,0x9b47,0x9b45,0x9b42,0x9b3f,0x9b3d,0x9b3a,0x9b37,
+ 0x9b35,0x9b32,0x9b30,0x9b2d,0x9b2a,0x9b28,0x9b25,0x9b23,0x9b20,0x9b1d,0x9b1b,0x9b18,0x9b16,0x9b13,0x9b10,0x9b0e,
+ 0x9b0b,0x9b0a,0x9b06,0x9b03,0x9b02,0x9afe,0x9afd,0x9afa,0x9af6,0x9af5,0x9af2,0x9af0,0x9aed,0x9aea,0x9ae8,0x9ae5,
+ 0x9ae3,0x9ae0,0x9add,0x9adb,0x9ad8,0x9ad5,0x9ad3,0x9ad0,0x9ace,0x9acb,0x9ac8,0x9ac6,0x9ac3,0x9ac1,0x9abe,0x9abb,
+ 0x9ab9,0x9ab6,0x9ab5,0x9ab1,0x9aae,0x9aad,0x9aa9,0x9aa8,0x9aa4,0x9aa1,0x9aa0,0x9a9c,0x9a9b,0x9a98,0x9a94,0x9a93,
+ 0x9a90,0x9a8e,0x9a8b,0x9a88,0x9a86,0x9a83,0x9a80,0x9a7e,0x9a7b,0x9a79,0x9a76,0x9a73,0x9a71,0x9a6e,0x9a6c,0x9a69,
+ 0x9a66,0x9a64,0x9a61,0x9a5f,0x9a5c,0x9a59,0x9a57,0x9a54,0x9a53,0x9a4f,0x9a4c,0x9a4b,0x9a47,0x9a46,0x9a43,0x9a3f,
+ 0x9a3e,0x9a3b,0x9a38,0x9a36,0x9a33,0x9a30,0x9a2e,0x9a2b,0x9a2a,0x9a26,0x9a23,0x9a22,0x9a1e,0x9a1d,0x9a1a,0x9a16,
+ 0x9a15,0x9a12,0x9a10,0x9a0d,0x9a0a,0x9a08,0x9a05,0x9a03,0x9a00,0x99fd,0x99fb,0x99f8,0x99f6,0x99f3,0x99f0,0x99ee,
+ 0x99eb,0x99ea,0x99e6,0x99e3,0x99e2,0x99de,0x99dd,0x99da,0x99d6,0x99d5,0x99d2,0x99d0,0x99cd,0x99ca,0x99c8,0x99c5,
+ 0x99c3,0x99c0,0x99bd,0x99bb,0x99b8,0x99b6,0x99b3,0x99b0,0x99ae,0x99ab,0x99aa,0x99a6,0x99a3,0x99a2,0x999e,0x999d,
+ 0x999a,0x9996,0x9995,0x9991,0x9990,0x998d,0x9989,0x9988,0x9985,0x9983,0x9980,0x997d,0x997b,0x9978,0x9976,0x9973,
+ 0x9970,0x996e,0x996b,0x9969,0x9966,0x9963,0x9961,0x995e,0x995d,0x9959,0x9956,0x9955,0x9951,0x9950,0x994d,0x9949,
+ 0x9948,0x9945,0x9943,0x9940,0x993d,0x993b,0x9938,0x9936,0x9933,0x9930,0x992e,0x992b,0x9929,0x9926,0x9923,0x9921,
+ 0x991e,0x991d,0x9919,0x9916,0x9915,0x9911,0x9910,0x990d,0x9909,0x9908,0x9905,0x9903,0x9900,0x98fd,0x98fb,0x98f8,
+ 0x98f5,0x98f2,0x98f1,0x98ed,0x98ec,0x98e9,0x98e6,0x98e4,0x98e1,0x98df,0x98dc,0x98d9,0x98d7,0x98d4,0x98d2,0x98cf,
+ 0x98ce,0x98ca,0x98c7,0x98c6,0x98c2,0x98c1,0x98be,0x98ba,0x98b9,0x98b6,0x98b4,0x98b1,0x98ae,0x98ac,0x98a9,0x98a7,
+ 0x98a4,0x98a1,0x989f,0x989c,0x989b,0x9897,0x9894,0x9893,0x988f,0x988e,0x988b,0x9887,0x9886,0x9883,0x9881,0x987e,
+ 0x987c,0x9879,0x9876,0x9874,0x9871,0x9870,0x986c,0x9869,0x9868,0x9864,0x9863,0x9860,0x985c,0x985b,0x9858,0x9856,
+ 0x9853,0x9850,0x984e,0x984b,0x9849,0x9846,0x9843,0x9841,0x983e,0x983d,0x9839,0x9836,0x9835,0x9831,0x9830,0x982d,
+ 0x982b,0x9828,0x9825,0x9823,0x9820,0x981e,0x981b,0x9818,0x9816,0x9813,0x9812,0x980e,0x980b,0x980a,0x9806,0x9805,
+ 0x9802,0x97fe,0x97fd,0x97fa,0x97f8,0x97f5,0x97f2,0x97f0,0x97ed,0x97eb,0x97e8,0x97e5,0x97e3,0x97e0,0x97df,0x97db,
+ 0x97da,0x97d7,0x97d3,0x97d2,0x97cf,0x97cd,0x97ca,0x97c7,0x97c5,0x97c2,0x97c0,0x97bd,0x97ba,0x97b8,0x97b5,0x97b4,
+ 0x97b0,0x97ad,0x97ac,0x97a9,0x97a5,0x97a4,0x97a1,0x979f,0x979c,0x9799,0x9797,0x9794,0x9792,0x978f,0x978c,0x978a,
+ 0x9787,0x9786,0x9782,0x9781,0x977e,0x977a,0x9779,0x9776,0x9774,0x9771,0x976e,0x976c,0x9769,0x9767,0x9764,0x9761,
+ 0x975f,0x975c,0x975b,0x9757,0x9756,0x9753,0x974f,0x974e,0x974b,0x9749,0x9746,0x9743,0x9741,0x973e,0x973c,0x9739,
+ 0x9736,0x9734,0x9731,0x9730,0x972d,0x9729,0x9728,0x9725,0x9723,0x9720,0x971e,0x971b,0x9718,0x9716,0x9713,0x9711,
+ 0x970e,0x970b,0x970a,0x9706,0x9705,0x9702,0x96fe,0x96fd,0x96fa,0x96f8,0x96f5,0x96f3,0x96f0,0x96ed,0x96eb,0x96e8,
+ 0x96e7,0x96e3,0x96e0,0x96df,0x96db,0x96da,0x96d7,0x96d3,0x96d2,0x96cf,0x96cd,0x96ca,0x96c7,0x96c5,0x96c2,0x96c0,
+ 0x96bd,0x96bc,0x96b8,0x96b5,0x96b4,0x96b1,0x96af,0x96ac,0x96a9,0x96a7,0x96a4,0x96a2,0x969f,0x969c,0x969a,0x9697,
+ 0x9695,0x9692,0x9691,0x968e,0x968a,0x9689,0x9686,0x9684,0x9681,0x967e,0x967c,0x9679,0x9677,0x9674,0x9671,0x966f,
+ 0x966d,0x966a,0x9667,0x9666,0x9662,0x9661,0x965e,0x965a,0x9659,0x9656,0x9654,0x9651,0x964e,0x964c,0x9649,0x9647,
+ 0x9644,0x9643,0x963f,0x963c,0x963b,0x9638,0x9636,0x9633,0x9630,0x962e,0x962b,0x9629,0x9626,0x9624,0x9621,0x961e,
+ 0x961d,0x9619,0x9618,0x9615,0x9611,0x9610,0x960d,0x960b,0x9608,0x9605,0x9603,0x9600,0x95fe,0x95fb,0x95fa,0x95f6,
+ 0x95f3,0x95f2,0x95ef,0x95ed,0x95ea,0x95e7,0x95e5,0x95e2,0x95e0,0x95dd,0x95dc,0x95d8,0x95d5,0x95d4,0x95d0,0x95cf,
+ 0x95cc,0x95c8,0x95c7,0x95c4,0x95c2,0x95bf,0x95bc,0x95ba,0x95b7,0x95b5,0x95b2,0x95b1,0x95ae,0x95aa,0x95a9,0x95a6,
+ 0x95a4,0x95a1,0x959e,0x959c,0x9599,0x9597,0x9594,0x9593,0x958f,0x958c,0x958b,0x9587,0x9586,0x9583,0x9580,0x957e,
+ 0x957b,0x9579,0x9576,0x9573,0x9571,0x956e,0x956d,0x9569,0x9568,0x9565,0x9561,0x9560,0x955d,0x955b,0x9558,0x9555,
+ 0x9553,0x9550,0x954e,0x954b,0x954a,0x9546,0x9543,0x9542,0x953f,0x953d,0x953a,0x9537,0x9535,0x9532,0x9530,0x952d,
+ 0x952b,0x9529,0x9526,0x9524,0x9521,0x951e,0x951c,0x9519,0x9518,0x9515,0x9511,0x9510,0x950d,0x950b,0x9508,0x9506,
+ 0x9503,0x9500,0x94fe,0x94fb,0x94fa,0x94f7,0x94f3,0x94f2,0x94ef,0x94ed,0x94ea,0x94e8,0x94e5,0x94e2,0x94e0,0x94dd,
+ 0x94dc,0x94d8,0x94d5,0x94d4,0x94d1,0x94cf,0x94cc,0x94ca,0x94c7,0x94c4,0x94c2,0x94bf,0x94be,0x94ba,0x94b7,0x94b6,
+ 0x94b2,0x94b1,0x94ae,0x94ac,0x94a9,0x94a6,0x94a4,0x94a1,0x949f,0x949c,0x9499,0x9498,0x9494,0x9493,0x9490,0x948e,
+ 0x948b,0x9488,0x9486,0x9483,0x9481,0x947e,0x947d,0x947a,0x9476,0x9475,0x9472,0x9470,0x946d,0x946a,0x9468,0x9465,
+ 0x9463,0x9460,0x945f,0x945b,0x9458,0x9457,0x9454,0x9452,0x944f,0x944c,0x944a,0x9447,0x9445,0x9442,0x9441,0x943d,
+ 0x943a,0x9439,0x9436,0x9434,0x9431,0x942e,0x942c,0x9429,0x9427,0x9424,0x9423,0x941f,0x941c,0x941b,0x9417,0x9416,
+ 0x9413,0x9410,0x940e,0x940b,0x9409,0x9406,0x9404,0x9401,0x93fe,0x93fd,0x93f9,0x93f8,0x93f5,0x93f1,0x93f0,0x93ed,
+ 0x93eb,0x93e9,0x93e6,0x93e4,0x93e1,0x93de,0x93dc,0x93d9,0x93d8,0x93d5,0x93d3,0x93d0,0x93cd,0x93cb,0x93c8,0x93c6,
+ 0x93c3,0x93c0,0x93be,0x93bb,0x93ba,0x93b7,0x93b5,0x93b2,0x93af,0x93ad,0x93aa,0x93a8,0x93a5,0x93a4,0x93a1,0x939d,
+ 0x939c,0x9399,0x9397,0x9394,0x9392,0x938f,0x938c,0x938b,0x9387,0x9386,0x9383,0x9381,0x937e,0x937b,0x9379,0x9376,
+ 0x9374,0x9371,0x9370,0x936d,0x9369,0x9368,0x9365,0x9363,0x9360,0x935e,0x935b,0x9358,0x9357,0x9353,0x9352,0x934f,
+ 0x934d,0x934a,0x9347,0x9345,0x9342,0x9341,0x933d,0x933a,0x9339,0x9336,0x9334,0x9331,0x932f,0x932c,0x9329,0x9327,
+ 0x9324,0x9323,0x931f,0x931e,0x931b,0x9318,0x9316,0x9313,0x9311,0x930e,0x930d,0x9309,0x9306,0x9305,0x9302,0x9300,
+ 0x92fd,0x92fb,0x92f8,0x92f5,0x92f3,0x92f0,0x92ef,0x92ec,0x92ea,0x92e7,0x92e4,0x92e2,0x92df,0x92dd,0x92da,0x92d9,
+ 0x92d5,0x92d2,0x92d1,0x92ce,0x92cc,0x92c9,0x92c6,0x92c4,0x92c1,0x92bf,0x92bc,0x92bb,0x92b8,0x92b4,0x92b3,0x92b0,
+ 0x92ae,0x92ab,0x92a8,0x92a6,0x92a3,0x92a2,0x929f,0x929d,0x929a,0x9297,0x9295,0x9292,0x9290,0x928d,0x928c,0x9289,
+ 0x9285,0x9284,0x9281,0x927f,0x927c,0x927a,0x9277,0x9274,0x9273,0x926f,0x926e,0x926b,0x9269,0x9266,0x9263,0x9261,
+ 0x925e,0x925d,0x925a,0x9258,0x9255,0x9252,0x9250,0x924d,0x924b,0x9248,0x9247,0x9244,0x9240,0x923f,0x923c,0x923a,
+ 0x9237,0x9235,0x9232,0x922f,0x922e,0x922a,0x9229,0x9226,0x9224,0x9221,0x921e,0x921c,0x9219,0x9218,0x9214,0x9213,
+ 0x9210,0x920d,0x920b,0x9208,0x9206,0x9203,0x9202,0x91fe,0x91fb,0x91fa,0x91f7,0x91f5,0x91f2,0x91f0,0x91ed,0x91ea,
+ 0x91e8,0x91e5,0x91e4,0x91e1,0x91df,0x91dc,0x91d9,0x91d7,0x91d4,0x91d2,0x91cf,0x91ce,0x91cb,0x91c7,0x91c6,0x91c3,
+ 0x91c1,0x91be,0x91bc,0x91b9,0x91b6,0x91b5,0x91b1,0x91b0,0x91ad,0x91ab,0x91a8,0x91a5,0x91a3,0x91a0,0x919f,0x919c,
+ 0x919a,0x9197,0x9194,0x9192,0x918f,0x918d,0x918a,0x9189,0x9186,0x9182,0x9181,0x917e,0x917c,0x9179,0x9177,0x9174,
+ 0x9172,0x916f,0x916e,0x916b,0x9167,0x9166,0x9163,0x9161,0x915e,0x915c,0x9159,0x9158,0x9155,0x9151,0x9150,0x914d,
+ 0x914b,0x9148,0x9146,0x9143,0x9140,0x913f,0x913c,0x913a,0x9137,0x9135,0x9132,0x912f,0x912d,0x912a,0x9129,0x9126,
+ 0x9124,0x9121,0x911e,0x911c,0x9119,0x9117,0x9114,0x9113,0x9110,0x910e,0x910b,0x9108,0x9106,0x9103,0x9102,0x90fe,
+ 0x90fd,0x90fa,0x90f7,0x90f5,0x90f2,0x90f0,0x90ed,0x90ec,0x90e9,0x90e5,0x90e4,0x90e1,0x90df,0x90dc,0x90da,0x90d7,
+ 0x90d6,0x90d3,0x90cf,0x90ce,0x90cb,0x90c9,0x90c6,0x90c4,0x90c1,0x90be,0x90bd,0x90ba,0x90b8,0x90b5,0x90b3,0x90b0,
+ 0x90ad,0x90ab,0x90a8,0x90a7,0x90a4,0x90a2,0x909f,0x909c,0x909a,0x9097,0x9095,0x9092,0x9091,0x908e,0x908c,0x9089,
+ 0x9086,0x9084,0x9081,0x9080,0x907c,0x907b,0x9078,0x9075,0x9073,0x9070,0x906e,0x906b,0x906a,0x9066,0x9063,0x9062,
+ 0x905f,0x905d,0x905a,0x9058,0x9055,0x9052,0x9051,0x904d,0x904c,0x9049,0x9047,0x9044,0x9042,0x903f,0x903c,0x903b,
+ 0x9038,0x9035,0x9034,0x9030,0x902f,0x902c,0x902a,0x9027,0x9026,0x9022,0x901f,0x901e,0x901b,0x9019,0x9016,0x9014,
+ 0x9011,0x900e,0x900d,0x9009,0x9008,0x9005,0x9003,0x9000,0x8ffe,0x8ffb,0x8ff8,0x8ff7,0x8ff4,0x8ff2,0x8fef,0x8fed,
+ 0x8fea,0x8fe7,0x8fe5,0x8fe2,0x8fe1,0x8fde,0x8fdc,0x8fd9,0x8fd7,0x8fd4,0x8fd1,0x8fd0,0x8fcc,0x8fcb,0x8fc8,0x8fc6,
+ 0x8fc3,0x8fc0,0x8fbe,0x8fbb,0x8fba,0x8fb7,0x8fb5,0x8fb2,0x8fb0,0x8fad,0x8faa,0x8fa9,0x8fa5,0x8fa4,0x8fa1,0x8f9f,
+ 0x8f9c,0x8f99,0x8f97,0x8f94,0x8f93,0x8f90,0x8f8e,0x8f8b,0x8f89,0x8f86,0x8f83,0x8f81,0x8f7e,0x8f7d,0x8f7a,0x8f78,
+ 0x8f75,0x8f72,0x8f70,0x8f6d,0x8f6c,0x8f68,0x8f67,0x8f64,0x8f62,0x8f5f,0x8f5c,0x8f5a,0x8f57,0x8f56,0x8f53,0x8f51,
+ 0x8f4e,0x8f4b,0x8f49,0x8f46,0x8f45,0x8f41,0x8f40,0x8f3d,0x8f3b,0x8f38,0x8f35,0x8f33,0x8f30,0x8f2f,0x8f2c,0x8f2a,
+ 0x8f27,0x8f24,0x8f22,0x8f1f,0x8f1d,0x8f1a,0x8f19,0x8f16,0x8f14,0x8f11,0x8f0e,0x8f0c,0x8f09,0x8f08,0x8f04,0x8f03,
+ 0x8f01,0x8efd,0x8efa,0x8ef9,0x8ef6,0x8ef4,0x8ef1,0x8eef,0x8eec,0x8eeb,0x8ee8,0x8ee5,0x8ee3,0x8ee0,0x8ede,0x8edb,
+ 0x8eda,0x8ed7,0x8ed5,0x8ed2,0x8ecf,0x8ecd,0x8eca,0x8ec9,0x8ec5,0x8ec4,0x8ec1,0x8ebf,0x8ebc,0x8eb9,0x8eb7,0x8eb4,
+ 0x8eb3,0x8eb0,0x8eae,0x8eab,0x8ea9,0x8ea6,0x8ea3,0x8ea2,0x8e9f,0x8e9d,0x8e9a,0x8e98,0x8e95,0x8e94,0x8e91,0x8e8d,
+ 0x8e8c,0x8e89,0x8e87,0x8e84,0x8e83,0x8e7f,0x8e7e,0x8e7b,0x8e78,0x8e76,0x8e73,0x8e71,0x8e6e,0x8e6d,0x8e6a,0x8e68,
+ 0x8e65,0x8e62,0x8e60,0x8e5d,0x8e5c,0x8e59,0x8e57,0x8e54,0x8e52,0x8e4f,0x8e4c,0x8e4b,0x8e48,0x8e46,0x8e43,0x8e41,
+ 0x8e3e,0x8e3d,0x8e3a,0x8e36,0x8e35,0x8e32,0x8e30,0x8e2d,0x8e2c,0x8e28,0x8e27,0x8e24,0x8e21,0x8e1f,0x8e1c,0x8e1a,
+ 0x8e17,0x8e16,0x8e13,0x8e11,0x8e0e,0x8e0b,0x8e09,0x8e06,0x8e05,0x8e02,0x8e00,0x8dfd,0x8dfb,0x8df8,0x8df5,0x8df4,
+ 0x8df0,0x8def,0x8dec,0x8dea,0x8de7,0x8de6,0x8de2,0x8ddf,0x8dde,0x8ddb,0x8dd9,0x8dd6,0x8dd4,0x8dd1,0x8dd0,0x8dcd,
+ 0x8dca,0x8dc8,0x8dc5,0x8dc3,0x8dc0,0x8dbd,0x8dbc,0x8db9,0x8db7,0x8db4,0x8db2,0x8daf,0x8dae,0x8dab,0x8da9,0x8da6,
+ 0x8da3,0x8da1,0x8d9e,0x8d9d,0x8d9a,0x8d98,0x8d95,0x8d93,0x8d90,0x8d8d,0x8d8c,0x8d88,0x8d87,0x8d84,0x8d82,0x8d7f,
+ 0x8d7e,0x8d7b,0x8d79,0x8d76,0x8d73,0x8d71,0x8d6e,0x8d6d,0x8d69,0x8d68,0x8d65,0x8d63,0x8d60,0x8d5d,0x8d5b,0x8d58,
+ 0x8d57,0x8d54,0x8d52,0x8d4f,0x8d4e,0x8d4a,0x8d49,0x8d46,0x8d43,0x8d41,0x8d3e,0x8d3c,0x8d39,0x8d38,0x8d35,0x8d33,
+ 0x8d30,0x8d2d,0x8d2b,0x8d28,0x8d27,0x8d24,0x8d22,0x8d1f,0x8d1d,0x8d1a,0x8d17,0x8d16,0x8d13,0x8d11,0x8d0e,0x8d0c,
+ 0x8d09,0x8d08,0x8d05,0x8d03,0x8d00,0x8cfd,0x8cfb,0x8cf8,0x8cf7,0x8cf4,0x8cf2,0x8cef,0x8ced,0x8cea,0x8ce7,0x8ce6,
+ 0x8ce3,0x8ce1,0x8cde,0x8cdc,0x8cd9,0x8cd8,0x8cd5,0x8cd3,0x8cd0,0x8ccd,0x8ccb,0x8cc8,0x8cc7,0x8cc4,0x8cc2,0x8cbf,
+ 0x8cbd,0x8cba,0x8cb7,0x8cb6,0x8cb2,0x8cb1,0x8cae,0x8cac,0x8ca9,0x8ca8,0x8ca5,0x8ca3,0x8ca0,0x8c9d,0x8c9b,0x8c98,
+ 0x8c96,0x8c93,0x8c91,0x8c8e,0x8c8d,0x8c8a,0x8c88,0x8c85,0x8c83,0x8c80,0x8c7f,0x8c7c,0x8c79,0x8c77,0x8c74,0x8c72,
+ 0x8c6f,0x8c6e,0x8c6b,0x8c69,0x8c66,0x8c65,0x8c61,0x8c5e,0x8c5d,0x8c5a,0x8c58,0x8c55,0x8c54,0x8c50,0x8c4f,0x8c4c,
+ 0x8c4a,0x8c47,0x8c44,0x8c43,0x8c3f,0x8c3e,0x8c3b,0x8c39,0x8c36,0x8c35,0x8c32,0x8c2e,0x8c2d,0x8c2a,0x8c28,0x8c25,
+ 0x8c24,0x8c20,0x8c1f,0x8c1c,0x8c1a,0x8c17,0x8c14,0x8c13,0x8c0f,0x8c0e,0x8c0b,0x8c09,0x8c06,0x8c05,0x8c02,0x8c00,
+ 0x8bfd,0x8bfa,0x8bf8,0x8bf5,0x8bf4,0x8bf1,0x8bef,0x8bec,0x8bea,0x8be7,0x8be6,0x8be3,0x8be0,0x8bde,0x8bdb,0x8bd9,
+ 0x8bd6,0x8bd5,0x8bd2,0x8bd0,0x8bcd,0x8bcb,0x8bc8,0x8bc5,0x8bc4,0x8bc1,0x8bbf,0x8bbc,0x8bba,0x8bb7,0x8bb6,0x8bb3,
+ 0x8bb1,0x8bae,0x8bab,0x8ba9,0x8ba6,0x8ba5,0x8ba2,0x8ba0,0x8b9d,0x8b9b,0x8b98,0x8b95,0x8b94,0x8b91,0x8b8f,0x8b8c,
+ 0x8b8a,0x8b87,0x8b86,0x8b83,0x8b81,0x8b7e,0x8b7b,0x8b79,0x8b76,0x8b75,0x8b72,0x8b70,0x8b6d,0x8b6c,0x8b68,0x8b67,
+ 0x8b64,0x8b61,0x8b60,0x8b5d,0x8b5b,0x8b58,0x8b55,0x8b53,0x8b50,0x8b4f,0x8b4c,0x8b4a,0x8b47,0x8b45,0x8b42,0x8b41,
+ 0x8b3e,0x8b3c,0x8b39,0x8b36,0x8b34,0x8b31,0x8b30,0x8b2d,0x8b2b,0x8b28,0x8b27,0x8b23,0x8b22,0x8b1f,0x8b1c,0x8b1a,
+ 0x8b17,0x8b16,0x8b13,0x8b11,0x8b0e,0x8b0c,0x8b09,0x8b08,0x8b05,0x8b02,0x8b00,0x8afd,0x8afb,0x8af8,0x8af7,0x8af4,
+ 0x8af2,0x8aef,0x8aed,0x8aea,0x8ae9,0x8ae6,0x8ae3,0x8ae1,0x8ade,0x8add,0x8ad9,0x8ad8,0x8ad5,0x8ad3,0x8ad0,0x8acf,
+ 0x8acc,0x8ac8,0x8ac7,0x8ac4,0x8ac2,0x8abf,0x8abe,0x8abb,0x8ab9,0x8ab6,0x8ab4,0x8ab1,0x8aae,0x8aad,0x8aaa,0x8aa8,
+ 0x8aa5,0x8aa3,0x8aa0,0x8a9f,0x8a9c,0x8a9a,0x8a97,0x8a96,0x8a92,0x8a8f,0x8a8e,0x8a8b,0x8a89,0x8a86,0x8a85,0x8a81,
+ 0x8a80,0x8a7d,0x8a7b,0x8a78,0x8a75,0x8a74,0x8a71,0x8a6f,0x8a6c,0x8a6a,0x8a67,0x8a66,0x8a63,0x8a61,0x8a5e,0x8a5b,
+ 0x8a59,0x8a56,0x8a55,0x8a52,0x8a50,0x8a4d,0x8a4b,0x8a48,0x8a47,0x8a44,0x8a42,0x8a3f,0x8a3c,0x8a3b,0x8a37,0x8a36,
+ 0x8a34,0x8a31,0x8a2e,0x8a2d,0x8a2a,0x8a28,0x8a25,0x8a23,0x8a20,0x8a1f,0x8a1c,0x8a1a,0x8a17,0x8a14,0x8a12,0x8a0f,
+ 0x8a0e,0x8a0b,0x8a09,0x8a06,0x8a05,0x8a02,0x8a00,0x89fd,0x89fb,0x89f8,0x89f5,0x89f4,0x89f1,0x89ef,0x89ec,0x89ea,
+ 0x89e7,0x89e6,0x89e3,0x89e1,0x89de,0x89dd,0x89da,0x89d6,0x89d5,0x89d2,0x89d0,0x89cd,0x89cc,0x89c9,0x89c7,0x89c4,
+ 0x89c2,0x89bf,0x89be,0x89bb,0x89b8,0x89b6,0x89b3,0x89b2,0x89ae,0x89ad,0x89aa,0x89a8,0x89a5,0x89a4,0x89a1,0x899f,
+ 0x899c,0x8999,0x8997,0x8994,0x8993,0x8990,0x898e,0x898b,0x8989,0x8986,0x8985,0x8982,0x8980,0x897d,0x897a,0x8979,
+ 0x8975,0x8974,0x8971,0x896f,0x896c,0x896b,0x8968,0x8966,0x8963,0x8961,0x895e,0x895b,0x895a,0x8957,0x8955,0x8952,
+ 0x8951,0x894d,0x894c,0x8949,0x8947,0x8944,0x8943,0x8940,0x893d,0x893b,0x8938,0x8936,0x8933,0x8932,0x892f,0x892d,
+ 0x892a,0x8929,0x8925,0x8924,0x8921,0x891e,0x891c,0x8919,0x8918,0x8915,0x8913,0x8910,0x890e,0x890b,0x890a,0x8907,
+ 0x8904,0x8901,0x8900,0x88fd,0x88fb,0x88f8,0x88f7,0x88f3,0x88f2,0x88ef,0x88ed,0x88ea,0x88e9,0x88e6,0x88e4,0x88e1,
+ 0x88e0,0x88dd,0x88d9,0x88d8,0x88d5,0x88d3,0x88d0,0x88cf,0x88cc,0x88ca,0x88c7,0x88c6,0x88c2,0x88c1,0x88be,0x88bc,
+ 0x88b9,0x88b6,0x88b5,0x88b2,0x88b0,0x88ad,0x88ac,0x88a8,0x88a7,0x88a4,0x88a2,0x889f,0x889e,0x889b,0x8899,0x8896,
+ 0x8895,0x8891,0x888e,0x888d,0x888a,0x8888,0x8885,0x8884,0x8881,0x887f,0x887c,0x887b,0x8877,0x8876,0x8873,0x8871,
+ 0x886e,0x886b,0x886a,0x8867,0x8865,0x8862,0x8860,0x885d,0x885c,0x8859,0x8857,0x8854,0x8853,0x8850,0x884e,0x884b,
+ 0x884a,0x8846,0x8843,0x8842,0x883f,0x883d,0x883a,0x8839,0x8836,0x8834,0x8831,0x882f,0x882c,0x882b,0x8828,0x8826,
+ 0x8823,0x8820,0x881f,0x881c,0x881a,0x8817,0x8815,0x8812,0x8811,0x880e,0x880c,0x8809,0x8808,0x8805,0x8803,0x8800,
+ 0x87fe,0x87fb,0x87f8,0x87f7,0x87f4,0x87f2,0x87ef,0x87ee,0x87eb,0x87e9,0x87e6,0x87e4,0x87e1,0x87e0,0x87dd,0x87db,
+ 0x87d7,0x87d6,0x87d3,0x87d1,0x87ce,0x87cd,0x87ca,0x87c8,0x87c5,0x87c4,0x87c0,0x87bd,0x87bc,0x87b9,0x87b7,0x87b4,
+ 0x87b3,0x87b0,0x87ae,0x87ab,0x87aa,0x87a6,0x87a5,0x87a2,0x87a0,0x879d,0x879c,0x8799,0x8796,0x8794,0x8791,0x8790,
+ 0x878d,0x878b,0x8788,0x8786,0x8783,0x8782,0x877f,0x877d,0x877a,0x8779,0x8776,0x8774,0x8771,0x876f,0x876c,0x8769,
+ 0x8768,0x8765,0x8763,0x8760,0x875f,0x875c,0x875a,0x8757,0x8756,0x8752,0x8751,0x874e,0x874c,0x8749,0x8748,0x8745,
+ 0x8743,0x8740,0x873d,0x873c,0x8739,0x8737,0x8734,0x8732,0x872f,0x872e,0x872b,0x8729,0x8726,0x8725,0x8722,0x8720,
+ 0x871d,0x871b,0x8718,0x8715,0x8714,0x8711,0x870f,0x870c,0x870b,0x8708,0x8706,0x8703,0x8702,0x86fe,0x86fd,0x86fa,
+ 0x86f8,0x86f5,0x86f4,0x86f1,0x86ef,0x86ec,0x86e9,0x86e8,0x86e5,0x86e3,0x86e0,0x86de,0x86db,0x86da,0x86d7,0x86d5,
+ 0x86d2,0x86d1,0x86ce,0x86cc,0x86c9,0x86c7,0x86c4,0x86c1,0x86c0,0x86bd,0x86bb,0x86b8,0x86b7,0x86b4,0x86b2,0x86af,
+ 0x86ae,0x86ab,0x86a8,0x86a6,0x86a3,0x86a1,0x869e,0x869d,0x869a,0x8698,0x8695,0x8694,0x8691,0x868f,0x868c,0x868b,
+ 0x8688,0x8686,0x8683,0x8681,0x867e,0x867d,0x867a,0x8677,0x8675,0x8672,0x8671,0x866e,0x866c,0x8669,0x8668,0x8665,
+ 0x8663,0x8660,0x865e,0x865b,0x865a,0x8657,0x8655,0x8652,0x8651,0x864e,0x864c,0x8649,0x8646,0x8645,0x8642,0x8640,
+ 0x863d,0x863b,0x8638,0x8637,0x8634,0x8632,0x862f,0x862e,0x862b,0x8629,0x8626,0x8625,0x8622,0x8620,0x861d,0x861b,
+ 0x8618,0x8615,0x8614,0x8611,0x860f,0x860c,0x860b,0x8608,0x8606,0x8603,0x8602,0x85fe,0x85fd,0x85fa,0x85f8,0x85f5,
+ 0x85f4,0x85f1,0x85ef,0x85ec,0x85eb,0x85e8,0x85e5,0x85e3,0x85e0,0x85de,0x85db,0x85da,0x85d7,0x85d5,0x85d2,0x85d1,
+ 0x85ce,0x85cc,0x85c9,0x85c8,0x85c5,0x85c3,0x85c0,0x85be,0x85bb,0x85ba,0x85b7,0x85b4,0x85b2,0x85af,0x85ae,0x85ab,
+ 0x85a9,0x85a6,0x85a5,0x85a2,0x85a0,0x859d,0x859b,0x8598,0x8597,0x8594,0x8592,0x858f,0x858e,0x858b,0x8589,0x8586,
+ 0x8584,0x8581,0x8580,0x857d,0x857b,0x8578,0x8577,0x8573,0x8572,0x856f,0x856d,0x856a,0x8569,0x8566,0x8563,0x8561,
+ 0x855e,0x855d,0x855a,0x8558,0x8555,0x8554,0x8551,0x854f,0x854c,0x854a,0x8547,0x8546,0x8543,0x8541,0x853e,0x853d,
+ 0x853a,0x8538,0x8535,0x8534,0x8531,0x852f,0x852c,0x8529,0x8528,0x8524,0x8523,0x8520,0x851e,0x851b,0x851a,0x8517,
+ 0x8515,0x8512,0x8511,0x850e,0x850c,0x8509,0x8508,0x8505,0x8503,0x8500,0x84fe,0x84fb,0x84fa,0x84f7,0x84f5,0x84f2,
+ 0x84f1,0x84ee,0x84eb,0x84e9,0x84e6,0x84e5,0x84e2,0x84e0,0x84dd,0x84dc,0x84d8,0x84d7,0x84d4,0x84d2,0x84cf,0x84ce,
+ 0x84cb,0x84c9,0x84c6,0x84c5,0x84c2,0x84c0,0x84bd,0x84bc,0x84b9,0x84b7,0x84b4,0x84b1,0x84af,0x84ac,0x84ab,0x84a8,
+ 0x84a6,0x84a3,0x84a2,0x849f,0x849d,0x849a,0x8499,0x8496,0x8494,0x8491,0x8490,0x848d,0x848b,0x8488,0x8486,0x8483,
+ 0x8482,0x847f,0x847d,0x847a,0x8477,0x8476,0x8473,0x8471,0x846e,0x846d,0x846a,0x8468,0x8465,0x8463,0x8460,0x845f,
+ 0x845c,0x8459,0x8458,0x8455,0x8453,0x8450,0x844f,0x844c,0x844a,0x8447,0x8446,0x8443,0x8441,0x843e,0x843d,0x843a,
+ 0x8438,0x8435,0x8434,0x8431,0x842f,0x842c,0x842a,0x8427,0x8426,0x8423,0x8421,0x841e,0x841d,0x841a,0x8418,0x8415,
+ 0x8414,0x8411,0x840e,0x840c,0x8409,0x8408,0x8405,0x8403,0x8400,0x83fe,0x83fb,0x83fa,0x83f7,0x83f5,0x83f2,0x83f1,
+ 0x83ee,0x83ec,0x83e9,0x83e8,0x83e5,0x83e3,0x83e0,0x83df,0x83dc,0x83da,0x83d7,0x83d6,0x83d3,0x83d1,0x83ce,0x83cc,
+ 0x83c9,0x83c6,0x83c5,0x83c2,0x83c0,0x83bd,0x83bc,0x83b9,0x83b7,0x83b4,0x83b3,0x83b0,0x83ae,0x83ab,0x83aa,0x83a7,
+ 0x83a5,0x83a2,0x83a1,0x839d,0x839c,0x8399,0x8397,0x8394,0x8393,0x8390,0x838e,0x838b,0x838a,0x8387,0x8385,0x8382,
+ 0x8381,0x837e,0x837b,0x8379,0x8376,0x8375,0x8372,0x8370,0x836d,0x836b,0x8368,0x8367,0x8364,0x8362,0x835f,0x835e,
+ 0x835b,0x8359,0x8356,0x8355,0x8352,0x8350,0x834d,0x834c,0x8349,0x8347,0x8344,0x8343,0x8340,0x833e,0x833b,0x8339,
+ 0x8336,0x8335,0x8332,0x8330,0x832d,0x832c,0x8329,0x8327,0x8324,0x8323,0x8320,0x831e,0x831b,0x831a,0x8317,0x8315,
+ 0x8312,0x8311,0x830e,0x830c,0x8309,0x8308,0x8305,0x8302,0x8300,0x82fd,0x82fb,0x82f8,0x82f7,0x82f4,0x82f2,0x82ef,
+ 0x82ee,0x82eb,0x82e9,0x82e6,0x82e5,0x82e2,0x82e0,0x82dd,0x82dc,0x82d9,0x82d7,0x82d4,0x82d3,0x82d0,0x82ce,0x82cb,
+ 0x82ca,0x82c7,0x82c5,0x82c2,0x82c1,0x82bd,0x82bc,0x82b9,0x82b7,0x82b4,0x82b3,0x82b0,0x82ae,0x82ab,0x82aa,0x82a7,
+ 0x82a5,0x82a2,0x829f,0x829e,0x829b,0x8299,0x8296,0x8295,0x8292,0x8290,0x828d,0x828c,0x8289,0x8287,0x8284,0x8283,
+ 0x8280,0x827e,0x827b,0x8279,0x8276,0x8275,0x8272,0x8270,0x826d,0x826c,0x8269,0x8267,0x8264,0x8263,0x8260,0x825e,
+ 0x825b,0x825a,0x8257,0x8255,0x8252,0x8251,0x824e,0x824c,0x8249,0x8248,0x8245,0x8242,0x8240,0x823d,0x823b,0x8238,
+ 0x8237,0x8234,0x8232,0x822f,0x822e,0x822b,0x8229,0x8226,0x8225,0x8222,0x8220,0x821d,0x821c,0x8219,0x8217,0x8214,
+ 0x8214,0x8211,0x820e,0x820c,0x8209,0x8208,0x8205,0x8203,0x8200,0x81fe,0x81fb,0x81fa,0x81f7,0x81f5,0x81f2,0x81f1,
+ 0x81ee,0x81ec,0x81e9,0x81e8,0x81e5,0x81e3,0x81e0,0x81df,0x81dc,0x81da,0x81d7,0x81d6,0x81d3,0x81d1,0x81ce,0x81cd,
+ 0x81ca,0x81c8,0x81c5,0x81c4,0x81c1,0x81bf,0x81bc,0x81bb,0x81b8,0x81b6,0x81b3,0x81b2,0x81af,0x81ad,0x81aa,0x81a9,
+ 0x81a6,0x81a4,0x81a1,0x81a0,0x819c,0x819b,0x8198,0x8196,0x8193,0x8192,0x818f,0x818d,0x818a,0x8189,0x8186,0x8184,
+ 0x8181,0x817e,0x817d,0x817a,0x8178,0x8175,0x8174,0x8171,0x816f,0x816c,0x816b,0x8168,0x8166,0x8163,0x8162,0x815f,
+ 0x815d,0x815a,0x8159,0x8156,0x8154,0x8151,0x8150,0x814d,0x814b,0x8148,0x8147,0x8144,0x8142,0x813f,0x813d,0x813a,
+ 0x8139,0x8136,0x8134,0x8131,0x8130,0x812d,0x812b,0x8128,0x8127,0x8124,0x8122,0x811f,0x811e,0x811b,0x8119,0x8116,
+ 0x8115,0x8112,0x8110,0x810d,0x810c,0x8109,0x8107,0x8104,0x8103,0x8100,0x80fe,0x80fb,0x80fa,0x80f7,0x80f5,0x80f2,
+ 0x80f0,0x80ef,0x80ec,0x80ea,0x80e7,0x80e6,0x80e3,0x80e1,0x80de,0x80dd,0x80da,0x80d8,0x80d5,0x80d4,0x80d1,0x80cf,
+ 0x80cc,0x80cb,0x80c8,0x80c6,0x80c3,0x80c2,0x80bf,0x80bd,0x80ba,0x80b9,0x80b6,0x80b4,0x80b1,0x80b0,0x80ad,0x80ab,
+ 0x80a8,0x80a7,0x80a4,0x80a2,0x809f,0x809e,0x809b,0x8099,0x8096,0x8095,0x8092,0x8090,0x808d,0x808c,0x8089,0x8087,
+ 0x8084,0x8083,0x8080,0x807e,0x807b,0x807a,0x8077,0x8075,0x8072,0x8071,0x806e,0x806c,0x8069,0x8068,0x8065,0x8063,
+ 0x8060,0x805f,0x805c,0x805a,0x8057,0x8056,0x8053,0x8051,0x804e,0x804d,0x804a,0x8048,0x8045,0x8044,0x8041,0x803f,
+ 0x803c,0x803b,0x8038,0x8036,0x8033,0x8032,0x802f,0x802d,0x802a,0x8029,0x8026,0x8024,0x8021,0x8020,0x801d,0x801b,
+ 0x8018,0x8017,0x8014,0x8012,0x800f,0x800e,0x800b,0x8009,0x8006,0x8005,0x8002,0x8000,0x7ffd,0x7ffc,0x7ff9,0x7ff7,
+ 0x7ff4,0x7ff3,0x7ff0,0x7fee,0x7feb,0x7fea,0x7fe7,0x7fe5,0x7fe2,0x7fe1,0x7fde,0x7fdc,0x7fd9,0x7fd8,0x7fd5,0x7fd3,
+ 0x7fd0,0x7fcd,0x7fcb,0x7fc8,0x7fc7,0x7fc4,0x7fc2,0x7fc0,0x7fbe,0x7fbb,0x7fba,0x7fb7,0x7fb5,0x7fb2,0x7fb1,0x7fae,
+ 0x7fac,0x7fa9,0x7fa8,0x7fa5,0x7fa3,0x7fa0,0x7f9f,0x7f9c,0x7f9a,0x7f97,0x7f96,0x7f93,0x7f91,0x7f8e,0x7f8d,0x7f8a,
+ 0x7f88,0x7f85,0x7f84,0x7f81,0x7f7f,0x7f7c,0x7f7b,0x7f78,0x7f76,0x7f73,0x7f72,0x7f6f,0x7f6d,0x7f6a,0x7f69,0x7f66,
+ 0x7f64,0x7f61,0x7f60,0x7f5d,0x7f5b,0x7f58,0x7f57,0x7f54,0x7f52,0x7f4f,0x7f4e,0x7f4b,0x7f49,0x7f46,0x7f45,0x7f42,
+ 0x7f40,0x7f3f,0x7f3c,0x7f3a,0x7f37,0x7f36,0x7f33,0x7f31,0x7f2e,0x7f2d,0x7f2a,0x7f28,0x7f25,0x7f24,0x7f21,0x7f1f,
+ 0x7f1c,0x7f1b,0x7f18,0x7f16,0x7f13,0x7f12,0x7f0f,0x7f0d,0x7f0a,0x7f09,0x7f06,0x7f04,0x7f01,0x7f00,0x7efd,0x7efc,
+ 0x7ef9,0x7ef7,0x7ef4,0x7ef3,0x7ef0,0x7eee,0x7eeb,0x7eea,0x7ee7,0x7ee5,0x7ee2,0x7ee1,0x7ede,0x7edc,0x7ed9,0x7ed8,
+ 0x7ed5,0x7ed3,0x7ed0,0x7ecf,0x7ecc,0x7eca,0x7ec7,0x7ec6,0x7ec3,0x7ec1,0x7ebe,0x7ebd,0x7eba,0x7eb8,0x7eb5,0x7eb4,
+ 0x7eb2,0x7eaf,0x7ead,0x7eaa,0x7ea9,0x7ea6,0x7ea4,0x7ea1,0x7ea0,0x7e9d,0x7e9b,0x7e98,0x7e97,0x7e94,0x7e92,0x7e8f,
+ 0x7e8e,0x7e8b,0x7e89,0x7e86,0x7e85,0x7e82,0x7e80,0x7e7d,0x7e7c,0x7e79,0x7e77,0x7e74,0x7e73,0x7e70,0x7e6e,0x7e6b,
+ 0x7e6a,0x7e67,0x7e65,0x7e62,0x7e61,0x7e5e,0x7e5d,0x7e5a,0x7e58,0x7e55,0x7e54,0x7e51,0x7e4f,0x7e4c,0x7e4b,0x7e48,
+ 0x7e46,0x7e43,0x7e42,0x7e3f,0x7e3d,0x7e3a,0x7e39,0x7e36,0x7e34,0x7e31,0x7e30,0x7e2d,0x7e2b,0x7e28,0x7e27,0x7e24,
+ 0x7e22,0x7e21,0x7e1e,0x7e1c,0x7e19,0x7e18,0x7e15,0x7e13,0x7e10,0x7e0f,0x7e0c,0x7e0a,0x7e07,0x7e06,0x7e03,0x7e01,
+ 0x7dff,0x7dfd,0x7dfa,0x7df9,0x7df6,0x7df4,0x7df1,0x7df0,0x7ded,0x7deb,0x7de8,0x7de7,0x7de4,0x7de2,0x7ddf,0x7dde,
+ 0x7ddb,0x7dd9,0x7dd6,0x7dd5,0x7dd2,0x7dd0,0x7dcd,0x7dcc,0x7dc9,0x7dc7,0x7dc4,0x7dc3,0x7dc0,0x7dbe,0x7dbb,0x7dba,
+ 0x7db7,0x7db5,0x7db2,0x7db1,0x7dae,0x7dac,0x7da9,0x7da8,0x7da5,0x7da3,0x7da1,0x7d9f,0x7d9c,0x7d9b,0x7d98,0x7d96,
+ 0x7d93,0x7d92,0x7d8f,0x7d8d,0x7d8a,0x7d89,0x7d86,0x7d84,0x7d81,0x7d80,0x7d7d,0x7d7c,0x7d79,0x7d77,0x7d74,0x7d73,
+ 0x7d70,0x7d6e,0x7d6b,0x7d6a,0x7d67,0x7d65,0x7d64,0x7d61,0x7d5f,0x7d5c,0x7d5b,0x7d58,0x7d56,0x7d53,0x7d52,0x7d4f,
+ 0x7d4d,0x7d4a,0x7d49,0x7d46,0x7d44,0x7d41,0x7d40,0x7d3d,0x7d3c,0x7d39,0x7d37,0x7d34,0x7d33,0x7d30,0x7d2e,0x7d2b,
+ 0x7d2a,0x7d27,0x7d25,0x7d22,0x7d21,0x7d1e,0x7d1c,0x7d19,0x7d18,0x7d15,0x7d13,0x7d10,0x7d0f,0x7d0c,0x7d0a,0x7d07,
+ 0x7d06,0x7d04,0x7d01,0x7d00,0x7cfd,0x7cfc,0x7cf9,0x7cf7,0x7cf4,0x7cf3,0x7cf0,0x7cee,0x7ceb,0x7cea,0x7ce7,0x7ce5,
+ 0x7ce2,0x7ce1,0x7cde,0x7cdc,0x7cd9,0x7cd8,0x7cd5,0x7cd3,0x7cd0,0x7ccf,0x7ccc,0x7cca,0x7cc7,0x7cc6,0x7cc3,0x7cc1,
+ 0x7cbf,0x7cbd,0x7cba,0x7cb9,0x7cb6,0x7cb4,0x7cb1,0x7cb0,0x7cad,0x7cab,0x7ca8,0x7ca7,0x7ca5,0x7ca2,0x7ca1,0x7c9e,
+ 0x7c9c,0x7c99,0x7c98,0x7c95,0x7c93,0x7c90,0x7c8f,0x7c8c,0x7c8a,0x7c87,0x7c86,0x7c83,0x7c81,0x7c7f,0x7c7d,0x7c7a,
+ 0x7c78,0x7c77,0x7c74,0x7c72,0x7c6f,0x7c6e,0x7c6b,0x7c69,0x7c66,0x7c65,0x7c62,0x7c60,0x7c5e,0x7c5c,0x7c59,0x7c58,
+ 0x7c55,0x7c53,0x7c50,0x7c4f,0x7c4c,0x7c4a,0x7c47,0x7c46,0x7c43,0x7c41,0x7c3e,0x7c3d,0x7c3a,0x7c38,0x7c35,0x7c34,
+ 0x7c32,0x7c30,0x7c2e,0x7c2b,0x7c2a,0x7c27,0x7c25,0x7c22,0x7c21,0x7c1e,0x7c1c,0x7c19,0x7c18,0x7c15,0x7c13,0x7c10,
+ 0x7c0f,0x7c0c,0x7c0a,0x7c07,0x7c06,0x7c03,0x7c01,0x7bff,0x7bfd,0x7bfa,0x7bf9,0x7bf6,0x7bf4,0x7bf1,0x7bf0,0x7bed,
+ 0x7beb,0x7bea,0x7be7,0x7be5,0x7be2,0x7be1,0x7bde,0x7bdc,0x7bd9,0x7bd8,0x7bd5,0x7bd3,0x7bd1,0x7bcf,0x7bcc,0x7bcb,
+ 0x7bc8,0x7bc6,0x7bc3,0x7bc2,0x7bbf,0x7bbd,0x7bba,0x7bb9,0x7bb6,0x7bb4,0x7bb1,0x7bb0,0x7bad,0x7bab,0x7ba8,0x7ba7,
+ 0x7ba5,0x7ba2,0x7ba1,0x7b9e,0x7b9d,0x7b9a,0x7b98,0x7b95,0x7b94,0x7b91,0x7b8f,0x7b8c,0x7b8b,0x7b88,0x7b86,0x7b83,
+ 0x7b82,0x7b7f,0x7b7d,0x7b7a,0x7b79,0x7b76,0x7b74,0x7b72,0x7b70,0x7b6d,0x7b6c,0x7b69,0x7b67,0x7b64,0x7b63,0x7b60,
+ 0x7b5f,0x7b5c,0x7b5a,0x7b57,0x7b56,0x7b53,0x7b51,0x7b4e,0x7b4d,0x7b4a,0x7b49,0x7b46,0x7b44,0x7b43,0x7b40,0x7b3e,
+ 0x7b3b,0x7b3a,0x7b37,0x7b35,0x7b32,0x7b31,0x7b2e,0x7b2c,0x7b29,0x7b28,0x7b25,0x7b24,0x7b21,0x7b1f,0x7b1c,0x7b1b,
+ 0x7b18,0x7b16,0x7b13,0x7b12,0x7b0f,0x7b0d,0x7b0a,0x7b09,0x7b07,0x7b04,0x7b03,0x7b00,0x7aff,0x7afc,0x7afa,0x7af7,
+ 0x7af6,0x7af3,0x7af1,0x7aee,0x7aed,0x7aea,0x7ae8,0x7ae5,0x7ae4,0x7ae1,0x7adf,0x7adc,0x7adb,0x7ad8,0x7ad7,0x7ad4,
+ 0x7ad2,0x7ad1,0x7ace,0x7acc,0x7ac9,0x7ac8,0x7ac5,0x7ac3,0x7ac0,0x7abf,0x7abc,0x7aba,0x7ab7,0x7ab6,0x7ab3,0x7ab2,
+ 0x7aaf,0x7aad,0x7aaa,0x7aa9,0x7aa6,0x7aa4,0x7aa1,0x7aa0,0x7a9d,0x7a9b,0x7a9a,0x7a97,0x7a95,0x7a92,0x7a91,0x7a8e,
+ 0x7a8d,0x7a8a,0x7a88,0x7a85,0x7a84,0x7a81,0x7a7f,0x7a7c,0x7a7b,0x7a78,0x7a76,0x7a73,0x7a72,0x7a6f,0x7a6d,0x7a6a,
+ 0x7a69,0x7a66,0x7a65,0x7a62,0x7a60,0x7a5f,0x7a5c,0x7a5a,0x7a57,0x7a56,0x7a53,0x7a51,0x7a4e,0x7a4d,0x7a4a,0x7a48,
+ 0x7a47,0x7a44,0x7a42,0x7a3f,0x7a3e,0x7a3b,0x7a3a,0x7a37,0x7a35,0x7a32,0x7a31,0x7a2e,0x7a2c,0x7a29,0x7a28,0x7a25,
+ 0x7a23,0x7a20,0x7a1f,0x7a1c,0x7a1b,0x7a18,0x7a16,0x7a15,0x7a12,0x7a10,0x7a0d,0x7a0c,0x7a09,0x7a07,0x7a04,0x7a03,
+ 0x7a00,0x79ff,0x79fc,0x79fa,0x79f7,0x79f6,0x79f3,0x79f1,0x79ee,0x79ed,0x79ea,0x79e8,0x79e7,0x79e4,0x79e2,0x79e0,
+ 0x79de,0x79db,0x79da,0x79d7,0x79d5,0x79d2,0x79d1,0x79ce,0x79cc,0x79c9,0x79c8,0x79c5,0x79c3,0x79c1,0x79bf,0x79bc,
+ 0x79bb,0x79b9,0x79b6,0x79b5,0x79b2,0x79b0,0x79ad,0x79ac,0x79a9,0x79a7,0x79a4,0x79a3,0x79a0,0x799f,0x799c,0x799a,
+ 0x7997,0x7996,0x7993,0x7991,0x798e,0x798d,0x798b,0x7988,0x7987,0x7984,0x7982,0x7980,0x797e,0x797b,0x797a,0x7977,
+ 0x7975,0x7972,0x7971,0x796e,0x796c,0x7969,0x7968,0x7965,0x7963,0x7961,0x795f,0x795e,0x795b,0x7959,0x7956,0x7955,
+ 0x7952,0x7950,0x794d,0x794c,0x7949,0x7947,0x7944,0x7943,0x7940,0x793f,0x793c,0x793a,0x7937,0x7936,0x7933,0x7931,
+ 0x792f,0x792e,0x792b,0x7929,0x7926,0x7925,0x7922,0x7920,0x791d,0x791c,0x791b,0x7918,0x7916,0x7913,0x7912,0x790f,
+ 0x790d,0x790a,0x7909,0x7906,0x7904,0x7901,0x7900,0x78fd,0x78fc,0x78f9,0x78f7,0x78f4,0x78f3,0x78f1,0x78ee,0x78ed,
+ 0x78ea,0x78e8,0x78e5,0x78e4,0x78e1,0x78e0,0x78dd,0x78db,0x78d8,0x78d7,0x78d4,0x78d2,0x78cf,0x78ce,0x78cc,0x78ca,
+ 0x78c8,0x78c5,0x78c4,0x78c1,0x78bf,0x78bc,0x78bb,0x78b8,0x78b6,0x78b3,0x78b2,0x78af,0x78ae,0x78ab,0x78a9,0x78a6,
+ 0x78a5,0x78a3,0x78a0,0x789f,0x789c,0x789a,0x7897,0x7896,0x7893,0x7892,0x788f,0x788d,0x788a,0x7889,0x7886,0x7884,
+ 0x7881,0x7880,0x787d,0x787b,0x787a,0x7877,0x7876,0x7873,0x7871,0x786e,0x786d,0x786a,0x7868,0x7865,0x7864,0x7861,
+ 0x785f,0x785d,0x785b,0x7858,0x7857,0x7855,0x7852,0x7851,0x784e,0x784c,0x7849,0x7848,0x7845,0x7844,0x7841,0x783f,
+ 0x783c,0x783b,0x7838,0x7836,0x7833,0x7832,0x782f,0x782d,0x782c,0x7829,0x7828,0x7825,0x7823,0x7820,0x781f,0x781c,
+ 0x781a,0x7819,0x7816,0x7815,0x7812,0x7810,0x780d,0x780c,0x7809,0x7807,0x7804,0x7803,0x7800,0x77ff,0x77fc,0x77fa,
+ 0x77f9,0x77f6,0x77f4,0x77f1,0x77f0,0x77ed,0x77eb,0x77e9,0x77e7,0x77e4,0x77e3,0x77e0,0x77de,0x77db,0x77da,0x77d7,
+ 0x77d5,0x77d4,0x77d1,0x77d0,0x77cd,0x77cb,0x77c8,0x77c7,0x77c4,0x77c2,0x77bf,0x77be,0x77bb,0x77ba,0x77b7,0x77b5,
+ 0x77b4,0x77b1,0x77af,0x77ac,0x77ab,0x77a8,0x77a6,0x77a3,0x77a2,0x779f,0x779e,0x779b,0x7799,0x7796,0x7795,0x7792,
+ 0x7790,0x778f,0x778c,0x778b,0x7788,0x7786,0x7783,0x7782,0x777f,0x777d,0x777a,0x7779,0x7776,0x7774,0x7772,0x7770,
+ 0x776f,0x776c,0x776a,0x7767,0x7766,0x7763,0x7761,0x775e,0x775d,0x775a,0x7759,0x7756,0x7754,0x7751,0x7750,0x774d,
+ 0x774b,0x774a,0x7747,0x7745,0x7743,0x7741,0x773e,0x773d,0x773a,0x7738,0x7735,0x7734,0x7731,0x772f,0x772d,0x772b,
+ 0x772a,0x7727,0x7725,0x7722,0x7721,0x771e,0x771c,0x7719,0x7718,0x7715,0x7714,0x7711,0x770f,0x770c,0x770b,0x7708,
+ 0x7707,0x7704,0x7703,0x7700,0x76fe,0x76fb,0x76fa,0x76f7,0x76f5,0x76f3,0x76f1,0x76ee,0x76ed,0x76eb,0x76e8,0x76e7,
+ 0x76e4,0x76e2,0x76e0,0x76de,0x76db,0x76da,0x76d7,0x76d5,0x76d2,0x76d1,0x76cf,0x76cd,0x76cb,0x76c8,0x76c7,0x76c4,
+ 0x76c2,0x76bf,0x76be,0x76bb,0x76ba,0x76b7,0x76b5,0x76b4,0x76b1,0x76af,0x76ac,0x76ab,0x76a8,0x76a7,0x76a4,0x76a2,
+ 0x769f,0x769e,0x769b,0x7699,0x7698,0x7695,0x7694,0x7691,0x768f,0x768c,0x768b,0x7688,0x7686,0x7683,0x7682,0x767f,
+ 0x767e,0x767c,0x7679,0x7678,0x7675,0x7673,0x7670,0x766f,0x766c,0x766b,0x7668,0x7666,0x7663,0x7662,0x7660,0x765e,
+ 0x765c,0x7659,0x7658,0x7655,0x7653,0x7650,0x764f,0x764c,0x764b,0x7648,0x7646,0x7645,0x7642,0x7640,0x763d,0x763c,
+ 0x7639,0x7638,0x7635,0x7633,0x7630,0x762f,0x762c,0x762a,0x7629,0x7626,0x7625,0x7622,0x7620,0x761d,0x761c,0x7619,
+ 0x7617,0x7614,0x7613,0x7610,0x760f,0x760d,0x760a,0x7609,0x7606,0x7604,0x7601,0x7600,0x75fd,0x75fc,0x75f9,0x75f7,
+ 0x75f5,0x75f2,0x75f0,0x75ed,0x75ec,0x75e9,0x75e8,0x75e6,0x75e3,0x75e2,0x75df,0x75dd,0x75db,0x75d9,0x75d6,0x75d5,
+ 0x75d2,0x75d0,0x75cf,0x75cc,0x75cb,0x75c8,0x75c6,0x75c3,0x75c2,0x75bf,0x75bd,0x75bb,0x75b9,0x75b6,0x75b5,0x75b3,
+ 0x75b0,0x75af,0x75ac,0x75aa,0x75a8,0x75a6,0x75a3,0x75a2,0x759f,0x759d,0x759c,0x7599,0x7598,0x7595,0x7593,0x7590,
+ 0x758f,0x758c,0x758a,0x7588,0x7586,0x7585,0x7582,0x7580,0x757d,0x757c,0x7579,0x7577,0x7575,0x7573,0x7570,0x756f,
+ 0x756d,0x756a,0x7569,0x7566,0x7565,0x7562,0x7560,0x755d,0x755c,0x7559,0x7557,0x7555,0x7553,0x7552,0x754f,0x754d,
+ 0x754a,0x7549,0x7546,0x7544,0x7542,0x7540,0x753d,0x753c,0x753a,0x7537,0x7536,0x7533,0x7532,0x752f,0x752d,0x752a,
+ 0x7529,0x7526,0x7524,0x7523,0x7520,0x751f,0x751c,0x751a,0x7517,0x7516,0x7513,0x7511,0x750f,0x750d,0x750a,0x7509,
+ 0x7507,0x7504,0x7503,0x7500,0x74ff,0x74fc,0x74fa,0x74f7,0x74f6,0x74f3,0x74f1,0x74f0,0x74ed,0x74ec,0x74e9,0x74e7,
+ 0x74e4,0x74e3,0x74e0,0x74de,0x74db,0x74da,0x74d7,0x74d6,0x74d3,0x74d1,0x74ce,0x74cd,0x74cb,0x74c9,0x74c7,0x74c4,
+ 0x74c3,0x74c0,0x74be,0x74bb,0x74ba,0x74b7,0x74b6,0x74b4,0x74b1,0x74b0,0x74ad,0x74ab,0x74a9,0x74a7,0x74a4,0x74a3,
+ 0x74a1,0x749e,0x749d,0x749a,0x7499,0x7496,0x7494,0x7491,0x7490,0x748d,0x748c,0x748a,0x7487,0x7486,0x7483,0x7481,
+ 0x747e,0x747d,0x747a,0x7479,0x7476,0x7474,0x7473,0x7470,0x746e,0x746c,0x746a,0x7467,0x7466,0x7463,0x7461,0x745e,
+ 0x745d,0x745c,0x7459,0x7457,0x7454,0x7453,0x7450,0x744e,0x744c,0x744a,0x7447,0x7446,0x7444,0x7441,0x7440,0x743d,
+ 0x743c,0x7439,0x7437,0x7434,0x7433,0x7430,0x742f,0x742d,0x742a,0x7429,0x7426,0x7424,0x7421,0x7420,0x741d,0x741c,
+ 0x741a,0x7417,0x7416,0x7413,0x7411,0x740f,0x740d,0x740a,0x7409,0x7406,0x7404,0x7403,0x7400,0x73ff,0x73fc,0x73fa,
+ 0x73f7,0x73f6,0x73f3,0x73f1,0x73ef,0x73ed,0x73ec,0x73e9,0x73e7,0x73e4,0x73e3,0x73e0,0x73df,0x73dc,0x73da,0x73d7,
+ 0x73d5,0x73d4,0x73d1,0x73cf,0x73cc,0x73cb,0x73c9,0x73c7,0x73c5,0x73c2,0x73c1,0x73be,0x73bc,0x73ba,0x73b8,0x73b7,
+ 0x73b4,0x73b2,0x73af,0x73ae,0x73ab,0x73aa,0x73a7,0x73a5,0x73a2,0x73a1,0x739f,0x739d,0x739b,0x7398,0x7397,0x7394,
+ 0x7392,0x738f,0x738e,0x738d,0x738a,0x7388,0x7385,0x7384,0x7381,0x7380,0x737d,0x737b,0x7378,0x7377,0x7375,0x7372,
+ 0x7371,0x736e,0x736d,0x736a,0x7368,0x7365,0x7364,0x7363,0x7360,0x735e,0x735b,0x735a,0x7357,0x7356,0x7353,0x7351,
+ 0x7350,0x734d,0x734b,0x7348,0x7347,0x7344,0x7343,0x7340,0x733e,0x733b,0x733a,0x7339,0x7336,0x7334,0x7331,0x7330,
+ 0x732d,0x732b,0x7329,0x7327,0x7326,0x7323,0x7321,0x731e,0x731d,0x731a,0x7319,0x7316,0x7314,0x7311,0x7310,0x730e,
+ 0x730c,0x730a,0x7307,0x7306,0x7303,0x7301,0x72ff,0x72fd,0x72fc,0x72f9,0x72f7,0x72f4,0x72f3,0x72f0,0x72ef,0x72ec,
+ 0x72ea,0x72e7,0x72e6,0x72e4,0x72e2,0x72e0,0x72dd,0x72dc,0x72d9,0x72d7,0x72d5,0x72d3,0x72d2,0x72cf,0x72cd,0x72ca,
+ 0x72c9,0x72c6,0x72c5,0x72c2,0x72c0,0x72bd,0x72bc,0x72b9,0x72b8,0x72b5,0x72b3,0x72b2,0x72af,0x72ad,0x72ab,0x72a9,
+ 0x72a6,0x72a5,0x72a2,0x72a0,0x729f,0x729c,0x729b,0x7298,0x7296,0x7293,0x7292,0x728f,0x728e,0x728c,0x7289,0x7288,
+ 0x7285,0x7284,0x7281,0x727f,0x727c,0x727b,0x7279,0x7277,0x7275,0x7272,0x7271,0x726e,0x726c,0x726a,0x7268,0x7267,
+ 0x7264,0x7262,0x725f,0x725e,0x725b,0x725a,0x7257,0x7255,0x7254,0x7251,0x724f,0x724d,0x724b,0x7248,0x7247,0x7244,
+ 0x7242,0x7241,0x723e,0x723d,0x723a,0x7238,0x7235,0x7234,0x7231,0x7230,0x722e,0x722b,0x722a,0x7227,0x7226,0x7223,
+ 0x7221,0x721e,0x721d,0x721b,0x7219,0x7217,0x7214,0x7213,0x7210,0x720e,0x720c,0x720a,0x7209,0x7206,0x7204,0x7201,
+ 0x7200,0x71fd,0x71fc,0x71f9,0x71f7,0x71f6,0x71f3,0x71f2,0x71ef,0x71ed,0x71ea,0x71e9,0x71e6,0x71e5,0x71e3,0x71e0,
+ 0x71df,0x71dc,0x71da,0x71d8,0x71d6,0x71d3,0x71d2,0x71d0,0x71cd,0x71cc,0x71c9,0x71c8,0x71c5,0x71c3,0x71c0,0x71bf,
+ 0x71bd,0x71ba,0x71b9,0x71b6,0x71b4,0x71b3,0x71b0,0x71ae,0x71ac,0x71aa,0x71a7,0x71a6,0x71a3,0x71a1,0x71a0,0x719d,
+ 0x719c,0x7199,0x7197,0x7194,0x7193,0x7190,0x718f,0x718d,0x718a,0x7189,0x7186,0x7185,0x7182,0x7180,0x717f,0x717c,
+ 0x717b,0x7178,0x7176,0x7173,0x7172,0x716f,0x716e,0x716c,0x7169,0x7168,0x7165,0x7163,0x7161,0x715f,0x715c,0x715b,
+ 0x7159,0x7156,0x7155,0x7152,0x7151,0x714e,0x714c,0x714a,0x7148,0x7147,0x7144,0x7142,0x713f,0x713e,0x713b,0x713a,
+ 0x7138,0x7135,0x7134,0x7131,0x7130,0x712d,0x712b,0x7128,0x7127,0x7125,0x7123,0x7121,0x711e,0x711d,0x711a,0x7119,
+ 0x7116,0x7114,0x7113,0x7110,0x710e,0x710c,0x710a,0x7107,0x7106,0x7103,0x7101,0x7100,0x70fd,0x70fc,0x70f9,0x70f7,
+ 0x70f4,0x70f3,0x70f0,0x70ef,0x70ed,0x70ea,0x70e9,0x70e6,0x70e5,0x70e2,0x70e0,0x70df,0x70dc,0x70db,0x70d8,0x70d6,
+ 0x70d3,0x70d2,0x70cf,0x70ce,0x70cc,0x70c9,0x70c8,0x70c5,0x70c3,0x70c1,0x70bf,0x70bc,0x70bb,0x70b9,0x70b6,0x70b5,
+ 0x70b2,0x70b1,0x70ae,0x70ad,0x70aa,0x70a8,0x70a5,0x70a4,0x70a2,0x70a0,0x709e,0x709b,0x709a,0x7097,0x7096,0x7093,
+ 0x7091,0x7090,0x708d,0x708b,0x7089,0x7087,0x7084,0x7083,0x7081,0x707f,0x707d,0x707a,0x7079,0x7076,0x7074,0x7072,
+ 0x7070,0x706f,0x706c,0x706a,0x7068,0x7066,0x7063,0x7062,0x7060,0x705d,0x705c,0x7059,0x7058,0x7055,0x7053,0x7051,
+ 0x704f,0x704e,0x704b,0x7049,0x7046,0x7045,0x7042,0x7041,0x703f,0x703c,0x703b,0x7038,0x7037,0x7034,0x7032,0x702f,
+ 0x702e,0x702d,0x702a,0x7028,0x7025,0x7024,0x7021,0x7020,0x701e,0x701b,0x701a,0x7017,0x7016,0x7013,0x7011,0x700e,
+ 0x700d,0x700c,0x7009,0x7007,0x7004,0x7003,0x7000,0x6fff,0x6ffd,0x6ffa,0x6ff9,0x6ff6,0x6ff5,0x6ff2,0x6ff0,0x6fed,
+ 0x6fec,0x6fea,0x6fe8,0x6fe6,0x6fe3,0x6fe2,0x6fdf,0x6fde,0x6fdc,0x6fd9,0x6fd8,0x6fd5,0x6fd3,0x6fd1,0x6fcf,0x6fcc,
+ 0x6fcb,0x6fc9,0x6fc7,0x6fc5,0x6fc2,0x6fc1,0x6fbe,0x6fbc,0x6fbb,0x6fb8,0x6fb7,0x6fb4,0x6fb2,0x6fb0,0x6fae,0x6fab,
+ 0x6fa9,0x6fa8,0x6fa5,0x6fa3,0x6fa2,0x6f9f,0x6f9e,0x6f9b,0x6f99,0x6f97,0x6f95,0x6f92,0x6f91,0x6f8f,0x6f8c,0x6f8b,
+ 0x6f88,0x6f87,0x6f84,0x6f82,0x6f81,0x6f7e,0x6f7d,0x6f7a,0x6f78,0x6f76,0x6f74,0x6f73,0x6f70,0x6f6e,0x6f6c,0x6f6a,
+ 0x6f67,0x6f66,0x6f64,0x6f61,0x6f60,0x6f5d,0x6f5c,0x6f59,0x6f57,0x6f55,0x6f53,0x6f52,0x6f4f,0x6f4d,0x6f4b,0x6f49,
+ 0x6f46,0x6f45,0x6f43,0x6f41,0x6f3f,0x6f3c,0x6f3b,0x6f38,0x6f36,0x6f35,0x6f32,0x6f31,0x6f2e,0x6f2c,0x6f2a,0x6f28,
+ 0x6f27,0x6f24,0x6f22,0x6f20,0x6f1e,0x6f1b,0x6f1a,0x6f17,0x6f16,0x6f14,0x6f11,0x6f10,0x6f0d,0x6f0b,0x6f09,0x6f07,
+ 0x6f06,0x6f03,0x6f01,0x6eff,0x6efd,0x6efa,0x6ef9,0x6ef7,0x6ef5,0x6ef3,0x6ef0,0x6eef,0x6eec,0x6eea,0x6ee8,0x6ee6,
+ 0x6ee5,0x6ee2,0x6ee0,0x6ede,0x6edc,0x6ed9,0x6ed8,0x6ed6,0x6ed4,0x6ed2,0x6ecf,0x6ece,0x6ecb,0x6eca,0x6ec8,0x6ec5,
+ 0x6ec4,0x6ec1,0x6ebf,0x6ebd,0x6ebb,0x6eba,0x6eb7,0x6eb5,0x6eb3,0x6eb1,0x6eae,0x6ead,0x6eaa,0x6ea9,0x6ea7,0x6ea4,
+ 0x6ea3,0x6ea0,0x6e9f,0x6e9c,0x6e9a,0x6e98,0x6e96,0x6e93,0x6e92,0x6e90,0x6e8e,0x6e8c,0x6e89,0x6e88,0x6e85,0x6e84,
+ 0x6e82,0x6e7f,0x6e7e,0x6e7b,0x6e7a,0x6e77,0x6e75,0x6e74,0x6e71,0x6e70,0x6e6d,0x6e6b,0x6e68,0x6e67,0x6e66,0x6e63,
+ 0x6e61,0x6e5e,0x6e5d,0x6e5a,0x6e59,0x6e57,0x6e54,0x6e53,0x6e50,0x6e4f,0x6e4c,0x6e4a,0x6e49,0x6e46,0x6e45,0x6e42,
+ 0x6e40,0x6e3d,0x6e3c,0x6e3b,0x6e38,0x6e36,0x6e33,0x6e32,0x6e2f,0x6e2e,0x6e2c,0x6e29,0x6e28,0x6e25,0x6e24,0x6e21,
+ 0x6e1f,0x6e1e,0x6e1b,0x6e1a,0x6e17,0x6e15,0x6e13,0x6e11,0x6e10,0x6e0d,0x6e0b,0x6e09,0x6e07,0x6e04,0x6e03,0x6e01,
+ 0x6dff,0x6dfd,0x6dfa,0x6df9,0x6df6,0x6df5,0x6df3,0x6df0,0x6def,0x6dec,0x6deb,0x6de8,0x6de6,0x6de5,0x6de2,0x6de1,
+ 0x6dde,0x6ddc,0x6dd9,0x6dd8,0x6dd7,0x6dd4,0x6dd2,0x6dcf,0x6dce,0x6dcb,0x6dca,0x6dc8,0x6dc5,0x6dc4,0x6dc1,0x6dc0,
+ 0x6dbd,0x6dbb,0x6dba,0x6db7,0x6db6,0x6db3,0x6db1,0x6daf,0x6dad,0x6dac,0x6da9,0x6da7,0x6da5,0x6da3,0x6da0,0x6d9f,
+ 0x6d9d,0x6d9a,0x6d99,0x6d96,0x6d94,0x6d93,0x6d90,0x6d8f,0x6d8c,0x6d8a,0x6d87,0x6d86,0x6d85,0x6d82,0x6d80,0x6d7d,
+ 0x6d7c,0x6d7b,0x6d78,0x6d76,0x6d73,0x6d72,0x6d6f,0x6d6e,0x6d6c,0x6d6a,0x6d68,0x6d65,0x6d64,0x6d61,0x6d60,0x6d5e,
+ 0x6d5b,0x6d5a,0x6d57,0x6d56,0x6d53,0x6d51,0x6d50,0x6d4d,0x6d4c,0x6d49,0x6d47,0x6d44,0x6d43,0x6d42,0x6d3f,0x6d3d,
+ 0x6d3a,0x6d39,0x6d36,0x6d35,0x6d33,0x6d30,0x6d2f,0x6d2c,0x6d2b,0x6d28,0x6d26,0x6d25,0x6d22,0x6d21,0x6d1e,0x6d1d,
+ 0x6d1b,0x6d18,0x6d17,0x6d14,0x6d13,0x6d10,0x6d0e,0x6d0d,0x6d0a,0x6d09,0x6d06,0x6d04,0x6d01,0x6d00,0x6cff,0x6cfc,
+ 0x6cfa,0x6cf7,0x6cf6,0x6cf3,0x6cf2,0x6cf0,0x6ced,0x6cec,0x6ce9,0x6ce8,0x6ce5,0x6ce3,0x6ce2,0x6cdf,0x6cde,0x6cdb,
+ 0x6cda,0x6cd7,0x6cd5,0x6cd4,0x6cd1,0x6cd0,0x6ccd,0x6ccb,0x6cc8,0x6cc7,0x6cc6,0x6cc3,0x6cc1,0x6cbe,0x6cbd,0x6cba,
+ 0x6cb9,0x6cb7,0x6cb4,0x6cb3,0x6cb0,0x6caf,0x6cad,0x6caa,0x6ca9,0x6ca6,0x6ca5,0x6ca2,0x6ca0,0x6c9f,0x6c9c,0x6c9b,
+ 0x6c98,0x6c97,0x6c94,0x6c92,0x6c90,0x6c8e,0x6c8b,0x6c8a,0x6c89,0x6c86,0x6c84,0x6c81,0x6c80,0x6c7f,0x6c7c,0x6c7a,
+ 0x6c77,0x6c76,0x6c73,0x6c72,0x6c70,0x6c6d,0x6c6c,0x6c69,0x6c68,0x6c65,0x6c64,0x6c62,0x6c5f,0x6c5e,0x6c5b,0x6c5a,
+ 0x6c58,0x6c55,0x6c54,0x6c51,0x6c50,0x6c4d,0x6c4b,0x6c4a,0x6c47,0x6c46,0x6c43,0x6c41,0x6c3f,0x6c3d,0x6c3c,0x6c39,
+ 0x6c37,0x6c35,0x6c33,0x6c30,0x6c2f,0x6c2e,0x6c2b,0x6c29,0x6c26,0x6c25,0x6c24,0x6c21,0x6c1f,0x6c1c,0x6c1b,0x6c18,
+ 0x6c17,0x6c15,0x6c12,0x6c11,0x6c0e,0x6c0d,0x6c0a,0x6c09,0x6c07,0x6c04,0x6c03,0x6c00,0x6bff,0x6bfd,0x6bfa,0x6bf9,
+ 0x6bf6,0x6bf5,0x6bf2,0x6bf0,0x6bef,0x6bec,0x6beb,0x6be8,0x6be6,0x6be4,0x6be2,0x6be1,0x6bde,0x6bdc,0x6bda,0x6bd8,
+ 0x6bd7,0x6bd4,0x6bd3,0x6bd0,0x6bce,0x6bcb,0x6bca,0x6bc9,0x6bc6,0x6bc4,0x6bc1,0x6bc0,0x6bbd,0x6bbc,0x6bba,0x6bb7,
+ 0x6bb6,0x6bb3,0x6bb2,0x6baf,0x6bae,0x6bac,0x6ba9,0x6ba8,0x6ba5,0x6ba4,0x6ba2,0x6b9f,0x6b9e,0x6b9b,0x6b9a,0x6b97,
+ 0x6b95,0x6b93,0x6b91,0x6b8f,0x6b8e,0x6b8b,0x6b8a,0x6b87,0x6b85,0x6b82,0x6b81,0x6b80,0x6b7d,0x6b7b,0x6b79,0x6b77,
+ 0x6b76,0x6b73,0x6b71,0x6b6f,0x6b6d,0x6b6a,0x6b69,0x6b68,0x6b65,0x6b63,0x6b60,0x6b5f,0x6b5e,0x6b5b,0x6b59,0x6b56,
+ 0x6b55,0x6b52,0x6b51,0x6b4f,0x6b4d,0x6b4b,0x6b48,0x6b47,0x6b45,0x6b43,0x6b41,0x6b3e,0x6b3d,0x6b3a,0x6b39,0x6b37,
+ 0x6b34,0x6b33,0x6b30,0x6b2f,0x6b2d,0x6b2b,0x6b29,0x6b26,0x6b25,0x6b22,0x6b21,0x6b1f,0x6b1c,0x6b1b,0x6b18,0x6b17,
+ 0x6b15,0x6b12,0x6b11,0x6b0e,0x6b0d,0x6b0a,0x6b09,0x6b07,0x6b04,0x6b03,0x6b00,0x6aff,0x6afc,0x6afa,0x6af9,0x6af6,
+ 0x6af5,0x6af2,0x6af0,0x6aef,0x6aec,0x6aeb,0x6ae8,0x6ae6,0x6ae4,0x6ae2,0x6ae1,0x6ade,0x6add,0x6ada,0x6ad8,0x6ad7,
+ 0x6ad4,0x6ad3,0x6ad0,0x6ace,0x6acc,0x6aca,0x6ac9,0x6ac6,0x6ac4,0x6ac2,0x6ac0,0x6abf,0x6abc,0x6abb,0x6ab8,0x6ab6,
+ 0x6ab3,0x6ab2,0x6ab1,0x6aae,0x6aac,0x6aaa,0x6aa8,0x6aa7,0x6aa4,0x6aa2,0x6aa0,0x6a9e,0x6a9b,0x6a9a,0x6a98,0x6a96,
+ 0x6a94,0x6a92,0x6a90,0x6a8d,0x6a8c,0x6a89,0x6a88,0x6a86,0x6a84,0x6a82,0x6a7f,0x6a7e,0x6a7c,0x6a7a,0x6a78,0x6a75,
+ 0x6a74,0x6a71,0x6a70,0x6a6e,0x6a6b,0x6a6a,0x6a67,0x6a66,0x6a64,0x6a62,0x6a60,0x6a5d,0x6a5c,0x6a59,0x6a58,0x6a56,
+ 0x6a53,0x6a52,0x6a4f,0x6a4e,0x6a4c,0x6a4a,0x6a48,0x6a45,0x6a44,0x6a42,0x6a40,0x6a3e,0x6a3b,0x6a3a,0x6a37,0x6a36,
+ 0x6a34,0x6a31,0x6a30,0x6a2d,0x6a2c,0x6a2a,0x6a28,0x6a26,0x6a23,0x6a22,0x6a1f,0x6a1e,0x6a1c,0x6a19,0x6a18,0x6a15,
+ 0x6a14,0x6a12,0x6a10,0x6a0e,0x6a0b,0x6a0a,0x6a08,0x6a06,0x6a04,0x6a01,0x6a00,0x69fd,0x69fc,0x69fa,0x69f8,0x69f6,
+ 0x69f3,0x69f2,0x69f0,0x69ee,0x69ec,0x69e9,0x69e8,0x69e5,0x69e4,0x69e2,0x69df,0x69de,0x69db,0x69da,0x69d8,0x69d6,
+ 0x69d4,0x69d1,0x69d0,0x69cf,0x69cc,0x69ca,0x69c7,0x69c6,0x69c3,0x69c2,0x69c0,0x69be,0x69bc,0x69b9,0x69b8,0x69b6,
+ 0x69b4,0x69b2,0x69af,0x69ae,0x69ab,0x69aa,0x69a8,0x69a6,0x69a4,0x69a1,0x69a0,0x699e,0x699c,0x699a,0x6997,0x6996,
+ 0x6994,0x6991,0x6990,0x698e,0x698c,0x698a,0x6987,0x6986,0x6983,0x6982,0x6980,0x697e,0x697c,0x6979,0x6978,0x6976,
+ 0x6974,0x6972,0x696f,0x696e,0x696d,0x696a,0x6968,0x6966,0x6964,0x6961,0x6960,0x695e,0x695c,0x695a,0x6957,0x6956,
+ 0x6955,0x6952,0x6950,0x694e,0x694c,0x694b,0x6948,0x6947,0x6944,0x6942,0x6941,0x693e,0x693d,0x693a,0x6938,0x6936,
+ 0x6934,0x6933,0x6930,0x692f,0x692c,0x692a,0x6929,0x6926,0x6925,0x6922,0x6920,0x691f,0x691c,0x691b,0x6918,0x6917,
+ 0x6915,0x6912,0x6911,0x690e,0x690d,0x690a,0x6908,0x6907,0x6904,0x6903,0x6900,0x68ff,0x68fd,0x68fa,0x68f9,0x68f6,
+ 0x68f5,0x68f3,0x68f0,0x68ef,0x68ec,0x68eb,0x68e8,0x68e7,0x68e5,0x68e2,0x68e1,0x68de,0x68dd,0x68db,0x68d9,0x68d7,
+ 0x68d4,0x68d3,0x68d1,0x68cf,0x68cd,0x68ca,0x68c9,0x68c8,0x68c5,0x68c3,0x68c1,0x68bf,0x68bc,0x68bb,0x68b9,0x68b7,
+ 0x68b5,0x68b2,0x68b1,0x68b0,0x68ad,0x68ab,0x68a9,0x68a7,0x68a6,0x68a3,0x68a2,0x689f,0x689d,0x689a,0x6899,0x6898,
+ 0x6895,0x6894,0x6891,0x688f,0x688d,0x688b,0x688a,0x6887,0x6886,0x6883,0x6881,0x6880,0x687d,0x687c,0x6879,0x6878,
+ 0x6876,0x6873,0x6872,0x686f,0x686e,0x686b,0x6869,0x6868,0x6865,0x6864,0x6861,0x6860,0x685e,0x685b,0x685a,0x6857,
+ 0x6856,0x6854,0x6852,0x6850,0x684d,0x684c,0x684b,0x6848,0x6846,0x6844,0x6842,0x6841,0x683e,0x683c,0x683a,0x6838,
+ 0x6837,0x6834,0x6833,0x6830,0x682e,0x682c,0x682a,0x6829,0x6826,0x6825,0x6822,0x6820,0x681f,0x681c,0x681b,0x6818,
+ 0x6817,0x6815,0x6812,0x6811,0x680e,0x680d,0x680b,0x6808,0x6807,0x6804,0x6803,0x6801,0x67ff,0x67fd,0x67fa,0x67f9,
+ 0x67f8,0x67f5,0x67f3,0x67f1,0x67ef,0x67ec,0x67eb,0x67ea,0x67e7,0x67e5,0x67e2,0x67e1,0x67e0,0x67dd,0x67db,0x67d9,
+ 0x67d7,0x67d6,0x67d3,0x67d2,0x67cf,0x67cd,0x67cc,0x67c9,0x67c8,0x67c5,0x67c4,0x67c2,0x67bf,0x67be,0x67bb,0x67ba,
+ 0x67b8,0x67b5,0x67b4,0x67b1,0x67b0,0x67ad,0x67ac,0x67aa,0x67a7,0x67a6,0x67a3,0x67a2,0x67a0,0x679e,0x679c,0x6799,
+ 0x6797,0x6796,0x6793,0x6792,0x6790,0x678e,0x678c,0x6789,0x6788,0x6787,0x6784,0x6782,0x6780,0x677e,0x677d,0x677a,
+ 0x6779,0x6776,0x6774,0x6773,0x6770,0x676f,0x676c,0x676b,0x6769,0x6766,0x6765,0x6762,0x6761,0x675f,0x675d,0x675b,
+ 0x6758,0x6757,0x6756,0x6753,0x6751,0x674f,0x674d,0x674c,0x6749,0x6748,0x6745,0x6743,0x6742,0x673f,0x673e,0x673b,
+ 0x6739,0x6738,0x6735,0x6734,0x6731,0x6730,0x672e,0x672b,0x672a,0x6727,0x6726,0x6724,0x6722,0x6720,0x671d,0x671c,
+ 0x671b,0x6718,0x6716,0x6714,0x6712,0x670f,0x670e,0x670d,0x670a,0x6708,0x6706,0x6704,0x6703,0x6700,0x66ff,0x66fc,
+ 0x66fa,0x66f9,0x66f6,0x66f5,0x66f2,0x66f1,0x66ef,0x66ec,0x66eb,0x66e8,0x66e7,0x66e5,0x66e3,0x66e1,0x66de,0x66dd,
+ 0x66dc,0x66d9,0x66d7,0x66d5,0x66d3,0x66d2,0x66cf,0x66ce,0x66cb,0x66c9,0x66c8,0x66c5,0x66c4,0x66c1,0x66bf,0x66be,
+ 0x66bb,0x66ba,0x66b7,0x66b6,0x66b4,0x66b1,0x66b0,0x66ad,0x66ac,0x66aa,0x66a8,0x66a6,0x66a3,0x66a2,0x66a1,0x669e,
+ 0x669d,0x669a,0x6698,0x6696,0x6694,0x6693,0x6690,0x668f,0x668c,0x668a,0x6689,0x6686,0x6685,0x6682,0x6681,0x667f,
+ 0x667c,0x667b,0x6678,0x6677,0x6675,0x6673,0x6671,0x666e,0x666d,0x666c,0x6669,0x6667,0x6665,0x6663,0x6662,0x665f,
+ 0x665e,0x665b,0x665a,0x6658,0x6655,0x6654,0x6651,0x6650,0x664e,0x664c,0x664a,0x6647,0x6646,0x6645,0x6642,0x6640,
+ 0x663e,0x663c,0x663b,0x6638,0x6637,0x6634,0x6632,0x6631,0x662e,0x662d,0x662a,0x6629,0x6627,0x6624,0x6623,0x6620,
+ 0x661f,0x661d,0x661b,0x6619,0x6616,0x6615,0x6614,0x6611,0x660f,0x660d,0x660b,0x660a,0x6607,0x6606,0x6603,0x6601,
+ 0x6600,0x65fd,0x65fc,0x65f9,0x65f8,0x65f6,0x65f3,0x65f2,0x65ef,0x65ee,0x65ec,0x65ea,0x65e8,0x65e5,0x65e4,0x65e3,
+ 0x65e0,0x65de,0x65dc,0x65da,0x65d9,0x65d6,0x65d5,0x65d2,0x65d0,0x65cf,0x65cc,0x65cb,0x65c8,0x65c7,0x65c5,0x65c2,
+ 0x65c1,0x65be,0x65bd,0x65bb,0x65b9,0x65b7,0x65b4,0x65b3,0x65b2,0x65af,0x65ad,0x65ab,0x65a9,0x65a8,0x65a5,0x65a4,
+ 0x65a2,0x659f,0x659e,0x659c,0x6599,0x6598,0x6595,0x6594,0x6592,0x6590,0x658e,0x658b,0x658a,0x6589,0x6586,0x6584,
+ 0x6582,0x6580,0x657f,0x657c,0x657b,0x6578,0x6577,0x6575,0x6572,0x6571,0x656e,0x656d,0x656b,0x6569,0x6567,0x6566,
+ 0x6563,0x6562,0x655f,0x655d,0x655c,0x6559,0x6558,0x6555,0x6554,0x6552,0x654f,0x654e,0x654b,0x654a,0x6549,0x6546,
+ 0x6544,0x6542,0x6540,0x653f,0x653c,0x653b,0x6538,0x6536,0x6535,0x6532,0x6531,0x652e,0x652d,0x652b,0x6528,0x6527,
+ 0x6526,0x6523,0x6521,0x651f,0x651d,0x651c,0x6519,0x6518,0x6515,0x6514,0x6512,0x650f,0x650e,0x650b,0x650a,0x6508,
+ 0x6506,0x6504,0x6501,0x6500,0x64ff,0x64fc,0x64fa,0x64f8,0x64f6,0x64f5,0x64f2,0x64f1,0x64ee,0x64ec,0x64eb,0x64e8,
+ 0x64e7,0x64e4,0x64e3,0x64e1,0x64df,0x64dd,0x64dc,0x64d9,0x64d8,0x64d5,0x64d3,0x64d2,0x64cf,0x64ce,0x64cb,0x64ca,
+ 0x64c8,0x64c5,0x64c4,0x64c1,0x64c0,0x64be,0x64bc,0x64ba,0x64b7,0x64b6,0x64b5,0x64b2,0x64b1,0x64ae,0x64ac,0x64ab,
+ 0x64a8,0x64a7,0x64a4,0x64a3,0x64a0,0x649f,0x649d,0x649a,0x6499,0x6496,0x6495,0x6493,0x6491,0x648f,0x648e,0x648b,
+ 0x648a,0x6487,0x6486,0x6484,0x6481,0x6480,0x647d,0x647c,0x647a,0x6478,0x6476,0x6473,0x6472,0x6471,0x646e,0x646c,
+ 0x646b,0x6468,0x6467,0x6464,0x6463,0x6461,0x645f,0x645d,0x645a,0x6459,0x6458,0x6455,0x6453,0x6451,0x644f,0x644e,
+ 0x644b,0x644a,0x6447,0x6446,0x6444,0x6441,0x6440,0x643f,0x643c,0x643a,0x6438,0x6436,0x6435,0x6432,0x6431,0x642e,
+ 0x642d,0x642b,0x6428,0x6427,0x6424,0x6423,0x6421,0x641f,0x641d,0x641a,0x6419,0x6418,0x6415,0x6413,0x6412,0x640f,
+ 0x640e,0x640b,0x640a,0x6408,0x6406,0x6404,0x6401,0x6400,0x63ff,0x63fc,0x63fa,0x63f8,0x63f6,0x63f5,0x63f2,0x63f1,
+ 0x63ef,0x63ed,0x63eb,0x63e8,0x63e7,0x63e6,0x63e3,0x63e1,0x63df,0x63dd,0x63dc,0x63d9,0x63d8,0x63d5,0x63d4,0x63d2,
+ 0x63cf,0x63ce,0x63cb,0x63ca,0x63c8,0x63c6,0x63c4,0x63c3,0x63c0,0x63bf,0x63bc,0x63ba,0x63b9,0x63b6,0x63b5,0x63b2,
+ 0x63b0,0x63af,0x63ac,0x63ab,0x63a9,0x63a6,0x63a5,0x63a4,0x63a1,0x639f,0x639d,0x639b,0x639a,0x6397,0x6396,0x6393,
+ 0x6392,0x6390,0x638d,0x638c,0x638b,0x6388,0x6387,0x6384,0x6382,0x6381,0x637e,0x637d,0x637a,0x6379,0x6377,0x6374,
+ 0x6373,0x6370,0x636f,0x636e,0x636b,0x6369,0x6368,0x6365,0x6364,0x6361,0x6360,0x635e,0x635c,0x635a,0x6357,0x6356,
+ 0x6355,0x6352,0x6350,0x634f,0x634c,0x634b,0x6348,0x6347,0x6345,0x6343,0x6341,0x633e,0x633d,0x633c,0x6339,0x6337,
+ 0x6336,0x6333,0x6332,0x632f,0x632e,0x632c,0x632a,0x6328,0x6325,0x6324,0x6323,0x6320,0x631f,0x631c,0x631a,0x6319,
+ 0x6316,0x6315,0x6313,0x6311,0x630f,0x630c,0x630b,0x630a,0x6307,0x6306,0x6303,0x6301,0x6300,0x62fd,0x62fc,0x62fa,
+ 0x62f8,0x62f6,0x62f4,0x62f2,0x62f1,0x62ee,0x62ed,0x62ea,0x62e8,0x62e7,0x62e4,0x62e3,0x62e0,0x62df,0x62dd,0x62db,
+ 0x62d9,0x62d8,0x62d5,0x62d4,0x62d1,0x62cf,0x62ce,0x62cb,0x62ca,0x62c7,0x62c6,0x62c4,0x62c2,0x62c0,0x62bf,0x62bc,
+ 0x62bb,0x62b8,0x62b7,0x62b4,0x62b2,0x62b1,0x62ae,0x62ad,0x62aa,0x62a9,0x62a7,0x62a5,0x62a3,0x62a2,0x629f,0x629e,
+ 0x629b,0x6299,0x6298,0x6295,0x6294,0x6291,0x6290,0x628e,0x628c,0x628a,0x6289,0x6286,0x6285,0x6282,0x6281,0x627f,
+ 0x627c,0x627b,0x6278,0x6277,0x6276,0x6273,0x6271,0x6270,0x626d,0x626c,0x6269,0x6268,0x6266,0x6264,0x6262,0x6261,
+ 0x625e,0x625d,0x625a,0x6259,0x6257,0x6254,0x6253,0x6250,0x624f,0x624d,0x624b,0x6249,0x6248,0x6245,0x6244,0x6241,
+ 0x6240,0x623e,0x623b,0x623a,0x6237,0x6236,0x6235,0x6232,0x6230,0x622f,0x622c,0x622b,0x6228,0x6227,0x6225,0x6223,
+ 0x6221,0x621e,0x621d,0x621c,0x6219,0x6218,0x6216,0x6213,0x6212,0x620f,0x620e,0x620c,0x620a,0x6208,0x6207,0x6204,
+ 0x6203,0x6200,0x61ff,0x61fd,0x61fa,0x61f9,0x61f6,0x61f5,0x61f4,0x61f1,0x61ef,0x61ee,0x61eb,0x61ea,0x61e7,0x61e6,
+ 0x61e4,0x61e2,0x61e0,0x61dd,0x61dc,0x61db,0x61d8,0x61d7,0x61d5,0x61d2,0x61d1,0x61ce,0x61cd,0x61cb,0x61c9,0x61c7,
+ 0x61c5,0x61c2,0x61c1,0x61c0,0x61bd,0x61bc,0x61b9,0x61b7,0x61b6,0x61b3,0x61b2,0x61b1,0x61ae,0x61ac,0x61aa,0x61a8,
+ 0x61a7,0x61a4,0x61a3,0x61a1,0x619f,0x619d,0x619a,0x6199,0x6198,0x6195,0x6194,0x6192,0x618f,0x618e,0x618b,0x618a,
+ 0x6189,0x6186,0x6184,0x6182,0x6180,0x617f,0x617c,0x617b,0x6179,0x6177,0x6175,0x6172,0x6171,0x6170,0x616d,0x616c,
+ 0x616a,0x6167,0x6166,0x6163,0x6162,0x6161,0x615e,0x615c,0x615b,0x6158,0x6157,0x6154,0x6153,0x6151,0x614f,0x614d,
+ 0x614c,0x6149,0x6148,0x6145,0x6144,0x6142,0x613f,0x613e,0x613b,0x613a,0x6139,0x6136,0x6134,0x6133,0x6130,0x612f,
+ 0x612c,0x612b,0x6129,0x6127,0x6125,0x6124,0x6121,0x6120,0x611d,0x611c,0x611a,0x6117,0x6116,0x6115,0x6112,0x6111,
+ 0x610e,0x610c,0x610b,0x6108,0x6107,0x6104,0x6103,0x6101,0x60ff,0x60fd,0x60fc,0x60f9,0x60f8,0x60f5,0x60f4,0x60f2,
+ 0x60ef,0x60ee,0x60ed,0x60ea,0x60e9,0x60e6,0x60e4,0x60e3,0x60e0,0x60df,0x60de,0x60db,0x60d9,0x60d7,0x60d5,0x60d4,
+ 0x60d1,0x60d0,0x60cd,0x60cc,0x60ca,0x60c7,0x60c6,0x60c3,0x60c2,0x60c1,0x60be,0x60bc,0x60bb,0x60b8,0x60b7,0x60b4,
+ 0x60b3,0x60b1,0x60af,0x60ad,0x60ac,0x60a9,0x60a8,0x60a5,0x60a4,0x60a2,0x60a0,0x609e,0x609d,0x609a,0x6099,0x6096,
+ 0x6095,0x6093,0x6090,0x608f,0x608e,0x608b,0x608a,0x6087,0x6085,0x6084,0x6081,0x6080,0x607f,0x607c,0x607a,0x6078,
+ 0x6076,0x6075,0x6072,0x6071,0x606f,0x606d,0x606b,0x6069,0x6067,0x6066,0x6063,0x6062,0x6060,0x605e,0x605c,0x6059,
+ 0x6058,0x6057,0x6054,0x6053,0x6051,0x604e,0x604d,0x604a,0x6049,0x6048,0x6045,0x6043,0x6042,0x603f,0x603e,0x603b,
+ 0x603a,0x6038,0x6036,0x6034,0x6033,0x6030,0x602f,0x602c,0x602b,0x6029,0x6027,0x6025,0x6024,0x6021,0x6020,0x601d,
+ 0x601c,0x601a,0x6017,0x6016,0x6015,0x6012,0x6011,0x600e,0x600c,0x600b,0x6008,0x6007,0x6006,0x6003,0x6001,0x5fff,
+ 0x5ffd,0x5ffc,0x5ff9,0x5ff8,0x5ff6,0x5ff4,0x5ff2,0x5ff0,0x5fee,0x5fed,0x5fea,0x5fe9,0x5fe7,0x5fe5,0x5fe3,0x5fe0,
+ 0x5fde,0x5fdd,0x5fdb,0x5fd9,0x5fd7,0x5fd5,0x5fd3,0x5fd2,0x5fcf,0x5fce,0x5fcc,0x5fca,0x5fc8,0x5fc5,0x5fc4,0x5fc3,
+ 0x5fc0,0x5fbf,0x5fbd,0x5fba,0x5fb9,0x5fb6,0x5fb5,0x5fb4,0x5fb1,0x5fb0,0x5fae,0x5fab,0x5faa,0x5fa7,0x5fa6,0x5fa5,
+ 0x5fa2,0x5fa0,0x5f9f,0x5f9c,0x5f9b,0x5f9a,0x5f97,0x5f95,0x5f93,0x5f91,0x5f90,0x5f8d,0x5f8c,0x5f8a,0x5f88,0x5f86,
+ 0x5f84,0x5f82,0x5f81,0x5f7e,0x5f7d,0x5f7b,0x5f79,0x5f77,0x5f75,0x5f73,0x5f72,0x5f6f,0x5f6e,0x5f6c,0x5f6a,0x5f68,
+ 0x5f67,0x5f64,0x5f63,0x5f60,0x5f5f,0x5f5d,0x5f5a,0x5f59,0x5f58,0x5f55,0x5f54,0x5f51,0x5f50,0x5f4e,0x5f4b,0x5f4a,
+ 0x5f49,0x5f46,0x5f45,0x5f42,0x5f40,0x5f3f,0x5f3c,0x5f3b,0x5f3a,0x5f37,0x5f35,0x5f33,0x5f31,0x5f30,0x5f2d,0x5f2c,
+ 0x5f2b,0x5f28,0x5f26,0x5f25,0x5f22,0x5f21,0x5f1e,0x5f1d,0x5f1b,0x5f19,0x5f17,0x5f16,0x5f13,0x5f12,0x5f0f,0x5f0e,
+ 0x5f0c,0x5f0a,0x5f08,0x5f07,0x5f04,0x5f03,0x5f00,0x5eff,0x5efd,0x5efb,0x5ef9,0x5ef8,0x5ef5,0x5ef4,0x5ef1,0x5ef0,
+ 0x5eee,0x5eeb,0x5eea,0x5ee7,0x5ee6,0x5ee4,0x5ee2,0x5ee0,0x5edf,0x5edc,0x5edb,0x5ed8,0x5ed7,0x5ed5,0x5ed3,0x5ed1,
+ 0x5ed0,0x5ecd,0x5ecc,0x5eca,0x5ec8,0x5ec6,0x5ec4,0x5ec2,0x5ec1,0x5ebe,0x5ebd,0x5ebb,0x5eb9,0x5eb7,0x5eb4,0x5eb3,
+ 0x5eb2,0x5eaf,0x5eae,0x5eac,0x5eaa,0x5ea8,0x5ea7,0x5ea4,0x5ea3,0x5ea0,0x5e9f,0x5e9d,0x5e9a,0x5e99,0x5e98,0x5e95,
+ 0x5e94,0x5e92,0x5e90,0x5e8e,0x5e8b,0x5e8a,0x5e89,0x5e86,0x5e85,0x5e83,0x5e81,0x5e7f,0x5e7c,0x5e7b,0x5e7a,0x5e77,
+ 0x5e76,0x5e74,0x5e71,0x5e70,0x5e6f,0x5e6c,0x5e6b,0x5e68,0x5e67,0x5e65,0x5e62,0x5e61,0x5e60,0x5e5d,0x5e5c,0x5e59,
+ 0x5e58,0x5e56,0x5e53,0x5e52,0x5e51,0x5e4e,0x5e4d,0x5e4b,0x5e48,0x5e47,0x5e44,0x5e43,0x5e42,0x5e3f,0x5e3e,0x5e3c,
+ 0x5e39,0x5e38,0x5e37,0x5e34,0x5e33,0x5e30,0x5e2e,0x5e2d,0x5e2a,0x5e29,0x5e28,0x5e25,0x5e24,0x5e21,0x5e1f,0x5e1e,
+ 0x5e1b,0x5e1a,0x5e19,0x5e16,0x5e15,0x5e13,0x5e10,0x5e0f,0x5e0c,0x5e0b,0x5e0a,0x5e07,0x5e05,0x5e04,0x5e01,0x5e00,
+ 0x5dff,0x5dfc,0x5dfb,0x5df8,0x5df6,0x5df5,0x5df2,0x5df1,0x5df0,0x5ded,0x5deb,0x5de9,0x5de7,0x5de6,0x5de3,0x5de2,
+ 0x5de1,0x5dde,0x5ddc,0x5ddb,0x5dd8,0x5dd7,0x5dd4,0x5dd3,0x5dd2,0x5dcf,0x5dcd,0x5dcc,0x5dc9,0x5dc8,0x5dc5,0x5dc4,
+ 0x5dc2,0x5dc0,0x5dbe,0x5dbd,0x5dba,0x5db9,0x5db8,0x5db5,0x5db3,0x5db1,0x5daf,0x5dae,0x5dab,0x5daa,0x5da9,0x5da6,
+ 0x5da4,0x5da3,0x5da0,0x5d9f,0x5d9c,0x5d9b,0x5d99,0x5d97,0x5d95,0x5d94,0x5d91,0x5d90,0x5d8d,0x5d8c,0x5d8a,0x5d88,
+ 0x5d86,0x5d85,0x5d82,0x5d81,0x5d7f,0x5d7d,0x5d7b,0x5d79,0x5d77,0x5d76,0x5d73,0x5d72,0x5d70,0x5d6e,0x5d6c,0x5d6a,
+ 0x5d68,0x5d67,0x5d64,0x5d63,0x5d61,0x5d5f,0x5d5d,0x5d5c,0x5d59,0x5d58,0x5d55,0x5d54,0x5d52,0x5d50,0x5d4e,0x5d4d,
+ 0x5d4a,0x5d49,0x5d47,0x5d45,0x5d43,0x5d41,0x5d3f,0x5d3e,0x5d3b,0x5d3a,0x5d38,0x5d36,0x5d34,0x5d32,0x5d30,0x5d2f,
+ 0x5d2c,0x5d2b,0x5d29,0x5d27,0x5d25,0x5d24,0x5d21,0x5d20,0x5d1d,0x5d1c,0x5d1a,0x5d18,0x5d16,0x5d15,0x5d12,0x5d11,
+ 0x5d0f,0x5d0e,0x5d0c,0x5d0a,0x5d08,0x5d05,0x5d04,0x5d03,0x5d00,0x5cff,0x5cfd,0x5cfb,0x5cf9,0x5cf8,0x5cf5,0x5cf4,
+ 0x5cf1,0x5cf0,0x5cee,0x5cec,0x5cea,0x5ce9,0x5ce6,0x5ce5,0x5ce3,0x5ce1,0x5cdf,0x5cdd,0x5cdb,0x5cda,0x5cd7,0x5cd6,
+ 0x5cd4,0x5cd2,0x5cd0,0x5ccf,0x5ccc,0x5ccb,0x5cc8,0x5cc7,0x5cc5,0x5cc3,0x5cc1,0x5cc0,0x5cbd,0x5cbc,0x5cba,0x5cb8,
+ 0x5cb6,0x5cb4,0x5cb2,0x5cb1,0x5cae,0x5cad,0x5cab,0x5ca9,0x5ca7,0x5ca6,0x5ca3,0x5ca2,0x5c9f,0x5c9e,0x5c9c,0x5c9a,
+ 0x5c98,0x5c97,0x5c94,0x5c93,0x5c92,0x5c8f,0x5c8d,0x5c8b,0x5c89,0x5c88,0x5c85,0x5c84,0x5c83,0x5c80,0x5c7e,0x5c7d,
+ 0x5c7a,0x5c79,0x5c76,0x5c75,0x5c74,0x5c71,0x5c6f,0x5c6e,0x5c6b,0x5c6a,0x5c69,0x5c66,0x5c65,0x5c62,0x5c60,0x5c5f,
+ 0x5c5c,0x5c5b,0x5c5a,0x5c57,0x5c56,0x5c54,0x5c52,0x5c50,0x5c4d,0x5c4c,0x5c4b,0x5c48,0x5c47,0x5c45,0x5c43,0x5c41,
+ 0x5c40,0x5c3d,0x5c3c,0x5c39,0x5c38,0x5c36,0x5c34,0x5c32,0x5c31,0x5c2e,0x5c2d,0x5c2b,0x5c29,0x5c27,0x5c25,0x5c23,
+ 0x5c22,0x5c21,0x5c1e,0x5c1d,0x5c1b,0x5c18,0x5c17,0x5c14,0x5c13,0x5c12,0x5c0f,0x5c0e,0x5c0c,0x5c0a,0x5c08,0x5c07,
+ 0x5c04,0x5c03,0x5c01,0x5bff,0x5bfd,0x5bfb,0x5bf9,0x5bf8,0x5bf5,0x5bf4,0x5bf2,0x5bf0,0x5bee,0x5bed,0x5bea,0x5be9,
+ 0x5be8,0x5be5,0x5be3,0x5be1,0x5bdf,0x5bde,0x5bdb,0x5bda,0x5bd9,0x5bd6,0x5bd5,0x5bd3,0x5bd0,0x5bcf,0x5bcc,0x5bcb,
+ 0x5bca,0x5bc7,0x5bc6,0x5bc4,0x5bc1,0x5bc0,0x5bbf,0x5bbc,0x5bbb,0x5bb9,0x5bb7,0x5bb5,0x5bb3,0x5bb1,0x5bb0,0x5bad,
+ 0x5bac,0x5baa,0x5ba8,0x5ba6,0x5ba5,0x5ba2,0x5ba1,0x5b9e,0x5b9d,0x5b9b,0x5b99,0x5b97,0x5b96,0x5b93,0x5b92,0x5b91,
+ 0x5b8e,0x5b8c,0x5b8b,0x5b88,0x5b87,0x5b84,0x5b83,0x5b82,0x5b7f,0x5b7e,0x5b7c,0x5b79,0x5b78,0x5b77,0x5b74,0x5b73,
+ 0x5b71,0x5b6f,0x5b6d,0x5b6a,0x5b69,0x5b68,0x5b65,0x5b64,0x5b62,0x5b60,0x5b5e,0x5b5d,0x5b5a,0x5b59,0x5b56,0x5b55,
+ 0x5b53,0x5b51,0x5b4f,0x5b4e,0x5b4b,0x5b4a,0x5b48,0x5b46,0x5b44,0x5b43,0x5b40,0x5b3f,0x5b3c,0x5b3b,0x5b3a,0x5b37,
+ 0x5b36,0x5b34,0x5b32,0x5b31,0x5b2e,0x5b2d,0x5b2b,0x5b29,0x5b27,0x5b26,0x5b23,0x5b22,0x5b1f,0x5b1e,0x5b1c,0x5b1a,
+ 0x5b18,0x5b17,0x5b14,0x5b13,0x5b12,0x5b0f,0x5b0e,0x5b0c,0x5b09,0x5b08,0x5b07,0x5b04,0x5b03,0x5b00,0x5aff,0x5afd,
+ 0x5afb,0x5af9,0x5af8,0x5af5,0x5af4,0x5af2,0x5af0,0x5aee,0x5aed,0x5aea,0x5ae9,0x5ae6,0x5ae5,0x5ae4,0x5ae1,0x5adf,
+ 0x5ade,0x5adb,0x5ada,0x5ad9,0x5ad6,0x5ad5,0x5ad3,0x5ad1,0x5acf,0x5acc,0x5acb,0x5aca,0x5ac7,0x5ac6,0x5ac4,0x5ac2,
+ 0x5ac0,0x5abf,0x5abc,0x5abb,0x5aba,0x5ab7,0x5ab5,0x5ab4,0x5ab1,0x5ab0,0x5aad,0x5aac,0x5aab,0x5aa8,0x5aa7,0x5aa5,
+ 0x5aa2,0x5aa1,0x5aa0,0x5a9d,0x5a9c,0x5a9a,0x5a98,0x5a96,0x5a94,0x5a92,0x5a91,0x5a8e,0x5a8d,0x5a8b,0x5a89,0x5a87,
+ 0x5a86,0x5a83,0x5a82,0x5a81,0x5a7e,0x5a7d,0x5a7a,0x5a78,0x5a77,0x5a74,0x5a73,0x5a72,0x5a6f,0x5a6e,0x5a6c,0x5a6a,
+ 0x5a68,0x5a67,0x5a64,0x5a63,0x5a61,0x5a5f,0x5a5d,0x5a5b,0x5a59,0x5a58,0x5a55,0x5a54,0x5a53,0x5a50,0x5a4e,0x5a4d,
+ 0x5a4c,0x5a49,0x5a48,0x5a45,0x5a44,0x5a42,0x5a40,0x5a3e,0x5a3d,0x5a3a,0x5a39,0x5a37,0x5a35,0x5a33,0x5a32,0x5a2f,
+ 0x5a2e,0x5a2d,0x5a2a,0x5a29,0x5a26,0x5a24,0x5a23,0x5a20,0x5a1f,0x5a1e,0x5a1b,0x5a1a,0x5a18,0x5a16,0x5a14,0x5a13,
+ 0x5a10,0x5a0f,0x5a0e,0x5a0b,0x5a09,0x5a07,0x5a05,0x5a04,0x5a01,0x5a00,0x59ff,0x59fc,0x59fb,0x59f9,0x59f7,0x59f5,
+ 0x59f4,0x59f1,0x59f0,0x59ee,0x59ec,0x59ea,0x59e9,0x59e6,0x59e5,0x59e2,0x59e1,0x59e0,0x59dd,0x59dc,0x59da,0x59d7,
+ 0x59d6,0x59d5,0x59d2,0x59d1,0x59cf,0x59cd,0x59cb,0x59ca,0x59c7,0x59c6,0x59c3,0x59c2,0x59c0,0x59be,0x59bc,0x59bb,
+ 0x59b8,0x59b7,0x59b6,0x59b3,0x59b2,0x59b0,0x59ae,0x59ac,0x59ab,0x59a8,0x59a7,0x59a5,0x59a3,0x59a1,0x599f,0x599d,
+ 0x599c,0x5999,0x5998,0x5997,0x5994,0x5993,0x5991,0x598e,0x598d,0x598c,0x5989,0x5988,0x5986,0x5984,0x5982,0x5980,
+ 0x597e,0x597d,0x597a,0x5979,0x5977,0x5975,0x5973,0x5972,0x596f,0x596e,0x596d,0x596a,0x5969,0x5967,0x5965,0x5963,
+ 0x5961,0x5960,0x595e,0x595c,0x595a,0x5959,0x5956,0x5955,0x5952,0x5951,0x5950,0x594d,0x594b,0x594a,0x5947,0x5946,
+ 0x5945,0x5942,0x5941,0x593f,0x593d,0x593b,0x593a,0x5937,0x5936,0x5935,0x5932,0x5931,0x592f,0x592c,0x592b,0x5928,
+ 0x5927,0x5926,0x5923,0x5922,0x5920,0x591e,0x591c,0x591b,0x5918,0x5917,0x5916,0x5913,0x5912,0x5910,0x590d,0x590c,
+ 0x590b,0x5908,0x5907,0x5905,0x5903,0x5901,0x58ff,0x58fd,0x58fc,0x58f9,0x58f8,0x58f7,0x58f4,0x58f3,0x58f1,0x58ee,
+ 0x58ed,0x58ec,0x58e9,0x58e8,0x58e6,0x58e4,0x58e2,0x58e1,0x58de,0x58dd,0x58dc,0x58d9,0x58d8,0x58d5,0x58d4,0x58d2,
+ 0x58cf,0x58ce,0x58cd,0x58ca,0x58c9,0x58c7,0x58c5,0x58c3,0x58c2,0x58bf,0x58be,0x58bd,0x58ba,0x58b9,0x58b7,0x58b5,
+ 0x58b3,0x58b2,0x58af,0x58ae,0x58ab,0x58aa,0x58a8,0x58a6,0x58a4,0x58a3,0x58a0,0x589f,0x589e,0x589b,0x589a,0x5898,
+ 0x5896,0x5894,0x5893,0x5890,0x588f,0x588d,0x588b,0x5889,0x5888,0x5885,0x5884,0x5881,0x5880,0x587f,0x587c,0x587b,
+ 0x5879,0x5878,0x5875,0x5874,0x5872,0x5870,0x586e,0x586d,0x586a,0x5869,0x5867,0x5865,0x5863,0x5862,0x585f,0x585e,
+ 0x585d,0x585a,0x5859,0x5856,0x5855,0x5853,0x5851,0x584f,0x584e,0x584b,0x584a,0x5849,0x5846,0x5845,0x5843,0x5841,
+ 0x583f,0x583e,0x583b,0x583a,0x5838,0x5836,0x5834,0x5833,0x5830,0x582f,0x582e,0x582b,0x582a,0x5828,0x5826,0x5824,
+ 0x5823,0x5820,0x581f,0x581c,0x581b,0x581a,0x5817,0x5816,0x5814,0x5811,0x5810,0x580f,0x580c,0x580b,0x5809,0x5807,
+ 0x5805,0x5804,0x5801,0x5800,0x57ff,0x57fc,0x57fb,0x57f9,0x57f7,0x57f5,0x57f4,0x57f1,0x57f0,0x57ef,0x57ec,0x57eb,
+ 0x57e9,0x57e6,0x57e5,0x57e2,0x57e1,0x57e0,0x57dd,0x57dc,0x57da,0x57d8,0x57d6,0x57d5,0x57d2,0x57d1,0x57d0,0x57cd,
+ 0x57cc,0x57ca,0x57c8,0x57c6,0x57c5,0x57c2,0x57c1,0x57c0,0x57bd,0x57bb,0x57ba,0x57b7,0x57b6,0x57b5,0x57b2,0x57b1,
+ 0x57af,0x57ad,0x57ab,0x57a9,0x57a7,0x57a6,0x57a3,0x57a2,0x57a1,0x579e,0x579d,0x579b,0x5799,0x5797,0x5796,0x5793,
+ 0x5792,0x578f,0x578e,0x578d,0x578a,0x5789,0x5787,0x5785,0x5783,0x5782,0x577f,0x577e,0x577d,0x577a,0x5779,0x5777,
+ 0x5775,0x5773,0x5772,0x576f,0x576e,0x576d,0x576a,0x5769,0x5767,0x5764,0x5763,0x5762,0x575f,0x575e,0x575c,0x575a,
+ 0x5758,0x5757,0x5754,0x5753,0x5752,0x574f,0x574e,0x574b,0x574a,0x5748,0x5746,0x5744,0x5743,0x5740,0x573f,0x573e,
+ 0x573b,0x573a,0x5738,0x5736,0x5734,0x5733,0x5730,0x572f,0x572e,0x572b,0x572a,0x5728,0x5726,0x5724,0x5723,0x5720,
+ 0x571f,0x571d,0x571b,0x5719,0x5718,0x5715,0x5714,0x5713,0x5710,0x570f,0x570d,0x570b,0x5709,0x5708,0x5705,0x5704,
+ 0x5703,0x5700,0x56ff,0x56fd,0x56fb,0x56f9,0x56f8,0x56f5,0x56f4,0x56f3,0x56f0,0x56ef,0x56ec,0x56eb,0x56e9,0x56e7,
+ 0x56e5,0x56e4,0x56e1,0x56e0,0x56df,0x56dc,0x56da,0x56d9,0x56d6,0x56d5,0x56d4,0x56d1,0x56d0,0x56ce,0x56cc,0x56ca,
+ 0x56c9,0x56c6,0x56c5,0x56c4,0x56c1,0x56c0,0x56be,0x56bc,0x56ba,0x56b9,0x56b6,0x56b5,0x56b4,0x56b1,0x56b0,0x56ae,
+ 0x56ac,0x56aa,0x56a8,0x56a6,0x56a4,0x56a3,0x56a0,0x569f,0x569e,0x569b,0x569a,0x5698,0x5696,0x5694,0x5693,0x5690,
+ 0x568f,0x568e,0x568b,0x568a,0x5688,0x5686,0x5684,0x5683,0x5680,0x567f,0x567e,0x567b,0x567a,0x5678,0x5676,0x5674,
+ 0x5673,0x5670,0x566f,0x566e,0x566b,0x566a,0x5668,0x5666,0x5664,0x5663,0x5660,0x565f,0x565e,0x565b,0x565a,0x5658,
+ 0x5656,0x5654,0x5653,0x5650,0x564f,0x564d,0x564b,0x5649,0x5648,0x5645,0x5644,0x5643,0x5640,0x563f,0x563d,0x563b,
+ 0x5639,0x5638,0x5635,0x5634,0x5633,0x5630,0x562f,0x562d,0x562b,0x5629,0x5628,0x5625,0x5624,0x5623,0x5620,0x561f,
+ 0x561d,0x561b,0x5619,0x5618,0x5615,0x5614,0x5613,0x5610,0x560f,0x560d,0x560b,0x5609,0x5608,0x5605,0x5604,0x5603,
+ 0x5600,0x55ff,0x55fd,0x55fb,0x55f9,0x55f8,0x55f5,0x55f4,0x55f3,0x55f0,0x55ef,0x55ed,0x55eb,0x55e9,0x55e8,0x55e5,
+ 0x55e4,0x55e3,0x55e0,0x55df,0x55dd,0x55db,0x55d9,0x55d8,0x55d5,0x55d4,0x55d3,0x55d0,0x55cf,0x55cd,0x55cb,0x55c9,
+ 0x55c6,0x55c5,0x55c4,0x55c1,0x55c0,0x55be,0x55bc,0x55ba,0x55b9,0x55b6,0x55b5,0x55b4,0x55b1,0x55b0,0x55ae,0x55ac,
+ 0x55ab,0x55a9,0x55a7,0x55a5,0x55a4,0x55a1,0x55a0,0x559f,0x559c,0x559b,0x5599,0x5597,0x5595,0x5594,0x5591,0x5590,
+ 0x558f,0x558c,0x558b,0x5589,0x5587,0x5585,0x5584,0x5581,0x5580,0x557f,0x557c,0x557b,0x5579,0x5577,0x5575,0x5574,
+ 0x5571,0x5570,0x556f,0x556c,0x556b,0x5569,0x5567,0x5565,0x5564,0x5561,0x5560,0x555f,0x555c,0x555b,0x5559,0x5557,
+ 0x5555,0x5554,0x5551,0x5550,0x554f,0x554c,0x554b,0x5549,0x5547,0x5545,0x5544,0x5541,0x5540,0x553f,0x553c,0x553b,
+ 0x5539,0x5537,0x5535,0x5534,0x5531,0x5530,0x552f,0x552c,0x552b,0x5529,0x5527,0x5525,0x5524,0x5521,0x5520,0x551f,
+ 0x551c,0x551b,0x5519,0x5517,0x5515,0x5514,0x5511,0x5510,0x550f,0x550c,0x550b,0x5509,0x5507,0x5505,0x5504,0x5501,
+ 0x5500,0x54ff,0x54fc,0x54fb,0x54f9,0x54f7,0x54f5,0x54f4,0x54f1,0x54f0,0x54ef,0x54ec,0x54eb,0x54e9,0x54e7,0x54e5,
+ 0x54e3,0x54e2,0x54df,0x54de,0x54dc,0x54da,0x54d8,0x54d7,0x54d5,0x54d3,0x54d2,0x54cf,0x54ce,0x54cd,0x54ca,0x54c9,
+ 0x54c7,0x54c5,0x54c3,0x54c2,0x54bf,0x54be,0x54bd,0x54ba,0x54b9,0x54b7,0x54b5,0x54b3,0x54b2,0x54af,0x54ae,0x54ad,
+ 0x54ab,0x54a9,0x54a7,0x54a6,0x54a3,0x54a2,0x54a1,0x549e,0x549d,0x549b,0x5499,0x5497,0x5496,0x5493,0x5492,0x5491,
+ 0x548e,0x548d,0x548b,0x5489,0x5487,0x5486,0x5483,0x5482,0x5481,0x547e,0x547d,0x547c,0x5479,0x5478,0x5476,0x5474,
+ 0x5472,0x5471,0x546e,0x546d,0x546c,0x5469,0x5468,0x5466,0x5464,0x5462,0x5461,0x545e,0x545d,0x545c,0x5459,0x5458,
+ 0x5456,0x5454,0x5452,0x5451,0x544e,0x544d,0x544c,0x5449,0x5448,0x5446,0x5444,0x5442,0x5441,0x543e,0x543d,0x543c,
+ 0x543a,0x5438,0x5436,0x5435,0x5432,0x5431,0x5430,0x542d,0x542c,0x542b,0x5428,0x5427,0x5425,0x5423,0x5421,0x5420,
+ 0x541d,0x541c,0x541b,0x5418,0x5417,0x5415,0x5413,0x5411,0x5410,0x540d,0x540c,0x540b,0x5408,0x5407,0x5405,0x5403,
+ 0x5401,0x5400,0x53fd,0x53fc,0x53fb,0x53f8,0x53f7,0x53f5,0x53f3,0x53f1,0x53f0,0x53ed,0x53ec,0x53eb,0x53e8,0x53e7,
+ 0x53e5,0x53e3,0x53e1,0x53e0,0x53dd,0x53dc,0x53db,0x53d8,0x53d7,0x53d6,0x53d3,0x53d2,0x53d0,0x53ce,0x53cc,0x53cb,
+ 0x53ca,0x53c7,0x53c6,0x53c4,0x53c2,0x53c0,0x53bf,0x53bc,0x53bb,0x53ba,0x53b7,0x53b6,0x53b4,0x53b2,0x53b0,0x53af,
+ 0x53ac,0x53ab,0x53aa,0x53a7,0x53a6,0x53a4,0x53a2,0x53a0,0x539f,0x539c,0x539b,0x539a,0x5397,0x5396,0x5394,0x5392,
+ 0x5390,0x538f,0x538c,0x538b,0x538a,0x5387,0x5386,0x5384,0x5382,0x5381,0x537f,0x537d,0x537b,0x537a,0x5377,0x5376,
+ 0x5375,0x5372,0x5371,0x536f,0x536d,0x536b,0x536a,0x5367,0x5366,0x5365,0x5362,0x5361,0x535f,0x535d,0x535b,0x535a,
+ 0x5359,0x5356,0x5355,0x5353,0x5351,0x534f,0x534e,0x534b,0x534a,0x5349,0x5346,0x5345,0x5343,0x5341,0x533f,0x533e,
+ 0x533b,0x533a,0x5339,0x5336,0x5335,0x5333,0x5331,0x532f,0x532e,0x532c,0x532a,0x5329,0x5326,0x5325,0x5324,0x5321,
+ 0x5320,0x531e,0x531d,0x531a,0x5319,0x5318,0x5315,0x5314,0x5313,0x5310,0x530f,0x530d,0x530b,0x5309,0x5308,0x5305,
+ 0x5304,0x5303,0x5300,0x52ff,0x52fd,0x52fb,0x52f9,0x52f8,0x52f5,0x52f4,0x52f3,0x52f0,0x52ef,0x52ed,0x52ec,0x52e9,
+ 0x52e8,0x52e7,0x52e4,0x52e3,0x52e2,0x52df,0x52de,0x52dc,0x52da,0x52d8,0x52d7,0x52d4,0x52d3,0x52d2,0x52cf,0x52ce,
+ 0x52cc,0x52ca,0x52c8,0x52c7,0x52c4,0x52c3,0x52c2,0x52bf,0x52be,0x52bc,0x52ba,0x52b8,0x52b7,0x52b5,0x52b3,0x52b2,
+ 0x52b1,0x52ae,0x52ad,0x52ab,0x52a9,0x52a7,0x52a6,0x52a3,0x52a2,0x52a1,0x529e,0x529d,0x529b,0x5299,0x5297,0x5296,
+ 0x5293,0x5292,0x5291,0x528e,0x528d,0x528b,0x5289,0x5287,0x5286,0x5284,0x5282,0x5281,0x527e,0x527d,0x527c,0x5279,
+ 0x5278,0x5276,0x5274,0x5272,0x5271,0x5270,0x526d,0x526c,0x526a,0x5268,0x5266,0x5265,0x5262,0x5261,0x5260,0x525d,
+ 0x525c,0x525a,0x5258,0x5257,0x5255,0x5253,0x5251,0x5250,0x524d,0x524c,0x524b,0x5248,0x5247,0x5245,0x5243,0x5241,
+ 0x5241,0x523e,0x523d,0x523b,0x5239,0x5237,0x5236,0x5233,0x5232,0x5231,0x522e,0x522d,0x522c,0x5229,0x5228,0x5226,
+ 0x5224,0x5222,0x5221,0x521e,0x521d,0x521c,0x5219,0x5218,0x5216,0x5214,0x5212,0x5211,0x5210,0x520d,0x520c,0x520b,
+ 0x5208,0x5207,0x5205,0x5203,0x5201,0x5200,0x51fd,0x51fc,0x51fb,0x51f8,0x51f7,0x51f5,0x51f3,0x51f1,0x51f0,0x51ee,
+ 0x51ec,0x51eb,0x51e8,0x51e7,0x51e6,0x51e4,0x51e2,0x51e0,0x51df,0x51dc,0x51db,0x51da,0x51d7,0x51d6,0x51d4,0x51d2,
+ 0x51d0,0x51cf,0x51cd,0x51cb,0x51ca,0x51c7,0x51c6,0x51c5,0x51c2,0x51c1,0x51bf,0x51bd,0x51bb,0x51ba,0x51b9,0x51b6,
+ 0x51b5,0x51b3,0x51b1,0x51af,0x51ae,0x51ac,0x51aa,0x51a9,0x51a6,0x51a5,0x51a4,0x51a1,0x51a0,0x519e,0x519c,0x519a,
+ 0x5199,0x5196,0x5195,0x5194,0x5191,0x5190,0x518e,0x518d,0x518a,0x5189,0x5188,0x5185,0x5184,0x5183,0x5180,0x517f,
+ 0x517d,0x517b,0x5179,0x5178,0x5175,0x5174,0x5173,0x5170,0x516f,0x516d,0x516b,0x5169,0x5168,0x5166,0x5164,0x5163,
+ 0x5161,0x515f,0x515d,0x515c,0x515a,0x5158,0x5157,0x5156,0x5153,0x5152,0x5150,0x514e,0x514c,0x514b,0x5148,0x5147,
+ 0x5146,0x5143,0x5142,0x5141,0x513e,0x513d,0x513b,0x5139,0x5137,0x5136,0x5135,0x5132,0x5131,0x512f,0x512d,0x512b,
+ 0x512a,0x5127,0x5126,0x5125,0x5122,0x5121,0x5120,0x511d,0x511c,0x511a,0x5118,0x5116,0x5115,0x5114,0x5111,0x5110,
+ 0x510e,0x510c,0x510b,0x5109,0x5107,0x5105,0x5104,0x5101,0x5100,0x50ff,0x50fc,0x50fb,0x50f9,0x50f7,0x50f5,0x50f4,
+ 0x50f3,0x50f0,0x50ef,0x50ee,0x50eb,0x50ea,0x50e8,0x50e6,0x50e4,0x50e3,0x50e0,0x50df,0x50de,0x50db,0x50da,0x50d9,
+ 0x50d6,0x50d5,0x50d3,0x50d1,0x50cf,0x50ce,0x50cd,0x50ca,0x50c9,0x50c7,0x50c5,0x50c3,0x50c2,0x50bf,0x50be,0x50bd,
+ 0x50ba,0x50b9,0x50b8,0x50b5,0x50b4,0x50b2,0x50b0,0x50ae,0x50ad,0x50ac,0x50a9,0x50a8,0x50a6,0x50a4,0x50a3,0x50a1,
+ 0x509f,0x509d,0x509c,0x5099,0x5098,0x5097,0x5094,0x5093,0x5091,0x508f,0x508d,0x508c,0x508b,0x5088,0x5087,0x5086,
+ 0x5083,0x5082,0x507f,0x507e,0x507d,0x507a,0x5079,0x5077,0x5076,0x5074,0x5072,0x5071,0x506e,0x506d,0x506c,0x5069,
+ 0x5068,0x5066,0x5064,0x5062,0x5061,0x505f,0x505d,0x505c,0x505b,0x5058,0x5057,0x5055,0x5053,0x5051,0x5050,0x504d,
+ 0x504c,0x504b,0x5048,0x5047,0x5046,0x5043,0x5042,0x5040,0x503f,0x503c,0x503b,0x503a,0x5037,0x5036,0x5035,0x5032,
+ 0x5031,0x502f,0x502d,0x502b,0x502a,0x5027,0x5026,0x5025,0x5023,0x5021,0x5020,0x501e,0x501c,0x501a,0x5019,0x5016,
+ 0x5015,0x5014,0x5011,0x5010,0x500e,0x500c,0x500b,0x5009,0x5008,0x5005,0x5004,0x5003,0x5000,0x4fff,0x4ffd,0x4ffb,
+ 0x4ff9,0x4ff8,0x4ff6,0x4ff4,0x4ff3,0x4ff0,0x4fef,0x4fee,0x4fec,0x4fea,0x4fe8,0x4fe7,0x4fe4,0x4fe3,0x4fe2,0x4fdf,
+ 0x4fde,0x4fdd,0x4fda,0x4fd9,0x4fd7,0x4fd5,0x4fd3,0x4fd2,0x4fd1,0x4fce,0x4fcd,0x4fcc,0x4fc9,0x4fc8,0x4fc6,0x4fc4,
+ 0x4fc2,0x4fc1,0x4fbe,0x4fbd,0x4fbc,0x4fb9,0x4fb8,0x4fb7,0x4fb5,0x4fb3,0x4fb1,0x4fb0,0x4fad,0x4fac,0x4fab,0x4fa8,
+ 0x4fa6,0x4fa5,0x4fa4,0x4fa1,0x4fa0,0x4f9e,0x4f9c,0x4f9a,0x4f99,0x4f96,0x4f95,0x4f94,0x4f93,0x4f90,0x4f8f,0x4f8d,
+ 0x4f8b,0x4f89,0x4f88,0x4f85,0x4f84,0x4f83,0x4f80,0x4f7f,0x4f7e,0x4f7c,0x4f7a,0x4f78,0x4f77,0x4f74,0x4f73,0x4f72,
+ 0x4f6f,0x4f6e,0x4f6d,0x4f6a,0x4f69,0x4f67,0x4f66,0x4f63,0x4f62,0x4f61,0x4f5e,0x4f5d,0x4f5c,0x4f59,0x4f58,0x4f56,
+ 0x4f54,0x4f52,0x4f51,0x4f50,0x4f4d,0x4f4c,0x4f4b,0x4f48,0x4f47,0x4f45,0x4f43,0x4f41,0x4f40,0x4f3e,0x4f3c,0x4f3b,
+ 0x4f3a,0x4f37,0x4f36,0x4f34,0x4f32,0x4f30,0x4f2f,0x4f2c,0x4f2b,0x4f2a,0x4f27,0x4f26,0x4f25,0x4f22,0x4f21,0x4f1f,
+ 0x4f1e,0x4f1b,0x4f1a,0x4f19,0x4f16,0x4f15,0x4f14,0x4f11,0x4f10,0x4f0e,0x4f0c,0x4f0a,0x4f09,0x4f08,0x4f05,0x4f04,
+ 0x4f03,0x4f00,0x4eff,0x4efd,0x4efb,0x4ef9,0x4ef8,0x4ef6,0x4ef4,0x4ef3,0x4ef2,0x4eef,0x4eee,0x4eec,0x4eea,0x4ee8,
+ 0x4ee7,0x4ee5,0x4ee3,0x4ee2,0x4edf,0x4ede,0x4edd,0x4edb,0x4ed9,0x4ed7,0x4ed6,0x4ed4,0x4ed2,0x4ed1,0x4ece,0x4ecd,
+ 0x4ecc,0x4ec9,0x4ec8,0x4ec6,0x4ec4,0x4ec2,0x4ec1,0x4ebe,0x4ebd,0x4ebc,0x4eb9,0x4eb8,0x4eb7,0x4eb5,0x4eb3,0x4eb1,
+ 0x4eb0,0x4eae,0x4eac,0x4eab,0x4ea8,0x4ea7,0x4ea6,0x4ea3,0x4ea2,0x4ea0,0x4e9f,0x4e9d,0x4e9b,0x4e9a,0x4e97,0x4e96,
+ 0x4e95,0x4e92,0x4e91,0x4e90,0x4e8e,0x4e8c,0x4e8a,0x4e89,0x4e86,0x4e85,0x4e84,0x4e81,0x4e80,0x4e7f,0x4e7c,0x4e7b,
+ 0x4e79,0x4e78,0x4e75,0x4e74,0x4e73,0x4e70,0x4e6f,0x4e6e,0x4e6b,0x4e6a,0x4e68,0x4e67,0x4e64,0x4e63,0x4e62,0x4e5f,
+ 0x4e5e,0x4e5d,0x4e5a,0x4e59,0x4e57,0x4e55,0x4e54,0x4e52,0x4e51,0x4e4e,0x4e4d,0x4e4c,0x4e49,0x4e48,0x4e46,0x4e44,
+ 0x4e43,0x4e41,0x4e40,0x4e3d,0x4e3c,0x4e3b,0x4e38,0x4e37,0x4e35,0x4e33,0x4e32,0x4e30,0x4e2e,0x4e2c,0x4e2b,0x4e2a,
+ 0x4e27,0x4e26,0x4e25,0x4e22,0x4e21,0x4e1f,0x4e1d,0x4e1b,0x4e1a,0x4e19,0x4e16,0x4e15,0x4e14,0x4e11,0x4e10,0x4e0e,
+ 0x4e0c,0x4e0a,0x4e09,0x4e07,0x4e05,0x4e04,0x4e03,0x4e00,0x4dff,0x4dfd,0x4dfb,0x4df9,0x4df8,0x4df6,0x4df4,0x4df3,
+ 0x4df2,0x4def,0x4dee,0x4dec,0x4dea,0x4de9,0x4de7,0x4de5,0x4de3,0x4de2,0x4ddf,0x4dde,0x4ddd,0x4ddb,0x4dd9,0x4dd8,
+ 0x4dd6,0x4dd4,0x4dd2,0x4dd1,0x4dce,0x4dcd,0x4dcc,0x4dc9,0x4dc8,0x4dc7,0x4dc5,0x4dc3,0x4dc1,0x4dc0,0x4dbd,0x4dbc,
+ 0x4dbb,0x4db8,0x4db7,0x4db6,0x4db4,0x4db2,0x4db0,0x4daf,0x4dad,0x4dab,0x4daa,0x4da7,0x4da6,0x4da5,0x4da2,0x4da1,
+ 0x4d9f,0x4d9e,0x4d9c,0x4d9a,0x4d99,0x4d96,0x4d95,0x4d94,0x4d91,0x4d90,0x4d8e,0x4d8d,0x4d8b,0x4d89,0x4d88,0x4d85,
+ 0x4d84,0x4d83,0x4d80,0x4d7f,0x4d7e,0x4d7b,0x4d7a,0x4d78,0x4d77,0x4d74,0x4d73,0x4d72,0x4d6f,0x4d6e,0x4d6d,0x4d6a,
+ 0x4d69,0x4d67,0x4d66,0x4d63,0x4d62,0x4d61,0x4d5e,0x4d5d,0x4d5c,0x4d59,0x4d58,0x4d56,0x4d54,0x4d52,0x4d51,0x4d50,
+ 0x4d4d,0x4d4c,0x4d4b,0x4d48,0x4d47,0x4d45,0x4d43,0x4d42,0x4d40,0x4d3f,0x4d3c,0x4d3b,0x4d3a,0x4d37,0x4d36,0x4d34,
+ 0x4d32,0x4d31,0x4d2f,0x4d2d,0x4d2b,0x4d2a,0x4d29,0x4d26,0x4d25,0x4d24,0x4d21,0x4d20,0x4d1e,0x4d1c,0x4d1a,0x4d19,
+ 0x4d17,0x4d16,0x4d15,0x4d12,0x4d11,0x4d10,0x4d0d,0x4d0c,0x4d0a,0x4d09,0x4d07,0x4d05,0x4d04,0x4d01,0x4d00,0x4cff,
+ 0x4cfc,0x4cfb,0x4cf9,0x4cf8,0x4cf6,0x4cf4,0x4cf3,0x4cf0,0x4cef,0x4cee,0x4ceb,0x4cea,0x4ce9,0x4ce7,0x4ce5,0x4ce3,
+ 0x4ce2,0x4cdf,0x4cde,0x4cdd,0x4cda,0x4cd9,0x4cd8,0x4cd6,0x4cd4,0x4cd2,0x4cd1,0x4ccf,0x4ccd,0x4ccc,0x4cc9,0x4cc8,
+ 0x4cc7,0x4cc5,0x4cc3,0x4cc2,0x4cc0,0x4cbe,0x4cbc,0x4cbb,0x4cb8,0x4cb7,0x4cb6,0x4cb5,0x4cb2,0x4cb1,0x4caf,0x4cad,
+ 0x4cab,0x4caa,0x4ca8,0x4ca6,0x4ca5,0x4ca2,0x4ca1,0x4ca0,0x4c9e,0x4c9c,0x4c9b,0x4c99,0x4c97,0x4c95,0x4c94,0x4c91,
+ 0x4c90,0x4c8f,0x4c8e,0x4c8b,0x4c8a,0x4c88,0x4c86,0x4c84,0x4c83,0x4c81,0x4c7f,0x4c7e,0x4c7d,0x4c7a,0x4c79,0x4c77,
+ 0x4c75,0x4c74,0x4c72,0x4c70,0x4c6e,0x4c6d,0x4c6c,0x4c69,0x4c68,0x4c67,0x4c64,0x4c63,0x4c61,0x4c5f,0x4c5d,0x4c5c,
+ 0x4c5b,0x4c58,0x4c57,0x4c56,0x4c53,0x4c52,0x4c50,0x4c4e,0x4c4c,0x4c4b,0x4c4a,0x4c47,0x4c46,0x4c45,0x4c42,0x4c41,
+ 0x4c40,0x4c3e,0x4c3c,0x4c3a,0x4c39,0x4c38,0x4c35,0x4c34,0x4c33,0x4c30,0x4c2f,0x4c2d,0x4c2b,0x4c2a,0x4c28,0x4c27,
+ 0x4c24,0x4c23,0x4c22,0x4c1f,0x4c1e,0x4c1d,0x4c1a,0x4c19,0x4c17,0x4c16,0x4c13,0x4c12,0x4c11,0x4c0e,0x4c0d,0x4c0c,
+ 0x4c0a,0x4c08,0x4c06,0x4c05,0x4c03,0x4c01,0x4c00,0x4bfd,0x4bfc,0x4bfb,0x4bfa,0x4bf7,0x4bf6,0x4bf4,0x4bf2,0x4bf0,
+ 0x4bef,0x4bed,0x4beb,0x4bea,0x4be9,0x4be6,0x4be5,0x4be3,0x4be1,0x4be0,0x4bde,0x4bdc,0x4bda,0x4bd9,0x4bd8,0x4bd5,
+ 0x4bd4,0x4bd3,0x4bd0,0x4bcf,0x4bcd,0x4bcc,0x4bca,0x4bc8,0x4bc7,0x4bc4,0x4bc3,0x4bc2,0x4bbf,0x4bbe,0x4bbd,0x4bbb,
+ 0x4bb9,0x4bb7,0x4bb6,0x4bb3,0x4bb2,0x4bb1,0x4bae,0x4bad,0x4bac,0x4baa,0x4ba8,0x4ba7,0x4ba5,0x4ba3,0x4ba1,0x4ba0,
+ 0x4b9f,0x4b9c,0x4b9b,0x4b9a,0x4b97,0x4b96,0x4b94,0x4b92,0x4b90,0x4b8f,0x4b8e,0x4b8b,0x4b8a,0x4b89,0x4b86,0x4b85,
+ 0x4b84,0x4b81,0x4b80,0x4b7e,0x4b7d,0x4b7a,0x4b79,0x4b78,0x4b75,0x4b74,0x4b73,0x4b70,0x4b6f,0x4b6d,0x4b6c,0x4b6a,
+ 0x4b69,0x4b66,0x4b65,0x4b64,0x4b62,0x4b60,0x4b5e,0x4b5d,0x4b5b,0x4b59,0x4b58,0x4b57,0x4b54,0x4b53,0x4b51,0x4b4f,
+ 0x4b4e,0x4b4c,0x4b4a,0x4b48,0x4b47,0x4b46,0x4b43,0x4b42,0x4b41,0x4b3e,0x4b3d,0x4b3b,0x4b3a,0x4b38,0x4b36,0x4b35,
+ 0x4b32,0x4b31,0x4b30,0x4b2d,0x4b2c,0x4b2b,0x4b29,0x4b27,0x4b25,0x4b24,0x4b22,0x4b20,0x4b1f,0x4b1e,0x4b1b,0x4b1a,
+ 0x4b19,0x4b16,0x4b15,0x4b13,0x4b12,0x4b10,0x4b0e,0x4b0d,0x4b0a,0x4b09,0x4b08,0x4b05,0x4b04,0x4b03,0x4b01,0x4aff,
+ 0x4afd,0x4afc,0x4afa,0x4af8,0x4af7,0x4af6,0x4af3,0x4af2,0x4af0,0x4aee,0x4aed,0x4aeb,0x4ae9,0x4ae7,0x4ae6,0x4ae5,
+ 0x4ae2,0x4ae1,0x4ae0,0x4add,0x4adc,0x4adb,0x4ad9,0x4ad7,0x4ad5,0x4ad4,0x4ad1,0x4ad0,0x4acf,0x4ace,0x4acb,0x4aca,
+ 0x4ac8,0x4ac6,0x4ac5,0x4ac3,0x4ac1,0x4abf,0x4abe,0x4abd,0x4aba,0x4ab9,0x4ab8,0x4ab5,0x4ab4,0x4ab2,0x4ab1,0x4aaf,
+ 0x4aad,0x4aac,0x4aa9,0x4aa8,0x4aa7,0x4aa4,0x4aa3,0x4aa2,0x4aa0,0x4a9e,0x4a9c,0x4a9b,0x4a99,0x4a97,0x4a96,0x4a95,
+ 0x4a93,0x4a90,0x4a8f,0x4a8e,0x4a8b,0x4a8a,0x4a89,0x4a86,0x4a85,0x4a83,0x4a82,0x4a80,0x4a7e,0x4a7d,0x4a7a,0x4a79,
+ 0x4a78,0x4a77,0x4a74,0x4a73,0x4a71,0x4a6f,0x4a6e,0x4a6c,0x4a6b,0x4a68,0x4a67,0x4a66,0x4a63,0x4a62,0x4a61,0x4a5f,
+ 0x4a5d,0x4a5c,0x4a5a,0x4a58,0x4a56,0x4a55,0x4a54,0x4a51,0x4a50,0x4a4f,0x4a4c,0x4a4b,0x4a49,0x4a47,0x4a46,0x4a44,
+ 0x4a43,0x4a40,0x4a3f,0x4a3e,0x4a3b,0x4a3a,0x4a39,0x4a37,0x4a35,0x4a34,0x4a32,0x4a30,0x4a2e,0x4a2d,0x4a2c,0x4a29,
+ 0x4a28,0x4a27,0x4a24,0x4a23,0x4a22,0x4a20,0x4a1e,0x4a1c,0x4a1b,0x4a18,0x4a17,0x4a16,0x4a15,0x4a12,0x4a11,0x4a0f,
+ 0x4a0d,0x4a0c,0x4a0a,0x4a09,0x4a06,0x4a05,0x4a04,0x4a01,0x4a00,0x49ff,0x49fc,0x49fb,0x49fa,0x49f8,0x49f6,0x49f4,
+ 0x49f3,0x49f1,0x49ef,0x49ee,0x49ed,0x49ea,0x49e9,0x49e8,0x49e5,0x49e4,0x49e2,0x49e1,0x49de,0x49dd,0x49dc,0x49d9,
+ 0x49d8,0x49d7,0x49d5,0x49d3,0x49d2,0x49d0,0x49ce,0x49cc,0x49cb,0x49ca,0x49c7,0x49c6,0x49c5,0x49c2,0x49c1,0x49c0,
+ 0x49bd,0x49bc,0x49ba,0x49b8,0x49b6,0x49b5,0x49b4,0x49b1,0x49b0,0x49af,0x49ac,0x49ab,0x49aa,0x49a8,0x49a6,0x49a5,
+ 0x49a3,0x49a1,0x499f,0x499e,0x499d,0x499a,0x4999,0x4998,0x4995,0x4994,0x4993,0x4991,0x498f,0x498d,0x498c,0x498a,
+ 0x4988,0x4987,0x4986,0x4983,0x4982,0x4981,0x497e,0x497d,0x497b,0x497a,0x4978,0x4976,0x4975,0x4972,0x4971,0x4970,
+ 0x496f,0x496c,0x496b,0x4969,0x4967,0x4966,0x4964,0x4963,0x4960,0x495f,0x495e,0x495b,0x495a,0x4959,0x4957,0x4955,
+ 0x4954,0x4952,0x4950,0x494e,0x494d,0x494c,0x4949,0x4948,0x4947,0x4944,0x4943,0x4942,0x4940,0x493e,0x493c,0x493b,
+ 0x4939,0x4937,0x4936,0x4935,0x4932,0x4931,0x4930,0x492d,0x492c,0x492a,0x4929,0x4927,0x4925,0x4924,0x4921,0x4920,
+ 0x491f,0x491e,0x491b,0x491a,0x4918,0x4916,0x4915,0x4913,0x4912,0x490f,0x490e,0x490d,0x490a,0x4909,0x4908,0x4906,
+ 0x4904,0x4903,0x4901,0x48ff,0x48fd,0x48fc,0x48fb,0x48f8,0x48f7,0x48f6,0x48f3,0x48f2,0x48f1,0x48ef,0x48ed,0x48eb,
+ 0x48ea,0x48e8,0x48e6,0x48e5,0x48e4,0x48e1,0x48e0,0x48df,0x48dc,0x48db,0x48d9,0x48d8,0x48d6,0x48d4,0x48d3,0x48d0,
+ 0x48cf,0x48ce,0x48cd,0x48ca,0x48c9,0x48c7,0x48c5,0x48c4,0x48c2,0x48c1,0x48be,0x48bd,0x48bc,0x48b9,0x48b8,0x48b7,
+ 0x48b5,0x48b3,0x48b2,0x48b0,0x48ae,0x48ac,0x48ab,0x48aa,0x48a7,0x48a6,0x48a5,0x48a2,0x48a1,0x48a0,0x489e,0x489c,
+ 0x489a,0x4899,0x4897,0x4895,0x4894,0x4893,0x4890,0x488f,0x488e,0x488b,0x488a,0x4888,0x4887,0x4885,0x4883,0x4882,
+ 0x4881,0x487e,0x487d,0x487c,0x4879,0x4878,0x4876,0x4875,0x4873,0x4871,0x4870,0x486d,0x486c,0x486b,0x486a,0x4867,
+ 0x4866,0x4864,0x4862,0x4861,0x485f,0x485e,0x485c,0x485a,0x4859,0x4856,0x4855,0x4854,0x4853,0x4850,0x484f,0x484d,
+ 0x484b,0x484a,0x4848,0x4847,0x4844,0x4843,0x4842,0x483f,0x483e,0x483d,0x483b,0x4839,0x4838,0x4836,0x4834,0x4832,
+ 0x4831,0x4830,0x482d,0x482c,0x482b,0x4828,0x4827,0x4826,0x4824,0x4822,0x4820,0x481f,0x481d,0x481b,0x481a,0x4819,
+ 0x4817,0x4816,0x4813,0x4812,0x4811,0x480f,0x480d,0x480c,0x480a,0x4808,0x4806,0x4805,0x4804,0x4801,0x4800,0x47ff,
+ 0x47fd,0x47fb,0x47fa,0x47f8,0x47f6,0x47f4,0x47f3,0x47f2,0x47ef,0x47ee,0x47ed,0x47ea,0x47e9,0x47e8,0x47e6,0x47e4,
+ 0x47e3,0x47e1,0x47df,0x47dd,0x47dc,0x47db,0x47d8,0x47d7,0x47d6,0x47d3,0x47d2,0x47d1,0x47cf,0x47cd,0x47cb,0x47ca,
+ 0x47c9,0x47c6,0x47c5,0x47c4,0x47c1,0x47c0,0x47bf,0x47bd,0x47bb,0x47ba,0x47b8,0x47b6,0x47b4,0x47b3,0x47b2,0x47af,
+ 0x47ae,0x47ad,0x47aa,0x47a9,0x47a8,0x47a6,0x47a4,0x47a2,0x47a1,0x479f,0x479d,0x479c,0x479b,0x4798,0x4797,0x4796,
+ 0x4794,0x4792,0x4791,0x478f,0x478d,0x478b,0x478a,0x4789,0x4786,0x4785,0x4784,0x4781,0x4780,0x477f,0x477d,0x477b,
+ 0x4779,0x4778,0x4776,0x4774,0x4773,0x4772,0x476f,0x476e,0x476d,0x476a,0x4769,0x4768,0x4766,0x4764,0x4762,0x4761,
+ 0x4760,0x475d,0x475c,0x475b,0x4758,0x4757,0x4756,0x4754,0x4752,0x4750,0x474f,0x474d,0x474b,0x474a,0x4749,0x4746,
+ 0x4745,0x4744,0x4742,0x4740,0x473f,0x473d,0x473c,0x4739,0x4738,0x4737,0x4734,0x4733,0x4732,0x4731,0x472e,0x472d,
+ 0x472b,0x472a,0x4728,0x4726,0x4725,0x4722,0x4721,0x4720,0x471f,0x471c,0x471b,0x471a,0x4717,0x4716,0x4714,0x4713,
+ 0x4711,0x470f,0x470e,0x470d,0x470a,0x4709,0x4708,0x4705,0x4704,0x4703,0x4701,0x46ff,0x46fd,0x46fc,0x46fa,0x46f8,
+ 0x46f7,0x46f6,0x46f3,0x46f2,0x46f1,0x46ef,0x46ed,0x46ec,0x46ea,0x46e8,0x46e6,0x46e5,0x46e4,0x46e1,0x46e0,0x46df,
+ 0x46de,0x46db,0x46da,0x46d8,0x46d6,0x46d5,0x46d3,0x46d2,0x46cf,0x46ce,0x46cd,0x46ca,0x46c9,0x46c8,0x46c7,0x46c4,
+ 0x46c3,0x46c1,0x46c0,0x46be,0x46bc,0x46bb,0x46b8,0x46b7,0x46b6,0x46b5,0x46b2,0x46b1,0x46b0,0x46ad,0x46ac,0x46aa,
+ 0x46a9,0x46a7,0x46a5,0x46a4,0x46a3,0x46a0,0x469f,0x469e,0x469b,0x469a,0x4699,0x4697,0x4695,0x4693,0x4692,0x4690,
+ 0x468e,0x468d,0x468c,0x4689,0x4688,0x4687,0x4685,0x4683,0x4682,0x4680,0x467e,0x467c,0x467b,0x467a,0x4677,0x4676,
+ 0x4675,0x4673,0x4671,0x4670,0x466e,0x466c,0x466b,0x466a,0x4667,0x4666,0x4665,0x4662,0x4661,0x4660,0x465e,0x465c,
+ 0x465a,0x4659,0x4658,0x4655,0x4654,0x4653,0x4650,0x464f,0x464e,0x464c,0x464a,0x4649,0x4647,0x4646,0x4643,0x4642,
+ 0x4641,0x463e,0x463d,0x463c,0x463b,0x4638,0x4637,0x4635,0x4634,0x4632,0x4630,0x462f,0x462d,0x462b,0x462a,0x4629,
+ 0x4626,0x4625,0x4624,0x4622,0x4620,0x461f,0x461d,0x461b,0x4619,0x4618,0x4617,0x4614,0x4613,0x4612,0x4611,0x460e,
+ 0x460d,0x460b,0x4609,0x4608,0x4606,0x4605,0x4603,0x4601,0x4600,0x45ff,0x45fc,0x45fb,0x45fa,0x45f7,0x45f6,0x45f5,
+ 0x45f3,0x45f1,0x45ef,0x45ee,0x45ed,0x45ea,0x45e9,0x45e8,0x45e5,0x45e4,0x45e3,0x45e1,0x45df,0x45de,0x45dc,0x45db,
+ 0x45d9,0x45d7,0x45d6,0x45d3,0x45d2,0x45d1,0x45d0,0x45cd,0x45cc,0x45cb,0x45c9,0x45c7,0x45c5,0x45c4,0x45c2,0x45c0,
+ 0x45bf,0x45be,0x45bb,0x45ba,0x45b9,0x45b7,0x45b5,0x45b4,0x45b2,0x45b0,0x45af,0x45ad,0x45ac,0x45a9,0x45a8,0x45a7,
+ 0x45a5,0x45a3,0x45a1,0x45a0,0x459f,0x459c,0x459b,0x459a,0x4598,0x4596,0x4595,0x4593,0x4592,0x458f,0x458e,0x458d,
+ 0x458a,0x4589,0x4588,0x4587,0x4584,0x4583,0x4581,0x4580,0x457e,0x457c,0x457b,0x4579,0x4577,0x4576,0x4575,0x4572,
+ 0x4571,0x4570,0x456e,0x456c,0x456b,0x4569,0x4568,0x4566,0x4564,0x4563,0x4560,0x455f,0x455e,0x455d,0x455a,0x4559,
+ 0x4558,0x4556,0x4554,0x4553,0x4551,0x454f,0x454d,0x454c,0x454b,0x4548,0x4547,0x4546,0x4545,0x4542,0x4541,0x453f,
+ 0x453e,0x453c,0x453a,0x4539,0x4537,0x4535,0x4534,0x4533,0x4530,0x452f,0x452e,0x452c,0x452a,0x4529,0x4527,0x4525,
+ 0x4524,0x4522,0x4521,0x451e,0x451d,0x451c,0x451b,0x4518,0x4517,0x4516,0x4513,0x4512,0x4511,0x450f,0x450d,0x450b,
+ 0x450a,0x4509,0x4506,0x4505,0x4504,0x4503,0x4500,0x44ff,0x44fd,0x44fb,0x44fa,0x44f8,0x44f7,0x44f5,0x44f3,0x44f2,
+ 0x44f1,0x44ee,0x44ed,0x44ec,0x44e9,0x44e8,0x44e7,0x44e5,0x44e3,0x44e2,0x44e0,0x44df,0x44dc,0x44db,0x44da,0x44d9,
+ 0x44d6,0x44d5,0x44d2,0x44d1,0x44d0,0x44ce,0x44cc,0x44cb,0x44c9,0x44c8,0x44c5,0x44c4,0x44c3,0x44c2,0x44bf,0x44be,
+ 0x44bd,0x44ba,0x44b9,0x44b8,0x44b6,0x44b4,0x44b2,0x44b1,0x44b0,0x44ad,0x44ac,0x44ab,0x44aa,0x44a7,0x44a6,0x44a5,
+ 0x44a3,0x44a1,0x449f,0x449e,0x449c,0x449a,0x4499,0x4498,0x4495,0x4494,0x4493,0x4492,0x448f,0x448e,0x448c,0x448b,
+ 0x4489,0x4487,0x4486,0x4484,0x4482,0x4481,0x4480,0x447d,0x447c,0x447b,0x447a,0x4477,0x4476,0x4474,0x4473,0x4471,
+ 0x446f,0x446e,0x446c,0x446a,0x4469,0x4468,0x4465,0x4464,0x4463,0x4461,0x445f,0x445e,0x445c,0x445b,0x4459,0x4457,
+ 0x4456,0x4454,0x4452,0x4451,0x4450,0x444d,0x444c,0x444b,0x4449,0x4447,0x4446,0x4444,0x4443,0x4441,0x443f,0x443e,
+ 0x443d,0x443a,0x4439,0x4438,0x4435,0x4434,0x4433,0x4431,0x442f,0x442e,0x442c,0x442b,0x4429,0x4427,0x4426,0x4425,
+ 0x4422,0x4421,0x4420,0x441d,0x441c,0x441b,0x4419,0x4417,0x4416,0x4414,0x4413,0x4410,0x440f,0x440e,0x440d,0x440a,
+ 0x4409,0x4408,0x4405,0x4404,0x4403,0x4401,0x43ff,0x43fd,0x43fc,0x43fb,0x43f8,0x43f7,0x43f6,0x43f5,0x43f2,0x43f1,
+ 0x43f0,0x43ed,0x43ec,0x43ea,0x43e9,0x43e7,0x43e5,0x43e4,0x43e3,0x43e0,0x43df,0x43de,0x43dd,0x43da,0x43d9,0x43d8,
+ 0x43d6,0x43d4,0x43d2,0x43d1,0x43cf,0x43cd,0x43cc,0x43cb,0x43c8,0x43c7,0x43c6,0x43c5,0x43c2,0x43c1,0x43bf,0x43be,
+ 0x43bc,0x43ba,0x43b9,0x43b7,0x43b5,0x43b4,0x43b3,0x43b0,0x43af,0x43ae,0x43ac,0x43aa,0x43a9,0x43a7,0x43a6,0x43a4,
+ 0x43a2,0x43a1,0x439f,0x439d,0x439c,0x439b,0x4398,0x4397,0x4396,0x4394,0x4392,0x4391,0x438f,0x438e,0x438c,0x438a,
+ 0x4389,0x4387,0x4385,0x4384,0x4383,0x4380,0x437f,0x437e,0x437c,0x437a,0x4379,0x4377,0x4376,0x4374,0x4372,0x4371,
+ 0x4370,0x436d,0x436c,0x436b,0x4368,0x4367,0x4366,0x4364,0x4362,0x4361,0x435f,0x435e,0x435b,0x435a,0x4359,0x4358,
+ 0x4355,0x4354,0x4353,0x4350,0x434f,0x434e,0x434c,0x434a,0x4348,0x4347,0x4346,0x4343,0x4342,0x4341,0x4340,0x433d,
+ 0x433d,0x433a,0x4339,0x4338,0x4336,0x4334,0x4332,0x4331,0x4330,0x432d,0x432c,0x432b,0x432a,0x4327,0x4326,0x4325,
+ 0x4323,0x4321,0x4320,0x431e,0x431d,0x431a,0x4319,0x4318,0x4315,0x4314,0x4313,0x4312,0x430f,0x430e,0x430d,0x430b,
+ 0x4309,0x4308,0x4306,0x4305,0x4303,0x4301,0x4300,0x42ff,0x42fc,0x42fb,0x42fa,0x42f7,0x42f6,0x42f5,0x42f3,0x42f1,
+ 0x42f0,0x42ee,0x42ed,0x42eb,0x42e9,0x42e8,0x42e7,0x42e4,0x42e3,0x42e2,0x42e0,0x42de,0x42dd,0x42db,0x42da,0x42d8,
+ 0x42d6,0x42d5,0x42d3,0x42d1,0x42d0,0x42cf,0x42cc,0x42cb,0x42ca,0x42c8,0x42c6,0x42c5,0x42c3,0x42c2,0x42c0,0x42be,
+ 0x42bd,0x42bc,0x42b9,0x42b8,0x42b7,0x42b6,0x42b3,0x42b2,0x42b1,0x42ae,0x42ad,0x42ab,0x42aa,0x42a8,0x42a6,0x42a5,
+ 0x42a4,0x42a1,0x42a0,0x429f,0x429e,0x429b,0x429a,0x4299,0x4297,0x4295,0x4293,0x4292,0x4290,0x428e,0x428d,0x428c,
+ 0x4289,0x4288,0x4287,0x4286,0x4283,0x4282,0x4281,0x427f,0x427d,0x427c,0x427a,0x4279,0x4276,0x4275,0x4274,0x4273,
+ 0x4271,0x426f,0x426d,0x426c,0x426a,0x4268,0x4267,0x4266,0x4263,0x4262,0x4261,0x4260,0x425d,0x425c,0x425b,0x4259,
+ 0x4257,0x4256,0x4254,0x4253,0x4251,0x424f,0x424e,0x424d,0x424a,0x4249,0x4248,0x4246,0x4244,0x4243,0x4241,0x4240,
+ 0x423e,0x423c,0x423b,0x4239,0x4237,0x4236,0x4235,0x4232,0x4231,0x4230,0x422f,0x422c,0x422b,0x422a,0x4228,0x4226,
+ 0x4224,0x4223,0x4222,0x421f,0x421e,0x421d,0x421c,0x4219,0x4218,0x4217,0x4215,0x4213,0x4212,0x4210,0x420f,0x420d,
+ 0x420b,0x420a,0x4208,0x4206,0x4205,0x4204,0x4201,0x4200,0x41ff,0x41fd,0x41fb,0x41fa,0x41f8,0x41f7,0x41f5,0x41f3,
+ 0x41f2,0x41f1,0x41ee,0x41ed,0x41ec,0x41eb,0x41e8,0x41e7,0x41e6,0x41e4,0x41e2,0x41e1,0x41df,0x41de,0x41dc,0x41da,
+ 0x41d9,0x41d6,0x41d5,0x41d4,0x41d3,0x41d0,0x41cf,0x41ce,0x41cc,0x41ca,0x41c9,0x41c7,0x41c6,0x41c4,0x41c2,0x41c1,
+ 0x41c0,0x41bd,0x41bc,0x41bb,0x41ba,0x41b7,0x41b6,0x41b5,0x41b3,0x41b1,0x41b0,0x41ae,0x41ad,0x41aa,0x41a9,0x41a8,
+ 0x41a6,0x41a4,0x41a3,0x41a1,0x419f,0x419e,0x419d,0x419a,0x4199,0x4198,0x4196,0x4194,0x4193,0x4191,0x4190,0x418e,
+ 0x418c,0x418b,0x418a,0x4187,0x4186,0x4185,0x4184,0x4181,0x4180,0x417f,0x417d,0x417b,0x417a,0x4178,0x4177,0x4175,
+ 0x4173,0x4172,0x4171,0x416e,0x416d,0x416c,0x416b,0x4168,0x4167,0x4166,0x4164,0x4162,0x4161,0x415f,0x415e,0x415c,
+ 0x415a,0x4159,0x4158,0x4155,0x4154,0x4153,0x4152,0x414f,0x414e,0x414c,0x414b,0x4149,0x4147,0x4146,0x4145,0x4142,
+ 0x4141,0x4140,0x413d,0x413c,0x413b,0x413a,0x4137,0x4136,0x4135,0x4133,0x4131,0x4130,0x412e,0x412d,0x412b,0x4129,
+ 0x4128,0x4127,0x4124,0x4123,0x4122,0x4121,0x411e,0x411d,0x411c,0x411a,0x4118,0x4117,0x4115,0x4114,0x4112,0x4110,
+ 0x410f,0x410e,0x410b,0x410a,0x4109,0x4108,0x4105,0x4104,0x4103,0x4101,0x40ff,0x40fd,0x40fc,0x40fb,0x40f8,0x40f7,
+ 0x40f6,0x40f5,0x40f2,0x40f1,0x40f0,0x40ee,0x40ec,0x40eb,0x40e9,0x40e8,0x40e6,0x40e4,0x40e3,0x40e2,0x40df,0x40de,
+ 0x40dc,0x40db,0x40da,0x40d7,0x40d6,0x40d5,0x40d3,0x40d1,0x40d0,0x40ce,0x40cd,0x40cb,0x40c9,0x40c8,0x40c7,0x40c4,
+ 0x40c3,0x40c2,0x40c1,0x40be,0x40bd,0x40bc,0x40ba,0x40b8,0x40b7,0x40b5,0x40b4,0x40b2,0x40b0,0x40af,0x40ae,0x40ab,
+ 0x40aa,0x40a9,0x40a8,0x40a5,0x40a4,0x40a3,0x40a1,0x409f,0x409e,0x409c,0x409b,0x4099,0x4097,0x4096,0x4095,0x4092,
+ 0x4091,0x4090,0x408f,0x408c,0x408b,0x408a,0x4088,0x4086,0x4085,0x4083,0x4082,0x4080,0x407e,0x407d,0x407c,0x4079,
+ 0x4078,0x4077,0x4076,0x4073,0x4072,0x4071,0x406f,0x406d,0x406c,0x406a,0x4069,0x4067,0x4065,0x4064,0x4063,0x4060,
+ 0x405f,0x405e,0x405d,0x405a,0x4059,0x4058,0x4056,0x4054,0x4053,0x4051,0x4050,0x404e,0x404c,0x404b,0x404a,0x4047,
+ 0x4046,0x4045,0x4044,0x4041,0x4040,0x403f,0x403d,0x403b,0x403a,0x4038,0x4037,0x4035,0x4033,0x4032,0x4031,0x402e,
+ 0x402d,0x402c,0x402b,0x4028,0x4027,0x4026,0x4024,0x4022,0x4021,0x401f,0x401e,0x401c,0x401a,0x4019,0x4018,0x4015,
+ 0x4014,0x4013,0x4012,0x400f,0x400e,0x400d,0x400b,0x4009,0x4008,0x4006,0x4005,0x4003,0x4001,0x4000,0x3fff,0x3ffc,
+ 0x3ffb,0x3ffa,0x3ff9,0x3ff6,0x3ff5,0x3ff4,0x3ff2,0x3ff0,0x3fef,0x3fed,0x3fec,0x3fea,0x3fe8,0x3fe7,0x3fe6,0x3fe3,
+ 0x3fe2,0x3fe1,0x3fe0,0x3fdd,0x3fdc,0x3fdb,0x3fd9,0x3fd7,0x3fd6,0x3fd4,0x3fd3,0x3fd1,0x3fcf,0x3fce,0x3fcd,0x3fca,
+ 0x3fc9,0x3fc8,0x3fc7,0x3fc4,0x3fc3,0x3fc2,0x3fc0,0x3fbe,0x3fbd,0x3fbb,0x3fba,0x3fb8,0x3fb6,0x3fb5,0x3fb4,0x3fb1,
+ 0x3fb0,0x3faf,0x3fae,0x3fab,0x3faa,0x3fa9,0x3fa7,0x3fa5,0x3fa4,0x3fa2,0x3fa1,0x3f9f,0x3f9d,0x3f9c,0x3f9b,0x3f98,
+ 0x3f97,0x3f96,0x3f95,0x3f92,0x3f91,0x3f90,0x3f8e,0x3f8c,0x3f8b,0x3f89,0x3f88,0x3f86,0x3f84,0x3f83,0x3f82,0x3f7f,
+ 0x3f7e,0x3f7d,0x3f7c,0x3f79,0x3f78,0x3f77,0x3f75,0x3f73,0x3f72,0x3f70,0x3f6f,0x3f6d,0x3f6b,0x3f6a,0x3f69,0x3f66,
+ 0x3f65,0x3f64,0x3f63,0x3f60,0x3f5f,0x3f5e,0x3f5c,0x3f5a,0x3f59,0x3f57,0x3f56,0x3f54,0x3f52,0x3f51,0x3f50,0x3f4d,
+ 0x3f4c,0x3f4b,0x3f4a,0x3f48,0x3f46,0x3f45,0x3f43,0x3f42,0x3f40,0x3f3e,0x3f3d,0x3f3c,0x3f39,0x3f38,0x3f37,0x3f36,
+ 0x3f33,0x3f32,0x3f31,0x3f2f,0x3f2d,0x3f2c,0x3f2a,0x3f29,0x3f27,0x3f25,0x3f24,0x3f23,0x3f20,0x3f1f,0x3f1e,0x3f1d,
+ 0x3f1a,0x3f19,0x3f18,0x3f16,0x3f14,0x3f13,0x3f11,0x3f10,0x3f0e,0x3f0c,0x3f0b,0x3f0a,0x3f07,0x3f06,0x3f05,0x3f04,
+ 0x3f01,0x3f00,0x3eff,0x3efe,0x3efb,0x3efa,0x3ef9,0x3ef7,0x3ef5,0x3ef4,0x3ef2,0x3ef1,0x3eef,0x3eed,0x3eec,0x3eeb,
+ 0x3eea,0x3ee7,0x3ee6,0x3ee5,0x3ee3,0x3ee1,0x3ee0,0x3ede,0x3edd,0x3edb,0x3ed9,0x3ed8,0x3ed7,0x3ed4,0x3ed3,0x3ed2,
+ 0x3ed1,0x3ece,0x3ecd,0x3ecc,0x3eca,0x3ec8,0x3ec7,0x3ec5,0x3ec4,0x3ec2,0x3ec0,0x3ebf,0x3ebe,0x3ebb,0x3eba,0x3eb9,
+ 0x3eb8,0x3eb5,0x3eb4,0x3eb3,0x3eb1,0x3eaf,0x3eae,0x3ead,0x3eab,0x3ea9,0x3ea8,0x3ea6,0x3ea5,0x3ea3,0x3ea1,0x3ea0,
+ 0x3e9f,0x3e9c,0x3e9b,0x3e9a,0x3e99,0x3e96,0x3e95,0x3e94,0x3e92,0x3e90,0x3e8f,0x3e8d,0x3e8c,0x3e8a,0x3e88,0x3e87,
+ 0x3e86,0x3e84,0x3e82,0x3e81,0x3e80,0x3e7d,0x3e7c,0x3e7b,0x3e7a,0x3e77,0x3e76,0x3e75,0x3e74,0x3e71,0x3e70,0x3e6f,
+ 0x3e6d,0x3e6b,0x3e6a,0x3e68,0x3e67,0x3e65,0x3e63,0x3e62,0x3e61,0x3e5e,0x3e5d,0x3e5c,0x3e5b,0x3e58,0x3e57,0x3e56,
+ 0x3e54,0x3e53,0x3e51,0x3e50,0x3e4e,0x3e4d,0x3e4b,0x3e49,0x3e48,0x3e47,0x3e44,0x3e43,0x3e42,0x3e41,0x3e3e,0x3e3d,
+ 0x3e3c,0x3e3a,0x3e38,0x3e37,0x3e35,0x3e34,0x3e32,0x3e30,0x3e2f,0x3e2e,0x3e2b,0x3e2a,0x3e29,0x3e28,0x3e25,0x3e24,
+ 0x3e23,0x3e22,0x3e20,0x3e1e,0x3e1d,0x3e1b,0x3e1a,0x3e18,0x3e16,0x3e15,0x3e14,0x3e11,0x3e10,0x3e0f,0x3e0e,0x3e0b,
+ 0x3e0a,0x3e09,0x3e07,0x3e05,0x3e04,0x3e02,0x3e01,0x3dff,0x3dfe,0x3dfc,0x3dfb,0x3df9,0x3df7,0x3df6,0x3df5,0x3df2,
+ 0x3df1,0x3df0,0x3def,0x3ded,0x3deb,0x3dea,0x3de8,0x3de7,0x3de5,0x3de3,0x3de2,0x3de1,0x3dde,0x3ddd,0x3ddc,0x3ddb,
+ 0x3dd8,0x3dd7,0x3dd6,0x3dd5,0x3dd2,0x3dd1,0x3dd0,0x3dce,0x3dcc,0x3dcb,0x3dc9,0x3dc8,0x3dc6,0x3dc4,0x3dc3,0x3dc2,
+ 0x3dc0,0x3dbf,0x3dbc,0x3dbb,0x3dba,0x3db9,0x3db6,0x3db5,0x3db4,0x3db2,0x3db0,0x3daf,0x3dad,0x3dac,0x3daa,0x3da8,
+ 0x3da7,0x3da6,0x3da3,0x3da2,0x3da1,0x3da0,0x3d9f,0x3d9c,0x3d9b,0x3d9a,0x3d98,0x3d96,0x3d95,0x3d93,0x3d92,0x3d90,
+ 0x3d8e,0x3d8d,0x3d8c,0x3d89,0x3d88,0x3d87,0x3d86,0x3d83,0x3d82,0x3d81,0x3d80,0x3d7e,0x3d7c,0x3d7b,0x3d79,0x3d78,
+ 0x3d76,0x3d74,0x3d73,0x3d72,0x3d6f,0x3d6e,0x3d6d,0x3d6c,0x3d69,0x3d68,0x3d67,0x3d66,0x3d63,0x3d62,0x3d61,0x3d5f,
+ 0x3d5e,0x3d5c,0x3d5a,0x3d59,0x3d58,0x3d55,0x3d54,0x3d53,0x3d52,0x3d4f,0x3d4e,0x3d4d,0x3d4c,0x3d49,0x3d48,0x3d47,
+ 0x3d45,0x3d43,0x3d42,0x3d40,0x3d3f,0x3d3d,0x3d3b,0x3d3a,0x3d39,0x3d38,0x3d35,0x3d34,0x3d33,0x3d32,0x3d2f,0x3d2e,
+ 0x3d2d,0x3d2b,0x3d29,0x3d28,0x3d26,0x3d25,0x3d23,0x3d21,0x3d20,0x3d1f,0x3d1c,0x3d1b,0x3d1a,0x3d19,0x3d18,0x3d15,
+ 0x3d14,0x3d13,0x3d11,0x3d0f,0x3d0e,0x3d0c,0x3d0b,0x3d09,0x3d07,0x3d06,0x3d05,0x3d02,0x3d01,0x3d00,0x3cff,0x3cfc,
+ 0x3cfb,0x3cfa,0x3cf9,0x3cf7,0x3cf5,0x3cf4,0x3cf2,0x3cf1,0x3cef,0x3ced,0x3cec,0x3ceb,0x3ce8,0x3ce7,0x3ce6,0x3ce5,
+ 0x3ce2,0x3ce1,0x3ce0,0x3cdf,0x3cdc,0x3cdb,0x3cda,0x3cd8,0x3cd7,0x3cd5,0x3cd3,0x3cd2,0x3cd1,0x3cce,0x3ccd,0x3ccc,
+ 0x3ccb,0x3cc8,0x3cc7,0x3cc6,0x3cc5,0x3cc2,0x3cc1,0x3cc0,0x3cbe,0x3cbc,0x3cbb,0x3cb9,0x3cb8,0x3cb7,0x3cb4,0x3cb3,
+ 0x3cb2,0x3cb1,0x3cae,0x3cad,0x3cac,0x3cab,0x3ca8,0x3ca7,0x3ca6,0x3ca4,0x3ca2,0x3ca1,0x3c9f,0x3c9e,0x3c9c,0x3c9a,
+ 0x3c99,0x3c98,0x3c97,0x3c94,0x3c93,0x3c92,0x3c91,0x3c8e,0x3c8d,0x3c8c,0x3c8a,0x3c88,0x3c87,0x3c85,0x3c84,0x3c82,
+ 0x3c80,0x3c7f,0x3c7e,0x3c7c,0x3c7a,0x3c79,0x3c78,0x3c77,0x3c74,0x3c73,0x3c72,0x3c70,0x3c6e,0x3c6d,0x3c6b,0x3c6a,
+ 0x3c68,0x3c66,0x3c65,0x3c64,0x3c62,0x3c60,0x3c5f,0x3c5e,0x3c5b,0x3c5a,0x3c59,0x3c58,0x3c56,0x3c54,0x3c53,0x3c51,
+ 0x3c50,0x3c4e,0x3c4c,0x3c4b,0x3c4a,0x3c47,0x3c46,0x3c45,0x3c44,0x3c41,0x3c40,0x3c3f,0x3c3e,0x3c3b,0x3c3a,0x3c39,
+ 0x3c38,0x3c36,0x3c35,0x3c33,0x3c31,0x3c30,0x3c2f,0x3c2c,0x3c2b,0x3c2a,0x3c29,0x3c26,0x3c25,0x3c24,0x3c23,0x3c20,
+ 0x3c1f,0x3c1e,0x3c1c,0x3c1b,0x3c19,0x3c17,0x3c16,0x3c15,0x3c13,0x3c11,0x3c10,0x3c0f,0x3c0c,0x3c0b,0x3c0a,0x3c09,
+ 0x3c07,0x3c05,0x3c04,0x3c02,0x3c01,0x3bff,0x3bfe,0x3bfc,0x3bfb,0x3bf9,0x3bf7,0x3bf6,0x3bf5,0x3bf2,0x3bf1,0x3bf0,
+ 0x3bef,0x3bed,0x3beb,0x3bea,0x3be9,0x3be7,0x3be5,0x3be4,0x3be2,0x3be1,0x3bdf,0x3bdd,0x3bdc,0x3bdb,0x3bd9,0x3bd7,
+ 0x3bd6,0x3bd5,0x3bd4,0x3bd1,0x3bd0,0x3bcf,0x3bcd,0x3bcb,0x3bca,0x3bc8,0x3bc7,0x3bc5,0x3bc4,0x3bc2,0x3bc1,0x3bbf,
+ 0x3bbd,0x3bbc,0x3bbb,0x3bba,0x3bb7,0x3bb6,0x3bb5,0x3bb3,0x3bb1,0x3bb0,0x3baf,0x3bad,0x3bab,0x3baa,0x3ba8,0x3ba7,
+ 0x3ba6,0x3ba3,0x3ba2,0x3ba1,0x3ba0,0x3b9d,0x3b9c,0x3b9b,0x3b9a,0x3b97,0x3b96,0x3b95,0x3b93,0x3b91,0x3b90,0x3b8e,
+ 0x3b8d,0x3b8c,0x3b8a,0x3b88,0x3b87,0x3b86,0x3b83,0x3b82,0x3b81,0x3b80,0x3b7d,0x3b7c,0x3b7b,0x3b79,0x3b77,0x3b76,
+ 0x3b75,0x3b74,0x3b71,0x3b70,0x3b6f,0x3b6e,0x3b6b,0x3b6a,0x3b69,0x3b67,0x3b65,0x3b64,0x3b62,0x3b61,0x3b60,0x3b5e,
+ 0x3b5c,0x3b5b,0x3b5a,0x3b57,0x3b56,0x3b55,0x3b54,0x3b51,0x3b50,0x3b4f,0x3b4e,0x3b4c,0x3b4a,0x3b49,0x3b47,0x3b46,
+ 0x3b44,0x3b42,0x3b41,0x3b40,0x3b3e,0x3b3c,0x3b3b,0x3b3a,0x3b39,0x3b36,0x3b35,0x3b34,0x3b32,0x3b30,0x3b2f,0x3b2e,
+ 0x3b2c,0x3b2a,0x3b29,0x3b27,0x3b26,0x3b25,0x3b22,0x3b21,0x3b20,0x3b1f,0x3b1c,0x3b1b,0x3b1a,0x3b19,0x3b16,0x3b15,
+ 0x3b14,0x3b12,0x3b11,0x3b0f,0x3b0e,0x3b0c,0x3b0b,0x3b09,0x3b07,0x3b06,0x3b05,0x3b02,0x3b01,0x3b00,0x3aff,0x3afe,
+ 0x3afb,0x3afa,0x3af9,0x3af7,0x3af5,0x3af4,0x3af2,0x3af1,0x3aef,0x3aee,0x3aec,0x3aeb,0x3aea,0x3ae7,0x3ae6,0x3ae5,
+ 0x3ae4,0x3ae1,0x3ae0,0x3adf,0x3ade,0x3adb,0x3ada,0x3ad9,0x3ad7,0x3ad6,0x3ad4,0x3ad2,0x3ad1,0x3ad0,0x3ace,0x3acc,
+ 0x3acb,0x3aca,0x3ac7,0x3ac6,0x3ac5,0x3ac4,0x3ac2,0x3ac0,0x3abf,0x3abe,0x3abc,0x3aba,0x3ab9,0x3ab7,0x3ab6,0x3ab4,
+ 0x3ab3,0x3ab1,0x3aaf,0x3aae,0x3aad,0x3aaa,0x3aa9,0x3aa8,0x3aa7,0x3aa4,0x3aa3,0x3aa2,0x3aa1,0x3a9f,0x3a9d,0x3a9c,
+ 0x3a9b,0x3a99,0x3a97,0x3a96,0x3a94,0x3a93,0x3a92,0x3a90,0x3a8e,0x3a8d,0x3a8c,0x3a89,0x3a88,0x3a87,0x3a86,0x3a83,
+ 0x3a82,0x3a81,0x3a80,0x3a7e,0x3a7c,0x3a7b,0x3a79,0x3a78,0x3a76,0x3a75,0x3a73,0x3a72,0x3a71,0x3a6e,0x3a6d,0x3a6c,
+ 0x3a6b,0x3a68,0x3a67,0x3a66,0x3a65,0x3a62,0x3a61,0x3a60,0x3a5e,0x3a5d,0x3a5b,0x3a5a,0x3a58,0x3a57,0x3a55,0x3a53,
+ 0x3a52,0x3a51,0x3a50,0x3a4d,0x3a4c,0x3a4b,0x3a4a,0x3a47,0x3a46,0x3a45,0x3a43,0x3a42,0x3a40,0x3a3f,0x3a3d,0x3a3c,
+ 0x3a3a,0x3a38,0x3a37,0x3a36,0x3a34,0x3a32,0x3a31,0x3a30,0x3a2f,0x3a2c,0x3a2b,0x3a2a,0x3a28,0x3a26,0x3a25,0x3a24,
+ 0x3a22,0x3a21,0x3a1f,0x3a1d,0x3a1c,0x3a1b,0x3a19,0x3a17,0x3a16,0x3a15,0x3a12,0x3a11,0x3a10,0x3a0f,0x3a0d,0x3a0b,
+ 0x3a0a,0x3a09,0x3a07,0x3a05,0x3a04,0x3a02,0x3a01,0x3a00,0x39fe,0x39fc,0x39fb,0x39fa,0x39f7,0x39f6,0x39f5,0x39f4,
+ 0x39f3,0x39f0,0x39ef,0x39ee,0x39ec,0x39ea,0x39e9,0x39e7,0x39e6,0x39e4,0x39e3,0x39e1,0x39e0,0x39df,0x39dc,0x39db,
+ 0x39da,0x39d9,0x39d6,0x39d5,0x39d4,0x39d3,0x39d1,0x39cf,0x39ce,0x39cc,0x39cb,0x39c9,0x39c8,0x39c6,0x39c5,0x39c3,
+ 0x39c1,0x39c0,0x39bf,0x39be,0x39bb,0x39ba,0x39b9,0x39b8,0x39b5,0x39b4,0x39b3,0x39b2,0x39b0,0x39ae,0x39ad,0x39ab,
+ 0x39aa,0x39a8,0x39a6,0x39a5,0x39a4,0x39a2,0x39a0,0x399f,0x399e,0x399d,0x399a,0x3999,0x3998,0x3997,0x3994,0x3993,
+ 0x3992,0x3990,0x398f,0x398d,0x398b,0x398a,0x3989,0x3987,0x3985,0x3984,0x3983,0x3982,0x397f,0x397e,0x397d,0x397c,
+ 0x3979,0x3978,0x3977,0x3975,0x3973,0x3972,0x3970,0x396f,0x396e,0x396c,0x396a,0x3969,0x3968,0x3965,0x3964,0x3963,
+ 0x3962,0x3961,0x395e,0x395d,0x395c,0x395a,0x3958,0x3957,0x3956,0x3954,0x3952,0x3951,0x394f,0x394e,0x394d,0x394a,
+ 0x3949,0x3948,0x3947,0x3944,0x3943,0x3942,0x3941,0x393f,0x393d,0x393c,0x393b,0x3939,0x3937,0x3936,0x3934,0x3933,
+ 0x3932,0x3931,0x392e,0x392d,0x392c,0x392b,0x3928,0x3927,0x3926,0x3925,0x3923,0x3921,0x3920,0x391f,0x391d,0x391b,
+ 0x391a,0x3918,0x3917,0x3916,0x3914,0x3912,0x3911,0x3910,0x390d,0x390c,0x390b,0x390a,0x3909,0x3906,0x3905,0x3904,
+ 0x3902,0x3900,0x38ff,0x38fe,0x38fc,0x38fb,0x38f9,0x38f7,0x38f6,0x38f5,0x38f3,0x38f1,0x38f0,0x38ef,0x38ee,0x38eb,
+ 0x38ea,0x38e9,0x38e8,0x38e5,0x38e4,0x38e3,0x38e1,0x38e0,0x38de,0x38dd,0x38db,0x38da,0x38d8,0x38d6,0x38d5,0x38d4,
+ 0x38d3,0x38d0,0x38cf,0x38ce,0x38cd,0x38ca,0x38c9,0x38c8,0x38c7,0x38c4,0x38c3,0x38c2,0x38c0,0x38bf,0x38bd,0x38bc,
+ 0x38ba,0x38b9,0x38b7,0x38b5,0x38b4,0x38b3,0x38b2,0x38af,0x38ae,0x38ad,0x38ac,0x38a9,0x38a8,0x38a7,0x38a6,0x38a4,
+ 0x38a2,0x38a1,0x389f,0x389e,0x389c,0x389b,0x3899,0x3898,0x3897,0x3894,0x3893,0x3892,0x3891,0x388e,0x388d,0x388c,
+ 0x388b,0x3889,0x3887,0x3886,0x3885,0x3883,0x3881,0x3880,0x387e,0x387d,0x387c,0x387a,0x3878,0x3877,0x3876,0x3873,
+ 0x3873,0x3871,0x3870,0x386e,0x386c,0x386b,0x386a,0x3868,0x3866,0x3865,0x3864,0x3863,0x3860,0x385f,0x385e,0x385d,
+ 0x385b,0x3859,0x3858,0x3857,0x3855,0x3853,0x3852,0x3850,0x384f,0x384e,0x384c,0x384a,0x3849,0x3848,0x3845,0x3844,
+ 0x3843,0x3842,0x3841,0x383e,0x383d,0x383c,0x383b,0x3838,0x3837,0x3836,0x3834,0x3833,0x3831,0x3830,0x382e,0x382d,
+ 0x382c,0x3829,0x3828,0x3827,0x3826,0x3823,0x3822,0x3821,0x3820,0x381e,0x381c,0x381b,0x381a,0x3818,0x3816,0x3815,
+ 0x3814,0x3812,0x3811,0x380f,0x380d,0x380c,0x380b,0x3809,0x3807,0x3806,0x3805,0x3804,0x3801,0x3800,0x37ff,0x37fe,
+ 0x37fc,0x37fa,0x37f9,0x37f7,0x37f6,0x37f4,0x37f3,0x37f1,0x37f0,0x37ef,0x37ed,0x37eb,0x37ea,0x37e9,0x37e6,0x37e5,
+ 0x37e4,0x37e3,0x37e2,0x37df,0x37de,0x37dd,0x37db,0x37d9,0x37d8,0x37d7,0x37d5,0x37d4,0x37d2,0x37d0,0x37cf,0x37ce,
+ 0x37cd,0x37ca,0x37c9,0x37c8,0x37c7,0x37c4,0x37c3,0x37c2,0x37c1,0x37bf,0x37bd,0x37bc,0x37bb,0x37b9,0x37b7,0x37b6,
+ 0x37b4,0x37b3,0x37b1,0x37b0,0x37ae,0x37ad,0x37ab,0x37aa,0x37a9,0x37a6,0x37a5,0x37a4,0x37a3,0x37a0,0x379f,0x379e,
+ 0x379d,0x379c,0x3799,0x3798,0x3797,0x3795,0x3794,0x3792,0x3791,0x378f,0x378e,0x378c,0x378a,0x3789,0x3788,0x3787,
+ 0x3784,0x3783,0x3782,0x3781,0x3780,0x377d,0x377c,0x377b,0x3779,0x3777,0x3776,0x3775,0x3773,0x3772,0x3770,0x376f,
+ 0x376d,0x376c,0x376b,0x3768,0x3767,0x3766,0x3765,0x3762,0x3761,0x3760,0x375f,0x375e,0x375b,0x375a,0x3759,0x3757,
+ 0x3756,0x3754,0x3753,0x3751,0x3750,0x374e,0x374d,0x374b,0x374a,0x3749,0x3746,0x3745,0x3744,0x3743,0x3740,0x373f,
+ 0x373e,0x373d,0x373c,0x3739,0x3738,0x3737,0x3735,0x3734,0x3732,0x3731,0x372f,0x372e,0x372c,0x372b,0x3729,0x3728,
+ 0x3727,0x3724,0x3723,0x3722,0x3721,0x3720,0x371d,0x371c,0x371b,0x371a,0x3717,0x3716,0x3715,0x3713,0x3712,0x3710,
+ 0x370f,0x370d,0x370c,0x370b,0x3709,0x3707,0x3706,0x3705,0x3702,0x3701,0x3700,0x36ff,0x36fe,0x36fb,0x36fa,0x36f9,
+ 0x36f7,0x36f6,0x36f4,0x36f3,0x36f1,0x36f0,0x36ee,0x36ed,0x36eb,0x36ea,0x36e9,0x36e6,0x36e5,0x36e4,0x36e3,0x36e2,
+ 0x36df,0x36de,0x36dd,0x36dc,0x36d9,0x36d8,0x36d7,0x36d5,0x36d4,0x36d2,0x36d1,0x36cf,0x36ce,0x36cd,0x36cb,0x36c9,
+ 0x36c8,0x36c7,0x36c4,0x36c3,0x36c2,0x36c1,0x36c0,0x36bd,0x36bc,0x36bb,0x36ba,0x36b8,0x36b6,0x36b5,0x36b3,0x36b2,
+ 0x36b0,0x36af,0x36ad,0x36ac,0x36ab,0x36a9,0x36a7,0x36a6,0x36a5,0x36a4,0x36a1,0x36a0,0x369f,0x369e,0x369b,0x369a,
+ 0x3699,0x3698,0x3696,0x3694,0x3693,0x3691,0x3690,0x368e,0x368d,0x368b,0x368a,0x3689,0x3687,0x3685,0x3684,0x3683,
+ 0x3682,0x367f,0x367e,0x367d,0x367c,0x3679,0x3678,0x3677,0x3676,0x3674,0x3672,0x3671,0x366f,0x366e,0x366d,0x366b,
+ 0x3669,0x3668,0x3667,0x3665,0x3663,0x3662,0x3661,0x3660,0x365d,0x365c,0x365b,0x365a,0x3658,0x3656,0x3655,0x3653,
+ 0x3652,0x3650,0x364f,0x364d,0x364c,0x364b,0x3649,0x3647,0x3646,0x3645,0x3644,0x3641,0x3640,0x363f,0x363e,0x363b,
+ 0x363b,0x3639,0x3638,0x3636,0x3635,0x3633,0x3632,0x3630,0x362f,0x362e,0x362c,0x362a,0x3629,0x3628,0x3627,0x3624,
+ 0x3623,0x3622,0x3621,0x361e,0x361d,0x361c,0x361b,0x3619,0x3617,0x3616,0x3615,0x3613,0x3612,0x3610,0x360f,0x360d,
+ 0x360c,0x360b,0x3608,0x3607,0x3606,0x3605,0x3602,0x3601,0x3600,0x35ff,0x35fe,0x35fb,0x35fa,0x35f9,0x35f8,0x35f6,
+ 0x35f4,0x35f3,0x35f1,0x35f0,0x35ef,0x35ed,0x35eb,0x35ea,0x35e9,0x35e7,0x35e5,0x35e4,0x35e3,0x35e2,0x35df,0x35de,
+ 0x35dd,0x35dc,0x35da,0x35d8,0x35d7,0x35d6,0x35d4,0x35d3,0x35d1,0x35d0,0x35ce,0x35cd,0x35cb,0x35ca,0x35c8,0x35c7,
+ 0x35c6,0x35c3,0x35c2,0x35c1,0x35c0,0x35bf,0x35bc,0x35bb,0x35ba,0x35b9,0x35b7,0x35b5,0x35b4,0x35b3,0x35b1,0x35af,
+ 0x35ae,0x35ac,0x35ab,0x35aa,0x35a8,0x35a6,0x35a5,0x35a4,0x35a3,0x35a0,0x359f,0x359e,0x359d,0x359b,0x3599,0x3598,
+ 0x3597,0x3595,0x3593,0x3592,0x3591,0x358f,0x358e,0x358c,0x358b,0x3589,0x3588,0x3587,0x3584,0x3583,0x3582,0x3581,
+ 0x357f,0x357e,0x357c,0x357b,0x3579,0x3577,0x3576,0x3575,0x3574,0x3571,0x3570,0x356f,0x356e,0x356d,0x356a,0x3569,
+ 0x3568,0x3567,0x3565,0x3563,0x3562,0x3561,0x355f,0x355d,0x355c,0x355b,0x3559,0x3558,0x3556,0x3554,0x3553,0x3552,
+ 0x3551,0x354e,0x354d,0x354c,0x354b,0x354a,0x3547,0x3546,0x3545,0x3544,0x3542,0x3540,0x353f,0x353e,0x353c,0x353b,
+ 0x3539,0x3538,0x3536,0x3535,0x3533,0x3531,0x3530,0x352f,0x352e,0x352b,0x352a,0x3529,0x3528,0x3527,0x3524,0x3523,
+ 0x3522,0x3521,0x351f,0x351d,0x351c,0x351b,0x3519,0x3518,0x3516,0x3515,0x3513,0x3512,0x3511,0x350e,0x350d,0x350c,
+ 0x350b,0x3508,0x3507,0x3506,0x3505,0x3504,0x3501,0x3500,0x34ff,0x34fe,0x34fc,0x34fa,0x34f9,0x34f8,0x34f6,0x34f5,
+ 0x34f3,0x34f2,0x34f0,0x34ef,0x34ee,0x34eb,0x34ea,0x34e9,0x34e8,0x34e7,0x34e4,0x34e3,0x34e2,0x34e1,0x34de,0x34dd,
+ 0x34dc,0x34db,0x34d9,0x34d7,0x34d6,0x34d5,0x34d3,0x34d2,0x34d0,0x34cf,0x34cd,0x34cc,0x34cb,0x34c8,0x34c7,0x34c6,
+ 0x34c4,0x34c3,0x34c2,0x34bf,0x34be,0x34bd,0x34bc,0x34ba,0x34b8,0x34b7,0x34b6,0x34b4,0x34b3,0x34b1,0x34b0,0x34ae,
+ 0x34ad,0x34ac,0x34aa,0x34a8,0x34a7,0x34a6,0x34a5,0x34a2,0x34a1,0x34a0,0x349f,0x349e,0x349b,0x349a,0x3499,0x3498,
+ 0x3496,0x3494,0x3493,0x3492,0x3490,0x348e,0x348d,0x348c,0x348a,0x3489,0x3487,0x3486,0x3484,0x3483,0x3482,0x3480,
+ 0x347e,0x347d,0x347c,0x347b,0x3478,0x3477,0x3476,0x3475,0x3474,0x3471,0x3470,0x346f,0x346d,0x346c,0x346a,0x3469,
+ 0x3467,0x3466,0x3465,0x3463,0x3461,0x3460,0x345f,0x345e,0x345b,0x345a,0x3459,0x3458,0x3457,0x3454,0x3453,0x3452,
+ 0x3451,0x344f,0x344d,0x344c,0x344b,0x3449,0x3448,0x3446,0x3445,0x3443,0x3442,0x3441,0x343f,0x343d,0x343c,0x343b,
+ 0x343a,0x3437,0x3436,0x3435,0x3434,0x3431,0x3430,0x342f,0x342e,0x342d,0x342a,0x3429,0x3428,0x3427,0x3425,0x3423,
+ 0x3422,0x3420,0x341f,0x341e,0x341c,0x341a,0x3419,0x3418,0x3417,0x3414,0x3413,0x3412,0x3411,0x3410,0x340d,0x340c,
+ 0x340b,0x340a,0x3408,0x3406,0x3405,0x3404,0x3402,0x3401,0x33ff,0x33fe,0x33fc,0x33fb,0x33fa,0x33f8,0x33f6,0x33f5,
+ 0x33f4,0x33f3,0x33f0,0x33ef,0x33ee,0x33ed,0x33ec,0x33e9,0x33e8,0x33e7,0x33e6,0x33e4,0x33e2,0x33e1,0x33e0,0x33de,
+ 0x33dd,0x33db,0x33da,0x33d8,0x33d7,0x33d5,0x33d3,0x33d2,0x33d1,0x33d0,0x33cd,0x33cc,0x33cb,0x33ca,0x33c9,0x33c6,
+ 0x33c5,0x33c4,0x33c3,0x33c1,0x33bf,0x33be,0x33bd,0x33bb,0x33ba,0x33b8,0x33b7,0x33b5,0x33b4,0x33b3,0x33b1,0x33af,
+ 0x33ae,0x33ad,0x33ac,0x33a9,0x33a8,0x33a7,0x33a6,0x33a5,0x33a2,0x33a1,0x33a0,0x339f,0x339d,0x339b,0x339a,0x3399,
+ 0x3397,0x3396,0x3394,0x3393,0x3391,0x3390,0x338f,0x338d,0x338b,0x338a,0x3389,0x3388,0x3385,0x3384,0x3383,0x3382,
+ 0x3380,0x337e,0x337d,0x337c,0x337a,0x3378,0x3377,0x3376,0x3374,0x3373,0x3371,0x3370,0x336e,0x336d,0x336c,0x336a,
+ 0x3368,0x3367,0x3366,0x3365,0x3362,0x3361,0x3360,0x335f,0x335e,0x335b,0x335a,0x3359,0x3358,0x3356,0x3354,0x3353,
+ 0x3352,0x3350,0x334f,0x334e,0x334c,0x334a,0x3349,0x3348,0x3347,0x3344,0x3343,0x3342,0x3341,0x3340,0x333d,0x333c,
+ 0x333b,0x333a,0x3338,0x3336,0x3335,0x3334,0x3332,0x3331,0x332f,0x332e,0x332c,0x332b,0x332a,0x3328,0x3326,0x3325,
+ 0x3324,0x3323,0x3320,0x331f,0x331e,0x331d,0x331c,0x3319,0x3318,0x3317,0x3316,0x3314,0x3312,0x3311,0x3310,0x330e,
+ 0x330d,0x330b,0x330a,0x3308,0x3307,0x3306,0x3304,0x3302,0x3301,0x3300,0x32ff,0x32fc,0x32fb,0x32fa,0x32f9,0x32f8,
+ 0x32f6,0x32f4,0x32f3,0x32f2,0x32f0,0x32ef,0x32ed,0x32ec,0x32ea,0x32e9,0x32e8,0x32e6,0x32e4,0x32e3,0x32e2,0x32e1,
+ 0x32de,0x32dd,0x32dc,0x32db,0x32da,0x32d7,0x32d6,0x32d5,0x32d4,0x32d2,0x32d0,0x32cf,0x32ce,0x32cc,0x32cb,0x32c9,
+ 0x32c8,0x32c6,0x32c5,0x32c4,0x32c2,0x32c0,0x32bf,0x32be,0x32bd,0x32ba,0x32b9,0x32b8,0x32b7,0x32b6,0x32b3,0x32b2,
+ 0x32b1,0x32b0,0x32ae,0x32ac,0x32ab,0x32aa,0x32a8,0x32a7,0x32a5,0x32a4,0x32a2,0x32a1,0x32a0,0x329e,0x329c,0x329b,
+ 0x329a,0x3298,0x3297,0x3295,0x3294,0x3293,0x3291,0x328f,0x328e,0x328d,0x328c,0x3289,0x3288,0x3287,0x3286,0x3285,
+ 0x3282,0x3281,0x3280,0x327f,0x327e,0x327b,0x327a,0x3279,0x3278,0x3276,0x3274,0x3273,0x3272,0x3270,0x326f,0x326d,
+ 0x326c,0x326a,0x3269,0x3268,0x3266,0x3264,0x3263,0x3262,0x3261,0x325e,0x325d,0x325c,0x325b,0x325a,0x3258,0x3256,
+ 0x3255,0x3254,0x3252,0x3251,0x324f,0x324e,0x324d,0x324b,0x324a,0x3248,0x3247,0x3245,0x3244,0x3243,0x3241,0x323f,
+ 0x323e,0x323d,0x323c,0x3239,0x3238,0x3237,0x3236,0x3235,0x3232,0x3231,0x3230,0x322f,0x322d,0x322b,0x322a,0x3229,
+ 0x3227,0x3226,0x3224,0x3223,0x3221,0x3220,0x321f,0x321e,0x321b,0x321a,0x3219,0x3218,0x3217,0x3214,0x3213,0x3212,
+ 0x3211,0x3210,0x320d,0x320c,0x320b,0x320a,0x3208,0x3206,0x3205,0x3204,0x3202,0x3201,0x31ff,0x31fe,0x31fc,0x31fb,
+ 0x31fa,0x31f8,0x31f6,0x31f5,0x31f4,0x31f3,0x31f0,0x31ef,0x31ee,0x31ed,0x31ec,0x31e9,0x31e8,0x31e7,0x31e6,0x31e5,
+ 0x31e3,0x31e1,0x31e0,0x31df,0x31dd,0x31dc,0x31da,0x31d9,0x31d7,0x31d6,0x31d5,0x31d3,0x31d1,0x31d0,0x31cf,0x31ce,
+ 0x31cb,0x31ca,0x31c9,0x31c8,0x31c7,0x31c4,0x31c3,0x31c2,0x31c1,0x31bf,0x31bd,0x31bc,0x31bb,0x31b9,0x31b8,0x31b6,
+ 0x31b5,0x31b4,0x31b2,0x31b1,0x31af,0x31ae,0x31ac,0x31ab,0x31aa,0x31a8,0x31a6,0x31a5,0x31a4,0x31a3,0x31a2,0x319f,
+ 0x319e,0x319d,0x319c,0x319a,0x3198,0x3197,0x3196,0x3194,0x3193,0x3191,0x3190,0x318e,0x318d,0x318c,0x318a,0x3188,
+ 0x3187,0x3186,0x3185,0x3182,0x3181,0x3180,0x317f,0x317e,0x317b,0x317a,0x3179,0x3178,0x3177,0x3174,0x3173,0x3172,
+ 0x3171,0x316f,0x316d,0x316c,0x316b,0x3169,0x3168,0x3167,0x3165,0x3163,0x3162,0x3161,0x3160,0x315d,0x315c,0x315b,
+ 0x315a,0x3159,0x3156,0x3155,0x3154,0x3153,0x3151,0x314f,0x314e,0x314d,0x314c,0x314a,0x3148,0x3147,0x3146,0x3144,
+ 0x3143,0x3141,0x3140,0x313e,0x313d,0x313c,0x313a,0x3138,0x3137,0x3136,0x3135,0x3132,0x3131,0x3130,0x312f,0x312e,
+ 0x312c,0x312b,0x312a,0x3129,0x3126,0x3125,0x3124,0x3123,0x3121,0x3120,0x311e,0x311d,0x311b,0x311a,0x3119,0x3117,
+ 0x3115,0x3114,0x3113,0x3112,0x310f,0x310e,0x310d,0x310c,0x310b,0x3108,0x3107,0x3106,0x3105,0x3104,0x3102,0x3100,
+ 0x30ff,0x30fe,0x30fc,0x30fb,0x30f9,0x30f8,0x30f6,0x30f5,0x30f4,0x30f2,0x30f1,0x30ef,0x30ee,0x30ed,0x30eb,0x30e9,
+ 0x30e8,0x30e7,0x30e6,0x30e3,0x30e2,0x30e1,0x30e0,0x30df,0x30dd,0x30db,0x30da,0x30d9,0x30d7,0x30d6,0x30d4,0x30d3,
+ 0x30d2,0x30d0,0x30cf,0x30cd,0x30cc,0x30ca,0x30c9,0x30c8,0x30c6,0x30c4,0x30c3,0x30c2,0x30c1,0x30c0,0x30bd,0x30bc,
+ 0x30bb,0x30ba,0x30b9,0x30b6,0x30b5,0x30b4,0x30b3,0x30b1,0x30af,0x30ae,0x30ad,0x30ab,0x30aa,0x30a8,0x30a7,0x30a5,
+ 0x30a4,0x30a3,0x30a1,0x309f,0x309e,0x309d,0x309c,0x309b,0x3098,0x3097,0x3096,0x3095,0x3094,0x3091,0x3090,0x308f,
+ 0x308e,0x308c,0x308a,0x3089,0x3088,0x3086,0x3085,0x3083,0x3082,0x3081,0x307f,0x307e,0x307d,0x307b,0x3079,0x3078,
+ 0x3077,0x3076,0x3074,0x3072,0x3071,0x3070,0x306e,0x306d,0x306c,0x306a,0x3069,0x3067,0x3066,0x3065,0x3063,0x3061,
+ 0x3060,0x305f,0x305e,0x305b,0x305a,0x3059,0x3058,0x3057,0x3056,0x3053,0x3052,0x3051,0x3050,0x304e,0x304c,0x304b,
+ 0x304a,0x3048,0x3047,0x3045,0x3044,0x3043,0x3041,0x3040,0x303f,0x303d,0x303b,0x303a,0x3039,0x3038,0x3035,0x3034,
+ 0x3033,0x3032,0x3031,0x302e,0x302d,0x302c,0x302b,0x302a,0x3028,0x3026,0x3025,0x3024,0x3022,0x3021,0x301f,0x301e,
+ 0x301d,0x301b,0x301a,0x3018,0x3017,0x3015,0x3014,0x3013,0x3012,0x300f,0x300e,0x300d,0x300c,0x300b,0x3008,0x3007,
+ 0x3006,0x3005,0x3004,0x3001,0x3000,0x2fff,0x2ffe,0x2ffc,0x2ffb,0x2ff9,0x2ff8,0x2ff7,0x2ff5,0x2ff4,0x2ff2,0x2ff1,
+ 0x2fef,0x2fee,0x2fed,0x2feb,0x2fe9,0x2fe8,0x2fe7,0x2fe6,0x2fe5,0x2fe2,0x2fe1,0x2fe0,0x2fdf,0x2fde,0x2fdb,0x2fda,
+ 0x2fd9,0x2fd8,0x2fd6,0x2fd4,0x2fd3,0x2fd2,0x2fd1,0x2fcf,0x2fce,0x2fcc,0x2fcb,0x2fc9,0x2fc8,0x2fc7,0x2fc5,0x2fc3,
+ 0x2fc2,0x2fc1,0x2fbf,0x2fbd,0x2fbc,0x2fbb,0x2fba,0x2fb7,0x2fb6,0x2fb5,0x2fb4,0x2fb3,0x2fb2,0x2faf,0x2fae,0x2fad,
+ 0x2fac,0x2faa,0x2fa8,0x2fa7,0x2fa6,0x2fa5,0x2fa3,0x2fa2,0x2fa0,0x2f9f,0x2f9d,0x2f9c,0x2f9b,0x2f99,0x2f98,0x2f96,
+ 0x2f95,0x2f94,0x2f93,0x2f90,0x2f8f,0x2f8e,0x2f8d,0x2f8c,0x2f89,0x2f88,0x2f87,0x2f86,0x2f85,0x2f82,0x2f81,0x2f80,
+ 0x2f7f,0x2f7d,0x2f7c,0x2f7a,0x2f79,0x2f78,0x2f76,0x2f75,0x2f73,0x2f72,0x2f70,0x2f6f,0x2f6e,0x2f6d,0x2f6b,0x2f69,
+ 0x2f68,0x2f67,0x2f66,0x2f63,0x2f62,0x2f61,0x2f60,0x2f5f,0x2f5e,0x2f5b,0x2f5a,0x2f59,0x2f58,0x2f56,0x2f54,0x2f53,
+ 0x2f52,0x2f50,0x2f4f,0x2f4e,0x2f4c,0x2f4b,0x2f49,0x2f48,0x2f47,0x2f45,0x2f43,0x2f42,0x2f41,0x2f40,0x2f3e,0x2f3c,
+ 0x2f3b,0x2f3a,0x2f39,0x2f38,0x2f35,0x2f34,0x2f33,0x2f32,0x2f31,0x2f2e,0x2f2d,0x2f2c,0x2f2b,0x2f29,0x2f28,0x2f26,
+ 0x2f25,0x2f24,0x2f22,0x2f21,0x2f1f,0x2f1e,0x2f1c,0x2f1b,0x2f1a,0x2f19,0x2f16,0x2f15,0x2f14,0x2f13,0x2f12,0x2f0f,
+ 0x2f0e,0x2f0d,0x2f0c,0x2f0b,0x2f09,0x2f07,0x2f06,0x2f05,0x2f04,0x2f02,0x2f00,0x2eff,0x2efe,0x2efc,0x2efb,0x2ef9,
+ 0x2ef8,0x2ef7,0x2ef5,0x2ef4,0x2ef3,0x2ef1,0x2eef,0x2eee,0x2eed,0x2eec,0x2eea,0x2ee8,0x2ee7,0x2ee6,0x2ee5,0x2ee4,
+ 0x2ee1,0x2ee0,0x2edf,0x2ede,0x2edc,0x2eda,0x2ed9,0x2ed8,0x2ed7,0x2ed5,0x2ed4,0x2ed2,0x2ed1,0x2ecf,0x2ece,0x2ecd,
+ 0x2ecb,0x2eca,0x2ec8,0x2ec7,0x2ec6,0x2ec5,0x2ec2,0x2ec1,0x2ec0,0x2ebf,0x2ebe,0x2ebb,0x2eba,0x2eb9,0x2eb8,0x2eb7,
+ 0x2eb5,0x2eb3,0x2eb2,0x2eb1,0x2eb0,0x2eae,0x2eac,0x2eab,0x2eaa,0x2ea8,0x2ea7,0x2ea5,0x2ea4,0x2ea2,0x2ea1,0x2ea0,
+ 0x2e9f,0x2e9d,0x2e9b,0x2e9a,0x2e99,0x2e98,0x2e95,0x2e94,0x2e93,0x2e92,0x2e91,0x2e90,0x2e8d,0x2e8c,0x2e8b,0x2e8a,
+ 0x2e88,0x2e86,0x2e85,0x2e84,0x2e83,0x2e81,0x2e80,0x2e7e,0x2e7d,0x2e7b,0x2e7a,0x2e79,0x2e77,0x2e76,0x2e74,0x2e73,
+ 0x2e72,0x2e71,0x2e6e,0x2e6d,0x2e6c,0x2e6b,0x2e6a,0x2e67,0x2e66,0x2e65,0x2e64,0x2e63,0x2e60,0x2e5f,0x2e5e,0x2e5d,
+ 0x2e5c,0x2e5a,0x2e58,0x2e57,0x2e56,0x2e55,0x2e53,0x2e51,0x2e50,0x2e4f,0x2e4e,0x2e4d,0x2e4a,0x2e49,0x2e48,0x2e47,
+ 0x2e46,0x2e43,0x2e42,0x2e41,0x2e40,0x2e3f,0x2e3d,0x2e3b,0x2e3a,0x2e39,0x2e37,0x2e36,0x2e34,0x2e33,0x2e32,0x2e30,
+ 0x2e2f,0x2e2e,0x2e2c,0x2e2a,0x2e29,0x2e28,0x2e27,0x2e25,0x2e23,0x2e22,0x2e21,0x2e20,0x2e1f,0x2e1c,0x2e1b,0x2e1a,
+ 0x2e19,0x2e18,0x2e16,0x2e14,0x2e13,0x2e12,0x2e11,0x2e0f,0x2e0d,0x2e0c,0x2e0b,0x2e09,0x2e08,0x2e07,0x2e05,0x2e04,
+ 0x2e02,0x2e01,0x2e00,0x2dfe,0x2dfc,0x2dfb,0x2dfa,0x2df9,0x2df8,0x2df5,0x2df4,0x2df3,0x2df2,0x2df1,0x2dee,0x2ded,
+ 0x2dec,0x2deb,0x2dea,0x2de8,0x2de6,0x2de5,0x2de4,0x2de3,0x2de1,0x2de0,0x2dde,0x2ddd,0x2ddb,0x2dda,0x2dd9,0x2dd7,
+ 0x2dd6,0x2dd4,0x2dd3,0x2dd2,0x2dd1,0x2dce,0x2dcd,0x2dcc,0x2dcb,0x2dca,0x2dc7,0x2dc6,0x2dc5,0x2dc4,0x2dc3,0x2dc1,
+ 0x2dbf,0x2dbe,0x2dbd,0x2dbc,0x2dba,0x2db8,0x2db7,0x2db6,0x2db5,0x2db3,0x2db2,0x2db0,0x2daf,0x2dad,0x2dac,0x2dab,
+ 0x2da9,0x2da8,0x2da6,0x2da5,0x2da3,0x2da2,0x2da1,0x2da0,0x2d9e,0x2d9c,0x2d9b,0x2d9a,0x2d99,0x2d97,0x2d95,0x2d94,
+ 0x2d93,0x2d92,0x2d91,0x2d8e,0x2d8d,0x2d8c,0x2d8b,0x2d8a,0x2d88,0x2d86,0x2d85,0x2d84,0x2d83,0x2d81,0x2d7f,0x2d7e,
+ 0x2d7d,0x2d7b,0x2d7a,0x2d79,0x2d77,0x2d76,0x2d74,0x2d73,0x2d72,0x2d71,0x2d6f,0x2d6d,0x2d6c,0x2d6b,0x2d6a,0x2d67,
+ 0x2d66,0x2d65,0x2d64,0x2d63,0x2d62,0x2d5f,0x2d5e,0x2d5d,0x2d5c,0x2d5b,0x2d59,0x2d57,0x2d56,0x2d55,0x2d53,0x2d52,
+ 0x2d51,0x2d4f,0x2d4e,0x2d4c,0x2d4b,0x2d4a,0x2d48,0x2d47,0x2d45,0x2d44,0x2d43,0x2d42,0x2d3f,0x2d3e,0x2d3d,0x2d3c,
+ 0x2d3b,0x2d3a,0x2d37,0x2d36,0x2d35,0x2d34,0x2d33,0x2d30,0x2d2f,0x2d2e,0x2d2d,0x2d2c,0x2d2a,0x2d28,0x2d27,0x2d26,
+ 0x2d24,0x2d23,0x2d22,0x2d20,0x2d1f,0x2d1d,0x2d1c,0x2d1b,0x2d19,0x2d18,0x2d16,0x2d15,0x2d14,0x2d13,0x2d10,0x2d0f,
+ 0x2d0e,0x2d0d,0x2d0c,0x2d0b,0x2d08,0x2d07,0x2d06,0x2d05,0x2d04,0x2d01,0x2d00,0x2cff,0x2cfe,0x2cfc,0x2cfb,0x2cf9,
+ 0x2cf8,0x2cf7,0x2cf5,0x2cf4,0x2cf3,0x2cf1,0x2cf0,0x2cee,0x2ced,0x2cec,0x2cea,0x2ce8,0x2ce7,0x2ce6,0x2ce5,0x2ce4,
+ 0x2ce1,0x2ce0,0x2cdf,0x2cde,0x2cdd,0x2cdc,0x2cd9,0x2cd8,0x2cd7,0x2cd6,0x2cd4,0x2cd3,0x2cd1,0x2cd0,0x2ccf,0x2ccd,
+ 0x2ccc,0x2cca,0x2cc9,0x2cc8,0x2cc6,0x2cc5,0x2cc4,0x2cc2,0x2cc1,0x2cbf,0x2cbe,0x2cbd,0x2cbc,0x2cb9,0x2cb8,0x2cb7,
+ 0x2cb6,0x2cb5,0x2cb2,0x2cb1,0x2cb0,0x2caf,0x2cae,0x2cad,0x2caa,0x2ca9,0x2ca8,0x2ca7,0x2ca5,0x2ca4,0x2ca2,0x2ca1,
+ 0x2ca0,0x2c9e,0x2c9d,0x2c9b,0x2c9a,0x2c99,0x2c97,0x2c96,0x2c95,0x2c93,0x2c91,0x2c90,0x2c8f,0x2c8e,0x2c8d,0x2c8a,
+ 0x2c89,0x2c88,0x2c87,0x2c86,0x2c83,0x2c82,0x2c81,0x2c80,0x2c7f,0x2c7d,0x2c7b,0x2c7a,0x2c79,0x2c78,0x2c76,0x2c75,
+ 0x2c73,0x2c72,0x2c71,0x2c6f,0x2c6e,0x2c6c,0x2c6b,0x2c6a,0x2c68,0x2c67,0x2c66,0x2c64,0x2c62,0x2c61,0x2c60,0x2c5f,
+ 0x2c5e,0x2c5b,0x2c5a,0x2c59,0x2c58,0x2c57,0x2c56,0x2c53,0x2c52,0x2c51,0x2c50,0x2c4e,0x2c4c,0x2c4b,0x2c4a,0x2c49,
+ 0x2c47,0x2c46,0x2c45,0x2c43,0x2c42,0x2c40,0x2c3f,0x2c3e,0x2c3d,0x2c3b,0x2c39,0x2c38,0x2c37,0x2c36,0x2c35,0x2c32,
+ 0x2c31,0x2c30,0x2c2f,0x2c2e,0x2c2d,0x2c2a,0x2c29,0x2c28,0x2c27,0x2c26,0x2c24,0x2c22,0x2c21,0x2c20,0x2c1e,0x2c1d,
+ 0x2c1c,0x2c1a,0x2c19,0x2c17,0x2c16,0x2c15,0x2c13,0x2c12,0x2c10,0x2c0f,0x2c0e,0x2c0d,0x2c0b,0x2c09,0x2c08,0x2c07,
+ 0x2c06,0x2c05,0x2c02,0x2c01,0x2c00,0x2bff,0x2bfe,0x2bfc,0x2bfa,0x2bf9,0x2bf8,0x2bf7,0x2bf5,0x2bf4,0x2bf2,0x2bf1,
+ 0x2bf0,0x2bee,0x2bed,0x2beb,0x2bea,0x2be9,0x2be7,0x2be6,0x2be5,0x2be3,0x2be2,0x2be0,0x2bdf,0x2bde,0x2bdd,0x2bdb,
+ 0x2bd9,0x2bd8,0x2bd7,0x2bd6,0x2bd5,0x2bd2,0x2bd1,0x2bd0,0x2bcf,0x2bce,0x2bcc,0x2bca,0x2bc9,0x2bc8,0x2bc7,0x2bc5,
+ 0x2bc4,0x2bc2,0x2bc1,0x2bc0,0x2bbe,0x2bbd,0x2bbb,0x2bba,0x2bb9,0x2bb7,0x2bb6,0x2bb5,0x2bb3,0x2bb1,0x2bb0,0x2baf,
+ 0x2bae,0x2bad,0x2baa,0x2ba9,0x2ba8,0x2ba7,0x2ba6,0x2ba5,0x2ba2,0x2ba1,0x2ba0,0x2b9f,0x2b9e,0x2b9c,0x2b9a,0x2b99,
+ 0x2b98,0x2b97,0x2b94,0x2b93,0x2b92,0x2b91,0x2b90,0x2b8e,0x2b8c,0x2b8b,0x2b8a,0x2b89,0x2b87,0x2b86,0x2b84,0x2b83,
+ 0x2b82,0x2b80,0x2b7f,0x2b7e,0x2b7c,0x2b7b,0x2b79,0x2b78,0x2b77,0x2b76,0x2b74,0x2b72,0x2b71,0x2b70,0x2b6f,0x2b6e,
+ 0x2b6b,0x2b6a,0x2b69,0x2b68,0x2b67,0x2b66,0x2b63,0x2b62,0x2b61,0x2b60,0x2b5f,0x2b5d,0x2b5b,0x2b5a,0x2b59,0x2b58,
+ 0x2b56,0x2b55,0x2b53,0x2b52,0x2b51,0x2b4f,0x2b4e,0x2b4d,0x2b4b,0x2b4a,0x2b48,0x2b47,0x2b46,0x2b45,0x2b43,0x2b41,
+ 0x2b40,0x2b3f,0x2b3e,0x2b3c,0x2b3a,0x2b39,0x2b38,0x2b37,0x2b36,0x2b33,0x2b32,0x2b31,0x2b30,0x2b2f,0x2b2e,0x2b2b,
+ 0x2b2a,0x2b29,0x2b28,0x2b27,0x2b25,0x2b23,0x2b22,0x2b21,0x2b20,0x2b1e,0x2b1d,0x2b1b,0x2b1a,0x2b19,0x2b17,0x2b16,
+ 0x2b15,0x2b13,0x2b12,0x2b10,0x2b0f,0x2b0e,0x2b0d,0x2b0b,0x2b09,0x2b08,0x2b07,0x2b06,0x2b05,0x2b02,0x2b01,0x2b00,
+ 0x2aff,0x2afe,0x2afc,0x2afa,0x2af9,0x2af8,0x2af7,0x2af5,0x2af4,0x2af2,0x2af1,0x2af0,0x2aee,0x2aed,0x2aec,0x2aea,
+ 0x2ae9,0x2ae7,0x2ae6,0x2ae5,0x2ae4,0x2ae2,0x2ae0,0x2adf,0x2ade,0x2add,0x2adc,0x2ad9,0x2ad8,0x2ad7,0x2ad6,0x2ad5,
+ 0x2ad4,0x2ad1,0x2ad0,0x2acf,0x2ace,0x2acd,0x2acb,0x2ac9,0x2ac8,0x2ac7,0x2ac6,0x2ac4,0x2ac3,0x2ac1,0x2ac0,0x2abf,
+ 0x2abd,0x2abc,0x2abb,0x2ab9,0x2ab8,0x2ab6,0x2ab5,0x2ab4,0x2ab3,0x2ab1,0x2aaf,0x2aae,0x2aad,0x2aac,0x2aab,0x2aa8,
+ 0x2aa7,0x2aa6,0x2aa5,0x2aa4,0x2aa3,0x2aa0,0x2a9f,0x2a9e,0x2a9d,0x2a9c,0x2a9a,0x2a98,0x2a97,0x2a96,0x2a95,0x2a93,
+ 0x2a92,0x2a90,0x2a8f,0x2a8e,0x2a8c,0x2a8b,0x2a89,0x2a88,0x2a87,0x2a85,0x2a84,0x2a83,0x2a81,0x2a80,0x2a7e,0x2a7d,
+ 0x2a7c,0x2a7b,0x2a79,0x2a77,0x2a76,0x2a75,0x2a74,0x2a73,0x2a70,0x2a6f,0x2a6e,0x2a6d,0x2a6c,0x2a6b,0x2a68,0x2a67,
+ 0x2a66,0x2a65,0x2a63,0x2a62,0x2a60,0x2a5f,0x2a5e,0x2a5c,0x2a5b,0x2a5a,0x2a58,0x2a57,0x2a55,0x2a54,0x2a53,0x2a52,
+ 0x2a50,0x2a4e,0x2a4d,0x2a4c,0x2a4b,0x2a4a,0x2a47,0x2a46,0x2a45,0x2a44,0x2a43,0x2a42,0x2a3f,0x2a3e,0x2a3d,0x2a3c,
+ 0x2a3b,0x2a39,0x2a38,0x2a37,0x2a36,0x2a34,0x2a33,0x2a31,0x2a30,0x2a2f,0x2a2d,0x2a2c,0x2a2b,0x2a29,0x2a28,0x2a26,
+ 0x2a25,0x2a24,0x2a23,0x2a21,0x2a1f,0x2a1e,0x2a1d,0x2a1c,0x2a1b,0x2a18,0x2a17,0x2a16,0x2a15,0x2a14,0x2a13,0x2a10,
+ 0x2a0f,0x2a0e,0x2a0d,0x2a0c,0x2a0a,0x2a08,0x2a07,0x2a06,0x2a05,0x2a03,0x2a02,0x2a00,0x29ff,0x29fe,0x29fd,0x29fb,
+ 0x29fa,0x29f8,0x29f7,0x29f6,0x29f4,0x29f3,0x29f2,0x29f0,0x29ef,0x29ed,0x29ec,0x29eb,0x29ea,0x29e8,0x29e6,0x29e5,
+ 0x29e4,0x29e3,0x29e2,0x29e1,0x29de,0x29dd,0x29dc,0x29db,0x29da,0x29d8,0x29d6,0x29d5,0x29d4,0x29d3,0x29d1,0x29d0,
+ 0x29ce,0x29cd,0x29cc,0x29ca,0x29c9,0x29c8,0x29c6,0x29c5,0x29c3,0x29c2,0x29c1,0x29c0,0x29be,0x29bc,0x29bb,0x29ba,
+ 0x29b9,0x29b8,0x29b6,0x29b4,0x29b3,0x29b2,0x29b1,0x29b0,0x29ad,0x29ac,0x29ab,0x29aa,0x29a9,0x29a8,0x29a5,0x29a4,
+ 0x29a3,0x29a2,0x29a1,0x299f,0x299d,0x299c,0x299b,0x299a,0x2998,0x2997,0x2995,0x2994,0x2993,0x2991,0x2990,0x298f,
+ 0x298e,0x298c,0x298a,0x2989,0x2988,0x2987,0x2985,0x2984,0x2982,0x2981,0x2980,0x297e,0x297d,0x297c,0x297b,0x2979,
+ 0x2977,0x2976,0x2975,0x2974,0x2973,0x2971,0x296f,0x296e,0x296d,0x296c,0x296b,0x2968,0x2967,0x2966,0x2965,0x2964,
+ 0x2963,0x2960,0x295f,0x295e,0x295d,0x295c,0x295a,0x2959,0x2957,0x2956,0x2955,0x2954,0x2952,0x2951,0x294f,0x294e,
+ 0x294d,0x294b,0x294a,0x2949,0x2947,0x2946,0x2944,0x2943,0x2942,0x2941,0x293f,0x293d,0x293c,0x293b,0x293a,0x2939,
+ 0x2938,0x2935,0x2934,0x2933,0x2932,0x2931,0x2930,0x292d,0x292c,0x292b,0x292a,0x2929,0x2927,0x2925,0x2924,0x2923,
+ 0x2922,0x2920,0x291f,0x291d,0x291c,0x291b,0x291a,0x2918,0x2917,0x2915,0x2914,0x2913,0x2911,0x2910,0x290f,0x290e,
+ 0x290c,0x290a,0x2909,0x2908,0x2907,0x2906,0x2903,0x2902,0x2901,0x2900,0x28ff,0x28fe,0x28fb,0x28fa,0x28f9,0x28f8,
+ 0x28f7,0x28f6,0x28f3,0x28f2,0x28f1,0x28f0,0x28ef,0x28ed,0x28ec,0x28ea,0x28e9,0x28e8,0x28e6,0x28e5,0x28e4,0x28e2,
+ 0x28e1,0x28e0,0x28de,0x28dd,0x28dc,0x28da,0x28d9,0x28d7,0x28d6,0x28d5,0x28d4,0x28d2,0x28d0,0x28cf,0x28ce,0x28cd,
+ 0x28cc,0x28cb,0x28c8,0x28c7,0x28c6,0x28c5,0x28c4,0x28c3,0x28c0,0x28bf,0x28be,0x28bd,0x28bc,0x28ba,0x28b8,0x28b7,
+ 0x28b6,0x28b5,0x28b3,0x28b2,0x28b0,0x28af,0x28ae,0x28ac,0x28ab,0x28aa,0x28a9,0x28a7,0x28a6,0x28a4,0x28a3,0x28a2,
+ 0x28a1,0x289f,0x289d,0x289c,0x289b,0x289a,0x2899,0x2896,0x2895,0x2894,0x2893,0x2892,0x2891,0x288e,0x288d,0x288c,
+ 0x288b,0x288a,0x2889,0x2887,0x2885,0x2884,0x2883,0x2882,0x2880,0x287f,0x287d,0x287c,0x287b,0x2879,0x2878,0x2877,
+ 0x2875,0x2874,0x2872,0x2871,0x2870,0x286f,0x286d,0x286c,0x286a,0x2869,0x2868,0x2867,0x2866,0x2863,0x2862,0x2861,
+ 0x2860,0x285f,0x285e,0x285b,0x285a,0x2859,0x2858,0x2857,0x2855,0x2853,0x2852,0x2851,0x2850,0x284e,0x284d,0x284b,
+ 0x284a,0x2849,0x2848,0x2846,0x2845,0x2844,0x2842,0x2841,0x283f,0x283e,0x283d,0x283c,0x283a,0x2838,0x2837,0x2836,
+ 0x2835,0x2834,0x2833,0x2832,0x282f,0x282e,0x282d,0x282c,0x282b,0x282a,0x2827,0x2826,0x2825,0x2824,0x2823,0x2822,
+ 0x2820,0x281e,0x281d,0x281c,0x281b,0x2819,0x2818,0x2816,0x2815,0x2814,0x2813,0x2811,0x2810,0x280e,0x280d,0x280c,
+ 0x280a,0x2809,0x2808,0x2807,0x2805,0x2803,0x2802,0x2801,0x2800,0x27ff,0x27fd,0x27fb,0x27fa,0x27f9,0x27f8,0x27f7,
+ 0x27f6,0x27f3,0x27f2,0x27f1,0x27f0,0x27ef,0x27ee,0x27eb,0x27ea,0x27e9,0x27e8,0x27e7,0x27e5,0x27e3,0x27e2,0x27e1,
+ 0x27e0,0x27de,0x27dd,0x27dc,0x27da,0x27d9,0x27d8,0x27d6,0x27d5,0x27d4,0x27d2,0x27d1,0x27cf,0x27ce,0x27cd,0x27cc,
+ 0x27cb,0x27c9,0x27c7,0x27c6,0x27c5,0x27c4,0x27c3,0x27c0,0x27bf,0x27be,0x27bd,0x27bc,0x27bb,0x27b8,0x27b7,0x27b6,
+ 0x27b5,0x27b4,0x27b3,0x27b1,0x27af,0x27ae,0x27ad,0x27ac,0x27aa,0x27a9,0x27a7,0x27a6,0x27a5,0x27a4,0x27a2,0x27a1,
+ 0x27a0,0x279e,0x279d,0x279b,0x279a,0x2799,0x2798,0x2796,0x2794,0x2793,0x2792,0x2791,0x2790,0x278e,0x278c,0x278b,
+ 0x278a,0x2789,0x2787,0x2786,0x2785,0x2783,0x2782,0x2781,0x2780,0x277e,0x277c,0x277b,0x277a,0x2779,0x2778,0x2776,
+ 0x2774,0x2773,0x2772,0x2771,0x2770,0x276f,0x276c,0x276b,0x276a,0x2769,0x2768,0x2767,0x2764,0x2763,0x2762,0x2761,
+ 0x2760,0x275e,0x275d,0x275b,0x275a,0x2759,0x2758,0x2756,0x2755,0x2754,0x2752,0x2751,0x2750,0x274e,0x274d,0x274c,
+ 0x274a,0x2749,0x2747,0x2746,0x2745,0x2744,0x2743,0x2741,0x273f,0x273e,0x273d,0x273c,0x273b,0x2738,0x2737,0x2736,
+ 0x2735,0x2734,0x2733,0x2732,0x272f,0x272e,0x272d,0x272c,0x272b,0x2729,0x2727,0x2726,0x2725,0x2724,0x2723,0x2721,
+ 0x2720,0x271e,0x271d,0x271c,0x271b,0x2719,0x2718,0x2716,0x2715,0x2714,0x2712,0x2711,0x2710,0x270f,0x270d,0x270c,
+ 0x270a,0x2709,0x2708,0x2707,0x2706,0x2703,0x2702,0x2701,0x2700,0x26ff,0x26fe,0x26fb,0x26fa,0x26f9,0x26f8,0x26f7,
+ 0x26f6,0x26f4,0x26f2,0x26f1,0x26f0,0x26ef,0x26ee,0x26ec,0x26ea,0x26e9,0x26e8,0x26e7,0x26e5,0x26e4,0x26e3,0x26e1,
+ 0x26e0,0x26df,0x26dd,0x26dc,0x26db,0x26d9,0x26d8,0x26d7,0x26d5,0x26d4,0x26d3,0x26d2,0x26d0,0x26ce,0x26cd,0x26cc,
+ 0x26cb,0x26ca,0x26c9,0x26c6,0x26c5,0x26c4,0x26c3,0x26c2,0x26c1,0x26be,0x26bd,0x26bc,0x26bb,0x26ba,0x26b9,0x26b7,
+ 0x26b5,0x26b4,0x26b3,0x26b2,0x26b0,0x26af,0x26ad,0x26ac,0x26ab,0x26aa,0x26a8,0x26a7,0x26a6,0x26a4,0x26a3,0x26a2,
+ 0x26a0,0x269f,0x269e,0x269c,0x269b,0x2699,0x2698,0x2697,0x2696,0x2695,0x2693,0x2691,0x2690,0x268f,0x268e,0x268d,
+ 0x268c,0x2689,0x2688,0x2687,0x2686,0x2685,0x2684,0x2681,0x2680,0x267f,0x267e,0x267d,0x267b,0x267a,0x2678,0x2677,
+ 0x2676,0x2675,0x2673,0x2672,0x2670,0x266f,0x266e,0x266d,0x266b,0x266a,0x2669,0x2667,0x2666,0x2664,0x2663,0x2662,
+ 0x2661,0x265f,0x265e,0x265c,0x265b,0x265a,0x2659,0x2658,0x2655,0x2654,0x2653,0x2652,0x2651,0x2650,0x264d,0x264c,
+ 0x264b,0x264a,0x2649,0x2648,0x2646,0x2644,0x2643,0x2642,0x2641,0x2640,0x263e,0x263d,0x263b,0x263a,0x2639,0x2637,
+ 0x2637,0x2635,0x2634,0x2633,0x2631,0x2630,0x262f,0x262d,0x262c,0x262a,0x2629,0x2628,0x2627,0x2626,0x2624,0x2622,
+ 0x2621,0x2620,0x261f,0x261e,0x261d,0x261a,0x2619,0x2618,0x2617,0x2616,0x2615,0x2612,0x2611,0x2610,0x260f,0x260e,
+ 0x260d,0x260b,0x2609,0x2608,0x2607,0x2606,0x2605,0x2603,0x2602,0x2600,0x25ff,0x25fe,0x25fd,0x25fb,0x25fa,0x25f9,
+ 0x25f7,0x25f6,0x25f5,0x25f3,0x25f2,0x25f1,0x25ef,0x25ee,0x25ec,0x25eb,0x25ea,0x25e9,0x25e8,0x25e6,0x25e4,0x25e3,
+ 0x25e2,0x25e1,0x25e0,0x25df,0x25dc,0x25db,0x25da,0x25d9,0x25d8,0x25d7,0x25d6,0x25d3,0x25d2,0x25d1,0x25d0,0x25cf,
+ 0x25cd,0x25cb,0x25ca,0x25c9,0x25c8,0x25c7,0x25c5,0x25c4,0x25c2,0x25c1,0x25c0,0x25bf,0x25bd,0x25bc,0x25bb,0x25b9,
+ 0x25b8,0x25b7,0x25b5,0x25b4,0x25b3,0x25b2,0x25b0,0x25ae,0x25ad,0x25ac,0x25ab,0x25aa,0x25a8,0x25a6,0x25a5,0x25a4,
+ 0x25a3,0x25a2,0x25a1,0x259e,0x259d,0x259c,0x259b,0x259a,0x2599,0x2597,0x2595,0x2594,0x2593,0x2592,0x2591,0x258f,
+ 0x258e,0x258d,0x258a,0x2589,0x2588,0x2587,0x2586,0x2585,0x2584,0x2581,0x2580,0x257f,0x257e,0x257d,0x257c,0x257a,
+ 0x2578,0x2577,0x2576,0x2575,0x2574,0x2572,0x2571,0x256f,0x256e,0x256d,0x256c,0x256a,0x2569,0x2568,0x2566,0x2565,
+ 0x2564,0x2562,0x2561,0x2560,0x255f,0x255d,0x255c,0x255a,0x2559,0x2558,0x2557,0x2556,0x2554,0x2552,0x2551,0x2550,
+ 0x254f,0x254e,0x254d,0x254a,0x2549,0x2548,0x2547,0x2546,0x2545,0x2544,0x2541,0x2540,0x253f,0x253e,0x253d,0x253c,
+ 0x253a,0x2538,0x2537,0x2536,0x2535,0x2534,0x2532,0x2530,0x252f,0x252e,0x252d,0x252b,0x252a,0x2529,0x2527,0x2526,
+ 0x2525,0x2523,0x2522,0x2521,0x2520,0x251e,0x251d,0x251b,0x251a,0x2519,0x2518,0x2517,0x2515,0x2513,0x2512,0x2511,
+ 0x2510,0x250f,0x250e,0x250b,0x250a,0x2509,0x2508,0x2507,0x2506,0x2505,0x2502,0x2501,0x2500,0x24ff,0x24fe,0x24fd,
+ 0x24fb,0x24f9,0x24f8,0x24f7,0x24f6,0x24f5,0x24f3,0x24f2,0x24f0,0x24ef,0x24ee,0x24ed,0x24eb,0x24ea,0x24e9,0x24e7,
+ 0x24e6,0x24e5,0x24e3,0x24e2,0x24e1,0x24e0,0x24de,0x24dd,0x24db,0x24da,0x24d9,0x24d8,0x24d7,0x24d5,0x24d3,0x24d2,
+ 0x24d1,0x24d0,0x24cf,0x24ce,0x24cb,0x24ca,0x24c9,0x24c8,0x24c7,0x24c6,0x24c3,0x24c2,0x24c1,0x24c0,0x24bf,0x24be,
+ 0x24bc,0x24ba,0x24b9,0x24b8,0x24b7,0x24b6,0x24b4,0x24b3,0x24b1,0x24b0,0x24af,0x24ae,0x24ac,0x24ab,0x24aa,0x24a8,
+ 0x24a7,0x24a6,0x24a4,0x24a3,0x24a2,0x24a1,0x249f,0x249e,0x249c,0x249b,0x249a,0x2499,0x2498,0x2496,0x2494,0x2493,
+ 0x2492,0x2491,0x2490,0x248f,0x248c,0x248b,0x248a,0x2489,0x2488,0x2487,0x2486,0x2483,0x2482,0x2481,0x2480,0x247f,
+ 0x247e,0x247c,0x247a,0x2479,0x2478,0x2477,0x2476,0x2474,0x2473,0x2471,0x2470,0x246f,0x246e,0x246c,0x246b,0x246a,
+ 0x2468,0x2467,0x2465,0x2464,0x2463,0x2462,0x2461,0x245f,0x245d,0x245c,0x245b,0x245a,0x2459,0x2457,0x2455,0x2454,
+ 0x2453,0x2452,0x2451,0x2450,0x244d,0x244c,0x244b,0x244a,0x2449,0x2448,0x2447,0x2444,0x2443,0x2442,0x2441,0x2440,
+ 0x243f,0x243e,0x243c,0x243b,0x2439,0x2438,0x2437,0x2436,0x2434,0x2433,0x2432,0x2430,0x242f,0x242e,0x242c,0x242b,
+ 0x242a,0x2429,0x2427,0x2426,0x2425,0x2423,0x2422,0x2421,0x2420,0x241e,0x241d,0x241b,0x241a,0x2419,0x2418,0x2417,
+ 0x2416,0x2413,0x2412,0x2411,0x2410,0x240f,0x240e,0x240d,0x240a,0x2409,0x2408,0x2407,0x2406,0x2405,0x2403,0x2401,
+ 0x2400,0x23ff,0x23fe,0x23fd,0x23fb,0x23fa,0x23f8,0x23f7,0x23f6,0x23f5,0x23f3,0x23f2,0x23f1,0x23ef,0x23ee,0x23ed,
+ 0x23eb,0x23ea,0x23e9,0x23e8,0x23e6,0x23e5,0x23e3,0x23e2,0x23e1,0x23e0,0x23df,0x23dd,0x23dc,0x23da,0x23d9,0x23d8,
+ 0x23d7,0x23d6,0x23d4,0x23d2,0x23d1,0x23d0,0x23cf,0x23ce,0x23cd,0x23ca,0x23c9,0x23c8,0x23c7,0x23c6,0x23c5,0x23c4,
+ 0x23c2,0x23c0,0x23bf,0x23be,0x23bd,0x23bc,0x23ba,0x23b9,0x23b7,0x23b6,0x23b5,0x23b4,0x23b2,0x23b1,0x23b0,0x23ae,
+ 0x23ad,0x23ac,0x23aa,0x23a9,0x23a8,0x23a7,0x23a5,0x23a4,0x23a2,0x23a1,0x23a0,0x239f,0x239e,0x239c,0x239a,0x2399,
+ 0x2398,0x2397,0x2395,0x2394,0x2393,0x2392,0x2390,0x238f,0x238e,0x238d,0x238b,0x238a,0x2388,0x2387,0x2386,0x2385,
+ 0x2384,0x2382,0x2380,0x237f,0x237e,0x237d,0x237c,0x237b,0x2378,0x2377,0x2376,0x2375,0x2374,0x2373,0x2372,0x2371,
+ 0x236e,0x236d,0x236c,0x236b,0x236a,0x2369,0x2367,0x2365,0x2364,0x2363,0x2362,0x2361,0x235f,0x235e,0x235c,0x235b,
+ 0x235a,0x2359,0x2358,0x2356,0x2355,0x2354,0x2352,0x2351,0x2350,0x234e,0x234d,0x234c,0x234b,0x2349,0x2348,0x2346,
+ 0x2345,0x2344,0x2343,0x2342,0x2340,0x233f,0x233d,0x233c,0x233b,0x233a,0x2339,0x2337,0x2335,0x2334,0x2333,0x2332,
+ 0x2331,0x2330,0x232f,0x232c,0x232b,0x232a,0x2329,0x2328,0x2327,0x2326,0x2323,0x2322,0x2321,0x2320,0x231f,0x231e,
+ 0x231c,0x231a,0x2319,0x2318,0x2317,0x2316,0x2314,0x2313,0x2312,0x2310,0x230f,0x230e,0x230d,0x230b,0x230a,0x2309,
+ 0x2307,0x2306,0x2305,0x2303,0x2302,0x2301,0x2300,0x22fe,0x22fd,0x22fb,0x22fa,0x22f9,0x22f8,0x22f7,0x22f6,0x22f3,
+ 0x22f2,0x22f1,0x22f0,0x22ef,0x22ee,0x22ed,0x22ea,0x22e9,0x22e8,0x22e7,0x22e6,0x22e5,0x22e4,0x22e1,0x22e0,0x22df,
+ 0x22de,0x22dd,0x22dc,0x22da,0x22d9,0x22d7,0x22d6,0x22d5,0x22d4,0x22d3,0x22d1,0x22d0,0x22ce,0x22cd,0x22cc,0x22cb,
+ 0x22c9,0x22c8,0x22c7,0x22c5,0x22c4,0x22c3,0x22c1,0x22c0,0x22bf,0x22be,0x22bd,0x22bb,0x22ba,0x22b8,0x22b7,0x22b6,
+ 0x22b5,0x22b4,0x22b2,0x22b0,0x22af,0x22ae,0x22ad,0x22ac,0x22ab,0x22a8,0x22a7,0x22a6,0x22a5,0x22a4,0x22a3,0x22a2,
+ 0x22a1,0x229e,0x229d,0x229c,0x229b,0x229a,0x2299,0x2297,0x2295,0x2294,0x2293,0x2292,0x2291,0x228f,0x228e,0x228c,
+ 0x228b,0x228a,0x2289,0x2288,0x2286,0x2285,0x2283,0x2282,0x2281,0x2280,0x227e,0x227d,0x227c,0x227b,0x2279,0x2278,
+ 0x2276,0x2275,0x2274,0x2273,0x2272,0x2270,0x226f,0x226d,0x226c,0x226b,0x226a,0x2269,0x2267,0x2265,0x2264,0x2263,
+ 0x2262,0x2261,0x2260,0x225f,0x225c,0x225b,0x225a,0x2259,0x2258,0x2257,0x2255,0x2253,0x2252,0x2251,0x2250,0x224f,
+ 0x224e,0x224c,0x224b,0x224a,0x2249,0x2247,0x2246,0x2245,0x2243,0x2242,0x2241,0x223f,0x223e,0x223d,0x223c,0x223b,
+ 0x2239,0x2238,0x2236,0x2235,0x2234,0x2233,0x2232,0x2230,0x222e,0x222d,0x222c,0x222b,0x222a,0x2229,0x2228,0x2225,
+ 0x2224,0x2223,0x2222,0x2221,0x2220,0x221f,0x221c,0x221b,0x221a,0x2219,0x2218,0x2217,0x2216,0x2214,0x2212,0x2211,
+ 0x2210,0x220f,0x220e,0x220c,0x220b,0x2209,0x2208,0x2207,0x2206,0x2205,0x2203,0x2202,0x2201,0x21ff,0x21fe,0x21fd,
+ 0x21fb,0x21fa,0x21f9,0x21f8,0x21f6,0x21f5,0x21f4,0x21f2,0x21f1,0x21f0,0x21ef,0x21ee,0x21ec,0x21ea,0x21e9,0x21e8,
+ 0x21e7,0x21e6,0x21e5,0x21e3,0x21e1,0x21e0,0x21df,0x21de,0x21dd,0x21dc,0x21db,0x21d8,0x21d7,0x21d6,0x21d5,0x21d4,
+ 0x21d3,0x21d2,0x21cf,0x21ce,0x21cd,0x21cc,0x21cb,0x21ca,0x21c8,0x21c7,0x21c5,0x21c4,0x21c3,0x21c2,0x21c1,0x21bf,
+ 0x21be,0x21bc,0x21bb,0x21ba,0x21b9,0x21b8,0x21b6,0x21b5,0x21b4,0x21b2,0x21b1,0x21b0,0x21ae,0x21ad,0x21ac,0x21ab,
+ 0x21a9,0x21a8,0x21a6,0x21a5,0x21a4,0x21a3,0x21a1,0x21a0,0x219f,0x219e,0x219c,0x219b,0x219a,0x2198,0x2197,0x2196,
+ 0x2195,0x2194,0x2192,0x2191,0x218f,0x218e,0x218d,0x218c,0x218b,0x218a,0x2187,0x2186,0x2185,0x2184,0x2183,0x2182,
+ 0x2181,0x217e,0x217d,0x217c,0x217b,0x217a,0x2179,0x2178,0x2177,0x2174,0x2173,0x2172,0x2171,0x2170,0x216f,0x216e,
+ 0x216c,0x216a,0x2169,0x2168,0x2167,0x2166,0x2164,0x2163,0x2162,0x2160,0x215f,0x215e,0x215d,0x215b,0x215a,0x2159,
+ 0x2158,0x2156,0x2155,0x2154,0x2152,0x2151,0x2150,0x214f,0x214d,0x214c,0x214b,0x2149,0x2148,0x2147,0x2146,0x2145,
+ 0x2143,0x2141,0x2140,0x213f,0x213e,0x213d,0x213c,0x213b,0x2138,0x2137,0x2136,0x2135,0x2134,0x2133,0x2132,0x2131,
+ 0x212e,0x212d,0x212c,0x212b,0x212a,0x2129,0x2128,0x2125,0x2124,0x2123,0x2122,0x2121,0x2120,0x211e,0x211d,0x211b,
+ 0x211a,0x2119,0x2118,0x2117,0x2115,0x2114,0x2113,0x2111,0x2110,0x210f,0x210e,0x210c,0x210b,0x210a,0x2109,0x2107,
+ 0x2106,0x2105,0x2103,0x2102,0x2101,0x2100,0x20fe,0x20fd,0x20fb,0x20fa,0x20f9,0x20f8,0x20f7,0x20f6,0x20f4,0x20f2,
+ 0x20f1,0x20f0,0x20ef,0x20ee,0x20ed,0x20ec,0x20e9,0x20e8,0x20e7,0x20e6,0x20e5,0x20e4,0x20e3,0x20e2,0x20df,0x20de,
+ 0x20dd,0x20dc,0x20db,0x20da,0x20d8,0x20d6,0x20d5,0x20d4,0x20d3,0x20d2,0x20d1,0x20cf,0x20ce,0x20cc,0x20cb,0x20ca,
+ 0x20c9,0x20c8,0x20c6,0x20c5,0x20c4,0x20c2,0x20c1,0x20c0,0x20bf,0x20bd,0x20bc,0x20bb,0x20ba,0x20b8,0x20b7,0x20b5,
+ 0x20b4,0x20b3,0x20b2,0x20b1,0x20af,0x20ae,0x20ac,0x20ab,0x20aa,0x20a9,0x20a8,0x20a7,0x20a5,0x20a3,0x20a2,0x20a1,
+ 0x20a0,0x209f,0x209e,0x209d,0x209a,0x2099,0x2098,0x2097,0x2096,0x2095,0x2094,0x2092,0x2090,0x208f,0x208e,0x208d,
+ 0x208c,0x208b,0x2089,0x2087,0x2086,0x2085,0x2084,0x2083,0x2082,0x2080,0x207f,0x207d,0x207c,0x207b,0x207a,0x2079,
+ 0x2077,0x2076,0x2075,0x2073,0x2072,0x2071,0x2070,0x206e,0x206d,0x206c,0x206b,0x2069,0x2068,0x2066,0x2065,0x2064,
+ 0x2063,0x2062,0x2061,0x2060,0x205f,0x205c,0x205b,0x205a,0x2059,0x2058,0x2057,0x2056,0x2054,0x2052,0x2051,0x2050,
+ 0x204f,0x204e,0x204d,0x204b,0x204a,0x2048,0x2047,0x2046,0x2045,0x2044,0x2042,0x2041,0x2040,0x203e,0x203d,0x203c,
+ 0x203b,0x2039,0x2038,0x2037,0x2036,0x2034,0x2033,0x2032,0x2030,0x202f,0x202e,0x202d,0x202c,0x202a,0x2029,0x2027,
+ 0x2026,0x2025,0x2024,0x2023,0x2022,0x2020,0x201e,0x201d,0x201c,0x201b,0x201a,0x2019,0x2018,0x2015,0x2014,0x2013,
+ 0x2012,0x2011,0x2010,0x200f,0x200e,0x200b,0x200a,0x2009,0x2008,0x2007,0x2006,0x2005,0x2003,0x2001,0x2000,0x1fff,
+ 0x1ffe,0x1ffd,0x1ffc,0x1ffa,0x1ff9,0x1ff7,0x1ff6,0x1ff5,0x1ff4,0x1ff3,0x1ff1,0x1ff0,0x1fef,0x1fed,0x1fec,0x1feb,
+ 0x1fea,0x1fe8,0x1fe7,0x1fe6,0x1fe5,0x1fe3,0x1fe2,0x1fe1,0x1fdf,0x1fde,0x1fdd,0x1fdc,0x1fdb,0x1fd9,0x1fd8,0x1fd6,
+ 0x1fd5,0x1fd4,0x1fd3,0x1fd2,0x1fd1,0x1fcf,0x1fcd,0x1fcc,0x1fcb,0x1fca,0x1fc9,0x1fc8,0x1fc7,0x1fc4,0x1fc3,0x1fc2,
+ 0x1fc1,0x1fc0,0x1fbf,0x1fbc,0x1fbb,0x1fba,0x1fb9,0x1fb8,0x1fb7,0x1fb6,0x1fb4,0x1fb2,0x1fb1,0x1fb0,0x1faf,0x1fae,
+ 0x1fad,0x1fac,0x1faa,0x1fa8,0x1fa7,0x1fa6,0x1fa5,0x1fa4,0x1fa3,0x1fa1,0x1fa0,0x1f9e,0x1f9d,0x1f9c,0x1f9b,0x1f9a,
+ 0x1f98,0x1f97,0x1f96,0x1f95,0x1f93,0x1f92,0x1f91,0x1f90,0x1f8e,0x1f8d,0x1f8c,0x1f8b,0x1f89,0x1f88,0x1f87,0x1f85,
+ 0x1f84,0x1f83,0x1f82,0x1f81,0x1f7f,0x1f7e,0x1f7c,0x1f7b,0x1f7a,0x1f79,0x1f78,0x1f77,0x1f75,0x1f73,0x1f72,0x1f71,
+ 0x1f70,0x1f6f,0x1f6e,0x1f6d,0x1f6c,0x1f69,0x1f68,0x1f67,0x1f66,0x1f65,0x1f64,0x1f63,0x1f62,0x1f5f,0x1f5e,0x1f5d,
+ 0x1f5c,0x1f5b,0x1f5a,0x1f59,0x1f57,0x1f55,0x1f54,0x1f53,0x1f52,0x1f51,0x1f50,0x1f4e,0x1f4d,0x1f4b,0x1f4a,0x1f49,
+ 0x1f48,0x1f47,0x1f46,0x1f44,0x1f43,0x1f42,0x1f40,0x1f3f,0x1f3e,0x1f3d,0x1f3b,0x1f3a,0x1f39,0x1f38,0x1f36,0x1f35,
+ 0x1f34,0x1f32,0x1f31,0x1f30,0x1f2f,0x1f2e,0x1f2c,0x1f2b,0x1f29,0x1f28,0x1f27,0x1f26,0x1f25,0x1f24,0x1f22,0x1f21,
+ 0x1f1f,0x1f1e,0x1f1d,0x1f1c,0x1f1b,0x1f1a,0x1f19,0x1f16,0x1f15,0x1f14,0x1f13,0x1f12,0x1f11,0x1f10,0x1f0f,0x1f0c,
+ 0x1f0b,0x1f0a,0x1f09,0x1f08,0x1f07,0x1f06,0x1f04,0x1f02,0x1f01,0x1f00,0x1eff,0x1efe,0x1efd,0x1efc,0x1efa,0x1ef8,
+ 0x1ef7,0x1ef6,0x1ef5,0x1ef4,0x1ef3,0x1ef1,0x1ef0,0x1eef,0x1eed,0x1eec,0x1eeb,0x1eea,0x1ee8,0x1ee7,0x1ee6,0x1ee5,
+ 0x1ee3,0x1ee2,0x1ee1,0x1edf,0x1ede,0x1edd,0x1edc,0x1edb,0x1ed9,0x1ed8,0x1ed7,0x1ed5,0x1ed4,0x1ed3,0x1ed2,0x1ed1,
+ 0x1ed0,0x1ece,0x1ecc,0x1ecb,0x1eca,0x1ec9,0x1ec8,0x1ec7,0x1ec6,0x1ec3,0x1ec2,0x1ec1,0x1ec0,0x1ebf,0x1ebe,0x1ebd,
+ 0x1ebc,0x1eb9,0x1eb8,0x1eb7,0x1eb6,0x1eb5,0x1eb4,0x1eb3,0x1eb2,0x1eaf,0x1eae,0x1ead,0x1eac,0x1eab,0x1eaa,0x1ea9,
+ 0x1ea7,0x1ea6,0x1ea4,0x1ea3,0x1ea2,0x1ea1,0x1ea0,0x1e9e,0x1e9d,0x1e9c,0x1e9a,0x1e99,0x1e98,0x1e97,0x1e95,0x1e94,
+ 0x1e93,0x1e92,0x1e90,0x1e8f,0x1e8e,0x1e8d,0x1e8b,0x1e8a,0x1e89,0x1e88,0x1e86,0x1e85,0x1e84,0x1e82,0x1e81,0x1e80,
+ 0x1e7f,0x1e7d,0x1e7c,0x1e7b,0x1e7a,0x1e79,0x1e78,0x1e76,0x1e75,0x1e73,0x1e72,0x1e71,0x1e70,0x1e6f,0x1e6d,0x1e6c,
+ 0x1e6b,0x1e6a,0x1e68,0x1e67,0x1e66,0x1e65,0x1e63,0x1e62,0x1e61,0x1e60,0x1e5e,0x1e5d,0x1e5c,0x1e5a,0x1e59,0x1e58,
+ 0x1e57,0x1e56,0x1e55,0x1e53,0x1e52,0x1e50,0x1e4f,0x1e4e,0x1e4d,0x1e4c,0x1e4b,0x1e49,0x1e48,0x1e46,0x1e45,0x1e44,
+ 0x1e43,0x1e42,0x1e41,0x1e40,0x1e3d,0x1e3c,0x1e3b,0x1e3a,0x1e39,0x1e38,0x1e37,0x1e36,0x1e33,0x1e32,0x1e31,0x1e30,
+ 0x1e2f,0x1e2e,0x1e2d,0x1e2c,0x1e2a,0x1e28,0x1e27,0x1e26,0x1e25,0x1e24,0x1e23,0x1e22,0x1e20,0x1e1e,0x1e1d,0x1e1c,
+ 0x1e1b,0x1e1a,0x1e19,0x1e17,0x1e16,0x1e15,0x1e13,0x1e12,0x1e11,0x1e10,0x1e0f,0x1e0d,0x1e0c,0x1e0b,0x1e09,0x1e08,
+ 0x1e07,0x1e06,0x1e04,0x1e03,0x1e02,0x1e01,0x1e00,0x1dfe,0x1dfd,0x1dfc,0x1dfa,0x1df9,0x1df8,0x1df7,0x1df6,0x1df4,
+ 0x1df3,0x1df1,0x1df0,0x1def,0x1dee,0x1ded,0x1dec,0x1deb,0x1de9,0x1de7,0x1de6,0x1de5,0x1de4,0x1de3,0x1de2,0x1de1,
+ 0x1de0,0x1ddd,0x1ddc,0x1ddb,0x1dda,0x1dd9,0x1dd8,0x1dd7,0x1dd6,0x1dd3,0x1dd2,0x1dd1,0x1dd0,0x1dcf,0x1dce,0x1dcd,
+ 0x1dcb,0x1dca,0x1dc8,0x1dc7,0x1dc6,0x1dc5,0x1dc4,0x1dc3,0x1dc1,0x1dc0,0x1dbe,0x1dbd,0x1dbc,0x1dbb,0x1dba,0x1db9,
+ 0x1db7,0x1db6,0x1db5,0x1db3,0x1db2,0x1db1,0x1db0,0x1dae,0x1dad,0x1dac,0x1dab,0x1da9,0x1da8,0x1da7,0x1da6,0x1da4,
+ 0x1da3,0x1da2,0x1da1,0x1da0,0x1d9e,0x1d9d,0x1d9b,0x1d9a,0x1d99,0x1d98,0x1d97,0x1d96,0x1d94,0x1d93,0x1d91,0x1d90,
+ 0x1d8f,0x1d8e,0x1d8d,0x1d8c,0x1d8b,0x1d88,0x1d87,0x1d86,0x1d85,0x1d84,0x1d83,0x1d82,0x1d81,0x1d7e,0x1d7d,0x1d7c,
+ 0x1d7b,0x1d7a,0x1d79,0x1d78,0x1d77,0x1d75,0x1d73,0x1d72,0x1d71,0x1d70,0x1d6f,0x1d6e,0x1d6d,0x1d6b,0x1d69,0x1d68,
+ 0x1d67,0x1d66,0x1d65,0x1d64,0x1d62,0x1d61,0x1d60,0x1d5e,0x1d5d,0x1d5c,0x1d5b,0x1d5a,0x1d58,0x1d57,0x1d56,0x1d54,
+ 0x1d53,0x1d52,0x1d51,0x1d4f,0x1d4e,0x1d4d,0x1d4c,0x1d4b,0x1d49,0x1d48,0x1d47,0x1d45,0x1d44,0x1d43,0x1d42,0x1d41,
+ 0x1d3f,0x1d3e,0x1d3d,0x1d3c,0x1d3b,0x1d3a,0x1d39,0x1d37,0x1d35,0x1d34,0x1d33,0x1d32,0x1d31,0x1d30,0x1d2f,0x1d2e,
+ 0x1d2b,0x1d2a,0x1d29,0x1d28,0x1d27,0x1d26,0x1d25,0x1d24,0x1d23,0x1d20,0x1d1f,0x1d1e,0x1d1d,0x1d1c,0x1d1b,0x1d1a,
+ 0x1d18,0x1d17,0x1d15,0x1d14,0x1d13,0x1d12,0x1d11,0x1d10,0x1d0e,0x1d0d,0x1d0b,0x1d0a,0x1d09,0x1d08,0x1d07,0x1d06,
+ 0x1d04,0x1d03,0x1d02,0x1d00,0x1cff,0x1cfe,0x1cfd,0x1cfc,0x1cfa,0x1cf9,0x1cf8,0x1cf7,0x1cf5,0x1cf4,0x1cf3,0x1cf2,
+ 0x1cf0,0x1cef,0x1cee,0x1ced,0x1cec,0x1cea,0x1ce9,0x1ce8,0x1ce6,0x1ce5,0x1ce4,0x1ce3,0x1ce2,0x1ce1,0x1cdf,0x1cdd,
+ 0x1cdc,0x1cdb,0x1cda,0x1cd9,0x1cd8,0x1cd7,0x1cd6,0x1cd3,0x1cd2,0x1cd1,0x1cd0,0x1ccf,0x1cce,0x1ccd,0x1ccc,0x1cc9,
+ 0x1cc8,0x1cc7,0x1cc6,0x1cc5,0x1cc4,0x1cc3,0x1cc2,0x1cc1,0x1cbe,0x1cbd,0x1cbc,0x1cbb,0x1cba,0x1cb9,0x1cb8,0x1cb7,
+ 0x1cb5,0x1cb3,0x1cb2,0x1cb1,0x1cb0,0x1caf,0x1cae,0x1cad,0x1cab,0x1caa,0x1ca8,0x1ca7,0x1ca6,0x1ca5,0x1ca4,0x1ca2,
+ 0x1ca1,0x1ca0,0x1c9f,0x1c9e,0x1c9c,0x1c9a,0x1c99,0x1c98,0x1c97,0x1c96,0x1c95,0x1c94,0x1c92,0x1c91,0x1c8f,0x1c8e,
+ 0x1c8d,0x1c8c,0x1c8b,0x1c8a,0x1c88,0x1c87,0x1c86,0x1c84,0x1c83,0x1c82,0x1c81,0x1c80,0x1c7e,0x1c7d,0x1c7c,0x1c7b,
+ 0x1c7a,0x1c78,0x1c77,0x1c76,0x1c74,0x1c73,0x1c72,0x1c71,0x1c70,0x1c6f,0x1c6d,0x1c6c,0x1c6b,0x1c69,0x1c68,0x1c67,
+ 0x1c66,0x1c65,0x1c64,0x1c62,0x1c61,0x1c5f,0x1c5e,0x1c5d,0x1c5c,0x1c5b,0x1c5a,0x1c59,0x1c57,0x1c55,0x1c54,0x1c53,
+ 0x1c52,0x1c51,0x1c50,0x1c4f,0x1c4e,0x1c4b,0x1c4a,0x1c49,0x1c48,0x1c47,0x1c46,0x1c45,0x1c44,0x1c43,0x1c40,0x1c3f,
+ 0x1c3e,0x1c3d,0x1c3c,0x1c3b,0x1c3a,0x1c39,0x1c37,0x1c35,0x1c34,0x1c33,0x1c32,0x1c31,0x1c30,0x1c2f,0x1c2d,0x1c2c,
+ 0x1c2b,0x1c29,0x1c28,0x1c27,0x1c26,0x1c25,0x1c24,0x1c22,0x1c21,0x1c20,0x1c1e,0x1c1d,0x1c1c,0x1c1b,0x1c1a,0x1c18,
+ 0x1c17,0x1c16,0x1c15,0x1c13,0x1c12,0x1c11,0x1c10,0x1c0e,0x1c0d,0x1c0c,0x1c0b,0x1c0a,0x1c08,0x1c07,0x1c06,0x1c04,
+ 0x1c03,0x1c02,0x1c01,0x1c00,0x1bff,0x1bfd,0x1bfc,0x1bfa,0x1bf9,0x1bf8,0x1bf7,0x1bf6,0x1bf5,0x1bf4,0x1bf2,0x1bf0,
+ 0x1bef,0x1bee,0x1bed,0x1bec,0x1beb,0x1bea,0x1be9,0x1be6,0x1be5,0x1be4,0x1be3,0x1be2,0x1be1,0x1be0,0x1bdf,0x1bde,
+ 0x1bdd,0x1bda,0x1bd9,0x1bd8,0x1bd7,0x1bd6,0x1bd5,0x1bd4,0x1bd3,0x1bd1,0x1bcf,0x1bce,0x1bcd,0x1bcc,0x1bcb,0x1bca,
+ 0x1bc9,0x1bc7,0x1bc6,0x1bc4,0x1bc3,0x1bc2,0x1bc1,0x1bc0,0x1bbf,0x1bbd,0x1bbc,0x1bbb,0x1bb9,0x1bb8,0x1bb7,0x1bb6,
+ 0x1bb5,0x1bb3,0x1bb2,0x1bb1,0x1bb0,0x1bae,0x1bad,0x1bac,0x1bab,0x1ba9,0x1ba8,0x1ba7,0x1ba6,0x1ba5,0x1ba3,0x1ba2,
+ 0x1ba1,0x1b9f,0x1b9e,0x1b9d,0x1b9c,0x1b9b,0x1b9a,0x1b98,0x1b97,0x1b96,0x1b94,0x1b93,0x1b92,0x1b91,0x1b90,0x1b8f,
+ 0x1b8e,0x1b8c,0x1b8a,0x1b89,0x1b88,0x1b87,0x1b86,0x1b85,0x1b84,0x1b83,0x1b80,0x1b7f,0x1b7e,0x1b7d,0x1b7c,0x1b7b,
+ 0x1b7a,0x1b79,0x1b78,0x1b75,0x1b74,0x1b73,0x1b72,0x1b71,0x1b70,0x1b6f,0x1b6e,0x1b6c,0x1b6a,0x1b69,0x1b68,0x1b67,
+ 0x1b66,0x1b65,0x1b63,0x1b62,0x1b61,0x1b60,0x1b5f,0x1b5e,0x1b5c,0x1b5b,0x1b5a,0x1b58,0x1b57,0x1b56,0x1b55,0x1b54,
+ 0x1b53,0x1b51,0x1b50,0x1b4e,0x1b4d,0x1b4c,0x1b4b,0x1b4a,0x1b49,0x1b48,0x1b47,0x1b45,0x1b43,0x1b42,0x1b41,0x1b40,
+ 0x1b3f,0x1b3e,0x1b3d,0x1b3c,0x1b39,0x1b38,0x1b37,0x1b36,0x1b35,0x1b34,0x1b33,0x1b32,0x1b31,0x1b30,0x1b2d,0x1b2c,
+ 0x1b2b,0x1b2a,0x1b29,0x1b28,0x1b27,0x1b26,0x1b24,0x1b22,0x1b21,0x1b20,0x1b1f,0x1b1e,0x1b1d,0x1b1c,0x1b1b,0x1b19,
+ 0x1b18,0x1b16,0x1b15,0x1b14,0x1b13,0x1b12,0x1b11,0x1b0f,0x1b0e,0x1b0d,0x1b0b,0x1b0a,0x1b09,0x1b08,0x1b07,0x1b06,
+ 0x1b04,0x1b03,0x1b02,0x1b00,0x1aff,0x1afe,0x1afd,0x1afc,0x1afa,0x1af9,0x1af8,0x1af7,0x1af6,0x1af4,0x1af3,0x1af2,
+ 0x1af1,0x1aef,0x1aee,0x1aed,0x1aec,0x1aeb,0x1ae9,0x1ae8,0x1ae7,0x1ae5,0x1ae4,0x1ae3,0x1ae2,0x1ae1,0x1ae0,0x1adf,
+ 0x1add,0x1adc,0x1ada,0x1ad9,0x1ad8,0x1ad7,0x1ad6,0x1ad5,0x1ad4,0x1ad2,0x1ad0,0x1acf,0x1ace,0x1acd,0x1acc,0x1acb,
+ 0x1aca,0x1ac7,0x1ac6,0x1ac5,0x1ac4,0x1ac3,0x1ac2,0x1ac1,0x1ac0,0x1abf,0x1abc,0x1abb,0x1aba,0x1ab9,0x1ab8,0x1ab7,
+ 0x1ab6,0x1ab5,0x1ab4,0x1ab2,0x1ab0,0x1aaf,0x1aae,0x1aad,0x1aac,0x1aab,0x1aaa,0x1aa9,0x1aa7,0x1aa6,0x1aa4,0x1aa3,
+ 0x1aa2,0x1aa1,0x1aa0,0x1a9f,0x1a9e,0x1a9c,0x1a9b,0x1a9a,0x1a98,0x1a97,0x1a96,0x1a95,0x1a94,0x1a93,0x1a91,0x1a90,
+ 0x1a8f,0x1a8e,0x1a8c,0x1a8b,0x1a8a,0x1a89,0x1a87,0x1a86,0x1a85,0x1a84,0x1a83,0x1a82,0x1a80,0x1a7f,0x1a7e,0x1a7c,
+ 0x1a7b,0x1a7a,0x1a79,0x1a78,0x1a77,0x1a75,0x1a74,0x1a73,0x1a71,0x1a70,0x1a6f,0x1a6e,0x1a6d,0x1a6c,0x1a6b,0x1a69,
+ 0x1a68,0x1a66,0x1a65,0x1a64,0x1a63,0x1a62,0x1a61,0x1a60,0x1a5f,0x1a5d,0x1a5b,0x1a5a,0x1a59,0x1a58,0x1a57,0x1a56,
+ 0x1a55,0x1a54,0x1a53,0x1a50,0x1a4f,0x1a4e,0x1a4d,0x1a4c,0x1a4b,0x1a4a,0x1a49,0x1a48,0x1a47,0x1a44,0x1a43,0x1a42,
+ 0x1a41,0x1a40,0x1a3f,0x1a3e,0x1a3d,0x1a3b,0x1a3a,0x1a38,0x1a37,0x1a36,0x1a35,0x1a34,0x1a33,0x1a32,0x1a30,0x1a2f,
+ 0x1a2e,0x1a2c,0x1a2b,0x1a2a,0x1a29,0x1a28,0x1a27,0x1a25,0x1a24,0x1a23,0x1a21,0x1a20,0x1a1f,0x1a1e,0x1a1d,0x1a1c,
+ 0x1a1a,0x1a19,0x1a18,0x1a17,0x1a15,0x1a14,0x1a13,0x1a12,0x1a11,0x1a0f,0x1a0e,0x1a0d,0x1a0c,0x1a0b,0x1a09,0x1a08,
+ 0x1a07,0x1a06,0x1a04,0x1a03,0x1a02,0x1a01,0x1a00,0x19ff,0x19fd,0x19fc,0x19fa,0x19f9,0x19f8,0x19f7,0x19f6,0x19f5,
+ 0x19f4,0x19f3,0x19f1,0x19ef,0x19ee,0x19ed,0x19ec,0x19eb,0x19ea,0x19e9,0x19e8,0x19e7,0x19e4,0x19e3,0x19e2,0x19e1,
+ 0x19e0,0x19df,0x19de,0x19dd,0x19dc,0x19d9,0x19d8,0x19d7,0x19d6,0x19d5,0x19d4,0x19d3,0x19d2,0x19d1,0x19d0,0x19cd,
+ 0x19cc,0x19cb,0x19ca,0x19c9,0x19c8,0x19c7,0x19c6,0x19c5,0x19c3,0x19c1,0x19c0,0x19bf,0x19be,0x19bd,0x19bc,0x19bb,
+ 0x19ba,0x19b8,0x19b7,0x19b5,0x19b4,0x19b3,0x19b2,0x19b1,0x19b0,0x19ae,0x19ad,0x19ac,0x19ab,0x19a9,0x19a8,0x19a7,
+ 0x19a6,0x19a5,0x19a3,0x19a2,0x19a1,0x19a0,0x199f,0x199d,0x199c,0x199b,0x199a,0x1998,0x1997,0x1996,0x1995,0x1994,
+ 0x1992,0x1991,0x1990,0x198f,0x198e,0x198d,0x198b,0x198a,0x1988,0x1987,0x1986,0x1985,0x1984,0x1983,0x1982,0x1980,
+ 0x197f,0x197e,0x197c,0x197b,0x197a,0x1979,0x1978,0x1977,0x1975,0x1974,0x1973,0x1972,0x1971,0x196f,0x196e,0x196d,
+ 0x196c,0x196a,0x1969,0x1968,0x1967,0x1966,0x1965,0x1963,0x1962,0x1961,0x195f,0x195e,0x195d,0x195c,0x195b,0x195a,
+ 0x1959,0x1957,0x1956,0x1955,0x1953,0x1952,0x1951,0x1950,0x194f,0x194e,0x194d,0x194b,0x194a,0x1948,0x1947,0x1946,
+ 0x1945,0x1944,0x1943,0x1942,0x1941,0x1940,0x193d,0x193c,0x193b,0x193a,0x1939,0x1938,0x1937,0x1936,0x1935,0x1934,
+ 0x1931,0x1930,0x192f,0x192e,0x192d,0x192c,0x192b,0x192a,0x1929,0x1928,0x1925,0x1924,0x1923,0x1922,0x1921,0x1920,
+ 0x191f,0x191e,0x191d,0x191b,0x1919,0x1918,0x1917,0x1916,0x1915,0x1914,0x1913,0x1912,0x1910,0x190f,0x190e,0x190c,
+ 0x190b,0x190a,0x1909,0x1908,0x1907,0x1905,0x1904,0x1903,0x1902,0x1900,0x18ff,0x18fe,0x18fd,0x18fc,0x18fb,0x18f9,
+ 0x18f8,0x18f7,0x18f6,0x18f4,0x18f3,0x18f2,0x18f1,0x18f0,0x18ee,0x18ed,0x18ec,0x18eb,0x18ea,0x18e8,0x18e7,0x18e6,
+ 0x18e5,0x18e3,0x18e2,0x18e1,0x18e0,0x18df,0x18de,0x18dd,0x18db,0x18da,0x18d8,0x18d7,0x18d6,0x18d5,0x18d4,0x18d3,
+ 0x18d2,0x18d1,0x18cf,0x18ce,0x18cc,0x18cb,0x18ca,0x18c9,0x18c8,0x18c7,0x18c6,0x18c5,0x18c3,0x18c1,0x18c0,0x18bf,
+ 0x18be,0x18bd,0x18bc,0x18bb,0x18ba,0x18b9,0x18b6,0x18b5,0x18b4,0x18b3,0x18b2,0x18b1,0x18b0,0x18af,0x18ae,0x18ad,
+ 0x18ab,0x18a9,0x18a8,0x18a7,0x18a6,0x18a5,0x18a4,0x18a3,0x18a2,0x18a1,0x189f,0x189d,0x189c,0x189b,0x189a,0x1899,
+ 0x1898,0x1897,0x1896,0x1894,0x1893,0x1891,0x1890,0x188f,0x188e,0x188d,0x188c,0x188b,0x1889,0x1888,0x1887,0x1885,
+ 0x1884,0x1883,0x1882,0x1881,0x1880,0x187e,0x187d,0x187c,0x187b,0x1879,0x1878,0x1877,0x1876,0x1875,0x1874,0x1872,
+ 0x1871,0x1870,0x186f,0x186e,0x186c,0x186b,0x186a,0x1869,0x1867,0x1866,0x1865,0x1864,0x1863,0x1862,0x1860,0x185f,
+ 0x185e,0x185d,0x185c,0x185b,0x185a,0x1859,0x1856,0x1855,0x1854,0x1853,0x1852,0x1851,0x1850,0x184f,0x184e,0x184d,
+ 0x184b,0x1849,0x1848,0x1847,0x1846,0x1845,0x1844,0x1843,0x1842,0x1841,0x183f,0x183d,0x183c,0x183b,0x183a,0x1839,
+ 0x1838,0x1837,0x1836,0x1835,0x1833,0x1832,0x1830,0x182f,0x182e,0x182d,0x182c,0x182b,0x182a,0x1828,0x1827,0x1826,
+ 0x1825,0x1823,0x1822,0x1821,0x1820,0x181f,0x181e,0x181c,0x181b,0x181a,0x1819,0x1817,0x1816,0x1815,0x1814,0x1813,
+ 0x1812,0x1810,0x180f,0x180e,0x180d,0x180c,0x180a,0x1809,0x1808,0x1807,0x1805,0x1804,0x1803,0x1802,0x1801,0x1800,
+ 0x17ff,0x17fd,0x17fc,0x17fb,0x17f9,0x17f8,0x17f7,0x17f6,0x17f5,0x17f4,0x17f3,0x17f1,0x17f0,0x17ef,0x17ed,0x17ec,
+ 0x17eb,0x17ea,0x17e9,0x17e8,0x17e7,0x17e6,0x17e4,0x17e2,0x17e1,0x17e0,0x17df,0x17de,0x17dd,0x17dc,0x17db,0x17da,
+ 0x17d9,0x17d6,0x17d5,0x17d4,0x17d3,0x17d2,0x17d1,0x17d0,0x17cf,0x17ce,0x17cd,0x17ca,0x17c9,0x17c8,0x17c7,0x17c6,
+ 0x17c4,0x17c3,0x17c2,0x17c1,0x17c0,0x17bf,0x17be,0x17bd,0x17bb,0x17b9,0x17b8,0x17b7,0x17b6,0x17b5,0x17b4,0x17b3,
+ 0x17b2,0x17b1,0x17af,0x17ae,0x17ac,0x17ab,0x17aa,0x17a9,0x17a8,0x17a7,0x17a6,0x17a5,0x17a3,0x17a2,0x17a1,0x179f,
+ 0x179e,0x179d,0x179c,0x179b,0x179a,0x1799,0x1797,0x1796,0x1795,0x1794,0x1792,0x1791,0x1790,0x178f,0x178e,0x178d,
+ 0x178c,0x178a,0x1789,0x1788,0x1787,0x1785,0x1784,0x1783,0x1782,0x1781,0x1780,0x177e,0x177d,0x177c,0x177b,0x177a,
+ 0x1779,0x1777,0x1776,0x1775,0x1774,0x1772,0x1771,0x1770,0x176f,0x176e,0x176d,0x176c,0x176a,0x1769,0x1768,0x1766,
+ 0x1765,0x1764,0x1763,0x1762,0x1761,0x1760,0x175f,0x175d,0x175c,0x175a,0x1759,0x1758,0x1757,0x1756,0x1755,0x1754,
+ 0x1753,0x1752,0x1750,0x174e,0x174d,0x174c,0x174b,0x174a,0x1749,0x1748,0x1747,0x1746,0x1745,0x1742,0x1741,0x1740,
+ 0x173f,0x173e,0x173d,0x173c,0x173b,0x173a,0x1739,0x1738,0x1735,0x1734,0x1733,0x1732,0x1731,0x1730,0x172f,0x172e,
+ 0x172d,0x172c,0x172b,0x1728,0x1727,0x1726,0x1725,0x1724,0x1723,0x1722,0x1721,0x1720,0x171f,0x171d,0x171b,0x171a,
+ 0x1719,0x1718,0x1717,0x1716,0x1715,0x1714,0x1713,0x1711,0x1710,0x170f,0x170d,0x170c,0x170b,0x170a,0x1709,0x1708,
+ 0x1707,0x1705,0x1704,0x1703,0x1702,0x1700,0x16ff,0x16fe,0x16fd,0x16fc,0x16fb,0x16f9,0x16f8,0x16f7,0x16f6,0x16f5,
+ 0x16f3,0x16f2,0x16f1,0x16f0,0x16ef,0x16ed,0x16ec,0x16eb,0x16ea,0x16e9,0x16e8,0x16e6,0x16e5,0x16e4,0x16e3,0x16e1,
+ 0x16e0,0x16df,0x16de,0x16dd,0x16dc,0x16db,0x16d9,0x16d8,0x16d7,0x16d5,0x16d4,0x16d3,0x16d2,0x16d1,0x16d0,0x16cf,
+ 0x16ce,0x16cc,0x16cb,0x16ca,0x16c8,0x16c7,0x16c6,0x16c5,0x16c4,0x16c3,0x16c2,0x16c1,0x16bf,0x16be,0x16bc,0x16bb,
+ 0x16ba,0x16b9,0x16b8,0x16b7,0x16b6,0x16b5,0x16b4,0x16b2,0x16b0,0x16af,0x16ae,0x16ad,0x16ac,0x16ab,0x16aa,0x16a9,
+ 0x16a8,0x16a7,0x16a6,0x16a3,0x16a2,0x16a1,0x16a0,0x169f,0x169e,0x169d,0x169c,0x169b,0x169a,0x1698,0x1696,0x1695,
+ 0x1695,0x1693,0x1692,0x1690,0x168f,0x168e,0x168d,0x168c,0x168b,0x168a,0x1689,0x1688,0x1686,0x1684,0x1683,0x1682,
+ 0x1681,0x1680,0x167f,0x167e,0x167d,0x167c,0x167b,0x167a,0x1677,0x1676,0x1675,0x1674,0x1673,0x1672,0x1671,0x1670,
+ 0x166f,0x166e,0x166d,0x166a,0x1669,0x1668,0x1667,0x1666,0x1665,0x1664,0x1663,0x1662,0x1661,0x1660,0x165e,0x165c,
+ 0x165b,0x165a,0x1659,0x1658,0x1657,0x1656,0x1655,0x1654,0x1653,0x1651,0x1650,0x164e,0x164d,0x164c,0x164b,0x164a,
+ 0x1649,0x1648,0x1647,0x1646,0x1644,0x1643,0x1641,0x1640,0x163f,0x163e,0x163d,0x163c,0x163b,0x163a,0x1638,0x1637,
+ 0x1636,0x1635,0x1633,0x1632,0x1631,0x1630,0x162f,0x162e,0x162d,0x162b,0x162a,0x1629,0x1628,0x1627,0x1625,0x1624,
+ 0x1623,0x1622,0x1621,0x161f,0x161e,0x161d,0x161c,0x161b,0x161a,0x1618,0x1617,0x1616,0x1615,0x1614,0x1612,0x1611,
+ 0x1610,0x160f,0x160e,0x160d,0x160c,0x160a,0x1609,0x1608,0x1607,0x1605,0x1604,0x1603,0x1602,0x1601,0x1600,0x15ff,
+ 0x15fe,0x15fc,0x15fb,0x15f9,0x15f8,0x15f7,0x15f6,0x15f5,0x15f4,0x15f3,0x15f2,0x15f1,0x15ef,0x15ee,0x15ec,0x15eb,
+ 0x15ea,0x15e9,0x15e8,0x15e7,0x15e6,0x15e5,0x15e4,0x15e3,0x15e1,0x15df,0x15de,0x15dd,0x15dc,0x15db,0x15da,0x15d9,
+ 0x15d8,0x15d7,0x15d6,0x15d3,0x15d2,0x15d1,0x15d0,0x15cf,0x15ce,0x15cd,0x15cc,0x15cb,0x15ca,0x15c9,0x15c8,0x15c5,
+ 0x15c4,0x15c3,0x15c2,0x15c1,0x15c0,0x15bf,0x15be,0x15bd,0x15bc,0x15bb,0x15b9,0x15b7,0x15b6,0x15b5,0x15b4,0x15b3,
+ 0x15b2,0x15b1,0x15b0,0x15af,0x15ad,0x15ac,0x15aa,0x15a9,0x15a8,0x15a7,0x15a6,0x15a5,0x15a4,0x15a3,0x15a2,0x15a0,
+ 0x159f,0x159e,0x159c,0x159b,0x159a,0x1599,0x1598,0x1597,0x1596,0x1594,0x1593,0x1592,0x1591,0x1590,0x158e,0x158d,
+ 0x158c,0x158b,0x158a,0x1589,0x1587,0x1586,0x1585,0x1584,0x1583,0x1581,0x1580,0x157f,0x157e,0x157d,0x157c,0x157a,
+ 0x1579,0x1578,0x1577,0x1576,0x1575,0x1573,0x1572,0x1571,0x1570,0x156e,0x156d,0x156c,0x156b,0x156a,0x1569,0x1568,
+ 0x1567,0x1566,0x1565,0x1564,0x1561,0x1560,0x155f,0x155e,0x155d,0x155c,0x155b,0x155a,0x1559,0x1558,0x1557,0x1555,
+ 0x1553,0x1552,0x1551,0x1550,0x154f,0x154e,0x154d,0x154c,0x154b,0x154a,0x1548,0x1547,0x1545,0x1544,0x1543,0x1542,
+ 0x1541,0x1540,0x153f,0x153e,0x153d,0x153c,0x153a,0x1539,0x1537,0x1536,0x1535,0x1534,0x1533,0x1532,0x1531,0x1530,
+ 0x152f,0x152d,0x152c,0x152b,0x1529,0x1528,0x1527,0x1526,0x1525,0x1524,0x1523,0x1522,0x1520,0x151f,0x151e,0x151d,
+ 0x151c,0x151a,0x1519,0x1518,0x1517,0x1516,0x1515,0x1513,0x1512,0x1511,0x1510,0x150f,0x150e,0x150c,0x150b,0x150a,
+ 0x1509,0x1508,0x1506,0x1505,0x1504,0x1503,0x1502,0x1501,0x1500,0x14fe,0x14fd,0x14fc,0x14fb,0x14fa,0x14f8,0x14f7,
+ 0x14f6,0x14f5,0x14f4,0x14f3,0x14f2,0x14f0,0x14ef,0x14ee,0x14ed,0x14eb,0x14ea,0x14e9,0x14e8,0x14e7,0x14e6,0x14e5,
+ 0x14e4,0x14e2,0x14e1,0x14e0,0x14de,0x14dd,0x14dc,0x14db,0x14da,0x14d9,0x14d8,0x14d7,0x14d6,0x14d4,0x14d3,0x14d1,
+ 0x14d0,0x14cf,0x14ce,0x14cd,0x14cc,0x14cb,0x14ca,0x14c9,0x14c8,0x14c7,0x14c4,0x14c3,0x14c2,0x14c1,0x14c0,0x14bf,
+ 0x14be,0x14bd,0x14bc,0x14bb,0x14ba,0x14b9,0x14b6,0x14b5,0x14b4,0x14b3,0x14b2,0x14b1,0x14b0,0x14af,0x14ae,0x14ad,
+ 0x14ac,0x14ab,0x14a8,0x14a7,0x14a6,0x14a5,0x14a4,0x14a3,0x14a2,0x14a1,0x14a0,0x149f,0x149e,0x149c,0x149a,0x1499,
+ 0x1498,0x1497,0x1496,0x1495,0x1494,0x1493,0x1492,0x1491,0x148f,0x148e,0x148c,0x148b,0x148a,0x1489,0x1488,0x1487,
+ 0x1486,0x1485,0x1484,0x1482,0x1481,0x1480,0x147f,0x147d,0x147c,0x147b,0x147a,0x1479,0x1478,0x1477,0x1476,0x1474,
+ 0x1473,0x1472,0x1471,0x146f,0x146e,0x146d,0x146c,0x146b,0x146a,0x1469,0x1467,0x1466,0x1465,0x1464,0x1463,0x1461,
+ 0x1460,0x145f,0x145e,0x145d,0x145c,0x145a,0x1459,0x1458,0x1457,0x1456,0x1455,0x1453,0x1452,0x1451,0x1450,0x144f,
+ 0x144d,0x144c,0x144b,0x144a,0x1449,0x1448,0x1447,0x1445,0x1444,0x1443,0x1442,0x1440,0x143f,0x143e,0x143d,0x143c,
+ 0x143b,0x143a,0x1439,0x1438,0x1437,0x1436,0x1435,0x1433,0x1432,0x1431,0x142f,0x142e,0x142d,0x142c,0x142b,0x142a,
+ 0x1429,0x1428,0x1427,0x1426,0x1424,0x1423,0x1421,0x1420,0x141f,0x141e,0x141d,0x141c,0x141b,0x141a,0x1419,0x1418,
+ 0x1417,0x1414,0x1413,0x1412,0x1411,0x1410,0x140f,0x140e,0x140d,0x140c,0x140b,0x140a,0x1409,0x1406,0x1405,0x1404,
+ 0x1403,0x1402,0x1401,0x1400,0x13ff,0x13fe,0x13fd,0x13fc,0x13fb,0x13fa,0x13f7,0x13f6,0x13f5,0x13f4,0x13f3,0x13f2,
+ 0x13f1,0x13f0,0x13ef,0x13ee,0x13ed,0x13ec,0x13ea,0x13e8,0x13e7,0x13e6,0x13e5,0x13e4,0x13e3,0x13e2,0x13e1,0x13e0,
+ 0x13df,0x13de,0x13dc,0x13db,0x13d9,0x13d8,0x13d7,0x13d6,0x13d5,0x13d4,0x13d3,0x13d2,0x13d1,0x13cf,0x13ce,0x13cd,
+ 0x13cc,0x13ca,0x13c9,0x13c8,0x13c7,0x13c6,0x13c5,0x13c4,0x13c3,0x13c1,0x13c0,0x13bf,0x13be,0x13bc,0x13bb,0x13ba,
+ 0x13b9,0x13b8,0x13b7,0x13b6,0x13b5,0x13b3,0x13b2,0x13b1,0x13b0,0x13af,0x13ad,0x13ac,0x13ab,0x13aa,0x13a9,0x13a8,
+ 0x13a7,0x13a5,0x13a4,0x13a3,0x13a1,0x13a0,0x139f,0x139e,0x139d,0x139c,0x139b,0x139a,0x1399,0x1397,0x1396,0x1395,
+ 0x1394,0x1392,0x1391,0x1390,0x138f,0x138e,0x138d,0x138c,0x138b,0x138a,0x1388,0x1387,0x1386,0x1385,0x1384,0x1382,
+ 0x1381,0x1380,0x137f,0x137e,0x137d,0x137c,0x137a,0x1379,0x1378,0x1377,0x1376,0x1375,0x1373,0x1372,0x1371,0x1370,
+ 0x136f,0x136e,0x136c,0x136b,0x136a,0x1369,0x1368,0x1367,0x1366,0x1365,0x1363,0x1362,0x1361,0x1360,0x135f,0x135d,
+ 0x135c,0x135b,0x135a,0x1359,0x1358,0x1357,0x1356,0x1354,0x1353,0x1352,0x1351,0x134f,0x134e,0x134d,0x134c,0x134b,
+ 0x134a,0x1349,0x1348,0x1347,0x1346,0x1344,0x1343,0x1342,0x1340,0x133f,0x133e,0x133d,0x133c,0x133b,0x133a,0x1339,
+ 0x1338,0x1337,0x1335,0x1334,0x1332,0x1331,0x1330,0x132f,0x132e,0x132d,0x132c,0x132b,0x132a,0x1329,0x1328,0x1327,
+ 0x1325,0x1323,0x1322,0x1321,0x1320,0x131f,0x131e,0x131d,0x131c,0x131b,0x131a,0x1319,0x1318,0x1315,0x1314,0x1313,
+ 0x1312,0x1311,0x1310,0x130f,0x130e,0x130d,0x130c,0x130b,0x130a,0x1309,0x1308,0x1305,0x1304,0x1303,0x1302,0x1301,
+ 0x1300,0x12ff,0x12fe,0x12fd,0x12fc,0x12fb,0x12fa,0x12f8,0x12f6,0x12f5,0x12f4,0x12f3,0x12f2,0x12f1,0x12f0,0x12ef,
+ 0x12ee,0x12ed,0x12ec,0x12eb,0x12e9,0x12e8,0x12e6,0x12e5,0x12e4,0x12e3,0x12e2,0x12e1,0x12e0,0x12df,0x12de,0x12dd,
+ 0x12db,0x12da,0x12d9,0x12d7,0x12d6,0x12d5,0x12d4,0x12d3,0x12d2,0x12d1,0x12d0,0x12cf,0x12ce,0x12cc,0x12cb,0x12ca,
+ 0x12c9,0x12c7,0x12c6,0x12c5,0x12c4,0x12c3,0x12c2,0x12c1,0x12c0,0x12be,0x12bd,0x12bc,0x12bb,0x12ba,0x12b8,0x12b7,
+ 0x12b6,0x12b5,0x12b4,0x12b3,0x12b2,0x12b1,0x12af,0x12ae,0x12ad,0x12ac,0x12ab,0x12a9,0x12a8,0x12a7,0x12a6,0x12a5,
+ 0x12a4,0x12a3,0x12a1,0x12a0,0x129f,0x129e,0x129d,0x129c,0x129b,0x1299,0x1298,0x1297,0x1296,0x1295,0x1294,0x1292,
+ 0x1291,0x1290,0x128f,0x128e,0x128d,0x128c,0x128a,0x1289,0x1288,0x1287,0x1286,0x1284,0x1283,0x1282,0x1281,0x1280,
+ 0x127f,0x127d,0x127c,0x127b,0x127a,0x1279,0x1278,0x1277,0x1276,0x1275,0x1274,0x1273,0x1271,0x1270,0x126f,0x126d,
+ 0x126c,0x126b,0x126a,0x1269,0x1268,0x1267,0x1266,0x1265,0x1264,0x1262,0x1261,0x1260,0x125f,0x125d,0x125c,0x125b,
+ 0x125a,0x1259,0x1258,0x1257,0x1256,0x1255,0x1253,0x1252,0x1251,0x1250,0x124f,0x124d,0x124c,0x124b,0x124a,0x1249,
+ 0x1248,0x1247,0x1246,0x1245,0x1243,0x1242,0x1241,0x1240,0x123f,0x123d,0x123c,0x123b,0x123a,0x1239,0x1238,0x1237,
+ 0x1236,0x1234,0x1233,0x1232,0x1231,0x1230,0x122f,0x122e,0x122c,0x122b,0x122a,0x1229,0x1228,0x1227,0x1225,0x1224,
+ 0x1223,0x1222,0x1221,0x1220,0x121f,0x121e,0x121c,0x121b,0x121a,0x1219,0x1218,0x1216,0x1215,0x1214,0x1213,0x1212,
+ 0x1211,0x1210,0x120f,0x120e,0x120c,0x120b,0x120a,0x1209,0x1207,0x1206,0x1205,0x1204,0x1203,0x1202,0x1201,0x1200,
+ 0x11ff,0x11fe,0x11fc,0x11fb,0x11fa,0x11f9,0x11f7,0x11f6,0x11f5,0x11f4,0x11f3,0x11f2,0x11f1,0x11f0,0x11ef,0x11ee,
+ 0x11ed,0x11eb,0x11ea,0x11e8,0x11e7,0x11e6,0x11e5,0x11e4,0x11e3,0x11e2,0x11e1,0x11e0,0x11df,0x11de,0x11dd,0x11db,
+ 0x11d9,0x11d8,0x11d7,0x11d6,0x11d5,0x11d4,0x11d3,0x11d2,0x11d1,0x11d0,0x11cf,0x11ce,0x11cd,0x11ca,0x11c9,0x11c8,
+ 0x11c7,0x11c6,0x11c5,0x11c4,0x11c3,0x11c2,0x11c1,0x11c0,0x11bf,0x11be,0x11bd,0x11ba,0x11b9,0x11b8,0x11b7,0x11b6,
+ 0x11b5,0x11b4,0x11b3,0x11b2,0x11b1,0x11b0,0x11af,0x11ae,0x11ad,0x11aa,0x11a9,0x11a8,0x11a7,0x11a6,0x11a5,0x11a4,
+ 0x11a3,0x11a2,0x11a1,0x11a0,0x119f,0x119e,0x119c,0x119b,0x1199,0x1198,0x1197,0x1196,0x1195,0x1194,0x1193,0x1192,
+ 0x1191,0x1190,0x118f,0x118d,0x118c,0x118b,0x1189,0x1188,0x1187,0x1186,0x1185,0x1184,0x1183,0x1182,0x1181,0x1180,
+ 0x117e,0x117d,0x117c,0x117b,0x1179,0x1178,0x1177,0x1176,0x1175,0x1174,0x1173,0x1172,0x1171,0x1170,0x116e,0x116d,
+ 0x116c,0x116b,0x1169,0x1168,0x1167,0x1166,0x1165,0x1164,0x1163,0x1162,0x1161,0x115f,0x115e,0x115d,0x115c,0x115b,
+ 0x115a,0x1159,0x1157,0x1156,0x1155,0x1154,0x1153,0x1152,0x1151,0x1150,0x114f,0x114e,0x114c,0x114b,0x114a,0x1149,
+ 0x1147,0x1146,0x1145,0x1144,0x1143,0x1142,0x1141,0x1140,0x113f,0x113e,0x113d,0x113b,0x113a,0x1139,0x1137,0x1136,
+ 0x1135,0x1134,0x1133,0x1132,0x1131,0x1130,0x112f,0x112e,0x112d,0x112c,0x112a,0x1129,0x1127,0x1126,0x1125,0x1124,
+ 0x1123,0x1122,0x1121,0x1120,0x111f,0x111e,0x111d,0x111c,0x111b,0x1119,0x1117,0x1116,0x1115,0x1114,0x1113,0x1112,
+ 0x1111,0x1110,0x110f,0x110e,0x110d,0x110c,0x110b,0x110a,0x1107,0x1106,0x1105,0x1104,0x1103,0x1102,0x1101,0x1100,
+ 0x10ff,0x10fe,0x10fd,0x10fc,0x10fb,0x10fa,0x10f9,0x10f6,0x10f5,0x10f4,0x10f3,0x10f2,0x10f1,0x10f0,0x10ef,0x10ee,
+ 0x10ed,0x10ec,0x10eb,0x10ea,0x10e9,0x10e7,0x10e5,0x10e4,0x10e3,0x10e2,0x10e1,0x10e0,0x10df,0x10de,0x10dd,0x10dc,
+ 0x10db,0x10da,0x10d9,0x10d7,0x10d6,0x10d4,0x10d3,0x10d2,0x10d1,0x10d0,0x10cf,0x10ce,0x10cd,0x10cc,0x10cb,0x10ca,
+ 0x10c8,0x10c7,0x10c6,0x10c5,0x10c4,0x10c2,0x10c1,0x10c0,0x10bf,0x10bd,0x10bc,0x10bb,0x10ba,0x10b9,0x10b8,0x10b7,
+ 0x10b6,0x10b5,0x10b4,0x10b3,0x10b1,0x10b0,0x10af,0x10ae,0x10ad,0x10ab,0x10aa,0x10a9,0x10a8,0x10a7,0x10a6,0x10a5,
+ 0x10a4,0x10a3,0x10a2,0x10a0,0x109f,0x109e,0x109d,0x109c,0x109b,0x1099,0x1098,0x1097,0x1096,0x1095,0x1094,0x1093,
+ 0x1092,0x1091,0x108f,0x108e,0x108d,0x108c,0x108b,0x108a,0x1089,0x1087,0x1086,0x1085,0x1084,0x1083,0x1082,0x1081,
+ 0x1080,0x107e,0x107d,0x107c,0x107b,0x107a,0x1079,0x1078,0x1077,0x1075,0x1074,0x1073,0x1072,0x1071,0x1070,0x106f,
+ 0x106d,0x106c,0x106b,0x106a,0x1069,0x1068,0x1067,0x1066,0x1065,0x1063,0x1062,0x1061,0x1060,0x105f,0x105e,0x105c,
+ 0x105b,0x105a,0x1059,0x1058,0x1057,0x1056,0x1055,0x1054,0x1053,0x1051,0x1050,0x104f,0x104e,0x104d,0x104b,0x104a,
+ 0x1049,0x1048,0x1047,0x1046,0x1045,0x1044,0x1043,0x1042,0x1041,0x103f,0x103e,0x103d,0x103c,0x103a,0x1039,0x1038,
+ 0x1037,0x1036,0x1035,0x1034,0x1033,0x1032,0x1031,0x1030,0x102f,0x102d,0x102c,0x102b,0x1029,0x1028,0x1027,0x1026,
+ 0x1025,0x1024,0x1023,0x1022,0x1021,0x1020,0x101f,0x101e,0x101d,0x101b,0x101a,0x1018,0x1017,0x1016,0x1015,0x1014,
+ 0x1013,0x1012,0x1011,0x1010,0x100f,0x100e,0x100d,0x100c,0x100b,0x1009,0x1007,0x1006,0x1005,0x1004,0x1003,0x1002,
+ 0x1001,0x1000,0xfff,0xffe,0xffd,0xffc,0xffb,0xffa,0xff9,0xff6,0xff5,0xff4,0xff3,0xff2,0xff1,0xff0,
+ 0xfef,0xfee,0xfed,0xfec,0xfeb,0xfea,0xfe9,0xfe8,0xfe7,0xfe4,0xfe3,0xfe2,0xfe1,0xfe0,0xfdf,0xfde,
+ 0xfdd,0xfdc,0xfdb,0xfda,0xfd9,0xfd8,0xfd7,0xfd6,0xfd4,0xfd2,0xfd1,0xfd0,0xfcf,0xfce,0xfcd,0xfcc,
+ 0xfcb,0xfca,0xfc9,0xfc8,0xfc7,0xfc6,0xfc5,0xfc3,0xfc2,0xfc0,0xfbf,0xfbe,0xfbd,0xfbc,0xfbb,0xfba,
+ 0xfb9,0xfb8,0xfb7,0xfb6,0xfb5,0xfb4,0xfb2,0xfb1,0xfb0,0xfae,0xfad,0xfac,0xfab,0xfaa,0xfa9,0xfa8,
+ 0xfa6,0xfa5,0xfa4,0xfa3,0xfa2,0xfa1,0xfa0,0xf9f,0xf9e,0xf9d,0xf9c,0xf9b,0xf99,0xf97,0xf96,0xf95,
+ 0xf94,0xf93,0xf92,0xf91,0xf90,0xf8f,0xf8e,0xf8d,0xf8c,0xf8b,0xf8a,0xf89,0xf88,0xf86,0xf84,0xf83,
+ 0xf82,0xf81,0xf80,0xf7f,0xf7e,0xf7d,0xf7c,0xf7b,0xf7a,0xf79,0xf78,0xf77,0xf76,0xf74,0xf73,0xf71,
+ 0xf70,0xf6f,0xf6e,0xf6d,0xf6c,0xf6b,0xf6a,0xf69,0xf68,0xf67,0xf66,0xf65,0xf64,0xf62,0xf61,0xf60,
+ 0xf5f,0xf5d,0xf5c,0xf5b,0xf5a,0xf59,0xf58,0xf57,0xf56,0xf55,0xf54,0xf53,0xf52,0xf50,0xf4f,0xf4e,
+ 0xf4d,0xf4c,0xf4a,0xf49,0xf48,0xf47,0xf46,0xf45,0xf44,0xf43,0xf42,0xf41,0xf40,0xf3e,0xf3d,0xf3c,
+ 0xf3b,0xf3a,0xf39,0xf37,0xf36,0xf35,0xf34,0xf33,0xf32,0xf31,0xf30,0xf2f,0xf2e,0xf2c,0xf2b,0xf2a,
+ 0xf29,0xf28,0xf27,0xf26,0xf24,0xf23,0xf22,0xf21,0xf20,0xf1f,0xf1e,0xf1d,0xf1c,0xf1a,0xf19,0xf18,
+ 0xf17,0xf16,0xf15,0xf14,0xf13,0xf11,0xf10,0xf0f,0xf0e,0xf0d,0xf0c,0xf0b,0xf0a,0xf08,0xf07,0xf06,
+ 0xf05,0xf04,0xf03,0xf02,0xf01,0xf00,0xefe,0xefd,0xefc,0xefb,0xefa,0xef9,0xef8,0xef6,0xef5,0xef4,
+ 0xef3,0xef2,0xef1,0xef0,0xeef,0xeee,0xeed,0xeeb,0xeea,0xee9,0xee8,0xee7,0xee6,0xee4,0xee3,0xee2,
+ 0xee1,0xee0,0xedf,0xede,0xedd,0xedc,0xedb,0xeda,0xed8,0xed7,0xed6,0xed5,0xed4,0xed2,0xed1,0xed0,
+ 0xecf,0xece,0xecd,0xecc,0xecb,0xeca,0xec9,0xec8,0xec7,0xec5,0xec4,0xec3,0xec2,0xec0,0xebf,0xebe,
+ 0xebd,0xebc,0xebb,0xeba,0xeb9,0xeb8,0xeb7,0xeb6,0xeb5,0xeb4,0xeb2,0xeb1,0xeb0,0xeae,0xead,0xeac,
+ 0xeab,0xeaa,0xea9,0xea8,0xea7,0xea6,0xea5,0xea4,0xea3,0xea2,0xea1,0xe9f,0xe9e,0xe9c,0xe9b,0xe9a,
+ 0xe99,0xe98,0xe97,0xe96,0xe95,0xe94,0xe93,0xe92,0xe91,0xe90,0xe8f,0xe8e,0xe8c,0xe8a,0xe89,0xe88,
+ 0xe88,0xe86,0xe85,0xe84,0xe83,0xe82,0xe81,0xe80,0xe7f,0xe7e,0xe7c,0xe7b,0xe7a,0xe79,0xe78,0xe77,
+ 0xe76,0xe75,0xe74,0xe72,0xe71,0xe70,0xe6f,0xe6e,0xe6d,0xe6c,0xe6b,0xe69,0xe68,0xe67,0xe66,0xe65,
+ 0xe64,0xe63,0xe62,0xe61,0xe60,0xe5e,0xe5d,0xe5c,0xe5b,0xe5a,0xe59,0xe58,0xe56,0xe55,0xe54,0xe53,
+ 0xe52,0xe51,0xe50,0xe4f,0xe4e,0xe4d,0xe4c,0xe4a,0xe49,0xe48,0xe47,0xe46,0xe45,0xe44,0xe42,0xe41,
+ 0xe40,0xe3f,0xe3e,0xe3d,0xe3c,0xe3b,0xe3a,0xe39,0xe38,0xe37,0xe35,0xe34,0xe33,0xe32,0xe31,0xe2f,
+ 0xe2e,0xe2d,0xe2c,0xe2b,0xe2a,0xe29,0xe28,0xe27,0xe26,0xe25,0xe24,0xe23,0xe21,0xe20,0xe1f,0xe1e,
+ 0xe1c,0xe1b,0xe1a,0xe19,0xe18,0xe17,0xe16,0xe15,0xe14,0xe13,0xe12,0xe11,0xe10,0xe0f,0xe0d,0xe0c,
+ 0xe0b,0xe09,0xe08,0xe07,0xe06,0xe05,0xe04,0xe03,0xe02,0xe01,0xe00,0xdff,0xdfe,0xdfd,0xdfc,0xdfb,
+ 0xdfa,0xdf8,0xdf7,0xdf5,0xdf4,0xdf3,0xdf2,0xdf1,0xdf0,0xdef,0xdee,0xded,0xdec,0xdeb,0xdea,0xde9,
+ 0xde8,0xde7,0xde6,0xde4,0xde2,0xde1,0xde0,0xddf,0xdde,0xddd,0xddc,0xddb,0xdda,0xdd9,0xdd8,0xdd7,
+ 0xdd6,0xdd5,0xdd4,0xdd3,0xdd2,0xdcf,0xdce,0xdcd,0xdcc,0xdcb,0xdca,0xdc9,0xdc8,0xdc7,0xdc6,0xdc5,
+ 0xdc4,0xdc3,0xdc2,0xdc1,0xdc0,0xdbf,0xdbe,0xdbb,0xdba,0xdb9,0xdb8,0xdb7,0xdb6,0xdb5,0xdb4,0xdb3,
+ 0xdb2,0xdb1,0xdb0,0xdaf,0xdae,0xdad,0xdac,0xdab,0xdaa,0xda8,0xda6,0xda5,0xda4,0xda3,0xda2,0xda1,
+ 0xda0,0xd9f,0xd9e,0xd9d,0xd9c,0xd9b,0xd9a,0xd99,0xd98,0xd97,0xd95,0xd94,0xd92,0xd91,0xd90,0xd8f,
+ 0xd8e,0xd8d,0xd8c,0xd8b,0xd8a,0xd89,0xd88,0xd87,0xd86,0xd85,0xd84,0xd82,0xd81,0xd80,0xd7e,0xd7d,
+ 0xd7c,0xd7b,0xd7a,0xd79,0xd78,0xd77,0xd76,0xd75,0xd74,0xd73,0xd72,0xd71,0xd70,0xd6e,0xd6d,0xd6c,
+ 0xd6b,0xd6a,0xd69,0xd68,0xd67,0xd65,0xd64,0xd63,0xd62,0xd61,0xd60,0xd5f,0xd5e,0xd5c,0xd5b,0xd5a,
+ 0xd59,0xd58,0xd57,0xd56,0xd55,0xd54,0xd53,0xd52,0xd51,0xd4f,0xd4e,0xd4d,0xd4c,0xd4b,0xd4a,0xd49,
+ 0xd47,0xd46,0xd45,0xd44,0xd43,0xd42,0xd41,0xd40,0xd3f,0xd3e,0xd3d,0xd3c,0xd3b,0xd39,0xd38,0xd37,
+ 0xd36,0xd35,0xd33,0xd32,0xd31,0xd30,0xd2f,0xd2e,0xd2d,0xd2c,0xd2b,0xd2a,0xd29,0xd28,0xd27,0xd26,
+ 0xd25,0xd23,0xd22,0xd21,0xd20,0xd1e,0xd1d,0xd1c,0xd1b,0xd1a,0xd19,0xd18,0xd17,0xd16,0xd15,0xd14,
+ 0xd13,0xd12,0xd11,0xd10,0xd0e,0xd0d,0xd0c,0xd0b,0xd09,0xd08,0xd07,0xd06,0xd05,0xd04,0xd03,0xd02,
+ 0xd01,0xd00,0xcff,0xcfe,0xcfd,0xcfc,0xcfb,0xcfa,0xcf8,0xcf7,0xcf5,0xcf4,0xcf3,0xcf2,0xcf1,0xcf0,
+ 0xcef,0xcee,0xced,0xcec,0xceb,0xcea,0xce9,0xce8,0xce7,0xce6,0xce5,0xce4,0xce2,0xce0,0xcdf,0xcde,
+ 0xcdd,0xcdc,0xcdb,0xcda,0xcd9,0xcd8,0xcd7,0xcd6,0xcd5,0xcd4,0xcd3,0xcd2,0xcd1,0xcd0,0xccf,0xccd,
+ 0xccb,0xcca,0xcc9,0xcc8,0xcc7,0xcc6,0xcc5,0xcc4,0xcc3,0xcc2,0xcc1,0xcc0,0xcbf,0xcbe,0xcbd,0xcbc,
+ 0xcbb,0xcba,0xcb9,0xcb6,0xcb5,0xcb4,0xcb3,0xcb2,0xcb1,0xcb0,0xcaf,0xcae,0xcad,0xcac,0xcab,0xcaa,
+ 0xca9,0xca8,0xca7,0xca6,0xca5,0xca4,0xca2,0xca0,0xc9f,0xc9e,0xc9d,0xc9c,0xc9b,0xc9a,0xc99,0xc98,
+ 0xc97,0xc96,0xc95,0xc94,0xc93,0xc92,0xc91,0xc90,0xc8f,0xc8d,0xc8b,0xc8a,0xc89,0xc88,0xc87,0xc86,
+ 0xc85,0xc84,0xc83,0xc82,0xc81,0xc80,0xc7f,0xc7e,0xc7d,0xc7c,0xc7b,0xc7a,0xc78,0xc77,0xc75,0xc74,
+ 0xc73,0xc72,0xc71,0xc70,0xc6f,0xc6e,0xc6d,0xc6c,0xc6b,0xc6a,0xc69,0xc68,0xc67,0xc66,0xc64,0xc63,
+ 0xc62,0xc61,0xc5f,0xc5e,0xc5d,0xc5c,0xc5b,0xc5a,0xc59,0xc58,0xc57,0xc56,0xc55,0xc54,0xc53,0xc52,
+ 0xc51,0xc50,0xc4f,0xc4d,0xc4c,0xc4b,0xc4a,0xc49,0xc48,0xc47,0xc46,0xc44,0xc43,0xc42,0xc41,0xc40,
+ 0xc3f,0xc3e,0xc3d,0xc3c,0xc3b,0xc3a,0xc39,0xc37,0xc36,0xc35,0xc34,0xc33,0xc32,0xc31,0xc30,0xc2f,
+ 0xc2e,0xc2c,0xc2b,0xc2a,0xc29,0xc28,0xc27,0xc26,0xc25,0xc24,0xc23,0xc22,0xc20,0xc1f,0xc1e,0xc1d,
+ 0xc1c,0xc1b,0xc1a,0xc19,0xc18,0xc17,0xc15,0xc14,0xc13,0xc12,0xc11,0xc10,0xc0f,0xc0e,0xc0d,0xc0c,
+ 0xc0a,0xc09,0xc08,0xc07,0xc06,0xc05,0xc04,0xc03,0xc02,0xc01,0xc00,0xbfe,0xbfd,0xbfc,0xbfb,0xbfa,
+ 0xbf9,0xbf8,0xbf7,0xbf6,0xbf4,0xbf3,0xbf2,0xbf1,0xbf0,0xbef,0xbee,0xbed,0xbec,0xbeb,0xbea,0xbe9,
+ 0xbe8,0xbe6,0xbe5,0xbe4,0xbe3,0xbe2,0xbe1,0xbe0,0xbdf,0xbdd,0xbdc,0xbdb,0xbda,0xbd9,0xbd8,0xbd7,
+ 0xbd6,0xbd5,0xbd4,0xbd3,0xbd2,0xbd1,0xbcf,0xbce,0xbcd,0xbcc,0xbcb,0xbca,0xbc9,0xbc7,0xbc6,0xbc5,
+ 0xbc4,0xbc3,0xbc2,0xbc1,0xbc0,0xbbf,0xbbd,0xbbc,0xbbb,0xbba,0xbb9,0xbb8,0xbb7,0xbb5,0xbb4,0xbb3,
+ 0xbb2,0xbb1,0xbb0,0xbaf,0xbae,0xbad,0xbac,0xbab,0xbaa,0xba9,0xba8,0xba7,0xba6,0xba5,0xba3,0xba2,
+ 0xba1,0xba0,0xb9f,0xb9d,0xb9c,0xb9b,0xb9a,0xb99,0xb98,0xb97,0xb96,0xb95,0xb94,0xb93,0xb92,0xb91,
+ 0xb90,0xb8f,0xb8e,0xb8d,0xb8c,0xb8a,0xb89,0xb88,0xb87,0xb86,0xb84,0xb83,0xb82,0xb81,0xb80,0xb7f,
+ 0xb7e,0xb7d,0xb7c,0xb7b,0xb7a,0xb79,0xb78,0xb77,0xb76,0xb75,0xb74,0xb73,0xb71,0xb70,0xb6f,0xb6e,
+ 0xb6c,0xb6b,0xb6a,0xb69,0xb68,0xb67,0xb66,0xb65,0xb64,0xb63,0xb62,0xb61,0xb60,0xb5f,0xb5e,0xb5d,
+ 0xb5c,0xb5b,0xb5a,0xb58,0xb57,0xb56,0xb54,0xb53,0xb52,0xb51,0xb50,0xb4f,0xb4e,0xb4d,0xb4c,0xb4b,
+ 0xb4a,0xb49,0xb48,0xb47,0xb46,0xb45,0xb44,0xb43,0xb42,0xb41,0xb40,0xb3e,0xb3c,0xb3b,0xb3a,0xb39,
+ 0xb38,0xb37,0xb36,0xb35,0xb34,0xb33,0xb32,0xb31,0xb30,0xb2f,0xb2e,0xb2d,0xb2c,0xb2b,0xb2a,0xb29,
+ 0xb28,0xb27,0xb25,0xb23,0xb22,0xb21,0xb20,0xb1f,0xb1e,0xb1d,0xb1c,0xb1b,0xb1a,0xb19,0xb18,0xb17,
+ 0xb16,0xb15,0xb14,0xb13,0xb12,0xb11,0xb10,0xb0f,0xb0e,0xb0b,0xb0a,0xb09,0xb08,0xb07,0xb06,0xb05,
+ 0xb04,0xb03,0xb02,0xb01,0xb00,0xaff,0xafe,0xafd,0xafc,0xafb,0xafa,0xaf9,0xaf8,0xaf7,0xaf6,0xaf5,
+ 0xaf3,0xaf1,0xaf0,0xaef,0xaee,0xaed,0xaec,0xaeb,0xaea,0xae9,0xae8,0xae7,0xae6,0xae5,0xae4,0xae3,
+ 0xae2,0xae1,0xae0,0xadf,0xade,0xadd,0xadb,0xada,0xad8,0xad7,0xad6,0xad5,0xad4,0xad3,0xad2,0xad1,
+ 0xad0,0xacf,0xace,0xacd,0xacc,0xacb,0xaca,0xac9,0xac8,0xac7,0xac6,0xac5,0xac4,0xac2,0xac1,0xabf,
+ 0xabe,0xabd,0xabc,0xabb,0xaba,0xab9,0xab8,0xab7,0xab6,0xab5,0xab4,0xab3,0xab2,0xab1,0xab0,0xaaf,
+ 0xaae,0xaab,0xaaa,0xaa9,0xaa8,0xaa7,0xaa6,0xaa5,0xaa4,0xaa3,0xaa2,0xaa1,0xaa0,0xa9f,0xa9e,0xa9d,
+ 0xa9c,0xa9b,0xa9a,0xa99,0xa98,0xa97,0xa96,0xa95,0xa94,0xa93,0xa90,0xa8f,0xa8e,0xa8d,0xa8c,0xa8b,
+ 0xa8a,0xa89,0xa88,0xa87,0xa86,0xa85,0xa84,0xa83,0xa82,0xa81,0xa80,0xa7f,0xa7e,0xa7d,0xa7c,0xa7b,
+ 0xa7a,0xa79,0xa77,0xa76,0xa74,0xa73,0xa72,0xa71,0xa70,0xa6f,0xa6e,0xa6d,0xa6c,0xa6b,0xa6a,0xa69,
+ 0xa68,0xa67,0xa66,0xa65,0xa64,0xa63,0xa62,0xa61,0xa60,0xa5f,0xa5e,0xa5c,0xa5b,0xa59,0xa58,0xa57,
+ 0xa56,0xa55,0xa54,0xa53,0xa52,0xa51,0xa50,0xa4f,0xa4e,0xa4d,0xa4c,0xa4b,0xa4a,0xa49,0xa48,0xa47,
+ 0xa46,0xa45,0xa44,0xa43,0xa41,0xa40,0xa3f,0xa3d,0xa3c,0xa3b,0xa3a,0xa39,0xa38,0xa37,0xa36,0xa35,
+ 0xa34,0xa33,0xa32,0xa31,0xa30,0xa2f,0xa2e,0xa2d,0xa2c,0xa2b,0xa2a,0xa29,0xa27,0xa26,0xa25,0xa24,
+ 0xa23,0xa21,0xa20,0xa1f,0xa1e,0xa1d,0xa1c,0xa1b,0xa1a,0xa19,0xa18,0xa17,0xa16,0xa15,0xa14,0xa13,
+ 0xa12,0xa11,0xa10,0xa0f,0xa0e,0xa0c,0xa0b,0xa0a,0xa09,0xa08,0xa06,0xa05,0xa04,0xa03,0xa02,0xa01,
+ 0xa00,0x9ff,0x9fe,0x9fd,0x9fc,0x9fb,0x9fa,0x9f9,0x9f8,0x9f7,0x9f6,0x9f5,0x9f4,0x9f2,0x9f1,0x9f0,
+ 0x9ef,0x9ee,0x9ed,0x9ec,0x9ea,0x9e9,0x9e8,0x9e7,0x9e6,0x9e5,0x9e4,0x9e3,0x9e2,0x9e1,0x9e0,0x9df,
+ 0x9de,0x9dd,0x9dc,0x9db,0x9da,0x9d9,0x9d7,0x9d6,0x9d5,0x9d4,0x9d3,0x9d2,0x9d1,0x9cf,0x9ce,0x9cd,
+ 0x9cc,0x9cb,0x9ca,0x9c9,0x9c8,0x9c7,0x9c6,0x9c5,0x9c4,0x9c3,0x9c2,0x9c1,0x9c0,0x9bf,0x9be,0x9bc,
+ 0x9bb,0x9ba,0x9b9,0x9b8,0x9b7,0x9b6,0x9b5,0x9b3,0x9b2,0x9b1,0x9b0,0x9af,0x9ae,0x9ad,0x9ac,0x9ab,
+ 0x9aa,0x9a9,0x9a8,0x9a7,0x9a6,0x9a5,0x9a4,0x9a2,0x9a1,0x9a0,0x99f,0x99e,0x99d,0x99c,0x99b,0x99a,
+ 0x998,0x997,0x996,0x995,0x994,0x993,0x992,0x991,0x990,0x98f,0x98e,0x98d,0x98c,0x98b,0x98a,0x989,
+ 0x988,0x987,0x986,0x985,0x983,0x982,0x980,0x97f,0x97e,0x97d,0x97c,0x97b,0x97a,0x979,0x978,0x977,
+ 0x976,0x975,0x974,0x973,0x972,0x971,0x970,0x96f,0x96e,0x96d,0x96c,0x96b,0x96a,0x969,0x968,0x966,
+ 0x965,0x964,0x962,0x961,0x960,0x95f,0x95e,0x95d,0x95c,0x95b,0x95a,0x959,0x958,0x957,0x956,0x955,
+ 0x954,0x953,0x952,0x951,0x950,0x94f,0x94e,0x94d,0x94c,0x94b,0x949,0x948,0x947,0x946,0x945,0x943,
+ 0x942,0x941,0x940,0x93f,0x93e,0x93d,0x93c,0x93b,0x93a,0x939,0x938,0x937,0x936,0x935,0x934,0x933,
+ 0x932,0x931,0x930,0x92f,0x92e,0x92d,0x92b,0x92a,0x929,0x928,0x927,0x925,0x924,0x923,0x922,0x921,
+ 0x920,0x91f,0x91e,0x91d,0x91c,0x91b,0x91a,0x919,0x918,0x917,0x916,0x915,0x914,0x913,0x912,0x911,
+ 0x910,0x90e,0x90d,0x90c,0x90b,0x90a,0x909,0x908,0x906,0x905,0x904,0x903,0x902,0x901,0x900,0x8ff,
+ 0x8fe,0x8fd,0x8fc,0x8fb,0x8fa,0x8f9,0x8f8,0x8f7,0x8f6,0x8f5,0x8f4,0x8f3,0x8f2,0x8f0,0x8ef,0x8ee,
+ 0x8ed,0x8ec,0x8eb,0x8ea,0x8e8,0x8e7,0x8e6,0x8e5,0x8e4,0x8e3,0x8e2,0x8e1,0x8e0,0x8df,0x8de,0x8dd,
+ 0x8dc,0x8db,0x8da,0x8d9,0x8d8,0x8d7,0x8d6,0x8d5,0x8d3,0x8d2,0x8d1,0x8d0,0x8cf,0x8ce,0x8cd,0x8cc,
+ 0x8cb,0x8c9,0x8c8,0x8c7,0x8c6,0x8c5,0x8c4,0x8c3,0x8c2,0x8c1,0x8c0,0x8bf,0x8be,0x8bd,0x8bc,0x8bb,
+ 0x8ba,0x8b9,0x8b8,0x8b7,0x8b5,0x8b4,0x8b3,0x8b2,0x8b1,0x8b0,0x8af,0x8ae,0x8ad,0x8ab,0x8aa,0x8a9,
+ 0x8a8,0x8a7,0x8a6,0x8a5,0x8a4,0x8a3,0x8a2,0x8a1,0x8a0,0x89f,0x89e,0x89d,0x89c,0x89b,0x89a,0x898,
+ 0x897,0x896,0x895,0x894,0x893,0x892,0x891,0x890,0x88f,0x88d,0x88c,0x88b,0x88a,0x889,0x888,0x887,
+ 0x886,0x885,0x884,0x883,0x882,0x881,0x880,0x87f,0x87e,0x87d,0x87c,0x87b,0x87a,0x879,0x878,0x877,
+ 0x876,0x874,0x872,0x871,0x870,0x86f,0x86e,0x86d,0x86c,0x86b,0x86a,0x869,0x868,0x867,0x866,0x865,
+ 0x864,0x863,0x862,0x861,0x860,0x85f,0x85e,0x85d,0x85c,0x85b,0x85a,0x859,0x858,0x857,0x856,0x855,
+ 0x854,0x851,0x850,0x84f,0x84e,0x84d,0x84c,0x84b,0x84a,0x849,0x848,0x847,0x846,0x845,0x844,0x843,
+ 0x842,0x841,0x840,0x83f,0x83e,0x83d,0x83c,0x83b,0x83a,0x839,0x838,0x837,0x836,0x835,0x834,0x833,
+ 0x832,0x82f,0x82e,0x82d,0x82c,0x82b,0x82a,0x829,0x828,0x827,0x826,0x825,0x824,0x823,0x822,0x821,
+ 0x820,0x81f,0x81e,0x81d,0x81c,0x81b,0x81a,0x819,0x818,0x817,0x816,0x815,0x814,0x813,0x812,0x811,
+ 0x80f,0x80d,0x80c,0x80b,0x80a,0x809,0x808,0x807,0x806,0x805,0x804,0x803,0x802,0x801,0x800,0x7ff,
+ 0x7fe,0x7fd,0x7fc,0x7fb,0x7fa,0x7f9,0x7f8,0x7f7,0x7f6,0x7f5,0x7f4,0x7f3,0x7f2,0x7f1,0x7f0,0x7ee,
+ 0x7ed,0x7eb,0x7ea,0x7e9,0x7e8,0x7e7,0x7e6,0x7e5,0x7e4,0x7e3,0x7e2,0x7e1,0x7e0,0x7df,0x7de,0x7dd,
+ 0x7dc,0x7db,0x7da,0x7d9,0x7d8,0x7d7,0x7d6,0x7d5,0x7d4,0x7d3,0x7d2,0x7d1,0x7d0,0x7cf,0x7cd,0x7cc,
+ 0x7cb,0x7c9,0x7c8,0x7c7,0x7c6,0x7c5,0x7c4,0x7c3,0x7c2,0x7c1,0x7c0,0x7bf,0x7be,0x7bd,0x7bc,0x7bb,
+ 0x7ba,0x7b9,0x7b8,0x7b7,0x7b6,0x7b5,0x7b4,0x7b3,0x7b2,0x7b1,0x7b0,0x7af,0x7ae,0x7ac,0x7ab,0x7aa,
+ 0x7a9,0x7a7,0x7a6,0x7a5,0x7a4,0x7a3,0x7a2,0x7a1,0x7a0,0x79f,0x79e,0x79d,0x79c,0x79b,0x79a,0x799,
+ 0x798,0x797,0x796,0x795,0x794,0x793,0x792,0x791,0x790,0x78f,0x78e,0x78d,0x78b,0x78a,0x789,0x788,
+ 0x787,0x785,0x784,0x783,0x782,0x781,0x780,0x77f,0x77e,0x77d,0x77c,0x77b,0x77a,0x779,0x778,0x777,
+ 0x776,0x775,0x774,0x773,0x772,0x771,0x770,0x76f,0x76e,0x76d,0x76b,0x76a,0x769,0x768,0x767,0x766,
+ 0x765,0x764,0x763,0x762,0x761,0x760,0x75f,0x75d,0x75c,0x75b,0x75a,0x759,0x758,0x757,0x756,0x755,
+ 0x754,0x753,0x752,0x751,0x750,0x74f,0x74e,0x74d,0x74c,0x74b,0x74a,0x749,0x748,0x747,0x745,0x744,
+ 0x743,0x742,0x741,0x740,0x73f,0x73e,0x73d,0x73c,0x73b,0x73a,0x739,0x737,0x736,0x735,0x734,0x733,
+ 0x732,0x731,0x730,0x72f,0x72e,0x72d,0x72c,0x72b,0x72a,0x729,0x728,0x727,0x726,0x725,0x724,0x723,
+ 0x722,0x721,0x720,0x71e,0x71d,0x71c,0x71b,0x71a,0x719,0x718,0x717,0x716,0x715,0x714,0x712,0x711,
+ 0x710,0x70f,0x70e,0x70d,0x70c,0x70b,0x70a,0x709,0x708,0x707,0x706,0x705,0x704,0x703,0x702,0x701,
+ 0x700,0x6ff,0x6fe,0x6fd,0x6fc,0x6fb,0x6fa,0x6f8,0x6f7,0x6f6,0x6f5,0x6f4,0x6f3,0x6f2,0x6f1,0x6f0,
+ 0x6ef,0x6ee,0x6ec,0x6eb,0x6ea,0x6e9,0x6e8,0x6e7,0x6e6,0x6e5,0x6e4,0x6e3,0x6e2,0x6e1,0x6e0,0x6df,
+ 0x6de,0x6dd,0x6dc,0x6db,0x6da,0x6d9,0x6d8,0x6d7,0x6d6,0x6d5,0x6d4,0x6d3,0x6d1,0x6d0,0x6cf,0x6ce,
+ 0x6cd,0x6cc,0x6cb,0x6ca,0x6c9,0x6c7,0x6c6,0x6c5,0x6c4,0x6c3,0x6c2,0x6c1,0x6c0,0x6bf,0x6be,0x6bd,
+ 0x6bc,0x6bb,0x6ba,0x6b9,0x6b8,0x6b7,0x6b6,0x6b5,0x6b4,0x6b3,0x6b2,0x6b1,0x6b0,0x6af,0x6ae,0x6ad,
+ 0x6ac,0x6aa,0x6a9,0x6a8,0x6a7,0x6a6,0x6a5,0x6a4,0x6a3,0x6a1,0x6a0,0x69f,0x69e,0x69d,0x69c,0x69b,
+ 0x69a,0x699,0x698,0x697,0x696,0x695,0x694,0x693,0x692,0x691,0x690,0x68f,0x68e,0x68d,0x68c,0x68b,
+ 0x68a,0x689,0x688,0x687,0x686,0x684,0x683,0x682,0x681,0x680,0x67f,0x67e,0x67d,0x67b,0x67a,0x679,
+ 0x678,0x677,0x676,0x675,0x674,0x673,0x672,0x671,0x670,0x66f,0x66e,0x66d,0x66c,0x66b,0x66a,0x669,
+ 0x668,0x666,0x665,0x664,0x663,0x662,0x661,0x660,0x65f,0x65e,0x65d,0x65c,0x65b,0x65a,0x659,0x658,
+ 0x657,0x656,0x655,0x654,0x653,0x652,0x651,0x650,0x64f,0x64e,0x64d,0x64c,0x64b,0x64a,0x649,0x648,
+ 0x647,0x646,0x645,0x644,0x643,0x642,0x640,0x63f,0x63e,0x63d,0x63c,0x63a,0x639,0x638,0x637,0x636,
+ 0x635,0x634,0x633,0x632,0x631,0x630,0x62f,0x62e,0x62d,0x62c,0x62b,0x62a,0x629,0x628,0x627,0x626,
+ 0x625,0x624,0x623,0x622,0x621,0x620,0x61f,0x61e,0x61d,0x61c,0x61b,0x61a,0x619,0x618,0x617,0x615,
+ 0x614,0x613,0x612,0x611,0x610,0x60f,0x60d,0x60c,0x60b,0x60a,0x609,0x608,0x607,0x606,0x605,0x604,
+ 0x603,0x602,0x601,0x600,0x5ff,0x5fe,0x5fd,0x5fc,0x5fb,0x5fa,0x5f9,0x5f8,0x5f7,0x5f6,0x5f5,0x5f4,
+ 0x5f3,0x5f2,0x5f1,0x5f0,0x5ef,0x5ee,0x5ed,0x5ec,0x5eb,0x5e9,0x5e8,0x5e7,0x5e6,0x5e5,0x5e4,0x5e3,
+ 0x5e2,0x5e0,0x5df,0x5de,0x5dd,0x5dc,0x5db,0x5da,0x5d9,0x5d8,0x5d7,0x5d6,0x5d5,0x5d4,0x5d3,0x5d2,
+ 0x5d1,0x5d0,0x5cf,0x5ce,0x5cd,0x5cc,0x5cb,0x5ca,0x5c9,0x5c8,0x5c7,0x5c6,0x5c5,0x5c4,0x5c3,0x5c2,
+ 0x5c1,0x5c0,0x5bf,0x5bd,0x5bc,0x5bb,0x5ba,0x5b9,0x5b8,0x5b7,0x5b6,0x5b4,0x5b3,0x5b2,0x5b1,0x5b0,
+ 0x5af,0x5ae,0x5ad,0x5ac,0x5ab,0x5aa,0x5a9,0x5a8,0x5a7,0x5a6,0x5a5,0x5a4,0x5a3,0x5a2,0x5a1,0x5a0,
+ 0x59f,0x59e,0x59d,0x59c,0x59b,0x59a,0x599,0x598,0x597,0x596,0x595,0x594,0x592,0x591,0x590,0x58f,
+ 0x58e,0x58d,0x58c,0x58b,0x58a,0x589,0x587,0x586,0x585,0x584,0x583,0x582,0x581,0x580,0x57f,0x57e,
+ 0x57d,0x57c,0x57b,0x57a,0x579,0x578,0x577,0x576,0x575,0x574,0x573,0x572,0x571,0x570,0x56f,0x56e,
+ 0x56d,0x56c,0x56b,0x56a,0x569,0x568,0x566,0x565,0x564,0x563,0x562,0x561,0x560,0x55f,0x55e,0x55d,
+ 0x55c,0x55b,0x55a,0x559,0x558,0x557,0x556,0x555,0x554,0x553,0x552,0x551,0x550,0x54f,0x54d,0x54c,
+ 0x54b,0x54a,0x549,0x548,0x547,0x546,0x545,0x544,0x543,0x542,0x541,0x540,0x53f,0x53e,0x53d,0x53c,
+ 0x53b,0x53a,0x539,0x538,0x537,0x536,0x535,0x533,0x532,0x531,0x530,0x52f,0x52e,0x52d,0x52c,0x52b,
+ 0x52a,0x529,0x528,0x527,0x526,0x525,0x524,0x523,0x522,0x521,0x520,0x51f,0x51e,0x51d,0x51c,0x51b,
+ 0x519,0x518,0x517,0x516,0x515,0x514,0x513,0x512,0x511,0x510,0x50f,0x50e,0x50d,0x50c,0x50b,0x50a,
+ 0x509,0x508,0x507,0x506,0x505,0x504,0x503,0x502,0x501,0x500,0x4fe,0x4fd,0x4fc,0x4fb,0x4fa,0x4f9,
+ 0x4f8,0x4f7,0x4f6,0x4f5,0x4f4,0x4f3,0x4f2,0x4f1,0x4f0,0x4ef,0x4ee,0x4ed,0x4ec,0x4eb,0x4ea,0x4e9,
+ 0x4e8,0x4e7,0x4e5,0x4e4,0x4e3,0x4e2,0x4e1,0x4e0,0x4df,0x4de,0x4dd,0x4dc,0x4db,0x4da,0x4d9,0x4d8,
+ 0x4d7,0x4d6,0x4d5,0x4d4,0x4d3,0x4d2,0x4d1,0x4d0,0x4cf,0x4ce,0x4cd,0x4cc,0x4cb,0x4c9,0x4c8,0x4c7,
+ 0x4c6,0x4c5,0x4c4,0x4c3,0x4c2,0x4c1,0x4c0,0x4bf,0x4be,0x4bd,0x4bc,0x4bb,0x4ba,0x4b9,0x4b8,0x4b7,
+ 0x4b6,0x4b5,0x4b4,0x4b3,0x4b1,0x4b0,0x4af,0x4ae,0x4ad,0x4ac,0x4ab,0x4aa,0x4a9,0x4a8,0x4a7,0x4a6,
+ 0x4a5,0x4a4,0x4a3,0x4a2,0x4a1,0x4a0,0x49f,0x49e,0x49d,0x49c,0x49b,0x49a,0x499,0x498,0x497,0x496,
+ 0x495,0x493,0x492,0x491,0x490,0x48f,0x48e,0x48d,0x48c,0x48b,0x48a,0x489,0x488,0x487,0x486,0x485,
+ 0x484,0x483,0x482,0x481,0x480,0x47f,0x47e,0x47c,0x47b,0x47a,0x479,0x478,0x477,0x476,0x475,0x474,
+ 0x473,0x472,0x471,0x470,0x46f,0x46e,0x46d,0x46c,0x46b,0x46a,0x469,0x468,0x467,0x466,0x465,0x464,
+ 0x463,0x462,0x461,0x460,0x45e,0x45d,0x45c,0x45b,0x45a,0x459,0x458,0x457,0x456,0x455,0x454,0x453,
+ 0x452,0x451,0x450,0x44f,0x44e,0x44d,0x44c,0x44b,0x44a,0x449,0x448,0x447,0x446,0x445,0x444,0x443,
+ 0x442,0x441,0x440,0x43f,0x43e,0x43d,0x43c,0x43b,0x43a,0x439,0x438,0x437,0x436,0x435,0x434,0x433,
+ 0x432,0x430,0x42f,0x42e,0x42d,0x42c,0x42b,0x42a,0x429,0x428,0x427,0x426,0x425,0x424,0x423,0x422,
+ 0x421,0x41f,0x41e,0x41d,0x41c,0x41b,0x41a,0x419,0x418,0x417,0x416,0x415,0x414,0x413,0x412,0x411,
+ 0x410,0x40f,0x40e,0x40d,0x40c,0x40b,0x40a,0x409,0x408,0x407,0x406,0x405,0x404,0x403,0x402,0x401,
+ 0x400,0x3ff,0x3fe,0x3fd,0x3fc,0x3fb,0x3fa,0x3f9,0x3f8,0x3f7,0x3f6,0x3f5,0x3f4,0x3f3,0x3f2,0x3f1,
+ 0x3f0,0x3ee,0x3ed,0x3ec,0x3eb,0x3ea,0x3e9,0x3e8,0x3e7,0x3e6,0x3e5,0x3e4,0x3e3,0x3e2,0x3e1,0x3e0,
+ 0x3de,0x3dd,0x3dc,0x3db,0x3da,0x3d9,0x3d8,0x3d7,0x3d6,0x3d5,0x3d4,0x3d3,0x3d2,0x3d1,0x3d0,0x3cf,
+ 0x3ce,0x3cd,0x3cc,0x3cb,0x3ca,0x3c9,0x3c8,0x3c7,0x3c6,0x3c5,0x3c4,0x3c3,0x3c2,0x3c1,0x3c0,0x3bf,
+ 0x3be,0x3bd,0x3bc,0x3bb,0x3ba,0x3b9,0x3b8,0x3b7,0x3b6,0x3b5,0x3b4,0x3b3,0x3b2,0x3b1,0x3b0,0x3af,
+ 0x3ae,0x3ac,0x3ab,0x3aa,0x3a9,0x3a8,0x3a7,0x3a6,0x3a5,0x3a4,0x3a3,0x3a2,0x3a1,0x3a0,0x39f,0x39d,
+ 0x39c,0x39b,0x39a,0x399,0x398,0x397,0x396,0x395,0x394,0x393,0x392,0x391,0x390,0x38f,0x38e,0x38d,
+ 0x38c,0x38b,0x38a,0x389,0x388,0x387,0x386,0x385,0x384,0x383,0x382,0x381,0x380,0x37f,0x37e,0x37d,
+ 0x37c,0x37b,0x37a,0x379,0x378,0x377,0x376,0x375,0x374,0x373,0x372,0x371,0x370,0x36f,0x36e,0x36d,
+ 0x36c,0x36a,0x369,0x368,0x367,0x366,0x365,0x364,0x363,0x362,0x361,0x360,0x35f,0x35e,0x35c,0x35b,
+ 0x35a,0x359,0x358,0x357,0x356,0x355,0x354,0x353,0x352,0x351,0x350,0x34f,0x34e,0x34d,0x34c,0x34b,
+ 0x34b,0x34a,0x349,0x348,0x347,0x346,0x345,0x344,0x343,0x342,0x341,0x340,0x33f,0x33e,0x33d,0x33c,
+ 0x33b,0x33a,0x339,0x338,0x337,0x336,0x334,0x333,0x332,0x331,0x330,0x32f,0x32e,0x32d,0x32c,0x32a,
+ 0x329,0x328,0x327,0x326,0x325,0x324,0x323,0x322,0x321,0x320,0x31f,0x31e,0x31d,0x31c,0x31b,0x31a,
+ 0x319,0x318,0x317,0x316,0x315,0x314,0x313,0x312,0x311,0x310,0x30f,0x30e,0x30d,0x30c,0x30b,0x30a,
+ 0x309,0x308,0x307,0x306,0x305,0x304,0x303,0x302,0x301,0x300,0x2ff,0x2fe,0x2fd,0x2fc,0x2fb,0x2fa,
+ 0x2f9,0x2f8,0x2f7,0x2f6,0x2f5,0x2f4,0x2f3,0x2f2,0x2f1,0x2f0,0x2ef,0x2ee,0x2ed,0x2ec,0x2eb,0x2ea,
+ 0x2e9,0x2e8,0x2e7,0x2e6,0x2e5,0x2e4,0x2e3,0x2e2,0x2e1,0x2e0,0x2df,0x2dd,0x2dc,0x2db,0x2da,0x2d9,
+ 0x2d8,0x2d7,0x2d6,0x2d4,0x2d3,0x2d2,0x2d1,0x2d0,0x2cf,0x2ce,0x2cd,0x2cc,0x2cb,0x2ca,0x2c9,0x2c8,
+ 0x2c7,0x2c6,0x2c5,0x2c4,0x2c3,0x2c2,0x2c1,0x2c0,0x2bf,0x2be,0x2bd,0x2bc,0x2bb,0x2ba,0x2b9,0x2b8,
+ 0x2b7,0x2b6,0x2b5,0x2b4,0x2b3,0x2b2,0x2b1,0x2b0,0x2af,0x2ae,0x2ad,0x2ac,0x2ab,0x2aa,0x2a9,0x2a8,
+ 0x2a7,0x2a6,0x2a5,0x2a4,0x2a3,0x2a2,0x2a1,0x2a0,0x29f,0x29e,0x29d,0x29c,0x29b,0x29a,0x299,0x298,
+ 0x297,0x296,0x295,0x294,0x293,0x292,0x291,0x290,0x28f,0x28e,0x28d,0x28c,0x28b,0x28a,0x289,0x288,
+ 0x287,0x285,0x284,0x283,0x282,0x281,0x280,0x27f,0x27d,0x27c,0x27b,0x27a,0x279,0x278,0x277,0x276,
+ 0x275,0x274,0x273,0x272,0x271,0x270,0x26f,0x26e,0x26d,0x26c,0x26b,0x26a,0x269,0x268,0x267,0x266,
+ 0x265,0x264,0x263,0x262,0x261,0x260,0x25f,0x25e,0x25d,0x25c,0x25b,0x25a,0x259,0x258,0x257,0x256,
+ 0x255,0x254,0x253,0x252,0x251,0x250,0x24f,0x24e,0x24d,0x24c,0x24b,0x24a,0x249,0x248,0x247,0x246,
+ 0x246,0x244,0x243,0x242,0x241,0x23f,0x23e,0x23d,0x23c,0x23b,0x23a,0x239,0x238,0x237,0x236,0x235,
+ 0x234,0x233,0x232,0x231,0x230,0x22f,0x22e,0x22d,0x22c,0x22b,0x22a,0x229,0x228,0x227,0x226,0x225,
+ 0x224,0x223,0x222,0x221,0x220,0x21f,0x21e,0x21d,0x21c,0x21b,0x21a,0x219,0x218,0x217,0x216,0x215,
+ 0x214,0x213,0x212,0x211,0x210,0x20f,0x20e,0x20d,0x20c,0x20b,0x20a,0x209,0x208,0x207,0x206,0x205,
+ 0x204,0x203,0x202,0x201,0x200,0x1ff,0x1fe,0x1fd,0x1fc,0x1fb,0x1fa,0x1f9,0x1f8,0x1f7,0x1f6,0x1f5,
+ 0x1f4,0x1f3,0x1f2,0x1f1,0x1f0,0x1ef,0x1ee,0x1ed,0x1ec,0x1eb,0x1ea,0x1e9,0x1e8,0x1e7,0x1e6,0x1e5,
+ 0x1e4,0x1e3,0x1e2,0x1e1,0x1e0,0x1df,0x1de,0x1dd,0x1dc,0x1db,0x1da,0x1d9,0x1d8,0x1d7,0x1d6,0x1d5,
+ 0x1d4,0x1d3,0x1d2,0x1d1,0x1d0,0x1cf,0x1ce,0x1cd,0x1cc,0x1cb,0x1ca,0x1c9,0x1c8,0x1c7,0x1c6,0x1c5,
+ 0x1c4,0x1c2,0x1c1,0x1c0,0x1be,0x1bd,0x1bc,0x1bb,0x1ba,0x1b9,0x1b8,0x1b7,0x1b6,0x1b5,0x1b4,0x1b3,
+ 0x1b2,0x1b1,0x1b0,0x1af,0x1ae,0x1ad,0x1ac,0x1ab,0x1aa,0x1a9,0x1a8,0x1a7,0x1a6,0x1a5,0x1a4,0x1a3,
+ 0x1a2,0x1a1,0x1a0,0x19f,0x19e,0x19d,0x19c,0x19b,0x19a,0x199,0x198,0x197,0x196,0x195,0x194,0x193,
+ 0x192,0x191,0x190,0x18f,0x18e,0x18d,0x18c,0x18b,0x18a,0x189,0x188,0x187,0x186,0x185,0x184,0x183,
+ 0x182,0x181,0x180,0x17f,0x17e,0x17d,0x17c,0x17b,0x17a,0x179,0x178,0x177,0x176,0x175,0x174,0x173,
+ 0x172,0x171,0x170,0x16f,0x16e,0x16d,0x16c,0x16b,0x16a,0x169,0x168,0x167,0x166,0x165,0x164,0x163,
+ 0x162,0x161,0x160,0x15f,0x15e,0x15d,0x15c,0x15b,0x15a,0x159,0x158,0x157,0x156,0x155,0x154,0x153,
+ 0x152,0x151,0x150,0x14f,0x14e,0x14d,0x14c,0x14b,0x14a,0x149,0x148,0x147,0x146,0x145,0x144,0x143,
+ 0x141,0x140,0x13f,0x13e,0x13d,0x13c,0x13b,0x13a,0x139,0x138,0x137,0x136,0x135,0x134,0x133,0x132,
+ 0x131,0x130,0x12f,0x12e,0x12d,0x12c,0x12b,0x12a,0x129,0x128,0x127,0x126,0x125,0x124,0x123,0x122,
+ 0x121,0x120,0x11f,0x11e,0x11d,0x11c,0x11b,0x11a,0x119,0x118,0x117,0x116,0x115,0x114,0x113,0x112,
+ 0x111,0x110,0x10f,0x10e,0x10d,0x10c,0x10b,0x10a,0x109,0x108,0x107,0x106,0x105,0x104,0x103,0x102,
+ 0x101,0x100,0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,
+ 0xf1,0xf0,0xef,0xee,0xed,0xec,0xeb,0xea,0xe9,0xe8,0xe7,0xe6,0xe5,0xe4,0xe3,0xe2,
+ 0xe1,0xe0,0xdf,0xde,0xdd,0xdc,0xdb,0xda,0xd9,0xd8,0xd7,0xd6,0xd5,0xd4,0xd3,0xd2,
+ 0xd1,0xd0,0xcf,0xce,0xcd,0xcc,0xcb,0xca,0xc9,0xc8,0xc7,0xc6,0xc5,0xc4,0xc3,0xc2,
+ 0xc1,0xc0,0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,
+ 0xb1,0xb0,0xaf,0xae,0xad,0xac,0xab,0xaa,0xa9,0xa8,0xa7,0xa6,0xa5,0xa4,0xa3,0xa2,
+ 0xa1,0xa0,0x9f,0x9e,0x9d,0x9c,0x9b,0x9a,0x99,0x98,0x97,0x96,0x95,0x94,0x93,0x92,
+ 0x91,0x90,0x8f,0x8e,0x8d,0x8c,0x8b,0x8a,0x89,0x88,0x87,0x86,0x85,0x84,0x83,0x82,
+ 0x81,0x7e,0x7d,0x7c,0x7b,0x7a,0x79,0x78,0x77,0x76,0x75,0x74,0x73,0x72,0x71,0x70,
+ 0x6f,0x6e,0x6d,0x6c,0x6b,0x6a,0x69,0x68,0x67,0x66,0x65,0x64,0x63,0x62,0x61,0x60,
+ 0x5f,0x5e,0x5d,0x5c,0x5b,0x5a,0x59,0x58,0x57,0x56,0x55,0x54,0x53,0x52,0x51,0x50,
+ 0x4f,0x4e,0x4d,0x4c,0x4b,0x4a,0x49,0x48,0x47,0x46,0x45,0x44,0x43,0x42,0x41,0x40,
+ 0x3f,0x3e,0x3d,0x3c,0x3b,0x3a,0x39,0x38,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30,
+ 0x2f,0x2e,0x2d,0x2c,0x2b,0x2a,0x29,0x28,0x27,0x26,0x25,0x24,0x23,0x22,0x21,0x20,
+ 0x1f,0x1e,0x1d,0x1c,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x12,0x11,0x10,
+ 0xf,0xe,0xd,0xc,0xb,0xa,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0,
+};
+
+INLINE UINT32 gte_divide( INT16 numerator, UINT16 denominator )
+{
+ if( numerator >= 0 && numerator < ( denominator * 2 ) )
+ {
+ UINT32 offset = denominator;
+ int shift = 0;
+ UINT64 reciprocal;
+ while( offset <= 0x8000 )
+ {
+ offset <<= 1;
+ shift++;
+ }
+
+ reciprocal = (UINT64)( 0x10000 | reciprocals[ offset & 0x7fff ] ) << shift;
+
+ return (UINT32)( ( ( reciprocal * numerator ) + 0x8000 ) >> 16 );
+ }
+
+ return 0xffffffff;
+}
+
+/* Setting bits 12 & 19-22 in FLAG does not set bit 31 */
+
+#define A1( a ) BOUNDS( ( a ), 0x7fffffff, ( 1 << 30 ), -(INT64)0x80000000, ( 1 << 31 ) | ( 1 << 27 ) )
+#define A2( a ) BOUNDS( ( a ), 0x7fffffff, ( 1 << 29 ), -(INT64)0x80000000, ( 1 << 31 ) | ( 1 << 26 ) )
+#define A3( a ) BOUNDS( ( a ), 0x7fffffff, ( 1 << 28 ), -(INT64)0x80000000, ( 1 << 31 ) | ( 1 << 25 ) )
+#define Lm_B1( a, l ) LIM( ( a ), 0x7fff, -0x8000 * !l, ( 1 << 31 ) | ( 1 << 24 ) )
+#define Lm_B2( a, l ) LIM( ( a ), 0x7fff, -0x8000 * !l, ( 1 << 31 ) | ( 1 << 23 ) )
+#define Lm_B3( a, l ) LIM( ( a ), 0x7fff, -0x8000 * !l, ( 1 << 22 ) )
+#define Lm_C1( a ) LIM( ( a ), 0x00ff, 0x0000, ( 1 << 21 ) )
+#define Lm_C2( a ) LIM( ( a ), 0x00ff, 0x0000, ( 1 << 20 ) )
+#define Lm_C3( a ) LIM( ( a ), 0x00ff, 0x0000, ( 1 << 19 ) )
+#define Lm_D( a ) LIM( ( a ), 0xffff, 0x0000, ( 1 << 31 ) | ( 1 << 18 ) )
+
+UINT32 gte::Lm_E( UINT32 result )
+{
+ if( result > 0x1ffff )
+ {
+ FLAG |= ( 1 << 31 ) | ( 1 << 17 );
+ return 0x1ffff;
+ }
+
+ return result;
+}
+
+#define F( a ) BOUNDS( ( a ), 0x7fffffff, ( 1 << 31 ) | ( 1 << 16 ), -(INT64)0x80000000, ( 1 << 31 ) | ( 1 << 15 ) )
+#define Lm_G1( a ) LIM( ( a ), 0x3ff, -0x400, ( 1 << 31 ) | ( 1 << 14 ) )
+#define Lm_G2( a ) LIM( ( a ), 0x3ff, -0x400, ( 1 << 31 ) | ( 1 << 13 ) )
+#define Lm_H( a ) LIM( ( a ), 0xfff, 0x000, ( 1 << 12 ) )
+
+int gte::docop2( UINT32 pc, int gteop )
+{
+ int shift;
+ int v;
+ int lm;
+ int cv;
+ int mx;
+ INT32 h_over_sz3;
+ INT64 mac0;
+
+ switch( GTE_FUNCT( gteop ) )
+ {
+ case 0x01:
+ if( gteop == 0x0180001 )
+ {
+ GTELOG( pc, "%08x RTPS", gteop );
+ FLAG = 0;
+
+ MAC1 = A1( ( ( (INT64) TRX << 12 ) + ( R11 * VX0 ) + ( R12 * VY0 ) + ( R13 * VZ0 ) ) >> 12 );
+ MAC2 = A2( ( ( (INT64) TRY << 12 ) + ( R21 * VX0 ) + ( R22 * VY0 ) + ( R23 * VZ0 ) ) >> 12 );
+ MAC3 = A3( ( ( (INT64) TRZ << 12 ) + ( R31 * VX0 ) + ( R32 * VY0 ) + ( R33 * VZ0 ) ) >> 12 );
+ IR1 = Lm_B1( MAC1, 0 );
+ IR2 = Lm_B2( MAC2, 0 );
+ IR3 = Lm_B3( MAC3, 0 );
+ SZ0 = SZ1;
+ SZ1 = SZ2;
+ SZ2 = SZ3;
+ SZ3 = Lm_D( MAC3 );
+ h_over_sz3 = Lm_E( gte_divide( H, SZ3 ) );
+ SXY0 = SXY1;
+ SXY1 = SXY2;
+ SX2 = Lm_G1( F( (INT64) OFX + ( (INT64) IR1 * h_over_sz3 ) ) >> 16 );
+ SY2 = Lm_G2( F( (INT64) OFY + ( (INT64) IR2 * h_over_sz3 ) ) >> 16 );
+ MAC0 = F( (INT64) DQB + ( (INT64) DQA * h_over_sz3 ) );
+ IR0 = Lm_H( MAC0 >> 12 );
+ return 1;
+ }
+ break;
+
+ case 0x06:
+ GTELOG( pc, "%08x NCLIP", gteop );
+ FLAG = 0;
+
+ MAC0 = F( (INT64)( SX0 * SY1 ) + ( SX1 * SY2 ) + ( SX2 * SY0 ) - ( SX0 * SY2 ) - ( SX1 * SY0 ) - ( SX2 * SY1 ) );
+ return 1;
+
+ case 0x0c:
+ GTELOG( pc, "%08x OP", gteop );
+ FLAG = 0;
+
+ shift = 12 * GTE_SF( gteop );
+ lm = GTE_LM( gteop );
+
+ MAC1 = A1( ( (INT64) ( R22 * IR3 ) - ( R33 * IR2 ) ) >> shift );
+ MAC2 = A2( ( (INT64) ( R33 * IR1 ) - ( R11 * IR3 ) ) >> shift );
+ MAC3 = A3( ( (INT64) ( R11 * IR2 ) - ( R22 * IR1 ) ) >> shift );
+ IR1 = Lm_B1( MAC1, lm );
+ IR2 = Lm_B2( MAC2, lm );
+ IR3 = Lm_B3( MAC3, lm );
+ return 1;
+
+ case 0x10:
+ GTELOG( pc, "%08x DPCS", gteop );
+ FLAG = 0;
+
+ shift = 12 * GTE_SF( gteop );
+ lm = GTE_LM( gteop );
+
+ MAC1 = ( ( R << 16 ) + ( IR0 * Lm_B1( A1( (INT64) RFC - ( R << 4 ) ) << ( 12 - shift ), 0 ) ) ) >> shift;
+ MAC2 = ( ( G << 16 ) + ( IR0 * Lm_B2( A2( (INT64) GFC - ( G << 4 ) ) << ( 12 - shift ), 0 ) ) ) >> shift;
+ MAC3 = ( ( B << 16 ) + ( IR0 * Lm_B3( A3( (INT64) BFC - ( B << 4 ) ) << ( 12 - shift ), 0 ) ) ) >> shift;
+ IR1 = Lm_B1( MAC1, lm );
+ IR2 = Lm_B2( MAC2, lm );
+ IR3 = Lm_B3( MAC3, lm );
+ RGB0 = RGB1;
+ RGB1 = RGB2;
+ CD2 = CODE;
+ R2 = Lm_C1( MAC1 >> 4 );
+ G2 = Lm_C2( MAC2 >> 4 );
+ B2 = Lm_C3( MAC3 >> 4 );
+ return 1;
+
+ case 0x11:
+ GTELOG( pc, "%08x INTPL", gteop );
+ FLAG = 0;
+
+ shift = 12 * GTE_SF( gteop );
+ lm = GTE_LM( gteop );
+
+ MAC1 = ( ( IR1 << 12 ) + ( IR0 * Lm_B1( A1( (INT64) RFC - IR1 ) << ( 12 - shift ), 0 ) ) ) >> shift;
+ MAC2 = ( ( IR2 << 12 ) + ( IR0 * Lm_B2( A2( (INT64) GFC - IR2 ) << ( 12 - shift ), 0 ) ) ) >> shift;
+ MAC3 = ( ( IR3 << 12 ) + ( IR0 * Lm_B3( A3( (INT64) BFC - IR3 ) << ( 12 - shift ), 0 ) ) ) >> shift;
+ IR1 = Lm_B1( MAC1, lm );
+ IR2 = Lm_B2( MAC2, lm );
+ IR3 = Lm_B3( MAC3, lm );
+ RGB0 = RGB1;
+ RGB1 = RGB2;
+ CD2 = CODE;
+ R2 = Lm_C1( MAC1 >> 4 );
+ G2 = Lm_C2( MAC2 >> 4 );
+ B2 = Lm_C3( MAC3 >> 4 );
+ return 1;
+
+ case 0x12:
+ if( GTE_OP( gteop ) == 0x04 )
+ {
+ GTELOG( pc, "%08x MVMVA", gteop );
+ shift = 12 * GTE_SF( gteop );
+ mx = GTE_MX( gteop );
+ v = GTE_V( gteop );
+ cv = GTE_CV( gteop );
+ lm = GTE_LM( gteop );
+
+ FLAG = 0;
+
+ MAC1 = A1( ( ( (INT64) CV1( cv ) << 12 ) + ( MX11( mx ) * VX( v ) ) + ( MX12( mx ) * VY( v ) ) + ( MX13( mx ) * VZ( v ) ) ) >> shift );
+ MAC2 = A2( ( ( (INT64) CV2( cv ) << 12 ) + ( MX21( mx ) * VX( v ) ) + ( MX22( mx ) * VY( v ) ) + ( MX23( mx ) * VZ( v ) ) ) >> shift );
+ MAC3 = A3( ( ( (INT64) CV3( cv ) << 12 ) + ( MX31( mx ) * VX( v ) ) + ( MX32( mx ) * VY( v ) ) + ( MX33( mx ) * VZ( v ) ) ) >> shift );
+
+ IR1 = Lm_B1( MAC1, lm );
+ IR2 = Lm_B2( MAC2, lm );
+ IR3 = Lm_B3( MAC3, lm );
+ return 1;
+ }
+ break;
+ case 0x13:
+ if( gteop == 0x0e80413 )
+ {
+ GTELOG( pc, "%08x NCDS", gteop );
+ FLAG = 0;
+
+ MAC1 = A1( ( ( (INT64) L11 * VX0 ) + ( L12 * VY0 ) + ( L13 * VZ0 ) ) >> 12 );
+ MAC2 = A2( ( ( (INT64) L21 * VX0 ) + ( L22 * VY0 ) + ( L23 * VZ0 ) ) >> 12 );
+ MAC3 = A3( ( ( (INT64) L31 * VX0 ) + ( L32 * VY0 ) + ( L33 * VZ0 ) ) >> 12 );
+ IR1 = Lm_B1( MAC1, 1 );
+ IR2 = Lm_B2( MAC2, 1 );
+ IR3 = Lm_B3( MAC3, 1 );
+ MAC1 = A1( ( ( (INT64) RBK << 12 ) + ( LR1 * IR1 ) + ( LR2 * IR2 ) + ( LR3 * IR3 ) ) >> 12 );
+ MAC2 = A2( ( ( (INT64) GBK << 12 ) + ( LG1 * IR1 ) + ( LG2 * IR2 ) + ( LG3 * IR3 ) ) >> 12 );
+ MAC3 = A3( ( ( (INT64) BBK << 12 ) + ( LB1 * IR1 ) + ( LB2 * IR2 ) + ( LB3 * IR3 ) ) >> 12 );
+ IR1 = Lm_B1( MAC1, 1 );
+ IR2 = Lm_B2( MAC2, 1 );
+ IR3 = Lm_B3( MAC3, 1 );
+ MAC1 = A1( ( ( ( (INT64) R << 4 ) * IR1 ) + ( IR0 * Lm_B1( RFC - ( ( R * IR1 ) >> 8 ), 0 ) ) ) >> 12 );
+ MAC2 = A2( ( ( ( (INT64) G << 4 ) * IR2 ) + ( IR0 * Lm_B2( GFC - ( ( G * IR2 ) >> 8 ), 0 ) ) ) >> 12 );
+ MAC3 = A3( ( ( ( (INT64) B << 4 ) * IR3 ) + ( IR0 * Lm_B3( BFC - ( ( B * IR3 ) >> 8 ), 0 ) ) ) >> 12 );
+ IR1 = Lm_B1( MAC1, 1 );
+ IR2 = Lm_B2( MAC2, 1 );
+ IR3 = Lm_B3( MAC3, 1 );
+ CD0 = CD1;
+ CD1 = CD2;
+ CD2 = CODE;
+ R0 = R1;
+ R1 = R2;
+ R2 = Lm_C1( MAC1 >> 4 );
+ G0 = G1;
+ G1 = G2;
+ G2 = Lm_C2( MAC2 >> 4 );
+ B0 = B1;
+ B1 = B2;
+ B2 = Lm_C3( MAC3 >> 4 );
+ return 1;
+ }
+ break;
+ case 0x14:
+ if( gteop == 0x1280414 )
+ {
+ GTELOG( pc, "%08x CDP", gteop );
+ FLAG = 0;
+
+ MAC1 = A1( ( ( (INT64) RBK << 12 ) + ( LR1 * IR1 ) + ( LR2 * IR2 ) + ( LR3 * IR3 ) ) >> 12 );
+ MAC2 = A2( ( ( (INT64) GBK << 12 ) + ( LG1 * IR1 ) + ( LG2 * IR2 ) + ( LG3 * IR3 ) ) >> 12 );
+ MAC3 = A3( ( ( (INT64) BBK << 12 ) + ( LB1 * IR1 ) + ( LB2 * IR2 ) + ( LB3 * IR3 ) ) >> 12 );
+ IR1 = Lm_B1( MAC1, 1 );
+ IR2 = Lm_B2( MAC2, 1 );
+ IR3 = Lm_B3( MAC3, 1 );
+ MAC1 = A1( ( ( ( (INT64) R << 4 ) * IR1 ) + ( IR0 * Lm_B1( RFC - ( ( R * IR1 ) >> 8 ), 0 ) ) ) >> 12 );
+ MAC2 = A2( ( ( ( (INT64) G << 4 ) * IR2 ) + ( IR0 * Lm_B2( GFC - ( ( G * IR2 ) >> 8 ), 0 ) ) ) >> 12 );
+ MAC3 = A3( ( ( ( (INT64) B << 4 ) * IR3 ) + ( IR0 * Lm_B3( BFC - ( ( B * IR3 ) >> 8 ), 0 ) ) ) >> 12 );
+ IR1 = Lm_B1( MAC1, 1 );
+ IR2 = Lm_B2( MAC2, 1 );
+ IR3 = Lm_B3( MAC3, 1 );
+ CD0 = CD1;
+ CD1 = CD2;
+ CD2 = CODE;
+ R0 = R1;
+ R1 = R2;
+ R2 = Lm_C1( MAC1 >> 4 );
+ G0 = G1;
+ G1 = G2;
+ G2 = Lm_C2( MAC2 >> 4 );
+ B0 = B1;
+ B1 = B2;
+ B2 = Lm_C3( MAC3 >> 4 );
+ return 1;
+ }
+ break;
+ case 0x16:
+ if( gteop == 0x0f80416 )
+ {
+ GTELOG( pc, "%08x NCDT", gteop );
+ FLAG = 0;
+
+ for( v = 0; v < 3; v++ )
+ {
+ MAC1 = A1( ( ( (INT64) L11 * VX( v ) ) + ( L12 * VY( v ) ) + ( L13 * VZ( v ) ) ) >> 12 );
+ MAC2 = A2( ( ( (INT64) L21 * VX( v ) ) + ( L22 * VY( v ) ) + ( L23 * VZ( v ) ) ) >> 12 );
+ MAC3 = A3( ( ( (INT64) L31 * VX( v ) ) + ( L32 * VY( v ) ) + ( L33 * VZ( v ) ) ) >> 12 );
+ IR1 = Lm_B1( MAC1, 1 );
+ IR2 = Lm_B2( MAC2, 1 );
+ IR3 = Lm_B3( MAC3, 1 );
+ MAC1 = A1( ( ( (INT64) RBK << 12 ) + ( LR1 * IR1 ) + ( LR2 * IR2 ) + ( LR3 * IR3 ) ) >> 12 );
+ MAC2 = A2( ( ( (INT64) GBK << 12 ) + ( LG1 * IR1 ) + ( LG2 * IR2 ) + ( LG3 * IR3 ) ) >> 12 );
+ MAC3 = A3( ( ( (INT64) BBK << 12 ) + ( LB1 * IR1 ) + ( LB2 * IR2 ) + ( LB3 * IR3 ) ) >> 12 );
+ IR1 = Lm_B1( MAC1, 1 );
+ IR2 = Lm_B2( MAC2, 1 );
+ IR3 = Lm_B3( MAC3, 1 );
+ MAC1 = A1( ( ( ( (INT64) R << 4 ) * IR1 ) + ( IR0 * Lm_B1( RFC - ( ( R * IR1 ) >> 8 ), 0 ) ) ) >> 12 );
+ MAC2 = A2( ( ( ( (INT64) G << 4 ) * IR2 ) + ( IR0 * Lm_B2( GFC - ( ( G * IR2 ) >> 8 ), 0 ) ) ) >> 12 );
+ MAC3 = A3( ( ( ( (INT64) B << 4 ) * IR3 ) + ( IR0 * Lm_B3( BFC - ( ( B * IR3 ) >> 8 ), 0 ) ) ) >> 12 );
+ IR1 = Lm_B1( MAC1, 1 );
+ IR2 = Lm_B2( MAC2, 1 );
+ IR3 = Lm_B3( MAC3, 1 );
+ CD0 = CD1;
+ CD1 = CD2;
+ CD2 = CODE;
+ R0 = R1;
+ R1 = R2;
+ R2 = Lm_C1( MAC1 >> 4 );
+ G0 = G1;
+ G1 = G2;
+ G2 = Lm_C2( MAC2 >> 4 );
+ B0 = B1;
+ B1 = B2;
+ B2 = Lm_C3( MAC3 >> 4 );
+ }
+ return 1;
+ }
+ break;
+ case 0x1b:
+ if( gteop == 0x108041b || gteop == 0x118041b )
+ {
+ GTELOG( pc, "%08x NCCS", gteop );
+ FLAG = 0;
+
+ MAC1 = A1( ( ( (INT64) L11 * VX0 ) + ( L12 * VY0 ) + ( L13 * VZ0 ) ) >> 12 );
+ MAC2 = A2( ( ( (INT64) L21 * VX0 ) + ( L22 * VY0 ) + ( L23 * VZ0 ) ) >> 12 );
+ MAC3 = A3( ( ( (INT64) L31 * VX0 ) + ( L32 * VY0 ) + ( L33 * VZ0 ) ) >> 12 );
+ IR1 = Lm_B1( MAC1, 1 );
+ IR2 = Lm_B2( MAC2, 1 );
+ IR3 = Lm_B3( MAC3, 1 );
+ MAC1 = A1( ( ( (INT64) RBK << 12 ) + ( LR1 * IR1 ) + ( LR2 * IR2 ) + ( LR3 * IR3 ) ) >> 12 );
+ MAC2 = A2( ( ( (INT64) GBK << 12 ) + ( LG1 * IR1 ) + ( LG2 * IR2 ) + ( LG3 * IR3 ) ) >> 12 );
+ MAC3 = A3( ( ( (INT64) BBK << 12 ) + ( LB1 * IR1 ) + ( LB2 * IR2 ) + ( LB3 * IR3 ) ) >> 12 );
+ IR1 = Lm_B1( MAC1, 1 );
+ IR2 = Lm_B2( MAC2, 1 );
+ IR3 = Lm_B3( MAC3, 1 );
+ MAC1 = A1( ( (INT64) R * IR1 ) >> 8 );
+ MAC2 = A2( ( (INT64) G * IR2 ) >> 8 );
+ MAC3 = A3( ( (INT64) B * IR3 ) >> 8 );
+ IR1 = Lm_B1( MAC1, 1 );
+ IR2 = Lm_B2( MAC2, 1 );
+ IR3 = Lm_B3( MAC3, 1 );
+ CD0 = CD1;
+ CD1 = CD2;
+ CD2 = CODE;
+ R0 = R1;
+ R1 = R2;
+ R2 = Lm_C1( MAC1 >> 4 );
+ G0 = G1;
+ G1 = G2;
+ G2 = Lm_C2( MAC2 >> 4 );
+ B0 = B1;
+ B1 = B2;
+ B2 = Lm_C3( MAC3 >> 4 );
+ return 1;
+ }
+ break;
+ case 0x1c:
+ if( gteop == 0x138041c )
+ {
+ GTELOG( pc, "%08x CC", gteop );
+ FLAG = 0;
+
+ MAC1 = A1( ( ( (INT64) RBK << 12 ) + ( LR1 * IR1 ) + ( LR2 * IR2 ) + ( LR3 * IR3 ) ) >> 12 );
+ MAC2 = A2( ( ( (INT64) GBK << 12 ) + ( LG1 * IR1 ) + ( LG2 * IR2 ) + ( LG3 * IR3 ) ) >> 12 );
+ MAC3 = A3( ( ( (INT64) BBK << 12 ) + ( LB1 * IR1 ) + ( LB2 * IR2 ) + ( LB3 * IR3 ) ) >> 12 );
+ IR1 = Lm_B1( MAC1, 1 );
+ IR2 = Lm_B2( MAC2, 1 );
+ IR3 = Lm_B3( MAC3, 1 );
+ MAC1 = A1( ( (INT64) R * IR1 ) >> 8 );
+ MAC2 = A2( ( (INT64) G * IR2 ) >> 8 );
+ MAC3 = A3( ( (INT64) B * IR3 ) >> 8 );
+ IR1 = Lm_B1( MAC1, 1 );
+ IR2 = Lm_B2( MAC2, 1 );
+ IR3 = Lm_B3( MAC3, 1 );
+ CD0 = CD1;
+ CD1 = CD2;
+ CD2 = CODE;
+ R0 = R1;
+ R1 = R2;
+ R2 = Lm_C1( MAC1 >> 4 );
+ G0 = G1;
+ G1 = G2;
+ G2 = Lm_C2( MAC2 >> 4 );
+ B0 = B1;
+ B1 = B2;
+ B2 = Lm_C3( MAC3 >> 4 );
+ return 1;
+ }
+ break;
+ case 0x1e:
+ if( gteop == 0x0c8041e )
+ {
+ GTELOG( pc, "%08x NCS", gteop );
+ FLAG = 0;
+
+ MAC1 = A1( ( ( (INT64) L11 * VX0 ) + ( L12 * VY0 ) + ( L13 * VZ0 ) ) >> 12 );
+ MAC2 = A2( ( ( (INT64) L21 * VX0 ) + ( L22 * VY0 ) + ( L23 * VZ0 ) ) >> 12 );
+ MAC3 = A3( ( ( (INT64) L31 * VX0 ) + ( L32 * VY0 ) + ( L33 * VZ0 ) ) >> 12 );
+ IR1 = Lm_B1( MAC1, 1 );
+ IR2 = Lm_B2( MAC2, 1 );
+ IR3 = Lm_B3( MAC3, 1 );
+ MAC1 = A1( ( ( (INT64) RBK << 12 ) + ( LR1 * IR1 ) + ( LR2 * IR2 ) + ( LR3 * IR3 ) ) >> 12 );
+ MAC2 = A2( ( ( (INT64) GBK << 12 ) + ( LG1 * IR1 ) + ( LG2 * IR2 ) + ( LG3 * IR3 ) ) >> 12 );
+ MAC3 = A3( ( ( (INT64) BBK << 12 ) + ( LB1 * IR1 ) + ( LB2 * IR2 ) + ( LB3 * IR3 ) ) >> 12 );
+ IR1 = Lm_B1( MAC1, 1 );
+ IR2 = Lm_B2( MAC2, 1 );
+ IR3 = Lm_B3( MAC3, 1 );
+ CD0 = CD1;
+ CD1 = CD2;
+ CD2 = CODE;
+ R0 = R1;
+ R1 = R2;
+ R2 = Lm_C1( MAC1 >> 4 );
+ G0 = G1;
+ G1 = G2;
+ G2 = Lm_C2( MAC2 >> 4 );
+ B0 = B1;
+ B1 = B2;
+ B2 = Lm_C3( MAC3 >> 4 );
+ return 1;
+ }
+ break;
+ case 0x20:
+ if( gteop == 0x0d80420 )
+ {
+ GTELOG( pc, "%08x NCT", gteop );
+ FLAG = 0;
+
+ for( v = 0; v < 3; v++ )
+ {
+ MAC1 = A1( ( ( (INT64) L11 * VX( v ) ) + ( L12 * VY( v ) ) + ( L13 * VZ( v ) ) ) >> 12 );
+ MAC2 = A2( ( ( (INT64) L21 * VX( v ) ) + ( L22 * VY( v ) ) + ( L23 * VZ( v ) ) ) >> 12 );
+ MAC3 = A3( ( ( (INT64) L31 * VX( v ) ) + ( L32 * VY( v ) ) + ( L33 * VZ( v ) ) ) >> 12 );
+ IR1 = Lm_B1( MAC1, 1 );
+ IR2 = Lm_B2( MAC2, 1 );
+ IR3 = Lm_B3( MAC3, 1 );
+ MAC1 = A1( ( ( (INT64) RBK << 12 ) + ( LR1 * IR1 ) + ( LR2 * IR2 ) + ( LR3 * IR3 ) ) >> 12 );
+ MAC2 = A2( ( ( (INT64) GBK << 12 ) + ( LG1 * IR1 ) + ( LG2 * IR2 ) + ( LG3 * IR3 ) ) >> 12 );
+ MAC3 = A3( ( ( (INT64) BBK << 12 ) + ( LB1 * IR1 ) + ( LB2 * IR2 ) + ( LB3 * IR3 ) ) >> 12 );
+ IR1 = Lm_B1( MAC1, 1 );
+ IR2 = Lm_B2( MAC2, 1 );
+ IR3 = Lm_B3( MAC3, 1 );
+ CD0 = CD1;
+ CD1 = CD2;
+ CD2 = CODE;
+ R0 = R1;
+ R1 = R2;
+ R2 = Lm_C1( MAC1 >> 4 );
+ G0 = G1;
+ G1 = G2;
+ G2 = Lm_C2( MAC2 >> 4 );
+ B0 = B1;
+ B1 = B2;
+ B2 = Lm_C3( MAC3 >> 4 );
+ }
+ return 1;
+ }
+ break;
+
+ case 0x28:
+ GTELOG( pc, "%08x SQR", gteop );
+ FLAG = 0;
+
+ shift = 12 * GTE_SF( gteop );
+ lm = GTE_LM( gteop );
+
+ MAC1 = A1( ( IR1 * IR1 ) >> shift );
+ MAC2 = A2( ( IR2 * IR2 ) >> shift );
+ MAC3 = A3( ( IR3 * IR3 ) >> shift );
+ IR1 = Lm_B1( MAC1, lm );
+ IR2 = Lm_B2( MAC2, lm );
+ IR3 = Lm_B3( MAC3, lm );
+ return 1;
+
+ // DCPL 0x29
+ case 0x2a:
+ if( gteop == 0x0f8002a )
+ {
+ GTELOG( pc, "%08x DPCT", gteop );
+ FLAG = 0;
+
+ for( v = 0; v < 3; v++ )
+ {
+ MAC1 = A1( ( ( (INT64) R0 << 16 ) + ( (INT64) IR0 * ( Lm_B1( RFC - ( R0 << 4 ), 0 ) ) ) ) >> 12 );
+ MAC2 = A2( ( ( (INT64) G0 << 16 ) + ( (INT64) IR0 * ( Lm_B1( GFC - ( G0 << 4 ), 0 ) ) ) ) >> 12 );
+ MAC3 = A3( ( ( (INT64) B0 << 16 ) + ( (INT64) IR0 * ( Lm_B1( BFC - ( B0 << 4 ), 0 ) ) ) ) >> 12 );
+ IR1 = Lm_B1( MAC1, 0 );
+ IR2 = Lm_B2( MAC2, 0 );
+ IR3 = Lm_B3( MAC3, 0 );
+ CD0 = CD1;
+ CD1 = CD2;
+ CD2 = CODE;
+ R0 = R1;
+ R1 = R2;
+ R2 = Lm_C1( MAC1 >> 4 );
+ G0 = G1;
+ G1 = G2;
+ G2 = Lm_C2( MAC2 >> 4 );
+ B0 = B1;
+ B1 = B2;
+ B2 = Lm_C3( MAC3 >> 4 );
+ }
+ return 1;
+ }
+ break;
+
+ case 0x2d:
+ GTELOG( pc, "%08x AVSZ3", gteop );
+ FLAG = 0;
+
+ mac0 = F( (INT64) ( ZSF3 * SZ1 ) + ( ZSF3 * SZ2 ) + ( ZSF3 * SZ3 ) );
+ OTZ = Lm_D( mac0 >> 12 );
+
+ MAC0 = mac0;
+ return 1;
+
+ case 0x2e:
+ GTELOG( pc, "%08x AVSZ4", gteop );
+ FLAG = 0;
+
+ mac0 = F( (INT64) ( ZSF4 * SZ0 ) + ( ZSF4 * SZ1 ) + ( ZSF4 * SZ2 ) + ( ZSF4 * SZ3 ) );
+ OTZ = Lm_D( mac0 >> 12 );
+
+ MAC0 = mac0;
+ return 1;
+
+ case 0x30:
+ if( gteop == 0x0280030 )
+ {
+ GTELOG( pc, "%08x RTPT", gteop );
+ FLAG = 0;
+
+ for( v = 0; v < 3; v++ )
+ {
+ MAC1 = A1( ( ( (INT64) TRX << 12 ) + ( R11 * VX( v ) ) + ( R12 * VY( v ) ) + ( R13 * VZ( v ) ) ) >> 12 );
+ MAC2 = A2( ( ( (INT64) TRY << 12 ) + ( R21 * VX( v ) ) + ( R22 * VY( v ) ) + ( R23 * VZ( v ) ) ) >> 12 );
+ MAC3 = A3( ( ( (INT64) TRZ << 12 ) + ( R31 * VX( v ) ) + ( R32 * VY( v ) ) + ( R33 * VZ( v ) ) ) >> 12 );
+ IR1 = Lm_B1( MAC1, 0 );
+ IR2 = Lm_B2( MAC2, 0 );
+ IR3 = Lm_B3( MAC3, 0 );
+ SZ0 = SZ1;
+ SZ1 = SZ2;
+ SZ2 = SZ3;
+ SZ3 = Lm_D( MAC3 );
+ h_over_sz3 = Lm_E( gte_divide( H, SZ3 ) );
+ SXY0 = SXY1;
+ SXY1 = SXY2;
+ SX2 = Lm_G1( F( ( (INT64) OFX + ( (INT64) IR1 * h_over_sz3 ) ) >> 16 ) );
+ SY2 = Lm_G2( F( ( (INT64) OFY + ( (INT64) IR2 * h_over_sz3 ) ) >> 16 ) );
+ MAC0 = F( (INT64) DQB + ( (INT64) DQA * h_over_sz3 ) );
+ IR0 = Lm_H( MAC0 >> 12 );
+ }
+ return 1;
+ }
+ break;
+ case 0x3d:
+ if( GTE_OP( gteop ) == 0x09 ||
+ GTE_OP( gteop ) == 0x19 )
+ {
+ GTELOG( pc, "%08x GPF", gteop );
+ shift = 12 * GTE_SF( gteop );
+ FLAG = 0;
+
+ MAC1 = A1( ( (INT64) IR0 * IR1 ) >> shift );
+ MAC2 = A2( ( (INT64) IR0 * IR2 ) >> shift );
+ MAC3 = A3( ( (INT64) IR0 * IR3 ) >> shift );
+ IR1 = Lm_B1( MAC1, 0 );
+ IR2 = Lm_B2( MAC2, 0 );
+ IR3 = Lm_B3( MAC3, 0 );
+ CD0 = CD1;
+ CD1 = CD2;
+ CD2 = CODE;
+ R0 = R1;
+ R1 = R2;
+ R2 = Lm_C1( MAC1 >> 4 );
+ G0 = G1;
+ G1 = G2;
+ G2 = Lm_C2( MAC2 >> 4 );
+ B0 = B1;
+ B1 = B2;
+ B2 = Lm_C3( MAC3 >> 4 );
+ return 1;
+ }
+ break;
+ case 0x3e:
+ if( GTE_OP( gteop ) == 0x1a )
+ {
+ GTELOG( pc, "%08x GPL", gteop );
+ shift = 12 * GTE_SF( gteop );
+ FLAG = 0;
+
+ MAC1 = A1( ( ( (INT64) MAC1 << shift ) + ( IR0 * IR1 ) ) >> shift );
+ MAC2 = A2( ( ( (INT64) MAC2 << shift ) + ( IR0 * IR2 ) ) >> shift );
+ MAC3 = A3( ( ( (INT64) MAC3 << shift ) + ( IR0 * IR3 ) ) >> shift );
+ IR1 = Lm_B1( MAC1, 0 );
+ IR2 = Lm_B2( MAC2, 0 );
+ IR3 = Lm_B3( MAC3, 0 );
+ CD0 = CD1;
+ CD1 = CD2;
+ CD2 = CODE;
+ R0 = R1;
+ R1 = R2;
+ R2 = Lm_C1( MAC1 >> 4 );
+ G0 = G1;
+ G1 = G2;
+ G2 = Lm_C2( MAC2 >> 4 );
+ B0 = B1;
+ B1 = B2;
+ B2 = Lm_C3( MAC3 >> 4 );
+ return 1;
+ }
+ break;
+ case 0x3f:
+ if( gteop == 0x108043f ||
+ gteop == 0x118043f )
+ {
+ GTELOG( pc, "%08x NCCT", gteop );
+ FLAG = 0;
+
+ for( v = 0; v < 3; v++ )
+ {
+ MAC1 = A1( ( ( (INT64) L11 * VX( v ) ) + ( L12 * VY( v ) ) + ( L13 * VZ( v ) ) ) >> 12 );
+ MAC2 = A2( ( ( (INT64) L21 * VX( v ) ) + ( L22 * VY( v ) ) + ( L23 * VZ( v ) ) ) >> 12 );
+ MAC3 = A3( ( ( (INT64) L31 * VX( v ) ) + ( L32 * VY( v ) ) + ( L33 * VZ( v ) ) ) >> 12 );
+ IR1 = Lm_B1( MAC1, 1 );
+ IR2 = Lm_B2( MAC2, 1 );
+ IR3 = Lm_B3( MAC3, 1 );
+ MAC1 = A1( ( ( (INT64) RBK << 12 ) + ( LR1 * IR1 ) + ( LR2 * IR2 ) + ( LR3 * IR3 ) ) >> 12 );
+ MAC2 = A2( ( ( (INT64) GBK << 12 ) + ( LG1 * IR1 ) + ( LG2 * IR2 ) + ( LG3 * IR3 ) ) >> 12 );
+ MAC3 = A3( ( ( (INT64) BBK << 12 ) + ( LB1 * IR1 ) + ( LB2 * IR2 ) + ( LB3 * IR3 ) ) >> 12 );
+ IR1 = Lm_B1( MAC1, 1 );
+ IR2 = Lm_B2( MAC2, 1 );
+ IR3 = Lm_B3( MAC3, 1 );
+ MAC1 = A1( ( (INT64) R * IR1 ) >> 8 );
+ MAC2 = A2( ( (INT64) G * IR2 ) >> 8 );
+ MAC3 = A3( ( (INT64) B * IR3 ) >> 8 );
+ IR1 = Lm_B1( MAC1, 1 );
+ IR2 = Lm_B2( MAC2, 1 );
+ IR3 = Lm_B3( MAC3, 1 );
+ CD0 = CD1;
+ CD1 = CD2;
+ CD2 = CODE;
+ R0 = R1;
+ R1 = R2;
+ R2 = Lm_C1( MAC1 >> 4 );
+ G0 = G1;
+ G1 = G2;
+ G2 = Lm_C2( MAC2 >> 4 );
+ B0 = B1;
+ B1 = B2;
+ B2 = Lm_C3( MAC3 >> 4 );
+ }
+ return 1;
+ }
+ break;
+ }
+
+ popmessage( "unknown GTE op %08x", gteop );
+ logerror( "%08x: unknown GTE op %08x\n", pc, gteop );
+
+ return 0;
+}
diff --git a/trunk/src/emu/cpu/psx/gte.h b/trunk/src/emu/cpu/psx/gte.h
new file mode 100644
index 00000000000..bf38d8dce9a
--- /dev/null
+++ b/trunk/src/emu/cpu/psx/gte.h
@@ -0,0 +1,45 @@
+/*
+ * PlayStation Geometry Transformation Engine emulator
+ *
+ * Copyright 2003-2011 smf
+ *
+ * divider reverse engineering by pSXAuthor.
+ *
+ */
+
+#pragma once
+
+#ifndef __PSXGTE_H__
+#define __PSXGTE_H__
+
+#include "emu.h"
+
+#define GTE_OP( op ) ( ( op >> 20 ) & 31 )
+#define GTE_SF( op ) ( ( op >> 19 ) & 1 )
+#define GTE_MX( op ) ( ( op >> 17 ) & 3 )
+#define GTE_V( op ) ( ( op >> 15 ) & 3 )
+#define GTE_CV( op ) ( ( op >> 13 ) & 3 )
+#define GTE_CD( op ) ( ( op >> 11 ) & 3 ) /* not used */
+#define GTE_LM( op ) ( ( op >> 10 ) & 1 )
+#define GTE_CT( op ) ( ( op >> 6 ) & 15 ) /* not used */
+#define GTE_FUNCT( op ) ( op & 63 )
+
+class gte
+{
+public:
+ PAIR m_cp2cr[ 32 ];
+ PAIR m_cp2dr[ 32 ];
+
+ UINT32 getcp2dr( UINT32 pc, int reg );
+ void setcp2dr( UINT32 pc, int reg, UINT32 value );
+ UINT32 getcp2cr( UINT32 pc, int reg );
+ void setcp2cr( UINT32 pc, int reg, UINT32 value );
+ int docop2( UINT32 pc, int gteop );
+
+protected:
+ INT32 LIM( INT32 value, INT32 max, INT32 min, UINT32 flag );
+ INT64 BOUNDS( INT64 n_value, INT64 n_max, int n_maxflag, INT64 n_min, int n_minflag );
+ UINT32 Lm_E( UINT32 result );
+};
+
+#endif
diff --git a/trunk/src/emu/cpu/psx/irq.c b/trunk/src/emu/cpu/psx/irq.c
new file mode 100644
index 00000000000..ff9d00c13e5
--- /dev/null
+++ b/trunk/src/emu/cpu/psx/irq.c
@@ -0,0 +1,112 @@
+/*
+ * PlayStation IRQ emulator
+ *
+ * Copyright 2003-2011 smf
+ *
+ */
+
+#include "psx.h"
+#include "irq.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 device_type PSX_IRQ = &device_creator<psxirq_device>;
+
+psxirq_device::psxirq_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, PSX_IRQ, "PSX IRQ", tag, owner, clock)
+{
+}
+
+void psxirq_device::device_reset()
+{
+ n_irqdata = 0;
+ n_irqmask = 0;
+
+ psx_irq_update();
+}
+
+void psxirq_device::device_post_load()
+{
+ psx_irq_update();
+}
+
+void psxirq_device::device_start()
+{
+ save_item( NAME( n_irqdata ) );
+ save_item( NAME( n_irqmask ) );
+}
+
+void psxirq_device::set( UINT32 bitmask )
+{
+ verboselog( machine(), 2, "psx_irq_set %08x\n", bitmask );
+ n_irqdata |= bitmask;
+ psx_irq_update();
+}
+
+void psxirq_device::psx_irq_update( void )
+{
+ if( ( n_irqdata & n_irqmask ) != 0 )
+ {
+ verboselog( machine(), 2, "psx irq assert\n" );
+ cputag_set_input_line( machine(), "maincpu", PSXCPU_IRQ0, ASSERT_LINE );
+ }
+ else
+ {
+ verboselog( machine(), 2, "psx irq clear\n" );
+ cputag_set_input_line( machine(), "maincpu", PSXCPU_IRQ0, CLEAR_LINE );
+ }
+}
+
+WRITE32_MEMBER( psxirq_device::write )
+{
+ switch( offset )
+ {
+ case 0x00:
+ verboselog( machine(), 2, "psx irq data ( %08x, %08x ) %08x -> %08x\n", data, mem_mask, n_irqdata, ( n_irqdata & ~mem_mask ) | ( n_irqdata & n_irqmask & data ) );
+ n_irqdata = ( n_irqdata & ~mem_mask ) | ( n_irqdata & n_irqmask & data );
+ psx_irq_update();
+ break;
+ case 0x01:
+ verboselog( machine(), 2, "psx irq mask ( %08x, %08x ) %08x -> %08x\n", data, mem_mask, n_irqmask, ( n_irqmask & ~mem_mask ) | data );
+ n_irqmask = ( n_irqmask & ~mem_mask ) | data;
+ if( ( n_irqmask &~ PSX_IRQ_MASK ) != 0 )
+ {
+ verboselog( machine(), 0, "psx_irq_w( %08x, %08x, %08x ) unknown irq\n", offset, data, mem_mask );
+ }
+ psx_irq_update();
+ break;
+ default:
+ verboselog( machine(), 0, "psx_irq_w( %08x, %08x, %08x ) unknown register\n", offset, data, mem_mask );
+ break;
+ }
+}
+
+READ32_MEMBER( psxirq_device::read )
+{
+ switch( offset )
+ {
+ case 0x00:
+ verboselog( machine(), 1, "psx_irq_r irq data %08x\n", n_irqdata );
+ return n_irqdata;
+ case 0x01:
+ verboselog( machine(), 1, "psx_irq_r irq mask %08x\n", n_irqmask );
+ return n_irqmask;
+ default:
+ verboselog( machine(), 0, "psx_irq_r unknown register %d\n", offset );
+ break;
+ }
+ return 0;
+}
diff --git a/trunk/src/emu/cpu/psx/irq.h b/trunk/src/emu/cpu/psx/irq.h
new file mode 100644
index 00000000000..103a7386964
--- /dev/null
+++ b/trunk/src/emu/cpu/psx/irq.h
@@ -0,0 +1,51 @@
+/*
+ * PlayStation IRQ emulator
+ *
+ * Copyright 2003-2011 smf
+ *
+ */
+
+#pragma once
+
+#ifndef __PSXIRQ_H__
+#define __PSXIRQ_H__
+
+#include "emu.h"
+
+#define PSX_IRQ_VBLANK 0x0001
+#define PSX_IRQ_CDROM 0x0004
+#define PSX_IRQ_DMA 0x0008
+#define PSX_IRQ_ROOTCOUNTER0 0x0010
+#define PSX_IRQ_ROOTCOUNTER1 0x0020
+#define PSX_IRQ_ROOTCOUNTER2 0x0040
+#define PSX_IRQ_SIO0 0x0080
+#define PSX_IRQ_SIO1 0x0100
+#define PSX_IRQ_SPU 0x0200
+#define PSX_IRQ_EXTCD 0x0400
+#define PSX_IRQ_MASK (PSX_IRQ_VBLANK | PSX_IRQ_CDROM | PSX_IRQ_DMA | PSX_IRQ_ROOTCOUNTER2 | PSX_IRQ_ROOTCOUNTER1 | PSX_IRQ_ROOTCOUNTER0 | PSX_IRQ_SIO0 | PSX_IRQ_SIO1 | PSX_IRQ_SPU | PSX_IRQ_EXTCD)
+
+extern const device_type PSX_IRQ;
+
+class psxirq_device : public device_t
+{
+public:
+ psxirq_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ READ32_MEMBER( read );
+ WRITE32_MEMBER( write );
+
+ void set( UINT32 bitmask );
+
+protected:
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_post_load();
+
+private:
+ void psx_irq_update( void );
+
+ UINT32 n_irqdata;
+ UINT32 n_irqmask;
+};
+
+#endif
diff --git a/trunk/src/emu/cpu/psx/mdec.c b/trunk/src/emu/cpu/psx/mdec.c
new file mode 100644
index 00000000000..08a319e6856
--- /dev/null
+++ b/trunk/src/emu/cpu/psx/mdec.c
@@ -0,0 +1,572 @@
+/*
+ * PlayStation Motion Decoder emulator
+ *
+ * Copyright 2003-2011 smf
+ *
+ * Thanks to Oliver Galibert for help figuring out IDCT
+ *
+ */
+
+#include "emu.h"
+#include "dma.h"
+#include "mdec.h"
+#include "includes/psx.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 device_type PSX_MDEC = &device_creator<psxmdec_device>;
+
+psxmdec_device::psxmdec_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, PSX_MDEC, "PSX MDEC", tag, owner, clock)
+{
+}
+
+void psxmdec_device::device_reset()
+{
+ n_0_command = 0;
+ n_0_address = 0;
+ n_0_size = 0;
+ n_1_command = 0;
+ n_1_status = 0;
+ n_offset = 0;
+ n_decoded = 0;
+}
+
+void psxmdec_device::device_post_load()
+{
+ mdec_cos_precalc();
+}
+
+void psxmdec_device::device_start()
+{
+ for( int n = 0; n < 256; n++ )
+ {
+ p_n_clamp8[ n ] = 0;
+ p_n_clamp8[ n + 256 ] = n;
+ p_n_clamp8[ n + 512 ] = 255;
+
+ p_n_r5[ n ] = 0;
+ p_n_r5[ n + 256 ] = ( n >> 3 );
+ p_n_r5[ n + 512 ] = ( 255 >> 3 );
+
+ p_n_g5[ n ] = 0;
+ p_n_g5[ n + 256 ] = ( n >> 3 ) << 5;
+ p_n_g5[ n + 512 ] = ( 255 >> 3 ) << 5;
+
+ p_n_b5[ n ] = 0;
+ p_n_b5[ n + 256 ] = ( n >> 3 ) << 10;
+ p_n_b5[ n + 512 ] = ( 255 >> 3 ) << 10;
+ }
+
+ save_item( NAME( n_0_command ) );
+ save_item( NAME( n_0_address ) );
+ save_item( NAME( n_0_size ) );
+ save_item( NAME( n_1_command ) );
+ save_item( NAME( n_1_status ) );
+ save_item( NAME( p_n_quantize_y ) );
+ save_item( NAME( p_n_quantize_uv ) );
+ save_item( NAME( p_n_cos ) );
+}
+
+#ifdef UNUSED_FUNCTION
+INLINE void psxwriteword( UINT32 *p_n_psxram, UINT32 n_address, UINT16 n_data )
+{
+ *( (UINT16 *)( (UINT8 *)p_n_psxram + WORD_XOR_LE( n_address ) ) ) = n_data;
+}
+#endif
+
+INLINE UINT16 psxreadword( UINT32 *p_n_psxram, UINT32 n_address )
+{
+ return *( (UINT16 *)( (UINT8 *)p_n_psxram + WORD_XOR_LE( n_address ) ) );
+}
+
+static const UINT32 m_p_n_mdec_zigzag[ DCTSIZE2 ] =
+{
+ 0, 1, 8, 16, 9, 2, 3, 10,
+ 17, 24, 32, 25, 18, 11, 4, 5,
+ 12, 19, 26, 33, 40, 48, 41, 34,
+ 27, 20, 13, 6, 7, 14, 21, 28,
+ 35, 42, 49, 56, 57, 50, 43, 36,
+ 29, 22, 15, 23, 30, 37, 44, 51,
+ 58, 59, 52, 45, 38, 31, 39, 46,
+ 53, 60, 61, 54, 47, 55, 62, 63
+};
+
+void psxmdec_device::mdec_cos_precalc()
+{
+ UINT32 n_x;
+ UINT32 n_y;
+ UINT32 n_u;
+ UINT32 n_v;
+ INT32 *p_n_precalc = p_n_cos_precalc;
+
+ for( n_y = 0; n_y < 8; n_y++ )
+ {
+ for( n_x = 0; n_x < 8; n_x++ )
+ {
+ for( n_v = 0; n_v < 8; n_v++ )
+ {
+ for( n_u = 0; n_u < 8; n_u++ )
+ {
+ *( p_n_precalc++ ) =
+ ( ( p_n_cos[ ( n_u * 8 ) + n_x ] *
+ p_n_cos[ ( n_v * 8 ) + n_y ] ) >> ( 30 - MDEC_COS_PRECALC_BITS ) );
+ }
+ }
+ }
+ }
+}
+
+void psxmdec_device::mdec_idct( INT32 *p_n_src, INT32 *p_n_dst )
+{
+ INT32 *p_n_precalc = p_n_cos_precalc;
+
+ for( UINT32 n_yx = 0; n_yx < DCTSIZE2; n_yx++ )
+ {
+ INT32 p_n_z[ 8 ];
+ INT32 *p_n_data = p_n_src;
+
+ memset( p_n_z, 0, sizeof( p_n_z ) );
+
+ for( UINT32 n_vu = 0; n_vu < DCTSIZE2 / 8; n_vu++ )
+ {
+ p_n_z[ 0 ] += p_n_data[ 0 ] * p_n_precalc[ 0 ];
+ p_n_z[ 1 ] += p_n_data[ 1 ] * p_n_precalc[ 1 ];
+ p_n_z[ 2 ] += p_n_data[ 2 ] * p_n_precalc[ 2 ];
+ p_n_z[ 3 ] += p_n_data[ 3 ] * p_n_precalc[ 3 ];
+ p_n_z[ 4 ] += p_n_data[ 4 ] * p_n_precalc[ 4 ];
+ p_n_z[ 5 ] += p_n_data[ 5 ] * p_n_precalc[ 5 ];
+ p_n_z[ 6 ] += p_n_data[ 6 ] * p_n_precalc[ 6 ];
+ p_n_z[ 7 ] += p_n_data[ 7 ] * p_n_precalc[ 7 ];
+ p_n_data += 8;
+ p_n_precalc += 8;
+ }
+
+ *( p_n_dst++ ) = ( p_n_z[ 0 ] + p_n_z[ 1 ] + p_n_z[ 2 ] + p_n_z[ 3 ] +
+ p_n_z[ 4 ] + p_n_z[ 5 ] + p_n_z[ 6 ] + p_n_z[ 7 ] ) >> ( MDEC_COS_PRECALC_BITS + 2 );
+ }
+}
+
+INLINE UINT16 mdec_unpack_run( UINT16 n_packed )
+{
+ return n_packed >> 10;
+}
+
+INLINE INT32 mdec_unpack_val( UINT16 n_packed )
+{
+ return ( ( (INT32)n_packed ) << 22 ) >> 22;
+}
+
+UINT32 psxmdec_device::mdec_unpack( UINT32 n_address )
+{
+ psx_state *p_psx = machine().driver_data<psx_state>();
+ UINT32 *p_n_psxram = p_psx->m_p_n_psxram;
+
+ UINT8 n_z;
+ INT32 n_qscale;
+ UINT16 n_packed;
+ INT32 *p_n_block;
+ INT32 p_n_unpacked[ 64 ];
+ INT32 *p_n_q;
+
+ p_n_q = p_n_quantize_uv;
+ p_n_block = m_p_n_unpacked;
+
+ for( UINT32 n_block = 0; n_block < 6; n_block++ )
+ {
+ memset( p_n_unpacked, 0, sizeof( p_n_unpacked ) );
+
+ if( n_block == 2 )
+ {
+ p_n_q = p_n_quantize_y;
+ }
+ n_packed = psxreadword( p_n_psxram, n_address );
+ n_address += 2;
+ if( n_packed == 0xfe00 )
+ {
+ break;
+ }
+
+ n_qscale = mdec_unpack_run( n_packed );
+ p_n_unpacked[ 0 ] = mdec_unpack_val( n_packed ) * p_n_q[ 0 ];
+
+ n_z = 0;
+ for( ;; )
+ {
+ n_packed = psxreadword( p_n_psxram, n_address );
+ n_address += 2;
+
+ if( n_packed == 0xfe00 )
+ {
+ break;
+ }
+ n_z += mdec_unpack_run( n_packed ) + 1;
+ if( n_z > 63 )
+ {
+ break;
+ }
+ p_n_unpacked[ m_p_n_mdec_zigzag[ n_z ] ] = ( mdec_unpack_val( n_packed ) * p_n_q[ n_z ] * n_qscale ) / 8;
+ }
+ mdec_idct( p_n_unpacked, p_n_block );
+ p_n_block += DCTSIZE2;
+ }
+ return n_address;
+}
+
+INLINE INT32 mdec_cr_to_r( INT32 n_cr )
+{
+ return ( 1435 * n_cr ) >> 10;
+}
+
+INLINE INT32 mdec_cr_to_g( INT32 n_cr )
+{
+ return ( -731 * n_cr ) >> 10;
+}
+
+INLINE INT32 mdec_cb_to_g( INT32 n_cb )
+{
+ return ( -351 * n_cb ) >> 10;
+}
+
+INLINE INT32 mdec_cb_to_b( INT32 n_cb )
+{
+ return ( 1814 * n_cb ) >> 10;
+}
+
+UINT16 psxmdec_device::mdec_clamp_r5( INT32 n_r ) const
+{
+ return p_n_r5[ n_r + 128 + 256 ];
+}
+
+UINT16 psxmdec_device::mdec_clamp_g5( INT32 n_g ) const
+{
+ return p_n_g5[ n_g + 128 + 256 ];
+}
+
+UINT16 psxmdec_device::mdec_clamp_b5( INT32 n_b ) const
+{
+ return p_n_b5[ n_b + 128 + 256 ];
+}
+
+void psxmdec_device::mdec_makergb15( UINT32 n_address, INT32 n_r, INT32 n_g, INT32 n_b, INT32 *p_n_y, UINT16 n_stp )
+{
+ p_n_output[ WORD_XOR_LE( n_address + 0 ) / 2 ] = n_stp |
+ mdec_clamp_r5( p_n_y[ 0 ] + n_r ) |
+ mdec_clamp_g5( p_n_y[ 0 ] + n_g ) |
+ mdec_clamp_b5( p_n_y[ 0 ] + n_b );
+
+ p_n_output[ WORD_XOR_LE( n_address + 2 ) / 2 ] = n_stp |
+ mdec_clamp_r5( p_n_y[ 1 ] + n_r ) |
+ mdec_clamp_g5( p_n_y[ 1 ] + n_g ) |
+ mdec_clamp_b5( p_n_y[ 1 ] + n_b );
+}
+
+void psxmdec_device::mdec_yuv2_to_rgb15( void )
+{
+ INT32 n_r;
+ INT32 n_g;
+ INT32 n_b;
+ INT32 n_cb;
+ INT32 n_cr;
+ INT32 *p_n_cb;
+ INT32 *p_n_cr;
+ INT32 *p_n_y;
+ UINT32 n_x;
+ UINT32 n_y;
+ UINT32 n_z;
+ UINT16 n_stp;
+ int n_address = 0;
+
+ if( ( n_0_command & ( 1L << 25 ) ) != 0 )
+ {
+ n_stp = 0x8000;
+ }
+ else
+ {
+ n_stp = 0x0000;
+ }
+
+ p_n_cr = &m_p_n_unpacked[ 0 ];
+ p_n_cb = &m_p_n_unpacked[ DCTSIZE2 ];
+ p_n_y = &m_p_n_unpacked[ DCTSIZE2 * 2 ];
+
+ for( n_z = 0; n_z < 2; n_z++ )
+ {
+ for( n_y = 0; n_y < 4; n_y++ )
+ {
+ for( n_x = 0; n_x < 4; n_x++ )
+ {
+ n_cr = *( p_n_cr );
+ n_cb = *( p_n_cb );
+ n_r = mdec_cr_to_r( n_cr );
+ n_g = mdec_cr_to_g( n_cr ) + mdec_cb_to_g( n_cb );
+ n_b = mdec_cb_to_b( n_cb );
+
+ mdec_makergb15( ( n_address + 0 ), n_r, n_g, n_b, p_n_y, n_stp );
+ mdec_makergb15( ( n_address + 32 ), n_r, n_g, n_b, p_n_y + 8, n_stp );
+
+ n_cr = *( p_n_cr + 4 );
+ n_cb = *( p_n_cb + 4 );
+ n_r = mdec_cr_to_r( n_cr );
+ n_g = mdec_cr_to_g( n_cr ) + mdec_cb_to_g( n_cb );
+ n_b = mdec_cb_to_b( n_cb );
+
+ mdec_makergb15( ( n_address + 16 ), n_r, n_g, n_b, p_n_y + DCTSIZE2, n_stp );
+ mdec_makergb15( ( n_address + 48 ), n_r, n_g, n_b, p_n_y + DCTSIZE2 + 8, n_stp );
+
+ p_n_cr++;
+ p_n_cb++;
+ p_n_y += 2;
+ n_address += 4;
+ }
+ p_n_cr += 4;
+ p_n_cb += 4;
+ p_n_y += 8;
+ n_address += 48;
+ }
+ p_n_y += DCTSIZE2;
+ }
+ n_decoded = ( 16 * 16 ) / 2;
+}
+
+UINT16 psxmdec_device::mdec_clamp8( INT32 n_r ) const
+{
+ return p_n_clamp8[ n_r + 128 + 256 ];
+}
+
+void psxmdec_device::mdec_makergb24( UINT32 n_address, INT32 n_r, INT32 n_g, INT32 n_b, INT32 *p_n_y, UINT32 n_stp )
+{
+ p_n_output[ WORD_XOR_LE( n_address + 0 ) / 2 ] = ( mdec_clamp8( p_n_y[ 0 ] + n_g ) << 8 ) | mdec_clamp8( p_n_y[ 0 ] + n_r );
+ p_n_output[ WORD_XOR_LE( n_address + 2 ) / 2 ] = ( mdec_clamp8( p_n_y[ 1 ] + n_r ) << 8 ) | mdec_clamp8( p_n_y[ 0 ] + n_b );
+ p_n_output[ WORD_XOR_LE( n_address + 4 ) / 2 ] = ( mdec_clamp8( p_n_y[ 1 ] + n_b ) << 8 ) | mdec_clamp8( p_n_y[ 1 ] + n_g );
+}
+
+void psxmdec_device::mdec_yuv2_to_rgb24( void )
+{
+ INT32 n_r;
+ INT32 n_g;
+ INT32 n_b;
+ INT32 n_cb;
+ INT32 n_cr;
+ INT32 *p_n_cb;
+ INT32 *p_n_cr;
+ INT32 *p_n_y;
+ UINT32 n_x;
+ UINT32 n_y;
+ UINT32 n_z;
+ UINT32 n_stp;
+ int n_address = 0;
+
+ if( ( n_0_command & ( 1L << 25 ) ) != 0 )
+ {
+ n_stp = 0x80008000;
+ }
+ else
+ {
+ n_stp = 0x00000000;
+ }
+
+ p_n_cr = &m_p_n_unpacked[ 0 ];
+ p_n_cb = &m_p_n_unpacked[ DCTSIZE2 ];
+ p_n_y = &m_p_n_unpacked[ DCTSIZE2 * 2 ];
+
+ for( n_z = 0; n_z < 2; n_z++ )
+ {
+ for( n_y = 0; n_y < 4; n_y++ )
+ {
+ for( n_x = 0; n_x < 4; n_x++ )
+ {
+ n_cr = *( p_n_cr );
+ n_cb = *( p_n_cb );
+ n_r = mdec_cr_to_r( n_cr );
+ n_g = mdec_cr_to_g( n_cr ) + mdec_cb_to_g( n_cb );
+ n_b = mdec_cb_to_b( n_cb );
+
+ mdec_makergb24( ( n_address + 0 ), n_r, n_g, n_b, p_n_y, n_stp );
+ mdec_makergb24( ( n_address + 48 ), n_r, n_g, n_b, p_n_y + 8, n_stp );
+
+ n_cr = *( p_n_cr + 4 );
+ n_cb = *( p_n_cb + 4 );
+ n_r = mdec_cr_to_r( n_cr );
+ n_g = mdec_cr_to_g( n_cr ) + mdec_cb_to_g( n_cb );
+ n_b = mdec_cb_to_b( n_cb );
+
+ mdec_makergb24( ( n_address + 24 ), n_r, n_g, n_b, p_n_y + DCTSIZE2, n_stp );
+ mdec_makergb24( ( n_address + 72 ), n_r, n_g, n_b, p_n_y + DCTSIZE2 + 8, n_stp );
+
+ p_n_cr++;
+ p_n_cb++;
+ p_n_y += 2;
+ n_address += 6;
+ }
+ p_n_cr += 4;
+ p_n_cb += 4;
+ p_n_y += 8;
+ n_address += 72;
+ }
+ p_n_y += DCTSIZE2;
+ }
+ n_decoded = ( 24 * 16 ) / 2;
+}
+
+void psxmdec_device::dma_write( UINT32 n_address, INT32 n_size )
+{
+ psx_state *p_psx = machine().driver_data<psx_state>();
+ UINT32 *p_n_psxram = p_psx->m_p_n_psxram;
+ int n_index;
+
+ verboselog( machine(), 2, "mdec0_write( %08x, %08x )\n", n_address, n_size );
+
+ switch( n_0_command >> 28 )
+ {
+ case 0x3:
+ verboselog( machine(), 1, "mdec decode %08x %08x %08x\n", n_0_command, n_address, n_size );
+ n_0_address = n_address;
+ n_0_size = n_size * 4;
+ n_1_status |= ( 1L << 29 );
+ break;
+ case 0x4:
+ verboselog( machine(), 1, "mdec quantize table %08x %08x %08x\n", n_0_command, n_address, n_size );
+ n_index = 0;
+ while( n_size > 0 )
+ {
+ if( n_index < DCTSIZE2 )
+ {
+ p_n_quantize_y[ n_index + 0 ] = ( p_n_psxram[ n_address / 4 ] >> 0 ) & 0xff;
+ p_n_quantize_y[ n_index + 1 ] = ( p_n_psxram[ n_address / 4 ] >> 8 ) & 0xff;
+ p_n_quantize_y[ n_index + 2 ] = ( p_n_psxram[ n_address / 4 ] >> 16 ) & 0xff;
+ p_n_quantize_y[ n_index + 3 ] = ( p_n_psxram[ n_address / 4 ] >> 24 ) & 0xff;
+ }
+ else if( n_index < DCTSIZE2 * 2 )
+ {
+ p_n_quantize_uv[ n_index + 0 - DCTSIZE2 ] = ( p_n_psxram[ n_address / 4 ] >> 0 ) & 0xff;
+ p_n_quantize_uv[ n_index + 1 - DCTSIZE2 ] = ( p_n_psxram[ n_address / 4 ] >> 8 ) & 0xff;
+ p_n_quantize_uv[ n_index + 2 - DCTSIZE2 ] = ( p_n_psxram[ n_address / 4 ] >> 16 ) & 0xff;
+ p_n_quantize_uv[ n_index + 3 - DCTSIZE2 ] = ( p_n_psxram[ n_address / 4 ] >> 24 ) & 0xff;
+ }
+ n_index += 4;
+ n_address += 4;
+ n_size--;
+ }
+ break;
+ case 0x6:
+ verboselog( machine(), 1, "mdec cosine table %08x %08x %08x\n", n_0_command, n_address, n_size );
+ n_index = 0;
+ while( n_size > 0 )
+ {
+ p_n_cos[ n_index + 0 ] = (INT16)( ( p_n_psxram[ n_address / 4 ] >> 0 ) & 0xffff );
+ p_n_cos[ n_index + 1 ] = (INT16)( ( p_n_psxram[ n_address / 4 ] >> 16 ) & 0xffff );
+ n_index += 2;
+ n_address += 4;
+ n_size--;
+ }
+ mdec_cos_precalc();
+ break;
+ default:
+ verboselog( machine(), 0, "mdec unknown command %08x %08x %08x\n", n_0_command, n_address, n_size );
+ break;
+ }
+}
+
+void psxmdec_device::dma_read( UINT32 n_address, INT32 n_size )
+{
+ psx_state *p_psx = machine().driver_data<psx_state>();
+ UINT32 *p_n_psxram = p_psx->m_p_n_psxram;
+ UINT32 n_this;
+ UINT32 n_nextaddress;
+
+ verboselog( machine(), 2, "mdec1_read( %08x, %08x )\n", n_address, n_size );
+ if( ( n_0_command & ( 1L << 29 ) ) != 0 && n_0_size != 0 )
+ {
+ while( n_size > 0 )
+ {
+ if( n_decoded == 0 )
+ {
+ if( (int)n_0_size <= 0 )
+ {
+ mame_printf_debug( "ran out of data %08x\n", n_size );
+ n_0_size = 0;
+ break;
+ }
+
+ n_nextaddress = mdec_unpack( n_0_address );
+ n_0_size -= n_nextaddress - n_0_address;
+ n_0_address = n_nextaddress;
+
+ if( ( n_0_command & ( 1L << 27 ) ) != 0 )
+ {
+ mdec_yuv2_to_rgb15();
+ }
+ else
+ {
+ mdec_yuv2_to_rgb24();
+ }
+ n_offset = 0;
+ }
+
+ n_this = n_decoded;
+ if( n_this > n_size )
+ {
+ n_this = n_size;
+ }
+ n_decoded -= n_this;
+
+ memcpy( (UINT8 *)p_n_psxram + n_address, (UINT8 *)p_n_output + n_offset, n_this * 4 );
+ n_offset += n_this * 4;
+ n_address += n_this * 4;
+ n_size -= n_this;
+ }
+
+ if( (int)n_0_size < 0 )
+ {
+ mame_printf_debug( "ran out of data %d\n", n_0_size );
+ }
+ }
+ else
+ {
+ mame_printf_debug( "mdec1_read no conversion :%08x:%08x:\n", n_0_command, n_0_size );
+ }
+ n_1_status &= ~( 1L << 29 );
+}
+
+WRITE32_MEMBER( psxmdec_device::write )
+{
+ switch( offset )
+ {
+ case 0:
+ verboselog( machine(), 2, "mdec 0 command %08x\n", data );
+ n_0_command = data;
+ break;
+ case 1:
+ verboselog( machine(), 2, "mdec 1 command %08x\n", data );
+ n_1_command = data;
+ break;
+ }
+}
+
+READ32_MEMBER( psxmdec_device::read )
+{
+ switch( offset )
+ {
+ case 0:
+ verboselog( machine(), 2, "mdec 0 status %08x\n", 0 );
+ return 0;
+ case 1:
+ verboselog( machine(), 2, "mdec 1 status %08x\n", n_1_status );
+ return n_1_status;
+ }
+ return 0;
+}
diff --git a/trunk/src/emu/cpu/psx/mdec.h b/trunk/src/emu/cpu/psx/mdec.h
new file mode 100644
index 00000000000..d4dc2379c63
--- /dev/null
+++ b/trunk/src/emu/cpu/psx/mdec.h
@@ -0,0 +1,74 @@
+/*
+ * PlayStation DMA emulator
+ *
+ * Copyright 2003-2011 smf
+ *
+ */
+
+#pragma once
+
+#ifndef __PSXMDEC_H__
+#define __PSXMDEC_H__
+
+#include "emu.h"
+
+extern const device_type PSX_MDEC;
+
+#define DCTSIZE ( 8 )
+#define DCTSIZE2 ( DCTSIZE * DCTSIZE )
+
+#define MDEC_COS_PRECALC_BITS ( 21 )
+
+class psxmdec_device : public device_t
+{
+public:
+ psxmdec_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ WRITE32_MEMBER( write );
+ READ32_MEMBER( read );
+
+ void dma_write( UINT32 n_address, INT32 n_size );
+ void dma_read( UINT32 n_address, INT32 n_size );
+
+protected:
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_post_load();
+
+private:
+ void mdec_cos_precalc();
+ void mdec_idct( INT32 *p_n_src, INT32 *p_n_dst );
+ UINT32 mdec_unpack( UINT32 n_address );
+ UINT16 mdec_clamp_r5( INT32 n_r ) const;
+ UINT16 mdec_clamp_g5( INT32 n_g ) const;
+ UINT16 mdec_clamp_b5( INT32 n_b ) const;
+ UINT16 mdec_clamp8( INT32 n_r ) const;
+ void mdec_yuv2_to_rgb15( void );
+ void mdec_yuv2_to_rgb24( void );
+ void mdec_makergb15( UINT32 n_address, INT32 n_r, INT32 n_g, INT32 n_b, INT32 *p_n_y, UINT16 n_stp );
+ void mdec_makergb24( UINT32 n_address, INT32 n_r, INT32 n_g, INT32 n_b, INT32 *p_n_y, UINT32 n_stp );
+
+ UINT32 n_decoded;
+ UINT32 n_offset;
+ UINT16 p_n_output[ 24 * 16 ];
+
+ INT32 p_n_quantize_y[ DCTSIZE2 ];
+ INT32 p_n_quantize_uv[ DCTSIZE2 ];
+ INT32 p_n_cos[ DCTSIZE2 ];
+ INT32 p_n_cos_precalc[ DCTSIZE2 * DCTSIZE2 ];
+
+ UINT32 n_0_command;
+ UINT32 n_0_address;
+ UINT32 n_0_size;
+ UINT32 n_1_command;
+ UINT32 n_1_status;
+
+ UINT16 p_n_clamp8[ 256 * 3 ];
+ UINT16 p_n_r5[ 256 * 3 ];
+ UINT16 p_n_g5[ 256 * 3 ];
+ UINT16 p_n_b5[ 256 * 3 ];
+
+ INT32 m_p_n_unpacked[ DCTSIZE2 * 6 * 2 ];
+};
+
+#endif
diff --git a/trunk/src/emu/cpu/psx/psx.c b/trunk/src/emu/cpu/psx/psx.c
new file mode 100644
index 00000000000..e743ca4ec1e
--- /dev/null
+++ b/trunk/src/emu/cpu/psx/psx.c
@@ -0,0 +1,3207 @@
+/*
+ * PlayStation CPU emulator
+ *
+ * Copyright 2003-2011 smf
+ *
+ * Known chip id's
+ * CXD8530AQ
+ * CXD8530BQ
+ * CXD8530CQ
+ * CXD8661R
+ * CXD8606BQ
+ * CXD8606CQ
+ *
+ * The PlayStation CPU is based on the LSI LR33300.
+ *
+ * Differences from the LR33300:
+ *
+ * There is only 1k of data cache ram ( the LR33300 has 2k )
+ *
+ * There is no data cache tag ram, so the data cache ram can only be used as a fast area
+ * of ram ( which is a standard LR33300 feature ).
+ *
+ * If COP0 is disabled in user mode you get a coprocessor unusable exception, while
+ * the LR33300 is documented to generate a reserved instruction exception.
+ *
+ * Known limitations of the emulation:
+ *
+ * Only read & write break points are emulated, trace and program counter breakpoints are not.
+ *
+ * Load/Store timings are based on load scheduling turned off & no write cache. This affects when
+ * bus error exceptions occur and also when the read & write handlers are called. A scheduled
+ * load will complete if a load breakpoint fires, but an unscheduled load will not.
+ *
+ * Reading from the data and instruction cache at the same time causes a bus conflict that
+ * corrupts the data in a reliable but strange way, which is not emulated.
+ *
+ * Values written to COP1 & COP3 can be read back by the next instruction, which is not emulated.
+ * Because of loadscheduling the value loaded with LWC1/LWC3 can be read by more than the next
+ * instruction.
+ *
+ * SWC0 writes stale data from a previous operation, this is only partially emulated as the timing
+ * is complicated. Left over instruction fetches are currently emulated as they are the most
+ * 'interesting' and have no impact on the rest of the emulation.
+ *
+ * MTC0 timing is not emulated, switching to user mode while in kernel space continues
+ * execution for another two instructions before taking an exception. Using RFE to do the same
+ * thing causes the exception straight away, unless the RFE is the first instructio that follows
+ * an MTC0 instruction.
+ *
+ * The PRId register should be 1 on some revisions of the CPU ( there might be other values too ).
+ *
+ * Moving to the HI/LO register after a multiply or divide, but before reading the results will
+ * always abort the operation as if you did it immediately. In reality it should complete on it's
+ * own, and aborting before it completes would result in returning the working results.
+ *
+ * Running code in cached address space does not use or update the instruction cache.
+ *
+ * Wait states are not emulated.
+ *
+ * Bus errors caused by instruction fetches are not supported.
+ *
+ */
+
+#define ADDRESS_MAP_MODERN
+#include "emu.h"
+#include "debugger.h"
+#include "psx.h"
+#include "dma.h"
+#include "irq.h"
+#include "mdec.h"
+#include "rcnt.h"
+#include "sio.h"
+#include "includes/psx.h"
+#include "sound/spu.h"
+
+#define LOG_BIOSCALL ( 0 )
+
+#define EXC_INT ( 0 )
+#define EXC_ADEL ( 4 )
+#define EXC_ADES ( 5 )
+#define EXC_DBE ( 7 )
+#define EXC_SYS ( 8 )
+#define EXC_BP ( 9 )
+#define EXC_RI ( 10 )
+#define EXC_CPU ( 11 )
+#define EXC_OVF ( 12 )
+
+#define CP0_INDEX ( 0 )
+#define CP0_RANDOM ( 1 )
+#define CP0_ENTRYLO ( 2 )
+#define CP0_CONTEXT ( 4 )
+#define CP0_ENTRYHI ( 10 )
+
+#define CP0_BPC ( 3 )
+#define CP0_BDA ( 5 )
+#define CP0_TAR ( 6 )
+#define CP0_DCIC ( 7 )
+#define CP0_BADA ( 8 )
+#define CP0_BDAM ( 9 )
+#define CP0_BPCM ( 11 )
+#define CP0_SR ( 12 )
+#define CP0_CAUSE ( 13 )
+#define CP0_EPC ( 14 )
+#define CP0_PRID ( 15 )
+
+#define DCIC_STATUS ( 0x3f )
+#define DCIC_DB ( 1L << 0 )
+#define DCIC_DA ( 1L << 2 )
+#define DCIC_R ( 1L << 3 )
+#define DCIC_W ( 1L << 4 )
+#define DCIC_DE ( 1L << 23 )
+#define DCIC_DAE ( 1L << 25 )
+#define DCIC_DR ( 1L << 26 )
+#define DCIC_DW ( 1L << 27 )
+#define DCIC_KD ( 1L << 29 )
+#define DCIC_UD ( 1L << 30 )
+#define DCIC_TR ( 1L << 31 )
+
+#define SR_IEC ( 1L << 0 )
+#define SR_KUC ( 1L << 1 )
+#define SR_ISC ( 1L << 16 )
+#define SR_SWC ( 1L << 17 )
+#define SR_BEV ( 1L << 22 )
+#define SR_CU0 ( 1L << 28 )
+#define SR_CU1 ( 1L << 29 )
+#define SR_CU2 ( 1L << 30 )
+#define SR_CU3 ( 1L << 31 )
+
+#define CAUSE_EXC ( 31L << 2 )
+#define CAUSE_IP ( 255L << 8 )
+#define CAUSE_IP2 ( 1L << 10 )
+#define CAUSE_IP3 ( 1L << 11 )
+#define CAUSE_IP4 ( 1L << 12 )
+#define CAUSE_IP5 ( 1L << 13 )
+#define CAUSE_IP6 ( 1L << 14 )
+#define CAUSE_IP7 ( 1L << 15 )
+#define CAUSE_CE ( 3L << 28 )
+#define CAUSE_BT ( 1L << 30 )
+#define CAUSE_BD ( 1L << 31 )
+
+#define BIU_LOCK ( 0x00000001 )
+#define BIU_INV ( 0x00000002 )
+#define BIU_TAG ( 0x00000004 )
+#define BIU_RAM ( 0x00000008 )
+#define BIU_DS ( 0x00000080 )
+#define BIU_IS1 ( 0x00000800 )
+
+#define TAG_MATCH_MASK ( 0 - ( ICACHE_ENTRIES * 4 ) )
+#define TAG_MATCH ( 0x10 )
+#define TAG_VALID ( 0x0f )
+
+#define MULTIPLIER_OPERATION_IDLE ( 0 )
+#define MULTIPLIER_OPERATION_MULT ( 1 )
+#define MULTIPLIER_OPERATION_MULTU ( 2 )
+#define MULTIPLIER_OPERATION_DIV ( 3 )
+#define MULTIPLIER_OPERATION_DIVU ( 4 )
+
+static const char *const delayn[] =
+{
+ "", "at", "v0", "v1", "a0", "a1", "a2", "a3",
+ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+ "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra",
+ "pc", "!pc"
+};
+
+// device type definition
+const device_type CXD8530AQ = &device_creator<cxd8530aq_device>;
+const device_type CXD8530BQ = &device_creator<cxd8530bq_device>;
+const device_type CXD8530CQ = &device_creator<cxd8530cq_device>;
+const device_type CXD8661R = &device_creator<cxd8661r_device>;
+const device_type CXD8606BQ = &device_creator<cxd8606bq_device>;
+const device_type CXD8606CQ = &device_creator<cxd8606cq_device>;
+
+static const UINT32 mtc0_writemask[]=
+{
+ 0x00000000, /* !INDEX */
+ 0x00000000, /* !RANDOM */
+ 0x00000000, /* !ENTRYLO */
+ 0xffffffff, /* BPC */
+ 0x00000000, /* !CONTEXT */
+ 0xffffffff, /* BDA */
+ 0x00000000, /* TAR */
+ 0xff80f03f, /* DCIC */
+ 0x00000000, /* BADA */
+ 0xffffffff, /* BDAM */
+ 0x00000000, /* !ENTRYHI */
+ 0xffffffff, /* BPCM */
+ 0xf04fff3f, /* SR */
+ 0x00000300, /* CAUSE */
+ 0x00000000, /* EPC */
+ 0x00000000 /* PRID */
+};
+
+READ32_MEMBER( psxcpu_device::berr_r )
+{
+ m_berr = 1;
+ return 0;
+}
+
+WRITE32_MEMBER( psxcpu_device::berr_w )
+{
+ m_berr = 1;
+}
+
+READ32_MEMBER( psxcpu_device::biu_r )
+{
+ return m_biu;
+}
+
+WRITE32_MEMBER( psxcpu_device::biu_w )
+{
+ UINT32 old = m_biu;
+
+ COMBINE_DATA( &m_biu );
+
+ if( ( old & ( BIU_RAM | BIU_DS ) ) != ( m_biu & ( BIU_RAM | BIU_DS ) ) )
+ {
+ update_scratchpad();
+ }
+}
+
+void psxcpu_device::stop()
+{
+ debugger_break( machine() );
+ debugger_instruction_hook( this, m_pc );
+}
+
+UINT32 psxcpu_device::cache_readword( UINT32 offset )
+{
+ UINT32 data = 0;
+
+ if( ( m_biu & BIU_TAG ) != 0 )
+ {
+ if( ( m_biu & BIU_IS1 ) != 0 )
+ {
+ UINT32 tag = m_icacheTag[ ( offset / 16 ) % ( ICACHE_ENTRIES / 4 ) ];
+ data |= tag & TAG_VALID;
+
+ if( ( ( tag ^ offset ) & TAG_MATCH_MASK ) == 0 )
+ {
+ data |= TAG_MATCH;
+ }
+ }
+ }
+ else if( ( m_biu & ( BIU_LOCK | BIU_INV ) ) != 0 )
+ {
+ }
+ else
+ {
+ if( ( m_biu & BIU_IS1 ) == BIU_IS1 )
+ {
+ data |= m_icache[ ( offset / 4 ) % ICACHE_ENTRIES ];
+ }
+
+ if( ( m_biu & BIU_DS ) == BIU_DS )
+ {
+ data |= m_dcache[ ( offset / 4 ) % DCACHE_ENTRIES ];
+ }
+ }
+
+ return data;
+}
+
+void psxcpu_device::cache_writeword( UINT32 offset, UINT32 data )
+{
+ if( ( m_biu & BIU_TAG ) != 0 )
+ {
+ if( ( m_biu & BIU_IS1 ) != 0 )
+ {
+ m_icacheTag[ ( offset / 16 ) % ( ICACHE_ENTRIES / 4 ) ] = ( data & TAG_VALID ) | ( offset & TAG_MATCH_MASK );
+ }
+ }
+ else if( ( m_biu & ( BIU_LOCK | BIU_INV ) ) != 0 )
+ {
+ if( ( m_biu & BIU_IS1 ) != 0 )
+ {
+ m_icacheTag[ ( offset / 16 ) % ( ICACHE_ENTRIES / 4 ) ] = ( offset & TAG_MATCH_MASK );
+ }
+ }
+ else
+ {
+ if( ( m_biu & BIU_IS1 ) != 0 )
+ {
+ m_icache[ ( offset / 4 ) % ICACHE_ENTRIES ] = data;
+ }
+
+ if( ( m_biu & BIU_DS ) != 0 )
+ {
+ m_dcache[ ( offset / 4 ) % DCACHE_ENTRIES ] = data;
+ }
+ }
+}
+
+UINT8 psxcpu_device::readbyte( UINT32 address )
+{
+ if( m_bus_attached )
+ {
+ return m_program->read_byte( address );
+ }
+
+ return cache_readword( address ) >> ( ( address & 3 ) * 8 );
+}
+
+UINT16 psxcpu_device::readhalf( UINT32 address )
+{
+ if( m_bus_attached )
+ {
+ return m_program->read_word( address );
+ }
+
+ return cache_readword( address ) >> ( ( address & 2 ) * 8 );
+}
+
+UINT32 psxcpu_device::readword( UINT32 address )
+{
+ if( m_bus_attached )
+ {
+ return m_program->read_dword( address );
+ }
+
+ return cache_readword( address );
+}
+
+UINT32 psxcpu_device::readword_masked( UINT32 address, UINT32 mask )
+{
+ if( m_bus_attached )
+ {
+ return m_program->read_dword( address, mask );
+ }
+
+ return cache_readword( address );
+}
+
+void psxcpu_device::writeword( UINT32 address, UINT32 data )
+{
+ if( m_bus_attached )
+ {
+ m_program->write_dword( address, data );
+ }
+ else
+ {
+ cache_writeword( address, data );
+ }
+}
+
+void psxcpu_device::writeword_masked( UINT32 address, UINT32 data, UINT32 mask )
+{
+ if( m_bus_attached )
+ {
+ m_program->write_dword( address, data, mask );
+ }
+ else
+ {
+ cache_writeword( address, data );
+ }
+}
+
+
+static const struct
+{
+ int address;
+ int operation;
+ const char *prototype;
+} bioscalls[] =
+{
+ { 0xa0, 0x00, "int open(const char *name, int mode)" },
+ { 0xa0, 0x01, "int lseek(int fd, int offset, int whence)" },
+ { 0xa0, 0x02, "int read(int fd, void *buf, int nbytes)" },
+ { 0xa0, 0x03, "int write(int fd, void *buf, int nbytes)" },
+ { 0xa0, 0x04, "int close(int fd)" },
+ { 0xa0, 0x05, "int ioctl(int fd, int cmd, int arg)" },
+ { 0xa0, 0x06, "void exit(int code)" },
+ { 0xa0, 0x07, "sys_a0_07()" },
+ { 0xa0, 0x08, "char getc(int fd)" },
+ { 0xa0, 0x09, "void putc(char c, int fd)" },
+ { 0xa0, 0x0a, "todigit()" },
+ { 0xa0, 0x0b, "double atof(const char *s)" },
+ { 0xa0, 0x0c, "long strtoul(const char *s, char **ptr, int base)" },
+ { 0xa0, 0x0d, "unsigned long strtol(const char *s, char **ptr, int base)" },
+ { 0xa0, 0x0e, "int abs(int val)" },
+ { 0xa0, 0x0f, "long labs(long lval)" },
+ { 0xa0, 0x10, "long atoi(const char *s)" },
+ { 0xa0, 0x11, "int atol(const char *s)" },
+ { 0xa0, 0x12, "atob()" },
+ { 0xa0, 0x13, "int setjmp(jmp_buf *ctx)" },
+ { 0xa0, 0x14, "void longjmp(jmp_buf *ctx, int value)" },
+ { 0xa0, 0x15, "char *strcat(char *dst, const char *src)" },
+ { 0xa0, 0x16, "char *strncat(char *dst, const char *src, size_t n)" },
+ { 0xa0, 0x17, "int strcmp(const char *dst, const char *src)" },
+ { 0xa0, 0x18, "int strncmp(const char *dst, const char *src, size_t n)" },
+ { 0xa0, 0x19, "char *strcpy(char *dst, const char *src)" },
+ { 0xa0, 0x1a, "char *strncpy(char *dst, const char *src, size_t n)" },
+ { 0xa0, 0x1b, "size_t strlen(const char *s)" },
+ { 0xa0, 0x1c, "int index(const char *s, int c)" },
+ { 0xa0, 0x1d, "int rindex(const char *s, int c)" },
+ { 0xa0, 0x1e, "char *strchr(const char *s, int c)" },
+ { 0xa0, 0x1f, "char *strrchr(const char *s, int c)" },
+ { 0xa0, 0x20, "char *strpbrk(const char *dst, const char *src)" },
+ { 0xa0, 0x21, "size_t strspn(const char *s, const char *set)" },
+ { 0xa0, 0x22, "size_t strcspn(const char *s, const char *set)" },
+ { 0xa0, 0x23, "char *strtok(char *s, const char *set)" },
+ { 0xa0, 0x24, "char *strstr(const char *s, const char *set)" },
+ { 0xa0, 0x25, "int toupper(int c)" },
+ { 0xa0, 0x26, "int tolower(int c)" },
+ { 0xa0, 0x27, "void bcopy(const void *src, void *dst, size_t len)" },
+ { 0xa0, 0x28, "void bzero(void *ptr, size_t len)" },
+ { 0xa0, 0x29, "int bcmp(const void *ptr1, const void *ptr2, int len)" },
+ { 0xa0, 0x2a, "void *memcpy(void *dst, const void *src, size_t n)" },
+ { 0xa0, 0x2b, "void *memset(void *dst, char c, size_t n)" },
+ { 0xa0, 0x2c, "void *memmove(void *dst, const void *src, size_t n)" },
+ { 0xa0, 0x2d, "int memcmp(const void *dst, const void *src, size_t n)" },
+ { 0xa0, 0x2e, "void *memchr(const void *s, int c, size_t n)" },
+ { 0xa0, 0x2f, "int rand()" },
+ { 0xa0, 0x30, "void srand(unsigned int seed)" },
+ { 0xa0, 0x31, "void qsort(void *base, int nel, int width, int (*cmp)(void *, void *))" },
+ { 0xa0, 0x32, "double strtod(const char *s, char **endptr)" },
+ { 0xa0, 0x33, "void *malloc(int size)" },
+ { 0xa0, 0x34, "void free(void *buf)" },
+ { 0xa0, 0x35, "void *lsearch(void *key, void *base, int belp, int width, int (*cmp)(void *, void *))" },
+ { 0xa0, 0x36, "void *bsearch(void *key, void *base, int nel, int size, int (*cmp)(void *, void *))" },
+ { 0xa0, 0x37, "void *calloc(int size, int n)" },
+ { 0xa0, 0x38, "void *realloc(void *buf, int n)" },
+ { 0xa0, 0x39, "InitHeap(void *block, int size)" },
+ { 0xa0, 0x3a, "void _exit(int code)" },
+ { 0xa0, 0x3b, "char getchar(void)" },
+ { 0xa0, 0x3c, "void putchar(char c)" },
+ { 0xa0, 0x3d, "char *gets(char *s)" },
+ { 0xa0, 0x3e, "void puts(const char *s)" },
+ { 0xa0, 0x3f, "int printf(const char *fmt, ...)" },
+ { 0xa0, 0x40, "sys_a0_40()" },
+ { 0xa0, 0x41, "int LoadTest(const char *name, struct EXEC *header)" },
+ { 0xa0, 0x42, "int Load(const char *name, struct EXEC *header)" },
+ { 0xa0, 0x43, "int Exec(struct EXEC *header, int argc, char **argv)" },
+ { 0xa0, 0x44, "void FlushCache()" },
+ { 0xa0, 0x45, "void InstallInterruptHandler()" },
+ { 0xa0, 0x46, "GPU_dw(int x, int y, int w, int h, long *data)" },
+ { 0xa0, 0x47, "mem2vram(int x, int y, int w, int h, long *data)" },
+ { 0xa0, 0x48, "SendGPU(int status)" },
+ { 0xa0, 0x49, "GPU_cw(long cw)" },
+ { 0xa0, 0x4a, "GPU_cwb(long *pkt, int len)" },
+ { 0xa0, 0x4b, "SendPackets(void *ptr)" },
+ { 0xa0, 0x4c, "sys_a0_4c()" },
+ { 0xa0, 0x4d, "int GetGPUStatus()" },
+ { 0xa0, 0x4e, "GPU_sync()" },
+ { 0xa0, 0x4f, "sys_a0_4f()" },
+ { 0xa0, 0x50, "sys_a0_50()" },
+ { 0xa0, 0x51, "int LoadExec(const char *name, int, int)" },
+ { 0xa0, 0x52, "GetSysSp()" },
+ { 0xa0, 0x53, "sys_a0_53()" },
+ { 0xa0, 0x54, "_96_init()" },
+ { 0xa0, 0x55, "_bu_init()" },
+ { 0xa0, 0x56, "_96_remove()" },
+ { 0xa0, 0x57, "sys_a0_57()" },
+ { 0xa0, 0x58, "sys_a0_58()" },
+ { 0xa0, 0x59, "sys_a0_59()" },
+ { 0xa0, 0x5a, "sys_a0_5a()" },
+ { 0xa0, 0x5b, "dev_tty_init()" },
+ { 0xa0, 0x5c, "dev_tty_open()" },
+ { 0xa0, 0x5d, "dev_tty_5d()" },
+ { 0xa0, 0x5e, "dev_tty_ioctl()" },
+ { 0xa0, 0x5f, "dev_cd_open()" },
+ { 0xa0, 0x60, "dev_cd_read()" },
+ { 0xa0, 0x61, "dev_cd_close()" },
+ { 0xa0, 0x62, "dev_cd_firstfile()" },
+ { 0xa0, 0x63, "dev_cd_nextfile()" },
+ { 0xa0, 0x64, "dev_cd_chdir()" },
+ { 0xa0, 0x65, "dev_card_open()" },
+ { 0xa0, 0x66, "dev_card_read()" },
+ { 0xa0, 0x67, "dev_card_write()" },
+ { 0xa0, 0x68, "dev_card_close()" },
+ { 0xa0, 0x69, "dev_card_firstfile()" },
+ { 0xa0, 0x6a, "dev_card_nextfile()" },
+ { 0xa0, 0x6b, "dev_card_erase()" },
+ { 0xa0, 0x6c, "dev_card_undelete()" },
+ { 0xa0, 0x6d, "dev_card_format()" },
+ { 0xa0, 0x6e, "dev_card_rename()" },
+ { 0xa0, 0x6f, "dev_card_6f()" },
+ { 0xa0, 0x70, "_bu_init()" },
+ { 0xa0, 0x71, "_96_init()" },
+ { 0xa0, 0x72, "_96_remove()" },
+ { 0xa0, 0x73, "sys_a0_73()" },
+ { 0xa0, 0x74, "sys_a0_74()" },
+ { 0xa0, 0x75, "sys_a0_75()" },
+ { 0xa0, 0x76, "sys_a0_76()" },
+ { 0xa0, 0x77, "sys_a0_77()" },
+ { 0xa0, 0x78, "_96_CdSeekL()" },
+ { 0xa0, 0x79, "sys_a0_79()" },
+ { 0xa0, 0x7a, "sys_a0_7a()" },
+ { 0xa0, 0x7b, "sys_a0_7b()" },
+ { 0xa0, 0x7c, "_96_CdGetStatus()" },
+ { 0xa0, 0x7d, "sys_a0_7d()" },
+ { 0xa0, 0x7e, "_96_CdRead()" },
+ { 0xa0, 0x7f, "sys_a0_7f()" },
+ { 0xa0, 0x80, "sys_a0_80()" },
+ { 0xa0, 0x81, "sys_a0_81()" },
+ { 0xa0, 0x82, "sys_a0_82()" },
+ { 0xa0, 0x83, "sys_a0_83()" },
+ { 0xa0, 0x84, "sys_a0_84()" },
+ { 0xa0, 0x85, "_96_CdStop()" },
+ { 0xa0, 0x84, "sys_a0_84()" },
+ { 0xa0, 0x85, "sys_a0_85()" },
+ { 0xa0, 0x86, "sys_a0_86()" },
+ { 0xa0, 0x87, "sys_a0_87()" },
+ { 0xa0, 0x88, "sys_a0_88()" },
+ { 0xa0, 0x89, "sys_a0_89()" },
+ { 0xa0, 0x8a, "sys_a0_8a()" },
+ { 0xa0, 0x8b, "sys_a0_8b()" },
+ { 0xa0, 0x8c, "sys_a0_8c()" },
+ { 0xa0, 0x8d, "sys_a0_8d()" },
+ { 0xa0, 0x8e, "sys_a0_8e()" },
+ { 0xa0, 0x8f, "sys_a0_8f()" },
+ { 0xa0, 0x90, "sys_a0_90()" },
+ { 0xa0, 0x91, "sys_a0_91()" },
+ { 0xa0, 0x92, "sys_a0_92()" },
+ { 0xa0, 0x93, "sys_a0_93()" },
+ { 0xa0, 0x94, "sys_a0_94()" },
+ { 0xa0, 0x95, "sys_a0_95()" },
+ { 0xa0, 0x96, "AddCDROMDevice()" },
+ { 0xa0, 0x97, "AddMemCardDevice()" },
+ { 0xa0, 0x98, "DisableKernelIORedirection()" },
+ { 0xa0, 0x99, "EnableKernelIORedirection()" },
+ { 0xa0, 0x9a, "sys_a0_9a()" },
+ { 0xa0, 0x9b, "sys_a0_9b()" },
+ { 0xa0, 0x9c, "void SetConf(int Event, int TCB, int Stack)" },
+ { 0xa0, 0x9d, "void GetConf(int *Event, int *TCB, int *Stack)" },
+ { 0xa0, 0x9e, "sys_a0_9e()" },
+ { 0xa0, 0x9f, "void SetMem(int size)" },
+ { 0xa0, 0xa0, "_boot()" },
+ { 0xa0, 0xa1, "SystemError()" },
+ { 0xa0, 0xa2, "EnqueueCdIntr()" },
+ { 0xa0, 0xa3, "DequeueCdIntr()" },
+ { 0xa0, 0xa4, "sys_a0_a4()" },
+ { 0xa0, 0xa5, "ReadSector(int count, int sector, void *buffer)" },
+ { 0xa0, 0xa6, "get_cd_status()" },
+ { 0xa0, 0xa7, "bufs_cb_0()" },
+ { 0xa0, 0xa8, "bufs_cb_1()" },
+ { 0xa0, 0xa9, "bufs_cb_2()" },
+ { 0xa0, 0xaa, "bufs_cb_3()" },
+ { 0xa0, 0xab, "_card_info()" },
+ { 0xa0, 0xac, "_card_load()" },
+ { 0xa0, 0xad, "_card_auto()" },
+ { 0xa0, 0xae, "bufs_cb_4()" },
+ { 0xa0, 0xaf, "sys_a0_af()" },
+ { 0xa0, 0xb0, "sys_a0_b0()" },
+ { 0xa0, 0xb1, "sys_a0_b1()" },
+ { 0xa0, 0xb2, "do_a_long_jmp()" },
+ { 0xa0, 0xb3, "sys_a0_b3()" },
+ { 0xa0, 0xb4, "GetKernelInfo(int sub_function)" },
+ { 0xb0, 0x00, "SysMalloc()" },
+ { 0xb0, 0x01, "sys_b0_01()" },
+ { 0xb0, 0x02, "sys_b0_02()" },
+ { 0xb0, 0x03, "sys_b0_03()" },
+ { 0xb0, 0x04, "sys_b0_04()" },
+ { 0xb0, 0x05, "sys_b0_05()" },
+ { 0xb0, 0x06, "sys_b0_06()" },
+ { 0xb0, 0x07, "void DeliverEvent(u_long class, u_long event)" },
+ { 0xb0, 0x08, "long OpenEvent(u_long class, long spec, long mode, long (*func)())" },
+ { 0xb0, 0x09, "long CloseEvent(long event)" },
+ { 0xb0, 0x0a, "long WaitEvent(long event)" },
+ { 0xb0, 0x0b, "long TestEvent(long event)" },
+ { 0xb0, 0x0c, "long EnableEvent(long event)" },
+ { 0xb0, 0x0d, "long DisableEvent(long event)" },
+ { 0xb0, 0x0e, "OpenTh()" },
+ { 0xb0, 0x0f, "CloseTh()" },
+ { 0xb0, 0x10, "ChangeTh()" },
+ { 0xb0, 0x11, "sys_b0_11()" },
+ { 0xb0, 0x12, "int InitPAD(char *buf1, int len1, char *buf2, int len2)" },
+ { 0xb0, 0x13, "int StartPAD(void)" },
+ { 0xb0, 0x14, "int StopPAD(void)" },
+ { 0xb0, 0x15, "PAD_init(u_long nazo, u_long *pad_buf)" },
+ { 0xb0, 0x16, "u_long PAD_dr()" },
+ { 0xb0, 0x17, "void ReturnFromException(void)" },
+ { 0xb0, 0x18, "ResetEntryInt()" },
+ { 0xb0, 0x19, "HookEntryInt()" },
+ { 0xb0, 0x1a, "sys_b0_1a()" },
+ { 0xb0, 0x1b, "sys_b0_1b()" },
+ { 0xb0, 0x1c, "sys_b0_1c()" },
+ { 0xb0, 0x1d, "sys_b0_1d()" },
+ { 0xb0, 0x1e, "sys_b0_1e()" },
+ { 0xb0, 0x1f, "sys_b0_1f()" },
+ { 0xb0, 0x20, "UnDeliverEvent(int class, int event)" },
+ { 0xb0, 0x21, "sys_b0_21()" },
+ { 0xb0, 0x22, "sys_b0_22()" },
+ { 0xb0, 0x23, "sys_b0_23()" },
+ { 0xb0, 0x24, "sys_b0_24()" },
+ { 0xb0, 0x25, "sys_b0_25()" },
+ { 0xb0, 0x26, "sys_b0_26()" },
+ { 0xb0, 0x27, "sys_b0_27()" },
+ { 0xb0, 0x28, "sys_b0_28()" },
+ { 0xb0, 0x29, "sys_b0_29()" },
+ { 0xb0, 0x2a, "sys_b0_2a()" },
+ { 0xb0, 0x2b, "sys_b0_2b()" },
+ { 0xb0, 0x2c, "sys_b0_2c()" },
+ { 0xb0, 0x2d, "sys_b0_2d()" },
+ { 0xb0, 0x2e, "sys_b0_2e()" },
+ { 0xb0, 0x2f, "sys_b0_2f()" },
+ { 0xb0, 0x2f, "sys_b0_30()" },
+ { 0xb0, 0x31, "sys_b0_31()" },
+ { 0xb0, 0x32, "int open(const char *name, int access)" },
+ { 0xb0, 0x33, "int lseek(int fd, long pos, int seektype)" },
+ { 0xb0, 0x34, "int read(int fd, void *buf, int nbytes)" },
+ { 0xb0, 0x35, "int write(int fd, void *buf, int nbytes)" },
+ { 0xb0, 0x36, "close(int fd)" },
+ { 0xb0, 0x37, "int ioctl(int fd, int cmd, int arg)" },
+ { 0xb0, 0x38, "exit(int exitcode)" },
+ { 0xb0, 0x39, "sys_b0_39()" },
+ { 0xb0, 0x3a, "char getc(int fd)" },
+ { 0xb0, 0x3b, "putc(int fd, char ch)" },
+ { 0xb0, 0x3c, "char getchar(void)" },
+ { 0xb0, 0x3d, "putchar(char ch)" },
+ { 0xb0, 0x3e, "char *gets(char *s)" },
+ { 0xb0, 0x3f, "puts(const char *s)" },
+ { 0xb0, 0x40, "int cd(const char *path)" },
+ { 0xb0, 0x41, "int format(const char *fs)" },
+ { 0xb0, 0x42, "struct DIRENTRY* firstfile(const char *name, struct DIRENTRY *dir)" },
+ { 0xb0, 0x43, "struct DIRENTRY* nextfile(struct DIRENTRY *dir)" },
+ { 0xb0, 0x44, "int rename(const char *oldname, const char *newname)" },
+ { 0xb0, 0x45, "int delete(const char *name)" },
+ { 0xb0, 0x46, "undelete()" },
+ { 0xb0, 0x47, "AddDevice()" },
+ { 0xb0, 0x48, "RemoveDevice()" },
+ { 0xb0, 0x49, "PrintInstalledDevices()" },
+ { 0xb0, 0x4a, "InitCARD()" },
+ { 0xb0, 0x4b, "StartCARD()" },
+ { 0xb0, 0x4c, "StopCARD()" },
+ { 0xb0, 0x4d, "sys_b0_4d()" },
+ { 0xb0, 0x4e, "_card_write()" },
+ { 0xb0, 0x4f, "_card_read()" },
+ { 0xb0, 0x50, "_new_card()" },
+ { 0xb0, 0x51, "void *Krom2RawAdd(int code)" },
+ { 0xb0, 0x52, "sys_b0_52()" },
+ { 0xb0, 0x53, "sys_b0_53()" },
+ { 0xb0, 0x54, "long _get_errno(void)" },
+ { 0xb0, 0x55, "long _get_error(long fd)" },
+ { 0xb0, 0x56, "GetC0Table()" },
+ { 0xb0, 0x57, "GetB0Table()" },
+ { 0xb0, 0x58, "_card_chan()" },
+ { 0xb0, 0x59, "sys_b0_59()" },
+ { 0xb0, 0x5a, "sys_b0_5a()" },
+ { 0xb0, 0x5b, "ChangeClearPAD(int, int)" },
+ { 0xb0, 0x5c, "_card_status()" },
+ { 0xb0, 0x5d, "_card_wait()" },
+ { 0xc0, 0x00, "InitRCnt()" },
+ { 0xc0, 0x01, "InitException()" },
+ { 0xc0, 0x02, "SysEnqIntRP(int index, long *queue)" },
+ { 0xc0, 0x03, "SysDeqIntRP(int index, long *queue)" },
+ { 0xc0, 0x04, "int get_free_EvCB_slot(void)" },
+ { 0xc0, 0x05, "get_free_TCB_slot()" },
+ { 0xc0, 0x06, "ExceptionHandler()" },
+ { 0xc0, 0x07, "InstallExceptionHandlers()" },
+ { 0xc0, 0x08, "SysInitMemory()" },
+ { 0xc0, 0x09, "SysInitKMem()" },
+ { 0xc0, 0x0a, "ChangeClearRCnt()" },
+ { 0xc0, 0x0b, "SystemError()" },
+ { 0xc0, 0x0c, "InitDefInt()" },
+ { 0xc0, 0x0d, "sys_c0_0d()" },
+ { 0xc0, 0x0e, "sys_c0_0e()" },
+ { 0xc0, 0x0f, "sys_c0_0f()" },
+ { 0xc0, 0x10, "sys_c0_10()" },
+ { 0xc0, 0x11, "sys_c0_11()" },
+ { 0xc0, 0x12, "InstallDevices()" },
+ { 0xc0, 0x13, "FlushStdInOutPut()" },
+ { 0xc0, 0x14, "sys_c0_14()" },
+ { 0xc0, 0x15, "_cdevinput()" },
+ { 0xc0, 0x16, "_cdevscan()" },
+ { 0xc0, 0x17, "char _circgetc(struct device_buf *circ)" },
+ { 0xc0, 0x18, "_circputc(char c, struct device_buf *circ)" },
+ { 0xc0, 0x19, "ioabort(const char *str)" },
+ { 0xc0, 0x1a, "sys_c0_1a()" },
+ { 0xc0, 0x1b, "KernelRedirect(int flag)" },
+ { 0xc0, 0x1c, "PatchA0Table()" },
+ { 0x00, 0x00, NULL }
+};
+
+UINT32 psxcpu_device::log_bioscall_parameter( int parm )
+{
+ if( parm < 4 )
+ {
+ return m_r[ 4 + parm ];
+ }
+
+ return readword( m_r[ 29 ] + ( parm * 4 ) );
+}
+
+const char *psxcpu_device::log_bioscall_string( int parm )
+{
+ int pos;
+ UINT32 address;
+ static char string[ 1024 ];
+
+ address = log_bioscall_parameter( parm );
+ if( address == 0 )
+ {
+ return "NULL";
+ }
+
+ pos = 0;
+ string[ pos++ ] = '\"';
+
+ for( ;; )
+ {
+ UINT8 c = readbyte( address );
+ if( c == 0 )
+ {
+ break;
+ }
+ else if( c == '\t' )
+ {
+ string[ pos++ ] = '\\';
+ string[ pos++ ] = 't';
+ }
+ else if( c == '\r' )
+ {
+ string[ pos++ ] = '\\';
+ string[ pos++ ] = 'r';
+ }
+ else if( c == '\n' )
+ {
+ string[ pos++ ] = '\\';
+ string[ pos++ ] = 'n';
+ }
+ else if( c < 32 || c > 127 )
+ {
+ string[ pos++ ] = '\\';
+ string[ pos++ ] = ( ( c / 64 ) % 8 ) + '0';
+ string[ pos++ ] = ( ( c / 8 ) % 8 ) + '0';
+ string[ pos++ ] = ( ( c / 1 ) % 8 ) + '0';
+ }
+ else
+ {
+ string[ pos++ ] = c;
+ }
+ address++;
+ }
+
+ string[ pos++ ] = '\"';
+ string[ pos++ ] = 0;
+
+ return string;
+}
+
+const char *psxcpu_device::log_bioscall_hex( int parm )
+{
+ static char string[ 1024 ];
+
+ sprintf( string, "0x%08x", log_bioscall_parameter( parm ) );
+
+ return string;
+}
+
+const char *psxcpu_device::log_bioscall_char( int parm )
+{
+ int c;
+ static char string[ 1024 ];
+
+ c = log_bioscall_parameter( parm );
+ if( c < 32 || c > 127 )
+ {
+ sprintf( string, "0x%02x", c );
+ }
+ else
+ {
+ sprintf( string, "'%c'", c );
+ }
+
+ return string;
+}
+
+void psxcpu_device::log_bioscall()
+{
+ int address = m_pc - 0x04;
+ if( address == 0xa0 ||
+ address == 0xb0 ||
+ address == 0xc0 )
+ {
+ char buf[ 1024 ];
+ int operation = m_r[ 9 ] & 0xff;
+ int bioscall = 0;
+
+ if( ( address == 0xa0 && operation == 0x3c ) ||
+ ( address == 0xb0 && operation == 0x3d ) )
+ {
+ putchar( log_bioscall_parameter( 0 ) );
+ }
+
+ if( ( address == 0xa0 && operation == 0x03 ) ||
+ ( address == 0xb0 && operation == 0x35 ) )
+ {
+ int fd = log_bioscall_parameter( 0 );
+ int buffer = log_bioscall_parameter( 1 );
+ int nbytes = log_bioscall_parameter( 2 );
+
+ if( fd == 1 )
+ {
+ while( nbytes > 0 )
+ {
+ UINT8 c = readbyte( buffer );
+ putchar( c );
+ nbytes--;
+ buffer++;
+ }
+ }
+ }
+
+ while( bioscalls[ bioscall ].prototype != NULL &&
+ ( bioscalls[ bioscall ].address != address ||
+ bioscalls[ bioscall ].operation != operation ) )
+ {
+ bioscall++;
+ }
+
+ if( bioscalls[ bioscall ].prototype != NULL )
+ {
+ const char *prototype = bioscalls[ bioscall ].prototype;
+ const char *parmstart = NULL;
+ int parm = 0;
+ int parmlen = -1;
+ int brackets = 0;
+ int pos = 0;
+
+ while( *( prototype ) != 0 )
+ {
+ int ch = *( prototype );
+
+ switch( ch )
+ {
+ case '(':
+ brackets++;
+ prototype++;
+ if( brackets == 1 )
+ {
+ buf[ pos++ ] = ch;
+ parmstart = prototype;
+ }
+ break;
+
+ case ')':
+ if( brackets == 1 )
+ {
+ parmlen = prototype - parmstart;
+ }
+ prototype++;
+ brackets--;
+ break;
+
+ case ',':
+ if( brackets == 1 )
+ {
+ parmlen = prototype - parmstart;
+ }
+ prototype++;
+ break;
+
+ default:
+ if( brackets == 0 )
+ {
+ buf[ pos++ ] = ch;
+ }
+ prototype++;
+ break;
+ }
+
+ if( parmlen >= 0 )
+ {
+ while( parmlen > 0 && parmstart[ 0 ] == ' ' )
+ {
+ parmstart++;
+ parmlen--;
+ }
+ while( parmlen > 0 && parmstart[ parmlen - 1 ] == ' ' )
+ {
+ parmlen--;
+ }
+
+ if( parmlen == 0 ||
+ ( parmlen == 4 && memcmp( parmstart, "void", 4 ) == 0 ) )
+ {
+ parm = -1;
+ }
+ else if( parmlen == 3 && memcmp( parmstart, "...", 3 ) == 0 )
+ {
+ if( parm > 0 )
+ {
+ UINT32 format = log_bioscall_parameter( parm - 1 );
+ const char *parmstr = NULL;
+ int percent = 0;
+
+ for( ;; )
+ {
+ UINT8 c = readbyte( format );
+ if( c == 0 )
+ {
+ break;
+ }
+ if( percent == 0 )
+ {
+ if( c == '%' )
+ {
+ percent = 1;
+ }
+ }
+ else
+ {
+ if( c == '%' )
+ {
+ percent = 0;
+ }
+ else if( c == '*' )
+ {
+ parmstr = log_bioscall_hex( parm );
+ }
+ else if( c == 's' )
+ {
+ parmstr = log_bioscall_string( parm );
+ percent = 0;
+ }
+ else if( c == 'c' )
+ {
+ parmstr = log_bioscall_char( parm );
+ percent = 0;
+ }
+ else if( c != '-' && c != '.' && c != 'l' && ( c < '0' || c > '9' ) )
+ {
+ parmstr = log_bioscall_hex( parm );
+ percent = 0;
+ }
+ }
+
+ if( parmstr != NULL )
+ {
+ if( parm > 0 )
+ {
+ buf[ pos++ ] = ',';
+ }
+ buf[ pos++ ] = ' ';
+
+ strcpy( &buf[ pos ], parmstr );
+ pos += strlen( parmstr );
+ parmstr = NULL;
+
+ parm++;
+ }
+ format++;
+ }
+ }
+ }
+ else if( parmlen > 0 )
+ {
+ const char *parmstr;
+
+ int typelen = parmlen;
+ while( typelen > 0 && parmstart[ typelen - 1 ] != ' ' && parmstart[ typelen - 1 ] != '*' )
+ {
+ typelen--;
+ }
+
+ if( typelen == 5 && memcmp( parmstart, "char ", 5 ) == 0 )
+ {
+ parmstr = log_bioscall_char( parm );
+ }
+ else if( typelen == 12 && memcmp( parmstart, "const char *", 12 ) == 0 )
+ {
+ parmstr = log_bioscall_string( parm );
+ }
+ else
+ {
+ parmstr = log_bioscall_hex( parm );
+ }
+
+ if( parm > 0 )
+ {
+ buf[ pos++ ] = ',';
+ }
+ buf[ pos++ ] = ' ';
+
+ strcpy( &buf[ pos ], parmstr );
+ pos += strlen( parmstr );
+ }
+
+ parmlen = -1;
+ parm++;
+
+ if( ch == ',' )
+ {
+ parmstart = prototype;
+ }
+ else
+ {
+ if( parm > 0 )
+ {
+ buf[ pos++ ] = ' ';
+ }
+ buf[ pos++ ] = ch;
+ }
+ }
+ }
+ buf[ pos ] = 0;
+ }
+ else
+ {
+ sprintf( buf, "unknown_%02x_%02x", address, operation );
+ }
+ logerror( "%08x: bioscall %s\n", (unsigned int)m_r[ 31 ] - 8, buf );
+ m_berr = 0;
+ }
+}
+
+void psxcpu_device::log_syscall()
+{
+ char buf[ 1024 ];
+ int operation = m_r[ 4 ];
+
+ switch( operation )
+ {
+ case 0:
+ strcpy( buf, "void Exception()" );
+ break;
+
+ case 1:
+ strcpy( buf, "void EnterCriticalSection()" );
+ break;
+
+ case 2:
+ strcpy( buf, "void ExitCriticalSection()" );
+ break;
+
+ default:
+ sprintf( buf, "unknown_%02x", operation );
+ break;
+ }
+ logerror( "%08x: syscall %s\n", (unsigned int)m_r[ 31 ] - 8, buf );
+}
+
+void psxcpu_device::update_memory_handlers()
+{
+ if( ( m_cp0r[ CP0_SR ] & SR_ISC ) != 0 )
+ {
+ m_bus_attached = 0;
+ }
+ else
+ {
+ m_bus_attached = 1;
+ }
+}
+
+void psxcpu_device::funct_mthi()
+{
+ m_multiplier_operation = MULTIPLIER_OPERATION_IDLE;
+ m_hi = m_r[ INS_RS( m_op ) ];
+}
+
+void psxcpu_device::funct_mtlo()
+{
+ m_multiplier_operation = MULTIPLIER_OPERATION_IDLE;
+ m_lo = m_r[ INS_RS( m_op ) ];
+}
+
+void psxcpu_device::funct_mult()
+{
+ m_multiplier_operation = MULTIPLIER_OPERATION_MULT;
+ m_multiplier_operand1 = m_r[ INS_RS( m_op ) ];
+ m_multiplier_operand2 = m_r[ INS_RT( m_op ) ];
+ m_lo = m_multiplier_operand1;
+}
+
+void psxcpu_device::funct_multu()
+{
+ m_multiplier_operation = MULTIPLIER_OPERATION_MULTU;
+ m_multiplier_operand1 = m_r[ INS_RS( m_op ) ];
+ m_multiplier_operand2 = m_r[ INS_RT( m_op ) ];
+ m_lo = m_multiplier_operand1;
+}
+
+void psxcpu_device::funct_div()
+{
+ m_multiplier_operation = MULTIPLIER_OPERATION_DIV;
+ m_multiplier_operand1 = m_r[ INS_RS( m_op ) ];
+ m_multiplier_operand2 = m_r[ INS_RT( m_op ) ];
+ m_lo = m_multiplier_operand1;
+ m_hi = 0;
+}
+
+void psxcpu_device::funct_divu()
+{
+ m_multiplier_operation = MULTIPLIER_OPERATION_DIVU;
+ m_multiplier_operand1 = m_r[ INS_RS( m_op ) ];
+ m_multiplier_operand2 = m_r[ INS_RT( m_op ) ];
+ m_lo = m_multiplier_operand1;
+ m_hi = 0;
+}
+
+void psxcpu_device::multiplier_update()
+{
+ switch( m_multiplier_operation )
+ {
+ case MULTIPLIER_OPERATION_MULT:
+ {
+ INT64 result = mul_32x32( (INT32)m_multiplier_operand1, (INT32)m_multiplier_operand2 );
+ m_lo = EXTRACT_64LO( result );
+ m_hi = EXTRACT_64HI( result );
+ }
+ break;
+
+ case MULTIPLIER_OPERATION_MULTU:
+ {
+ UINT64 result = mulu_32x32( m_multiplier_operand1, m_multiplier_operand2 );
+ m_lo = EXTRACT_64LO( result );
+ m_hi = EXTRACT_64HI( result );
+ }
+ break;
+
+ case MULTIPLIER_OPERATION_DIV:
+ if( m_multiplier_operand2 != 0 )
+ {
+ m_lo = (INT32)m_multiplier_operand1 / (INT32)m_multiplier_operand2;
+ m_hi = (INT32)m_multiplier_operand1 % (INT32)m_multiplier_operand2;
+ }
+ else
+ {
+ if( (INT32)m_multiplier_operand1 < 0 )
+ {
+ m_lo = 1;
+ }
+ else
+ {
+ m_lo = 0xffffffff;
+ }
+
+ m_hi = m_multiplier_operand1;
+ }
+ break;
+
+ case MULTIPLIER_OPERATION_DIVU:
+ if( m_multiplier_operand2 != 0 )
+ {
+ m_lo = m_multiplier_operand1 / m_multiplier_operand2;
+ m_hi = m_multiplier_operand1 % m_multiplier_operand2;
+ }
+ else
+ {
+ m_lo = 0xffffffff;
+ m_hi = m_multiplier_operand1;
+ }
+ break;
+ }
+
+ m_multiplier_operation = MULTIPLIER_OPERATION_IDLE;
+}
+
+UINT32 psxcpu_device::get_hi()
+{
+ if( m_multiplier_operation != MULTIPLIER_OPERATION_IDLE )
+ {
+ multiplier_update();
+ }
+
+ return m_hi;
+}
+
+UINT32 psxcpu_device::get_lo()
+{
+ if( m_multiplier_operation != MULTIPLIER_OPERATION_IDLE )
+ {
+ multiplier_update();
+ }
+
+ return m_lo;
+}
+
+int psxcpu_device::execute_unstoppable_instructions( int executeCop2 )
+{
+ switch( INS_OP( m_op ) )
+ {
+ case OP_SPECIAL:
+ switch( INS_FUNCT( m_op ) )
+ {
+ case FUNCT_MTHI:
+ funct_mthi();
+ break;
+
+ case FUNCT_MTLO:
+ funct_mtlo();
+ break;
+
+ case FUNCT_MULT:
+ funct_mult();
+ break;
+
+ case FUNCT_MULTU:
+ funct_multu();
+ break;
+
+ case FUNCT_DIV:
+ funct_div();
+ break;
+
+ case FUNCT_DIVU:
+ funct_divu();
+ break;
+ }
+ break;
+
+ case OP_COP2:
+ if( executeCop2 )
+ {
+ switch( INS_CO( m_op ) )
+ {
+ case 1:
+ if( ( m_cp0r[ CP0_SR ] & SR_CU2 ) == 0 )
+ {
+ return 0;
+ }
+
+ if( !m_gte.docop2( m_pc, INS_COFUN( m_op ) ) )
+ {
+ stop();
+ }
+ break;
+ }
+ }
+ }
+
+ return 1;
+}
+
+void psxcpu_device::update_address_masks()
+{
+ if( ( m_cp0r[ CP0_SR ] & SR_KUC ) != 0 )
+ {
+ m_bad_byte_address_mask = 0x80000000;
+ m_bad_half_address_mask = 0x80000001;
+ m_bad_word_address_mask = 0x80000003;
+ }
+ else
+ {
+ m_bad_byte_address_mask = 0;
+ m_bad_half_address_mask = 1;
+ m_bad_word_address_mask = 3;
+ }
+}
+
+void psxcpu_device::update_scratchpad()
+{
+ if( ( m_biu & BIU_RAM ) == 0 )
+ {
+ m_program->install_readwrite_handler( 0x1f800000, 0x1f8003ff, read32_delegate( FUNC(psxcpu_device::berr_r), this ), write32_delegate( FUNC(psxcpu_device::berr_w), this ) );
+ }
+ else if( ( m_biu & BIU_DS ) == 0 )
+ {
+ m_program->install_read_handler( 0x1f800000, 0x1f8003ff, read32_delegate( FUNC(psxcpu_device::berr_r), this ) );
+ m_program->nop_write( 0x1f800000, 0x1f8003ff);
+ }
+ else
+ {
+ m_program->install_ram( 0x1f800000, 0x1f8003ff, m_dcache );
+ }
+}
+
+void psxcpu_device::update_cop0( int reg )
+{
+ if( reg == CP0_SR )
+ {
+ update_memory_handlers();
+ update_address_masks();
+ }
+
+ if( ( reg == CP0_SR || reg == CP0_CAUSE ) &&
+ ( m_cp0r[ CP0_SR ] & SR_IEC ) != 0 &&
+ ( m_cp0r[ CP0_SR ] & m_cp0r[ CP0_CAUSE ] & CAUSE_IP ) != 0 )
+ {
+ m_op = m_direct->read_decrypted_dword( m_pc );
+ execute_unstoppable_instructions( 1 );
+ exception( EXC_INT );
+ }
+ else if( reg == CP0_SR &&
+ m_delayr != PSXCPU_DELAYR_PC &&
+ ( m_pc & m_bad_word_address_mask ) != 0 )
+ {
+ load_bad_address( m_pc );
+ }
+}
+
+void psxcpu_device::commit_delayed_load()
+{
+ if( m_delayr != 0 )
+ {
+ m_r[ m_delayr ] = m_delayv;
+ m_delayr = 0;
+ m_delayv = 0;
+ }
+}
+
+void psxcpu_device::set_pc( unsigned pc )
+{
+ m_pc = pc;
+}
+
+void psxcpu_device::fetch_next_op()
+{
+ if( m_delayr == PSXCPU_DELAYR_PC )
+ {
+ UINT32 safepc = m_delayv & ~m_bad_word_address_mask;
+
+ m_op = m_direct->read_decrypted_dword( safepc );
+ }
+ else
+ {
+ m_op = m_direct->read_decrypted_dword( m_pc + 4 );
+ }
+}
+
+int psxcpu_device::advance_pc()
+{
+ if( m_delayr == PSXCPU_DELAYR_PC )
+ {
+ m_pc = m_delayv;
+ m_delayr = 0;
+ m_delayv = 0;
+
+ if( ( m_pc & m_bad_word_address_mask ) != 0 )
+ {
+ load_bad_address( m_pc );
+ return 0;
+ }
+ }
+ else if( m_delayr == PSXCPU_DELAYR_NOTPC )
+ {
+ m_delayr = 0;
+ m_delayv = 0;
+ m_pc += 4;
+ }
+ else
+ {
+ commit_delayed_load();
+ m_pc += 4;
+ }
+
+ return 1;
+}
+
+void psxcpu_device::load( UINT32 reg, UINT32 value )
+{
+ advance_pc();
+
+ if( reg != 0 )
+ {
+ m_r[ reg ] = value;
+ }
+}
+
+void psxcpu_device::delayed_load( UINT32 reg, UINT32 value )
+{
+ advance_pc();
+
+ m_delayr = reg;
+ m_delayv = value;
+}
+
+void psxcpu_device::branch( UINT32 address )
+{
+ advance_pc();
+
+ m_delayr = PSXCPU_DELAYR_PC;
+ m_delayv = address;
+}
+
+void psxcpu_device::conditional_branch( int takeBranch )
+{
+ advance_pc();
+
+ if( takeBranch )
+ {
+ m_delayr = PSXCPU_DELAYR_PC;
+ m_delayv = m_pc + ( PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) ) << 2 );
+ }
+ else
+ {
+ m_delayr = PSXCPU_DELAYR_NOTPC;
+ m_delayv = 0;
+ }
+}
+
+void psxcpu_device::unconditional_branch()
+{
+ advance_pc();
+
+ m_delayr = PSXCPU_DELAYR_PC;
+ m_delayv = ( m_pc & 0xf0000000 ) + ( INS_TARGET( m_op ) << 2 );
+}
+
+void psxcpu_device::common_exception( int exception, UINT32 romOffset, UINT32 ramOffset )
+{
+ int cause = ( exception << 2 ) | ( ( ( m_op >> 26 ) & 3 ) << 28 );
+
+ if( m_delayr == PSXCPU_DELAYR_PC )
+ {
+ cause |= CAUSE_BT;
+ m_cp0r[ CP0_TAR ] = m_delayv;
+ }
+ else if( m_delayr == PSXCPU_DELAYR_NOTPC )
+ {
+ m_cp0r[ CP0_TAR ] = m_pc + 4;
+ }
+ else
+ {
+ commit_delayed_load();
+ }
+
+ if( m_delayr == PSXCPU_DELAYR_PC || m_delayr == PSXCPU_DELAYR_NOTPC )
+ {
+ cause |= CAUSE_BD;
+ m_cp0r[ CP0_EPC ] = m_pc - 4;
+ }
+ else
+ {
+ m_cp0r[ CP0_EPC ] = m_pc;
+ }
+
+ if( LOG_BIOSCALL && exception != EXC_INT )
+ {
+ logerror( "%08x: Exception %d\n", m_pc, exception );
+ }
+
+ m_delayr = 0;
+ m_delayv = 0;
+ m_berr = 0;
+
+ if( m_cp0r[ CP0_SR ] & SR_BEV )
+ {
+ set_pc( romOffset );
+ }
+ else
+ {
+ set_pc( ramOffset );
+ }
+
+ m_cp0r[ CP0_SR ] = ( m_cp0r[ CP0_SR ] & ~0x3f ) | ( ( m_cp0r[ CP0_SR ] << 2 ) & 0x3f );
+ m_cp0r[ CP0_CAUSE ] = ( m_cp0r[ CP0_CAUSE ] & ~( CAUSE_EXC | CAUSE_BD | CAUSE_BT | CAUSE_CE ) ) | cause;
+ update_cop0( CP0_SR );
+}
+
+void psxcpu_device::exception( int exception )
+{
+ common_exception( exception, 0xbfc00180, 0x80000080 );
+}
+
+void psxcpu_device::breakpoint_exception()
+{
+ fetch_next_op();
+ execute_unstoppable_instructions( 1 );
+ common_exception( EXC_BP, 0xbfc00140, 0x80000040 );
+}
+
+void psxcpu_device::load_bus_error_exception()
+{
+ fetch_next_op();
+ execute_unstoppable_instructions( 0 );
+ common_exception( EXC_DBE, 0xbfc00180, 0x80000080 );
+}
+
+void psxcpu_device::store_bus_error_exception()
+{
+ fetch_next_op();
+
+ if( execute_unstoppable_instructions( 1 ) )
+ {
+ if( !advance_pc() )
+ {
+ return;
+ }
+
+ fetch_next_op();
+ execute_unstoppable_instructions( 0 );
+ }
+
+ common_exception( EXC_DBE, 0xbfc00180, 0x80000080 );
+}
+
+void psxcpu_device::load_bad_address( UINT32 address )
+{
+ m_cp0r[ CP0_BADA ] = address;
+ exception( EXC_ADEL );
+}
+
+void psxcpu_device::store_bad_address( UINT32 address )
+{
+ m_cp0r[ CP0_BADA ] = address;
+ exception( EXC_ADES );
+}
+
+int psxcpu_device::data_address_breakpoint( int dcic_rw, int dcic_status, UINT32 address )
+{
+ if( address < 0x1f000000 || address > 0x1fffffff )
+ {
+ if( ( m_cp0r[ CP0_DCIC ] & DCIC_DE ) != 0 &&
+ ( ( ( m_cp0r[ CP0_DCIC ] & DCIC_KD ) != 0 && ( m_cp0r[ CP0_SR ] & SR_KUC ) == 0 ) ||
+ ( ( m_cp0r[ CP0_DCIC ] & DCIC_UD ) != 0 && ( m_cp0r[ CP0_SR ] & SR_KUC ) != 0 ) ) )
+ {
+ if( ( m_cp0r[ CP0_DCIC ] & dcic_rw ) == dcic_rw &&
+ ( address & m_cp0r[ CP0_BDAM ] ) == ( m_cp0r[ CP0_BDA ] & m_cp0r[ CP0_BDAM ] ) )
+ {
+ m_cp0r[ CP0_DCIC ] = ( m_cp0r[ CP0_DCIC ] & ~DCIC_STATUS ) | dcic_status;
+
+ if( ( m_cp0r[ CP0_DCIC ] & DCIC_TR ) != 0 )
+ {
+ return 1;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+int psxcpu_device::load_data_address_breakpoint( UINT32 address )
+{
+ return data_address_breakpoint( DCIC_DR | DCIC_DAE, DCIC_DB | DCIC_DA | DCIC_R, address );
+}
+
+int psxcpu_device::store_data_address_breakpoint( UINT32 address )
+{
+ return data_address_breakpoint( DCIC_DW | DCIC_DAE, DCIC_DB | DCIC_DA | DCIC_W, address );
+}
+
+// On-board RAM and peripherals
+static ADDRESS_MAP_START( psxcpu_internal_map, AS_PROGRAM, 32, psxcpu_device )
+ AM_RANGE(0x00800000, 0x1effffff) AM_READWRITE( berr_r, berr_w )
+ AM_RANGE(0x1f800000, 0x1f8003ff) AM_NOP /* scratchpad */
+ AM_RANGE(0x1f800400, 0x1f800fff) AM_READWRITE( berr_r, berr_w )
+ AM_RANGE(0x1f801004, 0x1f80101f) AM_RAM
+ /* 1f801014 spu delay */
+ /* 1f801018 dv delay */
+ AM_RANGE(0x1f801020, 0x1f801023) AM_READWRITE_LEGACY( psx_com_delay_r, psx_com_delay_w )
+ AM_RANGE(0x1f801024, 0x1f80102f) AM_RAM
+ AM_RANGE(0x1f801040, 0x1f80105f) AM_DEVREADWRITE( "sio", psxsio_device, read, write )
+ /* 1f801060 ram config */
+ AM_RANGE(0x1f801060, 0x1f80106f) AM_RAM
+ AM_RANGE(0x1f801070, 0x1f801077) AM_DEVREADWRITE( "irq", psxirq_device, read, write )
+ AM_RANGE(0x1f801080, 0x1f8010ff) AM_DEVREADWRITE( "dma", psxdma_device, read, write )
+ AM_RANGE(0x1f801100, 0x1f80112f) AM_DEVREADWRITE( "rcnt", psxrcnt_device, read, write )
+ /* 1f801800-1f801803 cd */
+ AM_RANGE(0x1f801810, 0x1f801817) AM_READWRITE_LEGACY( psx_gpu_r, psx_gpu_w )
+ AM_RANGE(0x1f801820, 0x1f801827) AM_DEVREADWRITE( "mdec", psxmdec_device, read, write )
+ AM_RANGE(0x1f801c00, 0x1f801dff) AM_READWRITE16_LEGACY( spu_r, spu_w, 0xffffffff )
+ AM_RANGE(0x1f802020, 0x1f802033) AM_RAM /* ?? */
+ /* 1f802030 int 2000 */
+ /* 1f802040 dip switches */
+ AM_RANGE(0x1f802040, 0x1f802043) AM_WRITENOP
+ AM_RANGE(0x20000000, 0x7fffffff) AM_READWRITE( berr_r, berr_w )
+ AM_RANGE(0x80800000, 0x9effffff) AM_READWRITE( berr_r, berr_w )
+ AM_RANGE(0xa0800000, 0xbeffffff) AM_READWRITE( berr_r, berr_w )
+ AM_RANGE(0xc0000000, 0xfffdffff) AM_READWRITE( berr_r, berr_w )
+ AM_RANGE(0xfffe0130, 0xfffe0133) AM_READWRITE( biu_r, biu_w )
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( cxd8661r_internal_map, AS_PROGRAM, 32, psxcpu_device )
+ AM_RANGE(0x01000000, 0x1effffff) AM_READWRITE( berr_r, berr_w )
+ AM_RANGE(0x1f800000, 0x1f8003ff) AM_NOP /* scratchpad */
+ AM_RANGE(0x1f800400, 0x1f800fff) AM_READWRITE( berr_r, berr_w )
+ AM_RANGE(0x1f801004, 0x1f80101f) AM_RAM
+ AM_RANGE(0x1f801020, 0x1f801023) AM_READWRITE_LEGACY( psx_com_delay_r, psx_com_delay_w )
+ AM_RANGE(0x1f801024, 0x1f80102f) AM_RAM
+ AM_RANGE(0x1f801040, 0x1f80105f) AM_DEVREADWRITE( "sio", psxsio_device, read, write )
+ AM_RANGE(0x1f801060, 0x1f80106f) AM_RAM
+ AM_RANGE(0x1f801070, 0x1f801077) AM_DEVREADWRITE( "irq", psxirq_device, read, write )
+ AM_RANGE(0x1f801080, 0x1f8010ff) AM_DEVREADWRITE( "dma", psxdma_device, read, write )
+ AM_RANGE(0x1f801100, 0x1f80112f) AM_DEVREADWRITE( "rcnt", psxrcnt_device, read, write )
+ AM_RANGE(0x1f801810, 0x1f801817) AM_READWRITE_LEGACY( psx_gpu_r, psx_gpu_w )
+ AM_RANGE(0x1f801820, 0x1f801827) AM_DEVREADWRITE( "mdec", psxmdec_device, read, write )
+ AM_RANGE(0x1f801c00, 0x1f801dff) AM_READWRITE16_LEGACY( spu_r, spu_w, 0xffffffff )
+ AM_RANGE(0x1f802020, 0x1f802033) AM_RAM /* ?? */
+ AM_RANGE(0x1f802040, 0x1f802043) AM_WRITENOP
+ AM_RANGE(0x20000000, 0x7fffffff) AM_READWRITE( berr_r, berr_w )
+ AM_RANGE(0x81000000, 0x9effffff) AM_READWRITE( berr_r, berr_w )
+ AM_RANGE(0xa1000000, 0xbeffffff) AM_READWRITE( berr_r, berr_w )
+ AM_RANGE(0xc0000000, 0xfffdffff) AM_READWRITE( berr_r, berr_w )
+ AM_RANGE(0xfffe0130, 0xfffe0133) AM_READWRITE( biu_r, biu_w )
+ADDRESS_MAP_END
+
+
+//**************************************************************************
+// DEVICE INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// psxcpu_device - constructor
+//-------------------------------------------------
+
+psxcpu_device::psxcpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, address_map_constructor internal_map)
+ : cpu_device(mconfig, type, name, tag, owner, clock),
+ m_program_config("program", ENDIANNESS_LITTLE, 32, 32, 0, internal_map)
+{
+}
+
+cxd8530aq_device::cxd8530aq_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : psxcpu_device(mconfig, CXD8661R, "CXD8530AQ", tag, owner, clock, ADDRESS_MAP_NAME(psxcpu_internal_map))
+{
+}
+
+cxd8530bq_device::cxd8530bq_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : psxcpu_device(mconfig, CXD8661R, "CXD8530BQ", tag, owner, clock, ADDRESS_MAP_NAME(psxcpu_internal_map))
+{
+}
+
+cxd8530cq_device::cxd8530cq_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : psxcpu_device(mconfig, CXD8661R, "CXD8530CQ", tag, owner, clock, ADDRESS_MAP_NAME(psxcpu_internal_map))
+{
+}
+
+cxd8661r_device::cxd8661r_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : psxcpu_device(mconfig, CXD8661R, "CXD8661R", tag, owner, clock, ADDRESS_MAP_NAME(cxd8661r_internal_map))
+{
+}
+
+cxd8606bq_device::cxd8606bq_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : psxcpu_device(mconfig, CXD8606BQ, "CXD8606BQ", tag, owner, clock, ADDRESS_MAP_NAME(cxd8661r_internal_map))
+{
+}
+
+cxd8606cq_device::cxd8606cq_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : psxcpu_device(mconfig, CXD8606CQ, "CXD8606CQ", tag, owner, clock, ADDRESS_MAP_NAME(cxd8661r_internal_map))
+{
+}
+
+//-------------------------------------------------
+// device_start - start up the device
+//-------------------------------------------------
+
+void psxcpu_device::device_start()
+{
+ // get our address spaces
+ m_program = space(AS_PROGRAM);
+ m_direct = &m_program->direct();
+
+ save_item( NAME(m_op) );
+ save_item( NAME(m_pc) );
+ save_item( NAME(m_delayv) );
+ save_item( NAME(m_delayr) );
+ save_item( NAME(m_hi) );
+ save_item( NAME(m_lo) );
+ save_item( NAME(m_biu) );
+ save_item( NAME(m_r) );
+ save_item( NAME(m_cp0r) );
+ save_item( NAME(m_gte.m_cp2cr) );
+ save_item( NAME(m_gte.m_cp2dr) );
+ save_item( NAME(m_icacheTag) );
+ save_item( NAME(m_icache) );
+ save_item( NAME(m_dcache) );
+ save_item( NAME(m_multiplier_operation) );
+ save_item( NAME(m_multiplier_operand1) );
+ save_item( NAME(m_multiplier_operand2) );
+
+ state_add( STATE_GENPC, "GENPC", m_pc ).noshow();
+ state_add( PSXCPU_PC, "pc", m_pc );
+ state_add( PSXCPU_DELAYR, "delayr", m_delayr ).formatstr("%8s");
+ state_add( PSXCPU_DELAYV, "delayv", m_delayv );
+ state_add( PSXCPU_HI, "hi", m_hi );
+ state_add( PSXCPU_LO, "lo", m_lo );
+ state_add( PSXCPU_BIU, "biu", m_biu );
+ state_add( PSXCPU_R0, "zero", m_r[ 0 ] );
+ state_add( PSXCPU_R1, "at", m_r[ 1 ] );
+ state_add( PSXCPU_R2, "v0", m_r[ 2 ] );
+ state_add( PSXCPU_R3, "v1", m_r[ 3 ] );
+ state_add( PSXCPU_R4, "a0", m_r[ 4 ] );
+ state_add( PSXCPU_R5, "a1", m_r[ 5 ] );
+ state_add( PSXCPU_R6, "a2", m_r[ 6 ] );
+ state_add( PSXCPU_R7, "a3", m_r[ 7 ] );
+ state_add( PSXCPU_R8, "t0", m_r[ 8 ] );
+ state_add( PSXCPU_R9, "t1", m_r[ 9 ] );
+ state_add( PSXCPU_R10, "t2", m_r[ 10 ] );
+ state_add( PSXCPU_R11, "t3", m_r[ 11 ] );
+ state_add( PSXCPU_R12, "t4", m_r[ 12 ] );
+ state_add( PSXCPU_R13, "t5", m_r[ 13 ] );
+ state_add( PSXCPU_R14, "t6", m_r[ 14 ] );
+ state_add( PSXCPU_R15, "t7", m_r[ 15 ] );
+ state_add( PSXCPU_R16, "s0", m_r[ 16 ] );
+ state_add( PSXCPU_R17, "s1", m_r[ 17 ] );
+ state_add( PSXCPU_R18, "s2", m_r[ 18 ] );
+ state_add( PSXCPU_R19, "s3", m_r[ 19 ] );
+ state_add( PSXCPU_R20, "s4", m_r[ 20 ] );
+ state_add( PSXCPU_R21, "s5", m_r[ 21 ] );
+ state_add( PSXCPU_R22, "s6", m_r[ 22 ] );
+ state_add( PSXCPU_R23, "s7", m_r[ 23 ] );
+ state_add( PSXCPU_R24, "t8", m_r[ 24 ] );
+ state_add( PSXCPU_R25, "t9", m_r[ 25 ] );
+ state_add( PSXCPU_R26, "k0", m_r[ 26 ] );
+ state_add( PSXCPU_R27, "k1", m_r[ 27 ] );
+ state_add( PSXCPU_R28, "gp", m_r[ 28 ] );
+ state_add( PSXCPU_R29, "sp", m_r[ 29 ] );
+ state_add( PSXCPU_R30, "fp", m_r[ 30 ] );
+ state_add( PSXCPU_R31, "ra", m_r[ 31 ] );
+ state_add( PSXCPU_CP0R0, "!Index", m_cp0r[ 0 ] );
+ state_add( PSXCPU_CP0R1, "!Random", m_cp0r[ 1 ] );
+ state_add( PSXCPU_CP0R2, "!EntryLo", m_cp0r[ 2 ] );
+ state_add( PSXCPU_CP0R3, "BPC", m_cp0r[ 3 ] );
+ state_add( PSXCPU_CP0R4, "!Context", m_cp0r[ 4 ] );
+ state_add( PSXCPU_CP0R5, "BDA", m_cp0r[ 5 ] );
+ state_add( PSXCPU_CP0R6, "TAR", m_cp0r[ 6 ] );
+ state_add( PSXCPU_CP0R7, "DCIC", m_cp0r[ 7 ] );
+ state_add( PSXCPU_CP0R8, "BadA", m_cp0r[ 8 ] );
+ state_add( PSXCPU_CP0R9, "BDAM", m_cp0r[ 9 ] );
+ state_add( PSXCPU_CP0R10, "!EntryHi", m_cp0r[ 10 ] );
+ state_add( PSXCPU_CP0R11, "BPCM", m_cp0r[ 11 ] );
+ state_add( PSXCPU_CP0R12, "SR", m_cp0r[ 12 ] ).callimport();
+ state_add( PSXCPU_CP0R13, "Cause", m_cp0r[ 13 ] ).callimport();
+ state_add( PSXCPU_CP0R14, "EPC", m_cp0r[ 14 ] );
+ state_add( PSXCPU_CP0R15, "PRId", m_cp0r[ 15 ] );
+ state_add( PSXCPU_CP2DR0, "vxy0", m_gte.m_cp2dr[ 0 ].d );
+ state_add( PSXCPU_CP2DR1, "vz0", m_gte.m_cp2dr[ 1 ].d );
+ state_add( PSXCPU_CP2DR2, "vxy1", m_gte.m_cp2dr[ 2 ].d );
+ state_add( PSXCPU_CP2DR3, "vz1", m_gte.m_cp2dr[ 3 ].d );
+ state_add( PSXCPU_CP2DR4, "vxy2", m_gte.m_cp2dr[ 4 ].d );
+ state_add( PSXCPU_CP2DR5, "vz2", m_gte.m_cp2dr[ 5 ].d );
+ state_add( PSXCPU_CP2DR6, "rgb", m_gte.m_cp2dr[ 6 ].d );
+ state_add( PSXCPU_CP2DR7, "otz", m_gte.m_cp2dr[ 7 ].d );
+ state_add( PSXCPU_CP2DR8, "ir0", m_gte.m_cp2dr[ 8 ].d );
+ state_add( PSXCPU_CP2DR9, "ir1", m_gte.m_cp2dr[ 9 ].d );
+ state_add( PSXCPU_CP2DR10, "ir2", m_gte.m_cp2dr[ 10 ].d );
+ state_add( PSXCPU_CP2DR11, "ir3", m_gte.m_cp2dr[ 11 ].d );
+ state_add( PSXCPU_CP2DR12, "sxy0", m_gte.m_cp2dr[ 12 ].d );
+ state_add( PSXCPU_CP2DR13, "sxy1", m_gte.m_cp2dr[ 13 ].d );
+ state_add( PSXCPU_CP2DR14, "sxy2", m_gte.m_cp2dr[ 14 ].d );
+ state_add( PSXCPU_CP2DR15, "sxyp", m_gte.m_cp2dr[ 15 ].d );
+ state_add( PSXCPU_CP2DR16, "sz0", m_gte.m_cp2dr[ 16 ].d );
+ state_add( PSXCPU_CP2DR17, "sz1", m_gte.m_cp2dr[ 17 ].d );
+ state_add( PSXCPU_CP2DR18, "sz2", m_gte.m_cp2dr[ 18 ].d );
+ state_add( PSXCPU_CP2DR19, "sz3", m_gte.m_cp2dr[ 19 ].d );
+ state_add( PSXCPU_CP2DR20, "rgb0", m_gte.m_cp2dr[ 20 ].d );
+ state_add( PSXCPU_CP2DR21, "rgb1", m_gte.m_cp2dr[ 21 ].d );
+ state_add( PSXCPU_CP2DR22, "rgb2", m_gte.m_cp2dr[ 22 ].d );
+ state_add( PSXCPU_CP2DR23, "res1", m_gte.m_cp2dr[ 23 ].d );
+ state_add( PSXCPU_CP2DR24, "mac0", m_gte.m_cp2dr[ 24 ].d );
+ state_add( PSXCPU_CP2DR25, "mac1", m_gte.m_cp2dr[ 25 ].d );
+ state_add( PSXCPU_CP2DR26, "mac2", m_gte.m_cp2dr[ 26 ].d );
+ state_add( PSXCPU_CP2DR27, "mac3", m_gte.m_cp2dr[ 27 ].d );
+ state_add( PSXCPU_CP2DR28, "irgb", m_gte.m_cp2dr[ 28 ].d );
+ state_add( PSXCPU_CP2DR29, "orgb", m_gte.m_cp2dr[ 29 ].d );
+ state_add( PSXCPU_CP2DR30, "lzcs", m_gte.m_cp2dr[ 30 ].d );
+ state_add( PSXCPU_CP2DR31, "lzcr", m_gte.m_cp2dr[ 31 ].d );
+ state_add( PSXCPU_CP2CR0, "r11r12", m_gte.m_cp2cr[ 0 ].d );
+ state_add( PSXCPU_CP2CR1, "r13r21", m_gte.m_cp2cr[ 1 ].d );
+ state_add( PSXCPU_CP2CR2, "r22r23", m_gte.m_cp2cr[ 2 ].d );
+ state_add( PSXCPU_CP2CR3, "r31r32", m_gte.m_cp2cr[ 3 ].d );
+ state_add( PSXCPU_CP2CR4, "r33", m_gte.m_cp2cr[ 4 ].d );
+ state_add( PSXCPU_CP2CR5, "trx", m_gte.m_cp2cr[ 5 ].d );
+ state_add( PSXCPU_CP2CR6, "try", m_gte.m_cp2cr[ 6 ].d );
+ state_add( PSXCPU_CP2CR7, "trz", m_gte.m_cp2cr[ 7 ].d );
+ state_add( PSXCPU_CP2CR8, "l11l12", m_gte.m_cp2cr[ 8 ].d );
+ state_add( PSXCPU_CP2CR9, "l13l21", m_gte.m_cp2cr[ 9 ].d );
+ state_add( PSXCPU_CP2CR10, "l22l23", m_gte.m_cp2cr[ 10 ].d );
+ state_add( PSXCPU_CP2CR11, "l31l32", m_gte.m_cp2cr[ 11 ].d );
+ state_add( PSXCPU_CP2CR12, "l33", m_gte.m_cp2cr[ 12 ].d );
+ state_add( PSXCPU_CP2CR13, "rbk", m_gte.m_cp2cr[ 13 ].d );
+ state_add( PSXCPU_CP2CR14, "gbk", m_gte.m_cp2cr[ 14 ].d );
+ state_add( PSXCPU_CP2CR15, "bbk", m_gte.m_cp2cr[ 15 ].d );
+ state_add( PSXCPU_CP2CR16, "lr1lr2", m_gte.m_cp2cr[ 16 ].d );
+ state_add( PSXCPU_CP2CR17, "lr31g1", m_gte.m_cp2cr[ 17 ].d );
+ state_add( PSXCPU_CP2CR18, "lg2lg3", m_gte.m_cp2cr[ 18 ].d );
+ state_add( PSXCPU_CP2CR19, "lb1lb2", m_gte.m_cp2cr[ 19 ].d );
+ state_add( PSXCPU_CP2CR20, "lb3", m_gte.m_cp2cr[ 20 ].d );
+ state_add( PSXCPU_CP2CR21, "rfc", m_gte.m_cp2cr[ 21 ].d );
+ state_add( PSXCPU_CP2CR22, "gfc", m_gte.m_cp2cr[ 22 ].d );
+ state_add( PSXCPU_CP2CR23, "bfc", m_gte.m_cp2cr[ 23 ].d );
+ state_add( PSXCPU_CP2CR24, "ofx", m_gte.m_cp2cr[ 24 ].d );
+ state_add( PSXCPU_CP2CR25, "ofy", m_gte.m_cp2cr[ 25 ].d );
+ state_add( PSXCPU_CP2CR26, "h", m_gte.m_cp2cr[ 26 ].d );
+ state_add( PSXCPU_CP2CR27, "dqa", m_gte.m_cp2cr[ 27 ].d );
+ state_add( PSXCPU_CP2CR28, "dqb", m_gte.m_cp2cr[ 28 ].d );
+ state_add( PSXCPU_CP2CR29, "zsf3", m_gte.m_cp2cr[ 29 ].d );
+ state_add( PSXCPU_CP2CR30, "zsf4", m_gte.m_cp2cr[ 30 ].d );
+ state_add( PSXCPU_CP2CR31, "flag", m_gte.m_cp2cr[ 31 ].d );
+
+ // set our instruction counter
+ m_icountptr = &m_icount;
+}
+
+
+//-------------------------------------------------
+// device_reset - reset the device
+//-------------------------------------------------
+
+void psxcpu_device::device_reset()
+{
+ m_delayr = 0;
+ m_delayv = 0;
+ m_berr = 0;
+
+ m_multiplier_operation = MULTIPLIER_OPERATION_IDLE;
+
+ m_r[ 0 ] = 0;
+
+ m_cp0r[ CP0_SR ] = SR_BEV;
+ m_cp0r[ CP0_CAUSE ] = 0x00000000;
+ m_cp0r[ CP0_PRID ] = 0x00000002;
+ m_cp0r[ CP0_DCIC ] = 0x00000000;
+ m_cp0r[ CP0_BPCM ] = 0xffffffff;
+ m_cp0r[ CP0_BDAM ] = 0xffffffff;
+
+ update_memory_handlers();
+ update_address_masks();
+ update_scratchpad();
+
+ set_pc( 0xbfc00000 );
+}
+
+
+//-------------------------------------------------
+// device_post_load - device-specific post-load
+//-------------------------------------------------
+
+void psxcpu_device::device_post_load()
+{
+ update_memory_handlers();
+ update_address_masks();
+ update_scratchpad();
+}
+
+
+//-------------------------------------------------
+// state_import - import state into the device,
+// after it has been set
+//-------------------------------------------------
+
+void psxcpu_device::state_import(const device_state_entry &entry)
+{
+ switch (entry.index())
+ {
+ case PSXCPU_CP0R12:
+ case PSXCPU_CP0R13:
+ update_cop0( entry.index() - PSXCPU_CP0R0 );
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// state_string_export - export state as a string
+// for the debugger
+//-------------------------------------------------
+
+void psxcpu_device::state_string_export(const device_state_entry &entry, astring &string)
+{
+ switch (entry.index())
+ {
+ case PSXCPU_DELAYR:
+ if( m_delayr <= PSXCPU_DELAYR_NOTPC )
+ {
+ string.printf( "%02x %-3s", m_delayr, delayn[ m_delayr ] );
+ }
+ else
+ {
+ string.printf( "%02x ---", m_delayr );
+ }
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// disasm_disassemble - call the disassembly
+// helper function
+//-------------------------------------------------
+
+offs_t psxcpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+{
+ DasmPSXCPU_state state;
+
+ state.pc = m_pc;
+ state.delayr = m_delayr;
+ state.delayv = m_delayv;
+ memcpy( state.r, m_r, sizeof( state.r ) );
+
+ return DasmPSXCPU( &state, buffer, pc, opram );
+}
+
+
+UINT32 psxcpu_device::get_register_from_pipeline( int reg )
+{
+ if( m_delayr == reg )
+ {
+ UINT32 data = m_delayv;
+
+ m_delayr = 0;
+ m_delayv = 0;
+
+ return data;
+ }
+
+ return m_r[ reg ];
+}
+
+int psxcpu_device::cop0_usable()
+{
+ if( ( m_cp0r[ CP0_SR ] & SR_KUC ) != 0 && ( m_cp0r[ CP0_SR ] & SR_CU0 ) == 0 )
+ {
+ exception( EXC_CPU );
+
+ return 0;
+ }
+
+ return 1;
+}
+
+void psxcpu_device::lwc( int cop, int sr_cu )
+{
+ UINT32 address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int breakpoint = load_data_address_breakpoint( address );
+
+ if( ( m_cp0r[ CP0_SR ] & sr_cu ) == 0 )
+ {
+ exception( EXC_CPU );
+ }
+ else if( ( address & m_bad_word_address_mask ) != 0 )
+ {
+ load_bad_address( address );
+ }
+ else if( breakpoint )
+ {
+ breakpoint_exception();
+ }
+ else
+ {
+ UINT32 data = readword( address );
+
+ if( m_berr )
+ {
+ load_bus_error_exception();
+ }
+ else
+ {
+ int reg = INS_RT( m_op );
+
+ advance_pc();
+
+ switch( cop )
+ {
+ case 0:
+ /* lwc0 doesn't update any cop0 registers */
+ break;
+
+ case 1:
+ setcp1dr( reg, data );
+ break;
+
+ case 2:
+ m_gte.setcp2dr( m_pc, reg, data );
+ break;
+
+ case 3:
+ setcp3dr( reg, data );
+ break;
+ }
+ }
+ }
+}
+
+void psxcpu_device::swc( int cop, int sr_cu )
+{
+ UINT32 address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int breakpoint = store_data_address_breakpoint( address );
+
+ if( ( m_cp0r[ CP0_SR ] & sr_cu ) == 0 )
+ {
+ exception( EXC_CPU );
+ }
+ else if( ( address & m_bad_word_address_mask ) != 0 )
+ {
+ store_bad_address( address );
+ }
+ else
+ {
+ UINT32 data = 0;
+
+ switch( cop )
+ {
+ case 0:
+ {
+ int address;
+
+ if( m_delayr == PSXCPU_DELAYR_PC )
+ {
+ switch( m_delayv & 0x0c )
+ {
+ case 0x0c:
+ address = m_delayv;
+ break;
+
+ default:
+ address = m_delayv + 4;
+ break;
+ }
+ }
+ else
+ {
+ switch( m_pc & 0x0c )
+ {
+ case 0x0:
+ case 0xc:
+ address = m_pc + 0x08;
+ break;
+
+ default:
+ address = m_pc | 0x0c;
+ break;
+ }
+ }
+
+ data = m_program->read_dword( address );
+ }
+ break;
+
+ case 1:
+ data = getcp1dr( INS_RT( m_op ) );
+ break;
+
+ case 2:
+ data = m_gte.getcp2dr( m_pc, INS_RT( m_op ) );
+ break;
+
+ case 3:
+ data = getcp3dr( INS_RT( m_op ) );
+ break;
+ }
+
+ writeword( address, data );
+
+ if( breakpoint )
+ {
+ breakpoint_exception();
+ }
+ else if( m_berr )
+ {
+ store_bus_error_exception();
+ }
+ else
+ {
+ advance_pc();
+ }
+ }
+}
+
+void psxcpu_device::bc( int cop, int sr_cu, int condition )
+{
+ if( ( m_cp0r[ CP0_SR ] & sr_cu ) == 0 )
+ {
+ exception( EXC_CPU );
+ }
+ else
+ {
+ conditional_branch( !condition );
+ }
+}
+
+
+
+/***************************************************************************
+ CORE EXECUTION LOOP
+***************************************************************************/
+
+
+void psxcpu_device::execute_set_input(int inputnum, int state)
+{
+ UINT32 ip;
+
+ switch( inputnum )
+ {
+ case PSXCPU_IRQ0:
+ ip = CAUSE_IP2;
+ break;
+
+ case PSXCPU_IRQ1:
+ ip = CAUSE_IP3;
+ break;
+
+ case PSXCPU_IRQ2:
+ ip = CAUSE_IP4;
+ break;
+
+ case PSXCPU_IRQ3:
+ ip = CAUSE_IP5;
+ break;
+
+ case PSXCPU_IRQ4:
+ ip = CAUSE_IP6;
+ break;
+
+ case PSXCPU_IRQ5:
+ ip = CAUSE_IP7;
+ break;
+
+ default:
+ return;
+ }
+
+ switch( state )
+ {
+ case CLEAR_LINE:
+ m_cp0r[ CP0_CAUSE ] &= ~ip;
+ break;
+
+ case ASSERT_LINE:
+ m_cp0r[ CP0_CAUSE ] |= ip;
+ break;
+ }
+
+ update_cop0( CP0_CAUSE );
+}
+
+
+void psxcpu_device::execute_run()
+{
+ do
+ {
+ if (LOG_BIOSCALL) log_bioscall();
+ debugger_instruction_hook( this, m_pc );
+
+ m_op = m_direct->read_decrypted_dword( m_pc );
+ switch( INS_OP( m_op ) )
+ {
+ case OP_SPECIAL:
+ switch( INS_FUNCT( m_op ) )
+ {
+ case FUNCT_SLL:
+ load( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] << INS_SHAMT( m_op ) );
+ break;
+
+ case FUNCT_SRL:
+ load( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] >> INS_SHAMT( m_op ) );
+ break;
+
+ case FUNCT_SRA:
+ load( INS_RD( m_op ), (INT32)m_r[ INS_RT( m_op ) ] >> INS_SHAMT( m_op ) );
+ break;
+
+ case FUNCT_SLLV:
+ load( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] << ( m_r[ INS_RS( m_op ) ] & 31 ) );
+ break;
+
+ case FUNCT_SRLV:
+ load( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] >> ( m_r[ INS_RS( m_op ) ] & 31 ) );
+ break;
+
+ case FUNCT_SRAV:
+ load( INS_RD( m_op ), (INT32)m_r[ INS_RT( m_op ) ] >> ( m_r[ INS_RS( m_op ) ] & 31 ) );
+ break;
+
+ case FUNCT_JR:
+ branch( m_r[ INS_RS( m_op ) ] );
+ break;
+
+ case FUNCT_JALR:
+ branch( m_r[ INS_RS( m_op ) ] );
+ if( INS_RD( m_op ) != 0 )
+ {
+ m_r[ INS_RD( m_op ) ] = m_pc + 4;
+ }
+ break;
+
+ case FUNCT_SYSCALL:
+ if (LOG_BIOSCALL) log_syscall();
+ exception( EXC_SYS );
+ break;
+
+ case FUNCT_BREAK:
+ exception( EXC_BP );
+ break;
+
+ case FUNCT_MFHI:
+ load( INS_RD( m_op ), get_hi() );
+ break;
+
+ case FUNCT_MTHI:
+ funct_mthi();
+ advance_pc();
+ break;
+
+ case FUNCT_MFLO:
+ load( INS_RD( m_op ), get_lo() );
+ break;
+
+ case FUNCT_MTLO:
+ funct_mtlo();
+ advance_pc();
+ break;
+
+ case FUNCT_MULT:
+ funct_mult();
+ advance_pc();
+ break;
+
+ case FUNCT_MULTU:
+ funct_multu();
+ advance_pc();
+ break;
+
+ case FUNCT_DIV:
+ funct_div();
+ advance_pc();
+ break;
+
+ case FUNCT_DIVU:
+ funct_divu();
+ advance_pc();
+ break;
+
+ case FUNCT_ADD:
+ {
+ UINT32 result = m_r[ INS_RS( m_op ) ] + m_r[ INS_RT( m_op ) ];
+ if( (INT32)( ~( m_r[ INS_RS( m_op ) ] ^ m_r[ INS_RT( m_op ) ] ) & ( m_r[ INS_RS( m_op ) ] ^ result ) ) < 0 )
+ {
+ exception( EXC_OVF );
+ }
+ else
+ {
+ load( INS_RD( m_op ), result );
+ }
+ }
+ break;
+
+ case FUNCT_ADDU:
+ load( INS_RD( m_op ), m_r[ INS_RS( m_op ) ] + m_r[ INS_RT( m_op ) ] );
+ break;
+
+ case FUNCT_SUB:
+ {
+ UINT32 result = m_r[ INS_RS( m_op ) ] - m_r[ INS_RT( m_op ) ];
+ if( (INT32)( ( m_r[ INS_RS( m_op ) ] ^ m_r[ INS_RT( m_op ) ] ) & ( m_r[ INS_RS( m_op ) ] ^ result ) ) < 0 )
+ {
+ exception( EXC_OVF );
+ }
+ else
+ {
+ load( INS_RD( m_op ), result );
+ }
+ }
+ break;
+
+ case FUNCT_SUBU:
+ load( INS_RD( m_op ), m_r[ INS_RS( m_op ) ] - m_r[ INS_RT( m_op ) ] );
+ break;
+
+ case FUNCT_AND:
+ load( INS_RD( m_op ), m_r[ INS_RS( m_op ) ] & m_r[ INS_RT( m_op ) ] );
+ break;
+
+ case FUNCT_OR:
+ load( INS_RD( m_op ), m_r[ INS_RS( m_op ) ] | m_r[ INS_RT( m_op ) ] );
+ break;
+
+ case FUNCT_XOR:
+ load( INS_RD( m_op ), m_r[ INS_RS( m_op ) ] ^ m_r[ INS_RT( m_op ) ] );
+ break;
+
+ case FUNCT_NOR:
+ load( INS_RD( m_op ), ~( m_r[ INS_RS( m_op ) ] | m_r[ INS_RT( m_op ) ] ) );
+ break;
+
+ case FUNCT_SLT:
+ load( INS_RD( m_op ), (INT32)m_r[ INS_RS( m_op ) ] < (INT32)m_r[ INS_RT( m_op ) ] );
+ break;
+
+ case FUNCT_SLTU:
+ load( INS_RD( m_op ), m_r[ INS_RS( m_op ) ] < m_r[ INS_RT( m_op ) ] );
+ break;
+
+ default:
+ exception( EXC_RI );
+ break;
+ }
+ break;
+
+ case OP_REGIMM:
+ switch( INS_RT_REGIMM( m_op ) )
+ {
+ case RT_BLTZ:
+ conditional_branch( (INT32)m_r[ INS_RS( m_op ) ] < 0 );
+
+ if( INS_RT( m_op ) == RT_BLTZAL )
+ {
+ m_r[ 31 ] = m_pc + 4;
+ }
+ break;
+
+ case RT_BGEZ:
+ conditional_branch( (INT32)m_r[ INS_RS( m_op ) ] >= 0 );
+
+ if( INS_RT( m_op ) == RT_BGEZAL )
+ {
+ m_r[ 31 ] = m_pc + 4;
+ }
+ break;
+ }
+ break;
+
+ case OP_J:
+ unconditional_branch();
+ break;
+
+ case OP_JAL:
+ unconditional_branch();
+ m_r[ 31 ] = m_pc + 4;
+ break;
+
+ case OP_BEQ:
+ conditional_branch( m_r[ INS_RS( m_op ) ] == m_r[ INS_RT( m_op ) ] );
+ break;
+
+ case OP_BNE:
+ conditional_branch( m_r[ INS_RS( m_op ) ] != m_r[ INS_RT( m_op ) ] );
+ break;
+
+ case OP_BLEZ:
+ conditional_branch( (INT32)m_r[ INS_RS( m_op ) ] < 0 || m_r[ INS_RS( m_op ) ] == m_r[ INS_RT( m_op ) ] );
+ break;
+
+ case OP_BGTZ:
+ conditional_branch( (INT32)m_r[ INS_RS( m_op ) ] >= 0 && m_r[ INS_RS( m_op ) ] != m_r[ INS_RT( m_op ) ] );
+ break;
+
+ case OP_ADDI:
+ {
+ UINT32 immediate = PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ UINT32 result = m_r[ INS_RS( m_op ) ] + immediate;
+ if( (INT32)( ~( m_r[ INS_RS( m_op ) ] ^ immediate ) & ( m_r[ INS_RS( m_op ) ] ^ result ) ) < 0 )
+ {
+ exception( EXC_OVF );
+ }
+ else
+ {
+ load( INS_RT( m_op ), result );
+ }
+ }
+ break;
+
+ case OP_ADDIU:
+ load( INS_RT( m_op ), m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) ) );
+ break;
+
+ case OP_SLTI:
+ load( INS_RT( m_op ), (INT32)m_r[ INS_RS( m_op ) ] < PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) ) );
+ break;
+
+ case OP_SLTIU:
+ load( INS_RT( m_op ), m_r[ INS_RS( m_op ) ] < (UINT32)PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) ) );
+ break;
+
+ case OP_ANDI:
+ load( INS_RT( m_op ), m_r[ INS_RS( m_op ) ] & INS_IMMEDIATE( m_op ) );
+ break;
+
+ case OP_ORI:
+ load( INS_RT( m_op ), m_r[ INS_RS( m_op ) ] | INS_IMMEDIATE( m_op ) );
+ break;
+
+ case OP_XORI:
+ load( INS_RT( m_op ), m_r[ INS_RS( m_op ) ] ^ INS_IMMEDIATE( m_op ) );
+ break;
+
+ case OP_LUI:
+ load( INS_RT( m_op ), INS_IMMEDIATE( m_op ) << 16 );
+ break;
+
+ case OP_COP0:
+ switch( INS_RS( m_op ) )
+ {
+ case RS_MFC:
+ {
+ int reg = INS_RD( m_op );
+
+ if( reg == CP0_INDEX ||
+ reg == CP0_RANDOM ||
+ reg == CP0_ENTRYLO ||
+ reg == CP0_CONTEXT ||
+ reg == CP0_ENTRYHI )
+ {
+ exception( EXC_RI );
+ }
+ else if( reg < 16 )
+ {
+ if( cop0_usable() )
+ {
+ delayed_load( INS_RT( m_op ), m_cp0r[ reg ] );
+ }
+ }
+ else
+ {
+ advance_pc();
+ }
+ }
+ break;
+
+ case RS_CFC:
+ exception( EXC_RI );
+ break;
+
+ case RS_MTC:
+ {
+ int reg = INS_RD( m_op );
+
+ if( reg == CP0_INDEX ||
+ reg == CP0_RANDOM ||
+ reg == CP0_ENTRYLO ||
+ reg == CP0_CONTEXT ||
+ reg == CP0_ENTRYHI )
+ {
+ exception( EXC_RI );
+ }
+ else if( reg < 16 )
+ {
+ if( cop0_usable() )
+ {
+ UINT32 data = ( m_cp0r[ reg ] & ~mtc0_writemask[ reg ] ) |
+ ( m_r[ INS_RT( m_op ) ] & mtc0_writemask[ reg ] );
+ advance_pc();
+
+ m_cp0r[ reg ] = data;
+ update_cop0( reg );
+ }
+ }
+ else
+ {
+ advance_pc();
+ }
+ }
+ break;
+
+ case RS_CTC:
+ exception( EXC_RI );
+ break;
+
+ case RS_BC:
+ case RS_BC_ALT:
+ switch( INS_BC( m_op ) )
+ {
+ case BC_BCF:
+ bc( 0, SR_CU0, 0 );
+ break;
+
+ case BC_BCT:
+ bc( 0, SR_CU0, 1 );
+ break;
+ }
+ break;
+
+ default:
+ switch( INS_CO( m_op ) )
+ {
+ case 1:
+ switch( INS_CF( m_op ) )
+ {
+ case CF_TLBR:
+ case CF_TLBWI:
+ case CF_TLBWR:
+ case CF_TLBP:
+ exception( EXC_RI );
+ break;
+
+ case CF_RFE:
+ if( cop0_usable() )
+ {
+ advance_pc();
+ m_cp0r[ CP0_SR ] = ( m_cp0r[ CP0_SR ] & ~0xf ) | ( ( m_cp0r[ CP0_SR ] >> 2 ) & 0xf );
+ update_cop0( CP0_SR );
+ }
+ break;
+
+ default:
+ advance_pc();
+ break;
+ }
+ break;
+
+ default:
+ advance_pc();
+ break;
+ }
+ break;
+ }
+ break;
+
+ case OP_COP1:
+ if( ( m_cp0r[ CP0_SR ] & SR_CU1 ) == 0 )
+ {
+ exception( EXC_CPU );
+ }
+ else
+ {
+ switch( INS_RS( m_op ) )
+ {
+ case RS_MFC:
+ delayed_load( INS_RT( m_op ), getcp1dr( INS_RD( m_op ) ) );
+ break;
+
+ case RS_CFC:
+ delayed_load( INS_RT( m_op ), getcp1cr( INS_RD( m_op ) ) );
+ break;
+
+ case RS_MTC:
+ setcp1dr( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] );
+ advance_pc();
+ break;
+
+ case RS_CTC:
+ setcp1cr( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] );
+ advance_pc();
+ break;
+
+ case RS_BC:
+ case RS_BC_ALT:
+ switch( INS_BC( m_op ) )
+ {
+ case BC_BCF:
+ bc( 1, SR_CU1, 0 );
+ break;
+
+ case BC_BCT:
+ bc( 1, SR_CU1, 1 );
+ break;
+ }
+ break;
+
+ default:
+ advance_pc();
+ break;
+ }
+ }
+ break;
+
+ case OP_COP2:
+ if( ( m_cp0r[ CP0_SR ] & SR_CU2 ) == 0 )
+ {
+ exception( EXC_CPU );
+ }
+ else
+ {
+ switch( INS_RS( m_op ) )
+ {
+ case RS_MFC:
+ delayed_load( INS_RT( m_op ), m_gte.getcp2dr( m_pc, INS_RD( m_op ) ) );
+ break;
+
+ case RS_CFC:
+ delayed_load( INS_RT( m_op ), m_gte.getcp2cr( m_pc, INS_RD( m_op ) ) );
+ break;
+
+ case RS_MTC:
+ m_gte.setcp2dr( m_pc, INS_RD( m_op ), m_r[ INS_RT( m_op ) ] );
+ advance_pc();
+ break;
+
+ case RS_CTC:
+ m_gte.setcp2cr( m_pc, INS_RD( m_op ), m_r[ INS_RT( m_op ) ] );
+ advance_pc();
+ break;
+
+ case RS_BC:
+ case RS_BC_ALT:
+ switch( INS_BC( m_op ) )
+ {
+ case BC_BCF:
+ bc( 2, SR_CU2, 0 );
+ break;
+
+ case BC_BCT:
+ bc( 2, SR_CU2, 1 );
+ break;
+ }
+ break;
+
+ default:
+ switch( INS_CO( m_op ) )
+ {
+ case 1:
+ if( !m_gte.docop2( m_pc, INS_COFUN( m_op ) ) )
+ {
+ stop();
+ }
+
+ advance_pc();
+ break;
+
+ default:
+ advance_pc();
+ break;
+ }
+ break;
+ }
+ }
+ break;
+
+ case OP_COP3:
+ if( ( m_cp0r[ CP0_SR ] & SR_CU3 ) == 0 )
+ {
+ exception( EXC_CPU );
+ }
+ else
+ {
+ switch( INS_RS( m_op ) )
+ {
+ case RS_MFC:
+ delayed_load( INS_RT( m_op ), getcp3dr( INS_RD( m_op ) ) );
+ break;
+
+ case RS_CFC:
+ delayed_load( INS_RT( m_op ), getcp3cr( INS_RD( m_op ) ) );
+ break;
+
+ case RS_MTC:
+ setcp3dr( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] );
+ advance_pc();
+ break;
+
+ case RS_CTC:
+ setcp3cr( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] );
+ advance_pc();
+ break;
+
+ case RS_BC:
+ case RS_BC_ALT:
+ switch( INS_BC( m_op ) )
+ {
+ case BC_BCF:
+ bc( 3, SR_CU3, 0 );
+ break;
+
+ case BC_BCT:
+ bc( 3, SR_CU3, 1 );
+ break;
+ }
+ break;
+
+ default:
+ advance_pc();
+ break;
+ }
+ }
+ break;
+
+ case OP_LB:
+ {
+ UINT32 address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int breakpoint = load_data_address_breakpoint( address );
+
+ if( ( address & m_bad_byte_address_mask ) != 0 )
+ {
+ load_bad_address( address );
+ }
+ else if( breakpoint )
+ {
+ breakpoint_exception();
+ }
+ else
+ {
+ UINT32 data = PSXCPU_BYTE_EXTEND( readbyte( address ) );
+
+ if( m_berr )
+ {
+ load_bus_error_exception();
+ }
+ else
+ {
+ delayed_load( INS_RT( m_op ), data );
+ }
+ }
+ }
+ break;
+
+ case OP_LH:
+ {
+ UINT32 address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int breakpoint = load_data_address_breakpoint( address );
+
+ if( ( address & m_bad_half_address_mask ) != 0 )
+ {
+ load_bad_address( address );
+ }
+ else if( breakpoint )
+ {
+ breakpoint_exception();
+ }
+ else
+ {
+ UINT32 data = PSXCPU_WORD_EXTEND( readhalf( address ) );
+
+ if( m_berr )
+ {
+ load_bus_error_exception();
+ }
+ else
+ {
+ delayed_load( INS_RT( m_op ), data );
+ }
+ }
+ }
+ break;
+
+ case OP_LWL:
+ {
+ UINT32 address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int load_type = address & 3;
+ int breakpoint;
+
+ address &= ~3;
+ breakpoint = load_data_address_breakpoint( address );
+
+ if( ( address & m_bad_byte_address_mask ) != 0 )
+ {
+ load_bad_address( address );
+ }
+ else if( breakpoint )
+ {
+ breakpoint_exception();
+ }
+ else
+ {
+ UINT32 data = get_register_from_pipeline( INS_RT( m_op ) );
+
+ switch( load_type )
+ {
+ case 0:
+ data = ( data & 0x00ffffff ) | ( readword_masked( address, 0x000000ff ) << 24 );
+ break;
+
+ case 1:
+ data = ( data & 0x0000ffff ) | ( readword_masked( address, 0x0000ffff ) << 16 );
+ break;
+
+ case 2:
+ data = ( data & 0x000000ff ) | ( readword_masked( address, 0x00ffffff ) << 8 );
+ break;
+
+ case 3:
+ data = readword( address );
+ break;
+ }
+
+ if( m_berr )
+ {
+ load_bus_error_exception();
+ }
+ else
+ {
+ delayed_load( INS_RT( m_op ), data );
+ }
+ }
+ }
+ break;
+
+ case OP_LW:
+ {
+ UINT32 address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int breakpoint = load_data_address_breakpoint( address );
+
+ if( ( address & m_bad_word_address_mask ) != 0 )
+ {
+ load_bad_address( address );
+ }
+ else if( breakpoint )
+ {
+ breakpoint_exception();
+ }
+ else
+ {
+ UINT32 data = readword( address );
+
+ if( m_berr )
+ {
+ load_bus_error_exception();
+ }
+ else
+ {
+ delayed_load( INS_RT( m_op ), data );
+ }
+ }
+ }
+ break;
+
+ case OP_LBU:
+ {
+ UINT32 address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int breakpoint = load_data_address_breakpoint( address );
+
+ if( ( address & m_bad_byte_address_mask ) != 0 )
+ {
+ load_bad_address( address );
+ }
+ else if( breakpoint )
+ {
+ breakpoint_exception();
+ }
+ else
+ {
+ UINT32 data = readbyte( address );
+
+ if( m_berr )
+ {
+ load_bus_error_exception();
+ }
+ else
+ {
+ delayed_load( INS_RT( m_op ), data );
+ }
+ }
+ }
+ break;
+
+ case OP_LHU:
+ {
+ UINT32 address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int breakpoint = load_data_address_breakpoint( address );
+
+ if( ( address & m_bad_half_address_mask ) != 0 )
+ {
+ load_bad_address( address );
+ }
+ else if( breakpoint )
+ {
+ breakpoint_exception();
+ }
+ else
+ {
+ UINT32 data = readhalf( address );
+
+ if( m_berr )
+ {
+ load_bus_error_exception();
+ }
+ else
+ {
+ delayed_load( INS_RT( m_op ), data );
+ }
+ }
+ }
+ break;
+
+ case OP_LWR:
+ {
+ UINT32 address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int breakpoint = load_data_address_breakpoint( address );
+
+ if( ( address & m_bad_byte_address_mask ) != 0 )
+ {
+ load_bad_address( address );
+ }
+ else if( breakpoint )
+ {
+ breakpoint_exception();
+ }
+ else
+ {
+ UINT32 data = get_register_from_pipeline( INS_RT( m_op ) );
+
+ switch( address & 3 )
+ {
+ case 0:
+ data = readword( address );
+ break;
+
+ case 1:
+ data = ( data & 0xff000000 ) | ( readword_masked( address, 0x00ffffff ) >> 8 );
+ break;
+
+ case 2:
+ data = ( data & 0xffff0000 ) | ( readword_masked( address, 0xffff0000 ) >> 16 );
+ break;
+
+ case 3:
+ data = ( data & 0xffffff00 ) | ( readword_masked( address, 0xff000000 ) >> 24 );
+ break;
+ }
+
+ if( m_berr )
+ {
+ load_bus_error_exception();
+ }
+ else
+ {
+ delayed_load( INS_RT( m_op ), data );
+ }
+ }
+ }
+ break;
+
+ case OP_SB:
+ {
+ UINT32 address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int breakpoint = store_data_address_breakpoint( address );
+
+ if( ( address & m_bad_byte_address_mask ) != 0 )
+ {
+ store_bad_address( address );
+ }
+ else
+ {
+ int shift = 8 * ( address & 3 );
+ writeword_masked( address, m_r[ INS_RT( m_op ) ] << shift, 0xff << shift );
+
+ if( breakpoint )
+ {
+ breakpoint_exception();
+ }
+ else if( m_berr )
+ {
+ store_bus_error_exception();
+ }
+ else
+ {
+ advance_pc();
+ }
+ }
+ }
+ break;
+
+ case OP_SH:
+ {
+ UINT32 address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int breakpoint = store_data_address_breakpoint( address );
+
+ if( ( address & m_bad_half_address_mask ) != 0 )
+ {
+ store_bad_address( address );
+ }
+ else
+ {
+ int shift = 8 * ( address & 2 );
+ writeword_masked( address, m_r[ INS_RT( m_op ) ] << shift, 0xffff << shift );
+
+ if( breakpoint )
+ {
+ breakpoint_exception();
+ }
+ else if( m_berr )
+ {
+ store_bus_error_exception();
+ }
+ else
+ {
+ advance_pc();
+ }
+ }
+ }
+ break;
+
+ case OP_SWL:
+ {
+ UINT32 address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int save_type = address & 3;
+ int breakpoint;
+
+ address &= ~3;
+ breakpoint = store_data_address_breakpoint( address );
+
+ if( ( address & m_bad_byte_address_mask ) != 0 )
+ {
+ store_bad_address( address );
+ }
+ else
+ {
+ switch( save_type )
+ {
+ case 0:
+ writeword_masked( address, m_r[ INS_RT( m_op ) ] >> 24, 0x000000ff );
+ break;
+
+ case 1:
+ writeword_masked( address, m_r[ INS_RT( m_op ) ] >> 16, 0x0000ffff );
+ break;
+
+ case 2:
+ writeword_masked( address, m_r[ INS_RT( m_op ) ] >> 8, 0x00ffffff );
+ break;
+
+ case 3:
+ writeword( address, m_r[ INS_RT( m_op ) ] );
+ break;
+ }
+
+ if( breakpoint )
+ {
+ breakpoint_exception();
+ }
+ else if( m_berr )
+ {
+ store_bus_error_exception();
+ }
+ else
+ {
+ advance_pc();
+ }
+ }
+ }
+ break;
+
+ case OP_SW:
+ {
+ UINT32 address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int breakpoint = store_data_address_breakpoint( address );
+
+ if( ( address & m_bad_word_address_mask ) != 0 )
+ {
+ store_bad_address( address );
+ }
+ else
+ {
+ writeword( address, m_r[ INS_RT( m_op ) ] );
+
+ if( breakpoint )
+ {
+ breakpoint_exception();
+ }
+ else if( m_berr )
+ {
+ store_bus_error_exception();
+ }
+ else
+ {
+ advance_pc();
+ }
+ }
+ }
+ break;
+
+ case OP_SWR:
+ {
+ UINT32 address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int breakpoint = store_data_address_breakpoint( address );
+
+ if( ( address & m_bad_byte_address_mask ) != 0 )
+ {
+ store_bad_address( address );
+ }
+ else
+ {
+ switch( address & 3 )
+ {
+ case 0:
+ writeword( address, m_r[ INS_RT( m_op ) ] );
+ break;
+
+ case 1:
+ writeword_masked( address, m_r[ INS_RT( m_op ) ] << 8, 0xffffff00 );
+ break;
+
+ case 2:
+ writeword_masked( address, m_r[ INS_RT( m_op ) ] << 16, 0xffff0000 );
+ break;
+
+ case 3:
+ writeword_masked( address, m_r[ INS_RT( m_op ) ] << 24, 0xff000000 );
+ break;
+ }
+
+ if( breakpoint )
+ {
+ breakpoint_exception();
+ }
+ else if( m_berr )
+ {
+ store_bus_error_exception();
+ }
+ else
+ {
+ advance_pc();
+ }
+ }
+ }
+ break;
+
+ case OP_LWC0:
+ lwc( 0, SR_CU0 );
+ break;
+
+ case OP_LWC1:
+ lwc( 1, SR_CU1 );
+ break;
+
+ case OP_LWC2:
+ lwc( 2, SR_CU2 );
+ break;
+
+ case OP_LWC3:
+ lwc( 3, SR_CU3 );
+ break;
+
+ case OP_SWC0:
+ swc( 0, SR_CU0 );
+ break;
+
+ case OP_SWC1:
+ swc( 1, SR_CU1 );
+ break;
+
+ case OP_SWC2:
+ swc( 2, SR_CU2 );
+ break;
+
+ case OP_SWC3:
+ swc( 3, SR_CU3 );
+ break;
+
+ default:
+ logerror( "%08x: unknown opcode %08x\n", m_pc, m_op );
+ stop();
+ exception( EXC_RI );
+ break;
+ }
+ m_icount--;
+ } while( m_icount > 0 );
+}
+
+UINT32 psxcpu_device::getcp1dr( int reg )
+{
+ /* if a mtc/ctc precedes then this will get the value moved (which cop1 register is irrelevant). */
+ /* if a mfc/cfc follows then it will get the same value as this one. */
+ return m_program->read_dword( m_pc + 4 );
+}
+
+void psxcpu_device::setcp1dr( int reg, UINT32 value )
+{
+}
+
+UINT32 psxcpu_device::getcp1cr( int reg )
+{
+ /* if a mtc/ctc precedes then this will get the value moved (which cop1 register is irrelevant). */
+ /* if a mfc/cfc follows then it will get the same value as this one. */
+ return m_program->read_dword( m_pc + 4 );
+}
+
+void psxcpu_device::setcp1cr( int reg, UINT32 value )
+{
+}
+
+
+UINT32 psxcpu_device::getcp3dr( int reg )
+{
+ /* if you have mtc/ctc with an mfc/cfc directly afterwards then you get the value that was moved. */
+ /* if you have an lwc with an mfc/cfc somewhere after it then you get the value that is loaded */
+ /* otherwise you get the next opcode. which register you transfer to or from is irrelevant. */
+ return m_program->read_dword( m_pc + 4 );
+}
+
+void psxcpu_device::setcp3dr( int reg, UINT32 value )
+{
+}
+
+UINT32 psxcpu_device::getcp3cr( int reg )
+{
+ /* if you have mtc/ctc with an mfc/cfc directly afterwards then you get the value that was moved. */
+ /* if you have an lwc with an mfc/cfc somewhere after it then you get the value that is loaded */
+ /* otherwise you get the next opcode. which register you transfer to or from is irrelevant. */
+ return m_program->read_dword( m_pc + 4 );
+}
+
+void psxcpu_device::setcp3cr( int reg, UINT32 value )
+{
+}
+
+psxcpu_device *psxcpu_device::getcpu( device_t &device, const char *cputag )
+{
+ if( strcmp( cputag, DEVICE_SELF ) == 0 )
+ {
+ return downcast<psxcpu_device *>( &device );
+ }
+
+ return downcast<psxcpu_device *>( device.siblingdevice( cputag ) );
+}
+
+void psxcpu_device::irq_set( device_t &device, const char *cputag, UINT32 bitmask )
+{
+ psxirq_device *irq = downcast<psxirq_device *>( getcpu( device, cputag )->subdevice("irq") );
+ irq->set( bitmask );
+}
+
+void psxcpu_device::install_sio_handler( device_t &device, const char *cputag, int n_port, psx_sio_handler p_f_sio_handler )
+{
+ psxsio_device *sio = downcast<psxsio_device *>( getcpu( device, cputag )->subdevice("sio") );
+ sio->install_handler( n_port, p_f_sio_handler );
+}
+
+void psxcpu_device::sio_input( device_t &device, const char *cputag, int n_port, int n_mask, int n_data )
+{
+ psxsio_device *sio = downcast<psxsio_device *>( getcpu( device, cputag )->subdevice("sio") );
+ sio->input( n_port, n_mask, n_data );
+}
+
+static MACHINE_CONFIG_FRAGMENT( psx )
+ MCFG_DEVICE_ADD("irq", PSX_IRQ, 0)
+ MCFG_DEVICE_ADD("dma", PSX_DMA, 0)
+
+ MCFG_DEVICE_ADD("mdec", PSX_MDEC, 0)
+ MCFG_PSX_DMA_CHANNEL_WRITE( DEVICE_SELF, 0, psx_dma_write_delegate( FUNC( psxmdec_device::dma_write ), (psxmdec_device *) device ) )
+ MCFG_PSX_DMA_CHANNEL_READ( DEVICE_SELF, 1, psx_dma_read_delegate( FUNC( psxmdec_device::dma_read ), (psxmdec_device *) device ) )
+
+ MCFG_DEVICE_ADD("rcnt", PSX_RCNT, 0)
+ MCFG_DEVICE_ADD("sio", PSX_SIO, 0)
+MACHINE_CONFIG_END
+
+//-------------------------------------------------
+// machine_config_additions - return a pointer to
+// the device's machine fragment
+//-------------------------------------------------
+
+machine_config_constructor psxcpu_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( psx );
+}
diff --git a/trunk/src/emu/cpu/psx/psx.h b/trunk/src/emu/cpu/psx/psx.h
new file mode 100644
index 00000000000..6b5e9349daf
--- /dev/null
+++ b/trunk/src/emu/cpu/psx/psx.h
@@ -0,0 +1,455 @@
+/*
+ * PlayStation CPU emulator
+ *
+ * Copyright 2003-2011 smf
+ *
+ */
+
+#pragma once
+
+#ifndef __PSXCPU_H__
+#define __PSXCPU_H__
+
+#include "gte.h"
+#include "dma.h"
+#include "sio.h"
+#include "includes/psx.h"
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// cache
+
+#define ICACHE_ENTRIES ( 0x400 )
+#define DCACHE_ENTRIES ( 0x100 )
+
+// interrupts
+
+#define PSXCPU_IRQ0 ( 0 )
+#define PSXCPU_IRQ1 ( 1 )
+#define PSXCPU_IRQ2 ( 2 )
+#define PSXCPU_IRQ3 ( 3 )
+#define PSXCPU_IRQ4 ( 4 )
+#define PSXCPU_IRQ5 ( 5 )
+
+// register enumeration
+
+enum
+{
+ PSXCPU_PC = 1,
+ PSXCPU_DELAYV, PSXCPU_DELAYR,
+ PSXCPU_HI, PSXCPU_LO,
+ PSXCPU_BIU,
+ PSXCPU_R0, PSXCPU_R1,
+ PSXCPU_R2, PSXCPU_R3,
+ PSXCPU_R4, PSXCPU_R5,
+ PSXCPU_R6, PSXCPU_R7,
+ PSXCPU_R8, PSXCPU_R9,
+ PSXCPU_R10, PSXCPU_R11,
+ PSXCPU_R12, PSXCPU_R13,
+ PSXCPU_R14, PSXCPU_R15,
+ PSXCPU_R16, PSXCPU_R17,
+ PSXCPU_R18, PSXCPU_R19,
+ PSXCPU_R20, PSXCPU_R21,
+ PSXCPU_R22, PSXCPU_R23,
+ PSXCPU_R24, PSXCPU_R25,
+ PSXCPU_R26, PSXCPU_R27,
+ PSXCPU_R28, PSXCPU_R29,
+ PSXCPU_R30, PSXCPU_R31,
+ PSXCPU_CP0R0, PSXCPU_CP0R1,
+ PSXCPU_CP0R2, PSXCPU_CP0R3,
+ PSXCPU_CP0R4, PSXCPU_CP0R5,
+ PSXCPU_CP0R6, PSXCPU_CP0R7,
+ PSXCPU_CP0R8, PSXCPU_CP0R9,
+ PSXCPU_CP0R10, PSXCPU_CP0R11,
+ PSXCPU_CP0R12, PSXCPU_CP0R13,
+ PSXCPU_CP0R14, PSXCPU_CP0R15,
+ PSXCPU_CP2DR0, PSXCPU_CP2DR1,
+ PSXCPU_CP2DR2, PSXCPU_CP2DR3,
+ PSXCPU_CP2DR4, PSXCPU_CP2DR5,
+ PSXCPU_CP2DR6, PSXCPU_CP2DR7,
+ PSXCPU_CP2DR8, PSXCPU_CP2DR9,
+ PSXCPU_CP2DR10, PSXCPU_CP2DR11,
+ PSXCPU_CP2DR12, PSXCPU_CP2DR13,
+ PSXCPU_CP2DR14, PSXCPU_CP2DR15,
+ PSXCPU_CP2DR16, PSXCPU_CP2DR17,
+ PSXCPU_CP2DR18, PSXCPU_CP2DR19,
+ PSXCPU_CP2DR20, PSXCPU_CP2DR21,
+ PSXCPU_CP2DR22, PSXCPU_CP2DR23,
+ PSXCPU_CP2DR24, PSXCPU_CP2DR25,
+ PSXCPU_CP2DR26, PSXCPU_CP2DR27,
+ PSXCPU_CP2DR28, PSXCPU_CP2DR29,
+ PSXCPU_CP2DR30, PSXCPU_CP2DR31,
+ PSXCPU_CP2CR0, PSXCPU_CP2CR1,
+ PSXCPU_CP2CR2, PSXCPU_CP2CR3,
+ PSXCPU_CP2CR4, PSXCPU_CP2CR5,
+ PSXCPU_CP2CR6, PSXCPU_CP2CR7,
+ PSXCPU_CP2CR8, PSXCPU_CP2CR9,
+ PSXCPU_CP2CR10, PSXCPU_CP2CR11,
+ PSXCPU_CP2CR12, PSXCPU_CP2CR13,
+ PSXCPU_CP2CR14, PSXCPU_CP2CR15,
+ PSXCPU_CP2CR16, PSXCPU_CP2CR17,
+ PSXCPU_CP2CR18, PSXCPU_CP2CR19,
+ PSXCPU_CP2CR20, PSXCPU_CP2CR21,
+ PSXCPU_CP2CR22, PSXCPU_CP2CR23,
+ PSXCPU_CP2CR24, PSXCPU_CP2CR25,
+ PSXCPU_CP2CR26, PSXCPU_CP2CR27,
+ PSXCPU_CP2CR28, PSXCPU_CP2CR29,
+ PSXCPU_CP2CR30, PSXCPU_CP2CR31
+};
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_PSX_DMA_CHANNEL_READ( cputag, channel, handler ) \
+ downcast<psxdma_device *>( psxcpu_device::getcpu( *owner, cputag )->subdevice("dma") )->install_read_handler( channel, handler );
+
+#define MCFG_PSX_DMA_CHANNEL_WRITE( cputag, channel, handler ) \
+ downcast<psxdma_device *>( psxcpu_device::getcpu( *owner, cputag )->subdevice("dma") )->install_write_handler( channel, handler );
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> psxcpu_device
+
+class psxcpu_device : public cpu_device
+{
+public:
+ // construction/destruction
+ psxcpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // public interfaces
+ WRITE32_MEMBER( biu_w );
+ READ32_MEMBER( biu_r );
+ WRITE32_MEMBER( berr_w );
+ READ32_MEMBER( berr_r );
+
+ static psxcpu_device *getcpu( device_t &device, const char *cputag );
+ static void install_sio_handler( device_t &device, const char *cputag, int n_port, psx_sio_handler p_f_sio_handler );
+ static void sio_input( device_t &device, const char *cputag, int n_port, int n_mask, int n_data );
+ static void irq_set( device_t &device, const char *cputag, UINT32 bitmask );
+
+protected:
+ psxcpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, address_map_constructor internal_map);
+
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_post_load();
+ machine_config_constructor device_mconfig_additions() const;
+
+ // device_execute_interface overrides
+ virtual UINT32 execute_min_cycles() const { return 1; }
+ virtual UINT32 execute_max_cycles() const { return 40; }
+ virtual UINT32 execute_input_lines() const { return 6; }
+ virtual UINT64 execute_clocks_to_cycles(UINT64 clocks) const { return ( clocks + 3 ) / 4; }
+ virtual UINT64 execute_cycles_to_clocks(UINT64 cycles) const { return cycles * 4; }
+ 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 { return (spacenum == AS_PROGRAM) ? &m_program_config : NULL; }
+
+ // 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 { return 4; }
+ virtual UINT32 disasm_max_opcode_bytes() const { return 4; }
+ virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
+
+ // CPU registers
+ UINT32 m_pc;
+ UINT32 m_r[ 32 ];
+ UINT32 m_cp0r[ 16 ];
+ UINT32 m_hi;
+ UINT32 m_lo;
+
+ // internal stuff
+ UINT32 m_op;
+
+ // memory access
+ inline UINT32 program_read(UINT32 addr);
+ inline void program_write(UINT32 addr, UINT32 data);
+ inline UINT32 opcode_read();
+
+ // address spaces
+ const address_space_config m_program_config;
+ address_space *m_program;
+ direct_read_data *m_direct;
+
+ // other internal states
+ int m_icount;
+ UINT32 m_delayv;
+ UINT32 m_delayr;
+ UINT32 m_berr;
+ UINT32 m_biu;
+ UINT32 m_icacheTag[ ICACHE_ENTRIES / 4 ];
+ UINT32 m_icache[ ICACHE_ENTRIES ];
+ UINT32 m_dcache[ DCACHE_ENTRIES ];
+ int m_multiplier_operation;
+ UINT32 m_multiplier_operand1;
+ UINT32 m_multiplier_operand2;
+ int m_bus_attached;
+ UINT32 m_bad_byte_address_mask;
+ UINT32 m_bad_half_address_mask;
+ UINT32 m_bad_word_address_mask;
+
+ void stop();
+ UINT32 cache_readword( UINT32 offset );
+ void cache_writeword( UINT32 offset, UINT32 data );
+ UINT8 readbyte( UINT32 address );
+ UINT16 readhalf( UINT32 address );
+ UINT32 readword( UINT32 address );
+ UINT32 readword_masked( UINT32 address, UINT32 mask );
+ void writeword( UINT32 address, UINT32 data );
+ void writeword_masked( UINT32 address, UINT32 data, UINT32 mask );
+ UINT32 log_bioscall_parameter( int parm );
+ const char *log_bioscall_string( int parm );
+ const char *log_bioscall_hex( int parm );
+ const char *log_bioscall_char( int parm );
+ void log_bioscall();
+ void log_syscall();
+ void update_memory_handlers();
+ void funct_mthi();
+ void funct_mtlo();
+ void funct_mult();
+ void funct_multu();
+ void funct_div();
+ void funct_divu();
+ void multiplier_update();
+ UINT32 get_hi();
+ UINT32 get_lo();
+ int execute_unstoppable_instructions( int executeCop2 );
+ void update_address_masks();
+ void update_scratchpad();
+ void update_cop0( int reg );
+ void commit_delayed_load();
+ void set_pc( unsigned pc );
+ void fetch_next_op();
+ int advance_pc();
+ void load( UINT32 reg, UINT32 value );
+ void delayed_load( UINT32 reg, UINT32 value );
+ void branch( UINT32 address );
+ void conditional_branch( int takeBranch );
+ void unconditional_branch();
+ void common_exception( int exception, UINT32 romOffset, UINT32 ramOffset );
+ void exception( int exception );
+ void breakpoint_exception();
+ void load_bus_error_exception();
+ void store_bus_error_exception();
+ void load_bad_address( UINT32 address );
+ void store_bad_address( UINT32 address );
+ int data_address_breakpoint( int dcic_rw, int dcic_status, UINT32 address );
+ int load_data_address_breakpoint( UINT32 address );
+ int store_data_address_breakpoint( UINT32 address );
+
+ UINT32 get_register_from_pipeline( int reg );
+ int cop0_usable();
+ void lwc( int cop, int sr_cu );
+ void swc( int cop, int sr_cu );
+ void bc( int cop, int sr_cu, int condition );
+
+ UINT32 getcp1dr( int reg );
+ void setcp1dr( int reg, UINT32 value );
+ UINT32 getcp1cr( int reg );
+ void setcp1cr( int reg, UINT32 value );
+ UINT32 getcp3dr( int reg );
+ void setcp3dr( int reg, UINT32 value );
+ UINT32 getcp3cr( int reg );
+ void setcp3cr( int reg, UINT32 value );
+
+ gte m_gte;
+};
+
+class cxd8530aq_device : public psxcpu_device
+{
+public:
+ // construction/destruction
+ cxd8530aq_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class cxd8530bq_device : public psxcpu_device
+{
+public:
+ // construction/destruction
+ cxd8530bq_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class cxd8530cq_device : public psxcpu_device
+{
+public:
+ // construction/destruction
+ cxd8530cq_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class cxd8661r_device : public psxcpu_device
+{
+public:
+ // construction/destruction
+ cxd8661r_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class cxd8606bq_device : public psxcpu_device
+{
+public:
+ // construction/destruction
+ cxd8606bq_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class cxd8606cq_device : public psxcpu_device
+{
+public:
+ // construction/destruction
+ cxd8606cq_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+// device type definition
+extern const device_type CXD8530AQ;
+extern const device_type CXD8530BQ;
+extern const device_type CXD8530CQ;
+extern const device_type CXD8661R;
+extern const device_type CXD8606BQ;
+extern const device_type CXD8606CQ;
+
+
+
+#define PSXCPU_DELAYR_PC ( 32 )
+#define PSXCPU_DELAYR_NOTPC ( 33 )
+
+#define PSXCPU_BYTE_EXTEND( a ) ( (INT32)(INT8)a )
+#define PSXCPU_WORD_EXTEND( a ) ( (INT32)(INT16)a )
+
+#define INS_OP( op ) ( ( op >> 26 ) & 63 )
+#define INS_RS( op ) ( ( op >> 21 ) & 31 )
+#define INS_RT( op ) ( ( op >> 16 ) & 31 )
+#define INS_IMMEDIATE( op ) ( op & 0xffff )
+#define INS_TARGET( op ) ( op & 0x3ffffff )
+#define INS_RD( op ) ( ( op >> 11 ) & 31 )
+#define INS_SHAMT( op ) ( ( op >> 6 ) & 31 )
+#define INS_FUNCT( op ) ( op & 63 )
+#define INS_CODE( op ) ( ( op >> 6 ) & 0xfffff )
+#define INS_CO( op ) ( ( op >> 25 ) & 1 )
+#define INS_COFUN( op ) ( op & 0x1ffffff )
+#define INS_CF( op ) ( op & 31 )
+#define INS_BC( op ) ( ( op >> 16 ) & 1 )
+#define INS_RT_REGIMM( op ) ( ( op >> 16 ) & 1 )
+
+#define OP_SPECIAL ( 0 )
+#define OP_REGIMM ( 1 )
+#define OP_J ( 2 )
+#define OP_JAL ( 3 )
+#define OP_BEQ ( 4 )
+#define OP_BNE ( 5 )
+#define OP_BLEZ ( 6 )
+#define OP_BGTZ ( 7 )
+#define OP_ADDI ( 8 )
+#define OP_ADDIU ( 9 )
+#define OP_SLTI ( 10 )
+#define OP_SLTIU ( 11 )
+#define OP_ANDI ( 12 )
+#define OP_ORI ( 13 )
+#define OP_XORI ( 14 )
+#define OP_LUI ( 15 )
+#define OP_COP0 ( 16 )
+#define OP_COP1 ( 17 )
+#define OP_COP2 ( 18 )
+#define OP_COP3 ( 19 )
+#define OP_LB ( 32 )
+#define OP_LH ( 33 )
+#define OP_LWL ( 34 )
+#define OP_LW ( 35 )
+#define OP_LBU ( 36 )
+#define OP_LHU ( 37 )
+#define OP_LWR ( 38 )
+#define OP_SB ( 40 )
+#define OP_SH ( 41 )
+#define OP_SWL ( 42 )
+#define OP_SW ( 43 )
+#define OP_SWR ( 46 )
+#define OP_LWC0 ( 48 )
+#define OP_LWC1 ( 49 )
+#define OP_LWC2 ( 50 )
+#define OP_LWC3 ( 51 )
+#define OP_SWC0 ( 56 )
+#define OP_SWC1 ( 57 )
+#define OP_SWC2 ( 58 )
+#define OP_SWC3 ( 59 )
+
+/* OP_SPECIAL */
+#define FUNCT_SLL ( 0 )
+#define FUNCT_SRL ( 2 )
+#define FUNCT_SRA ( 3 )
+#define FUNCT_SLLV ( 4 )
+#define FUNCT_SRLV ( 6 )
+#define FUNCT_SRAV ( 7 )
+#define FUNCT_JR ( 8 )
+#define FUNCT_JALR ( 9 )
+#define FUNCT_SYSCALL ( 12 )
+#define FUNCT_BREAK ( 13 )
+#define FUNCT_MFHI ( 16 )
+#define FUNCT_MTHI ( 17 )
+#define FUNCT_MFLO ( 18 )
+#define FUNCT_MTLO ( 19 )
+#define FUNCT_MULT ( 24 )
+#define FUNCT_MULTU ( 25 )
+#define FUNCT_DIV ( 26 )
+#define FUNCT_DIVU ( 27 )
+#define FUNCT_ADD ( 32 )
+#define FUNCT_ADDU ( 33 )
+#define FUNCT_SUB ( 34 )
+#define FUNCT_SUBU ( 35 )
+#define FUNCT_AND ( 36 )
+#define FUNCT_OR ( 37 )
+#define FUNCT_XOR ( 38 )
+#define FUNCT_NOR ( 39 )
+#define FUNCT_SLT ( 42 )
+#define FUNCT_SLTU ( 43 )
+
+/* OP_REGIMM */
+#define RT_BLTZ ( 0 )
+#define RT_BGEZ ( 1 )
+#define RT_BLTZAL ( 16 )
+#define RT_BGEZAL ( 17 )
+
+/* OP_COP0/OP_COP1/OP_COP2 */
+#define RS_MFC ( 0 )
+#define RS_CFC ( 2 )
+#define RS_MTC ( 4 )
+#define RS_CTC ( 6 )
+#define RS_BC ( 8 )
+#define RS_BC_ALT ( 12 )
+
+/* BC_BC */
+#define BC_BCF ( 0 )
+#define BC_BCT ( 1 )
+
+/* OP_COP0 */
+#define CF_TLBR ( 1 )
+#define CF_TLBWI ( 2 )
+#define CF_TLBWR ( 6 )
+#define CF_TLBP ( 8 )
+#define CF_RFE ( 16 )
+
+
+
+typedef struct _DasmPSXCPU_state DasmPSXCPU_state;
+
+struct _DasmPSXCPU_state
+{
+ UINT32 pc;
+ int delayr;
+ UINT32 delayv;
+ UINT32 r[ 32 ];
+};
+
+extern unsigned DasmPSXCPU( DasmPSXCPU_state *state, char *buffer, UINT32 pc, const UINT8 *opram );
+
+#endif /* __PSXCPU_H__ */
diff --git a/trunk/src/emu/cpu/psx/psxdasm.c b/trunk/src/emu/cpu/psx/psxdasm.c
new file mode 100644
index 00000000000..c7511ae385c
--- /dev/null
+++ b/trunk/src/emu/cpu/psx/psxdasm.c
@@ -0,0 +1,749 @@
+/*
+ * PSXCPU disassembler for the MAME project written by smf
+ *
+ */
+
+#include "emu.h"
+#include "psx.h"
+#include "gte.h"
+
+static char *make_signed_hex_str_16( UINT32 value )
+{
+ static char s_hex[ 20 ];
+
+ if( value & 0x8000 )
+ {
+ sprintf( s_hex, "-$%x", -value & 0xffff );
+ }
+ else
+ {
+ sprintf( s_hex, "$%x", value & 0xffff );
+ }
+
+ return s_hex;
+}
+
+static const char *const s_cpugenreg[] =
+{
+ "zero", "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"
+};
+
+static const char *const s_cp0genreg[] =
+{
+ "!Index", "!Random", "!EntryLo", "BPC", "!Context", "BDA", "TAR", "DCIC",
+ "BadA", "BDAM", "!EntryHi", "BPCM", "SR", "Cause", "EPC", "PRId",
+ "cp0r16", "cp0r17", "cp0r18", "cp0r19", "cp0r20", "cp0r21", "cp0r22", "cp0r23",
+ "cp0r24", "cp0r25", "cp0r26", "cp0r27", "cp0r28", "cp0r29", "cp0r30", "cp0r31"
+};
+
+static const char *const s_cp0ctlreg[] =
+{
+ "cp0cr0", "cp0cr1", "cp0cr2", "cp0cr3", "cp0cr4", "cp0cr5", "cp0cr6", "cp0cr7",
+ "cp0cr8", "cp0cr9", "cp0cr10", "cp0cr11", "cp0cr12", "cp0cr13", "cp0cr14", "cp0cr15",
+ "cp0cr16", "cp0cr17", "cp0cr18", "cp0cr19", "cp0cr20", "cp0cr21", "cp0cr22", "cp0cr23",
+ "cp0cr24", "cp0cr25", "cp0cr26", "cp0cr27", "cp0cr28", "cp0cr29", "cp0cr30", "cp0cr31"
+};
+
+static const char *const s_cp1genreg[] =
+{
+ "cp1r0", "cp1r1", "cp1r2", "cp1r3", "cp1r4", "cp1r5", "cp1r6", "cp1r7",
+ "cp1r8", "cp1r9", "cp1r10", "cp1r11", "cp1r12", "cp1r13", "cp1r14", "cp1r15",
+ "cp1r16", "cp1r17", "cp1r18", "cp1r19", "cp1r20", "cp1r21", "cp1r22", "cp1r22",
+ "cp1r23", "cp1r24", "cp1r25", "cp1r26", "cp1r27", "cp1r28", "cp1r29", "cp1r30"
+};
+
+static const char *const s_cp1ctlreg[] =
+{
+ "cp1cr0", "cp1cr1", "cp1cr2", "cp1cr3", "cp1cr4", "cp1cr5", "cp1cr6", "cp1cr7",
+ "cp1cr8", "cp1cr9", "cp1cr10", "cp1cr11", "cp1cr12", "cp1cr13", "cp1cr14", "cp1cr15",
+ "cp1cr16", "cp1cr17", "cp1cr18", "cp1cr19", "cp1cr20", "cp1cr21", "cp1cr22", "cp1cr23",
+ "cp1cr24", "cp1cr25", "cp1cr26", "cp1cr27", "cp1cr28", "cp1cr29", "cp1cr30", "cp1cr31"
+};
+
+static const char *const s_cp2genreg[] =
+{
+ "vxy0", "vz0", "vxy1", "vz1", "vxy2", "vz2", "rgb", "otz",
+ "ir0", "ir1", "ir2", "ir3", "sxy0", "sxy1", "sxy2", "sxyp",
+ "sz0", "sz1", "sz2", "sz3", "rgb0", "rgb1", "rgb2", "cp2cr23",
+ "mac0", "mac1", "mac2", "mac3", "irgb", "orgb", "lzcs", "lzcr"
+};
+
+static const char *const s_cp2ctlreg[] =
+{
+ "r11r12", "r13r21", "r22r23", "r31r32", "r33", "trx", "try", "trz",
+ "l11l12", "l13l21", "l22l23", "l31l32", "l33", "rbk", "gbk", "bbk",
+ "lr1lr2", "lr3lg1", "lg2lg3", "lb1lb2", "lb3", "rfc", "gfc", "bfc",
+ "ofx", "ofy", "h", "dqa", "dqb", "zsf3", "zsf4", "flag"
+};
+
+static const char *const s_cp3genreg[] =
+{
+ "cp3r0", "cp3r1", "cp3r2", "cp3r3", "cp3r4", "cp3r5", "cp3r6", "cp3r7",
+ "cp3r8", "cp3r9", "cp3r10", "cp3r11", "cp3r12", "cp3r13", "cp3r14", "cp3r15",
+ "cp3r16", "cp3r17", "cp3r18", "cp3r19", "cp3r20", "cp3r21", "cp3r22", "cp3r22",
+ "cp3r23", "cp3r24", "cp3r25", "cp3r26", "cp3r27", "cp3r28", "cp3r29", "cp3r30"
+};
+
+static const char *const s_cp3ctlreg[] =
+{
+ "cp3cr0", "cp3cr1", "cp3cr2", "cp3cr3", "cp3cr4", "cp3cr5", "cp3cr6", "cp3cr7",
+ "cp3cr8", "cp3cr9", "cp3cr10", "cp3cr11", "cp3cr12", "cp3cr13", "cp3cr14", "cp3cr15",
+ "cp3cr16", "cp3cr17", "cp3cr18", "cp3cr19", "cp3cr20", "cp3cr21", "cp3cr22", "cp3cr23",
+ "cp3cr24", "cp3cr25", "cp3cr26", "cp3cr27", "cp3cr28", "cp3cr29", "cp3cr30", "cp3cr31"
+};
+
+static const char *const s_gtesf[] =
+{
+ "0", "12"
+};
+
+static const char *const s_gtemx[] =
+{
+ "rm", "lm", "cm", "0"
+};
+
+static const char *const s_gtev[] =
+{
+ "v0", "v1", "v2", "ir"
+};
+
+static const char *const s_gtecv[] =
+{
+ "tr", "bk", "fc", "0"
+};
+
+static const char *const s_gtelm[] =
+{
+ "0", "1"
+};
+
+static char *effective_address( DasmPSXCPU_state *state, UINT32 pc, UINT32 op )
+{
+ static char s_address[ 20 ];
+
+ if( state != NULL && state->pc == pc )
+ {
+ sprintf( s_address, "%s(%s) ; 0x%08x", make_signed_hex_str_16( INS_IMMEDIATE( op ) ), s_cpugenreg[ INS_RS( op ) ],
+ (UINT32)( state->r[ INS_RS( op ) ] + (INT16)INS_IMMEDIATE( op ) ) );
+ return s_address;
+ }
+ sprintf( s_address, "%s(%s)", make_signed_hex_str_16( INS_IMMEDIATE( op ) ), s_cpugenreg[ INS_RS( op ) ] );
+ return s_address;
+}
+
+static UINT32 relative_address( DasmPSXCPU_state *state, UINT32 pc, UINT32 op )
+{
+ UINT32 nextpc = pc + 4;
+ if( state != NULL && state->pc == pc && state->delayr == PSXCPU_DELAYR_PC )
+ {
+ nextpc = state->delayv;
+ }
+
+ return nextpc + ( PSXCPU_WORD_EXTEND( INS_IMMEDIATE( op ) ) << 2 );
+}
+
+static UINT32 jump_address( DasmPSXCPU_state *state, UINT32 pc, UINT32 op )
+{
+ UINT32 nextpc = pc + 4;
+ if( state != NULL && state->pc == pc && state->delayr == PSXCPU_DELAYR_PC )
+ {
+ nextpc = state->delayv;
+ }
+ return ( nextpc & 0xf0000000 ) + ( INS_TARGET( op ) << 2 );
+}
+
+static UINT32 fetch_op( const UINT8 *opram )
+{
+ return ( opram[ 3 ] << 24 ) | ( opram[ 2 ] << 16 ) | ( opram[ 1 ] << 8 ) | ( opram[ 0 ] << 0 );
+}
+
+static char *upper_address( UINT32 op, const UINT8 *opram )
+{
+ static char s_address[ 20 ];
+ UINT32 nextop = fetch_op( opram );
+
+ if( INS_OP( nextop ) == OP_ORI && INS_RT( op ) == INS_RS( nextop ) )
+ {
+ sprintf( s_address, "$%04x ; 0x%08x", INS_IMMEDIATE( op ), ( INS_IMMEDIATE( op ) << 16 ) | INS_IMMEDIATE( nextop ) );
+ }
+ else if( INS_OP( nextop ) == OP_ADDIU && INS_RT( op ) == INS_RS( nextop ) )
+ {
+ sprintf( s_address, "$%04x ; 0x%08x", INS_IMMEDIATE( op ), ( INS_IMMEDIATE( op ) << 16 ) + (INT16) INS_IMMEDIATE( nextop ) );
+ }
+ else
+ {
+ sprintf( s_address, "$%04x", INS_IMMEDIATE( op ) );
+ }
+
+ return s_address;
+}
+
+unsigned DasmPSXCPU( DasmPSXCPU_state *state, char *buffer, UINT32 pc, const UINT8 *opram )
+{
+ UINT32 op;
+ const UINT8 *oldopram;
+ UINT32 flags = 0;
+
+ oldopram = opram;
+ op = fetch_op( opram );
+ opram += 4;
+
+ sprintf( buffer, "dw $%08x", op );
+
+ switch( INS_OP( op ) )
+ {
+ case OP_SPECIAL:
+ switch( INS_FUNCT( op ) )
+ {
+ case FUNCT_SLL:
+ if( op == 0 )
+ {
+ /* the standard nop is "sll zero,zero,$0000" */
+ sprintf( buffer, "nop" );
+ }
+ else
+ {
+ sprintf( buffer, "sll %s,%s,$%02x", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RT( op ) ], INS_SHAMT( op ) );
+ }
+ break;
+ case FUNCT_SRL:
+ sprintf( buffer, "srl %s,%s,$%02x", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RT( op ) ], INS_SHAMT( op ) );
+ break;
+ case FUNCT_SRA:
+ sprintf( buffer, "sra %s,%s,$%02x", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RT( op ) ], INS_SHAMT( op ) );
+ break;
+ case FUNCT_SLLV:
+ sprintf( buffer, "sllv %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RT( op ) ], s_cpugenreg[ INS_RS( op ) ] );
+ break;
+ case FUNCT_SRLV:
+ sprintf( buffer, "srlv %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RT( op ) ], s_cpugenreg[ INS_RS( op ) ] );
+ break;
+ case FUNCT_SRAV:
+ sprintf( buffer, "srav %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RT( op ) ], s_cpugenreg[ INS_RS( op ) ] );
+ break;
+ case FUNCT_JR:
+ sprintf( buffer, "jr %s", s_cpugenreg[ INS_RS( op ) ] );
+ if( INS_RS( op ) == 31 )
+ {
+ flags = DASMFLAG_STEP_OUT;
+ }
+ break;
+ case FUNCT_JALR:
+ sprintf( buffer, "jalr %s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RS( op ) ] );
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA( 1 );
+ break;
+ case FUNCT_SYSCALL:
+ sprintf( buffer, "syscall $%05x", INS_CODE( op ) );
+ flags = DASMFLAG_STEP_OVER;
+ break;
+ case FUNCT_BREAK:
+ sprintf( buffer, "break $%05x", INS_CODE( op ) );
+ flags = DASMFLAG_STEP_OVER;
+ break;
+ case FUNCT_MFHI:
+ sprintf( buffer, "mfhi %s", s_cpugenreg[ INS_RD( op ) ] );
+ break;
+ case FUNCT_MTHI:
+ sprintf( buffer, "mthi %s", s_cpugenreg[ INS_RS( op ) ] );
+ break;
+ case FUNCT_MFLO:
+ sprintf( buffer, "mflo %s", s_cpugenreg[ INS_RD( op ) ] );
+ break;
+ case FUNCT_MTLO:
+ sprintf( buffer, "mtlo %s", s_cpugenreg[ INS_RS( op ) ] );
+ break;
+ case FUNCT_MULT:
+ sprintf( buffer, "mult %s,%s", s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] );
+ break;
+ case FUNCT_MULTU:
+ sprintf( buffer, "multu %s,%s", s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] );
+ break;
+ case FUNCT_DIV:
+ sprintf( buffer, "div %s,%s", s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] );
+ break;
+ case FUNCT_DIVU:
+ sprintf( buffer, "divu %s,%s", s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] );
+ break;
+ case FUNCT_ADD:
+ sprintf( buffer, "add %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] );
+ break;
+ case FUNCT_ADDU:
+ sprintf( buffer, "addu %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] );
+ break;
+ case FUNCT_SUB:
+ sprintf( buffer, "sub %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] );
+ break;
+ case FUNCT_SUBU:
+ sprintf( buffer, "subu %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] );
+ break;
+ case FUNCT_AND:
+ sprintf( buffer, "and %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] );
+ break;
+ case FUNCT_OR:
+ sprintf( buffer, "or %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] );
+ break;
+ case FUNCT_XOR:
+ sprintf( buffer, "xor %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] );
+ break;
+ case FUNCT_NOR:
+ sprintf( buffer, "nor %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] );
+ break;
+ case FUNCT_SLT:
+ sprintf( buffer, "slt %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] );
+ break;
+ case FUNCT_SLTU:
+ sprintf( buffer, "sltu %s,%s,%s", s_cpugenreg[ INS_RD( op ) ], s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ] );
+ break;
+ }
+ break;
+ case OP_REGIMM:
+ switch( INS_RT_REGIMM( op ) )
+ {
+ case RT_BLTZ:
+ if( INS_RT( op ) == RT_BLTZAL )
+ {
+ sprintf( buffer, "bltzal %s,$%08x", s_cpugenreg[ INS_RS( op ) ], relative_address( state, pc, op ) );
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA( 1 );
+ }
+ else
+ {
+ sprintf( buffer, "bltz %s,$%08x", s_cpugenreg[ INS_RS( op ) ], relative_address( state, pc, op ) );
+ }
+ break;
+ case RT_BGEZ:
+ if( INS_RT( op ) == RT_BGEZAL )
+ {
+ sprintf( buffer, "bgezal %s,$%08x", s_cpugenreg[ INS_RS( op ) ], relative_address( state, pc, op ) );
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA( 1 );
+ }
+ else
+ {
+ sprintf( buffer, "bgez %s,$%08x", s_cpugenreg[ INS_RS( op ) ], relative_address( state, pc, op ) );
+ }
+ break;
+ }
+ break;
+ case OP_J:
+ sprintf( buffer, "j $%08x", jump_address( state, pc, op ) );
+ break;
+ case OP_JAL:
+ sprintf( buffer, "jal $%08x", jump_address( state, pc, op ) );
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA( 1 );
+ break;
+ case OP_BEQ:
+ sprintf( buffer, "beq %s,%s,$%08x", s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ], relative_address( state, pc, op ) );
+ break;
+ case OP_BNE:
+ sprintf( buffer, "bne %s,%s,$%08x", s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ], relative_address( state, pc, op ) );
+ break;
+ case OP_BLEZ:
+ sprintf( buffer, "blez %s,%s,$%08x", s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ], relative_address( state, pc, op ) );
+ break;
+ case OP_BGTZ:
+ sprintf( buffer, "bgtz %s,%s,$%08x", s_cpugenreg[ INS_RS( op ) ], s_cpugenreg[ INS_RT( op ) ], relative_address( state, pc, op ) );
+ break;
+ case OP_ADDI:
+ sprintf( buffer, "addi %s,%s,%s", s_cpugenreg[ INS_RT( op ) ], s_cpugenreg[ INS_RS( op ) ], make_signed_hex_str_16( INS_IMMEDIATE( op ) ) );
+ break;
+ case OP_ADDIU:
+ sprintf( buffer, "addiu %s,%s,%s", s_cpugenreg[ INS_RT( op ) ], s_cpugenreg[ INS_RS( op ) ], make_signed_hex_str_16( INS_IMMEDIATE( op ) ) );
+ break;
+ case OP_SLTI:
+ sprintf( buffer, "slti %s,%s,%s", s_cpugenreg[ INS_RT( op ) ], s_cpugenreg[ INS_RS( op ) ], make_signed_hex_str_16( INS_IMMEDIATE( op ) ) );
+ break;
+ case OP_SLTIU:
+ sprintf( buffer, "sltiu %s,%s,%s", s_cpugenreg[ INS_RT( op ) ], s_cpugenreg[ INS_RS( op ) ], make_signed_hex_str_16( INS_IMMEDIATE( op ) ) );
+ break;
+ case OP_ANDI:
+ sprintf( buffer, "andi %s,%s,$%04x", s_cpugenreg[ INS_RT( op ) ], s_cpugenreg[ INS_RS( op ) ], INS_IMMEDIATE( op ) );
+ break;
+ case OP_ORI:
+ sprintf( buffer, "ori %s,%s,$%04x", s_cpugenreg[ INS_RT( op ) ], s_cpugenreg[ INS_RS( op ) ], INS_IMMEDIATE( op ) );
+ break;
+ case OP_XORI:
+ sprintf( buffer, "xori %s,%s,$%04x", s_cpugenreg[ INS_RT( op ) ], s_cpugenreg[ INS_RS( op ) ], INS_IMMEDIATE( op ) );
+ break;
+ case OP_LUI:
+ sprintf( buffer, "lui %s,%s", s_cpugenreg[ INS_RT( op ) ], upper_address( op, opram ) );
+ break;
+ case OP_COP0:
+ switch( INS_RS( op ) )
+ {
+ case RS_MFC:
+ sprintf( buffer, "mfc0 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp0genreg[ INS_RD( op ) ] );
+ break;
+ case RS_CFC:
+ sprintf( buffer, "!cfc0 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp0ctlreg[ INS_RD( op ) ] );
+ break;
+ case RS_MTC:
+ sprintf( buffer, "mtc0 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp0genreg[ INS_RD( op ) ] );
+ break;
+ case RS_CTC:
+ sprintf( buffer, "!ctc0 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp0ctlreg[ INS_RD( op ) ] );
+ break;
+ case RS_BC:
+ case RS_BC_ALT:
+ switch( INS_BC( op ) )
+ {
+ case BC_BCF:
+ sprintf( buffer, "bc0f $%08x", relative_address( state, pc, op ) );
+ break;
+ case BC_BCT:
+ sprintf( buffer, "bc0t $%08x", relative_address( state, pc, op ) );
+ break;
+ }
+ break;
+ default:
+ switch( INS_CO( op ) )
+ {
+ case 1:
+ sprintf( buffer, "cop0 $%07x", INS_COFUN( op ) );
+
+ switch( INS_CF( op ) )
+ {
+ case CF_TLBR:
+ sprintf( buffer, "!tlbr" );
+ break;
+ case CF_TLBWI:
+ sprintf( buffer, "!tlbwi" );
+ break;
+ case CF_TLBWR:
+ sprintf( buffer, "!tlbwr" );
+ break;
+ case CF_TLBP:
+ sprintf( buffer, "!tlbp" );
+ break;
+ case CF_RFE:
+ sprintf( buffer, "rfe" );
+ break;
+ }
+ break;
+ }
+ break;
+ }
+ break;
+ case OP_COP1:
+ switch( INS_RS( op ) )
+ {
+ case RS_MFC:
+ sprintf( buffer, "mfc1 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp1genreg[ INS_RD( op ) ] );
+ break;
+ case RS_CFC:
+ sprintf( buffer, "cfc1 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp1ctlreg[ INS_RD( op ) ] );
+ break;
+ case RS_MTC:
+ sprintf( buffer, "mtc1 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp1genreg[ INS_RD( op ) ] );
+ break;
+ case RS_CTC:
+ sprintf( buffer, "ctc1 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp1ctlreg[ INS_RD( op ) ] );
+ break;
+ case RS_BC:
+ case RS_BC_ALT:
+ switch( INS_BC( op ) )
+ {
+ case BC_BCF:
+ sprintf( buffer, "bc1f $%08x", relative_address( state, pc, op ) );
+ break;
+ case BC_BCT:
+ sprintf( buffer, "bc1t $%08x", relative_address( state, pc, op ) );
+ break;
+ }
+ break;
+ default:
+ switch( INS_CO( op ) )
+ {
+ case 1:
+ sprintf( buffer, "cop1 $%07x", INS_COFUN( op ) );
+ break;
+ }
+ break;
+ }
+ break;
+ case OP_COP2:
+ switch( INS_RS( op ) )
+ {
+ case RS_MFC:
+ sprintf( buffer, "mfc2 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp2genreg[ INS_RD( op ) ] );
+ break;
+ case RS_CFC:
+ sprintf( buffer, "cfc2 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp2ctlreg[ INS_RD( op ) ] );
+ break;
+ case RS_MTC:
+ sprintf( buffer, "mtc2 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp2genreg[ INS_RD( op ) ] );
+ break;
+ case RS_CTC:
+ sprintf( buffer, "ctc2 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp2ctlreg[ INS_RD( op ) ] );
+ break;
+ case RS_BC:
+ case RS_BC_ALT:
+ switch( INS_BC( op ) )
+ {
+ case BC_BCF:
+ sprintf( buffer, "bc2f $%08x", relative_address( state, pc, op ) );
+ break;
+ case BC_BCT:
+ sprintf( buffer, "bc2t $%08x", relative_address( state, pc, op ) );
+ break;
+ }
+ break;
+ default:
+ switch( INS_CO( op ) )
+ {
+ case 1:
+ sprintf( buffer, "cop2 $%07x", INS_COFUN( op ) );
+
+ switch( GTE_FUNCT( op ) )
+ {
+ case 0x01:
+ if( INS_COFUN( op ) == 0x0180001 )
+ {
+ sprintf( buffer, "rtps" );
+ }
+ break;
+ case 0x06:
+ if( INS_COFUN( op ) == 0x0400006 ||
+ INS_COFUN( op ) == 0x1400006 ||
+ INS_COFUN( op ) == 0x0155cc6 )
+ {
+ sprintf( buffer, "nclip" );
+ }
+ break;
+ case 0x0c:
+ if( GTE_OP( op ) == 0x17 )
+ {
+ sprintf( buffer, "op%s", s_gtesf[ GTE_SF( op ) ] );
+ }
+ break;
+ case 0x10:
+ if( INS_COFUN( op ) == 0x0780010 )
+ {
+ sprintf( buffer, "dpcs" );
+ }
+ break;
+ case 0x11:
+ if( INS_COFUN( op ) == 0x0980011 )
+ {
+ sprintf( buffer, "intpl" );
+ }
+ break;
+ case 0x12:
+ if( GTE_OP( op ) == 0x04 )
+ {
+ sprintf( buffer, "mvmva%s %s + %s * %s (lm=%s)",
+ s_gtesf[ GTE_SF( op ) ], s_gtecv[ GTE_CV( op ) ], s_gtemx[ GTE_MX( op ) ],
+ s_gtev[ GTE_V( op ) ], s_gtelm[ GTE_LM( op ) ] );
+ }
+ break;
+ case 0x13:
+ if( INS_COFUN( op ) == 0x0e80413 )
+ {
+ sprintf( buffer, "ncds" );
+ }
+ break;
+ case 0x14:
+ if( INS_COFUN( op ) == 0x1280414 )
+ {
+ sprintf( buffer, "cdp" );
+ }
+ break;
+ case 0x16:
+ if( INS_COFUN( op ) == 0x0f80416 )
+ {
+ sprintf( buffer, "ncdt" );
+ }
+ break;
+ case 0x1b:
+ if( INS_COFUN( op ) == 0x108041b )
+ {
+ sprintf( buffer, "nccs" );
+ }
+ break;
+ case 0x1c:
+ if( INS_COFUN( op ) == 0x138041c )
+ {
+ sprintf( buffer, "cc" );
+ }
+ break;
+ case 0x1e:
+ if( INS_COFUN( op ) == 0x0c8041e )
+ {
+ sprintf( buffer, "ncs" );
+ }
+ break;
+ case 0x20:
+ if( INS_COFUN( op ) == 0x0d80420 )
+ {
+ sprintf( buffer, "nct" );
+ }
+ break;
+ case 0x28:
+ if( GTE_OP( op ) == 0x0a && GTE_LM( op ) == 1 )
+ {
+ sprintf( buffer, "sqr%s", s_gtesf[ GTE_SF( op ) ] );
+ }
+ break;
+ case 0x29:
+ if( INS_COFUN( op ) == 0x0680029 )
+ {
+ sprintf( buffer, "dcpl" );
+ }
+ break;
+ case 0x2a:
+ if( INS_COFUN( op ) == 0x0f8002a )
+ {
+ sprintf( buffer, "dpct" );
+ }
+ break;
+ case 0x2d:
+ if( INS_COFUN( op ) == 0x158002d )
+ {
+ sprintf( buffer, "avsz3" );
+ }
+ break;
+ case 0x2e:
+ if( INS_COFUN( op ) == 0x168002e )
+ {
+ sprintf( buffer, "avsz4" );
+ }
+ break;
+ case 0x30:
+ if( INS_COFUN( op ) == 0x0280030 )
+ {
+ sprintf( buffer, "rtpt" );
+ }
+ break;
+ case 0x3d:
+ if( GTE_OP( op ) == 0x09 ||
+ GTE_OP( op ) == 0x19 )
+ {
+ sprintf( buffer, "gpf%s", s_gtesf[ GTE_SF( op ) ] );
+ }
+ break;
+ case 0x3e:
+ if( GTE_OP( op ) == 0x1a )
+ {
+ sprintf( buffer, "gpl%s", s_gtesf[ GTE_SF( op ) ] );
+ }
+ break;
+ case 0x3f:
+ if( INS_COFUN( op ) == 0x108043f ||
+ INS_COFUN( op ) == 0x118043f )
+ {
+ sprintf( buffer, "ncct" );
+ }
+ break;
+ }
+ }
+ break;
+ }
+ break;
+ case OP_COP3:
+ switch( INS_RS( op ) )
+ {
+ case RS_MFC:
+ sprintf( buffer, "mfc3 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp3genreg[ INS_RD( op ) ] );
+ break;
+ case RS_CFC:
+ sprintf( buffer, "cfc3 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp3ctlreg[ INS_RD( op ) ] );
+ break;
+ case RS_MTC:
+ sprintf( buffer, "mtc3 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp3genreg[ INS_RD( op ) ] );
+ break;
+ case RS_CTC:
+ sprintf( buffer, "ctc3 %s,%s", s_cpugenreg[ INS_RT( op ) ], s_cp3ctlreg[ INS_RD( op ) ] );
+ break;
+ case RS_BC:
+ case RS_BC_ALT:
+ switch( INS_BC( op ) )
+ {
+ case BC_BCF:
+ sprintf( buffer, "bc3f $%08x", relative_address( state, pc, op ) );
+ break;
+ case BC_BCT:
+ sprintf( buffer, "bc3t $%08x", relative_address( state, pc, op ) );
+ break;
+ }
+ break;
+ default:
+ switch( INS_CO( op ) )
+ {
+ case 1:
+ sprintf( buffer, "cop3 $%07x", INS_COFUN( op ) );
+ break;
+ }
+ break;
+ }
+ break;
+ case OP_LB:
+ sprintf( buffer, "lb %s,%s", s_cpugenreg[ INS_RT( op ) ], effective_address( state, pc, op ) );
+ break;
+ case OP_LH:
+ sprintf( buffer, "lh %s,%s", s_cpugenreg[ INS_RT( op ) ], effective_address( state, pc, op ) );
+ break;
+ case OP_LWL:
+ sprintf( buffer, "lwl %s,%s", s_cpugenreg[ INS_RT( op ) ], effective_address( state, pc, op ) );
+ break;
+ case OP_LW:
+ sprintf( buffer, "lw %s,%s", s_cpugenreg[ INS_RT( op ) ], effective_address( state, pc, op ) );
+ break;
+ case OP_LBU:
+ sprintf( buffer, "lbu %s,%s", s_cpugenreg[ INS_RT( op ) ], effective_address( state, pc, op ) );
+ break;
+ case OP_LHU:
+ sprintf( buffer, "lhu %s,%s", s_cpugenreg[ INS_RT( op ) ], effective_address( state, pc, op ) );
+ break;
+ case OP_LWR:
+ sprintf( buffer, "lwr %s,%s", s_cpugenreg[ INS_RT( op ) ], effective_address( state, pc, op ) );
+ break;
+ case OP_SB:
+ sprintf( buffer, "sb %s,%s", s_cpugenreg[ INS_RT( op ) ], effective_address( state, pc, op ) );
+ break;
+ case OP_SH:
+ sprintf( buffer, "sh %s,%s", s_cpugenreg[ INS_RT( op ) ], effective_address( state, pc, op ) );
+ break;
+ case OP_SWL:
+ sprintf( buffer, "swl %s,%s", s_cpugenreg[ INS_RT( op ) ], effective_address( state, pc, op ) );
+ break;
+ case OP_SW:
+ sprintf( buffer, "sw %s,%s", s_cpugenreg[ INS_RT( op ) ], effective_address( state, pc, op ) );
+ break;
+ case OP_SWR:
+ sprintf( buffer, "swr %s,%s", s_cpugenreg[ INS_RT( op ) ], effective_address( state, pc, op ) );
+ break;
+ case OP_LWC0:
+ sprintf( buffer, "lwc0 %s,%s", s_cp0genreg[ INS_RT( op ) ], effective_address( state, pc, op ) );
+ break;
+ case OP_LWC1:
+ sprintf( buffer, "lwc1 %s,%s", s_cp1genreg[ INS_RT( op ) ], effective_address( state, pc, op ) );
+ break;
+ case OP_LWC2:
+ sprintf( buffer, "lwc2 %s,%s", s_cp2genreg[ INS_RT( op ) ], effective_address( state, pc, op ) );
+ break;
+ case OP_LWC3:
+ sprintf( buffer, "lwc3 %s,%s", s_cp2genreg[ INS_RT( op ) ], effective_address( state, pc, op ) );
+ break;
+ case OP_SWC0:
+ sprintf( buffer, "swc0 %s,%s", s_cp0genreg[ INS_RT( op ) ], effective_address( state, pc, op ) );
+ break;
+ case OP_SWC1:
+ sprintf( buffer, "swc1 %s,%s", s_cp1genreg[ INS_RT( op ) ], effective_address( state, pc, op ) );
+ break;
+ case OP_SWC2:
+ sprintf( buffer, "swc2 %s,%s", s_cp2genreg[ INS_RT( op ) ], effective_address( state, pc, op ) );
+ break;
+ case OP_SWC3:
+ sprintf( buffer, "swc3 %s,%s", s_cp2genreg[ INS_RT( op ) ], effective_address( state, pc, op ) );
+ break;
+ }
+ return ( opram - oldopram ) | flags | DASMFLAG_SUPPORTED;
+}
+
+CPU_DISASSEMBLE( psxcpu_generic )
+{
+ DasmPSXCPU_state state = {0};
+ state.pc = pc;
+ return DasmPSXCPU( &state, buffer, pc, opram );
+}
diff --git a/trunk/src/emu/cpu/psx/rcnt.c b/trunk/src/emu/cpu/psx/rcnt.c
new file mode 100644
index 00000000000..779943b346b
--- /dev/null
+++ b/trunk/src/emu/cpu/psx/rcnt.c
@@ -0,0 +1,237 @@
+/*
+ * PlayStation Root Counter emulator
+ *
+ * Copyright 2003-2011 smf
+ *
+ */
+
+#include "rcnt.h"
+#include "includes/psx.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 device_type PSX_RCNT = &device_creator<psxrcnt_device>;
+
+psxrcnt_device::psxrcnt_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, PSX_RCNT, "PSX RCNT", tag, owner, clock)
+{
+}
+
+void psxrcnt_device::device_reset()
+{
+}
+
+void psxrcnt_device::device_post_load()
+{
+ int n;
+ for( n = 0; n < 3; n++ )
+ {
+ root_timer_adjust( n );
+ }
+}
+
+void psxrcnt_device::device_start()
+{
+ int n;
+
+ for( n = 0; n < 3; n++ )
+ {
+ root_counter[ n ].timer = machine().scheduler().timer_alloc( timer_expired_delegate( FUNC( psxrcnt_device::root_finished ), this ) );
+ state_save_register_item( machine(), "psxroot", NULL, n, root_counter[ n ].n_count );
+ state_save_register_item( machine(), "psxroot", NULL, n, root_counter[ n ].n_mode );
+ state_save_register_item( machine(), "psxroot", NULL, n, root_counter[ n ].n_target );
+ state_save_register_item( machine(), "psxroot", NULL, n, root_counter[ n ].n_start );
+ }
+}
+
+WRITE32_MEMBER( psxrcnt_device::write )
+{
+ int n_counter = offset / 4;
+ psx_root *root = &root_counter[ n_counter ];
+
+ verboselog( machine(), 1, "psx_counter_w ( %08x, %08x, %08x )\n", offset, data, mem_mask );
+
+ switch( offset % 4 )
+ {
+ case 0:
+ root->n_count = data;
+ root->n_start = gettotalcycles();
+ break;
+ case 1:
+ root->n_count = root_current( n_counter );
+ root->n_start = gettotalcycles();
+
+ if( ( data & PSX_RC_RESET ) != 0 )
+ {
+ data &= ~( PSX_RC_RESET | PSX_RC_STOP );
+ root->n_count = 0;
+ }
+
+ root->n_mode = data;
+
+#if 0
+ if( ( data & 0xfca6 ) != 0 ||
+ ( ( data & 0x0100 ) != 0 && n_counter != 0 && n_counter != 1 ) ||
+ ( ( data & 0x0200 ) != 0 && n_counter != 2 ) )
+ {
+ mame_printf_debug( "mode %d 0x%04x\n", n_counter, data & 0xfca6 );
+ }
+#endif
+ break;
+ case 2:
+ root->n_target = data;
+ break;
+ default:
+ verboselog( machine(), 0, "psx_counter_w( %08x, %08x, %08x ) unknown register\n", offset, mem_mask, data );
+ return;
+ }
+
+ root_timer_adjust( n_counter );
+}
+
+READ32_MEMBER( psxrcnt_device::read )
+{
+ int n_counter = offset / 4;
+ psx_root *root = &root_counter[ n_counter ];
+ UINT32 data;
+
+ switch( offset % 4 )
+ {
+ case 0:
+ data = root_current( n_counter );
+ break;
+ case 1:
+ data = root->n_mode;
+ break;
+ case 2:
+ data = root->n_target;
+ break;
+ default:
+ verboselog( machine(), 0, "psx_counter_r( %08x, %08x ) unknown register\n", offset, mem_mask );
+ return 0;
+ }
+ verboselog( machine(), 1, "psx_counter_r ( %08x, %08x ) %08x\n", offset, mem_mask, data );
+ return data;
+}
+
+UINT64 psxrcnt_device::gettotalcycles( void )
+{
+ /* TODO: should return the start of the current tick. */
+ return machine().firstcpu->total_cycles() * 2;
+}
+
+int psxrcnt_device::root_divider( int n_counter )
+{
+ psx_root *root = &root_counter[ n_counter ];
+
+ if( n_counter == 0 && ( root->n_mode & PSX_RC_CLC ) != 0 )
+ {
+ /* TODO: pixel clock, probably based on resolution */
+ return 5;
+ }
+ else if( n_counter == 1 && ( root->n_mode & PSX_RC_CLC ) != 0 )
+ {
+ return 2150;
+ }
+ else if( n_counter == 2 && ( root->n_mode & PSX_RC_DIV ) != 0 )
+ {
+ return 8;
+ }
+ return 1;
+}
+
+UINT16 psxrcnt_device::root_current( int n_counter )
+{
+ psx_root *root = &root_counter[ n_counter ];
+
+ if( ( root->n_mode & PSX_RC_STOP ) != 0 )
+ {
+ return root->n_count;
+ }
+ else
+ {
+ UINT64 n_current;
+ n_current = gettotalcycles() - root->n_start;
+ n_current /= root_divider( n_counter );
+ n_current += root->n_count;
+ if( n_current > 0xffff )
+ {
+ /* TODO: use timer for wrap on 0x10000. */
+ root->n_count = n_current;
+ root->n_start = gettotalcycles();
+ }
+ return n_current;
+ }
+}
+
+int psxrcnt_device::root_target( int n_counter )
+{
+ psx_root *root = &root_counter[ n_counter ];
+
+ if( ( root->n_mode & PSX_RC_COUNTTARGET ) != 0 ||
+ ( root->n_mode & PSX_RC_IRQTARGET ) != 0 )
+ {
+ return root->n_target;
+ }
+ return 0x10000;
+}
+
+void psxrcnt_device::root_timer_adjust( int n_counter )
+{
+ psx_root *root = &root_counter[ n_counter ];
+
+ if( ( root->n_mode & PSX_RC_STOP ) != 0 )
+ {
+ root->timer->adjust( attotime::never, n_counter);
+ }
+ else
+ {
+ int n_duration;
+
+ n_duration = root_target( n_counter ) - root_current( n_counter );
+ if( n_duration < 1 )
+ {
+ n_duration += 0x10000;
+ }
+
+ n_duration *= root_divider( n_counter );
+
+ root->timer->adjust( attotime::from_hz(33868800) * n_duration, n_counter);
+ }
+}
+
+void psxrcnt_device::root_finished( void *ptr, int param )
+{
+ int n_counter = param;
+ psx_root *root = &root_counter[ n_counter ];
+
+ verboselog( machine(), 2, "root_finished( %d ) %04x\n", n_counter, root_current( n_counter ) );
+ //if( ( root->n_mode & PSX_RC_COUNTTARGET ) != 0 )
+ {
+ /* TODO: wrap should be handled differently as PSX_RC_COUNTTARGET & PSX_RC_IRQTARGET don't have to be the same. */
+ root->n_count = 0;
+ root->n_start = gettotalcycles();
+ }
+ if( ( root->n_mode & PSX_RC_REPEAT ) != 0 )
+ {
+ root_timer_adjust( n_counter );
+ }
+ if( ( root->n_mode & PSX_RC_IRQOVERFLOW ) != 0 ||
+ ( root->n_mode & PSX_RC_IRQTARGET ) != 0 )
+ {
+ psx_irq_set( machine(), PSX_IRQ_ROOTCOUNTER0 << n_counter );
+ }
+}
diff --git a/trunk/src/emu/cpu/psx/rcnt.h b/trunk/src/emu/cpu/psx/rcnt.h
new file mode 100644
index 00000000000..759ee518fad
--- /dev/null
+++ b/trunk/src/emu/cpu/psx/rcnt.h
@@ -0,0 +1,60 @@
+/*
+ * PlayStation Root Counter emulator
+ *
+ * Copyright 2003-2011 smf
+ *
+ */
+
+#pragma once
+
+#ifndef __PSXRCNT_H__
+#define __PSXRCNT_H__
+
+#include "emu.h"
+
+extern const device_type PSX_RCNT;
+
+#define PSX_RC_STOP ( 0x01 )
+#define PSX_RC_RESET ( 0x04 ) /* guess */
+#define PSX_RC_COUNTTARGET ( 0x08 )
+#define PSX_RC_IRQTARGET ( 0x10 )
+#define PSX_RC_IRQOVERFLOW ( 0x20 )
+#define PSX_RC_REPEAT ( 0x40 )
+#define PSX_RC_CLC ( 0x100 )
+#define PSX_RC_DIV ( 0x200 )
+
+typedef struct _psx_root psx_root;
+struct _psx_root
+{
+ emu_timer *timer;
+ UINT16 n_count;
+ UINT16 n_mode;
+ UINT16 n_target;
+ UINT64 n_start;
+};
+
+class psxrcnt_device : public device_t
+{
+public:
+ psxrcnt_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ WRITE32_MEMBER( write );
+ READ32_MEMBER( read );
+
+protected:
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_post_load();
+
+private:
+ psx_root root_counter[ 3 ];
+
+ UINT64 gettotalcycles( void );
+ int root_divider( int n_counter );
+ UINT16 root_current( int n_counter );
+ int root_target( int n_counter );
+ void root_timer_adjust( int n_counter );
+ void root_finished( void *ptr, int param );
+};
+
+#endif
diff --git a/trunk/src/emu/cpu/psx/sio.c b/trunk/src/emu/cpu/psx/sio.c
new file mode 100644
index 00000000000..170934cd8d7
--- /dev/null
+++ b/trunk/src/emu/cpu/psx/sio.c
@@ -0,0 +1,383 @@
+/*
+ * PlayStation Serial I/O emulator
+ *
+ * Copyright 2003-2011 smf
+ *
+ */
+
+#include "sio.h"
+#include "includes/psx.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 device_type PSX_SIO = &device_creator<psxsio_device>;
+
+psxsio_device::psxsio_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, PSX_SIO, "PSX SIO", tag, owner, clock)
+{
+ int n;
+
+ for( n = 0; n < 2; n++ )
+ {
+ port[ n ].fn_handler = NULL;
+ }
+}
+
+void psxsio_device::device_reset()
+{
+}
+
+void psxsio_device::device_post_load()
+{
+ int n;
+
+ for( n = 0; n < 2; n++ )
+ {
+ sio_timer_adjust( n );
+ }
+}
+
+void psxsio_device::device_start()
+{
+ int n;
+
+ for( n = 0; n < 2; n++ )
+ {
+ port[ n ].timer = machine().scheduler().timer_alloc( timer_expired_delegate( FUNC( psxsio_device::sio_clock ), this ) );
+ port[ n ].n_status = SIO_STATUS_TX_EMPTY | SIO_STATUS_TX_RDY;
+ port[ n ].n_mode = 0;
+ port[ n ].n_control = 0;
+ port[ n ].n_baud = 0;
+ port[ n ].n_tx = 0;
+ port[ n ].n_rx = 0;
+ port[ n ].n_tx_prev = 0;
+ port[ n ].n_rx_prev = 0;
+ port[ n ].n_rx_data = 0;
+ port[ n ].n_tx_data = 0;
+ port[ n ].n_rx_shift = 0;
+ port[ n ].n_tx_shift = 0;
+ port[ n ].n_rx_bits = 0;
+ port[ n ].n_tx_bits = 0;
+ }
+
+ for( n = 0; n < 2; n++ )
+ {
+ state_save_register_item( machine(), "psxsio", NULL, n, port[n].n_status );
+ state_save_register_item( machine(), "psxsio", NULL, n, port[n].n_mode );
+ state_save_register_item( machine(), "psxsio", NULL, n, port[n].n_control );
+ state_save_register_item( machine(), "psxsio", NULL, n, port[n].n_baud );
+ state_save_register_item( machine(), "psxsio", NULL, n, port[n].n_tx );
+ state_save_register_item( machine(), "psxsio", NULL, n, port[n].n_rx );
+ state_save_register_item( machine(), "psxsio", NULL, n, port[n].n_tx_prev );
+ state_save_register_item( machine(), "psxsio", NULL, n, port[n].n_rx_prev );
+ state_save_register_item( machine(), "psxsio", NULL, n, port[n].n_rx_data );
+ state_save_register_item( machine(), "psxsio", NULL, n, port[n].n_tx_data );
+ state_save_register_item( machine(), "psxsio", NULL, n, port[n].n_rx_shift );
+ state_save_register_item( machine(), "psxsio", NULL, n, port[n].n_tx_shift );
+ state_save_register_item( machine(), "psxsio", NULL, n, port[n].n_rx_bits );
+ state_save_register_item( machine(), "psxsio", NULL, n, port[n].n_tx_bits );
+ }
+}
+
+void psxsio_device::install_handler( int n_port, psx_sio_handler p_f_sio_handler )
+{
+ port[ n_port ].fn_handler = p_f_sio_handler;
+}
+
+void psxsio_device::sio_interrupt( int n_port )
+{
+ psx_sio *sio = &port[ n_port ];
+
+ verboselog( machine(), 1, "sio_interrupt( %d )\n", n_port );
+ sio->n_status |= SIO_STATUS_IRQ;
+ if( n_port == 0 )
+ {
+ psx_irq_set( machine(), PSX_IRQ_SIO0 );
+ }
+ else
+ {
+ psx_irq_set( machine(), PSX_IRQ_SIO1 );
+ }
+}
+
+void psxsio_device::sio_timer_adjust( int n_port )
+{
+ psx_sio *sio = &port[ n_port ];
+ attotime n_time;
+
+ if( ( sio->n_status & SIO_STATUS_TX_EMPTY ) == 0 || sio->n_tx_bits != 0 )
+ {
+ int n_prescaler;
+
+ switch( sio->n_mode & 3 )
+ {
+ case 1:
+ n_prescaler = 1;
+ break;
+ case 2:
+ n_prescaler = 16;
+ break;
+ case 3:
+ n_prescaler = 64;
+ break;
+ default:
+ n_prescaler = 0;
+ break;
+ }
+
+ if( sio->n_baud != 0 && n_prescaler != 0 )
+ {
+ n_time = attotime::from_hz(33868800) * (n_prescaler * sio->n_baud);
+ verboselog( machine(), 2, "sio_timer_adjust( %d ) = %s ( %d x %d )\n", n_port, n_time.as_string(), n_prescaler, sio->n_baud );
+ }
+ else
+ {
+ n_time = attotime::never;
+ verboselog( machine(), 0, "sio_timer_adjust( %d ) invalid baud rate ( %d x %d )\n", n_port, n_prescaler, sio->n_baud );
+ }
+ }
+ else
+ {
+ n_time = attotime::never;
+ verboselog( machine(), 2, "sio_timer_adjust( %d ) finished\n", n_port );
+ }
+ sio->timer->adjust( n_time, n_port);
+}
+
+void psxsio_device::sio_clock(void *ptr, int param)
+{
+ int n_port = param;
+ psx_sio *sio = &port[ n_port ];
+ verboselog( machine(), 2, "sio tick\n" );
+
+ if( sio->n_tx_bits == 0 &&
+ ( sio->n_control & SIO_CONTROL_TX_ENA ) != 0 &&
+ ( sio->n_status & SIO_STATUS_TX_EMPTY ) == 0 )
+ {
+ sio->n_tx_bits = 8;
+ sio->n_tx_shift = sio->n_tx_data;
+ if( n_port == 0 )
+ {
+ sio->n_rx_bits = 8;
+ sio->n_rx_shift = 0;
+ }
+ sio->n_status |= SIO_STATUS_TX_EMPTY;
+ sio->n_status |= SIO_STATUS_TX_RDY;
+ }
+
+ if( sio->n_tx_bits != 0 )
+ {
+ sio->n_tx = ( sio->n_tx & ~PSX_SIO_OUT_DATA ) | ( ( sio->n_tx_shift & 1 ) * PSX_SIO_OUT_DATA );
+ sio->n_tx_shift >>= 1;
+ sio->n_tx_bits--;
+
+ if( sio->fn_handler != NULL )
+ {
+ if( n_port == 0 )
+ {
+ sio->n_tx &= ~PSX_SIO_OUT_CLOCK;
+ (*sio->fn_handler)( machine(), sio->n_tx );
+ sio->n_tx |= PSX_SIO_OUT_CLOCK;
+ }
+ (*sio->fn_handler)( machine(), sio->n_tx );
+ }
+
+ if( sio->n_tx_bits == 0 &&
+ ( sio->n_control & SIO_CONTROL_TX_IENA ) != 0 )
+ {
+ sio_interrupt( n_port );
+ }
+ }
+
+ if( sio->n_rx_bits != 0 )
+ {
+ sio->n_rx_shift = ( sio->n_rx_shift >> 1 ) | ( ( ( sio->n_rx & PSX_SIO_IN_DATA ) / PSX_SIO_IN_DATA ) << 7 );
+ sio->n_rx_bits--;
+
+ if( sio->n_rx_bits == 0 )
+ {
+ if( ( sio->n_status & SIO_STATUS_RX_RDY ) != 0 )
+ {
+ sio->n_status |= SIO_STATUS_OVERRUN;
+ }
+ else
+ {
+ sio->n_rx_data = sio->n_rx_shift;
+ sio->n_status |= SIO_STATUS_RX_RDY;
+ }
+ if( ( sio->n_control & SIO_CONTROL_RX_IENA ) != 0 )
+ {
+ sio_interrupt( n_port );
+ }
+ }
+ }
+
+ sio_timer_adjust( n_port );
+}
+
+WRITE32_MEMBER( psxsio_device::write )
+{
+ int n_port = offset / 4;
+ psx_sio *sio = &port[ n_port ];
+
+ switch( offset % 4 )
+ {
+ case 0:
+ verboselog( machine(), 1, "psx_sio_w %d data %02x (%08x)\n", n_port, data, mem_mask );
+ sio->n_tx_data = data;
+ sio->n_status &= ~( SIO_STATUS_TX_RDY );
+ sio->n_status &= ~( SIO_STATUS_TX_EMPTY );
+ sio_timer_adjust( n_port );
+ break;
+ case 1:
+ verboselog( machine(), 0, "psx_sio_w( %08x, %08x, %08x )\n", offset, data, mem_mask );
+ break;
+ case 2:
+ if( ACCESSING_BITS_0_15 )
+ {
+ sio->n_mode = data & 0xffff;
+ verboselog( machine(), 1, "psx_sio_w %d mode %04x\n", n_port, data & 0xffff );
+ }
+ if( ACCESSING_BITS_16_31 )
+ {
+ verboselog( machine(), 1, "psx_sio_w %d control %04x\n", n_port, data >> 16 );
+ sio->n_control = data >> 16;
+
+ if( ( sio->n_control & SIO_CONTROL_RESET ) != 0 )
+ {
+ verboselog( machine(), 1, "psx_sio_w reset\n" );
+ sio->n_status |= SIO_STATUS_TX_EMPTY | SIO_STATUS_TX_RDY;
+ sio->n_status &= ~( SIO_STATUS_RX_RDY | SIO_STATUS_OVERRUN | SIO_STATUS_IRQ );
+ }
+ if( ( sio->n_control & SIO_CONTROL_IACK ) != 0 )
+ {
+ verboselog( machine(), 1, "psx_sio_w iack\n" );
+ sio->n_status &= ~( SIO_STATUS_IRQ );
+ sio->n_control &= ~( SIO_CONTROL_IACK );
+ }
+ if( ( sio->n_control & SIO_CONTROL_DTR ) != 0 )
+ {
+ sio->n_tx |= PSX_SIO_OUT_DTR;
+ }
+ else
+ {
+ sio->n_tx &= ~PSX_SIO_OUT_DTR;
+ }
+
+ if( ( ( sio->n_tx ^ sio->n_tx_prev ) & PSX_SIO_OUT_DTR ) != 0 )
+ {
+ if( sio->fn_handler != NULL )
+ {
+ (*sio->fn_handler)( machine(), sio->n_tx );
+ }
+ }
+ sio->n_tx_prev = sio->n_tx;
+
+ }
+ break;
+ case 3:
+ if( ACCESSING_BITS_0_15 )
+ {
+ verboselog( machine(), 0, "psx_sio_w( %08x, %08x, %08x )\n", offset, data, mem_mask );
+ }
+ if( ACCESSING_BITS_16_31 )
+ {
+ sio->n_baud = data >> 16;
+ verboselog( machine(), 1, "psx_sio_w %d baud %04x\n", n_port, data >> 16 );
+ }
+ break;
+ default:
+ verboselog( machine(), 0, "psx_sio_w( %08x, %08x, %08x )\n", offset, data, mem_mask );
+ break;
+ }
+}
+
+READ32_MEMBER( psxsio_device::read )
+{
+ int n_port = offset / 4;
+ psx_sio *sio = &port[ n_port ];
+ UINT32 data;
+
+ switch( offset % 4 )
+ {
+ case 0:
+ data = sio->n_rx_data;
+ sio->n_status &= ~( SIO_STATUS_RX_RDY );
+ sio->n_rx_data = 0xff;
+ verboselog( machine(), 1, "psx_sio_r %d data %02x (%08x)\n", n_port, data, mem_mask );
+ break;
+ case 1:
+ data = sio->n_status;
+ if( ACCESSING_BITS_0_15 )
+ {
+ verboselog( machine(), 1, "psx_sio_r %d status %04x\n", n_port, data & 0xffff );
+ }
+ if( ACCESSING_BITS_16_31 )
+ {
+ verboselog( machine(), 0, "psx_sio_r( %08x, %08x ) %08x\n", offset, mem_mask, data );
+ }
+ break;
+ case 2:
+ data = ( sio->n_control << 16 ) | sio->n_mode;
+ if( ACCESSING_BITS_0_15 )
+ {
+ verboselog( machine(), 1, "psx_sio_r %d mode %04x\n", n_port, data & 0xffff );
+ }
+ if( ACCESSING_BITS_16_31 )
+ {
+ verboselog( machine(), 1, "psx_sio_r %d control %04x\n", n_port, data >> 16 );
+ }
+ break;
+ case 3:
+ data = sio->n_baud << 16;
+ if( ACCESSING_BITS_0_15 )
+ {
+ verboselog( machine(), 0, "psx_sio_r( %08x, %08x ) %08x\n", offset, mem_mask, data );
+ }
+ if( ACCESSING_BITS_16_31 )
+ {
+ verboselog( machine(), 1, "psx_sio_r %d baud %04x\n", n_port, data >> 16 );
+ }
+ break;
+ default:
+ data = 0;
+ verboselog( machine(), 0, "psx_sio_r( %08x, %08x ) %08x\n", offset, mem_mask, data );
+ break;
+ }
+ return data;
+}
+
+void psxsio_device::input( int n_port, int n_mask, int n_data )
+{
+ psx_sio *sio = &port[ n_port ];
+ verboselog( machine(), 1, "psx_sio_input( %d, %02x, %02x )\n", n_port, n_mask, n_data );
+ sio->n_rx = ( sio->n_rx & ~n_mask ) | ( n_data & n_mask );
+
+ if( ( sio->n_rx & PSX_SIO_IN_DSR ) != 0 )
+ {
+ sio->n_status |= SIO_STATUS_DSR;
+ if( ( sio->n_rx_prev & PSX_SIO_IN_DSR ) == 0 &&
+ ( sio->n_control & SIO_CONTROL_DSR_IENA ) != 0 )
+ {
+ sio_interrupt( n_port );
+ }
+ }
+ else
+ {
+ sio->n_status &= ~SIO_STATUS_DSR;
+ }
+ sio->n_rx_prev = sio->n_rx;
+}
diff --git a/trunk/src/emu/cpu/psx/sio.h b/trunk/src/emu/cpu/psx/sio.h
new file mode 100644
index 00000000000..34f504b778e
--- /dev/null
+++ b/trunk/src/emu/cpu/psx/sio.h
@@ -0,0 +1,94 @@
+/*
+ * PlayStation Serial I/O emulator
+ *
+ * Copyright 2003-2011 smf
+ *
+ */
+
+#pragma once
+
+#ifndef __PSXSIO_H__
+#define __PSXSIO_H__
+
+#include "emu.h"
+
+extern const device_type PSX_SIO;
+
+typedef void ( *psx_sio_handler )( running_machine &, int );
+
+#define PSX_SIO_OUT_DATA ( 1 ) /* COMMAND */
+#define PSX_SIO_OUT_DTR ( 2 ) /* ATT */
+#define PSX_SIO_OUT_RTS ( 4 )
+#define PSX_SIO_OUT_CLOCK ( 8 ) /* CLOCK */
+#define PSX_SIO_IN_DATA ( 1 ) /* DATA */
+#define PSX_SIO_IN_DSR ( 2 ) /* ACK */
+#define PSX_SIO_IN_CTS ( 4 )
+
+#define SIO_BUF_SIZE ( 8 )
+
+#define SIO_STATUS_TX_RDY ( 1 << 0 )
+#define SIO_STATUS_RX_RDY ( 1 << 1 )
+#define SIO_STATUS_TX_EMPTY ( 1 << 2 )
+#define SIO_STATUS_OVERRUN ( 1 << 4 )
+#define SIO_STATUS_DSR ( 1 << 7 )
+#define SIO_STATUS_IRQ ( 1 << 9 )
+
+#define SIO_CONTROL_TX_ENA ( 1 << 0 )
+#define SIO_CONTROL_IACK ( 1 << 4 )
+#define SIO_CONTROL_RESET ( 1 << 6 )
+#define SIO_CONTROL_TX_IENA ( 1 << 10 )
+#define SIO_CONTROL_RX_IENA ( 1 << 11 )
+#define SIO_CONTROL_DSR_IENA ( 1 << 12 )
+#define SIO_CONTROL_DTR ( 1 << 13 )
+
+typedef struct _psx_sio psx_sio;
+struct _psx_sio
+{
+ UINT32 n_status;
+ UINT32 n_mode;
+ UINT32 n_control;
+ UINT32 n_baud;
+ UINT32 n_tx;
+ UINT32 n_rx;
+ UINT32 n_tx_prev;
+ UINT32 n_rx_prev;
+ UINT32 n_tx_data;
+ UINT32 n_rx_data;
+ UINT32 n_tx_shift;
+ UINT32 n_rx_shift;
+ UINT32 n_tx_bits;
+ UINT32 n_rx_bits;
+
+ emu_timer *timer;
+ psx_sio_handler fn_handler;
+};
+
+class psxsio_device : public device_t
+{
+public:
+ psxsio_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ void install_handler( int n_port, psx_sio_handler p_f_sio_handler );
+
+ WRITE32_MEMBER( write );
+ READ32_MEMBER( read );
+
+ void input( int n_port, int n_mask, int n_data );
+
+protected:
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_post_load();
+
+private:
+ void sio_interrupt( int n_port );
+ void sio_timer_adjust( int n_port );
+ void sio_clock(void *ptr, int param);
+
+ psx_sio port[2];
+};
+
+WRITE32_HANDLER( psx_sio_w );
+READ32_HANDLER( psx_sio_r );
+
+#endif
diff --git a/trunk/src/emu/cpu/rsp/rsp.c b/trunk/src/emu/cpu/rsp/rsp.c
new file mode 100644
index 00000000000..a6bedcf3fcd
--- /dev/null
+++ b/trunk/src/emu/cpu/rsp/rsp.c
@@ -0,0 +1,3144 @@
+/*
+ Nintendo/SGI Reality Signal Processor (RSP) emulator
+
+ Written by Ville Linde
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "rsp.h"
+#include "rspdiv.h"
+
+CPU_DISASSEMBLE( rsp );
+
+#ifndef USE_RSPDRC
+
+#define LOG_INSTRUCTION_EXECUTION 0
+#define SAVE_DISASM 0
+#define SAVE_DMEM 0
+#define RSP_TEST_SYNC 0
+
+#define PRINT_VECREG(x) mame_printf_debug("V%d: %04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X\n", (x), \
+ (UINT16)VREG_S((x),0), (UINT16)VREG_S((x),1), \
+ (UINT16)VREG_S((x),2), (UINT16)VREG_S((x),3), \
+ (UINT16)VREG_S((x),4), (UINT16)VREG_S((x),5), \
+ (UINT16)VREG_S((x),6), (UINT16)VREG_S((x),7))
+
+#define PRINT_ACCUM(x) mame_printf_debug("A%d: %08X|%08X\n", (x), \
+ (UINT32)( ( ACCUM(x) >> 32 ) & 0x00000000ffffffff ), \
+ (UINT32)( ACCUM(x) & 0x00000000ffffffff ))
+
+extern offs_t rsp_dasm_one(char *buffer, offs_t pc, UINT32 op);
+
+INLINE rsp_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == RSP);
+ return (rsp_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+#define SIMM16 ((INT32)(INT16)(op))
+#define UIMM16 ((UINT16)(op))
+#define UIMM26 (op & 0x03ffffff)
+
+#define JUMP_ABS(addr) { rsp->nextpc = 0x04001000 | (((addr) << 2) & 0xfff); }
+#define JUMP_ABS_L(addr,l) { rsp->nextpc = 0x04001000 | (((addr) << 2) & 0xfff); rsp->r[l] = rsp->pc + 4; }
+#define JUMP_REL(offset) { rsp->nextpc = 0x04001000 | ((rsp->pc + ((offset) << 2)) & 0xfff); }
+#define JUMP_REL_L(offset,l) { rsp->nextpc = 0x04001000 | ((rsp->pc + ((offset) << 2)) & 0xfff); rsp->r[l] = rsp->pc + 4; }
+#define JUMP_PC(addr) { rsp->nextpc = 0x04001000 | ((addr) & 0xfff); }
+#define JUMP_PC_L(addr,l) { rsp->nextpc = 0x04001000 | ((addr) & 0xfff); rsp->r[l] = rsp->pc + 4; }
+#define LINK(l) { rsp->r[l] = rsp->pc + 4; }
+
+#define VREG_B(reg, offset) rsp->v[(reg)].b[(offset)^1]
+#define VREG_S(reg, offset) rsp->v[(reg)].s[(offset)]
+#define VREG_L(reg, offset) rsp->v[(reg)].l[(offset)]
+
+#define R_VREG_B(reg, offset) rsp->v[(reg)].b[(offset)^1]
+#define R_VREG_S(reg, offset) (INT16)rsp->v[(reg)].s[(offset)]
+#define R_VREG_L(reg, offset) rsp->v[(reg)].l[(offset)]
+
+#define W_VREG_B(reg, offset, val) (rsp->v[(reg)].b[(offset)^1] = val)
+#define W_VREG_S(reg, offset, val) (rsp->v[(reg)].s[(offset)] = val)
+#define W_VREG_L(reg, offset, val) (rsp->v[(reg)].l[(offset)] = val)
+
+#define VEC_EL_2(x,z) (vector_elements[(x)][(z)])
+
+#define ACCUM(x) rsp->accum[((x))].q
+#define ACCUM_H(x) rsp->accum[((x))].w[3]
+#define ACCUM_M(x) rsp->accum[((x))].w[2]
+#define ACCUM_L(x) rsp->accum[((x))].w[1]
+
+#define CARRY_FLAG(x) ((rsp->flag[0] & (1 << ((x)))) ? 1 : 0)
+#define CLEAR_CARRY_FLAGS() { rsp->flag[0] &= ~0xff; }
+#define SET_CARRY_FLAG(x) { rsp->flag[0] |= (1 << ((x))); }
+#define CLEAR_CARRY_FLAG(x) { rsp->flag[0] &= ~(1 << ((x))); }
+
+#define COMPARE_FLAG(x) ((rsp->flag[1] & (1 << ((x)))) ? 1 : 0)
+#define CLEAR_COMPARE_FLAGS() { rsp->flag[1] &= ~0xff; }
+#define SET_COMPARE_FLAG(x) { rsp->flag[1] |= (1 << ((x))); }
+#define CLEAR_COMPARE_FLAG(x) { rsp->flag[1] &= ~(1 << ((x))); }
+
+#define ZERO_FLAG(x) ((rsp->flag[0] & (1 << (8+(x)))) ? 1 : 0)
+#define CLEAR_ZERO_FLAGS() { rsp->flag[0] &= ~0xff00; }
+#define SET_ZERO_FLAG(x) { rsp->flag[0] |= (1 << (8+(x))); }
+#define CLEAR_ZERO_FLAG(x) { rsp->flag[0] &= ~(1 << (8+(x))); }
+
+#define EXTENSION_FLAG(x) ((rsp.flag[2] & (1 << ((x)))) ? 1 : 0)
+
+#define ROPCODE(pc) rsp->program->read_dword(pc)
+
+INLINE UINT8 READ8(rsp_state *rsp, UINT32 address)
+{
+ UINT8 ret;
+ address = 0x04000000 | (address & 0xfff);
+ ret = rsp->program->read_byte(address);
+ printf("%04xr%02x\n", address & 0x0000ffff, ret);
+ return ret;
+}
+
+INLINE UINT16 READ16(rsp_state *rsp, UINT32 address)
+{
+ UINT16 ret;
+ address = 0x04000000 | (address & 0xfff);
+
+ if(address & 1)
+ {
+ ret = ((rsp->program->read_byte(address + 0) & 0xff) << 8) | (rsp->program->read_byte(address + 1) & 0xff);
+ }
+ else
+ {
+ ret = rsp->program->read_word(address);
+ }
+
+ printf("%04xr%04x\n", address & 0x0000ffff, ret);
+
+ return ret;
+}
+
+INLINE UINT32 READ32(rsp_state *rsp, UINT32 address)
+{
+ UINT32 ret;
+ address = 0x04000000 | (address & 0xfff);
+
+ if(address & 3)
+ {
+ ret = ((rsp->program->read_byte(address + 0) & 0xff) << 24) |
+ ((rsp->program->read_byte(address + 1) & 0xff) << 16) |
+ ((rsp->program->read_byte(address + 2) & 0xff) << 8) |
+ ((rsp->program->read_byte(address + 3) & 0xff) << 0);
+ }
+ else
+ {
+ ret = rsp->program->read_dword(address);
+ }
+
+ printf("%04xr%08x\n", address & 0x0000ffff, ret);
+ return ret;
+}
+
+INLINE void WRITE8(rsp_state *rsp, UINT32 address, UINT8 data)
+{
+ address = 0x04000000 | (address & 0xfff);
+ printf("%04x:%02x\n", address & 0x0000ffff, data);
+ rsp->program->write_byte(address, data);
+}
+
+INLINE void WRITE16(rsp_state *rsp, UINT32 address, UINT16 data)
+{
+ address = 0x04000000 | (address & 0xfff);
+ printf("%04x:%04x\n", address & 0x0000ffff, data);
+
+ if(address & 1)
+ {
+ rsp->program->write_byte(address + 0, (data >> 8) & 0xff);
+ rsp->program->write_byte(address + 1, (data >> 0) & 0xff);
+ return;
+ }
+
+ rsp->program->write_word(address, data);
+}
+
+INLINE void WRITE32(rsp_state *rsp, UINT32 address, UINT32 data)
+{
+ address = 0x04000000 | (address & 0xfff);
+ printf("%04x:%08x\n", address & 0x0000ffff, data);
+
+ if(address & 3)
+ {
+ rsp->program->write_byte(address + 0, (data >> 24) & 0xff);
+ rsp->program->write_byte(address + 1, (data >> 16) & 0xff);
+ rsp->program->write_byte(address + 2, (data >> 8) & 0xff);
+ rsp->program->write_byte(address + 3, (data >> 0) & 0xff);
+ return;
+ }
+
+ rsp->program->write_dword(address, data);
+}
+
+/*****************************************************************************/
+
+static UINT32 get_cop0_reg(rsp_state *rsp, int reg)
+{
+ reg &= 0xf;
+ if (reg < 8)
+ {
+ return (rsp->config->sp_reg_r)(rsp->device, reg, 0x00000000);
+ }
+ else if (reg >= 8 && reg < 16)
+ {
+ return (rsp->config->dp_reg_r)(rsp->device, reg - 8, 0x00000000);
+ }
+
+ return 0;
+}
+
+static void set_cop0_reg(rsp_state *rsp, int reg, UINT32 data)
+{
+ reg &= 0xf;
+ if (reg < 8)
+ {
+ (rsp->config->sp_reg_w)(rsp->device, reg, data, 0x00000000);
+ }
+ else if (reg >= 8 && reg < 16)
+ {
+ (rsp->config->dp_reg_w)(rsp->device, reg - 8, data, 0x00000000);
+ }
+}
+
+static void unimplemented_opcode(rsp_state *rsp, UINT32 op)
+{
+ if ((rsp->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ {
+ char string[200];
+ rsp_dasm_one(string, rsp->ppc, op);
+ mame_printf_debug("%08X: %s\n", rsp->ppc, string);
+ }
+
+#if SAVE_DISASM
+ {
+ char string[200];
+ int i;
+ FILE *dasm;
+ dasm = fopen("rsp_disasm.txt", "wt");
+
+ for (i=0; i < 0x1000; i+=4)
+ {
+ UINT32 opcode = ROPCODE(0x04001000 + i);
+ rsp_dasm_one(string, 0x04001000 + i, opcode);
+ fprintf(dasm, "%08X: %08X %s\n", 0x04001000 + i, opcode, string);
+ }
+ fclose(dasm);
+ }
+#endif
+#if SAVE_DMEM
+ {
+ int i;
+ FILE *dmem;
+ dmem = fopen("rsp_dmem.bin", "wb");
+
+ for (i=0; i < 0x1000; i++)
+ {
+ fputc(READ8(rsp, 0x04000000 + i), dmem);
+ }
+ fclose(dmem);
+ }
+#endif
+
+ fatalerror("RSP: unknown opcode %02X (%08X) at %08X\n", op >> 26, op, rsp->ppc);
+}
+
+/*****************************************************************************/
+
+static const int vector_elements[16][8] =
+{
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // none
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // ???
+ { 0, 0, 2, 2, 4, 4, 6, 6 }, // 0q
+ { 1, 1, 3, 3, 5, 5, 7, 7 }, // 1q
+ { 0, 0, 0, 0, 4, 4, 4, 4 }, // 0h
+ { 1, 1, 1, 1, 5, 5, 5, 5 }, // 1h
+ { 2, 2, 2, 2, 6, 6, 6, 6 }, // 2h
+ { 3, 3, 3, 3, 7, 7, 7, 7 }, // 3h
+ { 0, 0, 0, 0, 0, 0, 0, 0 }, // 0
+ { 1, 1, 1, 1, 1, 1, 1, 1 }, // 1
+ { 2, 2, 2, 2, 2, 2, 2, 2 }, // 2
+ { 3, 3, 3, 3, 3, 3, 3, 3 }, // 3
+ { 4, 4, 4, 4, 4, 4, 4, 4 }, // 4
+ { 5, 5, 5, 5, 5, 5, 5, 5 }, // 5
+ { 6, 6, 6, 6, 6, 6, 6, 6 }, // 6
+ { 7, 7, 7, 7, 7, 7, 7, 7 }, // 7
+};
+
+static CPU_INIT( rsp )
+{
+ rsp_state *rsp = get_safe_token(device);
+ int regIdx;
+ int accumIdx;
+ rsp->config = (const rsp_config *)device->static_config();
+
+ if (LOG_INSTRUCTION_EXECUTION)
+ rsp->exec_output = fopen("rsp_execute.txt", "wt");
+
+ rsp->irq_callback = irqcallback;
+ rsp->device = device;
+ rsp->program = device->space(AS_PROGRAM);
+ rsp->direct = &rsp->program->direct();
+
+#if 1
+ // Inaccurate. RSP registers power on to a random state...
+ for(regIdx = 0; regIdx < 32; regIdx++ )
+ {
+ rsp->r[regIdx] = 0;
+ rsp->v[regIdx].d[0] = 0;
+ rsp->v[regIdx].d[1] = 0;
+ }
+ rsp->flag[0] = 0;
+ rsp->flag[1] = 0;
+ rsp->flag[2] = 0;
+ rsp->flag[3] = 0;
+ rsp->square_root_res = 0;
+ rsp->square_root_high = 0;
+ rsp->reciprocal_res = 0;
+ rsp->reciprocal_high = 0;
+#endif
+
+ // ...except for the accumulators.
+ // We're not calling machine.rand() because initializing something with machine.rand()
+ // makes me retch uncontrollably.
+ for(accumIdx = 0; accumIdx < 8; accumIdx++ )
+ {
+ rsp->accum[accumIdx].q = 0;
+ }
+
+ rsp->sr = RSP_STATUS_HALT;
+ rsp->step_count = 0;
+}
+
+static CPU_EXIT( rsp )
+{
+ rsp_state *rsp = get_safe_token(device);
+
+#if SAVE_DISASM
+ {
+ char string[200];
+ int i;
+ FILE *dasm;
+ dasm = fopen("rsp_disasm.txt", "wt");
+
+ for (i=0; i < 0x1000; i+=4)
+ {
+ UINT32 opcode = ROPCODE(0x04001000 + i);
+ rsp_dasm_one(string, 0x04001000 + i, opcode);
+ fprintf(dasm, "%08X: %08X %s\n", 0x04001000 + i, opcode, string);
+ }
+ fclose(dasm);
+ }
+#endif
+#if SAVE_DMEM
+ {
+ int i;
+ FILE *dmem;
+#if 0
+ dmem = fopen("rsp_dmem.txt", "wt");
+
+ for (i=0; i < 0x1000; i+=4)
+ {
+ fprintf(dmem, "%08X: %08X\n", 0x04000000 + i, READ32(rsp, 0x04000000 + i));
+ }
+ fclose(dmem);
+#endif
+ dmem = fopen("rsp_dmem.bin", "wb");
+
+ for (i=0; i < 0x1000; i++)
+ {
+ fputc(READ8(rsp, 0x04000000 + i), dmem);
+ }
+ fclose(dmem);
+ }
+#endif
+
+ if (rsp->exec_output)
+ fclose(rsp->exec_output);
+ rsp->exec_output = NULL;
+}
+
+static CPU_RESET( rsp )
+{
+ rsp_state *rsp = get_safe_token(device);
+ rsp->nextpc = ~0;
+}
+
+static void handle_lwc2(rsp_state *rsp, UINT32 op)
+{
+ int i, end;
+ UINT32 ea;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ offset |= 0xffffffc0;
+
+ switch ((op >> 11) & 0x1f)
+ {
+ case 0x00: /* LBV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 00000 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Load 1 byte to vector byte index
+
+ ea = (base) ? rsp->r[base] + offset : offset;
+ VREG_B(dest, index) = READ8(rsp, ea);
+ break;
+ }
+ case 0x01: /* LSV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 00001 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads 2 bytes starting from vector byte index
+
+ ea = (base) ? rsp->r[base] + (offset * 2) : (offset * 2);
+
+ end = index + 2;
+
+ for (i=index; i < end; i++)
+ {
+ VREG_B(dest, i) = READ8(rsp, ea);
+ ea++;
+ }
+ break;
+ }
+ case 0x02: /* LLV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 00010 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads 4 bytes starting from vector byte index
+
+ ea = (base) ? rsp->r[base] + (offset * 4) : (offset * 4);
+
+ end = index + 4;
+
+ for (i=index; i < end; i++)
+ {
+ VREG_B(dest, i) = READ8(rsp, ea);
+ ea++;
+ }
+ break;
+ }
+ case 0x03: /* LDV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 00011 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads 8 bytes starting from vector byte index
+
+ ea = (base) ? rsp->r[base] + (offset * 8) : (offset * 8);
+
+ end = index + 8;
+
+ for (i=index; i < end; i++)
+ {
+ VREG_B(dest, i) = READ8(rsp, ea);
+ ea++;
+ }
+ break;
+ }
+ case 0x04: /* LQV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 00100 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads up to 16 bytes starting from vector byte index
+
+ ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
+
+ end = index + (16 - (ea & 0xf));
+ if (end > 16) end = 16;
+
+ for (i=index; i < end; i++)
+ {
+ VREG_B(dest, i) = READ8(rsp, ea);
+ ea++;
+ }
+ break;
+ }
+ case 0x05: /* LRV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 00101 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores up to 16 bytes starting from right side until 16-byte boundary
+
+ ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
+
+ index = 16 - ((ea & 0xf) - index);
+ end = 16;
+ ea &= ~0xf;
+
+ for (i=index; i < end; i++)
+ {
+ VREG_B(dest, i) = READ8(rsp, ea);
+ ea++;
+ }
+ break;
+ }
+ case 0x06: /* LPV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 00110 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads a byte as the upper 8 bits of each element
+
+ ea = (base) ? rsp->r[base] + (offset * 8) : (offset * 8);
+
+ for (i=0; i < 8; i++)
+ {
+ VREG_S(dest, i) = READ8(rsp, ea + (((16-index) + i) & 0xf)) << 8;
+ }
+ break;
+ }
+ case 0x07: /* LUV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 00111 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads a byte as the bits 14-7 of each element
+
+ ea = (base) ? rsp->r[base] + (offset * 8) : (offset * 8);
+
+ for (i=0; i < 8; i++)
+ {
+ VREG_S(dest, i) = READ8(rsp, ea + (((16-index) + i) & 0xf)) << 7;
+ }
+ break;
+ }
+ case 0x08: /* LHV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 01000 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads a byte as the bits 14-7 of each element, with 2-byte stride
+
+ ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
+
+ for (i=0; i < 8; i++)
+ {
+ VREG_S(dest, i) = READ8(rsp, ea + (((16-index) + (i<<1)) & 0xf)) << 7;
+ }
+ break;
+ }
+ case 0x09: /* LFV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 01001 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads a byte as the bits 14-7 of upper or lower quad, with 4-byte stride
+
+ ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
+
+ // not sure what happens if 16-byte boundary is crossed...
+
+ end = (index >> 1) + 4;
+
+ for (i=index >> 1; i < end; i++)
+ {
+ VREG_S(dest, i) = READ8(rsp, ea) << 7;
+ ea += 4;
+ }
+ break;
+ }
+ case 0x0a: /* LWV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 01010 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads the full 128-bit vector starting from vector byte index and wrapping to index 0
+ // after byte index 15
+
+ ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
+
+ // not sure what happens if 16-byte boundary is crossed...
+ if ((ea & 0xf) > 0) fatalerror("RSP: LWV: 16-byte boundary crossing at %08X, recheck this!\n", rsp->ppc);
+
+ end = (16 - index) + 16;
+
+ for (i=(16 - index); i < end; i++)
+ {
+ VREG_B(dest, i & 0xf) = READ8(rsp, ea);
+ ea += 4;
+ }
+ break;
+ }
+ case 0x0b: /* LTV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 01011 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads one element to maximum of 8 vectors, while incrementing element index
+
+ // FIXME: has a small problem with odd indices
+
+ int element;
+ int vs = dest;
+ int ve = dest + 8;
+ if (ve > 32)
+ ve = 32;
+
+ element = 7 - (index >> 1);
+
+ if (index & 1) fatalerror("RSP: LTV: index = %d\n", index);
+
+ ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
+
+ ea = ((ea + 8) & ~0xf) + (index & 1);
+ for (i=vs; i < ve; i++)
+ {
+ element = ((8 - (index >> 1) + (i-vs)) << 1);
+ VREG_B(i, (element & 0xf)) = READ8(rsp, ea);
+ VREG_B(i, ((element + 1) & 0xf)) = READ8(rsp, ea + 1);
+
+ ea += 2;
+ }
+ break;
+ }
+
+ default:
+ {
+ unimplemented_opcode(rsp, op);
+ break;
+ }
+ }
+}
+
+static void handle_swc2(rsp_state *rsp, UINT32 op)
+{
+ int i, end;
+ int eaoffset;
+ UINT32 ea;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ offset |= 0xffffffc0;
+
+ switch ((op >> 11) & 0x1f)
+ {
+ case 0x00: /* SBV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00000 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores 1 byte from vector byte index
+
+ ea = (base) ? rsp->r[base] + offset : offset;
+ WRITE8(rsp, ea, VREG_B(dest, index));
+ break;
+ }
+ case 0x01: /* SSV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00001 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores 2 bytes starting from vector byte index
+
+ ea = (base) ? rsp->r[base] + (offset * 2) : (offset * 2);
+
+ end = index + 2;
+
+ for (i=index; i < end; i++)
+ {
+ WRITE8(rsp, ea, VREG_B(dest, i));
+ ea++;
+ }
+ break;
+ }
+ case 0x02: /* SLV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00010 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores 4 bytes starting from vector byte index
+
+ ea = (base) ? rsp->r[base] + (offset * 4) : (offset * 4);
+
+ end = index + 4;
+
+ for (i=index; i < end; i++)
+ {
+ WRITE8(rsp, ea, VREG_B(dest, i));
+ ea++;
+ }
+ break;
+ }
+ case 0x03: /* SDV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00011 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores 8 bytes starting from vector byte index
+
+ ea = (base) ? rsp->r[base] + (offset * 8) : (offset * 8);
+
+ end = index + 8;
+
+ for (i=index; i < end; i++)
+ {
+ WRITE8(rsp, ea, VREG_B(dest, i));
+ ea++;
+ }
+ break;
+ }
+ case 0x04: /* SQV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00100 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores up to 16 bytes starting from vector byte index until 16-byte boundary
+
+ ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
+
+ end = index + (16 - (ea & 0xf));
+
+ for (i=index; i < end; i++)
+ {
+ WRITE8(rsp, ea, VREG_B(dest, i & 0xf));
+ ea++;
+ }
+ break;
+ }
+ case 0x05: /* SRV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00101 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores up to 16 bytes starting from right side until 16-byte boundary
+
+ int o;
+ ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
+
+ end = index + (ea & 0xf);
+ o = (16 - (ea & 0xf)) & 0xf;
+ ea &= ~0xf;
+
+ for (i=index; i < end; i++)
+ {
+ WRITE8(rsp, ea, VREG_B(dest, ((i + o) & 0xf)));
+ ea++;
+ }
+ break;
+ }
+ case 0x06: /* SPV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00110 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores upper 8 bits of each element
+
+ ea = (base) ? rsp->r[base] + (offset * 8) : (offset * 8);
+ end = index + 8;
+
+ for (i=index; i < end; i++)
+ {
+ if ((i & 0xf) < 8)
+ {
+ WRITE8(rsp, ea, VREG_B(dest, ((i & 0xf) << 1)));
+ }
+ else
+ {
+ WRITE8(rsp, ea, VREG_S(dest, (i & 0x7)) >> 7);
+ }
+ ea++;
+ }
+ break;
+ }
+ case 0x07: /* SUV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00111 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores bits 14-7 of each element
+
+ ea = (base) ? rsp->r[base] + (offset * 8) : (offset * 8);
+ end = index + 8;
+
+ for (i=index; i < end; i++)
+ {
+ if ((i & 0xf) < 8)
+ {
+ WRITE8(rsp, ea, VREG_S(dest, (i & 0x7)) >> 7);
+ }
+ else
+ {
+ WRITE8(rsp, ea, VREG_B(dest, ((i & 0x7) << 1)));
+ }
+ ea++;
+ }
+ break;
+ }
+ case 0x08: /* SHV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 01000 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores bits 14-7 of each element, with 2-byte stride
+
+ ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
+
+ for (i=0; i < 8; i++)
+ {
+ UINT8 d = ((VREG_B(dest, ((index + (i << 1) + 0) & 0xf))) << 1) |
+ ((VREG_B(dest, ((index + (i << 1) + 1) & 0xf))) >> 7);
+
+ WRITE8(rsp, ea, d);
+ ea += 2;
+ }
+ break;
+ }
+ case 0x09: /* SFV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 01001 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores bits 14-7 of upper or lower quad, with 4-byte stride
+
+ // FIXME: only works for index 0 and index 8
+
+ if (index & 0x7) mame_printf_debug("RSP: SFV: index = %d at %08X\n", index, rsp->ppc);
+
+ ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
+
+ eaoffset = ea & 0xf;
+ ea &= ~0xf;
+
+ end = (index >> 1) + 4;
+
+ for (i=index >> 1; i < end; i++)
+ {
+ WRITE8(rsp, ea + (eaoffset & 0xf), VREG_S(dest, i) >> 7);
+ eaoffset += 4;
+ }
+ break;
+ }
+ case 0x0a: /* SWV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 01010 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores the full 128-bit vector starting from vector byte index and wrapping to index 0
+ // after byte index 15
+
+ ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
+
+ eaoffset = ea & 0xf;
+ ea &= ~0xf;
+
+ end = index + 16;
+
+ for (i=index; i < end; i++)
+ {
+ WRITE8(rsp, ea + (eaoffset & 0xf), VREG_B(dest, i & 0xf));
+ eaoffset++;
+ }
+ break;
+ }
+ case 0x0b: /* STV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 01011 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores one element from maximum of 8 vectors, while incrementing element index
+
+ int element;
+ int vs = dest;
+ int ve = dest + 8;
+ if (ve > 32)
+ ve = 32;
+
+ element = 8 - (index >> 1);
+
+ ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
+
+ eaoffset = (ea & 0xf) + (element * 2);
+ ea &= ~0xf;
+
+ for (i=vs; i < ve; i++)
+ {
+ WRITE16(rsp, ea + (eaoffset & 0xf), VREG_S(i, element & 0x7));
+ eaoffset += 2;
+ element++;
+ }
+ break;
+ }
+
+ default:
+ {
+ unimplemented_opcode(rsp, op);
+ break;
+ }
+ }
+}
+
+INLINE UINT16 SATURATE_ACCUM(rsp_state *rsp, int accum, int slice, UINT16 negative, UINT16 positive)
+{
+ if ((INT16)ACCUM_H(accum) < 0)
+ {
+ if ((UINT16)(ACCUM_H(accum)) != 0xffff)
+ {
+ return negative;
+ }
+ else
+ {
+ if ((INT16)ACCUM_M(accum) >= 0)
+ {
+ return negative;
+ }
+ else
+ {
+ if (slice == 0)
+ {
+ return ACCUM_L(accum);
+ }
+ else if (slice == 1)
+ {
+ return ACCUM_M(accum);
+ }
+ }
+ }
+ }
+ else
+ {
+ if ((UINT16)(ACCUM_H(accum)) != 0)
+ {
+ return positive;
+ }
+ else
+ {
+ if ((INT16)ACCUM_M(accum) < 0)
+ {
+ return positive;
+ }
+ else
+ {
+ if (slice == 0)
+ {
+ return ACCUM_L(accum);
+ }
+ else
+ {
+ return ACCUM_M(accum);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+INLINE UINT16 SATURATE_ACCUM1(rsp_state *rsp, int accum, UINT16 negative, UINT16 positive)
+{
+ if ((INT16)ACCUM_H(accum) < 0)
+ {
+ if ((UINT16)(ACCUM_H(accum)) != 0xffff)
+ {
+ return negative;
+ }
+ else
+ {
+ if ((INT16)ACCUM_M(accum) >= 0)
+ {
+ return negative;
+ }
+ else
+ {
+ return ACCUM_M(accum);
+ }
+ }
+ }
+ else
+ {
+ if ((UINT16)(ACCUM_H(accum)) != 0)
+ {
+ return positive;
+ }
+ else
+ {
+ if ((INT16)ACCUM_M(accum) < 0)
+ {
+ return positive;
+ }
+ else
+ {
+ return ACCUM_M(accum);
+ }
+ }
+ }
+
+ return 0;
+}
+
+#define WRITEBACK_RESULT() {memcpy(&rsp->v[VDREG].s[0], &vres[0], 16);}
+
+#if 0
+static float float_round(float input)
+{
+ INT32 integer = (INT32)input;
+ float fraction = input - (float)integer;
+ float output = 0.0f;
+ if( fraction >= 0.5f )
+ {
+ output = (float)( integer + 1 );
+ }
+ else
+ {
+ output = (float)integer;
+ }
+ return output;
+}
+#endif
+
+static void handle_vector_ops(rsp_state *rsp, UINT32 op)
+{
+ int i;
+ UINT32 VS1REG = (op >> 11) & 0x1f;
+ UINT32 VS2REG = (op >> 16) & 0x1f;
+ UINT32 VDREG = (op >> 6) & 0x1f;
+ UINT32 EL = (op >> 21) & 0xf;
+ INT16 vres[8];
+
+ // Opcode legend:
+ // E = VS2 element type
+ // S = VS1, Source vector 1
+ // T = VS2, Source vector 2
+ // D = Destination vector
+
+ switch (op & 0x3f)
+ {
+ case 0x00: /* VMULF */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000000 |
+ // ------------------------------------------------------
+ //
+ // Multiplies signed integer by signed integer * 2
+
+ int sel;
+ INT32 s1, s2;
+ INT64 r;
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ s2 = (INT32)(INT16)VREG_S(VS2REG, sel);
+ if (s1 == -32768 && s2 == -32768)
+ {
+ // overflow
+ ACCUM_H(i) = 0;
+ ACCUM_M(i) = -32768;
+ ACCUM_L(i) = -32768;
+ vres[i] = 0x7fff;
+ }
+ else
+ {
+ r = s1 * s2 * 2;
+ r += 0x8000; // rounding ?
+ ACCUM_H(i) = (r < 0) ? 0xffff : 0; // sign-extend to 48-bit
+ ACCUM_M(i) = (INT16)(r >> 16);
+ ACCUM_L(i) = (UINT16)(r);
+ vres[i] = ACCUM_M(i);
+ }
+ }
+ WRITEBACK_RESULT();
+
+ break;
+ }
+
+ case 0x01: /* VMULU */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000001 |
+ // ------------------------------------------------------
+ //
+
+ int sel;
+ INT32 s1, s2;
+ INT64 r;
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ s2 = (INT32)(INT16)VREG_S(VS2REG, sel);
+ r = s1 * s2 * 2;
+ r += 0x8000; // rounding ?
+
+ ACCUM_H(i) = (UINT16)(r >> 32);
+ ACCUM_M(i) = (UINT16)(r >> 16);
+ ACCUM_L(i) = (UINT16)(r);
+
+ if (r < 0)
+ {
+ vres[i] = 0;
+ }
+ else if (((INT16)(ACCUM_H(i)) ^ (INT16)(ACCUM_M(i))) < 0)
+ {
+ vres[i] = -1;
+ }
+ else
+ {
+ vres[i] = ACCUM_M(i);
+ }
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x04: /* VMUDL */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000100 |
+ // ------------------------------------------------------
+ //
+ // Multiplies unsigned fraction by unsigned fraction
+ // Stores the higher 16 bits of the 32-bit result to accumulator
+ // The low slice of accumulator is stored into destination element
+
+ int sel;
+ UINT32 s1, s2;
+ UINT32 r;
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (UINT32)(UINT16)VREG_S(VS1REG, i);
+ s2 = (UINT32)(UINT16)VREG_S(VS2REG, sel);
+ r = s1 * s2;
+
+ ACCUM_H(i) = 0;
+ ACCUM_M(i) = 0;
+ ACCUM_L(i) = (UINT16)(r >> 16);
+
+ vres[i] = ACCUM_L(i);
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x05: /* VMUDM */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000101 |
+ // ------------------------------------------------------
+ //
+ // Multiplies signed integer by unsigned fraction
+ // The result is stored into accumulator
+ // The middle slice of accumulator is stored into destination element
+
+ int sel;
+ INT32 s1, s2;
+ INT32 r;
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ s2 = (UINT16)VREG_S(VS2REG, sel); // not sign-extended
+ r = s1 * s2;
+
+ ACCUM_H(i) = (r < 0) ? 0xffff : 0; // sign-extend to 48-bit
+ ACCUM_M(i) = (INT16)(r >> 16);
+ ACCUM_L(i) = (UINT16)(r);
+
+ vres[i] = ACCUM_M(i);
+ }
+ WRITEBACK_RESULT();
+ break;
+
+ }
+
+ case 0x06: /* VMUDN */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000110 |
+ // ------------------------------------------------------
+ //
+ // Multiplies unsigned fraction by signed integer
+ // The result is stored into accumulator
+ // The low slice of accumulator is stored into destination element
+
+ int sel;
+ INT32 s1, s2;
+ INT32 r;
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (UINT16)VREG_S(VS1REG, i); // not sign-extended
+ s2 = (INT32)(INT16)VREG_S(VS2REG, sel);
+ r = s1 * s2;
+
+ ACCUM_H(i) = (r < 0) ? 0xffff : 0; // sign-extend to 48-bit
+ ACCUM_M(i) = (INT16)(r >> 16);
+ ACCUM_L(i) = (UINT16)(r);
+
+ vres[i] = ACCUM_L(i);
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x07: /* VMUDH */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000111 |
+ // ------------------------------------------------------
+ //
+ // Multiplies signed integer by signed integer
+ // The result is stored into highest 32 bits of accumulator, the low slice is zero
+ // The highest 32 bits of accumulator is saturated into destination element
+
+ int sel;
+ INT32 s1, s2;
+ INT32 r;
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ s2 = (INT32)(INT16)VREG_S(VS2REG, sel);
+ r = s1 * s2;
+
+ ACCUM_H(i) = (INT16)(r >> 16);
+ ACCUM_M(i) = (UINT16)(r);
+ ACCUM_L(i) = 0;
+
+ if (r < -32768) r = -32768;
+ if (r > 32767) r = 32767;
+ vres[i] = (INT16)(r);
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x08: /* VMACF */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001000 |
+ // ------------------------------------------------------
+ //
+ // Multiplies signed integer by signed integer * 2
+ // The result is added to accumulator
+
+ int sel;
+ INT32 s1, s2;
+ INT32 r;
+ UINT16 res;
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ s2 = (INT32)(INT16)VREG_S(VS2REG, sel);
+ r = s1 * s2;
+
+ ACCUM(i) += (INT64)(r) << 17;
+ res = SATURATE_ACCUM(rsp, i, 1, 0x8000, 0x7fff);
+
+ vres[i] = res;
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x09: /* VMACU */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001001 |
+ // ------------------------------------------------------
+ //
+
+ UINT16 res;
+ int sel;
+ INT32 s1, s2, r1;
+ UINT32 r2, r3;
+ for (i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ s2 = (INT32)(INT16)VREG_S(VS2REG, sel);
+ r1 = s1 * s2;
+ r2 = (UINT16)ACCUM_L(i) + ((UINT16)(r1) * 2);
+ r3 = (UINT16)ACCUM_M(i) + (UINT16)((r1 >> 16) * 2) + (UINT16)(r2 >> 16);
+
+ ACCUM_L(i) = (UINT16)(r2);
+ ACCUM_M(i) = (UINT16)(r3);
+ ACCUM_H(i) += (UINT16)(r3 >> 16) + (UINT16)(r1 >> 31);
+
+ //res = SATURATE_ACCUM(i, 1, 0x0000, 0xffff);
+ if ((INT16)ACCUM_H(i) < 0)
+ {
+ res = 0;
+ }
+ else
+ {
+ if (ACCUM_H(i) != 0)
+ {
+ res = 0xffff;
+ }
+ else
+ {
+ if ((INT16)ACCUM_M(i) < 0)
+ {
+ res = 0xffff;
+ }
+ else
+ {
+ res = ACCUM_M(i);
+ }
+ }
+ }
+
+ vres[i] = res;
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x0c: /* VMADL */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001100 |
+ // ------------------------------------------------------
+ //
+ // Multiplies unsigned fraction by unsigned fraction
+ // Adds the higher 16 bits of the 32-bit result to accumulator
+ // The low slice of accumulator is stored into destination element
+
+ UINT16 res;
+ int sel;
+ UINT32 s1, s2, r1;
+ UINT32 r2, r3;
+ for (i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (UINT32)(UINT16)VREG_S(VS1REG, i);
+ s2 = (UINT32)(UINT16)VREG_S(VS2REG, sel);
+ r1 = s1 * s2;
+ r2 = (UINT16)ACCUM_L(i) + (r1 >> 16);
+ r3 = (UINT16)ACCUM_M(i) + (r2 >> 16);
+
+ ACCUM_L(i) = (UINT16)(r2);
+ ACCUM_M(i) = (UINT16)(r3);
+ ACCUM_H(i) += (INT16)(r3 >> 16);
+
+ res = SATURATE_ACCUM(rsp, i, 0, 0x0000, 0xffff);
+
+ vres[i] = res;
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x0d: /* VMADM */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001101 |
+ // ------------------------------------------------------
+ //
+ // Multiplies signed integer by unsigned fraction
+ // The result is added into accumulator
+ // The middle slice of accumulator is stored into destination element
+
+ UINT16 res;
+ int sel;
+ UINT32 s1, s2, r1;
+ UINT32 r2, r3;
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ s2 = (UINT16)VREG_S(VS2REG, sel); // not sign-extended
+ r1 = s1 * s2;
+ r2 = (UINT16)ACCUM_L(i) + (UINT16)(r1);
+ r3 = (UINT16)ACCUM_M(i) + (r1 >> 16) + (r2 >> 16);
+
+ ACCUM_L(i) = (UINT16)(r2);
+ ACCUM_M(i) = (UINT16)(r3);
+ ACCUM_H(i) += (UINT16)(r3 >> 16);
+ if ((INT32)(r1) < 0)
+ ACCUM_H(i) -= 1;
+
+ res = SATURATE_ACCUM(rsp, i, 1, 0x8000, 0x7fff);
+
+ vres[i] = res;
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x0e: /* VMADN */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001110 |
+ // ------------------------------------------------------
+ //
+ // Multiplies unsigned fraction by signed integer
+ // The result is added into accumulator
+ // The low slice of accumulator is stored into destination element
+
+ INT32 s1, s2;
+ UINT16 res;
+ int sel;
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (UINT16)VREG_S(VS1REG, i); // not sign-extended
+ s2 = (INT32)(INT16)VREG_S(VS2REG, sel);
+
+ ACCUM(i) += (INT64)(s1*s2)<<16;
+
+ res = SATURATE_ACCUM(rsp, i, 0, 0x0000, 0xffff);
+ vres[i] = res;
+ }
+ WRITEBACK_RESULT();
+
+ break;
+ }
+
+ case 0x0f: /* VMADH */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001111 |
+ // ------------------------------------------------------
+ //
+ // Multiplies signed integer by signed integer
+ // The result is added into highest 32 bits of accumulator, the low slice is zero
+ // The highest 32 bits of accumulator is saturated into destination element
+
+ UINT16 res;
+ int sel;
+ INT32 s1, s2;
+ for (i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ s2 = (INT32)(INT16)VREG_S(VS2REG, sel);
+
+ rsp->accum[i].l[1] += s1*s2;
+
+ res = SATURATE_ACCUM1(rsp, i, 0x8000, 0x7fff);
+
+ vres[i] = res;
+ }
+ WRITEBACK_RESULT();
+
+ break;
+ }
+
+ case 0x10: /* VADD */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010000 |
+ // ------------------------------------------------------
+ //
+ // Adds two vector registers and carry flag, the result is saturated to 32767
+
+ // TODO: check VS2REG == VDREG
+
+ int sel;
+ INT32 s1, s2, r;
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ s2 = (INT32)(INT16)VREG_S(VS2REG, sel);
+ r = s1 + s2 + CARRY_FLAG(i);
+
+ ACCUM_L(i) = (INT16)(r);
+
+ if (r > 32767) r = 32767;
+ if (r < -32768) r = -32768;
+ vres[i] = (INT16)(r);
+ }
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x11: /* VSUB */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010001 |
+ // ------------------------------------------------------
+ //
+ // Subtracts two vector registers and carry flag, the result is saturated to -32768
+
+ // TODO: check VS2REG == VDREG
+
+ int sel;
+ INT32 s1, s2, r;
+ for (i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ s2 = (INT32)(INT16)VREG_S(VS2REG, sel);
+ r = s1 - s2 - CARRY_FLAG(i);
+
+ ACCUM_L(i) = (INT16)(r);
+
+ if (r > 32767) r = 32767;
+ if (r < -32768) r = -32768;
+
+ vres[i] = (INT16)(r);
+ }
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x13: /* VABS */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010011 |
+ // ------------------------------------------------------
+ //
+ // Changes the sign of source register 2 if source register 1 is negative and stores
+ // the result to destination register
+
+ int sel;
+ INT16 s1, s2;
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (INT16)VREG_S(VS1REG, i);
+ s2 = (INT16)VREG_S(VS2REG, sel);
+
+ if (s1 < 0)
+ {
+ if (s2 == -32768)
+ {
+ vres[i] = 32767;
+ }
+ else
+ {
+ vres[i] = -s2;
+ }
+ }
+ else if (s1 > 0)
+ {
+ vres[i] = s2;
+ }
+ else
+ {
+ vres[i] = 0;
+ }
+
+ ACCUM_L(i) = vres[i];
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x14: /* VADDC */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010100 |
+ // ------------------------------------------------------
+ //
+ // Adds two vector registers, the carry out is stored into carry register
+
+ // TODO: check VS2REG = VDREG
+
+ int sel;
+ INT32 s1, s2, r;
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (UINT32)(UINT16)VREG_S(VS1REG, i);
+ s2 = (UINT32)(UINT16)VREG_S(VS2REG, sel);
+ r = s1 + s2;
+
+ vres[i] = (INT16)(r);
+ ACCUM_L(i) = (INT16)(r);
+
+ if (r & 0xffff0000)
+ {
+ SET_CARRY_FLAG(i);
+ }
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x15: /* VSUBC */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010101 |
+ // ------------------------------------------------------
+ //
+ // Subtracts two vector registers, the carry out is stored into carry register
+
+ // TODO: check VS2REG = VDREG
+
+ int sel;
+ INT32 s1, s2, r;
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (UINT32)(UINT16)VREG_S(VS1REG, i);
+ s2 = (UINT32)(UINT16)VREG_S(VS2REG, sel);
+ r = s1 - s2;
+
+ vres[i] = (INT16)(r);
+ ACCUM_L(i) = (UINT16)(r);
+
+ if ((UINT16)(r) != 0)
+ {
+ SET_ZERO_FLAG(i);
+ }
+ if (r & 0xffff0000)
+ {
+ SET_CARRY_FLAG(i);
+ }
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x1d: /* VSAW */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 011101 |
+ // ------------------------------------------------------
+ //
+ // Stores high, middle or low slice of accumulator to destination vector
+
+ switch (EL)
+ {
+ case 0x08: // VSAWH
+ {
+ for (i=0; i < 8; i++)
+ {
+ VREG_S(VDREG, i) = ACCUM_H(i);
+ }
+ break;
+ }
+ case 0x09: // VSAWM
+ {
+ for (i=0; i < 8; i++)
+ {
+ VREG_S(VDREG, i) = ACCUM_M(i);
+ }
+ break;
+ }
+ case 0x0a: // VSAWL
+ {
+ for (i=0; i < 8; i++)
+ {
+ VREG_S(VDREG, i) = ACCUM_L(i);
+ }
+ break;
+ }
+ default: //fatalerror("RSP: VSAW: el = %d\n", EL);//???????
+ printf("RSP: VSAW: el = %d\n", EL);//??? ???
+ exit(0);
+ }
+ break;
+ }
+
+ case 0x20: /* VLT */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100000 |
+ // ------------------------------------------------------
+ //
+ // Sets compare flags if elements in VS1 are less than VS2
+ // Moves the element in VS2 to destination vector
+
+ int sel;
+ rsp->flag[1] = 0;
+
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+
+ if (VREG_S(VS1REG, i) < VREG_S(VS2REG, sel))
+ {
+ SET_COMPARE_FLAG(i);
+ }
+ else if (VREG_S(VS1REG, i) == VREG_S(VS2REG, sel))
+ {
+ if (ZERO_FLAG(i) == 1 && CARRY_FLAG(i) != 0)
+ {
+ SET_COMPARE_FLAG(i);
+ }
+ }
+
+ if (COMPARE_FLAG(i))
+ {
+ vres[i] = VREG_S(VS1REG, i);
+ }
+ else
+ {
+ vres[i] = VREG_S(VS2REG, sel);
+ }
+
+ ACCUM_L(i) = vres[i];
+ }
+
+ rsp->flag[0] = 0;
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x21: /* VEQ */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100001 |
+ // ------------------------------------------------------
+ //
+ // Sets compare flags if elements in VS1 are equal with VS2
+ // Moves the element in VS2 to destination vector
+
+ int sel;
+ rsp->flag[1] = 0;
+
+ for (i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+
+ if ((VREG_S(VS1REG, i) == VREG_S(VS2REG, sel)) && ZERO_FLAG(i) == 0)
+ {
+ SET_COMPARE_FLAG(i);
+ vres[i] = VREG_S(VS1REG, i);
+ }
+ else
+ {
+ vres[i] = VREG_S(VS2REG, sel);
+ }
+ ACCUM_L(i) = vres[i];
+ }
+
+ rsp->flag[0] = 0;
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x22: /* VNE */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100010 |
+ // ------------------------------------------------------
+ //
+ // Sets compare flags if elements in VS1 are not equal with VS2
+ // Moves the element in VS2 to destination vector
+
+ int sel;
+ rsp->flag[1] = 0;
+
+ for (i=0; i < 8; i++)//?????????? ????
+ {
+ sel = VEC_EL_2(EL, i);
+
+ if (VREG_S(VS1REG, i) != VREG_S(VS2REG, sel))
+ {
+ SET_COMPARE_FLAG(i);
+ }
+ else
+ {
+ if (ZERO_FLAG(i) == 1)
+ {
+ SET_COMPARE_FLAG(i);
+ }
+ }
+ if (COMPARE_FLAG(i))
+ {
+ vres[i] = VREG_S(VS1REG, i);
+ }
+ else
+ {
+ vres[i] = VREG_S(VS2REG, sel);
+ }
+ ACCUM_L(i) = vres[i];
+ }
+
+ rsp->flag[0] = 0;
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x23: /* VGE */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100011 |
+ // ------------------------------------------------------
+ //
+ // Sets compare flags if elements in VS1 are greater or equal with VS2
+ // Moves the element in VS2 to destination vector
+
+ int sel;
+ rsp->flag[1] = 0;
+
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+
+ if (VREG_S(VS1REG, i) == VREG_S(VS2REG, sel))
+ {
+ if (ZERO_FLAG(i) == 0 || CARRY_FLAG(i) == 0)
+ {
+ SET_COMPARE_FLAG(i);
+ }
+ }
+ else if (VREG_S(VS1REG, i) > VREG_S(VS2REG, sel))
+ {
+ SET_COMPARE_FLAG(i);
+ }
+
+ if (COMPARE_FLAG(i) != 0)
+ {
+ vres[i] = VREG_S(VS1REG, i);
+ }
+ else
+ {
+ vres[i] = VREG_S(VS2REG, sel);
+ }
+
+ ACCUM_L(i) = vres[i];
+ }
+
+ rsp->flag[0] = 0;
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x24: /* VCL */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100100 |
+ // ------------------------------------------------------
+ //
+ // Vector clip low
+
+ int sel;
+ INT16 s1, s2;
+ for (i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = VREG_S(VS1REG, i);
+ s2 = VREG_S(VS2REG, sel);
+
+ if (CARRY_FLAG(i) != 0)
+ {
+
+ if (ZERO_FLAG(i) != 0)
+ {
+
+ if (COMPARE_FLAG(i) != 0)
+ {
+ ACCUM_L(i) = -(UINT16)s2;
+ }
+ else
+ {
+ ACCUM_L(i) = s1;
+ }
+ }
+ else//ZERO_FLAG(i)==0
+ {
+
+ if (rsp->flag[2] & (1 << (i)))
+ {
+
+ if (((UINT32)(UINT16)(s1) + (UINT32)(UINT16)(s2)) > 0x10000)
+ {//proper fix for Harvest Moon 64, r4
+
+ ACCUM_L(i) = s1;
+ CLEAR_COMPARE_FLAG(i);
+ }
+ else
+ {
+
+ ACCUM_L(i) = -((UINT16)s2);
+ SET_COMPARE_FLAG(i);
+ }
+ }
+ else
+ {
+ if (((UINT32)(UINT16)(s1) + (UINT32)(UINT16)(s2)) != 0)
+ {
+ ACCUM_L(i) = s1;
+ CLEAR_COMPARE_FLAG(i);
+ }
+ else
+ {
+ ACCUM_L(i) = -((UINT16)s2);
+ SET_COMPARE_FLAG(i);
+ }
+ }
+ }
+ }//
+ else//CARRY_FLAG(i)==0
+ {
+
+ if (ZERO_FLAG(i) != 0)
+ {
+
+ if (rsp->flag[1] & (1 << (8+i)))
+ {
+ ACCUM_L(i) = s2;
+ }
+ else
+ {
+ ACCUM_L(i) = s1;
+ }
+ }
+ else
+ {
+ if (((INT32)(UINT16)s1 - (INT32)(UINT16)s2) >= 0)
+ {
+ ACCUM_L(i) = s2;
+ rsp->flag[1] |= (1 << (8+i));
+ }
+ else
+ {
+ ACCUM_L(i) = s1;
+ rsp->flag[1] &= ~(1 << (8+i));
+ }
+ }
+ }
+
+ vres[i] = ACCUM_L(i);
+ }
+ rsp->flag[0] = 0;
+ rsp->flag[2] = 0;
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x25: /* VCH */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100101 |
+ // ------------------------------------------------------
+ //
+ // Vector clip high
+
+ int sel;
+ INT16 s1, s2;
+ rsp->flag[0] = 0;
+ rsp->flag[1] = 0;
+ rsp->flag[2] = 0;
+ UINT32 vce = 0;
+
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = VREG_S(VS1REG, i);
+ s2 = VREG_S(VS2REG, sel);
+
+ if ((s1 ^ s2) < 0)
+ {
+ vce = (s1 + s2 == -1);
+ SET_CARRY_FLAG(i);
+ if (s2 < 0)
+ {
+ rsp->flag[1] |= (1 << (8+i));
+ }
+
+ if (s1 + s2 <= 0)
+ {
+ SET_COMPARE_FLAG(i);
+ vres[i] = -((UINT16)s2);
+ }
+ else
+ {
+ vres[i] = s1;
+ }
+
+ if (s1 + s2 != 0)
+ {
+ if (s1 != ~s2)
+ {
+ SET_ZERO_FLAG(i);
+ }
+ }
+ }//sign
+ else
+ {
+ vce = 0;
+ if (s2 < 0)
+ {
+ SET_COMPARE_FLAG(i);
+ }
+ if (s1 - s2 >= 0)
+ {
+ rsp->flag[1] |= (1 << (8+i));
+ vres[i] = s2;
+ }
+ else
+ {
+ vres[i] = s1;
+ }
+
+ if ((s1 - s2) != 0)
+ {
+ if (s1 != ~s2)
+ {
+ SET_ZERO_FLAG(i);
+ }
+ }
+ }
+ rsp->flag[2] |= (vce << (i));
+ ACCUM_L(i) = vres[i];
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x26: /* VCR */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100110 |
+ // ------------------------------------------------------
+ //
+ // Vector clip reverse
+
+ int sel;
+ INT16 s1, s2;
+ rsp->flag[0] = 0;
+ rsp->flag[1] = 0;
+ rsp->flag[2] = 0;
+
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = VREG_S(VS1REG, i);
+ s2 = VREG_S(VS2REG, sel);
+
+ if ((INT16)(s1 ^ s2) < 0)
+ {
+ if (s2 < 0)
+ {
+ rsp->flag[1] |= (1 << (8+i));
+ }
+ if ((s1 + s2) <= 0)
+ {
+ ACCUM_L(i) = ~((UINT16)s2);
+ SET_COMPARE_FLAG(i);
+ }
+ else
+ {
+ ACCUM_L(i) = s1;
+ }
+ }
+ else
+ {
+ if (s2 < 0)
+ {
+ SET_COMPARE_FLAG(i);
+ }
+ if ((s1 - s2) >= 0)
+ {
+ ACCUM_L(i) = s2;
+ rsp->flag[1] |= (1 << (8+i));
+ }
+ else
+ {
+ ACCUM_L(i) = s1;
+ }
+ }
+
+ vres[i] = ACCUM_L(i);
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x27: /* VMRG */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100111 |
+ // ------------------------------------------------------
+ //
+ // Merges two vectors according to compare flags
+
+ int sel;
+ for (i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ if (COMPARE_FLAG(i) != 0)
+ {
+ vres[i] = VREG_S(VS1REG, i);
+ }
+ else
+ {
+ vres[i] = VREG_S(VS2REG, sel);//??? ???????????
+ }
+
+ ACCUM_L(i) = vres[i];
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+ case 0x28: /* VAND */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101000 |
+ // ------------------------------------------------------
+ //
+ // Bitwise AND of two vector registers
+
+ int sel;
+ for (i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ vres[i] = VREG_S(VS1REG, i) & VREG_S(VS2REG, sel);
+ ACCUM_L(i) = vres[i];
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+ case 0x29: /* VNAND */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101001 |
+ // ------------------------------------------------------
+ //
+ // Bitwise NOT AND of two vector registers
+
+ int sel;
+ for (i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ vres[i] = ~((VREG_S(VS1REG, i) & VREG_S(VS2REG, sel)));
+ ACCUM_L(i) = vres[i];
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+ case 0x2a: /* VOR */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101010 |
+ // ------------------------------------------------------
+ //
+ // Bitwise OR of two vector registers
+
+ int sel;
+ for (i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ vres[i] = VREG_S(VS1REG, i) | VREG_S(VS2REG, sel);
+ ACCUM_L(i) = vres[i];
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+ case 0x2b: /* VNOR */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101011 |
+ // ------------------------------------------------------
+ //
+ // Bitwise NOT OR of two vector registers
+
+ int sel;
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ vres[i] = ~((VREG_S(VS1REG, i) | VREG_S(VS2REG, sel)));
+ ACCUM_L(i) = vres[i];
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+ case 0x2c: /* VXOR */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101100 |
+ // ------------------------------------------------------
+ //
+ // Bitwise XOR of two vector registers
+
+ int sel;
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ vres[i] = VREG_S(VS1REG, i) ^ VREG_S(VS2REG, sel);
+ ACCUM_L(i) = vres[i];
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+ case 0x2d: /* VNXOR */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101101 |
+ // ------------------------------------------------------
+ //
+ // Bitwise NOT XOR of two vector registers
+
+ int sel;
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ vres[i] = ~((VREG_S(VS1REG, i) ^ VREG_S(VS2REG, sel)));
+ ACCUM_L(i) = vres[i];
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x30: /* VRCP */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110000 |
+ // ------------------------------------------------------
+ //
+ // Calculates reciprocal
+ int del = VS1REG & 7;
+ int sel = EL & 7;
+ INT32 shifter = 0;
+
+ INT32 rec = (INT16)(VREG_S(VS2REG, sel));
+ INT32 datainput = (rec < 0) ? (-rec) : rec;
+ if (datainput)
+ {
+ for (i = 0; i < 32; i++)
+ {
+ if (datainput & (1 << ((~i) & 0x1f)))//?.?.??? 31 - i
+ {
+ shifter = i;
+ break;
+ }
+ }
+ }
+ else
+ {
+ shifter = 0x10;
+ }
+
+ INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22;
+ INT32 fetchval = rsp_divtable[address];
+ INT32 temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f);
+ if (rec < 0)
+ {
+ temp = ~temp;
+ }
+ if (!rec)
+ {
+ temp = 0x7fffffff;
+ }
+ else if (rec == 0xffff8000)
+ {
+ temp = 0xffff0000;
+ }
+ rec = temp;
+
+ rsp->reciprocal_res = rec;
+ rsp->dp_allowed = 0;
+
+ VREG_S(VDREG, del) = (UINT16)(rec & 0xffff);
+
+ for (i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ ACCUM_L(i) = VREG_S(VS2REG, sel);
+ }
+
+
+ break;
+ }
+
+ case 0x31: /* VRCPL */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110001 |
+ // ------------------------------------------------------
+ //
+ // Calculates reciprocal low part
+
+ int del = VS1REG & 7;
+ int sel = EL & 7;
+ INT32 shifter = 0;
+
+ INT32 rec = ((UINT16)(VREG_S(VS2REG, sel)) | ((UINT32)(rsp->reciprocal_high) & 0xffff0000));
+
+ INT32 datainput = rec;
+
+ if (rec < 0)
+ {
+ if (rsp->dp_allowed)
+ {
+ if (rec < -32768)
+ {
+ datainput = ~datainput;
+ }
+ else
+ {
+ datainput = -datainput;
+ }
+ }
+ else
+ {
+ datainput = -datainput;
+ }
+ }
+
+
+ if (datainput)
+ {
+ for (i = 0; i < 32; i++)
+ {
+ if (datainput & (1 << ((~i) & 0x1f)))//?.?.??? 31 - i
+ {
+ shifter = i;
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (rsp->dp_allowed)
+ {
+ shifter = 0;
+ }
+ else
+ {
+ shifter = 0x10;
+ }
+ }
+
+ INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22;
+ INT32 fetchval = rsp_divtable[address];
+ INT32 temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f);
+ if (rec < 0)
+ {
+ temp = ~temp;
+ }
+ if (!rec)
+ {
+ temp = 0x7fffffff;
+ }
+ else if (rec == 0xffff8000)
+ {
+ temp = 0xffff0000;
+ }
+ rec = temp;
+
+ rsp->reciprocal_res = rec;
+ rsp->dp_allowed = 0;
+
+ VREG_S(VDREG, del) = (UINT16)(rec & 0xffff);
+
+ for (i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ ACCUM_L(i) = VREG_S(VS2REG, sel);
+ }
+
+ break;
+ }
+
+ case 0x32: /* VRCPH */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110010 |
+ // ------------------------------------------------------
+ //
+ // Calculates reciprocal high part
+
+ int del = VS1REG & 7;
+ int sel = EL & 7;
+
+ rsp->reciprocal_high = (VREG_S(VS2REG, sel)) << 16;
+ rsp->dp_allowed = 1;
+
+ for (i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ ACCUM_L(i) = VREG_S(VS2REG, sel);
+ }
+
+ VREG_S(VDREG, del) = (INT16)(rsp->reciprocal_res >> 16);
+
+ break;
+ }
+
+ case 0x33: /* VMOV */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110011 |
+ // ------------------------------------------------------
+ //
+ // Moves element from vector to destination vector
+
+ int del = VS1REG & 7;
+ int sel = EL & 7;
+
+ VREG_S(VDREG, del) = VREG_S(VS2REG, sel);
+ for (i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ ACCUM_L(i) = VREG_S(VS2REG, sel);
+ }
+ break;
+ }
+
+ case 0x34: /* VRSQ */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110100 |
+ // ------------------------------------------------------
+ //
+ // Calculates reciprocal square-root
+
+ int del = VS1REG & 7;
+ int sel = EL & 7;
+ INT32 shifter = 0;
+
+ INT32 rec = (INT16)(VREG_S(VS2REG, sel));
+ INT32 datainput = (rec < 0) ? (-rec) : rec;
+ if (datainput)
+ {
+ for (i = 0; i < 32; i++)
+ {
+ if (datainput & (1 << ((~i) & 0x1f)))//?.?.??? 31 - i
+ {
+ shifter = i;
+ break;
+ }
+ }
+ }
+ else
+ {
+ shifter = 0x10;
+ }
+
+ INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22;
+ address = ((address | 0x200) & 0x3fe) | (shifter & 1);
+
+ INT32 fetchval = rsp_divtable[address];
+ INT32 temp = (0x40000000 | (fetchval << 14)) >> (((~shifter) & 0x1f) >> 1);
+ if (rec < 0)
+ {
+ temp = ~temp;
+ }
+ if (!rec)
+ {
+ temp = 0x7fffffff;
+ }
+ else if (rec == 0xffff8000)
+ {
+ temp = 0xffff0000;
+ }
+ rec = temp;
+
+ rsp->reciprocal_res = rec;
+ rsp->dp_allowed = 0;
+
+ VREG_S(VDREG, del) = (UINT16)(rec & 0xffff);
+
+ for (i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ ACCUM_L(i) = VREG_S(VS2REG, sel);
+ }
+
+ break;
+ }
+
+ case 0x35: /* VRSQL */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110101 |
+ // ------------------------------------------------------
+ //
+ // Calculates reciprocal square-root low part
+
+ int del = VS1REG & 7;
+ int sel = EL & 7;
+ INT32 shifter = 0;
+
+ INT32 rec = ((UINT16)(VREG_S(VS2REG, sel)) | ((UINT32)(rsp->reciprocal_high) & 0xffff0000));
+
+ INT32 datainput = rec;
+
+ if (rec < 0)
+ {
+ if (rsp->dp_allowed)
+ {
+ if (rec < -32768)//VDIV.C,208
+ {
+ datainput = ~datainput;
+ }
+ else
+ {
+ datainput = -datainput;
+ }
+ }
+ else
+ {
+ datainput = -datainput;
+ }
+ }
+
+ if (datainput)
+ {
+ for (i = 0; i < 32; i++)
+ {
+ if (datainput & (1 << ((~i) & 0x1f)))
+ {
+ shifter = i;
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (rsp->dp_allowed)
+ {
+ shifter = 0;
+ }
+ else
+ {
+ shifter = 0x10;
+ }
+ }
+
+ INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22;
+ address = ((address | 0x200) & 0x3fe) | (shifter & 1);
+
+ INT32 fetchval = rsp_divtable[address];
+ INT32 temp = (0x40000000 | (fetchval << 14)) >> (((~shifter) & 0x1f) >> 1);
+ if (rec < 0)
+ {
+ temp = ~temp;
+ }
+ if (!rec)
+ {
+ temp = 0x7fffffff;
+ }
+ else if (rec == 0xffff8000)
+ {
+ temp = 0xffff0000;
+ }
+ rec = temp;
+
+ rsp->reciprocal_res = rec;
+ rsp->dp_allowed = 0;
+
+ VREG_S(VDREG, del) = (UINT16)(rec & 0xffff);
+
+ for (i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ ACCUM_L(i) = VREG_S(VS2REG, sel);
+ }
+
+ break;
+ }
+
+ case 0x36: /* VRSQH */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110110 |
+ // ------------------------------------------------------
+ //
+ // Calculates reciprocal square-root high part
+
+ int del = VS1REG & 7;
+ int sel = EL & 7;
+
+ rsp->reciprocal_high = (VREG_S(VS2REG, sel)) << 16;
+ rsp->dp_allowed = 1;
+
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ ACCUM_L(i) = VREG_S(VS2REG, sel);
+ }
+
+ VREG_S(VDREG, del) = (INT16)(rsp->reciprocal_res >> 16); // store high part
+ break;
+ }
+
+ case 0x37: /* VNOP */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110111 |
+ // ------------------------------------------------------
+ //
+ // Vector null instruction
+
+ break;
+ }
+
+ default: unimplemented_opcode(rsp, op); break;
+ }
+}
+
+static CPU_EXECUTE( rsp )
+{
+ rsp_state *rsp = get_safe_token(device);
+ UINT32 op;
+
+ rsp->pc = 0x4001000 | (rsp->pc & 0xfff);
+
+ if( rsp->sr & ( RSP_STATUS_HALT | RSP_STATUS_BROKE ) )
+ {
+ rsp->icount = MIN(rsp->icount, 0);
+ }
+
+ while (rsp->icount > 0)
+ {
+ rsp->ppc = rsp->pc;
+ debugger_instruction_hook(device, rsp->pc);
+
+ op = ROPCODE(rsp->pc);
+ if (rsp->nextpc != ~0)
+ {
+ rsp->pc = rsp->nextpc;
+ rsp->nextpc = ~0;
+ }
+ else
+ {
+ rsp->pc += 4;
+ }
+
+ switch (op >> 26)
+ {
+ case 0x00: /* SPECIAL */
+ {
+ switch (op & 0x3f)
+ {
+ case 0x00: /* SLL */ if (RDREG) RDVAL = (UINT32)RTVAL << SHIFT; break;
+ case 0x02: /* SRL */ if (RDREG) RDVAL = (UINT32)RTVAL >> SHIFT; break;
+ case 0x03: /* SRA */ if (RDREG) RDVAL = (INT32)RTVAL >> SHIFT; break;
+ case 0x04: /* SLLV */ if (RDREG) RDVAL = (UINT32)RTVAL << (RSVAL & 0x1f); break;
+ case 0x06: /* SRLV */ if (RDREG) RDVAL = (UINT32)RTVAL >> (RSVAL & 0x1f); break;
+ case 0x07: /* SRAV */ if (RDREG) RDVAL = (INT32)RTVAL >> (RSVAL & 0x1f); break;
+ case 0x08: /* JR */ JUMP_PC(RSVAL); break;
+ case 0x09: /* JALR */ JUMP_PC_L(RSVAL, RDREG); break;
+ case 0x0d: /* BREAK */
+ {
+ (rsp->config->sp_set_status)(rsp->device, 0x3);
+ rsp->icount = MIN(rsp->icount, 1);
+
+ if (LOG_INSTRUCTION_EXECUTION) fprintf(rsp->exec_output, "\n---------- break ----------\n\n");
+
+ break;
+ }
+ case 0x20: /* ADD */ if (RDREG) RDVAL = (INT32)(RSVAL + RTVAL); break;
+ case 0x21: /* ADDU */ if (RDREG) RDVAL = (INT32)(RSVAL + RTVAL); break;
+ case 0x22: /* SUB */ if (RDREG) RDVAL = (INT32)(RSVAL - RTVAL); break;
+ case 0x23: /* SUBU */ if (RDREG) RDVAL = (INT32)(RSVAL - RTVAL); break;
+ case 0x24: /* AND */ if (RDREG) RDVAL = RSVAL & RTVAL; break;
+ case 0x25: /* OR */ if (RDREG) RDVAL = RSVAL | RTVAL; break;
+ case 0x26: /* XOR */ if (RDREG) RDVAL = RSVAL ^ RTVAL; break;
+ case 0x27: /* NOR */ if (RDREG) RDVAL = ~(RSVAL | RTVAL); break;
+ case 0x2a: /* SLT */ if (RDREG) RDVAL = (INT32)RSVAL < (INT32)RTVAL; break;
+ case 0x2b: /* SLTU */ if (RDREG) RDVAL = (UINT32)RSVAL < (UINT32)RTVAL; break;
+ default: unimplemented_opcode(rsp, op); break;
+ }
+ break;
+ }
+
+ case 0x01: /* REGIMM */
+ {
+ switch (RTREG)
+ {
+ case 0x00: /* BLTZ */ if ((INT32)(RSVAL) < 0) JUMP_REL(SIMM16); break;
+ case 0x01: /* BGEZ */ if ((INT32)(RSVAL) >= 0) JUMP_REL(SIMM16); break;
+ case 0x10: /* BLTZAL */ if ((INT32)(RSVAL) < 0) JUMP_REL_L(SIMM16, 31); break;
+ case 0x11: /* BGEZAL */ if ((INT32)(RSVAL) >= 0) JUMP_REL_L(SIMM16, 31); break;
+ default: unimplemented_opcode(rsp, op); break;
+ }
+ break;
+ }
+
+ case 0x02: /* J */ JUMP_ABS(UIMM26); break;
+ case 0x03: /* JAL */ JUMP_ABS_L(UIMM26, 31); break;
+ case 0x04: /* BEQ */ if (RSVAL == RTVAL) JUMP_REL(SIMM16); break;
+ case 0x05: /* BNE */ if (RSVAL != RTVAL) JUMP_REL(SIMM16); break;
+ case 0x06: /* BLEZ */ if ((INT32)RSVAL <= 0) JUMP_REL(SIMM16); break;
+ case 0x07: /* BGTZ */ if ((INT32)RSVAL > 0) JUMP_REL(SIMM16); break;
+ case 0x08: /* ADDI */ if (RTREG) RTVAL = (INT32)(RSVAL + SIMM16); break;
+ case 0x09: /* ADDIU */ if (RTREG) RTVAL = (INT32)(RSVAL + SIMM16); break;
+ case 0x0a: /* SLTI */ if (RTREG) RTVAL = (INT32)(RSVAL) < ((INT32)SIMM16); break;
+ case 0x0b: /* SLTIU */ if (RTREG) RTVAL = (UINT32)(RSVAL) < (UINT32)((INT32)SIMM16); break;
+ case 0x0c: /* ANDI */ if (RTREG) RTVAL = RSVAL & UIMM16; break;
+ case 0x0d: /* ORI */ if (RTREG) RTVAL = RSVAL | UIMM16; break;
+ case 0x0e: /* XORI */ if (RTREG) RTVAL = RSVAL ^ UIMM16; break;
+ case 0x0f: /* LUI */ if (RTREG) RTVAL = UIMM16 << 16; break;
+
+ case 0x10: /* COP0 */
+ {
+ switch ((op >> 21) & 0x1f)
+ {
+ case 0x00: /* MFC0 */ if (RTREG) RTVAL = get_cop0_reg(rsp, RDREG); break;
+ case 0x04: /* MTC0 */ set_cop0_reg(rsp, RDREG, RTVAL); break;
+ default: unimplemented_opcode(rsp, op); break;
+ }
+ break;
+ }
+
+ case 0x12: /* COP2 */
+ {
+ switch ((op >> 21) & 0x1f)
+ {
+ case 0x00: /* MFC2 */
+ {
+ // 31 25 20 15 10 6 0
+ // ---------------------------------------------------
+ // | 010010 | 00000 | TTTTT | DDDDD | IIII | 0000000 |
+ // ---------------------------------------------------
+ //
+
+ int el = (op >> 7) & 0xf;
+ UINT16 b1 = VREG_B(RDREG, (el+0) & 0xf);
+ UINT16 b2 = VREG_B(RDREG, (el+1) & 0xf);
+ if (RTREG) RTVAL = (INT32)(INT16)((b1 << 8) | (b2));
+ break;
+ }
+ case 0x02: /* CFC2 */
+ {
+ // 31 25 20 15 10 0
+ // ------------------------------------------------
+ // | 010010 | 00010 | TTTTT | DDDDD | 00000000000 |
+ // ------------------------------------------------
+ //
+
+ if (RTREG)
+ {
+ if (RDREG == 2)
+ {
+ // Anciliary clipping flags
+ RTVAL = rsp->flag[RDREG] & 0x00ff;
+ }
+ else
+ {
+ // All other flags are 16 bits but sign-extended at retrieval
+ RTVAL = (UINT32)rsp->flag[RDREG] | ( ( rsp->flag[RDREG] & 0x8000 ) ? 0xffff0000 : 0 );
+ }
+ }
+ break;
+ }
+ case 0x04: /* MTC2 */
+ {
+ // 31 25 20 15 10 6 0
+ // ---------------------------------------------------
+ // | 010010 | 00100 | TTTTT | DDDDD | IIII | 0000000 |
+ // ---------------------------------------------------
+ //
+
+ int el = (op >> 7) & 0xf;
+ W_VREG_B(RDREG, (el+0) & 0xf, (RTVAL >> 8) & 0xff);
+ W_VREG_B(RDREG, (el+1) & 0xf, (RTVAL >> 0) & 0xff);
+ break;
+ }
+ case 0x06: /* CTC2 */
+ {
+ // 31 25 20 15 10 0
+ // ------------------------------------------------
+ // | 010010 | 00110 | TTTTT | DDDDD | 00000000000 |
+ // ------------------------------------------------
+ //
+
+ rsp->flag[RDREG] = RTVAL & 0xffff;
+ 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:
+ {
+ handle_vector_ops(rsp, op);
+ break;
+ }
+
+ default: unimplemented_opcode(rsp, op); break;
+ }
+ break;
+ }
+
+ case 0x20: /* LB */ if (RTREG) RTVAL = (INT32)(INT8)READ8(rsp, RSVAL + SIMM16); break;
+ case 0x21: /* LH */ if (RTREG) RTVAL = (INT32)(INT16)READ16(rsp, RSVAL + SIMM16); break;
+ case 0x23: /* LW */ if (RTREG) RTVAL = READ32(rsp, RSVAL + SIMM16); break;
+ case 0x24: /* LBU */ if (RTREG) RTVAL = (UINT8)READ8(rsp, RSVAL + SIMM16); break;
+ case 0x25: /* LHU */ if (RTREG) RTVAL = (UINT16)READ16(rsp, RSVAL + SIMM16); break;
+ case 0x28: /* SB */ WRITE8(rsp, RSVAL + SIMM16, RTVAL); break;
+ case 0x29: /* SH */ WRITE16(rsp, RSVAL + SIMM16, RTVAL); break;
+ case 0x2b: /* SW */ WRITE32(rsp, RSVAL + SIMM16, RTVAL); break;
+ case 0x32: /* LWC2 */ handle_lwc2(rsp, op); break;
+ case 0x3a: /* SWC2 */ handle_swc2(rsp, op); break;
+
+ default:
+ {
+ unimplemented_opcode(rsp, op);
+ break;
+ }
+ }
+
+ if (LOG_INSTRUCTION_EXECUTION)
+ {
+ int i, l;
+ static UINT32 prev_regs[32];
+ static VECTOR_REG prev_vecs[32];
+ char string[200];
+ rsp_dasm_one(string, rsp->ppc, op);
+
+ fprintf(rsp->exec_output, "%08X: %s", rsp->ppc, string);
+
+ l = strlen(string);
+ if (l < 36)
+ {
+ for (i=l; i < 36; i++)
+ {
+ fprintf(rsp->exec_output, " ");
+ }
+ }
+
+ fprintf(rsp->exec_output, "| ");
+
+ for (i=0; i < 32; i++)
+ {
+ if (rsp->r[i] != prev_regs[i])
+ {
+ fprintf(rsp->exec_output, "R%d: %08X ", i, rsp->r[i]);
+ }
+ prev_regs[i] = rsp->r[i];
+ }
+
+ for (i=0; i < 32; i++)
+ {
+ if (rsp->v[i].d[0] != prev_vecs[i].d[0] || rsp->v[i].d[1] != prev_vecs[i].d[1])
+ {
+ fprintf(rsp->exec_output, "V%d: %04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X ", i,
+ (UINT16)VREG_S(i,0), (UINT16)VREG_S(i,1), (UINT16)VREG_S(i,2), (UINT16)VREG_S(i,3), (UINT16)VREG_S(i,4), (UINT16)VREG_S(i,5), (UINT16)VREG_S(i,6), (UINT16)VREG_S(i,7));
+ }
+ prev_vecs[i].d[0] = rsp->v[i].d[0];
+ prev_vecs[i].d[1] = rsp->v[i].d[1];
+ }
+
+ fprintf(rsp->exec_output, "\n");
+
+ }
+
+ --rsp->icount;
+
+ if( rsp->sr & RSP_STATUS_SSTEP )
+ {
+ if( rsp->step_count )
+ {
+ rsp->step_count--;
+ }
+ else
+ {
+ rsp->sr |= RSP_STATUS_BROKE;
+ }
+ }
+
+ if( rsp->sr & ( RSP_STATUS_HALT | RSP_STATUS_BROKE ) )
+ {
+ rsp->icount = MIN(rsp->icount, 0);
+ }
+
+ }
+}
+
+
+
+
+/*****************************************************************************/
+
+static CPU_SET_INFO( rsp )
+{
+ rsp_state *rsp = 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 + RSP_PC: rsp->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R0: rsp->r[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R1: rsp->r[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R2: rsp->r[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R3: rsp->r[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R4: rsp->r[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R5: rsp->r[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R6: rsp->r[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R7: rsp->r[7] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R8: rsp->r[8] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R9: rsp->r[9] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R10: rsp->r[10] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R11: rsp->r[11] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R12: rsp->r[12] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R13: rsp->r[13] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R14: rsp->r[14] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R15: rsp->r[15] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R16: rsp->r[16] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R17: rsp->r[17] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R18: rsp->r[18] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R19: rsp->r[19] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R20: rsp->r[20] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R21: rsp->r[21] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R22: rsp->r[22] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R23: rsp->r[23] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R24: rsp->r[24] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R25: rsp->r[25] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R26: rsp->r[26] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R27: rsp->r[27] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R28: rsp->r[28] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R29: rsp->r[29] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R30: rsp->r[30] = info->i; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + RSP_R31: rsp->r[31] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_SR: rsp->sr = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_NEXTPC: rsp->nextpc = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_STEPCNT: rsp->step_count = info->i; break;
+ }
+}
+
+CPU_GET_INFO( rsp )
+{
+ rsp_state *rsp = (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(rsp_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 = 1; 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: info->i = rsp->ppc; break;
+
+ case CPUINFO_INT_PC: /* intentional fallthrough */
+ case CPUINFO_INT_REGISTER + RSP_PC: info->i = rsp->pc; break;
+
+ case CPUINFO_INT_REGISTER + RSP_R0: info->i = rsp->r[0]; break;
+ case CPUINFO_INT_REGISTER + RSP_R1: info->i = rsp->r[1]; break;
+ case CPUINFO_INT_REGISTER + RSP_R2: info->i = rsp->r[2]; break;
+ case CPUINFO_INT_REGISTER + RSP_R3: info->i = rsp->r[3]; break;
+ case CPUINFO_INT_REGISTER + RSP_R4: info->i = rsp->r[4]; break;
+ case CPUINFO_INT_REGISTER + RSP_R5: info->i = rsp->r[5]; break;
+ case CPUINFO_INT_REGISTER + RSP_R6: info->i = rsp->r[6]; break;
+ case CPUINFO_INT_REGISTER + RSP_R7: info->i = rsp->r[7]; break;
+ case CPUINFO_INT_REGISTER + RSP_R8: info->i = rsp->r[8]; break;
+ case CPUINFO_INT_REGISTER + RSP_R9: info->i = rsp->r[9]; break;
+ case CPUINFO_INT_REGISTER + RSP_R10: info->i = rsp->r[10]; break;
+ case CPUINFO_INT_REGISTER + RSP_R11: info->i = rsp->r[11]; break;
+ case CPUINFO_INT_REGISTER + RSP_R12: info->i = rsp->r[12]; break;
+ case CPUINFO_INT_REGISTER + RSP_R13: info->i = rsp->r[13]; break;
+ case CPUINFO_INT_REGISTER + RSP_R14: info->i = rsp->r[14]; break;
+ case CPUINFO_INT_REGISTER + RSP_R15: info->i = rsp->r[15]; break;
+ case CPUINFO_INT_REGISTER + RSP_R16: info->i = rsp->r[16]; break;
+ case CPUINFO_INT_REGISTER + RSP_R17: info->i = rsp->r[17]; break;
+ case CPUINFO_INT_REGISTER + RSP_R18: info->i = rsp->r[18]; break;
+ case CPUINFO_INT_REGISTER + RSP_R19: info->i = rsp->r[19]; break;
+ case CPUINFO_INT_REGISTER + RSP_R20: info->i = rsp->r[20]; break;
+ case CPUINFO_INT_REGISTER + RSP_R21: info->i = rsp->r[21]; break;
+ case CPUINFO_INT_REGISTER + RSP_R22: info->i = rsp->r[22]; break;
+ case CPUINFO_INT_REGISTER + RSP_R23: info->i = rsp->r[23]; break;
+ case CPUINFO_INT_REGISTER + RSP_R24: info->i = rsp->r[24]; break;
+ case CPUINFO_INT_REGISTER + RSP_R25: info->i = rsp->r[25]; break;
+ case CPUINFO_INT_REGISTER + RSP_R26: info->i = rsp->r[26]; break;
+ case CPUINFO_INT_REGISTER + RSP_R27: info->i = rsp->r[27]; break;
+ case CPUINFO_INT_REGISTER + RSP_R28: info->i = rsp->r[28]; break;
+ case CPUINFO_INT_REGISTER + RSP_R29: info->i = rsp->r[29]; break;
+ case CPUINFO_INT_REGISTER + RSP_R30: info->i = rsp->r[30]; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + RSP_R31: info->i = rsp->r[31]; break;
+ case CPUINFO_INT_REGISTER + RSP_SR: info->i = rsp->sr; break;
+ case CPUINFO_INT_REGISTER + RSP_NEXTPC: info->i = rsp->nextpc; break;
+ case CPUINFO_INT_REGISTER + RSP_STEPCNT: info->i = rsp->step_count; 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(rsp); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(rsp); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(rsp); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(rsp); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(rsp); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(rsp); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &rsp->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "RSP"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "RSP"); 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 + RSP_PC: sprintf(info->s, "PC: %08X", rsp->pc); break;
+
+ case CPUINFO_STR_REGISTER + RSP_R0: sprintf(info->s, "R0: %08X", rsp->r[0]); break;
+ case CPUINFO_STR_REGISTER + RSP_R1: sprintf(info->s, "R1: %08X", rsp->r[1]); break;
+ case CPUINFO_STR_REGISTER + RSP_R2: sprintf(info->s, "R2: %08X", rsp->r[2]); break;
+ case CPUINFO_STR_REGISTER + RSP_R3: sprintf(info->s, "R3: %08X", rsp->r[3]); break;
+ case CPUINFO_STR_REGISTER + RSP_R4: sprintf(info->s, "R4: %08X", rsp->r[4]); break;
+ case CPUINFO_STR_REGISTER + RSP_R5: sprintf(info->s, "R5: %08X", rsp->r[5]); break;
+ case CPUINFO_STR_REGISTER + RSP_R6: sprintf(info->s, "R6: %08X", rsp->r[6]); break;
+ case CPUINFO_STR_REGISTER + RSP_R7: sprintf(info->s, "R7: %08X", rsp->r[7]); break;
+ case CPUINFO_STR_REGISTER + RSP_R8: sprintf(info->s, "R8: %08X", rsp->r[8]); break;
+ case CPUINFO_STR_REGISTER + RSP_R9: sprintf(info->s, "R9: %08X", rsp->r[9]); break;
+ case CPUINFO_STR_REGISTER + RSP_R10: sprintf(info->s, "R10: %08X", rsp->r[10]); break;
+ case CPUINFO_STR_REGISTER + RSP_R11: sprintf(info->s, "R11: %08X", rsp->r[11]); break;
+ case CPUINFO_STR_REGISTER + RSP_R12: sprintf(info->s, "R12: %08X", rsp->r[12]); break;
+ case CPUINFO_STR_REGISTER + RSP_R13: sprintf(info->s, "R13: %08X", rsp->r[13]); break;
+ case CPUINFO_STR_REGISTER + RSP_R14: sprintf(info->s, "R14: %08X", rsp->r[14]); break;
+ case CPUINFO_STR_REGISTER + RSP_R15: sprintf(info->s, "R15: %08X", rsp->r[15]); break;
+ case CPUINFO_STR_REGISTER + RSP_R16: sprintf(info->s, "R16: %08X", rsp->r[16]); break;
+ case CPUINFO_STR_REGISTER + RSP_R17: sprintf(info->s, "R17: %08X", rsp->r[17]); break;
+ case CPUINFO_STR_REGISTER + RSP_R18: sprintf(info->s, "R18: %08X", rsp->r[18]); break;
+ case CPUINFO_STR_REGISTER + RSP_R19: sprintf(info->s, "R19: %08X", rsp->r[19]); break;
+ case CPUINFO_STR_REGISTER + RSP_R20: sprintf(info->s, "R20: %08X", rsp->r[20]); break;
+ case CPUINFO_STR_REGISTER + RSP_R21: sprintf(info->s, "R21: %08X", rsp->r[21]); break;
+ case CPUINFO_STR_REGISTER + RSP_R22: sprintf(info->s, "R22: %08X", rsp->r[22]); break;
+ case CPUINFO_STR_REGISTER + RSP_R23: sprintf(info->s, "R23: %08X", rsp->r[23]); break;
+ case CPUINFO_STR_REGISTER + RSP_R24: sprintf(info->s, "R24: %08X", rsp->r[24]); break;
+ case CPUINFO_STR_REGISTER + RSP_R25: sprintf(info->s, "R25: %08X", rsp->r[25]); break;
+ case CPUINFO_STR_REGISTER + RSP_R26: sprintf(info->s, "R26: %08X", rsp->r[26]); break;
+ case CPUINFO_STR_REGISTER + RSP_R27: sprintf(info->s, "R27: %08X", rsp->r[27]); break;
+ case CPUINFO_STR_REGISTER + RSP_R28: sprintf(info->s, "R28: %08X", rsp->r[28]); break;
+ case CPUINFO_STR_REGISTER + RSP_R29: sprintf(info->s, "R29: %08X", rsp->r[29]); break;
+ case CPUINFO_STR_REGISTER + RSP_R30: sprintf(info->s, "R30: %08X", rsp->r[30]); break;
+ case CPUINFO_STR_REGISTER + RSP_R31: sprintf(info->s, "R31: %08X", rsp->r[31]); break;
+ case CPUINFO_STR_REGISTER + RSP_SR: sprintf(info->s, "SR: %08X", rsp->sr); break;
+ case CPUINFO_STR_REGISTER + RSP_NEXTPC: sprintf(info->s, "NPC: %08X", rsp->nextpc);break;
+ case CPUINFO_STR_REGISTER + RSP_STEPCNT: sprintf(info->s, "STEP: %d", rsp->step_count); break;
+ }
+}
+
+void rspdrc_set_options(device_t *device, UINT32 options)
+{
+}
+
+void rspdrc_add_imem(device_t *device, void *base)
+{
+}
+
+void rspdrc_add_dmem(device_t *device, void *base)
+{
+}
+
+void rspdrc_flush_drc_cache(device_t *device)
+{
+}
+
+DEFINE_LEGACY_CPU_DEVICE(RSP, rsp);
+
+#endif // USE_RSPDRC
diff --git a/trunk/src/emu/cpu/rsp/rsp.h b/trunk/src/emu/cpu/rsp/rsp.h
new file mode 100644
index 00000000000..13e9afba965
--- /dev/null
+++ b/trunk/src/emu/cpu/rsp/rsp.h
@@ -0,0 +1,194 @@
+/***************************************************************************
+
+ rsp.h
+
+ Interface file for the universal machine language-based
+ Reality Signal Processor (RSP) emulator.
+
+ Copyright the MESS team
+ Released for general non-commercial use under the MAME license
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __RSP_H__
+#define __RSP_H__
+
+#define USE_RSPDRC
+
+/***************************************************************************
+ REGISTER ENUMERATION
+***************************************************************************/
+
+enum
+{
+ RSP_PC = 1,
+ RSP_R0,
+ RSP_R1,
+ RSP_R2,
+ RSP_R3,
+ RSP_R4,
+ RSP_R5,
+ RSP_R6,
+ RSP_R7,
+ RSP_R8,
+ RSP_R9,
+ RSP_R10,
+ RSP_R11,
+ RSP_R12,
+ RSP_R13,
+ RSP_R14,
+ RSP_R15,
+ RSP_R16,
+ RSP_R17,
+ RSP_R18,
+ RSP_R19,
+ RSP_R20,
+ RSP_R21,
+ RSP_R22,
+ RSP_R23,
+ RSP_R24,
+ RSP_R25,
+ RSP_R26,
+ RSP_R27,
+ RSP_R28,
+ RSP_R29,
+ RSP_R30,
+ RSP_R31,
+ RSP_SR,
+ RSP_NEXTPC,
+ RSP_STEPCNT,
+};
+
+
+
+/***************************************************************************
+ STRUCTURES
+***************************************************************************/
+
+typedef void (*rsp_set_status_func)(device_t *device, UINT32 status);
+
+typedef struct _rsp_config rsp_config;
+struct _rsp_config
+{
+ read32_device_func dp_reg_r;
+ write32_device_func dp_reg_w;
+ read32_device_func sp_reg_r;
+ write32_device_func sp_reg_w;
+ rsp_set_status_func sp_set_status;
+};
+
+
+
+/***************************************************************************
+ PUBLIC FUNCTIONS
+***************************************************************************/
+
+void rspdrc_flush_drc_cache(device_t *device);
+void rspdrc_set_options(device_t *device, UINT32 options);
+void rspdrc_add_imem(device_t *device, void *base);
+void rspdrc_add_dmem(device_t *device, void *base);
+
+/***************************************************************************
+ 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 RSVAL (rsp->r[RSREG])
+#define RTVAL (rsp->r[RTREG])
+#define RDVAL (rsp->r[RDREG])
+
+#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)
+
+#define RSP_STATUS_HALT 0x0001
+#define RSP_STATUS_BROKE 0x0002
+#define RSP_STATUS_DMABUSY 0x0004
+#define RSP_STATUS_DMAFULL 0x0008
+#define RSP_STATUS_IOFULL 0x0010
+#define RSP_STATUS_SSTEP 0x0020
+#define RSP_STATUS_INTR_BREAK 0x0040
+#define RSP_STATUS_SIGNAL0 0x0080
+#define RSP_STATUS_SIGNAL1 0x0100
+#define RSP_STATUS_SIGNAL2 0x0200
+#define RSP_STATUS_SIGNAL3 0x0400
+#define RSP_STATUS_SIGNAL4 0x0800
+#define RSP_STATUS_SIGNAL5 0x1000
+#define RSP_STATUS_SIGNAL6 0x2000
+#define RSP_STATUS_SIGNAL7 0x4000
+
+#define RSPDRC_STRICT_VERIFY 0x0001 /* verify all instructions */
+
+typedef union
+{
+ UINT64 d[2];
+ UINT32 l[4];
+ INT16 s[8];
+ UINT8 b[16];
+} VECTOR_REG;
+
+typedef union
+{
+ INT64 q;
+ INT32 l[2];
+ INT16 w[4];
+} ACCUMULATOR_REG;
+
+typedef struct _rspimp_state rspimp_state;
+typedef struct _rsp_state rsp_state;
+struct _rsp_state
+{
+ const rsp_config *config;
+ FILE *exec_output;
+
+ UINT32 pc;
+ UINT32 r[35];
+ VECTOR_REG v[32];
+ UINT16 flag[4];
+ UINT32 sr;
+ UINT32 step_count;
+
+ ACCUMULATOR_REG accum[8];
+ INT32 square_root_res;
+ INT32 square_root_high;
+ INT32 reciprocal_res;
+ INT32 reciprocal_high;
+ INT32 dp_allowed;
+
+ UINT32 ppc;
+ UINT32 nextpc;
+
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ int icount;
+
+ rspimp_state* impstate;
+};
+
+DECLARE_LEGACY_CPU_DEVICE(RSP, rsp);
+
+extern offs_t rsp_dasm_one(char *buffer, offs_t pc, UINT32 op);
+
+#endif /* __RSP_H__ */
diff --git a/trunk/src/emu/cpu/rsp/rsp_dasm.c b/trunk/src/emu/cpu/rsp/rsp_dasm.c
new file mode 100644
index 00000000000..d6751619a1e
--- /dev/null
+++ b/trunk/src/emu/cpu/rsp/rsp_dasm.c
@@ -0,0 +1,353 @@
+/*
+ Nintendo/SGI RSP Disassembler
+
+ Written by Ville Linde
+*/
+
+#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 vreg[32] =
+{
+ " v0", " v1", " v2", " v3", " v4", " v5", " v6", " v7",
+ " v8", " v9", "v10", "v11", "v12", "v13", "v14", "v15",
+ "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
+ "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
+};
+
+static const char *const cop0_regs[32] =
+{
+ "SP_MEM_ADDR", "SP_DRAM_ADDR", "SP_RD_LEN", "SP_WR_LEN",
+ "SP_STATUS", "SP_DMA_FULL", "SP_DMA_BUSY", "SP_SEMAPHORE",
+ "DPC_START", "DPC_END", "DPC_CURRENT", "DPC_STATUS",
+ "DPC_CLOCK", "DPC_BUFBUSY", "DPC_PIPEBUSY", "DPC_TMEM",
+ "???", "???", "???", "???",
+ "???", "???", "???", "???",
+ "???", "???", "???", "???",
+ "???", "???", "???", "???"
+};
+
+static const char *const element[16] =
+{
+ "", "[???]", "[00224466]", "[11335577]", "[00004444]", "[11115555]", "[22226666]", "[33337777]",
+ "[00000000]", "[11111111]", "[22222222]", "[33333333]", "[44444444]", "[55555555]", "[66666666]", "[77777777]"
+};
+
+static const char *const element2[16] =
+{
+ "01234567", "????????", "00224466", "11335577", "00004444", "11115555", "22226666", "33337777",
+ "00000000", "11111111", "22222222", "33333333", "44444444", "55555555", "66666666", "77777777"
+};
+
+INLINE char *signed_imm16(UINT32 op)
+{
+ static char temp[10];
+ INT16 value = op & 0xffff;
+
+ if (value < 0)
+ {
+ sprintf(temp, "-$%04x", -value);
+ }
+ else
+ {
+ sprintf(temp, "$%04x", value);
+ }
+ return temp;
+}
+
+
+static char *output;
+
+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 void disasm_cop0(UINT32 op)
+{
+ int rt = (op >> 16) & 31;
+ int rd = (op >> 11) & 31;
+
+ switch ((op >> 21) & 0x1f)
+ {
+ case 0x00: print("mfc0 %s, %s", reg[rt], cop0_regs[rd]); break;
+ case 0x04: print("mtc0 %s, %s", reg[rt], cop0_regs[rd]); break;
+
+ default: print("??? (COP0)"); break;
+ }
+}
+
+static void disasm_cop2(UINT32 op)
+{
+ int rt = (op >> 16) & 31;
+ int rd = (op >> 11) & 31;
+ int el = (op >> 21) & 0xf;
+ int dest = (op >> 6) & 0x1f;
+ int s1 = rd;
+ int s2 = rt;
+
+ switch ((op >> 21) & 0x1f)
+ {
+ case 0x00: print("mfc2 %s, %s[%d]", reg[rt], vreg[rd], dest); break;
+ case 0x02: print("cfc2 %s, FLAG%d", reg[rt], rd); break;
+ case 0x04: print("mtc2 %s, %s[%d]", reg[rt], vreg[rd], dest); break;
+ case 0x06: print("ctc2 %s, FLAG%d", reg[rt], rd); 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:
+ {
+ switch (op & 0x3f)
+ {
+ case 0x00: print("vmulf %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x01: print("vmulu %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x02: print("vrndp %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x03: print("vmulq %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x04: print("vmudl %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x05: print("vmudm %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x06: print("vmudn %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x07: print("vmudh %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x08: print("vmacf %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x09: print("vmacu %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x0a: print("vrndn %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x0b: print("vmacq %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x0c: print("vmadl %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x0d: print("vmadm %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x0e: print("vmadn %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x0f: print("vmadh %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x10: print("vadd %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x11: print("vsub %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x12: print("vsut???"); break;
+ case 0x13: print("vabs %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x14: print("vaddc %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x15: print("vsubc %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+
+ case 0x1d:
+ {
+ switch (el)
+ {
+ case 8: print("vsaw %s, ACCUM_H", vreg[dest]); break;
+ case 9: print("vsaw %s, ACCUM_M", vreg[dest]); break;
+ case 10: print("vsaw %s, ACCUM_L", vreg[dest]); break;
+ default: print("vsaw %s, ???", vreg[dest]); break;
+ }
+ break;
+ }
+
+ case 0x20: print("vlt %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x21: print("veq %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x22: print("vne %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x23: print("vge %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x24: print("vcl %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x25: print("vch %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x26: print("vcr %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x27: print("vmrg %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x28: print("vand %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x29: print("vnand %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x2a: print("vor %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x2b: print("vnor %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x2c: print("vxor %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x2d: print("vnxor %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x30: print("vrcp %s[%d], %s[%c]", vreg[dest], s1 & 7, vreg[s2], element2[el][7-(s1 & 7)]); break;
+ case 0x31: print("vrcpl %s[%d], %s[%c]", vreg[dest], s1 & 7, vreg[s2], element2[el][7-(s1 & 7)]); break;
+ case 0x32: print("vrcph %s[%d], %s[%c]", vreg[dest], s1 & 7, vreg[s2], element2[el][7-(s1 & 7)]); break;
+ case 0x33: print("vmov %s[%d], %s[%c]", vreg[dest], s1 & 7, vreg[s2], element2[el][7-(s1 & 7)]); break;
+ case 0x34: print("vrsq %s[%d], %s[%c]", vreg[dest], s1 & 7, vreg[s2], element2[el][7-(s1 & 7)]); break;
+ case 0x35: print("vrsql %s[%d], %s[%c]", vreg[dest], s1 & 7, vreg[s2], element2[el][7-(s1 & 7)]); break;
+ case 0x36: print("vrsqh %s[%d], %s[%c]", vreg[dest], s1 & 7, vreg[s2], element2[el][7-(s1 & 7)]); break;
+ case 0x37: print("vnop"); break;
+ default: print("??? (VECTOR OP)"); break;
+ }
+ break;
+ }
+
+ default: print("??? (COP2)"); break;
+ }
+}
+
+static void disasm_lwc2(UINT32 op)
+{
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int del = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ offset |= 0xffffff80;
+
+ switch ((op >> 11) & 0x1f)
+ {
+ case 0x00: print("lbv %s[%d], %s(%s)", vreg[dest], del, signed_imm16(offset * 1), reg[base]); break;
+ case 0x01: print("lsv %s[%d], %s(%s)", vreg[dest], del, signed_imm16(offset * 2), reg[base]); break;
+ case 0x02: print("llv %s[%d], %s(%s)", vreg[dest], del, signed_imm16(offset * 4), reg[base]); break;
+ case 0x03: print("ldv %s[%d], %s(%s)", vreg[dest], del, signed_imm16(offset * 8), reg[base]); break;
+ case 0x04: print("lqv %s[%d], %s(%s)", vreg[dest], del, signed_imm16(offset * 16), reg[base]); break;
+ case 0x05: print("lrv %s[%d], %s(%s)", vreg[dest], del, signed_imm16(offset * 16), reg[base]); break;
+ case 0x06: print("lpv %s[%d], %s(%s)", vreg[dest], del, signed_imm16(offset * 8), reg[base]); break;
+ case 0x07: print("luv %s[%d], %s(%s)", vreg[dest], del, signed_imm16(offset * 8), reg[base]); break;
+ case 0x08: print("lhv %s[%d], %s(%s)", vreg[dest], del, signed_imm16(offset * 16), reg[base]); break;
+ case 0x09: print("lfv %s[%d], %s(%s)", vreg[dest], del, signed_imm16(offset * 16), reg[base]); break;
+ case 0x0a: print("lwv %s[%d], %s(%s)", vreg[dest], del, signed_imm16(offset * 16), reg[base]); break;
+ case 0x0b: print("ltv %s[%d], %s(%s)", vreg[dest], del, signed_imm16(offset * 16), reg[base]); break;
+ default: print("??? (LWC2)"); break;
+ }
+}
+
+static void disasm_swc2(UINT32 op)
+{
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int del = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ offset |= 0xffffff80;
+
+ switch ((op >> 11) & 0x1f)
+ {
+ case 0x00: print("sbv %s[%d], %s(%s)", vreg[dest], del, signed_imm16(offset * 1), reg[base]); break;
+ case 0x01: print("ssv %s[%d], %s(%s)", vreg[dest], del, signed_imm16(offset * 2), reg[base]); break;
+ case 0x02: print("slv %s[%d], %s(%s)", vreg[dest], del, signed_imm16(offset * 4), reg[base]); break;
+ case 0x03: print("sdv %s[%d], %s(%s)", vreg[dest], del, signed_imm16(offset * 8), reg[base]); break;
+ case 0x04: print("sqv %s[%d], %s(%s)", vreg[dest], del, signed_imm16(offset * 16), reg[base]); break;
+ case 0x05: print("srv %s[%d], %s(%s)", vreg[dest], del, signed_imm16(offset * 16), reg[base]); break;
+ case 0x06: print("spv %s[%d], %s(%s)", vreg[dest], del, signed_imm16(offset * 8), reg[base]); break;
+ case 0x07: print("suv %s[%d], %s(%s)", vreg[dest], del, signed_imm16(offset * 8), reg[base]); break;
+ case 0x08: print("shv %s[%d], %s(%s)", vreg[dest], del, signed_imm16(offset * 16), reg[base]); break;
+ case 0x09: print("sfv %s[%d], %s(%s)", vreg[dest], del, signed_imm16(offset * 16), reg[base]); break;
+ case 0x0a: print("swv %s[%d], %s(%s)", vreg[dest], del, signed_imm16(offset * 16), reg[base]); break;
+ case 0x0b: print("stv %s[%d], %s(%s)", vreg[dest], del, signed_imm16(offset * 16), reg[base]); break;
+ default: print("??? (SWC2)"); break;
+ }
+}
+
+offs_t rsp_dasm_one(char *buffer, offs_t 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;
+
+ output = buffer;
+
+ switch (op >> 26)
+ {
+ case 0x00: // SPECIAL
+ {
+ switch (op & 0x3f)
+ {
+ case 0x00:
+ {
+ if (op == 0)
+ {
+ print("nop");
+ }
+ else
+ {
+ print("sll %s, %s, %d", reg[rd], reg[rt], shift);
+ }
+ break;
+ }
+ case 0x02: print("srl %s, %s, %d", reg[rd], reg[rt], shift); break;
+ case 0x03: print("sra %s, %s, %d", reg[rd], reg[rt], shift); break;
+ case 0x04: print("sllv %s, %s, %s", reg[rd], reg[rt], reg[rs]); break;
+ case 0x06: print("srlv %s, %s, %s", reg[rd], reg[rt], reg[rs]); break;
+ case 0x07: print("srav %s, %s, %s", reg[rd], reg[rt], reg[rs]); break;
+ case 0x08: print("jr %s", reg[rs]); if (rs == 31) flags = DASMFLAG_STEP_OUT; break;
+ case 0x09:
+ {
+ if (rd == 31)
+ {
+ print("jalr %s", reg[rs]);
+ }
+ else
+ {
+ print("jalr %s, %s", reg[rs], reg[rd]);
+ }
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
+ break;
+ }
+ case 0x0d: print("break"); flags = DASMFLAG_STEP_OVER; break;
+ case 0x20: print("add %s, %s, %s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x21: print("addu %s, %s, %s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x22: print("sub %s, %s, %s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x23: print("subu %s, %s, %s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x24: print("and %s, %s, %s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x25: print("or %s, %s, %s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x26: print("xor %s, %s, %s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x27: print("nor %s, %s, %s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x2a: print("slt %s, %s, %s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x2b: print("sltu %s, %s, %s", reg[rd], reg[rs], reg[rt]); break;
+
+ default: print("???"); break;
+ }
+ break;
+ }
+
+ case 0x01: // REGIMM
+ {
+ switch ((op >> 16) & 0x1f)
+ {
+ case 0x00: print("bltz %s, $%08X", reg[rs], pc + 4 + ((INT16)op << 2)); break;
+ case 0x01: print("bgez %s, $%08X", reg[rs], pc + 4 + ((INT16)op << 2)); break;
+ case 0x10: print("bltzal %s, $%08X", reg[rs], pc + 4 + ((INT16)op << 2)); break;
+ case 0x11: print("bgezal %s, $%08X", reg[rs], pc + 4 + ((INT16)op << 2)); break;
+
+ default: print("???"); break;
+ }
+ break;
+ }
+
+ case 0x02: print("j $%08X", (op & 0x03ffffff) << 2); break;
+ case 0x03: print("jal $%08X", (op & 0x03ffffff) << 2); break;
+ case 0x04: print("beq %s, %s, $%08X", reg[rs], reg[rt], pc + 4 + ((INT16)(op) << 2)); break;
+ case 0x05: print("bne %s, %s, $%08X", reg[rs], reg[rt], pc + 4 + ((INT16)(op) << 2)); break;
+ case 0x06: print("blez %s, $%08X", reg[rs], pc + 4 + ((INT16)(op) << 2)); break;
+ case 0x07: print("bgtz %s, $%08X", reg[rs], pc + 4 + ((INT16)(op) << 2)); break;
+ case 0x08: print("addi %s, %s, %s", reg[rt], reg[rs], signed_imm16(op)); break;
+ case 0x09: print("addiu %s, %s, %s", reg[rt], reg[rs], signed_imm16(op)); break;
+ case 0x0a: print("slti %s, %s, %s", reg[rt], reg[rs], signed_imm16(op)); break;
+ case 0x0b: print("sltiu %s, %s, %s", reg[rt], reg[rs], signed_imm16(op)); break;
+ case 0x0c: print("andi %s, %s, $%04X", reg[rt], reg[rs], (UINT16)(op)); break;
+ case 0x0d: print("ori %s, %s, $%04X", reg[rt], reg[rs], (UINT16)(op)); break;
+ case 0x0e: print("xori %s, %s, $%04X", reg[rt], reg[rs], (UINT16)(op)); break;
+ case 0x0f: print("lui %s, %s, $%04X", reg[rt], reg[rs], (UINT16)(op)); break;
+
+ case 0x10: disasm_cop0(op); break;
+ case 0x12: disasm_cop2(op); break;
+
+ case 0x20: print("lb %s, %s(%s)", reg[rt], signed_imm16(op), reg[rs]); break;
+ case 0x21: print("lh %s, %s(%s)", reg[rt], signed_imm16(op), reg[rs]); break;
+ case 0x23: print("lw %s, %s(%s)", reg[rt], signed_imm16(op), reg[rs]); break;
+ case 0x24: print("lbu %s, %s(%s)", reg[rt], signed_imm16(op), reg[rs]); break;
+ case 0x25: print("lhu %s, %s(%s)", reg[rt], signed_imm16(op), reg[rs]); break;
+ case 0x28: print("sb %s, %s(%s)", reg[rt], signed_imm16(op), reg[rs]); break;
+ case 0x29: print("sh %s, %s(%s)", reg[rt], signed_imm16(op), reg[rs]); break;
+ case 0x2b: print("sw %s, %s(%s)", reg[rt], signed_imm16(op), reg[rs]); break;
+
+ case 0x32: disasm_lwc2(op); break;
+ case 0x3a: disasm_swc2(op); break;
+
+ default: print("???"); break;
+ }
+
+ return 4 | flags | DASMFLAG_SUPPORTED;
+}
+
+/*****************************************************************************/
+
+CPU_DISASSEMBLE( rsp )
+{
+ UINT32 op = *(UINT32 *)opram;
+ op = BIG_ENDIANIZE_INT32(op);
+ return rsp_dasm_one(buffer, pc, op);
+}
diff --git a/trunk/src/emu/cpu/rsp/rspdiv.h b/trunk/src/emu/cpu/rsp/rspdiv.h
new file mode 100644
index 00000000000..7f492c6f7fb
--- /dev/null
+++ b/trunk/src/emu/cpu/rsp/rspdiv.h
@@ -0,0 +1,1027 @@
+static const UINT16 rsp_divtable[1024] =
+{
+ 0xffff,
+ 0xff00,
+ 0xfe01,
+ 0xfd04,
+ 0xfc07,
+ 0xfb0c,
+ 0xfa11,
+ 0xf918,
+ 0xf81f,
+ 0xf727,
+ 0xf631,
+ 0xf53b,
+ 0xf446,
+ 0xf352,
+ 0xf25f,
+ 0xf16d,
+ 0xf07c,
+ 0xef8b,
+ 0xee9c,
+ 0xedae,
+ 0xecc0,
+ 0xebd3,
+ 0xeae8,
+ 0xe9fd,
+ 0xe913,
+ 0xe829,
+ 0xe741,
+ 0xe65a,
+ 0xe573,
+ 0xe48d,
+ 0xe3a9,
+ 0xe2c5,
+ 0xe1e1,
+ 0xe0ff,
+ 0xe01e,
+ 0xdf3d,
+ 0xde5d,
+ 0xdd7e,
+ 0xdca0,
+ 0xdbc2,
+ 0xdae6,
+ 0xda0a,
+ 0xd92f,
+ 0xd854,
+ 0xd77b,
+ 0xd6a2,
+ 0xd5ca,
+ 0xd4f3,
+ 0xd41d,
+ 0xd347,
+ 0xd272,
+ 0xd19e,
+ 0xd0cb,
+ 0xcff8,
+ 0xcf26,
+ 0xce55,
+ 0xcd85,
+ 0xccb5,
+ 0xcbe6,
+ 0xcb18,
+ 0xca4b,
+ 0xc97e,
+ 0xc8b2,
+ 0xc7e7,
+ 0xc71c,
+ 0xc652,
+ 0xc589,
+ 0xc4c0,
+ 0xc3f8,
+ 0xc331,
+ 0xc26b,
+ 0xc1a5,
+ 0xc0e0,
+ 0xc01c,
+ 0xbf58,
+ 0xbe95,
+ 0xbdd2,
+ 0xbd10,
+ 0xbc4f,
+ 0xbb8f,
+ 0xbacf,
+ 0xba10,
+ 0xb951,
+ 0xb894,
+ 0xb7d6,
+ 0xb71a,
+ 0xb65e,
+ 0xb5a2,
+ 0xb4e8,
+ 0xb42e,
+ 0xb374,
+ 0xb2bb,
+ 0xb203,
+ 0xb14b,
+ 0xb094,
+ 0xafde,
+ 0xaf28,
+ 0xae73,
+ 0xadbe,
+ 0xad0a,
+ 0xac57,
+ 0xaba4,
+ 0xaaf1,
+ 0xaa40,
+ 0xa98e,
+ 0xa8de,
+ 0xa82e,
+ 0xa77e,
+ 0xa6d0,
+ 0xa621,
+ 0xa574,
+ 0xa4c6,
+ 0xa41a,
+ 0xa36e,
+ 0xa2c2,
+ 0xa217,
+ 0xa16d,
+ 0xa0c3,
+ 0xa01a,
+ 0x9f71,
+ 0x9ec8,
+ 0x9e21,
+ 0x9d79,
+ 0x9cd3,
+ 0x9c2d,
+ 0x9b87,
+ 0x9ae2,
+ 0x9a3d,
+ 0x9999,
+ 0x98f6,
+ 0x9852,
+ 0x97b0,
+ 0x970e,
+ 0x966c,
+ 0x95cb,
+ 0x952b,
+ 0x948b,
+ 0x93eb,
+ 0x934c,
+ 0x92ad,
+ 0x920f,
+ 0x9172,
+ 0x90d4,
+ 0x9038,
+ 0x8f9c,
+ 0x8f00,
+ 0x8e65,
+ 0x8dca,
+ 0x8d30,
+ 0x8c96,
+ 0x8bfc,
+ 0x8b64,
+ 0x8acb,
+ 0x8a33,
+ 0x899c,
+ 0x8904,
+ 0x886e,
+ 0x87d8,
+ 0x8742,
+ 0x86ad,
+ 0x8618,
+ 0x8583,
+ 0x84f0,
+ 0x845c,
+ 0x83c9,
+ 0x8336,
+ 0x82a4,
+ 0x8212,
+ 0x8181,
+ 0x80f0,
+ 0x8060,
+ 0x7fd0,
+ 0x7f40,
+ 0x7eb1,
+ 0x7e22,
+ 0x7d93,
+ 0x7d05,
+ 0x7c78,
+ 0x7beb,
+ 0x7b5e,
+ 0x7ad2,
+ 0x7a46,
+ 0x79ba,
+ 0x792f,
+ 0x78a4,
+ 0x781a,
+ 0x7790,
+ 0x7706,
+ 0x767d,
+ 0x75f5,
+ 0x756c,
+ 0x74e4,
+ 0x745d,
+ 0x73d5,
+ 0x734f,
+ 0x72c8,
+ 0x7242,
+ 0x71bc,
+ 0x7137,
+ 0x70b2,
+ 0x702e,
+ 0x6fa9,
+ 0x6f26,
+ 0x6ea2,
+ 0x6e1f,
+ 0x6d9c,
+ 0x6d1a,
+ 0x6c98,
+ 0x6c16,
+ 0x6b95,
+ 0x6b14,
+ 0x6a94,
+ 0x6a13,
+ 0x6993,
+ 0x6914,
+ 0x6895,
+ 0x6816,
+ 0x6798,
+ 0x6719,
+ 0x669c,
+ 0x661e,
+ 0x65a1,
+ 0x6524,
+ 0x64a8,
+ 0x642c,
+ 0x63b0,
+ 0x6335,
+ 0x62ba,
+ 0x623f,
+ 0x61c5,
+ 0x614b,
+ 0x60d1,
+ 0x6058,
+ 0x5fdf,
+ 0x5f66,
+ 0x5eed,
+ 0x5e75,
+ 0x5dfd,
+ 0x5d86,
+ 0x5d0f,
+ 0x5c98,
+ 0x5c22,
+ 0x5bab,
+ 0x5b35,
+ 0x5ac0,
+ 0x5a4b,
+ 0x59d6,
+ 0x5961,
+ 0x58ed,
+ 0x5879,
+ 0x5805,
+ 0x5791,
+ 0x571e,
+ 0x56ac,
+ 0x5639,
+ 0x55c7,
+ 0x5555,
+ 0x54e3,
+ 0x5472,
+ 0x5401,
+ 0x5390,
+ 0x5320,
+ 0x52af,
+ 0x5240,
+ 0x51d0,
+ 0x5161,
+ 0x50f2,
+ 0x5083,
+ 0x5015,
+ 0x4fa6,
+ 0x4f38,
+ 0x4ecb,
+ 0x4e5e,
+ 0x4df1,
+ 0x4d84,
+ 0x4d17,
+ 0x4cab,
+ 0x4c3f,
+ 0x4bd3,
+ 0x4b68,
+ 0x4afd,
+ 0x4a92,
+ 0x4a27,
+ 0x49bd,
+ 0x4953,
+ 0x48e9,
+ 0x4880,
+ 0x4817,
+ 0x47ae,
+ 0x4745,
+ 0x46dc,
+ 0x4674,
+ 0x460c,
+ 0x45a5,
+ 0x453d,
+ 0x44d6,
+ 0x446f,
+ 0x4408,
+ 0x43a2,
+ 0x433c,
+ 0x42d6,
+ 0x4270,
+ 0x420b,
+ 0x41a6,
+ 0x4141,
+ 0x40dc,
+ 0x4078,
+ 0x4014,
+ 0x3fb0,
+ 0x3f4c,
+ 0x3ee8,
+ 0x3e85,
+ 0x3e22,
+ 0x3dc0,
+ 0x3d5d,
+ 0x3cfb,
+ 0x3c99,
+ 0x3c37,
+ 0x3bd6,
+ 0x3b74,
+ 0x3b13,
+ 0x3ab2,
+ 0x3a52,
+ 0x39f1,
+ 0x3991,
+ 0x3931,
+ 0x38d2,
+ 0x3872,
+ 0x3813,
+ 0x37b4,
+ 0x3755,
+ 0x36f7,
+ 0x3698,
+ 0x363a,
+ 0x35dc,
+ 0x357f,
+ 0x3521,
+ 0x34c4,
+ 0x3467,
+ 0x340a,
+ 0x33ae,
+ 0x3351,
+ 0x32f5,
+ 0x3299,
+ 0x323e,
+ 0x31e2,
+ 0x3187,
+ 0x312c,
+ 0x30d1,
+ 0x3076,
+ 0x301c,
+ 0x2fc2,
+ 0x2f68,
+ 0x2f0e,
+ 0x2eb4,
+ 0x2e5b,
+ 0x2e02,
+ 0x2da9,
+ 0x2d50,
+ 0x2cf8,
+ 0x2c9f,
+ 0x2c47,
+ 0x2bef,
+ 0x2b97,
+ 0x2b40,
+ 0x2ae8,
+ 0x2a91,
+ 0x2a3a,
+ 0x29e4,
+ 0x298d,
+ 0x2937,
+ 0x28e0,
+ 0x288b,
+ 0x2835,
+ 0x27df,
+ 0x278a,
+ 0x2735,
+ 0x26e0,
+ 0x268b,
+ 0x2636,
+ 0x25e2,
+ 0x258d,
+ 0x2539,
+ 0x24e5,
+ 0x2492,
+ 0x243e,
+ 0x23eb,
+ 0x2398,
+ 0x2345,
+ 0x22f2,
+ 0x22a0,
+ 0x224d,
+ 0x21fb,
+ 0x21a9,
+ 0x2157,
+ 0x2105,
+ 0x20b4,
+ 0x2063,
+ 0x2012,
+ 0x1fc1,
+ 0x1f70,
+ 0x1f1f,
+ 0x1ecf,
+ 0x1e7f,
+ 0x1e2e,
+ 0x1ddf,
+ 0x1d8f,
+ 0x1d3f,
+ 0x1cf0,
+ 0x1ca1,
+ 0x1c52,
+ 0x1c03,
+ 0x1bb4,
+ 0x1b66,
+ 0x1b17,
+ 0x1ac9,
+ 0x1a7b,
+ 0x1a2d,
+ 0x19e0,
+ 0x1992,
+ 0x1945,
+ 0x18f8,
+ 0x18ab,
+ 0x185e,
+ 0x1811,
+ 0x17c4,
+ 0x1778,
+ 0x172c,
+ 0x16e0,
+ 0x1694,
+ 0x1648,
+ 0x15fd,
+ 0x15b1,
+ 0x1566,
+ 0x151b,
+ 0x14d0,
+ 0x1485,
+ 0x143b,
+ 0x13f0,
+ 0x13a6,
+ 0x135c,
+ 0x1312,
+ 0x12c8,
+ 0x127f,
+ 0x1235,
+ 0x11ec,
+ 0x11a3,
+ 0x1159,
+ 0x1111,
+ 0x10c8,
+ 0x107f,
+ 0x1037,
+ 0x0fef,
+ 0x0fa6,
+ 0x0f5e,
+ 0x0f17,
+ 0x0ecf,
+ 0x0e87,
+ 0x0e40,
+ 0x0df9,
+ 0x0db2,
+ 0x0d6b,
+ 0x0d24,
+ 0x0cdd,
+ 0x0c97,
+ 0x0c50,
+ 0x0c0a,
+ 0x0bc4,
+ 0x0b7e,
+ 0x0b38,
+ 0x0af2,
+ 0x0aad,
+ 0x0a68,
+ 0x0a22,
+ 0x09dd,
+ 0x0998,
+ 0x0953,
+ 0x090f,
+ 0x08ca,
+ 0x0886,
+ 0x0842,
+ 0x07fd,
+ 0x07b9,
+ 0x0776,
+ 0x0732,
+ 0x06ee,
+ 0x06ab,
+ 0x0668,
+ 0x0624,
+ 0x05e1,
+ 0x059e,
+ 0x055c,
+ 0x0519,
+ 0x04d6,
+ 0x0494,
+ 0x0452,
+ 0x0410,
+ 0x03ce,
+ 0x038c,
+ 0x034a,
+ 0x0309,
+ 0x02c7,
+ 0x0286,
+ 0x0245,
+ 0x0204,
+ 0x01c3,
+ 0x0182,
+ 0x0141,
+ 0x0101,
+ 0x00c0,
+ 0x0080,
+ 0x0040,
+ 0x6a09,
+ 0xffff,
+ 0x6955,
+ 0xff00,
+ 0x68a1,
+ 0xfe02,
+ 0x67ef,
+ 0xfd06,
+ 0x673e,
+ 0xfc0b,
+ 0x668d,
+ 0xfb12,
+ 0x65de,
+ 0xfa1a,
+ 0x6530,
+ 0xf923,
+ 0x6482,
+ 0xf82e,
+ 0x63d6,
+ 0xf73b,
+ 0x632b,
+ 0xf648,
+ 0x6280,
+ 0xf557,
+ 0x61d7,
+ 0xf467,
+ 0x612e,
+ 0xf379,
+ 0x6087,
+ 0xf28c,
+ 0x5fe0,
+ 0xf1a0,
+ 0x5f3a,
+ 0xf0b6,
+ 0x5e95,
+ 0xefcd,
+ 0x5df1,
+ 0xeee5,
+ 0x5d4e,
+ 0xedff,
+ 0x5cac,
+ 0xed19,
+ 0x5c0b,
+ 0xec35,
+ 0x5b6b,
+ 0xeb52,
+ 0x5acb,
+ 0xea71,
+ 0x5a2c,
+ 0xe990,
+ 0x598f,
+ 0xe8b1,
+ 0x58f2,
+ 0xe7d3,
+ 0x5855,
+ 0xe6f6,
+ 0x57ba,
+ 0xe61b,
+ 0x5720,
+ 0xe540,
+ 0x5686,
+ 0xe467,
+ 0x55ed,
+ 0xe38e,
+ 0x5555,
+ 0xe2b7,
+ 0x54be,
+ 0xe1e1,
+ 0x5427,
+ 0xe10d,
+ 0x5391,
+ 0xe039,
+ 0x52fc,
+ 0xdf66,
+ 0x5268,
+ 0xde94,
+ 0x51d5,
+ 0xddc4,
+ 0x5142,
+ 0xdcf4,
+ 0x50b0,
+ 0xdc26,
+ 0x501f,
+ 0xdb59,
+ 0x4f8e,
+ 0xda8c,
+ 0x4efe,
+ 0xd9c1,
+ 0x4e6f,
+ 0xd8f7,
+ 0x4de1,
+ 0xd82d,
+ 0x4d53,
+ 0xd765,
+ 0x4cc6,
+ 0xd69e,
+ 0x4c3a,
+ 0xd5d7,
+ 0x4baf,
+ 0xd512,
+ 0x4b24,
+ 0xd44e,
+ 0x4a9a,
+ 0xd38a,
+ 0x4a10,
+ 0xd2c8,
+ 0x4987,
+ 0xd206,
+ 0x48ff,
+ 0xd146,
+ 0x4878,
+ 0xd086,
+ 0x47f1,
+ 0xcfc7,
+ 0x476b,
+ 0xcf0a,
+ 0x46e5,
+ 0xce4d,
+ 0x4660,
+ 0xcd91,
+ 0x45dc,
+ 0xccd6,
+ 0x4558,
+ 0xcc1b,
+ 0x44d5,
+ 0xcb62,
+ 0x4453,
+ 0xcaa9,
+ 0x43d1,
+ 0xc9f2,
+ 0x434f,
+ 0xc93b,
+ 0x42cf,
+ 0xc885,
+ 0x424f,
+ 0xc7d0,
+ 0x41cf,
+ 0xc71c,
+ 0x4151,
+ 0xc669,
+ 0x40d2,
+ 0xc5b6,
+ 0x4055,
+ 0xc504,
+ 0x3fd8,
+ 0xc453,
+ 0x3f5b,
+ 0xc3a3,
+ 0x3edf,
+ 0xc2f4,
+ 0x3e64,
+ 0xc245,
+ 0x3de9,
+ 0xc198,
+ 0x3d6e,
+ 0xc0eb,
+ 0x3cf5,
+ 0xc03f,
+ 0x3c7c,
+ 0xbf93,
+ 0x3c03,
+ 0xbee9,
+ 0x3b8b,
+ 0xbe3f,
+ 0x3b13,
+ 0xbd96,
+ 0x3a9c,
+ 0xbced,
+ 0x3a26,
+ 0xbc46,
+ 0x39b0,
+ 0xbb9f,
+ 0x393a,
+ 0xbaf8,
+ 0x38c5,
+ 0xba53,
+ 0x3851,
+ 0xb9ae,
+ 0x37dd,
+ 0xb90a,
+ 0x3769,
+ 0xb867,
+ 0x36f6,
+ 0xb7c5,
+ 0x3684,
+ 0xb723,
+ 0x3612,
+ 0xb681,
+ 0x35a0,
+ 0xb5e1,
+ 0x352f,
+ 0xb541,
+ 0x34bf,
+ 0xb4a2,
+ 0x344f,
+ 0xb404,
+ 0x33df,
+ 0xb366,
+ 0x3370,
+ 0xb2c9,
+ 0x3302,
+ 0xb22c,
+ 0x3293,
+ 0xb191,
+ 0x3226,
+ 0xb0f5,
+ 0x31b9,
+ 0xb05b,
+ 0x314c,
+ 0xafc1,
+ 0x30df,
+ 0xaf28,
+ 0x3074,
+ 0xae8f,
+ 0x3008,
+ 0xadf7,
+ 0x2f9d,
+ 0xad60,
+ 0x2f33,
+ 0xacc9,
+ 0x2ec8,
+ 0xac33,
+ 0x2e5f,
+ 0xab9e,
+ 0x2df6,
+ 0xab09,
+ 0x2d8d,
+ 0xaa75,
+ 0x2d24,
+ 0xa9e1,
+ 0x2cbc,
+ 0xa94e,
+ 0x2c55,
+ 0xa8bc,
+ 0x2bee,
+ 0xa82a,
+ 0x2b87,
+ 0xa799,
+ 0x2b21,
+ 0xa708,
+ 0x2abb,
+ 0xa678,
+ 0x2a55,
+ 0xa5e8,
+ 0x29f0,
+ 0xa559,
+ 0x298b,
+ 0xa4cb,
+ 0x2927,
+ 0xa43d,
+ 0x28c3,
+ 0xa3b0,
+ 0x2860,
+ 0xa323,
+ 0x27fd,
+ 0xa297,
+ 0x279a,
+ 0xa20b,
+ 0x2738,
+ 0xa180,
+ 0x26d6,
+ 0xa0f6,
+ 0x2674,
+ 0xa06c,
+ 0x2613,
+ 0x9fe2,
+ 0x25b2,
+ 0x9f59,
+ 0x2552,
+ 0x9ed1,
+ 0x24f2,
+ 0x9e49,
+ 0x2492,
+ 0x9dc2,
+ 0x2432,
+ 0x9d3b,
+ 0x23d3,
+ 0x9cb4,
+ 0x2375,
+ 0x9c2f,
+ 0x2317,
+ 0x9ba9,
+ 0x22b9,
+ 0x9b25,
+ 0x225b,
+ 0x9aa0,
+ 0x21fe,
+ 0x9a1c,
+ 0x21a1,
+ 0x9999,
+ 0x2145,
+ 0x9916,
+ 0x20e8,
+ 0x9894,
+ 0x208d,
+ 0x9812,
+ 0x2031,
+ 0x9791,
+ 0x1fd6,
+ 0x9710,
+ 0x1f7b,
+ 0x968f,
+ 0x1f21,
+ 0x960f,
+ 0x1ec7,
+ 0x9590,
+ 0x1e6d,
+ 0x9511,
+ 0x1e13,
+ 0x9492,
+ 0x1dba,
+ 0x9414,
+ 0x1d61,
+ 0x9397,
+ 0x1d09,
+ 0x931a,
+ 0x1cb1,
+ 0x929d,
+ 0x1c59,
+ 0x9221,
+ 0x1c01,
+ 0x91a5,
+ 0x1baa,
+ 0x9129,
+ 0x1b53,
+ 0x90af,
+ 0x1afc,
+ 0x9034,
+ 0x1aa6,
+ 0x8fba,
+ 0x1a50,
+ 0x8f40,
+ 0x19fa,
+ 0x8ec7,
+ 0x19a5,
+ 0x8e4f,
+ 0x1950,
+ 0x8dd6,
+ 0x18fb,
+ 0x8d5e,
+ 0x18a7,
+ 0x8ce7,
+ 0x1853,
+ 0x8c70,
+ 0x17ff,
+ 0x8bf9,
+ 0x17ab,
+ 0x8b83,
+ 0x1758,
+ 0x8b0d,
+ 0x1705,
+ 0x8a98,
+ 0x16b2,
+ 0x8a23,
+ 0x1660,
+ 0x89ae,
+ 0x160d,
+ 0x893a,
+ 0x15bc,
+ 0x88c6,
+ 0x156a,
+ 0x8853,
+ 0x1519,
+ 0x87e0,
+ 0x14c8,
+ 0x876d,
+ 0x1477,
+ 0x86fb,
+ 0x1426,
+ 0x8689,
+ 0x13d6,
+ 0x8618,
+ 0x1386,
+ 0x85a7,
+ 0x1337,
+ 0x8536,
+ 0x12e7,
+ 0x84c6,
+ 0x1298,
+ 0x8456,
+ 0x1249,
+ 0x83e7,
+ 0x11fb,
+ 0x8377,
+ 0x11ac,
+ 0x8309,
+ 0x115e,
+ 0x829a,
+ 0x1111,
+ 0x822c,
+ 0x10c3,
+ 0x81bf,
+ 0x1076,
+ 0x8151,
+ 0x1029,
+ 0x80e4,
+ 0x0fdc,
+ 0x8078,
+ 0x0f8f,
+ 0x800c,
+ 0x0f43,
+ 0x7fa0,
+ 0x0ef7,
+ 0x7f34,
+ 0x0eab,
+ 0x7ec9,
+ 0x0e60,
+ 0x7e5e,
+ 0x0e15,
+ 0x7df4,
+ 0x0dca,
+ 0x7d8a,
+ 0x0d7f,
+ 0x7d20,
+ 0x0d34,
+ 0x7cb6,
+ 0x0cea,
+ 0x7c4d,
+ 0x0ca0,
+ 0x7be5,
+ 0x0c56,
+ 0x7b7c,
+ 0x0c0c,
+ 0x7b14,
+ 0x0bc3,
+ 0x7aac,
+ 0x0b7a,
+ 0x7a45,
+ 0x0b31,
+ 0x79de,
+ 0x0ae8,
+ 0x7977,
+ 0x0aa0,
+ 0x7911,
+ 0x0a58,
+ 0x78ab,
+ 0x0a10,
+ 0x7845,
+ 0x09c8,
+ 0x77df,
+ 0x0981,
+ 0x777a,
+ 0x0939,
+ 0x7715,
+ 0x08f2,
+ 0x76b1,
+ 0x08ab,
+ 0x764d,
+ 0x0865,
+ 0x75e9,
+ 0x081e,
+ 0x7585,
+ 0x07d8,
+ 0x7522,
+ 0x0792,
+ 0x74bf,
+ 0x074d,
+ 0x745d,
+ 0x0707,
+ 0x73fa,
+ 0x06c2,
+ 0x7398,
+ 0x067d,
+ 0x7337,
+ 0x0638,
+ 0x72d5,
+ 0x05f3,
+ 0x7274,
+ 0x05af,
+ 0x7213,
+ 0x056a,
+ 0x71b3,
+ 0x0526,
+ 0x7152,
+ 0x04e2,
+ 0x70f2,
+ 0x049f,
+ 0x7093,
+ 0x045b,
+ 0x7033,
+ 0x0418,
+ 0x6fd4,
+ 0x03d5,
+ 0x6f76,
+ 0x0392,
+ 0x6f17,
+ 0x0350,
+ 0x6eb9,
+ 0x030d,
+ 0x6e5b,
+ 0x02cb,
+ 0x6dfd,
+ 0x0289,
+ 0x6da0,
+ 0x0247,
+ 0x6d43,
+ 0x0206,
+ 0x6ce6,
+ 0x01c4,
+ 0x6c8a,
+ 0x0183,
+ 0x6c2d,
+ 0x0142,
+ 0x6bd1,
+ 0x0101,
+ 0x6b76,
+ 0x00c0,
+ 0x6b1a,
+ 0x0080,
+ 0x6abf,
+ 0x0040,
+ 0x6a64
+};
diff --git a/trunk/src/emu/cpu/rsp/rspdrc.c b/trunk/src/emu/cpu/rsp/rspdrc.c
new file mode 100644
index 00000000000..fff466a2e53
--- /dev/null
+++ b/trunk/src/emu/cpu/rsp/rspdrc.c
@@ -0,0 +1,4848 @@
+/***************************************************************************
+
+ rspdrc.c
+
+ Universal machine language-based Nintendo/SGI RSP emulator.
+ Written by Harmony of the MESS team.
+
+ Copyright the MESS team.
+ Released for general non-commercial use under the MAME license
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+****************************************************************************
+
+ Future improvements/changes:
+
+ * Confer with Aaron Giles about adding a memory hash-based caching
+ system and static recompilation for maximum overhead minimization
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "profiler.h"
+#include "rsp.h"
+#include "rspdiv.h"
+#include "rspfe.h"
+#include "cpu/drcfe.h"
+#include "cpu/drcuml.h"
+#include "cpu/drcumlsh.h"
+
+using namespace uml;
+
+CPU_DISASSEMBLE( rsp );
+
+extern offs_t rsp_dasm_one(char *buffer, offs_t pc, UINT32 op);
+
+#ifdef USE_RSPDRC
+
+/***************************************************************************
+ DEBUGGING
+***************************************************************************/
+
+#define FORCE_C_BACKEND (0)
+#define LOG_UML (0)
+#define LOG_NATIVE (0)
+
+#define SINGLE_INSTRUCTION_MODE (0)
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* map variables */
+#define MAPVAR_PC M0
+#define MAPVAR_CYCLES M1
+
+/* 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) rsp->impstate->regmap[reg]
+
+/***************************************************************************
+ 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 */
+};
+
+
+/* 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 */
+};
+
+struct _rspimp_state
+{
+ /* core state */
+ drc_cache * cache; /* pointer to the DRC code cache */
+ drcuml_state * drcuml; /* DRC UML generator state */
+ rsp_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 */
+ const char * format; /* format string for print_debug */
+ UINT32 arg0; /* print_debug argument 1 */
+ UINT32 arg1; /* print_debug argument 2 */
+ UINT32 arg2; /* print_debug argument 3 */
+ UINT32 arg3; /* print_debug argument 4 */
+ UINT32 vres[8]; /* used for temporary vector results */
+
+ /* register mappings */
+ parameter regmap[32]; /* 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 * read8; /* read byte */
+ code_handle * write8; /* write byte */
+ code_handle * read16; /* read half */
+ code_handle * write16; /* write half */
+ code_handle * read32; /* read word */
+ code_handle * write32; /* write word */
+};
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void code_flush_cache(rsp_state *rsp);
+static void code_compile_block(rsp_state *rsp, offs_t pc);
+
+static void cfunc_unimplemented(void *param);
+static void cfunc_set_cop0_reg(void *param);
+static void cfunc_get_cop0_reg(void *param);
+static void cfunc_mfc2(void *param);
+static void cfunc_cfc2(void *param);
+static void cfunc_mtc2(void *param);
+static void cfunc_ctc2(void *param);
+//static void cfunc_swc2(void *param);
+//static void cfunc_lwc2(void *param);
+static void cfunc_sp_set_status_cb(void *param);
+
+static void cfunc_rsp_lbv(void *param);
+static void cfunc_rsp_lsv(void *param);
+static void cfunc_rsp_llv(void *param);
+static void cfunc_rsp_ldv(void *param);
+static void cfunc_rsp_lqv(void *param);
+static void cfunc_rsp_lrv(void *param);
+static void cfunc_rsp_lpv(void *param);
+static void cfunc_rsp_luv(void *param);
+static void cfunc_rsp_lhv(void *param);
+static void cfunc_rsp_lfv(void *param);
+static void cfunc_rsp_lwv(void *param);
+static void cfunc_rsp_ltv(void *param);
+
+static void cfunc_rsp_sbv(void *param);
+static void cfunc_rsp_ssv(void *param);
+static void cfunc_rsp_slv(void *param);
+static void cfunc_rsp_sdv(void *param);
+static void cfunc_rsp_sqv(void *param);
+static void cfunc_rsp_srv(void *param);
+static void cfunc_rsp_spv(void *param);
+static void cfunc_rsp_suv(void *param);
+static void cfunc_rsp_shv(void *param);
+static void cfunc_rsp_sfv(void *param);
+static void cfunc_rsp_swv(void *param);
+static void cfunc_rsp_stv(void *param);
+
+static void static_generate_entry_point(rsp_state *rsp);
+static void static_generate_nocode_handler(rsp_state *rsp);
+static void static_generate_out_of_cycles(rsp_state *rsp);
+static void static_generate_memory_accessor(rsp_state *rsp, int size, int iswrite, const char *name, code_handle *&handleptr);
+
+static int generate_lwc2(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static int generate_swc2(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static void generate_update_cycles(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, parameter param, int allow_exception);
+static void generate_checksum_block(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast);
+static void generate_sequence_instruction(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static void generate_delay_slot_and_branch(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT8 linkreg);
+static int generate_opcode(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static int generate_special(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static int generate_regimm(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static int generate_cop0(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static int generate_cop2(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+
+static void log_add_disasm_comment(rsp_state *rsp, drcuml_block *block, UINT32 pc, UINT32 op);
+
+/***************************************************************************
+ HELPFUL DEFINES
+***************************************************************************/
+
+#define VDREG ((op >> 6) & 0x1f)
+#define VS1REG ((op >> 11) & 0x1f)
+#define VS2REG ((op >> 16) & 0x1f)
+#define EL ((op >> 21) & 0xf)
+
+#define VREG_B(reg, offset) rsp->v[(reg)].b[BYTE4_XOR_BE(offset)]
+#define VREG_S(reg, offset) rsp->v[(reg)].s[(offset)^1]
+
+#define VEC_EL_2(x,z) (vector_elements_2[(x)][(z)])
+
+#define ACCUM(x) rsp->accum[x].q
+#define ACCUM_H(x) rsp->accum[((x))].w[3]
+#define ACCUM_M(x) rsp->accum[((x))].w[2]
+#define ACCUM_L(x) rsp->accum[((x))].w[1]
+
+#define CARRY_FLAG(x) ((rsp->flag[0] & (1 << (x))) ? 1 : 0)
+#define CLEAR_CARRY_FLAGS() { rsp->flag[0] &= ~0xff; }
+#define SET_CARRY_FLAG(x) { rsp->flag[0] |= (1 << (x)); }
+#define CLEAR_CARRY_FLAG(x) { rsp->flag[0] &= ~(1 << (x)); }
+
+#define COMPARE_FLAG(x) ((rsp->flag[1] & (1 << (x))) ? 1 : 0)
+#define CLEAR_COMPARE_FLAGS() { rsp->flag[1] &= ~0xff; }
+#define SET_COMPARE_FLAG(x) { rsp->flag[1] |= (1 << (x)); }
+#define CLEAR_COMPARE_FLAG(x) { rsp->flag[1] &= ~(1 << (x)); }
+
+#define ZERO_FLAG(x) ((rsp->flag[0] & (0x100 << (x))) ? 1 : 0)
+#define CLEAR_ZERO_FLAGS() { rsp->flag[0] &= ~0xff00; }
+#define SET_ZERO_FLAG(x) { rsp->flag[0] |= (0x100 << (x)); }
+#define CLEAR_ZERO_FLAG(x) { rsp->flag[0] &= ~(0x100 << (x)); }
+
+INLINE rsp_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == RSP);
+ return *(rsp_state **)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ 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) | 0x1000;
+}
+
+
+/*-------------------------------------------------
+ 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(rsp_state *rsp, drcuml_block *block)
+{
+ int regnum;
+
+ for (regnum = 0; regnum < ARRAY_LENGTH(rsp->impstate->regmap); regnum++)
+ if (rsp->impstate->regmap[regnum].is_int_register())
+ UML_MOV(block, ireg(rsp->impstate->regmap[regnum].ireg() - REG_I0), mem(&rsp->r[regnum]));
+}
+
+
+/*-------------------------------------------------
+ save_fast_iregs - save any fast integer
+ registers
+-------------------------------------------------*/
+
+INLINE void save_fast_iregs(rsp_state *rsp, drcuml_block *block)
+{
+ int regnum;
+
+ for (regnum = 0; regnum < ARRAY_LENGTH(rsp->impstate->regmap); regnum++)
+ if (rsp->impstate->regmap[regnum].is_int_register())
+ UML_MOV(block, mem(&rsp->r[regnum]), ireg(rsp->impstate->regmap[regnum].ireg() - REG_I0));
+}
+
+/***************************************************************************
+ CORE CALLBACKS
+***************************************************************************/
+
+INLINE UINT8 READ8(rsp_state *rsp, UINT32 address)
+{
+ UINT8 ret;
+ address = 0x04000000 | (address & 0xfff);
+ ret = rsp->program->read_byte(address);
+ //printf("%04xr%02x\n",address & 0x1fff, ret);
+ return ret;
+}
+
+static void cfunc_read8(void *param)
+{
+ rsp_state *rsp = (rsp_state *)param;
+ rsp->impstate->arg0 = READ8(rsp, rsp->impstate->arg0);
+}
+
+INLINE UINT16 READ16(rsp_state *rsp, UINT32 address)
+{
+ UINT16 ret;
+ address = 0x04000000 | (address & 0xfff);
+ ret = rsp->program->read_byte(address+0) << 8;
+ ret |= rsp->program->read_byte(address+1) << 0;
+ //printf("%04xr%04x\n",address & 0x1fff, ret);
+ return ret;
+}
+
+static void cfunc_read16(void *param)
+{
+ rsp_state *rsp = (rsp_state *)param;
+ rsp->impstate->arg0 = READ16(rsp, rsp->impstate->arg0);
+}
+
+INLINE UINT32 READ32(rsp_state *rsp, UINT32 address)
+{
+ UINT32 ret;
+ address = 0x04000000 | (address & 0xfff);
+ ret = rsp->program->read_byte(address+0) << 24;
+ ret |= rsp->program->read_byte(address+1) << 16;
+ ret |= rsp->program->read_byte(address+2) << 8;
+ ret |= rsp->program->read_byte(address+3) << 0;
+ //printf("%04xr%08x\n",address & 0x1fff, ret);
+ return ret;
+}
+
+static void cfunc_read32(void *param)
+{
+ rsp_state *rsp = (rsp_state *)param;
+ rsp->impstate->arg0 = READ32(rsp, rsp->impstate->arg0);
+}
+
+INLINE void WRITE8(rsp_state *rsp, UINT32 address, UINT8 data)
+{
+ address = 0x04000000 | (address & 0xfff);
+ //printf("%04x:%02x\n",address & 0x1fff, data);
+ rsp->program->write_byte(address, data);
+}
+
+static void cfunc_write8(void *param)
+{
+ rsp_state *rsp = (rsp_state *)param;
+ WRITE8(rsp, rsp->impstate->arg0, (UINT8)rsp->impstate->arg1);
+}
+
+INLINE void WRITE16(rsp_state *rsp, UINT32 address, UINT16 data)
+{
+ address = 0x04000000 | (address & 0xfff);
+
+ //printf("%04x:%04x\n",address & 0x1fff, data);
+ rsp->program->write_byte(address + 0, (data >> 8) & 0xff);
+ rsp->program->write_byte(address + 1, (data >> 0) & 0xff);
+}
+
+static void cfunc_write16(void *param)
+{
+ rsp_state *rsp = (rsp_state *)param;
+ WRITE16(rsp, rsp->impstate->arg0, (UINT16)rsp->impstate->arg1);
+}
+
+INLINE void WRITE32(rsp_state *rsp, UINT32 address, UINT32 data)
+{
+ address = 0x04000000 | (address & 0xfff);
+
+ //printf("%04x:%08x\n",address & 0x1fff, data);
+ rsp->program->write_byte(address + 0, (data >> 24) & 0xff);
+ rsp->program->write_byte(address + 1, (data >> 16) & 0xff);
+ rsp->program->write_byte(address + 2, (data >> 8) & 0xff);
+ rsp->program->write_byte(address + 3, (data >> 0) & 0xff);
+}
+
+static void cfunc_write32(void *param)
+{
+ rsp_state *rsp = (rsp_state *)param;
+ WRITE32(rsp, rsp->impstate->arg0, rsp->impstate->arg1);
+}
+
+/*****************************************************************************/
+
+/*-------------------------------------------------
+ rspdrc_set_options - configure DRC options
+-------------------------------------------------*/
+
+void rspdrc_set_options(device_t *device, UINT32 options)
+{
+ rsp_state *rsp = get_safe_token(device);
+ rsp->impstate->drcoptions = options;
+}
+
+
+/*-------------------------------------------------
+ cfunc_printf_debug - generic printf for
+ debugging
+-------------------------------------------------*/
+
+#ifdef UNUSED_CODE
+static void cfunc_printf_debug(void *param)
+{
+ rsp_state *rsp = (rsp_state *)param;
+ switch(rsp->impstate->arg2)
+ {
+ case 0: // WRITE8
+ printf("%04x:%02x\n", rsp->impstate->arg0 & 0x0fff, (UINT8)rsp->impstate->arg1);
+ break;
+ case 1: // WRITE16
+ printf("%04x:%04x\n", rsp->impstate->arg0 & 0x0fff, (UINT16)rsp->impstate->arg1);
+ break;
+ case 2: // WRITE32
+ printf("%04x:%08x\n", rsp->impstate->arg0 & 0x0fff, rsp->impstate->arg1);
+ break;
+ case 3: // READ8
+ printf("%04xr%02x\n", rsp->impstate->arg0 & 0x0fff, (UINT8)rsp->impstate->arg1);
+ break;
+ case 4: // READ16
+ printf("%04xr%04x\n", rsp->impstate->arg0 & 0x0fff, (UINT16)rsp->impstate->arg1);
+ break;
+ case 5: // READ32
+ printf("%04xr%08x\n", rsp->impstate->arg0 & 0x0fff, rsp->impstate->arg1);
+ break;
+ default: // ???
+ printf("%08x %08x\n", rsp->impstate->arg0 & 0x0fff, rsp->impstate->arg1);
+ break;
+ }
+}
+#endif
+
+static void cfunc_get_cop0_reg(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int reg = rsp->impstate->arg0;
+ int dest = rsp->impstate->arg1;
+
+ if (reg >= 0 && reg < 8)
+ {
+ if(dest)
+ {
+ rsp->r[dest] = (rsp->config->sp_reg_r)(rsp->device, reg, 0x00000000);
+ }
+ }
+ else if (reg >= 8 && reg < 16)
+ {
+ if(dest)
+ {
+ rsp->r[dest] = (rsp->config->dp_reg_r)(rsp->device, reg - 8, 0x00000000);
+ }
+ }
+ else
+ {
+ fatalerror("RSP: cfunc_get_cop0_reg: %d", reg);
+ }
+}
+
+static void cfunc_set_cop0_reg(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int reg = rsp->impstate->arg0;
+ UINT32 data = rsp->impstate->arg1;
+
+ if (reg >= 0 && reg < 8)
+ {
+ (rsp->config->sp_reg_w)(rsp->device, reg, data, 0x00000000);
+ }
+ else if (reg >= 8 && reg < 16)
+ {
+ (rsp->config->dp_reg_w)(rsp->device, reg - 8, data, 0x00000000);
+ }
+ else
+ {
+ fatalerror("RSP: set_cop0_reg: %d, %08X\n", reg, data);
+ }
+}
+
+static void cfunc_unimplemented_opcode(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ if ((rsp->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ {
+ char string[200];
+ rsp_dasm_one(string, rsp->ppc, op);
+ mame_printf_debug("%08X: %s\n", rsp->ppc, string);
+ }
+
+ fatalerror("RSP: unknown opcode %02X (%08X) at %08X\n", op >> 26, op, rsp->ppc);
+}
+
+static void unimplemented_opcode(rsp_state *rsp, UINT32 op)
+{
+ if ((rsp->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ {
+ char string[200];
+ rsp_dasm_one(string, rsp->ppc, op);
+ mame_printf_debug("%08X: %s\n", rsp->ppc, string);
+ }
+
+ fatalerror("RSP: unknown opcode %02X (%08X) at %08X\n", op >> 26, op, rsp->ppc);
+}
+
+/*****************************************************************************/
+
+/* Legacy. Going forward, this will be transitioned into unrolled opcode decodes. */
+static const int vector_elements_1[16][8] =
+{
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // none
+ { 0, 1, 2, 3, 4, 5, 6 ,7 }, // ???
+ { 1, 3, 5, 7, 0, 2, 4, 6 }, // 0q
+ { 0, 2, 4, 6, 1, 3, 5, 7 }, // 1q
+ { 1, 2, 3, 5, 6, 7, 0, 4 }, // 0h
+ { 0, 2, 3, 4, 6, 7, 1, 5 }, // 1h
+ { 0, 1, 3, 4, 5, 7, 2, 6 }, // 2h
+ { 0, 1, 2, 4, 5, 6, 3, 7 }, // 3h
+ { 1, 2, 3, 4, 5, 6, 7, 0 }, // 0
+ { 0, 2, 3, 4, 5, 6, 7, 1 }, // 1
+ { 0, 1, 3, 4, 5, 6, 7, 2 }, // 2
+ { 0, 1, 2, 4, 5, 6, 7, 3 }, // 3
+ { 0, 1, 2, 3, 5, 6, 7, 4 }, // 4
+ { 0, 1, 2, 3, 4, 6, 7, 5 }, // 5
+ { 0, 1, 2, 3, 4, 5, 7, 6 }, // 6
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // 7
+};
+
+/* Legacy. Going forward, this will be transitioned into unrolled opcode decodes. */
+static const int vector_elements_2[16][8] =
+{
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // none
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // ???
+ { 0, 0, 2, 2, 4, 4, 6, 6 }, // 0q
+ { 1, 1, 3, 3, 5, 5, 7, 7 }, // 1q
+ { 0, 0, 0, 0, 4, 4, 4, 4 }, // 0h
+ { 1, 1, 1, 1, 5, 5, 5, 5 }, // 1h
+ { 2, 2, 2, 2, 6, 6, 6, 6 }, // 2h
+ { 3, 3, 3, 3, 7, 7, 7, 7 }, // 3h
+ { 0, 0, 0, 0, 0, 0, 0, 0 }, // 0
+ { 1, 1, 1, 1, 1, 1, 1, 1 }, // 1
+ { 2, 2, 2, 2, 2, 2, 2, 2 }, // 2
+ { 3, 3, 3, 3, 3, 3, 3, 3 }, // 3
+ { 4, 4, 4, 4, 4, 4, 4, 4 }, // 4
+ { 5, 5, 5, 5, 5, 5, 5, 5 }, // 5
+ { 6, 6, 6, 6, 6, 6, 6, 6 }, // 6
+ { 7, 7, 7, 7, 7, 7, 7, 7 }, // 7
+};
+
+static void rspcom_init(rsp_state *rsp, legacy_cpu_device *device, device_irq_callback irqcallback)
+{
+ int regIdx = 0;
+ int accumIdx;
+
+ memset(rsp, 0, sizeof(*rsp));
+
+ rsp->config = (const rsp_config *)device->static_config();
+ rsp->irq_callback = irqcallback;
+ rsp->device = device;
+ rsp->program = device->space(AS_PROGRAM);
+ rsp->direct = &rsp->program->direct();
+
+#if 1
+ // Inaccurate. RSP registers power on to a random state...
+ for(regIdx = 0; regIdx < 32; regIdx++ )
+ {
+ rsp->r[regIdx] = 0;
+ rsp->v[regIdx].d[0] = 0;
+ rsp->v[regIdx].d[1] = 0;
+ }
+ rsp->flag[0] = 0;
+ rsp->flag[1] = 0;
+ rsp->flag[2] = 0;
+ rsp->flag[3] = 0;
+ rsp->square_root_res = 0;
+ rsp->square_root_high = 0;
+ rsp->reciprocal_res = 0;
+ rsp->reciprocal_high = 0;
+#endif
+
+ // ...except for the accumulators.
+ for(accumIdx = 0; accumIdx < 8; accumIdx++ )
+ {
+ rsp->accum[accumIdx].q = 0;
+ }
+
+ rsp->sr = RSP_STATUS_HALT;
+ rsp->step_count = 0;
+}
+
+static CPU_INIT( rsp )
+{
+ rsp_state *rsp;
+ drc_cache *cache;
+ UINT32 flags = 0;
+ int regnum;
+ //int elnum;
+
+ /* allocate enough space for the cache and the core */
+ cache = auto_alloc(device->machine(), drc_cache(CACHE_SIZE + sizeof(*rsp)));
+
+ /* allocate the core memory */
+ *(rsp_state **)device->token() = rsp = (rsp_state *)cache->alloc_near(sizeof(*rsp));
+ memset(rsp, 0, sizeof(*rsp));
+
+ rspcom_init(rsp, device, irqcallback);
+
+ /* allocate the implementation-specific state from the full cache */
+ rsp->impstate = (rspimp_state *)cache->alloc_near(sizeof(*rsp->impstate));
+ memset(rsp->impstate, 0, sizeof(*rsp->impstate));
+ rsp->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;
+ }
+ rsp->impstate->drcuml = auto_alloc(device->machine(), drcuml_state(*device, *cache, flags, 8, 32, 2));
+
+ /* add symbols for our stuff */
+ rsp->impstate->drcuml->symbol_add(&rsp->pc, sizeof(rsp->pc), "pc");
+ rsp->impstate->drcuml->symbol_add(&rsp->icount, sizeof(rsp->icount), "icount");
+ for (regnum = 0; regnum < 32; regnum++)
+ {
+ char buf[10];
+ sprintf(buf, "r%d", regnum);
+ rsp->impstate->drcuml->symbol_add(&rsp->r[regnum], sizeof(rsp->r[regnum]), buf);
+ }
+ rsp->impstate->drcuml->symbol_add(&rsp->impstate->arg0, sizeof(rsp->impstate->arg0), "arg0");
+ rsp->impstate->drcuml->symbol_add(&rsp->impstate->arg1, sizeof(rsp->impstate->arg1), "arg1");
+ rsp->impstate->drcuml->symbol_add(&rsp->impstate->arg2, sizeof(rsp->impstate->arg2), "arg2");
+ rsp->impstate->drcuml->symbol_add(&rsp->impstate->arg3, sizeof(rsp->impstate->arg3), "arg3");
+ rsp->impstate->drcuml->symbol_add(&rsp->impstate->numcycles, sizeof(rsp->impstate->numcycles), "numcycles");
+
+ /* initialize the front-end helper */
+ rsp->impstate->drcfe = auto_alloc(device->machine(), rsp_frontend(*rsp, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE));
+
+ /* compute the register parameters */
+ for (regnum = 0; regnum < 32; regnum++)
+ rsp->impstate->regmap[regnum] = (regnum == 0) ? parameter(0) : parameter::make_memory(&rsp->r[regnum]);
+
+ /*
+ drcbe_info beinfo;
+ rsp->impstate->drcuml->get_backend_info(beinfo);
+ if (beinfo.direct_iregs > 2)
+ {
+ rsp->impstate->regmap[30] = I2;
+ }
+ if (beinfo.direct_iregs > 3)
+ {
+ rsp->impstate->regmap[31] = I3;
+ }
+ if (beinfo.direct_iregs > 4)
+ {
+ rsp->impstate->regmap[2] = I4;
+ }
+ if (beinfo.direct_iregs > 5)
+ {
+ rsp->impstate->regmap[3] = I5;
+ }
+ if (beinfo.direct_iregs > 6)
+ {
+ rsp->impstate->regmap[4] = I6;
+ }
+ */
+
+ /* mark the cache dirty so it is updated on next execute */
+ rsp->impstate->cache_dirty = TRUE;
+}
+
+static CPU_EXIT( rsp )
+{
+ rsp_state *rsp = get_safe_token(device);
+
+ /* clean up the DRC */
+ auto_free(device->machine(), rsp->impstate->drcfe);
+ auto_free(device->machine(), rsp->impstate->drcuml);
+ auto_free(device->machine(), rsp->impstate->cache);
+}
+
+
+static CPU_RESET( rsp )
+{
+ rsp_state *rsp = get_safe_token(device);
+ rsp->nextpc = ~0;
+}
+
+static void cfunc_rsp_lbv(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ UINT32 ea = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 00000 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Load 1 byte to vector byte index
+
+ ea = (base) ? rsp->r[base] + offset : offset;
+ VREG_B(dest, index) = READ8(rsp, ea);
+}
+
+static void cfunc_rsp_lsv(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ UINT32 ea = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 00001 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads 2 bytes starting from vector byte index
+
+ ea = (base) ? rsp->r[base] + (offset * 2) : (offset * 2);
+
+ int end = index + 2;
+
+ for (int i = index; i < end; i++)
+ {
+ VREG_B(dest, i) = READ8(rsp, ea);
+ ea++;
+ }
+}
+
+static void cfunc_rsp_llv(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ UINT32 ea = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 00010 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads 4 bytes starting from vector byte index
+
+ ea = (base) ? rsp->r[base] + (offset * 4) : (offset * 4);
+
+ int end = index + 4;
+
+ for (int i = index; i < end; i++)
+ {
+ VREG_B(dest, i) = READ8(rsp, ea);
+ ea++;
+ }
+}
+
+static void cfunc_rsp_ldv(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ UINT32 ea = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 00011 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads 8 bytes starting from vector byte index
+
+ ea = (base) ? rsp->r[base] + (offset * 8) : (offset * 8);
+
+ int end = index + 8;
+
+ for (int i = index; i < end; i++)
+ {
+ VREG_B(dest, i) = READ8(rsp, ea);
+ ea++;
+ }
+}
+
+static void cfunc_rsp_lqv(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ int i = 0;
+ int end = 0;
+ UINT32 ea = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 00100 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads up to 16 bytes starting from vector byte index
+
+ ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
+
+ end = index + (16 - (ea & 0xf));
+ if (end > 16) end = 16;
+ for (i=index; i < end; i++)
+ {
+ VREG_B(dest, i) = READ8(rsp, ea);
+ ea++;
+ }
+}
+
+static void cfunc_rsp_lrv(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ int i = 0;
+ int end = 0;
+ UINT32 ea = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 00101 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores up to 16 bytes starting from right side until 16-byte boundary
+
+ ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
+
+ index = 16 - ((ea & 0xf) - index);
+ end = 16;
+ ea &= ~0xf;
+
+ for (i=index; i < end; i++)
+ {
+ VREG_B(dest, i) = READ8(rsp, ea);
+ ea++;
+ }
+}
+
+static void cfunc_rsp_lpv(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ int i = 0;
+ UINT32 ea = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 00110 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads a byte as the upper 8 bits of each element
+
+ ea = (base) ? rsp->r[base] + (offset * 8) : (offset * 8);
+
+ for (i=0; i < 8; i++)
+ {
+ VREG_S(dest, i) = READ8(rsp, ea + (((16-index) + i) & 0xf)) << 8;
+ }
+}
+
+static void cfunc_rsp_luv(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ int i = 0;
+ UINT32 ea = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 00111 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads a byte as the bits 14-7 of each element
+
+ ea = (base) ? rsp->r[base] + (offset * 8) : (offset * 8);
+
+ for (i=0; i < 8; i++)
+ {
+ VREG_S(dest, i) = READ8(rsp, ea + (((16-index) + i) & 0xf)) << 7;
+ }
+}
+
+static void cfunc_rsp_lhv(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ int i = 0;
+ UINT32 ea = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 01000 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads a byte as the bits 14-7 of each element, with 2-byte stride
+
+ ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
+
+ for (i=0; i < 8; i++)
+ {
+ VREG_S(dest, i) = READ8(rsp, ea + (((16-index) + (i<<1)) & 0xf)) << 7;
+ }
+}
+
+static void cfunc_rsp_lfv(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ int i = 0;
+ int end = 0;
+ UINT32 ea = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 01001 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads a byte as the bits 14-7 of upper or lower quad, with 4-byte stride
+
+
+ ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
+
+ // not sure what happens if 16-byte boundary is crossed...
+
+ end = (index >> 1) + 4;
+
+ for (i=index >> 1; i < end; i++)
+ {
+ VREG_S(dest, i) = READ8(rsp, ea) << 7;
+ ea += 4;
+ }
+}
+
+static void cfunc_rsp_lwv(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ int i = 0;
+ int end = 0;
+ UINT32 ea = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 01010 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads the full 128-bit vector starting from vector byte index and wrapping to index 0
+ // after byte index 15
+
+ ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
+
+ end = (16 - index) + 16;
+
+ for (i=(16 - index); i < end; i++)
+ {
+ VREG_B(dest, i & 0xf) = READ8(rsp, ea);
+ ea += 4;
+ }
+}
+
+static void cfunc_rsp_ltv(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ int i = 0;
+ UINT32 ea = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 01011 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads one element to maximum of 8 vectors, while incrementing element index
+
+ // FIXME: has a small problem with odd indices
+
+ int element;
+ int vs = dest;
+ int ve = dest + 8;
+ if (ve > 32)
+ {
+ ve = 32;
+ }
+
+ element = 7 - (index >> 1);
+
+ ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
+
+ ea = ((ea + 8) & ~0xf) + (index & 1);
+ for (i = vs; i < ve; i++)
+ {
+ element = ((8 - (index >> 1) + (i - vs)) << 1);
+ VREG_B(i, (element & 0xf)) = READ8(rsp, ea);
+ VREG_B(i, ((element + 1) & 0xf)) = READ8(rsp, ea + 1);
+
+ ea += 2;
+ }
+}
+
+static int generate_lwc2(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ //int loopdest;
+ UINT32 op = desc->opptr.l[0];
+ //int dest = (op >> 16) & 0x1f;
+ //int base = (op >> 21) & 0x1f;
+ //int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ //int skip;
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ switch ((op >> 11) & 0x1f)
+ {
+ case 0x00: /* LBV */
+ //UML_ADD(block, I0, R32(RSREG), offset);
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_lbv, rsp);
+ return TRUE;
+ case 0x01: /* LSV */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_lsv, rsp);
+ return TRUE;
+ case 0x02: /* LLV */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_llv, rsp);
+ return TRUE;
+ case 0x03: /* LDV */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_ldv, rsp);
+ return TRUE;
+ case 0x04: /* LQV */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_lqv, rsp);
+ return TRUE;
+ case 0x05: /* LRV */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_lrv, rsp);
+ return TRUE;
+ case 0x06: /* LPV */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_lpv, rsp);
+ return TRUE;
+ case 0x07: /* LUV */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_luv, rsp);
+ return TRUE;
+ case 0x08: /* LHV */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_lhv, rsp);
+ return TRUE;
+ case 0x09: /* LFV */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_lfv, rsp);
+ return TRUE;
+ case 0x0a: /* LWV */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_lwv, rsp);
+ return TRUE;
+ case 0x0b: /* LTV */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_ltv, rsp);
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+static void cfunc_rsp_sbv(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ UINT32 ea = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00000 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores 1 byte from vector byte index
+
+ ea = (base) ? rsp->r[base] + offset : offset;
+ WRITE8(rsp, ea, VREG_B(dest, index));
+}
+
+static void cfunc_rsp_ssv(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ UINT32 ea = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00001 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores 2 bytes starting from vector byte index
+
+ ea = (base) ? rsp->r[base] + (offset * 2) : (offset * 2);
+
+ int end = index + 2;
+
+ for (int i = index; i < end; i++)
+ {
+ WRITE8(rsp, ea, VREG_B(dest, i));
+ ea++;
+ }
+}
+
+static void cfunc_rsp_slv(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ UINT32 ea = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00010 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores 4 bytes starting from vector byte index
+
+ ea = (base) ? rsp->r[base] + (offset * 4) : (offset * 4);
+
+ int end = index + 4;
+
+ for (int i = index; i < end; i++)
+ {
+ WRITE8(rsp, ea, VREG_B(dest, i));
+ ea++;
+ }
+}
+
+static void cfunc_rsp_sdv(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ UINT32 ea = 0;
+ int end = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00011 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores 8 bytes starting from vector byte index
+ ea = (base) ? rsp->r[base] + (offset * 8) : (offset * 8);
+
+ end = index + 8;
+
+ for (int i = index; i < end; i++)
+ {
+ WRITE8(rsp, ea, VREG_B(dest, i));
+ ea++;
+ }
+}
+
+static void cfunc_rsp_sqv(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ UINT32 ea = 0;
+ int i = 0;
+ int end = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00100 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores up to 16 bytes starting from vector byte index until 16-byte boundary
+
+ ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
+
+ end = index + (16 - (ea & 0xf));
+
+ for (i=index; i < end; i++)
+ {
+ WRITE8(rsp, ea, VREG_B(dest, i & 0xf));
+ ea++;
+ }
+}
+
+static void cfunc_rsp_srv(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00101 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores up to 16 bytes starting from right side until 16-byte boundary
+
+ UINT32 ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
+
+ int end = index + (ea & 0xf);
+ int o = (16 - (ea & 0xf)) & 0xf;
+ ea &= ~0xf;
+
+ for (int i = index; i < end; i++)
+ {
+ WRITE8(rsp, ea, VREG_B(dest, ((i + o) & 0xf)));
+ ea++;
+ }
+}
+
+static void cfunc_rsp_spv(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ UINT32 ea = 0;
+ int i = 0;
+ int end = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00110 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores upper 8 bits of each element
+
+ ea = (base) ? rsp->r[base] + (offset * 8) : (offset * 8);
+ end = index + 8;
+
+ for (i=index; i < end; i++)
+ {
+ if ((i & 0xf) < 8)
+ {
+ WRITE8(rsp, ea, VREG_B(dest, ((i & 0xf) << 1)));
+ }
+ else
+ {
+ WRITE8(rsp, ea, VREG_S(dest, (i & 0x7)) >> 7);
+ }
+ ea++;
+ }
+}
+
+static void cfunc_rsp_suv(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ UINT32 ea = 0;
+ int i = 0;
+ int end = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00111 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores bits 14-7 of each element
+
+ ea = (base) ? rsp->r[base] + (offset * 8) : (offset * 8);
+ end = index + 8;
+
+ for (i=index; i < end; i++)
+ {
+ if ((i & 0xf) < 8)
+ {
+ WRITE8(rsp, ea, VREG_S(dest, (i & 0x7)) >> 7);
+ }
+ else
+ {
+ WRITE8(rsp, ea, VREG_B(dest, ((i & 0x7) << 1)));
+ }
+ ea++;
+ }
+}
+
+static void cfunc_rsp_shv(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ UINT32 ea = 0;
+ int i = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 01000 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores bits 14-7 of each element, with 2-byte stride
+
+ ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
+
+ for (i=0; i < 8; i++)
+ {
+ UINT8 d = ((VREG_B(dest, ((index + (i << 1) + 0) & 0xf))) << 1) |
+ ((VREG_B(dest, ((index + (i << 1) + 1) & 0xf))) >> 7);
+
+ WRITE8(rsp, ea, d);
+ ea += 2;
+ }
+}
+
+static void cfunc_rsp_sfv(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ UINT32 ea = 0;
+ int i = 0;
+ int end = 0;
+ int eaoffset = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 01001 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores bits 14-7 of upper or lower quad, with 4-byte stride
+
+ if (index & 0x7) printf("RSP: SFV: index = %d at %08X\n", index, rsp->ppc);
+
+ ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
+
+ eaoffset = ea & 0xf;
+ ea &= ~0xf;
+
+ end = (index >> 1) + 4;
+
+ for (i=index >> 1; i < end; i++)
+ {
+ WRITE8(rsp, ea + (eaoffset & 0xf), VREG_S(dest, i) >> 7);
+ eaoffset += 4;
+ }
+}
+
+static void cfunc_rsp_swv(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ UINT32 ea = 0;
+ int i = 0;
+ int end = 0;
+ int eaoffset = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 01010 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores the full 128-bit vector starting from vector byte index and wrapping to index 0
+ // after byte index 15
+
+ ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
+
+ eaoffset = ea & 0xf;
+ ea &= ~0xf;
+
+ end = index + 16;
+
+ for (i=index; i < end; i++)
+ {
+ WRITE8(rsp, ea + (eaoffset & 0xf), VREG_B(dest, i & 0xf));
+ eaoffset++;
+ }
+}
+
+static void cfunc_rsp_stv(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ UINT32 ea = 0;
+ int i = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 01011 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores one element from maximum of 8 vectors, while incrementing element index
+
+ int vs = dest;
+ int ve = dest + 8;
+ if (ve > 32)
+ {
+ ve = 32;
+ }
+
+ int element = 8 - (index >> 1);
+
+ ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
+
+ int eaoffset = (ea & 0xf) + (element * 2);
+ ea &= ~0xf;
+
+ for (i=vs; i < ve; i++)
+ {
+ WRITE16(rsp, ea + (eaoffset & 0xf), VREG_S(i, element & 0x7));
+ eaoffset += 2;
+ element++;
+ }
+}
+
+static int generate_swc2(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+// int loopdest;
+ UINT32 op = desc->opptr.l[0];
+ //int dest = (op >> 16) & 0x1f;
+ //int base = (op >> 21) & 0x1f;
+ //int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ //int skip;
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ switch ((op >> 11) & 0x1f)
+ {
+ case 0x00: /* SBV */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_sbv, rsp);
+ return TRUE;
+ case 0x01: /* SSV */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_ssv, rsp);
+ return TRUE;
+ case 0x02: /* SLV */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_slv, rsp);
+ return TRUE;
+ case 0x03: /* SDV */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_sdv, rsp);
+ return TRUE;
+ case 0x04: /* SQV */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_sqv, rsp);
+ return TRUE;
+ case 0x05: /* SRV */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_srv, rsp);
+ return TRUE;
+ case 0x06: /* SPV */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_spv, rsp);
+ return TRUE;
+ case 0x07: /* SUV */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_suv, rsp);
+ return TRUE;
+ case 0x08: /* SHV */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_shv, rsp);
+ return TRUE;
+ case 0x09: /* SFV */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_sfv, rsp);
+ return TRUE;
+ case 0x0a: /* SWV */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_swv, rsp);
+ return TRUE;
+ case 0x0b: /* STV */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_stv, rsp);
+ return TRUE;
+
+ default:
+ unimplemented_opcode(rsp, op);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+INLINE UINT16 SATURATE_ACCUM(rsp_state *rsp, int accum, int slice, UINT16 negative, UINT16 positive)
+{
+ if ((INT16)ACCUM_H(accum) < 0)
+ {
+ if ((UINT16)(ACCUM_H(accum)) != 0xffff)
+ {
+ return negative;
+ }
+ else
+ {
+ if ((INT16)ACCUM_M(accum) >= 0)
+ {
+ return negative;
+ }
+ else
+ {
+ if (slice == 0)
+ {
+ return ACCUM_L(accum);
+ }
+ else if (slice == 1)
+ {
+ return ACCUM_M(accum);
+ }
+ }
+ }
+ }
+ else
+ {
+ if ((UINT16)(ACCUM_H(accum)) != 0)
+ {
+ return positive;
+ }
+ else
+ {
+ if ((INT16)ACCUM_M(accum) < 0)
+ {
+ return positive;
+ }
+ else
+ {
+ if (slice == 0)
+ {
+ return ACCUM_L(accum);
+ }
+ else
+ {
+ return ACCUM_M(accum);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+INLINE UINT16 SATURATE_ACCUM1(rsp_state *rsp, int accum, UINT16 negative, UINT16 positive)
+{
+ if ((INT16)ACCUM_H(accum) < 0)
+ {
+ if ((UINT16)(ACCUM_H(accum)) != 0xffff)
+ {
+ return negative;
+ }
+ else
+ {
+ if ((INT16)ACCUM_M(accum) >= 0)
+ {
+ return negative;
+ }
+ else
+ {
+ return ACCUM_M(accum);
+ }
+ }
+ }
+ else
+ {
+ if ((UINT16)(ACCUM_H(accum)) != 0)
+ {
+ return positive;
+ }
+ else
+ {
+ if ((INT16)ACCUM_M(accum) < 0)
+ {
+ return positive;
+ }
+ else
+ {
+ return ACCUM_M(accum);
+ }
+ }
+ }
+
+ return 0;
+}
+
+#define WRITEBACK_RESULT() { \
+ VREG_S(VDREG, 0) = vres[0]; \
+ VREG_S(VDREG, 1) = vres[1]; \
+ VREG_S(VDREG, 2) = vres[2]; \
+ VREG_S(VDREG, 3) = vres[3]; \
+ VREG_S(VDREG, 4) = vres[4]; \
+ VREG_S(VDREG, 5) = vres[5]; \
+ VREG_S(VDREG, 6) = vres[6]; \
+ VREG_S(VDREG, 7) = vres[7]; \
+}
+
+INLINE void cfunc_rsp_vmulf(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8] = { 0 };
+ //int i;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000000 |
+ // ------------------------------------------------------
+ //
+ // Multiplies signed integer by signed integer * 2
+
+ int sel;
+ INT32 s1, s2;
+ INT64 r;
+ for (int i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ s2 = (INT32)(INT16)VREG_S(VS2REG, sel);
+ if (s1 == -32768 && s2 == -32768)
+ {
+ // overflow
+ ACCUM_H(i) = 0;
+ ACCUM_M(i) = -32768;
+ ACCUM_L(i) = -32768;
+ vres[i] = 0x7fff;
+ }
+ else
+ {
+ r = s1 * s2 * 2;
+ r += 0x8000; // rounding ?
+ ACCUM_H(i) = (r < 0) ? 0xffff : 0; // sign-extend to 48-bit
+ ACCUM_M(i) = (INT16)(r >> 16);
+ ACCUM_L(i) = (UINT16)(r);
+ vres[i] = ACCUM_M(i);
+ }
+ }
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vmulu(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8];
+ int i;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000001 |
+ // ------------------------------------------------------
+ //
+
+ int sel;
+ INT32 s1, s2;
+ INT64 r;
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ s2 = (INT32)(INT16)VREG_S(VS2REG, sel);
+ r = s1 * s2 * 2;
+ r += 0x8000; // rounding ?
+
+ ACCUM_H(i) = (UINT16)(r >> 32);
+ ACCUM_M(i) = (UINT16)(r >> 16);
+ ACCUM_L(i) = (UINT16)(r);
+
+ if (r < 0)
+ {
+ vres[i] = 0;
+ }
+ else if (((INT16)(ACCUM_H(i)) ^ (INT16)(ACCUM_M(i))) < 0)
+ {
+ vres[i] = -1;
+ }
+ else
+ {
+ vres[i] = ACCUM_M(i);
+ }
+ }
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vmudl(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8] = { 0 };
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001101 |
+ // ------------------------------------------------------
+ //
+ // Multiplies signed integer by unsigned fraction
+ // The result is added into accumulator
+ // The middle slice of accumulator is stored into destination element
+
+ int sel;
+ UINT32 s1, s2;
+ UINT32 r;
+ for (int i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (UINT32)(UINT16)VREG_S(VS1REG, i);
+ s2 = (UINT32)(UINT16)VREG_S(VS2REG, sel);
+ r = s1 * s2;
+
+ ACCUM_H(i) = 0;
+ ACCUM_M(i) = 0;
+ ACCUM_L(i) = (UINT16)(r >> 16);
+
+ vres[i] = ACCUM_L(i);
+ }
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vmudm(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8] = { 0 };
+ //int i;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000101 |
+ // ------------------------------------------------------
+ //
+ // Multiplies signed integer by unsigned fraction
+ // The result is stored into accumulator
+ // The middle slice of accumulator is stored into destination element
+
+ int sel;
+ INT32 s1, s2;
+ INT32 r;
+ for (int i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ s2 = (UINT16)VREG_S(VS2REG, sel); // not sign-extended
+ r = s1 * s2;
+
+ ACCUM_H(i) = (r < 0) ? 0xffff : 0; // sign-extend to 48-bit
+ ACCUM_M(i) = (INT16)(r >> 16);
+ ACCUM_L(i) = (UINT16)(r);
+
+ vres[i] = ACCUM_M(i);
+ }
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vmudn(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8] = { 0 };
+
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000110 |
+ // ------------------------------------------------------
+ //
+ // Multiplies unsigned fraction by signed integer
+ // The result is stored into accumulator
+ // The low slice of accumulator is stored into destination element
+
+ int sel;
+ INT32 s1, s2;
+ INT32 r;
+ for (int i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (UINT16)VREG_S(VS1REG, i); // not sign-extended
+ s2 = (INT32)(INT16)VREG_S(VS2REG, sel);
+ r = s1 * s2;
+
+ ACCUM_H(i) = (r < 0) ? 0xffff : 0; // sign-extend to 48-bit
+ ACCUM_M(i) = (INT16)(r >> 16);
+ ACCUM_L(i) = (UINT16)(r);
+
+ vres[i] = ACCUM_L(i);
+ }
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vmudh(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8];
+ int i;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000111 |
+ // ------------------------------------------------------
+ //
+ // Multiplies signed integer by signed integer
+ // The result is stored into highest 32 bits of accumulator, the low slice is zero
+ // The highest 32 bits of accumulator is saturated into destination element
+
+ int sel;
+ INT32 s1, s2;
+ INT32 r;
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ s2 = (INT32)(INT16)VREG_S(VS2REG, sel);
+ r = s1 * s2;
+
+ ACCUM_H(i) = (INT16)(r >> 16);
+ ACCUM_M(i) = (UINT16)(r);
+ ACCUM_L(i) = 0;
+
+ if (r < -32768) r = -32768;
+ if (r > 32767) r = 32767;
+ vres[i] = (INT16)(r);
+ }
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vmacf(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8];
+
+ int sel;
+ INT32 s1, s2;
+ INT32 r;
+ UINT16 res;
+ for (int i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ s2 = (INT32)(INT16)VREG_S(VS2REG, sel);
+ r = s1 * s2;
+
+ ACCUM(i) += (INT64)(r) << 17;
+ res = SATURATE_ACCUM(rsp, i, 1, 0x8000, 0x7fff);
+
+ vres[i] = res;
+ }
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vmacu(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8];
+ int i;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001001 |
+ // ------------------------------------------------------
+ //
+
+ UINT16 res;
+ int sel;
+ INT32 s1, s2, r1;
+ UINT32 r2, r3;
+ for (i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ s2 = (INT32)(INT16)VREG_S(VS2REG, sel);
+ r1 = s1 * s2;
+ r2 = (UINT16)ACCUM_L(i) + ((UINT16)(r1) * 2);
+ r3 = (UINT16)ACCUM_M(i) + (UINT16)((r1 >> 16) * 2) + (UINT16)(r2 >> 16);
+
+ ACCUM_L(i) = (UINT16)(r2);
+ ACCUM_M(i) = (UINT16)(r3);
+ ACCUM_H(i) += (UINT16)(r3 >> 16) + (UINT16)(r1 >> 31);
+
+ //res = SATURATE_ACCUM(i, 1, 0x0000, 0xffff);
+ if ((INT16)ACCUM_H(i) < 0)
+ {
+ res = 0;
+ }
+ else
+ {
+ if (ACCUM_H(i) != 0)
+ {
+ res = 0xffff;
+ }
+ else
+ {
+ if ((INT16)ACCUM_M(i) < 0)
+ {
+ res = 0xffff;
+ }
+ else
+ {
+ res = ACCUM_M(i);
+ }
+ }
+ }
+
+ vres[i] = res;
+ }
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vmadl(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8];
+ int i;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001100 |
+ // ------------------------------------------------------
+ //
+ // Multiplies unsigned fraction by unsigned fraction
+ // Adds the higher 16 bits of the 32-bit result to accumulator
+ // The low slice of accumulator is stored into destination element
+
+ UINT16 res;
+ int sel;
+ UINT32 s1, s2, r1;
+ UINT32 r2, r3;
+ for (i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (UINT32)(UINT16)VREG_S(VS1REG, i);
+ s2 = (UINT32)(UINT16)VREG_S(VS2REG, sel);
+ r1 = s1 * s2;
+ r2 = (UINT16)ACCUM_L(i) + (r1 >> 16);
+ r3 = (UINT16)ACCUM_M(i) + (r2 >> 16);
+
+ ACCUM_L(i) = (UINT16)(r2);
+ ACCUM_M(i) = (UINT16)(r3);
+ ACCUM_H(i) += (INT16)(r3 >> 16);
+
+ res = SATURATE_ACCUM(rsp, i, 0, 0x0000, 0xffff);
+
+ vres[i] = res;
+ }
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vmadm(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8];
+
+ UINT16 res;
+ int sel;
+ UINT32 s1, s2, r1;
+ UINT32 r2, r3;
+ for (int i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ s2 = (UINT16)VREG_S(VS2REG, sel); // not sign-extended
+ r1 = s1 * s2;
+ r2 = (UINT16)ACCUM_L(i) + (UINT16)(r1);
+ r3 = (UINT16)ACCUM_M(i) + (r1 >> 16) + (r2 >> 16);
+
+ ACCUM_L(i) = (UINT16)(r2);
+ ACCUM_M(i) = (UINT16)(r3);
+ ACCUM_H(i) += (UINT16)(r3 >> 16);
+ if ((INT32)(r1) < 0)
+ ACCUM_H(i) -= 1;
+
+ res = SATURATE_ACCUM(rsp, i, 1, 0x8000, 0x7fff);
+
+ vres[i] = res;
+ }
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vmadn(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8];
+
+ INT32 s1, s2;
+ UINT16 res;
+ int sel;
+ for (int i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (UINT16)VREG_S(VS1REG, i); // not sign-extended
+ s2 = (INT32)(INT16)VREG_S(VS2REG, sel);
+
+ ACCUM(i) += (INT64)(s1*s2)<<16;
+
+ res = SATURATE_ACCUM(rsp, i, 0, 0x0000, 0xffff);
+ vres[i] = res;
+ }
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vmadh(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8];
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001111 |
+ // ------------------------------------------------------
+ //
+ // Multiplies signed integer by signed integer
+ // The result is added into highest 32 bits of accumulator, the low slice is zero
+ // The highest 32 bits of accumulator is saturated into destination element
+
+ UINT16 res;
+ int sel;
+ INT32 s1, s2;
+ for (int i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ s2 = (INT32)(INT16)VREG_S(VS2REG, sel);
+
+ rsp->accum[i].l[1] += s1*s2;
+
+ res = SATURATE_ACCUM1(rsp, i, 0x8000, 0x7fff);
+
+ vres[i] = res;
+ }
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vadd(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8] = { 0 };
+ //int i;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010000 |
+ // ------------------------------------------------------
+ //
+ // Adds two vector registers and carry flag, the result is saturated to 32767
+
+ int sel;
+ INT32 s1, s2, r;
+ for (int i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ s2 = (INT32)(INT16)VREG_S(VS2REG, sel);
+ r = s1 + s2 + CARRY_FLAG(i);
+
+ ACCUM_L(i) = (INT16)(r);
+
+ if (r > 32767) r = 32767;
+ if (r < -32768) r = -32768;
+ vres[i] = (INT16)(r);
+ }
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vsub(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8];
+ int i;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010001 |
+ // ------------------------------------------------------
+ //
+ // Subtracts two vector registers and carry flag, the result is saturated to -32768
+
+ // TODO: check VS2REG == VDREG
+
+ int sel;
+ INT32 s1, s2, r;
+ for (i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ s2 = (INT32)(INT16)VREG_S(VS2REG, sel);
+ r = s1 - s2 - CARRY_FLAG(i);
+
+ ACCUM_L(i) = (INT16)(r);
+
+ if (r > 32767) r = 32767;
+ if (r < -32768) r = -32768;
+
+ vres[i] = (INT16)(r);
+ }
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vabs(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8];
+ int i;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010011 |
+ // ------------------------------------------------------
+ //
+ // Changes the sign of source register 2 if source register 1 is negative and stores
+ // the result to destination register
+
+ int sel;
+ INT16 s1, s2;
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (INT16)VREG_S(VS1REG, i);
+ s2 = (INT16)VREG_S(VS2REG, sel);
+
+ if (s1 < 0)
+ {
+ if (s2 == -32768)
+ {
+ vres[i] = 32767;
+ }
+ else
+ {
+ vres[i] = -s2;
+ }
+ }
+ else if (s1 > 0)
+ {
+ vres[i] = s2;
+ }
+ else
+ {
+ vres[i] = 0;
+ }
+
+ ACCUM_L(i) = vres[i];
+ }
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vaddc(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8];
+ int i;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010100 |
+ // ------------------------------------------------------
+ //
+ // Adds two vector registers, the carry out is stored into carry register
+
+ // TODO: check VS2REG = VDREG
+
+ int sel;
+ INT32 s1, s2, r;
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (UINT32)(UINT16)VREG_S(VS1REG, i);
+ s2 = (UINT32)(UINT16)VREG_S(VS2REG, sel);
+ r = s1 + s2;
+
+ vres[i] = (INT16)(r);
+ ACCUM_L(i) = (INT16)(r);
+
+ if (r & 0xffff0000)
+ {
+ SET_CARRY_FLAG(i);
+ }
+ }
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vsubc(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8];
+ int i;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010101 |
+ // ------------------------------------------------------
+ //
+ // Subtracts two vector registers, the carry out is stored into carry register
+
+ // TODO: check VS2REG = VDREG
+
+ int sel;
+ INT32 s1, s2, r;
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = (UINT32)(UINT16)VREG_S(VS1REG, i);
+ s2 = (UINT32)(UINT16)VREG_S(VS2REG, sel);
+ r = s1 - s2;
+
+ vres[i] = (INT16)(r);
+ ACCUM_L(i) = (UINT16)(r);
+
+ if ((UINT16)(r) != 0)
+ {
+ SET_ZERO_FLAG(i);
+ }
+ if (r & 0xffff0000)
+ {
+ SET_CARRY_FLAG(i);
+ }
+ }
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vsaw(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 011101 |
+ // ------------------------------------------------------
+ //
+ // Stores high, middle or low slice of accumulator to destination vector
+
+ switch (EL)
+ {
+ case 0x08: // VSAWH
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ VREG_S(VDREG, i) = ACCUM_H(i);
+ }
+ break;
+ }
+ case 0x09: // VSAWM
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ VREG_S(VDREG, i) = ACCUM_M(i);
+ }
+ break;
+ }
+ case 0x0a: // VSAWL
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ VREG_S(VDREG, i) = ACCUM_L(i);
+ }
+ break;
+ }
+ default: fatalerror("RSP: VSAW: el = %d\n", EL);
+ }
+}
+
+INLINE void cfunc_rsp_vlt(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8] = { 0 };
+ //int i;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100000 |
+ // ------------------------------------------------------
+ //
+ // Sets compare flags if elements in VS1 are less than VS2
+ // Moves the element in VS2 to destination vector
+
+ int sel;
+ rsp->flag[1] = 0;
+
+ for (int i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+
+ if (VREG_S(VS1REG, i) < VREG_S(VS2REG, sel))
+ {
+ SET_COMPARE_FLAG(i);
+ }
+ else if (VREG_S(VS1REG, i) == VREG_S(VS2REG, sel))
+ {
+ if (ZERO_FLAG(i) == 1 && CARRY_FLAG(i) != 0)
+ {
+ SET_COMPARE_FLAG(i);
+ }
+ }
+
+ if (COMPARE_FLAG(i))
+ {
+ vres[i] = VREG_S(VS1REG, i);
+ }
+ else
+ {
+ vres[i] = VREG_S(VS2REG, sel);
+ }
+
+ ACCUM_L(i) = vres[i];
+ }
+
+ rsp->flag[0] = 0;
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_veq(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8];
+ int i;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100001 |
+ // ------------------------------------------------------
+ //
+ // Sets compare flags if elements in VS1 are equal with VS2
+ // Moves the element in VS2 to destination vector
+
+ int sel;
+ rsp->flag[1] = 0;
+
+ for (i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+
+ if ((VREG_S(VS1REG, i) == VREG_S(VS2REG, sel)) && ZERO_FLAG(i) == 0)
+ {
+ SET_COMPARE_FLAG(i);
+ vres[i] = VREG_S(VS1REG, i);
+ }
+ else
+ {
+ vres[i] = VREG_S(VS2REG, sel);
+ }
+ ACCUM_L(i) = vres[i];
+ }
+
+ rsp->flag[0] = 0;
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vne(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8];
+ int i;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100010 |
+ // ------------------------------------------------------
+ //
+ // Sets compare flags if elements in VS1 are not equal with VS2
+ // Moves the element in VS2 to destination vector
+
+ int sel;
+ rsp->flag[1] = 0;
+
+ for (i=0; i < 8; i++)//?????????? ????
+ {
+ sel = VEC_EL_2(EL, i);
+
+ if (VREG_S(VS1REG, i) != VREG_S(VS2REG, sel))
+ {
+ SET_COMPARE_FLAG(i);
+ }
+ else
+ {
+ if (ZERO_FLAG(i) == 1)
+ {
+ SET_COMPARE_FLAG(i);
+ }
+ }
+ if (COMPARE_FLAG(i))
+ {
+ vres[i] = VREG_S(VS1REG, i);
+ }
+ else
+ {
+ vres[i] = VREG_S(VS2REG, sel);
+ }
+ ACCUM_L(i) = vres[i];
+ }
+
+ rsp->flag[0] = 0;
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vge(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8] = { 0 };
+ //int i;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100011 |
+ // ------------------------------------------------------
+ //
+ // Sets compare flags if elements in VS1 are greater or equal with VS2
+ // Moves the element in VS2 to destination vector
+
+ int sel;
+ rsp->flag[1] = 0;
+
+ for (int i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+
+ if (VREG_S(VS1REG, i) == VREG_S(VS2REG, sel))
+ {
+ if (ZERO_FLAG(i) == 0 || CARRY_FLAG(i) == 0)
+ {
+ SET_COMPARE_FLAG(i);
+ }
+ }
+ else if (VREG_S(VS1REG, i) > VREG_S(VS2REG, sel))
+ {
+ SET_COMPARE_FLAG(i);
+ }
+
+ if (COMPARE_FLAG(i) != 0)
+ {
+ vres[i] = VREG_S(VS1REG, i);
+ }
+ else
+ {
+ vres[i] = VREG_S(VS2REG, sel);
+ }
+
+ ACCUM_L(i) = vres[i];
+ }
+
+ rsp->flag[0] = 0;
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vcl(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8];
+ int i;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100100 |
+ // ------------------------------------------------------
+ //
+ // Vector clip low
+
+ int sel;
+ INT16 s1, s2;
+ for (i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = VREG_S(VS1REG, i);
+ s2 = VREG_S(VS2REG, sel);
+
+ if (CARRY_FLAG(i) != 0)
+ {
+
+ if (ZERO_FLAG(i) != 0)
+ {
+
+ if (COMPARE_FLAG(i) != 0)
+ {
+ ACCUM_L(i) = -(UINT16)s2;
+ }
+ else
+ {
+ ACCUM_L(i) = s1;
+ }
+ }
+ else//ZERO_FLAG(i)==0
+ {
+
+ if (rsp->flag[2] & (1 << (i)))
+ {
+
+ if (((UINT32)(UINT16)(s1) + (UINT32)(UINT16)(s2)) > 0x10000)
+ {//proper fix for Harvest Moon 64, r4
+
+ ACCUM_L(i) = s1;
+ CLEAR_COMPARE_FLAG(i);
+ }
+ else
+ {
+
+ ACCUM_L(i) = -((UINT16)s2);
+ SET_COMPARE_FLAG(i);
+ }
+ }
+ else
+ {
+ if (((UINT32)(UINT16)(s1) + (UINT32)(UINT16)(s2)) != 0)
+ {
+ ACCUM_L(i) = s1;
+ CLEAR_COMPARE_FLAG(i);
+ }
+ else
+ {
+ ACCUM_L(i) = -((UINT16)s2);
+ SET_COMPARE_FLAG(i);
+ }
+ }
+ }
+ }//
+ else//CARRY_FLAG(i)==0
+ {
+
+ if (ZERO_FLAG(i) != 0)
+ {
+
+ if (rsp->flag[1] & (1 << (8+i)))
+ {
+ ACCUM_L(i) = s2;
+ }
+ else
+ {
+ ACCUM_L(i) = s1;
+ }
+ }
+ else
+ {
+ if (((INT32)(UINT16)s1 - (INT32)(UINT16)s2) >= 0)
+ {
+ ACCUM_L(i) = s2;
+ rsp->flag[1] |= (1 << (8+i));
+ }
+ else
+ {
+ ACCUM_L(i) = s1;
+ rsp->flag[1] &= ~(1 << (8+i));
+ }
+ }
+ }
+
+ vres[i] = ACCUM_L(i);
+ }
+ rsp->flag[0] = 0;
+ rsp->flag[2] = 0;
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vch(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8];
+ int i;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100101 |
+ // ------------------------------------------------------
+ //
+ // Vector clip high
+
+ int sel;
+ INT16 s1, s2;
+ rsp->flag[0] = 0;
+ rsp->flag[1] = 0;
+ rsp->flag[2] = 0;
+ UINT32 vce = 0;
+
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = VREG_S(VS1REG, i);
+ s2 = VREG_S(VS2REG, sel);
+
+ if ((s1 ^ s2) < 0)
+ {
+ vce = (s1 + s2 == -1);
+ SET_CARRY_FLAG(i);
+ if (s2 < 0)
+ {
+ rsp->flag[1] |= (1 << (8+i));
+ }
+
+ if (s1 + s2 <= 0)
+ {
+ SET_COMPARE_FLAG(i);
+ vres[i] = -((UINT16)s2);
+ }
+ else
+ {
+ vres[i] = s1;
+ }
+
+ if (s1 + s2 != 0)
+ {
+ if (s1 != ~s2)
+ {
+ SET_ZERO_FLAG(i);
+ }
+ }
+ }//sign
+ else
+ {
+ vce = 0;
+ if (s2 < 0)
+ {
+ SET_COMPARE_FLAG(i);
+ }
+ if (s1 - s2 >= 0)
+ {
+ rsp->flag[1] |= (1 << (8+i));
+ vres[i] = s2;
+ }
+ else
+ {
+ vres[i] = s1;
+ }
+
+ if ((s1 - s2) != 0)
+ {
+ if (s1 != ~s2)
+ {
+ SET_ZERO_FLAG(i);
+ }
+ }
+ }
+ rsp->flag[2] |= (vce << (i));
+ ACCUM_L(i) = vres[i];
+ }
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vcr(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8];
+ int i;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100110 |
+ // ------------------------------------------------------
+ //
+ // Vector clip reverse
+
+ int sel;
+ INT16 s1, s2;
+ rsp->flag[0] = 0;
+ rsp->flag[1] = 0;
+ rsp->flag[2] = 0;
+
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ s1 = VREG_S(VS1REG, i);
+ s2 = VREG_S(VS2REG, sel);
+
+ if ((INT16)(s1 ^ s2) < 0)
+ {
+ if (s2 < 0)
+ {
+ rsp->flag[1] |= (1 << (8+i));
+ }
+ if ((s1 + s2) <= 0)
+ {
+ ACCUM_L(i) = ~((UINT16)s2);
+ SET_COMPARE_FLAG(i);
+ }
+ else
+ {
+ ACCUM_L(i) = s1;
+ }
+ }
+ else
+ {
+ if (s2 < 0)
+ {
+ SET_COMPARE_FLAG(i);
+ }
+ if ((s1 - s2) >= 0)
+ {
+ ACCUM_L(i) = s2;
+ rsp->flag[1] |= (1 << (8+i));
+ }
+ else
+ {
+ ACCUM_L(i) = s1;
+ }
+ }
+
+ vres[i] = ACCUM_L(i);
+ }
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vmrg(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8] = { 0 };
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100111 |
+ // ------------------------------------------------------
+ //
+ // Merges two vectors according to compare flags
+
+ int sel;
+ for (int i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ if (COMPARE_FLAG(i) != 0)
+ {
+ vres[i] = VREG_S(VS1REG, i);
+ }
+ else
+ {
+ vres[i] = VREG_S(VS2REG, sel);//??? ???????????
+ }
+
+ ACCUM_L(i) = vres[i];
+ }
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vand(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8] = { 0 };
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101000 |
+ // ------------------------------------------------------
+ //
+ // Bitwise AND of two vector registers
+
+ int sel;
+ for (int i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ vres[i] = VREG_S(VS1REG, i) & VREG_S(VS2REG, sel);
+ ACCUM_L(i) = vres[i];
+ }
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vnand(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8] = { 0 };
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101001 |
+ // ------------------------------------------------------
+ //
+ // Bitwise NOT AND of two vector registers
+
+ int sel;
+ for (int i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ vres[i] = ~((VREG_S(VS1REG, i) & VREG_S(VS2REG, sel)));
+ ACCUM_L(i) = vres[i];
+ }
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vor(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8] = { 0 };;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101010 |
+ // ------------------------------------------------------
+ //
+ // Bitwise OR of two vector registers
+
+ int sel;
+ for (int i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ vres[i] = VREG_S(VS1REG, i) | VREG_S(VS2REG, sel);
+ ACCUM_L(i) = vres[i];
+ }
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vnor(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8] = { 0 };;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101011 |
+ // ------------------------------------------------------
+ //
+ // Bitwise NOT OR of two vector registers
+
+ int sel;
+ for (int i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ vres[i] = ~((VREG_S(VS1REG, i) | VREG_S(VS2REG, sel)));
+ ACCUM_L(i) = vres[i];
+ }
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vxor(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8] = { 0 };;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101100 |
+ // ------------------------------------------------------
+ //
+ // Bitwise XOR of two vector registers
+
+ int sel;
+ for (int i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ vres[i] = VREG_S(VS1REG, i) ^ VREG_S(VS2REG, sel);
+ ACCUM_L(i) = vres[i];
+ }
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vnxor(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ INT16 vres[8] = { 0 };;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101101 |
+ // ------------------------------------------------------
+ //
+ // Bitwise NOT XOR of two vector registers
+
+ int sel;
+ for (int i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ vres[i] = ~((VREG_S(VS1REG, i) ^ VREG_S(VS2REG, sel)));
+ ACCUM_L(i) = vres[i];
+ }
+ WRITEBACK_RESULT();
+}
+
+INLINE void cfunc_rsp_vrcp(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ int i;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110000 |
+ // ------------------------------------------------------
+ //
+ // Calculates reciprocal
+
+ int del = VS1REG & 7;
+ int sel = EL & 7;
+ INT32 shifter = 0;
+
+ INT32 rec = (INT16)(VREG_S(VS2REG, sel));
+ INT32 datainput = (rec < 0) ? (-rec) : rec;
+ if (datainput)
+ {
+ for (i = 0; i < 32; i++)
+ {
+ if (datainput & (1 << ((~i) & 0x1f)))//?.?.??? 31 - i
+ {
+ shifter = i;
+ break;
+ }
+ }
+ }
+ else
+ {
+ shifter = 0x10;
+ }
+
+ INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22;
+ INT32 fetchval = rsp_divtable[address];
+ INT32 temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f);
+ if (rec < 0)
+ {
+ temp = ~temp;
+ }
+ if (!rec)
+ {
+ temp = 0x7fffffff;
+ }
+ else if (rec == 0xffff8000)
+ {
+ temp = 0xffff0000;
+ }
+ rec = temp;
+
+ rsp->reciprocal_res = rec;
+ rsp->dp_allowed = 0;
+
+ VREG_S(VDREG, del) = (UINT16)(rec & 0xffff);
+
+ for (i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ ACCUM_L(i) = VREG_S(VS2REG, sel);
+ }
+}
+
+INLINE void cfunc_rsp_vrcpl(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ int i;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110001 |
+ // ------------------------------------------------------
+ //
+ // Calculates reciprocal low part
+
+ int del = VS1REG & 7;
+ int sel = EL & 7;
+ INT32 shifter = 0;
+
+ INT32 rec = ((UINT16)(VREG_S(VS2REG, sel)) | ((UINT32)(rsp->reciprocal_high) & 0xffff0000));
+
+ INT32 datainput = rec;
+
+ if (rec < 0)
+ {
+ if (rsp->dp_allowed)
+ {
+ if (rec < -32768)
+ {
+ datainput = ~datainput;
+ }
+ else
+ {
+ datainput = -datainput;
+ }
+ }
+ else
+ {
+ datainput = -datainput;
+ }
+ }
+
+
+ if (datainput)
+ {
+ for (i = 0; i < 32; i++)
+ {
+ if (datainput & (1 << ((~i) & 0x1f)))//?.?.??? 31 - i
+ {
+ shifter = i;
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (rsp->dp_allowed)
+ {
+ shifter = 0;
+ }
+ else
+ {
+ shifter = 0x10;
+ }
+ }
+
+ INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22;
+ INT32 fetchval = rsp_divtable[address];
+ INT32 temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f);
+ if (rec < 0)
+ {
+ temp = ~temp;
+ }
+ if (!rec)
+ {
+ temp = 0x7fffffff;
+ }
+ else if (rec == 0xffff8000)
+ {
+ temp = 0xffff0000;
+ }
+ rec = temp;
+
+ rsp->reciprocal_res = rec;
+ rsp->dp_allowed = 0;
+
+ VREG_S(VDREG, del) = (UINT16)(rec & 0xffff);
+
+ for (i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ ACCUM_L(i) = VREG_S(VS2REG, sel);
+ }
+}
+
+INLINE void cfunc_rsp_vrcph(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110010 |
+ // ------------------------------------------------------
+ //
+ // Calculates reciprocal high part
+
+ int del = VS1REG & 7;
+ int sel = EL & 7;
+
+ rsp->reciprocal_high = (VREG_S(VS2REG, sel)) << 16;
+ rsp->dp_allowed = 1;
+
+ for (int i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ ACCUM_L(i) = VREG_S(VS2REG, sel);
+ }
+
+ VREG_S(VDREG, del) = (INT16)(rsp->reciprocal_res >> 16);
+}
+
+INLINE void cfunc_rsp_vmov(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110011 |
+ // ------------------------------------------------------
+ //
+ // Moves element from vector to destination vector
+
+ int del = VS1REG & 7;
+ int sel = EL & 7;
+
+ VREG_S(VDREG, del) = VREG_S(VS2REG, sel);
+ for (int i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ ACCUM_L(i) = VREG_S(VS2REG, sel);
+ }
+}
+
+INLINE void cfunc_rsp_vrsql(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ int i;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110101 |
+ // ------------------------------------------------------
+ //
+ // Calculates reciprocal square-root low part
+
+ int del = VS1REG & 7;
+ int sel = EL & 7;
+ INT32 shifter = 0;
+
+ INT32 rec = ((UINT16)(VREG_S(VS2REG, sel)) | ((UINT32)(rsp->reciprocal_high) & 0xffff0000));
+
+ INT32 datainput = rec;
+
+ if (rec < 0)
+ {
+ if (rsp->dp_allowed)
+ {
+ if (rec < -32768)//VDIV.C,208
+ {
+ datainput = ~datainput;
+ }
+ else
+ {
+ datainput = -datainput;
+ }
+ }
+ else
+ {
+ datainput = -datainput;
+ }
+ }
+
+ if (datainput)
+ {
+ for (i = 0; i < 32; i++)
+ {
+ if (datainput & (1 << ((~i) & 0x1f)))
+ {
+ shifter = i;
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (rsp->dp_allowed)
+ {
+ shifter = 0;
+ }
+ else
+ {
+ shifter = 0x10;
+ }
+ }
+
+ INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22;
+ address = ((address | 0x200) & 0x3fe) | (shifter & 1);
+
+ INT32 fetchval = rsp_divtable[address];
+ INT32 temp = (0x40000000 | (fetchval << 14)) >> (((~shifter) & 0x1f) >> 1);
+ if (rec < 0)
+ {
+ temp = ~temp;
+ }
+ if (!rec)
+ {
+ temp = 0x7fffffff;
+ }
+ else if (rec == 0xffff8000)
+ {
+ temp = 0xffff0000;
+ }
+ rec = temp;
+
+ rsp->reciprocal_res = rec;
+ rsp->dp_allowed = 0;
+
+ VREG_S(VDREG, del) = (UINT16)(rec & 0xffff);
+
+ for (i = 0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ ACCUM_L(i) = VREG_S(VS2REG, sel);
+ }
+}
+
+INLINE void cfunc_rsp_vrsqh(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ int op = rsp->impstate->arg0;
+ int i;
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110110 |
+ // ------------------------------------------------------
+ //
+ // Calculates reciprocal square-root high part
+
+ int del = VS1REG & 7;
+ int sel = EL & 7;
+
+ rsp->reciprocal_high = (VREG_S(VS2REG, sel)) << 16;
+ rsp->dp_allowed = 1;
+
+ for (i=0; i < 8; i++)
+ {
+ sel = VEC_EL_2(EL, i);
+ ACCUM_L(i) = VREG_S(VS2REG, sel);
+ }
+
+ VREG_S(VDREG, del) = (INT16)(rsp->reciprocal_res >> 16); // store high part
+}
+
+static void cfunc_sp_set_status_cb(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ (rsp->config->sp_set_status)(rsp->device, rsp->impstate->arg0);
+}
+
+static CPU_EXECUTE( rsp )
+{
+ rsp_state *rsp = get_safe_token(device);
+ drcuml_state *drcuml = rsp->impstate->drcuml;
+ int execute_result;
+
+ /* reset the cache if dirty */
+ if (rsp->impstate->cache_dirty)
+ code_flush_cache(rsp);
+ rsp->impstate->cache_dirty = FALSE;
+
+ /* execute */
+ do
+ {
+ if( rsp->sr & ( RSP_STATUS_HALT | RSP_STATUS_BROKE ) )
+ {
+ rsp->icount = MIN(rsp->icount, 0);
+ break;
+ }
+
+ /* run as much as we can */
+ execute_result = drcuml->execute(*rsp->impstate->entry);
+
+ /* if we need to recompile, do it */
+ if (execute_result == EXECUTE_MISSING_CODE)
+ {
+ code_compile_block(rsp, rsp->pc);
+ }
+ else if (execute_result == EXECUTE_UNMAPPED_CODE)
+ {
+ fatalerror("Attempted to execute unmapped code at PC=%08X\n", rsp->pc);
+ }
+ else if (execute_result == EXECUTE_RESET_CACHE)
+ {
+ code_flush_cache(rsp);
+ }
+ } while (execute_result != EXECUTE_OUT_OF_CYCLES);
+}
+
+/***************************************************************************
+ CACHE MANAGEMENT
+***************************************************************************/
+
+/*-------------------------------------------------
+ rspdrc_flush_drc_cache - outward-facing
+ accessor to code_flush_cache
+-------------------------------------------------*/
+
+void rspdrc_flush_drc_cache(device_t *device)
+{
+ rsp_state *rsp = get_safe_token(device);
+ rsp->impstate->cache_dirty = TRUE;
+}
+
+/*-------------------------------------------------
+ code_flush_cache - flush the cache and
+ regenerate static code
+-------------------------------------------------*/
+
+static void code_flush_cache(rsp_state *rsp)
+{
+ /* empty the transient cache contents */
+ rsp->impstate->drcuml->reset();
+
+ try
+ {
+ /* generate the entry point and out-of-cycles handlers */
+ static_generate_entry_point(rsp);
+ static_generate_nocode_handler(rsp);
+ static_generate_out_of_cycles(rsp);
+
+ /* add subroutines for memory accesses */
+ static_generate_memory_accessor(rsp, 1, FALSE, "read8", rsp->impstate->read8);
+ static_generate_memory_accessor(rsp, 1, TRUE, "write8", rsp->impstate->write8);
+ static_generate_memory_accessor(rsp, 2, FALSE, "read16", rsp->impstate->read16);
+ static_generate_memory_accessor(rsp, 2, TRUE, "write16", rsp->impstate->write16);
+ static_generate_memory_accessor(rsp, 4, FALSE, "read32", rsp->impstate->read32);
+ static_generate_memory_accessor(rsp, 4, TRUE, "write32", rsp->impstate->write32);
+ }
+ catch (drcuml_block::abort_compilation &)
+ {
+ fatalerror("Unable to generate static RSP code");
+ }
+}
+
+
+/*-------------------------------------------------
+ code_compile_block - compile a block of the
+ given mode at the specified pc
+-------------------------------------------------*/
+
+static void code_compile_block(rsp_state *rsp, offs_t pc)
+{
+ drcuml_state *drcuml = rsp->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 = rsp->impstate->drcfe->describe_code(pc);
+
+ bool succeeded = false;
+ while (!succeeded)
+ {
+ try
+ {
+ /* start the block */
+ block = drcuml->begin_block(8192);
+
+ /* 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(0, seqhead->pc))
+ UML_HASH(block, 0, 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, 0, 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
+ UML_HASHJMP(block, 0, seqhead->pc, *rsp->impstate->nocode);
+ // hashjmp <0>,seqhead->pc,nocode
+ continue;
+ }
+
+ /* validate this code block if we're not pointing into ROM */
+ if (rsp->program->get_write_ptr(seqhead->physpc) != NULL)
+ generate_checksum_block(rsp, 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
+
+ /* iterate over instructions in the sequence and compile them */
+ for (curdesc = seqhead; curdesc != seqlast->next(); curdesc = curdesc->next())
+ generate_sequence_instruction(rsp, 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(rsp, block, &compiler, nextpc, TRUE); // <subtract cycles>
+
+ /* if the last instruction can change modes, use a variable mode; otherwise, assume the same mode */
+ if (seqlast->next() == NULL || seqlast->next()->pc != nextpc)
+ UML_HASHJMP(block, 0, nextpc, *rsp->impstate->nocode); // hashjmp <mode>,nextpc,nocode
+ }
+
+ /* end the sequence */
+ block->end();
+ g_profiler.stop();
+ succeeded = true;
+ }
+ catch (drcuml_block::abort_compilation &)
+ {
+ code_flush_cache(rsp);
+ }
+ }
+}
+
+/***************************************************************************
+ C FUNCTION CALLBACKS
+***************************************************************************/
+
+/*-------------------------------------------------
+ cfunc_unimplemented - handler for
+ unimplemented opcdes
+-------------------------------------------------*/
+
+static void cfunc_unimplemented(void *param)
+{
+ rsp_state *rsp = (rsp_state *)param;
+ UINT32 opcode = rsp->impstate->arg0;
+ fatalerror("PC=%08X: Unimplemented op %08X (%02X,%02X)", rsp->pc, opcode, opcode >> 26, opcode & 0x3f);
+}
+
+
+/*-------------------------------------------------
+ cfunc_fatalerror - a generic fatalerror call
+-------------------------------------------------*/
+
+#ifdef UNUSED_CODE
+static void cfunc_fatalerror(void *param)
+{
+ fatalerror("fatalerror");
+}
+#endif
+
+
+/***************************************************************************
+ STATIC CODEGEN
+***************************************************************************/
+
+/*-------------------------------------------------
+ ferate_entry_point - generate a
+ static entry point
+-------------------------------------------------*/
+
+static void static_generate_entry_point(rsp_state *rsp)
+{
+ drcuml_state *drcuml = rsp->impstate->drcuml;
+ drcuml_block *block;
+
+ /* begin generating */
+ block = drcuml->begin_block(20);
+
+ /* forward references */
+ alloc_handle(drcuml, &rsp->impstate->nocode, "nocode");
+
+ alloc_handle(drcuml, &rsp->impstate->entry, "entry");
+ UML_HANDLE(block, *rsp->impstate->entry); // handle entry
+
+ /* load fast integer registers */
+ load_fast_iregs(rsp, block);
+
+ /* generate a hash jump via the current mode and PC */
+ UML_HASHJMP(block, 0, mem(&rsp->pc), *rsp->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(rsp_state *rsp)
+{
+ drcuml_state *drcuml = rsp->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, &rsp->impstate->nocode, "nocode");
+ UML_HANDLE(block, *rsp->impstate->nocode); // handle nocode
+ UML_GETEXP(block, I0); // getexp i0
+ UML_MOV(block, mem(&rsp->pc), I0); // mov [pc],i0
+ save_fast_iregs(rsp, 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(rsp_state *rsp)
+{
+ drcuml_state *drcuml = rsp->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, &rsp->impstate->out_of_cycles, "out_of_cycles");
+ UML_HANDLE(block, *rsp->impstate->out_of_cycles); // handle out_of_cycles
+ UML_GETEXP(block, I0); // getexp i0
+ UML_MOV(block, mem(&rsp->pc), I0); // mov <pc>,i0
+ save_fast_iregs(rsp, block);
+ UML_EXIT(block, EXECUTE_OUT_OF_CYCLES); // exit EXECUTE_OUT_OF_CYCLES
+
+ block->end();
+}
+
+/*------------------------------------------------------------------
+ static_generate_memory_accessor
+------------------------------------------------------------------*/
+
+static void static_generate_memory_accessor(rsp_state *rsp, int size, int iswrite, const char *name, code_handle *&handleptr)
+{
+ /* on entry, address is in I0; data for writes is in I1 */
+ /* on exit, read result is in I0 */
+ /* routine trashes I0-I1 */
+ drcuml_state *drcuml = rsp->impstate->drcuml;
+ drcuml_block *block;
+
+ /* begin generating */
+ block = drcuml->begin_block(1024);
+
+ /* add a global entry for this */
+ alloc_handle(drcuml, &handleptr, name);
+ UML_HANDLE(block, *handleptr); // handle *handleptr
+
+ // write:
+ if (iswrite)
+ {
+ if (size == 1)
+ {
+ UML_MOV(block, mem(&rsp->impstate->arg0), I0); // mov [arg0],i0 ; address
+ UML_MOV(block, mem(&rsp->impstate->arg1), I1); // mov [arg1],i1 ; data
+ UML_CALLC(block, cfunc_write8, rsp); // callc cfunc_write8
+ }
+ else if (size == 2)
+ {
+ UML_MOV(block, mem(&rsp->impstate->arg0), I0); // mov [arg0],i0 ; address
+ UML_MOV(block, mem(&rsp->impstate->arg1), I1); // mov [arg1],i1 ; data
+ UML_CALLC(block, cfunc_write16, rsp); // callc cfunc_write16
+ }
+ else if (size == 4)
+ {
+ UML_MOV(block, mem(&rsp->impstate->arg0), I0); // mov [arg0],i0 ; address
+ UML_MOV(block, mem(&rsp->impstate->arg1), I1); // mov [arg1],i1 ; data
+ UML_CALLC(block, cfunc_write32, rsp); // callc cfunc_write32
+ }
+ }
+ else
+ {
+ if (size == 1)
+ {
+ UML_MOV(block, mem(&rsp->impstate->arg0), I0); // mov [arg0],i0 ; address
+ UML_CALLC(block, cfunc_read8, rsp); // callc cfunc_printf_debug
+ UML_MOV(block, I0, mem(&rsp->impstate->arg0)); // mov i0,[arg0],i0 ; result
+ }
+ else if (size == 2)
+ {
+ UML_MOV(block, mem(&rsp->impstate->arg0), I0); // mov [arg0],i0 ; address
+ UML_CALLC(block, cfunc_read16, rsp); // callc cfunc_read16
+ UML_MOV(block, I0, mem(&rsp->impstate->arg0)); // mov i0,[arg0],i0 ; result
+ }
+ else if (size == 4)
+ {
+ UML_MOV(block, mem(&rsp->impstate->arg0), I0); // mov [arg0],i0 ; address
+ UML_CALLC(block, cfunc_read32, rsp); // callc cfunc_read32
+ UML_MOV(block, I0, mem(&rsp->impstate->arg0)); // mov i0,[arg0],i0 ; result
+ }
+ }
+ UML_RET(block);
+
+ block->end();
+}
+
+
+
+/***************************************************************************
+ CODE GENERATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ generate_update_cycles - generate code to
+ subtract cycles from the icount and generate
+ an exception if out
+-------------------------------------------------*/
+static void generate_update_cycles(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, parameter param, int allow_exception)
+{
+ /* account for cycles */
+ if (compiler->cycles > 0)
+ {
+ UML_SUB(block, mem(&rsp->icount), mem(&rsp->icount), MAPVAR_CYCLES); // sub icount,icount,cycles
+ UML_MAPVAR(block, MAPVAR_CYCLES, 0); // mapvar cycles,0
+ UML_EXHc(block, COND_S, *rsp->impstate->out_of_cycles, param);
+ }
+ compiler->cycles = 0;
+}
+
+/*-------------------------------------------------
+ generate_checksum_block - generate code to
+ validate a sequence of opcodes
+-------------------------------------------------*/
+
+static void generate_checksum_block(rsp_state *rsp, 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 | 0x1000); // comment
+ }
+ /* loose verify or single instruction: just compare and fail */
+ if (!(rsp->impstate->drcoptions & RSPDRC_STRICT_VERIFY) || seqhead->next() == NULL)
+ {
+ if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP))
+ {
+ void *base = rsp->direct->read_decrypted_ptr(seqhead->physpc | 0x1000);
+ 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, *rsp->impstate->nocode, epc(seqhead)); // exne nocode,seqhead->pc
+ }
+ }
+
+ /* full verification; sum up everything */
+ else
+ {
+ UINT32 sum = 0;
+ void *base = rsp->direct->read_decrypted_ptr(seqhead->physpc | 0x1000);
+ 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 = rsp->direct->read_decrypted_ptr(curdesc->physpc | 0x1000);
+ 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];
+ }
+ UML_CMP(block, I0, sum); // cmp i0,sum
+ UML_EXHc(block, COND_NE, *rsp->impstate->nocode, epc(seqhead)); // exne nocode,seqhead->pc
+ }
+}
+
+
+/*-------------------------------------------------
+ generate_sequence_instruction - generate code
+ for a single instruction in a sequence
+-------------------------------------------------*/
+
+static void generate_sequence_instruction(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ offs_t expc;
+
+ /* add an entry for the log */
+ if (LOG_UML && !(desc->flags & OPFLAG_VIRTUAL_NOOP))
+ log_add_disasm_comment(rsp, 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;
+
+ /* update the icount map variable */
+ UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler->cycles
+
+ /* if we are debugging, call the debugger */
+ if ((rsp->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ {
+ UML_MOV(block, mem(&rsp->pc), desc->pc); // mov [pc],desc->pc
+ save_fast_iregs(rsp, block);
+ UML_DEBUG(block, desc->pc); // debug desc->pc
+ }
+
+ /* if we hit an unmapped address, fatal error */
+#if 0
+ if (desc->flags & OPFLAG_COMPILER_UNMAPPED)
+ {
+ UML_MOV(block, mem(&rsp->pc), desc->pc); // mov [pc],desc->pc
+ save_fast_iregs(rsp, block);
+ UML_EXIT(block, EXECUTE_UNMAPPED_CODE); // exit EXECUTE_UNMAPPED_CODE
+ }
+#endif
+
+ /* 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(rsp, block, compiler, desc))
+ {
+ UML_MOV(block, mem(&rsp->pc), desc->pc); // mov [pc],desc->pc
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_unimplemented, rsp); // callc cfunc_unimplemented
+ }
+ }
+}
+
+/*------------------------------------------------------------------
+ generate_delay_slot_and_branch
+------------------------------------------------------------------*/
+
+static void generate_delay_slot_and_branch(rsp_state *rsp, 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_AND(block, mem(&rsp->impstate->jmpdest), R32(RSREG), 0x00000fff);
+ UML_OR(block, mem(&rsp->impstate->jmpdest), mem(&rsp->impstate->jmpdest), 0x1000);
+ }
+
+ /* set the link if needed -- before the delay slot */
+ if (linkreg != 0)
+ {
+ UML_MOV(block, R32(linkreg), (INT32)(desc->pc + 8)); // mov <linkreg>,desc->pc + 8
+ }
+
+ /* compile the delay slot using temporary compiler state */
+ assert(desc->delay.first() != NULL);
+ generate_sequence_instruction(rsp, 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(rsp, block, &compiler_temp, desc->targetpc, TRUE); // <subtract cycles>
+ if (desc->flags & OPFLAG_INTRABLOCK_BRANCH)
+ {
+ UML_JMP(block, desc->targetpc | 0x80000000); // jmp desc->targetpc
+ }
+ else
+ {
+ UML_HASHJMP(block, 0, desc->targetpc, *rsp->impstate->nocode);
+ // hashjmp <mode>,desc->targetpc,nocode
+ }
+ }
+ else
+ {
+ generate_update_cycles(rsp, block, &compiler_temp, mem(&rsp->impstate->jmpdest), TRUE);
+ // <subtract cycles>
+ UML_HASHJMP(block, 0, mem(&rsp->impstate->jmpdest), *rsp->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_vector_opcode(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 op = desc->opptr.l[0];
+ // Opcode legend:
+ // E = VS2 element type
+ // S = VS1, Source vector 1
+ // T = VS2, Source vector 2
+ // D = Destination vector
+
+ switch (op & 0x3f)
+ {
+ case 0x00: /* VMULF */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vmulf, rsp);
+ return TRUE;
+
+ case 0x01: /* VMULU */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vmulu, rsp);
+ return TRUE;
+
+ case 0x04: /* VMUDL */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vmudl, rsp);
+ return TRUE;
+
+ case 0x05: /* VMUDM */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vmudm, rsp);
+ return TRUE;
+
+ case 0x06: /* VMUDN */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vmudn, rsp);
+ return TRUE;
+
+ case 0x07: /* VMUDH */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vmudh, rsp);
+ return TRUE;
+
+ case 0x08: /* VMACF */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vmacf, rsp);
+ return TRUE;
+
+ case 0x09: /* VMACU */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vmacu, rsp);
+ return TRUE;
+
+ case 0x0c: /* VMADL */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vmadl, rsp);
+ return TRUE;
+
+ case 0x0d: /* VMADM */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vmadm, rsp);
+ return TRUE;
+
+ case 0x0e: /* VMADN */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vmadn, rsp);
+ return TRUE;
+
+ case 0x0f: /* VMADH */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vmadh, rsp);
+ return TRUE;
+
+ case 0x10: /* VADD */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vadd, rsp);
+ return TRUE;
+
+ case 0x11: /* VSUB */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vsub, rsp);
+ return TRUE;
+
+ case 0x13: /* VABS */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vabs, rsp);
+ return TRUE;
+
+ case 0x14: /* VADDC */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vaddc, rsp);
+ return TRUE;
+
+ case 0x15: /* VSUBC */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vsubc, rsp);
+ return TRUE;
+
+ case 0x1d: /* VSAW */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vsaw, rsp);
+ return TRUE;
+
+ case 0x20: /* VLT */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vlt, rsp);
+ return TRUE;
+
+ case 0x21: /* VEQ */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_veq, rsp);
+ return TRUE;
+
+ case 0x22: /* VNE */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vne, rsp);
+ return TRUE;
+
+ case 0x23: /* VGE */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vge, rsp);
+ return TRUE;
+
+ case 0x24: /* VCL */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vcl, rsp);
+ return TRUE;
+
+ case 0x25: /* VCH */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vch, rsp);
+ return TRUE;
+
+ case 0x26: /* VCR */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vcr, rsp);
+ return TRUE;
+
+ case 0x27: /* VMRG */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vmrg, rsp);
+ return TRUE;
+
+ case 0x28: /* VAND */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vand, rsp);
+ return TRUE;
+
+ case 0x29: /* VNAND */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vnand, rsp);
+ return TRUE;
+
+ case 0x2a: /* VOR */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vor, rsp);
+ return TRUE;
+
+ case 0x2b: /* VNOR */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vnor, rsp);
+ return TRUE;
+
+ case 0x2c: /* VXOR */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vxor, rsp);
+ return TRUE;
+
+ case 0x2d: /* VNXOR */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vnxor, rsp);
+ return TRUE;
+
+ case 0x30: /* VRCP */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vrcp, rsp);
+ return TRUE;
+
+ case 0x31: /* VRCPL */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vrcpl, rsp);
+ return TRUE;
+
+ case 0x32: /* VRCPH */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vrcph, rsp);
+ return TRUE;
+
+ case 0x33: /* VMOV */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vmov, rsp);
+ return TRUE;
+
+ case 0x35: /* VRSQL */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vrsql, rsp);
+ return TRUE;
+
+ case 0x36: /* VRSQH */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vrsqh, rsp);
+ return TRUE;
+
+ default:
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_unimplemented_opcode, rsp);
+ return FALSE;
+ }
+}
+
+static int generate_opcode(rsp_state *rsp, 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(rsp, block, compiler, desc);
+
+ case 0x01: /* REGIMM - MIPS I */
+ return generate_regimm(rsp, block, compiler, desc);
+
+ /* ----- jumps and branches ----- */
+
+ case 0x02: /* J - MIPS I */
+ generate_delay_slot_and_branch(rsp, block, compiler, desc, 0); // <next instruction + hashjmp>
+ return TRUE;
+
+ case 0x03: /* JAL - MIPS I */
+ generate_delay_slot_and_branch(rsp, block, compiler, desc, 31); // <next instruction + hashjmp>
+ return TRUE;
+
+ case 0x04: /* BEQ - MIPS I */
+ UML_CMP(block, R32(RSREG), R32(RTREG)); // cmp <rsreg>,<rtreg>
+ UML_JMPc(block, COND_NE, skip = compiler->labelnum++); // jmp skip,NE
+ generate_delay_slot_and_branch(rsp, block, compiler, desc, 0); // <next instruction + hashjmp>
+ UML_LABEL(block, skip); // skip:
+ return TRUE;
+
+ case 0x05: /* BNE - MIPS I */
+ UML_CMP(block, R32(RSREG), R32(RTREG)); // dcmp <rsreg>,<rtreg>
+ UML_JMPc(block, COND_E, skip = compiler->labelnum++); // jmp skip,E
+ generate_delay_slot_and_branch(rsp, block, compiler, desc, 0); // <next instruction + hashjmp>
+ UML_LABEL(block, skip); // skip:
+ return TRUE;
+
+ case 0x06: /* BLEZ - MIPS I */
+ if (RSREG != 0)
+ {
+ UML_CMP(block, R32(RSREG), 0); // dcmp <rsreg>,0
+ UML_JMPc(block, COND_G, skip = compiler->labelnum++); // jmp skip,G
+ generate_delay_slot_and_branch(rsp, block, compiler, desc, 0); // <next instruction + hashjmp>
+ UML_LABEL(block, skip); // skip:
+ }
+ else
+ generate_delay_slot_and_branch(rsp, block, compiler, desc, 0); // <next instruction + hashjmp>
+ return TRUE;
+
+ case 0x07: /* BGTZ - MIPS I */
+ UML_CMP(block, R32(RSREG), 0); // dcmp <rsreg>,0
+ UML_JMPc(block, COND_LE, skip = compiler->labelnum++); // jmp skip,LE
+ generate_delay_slot_and_branch(rsp, 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_MOV(block, R32(RTREG), SIMMVAL << 16); // dmov <rtreg>,SIMMVAL << 16
+ return TRUE;
+
+ case 0x08: /* ADDI - MIPS I */
+ case 0x09: /* ADDIU - MIPS I */
+ if (RTREG != 0)
+ {
+ UML_ADD(block, R32(RTREG), R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL,V
+ }
+ return TRUE;
+
+ case 0x0a: /* SLTI - MIPS I */
+ if (RTREG != 0)
+ {
+ UML_CMP(block, R32(RSREG), SIMMVAL); // dcmp <rsreg>,SIMMVAL
+ UML_SETc(block, COND_L, R32(RTREG)); // dset <rtreg>,l
+ }
+ return TRUE;
+
+ case 0x0b: /* SLTIU - MIPS I */
+ if (RTREG != 0)
+ {
+ UML_CMP(block, R32(RSREG), SIMMVAL); // dcmp <rsreg>,SIMMVAL
+ UML_SETc(block, COND_B, R32(RTREG)); // dset <rtreg>,b
+ }
+ return TRUE;
+
+
+ case 0x0c: /* ANDI - MIPS I */
+ if (RTREG != 0)
+ UML_AND(block, R32(RTREG), R32(RSREG), UIMMVAL); // dand <rtreg>,<rsreg>,UIMMVAL
+ return TRUE;
+
+ case 0x0d: /* ORI - MIPS I */
+ if (RTREG != 0)
+ UML_OR(block, R32(RTREG), R32(RSREG), UIMMVAL); // dor <rtreg>,<rsreg>,UIMMVAL
+ return TRUE;
+
+ case 0x0e: /* XORI - MIPS I */
+ if (RTREG != 0)
+ UML_XOR(block, R32(RTREG), R32(RSREG), UIMMVAL); // dxor <rtreg>,<rsreg>,UIMMVAL
+ return TRUE;
+
+ /* ----- memory load operations ----- */
+
+ case 0x20: /* LB - MIPS I */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_CALLH(block, *rsp->impstate->read8); // callh read8
+ if (RTREG != 0)
+ UML_SEXT(block, R32(RTREG), I0, SIZE_BYTE); // dsext <rtreg>,i0,byte
+ if (!in_delay_slot)
+ generate_update_cycles(rsp, 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, *rsp->impstate->read16); // callh read16
+ if (RTREG != 0)
+ UML_SEXT(block, R32(RTREG), I0, SIZE_WORD); // dsext <rtreg>,i0,word
+ if (!in_delay_slot)
+ generate_update_cycles(rsp, 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, *rsp->impstate->read32); // callh read32
+ if (RTREG != 0)
+ UML_MOV(block, R32(RTREG), I0);
+ if (!in_delay_slot)
+ generate_update_cycles(rsp, 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, *rsp->impstate->read8); // callh read8
+ if (RTREG != 0)
+ UML_AND(block, R32(RTREG), I0, 0xff); // dand <rtreg>,i0,0xff
+ if (!in_delay_slot)
+ generate_update_cycles(rsp, 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, *rsp->impstate->read16); // callh read16
+ if (RTREG != 0)
+ UML_AND(block, R32(RTREG), I0, 0xffff); // dand <rtreg>,i0,0xffff
+ if (!in_delay_slot)
+ generate_update_cycles(rsp, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x32: /* LWC2 - MIPS I */
+ return generate_lwc2(rsp, block, compiler, desc);
+
+
+ /* ----- 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, *rsp->impstate->write8); // callh write8
+ if (!in_delay_slot)
+ generate_update_cycles(rsp, 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, *rsp->impstate->write16); // callh write16
+ if (!in_delay_slot)
+ generate_update_cycles(rsp, 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, *rsp->impstate->write32); // callh write32
+ if (!in_delay_slot)
+ generate_update_cycles(rsp, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x3a: /* SWC2 - MIPS I */
+ return generate_swc2(rsp, block, compiler, desc);
+ //UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ //UML_CALLC(block, cfunc_swc2, rsp); // callc cfunc_mfc2
+ //return TRUE;
+
+ /* ----- coprocessor instructions ----- */
+
+ case 0x10: /* COP0 - MIPS I */
+ return generate_cop0(rsp, block, compiler, desc);
+
+ case 0x12: /* COP2 - MIPS I */
+ return generate_cop2(rsp, block, compiler, desc);
+ //UML_EXH(block, rsp->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(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 op = desc->opptr.l[0];
+ UINT8 opswitch = op & 63;
+ //code_label skip;
+
+ switch (opswitch)
+ {
+ /* ----- shift instructions ----- */
+
+ case 0x00: /* SLL - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_SHL(block, R32(RDREG), R32(RTREG), SHIFT);
+ }
+ return TRUE;
+
+ case 0x02: /* SRL - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_SHR(block, R32(RDREG), R32(RTREG), SHIFT);
+ }
+ return TRUE;
+
+ case 0x03: /* SRA - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_SAR(block, R32(RDREG), R32(RTREG), SHIFT);
+ }
+ return TRUE;
+
+ case 0x04: /* SLLV - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_SHL(block, R32(RDREG), R32(RTREG), R32(RSREG));
+ }
+ return TRUE;
+
+ case 0x06: /* SRLV - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_SHR(block, R32(RDREG), R32(RTREG), R32(RSREG));
+ }
+ return TRUE;
+
+ case 0x07: /* SRAV - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_SAR(block, R32(RDREG), R32(RTREG), R32(RSREG));
+ }
+ return TRUE;
+
+ /* ----- basic arithmetic ----- */
+
+ case 0x20: /* ADD - MIPS I */
+ case 0x21: /* ADDU - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_ADD(block, R32(RDREG), R32(RSREG), R32(RTREG));
+ }
+ return TRUE;
+
+ case 0x22: /* SUB - MIPS I */
+ case 0x23: /* SUBU - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_SUB(block, R32(RDREG), R32(RSREG), R32(RTREG));
+ }
+ return TRUE;
+
+ /* ----- basic logical ops ----- */
+
+ case 0x24: /* AND - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_AND(block, R32(RDREG), R32(RSREG), R32(RTREG)); // dand <rdreg>,<rsreg>,<rtreg>
+ }
+ return TRUE;
+
+ case 0x25: /* OR - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_OR(block, R32(RDREG), R32(RSREG), R32(RTREG)); // dor <rdreg>,<rsreg>,<rtreg>
+ }
+ return TRUE;
+
+ case 0x26: /* XOR - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_XOR(block, R32(RDREG), R32(RSREG), R32(RTREG)); // dxor <rdreg>,<rsreg>,<rtreg>
+ }
+ return TRUE;
+
+ case 0x27: /* NOR - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_OR(block, I0, R32(RSREG), R32(RTREG)); // dor i0,<rsreg>,<rtreg>
+ UML_XOR(block, R32(RDREG), I0, (UINT64)~0); // dxor <rdreg>,i0,~0
+ }
+ return TRUE;
+
+
+ /* ----- basic comparisons ----- */
+
+ case 0x2a: /* SLT - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_CMP(block, R32(RSREG), R32(RTREG)); // dcmp <rsreg>,<rtreg>
+ UML_SETc(block, COND_L, R32(RDREG)); // dset <rdreg>,l
+ }
+ return TRUE;
+
+ case 0x2b: /* SLTU - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_CMP(block, R32(RSREG), R32(RTREG)); // dcmp <rsreg>,<rtreg>
+ UML_SETc(block, COND_B, R32(RDREG)); // dset <rdreg>,b
+ }
+ return TRUE;
+
+
+ /* ----- jumps and branches ----- */
+
+ case 0x08: /* JR - MIPS I */
+ generate_delay_slot_and_branch(rsp, block, compiler, desc, 0); // <next instruction + hashjmp>
+ return TRUE;
+
+ case 0x09: /* JALR - MIPS I */
+ generate_delay_slot_and_branch(rsp, block, compiler, desc, RDREG); // <next instruction + hashjmp>
+ return TRUE;
+
+
+ /* ----- system calls ----- */
+
+ case 0x0d: /* BREAK - MIPS I */
+ UML_MOV(block, mem(&rsp->impstate->arg0), 3); // mov [arg0],3
+ UML_CALLC(block, cfunc_sp_set_status_cb, rsp); // callc cfunc_sp_set_status_cb
+ UML_MOV(block, mem(&rsp->icount), 0); // mov icount, #0
+
+ UML_EXIT(block, EXECUTE_OUT_OF_CYCLES);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+
+/*-------------------------------------------------
+ generate_regimm - compile opcodes in the
+ 'REGIMM' group
+-------------------------------------------------*/
+
+static int generate_regimm(rsp_state *rsp, 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 0x10: /* BLTZAL */
+ if (RSREG != 0)
+ {
+ UML_CMP(block, R32(RSREG), 0); // dcmp <rsreg>,0
+ UML_JMPc(block, COND_GE, skip = compiler->labelnum++); // jmp skip,GE
+ generate_delay_slot_and_branch(rsp, block, compiler, desc, (opswitch & 0x10) ? 31 : 0);
+ // <next instruction + hashjmp>
+ UML_LABEL(block, skip); // skip:
+ }
+ return TRUE;
+
+ case 0x01: /* BGEZ */
+ case 0x11: /* BGEZAL */
+ if (RSREG != 0)
+ {
+ UML_CMP(block, R32(RSREG), 0); // dcmp <rsreg>,0
+ UML_JMPc(block, COND_L, skip = compiler->labelnum++); // jmp skip,L
+ generate_delay_slot_and_branch(rsp, block, compiler, desc, (opswitch & 0x10) ? 31 : 0);
+ // <next instruction + hashjmp>
+ UML_LABEL(block, skip); // skip:
+ }
+ else
+ generate_delay_slot_and_branch(rsp, block, compiler, desc, (opswitch & 0x10) ? 31 : 0);
+ // <next instruction + hashjmp>
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/*-------------------------------------------------
+ generate_cop2 - compile COP2 opcodes
+-------------------------------------------------*/
+
+static int generate_cop2(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 op = desc->opptr.l[0];
+ UINT8 opswitch = RSREG;
+
+ switch (opswitch)
+ {
+ case 0x00: /* MFCz */
+ if (RTREG != 0)
+ {
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_mfc2, rsp); // callc cfunc_mfc2
+ //UML_SEXT(block, R32(RTREG), I0, DWORD); // dsext <rtreg>,i0,dword
+ }
+ return TRUE;
+
+ case 0x02: /* CFCz */
+ if (RTREG != 0)
+ {
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_cfc2, rsp); // callc cfunc_cfc2
+ //UML_SEXT(block, R32(RTREG), I0, DWORD); // dsext <rtreg>,i0,dword
+ }
+ return TRUE;
+
+ case 0x04: /* MTCz */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_mtc2, rsp); // callc cfunc_mtc2
+ return TRUE;
+
+ case 0x06: /* CTCz */
+ UML_MOV(block, mem(&rsp->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_ctc2, rsp); // callc cfunc_ctc2
+ 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:
+ return generate_vector_opcode(rsp, block, compiler, desc);
+ }
+ return FALSE;
+}
+
+/*-------------------------------------------------
+ generate_cop0 - compile COP0 opcodes
+-------------------------------------------------*/
+
+static int generate_cop0(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 op = desc->opptr.l[0];
+ UINT8 opswitch = RSREG;
+
+ switch (opswitch)
+ {
+ case 0x00: /* MFCz */
+ if (RTREG != 0)
+ {
+ UML_MOV(block, mem(&rsp->impstate->arg0), RDREG); // mov [arg0],<rdreg>
+ UML_MOV(block, mem(&rsp->impstate->arg1), RTREG); // mov [arg1],<rtreg>
+ UML_CALLC(block, cfunc_get_cop0_reg, rsp); // callc cfunc_get_cop0_reg
+ }
+ return TRUE;
+
+ case 0x04: /* MTCz */
+ UML_MOV(block, mem(&rsp->impstate->arg0), RDREG); // mov [arg0],<rdreg>
+ UML_MOV(block, mem(&rsp->impstate->arg1), R32(RTREG)); // mov [arg1],rtreg
+ UML_CALLC(block, cfunc_set_cop0_reg, rsp); // callc cfunc_set_cop0_reg
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void cfunc_mfc2(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ int el = (op >> 7) & 0xf;
+ UINT16 b1 = VREG_B(VS1REG, (el+0) & 0xf);
+ UINT16 b2 = VREG_B(VS1REG, (el+1) & 0xf);
+ if (RTREG) RTVAL = (INT32)(INT16)((b1 << 8) | (b2));
+}
+
+static void cfunc_cfc2(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ if (RTREG)
+ {
+ if (RDREG == 2)
+ {
+ // Anciliary clipping flags
+ RTVAL = rsp->flag[RDREG] & 0x00ff;
+ }
+ else
+ {
+ // All other flags are 16 bits but sign-extended at retrieval
+ RTVAL = (UINT32)rsp->flag[RDREG] | ( ( rsp->flag[RDREG] & 0x8000 ) ? 0xffff0000 : 0 );
+ }
+ }
+}
+
+static void cfunc_mtc2(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ int el = (op >> 7) & 0xf;
+ VREG_B(VS1REG, (el+0) & 0xf) = (RTVAL >> 8) & 0xff;
+ VREG_B(VS1REG, (el+1) & 0xf) = (RTVAL >> 0) & 0xff;
+}
+
+static void cfunc_ctc2(void *param)
+{
+ rsp_state *rsp = (rsp_state*)param;
+ UINT32 op = rsp->impstate->arg0;
+ rsp->flag[RDREG] = RTVAL & 0xffff;
+}
+
+/***************************************************************************
+ CODE LOGGING HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ log_add_disasm_comment - add a comment
+ including disassembly of a RSP instruction
+-------------------------------------------------*/
+
+static void log_add_disasm_comment(rsp_state *rsp, drcuml_block *block, UINT32 pc, UINT32 op)
+{
+#if (LOG_UML)
+ char buffer[100];
+ rsp_dasm_one(buffer, pc, op);
+ block->append_comment("%08X: %s", pc, buffer); // comment
+#endif
+}
+
+
+static CPU_SET_INFO( rsp )
+{
+ rsp_state *rsp = 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 + RSP_PC: rsp->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R0: rsp->r[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R1: rsp->r[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R2: rsp->r[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R3: rsp->r[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R4: rsp->r[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R5: rsp->r[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R6: rsp->r[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R7: rsp->r[7] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R8: rsp->r[8] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R9: rsp->r[9] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R10: rsp->r[10] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R11: rsp->r[11] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R12: rsp->r[12] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R13: rsp->r[13] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R14: rsp->r[14] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R15: rsp->r[15] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R16: rsp->r[16] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R17: rsp->r[17] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R18: rsp->r[18] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R19: rsp->r[19] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R20: rsp->r[20] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R21: rsp->r[21] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R22: rsp->r[22] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R23: rsp->r[23] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R24: rsp->r[24] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R25: rsp->r[25] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R26: rsp->r[26] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R27: rsp->r[27] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R28: rsp->r[28] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R29: rsp->r[29] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_R30: rsp->r[30] = info->i; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + RSP_R31: rsp->r[31] = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_SR: rsp->sr = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_NEXTPC: rsp->nextpc = info->i; break;
+ case CPUINFO_INT_REGISTER + RSP_STEPCNT: rsp->step_count = info->i; break;
+ }
+}
+
+CPU_GET_INFO( rsp )
+{
+ rsp_state *rsp = (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(rsp_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 = 1; 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: info->i = rsp->ppc; break;
+
+ case CPUINFO_INT_PC: /* intentional fallthrough */
+ case CPUINFO_INT_REGISTER + RSP_PC: info->i = rsp->pc; break;
+
+ case CPUINFO_INT_REGISTER + RSP_R0: info->i = rsp->r[0]; break;
+ case CPUINFO_INT_REGISTER + RSP_R1: info->i = rsp->r[1]; break;
+ case CPUINFO_INT_REGISTER + RSP_R2: info->i = rsp->r[2]; break;
+ case CPUINFO_INT_REGISTER + RSP_R3: info->i = rsp->r[3]; break;
+ case CPUINFO_INT_REGISTER + RSP_R4: info->i = rsp->r[4]; break;
+ case CPUINFO_INT_REGISTER + RSP_R5: info->i = rsp->r[5]; break;
+ case CPUINFO_INT_REGISTER + RSP_R6: info->i = rsp->r[6]; break;
+ case CPUINFO_INT_REGISTER + RSP_R7: info->i = rsp->r[7]; break;
+ case CPUINFO_INT_REGISTER + RSP_R8: info->i = rsp->r[8]; break;
+ case CPUINFO_INT_REGISTER + RSP_R9: info->i = rsp->r[9]; break;
+ case CPUINFO_INT_REGISTER + RSP_R10: info->i = rsp->r[10]; break;
+ case CPUINFO_INT_REGISTER + RSP_R11: info->i = rsp->r[11]; break;
+ case CPUINFO_INT_REGISTER + RSP_R12: info->i = rsp->r[12]; break;
+ case CPUINFO_INT_REGISTER + RSP_R13: info->i = rsp->r[13]; break;
+ case CPUINFO_INT_REGISTER + RSP_R14: info->i = rsp->r[14]; break;
+ case CPUINFO_INT_REGISTER + RSP_R15: info->i = rsp->r[15]; break;
+ case CPUINFO_INT_REGISTER + RSP_R16: info->i = rsp->r[16]; break;
+ case CPUINFO_INT_REGISTER + RSP_R17: info->i = rsp->r[17]; break;
+ case CPUINFO_INT_REGISTER + RSP_R18: info->i = rsp->r[18]; break;
+ case CPUINFO_INT_REGISTER + RSP_R19: info->i = rsp->r[19]; break;
+ case CPUINFO_INT_REGISTER + RSP_R20: info->i = rsp->r[20]; break;
+ case CPUINFO_INT_REGISTER + RSP_R21: info->i = rsp->r[21]; break;
+ case CPUINFO_INT_REGISTER + RSP_R22: info->i = rsp->r[22]; break;
+ case CPUINFO_INT_REGISTER + RSP_R23: info->i = rsp->r[23]; break;
+ case CPUINFO_INT_REGISTER + RSP_R24: info->i = rsp->r[24]; break;
+ case CPUINFO_INT_REGISTER + RSP_R25: info->i = rsp->r[25]; break;
+ case CPUINFO_INT_REGISTER + RSP_R26: info->i = rsp->r[26]; break;
+ case CPUINFO_INT_REGISTER + RSP_R27: info->i = rsp->r[27]; break;
+ case CPUINFO_INT_REGISTER + RSP_R28: info->i = rsp->r[28]; break;
+ case CPUINFO_INT_REGISTER + RSP_R29: info->i = rsp->r[29]; break;
+ case CPUINFO_INT_REGISTER + RSP_R30: info->i = rsp->r[30]; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + RSP_R31: info->i = rsp->r[31]; break;
+ case CPUINFO_INT_REGISTER + RSP_SR: info->i = rsp->sr; break;
+ case CPUINFO_INT_REGISTER + RSP_NEXTPC: info->i = rsp->nextpc; break;
+ case CPUINFO_INT_REGISTER + RSP_STEPCNT: info->i = rsp->step_count; 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(rsp); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(rsp); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(rsp); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(rsp); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(rsp); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(rsp); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &rsp->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "RSP"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "RSP"); 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 + RSP_PC: sprintf(info->s, "PC: %08X", rsp->pc); break;
+
+ case CPUINFO_STR_REGISTER + RSP_R0: sprintf(info->s, "R0: %08X", rsp->r[0]); break;
+ case CPUINFO_STR_REGISTER + RSP_R1: sprintf(info->s, "R1: %08X", rsp->r[1]); break;
+ case CPUINFO_STR_REGISTER + RSP_R2: sprintf(info->s, "R2: %08X", rsp->r[2]); break;
+ case CPUINFO_STR_REGISTER + RSP_R3: sprintf(info->s, "R3: %08X", rsp->r[3]); break;
+ case CPUINFO_STR_REGISTER + RSP_R4: sprintf(info->s, "R4: %08X", rsp->r[4]); break;
+ case CPUINFO_STR_REGISTER + RSP_R5: sprintf(info->s, "R5: %08X", rsp->r[5]); break;
+ case CPUINFO_STR_REGISTER + RSP_R6: sprintf(info->s, "R6: %08X", rsp->r[6]); break;
+ case CPUINFO_STR_REGISTER + RSP_R7: sprintf(info->s, "R7: %08X", rsp->r[7]); break;
+ case CPUINFO_STR_REGISTER + RSP_R8: sprintf(info->s, "R8: %08X", rsp->r[8]); break;
+ case CPUINFO_STR_REGISTER + RSP_R9: sprintf(info->s, "R9: %08X", rsp->r[9]); break;
+ case CPUINFO_STR_REGISTER + RSP_R10: sprintf(info->s, "R10: %08X", rsp->r[10]); break;
+ case CPUINFO_STR_REGISTER + RSP_R11: sprintf(info->s, "R11: %08X", rsp->r[11]); break;
+ case CPUINFO_STR_REGISTER + RSP_R12: sprintf(info->s, "R12: %08X", rsp->r[12]); break;
+ case CPUINFO_STR_REGISTER + RSP_R13: sprintf(info->s, "R13: %08X", rsp->r[13]); break;
+ case CPUINFO_STR_REGISTER + RSP_R14: sprintf(info->s, "R14: %08X", rsp->r[14]); break;
+ case CPUINFO_STR_REGISTER + RSP_R15: sprintf(info->s, "R15: %08X", rsp->r[15]); break;
+ case CPUINFO_STR_REGISTER + RSP_R16: sprintf(info->s, "R16: %08X", rsp->r[16]); break;
+ case CPUINFO_STR_REGISTER + RSP_R17: sprintf(info->s, "R17: %08X", rsp->r[17]); break;
+ case CPUINFO_STR_REGISTER + RSP_R18: sprintf(info->s, "R18: %08X", rsp->r[18]); break;
+ case CPUINFO_STR_REGISTER + RSP_R19: sprintf(info->s, "R19: %08X", rsp->r[19]); break;
+ case CPUINFO_STR_REGISTER + RSP_R20: sprintf(info->s, "R20: %08X", rsp->r[20]); break;
+ case CPUINFO_STR_REGISTER + RSP_R21: sprintf(info->s, "R21: %08X", rsp->r[21]); break;
+ case CPUINFO_STR_REGISTER + RSP_R22: sprintf(info->s, "R22: %08X", rsp->r[22]); break;
+ case CPUINFO_STR_REGISTER + RSP_R23: sprintf(info->s, "R23: %08X", rsp->r[23]); break;
+ case CPUINFO_STR_REGISTER + RSP_R24: sprintf(info->s, "R24: %08X", rsp->r[24]); break;
+ case CPUINFO_STR_REGISTER + RSP_R25: sprintf(info->s, "R25: %08X", rsp->r[25]); break;
+ case CPUINFO_STR_REGISTER + RSP_R26: sprintf(info->s, "R26: %08X", rsp->r[26]); break;
+ case CPUINFO_STR_REGISTER + RSP_R27: sprintf(info->s, "R27: %08X", rsp->r[27]); break;
+ case CPUINFO_STR_REGISTER + RSP_R28: sprintf(info->s, "R28: %08X", rsp->r[28]); break;
+ case CPUINFO_STR_REGISTER + RSP_R29: sprintf(info->s, "R29: %08X", rsp->r[29]); break;
+ case CPUINFO_STR_REGISTER + RSP_R30: sprintf(info->s, "R30: %08X", rsp->r[30]); break;
+ case CPUINFO_STR_REGISTER + RSP_R31: sprintf(info->s, "R31: %08X", rsp->r[31]); break;
+ case CPUINFO_STR_REGISTER + RSP_SR: sprintf(info->s, "SR: %08X", rsp->sr); break;
+ case CPUINFO_STR_REGISTER + RSP_NEXTPC: sprintf(info->s, "NPC: %08X", rsp->nextpc);break;
+ case CPUINFO_STR_REGISTER + RSP_STEPCNT: sprintf(info->s, "STEP: %d", rsp->step_count); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(RSP, rsp);
+
+#endif // USE_RSPDRC
diff --git a/trunk/src/emu/cpu/rsp/rspfe.c b/trunk/src/emu/cpu/rsp/rspfe.c
new file mode 100644
index 00000000000..dca31e40f2d
--- /dev/null
+++ b/trunk/src/emu/cpu/rsp/rspfe.c
@@ -0,0 +1,304 @@
+/***************************************************************************
+
+ rspfe.c
+
+ Front-end for RSP recompiler
+
+ Copyright the MESS team
+ Released for general non-commercial use under the MAME license
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "rspfe.h"
+#include "rsp.h"
+
+//**************************************************************************
+// RSP FRONTEND
+//**************************************************************************
+
+//-------------------------------------------------
+// rsp_frontend - constructor
+//-------------------------------------------------
+
+rsp_frontend::rsp_frontend(rsp_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 rsp_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
+{
+ UINT32 op, opswitch;
+
+ // fetch the opcode
+ op = desc.opptr.l[0] = m_context.direct->read_decrypted_dword(desc.physpc | 0x1000);
+
+ // 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 0x12: // COP2
+ return describe_cop2(op, desc);
+
+ case 0x02: // J
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.targetpc = ((LIMMVAL << 2) & 0x00000fff) | 0x1000;
+ 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 = ((LIMMVAL << 2) & 0x00000fff) | 0x1000;
+ desc.delayslots = 1;
+ return true;
+
+ case 0x04: // BEQ
+ case 0x05: // BNE
+ 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)) & 0x00000fff) | 0x1000;
+ desc.delayslots = 1;
+ desc.skipslots = (opswitch & 0x10) ? 1 : 0;
+ return true;
+
+ case 0x06: // BLEZ
+ case 0x07: // BGTZ
+ 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)) & 0x00000fff) | 0x1000;
+ desc.delayslots = 1;
+ desc.skipslots = (opswitch & 0x10) ? 1 : 0;
+ return true;
+
+ case 0x08: // ADDI
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x09: // ADDIU
+ case 0x0a: // SLTI
+ case 0x0b: // SLTIU
+ case 0x0c: // ANDI
+ case 0x0d: // ORI
+ case 0x0e: // XORI
+ 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 0x20: // LB
+ case 0x21: // LH
+ case 0x23: // LW
+ case 0x24: // LBU
+ case 0x25: // LHU
+ case 0x27: // LWU
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 0x28: // SB
+ case 0x29: // SH
+ case 0x2b: // SW
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 0x32: // LWC2
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 0x3a: // SWC2
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+ }
+
+ return false;
+}
+
+
+//-------------------------------------------------
+// describe_special - build a description of a
+// single instruction in the 'special' group
+//-------------------------------------------------
+
+bool rsp_frontend::describe_special(UINT32 op, opcode_desc &desc)
+{
+ switch (op & 63)
+ {
+ case 0x00: // SLL
+ case 0x02: // SRL
+ case 0x03: // SRA
+ desc.regin[0] |= REGFLAG_R(RTREG);
+ desc.regout[0] |= REGFLAG_R(RDREG);
+ return true;
+
+ case 0x04: // SLLV
+ case 0x06: // SRLV
+ case 0x07: // SRAV
+ case 0x21: // ADDU
+ case 0x23: // SUBU
+ case 0x24: // AND
+ case 0x25: // OR
+ case 0x26: // XOR
+ case 0x27: // NOR
+ case 0x2a: // SLT
+ case 0x2b: // SLTU
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ desc.regout[0] |= REGFLAG_R(RDREG);
+ return true;
+
+ case 0x20: // ADD
+ case 0x22: // SUB
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ 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 0x0d: // BREAK
+ desc.flags |= OPFLAG_END_SEQUENCE;
+ desc.targetpc = BRANCH_TARGET_DYNAMIC;
+ return true;
+ }
+
+ return false;
+}
+
+
+//-------------------------------------------------
+// describe_regimm - build a description of a
+// single instruction in the 'regimm' group
+//-------------------------------------------------
+
+bool rsp_frontend::describe_regimm(UINT32 op, opcode_desc &desc)
+{
+ switch (RTREG)
+ {
+ case 0x00: // BLTZ
+ case 0x01: // BGEZ
+ 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)) & 0x00000fff) | 0x1000;
+ desc.delayslots = 1;
+ desc.skipslots = (RTREG & 0x02) ? 1 : 0;
+ return true;
+
+ case 0x10: // BLTZAL
+ case 0x11: // BGEZAL
+ 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)) & 0x00000fff) | 0x1000;
+ desc.delayslots = 1;
+ desc.skipslots = (RTREG & 0x02) ? 1 : 0;
+ return true;
+ }
+
+ return false;
+}
+
+
+//-------------------------------------------------
+// describe_cop0 - build a description of a
+// single instruction in the COP0 group
+//-------------------------------------------------
+
+bool rsp_frontend::describe_cop0(UINT32 op, opcode_desc &desc)
+{
+ switch (RSREG)
+ {
+ case 0x00: // MFCz
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x04: // MTCz
+ desc.regin[0] |= REGFLAG_R(RTREG);
+ return true;
+ }
+
+ return false;
+}
+
+//-------------------------------------------------
+// describe_cop2 - build a description of a
+// single instruction in the COP2 group
+//-------------------------------------------------
+
+bool rsp_frontend::describe_cop2(UINT32 op, opcode_desc &desc)
+{
+ switch (RSREG)
+ {
+ case 0x00: // MFCz
+ case 0x02: // CFCz
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x04: // MTCz
+ case 0x06: // CTCz
+ desc.regin[0] |= REGFLAG_R(RTREG);
+ return true;
+ }
+
+ return false;
+}
diff --git a/trunk/src/emu/cpu/rsp/rspfe.h b/trunk/src/emu/cpu/rsp/rspfe.h
new file mode 100644
index 00000000000..b032c306b2b
--- /dev/null
+++ b/trunk/src/emu/cpu/rsp/rspfe.h
@@ -0,0 +1,58 @@
+/***************************************************************************
+
+ rspfe.h
+
+ Front-end for RSP recompiler
+
+ Copyright the MESS team
+ Released for general non-commercial use under the MAME license
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __RSPFE_H__
+#define __RSPFE_H__
+
+#include "rsp.h"
+#include "cpu/drcfe.h"
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// register flags 0
+#define REGFLAG_R(n) (((n) == 0) ? 0 : (1 << (n)))
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class rsp_frontend : public drc_frontend
+{
+public:
+ // construction/destruction
+ rsp_frontend(rsp_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_cop0(UINT32 op, opcode_desc &desc);
+ bool describe_cop2(UINT32 op, opcode_desc &desc);
+
+ // internal state
+ rsp_state &m_context;
+};
+
+
+
+#endif /* __RSPFE_H__ */
diff --git a/trunk/src/emu/cpu/s2650/2650dasm.c b/trunk/src/emu/cpu/s2650/2650dasm.c
new file mode 100644
index 00000000000..1841ca2eba5
--- /dev/null
+++ b/trunk/src/emu/cpu/s2650/2650dasm.c
@@ -0,0 +1,868 @@
+/***************************************************************************
+ *
+ * Portable Signetics 2650 disassembler
+ *
+ * Written by J. Buchmueller (pullmoll@t-online.de)
+ * for the MAME project
+ *
+ **************************************************************************/
+
+#include "emu.h"
+
+static const UINT8 *rambase;
+static offs_t pcbase;
+
+#define readarg(A) (rambase[(A) - pcbase])
+
+/* Set this to 1 to disassemble using Z80 style mnemonics */
+#define HJB 0
+
+/* Set this to 1 to give names to condition codes and flag bits */
+#define MNEMO 1
+
+/* handy table to build relative offsets from HR (holding register) */
+static const int rel[0x100] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ -64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,
+ -48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,
+ -32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,
+ -16,-15,-14,-13,-12,-11,-10, -9, -8, -7, -6, -5, -4, -3, -2, -1,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ -64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,
+ -48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,
+ -32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,
+ -16,-15,-14,-13,-12,-11,-10, -9, -8, -7, -6, -5, -4, -3, -2, -1,
+};
+
+typedef char* (*callback) (int addr);
+static callback find_symbol = 0;
+
+static char *SYM(int addr)
+{
+ static char buff[8+1];
+ char * s = NULL;
+
+ if (find_symbol) s = (*find_symbol)(addr);
+ if (s) return s;
+
+ sprintf(buff, "$%04x", addr);
+ return buff;
+}
+
+/* format an immediate */
+static char *IMM(int pc)
+{
+ static char buff[32];
+
+ sprintf(buff, "$%02x", readarg(pc));
+ return buff;
+}
+
+#if MNEMO
+static const char cc[4] = { 'z', 'p', 'm', 'a' };
+
+/* format an immediate for PSL */
+static char *IMM_PSL(int pc)
+{
+ static char buff[32];
+ char *p = buff;
+ int v = readarg(pc);
+
+ if (v == 0xff) {
+ p += sprintf(p, "all");
+ } else {
+ switch (v & 0xc0)
+ {
+ case 0x40: p += sprintf(p, "p+"); break;
+ case 0x80: p += sprintf(p, "m+"); break;
+ case 0xc0: p += sprintf(p, "cc+"); break;
+ }
+ if (v & 0x20) /* inter digit carry */
+ p += sprintf(p, "idc+");
+ if (v & 0x10) /* register select */
+ p += sprintf(p, "rs+");
+ if (v & 0x08) /* with carry */
+ p += sprintf(p, "wc+");
+ if (v & 0x04) /* overflow */
+ p += sprintf(p, "ovf+");
+ if (v & 0x02) /* 2's complement comparisons */
+ p += sprintf(p, "com+");
+ if (v & 0x01) /* carry */
+ p += sprintf(p, "c+");
+ if (p > buff)
+ *--p = '\0';
+ }
+ return buff;
+}
+
+/* format an immediate for PSU (processor status upper) */
+static char *IMM_PSU(int pc)
+{
+ static char buff[32];
+ char *p = buff;
+ int v = readarg(pc);
+
+ if (v == 0xff) {
+
+ p += sprintf(p, "all");
+
+ } else {
+
+ if (v & 0x80) /* sense input */
+ p += sprintf(p, "si+");
+ if (v & 0x40) /* flag output */
+ p += sprintf(p, "fo+");
+ if (v & 0x20) /* interrupt inhibit */
+ p += sprintf(p, "ii+");
+ if (v & 0x10) /* unused bit 4 */
+ p += sprintf(p, "4+");
+ if (v & 0x08) /* unused bit 3 */
+ p += sprintf(p, "3+");
+ if (v & 0x04) /* stack pointer bit 2 */
+ p += sprintf(p, "sp2+");
+ if (v & 0x02) /* stack pointer bit 1 */
+ p += sprintf(p, "sp1+");
+ if (v & 0x01) /* stack pointer bit 0 */
+ p += sprintf(p, "sp0+");
+ if (p > buff)
+ *--p = '\0';
+ }
+ return buff;
+}
+#else
+static const char cc[4] = { '0', '1', '2', '3' };
+#define IMM_PSL IMM
+#define IMM_PSU IMM
+#endif
+
+/* format an relative address */
+static char *REL(int pc)
+{
+static char buff[32];
+int o = readarg(pc);
+ sprintf(buff, "%s%s", (o&0x80)?"*":"", SYM((pc&0x6000)+((pc+1+rel[o])&0x1fff)));
+ return buff;
+}
+
+/* format an relative address (implicit page 0) */
+static char *REL0(int pc)
+{
+static char buff[32];
+int o = readarg(pc);
+ sprintf(buff, "%s%s", (o&0x80)?"*":"", SYM((rel[o]) & 0x1fff));
+ return buff;
+}
+
+/* format a destination register and an absolute address */
+static char *ABS(int load, int r, int pc)
+{
+ static char buff[32];
+ int h = readarg(pc);
+ int l = readarg((pc&0x6000)+((pc+1)&0x1fff));
+ int a = (pc & 0x6000) + ((h & 0x1f) << 8) + l;
+
+#if HJB
+ if (load) {
+ switch (h >> 5) {
+ case 0: sprintf(buff, "r%d,(%s)", r, SYM(a)); break;
+ case 1: sprintf(buff, "r0,(%s,r%d++)", SYM(a), r); break;
+ case 2: sprintf(buff, "r0,(%s,r%d--)", SYM(a), r); break;
+ case 3: sprintf(buff, "r0,(%s,r%d)", SYM(a), r); break;
+ case 4: sprintf(buff, "r%d,*(%s)", r, SYM(a)); break;
+ case 5: sprintf(buff, "r0,*(%s,r%d++)", SYM(a), r); break;
+ case 6: sprintf(buff, "r0,*(%s,r%d--)", SYM(a), r); break;
+ case 7: sprintf(buff, "r0,*(%s,r%d)", SYM(a), r); break;
+ }
+ } else {
+ switch (h >> 5) {
+ case 0: sprintf(buff, "(%s),r%d", SYM(a), r); break;
+ case 1: sprintf(buff, "(%s,r%d++),r0", SYM(a), r); break;
+ case 2: sprintf(buff, "(%s,r%d--),r0", SYM(a), r); break;
+ case 3: sprintf(buff, "(%s,r%d),r0", SYM(a), r); break;
+ case 4: sprintf(buff, "*(%s),r%d", SYM(a), r); break;
+ case 5: sprintf(buff, "*(%s,r%d++),r0", SYM(a), r); break;
+ case 6: sprintf(buff, "*(%s,r%d--),r0", SYM(a), r); break;
+ case 7: sprintf(buff, "*(%s,r%d),r0", SYM(a), r); break;
+ }
+ }
+#else
+ switch (h >> 5) {
+ case 0: sprintf(buff, "%d %s", r, SYM(a)); break;
+ case 1: sprintf(buff, "0 %s,r%d+", SYM(a), r); break;
+ case 2: sprintf(buff, "0 %s,r%d-", SYM(a), r); break;
+ case 3: sprintf(buff, "0 %s,r%d", SYM(a), r); break;
+ case 4: sprintf(buff, "%d *%s", r, SYM(a)); break;
+ case 5: sprintf(buff, "0 *%s,r%d+", SYM(a), r); break;
+ case 6: sprintf(buff, "0 *%s,r%d-", SYM(a), r); break;
+ case 7: sprintf(buff, "0 *%s,r%d", SYM(a), r); break;
+ }
+#endif
+ return buff;
+}
+
+/* format an (branch) absolute address */
+static char *ADR(int pc)
+{
+ static char buff[32];
+ int h = readarg(pc);
+ int l = readarg((pc&0x6000)+((pc+1)&0x1fff));
+ int a = ((h & 0x7f) << 8) + l;
+ if (h & 0x80)
+ sprintf(buff, "*%s", SYM(a));
+ else
+ sprintf(buff, "%s", SYM(a));
+ return buff;
+}
+
+/* disassemble one instruction at PC into buff. return byte size of instr */
+CPU_DISASSEMBLE( s2650 )
+{
+ UINT32 flags = 0;
+ int PC = pc;
+ int op = oprom[0];
+ int rv = op & 3;
+
+ rambase = opram;
+ pcbase = PC;
+
+ pc += 1;
+ switch (op)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03:
+#if HJB
+ sprintf(buffer, "ld r0,r%d", rv);
+#else
+ sprintf(buffer, "lodz,%d", rv);
+#endif
+ break;
+ case 0x04: case 0x05: case 0x06: case 0x07:
+#if HJB
+ sprintf(buffer, "ld r%d,%s", rv, IMM(pc));
+#else
+ sprintf(buffer, "lodi,%d %s", rv, IMM(pc));
+#endif
+ pc+=1;
+ break;
+ case 0x08: case 0x09: case 0x0a: case 0x0b:
+#if HJB
+ sprintf(buffer, "ld r%d,(%s)", rv, REL(pc));
+#else
+ sprintf(buffer, "lodr,%d %s", rv, REL(pc));
+#endif
+ pc+=1;
+ break;
+ case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+#if HJB
+ sprintf(buffer, "ld %s", ABS(1,rv,pc));
+#else
+ sprintf(buffer, "loda,%s", ABS(1,rv,pc));
+#endif
+ pc+=2;
+ break;
+ case 0x10: case 0x11:
+#if HJB
+ sprintf(buffer, "**** $%02X",op);
+#else
+ sprintf(buffer, "**** $%02X",op);
+#endif
+ break;
+ case 0x12:
+#if HJB
+ sprintf(buffer, "ld psu,r0");
+#else
+ sprintf(buffer, "spsu");
+#endif
+ break;
+ case 0x13:
+#if HJB
+ sprintf(buffer, "ld psl,r0");
+#else
+ sprintf(buffer, "spsl");
+#endif
+ break;
+ case 0x14: case 0x15: case 0x16: case 0x17:
+#if HJB
+ if (rv == 3)
+ sprintf(buffer, "ret");
+ else
+ sprintf(buffer, "ret %c", cc[rv]);
+#else
+ sprintf(buffer, "retc %c", cc[rv]);
+#endif
+ flags = DASMFLAG_STEP_OUT;
+ break;
+ case 0x18: case 0x19: case 0x1a: case 0x1b:
+#if HJB
+ if (rv == 3)
+ sprintf(buffer, "jr %s", REL(pc));
+ else
+ sprintf(buffer, "jr %c,%s", cc[rv], REL(pc));
+#else
+ sprintf(buffer, "bctr,%c %s", cc[rv], REL(pc));
+#endif
+ pc+=1;
+ break;
+ case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+#if HJB
+ if (rv == 3)
+ sprintf(buffer, "jp %s", ADR(pc));
+ else
+ sprintf(buffer, "jp %c,%s", cc[rv], ADR(pc));
+#else
+ sprintf(buffer, "bcta,%c %s", cc[rv], ADR(pc));
+#endif
+ pc+=2;
+ break;
+ case 0x20: case 0x21: case 0x22: case 0x23:
+#if HJB
+ sprintf(buffer, "xor r0,r%d", rv);
+#else
+ sprintf(buffer, "eorz,%d", rv);
+#endif
+ break;
+ case 0x24: case 0x25: case 0x26: case 0x27:
+#if HJB
+ sprintf(buffer, "xor r%d,%s", rv, IMM(pc));
+#else
+ sprintf(buffer, "eori,%d %s", rv, IMM(pc));
+#endif
+ pc+=1;
+ break;
+ case 0x28: case 0x29: case 0x2a: case 0x2b:
+#if HJB
+ sprintf(buffer, "xor r%d,(%s)", rv, REL(pc));
+#else
+ sprintf(buffer, "eorr,%d %s", rv, REL(pc));
+#endif
+ pc+=1;
+ break;
+ case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+#if HJB
+ sprintf(buffer, "xor %s", ABS(1,rv,pc));
+#else
+ sprintf(buffer, "eora,%s", ABS(1,rv,pc));
+#endif
+ pc+=2;
+ break;
+ case 0x30: case 0x31: case 0x32: case 0x33:
+#if HJB
+ sprintf(buffer, "in r%d,(ctrl)", rv);
+#else
+ sprintf(buffer, "redc,%d", rv);
+#endif
+ break;
+ case 0x34: case 0x35: case 0x36: case 0x37:
+#if HJB
+ if (rv == 3)
+ sprintf(buffer, "iret");
+ else
+ sprintf(buffer, "iret %c", cc[rv]);
+#else
+ sprintf(buffer, "rete %c", cc[rv]);
+#endif
+ flags = DASMFLAG_STEP_OUT;
+ break;
+ case 0x38: case 0x39: case 0x3a: case 0x3b:
+#if HJB
+ if (rv == 3)
+ sprintf(buffer, "calr %s", REL(pc));
+ else
+ sprintf(buffer, "calr %c,%s", cc[rv], REL(pc));
+#else
+ sprintf(buffer, "bstr,%c %s", cc[rv], REL(pc));
+#endif
+ pc+=1;
+ flags = DASMFLAG_STEP_OVER;
+ break;
+ case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+#if HJB
+ if (rv == 3)
+ sprintf(buffer, "call %s", ADR(pc));
+ else
+ sprintf(buffer, "call %c,%s", cc[rv], ADR(pc));
+#else
+ sprintf(buffer, "bsta,%c %s", cc[rv], ADR(pc));
+#endif
+ pc+=2;
+ flags = DASMFLAG_STEP_OVER;
+ break;
+ case 0x40:
+ sprintf(buffer, "halt");
+ break;
+ case 0x41: case 0x42: case 0x43:
+#if HJB
+ sprintf(buffer, "and r0,r%d", rv);
+#else
+ sprintf(buffer, "andz,%d", rv);
+#endif
+ break;
+ case 0x44: case 0x45: case 0x46: case 0x47:
+#if HJB
+ sprintf(buffer, "and r%d,%s", rv, IMM(pc));
+#else
+ sprintf(buffer, "andi,%d %s", rv, IMM(pc));
+#endif
+ pc+=1;
+ break;
+ case 0x48: case 0x49: case 0x4a: case 0x4b:
+#if HJB
+ sprintf(buffer, "and r%d,(%s)", rv, REL(pc));
+#else
+ sprintf(buffer, "andr,%d %s", rv, REL(pc));
+#endif
+ pc+=1;
+ break;
+ case 0x4c: case 0x4d: case 0x4e: case 0x4f:
+#if HJB
+ sprintf(buffer, "and %s", ABS(1,rv,pc));
+#else
+ sprintf(buffer, "anda,%s", ABS(1,rv,pc));
+#endif
+ pc+=2;
+ break;
+ case 0x50: case 0x51: case 0x52: case 0x53:
+#if HJB
+ sprintf(buffer, "ror r%d", rv);
+#else
+ sprintf(buffer, "rrr,%d", rv);
+#endif
+ break;
+ case 0x54: case 0x55: case 0x56: case 0x57:
+#if HJB
+ sprintf(buffer, "in r%d,(%s)", rv, IMM(pc));
+#else
+ sprintf(buffer, "rede,%d %s", rv, IMM(pc));
+#endif
+ pc+=1;
+ break;
+ case 0x58: case 0x59: case 0x5a: case 0x5b:
+#if HJB
+ sprintf(buffer, "jrnz r%d,%s", rv, REL(pc));
+#else
+ sprintf(buffer, "brnr,%d %s", rv, REL(pc));
+#endif
+ pc+=1;
+ break;
+ case 0x5c: case 0x5d: case 0x5e: case 0x5f:
+#if HJB
+ sprintf(buffer, "jpnz r%d,%s", rv, ADR(pc));
+#else
+ sprintf(buffer, "brna,%d %s", rv, ADR(pc));
+#endif
+ pc+=2;
+ break;
+ case 0x60: case 0x61: case 0x62: case 0x63:
+#if HJB
+ sprintf(buffer, "or r0,r%d", rv);
+#else
+ sprintf(buffer, "iorz,%d", rv);
+#endif
+ break;
+ case 0x64: case 0x65: case 0x66: case 0x67:
+#if HJB
+ sprintf(buffer, "or r%d,%s", rv, IMM(pc));
+#else
+ sprintf(buffer, "iori,%d %s", rv, IMM(pc));
+#endif
+ pc+=1;
+ break;
+ case 0x68: case 0x69: case 0x6a: case 0x6b:
+#if HJB
+ sprintf(buffer, "or r%d,(%s)", rv, REL(pc));
+#else
+ sprintf(buffer, "iorr,%d %s", rv, REL(pc));
+#endif
+ pc+=1;
+ break;
+ case 0x6c: case 0x6d: case 0x6e: case 0x6f:
+#if HJB
+ sprintf(buffer, "or %s", ABS(1,rv,pc));
+#else
+ sprintf(buffer, "iora,%s", ABS(1,rv,pc));
+#endif
+ pc+=2;
+ break;
+ case 0x70: case 0x71: case 0x72: case 0x73:
+#if HJB
+ sprintf(buffer, "in r%d,(data)", rv);
+#else
+ sprintf(buffer, "redd,%d", rv);
+#endif
+ break;
+ case 0x74:
+#if HJB
+ sprintf(buffer, "res psu,%s", IMM_PSU(pc));
+#else
+ sprintf(buffer, "cpsu %s", IMM_PSU(pc));
+#endif
+ pc+=1;
+ break;
+ case 0x75:
+#if HJB
+ sprintf(buffer, "res psl,%s", IMM_PSL(pc));
+#else
+ sprintf(buffer, "cpsl %s", IMM_PSL(pc));
+#endif
+ pc+=1;
+ break;
+ case 0x76:
+#if HJB
+ sprintf(buffer, "set psu,%s", IMM_PSU(pc));
+#else
+ sprintf(buffer, "ppsu %s", IMM_PSU(pc));
+#endif
+ pc+=1;
+ break;
+ case 0x77:
+#if HJB
+ sprintf(buffer, "set psl,%s", IMM_PSL(pc));
+#else
+ sprintf(buffer, "ppsl %s", IMM_PSL(pc));
+#endif
+ pc+=1;
+ break;
+ case 0x78: case 0x79: case 0x7a: case 0x7b:
+#if HJB
+ sprintf(buffer, "call r%d-nz,%s", rv, REL(pc));
+#else
+ sprintf(buffer, "bsnr,%d %s", rv, REL(pc));
+#endif
+ pc+=1;
+ flags = DASMFLAG_STEP_OVER;
+ break;
+ case 0x7c: case 0x7d: case 0x7e: case 0x7f:
+#if HJB
+ sprintf(buffer, "call r%d-nz,%s", rv, ADR(pc));
+#else
+ sprintf(buffer, "bsna,%d %s", rv, ADR(pc));
+#endif
+ pc+=2;
+ flags = DASMFLAG_STEP_OVER;
+ break;
+ case 0x80: case 0x81: case 0x82: case 0x83:
+#if HJB
+ sprintf(buffer, "add r0,r%d", rv);
+#else
+ sprintf(buffer, "addz,%d", rv);
+#endif
+ break;
+ case 0x84: case 0x85: case 0x86: case 0x87:
+#if HJB
+ sprintf(buffer, "add r%d,%s", rv, IMM(pc));
+#else
+ sprintf(buffer, "addi,%d %s", rv, IMM(pc));
+#endif
+ pc+=1;
+ break;
+ case 0x88: case 0x89: case 0x8a: case 0x8b:
+#if HJB
+ sprintf(buffer, "add r%d,(%s)", rv, REL(pc));
+#else
+ sprintf(buffer, "addr,%d %s", rv, REL(pc));
+#endif
+ pc+=1;
+ break;
+ case 0x8c: case 0x8d: case 0x8e: case 0x8f:
+#if HJB
+ sprintf(buffer, "add %s", ABS(1,rv,pc));
+#else
+ sprintf(buffer, "adda,%s", ABS(1,rv,pc));
+#endif
+ pc+=2;
+ break;
+ case 0x90: case 0x91:
+#if HJB
+ sprintf(buffer, "**** $%02X",op);
+#else
+ sprintf(buffer, "**** $%02X",op);
+#endif
+ break;
+ case 0x92:
+#if HJB
+ sprintf(buffer, "ld r0,psu");
+#else
+ sprintf(buffer, "lpsu");
+#endif
+ break;
+ case 0x93:
+#if HJB
+ sprintf(buffer, "ld r0,psl");
+#else
+ sprintf(buffer, "lpsl");
+#endif
+ break;
+ case 0x94: case 0x95: case 0x96: case 0x97:
+#if HJB
+ sprintf(buffer, "daa r%d", rv);
+#else
+ sprintf(buffer, "dar,%d", rv);
+#endif
+ break;
+ case 0x98: case 0x99: case 0x9a:
+#if HJB
+ sprintf(buffer, "jr n%c,%s", cc[rv], REL(pc));
+#else
+ sprintf(buffer, "bcfr,%c %s", cc[rv], REL(pc));
+#endif
+ pc+=1;
+ break;
+ case 0x9b:
+#if HJB
+ sprintf(buffer, "jr0 %s", REL0(pc));
+#else
+ sprintf(buffer, "zbrr %s", REL0(pc));
+#endif
+ pc+=1;
+ break;
+ case 0x9c: case 0x9d: case 0x9e:
+#if HJB
+ sprintf(buffer, "jp n%c,%s", cc[rv], ADR(pc));
+#else
+ sprintf(buffer, "bcfa,%c %s", cc[rv], ADR(pc));
+#endif
+ pc+=2;
+ break;
+ case 0x9f:
+#if HJB
+ sprintf(buffer, "jp %s+r3", ADR(pc));
+#else
+ sprintf(buffer, "bxa %s", ADR(pc));
+#endif
+ pc+=2;
+ break;
+ case 0xa0: case 0xa1: case 0xa2: case 0xa3:
+#if HJB
+ sprintf(buffer, "sub r0,r%d", rv);
+#else
+ sprintf(buffer, "subz,%d", rv);
+#endif
+ break;
+ case 0xa4: case 0xa5: case 0xa6: case 0xa7:
+#if HJB
+ sprintf(buffer, "sub r%d,%s", rv, IMM(pc));
+#else
+ sprintf(buffer, "subi,%d %s", rv, IMM(pc));
+#endif
+ pc+=1;
+ break;
+ case 0xa8: case 0xa9: case 0xaa: case 0xab:
+#if HJB
+ sprintf(buffer, "sub r%d,(%s)", rv, REL(pc));
+#else
+ sprintf(buffer, "subr,%d %s", rv, REL(pc));
+#endif
+ pc+=1;
+ break;
+ case 0xac: case 0xad: case 0xae: case 0xaf:
+#if HJB
+ sprintf(buffer, "sub %s", ABS(1,rv,pc));
+#else
+ sprintf(buffer, "suba,%s", ABS(1,rv,pc));
+#endif
+ pc+=2;
+ break;
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3:
+#if HJB
+ sprintf(buffer, "out (ctrl),r%d", rv);
+#else
+ sprintf(buffer, "wrtc,%d", rv);
+#endif
+ break;
+ case 0xb4:
+#if HJB
+ sprintf(buffer, "bit psu,%s", IMM_PSU(pc));
+#else
+ sprintf(buffer, "tpsu %s", IMM_PSU(pc));
+#endif
+ pc+=1;
+ break;
+ case 0xb5:
+#if HJB
+ sprintf(buffer, "bit psl,%s", IMM_PSL(pc));
+#else
+ sprintf(buffer, "tpsl %s", IMM_PSL(pc));
+#endif
+ pc+=1;
+ break;
+ case 0xb6: case 0xb7:
+#if HJB
+ sprintf(buffer, "**** $%02X",op);
+#else
+ sprintf(buffer, "**** $%02X",op);
+#endif
+ break;
+ case 0xb8: case 0xb9: case 0xba:
+#if HJB
+ sprintf(buffer, "calr n%c,%s", cc[rv], REL(pc));
+#else
+ sprintf(buffer, "bsfr,%c %s", cc[rv], REL(pc));
+#endif
+ pc+=1;
+ flags = DASMFLAG_STEP_OVER;
+ break;
+ case 0xbb:
+#if HJB
+ sprintf(buffer, "cal0 %s", REL0(pc));
+#else
+ sprintf(buffer, "zbsr %s", REL0(pc));
+#endif
+ pc+=1;
+ flags = DASMFLAG_STEP_OVER;
+ break;
+ case 0xbc: case 0xbd: case 0xbe:
+#if HJB
+ sprintf(buffer, "call n%c,%s", cc[rv], ADR(pc));
+#else
+ sprintf(buffer, "bsfa,%c %s", cc[rv], ADR(pc));
+#endif
+ pc+=2;
+ flags = DASMFLAG_STEP_OVER;
+ break;
+ case 0xbf:
+#if HJB
+ sprintf(buffer, "call %s+r3", ADR(pc));
+#else
+ sprintf(buffer, "bsxa %s", ADR(pc));
+#endif
+ pc+=2;
+ flags = DASMFLAG_STEP_OVER;
+ break;
+ case 0xc0:
+ sprintf(buffer, "nop");
+ break;
+ case 0xc1: case 0xc2: case 0xc3:
+#if HJB
+ sprintf(buffer, "ld r%d,r0", rv);
+#else
+ sprintf(buffer, "strz,%d", rv);
+#endif
+ break;
+ case 0xc4: case 0xc5: case 0xc6: case 0xc7:
+#if HJB
+ sprintf(buffer, "**** $%02X",op);
+#else
+ sprintf(buffer, "**** $%02X",op);
+#endif
+ break;
+ case 0xc8: case 0xc9: case 0xca: case 0xcb:
+#if HJB
+ sprintf(buffer, "ld (%s),r%d", REL(pc), rv);
+#else
+ sprintf(buffer, "strr,%d %s", rv, REL(pc));
+#endif
+ pc+=1;
+ break;
+ case 0xcc: case 0xcd: case 0xce: case 0xcf:
+#if HJB
+ sprintf(buffer, "ld %s", ABS(0,rv,pc));
+#else
+ sprintf(buffer, "stra,%s", ABS(1,rv,pc));
+#endif
+ pc+=2;
+ break;
+ case 0xd0: case 0xd1: case 0xd2: case 0xd3:
+#if HJB
+ sprintf(buffer, "rol r%d", rv);
+#else
+ sprintf(buffer, "rrl,%d", rv);
+#endif
+ break;
+ case 0xd4: case 0xd5: case 0xd6: case 0xd7:
+#if HJB
+ sprintf(buffer, "out (%s),r%d", IMM(pc), rv);
+#else
+ sprintf(buffer, "wrte,%d %s", rv, IMM(pc));
+#endif
+ pc+=1;
+ break;
+ case 0xd8: case 0xd9: case 0xda: case 0xdb:
+#if HJB
+ sprintf(buffer, "ijnz r%d,%s", rv, REL(pc));
+#else
+ sprintf(buffer, "birr,%d %s", rv, REL(pc));
+#endif
+ pc+=1;
+ flags = DASMFLAG_STEP_OVER;
+ break;
+ case 0xdc: case 0xdd: case 0xde: case 0xdf:
+#if HJB
+ sprintf(buffer, "ijnz r%d,%s", rv, ADR(pc));
+#else
+ sprintf(buffer, "bira,%d %s", rv, ADR(pc));
+#endif
+ pc+=2;
+ flags = DASMFLAG_STEP_OVER;
+ break;
+ case 0xe0: case 0xe1: case 0xe2: case 0xe3:
+#if HJB
+ sprintf(buffer, "cp r0,%d", rv);
+#else
+ sprintf(buffer, "comz,%d", rv);
+#endif
+ break;
+ case 0xe4: case 0xe5: case 0xe6: case 0xe7:
+#if HJB
+ sprintf(buffer, "cp r%d,%s", rv, IMM(pc));
+#else
+ sprintf(buffer, "comi,%d %s", rv, IMM(pc));
+#endif
+ pc+=1;
+ break;
+ case 0xe8: case 0xe9: case 0xea: case 0xeb:
+#if HJB
+ sprintf(buffer, "cp r%d,(%s)", rv, REL(pc));
+#else
+ sprintf(buffer, "comr,%d %s", rv, REL(pc));
+#endif
+ pc+=1;
+ break;
+ case 0xec: case 0xed: case 0xee: case 0xef:
+#if HJB
+ sprintf(buffer, "cp %s", ABS(1,rv,pc));
+#else
+ sprintf(buffer, "coma,%s", ABS(1,rv,pc));
+#endif
+ pc+=2;
+ break;
+ case 0xf0: case 0xf1: case 0xf2: case 0xf3:
+#if HJB
+ sprintf(buffer, "out (data),r%d", rv);
+#else
+ sprintf(buffer, "wrtd,%d", rv);
+#endif
+ break;
+ case 0xf4: case 0xf5: case 0xf6: case 0xf7:
+#if HJB
+ sprintf(buffer, "test r%d,%s", rv, IMM(pc));
+#else
+ sprintf(buffer, "tmi,%d %s", rv, IMM(pc));
+#endif
+ pc+=1;
+ break;
+ case 0xf8: case 0xf9: case 0xfa: case 0xfb:
+#if HJB
+ sprintf(buffer, "djnz r%d,%s", rv, REL(pc));
+#else
+ sprintf(buffer, "bdrr,%d %s", rv, REL(pc));
+#endif
+ pc+=1;
+ flags = DASMFLAG_STEP_OVER;
+ break;
+ case 0xfc: case 0xfd: case 0xfe: case 0xff:
+#if HJB
+ sprintf(buffer, "djnz r%d,%s", rv, ADR(pc));
+#else
+ sprintf(buffer, "bdra,%d %s", rv, ADR(pc));
+#endif
+ pc+=2;
+ flags = DASMFLAG_STEP_OVER;
+ break;
+ }
+ return (pc - PC) | flags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/s2650/s2650.c b/trunk/src/emu/cpu/s2650/s2650.c
new file mode 100644
index 00000000000..20ab35740ea
--- /dev/null
+++ b/trunk/src/emu/cpu/s2650/s2650.c
@@ -0,0 +1,1647 @@
+/*************************************************************************
+ *
+ * Portable Signetics 2650 cpu emulation
+ *
+ * Written by Juergen Buchmueller for use with MAME
+ *
+ * Version 1.2
+ * - changed to clock cycle counts from machine cycles
+ * - replaced cycle table with inline code (M_RET conditional case)
+ * - removed wrong distinct add/sub CC and OVF handling
+ * - cosmetics, readability
+ *
+ *************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "s2650.h"
+#include "s2650cpu.h"
+
+/* define this to have some interrupt information logged */
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+/* define this to expand all EA calculations inline */
+#define INLINE_EA 1
+
+typedef struct _s2650_regs s2650_regs;
+struct _s2650_regs {
+ UINT16 ppc; /* previous program counter (page + iar) */
+ UINT16 page; /* 8K page select register (A14..A13) */
+ UINT16 iar; /* instruction address register (A12..A0) */
+ UINT16 ea; /* effective address (A14..A0) */
+ UINT8 psl; /* processor status lower */
+ UINT8 psu; /* processor status upper */
+ UINT8 r; /* absolute addressing dst/src register */
+ UINT8 reg[7]; /* 7 general purpose registers */
+ UINT8 halt; /* 1 if cpu is halted */
+ UINT8 ir; /* instruction register */
+ UINT16 ras[8]; /* 8 return address stack entries */
+ UINT8 irq_state;
+
+ int icount;
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *io;
+};
+
+INLINE s2650_regs *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == S2650);
+ return (s2650_regs *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/* condition code changes for a byte */
+static const UINT8 ccc[0x200] = {
+ 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x04,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
+ 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84
+};
+
+/***************************************************************
+ * handy table to build PC relative offsets
+ * from HR (holding register)
+ ***************************************************************/
+static const int S2650_relative[0x100] =
+{
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ -64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,
+ -48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,
+ -32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,
+ -16,-15,-14,-13,-12,-11,-10, -9, -8, -7, -6, -5, -4, -3, -2, -1,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ -64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,
+ -48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,
+ -32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,
+ -16,-15,-14,-13,-12,-11,-10, -9, -8, -7, -6, -5, -4, -3, -2, -1,
+};
+
+
+/***************************************************************
+ * RDMEM
+ * read memory byte from addr
+ ***************************************************************/
+#define RDMEM(addr) s2650c->program->read_byte(addr)
+
+static void s2650_set_sense(s2650_regs *s2650c, int state);
+
+INLINE void set_psu(s2650_regs *s2650c, UINT8 new_val)
+{
+ UINT8 old = s2650c->psu;
+
+ s2650c->psu = new_val;
+ if ((new_val ^ old) & FO)
+ s2650c->io->write_byte(S2650_FO_PORT, (new_val & FO) ? 1 : 0);
+}
+
+INLINE UINT8 get_sp(s2650_regs *s2650c)
+{
+ return (s2650c->psu & SP);
+}
+
+INLINE void set_sp(s2650_regs *s2650c, UINT8 new_sp)
+{
+ s2650c->psu = (s2650c->psu & ~SP) | (new_sp & SP);
+}
+
+INLINE int check_irq_line(s2650_regs *s2650c)
+{
+ int cycles = 0;
+
+ if (s2650c->irq_state != CLEAR_LINE)
+ {
+ if( (s2650c->psu & II) == 0 )
+ {
+ int vector;
+ if (s2650c->halt)
+ {
+ s2650c->halt = 0;
+ s2650c->iar = (s2650c->iar + 1) & PMSK;
+ }
+ vector = (*s2650c->irq_callback)(s2650c->device, 0) & 0xff;
+ /* build effective address within first 8K page */
+ s2650c->ea = S2650_relative[vector] & PMSK;
+ if (vector & 0x80) /* indirect bit set ? */
+ {
+ int addr = s2650c->ea;
+ cycles += 6;
+ /* build indirect 32K address */
+ s2650c->ea = RDMEM(addr) << 8;
+ if (!(++addr & PMSK)) addr -= PLEN;
+ s2650c->ea = (s2650c->ea + RDMEM(addr)) & AMSK;
+ }
+ LOG(("S2650 interrupt to $%04x\n", s2650c->ea));
+ set_sp(s2650c, get_sp(s2650c) + 1);
+ set_psu(s2650c, s2650c->psu | II);
+ s2650c->ras[get_sp(s2650c)] = s2650c->page + s2650c->iar;
+ s2650c->page = s2650c->ea & PAGE;
+ s2650c->iar = s2650c->ea & PMSK;
+ }
+ }
+ return cycles;
+}
+
+/***************************************************************
+ *
+ * set condition code (zero,plus,minus) from result
+ ***************************************************************/
+#define SET_CC(result) \
+ s2650c->psl = (s2650c->psl & ~CC) | ccc[result]
+
+/***************************************************************
+ *
+ * set condition code (zero,plus,minus) and overflow
+ ***************************************************************/
+#define SET_CC_OVF(result,value) \
+ s2650c->psl = (s2650c->psl & ~(OVF+CC)) | \
+ ccc[result + (((value) & 0x80) << 1)]
+
+#define SET_CC_OVF_ADD(result,value1,value2) SET_CC_OVF(result,~((value1) ^ (value2)) & ((value1) ^ (result)))
+#define SET_CC_OVF_SUB(result,value1,value2) SET_CC_OVF(result,~((value1) ^ (value2)) & ((value1) ^ (result)))
+
+/***************************************************************
+ * ROP
+ * read next opcode
+ ***************************************************************/
+INLINE UINT8 ROP(s2650_regs *s2650c)
+{
+ UINT8 result = s2650c->direct->read_decrypted_byte(s2650c->page + s2650c->iar);
+ s2650c->iar = (s2650c->iar + 1) & PMSK;
+ return result;
+}
+
+/***************************************************************
+ * ARG
+ * read next opcode argument
+ ***************************************************************/
+INLINE UINT8 ARG(s2650_regs *s2650c)
+{
+ UINT8 result = s2650c->direct->read_raw_byte(s2650c->page + s2650c->iar);
+ s2650c->iar = (s2650c->iar + 1) & PMSK;
+ return result;
+}
+
+/***************************************************************
+ * _REL_EA
+ * build effective address with relative addressing
+ ***************************************************************/
+#define _REL_EA(page) \
+{ \
+ UINT8 hr = ARG(s2650c); /* get 'holding register' */ \
+ /* build effective address within current 8K page */ \
+ s2650c->ea = page + ((s2650c->iar + S2650_relative[hr]) & PMSK); \
+ if (hr & 0x80) { /* indirect bit set ? */ \
+ int addr = s2650c->ea; \
+ s2650c->icount -= 6; \
+ /* build indirect 32K address */ \
+ s2650c->ea = RDMEM(addr) << 8; \
+ if( (++addr & PMSK) == 0 ) addr -= PLEN; /* page wrap */\
+ s2650c->ea = (s2650c->ea + RDMEM(addr)) & AMSK; \
+ } \
+}
+
+/***************************************************************
+ * _REL_ZERO
+ * build effective address with zero relative addressing
+ ***************************************************************/
+#define _REL_ZERO(page) \
+{ \
+ UINT8 hr = ARG(s2650c); /* get 'holding register' */ \
+ /* build effective address from 0 */ \
+ s2650c->ea = (S2650_relative[hr] & PMSK); \
+ if (hr & 0x80) { /* indirect bit set ? */ \
+ int addr = s2650c->ea; \
+ s2650c->icount -= 6; \
+ /* build indirect 32K address */ \
+ s2650c->ea = RDMEM(addr) << 8; \
+ if( (++addr & PMSK) == 0 ) addr -= PLEN; /* page wrap */\
+ s2650c->ea = (s2650c->ea + RDMEM(addr)) & AMSK; \
+ } \
+}
+
+/***************************************************************
+ * _ABS_EA
+ * build effective address with absolute addressing
+ ***************************************************************/
+#define _ABS_EA() \
+{ \
+ UINT8 hr, dr; \
+ hr = ARG(s2650c); /* get 'holding register' */ \
+ dr = ARG(s2650c); /* get 'data bus register' */ \
+ /* build effective address within current 8K page */ \
+ s2650c->ea = s2650c->page + (((hr << 8) + dr) & PMSK); \
+ /* indirect addressing ? */ \
+ if (hr & 0x80) { \
+ int addr = s2650c->ea; \
+ s2650c->icount -= 6; \
+ /* build indirect 32K address */ \
+ /* build indirect 32K address */ \
+ s2650c->ea = RDMEM(addr) << 8; \
+ if( (++addr & PMSK) == 0 ) addr -= PLEN; /* page wrap */\
+ s2650c->ea = (s2650c->ea + RDMEM(addr)) & AMSK; \
+ } \
+ /* check indexed addressing modes */ \
+ switch (hr & 0x60) { \
+ case 0x00: /* not indexed */ \
+ break; \
+ case 0x20: /* auto increment indexed */ \
+ s2650c->reg[s2650c->r] += 1; \
+ s2650c->ea = (s2650c->ea & PAGE)+((s2650c->ea+s2650c->reg[s2650c->r]) & PMSK); \
+ s2650c->r = 0; /* absolute addressing reg is R0 */ \
+ break; \
+ case 0x40: /* auto decrement indexed */ \
+ s2650c->reg[s2650c->r] -= 1; \
+ s2650c->ea = (s2650c->ea & PAGE)+((s2650c->ea+s2650c->reg[s2650c->r]) & PMSK); \
+ s2650c->r = 0; /* absolute addressing reg is R0 */ \
+ break; \
+ case 0x60: /* indexed */ \
+ s2650c->ea = (s2650c->ea & PAGE)+((s2650c->ea+s2650c->reg[s2650c->r]) & PMSK); \
+ s2650c->r = 0; /* absolute addressing reg is R0 */ \
+ break; \
+ } \
+}
+
+/***************************************************************
+ * _BRA_EA
+ * build effective address with absolute addressing (branch)
+ ***************************************************************/
+#define _BRA_EA() \
+{ \
+ UINT8 hr, dr; \
+ hr = ARG(s2650c); /* get 'holding register' */ \
+ dr = ARG(s2650c); /* get 'data bus register' */ \
+ /* build address in 32K address space */ \
+ s2650c->ea = ((hr << 8) + dr) & AMSK; \
+ /* indirect addressing ? */ \
+ if (hr & 0x80) { \
+ int addr = s2650c->ea; \
+ s2650c->icount -= 6; \
+ /* build indirect 32K address */ \
+ s2650c->ea = RDMEM(addr) << 8; \
+ if( (++addr & PMSK) == 0 ) addr -= PLEN; /* page wrap */\
+ s2650c->ea = (s2650c->ea + RDMEM(addr)) & AMSK; \
+ } \
+}
+
+/***************************************************************
+ * SWAP_REGS
+ * Swap registers r1-r3 with r4-r6 (the second set)
+ * This is done everytime the RS bit in PSL changes
+ ***************************************************************/
+#define SWAP_REGS \
+{ \
+ UINT8 tmp; \
+ tmp = s2650c->reg[1]; \
+ s2650c->reg[1] = s2650c->reg[4]; \
+ s2650c->reg[4] = tmp; \
+ tmp = s2650c->reg[2]; \
+ s2650c->reg[2] = s2650c->reg[5]; \
+ s2650c->reg[5] = tmp; \
+ tmp = s2650c->reg[3]; \
+ s2650c->reg[3] = s2650c->reg[6]; \
+ s2650c->reg[6] = tmp; \
+}
+
+/***************************************************************
+ * M_BRR
+ * Branch relative if cond is true
+ ***************************************************************/
+#define M_BRR(cond) \
+{ \
+ if (cond) \
+ { \
+ REL_EA( s2650c->page ); \
+ s2650c->page = s2650c->ea & PAGE; \
+ s2650c->iar = s2650c->ea & PMSK; \
+ } else s2650c->iar = (s2650c->iar + 1) & PMSK; \
+}
+
+/***************************************************************
+ * M_ZBRR
+ * Branch relative to page zero
+ ***************************************************************/
+#define M_ZBRR() \
+{ \
+ REL_ZERO( 0 ); \
+ s2650c->page = s2650c->ea & PAGE; \
+ s2650c->iar = s2650c->ea & PMSK; \
+}
+
+/***************************************************************
+ * M_BRA
+ * Branch absolute if cond is true
+ ***************************************************************/
+#define M_BRA(cond) \
+{ \
+ if( cond ) \
+ { \
+ BRA_EA(); \
+ s2650c->page = s2650c->ea & PAGE; \
+ s2650c->iar = s2650c->ea & PMSK; \
+ } else s2650c->iar = (s2650c->iar + 2) & PMSK; \
+}
+
+/***************************************************************
+ * M_BXA
+ * Branch indexed absolute (EA + R3)
+ ***************************************************************/
+#define M_BXA() \
+{ \
+ BRA_EA(); \
+ s2650c->ea = (s2650c->ea + s2650c->reg[3]) & AMSK; \
+ s2650c->page = s2650c->ea & PAGE; \
+ s2650c->iar = s2650c->ea & PMSK; \
+}
+
+/***************************************************************
+ * M_BSR
+ * Branch to subroutine relative if cond is true
+ ***************************************************************/
+#define M_BSR(cond) \
+{ \
+ if( cond ) \
+ { \
+ REL_EA(s2650c->page); \
+ set_sp(s2650c, get_sp(s2650c) + 1); \
+ s2650c->ras[get_sp(s2650c)] = s2650c->page + s2650c->iar; \
+ s2650c->page = s2650c->ea & PAGE; \
+ s2650c->iar = s2650c->ea & PMSK; \
+ } else s2650c->iar = (s2650c->iar + 1) & PMSK; \
+}
+
+/***************************************************************
+ * M_ZBSR
+ * Branch to subroutine relative to page zero
+ ***************************************************************/
+#define M_ZBSR() \
+{ \
+ REL_ZERO(0); \
+ set_sp(s2650c, get_sp(s2650c) + 1); \
+ s2650c->ras[get_sp(s2650c)] = s2650c->page + s2650c->iar; \
+ s2650c->page = s2650c->ea & PAGE; \
+ s2650c->iar = s2650c->ea & PMSK; \
+}
+
+/***************************************************************
+ * M_BSA
+ * Branch to subroutine absolute
+ ***************************************************************/
+#define M_BSA(cond) \
+{ \
+ if( cond ) \
+ { \
+ BRA_EA(); \
+ set_sp(s2650c, get_sp(s2650c) + 1); \
+ s2650c->ras[get_sp(s2650c)] = s2650c->page + s2650c->iar; \
+ s2650c->page = s2650c->ea & PAGE; \
+ s2650c->iar = s2650c->ea & PMSK; \
+ } else s2650c->iar = (s2650c->iar + 2) & PMSK; \
+}
+
+/***************************************************************
+ * M_BSXA
+ * Branch to subroutine indexed absolute (EA + R3)
+ ***************************************************************/
+#define M_BSXA() \
+{ \
+ BRA_EA(); \
+ s2650c->ea = (s2650c->ea + s2650c->reg[3]) & AMSK; \
+ set_sp(s2650c, get_sp(s2650c) + 1); \
+ s2650c->ras[get_sp(s2650c)] = s2650c->page + s2650c->iar; \
+ s2650c->page = s2650c->ea & PAGE; \
+ s2650c->iar = s2650c->ea & PMSK; \
+}
+
+/***************************************************************
+ * M_RET
+ * Return from subroutine if cond is true
+ ***************************************************************/
+#define M_RET(cond) \
+{ \
+ if( cond ) \
+ { \
+ s2650c->icount -= 6; \
+ s2650c->ea = s2650c->ras[get_sp(s2650c)]; \
+ set_sp(s2650c, get_sp(s2650c) - 1); \
+ s2650c->page = s2650c->ea & PAGE; \
+ s2650c->iar = s2650c->ea & PMSK; \
+ } \
+}
+
+/***************************************************************
+ * M_RETE
+ * Return from subroutine if cond is true
+ * and enable interrupts; afterwards check IRQ line
+ * state and eventually take next interrupt
+ ***************************************************************/
+#define M_RETE(cond) \
+{ \
+ if( cond ) \
+ { \
+ s2650c->ea = s2650c->ras[get_sp(s2650c)]; \
+ set_sp(s2650c, get_sp(s2650c) - 1); \
+ s2650c->page = s2650c->ea & PAGE; \
+ s2650c->iar = s2650c->ea & PMSK; \
+ set_psu(s2650c, s2650c->psu & ~II); \
+ s2650c->icount -= check_irq_line(s2650c); \
+ } \
+}
+
+/***************************************************************
+ * M_LOD
+ * Load destination with source register
+ ***************************************************************/
+#define M_LOD(dest,source) \
+{ \
+ dest = source; \
+ SET_CC(dest); \
+}
+
+/***************************************************************
+ * M_STR
+ * Store source register to memory addr (CC unchanged)
+ ***************************************************************/
+#define M_STR(address,source) \
+ s2650c->program->write_byte(address, source)
+
+/***************************************************************
+ * M_AND
+ * Logical and destination with source
+ ***************************************************************/
+#define M_AND(dest,source) \
+{ \
+ dest &= source; \
+ SET_CC(dest); \
+}
+
+/***************************************************************
+ * M_IOR
+ * Logical inclusive or destination with source
+ ***************************************************************/
+#define M_IOR(dest,source) \
+{ \
+ dest |= source; \
+ SET_CC(dest); \
+}
+
+/***************************************************************
+ * M_EOR
+ * Logical exclusive or destination with source
+ ***************************************************************/
+#define M_EOR(dest,source) \
+{ \
+ dest ^= source; \
+ SET_CC(dest); \
+}
+
+/***************************************************************
+ * M_ADD
+ * Add source to destination
+ * Add with carry if WC flag of PSL is set
+ ***************************************************************/
+#define M_ADD(dest,_source) \
+{ \
+ UINT8 source = _source; \
+ UINT8 before = dest; \
+ /* add source; carry only if WC is set */ \
+ UINT16 res = dest + source + ((s2650c->psl >> 3) & s2650c->psl & C); \
+ s2650c->psl &= ~(C | OVF | IDC); \
+ if(res & 0x100) s2650c->psl |= C; \
+ dest = res & 0xff; \
+ if( (dest & 15) < (before & 15) ) s2650c->psl |= IDC; \
+ SET_CC_OVF_ADD(dest,before,source); \
+}
+
+/***************************************************************
+ * M_SUB
+ * Subtract source from destination
+ * Subtract with borrow if WC flag of PSL is set
+ ***************************************************************/
+#define M_SUB(dest,_source) \
+{ \
+ UINT8 source = _source; \
+ UINT8 before = dest; \
+ /* subtract source; borrow only if WC is set */ \
+ UINT16 res = dest - source - ((s2650c->psl >> 3) & (s2650c->psl ^ C) & C); \
+ s2650c->psl &= ~(C | OVF | IDC); \
+ if((res & 0x100)==0) s2650c->psl |= C; \
+ dest = res & 0xff; \
+ if( (dest & 15) <= (before & 15) ) s2650c->psl |= IDC; \
+ SET_CC_OVF_SUB(dest,before,source); \
+}
+
+/***************************************************************
+ * M_COM
+ * Compare register against value. If COM of PSL is set,
+ * use unsigned, else signed comparison
+ ***************************************************************/
+#define M_COM(reg,val) \
+{ \
+ int d; \
+ s2650c->psl &= ~CC; \
+ if (s2650c->psl & COM) d = (UINT8)reg - (UINT8)val; \
+ else d = (INT8)reg - (INT8)val; \
+ if( d < 0 ) s2650c->psl |= 0x80; \
+ else \
+ if( d > 0 ) s2650c->psl |= 0x40; \
+}
+
+/***************************************************************
+ * M_DAR
+ * Decimal adjust register
+ ***************************************************************/
+#define M_DAR(dest) \
+{ \
+ if ((s2650c->psl & C) == 0) dest += 0xA0; \
+ if ((s2650c->psl & IDC) == 0) dest = (dest & 0xF0) | ((dest + 0x0A) & 0x0F);\
+}
+
+/***************************************************************
+ * M_RRL
+ * Rotate register left; If WC of PSL is set, rotate
+ * through carry, else rotate circular
+ ***************************************************************/
+#define M_RRL(dest) \
+{ \
+ UINT8 before = dest; \
+ if( s2650c->psl & WC ) \
+ { \
+ UINT8 c = s2650c->psl & C; \
+ s2650c->psl &= ~(C + IDC); \
+ dest = (before << 1) | c; \
+ s2650c->psl |= (before >> 7) + (dest & IDC); \
+ } \
+ else \
+ { \
+ dest = (before << 1) | (before >> 7); \
+ } \
+ SET_CC(dest); \
+ s2650c->psl = (s2650c->psl & ~OVF) | (((dest ^ before) >> 5) & OVF); \
+}
+
+/***************************************************************
+ * M_RRR
+ * Rotate register right; If WC of PSL is set, rotate
+ * through carry, else rotate circular
+ ***************************************************************/
+#define M_RRR(dest) \
+{ \
+ UINT8 before = dest; \
+ if (s2650c->psl & WC) \
+ { \
+ UINT8 c = s2650c->psl & C; \
+ s2650c->psl &= ~(C + IDC); \
+ dest = (before >> 1) | (c << 7); \
+ s2650c->psl |= (before & C) + (dest & IDC); \
+ } else dest = (before >> 1) | (before << 7); \
+ SET_CC(dest); \
+ s2650c->psl = (s2650c->psl & ~OVF) | (((dest ^ before) >> 5) & OVF); \
+}
+
+// bxd() not necessary
+
+/***************************************************************
+ * M_SPSU
+ * Store processor status upper (PSU) to register R0
+ * Checks for External Sense IO port
+ ***************************************************************/
+#define M_SPSU() \
+{ \
+ R0 = ((s2650c->psu & ~PSU34) | (s2650c->io->read_byte(S2650_SENSE_PORT) ? SI : 0)); \
+ SET_CC(R0); \
+}
+
+/***************************************************************
+ * M_SPSL
+ * Store processor status lower (PSL) to register R0
+ ***************************************************************/
+#define M_SPSL() \
+{ \
+ R0 = s2650c->psl; \
+ SET_CC(R0); \
+}
+
+/***************************************************************
+ * M_CPSU
+ * Clear processor status upper (PSU), selective
+ ***************************************************************/
+#define M_CPSU() \
+{ \
+ UINT8 cpsu = ARG(s2650c); \
+ set_psu(s2650c, s2650c->psu & ~cpsu); \
+ s2650c->icount -= check_irq_line(s2650c); \
+}
+
+/***************************************************************
+ * M_CPSL
+ * Clear processor status lower (PSL), selective
+ ***************************************************************/
+#define M_CPSL() \
+{ \
+ UINT8 cpsl = ARG(s2650c); \
+ /* select other register set now ? */ \
+ if( (cpsl & RS) && (s2650c->psl & RS) ) \
+ SWAP_REGS; \
+ s2650c->psl = s2650c->psl & ~cpsl; \
+}
+
+/***************************************************************
+ * M_PPSU
+ * Preset processor status upper (PSU), selective
+ * Unused bits 3 and 4 can't be set
+ ***************************************************************/
+#define M_PPSU() \
+{ \
+ UINT8 ppsu = (ARG(s2650c) & ~PSU34) & ~SI; \
+ set_psu(s2650c, s2650c->psu | ppsu); \
+}
+
+/***************************************************************
+ * M_PPSL
+ * Preset processor status lower (PSL), selective
+ ***************************************************************/
+#define M_PPSL() \
+{ \
+ UINT8 ppsl = ARG(s2650c); \
+ /* select 2nd register set now ? */ \
+ if ((ppsl & RS) && !(s2650c->psl & RS)) \
+ SWAP_REGS; \
+ s2650c->psl = s2650c->psl | ppsl; \
+}
+
+/***************************************************************
+ * M_TPSU
+ * Test processor status upper (PSU)
+ ***************************************************************/
+#define M_TPSU() \
+{ \
+ UINT8 tpsu = ARG(s2650c); \
+ UINT8 rpsu = (s2650c->psu | (s2650c->io->read_byte(S2650_SENSE_PORT) ? SI : 0)); \
+ s2650c->psl &= ~CC; \
+ if( (rpsu & tpsu) != tpsu ) \
+ s2650c->psl |= 0x80; \
+}
+
+/***************************************************************
+ * M_TPSL
+ * Test processor status lower (PSL)
+ ***************************************************************/
+#define M_TPSL() \
+{ \
+ UINT8 tpsl = ARG(s2650c); \
+ if( (s2650c->psl & tpsl) != tpsl ) \
+ s2650c->psl = (s2650c->psl & ~CC) | 0x80; \
+ else \
+ s2650c->psl &= ~CC; \
+}
+
+/***************************************************************
+ * M_TMI
+ * Test under mask immediate
+ ***************************************************************/
+#define M_TMI(value) \
+{ \
+ UINT8 tmi = ARG(s2650c); \
+ s2650c->psl &= ~CC; \
+ if( (value & tmi) != tmi ) \
+ s2650c->psl |= 0x80; \
+}
+
+#if INLINE_EA
+#define REL_EA(page) _REL_EA(page)
+#define REL_ZERO(page) _REL_ZERO(page)
+#define ABS_EA() _ABS_EA()
+#define BRA_EA() _BRA_EA()
+#else
+static void REL_EA(unsigned short page) _REL_EA(page)
+static void REL_ZERO(unsigned short page) _REL_ZERO(page)
+static void ABS_EA(void) _ABS_EA()
+static void BRA_EA(void) _BRA_EA()
+#endif
+
+static CPU_INIT( s2650 )
+{
+ s2650_regs *s2650c = get_safe_token(device);
+
+ s2650c->irq_callback = irqcallback;
+ s2650c->device = device;
+ s2650c->program = device->space(AS_PROGRAM);
+ s2650c->direct = &s2650c->program->direct();
+ s2650c->io = device->space(AS_IO);
+
+ device->save_item(NAME(s2650c->ppc));
+ device->save_item(NAME(s2650c->page));
+ device->save_item(NAME(s2650c->iar));
+ device->save_item(NAME(s2650c->ea));
+ device->save_item(NAME(s2650c->psl));
+ device->save_item(NAME(s2650c->psu));
+ device->save_item(NAME(s2650c->r));
+ device->save_item(NAME(s2650c->reg));
+ device->save_item(NAME(s2650c->halt));
+ device->save_item(NAME(s2650c->ir));
+ device->save_item(NAME(s2650c->ras));
+ device->save_item(NAME(s2650c->irq_state));
+}
+
+static CPU_RESET( s2650 )
+{
+ s2650_regs *s2650c = get_safe_token(device);
+
+ s2650c->ppc = 0;
+ s2650c->page = 0,
+ s2650c->iar = 0;
+ s2650c->ea = 0;
+ s2650c->r = 0;
+ s2650c->halt = 0;
+ s2650c->ir = 0;
+ memset(s2650c->reg, 0, sizeof(s2650c->reg));
+ memset(s2650c->ras, 0, sizeof(s2650c->ras));
+
+ s2650c->device = device;
+ s2650c->program = device->space(AS_PROGRAM);
+ s2650c->direct = &s2650c->program->direct();
+ s2650c->io = device->space(AS_IO);
+ s2650c->psl = COM | WC;
+ /* force write */
+ s2650c->psu = 0xff;
+ set_psu(s2650c, 0);
+}
+
+static CPU_EXIT( s2650 )
+{
+ /* nothing to do */
+}
+
+static void set_irq_line(s2650_regs *s2650c, int irqline, int state)
+{
+ if (irqline == 1)
+ {
+ if (state == CLEAR_LINE)
+ s2650_set_sense(s2650c, 0);
+ else
+ s2650_set_sense(s2650c, 1);
+ return;
+ }
+
+ s2650c->irq_state = state;
+}
+
+static void s2650_set_flag(s2650_regs *s2650c, int state)
+{
+ if (state)
+ set_psu(s2650c, s2650c->psu | FO);
+ else
+ set_psu(s2650c, s2650c->psu & ~FO);
+}
+
+static int s2650_get_flag(s2650_regs *s2650c)
+{
+ return (s2650c->psu & FO) ? 1 : 0;
+}
+
+static void s2650_set_sense(s2650_regs *s2650c, int state)
+{
+ if (state)
+ set_psu(s2650c, s2650c->psu | SI);
+ else
+ set_psu(s2650c, s2650c->psu & ~SI);
+}
+
+static int s2650_get_sense(s2650_regs *s2650c)
+{
+ /* OR'd with Input to allow for external connections */
+
+ return (((s2650c->psu & SI) ? 1 : 0) | ((s2650c->io->read_byte(S2650_SENSE_PORT) & SI) ? 1 : 0));
+}
+
+static CPU_EXECUTE( s2650 )
+{
+ s2650_regs *s2650c = get_safe_token(device);
+
+ /* check for external irqs */
+ int cycles = check_irq_line(s2650c);
+ s2650c->icount -= cycles;
+
+ do
+ {
+ s2650c->ppc = s2650c->page + s2650c->iar;
+
+ debugger_instruction_hook(device, s2650c->page + s2650c->iar);
+
+ s2650c->ir = ROP(s2650c);
+ s2650c->r = s2650c->ir & 3; /* register / value */
+ switch (s2650c->ir) {
+ case 0x00: /* LODZ,0 */
+ case 0x01: /* LODZ,1 */
+ case 0x02: /* LODZ,2 */
+ case 0x03: /* LODZ,3 */
+ s2650c->icount -= 6;
+ M_LOD( R0, s2650c->reg[s2650c->r] );
+ break;
+
+ case 0x04: /* LODI,0 v */
+ case 0x05: /* LODI,1 v */
+ case 0x06: /* LODI,2 v */
+ case 0x07: /* LODI,3 v */
+ s2650c->icount -= 6;
+ M_LOD( s2650c->reg[s2650c->r], ARG(s2650c) );
+ break;
+
+ case 0x08: /* LODR,0 (*)a */
+ case 0x09: /* LODR,1 (*)a */
+ case 0x0a: /* LODR,2 (*)a */
+ case 0x0b: /* LODR,3 (*)a */
+ s2650c->icount -= 9;
+ REL_EA( s2650c->page );
+ M_LOD( s2650c->reg[s2650c->r], RDMEM(s2650c->ea) );
+ break;
+
+ case 0x0c: /* LODA,0 (*)a(,X) */
+ case 0x0d: /* LODA,1 (*)a(,X) */
+ case 0x0e: /* LODA,2 (*)a(,X) */
+ case 0x0f: /* LODA,3 (*)a(,X) */
+ s2650c->icount -= 12;
+ ABS_EA();
+ M_LOD( s2650c->reg[s2650c->r], RDMEM(s2650c->ea) );
+ break;
+
+ case 0x10: /* illegal */
+ case 0x11: /* illegal */
+ s2650c->icount -= 7;
+ break;
+ case 0x12: /* SPSU */
+ s2650c->icount -= 6;
+ M_SPSU();
+ break;
+ case 0x13: /* SPSL */
+ s2650c->icount -= 6;
+ M_SPSL();
+ break;
+
+ case 0x14: /* RETC,0 (zero) */
+ case 0x15: /* RETC,1 (plus) */
+ case 0x16: /* RETC,2 (minus) */
+ s2650c->icount -= 9; /* +2 cycles if condition is true */
+ M_RET( (s2650c->psl >> 6) == s2650c->r );
+ break;
+ case 0x17: /* RETC,3 (always) */
+ s2650c->icount -= 9; /* +2 cycles if condition is true */
+ M_RET( 1 );
+ break;
+
+ case 0x18: /* BCTR,0 (*)a */
+ case 0x19: /* BCTR,1 (*)a */
+ case 0x1a: /* BCTR,2 (*)a */
+ s2650c->icount -= 9;
+ M_BRR( (s2650c->psl >> 6) == s2650c->r );
+ break;
+ case 0x1b: /* BCTR,3 (*)a */
+ s2650c->icount -= 9;
+ M_BRR( 1 );
+ break;
+
+ case 0x1c: /* BCTA,0 (*)a */
+ case 0x1d: /* BCTA,1 (*)a */
+ case 0x1e: /* BCTA,2 (*)a */
+ s2650c->icount -= 9;
+ M_BRA( (s2650c->psl >> 6) == s2650c->r );
+ break;
+ case 0x1f: /* BCTA,3 (*)a */
+ s2650c->icount -= 9;
+ M_BRA( 1 );
+ break;
+
+ case 0x20: /* EORZ,0 */
+ case 0x21: /* EORZ,1 */
+ case 0x22: /* EORZ,2 */
+ case 0x23: /* EORZ,3 */
+ s2650c->icount -= 6;
+ M_EOR( R0, s2650c->reg[s2650c->r] );
+ break;
+
+ case 0x24: /* EORI,0 v */
+ case 0x25: /* EORI,1 v */
+ case 0x26: /* EORI,2 v */
+ case 0x27: /* EORI,3 v */
+ s2650c->icount -= 6;
+ M_EOR( s2650c->reg[s2650c->r], ARG(s2650c) );
+ break;
+
+ case 0x28: /* EORR,0 (*)a */
+ case 0x29: /* EORR,1 (*)a */
+ case 0x2a: /* EORR,2 (*)a */
+ case 0x2b: /* EORR,3 (*)a */
+ s2650c->icount -= 9;
+ REL_EA( s2650c->page );
+ M_EOR( s2650c->reg[s2650c->r], RDMEM(s2650c->ea) );
+ break;
+
+ case 0x2c: /* EORA,0 (*)a(,X) */
+ case 0x2d: /* EORA,1 (*)a(,X) */
+ case 0x2e: /* EORA,2 (*)a(,X) */
+ case 0x2f: /* EORA,3 (*)a(,X) */
+ s2650c->icount -= 12;
+ ABS_EA();
+ M_EOR( s2650c->reg[s2650c->r], RDMEM(s2650c->ea) );
+ break;
+
+ case 0x30: /* REDC,0 */
+ case 0x31: /* REDC,1 */
+ case 0x32: /* REDC,2 */
+ case 0x33: /* REDC,3 */
+ s2650c->icount -= 6;
+ s2650c->reg[s2650c->r] = s2650c->io->read_byte(S2650_CTRL_PORT);
+ SET_CC( s2650c->reg[s2650c->r] );
+ break;
+
+ case 0x34: /* RETE,0 */
+ case 0x35: /* RETE,1 */
+ case 0x36: /* RETE,2 */
+ s2650c->icount -= 9;
+ M_RETE( (s2650c->psl >> 6) == s2650c->r );
+ break;
+ case 0x37: /* RETE,3 */
+ s2650c->icount -= 9;
+ M_RETE( 1 );
+ break;
+
+ case 0x38: /* BSTR,0 (*)a */
+ case 0x39: /* BSTR,1 (*)a */
+ case 0x3a: /* BSTR,2 (*)a */
+ s2650c->icount -= 9;
+ M_BSR( (s2650c->psl >> 6) == s2650c->r );
+ break;
+ case 0x3b: /* BSTR,R3 (*)a */
+ s2650c->icount -= 9;
+ M_BSR( 1 );
+ break;
+
+ case 0x3c: /* BSTA,0 (*)a */
+ case 0x3d: /* BSTA,1 (*)a */
+ case 0x3e: /* BSTA,2 (*)a */
+ s2650c->icount -= 9;
+ M_BSA( (s2650c->psl >> 6) == s2650c->r );
+ break;
+ case 0x3f: /* BSTA,3 (*)a */
+ s2650c->icount -= 9;
+ M_BSA( 1 );
+ break;
+
+ case 0x40: /* HALT */
+ s2650c->icount -= 6;
+ s2650c->iar = (s2650c->iar - 1) & PMSK;
+ s2650c->halt = 1;
+ if (s2650c->icount > 0)
+ s2650c->icount = 0;
+ break;
+ case 0x41: /* ANDZ,1 */
+ case 0x42: /* ANDZ,2 */
+ case 0x43: /* ANDZ,3 */
+ s2650c->icount -= 6;
+ M_AND( R0, s2650c->reg[s2650c->r] );
+ break;
+
+ case 0x44: /* ANDI,0 v */
+ case 0x45: /* ANDI,1 v */
+ case 0x46: /* ANDI,2 v */
+ case 0x47: /* ANDI,3 v */
+ s2650c->icount -= 6;
+ M_AND( s2650c->reg[s2650c->r], ARG(s2650c) );
+ break;
+
+ case 0x48: /* ANDR,0 (*)a */
+ case 0x49: /* ANDR,1 (*)a */
+ case 0x4a: /* ANDR,2 (*)a */
+ case 0x4b: /* ANDR,3 (*)a */
+ s2650c->icount -= 9;
+ REL_EA( s2650c->page );
+ M_AND( s2650c->reg[s2650c->r], RDMEM(s2650c->ea) );
+ break;
+
+ case 0x4c: /* ANDA,0 (*)a(,X) */
+ case 0x4d: /* ANDA,1 (*)a(,X) */
+ case 0x4e: /* ANDA,2 (*)a(,X) */
+ case 0x4f: /* ANDA,3 (*)a(,X) */
+ s2650c->icount -= 12;
+ ABS_EA();
+ M_AND( s2650c->reg[s2650c->r], RDMEM(s2650c->ea) );
+ break;
+
+ case 0x50: /* RRR,0 */
+ case 0x51: /* RRR,1 */
+ case 0x52: /* RRR,2 */
+ case 0x53: /* RRR,3 */
+ s2650c->icount -= 6;
+ M_RRR( s2650c->reg[s2650c->r] );
+ break;
+
+ case 0x54: /* REDE,0 v */
+ case 0x55: /* REDE,1 v */
+ case 0x56: /* REDE,2 v */
+ case 0x57: /* REDE,3 v */
+ s2650c->icount -= 9;
+ s2650c->reg[s2650c->r] = s2650c->io->read_byte( ARG(s2650c) );
+ SET_CC(s2650c->reg[s2650c->r]);
+ break;
+
+ case 0x58: /* BRNR,0 (*)a */
+ case 0x59: /* BRNR,1 (*)a */
+ case 0x5a: /* BRNR,2 (*)a */
+ case 0x5b: /* BRNR,3 (*)a */
+ s2650c->icount -= 9;
+ M_BRR( s2650c->reg[s2650c->r] );
+ break;
+
+ case 0x5c: /* BRNA,0 (*)a */
+ case 0x5d: /* BRNA,1 (*)a */
+ case 0x5e: /* BRNA,2 (*)a */
+ case 0x5f: /* BRNA,3 (*)a */
+ s2650c->icount -= 9;
+ M_BRA( s2650c->reg[s2650c->r] );
+ break;
+
+ case 0x60: /* IORZ,0 */
+ case 0x61: /* IORZ,1 */
+ case 0x62: /* IORZ,2 */
+ case 0x63: /* IORZ,3 */
+ s2650c->icount -= 6;
+ M_IOR( R0, s2650c->reg[s2650c->r] );
+ break;
+
+ case 0x64: /* IORI,0 v */
+ case 0x65: /* IORI,1 v */
+ case 0x66: /* IORI,2 v */
+ case 0x67: /* IORI,3 v */
+ s2650c->icount -= 6;
+ M_IOR( s2650c->reg[s2650c->r], ARG(s2650c) );
+ break;
+
+ case 0x68: /* IORR,0 (*)a */
+ case 0x69: /* IORR,1 (*)a */
+ case 0x6a: /* IORR,2 (*)a */
+ case 0x6b: /* IORR,3 (*)a */
+ s2650c->icount -= 9;
+ REL_EA( s2650c->page );
+ M_IOR( s2650c->reg[s2650c-> r],RDMEM(s2650c->ea) );
+ break;
+
+ case 0x6c: /* IORA,0 (*)a(,X) */
+ case 0x6d: /* IORA,1 (*)a(,X) */
+ case 0x6e: /* IORA,2 (*)a(,X) */
+ case 0x6f: /* IORA,3 (*)a(,X) */
+ s2650c->icount -= 12;
+ ABS_EA();
+ M_IOR( s2650c->reg[s2650c->r], RDMEM(s2650c->ea) );
+ break;
+
+ case 0x70: /* REDD,0 */
+ case 0x71: /* REDD,1 */
+ case 0x72: /* REDD,2 */
+ case 0x73: /* REDD,3 */
+ s2650c->icount -= 6;
+ s2650c->reg[s2650c->r] = s2650c->io->read_byte(S2650_DATA_PORT);
+ SET_CC(s2650c->reg[s2650c->r]);
+ break;
+
+ case 0x74: /* CPSU */
+ s2650c->icount -= 9;
+ M_CPSU();
+ break;
+ case 0x75: /* CPSL */
+ s2650c->icount -= 9;
+ M_CPSL();
+ break;
+ case 0x76: /* PPSU */
+ s2650c->icount -= 9;
+ M_PPSU();
+ break;
+ case 0x77: /* PPSL */
+ s2650c->icount -= 9;
+ M_PPSL();
+ break;
+
+ case 0x78: /* BSNR,0 (*)a */
+ case 0x79: /* BSNR,1 (*)a */
+ case 0x7a: /* BSNR,2 (*)a */
+ case 0x7b: /* BSNR,3 (*)a */
+ s2650c->icount -= 9;
+ M_BSR( s2650c->reg[s2650c->r] );
+ break;
+
+ case 0x7c: /* BSNA,0 (*)a */
+ case 0x7d: /* BSNA,1 (*)a */
+ case 0x7e: /* BSNA,2 (*)a */
+ case 0x7f: /* BSNA,3 (*)a */
+ s2650c->icount -= 9;
+ M_BSA( s2650c->reg[s2650c->r] );
+ break;
+
+ case 0x80: /* ADDZ,0 */
+ case 0x81: /* ADDZ,1 */
+ case 0x82: /* ADDZ,2 */
+ case 0x83: /* ADDZ,3 */
+ s2650c->icount -= 6;
+ M_ADD( R0,s2650c->reg[s2650c->r] );
+ break;
+
+ case 0x84: /* ADDI,0 v */
+ case 0x85: /* ADDI,1 v */
+ case 0x86: /* ADDI,2 v */
+ case 0x87: /* ADDI,3 v */
+ s2650c->icount -= 6;
+ M_ADD( s2650c->reg[s2650c->r], ARG(s2650c) );
+ break;
+
+ case 0x88: /* ADDR,0 (*)a */
+ case 0x89: /* ADDR,1 (*)a */
+ case 0x8a: /* ADDR,2 (*)a */
+ case 0x8b: /* ADDR,3 (*)a */
+ s2650c->icount -= 9;
+ REL_EA(s2650c->page);
+ M_ADD( s2650c->reg[s2650c->r], RDMEM(s2650c->ea) );
+ break;
+
+ case 0x8c: /* ADDA,0 (*)a(,X) */
+ case 0x8d: /* ADDA,1 (*)a(,X) */
+ case 0x8e: /* ADDA,2 (*)a(,X) */
+ case 0x8f: /* ADDA,3 (*)a(,X) */
+ s2650c->icount -= 12;
+ ABS_EA();
+ M_ADD( s2650c->reg[s2650c->r], RDMEM(s2650c->ea) );
+ break;
+
+ case 0x90: /* illegal */
+ case 0x91: /* illegal */
+ s2650c->icount -= 7;
+ break;
+ case 0x92: /* LPSU */
+ s2650c->icount -= 6;
+ set_psu(s2650c, (R0 & ~PSU34) & ~SI);
+ break;
+ case 0x93: /* LPSL */
+ s2650c->icount -= 6;
+ /* change register set ? */
+ if ((s2650c->psl ^ R0) & RS)
+ SWAP_REGS;
+ s2650c->psl = R0;
+ break;
+
+ case 0x94: /* DAR,0 */
+ case 0x95: /* DAR,1 */
+ case 0x96: /* DAR,2 */
+ case 0x97: /* DAR,3 */
+ s2650c->icount -= 9;
+ M_DAR( s2650c->reg[s2650c->r] );
+ break;
+
+ case 0x98: /* BCFR,0 (*)a */
+ case 0x99: /* BCFR,1 (*)a */
+ case 0x9a: /* BCFR,2 (*)a */
+ s2650c->icount -= 9;
+ M_BRR( (s2650c->psl >> 6) != s2650c->r );
+ break;
+ case 0x9b: /* ZBRR (*)a */
+ s2650c->icount -= 9;
+ M_ZBRR();
+ break;
+
+ case 0x9c: /* BCFA,0 (*)a */
+ case 0x9d: /* BCFA,1 (*)a */
+ case 0x9e: /* BCFA,2 (*)a */
+ s2650c->icount -= 9;
+ M_BRA( (s2650c->psl >> 6) != s2650c->r );
+ break;
+ case 0x9f: /* BXA (*)a */
+ s2650c->icount -= 9;
+ M_BXA();
+ break;
+
+ case 0xa0: /* SUBZ,0 */
+ case 0xa1: /* SUBZ,1 */
+ case 0xa2: /* SUBZ,2 */
+ case 0xa3: /* SUBZ,3 */
+ s2650c->icount -= 6;
+ M_SUB( R0, s2650c->reg[s2650c->r] );
+ break;
+
+ case 0xa4: /* SUBI,0 v */
+ case 0xa5: /* SUBI,1 v */
+ case 0xa6: /* SUBI,2 v */
+ case 0xa7: /* SUBI,3 v */
+ s2650c->icount -= 6;
+ M_SUB( s2650c->reg[s2650c->r], ARG(s2650c) );
+ break;
+
+ case 0xa8: /* SUBR,0 (*)a */
+ case 0xa9: /* SUBR,1 (*)a */
+ case 0xaa: /* SUBR,2 (*)a */
+ case 0xab: /* SUBR,3 (*)a */
+ s2650c->icount -= 9;
+ REL_EA(s2650c->page);
+ M_SUB( s2650c->reg[s2650c->r], RDMEM(s2650c->ea) );
+ break;
+
+ case 0xac: /* SUBA,0 (*)a(,X) */
+ case 0xad: /* SUBA,1 (*)a(,X) */
+ case 0xae: /* SUBA,2 (*)a(,X) */
+ case 0xaf: /* SUBA,3 (*)a(,X) */
+ s2650c->icount -= 12;
+ ABS_EA();
+ M_SUB( s2650c->reg[s2650c->r], RDMEM(s2650c->ea) );
+ break;
+
+ case 0xb0: /* WRTC,0 */
+ case 0xb1: /* WRTC,1 */
+ case 0xb2: /* WRTC,2 */
+ case 0xb3: /* WRTC,3 */
+ s2650c->icount -= 6;
+ s2650c->io->write_byte(S2650_CTRL_PORT,s2650c->reg[s2650c->r]);
+ break;
+
+ case 0xb4: /* TPSU */
+ s2650c->icount -= 9;
+ M_TPSU();
+ break;
+ case 0xb5: /* TPSL */
+ s2650c->icount -= 9;
+ M_TPSL();
+ break;
+ case 0xb6: /* illegal */
+ case 0xb7: /* illegal */
+ s2650c->icount -= 7;
+ break;
+
+ case 0xb8: /* BSFR,0 (*)a */
+ case 0xb9: /* BSFR,1 (*)a */
+ case 0xba: /* BSFR,2 (*)a */
+ s2650c->icount -= 9;
+ M_BSR( (s2650c->psl >> 6) != s2650c->r );
+ break;
+ case 0xbb: /* ZBSR (*)a */
+ s2650c->icount -= 9;
+ M_ZBSR();
+ break;
+
+ case 0xbc: /* BSFA,0 (*)a */
+ case 0xbd: /* BSFA,1 (*)a */
+ case 0xbe: /* BSFA,2 (*)a */
+ s2650c->icount -= 9;
+ M_BSA( (s2650c->psl >> 6) != s2650c->r );
+ break;
+ case 0xbf: /* BSXA (*)a */
+ s2650c->icount -= 9;
+ M_BSXA();
+ break;
+
+ case 0xc0: /* NOP */
+ s2650c->icount -= 6;
+ break;
+ case 0xc1: /* STRZ,1 */
+ case 0xc2: /* STRZ,2 */
+ case 0xc3: /* STRZ,3 */
+ s2650c->icount -= 6;
+ M_LOD( s2650c->reg[s2650c->r], R0 );
+ break;
+
+ case 0xc4: /* illegal */
+ case 0xc5: /* illegal */
+ case 0xc6: /* illegal */
+ case 0xc7: /* illegal */
+ s2650c->icount -= 7;
+ break;
+
+ case 0xc8: /* STRR,0 (*)a */
+ case 0xc9: /* STRR,1 (*)a */
+ case 0xca: /* STRR,2 (*)a */
+ case 0xcb: /* STRR,3 (*)a */
+ s2650c->icount -= 9;
+ REL_EA(s2650c->page);
+ M_STR( s2650c->ea, s2650c->reg[s2650c->r] );
+ break;
+
+ case 0xcc: /* STRA,0 (*)a(,X) */
+ case 0xcd: /* STRA,1 (*)a(,X) */
+ case 0xce: /* STRA,2 (*)a(,X) */
+ case 0xcf: /* STRA,3 (*)a(,X) */
+ s2650c->icount -= 12;
+ ABS_EA();
+ M_STR( s2650c->ea, s2650c->reg[s2650c->r] );
+ break;
+
+ case 0xd0: /* RRL,0 */
+ case 0xd1: /* RRL,1 */
+ case 0xd2: /* RRL,2 */
+ case 0xd3: /* RRL,3 */
+ s2650c->icount -= 6;
+ M_RRL( s2650c->reg[s2650c->r] );
+ break;
+
+ case 0xd4: /* WRTE,0 v */
+ case 0xd5: /* WRTE,1 v */
+ case 0xd6: /* WRTE,2 v */
+ case 0xd7: /* WRTE,3 v */
+ s2650c->icount -= 9;
+ s2650c->io->write_byte( ARG(s2650c), s2650c->reg[s2650c->r] );
+ break;
+
+ case 0xd8: /* BIRR,0 (*)a */
+ case 0xd9: /* BIRR,1 (*)a */
+ case 0xda: /* BIRR,2 (*)a */
+ case 0xdb: /* BIRR,3 (*)a */
+ s2650c->icount -= 9;
+ M_BRR( ++s2650c->reg[s2650c->r] );
+ break;
+
+ case 0xdc: /* BIRA,0 (*)a */
+ case 0xdd: /* BIRA,1 (*)a */
+ case 0xde: /* BIRA,2 (*)a */
+ case 0xdf: /* BIRA,3 (*)a */
+ s2650c->icount -= 9;
+ M_BRA( ++s2650c->reg[s2650c->r] );
+ break;
+
+ case 0xe0: /* COMZ,0 */
+ case 0xe1: /* COMZ,1 */
+ case 0xe2: /* COMZ,2 */
+ case 0xe3: /* COMZ,3 */
+ s2650c->icount -= 6;
+ M_COM( R0, s2650c->reg[s2650c->r] );
+ break;
+
+ case 0xe4: /* COMI,0 v */
+ case 0xe5: /* COMI,1 v */
+ case 0xe6: /* COMI,2 v */
+ case 0xe7: /* COMI,3 v */
+ s2650c->icount -= 6;
+ M_COM( s2650c->reg[s2650c->r], ARG(s2650c) );
+ break;
+
+ case 0xe8: /* COMR,0 (*)a */
+ case 0xe9: /* COMR,1 (*)a */
+ case 0xea: /* COMR,2 (*)a */
+ case 0xeb: /* COMR,3 (*)a */
+ s2650c->icount -= 9;
+ REL_EA(s2650c->page);
+ M_COM( s2650c->reg[s2650c->r], RDMEM(s2650c->ea) );
+ break;
+
+ case 0xec: /* COMA,0 (*)a(,X) */
+ case 0xed: /* COMA,1 (*)a(,X) */
+ case 0xee: /* COMA,2 (*)a(,X) */
+ case 0xef: /* COMA,3 (*)a(,X) */
+ s2650c->icount -= 12;
+ ABS_EA();
+ M_COM( s2650c->reg[s2650c->r], RDMEM(s2650c->ea) );
+ break;
+
+ case 0xf0: /* WRTD,0 */
+ case 0xf1: /* WRTD,1 */
+ case 0xf2: /* WRTD,2 */
+ case 0xf3: /* WRTD,3 */
+ s2650c->icount -= 6;
+ s2650c->io->write_byte(S2650_DATA_PORT, s2650c->reg[s2650c->r]);
+ break;
+
+ case 0xf4: /* TMI,0 v */
+ case 0xf5: /* TMI,1 v */
+ case 0xf6: /* TMI,2 v */
+ case 0xf7: /* TMI,3 v */
+ s2650c->icount -= 9;
+ M_TMI( s2650c->reg[s2650c->r] );
+ break;
+
+ case 0xf8: /* BDRR,0 (*)a */
+ case 0xf9: /* BDRR,1 (*)a */
+ case 0xfa: /* BDRR,2 (*)a */
+ case 0xfb: /* BDRR,3 (*)a */
+ s2650c->icount -= 9;
+ M_BRR( --s2650c->reg[s2650c->r] );
+ break;
+
+ case 0xfc: /* BDRA,0 (*)a */
+ case 0xfd: /* BDRA,1 (*)a */
+ case 0xfe: /* BDRA,2 (*)a */
+ case 0xff: /* BDRA,3 (*)a */
+ s2650c->icount -= 9;
+ M_BRA( --s2650c->reg[s2650c->r] );
+ break;
+ }
+ } while( s2650c->icount > 0 );
+}
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( s2650 )
+{
+ s2650_regs *s2650c = 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(s2650c, 0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + 1: set_irq_line(s2650c, 1, info->i); break;
+
+ case CPUINFO_INT_PC:
+ s2650c->page = info->i & PAGE;
+ s2650c->iar = info->i & PMSK;
+ break;
+
+ case CPUINFO_INT_REGISTER + S2650_PC: s2650c->page = info->i & PAGE; s2650c->iar = info->i & PMSK; break;
+ case CPUINFO_INT_SP: set_sp(s2650c, info->i); break;
+ case CPUINFO_INT_REGISTER + S2650_PS: s2650c->psl = info->i & 0xff; set_psu(s2650c, info->i >> 8); break;
+ case CPUINFO_INT_REGISTER + S2650_R0: s2650c->reg[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + S2650_R1: s2650c->reg[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + S2650_R2: s2650c->reg[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + S2650_R3: s2650c->reg[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + S2650_R1A: s2650c->reg[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + S2650_R2A: s2650c->reg[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + S2650_R3A: s2650c->reg[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + S2650_HALT: s2650c->halt = info->i; break;
+ case CPUINFO_INT_REGISTER + S2650_SI: s2650_set_sense(s2650c, info->i); break;
+ case CPUINFO_INT_REGISTER + S2650_FO: s2650_set_flag(s2650c, info->i); break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( s2650 )
+{
+ s2650_regs *s2650c = (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(s2650_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 = 5; 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 = 15; 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 = 9; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + 0: info->i = s2650c->irq_state; break;
+ case CPUINFO_INT_INPUT_STATE + 1: info->i = s2650_get_sense(s2650c) ? ASSERT_LINE : CLEAR_LINE; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = s2650c->ppc; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + S2650_PC: info->i = s2650c->page + s2650c->iar; break;
+
+ case CPUINFO_INT_SP: info->i = get_sp(s2650c); break;
+ case CPUINFO_INT_REGISTER + S2650_PS: info->i = (s2650c->psu << 8) | s2650c->psl; break;
+ case CPUINFO_INT_REGISTER + S2650_R0: info->i = s2650c->reg[0]; break;
+ case CPUINFO_INT_REGISTER + S2650_R1: info->i = s2650c->reg[1]; break;
+ case CPUINFO_INT_REGISTER + S2650_R2: info->i = s2650c->reg[2]; break;
+ case CPUINFO_INT_REGISTER + S2650_R3: info->i = s2650c->reg[3]; break;
+ case CPUINFO_INT_REGISTER + S2650_R1A: info->i = s2650c->reg[4]; break;
+ case CPUINFO_INT_REGISTER + S2650_R2A: info->i = s2650c->reg[5]; break;
+ case CPUINFO_INT_REGISTER + S2650_R3A: info->i = s2650c->reg[6]; break;
+ case CPUINFO_INT_REGISTER + S2650_HALT: info->i = s2650c->halt; break;
+ case CPUINFO_INT_REGISTER + S2650_SI: info->i = s2650_get_sense(s2650c); break;
+ case CPUINFO_INT_REGISTER + S2650_FO: info->i = s2650_get_flag(s2650c); 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(s2650); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(s2650); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(s2650); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(s2650); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(s2650); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(s2650); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &s2650c->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "S2650"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Signetics 2650"); 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, "Written by Juergen Buchmueller for use with MAME"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
+ s2650c->psu & 0x80 ? 'S':'.',
+ s2650c->psu & 0x40 ? 'O':'.',
+ s2650c->psu & 0x20 ? 'I':'.',
+ s2650c->psu & 0x10 ? '?':'.',
+ s2650c->psu & 0x08 ? '?':'.',
+ s2650c->psu & 0x04 ? 's':'.',
+ s2650c->psu & 0x02 ? 's':'.',
+ s2650c->psu & 0x01 ? 's':'.',
+ s2650c->psl & 0x80 ? 'M':'.',
+ s2650c->psl & 0x40 ? 'P':'.',
+ s2650c->psl & 0x20 ? 'H':'.',
+ s2650c->psl & 0x10 ? 'R':'.',
+ s2650c->psl & 0x08 ? 'W':'.',
+ s2650c->psl & 0x04 ? 'V':'.',
+ s2650c->psl & 0x02 ? '2':'.',
+ s2650c->psl & 0x01 ? 'C':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + S2650_PC: sprintf(info->s, "PC:%04X", s2650c->page + s2650c->iar); break;
+ case CPUINFO_STR_REGISTER + S2650_PS: sprintf(info->s, "PS:%02X%02X", s2650c->psu, s2650c->psl); break;
+ case CPUINFO_STR_REGISTER + S2650_R0: sprintf(info->s, "R0:%02X", s2650c->reg[0]); break;
+ case CPUINFO_STR_REGISTER + S2650_R1: sprintf(info->s, "R1:%02X", s2650c->reg[1]); break;
+ case CPUINFO_STR_REGISTER + S2650_R2: sprintf(info->s, "R2:%02X", s2650c->reg[2]); break;
+ case CPUINFO_STR_REGISTER + S2650_R3: sprintf(info->s, "R3:%02X", s2650c->reg[3]); break;
+ case CPUINFO_STR_REGISTER + S2650_R1A: sprintf(info->s, "R1':%02X", s2650c->reg[4]); break;
+ case CPUINFO_STR_REGISTER + S2650_R2A: sprintf(info->s, "R2':%02X", s2650c->reg[5]); break;
+ case CPUINFO_STR_REGISTER + S2650_R3A: sprintf(info->s, "R3':%02X", s2650c->reg[6]); break;
+ case CPUINFO_STR_REGISTER + S2650_HALT: sprintf(info->s, "HALT:%X", s2650c->halt); break;
+ case CPUINFO_STR_REGISTER + S2650_SI: sprintf(info->s, "SI:%X", (s2650c->psu & SI) ? 1 : 0); break;
+ case CPUINFO_STR_REGISTER + S2650_FO: sprintf(info->s, "FO:%X", (s2650c->psu & FO) ? 1 : 0); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(S2650, s2650);
diff --git a/trunk/src/emu/cpu/s2650/s2650.h b/trunk/src/emu/cpu/s2650/s2650.h
new file mode 100644
index 00000000000..8fa34426fff
--- /dev/null
+++ b/trunk/src/emu/cpu/s2650/s2650.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#ifndef __S2650_H__
+#define __S2650_H__
+
+
+enum
+{
+ S2650_PC=1, S2650_PS, S2650_R0, S2650_R1, S2650_R2, S2650_R3,
+ S2650_R1A, S2650_R2A, S2650_R3A,
+ S2650_HALT, S2650_SI, S2650_FO
+};
+
+/* fake I/O space ports */
+enum
+{
+ S2650_EXT_PORT = 0x00ff, /* M/~IO=0 D/~C=x E/~NE=1 */
+ S2650_CTRL_PORT = 0x0100, /* M/~IO=0 D/~C=0 E/~NE=0 */
+ S2650_DATA_PORT = 0x0101, /* M/~IO=0 D/~C=1 E/~NE=0 */
+ S2650_SENSE_PORT = 0x0102, /* Fake Sense Line */
+ S2650_FO_PORT = 0x0103 /* Fake FO Line */
+};
+
+DECLARE_LEGACY_CPU_DEVICE(S2650, s2650);
+
+extern CPU_DISASSEMBLE( s2650 );
+
+#endif /* __S2650_H__ */
diff --git a/trunk/src/emu/cpu/s2650/s2650cpu.h b/trunk/src/emu/cpu/s2650/s2650cpu.h
new file mode 100644
index 00000000000..e0158390e67
--- /dev/null
+++ b/trunk/src/emu/cpu/s2650/s2650cpu.h
@@ -0,0 +1,33 @@
+/*******************************************************
+ *
+ * Portable Signetics 2650 cpu emulation
+ *
+ * Written by Juergen Buchmueller for use with MAME
+ *
+ *******************************************************/
+
+#define PMSK 0x1fff /* mask page offset */
+#define PLEN 0x2000 /* page length */
+#define PAGE 0x6000 /* mask page */
+#define AMSK 0x7fff /* mask address range */
+
+/* processor status lower */
+#define C 0x01 /* carry flag */
+#define COM 0x02 /* compare: 0 binary, 1 2s complement */
+#define OVF 0x04 /* 2s complement overflow */
+#define WC 0x08 /* with carry: use carry in arithmetic / rotate ops */
+#define RS 0x10 /* register select 0: R0/R1/R2/R3 1: R0/R4/R5/R6 */
+#define IDC 0x20 /* inter digit carry: bit-3-to-bit-4 carry */
+#define CC 0xc0 /* condition code */
+
+/* processor status upper */
+#define SP 0x07 /* stack pointer: indexing 8 15bit words */
+#define PSU34 0x18 /* unused bits */
+#define II 0x20 /* interrupt inhibit 0: allow, 1: inhibit */
+#define FO 0x40 /* flag output */
+#define SI 0x80 /* sense input */
+
+#define R0 s2650c->reg[0]
+#define R1 s2650c->reg[1]
+#define R2 s2650c->reg[2]
+#define R3 s2650c->reg[3]
diff --git a/trunk/src/emu/cpu/saturn/satops.c b/trunk/src/emu/cpu/saturn/satops.c
new file mode 100644
index 00000000000..bfc5f00f2b8
--- /dev/null
+++ b/trunk/src/emu/cpu/saturn/satops.c
@@ -0,0 +1,1137 @@
+#define IRQ_ADDRESS 0xf
+
+#define saturn_assert(x) \
+ do { if (!(x)) logerror("SATURN '%s' assertion failed: %s at %s:%i, pc=%05x\n", cpustate->device->tag(), #x, __FILE__, __LINE__, cpustate->pc); } while (0)
+
+INLINE int READ_OP(saturn_state *cpustate)
+{
+ UINT8 data;
+ cpustate->icount-=3;
+ data=cpustate->direct->read_decrypted_byte(cpustate->pc);
+ saturn_assert(data<0x10);
+ cpustate->pc=(cpustate->pc+1)&0xfffff;
+ return data;
+}
+
+INLINE int READ_OP_ARG(saturn_state *cpustate)
+{
+ UINT8 data;
+ cpustate->icount-=3;
+ data=cpustate->direct->read_raw_byte(cpustate->pc);
+ saturn_assert(data<0x10);
+ cpustate->pc=(cpustate->pc+1)&0xfffff;
+ return data;
+}
+
+INLINE int READ_OP_ARG8(saturn_state *cpustate)
+{
+ int n0=READ_OP_ARG(cpustate);
+ int n1=READ_OP_ARG(cpustate);
+ return n0|(n1<<4);
+}
+
+INLINE INT8 READ_OP_DIS8(saturn_state *cpustate)
+{
+ return (INT8)READ_OP_ARG8(cpustate);
+}
+
+INLINE int READ_OP_ARG12(saturn_state *cpustate)
+{
+ int n0=READ_OP_ARG(cpustate);
+ int n1=READ_OP_ARG(cpustate);
+ int n2=READ_OP_ARG(cpustate);
+ return n0|(n1<<4)|(n2<<8);
+}
+
+INLINE int READ_OP_DIS12(saturn_state *cpustate)
+{
+ int temp=READ_OP_ARG12(cpustate);
+ if (temp&0x800) temp-=0x1000;
+ return temp;
+}
+
+INLINE int READ_OP_ARG16(saturn_state *cpustate)
+{
+ int n0=READ_OP_ARG(cpustate);
+ int n1=READ_OP_ARG(cpustate);
+ int n2=READ_OP_ARG(cpustate);
+ int n3=READ_OP_ARG(cpustate);
+ return n0|(n1<<4)|(n2<<8)|(n3<<12);
+}
+
+INLINE INT16 READ_OP_DIS16(saturn_state *cpustate)
+{
+ return (INT16)READ_OP_ARG16(cpustate);
+}
+
+INLINE int READ_OP_ARG20(saturn_state *cpustate)
+{
+ int n0=READ_OP_ARG(cpustate);
+ int n1=READ_OP_ARG(cpustate);
+ int n2=READ_OP_ARG(cpustate);
+ int n3=READ_OP_ARG(cpustate);
+ int n4=READ_OP_ARG(cpustate);
+ return n0|(n1<<4)|(n2<<8)|(n3<<12)|(n4<<16);
+}
+
+INLINE int READ_NIBBLE(saturn_state *cpustate, SaturnAdr adr)
+{
+ UINT8 data;
+ cpustate->icount-=3;
+ data=cpustate->program->read_byte(adr&0xfffff);
+ saturn_assert(data<0x10);
+ if (cpustate->config&&cpustate->config->crc) cpustate->config->crc(cpustate->device, adr&0xfffff, data);
+ return data;
+}
+
+INLINE int READ_8(saturn_state *cpustate, SaturnAdr adr)
+{
+ return READ_NIBBLE(cpustate, adr)|(READ_NIBBLE(cpustate, adr+1)<<4);
+}
+
+INLINE int READ_12(saturn_state *cpustate, SaturnAdr adr)
+{
+ return READ_NIBBLE(cpustate, adr)|(READ_NIBBLE(cpustate, adr+1)<<4)|(READ_NIBBLE(cpustate, adr+2)<<8);
+}
+
+INLINE int READ_16(saturn_state *cpustate, SaturnAdr adr)
+{
+ return READ_NIBBLE(cpustate, adr)|(READ_NIBBLE(cpustate, adr+1)<<4)|(READ_NIBBLE(cpustate, adr+2)<<8)|(READ_NIBBLE(cpustate, adr+3)<<12);
+}
+
+INLINE int READ_20(saturn_state *cpustate, SaturnAdr adr)
+{
+ return READ_NIBBLE(cpustate, adr)|(READ_NIBBLE(cpustate, adr+1)<<4)|(READ_NIBBLE(cpustate, adr+2)<<8)|(READ_NIBBLE(cpustate, adr+3)<<12)|(READ_NIBBLE(cpustate, adr+4)<<16);
+}
+
+INLINE void WRITE_NIBBLE(saturn_state *cpustate, SaturnAdr adr, SaturnNib nib)
+{
+ cpustate->icount-=3;
+ saturn_assert(nib<0x10);
+ cpustate->program->write_byte(adr&0xfffff,nib);
+}
+
+#define BEGIN_B 0
+#define COUNT_B 2
+#define BEGIN_X 0
+#define COUNT_X 3
+#define BEGIN_XS 2
+#define COUNT_XS 1
+#define BEGIN_A 0
+#define COUNT_A 5
+#define BEGIN_M 3
+#define COUNT_M 12
+#define BEGIN_S 15
+#define COUNT_S 1
+#define BEGIN_W 0
+#define COUNT_W 16
+
+
+INLINE int S64_READ_X(saturn_state *cpustate, int r)
+{
+ return cpustate->reg[r][0]|(cpustate->reg[r][1]<<4)|(cpustate->reg[r][2]<<8);
+}
+
+INLINE int S64_READ_WORD(saturn_state *cpustate, int r)
+{
+ return cpustate->reg[r][0]|(cpustate->reg[r][1]<<4)|(cpustate->reg[r][2]<<8)|(cpustate->reg[r][3]<<12);
+}
+
+INLINE int S64_READ_A(saturn_state *cpustate, int r)
+{
+ return cpustate->reg[r][0]|(cpustate->reg[r][1]<<4)|(cpustate->reg[r][2]<<8)|(cpustate->reg[r][3]<<12)|(cpustate->reg[r][4]<<16);
+}
+
+INLINE void S64_WRITE_X(saturn_state *cpustate, int r, int v)
+{
+ cpustate->reg[r][0]=v&0xf;
+ cpustate->reg[r][1]=(v>>4)&0xf;
+ cpustate->reg[r][2]=(v>>8)&0xf;
+}
+
+INLINE void S64_WRITE_WORD(saturn_state *cpustate, int r, int v)
+{
+ cpustate->reg[r][0]=v&0xf;
+ cpustate->reg[r][1]=(v>>4)&0xf;
+ cpustate->reg[r][2]=(v>>8)&0xf;
+ cpustate->reg[r][3]=(v>>12)&0xf;
+}
+
+INLINE void S64_WRITE_A(saturn_state *cpustate, int r, int v)
+{
+ cpustate->reg[r][0]=v&0xf;
+ cpustate->reg[r][1]=(v>>4)&0xf;
+ cpustate->reg[r][2]=(v>>8)&0xf;
+ cpustate->reg[r][3]=(v>>12)&0xf;
+ cpustate->reg[r][4]=(v>>16)&0xf;
+}
+
+
+
+
+
+INLINE SaturnAdr saturn_pop(saturn_state *cpustate)
+{
+ SaturnAdr temp=cpustate->rstk[0];
+ memmove(cpustate->rstk, cpustate->rstk+1, sizeof(cpustate->rstk)-sizeof(cpustate->rstk[0]));
+ cpustate->rstk[7]=0;
+ return temp;
+}
+
+INLINE void saturn_push(saturn_state *cpustate, SaturnAdr adr)
+{
+ memmove(cpustate->rstk+1, cpustate->rstk, sizeof(cpustate->rstk)-sizeof(cpustate->rstk[0]));
+ cpustate->rstk[0]=adr;
+}
+
+INLINE void saturn_interrupt_on(saturn_state *cpustate)
+{
+ LOG(( "SATURN '%s' at %05x: INTON\n", cpustate->device->tag(), cpustate->pc-4 ));
+ cpustate->irq_enable=1;
+ if (cpustate->irq_state)
+ {
+ LOG(( "SATURN '%s' set_irq_line(ASSERT)\n", cpustate->device->tag()));
+ cpustate->pending_irq=1;
+ }
+}
+
+INLINE void saturn_interrupt_off(saturn_state *cpustate)
+{
+ LOG(( "SATURN '%s' at %05x: INTOFF\n", cpustate->device->tag(), cpustate->pc-4 ));
+ cpustate->irq_enable=0;
+}
+
+INLINE void saturn_reset_interrupt(saturn_state *cpustate)
+{
+ LOG(( "SATURN '%s' at %05x: RSI\n", cpustate->device->tag(), cpustate->pc-5 ));
+ if (cpustate->config&&cpustate->config->rsi) cpustate->config->rsi(cpustate->device);
+}
+
+INLINE void saturn_mem_reset(saturn_state *cpustate)
+{
+ if (cpustate->config&&cpustate->config->reset) cpustate->config->reset(cpustate->device);
+}
+
+INLINE void saturn_mem_config(saturn_state *cpustate)
+{
+ if (cpustate->config&&cpustate->config->config) cpustate->config->config(cpustate->device, S64_READ_A(cpustate, C));
+}
+
+INLINE void saturn_mem_unconfig(saturn_state *cpustate)
+{
+ if (cpustate->config&&cpustate->config->unconfig) cpustate->config->unconfig(cpustate->device, S64_READ_A(cpustate, C));
+}
+
+INLINE void saturn_mem_id(saturn_state *cpustate)
+{
+ int id=0;
+ if (cpustate->config&&cpustate->config->id) id=cpustate->config->id(cpustate->device);
+ S64_WRITE_A(cpustate, C,id);
+ cpustate->monitor_id = id;
+}
+
+INLINE void saturn_shutdown(saturn_state *cpustate)
+{
+ cpustate->sleeping=1;
+ cpustate->irq_enable=1;
+ LOG(( "SATURN '%s' at %05x: SHUTDN\n", cpustate->device->tag(), cpustate->pc-3 ));
+}
+
+INLINE void saturn_bus_command_b(saturn_state *cpustate)
+{
+ logerror( "SATURN '%s' at %05x: BUSCB opcode not handled\n", cpustate->device->tag(), cpustate->pc-4 );
+}
+
+INLINE void saturn_bus_command_c(saturn_state *cpustate)
+{
+ logerror( "SATURN '%s' at %05x: BUSCC opcode not handled\n", cpustate->device->tag(), cpustate->pc-3 );
+}
+
+INLINE void saturn_bus_command_d(saturn_state *cpustate)
+{
+ logerror( "SATURN '%s' at %05x: BUSCD opcode not handled\n", cpustate->device->tag(), cpustate->pc-4 );
+}
+
+INLINE void saturn_serial_request(saturn_state *cpustate)
+{
+ logerror( "SATURN '%s' at %05x: SREQ? opcode not handled\n", cpustate->device->tag(), cpustate->pc-3 );
+}
+
+INLINE void saturn_out_c(saturn_state *cpustate)
+{
+ cpustate->out=S64_READ_X(cpustate, C);
+ if (cpustate->config&&cpustate->config->out) cpustate->config->out(cpustate->device, cpustate->out);
+}
+
+INLINE void saturn_out_cs(saturn_state *cpustate)
+{
+ cpustate->out=(cpustate->out&0xff0)|cpustate->reg[C][0];
+ if (cpustate->config&&cpustate->config->out) cpustate->config->out(cpustate->device, cpustate->out);
+}
+
+INLINE void saturn_in(saturn_state *cpustate, int reg)
+{
+ int in = 0;
+ saturn_assert(reg>=0 && reg<9);
+ if (!(cpustate->pc&1))
+ logerror( "SATURN '%s' at %05x: reg=IN opcode at odd addresse\n",
+ cpustate->device->tag(), cpustate->pc-3 );
+ if (cpustate->config&&cpustate->config->in) in = cpustate->config->in(cpustate->device);
+ S64_WRITE_WORD(cpustate, reg,in);
+ cpustate->monitor_in = in;
+}
+
+INLINE void saturn_sethex(saturn_state *cpustate) { cpustate->decimal=0; }
+INLINE void saturn_setdec(saturn_state *cpustate) { cpustate->decimal=1; }
+
+/* st related */
+INLINE void saturn_clear_st(saturn_state *cpustate)
+{
+ cpustate->st&=0xf000;
+}
+
+INLINE void saturn_st_to_c(saturn_state *cpustate)
+{
+ S64_WRITE_X(cpustate, C,cpustate->st);
+}
+
+INLINE void saturn_c_to_st(saturn_state *cpustate)
+{
+ cpustate->st=(cpustate->st&0xf000)|(S64_READ_X(cpustate, C));
+}
+
+INLINE void saturn_exchange_c_st(saturn_state *cpustate)
+{
+ int t=cpustate->st;
+ cpustate->st=(t&0xf000)|(S64_READ_X(cpustate, C));
+ S64_WRITE_X(cpustate, C,t);
+}
+
+INLINE void saturn_jump_after_test(saturn_state *cpustate)
+{
+ int adr=READ_OP_DIS8(cpustate);
+ if (cpustate->carry) {
+ if (adr==0) {
+ cpustate->pc=saturn_pop(cpustate);
+ } else {
+ cpustate->pc=(cpustate->pc+adr-2)&0xfffff;
+ }
+ }
+}
+INLINE void saturn_st_clear_bit(saturn_state *cpustate)
+{
+ cpustate->st &= ~(1<<(READ_OP_ARG(cpustate)));
+}
+
+INLINE void saturn_st_set_bit(saturn_state *cpustate)
+{
+ cpustate->st |= (1<<(READ_OP_ARG(cpustate)));
+}
+
+INLINE void saturn_st_jump_bit_clear(saturn_state *cpustate)
+{
+ cpustate->carry=!((cpustate->st>>(READ_OP_ARG(cpustate)))&1);
+ saturn_jump_after_test(cpustate);
+}
+
+INLINE void saturn_st_jump_bit_set(saturn_state *cpustate)
+{
+ cpustate->carry=(cpustate->st>>(READ_OP_ARG(cpustate)))&1;
+ saturn_jump_after_test(cpustate);
+}
+
+INLINE void saturn_hst_clear_bits(saturn_state *cpustate)
+{
+ cpustate->hst&=~(READ_OP_ARG(cpustate));
+}
+
+INLINE void saturn_hst_bits_cleared(saturn_state *cpustate)
+{
+ cpustate->carry=!(cpustate->hst&(READ_OP_ARG(cpustate)));
+ saturn_jump_after_test(cpustate);
+}
+
+/* p related */
+INLINE void saturn_exchange_p(saturn_state *cpustate)
+{
+ int nr=READ_OP_ARG(cpustate);
+ int t=cpustate->p;
+ cpustate->p=cpustate->reg[C][nr];
+ cpustate->reg[C][nr]=t;
+}
+
+INLINE void saturn_p_to_c(saturn_state *cpustate)
+{
+ int nr=READ_OP_ARG(cpustate);
+ cpustate->reg[C][nr]=cpustate->p;
+}
+
+INLINE void saturn_c_to_p(saturn_state *cpustate)
+{
+ int nr=READ_OP_ARG(cpustate);
+ cpustate->p=cpustate->reg[C][nr];
+}
+
+INLINE void saturn_dec_p(saturn_state *cpustate)
+{
+ cpustate->carry=cpustate->p==0;
+ cpustate->p=(cpustate->p-1)&0xf;
+}
+
+INLINE void saturn_inc_p(saturn_state *cpustate)
+{
+ cpustate->p=(cpustate->p+1)&0xf;
+ cpustate->carry=cpustate->p==0;
+}
+
+INLINE void saturn_load_p(saturn_state *cpustate)
+{
+ cpustate->p=READ_OP_ARG(cpustate);
+}
+
+INLINE void saturn_p_equals(saturn_state *cpustate)
+{
+ cpustate->carry=cpustate->p==(READ_OP_ARG(cpustate));
+ saturn_jump_after_test(cpustate);
+}
+
+INLINE void saturn_p_not_equals(saturn_state *cpustate)
+{
+ cpustate->carry=cpustate->p!=(READ_OP_ARG(cpustate));
+ saturn_jump_after_test(cpustate);
+}
+
+INLINE void saturn_ca_p_1(saturn_state *cpustate)
+{
+ int a=(S64_READ_A(cpustate, C))+1+cpustate->p;
+ cpustate->carry=a>=0x100000;
+ S64_WRITE_A(cpustate, C,a&0xfffff);
+}
+
+INLINE void saturn_load_reg(saturn_state *cpustate, int reg)
+{
+ int count=READ_OP_ARG(cpustate);
+ int pos=cpustate->p;
+ saturn_assert(reg>=0 && reg<9);
+ for (; count>=0; count--, pos=(pos+1)&0xf ) {
+ cpustate->reg[reg][pos]=READ_OP_ARG(cpustate);
+ }
+}
+
+INLINE void saturn_jump(saturn_state *cpustate, int adr, int jump)
+{
+ saturn_assert(adr>=0 && adr<0x100000);
+ if (jump) {
+ cpustate->pc=adr;
+ cpustate->icount-=10;
+ }
+}
+
+INLINE void saturn_call(saturn_state *cpustate, int adr)
+{
+ saturn_assert(adr>=0 && adr<0x100000);
+ saturn_push(cpustate, cpustate->pc);
+ cpustate->pc=adr;
+// cpustate->icount-=10;
+}
+
+INLINE void saturn_return(saturn_state *cpustate, int yes)
+{
+ if (yes) {
+ cpustate->pc=saturn_pop(cpustate);
+// cpustate->icount-=10;
+ }
+}
+
+INLINE void saturn_return_carry_set(saturn_state *cpustate)
+{
+ cpustate->pc=saturn_pop(cpustate);
+// cpustate->icount-=10;
+ cpustate->carry=1;
+}
+
+INLINE void saturn_return_carry_clear(saturn_state *cpustate)
+{
+ cpustate->pc=saturn_pop(cpustate);
+// cpustate->icount-=10;
+ cpustate->carry=0;
+}
+
+INLINE void saturn_return_interrupt(saturn_state *cpustate)
+{
+ LOG(( "SATURN '%s' at %05x: RTI\n", cpustate->device->tag(), cpustate->pc-2 ));
+ cpustate->in_irq=0; /* set to 1 when an IRQ is taken */
+ cpustate->pc=saturn_pop(cpustate);
+// cpustate->icount-=10;
+}
+
+INLINE void saturn_return_xm_set(saturn_state *cpustate)
+{
+ cpustate->pc=saturn_pop(cpustate);
+ cpustate->hst|=XM;
+// cpustate->icount-=10;
+}
+
+INLINE void saturn_pop_c(saturn_state *cpustate)
+{
+ S64_WRITE_A(cpustate, C,saturn_pop(cpustate));
+}
+
+INLINE void saturn_push_c(saturn_state *cpustate)
+{
+ saturn_push(cpustate, S64_READ_A(cpustate, C));
+}
+
+INLINE void saturn_indirect_jump(saturn_state *cpustate, int reg)
+{
+ saturn_assert(reg>=0 && reg<9);
+ cpustate->pc=READ_20(cpustate, S64_READ_A(cpustate, reg));
+}
+
+INLINE void saturn_equals_zero(saturn_state *cpustate, int reg, int begin, int count)
+{
+ int i, t;
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ cpustate->carry=1;
+ for (i=0; i<count; i++) {
+ t=cpustate->reg[reg][begin+i];
+ if (t!=0) { cpustate->carry=0; break; }
+ cpustate->icount-=2;
+ }
+ saturn_jump_after_test(cpustate);
+}
+
+INLINE void saturn_equals(saturn_state *cpustate, int reg, int begin, int count, int right)
+{
+ int i, t,t2;
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(right>=0 && right<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ cpustate->carry=1;
+ for (i=0; i<count; i++) {
+ t=cpustate->reg[reg][begin+i];
+ t2=cpustate->reg[right][begin+i];
+ if (t!=t2) { cpustate->carry=0; break; }
+ cpustate->icount-=2;
+ }
+ saturn_jump_after_test(cpustate);
+}
+
+INLINE void saturn_not_equals_zero(saturn_state *cpustate, int reg, int begin, int count)
+{
+ int i, t;
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ cpustate->carry=0;
+ for (i=0; i<count; i++) {
+ t=cpustate->reg[reg][begin+i];
+ if (t!=0) { cpustate->carry=1; break; }
+ cpustate->icount-=2;
+ }
+ saturn_jump_after_test(cpustate);
+}
+
+INLINE void saturn_not_equals(saturn_state *cpustate, int reg, int begin, int count, int right)
+{
+ int i, t,t2;
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(right>=0 && right<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ cpustate->carry=0;
+ for (i=0; i<count; i++) {
+ t=cpustate->reg[reg][begin+i];
+ t2=cpustate->reg[right][begin+i];
+ if (t!=t2) { cpustate->carry=1; break; }
+ cpustate->icount-=2;
+ }
+ saturn_jump_after_test(cpustate);
+}
+
+INLINE void saturn_greater(saturn_state *cpustate, int reg, int begin, int count, int right)
+{
+ int i, t,t2;
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(right>=0 && right<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ cpustate->carry=0;
+ for (i=count-1; i>=0; i--) {
+ t=cpustate->reg[reg][begin+i];
+ t2=cpustate->reg[right][begin+i];
+ if (t>t2) { cpustate->carry=1; break; }
+ if (t<t2) break;
+ cpustate->icount-=2;
+ }
+ saturn_jump_after_test(cpustate);
+}
+
+INLINE void saturn_greater_equals(saturn_state *cpustate, int reg, int begin, int count, int right)
+{
+ int i, t,t2;
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(right>=0 && right<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ cpustate->carry=1;
+ for (i=count-1; i>=0; i--) {
+ t=cpustate->reg[reg][begin+i];
+ t2=cpustate->reg[right][begin+i];
+ if (t<t2) { cpustate->carry=0; break; }
+ if (t>t2) break;
+ cpustate->icount-=2;
+ }
+ saturn_jump_after_test(cpustate);
+}
+
+INLINE void saturn_smaller_equals(saturn_state *cpustate, int reg, int begin, int count, int right)
+{
+ int i, t,t2;
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(right>=0 && right<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ cpustate->carry=1;
+ for (i=count-1; i>=0; i--) {
+ t=cpustate->reg[reg][begin+i];
+ t2=cpustate->reg[right][begin+i];
+ if (t>t2) { cpustate->carry=0; break; }
+ if (t<t2) break;
+ cpustate->icount-=2;
+ }
+ saturn_jump_after_test(cpustate);
+}
+
+INLINE void saturn_smaller(saturn_state *cpustate, int reg, int begin, int count, int right)
+{
+ int i, t,t2;
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(right>=0 && right<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ cpustate->carry=0;
+ for (i=count-1; i>=0; i--) {
+ t=cpustate->reg[reg][begin+i];
+ t2=cpustate->reg[right][begin+i];
+ if (t<t2) { cpustate->carry=1; break; }
+ if (t>t2) break;
+ cpustate->icount-=2;
+ }
+ saturn_jump_after_test(cpustate);
+}
+
+INLINE void saturn_jump_bit_clear(saturn_state *cpustate, int reg)
+{
+ int op=READ_OP_ARG(cpustate);
+ saturn_assert(reg>=0 && reg<9);
+ cpustate->carry=!((cpustate->reg[reg][op>>2]>>(op&3))&1);
+ saturn_jump_after_test(cpustate);
+}
+
+INLINE void saturn_jump_bit_set(saturn_state *cpustate, int reg)
+{
+ int op=READ_OP_ARG(cpustate);
+ saturn_assert(reg>=0 && reg<9);
+ cpustate->carry=(cpustate->reg[reg][op>>2]>>(op&3))&1;
+ saturn_jump_after_test(cpustate);
+}
+
+INLINE void saturn_load_pc(saturn_state *cpustate, int reg)
+{
+ saturn_assert(reg>=0 && reg<9);
+ cpustate->pc=S64_READ_A(cpustate, reg);
+}
+
+INLINE void saturn_store_pc(saturn_state *cpustate, int reg)
+{
+ saturn_assert(reg>=0 && reg<9);
+ S64_WRITE_A(cpustate, reg,cpustate->pc);
+}
+
+INLINE void saturn_exchange_pc(saturn_state *cpustate, int reg)
+{
+ int temp=cpustate->pc;
+ saturn_assert(reg>=0 && reg<9);
+ cpustate->pc=S64_READ_A(cpustate, reg);
+ S64_WRITE_A(cpustate, reg, temp);
+}
+
+/*************************************************************************************
+ address register related
+*************************************************************************************/
+INLINE void saturn_load_adr(saturn_state *cpustate, int reg, int nibbles)
+{
+ saturn_assert(reg>=0 && reg<2);
+ saturn_assert(nibbles==2 || nibbles==4 || nibbles==5);
+ switch (nibbles) {
+ case 5:
+ cpustate->d[reg]=READ_OP_ARG20(cpustate);
+ break;
+ case 4:
+ cpustate->d[reg]=(cpustate->d[reg]&0xf0000)|READ_OP_ARG16(cpustate);
+ break;
+ case 2:
+ cpustate->d[reg]=(cpustate->d[reg]&0xfff00)|READ_OP_ARG8(cpustate);
+ break;
+ }
+}
+
+INLINE void saturn_add_adr(saturn_state *cpustate, int reg)
+{
+ int t=cpustate->d[reg]+READ_OP_ARG(cpustate)+1;
+ saturn_assert(reg>=0 && reg<2);
+ cpustate->d[reg]=t&0xfffff;
+ cpustate->carry=t>=0x100000;
+}
+
+INLINE void saturn_sub_adr(saturn_state *cpustate, int reg)
+{
+ int t=cpustate->d[reg]-READ_OP_ARG(cpustate)-1;
+ saturn_assert(reg>=0 && reg<2);
+ cpustate->d[reg]=t&0xfffff;
+ cpustate->carry=t<0;
+}
+
+INLINE void saturn_adr_to_reg(saturn_state *cpustate, int adr, int reg)
+{
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(adr>=0 && adr<2);
+ S64_WRITE_A(cpustate, reg,cpustate->d[adr]);
+}
+
+INLINE void saturn_reg_to_adr(saturn_state *cpustate, int reg, int adr)
+{
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(adr>=0 && adr<2);
+ cpustate->d[adr]=S64_READ_A(cpustate, reg);
+}
+
+INLINE void saturn_adr_to_reg_word(saturn_state *cpustate, int adr, int reg)
+{
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(adr>=0 && adr<2);
+ S64_WRITE_WORD(cpustate, reg,cpustate->d[adr]&0xffff);
+}
+
+INLINE void saturn_reg_to_adr_word(saturn_state *cpustate, int reg, int adr)
+{
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(adr>=0 && adr<2);
+ cpustate->d[adr]=(cpustate->d[adr]&0xf0000)|S64_READ_WORD(cpustate, reg);
+}
+
+INLINE void saturn_exchange_adr_reg(saturn_state *cpustate, int adr, int reg)
+{
+ int temp=cpustate->d[adr];
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(adr>=0 && adr<2);
+ cpustate->d[adr]=S64_READ_A(cpustate, reg);
+ S64_WRITE_A(cpustate, reg,temp);
+}
+
+INLINE void saturn_exchange_adr_reg_word(saturn_state *cpustate, int adr, int reg)
+{
+ int temp=cpustate->d[adr]&0xffff;
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(adr>=0 && adr<2);
+ cpustate->d[adr]=(cpustate->d[adr]&0xf0000)|S64_READ_WORD(cpustate, reg);
+ S64_WRITE_WORD(cpustate, reg,temp);
+}
+
+INLINE void saturn_load_nibbles(saturn_state *cpustate, int reg, int begin, int count, int adr)
+{
+ int i;
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(adr>=0 && adr<2);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ for (i=0; i<count; i++) {
+ cpustate->reg[reg][begin+i]=READ_NIBBLE(cpustate, cpustate->d[adr]+i);
+ cpustate->icount-=2;
+ }
+}
+
+INLINE void saturn_store_nibbles(saturn_state *cpustate, int reg, int begin, int count, int adr)
+{
+ int i;
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(adr>=0 && adr<2);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ for (i=0; i<count; i++) {
+ WRITE_NIBBLE(cpustate,(cpustate->d[adr]+i)&0xfffff,cpustate->reg[reg][begin+i]);
+ cpustate->icount-=2;
+ }
+}
+
+INLINE void saturn_clear_bit(saturn_state *cpustate, int reg)
+{
+ int arg=READ_OP_ARG(cpustate);
+ saturn_assert(reg>=0 && reg<9);
+ cpustate->reg[reg][arg>>2]&=~(1<<(arg&3));
+}
+
+INLINE void saturn_set_bit(saturn_state *cpustate, int reg)
+{
+ int arg=READ_OP_ARG(cpustate);
+ saturn_assert(reg>=0 && reg<9);
+ cpustate->reg[reg][arg>>2]|=1<<(arg&3);
+}
+
+/****************************************************************************
+ clear opers
+ ****************************************************************************/
+INLINE void saturn_clear(saturn_state *cpustate, int reg, int begin, int count)
+{
+ int i;
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ for (i=0; i<count; i++) {
+ cpustate->reg[reg][begin+i]=0;
+ cpustate->icount-=2;
+ }
+}
+
+/****************************************************************************
+ exchange opers
+ ****************************************************************************/
+INLINE void saturn_exchange(saturn_state *cpustate, int left, int begin, int count, int right)
+{
+ int i;
+ SaturnNib temp;
+ saturn_assert(left>=0 && left<9);
+ saturn_assert(right>=0 && right<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ for (i=0; i<count; i++) {
+ temp=cpustate->reg[left][begin+i];
+ cpustate->reg[left][begin+i]=cpustate->reg[right][begin+i];
+ cpustate->reg[right][begin+i]=temp;
+ cpustate->icount-=2;
+ }
+}
+
+/****************************************************************************
+ copy opers
+ ****************************************************************************/
+INLINE void saturn_copy(saturn_state *cpustate, int dest, int begin, int count, int src)
+{
+ int i;
+ saturn_assert(dest>=0 && dest<9);
+ saturn_assert(src>=0 && src<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ for (i=0; i<count; i++) {
+ cpustate->reg[dest][begin+i]=cpustate->reg[src][begin+i];
+ cpustate->icount-=2;
+ }
+}
+
+/****************************************************************************
+ add opers
+ ****************************************************************************/
+INLINE void saturn_add(saturn_state *cpustate, int reg, int begin, int count, int right)
+{
+ int i, t;
+ int base=cpustate->decimal?10:16;
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(right>=0 && right<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ cpustate->carry=0;
+ for (i=0; i<count; i++) {
+ t=cpustate->reg[reg][begin+i];
+ t+=cpustate->reg[right][begin+i];
+ t+=cpustate->carry;
+ if (t>=base) {
+ cpustate->carry=1;
+ t-=base;
+ }
+ else cpustate->carry=0;
+ saturn_assert(t>=0); saturn_assert(t<base);
+ cpustate->reg[reg][begin+i]=t&0xf;
+ cpustate->icount-=2;
+ }
+}
+
+INLINE void saturn_add_const(saturn_state *cpustate, int reg, int begin, int count, SaturnNib right)
+{
+ int i, t;
+ int base=cpustate->decimal?10:16;
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ saturn_assert(count>1 || !cpustate->decimal); /* SATURN bug */
+ for (i=0; i<count; i++) {
+ t=cpustate->reg[reg][begin+i];
+ t+=(right&0xf);
+ right>>=4;
+ if (t>=base) {
+ right++;
+ t-=base;
+ }
+ saturn_assert(t>=0); saturn_assert(t<base);
+ cpustate->reg[reg][begin+i]=t&0xf;
+ cpustate->icount-=2;
+ if (!right) break;
+ }
+ cpustate->carry=right>0;
+}
+
+/****************************************************************************
+ sub opers
+ ****************************************************************************/
+INLINE void saturn_sub(saturn_state *cpustate, int reg, int begin, int count, int right)
+{
+ int i, t;
+ int base=cpustate->decimal?10:16;
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(right>=0 && right<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ cpustate->carry=0;
+ for (i=0; i<count; i++) {
+ t=cpustate->reg[reg][begin+i];
+ t-=cpustate->reg[right][begin+i];
+ t-=cpustate->carry;
+ if (t<0) {
+ cpustate->carry=1;
+ t+=base;
+ }
+ else cpustate->carry=0;
+ saturn_assert(t>=0); saturn_assert(t<base);
+ cpustate->reg[reg][begin+i]=t&0xf;
+ cpustate->icount-=2;
+ }
+}
+
+INLINE void saturn_sub_const(saturn_state *cpustate, int reg, int begin, int count, int right)
+{
+ int i, t;
+ int base=cpustate->decimal?10:16;
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ saturn_assert(count>1 || !cpustate->decimal); /* SATURN bug */
+ for (i=0; i<count; i++) {
+ t=cpustate->reg[reg][begin+i];
+ t-=(right&0xf);
+ right>>=4;
+ if (t<0) {
+ right++;
+ t+=base;
+ }
+ saturn_assert(t>=0); saturn_assert(t<base);
+ cpustate->reg[reg][begin+i]=t&0xf;
+ cpustate->icount-=2;
+ if (!right) break;
+ }
+ cpustate->carry=right>0;
+}
+
+/****************************************************************************
+ sub2 opers (a=b-a)
+ ****************************************************************************/
+INLINE void saturn_sub2(saturn_state *cpustate, int reg, int begin, int count, int right)
+{
+ int i, t;
+ int base=cpustate->decimal?10:16;
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(right>=0 && right<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ cpustate->carry=0;
+ for (i=0; i<count; i++) {
+ t=cpustate->reg[right][begin+i];
+ t-=cpustate->reg[reg][begin+i];
+ t-=cpustate->carry;
+ if (t<0) {
+ cpustate->carry=1;
+ t+=base;
+ }
+ else cpustate->carry=0;
+ saturn_assert(t>=0); saturn_assert(t<base);
+ cpustate->reg[reg][begin+i]=t&0xf;
+ cpustate->icount-=2;
+ }
+}
+
+/****************************************************************************
+ increment opers
+ ****************************************************************************/
+INLINE void saturn_increment(saturn_state *cpustate, int reg, int begin, int count)
+{
+ int i, t=0;
+ int base=cpustate->decimal?10:16;
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ for (i=0; i<count; i++) {
+ cpustate->icount-=2;
+ t=cpustate->reg[reg][begin+i];
+ t++;
+ if (t>=base) cpustate->reg[reg][begin+i]=t-base;
+ else { cpustate->reg[reg][begin+i]=t; break; }
+ }
+ cpustate->carry=t>=base;
+}
+
+/****************************************************************************
+ decrement opers
+ ****************************************************************************/
+INLINE void saturn_decrement(saturn_state *cpustate, int reg, int begin, int count)
+{
+ int i, t=0;
+ int base=cpustate->decimal?10:16;
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ for (i=0; i<count; i++) {
+ cpustate->icount-=2;
+ t=cpustate->reg[reg][begin+i];
+ t--;
+ if (t<0) cpustate->reg[reg][begin+i]=t+base;
+ else { cpustate->reg[reg][begin+i]=t; break; }
+ }
+ cpustate->carry=t<0;
+}
+
+/****************************************************************************
+ invert (1 complement) opers
+ ****************************************************************************/
+INLINE void saturn_invert(saturn_state *cpustate, int reg, int begin, int count)
+{
+ int i;
+ int max=cpustate->decimal?9:15;
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ cpustate->carry=0;
+ for (i=0; i<count; i++) {
+ cpustate->reg[reg][begin+i]=(max-cpustate->reg[reg][begin+i])&0xf;
+ cpustate->icount-=2;
+ }
+}
+
+/****************************************************************************
+ negate (2 complement) opers
+ ****************************************************************************/
+INLINE void saturn_negate(saturn_state *cpustate, int reg, int begin, int count)
+{
+ int i, n, c;
+ int max=cpustate->decimal?9:15;
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ c=1;
+ cpustate->carry=0;
+ for (i=0; i<count; i++) {
+ n=cpustate->reg[reg][begin+i];
+ if (n) cpustate->carry=1;
+ n=max+c-n;
+ if (n>max) n-=max+1;
+ else c=0;
+ saturn_assert(n>=0); saturn_assert(n<=max);
+ cpustate->reg[reg][begin+i]=n&0xf;
+ cpustate->icount-=2;
+ }
+}
+
+/****************************************************************************
+ or opers
+ ****************************************************************************/
+INLINE void saturn_or(saturn_state *cpustate, int dest, int begin, int count, int src)
+{
+ int i;
+ saturn_assert(dest>=0 && dest<9);
+ saturn_assert(src>=0 && src<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ for (i=0; i<count; i++) {
+ cpustate->reg[dest][begin+i]|=cpustate->reg[src][begin+i];
+ cpustate->icount-=2;
+ }
+}
+
+/****************************************************************************
+ and opers
+ ****************************************************************************/
+INLINE void saturn_and(saturn_state *cpustate, int dest, int begin, int count, int src)
+{
+ int i;
+ saturn_assert(dest>=0 && dest<9);
+ saturn_assert(src>=0 && src<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ for (i=0; i<count; i++) {
+ cpustate->reg[dest][begin+i]&=cpustate->reg[src][begin+i];
+ cpustate->icount-=2;
+ }
+}
+
+/****************************************************************************
+ shift nibbles left opers
+ ****************************************************************************/
+INLINE void saturn_shift_nibble_left(saturn_state *cpustate, int reg, int begin, int count)
+{
+ int i;
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ if (cpustate->reg[reg][begin+count-1]) cpustate->hst|=SB;
+ for (i=count-1; i>=1; i--) {
+ cpustate->reg[reg][begin+i]=cpustate->reg[reg][begin+i-1];
+ cpustate->icount-=2;
+ }
+ cpustate->reg[reg][begin]=0;
+ cpustate->icount-=2;
+}
+
+/****************************************************************************
+ shift nibbles right opers
+ ****************************************************************************/
+INLINE void saturn_shift_nibble_right(saturn_state *cpustate, int reg, int begin, int count)
+{
+ int i;
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ if (cpustate->reg[reg][begin]) cpustate->hst|=SB;
+ for (i=1; i<count; i++) {
+ cpustate->reg[reg][begin+i-1]=cpustate->reg[reg][begin+i];
+ cpustate->icount-=2;
+ }
+ cpustate->reg[reg][begin+count-1]=0;
+ cpustate->icount-=2;
+}
+
+
+/****************************************************************************
+ rotate nibbles left opers
+ ****************************************************************************/
+INLINE void saturn_rotate_nibble_left_w(saturn_state *cpustate, int reg)
+{
+ int i, x=cpustate->reg[reg][15];
+ saturn_assert(reg>=0 && reg<9);
+ for (i=15; i>=1; i--) {
+ cpustate->reg[reg][i]=cpustate->reg[reg][i-1];
+ cpustate->icount-=2;
+ }
+ cpustate->reg[reg][0]=x;
+ cpustate->icount-=2;
+}
+
+/****************************************************************************
+ rotate nibbles right opers
+ ****************************************************************************/
+INLINE void saturn_rotate_nibble_right_w(saturn_state *cpustate, int reg)
+{
+ int i, x=cpustate->reg[reg][0];
+ saturn_assert(reg>=0 && reg<9);
+ for (i=1; i<16; i++) {
+ cpustate->reg[reg][i-1]=cpustate->reg[reg][i];
+ cpustate->icount-=2;
+ }
+ cpustate->reg[reg][15]=x;
+ if (x) cpustate->hst|=SB;
+ cpustate->icount-=2;
+}
+
+
+/****************************************************************************
+ shift right opers
+ ****************************************************************************/
+INLINE void saturn_shift_right(saturn_state *cpustate, int reg, int begin, int count)
+{
+ int i, t, c=0;
+ saturn_assert(reg>=0 && reg<9);
+ saturn_assert(begin>=0 && count>=0 && begin+count<=16);
+ for (i=count-1; i>=0; i--) {
+ t=cpustate->reg[reg][begin+i];
+ t|=(c<<4);
+ c=t&1;
+ cpustate->reg[reg][begin+i]=t>>1;
+ cpustate->icount-=2;
+ }
+ if (c) cpustate->hst|=SB;
+ cpustate->icount-=2;
+}
diff --git a/trunk/src/emu/cpu/saturn/sattable.c b/trunk/src/emu/cpu/saturn/sattable.c
new file mode 100644
index 00000000000..902a698aad7
--- /dev/null
+++ b/trunk/src/emu/cpu/saturn/sattable.c
@@ -0,0 +1,1037 @@
+static const int adr_a_begin[]={
+-1, -1, BEGIN_XS, BEGIN_X, BEGIN_S, BEGIN_M, BEGIN_B, BEGIN_W,
+-1, -1, -1, -1, -1, -1, -1, -1,
+};
+
+static const int adr_a_count[]={
+-1, -1, COUNT_XS, COUNT_X, COUNT_S, COUNT_M, COUNT_B, COUNT_W,
+-1, -1, -1, -1, -1, -1, -1, -1,
+};
+
+static const int adr_b_begin[]={
+-1, -1, -1, -1, -1, -1, -1, -1,
+-1, -1, BEGIN_XS, BEGIN_X, BEGIN_S, BEGIN_M, BEGIN_B, BEGIN_W,
+};
+
+static const int adr_b_count[]={
+-1, -1, -1, -1, -1, -1, -1, -1,
+-1, -1, COUNT_XS, COUNT_X, COUNT_S, COUNT_M, COUNT_B, COUNT_W,
+};
+
+static const int adr_af_begin[]={
+-1, -1, BEGIN_XS, BEGIN_X, BEGIN_S, BEGIN_M, BEGIN_B, BEGIN_W,
+-1, -1, -1, -1, -1, -1, -1, BEGIN_A
+};
+
+static const int adr_af_count[]={
+-1, -1, COUNT_XS, COUNT_X, COUNT_S, COUNT_M, COUNT_B, COUNT_W,
+-1, -1, -1, -1, -1, -1, -1, COUNT_A
+};
+
+static const int reg_left[] ={A,B,C,D, B,C,A,C, I,I,I,I, I,I,I,I};
+static const int reg_right[]={B,C,A,C, A,B,C,D, I,I,I,I, I,I,I,I};
+static const int add_left[] ={A,B,C,D, I,I,I,I, B,C,A,C, I,I,I,I};
+static const int add_right[]={B,C,A,C, I,I,I,I, A,B,C,D, I,I,I,I};
+static const int sub_left[] ={A,B,C,D, I,I,I,I, B,C,A,C, A,B,C,D};
+static const int sub_right[]={B,C,A,C, I,I,I,I, A,B,C,D, B,C,A,C};
+
+static void saturn_invalid3( saturn_state *cpustate, int op1, int op2, int op3 )
+{
+ logerror( "SATURN '%s' invalid opcode %x%x%x at %05x\n",
+ cpustate->device->tag(), op1, op2, op3, cpustate->pc-3 );
+}
+
+static void saturn_invalid4( saturn_state *cpustate, int op1, int op2, int op3, int op4 )
+{
+ logerror( "SATURN '%s' invalid opcode %x%x%x%x at %05x\n",
+ cpustate->device->tag(), op1, op2, op3, op4, cpustate->pc-4 );
+}
+
+static void saturn_invalid5( saturn_state *cpustate, int op1, int op2, int op3, int op4, int op5 )
+{
+ logerror( "SATURN '%s' invalid opcode %x%x%x%x%x at %05x\n",
+ cpustate->device->tag(), op1, op2, op3, op4, op5, cpustate->pc-5 );
+}
+
+static void saturn_invalid6( saturn_state *cpustate, int op1, int op2, int op3, int op4, int op5, int op6 )
+{
+ logerror( "SATURN '%s' invalid opcode %x%x%x%x%x%x at %05x\n",
+ cpustate->device->tag(), op1, op2, op3, op4, op5, op6, cpustate->pc-6 );
+}
+
+
+INLINE void saturn_instruction_0e(saturn_state *cpustate)
+{
+ int reg, adr;
+
+ switch(adr=READ_OP(cpustate)) {
+ case 0:
+ switch(reg=READ_OP(cpustate)){
+ case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
+ saturn_and(cpustate, reg_left[reg], cpustate->p, 1, reg_right[reg]);
+ break; //A=A&B p
+ case 8: case 9: case 0xa: case 0xb: case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_or(cpustate, reg_left[reg&7], cpustate->p, 1, reg_right[reg&7]);
+ break; //A=A!B p
+ }
+ break;
+ case 1:
+ switch(reg=READ_OP(cpustate)){
+ case 0: case 1: case 2: case 3:case 4: case 5: case 6: case 7:
+ saturn_and(cpustate, reg_left[reg], 0, cpustate->p+1, reg_right[reg]);
+ break; //A=A&B wp
+ case 8: case 9: case 0xa: case 0xb: case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_or(cpustate, reg_left[reg&7], 0, cpustate->p+1, reg_right[reg&7]);
+ break; //A=A!B wp
+ }
+ break;
+ case 2: case 3: case 4: case 5: case 6: case 7: case 0xf:
+ switch(reg=READ_OP(cpustate)){
+ case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
+ saturn_and(cpustate, reg_left[reg], adr_af_begin[adr], adr_af_count[adr], reg_right[reg]);
+ break; //A=A&B xs
+ case 8: case 9: case 0xa: case 0xb: case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_or(cpustate, reg_left[reg&7], adr_af_begin[adr], adr_af_count[adr], reg_right[reg&7]);
+ break; //A=A!B xs
+ }
+ break;
+ default:
+ saturn_invalid3( cpustate, 0, 0xe, adr );
+ break;
+ }
+}
+
+static void saturn_instruction_1(saturn_state *cpustate)
+{
+ int reg, adr, oper;
+
+ switch (adr=READ_OP(cpustate)) {
+ case 0:
+ switch (reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3: case 4:
+ saturn_copy(cpustate, R0+reg, BEGIN_W, COUNT_W, A);
+ break; // r0=a w
+ case 8: case 9: case 0xa: case 0xb: case 0xc:
+ saturn_copy(cpustate, R0+(reg&7), BEGIN_W, COUNT_W, C);
+ break; // r0=c w
+ default:
+ saturn_invalid3( cpustate, 1, adr, reg );
+ break;
+ }
+ break;
+ case 1:
+ switch (reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3: case 4:
+ saturn_copy(cpustate, A, BEGIN_W, COUNT_W, R0+reg);
+ break; // a=r0 w
+ case 8: case 9: case 0xa: case 0xb: case 0xc:
+ saturn_copy(cpustate, C, BEGIN_W, COUNT_W, R0+(reg&7));
+ break; // c=r0 w
+ default:
+ saturn_invalid3( cpustate, 1, adr, reg );
+ break;
+ }
+ break;
+ case 2:
+ switch (reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3: case 4:
+ saturn_exchange(cpustate, A, BEGIN_W, COUNT_W, R0+reg);
+ break; // ar0ex w
+ case 8: case 9: case 0xa: case 0xb: case 0xc:
+ saturn_exchange(cpustate, C, BEGIN_W, COUNT_W, R0+(reg&7));
+ break; // cr0ex w
+ default:
+ saturn_invalid3( cpustate, 2, adr, reg );
+ break;
+ }
+ break;
+ case 3:
+ switch (READ_OP(cpustate)) {
+ case 0: saturn_reg_to_adr(cpustate, A,0);break;
+ case 1: saturn_reg_to_adr(cpustate, A,1);break;
+ case 2: saturn_exchange_adr_reg(cpustate, 0,A);break;
+ case 3: saturn_exchange_adr_reg(cpustate, 1,A);break;
+ case 4: saturn_reg_to_adr(cpustate, C,0);break;
+ case 5: saturn_reg_to_adr(cpustate, C,1);break;
+ case 6: saturn_exchange_adr_reg(cpustate, 0,C);break;
+ case 7: saturn_exchange_adr_reg(cpustate, 1,C);break;
+ case 8: saturn_reg_to_adr_word(cpustate, A,0);break;
+ case 9: saturn_reg_to_adr_word(cpustate, A,1);break;
+ case 0xa: saturn_exchange_adr_reg_word(cpustate, 0,A);break;
+ case 0xb: saturn_exchange_adr_reg_word(cpustate, 1,A);break;
+ case 0xc: saturn_reg_to_adr_word(cpustate, C,0);break;
+ case 0xd: saturn_reg_to_adr_word(cpustate, C,1);break;
+ case 0xe: saturn_exchange_adr_reg_word(cpustate, 0,C);break;
+ case 0xf: saturn_exchange_adr_reg_word(cpustate, 1,C);break;
+ }
+ break;
+ case 4:
+ switch (READ_OP(cpustate)) {
+ case 0: saturn_store_nibbles(cpustate, A, BEGIN_A, COUNT_A, 0); break;
+ case 1: saturn_store_nibbles(cpustate, A, BEGIN_A, COUNT_A, 1); break;
+ case 2: saturn_load_nibbles(cpustate, A, BEGIN_A, COUNT_A, 0); break;
+ case 3: saturn_load_nibbles(cpustate, A, BEGIN_A, COUNT_A, 1); break;
+ case 4: saturn_store_nibbles(cpustate, C, BEGIN_A, COUNT_A, 0); break;
+ case 5: saturn_store_nibbles(cpustate, C, BEGIN_A, COUNT_A, 1); break;
+ case 6: saturn_load_nibbles(cpustate, C, BEGIN_A, COUNT_A, 0); break;
+ case 7: saturn_load_nibbles(cpustate, C, BEGIN_A, COUNT_A, 1); break;
+ case 8: saturn_store_nibbles(cpustate, A, BEGIN_B, COUNT_B, 0); break;
+ case 9: saturn_store_nibbles(cpustate, A, BEGIN_B, COUNT_B, 1); break;
+ case 0xa: saturn_load_nibbles(cpustate, A, BEGIN_B, COUNT_B, 0); break;
+ case 0xb: saturn_load_nibbles(cpustate, A, BEGIN_B, COUNT_B, 1); break;
+ case 0xc: saturn_store_nibbles(cpustate, C, BEGIN_B, COUNT_B, 0); break;
+ case 0xd: saturn_store_nibbles(cpustate, C, BEGIN_B, COUNT_B, 1); break;
+ case 0xe: saturn_load_nibbles(cpustate, C, BEGIN_B, COUNT_B, 0); break;
+ case 0xf: saturn_load_nibbles(cpustate, C, BEGIN_B, COUNT_B, 1); break;
+ }
+ break;
+ case 5:
+ switch (oper=READ_OP(cpustate)) {
+ case 0: case 1: case 4: case 5:
+ switch (adr=READ_OP(cpustate)) {
+ case 0:
+ saturn_store_nibbles(cpustate, oper&4?C:A,cpustate->p,1,oper&1);
+ break;
+ case 1:
+ saturn_store_nibbles(cpustate, oper&4?C:A,0,cpustate->p+1,oper&1);
+ break;
+ case 2: case 3: case 4: case 5: case 6: case 7:
+ saturn_store_nibbles(cpustate, oper&4?C:A,adr_a_begin[adr],adr_a_count[adr],oper&1);
+ break;
+ default:
+ saturn_invalid4( cpustate, 1, 5, oper, adr );
+ break;
+ }
+ break;
+ case 2: case 3: case 6: case 7:
+ switch (adr=READ_OP(cpustate)) {
+ case 0:
+ saturn_load_nibbles(cpustate, oper&4?C:A,cpustate->p,1,oper&1);
+ break;
+ case 1:
+ saturn_load_nibbles(cpustate, oper&4?C:A,0,cpustate->p+1,oper&1);
+ break;
+ case 2: case 3: case 4: case 5: case 6: case 7:
+ saturn_load_nibbles(cpustate, oper&4?C:A,adr_a_begin[adr],adr_a_count[adr],oper&1);
+ break;
+ default:
+ saturn_invalid4( cpustate, 1, 5, oper, adr );
+ break;
+ }
+ break;
+ case 8: saturn_store_nibbles(cpustate, A, 0, READ_OP(cpustate)+1, 0); break;
+ case 9: saturn_store_nibbles(cpustate, A, 0, READ_OP(cpustate)+1, 1); break;
+ case 0xa: saturn_load_nibbles(cpustate, A, 0, READ_OP(cpustate)+1, 0); break;
+ case 0xb: saturn_load_nibbles(cpustate, A, 0, READ_OP(cpustate)+1, 1); break;
+ case 0xc: saturn_store_nibbles(cpustate, C, 0, READ_OP(cpustate)+1, 0); break;
+ case 0xd: saturn_store_nibbles(cpustate, C, 0, READ_OP(cpustate)+1, 1); break;
+ case 0xe: saturn_load_nibbles(cpustate, C, 0, READ_OP(cpustate)+1, 0); break;
+ case 0xf: saturn_load_nibbles(cpustate, C, 0, READ_OP(cpustate)+1, 1); break;
+ }
+ break;
+ case 6: saturn_add_adr(cpustate, 0);break;
+ case 7: saturn_add_adr(cpustate, 1);break;
+ case 8: saturn_sub_adr(cpustate, 0);break;
+ case 9: saturn_load_adr(cpustate, 0,2);break;
+ case 0xa: saturn_load_adr(cpustate, 0,4);break;
+ case 0xb: saturn_load_adr(cpustate, 0,5);break;
+ case 0xc: saturn_sub_adr(cpustate, 1);break;
+ case 0xd: saturn_load_adr(cpustate, 1,2);break;
+ case 0xe: saturn_load_adr(cpustate, 1,4);break;
+ case 0xf: saturn_load_adr(cpustate, 1,5);break;
+ }
+}
+
+static void saturn_instruction_80(saturn_state *cpustate)
+{
+ int op;
+ switch(READ_OP(cpustate)) {
+ case 0: saturn_out_cs(cpustate);break;
+ case 1: saturn_out_c(cpustate);break;
+ case 2: saturn_in(cpustate, A);break;
+ case 3: saturn_in(cpustate, C);break;
+ case 4: saturn_mem_unconfig(cpustate);break;
+ case 5: saturn_mem_config(cpustate);break;
+ case 6: saturn_mem_id(cpustate);break;
+ case 7: saturn_shutdown(cpustate);break;
+ case 8:
+ switch(READ_OP(cpustate)) {
+ case 0: saturn_interrupt_on(cpustate);break;
+ case 1:
+ switch(op=READ_OP(cpustate)) {
+ case 0: saturn_reset_interrupt(cpustate);break;
+ default: saturn_invalid5( cpustate, 8, 0, 8, 1, op ); break;
+ }
+ break;
+ case 2: saturn_load_reg(cpustate, A);break; //la
+ case 3: saturn_bus_command_b(cpustate);break;
+ case 4: saturn_clear_bit(cpustate, A);break; // abit=0
+ case 5: saturn_set_bit(cpustate, A);break; // abit=1
+ case 6: saturn_jump_bit_clear(cpustate, A);break;
+ case 7: saturn_jump_bit_set(cpustate, A);break;
+ case 8: saturn_clear_bit(cpustate, C);break; // cbit=0
+ case 9: saturn_set_bit(cpustate, C);break; // cbit=1
+ case 0xa: saturn_jump_bit_clear(cpustate, C);break;
+ case 0xb: saturn_jump_bit_set(cpustate, C);break;
+ case 0xc: saturn_indirect_jump(cpustate, A);break;
+ case 0xd: saturn_bus_command_d(cpustate);break;
+ case 0xe: saturn_indirect_jump(cpustate, C);break;
+ case 0xf: saturn_interrupt_off(cpustate);break;
+ }
+ break;
+ case 9: saturn_ca_p_1(cpustate);break;//C+P+1
+ case 0xa: saturn_mem_reset(cpustate);break;
+ case 0xb: saturn_bus_command_b(cpustate);break;
+ case 0xc: saturn_p_to_c(cpustate);break;
+ case 0xd: saturn_c_to_p(cpustate);break;
+ case 0xe: saturn_serial_request(cpustate);break;
+ case 0xf: saturn_exchange_p(cpustate);break;
+ }
+}
+
+static void saturn_instruction_81a(saturn_state *cpustate)
+{
+ int reg, adr,op;
+ switch(adr=READ_OP(cpustate)) {
+ case 0:
+ switch(op=READ_OP(cpustate)) {
+ case 0:
+ switch(reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3: case 4:
+ saturn_copy(cpustate, R0+reg,cpustate->p,1,A);
+ break; //r0=a p
+ case 8: case 9: case 0xa: case 0xb: case 0xc:
+ saturn_copy(cpustate, R0+(reg&7),cpustate->p,1,C);
+ break; //r0=c p
+ default:
+ saturn_invalid6( cpustate, 8, 1, 0xa, adr, op, reg);
+ break;
+ }
+ break;
+ case 1:
+ switch(reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3: case 4:
+ saturn_copy(cpustate, A,cpustate->p,1,R0+reg);
+ break; //a=r0 p
+ case 8: case 9: case 0xa: case 0xb: case 0xc:
+ saturn_copy(cpustate, C,cpustate->p,1,R0+(reg&7));
+ break; //c=r0 p
+ default:
+ saturn_invalid6( cpustate, 8, 1, 0xa, adr, op, reg);
+ break;
+ }
+ break;
+ case 2:
+ switch (reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3: case 4:
+ saturn_exchange(cpustate, A, cpustate->p,1,R0+reg);
+ break; // ar0ex p
+ case 8: case 9: case 0xa: case 0xb: case 0xc:
+ saturn_exchange(cpustate, C, cpustate->p,1,R0+(reg&7));
+ break; // cr0ex p
+ default:
+ saturn_invalid6( cpustate, 8, 1, 0xa, adr, op, reg);
+ break;
+ }
+ break;
+ default:
+ saturn_invalid5( cpustate, 8, 1, 0xa, adr, op );
+ break;
+ }
+ break;
+ case 1:
+ switch(op=READ_OP(cpustate)) {
+ case 0:
+ switch(reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3: case 4:
+ saturn_copy(cpustate, R0+reg,0,cpustate->p+1,A);
+ break; //r0=a wp
+ case 8: case 9: case 0xa: case 0xb: case 0xc:
+ saturn_copy(cpustate, R0+(reg&7),0,cpustate->p+1,C);
+ break; //r0=c wp
+ default:
+ saturn_invalid6( cpustate, 8, 1, 0xa, adr, op, reg);
+ break;
+ }
+ break;
+ case 1:
+ switch(reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3: case 4:
+ saturn_copy(cpustate, A,0,cpustate->p+1,R0+reg);
+ break; //a=r0 wp
+ case 8: case 9: case 0xa: case 0xb: case 0xc:
+ saturn_copy(cpustate, C,0,cpustate->p+1,R0+(reg&7));
+ break; //c=r0 wp
+ default:
+ saturn_invalid6( cpustate, 8, 1, 0xa, adr, op, reg);
+ break;
+ }
+ break;
+ case 2:
+ switch (reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3: case 4:
+ saturn_exchange(cpustate, A, 0, cpustate->p+1, R0+reg);
+ break; // ar0ex wp
+ case 8: case 9: case 0xa: case 0xb: case 0xc:
+ saturn_exchange(cpustate, C, 0, cpustate->p+1, R0+(reg&7));
+ break; // cr0ex wp
+ default:
+ saturn_invalid6( cpustate, 8, 1, 0xa, adr, op, reg);
+ break;
+ }
+ break;
+ default:
+ saturn_invalid5( cpustate, 8, 1, 0xa, adr, op );
+ break;
+ }
+ break;
+ case 2: case 3: case 4: case 5: case 6: case 7: case 0xf:
+ switch(op=READ_OP(cpustate)) {
+ case 0:
+ switch(reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3: case 4:
+ saturn_copy(cpustate, R0+reg,adr_af_begin[adr],adr_af_count[adr],A);
+ break; //r0=a xs
+ case 8: case 9: case 0xa: case 0xb: case 0xc:
+ saturn_copy(cpustate, R0+(reg&7),adr_af_begin[adr], adr_af_count[adr],C);
+ break; //r0=c xs
+ default:
+ saturn_invalid6( cpustate, 8, 1, 0xa, adr, op, reg);
+ break;
+ }
+ break;
+ case 1:
+ switch(reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3: case 4:
+ saturn_copy(cpustate, A,adr_af_begin[adr],adr_af_count[adr],R0+reg);
+ break; //a=r0 xs
+ case 8: case 9: case 0xa: case 0xb: case 0xc:
+ saturn_copy(cpustate, C,adr_af_begin[adr],adr_af_count[adr],R0+(reg&7));
+ break; //c=r0 xs
+ default:
+ saturn_invalid6( cpustate, 8, 1, 0xa, adr, op, reg);
+ break;
+ }
+ break;
+ case 2:
+ switch (reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3: case 4:
+ saturn_exchange(cpustate, A, adr_af_begin[adr], adr_af_count[adr], R0+reg);
+ break; // ar0ex xs
+ case 8: case 9: case 0xa: case 0xb: case 0xc:
+ saturn_exchange(cpustate, C, adr_af_begin[adr], adr_af_count[adr], R0+(reg&7));
+ break; // cr0ex xs
+ default:
+ saturn_invalid6( cpustate, 8, 1, 0xa, adr, op, reg);
+ break;
+ }
+ break;
+ default:
+ saturn_invalid5( cpustate, 8, 1, 0xa, adr, op );
+ break;
+ }
+ break;
+ default:
+ saturn_invalid4( cpustate, 8, 1, 0xa, adr );
+ break;
+ }
+}
+
+static void saturn_instruction_81(saturn_state *cpustate)
+{
+ int reg, adr;
+
+ switch(reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ saturn_rotate_nibble_left_w(cpustate, A+reg); break; // aslc w
+ case 4: case 5: case 6: case 7:
+ saturn_rotate_nibble_right_w(cpustate, A+(reg&3)); break; // asrc w
+ case 8:
+ switch(adr=READ_OP(cpustate)) {
+ case 0:
+ switch (reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ saturn_add_const(cpustate, A+reg, cpustate->p, 1, READ_OP(cpustate)+1);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_sub_const(cpustate, A+(reg&3), cpustate->p, 1, READ_OP(cpustate)+1);
+ break;
+ default:
+ saturn_invalid5( cpustate, 8, 1, 8, adr, reg );
+ break;
+ }
+ break;
+ case 1:
+ switch (reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ saturn_add_const(cpustate, A+reg, 0, cpustate->p+1, READ_OP(cpustate)+1);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_sub_const(cpustate, A+(reg&3), 0, cpustate->p+1, READ_OP(cpustate)+1);
+ break;
+ default:
+ saturn_invalid5( cpustate, 8, 1, 8, adr, reg );
+ break;
+ }
+ break;
+ case 2: case 3: case 4: case 5: case 6: case 7: case 0xf:
+ switch (reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ saturn_add_const(cpustate, A+reg, adr_af_begin[adr], adr_af_count[adr], READ_OP(cpustate)+1);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_sub_const(cpustate, A+(reg&3), adr_af_begin[adr], adr_af_count[adr], READ_OP(cpustate)+1);
+ break;
+ default:
+ saturn_invalid5( cpustate, 8, 1, 8, adr, reg );
+ break;
+ }
+ break;
+ default:
+ saturn_invalid4( cpustate, 8, 1, 8, adr );
+ break;
+ }
+ break;
+ case 9:
+ switch(adr=READ_OP(cpustate)) {
+ case 0:
+ switch(reg=READ_OP(cpustate)){
+ case 0: case 1: case 2: case 3:
+ saturn_shift_right(cpustate, A+reg,cpustate->p,1);
+ break; // asrb p
+ default:
+ saturn_invalid5( cpustate, 8, 1, 9, adr, reg );
+ break;
+ }
+ break;
+ case 1:
+ switch(reg=READ_OP(cpustate)){
+ case 0: case 1: case 2: case 3:
+ saturn_shift_right(cpustate, A+reg, 0,cpustate->p+1);
+ break; // asrb wp
+ default:
+ saturn_invalid5( cpustate, 8, 1, 9, adr, reg );
+ break;
+ }
+ break;
+ case 2: case 3: case 4: case 5: case 6: case 7: case 0xf:
+ switch(reg=READ_OP(cpustate)){
+ case 0: case 1: case 2: case 3:
+ saturn_shift_right(cpustate, A+reg, adr_af_begin[adr], adr_af_count[adr]);
+ break; // asrb xs
+ default:
+ saturn_invalid5( cpustate, 8, 1, 9, adr, reg );
+ break;
+ }
+ break;
+ default:
+ saturn_invalid4( cpustate, 8, 1, 9, adr );
+ break;
+ }
+ break;
+ case 0xa:
+ saturn_instruction_81a(cpustate);
+ break;
+ case 0xb:
+ switch(adr=READ_OP(cpustate)) {
+ case 2: saturn_load_pc(cpustate, A);break;
+ case 3: saturn_load_pc(cpustate, C);break;
+ case 4: saturn_store_pc(cpustate, A);break;
+ case 5: saturn_store_pc(cpustate, C);break;
+ case 6: saturn_exchange_pc(cpustate, A);break;
+ case 7: saturn_exchange_pc(cpustate, C);break;
+ default: saturn_invalid4( cpustate, 8, 1, reg, adr ); break;
+ }
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_shift_right(cpustate, A+(reg&3), BEGIN_W, COUNT_W);
+ break; // asrb w
+ }
+}
+
+static void saturn_instruction_8(saturn_state *cpustate)
+{
+ int oper, adr;
+
+ switch(READ_OP(cpustate)) {
+ case 0:
+ saturn_instruction_80(cpustate);
+ break;
+ case 1:
+ saturn_instruction_81(cpustate);
+ break;
+ case 2: saturn_hst_clear_bits(cpustate);break;
+ case 3: saturn_hst_bits_cleared(cpustate);break;
+ case 4: saturn_st_clear_bit(cpustate);break;
+ case 5: saturn_st_set_bit(cpustate);break;
+ case 6: saturn_st_jump_bit_clear(cpustate);break;
+ case 7: saturn_st_jump_bit_set(cpustate);break;
+ case 8: saturn_p_not_equals(cpustate); break;
+ case 9: saturn_p_equals(cpustate); break;
+ case 0xa:
+ switch(oper=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ saturn_equals(cpustate, reg_left[oper&3] , BEGIN_A, COUNT_A, reg_right[oper&3]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_not_equals(cpustate, reg_left[oper&3] , BEGIN_A, COUNT_A, reg_right[oper&3]);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_equals_zero(cpustate, A+(oper&3), BEGIN_A, COUNT_A);
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_not_equals_zero(cpustate, A+(oper&3), BEGIN_A, COUNT_A);
+ break;
+ }
+ break;
+ case 0xb:
+ switch(oper=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ saturn_greater(cpustate, reg_left[oper&3] , BEGIN_A, COUNT_A, reg_right[oper&3]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_smaller(cpustate, reg_left[oper&3] , BEGIN_A, COUNT_A, reg_right[oper&3]);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_greater_equals(cpustate, reg_left[oper&3], BEGIN_A, COUNT_A, reg_right[oper&3]);
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_smaller_equals(cpustate, reg_left[oper&3], BEGIN_A, COUNT_A, reg_right[oper&3]);
+ break;
+ }
+ break;
+ case 0xc:
+ adr=READ_OP_DIS16(cpustate);
+ saturn_jump(cpustate, (adr+cpustate->pc-4)&0xfffff,1);
+ break;
+ case 0xd:
+ adr=READ_OP_ARG20(cpustate);
+ saturn_jump(cpustate, adr,1);
+ break;
+ case 0xe:
+ adr=READ_OP_DIS16(cpustate);
+ saturn_call(cpustate, (adr+cpustate->pc)&0xfffff);
+ break;
+ case 0xf:
+ adr=READ_OP_ARG20(cpustate);
+ saturn_call(cpustate, adr);
+ break;
+ }
+}
+
+static void saturn_instruction_9(saturn_state *cpustate)
+{
+ int adr, oper;
+
+ switch(adr=READ_OP(cpustate)) {
+ case 0:
+ switch(oper=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ saturn_equals(cpustate, reg_left[oper&3] , cpustate->p, 1, reg_right[oper&3]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_not_equals(cpustate, reg_left[oper&3] ,cpustate->p, 1, reg_right[oper&3]);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_equals_zero(cpustate, A+(oper&3), cpustate->p, 1);
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_not_equals_zero(cpustate, A+(oper&3), cpustate->p, 1);
+ break;
+ }
+ break;
+ case 1:
+ switch(oper=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ saturn_equals(cpustate, reg_left[oper&3] , 0, cpustate->p+1, reg_right[oper&3]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_not_equals(cpustate, reg_left[oper&3] , 0, cpustate->p+1, reg_right[oper&3]);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_equals_zero(cpustate, A+(oper&3), 0, cpustate->p+1);
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_not_equals_zero(cpustate, A+(oper&3), 0, cpustate->p+1);
+ break;
+ }
+ break;
+ case 2: case 3: case 4: case 5: case 6: case 7:
+ switch(oper=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ saturn_equals(cpustate, reg_left[oper&3] ,adr_a_begin[adr], adr_a_count[adr], reg_right[oper&3]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_not_equals(cpustate, reg_left[oper&3] ,adr_a_begin[adr], adr_a_count[adr], reg_right[oper&3]);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_equals_zero(cpustate, A+(oper&3),adr_a_begin[adr], adr_a_count[adr]);
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_not_equals_zero(cpustate, A+(oper&3) ,adr_a_begin[adr], adr_a_count[adr]);
+ break;
+ }
+ break;
+ case 8:
+ switch(oper=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ saturn_greater(cpustate, reg_left[oper&3] ,cpustate->p, 1, reg_right[oper&3]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_smaller(cpustate, reg_left[oper&3] ,cpustate->p, 1, reg_right[oper&3]);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_greater_equals(cpustate, reg_left[oper&3] ,cpustate->p, 1, reg_right[oper&3]);
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_smaller_equals(cpustate, reg_left[oper&3] ,cpustate->p, 1, reg_right[oper&3]);
+ break;
+ }
+ break;
+ case 9:
+ switch(oper=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ saturn_greater(cpustate, reg_left[oper&3] , 0, cpustate->p+1, reg_right[oper&3]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_smaller(cpustate, reg_left[oper&3] , 0, cpustate->p+1, reg_right[oper&3]);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_greater_equals(cpustate, reg_left[oper&3], 0, cpustate->p+1, reg_right[oper&3]);
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_smaller_equals(cpustate, reg_left[oper&3], 0, cpustate->p+1, reg_right[oper&3]);
+ break;
+ }
+ break;
+ case 0xa: case 0xb: case 0xc: case 0xd: case 0xe: case 0xf:
+ switch(oper=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ saturn_greater(cpustate, reg_left[oper&3] ,adr_b_begin[adr], adr_b_count[adr], reg_right[oper&3]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_smaller(cpustate, reg_left[oper&3] ,adr_b_begin[adr], adr_b_count[adr], reg_right[oper&3]);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_greater_equals(cpustate, reg_left[oper&3] ,adr_b_begin[adr], adr_b_count[adr], reg_right[oper&3]);
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_smaller_equals(cpustate, reg_left[oper&3] ,adr_b_begin[adr], adr_b_count[adr], reg_right[oper&3]);
+ break;
+ }
+ break;
+ }
+}
+
+static void saturn_instruction_a(saturn_state *cpustate)
+{
+ int reg, adr;
+
+ switch(adr=READ_OP(cpustate)) {
+ case 0:
+ switch (reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_add(cpustate, add_left[reg], cpustate->p, 1, add_right[reg]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_add(cpustate, A+(reg&3), cpustate->p, 1, A+(reg&3));
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_decrement(cpustate, A+(reg&3), cpustate->p, 1);
+ break;
+ }
+ break;
+ case 1:
+ switch (reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_add(cpustate, add_left[reg], 0, cpustate->p+1, add_right[reg]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_add(cpustate, A+(reg&3), 0, cpustate->p+1, A+(reg&3));
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_decrement(cpustate, A+(reg&3), 0, cpustate->p+1);
+ break;
+ }
+ break;
+ case 2: case 3: case 4: case 5: case 6: case 7:
+ switch (reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_add(cpustate, add_left[reg], adr_a_begin[adr], adr_a_count[adr], add_right[reg]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_add(cpustate, A+(reg&3), adr_a_begin[adr], adr_a_count[adr], A+(reg&3));
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_decrement(cpustate, A+(reg&3), adr_a_begin[adr], adr_a_count[adr]);
+ break;
+ }
+ break;
+ case 8:
+ switch(reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ saturn_clear(cpustate, A+reg, cpustate->p,1);
+ break; // a=0 p
+ case 4: case 5: case 6: case 7:
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_copy(cpustate, reg_right[reg&7], cpustate->p,1,reg_left[reg&7]);
+ break; // a=b p
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_exchange(cpustate, reg_left[reg&3], cpustate->p,1,reg_right[reg&3]);
+ break; // abex p
+ }
+ break;
+ case 9:
+ switch(reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ saturn_clear(cpustate, A+reg,0,cpustate->p+1);
+ break; // a=0 wp
+ case 4: case 5: case 6: case 7:
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_copy(cpustate, reg_right[reg&7], 0, cpustate->p+1, reg_left[reg&7]);
+ break; // a=b wp
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_exchange(cpustate, reg_left[reg&3], 0, cpustate->p+1, reg_right[reg&3]);
+ break; // abex wp
+ }
+ break;
+ case 0xa: case 0xb: case 0xc: case 0xd: case 0xe: case 0xf:
+ switch(reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ saturn_clear(cpustate, A+reg, adr_b_begin[adr], adr_b_count[adr]);
+ break; // a=0 xs
+ case 4: case 5: case 6: case 7:
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_copy(cpustate, reg_right[reg&7], adr_b_begin[adr], adr_b_count[adr], reg_left[reg&7]);
+ break; // a=b xs
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_exchange(cpustate, reg_left[reg&3], adr_b_begin[adr], adr_b_count[adr], reg_right[reg&3]);
+ break; // abex xs
+ }
+ break;
+ }
+}
+
+static void saturn_instruction_b(saturn_state *cpustate)
+{
+ int adr, reg;
+
+ switch(adr=READ_OP(cpustate)) {
+ case 0:
+ switch(reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_sub(cpustate, sub_left[reg], cpustate->p, 1, sub_right[reg]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_increment(cpustate, A+(reg&3), cpustate->p, 1); break; // a=a+1 p
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_sub2(cpustate, sub_left[reg], cpustate->p, 1, sub_right[reg]);
+ break;
+ }
+ break;
+ case 1:
+ switch(reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_sub(cpustate, sub_left[reg], 0, cpustate->p+1, sub_right[reg]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_increment(cpustate, A+(reg&3), 0, cpustate->p+1); break; // a=a+1 wp
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_sub2(cpustate, sub_left[reg], 0, cpustate->p+1, sub_right[reg]);
+ break;
+ }
+ break;
+ case 2: case 3: case 4: case 5: case 6: case 7:
+ switch(reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_sub(cpustate, sub_left[reg], adr_a_begin[adr], adr_a_count[adr], sub_right[reg]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_increment(cpustate, A+(reg&3), adr_a_begin[adr], adr_a_count[adr]);
+ break; // a=a+1 xs
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_sub2(cpustate, sub_left[reg], adr_a_begin[adr], adr_a_count[adr],
+ sub_right[reg]);
+ break;
+ }
+ break;
+ case 8:
+ switch(reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ saturn_shift_nibble_left(cpustate, A+reg, cpustate->p, 1); break; // asl p
+ case 4: case 5: case 6: case 7:
+ saturn_shift_nibble_right(cpustate, A+(reg&3), cpustate->p, 1); break; // asr p
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_negate(cpustate, A+(reg&3), cpustate->p, 1); break; // A=-A p
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_invert(cpustate, A+(reg&3), cpustate->p, 1); break; // A=-A-1 p
+ }
+ break;
+ case 9:
+ switch(reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ saturn_shift_nibble_left(cpustate, A+reg,0,cpustate->p+1); break; // asl wp
+ case 4: case 5: case 6: case 7:
+ saturn_shift_nibble_right(cpustate, A+(reg&3),0,cpustate->p+1); break; // asr wp
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_negate(cpustate, A+(reg&3),0,cpustate->p+1); break; // A=-A wp
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_invert(cpustate, A+(reg&3),0,cpustate->p+1); break; // A=-A-1 wp
+ }
+ break;
+ case 0xa: case 0xb: case 0xc: case 0xd: case 0xe: case 0xf:
+ switch(reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ saturn_shift_nibble_left(cpustate, A+reg,adr_b_begin[adr], adr_b_count[adr]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_shift_nibble_right(cpustate, A+(reg&3), adr_b_begin[adr], adr_b_count[adr]);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_negate(cpustate, A+(reg&3), adr_b_begin[adr], adr_b_count[adr]);
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_invert(cpustate, A+(reg&3), adr_b_begin[adr], adr_b_count[adr]);
+ break;
+ }
+ break;
+ }
+}
+
+
+static void saturn_instruction(saturn_state *cpustate)
+{
+ int reg, adr;
+
+ switch(READ_OP(cpustate)) {
+ case 0:
+ switch(READ_OP(cpustate)) {
+ case 0: saturn_return_xm_set(cpustate);break;
+ case 1: saturn_return(cpustate, 1);break;
+ case 2: saturn_return_carry_set(cpustate);break;
+ case 3: saturn_return_carry_clear(cpustate);break;
+ case 4: saturn_sethex(cpustate);break;
+ case 5: saturn_setdec(cpustate);break;
+ case 6: saturn_push_c(cpustate);break;
+ case 7: saturn_pop_c(cpustate);break;
+ case 8: saturn_clear_st(cpustate);break;
+ case 9: saturn_st_to_c(cpustate);break;
+ case 0xa: saturn_c_to_st(cpustate);break;
+ case 0xb: saturn_exchange_c_st(cpustate);break;
+ case 0xc: saturn_inc_p(cpustate);break;
+ case 0xd: saturn_dec_p(cpustate);break;
+ case 0xe: saturn_instruction_0e(cpustate);break;
+ case 0xf: saturn_return_interrupt(cpustate);break;
+ }
+ break;
+ case 1:
+ saturn_instruction_1(cpustate);
+ break;
+ case 2:
+ saturn_load_p(cpustate);
+ break;
+ case 3:
+ saturn_load_reg(cpustate, C);
+ break; // lc
+ case 4:
+ adr=READ_OP_DIS8(cpustate);
+ if (adr==0) {
+ saturn_return(cpustate, cpustate->carry);
+ }
+ else {
+ saturn_jump(cpustate, (cpustate->pc+adr-2)&0xfffff, cpustate->carry);
+ }
+ break;
+ case 5:
+ adr=READ_OP_DIS8(cpustate);
+ if (adr==0) {
+ saturn_return(cpustate, !cpustate->carry);
+ }
+ else {
+ saturn_jump(cpustate, (cpustate->pc+adr-2)&0xfffff,!cpustate->carry);
+ }
+ break;
+ case 6:
+ adr=READ_OP_DIS12(cpustate);
+ saturn_jump(cpustate, (cpustate->pc+adr-3)&0xfffff,1); break;
+ case 7:
+ adr=READ_OP_DIS12(cpustate);
+ saturn_call(cpustate, (adr+cpustate->pc)&0xfffff); break;
+ case 8:
+ saturn_instruction_8(cpustate);
+ break;
+ case 9:
+ saturn_instruction_9(cpustate);
+ break;
+ case 0xa:
+ saturn_instruction_a(cpustate);
+ break;
+ case 0xb:
+ saturn_instruction_b(cpustate);
+ break;
+ case 0xc:
+ switch (reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_add(cpustate, add_left[reg], BEGIN_A, COUNT_A, add_right[reg]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_add(cpustate, A+(reg&3), BEGIN_A, COUNT_A, A+(reg&3));
+ break;
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_decrement(cpustate, A+(reg&3), BEGIN_A, COUNT_A);
+ break;
+ }
+ break;
+ case 0xd:
+ switch(reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ saturn_clear(cpustate, A+reg, BEGIN_A, COUNT_A);
+ break; // a=0 a
+ case 4: case 5: case 6: case 7:
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_copy(cpustate, reg_right[reg&7], BEGIN_A, COUNT_A, reg_left[reg&7]);
+ break; // a=b a
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_exchange(cpustate, reg_left[reg&3], BEGIN_A, COUNT_A, reg_right[reg&3]);
+ break; // abex a
+ }
+ break;
+ case 0xe:
+ switch(reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_sub(cpustate, sub_left[reg], BEGIN_A, COUNT_A, sub_right[reg]);
+ break;
+ case 4: case 5: case 6: case 7:
+ saturn_increment(cpustate, A+(reg&3), BEGIN_A, COUNT_A);
+ break; // a=a+1 a
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_sub2(cpustate, sub_left[reg], BEGIN_A, COUNT_A, sub_right[reg]);
+ break;
+ }
+ break;
+ case 0xf:
+ switch(reg=READ_OP(cpustate)) {
+ case 0: case 1: case 2: case 3:
+ saturn_shift_nibble_left(cpustate, A+reg,BEGIN_A, COUNT_A);
+ break; // asl a
+ case 4: case 5: case 6: case 7:
+ saturn_shift_nibble_right(cpustate, A+(reg&3),BEGIN_A, COUNT_A);
+ break; // asr a
+ case 8: case 9: case 0xa: case 0xb:
+ saturn_negate(cpustate, A+(reg&3),BEGIN_A, COUNT_A);
+ break; // A=-A a
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ saturn_invert(cpustate, A+(reg&3),BEGIN_A, COUNT_A);
+ break; // A=-A-1 a
+ }
+ break;
+ }
+}
diff --git a/trunk/src/emu/cpu/saturn/saturn.c b/trunk/src/emu/cpu/saturn/saturn.c
new file mode 100644
index 00000000000..b03c4260923
--- /dev/null
+++ b/trunk/src/emu/cpu/saturn/saturn.c
@@ -0,0 +1,412 @@
+/*****************************************************************************
+ *
+ * saturn.c
+ * portable saturn emulator interface
+ * (hp calculators)
+ *
+ * Copyright Peter Trauner, all rights reserved.
+ *
+ * Modified by Antoine Mine'
+ *
+ * - 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 "saturn.h"
+
+#define R0 0
+#define R1 1
+#define R2 2
+#define R3 3
+#define R4 4
+#define A 5
+#define B 6
+#define C 7
+#define D 8
+#define I 9 // invalid
+
+typedef UINT32 SaturnAdr; // 20 bit, packed
+typedef UINT8 SaturnNib; // 4 bit
+
+// 64 bit, unpacked (one nibble per byte)
+typedef SaturnNib Saturn64[16];
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+
+/****************************************************************************
+ * The SATURN registers.
+ ****************************************************************************/
+typedef struct _saturn_state saturn_state;
+struct _saturn_state
+{
+ saturn_cpu_core *config;
+
+ Saturn64 reg[9]; //r0,r1,r2,r3,r4,a,b,c,d
+
+ SaturnAdr d[2], pc, oldpc, rstk[8]; // 20 bit addresses
+
+ SaturnNib p; // 4 bit pointer
+
+ UINT16 out; // 12 bit (packed)
+ UINT8 carry, decimal;
+ UINT16 st; // status 16 bit
+
+ SaturnNib hst; // hardware status 4 bit
+#define XM 1 // external Modules missing
+#define SB 2 // Sticky bit
+#define SR 4 // Service Request
+#define MP 8 // Module Pulled
+
+ UINT8 nmi_state;
+ UINT8 irq_state;
+ UINT8 irq_enable; /* INTON / INTOFF */
+ UINT8 in_irq; /* already servicing IRQ */
+ UINT8 pending_irq; /* IRQ is pending */
+ UINT8 sleeping; /* low-consumption state */
+ int monitor_id;
+ int monitor_in;
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ int icount;
+};
+
+INLINE saturn_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == SATURN);
+ return (saturn_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/***************************************************************
+ * include the opcode macros, functions and tables
+ ***************************************************************/
+
+#include "satops.c"
+#include "sattable.c"
+
+/*****************************************************************************
+ *
+ * Saturn CPU interface functions
+ *
+ *****************************************************************************/
+
+static CPU_INIT( saturn )
+{
+ saturn_state *cpustate = get_safe_token(device);
+
+ cpustate->config = (saturn_cpu_core *) device->static_config();
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+
+ device->save_item(NAME(cpustate->reg[R0]));
+ device->save_item(NAME(cpustate->reg[R1]));
+ device->save_item(NAME(cpustate->reg[R2]));
+ device->save_item(NAME(cpustate->reg[R3]));
+ device->save_item(NAME(cpustate->reg[R4]));
+ device->save_item(NAME(cpustate->reg[A]));
+ device->save_item(NAME(cpustate->reg[B]));
+ device->save_item(NAME(cpustate->reg[C]));
+ device->save_item(NAME(cpustate->reg[D]));
+ device->save_item(NAME(cpustate->d));
+ device->save_item(NAME(cpustate->pc));
+ device->save_item(NAME(cpustate->oldpc));
+ device->save_item(NAME(cpustate->rstk));
+ device->save_item(NAME(cpustate->out));
+ device->save_item(NAME(cpustate->carry));
+ device->save_item(NAME(cpustate->st));
+ device->save_item(NAME(cpustate->hst));
+ device->save_item(NAME(cpustate->nmi_state));
+ device->save_item(NAME(cpustate->irq_state));
+ device->save_item(NAME(cpustate->irq_enable));
+ device->save_item(NAME(cpustate->in_irq));
+ device->save_item(NAME(cpustate->pending_irq));
+ device->save_item(NAME(cpustate->sleeping));
+}
+
+static CPU_RESET( saturn )
+{
+ saturn_state *cpustate = get_safe_token(device);
+
+ cpustate->pc=0;
+ cpustate->sleeping = 0;
+ cpustate->irq_enable = 0;
+ cpustate->in_irq = 0;
+}
+
+
+INLINE void saturn_take_irq(saturn_state *cpustate)
+{
+ cpustate->in_irq = 1; /* reset by software, using RTI */
+ cpustate->pending_irq = 0;
+ cpustate->icount -= 7;
+ saturn_push(cpustate, cpustate->pc);
+ cpustate->pc=IRQ_ADDRESS;
+
+ LOG(("Saturn '%s' takes IRQ ($%04x)\n", cpustate->device->tag(), cpustate->pc));
+
+ if (cpustate->irq_callback) (*cpustate->irq_callback)(cpustate->device, SATURN_IRQ_LINE);
+}
+
+static CPU_EXECUTE( saturn )
+{
+ saturn_state *cpustate = get_safe_token(device);
+
+ do
+ {
+ cpustate->oldpc = cpustate->pc;
+
+ debugger_instruction_hook(device, cpustate->pc);
+
+ if ( cpustate->sleeping )
+ {
+ /* advance time when sleeping */
+ cpustate->icount -= 100;
+ }
+ else
+ {
+ /* takes irq */
+ if ( cpustate->pending_irq && (!cpustate->in_irq) )
+ saturn_take_irq(cpustate);
+
+ /* execute one instruction */
+ saturn_instruction(cpustate);
+ }
+
+ } while (cpustate->icount > 0);
+}
+
+
+static void saturn_set_nmi_line(saturn_state *cpustate, int state)
+{
+ if ( state == cpustate->nmi_state ) return;
+ cpustate->nmi_state = state;
+ if ( state != CLEAR_LINE )
+ {
+ LOG(( "SATURN '%s' set_nmi_line(ASSERT)\n", cpustate->device->tag()));
+ cpustate->pending_irq = 1;
+ }
+}
+
+static void saturn_set_irq_line(saturn_state *cpustate, int state)
+{
+ if ( state == cpustate->irq_state ) return;
+ cpustate->irq_state = state;
+ if ( state != CLEAR_LINE && cpustate->irq_enable )
+ {
+ LOG(( "SATURN '%s' set_irq_line(ASSERT)\n", cpustate->device->tag()));
+ cpustate->pending_irq = 1;
+ }
+}
+
+static void saturn_set_wakeup_line(saturn_state *cpustate, int state)
+{
+ if (cpustate->sleeping && state==1)
+ {
+ LOG(( "SATURN '%s' set_wakeup_line(ASSERT)\n", cpustate->device->tag()));
+ if (cpustate->irq_callback) (*cpustate->irq_callback)(cpustate->device, SATURN_WAKEUP_LINE);
+ cpustate->sleeping = 0;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static void IntReg64(Saturn64 r, INT64 d)
+{
+ int i;
+ for (i=0; i<16; i++)
+ r[i] = (d >> (4*i)) & 0xf;
+}
+
+
+static CPU_SET_INFO( saturn )
+{
+ saturn_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 + SATURN_NMI_LINE: saturn_set_nmi_line(cpustate, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SATURN_IRQ_LINE: saturn_set_irq_line(cpustate, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SATURN_WAKEUP_LINE: saturn_set_wakeup_line(cpustate, info->i); break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + SATURN_PC: cpustate->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_D0: cpustate->d[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_D1: cpustate->d[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_A: IntReg64(cpustate->reg[A], info->i); break;
+ case CPUINFO_INT_REGISTER + SATURN_B: IntReg64(cpustate->reg[B], info->i); break;
+ case CPUINFO_INT_REGISTER + SATURN_C: IntReg64(cpustate->reg[C], info->i); break;
+ case CPUINFO_INT_REGISTER + SATURN_D: IntReg64(cpustate->reg[D], info->i); break;
+ case CPUINFO_INT_REGISTER + SATURN_R0: IntReg64(cpustate->reg[R0], info->i); break;
+ case CPUINFO_INT_REGISTER + SATURN_R1: IntReg64(cpustate->reg[R1], info->i); break;
+ case CPUINFO_INT_REGISTER + SATURN_R2: IntReg64(cpustate->reg[R2], info->i); break;
+ case CPUINFO_INT_REGISTER + SATURN_R3: IntReg64(cpustate->reg[R3], info->i); break;
+ case CPUINFO_INT_REGISTER + SATURN_R4: IntReg64(cpustate->reg[R4], info->i); break;
+ case CPUINFO_INT_REGISTER + SATURN_P: cpustate->p = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_OUT: cpustate->out = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_CARRY: cpustate->carry = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_ST: cpustate->st = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_HST: cpustate->hst = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK0: cpustate->rstk[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK1: cpustate->rstk[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK2: cpustate->rstk[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK3: cpustate->rstk[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK4: cpustate->rstk[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK5: cpustate->rstk[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK6: cpustate->rstk[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK7: cpustate->rstk[7] = info->i; break;
+ case CPUINFO_INT_REGISTER + SATURN_SLEEPING: cpustate->sleeping = info->i;
+ }
+}
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+#define Reg64Data(s) s[15],s[14],s[13],s[12],s[11],s[10],s[9],s[8],s[7],s[6],s[5],s[4],s[3],s[2],s[1],s[0]
+#define Reg64Format "%x %x%x%x%x%x%x%x %x%x%x %x%x%x%x%x"
+
+static INT64 Reg64Int(Saturn64 r)
+{
+ INT64 x = 0;
+ int i;
+ for (i=0; i<16; i++)
+ x |= (INT64) r[i] << (4*i);
+ return x;
+}
+
+CPU_GET_INFO( saturn )
+{
+ saturn_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(saturn_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 = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 20; /* 20 nibbles max */ break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 2; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 21; 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 + SATURN_NMI_LINE: info->i = cpustate->nmi_state; break;
+ case CPUINFO_INT_INPUT_STATE + SATURN_IRQ_LINE: info->i = cpustate->irq_state; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->oldpc; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + SATURN_PC: info->i = cpustate->pc; break;
+ case CPUINFO_INT_REGISTER + SATURN_D0: info->i = cpustate->d[0]; break;
+ case CPUINFO_INT_REGISTER + SATURN_D1: info->i = cpustate->d[1]; break;
+
+ case CPUINFO_INT_REGISTER + SATURN_A: info->i = Reg64Int(cpustate->reg[A]); break;
+ case CPUINFO_INT_REGISTER + SATURN_B: info->i = Reg64Int(cpustate->reg[B]); break;
+ case CPUINFO_INT_REGISTER + SATURN_C: info->i = Reg64Int(cpustate->reg[C]); break;
+ case CPUINFO_INT_REGISTER + SATURN_D: info->i = Reg64Int(cpustate->reg[D]); break;
+ case CPUINFO_INT_REGISTER + SATURN_R0: info->i = Reg64Int(cpustate->reg[R0]); break;
+ case CPUINFO_INT_REGISTER + SATURN_R1: info->i = Reg64Int(cpustate->reg[R1]); break;
+ case CPUINFO_INT_REGISTER + SATURN_R2: info->i = Reg64Int(cpustate->reg[R2]); break;
+ case CPUINFO_INT_REGISTER + SATURN_R3: info->i = Reg64Int(cpustate->reg[R3]); break;
+ case CPUINFO_INT_REGISTER + SATURN_R4: info->i = Reg64Int(cpustate->reg[R4]); break;
+
+ case CPUINFO_INT_REGISTER + SATURN_P: info->i = cpustate->p; break;
+ case CPUINFO_INT_REGISTER + SATURN_OUT: info->i = cpustate->out; break;
+ case CPUINFO_INT_REGISTER + SATURN_CARRY: info->i = cpustate->carry; break;
+ case CPUINFO_INT_REGISTER + SATURN_ST: info->i = cpustate->st; break;
+ case CPUINFO_INT_REGISTER + SATURN_HST: info->i = cpustate->hst; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK0: info->i = cpustate->rstk[0]; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK1: info->i = cpustate->rstk[1]; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK2: info->i = cpustate->rstk[2]; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK3: info->i = cpustate->rstk[3]; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK4: info->i = cpustate->rstk[4]; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK5: info->i = cpustate->rstk[5]; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK6: info->i = cpustate->rstk[6]; break;
+ case CPUINFO_INT_REGISTER + SATURN_RSTK7: info->i = cpustate->rstk[7]; break;
+ case CPUINFO_INT_REGISTER + SATURN_SLEEPING: info->i = cpustate->sleeping;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(saturn); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(saturn); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(saturn); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(saturn); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(saturn); 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, "Saturn"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Saturn"); 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_REGISTER + SATURN_PC: sprintf(info->s, "PC: %.5x", cpustate->pc);break;
+ case CPUINFO_STR_REGISTER + SATURN_D0: sprintf(info->s, "D0: %.5x", cpustate->d[0]);break;
+ case CPUINFO_STR_REGISTER + SATURN_D1: sprintf(info->s, "D1: %.5x", cpustate->d[1]);break;
+ case CPUINFO_STR_REGISTER + SATURN_A: sprintf(info->s, "A: " Reg64Format, Reg64Data(cpustate->reg[A]));break;
+ case CPUINFO_STR_REGISTER + SATURN_B: sprintf(info->s, "B: " Reg64Format, Reg64Data(cpustate->reg[B]));break;
+ case CPUINFO_STR_REGISTER + SATURN_C: sprintf(info->s, "C: " Reg64Format, Reg64Data(cpustate->reg[C]));break;
+ case CPUINFO_STR_REGISTER + SATURN_D: sprintf(info->s, "D: " Reg64Format, Reg64Data(cpustate->reg[D]));break;
+ case CPUINFO_STR_REGISTER + SATURN_R0: sprintf(info->s, "R0: " Reg64Format, Reg64Data(cpustate->reg[R0]));break;
+ case CPUINFO_STR_REGISTER + SATURN_R1: sprintf(info->s, "R1: " Reg64Format, Reg64Data(cpustate->reg[R1]));break;
+ case CPUINFO_STR_REGISTER + SATURN_R2: sprintf(info->s, "R2: " Reg64Format, Reg64Data(cpustate->reg[R2]));break;
+ case CPUINFO_STR_REGISTER + SATURN_R3: sprintf(info->s, "R3: " Reg64Format, Reg64Data(cpustate->reg[R3]));break;
+ case CPUINFO_STR_REGISTER + SATURN_R4: sprintf(info->s, "R4: " Reg64Format, Reg64Data(cpustate->reg[R4]));break;
+ case CPUINFO_STR_REGISTER + SATURN_P: sprintf(info->s, "P:%x", cpustate->p);break;
+ case CPUINFO_STR_REGISTER + SATURN_OUT: sprintf(info->s, "OUT:%.3x", cpustate->out);break;
+ case CPUINFO_STR_REGISTER + SATURN_CARRY: sprintf(info->s, "Carry: %d", cpustate->carry);break;
+ case CPUINFO_STR_REGISTER + SATURN_ST: sprintf(info->s, "ST:%.4x", cpustate->st);break;
+ case CPUINFO_STR_REGISTER + SATURN_HST: sprintf(info->s, "HST:%x", cpustate->hst);break;
+ case CPUINFO_STR_REGISTER + SATURN_RSTK0: sprintf(info->s, "RSTK0:%.5x", cpustate->rstk[0]);break;
+ case CPUINFO_STR_REGISTER + SATURN_RSTK1: sprintf(info->s, "RSTK1:%.5x", cpustate->rstk[1]);break;
+ case CPUINFO_STR_REGISTER + SATURN_RSTK2: sprintf(info->s, "RSTK2:%.5x", cpustate->rstk[2]);break;
+ case CPUINFO_STR_REGISTER + SATURN_RSTK3: sprintf(info->s, "RSTK3:%.5x", cpustate->rstk[3]);break;
+ case CPUINFO_STR_REGISTER + SATURN_RSTK4: sprintf(info->s, "RSTK4:%.5x", cpustate->rstk[4]);break;
+ case CPUINFO_STR_REGISTER + SATURN_RSTK5: sprintf(info->s, "RSTK5:%.5x", cpustate->rstk[5]);break;
+ case CPUINFO_STR_REGISTER + SATURN_RSTK6: sprintf(info->s, "RSTK6:%.5x", cpustate->rstk[6]);break;
+ case CPUINFO_STR_REGISTER + SATURN_RSTK7: sprintf(info->s, "RSTK7:%.5x", cpustate->rstk[7]);break;
+ case CPUINFO_STR_REGISTER + SATURN_IRQ_STATE: sprintf(info->s, "IRQ:%c%c%c%i", cpustate->in_irq?'S':'.', cpustate->irq_enable?'e':'.', cpustate->pending_irq?'p':'.', cpustate->irq_state); break;
+ case CPUINFO_STR_FLAGS: sprintf(info->s, "%c%c", cpustate->decimal?'D':'.', cpustate->carry ? 'C':'.'); break;
+ case CPUINFO_STR_REGISTER + SATURN_SLEEPING: sprintf(info->s, "sleep:%c", cpustate->sleeping?'S':'.'); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(SATURN, saturn);
diff --git a/trunk/src/emu/cpu/saturn/saturn.h b/trunk/src/emu/cpu/saturn/saturn.h
new file mode 100644
index 00000000000..1cb913e909b
--- /dev/null
+++ b/trunk/src/emu/cpu/saturn/saturn.h
@@ -0,0 +1,92 @@
+/*****************************************************************************
+ *
+ * cpustate->h
+ * portable saturn emulator interface
+ * (hp calculators)
+ *
+ * Copyright Peter Trauner, all rights reserved.
+ *
+ * Modified by Antoine Mine'
+ *
+ * - 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.
+ *
+ *****************************************************************************/
+/*
+Calculator Release Date Chip Version Analog/Digital IC
+HP71B (early) 02/01/84 1LF2 -
+HP71B (later) ??/??/?? 1LK7 -
+HP18C 06/01/86 1LK7 -
+HP28C 01/05/87 1LK7 -
+HP17B 01/04/88 1LT8 Lewis
+HP19B 01/04/88 1LT8 Lewis
+HP27S 01/04/88 1LT8 Lewis
+HP28S 01/04/88 1LT8 Lewis
+HP48SX 03/16/91 1LT8 Clarke
+HP48S 04/02/91 1LT8 Clarke
+HP48GX 06/01/93 1LT8 Yorke
+HP48G 06/01/93 1LT8 Yorke
+HP38G 09/??/95 1LT8 Yorke
+*/
+/* 4 bit processor
+ 20 address lines */
+
+#pragma once
+
+#ifndef __SATURN_H__
+#define _SATURN_H
+
+
+#define SATURN_INT_NONE 0
+#define SATURN_INT_IRQ 1
+#define SATURN_INT_NMI 2
+
+typedef struct _saturn_cpu_core saturn_cpu_core;
+struct _saturn_cpu_core
+{
+ void (*out)(device_t*,int);
+ int (*in)(device_t*);
+ void (*reset)(device_t*);
+ void (*config)(device_t*,int v);
+ void (*unconfig)(device_t*,int v);
+ int (*id)(device_t*);
+ void (*crc)(device_t*,int addr, int data);
+ void (*rsi)(device_t*);
+};
+
+enum
+{
+ SATURN_A=1, SATURN_B, SATURN_C, SATURN_D,
+ SATURN_R0, SATURN_R1, SATURN_R2, SATURN_R3, SATURN_R4,
+ SATURN_RSTK0, SATURN_RSTK1, SATURN_RSTK2, SATURN_RSTK3,
+ SATURN_RSTK4, SATURN_RSTK5, SATURN_RSTK6, SATURN_RSTK7,
+ SATURN_PC, SATURN_D0, SATURN_D1,
+
+ SATURN_P,
+ SATURN_OUT,
+ SATURN_CARRY,
+ SATURN_ST,
+ SATURN_HST,
+
+ SATURN_IRQ_STATE,
+ SATURN_SLEEPING,
+};
+
+#define SATURN_IRQ_LINE 0
+#define SATURN_NMI_LINE 1
+#define SATURN_WAKEUP_LINE 2
+
+CPU_DISASSEMBLE( saturn );
+
+DECLARE_LEGACY_CPU_DEVICE(SATURN, saturn);
+
+#endif /* __SATURN_H__ */
diff --git a/trunk/src/emu/cpu/saturn/saturnds.c b/trunk/src/emu/cpu/saturn/saturnds.c
new file mode 100644
index 00000000000..e0889250027
--- /dev/null
+++ b/trunk/src/emu/cpu/saturn/saturnds.c
@@ -0,0 +1,1486 @@
+/*****************************************************************************
+ *
+ * saturnds.c
+ * portable saturn emulator interface
+ * (hp calculators)
+ *
+ * Copyright Peter Trauner, all rights reserved.
+ *
+ * Modified by Antoine Mine'
+ *
+ * - 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 "saturn.h"
+
+#define SATURN_HP_MNEMONICS
+
+#if defined SATURN_HP_MNEMONICS
+// class/hp mnemonics
+static int set=0;
+#else
+// readable/normal mnemonics
+static int set=1;
+#endif
+
+#define P "P"
+#define WP "WP"
+#define XS "XS"
+#define X "X"
+#define S "S"
+#define M "M"
+#define B "B"
+#define W "W"
+#define A "A"
+
+static const char *const adr_b[]=
+{ P, WP, XS, X, S, M, B, W };
+
+static const char *const adr_af[]=
+{ P, WP, XS, X, S, M, B, W, 0, 0, 0, 0, 0, 0, 0, A };
+
+static const char *const adr_a[]=
+ { P, WP, XS, X, S, M, B, W };
+
+static const char number_2_hex[]=
+{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+
+#define SATURN_PEEKOP_DIS8(v) v = (INT8)( oprom[pos] | ( oprom[pos+1] << 4 ) ); pos+= 2;
+
+#define SATURN_PEEKOP_DIS12(v) v = oprom[pos] | ( oprom[pos+1] << 4 ) | ( oprom[pos+2] << 8 ); \
+ pos += 3; \
+ if ( v & 0x0800 ) v = -0x1000 + v;
+
+#define SATURN_PEEKOP_DIS16(v) v = (INT16)( oprom[pos] | ( oprom[pos+1] << 4 ) | ( oprom[pos+2] << 8 ) | ( oprom[pos+3] << 12 ) ); pos += 4;
+
+#define SATURN_PEEKOP_ADR(v) v = oprom[pos] | ( oprom[pos+1] << 4 ) | ( oprom[pos+2] << 8 ) | ( oprom[pos+3] << 12 ) | ( oprom[pos+4] << 16 ); pos += 5;
+
+
+// don't split branch and return, source relies on this ordering
+typedef enum
+{
+ Return, ReturnSetXM, ReturnSetCarry, ReturnClearCarry, ReturnFromInterrupt,
+ jump3,jump4,jump,
+ call3,call4,call,
+ branchCarrySet, returnCarrySet,
+ branchCarryClear, returnCarryClear,
+
+ outCS, outC, inA, inC,
+ unconfig, config, Cid, shutdown, cp1, reset, buscc,
+ CcopyP, PcopyC, sreq, CswapP,
+
+ inton, AloadImm, buscb,
+ clearAbit, setAbit,
+ branchAbitclear, returnAbitclear,
+ branchAbitset, returnAbitset,
+ clearCbit, setCbit,
+ branchCbitclear, returnCbitclear,
+ branchCbitset, returnCbitset,
+ PCloadA, buscd, PCloadC, intoff, rsi,
+
+ jumpA, jumpC, PCcopyA, PCcopyC, AcopyPC, CcopyPC,
+
+ clearHST,
+ branchHSTclear, returnHSTclear,
+
+ clearBitST, setBitST,
+ branchSTclear, returnSTclear,
+ branchSTset, returnSTset,
+
+
+ branchPdiffers, returnPdiffers,
+ branchPequals, returnPequals,
+
+ branchAequalsB, returnAequalsB,
+ branchBequalsC, returnBequalsC,
+ branchAequalsC, returnAequalsC,
+ branchCequalsD, returnCequalsD,
+ branchAdiffersB, returnAdiffersB,
+ branchBdiffersC, returnBdiffersC,
+ branchAdiffersC, returnAdiffersC,
+ branchCdiffersD, returnCdiffersD,
+ branchAzero, returnAzero,
+ branchBzero, returnBzero,
+ branchCzero, returnCzero,
+ branchDzero, returnDzero,
+ branchAnotzero, returnAnotzero,
+ branchBnotzero, returnBnotzero,
+ branchCnotzero, returnCnotzero,
+ branchDnotzero, returnDnotzero,
+
+ branchAgreaterB, returnAgreaterB,
+ branchBgreaterC, returnBgreaterC,
+ branchCgreaterA, returnCgreaterA,
+ branchDgreaterC, returnDgreaterC,
+ branchAlowerB, returnAlowerB,
+ branchBlowerC, returnBlowerC,
+ branchClowerA, returnClowerA,
+ branchDlowerC, returnDlowerC,
+ branchAnotlowerB, returnAnotlowerB,
+ branchBnotlowerC, returnBnotlowerC,
+ branchCnotlowerA, returnCnotlowerA,
+ branchDnotlowerC, returnDnotlowerC,
+ branchAnotgreaterB, returnAnotgreaterB,
+ branchBnotgreaterC, returnBnotgreaterC,
+ branchCnotgreaterA, returnCnotgreaterA,
+ branchDnotgreaterC, returnDnotgreaterC,
+
+ SetHexMode, SetDecMode,
+ PushC, PopC,
+
+ D0loadImm2, D0loadImm4, D0loadImm5,
+ D1loadImm2, D1loadImm4, D1loadImm5,
+ PloadImm, CloadImm,
+
+ clearST,
+ CcopyST, STcopyC,
+ swapCST,
+
+ incP, decP,
+
+ R0copyA, R1copyA, R2copyA, R3copyA, R4copyA,
+ R0copyC, R1copyC, R2copyC, R3copyC, R4copyC,
+
+ AcopyR0, AcopyR1, AcopyR2, AcopyR3, AcopyR4,
+ CcopyR0, CcopyR1, CcopyR2, CcopyR3, CcopyR4,
+
+ D0copyA, D1copyA, D0copyC, D1copyC,
+ D0copyAShort, D1copyAShort, D0copyCShort, D1copyCShort, // other class mnemonic
+
+ SwapAR0, SwapAR1, SwapAR2, SwapAR3, SwapAR4,
+ SwapCR0, SwapCR1, SwapCR2, SwapCR3, SwapCR4,
+
+ SwapAD0, SwapAD1, SwapCD0, SwapCD1,
+ SwapAD0Short, SwapAD1Short, SwapCD0Short, SwapCD1Short, // other class mnemonic
+
+ D0storeA, D1storeA, D0storeC, D1storeC,
+ AloadD0, AloadD1, CloadD0, CloadD1,
+
+ D0addImm, D1addImm, D0subImm, D1subImm,
+ AaddImm, BaddImm, CaddImm, DaddImm,
+ AsubImm, BsubImm, CsubImm, DsubImm,
+
+ AandB, BandC, CandA, DandC, BandA, CandB, AandC, CandD,
+ AorB, BorC, CorA, DorC, BorA, CorB, AorC, CorD,
+
+ Ashiftrightbit, Bshiftrightbit, Cshiftrightbit, Dshiftrightbit,
+
+ AshiftleftCarry, BshiftleftCarry, CshiftleftCarry, DshiftleftCarry,
+ AshiftrightCarry, BshiftrightCarry, CshiftrightCarry, DshiftrightCarry,
+
+ AaddB, BaddC, CaddA, DaddC, AaddA, BaddB, CaddC, DaddD,
+ BaddA, CaddB, AaddC, CaddD, decA, decB, decC, decD,
+
+ AsubB, BsubC, CsubA, DsubC, incA, incB, incC, incD,
+ BsubA, CsubB, AsubC, CsubD, AsubnB, BsubnC, CsubnA, DsubnC,
+
+ clearA, clearB, clearC, clearD,
+ AcopyB, BcopyC, CcopyA, DcopyC, BcopyA, CcopyB, AcopyC, CcopyD,
+ AswapB, BswapC, CswapA, DswapC,
+
+ Ashiftleft, Bshiftleft, Cshiftleft, Dshiftleft,
+ Ashiftright, Bshiftright, Cshiftright, Dshiftright,
+ negateA, negateB, negateC, negateD,
+ notA, notB, notC, notD
+
+} MNEMONICS;
+
+static const struct {
+ const char *name[2];
+} mnemonics[]={
+ { { "rtn", "RET" } },
+ { { "rtnsXM", "RETSETXM" } },
+ { { "rtnsC", "RETSETC" } },
+ { { "rtncC", "RETCLRC" } },
+ { { "rti", "RETI" } },
+ { { "goto %05x", "JUMP.3 %05x" } },
+ { { "goto %05x", "JUMP.4 %05x" } },
+ { { "goto %05x", "JUMP %05x" } },
+ { { "gosub %05x", "CALL.3 %05x" } },
+ { { "gosub %05x", "CALL.4 %05x" } },
+ { { "gosub %05x", "CALL %05x" } },
+ { { "goC %05x", "BRCS %05x" } },
+ { { "rtnC", "RETCS" } },
+ { { "gonC %05x", "BRCC %05x" } },
+ { { "rtnnC", "RETCC" } },
+
+ { { "OUT=CS", "OUT.S C" } },
+ { { "OUT=C", "OUT.X C" } },
+ { { "A=IN", "IN.4 A" } },
+ { { "C=IN", "IN.4 C" } },
+ { { "uncnfg", "UNCNFG" } },
+ { { "config", "CONFIG" } },
+ { { "C=id", "MOVE.A ID,C" } },
+ { { "!shutdn", "!SHUTDN" } },
+ { { "C+P+1", "ADD.A P+1,C" } },
+ { { "reset", "RESET" } },
+ { { "!buscc", "!BUSCC" } },
+ { { "C=P %x", "MOVE.1 P,C,%x" } },
+ { { "P=C %x", "MOVE.1 C,%x,P" } },
+ { { "!sreq?", "!SREQ" } },
+ { { "CPex %x", "SWAP.1 P,C,%x" } },
+
+ { { "!inton", "!INTON" } },
+ { { "LA %-2x %s", "MOVE.P%-2x %s,A" } },
+ { { "!buscb", "!BUSCB" } },
+ { { "Abit=0 %x", "CLRB %x,A" } },
+ { { "Abit=1 %x", "SETB %x,A" } },
+ { { "?Abit=0 %x,%05x", "BRBC %x,A,%05x" } },
+ { { "?Abit=0 %x,rtn", "RETBC %x,A" } },
+ { { "?Abit=1 %x,%05x", "BRBS %x,A,%05x" } },
+ { { "?Abit=1 %x,rtn", "RETBS %x,A" } },
+ { { "Cbit=0 %x", "CLRB %x,C" } },
+ { { "Cbit=1 %x", "SETB %x,C" } },
+ { { "?Cbit=0 %x,%05x", "BRBC %x,C,%05x" } },
+ { { "?Cbit=0 %x,rtn", "RETBC %x,C" } },
+ { { "?Cbit=1 %x,%05x", "BRBS %x,C,%05x" } },
+ { { "?Cbit=1 %x,rtn", "RETBS %x,C" } },
+ { { "PC=(A)", "JUMP.A @A" } },
+ { { "!buscd", "!BUSCD" } },
+ { { "PC=(C)", "JUMP.A @C" } },
+ { { "!intoff", "!INTOFF" } },
+ { { "!rsi", "!RSI" } },
+
+ { { "PC=A", "JUMP.A A" } },
+ { { "PC=C", "JUMP.A C" } },
+ { { "A=PC", "MOVE.A PC,A" } },
+ { { "C=PC", "MOVE.A PC,C" } },
+ { { "APCex", "SWAP.A A,PC" } },
+ { { "CPCex", "SWAP.A C,PC" } },
+
+ { { "HST=0 %x", "CLRHST %x" } },
+ { { "?HST=0 %x,%05x", "BRBCHST %x,%05x" } },
+ { { "?HST=0 %x,rtn", "RETBCHST %x" } },
+ { { "ST=0 %x", "CLRB %x,ST" } },
+ { { "ST=1 %x", "SETB %x,ST" } },
+ { { "?ST=0 %x,%05x", "BRBC ST,%x,%05x" } },
+ { { "?ST=0 %x,rtn", "RETBC ST,%x" } },
+ { { "?ST=1 %x,%05x", "BRBS ST,%x,%05x" } },
+ { { "?ST=1 %x,rtn", "RETBS ST,%x" } },
+ { { "?P# %x,%05x", "BRNE P,%x,%05x" } },
+ { { "?P# %x,rtn", "RETNE P,%x" } },
+ { { "?P= %x,%05x", "BREQ P,%x,%05x" } },
+ { { "?P= %x,rtn", "RETEQ P,%x" } },
+
+ { { "?A=B %s,%05x", "BREQ.%-2s A,B,%05x" } },
+ { { "?A=B %s,rtn", "RETEQ.%-2s A,B" } },
+ { { "?B=C %s,%05x", "BREQ.%-2s B,C,%05x" } },
+ { { "?B=C %s,rtn", "RETEQ.%-2s B,C" } },
+ { { "?A=C %s,%05x", "BREQ.%-2s A,C,%05x" } },
+ { { "?A=C %s,rtn", "RETEQ.%-2s A,C" } },
+ { { "?C=D %s,%05x", "BREQ.%-2s C,D,%05x" } },
+ { { "?C=D %s,rtn", "RETEQ.%-2s C,D" } },
+ { { "?A#B %s,%05x", "BRNE.%-2s A,B,%05x" } },
+ { { "?A#B %s,rtn", "RETNE.%-2s A,B" } },
+ { { "?B#C %s,%05x", "BRNE.%-2s B,C,%05x" } },
+ { { "?B#C %s,rtn", "RETNE.%-2s B,C" } },
+ { { "?A#C %s,%05x", "BRNE.%-2s A,C,%05x" } },
+ { { "?A#C %s,rtn", "RETNE.%-2s A,C" } },
+ { { "?C#D %s,%05x", "BRNE.%-2s C,D,%05x" } },
+ { { "?C#D %s,rtn", "RETNE.%-2s C,D" } },
+ { { "?A=0 %s,%05x", "BRZ.%-2s A,%05x" } },
+ { { "?A=0 %s,rtn", "RETZ.%-2s A" } },
+ { { "?B=0 %s,%05x", "BRZ.%-2s B,%05x" } },
+ { { "?B=0 %s,rtn", "RETZ.%-2s B" } },
+ { { "?C=0 %s,%05x", "BRZ.%-2s C,%05x" } },
+ { { "?C=0 %s,rtn", "RETZ.%-2s C" } },
+ { { "?D=0 %s,%05x", "BRZ.%-2s D,%05x" } },
+ { { "?D=0 %s,rtn", "RETZ.%-2s D" } },
+ { { "?A#0 %s,%05x", "BRNZ.%-2s A,%05x" } },
+ { { "?A#0 %s,rtn", "RETNZ.%-2s A" } },
+ { { "?B#0 %s,%05x", "BRNZ.%-2s B,%05x" } },
+ { { "?B#0 %s,rtn", "RETNZ.%-2s B" } },
+ { { "?C#0 %s,%05x", "BRNZ.%-2s C,%05x" } },
+ { { "?C#0 %s,rtn", "RETNZ.%-2s C" } },
+ { { "?D#0 %s,%05x", "BRNZ.%-2s D,%05x" } },
+ { { "?D#0 %s,rtn", "RETNZ.%-2s D" } },
+
+ { { "?A>B %s,%05x", "BRGT.%-2s A,B,%05x" } },
+ { { "?A>B %s,rtn", "RETGT.%-2s A,B" } },
+ { { "?B>C %s,%05x", "BRGT.%-2s B,C,%05x" } },
+ { { "?B>C %s,rtn", "RETGT.%-2s B,C" } },
+ { { "?C>A %s,%05x", "BRGT.%-2s C,A,%05x" } },
+ { { "?C>A %s,rtn", "RETGT.%-2s C,A" } },
+ { { "?D>C %s,%05x", "BRGT.%-2s D,C,%05x" } },
+ { { "?D>C %s,rtn", "RETGT.%-2s D,C" } },
+ { { "?A<B %s,%05x", "BRLT.%-2s A,B,%05x" } },
+ { { "?A<B %s,rtn", "RETLT.%-2s A,B" } },
+ { { "?B<C %s,%05x", "BRLT.%-2s B,C,%05x" } },
+ { { "?B<C %s,rtn", "RETLT.%-2s B,C" } },
+ { { "?C<A %s,%05x", "BRLT.%-2s C,A,%05x" } },
+ { { "?C<A %s,rtn", "RETLT.%-2s C,A" } },
+ { { "?D<C %s,%05x", "BRLT.%-2s D,C,%05x" } },
+ { { "?D<C %s,rtn", "RETLT.%-2s D,C" } },
+ { { "?A>=B %s,%05x", "BRGE.%-2s A,B,%05x" } },
+ { { "?A>=B %s,rtn", "RETGE.%-2s A,B" } },
+ { { "?B>=C %s,%05x", "BRGE.%-2s B,C,%05x" } },
+ { { "?B>=C %s,rtn", "RETGE.%-2s B,C" } },
+ { { "?C>=A %s,%05x", "BRGE.%-2s C,A,%05x" } },
+ { { "?C>=A %s,rtn", "RETGE.%-2s C,A" } },
+ { { "?D>=C %s,%05x", "BRGE.%-2s D,C,%05x" } },
+ { { "?D>=C %s,rtn", "RETGE.%-2s D,C" } },
+ { { "?A<=B %s,%05x", "BRLE.%-2s A,B,%05x" } },
+ { { "?A<=B %s,rtn", "RETLE.%-2s A,B" } },
+ { { "?B<=C %s,%05x", "BRLE.%-2s B,C,%05x" } },
+ { { "?B<=C %s,rtn", "RETLE.%-2s B,C" } },
+ { { "?C<=A %s,%05x", "BRLE.%-2s C,A,%05x" } },
+ { { "?C<=A %s,rtn", "RETLE.%-2s C,A" } },
+ { { "?D<=C %s,%05x", "BRLE.%-2s D,C,%05x" } },
+ { { "?D<=C %s,rtn", "RETLE.%-2s D,C" } },
+
+ { { "sethex", "SETHEX" } },
+ { { "setdec", "SETDEC" } },
+ { { "RSTK=C", "PUSH.A C" } },
+ { { "C=RSTK", "POP.A C" } },
+
+ // load immediate
+ { { "D0= %02x", "MOVE.2 %02x,D0" } },
+ { { "D0= %04x", "MOVE.4 %04x,D0" } },
+ { { "D0= %05x", "MOVE.5 %05x,D0" } },
+
+ { { "D1= %02x", "MOVE.2 %02x,D1" } },
+ { { "D1= %04x", "MOVE.4 %04x,D1" } },
+ { { "D1= %05x", "MOVE.5 %05x,D1" } },
+
+ { { "P= %x", "MOVE %x,P" } },
+ { { "lC %-2x %s", "MOVE.P%-2x %s,C" } },
+
+ { { "clrST", "CLR.X ST" } },
+ { { "C=ST", "MOVE.X ST,C" } },
+ { { "ST=C", "MOVE.X C,ST" } },
+ { { "CSTex", "SWAP.X C,ST" } },
+
+ { { "P=P+1", "INC P" } },
+ { { "P=P-1", "DEC P" } },
+
+ // copy
+ { { "R0=A %s", "MOVE.%-2s A,R0" } },
+ { { "R1=A %s", "MOVE.%-2s A,R1" } },
+ { { "R2=A %s", "MOVE.%-2s A,R2" } },
+ { { "R3=A %s", "MOVE.%-2s A,R3" } },
+ { { "R4=A %s", "MOVE.%-2s A,R4" } },
+
+ { { "R0=C %s", "MOVE.%-2s C,R0" } },
+ { { "R1=C %s", "MOVE.%-2s C,R1" } },
+ { { "R2=C %s", "MOVE.%-2s C,R2" } },
+ { { "R3=C %s", "MOVE.%-2s C,R3" } },
+ { { "R4=C %s", "MOVE.%-2s C,R4" } },
+
+ { { "A=R0 %s", "MOVE.%-2s R0,A" } },
+ { { "A=R1 %s", "MOVE.%-2s R1,A" } },
+ { { "A=R2 %s", "MOVE.%-2s R2,A" } },
+ { { "A=R3 %s", "MOVE.%-2s R3,A" } },
+ { { "A=R4 %s", "MOVE.%-2s R4,A" } },
+
+ { { "C=R0 %s", "MOVE.%-2s R0,C" } },
+ { { "C=R1 %s", "MOVE.%-2s R1,C" } },
+ { { "C=R2 %s", "MOVE.%-2s R2,C" } },
+ { { "C=R3 %s", "MOVE.%-2s R3,C" } },
+ { { "C=R4 %s", "MOVE.%-2s R4,C" } },
+
+ { { "D0=A", "MOVE.A A,D0" } },
+ { { "D1=A", "MOVE.A A,D1" } },
+ { { "D0=C", "MOVE.A C,D0" } },
+ { { "D1=C", "MOVE.A C,D1" } },
+ { { "D0=As", "MOVE.S A,D0" } },
+ { { "D1=As", "MOVE.S A,D1" } },
+ { { "D0=Cs", "MOVE.S C,D0" } },
+ { { "D1=Cs", "MOVE.S C,D1" } },
+
+ // swap operations
+ { { "AR0ex %s", "SWAP.%-2s A,R0" } },
+ { { "AR1ex %s", "SWAP.%-2s A,R1" } },
+ { { "AR2ex %s", "SWAP.%-2s A,R2" } },
+ { { "AR3ex %s", "SWAP.%-2s A,R3" } },
+ { { "AR4ex %s", "SWAP.%-2s A,R4" } },
+
+ { { "CR0ex %s", "SWAP.%-2s C,R0" } },
+ { { "CR1ex %s", "SWAP.%-2s C,R1" } },
+ { { "CR2ex %s", "SWAP.%-2s C,R2" } },
+ { { "CR3ex %s", "SWAP.%-2s C,R3" } },
+ { { "CR4ex %s", "SWAP.%-2s C,R4" } },
+
+ { { "AD0ex", "SWAP.A A,D0" } },
+ { { "AD1ex", "SWAP.A A,D1" } },
+ { { "CD0ex", "SWAP.A C,D0" } },
+ { { "CD1ex", "SWAP.A C,D1" } },
+ { { "AD0xs", "SWAP.S A,D0" } },
+ { { "AD1xs", "SWAP.S A,D1" } },
+ { { "CD0xs", "SWAP.S C,D0" } },
+ { { "CD1xs", "SWAP.S C,D1" } },
+
+ // store
+ { { "Dat0=A %s", "MOVE.%-2s A,@D0" } },
+ { { "Dat1=A %s", "MOVE.%-2s A,@D0" } },
+ { { "Dat0=C %s", "MOVE.%-2s C,@D0" } },
+ { { "Dat1=C %s", "MOVE.%-2s C,@D0" } },
+
+ // load
+ { { "A=Dat0 %s", "MOVE.%-2s @D0,A" } },
+ { { "A=Dat1 %s", "MOVE.%-2s @D0,A" } },
+ { { "C=Dat0 %s", "MOVE.%-2s @D0,C" } },
+ { { "C=Dat1 %s", "MOVE.%-2s @D0,C" } },
+
+ // add/sub immediate
+ { { "D0=D0+ %x", "ADD.A %x,D0" } },
+ { { "D1=D1+ %x", "ADD.A %x,D1" } },
+ { { "D0=D0- %x", "SUB.A %x,D0" } },
+ { { "D1=D1- %x", "SUB.A %x,D1" } },
+
+ { { "A=A+ %s,%x", "ADD.%-2s %x,A" } },
+ { { "B=B+ %s,%x", "ADD.%-2s %x,B" } },
+ { { "C=C+ %s,%x", "ADD.%-2s %x,C" } },
+ { { "D=D+ %s,%x", "ADD.%-2s %x,D" } },
+ { { "A=A- %s,%x", "SUB.%-2s %x,A" } },
+ { { "B=B- %s,%x", "SUB.%-2s %x,B" } },
+ { { "C=C- %s,%x", "SUB.%-2s %x,C" } },
+ { { "D=D- %s,%x", "SUB.%-2s %x,D" } },
+
+ { { "A=A&B %s", "AND.%-2s B,A" } },
+ { { "B=B&C %s", "AND.%-2s C,B" } },
+ { { "C=C&A %s", "AND.%-2s A,C" } },
+ { { "D=D&C %s", "AND.%-2s C,D" } },
+ { { "B=B&A %s", "AND.%-2s A,B" } },
+ { { "C=C&B %s", "AND.%-2s B,C" } },
+ { { "A=A&C %s", "AND.%-2s C,A" } },
+ { { "C=C&D %s", "AND.%-2s D,C" } },
+
+ { { "A=A!B %s", "OR.%-2s B,A" } },
+ { { "B=B!C %s", "OR.%-2s C,B" } },
+ { { "C=C!A %s", "OR.%-2s A,C" } },
+ { { "D=D!C %s", "OR.%-2s C,D" } },
+ { { "B=B!A %s", "OR.%-2s A,B" } },
+ { { "C=C!B %s", "OR.%-2s B,C" } },
+ { { "A=A!C %s", "OR.%-2s C,A" } },
+ { { "C=C!D %s", "OR.%-2s D,C" } },
+
+ { { "Asrb %s", "SRB.%-2s A" } },
+ { { "Bsrb %s", "SRB.%-2s B" } },
+ { { "Csrb %s", "SRB.%-2s C" } },
+ { { "Dsrb %s", "SRB.%-2s D" } },
+
+ { { "Aslc %s", "RLN.%-2s A" } },
+ { { "Bslc %s", "RLN.%-2s B" } },
+ { { "Cslc %s", "RLN.%-2s C" } },
+ { { "Dslc %s", "RLN.%-2s D" } },
+ { { "Asrc %s", "RRN.%-2s A" } },
+ { { "Bsrc %s", "RRN.%-2s B" } },
+ { { "Csrc %s", "RRN.%-2s C" } },
+ { { "Dsrc %s", "RRN.%-2s D" } },
+
+ { { "A=A+B %s", "ADD.%-2s B,A" } },
+ { { "B=B+C %s", "ADD.%-2s C,B" } },
+ { { "C=C+A %s", "ADD.%-2s A,C" } },
+ { { "D=D+C %s", "ADD.%-2s C,D" } },
+ { { "A=A+A %s", "ADD.%-2s A,A" } },
+ { { "B=B+B %s", "ADD.%-2s B,B" } },
+ { { "C=C+C %s", "ADD.%-2s C,C" } },
+ { { "D=D+C %s", "ADD.%-2s D,D" } },
+ { { "B=B+A %s", "ADD.%-2s A,B" } },
+ { { "C=C+B %s", "ADD.%-2s B,C" } },
+ { { "A=A+C %s", "ADD.%-2s C,A" } },
+ { { "C=C+D %s", "ADD.%-2s D,C" } },
+ { { "A=A-1 %s", "DEC.%-2s A" } },
+ { { "B=B-1 %s", "DEC.%-2s B" } },
+ { { "C=C-1 %s", "DEC.%-2s C" } },
+ { { "D=D-1 %s", "DEC.%-2s D" } },
+
+ { { "A=A-B %s", "ADD.%-2s B,A" } },
+ { { "B=B-C %s", "ADD.%-2s C,B" } },
+ { { "C=C-A %s", "ADD.%-2s A,C" } },
+ { { "D=D-C %s", "ADD.%-2s C,D" } },
+ { { "A=A+1 %s", "INC.%-2s A" } },
+ { { "B=B+1 %s", "INC.%-2s B" } },
+ { { "C=C+1 %s", "INC.%-2s C" } },
+ { { "D=D+1 %s", "INC.%-2s D" } },
+ { { "B=B-A %s", "SUB.%-2s A,B" } },
+ { { "C=C-B %s", "SUB.%-2s B,C" } },
+ { { "A=A-C %s", "SUB.%-2s C,A" } },
+ { { "C=C-D %s", "SUB.%-2s D,C" } },
+ { { "A=B-A %s", "SUBN.%-2s B,A" } },
+ { { "B=C-B %s", "SUBN.%-2s C,B" } },
+ { { "C=A-C %s", "SUBN.%-2s A,C" } },
+ { { "D=C-D %s", "SUBN.%-2s C,D" } },
+
+ { { "A=0 %s", "CLR.%-2s A" } },
+ { { "B=0 %s", "CLR.%-2s B" } },
+ { { "C=0 %s", "CLR.%-2s C" } },
+ { { "D=0 %s", "CLR.%-2s D" } },
+ { { "A=B %s", "MOVE.%-2s B,A" } },
+ { { "B=C %s", "MOVE.%-2s C,B" } },
+ { { "C=A %s", "MOVE.%-2s A,C" } },
+ { { "D=C %s", "MOVE.%-2s C,D" } },
+ { { "B=A %s", "MOVE.%-2s A,B" } },
+ { { "C=B %s", "MOVE.%-2s B,C" } },
+ { { "A=C %s", "MOVE.%-2s C,A" } },
+ { { "C=D %s", "MOVE.%-2s D,C" } },
+ { { "ABex %s", "SWAP.%-2s A,B" } },
+ { { "BCex %s", "SWAP.%-2s B,C" } },
+ { { "ACex %s", "SWAP.%-2s A,C" } },
+ { { "CDex %s", "SWAP.%-2s C,D" } },
+
+ { { "Asl %s", "SLN.%-2s A" } },
+ { { "Bsl %s", "SLN.%-2s B" } },
+ { { "Csl %s", "SLN.%-2s C" } },
+ { { "Dsl %s", "SLN.%-2s D" } },
+ { { "Asr %s", "SRN.%-2s A" } },
+ { { "Bsr %s", "SRN.%-2s B" } },
+ { { "Csr %s", "SRN.%-2s C" } },
+ { { "Dsr %s", "SRN.%-2s D" } },
+ { { "A=-A %s", "NEG.%-2s A" } },
+ { { "B=-B %s", "NEG.%-2s B" } },
+ { { "C=-C %s", "NEG.%-2s C" } },
+ { { "D=-D %s", "NEG.%-2s D" } },
+ { { "A=-A-1 %s", "NOT.%-2s A" } },
+ { { "B=-B-1 %s", "NOT.%-2s B" } },
+ { { "C=-C-1 %s", "NOT.%-2s C" } },
+ { { "D=-D-1 %s", "NOT.%-2s D" } }
+
+};
+
+enum _opcode_sel
+{
+ Complete=-1,
+ Illegal,
+ Opcode0, Opcode0E, Opcode0Ea,
+ Opcode1, Opcode10, Opcode11, Opcode12, Opcode13, Opcode14, Opcode15,
+ Opcode8, Opcode80, Opcode808, Opcode8081,
+ Opcode81, Opcode818, Opcode818a, Opcode819, Opcode819a,
+ Opcode81A, Opcode81Aa, Opcode81Aa0,Opcode81Aa1, Opcode81Aa2, Opcode81B,
+ Opcode8A, Opcode8B,
+ Opcode9, Opcode9a, Opcode9b,
+ OpcodeA, OpcodeAa, OpcodeAb,
+ OpcodeB, OpcodeBa, OpcodeBb,
+ OpcodeC,
+ OpcodeD,
+ OpcodeE,
+ OpcodeF
+};
+typedef enum _opcode_sel opcode_sel;
+
+enum _opcode_adr
+{
+ AdrNone,
+ AdrAF, AdrA, AdrB, AdrCount,
+ BranchReturn, TestBranchRet, ImmBranch,
+ ABranchReturn, // address field A
+ xBranchReturn, // address field specified in previous opcode entry
+ Imm, ImmCount, ImmCload, Imm2, Imm4, Imm5,
+ Dis3, Dis3Call, Dis4, Dis4Call, Abs,
+ FieldP, FieldWP, FieldXS, FieldX, FieldS, FieldM, FieldB, FieldW, FieldA,
+ AdrImmCount
+};
+typedef enum _opcode_adr opcode_adr;
+
+typedef struct
+{
+ opcode_sel sel;
+ opcode_adr adr;
+ MNEMONICS mnemonic;
+} OPCODE;
+
+static const char *field_2_string(int adr_enum)
+{
+ switch (adr_enum) {
+ case FieldP: return P;
+ case FieldWP: return WP;
+ case FieldXS: return XS;
+ case FieldX: return X;
+ case FieldS: return S;
+ case FieldM: return M;
+ case FieldB: return B;
+ case FieldW: return W;
+ case FieldA: return A;
+ }
+ return 0;
+}
+
+static const OPCODE opcodes[][0x10]= {
+ {
+ // first digit
+ { Opcode0 },
+ { Opcode1 },
+ { Complete, Imm, PloadImm },
+ { Complete, ImmCload, CloadImm },
+ { Complete, BranchReturn, branchCarrySet},
+ { Complete, BranchReturn, branchCarryClear },
+ { Complete, Dis3, jump3 },
+ { Complete, Dis3Call, call3 },
+ { Opcode8 },
+ { Opcode9 },
+ { OpcodeA },
+ { OpcodeB },
+ { OpcodeC },
+ { OpcodeD },
+ { OpcodeE },
+ { OpcodeF }
+ }, { // 0
+ { Complete, AdrNone, ReturnSetXM },
+ { Complete, AdrNone, Return },
+ { Complete, AdrNone, ReturnSetCarry },
+ { Complete, AdrNone, ReturnClearCarry },
+ { Complete, AdrNone, SetHexMode },
+ { Complete, AdrNone, SetDecMode },
+ { Complete, AdrNone, PushC },
+ { Complete, AdrNone, PopC },
+ { Complete, AdrNone, clearST },
+ { Complete, AdrNone, CcopyST },
+ { Complete, AdrNone, STcopyC },
+ { Complete, AdrNone, swapCST },
+ { Complete, AdrNone, incP },
+ { Complete, AdrNone, decP },
+ { Opcode0E },
+ { Complete, AdrNone, ReturnFromInterrupt }
+ }, { //0E
+ { Opcode0Ea, AdrAF },
+ { Opcode0Ea, AdrAF },
+ { Opcode0Ea, AdrAF },
+ { Opcode0Ea, AdrAF },
+ { Opcode0Ea, AdrAF },
+ { Opcode0Ea, AdrAF },
+ { Opcode0Ea, AdrAF },
+ { Opcode0Ea, AdrAF },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Opcode0Ea, AdrAF }
+ }, { //0Ea
+ { Complete, AdrNone, AandB },
+ { Complete, AdrNone, BandC },
+ { Complete, AdrNone, CandA },
+ { Complete, AdrNone, DandC },
+ { Complete, AdrNone, BandA },
+ { Complete, AdrNone, CandB },
+ { Complete, AdrNone, AandC },
+ { Complete, AdrNone, CandD },
+ { Complete, AdrNone, AorB },
+ { Complete, AdrNone, BorC },
+ { Complete, AdrNone, CorA },
+ { Complete, AdrNone, DorC },
+ { Complete, AdrNone, BorA },
+ { Complete, AdrNone, CorB },
+ { Complete, AdrNone, AorC },
+ { Complete, AdrNone, CorD }
+ }, { //1
+ { Opcode10 },
+ { Opcode11 },
+ { Opcode12 },
+ { Opcode13 },
+ { Opcode14 },
+ { Opcode15 },
+ { Complete, ImmCount, D0addImm },
+ { Complete, ImmCount, D1addImm },
+ { Complete, ImmCount, D0subImm },
+ { Complete, Imm2, D0loadImm2 },
+ { Complete, Imm4, D0loadImm4 },
+ { Complete, Imm5, D0loadImm5 },
+ { Complete, ImmCount, D1subImm },
+ { Complete, Imm2, D1loadImm2 },
+ { Complete, Imm4, D1loadImm4 },
+ { Complete, Imm5, D1loadImm5 }
+ }, { //10
+ { Complete, FieldW, R0copyA },
+ { Complete, FieldW, R1copyA },
+ { Complete, FieldW, R2copyA },
+ { Complete, FieldW, R3copyA },
+ { Complete, FieldW, R4copyA },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Complete, FieldW, R0copyC },
+ { Complete, FieldW, R1copyC },
+ { Complete, FieldW, R2copyC },
+ { Complete, FieldW, R3copyC },
+ { Complete, FieldW, R4copyC },
+ { Illegal },
+ { Illegal },
+ { Illegal }
+ }, { //11
+ { Complete, FieldW, AcopyR0 },
+ { Complete, FieldW, AcopyR1 },
+ { Complete, FieldW, AcopyR2 },
+ { Complete, FieldW, AcopyR3 },
+ { Complete, FieldW, AcopyR4 },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Complete, FieldW, CcopyR0 },
+ { Complete, FieldW, CcopyR1 },
+ { Complete, FieldW, CcopyR2 },
+ { Complete, FieldW, CcopyR3 },
+ { Complete, FieldW, CcopyR4 },
+ { Illegal },
+ { Illegal },
+ { Illegal }
+ }, { //12
+ { Complete, FieldW, SwapAR0 },
+ { Complete, FieldW, SwapAR1 },
+ { Complete, FieldW, SwapAR2 },
+ { Complete, FieldW, SwapAR3 },
+ { Complete, FieldW, SwapAR4 },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Complete, FieldW, SwapCR0 },
+ { Complete, FieldW, SwapCR1 },
+ { Complete, FieldW, SwapCR2 },
+ { Complete, FieldW, SwapCR3 },
+ { Complete, FieldW, SwapCR4 },
+ { Illegal },
+ { Illegal },
+ { Illegal }
+ }, { //13
+ { Complete, FieldA, D0copyA },
+ { Complete, FieldA, D1copyA },
+ { Complete, FieldA, SwapAD0 },
+ { Complete, FieldA, SwapAD1 },
+ { Complete, FieldA, D0copyC },
+ { Complete, FieldA, D1copyC },
+ { Complete, FieldA, SwapCD0 },
+ { Complete, FieldA, SwapCD1 },
+ { Complete, FieldS, D0copyAShort },
+ { Complete, FieldS, D1copyAShort },
+ { Complete, FieldS, SwapAD0Short },
+ { Complete, FieldS, SwapAD1Short },
+ { Complete, FieldS, D0copyCShort },
+ { Complete, FieldS, D1copyCShort },
+ { Complete, FieldS, SwapCD0Short },
+ { Complete, FieldS, SwapCD1Short }
+ }, { //14
+ { Complete, FieldA, D0storeA },
+ { Complete, FieldA, D1storeA },
+ { Complete, FieldA, AloadD0 },
+ { Complete, FieldA, AloadD1 },
+ { Complete, FieldA, D0storeC },
+ { Complete, FieldA, D1storeC },
+ { Complete, FieldA, CloadD0 },
+ { Complete, FieldA, CloadD1 },
+ { Complete, FieldB, D0storeA },
+ { Complete, FieldB, D1storeA },
+ { Complete, FieldB, AloadD0 },
+ { Complete, FieldB, AloadD1 },
+ { Complete, FieldB, D0storeC },
+ { Complete, FieldB, D1storeC },
+ { Complete, FieldB, CloadD0 },
+ { Complete, FieldB, CloadD1 }
+ }, { //15
+ { Complete, AdrA, D0storeA },
+ { Complete, AdrA, D1storeA },
+ { Complete, AdrA, AloadD0 },
+ { Complete, AdrA, AloadD1 },
+ { Complete, AdrA, D0storeC },
+ { Complete, AdrA, D1storeC },
+ { Complete, AdrA, CloadD0 },
+ { Complete, AdrA, CloadD1 },
+ { Complete, AdrCount, D0storeA },
+ { Complete, AdrCount, D1storeA },
+ { Complete, AdrCount, AloadD0 },
+ { Complete, AdrCount, AloadD1 },
+ { Complete, AdrCount, D0storeC },
+ { Complete, AdrCount, D1storeC },
+ { Complete, AdrCount, CloadD0 },
+ { Complete, AdrCount, CloadD1 },
+ }, { //8
+ { Opcode80 },
+ { Opcode81 },
+ { Complete, Imm, clearHST },
+ { Complete, TestBranchRet, branchHSTclear },
+ { Complete, Imm, clearBitST },
+ { Complete, Imm, setBitST },
+ { Complete, TestBranchRet, branchSTclear },
+ { Complete, TestBranchRet, branchSTset },
+ { Complete, TestBranchRet, branchPdiffers},
+ { Complete, TestBranchRet, branchPequals},
+ { Opcode8A },
+ { Opcode8B },
+ { Complete, Dis4, jump4 },
+ { Complete, Abs, jump },
+ { Complete, Dis4Call, call4 },
+ { Complete, Abs, call }
+ }, { //80
+ { Complete, AdrNone, outCS },
+ { Complete, AdrNone, outC },
+ { Complete, AdrNone, inA },
+ { Complete, AdrNone, inC },
+ { Complete, AdrNone, unconfig },
+ { Complete, AdrNone, config },
+ { Complete, AdrNone, Cid },
+ { Complete, AdrNone, shutdown },
+ { Opcode808 },
+ { Complete, AdrNone, cp1 },
+ { Complete, AdrNone, reset },
+ { Complete, AdrNone, buscc },
+ { Complete, Imm, CcopyP },
+ { Complete, Imm, PcopyC },
+ { Complete, AdrNone, sreq },
+ { Complete, Imm, CswapP }
+ }, { //808
+ { Complete, AdrNone, inton },
+ { Opcode8081 },
+ { Complete, ImmCload, AloadImm },
+ { Complete, AdrNone, buscb },
+ { Complete, Imm, clearAbit },
+ { Complete, Imm, setAbit },
+ { Complete, TestBranchRet, branchAbitclear },
+ { Complete, TestBranchRet, branchAbitset },
+ { Complete, Imm, clearCbit },
+ { Complete, Imm, setCbit },
+ { Complete, TestBranchRet, branchCbitclear },
+ { Complete, TestBranchRet, branchCbitset },
+ { Complete, AdrNone, PCloadA },
+ { Complete, AdrNone, buscd },
+ { Complete, AdrNone, PCloadC },
+ { Complete, AdrNone, intoff }
+ }, { //8081
+ { Complete, AdrNone, rsi },
+ //! rest illegal
+ }, { //81
+ { Complete, FieldW, AshiftleftCarry },
+ { Complete, FieldW, BshiftleftCarry },
+ { Complete, FieldW, CshiftleftCarry },
+ { Complete, FieldW, DshiftleftCarry },
+ { Complete, FieldW, AshiftrightCarry },
+ { Complete, FieldW, BshiftrightCarry },
+ { Complete, FieldW, CshiftrightCarry },
+ { Complete, FieldW, DshiftrightCarry },
+ { Opcode818 },
+ { Opcode819 },
+ { Opcode81A },
+ { Opcode81B },
+ { Complete, FieldW, Ashiftrightbit },
+ { Complete, FieldW, Bshiftrightbit },
+ { Complete, FieldW, Cshiftrightbit },
+ { Complete, FieldW, Dshiftrightbit }
+ }, { //818
+ { Opcode818a, AdrAF },
+ { Opcode818a, AdrAF },
+ { Opcode818a, AdrAF },
+ { Opcode818a, AdrAF },
+ { Opcode818a, AdrAF },
+ { Opcode818a, AdrAF },
+ { Opcode818a, AdrAF },
+ { Opcode818a, AdrAF },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Opcode818a, AdrAF },
+ }, { //818a
+ { Complete, AdrImmCount, AaddImm },
+ { Complete, AdrImmCount, BaddImm },
+ { Complete, AdrImmCount, CaddImm },
+ { Complete, AdrImmCount, DaddImm },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Complete, AdrImmCount, AsubImm },
+ { Complete, AdrImmCount, BsubImm },
+ { Complete, AdrImmCount, CsubImm },
+ { Complete, AdrImmCount, DsubImm },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ }, { //819
+ { Opcode819a, AdrAF },
+ { Opcode819a, AdrAF },
+ { Opcode819a, AdrAF },
+ { Opcode819a, AdrAF },
+ { Opcode819a, AdrAF },
+ { Opcode819a, AdrAF },
+ { Opcode819a, AdrAF },
+ { Opcode819a, AdrAF }, //?
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Opcode819a, AdrAF },
+ }, { //819a }
+ { Complete, AdrNone, Ashiftright },
+ { Complete, AdrNone, Bshiftright },
+ { Complete, AdrNone, Cshiftright },
+ { Complete, AdrNone, Dshiftright },
+ //! rest illegal
+ }, { //81A
+ { Opcode81Aa, AdrAF },
+ { Opcode81Aa, AdrAF },
+ { Opcode81Aa, AdrAF },
+ { Opcode81Aa, AdrAF },
+ { Opcode81Aa, AdrAF },
+ { Opcode81Aa, AdrAF },
+ { Opcode81Aa, AdrAF },
+ { Opcode81Aa, AdrAF },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Opcode81Aa, AdrAF },
+ }, { //81Aa
+ { Opcode81Aa0 },
+ { Opcode81Aa1 },
+ { Opcode81Aa2 },
+ //! rest illegal
+ }, { //81Aa0
+ { Complete, AdrNone, R0copyA },
+ { Complete, AdrNone, R1copyA },
+ { Complete, AdrNone, R2copyA },
+ { Complete, AdrNone, R3copyA },
+ { Complete, AdrNone, R4copyA },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Complete, AdrNone, R0copyC },
+ { Complete, AdrNone, R1copyC },
+ { Complete, AdrNone, R2copyC },
+ { Complete, AdrNone, R3copyC },
+ { Complete, AdrNone, R4copyC },
+ { Illegal },
+ { Illegal },
+ { Illegal }
+ }, { //81Aa1
+ { Complete, AdrNone, AcopyR0 },
+ { Complete, AdrNone, AcopyR1 },
+ { Complete, AdrNone, AcopyR2 },
+ { Complete, AdrNone, AcopyR3 },
+ { Complete, AdrNone, AcopyR4 },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Complete, AdrNone, CcopyR0 },
+ { Complete, AdrNone, CcopyR1 },
+ { Complete, AdrNone, CcopyR2 },
+ { Complete, AdrNone, CcopyR3 },
+ { Complete, AdrNone, CcopyR4 },
+ { Illegal },
+ { Illegal },
+ { Illegal }
+ }, { //81Aa2
+ { Complete, AdrNone, SwapAR0 },
+ { Complete, AdrNone, SwapAR1 },
+ { Complete, AdrNone, SwapAR2 },
+ { Complete, AdrNone, SwapAR3 },
+ { Complete, AdrNone, SwapAR4 },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Complete, AdrNone, SwapCR0 },
+ { Complete, AdrNone, SwapCR1 },
+ { Complete, AdrNone, SwapCR2 },
+ { Complete, AdrNone, SwapCR3 },
+ { Complete, AdrNone, SwapCR4 },
+ { Illegal },
+ { Illegal },
+ { Illegal }
+ }, { //81B
+ { Illegal },
+ { Illegal },
+ { Complete, AdrNone, jumpA },
+ { Complete, AdrNone, jumpC },
+ { Complete, AdrNone, PCcopyA },
+ { Complete, AdrNone, PCcopyC },
+ { Complete, AdrNone, AcopyPC },
+ { Complete, AdrNone, CcopyPC },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal },
+ { Illegal }
+ }, { //8A
+ { Complete, ABranchReturn, branchAequalsB },
+ { Complete, ABranchReturn, branchBequalsC },
+ { Complete, ABranchReturn, branchAequalsC },
+ { Complete, ABranchReturn, branchCequalsD },
+ { Complete, ABranchReturn, branchAdiffersB },
+ { Complete, ABranchReturn, branchBdiffersC },
+ { Complete, ABranchReturn, branchAdiffersC },
+ { Complete, ABranchReturn, branchCdiffersD },
+ { Complete, ABranchReturn, branchAzero },
+ { Complete, ABranchReturn, branchBzero },
+ { Complete, ABranchReturn, branchCzero },
+ { Complete, ABranchReturn, branchDzero },
+ { Complete, ABranchReturn, branchAnotzero },
+ { Complete, ABranchReturn, branchBnotzero },
+ { Complete, ABranchReturn, branchCnotzero },
+ { Complete, ABranchReturn, branchDnotzero }
+ }, { //8B
+ { Complete, ABranchReturn, branchAgreaterB },
+ { Complete, ABranchReturn, branchBgreaterC },
+ { Complete, ABranchReturn, branchCgreaterA },
+ { Complete, ABranchReturn, branchDgreaterC },
+ { Complete, ABranchReturn, branchAlowerB },
+ { Complete, ABranchReturn, branchBlowerC },
+ { Complete, ABranchReturn, branchClowerA },
+ { Complete, ABranchReturn, branchDlowerC },
+ { Complete, ABranchReturn, branchAnotlowerB },
+ { Complete, ABranchReturn, branchBnotlowerC },
+ { Complete, ABranchReturn, branchCnotlowerA },
+ { Complete, ABranchReturn, branchDnotlowerC },
+ { Complete, ABranchReturn, branchAnotgreaterB },
+ { Complete, ABranchReturn, branchBnotgreaterC },
+ { Complete, ABranchReturn, branchCnotgreaterA },
+ { Complete, ABranchReturn, branchDnotgreaterC }
+ }, { //9
+ { Opcode9a, AdrA },
+ { Opcode9a, AdrA },
+ { Opcode9a, AdrA },
+ { Opcode9a, AdrA },
+ { Opcode9a, AdrA },
+ { Opcode9a, AdrA },
+ { Opcode9a, AdrA },
+ { Opcode9a, AdrA },
+ { Opcode9b, AdrB },
+ { Opcode9b, AdrB },
+ { Opcode9b, AdrB },
+ { Opcode9b, AdrB },
+ { Opcode9b, AdrB },
+ { Opcode9b, AdrB },
+ { Opcode9b, AdrB },
+ { Opcode9b, AdrB },
+ }, { //9a
+ { Complete, xBranchReturn, branchAequalsB },
+ { Complete, xBranchReturn, branchBequalsC },
+ { Complete, xBranchReturn, branchAequalsC },
+ { Complete, xBranchReturn, branchCequalsD },
+ { Complete, xBranchReturn, branchAdiffersB },
+ { Complete, xBranchReturn, branchBdiffersC },
+ { Complete, xBranchReturn, branchAdiffersC },
+ { Complete, xBranchReturn, branchCdiffersD },
+ { Complete, xBranchReturn, branchAzero },
+ { Complete, xBranchReturn, branchBzero },
+ { Complete, xBranchReturn, branchCzero },
+ { Complete, xBranchReturn, branchDzero },
+ { Complete, xBranchReturn, branchAnotzero },
+ { Complete, xBranchReturn, branchBnotzero },
+ { Complete, xBranchReturn, branchCnotzero },
+ { Complete, xBranchReturn, branchDnotzero }
+ }, { //9b
+ { Complete, xBranchReturn, branchAgreaterB },
+ { Complete, xBranchReturn, branchBgreaterC },
+ { Complete, xBranchReturn, branchCgreaterA },
+ { Complete, xBranchReturn, branchDgreaterC },
+ { Complete, xBranchReturn, branchAlowerB },
+ { Complete, xBranchReturn, branchBlowerC },
+ { Complete, xBranchReturn, branchClowerA },
+ { Complete, xBranchReturn, branchDlowerC },
+ { Complete, xBranchReturn, branchAnotlowerB },
+ { Complete, xBranchReturn, branchBnotlowerC },
+ { Complete, xBranchReturn, branchCnotlowerA },
+ { Complete, xBranchReturn, branchDnotlowerC },
+ { Complete, xBranchReturn, branchAnotgreaterB },
+ { Complete, xBranchReturn, branchBnotgreaterC },
+ { Complete, xBranchReturn, branchCnotgreaterA },
+ { Complete, xBranchReturn, branchDnotgreaterC }
+ }, { //A
+ { OpcodeAa, AdrA },
+ { OpcodeAa, AdrA },
+ { OpcodeAa, AdrA },
+ { OpcodeAa, AdrA },
+ { OpcodeAa, AdrA },
+ { OpcodeAa, AdrA },
+ { OpcodeAa, AdrA },
+ { OpcodeAa, AdrA },
+ { OpcodeAb, AdrB },
+ { OpcodeAb, AdrB },
+ { OpcodeAb, AdrB },
+ { OpcodeAb, AdrB },
+ { OpcodeAb, AdrB },
+ { OpcodeAb, AdrB },
+ { OpcodeAb, AdrB },
+ { OpcodeAb, AdrB },
+ }, { //Aa
+ { Complete, AdrNone, AaddB },
+ { Complete, AdrNone, BaddC },
+ { Complete, AdrNone, CaddA },
+ { Complete, AdrNone, DaddC },
+ { Complete, AdrNone, AaddA },
+ { Complete, AdrNone, BaddB },
+ { Complete, AdrNone, CaddC },
+ { Complete, AdrNone, DaddD },
+ { Complete, AdrNone, BaddA },
+ { Complete, AdrNone, CaddB },
+ { Complete, AdrNone, AaddC },
+ { Complete, AdrNone, CaddD },
+ { Complete, AdrNone, decA },
+ { Complete, AdrNone, decB },
+ { Complete, AdrNone, decC },
+ { Complete, AdrNone, decD },
+ }, { //Ab
+ { Complete, AdrNone, clearA },
+ { Complete, AdrNone, clearB },
+ { Complete, AdrNone, clearC },
+ { Complete, AdrNone, clearD },
+ { Complete, AdrNone, AcopyB },
+ { Complete, AdrNone, BcopyC },
+ { Complete, AdrNone, CcopyA },
+ { Complete, AdrNone, DcopyC },
+ { Complete, AdrNone, BcopyA },
+ { Complete, AdrNone, CcopyB },
+ { Complete, AdrNone, AcopyC },
+ { Complete, AdrNone, CcopyD },
+ { Complete, AdrNone, AswapB },
+ { Complete, AdrNone, BswapC },
+ { Complete, AdrNone, CswapA },
+ { Complete, AdrNone, DswapC }
+ }, { //B
+ { OpcodeBa, AdrA },
+ { OpcodeBa, AdrA },
+ { OpcodeBa, AdrA },
+ { OpcodeBa, AdrA },
+ { OpcodeBa, AdrA },
+ { OpcodeBa, AdrA },
+ { OpcodeBa, AdrA },
+ { OpcodeBa, AdrA },
+ { OpcodeBb, AdrB },
+ { OpcodeBb, AdrB },
+ { OpcodeBb, AdrB },
+ { OpcodeBb, AdrB },
+ { OpcodeBb, AdrB },
+ { OpcodeBb, AdrB },
+ { OpcodeBb, AdrB },
+ { OpcodeBb, AdrB },
+ }, { //Ba
+ { Complete, AdrNone, AsubB },
+ { Complete, AdrNone, BsubC },
+ { Complete, AdrNone, CsubA },
+ { Complete, AdrNone, DsubC },
+ { Complete, AdrNone, incA },
+ { Complete, AdrNone, incB },
+ { Complete, AdrNone, incC },
+ { Complete, AdrNone, incD },
+ { Complete, AdrNone, BsubA },
+ { Complete, AdrNone, CsubB },
+ { Complete, AdrNone, AsubC },
+ { Complete, AdrNone, CsubD },
+ { Complete, AdrNone, AsubnB },
+ { Complete, AdrNone, BsubnC },
+ { Complete, AdrNone, CsubnA },
+ { Complete, AdrNone, DsubnC },
+ }, { //Bb
+ { Complete, AdrNone, Ashiftleft },
+ { Complete, AdrNone, Bshiftleft },
+ { Complete, AdrNone, Cshiftleft },
+ { Complete, AdrNone, Dshiftleft },
+ { Complete, AdrNone, Ashiftright },
+ { Complete, AdrNone, Bshiftright },
+ { Complete, AdrNone, Cshiftright },
+ { Complete, AdrNone, Dshiftright },
+ { Complete, AdrNone, negateA },
+ { Complete, AdrNone, negateB },
+ { Complete, AdrNone, negateC },
+ { Complete, AdrNone, negateD },
+ { Complete, AdrNone, notA },
+ { Complete, AdrNone, notB },
+ { Complete, AdrNone, notC },
+ { Complete, AdrNone, notD }
+ }, { //C
+ { Complete, FieldA, AaddB },
+ { Complete, FieldA, BaddC },
+ { Complete, FieldA, CaddA },
+ { Complete, FieldA, DaddC },
+ { Complete, FieldA, AaddA },
+ { Complete, FieldA, BaddB },
+ { Complete, FieldA, CaddC },
+ { Complete, FieldA, DaddD },
+ { Complete, FieldA, BaddA },
+ { Complete, FieldA, CaddB },
+ { Complete, FieldA, AaddC },
+ { Complete, FieldA, CaddD },
+ { Complete, FieldA, decA },
+ { Complete, FieldA, decB },
+ { Complete, FieldA, decC },
+ { Complete, FieldA, decD }
+ }, { //D
+ { Complete, FieldA, clearA },
+ { Complete, FieldA, clearB },
+ { Complete, FieldA, clearC },
+ { Complete, FieldA, clearD },
+ { Complete, FieldA, AcopyB },
+ { Complete, FieldA, BcopyC },
+ { Complete, FieldA, CcopyA },
+ { Complete, FieldA, DcopyC },
+ { Complete, FieldA, BcopyA },
+ { Complete, FieldA, CcopyB },
+ { Complete, FieldA, AcopyC },
+ { Complete, FieldA, CcopyD },
+ { Complete, FieldA, AswapB },
+ { Complete, FieldA, BswapC },
+ { Complete, FieldA, CswapA },
+ { Complete, FieldA, DswapC }
+ }, { //E
+ { Complete, FieldA, AsubB },
+ { Complete, FieldA, BsubC },
+ { Complete, FieldA, CsubA },
+ { Complete, FieldA, DsubC },
+ { Complete, FieldA, incA },
+ { Complete, FieldA, incB },
+ { Complete, FieldA, incC },
+ { Complete, FieldA, incD },
+ { Complete, FieldA, BsubA },
+ { Complete, FieldA, CsubB },
+ { Complete, FieldA, AsubC },
+ { Complete, FieldA, CsubD },
+ { Complete, FieldA, AsubnB },
+ { Complete, FieldA, BsubnC },
+ { Complete, FieldA, CsubnA },
+ { Complete, FieldA, DsubnC }
+ }, { //F
+ { Complete, FieldA, Ashiftleft },
+ { Complete, FieldA, Bshiftleft },
+ { Complete, FieldA, Cshiftleft },
+ { Complete, FieldA, Dshiftleft },
+ { Complete, FieldA, Ashiftright },
+ { Complete, FieldA, Bshiftright },
+ { Complete, FieldA, Cshiftright },
+ { Complete, FieldA, Dshiftright },
+ { Complete, FieldA, negateA },
+ { Complete, FieldA, negateB },
+ { Complete, FieldA, negateC },
+ { Complete, FieldA, negateD },
+ { Complete, FieldA, notA },
+ { Complete, FieldA, notB },
+ { Complete, FieldA, notC },
+ { Complete, FieldA, notD }
+ }
+};
+
+static const int field_adr_af[]=
+{ FieldP, FieldWP, FieldXS, FieldX, FieldS, FieldM, FieldB, FieldW, 0, 0, 0, 0, 0, 0, 0, FieldA };
+
+static const int field_adr_a[]=
+{ FieldP, FieldWP, FieldXS, FieldX, FieldS, FieldM, FieldB, FieldW};
+
+static const int field_adr_b[]=
+{ FieldP, FieldWP, FieldXS, FieldX, FieldS, FieldM, FieldB, FieldW };
+
+CPU_DISASSEMBLE( saturn )
+{
+ int adr=0;
+
+ int cont=1; // operation still not complete disassembled
+ char bin[10]; int binsize=0; // protocollizing fetched nibbles
+ char number[17];
+ const OPCODE *level=opcodes[0]; //pointer to current digit
+ int op; // currently fetched nibble
+ int pos = 0;
+
+ int i,c,v;
+
+ while (cont)
+ {
+ op = oprom[pos++] & 0xf;
+ level+=op;
+ switch (level->sel) {
+ case Illegal:
+ cont=0;
+ bin[binsize++]=number_2_hex[op];
+ bin[binsize]=0;
+ sprintf(buffer, "???%s",bin);
+ break;
+ default:
+ bin[binsize++]=number_2_hex[op];
+ switch (level->adr) {
+ case AdrNone: break;
+ case AdrA:
+ adr=field_adr_a[op];
+ break;
+ case AdrAF:
+ adr=field_adr_af[op];
+ break;
+ case AdrB:
+ adr=field_adr_b[op&7];
+ break;
+ default:
+ cont = 0;
+ bin[binsize++]=number_2_hex[op];
+ bin[binsize]=0;
+ sprintf(buffer, "???%s",bin);
+ break;
+ }
+ break;
+ case Complete:
+ cont=0;
+ switch (level->adr==AdrNone?adr:level->adr) {
+ case AdrNone:
+ strcpy(buffer, mnemonics[level->mnemonic].name[set]);
+ break;
+ case Imm:
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], oprom[pos++]);
+ break;
+ case ImmCount:
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], oprom[pos++]+1);
+ break;
+ case AdrImmCount:
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], field_2_string(adr), oprom[pos++]+1);
+ break;
+ case AdrCount: // mnemonics have string %s for address field
+ snprintf(number,sizeof(number),"%x",oprom[pos++]+1);
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], number);
+ break;
+ case Imm2:
+ v=oprom[pos++];
+ v|=oprom[pos++]<<4;
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], v);
+ break;
+ case Imm4:
+ v=oprom[pos++];
+ v|=oprom[pos++]<<4;
+ v|=oprom[pos++]<<8;
+ v|=oprom[pos++]<<12;
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], v);
+ break;
+ case Imm5:
+ v=oprom[pos++];
+ v|=oprom[pos++]<<4;
+ v|=oprom[pos++]<<8;
+ v|=oprom[pos++]<<12;
+ v|=oprom[pos++]<<16;
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], v);
+ break;
+ case ImmCload:
+ c=i=oprom[pos++] & 0xf;
+ number[i+1]=0;
+ for (;i>=0; i--) number[i]=number_2_hex[oprom[pos++] & 0xf];
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], c+1, number);
+ break;
+ case Dis3:
+ SATURN_PEEKOP_DIS12(v);
+ c=(pc+pos-3+v)&0xfffff;
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], c );
+ break;
+ case Dis3Call:
+ SATURN_PEEKOP_DIS12(v);
+ c=(pc+pos+v)&0xfffff;
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], c );
+ break;
+ case Dis4:
+ SATURN_PEEKOP_DIS16(v);
+ c=(pc+pos-4+v)&0xfffff;
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], c );
+ break;
+ case Dis4Call:
+ SATURN_PEEKOP_DIS16(v);
+ c=(pc+pos+v)&0xfffff;
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], c );
+ break;
+ case Abs:
+ SATURN_PEEKOP_ADR(v);
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], v );
+ break;
+ case BranchReturn:
+ SATURN_PEEKOP_DIS8(v);
+ if (v==0) {
+ strcpy(buffer, mnemonics[level->mnemonic+1].name[set]);
+ } else {
+ c=(pc+pos-2+v)&0xfffff;
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], c);
+ }
+ break;
+ case ABranchReturn:
+ SATURN_PEEKOP_DIS8(v);
+ if (v==0) {
+ sprintf(buffer, mnemonics[level->mnemonic+1].name[set], A);
+ } else {
+ c=(pc+pos-2+v)&0xfffff;
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], A, c);
+ }
+ break;
+ case xBranchReturn:
+ SATURN_PEEKOP_DIS8(v);
+ if (v==0) {
+ sprintf(buffer, mnemonics[level->mnemonic+1].name[set], field_2_string(adr));
+ } else {
+ c=(pc+pos-2+v)&0xfffff;
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], field_2_string(adr), c);
+ }
+ break;
+ case TestBranchRet:
+ i=oprom[pos++];
+ SATURN_PEEKOP_DIS8(v);
+ if (v==0) {
+ sprintf(buffer, mnemonics[level->mnemonic+1].name[set], i);
+ } else {
+ c=(pc+pos-2+v)&0xfffff;
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], i, c);
+ }
+ break;
+ case ImmBranch:
+ i=oprom[pos++];
+ SATURN_PEEKOP_DIS8(v);
+ c=(pc+pos-2+v)&0xfffff;
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], i, c);
+ break;
+ case FieldP:
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], P );
+ break;
+ case FieldWP:
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], WP );
+ break;
+ case FieldXS:
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], XS );
+ break;
+ case FieldX:
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], X );
+ break;
+ case FieldS:
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], S );
+ break;
+ case FieldM:
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], M );
+ break;
+ case FieldB:
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], B );
+ break;
+ case FieldA:
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], A );
+ break;
+ case FieldW:
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], W );
+ break;
+ case AdrA:
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], adr_a[oprom[pos++] & 0x7] );
+ break;
+ case AdrAF:
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], adr_af[oprom[pos++] & 0xf] );
+ break;
+ case AdrB:
+ sprintf(buffer, mnemonics[level->mnemonic].name[set], adr_b[oprom[pos++] & 0x7] );
+ break;
+ }
+ break;
+ }
+ level = opcodes[level->sel];
+ }
+
+ return pos;
+}
diff --git a/trunk/src/emu/cpu/sc61860/readpc.c b/trunk/src/emu/cpu/sc61860/readpc.c
new file mode 100644
index 00000000000..79900746c3f
--- /dev/null
+++ b/trunk/src/emu/cpu/sc61860/readpc.c
@@ -0,0 +1,195 @@
+#if 0
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/io.h>
+#include <fcntl.h>
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <dos.h>
+
+// gcc -O
+// important because of inb, outb
+
+/*
+ dumps data sent form sharp pc1401 into file
+ at sharp the following program must be started after
+ this dos program was started
+ simple dos utility
+ first arg (filename of file to be written) must be specified
+
+ ct eprop needed
+ changing to parallel port should be easy
+
+nearly all sharp pocket pc's system roms should be readable
+this way.
+
+for some early pocket pc's it would be necessary to load
+this program into memory.
+(they don't have poke/peek/call instructions,
+so this program can't be typed in)
+
+adapter sharp - cteprommer
+
+1
+2 6v
+3 gnd 8 bit textool gnd pin 20
+4 f0 data--> 8 bit textool data 0 pin 17
+5 f1 handshake --> 8 bit textool data 1 pin 18
+6 save
+7 load
+8 ib7 <--handshake 8 bit textool address 0 pin 16
+9 ib9
+10
+11
+
+problems with the handshake in at the sharp
+so I didn't use the handshake in the sharp side
+but the pc side must not be interrupted with interrupt
+(pure dos needed?)
+
+*/
+
+
+#define outb(v,adr) outportb(adr,v)
+#define inb(adr) inportb(adr)
+
+#if 0
+ /* this routine dump the memory (start 0)
+ in an endless loop,
+ the pc side must be started before this
+ actual version should be in mess/machine/pocketc.c
+ */
+
+1 restore: for i=16384 to 16455:read a: poke i,a: next i
+10 call 16384
+100 data
+#if 1
+ 18,4,//lip xl
+ 2,0,//lia 0 startaddress low
+ 219,//exam
+ 18,5,//lip xh
+ 2,0,//lia 0 startaddress high
+ 219,//exam
+//400f x:
+ // dump internal rom
+ 18,5,//lip 4
+ 89,//ldm
+ 218,//exab
+ 18,4,//lip 5
+ 89,//ldm
+ 4,//ix for increasing x
+ 0,0,//lii,0
+ 18,20,//lip 20
+ 53, //
+ 18,20,// lip 20
+ 219,//exam
+#else
+ 18,4,//lip xl
+ 2,255,//lia 0
+ 219,//exam
+ 18,5,//lip xh
+ 2,255,//lia 0
+ 219,//exam
+//400f x:
+ // dump external memory
+ 4, //ix
+ 87,// ldd
+#endif
+ 218,//exab
+
+
+
+ 0,4,//lii 4
+
+ //a:
+ 218,// exab
+ 90,// sl
+ 218,// exab
+ 18,94,// lip 94
+ 96,252,// anma 252
+ 2,2, //lia 2
+ 196,// adcm
+ 95,// outf
+ //b:
+ 204,//inb
+ 102,128,//tsia 0x80
+#if 0
+ 41,4,// jnzm b
+#else
+ // input not working reliable!
+ // so handshake removed, PC side must run with disabled
+ // interrupt to not lose data
+ 78,20, //wait 20
+#endif
+
+ 218,// exab
+ 90,// sl
+ 218,// exab
+ 18,94,// lip 94
+ 96,252,//anma 252
+ 2,0,// lia 0
+ 196,//adcm
+ 95,// outf
+ //c:
+ 204,//inb
+ 102,128,//tsia 0x80
+#if 0
+ 57,4,// jzm c
+#else
+ 78,20, //wait 20
+#endif
+
+ 65,//deci
+ 41,34,//jnzm a
+
+ 41,41,//jnzm x:
+
+ 55,// rtn
+// fill up with several 55
+// so you don't have to calculate the exact end in the loop
+#endif
+
+#define PORT_BASE 0x3e0
+
+int main(int argc, char *argv[])
+{
+ unsigned i,v,j,a;
+ char buffer[32768];
+ FILE *out=fopen(argv[1],"wb");
+
+#if 0
+ ioperm(PORT_BASE,8,1);
+ nice(-256);
+#endif
+ asm { cli }
+
+ outb(0x18,PORT_BASE+3); // VCC ON
+ outb(0xc0, PORT_BASE+2);
+ outb(7,PORT_BASE+6); // VPP 12.5, reset off
+
+ outb(0,PORT_BASE);
+ for(j=0;j<0x8000;j++) {
+ for (i=0,v=0;i<4;i++) {
+ for(;((a=inb(PORT_BASE+4))&2)==0; ) ;
+ v=(v<<1)|(a&1);
+ outb(1,PORT_BASE);
+ for(;((a=inb(PORT_BASE+4))&2)!=0; ) ;
+ v=(v<<1)|(a&1);
+ outb(0,PORT_BASE);
+ }
+ buffer[j]=v;
+// printf("%.2x\n",v);
+ }
+ asm { sti }
+ fwrite(buffer,2,0x4000,out);
+ fclose(out);
+
+#if 0
+ outb(8,PORT_BASE+2); // led off
+ outb(0,PORT_BASE+3); //VCC off
+ outb(0,PORT_BASE+6); //VPP off
+#endif
+ return 0;
+}
+
diff --git a/trunk/src/emu/cpu/sc61860/sc.h b/trunk/src/emu/cpu/sc61860/sc.h
new file mode 100644
index 00000000000..526e78f1f29
--- /dev/null
+++ b/trunk/src/emu/cpu/sc61860/sc.h
@@ -0,0 +1,32 @@
+#define I 0
+#define J 1
+#define A 2
+#define B 3
+#define XL 4
+#define XH 5
+#define YL 6
+#define YH 7
+#define K 8
+#define L 9
+#define V 10 // some docus m
+#define W 11 // some docus n
+#define IA 92
+#define IB 93
+#define F0 94
+#define C 95
+
+enum
+{
+ SC61860_PC=1, SC61860_DP,
+ SC61860_P, SC61860_Q, SC61860_R,
+ SC61860_CARRY,
+ SC61860_ZERO,
+ // the following are in the internal ram!
+ SC61860_BA,
+ SC61860_X, SC61860_Y,
+ SC61860_I, SC61860_J, SC61860_K, SC61860_L, SC61860_V, SC61860_W,
+ SC61860_H
+
+// SC61860_NMI_STATE,
+// SC61860_IRQ_STATE
+};
diff --git a/trunk/src/emu/cpu/sc61860/sc61860.c b/trunk/src/emu/cpu/sc61860/sc61860.c
new file mode 100644
index 00000000000..b943bbef7d6
--- /dev/null
+++ b/trunk/src/emu/cpu/sc61860/sc61860.c
@@ -0,0 +1,252 @@
+/*****************************************************************************
+ *
+ * sc61860.c
+ * portable sharp 61860 emulator interface
+ * (sharp pocket computers)
+ *
+ * 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.
+ *
+ * History of changes:
+ * 29.7.2001 Several changes listed below taken by Mario Konegger
+ * (konegger@itp.tu-graz.ac.at)
+ * Added 0x7f to set_reg, to prevent p,q,r, overflow.
+ * Changed 512ms timerinterval from 256 to 128, thus the
+ * duration of one period is 512ms.
+ * Extended execute procudure with HLT-mode of CPU.
+ *****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+
+#include "sc61860.h"
+#include "sc.h"
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+/****************************************************************************
+ * The 61860 registers.
+ ****************************************************************************/
+typedef struct _sc61860_state sc61860_state;
+struct _sc61860_state
+{
+ sc61860_cpu_core *config;
+ UINT8 p, q, r; //7 bits only?
+
+ UINT8 c; // port c, used for HLT.
+ UINT8 d, h;
+ UINT16 oldpc, pc, dp;
+
+ int carry, zero;
+
+ struct { int t2ms, t512ms; int count; } timer;
+
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ int icount;
+ UINT8 ram[0x100]; // internal special ram, should be 0x60, 0x100 to avoid memory corruption for now
+};
+
+INLINE sc61860_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == SC61860);
+ return (sc61860_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+UINT8 *sc61860_internal_ram(device_t *device)
+{
+ sc61860_state *cpustate = get_safe_token(device);
+ return cpustate->ram;
+}
+
+static TIMER_CALLBACK(sc61860_2ms_tick)
+{
+ sc61860_state *cpustate = (sc61860_state *)ptr;
+ if (--cpustate->timer.count == 0)
+ {
+ cpustate->timer.count = 128;
+ cpustate->timer.t512ms = !cpustate->timer.t512ms;
+ }
+ cpustate->timer.t2ms = !cpustate->timer.t2ms;
+}
+
+/***************************************************************
+ * include the opcode macros, functions and tables
+ ***************************************************************/
+#include "scops.c"
+#include "sctable.c"
+
+static CPU_RESET( sc61860 )
+{
+ sc61860_state *cpustate = get_safe_token(device);
+ cpustate->timer.t2ms=0;
+ cpustate->timer.t512ms=0;
+ cpustate->timer.count=256;
+ cpustate->pc=0;
+}
+
+static CPU_INIT( sc61860 )
+{
+ sc61860_state *cpustate = get_safe_token(device);
+ cpustate->config = (sc61860_cpu_core *) device->static_config();
+ device->machine().scheduler().timer_pulse(attotime::from_hz(500), FUNC(sc61860_2ms_tick), 0, cpustate);
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+}
+
+static CPU_EXECUTE( sc61860 )
+{
+ sc61860_state *cpustate = get_safe_token(device);
+
+ do
+ {
+ cpustate->oldpc = cpustate->pc;
+
+ debugger_instruction_hook(device, cpustate->pc);
+
+ sc61860_instruction(cpustate);
+
+#if 0
+ /* Are we in HLT-mode? */
+ if (cpustate->c & 4)
+ {
+ if ((cpustate->config && cpustate->config->ina && (cpustate->config->ina(cpustate)!=0)) || cpustate->timer.t512ms)
+ {
+ cpustate->c&=0xfb;
+ if (cpustate->config->outc) cpustate->config->outc(cpustate->c);
+ }
+ cpustate->icount-=4;
+ }
+ else if(cpustate->c & 8) {}
+
+ else sc61860_instruction(cpustate);
+#endif
+
+ } while (cpustate->icount > 0);
+}
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( sc61860 )
+{
+ sc61860_state *cpustate = get_safe_token(device);
+ switch (state)
+ {
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + SC61860_PC: cpustate->pc = info->i; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + SC61860_R: cpustate->r = info->i & 0x7F; break;
+ case CPUINFO_INT_REGISTER + SC61860_DP: cpustate->dp = info->i; break;
+ case CPUINFO_INT_REGISTER + SC61860_P: cpustate->p = info->i & 0x7F; break;
+ case CPUINFO_INT_REGISTER + SC61860_Q: cpustate->q = info->i & 0x7F; break;
+ case CPUINFO_INT_REGISTER + SC61860_CARRY: cpustate->carry = info->i; break;
+ case CPUINFO_INT_REGISTER + SC61860_ZERO: cpustate->zero = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( sc61860 )
+{
+ sc61860_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(sc61860_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 = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 2; 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 = 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_PREVIOUSPC: info->i = cpustate->oldpc; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + SC61860_PC: info->i = cpustate->pc; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + SC61860_R: info->i = cpustate->r; break;
+ case CPUINFO_INT_REGISTER + SC61860_DP: info->i = cpustate->dp; break;
+ case CPUINFO_INT_REGISTER + SC61860_P: info->i = cpustate->p; break;
+ case CPUINFO_INT_REGISTER + SC61860_Q: info->i = cpustate->q; break;
+ case CPUINFO_INT_REGISTER + SC61860_CARRY: info->i = cpustate->carry; break;
+ case CPUINFO_INT_REGISTER + SC61860_ZERO: info->i = cpustate->zero; 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(sc61860); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(sc61860); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(sc61860); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(sc61860); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(sc61860); 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, "SC61860"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "SC61860"); 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 Peter Trauner, all rights reserved."); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c", cpustate->zero?'Z':'.', cpustate->carry ? 'C':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + SC61860_PC: sprintf(info->s, "PC:%.4x", cpustate->pc);break;
+ case CPUINFO_STR_REGISTER + SC61860_DP: sprintf(info->s, "DP:%.4x", cpustate->dp);break;
+ case CPUINFO_STR_REGISTER + SC61860_P: sprintf(info->s, "P:%.2x", cpustate->p);break;
+ case CPUINFO_STR_REGISTER + SC61860_Q: sprintf(info->s, "Q:%.2x", cpustate->q);break;
+ case CPUINFO_STR_REGISTER + SC61860_R: sprintf(info->s, "R:%.2x", cpustate->r);break;
+ case CPUINFO_STR_REGISTER + SC61860_I: sprintf(info->s, "I:%.2x", cpustate->ram[I]);break;
+ case CPUINFO_STR_REGISTER + SC61860_J: sprintf(info->s, "J:%.2x", cpustate->ram[J]);break;
+ case CPUINFO_STR_REGISTER + SC61860_K: sprintf(info->s, "K:%.2x", cpustate->ram[K]);break;
+ case CPUINFO_STR_REGISTER + SC61860_L: sprintf(info->s, "L:%.2x", cpustate->ram[L]);break;
+ case CPUINFO_STR_REGISTER + SC61860_V: sprintf(info->s, "V:%.2x", cpustate->ram[V]);break;
+ case CPUINFO_STR_REGISTER + SC61860_W: sprintf(info->s, "W:%.2x", cpustate->ram[W]);break;
+ case CPUINFO_STR_REGISTER + SC61860_H: sprintf(info->s, "W:%.2x", cpustate->h);break;
+ case CPUINFO_STR_REGISTER + SC61860_BA: sprintf(info->s, "BA:%.2x%.2x", cpustate->ram[B], cpustate->ram[A]);break;
+ case CPUINFO_STR_REGISTER + SC61860_X: sprintf(info->s, "X: %.2x%.2x", cpustate->ram[XH], cpustate->ram[XL]);break;
+ case CPUINFO_STR_REGISTER + SC61860_Y: sprintf(info->s, "Y: %.2x%.2x", cpustate->ram[YH], cpustate->ram[YL]);break;
+ case CPUINFO_STR_REGISTER + SC61860_CARRY: sprintf(info->s, "Carry: %d", cpustate->carry);break;
+ case CPUINFO_STR_REGISTER + SC61860_ZERO: sprintf(info->s, "Zero: %d", cpustate->zero);break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(SC61860, sc61860);
diff --git a/trunk/src/emu/cpu/sc61860/sc61860.h b/trunk/src/emu/cpu/sc61860/sc61860.h
new file mode 100644
index 00000000000..16009bb0551
--- /dev/null
+++ b/trunk/src/emu/cpu/sc61860/sc61860.h
@@ -0,0 +1,60 @@
+/*****************************************************************************
+ *
+ * sc61860.h
+ * portable sharp 61860 emulator interface
+ * (sharp pocket computers)
+ *
+ * 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 __SC61860_H__
+#define __SC61860_H__
+
+/*
+ official names seam to be
+ ESR-H, ESR-J
+ (ESR-L SC62015 ist complete different)
+ */
+
+/* unsolved problems
+ the processor has 8 kbyte internal rom
+ only readable with special instructions and program execution
+ 64 kb external ram (first 8kbyte not seen for program execution?) */
+
+
+typedef struct _sc61860_cpu_core sc61860_cpu_core;
+struct _sc61860_cpu_core
+{
+ int (*reset)(device_t *device);
+ int (*brk)(device_t *device);
+ int (*x)(device_t *device);
+ int (*ina)(device_t *device);
+ void (*outa)(device_t *device, int);
+ int (*inb)(device_t *device);
+ void (*outb)(device_t *device, int);
+ void (*outc)(device_t *device, int);
+};
+
+CPU_DISASSEMBLE( sc61860 );
+
+/* this is though for power on/off of the sharps */
+UINT8 *sc61860_internal_ram(device_t *device);
+
+DECLARE_LEGACY_CPU_DEVICE(SC61860, sc61860);
+
+#endif /* __SC61860_H__ */
diff --git a/trunk/src/emu/cpu/sc61860/scdasm.c b/trunk/src/emu/cpu/sc61860/scdasm.c
new file mode 100644
index 00000000000..1ac4137bf72
--- /dev/null
+++ b/trunk/src/emu/cpu/sc61860/scdasm.c
@@ -0,0 +1,221 @@
+/*****************************************************************************
+ *
+ * scdasm.c
+ * portable sharp 61860 emulator interface
+ * (sharp pocket computers)
+ *
+ * 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 "sc61860.h"
+#include "sc.h"
+
+/*
+ new:
+ clra 0x23
+ nopt 0x33
+ nopt 0x68
+ nopt 0x6a
+ rz n 0x72, 0x73, 0x76, 0x77
+ tsma 0xc6
+ nopw 0xcd
+ nopw 0xd3
+ sz n 0xd7
+ nopw 0xda
+
+! writ 211 nopw?
+*/
+
+/* explanations for the sharp mnemonics
+ d data: external memory
+ m memory: internal memory (address in p register)
+ p register (internal memory address)
+ q register (internal memory address), internally used in several opcodes!?
+ r stack pointer (internal memory)
+ c carry flag
+ z zero flag
+
+ the following are special internal memory registers
+ a akkumulator: (2)
+ b b register: (3)
+ i,j,k,l,v,w counter
+ x external memory address
+ y external memory address
+ ia input/output (92)
+ ib input/output (93)
+ f0 output (94)
+ c output(95)
+
+ li load immediate
+ ld load accu
+ st store accu
+ or
+ an and
+ inc
+ dec
+ ad add
+ sb sub
+ cp compare
+ jr jump relativ
+ jp jump absolut
+ mv move
+ ex exchange
+*/
+
+
+typedef enum
+{
+ Ill,
+ Imp,
+ Imm, ImmW,
+ RelP, RelM,
+ Abs,
+ Ptc,
+ Etc,
+ Cal,
+ Lp
+} Adr;
+
+static const struct { const char *mnemonic; Adr adr; } table[]={
+ { "LII", Imm }, { "LIJ", Imm }, { "LIA", Imm }, { "LIB", Imm },
+ { "IX", Imp }, { "DX", Imp }, { "IY", Imp }, { "DY", Imp },
+ { "MVW", Imp }, { "EXW", Imp }, { "MVB", Imp }, { "EXB", Imp },
+ { "ADN", Imp }, { "SBN", Imp }, { "ADW", Imp }, { "SBW", Imp },
+
+ { "LIDP", ImmW}, { "LIDL", Imm }, { "LIP", Imm }, { "LIQ", Imm },
+ { "ADB", Imp }, { "SBB", Imp }, { "LIDP", ImmW}, { "LIDL", Imm },
+ { "MVWD", Imp }, { "EXWD", Imp }, { "MVBD", Imp }, { "EXBD", Imp },
+ { "SRW", Imp }, { "SLW", Imp }, { "FILM", Imp }, { "FILD", Imp },
+
+ { "LDP", Imp }, { "LPQ", Imp }, { "LPR", Imp }, { 0, Ill },
+ { "IXL", Imp }, { "DXL", Imp }, { "IYS", Imp }, { "DYS", Imp },
+ { "JRNZP", RelP}, { "JRNZM", RelM}, { "JRNCP", RelP}, { "JRNCM", RelM},
+ { "JRP", RelP}, { "JRM", RelM}, { 0, Ill }, { "LOOP", RelM},
+
+ { "STP", Imp }, { "STQ", Imp }, { "STR", Imp }, { 0, Ill },
+ { "PUSH", Imp }, { "DATA", Imp }, { 0, Ill }, { "RTN", Imp },
+ { "JRZP", RelP}, { "JRZM", RelM}, { "JRCP", RelP}, { "JRCM", RelM},
+ { 0, Ill }, { 0, Ill }, { 0, Ill }, { 0, Ill },
+
+ { "INCI", Imp }, { "DECI", Imp }, { "INCA", Imp }, { "DECA", Imp },
+ { "ADM", Imp }, { "SBM", Imp }, { "ANMA", Imp }, { "ORMA", Imp },
+ { "INCK", Imp }, { "DECK", Imp }, { "INCV", Imp }, { "DECV", Imp },
+ { "INA", Imp }, { "NOPW", Imp }, { "WAIT", Imm }, { "IPXL"/*CDN, lxn*/, Imp },
+
+ { "INCP", Imp }, { "DECP", Imp }, { "STD", Imp }, { "MVDM", Imp },
+ { "READM",/*mvmp*/ Imp }, { "MVMD", Imp }, { "READ"/*ldpc*/, Imp }, { "LDD", Imp },
+ { "SWP", Imp }, { "LDM", Imp }, { "SL", Imp }, { "POP", Imp },
+ { 0, Ill }, { "OUTA", Imp }, { 0, Ill }, { "OUTF", Imp },
+
+ { "ANIM", Imm }, { "ORIM", Imm }, { "TSIM", Imm }, { "CPIM", Imm },
+ { "ANIA", Imm }, { "ORIA", Imm }, { "TSIA", Imm }, { "CPIA", Imm },
+ { 0, Ill }, { "ETC", Etc }, { 0, Ill }, { "TEST", Imm },
+ { 0, Ill }, { 0, Ill }, { 0, Ill }, { "IPXH"/*CDN,lxp*/, Imp },
+
+ { "ADIM", Imm }, { "SBIM", Imm }, { 0, Ill }, { 0, Ill },
+ { "ADIA", Imm }, { "SBIA", Imm }, { 0, Ill }, { 0, Ill },
+ { "CALL", Abs }, { "JP", Abs }, { "PTC", Ptc }, { 0, Ill },
+ { "JPNZ", Abs }, { "JPNC", Abs }, { "JPZ", Abs }, { "JPC", Abs },
+
+
+ { "LP", Lp }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { "INCJ", Imp }, { "DECJ", Imp }, { "INCB", Imp }, { "DECB", Imp },
+ { "ACDM", Imp }, { "SBCM", Imp }, { 0, Ill }, { "CPMA", Imp },
+ { "INCL", Imp }, { "DECL", Imp }, { "INCW", Imp }, { "DECW", Imp },
+ { "INB", Imp }, { 0, Ill }, { "NOPT", Imp }, { 0, Ill },
+
+ { "SC", Imp }, { "RC", Imp }, { "SR", Imp }, { 0, Ill },
+ { "ANID", Imm }, { "ORID", Imm }, { "TSID", Imm }, { 0, Ill },
+ { "LEAVE", Imp }, { 0, Ill }, { "EXAB", Imp }, { "EXAM", Imp },
+ { 0, Ill }, { "OUTB", Imp }, { 0, Ill }, { "OUTC", Imp },
+
+ { "CAL", Imp }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+};
+
+CPU_DISASSEMBLE( sc61860 )
+{
+ const UINT8 *base_oprom = oprom;
+ int oper=*(oprom++);
+ int t;
+ UINT16 adr;
+
+ switch(oper&0xc0) {
+ case 0x80:
+ sprintf(buffer,"%-6s%.2x",table[oper&0x80].mnemonic, oper&0x3f);
+ break;
+ default:
+ switch(oper&0xe0) {
+ case 0xe0:
+ sprintf(buffer,"%-6s%.4x",table[oper&0xe0].mnemonic,
+ *(oprom++)|((oper&0x1f)<<8));
+ break;
+ default:
+ switch (table[oper].adr) {
+ case Ill: sprintf(buffer,"?%.2x",oper);break;
+ case Imp: sprintf(buffer,"%s",table[oper].mnemonic); break;
+ case Imm: sprintf(buffer,"%-6s%.2x",table[oper].mnemonic, *(oprom++)); break;
+ case ImmW:
+ adr=(oprom[0]<<8)|oprom[1];oprom+=2;
+ sprintf(buffer,"%-6s%.4x",table[oper].mnemonic, adr);
+ break;
+ case Abs:
+ adr=(oprom[0]<<8)|oprom[1];oprom+=2;
+ sprintf(buffer,"%-6s%.4x",table[oper].mnemonic, adr);
+ break;
+ case RelM:
+ adr=pc-*(oprom++);
+ sprintf(buffer,"%-6s%.4x",table[oper].mnemonic, adr&0xffff);
+ break;
+ case RelP:
+ adr=pc+*(oprom++);
+ sprintf(buffer,"%-6s%.4x",table[oper].mnemonic, adr&0xffff);
+ break;
+ case Ptc:
+ t=*(oprom++);
+ adr=(oprom[0]<<8)|oprom[1];oprom+=2;
+ sprintf(buffer,"%-6s%.2x,%.4x",table[oper].mnemonic,t, adr);
+ break;
+ case Etc:
+ sprintf(buffer,"%-6s",table[oper].mnemonic);
+ /*H imm, abs */
+ /* abs */
+ break;
+ case Cal: case Lp: break;
+ }
+ break;
+ }
+ break;
+ }
+ return oprom - base_oprom;
+}
diff --git a/trunk/src/emu/cpu/sc61860/scops.c b/trunk/src/emu/cpu/sc61860/scops.c
new file mode 100644
index 00000000000..84fed01c3ea
--- /dev/null
+++ b/trunk/src/emu/cpu/sc61860/scops.c
@@ -0,0 +1,773 @@
+/*****************************************************************************
+ *
+ * scops.c
+ * portable sharp 61860 emulator interface
+ * (sharp pocket computers)
+ *
+ * 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.
+ *
+ * History of changes:
+ * 21.07.2001 Several changes listed below were made by Mario Konegger
+ * (konegger@itp.tu-graz.ac.at)
+ * replaced buggy BCD-commands add_bcd, sub_bcd, add_bcd_a,
+ * sub_bcd_a and changed out_c, to implement HLT-mode of the CPU.
+ *
+ *****************************************************************************/
+
+INLINE UINT8 READ_OP(sc61860_state *cpustate)
+{
+ return cpustate->direct->read_decrypted_byte(cpustate->pc++);
+}
+
+INLINE UINT8 READ_OP_ARG(sc61860_state *cpustate)
+{
+ return cpustate->direct->read_raw_byte(cpustate->pc++);
+}
+
+INLINE UINT16 READ_OP_ARG_WORD(sc61860_state *cpustate)
+{
+ UINT16 t=cpustate->direct->read_decrypted_byte(cpustate->pc++)<<8;
+ t|=cpustate->direct->read_decrypted_byte(cpustate->pc++);
+ return t;
+}
+
+INLINE UINT8 READ_BYTE(sc61860_state *cpustate, UINT16 adr)
+{
+ return cpustate->program->read_byte(adr);
+}
+
+INLINE void WRITE_BYTE(sc61860_state *cpustate, UINT16 a, UINT8 v)
+{
+ cpustate->program->write_byte(a, v);
+}
+
+INLINE UINT8 READ_RAM(sc61860_state *cpustate, int r)
+{
+ return cpustate->ram[r];
+}
+
+INLINE void WRITE_RAM(sc61860_state *cpustate, int r, UINT8 v)
+{
+ cpustate->ram[r] = v;
+}
+
+INLINE void PUSH(sc61860_state *cpustate, UINT8 v)
+{
+ cpustate->r--;
+ WRITE_RAM(cpustate, cpustate->r, v);
+}
+
+INLINE UINT8 POP(sc61860_state *cpustate)
+{
+ UINT8 t = READ_RAM(cpustate, cpustate->r);
+ cpustate->r++;
+ return t;
+}
+
+INLINE void sc61860_load_imm(sc61860_state *cpustate, int r, UINT8 v)
+{
+ WRITE_RAM(cpustate, r, v);
+}
+
+INLINE void sc61860_load(sc61860_state *cpustate)
+{
+ WRITE_RAM(cpustate, A, READ_RAM(cpustate, cpustate->p));
+}
+
+INLINE void sc61860_load_imm_p(sc61860_state *cpustate, UINT8 v)
+{
+ cpustate->p=v&0x7f;
+}
+
+INLINE void sc61860_load_imm_q(sc61860_state *cpustate, UINT8 v)
+{
+ cpustate->q=v&0x7f;
+}
+
+INLINE void sc61860_load_r(sc61860_state *cpustate)
+{
+ cpustate->r = READ_RAM(cpustate, A) & 0x7f;
+}
+
+INLINE void sc61860_load_ext(sc61860_state *cpustate, int r)
+{
+ WRITE_RAM(cpustate, r, READ_BYTE(cpustate, cpustate->dp));
+}
+
+INLINE void sc61860_load_dp(sc61860_state *cpustate)
+{
+ cpustate->dp=READ_OP_ARG_WORD(cpustate);
+}
+
+INLINE void sc61860_load_dl(sc61860_state *cpustate)
+{
+ cpustate->dp=(cpustate->dp&~0xff)|READ_OP_ARG(cpustate);
+}
+
+INLINE void sc61860_store_p(sc61860_state *cpustate)
+{
+ WRITE_RAM(cpustate, A, cpustate->p);
+}
+
+INLINE void sc61860_store_q(sc61860_state *cpustate)
+{
+ WRITE_RAM(cpustate, A, cpustate->q);
+}
+
+INLINE void sc61860_store_r(sc61860_state *cpustate)
+{
+ WRITE_RAM(cpustate, A, cpustate->r);
+}
+
+INLINE void sc61860_store_ext(sc61860_state *cpustate, int r)
+{
+ WRITE_BYTE(cpustate, cpustate->dp, READ_RAM(cpustate, r));
+}
+
+INLINE void sc61860_exam(sc61860_state *cpustate, int a, int b)
+{
+ UINT8 t = READ_RAM(cpustate, a);
+ WRITE_RAM(cpustate, a, READ_RAM(cpustate, b));
+ WRITE_RAM(cpustate, b, t);
+}
+
+INLINE void sc61860_test(sc61860_state *cpustate, int reg, UINT8 value)
+{
+ cpustate->zero=(READ_RAM(cpustate, reg) & value)==0;
+}
+
+INLINE void sc61860_test_ext(sc61860_state *cpustate)
+{
+ cpustate->zero=(READ_BYTE(cpustate, cpustate->dp)&READ_OP_ARG(cpustate))==0;
+}
+
+INLINE void sc61860_and(sc61860_state *cpustate, int reg, UINT8 value)
+{
+ UINT8 t = READ_RAM(cpustate, reg) & value;
+ WRITE_RAM(cpustate, reg, t);
+ cpustate->zero=t==0;
+}
+
+INLINE void sc61860_and_ext(sc61860_state *cpustate)
+{
+ UINT8 t = READ_BYTE(cpustate, cpustate->dp) & READ_OP_ARG(cpustate);
+ cpustate->zero=t==0;
+ WRITE_BYTE(cpustate, cpustate->dp, t);
+}
+
+INLINE void sc61860_or(sc61860_state *cpustate, int reg, UINT8 value)
+{
+ UINT8 t = READ_RAM(cpustate, reg) | value;
+ WRITE_RAM(cpustate, reg, t);
+ cpustate->zero=t==0;
+}
+
+INLINE void sc61860_or_ext(sc61860_state *cpustate)
+{
+ UINT8 t=READ_BYTE(cpustate, cpustate->dp)|READ_OP_ARG(cpustate);
+ cpustate->zero=t==0;
+ WRITE_BYTE(cpustate, cpustate->dp, t);
+}
+
+INLINE void sc61860_rotate_right(sc61860_state *cpustate)
+{
+ int t = READ_RAM(cpustate, A);
+ if (cpustate->carry) t|=0x100;
+ cpustate->carry=t&1;
+ WRITE_RAM(cpustate, A, t>>1);
+}
+
+INLINE void sc61860_rotate_left(sc61860_state *cpustate)
+{
+ int t = READ_RAM(cpustate, A) << 1;
+ if (cpustate->carry) t|=1;
+ cpustate->carry=t&0x100;
+ WRITE_RAM(cpustate, A, t);
+}
+
+INLINE void sc61860_swap(sc61860_state *cpustate)
+{
+ int t = READ_RAM(cpustate, A);
+ WRITE_RAM(cpustate, A, (t<<4)|((t>>4)&0xf));
+}
+
+// q=reg sideeffect
+INLINE void sc61860_inc(sc61860_state *cpustate, int reg)
+{
+ UINT8 t = READ_RAM(cpustate, reg) + 1;
+ cpustate->q=reg;
+ WRITE_RAM(cpustate, reg, t);
+ cpustate->zero=t==0;
+ cpustate->carry=t==0;
+}
+
+INLINE void sc61860_inc_p(sc61860_state *cpustate)
+{
+ cpustate->p++;
+}
+
+// q=reg sideeffect
+INLINE void sc61860_dec(sc61860_state *cpustate, int reg)
+{
+ UINT8 t = READ_RAM(cpustate, reg) - 1;
+ cpustate->q=reg;
+ WRITE_RAM(cpustate, reg, t);
+ cpustate->zero=t==0;
+ cpustate->carry=t==0xff;
+}
+
+INLINE void sc61860_dec_p(sc61860_state *cpustate)
+{
+ cpustate->p--;
+}
+
+INLINE void sc61860_add(sc61860_state *cpustate, int reg, UINT8 value)
+{
+ int t = READ_RAM(cpustate, reg) + value;
+ WRITE_RAM(cpustate, reg, t);
+ cpustate->zero=(t&0xff)==0;
+ cpustate->carry=t>=0x100;
+}
+
+INLINE void sc61860_add_carry(sc61860_state *cpustate)
+{
+ int t = READ_RAM(cpustate, cpustate->p) + READ_RAM(cpustate, A);
+ if (cpustate->carry) t++;
+ WRITE_RAM(cpustate, cpustate->p, t);
+ cpustate->zero=(t&0xff)==0;
+ cpustate->carry=t>=0x100;
+}
+
+// p++ sideeffect
+INLINE void sc61860_add_word(sc61860_state *cpustate)
+{
+ int t = READ_RAM(cpustate, cpustate->p) + READ_RAM(cpustate, A), t2;
+ WRITE_RAM(cpustate, cpustate->p, t);
+ cpustate->p++;
+ t2 = READ_RAM(cpustate, cpustate->p) + READ_RAM(cpustate, B);
+ if (t>=0x100) t2++;
+ WRITE_RAM(cpustate, cpustate->p, t2);
+ cpustate->zero=(t2&0xff)==0 &&(t&0xff)==0;
+ cpustate->carry=t2>=0x100;
+}
+
+
+INLINE void sc61860_sub(sc61860_state *cpustate, int reg, UINT8 value)
+{
+ int t = READ_RAM(cpustate, reg) - value;
+ WRITE_RAM(cpustate, reg, t);
+ cpustate->zero=(t&0xff)==0;
+ cpustate->carry=t<0;
+}
+
+INLINE void sc61860_sub_carry(sc61860_state *cpustate)
+{
+ int t = READ_RAM(cpustate, cpustate->p) - READ_RAM(cpustate, A);
+ if (cpustate->carry) t--;
+ WRITE_RAM(cpustate, cpustate->p, t);
+ cpustate->zero=(t&0xff)==0;
+ cpustate->carry=t<0;
+}
+
+
+// p++ sideeffect
+INLINE void sc61860_sub_word(sc61860_state *cpustate)
+{
+ int t = READ_RAM(cpustate, cpustate->p) - READ_RAM(cpustate, A), t2;
+ WRITE_RAM(cpustate, cpustate->p, t);
+ cpustate->p++;
+ t2 = READ_RAM(cpustate, cpustate->p) - READ_RAM(cpustate, B);
+ if (t<0) t2--;
+ WRITE_RAM(cpustate, cpustate->p, t2);
+ cpustate->zero=(t2&0xff)==0 && (t&0xff)==0;
+ cpustate->carry=t2<0;
+}
+
+INLINE void sc61860_cmp(sc61860_state *cpustate, int reg, UINT8 value)
+{
+ int t = READ_RAM(cpustate, reg) - value;
+ cpustate->zero=t==0;
+ cpustate->carry=t<0;
+}
+
+INLINE void sc61860_pop(sc61860_state *cpustate)
+{
+ WRITE_RAM(cpustate, A, POP(cpustate));
+}
+
+INLINE void sc61860_push(sc61860_state *cpustate)
+{
+ PUSH(cpustate, READ_RAM(cpustate, A));
+}
+
+INLINE void sc61860_prepare_table_call(sc61860_state *cpustate)
+{
+ int adr;
+ cpustate->h=READ_OP(cpustate);
+ adr=READ_OP_ARG_WORD(cpustate);
+ PUSH(cpustate, adr>>8);
+ PUSH(cpustate, adr&0xff);
+}
+
+INLINE void sc61860_execute_table_call(sc61860_state *cpustate)
+{
+ int i, v, adr;
+ for (i=0; i<cpustate->h; i++) {
+ v=READ_OP(cpustate);
+ adr=READ_OP_ARG_WORD(cpustate);
+ cpustate->zero=v==READ_RAM(cpustate, A);
+ if (cpustate->zero) {
+ cpustate->pc=adr;
+ return;
+ }
+ }
+ cpustate->pc=READ_OP_ARG_WORD(cpustate);
+}
+
+
+INLINE void sc61860_call(sc61860_state *cpustate, UINT16 adr)
+{
+ PUSH(cpustate, cpustate->pc>>8);
+ PUSH(cpustate, cpustate->pc&0xff);
+ cpustate->pc=adr;
+}
+
+INLINE void sc61860_return(sc61860_state *cpustate)
+{
+ UINT16 t=POP(cpustate);
+ t|=POP(cpustate)<<8;
+ cpustate->pc=t;
+}
+
+INLINE void sc61860_jump(sc61860_state *cpustate, int yes)
+{
+ UINT16 adr = READ_OP_ARG_WORD(cpustate);
+ if (yes) {
+ cpustate->pc=adr;
+ }
+}
+
+INLINE void sc61860_jump_rel_plus(sc61860_state *cpustate, int yes)
+{
+ UINT16 adr = cpustate->pc + READ_OP_ARG(cpustate);
+ if (yes) {
+ cpustate->pc=adr;
+ cpustate->icount-=3;
+ }
+}
+
+INLINE void sc61860_jump_rel_minus(sc61860_state *cpustate, int yes)
+{
+ UINT16 adr = cpustate->pc - READ_OP_ARG(cpustate);
+ if (yes) {
+ cpustate->pc=adr;
+ cpustate->icount-=3;
+ }
+}
+
+INLINE void sc61860_loop(sc61860_state *cpustate)
+{
+ UINT16 adr = cpustate->pc - READ_OP_ARG(cpustate);
+ UINT8 t = READ_RAM(cpustate, cpustate->r) - 1;
+ WRITE_RAM(cpustate, cpustate->r, t);
+ cpustate->zero=t==0;
+ cpustate->carry=t==0xff;
+ if (!cpustate->carry) {
+ cpustate->pc=adr;
+ adr=POP(cpustate);
+ cpustate->icount-=3;
+ }
+}
+
+INLINE void sc61860_leave(sc61860_state *cpustate)
+{
+ WRITE_RAM(cpustate, cpustate->r, 0);
+}
+
+INLINE void sc61860_wait(sc61860_state *cpustate)
+{
+ int t=READ_OP(cpustate);
+ cpustate->icount-=t;
+ cpustate->icount-=t;
+ cpustate->icount-=3;
+}
+
+INLINE void sc61860_set_carry(sc61860_state *cpustate)
+{
+ cpustate->carry=1;
+ cpustate->zero=1;
+}
+
+INLINE void sc61860_reset_carry(sc61860_state *cpustate)
+{
+ cpustate->carry=0;
+ cpustate->zero=1;
+}
+
+INLINE void sc61860_out_a(sc61860_state *cpustate)
+{
+ cpustate->q=IA;
+ if (cpustate->config&&cpustate->config->outa)
+ cpustate->config->outa(cpustate->device, READ_RAM(cpustate, IA));
+}
+
+INLINE void sc61860_out_b(sc61860_state *cpustate)
+{
+ cpustate->q=IB;
+ if (cpustate->config&&cpustate->config->outb)
+ cpustate->config->outb(cpustate->device, READ_RAM(cpustate, IB));
+}
+
+INLINE void sc61860_out_f(sc61860_state *cpustate)
+{
+ cpustate->q=F0;
+ /*READ_RAM(cpustate, F0); */
+}
+
+
+/* c0 display on
+ c1 counter reset
+ c2 cpu halt
+ c3 computer off
+ c4 beeper frequency (1 4khz, 0 2khz), or (c5=0) membran pos1/pos2
+ c5 beeper on
+ c6 beeper steuerung*/
+INLINE void sc61860_out_c(sc61860_state *cpustate)
+{
+ cpustate->q=C;
+ if (cpustate->config&&cpustate->config->outc)
+ cpustate->config->outc(cpustate->device, READ_RAM(cpustate, C));
+ cpustate->c = READ_RAM(cpustate, C);
+}
+
+INLINE void sc61860_in_a(sc61860_state *cpustate)
+{
+ int data=0;
+ if (cpustate->config&&cpustate->config->ina) data=cpustate->config->ina(cpustate->device);
+ WRITE_RAM(cpustate, A, data);
+ cpustate->zero=data==0;
+}
+
+INLINE void sc61860_in_b(sc61860_state *cpustate)
+{
+ int data=0;
+ if (cpustate->config&&cpustate->config->inb) data=cpustate->config->inb(cpustate->device);
+ WRITE_RAM(cpustate, A, data);
+ cpustate->zero=data==0;
+}
+
+/* 0 systemclock 512ms
+ 1 systemclock 2ms
+ 2 ?
+ 3 brk/on key
+ 4 ?
+ 5 ?
+ 6 reset
+ 7 cassette input */
+INLINE void sc61860_test_special(sc61860_state *cpustate)
+{
+ int t=0;
+ if (cpustate->timer.t512ms) t|=1;
+ if (cpustate->timer.t2ms) t|=2;
+ if (cpustate->config&&cpustate->config->brk&&cpustate->config->brk(cpustate->device)) t|=8;
+ if (cpustate->config&&cpustate->config->reset&&cpustate->config->reset(cpustate->device)) t|=0x40;
+ if (cpustate->config&&cpustate->config->x&&cpustate->config->x(cpustate->device)) t|=0x80;
+
+ cpustate->zero=(t&READ_OP(cpustate))==0;
+}
+
+/************************************************************************************
+ "string" operations
+***********************************************************************************/
+
+// p-=I+1 sideeffect
+INLINE void sc61860_add_bcd_a(sc61860_state *cpustate)
+{
+ UINT8 help = READ_RAM(cpustate, A);
+ int i, hlp, hlp1 = 0;
+ cpustate->zero=1;
+ for (i=0; i <= READ_RAM(cpustate, I); i++) {
+ int t = READ_RAM(cpustate, cpustate->p);
+ hlp1 = (t & 0x0f) + (help & 0x0f) + hlp1;
+ if (hlp1 > 9) { hlp = hlp1 - 0x0a; hlp1 = 0x10; }
+ else { hlp = hlp1; hlp1 = 0x00; }
+ hlp1 = (t & 0xf0) + (help & 0xf0) + hlp1;
+ if (hlp1 > 0x90) { WRITE_RAM(cpustate, cpustate->p, hlp1 - 0xa0 + hlp); hlp1 = 1; }
+ else { WRITE_RAM(cpustate, cpustate->p, hlp1 + hlp); hlp1 = 0; }
+ if ( READ_RAM(cpustate, cpustate->p) != 0 ) cpustate->zero = 0;
+ cpustate->p--;
+ help = 0;
+ }
+ cpustate->carry= ( hlp1 ) ? 1 : 0;
+ cpustate->icount-=3*(READ_RAM(cpustate, I)+1);
+}
+
+
+// p-=I+1, q-=I+2 sideeffect
+INLINE void sc61860_add_bcd(sc61860_state *cpustate)
+{
+ int i, hlp, hlp1 = 0;
+ cpustate->zero=1;
+ for (i=0; i <= READ_RAM(cpustate, I); i++) {
+ int t = READ_RAM(cpustate, cpustate->p);
+ int t2 = READ_RAM(cpustate, cpustate->q);
+ hlp1 = (t & 0x0f) + (t2 & 0x0f) + hlp1;
+ if (hlp1 > 9) { hlp = hlp1 - 0x0a; hlp1 = 0x10; }
+ else { hlp = hlp1; hlp1 = 0x00; }
+ hlp1 = (t & 0xf0) + (t2 & 0xf0) + hlp1;
+ cpustate->q--;
+ if (hlp1 > 0x90) { WRITE_RAM(cpustate, cpustate->p, hlp1 - 0xa0 + hlp); hlp1 = 1; }
+ else { WRITE_RAM(cpustate, cpustate->p, hlp1 + hlp); hlp1 = 0; }
+ if ( READ_RAM(cpustate, cpustate->p) != 0 ) cpustate->zero = 0;
+ cpustate->p--;
+ }
+ cpustate->carry= ( hlp1 ) ? 1 : 0;
+ cpustate->icount-=3*(READ_RAM(cpustate, I)+1);
+ cpustate->q--;
+}
+
+
+// p-=I+1 sideeffect
+INLINE void sc61860_sub_bcd_a(sc61860_state *cpustate)
+{
+ UINT8 help = READ_RAM(cpustate, A);
+ int i, hlp, hlp1 = 0;
+ cpustate->zero=1;
+ for (i=0; i <= READ_RAM(cpustate, I); i++) {
+ int t = READ_RAM(cpustate, cpustate->p);
+ hlp1 = (t & 0x0f) - (help & 0x0f) - hlp1;
+ if ( hlp1 < 0 ) { hlp = hlp1 + 0x0a; hlp1 = 0x10; }
+ else { hlp = hlp1; hlp1 = 0x00; }
+ hlp1 = (t & 0xf0) - (help & 0xf0) - hlp1;
+ if ( hlp1 < 0 ) { WRITE_RAM(cpustate, cpustate->p, hlp1 + 0xa0 + hlp); hlp1 = 1; }
+ else { WRITE_RAM(cpustate, cpustate->p, hlp1 + hlp); hlp1 = 0; }
+ if ( READ_RAM(cpustate, cpustate->p) != 0 ) cpustate->zero = 0;
+ cpustate->p--;
+ help = 0;
+ }
+ cpustate->carry= ( hlp1 ) ? 1 : 0;
+ cpustate->icount-=3*(READ_RAM(cpustate, I)+1);
+}
+
+
+// p-=I+1, q-=I+2 sideeffect
+INLINE void sc61860_sub_bcd(sc61860_state *cpustate)
+{
+ int i, hlp, hlp1 = 0;
+ cpustate->zero=1;
+ for (i=0; i <= READ_RAM(cpustate, I); i++) {
+ int t = READ_RAM(cpustate, cpustate->p);
+ int t2 = READ_RAM(cpustate, cpustate->q);
+ hlp1 = (t & 0x0f) - (t2 & 0x0f) - hlp1;
+ if ( hlp1 < 0 ) { hlp = hlp1 + 0x0a; hlp1 = 0x10; }
+ else { hlp = hlp1; hlp1 = 0x00; }
+ hlp1 = (t & 0xf0) - (t2 & 0xf0) - hlp1;
+ cpustate->q--;
+ if ( hlp1 < 0 ) { WRITE_RAM(cpustate, cpustate->p, hlp1 + 0xa0 + hlp); hlp1 = 1; }
+ else { WRITE_RAM(cpustate, cpustate->p, hlp1 + hlp); hlp1 = 0; }
+ if ( READ_RAM(cpustate, cpustate->p) != 0 ) cpustate->zero = 0;
+ cpustate->p--;
+ }
+ cpustate->carry= ( hlp1 ) ? 1 : 0;
+ cpustate->icount-=3*(READ_RAM(cpustate, I)+1);
+ cpustate->q--;
+}
+
+/* side effect p-i-1 -> p correct! */
+INLINE void sc61860_shift_left_nibble(sc61860_state *cpustate)
+{
+ int i,t=0;
+ for (i=0; i<=READ_RAM(cpustate, I); i++) {
+ t |= READ_RAM(cpustate, cpustate->p)<<4;
+ WRITE_RAM(cpustate, cpustate->p, t);
+ cpustate->p--;
+ t>>=8;
+ cpustate->icount--;
+ }
+}
+
+/* side effect p+i+1 -> p correct! */
+INLINE void sc61860_shift_right_nibble(sc61860_state *cpustate)
+{
+ int i,t=0;
+ for (i=0; i<=READ_RAM(cpustate, I); i++) {
+ t |= READ_RAM(cpustate, cpustate->p);
+ WRITE_RAM(cpustate, cpustate->p, t>>4);
+ cpustate->p++;
+ t=(t<<8)&0xf00;
+ cpustate->icount--;
+ }
+}
+
+// q=reg+1 sideeffect
+INLINE void sc61860_inc_load_dp(sc61860_state *cpustate, int reg)
+{
+ UINT8 t = READ_RAM(cpustate, reg) + 1;
+ UINT8 t2 = READ_RAM(cpustate, reg + 1);
+ WRITE_RAM(cpustate, reg, t);
+ if (t == 0) { t2++; WRITE_RAM(cpustate, reg + 1, t2); }
+ cpustate->dp=t|(t2<<8);
+ cpustate->q=reg+1;
+}
+
+// q=reg+1 sideeffect
+INLINE void sc61860_dec_load_dp(sc61860_state *cpustate, int reg)
+{
+ UINT8 t = READ_RAM(cpustate, reg) - 1;
+ UINT8 t2 = READ_RAM(cpustate, reg + 1);
+ WRITE_RAM(cpustate, reg, t);
+ if (t == 0xff) { t2--; WRITE_RAM(cpustate, reg + 1, t2); }
+ cpustate->dp=t|(t2<<8);
+ cpustate->q=reg+1;
+}
+
+// q=XH sideeffect
+INLINE void sc61860_inc_load_dp_load(sc61860_state *cpustate)
+{
+ sc61860_inc_load_dp(cpustate, XL);
+ WRITE_RAM(cpustate, A, READ_BYTE(cpustate, cpustate->dp));
+}
+
+// q=XH sideeffect
+INLINE void sc61860_dec_load_dp_load(sc61860_state *cpustate)
+{
+ sc61860_dec_load_dp(cpustate, XL);
+ WRITE_RAM(cpustate, A, READ_BYTE(cpustate, cpustate->dp));
+}
+
+// q=YH sideeffect
+INLINE void sc61860_inc_load_dp_store(sc61860_state *cpustate)
+{
+ sc61860_inc_load_dp(cpustate, YL);
+ WRITE_BYTE(cpustate, cpustate->dp, READ_RAM(cpustate, A));
+}
+
+// q=YH sideeffect
+INLINE void sc61860_dec_load_dp_store(sc61860_state *cpustate)
+{
+ sc61860_dec_load_dp(cpustate, YL);
+ WRITE_BYTE(cpustate, cpustate->dp, READ_RAM(cpustate, A));
+}
+
+INLINE void sc61860_fill(sc61860_state *cpustate)
+{
+ int i;
+ for (i=0;i<=READ_RAM(cpustate, I);i++) {
+ WRITE_RAM(cpustate, cpustate->p, READ_RAM(cpustate, A)); /* could be overwritten? */
+ cpustate->p++;
+ cpustate->icount--;
+ }
+}
+
+INLINE void sc61860_fill_ext(sc61860_state *cpustate)
+{
+ int i;
+ for (i=0;i<=READ_RAM(cpustate, I);i++) {
+ WRITE_BYTE(cpustate, cpustate->dp, READ_RAM(cpustate, A));
+ if (i!=READ_RAM(cpustate, I)) cpustate->dp++;
+ cpustate->icount-=3;
+ }
+}
+
+// p+=count+1, q+=count+1 sideeffects
+INLINE void sc61860_copy(sc61860_state *cpustate, int count)
+{
+ int i;
+ for (i=0; i<=count; i++) {
+ WRITE_RAM(cpustate, cpustate->p, READ_RAM(cpustate, cpustate->q));
+ cpustate->p++;
+ cpustate->q++;
+ cpustate->icount-=2;
+ }
+
+}
+
+// p+=count+1, dp+=count sideeffects
+INLINE void sc61860_copy_ext(sc61860_state *cpustate, int count)
+{
+ int i;
+ for (i=0; i<=count; i++) {
+ WRITE_RAM(cpustate, cpustate->p, READ_BYTE(cpustate, cpustate->dp));
+ cpustate->p++;
+ if (i!=count) cpustate->dp++;
+ cpustate->icount-=4;
+ }
+}
+
+INLINE void sc61860_copy_int(sc61860_state *cpustate, int count)
+{
+ int i;
+ for (i=0; i<=count; i++) {
+ UINT8 t = READ_BYTE(cpustate, (READ_RAM(cpustate, A)|(READ_RAM(cpustate, B)<<8))); /* internal rom! */
+ WRITE_RAM(cpustate, cpustate->p, t);
+ cpustate->p++;
+ if (i!=count) {
+ t = READ_RAM(cpustate, A) + 1;
+ WRITE_RAM(cpustate, A, t);
+ if (t==0) {
+ t = READ_RAM(cpustate, B) + 1;
+ WRITE_RAM(cpustate, B, t);
+ }
+ }
+ cpustate->icount-=4;
+ }
+}
+
+INLINE void sc61860_exchange(sc61860_state *cpustate, int count)
+{
+ int i;
+ UINT8 t;
+ for (i=0; i<=count; i++) {
+ t = READ_RAM(cpustate, cpustate->p);
+ WRITE_RAM(cpustate, cpustate->p, READ_RAM(cpustate, cpustate->q));
+ WRITE_RAM(cpustate, cpustate->q, t);
+ cpustate->p++;
+ cpustate->q++;
+ cpustate->icount-=3;
+ }
+}
+
+INLINE void sc61860_exchange_ext(sc61860_state *cpustate, int count)
+{
+ int i;
+ UINT8 t;
+ for (i=0; i<=count; i++) {
+ t = READ_RAM(cpustate, cpustate->p);
+ WRITE_RAM(cpustate, cpustate->p, READ_BYTE(cpustate, cpustate->dp));
+ cpustate->p++;
+ WRITE_BYTE(cpustate, cpustate->dp, t);
+ if (i!=count) cpustate->dp++;
+ cpustate->icount-=6;
+ }
+}
+
+// undocumented
+// only 1 opcode working in pc1403
+// both opcodes working in pc1350
+INLINE void sc61860_wait_x(sc61860_state *cpustate, int level)
+{
+ int c;
+ cpustate->zero=level;
+
+ if (cpustate->config&&cpustate->config->x) {
+ for (c=READ_RAM(cpustate, I); c>=0; c--) {
+ UINT8 t = (READ_RAM(cpustate, cpustate->p)+1)&0x7f;
+ WRITE_RAM(cpustate, cpustate->p, t);
+ cpustate->zero=cpustate->config->x(cpustate->device);
+ cpustate->icount-=4;
+ if (level != cpustate->zero) break;
+ }
+ }
+}
diff --git a/trunk/src/emu/cpu/sc61860/sctable.c b/trunk/src/emu/cpu/sc61860/sctable.c
new file mode 100644
index 00000000000..02e61f58957
--- /dev/null
+++ b/trunk/src/emu/cpu/sc61860/sctable.c
@@ -0,0 +1,144 @@
+
+static void sc61860_instruction(sc61860_state *cpustate)
+{
+ int oper=READ_OP(cpustate);
+ if ((oper&0xc0)==0x80) {
+ sc61860_load_imm_p(cpustate, oper&0x3f);cpustate->icount-=2;
+ } else if ((oper&0xe0)==0xe0) {
+ sc61860_call(cpustate, READ_OP(cpustate)|((oper&0x1f)<<8));cpustate->icount-=7;
+ } else {
+ switch(oper) {
+ case 0: sc61860_load_imm(cpustate, I, READ_OP(cpustate));cpustate->icount-=4;break;
+ case 1: sc61860_load_imm(cpustate, J, READ_OP(cpustate));cpustate->icount-=4;break;
+ case 2: sc61860_load_imm(cpustate, A, READ_OP(cpustate));cpustate->icount-=4;break;
+ case 3: sc61860_load_imm(cpustate, B, READ_OP(cpustate));cpustate->icount-=4;break;
+ case 4: sc61860_inc_load_dp(cpustate, XL);cpustate->icount-=6;break;
+ case 5: sc61860_dec_load_dp(cpustate, XL);cpustate->icount-=6;break;
+ case 6: sc61860_inc_load_dp(cpustate, YL);cpustate->icount-=6;break;
+ case 7: sc61860_dec_load_dp(cpustate, YL);cpustate->icount-=6;break;
+ case 8: sc61860_copy(cpustate, READ_RAM(cpustate, I));break;
+ case 9: sc61860_exchange(cpustate, READ_RAM(cpustate, I));break;
+ case 10: sc61860_copy(cpustate, READ_RAM(cpustate, J));break;
+ case 11: sc61860_exchange(cpustate, READ_RAM(cpustate, J));break;
+ case 12: sc61860_add_bcd_a(cpustate);cpustate->icount-=7;break;
+ case 13: sc61860_sub_bcd_a(cpustate);cpustate->icount-=7;break;
+ case 14: sc61860_add_bcd(cpustate);cpustate->icount-=7;break;
+ case 15: sc61860_sub_bcd(cpustate);cpustate->icount-=7;break;
+ case 16: sc61860_load_dp(cpustate);cpustate->icount-=8;break;
+ case 17: sc61860_load_dl(cpustate);cpustate->icount-=5;break;
+ case 18: sc61860_load_imm_p(cpustate, READ_OP(cpustate));cpustate->icount-=4;break;
+ case 19: sc61860_load_imm_q(cpustate, READ_OP(cpustate));cpustate->icount-=4;break;
+ case 20: sc61860_add_word(cpustate);cpustate->icount-=5;break;
+ case 21: sc61860_sub_word(cpustate);cpustate->icount-=5;break;
+ case 24: sc61860_copy_ext(cpustate, READ_RAM(cpustate, I));break;
+ case 25: sc61860_exchange_ext(cpustate, READ_RAM(cpustate, I));break;
+ case 26: sc61860_copy_ext(cpustate, READ_RAM(cpustate, J));break;
+ case 27: sc61860_exchange_ext(cpustate, READ_RAM(cpustate, J));break;
+ case 28: sc61860_shift_right_nibble(cpustate);cpustate->icount-=5;break;
+ case 29: sc61860_shift_left_nibble(cpustate);cpustate->icount-=5;break;
+ case 30: sc61860_fill(cpustate);cpustate->icount-=5;break;
+ case 31: sc61860_fill_ext(cpustate);cpustate->icount-=4;break;
+ case 32: sc61860_store_p(cpustate);cpustate->icount-=2;break;
+ case 33: sc61860_store_q(cpustate);cpustate->icount-=2;break;
+ case 34: sc61860_store_r(cpustate);cpustate->icount-=2;break;
+ case 36: sc61860_inc_load_dp_load(cpustate);cpustate->icount-=7;break;
+ case 37: sc61860_dec_load_dp_load(cpustate);cpustate->icount-=7;break;
+ case 38: sc61860_inc_load_dp_store(cpustate);cpustate->icount-=7;break;
+ case 39: sc61860_dec_load_dp_store(cpustate);cpustate->icount-=7;break;
+ case 40: sc61860_jump_rel_plus(cpustate, !cpustate->zero);cpustate->icount-=4;break;
+ case 41: sc61860_jump_rel_minus(cpustate, !cpustate->zero);cpustate->icount-=4;break;
+ case 42: sc61860_jump_rel_plus(cpustate, !cpustate->carry);cpustate->icount-=4;break;
+ case 43: sc61860_jump_rel_minus(cpustate, !cpustate->carry);cpustate->icount-=4;break;
+ case 44: sc61860_jump_rel_plus(cpustate, TRUE);cpustate->icount-=4;break;
+ case 45: sc61860_jump_rel_minus(cpustate, TRUE);cpustate->icount-=4;break;
+ case 47: sc61860_loop(cpustate);cpustate->icount-=7;break;
+ case 48: sc61860_load_imm_p(cpustate, READ_RAM(cpustate, A));cpustate->icount-=2;break;
+ case 49: sc61860_load_imm_q(cpustate, READ_RAM(cpustate, A));cpustate->icount-=2;break;
+ case 50: sc61860_load_r(cpustate);cpustate->icount-=2;break;
+ case 52: sc61860_push(cpustate);cpustate->icount-=3;break;
+ case 53: sc61860_copy_int(cpustate, READ_RAM(cpustate, I));break;
+ case 55: sc61860_return(cpustate);cpustate->icount-=4;break;
+ case 56: sc61860_jump_rel_plus(cpustate, cpustate->zero);cpustate->icount-=4;break;
+ case 57: sc61860_jump_rel_minus(cpustate, cpustate->zero);cpustate->icount-=4;break;
+ case 58: sc61860_jump_rel_plus(cpustate, cpustate->carry);cpustate->icount-=4;break;
+ case 59: sc61860_jump_rel_minus(cpustate, cpustate->carry);cpustate->icount-=4;break;
+ case 64: sc61860_inc(cpustate, I);cpustate->icount-=4;break;
+ case 65: sc61860_dec(cpustate, I);cpustate->icount-=4;break;
+ case 66: sc61860_inc(cpustate, A);cpustate->icount-=4;break;
+ case 67: sc61860_dec(cpustate, A);cpustate->icount-=4;break;
+ case 68: sc61860_add(cpustate, cpustate->p, READ_RAM(cpustate, A));cpustate->icount-=3;break;
+ case 69: sc61860_sub(cpustate, cpustate->p, READ_RAM(cpustate, A));cpustate->icount-=3;break;
+ case 70: sc61860_and(cpustate, cpustate->p, READ_RAM(cpustate, A));cpustate->icount-=3;break;
+ case 71: sc61860_or(cpustate, cpustate->p, READ_RAM(cpustate, A));cpustate->icount-=3;break;
+ case 72: sc61860_inc(cpustate, K);cpustate->icount-=4;break;
+ case 73: sc61860_dec(cpustate, K);cpustate->icount-=4;break;
+ case 74: sc61860_inc(cpustate, V);cpustate->icount-=4;break;
+ case 75: sc61860_dec(cpustate, V);cpustate->icount-=4;break;
+ case 76: sc61860_in_a(cpustate);cpustate->icount-=2;break;
+ case 77: /*nopw*/;cpustate->icount-=2;break;
+ case 78: sc61860_wait(cpustate);cpustate->icount-=6;break;
+ case 79: sc61860_wait_x(cpustate, FALSE);cpustate->icount-=1;break;
+ case 80: sc61860_inc_p(cpustate);cpustate->icount-=2;break;
+ case 81: sc61860_dec_p(cpustate);cpustate->icount-=2;break;
+ case 82: sc61860_store_ext(cpustate, A);cpustate->icount-=2;break;
+ case 83: sc61860_store_ext(cpustate, cpustate->p);cpustate->icount-=2;break;
+ case 84: sc61860_load_imm(cpustate, cpustate->p, READ_OP(cpustate));cpustate->icount-=3/*?*/;break; // undocumented
+ case 85: sc61860_load_ext(cpustate, cpustate->p);cpustate->icount-=3;break;
+ case 86: sc61860_load_imm(cpustate, cpustate->p, READ_OP(cpustate));cpustate->icount-=3/*?*/;break; // undocumented
+ case 87: sc61860_load_ext(cpustate, A);cpustate->icount-=3;break;
+ case 88: sc61860_swap(cpustate);cpustate->icount-=2;break;
+ case 89: sc61860_load(cpustate);cpustate->icount-=2;break;
+ case 90: sc61860_rotate_left(cpustate);cpustate->icount-=2;break;
+ case 91: sc61860_pop(cpustate);cpustate->icount-=2;break;
+ case 93: sc61860_out_a(cpustate);cpustate->icount-=3;break;
+ case 95: sc61860_out_f(cpustate);cpustate->icount-=3;break;
+ case 96: sc61860_and(cpustate, cpustate->p, READ_OP(cpustate));cpustate->icount-=4;break;
+ case 97: sc61860_or(cpustate, cpustate->p, READ_OP(cpustate));cpustate->icount-=4;break;
+ case 98: sc61860_test(cpustate, cpustate->p, READ_OP(cpustate));cpustate->icount-=4;break;
+ case 99: sc61860_cmp(cpustate, cpustate->p, READ_OP(cpustate));cpustate->icount-=4;break;
+ case 100: sc61860_and(cpustate, A, READ_OP(cpustate));cpustate->icount-=4;break;
+ case 101: sc61860_or(cpustate, A, READ_OP(cpustate));cpustate->icount-=4;break;
+ case 102: sc61860_test(cpustate, A, READ_OP(cpustate));cpustate->icount-=4;break;
+ case 103: sc61860_cmp(cpustate, A, READ_OP(cpustate));cpustate->icount-=4;break;
+ case 105: sc61860_execute_table_call(cpustate);cpustate->icount-=3;break;
+ case 107: sc61860_test_special(cpustate);cpustate->icount-=4;break;
+ case 111: sc61860_wait_x(cpustate, TRUE);cpustate->icount-=1;break;
+ case 112: sc61860_add(cpustate, cpustate->p, READ_OP(cpustate));cpustate->icount-=4;break;
+ case 113: sc61860_sub(cpustate, cpustate->p, READ_OP(cpustate));cpustate->icount-=4;break;
+ case 116: sc61860_add(cpustate, A, READ_OP(cpustate));cpustate->icount-=4;break;
+ case 117: sc61860_sub(cpustate, A, READ_OP(cpustate));cpustate->icount-=4;break;
+ case 120: sc61860_call(cpustate, READ_OP_ARG_WORD(cpustate));cpustate->icount-=8;break;
+ case 121: sc61860_jump(cpustate, 1);cpustate->icount-=6;break;
+ case 122: sc61860_prepare_table_call(cpustate);cpustate->icount-=9;break;
+ case 124: sc61860_jump(cpustate, !cpustate->zero);cpustate->icount-=6;break;
+ case 125: sc61860_jump(cpustate, !cpustate->carry);cpustate->icount-=6;break;
+ case 126: sc61860_jump(cpustate, cpustate->zero);cpustate->icount-=6;break;
+ case 127: sc61860_jump(cpustate, cpustate->carry);cpustate->icount-=6;break;
+ case 192: sc61860_inc(cpustate, J);cpustate->icount-=4;break;
+ case 193: sc61860_dec(cpustate, J);cpustate->icount-=4;break;
+ case 194: sc61860_inc(cpustate, B);cpustate->icount-=4;break;
+ case 195: sc61860_dec(cpustate, B);cpustate->icount-=4;break;
+ case 196: sc61860_add_carry(cpustate);cpustate->icount-=3;break;
+ case 197: sc61860_sub_carry(cpustate);cpustate->icount-=3;break;
+ case 199: sc61860_cmp(cpustate, cpustate->p, READ_RAM(cpustate, A));cpustate->icount-=3;break;
+ case 200: sc61860_inc(cpustate, L);cpustate->icount-=4;break;
+ case 201: sc61860_dec(cpustate, L);cpustate->icount-=4;break;
+ case 202: sc61860_inc(cpustate, W);cpustate->icount-=4;break;
+ case 203: sc61860_dec(cpustate, W);cpustate->icount-=4;break;
+ case 204: sc61860_in_b(cpustate);cpustate->icount-=2;break;
+ case 206: /*nopt*/;cpustate->icount-=3;break;
+ case 208: sc61860_set_carry(cpustate);cpustate->icount-=2;break;
+ case 209: sc61860_reset_carry(cpustate);cpustate->icount-=4;break;
+ case 210: sc61860_rotate_right(cpustate);cpustate->icount-=2;break;
+ case 212: sc61860_and_ext(cpustate);cpustate->icount-=6;break;
+ case 213: sc61860_or_ext(cpustate);cpustate->icount-=6;break;
+ case 214: sc61860_test_ext(cpustate);cpustate->icount-=6;break;
+ case 216: sc61860_leave(cpustate);cpustate->icount-=2;break;
+ case 218: sc61860_exam(cpustate, A, B);cpustate->icount-=3;break;
+ case 219: sc61860_exam(cpustate, A, cpustate->p);cpustate->icount-=3;break;
+ case 221: sc61860_out_b(cpustate);cpustate->icount-=2;break;
+ case 223: sc61860_out_c(cpustate);cpustate->icount-=2;break;
+ default: logerror("sc61860 illegal opcode at %.4x %.2x\n",cpustate->pc-1, oper);
+ }
+ }
+}
diff --git a/trunk/src/emu/cpu/scmp/scmp.c b/trunk/src/emu/cpu/scmp/scmp.c
new file mode 100644
index 00000000000..f4aacbcd132
--- /dev/null
+++ b/trunk/src/emu/cpu/scmp/scmp.c
@@ -0,0 +1,670 @@
+/*****************************************************************************
+ *
+ * scmp.c
+ *
+ * National Semiconductor SC/MP CPU Disassembly
+ *
+ * Initial version by Miodrag Milanovic
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "scmp.h"
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _scmp_state scmp_state;
+struct _scmp_state
+{
+ scmp_config config;
+ PAIR PC;
+ PAIR P1;
+ PAIR P2;
+ PAIR P3;
+ UINT8 AC;
+ UINT8 ER;
+ UINT8 SR;
+
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *io;
+ int icount;
+
+ devcb_resolved_write8 flag_out_func;
+ devcb_resolved_write_line sout_func;
+ devcb_resolved_read_line sin_func;
+ devcb_resolved_read_line sensea_func;
+ devcb_resolved_read_line senseb_func;
+ devcb_resolved_write_line halt_func;
+};
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE scmp_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == SCMP || device->type() == INS8060);
+ return (scmp_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+INLINE UINT16 ADD12(UINT16 addr, INT8 val)
+{
+ return ((addr + val) & 0x0fff) | (addr & 0xf000);
+}
+
+INLINE UINT8 ROP(scmp_state *cpustate)
+{
+ UINT16 pc = cpustate->PC.w.l;
+ cpustate->PC.w.l = ADD12(cpustate->PC.w.l,1);
+ return cpustate->direct->read_decrypted_byte( pc);
+}
+
+INLINE UINT8 ARG(scmp_state *cpustate)
+{
+ UINT16 pc = cpustate->PC.w.l;
+ cpustate->PC.w.l = ADD12(cpustate->PC.w.l,1);
+ return cpustate->direct->read_raw_byte(pc);
+}
+
+INLINE UINT8 RM(scmp_state *cpustate,UINT32 a)
+{
+ return cpustate->program->read_byte(a);
+}
+
+INLINE void WM(scmp_state *cpustate,UINT32 a, UINT8 v)
+{
+ cpustate->program->write_byte(a, v);
+}
+
+INLINE void illegal(scmp_state *cpustate,UINT8 opcode)
+{
+#if VERBOSE
+ UINT16 pc = cpustate->PC.w.l;
+ LOG(("SC/MP illegal instruction %04X $%02X\n", pc-1, opcode));
+#endif
+}
+
+INLINE PAIR *GET_PTR_REG(scmp_state *cpustate, int num)
+{
+ switch(num) {
+ case 1: return &cpustate->P1;
+ case 2: return &cpustate->P2;
+ case 3: return &cpustate->P3;
+ default :
+ return &cpustate->PC;
+ }
+}
+
+INLINE void BIN_ADD(scmp_state *cpustate, UINT8 val)
+{
+ UINT16 tmp = cpustate->AC + val + ((cpustate->SR >> 7) & 1);
+ UINT8 ov = (((cpustate->AC & 0x80)==(val & 0x80)) && ((cpustate->AC & 0x80)!=(tmp & 0x80))) ? 0x40 : 0x00;
+
+ cpustate->AC = tmp & 0xff;
+ cpustate->SR &= 0x3f; // clear CY/L and OV flag
+ cpustate->SR |= (tmp & 0x100) ? 0x80 : 0x00; // set CY/L
+ cpustate->SR |= ov;
+}
+
+INLINE void DEC_ADD(scmp_state *cpustate, UINT8 val)
+{
+ UINT16 tmp = cpustate->AC + val + ((cpustate->SR >> 7) & 1);
+ if ((tmp & 0x0f) > 9) tmp +=6;
+ cpustate->AC = tmp % 0xa0;
+ cpustate->SR &= 0x7f; // clear CY/L flag
+ cpustate->SR |= (tmp > 0x99) ? 0x80 : 0x00;
+}
+
+INLINE UINT16 GET_ADDR(scmp_state *cpustate, UINT8 code)
+{
+ UINT16 addr = 0;
+ INT8 offset = 0;
+ UINT16 retVal = 0;
+ UINT16 ptr = GET_PTR_REG(cpustate,code & 0x03)->w.l;
+
+ UINT8 arg = ARG(cpustate);
+ if (arg == 0x80) {
+ offset = cpustate->ER;
+ } else {
+ if (arg & 0x80) {
+ offset = (INT8)arg;
+ } else {
+ offset = arg;
+ }
+ }
+
+ addr = ADD12(ptr,offset);
+
+ if (code & 0x04) {
+ if (code & 0x03) {
+ // Auto-indexed
+ if (offset < 0) {
+ // pre decrement
+ GET_PTR_REG(cpustate,code & 0x03)->w.l = addr;
+ retVal = addr;
+ } else {
+ // post increment
+ retVal = ptr;
+ GET_PTR_REG(cpustate,code & 0x03)->w.l = addr;
+ }
+ } else {
+ // Immediate
+ }
+ } else {
+ // Indexed
+ retVal = addr;
+ }
+ return retVal;
+}
+
+static void execute_one(scmp_state *cpustate, int opcode)
+{
+ UINT8 tmp;
+ UINT8 ptr = opcode & 3;
+ if (BIT(opcode,7)) {
+ // two bytes instructions
+ switch (opcode)
+ {
+ // Memory Reference Instructions
+ case 0xc0 : case 0xc1 : case 0xc2 : case 0xc3 :
+ case 0xc5 : case 0xc6 : case 0xc7 :
+ //LD
+ cpustate->icount -= 18;
+ cpustate->AC = RM(cpustate,GET_ADDR(cpustate,opcode));
+ break;
+ case 0xc8 : case 0xc9 : case 0xca : case 0xcb :
+ case 0xcd : case 0xce : case 0xcf :
+ // ST
+ cpustate->icount -= 18;
+ WM(cpustate,GET_ADDR(cpustate,opcode),cpustate->AC);
+ break;
+ case 0xd0 : case 0xd1 : case 0xd2 : case 0xd3 :
+ case 0xd5 : case 0xd6 : case 0xd7 :
+ // AND
+ cpustate->icount -= 18;
+ cpustate->AC &= RM(cpustate,GET_ADDR(cpustate,opcode));
+ break;
+ case 0xd8 : case 0xd9 : case 0xda : case 0xdb :
+ case 0xdd : case 0xde : case 0xdf :
+ //OR
+ cpustate->icount -= 18;
+ cpustate->AC |= RM(cpustate,GET_ADDR(cpustate,opcode));
+ break;
+ case 0xe0 : case 0xe1 : case 0xe2 : case 0xe3 :
+ case 0xe5 : case 0xe6 : case 0xe7 :
+ // XOR
+ cpustate->icount -= 18;
+ cpustate->AC ^= RM(cpustate,GET_ADDR(cpustate,opcode));
+ break;
+ case 0xe8 : case 0xe9 : case 0xea : case 0xeb :
+ case 0xed : case 0xee : case 0xef :
+ // DAD
+ cpustate->icount -= 23;
+ DEC_ADD(cpustate,RM(cpustate,GET_ADDR(cpustate,opcode)));
+ break;
+ case 0xf0 : case 0xf1 : case 0xf2 : case 0xf3 :
+ case 0xf5 : case 0xf6 : case 0xf7 :
+ // ADD
+ cpustate->icount -= 19;
+ BIN_ADD(cpustate,RM(cpustate,GET_ADDR(cpustate,opcode)));
+ break;
+ case 0xf8 : case 0xf9 : case 0xfa : case 0xfb :
+ case 0xfd : case 0xfe : case 0xff :
+ // CAD
+ cpustate->icount -= 20;
+ BIN_ADD(cpustate,~RM(cpustate,GET_ADDR(cpustate,opcode)));
+ break;
+ // Memory Increment/Decrement Instructions
+ case 0xa8 : case 0xa9 : case 0xaa : case 0xab :
+ // IDL
+ {
+ UINT16 addr = GET_ADDR(cpustate,opcode);
+ cpustate->icount -= 22;
+ cpustate->AC = RM(cpustate,addr) + 1;
+ WM(cpustate,addr,cpustate->AC);
+ }
+ break;
+ case 0xb8 : case 0xb9 : case 0xba : case 0xbb :
+ // DLD
+ {
+ UINT16 addr = GET_ADDR(cpustate,opcode);
+ cpustate->icount -= 22;
+ cpustate->AC = RM(cpustate,addr) - 1;
+ WM(cpustate,addr,cpustate->AC);
+ }
+ break;
+ // Immediate Instructions
+ case 0xc4 : // LDI
+ cpustate->icount -= 10;
+ cpustate->AC = ARG(cpustate);
+ break;
+ case 0xd4 : // ANI
+ cpustate->icount -= 10;
+ cpustate->AC &= ARG(cpustate);
+ break;
+ case 0xdc : // ORI
+ cpustate->icount -= 10;
+ cpustate->AC |= ARG(cpustate);
+ break;
+ case 0xe4 : // XRI
+ cpustate->icount -= 10;
+ cpustate->AC ^= ARG(cpustate);
+ break;
+ case 0xec : // DAI
+ cpustate->icount -= 15;
+ DEC_ADD(cpustate,ARG(cpustate));
+ break;
+ case 0xf4 : // ADI
+ cpustate->icount -= 11;
+ BIN_ADD(cpustate,ARG(cpustate));
+ break;
+ case 0xfc : // CAI
+ cpustate->icount -= 12;
+ BIN_ADD(cpustate,~ARG(cpustate));
+ break;
+ // Transfer Instructions
+ case 0x90 : case 0x91 : case 0x92 : case 0x93 :// JMP
+ cpustate->icount -= 11;
+ cpustate->PC.w.l = ADD12(GET_PTR_REG(cpustate,ptr)->w.l,(INT8)ARG(cpustate));
+ break;
+ case 0x94 : case 0x95 : case 0x96 : case 0x97 :
+ // JP
+ cpustate->icount -= 9;
+ tmp = ARG(cpustate);
+ if (!(cpustate->AC & 0x80)) {
+ cpustate->PC.w.l = ADD12(GET_PTR_REG(cpustate,ptr)->w.l,(INT8)tmp);
+ cpustate->icount -= 2;
+ }
+ break;
+ case 0x98 : case 0x99 : case 0x9a : case 0x9b :
+ // JZ
+ cpustate->icount -= 9;
+ tmp = ARG(cpustate);
+ if (!cpustate->AC) {
+ cpustate->PC.w.l = ADD12(GET_PTR_REG(cpustate,ptr)->w.l,(INT8)tmp);
+ cpustate->icount -= 2;
+ }
+ break;
+ case 0x9c : case 0x9d : case 0x9e : case 0x9f :
+ // JNZ
+ cpustate->icount -= 9;
+ tmp = ARG(cpustate);
+ if (cpustate->AC) {
+ cpustate->PC.w.l = ADD12(GET_PTR_REG(cpustate,ptr)->w.l,(INT8)tmp);
+ cpustate->icount -= 2;
+ }
+ break;
+ // Double-Byte Miscellaneous Instructions
+ case 0x8f: // DLY
+ tmp = ARG(cpustate);
+ cpustate->icount -= 13 + (cpustate->AC * 2) + (((UINT32)tmp) << 1) + (((UINT32)tmp) << 9);
+ cpustate->AC = 0xff;
+ break;
+ // Others are illegal
+ default : cpustate->icount -= 1;
+ illegal (cpustate,opcode);
+ break;
+ }
+ } else {
+ // one byte instructions
+ switch (opcode)
+ {
+ // Extension Register Instructions
+ case 0x40: // LDE
+ cpustate->icount -= 6;
+ cpustate->AC = cpustate->ER;
+ break;
+ case 0x01: // XAE
+ cpustate->icount -= 7;
+ tmp = cpustate->AC;
+ cpustate->AC = cpustate->ER;
+ cpustate->ER = tmp;
+ break;
+ case 0x50: // ANE
+ cpustate->icount -= 6;
+ cpustate->AC &= cpustate->ER;
+ break;
+ case 0x58: // ORE
+ cpustate->icount -= 6;
+ cpustate->AC |= cpustate->ER;
+ break;
+ case 0x60: // XRE
+ cpustate->icount -= 6;
+ cpustate->AC ^= cpustate->ER;
+ break;
+ case 0x68: // DAE
+ cpustate->icount -= 11;
+ DEC_ADD(cpustate,cpustate->ER);
+ break;
+ case 0x70: // ADE
+ cpustate->icount -= 7;
+ BIN_ADD(cpustate,cpustate->ER);
+ break;
+ case 0x78: // CAE
+ cpustate->icount -= 8;
+ BIN_ADD(cpustate,~cpustate->ER);
+ break;
+ // Pointer Register Move Instructions
+ case 0x30: case 0x31: case 0x32: case 0x33: // XPAL
+ cpustate->icount -= 8;
+ tmp = cpustate->AC;
+ cpustate->AC = GET_PTR_REG(cpustate,ptr)->b.l;
+ GET_PTR_REG(cpustate,ptr)->b.l = tmp;
+ break;
+ case 0x34: case 0x35 :case 0x36: case 0x37:
+ // XPAH
+ cpustate->icount -= 8;
+ tmp = cpustate->AC;
+ cpustate->AC = GET_PTR_REG(cpustate,ptr)->b.h;
+ GET_PTR_REG(cpustate,ptr)->b.h = tmp;
+ break;
+ case 0x3c: case 0x3d :case 0x3e: case 0x3f:
+ // XPPC
+ {
+ UINT16 tmp16 = ADD12(cpustate->PC.w.l,-1); // Since PC is incremented we need to fix it
+ cpustate->icount -= 7;
+ cpustate->PC.w.l = GET_PTR_REG(cpustate,ptr)->w.l;
+ GET_PTR_REG(cpustate,ptr)->w.l = tmp16;
+ // After exchange CPU increment PC
+ cpustate->PC.w.l = ADD12(cpustate->PC.w.l,1);
+ }
+ break;
+ // Shift, Rotate, Serial I/O Instructions
+ case 0x19: // SIO
+ cpustate->icount -= 5;
+ cpustate->sout_func(cpustate->ER & 0x01);
+ cpustate->ER >>= 1;
+ cpustate->ER |= cpustate->sin_func() ? 0x80 : 0x00;
+ break;
+ case 0x1c: // SR
+ cpustate->icount -= 5;
+ cpustate->AC >>= 1;
+ break;
+ case 0x1d: // SRL
+ cpustate->icount -= 5;
+ cpustate->AC >>= 1;
+ cpustate->AC |= cpustate->SR & 0x80; // add C/L flag
+ break;
+ case 0x1e: // RR
+ cpustate->icount -= 5;
+ cpustate->AC = (cpustate->AC >> 1) | ((cpustate->AC & 0x01) << 7);
+ break;
+ case 0x1f: // RRL
+ cpustate->icount -= 5;
+ tmp = (cpustate->AC & 0x01) << 7;
+ cpustate->AC = (cpustate->AC >> 1) | (cpustate->SR & 0x80);
+ cpustate->SR = (cpustate->SR & 0x7f) | tmp;
+ break;
+ // Single Byte Miscellaneous Instructions
+ case 0x00: // HALT
+ cpustate->icount -= 8;
+ cpustate->halt_func(1);
+ cpustate->halt_func(0);
+ break;
+ case 0x02: // CCL
+ cpustate->icount -= 5;
+ cpustate->SR &= 0x7f;
+ break;
+ case 0x03: // SCL
+ cpustate->icount -= 5;
+ cpustate->SR |= 0x80;
+ break;
+ case 0x04: // DINT
+ cpustate->icount -= 6;
+ cpustate->SR &= 0xf7;
+ break;
+ case 0x05: // IEN
+ cpustate->icount -= 6;
+ cpustate->SR |= 0x08;
+ break;
+ case 0x06: // CSA
+ cpustate->icount -= 5;
+ cpustate->SR &= 0xcf; // clear SA and SB flags
+ cpustate->SR |= cpustate->sensea_func() ? 0x10 : 0x00;
+ cpustate->SR |= cpustate->senseb_func() ? 0x20 : 0x00;
+ cpustate->AC = cpustate->SR;
+ break;
+ case 0x07: // CAS
+ cpustate->icount -= 6;
+ cpustate->SR = cpustate->AC;
+ cpustate->flag_out_func(0, cpustate->SR & 0x07);
+ break;
+ case 0x08: // NOP
+ cpustate->icount -= 5;
+ break;
+ // Others are illegal
+ default : cpustate->icount -= 1;
+ illegal (cpustate,opcode);
+ break;
+ }
+ }
+}
+
+
+/***************************************************************************
+ COMMON EXECUTION
+***************************************************************************/
+static void take_interrupt(scmp_state *cpustate)
+{
+ UINT16 tmp = ADD12(cpustate->PC.w.l,-1); // We fix PC so at return it goes to current location
+ cpustate->SR &= 0xf7; // clear IE flag
+
+ cpustate->icount -= 8; // assumption
+ // do XPPC 3
+ cpustate->PC.w.l = GET_PTR_REG(cpustate,3)->w.l;
+ GET_PTR_REG(cpustate,3)->w.l = tmp;
+ // After exchange CPU increment PC
+ cpustate->PC.w.l = ADD12(cpustate->PC.w.l,1);
+}
+
+static CPU_EXECUTE( scmp )
+{
+ scmp_state *cpustate = get_safe_token(device);
+
+ do
+ {
+ if ((cpustate->SR & 0x08) && (cpustate->sensea_func())) {
+ take_interrupt(cpustate);
+ }
+ debugger_instruction_hook(device, cpustate->PC.d);
+ execute_one(cpustate, ROP(cpustate));
+
+ } while (cpustate->icount > 0);
+}
+
+/***************************************************************************
+ CORE INITIALIZATION
+***************************************************************************/
+
+static CPU_INIT( scmp )
+{
+ scmp_state *cpustate = get_safe_token(device);
+
+ if (device->static_config() != NULL)
+ cpustate->config = *(scmp_config *)device->static_config();
+
+ /* set up the state table */
+ {
+ device_state_interface *state;
+ device->interface(state);
+ state->state_add(SCMP_PC, "PC", cpustate->PC.w.l);
+ state->state_add(STATE_GENPC, "GENPC", cpustate->PC.w.l).noshow();
+ state->state_add(STATE_GENFLAGS, "GENFLAGS", cpustate->SR).noshow().formatstr("%8s");
+ state->state_add(SCMP_P1, "P1", cpustate->P1.w.l);
+ state->state_add(SCMP_P2, "P2", cpustate->P2.w.l);
+ state->state_add(SCMP_P3, "P3", cpustate->P3.w.l);
+ state->state_add(SCMP_AC, "AC", cpustate->AC);
+ state->state_add(SCMP_ER, "ER", cpustate->ER);
+ state->state_add(SCMP_SR, "SR", cpustate->SR);
+ }
+
+ cpustate->device = device;
+
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+
+ /* resolve callbacks */
+ cpustate->flag_out_func.resolve(cpustate->config.flag_out_func, *device);
+ cpustate->sout_func.resolve(cpustate->config.sout_func, *device);
+ cpustate->sin_func.resolve(cpustate->config.sin_func, *device);
+ cpustate->sensea_func.resolve(cpustate->config.sensea_func, *device);
+ cpustate->senseb_func.resolve(cpustate->config.senseb_func, *device);
+ cpustate->halt_func.resolve(cpustate->config.halt_func, *device);
+
+ device->save_item(NAME(cpustate->PC));
+ device->save_item(NAME(cpustate->P1));
+ device->save_item(NAME(cpustate->P2));
+ device->save_item(NAME(cpustate->P3));
+ device->save_item(NAME(cpustate->AC));
+ device->save_item(NAME(cpustate->ER));
+ device->save_item(NAME(cpustate->SR));
+}
+
+
+
+/***************************************************************************
+ COMMON RESET
+***************************************************************************/
+
+static CPU_RESET( scmp )
+{
+ scmp_state *cpustate = get_safe_token(device);
+
+ cpustate->PC.d = 0;
+ cpustate->P1.d = 0;
+ cpustate->P2.d = 0;
+ cpustate->P3.d = 0;
+ cpustate->AC = 0;
+ cpustate->ER = 0;
+ cpustate->SR = 0;
+}
+
+
+
+/***************************************************************************
+ COMMON STATE IMPORT/EXPORT
+***************************************************************************/
+
+static CPU_IMPORT_STATE( scmp )
+{
+}
+
+static CPU_EXPORT_STATE( scmp )
+{
+}
+
+static CPU_EXPORT_STRING( scmp )
+{
+ scmp_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ string.printf("%c%c%c%c%c%c%c%c",
+ (cpustate->SR & 0x80) ? 'C' : '.',
+ (cpustate->SR & 0x40) ? 'V' : '.',
+ (cpustate->SR & 0x20) ? 'B' : '.',
+ (cpustate->SR & 0x10) ? 'A' : '.',
+ (cpustate->SR & 0x08) ? 'I' : '.',
+ (cpustate->SR & 0x04) ? '2' : '.',
+ (cpustate->SR & 0x02) ? '1' : '.',
+ (cpustate->SR & 0x01) ? '0' : '.');
+ break;
+ }
+}
+
+/***************************************************************************
+ COMMON SET INFO
+***************************************************************************/
+static CPU_SET_INFO( scmp )
+{
+}
+
+/***************************************************************************
+ SCMP GET INFO
+***************************************************************************/
+
+CPU_GET_INFO( scmp )
+{
+ scmp_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(scmp_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 = 5; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 131593; break; // DLY instruction max time
+
+ 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;
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(scmp); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(scmp); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(scmp); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(scmp); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(scmp); break;
+ case CPUINFO_FCT_IMPORT_STATE: info->import_state = CPU_IMPORT_STATE_NAME(scmp); break;
+ case CPUINFO_FCT_EXPORT_STATE: info->export_state = CPU_EXPORT_STATE_NAME(scmp); break;
+ case CPUINFO_FCT_EXPORT_STRING: info->export_string = CPU_EXPORT_STRING_NAME(scmp); 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, "INS 8050 SC/MP"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "National Semiconductor SC/MP"); 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;
+ }
+}
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+CPU_GET_INFO( ins8060 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 2; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "INS 8060 SC/MP II"); break;
+
+ default: CPU_GET_INFO_CALL(scmp); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(SCMP, scmp);
+DEFINE_LEGACY_CPU_DEVICE(INS8060, ins8060);
diff --git a/trunk/src/emu/cpu/scmp/scmp.h b/trunk/src/emu/cpu/scmp/scmp.h
new file mode 100644
index 00000000000..c0ff8a4c8ad
--- /dev/null
+++ b/trunk/src/emu/cpu/scmp/scmp.h
@@ -0,0 +1,42 @@
+#ifndef __SCMP_H__
+#define __SCMP_H__
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+enum
+{
+ SCMP_PC, SCMP_P1, SCMP_P2, SCMP_P3, SCMP_AC, SCMP_ER, SCMP_SR,
+ SCMP_GENPC = STATE_GENPC,
+ SCMP_GENSP = STATE_GENSP,
+ SCMP_GENPCBASE = STATE_GENPCBASE
+};
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+typedef struct _scmp_config scmp_config;
+struct _scmp_config
+{
+ devcb_write8 flag_out_func;
+ devcb_write_line sout_func;
+ devcb_read_line sin_func;
+ devcb_read_line sensea_func;
+ devcb_read_line senseb_func;
+ devcb_write_line halt_func;
+};
+#define SCMP_CONFIG(name) const scmp_config (name) =
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+DECLARE_LEGACY_CPU_DEVICE(SCMP, scmp);
+
+CPU_DISASSEMBLE( scmp );
+
+DECLARE_LEGACY_CPU_DEVICE(INS8060, ins8060);
+
+#endif
diff --git a/trunk/src/emu/cpu/scmp/scmpdasm.c b/trunk/src/emu/cpu/scmp/scmpdasm.c
new file mode 100644
index 00000000000..86c7901c4fd
--- /dev/null
+++ b/trunk/src/emu/cpu/scmp/scmpdasm.c
@@ -0,0 +1,153 @@
+/*****************************************************************************
+ *
+ * scmpdasm.c
+ *
+ * National Semiconductor SC/MP CPU Disassembly
+ *
+ * Initial version by Miodrag Milanovic
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+
+#define OP(A) oprom[(A) - PC]
+#define ARG(A) opram[(A) - PC]
+
+CPU_DISASSEMBLE( scmp )
+{
+ unsigned PC = pc;
+ UINT8 op = OP(pc++);
+ UINT8 ptr = op & 3;
+
+ if (BIT(op,7)) {
+ // two bytes instructions
+ char as[10];
+ char aspr[10];
+ UINT8 arg = ARG(pc); pc++;
+ if (arg==0x80) {
+ sprintf(as,"E");
+ } else {
+ if (arg & 0x80) {
+ sprintf(as,"-$%02x",0x100-arg);
+ } else {
+ sprintf(as,"+$%02x",arg);
+ }
+ }
+ sprintf(aspr,"%s(%d)",as,ptr);
+
+ switch (op)
+ {
+ // Memory Reference Instructions
+ case 0xc0 : sprintf (buffer,"ld %s",as); break;
+ case 0xc1 : case 0xc2 : case 0xc3 :
+ sprintf (buffer,"ld %s",aspr);break;
+ case 0xc5 : case 0xc6 : case 0xc7 :
+ sprintf (buffer,"ld @%s",aspr); break;
+ case 0xc8 : sprintf (buffer,"st %s",as); break;
+ case 0xc9 : case 0xca : case 0xcb :
+ sprintf (buffer,"st %s",aspr);break;
+ case 0xcd : case 0xce : case 0xcf :
+ sprintf (buffer,"st @%s",aspr); break;
+ case 0xd0 : sprintf (buffer,"and %s",as); break;
+ case 0xd1 : case 0xd2 : case 0xd3 :
+ sprintf (buffer,"and %s",aspr);break;
+ case 0xd5 : case 0xd6 : case 0xd7 :
+ sprintf (buffer,"and @%s",aspr); break;
+ case 0xd8 : sprintf (buffer,"or %s",as); break;
+ case 0xd9 : case 0xda : case 0xdb :
+ sprintf (buffer,"or %s",aspr);break;
+ case 0xdd : case 0xde : case 0xdf :
+ sprintf (buffer,"or @%s",aspr); break;
+ case 0xe0 : sprintf (buffer,"xor %s",as); break;
+ case 0xe1 : case 0xe2 : case 0xe3 :
+ sprintf (buffer,"xor %s",aspr);break;
+ case 0xe5 : case 0xe6 : case 0xe7 :
+ sprintf (buffer,"xor @%s",aspr); break;
+ case 0xe8 : sprintf (buffer,"dad %s",as); break;
+ case 0xe9 : case 0xea : case 0xeb :
+ sprintf (buffer,"dad %s",aspr);break;
+ case 0xed : case 0xee : case 0xef :
+ sprintf (buffer,"dad @%s",aspr); break;
+ case 0xf0 : sprintf (buffer,"add %s",as); break;
+ case 0xf1 : case 0xf2 : case 0xf3 :
+ sprintf (buffer,"add %s",aspr);break;
+ case 0xf5 : case 0xf6 : case 0xf7 :
+ sprintf (buffer,"add @%s",aspr); break;
+ case 0xf8 : sprintf (buffer,"cad %s",as); break;
+ case 0xf9 : case 0xfa : case 0xfb :
+ sprintf (buffer,"cad %s",aspr);break;
+ case 0xfd : case 0xfe : case 0xff :
+ sprintf (buffer,"cad @%s",aspr); break;
+ // Memory Increment/Decrement Instructions
+ case 0xa8 : case 0xa9 : case 0xaa : case 0xab :
+ sprintf (buffer,"ild %s",aspr); break;
+ case 0xb8 : case 0xb9 : case 0xba : case 0xbb :
+ sprintf (buffer,"dld %s",aspr); break;
+ // Immediate Instructions
+ case 0xc4 : sprintf (buffer,"ldi $%02x",arg); break;
+ case 0xd4 : sprintf (buffer,"ani $%02x",arg); break;
+ case 0xdc : sprintf (buffer,"ori $%02x",arg); break;
+ case 0xe4 : sprintf (buffer,"xri $%02x",arg); break;
+ case 0xec : sprintf (buffer,"dai $%02x",arg); break;
+ case 0xf4 : sprintf (buffer,"adi $%02x",arg); break;
+ case 0xfc : sprintf (buffer,"cai $%02x",arg); break;
+ // Transfer Instructions
+ case 0x90 : sprintf (buffer,"jmp %s",as);break;
+ case 0x91 : case 0x92 : case 0x93 :
+ sprintf (buffer,"jmp %s",aspr);break;
+ case 0x94 : sprintf (buffer,"jp %s",as); break;
+ case 0x95 : case 0x96 : case 0x97 :
+ sprintf (buffer,"jp %s",aspr); break;
+ case 0x98 : sprintf (buffer,"jz %s",as); break;
+ case 0x99 : case 0x9a : case 0x9b :
+ sprintf (buffer,"jz %s",aspr); break;
+ case 0x9c : sprintf (buffer,"jnz %s",as); break;
+ case 0x9d : case 0x9e : case 0x9f :
+ sprintf (buffer,"jnz %s",aspr); break;
+ // Double-Byte Miscellaneous Instructions
+ case 0x8f: sprintf (buffer,"dly $%02x",arg); break;
+ // Others are illegal
+ default : sprintf (buffer,"illegal"); pc--; break; // Illegal we consider without param
+ }
+ } else {
+ // one byte instructions
+ switch (op)
+ {
+ // Extension Register Instructions
+ case 0x40: sprintf (buffer,"lde"); break;
+ case 0x01: sprintf (buffer,"xae"); break;
+ case 0x50: sprintf (buffer,"ane"); break;
+ case 0x58: sprintf (buffer,"ore"); break;
+ case 0x60: sprintf (buffer,"xre"); break;
+ case 0x68: sprintf (buffer,"dae"); break;
+ case 0x70: sprintf (buffer,"ade"); break;
+ case 0x78: sprintf (buffer,"cae"); break;
+ // Pointer Register Move Instructions
+ case 0x30: case 0x31 :case 0x32: case 0x33:
+ sprintf (buffer,"xpal %d",ptr); break;
+ case 0x34: case 0x35 :case 0x36: case 0x37:
+ sprintf (buffer,"xpah %d",ptr); break;
+ case 0x3c: case 0x3d :case 0x3e: case 0x3f:
+ sprintf (buffer,"xppc %d",ptr); break;
+ // Shift, Rotate, Serial I/O Instructions
+ case 0x19: sprintf (buffer,"sio"); break;
+ case 0x1c: sprintf (buffer,"sr"); break;
+ case 0x1d: sprintf (buffer,"srl"); break;
+ case 0x1e: sprintf (buffer,"rr"); break;
+ case 0x1f: sprintf (buffer,"rrl"); break;
+ // Single Byte Miscellaneous Instructions
+ case 0x00: sprintf (buffer,"halt"); break;
+ case 0x02: sprintf (buffer,"ccl"); break;
+ case 0x03: sprintf (buffer,"scl"); break;
+ case 0x04: sprintf (buffer,"dint"); break;
+ case 0x05: sprintf (buffer,"ien"); break;
+ case 0x06: sprintf (buffer,"csa"); break;
+ case 0x07: sprintf (buffer,"cas"); break;
+ case 0x08: sprintf (buffer,"nop"); break;
+ // Others are illegal
+ default : sprintf (buffer,"illegal"); break;
+ }
+ }
+
+ return (pc - PC);
+}
diff --git a/trunk/src/emu/cpu/se3208/se3208.c b/trunk/src/emu/cpu/se3208/se3208.c
new file mode 100644
index 00000000000..6add121d646
--- /dev/null
+++ b/trunk/src/emu/cpu/se3208/se3208.c
@@ -0,0 +1,1941 @@
+#include "emu.h"
+#include "debugger.h"
+#include "se3208.h"
+
+/*
+ SE3208 CPU Emulator by ElSemi
+
+ For information about this CPU:
+ www.adc.co.kr
+
+*/
+
+typedef struct _se3208_state_t se3208_state_t;
+struct _se3208_state_t
+{
+ //GPR
+ UINT32 R[8];
+ //SPR
+ UINT32 PC;
+ UINT32 SR;
+ UINT32 SP;
+ UINT32 ER;
+ UINT32 PPC;
+
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ UINT8 IRQ;
+ UINT8 NMI;
+
+ int icount;
+};
+
+#define FLAG_C 0x0080
+#define FLAG_V 0x0010
+#define FLAG_S 0x0020
+#define FLAG_Z 0x0040
+
+#define FLAG_M 0x0200
+#define FLAG_E 0x0800
+#define FLAG_AUT 0x1000
+#define FLAG_ENI 0x2000
+#define FLAG_NMI 0x4000
+
+#define CLRFLAG(f) se3208_state->SR&=~(f);
+#define SETFLAG(f) se3208_state->SR|=(f);
+#define TESTFLAG(f) (se3208_state->SR&(f))
+
+#define EXTRACT(val,sbit,ebit) (((val)>>sbit)&((1<<((ebit-sbit)+1))-1))
+#define SEX8(val) ((val&0x80)?(val|0xFFFFFF00):(val&0xFF))
+#define SEX16(val) ((val&0x8000)?(val|0xFFFF0000):(val&0xFFFF))
+#define ZEX8(val) ((val)&0xFF)
+#define ZEX16(val) ((val)&0xFFFF)
+#define SEX(bits,val) ((val)&(1<<(bits-1))?((val)|(~((1<<bits)-1))):(val&((1<<bits)-1)))
+
+//Precompute the instruction decoding in a big table
+typedef void (*_OP)(se3208_state_t *se3208_state, UINT16 Opcode);
+#define INST(a) static void a(se3208_state_t *se3208_state, UINT16 Opcode)
+static _OP *OpTable=NULL;
+
+INLINE se3208_state_t *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == SE3208);
+ return (se3208_state_t *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+INLINE UINT32 read_dword_unaligned(address_space *space, UINT32 address)
+{
+ if (address & 3)
+ return space->read_byte(address) | space->read_byte(address+1)<<8 | space->read_byte(address+2)<<16 | space->read_byte(address+3)<<24;
+ else
+ return space->read_dword(address);
+}
+
+INLINE UINT16 read_word_unaligned(address_space *space, UINT32 address)
+{
+ if (address & 1)
+ return space->read_byte(address) | space->read_byte(address+1)<<8;
+ else
+ return space->read_word(address);
+}
+
+INLINE void write_dword_unaligned(address_space *space, UINT32 address, UINT32 data)
+{
+ if (address & 3)
+ {
+ space->write_byte(address, data & 0xff);
+ space->write_byte(address+1, (data>>8)&0xff);
+ space->write_byte(address+2, (data>>16)&0xff);
+ space->write_byte(address+3, (data>>24)&0xff);
+ }
+ else
+ {
+ space->write_dword(address, data);
+ }
+}
+
+INLINE void write_word_unaligned(address_space *space, UINT32 address, UINT16 data)
+{
+ if (address & 1)
+ {
+ space->write_byte(address, data & 0xff);
+ space->write_byte(address+1, (data>>8)&0xff);
+ }
+ else
+ {
+ space->write_word(address, data);
+ }
+}
+
+
+INLINE UINT8 SE3208_Read8(se3208_state_t *se3208_state, UINT32 addr)
+{
+ return se3208_state->program->read_byte(addr);
+}
+
+INLINE UINT16 SE3208_Read16(se3208_state_t *se3208_state, UINT32 addr)
+{
+ return read_word_unaligned(se3208_state->program,addr);
+}
+
+INLINE UINT32 SE3208_Read32(se3208_state_t *se3208_state, UINT32 addr)
+{
+ return read_dword_unaligned(se3208_state->program,addr);
+}
+
+INLINE void SE3208_Write8(se3208_state_t *se3208_state, UINT32 addr,UINT8 val)
+{
+ se3208_state->program->write_byte(addr,val);
+}
+
+INLINE void SE3208_Write16(se3208_state_t *se3208_state, UINT32 addr,UINT16 val)
+{
+ write_word_unaligned(se3208_state->program,addr,val);
+}
+
+INLINE void SE3208_Write32(se3208_state_t *se3208_state, UINT32 addr,UINT32 val)
+{
+ write_dword_unaligned(se3208_state->program,addr,val);
+}
+
+
+
+INLINE UINT32 AddWithFlags(se3208_state_t *se3208_state, UINT32 a,UINT32 b)
+{
+ UINT32 r=a+b;
+ CLRFLAG(FLAG_Z|FLAG_C|FLAG_V|FLAG_S);
+ if(!r)
+ SETFLAG(FLAG_Z);
+ if(r&0x80000000)
+ SETFLAG(FLAG_S);
+ if(((((a&b)|(~r&(a|b)))>>31))&1)
+ SETFLAG(FLAG_C);
+ if(((((a^r)&(b^r))>>31))&1)
+ SETFLAG(FLAG_V);
+ return r;
+}
+
+INLINE UINT32 SubWithFlags(se3208_state_t *se3208_state, UINT32 a,UINT32 b) //a-b
+{
+ UINT32 r=a-b;
+ CLRFLAG(FLAG_Z|FLAG_C|FLAG_V|FLAG_S);
+ if(!r)
+ SETFLAG(FLAG_Z);
+ if(r&0x80000000)
+ SETFLAG(FLAG_S);
+ if((((b&r)|(~a&(b|r)))>>31)&1)
+ SETFLAG(FLAG_C);
+ if((((b^a)&(r^a))>>31)&1)
+ SETFLAG(FLAG_V);
+ return r;
+}
+
+INLINE UINT32 AdcWithFlags(se3208_state_t *se3208_state,UINT32 a,UINT32 b)
+{
+ UINT32 C=(se3208_state->SR&FLAG_C)?1:0;
+ UINT32 r=a+b+C;
+ CLRFLAG(FLAG_Z|FLAG_C|FLAG_V|FLAG_S);
+ if(!r)
+ SETFLAG(FLAG_Z);
+ if(r&0x80000000)
+ SETFLAG(FLAG_S);
+ if(((((a&b)|(~r&(a|b)))>>31))&1)
+ SETFLAG(FLAG_C);
+ if(((((a^r)&(b^r))>>31))&1)
+ SETFLAG(FLAG_V);
+ return r;
+
+}
+
+INLINE UINT32 SbcWithFlags(se3208_state_t *se3208_state,UINT32 a,UINT32 b)
+{
+ UINT32 C=(se3208_state->SR&FLAG_C)?1:0;
+ UINT32 r=a-b-C;
+ CLRFLAG(FLAG_Z|FLAG_C|FLAG_V|FLAG_S);
+ if(!r)
+ SETFLAG(FLAG_Z);
+ if(r&0x80000000)
+ SETFLAG(FLAG_S);
+ if((((b&r)|(~a&(b|r)))>>31)&1)
+ SETFLAG(FLAG_C);
+ if((((b^a)&(r^a))>>31)&1)
+ SETFLAG(FLAG_V);
+ return r;
+}
+
+INLINE UINT32 MulWithFlags(se3208_state_t *se3208_state,UINT32 a,UINT32 b)
+{
+ INT64 r=(INT64) a*(INT64) b;
+ CLRFLAG(FLAG_V);
+ if(r>>32)
+ SETFLAG(FLAG_V);
+ return (UINT32) (r&0xffffffff);
+}
+
+INLINE UINT32 NegWithFlags(se3208_state_t *se3208_state,UINT32 a)
+{
+ return SubWithFlags(se3208_state,0,a);
+}
+
+INLINE UINT32 AsrWithFlags(se3208_state_t *se3208_state,UINT32 Val, UINT8 By)
+{
+ signed int v=(signed int) Val;
+ v>>=By;
+ CLRFLAG(FLAG_Z|FLAG_C|FLAG_V|FLAG_S);
+ if(!v)
+ SETFLAG(FLAG_Z);
+ if(v&0x80000000)
+ SETFLAG(FLAG_S);
+ if(Val&(1<<(By-1)))
+ SETFLAG(FLAG_C);
+ return (UINT32) v;
+}
+
+INLINE UINT32 LsrWithFlags(se3208_state_t *se3208_state,UINT32 Val, UINT8 By)
+{
+ UINT32 v=Val;
+ v>>=By;
+ CLRFLAG(FLAG_Z|FLAG_C|FLAG_V|FLAG_S);
+ if(!v)
+ SETFLAG(FLAG_Z);
+ if(v&0x80000000)
+ SETFLAG(FLAG_S);
+ if(Val&(1<<(By-1)))
+ SETFLAG(FLAG_C);
+ return v;
+}
+
+INLINE UINT32 AslWithFlags(se3208_state_t *se3208_state,UINT32 Val, UINT8 By)
+{
+ UINT32 v=Val;
+ v<<=By;
+ CLRFLAG(FLAG_Z|FLAG_C|FLAG_V|FLAG_S);
+ if(!v)
+ SETFLAG(FLAG_Z);
+ if(v&0x80000000)
+ SETFLAG(FLAG_S);
+ if(Val&(1<<(32-By)))
+ SETFLAG(FLAG_C);
+ return v;
+}
+
+
+INST(INVALIDOP)
+{
+ //assert(false);
+}
+
+INST(LDB)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,4);
+ UINT32 Index=EXTRACT(Opcode,5,7);
+ UINT32 SrcDst=EXTRACT(Opcode,8,10);
+ UINT32 Val;
+
+ if(Index)
+ Index=se3208_state->R[Index];
+ else
+ Index=0;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf);
+
+ Val=SE3208_Read8(se3208_state, Index+Offset);
+ se3208_state->R[SrcDst]=SEX8(Val);
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(STB)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,4);
+ UINT32 Index=EXTRACT(Opcode,5,7);
+ UINT32 SrcDst=EXTRACT(Opcode,8,10);
+
+ if(Index)
+ Index=se3208_state->R[Index];
+ else
+ Index=0;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf);
+
+ SE3208_Write8(se3208_state, Index+Offset,ZEX8(se3208_state->R[SrcDst]));
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(LDS)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,4);
+ UINT32 Index=EXTRACT(Opcode,5,7);
+ UINT32 SrcDst=EXTRACT(Opcode,8,10);
+ UINT32 Val;
+
+ Offset<<=1;
+
+ if(Index)
+ Index=se3208_state->R[Index];
+ else
+ Index=0;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf);
+
+ Val=SE3208_Read16(se3208_state, Index+Offset);
+ se3208_state->R[SrcDst]=SEX16(Val);
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(STS)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,4);
+ UINT32 Index=EXTRACT(Opcode,5,7);
+ UINT32 SrcDst=EXTRACT(Opcode,8,10);
+
+ Offset<<=1;
+
+ if(Index)
+ Index=se3208_state->R[Index];
+ else
+ Index=0;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf);
+
+ SE3208_Write16(se3208_state, Index+Offset,ZEX16(se3208_state->R[SrcDst]));
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(LD)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,4);
+ UINT32 Index=EXTRACT(Opcode,5,7);
+ UINT32 SrcDst=EXTRACT(Opcode,8,10);
+
+ Offset<<=2;
+
+ if(Index)
+ Index=se3208_state->R[Index];
+ else
+ Index=0;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf);
+
+ se3208_state->R[SrcDst]=SE3208_Read32(se3208_state, Index+Offset);
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(ST)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,4);
+ UINT32 Index=EXTRACT(Opcode,5,7);
+ UINT32 SrcDst=EXTRACT(Opcode,8,10);
+
+ Offset<<=2;
+
+ if(Index)
+ Index=se3208_state->R[Index];
+ else
+ Index=0;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf);
+
+ SE3208_Write32(se3208_state, Index+Offset,se3208_state->R[SrcDst]);
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(LDBU)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,4);
+ UINT32 Index=EXTRACT(Opcode,5,7);
+ UINT32 SrcDst=EXTRACT(Opcode,8,10);
+ UINT32 Val;
+
+ if(Index)
+ Index=se3208_state->R[Index];
+ else
+ Index=0;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf);
+
+ Val=SE3208_Read8(se3208_state, Index+Offset);
+ se3208_state->R[SrcDst]=ZEX8(Val);
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(LDSU)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,4);
+ UINT32 Index=EXTRACT(Opcode,5,7);
+ UINT32 SrcDst=EXTRACT(Opcode,8,10);
+ UINT32 Val;
+
+ Offset<<=1;
+
+ if(Index)
+ Index=se3208_state->R[Index];
+ else
+ Index=0;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf);
+
+ Val=SE3208_Read16(se3208_state, Index+Offset);
+ se3208_state->R[SrcDst]=ZEX16(Val);
+
+ CLRFLAG(FLAG_E);
+}
+
+
+INST(LERI)
+{
+ UINT32 Imm=EXTRACT(Opcode,0,13);
+ if(TESTFLAG(FLAG_E))
+ se3208_state->ER=(EXTRACT(se3208_state->ER,0,17)<<14)|Imm;
+ else
+ se3208_state->ER=SEX(14,Imm);
+
+
+ SETFLAG(FLAG_E);
+}
+
+INST(LDSP)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+ UINT32 Index=se3208_state->SP;
+ UINT32 SrcDst=EXTRACT(Opcode,8,10);
+
+ Offset<<=2;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf);
+
+ se3208_state->R[SrcDst]=SE3208_Read32(se3208_state, Index+Offset);
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(STSP)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+ UINT32 Index=se3208_state->SP;
+ UINT32 SrcDst=EXTRACT(Opcode,8,10);
+
+ Offset<<=2;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf);
+
+ SE3208_Write32(se3208_state, Index+Offset,se3208_state->R[SrcDst]);
+
+ CLRFLAG(FLAG_E);
+}
+
+static void PushVal(se3208_state_t *se3208_state, UINT32 Val)
+{
+ se3208_state->SP-=4;
+ SE3208_Write32(se3208_state, se3208_state->SP,Val);
+}
+
+static UINT32 PopVal(se3208_state_t *se3208_state)
+{
+ UINT32 Val=SE3208_Read32(se3208_state, se3208_state->SP);
+ se3208_state->SP+=4;
+ return Val;
+}
+
+INST(PUSH)
+{
+ UINT32 Set=EXTRACT(Opcode,0,10);
+ if(Set&(1<<10))
+ PushVal(se3208_state,se3208_state->PC);
+ if(Set&(1<<9))
+ PushVal(se3208_state,se3208_state->SR);
+ if(Set&(1<<8))
+ PushVal(se3208_state,se3208_state->ER);
+ if(Set&(1<<7))
+ PushVal(se3208_state,se3208_state->R[7]);
+ if(Set&(1<<6))
+ PushVal(se3208_state,se3208_state->R[6]);
+ if(Set&(1<<5))
+ PushVal(se3208_state,se3208_state->R[5]);
+ if(Set&(1<<4))
+ PushVal(se3208_state,se3208_state->R[4]);
+ if(Set&(1<<3))
+ PushVal(se3208_state,se3208_state->R[3]);
+ if(Set&(1<<2))
+ PushVal(se3208_state,se3208_state->R[2]);
+ if(Set&(1<<1))
+ PushVal(se3208_state,se3208_state->R[1]);
+ if(Set&(1<<0))
+ PushVal(se3208_state,se3208_state->R[0]);
+}
+
+INST(POP)
+{
+ UINT32 Set=EXTRACT(Opcode,0,10);
+ if(Set&(1<<0))
+ se3208_state->R[0]=PopVal(se3208_state);
+ if(Set&(1<<1))
+ se3208_state->R[1]=PopVal(se3208_state);
+ if(Set&(1<<2))
+ se3208_state->R[2]=PopVal(se3208_state);
+ if(Set&(1<<3))
+ se3208_state->R[3]=PopVal(se3208_state);
+ if(Set&(1<<4))
+ se3208_state->R[4]=PopVal(se3208_state);
+ if(Set&(1<<5))
+ se3208_state->R[5]=PopVal(se3208_state);
+ if(Set&(1<<6))
+ se3208_state->R[6]=PopVal(se3208_state);
+ if(Set&(1<<7))
+ se3208_state->R[7]=PopVal(se3208_state);
+ if(Set&(1<<8))
+ se3208_state->ER=PopVal(se3208_state);
+ if(Set&(1<<9))
+ se3208_state->SR=PopVal(se3208_state);
+ if(Set&(1<<10))
+ {
+ se3208_state->PC=PopVal(se3208_state)-2; //PC automatically incresases by 2
+ }
+}
+
+INST(LEATOSP)
+{
+ UINT32 Offset=EXTRACT(Opcode,9,12);
+ UINT32 Index=EXTRACT(Opcode,3,5);
+
+ if(Index)
+ Index=se3208_state->R[Index];
+ else
+ Index=0;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf);
+ else
+ Offset=SEX(4,Offset);
+
+ se3208_state->SP=Index+Offset;
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(LEAFROMSP)
+{
+ UINT32 Offset=EXTRACT(Opcode,9,12);
+ UINT32 Index=EXTRACT(Opcode,3,5);
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf);
+ else
+ Offset=SEX(4,Offset);
+
+ se3208_state->R[Index]=se3208_state->SP+Offset;
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(LEASPTOSP)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+
+ Offset<<=2;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,23)<<8)|(Offset&0xff);
+ else
+ Offset=SEX(10,Offset);
+
+ se3208_state->SP=se3208_state->SP+Offset;
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(MOV)
+{
+ UINT32 Src=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,9,11);
+
+ se3208_state->R[Dst]=se3208_state->R[Src];
+}
+
+INST(LDI)
+{
+ UINT32 Dst=EXTRACT(Opcode,8,10);
+ UINT32 Imm=EXTRACT(Opcode,0,7);
+
+ if(TESTFLAG(FLAG_E))
+ Imm=(EXTRACT(se3208_state->ER,0,27)<<4)|(Imm&0xf);
+ else
+ Imm=SEX8(Imm);
+
+ se3208_state->R[Dst]=Imm;
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(LDBSP)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,3);
+ UINT32 Index=se3208_state->SP;
+ UINT32 SrcDst=EXTRACT(Opcode,4,6);
+ UINT32 Val;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf);
+
+ Val=SE3208_Read8(se3208_state, Index+Offset);
+ se3208_state->R[SrcDst]=SEX8(Val);
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(STBSP)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,3);
+ UINT32 Index=se3208_state->SP;
+ UINT32 SrcDst=EXTRACT(Opcode,4,6);
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf);
+
+ SE3208_Write8(se3208_state, Index+Offset,ZEX8(se3208_state->R[SrcDst]));
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(LDSSP)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,3);
+ UINT32 Index=se3208_state->SP;
+ UINT32 SrcDst=EXTRACT(Opcode,4,6);
+ UINT32 Val;
+
+ Offset<<=1;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf);
+
+ Val=SE3208_Read16(se3208_state, Index+Offset);
+ se3208_state->R[SrcDst]=SEX16(Val);
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(STSSP)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,3);
+ UINT32 Index=se3208_state->SP;
+ UINT32 SrcDst=EXTRACT(Opcode,4,6);
+
+ Offset<<=1;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf);
+
+ SE3208_Write16(se3208_state, Index+Offset,ZEX16(se3208_state->R[SrcDst]));
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(LDBUSP)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,3);
+ UINT32 Index=se3208_state->SP;
+ UINT32 SrcDst=EXTRACT(Opcode,4,6);
+ UINT32 Val;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf);
+
+ Val=SE3208_Read8(se3208_state, Index+Offset);
+ se3208_state->R[SrcDst]=ZEX8(Val);
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(LDSUSP)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,3);
+ UINT32 Index=se3208_state->SP;
+ UINT32 SrcDst=EXTRACT(Opcode,4,6);
+ UINT32 Val;
+
+ Offset<<=1;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf);
+
+ Val=SE3208_Read16(se3208_state, Index+Offset);
+ se3208_state->R[SrcDst]=ZEX16(Val);
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(ADDI)
+{
+ UINT32 Imm=EXTRACT(Opcode,9,12);
+ UINT32 Src=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+
+ if(TESTFLAG(FLAG_E))
+ Imm=(EXTRACT(se3208_state->ER,0,27)<<4)|(Imm&0xf);
+ else
+ Imm=SEX(4,Imm);
+
+ se3208_state->R[Dst]=AddWithFlags(se3208_state,se3208_state->R[Src],Imm);
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(SUBI)
+{
+ UINT32 Imm=EXTRACT(Opcode,9,12);
+ UINT32 Src=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+
+ if(TESTFLAG(FLAG_E))
+ Imm=(EXTRACT(se3208_state->ER,0,27)<<4)|(Imm&0xf);
+ else
+ Imm=SEX(4,Imm);
+
+ se3208_state->R[Dst]=SubWithFlags(se3208_state,se3208_state->R[Src],Imm);
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(ADCI)
+{
+ UINT32 Imm=EXTRACT(Opcode,9,12);
+ UINT32 Src=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+
+ if(TESTFLAG(FLAG_E))
+ Imm=(EXTRACT(se3208_state->ER,0,27)<<4)|(Imm&0xf);
+ else
+ Imm=SEX(4,Imm);
+
+ se3208_state->R[Dst]=AdcWithFlags(se3208_state,se3208_state->R[Src],Imm);
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(SBCI)
+{
+ UINT32 Imm=EXTRACT(Opcode,9,12);
+ UINT32 Src=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+
+ if(TESTFLAG(FLAG_E))
+ Imm=(EXTRACT(se3208_state->ER,0,27)<<4)|(Imm&0xf);
+ else
+ Imm=SEX(4,Imm);
+
+ se3208_state->R[Dst]=SbcWithFlags(se3208_state,se3208_state->R[Src],Imm);
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(ANDI)
+{
+ UINT32 Imm=EXTRACT(Opcode,9,12);
+ UINT32 Src=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+
+ if(TESTFLAG(FLAG_E))
+ Imm=(EXTRACT(se3208_state->ER,0,27)<<4)|(Imm&0xf);
+ else
+ Imm=SEX(4,Imm);
+
+ se3208_state->R[Dst]=se3208_state->R[Src]&Imm;
+
+ CLRFLAG(FLAG_S|FLAG_Z|FLAG_E);
+ if(!se3208_state->R[Dst])
+ SETFLAG(FLAG_Z);
+ if(se3208_state->R[Dst]&0x80000000)
+ SETFLAG(FLAG_S);
+}
+
+INST(ORI)
+{
+ UINT32 Imm=EXTRACT(Opcode,9,12);
+ UINT32 Src=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+
+ if(TESTFLAG(FLAG_E))
+ Imm=(EXTRACT(se3208_state->ER,0,27)<<4)|(Imm&0xf);
+ else
+ Imm=SEX(4,Imm);
+
+ se3208_state->R[Dst]=se3208_state->R[Src]|Imm;
+
+ CLRFLAG(FLAG_S|FLAG_Z|FLAG_E);
+ if(!se3208_state->R[Dst])
+ SETFLAG(FLAG_Z);
+ if(se3208_state->R[Dst]&0x80000000)
+ SETFLAG(FLAG_S);
+}
+
+INST(XORI)
+{
+ UINT32 Imm=EXTRACT(Opcode,9,12);
+ UINT32 Src=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+
+ if(TESTFLAG(FLAG_E))
+ Imm=(EXTRACT(se3208_state->ER,0,27)<<4)|(Imm&0xf);
+ else
+ Imm=SEX(4,Imm);
+
+ se3208_state->R[Dst]=se3208_state->R[Src]^Imm;
+
+ CLRFLAG(FLAG_S|FLAG_Z|FLAG_E);
+ if(!se3208_state->R[Dst])
+ SETFLAG(FLAG_Z);
+ if(se3208_state->R[Dst]&0x80000000)
+ SETFLAG(FLAG_S);
+}
+
+INST(CMPI)
+{
+ UINT32 Imm=EXTRACT(Opcode,9,12);
+ UINT32 Src=EXTRACT(Opcode,3,5);
+
+ if(TESTFLAG(FLAG_E))
+ Imm=(EXTRACT(se3208_state->ER,0,27)<<4)|(Imm&0xf);
+ else
+ Imm=SEX(4,Imm);
+
+ SubWithFlags(se3208_state,se3208_state->R[Src],Imm);
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(TSTI)
+{
+ UINT32 Imm=EXTRACT(Opcode,9,12);
+ UINT32 Src=EXTRACT(Opcode,3,5);
+ UINT32 Dst;
+
+ if(TESTFLAG(FLAG_E))
+ Imm=(EXTRACT(se3208_state->ER,0,27)<<4)|(Imm&0xf);
+ else
+ Imm=SEX(4,Imm);
+
+ Dst=se3208_state->R[Src]&Imm;
+
+ CLRFLAG(FLAG_S|FLAG_Z|FLAG_E);
+ if(!Dst)
+ SETFLAG(FLAG_Z);
+ if(Dst&0x80000000)
+ SETFLAG(FLAG_S);
+}
+
+INST(ADD)
+{
+ UINT32 Src2=EXTRACT(Opcode,9,11);
+ UINT32 Src1=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+
+ se3208_state->R[Dst]=AddWithFlags(se3208_state,se3208_state->R[Src1],se3208_state->R[Src2]);
+}
+
+INST(SUB)
+{
+ UINT32 Src2=EXTRACT(Opcode,9,11);
+ UINT32 Src1=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+
+ se3208_state->R[Dst]=SubWithFlags(se3208_state,se3208_state->R[Src1],se3208_state->R[Src2]);
+}
+
+INST(ADC)
+{
+ UINT32 Src2=EXTRACT(Opcode,9,11);
+ UINT32 Src1=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+
+ se3208_state->R[Dst]=AdcWithFlags(se3208_state,se3208_state->R[Src1],se3208_state->R[Src2]);
+}
+
+INST(SBC)
+{
+ UINT32 Src2=EXTRACT(Opcode,9,11);
+ UINT32 Src1=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+
+ se3208_state->R[Dst]=SbcWithFlags(se3208_state,se3208_state->R[Src1],se3208_state->R[Src2]);
+}
+
+INST(AND)
+{
+ UINT32 Src2=EXTRACT(Opcode,9,11);
+ UINT32 Src1=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+
+ se3208_state->R[Dst]=se3208_state->R[Src1]&se3208_state->R[Src2];
+
+ CLRFLAG(FLAG_S|FLAG_Z);
+ if(!se3208_state->R[Dst])
+ SETFLAG(FLAG_Z);
+ if(se3208_state->R[Dst]&0x80000000)
+ SETFLAG(FLAG_S);
+}
+
+INST(OR)
+{
+ UINT32 Src2=EXTRACT(Opcode,9,11);
+ UINT32 Src1=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+
+ se3208_state->R[Dst]=se3208_state->R[Src1]|se3208_state->R[Src2];
+
+ CLRFLAG(FLAG_S|FLAG_Z);
+ if(!se3208_state->R[Dst])
+ SETFLAG(FLAG_Z);
+ if(se3208_state->R[Dst]&0x80000000)
+ SETFLAG(FLAG_S);
+
+}
+
+INST(XOR)
+{
+ UINT32 Src2=EXTRACT(Opcode,9,11);
+ UINT32 Src1=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+
+ se3208_state->R[Dst]=se3208_state->R[Src1]^se3208_state->R[Src2];
+
+ CLRFLAG(FLAG_S|FLAG_Z);
+ if(!se3208_state->R[Dst])
+ SETFLAG(FLAG_Z);
+ if(se3208_state->R[Dst]&0x80000000)
+ SETFLAG(FLAG_S);
+
+}
+
+INST(CMP)
+{
+ UINT32 Src2=EXTRACT(Opcode,9,11);
+ UINT32 Src1=EXTRACT(Opcode,3,5);
+
+ SubWithFlags(se3208_state,se3208_state->R[Src1],se3208_state->R[Src2]);
+}
+
+INST(TST)
+{
+ UINT32 Src2=EXTRACT(Opcode,9,11);
+ UINT32 Src1=EXTRACT(Opcode,3,5);
+ UINT32 Dst;
+
+ Dst=se3208_state->R[Src1]&se3208_state->R[Src2];
+
+ CLRFLAG(FLAG_S|FLAG_Z);
+ if(!Dst)
+ SETFLAG(FLAG_Z);
+ if(Dst&0x80000000)
+ SETFLAG(FLAG_S);
+}
+
+INST(MULS)
+{
+ UINT32 Src2=EXTRACT(Opcode,6,8);
+ UINT32 Src1=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+
+ se3208_state->R[Dst]=MulWithFlags(se3208_state,se3208_state->R[Src1],se3208_state->R[Src2]);
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(NEG)
+{
+ UINT32 Dst=EXTRACT(Opcode,9,11);
+ UINT32 Src=EXTRACT(Opcode,3,5);
+
+ se3208_state->R[Dst]=NegWithFlags(se3208_state,se3208_state->R[Src]);
+}
+
+INST(CALL)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset;
+ else
+ Offset=SEX(8,Offset);
+ Offset<<=1;
+ PushVal(se3208_state,se3208_state->PC+2);
+ se3208_state->PC=se3208_state->PC+Offset;
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(JV)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset;
+ else
+ Offset=SEX(8,Offset);
+ Offset<<=1;
+
+ if(TESTFLAG(FLAG_V))
+ {
+ se3208_state->PC=se3208_state->PC+Offset;
+ }
+
+ CLRFLAG(FLAG_E);
+
+}
+
+INST(JNV)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset;
+ else
+ Offset=SEX(8,Offset);
+ Offset<<=1;
+
+ if(!TESTFLAG(FLAG_V))
+ {
+ se3208_state->PC=se3208_state->PC+Offset;
+ }
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(JC)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset;
+ else
+ Offset=SEX(8,Offset);
+ Offset<<=1;
+
+ if(TESTFLAG(FLAG_C))
+ {
+ se3208_state->PC=se3208_state->PC+Offset;
+ }
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(JNC)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset;
+ else
+ Offset=SEX(8,Offset);
+ Offset<<=1;
+
+ if(!TESTFLAG(FLAG_C))
+ {
+ se3208_state->PC=se3208_state->PC+Offset;
+ }
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(JP)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset;
+ else
+ Offset=SEX(8,Offset);
+ Offset<<=1;
+
+ if(!TESTFLAG(FLAG_S))
+ {
+ se3208_state->PC=se3208_state->PC+Offset;
+ }
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(JM)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset;
+ else
+ Offset=SEX(8,Offset);
+ Offset<<=1;
+
+ if(TESTFLAG(FLAG_S))
+ {
+ se3208_state->PC=se3208_state->PC+Offset;
+ }
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(JNZ)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset;
+ else
+ Offset=SEX(8,Offset);
+ Offset<<=1;
+
+ if(!TESTFLAG(FLAG_Z))
+ {
+ se3208_state->PC=se3208_state->PC+Offset;
+ }
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(JZ)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset;
+ else
+ Offset=SEX(8,Offset);
+ Offset<<=1;
+
+ if(TESTFLAG(FLAG_Z))
+ {
+ se3208_state->PC=se3208_state->PC+Offset;
+ }
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(JGE)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+ UINT32 S=TESTFLAG(FLAG_S)?1:0;
+ UINT32 V=TESTFLAG(FLAG_V)?1:0;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset;
+ else
+ Offset=SEX(8,Offset);
+ Offset<<=1;
+
+ if(!(S^V))
+ {
+ se3208_state->PC=se3208_state->PC+Offset;
+ }
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(JLE)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+ UINT32 S=TESTFLAG(FLAG_S)?1:0;
+ UINT32 V=TESTFLAG(FLAG_V)?1:0;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset;
+ else
+ Offset=SEX(8,Offset);
+ Offset<<=1;
+
+ if(TESTFLAG(FLAG_Z) || (S^V))
+ {
+ se3208_state->PC=se3208_state->PC+Offset;
+ }
+ CLRFLAG(FLAG_E);
+}
+
+INST(JHI)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset;
+ else
+ Offset=SEX(8,Offset);
+ Offset<<=1;
+
+ if(!(TESTFLAG(FLAG_Z) || TESTFLAG(FLAG_C)))
+ {
+ se3208_state->PC=se3208_state->PC+Offset;
+ }
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(JLS)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset;
+ else
+ Offset=SEX(8,Offset);
+ Offset<<=1;
+
+ if(TESTFLAG(FLAG_Z) || TESTFLAG(FLAG_C))
+ {
+ se3208_state->PC=se3208_state->PC+Offset;
+ }
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(JGT)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+ UINT32 S=TESTFLAG(FLAG_S)?1:0;
+ UINT32 V=TESTFLAG(FLAG_V)?1:0;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset;
+ else
+ Offset=SEX(8,Offset);
+ Offset<<=1;
+
+ if(!(TESTFLAG(FLAG_Z) || (S^V)))
+ {
+ se3208_state->PC=se3208_state->PC+Offset;
+ }
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(JLT)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+ UINT32 S=TESTFLAG(FLAG_S)?1:0;
+ UINT32 V=TESTFLAG(FLAG_V)?1:0;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset;
+ else
+ Offset=SEX(8,Offset);
+ Offset<<=1;
+
+ if(S^V)
+ {
+ se3208_state->PC=se3208_state->PC+Offset;
+ }
+
+ CLRFLAG(FLAG_E);
+}
+
+
+
+INST(JMP)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset;
+ else
+ Offset=SEX(8,Offset);
+
+ Offset<<=1;
+
+ se3208_state->PC=se3208_state->PC+Offset;
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(JR)
+{
+ UINT32 Src=EXTRACT(Opcode,0,3);
+
+ se3208_state->PC=se3208_state->R[Src]-2;
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(CALLR)
+{
+ UINT32 Src=EXTRACT(Opcode,0,3);
+ PushVal(se3208_state,se3208_state->PC+2);
+ se3208_state->PC=se3208_state->R[Src]-2;
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(ASR)
+{
+ UINT32 CS=Opcode&(1<<10);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+ UINT32 Imm=EXTRACT(Opcode,5,9);
+ UINT32 Cnt=EXTRACT(Opcode,5,7);
+
+ if(CS)
+ se3208_state->R[Dst]=AsrWithFlags(se3208_state,se3208_state->R[Dst],se3208_state->R[Cnt]&0x1f);
+ else
+ se3208_state->R[Dst]=AsrWithFlags(se3208_state,se3208_state->R[Dst],Imm&0x1f);
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(LSR)
+{
+ UINT32 CS=Opcode&(1<<10);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+ UINT32 Imm=EXTRACT(Opcode,5,9);
+ UINT32 Cnt=EXTRACT(Opcode,5,7);
+
+ if(CS)
+ se3208_state->R[Dst]=LsrWithFlags(se3208_state,se3208_state->R[Dst],se3208_state->R[Cnt]&0x1f);
+ else
+ se3208_state->R[Dst]=LsrWithFlags(se3208_state,se3208_state->R[Dst],Imm&0x1f);
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(ASL)
+{
+ UINT32 CS=Opcode&(1<<10);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+ UINT32 Imm=EXTRACT(Opcode,5,9);
+ UINT32 Cnt=EXTRACT(Opcode,5,7);
+
+ if(CS)
+ se3208_state->R[Dst]=AslWithFlags(se3208_state,se3208_state->R[Dst],se3208_state->R[Cnt]&0x1f);
+ else
+ se3208_state->R[Dst]=AslWithFlags(se3208_state,se3208_state->R[Dst],Imm&0x1f);
+
+ CLRFLAG(FLAG_E);
+}
+
+INST(EXTB)
+{
+ UINT32 Dst=EXTRACT(Opcode,0,3);
+ UINT32 Val=se3208_state->R[Dst];
+
+ se3208_state->R[Dst]=SEX8(Val);
+
+ CLRFLAG(FLAG_S|FLAG_Z|FLAG_E);
+ if(!se3208_state->R[Dst])
+ SETFLAG(FLAG_Z);
+ if(se3208_state->R[Dst]&0x80000000)
+ SETFLAG(FLAG_S);
+
+}
+
+INST(EXTS)
+{
+ UINT32 Dst=EXTRACT(Opcode,0,3);
+ UINT32 Val=se3208_state->R[Dst];
+
+ se3208_state->R[Dst]=SEX16(Val);
+
+ CLRFLAG(FLAG_S|FLAG_Z|FLAG_E);
+ if(!se3208_state->R[Dst])
+ SETFLAG(FLAG_Z);
+ if(se3208_state->R[Dst]&0x80000000)
+ SETFLAG(FLAG_S);
+}
+
+INST(SET)
+{
+ UINT32 Imm=EXTRACT(Opcode,0,3);
+
+ se3208_state->SR|=(1<<Imm);
+}
+
+INST(CLR)
+{
+ UINT32 Imm=EXTRACT(Opcode,0,3);
+
+ se3208_state->SR&=~(1<<Imm);
+}
+
+INST(SWI)
+{
+ UINT32 Imm=EXTRACT(Opcode,0,3);
+
+ if(!TESTFLAG(FLAG_ENI))
+ return;
+ PushVal(se3208_state,se3208_state->PC);
+ PushVal(se3208_state,se3208_state->SR);
+
+ CLRFLAG(FLAG_ENI|FLAG_E|FLAG_M);
+
+ se3208_state->PC=SE3208_Read32(se3208_state, 4*Imm+0x40)-2;
+}
+
+INST(HALT)
+{
+// UINT32 Imm=EXTRACT(Opcode,0,3);
+
+// DEBUGMESSAGE("HALT\t0x%x",Imm);
+}
+
+INST(MVTC)
+{
+// UINT32 Imm=EXTRACT(Opcode,0,3);
+
+// DEBUGMESSAGE("MVTC\t%%R0,%%CR%d",Imm);
+}
+
+INST(MVFC)
+{
+// UINT32 Imm=EXTRACT(Opcode,0,3);
+
+// DEBUGMESSAGE("MVFC\t%%CR0%d,%%R0",Imm);
+}
+
+
+static _OP DecodeOp(UINT16 Opcode)
+{
+ switch(EXTRACT(Opcode,14,15))
+ {
+ case 0x0:
+ {
+ UINT8 Op=EXTRACT(Opcode,11,13);
+ switch(Op)
+ {
+ case 0x0:
+ return LDB;
+ case 0x1:
+ return LDS;
+ case 0x2:
+ return LD;
+ case 0x3:
+ return LDBU;
+ case 0x4:
+ return STB;
+ case 0x5:
+ return STS;
+ case 0x6:
+ return ST;
+ case 0x7:
+ return LDSU;
+ }
+ }
+ break;
+ case 0x1:
+ return LERI;
+ case 0x2:
+ {
+ switch(EXTRACT(Opcode,11,13))
+ {
+ case 0:
+ return LDSP;
+ case 1:
+ return STSP;
+ case 2:
+ return PUSH;
+ case 3:
+ return POP;
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8: //arith
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ switch(EXTRACT(Opcode,6,8))
+ {
+ case 0:
+ return ADDI;
+ case 1:
+ return ADCI;
+ case 2:
+ return SUBI;
+ case 3:
+ return SBCI;
+ case 4:
+ return ANDI;
+ case 5:
+ return ORI;
+ case 6:
+ return XORI;
+ case 7:
+ switch(EXTRACT(Opcode,0,2))
+ {
+ case 0:
+ return CMPI;
+ case 1:
+ return TSTI;
+ case 2:
+ return LEATOSP;
+ case 3:
+ return LEAFROMSP;
+ }
+ break;
+ }
+ break;
+ }
+ }
+ break;
+ case 3:
+ switch(EXTRACT(Opcode,12,13))
+ {
+ case 0:
+ switch(EXTRACT(Opcode,6,8))
+ {
+ case 0:
+ return ADD;
+ case 1:
+ return ADC;
+ case 2:
+ return SUB;
+ case 3:
+ return SBC;
+ case 4:
+ return AND;
+ case 5:
+ return OR;
+ case 6:
+ return XOR;
+ case 7:
+ switch(EXTRACT(Opcode,0,2))
+ {
+ case 0:
+ return CMP;
+ case 1:
+ return TST;
+ case 2:
+ return MOV;
+ case 3:
+ return NEG;
+ }
+ break;
+ }
+ break;
+ case 1: //Jumps
+ switch(EXTRACT(Opcode,8,11))
+ {
+ case 0x0:
+ return JNV;
+ case 0x1:
+ return JV;
+ case 0x2:
+ return JP;
+ case 0x3:
+ return JM;
+ case 0x4:
+ return JNZ;
+ case 0x5:
+ return JZ;
+ case 0x6:
+ return JNC;
+ case 0x7:
+ return JC;
+ case 0x8:
+ return JGT;
+ case 0x9:
+ return JLT;
+ case 0xa:
+ return JGE;
+ case 0xb:
+ return JLE;
+ case 0xc:
+ return JHI;
+ case 0xd:
+ return JLS;
+ case 0xe:
+ return JMP;
+ case 0xf:
+ return CALL;
+ }
+ break;
+ case 2:
+ if(Opcode&(1<<11))
+ return LDI;
+ else //SP Ops
+ {
+ if(Opcode&(1<<10))
+ {
+ switch(EXTRACT(Opcode,7,9))
+ {
+ case 0:
+ return LDBSP;
+ case 1:
+ return LDSSP;
+ case 3:
+ return LDBUSP;
+ case 4:
+ return STBSP;
+ case 5:
+ return STSSP;
+ case 7:
+ return LDSUSP;
+ }
+ }
+ else
+ {
+ if(Opcode&(1<<9))
+ {
+ return LEASPTOSP;
+ }
+ else
+ {
+ if(Opcode&(1<<8))
+ {
+
+ }
+ else
+ {
+ switch(EXTRACT(Opcode,4,7))
+ {
+ case 0:
+ return EXTB;
+ case 1:
+ return EXTS;
+ case 8:
+ return JR;
+ case 9:
+ return CALLR;
+ case 10:
+ return SET;
+ case 11:
+ return CLR;
+ case 12:
+ return SWI;
+ case 13:
+ return HALT;
+ }
+ }
+ }
+ }
+ }
+ break;
+ case 3:
+ switch(EXTRACT(Opcode,9,11))
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ switch(EXTRACT(Opcode,3,4))
+ {
+ case 0:
+ return ASR;
+ case 1:
+ return LSR;
+ case 2:
+ return ASL;
+ //case 3:
+ // return LSL;
+ }
+ break;
+ case 4:
+ return MULS;
+ case 6:
+ if(Opcode&(1<<3))
+ return MVFC;
+ else
+ return MVTC;
+ break;
+ }
+ break;
+ }
+ break;
+
+ }
+ return INVALIDOP;
+}
+
+
+static void BuildTable(void)
+{
+ int i;
+ if(!OpTable)
+ OpTable=global_alloc_array(_OP, 0x10000);
+ for(i=0;i<0x10000;++i)
+ OpTable[i]=DecodeOp(i);
+}
+
+static CPU_RESET( se3208 )
+{
+ se3208_state_t *se3208_state = get_safe_token(device);
+
+ device_irq_callback save_irqcallback = se3208_state->irq_callback;
+ memset(se3208_state,0,sizeof(se3208_state_t));
+ se3208_state->irq_callback = save_irqcallback;
+ se3208_state->device = device;
+ se3208_state->program = device->space(AS_PROGRAM);
+ se3208_state->direct = &se3208_state->program->direct();
+ se3208_state->PC=SE3208_Read32(se3208_state, 0);
+ se3208_state->SR=0;
+ se3208_state->IRQ=CLEAR_LINE;
+ se3208_state->NMI=CLEAR_LINE;
+}
+
+static void SE3208_NMI(se3208_state_t *se3208_state)
+{
+ PushVal(se3208_state,se3208_state->PC);
+ PushVal(se3208_state,se3208_state->SR);
+
+ CLRFLAG(FLAG_NMI|FLAG_ENI|FLAG_E|FLAG_M);
+
+ se3208_state->PC=SE3208_Read32(se3208_state, 4);
+}
+
+static void SE3208_Interrupt(se3208_state_t *se3208_state)
+{
+ if(!TESTFLAG(FLAG_ENI))
+ return;
+
+ PushVal(se3208_state,se3208_state->PC);
+ PushVal(se3208_state,se3208_state->SR);
+
+ CLRFLAG(FLAG_ENI|FLAG_E|FLAG_M);
+
+
+ if(!(TESTFLAG(FLAG_AUT)))
+ se3208_state->PC=SE3208_Read32(se3208_state, 8);
+ else
+ se3208_state->PC=SE3208_Read32(se3208_state, 4*se3208_state->irq_callback(se3208_state->device, 0));
+}
+
+
+static CPU_EXECUTE( se3208 )
+{
+ se3208_state_t *se3208_state = get_safe_token(device);
+
+ do
+ {
+ UINT16 Opcode=se3208_state->direct->read_decrypted_word(se3208_state->PC, WORD_XOR_LE(0));
+
+ debugger_instruction_hook(device, se3208_state->PC);
+
+ OpTable[Opcode](se3208_state, Opcode);
+ se3208_state->PPC=se3208_state->PC;
+ se3208_state->PC+=2;
+ //Check interrupts
+ if(se3208_state->NMI==ASSERT_LINE)
+ {
+ SE3208_NMI(se3208_state);
+ se3208_state->NMI=CLEAR_LINE;
+ }
+ else if(se3208_state->IRQ==ASSERT_LINE && TESTFLAG(FLAG_ENI))
+ {
+ SE3208_Interrupt(se3208_state);
+ }
+ --(se3208_state->icount);
+ } while(se3208_state->icount>0);
+}
+
+static CPU_INIT( se3208 )
+{
+ se3208_state_t *se3208_state = get_safe_token(device);
+
+ BuildTable();
+
+ se3208_state->irq_callback = irqcallback;
+ se3208_state->device = device;
+ se3208_state->program = device->space(AS_PROGRAM);
+ se3208_state->direct = &se3208_state->program->direct();
+}
+
+static CPU_EXIT( se3208 )
+{
+ if(OpTable) {
+ global_free(OpTable);
+ OpTable = NULL;
+ }
+}
+
+
+static void set_irq_line(se3208_state_t *se3208_state, int line,int state)
+{
+ if(line==INPUT_LINE_NMI) //NMI
+ se3208_state->NMI=state;
+ else
+ se3208_state->IRQ=state;
+}
+
+
+static CPU_SET_INFO( se3208 )
+{
+ se3208_state_t *se3208_state = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + SE3208_INT: set_irq_line(se3208_state, 0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line(se3208_state, INPUT_LINE_NMI, info->i); break;
+
+ case CPUINFO_INT_REGISTER + SE3208_PC:
+ case CPUINFO_INT_PC: se3208_state->PC = info->i; break;
+ case CPUINFO_INT_REGISTER + SE3208_SP:
+ case CPUINFO_INT_SP: se3208_state->SP = info->i; break;
+ case CPUINFO_INT_REGISTER + SE3208_ER: se3208_state->ER = info->i; break;
+ case CPUINFO_INT_REGISTER + SE3208_SR: se3208_state->SR = info->i; break;
+ case CPUINFO_INT_REGISTER + SE3208_R0: se3208_state->R[ 0] = info->i; break;
+ case CPUINFO_INT_REGISTER + SE3208_R1: se3208_state->R[ 1] = info->i; break;
+ case CPUINFO_INT_REGISTER + SE3208_R2: se3208_state->R[ 2] = info->i; break;
+ case CPUINFO_INT_REGISTER + SE3208_R3: se3208_state->R[ 3] = info->i; break;
+ case CPUINFO_INT_REGISTER + SE3208_R4: se3208_state->R[ 4] = info->i; break;
+ case CPUINFO_INT_REGISTER + SE3208_R5: se3208_state->R[ 5] = info->i; break;
+ case CPUINFO_INT_REGISTER + SE3208_R6: se3208_state->R[ 6] = info->i; break;
+ case CPUINFO_INT_REGISTER + SE3208_R7: se3208_state->R[ 7] = info->i; break;
+ }
+}
+
+
+CPU_GET_INFO( se3208 )
+{
+ se3208_state_t *se3208_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(se3208_state_t); 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 = 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 = 1; 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 + SE3208_INT: info->i = se3208_state->IRQ; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = se3208_state->NMI; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = se3208_state->PPC; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + SE3208_PC: info->i = se3208_state->PC; break;
+ case CPUINFO_INT_REGISTER + SE3208_SP:
+ case CPUINFO_INT_SP: info->i = se3208_state->SP; break;
+ case CPUINFO_INT_REGISTER + SE3208_SR: info->i = se3208_state->SR; break;
+ case CPUINFO_INT_REGISTER + SE3208_ER: info->i = se3208_state->ER; break;
+ case CPUINFO_INT_REGISTER + SE3208_R0: info->i = se3208_state->R[ 0]; break;
+ case CPUINFO_INT_REGISTER + SE3208_R1: info->i = se3208_state->R[ 1]; break;
+ case CPUINFO_INT_REGISTER + SE3208_R2: info->i = se3208_state->R[ 2]; break;
+ case CPUINFO_INT_REGISTER + SE3208_R3: info->i = se3208_state->R[ 3]; break;
+ case CPUINFO_INT_REGISTER + SE3208_R4: info->i = se3208_state->R[ 4]; break;
+ case CPUINFO_INT_REGISTER + SE3208_R5: info->i = se3208_state->R[ 5]; break;
+ case CPUINFO_INT_REGISTER + SE3208_R6: info->i = se3208_state->R[ 6]; break;
+ case CPUINFO_INT_REGISTER + SE3208_R7: info->i = se3208_state->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(se3208); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(se3208); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(se3208); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(se3208); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(se3208);break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(se3208); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &se3208_state->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "SE3208"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Advanced Digital Chips Inc."); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.00"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Miguel Angel Horna, all rights reserved."); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c %c%c%c%c%c",
+ se3208_state->SR&FLAG_C?'C':'.',
+ se3208_state->SR&FLAG_V?'V':'.',
+ se3208_state->SR&FLAG_S?'S':'.',
+ se3208_state->SR&FLAG_Z?'Z':'.',
+
+ se3208_state->SR&FLAG_M?'M':'.',
+ se3208_state->SR&FLAG_E?'E':'.',
+ se3208_state->SR&FLAG_AUT?'A':'.',
+ se3208_state->SR&FLAG_ENI?'I':'.',
+ se3208_state->SR&FLAG_NMI?'N':'.'
+
+ );
+
+ break;
+
+ case CPUINFO_STR_REGISTER + SE3208_PC: sprintf(info->s, "PC :%08X", se3208_state->PC); break;
+ case CPUINFO_STR_REGISTER + SE3208_SR: sprintf(info->s, "SR :%08X", se3208_state->SR); break;
+ case CPUINFO_STR_REGISTER + SE3208_ER: sprintf(info->s, "ER :%08X", se3208_state->ER); break;
+ case CPUINFO_STR_REGISTER + SE3208_SP: sprintf(info->s, "SP :%08X", se3208_state->SP); break;
+ case CPUINFO_STR_REGISTER + SE3208_R0: sprintf(info->s, "R0 :%08X", se3208_state->R[ 0]); break;
+ case CPUINFO_STR_REGISTER + SE3208_R1: sprintf(info->s, "R1 :%08X", se3208_state->R[ 1]); break;
+ case CPUINFO_STR_REGISTER + SE3208_R2: sprintf(info->s, "R2 :%08X", se3208_state->R[ 2]); break;
+ case CPUINFO_STR_REGISTER + SE3208_R3: sprintf(info->s, "R3 :%08X", se3208_state->R[ 3]); break;
+ case CPUINFO_STR_REGISTER + SE3208_R4: sprintf(info->s, "R4 :%08X", se3208_state->R[ 4]); break;
+ case CPUINFO_STR_REGISTER + SE3208_R5: sprintf(info->s, "R5 :%08X", se3208_state->R[ 5]); break;
+ case CPUINFO_STR_REGISTER + SE3208_R6: sprintf(info->s, "R6 :%08X", se3208_state->R[ 6]); break;
+ case CPUINFO_STR_REGISTER + SE3208_R7: sprintf(info->s, "R7 :%08X", se3208_state->R[ 7]); break;
+ case CPUINFO_STR_REGISTER + SE3208_PPC: sprintf(info->s, "PPC :%08X", se3208_state->PPC); break;
+ }
+}
+
+
+DEFINE_LEGACY_CPU_DEVICE(SE3208, se3208);
diff --git a/trunk/src/emu/cpu/se3208/se3208.h b/trunk/src/emu/cpu/se3208/se3208.h
new file mode 100644
index 00000000000..272fb7beddd
--- /dev/null
+++ b/trunk/src/emu/cpu/se3208/se3208.h
@@ -0,0 +1,12 @@
+
+enum
+{
+ SE3208_PC=1, SE3208_SR, SE3208_ER, SE3208_SP,SE3208_PPC,
+ SE3208_R0, SE3208_R1, SE3208_R2, SE3208_R3, SE3208_R4, SE3208_R5, SE3208_R6, SE3208_R7
+};
+
+#define SE3208_INT 0
+
+DECLARE_LEGACY_CPU_DEVICE(SE3208, se3208);
+
+CPU_DISASSEMBLE( se3208 );
diff --git a/trunk/src/emu/cpu/se3208/se3208dis.c b/trunk/src/emu/cpu/se3208/se3208dis.c
new file mode 100644
index 00000000000..a348d2b070e
--- /dev/null
+++ b/trunk/src/emu/cpu/se3208/se3208dis.c
@@ -0,0 +1,1413 @@
+#include "emu.h"
+#include "debugger.h"
+#include "se3208.h"
+
+
+static struct _DisSE3208
+{
+ UINT32 PC;
+ UINT32 SR;
+ UINT32 ER;
+} Context;
+
+#define FLAG_E 0x0800
+
+#define CLRFLAG(f) Context.SR&=~(f);
+#define SETFLAG(f) Context.SR|=(f);
+#define TESTFLAG(f) (Context.SR&(f))
+
+#define EXTRACT(val,sbit,ebit) (((val)>>sbit)&((1<<((ebit-sbit)+1))-1))
+#define SEX8(val) ((val&0x80)?(val|0xFFFFFF00):(val&0xFF))
+#define SEX16(val) ((val&0x8000)?(val|0xFFFF0000):(val&0xFFFF))
+#define ZEX8(val) ((val)&0xFF)
+#define ZEX16(val) ((val)&0xFFFF)
+#define SEX(bits,val) ((val)&(1<<(bits-1))?((val)|(~((1<<bits)-1))):(val&((1<<bits)-1)))
+
+typedef UINT32 (*_OP)(UINT16 Opcode,char *dst);
+#define INST(a) static UINT32 a(UINT16 Opcode,char *dst)
+
+
+INST(INVALIDOP)
+{
+ sprintf(dst,"INVALID");
+ return 0;
+}
+
+INST(LDB)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,4);
+ UINT32 Index=EXTRACT(Opcode,5,7);
+ UINT32 SrcDst=EXTRACT(Opcode,8,10);
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(Context.ER,0,27)<<4)|(Offset&0xf);
+
+ if(Index)
+ sprintf(dst,"LDB (%%R%d,0x%x),%%R%d",Index,Offset,SrcDst);
+ else
+ sprintf(dst,"LDB (0x%x),%%R%d",Index+Offset,SrcDst);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(STB)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,4);
+ UINT32 Index=EXTRACT(Opcode,5,7);
+ UINT32 SrcDst=EXTRACT(Opcode,8,10);
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(Context.ER,0,27)<<4)|(Offset&0xf);
+
+ if(Index)
+ sprintf(dst,"STB %%R%d,(%%R%d,0x%x)",SrcDst,Index,Offset);
+ else
+ sprintf(dst,"STB %%R%d,(0x%x)",SrcDst,Index+Offset);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(LDS)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,4);
+ UINT32 Index=EXTRACT(Opcode,5,7);
+ UINT32 SrcDst=EXTRACT(Opcode,8,10);
+
+ Offset<<=1;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(Context.ER,0,27)<<4)|(Offset&0xf);
+
+ if(Index)
+ sprintf(dst,"LDS (%%R%d,0x%x),%%R%d",Index,Offset,SrcDst);
+ else
+ sprintf(dst,"LDS (0x%x),%%R%d",Index+Offset,SrcDst);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(STS)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,4);
+ UINT32 Index=EXTRACT(Opcode,5,7);
+ UINT32 SrcDst=EXTRACT(Opcode,8,10);
+
+ Offset<<=1;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(Context.ER,0,27)<<4)|(Offset&0xf);
+
+ if(Index)
+ sprintf(dst,"STS %%R%d,(%%R%d,0x%x)",SrcDst,Index,Offset);
+ else
+ sprintf(dst,"STS %%R%d,(0x%x)",SrcDst,Index+Offset);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(LD)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,4);
+ UINT32 Index=EXTRACT(Opcode,5,7);
+ UINT32 SrcDst=EXTRACT(Opcode,8,10);
+
+ Offset<<=2;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(Context.ER,0,27)<<4)|(Offset&0xf);
+
+ if(Index)
+ sprintf(dst,"LD (%%R%d,0x%x),%%R%d",Index,Offset,SrcDst);
+ else
+ sprintf(dst,"LD (0x%x),%%R%d",Index+Offset,SrcDst);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(ST)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,4);
+ UINT32 Index=EXTRACT(Opcode,5,7);
+ UINT32 SrcDst=EXTRACT(Opcode,8,10);
+
+ Offset<<=2;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(Context.ER,0,27)<<4)|(Offset&0xf);
+
+ if(Index)
+ sprintf(dst,"ST %%R%d,(%%R%d,0x%x)",SrcDst,Index,Offset);
+ else
+ sprintf(dst,"ST %%R%d,(0x%x)",SrcDst,Index+Offset);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(LDBU)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,4);
+ UINT32 Index=EXTRACT(Opcode,5,7);
+ UINT32 SrcDst=EXTRACT(Opcode,8,10);
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(Context.ER,0,27)<<4)|(Offset&0xf);
+
+ if(Index)
+ sprintf(dst,"LDBU (%%R%d,0x%x),%%R%d",Index,Offset,SrcDst);
+ else
+ sprintf(dst,"LDBU (0x%x),%%R%d",Index+Offset,SrcDst);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(LDSU)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,4);
+ UINT32 Index=EXTRACT(Opcode,5,7);
+ UINT32 SrcDst=EXTRACT(Opcode,8,10);
+
+ Offset<<=1;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(Context.ER,0,27)<<4)|(Offset&0xf);
+
+ if(Index)
+ sprintf(dst,"LDSU (%%R%d,0x%x),%%R%d",Index,Offset,SrcDst);
+ else
+ sprintf(dst,"LDSU (0x%x),%%R%d",Index+Offset,SrcDst);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+
+INST(LERI)
+{
+ UINT32 Imm=EXTRACT(Opcode,0,13);
+
+ if(TESTFLAG(FLAG_E))
+ Context.ER=(EXTRACT(Context.ER,0,17)<<14)|Imm;
+ else
+ Context.ER=SEX(14,Imm);
+
+ //sprintf(dst,"LERI 0x%x\t\tER=%08X",Imm,Context.ER);
+ sprintf(dst,"LERI 0x%x",Imm/*,Context.ER*/);
+
+ SETFLAG(FLAG_E);
+ return 0;
+}
+
+INST(LDSP)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+ UINT32 SrcDst=EXTRACT(Opcode,8,10);
+
+ Offset<<=2;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(Context.ER,0,27)<<4)|(Offset&0xf);
+
+ sprintf(dst,"LD (%%SP,0x%x),%%R%d",Offset,SrcDst);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(STSP)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+ UINT32 SrcDst=EXTRACT(Opcode,8,10);
+
+ Offset<<=2;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(Context.ER,0,27)<<4)|(Offset&0xf);
+
+ sprintf(dst,"ST %%R%d,(%%SP,0x%x)",SrcDst,Offset);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(PUSH)
+{
+ UINT32 Set=EXTRACT(Opcode,0,10);
+ char str[1024];
+ strcpy(str,"PUSH ");
+ if(Set&(1<<10))
+ strcat(str,"%PC-");
+ if(Set&(1<<9))
+ strcat(str,"%SR-");
+ if(Set&(1<<8))
+ strcat(str,"%ER-");
+ if(Set&(1<<7))
+ strcat(str,"%R7-");
+ if(Set&(1<<6))
+ strcat(str,"%R6-");
+ if(Set&(1<<5))
+ strcat(str,"%R5-");
+ if(Set&(1<<4))
+ strcat(str,"%R4-");
+ if(Set&(1<<3))
+ strcat(str,"%R3-");
+ if(Set&(1<<2))
+ strcat(str,"%R2-");
+ if(Set&(1<<1))
+ strcat(str,"%R1-");
+ if(Set&(1<<0))
+ strcat(str,"%R0-");
+ str[strlen(str)-1]=0;
+ strcpy(dst,str);
+ return 0;
+}
+
+INST(POP)
+{
+ UINT32 Set=EXTRACT(Opcode,0,10);
+ char str[1024];
+ int Ret=0;
+ strcpy(str,"POP ");
+ if(Set&(1<<0))
+ strcat(str,"%R0-");
+ if(Set&(1<<1))
+ strcat(str,"%R1-");
+ if(Set&(1<<2))
+ strcat(str,"%R2-");
+ if(Set&(1<<3))
+ strcat(str,"%R3-");
+ if(Set&(1<<4))
+ strcat(str,"%R4-");
+ if(Set&(1<<5))
+ strcat(str,"%R5-");
+ if(Set&(1<<6))
+ strcat(str,"%R6-");
+ if(Set&(1<<7))
+ strcat(str,"%R7-");
+ if(Set&(1<<8))
+ strcat(str,"%ER-");
+ if(Set&(1<<9))
+ strcat(str,"%SR-");
+ if(Set&(1<<10))
+ {
+ strcat(str,"%PC-");
+ CLRFLAG(FLAG_E); //Clear the flag, this is a ret so disassemble will start a new E block
+ Ret=1;
+ }
+ str[strlen(str)-1]=0;
+ if(Ret)
+ strcat(str,"\n");
+ strcpy(dst,str);
+ return Ret ? DASMFLAG_STEP_OUT : 0;
+}
+
+INST(LEATOSP)
+{
+ UINT32 Offset=EXTRACT(Opcode,9,12);
+ UINT32 Index=EXTRACT(Opcode,3,5);
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(Context.ER,0,27)<<4)|(Offset&0xf);
+ else
+ Offset=SEX(4,Offset);
+
+ if(Index)
+ sprintf(dst,"LEA (%%R%d,0x%x),%%SP",Index,Offset);
+ else
+ sprintf(dst,"LEA (0x%x),%%SP",Index+Offset);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(LEAFROMSP)
+{
+ UINT32 Offset=EXTRACT(Opcode,9,12);
+ UINT32 Index=EXTRACT(Opcode,3,5);
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(Context.ER,0,27)<<4)|(Offset&0xf);
+ else
+ Offset=SEX(4,Offset);
+
+ sprintf(dst,"LEA (%%SP,0x%x),%%R%d",Offset,Index);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(LEASPTOSP)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+
+ Offset<<=2;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(Context.ER,0,23)<<8)|(Offset&0xff);
+ else
+ Offset=SEX(10,Offset);
+
+
+ sprintf(dst,"LEA (%%SP,0x%x),%%SP",Offset);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(MOV)
+{
+ UINT32 Src=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,9,11);
+
+ if(Src==0 && Dst==0)
+ sprintf(dst,"NOP");
+ else
+ sprintf(dst,"MOV %%SR%d,%%DR%d",Src,Dst);
+ return 0;
+}
+
+INST(LDI)
+{
+ UINT32 Dst=EXTRACT(Opcode,8,10);
+ UINT32 Imm=EXTRACT(Opcode,0,7);
+
+ if(TESTFLAG(FLAG_E))
+ Imm=(EXTRACT(Context.ER,0,27)<<4)|(Imm&0xf);
+ else
+ Imm=SEX8(Imm);
+
+ sprintf(dst,"LDI 0x%x,%%R%d",Imm,Dst);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(LDBSP)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,3);
+ UINT32 SrcDst=EXTRACT(Opcode,4,6);
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(Context.ER,0,27)<<4)|(Offset&0xf);
+
+ sprintf(dst,"LDB (%%SP,0x%x),%%R%d",Offset,SrcDst);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(STBSP)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,3);
+ UINT32 SrcDst=EXTRACT(Opcode,4,6);
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(Context.ER,0,27)<<4)|(Offset&0xf);
+
+ sprintf(dst,"STB %%R%d,(%%SP,0x%x)",SrcDst,Offset);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(LDSSP)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,3);
+ UINT32 SrcDst=EXTRACT(Opcode,4,6);
+
+ Offset<<=1;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(Context.ER,0,27)<<4)|(Offset&0xf);
+
+ sprintf(dst,"LDS (%%SP,0x%x),%%R%d",Offset,SrcDst);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(STSSP)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,3);
+ UINT32 SrcDst=EXTRACT(Opcode,4,6);
+
+ Offset<<=1;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(Context.ER,0,27)<<4)|(Offset&0xf);
+
+ sprintf(dst,"STS %%R%d,(%%SP,0x%x)",SrcDst,Offset);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(LDBUSP)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,3);
+ UINT32 SrcDst=EXTRACT(Opcode,4,6);
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(Context.ER,0,27)<<4)|(Offset&0xf);
+
+ sprintf(dst,"LDBU (%%SP,0x%x),%%R%d",Offset,SrcDst);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(LDSUSP)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,3);
+ UINT32 SrcDst=EXTRACT(Opcode,4,6);
+
+ Offset<<=1;
+
+ if(TESTFLAG(FLAG_E))
+ Offset=(EXTRACT(Context.ER,0,27)<<4)|(Offset&0xf);
+
+ sprintf(dst,"LDSU (%%SP,0x%x),%%R%d",Offset,SrcDst);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(ADDI)
+{
+ UINT32 Imm=EXTRACT(Opcode,9,12);
+ UINT32 Src=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+ UINT32 Imm2=Imm;
+
+ if(TESTFLAG(FLAG_E))
+ Imm2=(EXTRACT(Context.ER,0,27)<<4)|(Imm2&0xf);
+ else
+ Imm2=SEX(4,Imm2);
+
+ sprintf(dst,"ADD %%SR%d,0x%x,%%DR%d",Src,Imm2,Dst/*,Imm2*/);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(SUBI)
+{
+ UINT32 Imm=EXTRACT(Opcode,9,12);
+ UINT32 Src=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+ UINT32 Imm2=Imm;
+
+ if(TESTFLAG(FLAG_E))
+ Imm2=(EXTRACT(Context.ER,0,27)<<4)|(Imm2&0xf);
+ else
+ Imm2=SEX(4,Imm2);
+
+ sprintf(dst,"SUB %%SR%d,0x%x,%%DR%d",Src,Imm2,Dst/*,Imm2*/);
+
+ CLRFLAG(FLAG_E);
+
+ return 0;
+}
+
+INST(ADCI)
+{
+ UINT32 Imm=EXTRACT(Opcode,9,12);
+ UINT32 Src=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+ UINT32 Imm2=Imm;
+
+ if(TESTFLAG(FLAG_E))
+ Imm2=(EXTRACT(Context.ER,0,27)<<4)|(Imm2&0xf);
+ else
+ Imm2=SEX(4,Imm2);
+
+ sprintf(dst,"ADC %%SR%d,0x%x,%%DR%d",Src,Imm2,Dst/*,Imm2*/);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(SBCI)
+{
+ UINT32 Imm=EXTRACT(Opcode,9,12);
+ UINT32 Src=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+ UINT32 Imm2=Imm;
+
+ if(TESTFLAG(FLAG_E))
+ Imm2=(EXTRACT(Context.ER,0,27)<<4)|(Imm2&0xf);
+ else
+ Imm2=SEX(4,Imm2);
+
+ sprintf(dst,"SBC %%SR%d,0x%x,%%DR%d",Src,Imm2,Dst/*,Imm2*/);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(ANDI)
+{
+ UINT32 Imm=EXTRACT(Opcode,9,12);
+ UINT32 Src=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+ UINT32 Imm2=Imm;
+
+ if(TESTFLAG(FLAG_E))
+ Imm2=(EXTRACT(Context.ER,0,27)<<4)|(Imm2&0xf);
+ else
+ Imm2=SEX(4,Imm2);
+
+ sprintf(dst,"AND %%SR%d,0x%x,%%DR%d",Src,Imm2,Dst/*,Imm2*/);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(ORI)
+{
+ UINT32 Imm=EXTRACT(Opcode,9,12);
+ UINT32 Src=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+ UINT32 Imm2=Imm;
+
+ if(TESTFLAG(FLAG_E))
+ Imm2=(EXTRACT(Context.ER,0,27)<<4)|(Imm2&0xf);
+ else
+ Imm2=SEX(4,Imm2);
+
+ sprintf(dst,"OR %%SR%d,0x%x,%%DR%d",Src,Imm2,Dst/*,Imm2*/);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(XORI)
+{
+ UINT32 Imm=EXTRACT(Opcode,9,12);
+ UINT32 Src=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+ UINT32 Imm2=Imm;
+
+ if(TESTFLAG(FLAG_E))
+ Imm2=(EXTRACT(Context.ER,0,27)<<4)|(Imm2&0xf);
+ else
+ Imm2=SEX(4,Imm2);
+
+ sprintf(dst,"XOR %%SR%d,0x%x,%%DR%d",Src,Imm2,Dst/*,Imm2*/);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(CMPI)
+{
+ UINT32 Imm=EXTRACT(Opcode,9,12);
+ UINT32 Src=EXTRACT(Opcode,3,5);
+ UINT32 Imm2=Imm;
+
+ if(TESTFLAG(FLAG_E))
+ Imm2=(EXTRACT(Context.ER,0,27)<<4)|(Imm2&0xf);
+ else
+ Imm2=SEX(4,Imm2);
+
+ sprintf(dst,"CMP %%SR%d,0x%x",Src,Imm2/*,Imm2*/);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(TSTI)
+{
+ UINT32 Imm=EXTRACT(Opcode,9,12);
+ UINT32 Src=EXTRACT(Opcode,3,5);
+ UINT32 Imm2=Imm;
+
+ if(TESTFLAG(FLAG_E))
+ Imm2=(EXTRACT(Context.ER,0,27)<<4)|(Imm2&0xf);
+ else
+ Imm2=SEX(4,Imm2);
+
+ sprintf(dst,"TST %%SR%d,0x%x",Src,Imm2/*,Imm2*/);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(ADD)
+{
+ UINT32 Src2=EXTRACT(Opcode,9,11);
+ UINT32 Src1=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+
+ sprintf(dst,"ADD %%SR%d,%%SR%d,%%DR%d",Src1,Src2,Dst);
+ return 0;
+}
+
+INST(SUB)
+{
+ UINT32 Src2=EXTRACT(Opcode,9,11);
+ UINT32 Src1=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+
+ sprintf(dst,"SUB %%SR%d,%%SR%d,%%DR%d",Src1,Src2,Dst);
+ return 0;
+}
+
+INST(ADC)
+{
+ UINT32 Src2=EXTRACT(Opcode,9,11);
+ UINT32 Src1=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+
+ sprintf(dst,"ADC %%SR%d,%%SR%d,%%DR%d",Src1,Src2,Dst);
+ return 0;
+}
+
+INST(SBC)
+{
+ UINT32 Src2=EXTRACT(Opcode,9,11);
+ UINT32 Src1=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+
+ sprintf(dst,"SBC %%SR%d,%%SR%d,%%DR%d",Src1,Src2,Dst);
+ return 0;
+}
+
+INST(AND)
+{
+ UINT32 Src2=EXTRACT(Opcode,9,11);
+ UINT32 Src1=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+
+ sprintf(dst,"AND %%SR%d,%%SR%d,%%DR%d",Src1,Src2,Dst);
+ return 0;
+}
+
+INST(OR)
+{
+ UINT32 Src2=EXTRACT(Opcode,9,11);
+ UINT32 Src1=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+
+ sprintf(dst,"OR %%SR%d,%%SR%d,%%DR%d",Src1,Src2,Dst);
+ return 0;
+}
+
+INST(XOR)
+{
+ UINT32 Src2=EXTRACT(Opcode,9,11);
+ UINT32 Src1=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+
+ sprintf(dst,"XOR %%SR%d,%%SR%d,%%DR%d",Src1,Src2,Dst);
+ return 0;
+}
+
+INST(CMP)
+{
+ UINT32 Src2=EXTRACT(Opcode,9,11);
+ UINT32 Src1=EXTRACT(Opcode,3,5);
+
+ sprintf(dst,"CMP %%SR%d,%%SR%d",Src1,Src2);
+ return 0;
+}
+
+INST(TST)
+{
+ UINT32 Src2=EXTRACT(Opcode,9,11);
+ UINT32 Src1=EXTRACT(Opcode,3,5);
+
+ sprintf(dst,"TST %%SR%d,%%SR%d",Src1,Src2);
+ return 0;
+}
+
+INST(MULS)
+{
+ UINT32 Src2=EXTRACT(Opcode,6,8);
+ UINT32 Src1=EXTRACT(Opcode,3,5);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+
+ sprintf(dst,"MUL %%SR%d,%%SR%d,%%DR%d",Src1,Src2,Dst);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(NEG)
+{
+ UINT32 Dst=EXTRACT(Opcode,9,11);
+ UINT32 Src=EXTRACT(Opcode,3,5);
+
+ sprintf(dst,"NEG %%SR%d,%%DR%d",Src,Dst);
+ return 0;
+}
+
+INST(CALL)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+ UINT32 Offset2;
+
+ if(TESTFLAG(FLAG_E))
+ Offset2=(EXTRACT(Context.ER,0,22)<<8)|Offset;
+ else
+ Offset2=SEX(8,Offset);
+ Offset2<<=1;
+ sprintf(dst,"CALL 0x%x",Context.PC+2+Offset2);
+
+ CLRFLAG(FLAG_E);
+ return DASMFLAG_STEP_OVER;
+}
+
+INST(JV)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+ UINT32 Offset2;
+
+ if(TESTFLAG(FLAG_E))
+ Offset2=(EXTRACT(Context.ER,0,22)<<8)|Offset;
+ else
+ Offset2=SEX(8,Offset);
+ Offset2<<=1;
+ sprintf(dst,"JV 0x%x",Context.PC+2+Offset2);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(JNV)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+ UINT32 Offset2;
+
+ if(TESTFLAG(FLAG_E))
+ Offset2=(EXTRACT(Context.ER,0,22)<<8)|Offset;
+ else
+ Offset2=SEX(8,Offset);
+ Offset2<<=1;
+ sprintf(dst,"JNV 0x%x",Context.PC+2+Offset2);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(JC)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+ UINT32 Offset2;
+
+ if(TESTFLAG(FLAG_E))
+ Offset2=(EXTRACT(Context.ER,0,22)<<8)|Offset;
+ else
+ Offset2=SEX(8,Offset);
+ Offset2<<=1;
+ sprintf(dst,"JC 0x%x",Context.PC+2+Offset2);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(JNC)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+ UINT32 Offset2;
+
+ if(TESTFLAG(FLAG_E))
+ Offset2=(EXTRACT(Context.ER,0,22)<<8)|Offset;
+ else
+ Offset2=SEX(8,Offset);
+ Offset2<<=1;
+ sprintf(dst,"JNC 0x%x",Context.PC+2+Offset2);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(JP)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+ UINT32 Offset2;
+
+ if(TESTFLAG(FLAG_E))
+ Offset2=(EXTRACT(Context.ER,0,22)<<8)|Offset;
+ else
+ Offset2=SEX(8,Offset);
+ Offset2<<=1;
+ sprintf(dst,"JP 0x%x",Context.PC+2+Offset2);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(JM)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+ UINT32 Offset2;
+
+ if(TESTFLAG(FLAG_E))
+ Offset2=(EXTRACT(Context.ER,0,22)<<8)|Offset;
+ else
+ Offset2=SEX(8,Offset);
+ Offset2<<=1;
+ sprintf(dst,"JM 0x%x",Context.PC+2+Offset2);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(JNZ)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+ UINT32 Offset2;
+
+ if(TESTFLAG(FLAG_E))
+ Offset2=(EXTRACT(Context.ER,0,22)<<8)|Offset;
+ else
+ Offset2=SEX(8,Offset);
+ Offset2<<=1;
+ sprintf(dst,"JNZ 0x%x",Context.PC+2+Offset2);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(JZ)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+ UINT32 Offset2;
+
+ if(TESTFLAG(FLAG_E))
+ Offset2=(EXTRACT(Context.ER,0,22)<<8)|Offset;
+ else
+ Offset2=SEX(8,Offset);
+ Offset2<<=1;
+ sprintf(dst,"JZ 0x%x",Context.PC+2+Offset2);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(JGE)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+ UINT32 Offset2;
+
+ if(TESTFLAG(FLAG_E))
+ Offset2=(EXTRACT(Context.ER,0,22)<<8)|Offset;
+ else
+ Offset2=SEX(8,Offset);
+ Offset2<<=1;
+ sprintf(dst,"JGE 0x%x",Context.PC+2+Offset2);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(JLE)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+ UINT32 Offset2;
+
+ if(TESTFLAG(FLAG_E))
+ Offset2=(EXTRACT(Context.ER,0,22)<<8)|Offset;
+ else
+ Offset2=SEX(8,Offset);
+ Offset2<<=1;
+ sprintf(dst,"JLE 0x%x",Context.PC+2+Offset2);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(JHI)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+ UINT32 Offset2;
+
+ if(TESTFLAG(FLAG_E))
+ Offset2=(EXTRACT(Context.ER,0,22)<<8)|Offset;
+ else
+ Offset2=SEX(8,Offset);
+ Offset2<<=1;
+ sprintf(dst,"JHI 0x%x",Context.PC+2+Offset2);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(JLS)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+ UINT32 Offset2;
+
+ if(TESTFLAG(FLAG_E))
+ Offset2=(EXTRACT(Context.ER,0,22)<<8)|Offset;
+ else
+ Offset2=SEX(8,Offset);
+ Offset2<<=1;
+ sprintf(dst,"JLS 0x%x",Context.PC+2+Offset2);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(JGT)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+ UINT32 Offset2;
+
+ if(TESTFLAG(FLAG_E))
+ Offset2=(EXTRACT(Context.ER,0,22)<<8)|Offset;
+ else
+ Offset2=SEX(8,Offset);
+ Offset2<<=1;
+ sprintf(dst,"JGT 0x%x",Context.PC+2+Offset2);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(JLT)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+ UINT32 Offset2;
+
+ if(TESTFLAG(FLAG_E))
+ Offset2=(EXTRACT(Context.ER,0,22)<<8)|Offset;
+ else
+ Offset2=SEX(8,Offset);
+ Offset2<<=1;
+ sprintf(dst,"JLT 0x%x",Context.PC+2+Offset2);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+
+
+INST(JMP)
+{
+ UINT32 Offset=EXTRACT(Opcode,0,7);
+ UINT32 Offset2;
+
+ if(TESTFLAG(FLAG_E))
+ Offset2=(EXTRACT(Context.ER,0,22)<<8)|Offset;
+ else
+ Offset2=SEX(8,Offset);
+ Offset2<<=1;
+ sprintf(dst,"JMP 0x%x",Context.PC+2+Offset2);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(JR)
+{
+ UINT32 Src=EXTRACT(Opcode,0,3);
+
+ sprintf(dst,"JR %%R%d",Src);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(CALLR)
+{
+ UINT32 Src=EXTRACT(Opcode,0,3);
+
+ sprintf(dst,"CALLR %%R%d",Src);
+
+ CLRFLAG(FLAG_E);
+ return DASMFLAG_STEP_OVER;
+}
+
+INST(ASR)
+{
+ UINT32 CS=Opcode&(1<<10);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+ UINT32 Imm=EXTRACT(Opcode,5,9);
+ UINT32 Cnt=EXTRACT(Opcode,5,7);
+
+ if(CS)
+ sprintf(dst,"ASR %%R%d,%%R%d",Cnt,Dst);
+ else
+ sprintf(dst,"ASR %x,%%R%d",Imm,Dst);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(LSR)
+{
+ UINT32 CS=Opcode&(1<<10);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+ UINT32 Imm=EXTRACT(Opcode,5,9);
+ UINT32 Cnt=EXTRACT(Opcode,5,7);
+
+ if(CS)
+ sprintf(dst,"LSR %%R%d,%%R%d",Cnt,Dst);
+ else
+ sprintf(dst,"LSR %x,%%R%d",Imm,Dst);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(ASL)
+{
+ UINT32 CS=Opcode&(1<<10);
+ UINT32 Dst=EXTRACT(Opcode,0,2);
+ UINT32 Imm=EXTRACT(Opcode,5,9);
+ UINT32 Cnt=EXTRACT(Opcode,5,7);
+
+ if(CS)
+ sprintf(dst,"ASL %%R%d,%%R%d",Cnt,Dst);
+ else
+ sprintf(dst,"ASL %x,%%R%d",Imm,Dst);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(EXTB)
+{
+ UINT32 Dst=EXTRACT(Opcode,0,3);
+
+ sprintf(dst,"EXTB %%R%d",Dst);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(EXTS)
+{
+ UINT32 Dst=EXTRACT(Opcode,0,3);
+
+ sprintf(dst,"EXTS %%R%d",Dst);
+
+ CLRFLAG(FLAG_E);
+ return 0;
+}
+
+INST(SET)
+{
+ UINT32 Imm=EXTRACT(Opcode,0,3);
+
+ sprintf(dst,"SET 0x%x",Imm);
+ return 0;
+}
+
+INST(CLR)
+{
+ UINT32 Imm=EXTRACT(Opcode,0,3);
+
+ sprintf(dst,"CLR 0x%x",Imm);
+ return 0;
+}
+
+INST(SWI)
+{
+ UINT32 Imm=EXTRACT(Opcode,0,3);
+
+ sprintf(dst,"SWI 0x%x",Imm);
+ return 0;
+}
+
+INST(HALT)
+{
+ UINT32 Imm=EXTRACT(Opcode,0,3);
+
+ sprintf(dst,"HALT 0x%x",Imm);
+ return 0;
+}
+
+INST(MVTC)
+{
+ UINT32 Imm=EXTRACT(Opcode,0,3);
+
+ sprintf(dst,"MVTC %%R0,%%CR%d",Imm);
+ return 0;
+}
+
+INST(MVFC)
+{
+ UINT32 Imm=EXTRACT(Opcode,0,3);
+
+ sprintf(dst,"MVFC %%CR0%d,%%R0",Imm);
+ return 0;
+}
+
+static _OP DecodeOp(UINT16 Opcode)
+{
+ switch(EXTRACT(Opcode,14,15))
+ {
+ case 0x0:
+ {
+ UINT8 Op=EXTRACT(Opcode,11,13);
+ switch(Op)
+ {
+ case 0x0:
+ return LDB;
+ case 0x1:
+ return LDS;
+ case 0x2:
+ return LD;
+ case 0x3:
+ return LDBU;
+ case 0x4:
+ return STB;
+ case 0x5:
+ return STS;
+ case 0x6:
+ return ST;
+ case 0x7:
+ return LDSU;
+ }
+ }
+ break;
+ case 0x1:
+ return LERI;
+ case 0x2:
+ {
+ switch(EXTRACT(Opcode,11,13))
+ {
+ case 0:
+ return LDSP;
+ case 1:
+ return STSP;
+ case 2:
+ return PUSH;
+ case 3:
+ return POP;
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8: //arith
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ switch(EXTRACT(Opcode,6,8))
+ {
+ case 0:
+ return ADDI;
+ case 1:
+ return ADCI;
+ case 2:
+ return SUBI;
+ case 3:
+ return SBCI;
+ case 4:
+ return ANDI;
+ case 5:
+ return ORI;
+ case 6:
+ return XORI;
+ case 7:
+ switch(EXTRACT(Opcode,0,2))
+ {
+ case 0:
+ return CMPI;
+ case 1:
+ return TSTI;
+ case 2:
+ return LEATOSP;
+ case 3:
+ return LEAFROMSP;
+ }
+ break;
+ }
+ break;
+ }
+ }
+ break;
+ case 3:
+ switch(EXTRACT(Opcode,12,13))
+ {
+ case 0:
+ switch(EXTRACT(Opcode,6,8))
+ {
+ case 0:
+ return ADD;
+ case 1:
+ return ADC;
+ case 2:
+ return SUB;
+ case 3:
+ return SBC;
+ case 4:
+ return AND;
+ case 5:
+ return OR;
+ case 6:
+ return XOR;
+ case 7:
+ switch(EXTRACT(Opcode,0,2))
+ {
+ case 0:
+ return CMP;
+ case 1:
+ return TST;
+ case 2:
+ return MOV;
+ case 3:
+ return NEG;
+ }
+ break;
+ }
+ break;
+ case 1: //Jumps
+ switch(EXTRACT(Opcode,8,11))
+ {
+ case 0x0:
+ return JNV;
+ case 0x1:
+ return JV;
+ case 0x2:
+ return JP;
+ case 0x3:
+ return JM;
+ case 0x4:
+ return JNZ;
+ case 0x5:
+ return JZ;
+ case 0x6:
+ return JNC;
+ case 0x7:
+ return JC;
+ case 0x8:
+ return JGT;
+ case 0x9:
+ return JLT;
+ case 0xa:
+ return JGE;
+ case 0xb:
+ return JLE;
+ case 0xc:
+ return JHI;
+ case 0xd:
+ return JLS;
+ case 0xe:
+ return JMP;
+ case 0xf:
+ return CALL;
+ }
+ break;
+ case 2:
+ if(Opcode&(1<<11))
+ return LDI;
+ else //SP Ops
+ {
+ if(Opcode&(1<<10))
+ {
+ switch(EXTRACT(Opcode,7,9))
+ {
+ case 0:
+ return LDBSP;
+ case 1:
+ return LDSSP;
+ case 3:
+ return LDBUSP;
+ case 4:
+ return STBSP;
+ case 5:
+ return STSSP;
+ case 7:
+ return LDSUSP;
+ }
+ }
+ else
+ {
+ if(Opcode&(1<<9))
+ {
+ return LEASPTOSP;
+ }
+ else
+ {
+ if(Opcode&(1<<8))
+ {
+
+ }
+ else
+ {
+ switch(EXTRACT(Opcode,4,7))
+ {
+ case 0:
+ return EXTB;
+ case 1:
+ return EXTS;
+ case 8:
+ return JR;
+ case 9:
+ return CALLR;
+ case 10:
+ return SET;
+ case 11:
+ return CLR;
+ case 12:
+ return SWI;
+ case 13:
+ return HALT;
+ }
+ }
+ }
+ }
+ }
+ break;
+ case 3:
+ switch(EXTRACT(Opcode,9,11))
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ switch(EXTRACT(Opcode,3,4))
+ {
+ case 0:
+ return ASR;
+ case 1:
+ return LSR;
+ case 2:
+ return ASL;
+ //case 3:
+ // return LSL;
+ }
+ break;
+ case 4:
+ return MULS;
+ case 6:
+ if(Opcode&(1<<3))
+ return MVFC;
+ else
+ return MVTC;
+ break;
+ }
+ break;
+ }
+ break;
+
+ }
+ return INVALIDOP;
+}
+
+
+CPU_DISASSEMBLE( se3208 )
+{
+ UINT16 Opcode;
+
+ CLRFLAG(FLAG_E);
+ Context.ER=0;
+
+ Context.PC=pc;
+ Opcode=oprom[0] | (oprom[1] << 8);
+ return 2 | ((*DecodeOp(Opcode))(Opcode,buffer)) | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/sh2/sh2.c b/trunk/src/emu/cpu/sh2/sh2.c
new file mode 100644
index 00000000000..70282c98c95
--- /dev/null
+++ b/trunk/src/emu/cpu/sh2/sh2.c
@@ -0,0 +1,2508 @@
+/*****************************************************************************
+ *
+ * sh2.c
+ * Portable Hitachi SH-2 (SH7600 family) emulator
+ *
+ * Copyright Juergen Buchmueller <pullmoll@t-online.de>,
+ * 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 <tiraniddo@hotmail.com> C/C++ implementation of
+ * the SH-2 CPU core and was adapted to the MAME CPU core requirements.
+ * Thanks also go to Chuck Mason <chukjr@sundail.net> and Olivier Galibert
+ * <galibert@pobox.com> for letting me peek into their SEMU code :-)
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ Changes
+ 20051129 Mariusz Wojcieszek
+ - introduced memory_decrypted_read_word() for opcode fetching
+
+ 20050813 Mariusz Wojcieszek
+ - fixed 64 bit / 32 bit division in division unit
+
+ 20031015 O. Galibert
+ - dma fixes, thanks to sthief
+
+ 20031013 O. Galibert, A. Giles
+ - timer fixes
+ - multi-cpu simplifications
+
+ 20030915 O. Galibert
+ - fix DMA1 irq vector
+ - ignore writes to DRCRx
+ - fix cpu number issues
+ - fix slave/master recognition
+ - fix wrong-cpu-in-context problem with the timers
+
+ 20021020 O. Galibert
+ - DMA implementation, lightly tested
+ - delay slot in debugger fixed
+ - add divide box mirrors
+ - Nicola-ify the indentation
+ - Uncrapify sh2_internal_*
+ - Put back nmi support that had been lost somehow
+
+ 20020914 R. Belmont
+ - Initial SH2 internal timers implementation, based on code by O. Galibert.
+ Makes music work in galspanic4/s/s2, panic street, cyvern, other SKNS games.
+ - Fix to external division, thanks to "spice" on the E2J board.
+ Corrects behavior of s1945ii turret boss.
+
+ 20020302 Olivier Galibert (galibert@mame.net)
+ - Fixed interrupt in delay slot
+ - Fixed rotcr
+ - Fixed div1
+ - Fixed mulu
+ - Fixed negc
+
+ 20020301 R. Belmont
+ - Fixed external division
+
+ 20020225 Olivier Galibert (galibert@mame.net)
+ - Fixed interrupt handling
+
+ 20010207 Sylvain Glaize (mokona@puupuu.org)
+
+ - Bug fix in INLINE void MOVBM(UINT32 m, UINT32 n) (see comment)
+ - Support of full 32 bit addressing (RB, RW, RL and WB, WW, WL functions)
+ reason : when the two high bits of the address are set, access is
+ done directly in the cache data array. The SUPER KANEKO NOVA SYSTEM
+ sets the stack pointer here, using these addresses as usual RAM access.
+
+ No real cache support has been added.
+ - Read/Write memory format correction (_bew to _bedw) (see also SH2
+ definition in cpuintrf.c and DasmSH2(..) in sh2dasm.c )
+
+ 20010623 James Forshaw (TyRaNiD@totalise.net)
+
+ - Modified operation of sh2_exception. Done cause mame irq system is stupid, and
+ doesnt really seem designed for any more than 8 interrupt lines.
+
+ 20010701 James Forshaw (TyRaNiD@totalise.net)
+
+ - Fixed DIV1 operation. Q bit now correctly generated
+
+ 20020218 Added save states (mokona@puupuu.org)
+
+ *****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "sh2.h"
+#include "sh2comn.h"
+
+CPU_DISASSEMBLE( sh2 );
+
+#ifndef USE_SH2DRC
+
+/* speed up delay loops, bail out of tight loops */
+#define BUSY_LOOP_HACKS 1
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+INLINE sh2_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->token != NULL);
+ assert(device->type() == CPU);
+ assert(cpu_get_type(device) == CPU_SH1 ||
+ cpu_get_type(device) == CPU_SH2);
+ return (sh2_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+INLINE UINT8 RB(sh2_state *sh2, offs_t A)
+{
+ if (A >= 0xe0000000)
+ return sh2_internal_r(sh2->internal, (A & 0x1fc)>>2, 0xff << (((~A) & 3)*8)) >> (((~A) & 3)*8);
+
+ if (A >= 0xc0000000)
+ return sh2->program->read_byte(A);
+
+ if (A >= 0x40000000)
+ return 0xa5;
+
+ return sh2->program->read_byte(A & AM);
+}
+
+INLINE UINT16 RW(sh2_state *sh2, offs_t A)
+{
+ if (A >= 0xe0000000)
+ return sh2_internal_r(sh2->internal, (A & 0x1fc)>>2, 0xffff << (((~A) & 2)*8)) >> (((~A) & 2)*8);
+
+ if (A >= 0xc0000000)
+ return sh2->program->read_word(A);
+
+ if (A >= 0x40000000)
+ return 0xa5a5;
+
+ return sh2->program->read_word(A & AM);
+}
+
+INLINE UINT32 RL(sh2_state *sh2, offs_t A)
+{
+ if (A >= 0xe0000000)
+ return sh2_internal_r(sh2->internal, (A & 0x1fc)>>2, 0xffffffff);
+
+ if (A >= 0xc0000000)
+ return sh2->program->read_dword(A);
+
+ if (A >= 0x40000000)
+ return 0xa5a5a5a5;
+
+ return sh2->program->read_dword(A & AM);
+}
+
+INLINE void WB(sh2_state *sh2, offs_t A, UINT8 V)
+{
+
+ if (A >= 0xe0000000)
+ {
+ sh2_internal_w(sh2->internal, (A & 0x1fc)>>2, V << (((~A) & 3)*8), 0xff << (((~A) & 3)*8));
+ return;
+ }
+
+ if (A >= 0xc0000000)
+ {
+ sh2->program->write_byte(A,V);
+ return;
+ }
+
+ if (A >= 0x40000000)
+ return;
+
+ sh2->program->write_byte(A & AM,V);
+}
+
+INLINE void WW(sh2_state *sh2, offs_t A, UINT16 V)
+{
+ if (A >= 0xe0000000)
+ {
+ sh2_internal_w(sh2->internal, (A & 0x1fc)>>2, V << (((~A) & 2)*8), 0xffff << (((~A) & 2)*8));
+ return;
+ }
+
+ if (A >= 0xc0000000)
+ {
+ sh2->program->write_word(A,V);
+ return;
+ }
+
+ if (A >= 0x40000000)
+ return;
+
+ sh2->program->write_word(A & AM,V);
+}
+
+INLINE void WL(sh2_state *sh2, offs_t A, UINT32 V)
+{
+ if (A >= 0xe0000000)
+ {
+ sh2_internal_w(sh2->internal, (A & 0x1fc)>>2, V, 0xffffffff);
+ return;
+ }
+
+ if (A >= 0xc0000000)
+ {
+ sh2->program->write_dword(A,V);
+ return;
+ }
+
+ if (A >= 0x40000000)
+ return;
+
+ sh2->program->write_dword(A & AM,V);
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 1100 1 -
+ * ADD Rm,Rn
+ */
+INLINE void ADD(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->r[n] += sh2->r[m];
+}
+
+/* code cycles t-bit
+ * 0111 nnnn iiii iiii 1 -
+ * ADD #imm,Rn
+ */
+INLINE void ADDI(sh2_state *sh2, UINT32 i, UINT32 n)
+{
+ sh2->r[n] += (INT32)(INT16)(INT8)i;
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 1110 1 carry
+ * ADDC Rm,Rn
+ */
+INLINE void ADDC(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ UINT32 tmp0, tmp1;
+
+ tmp1 = sh2->r[n] + sh2->r[m];
+ tmp0 = sh2->r[n];
+ sh2->r[n] = tmp1 + (sh2->sr & T);
+ if (tmp0 > tmp1)
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+ if (tmp1 > sh2->r[n])
+ sh2->sr |= T;
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 1111 1 overflow
+ * ADDV Rm,Rn
+ */
+INLINE void ADDV(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ INT32 dest, src, ans;
+
+ if ((INT32) sh2->r[n] >= 0)
+ dest = 0;
+ else
+ dest = 1;
+ if ((INT32) sh2->r[m] >= 0)
+ src = 0;
+ else
+ src = 1;
+ src += dest;
+ sh2->r[n] += sh2->r[m];
+ if ((INT32) sh2->r[n] >= 0)
+ ans = 0;
+ else
+ ans = 1;
+ ans += dest;
+ if (src == 0 || src == 2)
+ {
+ if (ans == 1)
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+ }
+ else
+ sh2->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0010 nnnn mmmm 1001 1 -
+ * AND Rm,Rn
+ */
+INLINE void AND(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->r[n] &= sh2->r[m];
+}
+
+
+/* code cycles t-bit
+ * 1100 1001 iiii iiii 1 -
+ * AND #imm,R0
+ */
+INLINE void ANDI(sh2_state *sh2, UINT32 i)
+{
+ sh2->r[0] &= i;
+}
+
+/* code cycles t-bit
+ * 1100 1101 iiii iiii 1 -
+ * AND.B #imm,@(R0,GBR)
+ */
+INLINE void ANDM(sh2_state *sh2, UINT32 i)
+{
+ UINT32 temp;
+
+ sh2->ea = sh2->gbr + sh2->r[0];
+ temp = i & RB( sh2, sh2->ea );
+ WB( sh2, sh2->ea, temp );
+ sh2->icount -= 2;
+}
+
+/* code cycles t-bit
+ * 1000 1011 dddd dddd 3/1 -
+ * BF disp8
+ */
+INLINE void BF(sh2_state *sh2, UINT32 d)
+{
+ if ((sh2->sr & T) == 0)
+ {
+ INT32 disp = ((INT32)d << 24) >> 24;
+ sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2;
+ sh2->icount -= 2;
+ }
+}
+
+/* code cycles t-bit
+ * 1000 1111 dddd dddd 3/1 -
+ * BFS disp8
+ */
+INLINE void BFS(sh2_state *sh2, UINT32 d)
+{
+ if ((sh2->sr & T) == 0)
+ {
+ INT32 disp = ((INT32)d << 24) >> 24;
+ sh2->delay = sh2->pc;
+ sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2;
+ sh2->icount--;
+ }
+}
+
+/* code cycles t-bit
+ * 1010 dddd dddd dddd 2 -
+ * BRA disp12
+ */
+INLINE void BRA(sh2_state *sh2, UINT32 d)
+{
+ INT32 disp = ((INT32)d << 20) >> 20;
+
+#if BUSY_LOOP_HACKS
+ if (disp == -2)
+ {
+ UINT32 next_opcode = RW( sh2, sh2->ppc & AM );
+ /* BRA $
+ * NOP
+ */
+ if (next_opcode == 0x0009)
+ sh2->icount %= 3; /* cycles for BRA $ and NOP taken (3) */
+ }
+#endif
+ sh2->delay = sh2->pc;
+ sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2;
+ sh2->icount--;
+}
+
+/* code cycles t-bit
+ * 0000 mmmm 0010 0011 2 -
+ * BRAF Rm
+ */
+INLINE void BRAF(sh2_state *sh2, UINT32 m)
+{
+ sh2->delay = sh2->pc;
+ sh2->pc += sh2->r[m] + 2;
+ sh2->icount--;
+}
+
+/* code cycles t-bit
+ * 1011 dddd dddd dddd 2 -
+ * BSR disp12
+ */
+INLINE void BSR(sh2_state *sh2, UINT32 d)
+{
+ INT32 disp = ((INT32)d << 20) >> 20;
+
+ sh2->pr = sh2->pc + 2;
+ sh2->delay = sh2->pc;
+ sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2;
+ sh2->icount--;
+}
+
+/* code cycles t-bit
+ * 0000 mmmm 0000 0011 2 -
+ * BSRF Rm
+ */
+INLINE void BSRF(sh2_state *sh2, UINT32 m)
+{
+ sh2->pr = sh2->pc + 2;
+ sh2->delay = sh2->pc;
+ sh2->pc += sh2->r[m] + 2;
+ sh2->icount--;
+}
+
+/* code cycles t-bit
+ * 1000 1001 dddd dddd 3/1 -
+ * BT disp8
+ */
+INLINE void BT(sh2_state *sh2, UINT32 d)
+{
+ if ((sh2->sr & T) != 0)
+ {
+ INT32 disp = ((INT32)d << 24) >> 24;
+ sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2;
+ sh2->icount -= 2;
+ }
+}
+
+/* code cycles t-bit
+ * 1000 1101 dddd dddd 2/1 -
+ * BTS disp8
+ */
+INLINE void BTS(sh2_state *sh2, UINT32 d)
+{
+ if ((sh2->sr & T) != 0)
+ {
+ INT32 disp = ((INT32)d << 24) >> 24;
+ sh2->delay = sh2->pc;
+ sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2;
+ sh2->icount--;
+ }
+}
+
+/* code cycles t-bit
+ * 0000 0000 0010 1000 1 -
+ * CLRMAC
+ */
+INLINE void CLRMAC(sh2_state *sh2)
+{
+ sh2->mach = 0;
+ sh2->macl = 0;
+}
+
+/* code cycles t-bit
+ * 0000 0000 0000 1000 1 -
+ * CLRT
+ */
+INLINE void CLRT(sh2_state *sh2)
+{
+ sh2->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 0000 1 comparison result
+ * CMP_EQ Rm,Rn
+ */
+INLINE void CMPEQ(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ if (sh2->r[n] == sh2->r[m])
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 0011 1 comparison result
+ * CMP_GE Rm,Rn
+ */
+INLINE void CMPGE(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ if ((INT32) sh2->r[n] >= (INT32) sh2->r[m])
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 0111 1 comparison result
+ * CMP_GT Rm,Rn
+ */
+INLINE void CMPGT(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ if ((INT32) sh2->r[n] > (INT32) sh2->r[m])
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 0110 1 comparison result
+ * CMP_HI Rm,Rn
+ */
+INLINE void CMPHI(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ if ((UINT32) sh2->r[n] > (UINT32) sh2->r[m])
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 0010 1 comparison result
+ * CMP_HS Rm,Rn
+ */
+INLINE void CMPHS(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ if ((UINT32) sh2->r[n] >= (UINT32) sh2->r[m])
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+}
+
+
+/* code cycles t-bit
+ * 0100 nnnn 0001 0101 1 comparison result
+ * CMP_PL Rn
+ */
+INLINE void CMPPL(sh2_state *sh2, UINT32 n)
+{
+ if ((INT32) sh2->r[n] > 0)
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0100 nnnn 0001 0001 1 comparison result
+ * CMP_PZ Rn
+ */
+INLINE void CMPPZ(sh2_state *sh2, UINT32 n)
+{
+ if ((INT32) sh2->r[n] >= 0)
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0010 nnnn mmmm 1100 1 comparison result
+ * CMP_STR Rm,Rn
+ */
+INLINE void CMPSTR(sh2_state *sh2, UINT32 m, UINT32 n)
+ {
+ UINT32 temp;
+ INT32 HH, HL, LH, LL;
+ temp = sh2->r[n] ^ sh2->r[m];
+ HH = (temp >> 24) & 0xff;
+ HL = (temp >> 16) & 0xff;
+ LH = (temp >> 8) & 0xff;
+ LL = temp & 0xff;
+ if (HH && HL && LH && LL)
+ sh2->sr &= ~T;
+ else
+ sh2->sr |= T;
+ }
+
+
+/* code cycles t-bit
+ * 1000 1000 iiii iiii 1 comparison result
+ * CMP/EQ #imm,R0
+ */
+INLINE void CMPIM(sh2_state *sh2, UINT32 i)
+{
+ UINT32 imm = (UINT32)(INT32)(INT16)(INT8)i;
+
+ if (sh2->r[0] == imm)
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0010 nnnn mmmm 0111 1 calculation result
+ * DIV0S Rm,Rn
+ */
+INLINE void DIV0S(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ if ((sh2->r[n] & 0x80000000) == 0)
+ sh2->sr &= ~Q;
+ else
+ sh2->sr |= Q;
+ if ((sh2->r[m] & 0x80000000) == 0)
+ sh2->sr &= ~M;
+ else
+ sh2->sr |= M;
+ if ((sh2->r[m] ^ sh2->r[n]) & 0x80000000)
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0000 0000 0001 1001 1 0
+ * DIV0U
+ */
+INLINE void DIV0U(sh2_state *sh2)
+{
+ sh2->sr &= ~(M | Q | T);
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 0100 1 calculation result
+ * DIV1 Rm,Rn
+ */
+INLINE void DIV1(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ UINT32 tmp0;
+ UINT32 old_q;
+
+ old_q = sh2->sr & Q;
+ if (0x80000000 & sh2->r[n])
+ sh2->sr |= Q;
+ else
+ sh2->sr &= ~Q;
+
+ sh2->r[n] = (sh2->r[n] << 1) | (sh2->sr & T);
+
+ if (!old_q)
+ {
+ if (!(sh2->sr & M))
+ {
+ tmp0 = sh2->r[n];
+ sh2->r[n] -= sh2->r[m];
+ if(!(sh2->sr & Q))
+ if(sh2->r[n] > tmp0)
+ sh2->sr |= Q;
+ else
+ sh2->sr &= ~Q;
+ else
+ if(sh2->r[n] > tmp0)
+ sh2->sr &= ~Q;
+ else
+ sh2->sr |= Q;
+ }
+ else
+ {
+ tmp0 = sh2->r[n];
+ sh2->r[n] += sh2->r[m];
+ if(!(sh2->sr & Q))
+ {
+ if(sh2->r[n] < tmp0)
+ sh2->sr &= ~Q;
+ else
+ sh2->sr |= Q;
+ }
+ else
+ {
+ if(sh2->r[n] < tmp0)
+ sh2->sr |= Q;
+ else
+ sh2->sr &= ~Q;
+ }
+ }
+ }
+ else
+ {
+ if (!(sh2->sr & M))
+ {
+ tmp0 = sh2->r[n];
+ sh2->r[n] += sh2->r[m];
+ if(!(sh2->sr & Q))
+ if(sh2->r[n] < tmp0)
+ sh2->sr |= Q;
+ else
+ sh2->sr &= ~Q;
+ else
+ if(sh2->r[n] < tmp0)
+ sh2->sr &= ~Q;
+ else
+ sh2->sr |= Q;
+ }
+ else
+ {
+ tmp0 = sh2->r[n];
+ sh2->r[n] -= sh2->r[m];
+ if(!(sh2->sr & Q))
+ if(sh2->r[n] > tmp0)
+ sh2->sr &= ~Q;
+ else
+ sh2->sr |= Q;
+ else
+ if(sh2->r[n] > tmp0)
+ sh2->sr |= Q;
+ else
+ sh2->sr &= ~Q;
+ }
+ }
+
+ tmp0 = (sh2->sr & (Q | M));
+ if((!tmp0) || (tmp0 == 0x300)) /* if Q == M set T else clear T */
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+}
+
+/* DMULS.L Rm,Rn */
+INLINE void DMULS(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2;
+ UINT32 temp0, temp1, temp2, temp3;
+ INT32 tempm, tempn, fnLmL;
+
+ tempn = (INT32) sh2->r[n];
+ tempm = (INT32) sh2->r[m];
+ if (tempn < 0)
+ tempn = 0 - tempn;
+ if (tempm < 0)
+ tempm = 0 - tempm;
+ if ((INT32) (sh2->r[n] ^ sh2->r[m]) < 0)
+ fnLmL = -1;
+ else
+ fnLmL = 0;
+ temp1 = (UINT32) tempn;
+ temp2 = (UINT32) tempm;
+ RnL = temp1 & 0x0000ffff;
+ RnH = (temp1 >> 16) & 0x0000ffff;
+ RmL = temp2 & 0x0000ffff;
+ RmH = (temp2 >> 16) & 0x0000ffff;
+ temp0 = RmL * RnL;
+ temp1 = RmH * RnL;
+ temp2 = RmL * RnH;
+ temp3 = RmH * RnH;
+ Res2 = 0;
+ Res1 = temp1 + temp2;
+ if (Res1 < temp1)
+ Res2 += 0x00010000;
+ temp1 = (Res1 << 16) & 0xffff0000;
+ Res0 = temp0 + temp1;
+ if (Res0 < temp0)
+ Res2++;
+ Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3;
+ if (fnLmL < 0)
+ {
+ Res2 = ~Res2;
+ if (Res0 == 0)
+ Res2++;
+ else
+ Res0 = (~Res0) + 1;
+ }
+ sh2->mach = Res2;
+ sh2->macl = Res0;
+ sh2->icount--;
+}
+
+/* DMULU.L Rm,Rn */
+INLINE void DMULU(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2;
+ UINT32 temp0, temp1, temp2, temp3;
+
+ RnL = sh2->r[n] & 0x0000ffff;
+ RnH = (sh2->r[n] >> 16) & 0x0000ffff;
+ RmL = sh2->r[m] & 0x0000ffff;
+ RmH = (sh2->r[m] >> 16) & 0x0000ffff;
+ temp0 = RmL * RnL;
+ temp1 = RmH * RnL;
+ temp2 = RmL * RnH;
+ temp3 = RmH * RnH;
+ Res2 = 0;
+ Res1 = temp1 + temp2;
+ if (Res1 < temp1)
+ Res2 += 0x00010000;
+ temp1 = (Res1 << 16) & 0xffff0000;
+ Res0 = temp0 + temp1;
+ if (Res0 < temp0)
+ Res2++;
+ Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3;
+ sh2->mach = Res2;
+ sh2->macl = Res0;
+ sh2->icount--;
+}
+
+/* DT Rn */
+INLINE void DT(sh2_state *sh2, UINT32 n)
+{
+ sh2->r[n]--;
+ if (sh2->r[n] == 0)
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+#if BUSY_LOOP_HACKS
+ {
+ UINT32 next_opcode = RW( sh2, sh2->ppc & AM );
+ /* DT Rn
+ * BF $-2
+ */
+ if (next_opcode == 0x8bfd)
+ {
+ while (sh2->r[n] > 1 && sh2->icount > 4)
+ {
+ sh2->r[n]--;
+ sh2->icount -= 4; /* cycles for DT (1) and BF taken (3) */
+ }
+ }
+ }
+#endif
+}
+
+/* EXTS.B Rm,Rn */
+INLINE void EXTSB(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->r[n] = ((INT32)sh2->r[m] << 24) >> 24;
+}
+
+/* EXTS.W Rm,Rn */
+INLINE void EXTSW(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->r[n] = ((INT32)sh2->r[m] << 16) >> 16;
+}
+
+/* EXTU.B Rm,Rn */
+INLINE void EXTUB(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->r[n] = sh2->r[m] & 0x000000ff;
+}
+
+/* EXTU.W Rm,Rn */
+INLINE void EXTUW(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->r[n] = sh2->r[m] & 0x0000ffff;
+}
+
+/* JMP @Rm */
+INLINE void JMP(sh2_state *sh2, UINT32 m)
+{
+ sh2->delay = sh2->pc;
+ sh2->pc = sh2->ea = sh2->r[m];
+}
+
+/* JSR @Rm */
+INLINE void JSR(sh2_state *sh2, UINT32 m)
+{
+ sh2->delay = sh2->pc;
+ sh2->pr = sh2->pc + 2;
+ sh2->pc = sh2->ea = sh2->r[m];
+ sh2->icount--;
+}
+
+
+/* LDC Rm,SR */
+INLINE void LDCSR(sh2_state *sh2, UINT32 m)
+{
+ sh2->sr = sh2->r[m] & FLAGS;
+ sh2->test_irq = 1;
+}
+
+/* LDC Rm,GBR */
+INLINE void LDCGBR(sh2_state *sh2, UINT32 m)
+{
+ sh2->gbr = sh2->r[m];
+}
+
+/* LDC Rm,VBR */
+INLINE void LDCVBR(sh2_state *sh2, UINT32 m)
+{
+ sh2->vbr = sh2->r[m];
+}
+
+/* LDC.L @Rm+,SR */
+INLINE void LDCMSR(sh2_state *sh2, UINT32 m)
+{
+ sh2->ea = sh2->r[m];
+ sh2->sr = RL( sh2, sh2->ea ) & FLAGS;
+ sh2->r[m] += 4;
+ sh2->icount -= 2;
+ sh2->test_irq = 1;
+}
+
+/* LDC.L @Rm+,GBR */
+INLINE void LDCMGBR(sh2_state *sh2, UINT32 m)
+{
+ sh2->ea = sh2->r[m];
+ sh2->gbr = RL( sh2, sh2->ea );
+ sh2->r[m] += 4;
+ sh2->icount -= 2;
+}
+
+/* LDC.L @Rm+,VBR */
+INLINE void LDCMVBR(sh2_state *sh2, UINT32 m)
+{
+ sh2->ea = sh2->r[m];
+ sh2->vbr = RL( sh2, sh2->ea );
+ sh2->r[m] += 4;
+ sh2->icount -= 2;
+}
+
+/* LDS Rm,MACH */
+INLINE void LDSMACH(sh2_state *sh2, UINT32 m)
+{
+ sh2->mach = sh2->r[m];
+}
+
+/* LDS Rm,MACL */
+INLINE void LDSMACL(sh2_state *sh2, UINT32 m)
+{
+ sh2->macl = sh2->r[m];
+}
+
+/* LDS Rm,PR */
+INLINE void LDSPR(sh2_state *sh2, UINT32 m)
+{
+ sh2->pr = sh2->r[m];
+}
+
+/* LDS.L @Rm+,MACH */
+INLINE void LDSMMACH(sh2_state *sh2, UINT32 m)
+{
+ sh2->ea = sh2->r[m];
+ sh2->mach = RL( sh2, sh2->ea );
+ sh2->r[m] += 4;
+}
+
+/* LDS.L @Rm+,MACL */
+INLINE void LDSMMACL(sh2_state *sh2, UINT32 m)
+{
+ sh2->ea = sh2->r[m];
+ sh2->macl = RL( sh2, sh2->ea );
+ sh2->r[m] += 4;
+}
+
+/* LDS.L @Rm+,PR */
+INLINE void LDSMPR(sh2_state *sh2, UINT32 m)
+{
+ sh2->ea = sh2->r[m];
+ sh2->pr = RL( sh2, sh2->ea );
+ sh2->r[m] += 4;
+}
+
+/* MAC.L @Rm+,@Rn+ */
+INLINE void MAC_L(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2;
+ UINT32 temp0, temp1, temp2, temp3;
+ INT32 tempm, tempn, fnLmL;
+
+ tempn = (INT32) RL( sh2, sh2->r[n] );
+ sh2->r[n] += 4;
+ tempm = (INT32) RL( sh2, sh2->r[m] );
+ sh2->r[m] += 4;
+ if ((INT32) (tempn ^ tempm) < 0)
+ fnLmL = -1;
+ else
+ fnLmL = 0;
+ if (tempn < 0)
+ tempn = 0 - tempn;
+ if (tempm < 0)
+ tempm = 0 - tempm;
+ temp1 = (UINT32) tempn;
+ temp2 = (UINT32) tempm;
+ RnL = temp1 & 0x0000ffff;
+ RnH = (temp1 >> 16) & 0x0000ffff;
+ RmL = temp2 & 0x0000ffff;
+ RmH = (temp2 >> 16) & 0x0000ffff;
+ temp0 = RmL * RnL;
+ temp1 = RmH * RnL;
+ temp2 = RmL * RnH;
+ temp3 = RmH * RnH;
+ Res2 = 0;
+ Res1 = temp1 + temp2;
+ if (Res1 < temp1)
+ Res2 += 0x00010000;
+ temp1 = (Res1 << 16) & 0xffff0000;
+ Res0 = temp0 + temp1;
+ if (Res0 < temp0)
+ Res2++;
+ Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3;
+ if (fnLmL < 0)
+ {
+ Res2 = ~Res2;
+ if (Res0 == 0)
+ Res2++;
+ else
+ Res0 = (~Res0) + 1;
+ }
+ if (sh2->sr & S)
+ {
+ Res0 = sh2->macl + Res0;
+ if (sh2->macl > Res0)
+ Res2++;
+ Res2 += (sh2->mach & 0x0000ffff);
+ if (((INT32) Res2 < 0) && (Res2 < 0xffff8000))
+ {
+ Res2 = 0x00008000;
+ Res0 = 0x00000000;
+ }
+ else if (((INT32) Res2 > 0) && (Res2 > 0x00007fff))
+ {
+ Res2 = 0x00007fff;
+ Res0 = 0xffffffff;
+ }
+ sh2->mach = Res2;
+ sh2->macl = Res0;
+ }
+ else
+ {
+ Res0 = sh2->macl + Res0;
+ if (sh2->macl > Res0)
+ Res2++;
+ Res2 += sh2->mach;
+ sh2->mach = Res2;
+ sh2->macl = Res0;
+ }
+ sh2->icount -= 2;
+}
+
+/* MAC.W @Rm+,@Rn+ */
+INLINE void MAC_W(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ INT32 tempm, tempn, dest, src, ans;
+ UINT32 templ;
+
+ tempn = (INT32) RW( sh2, sh2->r[n] );
+ sh2->r[n] += 2;
+ tempm = (INT32) RW( sh2, sh2->r[m] );
+ sh2->r[m] += 2;
+ templ = sh2->macl;
+ tempm = ((INT32) (short) tempn * (INT32) (short) tempm);
+ if ((INT32) sh2->macl >= 0)
+ dest = 0;
+ else
+ dest = 1;
+ if ((INT32) tempm >= 0)
+ {
+ src = 0;
+ tempn = 0;
+ }
+ else
+ {
+ src = 1;
+ tempn = 0xffffffff;
+ }
+ src += dest;
+ sh2->macl += tempm;
+ if ((INT32) sh2->macl >= 0)
+ ans = 0;
+ else
+ ans = 1;
+ ans += dest;
+ if (sh2->sr & S)
+ {
+ if (ans == 1)
+ {
+ if (src == 0)
+ sh2->macl = 0x7fffffff;
+ if (src == 2)
+ sh2->macl = 0x80000000;
+ }
+ }
+ else
+ {
+ sh2->mach += tempn;
+ if (templ > sh2->macl)
+ sh2->mach += 1;
+ }
+ sh2->icount -= 2;
+}
+
+/* MOV Rm,Rn */
+INLINE void MOV(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->r[n] = sh2->r[m];
+}
+
+/* MOV.B Rm,@Rn */
+INLINE void MOVBS(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->ea = sh2->r[n];
+ WB( sh2, sh2->ea, sh2->r[m] & 0x000000ff);
+}
+
+/* MOV.W Rm,@Rn */
+INLINE void MOVWS(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->ea = sh2->r[n];
+ WW( sh2, sh2->ea, sh2->r[m] & 0x0000ffff);
+}
+
+/* MOV.L Rm,@Rn */
+INLINE void MOVLS(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->ea = sh2->r[n];
+ WL( sh2, sh2->ea, sh2->r[m] );
+}
+
+/* MOV.B @Rm,Rn */
+INLINE void MOVBL(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->ea = sh2->r[m];
+ sh2->r[n] = (UINT32)(INT32)(INT16)(INT8) RB( sh2, sh2->ea );
+}
+
+/* MOV.W @Rm,Rn */
+INLINE void MOVWL(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->ea = sh2->r[m];
+ sh2->r[n] = (UINT32)(INT32)(INT16) RW( sh2, sh2->ea );
+}
+
+/* MOV.L @Rm,Rn */
+INLINE void MOVLL(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->ea = sh2->r[m];
+ sh2->r[n] = RL( sh2, sh2->ea );
+}
+
+/* MOV.B Rm,@-Rn */
+INLINE void MOVBM(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ /* SMG : bug fix, was reading sh2->r[n] */
+ UINT32 data = sh2->r[m] & 0x000000ff;
+
+ sh2->r[n] -= 1;
+ WB( sh2, sh2->r[n], data );
+}
+
+/* MOV.W Rm,@-Rn */
+INLINE void MOVWM(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ UINT32 data = sh2->r[m] & 0x0000ffff;
+
+ sh2->r[n] -= 2;
+ WW( sh2, sh2->r[n], data );
+}
+
+/* MOV.L Rm,@-Rn */
+INLINE void MOVLM(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ UINT32 data = sh2->r[m];
+
+ sh2->r[n] -= 4;
+ WL( sh2, sh2->r[n], data );
+}
+
+/* MOV.B @Rm+,Rn */
+INLINE void MOVBP(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->r[n] = (UINT32)(INT32)(INT16)(INT8) RB( sh2, sh2->r[m] );
+ if (n != m)
+ sh2->r[m] += 1;
+}
+
+/* MOV.W @Rm+,Rn */
+INLINE void MOVWP(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->r[n] = (UINT32)(INT32)(INT16) RW( sh2, sh2->r[m] );
+ if (n != m)
+ sh2->r[m] += 2;
+}
+
+/* MOV.L @Rm+,Rn */
+INLINE void MOVLP(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->r[n] = RL( sh2, sh2->r[m] );
+ if (n != m)
+ sh2->r[m] += 4;
+}
+
+/* MOV.B Rm,@(R0,Rn) */
+INLINE void MOVBS0(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->ea = sh2->r[n] + sh2->r[0];
+ WB( sh2, sh2->ea, sh2->r[m] & 0x000000ff );
+}
+
+/* MOV.W Rm,@(R0,Rn) */
+INLINE void MOVWS0(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->ea = sh2->r[n] + sh2->r[0];
+ WW( sh2, sh2->ea, sh2->r[m] & 0x0000ffff );
+}
+
+/* MOV.L Rm,@(R0,Rn) */
+INLINE void MOVLS0(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->ea = sh2->r[n] + sh2->r[0];
+ WL( sh2, sh2->ea, sh2->r[m] );
+}
+
+/* MOV.B @(R0,Rm),Rn */
+INLINE void MOVBL0(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->ea = sh2->r[m] + sh2->r[0];
+ sh2->r[n] = (UINT32)(INT32)(INT16)(INT8) RB( sh2, sh2->ea );
+}
+
+/* MOV.W @(R0,Rm),Rn */
+INLINE void MOVWL0(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->ea = sh2->r[m] + sh2->r[0];
+ sh2->r[n] = (UINT32)(INT32)(INT16) RW( sh2, sh2->ea );
+}
+
+/* MOV.L @(R0,Rm),Rn */
+INLINE void MOVLL0(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->ea = sh2->r[m] + sh2->r[0];
+ sh2->r[n] = RL( sh2, sh2->ea );
+}
+
+/* MOV #imm,Rn */
+INLINE void MOVI(sh2_state *sh2, UINT32 i, UINT32 n)
+{
+ sh2->r[n] = (UINT32)(INT32)(INT16)(INT8) i;
+}
+
+/* MOV.W @(disp8,PC),Rn */
+INLINE void MOVWI(sh2_state *sh2, UINT32 d, UINT32 n)
+{
+ UINT32 disp = d & 0xff;
+ sh2->ea = sh2->pc + disp * 2 + 2;
+ sh2->r[n] = (UINT32)(INT32)(INT16) RW( sh2, sh2->ea );
+}
+
+/* MOV.L @(disp8,PC),Rn */
+INLINE void MOVLI(sh2_state *sh2, UINT32 d, UINT32 n)
+{
+ UINT32 disp = d & 0xff;
+ sh2->ea = ((sh2->pc + 2) & ~3) + disp * 4;
+ sh2->r[n] = RL( sh2, sh2->ea );
+}
+
+/* MOV.B @(disp8,GBR),R0 */
+INLINE void MOVBLG(sh2_state *sh2, UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh2->ea = sh2->gbr + disp;
+ sh2->r[0] = (UINT32)(INT32)(INT16)(INT8) RB( sh2, sh2->ea );
+}
+
+/* MOV.W @(disp8,GBR),R0 */
+INLINE void MOVWLG(sh2_state *sh2, UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh2->ea = sh2->gbr + disp * 2;
+ sh2->r[0] = (INT32)(INT16) RW( sh2, sh2->ea );
+}
+
+/* MOV.L @(disp8,GBR),R0 */
+INLINE void MOVLLG(sh2_state *sh2, UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh2->ea = sh2->gbr + disp * 4;
+ sh2->r[0] = RL( sh2, sh2->ea );
+}
+
+/* MOV.B R0,@(disp8,GBR) */
+INLINE void MOVBSG(sh2_state *sh2, UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh2->ea = sh2->gbr + disp;
+ WB( sh2, sh2->ea, sh2->r[0] & 0x000000ff );
+}
+
+/* MOV.W R0,@(disp8,GBR) */
+INLINE void MOVWSG(sh2_state *sh2, UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh2->ea = sh2->gbr + disp * 2;
+ WW( sh2, sh2->ea, sh2->r[0] & 0x0000ffff );
+}
+
+/* MOV.L R0,@(disp8,GBR) */
+INLINE void MOVLSG(sh2_state *sh2, UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh2->ea = sh2->gbr + disp * 4;
+ WL( sh2, sh2->ea, sh2->r[0] );
+}
+
+/* MOV.B R0,@(disp4,Rn) */
+INLINE void MOVBS4(sh2_state *sh2, UINT32 d, UINT32 n)
+{
+ UINT32 disp = d & 0x0f;
+ sh2->ea = sh2->r[n] + disp;
+ WB( sh2, sh2->ea, sh2->r[0] & 0x000000ff );
+}
+
+/* MOV.W R0,@(disp4,Rn) */
+INLINE void MOVWS4(sh2_state *sh2, UINT32 d, UINT32 n)
+{
+ UINT32 disp = d & 0x0f;
+ sh2->ea = sh2->r[n] + disp * 2;
+ WW( sh2, sh2->ea, sh2->r[0] & 0x0000ffff );
+}
+
+/* MOV.L Rm,@(disp4,Rn) */
+INLINE void MOVLS4(sh2_state *sh2, UINT32 m, UINT32 d, UINT32 n)
+{
+ UINT32 disp = d & 0x0f;
+ sh2->ea = sh2->r[n] + disp * 4;
+ WL( sh2, sh2->ea, sh2->r[m] );
+}
+
+/* MOV.B @(disp4,Rm),R0 */
+INLINE void MOVBL4(sh2_state *sh2, UINT32 m, UINT32 d)
+{
+ UINT32 disp = d & 0x0f;
+ sh2->ea = sh2->r[m] + disp;
+ sh2->r[0] = (UINT32)(INT32)(INT16)(INT8) RB( sh2, sh2->ea );
+}
+
+/* MOV.W @(disp4,Rm),R0 */
+INLINE void MOVWL4(sh2_state *sh2, UINT32 m, UINT32 d)
+{
+ UINT32 disp = d & 0x0f;
+ sh2->ea = sh2->r[m] + disp * 2;
+ sh2->r[0] = (UINT32)(INT32)(INT16) RW( sh2, sh2->ea );
+}
+
+/* MOV.L @(disp4,Rm),Rn */
+INLINE void MOVLL4(sh2_state *sh2, UINT32 m, UINT32 d, UINT32 n)
+{
+ UINT32 disp = d & 0x0f;
+ sh2->ea = sh2->r[m] + disp * 4;
+ sh2->r[n] = RL( sh2, sh2->ea );
+}
+
+/* MOVA @(disp8,PC),R0 */
+INLINE void MOVA(sh2_state *sh2, UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh2->ea = ((sh2->pc + 2) & ~3) + disp * 4;
+ sh2->r[0] = sh2->ea;
+}
+
+/* MOVT Rn */
+INLINE void MOVT(sh2_state *sh2, UINT32 n)
+{
+ sh2->r[n] = sh2->sr & T;
+}
+
+/* MUL.L Rm,Rn */
+INLINE void MULL(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->macl = sh2->r[n] * sh2->r[m];
+ sh2->icount--;
+}
+
+/* MULS Rm,Rn */
+INLINE void MULS(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->macl = (INT16) sh2->r[n] * (INT16) sh2->r[m];
+}
+
+/* MULU Rm,Rn */
+INLINE void MULU(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->macl = (UINT16) sh2->r[n] * (UINT16) sh2->r[m];
+}
+
+/* NEG Rm,Rn */
+INLINE void NEG(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->r[n] = 0 - sh2->r[m];
+}
+
+/* NEGC Rm,Rn */
+INLINE void NEGC(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ UINT32 temp;
+
+ temp = sh2->r[m];
+ sh2->r[n] = -temp - (sh2->sr & T);
+ if (temp || (sh2->sr & T))
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+}
+
+/* NOP */
+INLINE void NOP(void)
+{
+}
+
+/* NOT Rm,Rn */
+INLINE void NOT(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->r[n] = ~sh2->r[m];
+}
+
+/* OR Rm,Rn */
+INLINE void OR(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->r[n] |= sh2->r[m];
+}
+
+/* OR #imm,R0 */
+INLINE void ORI(sh2_state *sh2, UINT32 i)
+{
+ sh2->r[0] |= i;
+ sh2->icount -= 2;
+}
+
+/* OR.B #imm,@(R0,GBR) */
+INLINE void ORM(sh2_state *sh2, UINT32 i)
+{
+ UINT32 temp;
+
+ sh2->ea = sh2->gbr + sh2->r[0];
+ temp = RB( sh2, sh2->ea );
+ temp |= i;
+ WB( sh2, sh2->ea, temp );
+}
+
+/* ROTCL Rn */
+INLINE void ROTCL(sh2_state *sh2, UINT32 n)
+{
+ UINT32 temp;
+
+ temp = (sh2->r[n] >> 31) & T;
+ sh2->r[n] = (sh2->r[n] << 1) | (sh2->sr & T);
+ sh2->sr = (sh2->sr & ~T) | temp;
+}
+
+/* ROTCR Rn */
+INLINE void ROTCR(sh2_state *sh2, UINT32 n)
+{
+ UINT32 temp;
+ temp = (sh2->sr & T) << 31;
+ if (sh2->r[n] & T)
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+ sh2->r[n] = (sh2->r[n] >> 1) | temp;
+}
+
+/* ROTL Rn */
+INLINE void ROTL(sh2_state *sh2, UINT32 n)
+{
+ sh2->sr = (sh2->sr & ~T) | ((sh2->r[n] >> 31) & T);
+ sh2->r[n] = (sh2->r[n] << 1) | (sh2->r[n] >> 31);
+}
+
+/* ROTR Rn */
+INLINE void ROTR(sh2_state *sh2, UINT32 n)
+{
+ sh2->sr = (sh2->sr & ~T) | (sh2->r[n] & T);
+ sh2->r[n] = (sh2->r[n] >> 1) | (sh2->r[n] << 31);
+}
+
+/* RTE */
+INLINE void RTE(sh2_state *sh2)
+{
+ sh2->ea = sh2->r[15];
+ sh2->delay = sh2->pc;
+ sh2->pc = RL( sh2, sh2->ea );
+ sh2->r[15] += 4;
+ sh2->ea = sh2->r[15];
+ sh2->sr = RL( sh2, sh2->ea ) & FLAGS;
+ sh2->r[15] += 4;
+ sh2->icount -= 3;
+ sh2->test_irq = 1;
+}
+
+/* RTS */
+INLINE void RTS(sh2_state *sh2)
+{
+ sh2->delay = sh2->pc;
+ sh2->pc = sh2->ea = sh2->pr;
+ sh2->icount--;
+}
+
+/* SETT */
+INLINE void SETT(sh2_state *sh2)
+{
+ sh2->sr |= T;
+}
+
+/* SHAL Rn (same as SHLL) */
+INLINE void SHAL(sh2_state *sh2, UINT32 n)
+{
+ sh2->sr = (sh2->sr & ~T) | ((sh2->r[n] >> 31) & T);
+ sh2->r[n] <<= 1;
+}
+
+/* SHAR Rn */
+INLINE void SHAR(sh2_state *sh2, UINT32 n)
+{
+ sh2->sr = (sh2->sr & ~T) | (sh2->r[n] & T);
+ sh2->r[n] = (UINT32)((INT32)sh2->r[n] >> 1);
+}
+
+/* SHLL Rn (same as SHAL) */
+INLINE void SHLL(sh2_state *sh2, UINT32 n)
+{
+ sh2->sr = (sh2->sr & ~T) | ((sh2->r[n] >> 31) & T);
+ sh2->r[n] <<= 1;
+}
+
+/* SHLL2 Rn */
+INLINE void SHLL2(sh2_state *sh2, UINT32 n)
+{
+ sh2->r[n] <<= 2;
+}
+
+/* SHLL8 Rn */
+INLINE void SHLL8(sh2_state *sh2, UINT32 n)
+{
+ sh2->r[n] <<= 8;
+}
+
+/* SHLL16 Rn */
+INLINE void SHLL16(sh2_state *sh2, UINT32 n)
+{
+ sh2->r[n] <<= 16;
+}
+
+/* SHLR Rn */
+INLINE void SHLR(sh2_state *sh2, UINT32 n)
+{
+ sh2->sr = (sh2->sr & ~T) | (sh2->r[n] & T);
+ sh2->r[n] >>= 1;
+}
+
+/* SHLR2 Rn */
+INLINE void SHLR2(sh2_state *sh2, UINT32 n)
+{
+ sh2->r[n] >>= 2;
+}
+
+/* SHLR8 Rn */
+INLINE void SHLR8(sh2_state *sh2, UINT32 n)
+{
+ sh2->r[n] >>= 8;
+}
+
+/* SHLR16 Rn */
+INLINE void SHLR16(sh2_state *sh2, UINT32 n)
+{
+ sh2->r[n] >>= 16;
+}
+
+/* SLEEP */
+INLINE void SLEEP(sh2_state *sh2)
+{
+ sh2->pc -= 2;
+ sh2->icount -= 2;
+ /* Wait_for_exception; */
+}
+
+/* STC SR,Rn */
+INLINE void STCSR(sh2_state *sh2, UINT32 n)
+{
+ sh2->r[n] = sh2->sr;
+}
+
+/* STC GBR,Rn */
+INLINE void STCGBR(sh2_state *sh2, UINT32 n)
+{
+ sh2->r[n] = sh2->gbr;
+}
+
+/* STC VBR,Rn */
+INLINE void STCVBR(sh2_state *sh2, UINT32 n)
+{
+ sh2->r[n] = sh2->vbr;
+}
+
+/* STC.L SR,@-Rn */
+INLINE void STCMSR(sh2_state *sh2, UINT32 n)
+{
+ sh2->r[n] -= 4;
+ sh2->ea = sh2->r[n];
+ WL( sh2, sh2->ea, sh2->sr );
+ sh2->icount--;
+}
+
+/* STC.L GBR,@-Rn */
+INLINE void STCMGBR(sh2_state *sh2, UINT32 n)
+{
+ sh2->r[n] -= 4;
+ sh2->ea = sh2->r[n];
+ WL( sh2, sh2->ea, sh2->gbr );
+ sh2->icount--;
+}
+
+/* STC.L VBR,@-Rn */
+INLINE void STCMVBR(sh2_state *sh2, UINT32 n)
+{
+ sh2->r[n] -= 4;
+ sh2->ea = sh2->r[n];
+ WL( sh2, sh2->ea, sh2->vbr );
+ sh2->icount--;
+}
+
+/* STS MACH,Rn */
+INLINE void STSMACH(sh2_state *sh2, UINT32 n)
+{
+ sh2->r[n] = sh2->mach;
+}
+
+/* STS MACL,Rn */
+INLINE void STSMACL(sh2_state *sh2, UINT32 n)
+{
+ sh2->r[n] = sh2->macl;
+}
+
+/* STS PR,Rn */
+INLINE void STSPR(sh2_state *sh2, UINT32 n)
+{
+ sh2->r[n] = sh2->pr;
+}
+
+/* STS.L MACH,@-Rn */
+INLINE void STSMMACH(sh2_state *sh2, UINT32 n)
+{
+ sh2->r[n] -= 4;
+ sh2->ea = sh2->r[n];
+ WL( sh2, sh2->ea, sh2->mach );
+}
+
+/* STS.L MACL,@-Rn */
+INLINE void STSMMACL(sh2_state *sh2, UINT32 n)
+{
+ sh2->r[n] -= 4;
+ sh2->ea = sh2->r[n];
+ WL( sh2, sh2->ea, sh2->macl );
+}
+
+/* STS.L PR,@-Rn */
+INLINE void STSMPR(sh2_state *sh2, UINT32 n)
+{
+ sh2->r[n] -= 4;
+ sh2->ea = sh2->r[n];
+ WL( sh2, sh2->ea, sh2->pr );
+}
+
+/* SUB Rm,Rn */
+INLINE void SUB(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->r[n] -= sh2->r[m];
+}
+
+/* SUBC Rm,Rn */
+INLINE void SUBC(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ UINT32 tmp0, tmp1;
+
+ tmp1 = sh2->r[n] - sh2->r[m];
+ tmp0 = sh2->r[n];
+ sh2->r[n] = tmp1 - (sh2->sr & T);
+ if (tmp0 < tmp1)
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+ if (tmp1 < sh2->r[n])
+ sh2->sr |= T;
+}
+
+/* SUBV Rm,Rn */
+INLINE void SUBV(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ INT32 dest, src, ans;
+
+ if ((INT32) sh2->r[n] >= 0)
+ dest = 0;
+ else
+ dest = 1;
+ if ((INT32) sh2->r[m] >= 0)
+ src = 0;
+ else
+ src = 1;
+ src += dest;
+ sh2->r[n] -= sh2->r[m];
+ if ((INT32) sh2->r[n] >= 0)
+ ans = 0;
+ else
+ ans = 1;
+ ans += dest;
+ if (src == 1)
+ {
+ if (ans == 1)
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+ }
+ else
+ sh2->sr &= ~T;
+}
+
+/* SWAP.B Rm,Rn */
+INLINE void SWAPB(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ UINT32 temp0, temp1;
+
+ temp0 = sh2->r[m] & 0xffff0000;
+ temp1 = (sh2->r[m] & 0x000000ff) << 8;
+ sh2->r[n] = (sh2->r[m] >> 8) & 0x000000ff;
+ sh2->r[n] = sh2->r[n] | temp1 | temp0;
+}
+
+/* SWAP.W Rm,Rn */
+INLINE void SWAPW(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ UINT32 temp;
+
+ temp = (sh2->r[m] >> 16) & 0x0000ffff;
+ sh2->r[n] = (sh2->r[m] << 16) | temp;
+}
+
+/* TAS.B @Rn */
+INLINE void TAS(sh2_state *sh2, UINT32 n)
+{
+ UINT32 temp;
+ sh2->ea = sh2->r[n];
+ /* Bus Lock enable */
+ temp = RB( sh2, sh2->ea );
+ if (temp == 0)
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+ temp |= 0x80;
+ /* Bus Lock disable */
+ WB( sh2, sh2->ea, temp );
+ sh2->icount -= 3;
+}
+
+/* TRAPA #imm */
+INLINE void TRAPA(sh2_state *sh2, UINT32 i)
+{
+ UINT32 imm = i & 0xff;
+
+ sh2->ea = sh2->vbr + imm * 4;
+
+ sh2->r[15] -= 4;
+ WL( sh2, sh2->r[15], sh2->sr );
+ sh2->r[15] -= 4;
+ WL( sh2, sh2->r[15], sh2->pc );
+
+ sh2->pc = RL( sh2, sh2->ea );
+
+ sh2->icount -= 7;
+}
+
+/* TST Rm,Rn */
+INLINE void TST(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ if ((sh2->r[n] & sh2->r[m]) == 0)
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+}
+
+/* TST #imm,R0 */
+INLINE void TSTI(sh2_state *sh2, UINT32 i)
+{
+ UINT32 imm = i & 0xff;
+
+ if ((imm & sh2->r[0]) == 0)
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+}
+
+/* TST.B #imm,@(R0,GBR) */
+INLINE void TSTM(sh2_state *sh2, UINT32 i)
+{
+ UINT32 imm = i & 0xff;
+
+ sh2->ea = sh2->gbr + sh2->r[0];
+ if ((imm & RB( sh2, sh2->ea )) == 0)
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+ sh2->icount -= 2;
+}
+
+/* XOR Rm,Rn */
+INLINE void XOR(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ sh2->r[n] ^= sh2->r[m];
+}
+
+/* XOR #imm,R0 */
+INLINE void XORI(sh2_state *sh2, UINT32 i)
+{
+ UINT32 imm = i & 0xff;
+ sh2->r[0] ^= imm;
+}
+
+/* XOR.B #imm,@(R0,GBR) */
+INLINE void XORM(sh2_state *sh2, UINT32 i)
+{
+ UINT32 imm = i & 0xff;
+ UINT32 temp;
+
+ sh2->ea = sh2->gbr + sh2->r[0];
+ temp = RB( sh2, sh2->ea );
+ temp ^= imm;
+ WB( sh2, sh2->ea, temp );
+ sh2->icount -= 2;
+}
+
+/* XTRCT Rm,Rn */
+INLINE void XTRCT(sh2_state *sh2, UINT32 m, UINT32 n)
+{
+ UINT32 temp;
+
+ temp = (sh2->r[m] << 16) & 0xffff0000;
+ sh2->r[n] = (sh2->r[n] >> 16) & 0x0000ffff;
+ sh2->r[n] |= temp;
+}
+
+/*****************************************************************************
+ * OPCODE DISPATCHERS
+ *****************************************************************************/
+
+INLINE void op0000(sh2_state *sh2, UINT16 opcode)
+{
+ switch (opcode & 0x3F)
+ {
+ case 0x00: NOP(); break;
+ case 0x01: NOP(); break;
+ case 0x02: STCSR(sh2, Rn); break;
+ case 0x03: BSRF(sh2, Rn); break;
+ case 0x04: MOVBS0(sh2, Rm, Rn); break;
+ case 0x05: MOVWS0(sh2, Rm, Rn); break;
+ case 0x06: MOVLS0(sh2, Rm, Rn); break;
+ case 0x07: MULL(sh2, Rm, Rn); break;
+ case 0x08: CLRT(sh2); break;
+ case 0x09: NOP(); break;
+ case 0x0a: STSMACH(sh2, Rn); break;
+ case 0x0b: RTS(sh2); break;
+ case 0x0c: MOVBL0(sh2, Rm, Rn); break;
+ case 0x0d: MOVWL0(sh2, Rm, Rn); break;
+ case 0x0e: MOVLL0(sh2, Rm, Rn); break;
+ case 0x0f: MAC_L(sh2, Rm, Rn); break;
+
+ case 0x10: NOP(); break;
+ case 0x11: NOP(); break;
+ case 0x12: STCGBR(sh2, Rn); break;
+ case 0x13: NOP(); break;
+ case 0x14: MOVBS0(sh2, Rm, Rn); break;
+ case 0x15: MOVWS0(sh2, Rm, Rn); break;
+ case 0x16: MOVLS0(sh2, Rm, Rn); break;
+ case 0x17: MULL(sh2, Rm, Rn); break;
+ case 0x18: SETT(sh2); break;
+ case 0x19: DIV0U(sh2); break;
+ case 0x1a: STSMACL(sh2, Rn); break;
+ case 0x1b: SLEEP(sh2); break;
+ case 0x1c: MOVBL0(sh2, Rm, Rn); break;
+ case 0x1d: MOVWL0(sh2, Rm, Rn); break;
+ case 0x1e: MOVLL0(sh2, Rm, Rn); break;
+ case 0x1f: MAC_L(sh2, Rm, Rn); break;
+
+ case 0x20: NOP(); break;
+ case 0x21: NOP(); break;
+ case 0x22: STCVBR(sh2, Rn); break;
+ case 0x23: BRAF(sh2, Rn); break;
+ case 0x24: MOVBS0(sh2, Rm, Rn); break;
+ case 0x25: MOVWS0(sh2, Rm, Rn); break;
+ case 0x26: MOVLS0(sh2, Rm, Rn); break;
+ case 0x27: MULL(sh2, Rm, Rn); break;
+ case 0x28: CLRMAC(sh2); break;
+ case 0x29: MOVT(sh2, Rn); break;
+ case 0x2a: STSPR(sh2, Rn); break;
+ case 0x2b: RTE(sh2); break;
+ case 0x2c: MOVBL0(sh2, Rm, Rn); break;
+ case 0x2d: MOVWL0(sh2, Rm, Rn); break;
+ case 0x2e: MOVLL0(sh2, Rm, Rn); break;
+ case 0x2f: MAC_L(sh2, Rm, Rn); break;
+
+ case 0x30: NOP(); break;
+ case 0x31: NOP(); break;
+ case 0x32: NOP(); break;
+ case 0x33: NOP(); break;
+ case 0x34: MOVBS0(sh2, Rm, Rn); break;
+ case 0x35: MOVWS0(sh2, Rm, Rn); break;
+ case 0x36: MOVLS0(sh2, Rm, Rn); break;
+ case 0x37: MULL(sh2, Rm, Rn); break;
+ case 0x38: NOP(); break;
+ case 0x39: NOP(); break;
+ case 0x3c: MOVBL0(sh2, Rm, Rn); break;
+ case 0x3d: MOVWL0(sh2, Rm, Rn); break;
+ case 0x3e: MOVLL0(sh2, Rm, Rn); break;
+ case 0x3f: MAC_L(sh2, Rm, Rn); break;
+ case 0x3a: NOP(); break;
+ case 0x3b: NOP(); break;
+
+
+
+ }
+}
+
+INLINE void op0001(sh2_state *sh2, UINT16 opcode)
+{
+ MOVLS4(sh2, Rm, opcode & 0x0f, Rn);
+}
+
+INLINE void op0010(sh2_state *sh2, UINT16 opcode)
+{
+ switch (opcode & 15)
+ {
+ case 0: MOVBS(sh2, Rm, Rn); break;
+ case 1: MOVWS(sh2, Rm, Rn); break;
+ case 2: MOVLS(sh2, Rm, Rn); break;
+ case 3: NOP(); break;
+ case 4: MOVBM(sh2, Rm, Rn); break;
+ case 5: MOVWM(sh2, Rm, Rn); break;
+ case 6: MOVLM(sh2, Rm, Rn); break;
+ case 7: DIV0S(sh2, Rm, Rn); break;
+ case 8: TST(sh2, Rm, Rn); break;
+ case 9: AND(sh2, Rm, Rn); break;
+ case 10: XOR(sh2, Rm, Rn); break;
+ case 11: OR(sh2, Rm, Rn); break;
+ case 12: CMPSTR(sh2, Rm, Rn); break;
+ case 13: XTRCT(sh2, Rm, Rn); break;
+ case 14: MULU(sh2, Rm, Rn); break;
+ case 15: MULS(sh2, Rm, Rn); break;
+ }
+}
+
+INLINE void op0011(sh2_state *sh2, UINT16 opcode)
+{
+ switch (opcode & 15)
+ {
+ case 0: CMPEQ(sh2, Rm, Rn); break;
+ case 1: NOP(); break;
+ case 2: CMPHS(sh2, Rm, Rn); break;
+ case 3: CMPGE(sh2, Rm, Rn); break;
+ case 4: DIV1(sh2, Rm, Rn); break;
+ case 5: DMULU(sh2, Rm, Rn); break;
+ case 6: CMPHI(sh2, Rm, Rn); break;
+ case 7: CMPGT(sh2, Rm, Rn); break;
+ case 8: SUB(sh2, Rm, Rn); break;
+ case 9: NOP(); break;
+ case 10: SUBC(sh2, Rm, Rn); break;
+ case 11: SUBV(sh2, Rm, Rn); break;
+ case 12: ADD(sh2, Rm, Rn); break;
+ case 13: DMULS(sh2, Rm, Rn); break;
+ case 14: ADDC(sh2, Rm, Rn); break;
+ case 15: ADDV(sh2, Rm, Rn); break;
+ }
+}
+
+INLINE void op0100(sh2_state *sh2, UINT16 opcode)
+{
+ switch (opcode & 0x3F)
+ {
+ case 0x00: SHLL(sh2, Rn); break;
+ case 0x01: SHLR(sh2, Rn); break;
+ case 0x02: STSMMACH(sh2, Rn); break;
+ case 0x03: STCMSR(sh2, Rn); break;
+ case 0x04: ROTL(sh2, Rn); break;
+ case 0x05: ROTR(sh2, Rn); break;
+ case 0x06: LDSMMACH(sh2, Rn); break;
+ case 0x07: LDCMSR(sh2, Rn); break;
+ case 0x08: SHLL2(sh2, Rn); break;
+ case 0x09: SHLR2(sh2, Rn); break;
+ case 0x0a: LDSMACH(sh2, Rn); break;
+ case 0x0b: JSR(sh2, Rn); break;
+ case 0x0c: NOP(); break;
+ case 0x0d: NOP(); break;
+ case 0x0e: LDCSR(sh2, Rn); break;
+ case 0x0f: MAC_W(sh2, Rm, Rn); break;
+
+ case 0x10: DT(sh2, Rn); break;
+ case 0x11: CMPPZ(sh2, Rn); break;
+ case 0x12: STSMMACL(sh2, Rn); break;
+ case 0x13: STCMGBR(sh2, Rn); break;
+ case 0x14: NOP(); break;
+ case 0x15: CMPPL(sh2, Rn); break;
+ case 0x16: LDSMMACL(sh2, Rn); break;
+ case 0x17: LDCMGBR(sh2, Rn); break;
+ case 0x18: SHLL8(sh2, Rn); break;
+ case 0x19: SHLR8(sh2, Rn); break;
+ case 0x1a: LDSMACL(sh2, Rn); break;
+ case 0x1b: TAS(sh2, Rn); break;
+ case 0x1c: NOP(); break;
+ case 0x1d: NOP(); break;
+ case 0x1e: LDCGBR(sh2, Rn); break;
+ case 0x1f: MAC_W(sh2, Rm, Rn); break;
+
+ case 0x20: SHAL(sh2, Rn); break;
+ case 0x21: SHAR(sh2, Rn); break;
+ case 0x22: STSMPR(sh2, Rn); break;
+ case 0x23: STCMVBR(sh2, Rn); break;
+ case 0x24: ROTCL(sh2, Rn); break;
+ case 0x25: ROTCR(sh2, Rn); break;
+ case 0x26: LDSMPR(sh2, Rn); break;
+ case 0x27: LDCMVBR(sh2, Rn); break;
+ case 0x28: SHLL16(sh2, Rn); break;
+ case 0x29: SHLR16(sh2, Rn); break;
+ case 0x2a: LDSPR(sh2, Rn); break;
+ case 0x2b: JMP(sh2, Rn); break;
+ case 0x2c: NOP(); break;
+ case 0x2d: NOP(); break;
+ case 0x2e: LDCVBR(sh2, Rn); break;
+ case 0x2f: MAC_W(sh2, Rm, Rn); break;
+
+ case 0x30: NOP(); break;
+ case 0x31: NOP(); break;
+ case 0x32: NOP(); break;
+ case 0x33: NOP(); break;
+ case 0x34: NOP(); break;
+ case 0x35: NOP(); break;
+ case 0x36: NOP(); break;
+ case 0x37: NOP(); break;
+ case 0x38: NOP(); break;
+ case 0x39: NOP(); break;
+ case 0x3a: NOP(); break;
+ case 0x3b: NOP(); break;
+ case 0x3c: NOP(); break;
+ case 0x3d: NOP(); break;
+ case 0x3e: NOP(); break;
+ case 0x3f: MAC_W(sh2, Rm, Rn); break;
+
+ }
+}
+
+INLINE void op0101(sh2_state *sh2, UINT16 opcode)
+{
+ MOVLL4(sh2, Rm, opcode & 0x0f, Rn);
+}
+
+INLINE void op0110(sh2_state *sh2, UINT16 opcode)
+{
+ switch (opcode & 15)
+ {
+ case 0: MOVBL(sh2, Rm, Rn); break;
+ case 1: MOVWL(sh2, Rm, Rn); break;
+ case 2: MOVLL(sh2, Rm, Rn); break;
+ case 3: MOV(sh2, Rm, Rn); break;
+ case 4: MOVBP(sh2, Rm, Rn); break;
+ case 5: MOVWP(sh2, Rm, Rn); break;
+ case 6: MOVLP(sh2, Rm, Rn); break;
+ case 7: NOT(sh2, Rm, Rn); break;
+ case 8: SWAPB(sh2, Rm, Rn); break;
+ case 9: SWAPW(sh2, Rm, Rn); break;
+ case 10: NEGC(sh2, Rm, Rn); break;
+ case 11: NEG(sh2, Rm, Rn); break;
+ case 12: EXTUB(sh2, Rm, Rn); break;
+ case 13: EXTUW(sh2, Rm, Rn); break;
+ case 14: EXTSB(sh2, Rm, Rn); break;
+ case 15: EXTSW(sh2, Rm, Rn); break;
+ }
+}
+
+INLINE void op0111(sh2_state *sh2, UINT16 opcode)
+{
+ ADDI(sh2, opcode & 0xff, Rn);
+}
+
+INLINE void op1000(sh2_state *sh2, UINT16 opcode)
+{
+ switch ( opcode & (15<<8) )
+ {
+ case 0 << 8: MOVBS4(sh2, opcode & 0x0f, Rm); break;
+ case 1 << 8: MOVWS4(sh2, opcode & 0x0f, Rm); break;
+ case 2<< 8: NOP(); break;
+ case 3<< 8: NOP(); break;
+ case 4<< 8: MOVBL4(sh2, Rm, opcode & 0x0f); break;
+ case 5<< 8: MOVWL4(sh2, Rm, opcode & 0x0f); break;
+ case 6<< 8: NOP(); break;
+ case 7<< 8: NOP(); break;
+ case 8<< 8: CMPIM(sh2, opcode & 0xff); break;
+ case 9<< 8: BT(sh2, opcode & 0xff); break;
+ case 10<< 8: NOP(); break;
+ case 11<< 8: BF(sh2, opcode & 0xff); break;
+ case 12<< 8: NOP(); break;
+ case 13<< 8: BTS(sh2, opcode & 0xff); break;
+ case 14<< 8: NOP(); break;
+ case 15<< 8: BFS(sh2, opcode & 0xff); break;
+ }
+}
+
+
+INLINE void op1001(sh2_state *sh2, UINT16 opcode)
+{
+ MOVWI(sh2, opcode & 0xff, Rn);
+}
+
+INLINE void op1010(sh2_state *sh2, UINT16 opcode)
+{
+ BRA(sh2, opcode & 0xfff);
+}
+
+INLINE void op1011(sh2_state *sh2, UINT16 opcode)
+{
+ BSR(sh2, opcode & 0xfff);
+}
+
+INLINE void op1100(sh2_state *sh2, UINT16 opcode)
+{
+ switch (opcode & (15<<8))
+ {
+ case 0<<8: MOVBSG(sh2, opcode & 0xff); break;
+ case 1<<8: MOVWSG(sh2, opcode & 0xff); break;
+ case 2<<8: MOVLSG(sh2, opcode & 0xff); break;
+ case 3<<8: TRAPA(sh2, opcode & 0xff); break;
+ case 4<<8: MOVBLG(sh2, opcode & 0xff); break;
+ case 5<<8: MOVWLG(sh2, opcode & 0xff); break;
+ case 6<<8: MOVLLG(sh2, opcode & 0xff); break;
+ case 7<<8: MOVA(sh2, opcode & 0xff); break;
+ case 8<<8: TSTI(sh2, opcode & 0xff); break;
+ case 9<<8: ANDI(sh2, opcode & 0xff); break;
+ case 10<<8: XORI(sh2, opcode & 0xff); break;
+ case 11<<8: ORI(sh2, opcode & 0xff); break;
+ case 12<<8: TSTM(sh2, opcode & 0xff); break;
+ case 13<<8: ANDM(sh2, opcode & 0xff); break;
+ case 14<<8: XORM(sh2, opcode & 0xff); break;
+ case 15<<8: ORM(sh2, opcode & 0xff); break;
+ }
+}
+
+INLINE void op1101(sh2_state *sh2, UINT16 opcode)
+{
+ MOVLI(sh2, opcode & 0xff, Rn);
+}
+
+INLINE void op1110(sh2_state *sh2, UINT16 opcode)
+{
+ MOVI(sh2, opcode & 0xff, Rn);
+}
+
+INLINE void op1111(sh2_state *sh2, UINT16 opcode)
+{
+ NOP();
+}
+
+/*****************************************************************************
+ * MAME CPU INTERFACE
+ *****************************************************************************/
+
+static CPU_RESET( sh2 )
+{
+ sh2_state *sh2 = get_safe_token(device);
+ emu_timer *tsave, *tsaved0, *tsaved1;
+ UINT32 *m;
+ int (*dma_callback_kludge)(device_t *device, UINT32 src, UINT32 dst, UINT32 data, int size);
+ int (*dma_callback_fifo_data_available)(device_t *device, UINT32 src, UINT32 dst, UINT32 data, int size);
+ int save_is_slave;
+
+ void (*f)(UINT32 data);
+ device_irq_callback save_irqcallback;
+
+ m = sh2->m;
+ tsave = sh2->timer;
+ tsaved0 = sh2->dma_current_active_timer[0];
+ tsaved1 = sh2->dma_current_active_timer[1];
+
+ f = sh2->ftcsr_read_callback;
+ save_irqcallback = sh2->irq_callback;
+ save_is_slave = sh2->is_slave;
+ dma_callback_kludge = sh2->dma_callback_kludge;
+ dma_callback_fifo_data_available = sh2->dma_callback_fifo_data_available;
+
+ sh2->ppc = sh2->pc = sh2->pr = sh2->sr = sh2->gbr = sh2->vbr = sh2->mach = sh2->macl = 0;
+ sh2->evec = sh2->irqsr = 0;
+ memset(&sh2->r[0], 0, sizeof(sh2->r[0])*16);
+ sh2->ea = sh2->delay = sh2->cpu_off = sh2->dvsr = sh2->dvdnth = sh2->dvdntl = sh2->dvcr = 0;
+ sh2->pending_irq = sh2->test_irq = 0;
+ memset(&sh2->irq_queue[0], 0, sizeof(sh2->irq_queue[0])*16);
+ memset(&sh2->irq_line_state[0], 0, sizeof(sh2->irq_line_state[0])*17);
+ sh2->frc = sh2->ocra = sh2->ocrb = sh2->icr = 0;
+ sh2->frc_base = 0;
+ sh2->frt_input = sh2->internal_irq_level = sh2->internal_irq_vector = 0;
+ sh2->dma_timer_active[0] = sh2->dma_timer_active[1] = 0;
+
+ sh2->dma_callback_kludge = dma_callback_kludge;
+ sh2->dma_callback_fifo_data_available = dma_callback_fifo_data_available;
+ sh2->is_slave = save_is_slave;
+ sh2->ftcsr_read_callback = f;
+ sh2->irq_callback = save_irqcallback;
+ sh2->device = device;
+
+ sh2->timer = tsave;
+ sh2->dma_current_active_timer[0] = tsaved0;
+ sh2->dma_current_active_timer[1] = tsaved1;
+ sh2->m = m;
+ memset(sh2->m, 0, 0x200);
+
+ sh2->pc = RL(sh2, 0);
+ sh2->r[15] = RL(sh2, 4);
+ sh2->sr = I;
+
+ sh2->internal_irq_level = -1;
+}
+
+/*-------------------------------------------------
+ sh1_reset - reset the processor
+-------------------------------------------------*/
+
+static CPU_RESET( sh1 )
+{
+ sh2_state *sh2 = get_safe_token(device);
+ CPU_RESET_CALL( sh2 );
+ sh2->cpu_type = CPU_TYPE_SH1;
+}
+
+/* Execute cycles - returns number of cycles actually run */
+static CPU_EXECUTE( sh2 )
+{
+ sh2_state *sh2 = get_safe_token(device);
+
+ if (sh2->cpu_off)
+ {
+ sh2->icount = 0;
+ return;
+ }
+
+ // run any active DMAs now
+#ifndef USE_TIMER_FOR_DMA
+ for ( int i = 0; i < sh2->icount ; i++)
+ {
+ for( int dma=0;dma<1;dma++)
+ {
+ if (sh2->dma_timer_active[dma])
+ sh2_do_dma(sh2, dma);
+ }
+ }
+#endif
+
+ do
+ {
+ UINT32 opcode;
+
+ if (sh2->delay)
+ {
+ opcode = sh2->program->read_word(((UINT32)(sh2->delay & AM)));
+ sh2->pc -= 2;
+ }
+ else
+ opcode = sh2->program->read_word(((UINT32)(sh2->pc & AM)));
+
+ debugger_instruction_hook(device, sh2->pc);
+
+ sh2->delay = 0;
+ sh2->pc += 2;
+ sh2->ppc = sh2->pc;
+
+ switch (opcode & ( 15 << 12))
+ {
+ case 0<<12: op0000(sh2, opcode); break;
+ case 1<<12: op0001(sh2, opcode); break;
+ case 2<<12: op0010(sh2, opcode); break;
+ case 3<<12: op0011(sh2, opcode); break;
+ case 4<<12: op0100(sh2, opcode); break;
+ case 5<<12: op0101(sh2, opcode); break;
+ case 6<<12: op0110(sh2, opcode); break;
+ case 7<<12: op0111(sh2, opcode); break;
+ case 8<<12: op1000(sh2, opcode); break;
+ case 9<<12: op1001(sh2, opcode); break;
+ case 10<<12: op1010(sh2, opcode); break;
+ case 11<<12: op1011(sh2, opcode); break;
+ case 12<<12: op1100(sh2, opcode); break;
+ case 13<<12: op1101(sh2, opcode); break;
+ case 14<<12: op1110(sh2, opcode); break;
+ default: op1111(sh2, opcode); break;
+ }
+
+ if(sh2->test_irq && !sh2->delay)
+ {
+ CHECK_PENDING_IRQ("mame_sh2_execute");
+ sh2->test_irq = 0;
+ }
+ sh2->icount--;
+ } while( sh2->icount > 0 );
+}
+
+static CPU_INIT( sh2 )
+{
+ sh2_state *sh2 = get_safe_token(device);
+
+ /* initialize the common core parts */
+ sh2_common_init(sh2, device, irqcallback);
+}
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( sh2 )
+{
+ sh2_state *sh2 = get_safe_token(device);
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_VBLIN: sh2_set_irq_line(sh2, SH2_INT_VBLIN, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_VBLOUT: sh2_set_irq_line(sh2, SH2_INT_VBLOUT, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_HBLIN: sh2_set_irq_line(sh2, SH2_INT_HBLIN, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_TIMER0: sh2_set_irq_line(sh2, SH2_INT_TIMER0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_TIMER1: sh2_set_irq_line(sh2, SH2_INT_TIMER1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DSP: sh2_set_irq_line(sh2, SH2_INT_DSP, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_SOUND: sh2_set_irq_line(sh2, SH2_INT_SOUND, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_SMPC: sh2_set_irq_line(sh2, SH2_INT_SMPC, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_PAD: sh2_set_irq_line(sh2, SH2_INT_PAD, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA2: sh2_set_irq_line(sh2, SH2_INT_DMA2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA1: sh2_set_irq_line(sh2, SH2_INT_DMA1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA0: sh2_set_irq_line(sh2, SH2_INT_DMA0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DMAILL: sh2_set_irq_line(sh2, SH2_INT_DMAILL, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_SPRITE: sh2_set_irq_line(sh2, SH2_INT_SPRITE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_14: sh2_set_irq_line(sh2, SH2_INT_14, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_15: sh2_set_irq_line(sh2, SH2_INT_15, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_ABUS: sh2_set_irq_line(sh2, SH2_INT_ABUS, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: sh2_set_irq_line(sh2, INPUT_LINE_NMI, info->i); break;
+
+ case CPUINFO_INT_REGISTER + SH2_PC:
+ case CPUINFO_INT_PC: sh2->pc = info->i; sh2->delay = 0; break;
+ case CPUINFO_INT_SP: sh2->r[15] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_PR: sh2->pr = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_SR: sh2->sr = info->i; CHECK_PENDING_IRQ("sh2_set_reg"); break;
+ case CPUINFO_INT_REGISTER + SH2_GBR: sh2->gbr = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_VBR: sh2->vbr = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_MACH: sh2->mach = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_MACL: sh2->macl = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R0: sh2->r[ 0] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R1: sh2->r[ 1] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R2: sh2->r[ 2] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R3: sh2->r[ 3] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R4: sh2->r[ 4] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R5: sh2->r[ 5] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R6: sh2->r[ 6] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R7: sh2->r[ 7] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R8: sh2->r[ 8] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R9: sh2->r[ 9] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R10: sh2->r[10] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R11: sh2->r[11] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R12: sh2->r[12] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R13: sh2->r[13] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R14: sh2->r[14] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R15: sh2->r[15] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_EA: sh2->ea = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( sh2 )
+{
+ sh2_state *sh2 = (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(sh2_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; 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 = 2; 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 = 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 + SH2_INT_VBLIN: info->i = sh2->irq_line_state[SH2_INT_VBLIN]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_VBLOUT: info->i = sh2->irq_line_state[SH2_INT_VBLOUT]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_HBLIN: info->i = sh2->irq_line_state[SH2_INT_HBLIN]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_TIMER0: info->i = sh2->irq_line_state[SH2_INT_TIMER0]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_TIMER1: info->i = sh2->irq_line_state[SH2_INT_TIMER1]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DSP: info->i = sh2->irq_line_state[SH2_INT_DSP]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_SOUND: info->i = sh2->irq_line_state[SH2_INT_SOUND]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_SMPC: info->i = sh2->irq_line_state[SH2_INT_SMPC]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_PAD: info->i = sh2->irq_line_state[SH2_INT_PAD]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA2: info->i = sh2->irq_line_state[SH2_INT_DMA2]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA1: info->i = sh2->irq_line_state[SH2_INT_DMA1]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA0: info->i = sh2->irq_line_state[SH2_INT_DMA0]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DMAILL: info->i = sh2->irq_line_state[SH2_INT_DMAILL]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_SPRITE: info->i = sh2->irq_line_state[SH2_INT_SPRITE]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_14: info->i = sh2->irq_line_state[SH2_INT_14]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_15: info->i = sh2->irq_line_state[SH2_INT_15]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_ABUS: info->i = sh2->irq_line_state[SH2_INT_ABUS]; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = sh2->nmi_line_state; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = sh2->ppc; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + SH2_PC: info->i = (sh2->delay) ? (sh2->delay & AM) : (sh2->pc & AM); break;
+ case CPUINFO_INT_SP: info->i = sh2->r[15]; break;
+ case CPUINFO_INT_REGISTER + SH2_PR: info->i = sh2->pr; break;
+ case CPUINFO_INT_REGISTER + SH2_SR: info->i = sh2->sr; break;
+ case CPUINFO_INT_REGISTER + SH2_GBR: info->i = sh2->gbr; break;
+ case CPUINFO_INT_REGISTER + SH2_VBR: info->i = sh2->vbr; break;
+ case CPUINFO_INT_REGISTER + SH2_MACH: info->i = sh2->mach; break;
+ case CPUINFO_INT_REGISTER + SH2_MACL: info->i = sh2->macl; break;
+ case CPUINFO_INT_REGISTER + SH2_R0: info->i = sh2->r[ 0]; break;
+ case CPUINFO_INT_REGISTER + SH2_R1: info->i = sh2->r[ 1]; break;
+ case CPUINFO_INT_REGISTER + SH2_R2: info->i = sh2->r[ 2]; break;
+ case CPUINFO_INT_REGISTER + SH2_R3: info->i = sh2->r[ 3]; break;
+ case CPUINFO_INT_REGISTER + SH2_R4: info->i = sh2->r[ 4]; break;
+ case CPUINFO_INT_REGISTER + SH2_R5: info->i = sh2->r[ 5]; break;
+ case CPUINFO_INT_REGISTER + SH2_R6: info->i = sh2->r[ 6]; break;
+ case CPUINFO_INT_REGISTER + SH2_R7: info->i = sh2->r[ 7]; break;
+ case CPUINFO_INT_REGISTER + SH2_R8: info->i = sh2->r[ 8]; break;
+ case CPUINFO_INT_REGISTER + SH2_R9: info->i = sh2->r[ 9]; break;
+ case CPUINFO_INT_REGISTER + SH2_R10: info->i = sh2->r[10]; break;
+ case CPUINFO_INT_REGISTER + SH2_R11: info->i = sh2->r[11]; break;
+ case CPUINFO_INT_REGISTER + SH2_R12: info->i = sh2->r[12]; break;
+ case CPUINFO_INT_REGISTER + SH2_R13: info->i = sh2->r[13]; break;
+ case CPUINFO_INT_REGISTER + SH2_R14: info->i = sh2->r[14]; break;
+ case CPUINFO_INT_REGISTER + SH2_R15: info->i = sh2->r[15]; break;
+ case CPUINFO_INT_REGISTER + SH2_EA: info->i = sh2->ea; 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(sh2); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(sh2); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(sh2); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(sh2); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(sh2); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &sh2->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "SH-2"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Hitachi SH7600"); 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 Juergen Buchmueller, all rights reserved."); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%d%c%c",
+ sh2->sr & M ? 'M':'.',
+ sh2->sr & Q ? 'Q':'.',
+ (sh2->sr & I) >> 4,
+ sh2->sr & S ? 'S':'.',
+ sh2->sr & T ? 'T':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + SH2_PC: sprintf(info->s, "PC :%08X", sh2->pc); break;
+ case CPUINFO_STR_REGISTER + SH2_SR: sprintf(info->s, "SR :%08X", sh2->sr); break;
+ case CPUINFO_STR_REGISTER + SH2_PR: sprintf(info->s, "PR :%08X", sh2->pr); break;
+ case CPUINFO_STR_REGISTER + SH2_GBR: sprintf(info->s, "GBR :%08X", sh2->gbr); break;
+ case CPUINFO_STR_REGISTER + SH2_VBR: sprintf(info->s, "VBR :%08X", sh2->vbr); break;
+ case CPUINFO_STR_REGISTER + SH2_MACH: sprintf(info->s, "MACH:%08X", sh2->mach); break;
+ case CPUINFO_STR_REGISTER + SH2_MACL: sprintf(info->s, "MACL:%08X", sh2->macl); break;
+ case CPUINFO_STR_REGISTER + SH2_R0: sprintf(info->s, "R0 :%08X", sh2->r[ 0]); break;
+ case CPUINFO_STR_REGISTER + SH2_R1: sprintf(info->s, "R1 :%08X", sh2->r[ 1]); break;
+ case CPUINFO_STR_REGISTER + SH2_R2: sprintf(info->s, "R2 :%08X", sh2->r[ 2]); break;
+ case CPUINFO_STR_REGISTER + SH2_R3: sprintf(info->s, "R3 :%08X", sh2->r[ 3]); break;
+ case CPUINFO_STR_REGISTER + SH2_R4: sprintf(info->s, "R4 :%08X", sh2->r[ 4]); break;
+ case CPUINFO_STR_REGISTER + SH2_R5: sprintf(info->s, "R5 :%08X", sh2->r[ 5]); break;
+ case CPUINFO_STR_REGISTER + SH2_R6: sprintf(info->s, "R6 :%08X", sh2->r[ 6]); break;
+ case CPUINFO_STR_REGISTER + SH2_R7: sprintf(info->s, "R7 :%08X", sh2->r[ 7]); break;
+ case CPUINFO_STR_REGISTER + SH2_R8: sprintf(info->s, "R8 :%08X", sh2->r[ 8]); break;
+ case CPUINFO_STR_REGISTER + SH2_R9: sprintf(info->s, "R9 :%08X", sh2->r[ 9]); break;
+ case CPUINFO_STR_REGISTER + SH2_R10: sprintf(info->s, "R10 :%08X", sh2->r[10]); break;
+ case CPUINFO_STR_REGISTER + SH2_R11: sprintf(info->s, "R11 :%08X", sh2->r[11]); break;
+ case CPUINFO_STR_REGISTER + SH2_R12: sprintf(info->s, "R12 :%08X", sh2->r[12]); break;
+ case CPUINFO_STR_REGISTER + SH2_R13: sprintf(info->s, "R13 :%08X", sh2->r[13]); break;
+ case CPUINFO_STR_REGISTER + SH2_R14: sprintf(info->s, "R14 :%08X", sh2->r[14]); break;
+ case CPUINFO_STR_REGISTER + SH2_R15: sprintf(info->s, "R15 :%08X", sh2->r[15]); break;
+ case CPUINFO_STR_REGISTER + SH2_EA: sprintf(info->s, "EA :%08X", sh2->ea); break;
+
+ }
+}
+
+CPU_GET_INFO( sh1 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(sh1); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "SH-1"); break;
+
+ default: CPU_GET_INFO_CALL(sh2); break;
+ }
+}
+
+void sh2drc_set_options(device_t *device, UINT32 options)
+{
+ /* doesn't apply here */
+}
+
+void sh2drc_add_pcflush(device_t *device, offs_t address)
+{
+ /* doesn't apply here */
+}
+
+DEFINE_LEGACY_CPU_DEVICE(SH1, sh1);
+DEFINE_LEGACY_CPU_DEVICE(SH2, sh2);
+
+#endif
diff --git a/trunk/src/emu/cpu/sh2/sh2.h b/trunk/src/emu/cpu/sh2/sh2.h
new file mode 100644
index 00000000000..8ed16c75aa8
--- /dev/null
+++ b/trunk/src/emu/cpu/sh2/sh2.h
@@ -0,0 +1,91 @@
+/*****************************************************************************
+ *
+ * sh2.h
+ * Portable Hitachi SH-2 (SH7600 family) emulator interface
+ *
+ * Copyright Juergen Buchmueller <pullmoll@t-online.de>,
+ * 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 <tiraniddo@hotmail.com> C/C++ implementation of
+ * the SH-2 CPU core and was heavily changed to the MAME CPU requirements.
+ * Thanks also go to Chuck Mason <chukjr@sundail.net> and Olivier Galibert
+ * <galibert@pobox.com> for letting me peek into their SEMU code :-)
+ *
+ *****************************************************************************/
+
+#pragma once
+
+#ifndef __SH2_H__
+#define __SH2_H__
+
+
+#define SH2_INT_NONE -1
+#define SH2_INT_VBLIN 0
+#define SH2_INT_VBLOUT 1
+#define SH2_INT_HBLIN 2
+#define SH2_INT_TIMER0 3
+#define SH2_INT_TIMER1 4
+#define SH2_INT_DSP 5
+#define SH2_INT_SOUND 6
+#define SH2_INT_SMPC 7
+#define SH2_INT_PAD 8
+#define SH2_INT_DMA2 9
+#define SH2_INT_DMA1 10
+#define SH2_INT_DMA0 11
+#define SH2_INT_DMAILL 12
+#define SH2_INT_SPRITE 13
+#define SH2_INT_14 14
+#define SH2_INT_15 15
+#define SH2_INT_ABUS 16
+
+enum
+{
+ SH2_PC=1, SH2_SR, SH2_PR, SH2_GBR, SH2_VBR, SH2_MACH, SH2_MACL,
+ SH2_R0, SH2_R1, SH2_R2, SH2_R3, SH2_R4, SH2_R5, SH2_R6, SH2_R7,
+ SH2_R8, SH2_R9, SH2_R10, SH2_R11, SH2_R12, SH2_R13, SH2_R14, SH2_R15, SH2_EA
+};
+
+typedef struct _sh2_cpu_core sh2_cpu_core;
+struct _sh2_cpu_core
+{
+ int is_slave;
+ int (*dma_callback_kludge)(device_t *device, UINT32 src, UINT32 dst, UINT32 data, int size);
+ int (*dma_callback_fifo_data_available)(device_t *device, UINT32 src, UINT32 dst, UINT32 data, int size);
+};
+
+DECLARE_LEGACY_CPU_DEVICE(SH1, sh1);
+DECLARE_LEGACY_CPU_DEVICE(SH2, sh2);
+
+WRITE32_HANDLER( sh2_internal_w );
+READ32_HANDLER( sh2_internal_r );
+
+void sh2_set_ftcsr_read_callback(device_t *device, void (*callback)(UINT32));
+void sh2_set_frt_input(device_t *device, int state);
+
+/***************************************************************************
+ COMPILER-SPECIFIC OPTIONS
+***************************************************************************/
+
+#define SH2DRC_STRICT_VERIFY 0x0001 /* verify all instructions */
+#define SH2DRC_FLUSH_PC 0x0002 /* flush the PC value before each memory access */
+#define SH2DRC_STRICT_PCREL 0x0004 /* do actual loads on MOVLI/MOVWI instead of collapsing to immediates */
+
+#define SH2DRC_COMPATIBLE_OPTIONS (SH2DRC_STRICT_VERIFY | SH2DRC_FLUSH_PC | SH2DRC_STRICT_PCREL)
+#define SH2DRC_FASTEST_OPTIONS (0)
+
+void sh2drc_set_options(device_t *device, UINT32 options);
+void sh2drc_add_pcflush(device_t *device, offs_t address);
+
+#endif /* __SH2_H__ */
diff --git a/trunk/src/emu/cpu/sh2/sh2comn.c b/trunk/src/emu/cpu/sh2/sh2comn.c
new file mode 100644
index 00000000000..220a38166ae
--- /dev/null
+++ b/trunk/src/emu/cpu/sh2/sh2comn.c
@@ -0,0 +1,1011 @@
+/*****************************************************************************
+ *
+ * sh2common.c
+ *
+ * SH-2 non-specific components
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "sh2.h"
+#include "sh2comn.h"
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+#ifdef USE_SH2DRC
+#define GET_SH2(dev) *(sh2_state **)downcast<legacy_cpu_device *>(dev)->token()
+#else
+#define GET_SH2(dev) (sh2_state *)downcast<legacy_cpu_device *>(dev)->token()
+#endif
+
+
+static const int div_tab[4] = { 3, 5, 7, 0 };
+
+INLINE UINT32 RL(sh2_state *sh2, offs_t A)
+{
+ if (A >= 0xe0000000)
+ return sh2_internal_r(sh2->internal, (A & 0x1fc)>>2, 0xffffffff);
+
+ if (A >= 0xc0000000)
+ return sh2->program->read_dword(A);
+
+ if (A >= 0x40000000)
+ return 0xa5a5a5a5;
+
+ return sh2->program->read_dword(A & AM);
+}
+
+INLINE void WL(sh2_state *sh2, offs_t A, UINT32 V)
+{
+ if (A >= 0xe0000000)
+ {
+ sh2_internal_w(sh2->internal, (A & 0x1fc)>>2, V, 0xffffffff);
+ return;
+ }
+
+ if (A >= 0xc0000000)
+ {
+ sh2->program->write_dword(A,V);
+ return;
+ }
+
+ if (A >= 0x40000000)
+ return;
+
+ sh2->program->write_dword(A & AM,V);
+}
+
+static void sh2_timer_resync(sh2_state *sh2)
+{
+ int divider = div_tab[(sh2->m[5] >> 8) & 3];
+ UINT64 cur_time = sh2->device->total_cycles();
+ UINT64 add = (cur_time - sh2->frc_base) >> divider;
+
+ if (add > 0)
+ {
+ if(divider)
+ sh2->frc += add;
+
+ sh2->frc_base = cur_time;
+ }
+}
+
+static void sh2_timer_activate(sh2_state *sh2)
+{
+ int max_delta = 0xfffff;
+ UINT16 frc;
+
+ sh2->timer->adjust(attotime::never);
+
+ frc = sh2->frc;
+ if(!(sh2->m[4] & OCFA)) {
+ UINT16 delta = sh2->ocra - frc;
+ if(delta < max_delta)
+ max_delta = delta;
+ }
+
+ if(!(sh2->m[4] & OCFB) && (sh2->ocra <= sh2->ocrb || !(sh2->m[4] & 0x010000))) {
+ UINT16 delta = sh2->ocrb - frc;
+ if(delta < max_delta)
+ max_delta = delta;
+ }
+
+ if(!(sh2->m[4] & OVF) && !(sh2->m[4] & 0x010000)) {
+ int delta = 0x10000 - frc;
+ if(delta < max_delta)
+ max_delta = delta;
+ }
+
+ if(max_delta != 0xfffff) {
+ int divider = div_tab[(sh2->m[5] >> 8) & 3];
+ if(divider) {
+ max_delta <<= divider;
+ sh2->frc_base = sh2->device->total_cycles();
+ sh2->timer->adjust(sh2->device->cycles_to_attotime(max_delta));
+ } else {
+ logerror("SH2.%s: Timer event in %d cycles of external clock", sh2->device->tag(), max_delta);
+ }
+ }
+}
+
+
+static TIMER_CALLBACK( sh2_timer_callback )
+{
+ sh2_state *sh2 = (sh2_state *)ptr;
+ UINT16 frc;
+
+ sh2_timer_resync(sh2);
+
+ frc = sh2->frc;
+
+ if(frc == sh2->ocrb)
+ sh2->m[4] |= OCFB;
+
+ if(frc == 0x0000)
+ sh2->m[4] |= OVF;
+
+ if(frc == sh2->ocra)
+ {
+ sh2->m[4] |= OCFA;
+
+ if(sh2->m[4] & 0x010000)
+ sh2->frc = 0;
+ }
+
+ sh2_recalc_irq(sh2);
+ sh2_timer_activate(sh2);
+}
+
+
+/*
+ We have to do DMA on a timer (or at least, in chunks) due to the way some systems use it.
+ The 32x is a difficult case, they set the SOURCE of the DMA to a FIFO buffer, which at most
+ can have 8 words in it. Attempting to do an 'instant DMA' in this scenario is impossible
+ because the game is expecting the 68k of the system to feed data into the FIFO at the same
+ time as the SH2 is transfering it out via DMA
+
+ There are two ways we can do this
+
+ a) with a high frequency timer (more accurate, but a large performance hit)
+
+ or
+
+ b) in the CPU_EXECUTE loop
+
+
+ we're currently doing a)
+
+ b) causes problems with ST-V games
+
+*/
+
+
+
+void sh2_notify_dma_data_available(device_t *device)
+{
+ sh2_state *sh2 = GET_SH2(device);
+ //printf("call notify\n");
+
+ for (int dma=0;dma<2;dma++)
+ {
+ //printf("sh2->dma_timer_active[dma] %04x\n",sh2->dma_timer_active[dma]);
+
+ if (sh2->dma_timer_active[dma]==2) // 2 = stalled
+ {
+ // printf("resuming stalled dma\n");
+ sh2->dma_timer_active[dma]=1;
+ sh2->dma_current_active_timer[dma]->adjust(attotime::zero, dma);
+ }
+ }
+
+}
+
+void sh2_do_dma(sh2_state *sh2, int dma)
+{
+ UINT32 dmadata;
+
+ UINT32 tempsrc, tempdst;
+
+ if (sh2->active_dma_count[dma] > 0)
+ {
+
+
+ // process current DMA
+ switch(sh2->active_dma_size[dma])
+ {
+ case 0:
+ {
+ // we need to know the src / dest ahead of time without changing them
+ // to allow for the callback to check if we can process the DMA at this
+ // time (we need to know where we're reading / writing to/from)
+
+ if(sh2->active_dma_incs[dma] == 2)
+ tempsrc = sh2->active_dma_src[dma] - 1;
+ else
+ tempsrc = sh2->active_dma_src[dma];
+
+ if(sh2->active_dma_incd[dma] == 2)
+ tempdst = sh2->active_dma_dst[dma] - 1;
+ else
+ tempdst = sh2->active_dma_dst[dma];
+
+ if (sh2->dma_callback_fifo_data_available)
+ {
+ int available = sh2->dma_callback_fifo_data_available(sh2->device, tempsrc, tempdst, 0, sh2->active_dma_size[dma]);
+
+ if (!available)
+ {
+ //printf("dma stalled\n");
+ sh2->dma_timer_active[dma]=2;// mark as stalled
+ return;
+ }
+ }
+
+ #ifdef USE_TIMER_FOR_DMA
+ //schedule next DMA callback
+ sh2->dma_current_active_timer[dma]->adjust(sh2->device->cycles_to_attotime(2), dma);
+ #endif
+
+
+ dmadata = sh2->program->read_byte(tempsrc);
+ if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(sh2->device, tempsrc, tempdst, dmadata, sh2->active_dma_size[dma]);
+ sh2->program->write_byte(tempdst, dmadata);
+
+ if(sh2->active_dma_incs[dma] == 2)
+ sh2->active_dma_src[dma] --;
+ if(sh2->active_dma_incd[dma] == 2)
+ sh2->active_dma_dst[dma] --;
+
+
+ if(sh2->active_dma_incs[dma] == 1)
+ sh2->active_dma_src[dma] ++;
+ if(sh2->active_dma_incd[dma] == 1)
+ sh2->active_dma_dst[dma] ++;
+
+ sh2->active_dma_count[dma] --;
+ }
+ break;
+ case 1:
+ {
+ if(sh2->active_dma_incs[dma] == 2)
+ tempsrc = sh2->active_dma_src[dma] - 2;
+ else
+ tempsrc = sh2->active_dma_src[dma];
+
+ if(sh2->active_dma_incd[dma] == 2)
+ tempdst = sh2->active_dma_dst[dma] - 2;
+ else
+ tempdst = sh2->active_dma_dst[dma];
+
+ if (sh2->dma_callback_fifo_data_available)
+ {
+ int available = sh2->dma_callback_fifo_data_available(sh2->device, tempsrc, tempdst, 0, sh2->active_dma_size[dma]);
+
+ if (!available)
+ {
+ //printf("dma stalled\n");
+ sh2->dma_timer_active[dma]=2;// mark as stalled
+ return;
+ }
+ }
+
+ #ifdef USE_TIMER_FOR_DMA
+ //schedule next DMA callback
+ sh2->dma_current_active_timer[dma]->adjust(sh2->device->cycles_to_attotime(2), dma);
+ #endif
+
+ // check: should this really be using read_word_32 / write_word_32?
+ dmadata = sh2->program->read_word(tempsrc);
+ if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(sh2->device, tempsrc, tempdst, dmadata, sh2->active_dma_size[dma]);
+ sh2->program->write_word(tempdst, dmadata);
+
+ if(sh2->active_dma_incs[dma] == 2)
+ sh2->active_dma_src[dma] -= 2;
+ if(sh2->active_dma_incd[dma] == 2)
+ sh2->active_dma_dst[dma] -= 2;
+
+ if(sh2->active_dma_incs[dma] == 1)
+ sh2->active_dma_src[dma] += 2;
+ if(sh2->active_dma_incd[dma] == 1)
+ sh2->active_dma_dst[dma] += 2;
+
+ sh2->active_dma_count[dma] --;
+ }
+ break;
+ case 2:
+ {
+ if(sh2->active_dma_incs[dma] == 2)
+ tempsrc = sh2->active_dma_src[dma] - 4;
+ else
+ tempsrc = sh2->active_dma_src[dma];
+
+ if(sh2->active_dma_incd[dma] == 2)
+ tempdst = sh2->active_dma_dst[dma] - 4;
+ else
+ tempdst = sh2->active_dma_dst[dma];
+
+ if (sh2->dma_callback_fifo_data_available)
+ {
+ int available = sh2->dma_callback_fifo_data_available(sh2->device, tempsrc, tempdst, 0, sh2->active_dma_size[dma]);
+
+ if (!available)
+ {
+ //printf("dma stalled\n");
+ sh2->dma_timer_active[dma]=2;// mark as stalled
+ return;
+ }
+ }
+
+ #ifdef USE_TIMER_FOR_DMA
+ //schedule next DMA callback
+ sh2->dma_current_active_timer[dma]->adjust(sh2->device->cycles_to_attotime(2), dma);
+ #endif
+
+ dmadata = sh2->program->read_dword(tempsrc);
+ if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(sh2->device, tempsrc, tempdst, dmadata, sh2->active_dma_size[dma]);
+ sh2->program->write_dword(tempdst, dmadata);
+
+ if(sh2->active_dma_incs[dma] == 2)
+ sh2->active_dma_src[dma] -= 4;
+ if(sh2->active_dma_incd[dma] == 2)
+ sh2->active_dma_dst[dma] -= 4;
+
+ if(sh2->active_dma_incs[dma] == 1)
+ sh2->active_dma_src[dma] += 4;
+ if(sh2->active_dma_incd[dma] == 1)
+ sh2->active_dma_dst[dma] += 4;
+
+ sh2->active_dma_count[dma] --;
+ }
+ break;
+ case 3:
+ {
+ // shouldn't this really be 4 calls here instead?
+
+ tempsrc = sh2->active_dma_src[dma];
+
+ if(sh2->active_dma_incd[dma] == 2)
+ tempdst = sh2->active_dma_dst[dma] - 16;
+ else
+ tempdst = sh2->active_dma_dst[dma];
+
+ if (sh2->dma_callback_fifo_data_available)
+ {
+ int available = sh2->dma_callback_fifo_data_available(sh2->device, tempsrc, tempdst, 0, sh2->active_dma_size[dma]);
+
+ if (!available)
+ {
+ //printf("dma stalled\n");
+ sh2->dma_timer_active[dma]=2;// mark as stalled
+ fatalerror("SH2 dma_callback_fifo_data_available == 0 in unsupported mode");
+ }
+ }
+
+ #ifdef USE_TIMER_FOR_DMA
+ //schedule next DMA callback
+ sh2->dma_current_active_timer[dma]->adjust(sh2->device->cycles_to_attotime(2), dma);
+ #endif
+
+ dmadata = sh2->program->read_dword(tempsrc);
+ if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(sh2->device, tempsrc, tempdst, dmadata, sh2->active_dma_size[dma]);
+ sh2->program->write_dword(tempdst, dmadata);
+
+ dmadata = sh2->program->read_dword(tempsrc+4);
+ if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(sh2->device, tempsrc, tempdst, dmadata, sh2->active_dma_size[dma]);
+ sh2->program->write_dword(tempdst+4, dmadata);
+
+ dmadata = sh2->program->read_dword(tempsrc+8);
+ if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(sh2->device, tempsrc, tempdst, dmadata, sh2->active_dma_size[dma]);
+ sh2->program->write_dword(tempdst+8, dmadata);
+
+ dmadata = sh2->program->read_dword(tempsrc+12);
+ if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(sh2->device, tempsrc, tempdst, dmadata, sh2->active_dma_size[dma]);
+ sh2->program->write_dword(tempdst+12, dmadata);
+
+ if(sh2->active_dma_incd[dma] == 2)
+ sh2->active_dma_dst[dma] -= 16;
+
+ sh2->active_dma_src[dma] += 16;
+ if(sh2->active_dma_incd[dma] == 1)
+ sh2->active_dma_dst[dma] += 16;
+
+ sh2->active_dma_count[dma]-=4;
+ }
+ break;
+ }
+ }
+ else // the dma is complete
+ {
+ // int dma = param & 1;
+ // sh2_state *sh2 = (sh2_state *)ptr;
+
+ // fever soccer uses cycle-stealing mode, resume the CPU now DMA has finished
+ if (sh2->active_dma_steal[dma])
+ {
+ sh2->device->resume(SUSPEND_REASON_HALT );
+ }
+
+
+ LOG(("SH2.%s: DMA %d complete\n", sh2->device->tag(), dma));
+ sh2->m[0x63+4*dma] |= 2;
+ sh2->dma_timer_active[dma] = 0;
+ sh2_recalc_irq(sh2);
+
+ }
+}
+
+static TIMER_CALLBACK( sh2_dma_current_active_callback )
+{
+ int dma = param & 1;
+ sh2_state *sh2 = (sh2_state *)ptr;
+
+ sh2_do_dma(sh2, dma);
+}
+
+
+static void sh2_dmac_check(sh2_state *sh2, int dma)
+{
+ if(sh2->m[0x63+4*dma] & sh2->m[0x6c] & 1)
+ {
+ if(!sh2->dma_timer_active[dma] && !(sh2->m[0x63+4*dma] & 2))
+ {
+
+ sh2->active_dma_incd[dma] = (sh2->m[0x63+4*dma] >> 14) & 3;
+ sh2->active_dma_incs[dma] = (sh2->m[0x63+4*dma] >> 12) & 3;
+ sh2->active_dma_size[dma] = (sh2->m[0x63+4*dma] >> 10) & 3;
+ sh2->active_dma_steal[dma] = (sh2->m[0x63+4*dma] &0x10);
+
+ if(sh2->active_dma_incd[dma] == 3 || sh2->active_dma_incs[dma] == 3)
+ {
+ logerror("SH2: DMA: bad increment values (%d, %d, %d, %04x)\n", sh2->active_dma_incd[dma], sh2->active_dma_incs[dma], sh2->active_dma_size[dma], sh2->m[0x63+4*dma]);
+ return;
+ }
+ sh2->active_dma_src[dma] = sh2->m[0x60+4*dma];
+ sh2->active_dma_dst[dma] = sh2->m[0x61+4*dma];
+ sh2->active_dma_count[dma] = sh2->m[0x62+4*dma];
+ if(!sh2->active_dma_count[dma])
+ sh2->active_dma_count[dma] = 0x1000000;
+
+ LOG(("SH2: DMA %d start %x, %x, %x, %04x, %d, %d, %d\n", dma, sh2->active_dma_src[dma], sh2->active_dma_dst[dma], sh2->active_dma_count[dma], sh2->m[0x63+4*dma], sh2->active_dma_incs[dma], sh2->active_dma_incd[dma], sh2->active_dma_size[dma]));
+
+ sh2->dma_timer_active[dma] = 1;
+
+ sh2->active_dma_src[dma] &= AM;
+ sh2->active_dma_dst[dma] &= AM;
+
+ switch(sh2->active_dma_size[dma])
+ {
+ case 0:
+ break;
+ case 1:
+ sh2->active_dma_src[dma] &= ~1;
+ sh2->active_dma_dst[dma] &= ~1;
+ break;
+ case 2:
+ sh2->active_dma_src[dma] &= ~3;
+ sh2->active_dma_dst[dma] &= ~3;
+ break;
+ case 3:
+ sh2->active_dma_src[dma] &= ~3;
+ sh2->active_dma_dst[dma] &= ~3;
+ sh2->active_dma_count[dma] &= ~3;
+ break;
+ }
+
+
+
+
+#ifdef USE_TIMER_FOR_DMA
+ // start DMA timer
+
+ // fever soccer uses cycle-stealing mode, requiring the CPU to be halted
+ if (sh2->active_dma_steal[dma])
+ {
+ //printf("cycle stealing DMA\n");
+ sh2->device->suspend(SUSPEND_REASON_HALT, 1 );
+ }
+
+ sh2->dma_current_active_timer[dma]->adjust(sh2->device->cycles_to_attotime(2), dma);
+#endif
+
+ }
+ }
+ else
+ {
+ if(sh2->dma_timer_active[dma])
+ {
+ logerror("SH2: DMA %d cancelled in-flight\n", dma);
+ //sh2->dma_complete_timer[dma]->adjust(attotime::never);
+ sh2->dma_current_active_timer[dma]->adjust(attotime::never);
+
+ sh2->dma_timer_active[dma] = 0;
+ }
+ }
+}
+
+WRITE32_HANDLER( sh2_internal_w )
+{
+ sh2_state *sh2 = GET_SH2(&space->device());
+ UINT32 old;
+
+#ifdef USE_SH2DRC
+ offset &= 0x7f;
+#endif
+
+ old = sh2->m[offset];
+ COMBINE_DATA(sh2->m+offset);
+
+ // if(offset != 0x20)
+ // logerror("sh2_internal_w: Write %08x (%x), %08x @ %08x\n", 0xfffffe00+offset*4, offset, data, mem_mask);
+
+// if(offset != 0x20)
+// printf("sh2_internal_w: Write %08x (%x), %08x @ %08x (PC %x)\n", 0xfffffe00+offset*4, offset, data, mem_mask, cpu_get_pc(&space->device()));
+
+ switch( offset )
+ {
+ // Timers
+ case 0x04: // TIER, FTCSR, FRC
+ if((mem_mask & 0x00ffffff) != 0)
+ {
+ sh2_timer_resync(sh2);
+ }
+// printf("SH2.%s: TIER write %04x @ %04x\n", sh2->device->tag(), data >> 16, mem_mask>>16);
+ sh2->m[4] = (sh2->m[4] & ~(ICF|OCFA|OCFB|OVF)) | (old & sh2->m[4] & (ICF|OCFA|OCFB|OVF));
+ COMBINE_DATA(&sh2->frc);
+ if((mem_mask & 0x00ffffff) != 0)
+ sh2_timer_activate(sh2);
+ sh2_recalc_irq(sh2);
+ break;
+ case 0x05: // OCRx, TCR, TOCR
+// printf("SH2.%s: TCR write %08x @ %08x\n", sh2->device->tag(), data, mem_mask);
+ sh2_timer_resync(sh2);
+ if(sh2->m[5] & 0x10)
+ sh2->ocrb = (sh2->ocrb & (~mem_mask >> 16)) | ((data & mem_mask) >> 16);
+ else
+ sh2->ocra = (sh2->ocra & (~mem_mask >> 16)) | ((data & mem_mask) >> 16);
+ sh2_timer_activate(sh2);
+ break;
+
+ case 0x06: // ICR
+ break;
+
+ // Interrupt vectors
+ case 0x18: // IPRB, VCRA
+ case 0x19: // VCRB, VCRC
+ case 0x1a: // VCRD
+ sh2_recalc_irq(sh2);
+ break;
+
+ // DMA
+ case 0x1c: // DRCR0, DRCR1
+ break;
+
+ // Watchdog
+ case 0x20: // WTCNT, RSTCSR
+ break;
+
+ // Standby and cache
+ case 0x24: // SBYCR, CCR
+ break;
+
+ // Interrupt vectors cont.
+ case 0x38: // ICR, IRPA
+ break;
+ case 0x39: // VCRWDT
+ break;
+
+ // Division box
+ case 0x40: // DVSR
+ break;
+ case 0x41: // DVDNT
+ {
+ INT32 a = sh2->m[0x41];
+ INT32 b = sh2->m[0x40];
+ LOG(("SH2 '%s' div+mod %d/%d\n", sh2->device->tag(), a, b));
+ if (b)
+ {
+ sh2->m[0x45] = a / b;
+ sh2->m[0x44] = a % b;
+ }
+ else
+ {
+ sh2->m[0x42] |= 0x00010000;
+ sh2->m[0x45] = 0x7fffffff;
+ sh2->m[0x44] = 0x7fffffff;
+ sh2_recalc_irq(sh2);
+ }
+ break;
+ }
+ case 0x42: // DVCR
+ sh2->m[0x42] = (sh2->m[0x42] & ~0x00001000) | (old & sh2->m[0x42] & 0x00010000);
+ sh2_recalc_irq(sh2);
+ break;
+ case 0x43: // VCRDIV
+ sh2_recalc_irq(sh2);
+ break;
+ case 0x44: // DVDNTH
+ break;
+ case 0x45: // DVDNTL
+ {
+ INT64 a = sh2->m[0x45] | ((UINT64)(sh2->m[0x44]) << 32);
+ INT64 b = (INT32)sh2->m[0x40];
+ LOG(("SH2 '%s' div+mod %" I64FMT "d/%" I64FMT "d\n", sh2->device->tag(), a, b));
+ if (b)
+ {
+ INT64 q = a / b;
+ if (q != (INT32)q)
+ {
+ sh2->m[0x42] |= 0x00010000;
+ sh2->m[0x45] = 0x7fffffff;
+ sh2->m[0x44] = 0x7fffffff;
+ sh2_recalc_irq(sh2);
+ }
+ else
+ {
+ sh2->m[0x45] = q;
+ sh2->m[0x44] = a % b;
+ }
+ }
+ else
+ {
+ sh2->m[0x42] |= 0x00010000;
+ sh2->m[0x45] = 0x7fffffff;
+ sh2->m[0x44] = 0x7fffffff;
+ sh2_recalc_irq(sh2);
+ }
+ break;
+ }
+
+ // DMA controller
+ case 0x60: // SAR0
+ case 0x61: // DAR0
+ break;
+ case 0x62: // DTCR0
+ sh2->m[0x62] &= 0xffffff;
+ break;
+ case 0x63: // CHCR0
+ sh2->m[0x63] = (sh2->m[0x63] & ~2) | (old & sh2->m[0x63] & 2);
+ sh2_dmac_check(sh2, 0);
+ break;
+ case 0x64: // SAR1
+ case 0x65: // DAR1
+ break;
+ case 0x66: // DTCR1
+ sh2->m[0x66] &= 0xffffff;
+ break;
+ case 0x67: // CHCR1
+ sh2->m[0x67] = (sh2->m[0x67] & ~2) | (old & sh2->m[0x67] & 2);
+ sh2_dmac_check(sh2, 1);
+ break;
+ case 0x68: // VCRDMA0
+ case 0x6a: // VCRDMA1
+ sh2_recalc_irq(sh2);
+ break;
+ case 0x6c: // DMAOR
+ sh2->m[0x6c] = (sh2->m[0x6c] & ~6) | (old & sh2->m[0x6c] & 6);
+ sh2_dmac_check(sh2, 0);
+ sh2_dmac_check(sh2, 1);
+ break;
+
+ // Bus controller
+ case 0x78: // BCR1
+ case 0x79: // BCR2
+ case 0x7a: // WCR
+ case 0x7b: // MCR
+ case 0x7c: // RTCSR
+ case 0x7d: // RTCNT
+ case 0x7e: // RTCOR
+ break;
+
+ default:
+ logerror("sh2_internal_w: Unmapped write %08x, %08x @ %08x\n", 0xfffffe00+offset*4, data, mem_mask);
+ break;
+ }
+}
+
+READ32_HANDLER( sh2_internal_r )
+{
+ sh2_state *sh2 = GET_SH2(&space->device());
+
+#ifdef USE_SH2DRC
+ offset &= 0x7f;
+#endif
+// logerror("sh2_internal_r: Read %08x (%x) @ %08x\n", 0xfffffe00+offset*4, offset, mem_mask);
+ switch( offset )
+ {
+ case 0x04: // TIER, FTCSR, FRC
+ if ( mem_mask == 0x00ff0000 )
+ {
+ if ( sh2->ftcsr_read_callback != NULL )
+ {
+ sh2->ftcsr_read_callback( (sh2->m[4] & 0xffff0000) | sh2->frc );
+ }
+ }
+ sh2_timer_resync(sh2);
+ return (sh2->m[4] & 0xffff0000) | sh2->frc;
+ case 0x05: // OCRx, TCR, TOCR
+ if(sh2->m[5] & 0x10)
+ return (sh2->ocrb << 16) | (sh2->m[5] & 0xffff);
+ else
+ return (sh2->ocra << 16) | (sh2->m[5] & 0xffff);
+ case 0x06: // ICR
+ return sh2->icr << 16;
+
+ case 0x38: // ICR, IPRA
+ return (sh2->m[0x38] & 0x7fffffff) | (sh2->nmi_line_state == ASSERT_LINE ? 0 : 0x80000000);
+
+ case 0x78: // BCR1
+ return sh2->is_slave ? 0x00008000 : 0;
+
+ case 0x41: // dvdntl mirrors
+ case 0x47:
+ return sh2->m[0x45];
+
+ case 0x46: // dvdnth mirror
+ return sh2->m[0x44];
+ }
+ return sh2->m[offset];
+}
+
+void sh2_set_ftcsr_read_callback(device_t *device, void (*callback)(UINT32))
+{
+ sh2_state *sh2 = GET_SH2(device);
+ sh2->ftcsr_read_callback = callback;
+}
+
+void sh2_set_frt_input(device_t *device, int state)
+{
+ sh2_state *sh2 = GET_SH2(device);
+
+ if(state == PULSE_LINE)
+ {
+ sh2_set_frt_input(device, ASSERT_LINE);
+ sh2_set_frt_input(device, CLEAR_LINE);
+ return;
+ }
+
+ if(sh2->frt_input == state) {
+ return;
+ }
+
+ sh2->frt_input = state;
+
+ if(sh2->m[5] & 0x8000) {
+ if(state == CLEAR_LINE) {
+ return;
+ }
+ } else {
+ if(state == ASSERT_LINE) {
+ return;
+ }
+ }
+
+ sh2_timer_resync(sh2);
+ sh2->icr = sh2->frc;
+ sh2->m[4] |= ICF;
+ //logerror("SH2.%s: ICF activated (%x)\n", sh2->device->tag(), sh2->pc & AM);
+ sh2_recalc_irq(sh2);
+}
+
+void sh2_set_irq_line(sh2_state *sh2, int irqline, int state)
+{
+ if (irqline == INPUT_LINE_NMI)
+ {
+ if (sh2->nmi_line_state == state)
+ return;
+ sh2->nmi_line_state = state;
+
+ if( state == CLEAR_LINE )
+ {
+ LOG(("SH-2 '%s' cleared nmi\n", sh2->device->tag()));
+ }
+ else
+ {
+ LOG(("SH-2 '%s' assert nmi\n", sh2->device->tag()));
+
+ sh2_exception(sh2, "Set IRQ line", 16);
+
+ #ifdef USE_SH2DRC
+ sh2->pending_nmi = 1;
+ #endif
+ }
+ }
+ else
+ {
+ if (sh2->irq_line_state[irqline] == state)
+ return;
+ sh2->irq_line_state[irqline] = state;
+
+ if( state == CLEAR_LINE )
+ {
+ LOG(("SH-2 '%s' cleared irq #%d\n", sh2->device->tag(), irqline));
+ sh2->pending_irq &= ~(1 << irqline);
+ }
+ else
+ {
+ LOG(("SH-2 '%s' assert irq #%d\n", sh2->device->tag(), irqline));
+ sh2->pending_irq |= 1 << irqline;
+ #ifdef USE_SH2DRC
+ sh2->test_irq = 1;
+ #else
+ if(sh2->delay)
+ sh2->test_irq = 1;
+ else
+ CHECK_PENDING_IRQ("sh2_set_irq_line");
+ #endif
+ }
+ }
+}
+
+void sh2_recalc_irq(sh2_state *sh2)
+{
+ int irq = 0, vector = -1;
+ int level;
+
+ // Timer irqs
+ if((sh2->m[4]>>8) & sh2->m[4] & (ICF|OCFA|OCFB|OVF))
+ {
+ level = (sh2->m[0x18] >> 24) & 15;
+ if(level > irq)
+ {
+ int mask = (sh2->m[4]>>8) & sh2->m[4];
+ irq = level;
+ if(mask & ICF)
+ vector = (sh2->m[0x19] >> 8) & 0x7f;
+ else if(mask & (OCFA|OCFB))
+ vector = sh2->m[0x19] & 0x7f;
+ else
+ vector = (sh2->m[0x1a] >> 24) & 0x7f;
+ }
+ }
+
+ // DMA irqs
+ if((sh2->m[0x63] & 6) == 6) {
+ level = (sh2->m[0x38] >> 8) & 15;
+ if(level > irq) {
+ irq = level;
+ vector = (sh2->m[0x68] >> 24) & 0x7f;
+ }
+ }
+
+ if((sh2->m[0x67] & 6) == 6) {
+ level = (sh2->m[0x38] >> 8) & 15;
+ if(level > irq) {
+ irq = level;
+ vector = (sh2->m[0x6a] >> 24) & 0x7f;
+ }
+ }
+
+ sh2->internal_irq_level = irq;
+ sh2->internal_irq_vector = vector;
+ sh2->test_irq = 1;
+}
+
+void sh2_exception(sh2_state *sh2, const char *message, int irqline)
+{
+ int vector;
+
+ if (irqline != 16)
+ {
+ if (irqline <= ((sh2->sr >> 4) & 15)) /* If the cpu forbids this interrupt */
+ return;
+
+ // if this is an sh2 internal irq, use its vector
+ if (sh2->internal_irq_level == irqline)
+ {
+ vector = sh2->internal_irq_vector;
+ LOG(("SH-2 '%s' exception #%d (internal vector: $%x) after [%s]\n", sh2->device->tag(), irqline, vector, message));
+ }
+ else
+ {
+ if(sh2->m[0x38] & 0x00010000)
+ {
+ vector = sh2->irq_callback(sh2->device, irqline);
+ LOG(("SH-2 '%s' exception #%d (external vector: $%x) after [%s]\n", sh2->device->tag(), irqline, vector, message));
+ }
+ else
+ {
+ sh2->irq_callback(sh2->device, irqline);
+ vector = 64 + irqline/2;
+ LOG(("SH-2 '%s' exception #%d (autovector: $%x) after [%s]\n", sh2->device->tag(), irqline, vector, message));
+ }
+ }
+ }
+ else
+ {
+ vector = 11;
+ LOG(("SH-2 '%s' nmi exception (autovector: $%x) after [%s]\n", sh2->device->tag(), vector, message));
+ }
+
+ #ifdef USE_SH2DRC
+ sh2->evec = RL( sh2, sh2->vbr + vector * 4 );
+ sh2->evec &= AM;
+ sh2->irqsr = sh2->sr;
+
+ /* set I flags in SR */
+ if (irqline > SH2_INT_15)
+ sh2->sr = sh2->sr | I;
+ else
+ sh2->sr = (sh2->sr & ~I) | (irqline << 4);
+
+// printf("sh2_exception [%s] irqline %x evec %x save SR %x new SR %x\n", message, irqline, sh2->evec, sh2->irqsr, sh2->sr);
+ #else
+ sh2->r[15] -= 4;
+ WL( sh2, sh2->r[15], sh2->sr ); /* push SR onto stack */
+ sh2->r[15] -= 4;
+ WL( sh2, sh2->r[15], sh2->pc ); /* push PC onto stack */
+
+ /* set I flags in SR */
+ if (irqline > SH2_INT_15)
+ sh2->sr = sh2->sr | I;
+ else
+ sh2->sr = (sh2->sr & ~I) | (irqline << 4);
+
+ /* fetch PC */
+ sh2->pc = RL( sh2, sh2->vbr + vector * 4 );
+ #endif
+}
+
+void sh2_common_init(sh2_state *sh2, legacy_cpu_device *device, device_irq_callback irqcallback)
+{
+ const sh2_cpu_core *conf = (const sh2_cpu_core *)device->static_config();
+ int i;
+
+ sh2->timer = device->machine().scheduler().timer_alloc(FUNC(sh2_timer_callback), sh2);
+ sh2->timer->adjust(attotime::never);
+
+ sh2->dma_current_active_timer[0] = device->machine().scheduler().timer_alloc(FUNC(sh2_dma_current_active_callback), sh2);
+ sh2->dma_current_active_timer[0]->adjust(attotime::never);
+
+ sh2->dma_current_active_timer[1] = device->machine().scheduler().timer_alloc(FUNC(sh2_dma_current_active_callback), sh2);
+ sh2->dma_current_active_timer[1]->adjust(attotime::never);
+
+
+ sh2->m = auto_alloc_array(device->machine(), UINT32, 0x200/4);
+
+ if(conf)
+ {
+ sh2->is_slave = conf->is_slave;
+ sh2->dma_callback_kludge = conf->dma_callback_kludge;
+ sh2->dma_callback_fifo_data_available = conf->dma_callback_fifo_data_available;
+ }
+ else
+ {
+ sh2->is_slave = 0;
+ sh2->dma_callback_kludge = NULL;
+ sh2->dma_callback_fifo_data_available = NULL;
+
+ }
+ sh2->irq_callback = irqcallback;
+ sh2->device = device;
+ sh2->program = device->space(AS_PROGRAM);
+ sh2->direct = &sh2->program->direct();
+ sh2->internal = device->space(AS_PROGRAM);
+
+ device->save_item(NAME(sh2->pc));
+ device->save_item(NAME(sh2->sr));
+ device->save_item(NAME(sh2->pr));
+ device->save_item(NAME(sh2->gbr));
+ device->save_item(NAME(sh2->vbr));
+ device->save_item(NAME(sh2->mach));
+ device->save_item(NAME(sh2->macl));
+ device->save_item(NAME(sh2->r));
+ device->save_item(NAME(sh2->ea));
+ device->save_item(NAME(sh2->delay));
+ device->save_item(NAME(sh2->cpu_off));
+ device->save_item(NAME(sh2->dvsr));
+ device->save_item(NAME(sh2->dvdnth));
+ device->save_item(NAME(sh2->dvdntl));
+ device->save_item(NAME(sh2->dvcr));
+ device->save_item(NAME(sh2->pending_irq));
+ device->save_item(NAME(sh2->test_irq));
+ device->save_item(NAME(sh2->pending_nmi));
+ device->save_item(NAME(sh2->irqline));
+ device->save_item(NAME(sh2->evec));
+ device->save_item(NAME(sh2->irqsr));
+ device->save_item(NAME(sh2->target));
+ for (i = 0; i < 16; ++i)
+ {
+ device->save_item(NAME(sh2->irq_queue[i].irq_vector), i);
+ device->save_item(NAME(sh2->irq_queue[i].irq_priority), i);
+ }
+ device->save_item(NAME(sh2->pcfsel));
+ device->save_item(NAME(sh2->maxpcfsel));
+ device->save_item(NAME(sh2->pcflushes));
+ device->save_item(NAME(sh2->irq_line_state));
+ device->save_pointer(NAME(sh2->m), 0x200/4);
+ device->save_item(NAME(sh2->nmi_line_state));
+ device->save_item(NAME(sh2->frc));
+ device->save_item(NAME(sh2->ocra));
+ device->save_item(NAME(sh2->ocrb));
+ device->save_item(NAME(sh2->icr));
+ device->save_item(NAME(sh2->frc_base));
+ device->save_item(NAME(sh2->frt_input));
+ device->save_item(NAME(sh2->internal_irq_level));
+ device->save_item(NAME(sh2->internal_irq_vector));
+ device->save_item(NAME(sh2->dma_timer_active));
+}
+
diff --git a/trunk/src/emu/cpu/sh2/sh2comn.h b/trunk/src/emu/cpu/sh2/sh2comn.h
new file mode 100644
index 00000000000..9f2509a0146
--- /dev/null
+++ b/trunk/src/emu/cpu/sh2/sh2comn.h
@@ -0,0 +1,217 @@
+/*****************************************************************************
+ *
+ * sh2common.h
+ *
+ * SH-2 non-specific components
+ *
+ *****************************************************************************/
+
+#pragma once
+
+#ifndef __SH2COMN_H__
+#define __SH2COMN_H__
+
+
+#define USE_SH2DRC
+
+// do we use a timer for the DMA, or have it in CPU_EXECUTE
+#define USE_TIMER_FOR_DMA
+
+#ifdef USE_SH2DRC
+#include "cpu/drcfe.h"
+#include "cpu/drcuml.h"
+#include "cpu/drcumlsh.h"
+class sh2_frontend;
+#endif
+
+#define SH2_CODE_XOR(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(2,0))
+
+typedef struct _irq_entry irq_entry;
+struct _irq_entry
+{
+ int irq_vector;
+ int irq_priority;
+};
+
+enum
+{
+ ICF = 0x00800000,
+ OCFA = 0x00080000,
+ OCFB = 0x00040000,
+ OVF = 0x00020000
+};
+
+#define T 0x00000001
+#define S 0x00000002
+#define I 0x000000f0
+#define Q 0x00000100
+#define M 0x00000200
+
+#define AM 0xc7ffffff
+
+#define FLAGS (M|Q|I|S|T)
+
+#define Rn ((opcode>>8)&15)
+#define Rm ((opcode>>4)&15)
+
+#define CPU_TYPE_SH1 (0)
+#define CPU_TYPE_SH2 (1)
+
+#define REGFLAG_R(n) (1 << (n))
+
+/* register flags 1 */
+#define REGFLAG_PR (1 << 0)
+#define REGFLAG_MACL (1 << 1)
+#define REGFLAG_MACH (1 << 2)
+#define REGFLAG_GBR (1 << 3)
+#define REGFLAG_VBR (1 << 4)
+#define REGFLAG_SR (1 << 5)
+
+#define CHECK_PENDING_IRQ(message) \
+do { \
+ int irq = -1; \
+ if (sh2->pending_irq & (1 << 0)) irq = 0; \
+ if (sh2->pending_irq & (1 << 1)) irq = 1; \
+ if (sh2->pending_irq & (1 << 2)) irq = 2; \
+ if (sh2->pending_irq & (1 << 3)) irq = 3; \
+ if (sh2->pending_irq & (1 << 4)) irq = 4; \
+ if (sh2->pending_irq & (1 << 5)) irq = 5; \
+ if (sh2->pending_irq & (1 << 6)) irq = 6; \
+ if (sh2->pending_irq & (1 << 7)) irq = 7; \
+ if (sh2->pending_irq & (1 << 8)) irq = 8; \
+ if (sh2->pending_irq & (1 << 9)) irq = 9; \
+ if (sh2->pending_irq & (1 << 10)) irq = 10; \
+ if (sh2->pending_irq & (1 << 11)) irq = 11; \
+ if (sh2->pending_irq & (1 << 12)) irq = 12; \
+ if (sh2->pending_irq & (1 << 13)) irq = 13; \
+ if (sh2->pending_irq & (1 << 14)) irq = 14; \
+ if (sh2->pending_irq & (1 << 15)) irq = 15; \
+ if ((sh2->internal_irq_level != -1) && (sh2->internal_irq_level > irq)) irq = sh2->internal_irq_level; \
+ if (irq >= 0) \
+ sh2_exception(sh2,message,irq); \
+} while(0)
+
+typedef struct
+{
+ UINT32 ppc;
+ UINT32 pc;
+ UINT32 pr;
+ UINT32 sr;
+ UINT32 gbr, vbr;
+ UINT32 mach, macl;
+ UINT32 r[16];
+ UINT32 ea;
+ UINT32 delay;
+ UINT32 cpu_off;
+ UINT32 dvsr, dvdnth, dvdntl, dvcr;
+ UINT32 pending_irq;
+ UINT32 test_irq;
+ UINT32 pending_nmi;
+ INT32 irqline;
+ UINT32 evec; // exception vector for DRC
+ UINT32 irqsr; // IRQ-time old SR for DRC
+ UINT32 target; // target for jmp/jsr/etc so the delay slot can't kill it
+ irq_entry irq_queue[16];
+
+ int pcfsel; // last pcflush entry set
+ int maxpcfsel; // highest valid pcflush entry
+ UINT32 pcflushes[16]; // pcflush entries
+
+ INT8 irq_line_state[17];
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *internal;
+ UINT32 *m;
+ INT8 nmi_line_state;
+
+ UINT16 frc;
+ UINT16 ocra, ocrb, icr;
+ UINT64 frc_base;
+
+ int frt_input;
+ int internal_irq_level;
+ int internal_irq_vector;
+ int icount;
+
+ emu_timer *timer;
+ emu_timer *dma_current_active_timer[2];
+ int dma_timer_active[2];
+
+ int active_dma_incs[2];
+ int active_dma_incd[2];
+ int active_dma_size[2];
+ int active_dma_steal[2];
+ UINT32 active_dma_src[2];
+ UINT32 active_dma_dst[2];
+ UINT32 active_dma_count[2];
+
+ int is_slave, cpu_type;
+ int (*dma_callback_kludge)(device_t *device, UINT32 src, UINT32 dst, UINT32 data, int size);
+ int (*dma_callback_fifo_data_available)(device_t *device, UINT32 src, UINT32 dst, UINT32 data, int size);
+
+ void (*ftcsr_read_callback)(UINT32 data);
+
+#ifdef USE_SH2DRC
+ drc_cache * cache; /* pointer to the DRC code cache */
+ drcuml_state * drcuml; /* DRC UML generator state */
+ sh2_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 */
+
+ /* parameters for subroutines */
+ UINT64 numcycles; /* return value from gettotalcycles */
+ UINT32 arg0; /* print_debug argument 1 */
+ UINT32 arg1; /* print_debug argument 2 */
+ UINT32 irq; /* irq we're taking */
+
+ /* register mappings */
+ uml::parameter regmap[16]; /* parameter to register mappings for all 16 integer registers */
+
+ uml::code_handle * entry; /* entry point */
+ uml::code_handle * read8; /* read byte */
+ uml::code_handle * write8; /* write byte */
+ uml::code_handle * read16; /* read half */
+ uml::code_handle * write16; /* write half */
+ uml::code_handle * read32; /* read word */
+ uml::code_handle * write32; /* write word */
+
+ uml::code_handle * interrupt; /* interrupt */
+ uml::code_handle * nocode; /* nocode */
+ uml::code_handle * out_of_cycles; /* out of cycles exception handler */
+#endif
+} sh2_state;
+
+#ifdef USE_SH2DRC
+class sh2_frontend : public drc_frontend
+{
+public:
+ sh2_frontend(sh2_state &state, UINT32 window_start, UINT32 window_end, UINT32 max_sequence);
+
+protected:
+ virtual bool describe(opcode_desc &desc, const opcode_desc *prev);
+
+private:
+ bool describe_group_0(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
+ bool describe_group_2(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
+ bool describe_group_3(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
+ bool describe_group_4(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
+ bool describe_group_6(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
+ bool describe_group_8(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
+ bool describe_group_12(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
+
+ sh2_state &m_context;
+};
+#endif
+
+void sh2_common_init(sh2_state *sh2, legacy_cpu_device *device, device_irq_callback irqcallback);
+void sh2_recalc_irq(sh2_state *sh2);
+void sh2_set_irq_line(sh2_state *sh2, int irqline, int state);
+void sh2_exception(sh2_state *sh2, const char *message, int irqline);
+void sh2_do_dma(sh2_state *sh2, int dma);
+void sh2_notify_dma_data_available(device_t *device);
+
+#endif /* __SH2COMN_H__ */
diff --git a/trunk/src/emu/cpu/sh2/sh2dasm.c b/trunk/src/emu/cpu/sh2/sh2dasm.c
new file mode 100644
index 00000000000..f94125fb27c
--- /dev/null
+++ b/trunk/src/emu/cpu/sh2/sh2dasm.c
@@ -0,0 +1,609 @@
+#include "emu.h"
+#include "debugger.h"
+#include "sh2.h"
+
+#define SIGNX8(x) (((INT32)(x) << 24) >> 24)
+#define SIGNX12(x) (((INT32)(x) << 20) >> 20)
+
+#define Rn ((opcode >> 8) & 15)
+#define Rm ((opcode >> 4) & 15)
+
+static const char *const regname[16] = {
+ "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
+ "R8", "R9", "R10","R11","R12","R13","R14","SP"
+};
+
+static UINT32 op0000(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ UINT32 flags = 0;
+ switch(opcode & 0x3f)
+ {
+ case 0x02:
+ sprintf(buffer,"STC SR,%s", regname[Rn]);
+ break;
+ case 0x03:
+ sprintf(buffer,"BSRF %s", regname[Rn]);
+ break;
+ case 0x08:
+ sprintf(buffer,"CLRT");
+ break;
+ case 0x09:
+ sprintf(buffer,"NOP");
+ break;
+ case 0x0A:
+ sprintf(buffer,"STS MACH,%s", regname[Rn]);
+ break;
+ case 0x0B:
+ sprintf(buffer,"RTS");
+ flags = DASMFLAG_STEP_OUT;
+ break;
+ case 0x12:
+ sprintf(buffer,"STS GBR,%s", regname[Rn]);
+ break;
+ case 0x18:
+ sprintf(buffer,"SETT");
+ break;
+ case 0x19:
+ sprintf(buffer,"DIV0U");
+ break;
+ case 0x1A:
+ sprintf(buffer,"STS MACL,%s", regname[Rn]);
+ break;
+ case 0x1B:
+ sprintf(buffer,"SLEEP");
+ break;
+ case 0x22:
+ sprintf(buffer,"STC VBR,%s", regname[Rn]);
+ break;
+ case 0x23:
+ sprintf(buffer,"BRAF %s", regname[Rn]);
+ break;
+ case 0x28:
+ sprintf(buffer,"CLRMAC");
+ break;
+ case 0x29:
+ sprintf(buffer,"MOVT %s", regname[Rn]);
+ break;
+ case 0x2A:
+ sprintf(buffer,"STS PR,%s", regname[Rn]);
+ break;
+ case 0x2B:
+ sprintf(buffer,"RTE");
+ flags = DASMFLAG_STEP_OUT;
+ break;
+ default:
+ switch(opcode & 15)
+ {
+ case 0:
+ sprintf(buffer, "?????? $%04X", opcode);
+ break;
+ case 1:
+ sprintf(buffer, "?????? $%04X", opcode);
+ break;
+ case 2:
+ sprintf(buffer, "?????? $%04X", opcode);
+ break;
+ case 3:
+ sprintf(buffer, "?????? $%04X", opcode);
+ break;
+ case 4:
+ sprintf(buffer, "MOV.B %s,@(R0,%s)", regname[Rm], regname[Rn]);
+ break;
+ case 5:
+ sprintf(buffer, "MOV.W %s,@(R0,%s)", regname[Rm], regname[Rn]);
+ break;
+ case 6:
+ sprintf(buffer, "MOV.L %s,@(R0,%s)", regname[Rm], regname[Rn]);
+ break;
+ case 7:
+ sprintf(buffer, "MUL.L %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 8:
+ sprintf(buffer, "?????? $%04X", opcode);
+ break;
+ case 9:
+ sprintf(buffer, "?????? $%04X", opcode);
+ break;
+ case 10:
+ sprintf(buffer, "?????? $%04X", opcode);
+ break;
+ case 11:
+ sprintf(buffer, "?????? $%04X", opcode);
+ break;
+ case 12:
+ sprintf(buffer, "MOV.B @(R0,%s),%s", regname[Rm], regname[Rn]);
+ break;
+ case 13:
+ sprintf(buffer, "MOV.W @(R0,%s),%s", regname[Rm], regname[Rn]);
+ break;
+ case 14:
+ sprintf(buffer, "MOV.L @(R0,%s),%s", regname[Rm], regname[Rn]);
+ break;
+ case 15:
+ sprintf(buffer, "MAC.L @%s+,@%s+", regname[Rn], regname[Rm]);
+ break;
+ }
+ }
+ return flags;
+}
+
+static UINT32 op0001(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ sprintf(buffer, "MOV.L %s,@($%02X,%s)", regname[Rm], (opcode & 15) * 4, regname[Rn]);
+ return 0;
+}
+
+static UINT32 op0010(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ switch (opcode & 15)
+ {
+ case 0:
+ sprintf(buffer, "MOV.B %s,@%s", regname[Rm], regname[Rn]);
+ break;
+ case 1:
+ sprintf(buffer, "MOV.W %s,@%s", regname[Rm], regname[Rn]);
+ break;
+ case 2:
+ sprintf(buffer, "MOV.L %s,@%s", regname[Rm], regname[Rn]);
+ break;
+ case 3:
+ sprintf(buffer, "?????? $%04X", opcode);
+ break;
+ case 4:
+ sprintf(buffer, "MOV.B %s,@-%s", regname[Rm], regname[Rn]);
+ break;
+ case 5:
+ sprintf(buffer, "MOV.W %s,@-%s", regname[Rm], regname[Rn]);
+ break;
+ case 6:
+ sprintf(buffer, "MOV.L %s,@-%s", regname[Rm], regname[Rn]);
+ break;
+ case 7:
+ sprintf(buffer, "DIV0S %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 8:
+ sprintf(buffer, "TST %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 9:
+ sprintf(buffer, "AND %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 10:
+ sprintf(buffer, "XOR %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 11:
+ sprintf(buffer, "OR %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 12:
+ sprintf(buffer, "CMP/STR %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 13:
+ sprintf(buffer, "XTRCT %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 14:
+ sprintf(buffer, "MULU.W %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 15:
+ sprintf(buffer, "MULS.W %s,%s", regname[Rm], regname[Rn]);
+ break;
+ }
+ return 0;
+}
+
+static UINT32 op0011(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ switch (opcode & 15)
+ {
+ case 0:
+ sprintf(buffer, "CMP/EQ %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 1:
+ sprintf(buffer, "?????? %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 2:
+ sprintf(buffer, "CMP/HS %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 3:
+ sprintf(buffer, "CMP/GE %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 4:
+ sprintf(buffer, "DIV1 %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 5:
+ sprintf(buffer, "DMULU.L %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 6:
+ sprintf(buffer, "CMP/HI %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 7:
+ sprintf(buffer, "CMP/GT %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 8:
+ sprintf(buffer, "SUB %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 9:
+ sprintf(buffer, "?????? %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 10:
+ sprintf(buffer, "SUBC %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 11:
+ sprintf(buffer, "SUBV %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 12:
+ sprintf(buffer, "ADD %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 13:
+ sprintf(buffer, "DMULS.L %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 14:
+ sprintf(buffer, "ADDC %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 15:
+ sprintf(buffer, "ADDV %s,%s", regname[Rm], regname[Rn]);
+ break;
+ }
+ return 0;
+}
+
+static UINT32 op0100(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ UINT32 flags = 0;
+ switch(opcode & 0x3F)
+ {
+ case 0x00:
+ sprintf(buffer, "SHLL %s", regname[Rn]);
+ break;
+ case 0x01:
+ sprintf(buffer, "SHLR %s", regname[Rn]);
+ break;
+ case 0x02:
+ sprintf(buffer, "STS.L MACH,@-%s", regname[Rn]);
+ break;
+ case 0x03:
+ sprintf(buffer, "STC.L SR,@-%s", regname[Rn]);
+ break;
+ case 0x04:
+ sprintf(buffer, "ROTL %s", regname[Rn]);
+ break;
+ case 0x05:
+ sprintf(buffer, "ROTR %s", regname[Rn]);
+ break;
+ case 0x06:
+ sprintf(buffer, "LDS.L @%s+,MACH", regname[Rn]);
+ break;
+ case 0x07:
+ sprintf(buffer, "LDC.L @%s+,SR", regname[Rn]);
+ break;
+ case 0x08:
+ sprintf(buffer, "SHLL2 %s", regname[Rn]);
+ break;
+ case 0x09:
+ sprintf(buffer, "SHLR2 %s", regname[Rn]);
+ break;
+ case 0x0a:
+ sprintf(buffer, "LDS %s,MACH", regname[Rn]);
+ break;
+ case 0x0b:
+ sprintf(buffer, "JSR %s", regname[Rn]);
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
+ break;
+ case 0x0e:
+ sprintf(buffer, "LDC %s,SR", regname[Rn]);
+ break;
+ case 0x10:
+ sprintf(buffer, "DT %s", regname[Rn]);
+ break;
+ case 0x11:
+ sprintf(buffer, "CMP/PZ %s", regname[Rn]);
+ break;
+ case 0x12:
+ sprintf(buffer, "STS.L MACL,@-%s", regname[Rn]);
+ break;
+ case 0x13:
+ sprintf(buffer, "STC.L GBR,@-%s", regname[Rn]);
+ break;
+ case 0x15:
+ sprintf(buffer, "CMP/PL %s", regname[Rn]);
+ break;
+ case 0x16:
+ sprintf(buffer, "LDS.L @%s+,MACL", regname[Rn]);
+ break;
+ case 0x17:
+ sprintf(buffer, "LDC.L @%s+,GBR", regname[Rn]);
+ break;
+ case 0x18:
+ sprintf(buffer, "SHLL8 %s", regname[Rn]);
+ break;
+ case 0x19:
+ sprintf(buffer, "SHLR8 %s", regname[Rn]);
+ break;
+ case 0x1a:
+ sprintf(buffer, "LDS %s,MACL", regname[Rn]);
+ break;
+ case 0x1b:
+ sprintf(buffer, "TAS %s", regname[Rn]);
+ break;
+ case 0x1e:
+ sprintf(buffer, "LDC %s,GBR", regname[Rn]);
+ break;
+ case 0x20:
+ sprintf(buffer, "SHAL %s", regname[Rn]);
+ break;
+ case 0x21:
+ sprintf(buffer, "SHAR %s", regname[Rn]);
+ break;
+ case 0x22:
+ sprintf(buffer, "STS.L PR,@-%s", regname[Rn]);
+ break;
+ case 0x23:
+ sprintf(buffer, "STC.L VBR,@-%s", regname[Rn]);
+ break;
+ case 0x24:
+ sprintf(buffer, "ROTCL %s", regname[Rn]);
+ break;
+ case 0x25:
+ sprintf(buffer, "ROTCR %s", regname[Rn]);
+ break;
+ case 0x26:
+ sprintf(buffer, "LDS.L @%s+,PR", regname[Rn]);
+ break;
+ case 0x27:
+ sprintf(buffer, "LDC.L @%s+,VBR", regname[Rn]);
+ break;
+ case 0x28:
+ sprintf(buffer, "SHLL16 %s", regname[Rn]);
+ break;
+ case 0x29:
+ sprintf(buffer, "SHLR16 %s", regname[Rn]);
+ break;
+ case 0x2a:
+ sprintf(buffer, "LDS %s,PR", regname[Rn]);
+ break;
+ case 0x2b:
+ sprintf(buffer, "JMP %s", regname[Rn]);
+ break;
+ case 0x2e:
+ sprintf(buffer, "LDC %s,VBR", regname[Rn]);
+ break;
+ default:
+ if ((opcode & 15) == 15)
+ sprintf(buffer, "MAC.W @%s+,@%s+", regname[Rm], regname[Rn]);
+ else
+ sprintf(buffer, "?????? $%04X", opcode);
+ }
+ return flags;
+}
+
+static UINT32 op0101(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ sprintf(buffer, "MOV.L @($%02X,%s),%s", (opcode & 15) * 4, regname[Rm], regname[Rn]);
+ return 0;
+}
+
+static UINT32 op0110(char *buffer, UINT32 pc, UINT16 opcode)
+
+{
+ switch(opcode & 0xF)
+ {
+ case 0x00:
+ sprintf(buffer, "MOV.B @%s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x01:
+ sprintf(buffer, "MOV.W @%s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x02:
+ sprintf(buffer, "MOV.L @%s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x03:
+ sprintf(buffer, "MOV %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x04:
+ sprintf(buffer, "MOV.B @%s+,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x05:
+ sprintf(buffer, "MOV.W @%s+,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x06:
+ sprintf(buffer, "MOV.L @%s+,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x07:
+ sprintf(buffer, "NOT %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x08:
+ sprintf(buffer, "SWAP.B %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x09:
+ sprintf(buffer, "SWAP.W %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x0a:
+ sprintf(buffer, "NEGC %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x0b:
+ sprintf(buffer, "NEG %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x0c:
+ sprintf(buffer, "EXTU.B %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x0d:
+ sprintf(buffer, "EXTU.W %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x0e:
+ sprintf(buffer, "EXTS.B %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x0f:
+ sprintf(buffer, "EXTS.W %s,%s", regname[Rm], regname[Rn]);
+ break;
+ }
+ return 0;
+}
+
+static UINT32 op0111(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ sprintf(buffer, "ADD #$%02X,%s", opcode & 0xff, regname[Rn]);
+ return 0;
+}
+
+static UINT32 op1000(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ switch((opcode >> 8) & 15)
+ {
+ case 0:
+ sprintf(buffer, "MOV.B R0,@($%02X,%s)", (opcode & 15), regname[Rm]);
+ break;
+ case 1:
+ sprintf(buffer, "MOV.W R0,@($%02X,%s)", (opcode & 15) * 2, regname[Rm]);
+ break;
+ case 4:
+ sprintf(buffer, "MOV.B @($%02X,%s),R0", (opcode & 15), regname[Rm]);
+ break;
+ case 5:
+ sprintf(buffer, "MOV.W @($%02X,%s),R0", (opcode & 15), regname[Rm]);
+ break;
+ case 8:
+ sprintf(buffer, "CMP/EQ #$%02X,R0", (opcode & 0xff));
+ break;
+ case 9:
+ sprintf(buffer, "BT $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2);
+ break;
+ case 11:
+ sprintf(buffer, "BF $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2);
+ break;
+ case 13:
+ sprintf(buffer, "BTS $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2);
+ break;
+ case 15:
+ sprintf(buffer, "BFS $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2);
+ break;
+ default :
+ sprintf(buffer, "invalid $%04X", opcode);
+ }
+ return 0;
+}
+
+static UINT32 op1001(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ sprintf(buffer, "MOV.W @($%04X,PC),%s", (opcode & 0xff) * 2, regname[Rn]);
+ return 0;
+}
+
+static UINT32 op1010(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ sprintf(buffer, "BRA $%08X", SIGNX12(opcode & 0xfff) * 2 + pc + 2);
+ return 0;
+}
+
+static UINT32 op1011(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ sprintf(buffer, "BSR $%08X", SIGNX12(opcode & 0xfff) * 2 + pc + 2);
+ return DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
+}
+
+static UINT32 op1100(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ UINT32 flags = 0;
+ switch((opcode >> 8) & 15)
+ {
+ case 0:
+ sprintf(buffer, "MOV.B R0,@($%02X,GBR)", opcode & 0xff);
+ break;
+ case 1:
+ sprintf(buffer, "MOV.W R0,@($%04X,GBR)", (opcode & 0xff) * 2);
+ break;
+ case 2:
+ sprintf(buffer, "MOV.L R0,@($%04X,GBR)", (opcode & 0xff) * 4);
+ break;
+ case 3:
+ sprintf(buffer, "TRAPA #$%02X", opcode & 0xff);
+ flags = DASMFLAG_STEP_OVER;
+ break;
+ case 4:
+ sprintf(buffer, "MOV.B @($%02X,GBR),R0", opcode & 0xff);
+ break;
+ case 5:
+ sprintf(buffer, "MOV.W @($%04X,GBR),R0", (opcode & 0xff) * 2);
+ break;
+ case 6:
+ sprintf(buffer, "MOV.L @($%04X,GBR),R0", (opcode & 0xff) * 4);
+ break;
+ case 7:
+ sprintf(buffer, "MOVA @($%04X,PC),R0", (opcode & 0xff) * 4);
+ break;
+ case 8:
+ sprintf(buffer, "TST #$%02X,R0", opcode & 0xff);
+ break;
+ case 9:
+ sprintf(buffer, "AND #$%02X,R0", opcode & 0xff);
+ break;
+ case 10:
+ sprintf(buffer, "XOR #$%02X,R0", opcode & 0xff);
+ break;
+ case 11:
+ sprintf(buffer, "OR #$%02X,R0", opcode & 0xff);
+ break;
+ case 12:
+ sprintf(buffer, "TST.B #$%02X,@(R0,GBR)", opcode & 0xff);
+ break;
+ case 13:
+ sprintf(buffer, "AND.B #$%02X,@(R0,GBR)", opcode & 0xff);
+ break;
+ case 14:
+ sprintf(buffer, "XOR.B #$%02X,@(R0,GBR)", opcode & 0xff);
+ break;
+ case 15:
+ sprintf(buffer, "OR.B #$%02X,@(R0,GBR)", opcode & 0xff);
+ break;
+ }
+ return flags;
+}
+
+static UINT32 op1101(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ sprintf(buffer, "MOV.L @($%02X,PC),%s", (opcode * 4) & 0xff, regname[Rn]);
+ return 0;
+}
+
+static UINT32 op1110(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ sprintf(buffer, "MOV #$%02X,%s", (opcode & 0xff), regname[Rn]);
+ return 0;
+}
+
+static UINT32 op1111(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ sprintf(buffer, "unknown $%04X", opcode);
+ return 0;
+}
+
+unsigned DasmSH2(char *buffer, unsigned pc, UINT16 opcode)
+{
+ UINT32 flags;
+
+ pc += 2;
+
+ switch((opcode >> 12) & 15)
+ {
+ case 0: flags = op0000(buffer,pc,opcode); break;
+ case 1: flags = op0001(buffer,pc,opcode); break;
+ case 2: flags = op0010(buffer,pc,opcode); break;
+ case 3: flags = op0011(buffer,pc,opcode); break;
+ case 4: flags = op0100(buffer,pc,opcode); break;
+ case 5: flags = op0101(buffer,pc,opcode); break;
+ case 6: flags = op0110(buffer,pc,opcode); break;
+ case 7: flags = op0111(buffer,pc,opcode); break;
+ case 8: flags = op1000(buffer,pc,opcode); break;
+ case 9: flags = op1001(buffer,pc,opcode); break;
+ case 10: flags = op1010(buffer,pc,opcode); break;
+ case 11: flags = op1011(buffer,pc,opcode); break;
+ case 12: flags = op1100(buffer,pc,opcode); break;
+ case 13: flags = op1101(buffer,pc,opcode); break;
+ case 14: flags = op1110(buffer,pc,opcode); break;
+ default: flags = op1111(buffer,pc,opcode); break;
+ }
+ return 2 | flags | DASMFLAG_SUPPORTED;
+}
+
+CPU_DISASSEMBLE( sh2 )
+{
+ return DasmSH2( buffer, pc, (oprom[0] << 8) | oprom[1] );
+}
+
diff --git a/trunk/src/emu/cpu/sh2/sh2drc.c b/trunk/src/emu/cpu/sh2/sh2drc.c
new file mode 100644
index 00000000000..41bcc49289e
--- /dev/null
+++ b/trunk/src/emu/cpu/sh2/sh2drc.c
@@ -0,0 +1,3421 @@
+/***************************************************************************
+
+ sh2drc.c
+ Universal machine language-based SH-2 emulator.
+ By R. Belmont
+
+ Released for general non-commercial use under the MAME license
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+ ST-V status:
+ colmns97 & stress crash due to SCSP stream->machine() getting corrupted.
+
+ cottonbm w/US bios: run to 60323B4 on master, then MOV insn @ 602f5aa crashes?
+ actually crash on slave @ 6032b38 after above. reading wrong addr for jump vector.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "sh2.h"
+#include "sh2comn.h"
+#include "profiler.h"
+
+CPU_DISASSEMBLE( sh2 );
+extern unsigned DasmSH2(char *buffer, unsigned pc, UINT16 opcode);
+
+#ifdef USE_SH2DRC
+
+using namespace uml;
+
+/***************************************************************************
+ DEBUGGING
+***************************************************************************/
+
+#define FORCE_C_BACKEND (0) // use the C backend even when a native one is available
+#define LOG_UML (0) // log UML assembly
+#define LOG_NATIVE (0) // log native assembly
+
+#define SET_EA (0) // makes slower but "shows work" in the EA fake register like the interpreter
+
+#define DISABLE_FAST_REGISTERS (0) // set to 1 to turn off usage of register caching
+#define SINGLE_INSTRUCTION_MODE (0)
+
+#define ADDSUBV_DIRECT (0)
+
+#define VERBOSE 0
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+#if SET_EA
+#define SETEA(x) UML_MOV(block, mem(&sh2->ea), ireg(x))
+#else
+#define SETEA(x)
+#endif
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* map variables */
+#define MAPVAR_PC M0
+#define MAPVAR_CYCLES M1
+
+/* 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 64
+#define COMPILE_FORWARDS_BYTES 256
+#define COMPILE_MAX_INSTRUCTIONS ((COMPILE_BACKWARDS_BYTES/2) + (COMPILE_FORWARDS_BYTES/2))
+#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
+
+#define PROBE_ADDRESS ~0
+
+extern int sh2_describe(void *param, opcode_desc *desc, const opcode_desc *prev);
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define R32(reg) sh2->regmap[reg]
+
+/***************************************************************************
+ STRUCTURES & TYPEDEFS
+***************************************************************************/
+
+/* 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 */
+ code_label labelnum; /* index for local labels */
+};
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void static_generate_entry_point(sh2_state *sh2);
+static void static_generate_nocode_handler(sh2_state *sh2);
+static void static_generate_out_of_cycles(sh2_state *sh2);
+static void static_generate_memory_accessor(sh2_state *sh2, int size, int iswrite, const char *name, code_handle **handleptr);
+
+static void generate_update_cycles(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, parameter param, int allow_exception);
+static void generate_checksum_block(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast);
+static void generate_sequence_instruction(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 ovrpc);
+static void generate_delay_slot(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 ovrpc);
+
+static int generate_opcode(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 ovrpc);
+static int generate_group_0(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc);
+static int generate_group_2(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc);
+static int generate_group_3(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, UINT32 ovrpc);
+static int generate_group_4(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc);
+static int generate_group_6(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc);
+static int generate_group_8(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc);
+static int generate_group_12(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc);
+
+static void code_compile_block(sh2_state *sh2, UINT8 mode, offs_t pc);
+
+static void log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, int indent);
+static void log_register_list(drcuml_state *drcuml, const char *string, const UINT32 *reglist, const UINT32 *regnostarlist);
+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 cfunc_printf_probe(void *param);
+static void cfunc_unimplemented(void *param);
+static void cfunc_checkirqs(void *param);
+static void cfunc_fastirq(void *param);
+static void cfunc_MAC_W(void *param);
+static void cfunc_MAC_L(void *param);
+static void cfunc_DIV1(void *param);
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE sh2_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == SH1 ||
+ device->type() == SH2);
+ return *(sh2_state **)downcast<legacy_cpu_device *>(device)->token();
+}
+
+INLINE UINT16 RW(sh2_state *sh2, offs_t A)
+{
+ if (A >= 0xe0000000)
+ return sh2_internal_r(sh2->internal, (A & 0x1fc)>>2, 0xffff << (((~A) & 2)*8)) >> (((~A) & 2)*8);
+
+ if (A >= 0xc0000000)
+ return sh2->program->read_word(A);
+
+ return sh2->program->read_word(A & AM);
+}
+
+INLINE UINT32 RL(sh2_state *sh2, offs_t A)
+{
+ if (A >= 0xe0000000)
+ return sh2_internal_r(sh2->internal, (A & 0x1fc)>>2, 0xffffffff);
+
+ if (A >= 0xc0000000)
+ return sh2->program->read_dword(A);
+
+ return sh2->program->read_dword(A & AM);
+}
+
+/*-------------------------------------------------
+ epc - compute the exception PC from a
+ descriptor
+-------------------------------------------------*/
+
+INLINE UINT32 epc(const opcode_desc *desc)
+{
+ return (desc->flags & OPFLAG_IN_DELAY_SLOT) ? (desc->pc - 1) : 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(sh2_state *sh2, drcuml_block *block)
+{
+ int regnum;
+
+ for (regnum = 0; regnum < ARRAY_LENGTH(sh2->regmap); regnum++)
+ {
+ if (sh2->regmap[regnum].is_int_register())
+ {
+ UML_MOV(block, parameter::make_ireg(sh2->regmap[regnum].ireg()), mem(&sh2->r[regnum]));
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ save_fast_iregs - save any fast integer
+ registers
+-------------------------------------------------*/
+
+INLINE void save_fast_iregs(sh2_state *sh2, drcuml_block *block)
+{
+ int regnum;
+
+ for (regnum = 0; regnum < ARRAY_LENGTH(sh2->regmap); regnum++)
+ {
+ if (sh2->regmap[regnum].is_int_register())
+ {
+ UML_MOV(block, mem(&sh2->r[regnum]), parameter::make_ireg(sh2->regmap[regnum].ireg()));
+ }
+ }
+}
+
+/*-------------------------------------------------
+ cfunc_printf_probe - print the current CPU
+ state and return
+-------------------------------------------------*/
+
+static void cfunc_printf_probe(void *param)
+{
+ sh2_state *sh2 = (sh2_state *)param;
+ UINT32 pc = sh2->pc;
+
+ printf(" PC=%08X r0=%08X r1=%08X r2=%08X\n",
+ pc,
+ (UINT32)sh2->r[0],
+ (UINT32)sh2->r[1],
+ (UINT32)sh2->r[2]);
+ printf(" r3=%08X r4=%08X r5=%08X r6=%08X\n",
+ (UINT32)sh2->r[3],
+ (UINT32)sh2->r[4],
+ (UINT32)sh2->r[5],
+ (UINT32)sh2->r[6]);
+ printf(" r7=%08X r8=%08X r9=%08X r10=%08X\n",
+ (UINT32)sh2->r[7],
+ (UINT32)sh2->r[8],
+ (UINT32)sh2->r[9],
+ (UINT32)sh2->r[10]);
+ printf(" r11=%08X r12=%08X r13=%08X r14=%08X\n",
+ (UINT32)sh2->r[11],
+ (UINT32)sh2->r[12],
+ (UINT32)sh2->r[13],
+ (UINT32)sh2->r[14]);
+ printf(" r15=%08X macl=%08X mach=%08X gbr=%08X\n",
+ (UINT32)sh2->r[15],
+ (UINT32)sh2->macl,
+ (UINT32)sh2->mach,
+ (UINT32)sh2->gbr);
+ printf(" evec %x irqsr %x pc=%08x\n",
+ (UINT32)sh2->evec,
+ (UINT32)sh2->irqsr, (UINT32)sh2->pc);
+}
+
+/*-------------------------------------------------
+ cfunc_unimplemented - handler for
+ unimplemented opcdes
+-------------------------------------------------*/
+
+static void cfunc_unimplemented(void *param)
+{
+ sh2_state *sh2 = (sh2_state *)param;
+ UINT16 opcode = sh2->arg0;
+ fatalerror("PC=%08X: Unimplemented op %04X", sh2->pc, opcode);
+}
+
+/*-------------------------------------------------
+ cfunc_checkirqs - checks for pending IRQs
+-------------------------------------------------*/
+static void cfunc_checkirqs(void *param)
+{
+ sh2_state *sh2 = (sh2_state *)param;
+ // if NMI is pending, evec etc are already set up
+ if (sh2->pending_nmi)
+ {
+ sh2->pending_nmi = 0;
+ }
+ else
+ {
+ sh2->evec = 0xffffffff;
+ CHECK_PENDING_IRQ("cfunc_checkirqs");
+ }
+}
+
+/*-------------------------------------------------
+ cfunc_fastirq - checks for pending IRQs
+-------------------------------------------------*/
+static void cfunc_fastirq(void *param)
+{
+ sh2_state *sh2 = (sh2_state *)param;
+ sh2_exception(sh2, "fastirq",sh2->irqline);
+}
+
+/*-------------------------------------------------
+ cfunc_MAC_W - implementation of MAC_W Rm,Rn
+-------------------------------------------------*/
+static void cfunc_MAC_W(void *param)
+{
+ sh2_state *sh2 = (sh2_state *)param;
+ INT32 tempm, tempn, dest, src, ans;
+ UINT32 templ;
+ UINT16 opcode;
+ int n, m;
+
+ // recover the opcode
+ opcode = sh2->arg0;
+
+ // extract the operands
+ n = Rn;
+ m = Rm;
+
+ tempn = (INT32) RW( sh2, sh2->r[n] );
+ sh2->r[n] += 2;
+ tempm = (INT32) RW( sh2, sh2->r[m] );
+ sh2->r[m] += 2;
+ templ = sh2->macl;
+ tempm = ((INT32) (short) tempn * (INT32) (short) tempm);
+ if ((INT32) sh2->macl >= 0)
+ dest = 0;
+ else
+ dest = 1;
+ if ((INT32) tempm >= 0)
+ {
+ src = 0;
+ tempn = 0;
+ }
+ else
+ {
+ src = 1;
+ tempn = 0xffffffff;
+ }
+ src += dest;
+ sh2->macl += tempm;
+ if ((INT32) sh2->macl >= 0)
+ ans = 0;
+ else
+ ans = 1;
+ ans += dest;
+ if (sh2->sr & S)
+ {
+ if (ans == 1)
+ {
+ if ((sh2->cpu_type == CPU_TYPE_SH1) && ((src == 0) || (src == 2)))
+ {
+ sh2->mach |= 0x00000001;
+ }
+
+ if (src == 0)
+ sh2->macl = 0x7fffffff;
+ if (src == 2)
+ sh2->macl = 0x80000000;
+ }
+ }
+ else
+ {
+ sh2->mach += tempn;
+ if (templ > sh2->macl)
+ sh2->mach += 1;
+
+ // SH-1 has limited precision
+ if (sh2->cpu_type == CPU_TYPE_SH1)
+ {
+ if ((sh2->mach & 0x200) == 0)
+ {
+ sh2->mach &= 0x3ff;
+ }
+ else
+ {
+ sh2->mach |= 0xfffffc00;
+ }
+ }
+
+
+ }
+}
+
+/*-------------------------------------------------
+ cfunc_MAC_L - implementation of MAC_L Rm,Rn
+-------------------------------------------------*/
+static void cfunc_MAC_L(void *param)
+{
+ sh2_state *sh2 = (sh2_state *)param;
+ UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2;
+ UINT32 temp0, temp1, temp2, temp3;
+ INT32 tempm, tempn, fnLmL;
+ UINT16 opcode;
+ int n, m;
+
+ // recover the opcode
+ opcode = sh2->arg0;
+
+ // extract the operands
+ n = Rn;
+ m = Rm;
+
+ tempn = (INT32) RL( sh2, sh2->r[n] );
+ sh2->r[n] += 4;
+ tempm = (INT32) RL( sh2, sh2->r[m] );
+ sh2->r[m] += 4;
+ if ((INT32) (tempn ^ tempm) < 0)
+ fnLmL = -1;
+ else
+ fnLmL = 0;
+ if (tempn < 0)
+ tempn = 0 - tempn;
+ if (tempm < 0)
+ tempm = 0 - tempm;
+ temp1 = (UINT32) tempn;
+ temp2 = (UINT32) tempm;
+ RnL = temp1 & 0x0000ffff;
+ RnH = (temp1 >> 16) & 0x0000ffff;
+ RmL = temp2 & 0x0000ffff;
+ RmH = (temp2 >> 16) & 0x0000ffff;
+ temp0 = RmL * RnL;
+ temp1 = RmH * RnL;
+ temp2 = RmL * RnH;
+ temp3 = RmH * RnH;
+ Res2 = 0;
+ Res1 = temp1 + temp2;
+ if (Res1 < temp1)
+ Res2 += 0x00010000;
+ temp1 = (Res1 << 16) & 0xffff0000;
+ Res0 = temp0 + temp1;
+ if (Res0 < temp0)
+ Res2++;
+ Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3;
+ if (fnLmL < 0)
+ {
+ Res2 = ~Res2;
+ if (Res0 == 0)
+ Res2++;
+ else
+ Res0 = (~Res0) + 1;
+ }
+ if (sh2->sr & S)
+ {
+ Res0 = sh2->macl + Res0;
+ if (sh2->macl > Res0)
+ Res2++;
+ Res2 += (sh2->mach & 0x0000ffff);
+ if (((INT32) Res2 < 0) && (Res2 < 0xffff8000))
+ {
+ Res2 = 0x00008000;
+ Res0 = 0x00000000;
+ }
+ else if (((INT32) Res2 > 0) && (Res2 > 0x00007fff))
+ {
+ Res2 = 0x00007fff;
+ Res0 = 0xffffffff;
+ }
+ sh2->mach = Res2;
+ sh2->macl = Res0;
+ }
+ else
+ {
+ Res0 = sh2->macl + Res0;
+ if (sh2->macl > Res0)
+ Res2++;
+ Res2 += sh2->mach;
+ sh2->mach = Res2;
+ sh2->macl = Res0;
+ }
+}
+
+/*-------------------------------------------------
+ cfunc_DIV1 - implementation of DIV1 Rm,Rn
+-------------------------------------------------*/
+static void cfunc_DIV1(void *param)
+{
+ sh2_state *sh2 = (sh2_state *)param;
+ UINT32 tmp0;
+ UINT32 old_q;
+ UINT16 opcode;
+ int n, m;
+
+ // recover the opcode
+ opcode = sh2->arg0;
+
+ // extract the operands
+ n = Rn;
+ m = Rm;
+
+ old_q = sh2->sr & Q;
+ if (0x80000000 & sh2->r[n])
+ sh2->sr |= Q;
+ else
+ sh2->sr &= ~Q;
+
+ sh2->r[n] = (sh2->r[n] << 1) | (sh2->sr & T);
+
+ if (!old_q)
+ {
+ if (!(sh2->sr & M))
+ {
+ tmp0 = sh2->r[n];
+ sh2->r[n] -= sh2->r[m];
+ if(!(sh2->sr & Q))
+ if(sh2->r[n] > tmp0)
+ sh2->sr |= Q;
+ else
+ sh2->sr &= ~Q;
+ else
+ if(sh2->r[n] > tmp0)
+ sh2->sr &= ~Q;
+ else
+ sh2->sr |= Q;
+ }
+ else
+ {
+ tmp0 = sh2->r[n];
+ sh2->r[n] += sh2->r[m];
+ if(!(sh2->sr & Q))
+ {
+ if(sh2->r[n] < tmp0)
+ sh2->sr &= ~Q;
+ else
+ sh2->sr |= Q;
+ }
+ else
+ {
+ if(sh2->r[n] < tmp0)
+ sh2->sr |= Q;
+ else
+ sh2->sr &= ~Q;
+ }
+ }
+ }
+ else
+ {
+ if (!(sh2->sr & M))
+ {
+ tmp0 = sh2->r[n];
+ sh2->r[n] += sh2->r[m];
+ if(!(sh2->sr & Q))
+ if(sh2->r[n] < tmp0)
+ sh2->sr |= Q;
+ else
+ sh2->sr &= ~Q;
+ else
+ if(sh2->r[n] < tmp0)
+ sh2->sr &= ~Q;
+ else
+ sh2->sr |= Q;
+ }
+ else
+ {
+ tmp0 = sh2->r[n];
+ sh2->r[n] -= sh2->r[m];
+ if(!(sh2->sr & Q))
+ if(sh2->r[n] > tmp0)
+ sh2->sr &= ~Q;
+ else
+ sh2->sr |= Q;
+ else
+ if(sh2->r[n] > tmp0)
+ sh2->sr |= Q;
+ else
+ sh2->sr &= ~Q;
+ }
+ }
+
+ tmp0 = (sh2->sr & (Q | M));
+ if((!tmp0) || (tmp0 == 0x300)) /* if Q == M set T else clear T */
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+}
+
+#if (!ADDSUBV_DIRECT)
+/*-------------------------------------------------
+ cfunc_ADDV - implementation of ADDV Rm,Rn
+-------------------------------------------------*/
+static void cfunc_ADDV(void *param)
+{
+ sh2_state *sh2 = (sh2_state *)param;
+ INT32 dest, src, ans;
+ UINT16 opcode;
+ int n, m;
+
+ // recover the opcode
+ opcode = sh2->arg0;
+
+ // extract the operands
+ n = Rn;
+ m = Rm;
+
+ if ((INT32) sh2->r[n] >= 0)
+ dest = 0;
+ else
+ dest = 1;
+ if ((INT32) sh2->r[m] >= 0)
+ src = 0;
+ else
+ src = 1;
+ src += dest;
+ sh2->r[n] += sh2->r[m];
+ if ((INT32) sh2->r[n] >= 0)
+ ans = 0;
+ else
+ ans = 1;
+ ans += dest;
+ if (src == 0 || src == 2)
+ {
+ if (ans == 1)
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+ }
+ else
+ sh2->sr &= ~T;
+}
+
+/*-------------------------------------------------
+ cfunc_SUBV - implementation of SUBV Rm,Rn
+-------------------------------------------------*/
+static void cfunc_SUBV(void *param)
+{
+ sh2_state *sh2 = (sh2_state *)param;
+ INT32 dest, src, ans;
+ UINT16 opcode;
+ int n, m;
+
+ // recover the opcode
+ opcode = sh2->arg0;
+
+ // extract the operands
+ n = Rn;
+ m = Rm;
+
+ if ((INT32) sh2->r[n] >= 0)
+ dest = 0;
+ else
+ dest = 1;
+ if ((INT32) sh2->r[m] >= 0)
+ src = 0;
+ else
+ src = 1;
+ src += dest;
+ sh2->r[n] -= sh2->r[m];
+ if ((INT32) sh2->r[n] >= 0)
+ ans = 0;
+ else
+ ans = 1;
+ ans += dest;
+ if (src == 1)
+ {
+ if (ans == 1)
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+ }
+ else
+ sh2->sr &= ~T;
+}
+#endif
+
+/*-------------------------------------------------
+ sh2_init - initialize the processor
+-------------------------------------------------*/
+
+static CPU_INIT( sh2 )
+{
+ sh2_state *sh2 = get_safe_token(device);
+ 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(sh2_state)));
+
+ /* allocate the core memory */
+ *(sh2_state **)device->token() = sh2 = (sh2_state *)cache->alloc_near(sizeof(sh2_state));
+ memset(sh2, 0, sizeof(sh2_state));
+
+ /* initialize the common core parts */
+ sh2_common_init(sh2, device, irqcallback);
+
+ /* allocate the implementation-specific state from the full cache */
+ sh2->cache = cache;
+
+ /* reset per-driver pcflushes */
+ sh2->pcfsel = 0;
+
+ /* 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;
+ sh2->drcuml = auto_alloc(device->machine(), drcuml_state(*device, *cache, flags, 1, 32, 1));
+
+ /* add symbols for our stuff */
+ sh2->drcuml->symbol_add(&sh2->pc, sizeof(sh2->pc), "pc");
+ sh2->drcuml->symbol_add(&sh2->icount, sizeof(sh2->icount), "icount");
+ for (regnum = 0; regnum < 16; regnum++)
+ {
+ char buf[10];
+ sprintf(buf, "r%d", regnum);
+ sh2->drcuml->symbol_add(&sh2->r[regnum], sizeof(sh2->r[regnum]), buf);
+ }
+ sh2->drcuml->symbol_add(&sh2->pr, sizeof(sh2->pr), "pr");
+ sh2->drcuml->symbol_add(&sh2->sr, sizeof(sh2->sr), "sr");
+ sh2->drcuml->symbol_add(&sh2->gbr, sizeof(sh2->gbr), "gbr");
+ sh2->drcuml->symbol_add(&sh2->vbr, sizeof(sh2->vbr), "vbr");
+ sh2->drcuml->symbol_add(&sh2->macl, sizeof(sh2->macl), "macl");
+ sh2->drcuml->symbol_add(&sh2->mach, sizeof(sh2->macl), "mach");
+
+ /* initialize the front-end helper */
+ sh2->drcfe = auto_alloc(device->machine(), sh2_frontend(*sh2, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE));
+
+ /* compute the register parameters */
+ for (regnum = 0; regnum < 16; regnum++)
+ {
+ sh2->regmap[regnum] = mem(&sh2->r[regnum]);
+ }
+
+ /* if we have registers to spare, assign r0, r1, r2 to leftovers */
+ /* WARNING: do not use synthetic registers that are mapped here! */
+ if (!DISABLE_FAST_REGISTERS)
+ {
+ sh2->drcuml->get_backend_info(beinfo);
+ if (beinfo.direct_iregs > 4)
+ {
+ sh2->regmap[0] = I4;
+ }
+ if (beinfo.direct_iregs > 5)
+ {
+ sh2->regmap[1] = I5;
+ }
+ if (beinfo.direct_iregs > 6)
+ {
+ sh2->regmap[2] = I6;
+ }
+ }
+
+ /* mark the cache dirty so it is updated on next execute */
+ sh2->cache_dirty = TRUE;
+}
+
+/*-------------------------------------------------
+ sh2_exit - cleanup from execution
+-------------------------------------------------*/
+
+static CPU_EXIT( sh2 )
+{
+ sh2_state *sh2 = get_safe_token(device);
+
+ /* clean up the DRC */
+ auto_free(device->machine(), sh2->drcfe);
+ auto_free(device->machine(), sh2->drcuml);
+ auto_free(device->machine(), sh2->cache);
+}
+
+
+/*-------------------------------------------------
+ sh2_reset - reset the processor
+-------------------------------------------------*/
+
+static CPU_RESET( sh2 )
+{
+ sh2_state *sh2 = get_safe_token(device);
+ emu_timer *tsave, *tsaved0, *tsaved1;
+ UINT32 *m;
+
+ void (*f)(UINT32 data);
+ device_irq_callback save_irqcallback;
+
+ m = sh2->m;
+ tsave = sh2->timer;
+ tsaved0 = sh2->dma_current_active_timer[0];
+ tsaved1 = sh2->dma_current_active_timer[1];
+
+ f = sh2->ftcsr_read_callback;
+ save_irqcallback = sh2->irq_callback;
+
+ sh2->ppc = sh2->pc = sh2->pr = sh2->sr = sh2->gbr = sh2->vbr = sh2->mach = sh2->macl = 0;
+ sh2->evec = sh2->irqsr = 0;
+ memset(&sh2->r[0], 0, sizeof(sh2->r[0])*16);
+ sh2->ea = sh2->delay = sh2->cpu_off = sh2->dvsr = sh2->dvdnth = sh2->dvdntl = sh2->dvcr = 0;
+ sh2->pending_irq = sh2->test_irq = 0;
+ memset(&sh2->irq_queue[0], 0, sizeof(sh2->irq_queue[0])*16);
+ memset(&sh2->irq_line_state[0], 0, sizeof(sh2->irq_line_state[0])*17);
+ sh2->frc = sh2->ocra = sh2->ocrb = sh2->icr = 0;
+ sh2->frc_base = 0;
+ sh2->frt_input = sh2->internal_irq_level = sh2->internal_irq_vector = 0;
+ sh2->dma_timer_active[0] = sh2->dma_timer_active[1] = 0;
+
+ sh2->ftcsr_read_callback = f;
+ sh2->irq_callback = save_irqcallback;
+ sh2->device = device;
+
+ sh2->timer = tsave;
+ sh2->dma_current_active_timer[0] = tsaved0;
+ sh2->dma_current_active_timer[1] = tsaved1;
+ sh2->m = m;
+ memset(sh2->m, 0, 0x200);
+
+ sh2->pc = sh2->program->read_dword(0);
+ sh2->r[15] = sh2->program->read_dword(4);
+ sh2->sr = I;
+
+ sh2->internal_irq_level = -1;
+
+ sh2->cache_dirty = TRUE;
+
+ sh2->cpu_type = CPU_TYPE_SH2;
+}
+
+/*-------------------------------------------------
+ sh1_reset - reset the processor
+-------------------------------------------------*/
+
+static CPU_RESET( sh1 )
+{
+ sh2_state *sh2 = get_safe_token(device);
+ CPU_RESET_CALL(sh2);
+ sh2->cpu_type = CPU_TYPE_SH1;
+}
+
+/*-------------------------------------------------
+ code_flush_cache - flush the cache and
+ regenerate static code
+-------------------------------------------------*/
+
+static void code_flush_cache(sh2_state *sh2)
+{
+ drcuml_state *drcuml = sh2->drcuml;
+
+ /* empty the transient cache contents */
+ drcuml->reset();
+
+ try
+ {
+ /* generate the entry point and out-of-cycles handlers */
+ static_generate_nocode_handler(sh2);
+ static_generate_out_of_cycles(sh2);
+ static_generate_entry_point(sh2);
+
+ /* add subroutines for memory accesses */
+ static_generate_memory_accessor(sh2, 1, FALSE, "read8", &sh2->read8);
+ static_generate_memory_accessor(sh2, 1, TRUE, "write8", &sh2->write8);
+ static_generate_memory_accessor(sh2, 2, FALSE, "read16", &sh2->read16);
+ static_generate_memory_accessor(sh2, 2, TRUE, "write16", &sh2->write16);
+ static_generate_memory_accessor(sh2, 4, FALSE, "read32", &sh2->read32);
+ static_generate_memory_accessor(sh2, 4, TRUE, "write32", &sh2->write32);
+ }
+ catch (drcuml_block::abort_compilation &)
+ {
+ fatalerror("Unable to generate SH2 static code");
+ }
+
+ sh2->cache_dirty = FALSE;
+}
+
+/* Execute cycles - returns number of cycles actually run */
+static CPU_EXECUTE( sh2 )
+{
+ sh2_state *sh2 = get_safe_token(device);
+ drcuml_state *drcuml = sh2->drcuml;
+ int execute_result;
+
+ // run any active DMAs now
+#ifndef USE_TIMER_FOR_DMA
+ for ( int i = 0; i < sh2->icount ; i++)
+ {
+ for( int dma=0;dma<1;dma++)
+ {
+ if (sh2->dma_timer_active[dma])
+ sh2_do_dma(sh2, dma);
+ }
+ }
+#endif
+
+ /* reset the cache if dirty */
+ if (sh2->cache_dirty)
+ code_flush_cache(sh2);
+
+ /* execute */
+ do
+ {
+ /* run as much as we can */
+ execute_result = drcuml->execute(*sh2->entry);
+
+ /* if we need to recompile, do it */
+ if (execute_result == EXECUTE_MISSING_CODE)
+ {
+ code_compile_block(sh2, 0, sh2->pc);
+ }
+ else if (execute_result == EXECUTE_UNMAPPED_CODE)
+ {
+ fatalerror("Attempted to execute unmapped code at PC=%08X\n", sh2->pc);
+ }
+ else if (execute_result == EXECUTE_RESET_CACHE)
+ {
+ code_flush_cache(sh2);
+ }
+ } while (execute_result != EXECUTE_OUT_OF_CYCLES);
+}
+
+/*-------------------------------------------------
+ code_compile_block - compile a block of the
+ given mode at the specified pc
+-------------------------------------------------*/
+
+static void code_compile_block(sh2_state *sh2, UINT8 mode, offs_t pc)
+{
+ drcuml_state *drcuml = sh2->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 = sh2->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, 0, seqhead->pc, *sh2->nocode);
+ // hashjmp <mode>,seqhead->pc,nocode
+ continue;
+ }
+
+ /* validate this code block if we're not pointing into ROM */
+ if (sh2->program->get_write_ptr(seqhead->physpc) != NULL)
+ generate_checksum_block(sh2, 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(sh2, block, &compiler, curdesc, 0xffffffff);
+ }
+
+ /* 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) * 2;
+ }
+
+ /* count off cycles and go there */
+ generate_update_cycles(sh2, block, &compiler, nextpc, TRUE); // <subtract cycles>
+
+ /* SH2 has no modes */
+ if (seqlast->next() == NULL || seqlast->next()->pc != nextpc)
+ {
+ UML_HASHJMP(block, 0, nextpc, *sh2->nocode);
+ }
+ // hashjmp <mode>,nextpc,nocode
+ }
+
+ /* end the sequence */
+ block->end();
+ g_profiler.stop();
+ succeeded = true;
+ }
+ catch (drcuml_block::abort_compilation &)
+ {
+ code_flush_cache(sh2);
+ }
+ }
+}
+
+/*-------------------------------------------------
+ static_generate_entry_point - generate a
+ static entry point
+-------------------------------------------------*/
+
+static void static_generate_entry_point(sh2_state *sh2)
+{
+ drcuml_state *drcuml = sh2->drcuml;
+ code_label skip = 1;
+ drcuml_block *block;
+
+ /* begin generating */
+ block = drcuml->begin_block(200);
+
+ /* forward references */
+ alloc_handle(drcuml, &sh2->nocode, "nocode");
+ alloc_handle(drcuml, &sh2->write32, "write32"); // necessary?
+ alloc_handle(drcuml, &sh2->entry, "entry");
+ UML_HANDLE(block, *sh2->entry); // handle entry
+
+ /* load fast integer registers */
+ load_fast_iregs(sh2, block);
+
+ /* check for interrupts */
+ UML_MOV(block, mem(&sh2->irqline), 0xffffffff); // mov irqline, #-1
+ UML_CMP(block, mem(&sh2->pending_nmi), 0); // cmp pending_nmi, #0
+ UML_JMPc(block, COND_Z, skip+2); // jz skip+2
+
+ UML_MOV(block, mem(&sh2->pending_nmi), 0); // zap pending_nmi
+ UML_JMP(block, skip+1); // and then go take it (evec is already set)
+
+ UML_LABEL(block, skip+2); // skip+2:
+ UML_MOV(block, mem(&sh2->evec), 0xffffffff); // mov evec, -1
+ UML_MOV(block, I0, 0xffffffff); // mov r0, -1 (r0 = irq)
+ UML_AND(block, I1, I0, 0xffff); // and r1, 0xffff
+
+ UML_LZCNT(block, I1, mem(&sh2->pending_irq)); // lzcnt r1, r1
+ UML_CMP(block, I1, 32); // cmp r1, #32
+ UML_JMPc(block, COND_Z, skip+4); // jz skip+4
+
+ UML_SUB(block, mem(&sh2->irqline), 31, I1); // sub irqline, #31, r1
+
+ UML_LABEL(block, skip+4); // skip+4:
+ UML_CMP(block, mem(&sh2->internal_irq_level), 0xffffffff); // cmp internal_irq_level, #-1
+ UML_JMPc(block, COND_Z, skip+3); // jz skip+3
+ UML_CMP(block, mem(&sh2->internal_irq_level), mem(&sh2->irqline)); // cmp internal_irq_level, irqline
+ UML_JMPc(block, COND_LE, skip+3); // jle skip+3
+
+ UML_MOV(block, mem(&sh2->irqline), mem(&sh2->internal_irq_level)); // mov r0, internal_irq_level
+
+ UML_LABEL(block, skip+3); // skip+3:
+ UML_CMP(block, mem(&sh2->irqline), 0xffffffff); // cmp irqline, #-1
+ UML_JMPc(block, COND_Z, skip+1); // jz skip+1
+ UML_CALLC(block, cfunc_fastirq, sh2); // callc fastirq
+
+ UML_LABEL(block, skip+1); // skip+1:
+
+ UML_CMP(block, mem(&sh2->evec), 0xffffffff); // cmp evec, 0xffffffff
+ UML_JMPc(block, COND_Z, skip); // jz skip
+
+ UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4
+ UML_MOV(block, I0, R32(15)); // mov r0, R15
+ UML_MOV(block, I1, mem(&sh2->irqsr)); // mov r1, irqsr
+ UML_CALLH(block, *sh2->write32); // call write32
+
+ UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4
+ UML_MOV(block, I0, R32(15)); // mov r0, R15
+ UML_MOV(block, I1, mem(&sh2->pc)); // mov r1, pc
+ UML_CALLH(block, *sh2->write32); // call write32
+
+ UML_MOV(block, mem(&sh2->pc), mem(&sh2->evec)); // mov pc, evec
+
+ UML_LABEL(block, skip); // skip:
+
+ /* generate a hash jump via the current mode and PC */
+ UML_HASHJMP(block, 0, mem(&sh2->pc), *sh2->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(sh2_state *sh2)
+{
+ drcuml_state *drcuml = sh2->drcuml;
+ drcuml_block *block;
+
+ /* begin generating */
+ block = drcuml->begin_block(10);
+
+ /* generate a hash jump via the current mode and PC */
+ alloc_handle(drcuml, &sh2->nocode, "nocode");
+ UML_HANDLE(block, *sh2->nocode); // handle nocode
+ UML_GETEXP(block, I0); // getexp i0
+ UML_MOV(block, mem(&sh2->pc), I0); // mov [pc],i0
+ save_fast_iregs(sh2, 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(sh2_state *sh2)
+{
+ drcuml_state *drcuml = sh2->drcuml;
+ drcuml_block *block;
+
+ /* begin generating */
+ block = drcuml->begin_block(10);
+
+ /* generate a hash jump via the current mode and PC */
+ alloc_handle(drcuml, &sh2->out_of_cycles, "out_of_cycles");
+ UML_HANDLE(block, *sh2->out_of_cycles); // handle out_of_cycles
+ UML_GETEXP(block, I0); // getexp i0
+ UML_MOV(block, mem(&sh2->pc), I0); // mov <pc>,i0
+ save_fast_iregs(sh2,block);
+ UML_EXIT(block, EXECUTE_OUT_OF_CYCLES); // exit EXECUTE_OUT_OF_CYCLES
+
+ block->end();
+}
+
+/*------------------------------------------------------------------
+ static_generate_memory_accessor
+------------------------------------------------------------------*/
+
+static void static_generate_memory_accessor(sh2_state *sh2, int size, int iswrite, const char *name, code_handle **handleptr)
+{
+ /* on entry, address is in I0; data for writes is in I1 */
+ /* on exit, read result is in I0 */
+ /* routine trashes I0 */
+ drcuml_state *drcuml = sh2->drcuml;
+ drcuml_block *block;
+ int label = 1;
+
+ /* begin generating */
+ block = drcuml->begin_block(1024);
+
+ /* add a global entry for this */
+ alloc_handle(drcuml, handleptr, name);
+ UML_HANDLE(block, **handleptr); // handle *handleptr
+
+ // with internal handlers this becomes easier.
+ // if addr < 0x40000000 AND it with AM and do the read/write, else just do the read/write
+ UML_TEST(block, I0, 0x80000000); // test r0, #0x80000000
+ UML_JMPc(block, COND_NZ, label); // if high bit is set, don't mask
+
+ UML_CMP(block, I0, 0x40000000); // cmp #0x40000000, r0
+ UML_JMPc(block, COND_AE, label); // bae label
+
+ UML_AND(block, I0, I0, AM); // and r0, r0, #AM (0xc7ffffff)
+
+ UML_LABEL(block, label++); // label:
+
+ if (iswrite)
+ {
+ switch (size)
+ {
+ case 1:
+ UML_WRITE(block, I0, I1, SIZE_BYTE, SPACE_PROGRAM); // write r0, r1, program_byte
+ break;
+
+ case 2:
+ UML_WRITE(block, I0, I1, SIZE_WORD, SPACE_PROGRAM); // write r0, r1, program_word
+ break;
+
+ case 4:
+ UML_WRITE(block, I0, I1, SIZE_DWORD, SPACE_PROGRAM); // write r0, r1, program_dword
+ break;
+ }
+ }
+ else
+ {
+ switch (size)
+ {
+ case 1:
+ UML_READ(block, I0, I0, SIZE_BYTE, SPACE_PROGRAM); // read r0, program_byte
+ break;
+
+ case 2:
+ UML_READ(block, I0, I0, SIZE_WORD, SPACE_PROGRAM); // read r0, program_word
+ break;
+
+ case 4:
+ UML_READ(block, I0, I0, SIZE_DWORD, SPACE_PROGRAM); // read r0, program_dword
+ break;
+ }
+ }
+
+ UML_RET(block); // ret
+
+ block->end();
+}
+
+/*-------------------------------------------------
+ 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 = 0; regnum < 16; 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("*");
+ }
+ }
+
+ if (reglist[1] & REGFLAG_PR)
+ {
+ drcuml->log_printf("%spr", (count++ == 0) ? "" : ",");
+ if (regnostarlist != NULL && !(regnostarlist[1] & REGFLAG_PR))
+ drcuml->log_printf("*");
+ }
+
+ if (reglist[1] & REGFLAG_SR)
+ {
+ drcuml->log_printf("%ssr", (count++ == 0) ? "" : ",");
+ if (regnostarlist != NULL && !(regnostarlist[1] & REGFLAG_SR))
+ drcuml->log_printf("*");
+ }
+
+ if (reglist[1] & REGFLAG_MACL)
+ {
+ drcuml->log_printf("%smacl", (count++ == 0) ? "" : ",");
+ if (regnostarlist != NULL && !(regnostarlist[1] & REGFLAG_MACL))
+ drcuml->log_printf("*");
+ }
+
+ if (reglist[1] & REGFLAG_MACH)
+ {
+ drcuml->log_printf("%smach", (count++ == 0) ? "" : ",");
+ if (regnostarlist != NULL && !(regnostarlist[1] & REGFLAG_MACH))
+ drcuml->log_printf("*");
+ }
+
+ if (reglist[1] & REGFLAG_GBR)
+ {
+ drcuml->log_printf("%sgbr", (count++ == 0) ? "" : ",");
+ if (regnostarlist != NULL && !(regnostarlist[1] & REGFLAG_GBR))
+ drcuml->log_printf("*");
+ }
+
+ if (reglist[1] & REGFLAG_VBR)
+ {
+ drcuml->log_printf("%svbr", (count++ == 0) ? "" : ",");
+ if (regnostarlist != NULL && !(regnostarlist[1] & REGFLAG_VBR))
+ 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
+ DasmSH2(buffer, desclist->pc, desclist->opptr.w[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");
+ }
+}
+
+/*-------------------------------------------------
+ log_add_disasm_comment - add a comment
+ including disassembly of a MIPS instruction
+-------------------------------------------------*/
+
+static void log_add_disasm_comment(drcuml_block *block, UINT32 pc, UINT32 op)
+{
+#if (LOG_UML)
+ char buffer[100];
+ DasmSH2(buffer, pc, op);
+ block->append_comment("%08X: %s", pc, buffer); // comment
+#endif
+}
+
+/*-------------------------------------------------
+ generate_update_cycles - generate code to
+ subtract cycles from the icount and generate
+ an exception if out
+-------------------------------------------------*/
+static void generate_update_cycles(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, parameter param, int allow_exception)
+{
+ /* check full interrupts if pending */
+ if (compiler->checkints)
+ {
+ code_label skip = compiler->labelnum++;
+
+ compiler->checkints = FALSE;
+ compiler->labelnum += 4;
+
+ /* check for interrupts */
+ UML_MOV(block, mem(&sh2->irqline), 0xffffffff); // mov irqline, #-1
+ UML_CMP(block, mem(&sh2->pending_nmi), 0); // cmp pending_nmi, #0
+ UML_JMPc(block, COND_Z, skip+2); // jz skip+2
+
+ UML_MOV(block, mem(&sh2->pending_nmi), 0); // zap pending_nmi
+ UML_JMP(block, skip+1); // and then go take it (evec is already set)
+
+ UML_LABEL(block, skip+2); // skip+2:
+ UML_MOV(block, mem(&sh2->evec), 0xffffffff); // mov evec, -1
+ UML_MOV(block, I0, 0xffffffff); // mov r0, -1 (r0 = irq)
+ UML_AND(block, I1, I0, 0xffff); // and r1, r0, 0xffff
+
+ UML_LZCNT(block, I1, mem(&sh2->pending_irq)); // lzcnt r1, pending_irq
+ UML_CMP(block, I1, 32); // cmp r1, #32
+ UML_JMPc(block, COND_Z, skip+4); // jz skip+4
+
+ UML_SUB(block, mem(&sh2->irqline), 31, I1); // sub irqline, #31, r1
+
+ UML_LABEL(block, skip+4); // skip+4:
+ UML_CMP(block, mem(&sh2->internal_irq_level), 0xffffffff); // cmp internal_irq_level, #-1
+ UML_JMPc(block, COND_Z, skip+3); // jz skip+3
+ UML_CMP(block, mem(&sh2->internal_irq_level), mem(&sh2->irqline)); // cmp internal_irq_level, irqline
+ UML_JMPc(block, COND_LE, skip+3); // jle skip+3
+
+ UML_MOV(block, mem(&sh2->irqline), mem(&sh2->internal_irq_level)); // mov r0, internal_irq_level
+
+ UML_LABEL(block, skip+3); // skip+3:
+ UML_CMP(block, mem(&sh2->irqline), 0xffffffff); // cmp irqline, #-1
+ UML_JMPc(block, COND_Z, skip+1); // jz skip+1
+ UML_CALLC(block, cfunc_fastirq, sh2); // callc fastirq
+
+ UML_LABEL(block, skip+1); // skip+1:
+ UML_CMP(block, mem(&sh2->evec), 0xffffffff); // cmp evec, 0xffffffff
+ UML_JMPc(block, COND_Z, skip); // jz skip
+
+ UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4
+ UML_MOV(block, I0, R32(15)); // mov r0, R15
+ UML_MOV(block, I1, mem(&sh2->irqsr)); // mov r1, irqsr
+ UML_CALLH(block, *sh2->write32); // call write32
+
+ UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4
+ UML_MOV(block, I0, R32(15)); // mov r0, R15
+ UML_MOV(block, I1, param); // mov r1, nextpc
+ UML_CALLH(block, *sh2->write32); // call write32
+
+ UML_HASHJMP(block, 0, mem(&sh2->evec), *sh2->nocode); // hashjmp sh2->evec
+
+ UML_LABEL(block, skip); // skip:
+ }
+
+ /* account for cycles */
+ if (compiler->cycles > 0)
+ {
+ UML_SUB(block, mem(&sh2->icount), mem(&sh2->icount), MAPVAR_CYCLES); // sub icount,icount,cycles
+ UML_MAPVAR(block, MAPVAR_CYCLES, 0); // mapvar cycles,0
+ if (allow_exception)
+ UML_EXHc(block, COND_S, *sh2->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(sh2_state *sh2, 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 (!(sh2->drcoptions & SH2DRC_STRICT_VERIFY) || seqhead->next() == NULL)
+ {
+ if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP))
+ {
+ void *base = sh2->direct->read_decrypted_ptr(seqhead->physpc, SH2_CODE_XOR(0));
+ UML_LOAD(block, I0, base, 0, SIZE_WORD, SCALE_x2); // load i0,base,word
+ UML_CMP(block, I0, seqhead->opptr.w[0]); // cmp i0,*opptr
+ UML_EXHc(block, COND_NE, *sh2->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))
+ {
+ base = sh2->direct->read_decrypted_ptr(curdesc->physpc, SH2_CODE_XOR(0));
+ UML_LOAD(block, I0, curdesc->opptr.w, 0, SIZE_WORD, SCALE_x2); // load i0,*opptr,0,word
+ UML_CMP(block, I0, curdesc->opptr.w[0]); // cmp i0,*opptr
+ UML_EXHc(block, COND_NE, *sh2->nocode, epc(seqhead)); // exne nocode,seqhead->pc
+ }
+#else
+ UINT32 sum = 0;
+ void *base = sh2->direct->read_decrypted_ptr(seqhead->physpc, SH2_CODE_XOR(0));
+ UML_LOAD(block, I0, base, 0, SIZE_WORD, SCALE_x4); // load i0,base,word
+ sum += seqhead->opptr.w[0];
+ for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next())
+ if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
+ {
+ base = sh2->direct->read_decrypted_ptr(curdesc->physpc, SH2_CODE_XOR(0));
+ UML_LOAD(block, I1, base, 0, SIZE_WORD, SCALE_x2); // load i1,*opptr,word
+ UML_ADD(block, I0, I0, I1); // add i0,i0,i1
+ sum += curdesc->opptr.w[0];
+ }
+ UML_CMP(block, I0, sum); // cmp i0,sum
+ UML_EXHc(block, COND_NE, *sh2->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(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 ovrpc)
+{
+ offs_t expc;
+
+ /* add an entry for the log */
+ if (LOG_UML && !(desc->flags & OPFLAG_VIRTUAL_NOOP))
+ log_add_disasm_comment(block, desc->pc, desc->opptr.w[0]);
+
+ /* set the PC map variable */
+ expc = (desc->flags & OPFLAG_IN_DELAY_SLOT) ? desc->pc - 1 : desc->pc;
+ UML_MAPVAR(block, MAPVAR_PC, expc); // mapvar PC,expc
+
+ /* accumulate total cycles */
+ compiler->cycles += desc->cycles;
+
+ /* 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(&sh2->pc), desc->pc); // mov [pc],desc->pc
+ UML_CALLC(block, cfunc_printf_probe, sh2); // callc cfunc_printf_probe,sh2
+ }
+
+ /* if we are debugging, call the debugger */
+ if ((sh2->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ {
+ UML_MOV(block, mem(&sh2->pc), desc->pc); // mov [pc],desc->pc
+ save_fast_iregs(sh2, block);
+ UML_DEBUG(block, desc->pc); // debug desc->pc
+ }
+ else // not debug, see what other reasons there are for flushing the PC
+ {
+ if (sh2->drcoptions & SH2DRC_FLUSH_PC) // always flush?
+ {
+ UML_MOV(block, mem(&sh2->pc), desc->pc); // mov sh2->pc, desc->pc
+ }
+ else // check for driver-selected flushes
+ {
+ int pcflush;
+
+ for (pcflush = 0; pcflush < sh2->pcfsel; pcflush++)
+ {
+ if (desc->pc == sh2->pcflushes[pcflush])
+ {
+ UML_MOV(block, mem(&sh2->pc), desc->pc); // mov sh2->pc, desc->pc
+ }
+ }
+ }
+ }
+
+
+ /* if we hit an unmapped address, fatal error */
+ if (desc->flags & OPFLAG_COMPILER_UNMAPPED)
+ {
+ UML_MOV(block, mem(&sh2->pc), desc->pc); // mov [pc],desc->pc
+ save_fast_iregs(sh2, block);
+ UML_EXIT(block, EXECUTE_UNMAPPED_CODE); // exit EXECUTE_UNMAPPED_CODE
+ }
+
+ /* if this is an invalid opcode, die */
+ if (desc->flags & OPFLAG_INVALID_OPCODE)
+ {
+ fatalerror("SH2DRC: invalid opcode!\n");
+ }
+
+ /* 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(sh2, block, compiler, desc, ovrpc))
+ {
+ UML_MOV(block, mem(&sh2->pc), desc->pc); // mov [pc],desc->pc
+ UML_MOV(block, mem(&sh2->arg0), desc->opptr.w[0]); // mov [arg0],opcode
+ UML_CALLC(block, cfunc_unimplemented, sh2); // callc cfunc_unimplemented
+ }
+ }
+}
+
+/*------------------------------------------------------------------
+ generate_delay_slot
+------------------------------------------------------------------*/
+
+static void generate_delay_slot(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 ovrpc)
+{
+ compiler_state compiler_temp = *compiler;
+
+ /* compile the delay slot using temporary compiler state */
+ assert(desc->delay.first() != NULL);
+ generate_sequence_instruction(sh2, block, &compiler_temp, desc->delay.first(), ovrpc); // <next instruction>
+
+ /* update the label */
+ compiler->labelnum = compiler_temp.labelnum;
+}
+
+/*-------------------------------------------------
+ generate_opcode - generate code for a specific
+ opcode
+-------------------------------------------------*/
+
+static int generate_opcode(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 ovrpc)
+{
+ UINT32 scratch, scratch2;
+ INT32 disp;
+ UINT16 opcode = desc->opptr.w[0];
+ UINT8 opswitch = opcode >> 12;
+ int in_delay_slot = ((desc->flags & OPFLAG_IN_DELAY_SLOT) != 0);
+
+ switch (opswitch)
+ {
+ case 0:
+ return generate_group_0(sh2, block, compiler, desc, opcode, in_delay_slot, ovrpc);
+
+ case 1: // MOVLS4
+ scratch = (opcode & 0x0f) * 4;
+ UML_ADD(block, I0, R32(Rn), scratch); // add r0, Rn, scratch
+ UML_MOV(block, I1, R32(Rm)); // mov r1, Rm
+ SETEA(0); // set ea for debug
+ UML_CALLH(block, *sh2->write32);
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 2:
+ return generate_group_2(sh2, block, compiler, desc, opcode, in_delay_slot, ovrpc);
+ case 3:
+ return generate_group_3(sh2, block, compiler, desc, opcode, ovrpc);
+ case 4:
+ return generate_group_4(sh2, block, compiler, desc, opcode, in_delay_slot, ovrpc);
+
+ case 5: // MOVLL4
+ scratch = (opcode & 0x0f) * 4;
+ UML_ADD(block, I0, R32(Rm), scratch); // add r0, Rm, scratch
+ SETEA(0); // set ea for debug
+ UML_CALLH(block, *sh2->read32); // call read32
+ UML_MOV(block, R32(Rn), I0); // mov Rn, r0
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 6:
+ return generate_group_6(sh2, block, compiler, desc, opcode, in_delay_slot, ovrpc);
+
+ case 7: // ADDI
+ scratch = opcode & 0xff;
+ scratch2 = (UINT32)(INT32)(INT16)(INT8)scratch;
+ UML_ADD(block, R32(Rn), R32(Rn), scratch2); // add Rn, Rn, scratch2
+ return TRUE;
+
+ case 8:
+ return generate_group_8(sh2, block, compiler, desc, opcode, in_delay_slot, ovrpc);
+
+ case 9: // MOVWI
+ if (ovrpc == 0xffffffff)
+ {
+ scratch = (desc->pc + 2) + ((opcode & 0xff) * 2) + 2;
+ }
+ else
+ {
+ scratch = (ovrpc + 2) + ((opcode & 0xff) * 2) + 2;
+ }
+
+ if (sh2->drcoptions & SH2DRC_STRICT_PCREL)
+ {
+ UML_MOV(block, I0, scratch); // mov r0, scratch
+ SETEA(0); // set ea for debug
+ UML_CALLH(block, *sh2->read16); // read16(r0, r1)
+ UML_SEXT(block, R32(Rn), I0, SIZE_WORD); // sext Rn, r0, WORD
+ }
+ else
+ {
+ scratch2 = (UINT32)(INT32)(INT16) RW(sh2, scratch);
+ UML_MOV(block, R32(Rn), scratch2); // mov Rn, scratch2
+ }
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 10: // BRA
+ disp = ((INT32)opcode << 20) >> 20;
+ sh2->ea = (desc->pc + 2) + disp * 2 + 2; // sh2->ea = pc+4 + disp*2 + 2
+
+ generate_delay_slot(sh2, block, compiler, desc, sh2->ea-2);
+
+ generate_update_cycles(sh2, block, compiler, sh2->ea, TRUE); // <subtract cycles>
+ UML_HASHJMP(block, 0, sh2->ea, *sh2->nocode); // hashjmp sh2->ea
+ return TRUE;
+
+ case 11: // BSR
+ // panicstr @ 403da22 relies on the delay slot clobbering the PR set by a BSR, so
+ // do this before running the delay slot
+ UML_ADD(block, mem(&sh2->pr), desc->pc, 4); // add sh2->pr, desc->pc, #4 (skip the current insn & delay slot)
+
+ disp = ((INT32)opcode << 20) >> 20;
+ sh2->ea = (desc->pc + 2) + disp * 2 + 2; // sh2->ea = pc+4 + disp*2 + 2
+
+ generate_delay_slot(sh2, block, compiler, desc, sh2->ea-2);
+
+ generate_update_cycles(sh2, block, compiler, sh2->ea, TRUE); // <subtract cycles>
+ UML_HASHJMP(block, 0, sh2->ea, *sh2->nocode); // hashjmp sh2->ea
+ return TRUE;
+
+ case 12:
+ return generate_group_12(sh2, block, compiler, desc, opcode, in_delay_slot, ovrpc);
+
+ case 13: // MOVLI
+ if (ovrpc == 0xffffffff)
+ {
+ scratch = ((desc->pc + 4) & ~3) + ((opcode & 0xff) * 4);
+ }
+ else
+ {
+ scratch = ((ovrpc + 4) & ~3) + ((opcode & 0xff) * 4);
+ }
+
+ if (sh2->drcoptions & SH2DRC_STRICT_PCREL)
+ {
+ UML_MOV(block, I0, scratch); // mov r0, scratch
+ UML_CALLH(block, *sh2->read32); // read32(r0, r1)
+ UML_MOV(block, R32(Rn), I0); // mov Rn, r0
+ }
+ else
+ {
+ scratch2 = RL(sh2, scratch);
+ UML_MOV(block, R32(Rn), scratch2); // mov Rn, scratch2
+ }
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 14: // MOVI
+ scratch = opcode & 0xff;
+ scratch2 = (UINT32)(INT32)(INT16)(INT8)scratch;
+ UML_MOV(block, R32(Rn), scratch2);
+ return TRUE;
+
+ case 15: // NOP
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static int generate_group_0(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc)
+{
+ switch (opcode & 0x3F)
+ {
+ case 0x00: // NOP();
+ case 0x01: // NOP();
+ case 0x09: // NOP();
+ case 0x10: // NOP();
+ case 0x11: // NOP();
+ case 0x13: // NOP();
+ case 0x20: // NOP();
+ case 0x21: // NOP();
+ case 0x30: // NOP();
+ case 0x31: // NOP();
+ case 0x32: // NOP();
+ case 0x33: // NOP();
+ case 0x38: // NOP();
+ case 0x39: // NOP();
+ case 0x3a: // NOP();
+ case 0x3b: // NOP();
+ return TRUE;
+
+ case 0x02: // STCSR(Rn);
+ UML_MOV(block, R32(Rn), mem(&sh2->sr));
+ return TRUE;
+
+ case 0x03: // BSRF(Rn);
+ if (sh2->cpu_type > CPU_TYPE_SH1)
+ {
+ UML_ADD(block, mem(&sh2->target), R32(Rn), 4); // add target, Rm, #4
+ UML_ADD(block, mem(&sh2->target), mem(&sh2->target), desc->pc); // add target, target, pc
+
+ // 32x Cosmic Carnage @ 6002cb0 relies on the delay slot
+ // clobbering the calculated PR, so do it first
+ UML_ADD(block, mem(&sh2->pr), desc->pc, 4); // add sh2->pr, desc->pc, #4 (skip the current insn & delay slot)
+
+ generate_delay_slot(sh2, block, compiler, desc, sh2->target);
+
+ generate_update_cycles(sh2, block, compiler, mem(&sh2->target), TRUE); // <subtract cycles>
+ UML_HASHJMP(block, 0, mem(&sh2->target), *sh2->nocode); // jmp target
+ return TRUE;
+ }
+ break;
+
+ case 0x04: // MOVBS0(Rm, Rn);
+ case 0x14: // MOVBS0(Rm, Rn);
+ case 0x24: // MOVBS0(Rm, Rn);
+ case 0x34: // MOVBS0(Rm, Rn);
+ UML_ADD(block, I0, R32(0), R32(Rn)); // add r0, R0, Rn
+ UML_AND(block, I1, R32(Rm), 0x000000ff); // and r1, Rm, 0xff
+ UML_CALLH(block, *sh2->write8); // call write8
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 0x05: // MOVWS0(Rm, Rn);
+ case 0x15: // MOVWS0(Rm, Rn);
+ case 0x25: // MOVWS0(Rm, Rn);
+ case 0x35: // MOVWS0(Rm, Rn);
+ UML_ADD(block, I0, R32(0), R32(Rn)); // add r0, R0, Rn
+ UML_AND(block, I1, R32(Rm), 0x0000ffff); // and r1, Rm, 0xffff
+ UML_CALLH(block, *sh2->write16); // call write16
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 0x06: // MOVLS0(Rm, Rn);
+ case 0x16: // MOVLS0(Rm, Rn);
+ case 0x26: // MOVLS0(Rm, Rn);
+ case 0x36: // MOVLS0(Rm, Rn);
+ UML_ADD(block, I0, R32(0), R32(Rn)); // add r0, R0, Rn
+ UML_MOV(block, I1, R32(Rm)); // mov r1, Rm
+ UML_CALLH(block, *sh2->write32); // call write32
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 0x07: // MULL(Rm, Rn);
+ case 0x17: // MULL(Rm, Rn);
+ case 0x27: // MULL(Rm, Rn);
+ case 0x37: // MULL(Rm, Rn);
+ if (sh2->cpu_type > CPU_TYPE_SH1)
+ {
+ UML_MULU(block, mem(&sh2->macl), mem(&sh2->ea), R32(Rn), R32(Rm)); // mulu macl, ea, Rn, Rm
+ return TRUE;
+ }
+ break;
+
+ case 0x08: // CLRT();
+ UML_AND(block, mem(&sh2->sr), mem(&sh2->sr), ~T); // and r0, sr, ~T (clear the T bit)
+ return TRUE;
+
+ case 0x0a: // STSMACH(Rn);
+ UML_MOV(block, R32(Rn), mem(&sh2->mach)); // mov Rn, mach
+ return TRUE;
+
+ case 0x0b: // RTS();
+ UML_MOV(block, mem(&sh2->target), mem(&sh2->pr)); // mov target, pr (in case of d-slot shenanigans)
+
+ generate_delay_slot(sh2, block, compiler, desc, sh2->target);
+
+ generate_update_cycles(sh2, block, compiler, mem(&sh2->target), TRUE); // <subtract cycles>
+ UML_HASHJMP(block, 0, mem(&sh2->target), *sh2->nocode);
+ return TRUE;
+
+ case 0x0c: // MOVBL0(Rm, Rn);
+ case 0x1c: // MOVBL0(Rm, Rn);
+ case 0x2c: // MOVBL0(Rm, Rn);
+ case 0x3c: // MOVBL0(Rm, Rn);
+ UML_ADD(block, I0, R32(0), R32(Rm)); // add r0, R0, Rm
+ UML_CALLH(block, *sh2->read8); // call read8
+ UML_SEXT(block, R32(Rn), I0, SIZE_BYTE); // sext Rn, r0, BYTE
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 0x0d: // MOVWL0(Rm, Rn);
+ case 0x1d: // MOVWL0(Rm, Rn);
+ case 0x2d: // MOVWL0(Rm, Rn);
+ case 0x3d: // MOVWL0(Rm, Rn);
+ UML_ADD(block, I0, R32(0), R32(Rm)); // add r0, R0, Rm
+ UML_CALLH(block, *sh2->read16); // call read16
+ UML_SEXT(block, R32(Rn), I0, SIZE_WORD); // sext Rn, r0, WORD
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 0x0e: // MOVLL0(Rm, Rn);
+ case 0x1e: // MOVLL0(Rm, Rn);
+ case 0x2e: // MOVLL0(Rm, Rn);
+ case 0x3e: // MOVLL0(Rm, Rn);
+ UML_ADD(block, I0, R32(0), R32(Rm)); // add r0, R0, Rm
+ UML_CALLH(block, *sh2->read32); // call read32
+ UML_MOV(block, R32(Rn), I0); // mov Rn, r0
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 0x0f: // MAC_L(Rm, Rn);
+ case 0x1f: // MAC_L(Rm, Rn);
+ case 0x2f: // MAC_L(Rm, Rn);
+ case 0x3f: // MAC_L(Rm, Rn);
+ if (sh2->cpu_type > CPU_TYPE_SH1)
+ {
+ save_fast_iregs(sh2, block);
+ UML_MOV(block, mem(&sh2->arg0), desc->opptr.w[0]);
+ UML_CALLC(block, cfunc_MAC_L, sh2);
+ load_fast_iregs(sh2, block);
+ return TRUE;
+ }
+ break;
+
+ case 0x12: // STCGBR(Rn);
+ UML_MOV(block, R32(Rn), mem(&sh2->gbr)); // mov Rn, gbr
+ return TRUE;
+
+ case 0x18: // SETT();
+ UML_OR(block, mem(&sh2->sr), mem(&sh2->sr), T); // or sr, sr, T
+ return TRUE;
+
+ case 0x19: // DIV0U();
+ UML_AND(block, mem(&sh2->sr), mem(&sh2->sr), ~(M|Q|T)); // and sr, sr, ~(M|Q|T)
+ return TRUE;
+
+ case 0x1a: // STSMACL(Rn);
+ UML_MOV(block, R32(Rn), mem(&sh2->macl)); // mov Rn, macl
+ return TRUE;
+
+ case 0x1b: // SLEEP();
+ // inlined special version of generate_update_cycles here
+ // if an interrupt is taken, the return address is set to the next instruction
+ UML_CALLC(block, cfunc_checkirqs, sh2);
+
+ UML_MOV(block, I0, mem(&sh2->evec)); // mov r0, evec
+ UML_CMP(block, I0, 0xffffffff); // cmp r0, 0xffffffff
+ UML_JMPc(block, COND_Z, compiler->labelnum); // jz skip
+
+ UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4
+ UML_MOV(block, I0, R32(15)); // mov r0, R15
+ UML_MOV(block, I1, mem(&sh2->irqsr)); // mov r1, irqsr
+ UML_CALLH(block, *sh2->write32); // call write32
+
+ UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4
+ UML_MOV(block, I0, R32(15)); // mov r0, R15
+ UML_MOV(block, I1, desc->pc+2); // mov r1, nextpc
+ UML_CALLH(block, *sh2->write32); // call write32
+
+ UML_HASHJMP(block, 0, mem(&sh2->evec), *sh2->nocode); // hashjmp sh2->evec
+
+ UML_LABEL(block, compiler->labelnum++); // skip:
+
+ // now go "out of cycles"
+ if (compiler->cycles > 0)
+ {
+ UML_MOV(block, mem(&sh2->icount), 0); // mov icount, #0
+ UML_MAPVAR(block, MAPVAR_CYCLES, 0); // mapvar cycles,0
+ UML_EXH(block, *sh2->out_of_cycles, desc->pc); // go out of cycles
+ }
+ else
+ {
+ UML_HASHJMP(block, 0, desc->pc, *sh2->nocode);
+ }
+
+ return TRUE;
+
+ case 0x22: // STCVBR(Rn);
+ UML_MOV(block, R32(Rn), mem(&sh2->vbr)); // mov Rn, vbr
+ return TRUE;
+
+ case 0x23: // BRAF(Rn);
+ if (sh2->cpu_type > CPU_TYPE_SH1)
+ {
+ UML_ADD(block, mem(&sh2->target), R32(Rn), desc->pc+4); // add target, Rn, pc+4
+
+ generate_delay_slot(sh2, block, compiler, desc, sh2->target);
+
+ generate_update_cycles(sh2, block, compiler, mem(&sh2->target), TRUE); // <subtract cycles>
+ UML_HASHJMP(block, 0, mem(&sh2->target), *sh2->nocode); // jmp target
+ return TRUE;
+ }
+ break;
+
+ case 0x28: // CLRMAC();
+ UML_MOV(block, mem(&sh2->macl), 0); // mov macl, #0
+ UML_MOV(block, mem(&sh2->mach), 0); // mov mach, #0
+ return TRUE;
+
+ case 0x29: // MOVT(Rn);
+ UML_AND(block, R32(Rn), mem(&sh2->sr), T); // and Rn, sr, T
+ return TRUE;
+
+ case 0x2a: // STSPR(Rn);
+ UML_MOV(block, R32(Rn), mem(&sh2->pr)); // mov Rn, pr
+ return TRUE;
+
+ case 0x2b: // RTE();
+ generate_delay_slot(sh2, block, compiler, desc, 0xffffffff);
+
+ UML_MOV(block, I0, R32(15)); // mov r0, R15
+ UML_CALLH(block, *sh2->read32); // call read32
+ UML_MOV(block, mem(&sh2->pc), I0); // mov pc, r0
+ UML_ADD(block, R32(15), R32(15), 4); // add R15, R15, #4
+
+ UML_MOV(block, I0, R32(15)); // mov r0, R15
+ UML_CALLH(block, *sh2->read32); // call read32
+ UML_MOV(block, mem(&sh2->sr), I0); // mov sr, r0
+ UML_ADD(block, R32(15), R32(15), 4); // add R15, R15, #4
+
+ compiler->checkints = TRUE;
+ UML_MOV(block, mem(&sh2->ea), mem(&sh2->pc)); // mov ea, pc
+ generate_update_cycles(sh2, block, compiler, mem(&sh2->ea), TRUE); // <subtract cycles>
+ UML_HASHJMP(block, 0, mem(&sh2->pc), *sh2->nocode); // and jump to the "resume PC"
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static int generate_group_2(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc)
+{
+ switch (opcode & 15)
+ {
+ case 0: // MOVBS(Rm, Rn);
+ UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_AND(block, I1, R32(Rm), 0xff); // and r1, Rm, 0xff
+ UML_CALLH(block, *sh2->write8);
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 1: // MOVWS(Rm, Rn);
+ UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_AND(block, I1, R32(Rm), 0xffff); // and r1, Rm, 0xffff
+ UML_CALLH(block, *sh2->write16);
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 2: // MOVLS(Rm, Rn);
+ UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_MOV(block, I1, R32(Rm)); // mov r1, Rm
+ UML_CALLH(block, *sh2->write32);
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 3: // NOP();
+ return TRUE;
+
+ case 4: // MOVBM(Rm, Rn);
+ UML_MOV(block, I1, R32(Rm)); // mov r1, Rm
+ UML_SUB(block, R32(Rn), R32(Rn), 1); // sub Rn, Rn, 1
+ UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_CALLH(block, *sh2->write8); // call write8
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 5: // MOVWM(Rm, Rn);
+ UML_MOV(block, I1, R32(Rm)); // mov r1, Rm
+ UML_SUB(block, R32(Rn), R32(Rn), 2); // sub Rn, Rn, 2
+ UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_CALLH(block, *sh2->write16); // call write16
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 6: // MOVLM(Rm, Rn);
+ UML_MOV(block, I1, R32(Rm)); // mov r1, Rm
+ UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, 4
+ UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_CALLH(block, *sh2->write32); // call write32
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 13: // XTRCT(Rm, Rn);
+ UML_SHL(block, I0, R32(Rm), 16); // shl r0, Rm, #16
+ UML_AND(block, I0, I0, 0xffff0000); // and r0, r0, #0xffff0000
+
+ UML_SHR(block, I1, R32(Rn), 16); // shr, r1, Rn, #16
+ UML_AND(block, I1, I1, 0xffff); // and r1, r1, #0x0000ffff
+
+ UML_OR(block, R32(Rn), I0, I1); // or Rn, r0, r1
+ return TRUE;
+
+ case 7: // DIV0S(Rm, Rn);
+ UML_MOV(block, I0, mem(&sh2->sr)); // move r0, sr
+ UML_AND(block, I0, I0, ~(Q|M|T)); // and r0, r0, ~(Q|M|T) (clear the Q,M, and T bits)
+
+ UML_TEST(block, R32(Rn), 0x80000000); // test Rn, #0x80000000
+ UML_JMPc(block, COND_Z, compiler->labelnum); // jz labelnum
+
+ UML_OR(block, I0, I0, Q); // or r0, r0, Q
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+
+ UML_TEST(block, R32(Rm), 0x80000000); // test Rm, #0x80000000
+ UML_JMPc(block, COND_Z, compiler->labelnum); // jz labelnum
+
+ UML_OR(block, I0, I0, M); // or r0, r0, M
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+
+ UML_XOR(block, I1, R32(Rn), R32(Rm)); // xor r1, Rn, Rm
+ UML_TEST(block, I1, 0x80000000); // test r1, #0x80000000
+ UML_JMPc(block, COND_Z, compiler->labelnum); // jz labelnum
+
+ UML_OR(block, I0, I0, T); // or r0, r0, T
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+ UML_MOV(block, mem(&sh2->sr), I0); // mov sr, r0
+ return TRUE;
+
+ case 8: // TST(Rm, Rn);
+ UML_AND(block, I0, mem(&sh2->sr), ~T); // and r0, sr, ~T (clear the T bit)
+ UML_TEST(block, R32(Rm), R32(Rn)); // test Rm, Rn
+ UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz compiler->labelnum
+
+ UML_OR(block, I0, I0, T); // or r0, r0, T
+ UML_LABEL(block, compiler->labelnum++); // desc->pc:
+
+ UML_MOV(block, mem(&sh2->sr), I0); // mov sh2->sr, r0
+ return TRUE;
+
+ case 12: // CMPSTR(Rm, Rn);
+ UML_XOR(block, I0, R32(Rn), R32(Rm)); // xor r0, Rn, Rm (temp)
+
+ UML_SHR(block, I1, I0, 24); // shr r1, r0, #24 (HH)
+ UML_AND(block, I1, I1, 0xff); // and r1, r1, #0xff
+
+ UML_SHR(block, I2, I0, 16); // shr r2, r0, #16 (HL)
+ UML_AND(block, I2, I2, 0xff); // and r2, r2, #0xff
+
+ UML_SHR(block, I3, I0, 8); // shr r3, r0, #8 (LH)
+ UML_AND(block, I3, I3, 0xff); // and r3, r3, #0xff
+
+ UML_AND(block, I7, I0, 0xff); // and r7, r0, #0xff (LL)
+
+ UML_AND(block, mem(&sh2->sr), mem(&sh2->sr), ~T); // and sr, sr, ~T (clear the T bit)
+
+ UML_CMP(block, I1, 0); // cmp r1, #0
+ UML_JMPc(block, COND_Z, compiler->labelnum); // jnz labelnum
+ UML_CMP(block, I2, 0); // cmp r2, #0
+ UML_JMPc(block, COND_Z, compiler->labelnum); // jnz labelnum
+ UML_CMP(block, I3, 0); // cmp r3, #0
+ UML_JMPc(block, COND_Z, compiler->labelnum); // jnz labelnum
+ UML_CMP(block, I7, 0); // cmp r7, #0
+ UML_JMPc(block, COND_NZ, compiler->labelnum+1); // jnz labelnum
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+ UML_OR(block, mem(&sh2->sr), mem(&sh2->sr), T); // or sr, sr, T
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum+1:
+ return TRUE;
+
+ case 9: // AND(Rm, Rn);
+ UML_AND(block, R32(Rn), R32(Rn), R32(Rm)); // and Rn, Rn, Rm
+ return TRUE;
+
+ case 10: // XOR(Rm, Rn);
+ UML_XOR(block, R32(Rn), R32(Rn), R32(Rm)); // xor Rn, Rn, Rm
+ return TRUE;
+
+ case 11: // OR(Rm, Rn);
+ UML_OR(block, R32(Rn), R32(Rn), R32(Rm)); // or Rn, Rn, Rm
+ return TRUE;
+
+ case 14: // MULU(Rm, Rn);
+ UML_AND(block, I0, R32(Rm), 0xffff); // and r0, Rm, 0xffff
+ UML_AND(block, I1, R32(Rn), 0xffff); // and r1, Rn, 0xffff
+ UML_MULU(block, mem(&sh2->macl), mem(&sh2->ea), I0, I1); // mulu macl, ea, r0, r1
+ return TRUE;
+
+ case 15: // MULS(Rm, Rn);
+ UML_SEXT(block, I0, R32(Rm), SIZE_WORD); // sext r0, Rm
+ UML_SEXT(block, I1, R32(Rn), SIZE_WORD); // sext r1, Rn
+ UML_MULS(block, mem(&sh2->macl), mem(&sh2->ea), I0, I1); // muls macl, ea, r0, r1
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static int generate_group_3(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, UINT32 ovrpc)
+{
+ switch (opcode & 15)
+ {
+ case 0: // CMPEQ(Rm, Rn); (equality)
+ UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm
+ UML_SETc(block, COND_E, I0); // set E, r0
+ UML_ROLINS(block, mem(&sh2->sr), I0, 0, 1); // rolins sr, r0, 0, 1
+ return TRUE;
+
+ case 2: // CMPHS(Rm, Rn); (unsigned greater than or equal)
+ UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm
+ UML_SETc(block, COND_AE, I0); // set AE, r0
+ UML_ROLINS(block, mem(&sh2->sr), I0, 0, 1); // rolins sr, r0, 0, 1
+ return TRUE;
+
+ case 3: // CMPGE(Rm, Rn); (signed greater than or equal)
+ UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm
+ UML_SETc(block, COND_GE, I0); // set GE, r0
+ UML_ROLINS(block, mem(&sh2->sr), I0, 0, 1); // rolins sr, r0, 0, 1
+ return TRUE;
+
+ case 6: // CMPHI(Rm, Rn); (unsigned greater than)
+ UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm
+ UML_SETc(block, COND_A, I0); // set A, r0
+ UML_ROLINS(block, mem(&sh2->sr), I0, 0, 1); // rolins sr, r0, 0, 1
+ return TRUE;
+
+ case 7: // CMPGT(Rm, Rn); (signed greater than)
+ UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm
+ UML_SETc(block, COND_G, I0); // set G, r0
+ UML_ROLINS(block, mem(&sh2->sr), I0, 0, 1); // rolins sr, r0, 0, 1
+ return TRUE;
+
+ case 1: // NOP();
+ case 9: // NOP();
+ return TRUE;
+
+ case 4: // DIV1(Rm, Rn);
+ save_fast_iregs(sh2, block);
+ UML_MOV(block, mem(&sh2->arg0), desc->opptr.w[0]);
+ UML_CALLC(block, cfunc_DIV1, sh2);
+ load_fast_iregs(sh2, block);
+ return TRUE;
+
+ case 5: // DMULU(Rm, Rn);
+ if (sh2->cpu_type > CPU_TYPE_SH1)
+ {
+ UML_MULU(block, mem(&sh2->macl), mem(&sh2->mach), R32(Rn), R32(Rm));
+ return TRUE;
+ }
+ break;
+
+ case 13: // DMULS(Rm, Rn);
+ if (sh2->cpu_type > CPU_TYPE_SH1)
+ {
+ UML_MULS(block, mem(&sh2->macl), mem(&sh2->mach), R32(Rn), R32(Rm));
+ return TRUE;
+ }
+ break;
+
+ case 8: // SUB(Rm, Rn);
+ UML_SUB(block, R32(Rn), R32(Rn), R32(Rm)); // sub Rn, Rn, Rm
+ return TRUE;
+
+ case 12: // ADD(Rm, Rn);
+ UML_ADD(block, R32(Rn), R32(Rn), R32(Rm)); // add Rn, Rn, Rm
+ return TRUE;
+
+ case 10: // SUBC(Rm, Rn);
+ UML_CARRY(block, mem(&sh2->sr), 0); // carry = T (T is bit 0 of SR)
+ UML_SUBB(block, R32(Rn), R32(Rn), R32(Rm)); // addc Rn, Rn, Rm
+ UML_SETc(block, COND_C, I0); // setc i0, C
+ UML_ROLINS(block, mem(&sh2->sr), I0, 0, T); // rolins sr,i0,0,T
+ return TRUE;
+
+ case 11: // SUBV(Rm, Rn);
+#if ADDSUBV_DIRECT
+ UML_SUB(block, R32(Rn), R32(Rn), R32(Rm)); // sub Rn, Rn, Rm
+ UML_SETc(block, COND_V, I0); // setc i0, V
+ UML_ROLINS(block, mem(&sh2->sr), I0, 0, T); // rolins [sr],i0,0,T
+#else
+ save_fast_iregs(sh2, block);
+ UML_MOV(block, mem(&sh2->arg0), desc->opptr.w[0]);
+ UML_CALLC(block, cfunc_SUBV, sh2);
+ load_fast_iregs(sh2, block);
+#endif
+ return TRUE;
+
+ case 14: // ADDC(Rm, Rn);
+ UML_CARRY(block, mem(&sh2->sr), 0); // carry = T (T is bit 0 of SR)
+ UML_ADDC(block, R32(Rn), R32(Rn), R32(Rm)); // addc Rn, Rn, Rm
+ UML_SETc(block, COND_C, I0); // setc i0, C
+ UML_ROLINS(block, mem(&sh2->sr), I0, 0, T); // rolins sr,i0,0,T
+ return TRUE;
+
+ case 15: // ADDV(Rm, Rn);
+#if ADDSUBV_DIRECT
+ UML_ADD(block, R32(Rn), R32(Rn), R32(Rm)); // add Rn, Rn, Rm
+ UML_SETc(block, COND_V, I0); // setc i0, V
+ UML_ROLINS(block, mem(&sh2->sr), I0, 0, T); // rolins [sr],i0,0,T
+#else
+ save_fast_iregs(sh2, block);
+ UML_MOV(block, mem(&sh2->arg0), desc->opptr.w[0]);
+ UML_CALLC(block, cfunc_ADDV, sh2);
+ load_fast_iregs(sh2, block);
+#endif
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static int generate_group_4(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc)
+{
+ switch (opcode & 0x3F)
+ {
+ case 0x00: // SHLL(Rn);
+ UML_SHL(block, R32(Rn), R32(Rn), 1); // shl Rn, Rn, 1
+ UML_SETc(block, COND_C, I0); // set i0,C
+ UML_ROLINS(block, mem(&sh2->sr), I0, 0, T); // rolins [sr],i0,0,T
+ return TRUE;
+
+ case 0x01: // SHLR(Rn);
+ UML_SHR(block, R32(Rn), R32(Rn), 1); // shr Rn, Rn, 1
+ UML_SETc(block, COND_C, I0); // set i0,C
+ UML_ROLINS(block, mem(&sh2->sr), I0, 0, T); // rolins [sr],i0,0,T
+ return TRUE;
+
+ case 0x04: // ROTL(Rn);
+ UML_ROL(block, R32(Rn), R32(Rn), 1); // rol Rn, Rn, 1
+ UML_SETc(block, COND_C, I0); // set i0,C
+ UML_ROLINS(block, mem(&sh2->sr), I0, 0, T); // rolins [sr],i0,0,T
+ return TRUE;
+
+ case 0x05: // ROTR(Rn);
+ UML_ROR(block, R32(Rn), R32(Rn), 1); // ror Rn, Rn, 1
+ UML_SETc(block, COND_C, I0); // set i0,C
+ UML_ROLINS(block, mem(&sh2->sr), I0, 0, T); // rolins [sr],i0,0,T
+ return TRUE;
+
+ case 0x02: // STSMMACH(Rn);
+ UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, #4
+ UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_MOV(block, I1, mem(&sh2->mach)); // mov r1, mach
+ SETEA(0); // set ea for debug
+ UML_CALLH(block, *sh2->write32); // call write32
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 0x03: // STCMSR(Rn);
+ UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, #4
+ UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_MOV(block, I1, mem(&sh2->sr)); // mov r1, sr
+ SETEA(0); // set ea for debug
+ UML_CALLH(block, *sh2->write32); // call write32
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 0x06: // LDSMMACH(Rn);
+ UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ SETEA(0);
+ UML_CALLH(block, *sh2->read32); // call read32
+ UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4
+ UML_MOV(block, mem(&sh2->mach), I0); // mov mach, r0
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 0x07: // LDCMSR(Rn);
+ UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ SETEA(0);
+ UML_CALLH(block, *sh2->read32); // call read32
+ UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4
+ UML_MOV(block, mem(&sh2->sr), I0); // mov sr, r0
+
+ compiler->checkints = TRUE;
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+
+ case 0x08: // SHLL2(Rn);
+ UML_SHL(block, R32(Rn), R32(Rn), 2);
+ return TRUE;
+
+ case 0x09: // SHLR2(Rn);
+ UML_SHR(block, R32(Rn), R32(Rn), 2);
+ return TRUE;
+
+ case 0x18: // SHLL8(Rn);
+ UML_SHL(block, R32(Rn), R32(Rn), 8);
+ return TRUE;
+
+ case 0x19: // SHLR8(Rn);
+ UML_SHR(block, R32(Rn), R32(Rn), 8);
+ return TRUE;
+
+ case 0x28: // SHLL16(Rn);
+ UML_SHL(block, R32(Rn), R32(Rn), 16);
+ return TRUE;
+
+ case 0x29: // SHLR16(Rn);
+ UML_SHR(block, R32(Rn), R32(Rn), 16);
+ return TRUE;
+
+ case 0x0a: // LDSMACH(Rn);
+ UML_MOV(block, mem(&sh2->mach), R32(Rn)); // mov mach, Rn
+ return TRUE;
+
+ case 0x0b: // JSR(Rn);
+ UML_MOV(block, mem(&sh2->target), R32(Rn)); // mov target, Rn
+
+ UML_ADD(block, mem(&sh2->pr), desc->pc, 4); // add sh2->pr, desc->pc, #4 (skip the current insn & delay slot)
+
+ generate_delay_slot(sh2, block, compiler, desc, sh2->target-4);
+
+ generate_update_cycles(sh2, block, compiler, mem(&sh2->target), TRUE); // <subtract cycles>
+ UML_HASHJMP(block, 0, mem(&sh2->target), *sh2->nocode); // and do the jump
+ return TRUE;
+
+ case 0x0e: // LDCSR(Rn);
+ UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_AND(block, I0, I0, FLAGS); // and r0, r0, FLAGS
+ UML_MOV(block, mem(&sh2->sr), I0);
+
+ compiler->checkints = TRUE;
+ return TRUE;
+
+ case 0x0f: // MAC_W(Rm, Rn);
+ case 0x1f: // MAC_W(Rm, Rn);
+ case 0x2f: // MAC_W(Rm, Rn);
+ case 0x3f: // MAC_W(Rm, Rn);
+ save_fast_iregs(sh2, block);
+ UML_MOV(block, mem(&sh2->arg0), desc->opptr.w[0]);
+ UML_CALLC(block, cfunc_MAC_W, sh2);
+ load_fast_iregs(sh2, block);
+ return TRUE;
+
+ case 0x10: // DT(Rn);
+ if (sh2->cpu_type > CPU_TYPE_SH1)
+ {
+ UML_AND(block, I0, mem(&sh2->sr), ~T); // and r0, sr, ~T (clear the T bit)
+ UML_SUB(block, R32(Rn), R32(Rn), 1); // sub Rn, Rn, 1
+ UML_JMPc(block, COND_NZ, compiler->labelnum); // jz compiler->labelnum
+
+ UML_OR(block, I0, I0, T); // or r0, r0, T
+ UML_LABEL(block, compiler->labelnum++); // desc->pc:
+
+ UML_MOV(block, mem(&sh2->sr), I0); // mov sh2->sr, r0
+ return TRUE;
+ }
+ break;
+
+ case 0x11: // CMPPZ(Rn);
+ UML_AND(block, I0, mem(&sh2->sr), ~T); // and r0, sr, ~T (clear the T bit)
+
+ UML_CMP(block, R32(Rn), 0); // cmp Rn, 0
+ UML_JMPc(block, COND_S, compiler->labelnum); // js compiler->labelnum (if negative)
+
+ UML_OR(block, I0, I0, T); // or r0, r0, T
+ UML_LABEL(block, compiler->labelnum++); // desc->pc:
+
+ UML_MOV(block, mem(&sh2->sr), I0); // mov sh2->sr, r0
+ return TRUE;
+
+ case 0x15: // CMPPL(Rn);
+ UML_AND(block, I0, mem(&sh2->sr), ~T); // and r0, sr, ~T (clear the T bit)
+
+ UML_CMP(block, R32(Rn), 0); // cmp Rn, 0
+
+ UML_JMPc(block, COND_S, compiler->labelnum); // js compiler->labelnum (if negative)
+ UML_JMPc(block, COND_Z, compiler->labelnum); // jz compiler->labelnum (if zero)
+
+ UML_OR(block, I0, I0, T); // or r0, r0, T
+
+ UML_LABEL(block, compiler->labelnum++); // desc->pc:
+ UML_MOV(block, mem(&sh2->sr), I0); // mov sh2->sr, r0
+ return TRUE;
+
+ case 0x12: // STSMMACL(Rn);
+ UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, #4
+ UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_MOV(block, I1, mem(&sh2->macl)); // mov r1, macl
+ SETEA(0); // set ea for debug
+ UML_CALLH(block, *sh2->write32); // call write32
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 0x13: // STCMGBR(Rn);
+ UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, #4
+ UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_MOV(block, I1, mem(&sh2->gbr)); // mov r1, gbr
+ SETEA(0); // set ea for debug
+ UML_CALLH(block, *sh2->write32); // call write32
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 0x16: // LDSMMACL(Rn);
+ UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ SETEA(0);
+ UML_CALLH(block, *sh2->read32); // call read32
+ UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4
+ UML_MOV(block, mem(&sh2->macl), I0); // mov macl, r0
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 0x17: // LDCMGBR(Rn);
+ UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ SETEA(0);
+ UML_CALLH(block, *sh2->read32); // call read32
+ UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4
+ UML_MOV(block, mem(&sh2->gbr), I0); // mov gbr, r0
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 0x1a: // LDSMACL(Rn);
+ UML_MOV(block, mem(&sh2->macl), R32(Rn)); // mov macl, Rn
+ return TRUE;
+
+ case 0x1b: // TAS(Rn);
+ UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ SETEA(0);
+ UML_CALLH(block, *sh2->read8); // call read8
+
+ UML_AND(block, mem(&sh2->sr), mem(&sh2->sr), ~T); // and sr, sr, ~T
+
+ UML_CMP(block, I0, 0); // cmp r0, #0
+ UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz labelnum
+
+ UML_OR(block, mem(&sh2->sr), mem(&sh2->sr), T); // or sr, sr, T
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+
+ UML_OR(block, I1, I0, 0x80); // or r1, r0, #0x80
+
+ UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_CALLH(block, *sh2->write8); // write the value back
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 0x1e: // LDCGBR(Rn);
+ UML_MOV(block, mem(&sh2->gbr), R32(Rn)); // mov gbr, Rn
+ return TRUE;
+
+ case 0x20: // SHAL(Rn);
+ UML_AND(block, mem(&sh2->sr), mem(&sh2->sr), ~T); // and sr, sr, ~T
+ UML_SHR(block, I0, R32(Rn), 31); // shr r0, Rn, 31
+ UML_AND(block, I0, I0, T); // and r0, r0, T
+ UML_OR(block, mem(&sh2->sr), mem(&sh2->sr), I0); // or sr, sr, r0
+ UML_SHL(block, R32(Rn), R32(Rn), 1); // shl Rn, Rn, 1
+ return TRUE;
+
+ case 0x21: // SHAR(Rn);
+ UML_AND(block, mem(&sh2->sr), mem(&sh2->sr), ~T); // and sr, sr, ~T
+ UML_AND(block, I0, R32(Rn), T); // and r0, Rn, T
+ UML_OR(block, mem(&sh2->sr), mem(&sh2->sr), I0); // or sr, sr, r0
+ UML_SAR(block, R32(Rn), R32(Rn), 1); // sar Rn, Rn, 1
+ return TRUE;
+
+ case 0x22: // STSMPR(Rn);
+ UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, 4
+ UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ SETEA(0);
+ UML_MOV(block, I1, mem(&sh2->pr)); // mov r1, pr
+ UML_CALLH(block, *sh2->write32); // call write32
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 0x23: // STCMVBR(Rn);
+ UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, 4
+ UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ SETEA(0);
+ UML_MOV(block, I1, mem(&sh2->vbr)); // mov r1, vbr
+ UML_CALLH(block, *sh2->write32); // call write32
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 0x24: // ROTCL(Rn);
+ UML_CARRY(block, mem(&sh2->sr), 0); // carry sr,0
+ UML_ROLC(block, R32(Rn), R32(Rn), 1); // rolc Rn,Rn,1
+ UML_SETc(block, COND_C, I0); // set i0,C
+ UML_ROLINS(block, mem(&sh2->sr), I0, 0, T); // rolins sr,i0,0,T
+ return TRUE;
+
+ case 0x25: // ROTCR(Rn);
+ UML_CARRY(block, mem(&sh2->sr), 0); // carry sr,0
+ UML_RORC(block, R32(Rn), R32(Rn), 1); // rorc Rn,Rn,1
+ UML_SETc(block, COND_C, I0); // set i0,C
+ UML_ROLINS(block, mem(&sh2->sr), I0, 0, T); // rolins sr,i0,0,T
+ return TRUE;
+
+ case 0x26: // LDSMPR(Rn);
+ UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ SETEA(0);
+ UML_CALLH(block, *sh2->read32); // call read32
+ UML_MOV(block, mem(&sh2->pr), I0); // mov sh2->pr, r0
+ UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, Rn, #4
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 0x27: // LDCMVBR(Rn);
+ UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ SETEA(0);
+ UML_CALLH(block, *sh2->read32); // call read32
+ UML_MOV(block, mem(&sh2->vbr), I0); // mov sh2->vbr, r0
+ UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, Rn, #4
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 0x2a: // LDSPR(Rn);
+ UML_MOV(block, mem(&sh2->pr), R32(Rn)); // mov sh2->pr, Rn
+ return TRUE;
+
+ case 0x2b: // JMP(Rn);
+ UML_MOV(block, mem(&sh2->target), R32(Rn)); // mov target, Rn
+
+ generate_delay_slot(sh2, block, compiler, desc, sh2->target);
+
+ generate_update_cycles(sh2, block, compiler, mem(&sh2->target), TRUE); // <subtract cycles>
+ UML_HASHJMP(block, 0, mem(&sh2->target), *sh2->nocode); // jmp (target)
+ return TRUE;
+
+ case 0x2e: // LDCVBR(Rn);
+ UML_MOV(block, mem(&sh2->vbr), R32(Rn)); // mov vbr, Rn
+ return TRUE;
+
+ case 0x0c: // NOP();
+ case 0x0d: // NOP();
+ case 0x14: // NOP();
+ case 0x1c: // NOP();
+ case 0x1d: // NOP();
+ case 0x2c: // NOP();
+ case 0x2d: // NOP();
+ case 0x30: // NOP();
+ case 0x31: // NOP();
+ case 0x32: // NOP();
+ case 0x33: // NOP();
+ case 0x34: // NOP();
+ case 0x35: // NOP();
+ case 0x36: // NOP();
+ case 0x37: // NOP();
+ case 0x38: // NOP();
+ case 0x39: // NOP();
+ case 0x3a: // NOP();
+ case 0x3b: // NOP();
+ case 0x3c: // NOP();
+ case 0x3d: // NOP();
+ case 0x3e: // NOP();
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static int generate_group_6(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc)
+{
+ switch (opcode & 15)
+ {
+ case 0: // MOVBL(Rm, Rn);
+ UML_MOV(block, I0, R32(Rm)); // mov r0, Rm
+ SETEA(0); // debug: ea = r0
+ UML_CALLH(block, *sh2->read8); // call read8
+ UML_SEXT(block, R32(Rn), I0, SIZE_BYTE); // sext Rn, r0, BYTE
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 1: // MOVWL(Rm, Rn);
+ UML_MOV(block, I0, R32(Rm)); // mov r0, Rm
+ SETEA(0); // debug: ea = r0
+ UML_CALLH(block, *sh2->read16); // call read16
+ UML_SEXT(block, R32(Rn), I0, SIZE_WORD); // sext Rn, r0, WORD
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 2: // MOVLL(Rm, Rn);
+ UML_MOV(block, I0, R32(Rm)); // mov r0, Rm
+ SETEA(0); // debug: ea = r0
+ UML_CALLH(block, *sh2->read32); // call read32
+ UML_MOV(block, R32(Rn), I0); // mov Rn, r0
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 3: // MOV(Rm, Rn);
+ UML_MOV(block, R32(Rn), R32(Rm)); // mov Rn, Rm
+ return TRUE;
+
+ case 7: // NOT(Rm, Rn);
+ UML_XOR(block, R32(Rn), R32(Rm), 0xffffffff); // xor Rn, Rm, 0xffffffff
+ return TRUE;
+
+ case 9: // SWAPW(Rm, Rn);
+ UML_ROL(block, R32(Rn), R32(Rm), 16); // rol Rn, Rm, 16
+ return TRUE;
+
+ case 11: // NEG(Rm, Rn);
+ UML_SUB(block, R32(Rn), 0, R32(Rm)); // sub Rn, 0, Rm
+ return TRUE;
+
+ case 12: // EXTUB(Rm, Rn);
+ UML_AND(block, R32(Rn), R32(Rm), 0x000000ff); // and Rn, Rm, 0xff
+ return TRUE;
+
+ case 13: // EXTUW(Rm, Rn);
+ UML_AND(block, R32(Rn), R32(Rm), 0x0000ffff); // and Rn, Rm, 0xffff
+ return TRUE;
+
+ case 14: // EXTSB(Rm, Rn);
+ UML_SEXT(block, R32(Rn), R32(Rm), SIZE_BYTE); // sext Rn, Rm, BYTE
+ return TRUE;
+
+ case 15: // EXTSW(Rm, Rn);
+ UML_SEXT(block, R32(Rn), R32(Rm), SIZE_WORD); // sext Rn, Rm, WORD
+ return TRUE;
+
+ case 4: // MOVBP(Rm, Rn);
+ UML_MOV(block, I0, R32(Rm)); // mov r0, Rm
+ UML_CALLH(block, *sh2->read8); // call read8
+ UML_SEXT(block, R32(Rn), I0, SIZE_BYTE); // sext Rn, r0, BYTE
+
+ if (Rm != Rn)
+ UML_ADD(block, R32(Rm), R32(Rm), 1); // add Rm, Rm, #1
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 5: // MOVWP(Rm, Rn);
+ UML_MOV(block, I0, R32(Rm)); // mov r0, Rm
+ UML_CALLH(block, *sh2->read16); // call read16
+ UML_SEXT(block, R32(Rn), I0, SIZE_WORD); // sext Rn, r0, WORD
+
+ if (Rm != Rn)
+ UML_ADD(block, R32(Rm), R32(Rm), 2); // add Rm, Rm, #2
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 6: // MOVLP(Rm, Rn);
+ UML_MOV(block, I0, R32(Rm)); // mov r0, Rm
+ UML_CALLH(block, *sh2->read32); // call read32
+ UML_MOV(block, R32(Rn), I0); // mov Rn, r0
+
+ if (Rm != Rn)
+ UML_ADD(block, R32(Rm), R32(Rm), 4); // add Rm, Rm, #4
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 8: // SWAPB(Rm, Rn);
+ UML_AND(block, I0, R32(Rm), 0xffff0000); // and r0, Rm, #0xffff0000
+ UML_AND(block, I1, R32(Rm), 0x000000ff); // and r0, Rm, #0x000000ff
+ UML_AND(block, I2, R32(Rm), 0x0000ff00); // and r0, Rm, #0x0000ff00
+ UML_SHL(block, I1, I1, 8); // shl r1, r1, #8
+ UML_SHR(block, I2, I2, 8); // shr r2, r2, #8
+ UML_OR(block, I0, I0, I1); // or r0, r0, r1
+ UML_OR(block, R32(Rn), I0, I2); // or Rn, r0, r2
+ return TRUE;
+
+ case 10: // NEGC(Rm, Rn);
+ UML_MOV(block, I0, mem(&sh2->sr)); // mov r0, sr (save SR)
+ UML_AND(block, mem(&sh2->sr), mem(&sh2->sr), ~T); // and sr, sr, ~T (clear the T bit)
+ UML_CARRY(block, I0, 0); // carry = T (T is bit 0 of SR)
+ UML_SUBB(block, R32(Rn), 0, R32(Rm)); // subb Rn, #0, Rm
+
+ UML_JMPc(block, COND_NC, compiler->labelnum); // jnc labelnum
+
+ UML_OR(block, mem(&sh2->sr), mem(&sh2->sr), T); // or sr, sr, T
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static int generate_group_8(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc)
+{
+ INT32 disp;
+ UINT32 udisp;
+ code_label templabel;
+
+ switch ( opcode & (15<<8) )
+ {
+ case 0 << 8: // MOVBS4(opcode & 0x0f, Rm);
+ udisp = (opcode & 0x0f);
+ UML_ADD(block, I0, R32(Rm), udisp); // add r0, Rm, udisp
+ UML_MOV(block, I1, R32(0)); // mov r1, R0
+ UML_CALLH(block, *sh2->write8); // call write8
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 1 << 8: // MOVWS4(opcode & 0x0f, Rm);
+ udisp = (opcode & 0x0f) * 2;
+ UML_ADD(block, I0, R32(Rm), udisp); // add r0, Rm, udisp
+ UML_MOV(block, I1, R32(0)); // mov r1, R0
+ UML_CALLH(block, *sh2->write16); // call write16
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 2<< 8: // NOP();
+ case 3<< 8: // NOP();
+ case 6<< 8: // NOP();
+ case 7<< 8: // NOP();
+ case 10<< 8: // NOP();
+ case 12<< 8: // NOP();
+ case 14<< 8: // NOP();
+ return TRUE;
+
+ case 4<< 8: // MOVBL4(Rm, opcode & 0x0f);
+ udisp = opcode & 0x0f;
+ UML_ADD(block, I0, R32(Rm), udisp); // add r0, Rm, udisp
+ SETEA(0);
+ UML_CALLH(block, *sh2->read8); // call read8
+ UML_SEXT(block, R32(0), I0, SIZE_BYTE); // sext R0, r0, BYTE
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 5<< 8: // MOVWL4(Rm, opcode & 0x0f);
+ udisp = (opcode & 0x0f)*2;
+ UML_ADD(block, I0, R32(Rm), udisp); // add r0, Rm, udisp
+ SETEA(0);
+ UML_CALLH(block, *sh2->read16); // call read16
+ UML_SEXT(block, R32(0), I0, SIZE_WORD); // sext R0, r0, WORD
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 8<< 8: // CMPIM(opcode & 0xff);
+ UML_AND(block, I0, mem(&sh2->sr), ~T); // and r0, sr, ~T (clear the T bit)
+
+ UML_SEXT(block, I1, opcode&0xff, SIZE_BYTE); // sext r1, opcode&0xff, BYTE
+ UML_CMP(block, I1, R32(0)); // cmp r1, R0
+ UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz compiler->labelnum (if negative)
+
+ UML_OR(block, I0, I0, T); // or r0, r0, T
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+ UML_MOV(block, mem(&sh2->sr), I0); // mov sh2->sr, r0
+ return TRUE;
+
+ case 9<< 8: // BT(opcode & 0xff);
+ UML_TEST(block, mem(&sh2->sr), T); // test sh2->sr, T
+ UML_JMPc(block, COND_Z, compiler->labelnum); // jz compiler->labelnum
+
+ disp = ((INT32)opcode << 24) >> 24;
+ sh2->ea = (desc->pc + 2) + disp * 2 + 2; // sh2->ea = destination
+
+ generate_update_cycles(sh2, block, compiler, sh2->ea, TRUE); // <subtract cycles>
+ UML_HASHJMP(block, 0, sh2->ea, *sh2->nocode); // jmp sh2->ea
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+ return TRUE;
+
+ case 11<< 8: // BF(opcode & 0xff);
+ UML_TEST(block, mem(&sh2->sr), T); // test sh2->sr, T
+ UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz compiler->labelnum
+
+ disp = ((INT32)opcode << 24) >> 24;
+ sh2->ea = (desc->pc + 2) + disp * 2 + 2; // sh2->ea = destination
+
+ generate_update_cycles(sh2, block, compiler, sh2->ea, TRUE); // <subtract cycles>
+ UML_HASHJMP(block, 0, sh2->ea, *sh2->nocode); // jmp sh2->ea
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+ return TRUE;
+
+ case 13<< 8: // BTS(opcode & 0xff);
+ if (sh2->cpu_type > CPU_TYPE_SH1)
+ {
+ UML_TEST(block, mem(&sh2->sr), T); // test sh2->sr, T
+ UML_JMPc(block, COND_Z, compiler->labelnum); // jz compiler->labelnum
+
+ disp = ((INT32)opcode << 24) >> 24;
+ sh2->ea = (desc->pc + 2) + disp * 2 + 2; // sh2->ea = destination
+
+ templabel = compiler->labelnum; // save our label
+ compiler->labelnum++; // make sure the delay slot doesn't use it
+ generate_delay_slot(sh2, block, compiler, desc, sh2->ea-2);
+
+ generate_update_cycles(sh2, block, compiler, sh2->ea, TRUE); // <subtract cycles>
+ UML_HASHJMP(block, 0, sh2->ea, *sh2->nocode); // jmp sh2->ea
+
+ UML_LABEL(block, templabel); // labelnum:
+ return TRUE;
+ }
+ break;
+
+ case 15<< 8: // BFS(opcode & 0xff);
+ if (sh2->cpu_type > CPU_TYPE_SH1)
+ {
+ UML_TEST(block, mem(&sh2->sr), T); // test sh2->sr, T
+ UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz compiler->labelnum
+
+ disp = ((INT32)opcode << 24) >> 24;
+ sh2->ea = (desc->pc + 2) + disp * 2 + 2; // sh2->ea = destination
+
+ templabel = compiler->labelnum; // save our label
+ compiler->labelnum++; // make sure the delay slot doesn't use it
+ generate_delay_slot(sh2, block, compiler, desc, sh2->ea-2); // delay slot only if the branch is taken
+
+ generate_update_cycles(sh2, block, compiler, sh2->ea, TRUE); // <subtract cycles>
+ UML_HASHJMP(block, 0, sh2->ea, *sh2->nocode); // jmp sh2->ea
+
+ UML_LABEL(block, templabel); // labelnum:
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+static int generate_group_12(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc)
+{
+ UINT32 scratch;
+
+ switch (opcode & (15<<8))
+ {
+ case 0<<8: // MOVBSG(opcode & 0xff);
+ scratch = (opcode & 0xff);
+ UML_ADD(block, I0, mem(&sh2->gbr), scratch); // add r0, gbr, scratch
+ UML_AND(block, I1, R32(0), 0xff); // and r1, R0, 0xff
+ UML_CALLH(block, *sh2->write8); // call write8
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 1<<8: // MOVWSG(opcode & 0xff);
+ scratch = (opcode & 0xff) * 2;
+ UML_ADD(block, I0, mem(&sh2->gbr), scratch); // add r0, gbr, scratch
+ UML_AND(block, I1, R32(0), 0xffff); // and r1, R0, 0xffff
+ UML_CALLH(block, *sh2->write16); // call write16
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 2<<8: // MOVLSG(opcode & 0xff);
+ scratch = (opcode & 0xff) * 4;
+ UML_ADD(block, I0, mem(&sh2->gbr), scratch); // add r0, gbr, scratch
+ UML_MOV(block, I1, R32(0)); // mov r1, R0
+ UML_CALLH(block, *sh2->write32); // call write32
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 3<<8: // TRAPA(opcode & 0xff);
+ scratch = (opcode & 0xff) * 4;
+ UML_ADD(block, mem(&sh2->ea), mem(&sh2->vbr), scratch); // add ea, vbr, scratch
+
+ UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4
+ UML_MOV(block, I0, R32(15)); // mov r0, R15
+ UML_MOV(block, I1, mem(&sh2->sr)); // mov r1, sr
+ UML_CALLH(block, *sh2->write32); // write32
+
+ UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4
+ UML_MOV(block, I0, R32(15)); // mov r0, R15
+ UML_MOV(block, I1, desc->pc+2); // mov r1, pc+2
+ UML_CALLH(block, *sh2->write32); // write32
+
+ UML_MOV(block, I0, mem(&sh2->ea)); // mov r0, ea
+ UML_CALLH(block, *sh2->read32); // read32
+ UML_HASHJMP(block, 0, I0, *sh2->nocode); // jmp (r0)
+
+ return TRUE;
+
+ case 4<<8: // MOVBLG(opcode & 0xff);
+ scratch = (opcode & 0xff);
+ UML_ADD(block, I0, mem(&sh2->gbr), scratch); // add r0, gbr, scratch
+ UML_CALLH(block, *sh2->read8); // call read16
+ UML_SEXT(block, R32(0), I0, SIZE_BYTE); // sext R0, r0, BYTE
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 5<<8: // MOVWLG(opcode & 0xff);
+ scratch = (opcode & 0xff) * 2;
+ UML_ADD(block, I0, mem(&sh2->gbr), scratch); // add r0, gbr, scratch
+ UML_CALLH(block, *sh2->read16); // call read16
+ UML_SEXT(block, R32(0), I0, SIZE_WORD); // sext R0, r0, WORD
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 6<<8: // MOVLLG(opcode & 0xff);
+ scratch = (opcode & 0xff) * 4;
+ UML_ADD(block, I0, mem(&sh2->gbr), scratch); // add r0, gbr, scratch
+ UML_CALLH(block, *sh2->read32); // call read32
+ UML_MOV(block, R32(0), I0); // mov R0, r0
+
+ if (!in_delay_slot)
+ generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE);
+ return TRUE;
+
+ case 7<<8: // MOVA(opcode & 0xff);
+ scratch = (opcode & 0xff) * 4;
+ scratch += ((desc->pc + 4) & ~3);
+
+ UML_MOV(block, R32(0), scratch); // mov R0, scratch
+ return TRUE;
+
+ case 8<<8: // TSTI(opcode & 0xff);
+ scratch = opcode & 0xff;
+
+ UML_AND(block, mem(&sh2->sr), mem(&sh2->sr), ~T); // and sr, sr, ~T (clear the T bit)
+ UML_AND(block, I0, R32(0), scratch); // and r0, R0, scratch
+ UML_CMP(block, I0, 0); // cmp r0, #0
+ UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz labelnum
+
+ UML_OR(block, mem(&sh2->sr), mem(&sh2->sr), T); // or sr, sr, T
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+ return TRUE;
+
+ case 9<<8: // ANDI(opcode & 0xff);
+ UML_AND(block, R32(0), R32(0), opcode & 0xff); // and r0, r0, opcode & 0xff
+ return TRUE;
+
+ case 10<<8: // XORI(opcode & 0xff);
+ UML_XOR(block, R32(0), R32(0), opcode & 0xff); // xor r0, r0, opcode & 0xff
+ return TRUE;
+
+ case 11<<8: // ORI(opcode & 0xff);
+ UML_OR(block, R32(0), R32(0), opcode & 0xff); // or r0, r0, opcode & 0xff
+ return TRUE;
+
+ case 12<<8: // TSTM(opcode & 0xff);
+ UML_AND(block, mem(&sh2->sr), mem(&sh2->sr), ~T); // and sr, sr, ~T (clear the T bit)
+ UML_ADD(block, I0, R32(0), mem(&sh2->gbr)); // add r0, R0, gbr
+ UML_CALLH(block, *sh2->read8); // read8
+
+ UML_AND(block, I0, I0, opcode & 0xff);
+ UML_CMP(block, I0, 0); // cmp r0, #0
+ UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz labelnum
+
+ UML_OR(block, mem(&sh2->sr), mem(&sh2->sr), T); // or sr, sr, T
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+ return TRUE;
+
+ case 13<<8: // ANDM(opcode & 0xff);
+ UML_ADD(block, I0, R32(0), mem(&sh2->gbr)); // add r0, R0, gbr
+ UML_CALLH(block, *sh2->read8); // read8
+
+ UML_AND(block, I1, I0, opcode&0xff); // and r1, r0, #opcode&0xff
+ UML_ADD(block, I0, R32(0), mem(&sh2->gbr)); // add r0, R0, gbr
+ SETEA(0);
+ UML_CALLH(block, *sh2->write8); // write8
+ return TRUE;
+
+ case 14<<8: // XORM(opcode & 0xff);
+ UML_ADD(block, I0, R32(0), mem(&sh2->gbr)); // add r0, R0, gbr
+ UML_CALLH(block, *sh2->read8); // read8
+
+ UML_XOR(block, I1, I0, opcode&0xff); // xor r1, r0, #opcode&0xff
+ UML_ADD(block, I0, R32(0), mem(&sh2->gbr)); // add r0, R0, gbr
+ SETEA(0);
+ UML_CALLH(block, *sh2->write8); // write8
+ return TRUE;
+
+ case 15<<8: // ORM(opcode & 0xff);
+ UML_ADD(block, I0, R32(0), mem(&sh2->gbr)); // add r0, R0, gbr
+ UML_CALLH(block, *sh2->read8); // read8
+
+ UML_OR(block, I1, I0, opcode&0xff); // or r1, r0, #opcode&0xff
+ UML_ADD(block, I0, R32(0), mem(&sh2->gbr)); // add r0, R0, gbr
+ SETEA(0);
+ UML_CALLH(block, *sh2->write8); // write8
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/***************************************************************************
+ CORE CALLBACKS
+***************************************************************************/
+
+/*-------------------------------------------------
+ sh2drc_set_options - configure DRC options
+-------------------------------------------------*/
+
+void sh2drc_set_options(device_t *device, UINT32 options)
+{
+ sh2_state *sh2 = get_safe_token(device);
+ sh2->drcoptions = options;
+}
+
+
+/*-------------------------------------------------
+ sh2drc_add_pcflush - add a new address where
+ the PC must be flushed for speedups to work
+-------------------------------------------------*/
+
+void sh2drc_add_pcflush(device_t *device, offs_t address)
+{
+ sh2_state *sh2 = get_safe_token(device);
+
+ if (sh2->pcfsel < ARRAY_LENGTH(sh2->pcflushes))
+ sh2->pcflushes[sh2->pcfsel++] = address;
+}
+
+
+/*-------------------------------------------------
+ sh2_internal_a5 - read handler for
+ SH2 internal map
+-------------------------------------------------*/
+
+static READ32_HANDLER(sh2_internal_a5)
+{
+ return 0xa5a5a5a5;
+}
+
+
+/*-------------------------------------------------
+ sh2_internal_map - maps SH2 built-ins
+-------------------------------------------------*/
+
+static ADDRESS_MAP_START( sh2_internal_map, AS_PROGRAM, 32 )
+ AM_RANGE(0x40000000, 0xbfffffff) AM_READ(sh2_internal_a5)
+ AM_RANGE(0xe0000000, 0xffffffff) AM_READWRITE(sh2_internal_r, sh2_internal_w)
+ADDRESS_MAP_END
+
+/*-------------------------------------------------
+ sh2_set_info - set information about a given
+ CPU instance
+-------------------------------------------------*/
+
+static CPU_SET_INFO( sh2 )
+{
+ sh2_state *sh2 = get_safe_token(device);
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_VBLIN: sh2_set_irq_line(sh2, SH2_INT_VBLIN, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_VBLOUT: sh2_set_irq_line(sh2, SH2_INT_VBLOUT, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_HBLIN: sh2_set_irq_line(sh2, SH2_INT_HBLIN, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_TIMER0: sh2_set_irq_line(sh2, SH2_INT_TIMER0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_TIMER1: sh2_set_irq_line(sh2, SH2_INT_TIMER1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DSP: sh2_set_irq_line(sh2, SH2_INT_DSP, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_SOUND: sh2_set_irq_line(sh2, SH2_INT_SOUND, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_SMPC: sh2_set_irq_line(sh2, SH2_INT_SMPC, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_PAD: sh2_set_irq_line(sh2, SH2_INT_PAD, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA2: sh2_set_irq_line(sh2, SH2_INT_DMA2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA1: sh2_set_irq_line(sh2, SH2_INT_DMA1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA0: sh2_set_irq_line(sh2, SH2_INT_DMA0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DMAILL: sh2_set_irq_line(sh2, SH2_INT_DMAILL, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_SPRITE: sh2_set_irq_line(sh2, SH2_INT_SPRITE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_14: sh2_set_irq_line(sh2, SH2_INT_14, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_15: sh2_set_irq_line(sh2, SH2_INT_15, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_ABUS: sh2_set_irq_line(sh2, SH2_INT_ABUS, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: sh2_set_irq_line(sh2, INPUT_LINE_NMI, info->i); break;
+
+ case CPUINFO_INT_REGISTER + SH2_PC:
+ case CPUINFO_INT_PC: sh2->pc = info->i; sh2->delay = 0; break;
+ case CPUINFO_INT_SP: sh2->r[15] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_PR: sh2->pr = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_SR: sh2->sr = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_GBR: sh2->gbr = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_VBR: sh2->vbr = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_MACH: sh2->mach = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_MACL: sh2->macl = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R0: sh2->r[ 0] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R1: sh2->r[ 1] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R2: sh2->r[ 2] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R3: sh2->r[ 3] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R4: sh2->r[ 4] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R5: sh2->r[ 5] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R6: sh2->r[ 6] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R7: sh2->r[ 7] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R8: sh2->r[ 8] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R9: sh2->r[ 9] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R10: sh2->r[10] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R11: sh2->r[11] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R12: sh2->r[12] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R13: sh2->r[13] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R14: sh2->r[14] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R15: sh2->r[15] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_EA: sh2->ea = info->i; break;
+ }
+}
+
+/*-------------------------------------------------
+ sh2_get_info - return information about a
+ given CPU instance
+-------------------------------------------------*/
+
+CPU_GET_INFO( sh2 )
+{
+ sh2_state *sh2 = (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(sh2_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; 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 = 2; 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 = 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;
+
+ // Internal maps
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map32 = ADDRESS_MAP_NAME(sh2_internal_map); 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;
+
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_VBLIN: info->i = sh2->irq_line_state[SH2_INT_VBLIN]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_VBLOUT: info->i = sh2->irq_line_state[SH2_INT_VBLOUT]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_HBLIN: info->i = sh2->irq_line_state[SH2_INT_HBLIN]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_TIMER0: info->i = sh2->irq_line_state[SH2_INT_TIMER0]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_TIMER1: info->i = sh2->irq_line_state[SH2_INT_TIMER1]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DSP: info->i = sh2->irq_line_state[SH2_INT_DSP]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_SOUND: info->i = sh2->irq_line_state[SH2_INT_SOUND]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_SMPC: info->i = sh2->irq_line_state[SH2_INT_SMPC]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_PAD: info->i = sh2->irq_line_state[SH2_INT_PAD]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA2: info->i = sh2->irq_line_state[SH2_INT_DMA2]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA1: info->i = sh2->irq_line_state[SH2_INT_DMA1]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA0: info->i = sh2->irq_line_state[SH2_INT_DMA0]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DMAILL: info->i = sh2->irq_line_state[SH2_INT_DMAILL]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_SPRITE: info->i = sh2->irq_line_state[SH2_INT_SPRITE]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_14: info->i = sh2->irq_line_state[SH2_INT_14]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_15: info->i = sh2->irq_line_state[SH2_INT_15]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_ABUS: info->i = sh2->irq_line_state[SH2_INT_ABUS]; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = sh2->nmi_line_state; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = sh2->ppc; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + SH2_PC: info->i = (sh2->delay) ? (sh2->delay & AM) : (sh2->pc & AM); break;
+ case CPUINFO_INT_SP: info->i = sh2->r[15]; break;
+ case CPUINFO_INT_REGISTER + SH2_PR: info->i = sh2->pr; break;
+ case CPUINFO_INT_REGISTER + SH2_SR: info->i = sh2->sr; break;
+ case CPUINFO_INT_REGISTER + SH2_GBR: info->i = sh2->gbr; break;
+ case CPUINFO_INT_REGISTER + SH2_VBR: info->i = sh2->vbr; break;
+ case CPUINFO_INT_REGISTER + SH2_MACH: info->i = sh2->mach; break;
+ case CPUINFO_INT_REGISTER + SH2_MACL: info->i = sh2->macl; break;
+ case CPUINFO_INT_REGISTER + SH2_R0: info->i = sh2->r[ 0]; break;
+ case CPUINFO_INT_REGISTER + SH2_R1: info->i = sh2->r[ 1]; break;
+ case CPUINFO_INT_REGISTER + SH2_R2: info->i = sh2->r[ 2]; break;
+ case CPUINFO_INT_REGISTER + SH2_R3: info->i = sh2->r[ 3]; break;
+ case CPUINFO_INT_REGISTER + SH2_R4: info->i = sh2->r[ 4]; break;
+ case CPUINFO_INT_REGISTER + SH2_R5: info->i = sh2->r[ 5]; break;
+ case CPUINFO_INT_REGISTER + SH2_R6: info->i = sh2->r[ 6]; break;
+ case CPUINFO_INT_REGISTER + SH2_R7: info->i = sh2->r[ 7]; break;
+ case CPUINFO_INT_REGISTER + SH2_R8: info->i = sh2->r[ 8]; break;
+ case CPUINFO_INT_REGISTER + SH2_R9: info->i = sh2->r[ 9]; break;
+ case CPUINFO_INT_REGISTER + SH2_R10: info->i = sh2->r[10]; break;
+ case CPUINFO_INT_REGISTER + SH2_R11: info->i = sh2->r[11]; break;
+ case CPUINFO_INT_REGISTER + SH2_R12: info->i = sh2->r[12]; break;
+ case CPUINFO_INT_REGISTER + SH2_R13: info->i = sh2->r[13]; break;
+ case CPUINFO_INT_REGISTER + SH2_R14: info->i = sh2->r[14]; break;
+ case CPUINFO_INT_REGISTER + SH2_R15: info->i = sh2->r[15]; break;
+ case CPUINFO_INT_REGISTER + SH2_EA: info->i = sh2->ea; 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(sh2); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(sh2); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(sh2); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(sh2); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(sh2); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(sh2); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &sh2->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "SH-2"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Hitachi SuperH RISC"); 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 Nicola Salmoria and the MAME team, all rights reserved."); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%d%c%c",
+ sh2->sr & M ? 'M':'.',
+ sh2->sr & Q ? 'Q':'.',
+ (sh2->sr & I) >> 4,
+ sh2->sr & S ? 'S':'.',
+ sh2->sr & T ? 'T':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + SH2_PC: sprintf(info->s, "PC :%08X", sh2->pc); break;
+ case CPUINFO_STR_REGISTER + SH2_SR: sprintf(info->s, "SR :%08X", sh2->sr); break;
+ case CPUINFO_STR_REGISTER + SH2_PR: sprintf(info->s, "PR :%08X", sh2->pr); break;
+ case CPUINFO_STR_REGISTER + SH2_GBR: sprintf(info->s, "GBR :%08X", sh2->gbr); break;
+ case CPUINFO_STR_REGISTER + SH2_VBR: sprintf(info->s, "VBR :%08X", sh2->vbr); break;
+ case CPUINFO_STR_REGISTER + SH2_MACH: sprintf(info->s, "MACH:%08X", sh2->mach); break;
+ case CPUINFO_STR_REGISTER + SH2_MACL: sprintf(info->s, "MACL:%08X", sh2->macl); break;
+ case CPUINFO_STR_REGISTER + SH2_R0: sprintf(info->s, "R0 :%08X", sh2->r[ 0]); break;
+ case CPUINFO_STR_REGISTER + SH2_R1: sprintf(info->s, "R1 :%08X", sh2->r[ 1]); break;
+ case CPUINFO_STR_REGISTER + SH2_R2: sprintf(info->s, "R2 :%08X", sh2->r[ 2]); break;
+ case CPUINFO_STR_REGISTER + SH2_R3: sprintf(info->s, "R3 :%08X", sh2->r[ 3]); break;
+ case CPUINFO_STR_REGISTER + SH2_R4: sprintf(info->s, "R4 :%08X", sh2->r[ 4]); break;
+ case CPUINFO_STR_REGISTER + SH2_R5: sprintf(info->s, "R5 :%08X", sh2->r[ 5]); break;
+ case CPUINFO_STR_REGISTER + SH2_R6: sprintf(info->s, "R6 :%08X", sh2->r[ 6]); break;
+ case CPUINFO_STR_REGISTER + SH2_R7: sprintf(info->s, "R7 :%08X", sh2->r[ 7]); break;
+ case CPUINFO_STR_REGISTER + SH2_R8: sprintf(info->s, "R8 :%08X", sh2->r[ 8]); break;
+ case CPUINFO_STR_REGISTER + SH2_R9: sprintf(info->s, "R9 :%08X", sh2->r[ 9]); break;
+ case CPUINFO_STR_REGISTER + SH2_R10: sprintf(info->s, "R10 :%08X", sh2->r[10]); break;
+ case CPUINFO_STR_REGISTER + SH2_R11: sprintf(info->s, "R11 :%08X", sh2->r[11]); break;
+ case CPUINFO_STR_REGISTER + SH2_R12: sprintf(info->s, "R12 :%08X", sh2->r[12]); break;
+ case CPUINFO_STR_REGISTER + SH2_R13: sprintf(info->s, "R13 :%08X", sh2->r[13]); break;
+ case CPUINFO_STR_REGISTER + SH2_R14: sprintf(info->s, "R14 :%08X", sh2->r[14]); break;
+ case CPUINFO_STR_REGISTER + SH2_R15: sprintf(info->s, "R15 :%08X", sh2->r[15]); break;
+ case CPUINFO_STR_REGISTER + SH2_EA: sprintf(info->s, "EA :%08X", sh2->ea); break;
+ }
+}
+
+/*-------------------------------------------------
+ sh1_get_info - return information about a
+ given CPU instance
+-------------------------------------------------*/
+
+CPU_GET_INFO( sh1 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(sh1); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "SH-1"); break;
+
+ default: CPU_GET_INFO_CALL(sh2); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(SH1, sh1);
+DEFINE_LEGACY_CPU_DEVICE(SH2, sh2);
+
+#endif // USE_SH2DRC
diff --git a/trunk/src/emu/cpu/sh2/sh2fe.c b/trunk/src/emu/cpu/sh2/sh2fe.c
new file mode 100644
index 00000000000..5cbc7c3f57b
--- /dev/null
+++ b/trunk/src/emu/cpu/sh2/sh2fe.c
@@ -0,0 +1,764 @@
+/***************************************************************************
+
+ sh2fe.c
+
+ Front end for SH-2 recompiler
+
+ Released for general non-commercial use under the MAME license
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "sh2.h"
+#include "sh2comn.h"
+#include "cpu/drcfe.h"
+
+#ifdef USE_SH2DRC
+/***************************************************************************
+ INSTRUCTION PARSERS
+***************************************************************************/
+
+sh2_frontend::sh2_frontend(sh2_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_instruction - build a description
+ of a single instruction
+-------------------------------------------------*/
+
+bool sh2_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
+{
+ UINT16 opcode;
+
+ /* fetch the opcode */
+ opcode = desc.opptr.w[0] = m_context.direct->read_decrypted_word(desc.physpc, SH2_CODE_XOR(0));
+
+ /* all instructions are 2 bytes and most are a single cycle */
+ desc.length = 2;
+ desc.cycles = 1;
+
+ switch (opcode>>12)
+ {
+ case 0:
+ return describe_group_0(desc, prev, opcode);
+
+ case 1: // MOVLS4
+ desc.regin[0] |= REGFLAG_R(Rn) | REGFLAG_R(Rm);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 2:
+ return describe_group_2(desc, prev, opcode);
+
+ case 3:
+ return describe_group_3(desc, prev, opcode);
+
+ case 4:
+ return describe_group_4(desc, prev, opcode);
+
+ case 5: // MOVLL4
+ desc.regin[0] |= REGFLAG_R(Rm);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 6:
+ return describe_group_6(desc, prev, opcode);
+
+ case 7: // ADDI
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ return true;
+
+ case 8:
+ return describe_group_8(desc, prev, opcode);
+
+ case 9: // MOVWI
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 11: // BSR
+ desc.regout[1] |= REGFLAG_PR;
+ // (intentional fallthrough - BSR is BRA with the addition of PR = the return address)
+ case 10: // BRA
+ {
+ INT32 disp = ((INT32)opcode << 20) >> 20;
+
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.targetpc = (desc.pc + 2) + disp * 2 + 2;
+ desc.delayslots = 1;
+ desc.cycles = 2;
+ return true;
+ }
+
+ case 12:
+ return describe_group_12(desc, prev, opcode);
+
+ case 13: // MOVLI
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 14: // MOVI
+ desc.regout[0] |= REGFLAG_R(Rn);
+ return true;
+
+ case 15: // NOP
+ return true;
+ }
+
+ return false;
+}
+
+bool sh2_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode)
+{
+ switch (opcode & 0x3F)
+ {
+ case 0x00: // NOP();
+ case 0x01: // NOP();
+ case 0x09: // NOP();
+ case 0x10: // NOP();
+ case 0x11: // NOP();
+ case 0x13: // NOP();
+ case 0x20: // NOP();
+ case 0x21: // NOP();
+ case 0x30: // NOP();
+ case 0x31: // NOP();
+ case 0x32: // NOP();
+ case 0x33: // NOP();
+ case 0x38: // NOP();
+ case 0x39: // NOP();
+ case 0x3a: // NOP();
+ case 0x3b: // NOP();
+ return true;
+
+ case 0x02: // STCSR(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ return true;
+
+ case 0x03: // BSRF(Rn);
+ desc.regout[1] |= REGFLAG_PR;
+
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.targetpc = BRANCH_TARGET_DYNAMIC;
+ desc.delayslots = 1;
+
+ return true;
+
+ case 0x04: // MOVBS0(Rm, Rn);
+ case 0x05: // MOVWS0(Rm, Rn);
+ case 0x06: // MOVLS0(Rm, Rn);
+ case 0x14: // MOVBS0(Rm, Rn);
+ case 0x15: // MOVWS0(Rm, Rn);
+ case 0x16: // MOVLS0(Rm, Rn);
+ case 0x24: // MOVBS0(Rm, Rn);
+ case 0x25: // MOVWS0(Rm, Rn);
+ case 0x26: // MOVLS0(Rm, Rn);
+ case 0x34: // MOVBS0(Rm, Rn);
+ case 0x35: // MOVWS0(Rm, Rn);
+ case 0x36: // MOVLS0(Rm, Rn);
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn) | REGFLAG_R(0);
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 0x07: // MULL(Rm, Rn);
+ case 0x17: // MULL(Rm, Rn);
+ case 0x27: // MULL(Rm, Rn);
+ case 0x37: // MULL(Rm, Rn);
+ desc.regin[0] |= REGFLAG_R(Rn) | REGFLAG_R(Rm);
+ desc.regout[1] |= REGFLAG_MACL;
+ desc.cycles = 2;
+ return true;
+
+ case 0x08: // CLRT();
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
+
+ case 0x0a: // STSMACH(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_MACH;
+ return true;
+
+ case 0x0b: // RTS();
+ desc.regin[1] |= REGFLAG_PR;
+
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.targetpc = BRANCH_TARGET_DYNAMIC;
+ desc.delayslots = 1;
+ desc.cycles = 2;
+
+ return true;
+
+ case 0x0c: // MOVBL0(Rm, Rn);
+ case 0x0d: // MOVWL0(Rm, Rn);
+ case 0x0e: // MOVLL0(Rm, Rn);
+ case 0x1c: // MOVBL0(Rm, Rn);
+ case 0x1d: // MOVWL0(Rm, Rn);
+ case 0x1e: // MOVLL0(Rm, Rn);
+ case 0x2c: // MOVBL0(Rm, Rn);
+ case 0x2d: // MOVWL0(Rm, Rn);
+ case 0x2e: // MOVLL0(Rm, Rn);
+ case 0x3c: // MOVBL0(Rm, Rn);
+ case 0x3d: // MOVWL0(Rm, Rn);
+ case 0x3e: // MOVLL0(Rm, Rn);
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(0);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 0x0f: // MAC_L(Rm, Rn);
+ case 0x1f: // MAC_L(Rm, Rn);
+ case 0x2f: // MAC_L(Rm, Rn);
+ case 0x3f: // MAC_L(Rm, Rn);
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH;
+ desc.cycles = 3;
+ return true;
+
+ case 0x12: // STCGBR(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regin[1] |= REGFLAG_GBR;
+ return true;
+
+ case 0x18: // SETT();
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
+
+ case 0x19: // DIV0U();
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
+
+ case 0x1a: // STSMACL(Rn);
+ desc.regin[1] |= REGFLAG_MACL;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ return true;
+
+ case 0x1b: // SLEEP();
+ desc.cycles = 3;
+ return true;
+
+ case 0x22: // STCVBR(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_VBR;
+ return true;
+
+ case 0x23: // BRAF(Rn);
+ desc.regin[0] |= REGFLAG_R(Rm);
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.targetpc = BRANCH_TARGET_DYNAMIC;
+ desc.delayslots = 1;
+ desc.cycles = 2;
+ return true;
+
+ case 0x28: // CLRMAC();
+ desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH;
+ return true;
+
+ case 0x29: // MOVT(Rn);
+ desc.regin[1] |= REGFLAG_SR;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ return true;
+
+ case 0x2a: // STSPR(Rn);
+ desc.regin[1] |= REGFLAG_PR;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ return true;
+
+ case 0x2b: // RTE();
+ desc.regin[0] |= REGFLAG_R(15);
+ desc.regout[0] |= REGFLAG_R(15);
+
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE | OPFLAG_CAN_EXPOSE_EXTERNAL_INT;
+ desc.targetpc = BRANCH_TARGET_DYNAMIC;
+ desc.delayslots = 1;
+ desc.cycles = 4;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool sh2_frontend::describe_group_2(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode)
+{
+ switch (opcode & 15)
+ {
+ case 0: // MOVBS(Rm, Rn);
+ case 1: // MOVWS(Rm, Rn);
+ case 2: // MOVLS(Rm, Rn);
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 3: // NOP();
+ return true;
+
+ case 4: // MOVBM(Rm, Rn);
+ case 5: // MOVWM(Rm, Rn);
+ case 6: // MOVLM(Rm, Rn);
+ case 13: // XTRCT(Rm, Rn);
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 7: // DIV0S(Rm, Rn);
+ case 8: // TST(Rm, Rn);
+ case 12: // CMPSTR(Rm, Rn);
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
+
+ case 9: // AND(Rm, Rn);
+ case 10: // XOR(Rm, Rn);
+ case 11: // OR(Rm, Rn);
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ return true;
+
+ case 14: // MULU(Rm, Rn);
+ case 15: // MULS(Rm, Rn);
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH;
+ desc.cycles = 2;
+ return true;
+ }
+
+ return false;
+}
+
+bool sh2_frontend::describe_group_3(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode)
+{
+ switch (opcode & 15)
+ {
+ case 0: // CMPEQ(Rm, Rn);
+ case 2: // CMPHS(Rm, Rn);
+ case 3: // CMPGE(Rm, Rn);
+ case 6: // CMPHI(Rm, Rn);
+ case 7: // CMPGT(Rm, Rn);
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
+
+ case 1: // NOP();
+ case 9: // NOP();
+ return true;
+
+ case 4: // DIV1(Rm, Rn);
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
+
+ case 5: // DMULU(Rm, Rn);
+ case 13: // DMULS(Rm, Rn);
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH;
+ desc.cycles = 2;
+ return true;
+
+ case 8: // SUB(Rm, Rn);
+ case 12: // ADD(Rm, Rn);
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ return true;
+
+ case 10: // SUBC(Rm, Rn);
+ case 11: // SUBV(Rm, Rn);
+ case 14: // ADDC(Rm, Rn);
+ case 15: // ADDV(Rm, Rn);
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regin[1] |= REGFLAG_SR;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
+ }
+ return false;
+}
+
+bool sh2_frontend::describe_group_4(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode)
+{
+ switch (opcode & 0x3F)
+ {
+ case 0x00: // SHLL(Rn);
+ case 0x01: // SHLR(Rn);
+ case 0x04: // ROTL(Rn);
+ case 0x05: // ROTR(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
+
+ case 0x02: // STSMMACH(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[1] |= REGFLAG_MACH;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 0x03: // STCMSR(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.cycles = 2;
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 0x06: // LDSMMACH(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_MACH;
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 0x07: // LDCMSR(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_SR;
+ desc.cycles = 3;
+ desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_END_SEQUENCE;
+ return true;
+
+ case 0x08: // SHLL2(Rn);
+ case 0x09: // SHLR2(Rn);
+ case 0x18: // SHLL8(Rn);
+ case 0x19: // SHLR8(Rn);
+ case 0x28: // SHLL16(Rn);
+ case 0x29: // SHLR16(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ return true;
+
+ case 0x0a: // LDSMACH(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_MACH;
+ return true;
+
+ case 0x0b: // JSR(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_PR;
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.targetpc = BRANCH_TARGET_DYNAMIC;
+ desc.delayslots = 1;
+ return true;
+
+ case 0x0e: // LDCSR(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_SR;
+ desc.flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_END_SEQUENCE;
+ return true;
+
+ case 0x0f: // MAC_W(Rm, Rn);
+ case 0x1f: // MAC_W(Rm, Rn);
+ case 0x2f: // MAC_W(Rm, Rn);
+ case 0x3f: // MAC_W(Rm, Rn);
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regin[1] |= REGFLAG_MACL | REGFLAG_MACH;
+ desc.regout[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH;
+ desc.cycles = 3;
+ return true;
+
+ case 0x10: // DT(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[1] |= REGFLAG_SR;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
+
+ case 0x11: // CMPPZ(Rn);
+ case 0x15: // CMPPL(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[1] |= REGFLAG_SR;
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
+
+ case 0x12: // STSMMACL(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[1] |= REGFLAG_MACL;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 0x13: // STCMGBR(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[1] |= REGFLAG_GBR;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 0x16: // LDSMMACL(Rn);
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_MACL;
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 0x17: // LDCMGBR(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_GBR;
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 0x1a: // LDSMACL(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_MACL;
+ return true;
+
+ case 0x1b: // TAS(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[1] |= REGFLAG_SR;
+ desc.regout[1] |= REGFLAG_SR;
+ desc.cycles = 4;
+ desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 0x1e: // LDCGBR(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_GBR;
+ return true;
+
+ case 0x20: // SHAL(Rn);
+ case 0x21: // SHAR(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
+
+ case 0x22: // STSMPR(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[1] |= REGFLAG_PR;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 0x23: // STCMVBR(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[1] |= REGFLAG_VBR;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 0x24: // ROTCL(Rn);
+ case 0x25: // ROTCR(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[1] |= REGFLAG_SR;
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
+
+ case 0x26: // LDSMPR(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_PR;
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 0x27: // LDCMVBR(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_VBR;
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 0x2a: // LDSPR(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_PR;
+ return true;
+
+ case 0x2b: // JMP(Rm);
+ desc.regin[0] |= REGFLAG_R(Rm);
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.targetpc = BRANCH_TARGET_DYNAMIC;
+ desc.delayslots = 1;
+ return true;
+
+ case 0x2e: // LDCVBR(Rn);
+ desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_VBR;
+ return true;
+
+ case 0x0c: // NOP();
+ case 0x0d: // NOP();
+ case 0x14: // NOP();
+ case 0x1c: // NOP();
+ case 0x1d: // NOP();
+ case 0x2c: // NOP();
+ case 0x2d: // NOP();
+ case 0x30: // NOP();
+ case 0x31: // NOP();
+ case 0x32: // NOP();
+ case 0x33: // NOP();
+ case 0x34: // NOP();
+ case 0x35: // NOP();
+ case 0x36: // NOP();
+ case 0x37: // NOP();
+ case 0x38: // NOP();
+ case 0x39: // NOP();
+ case 0x3a: // NOP();
+ case 0x3b: // NOP();
+ case 0x3c: // NOP();
+ case 0x3d: // NOP();
+ case 0x3e: // NOP();
+ return true;
+ }
+
+ return false;
+}
+
+bool sh2_frontend::describe_group_6(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode)
+{
+ switch (opcode & 15)
+ {
+ case 0: // MOVBL(Rm, Rn);
+ case 1: // MOVWL(Rm, Rn);
+ case 2: // MOVLL(Rm, Rn);
+ case 3: // MOV(Rm, Rn);
+ case 7: // NOT(Rm, Rn);
+ case 9: // SWAPW(Rm, Rn);
+ case 11: // NEG(Rm, Rn);
+ case 12: // EXTUB(Rm, Rn);
+ case 13: // EXTUW(Rm, Rn);
+ case 14: // EXTSB(Rm, Rn);
+ case 15: // EXTSW(Rm, Rn);
+ desc.regin[0] |= REGFLAG_R(Rm);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ return true;
+
+ case 4: // MOVBP(Rm, Rn);
+ case 5: // MOVWP(Rm, Rn);
+ case 6: // MOVLP(Rm, Rn);
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 8: // SWAPB(Rm, Rn);
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ return true;
+
+ case 10: // NEGC(Rm, Rn);
+ desc.regin[0] |= REGFLAG_R(Rm);
+ desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
+ }
+ return false;
+}
+
+bool sh2_frontend::describe_group_8(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode)
+{
+ INT32 disp;
+
+ switch ( opcode & (15<<8) )
+ {
+ case 0 << 8: // MOVBS4(opcode & 0x0f, Rm);
+ case 1 << 8: // MOVWS4(opcode & 0x0f, Rm);
+ desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(0);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 2<< 8: // NOP();
+ case 3<< 8: // NOP();
+ case 6<< 8: // NOP();
+ case 7<< 8: // NOP();
+ case 10<< 8: // NOP();
+ case 12<< 8: // NOP();
+ case 14<< 8: // NOP();
+ return true;
+
+ case 4<< 8: // MOVBL4(Rm, opcode & 0x0f);
+ case 5<< 8: // MOVWL4(Rm, opcode & 0x0f);
+ desc.regin[0] |= REGFLAG_R(Rm);
+ desc.regout[0] |= REGFLAG_R(0);
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 8<< 8: // CMPIM(opcode & 0xff);
+ desc.regin[0] |= REGFLAG_R(Rm);
+ desc.regin[1] |= REGFLAG_SR;
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
+
+ case 9<< 8: // BT(opcode & 0xff);
+ case 11<< 8: // BF(opcode & 0xff);
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc.cycles = 3;
+ disp = ((INT32)opcode << 24) >> 24;
+ desc.targetpc = (desc.pc + 2) + disp * 2 + 2;
+ return true;
+
+ case 13<< 8: // BTS(opcode & 0xff);
+ case 15<< 8: // BFS(opcode & 0xff);
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc.cycles = 2;
+ disp = ((INT32)opcode << 24) >> 24;
+ desc.targetpc = (desc.pc + 2) + disp * 2 + 2;
+ desc.delayslots = 1;
+ return true;
+ }
+
+ return false;
+}
+
+bool sh2_frontend::describe_group_12(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode)
+{
+ switch (opcode & (15<<8))
+ {
+ case 0<<8: // MOVBSG(opcode & 0xff);
+ case 1<<8: // MOVWSG(opcode & 0xff);
+ case 2<<8: // MOVLSG(opcode & 0xff);
+ desc.regin[0] |= REGFLAG_R(0);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 3<<8: // TRAPA(opcode & 0xff);
+ desc.regin[0] |= REGFLAG_R(15);
+ desc.regin[1] |= REGFLAG_VBR;
+ desc.regout[0] |= REGFLAG_R(15);
+ desc.cycles = 8;
+ desc.targetpc = BRANCH_TARGET_DYNAMIC;
+ desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ return true;
+
+ case 4<<8: // MOVBLG(opcode & 0xff);
+ case 5<<8: // MOVWLG(opcode & 0xff);
+ case 6<<8: // MOVLLG(opcode & 0xff);
+ case 7<<8: // MOVA(opcode & 0xff);
+ desc.regout[0] |= REGFLAG_R(0);
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 8<<8: // TSTI(opcode & 0xff);
+ desc.regin[0] |= REGFLAG_R(0);
+ desc.regin[1] |= REGFLAG_SR;
+ desc.regout[1] |= REGFLAG_SR;
+ return true;
+
+ case 9<<8: // ANDI(opcode & 0xff);
+ case 10<<8: // XORI(opcode & 0xff);
+ case 11<<8: // ORI(opcode & 0xff);
+ desc.regin[0] |= REGFLAG_R(0);
+ desc.regout[0] |= REGFLAG_R(0);
+ return true;
+
+ case 12<<8: // TSTM(opcode & 0xff);
+ case 13<<8: // ANDM(opcode & 0xff);
+ case 14<<8: // XORM(opcode & 0xff);
+ case 15<<8: // ORM(opcode & 0xff);
+ desc.regin[0] |= REGFLAG_R(0);
+ desc.regin[1] |= REGFLAG_SR | REGFLAG_GBR;
+ desc.regout[1] |= REGFLAG_SR;
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+ }
+
+ return false;
+}
+#endif
diff --git a/trunk/src/emu/cpu/sh4/sh4.c b/trunk/src/emu/cpu/sh4/sh4.c
new file mode 100644
index 00000000000..bf74d97941b
--- /dev/null
+++ b/trunk/src/emu/cpu/sh4/sh4.c
@@ -0,0 +1,3852 @@
+/*****************************************************************************
+ *
+ * sh4.c
+ * Portable Hitachi SH-4 (SH7750 family) emulator
+ *
+ * By R. Belmont, based on sh2.c by Juergen Buchmueller, Mariusz Wojcieszek,
+ * Olivier Galibert, Sylvain Glaize, and James Forshaw.
+ *
+ *
+ * TODO: FPU
+ * DMA
+ * on-board peripherals
+ *
+ * DONE: boot/reset setup
+ * 64-bit data bus
+ * banked registers
+ * additional registers for supervisor mode
+ * FPU status and data registers
+ * state save for the new registers
+ * interrupts
+ * store queues
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "sh4.h"
+#include "sh4regs.h"
+#include "sh4comn.h"
+
+#ifndef USE_SH4DRC
+
+CPU_DISASSEMBLE( sh4 );
+
+/* Called for unimplemented opcodes */
+static void TODO(sh4_state *sh4)
+{
+}
+
+#if 0
+int sign_of(int n)
+{
+ return(sh4->fr[n]>>31);
+}
+
+void zero(int n,int sign)
+{
+if (sign == 0)
+ sh4->fr[n] = 0x00000000;
+else
+ sh4->fr[n] = 0x80000000;
+if ((sh4->fpscr & PR) == 1)
+ sh4->fr[n+1] = 0x00000000;
+}
+
+int data_type_of(int n)
+{
+UINT32 abs;
+
+ abs = sh4->fr[n] & 0x7fffffff;
+ if ((sh4->fpscr & PR) == 0) { /* Single-precision */
+ if (abs < 0x00800000) {
+ if (((sh4->fpscr & DN) == 1) || (abs == 0x00000000)) {
+ if (sign_of(n) == 0) {
+ zero(n, 0);
+ return(SH4_FPU_PZERO);
+ } else {
+ zero(n, 1);
+ return(SH4_FPU_NZERO);
+ }
+ } else
+ return(SH4_FPU_DENORM);
+ } else
+ if (abs < 0x7f800000)
+ return(SH4_FPU_NORM);
+ else
+ if (abs == 0x7f800000) {
+ if (sign_of(n) == 0)
+ return(SH4_FPU_PINF);
+ else
+ return(SH4_FPU_NINF);
+ } else
+ if (abs < 0x7fc00000)
+ return(SH4_FPU_qNaN);
+ else
+ return(SH4_FPU_sNaN);
+ } else { /* Double-precision */
+ if (abs < 0x00100000) {
+ if (((sh4->fpscr & DN) == 1) || ((abs == 0x00000000) && (sh4->fr[n+1] == 0x00000000))) {
+ if(sign_of(n) == 0) {
+ zero(n, 0);
+ return(SH4_FPU_PZERO);
+ } else {
+ zero(n, 1);
+ return(SH4_FPU_NZERO);
+ }
+ } else
+ return(SH4_FPU_DENORM);
+ } else
+ if (abs < 0x7ff00000)
+ return(SH4_FPU_NORM);
+ else
+ if ((abs == 0x7ff00000) && (sh4->fr[n+1] == 0x00000000)) {
+ if (sign_of(n) == 0)
+ return(SH4_FPU_PINF);
+ else
+ return(SH4_FPU_NINF);
+ } else
+ if (abs < 0x7ff80000)
+ return(SH4_FPU_qNaN);
+ else
+ return(SH4_FPU_sNaN);
+ }
+ return(SH4_FPU_NORM);
+}
+#endif
+
+INLINE UINT8 RB(sh4_state *sh4, offs_t A)
+{
+ if (A >= 0xe0000000)
+ return sh4->program->read_byte(A);
+
+ return sh4->program->read_byte(A & AM);
+}
+
+INLINE UINT16 RW(sh4_state *sh4, offs_t A)
+{
+ if (A >= 0xe0000000)
+ return sh4->program->read_word(A);
+
+ return sh4->program->read_word(A & AM);
+}
+
+INLINE UINT32 RL(sh4_state *sh4, offs_t A)
+{
+ if (A >= 0xe0000000)
+ return sh4->program->read_dword(A);
+
+ return sh4->program->read_dword(A & AM);
+}
+
+INLINE void WB(sh4_state *sh4, offs_t A, UINT8 V)
+{
+ if (A >= 0xe0000000)
+ {
+ sh4->program->write_byte(A,V);
+ return;
+ }
+
+ sh4->program->write_byte(A & AM,V);
+}
+
+INLINE void WW(sh4_state *sh4, offs_t A, UINT16 V)
+{
+ if (A >= 0xe0000000)
+ {
+ sh4->program->write_word(A,V);
+ return;
+ }
+
+ sh4->program->write_word(A & AM,V);
+}
+
+INLINE void WL(sh4_state *sh4, offs_t A, UINT32 V)
+{
+ if (A >= 0xe0000000)
+ {
+ sh4->program->write_dword(A,V);
+ return;
+ }
+
+ sh4->program->write_dword(A & AM,V);
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 1100 1 -
+ * ADD Rm,Rn
+ */
+INLINE void ADD(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] += sh4->r[m];
+}
+
+/* code cycles t-bit
+ * 0111 nnnn iiii iiii 1 -
+ * ADD #imm,Rn
+ */
+INLINE void ADDI(sh4_state *sh4, UINT32 i, UINT32 n)
+{
+ sh4->r[n] += (INT32)(INT16)(INT8)i;
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 1110 1 carry
+ * ADDC Rm,Rn
+ */
+INLINE void ADDC(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ UINT32 tmp0, tmp1;
+
+ tmp1 = sh4->r[n] + sh4->r[m];
+ tmp0 = sh4->r[n];
+ sh4->r[n] = tmp1 + (sh4->sr & T);
+ if (tmp0 > tmp1)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+ if (tmp1 > sh4->r[n])
+ sh4->sr |= T;
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 1111 1 overflow
+ * ADDV Rm,Rn
+ */
+INLINE void ADDV(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ INT32 dest, src, ans;
+
+ if ((INT32) sh4->r[n] >= 0)
+ dest = 0;
+ else
+ dest = 1;
+ if ((INT32) sh4->r[m] >= 0)
+ src = 0;
+ else
+ src = 1;
+ src += dest;
+ sh4->r[n] += sh4->r[m];
+ if ((INT32) sh4->r[n] >= 0)
+ ans = 0;
+ else
+ ans = 1;
+ ans += dest;
+ if (src == 0 || src == 2)
+ {
+ if (ans == 1)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+ }
+ else
+ sh4->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0010 nnnn mmmm 1001 1 -
+ * AND Rm,Rn
+ */
+INLINE void AND(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] &= sh4->r[m];
+}
+
+
+/* code cycles t-bit
+ * 1100 1001 iiii iiii 1 -
+ * AND #imm,R0
+ */
+INLINE void ANDI(sh4_state *sh4, UINT32 i)
+{
+ sh4->r[0] &= i;
+}
+
+/* code cycles t-bit
+ * 1100 1101 iiii iiii 1 -
+ * AND.B #imm,@(R0,GBR)
+ */
+INLINE void ANDM(sh4_state *sh4, UINT32 i)
+{
+ UINT32 temp;
+
+ sh4->ea = sh4->gbr + sh4->r[0];
+ temp = i & RB(sh4, sh4->ea );
+ WB(sh4, sh4->ea, temp );
+ sh4->sh4_icount -= 2;
+}
+
+/* code cycles t-bit
+ * 1000 1011 dddd dddd 3/1 -
+ * BF disp8
+ */
+INLINE void BF(sh4_state *sh4, UINT32 d)
+{
+ if ((sh4->sr & T) == 0)
+ {
+ INT32 disp = ((INT32)d << 24) >> 24;
+ sh4->pc = sh4->ea = sh4->pc + disp * 2 + 2;
+ sh4->sh4_icount -= 2;
+ }
+}
+
+/* code cycles t-bit
+ * 1000 1111 dddd dddd 3/1 -
+ * BFS disp8
+ */
+INLINE void BFS(sh4_state *sh4, UINT32 d)
+{
+ if ((sh4->sr & T) == 0)
+ {
+ INT32 disp = ((INT32)d << 24) >> 24;
+ sh4->delay = sh4->pc;
+ sh4->pc = sh4->ea = sh4->pc + disp * 2 + 2;
+ sh4->sh4_icount--;
+ }
+}
+
+/* code cycles t-bit
+ * 1010 dddd dddd dddd 2 -
+ * BRA disp12
+ */
+INLINE void BRA(sh4_state *sh4, UINT32 d)
+{
+ INT32 disp = ((INT32)d << 20) >> 20;
+
+#if BUSY_LOOP_HACKS
+ if (disp == -2)
+ {
+ UINT32 next_opcode = RW(sh4,sh4->ppc & AM);
+ /* BRA $
+ * NOP
+ */
+ if (next_opcode == 0x0009)
+ sh4->sh4_icount %= 3; /* cycles for BRA $ and NOP taken (3) */
+ }
+#endif
+ sh4->delay = sh4->pc;
+ sh4->pc = sh4->ea = sh4->pc + disp * 2 + 2;
+ sh4->sh4_icount--;
+}
+
+/* code cycles t-bit
+ * 0000 mmmm 0010 0011 2 -
+ * BRAF Rm
+ */
+INLINE void BRAF(sh4_state *sh4, UINT32 m)
+{
+ sh4->delay = sh4->pc;
+ sh4->pc += sh4->r[m] + 2;
+ sh4->sh4_icount--;
+}
+
+/* code cycles t-bit
+ * 1011 dddd dddd dddd 2 -
+ * BSR disp12
+ */
+INLINE void BSR(sh4_state *sh4, UINT32 d)
+{
+ INT32 disp = ((INT32)d << 20) >> 20;
+
+ sh4->pr = sh4->pc + 2;
+ sh4->delay = sh4->pc;
+ sh4->pc = sh4->ea = sh4->pc + disp * 2 + 2;
+ sh4->sh4_icount--;
+}
+
+/* code cycles t-bit
+ * 0000 mmmm 0000 0011 2 -
+ * BSRF Rm
+ */
+INLINE void BSRF(sh4_state *sh4, UINT32 m)
+{
+ sh4->pr = sh4->pc + 2;
+ sh4->delay = sh4->pc;
+ sh4->pc += sh4->r[m] + 2;
+ sh4->sh4_icount--;
+}
+
+/* code cycles t-bit
+ * 1000 1001 dddd dddd 3/1 -
+ * BT disp8
+ */
+INLINE void BT(sh4_state *sh4, UINT32 d)
+{
+ if ((sh4->sr & T) != 0)
+ {
+ INT32 disp = ((INT32)d << 24) >> 24;
+ sh4->pc = sh4->ea = sh4->pc + disp * 2 + 2;
+ sh4->sh4_icount -= 2;
+ }
+}
+
+/* code cycles t-bit
+ * 1000 1101 dddd dddd 2/1 -
+ * BTS disp8
+ */
+INLINE void BTS(sh4_state *sh4, UINT32 d)
+{
+ if ((sh4->sr & T) != 0)
+ {
+ INT32 disp = ((INT32)d << 24) >> 24;
+ sh4->delay = sh4->pc;
+ sh4->pc = sh4->ea = sh4->pc + disp * 2 + 2;
+ sh4->sh4_icount--;
+ }
+}
+
+/* code cycles t-bit
+ * 0000 0000 0010 1000 1 -
+ * CLRMAC
+ */
+INLINE void CLRMAC(sh4_state *sh4)
+{
+ sh4->mach = 0;
+ sh4->macl = 0;
+}
+
+/* code cycles t-bit
+ * 0000 0000 0000 1000 1 -
+ * CLRT
+ */
+INLINE void CLRT(sh4_state *sh4)
+{
+ sh4->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 0000 1 comparison result
+ * CMP_EQ Rm,Rn
+ */
+INLINE void CMPEQ(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ if (sh4->r[n] == sh4->r[m])
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 0011 1 comparison result
+ * CMP_GE Rm,Rn
+ */
+INLINE void CMPGE(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ if ((INT32) sh4->r[n] >= (INT32) sh4->r[m])
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 0111 1 comparison result
+ * CMP_GT Rm,Rn
+ */
+INLINE void CMPGT(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ if ((INT32) sh4->r[n] > (INT32) sh4->r[m])
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 0110 1 comparison result
+ * CMP_HI Rm,Rn
+ */
+INLINE void CMPHI(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ if ((UINT32) sh4->r[n] > (UINT32) sh4->r[m])
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 0010 1 comparison result
+ * CMP_HS Rm,Rn
+ */
+INLINE void CMPHS(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ if ((UINT32) sh4->r[n] >= (UINT32) sh4->r[m])
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+
+/* code cycles t-bit
+ * 0100 nnnn 0001 0101 1 comparison result
+ * CMP_PL Rn
+ */
+INLINE void CMPPL(sh4_state *sh4, UINT32 n)
+{
+ if ((INT32) sh4->r[n] > 0)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0100 nnnn 0001 0001 1 comparison result
+ * CMP_PZ Rn
+ */
+INLINE void CMPPZ(sh4_state *sh4, UINT32 n)
+{
+ if ((INT32) sh4->r[n] >= 0)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0010 nnnn mmmm 1100 1 comparison result
+ * CMP_STR Rm,Rn
+ */
+INLINE void CMPSTR(sh4_state *sh4, UINT32 m, UINT32 n)
+ {
+ UINT32 temp;
+ INT32 HH, HL, LH, LL;
+ temp = sh4->r[n] ^ sh4->r[m];
+ HH = (temp >> 24) & 0xff;
+ HL = (temp >> 16) & 0xff;
+ LH = (temp >> 8) & 0xff;
+ LL = temp & 0xff;
+ if (HH && HL && LH && LL)
+ sh4->sr &= ~T;
+ else
+ sh4->sr |= T;
+ }
+
+
+/* code cycles t-bit
+ * 1000 1000 iiii iiii 1 comparison result
+ * CMP/EQ #imm,R0
+ */
+INLINE void CMPIM(sh4_state *sh4, UINT32 i)
+{
+ UINT32 imm = (UINT32)(INT32)(INT16)(INT8)i;
+
+ if (sh4->r[0] == imm)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0010 nnnn mmmm 0111 1 calculation result
+ * DIV0S Rm,Rn
+ */
+INLINE void DIV0S(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ if ((sh4->r[n] & 0x80000000) == 0)
+ sh4->sr &= ~Q;
+ else
+ sh4->sr |= Q;
+ if ((sh4->r[m] & 0x80000000) == 0)
+ sh4->sr &= ~M;
+ else
+ sh4->sr |= M;
+ if ((sh4->r[m] ^ sh4->r[n]) & 0x80000000)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0000 0000 0001 1001 1 0
+ * DIV0U
+ */
+INLINE void DIV0U(sh4_state *sh4)
+{
+ sh4->sr &= ~(M | Q | T);
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 0100 1 calculation result
+ * DIV1 Rm,Rn
+ */
+INLINE void DIV1(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ UINT32 tmp0;
+ UINT32 old_q;
+
+ old_q = sh4->sr & Q;
+ if (0x80000000 & sh4->r[n])
+ sh4->sr |= Q;
+ else
+ sh4->sr &= ~Q;
+
+ sh4->r[n] = (sh4->r[n] << 1) | (sh4->sr & T);
+
+ if (!old_q)
+ {
+ if (!(sh4->sr & M))
+ {
+ tmp0 = sh4->r[n];
+ sh4->r[n] -= sh4->r[m];
+ if(!(sh4->sr & Q))
+ if(sh4->r[n] > tmp0)
+ sh4->sr |= Q;
+ else
+ sh4->sr &= ~Q;
+ else
+ if(sh4->r[n] > tmp0)
+ sh4->sr &= ~Q;
+ else
+ sh4->sr |= Q;
+ }
+ else
+ {
+ tmp0 = sh4->r[n];
+ sh4->r[n] += sh4->r[m];
+ if(!(sh4->sr & Q))
+ {
+ if(sh4->r[n] < tmp0)
+ sh4->sr &= ~Q;
+ else
+ sh4->sr |= Q;
+ }
+ else
+ {
+ if(sh4->r[n] < tmp0)
+ sh4->sr |= Q;
+ else
+ sh4->sr &= ~Q;
+ }
+ }
+ }
+ else
+ {
+ if (!(sh4->sr & M))
+ {
+ tmp0 = sh4->r[n];
+ sh4->r[n] += sh4->r[m];
+ if(!(sh4->sr & Q))
+ if(sh4->r[n] < tmp0)
+ sh4->sr |= Q;
+ else
+ sh4->sr &= ~Q;
+ else
+ if(sh4->r[n] < tmp0)
+ sh4->sr &= ~Q;
+ else
+ sh4->sr |= Q;
+ }
+ else
+ {
+ tmp0 = sh4->r[n];
+ sh4->r[n] -= sh4->r[m];
+ if(!(sh4->sr & Q))
+ if(sh4->r[n] > tmp0)
+ sh4->sr &= ~Q;
+ else
+ sh4->sr |= Q;
+ else
+ if(sh4->r[n] > tmp0)
+ sh4->sr |= Q;
+ else
+ sh4->sr &= ~Q;
+ }
+ }
+
+ tmp0 = (sh4->sr & (Q | M));
+ if((!tmp0) || (tmp0 == 0x300)) /* if Q == M set T else clear T */
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+/* DMULS.L Rm,Rn */
+INLINE void DMULS(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2;
+ UINT32 temp0, temp1, temp2, temp3;
+ INT32 tempm, tempn, fnLmL;
+
+ tempn = (INT32) sh4->r[n];
+ tempm = (INT32) sh4->r[m];
+ if (tempn < 0)
+ tempn = 0 - tempn;
+ if (tempm < 0)
+ tempm = 0 - tempm;
+ if ((INT32) (sh4->r[n] ^ sh4->r[m]) < 0)
+ fnLmL = -1;
+ else
+ fnLmL = 0;
+ temp1 = (UINT32) tempn;
+ temp2 = (UINT32) tempm;
+ RnL = temp1 & 0x0000ffff;
+ RnH = (temp1 >> 16) & 0x0000ffff;
+ RmL = temp2 & 0x0000ffff;
+ RmH = (temp2 >> 16) & 0x0000ffff;
+ temp0 = RmL * RnL;
+ temp1 = RmH * RnL;
+ temp2 = RmL * RnH;
+ temp3 = RmH * RnH;
+ Res2 = 0;
+ Res1 = temp1 + temp2;
+ if (Res1 < temp1)
+ Res2 += 0x00010000;
+ temp1 = (Res1 << 16) & 0xffff0000;
+ Res0 = temp0 + temp1;
+ if (Res0 < temp0)
+ Res2++;
+ Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3;
+ if (fnLmL < 0)
+ {
+ Res2 = ~Res2;
+ if (Res0 == 0)
+ Res2++;
+ else
+ Res0 = (~Res0) + 1;
+ }
+ sh4->mach = Res2;
+ sh4->macl = Res0;
+ sh4->sh4_icount--;
+}
+
+/* DMULU.L Rm,Rn */
+INLINE void DMULU(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2;
+ UINT32 temp0, temp1, temp2, temp3;
+
+ RnL = sh4->r[n] & 0x0000ffff;
+ RnH = (sh4->r[n] >> 16) & 0x0000ffff;
+ RmL = sh4->r[m] & 0x0000ffff;
+ RmH = (sh4->r[m] >> 16) & 0x0000ffff;
+ temp0 = RmL * RnL;
+ temp1 = RmH * RnL;
+ temp2 = RmL * RnH;
+ temp3 = RmH * RnH;
+ Res2 = 0;
+ Res1 = temp1 + temp2;
+ if (Res1 < temp1)
+ Res2 += 0x00010000;
+ temp1 = (Res1 << 16) & 0xffff0000;
+ Res0 = temp0 + temp1;
+ if (Res0 < temp0)
+ Res2++;
+ Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3;
+ sh4->mach = Res2;
+ sh4->macl = Res0;
+ sh4->sh4_icount--;
+}
+
+/* DT Rn */
+INLINE void DT(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n]--;
+ if (sh4->r[n] == 0)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+#if BUSY_LOOP_HACKS
+ {
+ UINT32 next_opcode = RW(sh4,sh4->ppc & AM);
+ /* DT Rn
+ * BF $-2
+ */
+ if (next_opcode == 0x8bfd)
+ {
+ while (sh4->r[n] > 1 && sh4->sh4_icount > 4)
+ {
+ sh4->r[n]--;
+ sh4->sh4_icount -= 4; /* cycles for DT (1) and BF taken (3) */
+ }
+ }
+ }
+#endif
+}
+
+/* EXTS.B Rm,Rn */
+INLINE void EXTSB(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] = ((INT32)sh4->r[m] << 24) >> 24;
+}
+
+/* EXTS.W Rm,Rn */
+INLINE void EXTSW(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] = ((INT32)sh4->r[m] << 16) >> 16;
+}
+
+/* EXTU.B Rm,Rn */
+INLINE void EXTUB(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] = sh4->r[m] & 0x000000ff;
+}
+
+/* EXTU.W Rm,Rn */
+INLINE void EXTUW(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] = sh4->r[m] & 0x0000ffff;
+}
+
+/* JMP @Rm */
+INLINE void JMP(sh4_state *sh4, UINT32 m)
+{
+ sh4->delay = sh4->pc;
+ sh4->pc = sh4->ea = sh4->r[m];
+}
+
+/* JSR @Rm */
+INLINE void JSR(sh4_state *sh4, UINT32 m)
+{
+ sh4->delay = sh4->pc;
+ sh4->pr = sh4->pc + 2;
+ sh4->pc = sh4->ea = sh4->r[m];
+ sh4->sh4_icount--;
+}
+
+
+/* LDC Rm,SR */
+INLINE void LDCSR(sh4_state *sh4, UINT32 m)
+{
+UINT32 reg;
+
+ reg = sh4->r[m];
+ if ((sh4->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ sh4_syncronize_register_bank(sh4, (sh4->sr & sRB) >> 29);
+ if ((sh4->r[m] & sRB) != (sh4->sr & sRB))
+ sh4_change_register_bank(sh4, sh4->r[m] & sRB ? 1 : 0);
+ sh4->sr = reg & FLAGS;
+ sh4_exception_recompute(sh4);
+}
+
+/* LDC Rm,GBR */
+INLINE void LDCGBR(sh4_state *sh4, UINT32 m)
+{
+ sh4->gbr = sh4->r[m];
+}
+
+/* LDC Rm,VBR */
+INLINE void LDCVBR(sh4_state *sh4, UINT32 m)
+{
+ sh4->vbr = sh4->r[m];
+}
+
+/* LDC.L @Rm+,SR */
+INLINE void LDCMSR(sh4_state *sh4, UINT32 m)
+{
+UINT32 old;
+
+ old = sh4->sr;
+ sh4->ea = sh4->r[m];
+ sh4->sr = RL(sh4, sh4->ea ) & FLAGS;
+ if ((sh4->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ sh4_syncronize_register_bank(sh4, (old & sRB) >> 29);
+ if ((old & sRB) != (sh4->sr & sRB))
+ sh4_change_register_bank(sh4, sh4->sr & sRB ? 1 : 0);
+ sh4->r[m] += 4;
+ sh4->sh4_icount -= 2;
+ sh4_exception_recompute(sh4);
+}
+
+/* LDC.L @Rm+,GBR */
+INLINE void LDCMGBR(sh4_state *sh4, UINT32 m)
+{
+ sh4->ea = sh4->r[m];
+ sh4->gbr = RL(sh4, sh4->ea );
+ sh4->r[m] += 4;
+ sh4->sh4_icount -= 2;
+}
+
+/* LDC.L @Rm+,VBR */
+INLINE void LDCMVBR(sh4_state *sh4, UINT32 m)
+{
+ sh4->ea = sh4->r[m];
+ sh4->vbr = RL(sh4, sh4->ea );
+ sh4->r[m] += 4;
+ sh4->sh4_icount -= 2;
+}
+
+/* LDS Rm,MACH */
+INLINE void LDSMACH(sh4_state *sh4, UINT32 m)
+{
+ sh4->mach = sh4->r[m];
+}
+
+/* LDS Rm,MACL */
+INLINE void LDSMACL(sh4_state *sh4, UINT32 m)
+{
+ sh4->macl = sh4->r[m];
+}
+
+/* LDS Rm,PR */
+INLINE void LDSPR(sh4_state *sh4, UINT32 m)
+{
+ sh4->pr = sh4->r[m];
+}
+
+/* LDS.L @Rm+,MACH */
+INLINE void LDSMMACH(sh4_state *sh4, UINT32 m)
+{
+ sh4->ea = sh4->r[m];
+ sh4->mach = RL(sh4, sh4->ea );
+ sh4->r[m] += 4;
+}
+
+/* LDS.L @Rm+,MACL */
+INLINE void LDSMMACL(sh4_state *sh4, UINT32 m)
+{
+ sh4->ea = sh4->r[m];
+ sh4->macl = RL(sh4, sh4->ea );
+ sh4->r[m] += 4;
+}
+
+/* LDS.L @Rm+,PR */
+INLINE void LDSMPR(sh4_state *sh4, UINT32 m)
+{
+ sh4->ea = sh4->r[m];
+ sh4->pr = RL(sh4, sh4->ea );
+ sh4->r[m] += 4;
+}
+
+/* MAC.L @Rm+,@Rn+ */
+INLINE void MAC_L(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2;
+ UINT32 temp0, temp1, temp2, temp3;
+ INT32 tempm, tempn, fnLmL;
+
+ tempn = (INT32) RL(sh4, sh4->r[n] );
+ sh4->r[n] += 4;
+ tempm = (INT32) RL(sh4, sh4->r[m] );
+ sh4->r[m] += 4;
+ if ((INT32) (tempn ^ tempm) < 0)
+ fnLmL = -1;
+ else
+ fnLmL = 0;
+ if (tempn < 0)
+ tempn = 0 - tempn;
+ if (tempm < 0)
+ tempm = 0 - tempm;
+ temp1 = (UINT32) tempn;
+ temp2 = (UINT32) tempm;
+ RnL = temp1 & 0x0000ffff;
+ RnH = (temp1 >> 16) & 0x0000ffff;
+ RmL = temp2 & 0x0000ffff;
+ RmH = (temp2 >> 16) & 0x0000ffff;
+ temp0 = RmL * RnL;
+ temp1 = RmH * RnL;
+ temp2 = RmL * RnH;
+ temp3 = RmH * RnH;
+ Res2 = 0;
+ Res1 = temp1 + temp2;
+ if (Res1 < temp1)
+ Res2 += 0x00010000;
+ temp1 = (Res1 << 16) & 0xffff0000;
+ Res0 = temp0 + temp1;
+ if (Res0 < temp0)
+ Res2++;
+ Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3;
+ if (fnLmL < 0)
+ {
+ Res2 = ~Res2;
+ if (Res0 == 0)
+ Res2++;
+ else
+ Res0 = (~Res0) + 1;
+ }
+ if (sh4->sr & S)
+ {
+ Res0 = sh4->macl + Res0;
+ if (sh4->macl > Res0)
+ Res2++;
+ Res2 += (sh4->mach & 0x0000ffff);
+ if (((INT32) Res2 < 0) && (Res2 < 0xffff8000))
+ {
+ Res2 = 0x00008000;
+ Res0 = 0x00000000;
+ }
+ else if (((INT32) Res2 > 0) && (Res2 > 0x00007fff))
+ {
+ Res2 = 0x00007fff;
+ Res0 = 0xffffffff;
+ }
+ sh4->mach = Res2;
+ sh4->macl = Res0;
+ }
+ else
+ {
+ Res0 = sh4->macl + Res0;
+ if (sh4->macl > Res0)
+ Res2++;
+ Res2 += sh4->mach;
+ sh4->mach = Res2;
+ sh4->macl = Res0;
+ }
+ sh4->sh4_icount -= 2;
+}
+
+/* MAC.W @Rm+,@Rn+ */
+INLINE void MAC_W(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ INT32 tempm, tempn, dest, src, ans;
+ UINT32 templ;
+
+ tempn = (INT32) RW(sh4, sh4->r[n] );
+ sh4->r[n] += 2;
+ tempm = (INT32) RW(sh4, sh4->r[m] );
+ sh4->r[m] += 2;
+ templ = sh4->macl;
+ tempm = ((INT32) (short) tempn * (INT32) (short) tempm);
+ if ((INT32) sh4->macl >= 0)
+ dest = 0;
+ else
+ dest = 1;
+ if ((INT32) tempm >= 0)
+ {
+ src = 0;
+ tempn = 0;
+ }
+ else
+ {
+ src = 1;
+ tempn = 0xffffffff;
+ }
+ src += dest;
+ sh4->macl += tempm;
+ if ((INT32) sh4->macl >= 0)
+ ans = 0;
+ else
+ ans = 1;
+ ans += dest;
+ if (sh4->sr & S)
+ {
+ if (ans == 1)
+ {
+ if (src == 0)
+ sh4->macl = 0x7fffffff;
+ if (src == 2)
+ sh4->macl = 0x80000000;
+ }
+ }
+ else
+ {
+ sh4->mach += tempn;
+ if (templ > sh4->macl)
+ sh4->mach += 1;
+ }
+ sh4->sh4_icount -= 2;
+}
+
+/* MOV Rm,Rn */
+INLINE void MOV(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] = sh4->r[m];
+}
+
+/* MOV.B Rm,@Rn */
+INLINE void MOVBS(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[n];
+ WB(sh4, sh4->ea, sh4->r[m] & 0x000000ff);
+}
+
+/* MOV.W Rm,@Rn */
+INLINE void MOVWS(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[n];
+ WW(sh4, sh4->ea, sh4->r[m] & 0x0000ffff);
+}
+
+/* MOV.L Rm,@Rn */
+INLINE void MOVLS(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->r[m] );
+}
+
+/* MOV.B @Rm,Rn */
+INLINE void MOVBL(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[m];
+ sh4->r[n] = (UINT32)(INT32)(INT16)(INT8) RB(sh4, sh4->ea );
+}
+
+/* MOV.W @Rm,Rn */
+INLINE void MOVWL(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[m];
+ sh4->r[n] = (UINT32)(INT32)(INT16) RW(sh4, sh4->ea );
+}
+
+/* MOV.L @Rm,Rn */
+INLINE void MOVLL(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[m];
+ sh4->r[n] = RL(sh4, sh4->ea );
+}
+
+/* MOV.B Rm,@-Rn */
+INLINE void MOVBM(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ /* SMG : bug fix, was reading sh4->r[n] */
+ UINT32 data = sh4->r[m] & 0x000000ff;
+
+ sh4->r[n] -= 1;
+ WB(sh4, sh4->r[n], data );
+}
+
+/* MOV.W Rm,@-Rn */
+INLINE void MOVWM(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ UINT32 data = sh4->r[m] & 0x0000ffff;
+
+ sh4->r[n] -= 2;
+ WW(sh4, sh4->r[n], data );
+}
+
+/* MOV.L Rm,@-Rn */
+INLINE void MOVLM(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ UINT32 data = sh4->r[m];
+
+ sh4->r[n] -= 4;
+ WL(sh4, sh4->r[n], data );
+}
+
+/* MOV.B @Rm+,Rn */
+INLINE void MOVBP(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] = (UINT32)(INT32)(INT16)(INT8) RB(sh4, sh4->r[m] );
+ if (n != m)
+ sh4->r[m] += 1;
+}
+
+/* MOV.W @Rm+,Rn */
+INLINE void MOVWP(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] = (UINT32)(INT32)(INT16) RW(sh4, sh4->r[m] );
+ if (n != m)
+ sh4->r[m] += 2;
+}
+
+/* MOV.L @Rm+,Rn */
+INLINE void MOVLP(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] = RL(sh4, sh4->r[m] );
+ if (n != m)
+ sh4->r[m] += 4;
+}
+
+/* MOV.B Rm,@(R0,Rn) */
+INLINE void MOVBS0(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[n] + sh4->r[0];
+ WB(sh4, sh4->ea, sh4->r[m] & 0x000000ff );
+}
+
+/* MOV.W Rm,@(R0,Rn) */
+INLINE void MOVWS0(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[n] + sh4->r[0];
+ WW(sh4, sh4->ea, sh4->r[m] & 0x0000ffff );
+}
+
+/* MOV.L Rm,@(R0,Rn) */
+INLINE void MOVLS0(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[n] + sh4->r[0];
+ WL(sh4, sh4->ea, sh4->r[m] );
+}
+
+/* MOV.B @(R0,Rm),Rn */
+INLINE void MOVBL0(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[m] + sh4->r[0];
+ sh4->r[n] = (UINT32)(INT32)(INT16)(INT8) RB(sh4, sh4->ea );
+}
+
+/* MOV.W @(R0,Rm),Rn */
+INLINE void MOVWL0(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[m] + sh4->r[0];
+ sh4->r[n] = (UINT32)(INT32)(INT16) RW(sh4, sh4->ea );
+}
+
+/* MOV.L @(R0,Rm),Rn */
+INLINE void MOVLL0(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[m] + sh4->r[0];
+ sh4->r[n] = RL(sh4, sh4->ea );
+}
+
+/* MOV #imm,Rn */
+INLINE void MOVI(sh4_state *sh4, UINT32 i, UINT32 n)
+{
+ sh4->r[n] = (UINT32)(INT32)(INT16)(INT8) i;
+}
+
+/* MOV.W @(disp8,PC),Rn */
+INLINE void MOVWI(sh4_state *sh4, UINT32 d, UINT32 n)
+{
+ UINT32 disp = d & 0xff;
+ sh4->ea = sh4->pc + disp * 2 + 2;
+ sh4->r[n] = (UINT32)(INT32)(INT16) RW(sh4, sh4->ea );
+}
+
+/* MOV.L @(disp8,PC),Rn */
+INLINE void MOVLI(sh4_state *sh4, UINT32 d, UINT32 n)
+{
+ UINT32 disp = d & 0xff;
+ sh4->ea = ((sh4->pc + 2) & ~3) + disp * 4;
+ sh4->r[n] = RL(sh4, sh4->ea );
+}
+
+/* MOV.B @(disp8,GBR),R0 */
+INLINE void MOVBLG(sh4_state *sh4, UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh4->ea = sh4->gbr + disp;
+ sh4->r[0] = (UINT32)(INT32)(INT16)(INT8) RB(sh4, sh4->ea );
+}
+
+/* MOV.W @(disp8,GBR),R0 */
+INLINE void MOVWLG(sh4_state *sh4, UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh4->ea = sh4->gbr + disp * 2;
+ sh4->r[0] = (INT32)(INT16) RW(sh4, sh4->ea );
+}
+
+/* MOV.L @(disp8,GBR),R0 */
+INLINE void MOVLLG(sh4_state *sh4, UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh4->ea = sh4->gbr + disp * 4;
+ sh4->r[0] = RL(sh4, sh4->ea );
+}
+
+/* MOV.B R0,@(disp8,GBR) */
+INLINE void MOVBSG(sh4_state *sh4, UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh4->ea = sh4->gbr + disp;
+ WB(sh4, sh4->ea, sh4->r[0] & 0x000000ff );
+}
+
+/* MOV.W R0,@(disp8,GBR) */
+INLINE void MOVWSG(sh4_state *sh4, UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh4->ea = sh4->gbr + disp * 2;
+ WW(sh4, sh4->ea, sh4->r[0] & 0x0000ffff );
+}
+
+/* MOV.L R0,@(disp8,GBR) */
+INLINE void MOVLSG(sh4_state *sh4, UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh4->ea = sh4->gbr + disp * 4;
+ WL(sh4, sh4->ea, sh4->r[0] );
+}
+
+/* MOV.B R0,@(disp4,Rn) */
+INLINE void MOVBS4(sh4_state *sh4, UINT32 d, UINT32 n)
+{
+ UINT32 disp = d & 0x0f;
+ sh4->ea = sh4->r[n] + disp;
+ WB(sh4, sh4->ea, sh4->r[0] & 0x000000ff );
+}
+
+/* MOV.W R0,@(disp4,Rn) */
+INLINE void MOVWS4(sh4_state *sh4, UINT32 d, UINT32 n)
+{
+ UINT32 disp = d & 0x0f;
+ sh4->ea = sh4->r[n] + disp * 2;
+ WW(sh4, sh4->ea, sh4->r[0] & 0x0000ffff );
+}
+
+/* MOV.L Rm,@(disp4,Rn) */
+INLINE void MOVLS4(sh4_state *sh4, UINT32 m, UINT32 d, UINT32 n)
+{
+ UINT32 disp = d & 0x0f;
+ sh4->ea = sh4->r[n] + disp * 4;
+ WL(sh4, sh4->ea, sh4->r[m] );
+}
+
+/* MOV.B @(disp4,Rm),R0 */
+INLINE void MOVBL4(sh4_state *sh4, UINT32 m, UINT32 d)
+{
+ UINT32 disp = d & 0x0f;
+ sh4->ea = sh4->r[m] + disp;
+ sh4->r[0] = (UINT32)(INT32)(INT16)(INT8) RB(sh4, sh4->ea );
+}
+
+/* MOV.W @(disp4,Rm),R0 */
+INLINE void MOVWL4(sh4_state *sh4, UINT32 m, UINT32 d)
+{
+ UINT32 disp = d & 0x0f;
+ sh4->ea = sh4->r[m] + disp * 2;
+ sh4->r[0] = (UINT32)(INT32)(INT16) RW(sh4, sh4->ea );
+}
+
+/* MOV.L @(disp4,Rm),Rn */
+INLINE void MOVLL4(sh4_state *sh4, UINT32 m, UINT32 d, UINT32 n)
+{
+ UINT32 disp = d & 0x0f;
+ sh4->ea = sh4->r[m] + disp * 4;
+ sh4->r[n] = RL(sh4, sh4->ea );
+}
+
+/* MOVA @(disp8,PC),R0 */
+INLINE void MOVA(sh4_state *sh4, UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh4->ea = ((sh4->pc + 2) & ~3) + disp * 4;
+ sh4->r[0] = sh4->ea;
+}
+
+/* MOVT Rn */
+INLINE void MOVT(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->sr & T;
+}
+
+/* MUL.L Rm,Rn */
+INLINE void MULL(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->macl = sh4->r[n] * sh4->r[m];
+ sh4->sh4_icount--;
+}
+
+/* MULS Rm,Rn */
+INLINE void MULS(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->macl = (INT16) sh4->r[n] * (INT16) sh4->r[m];
+}
+
+/* MULU Rm,Rn */
+INLINE void MULU(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->macl = (UINT16) sh4->r[n] * (UINT16) sh4->r[m];
+}
+
+/* NEG Rm,Rn */
+INLINE void NEG(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] = 0 - sh4->r[m];
+}
+
+/* NEGC Rm,Rn */
+INLINE void NEGC(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ UINT32 temp;
+
+ temp = sh4->r[m];
+ sh4->r[n] = -temp - (sh4->sr & T);
+ if (temp || (sh4->sr & T))
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+/* NOP */
+INLINE void NOP(sh4_state *sh4)
+{
+}
+
+/* NOT Rm,Rn */
+INLINE void NOT(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] = ~sh4->r[m];
+}
+
+/* OR Rm,Rn */
+INLINE void OR(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] |= sh4->r[m];
+}
+
+/* OR #imm,R0 */
+INLINE void ORI(sh4_state *sh4, UINT32 i)
+{
+ sh4->r[0] |= i;
+ sh4->sh4_icount -= 2;
+}
+
+/* OR.B #imm,@(R0,GBR) */
+INLINE void ORM(sh4_state *sh4, UINT32 i)
+{
+ UINT32 temp;
+
+ sh4->ea = sh4->gbr + sh4->r[0];
+ temp = RB(sh4, sh4->ea );
+ temp |= i;
+ WB(sh4, sh4->ea, temp );
+}
+
+/* ROTCL Rn */
+INLINE void ROTCL(sh4_state *sh4, UINT32 n)
+{
+ UINT32 temp;
+
+ temp = (sh4->r[n] >> 31) & T;
+ sh4->r[n] = (sh4->r[n] << 1) | (sh4->sr & T);
+ sh4->sr = (sh4->sr & ~T) | temp;
+}
+
+/* ROTCR Rn */
+INLINE void ROTCR(sh4_state *sh4, UINT32 n)
+{
+ UINT32 temp;
+ temp = (sh4->sr & T) << 31;
+ if (sh4->r[n] & T)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+ sh4->r[n] = (sh4->r[n] >> 1) | temp;
+}
+
+/* ROTL Rn */
+INLINE void ROTL(sh4_state *sh4, UINT32 n)
+{
+ sh4->sr = (sh4->sr & ~T) | ((sh4->r[n] >> 31) & T);
+ sh4->r[n] = (sh4->r[n] << 1) | (sh4->r[n] >> 31);
+}
+
+/* ROTR Rn */
+INLINE void ROTR(sh4_state *sh4, UINT32 n)
+{
+ sh4->sr = (sh4->sr & ~T) | (sh4->r[n] & T);
+ sh4->r[n] = (sh4->r[n] >> 1) | (sh4->r[n] << 31);
+}
+
+/* RTE */
+INLINE void RTE(sh4_state *sh4)
+{
+ sh4->delay = sh4->pc;
+ sh4->pc = sh4->ea = sh4->spc;
+ if ((sh4->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ sh4_syncronize_register_bank(sh4, (sh4->sr & sRB) >> 29);
+ if ((sh4->ssr & sRB) != (sh4->sr & sRB))
+ sh4_change_register_bank(sh4, sh4->ssr & sRB ? 1 : 0);
+ sh4->sr = sh4->ssr;
+ sh4->sh4_icount--;
+ sh4_exception_recompute(sh4);
+}
+
+/* RTS */
+INLINE void RTS(sh4_state *sh4)
+{
+ sh4->delay = sh4->pc;
+ sh4->pc = sh4->ea = sh4->pr;
+ sh4->sh4_icount--;
+}
+
+/* SETT */
+INLINE void SETT(sh4_state *sh4)
+{
+ sh4->sr |= T;
+}
+
+/* SHAL Rn (same as SHLL) */
+INLINE void SHAL(sh4_state *sh4, UINT32 n)
+{
+ sh4->sr = (sh4->sr & ~T) | ((sh4->r[n] >> 31) & T);
+ sh4->r[n] <<= 1;
+}
+
+/* SHAR Rn */
+INLINE void SHAR(sh4_state *sh4, UINT32 n)
+{
+ sh4->sr = (sh4->sr & ~T) | (sh4->r[n] & T);
+ sh4->r[n] = (UINT32)((INT32)sh4->r[n] >> 1);
+}
+
+/* SHLL Rn (same as SHAL) */
+INLINE void SHLL(sh4_state *sh4, UINT32 n)
+{
+ sh4->sr = (sh4->sr & ~T) | ((sh4->r[n] >> 31) & T);
+ sh4->r[n] <<= 1;
+}
+
+/* SHLL2 Rn */
+INLINE void SHLL2(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] <<= 2;
+}
+
+/* SHLL8 Rn */
+INLINE void SHLL8(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] <<= 8;
+}
+
+/* SHLL16 Rn */
+INLINE void SHLL16(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] <<= 16;
+}
+
+/* SHLR Rn */
+INLINE void SHLR(sh4_state *sh4, UINT32 n)
+{
+ sh4->sr = (sh4->sr & ~T) | (sh4->r[n] & T);
+ sh4->r[n] >>= 1;
+}
+
+/* SHLR2 Rn */
+INLINE void SHLR2(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] >>= 2;
+}
+
+/* SHLR8 Rn */
+INLINE void SHLR8(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] >>= 8;
+}
+
+/* SHLR16 Rn */
+INLINE void SHLR16(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] >>= 16;
+}
+
+/* SLEEP */
+INLINE void SLEEP(sh4_state *sh4)
+{
+ /* 0 = normal mode */
+ /* 1 = enters into power-down mode */
+ /* 2 = go out the power-down mode after an exception */
+ if(sh4->sleep_mode != 2)
+ sh4->pc -= 2;
+ sh4->sh4_icount -= 2;
+ /* Wait_for_exception; */
+ if(sh4->sleep_mode == 0)
+ sh4->sleep_mode = 1;
+ else if(sh4->sleep_mode == 2)
+ sh4->sleep_mode = 0;
+}
+
+/* STC SR,Rn */
+INLINE void STCSR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->sr;
+}
+
+/* STC GBR,Rn */
+INLINE void STCGBR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->gbr;
+}
+
+/* STC VBR,Rn */
+INLINE void STCVBR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->vbr;
+}
+
+/* STC.L SR,@-Rn */
+INLINE void STCMSR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->sr );
+ sh4->sh4_icount--;
+}
+
+/* STC.L GBR,@-Rn */
+INLINE void STCMGBR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->gbr );
+ sh4->sh4_icount--;
+}
+
+/* STC.L VBR,@-Rn */
+INLINE void STCMVBR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->vbr );
+ sh4->sh4_icount--;
+}
+
+/* STS MACH,Rn */
+INLINE void STSMACH(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->mach;
+}
+
+/* STS MACL,Rn */
+INLINE void STSMACL(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->macl;
+}
+
+/* STS PR,Rn */
+INLINE void STSPR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->pr;
+}
+
+/* STS.L MACH,@-Rn */
+INLINE void STSMMACH(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->mach );
+}
+
+/* STS.L MACL,@-Rn */
+INLINE void STSMMACL(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->macl );
+}
+
+/* STS.L PR,@-Rn */
+INLINE void STSMPR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->pr );
+}
+
+/* SUB Rm,Rn */
+INLINE void SUB(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] -= sh4->r[m];
+}
+
+/* SUBC Rm,Rn */
+INLINE void SUBC(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ UINT32 tmp0, tmp1;
+
+ tmp1 = sh4->r[n] - sh4->r[m];
+ tmp0 = sh4->r[n];
+ sh4->r[n] = tmp1 - (sh4->sr & T);
+ if (tmp0 < tmp1)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+ if (tmp1 < sh4->r[n])
+ sh4->sr |= T;
+}
+
+/* SUBV Rm,Rn */
+INLINE void SUBV(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ INT32 dest, src, ans;
+
+ if ((INT32) sh4->r[n] >= 0)
+ dest = 0;
+ else
+ dest = 1;
+ if ((INT32) sh4->r[m] >= 0)
+ src = 0;
+ else
+ src = 1;
+ src += dest;
+ sh4->r[n] -= sh4->r[m];
+ if ((INT32) sh4->r[n] >= 0)
+ ans = 0;
+ else
+ ans = 1;
+ ans += dest;
+ if (src == 1)
+ {
+ if (ans == 1)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+ }
+ else
+ sh4->sr &= ~T;
+}
+
+/* SWAP.B Rm,Rn */
+INLINE void SWAPB(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ UINT32 temp0, temp1;
+
+ temp0 = sh4->r[m] & 0xffff0000;
+ temp1 = (sh4->r[m] & 0x000000ff) << 8;
+ sh4->r[n] = (sh4->r[m] >> 8) & 0x000000ff;
+ sh4->r[n] = sh4->r[n] | temp1 | temp0;
+}
+
+/* SWAP.W Rm,Rn */
+INLINE void SWAPW(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ UINT32 temp;
+
+ temp = (sh4->r[m] >> 16) & 0x0000ffff;
+ sh4->r[n] = (sh4->r[m] << 16) | temp;
+}
+
+/* TAS.B @Rn */
+INLINE void TAS(sh4_state *sh4, UINT32 n)
+{
+ UINT32 temp;
+ sh4->ea = sh4->r[n];
+ /* Bus Lock enable */
+ temp = RB(sh4, sh4->ea );
+ if (temp == 0)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+ temp |= 0x80;
+ /* Bus Lock disable */
+ WB(sh4, sh4->ea, temp );
+ sh4->sh4_icount -= 3;
+}
+
+/* TRAPA #imm */
+INLINE void TRAPA(sh4_state *sh4, UINT32 i)
+{
+ UINT32 imm = i & 0xff;
+
+ sh4->m[TRA] = imm;
+ sh4->ssr = sh4->sr;
+ sh4->spc = sh4->pc;
+ sh4->sgr = sh4->r[15];
+
+ sh4->sr |= MD;
+ if ((sh4->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ sh4_syncronize_register_bank(sh4, (sh4->sr & sRB) >> 29);
+ if (!(sh4->sr & sRB))
+ sh4_change_register_bank(sh4, 1);
+ sh4->sr |= sRB;
+ sh4->sr |= BL;
+ sh4_exception_recompute(sh4);
+
+ sh4->m[EXPEVT] = 0x00000160;
+ sh4->pc = sh4->vbr + 0x00000100;
+
+ sh4->sh4_icount -= 7;
+}
+
+/* TST Rm,Rn */
+INLINE void TST(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ if ((sh4->r[n] & sh4->r[m]) == 0)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+/* TST #imm,R0 */
+INLINE void TSTI(sh4_state *sh4, UINT32 i)
+{
+ UINT32 imm = i & 0xff;
+
+ if ((imm & sh4->r[0]) == 0)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+/* TST.B #imm,@(R0,GBR) */
+INLINE void TSTM(sh4_state *sh4, UINT32 i)
+{
+ UINT32 imm = i & 0xff;
+
+ sh4->ea = sh4->gbr + sh4->r[0];
+ if ((imm & RB(sh4, sh4->ea )) == 0)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+ sh4->sh4_icount -= 2;
+}
+
+/* XOR Rm,Rn */
+INLINE void XOR(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] ^= sh4->r[m];
+}
+
+/* XOR #imm,R0 */
+INLINE void XORI(sh4_state *sh4, UINT32 i)
+{
+ UINT32 imm = i & 0xff;
+ sh4->r[0] ^= imm;
+}
+
+/* XOR.B #imm,@(R0,GBR) */
+INLINE void XORM(sh4_state *sh4, UINT32 i)
+{
+ UINT32 imm = i & 0xff;
+ UINT32 temp;
+
+ sh4->ea = sh4->gbr + sh4->r[0];
+ temp = RB(sh4, sh4->ea );
+ temp ^= imm;
+ WB(sh4, sh4->ea, temp );
+ sh4->sh4_icount -= 2;
+}
+
+/* XTRCT Rm,Rn */
+INLINE void XTRCT(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ UINT32 temp;
+
+ temp = (sh4->r[m] << 16) & 0xffff0000;
+ sh4->r[n] = (sh4->r[n] >> 16) & 0x0000ffff;
+ sh4->r[n] |= temp;
+}
+
+/* STC SSR,Rn */
+INLINE void STCSSR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->ssr;
+}
+
+/* STC SPC,Rn */
+INLINE void STCSPC(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->spc;
+}
+
+/* STC SGR,Rn */
+INLINE void STCSGR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->sgr;
+}
+
+/* STS FPUL,Rn */
+INLINE void STSFPUL(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->fpul;
+}
+
+/* STS FPSCR,Rn */
+INLINE void STSFPSCR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->fpscr & 0x003FFFFF;
+}
+
+/* STC DBR,Rn */
+INLINE void STCDBR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->dbr;
+}
+
+/* STCRBANK Rm_BANK,Rn */
+INLINE void STCRBANK(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] = sh4->rbnk[sh4->sr&sRB ? 0 : 1][m & 7];
+}
+
+/* STCMRBANK Rm_BANK,@-Rn */
+INLINE void STCMRBANK(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->rbnk[sh4->sr&sRB ? 0 : 1][m & 7]);
+ sh4->sh4_icount--;
+}
+
+/* MOVCA.L R0,@Rn */
+INLINE void MOVCAL(sh4_state *sh4, UINT32 n)
+{
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->r[0] );
+}
+
+INLINE void CLRS(sh4_state *sh4)
+{
+ sh4->sr &= ~S;
+}
+
+INLINE void SETS(sh4_state *sh4)
+{
+ sh4->sr |= S;
+}
+
+/* STS.L SGR,@-Rn */
+INLINE void STCMSGR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->sgr );
+}
+
+/* STS.L FPUL,@-Rn */
+INLINE void STSMFPUL(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->fpul );
+}
+
+/* STS.L FPSCR,@-Rn */
+INLINE void STSMFPSCR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->fpscr & 0x003FFFFF);
+}
+
+/* STC.L DBR,@-Rn */
+INLINE void STCMDBR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->dbr );
+}
+
+/* STC.L SSR,@-Rn */
+INLINE void STCMSSR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->ssr );
+}
+
+/* STC.L SPC,@-Rn */
+INLINE void STCMSPC(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->spc );
+}
+
+/* LDS.L @Rm+,FPUL */
+INLINE void LDSMFPUL(sh4_state *sh4, UINT32 m)
+{
+ sh4->ea = sh4->r[m];
+ sh4->fpul = RL(sh4, sh4->ea );
+ sh4->r[m] += 4;
+}
+
+/* LDS.L @Rm+,FPSCR */
+INLINE void LDSMFPSCR(sh4_state *sh4, UINT32 m)
+{
+UINT32 s;
+
+ s = sh4->fpscr;
+ sh4->ea = sh4->r[m];
+ sh4->fpscr = RL(sh4, sh4->ea );
+ sh4->fpscr &= 0x003FFFFF;
+ sh4->r[m] += 4;
+ if ((s & FR) != (sh4->fpscr & FR))
+ sh4_swap_fp_registers(sh4);
+#ifdef LSB_FIRST
+ if ((s & PR) != (sh4->fpscr & PR))
+ sh4_swap_fp_couples(sh4);
+#endif
+ sh4->fpu_sz = (sh4->fpscr & SZ) ? 1 : 0;
+ sh4->fpu_pr = (sh4->fpscr & PR) ? 1 : 0;
+}
+
+/* LDC.L @Rm+,DBR */
+INLINE void LDCMDBR(sh4_state *sh4, UINT32 m)
+{
+ sh4->ea = sh4->r[m];
+ sh4->dbr = RL(sh4, sh4->ea );
+ sh4->r[m] += 4;
+}
+
+/* LDC.L @Rn+,Rm_BANK */
+INLINE void LDCMRBANK(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[n];
+ sh4->rbnk[sh4->sr&sRB ? 0 : 1][m & 7] = RL(sh4, sh4->ea );
+ sh4->r[n] += 4;
+}
+
+/* LDC.L @Rm+,SSR */
+INLINE void LDCMSSR(sh4_state *sh4, UINT32 m)
+{
+ sh4->ea = sh4->r[m];
+ sh4->ssr = RL(sh4, sh4->ea );
+ sh4->r[m] += 4;
+}
+
+/* LDC.L @Rm+,SPC */
+INLINE void LDCMSPC(sh4_state *sh4, UINT32 m)
+{
+ sh4->ea = sh4->r[m];
+ sh4->spc = RL(sh4, sh4->ea );
+ sh4->r[m] += 4;
+}
+
+/* LDS Rm,FPUL */
+INLINE void LDSFPUL(sh4_state *sh4, UINT32 m)
+{
+ sh4->fpul = sh4->r[m];
+}
+
+/* LDS Rm,FPSCR */
+INLINE void LDSFPSCR(sh4_state *sh4, UINT32 m)
+{
+UINT32 s;
+
+ s = sh4->fpscr;
+ sh4->fpscr = sh4->r[m] & 0x003FFFFF;
+ if ((s & FR) != (sh4->fpscr & FR))
+ sh4_swap_fp_registers(sh4);
+#ifdef LSB_FIRST
+ if ((s & PR) != (sh4->fpscr & PR))
+ sh4_swap_fp_couples(sh4);
+#endif
+ sh4->fpu_sz = (sh4->fpscr & SZ) ? 1 : 0;
+ sh4->fpu_pr = (sh4->fpscr & PR) ? 1 : 0;
+}
+
+/* LDC Rm,DBR */
+INLINE void LDCDBR(sh4_state *sh4, UINT32 m)
+{
+ sh4->dbr = sh4->r[m];
+}
+
+/* SHAD Rm,Rn */
+INLINE void SHAD(sh4_state *sh4, UINT32 m,UINT32 n)
+{
+ if ((sh4->r[m] & 0x80000000) == 0)
+ sh4->r[n] = sh4->r[n] << (sh4->r[m] & 0x1F);
+ else if ((sh4->r[m] & 0x1F) == 0) {
+ if ((sh4->r[n] & 0x80000000) == 0)
+ sh4->r[n] = 0;
+ else
+ sh4->r[n] = 0xFFFFFFFF;
+ } else
+ sh4->r[n]=(INT32)sh4->r[n] >> ((~sh4->r[m] & 0x1F)+1);
+}
+
+/* SHLD Rm,Rn */
+INLINE void SHLD(sh4_state *sh4, UINT32 m,UINT32 n)
+{
+ if ((sh4->r[m] & 0x80000000) == 0)
+ sh4->r[n] = sh4->r[n] << (sh4->r[m] & 0x1F);
+ else if ((sh4->r[m] & 0x1F) == 0)
+ sh4->r[n] = 0;
+ else
+ sh4->r[n] = sh4->r[n] >> ((~sh4->r[m] & 0x1F)+1);
+}
+
+/* LDCRBANK Rn,Rm_BANK */
+INLINE void LDCRBANK(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->rbnk[sh4->sr&sRB ? 0 : 1][m & 7] = sh4->r[n];
+}
+
+/* LDC Rm,SSR */
+INLINE void LDCSSR(sh4_state *sh4, UINT32 m)
+{
+ sh4->ssr = sh4->r[m];
+}
+
+/* LDC Rm,SPC */
+INLINE void LDCSPC(sh4_state *sh4, UINT32 m)
+{
+ sh4->spc = sh4->r[m];
+}
+
+/* PREF @Rn */
+INLINE void PREFM(sh4_state *sh4, UINT32 n)
+{
+ int a;
+ UINT32 addr,dest,sq;
+
+ addr = sh4->r[n]; // address
+ if ((addr >= 0xE0000000) && (addr <= 0xE3FFFFFF))
+ {
+ if (sh4->sh4_mmu_enabled)
+ {
+ addr = addr & 0xFFFFFFE0;
+ dest = sh4_getsqremap(sh4, addr); // good enough for naomi-gd rom, probably not much else
+
+ }
+ else
+ {
+ sq = (addr & 0x20) >> 5;
+ dest = addr & 0x03FFFFE0;
+ if (sq == 0)
+ dest |= (sh4->m[QACR0] & 0x1C) << 24;
+ else
+ dest |= (sh4->m[QACR1] & 0x1C) << 24;
+ addr = addr & 0xFFFFFFE0;
+ }
+
+ for (a = 0;a < 4;a++)
+ {
+ // shouldn't be causing a memory read, should store sq writes in registers.
+ sh4->program->write_qword(dest, sh4->program->read_qword(addr));
+ addr += 8;
+ dest += 8;
+ }
+ }
+}
+
+/*****************************************************************************
+ * OPCODE DISPATCHERS
+ *****************************************************************************/
+INLINE void op0000(sh4_state *sh4, UINT16 opcode)
+{
+ switch (opcode & 0xF)
+ {
+ case 0x0:
+ case 0x1:
+ break;
+ case 0x2:
+ if (opcode & 0x80) {
+ STCRBANK(sh4, Rm, Rn); return;
+ }
+ switch (opcode & 0x70)
+ {
+ case 0x00:
+ STCSR(sh4, Rn); break;
+ case 0x10:
+ STCGBR(sh4, Rn); break;
+ case 0x20:
+ STCVBR(sh4, Rn); break;
+ case 0x30:
+ STCSSR(sh4, Rn); break;
+ case 0x40:
+ STCSPC(sh4, Rn); break;
+ }
+ break;
+ case 0x3:
+ switch (opcode & 0xF0)
+ {
+ case 0x00:
+ BSRF(sh4, Rn); break;
+ case 0x20:
+ BRAF(sh4, Rn); break;
+ case 0x80:
+ PREFM(sh4, Rn); break;
+ case 0x90:
+ TODO(sh4); break;
+ case 0xA0:
+ TODO(sh4); break;
+ case 0xB0:
+ TODO(sh4); break;
+ case 0xC0:
+ MOVCAL(sh4, Rn); break;
+ }
+ break;
+ case 0x4:
+ MOVBS0(sh4, Rm, Rn); break;
+ case 0x5:
+ MOVWS0(sh4, Rm, Rn); break;
+ case 0x6:
+ MOVLS0(sh4, Rm, Rn); break;
+ case 0x7:
+ MULL(sh4, Rm, Rn); break;
+ case 0x8:
+ switch (opcode & 0x70)
+ {
+ case 0x00:
+ CLRT(sh4); break;
+ case 0x10:
+ SETT(sh4); break;
+ case 0x20:
+ CLRMAC(sh4); break;
+ case 0x30:
+ TODO(sh4); break;
+ case 0x40:
+ CLRS(sh4); break;
+ case 0x50:
+ SETS(sh4); break;
+ }
+ break;
+ case 0x9:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ NOP(sh4); break;
+ case 0x10:
+ DIV0U(sh4); break;
+ case 0x20:
+ MOVT(sh4, Rn); break;
+ }
+ break;
+ case 0xA:
+ switch (opcode & 0x70)
+ {
+ case 0x00:
+ STSMACH(sh4, Rn); break;
+ case 0x10:
+ STSMACL(sh4, Rn); break;
+ case 0x20:
+ STSPR(sh4, Rn); break;
+ case 0x30:
+ STCSGR(sh4, Rn); break;
+ case 0x50:
+ STSFPUL(sh4, Rn); break;
+ case 0x60:
+ STSFPSCR(sh4, Rn); break;
+ case 0x70:
+ STCDBR(sh4, Rn); break;
+ }
+ break;
+ case 0xB:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ RTS(sh4); break;
+ case 0x10:
+ SLEEP(sh4); break;
+ case 0x20:
+ RTE(sh4); break;
+ }
+ break;
+ case 0xC:
+ MOVBL0(sh4, Rm, Rn); break;
+ case 0xD:
+ MOVWL0(sh4, Rm, Rn); break;
+ case 0xE:
+ MOVLL0(sh4, Rm, Rn); break;
+ case 0xF:
+ MAC_L(sh4, Rm, Rn); break;
+ }
+}
+
+INLINE void op0001(sh4_state *sh4, UINT16 opcode)
+{
+ MOVLS4(sh4, Rm, opcode & 0x0f, Rn);
+}
+
+INLINE void op0010(sh4_state *sh4, UINT16 opcode)
+{
+ switch (opcode & 15)
+ {
+ case 0: MOVBS(sh4, Rm, Rn); break;
+ case 1: MOVWS(sh4, Rm, Rn); break;
+ case 2: MOVLS(sh4, Rm, Rn); break;
+ case 3: NOP(sh4); break;
+ case 4: MOVBM(sh4, Rm, Rn); break;
+ case 5: MOVWM(sh4, Rm, Rn); break;
+ case 6: MOVLM(sh4, Rm, Rn); break;
+ case 7: DIV0S(sh4, Rm, Rn); break;
+ case 8: TST(sh4, Rm, Rn); break;
+ case 9: AND(sh4, Rm, Rn); break;
+ case 10: XOR(sh4, Rm, Rn); break;
+ case 11: OR(sh4, Rm, Rn); break;
+ case 12: CMPSTR(sh4, Rm, Rn); break;
+ case 13: XTRCT(sh4, Rm, Rn); break;
+ case 14: MULU(sh4, Rm, Rn); break;
+ case 15: MULS(sh4, Rm, Rn); break;
+ }
+}
+
+INLINE void op0011(sh4_state *sh4, UINT16 opcode)
+{
+ switch (opcode & 15)
+ {
+ case 0: CMPEQ(sh4, Rm, Rn); break;
+ case 1: NOP(sh4); break;
+ case 2: CMPHS(sh4, Rm, Rn); break;
+ case 3: CMPGE(sh4, Rm, Rn); break;
+ case 4: DIV1(sh4, Rm, Rn); break;
+ case 5: DMULU(sh4, Rm, Rn); break;
+ case 6: CMPHI(sh4, Rm, Rn); break;
+ case 7: CMPGT(sh4, Rm, Rn); break;
+ case 8: SUB(sh4, Rm, Rn); break;
+ case 9: NOP(sh4); break;
+ case 10: SUBC(sh4, Rm, Rn); break;
+ case 11: SUBV(sh4, Rm, Rn); break;
+ case 12: ADD(sh4, Rm, Rn); break;
+ case 13: DMULS(sh4, Rm, Rn); break;
+ case 14: ADDC(sh4, Rm, Rn); break;
+ case 15: ADDV(sh4, Rm, Rn); break;
+ }
+}
+
+INLINE void op0100(sh4_state *sh4, UINT16 opcode)
+{
+ switch (opcode & 0xF)
+ {
+ case 0x0:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ SHLL(sh4, Rn); break;
+ case 0x10:
+ DT(sh4, Rn); break;
+ case 0x20:
+ SHAL(sh4, Rn); break;
+ }
+ break;
+ case 0x1:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ SHLR(sh4, Rn); break;
+ case 0x10:
+ CMPPZ(sh4, Rn); break;
+ case 0x20:
+ SHAR(sh4, Rn); break;
+ }
+ break;
+ case 0x2:
+ switch (opcode & 0xF0)
+ {
+ case 0x00:
+ STSMMACH(sh4, Rn); break;
+ case 0x10:
+ STSMMACL(sh4, Rn); break;
+ case 0x20:
+ STSMPR(sh4, Rn); break;
+ case 0x30:
+ STCMSGR(sh4, Rn); break;
+ case 0x50:
+ STSMFPUL(sh4, Rn); break;
+ case 0x60:
+ STSMFPSCR(sh4, Rn); break;
+ case 0xF0:
+ STCMDBR(sh4, Rn); break;
+ }
+ break;
+ case 0x3:
+ if (opcode & 0x80) {
+ STCMRBANK(sh4, Rm, Rn); return;
+ }
+ switch (opcode & 0x70)
+ {
+ case 0x00:
+ STCMSR(sh4, Rn); break;
+ case 0x10:
+ STCMGBR(sh4, Rn); break;
+ case 0x20:
+ STCMVBR(sh4, Rn); break;
+ case 0x30:
+ STCMSSR(sh4, Rn); break;
+ case 0x40:
+ STCMSPC(sh4, Rn); break;
+ }
+ break;
+ case 0x4:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ ROTL(sh4, Rn); break;
+ case 0x20:
+ ROTCL(sh4, Rn); break;
+ }
+ break;
+ case 0x5:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ ROTR(sh4, Rn); break;
+ case 0x10:
+ CMPPL(sh4, Rn); break;
+ case 0x20:
+ ROTCR(sh4, Rn); break;
+ }
+ break;
+ case 0x6:
+ switch (opcode & 0xF0)
+ {
+ case 0x00:
+ LDSMMACH(sh4, Rn); break;
+ case 0x10:
+ LDSMMACL(sh4, Rn); break;
+ case 0x20:
+ LDSMPR(sh4, Rn); break;
+ case 0x50:
+ LDSMFPUL(sh4, Rn); break;
+ case 0x60:
+ LDSMFPSCR(sh4, Rn); break;
+ case 0xF0:
+ LDCMDBR(sh4, Rn); break;
+ }
+ break;
+ case 0x7:
+ if (opcode & 0x80) {
+ LDCMRBANK(sh4, Rm,Rn); return;
+ }
+ switch (opcode & 0x70)
+ {
+ case 0x00:
+ LDCMSR(sh4, Rn); break;
+ case 0x10:
+ LDCMGBR(sh4, Rn); break;
+ case 0x20:
+ LDCMVBR(sh4, Rn); break;
+ case 0x30:
+ LDCMSSR(sh4, Rn); break;
+ case 0x40:
+ LDCMSPC(sh4, Rn); break;
+ }
+ break;
+ case 0x8:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ SHLL2(sh4, Rn); break;
+ case 0x10:
+ SHLL8(sh4, Rn); break;
+ case 0x20:
+ SHLL16(sh4, Rn); break;
+ }
+ break;
+ case 0x9:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ SHLR2(sh4, Rn); break;
+ case 0x10:
+ SHLR8(sh4, Rn); break;
+ case 0x20:
+ SHLR16(sh4, Rn); break;
+ }
+ break;
+ case 0xA:
+ switch (opcode & 0xF0)
+ {
+ case 0x00:
+ LDSMACH(sh4, Rn); break;
+ case 0x10:
+ LDSMACL(sh4, Rn); break;
+ case 0x20:
+ LDSPR(sh4, Rn); break;
+ case 0x50:
+ LDSFPUL(sh4, Rn); break;
+ case 0x60:
+ LDSFPSCR(sh4, Rn); break;
+ case 0xF0:
+ LDCDBR(sh4, Rn); break;
+ }
+ break;
+ case 0xB:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ JSR(sh4, Rn); break;
+ case 0x10:
+ TAS(sh4, Rn); break;
+ case 0x20:
+ JMP(sh4, Rn); break;
+ }
+ break;
+ case 0xC:
+ SHAD(sh4, Rm,Rn); break;
+ case 0xD:
+ SHLD(sh4, Rm,Rn); break;
+ case 0xE:
+ if (opcode & 0x80) {
+ LDCRBANK(sh4, Rm,Rn); return;
+ }
+ switch (opcode & 0x70)
+ {
+ case 0x00:
+ LDCSR(sh4, Rn); break;
+ case 0x10:
+ LDCGBR(sh4, Rn); break;
+ case 0x20:
+ LDCVBR(sh4, Rn); break;
+ case 0x30:
+ LDCSSR(sh4, Rn); break;
+ case 0x40:
+ LDCSPC(sh4, Rn); break;
+ }
+ break;
+ case 0xF:
+ MAC_W(sh4, Rm, Rn); break;
+ }
+}
+
+INLINE void op0101(sh4_state *sh4, UINT16 opcode)
+{
+ MOVLL4(sh4, Rm, opcode & 0x0f, Rn);
+}
+
+INLINE void op0110(sh4_state *sh4, UINT16 opcode)
+{
+ switch (opcode & 15)
+ {
+ case 0: MOVBL(sh4, Rm, Rn); break;
+ case 1: MOVWL(sh4, Rm, Rn); break;
+ case 2: MOVLL(sh4, Rm, Rn); break;
+ case 3: MOV(sh4, Rm, Rn); break;
+ case 4: MOVBP(sh4, Rm, Rn); break;
+ case 5: MOVWP(sh4, Rm, Rn); break;
+ case 6: MOVLP(sh4, Rm, Rn); break;
+ case 7: NOT(sh4, Rm, Rn); break;
+ case 8: SWAPB(sh4, Rm, Rn); break;
+ case 9: SWAPW(sh4, Rm, Rn); break;
+ case 10: NEGC(sh4, Rm, Rn); break;
+ case 11: NEG(sh4, Rm, Rn); break;
+ case 12: EXTUB(sh4, Rm, Rn); break;
+ case 13: EXTUW(sh4, Rm, Rn); break;
+ case 14: EXTSB(sh4, Rm, Rn); break;
+ case 15: EXTSW(sh4, Rm, Rn); break;
+ }
+}
+
+INLINE void op0111(sh4_state *sh4, UINT16 opcode)
+{
+ ADDI(sh4, opcode & 0xff, Rn);
+}
+
+INLINE void op1000(sh4_state *sh4, UINT16 opcode)
+{
+ switch ( opcode & (15<<8) )
+ {
+ case 0 << 8: MOVBS4(sh4, opcode & 0x0f, Rm); break;
+ case 1 << 8: MOVWS4(sh4, opcode & 0x0f, Rm); break;
+ case 2<< 8: NOP(sh4); break;
+ case 3<< 8: NOP(sh4); break;
+ case 4<< 8: MOVBL4(sh4, Rm, opcode & 0x0f); break;
+ case 5<< 8: MOVWL4(sh4, Rm, opcode & 0x0f); break;
+ case 6<< 8: NOP(sh4); break;
+ case 7<< 8: NOP(sh4); break;
+ case 8<< 8: CMPIM(sh4, opcode & 0xff); break;
+ case 9<< 8: BT(sh4, opcode & 0xff); break;
+ case 10<< 8: NOP(sh4); break;
+ case 11<< 8: BF(sh4, opcode & 0xff); break;
+ case 12<< 8: NOP(sh4); break;
+ case 13<< 8: BTS(sh4, opcode & 0xff); break;
+ case 14<< 8: NOP(sh4); break;
+ case 15<< 8: BFS(sh4, opcode & 0xff); break;
+ }
+}
+
+
+INLINE void op1001(sh4_state *sh4, UINT16 opcode)
+{
+ MOVWI(sh4, opcode & 0xff, Rn);
+}
+
+INLINE void op1010(sh4_state *sh4, UINT16 opcode)
+{
+ BRA(sh4, opcode & 0xfff);
+}
+
+INLINE void op1011(sh4_state *sh4, UINT16 opcode)
+{
+ BSR(sh4, opcode & 0xfff);
+}
+
+INLINE void op1100(sh4_state *sh4, UINT16 opcode)
+{
+ switch (opcode & (15<<8))
+ {
+ case 0<<8: MOVBSG(sh4, opcode & 0xff); break;
+ case 1<<8: MOVWSG(sh4, opcode & 0xff); break;
+ case 2<<8: MOVLSG(sh4, opcode & 0xff); break;
+ case 3<<8: TRAPA(sh4, opcode & 0xff); break;
+ case 4<<8: MOVBLG(sh4, opcode & 0xff); break;
+ case 5<<8: MOVWLG(sh4, opcode & 0xff); break;
+ case 6<<8: MOVLLG(sh4, opcode & 0xff); break;
+ case 7<<8: MOVA(sh4, opcode & 0xff); break;
+ case 8<<8: TSTI(sh4, opcode & 0xff); break;
+ case 9<<8: ANDI(sh4, opcode & 0xff); break;
+ case 10<<8: XORI(sh4, opcode & 0xff); break;
+ case 11<<8: ORI(sh4, opcode & 0xff); break;
+ case 12<<8: TSTM(sh4, opcode & 0xff); break;
+ case 13<<8: ANDM(sh4, opcode & 0xff); break;
+ case 14<<8: XORM(sh4, opcode & 0xff); break;
+ case 15<<8: ORM(sh4, opcode & 0xff); break;
+ }
+}
+
+INLINE void op1101(sh4_state *sh4, UINT16 opcode)
+{
+ MOVLI(sh4, opcode & 0xff, Rn);
+}
+
+INLINE void op1110(sh4_state *sh4, UINT16 opcode)
+{
+ MOVI(sh4, opcode & 0xff, Rn);
+}
+
+/* FMOV.S @Rm+,FRn PR=0 SZ=0 1111nnnnmmmm1001 */
+/* FMOV @Rm+,DRn PR=0 SZ=1 1111nnn0mmmm1001 */
+/* FMOV @Rm+,XDn PR=0 SZ=1 1111nnn1mmmm1001 */
+/* FMOV @Rm+,XDn PR=1 1111nnn1mmmm1001 */
+INLINE void FMOVMRIFR(sh4_state *sh4, UINT32 m,UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ sh4->ea = sh4->r[m];
+ sh4->r[m] += 8;
+ sh4->xf[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(sh4, sh4->ea );
+ sh4->xf[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(sh4, sh4->ea+4 );
+ } else { /* PR = 0 */
+ if (sh4->fpu_sz) { /* SZ = 1 */
+ if (n & 1) {
+ n = n & 14;
+ sh4->ea = sh4->r[m];
+ sh4->xf[n] = RL(sh4, sh4->ea );
+ sh4->r[m] += 4;
+ sh4->xf[n+1] = RL(sh4, sh4->ea+4 );
+ sh4->r[m] += 4;
+ } else {
+ sh4->ea = sh4->r[m];
+ sh4->fr[n] = RL(sh4, sh4->ea );
+ sh4->r[m] += 4;
+ sh4->fr[n+1] = RL(sh4, sh4->ea+4 );
+ sh4->r[m] += 4;
+ }
+ } else { /* SZ = 0 */
+ sh4->ea = sh4->r[m];
+ sh4->fr[n] = RL(sh4, sh4->ea );
+ sh4->r[m] += 4;
+ }
+ }
+}
+
+/* FMOV.S FRm,@Rn PR=0 SZ=0 1111nnnnmmmm1010 */
+/* FMOV DRm,@Rn PR=0 SZ=1 1111nnnnmmm01010 */
+/* FMOV XDm,@Rn PR=0 SZ=1 1111nnnnmmm11010 */
+/* FMOV XDm,@Rn PR=1 1111nnnnmmm11010 */
+INLINE void FMOVFRMR(sh4_state *sh4,UINT32 m,UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ m= m & 14;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea,sh4->xf[m+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] );
+ WL(sh4, sh4->ea+4,sh4->xf[m+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] );
+ } else { /* PR = 0 */
+ if (sh4->fpu_sz) { /* SZ = 1 */
+ if (m & 1) {
+ m= m & 14;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea,sh4->xf[m] );
+ WL(sh4, sh4->ea+4,sh4->xf[m+1] );
+ } else {
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea,sh4->fr[m] );
+ WL(sh4, sh4->ea+4,sh4->fr[m+1] );
+ }
+ } else { /* SZ = 0 */
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea,sh4->fr[m] );
+ }
+ }
+}
+
+/* FMOV.S FRm,@-Rn PR=0 SZ=0 1111nnnnmmmm1011 */
+/* FMOV DRm,@-Rn PR=0 SZ=1 1111nnnnmmm01011 */
+/* FMOV XDm,@-Rn PR=0 SZ=1 1111nnnnmmm11011 */
+/* FMOV XDm,@-Rn PR=1 1111nnnnmmm11011 */
+INLINE void FMOVFRMDR(sh4_state *sh4,UINT32 m,UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ m= m & 14;
+ sh4->r[n] -= 8;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea,sh4->xf[m+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] );
+ WL(sh4, sh4->ea+4,sh4->xf[m+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] );
+ } else { /* PR = 0 */
+ if (sh4->fpu_sz) { /* SZ = 1 */
+ if (m & 1) {
+ m= m & 14;
+ sh4->r[n] -= 8;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea,sh4->xf[m] );
+ WL(sh4, sh4->ea+4,sh4->xf[m+1] );
+ } else {
+ sh4->r[n] -= 8;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea,sh4->fr[m] );
+ WL(sh4, sh4->ea+4,sh4->fr[m+1] );
+ }
+ } else { /* SZ = 0 */
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea,sh4->fr[m] );
+ }
+ }
+}
+
+/* FMOV.S FRm,@(R0,Rn) PR=0 SZ=0 1111nnnnmmmm0111 */
+/* FMOV DRm,@(R0,Rn) PR=0 SZ=1 1111nnnnmmm00111 */
+/* FMOV XDm,@(R0,Rn) PR=0 SZ=1 1111nnnnmmm10111 */
+/* FMOV XDm,@(R0,Rn) PR=1 1111nnnnmmm10111 */
+INLINE void FMOVFRS0(sh4_state *sh4,UINT32 m,UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ m= m & 14;
+ sh4->ea = sh4->r[0] + sh4->r[n];
+ WL(sh4, sh4->ea,sh4->xf[m+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] );
+ WL(sh4, sh4->ea+4,sh4->xf[m+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] );
+ } else { /* PR = 0 */
+ if (sh4->fpu_sz) { /* SZ = 1 */
+ if (m & 1) {
+ m= m & 14;
+ sh4->ea = sh4->r[0] + sh4->r[n];
+ WL(sh4, sh4->ea,sh4->xf[m] );
+ WL(sh4, sh4->ea+4,sh4->xf[m+1] );
+ } else {
+ sh4->ea = sh4->r[0] + sh4->r[n];
+ WL(sh4, sh4->ea,sh4->fr[m] );
+ WL(sh4, sh4->ea+4,sh4->fr[m+1] );
+ }
+ } else { /* SZ = 0 */
+ sh4->ea = sh4->r[0] + sh4->r[n];
+ WL(sh4, sh4->ea,sh4->fr[m] );
+ }
+ }
+}
+
+/* FMOV.S @(R0,Rm),FRn PR=0 SZ=0 1111nnnnmmmm0110 */
+/* FMOV @(R0,Rm),DRn PR=0 SZ=1 1111nnn0mmmm0110 */
+/* FMOV @(R0,Rm),XDn PR=0 SZ=1 1111nnn1mmmm0110 */
+/* FMOV @(R0,Rm),XDn PR=1 1111nnn1mmmm0110 */
+INLINE void FMOVS0FR(sh4_state *sh4,UINT32 m,UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ n= n & 14;
+ sh4->ea = sh4->r[0] + sh4->r[m];
+ sh4->xf[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(sh4, sh4->ea );
+ sh4->xf[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(sh4, sh4->ea+4 );
+ } else { /* PR = 0 */
+ if (sh4->fpu_sz) { /* SZ = 1 */
+ if (n & 1) {
+ n= n & 14;
+ sh4->ea = sh4->r[0] + sh4->r[m];
+ sh4->xf[n] = RL(sh4, sh4->ea );
+ sh4->xf[n+1] = RL(sh4, sh4->ea+4 );
+ } else {
+ sh4->ea = sh4->r[0] + sh4->r[m];
+ sh4->fr[n] = RL(sh4, sh4->ea );
+ sh4->fr[n+1] = RL(sh4, sh4->ea+4 );
+ }
+ } else { /* SZ = 0 */
+ sh4->ea = sh4->r[0] + sh4->r[m];
+ sh4->fr[n] = RL(sh4, sh4->ea );
+ }
+ }
+}
+
+/* FMOV.S @Rm,FRn PR=0 SZ=0 1111nnnnmmmm1000 */
+/* FMOV @Rm,DRn PR=0 SZ=1 1111nnn0mmmm1000 */
+/* FMOV @Rm,XDn PR=0 SZ=1 1111nnn1mmmm1000 */
+/* FMOV @Rm,XDn PR=1 1111nnn1mmmm1000 */
+/* FMOV @Rm,DRn PR=1 1111nnn0mmmm1000 */
+INLINE void FMOVMRFR(sh4_state *sh4,UINT32 m,UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ if (n & 1) {
+ n= n & 14;
+ sh4->ea = sh4->r[m];
+ sh4->xf[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(sh4, sh4->ea );
+ sh4->xf[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(sh4, sh4->ea+4 );
+ } else {
+ n= n & 14;
+ sh4->ea = sh4->r[m];
+ sh4->fr[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(sh4, sh4->ea );
+ sh4->fr[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(sh4, sh4->ea+4 );
+ }
+ } else { /* PR = 0 */
+ if (sh4->fpu_sz) { /* SZ = 1 */
+ if (n & 1) {
+ n= n & 14;
+ sh4->ea = sh4->r[m];
+ sh4->xf[n] = RL(sh4, sh4->ea );
+ sh4->xf[n+1] = RL(sh4, sh4->ea+4 );
+ } else {
+ n= n & 14;
+ sh4->ea = sh4->r[m];
+ sh4->fr[n] = RL(sh4, sh4->ea );
+ sh4->fr[n+1] = RL(sh4, sh4->ea+4 );
+ }
+ } else { /* SZ = 0 */
+ sh4->ea = sh4->r[m];
+ sh4->fr[n] = RL(sh4, sh4->ea );
+ }
+ }
+}
+
+/* FMOV FRm,FRn PR=0 SZ=0 FRm -> FRn 1111nnnnmmmm1100 */
+/* FMOV DRm,DRn PR=0 SZ=1 DRm -> DRn 1111nnn0mmm01100 */
+/* FMOV XDm,DRn PR=1 XDm -> DRn 1111nnn0mmm11100 */
+/* FMOV DRm,XDn PR=1 DRm -> XDn 1111nnn1mmm01100 */
+/* FMOV XDm,XDn PR=1 XDm -> XDn 1111nnn1mmm11100 */
+INLINE void FMOVFR(sh4_state *sh4,UINT32 m,UINT32 n)
+{
+ if ((sh4->fpu_sz == 0) && (sh4->fpu_pr == 0)) /* SZ = 0 */
+ sh4->fr[n] = sh4->fr[m];
+ else { /* SZ = 1 or PR = 1 */
+ if (m & 1) {
+ if (n & 1) {
+ sh4->xf[n & 14] = sh4->xf[m & 14];
+ sh4->xf[n | 1] = sh4->xf[m | 1];
+ } else {
+ sh4->fr[n] = sh4->xf[m & 14];
+ sh4->fr[n | 1] = sh4->xf[m | 1];
+ }
+ } else {
+ if (n & 1) {
+ sh4->xf[n & 14] = sh4->fr[m];
+ sh4->xf[n | 1] = sh4->fr[m | 1]; // (a&14)+1 -> a|1
+ } else {
+ sh4->fr[n] = sh4->fr[m];
+ sh4->fr[n | 1] = sh4->fr[m | 1];
+ }
+ }
+ }
+}
+
+/* FLDI1 FRn 1111nnnn10011101 */
+INLINE void FLDI1(sh4_state *sh4, UINT32 n)
+{
+ sh4->fr[n] = 0x3F800000;
+}
+
+/* FLDI0 FRn 1111nnnn10001101 */
+INLINE void FLDI0(sh4_state *sh4, UINT32 n)
+{
+ sh4->fr[n] = 0;
+}
+
+/* FLDS FRm,FPUL 1111mmmm00011101 */
+INLINE void FLDS(sh4_state *sh4, UINT32 m)
+{
+ sh4->fpul = sh4->fr[m];
+}
+
+/* FSTS FPUL,FRn 1111nnnn00001101 */
+INLINE void FSTS(sh4_state *sh4, UINT32 n)
+{
+ sh4->fr[n] = sh4->fpul;
+}
+
+/* FRCHG 1111101111111101 */
+INLINE void FRCHG(sh4_state *sh4)
+{
+ sh4->fpscr ^= FR;
+ sh4_swap_fp_registers(sh4);
+}
+
+/* FSCHG 1111001111111101 */
+INLINE void FSCHG(sh4_state *sh4)
+{
+ sh4->fpscr ^= SZ;
+ sh4->fpu_sz = (sh4->fpscr & SZ) ? 1 : 0;
+}
+
+/* FTRC FRm,FPUL PR=0 1111mmmm00111101 */
+/* FTRC DRm,FPUL PR=1 1111mmm000111101 */
+INLINE void FTRC(sh4_state *sh4, UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ *((INT32 *)&sh4->fpul) = (INT32)FP_RFD(n);
+ } else { /* PR = 0 */
+ /* read sh4->fr[n] as float -> truncate -> fpul(32) */
+ *((INT32 *)&sh4->fpul) = (INT32)FP_RFS(n);
+ }
+}
+
+/* FLOAT FPUL,FRn PR=0 1111nnnn00101101 */
+/* FLOAT FPUL,DRn PR=1 1111nnn000101101 */
+INLINE void FLOAT(sh4_state *sh4, UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ FP_RFD(n) = (double)*((INT32 *)&sh4->fpul);
+ } else { /* PR = 0 */
+ FP_RFS(n) = (float)*((INT32 *)&sh4->fpul);
+ }
+}
+
+/* FNEG FRn PR=0 1111nnnn01001101 */
+/* FNEG DRn PR=1 1111nnn001001101 */
+INLINE void FNEG(sh4_state *sh4, UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ FP_RFD(n) = -FP_RFD(n);
+ } else { /* PR = 0 */
+ FP_RFS(n) = -FP_RFS(n);
+ }
+}
+
+/* FABS FRn PR=0 1111nnnn01011101 */
+/* FABS DRn PR=1 1111nnn001011101 */
+INLINE void FABS(sh4_state *sh4, UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+#ifdef LSB_FIRST
+ n = n | 1; // n & 14 + 1
+ sh4->fr[n] = sh4->fr[n] & 0x7fffffff;
+#else
+ n = n & 14;
+ sh4->fr[n] = sh4->fr[n] & 0x7fffffff;
+#endif
+ } else { /* PR = 0 */
+ sh4->fr[n] = sh4->fr[n] & 0x7fffffff;
+ }
+}
+
+/* FCMP/EQ FRm,FRn PR=0 1111nnnnmmmm0100 */
+/* FCMP/EQ DRm,DRn PR=1 1111nnn0mmm00100 */
+INLINE void FCMP_EQ(sh4_state *sh4, UINT32 m,UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ m = m & 14;
+ if (FP_RFD(n) == FP_RFD(m))
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+ } else { /* PR = 0 */
+ if (FP_RFS(n) == FP_RFS(m))
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+ }
+}
+
+/* FCMP/GT FRm,FRn PR=0 1111nnnnmmmm0101 */
+/* FCMP/GT DRm,DRn PR=1 1111nnn0mmm00101 */
+INLINE void FCMP_GT(sh4_state *sh4, UINT32 m,UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ m = m & 14;
+ if (FP_RFD(n) > FP_RFD(m))
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+ } else { /* PR = 0 */
+ if (FP_RFS(n) > FP_RFS(m))
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+ }
+}
+
+/* FCNVDS DRm,FPUL PR=1 1111mmm010111101 */
+INLINE void FCNVDS(sh4_state *sh4, UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ if (sh4->fpscr & RM)
+ sh4->fr[n | NATIVE_ENDIAN_VALUE_LE_BE(0,1)] &= 0xe0000000; /* round toward zero*/
+ *((float *)&sh4->fpul) = (float)FP_RFD(n);
+ }
+}
+
+/* FCNVSD FPUL, DRn PR=1 1111nnn010101101 */
+INLINE void FCNVSD(sh4_state *sh4, UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ FP_RFD(n) = (double)*((float *)&sh4->fpul);
+ }
+}
+
+/* FADD FRm,FRn PR=0 1111nnnnmmmm0000 */
+/* FADD DRm,DRn PR=1 1111nnn0mmm00000 */
+INLINE void FADD(sh4_state *sh4, UINT32 m,UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ m = m & 14;
+ FP_RFD(n) = FP_RFD(n) + FP_RFD(m);
+ } else { /* PR = 0 */
+ FP_RFS(n) = FP_RFS(n) + FP_RFS(m);
+ }
+}
+
+/* FSUB FRm,FRn PR=0 1111nnnnmmmm0001 */
+/* FSUB DRm,DRn PR=1 1111nnn0mmm00001 */
+INLINE void FSUB(sh4_state *sh4, UINT32 m,UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ m = m & 14;
+ FP_RFD(n) = FP_RFD(n) - FP_RFD(m);
+ } else { /* PR = 0 */
+ FP_RFS(n) = FP_RFS(n) - FP_RFS(m);
+ }
+}
+
+
+/* FMUL FRm,FRn PR=0 1111nnnnmmmm0010 */
+/* FMUL DRm,DRn PR=1 1111nnn0mmm00010 */
+INLINE void FMUL(sh4_state *sh4, UINT32 m,UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ m = m & 14;
+ FP_RFD(n) = FP_RFD(n) * FP_RFD(m);
+ } else { /* PR = 0 */
+ FP_RFS(n) = FP_RFS(n) * FP_RFS(m);
+ }
+}
+
+/* FDIV FRm,FRn PR=0 1111nnnnmmmm0011 */
+/* FDIV DRm,DRn PR=1 1111nnn0mmm00011 */
+INLINE void FDIV(sh4_state *sh4, UINT32 m,UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ m = m & 14;
+ if (FP_RFD(m) == 0)
+ return;
+ FP_RFD(n) = FP_RFD(n) / FP_RFD(m);
+ } else { /* PR = 0 */
+ if (FP_RFS(m) == 0)
+ return;
+ FP_RFS(n) = FP_RFS(n) / FP_RFS(m);
+ }
+}
+
+/* FMAC FR0,FRm,FRn PR=0 1111nnnnmmmm1110 */
+INLINE void FMAC(sh4_state *sh4, UINT32 m,UINT32 n)
+{
+ if (sh4->fpu_pr == 0) { /* PR = 0 */
+ FP_RFS(n) = (FP_RFS(0) * FP_RFS(m)) + FP_RFS(n);
+ }
+}
+
+/* FSQRT FRn PR=0 1111nnnn01101101 */
+/* FSQRT DRn PR=1 1111nnnn01101101 */
+INLINE void FSQRT(sh4_state *sh4, UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ if (FP_RFD(n) < 0)
+ return;
+ FP_RFD(n) = sqrtf(FP_RFD(n));
+ } else { /* PR = 0 */
+ if (FP_RFS(n) < 0)
+ return;
+ FP_RFS(n) = sqrtf(FP_RFS(n));
+ }
+}
+
+/* FSRRA FRn PR=0 1111nnnn01111101 */
+INLINE void FSRRA(sh4_state *sh4, UINT32 n)
+{
+ if (FP_RFS(n) < 0)
+ return;
+ FP_RFS(n) = 1.0 / sqrtf(FP_RFS(n));
+}
+
+/* FSSCA FPUL,FRn PR=0 1111nnn011111101 */
+INLINE void FSSCA(sh4_state *sh4, UINT32 n)
+{
+float angle;
+
+ angle = (((float)(sh4->fpul & 0xFFFF)) / 65536.0) * 2.0 * M_PI;
+ FP_RFS(n) = sinf(angle);
+ FP_RFS(n+1) = cosf(angle);
+}
+
+/* FIPR FVm,FVn PR=0 1111nnmm11101101 */
+INLINE void FIPR(sh4_state *sh4, UINT32 n)
+{
+UINT32 m;
+float ml[4];
+int a;
+
+ m = (n & 3) << 2;
+ n = n & 12;
+ for (a = 0;a < 4;a++)
+ ml[a] = FP_RFS(n+a) * FP_RFS(m+a);
+ FP_RFS(n+3) = ml[0] + ml[1] + ml[2] + ml[3];
+}
+
+/* FTRV XMTRX,FVn PR=0 1111nn0111111101 */
+INLINE void FTRV(sh4_state *sh4, UINT32 n)
+{
+int i,j;
+float sum[4];
+
+ n = n & 12;
+ for (i = 0;i < 4;i++) {
+ sum[i] = 0;
+ for (j=0;j < 4;j++)
+ sum[i] += FP_XFS((j << 2) + i)*FP_RFS(n + j);
+ }
+ for (i = 0;i < 4;i++)
+ FP_RFS(n + i) = sum[i];
+}
+
+INLINE void op1111(sh4_state *sh4, UINT16 opcode)
+{
+ switch (opcode & 0xf)
+ {
+ case 0:
+ FADD(sh4, Rm,Rn);
+ break;
+ case 1:
+ FSUB(sh4, Rm,Rn);
+ break;
+ case 2:
+ FMUL(sh4, Rm,Rn);
+ break;
+ case 3:
+ FDIV(sh4, Rm,Rn);
+ break;
+ case 4:
+ FCMP_EQ(sh4, Rm,Rn);
+ break;
+ case 5:
+ FCMP_GT(sh4, Rm,Rn);
+ break;
+ case 6:
+ FMOVS0FR(sh4, Rm,Rn);
+ break;
+ case 7:
+ FMOVFRS0(sh4, Rm,Rn);
+ break;
+ case 8:
+ FMOVMRFR(sh4, Rm,Rn);
+ break;
+ case 9:
+ FMOVMRIFR(sh4, Rm,Rn);
+ break;
+ case 10:
+ FMOVFRMR(sh4, Rm,Rn);
+ break;
+ case 11:
+ FMOVFRMDR(sh4, Rm,Rn);
+ break;
+ case 12:
+ FMOVFR(sh4, Rm,Rn);
+ break;
+ case 13:
+ switch (opcode & 0xF0)
+ {
+ case 0x00:
+ FSTS(sh4, Rn);
+ break;
+ case 0x10:
+ FLDS(sh4, Rn);
+ break;
+ case 0x20:
+ FLOAT(sh4, Rn);
+ break;
+ case 0x30:
+ FTRC(sh4, Rn);
+ break;
+ case 0x40:
+ FNEG(sh4, Rn);
+ break;
+ case 0x50:
+ FABS(sh4, Rn);
+ break;
+ case 0x60:
+ FSQRT(sh4, Rn);
+ break;
+ case 0x70:
+ FSRRA(sh4, Rn);
+ break;
+ case 0x80:
+ FLDI0(sh4, Rn);
+ break;
+ case 0x90:
+ FLDI1(sh4, Rn);
+ break;
+ case 0xA0:
+ FCNVSD(sh4, Rn);
+ break;
+ case 0xB0:
+ FCNVDS(sh4, Rn);
+ break;
+ case 0xE0:
+ FIPR(sh4, Rn);
+ break;
+ case 0xF0:
+ if (opcode & 0x100) {
+ if (opcode & 0x200) {
+ switch (opcode & 0xC00)
+ {
+ case 0x000:
+ FSCHG(sh4);
+ break;
+ case 0x800:
+ FRCHG(sh4);
+ break;
+ default:
+ debugger_break(sh4->device->machine());
+ break;
+ }
+ } else {
+ FTRV(sh4, Rn);
+ }
+ } else {
+ FSSCA(sh4, Rn);
+ }
+ break;
+ default:
+ debugger_break(sh4->device->machine());
+ break;
+ }
+ break;
+ case 14:
+ FMAC(sh4, Rm,Rn);
+ break;
+ default:
+ debugger_break(sh4->device->machine());
+ break;
+ }
+}
+
+/*****************************************************************************
+ * MAME CPU INTERFACE
+ *****************************************************************************/
+
+static CPU_RESET( sh4 )
+{
+ sh4_state *sh4 = get_safe_token(device);
+ emu_timer *tsaved[4];
+ emu_timer *tsave[5];
+ UINT32 *m;
+ int save_is_slave;
+ int savecpu_clock, savebus_clock, savepm_clock;
+
+ void (*f)(UINT32 data);
+ device_irq_callback save_irqcallback;
+
+ m = sh4->m;
+ tsaved[0] = sh4->dma_timer[0];
+ tsaved[1] = sh4->dma_timer[1];
+ tsaved[2] = sh4->dma_timer[2];
+ tsaved[3] = sh4->dma_timer[3];
+ tsave[0] = sh4->refresh_timer;
+ tsave[1] = sh4->rtc_timer;
+ tsave[2] = sh4->timer[0];
+ tsave[3] = sh4->timer[1];
+ tsave[4] = sh4->timer[2];
+
+ f = sh4->ftcsr_read_callback;
+ save_irqcallback = sh4->irq_callback;
+ save_is_slave = sh4->is_slave;
+ savecpu_clock = sh4->cpu_clock;
+ savebus_clock = sh4->bus_clock;
+ savepm_clock = sh4->pm_clock;
+ memset(sh4, 0, sizeof(*sh4));
+ sh4->is_slave = save_is_slave;
+ sh4->cpu_clock = savecpu_clock;
+ sh4->bus_clock = savebus_clock;
+ sh4->pm_clock = savepm_clock;
+ sh4->ftcsr_read_callback = f;
+ sh4->irq_callback = save_irqcallback;
+ sh4->device = device;
+ sh4->internal = device->space(AS_PROGRAM);
+ sh4->program = device->space(AS_PROGRAM);
+ sh4->direct = &sh4->program->direct();
+ sh4->io = device->space(AS_IO);
+
+ sh4->dma_timer[0] = tsaved[0];
+ sh4->dma_timer[1] = tsaved[1];
+ sh4->dma_timer[2] = tsaved[2];
+ sh4->dma_timer[3] = tsaved[3];
+ sh4->refresh_timer = tsave[0];
+ sh4->rtc_timer = tsave[1];
+ sh4->timer[0] = tsave[2];
+ sh4->timer[1] = tsave[3];
+ sh4->timer[2] = tsave[4];
+ sh4->m = m;
+ memset(sh4->m, 0, 16384*4);
+ sh4_default_exception_priorities(sh4);
+ memset(sh4->exception_requesting, 0, sizeof(sh4->exception_requesting));
+
+ sh4->rtc_timer->adjust(attotime::from_hz(128));
+ sh4->m[RCR2] = 0x09;
+ sh4->m[TCOR0] = 0xffffffff;
+ sh4->m[TCNT0] = 0xffffffff;
+ sh4->m[TCOR1] = 0xffffffff;
+ sh4->m[TCNT1] = 0xffffffff;
+ sh4->m[TCOR2] = 0xffffffff;
+ sh4->m[TCNT2] = 0xffffffff;
+
+ sh4->pc = 0xa0000000;
+ sh4->r[15] = RL(sh4,4);
+ sh4->sr = 0x700000f0;
+ sh4->fpscr = 0x00040001;
+ sh4->fpu_sz = (sh4->fpscr & SZ) ? 1 : 0;
+ sh4->fpu_pr = (sh4->fpscr & PR) ? 1 : 0;
+ sh4->fpul = 0;
+ sh4->dbr = 0;
+
+ sh4->internal_irq_level = -1;
+ sh4->irln = 15;
+ sh4->sleep_mode = 0;
+
+ sh4->sh4_mmu_enabled = 0;
+
+ sh4->cpu_type = CPU_TYPE_SH4;
+}
+
+/*-------------------------------------------------
+ sh3_reset - reset the processor
+-------------------------------------------------*/
+
+static CPU_RESET( sh3 )
+{
+ sh4_state *sh4 = get_safe_token(device);
+ CPU_RESET_CALL(sh4);
+ sh4->cpu_type = CPU_TYPE_SH3;
+}
+
+/* Execute cycles - returns number of cycles actually run */
+static CPU_EXECUTE( sh4 )
+{
+ sh4_state *sh4 = get_safe_token(device);
+
+ if (sh4->cpu_off)
+ {
+ sh4->sh4_icount = 0;
+ return;
+ }
+
+ do
+ {
+ UINT32 opcode;
+
+ if (sh4->delay)
+ {
+ opcode = sh4->direct->read_decrypted_word((UINT32)(sh4->delay & AM), WORD2_XOR_LE(0));
+ sh4->pc -= 2;
+ }
+ else
+ opcode = sh4->direct->read_decrypted_word((UINT32)(sh4->pc & AM), WORD2_XOR_LE(0));
+
+ debugger_instruction_hook(device, sh4->pc & AM);
+
+ sh4->delay = 0;
+ sh4->pc += 2;
+ sh4->ppc = sh4->pc;
+
+ switch (opcode & ( 15 << 12))
+ {
+ case 0<<12: op0000(sh4, opcode); break;
+ case 1<<12: op0001(sh4, opcode); break;
+ case 2<<12: op0010(sh4, opcode); break;
+ case 3<<12: op0011(sh4, opcode); break;
+ case 4<<12: op0100(sh4, opcode); break;
+ case 5<<12: op0101(sh4, opcode); break;
+ case 6<<12: op0110(sh4, opcode); break;
+ case 7<<12: op0111(sh4, opcode); break;
+ case 8<<12: op1000(sh4, opcode); break;
+ case 9<<12: op1001(sh4, opcode); break;
+ case 10<<12: op1010(sh4, opcode); break;
+ case 11<<12: op1011(sh4, opcode); break;
+ case 12<<12: op1100(sh4, opcode); break;
+ case 13<<12: op1101(sh4, opcode); break;
+ case 14<<12: op1110(sh4, opcode); break;
+ default: op1111(sh4, opcode); break;
+ }
+
+ if (sh4->test_irq && !sh4->delay)
+ {
+ sh4_check_pending_irq(sh4, "mame_sh4_execute");
+ }
+ sh4->sh4_icount--;
+ } while( sh4->sh4_icount > 0 );
+}
+
+static CPU_INIT( sh4 )
+{
+ const struct sh4_config *conf = (const struct sh4_config *)device->static_config();
+ sh4_state *sh4 = get_safe_token(device);
+
+ sh4_common_init(device);
+
+ sh4_parse_configuration(sh4, conf);
+
+ sh4->irq_callback = irqcallback;
+ sh4->device = device;
+ sh4->internal = device->space(AS_PROGRAM);
+ sh4->program = device->space(AS_PROGRAM);
+ sh4->io = device->space(AS_IO);
+ sh4_default_exception_priorities(sh4);
+ sh4->irln = 15;
+ sh4->test_irq = 0;
+
+ device->save_item(NAME(sh4->pc));
+ device->save_item(NAME(sh4->r[15]));
+ device->save_item(NAME(sh4->sr));
+ device->save_item(NAME(sh4->pr));
+ device->save_item(NAME(sh4->gbr));
+ device->save_item(NAME(sh4->vbr));
+ device->save_item(NAME(sh4->mach));
+ device->save_item(NAME(sh4->macl));
+ device->save_item(NAME(sh4->spc));
+ device->save_item(NAME(sh4->ssr));
+ device->save_item(NAME(sh4->sgr));
+ device->save_item(NAME(sh4->fpscr));
+ device->save_item(NAME(sh4->r[ 0]));
+ device->save_item(NAME(sh4->r[ 1]));
+ device->save_item(NAME(sh4->r[ 2]));
+ device->save_item(NAME(sh4->r[ 3]));
+ device->save_item(NAME(sh4->r[ 4]));
+ device->save_item(NAME(sh4->r[ 5]));
+ device->save_item(NAME(sh4->r[ 6]));
+ device->save_item(NAME(sh4->r[ 7]));
+ device->save_item(NAME(sh4->r[ 8]));
+ device->save_item(NAME(sh4->r[ 9]));
+ device->save_item(NAME(sh4->r[10]));
+ device->save_item(NAME(sh4->r[11]));
+ device->save_item(NAME(sh4->r[12]));
+ device->save_item(NAME(sh4->r[13]));
+ device->save_item(NAME(sh4->r[14]));
+ device->save_item(NAME(sh4->fr[ 0]));
+ device->save_item(NAME(sh4->fr[ 1]));
+ device->save_item(NAME(sh4->fr[ 2]));
+ device->save_item(NAME(sh4->fr[ 3]));
+ device->save_item(NAME(sh4->fr[ 4]));
+ device->save_item(NAME(sh4->fr[ 5]));
+ device->save_item(NAME(sh4->fr[ 6]));
+ device->save_item(NAME(sh4->fr[ 7]));
+ device->save_item(NAME(sh4->fr[ 8]));
+ device->save_item(NAME(sh4->fr[ 9]));
+ device->save_item(NAME(sh4->fr[10]));
+ device->save_item(NAME(sh4->fr[11]));
+ device->save_item(NAME(sh4->fr[12]));
+ device->save_item(NAME(sh4->fr[13]));
+ device->save_item(NAME(sh4->fr[14]));
+ device->save_item(NAME(sh4->fr[15]));
+ device->save_item(NAME(sh4->xf[ 0]));
+ device->save_item(NAME(sh4->xf[ 1]));
+ device->save_item(NAME(sh4->xf[ 2]));
+ device->save_item(NAME(sh4->xf[ 3]));
+ device->save_item(NAME(sh4->xf[ 4]));
+ device->save_item(NAME(sh4->xf[ 5]));
+ device->save_item(NAME(sh4->xf[ 6]));
+ device->save_item(NAME(sh4->xf[ 7]));
+ device->save_item(NAME(sh4->xf[ 8]));
+ device->save_item(NAME(sh4->xf[ 9]));
+ device->save_item(NAME(sh4->xf[10]));
+ device->save_item(NAME(sh4->xf[11]));
+ device->save_item(NAME(sh4->xf[12]));
+ device->save_item(NAME(sh4->xf[13]));
+ device->save_item(NAME(sh4->xf[14]));
+ device->save_item(NAME(sh4->xf[15]));
+ device->save_item(NAME(sh4->ea));
+ device->save_item(NAME(sh4->fpul));
+ device->save_item(NAME(sh4->dbr));
+ device->save_item(NAME(sh4->exception_priority));
+ device->save_item(NAME(sh4->exception_requesting));
+
+}
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( sh4 )
+{
+ sh4_state *sh4 = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + SH4_IRL0: sh4_set_irq_line(sh4, SH4_IRL0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH4_IRL1: sh4_set_irq_line(sh4, SH4_IRL1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH4_IRL2: sh4_set_irq_line(sh4, SH4_IRL2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH4_IRL3: sh4_set_irq_line(sh4, SH4_IRL3, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH4_IRLn: sh4_set_irq_line(sh4, SH4_IRLn, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: sh4_set_irq_line(sh4, INPUT_LINE_NMI, info->i); break;
+
+ case CPUINFO_INT_REGISTER + SH4_PC:
+ case CPUINFO_INT_PC: sh4->pc = info->i; sh4->delay = 0; break;
+ case CPUINFO_INT_SP: sh4->r[15] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_PR: sh4->pr = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_SR:
+ sh4->sr = info->i;
+ sh4_exception_recompute(sh4);
+ sh4_check_pending_irq(sh4, "sh4_set_info");
+ break;
+ case CPUINFO_INT_REGISTER + SH4_GBR: sh4->gbr = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_VBR: sh4->vbr = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_DBR: sh4->dbr = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_MACH: sh4->mach = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_MACL: sh4->macl = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R0: sh4->r[ 0] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R1: sh4->r[ 1] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R2: sh4->r[ 2] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R3: sh4->r[ 3] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R4: sh4->r[ 4] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R5: sh4->r[ 5] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R6: sh4->r[ 6] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R7: sh4->r[ 7] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R8: sh4->r[ 8] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R9: sh4->r[ 9] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R10: sh4->r[10] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R11: sh4->r[11] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R12: sh4->r[12] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R13: sh4->r[13] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R14: sh4->r[14] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R15: sh4->r[15] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_EA: sh4->ea = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R0_BK0: sh4->rbnk[0][0] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R1_BK0: sh4->rbnk[0][1] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R2_BK0: sh4->rbnk[0][2] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R3_BK0: sh4->rbnk[0][3] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R4_BK0: sh4->rbnk[0][4] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R5_BK0: sh4->rbnk[0][5] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R6_BK0: sh4->rbnk[0][6] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R7_BK0: sh4->rbnk[0][7] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R0_BK1: sh4->rbnk[1][0] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R1_BK1: sh4->rbnk[1][1] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R2_BK1: sh4->rbnk[1][2] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R3_BK1: sh4->rbnk[1][3] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R4_BK1: sh4->rbnk[1][4] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R5_BK1: sh4->rbnk[1][5] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R6_BK1: sh4->rbnk[1][6] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R7_BK1: sh4->rbnk[1][7] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_SPC: sh4->spc = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_SSR: sh4->ssr = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_SGR: sh4->sgr = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FPSCR: sh4->fpscr = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FPUL: sh4->fpul = info->i; break;
+#ifdef LSB_FIRST
+ case CPUINFO_STR_REGISTER + SH4_FR0: sh4->fr[ 0 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR1: sh4->fr[ 1 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR2: sh4->fr[ 2 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR3: sh4->fr[ 3 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR4: sh4->fr[ 4 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR5: sh4->fr[ 5 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR6: sh4->fr[ 6 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR7: sh4->fr[ 7 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR8: sh4->fr[ 8 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR9: sh4->fr[ 9 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR10: sh4->fr[10 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR11: sh4->fr[11 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR12: sh4->fr[12 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR13: sh4->fr[13 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR14: sh4->fr[14 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR15: sh4->fr[15 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF0: sh4->xf[ 0 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF1: sh4->xf[ 1 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF2: sh4->xf[ 2 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF3: sh4->xf[ 3 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF4: sh4->xf[ 4 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF5: sh4->xf[ 5 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF6: sh4->xf[ 6 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF7: sh4->xf[ 7 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF8: sh4->xf[ 8 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF9: sh4->xf[ 9 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF10: sh4->xf[10 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF11: sh4->xf[11 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF12: sh4->xf[12 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF13: sh4->xf[13 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF14: sh4->xf[14 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF15: sh4->xf[15 ^ sh4->fpu_pr] = info->i; break;
+#else
+ case CPUINFO_STR_REGISTER + SH4_FR0: sh4->fr[ 0] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR1: sh4->fr[ 1] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR2: sh4->fr[ 2] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR3: sh4->fr[ 3] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR4: sh4->fr[ 4] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR5: sh4->fr[ 5] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR6: sh4->fr[ 6] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR7: sh4->fr[ 7] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR8: sh4->fr[ 8] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR9: sh4->fr[ 9] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR10: sh4->fr[10] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR11: sh4->fr[11] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR12: sh4->fr[12] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR13: sh4->fr[13] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR14: sh4->fr[14] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR15: sh4->fr[15] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF0: sh4->xf[ 0] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF1: sh4->xf[ 1] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF2: sh4->xf[ 2] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF3: sh4->xf[ 3] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF4: sh4->xf[ 4] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF5: sh4->xf[ 5] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF6: sh4->xf[ 6] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF7: sh4->xf[ 7] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF8: sh4->xf[ 8] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF9: sh4->xf[ 9] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF10: sh4->xf[10] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF11: sh4->xf[11] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF12: sh4->xf[12] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF13: sh4->xf[13] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF14: sh4->xf[14] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF15: sh4->xf[15] = info->i; break;
+#endif
+ }
+}
+
+void sh4_set_ftcsr_callback(device_t *device, sh4_ftcsr_callback callback)
+{
+ sh4_state *sh4 = get_safe_token(device);
+ sh4->ftcsr_read_callback = callback;
+}
+
+
+#if 0
+/*When OC index mode is off (CCR.OIX = 0)*/
+static ADDRESS_MAP_START( sh4_internal_map, AS_PROGRAM, 64 )
+ AM_RANGE(0x1C000000, 0x1C000FFF) AM_RAM AM_MIRROR(0x03FFD000)
+ AM_RANGE(0x1C002000, 0x1C002FFF) AM_RAM AM_MIRROR(0x03FFD000)
+ AM_RANGE(0xE0000000, 0xE000003F) AM_RAM AM_MIRROR(0x03FFFFC0)
+ADDRESS_MAP_END
+#endif
+
+/*When OC index mode is on (CCR.OIX = 1)*/
+static ADDRESS_MAP_START( sh4_internal_map, AS_PROGRAM, 64 )
+ AM_RANGE(0x1C000000, 0x1C000FFF) AM_RAM AM_MIRROR(0x01FFF000)
+ AM_RANGE(0x1E000000, 0x1E000FFF) AM_RAM AM_MIRROR(0x01FFF000)
+ AM_RANGE(0xE0000000, 0xE000003F) AM_RAM AM_MIRROR(0x03FFFFC0) // todo: store queues should be write only on DC's SH4, executing PREFM shouldn't cause an actual memory read access!
+ AM_RANGE(0xF6000000, 0xF7FFFFFF) AM_READWRITE(sh4_tlb_r,sh4_tlb_w)
+ AM_RANGE(0xFE000000, 0xFFFFFFFF) AM_READWRITE32(sh4_internal_r, sh4_internal_w, U64(0xffffffffffffffff))
+ADDRESS_MAP_END
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( sh4 )
+{
+ sh4_state *sh4 = (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(sh4_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_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 = 2; 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 = 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 = 64; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map64 = ADDRESS_MAP_NAME(sh4_internal_map); break;
+
+ case CPUINFO_INT_INPUT_STATE + SH4_IRL0: info->i = sh4->irq_line_state[SH4_IRL0]; break;
+ case CPUINFO_INT_INPUT_STATE + SH4_IRL1: info->i = sh4->irq_line_state[SH4_IRL1]; break;
+ case CPUINFO_INT_INPUT_STATE + SH4_IRL2: info->i = sh4->irq_line_state[SH4_IRL2]; break;
+ case CPUINFO_INT_INPUT_STATE + SH4_IRL3: info->i = sh4->irq_line_state[SH4_IRL3]; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = sh4->nmi_line_state; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = sh4->ppc; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + SH4_PC: info->i = (sh4->delay) ? (sh4->delay & AM) : (sh4->pc & AM); break;
+ case CPUINFO_INT_SP: info->i = sh4->r[15]; break;
+ case CPUINFO_INT_REGISTER + SH4_PR: info->i = sh4->pr; break;
+ case CPUINFO_INT_REGISTER + SH4_SR: info->i = sh4->sr; break;
+ case CPUINFO_INT_REGISTER + SH4_GBR: info->i = sh4->gbr; break;
+ case CPUINFO_INT_REGISTER + SH4_VBR: info->i = sh4->vbr; break;
+ case CPUINFO_INT_REGISTER + SH4_DBR: info->i = sh4->dbr; break;
+ case CPUINFO_INT_REGISTER + SH4_MACH: info->i = sh4->mach; break;
+ case CPUINFO_INT_REGISTER + SH4_MACL: info->i = sh4->macl; break;
+ case CPUINFO_INT_REGISTER + SH4_R0: info->i = sh4->r[ 0]; break;
+ case CPUINFO_INT_REGISTER + SH4_R1: info->i = sh4->r[ 1]; break;
+ case CPUINFO_INT_REGISTER + SH4_R2: info->i = sh4->r[ 2]; break;
+ case CPUINFO_INT_REGISTER + SH4_R3: info->i = sh4->r[ 3]; break;
+ case CPUINFO_INT_REGISTER + SH4_R4: info->i = sh4->r[ 4]; break;
+ case CPUINFO_INT_REGISTER + SH4_R5: info->i = sh4->r[ 5]; break;
+ case CPUINFO_INT_REGISTER + SH4_R6: info->i = sh4->r[ 6]; break;
+ case CPUINFO_INT_REGISTER + SH4_R7: info->i = sh4->r[ 7]; break;
+ case CPUINFO_INT_REGISTER + SH4_R8: info->i = sh4->r[ 8]; break;
+ case CPUINFO_INT_REGISTER + SH4_R9: info->i = sh4->r[ 9]; break;
+ case CPUINFO_INT_REGISTER + SH4_R10: info->i = sh4->r[10]; break;
+ case CPUINFO_INT_REGISTER + SH4_R11: info->i = sh4->r[11]; break;
+ case CPUINFO_INT_REGISTER + SH4_R12: info->i = sh4->r[12]; break;
+ case CPUINFO_INT_REGISTER + SH4_R13: info->i = sh4->r[13]; break;
+ case CPUINFO_INT_REGISTER + SH4_R14: info->i = sh4->r[14]; break;
+ case CPUINFO_INT_REGISTER + SH4_R15: info->i = sh4->r[15]; break;
+ case CPUINFO_INT_REGISTER + SH4_EA: info->i = sh4->ea; 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(sh4); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(sh4); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(sh4); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(sh4); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(sh4); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &sh4->sh4_icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "SH-4"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Hitachi SH7750"); 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 R. Belmont"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%s%s%s%s%c%c%d%c%c",
+ sh4->sr & MD ? "MD ":" ",
+ sh4->sr & sRB ? "RB ":" ",
+ sh4->sr & BL ? "BL ":" ",
+ sh4->sr & FD ? "FD ":" ",
+ sh4->sr & M ? 'M':'.',
+ sh4->sr & Q ? 'Q':'.',
+ (sh4->sr & I) >> 4,
+ sh4->sr & S ? 'S':'.',
+ sh4->sr & T ? 'T':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + SH4_PC: sprintf(info->s, "PC :%08X", sh4->pc); break;
+ case CPUINFO_STR_REGISTER + SH4_SR: sprintf(info->s, "SR :%08X", sh4->sr); break;
+ case CPUINFO_STR_REGISTER + SH4_PR: sprintf(info->s, "PR :%08X", sh4->pr); break;
+ case CPUINFO_STR_REGISTER + SH4_GBR: sprintf(info->s, "GBR :%08X", sh4->gbr); break;
+ case CPUINFO_STR_REGISTER + SH4_VBR: sprintf(info->s, "VBR :%08X", sh4->vbr); break;
+ case CPUINFO_STR_REGISTER + SH4_DBR: sprintf(info->s, "DBR :%08X", sh4->dbr); break;
+ case CPUINFO_STR_REGISTER + SH4_MACH: sprintf(info->s, "MACH:%08X", sh4->mach); break;
+ case CPUINFO_STR_REGISTER + SH4_MACL: sprintf(info->s, "MACL:%08X", sh4->macl); break;
+ case CPUINFO_STR_REGISTER + SH4_R0: sprintf(info->s, "R0 :%08X", sh4->r[ 0]); break;
+ case CPUINFO_STR_REGISTER + SH4_R1: sprintf(info->s, "R1 :%08X", sh4->r[ 1]); break;
+ case CPUINFO_STR_REGISTER + SH4_R2: sprintf(info->s, "R2 :%08X", sh4->r[ 2]); break;
+ case CPUINFO_STR_REGISTER + SH4_R3: sprintf(info->s, "R3 :%08X", sh4->r[ 3]); break;
+ case CPUINFO_STR_REGISTER + SH4_R4: sprintf(info->s, "R4 :%08X", sh4->r[ 4]); break;
+ case CPUINFO_STR_REGISTER + SH4_R5: sprintf(info->s, "R5 :%08X", sh4->r[ 5]); break;
+ case CPUINFO_STR_REGISTER + SH4_R6: sprintf(info->s, "R6 :%08X", sh4->r[ 6]); break;
+ case CPUINFO_STR_REGISTER + SH4_R7: sprintf(info->s, "R7 :%08X", sh4->r[ 7]); break;
+ case CPUINFO_STR_REGISTER + SH4_R8: sprintf(info->s, "R8 :%08X", sh4->r[ 8]); break;
+ case CPUINFO_STR_REGISTER + SH4_R9: sprintf(info->s, "R9 :%08X", sh4->r[ 9]); break;
+ case CPUINFO_STR_REGISTER + SH4_R10: sprintf(info->s, "R10 :%08X", sh4->r[10]); break;
+ case CPUINFO_STR_REGISTER + SH4_R11: sprintf(info->s, "R11 :%08X", sh4->r[11]); break;
+ case CPUINFO_STR_REGISTER + SH4_R12: sprintf(info->s, "R12 :%08X", sh4->r[12]); break;
+ case CPUINFO_STR_REGISTER + SH4_R13: sprintf(info->s, "R13 :%08X", sh4->r[13]); break;
+ case CPUINFO_STR_REGISTER + SH4_R14: sprintf(info->s, "R14 :%08X", sh4->r[14]); break;
+ case CPUINFO_STR_REGISTER + SH4_R15: sprintf(info->s, "R15 :%08X", sh4->r[15]); break;
+ case CPUINFO_STR_REGISTER + SH4_EA: sprintf(info->s, "EA :%08X", sh4->ea); break;
+ case CPUINFO_STR_REGISTER + SH4_R0_BK0: sprintf(info->s, "R0 BK 0 :%08X", sh4->rbnk[0][0]); break;
+ case CPUINFO_STR_REGISTER + SH4_R1_BK0: sprintf(info->s, "R1 BK 0 :%08X", sh4->rbnk[0][1]); break;
+ case CPUINFO_STR_REGISTER + SH4_R2_BK0: sprintf(info->s, "R2 BK 0 :%08X", sh4->rbnk[0][2]); break;
+ case CPUINFO_STR_REGISTER + SH4_R3_BK0: sprintf(info->s, "R3 BK 0 :%08X", sh4->rbnk[0][3]); break;
+ case CPUINFO_STR_REGISTER + SH4_R4_BK0: sprintf(info->s, "R4 BK 0 :%08X", sh4->rbnk[0][4]); break;
+ case CPUINFO_STR_REGISTER + SH4_R5_BK0: sprintf(info->s, "R5 BK 0 :%08X", sh4->rbnk[0][5]); break;
+ case CPUINFO_STR_REGISTER + SH4_R6_BK0: sprintf(info->s, "R6 BK 0 :%08X", sh4->rbnk[0][6]); break;
+ case CPUINFO_STR_REGISTER + SH4_R7_BK0: sprintf(info->s, "R7 BK 0 :%08X", sh4->rbnk[0][7]); break;
+ case CPUINFO_STR_REGISTER + SH4_R0_BK1: sprintf(info->s, "R0 BK 1 :%08X", sh4->rbnk[1][0]); break;
+ case CPUINFO_STR_REGISTER + SH4_R1_BK1: sprintf(info->s, "R1 BK 1 :%08X", sh4->rbnk[1][1]); break;
+ case CPUINFO_STR_REGISTER + SH4_R2_BK1: sprintf(info->s, "R2 BK 1 :%08X", sh4->rbnk[1][2]); break;
+ case CPUINFO_STR_REGISTER + SH4_R3_BK1: sprintf(info->s, "R3 BK 1 :%08X", sh4->rbnk[1][3]); break;
+ case CPUINFO_STR_REGISTER + SH4_R4_BK1: sprintf(info->s, "R4 BK 1 :%08X", sh4->rbnk[1][4]); break;
+ case CPUINFO_STR_REGISTER + SH4_R5_BK1: sprintf(info->s, "R5 BK 1 :%08X", sh4->rbnk[1][5]); break;
+ case CPUINFO_STR_REGISTER + SH4_R6_BK1: sprintf(info->s, "R6 BK 1 :%08X", sh4->rbnk[1][6]); break;
+ case CPUINFO_STR_REGISTER + SH4_R7_BK1: sprintf(info->s, "R7 BK 1 :%08X", sh4->rbnk[1][7]); break;
+ case CPUINFO_STR_REGISTER + SH4_SPC: sprintf(info->s, "SPC :%08X", sh4->spc); break;
+ case CPUINFO_STR_REGISTER + SH4_SSR: sprintf(info->s, "SSR :%08X", sh4->ssr); break;
+ case CPUINFO_STR_REGISTER + SH4_SGR: sprintf(info->s, "SGR :%08X", sh4->sgr); break;
+ case CPUINFO_STR_REGISTER + SH4_FPSCR: sprintf(info->s, "FPSCR :%08X", sh4->fpscr); break;
+ case CPUINFO_STR_REGISTER + SH4_FPUL: sprintf(info->s, "FPUL :%08X", sh4->fpul); break;
+#ifdef LSB_FIRST
+ case CPUINFO_STR_REGISTER + SH4_FR0: sprintf(info->s, "FR0 :%08X %f", FP_RS2( 0),(double)FP_RFS2( 0)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR1: sprintf(info->s, "FR1 :%08X %f", FP_RS2( 1),(double)FP_RFS2( 1)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR2: sprintf(info->s, "FR2 :%08X %f", FP_RS2( 2),(double)FP_RFS2( 2)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR3: sprintf(info->s, "FR3 :%08X %f", FP_RS2( 3),(double)FP_RFS2( 3)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR4: sprintf(info->s, "FR4 :%08X %f", FP_RS2( 4),(double)FP_RFS2( 4)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR5: sprintf(info->s, "FR5 :%08X %f", FP_RS2( 5),(double)FP_RFS2( 5)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR6: sprintf(info->s, "FR6 :%08X %f", FP_RS2( 6),(double)FP_RFS2( 6)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR7: sprintf(info->s, "FR7 :%08X %f", FP_RS2( 7),(double)FP_RFS2( 7)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR8: sprintf(info->s, "FR8 :%08X %f", FP_RS2( 8),(double)FP_RFS2( 8)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR9: sprintf(info->s, "FR9 :%08X %f", FP_RS2( 9),(double)FP_RFS2( 9)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR10: sprintf(info->s, "FR10 :%08X %f", FP_RS2(10),(double)FP_RFS2(10)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR11: sprintf(info->s, "FR11 :%08X %f", FP_RS2(11),(double)FP_RFS2(11)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR12: sprintf(info->s, "FR12 :%08X %f", FP_RS2(12),(double)FP_RFS2(12)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR13: sprintf(info->s, "FR13 :%08X %f", FP_RS2(13),(double)FP_RFS2(13)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR14: sprintf(info->s, "FR14 :%08X %f", FP_RS2(14),(double)FP_RFS2(14)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR15: sprintf(info->s, "FR15 :%08X %f", FP_RS2(15),(double)FP_RFS2(15)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF0: sprintf(info->s, "XF0 :%08X %f", FP_XS2( 0),(double)FP_XFS2( 0)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF1: sprintf(info->s, "XF1 :%08X %f", FP_XS2( 1),(double)FP_XFS2( 1)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF2: sprintf(info->s, "XF2 :%08X %f", FP_XS2( 2),(double)FP_XFS2( 2)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF3: sprintf(info->s, "XF3 :%08X %f", FP_XS2( 3),(double)FP_XFS2( 3)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF4: sprintf(info->s, "XF4 :%08X %f", FP_XS2( 4),(double)FP_XFS2( 4)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF5: sprintf(info->s, "XF5 :%08X %f", FP_XS2( 5),(double)FP_XFS2( 5)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF6: sprintf(info->s, "XF6 :%08X %f", FP_XS2( 6),(double)FP_XFS2( 6)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF7: sprintf(info->s, "XF7 :%08X %f", FP_XS2( 7),(double)FP_XFS2( 7)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF8: sprintf(info->s, "XF8 :%08X %f", FP_XS2( 8),(double)FP_XFS2( 8)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF9: sprintf(info->s, "XF9 :%08X %f", FP_XS2( 9),(double)FP_XFS2( 9)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF10: sprintf(info->s, "XF10 :%08X %f", FP_XS2(10),(double)FP_XFS2(10)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF11: sprintf(info->s, "XF11 :%08X %f", FP_XS2(11),(double)FP_XFS2(11)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF12: sprintf(info->s, "XF12 :%08X %f", FP_XS2(12),(double)FP_XFS2(12)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF13: sprintf(info->s, "XF13 :%08X %f", FP_XS2(13),(double)FP_XFS2(13)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF14: sprintf(info->s, "XF14 :%08X %f", FP_XS2(14),(double)FP_XFS2(14)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF15: sprintf(info->s, "XF15 :%08X %f", FP_XS2(15),(double)FP_XFS2(15)); break;
+#else
+ case CPUINFO_STR_REGISTER + SH4_FR0: sprintf(info->s, "FR0 :%08X %f", FP_RS( 0),(double)FP_RFS( 0)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR1: sprintf(info->s, "FR1 :%08X %f", FP_RS( 1),(double)FP_RFS( 1)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR2: sprintf(info->s, "FR2 :%08X %f", FP_RS( 2),(double)FP_RFS( 2)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR3: sprintf(info->s, "FR3 :%08X %f", FP_RS( 3),(double)FP_RFS( 3)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR4: sprintf(info->s, "FR4 :%08X %f", FP_RS( 4),(double)FP_RFS( 4)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR5: sprintf(info->s, "FR5 :%08X %f", FP_RS( 5),(double)FP_RFS( 5)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR6: sprintf(info->s, "FR6 :%08X %f", FP_RS( 6),(double)FP_RFS( 6)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR7: sprintf(info->s, "FR7 :%08X %f", FP_RS( 7),(double)FP_RFS( 7)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR8: sprintf(info->s, "FR8 :%08X %f", FP_RS( 8),(double)FP_RFS( 8)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR9: sprintf(info->s, "FR9 :%08X %f", FP_RS( 9),(double)FP_RFS( 9)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR10: sprintf(info->s, "FR10 :%08X %f", FP_RS(10),(double)FP_RFS(10)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR11: sprintf(info->s, "FR11 :%08X %f", FP_RS(11),(double)FP_RFS(11)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR12: sprintf(info->s, "FR12 :%08X %f", FP_RS(12),(double)FP_RFS(12)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR13: sprintf(info->s, "FR13 :%08X %f", FP_RS(13),(double)FP_RFS(13)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR14: sprintf(info->s, "FR14 :%08X %f", FP_RS(14),(double)FP_RFS(14)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR15: sprintf(info->s, "FR15 :%08X %f", FP_RS(15),(double)FP_RFS(15)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF0: sprintf(info->s, "XF0 :%08X %f", FP_XS( 0),(double)FP_XFS( 0)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF1: sprintf(info->s, "XF1 :%08X %f", FP_XS( 1),(double)FP_XFS( 1)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF2: sprintf(info->s, "XF2 :%08X %f", FP_XS( 2),(double)FP_XFS( 2)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF3: sprintf(info->s, "XF3 :%08X %f", FP_XS( 3),(double)FP_XFS( 3)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF4: sprintf(info->s, "XF4 :%08X %f", FP_XS( 4),(double)FP_XFS( 4)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF5: sprintf(info->s, "XF5 :%08X %f", FP_XS( 5),(double)FP_XFS( 5)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF6: sprintf(info->s, "XF6 :%08X %f", FP_XS( 6),(double)FP_XFS( 6)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF7: sprintf(info->s, "XF7 :%08X %f", FP_XS( 7),(double)FP_XFS( 7)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF8: sprintf(info->s, "XF8 :%08X %f", FP_XS( 8),(double)FP_XFS( 8)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF9: sprintf(info->s, "XF9 :%08X %f", FP_XS( 9),(double)FP_XFS( 9)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF10: sprintf(info->s, "XF10 :%08X %f", FP_XS(10),(double)FP_XFS(10)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF11: sprintf(info->s, "XF11 :%08X %f", FP_XS(11),(double)FP_XFS(11)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF12: sprintf(info->s, "XF12 :%08X %f", FP_XS(12),(double)FP_XFS(12)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF13: sprintf(info->s, "XF13 :%08X %f", FP_XS(13),(double)FP_XFS(13)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF14: sprintf(info->s, "XF14 :%08X %f", FP_XS(14),(double)FP_XFS(14)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF15: sprintf(info->s, "XF15 :%08X %f", FP_XS(15),(double)FP_XFS(15)); break; //%01.2e
+#endif
+ }
+}
+
+CPU_GET_INFO( sh3 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(sh3); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "SH-3"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Hitachi SH7700"); break;
+
+ default: CPU_GET_INFO_CALL(sh4); break;
+ }
+}
+
+CPU_GET_INFO( sh3be )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(sh3); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "SH-3"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Hitachi SH7700"); break;
+
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ default: CPU_GET_INFO_CALL(sh4); break;
+ }
+}
+
+CPU_GET_INFO( sh4be )
+{
+ switch (state)
+ {
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ default: CPU_GET_INFO_CALL(sh4); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(SH3LE, sh3);
+DEFINE_LEGACY_CPU_DEVICE(SH3BE, sh3be);
+DEFINE_LEGACY_CPU_DEVICE(SH4LE, sh4);
+DEFINE_LEGACY_CPU_DEVICE(SH4BE, sh4be);
+
+#endif // USE_SH4DRC
diff --git a/trunk/src/emu/cpu/sh4/sh4.h b/trunk/src/emu/cpu/sh4/sh4.h
new file mode 100644
index 00000000000..d49b7cf4c36
--- /dev/null
+++ b/trunk/src/emu/cpu/sh4/sh4.h
@@ -0,0 +1,131 @@
+/*****************************************************************************
+ *
+ * sh4->h
+ * Portable Hitachi SH-4 (SH7750 family) emulator interface
+ *
+ * By R. Belmont, based on sh2.c by Juergen Buchmueller, Mariusz Wojcieszek,
+ * Olivier Galibert, Sylvain Glaize, and James Forshaw.
+ *
+ *****************************************************************************/
+
+#ifndef __SH4_H__
+#define __SH4_H__
+
+
+#define SH4_INT_NONE -1
+enum
+{
+ SH4_IRL0=0, SH4_IRL1, SH4_IRL2, SH4_IRL3, SH4_IRLn
+};
+
+enum
+{
+ SH4_PC=1, SH4_SR, SH4_PR, SH4_GBR, SH4_VBR, SH4_DBR, SH4_MACH, SH4_MACL,
+ SH4_R0, SH4_R1, SH4_R2, SH4_R3, SH4_R4, SH4_R5, SH4_R6, SH4_R7,
+ SH4_R8, SH4_R9, SH4_R10, SH4_R11, SH4_R12, SH4_R13, SH4_R14, SH4_R15, SH4_EA,
+ SH4_R0_BK0, SH4_R1_BK0, SH4_R2_BK0, SH4_R3_BK0, SH4_R4_BK0, SH4_R5_BK0, SH4_R6_BK0, SH4_R7_BK0,
+ SH4_R0_BK1, SH4_R1_BK1, SH4_R2_BK1, SH4_R3_BK1, SH4_R4_BK1, SH4_R5_BK1, SH4_R6_BK1, SH4_R7_BK1,
+ SH4_SPC, SH4_SSR, SH4_SGR, SH4_FPSCR, SH4_FPUL, SH4_FR0, SH4_FR1, SH4_FR2, SH4_FR3, SH4_FR4, SH4_FR5,
+ SH4_FR6, SH4_FR7, SH4_FR8, SH4_FR9, SH4_FR10, SH4_FR11, SH4_FR12, SH4_FR13, SH4_FR14, SH4_FR15,
+ SH4_XF0, SH4_XF1, SH4_XF2, SH4_XF3, SH4_XF4, SH4_XF5, SH4_XF6, SH4_XF7,
+ SH4_XF8, SH4_XF9, SH4_XF10, SH4_XF11, SH4_XF12, SH4_XF13, SH4_XF14, SH4_XF15
+};
+
+enum
+{
+ SH4_INTC_NMI=23, SH4_INTC_IRLn0, SH4_INTC_IRLn1, SH4_INTC_IRLn2, SH4_INTC_IRLn3, SH4_INTC_IRLn4,
+ SH4_INTC_IRLn5, SH4_INTC_IRLn6, SH4_INTC_IRLn7, SH4_INTC_IRLn8, SH4_INTC_IRLn9, SH4_INTC_IRLnA,
+ SH4_INTC_IRLnB, SH4_INTC_IRLnC, SH4_INTC_IRLnD, SH4_INTC_IRLnE, SH4_INTC_IRL0, SH4_INTC_IRL1,
+ SH4_INTC_IRL2, SH4_INTC_IRL3, SH4_INTC_HUDI, SH4_INTC_GPOI, SH4_INTC_DMTE0, SH4_INTC_DMTE1,
+ SH4_INTC_DMTE2, SH4_INTC_DMTE3, SH4_INTC_DMTE4, SH4_INTC_DMTE5, SH4_INTC_DMTE6, SH4_INTC_DMTE7,
+ SH4_INTC_DMAE, SH4_INTC_TUNI3, SH4_INTC_TUNI4, SH4_INTC_TUNI0, SH4_INTC_TUNI1, SH4_INTC_TUNI2,
+ SH4_INTC_TICPI2, SH4_INTC_ATI, SH4_INTC_PRI, SH4_INTC_CUI, SH4_INTC_SCI1ERI, SH4_INTC_SCI1RXI,
+ SH4_INTC_SCI1TXI, SH4_INTC_SCI1TEI, SH4_INTC_SCIFERI, SH4_INTC_SCIFRXI, SH4_INTC_SCIFBRI,
+ SH4_INTC_SCIFTXI, SH4_INTC_ITI, SH4_INTC_RCMI, SH4_INTC_ROVI
+};
+
+#define SH4_FPU_PZERO 0
+#define SH4_FPU_NZERO 1
+#define SH4_FPU_DENORM 2
+#define SH4_FPU_NORM 3
+#define SH4_FPU_PINF 4
+#define SH4_FPU_NINF 5
+#define SH4_FPU_qNaN 6
+#define SH4_FPU_sNaN 7
+
+enum
+{
+ SH4_IOPORT_16=8*0,
+ SH4_IOPORT_4=8*1,
+ SH4_IOPORT_DMA=8*2,
+ // future use
+ SH4_IOPORT_SCI=8*3,
+ SH4_IOPORT_SCIF=8*4
+};
+
+struct sh4_config
+{
+ int md2;
+ int md1;
+ int md0;
+ int md6;
+ int md4;
+ int md3;
+ int md5;
+ int md7;
+ int md8;
+ int clock;
+};
+
+struct sh4_device_dma
+{
+ UINT32 length;
+ UINT32 size;
+ void *buffer;
+ int channel;
+};
+
+struct sh4_ddt_dma
+{
+ UINT32 source;
+ UINT32 length;
+ UINT32 size;
+ UINT32 destination;
+ void *buffer;
+ int direction;
+ int channel;
+ int mode;
+};
+
+typedef void (*sh4_ftcsr_callback)(UINT32);
+
+DECLARE_LEGACY_CPU_DEVICE(SH3LE, sh3);
+DECLARE_LEGACY_CPU_DEVICE(SH3BE, sh3be);
+DECLARE_LEGACY_CPU_DEVICE(SH4LE, sh4);
+DECLARE_LEGACY_CPU_DEVICE(SH4BE, sh4be);
+
+WRITE32_HANDLER( sh4_internal_w );
+READ32_HANDLER( sh4_internal_r );
+
+void sh4_set_frt_input(device_t *device, int state);
+void sh4_set_irln_input(device_t *device, int value);
+void sh4_set_ftcsr_callback(device_t *device, sh4_ftcsr_callback callback);
+int sh4_dma_data(device_t *device, struct sh4_device_dma *s);
+void sh4_dma_ddt(device_t *device, struct sh4_ddt_dma *s);
+
+/***************************************************************************
+ COMPILER-SPECIFIC OPTIONS
+***************************************************************************/
+
+#define SH4DRC_STRICT_VERIFY 0x0001 /* verify all instructions */
+#define SH4DRC_FLUSH_PC 0x0002 /* flush the PC value before each memory access */
+#define SH4DRC_STRICT_PCREL 0x0004 /* do actual loads on MOVLI/MOVWI instead of collapsing to immediates */
+
+#define SH4DRC_COMPATIBLE_OPTIONS (SH4DRC_STRICT_VERIFY | SH4DRC_FLUSH_PC | SH4DRC_STRICT_PCREL)
+#define SH4DRC_FASTEST_OPTIONS (0)
+
+void sh4drc_set_options(device_t *device, UINT32 options);
+void sh4drc_add_pcflush(device_t *device, offs_t address);
+
+#endif /* __SH4_H__ */
+
diff --git a/trunk/src/emu/cpu/sh4/sh4comn.c b/trunk/src/emu/cpu/sh4/sh4comn.c
new file mode 100644
index 00000000000..7fc70281eef
--- /dev/null
+++ b/trunk/src/emu/cpu/sh4/sh4comn.c
@@ -0,0 +1,1566 @@
+/*****************************************************************************
+ *
+ * sh4comn.c
+ *
+ * SH-4 non-specific components
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "sh4.h"
+#include "sh4regs.h"
+#include "sh4comn.h"
+
+static const int tcnt_div[8] = { 4, 16, 64, 256, 1024, 1, 1, 1 };
+static const int rtcnt_div[8] = { 0, 4, 16, 64, 256, 1024, 2048, 4096 };
+static const int daysmonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+static const int dmasize[8] = { 8, 1, 2, 4, 32, 0, 0, 0 };
+static const UINT32 exception_priority_default[] = { EXPPRI(1,1,0,0), EXPPRI(1,2,0,1), EXPPRI(1,1,0,2), EXPPRI(1,3,0,3), EXPPRI(1,4,0,4),
+ EXPPRI(2,0,0,5), EXPPRI(2,1,0,6), EXPPRI(2,2,0,7), EXPPRI(2,3,0,8), EXPPRI(2,4,0,9), EXPPRI(2,4,0,10), EXPPRI(2,4,0,11), EXPPRI(2,4,0,12),
+ EXPPRI(2,5,0,13), EXPPRI(2,5,0,14), EXPPRI(2,6,0,15), EXPPRI(2,6,0,16), EXPPRI(2,7,0,17), EXPPRI(2,7,0,18), EXPPRI(2,8,0,19),
+ EXPPRI(2,9,0,20), EXPPRI(2,4,0,21), EXPPRI(2,10,0,22), EXPPRI(3,0,16,SH4_INTC_NMI) };
+static const int exception_codes[] = { 0x000, 0x020, 0x000, 0x140, 0x140, 0x1E0, 0x0E0, 0x040, 0x0A0, 0x180, 0x1A0, 0x800, 0x820, 0x0E0,
+ 0x100, 0x040, 0x060, 0x0A0, 0x0C0, 0x120, 0x080, 0x160, 0x1E0, 0x1C0, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0, 0x300,
+ 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x240, 0x2A0, 0x300, 0x360, 0x600, 0x620, 0x640, 0x660, 0x680, 0x6A0, 0x780, 0x7A0, 0x7C0,
+ 0x7E0, 0x6C0, 0xB00, 0xB80, 0x400, 0x420, 0x440, 0x460, 0x480, 0x4A0, 0x4C0, 0x4E0, 0x500, 0x520, 0x540, 0x700, 0x720, 0x740, 0x760,
+ 0x560, 0x580, 0x5A0 };
+
+static const UINT16 tcnt[] = { TCNT0, TCNT1, TCNT2 };
+static const UINT16 tcor[] = { TCOR0, TCOR1, TCOR2 };
+static const UINT16 tcr[] = { TCR0, TCR1, TCR2 };
+
+void sh4_change_register_bank(sh4_state *sh4, int to)
+{
+int s;
+
+ if (to) // 0 -> 1
+ {
+ for (s = 0;s < 8;s++)
+ {
+ sh4->rbnk[0][s] = sh4->r[s];
+ sh4->r[s] = sh4->rbnk[1][s];
+ }
+ }
+ else // 1 -> 0
+ {
+ for (s = 0;s < 8;s++)
+ {
+ sh4->rbnk[1][s] = sh4->r[s];
+ sh4->r[s] = sh4->rbnk[0][s];
+ }
+ }
+}
+
+void sh4_swap_fp_registers(sh4_state *sh4)
+{
+int s;
+UINT32 z;
+
+ for (s = 0;s <= 15;s++)
+ {
+ z = sh4->fr[s];
+ sh4->fr[s] = sh4->xf[s];
+ sh4->xf[s] = z;
+ }
+}
+
+#ifdef LSB_FIRST
+void sh4_swap_fp_couples(sh4_state *sh4)
+{
+int s;
+UINT32 z;
+
+ for (s = 0;s <= 15;s = s+2)
+ {
+ z = sh4->fr[s];
+ sh4->fr[s] = sh4->fr[s + 1];
+ sh4->fr[s + 1] = z;
+ z = sh4->xf[s];
+ sh4->xf[s] = sh4->xf[s + 1];
+ sh4->xf[s + 1] = z;
+ }
+}
+#endif
+
+void sh4_syncronize_register_bank(sh4_state *sh4, int to)
+{
+int s;
+
+ for (s = 0;s < 8;s++)
+ {
+ sh4->rbnk[to][s] = sh4->r[s];
+ }
+}
+
+void sh4_default_exception_priorities(sh4_state *sh4) // setup default priorities for exceptions
+{
+int a;
+
+ for (a=0;a <= SH4_INTC_NMI;a++)
+ sh4->exception_priority[a] = exception_priority_default[a];
+ for (a=SH4_INTC_IRLn0;a <= SH4_INTC_IRLnE;a++)
+ sh4->exception_priority[a] = INTPRI(15-(a-SH4_INTC_IRLn0), a);
+ sh4->exception_priority[SH4_INTC_IRL0] = INTPRI(13, SH4_INTC_IRL0);
+ sh4->exception_priority[SH4_INTC_IRL1] = INTPRI(10, SH4_INTC_IRL1);
+ sh4->exception_priority[SH4_INTC_IRL2] = INTPRI(7, SH4_INTC_IRL2);
+ sh4->exception_priority[SH4_INTC_IRL3] = INTPRI(4, SH4_INTC_IRL3);
+ for (a=SH4_INTC_HUDI;a <= SH4_INTC_ROVI;a++)
+ sh4->exception_priority[a] = INTPRI(0, a);
+}
+
+void sh4_exception_recompute(sh4_state *sh4) // checks if there is any interrupt with high enough priority
+{
+ int a,z;
+
+ sh4->test_irq = 0;
+ if ((!sh4->pending_irq) || ((sh4->sr & BL) && (sh4->exception_requesting[SH4_INTC_NMI] == 0)))
+ return;
+ z = (sh4->sr >> 4) & 15;
+ for (a=0;a <= SH4_INTC_ROVI;a++)
+ {
+ if (sh4->exception_requesting[a])
+ if ((((int)sh4->exception_priority[a] >> 8) & 255) > z)
+ {
+ sh4->test_irq = 1; // will check for exception at end of instructions
+ break;
+ }
+ }
+}
+
+void sh4_exception_request(sh4_state *sh4, int exception) // start requesting an exception
+{
+ if (!sh4->exception_requesting[exception])
+ {
+ sh4->exception_requesting[exception] = 1;
+ sh4->pending_irq++;
+ sh4_exception_recompute(sh4);
+ }
+}
+
+void sh4_exception_unrequest(sh4_state *sh4, int exception) // stop requesting an exception
+{
+ if (sh4->exception_requesting[exception])
+ {
+ sh4->exception_requesting[exception] = 0;
+ sh4->pending_irq--;
+ sh4_exception_recompute(sh4);
+ }
+}
+
+void sh4_exception_checkunrequest(sh4_state *sh4, int exception)
+{
+ if (exception == SH4_INTC_NMI)
+ sh4_exception_unrequest(sh4, exception);
+ if ((exception == SH4_INTC_DMTE0) || (exception == SH4_INTC_DMTE1) ||
+ (exception == SH4_INTC_DMTE2) || (exception == SH4_INTC_DMTE3))
+ sh4_exception_unrequest(sh4, exception);
+}
+
+void sh4_exception(sh4_state *sh4, const char *message, int exception) // handle exception
+{
+ UINT32 vector;
+
+ if (exception < SH4_INTC_NMI)
+ return; // Not yet supported
+ if (exception == SH4_INTC_NMI) {
+ if ((sh4->sr & BL) && (!(sh4->m[ICR] & 0x200)))
+ return;
+ sh4->m[ICR] &= ~0x200;
+ sh4->m[INTEVT] = 0x1c0;
+ vector = 0x600;
+ sh4->irq_callback(sh4->device, INPUT_LINE_NMI);
+ LOG(("SH-4 '%s' nmi exception after [%s]\n", sh4->device->tag(), message));
+ } else {
+// if ((sh4->m[ICR] & 0x4000) && (sh4->nmi_line_state == ASSERT_LINE))
+// return;
+ if (sh4->sr & BL)
+ return;
+ if (((sh4->exception_priority[exception] >> 8) & 255) <= ((sh4->sr >> 4) & 15))
+ return;
+ sh4->m[INTEVT] = exception_codes[exception];
+ vector = 0x600;
+ if ((exception >= SH4_INTC_IRL0) && (exception <= SH4_INTC_IRL3))
+ sh4->irq_callback(sh4->device, SH4_INTC_IRL0-exception+SH4_IRL0);
+ else
+ sh4->irq_callback(sh4->device, SH4_IRL3+1);
+ LOG(("SH-4 '%s' interrupt exception #%d after [%s]\n", sh4->device->tag(), exception, message));
+ }
+ sh4_exception_checkunrequest(sh4, exception);
+
+ sh4->spc = sh4->pc;
+ sh4->ssr = sh4->sr;
+ sh4->sgr = sh4->r[15];
+
+ sh4->sr |= MD;
+ if ((sh4->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ sh4_syncronize_register_bank(sh4, (sh4->sr & sRB) >> 29);
+ if (!(sh4->sr & sRB))
+ sh4_change_register_bank(sh4, 1);
+ sh4->sr |= sRB;
+ sh4->sr |= BL;
+ sh4_exception_recompute(sh4);
+
+ /* fetch PC */
+ sh4->pc = sh4->vbr + vector;
+ /* wake up if a sleep opcode is triggered */
+ if(sh4->sleep_mode == 1) { sh4->sleep_mode = 2; }
+}
+
+static UINT32 compute_ticks_refresh_timer(emu_timer *timer, int hertz, int base, int divisor)
+{
+ // elapsed:total = x : ticks
+ // x=elapsed*tics/total -> x=elapsed*(double)100000000/rtcnt_div[(sh4->m[RTCSR] >> 3) & 7]
+ // ticks/total=ticks / ((rtcnt_div[(sh4->m[RTCSR] >> 3) & 7] * ticks) / 100000000)=1/((rtcnt_div[(sh4->m[RTCSR] >> 3) & 7] / 100000000)=100000000/rtcnt_div[(sh4->m[RTCSR] >> 3) & 7]
+ return base + (UINT32)((timer->elapsed().as_double() * (double)hertz) / (double)divisor);
+}
+
+static void sh4_refresh_timer_recompute(sh4_state *sh4)
+{
+UINT32 ticks;
+
+ //if rtcnt < rtcor then rtcor-rtcnt
+ //if rtcnt >= rtcor then 256-rtcnt+rtcor=256+rtcor-rtcnt
+ ticks = sh4->m[RTCOR]-sh4->m[RTCNT];
+ if (ticks <= 0)
+ ticks = 256 + ticks;
+ sh4->refresh_timer->adjust(attotime::from_hz(sh4->bus_clock) * rtcnt_div[(sh4->m[RTCSR] >> 3) & 7] * ticks);
+ sh4->refresh_timer_base = sh4->m[RTCNT];
+}
+
+/*-------------------------------------------------
+ sh4_scale_up_mame_time - multiply a attotime by
+ a (constant+1) where 0 <= constant < 2^32
+-------------------------------------------------*/
+
+INLINE attotime sh4_scale_up_mame_time(attotime _time1, UINT32 factor1)
+{
+ return _time1 * factor1 + _time1;
+}
+
+static UINT32 compute_ticks_timer(emu_timer *timer, int hertz, int divisor)
+{
+ double ret;
+
+ ret=((timer->remaining().as_double() * (double)hertz) / (double)divisor) - 1;
+ return (UINT32)ret;
+}
+
+static void sh4_timer_recompute(sh4_state *sh4, int which)
+{
+ double ticks;
+
+ ticks = sh4->m[tcnt[which]];
+ sh4->timer[which]->adjust(sh4_scale_up_mame_time(attotime::from_hz(sh4->pm_clock) * tcnt_div[sh4->m[tcr[which]] & 7], ticks), which);
+}
+
+static TIMER_CALLBACK( sh4_refresh_timer_callback )
+{
+ sh4_state *sh4 = (sh4_state *)ptr;
+
+ sh4->m[RTCNT] = 0;
+ sh4_refresh_timer_recompute(sh4);
+ sh4->m[RTCSR] |= 128;
+ if ((sh4->m[MCR] & 4) && !(sh4->m[MCR] & 2))
+ {
+ sh4->m[RFCR] = (sh4->m[RFCR] + 1) & 1023;
+ if (((sh4->m[RTCSR] & 1) && (sh4->m[RFCR] == 512)) || (sh4->m[RFCR] == 0))
+ {
+ sh4->m[RFCR] = 0;
+ sh4->m[RTCSR] |= 4;
+ }
+ }
+}
+
+static void increment_rtc_time(sh4_state *sh4, int mode)
+{
+ int carry, year, leap, days;
+
+ if (mode == 0)
+ {
+ carry = 0;
+ sh4->m[RSECCNT] = sh4->m[RSECCNT] + 1;
+ if ((sh4->m[RSECCNT] & 0xf) == 0xa)
+ sh4->m[RSECCNT] = sh4->m[RSECCNT] + 6;
+ if (sh4->m[RSECCNT] == 0x60)
+ {
+ sh4->m[RSECCNT] = 0;
+ carry=1;
+ }
+ else
+ return;
+ }
+ else
+ carry = 1;
+
+ sh4->m[RMINCNT] = sh4->m[RMINCNT] + carry;
+ if ((sh4->m[RMINCNT] & 0xf) == 0xa)
+ sh4->m[RMINCNT] = sh4->m[RMINCNT] + 6;
+ carry=0;
+ if (sh4->m[RMINCNT] == 0x60)
+ {
+ sh4->m[RMINCNT] = 0;
+ carry = 1;
+ }
+
+ sh4->m[RHRCNT] = sh4->m[RHRCNT] + carry;
+ if ((sh4->m[RHRCNT] & 0xf) == 0xa)
+ sh4->m[RHRCNT] = sh4->m[RHRCNT] + 6;
+ carry = 0;
+ if (sh4->m[RHRCNT] == 0x24)
+ {
+ sh4->m[RHRCNT] = 0;
+ carry = 1;
+ }
+
+ sh4->m[RWKCNT] = sh4->m[RWKCNT] + carry;
+ if (sh4->m[RWKCNT] == 0x7)
+ {
+ sh4->m[RWKCNT] = 0;
+ }
+
+ days = 0;
+ year = (sh4->m[RYRCNT] & 0xf) + ((sh4->m[RYRCNT] & 0xf0) >> 4)*10 + ((sh4->m[RYRCNT] & 0xf00) >> 8)*100 + ((sh4->m[RYRCNT] & 0xf000) >> 12)*1000;
+ leap = 0;
+ if (!(year%100))
+ {
+ if (!(year%400))
+ leap = 1;
+ }
+ else if (!(year%4))
+ leap = 1;
+ if (sh4->m[RMONCNT] != 2)
+ leap = 0;
+ if (sh4->m[RMONCNT])
+ days = daysmonth[(sh4->m[RMONCNT] & 0xf) + ((sh4->m[RMONCNT] & 0xf0) >> 4)*10 - 1];
+
+ sh4->m[RDAYCNT] = sh4->m[RDAYCNT] + carry;
+ if ((sh4->m[RDAYCNT] & 0xf) == 0xa)
+ sh4->m[RDAYCNT] = sh4->m[RDAYCNT] + 6;
+ carry = 0;
+ if (sh4->m[RDAYCNT] > (days+leap))
+ {
+ sh4->m[RDAYCNT] = 1;
+ carry = 1;
+ }
+
+ sh4->m[RMONCNT] = sh4->m[RMONCNT] + carry;
+ if ((sh4->m[RMONCNT] & 0xf) == 0xa)
+ sh4->m[RMONCNT] = sh4->m[RMONCNT] + 6;
+ carry=0;
+ if (sh4->m[RMONCNT] == 0x13)
+ {
+ sh4->m[RMONCNT] = 1;
+ carry = 1;
+ }
+
+ sh4->m[RYRCNT] = sh4->m[RYRCNT] + carry;
+ if ((sh4->m[RYRCNT] & 0xf) >= 0xa)
+ sh4->m[RYRCNT] = sh4->m[RYRCNT] + 6;
+ if ((sh4->m[RYRCNT] & 0xf0) >= 0xa0)
+ sh4->m[RYRCNT] = sh4->m[RYRCNT] + 0x60;
+ if ((sh4->m[RYRCNT] & 0xf00) >= 0xa00)
+ sh4->m[RYRCNT] = sh4->m[RYRCNT] + 0x600;
+ if ((sh4->m[RYRCNT] & 0xf000) >= 0xa000)
+ sh4->m[RYRCNT] = 0;
+}
+
+static TIMER_CALLBACK( sh4_rtc_timer_callback )
+{
+ sh4_state *sh4 = (sh4_state *)ptr;
+
+ sh4->rtc_timer->adjust(attotime::from_hz(128));
+ sh4->m[R64CNT] = (sh4->m[R64CNT]+1) & 0x7f;
+ if (sh4->m[R64CNT] == 64)
+ {
+ sh4->m[RCR1] |= 0x80;
+ increment_rtc_time(sh4, 0);
+ //sh4_exception_request(sh4, SH4_INTC_NMI); // TEST
+ }
+}
+
+static TIMER_CALLBACK( sh4_timer_callback )
+{
+ static const UINT16 tuni[] = { SH4_INTC_TUNI0, SH4_INTC_TUNI1, SH4_INTC_TUNI2 };
+ sh4_state *sh4 = (sh4_state *)ptr;
+ int which = param;
+ int idx = tcr[which];
+
+ sh4->m[tcnt[which]] = sh4->m[tcor[which]];
+ sh4_timer_recompute(sh4, which);
+ sh4->m[idx] = sh4->m[idx] | 0x100;
+ if (sh4->m[idx] & 0x20)
+ sh4_exception_request(sh4, tuni[which]);
+}
+
+static TIMER_CALLBACK( sh4_dmac_callback )
+{
+ sh4_state *sh4 = (sh4_state *)ptr;
+ int channel = param;
+
+ LOG(("SH4 '%s': DMA %d complete\n", sh4->device->tag(), channel));
+ sh4->dma_timer_active[channel] = 0;
+ switch (channel)
+ {
+ case 0:
+ sh4->m[DMATCR0] = 0;
+ sh4->m[CHCR0] |= CHCR_TE;
+ if (sh4->m[CHCR0] & CHCR_IE)
+ sh4_exception_request(sh4, SH4_INTC_DMTE0);
+ break;
+ case 1:
+ sh4->m[DMATCR1] = 0;
+ sh4->m[CHCR1] |= CHCR_TE;
+ if (sh4->m[CHCR1] & CHCR_IE)
+ sh4_exception_request(sh4, SH4_INTC_DMTE1);
+ break;
+ case 2:
+ sh4->m[DMATCR2] = 0;
+ sh4->m[CHCR2] |= CHCR_TE;
+ if (sh4->m[CHCR2] & CHCR_IE)
+ sh4_exception_request(sh4, SH4_INTC_DMTE2);
+ break;
+ case 3:
+ sh4->m[DMATCR3] = 0;
+ sh4->m[CHCR3] |= CHCR_TE;
+ if (sh4->m[CHCR3] & CHCR_IE)
+ sh4_exception_request(sh4, SH4_INTC_DMTE3);
+ break;
+ }
+}
+
+static int sh4_dma_transfer(sh4_state *sh4, int channel, int timermode, UINT32 chcr, UINT32 *sar, UINT32 *dar, UINT32 *dmatcr)
+{
+ int incs, incd, size;
+ UINT32 src, dst, count;
+
+ incd = (chcr & CHCR_DM) >> 14;
+ incs = (chcr & CHCR_SM) >> 12;
+ size = dmasize[(chcr & CHCR_TS) >> 4];
+ if(incd == 3 || incs == 3)
+ {
+ logerror("SH4: DMA: bad increment values (%d, %d, %d, %04x)\n", incd, incs, size, chcr);
+ return 0;
+ }
+ src = *sar;
+ dst = *dar;
+ count = *dmatcr;
+ if (!count)
+ count = 0x1000000;
+
+ LOG(("SH4: DMA %d start %x, %x, %x, %04x, %d, %d, %d\n", channel, src, dst, count, chcr, incs, incd, size));
+
+ if (timermode == 1) // timer actvated after a time based on the number of words to transfer
+ {
+ sh4->dma_timer_active[channel] = 1;
+ sh4->dma_timer[channel]->adjust(sh4->device->cycles_to_attotime(2*count+1), channel);
+ }
+ else if (timermode == 2) // timer activated immediately
+ {
+ sh4->dma_timer_active[channel] = 1;
+ sh4->dma_timer[channel]->adjust(attotime::zero, channel);
+ }
+
+ src &= AM;
+ dst &= AM;
+
+ switch(size)
+ {
+ case 1: // 8 bit
+ for(;count > 0; count --)
+ {
+ if(incs == 2)
+ src --;
+ if(incd == 2)
+ dst --;
+ sh4->program->write_byte(dst, sh4->program->read_byte(src));
+ if(incs == 1)
+ src ++;
+ if(incd == 1)
+ dst ++;
+ }
+ break;
+ case 2: // 16 bit
+ src &= ~1;
+ dst &= ~1;
+ for(;count > 0; count --)
+ {
+ if(incs == 2)
+ src -= 2;
+ if(incd == 2)
+ dst -= 2;
+ sh4->program->write_word(dst, sh4->program->read_word(src));
+ if(incs == 1)
+ src += 2;
+ if(incd == 1)
+ dst += 2;
+ }
+ break;
+ case 8: // 64 bit
+ src &= ~7;
+ dst &= ~7;
+ for(;count > 0; count --)
+ {
+ if(incs == 2)
+ src -= 8;
+ if(incd == 2)
+ dst -= 8;
+ sh4->program->write_qword(dst, sh4->program->read_qword(src));
+ if(incs == 1)
+ src += 8;
+ if(incd == 1)
+ dst += 8;
+
+ }
+ break;
+ case 4: // 32 bit
+ src &= ~3;
+ dst &= ~3;
+ for(;count > 0; count --)
+ {
+ if(incs == 2)
+ src -= 4;
+ if(incd == 2)
+ dst -= 4;
+ sh4->program->write_dword(dst, sh4->program->read_dword(src));
+ if(incs == 1)
+ src += 4;
+ if(incd == 1)
+ dst += 4;
+
+ }
+ break;
+ case 32:
+ src &= ~31;
+ dst &= ~31;
+ for(;count > 0; count --)
+ {
+ if(incs == 2)
+ src -= 32;
+ if(incd == 2)
+ dst -= 32;
+ sh4->program->write_qword(dst, sh4->program->read_qword(src));
+ sh4->program->write_qword(dst+8, sh4->program->read_qword(src+8));
+ sh4->program->write_qword(dst+16, sh4->program->read_qword(src+16));
+ sh4->program->write_qword(dst+24, sh4->program->read_qword(src+24));
+ if(incs == 1)
+ src += 32;
+ if(incd == 1)
+ dst += 32;
+ }
+ break;
+ }
+ *sar = (*sar & !AM) | src;
+ *dar = (*dar & !AM) | dst;
+ *dmatcr = count;
+ return 1;
+}
+
+static int sh4_dma_transfer_device(sh4_state *sh4, int channel, UINT32 chcr, UINT32 *sar, UINT32 *dar, UINT32 *dmatcr)
+{
+ int incs, incd, size, mod;
+ UINT32 src, dst, count;
+
+ incd = (chcr & CHCR_DM) >> 14;
+ incs = (chcr & CHCR_SM) >> 12;
+ size = dmasize[(chcr & CHCR_TS) >> 4];
+ mod = ((chcr & CHCR_RS) >> 8);
+ if (incd == 3 || incs == 3)
+ {
+ logerror("SH4: DMA: bad increment values (%d, %d, %d, %04x)\n", incd, incs, size, chcr);
+ return 0;
+ }
+ src = *sar;
+ dst = *dar;
+ count = *dmatcr;
+ if (!count)
+ count = 0x1000000;
+
+ LOG(("SH4: DMA %d start device<->memory %x, %x, %x, %04x, %d, %d, %d\n", channel, src, dst, count, chcr, incs, incd, size));
+
+ sh4->dma_timer_active[channel] = 1;
+
+ src &= AM;
+ dst &= AM;
+
+ // remember parameters
+ sh4->dma_source[channel]=src;
+ sh4->dma_destination[channel]=dst;
+ sh4->dma_count[channel]=count;
+ sh4->dma_wordsize[channel]=size;
+ sh4->dma_source_increment[channel]=incs;
+ sh4->dma_destination_increment[channel]=incd;
+ sh4->dma_mode[channel]=mod;
+
+ // inform device its ready to transfer
+ sh4->io->write_dword(SH4_IOPORT_DMA, channel | (mod << 16));
+ return 1;
+}
+
+static void sh4_dmac_check(sh4_state *sh4, int channel)
+{
+UINT32 dmatcr, chcr, sar, dar;
+
+ switch (channel)
+ {
+ case 0:
+ sar = sh4->m[SAR0];
+ dar = sh4->m[DAR0];
+ chcr = sh4->m[CHCR0];
+ dmatcr = sh4->m[DMATCR0];
+ break;
+ case 1:
+ sar = sh4->m[SAR1];
+ dar = sh4->m[DAR1];
+ chcr = sh4->m[CHCR1];
+ dmatcr = sh4->m[DMATCR1];
+ break;
+ case 2:
+ sar = sh4->m[SAR2];
+ dar = sh4->m[DAR2];
+ chcr = sh4->m[CHCR2];
+ dmatcr = sh4->m[DMATCR2];
+ break;
+ case 3:
+ sar = sh4->m[SAR3];
+ dar = sh4->m[DAR3];
+ chcr = sh4->m[CHCR3];
+ dmatcr = sh4->m[DMATCR3];
+ break;
+ default:
+ return;
+ }
+ if (chcr & sh4->m[DMAOR] & DMAOR_DME)
+ {
+ if ((((chcr & CHCR_RS) >> 8) < 2) || (((chcr & CHCR_RS) >> 8) > 6))
+ return;
+ if (!sh4->dma_timer_active[channel] && !(chcr & CHCR_TE) && !(sh4->m[DMAOR] & (DMAOR_AE | DMAOR_NMIF)))
+ {
+ if (((chcr & CHCR_RS) >> 8) > 3)
+ sh4_dma_transfer(sh4, channel, 1, chcr, &sar, &dar, &dmatcr);
+ else if ((sh4->m[DMAOR] & DMAOR_DDT) == 0)
+ sh4_dma_transfer_device(sh4, channel, chcr, &sar, &dar, &dmatcr); // tell device we are ready to transfer
+ }
+ }
+ else
+ {
+ if (sh4->dma_timer_active[channel])
+ {
+ logerror("SH4: DMA %d cancelled in-flight but all data transferred", channel);
+ sh4->dma_timer[channel]->adjust(attotime::never, channel);
+ sh4->dma_timer_active[channel] = 0;
+ }
+ }
+}
+
+static void sh4_dmac_nmi(sh4_state *sh4) // manage dma when nmi gets asserted
+{
+int s;
+
+ sh4->m[DMAOR] |= DMAOR_NMIF;
+ for (s = 0;s < 4;s++)
+ {
+ if (sh4->dma_timer_active[s])
+ {
+ logerror("SH4: DMA %d cancelled due to NMI but all data transferred", s);
+ sh4->dma_timer[s]->adjust(attotime::never, s);
+ sh4->dma_timer_active[s] = 0;
+ }
+ }
+}
+
+WRITE32_HANDLER( sh4_internal_w )
+{
+ sh4_state *sh4 = get_safe_token(&space->device());
+ int a;
+ UINT32 addr = (offset << 2) + 0xfe000000;
+ offset = ((addr & 0xfc) >> 2) | ((addr & 0x1fe0000) >> 11);
+
+ UINT32 old = sh4->m[offset];
+ COMBINE_DATA(sh4->m+offset);
+
+// printf("sh4_internal_w: Write %08x (%x), %08x @ %08x\n", 0xfe000000+((offset & 0x3fc0) << 11)+((offset & 0x3f) << 2), offset, data, mem_mask);
+
+ switch( offset )
+ {
+ case MMUCR: // MMU Control
+ if (data & MMUCR_AT)
+ {
+ printf("SH4 MMU Enabled\n");
+ printf("If you're seeing this, but running something other than a Naomi GD-ROM game then chances are it won't work\n");
+ printf("The MMU emulation is a hack specific to that system\n");
+ sh4->sh4_mmu_enabled = 1;
+
+ // should be a different bit!
+ {
+ int i;
+ for (i=0;i<64;i++)
+ {
+ sh4->sh4_tlb_address[i] = 0;
+ sh4->sh4_tlb_data[i] = 0;
+ }
+
+ }
+ }
+ else
+ {
+ sh4->sh4_mmu_enabled = 0;
+ }
+
+ break;
+
+ // Memory refresh
+ case RTCSR:
+ sh4->m[RTCSR] &= 255;
+ if ((old >> 3) & 7)
+ sh4->m[RTCNT] = compute_ticks_refresh_timer(sh4->refresh_timer, sh4->bus_clock, sh4->refresh_timer_base, rtcnt_div[(old >> 3) & 7]) & 0xff;
+ if ((sh4->m[RTCSR] >> 3) & 7)
+ { // activated
+ sh4_refresh_timer_recompute(sh4);
+ }
+ else
+ {
+ sh4->refresh_timer->adjust(attotime::never);
+ }
+ break;
+
+ case RTCNT:
+ sh4->m[RTCNT] &= 255;
+ if ((sh4->m[RTCSR] >> 3) & 7)
+ { // active
+ sh4_refresh_timer_recompute(sh4);
+ }
+ break;
+
+ case RTCOR:
+ sh4->m[RTCOR] &= 255;
+ if ((sh4->m[RTCSR] >> 3) & 7)
+ { // active
+ sh4->m[RTCNT] = compute_ticks_refresh_timer(sh4->refresh_timer, sh4->bus_clock, sh4->refresh_timer_base, rtcnt_div[(sh4->m[RTCSR] >> 3) & 7]) & 0xff;
+ sh4_refresh_timer_recompute(sh4);
+ }
+ break;
+
+ case RFCR:
+ sh4->m[RFCR] &= 1023;
+ break;
+
+ // RTC
+ case RCR1:
+ if ((sh4->m[RCR1] & 8) && (~old & 8)) // 0 -> 1
+ sh4->m[RCR1] ^= 1;
+ break;
+
+ case RCR2:
+ if (sh4->m[RCR2] & 2)
+ {
+ sh4->m[R64CNT] = 0;
+ sh4->m[RCR2] ^= 2;
+ }
+ if (sh4->m[RCR2] & 4)
+ {
+ sh4->m[R64CNT] = 0;
+ if (sh4->m[RSECCNT] >= 30)
+ increment_rtc_time(sh4, 1);
+ sh4->m[RSECCNT] = 0;
+ }
+ if ((sh4->m[RCR2] & 8) && (~old & 8))
+ { // 0 -> 1
+ sh4->rtc_timer->adjust(attotime::from_hz(128));
+ }
+ else if (~(sh4->m[RCR2]) & 8)
+ { // 0
+ sh4->rtc_timer->adjust(attotime::never);
+ }
+ break;
+
+ // TMU
+ case TSTR:
+ if (old & 1)
+ sh4->m[TCNT0] = compute_ticks_timer(sh4->timer[0], sh4->pm_clock, tcnt_div[sh4->m[TCR0] & 7]);
+ if ((sh4->m[TSTR] & 1) == 0) {
+ sh4->timer[0]->adjust(attotime::never);
+ } else
+ sh4_timer_recompute(sh4, 0);
+
+ if (old & 2)
+ sh4->m[TCNT1] = compute_ticks_timer(sh4->timer[1], sh4->pm_clock, tcnt_div[sh4->m[TCR1] & 7]);
+ if ((sh4->m[TSTR] & 2) == 0) {
+ sh4->timer[1]->adjust(attotime::never);
+ } else
+ sh4_timer_recompute(sh4, 1);
+
+ if (old & 4)
+ sh4->m[TCNT2] = compute_ticks_timer(sh4->timer[2], sh4->pm_clock, tcnt_div[sh4->m[TCR2] & 7]);
+ if ((sh4->m[TSTR] & 4) == 0) {
+ sh4->timer[2]->adjust(attotime::never);
+ } else
+ sh4_timer_recompute(sh4, 2);
+ break;
+
+ case TCR0:
+ if (sh4->m[TSTR] & 1)
+ {
+ sh4->m[TCNT0] = compute_ticks_timer(sh4->timer[0], sh4->pm_clock, tcnt_div[old & 7]);
+ sh4_timer_recompute(sh4, 0);
+ }
+ if (!(sh4->m[TCR0] & 0x20) || !(sh4->m[TCR0] & 0x100))
+ sh4_exception_unrequest(sh4, SH4_INTC_TUNI0);
+ break;
+ case TCR1:
+ if (sh4->m[TSTR] & 2)
+ {
+ sh4->m[TCNT1] = compute_ticks_timer(sh4->timer[1], sh4->pm_clock, tcnt_div[old & 7]);
+ sh4_timer_recompute(sh4, 1);
+ }
+ if (!(sh4->m[TCR1] & 0x20) || !(sh4->m[TCR1] & 0x100))
+ sh4_exception_unrequest(sh4, SH4_INTC_TUNI1);
+ break;
+ case TCR2:
+ if (sh4->m[TSTR] & 4)
+ {
+ sh4->m[TCNT2] = compute_ticks_timer(sh4->timer[2], sh4->pm_clock, tcnt_div[old & 7]);
+ sh4_timer_recompute(sh4, 2);
+ }
+ if (!(sh4->m[TCR2] & 0x20) || !(sh4->m[TCR2] & 0x100))
+ sh4_exception_unrequest(sh4, SH4_INTC_TUNI2);
+ break;
+
+ case TCOR0:
+ if (sh4->m[TSTR] & 1)
+ {
+ sh4->m[TCNT0] = compute_ticks_timer(sh4->timer[0], sh4->pm_clock, tcnt_div[sh4->m[TCR0] & 7]);
+ sh4_timer_recompute(sh4, 0);
+ }
+ break;
+ case TCNT0:
+ if (sh4->m[TSTR] & 1)
+ sh4_timer_recompute(sh4, 0);
+ break;
+ case TCOR1:
+ if (sh4->m[TSTR] & 2)
+ {
+ sh4->m[TCNT1] = compute_ticks_timer(sh4->timer[1], sh4->pm_clock, tcnt_div[sh4->m[TCR1] & 7]);
+ sh4_timer_recompute(sh4, 1);
+ }
+ break;
+ case TCNT1:
+ if (sh4->m[TSTR] & 2)
+ sh4_timer_recompute(sh4, 1);
+ break;
+ case TCOR2:
+ if (sh4->m[TSTR] & 4)
+ {
+ sh4->m[TCNT2] = compute_ticks_timer(sh4->timer[2], sh4->pm_clock, tcnt_div[sh4->m[TCR2] & 7]);
+ sh4_timer_recompute(sh4, 2);
+ }
+ break;
+ case TCNT2:
+ if (sh4->m[TSTR] & 4)
+ sh4_timer_recompute(sh4, 2);
+ break;
+
+ // INTC
+ case ICR:
+ sh4->m[ICR] = (sh4->m[ICR] & 0x7fff) | (old & 0x8000);
+ break;
+ case IPRA:
+ sh4->exception_priority[SH4_INTC_ATI] = INTPRI(sh4->m[IPRA] & 0x000f, SH4_INTC_ATI);
+ sh4->exception_priority[SH4_INTC_PRI] = INTPRI(sh4->m[IPRA] & 0x000f, SH4_INTC_PRI);
+ sh4->exception_priority[SH4_INTC_CUI] = INTPRI(sh4->m[IPRA] & 0x000f, SH4_INTC_CUI);
+ sh4->exception_priority[SH4_INTC_TUNI2] = INTPRI((sh4->m[IPRA] & 0x00f0) >> 4, SH4_INTC_TUNI2);
+ sh4->exception_priority[SH4_INTC_TICPI2] = INTPRI((sh4->m[IPRA] & 0x00f0) >> 4, SH4_INTC_TICPI2);
+ sh4->exception_priority[SH4_INTC_TUNI1] = INTPRI((sh4->m[IPRA] & 0x0f00) >> 8, SH4_INTC_TUNI1);
+ sh4->exception_priority[SH4_INTC_TUNI0] = INTPRI((sh4->m[IPRA] & 0xf000) >> 12, SH4_INTC_TUNI0);
+ sh4_exception_recompute(sh4);
+ break;
+ case IPRB:
+ sh4->exception_priority[SH4_INTC_SCI1ERI] = INTPRI((sh4->m[IPRB] & 0x00f0) >> 4, SH4_INTC_SCI1ERI);
+ sh4->exception_priority[SH4_INTC_SCI1RXI] = INTPRI((sh4->m[IPRB] & 0x00f0) >> 4, SH4_INTC_SCI1RXI);
+ sh4->exception_priority[SH4_INTC_SCI1TXI] = INTPRI((sh4->m[IPRB] & 0x00f0) >> 4, SH4_INTC_SCI1TXI);
+ sh4->exception_priority[SH4_INTC_SCI1TEI] = INTPRI((sh4->m[IPRB] & 0x00f0) >> 4, SH4_INTC_SCI1TEI);
+ sh4->exception_priority[SH4_INTC_RCMI] = INTPRI((sh4->m[IPRB] & 0x0f00) >> 8, SH4_INTC_RCMI);
+ sh4->exception_priority[SH4_INTC_ROVI] = INTPRI((sh4->m[IPRB] & 0x0f00) >> 8, SH4_INTC_ROVI);
+ sh4->exception_priority[SH4_INTC_ITI] = INTPRI((sh4->m[IPRB] & 0xf000) >> 12, SH4_INTC_ITI);
+ sh4_exception_recompute(sh4);
+ break;
+ case IPRC:
+ sh4->exception_priority[SH4_INTC_HUDI] = INTPRI(sh4->m[IPRC] & 0x000f, SH4_INTC_HUDI);
+ sh4->exception_priority[SH4_INTC_SCIFERI] = INTPRI((sh4->m[IPRC] & 0x00f0) >> 4, SH4_INTC_SCIFERI);
+ sh4->exception_priority[SH4_INTC_SCIFRXI] = INTPRI((sh4->m[IPRC] & 0x00f0) >> 4, SH4_INTC_SCIFRXI);
+ sh4->exception_priority[SH4_INTC_SCIFBRI] = INTPRI((sh4->m[IPRC] & 0x00f0) >> 4, SH4_INTC_SCIFBRI);
+ sh4->exception_priority[SH4_INTC_SCIFTXI] = INTPRI((sh4->m[IPRC] & 0x00f0) >> 4, SH4_INTC_SCIFTXI);
+ sh4->exception_priority[SH4_INTC_DMTE0] = INTPRI((sh4->m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMTE0);
+ sh4->exception_priority[SH4_INTC_DMTE1] = INTPRI((sh4->m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMTE1);
+ sh4->exception_priority[SH4_INTC_DMTE2] = INTPRI((sh4->m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMTE2);
+ sh4->exception_priority[SH4_INTC_DMTE3] = INTPRI((sh4->m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMTE3);
+ sh4->exception_priority[SH4_INTC_DMAE] = INTPRI((sh4->m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMAE);
+ sh4->exception_priority[SH4_INTC_GPOI] = INTPRI((sh4->m[IPRC] & 0xf000) >> 12, SH4_INTC_GPOI);
+ sh4_exception_recompute(sh4);
+ break;
+
+ // DMA
+ case SAR0:
+ case SAR1:
+ case SAR2:
+ case SAR3:
+ case DAR0:
+ case DAR1:
+ case DAR2:
+ case DAR3:
+ case DMATCR0:
+ case DMATCR1:
+ case DMATCR2:
+ case DMATCR3:
+ break;
+ case CHCR0:
+ sh4_dmac_check(sh4, 0);
+ break;
+ case CHCR1:
+ sh4_dmac_check(sh4, 1);
+ break;
+ case CHCR2:
+ sh4_dmac_check(sh4, 2);
+ break;
+ case CHCR3:
+ sh4_dmac_check(sh4, 3);
+ break;
+ case DMAOR:
+ if ((sh4->m[DMAOR] & DMAOR_AE) && (~old & DMAOR_AE))
+ sh4->m[DMAOR] &= ~DMAOR_AE;
+ if ((sh4->m[DMAOR] & DMAOR_NMIF) && (~old & DMAOR_NMIF))
+ sh4->m[DMAOR] &= ~DMAOR_NMIF;
+ sh4_dmac_check(sh4, 0);
+ sh4_dmac_check(sh4, 1);
+ sh4_dmac_check(sh4, 2);
+ sh4_dmac_check(sh4, 3);
+ break;
+
+ // Store Queues
+ case QACR0:
+ case QACR1:
+ break;
+
+ // I/O ports
+ case PCTRA:
+ sh4->ioport16_pullup = 0;
+ sh4->ioport16_direction = 0;
+ for (a=0;a < 16;a++) {
+ sh4->ioport16_direction |= (sh4->m[PCTRA] & (1 << (a*2))) >> a;
+ sh4->ioport16_pullup |= (sh4->m[PCTRA] & (1 << (a*2+1))) >> (a+1);
+ }
+ sh4->ioport16_direction &= 0xffff;
+ sh4->ioport16_pullup = (sh4->ioport16_pullup | sh4->ioport16_direction) ^ 0xffff;
+ if (sh4->m[BCR2] & 1)
+ sh4->io->write_dword(SH4_IOPORT_16, (UINT64)(sh4->m[PDTRA] & sh4->ioport16_direction) | ((UINT64)sh4->m[PCTRA] << 16));
+ break;
+ case PDTRA:
+ if (sh4->m[BCR2] & 1)
+ sh4->io->write_dword(SH4_IOPORT_16, (UINT64)(sh4->m[PDTRA] & sh4->ioport16_direction) | ((UINT64)sh4->m[PCTRA] << 16));
+ break;
+ case PCTRB:
+ sh4->ioport4_pullup = 0;
+ sh4->ioport4_direction = 0;
+ for (a=0;a < 4;a++) {
+ sh4->ioport4_direction |= (sh4->m[PCTRB] & (1 << (a*2))) >> a;
+ sh4->ioport4_pullup |= (sh4->m[PCTRB] & (1 << (a*2+1))) >> (a+1);
+ }
+ sh4->ioport4_direction &= 0xf;
+ sh4->ioport4_pullup = (sh4->ioport4_pullup | sh4->ioport4_direction) ^ 0xf;
+ if (sh4->m[BCR2] & 1)
+ sh4->io->write_dword(SH4_IOPORT_4, (sh4->m[PDTRB] & sh4->ioport4_direction) | (sh4->m[PCTRB] << 16));
+ break;
+ case PDTRB:
+ if (sh4->m[BCR2] & 1)
+ sh4->io->write_dword(SH4_IOPORT_4, (sh4->m[PDTRB] & sh4->ioport4_direction) | (sh4->m[PCTRB] << 16));
+ break;
+
+ case SCBRR2:
+ break;
+
+ case SCSPTR2: //trips often in aristocrat mk-6
+ break;
+
+ default:
+ logerror("sh4_internal_w: Unmapped write %08x, %08x @ %08x\n", 0xfe000000+((offset & 0x3fc0) << 11)+((offset & 0x3f) << 2), data, mem_mask);
+ break;
+ }
+}
+
+READ32_HANDLER( sh4_internal_r )
+{
+ sh4_state *sh4 = get_safe_token(&space->device());
+
+ UINT32 addr = (offset << 2) + 0xfe000000;
+ offset = ((addr & 0xfc) >> 2) | ((addr & 0x1fe0000) >> 11);
+
+// printf("sh4_internal_r: Read %08x (%x) @ %08x\n", 0xfe000000+((offset & 0x3fc0) << 11)+((offset & 0x3f) << 2), offset, mem_mask);
+
+ switch( offset )
+ {
+ case VERSION:
+ return PVR_SH7091; // 0x040205c1, this is what a real SH7091 in a Dreamcast returns - the later Naomi BIOSes check and care!
+ break;
+ case PRR:
+ return 0;
+ break;
+ case IPRD:
+ return 0x00000000; // SH7750 ignores writes here and always returns zero
+ break;
+ case RTCNT:
+ if ((sh4->m[RTCSR] >> 3) & 7)
+ { // activated
+ //((double)rtcnt_div[(sh4->m[RTCSR] >> 3) & 7] / (double)100000000)
+ //return (refresh_timer_base + (sh4->refresh_timer->elapsed() * (double)100000000) / (double)rtcnt_div[(sh4->m[RTCSR] >> 3) & 7]) & 0xff;
+ return compute_ticks_refresh_timer(sh4->refresh_timer, sh4->bus_clock, sh4->refresh_timer_base, rtcnt_div[(sh4->m[RTCSR] >> 3) & 7]) & 0xff;
+ }
+ else
+ return sh4->m[RTCNT];
+ break;
+
+ case TCNT0:
+ if (sh4->m[TSTR] & 1)
+ return compute_ticks_timer(sh4->timer[0], sh4->pm_clock, tcnt_div[sh4->m[TCR0] & 7]);
+ else
+ return sh4->m[TCNT0];
+ break;
+ case TCNT1:
+ if (sh4->m[TSTR] & 2)
+ return compute_ticks_timer(sh4->timer[1], sh4->pm_clock, tcnt_div[sh4->m[TCR1] & 7]);
+ else
+ return sh4->m[TCNT1];
+ break;
+ case TCNT2:
+ if (sh4->m[TSTR] & 4)
+ return compute_ticks_timer(sh4->timer[2], sh4->pm_clock, tcnt_div[sh4->m[TCR2] & 7]);
+ else
+ return sh4->m[TCNT2];
+ break;
+
+ // I/O ports
+ case PDTRA:
+ if (sh4->m[BCR2] & 1)
+ return (sh4->io->read_dword(SH4_IOPORT_16) & ~sh4->ioport16_direction) | (sh4->m[PDTRA] & sh4->ioport16_direction);
+ break;
+ case PDTRB:
+ if (sh4->m[BCR2] & 1)
+ return (sh4->io->read_dword(SH4_IOPORT_4) & ~sh4->ioport4_direction) | (sh4->m[PDTRB] & sh4->ioport4_direction);
+ break;
+
+ // SCIF (UART with FIFO)
+ case SCFSR2:
+ return 0x60; //read-only status register
+ }
+ return sh4->m[offset];
+}
+
+void sh4_set_frt_input(device_t *device, int state)
+{
+ sh4_state *sh4 = get_safe_token(device);
+
+ if(state == PULSE_LINE)
+ {
+ sh4_set_frt_input(device, ASSERT_LINE);
+ sh4_set_frt_input(device, CLEAR_LINE);
+ return;
+ }
+
+ if(sh4->frt_input == state) {
+ return;
+ }
+
+ sh4->frt_input = state;
+
+ if(sh4->m[5] & 0x8000) {
+ if(state == CLEAR_LINE) {
+ return;
+ }
+ } else {
+ if(state == ASSERT_LINE) {
+ return;
+ }
+ }
+
+#if 0
+ sh4_timer_resync();
+ sh4->icr = sh4->frc;
+ sh4->m[4] |= ICF;
+ logerror("SH4 '%s': ICF activated (%x)\n", sh4->device->tag(), sh4->pc & AM);
+ sh4_recalc_irq();
+#endif
+}
+
+void sh4_set_irln_input(device_t *device, int value)
+{
+ sh4_state *sh4 = get_safe_token(device);
+
+ if (sh4->irln == value)
+ return;
+ sh4->irln = value;
+ device_set_input_line(device, SH4_IRLn, ASSERT_LINE);
+ device_set_input_line(device, SH4_IRLn, CLEAR_LINE);
+}
+
+void sh4_set_irq_line(sh4_state *sh4, int irqline, int state) // set state of external interrupt line
+{
+ int s;
+
+ if (irqline == INPUT_LINE_NMI)
+ {
+ if (sh4->nmi_line_state == state)
+ return;
+ if (sh4->m[ICR] & 0x100)
+ {
+ if ((state == CLEAR_LINE) && (sh4->nmi_line_state == ASSERT_LINE)) // rising
+ {
+ LOG(("SH-4 '%s' assert nmi\n", sh4->device->tag()));
+ sh4_exception_request(sh4, SH4_INTC_NMI);
+ sh4_dmac_nmi(sh4);
+ }
+ }
+ else
+ {
+ if ((state == ASSERT_LINE) && (sh4->nmi_line_state == CLEAR_LINE)) // falling
+ {
+ LOG(("SH-4 '%s' assert nmi\n", sh4->device->tag()));
+ sh4_exception_request(sh4, SH4_INTC_NMI);
+ sh4_dmac_nmi(sh4);
+ }
+ }
+ if (state == CLEAR_LINE)
+ sh4->m[ICR] ^= 0x8000;
+ else
+ sh4->m[ICR] |= 0x8000;
+ sh4->nmi_line_state = state;
+ }
+ else
+ {
+ if (sh4->m[ICR] & 0x80) // four independent external interrupt sources
+ {
+ if (irqline > SH4_IRL3)
+ return;
+ if (sh4->irq_line_state[irqline] == state)
+ return;
+ sh4->irq_line_state[irqline] = state;
+
+ if( state == CLEAR_LINE )
+ {
+ LOG(("SH-4 '%s' cleared external irq IRL%d\n", sh4->device->tag(), irqline));
+ sh4_exception_unrequest(sh4, SH4_INTC_IRL0+irqline-SH4_IRL0);
+ }
+ else
+ {
+ LOG(("SH-4 '%s' assert external irq IRL%d\n", sh4->device->tag(), irqline));
+ sh4_exception_request(sh4, SH4_INTC_IRL0+irqline-SH4_IRL0);
+ }
+ }
+ else // level-encoded interrupt
+ {
+ if (irqline != SH4_IRLn)
+ return;
+ if ((sh4->irln > 15) || (sh4->irln < 0))
+ return;
+ for (s = 0; s < 15; s++)
+ sh4_exception_unrequest(sh4, SH4_INTC_IRLn0+s);
+ if (sh4->irln < 15)
+ sh4_exception_request(sh4, SH4_INTC_IRLn0+sh4->irln);
+ LOG(("SH-4 '%s' IRLn0-IRLn3 level #%d\n", sh4->device->tag(), sh4->irln));
+ }
+ }
+ if (sh4->test_irq && (!sh4->delay))
+ sh4_check_pending_irq(sh4, "sh4_set_irq_line");
+}
+
+void sh4_parse_configuration(sh4_state *sh4, const struct sh4_config *conf)
+{
+ if(conf)
+ {
+ switch((conf->md2 << 2) | (conf->md1 << 1) | (conf->md0))
+ {
+ case 0:
+ sh4->cpu_clock = conf->clock;
+ sh4->bus_clock = conf->clock / 4;
+ sh4->pm_clock = conf->clock / 4;
+ break;
+ case 1:
+ sh4->cpu_clock = conf->clock;
+ sh4->bus_clock = conf->clock / 6;
+ sh4->pm_clock = conf->clock / 6;
+ break;
+ case 2:
+ sh4->cpu_clock = conf->clock;
+ sh4->bus_clock = conf->clock / 3;
+ sh4->pm_clock = conf->clock / 6;
+ break;
+ case 3:
+ sh4->cpu_clock = conf->clock;
+ sh4->bus_clock = conf->clock / 3;
+ sh4->pm_clock = conf->clock / 6;
+ break;
+ case 4:
+ sh4->cpu_clock = conf->clock;
+ sh4->bus_clock = conf->clock / 2;
+ sh4->pm_clock = conf->clock / 4;
+ break;
+ case 5:
+ sh4->cpu_clock = conf->clock;
+ sh4->bus_clock = conf->clock / 2;
+ sh4->pm_clock = conf->clock / 4;
+ break;
+ }
+ sh4->is_slave = (~(conf->md7)) & 1;
+ }
+ else
+ {
+ sh4->cpu_clock = 200000000;
+ sh4->bus_clock = 100000000;
+ sh4->pm_clock = 50000000;
+ sh4->is_slave = 0;
+ }
+}
+
+void sh4_common_init(device_t *device)
+{
+ sh4_state *sh4 = get_safe_token(device);
+ int i;
+
+ for (i=0; i<3; i++)
+ {
+ sh4->timer[i] = device->machine().scheduler().timer_alloc(FUNC(sh4_timer_callback), sh4);
+ sh4->timer[i]->adjust(attotime::never, i);
+ }
+
+ for (i=0; i<4; i++)
+ {
+ sh4->dma_timer[i] = device->machine().scheduler().timer_alloc(FUNC(sh4_dmac_callback), sh4);
+ sh4->dma_timer[i]->adjust(attotime::never, i);
+ }
+
+ sh4->refresh_timer = device->machine().scheduler().timer_alloc(FUNC(sh4_refresh_timer_callback), sh4);
+ sh4->refresh_timer->adjust(attotime::never);
+ sh4->refresh_timer_base = 0;
+
+ sh4->rtc_timer = device->machine().scheduler().timer_alloc(FUNC(sh4_rtc_timer_callback), sh4);
+ sh4->rtc_timer->adjust(attotime::never);
+
+ sh4->m = auto_alloc_array(device->machine(), UINT32, 16384);
+}
+
+// called by drivers to transfer data in a cpu<->device dma. 'device' must be a SH4 cpu
+int sh4_dma_data(device_t *device, struct sh4_device_dma *s)
+{
+ UINT32 pos, len, siz;
+ int channel = s->channel;
+ void *data = s->buffer;
+
+ sh4_state *sh4 = get_safe_token(device);
+
+ if (!sh4->dma_timer_active[channel])
+ return 0;
+
+ if (sh4->dma_mode[channel] == 2)
+ {
+ // device receives data
+ len = sh4->dma_count[channel];
+ if (s->length < len)
+ len = s->length;
+ siz = sh4->dma_wordsize[channel];
+ for (pos = 0;pos < len;pos++) {
+ switch (siz)
+ {
+ case 8:
+ if (sh4->dma_source_increment[channel] == 2)
+ sh4->dma_source[channel] -= 8;
+ *(UINT64 *)data = sh4->program->read_qword(sh4->dma_source[channel] & ~7);
+ if (sh4->dma_source_increment[channel] == 1)
+ sh4->dma_source[channel] += 8;
+ break;
+ case 1:
+ if (sh4->dma_source_increment[channel] == 2)
+ sh4->dma_source[channel]--;
+ *(UINT8 *)data = sh4->program->read_byte(sh4->dma_source[channel]);
+ if (sh4->dma_source_increment[channel] == 1)
+ sh4->dma_source[channel]++;
+ break;
+ case 2:
+ if (sh4->dma_source_increment[channel] == 2)
+ sh4->dma_source[channel] -= 2;
+ *(UINT16 *)data = sh4->program->read_word(sh4->dma_source[channel] & ~1);
+ if (sh4->dma_source_increment[channel] == 1)
+ sh4->dma_source[channel] += 2;
+ break;
+ case 4:
+ if (sh4->dma_source_increment[channel] == 2)
+ sh4->dma_source[channel] -= 4;
+ *(UINT32 *)data = sh4->program->read_dword(sh4->dma_source[channel] & ~3);
+ if (sh4->dma_source_increment[channel] == 1)
+ sh4->dma_source[channel] += 4;
+ break;
+ case 32:
+ if (sh4->dma_source_increment[channel] == 2)
+ sh4->dma_source[channel] -= 32;
+ *(UINT64 *)data = sh4->program->read_qword(sh4->dma_source[channel] & ~31);
+ *((UINT64 *)data+1) = sh4->program->read_qword((sh4->dma_source[channel] & ~31)+8);
+ *((UINT64 *)data+2) = sh4->program->read_qword((sh4->dma_source[channel] & ~31)+16);
+ *((UINT64 *)data+3) = sh4->program->read_qword((sh4->dma_source[channel] & ~31)+24);
+ if (sh4->dma_source_increment[channel] == 1)
+ sh4->dma_source[channel] += 32;
+ break;
+ }
+ sh4->dma_count[channel]--;
+ }
+ if (sh4->dma_count[channel] == 0) // all data transferred ?
+ {
+ sh4->dma_timer[channel]->adjust(attotime::zero, channel);
+ return 2;
+ }
+ return 1;
+ }
+ else if (sh4->dma_mode[channel] == 3)
+ {
+ // device sends data
+ len = sh4->dma_count[channel];
+ if (s->length < len)
+ len = s->length;
+ siz = sh4->dma_wordsize[channel];
+ for (pos = 0;pos < len;pos++) {
+ switch (siz)
+ {
+ case 8:
+ if (sh4->dma_destination_increment[channel] == 2)
+ sh4->dma_destination[channel]-=8;
+ sh4->program->write_qword(sh4->dma_destination[channel] & ~7, *(UINT64 *)data);
+ if (sh4->dma_destination_increment[channel] == 1)
+ sh4->dma_destination[channel]+=8;
+ break;
+ case 1:
+ if (sh4->dma_destination_increment[channel] == 2)
+ sh4->dma_destination[channel]--;
+ sh4->program->write_byte(sh4->dma_destination[channel], *(UINT8 *)data);
+ if (sh4->dma_destination_increment[channel] == 1)
+ sh4->dma_destination[channel]++;
+ break;
+ case 2:
+ if (sh4->dma_destination_increment[channel] == 2)
+ sh4->dma_destination[channel]-=2;
+ sh4->program->write_word(sh4->dma_destination[channel] & ~1, *(UINT16 *)data);
+ if (sh4->dma_destination_increment[channel] == 1)
+ sh4->dma_destination[channel]+=2;
+ break;
+ case 4:
+ if (sh4->dma_destination_increment[channel] == 2)
+ sh4->dma_destination[channel]-=4;
+ sh4->program->write_dword(sh4->dma_destination[channel] & ~3, *(UINT32 *)data);
+ if (sh4->dma_destination_increment[channel] == 1)
+ sh4->dma_destination[channel]+=4;
+ break;
+ case 32:
+ if (sh4->dma_destination_increment[channel] == 2)
+ sh4->dma_destination[channel]-=32;
+ sh4->program->write_qword(sh4->dma_destination[channel] & ~31, *(UINT64 *)data);
+ sh4->program->write_qword((sh4->dma_destination[channel] & ~31)+8, *((UINT64 *)data+1));
+ sh4->program->write_qword((sh4->dma_destination[channel] & ~31)+16, *((UINT64 *)data+2));
+ sh4->program->write_qword((sh4->dma_destination[channel] & ~31)+24, *((UINT64 *)data+3));
+ if (sh4->dma_destination_increment[channel] == 1)
+ sh4->dma_destination[channel]+=32;
+ break;
+ }
+ sh4->dma_count[channel]--;
+ }
+
+ if (sh4->dma_count[channel] == 0) // all data transferred ?
+ {
+ sh4->dma_timer[channel]->adjust(attotime::zero, channel);
+ return 2;
+ }
+ return 1;
+ }
+ else
+ return 0;
+}
+
+// called by drivers to transfer data in a DDT dma. 'device' must be a SH4 cpu
+void sh4_dma_ddt(device_t *device, struct sh4_ddt_dma *s)
+{
+ sh4_state *sh4 = get_safe_token(device);
+ UINT32 chcr;
+ UINT32 *p32bits;
+ UINT64 *p32bytes;
+ UINT32 pos,len,siz;
+
+ if (sh4->dma_timer_active[s->channel])
+ return;
+ if (s->mode >= 0) {
+ switch (s->channel)
+ {
+ case 0:
+ if (s->mode & 1)
+ s->source = sh4->m[SAR0];
+ if (s->mode & 2)
+ sh4->m[SAR0] = s->source;
+ if (s->mode & 4)
+ s->destination = sh4->m[DAR0];
+ if (s->mode & 8)
+ sh4->m[DAR0] = s->destination;
+ break;
+ case 1:
+ if (s->mode & 1)
+ s->source = sh4->m[SAR1];
+ if (s->mode & 2)
+ sh4->m[SAR1] = s->source;
+ if (s->mode & 4)
+ s->destination = sh4->m[DAR1];
+ if (s->mode & 8)
+ sh4->m[DAR1] = s->destination;
+ break;
+ case 2:
+ if (s->mode & 1)
+ s->source = sh4->m[SAR2];
+ if (s->mode & 2)
+ sh4->m[SAR2] = s->source;
+ if (s->mode & 4)
+ s->destination = sh4->m[DAR2];
+ if (s->mode & 8)
+ sh4->m[DAR2] = s->destination;
+ break;
+ case 3:
+ default:
+ if (s->mode & 1)
+ s->source = sh4->m[SAR3];
+ if (s->mode & 2)
+ sh4->m[SAR3] = s->source;
+ if (s->mode & 4)
+ s->destination = sh4->m[DAR3];
+ if (s->mode & 8)
+ sh4->m[DAR3] = s->destination;
+ break;
+ }
+ switch (s->channel)
+ {
+ case 0:
+ chcr = sh4->m[CHCR0];
+ len = sh4->m[DMATCR0];
+ break;
+ case 1:
+ chcr = sh4->m[CHCR1];
+ len = sh4->m[DMATCR1];
+ break;
+ case 2:
+ chcr = sh4->m[CHCR2];
+ len = sh4->m[DMATCR2];
+ break;
+ case 3:
+ default:
+ chcr = sh4->m[CHCR3];
+ len = sh4->m[DMATCR3];
+ break;
+ }
+ if ((s->direction) == 0) {
+ chcr = (chcr & 0xffff3fff) | ((s->mode & 0x30) << 10);
+ } else {
+ chcr = (chcr & 0xffffcfff) | ((s->mode & 0x30) << 8);
+ }
+ siz = dmasize[(chcr >> 4) & 7];
+ if (siz && (s->size))
+ if ((len * siz) != (s->length * s->size))
+ return;
+ sh4_dma_transfer(sh4, s->channel, 0, chcr, &s->source, &s->destination, &len);
+ } else {
+ if (s->size == 4) {
+ if ((s->direction) == 0) {
+ len = s->length;
+ p32bits = (UINT32 *)(s->buffer);
+ for (pos = 0;pos < len;pos++) {
+ *p32bits = sh4->program->read_dword(s->source);
+ p32bits++;
+ s->source = s->source + 4;
+ }
+ } else {
+ len = s->length;
+ p32bits = (UINT32 *)(s->buffer);
+ for (pos = 0;pos < len;pos++) {
+ sh4->program->write_dword(s->destination, *p32bits);
+ p32bits++;
+ s->destination = s->destination + 4;
+ }
+ }
+ }
+ if (s->size == 32) {
+ if ((s->direction) == 0) {
+ len = s->length * 4;
+ p32bytes = (UINT64 *)(s->buffer);
+ for (pos = 0;pos < len;pos++) {
+ *p32bytes = sh4->program->read_qword(s->source);
+ p32bytes++;
+ s->destination = s->destination + 8;
+ }
+ } else {
+ len = s->length * 4;
+ p32bytes = (UINT64 *)(s->buffer);
+ for (pos = 0;pos < len;pos++) {
+ sh4->program->write_qword(s->destination, *p32bytes);
+ p32bytes++;
+ s->destination = s->destination + 8;
+ }
+ }
+ }
+ }
+}
+
+UINT32 sh4_getsqremap(sh4_state *sh4, UINT32 address)
+{
+ if (!sh4->sh4_mmu_enabled)
+ return address;
+ else
+ {
+ int i;
+ UINT32 topaddr = address&0xfff00000;
+
+ for (i=0;i<64;i++)
+ {
+ UINT32 topcmp = sh4->sh4_tlb_address[i]&0xfff00000;
+ if (topcmp==topaddr)
+ return (address&0x000fffff) | ((sh4->sh4_tlb_data[i])&0xfff00000);
+ }
+
+ }
+
+ return address;
+}
+
+READ64_HANDLER( sh4_tlb_r )
+{
+ sh4_state *sh4 = get_safe_token(&space->device());
+
+ int offs = offset*8;
+
+ if (offs >= 0x01000000)
+ {
+ UINT8 i = (offs>>8)&63;
+ return sh4->sh4_tlb_data[i];
+ }
+ else
+ {
+ UINT8 i = (offs>>8)&63;
+ return sh4->sh4_tlb_address[i];
+ }
+}
+
+WRITE64_HANDLER( sh4_tlb_w )
+{
+ sh4_state *sh4 = get_safe_token(&space->device());
+
+ int offs = offset*8;
+
+ if (offs >= 0x01000000)
+ {
+ UINT8 i = (offs>>8)&63;
+ sh4->sh4_tlb_data[i] = data&0xffffffff;
+ }
+ else
+ {
+ UINT8 i = (offs>>8)&63;
+ sh4->sh4_tlb_address[i] = data&0xffffffff;
+ }
+}
+
diff --git a/trunk/src/emu/cpu/sh4/sh4comn.h b/trunk/src/emu/cpu/sh4/sh4comn.h
new file mode 100644
index 00000000000..ab08e9ffd1b
--- /dev/null
+++ b/trunk/src/emu/cpu/sh4/sh4comn.h
@@ -0,0 +1,299 @@
+/*****************************************************************************
+ *
+ * sh4comn.h
+ *
+ * SH-4 non-specific components
+ *
+ *****************************************************************************/
+
+#pragma once
+
+#ifndef __SH4COMN_H__
+#define __SH4COMN_H__
+
+//#define USE_SH4DRC
+
+/* speed up delay loops, bail out of tight loops */
+#define BUSY_LOOP_HACKS 0
+
+#define VERBOSE 0
+
+#ifdef USE_SH4DRC
+#include "cpu/drcfe.h"
+#include "cpu/drcuml.h"
+#include "cpu/drcumlsh.h"
+
+class sh4_frontend;
+#endif
+
+#define CPU_TYPE_SH3 (2)
+#define CPU_TYPE_SH4 (3)
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+#define EXPPRI(pl,po,p,n) (((4-(pl)) << 24) | ((15-(po)) << 16) | ((p) << 8) | (255-(n)))
+#define NMIPRI() EXPPRI(3,0,16,SH4_INTC_NMI)
+#define INTPRI(p,n) EXPPRI(4,2,p,n)
+
+#define FP_RS(r) sh4->fr[(r)] // binary representation of single precision floating point register r
+#define FP_RFS(r) *( (float *)(sh4->fr+(r)) ) // single precision floating point register r
+#define FP_RFD(r) *( (double *)(sh4->fr+(r)) ) // double precision floating point register r
+#define FP_XS(r) sh4->xf[(r)] // binary representation of extended single precision floating point register r
+#define FP_XFS(r) *( (float *)(sh4->xf+(r)) ) // single precision extended floating point register r
+#define FP_XFD(r) *( (double *)(sh4->xf+(r)) ) // double precision extended floating point register r
+#ifdef LSB_FIRST
+#define FP_RS2(r) sh4->fr[(r) ^ sh4->fpu_pr]
+#define FP_RFS2(r) *( (float *)(sh4->fr+((r) ^ sh4->fpu_pr)) )
+#define FP_XS2(r) sh4->xf[(r) ^ sh4->fpu_pr]
+#define FP_XFS2(r) *( (float *)(sh4->xf+((r) ^ sh4->fpu_pr)) )
+#endif
+
+
+typedef struct
+{
+ UINT32 ppc;
+ UINT32 pc, spc;
+ UINT32 pr;
+ UINT32 sr, ssr;
+ UINT32 gbr, vbr;
+ UINT32 mach, macl;
+ UINT32 r[16], rbnk[2][8], sgr;
+ UINT32 fr[16], xf[16];
+ UINT32 ea;
+ UINT32 delay;
+ UINT32 cpu_off;
+ UINT32 pending_irq;
+ UINT32 test_irq;
+ UINT32 fpscr;
+ UINT32 fpul;
+ UINT32 dbr;
+
+ UINT32 exception_priority[128];
+ int exception_requesting[128];
+
+ INT8 irq_line_state[17];
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *internal;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *io;
+ UINT32 *m;
+ INT8 nmi_line_state;
+
+ UINT8 sleep_mode;
+
+ int frt_input;
+ int irln;
+ int internal_irq_level;
+ int internal_irq_vector;
+
+ emu_timer *dma_timer[4];
+ emu_timer *refresh_timer;
+ emu_timer *rtc_timer;
+ emu_timer *timer[3];
+ UINT32 refresh_timer_base;
+ int dma_timer_active[4];
+ UINT32 dma_source[4];
+ UINT32 dma_destination[4];
+ UINT32 dma_count[4];
+ int dma_wordsize[4];
+ int dma_source_increment[4];
+ int dma_destination_increment[4];
+ int dma_mode[4];
+
+ int sh4_icount;
+ int is_slave;
+ int cpu_clock, bus_clock, pm_clock;
+ int fpu_sz, fpu_pr;
+ int ioport16_pullup, ioport16_direction;
+ int ioport4_pullup, ioport4_direction;
+
+ void (*ftcsr_read_callback)(UINT32 data);
+
+
+ /* This MMU simulation is good for the simple remap used on Naomi GD-ROM SQ access *ONLY* */
+ UINT32 sh4_tlb_address[64];
+ UINT32 sh4_tlb_data[64];
+ UINT8 sh4_mmu_enabled;
+
+ int cpu_type;
+
+#ifdef USE_SH4DRC
+ int icount;
+
+ int pcfsel; // last pcflush entry set
+ int maxpcfsel; // highest valid pcflush entry
+ UINT32 pcflushes[16]; // pcflush entries
+
+ drc_cache * cache; /* pointer to the DRC code cache */
+ drcuml_state * drcuml; /* DRC UML generator state */
+ sh4_frontend * drcfe; /* pointer to the DRC front-end class */
+ UINT32 drcoptions; /* configurable DRC options */
+
+ /* internal stuff */
+ UINT8 cache_dirty; /* true if we need to flush the cache */
+
+ /* parameters for subroutines */
+ UINT64 numcycles; /* return value from gettotalcycles */
+ UINT32 arg0; /* print_debug argument 1 */
+ UINT32 arg1; /* print_debug argument 2 */
+ UINT32 irq; /* irq we're taking */
+
+ /* register mappings */
+ uml::parameter regmap[16]; /* parameter to register mappings for all 16 integer registers */
+
+ uml::code_handle * entry; /* entry point */
+ uml::code_handle * read8; /* read byte */
+ uml::code_handle * write8; /* write byte */
+ uml::code_handle * read16; /* read half */
+ uml::code_handle * write16; /* write half */
+ uml::code_handle * read32; /* read word */
+ uml::code_handle * write32; /* write word */
+
+ uml::code_handle * interrupt; /* interrupt */
+ uml::code_handle * nocode; /* nocode */
+ uml::code_handle * out_of_cycles; /* out of cycles exception handler */
+
+ UINT32 prefadr;
+ UINT32 target;
+#endif
+} sh4_state;
+
+#ifdef USE_SH4DRC
+class sh4_frontend : public drc_frontend
+{
+public:
+ sh4_frontend(sh4_state &state, UINT32 window_start, UINT32 window_end, UINT32 max_sequence);
+
+protected:
+ virtual bool describe(opcode_desc &desc, const opcode_desc *prev);
+
+private:
+ bool describe_group_0(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
+ bool describe_group_2(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
+ bool describe_group_3(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
+ bool describe_group_4(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
+ bool describe_group_6(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
+ bool describe_group_8(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
+ bool describe_group_12(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
+ bool describe_group_15(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
+
+ sh4_state &m_context;
+};
+
+INLINE sh4_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == SH3 ||
+ device->type() == SH4);
+ return *(sh4_state **)downcast<legacy_cpu_device *>(device)->token();
+}
+#else
+INLINE sh4_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == SH3 ||
+ device->type() == SH4);
+ return (sh4_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+#endif
+
+
+enum
+{
+ ICF = 0x00800000,
+ OCFA = 0x00080000,
+ OCFB = 0x00040000,
+ OVF = 0x00020000
+};
+
+/* Bits in SR */
+#define T 0x00000001
+#define S 0x00000002
+#define I 0x000000f0
+#define Q 0x00000100
+#define M 0x00000200
+#define FD 0x00008000
+#define BL 0x10000000
+#define sRB 0x20000000
+#define MD 0x40000000
+
+/* 29 bits */
+#define AM 0x1fffffff
+
+#define FLAGS (MD|sRB|BL|FD|M|Q|I|S|T)
+
+/* Bits in FPSCR */
+#define RM 0x00000003
+#define DN 0x00040000
+#define PR 0x00080000
+#define SZ 0x00100000
+#define FR 0x00200000
+
+#define Rn ((opcode>>8)&15)
+#define Rm ((opcode>>4)&15)
+
+#define REGFLAG_R(n) (1 << (n))
+#define REGFLAG_FR(n) (1 << (n))
+#define REGFLAG_XR(n) (1 << (n))
+
+/* register flags 1 */
+#define REGFLAG_PR (1 << 0)
+#define REGFLAG_MACL (1 << 1)
+#define REGFLAG_MACH (1 << 2)
+#define REGFLAG_GBR (1 << 3)
+#define REGFLAG_VBR (1 << 4)
+#define REGFLAG_SR (1 << 5)
+#define REGFLAG_SGR (1 << 6)
+#define REGFLAG_FPUL (1 << 7)
+#define REGFLAG_FPSCR (1 << 8)
+#define REGFLAG_DBR (1 << 9)
+#define REGFLAG_SSR (1 << 10)
+#define REGFLAG_SPC (1 << 11)
+
+void sh4_exception_recompute(sh4_state *sh4); // checks if there is any interrupt with high enough priority
+void sh4_exception_request(sh4_state *sh4, int exception); // start requesting an exception
+void sh4_exception_unrequest(sh4_state *sh4, int exception); // stop requesting an exception
+void sh4_exception_checkunrequest(sh4_state *sh4, int exception);
+void sh4_exception(sh4_state *sh4, const char *message, int exception); // handle exception
+void sh4_change_register_bank(sh4_state *sh4, int to);
+void sh4_syncronize_register_bank(sh4_state *sh4, int to);
+void sh4_swap_fp_registers(sh4_state *sh4);
+void sh4_default_exception_priorities(sh4_state *sh4); // setup default priorities for exceptions
+void sh4_parse_configuration(sh4_state *sh4, const struct sh4_config *conf);
+void sh4_set_irq_line(sh4_state *sh4, int irqline, int state); // set state of external interrupt line
+#ifdef LSB_FIRST
+void sh4_swap_fp_couples(sh4_state *sh4);
+#endif
+void sh4_common_init(device_t *device);
+UINT32 sh4_getsqremap(sh4_state *sh4, UINT32 address);
+
+READ64_HANDLER( sh4_tlb_r );
+WRITE64_HANDLER( sh4_tlb_w );
+
+INLINE void sh4_check_pending_irq(sh4_state *sh4, const char *message) // look for highest priority active exception and handle it
+{
+ int a,irq,z;
+
+ irq = 0;
+ z = -1;
+ for (a=0;a <= SH4_INTC_ROVI;a++)
+ {
+ if (sh4->exception_requesting[a])
+ {
+ if ((int)sh4->exception_priority[a] > z)
+ {
+ z = sh4->exception_priority[a];
+ irq = a;
+ }
+ }
+ }
+ if (z >= 0)
+ {
+ sh4_exception(sh4, message, irq);
+ }
+}
+
+#endif /* __SH4COMN_H__ */
+
diff --git a/trunk/src/emu/cpu/sh4/sh4dasm.c b/trunk/src/emu/cpu/sh4/sh4dasm.c
new file mode 100644
index 00000000000..4ec1f8fcd9f
--- /dev/null
+++ b/trunk/src/emu/cpu/sh4/sh4dasm.c
@@ -0,0 +1,818 @@
+#include "emu.h"
+#include "debugger.h"
+#include "sh4.h"
+
+#define SIGNX8(x) (((INT32)(x) << 24) >> 24)
+#define SIGNX12(x) (((INT32)(x) << 20) >> 20)
+
+#define Rn ((opcode >> 8) & 15)
+#define Rm ((opcode >> 4) & 15)
+
+static const char *const regname[16] = {
+ "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
+ "R8", "R9", "R10","R11","R12","R13","R14","R15"
+};
+
+static UINT32 op0000(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ UINT32 flags = 0;
+ switch (opcode & 0xF)
+ {
+ case 0x0:
+ case 0x1:
+ sprintf(buffer, "?????? $%04X", opcode); break;
+ case 0x2:
+ if (opcode & 0x80) {
+ sprintf(buffer,"STC %s_BANK,%s", regname[(Rm) & 7],regname[Rn]);
+ return flags;
+ }
+ switch (opcode & 0x70)
+ {
+ case 0x00:
+ sprintf(buffer,"STC SR,%s", regname[Rn]); break;
+ case 0x10:
+ sprintf(buffer,"STC GBR,%s", regname[Rn]); break;
+ case 0x20:
+ sprintf(buffer,"STC VBR,%s", regname[Rn]); break;
+ case 0x30:
+ sprintf(buffer,"STC SSR,%s", regname[Rn]); break;
+ case 0x40:
+ sprintf(buffer,"STC SPC,%s", regname[Rn]); break;
+ }
+ break;
+ case 0x3:
+ switch (opcode & 0xF0)
+ {
+ case 0x00:
+ sprintf(buffer,"BSRF %s", regname[Rn]); break;
+ case 0x20:
+ sprintf(buffer,"BRAF %s", regname[Rn]); break;
+ case 0x80:
+ sprintf(buffer,"PREF @%s", regname[Rn]); break;
+ case 0x90:
+ sprintf(buffer,"OCBI @%s", regname[Rn]); break;
+ case 0xA0:
+ sprintf(buffer,"OCBP @%s", regname[Rn]); break;
+ case 0xB0:
+ sprintf(buffer,"OCBWB @%s", regname[Rn]); break;
+ case 0xC0:
+ sprintf(buffer,"MOVCA.L R0,@%s", regname[Rn]); break;
+ }
+ break;
+ case 0x4:
+ sprintf(buffer, "MOV.B %s,@(R0,%s)", regname[Rm], regname[Rn]); break;
+ case 0x5:
+ sprintf(buffer, "MOV.W %s,@(R0,%s)", regname[Rm], regname[Rn]); break;
+ case 0x6:
+ sprintf(buffer, "MOV.L %s,@(R0,%s)", regname[Rm], regname[Rn]); break;
+ case 0x7:
+ sprintf(buffer, "MUL.L %s,%s", regname[Rm], regname[Rn]); break;
+ case 0x8:
+ switch (opcode & 0x70)
+ {
+ case 0x00:
+ sprintf(buffer,"CLRT"); break;
+ case 0x10:
+ sprintf(buffer,"SETT"); break;
+ case 0x20:
+ sprintf(buffer,"CLRMAC"); break;
+ case 0x30:
+ sprintf(buffer,"LDTLB"); break;
+ case 0x40:
+ sprintf(buffer,"CLRS"); break;
+ case 0x50:
+ sprintf(buffer,"SETS"); break;
+ }
+ break;
+ case 0x9:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ sprintf(buffer,"NOP"); break;
+ case 0x10:
+ sprintf(buffer,"DIV0U"); break;
+ case 0x20:
+ sprintf(buffer,"MOVT %s", regname[Rn]); break;
+ }
+ break;
+ case 0xA:
+ switch (opcode & 0x70)
+ {
+ case 0x00:
+ sprintf(buffer,"STS MACH,%s", regname[Rn]); break;
+ case 0x10:
+ sprintf(buffer,"STS MACL,%s", regname[Rn]); break;
+ case 0x20:
+ sprintf(buffer,"STS PR,%s", regname[Rn]); break;
+ case 0x30:
+ sprintf(buffer,"STC SGR,%s", regname[Rn]); break;
+ case 0x50:
+ sprintf(buffer,"STS FPUL,%s", regname[Rn]); break;
+ case 0x60:
+ sprintf(buffer,"STS FPSCR,%s", regname[Rn]); break;
+ case 0x70:
+ sprintf(buffer,"STC DBR,%s", regname[Rn]); break;
+ }
+ break;
+ case 0xB:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ sprintf(buffer,"RTS");
+ flags = DASMFLAG_STEP_OUT;
+ break;
+ case 0x10:
+ sprintf(buffer,"SLEEP"); break;
+ case 0x20:
+ sprintf(buffer,"RTE");
+ flags = DASMFLAG_STEP_OUT;
+ break;
+ }
+ break;
+ case 0xC:
+ sprintf(buffer, "MOV.B @(R0,%s),%s", regname[Rm], regname[Rn]); break;
+ case 0xD:
+ sprintf(buffer, "MOV.W @(R0,%s),%s", regname[Rm], regname[Rn]); break;
+ case 0xE:
+ sprintf(buffer, "MOV.L @(R0,%s),%s", regname[Rm], regname[Rn]); break;
+ case 0xF:
+ sprintf(buffer, "MAC.L @%s+,@%s+", regname[Rn], regname[Rm]); break;
+ }
+ return flags;
+}
+
+static UINT32 op0001(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ sprintf(buffer, "MOV.L %s,@($%02X,%s)", regname[Rm], (opcode & 15) * 4, regname[Rn]);
+ return 0;
+}
+
+static UINT32 op0010(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ switch (opcode & 15)
+ {
+ case 0:
+ sprintf(buffer, "MOV.B %s,@%s", regname[Rm], regname[Rn]);
+ break;
+ case 1:
+ sprintf(buffer, "MOV.W %s,@%s", regname[Rm], regname[Rn]);
+ break;
+ case 2:
+ sprintf(buffer, "MOV.L %s,@%s", regname[Rm], regname[Rn]);
+ break;
+ case 3:
+ sprintf(buffer, "?????? $%04X", opcode);
+ break;
+ case 4:
+ sprintf(buffer, "MOV.B %s,@-%s", regname[Rm], regname[Rn]);
+ break;
+ case 5:
+ sprintf(buffer, "MOV.W %s,@-%s", regname[Rm], regname[Rn]);
+ break;
+ case 6:
+ sprintf(buffer, "MOV.L %s,@-%s", regname[Rm], regname[Rn]);
+ break;
+ case 7:
+ sprintf(buffer, "DIV0S %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 8:
+ sprintf(buffer, "TST %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 9:
+ sprintf(buffer, "AND %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 10:
+ sprintf(buffer, "XOR %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 11:
+ sprintf(buffer, "OR %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 12:
+ sprintf(buffer, "CMP/STR %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 13:
+ sprintf(buffer, "XTRCT %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 14:
+ sprintf(buffer, "MULU.W %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 15:
+ sprintf(buffer, "MULS.W %s,%s", regname[Rm], regname[Rn]);
+ break;
+ }
+ return 0;
+}
+
+static UINT32 op0011(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ switch (opcode & 15)
+ {
+ case 0:
+ sprintf(buffer, "CMP/EQ %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 1:
+ sprintf(buffer, "?????? %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 2:
+ sprintf(buffer, "CMP/HS %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 3:
+ sprintf(buffer, "CMP/GE %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 4:
+ sprintf(buffer, "DIV1 %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 5:
+ sprintf(buffer, "DMULU.L %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 6:
+ sprintf(buffer, "CMP/HI %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 7:
+ sprintf(buffer, "CMP/GT %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 8:
+ sprintf(buffer, "SUB %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 9:
+ sprintf(buffer, "?????? %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 10:
+ sprintf(buffer, "SUBC %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 11:
+ sprintf(buffer, "SUBV %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 12:
+ sprintf(buffer, "ADD %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 13:
+ sprintf(buffer, "DMULS.L %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 14:
+ sprintf(buffer, "ADDC %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 15:
+ sprintf(buffer, "ADDV %s,%s", regname[Rm], regname[Rn]);
+ break;
+ }
+ return 0;
+}
+
+static UINT32 op0100(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ UINT32 flags = 0;
+ switch (opcode & 0xF)
+ {
+ case 0x0:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ sprintf(buffer, "SHLL %s", regname[Rn]); break;
+ case 0x10:
+ sprintf(buffer, "DT %s", regname[Rn]); break;
+ case 0x20:
+ sprintf(buffer, "SHAL %s", regname[Rn]); break;
+ }
+ break;
+ case 0x1:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ sprintf(buffer, "SHLR %s", regname[Rn]); break;
+ case 0x10:
+ sprintf(buffer, "CMP/PZ %s", regname[Rn]); break;
+ case 0x20:
+ sprintf(buffer, "SHAR %s", regname[Rn]); break;
+ }
+ break;
+ case 0x2:
+ switch (opcode & 0xF0)
+ {
+ case 0x00:
+ sprintf(buffer, "STS.L MACH,@-%s", regname[Rn]); break;
+ case 0x10:
+ sprintf(buffer, "STS.L MACL,@-%s", regname[Rn]); break;
+ case 0x20:
+ sprintf(buffer, "STS.L PR,@-%s", regname[Rn]); break;
+ case 0x30:
+ sprintf(buffer, "STC.L SGR,@-%s", regname[Rn]); break;
+ case 0x50:
+ sprintf(buffer, "STS.L FPUL,@-%s", regname[Rn]); break;
+ case 0x60:
+ sprintf(buffer, "STS.L FPSCR,@-%s", regname[Rn]); break;
+ case 0xF0:
+ sprintf(buffer, "STC.L DBR,@-%s", regname[Rn]); break;
+ }
+ break;
+ case 0x3:
+ if (opcode & 0x80) {
+ sprintf(buffer, "STC.L %s_BANK,@-%s", regname[(Rm) & 7],regname[Rn]);
+ return flags;
+ }
+ switch (opcode & 0x70)
+ {
+ case 0x00:
+ sprintf(buffer, "STC.L SR,@-%s", regname[Rn]); break;
+ case 0x10:
+ sprintf(buffer, "STC.L GBR,@-%s", regname[Rn]); break;
+ case 0x20:
+ sprintf(buffer, "STC.L VBR,@-%s", regname[Rn]); break;
+ case 0x30:
+ sprintf(buffer, "STC.L SSR,@-%s", regname[Rn]); break;
+ case 0x40:
+ sprintf(buffer, "STC.L SPC,@-%s", regname[Rn]); break;
+ }
+ break;
+ case 0x4:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ sprintf(buffer, "ROTL %s", regname[Rn]); break;
+ case 0x20:
+ sprintf(buffer, "ROTCL %s", regname[Rn]); break;
+ }
+ break;
+ case 0x5:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ sprintf(buffer, "ROTR %s", regname[Rn]); break;
+ case 0x10:
+ sprintf(buffer, "CMP/PL %s", regname[Rn]); break;
+ case 0x20:
+ sprintf(buffer, "ROTCR %s", regname[Rn]); break;
+ }
+ break;
+ case 0x6:
+ switch (opcode & 0xF0)
+ {
+ case 0x00:
+ sprintf(buffer, "LDS.L @%s+,MACH", regname[Rn]); break;
+ case 0x10:
+ sprintf(buffer, "LDS.L @%s+,MACL", regname[Rn]); break;
+ case 0x20:
+ sprintf(buffer, "LDS.L @%s+,PR", regname[Rn]); break;
+ case 0x50:
+ sprintf(buffer, "LDS.L @%s+,FPUL", regname[Rn]); break;
+ case 0x60:
+ sprintf(buffer, "LDS.L @%s+,FPSCR", regname[Rn]); break;
+ case 0xF0:
+ sprintf(buffer, "LDC.L @%s+,DBR", regname[Rn]); break;
+ }
+ break;
+ case 0x7:
+ if (opcode & 0x80) {
+ sprintf(buffer, "LDC.L @%s+,%s_BANK", regname[Rn],regname[(Rm) & 7]);
+ return flags;
+ }
+ switch (opcode & 0x70)
+ {
+ case 0x00:
+ sprintf(buffer, "LDC.L @%s+,SR", regname[Rn]); break;
+ case 0x10:
+ sprintf(buffer, "LDC.L @%s+,GBR", regname[Rn]); break;
+ case 0x20:
+ sprintf(buffer, "LDC.L @%s+,VBR", regname[Rn]); break;
+ case 0x30:
+ sprintf(buffer, "LDC.L @%s+,SSR", regname[Rn]); break;
+ case 0x40:
+ sprintf(buffer, "LDC.L @%s+,SPC", regname[Rn]); break;
+ }
+ break;
+ case 0x8:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ sprintf(buffer, "SHLL2 %s", regname[Rn]); break;
+ case 0x10:
+ sprintf(buffer, "SHLL8 %s", regname[Rn]); break;
+ case 0x20:
+ sprintf(buffer, "SHLL16 %s", regname[Rn]); break;
+ }
+ break;
+ case 0x9:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ sprintf(buffer, "SHLR2 %s", regname[Rn]); break;
+ case 0x10:
+ sprintf(buffer, "SHLR8 %s", regname[Rn]); break;
+ case 0x20:
+ sprintf(buffer, "SHLR16 %s", regname[Rn]); break;
+ }
+ break;
+ case 0xA:
+ switch (opcode & 0xF0)
+ {
+ case 0x00:
+ sprintf(buffer, "LDS %s,MACH", regname[Rn]); break;
+ case 0x10:
+ sprintf(buffer, "LDS %s,MACL", regname[Rn]); break;
+ case 0x20:
+ sprintf(buffer, "LDS %s,PR", regname[Rn]); break;
+ case 0x50:
+ sprintf(buffer, "LDS %s,FPUL", regname[Rn]); break;
+ case 0x60:
+ sprintf(buffer, "LDS %s,FPSCR", regname[Rn]); break;
+ case 0xF0:
+ sprintf(buffer, "LDC %s,DBR", regname[Rn]); break;
+ }
+ break;
+ case 0xB:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ sprintf(buffer, "JSR %s", regname[Rn]);
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
+ break;
+ case 0x10:
+ sprintf(buffer, "TAS %s", regname[Rn]); break;
+ case 0x20:
+ sprintf(buffer, "JMP %s", regname[Rn]); break;
+ }
+ break;
+ case 0xC:
+ sprintf(buffer, "SHAD %s,%s", regname[Rm], regname[Rn]); break;
+ case 0xD:
+ sprintf(buffer, "SHLD %s,%s", regname[Rm], regname[Rn]); break;
+ case 0xE:
+ if (opcode & 0x80) {
+ sprintf(buffer, "LDC %s,%s_BANK", regname[Rn],regname[(Rm) & 7]);
+ return flags;
+ }
+ switch (opcode & 0x70)
+ {
+ case 0x00:
+ sprintf(buffer, "LDC %s,SR", regname[Rn]); break;
+ case 0x10:
+ sprintf(buffer, "LDC %s,GBR", regname[Rn]); break;
+ case 0x20:
+ sprintf(buffer, "LDC %s,VBR", regname[Rn]); break;
+ case 0x30:
+ sprintf(buffer, "LDC %s,SSR", regname[Rn]); break;
+ case 0x40:
+ sprintf(buffer, "LDC %s,SPC", regname[Rn]); break;
+ }
+ break;
+ case 0xF:
+ sprintf(buffer, "MAC.W @%s+,@%s+", regname[Rm], regname[Rn]); break;
+ }
+ return flags;
+}
+
+static UINT32 op0101(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ sprintf(buffer, "MOV.L @($%02X,%s),%s", (opcode & 15) * 4, regname[Rm], regname[Rn]);
+ return 0;
+}
+
+static UINT32 op0110(char *buffer, UINT32 pc, UINT16 opcode)
+
+{
+ switch(opcode & 0xF)
+ {
+ case 0x00:
+ sprintf(buffer, "MOV.B @%s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x01:
+ sprintf(buffer, "MOV.W @%s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x02:
+ sprintf(buffer, "MOV.L @%s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x03:
+ sprintf(buffer, "MOV %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x04:
+ sprintf(buffer, "MOV.B @%s+,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x05:
+ sprintf(buffer, "MOV.W @%s+,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x06:
+ sprintf(buffer, "MOV.L @%s+,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x07:
+ sprintf(buffer, "NOT %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x08:
+ sprintf(buffer, "SWAP.B %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x09:
+ sprintf(buffer, "SWAP.W %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x0a:
+ sprintf(buffer, "NEGC %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x0b:
+ sprintf(buffer, "NEG %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x0c:
+ sprintf(buffer, "EXTU.B %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x0d:
+ sprintf(buffer, "EXTU.W %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x0e:
+ sprintf(buffer, "EXTS.B %s,%s", regname[Rm], regname[Rn]);
+ break;
+ case 0x0f:
+ sprintf(buffer, "EXTS.W %s,%s", regname[Rm], regname[Rn]);
+ break;
+ }
+ return 0;
+}
+
+static UINT32 op0111(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ sprintf(buffer, "ADD #$%02X,%s", opcode & 0xff, regname[Rn]);
+ return 0;
+}
+
+static UINT32 op1000(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ switch((opcode >> 8) & 15)
+ {
+ case 0:
+ sprintf(buffer, "MOV.B R0,@($%02X,%s)", (opcode & 15), regname[Rm]);
+ break;
+ case 1:
+ sprintf(buffer, "MOV.W R0,@($%02X,%s)", (opcode & 15) * 2, regname[Rm]);
+ break;
+ case 4:
+ sprintf(buffer, "MOV.B @($%02X,%s),R0", (opcode & 15), regname[Rm]);
+ break;
+ case 5:
+ sprintf(buffer, "MOV.W @($%02X,%s),R0", (opcode & 15) * 2, regname[Rm]);
+ break;
+ case 8:
+ sprintf(buffer, "CMP/EQ #$%02X,R0", (opcode & 0xff));
+ break;
+ case 9:
+ sprintf(buffer, "BT $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2);
+ break;
+ case 11:
+ sprintf(buffer, "BF $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2);
+ break;
+ case 13:
+ sprintf(buffer, "BTS $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2);
+ break;
+ case 15:
+ sprintf(buffer, "BFS $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2);
+ break;
+ default :
+ sprintf(buffer, "invalid $%04X", opcode);
+ }
+ return 0;
+}
+
+static UINT32 op1001(char *buffer, UINT32 pc, UINT16 opcode)
+{
+UINT32 ea=(pc+((opcode & 0xff) * 2)+2);
+
+ sprintf(buffer, "MOV.W @($%04X,PC),%s [%08X]", (opcode & 0xff) * 2, regname[Rn], ea);
+ return 0;
+}
+
+static UINT32 op1010(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ sprintf(buffer, "BRA $%08X", SIGNX12(opcode & 0xfff) * 2 + pc + 2);
+ return 0;
+}
+
+static UINT32 op1011(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ sprintf(buffer, "BSR $%08X", SIGNX12(opcode & 0xfff) * 2 + pc + 2);
+ return DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
+}
+
+static UINT32 op1100(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ UINT32 flags = 0;
+ switch((opcode >> 8) & 15)
+ {
+ case 0:
+ sprintf(buffer, "MOV.B R0,@($%02X,GBR)", opcode & 0xff);
+ break;
+ case 1:
+ sprintf(buffer, "MOV.W R0,@($%04X,GBR)", (opcode & 0xff) * 2);
+ break;
+ case 2:
+ sprintf(buffer, "MOV.L R0,@($%04X,GBR)", (opcode & 0xff) * 4);
+ break;
+ case 3:
+ sprintf(buffer, "TRAPA #$%02X", opcode & 0xff);
+ flags = DASMFLAG_STEP_OVER;
+ break;
+ case 4:
+ sprintf(buffer, "MOV.B @($%02X,GBR),R0", opcode & 0xff);
+ break;
+ case 5:
+ sprintf(buffer, "MOV.W @($%04X,GBR),R0", (opcode & 0xff) * 2);
+ break;
+ case 6:
+ sprintf(buffer, "MOV.L @($%04X,GBR),R0", (opcode & 0xff) * 4);
+ break;
+ case 7:
+ sprintf(buffer, "MOVA @($%04X,PC),R0 [%08X]", (opcode & 0xff) * 4, ((pc + 2) & ~3) + (opcode & 0xff) * 4);
+ break;
+ case 8:
+ sprintf(buffer, "TST #$%02X,R0", opcode & 0xff);
+ break;
+ case 9:
+ sprintf(buffer, "AND #$%02X,R0", opcode & 0xff);
+ break;
+ case 10:
+ sprintf(buffer, "XOR #$%02X,R0", opcode & 0xff);
+ break;
+ case 11:
+ sprintf(buffer, "OR #$%02X,R0", opcode & 0xff);
+ break;
+ case 12:
+ sprintf(buffer, "TST.B #$%02X,@(R0,GBR)", opcode & 0xff);
+ break;
+ case 13:
+ sprintf(buffer, "AND.B #$%02X,@(R0,GBR)", opcode & 0xff);
+ break;
+ case 14:
+ sprintf(buffer, "XOR.B #$%02X,@(R0,GBR)", opcode & 0xff);
+ break;
+ case 15:
+ sprintf(buffer, "OR.B #$%02X,@(R0,GBR)", opcode & 0xff);
+ break;
+ }
+ return flags;
+}
+
+static UINT32 op1101(char *buffer, UINT32 pc, UINT16 opcode)
+{
+UINT32 ea=((pc + 2) & ~3) + (opcode & 0xff) * 4;
+
+ sprintf(buffer, "MOV.L @($%04X,PC),%s [%08X]", (opcode & 0xff) * 4, regname[Rn], ea);
+ return 0;
+}
+
+static UINT32 op1110(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ sprintf(buffer, "MOV #$%02X,%s", (opcode & 0xff), regname[Rn]);
+ return 0;
+}
+
+static UINT32 op1111(char *buffer, UINT32 pc, UINT16 opcode)
+{
+ switch (opcode & 0xf)
+ {
+ case 0:
+ sprintf(buffer, "FADD F%s, F%s", regname[Rm], regname[Rn]);
+ break;
+ case 1:
+ sprintf(buffer, "FSUB F%s, F%s", regname[Rm], regname[Rn]);
+ break;
+ case 2:
+ sprintf(buffer, "FMUL F%s, F%s", regname[Rm], regname[Rn]);
+ break;
+ case 3:
+ sprintf(buffer, "FDIV F%s, F%s", regname[Rm], regname[Rn]);
+ break;
+ case 4:
+ sprintf(buffer, "FCMP/EQ F%s, F%s", regname[Rm], regname[Rn]);
+ break;
+ case 5:
+ sprintf(buffer, "FCMP/GT F%s, F%s", regname[Rm], regname[Rn]);
+ break;
+ case 6:
+ sprintf(buffer, "FMOV.S @(R0,%s),F%s", regname[Rm], regname[Rn]);
+ break;
+ case 7:
+ sprintf(buffer, "FMOV.S F%s, @(R0,%s)", regname[Rm], regname[Rn]);
+ break;
+ case 8:
+ sprintf(buffer, "FMOV.S @%s, F%s", regname[Rm], regname[Rn]);
+ break;
+ case 9:
+ sprintf(buffer, "FMOV.S @%s+, F%s", regname[Rm], regname[Rn]);
+ break;
+ case 10:
+ sprintf(buffer, "FMOV.S F%s, @%s", regname[Rm], regname[Rn]);
+ break;
+ case 11:
+ sprintf(buffer, "FMOV.S F%s, @-%s", regname[Rm], regname[Rn]);
+ break;
+ case 12:
+ sprintf(buffer, "FMOV.S F%s, F%s", regname[Rm], regname[Rn]);
+ break;
+ case 13:
+ switch (opcode & 0xF0)
+ {
+ case 0x00:
+ sprintf(buffer, "FSTS FPUL, F%s", regname[Rn]);
+ break;
+ case 0x10:
+ sprintf(buffer, "FLDS F%s, FPUL", regname[Rn]);
+ break;
+ case 0x20:
+ sprintf(buffer, "FLOAT FPUL, F%s", regname[Rn]);
+ break;
+ case 0x30:
+ sprintf(buffer, "FTRC F%s, FPUL", regname[Rn]);
+ break;
+ case 0x40:
+ sprintf(buffer, "FNEG F%s", regname[Rn]);
+ break;
+ case 0x50:
+ sprintf(buffer, "FABS F%s", regname[Rn]);
+ break;
+ case 0x60:
+ sprintf(buffer, "FSQRT F%s", regname[Rn]);
+ break;
+ case 0x70:
+ sprintf(buffer, "FSRRA F%s", regname[Rn]);
+ break;
+ case 0x80:
+ sprintf(buffer, "FLDI0 F%s", regname[Rn]);
+ break;
+ case 0x90:
+ sprintf(buffer, "FLDI1 F%s", regname[Rn]);
+ break;
+ case 0xA0:
+ sprintf(buffer, "FCNVSD FPUL, D%s", regname[Rn]);
+ break;
+ case 0xB0:
+ sprintf(buffer, "FCNVDS D%s, FPUL", regname[Rn]);
+ break;
+ case 0xE0:
+ sprintf(buffer, "FIPR FV%d, FV%d", (Rn & 3) << 2, Rn & 12);
+ break;
+ case 0xF0:
+ if (opcode & 0x100) {
+ if (opcode & 0x200) {
+ switch (opcode & 0xC00)
+ {
+ case 0x000:
+ sprintf(buffer, "FSCHG");
+ break;
+ case 0x800:
+ sprintf(buffer, "FRCHG");
+ break;
+ default:
+ sprintf(buffer, "Funknown $%04X", opcode);
+ break;
+ }
+ } else {
+ sprintf(buffer, "FTRV XMTRX, FV%d", Rn & 12);
+ }
+ } else {
+ sprintf(buffer, "FSCA FPUL, F%s", regname[Rn & 14]);
+ }
+ break;
+ default:
+ sprintf(buffer, "Funknown $%04X", opcode);
+ break;
+ }
+ break;
+ case 14:
+ sprintf(buffer, "FMAC FR0, F%s,F%s", regname[Rm], regname[Rn]);
+ break;
+ default:
+ sprintf(buffer, "Funknown $%04X", opcode);
+ break;
+
+ }
+
+ return 0;
+}
+
+unsigned DasmSH4(char *buffer, unsigned pc, UINT16 opcode)
+{
+ UINT32 flags;
+
+ pc += 2;
+
+ switch((opcode >> 12) & 15)
+ {
+ case 0: flags = op0000(buffer,pc,opcode); break;
+ case 1: flags = op0001(buffer,pc,opcode); break;
+ case 2: flags = op0010(buffer,pc,opcode); break;
+ case 3: flags = op0011(buffer,pc,opcode); break;
+ case 4: flags = op0100(buffer,pc,opcode); break;
+ case 5: flags = op0101(buffer,pc,opcode); break;
+ case 6: flags = op0110(buffer,pc,opcode); break;
+ case 7: flags = op0111(buffer,pc,opcode); break;
+ case 8: flags = op1000(buffer,pc,opcode); break;
+ case 9: flags = op1001(buffer,pc,opcode); break;
+ case 10: flags = op1010(buffer,pc,opcode); break;
+ case 11: flags = op1011(buffer,pc,opcode); break;
+ case 12: flags = op1100(buffer,pc,opcode); break;
+ case 13: flags = op1101(buffer,pc,opcode); break;
+ case 14: flags = op1110(buffer,pc,opcode); break;
+ default: flags = op1111(buffer,pc,opcode); break;
+ }
+ return 2 | flags | DASMFLAG_SUPPORTED;
+}
+
+CPU_DISASSEMBLE( sh4 )
+{
+ return DasmSH4( buffer, pc, (oprom[1] << 8) | oprom[0] );
+}
+
diff --git a/trunk/src/emu/cpu/sh4/sh4regs.h b/trunk/src/emu/cpu/sh4/sh4regs.h
new file mode 100644
index 00000000000..a8ef7066798
--- /dev/null
+++ b/trunk/src/emu/cpu/sh4/sh4regs.h
@@ -0,0 +1,204 @@
+#pragma once
+
+#ifndef __SH4REGS_H__
+#define __SH4REGS_H__
+
+/* 00000001111111100000000011111100 */
+#define PTEH 0x2000 /* FF000000 */
+#define PTEL 0x2001 /* FF000004 */
+#define TTB 0x2002 /* FF000008 */
+#define TEA 0x2003 /* FF00000C */
+#define MMUCR 0x2004 /* FF000010 */
+#define BASRA 0x2005 /* FF000014 */
+#define BASRB 0x2006 /* FF000018 */
+#define CCR 0x2007 /* FF00001C */
+#define TRA 0x2008 /* FF000020 */
+#define EXPEVT 0x2009 /* FF000024 */
+#define INTEVT 0x200A /* FF000028 */
+#define VERSION 0x200C /* FF000030 */
+#define PTEA 0x200D /* FF000034 */
+#define QACR0 0x200E /* FF000038 */
+#define QACR1 0x200F /* FF00003C */
+#define PRR 0x2011 /* FF000044 */
+#define BARA 0x2400 /* FF200000 */
+#define BAMRA 0x2401 /* FF200004 */
+#define BBRA 0x2402 /* FF200008 */
+#define BARB 0x2403 /* FF20000C */
+#define BAMRB 0x2404 /* FF200010 */
+#define BBRB 0x2405 /* FF200014 */
+#define BDRB 0x2406 /* FF200018 */
+#define BDMRB 0x2407 /* FF20001C */
+#define BRCR 0x2408 /* FF200020 */
+#define BCR1 0x3000 /* FF800000 */
+#define BCR2 0x3001 /* FF800004 */
+#define BCR3 0x3014 /* FF800050 */
+#define BCR4 0x17C /* FE0A00F0 */
+#define WCR1 0x3002 /* FF800008 */
+#define WCR2 0x3003 /* FF80000C */
+#define WCR3 0x3004 /* FF800010 */
+#define MCR 0x3005 /* FF800014 */
+#define PCR 0x3006 /* FF800018 */
+#define RTCSR 0x3007 /* FF80001C */
+#define RTCNT 0x3008 /* FF800020 */
+#define RTCOR 0x3009 /* FF800024 */
+#define RFCR 0x300A /* FF800028 */
+#define PCTRA 0x300B /* FF80002C */
+#define PDTRA 0x300C /* FF800030 */
+#define PCTRB 0x3010 /* FF800040 */
+#define PDTRB 0x3011 /* FF800044 */
+#define GPIOIC 0x3012 /* FF800048 */
+#define SDMR2 0x3200 /* FF900000 */
+#define SDMR3 0x3280 /* FF940000 */
+#define SAR0 0x3400 /* FFA00000 */
+#define DAR0 0x3401 /* FFA00004 */
+#define DMATCR0 0x3402 /* FFA00008 */
+#define CHCR0 0x3403 /* FFA0000C */
+#define SAR1 0x3404 /* FFA00010 */
+#define DAR1 0x3405 /* FFA00014 */
+#define DMATCR1 0x3406 /* FFA00018 */
+#define CHCR1 0x3407 /* FFA0001C */
+#define SAR2 0x3408 /* FFA00020 */
+#define DAR2 0x3409 /* FFA00024 */
+#define DMATCR2 0x340A /* FFA00028 */
+#define CHCR2 0x340B /* FFA0002C */
+#define SAR3 0x340C /* FFA00030 */
+#define DAR3 0x340D /* FFA00034 */
+#define DMATCR3 0x340E /* FFA00038 */
+#define CHCR3 0x340F /* FFA0003C */
+#define DMAOR 0x3410 /* FFA00040 */
+#define SAR4 0x3414 /* FFA00050 */
+#define DAR4 0x3415 /* FFA00054 */
+#define DMATCR4 0x3416 /* FFA00058 */
+#define CHCR4 0x3417 /* FFA0005C */
+#define SAR5 0x3418 /* FFA00060 */
+#define DAR5 0x3419 /* FFA00064 */
+#define DMATCR5 0x341A /* FFA00068 */
+#define CHCR5 0x341B /* FFA0006C */
+#define SAR6 0x341C /* FFA00070 */
+#define DAR6 0x341D /* FFA00074 */
+#define DMATCR6 0x341E /* FFA00078 */
+#define CHCR6 0x341F /* FFA0007C */
+#define SAR7 0x3420 /* FFA00080 */
+#define DAR7 0x3421 /* FFA00084 */
+#define DMATCR7 0x3422 /* FFA00088 */
+#define CHCR7 0x3423 /* FFA0008C */
+#define FRQCR 0x3800 /* FFC00000 */
+#define STBCR 0x3801 /* FFC00004 */
+#define WTCNT 0x3802 /* FFC00008 */
+#define WTCSR 0x3803 /* FFC0000C */
+#define STBCR2 0x3804 /* FFC00010 */
+#define R64CNT 0x3900 /* FFC80000 */
+#define RSECCNT 0x3901 /* FFC80004 */
+#define RMINCNT 0x3902 /* FFC80008 */
+#define RHRCNT 0x3903 /* FFC8000C */
+#define RWKCNT 0x3904 /* FFC80010 */
+#define RDAYCNT 0x3905 /* FFC80014 */
+#define RMONCNT 0x3906 /* FFC80018 */
+#define RYRCNT 0x3907 /* FFC8001C */
+#define RSECAR 0x3908 /* FFC80020 */
+#define RMINAR 0x3909 /* FFC80024 */
+#define RHRAR 0x390A /* FFC80028 */
+#define RWKAR 0x390B /* FFC8002C */
+#define RDAYAR 0x390C /* FFC80030 */
+#define RMONAR 0x390D /* FFC80034 */
+#define RCR1 0x390E /* FFC80038 */
+#define RCR2 0x390F /* FFC8003C */
+#define RCR3 0x3914 /* FFC80050 */
+#define RYRAR 0x3915 /* FFC80054 */
+#define ICR 0x3A00 /* FFD00000 */
+#define IPRA 0x3A01 /* FFD00004 */
+#define IPRB 0x3A02 /* FFD00008 */
+#define IPRC 0x3A03 /* FFD0000C */
+#define IPRD 0x3A04 /* FFD00010 */
+#define INTPRI00 0x100 /* FE080000 */
+#define INTREQ00 0x108 /* FE080020 */
+#define INTMSK00 0x110 /* FE080040 */
+#define INTMSKCLR00 0x118 /* FE080060 */
+#define CLKSTP00 0x140 /* FE0A0000 */
+#define CLKSTPCLR00 0x142 /* FE0A0008 */
+#define TSTR2 0x201 /* FE100004 */
+#define TCOR3 0x202 /* FE100008 */
+#define TCNT3 0x203 /* FE10000C */
+#define TCR3 0x204 /* FE100010 */
+#define TCOR4 0x205 /* FE100014 */
+#define TCNT4 0x206 /* FE100018 */
+#define TCR4 0x207 /* FE10001C */
+#define TOCR 0x3B00 /* FFD80000 */
+#define TSTR 0x3B01 /* FFD80004 */
+#define TCOR0 0x3B02 /* FFD80008 */
+#define TCNT0 0x3B03 /* FFD8000C */
+#define TCR0 0x3B04 /* FFD80010 */
+#define TCOR1 0x3B05 /* FFD80014 */
+#define TCNT1 0x3B06 /* FFD80018 */
+#define TCR1 0x3B07 /* FFD8001C */
+#define TCOR2 0x3B08 /* FFD80020 */
+#define TCNT2 0x3B09 /* FFD80024 */
+#define TCR2 0x3B0A /* FFD80028 */
+#define TCPR2 0x3B0B /* FFD8002C */
+#define SCSMR1 0x3C00 /* FFE00000 */
+#define SCBRR1 0x3C01 /* FFE00004 */
+#define SCSCR1 0x3C02 /* FFE00008 */
+#define SCTDR1 0x3C03 /* FFE0000C */
+#define SCSSR1 0x3C04 /* FFE00010 */
+#define SCRDR1 0x3C05 /* FFE00014 */
+#define SCSCMR1 0x3C06 /* FFE00018 */
+#define SCSPTR1 0x3C07 /* FFE0001C */
+#define SCSMR2 0x3D00 /* FFE80000 */
+#define SCBRR2 0x3D01 /* FFE80004 */
+#define SCSCR2 0x3D02 /* FFE80008 */
+#define SCFTDR2 0x3D03 /* FFE8000C */
+#define SCFSR2 0x3D04 /* FFE80010 */
+#define SCFRDR2 0x3D05 /* FFE80014 */
+#define SCFCR2 0x3D06 /* FFE80018 */
+#define SCFDR2 0x3D07 /* FFE8001C */
+#define SCSPTR2 0x3D08 /* FFE80020 */
+#define SCLSR2 0x3D09 /* FFE80024 */
+#define SDIR 0x3E00 /* FFF00000 */
+#define SDDR 0x3E02 /* FFF00008 */
+#define SDINT 0x3E05 /* FFF00014 */
+#define SIZEREGS 15878
+
+/* bit definitions */
+#define CHCR_SSA 0xe0000000
+#define CHCR_STC 0x10000000
+#define CHCR_DSA 0x0e000000
+#define CHCR_DTC 0x01000000
+#define CHCR_DS 0x00080000
+#define CHCR_RL 0x00040000
+#define CHCR_AM 0x00020000
+#define CHCR_AL 0x00010000
+#define CHCR_DM 0x0000c000
+#define CHCR_SM 0x00003000
+#define CHCR_RS 0x00000f00
+#define CHCR_TM 0x00000080
+#define CHCR_TS 0x00000070
+#define CHCR_IE 0x00000004
+#define CHCR_TE 0x00000002
+#define CHCR_DE 0x00000001
+
+#define DMAOR_DDT 0x8000
+#define DMAOR_PR 0x0300
+#define DMAOR_COD 0x0010
+#define DMAOR_AE 0x0004
+#define DMAOR_NMIF 0x0002
+#define DMAOR_DME 0x0001
+
+#define MMUCR_LRUI 0xfc000000
+#define MMUCR_URB 0x00fc0000
+#define MMUCR_URC 0x0000fc00
+#define MMUCR_SQMD 0x00000200
+#define MMUCR_SV 0x00000100
+#define MMUCR_TI 0x00000004
+#define MMUCR_AT 0x00000001
+
+/* constants */
+#define PVR_SH7091 0x040205c1
+#define PVR_SH7750 0x04020500 // from TN-SH7-361B/E
+#define PVR_SH7750S 0x04020600
+#define PVR_SH7750R 0x04050000
+#define PRR_SH7750R 0x00000100
+#define PVR_SH7751 0x04110000
+#define PVR_SH7751R 0x04050000
+#define PRR_SH7751R 0x00000110
+
+#endif /* __SH4REGS_H__ */
diff --git a/trunk/src/emu/cpu/sharc/compute.c b/trunk/src/emu/cpu/sharc/compute.c
new file mode 100644
index 00000000000..d2fa09a167c
--- /dev/null
+++ b/trunk/src/emu/cpu/sharc/compute.c
@@ -0,0 +1,1338 @@
+/* compute operations */
+
+#include <math.h>
+
+#define CLEAR_ALU_FLAGS() (cpustate->astat &= ~(AZ|AN|AV|AC|AS|AI))
+
+#define SET_FLAG_AZ(r) { cpustate->astat |= (((r) == 0) ? AZ : 0); }
+#define SET_FLAG_AN(r) { cpustate->astat |= (((r) & 0x80000000) ? AN : 0); }
+#define SET_FLAG_AC_ADD(r,a,b) { cpustate->astat |= (((UINT32)r < (UINT32)a) ? AC : 0); }
+#define SET_FLAG_AV_ADD(r,a,b) { cpustate->astat |= (((~((a) ^ (b)) & ((a) ^ (r))) & 0x80000000) ? AV : 0); }
+#define SET_FLAG_AC_SUB(r,a,b) { cpustate->astat |= ((!((UINT32)a < (UINT32)b)) ? AC : 0); }
+#define SET_FLAG_AV_SUB(r,a,b) { cpustate->astat |= ((( ((a) ^ (b)) & ((a) ^ (r))) & 0x80000000) ? AV : 0); }
+
+#define IS_FLOAT_ZERO(r) ((((r) & 0x7fffffff) == 0))
+#define IS_FLOAT_DENORMAL(r) ((((r) & 0x7f800000) == 0) && (((r) & 0x7fffff) != 0))
+#define IS_FLOAT_NAN(r) ((((r) & 0x7f800000) == 0x7f800000) && (((r) & 0x7fffff) != 0))
+#define IS_FLOAT_INFINITY(r) (((r) & 0x7fffffff) == 0x7f800000)
+
+#define CLEAR_MULTIPLIER_FLAGS() (cpustate->astat &= ~(MN|MV|MU|MI))
+
+#define SET_FLAG_MN(r) { cpustate->astat |= (((r) & 0x80000000) ? MN : 0); }
+#define SET_FLAG_MV(r) { cpustate->astat |= ((((UINT32)((r) >> 32) != 0) && ((UINT32)((r) >> 32) != 0xffffffff)) ? MV : 0); }
+
+/* TODO: MU needs 80-bit result */
+#define SET_FLAG_MU(r) { cpustate->astat |= ((((UINT32)((r) >> 32) == 0) && ((UINT32)(r)) != 0) ? MU : 0); }
+
+
+#define FLOAT_SIGN 0x80000000
+#define FLOAT_INFINITY 0x7f800000
+#define FLOAT_MANTISSA 0x007fffff
+
+/*****************************************************************************/
+
+// Mantissa lookup-table for RECIPS opcode
+static const UINT32 recips_mantissa_lookup[128] =
+{
+ 0x007F8000, 0x007E0000, 0x007C0000, 0x007A0000,
+ 0x00780000, 0x00760000, 0x00740000, 0x00720000,
+ 0x00700000, 0x006F0000, 0x006D0000, 0x006B0000,
+ 0x006A0000, 0x00680000, 0x00660000, 0x00650000,
+ 0x00630000, 0x00610000, 0x00600000, 0x005E0000,
+ 0x005D0000, 0x005B0000, 0x005A0000, 0x00590000,
+ 0x00570000, 0x00560000, 0x00540000, 0x00530000,
+ 0x00520000, 0x00500000, 0x004F0000, 0x004E0000,
+ 0x004C0000, 0x004B0000, 0x004A0000, 0x00490000,
+ 0x00470000, 0x00460000, 0x00450000, 0x00440000,
+ 0x00430000, 0x00410000, 0x00400000, 0x003F0000,
+ 0x003E0000, 0x003D0000, 0x003C0000, 0x003B0000,
+ 0x003A0000, 0x00390000, 0x00380000, 0x00370000,
+ 0x00360000, 0x00350000, 0x00340000, 0x00330000,
+ 0x00320000, 0x00310000, 0x00300000, 0x002F0000,
+ 0x002E0000, 0x002D0000, 0x002C0000, 0x002B0000,
+ 0x002A0000, 0x00290000, 0x00280000, 0x00280000,
+ 0x00270000, 0x00260000, 0x00250000, 0x00240000,
+ 0x00230000, 0x00230000, 0x00220000, 0x00210000,
+ 0x00200000, 0x001F0000, 0x001F0000, 0x001E0000,
+ 0x001D0000, 0x001C0000, 0x001C0000, 0x001B0000,
+ 0x001A0000, 0x00190000, 0x00190000, 0x00180000,
+ 0x00170000, 0x00170000, 0x00160000, 0x00150000,
+ 0x00140000, 0x00140000, 0x00130000, 0x00120000,
+ 0x00120000, 0x00110000, 0x00100000, 0x00100000,
+ 0x000F0000, 0x000F0000, 0x000E0000, 0x000D0000,
+ 0x000D0000, 0x000C0000, 0x000C0000, 0x000B0000,
+ 0x000A0000, 0x000A0000, 0x00090000, 0x00090000,
+ 0x00080000, 0x00070000, 0x00070000, 0x00060000,
+ 0x00060000, 0x00050000, 0x00050000, 0x00040000,
+ 0x00040000, 0x00030000, 0x00030000, 0x00020000,
+ 0x00020000, 0x00010000, 0x00010000, 0x00000000,
+};
+
+// Mantissa lookup-table for RSQRTS opcode
+static const UINT32 rsqrts_mantissa_lookup[128] =
+{
+ 0x00350000, 0x00330000, 0x00320000, 0x00300000,
+ 0x002F0000, 0x002E0000, 0x002D0000, 0x002B0000,
+ 0x002A0000, 0x00290000, 0x00280000, 0x00270000,
+ 0x00260000, 0x00250000, 0x00230000, 0x00220000,
+ 0x00210000, 0x00200000, 0x001F0000, 0x001E0000,
+ 0x001E0000, 0x001D0000, 0x001C0000, 0x001B0000,
+ 0x001A0000, 0x00190000, 0x00180000, 0x00170000,
+ 0x00160000, 0x00160000, 0x00150000, 0x00140000,
+ 0x00130000, 0x00130000, 0x00120000, 0x00110000,
+ 0x00100000, 0x00100000, 0x000F0000, 0x000E0000,
+ 0x000E0000, 0x000D0000, 0x000C0000, 0x000B0000,
+ 0x000B0000, 0x000A0000, 0x000A0000, 0x00090000,
+ 0x00080000, 0x00080000, 0x00070000, 0x00070000,
+ 0x00060000, 0x00050000, 0x00050000, 0x00040000,
+ 0x00040000, 0x00030000, 0x00030000, 0x00020000,
+ 0x00020000, 0x00010000, 0x00010000, 0x00000000,
+ 0x007F8000, 0x007E0000, 0x007C0000, 0x007A0000,
+ 0x00780000, 0x00760000, 0x00740000, 0x00730000,
+ 0x00710000, 0x006F0000, 0x006E0000, 0x006C0000,
+ 0x006A0000, 0x00690000, 0x00670000, 0x00660000,
+ 0x00640000, 0x00630000, 0x00620000, 0x00600000,
+ 0x005F0000, 0x005E0000, 0x005C0000, 0x005B0000,
+ 0x005A0000, 0x00590000, 0x00570000, 0x00560000,
+ 0x00550000, 0x00540000, 0x00530000, 0x00520000,
+ 0x00510000, 0x004F0000, 0x004E0000, 0x004D0000,
+ 0x004C0000, 0x004B0000, 0x004A0000, 0x00490000,
+ 0x00480000, 0x00470000, 0x00460000, 0x00450000,
+ 0x00450000, 0x00440000, 0x00430000, 0x00420000,
+ 0x00410000, 0x00400000, 0x003F0000, 0x003E0000,
+ 0x003E0000, 0x003D0000, 0x003C0000, 0x003B0000,
+ 0x003A0000, 0x003A0000, 0x00390000, 0x00380000,
+ 0x00370000, 0x00370000, 0x00360000, 0x00350000,
+};
+
+/*****************************************************************************/
+/* Integer ALU operations */
+
+/* Rn = Rx + Ry */
+INLINE void compute_add(SHARC_REGS *cpustate, int rn, int rx, int ry)
+{
+ UINT32 r = REG(rx) + REG(ry);
+
+ if (cpustate->mode1 & MODE1_ALUSAT)
+ fatalerror("SHARC: compute_add: ALU saturation not implemented !");
+
+ CLEAR_ALU_FLAGS();
+ SET_FLAG_AN(r);
+ SET_FLAG_AZ(r);
+ SET_FLAG_AV_ADD(r, REG(rx), REG(ry));
+ SET_FLAG_AC_ADD(r, REG(rx), REG(ry));
+ REG(rn) = r;
+
+ cpustate->astat &= ~AF;
+}
+
+/* Rn = Rx - Ry */
+INLINE void compute_sub(SHARC_REGS *cpustate, int rn, int rx, int ry)
+{
+ UINT32 r = REG(rx) - REG(ry);
+
+ if (cpustate->mode1 & MODE1_ALUSAT)
+ fatalerror("SHARC: compute_sub: ALU saturation not implemented !");
+
+ CLEAR_ALU_FLAGS();
+ SET_FLAG_AN(r);
+ SET_FLAG_AZ(r);
+ SET_FLAG_AV_SUB(r, REG(rx), REG(ry));
+ SET_FLAG_AC_SUB(r, REG(rx), REG(ry));
+ REG(rn) = r;
+
+ cpustate->astat &= ~AF;
+}
+
+/* Rn = Rx + Ry + CI */
+INLINE void compute_add_ci(SHARC_REGS *cpustate, int rn, int rx, int ry)
+{
+ int c = (cpustate->astat & AC) ? 1 : 0;
+ UINT32 r = REG(rx) + REG(ry) + c;
+
+ if (cpustate->mode1 & MODE1_ALUSAT)
+ fatalerror("SHARC: compute_add_ci: ALU saturation not implemented !");
+
+ CLEAR_ALU_FLAGS();
+ SET_FLAG_AN(r);
+ SET_FLAG_AZ(r);
+ SET_FLAG_AV_ADD(r, REG(rx), REG(ry)+c);
+ SET_FLAG_AC_ADD(r, REG(rx), REG(ry)+c);
+ REG(rn) = r;
+
+ cpustate->astat &= ~AF;
+}
+
+/* Rn = Rx - Ry + CI - 1 */
+INLINE void compute_sub_ci(SHARC_REGS *cpustate, int rn, int rx, int ry)
+{
+ int c = (cpustate->astat & AC) ? 1 : 0;
+ UINT32 r = REG(rx) - REG(ry) + c - 1;
+
+ if (cpustate->mode1 & MODE1_ALUSAT)
+ fatalerror("SHARC: compute_sub_ci: ALU saturation not implemented !");
+
+ CLEAR_ALU_FLAGS();
+ SET_FLAG_AN(r);
+ SET_FLAG_AZ(r);
+ SET_FLAG_AV_SUB(r, REG(rx), REG(ry)+c-1);
+ SET_FLAG_AC_SUB(r, REG(rx), REG(ry)+c-1);
+ REG(rn) = r;
+
+ cpustate->astat &= ~AF;
+}
+
+/* Rn = Rx AND Ry */
+INLINE void compute_and(SHARC_REGS *cpustate, int rn, int rx, int ry)
+{
+ UINT32 r = REG(rx) & REG(ry);
+
+ CLEAR_ALU_FLAGS();
+ SET_FLAG_AN(r);
+ SET_FLAG_AZ(r);
+ REG(rn) = r;
+
+ cpustate->astat &= ~AF;
+}
+
+/* COMP(Rx, Ry) */
+INLINE void compute_comp(SHARC_REGS *cpustate, int rx, int ry)
+{
+ UINT32 comp_accum;
+
+ CLEAR_ALU_FLAGS();
+ if( REG(rx) == REG(ry) )
+ cpustate->astat |= AZ;
+ if( (INT32)REG(rx) < (INT32)REG(ry) )
+ cpustate->astat |= AN;
+
+ // Update ASTAT compare accumulation register
+ comp_accum = (cpustate->astat >> 24) & 0xff;
+ comp_accum >>= 1;
+ if ((cpustate->astat & (AZ|AN)) == 0)
+ {
+ comp_accum |= 0x80;
+ }
+ cpustate->astat &= 0xffffff;
+ cpustate->astat |= comp_accum << 24;
+
+ cpustate->astat &= ~AF;
+}
+
+/* Rn = PASS Rx */
+INLINE void compute_pass(SHARC_REGS *cpustate, int rn, int rx)
+{
+ CLEAR_ALU_FLAGS();
+ /* TODO: floating-point extension field is set to 0 */
+
+ REG(rn) = REG(rx);
+ if (REG(rn) == 0)
+ cpustate->astat |= AZ;
+ if (REG(rn) & 0x80000000)
+ cpustate->astat |= AN;
+
+ cpustate->astat &= ~AF;
+}
+
+/* Rn = Rx XOR Ry */
+INLINE void compute_xor(SHARC_REGS *cpustate, int rn, int rx, int ry)
+{
+ UINT32 r = REG(rx) ^ REG(ry);
+ CLEAR_ALU_FLAGS();
+ SET_FLAG_AN(r);
+ SET_FLAG_AZ(r);
+ REG(rn) = r;
+
+ cpustate->astat &= ~AF;
+}
+
+/* Rn = Rx OR Ry */
+INLINE void compute_or(SHARC_REGS *cpustate, int rn, int rx, int ry)
+{
+ UINT32 r = REG(rx) | REG(ry);
+ CLEAR_ALU_FLAGS();
+ SET_FLAG_AN(r);
+ SET_FLAG_AZ(r);
+ REG(rn) = r;
+
+ cpustate->astat &= ~AF;
+}
+
+/* Rn = Rx + 1 */
+INLINE void compute_inc(SHARC_REGS *cpustate, int rn, int rx)
+{
+ UINT32 r = REG(rx) + 1;
+
+ CLEAR_ALU_FLAGS();
+ SET_FLAG_AN(r);
+ SET_FLAG_AZ(r);
+ SET_FLAG_AV_ADD(r, REG(rx), 1);
+ SET_FLAG_AC_ADD(r, REG(rx), 1);
+
+ REG(rn) = r;
+
+ cpustate->astat &= ~AF;
+}
+
+/* Rn = Rx - 1 */
+INLINE void compute_dec(SHARC_REGS *cpustate, int rn, int rx)
+{
+ UINT32 r = REG(rx) - 1;
+
+ CLEAR_ALU_FLAGS();
+ SET_FLAG_AN(r);
+ SET_FLAG_AZ(r);
+ SET_FLAG_AV_SUB(r, REG(rx), 1);
+ SET_FLAG_AC_SUB(r, REG(rx), 1);
+
+ REG(rn) = r;
+
+ cpustate->astat &= ~AF;
+}
+
+/* Rn = MIN(Rx, Ry) */
+INLINE void compute_min(SHARC_REGS *cpustate, int rn, int rx, int ry)
+{
+ UINT32 r = MIN((INT32)REG(rx), (INT32)REG(ry));
+
+ CLEAR_ALU_FLAGS();
+ SET_FLAG_AN(r);
+ SET_FLAG_AZ(r);
+
+ REG(rn) = r;
+
+ cpustate->astat &= ~AF;
+}
+
+/* Rn = MAX(Rx, Ry) */
+INLINE void compute_max(SHARC_REGS *cpustate, int rn, int rx, int ry)
+{
+ UINT32 r = MAX((INT32)REG(rx), (INT32)REG(ry));
+
+ CLEAR_ALU_FLAGS();
+ SET_FLAG_AN(r);
+ SET_FLAG_AZ(r);
+
+ REG(rn) = r;
+
+ cpustate->astat &= ~AF;
+}
+
+/* Rn = -Rx */
+INLINE void compute_neg(SHARC_REGS *cpustate, int rn, int rx)
+{
+ UINT32 r = -(INT32)(REG(rx));
+
+ CLEAR_ALU_FLAGS();
+ SET_FLAG_AN(r);
+ SET_FLAG_AZ(r);
+ SET_FLAG_AV_SUB(r, 0, REG(rx));
+ SET_FLAG_AC_SUB(r, 0, REG(rx));
+
+ REG(rn) = r;
+
+ cpustate->astat &= ~AF;
+}
+
+/* Rn = NOT Rx */
+INLINE void compute_not(SHARC_REGS *cpustate, int rn, int rx)
+{
+ UINT32 r = ~REG(rx);
+
+ CLEAR_ALU_FLAGS();
+ SET_FLAG_AN(r);
+ SET_FLAG_AZ(r);
+
+ REG(rn) = r;
+
+ cpustate->astat &= ~AF;
+}
+
+/*****************************************************************************/
+/* Floating-point ALU operations */
+
+INLINE UINT32 SCALB(SHARC_REGS *cpustate, SHARC_REG rx, int ry)
+{
+ UINT32 mantissa = rx.r & FLOAT_MANTISSA;
+ UINT32 sign = rx.r & FLOAT_SIGN;
+
+ int exponent = ((rx.r >> 23) & 0xff) - 127;
+ exponent += (INT32)(REG(ry));
+
+ if (exponent > 127)
+ {
+ // overflow
+ cpustate->astat |= AV;
+ return sign | FLOAT_INFINITY;
+ }
+ else if (exponent < -126)
+ {
+ // denormal
+ cpustate->astat |= AZ;
+ return sign;
+ }
+ else
+ {
+ return sign | (((exponent + 127) & 0xff) << 23) | mantissa;
+ }
+}
+
+/* Fn = FLOAT Rx */
+INLINE void compute_float(SHARC_REGS *cpustate, int rn, int rx)
+{
+ // verified
+ FREG(rn) = (float)(INT32)REG(rx);
+
+ CLEAR_ALU_FLAGS();
+ // AN
+ SET_FLAG_AN(REG(rn));
+ // AZ
+ cpustate->astat |= (IS_FLOAT_DENORMAL(REG(rn)) || IS_FLOAT_ZERO(REG(rn))) ? AZ : 0;
+ // AUS
+ cpustate->stky |= (IS_FLOAT_DENORMAL(REG(rn))) ? AUS : 0;
+ /* TODO: AV flag */
+
+ cpustate->astat |= AF;
+}
+
+/* Rn = FIX Fx */
+INLINE void compute_fix(SHARC_REGS *cpustate, int rn, int rx)
+{
+ INT32 alu_i;
+ SHARC_REG r_alu;
+
+ r_alu.f = FREG(rx);
+ if (cpustate->mode1 & MODE1_TRUNCATE)
+ {
+ alu_i = (INT32)(r_alu.f);
+ }
+ else
+ {
+ alu_i = (INT32)(r_alu.f < 0 ? (r_alu.f - 0.5f) : (r_alu.f + 0.5f));
+ }
+
+ CLEAR_ALU_FLAGS();
+ SET_FLAG_AN(alu_i);
+ // AZ
+ SET_FLAG_AZ(alu_i);
+ // AU
+ cpustate->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
+ // AI
+ cpustate->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0;
+ /* TODO: AV flag */
+
+ REG(rn) = alu_i;
+ cpustate->astat |= AF;
+}
+
+/* Rn = FIX Fx BY Ry */
+INLINE void compute_fix_scaled(SHARC_REGS *cpustate, int rn, int rx, int ry)
+{
+ INT32 alu_i;
+ SHARC_REG r_alu;
+
+ r_alu.r = SCALB(cpustate, cpustate->r[rx], ry);
+ if (cpustate->mode1 & MODE1_TRUNCATE)
+ {
+ alu_i = (INT32)(r_alu.f);
+ }
+ else
+ {
+ alu_i = (INT32)(r_alu.f < 0 ? (r_alu.f - 0.5f) : (r_alu.f + 0.5f));
+ }
+
+ CLEAR_ALU_FLAGS();
+ SET_FLAG_AN(alu_i);
+ // AZ
+ SET_FLAG_AZ(alu_i);
+ // AU
+ cpustate->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
+ // AI
+ cpustate->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0;
+ /* TODO: AV flag */
+
+ REG(rn) = alu_i;
+ cpustate->astat |= AF;
+}
+
+/* Fn = FLOAT Rx BY Ry */
+INLINE void compute_float_scaled(SHARC_REGS *cpustate, int rn, int rx, int ry)
+{
+ SHARC_REG x;
+ x.f = (float)(INT32)(REG(rx));
+
+ // verified
+ CLEAR_ALU_FLAGS();
+
+ REG(rn) = SCALB(cpustate, x, ry);
+
+ // AN
+ SET_FLAG_AN(REG(rn));
+ // AZ
+ cpustate->astat |= (IS_FLOAT_DENORMAL(REG(rn)) || IS_FLOAT_ZERO(REG(rn))) ? AZ : 0;
+ // AU
+ cpustate->stky |= (IS_FLOAT_DENORMAL(REG(rn))) ? AUS : 0;
+
+ cpustate->astat |= AF;
+}
+
+/* Rn = LOGB Fx */
+INLINE void compute_logb(SHARC_REGS *cpustate, int rn, int rx)
+{
+ // verified
+ UINT32 r = REG(rx);
+
+ CLEAR_ALU_FLAGS();
+
+ if (IS_FLOAT_INFINITY(REG(rx)))
+ {
+ REG(rn) = FLOAT_INFINITY;
+
+ cpustate->astat |= AV;
+ }
+ else if (IS_FLOAT_ZERO(REG(rx)))
+ {
+ REG(rn) = FLOAT_SIGN | FLOAT_INFINITY;
+
+ cpustate->astat |= AV;
+ }
+ else if (IS_FLOAT_NAN(REG(rx)))
+ {
+ REG(rn) = 0xffffffff;
+
+ cpustate->astat |= AI;
+ cpustate->stky |= AIS;
+ }
+ else
+ {
+ int exponent = (r >> 23) & 0xff;
+ exponent -= 127;
+
+ // AN
+ SET_FLAG_AN(exponent);
+ // AZ
+ SET_FLAG_AZ(exponent);
+
+ REG(rn) = exponent;
+ }
+ cpustate->astat |= AF;
+}
+
+/* Fn = SCALB Fx BY Fy */
+INLINE void compute_scalb(SHARC_REGS *cpustate, int rn, int rx, int ry)
+{
+ // verified
+ SHARC_REG r;
+ CLEAR_ALU_FLAGS();
+
+ if (IS_FLOAT_NAN(REG(rx)))
+ {
+ cpustate->astat |= AI;
+ cpustate->stky |= AIS;
+
+ REG(rn) = 0xffffffff;
+ }
+ else
+ {
+ r.r = SCALB(cpustate, cpustate->r[rx], ry);
+
+ // AN
+ SET_FLAG_AN(r.r);
+ // AZ
+ cpustate->astat |= IS_FLOAT_ZERO(r.r) ? AZ : 0;
+ // AUS
+ cpustate->stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0;
+
+ FREG(rn) = r.f;
+ }
+ cpustate->astat |= AF;
+}
+
+/* Fn = Fx + Fy */
+INLINE void compute_fadd(SHARC_REGS *cpustate, int rn, int rx, int ry)
+{
+ SHARC_REG r;
+ r.f = FREG(rx) + FREG(ry);
+
+ CLEAR_ALU_FLAGS();
+ // AN
+ cpustate->astat |= (r.f < 0.0f) ? AN : 0;
+ // AZ
+ cpustate->astat |= (IS_FLOAT_DENORMAL(r.r) || IS_FLOAT_ZERO(r.r)) ? AZ : 0;
+ // AUS
+ cpustate->stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0;
+ // AI
+ cpustate->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
+ /* TODO: AV flag */
+
+ // AIS
+ if (cpustate->astat & AI) cpustate->stky |= AIS;
+
+ FREG(rn) = r.f;
+ cpustate->astat |= AF;
+}
+
+/* Fn = Fx - Fy */
+INLINE void compute_fsub(SHARC_REGS *cpustate, int rn, int rx, int ry)
+{
+ SHARC_REG r;
+ r.f = FREG(rx) - FREG(ry);
+
+ CLEAR_ALU_FLAGS();
+ // AN
+ cpustate->astat |= (r.f < 0.0f) ? AN : 0;
+ // AZ
+ cpustate->astat |= (IS_FLOAT_DENORMAL(r.r) || IS_FLOAT_ZERO(r.r)) ? AZ : 0;
+ // AUS
+ cpustate->stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0;
+ // AI
+ cpustate->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
+ /* TODO: AV flag */
+
+ // AIS
+ if (cpustate->astat & AI) cpustate->stky |= AIS;
+
+ FREG(rn) = r.f;
+ cpustate->astat |= AF;
+}
+
+/* Fn = -Fx */
+INLINE void compute_fneg(SHARC_REGS *cpustate, int rn, int rx)
+{
+ SHARC_REG r;
+ r.f = -FREG(rx);
+
+ CLEAR_ALU_FLAGS();
+ // AZ
+ cpustate->astat |= (IS_FLOAT_ZERO(r.r)) ? AZ : 0;
+ // AN
+ cpustate->astat |= (r.f < 0.0f) ? AN : 0;
+ // AI
+ cpustate->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0;
+
+ // AIS
+ if (cpustate->astat & AI) cpustate->stky |= AIS;
+
+ FREG(rn) = r.f;
+ cpustate->astat |= AF;
+}
+
+/* COMP(Fx, Fy) */
+INLINE void compute_fcomp(SHARC_REGS *cpustate, int rx, int ry)
+{
+ UINT32 comp_accum;
+
+ CLEAR_ALU_FLAGS();
+ // AZ
+ if( FREG(rx) == FREG(ry) )
+ cpustate->astat |= AZ;
+ // AN
+ if( FREG(rx) < FREG(ry) )
+ cpustate->astat |= AN;
+ // AI
+ cpustate->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
+
+ // AIS
+ if (cpustate->astat & AI) cpustate->stky |= AIS;
+
+ // Update ASTAT compare accumulation register
+ comp_accum = (cpustate->astat >> 24) & 0xff;
+ comp_accum >>= 1;
+ if ((cpustate->astat & (AZ|AN)) == 0)
+ {
+ comp_accum |= 0x80;
+ }
+ cpustate->astat &= 0xffffff;
+ cpustate->astat |= comp_accum << 24;
+ cpustate->astat |= AF;
+}
+
+/* Fn = ABS(Fx + Fy) */
+INLINE void compute_fabs_plus(SHARC_REGS *cpustate, int rn, int rx, int ry)
+{
+ SHARC_REG r;
+ r.f = fabs(FREG(rx) + FREG(ry));
+
+ CLEAR_ALU_FLAGS();
+ // AZ
+ cpustate->astat |= (IS_FLOAT_DENORMAL(r.r) || IS_FLOAT_ZERO(r.r)) ? AZ : 0;
+ // AUS
+ cpustate->stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0;
+ // AI
+ cpustate->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
+ /* TODO: AV flag */
+
+ // AIS
+ if (cpustate->astat & AI) cpustate->stky |= AIS;
+
+ FREG(rn) = r.f;
+ cpustate->astat |= AF;
+}
+
+/* Fn = MAX(Fx, Fy) */
+INLINE void compute_fmax(SHARC_REGS *cpustate, int rn, int rx, int ry)
+{
+ SHARC_REG r_alu;
+
+ r_alu.f = MAX(FREG(rx), FREG(ry));
+
+ CLEAR_ALU_FLAGS();
+ cpustate->astat |= (r_alu.f < 0.0f) ? AN : 0;
+ // AZ
+ cpustate->astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0;
+ // AU
+ cpustate->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
+ // AI
+ cpustate->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
+ /* TODO: AV flag */
+
+ FREG(rn) = r_alu.f;
+ cpustate->astat |= AF;
+}
+
+/* Fn = MIN(Fx, Fy) */
+INLINE void compute_fmin(SHARC_REGS *cpustate, int rn, int rx, int ry)
+{
+ SHARC_REG r_alu;
+
+ r_alu.f = MIN(FREG(rx), FREG(ry));
+
+ CLEAR_ALU_FLAGS();
+ cpustate->astat |= (r_alu.f < 0.0f) ? AN : 0;
+ // AZ
+ cpustate->astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0;
+ // AU
+ cpustate->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
+ // AI
+ cpustate->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
+ /* TODO: AV flag */
+
+ FREG(rn) = r_alu.f;
+ cpustate->astat |= AF;
+}
+
+/* Fn = CLIP Fx BY Fy */
+INLINE void compute_fclip(SHARC_REGS *cpustate, int rn, int rx, int ry)
+{
+ SHARC_REG r_alu;
+
+ if (FREG(rx) < fabs(FREG(ry)))
+ {
+ r_alu.f = FREG(rx);
+ }
+ else
+ {
+ if (FREG(rx) >= 0.0f)
+ {
+ r_alu.f = fabs(FREG(ry));
+ }
+ else
+ {
+ r_alu.f = -fabs(FREG(ry));
+ }
+ }
+
+
+ CLEAR_ALU_FLAGS();
+ SET_FLAG_AN(r_alu.r);
+ // AZ
+ cpustate->astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0;
+ // AU
+ cpustate->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
+ // AI
+ cpustate->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
+
+ FREG(rn) = r_alu.f;
+ cpustate->astat |= AF;
+}
+
+/* Fn = RECIPS Fx */
+INLINE void compute_recips(SHARC_REGS *cpustate, int rn, int rx)
+{
+ // verified
+ UINT32 r;
+
+ CLEAR_ALU_FLAGS();
+
+ if (IS_FLOAT_NAN(REG(rx)))
+ {
+ // NaN
+ r = 0xffffffff;
+
+ // AI
+ cpustate->astat |= AI;
+
+ // AIS
+ cpustate->stky |= AIS;
+ }
+ else if (IS_FLOAT_ZERO(REG(rx)))
+ {
+ // +- Zero
+ r = (REG(rx) & FLOAT_SIGN) | FLOAT_INFINITY;
+
+ cpustate->astat |= AZ;
+ }
+ else
+ {
+ UINT32 mantissa = REG(rx) & 0x7fffff;
+ UINT32 exponent = (REG(rx) >> 23) & 0xff;
+ UINT32 sign = REG(rx) & FLOAT_SIGN;
+
+ UINT32 res_mantissa = recips_mantissa_lookup[mantissa >> 16];
+
+ int res_exponent = -(exponent - 127) - 1;
+ if (res_exponent > 125 || res_exponent < -126)
+ {
+ res_exponent = 0;
+ res_mantissa = 0;
+ }
+ else
+ {
+ res_exponent = (res_exponent + 127) & 0xff;
+ }
+
+ r = sign | (res_exponent << 23) | res_mantissa;
+
+ SET_FLAG_AN(REG(rx));
+ // AZ & AV
+ cpustate->astat |= (IS_FLOAT_ZERO(r)) ? AZ : 0;
+ cpustate->astat |= (IS_FLOAT_ZERO(REG(rx))) ? AV : 0;
+ // AI
+ cpustate->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0;
+
+ // AIS
+ if (cpustate->astat & AI) cpustate->stky |= AIS;
+ }
+
+ // AF
+ cpustate->astat |= AF;
+
+ REG(rn) = r;
+}
+
+/* Fn = RSQRTS Fx */
+INLINE void compute_rsqrts(SHARC_REGS *cpustate, int rn, int rx)
+{
+ // verified
+ UINT32 r;
+
+ if ((UINT32)(REG(rx)) > 0x80000000)
+ {
+ // non-zero negative
+ r = 0xffffffff;
+ }
+ else if (IS_FLOAT_NAN(REG(rx)))
+ {
+ // NaN
+ r = 0xffffffff;
+ }
+ else
+ {
+ UINT32 mantissa = REG(rx) & 0xffffff; // mantissa + LSB of biased exponent
+ UINT32 exponent = (REG(rx) >> 23) & 0xff;
+ UINT32 sign = REG(rx) & FLOAT_SIGN;
+
+ UINT32 res_mantissa = rsqrts_mantissa_lookup[mantissa >> 17];
+
+ int res_exponent = -((exponent - 127) / 2) - 1;
+ res_exponent = (res_exponent + 127) & 0xff;
+
+ r = sign | (res_exponent << 23) | res_mantissa;
+ }
+
+ CLEAR_ALU_FLAGS();
+ // AN
+ cpustate->astat |= (REG(rx) == 0x80000000) ? AN : 0;
+ // AZ & AV
+ cpustate->astat |= (IS_FLOAT_ZERO(r)) ? AZ : 0;
+ cpustate->astat |= (IS_FLOAT_ZERO(REG(rx))) ? AV : 0;
+ // AI
+ cpustate->astat |= (IS_FLOAT_NAN(REG(rx)) || (REG(rx) & 0x80000000)) ? AI : 0;
+ // AIS
+ if (cpustate->astat & AI) cpustate->stky |= AIS;
+ // AF
+ cpustate->astat |= AF;
+
+ REG(rn) = r;
+}
+
+
+/* Fn = PASS Fx */
+INLINE void compute_fpass(SHARC_REGS *cpustate, int rn, int rx)
+{
+ SHARC_REG r;
+ r.f = FREG(rx);
+
+ CLEAR_ALU_FLAGS();
+ // AN
+ cpustate->astat |= (r.f < 0.0f) ? AN : 0;
+ // AZ
+ cpustate->astat |= (IS_FLOAT_ZERO(r.r)) ? AZ : 0;
+ // AI
+ cpustate->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0;
+
+ FREG(rn) = r.f;
+ cpustate->astat |= AF;
+}
+
+/* Fn = ABS Fx */
+INLINE void compute_fabs(SHARC_REGS *cpustate, int rn, int rx)
+{
+ SHARC_REG r;
+ r.f = fabs(FREG(rx));
+
+ CLEAR_ALU_FLAGS();
+ // AN
+ cpustate->astat |= (r.f < 0.0f) ? AN : 0;
+ // AZ
+ cpustate->astat |= (IS_FLOAT_ZERO(r.r)) ? AZ : 0;
+ // AI
+ cpustate->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0;
+
+ FREG(rn) = r.f;
+ cpustate->astat |= AF;
+}
+
+/*****************************************************************************/
+/* Multiplier opcodes */
+
+/* Rn = (unsigned)Rx * (unsigned)Ry, integer, no rounding */
+INLINE void compute_mul_uuin(SHARC_REGS *cpustate, int rn, int rx, int ry)
+{
+ UINT64 r = (UINT64)(UINT32)REG(rx) * (UINT64)(UINT32)REG(ry);
+
+ CLEAR_MULTIPLIER_FLAGS();
+ SET_FLAG_MN((UINT32)r);
+ SET_FLAG_MV(r);
+ SET_FLAG_MU(r);
+
+ REG(rn) = (UINT32)(r);
+}
+
+/* Rn = (signed)Rx * (signed)Ry, integer, no rounding */
+INLINE void compute_mul_ssin(SHARC_REGS *cpustate, int rn, int rx, int ry)
+{
+ UINT64 r = (INT64)(INT32)REG(rx) * (INT64)(INT32)REG(ry);
+
+ CLEAR_MULTIPLIER_FLAGS();
+ SET_FLAG_MN((UINT32)r);
+ SET_FLAG_MV(r);
+ SET_FLAG_MU(r);
+
+ REG(rn) = (UINT32)(r);
+}
+
+/* MRF + (signed)Rx * (signed)Ry, integer, no rounding */
+INLINE UINT32 compute_mrf_plus_mul_ssin(SHARC_REGS *cpustate, int rx, int ry)
+{
+ UINT64 r = cpustate->mrf + ((INT64)(INT32)REG(rx) * (INT64)(INT32)REG(ry));
+
+ CLEAR_MULTIPLIER_FLAGS();
+ SET_FLAG_MN((UINT32)r);
+ SET_FLAG_MV(r);
+ SET_FLAG_MU(r);
+
+ return (UINT32)(r);
+}
+
+/* MRB + (signed)Rx * (signed)Ry, integer, no rounding */
+INLINE UINT32 compute_mrb_plus_mul_ssin(SHARC_REGS *cpustate, int rx, int ry)
+{
+ INT64 r = cpustate->mrb + ((INT64)(INT32)REG(rx) * (INT64)(INT32)REG(ry));
+
+ CLEAR_MULTIPLIER_FLAGS();
+ SET_FLAG_MN((UINT32)r);
+ SET_FLAG_MV(r);
+ SET_FLAG_MU(r);
+
+ return (UINT32)(r);
+}
+
+/* Fn = Fx * Fy */
+INLINE void compute_fmul(SHARC_REGS *cpustate, int rn, int rx, int ry)
+{
+ FREG(rn) = FREG(rx) * FREG(ry);
+
+ CLEAR_MULTIPLIER_FLAGS();
+ SET_FLAG_MN(REG(rn));
+ /* TODO: MV flag */
+ /* TODO: MU flag */
+ /* TODO: MI flag */
+}
+
+/*****************************************************************************/
+
+/* multi function opcodes */
+
+/* integer*/
+INLINE void compute_multi_mr_to_reg(SHARC_REGS *cpustate, int ai, int rk)
+{
+ switch(ai)
+ {
+ case 0: SET_UREG(cpustate, rk, (UINT32)(cpustate->mrf)); break;
+ case 1: SET_UREG(cpustate, rk, (UINT32)(cpustate->mrf >> 32)); break;
+ case 2: fatalerror("SHARC: tried to load MR2F"); break;
+ case 4: SET_UREG(cpustate, rk, (UINT32)(cpustate->mrb)); break;
+ case 5: SET_UREG(cpustate, rk, (UINT32)(cpustate->mrb >> 32)); break;
+ case 6: fatalerror("SHARC: tried to load MR2B"); break;
+ default: fatalerror("SHARC: unknown ai %d in mr_to_reg", ai);
+ }
+
+ CLEAR_MULTIPLIER_FLAGS();
+}
+
+INLINE void compute_multi_reg_to_mr(SHARC_REGS *cpustate, int ai, int rk)
+{
+ switch(ai)
+ {
+ case 0: cpustate->mrf &= ~0xffffffff; cpustate->mrf |= GET_UREG(cpustate, rk); break;
+ case 1: cpustate->mrf &= 0xffffffff; cpustate->mrf |= (UINT64)(GET_UREG(cpustate, rk)) << 32; break;
+ case 2: fatalerror("SHARC: tried to write MR2F"); break;
+ case 4: cpustate->mrb &= ~0xffffffff; cpustate->mrb |= GET_UREG(cpustate, rk); break;
+ case 5: cpustate->mrb &= 0xffffffff; cpustate->mrb |= (UINT64)(GET_UREG(cpustate, rk)) << 32; break;
+ case 6: fatalerror("SHARC: tried to write MR2B"); break;
+ default: fatalerror("SHARC: unknown ai %d in reg_to_mr", ai);
+ }
+
+ CLEAR_MULTIPLIER_FLAGS();
+}
+
+/* Ra = Rx + Ry, Rs = Rx - Ry */
+INLINE void compute_dual_add_sub(SHARC_REGS *cpustate, int ra, int rs, int rx, int ry)
+{
+ UINT32 r_add = REG(rx) + REG(ry);
+ UINT32 r_sub = REG(rx) - REG(ry);
+
+ CLEAR_ALU_FLAGS();
+ if (r_add == 0 || r_sub == 0)
+ {
+ cpustate->astat |= AZ;
+ }
+ if (r_add & 0x80000000 || r_sub & 0x80000000)
+ {
+ cpustate->astat |= AN;
+ }
+ if (((~(REG(rx) ^ REG(ry)) & (REG(rx) ^ r_add)) & 0x80000000) ||
+ (( (REG(rx) ^ REG(ry)) & (REG(rx) ^ r_sub)) & 0x80000000))
+ {
+ cpustate->astat |= AV;
+ }
+ if (((UINT32)r_add < (UINT32)REG(rx)) ||
+ (!((UINT32)r_sub < (UINT32)REG(rx))))
+ {
+ cpustate->astat |= AC;
+ }
+
+ REG(ra) = r_add;
+ REG(rs) = r_sub;
+
+ cpustate->astat &= ~AF;
+}
+
+/* Rm = (signed)Rxm * (signed)Rym, fractional, rounding, Ra = Rxa + Rya */
+INLINE void compute_mul_ssfr_add(SHARC_REGS *cpustate, int rm, int rxm, int rym, int ra, int rxa, int rya)
+{
+ UINT32 r_mul = (UINT32)(((INT64)(REG(rxm)) * (INT64)(REG(rym))) >> 31);
+ UINT32 r_add = REG(rxa) + REG(rya);
+
+ CLEAR_MULTIPLIER_FLAGS();
+ SET_FLAG_MN(r_mul);
+ /* TODO: MV flag */
+ /* TODO: MU flag */
+ /* TODO: MI flag */
+
+ CLEAR_ALU_FLAGS();
+ SET_FLAG_AN(r_add);
+ SET_FLAG_AZ(r_add);
+ SET_FLAG_AV_ADD(r_add, REG(rxa), REG(rya));
+ SET_FLAG_AC_ADD(r_add, REG(rxa), REG(rya));
+
+
+ REG(rm) = r_mul;
+ REG(ra) = r_add;
+
+ cpustate->astat &= ~AF;
+}
+
+/* Rm = (signed)Rxm * (signed)Rym, fractional, rounding, Ra = Rxa - Rya */
+INLINE void compute_mul_ssfr_sub(SHARC_REGS *cpustate, int rm, int rxm, int rym, int ra, int rxa, int rya)
+{
+ UINT32 r_mul = (UINT32)(((INT64)(REG(rxm)) * (INT64)(REG(rym))) >> 31);
+ UINT32 r_sub = REG(rxa) - REG(rya);
+
+ CLEAR_MULTIPLIER_FLAGS();
+ SET_FLAG_MN(r_mul);
+ /* TODO: MV flag */
+ /* TODO: MU flag */
+ /* TODO: MI flag */
+
+ CLEAR_ALU_FLAGS();
+ SET_FLAG_AN(r_sub);
+ SET_FLAG_AZ(r_sub);
+ SET_FLAG_AV_SUB(r_sub, REG(rxa), REG(rya));
+ SET_FLAG_AC_SUB(r_sub, REG(rxa), REG(rya));
+
+
+ REG(rm) = r_mul;
+ REG(ra) = r_sub;
+
+ cpustate->astat &= ~AF;
+}
+
+
+/* floating-point */
+
+/* Fa = Fx + Fy, Fs = Fx - Fy */
+INLINE void compute_dual_fadd_fsub(SHARC_REGS *cpustate, int ra, int rs, int rx, int ry)
+{
+ SHARC_REG r_add, r_sub;
+ r_add.f = FREG(rx) + FREG(ry);
+ r_sub.f = FREG(rx) - FREG(ry);
+
+ CLEAR_ALU_FLAGS();
+ // AN
+ cpustate->astat |= ((r_add.f < 0.0f) || (r_sub.f < 0.0f)) ? AN : 0;
+ // AZ
+ cpustate->astat |= (IS_FLOAT_DENORMAL(r_add.r) || IS_FLOAT_ZERO(r_add.r) ||
+ IS_FLOAT_DENORMAL(r_sub.r) || IS_FLOAT_ZERO(r_sub.r)) ? AZ : 0;
+ // AUS
+ cpustate->stky |= (IS_FLOAT_DENORMAL(r_add.r) || IS_FLOAT_DENORMAL(r_sub.r)) ? AUS : 0;
+ // AI
+ cpustate->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
+ /* TODO: AV flag */
+
+ // AIS
+ if (cpustate->astat & AI) cpustate->stky |= AIS;
+
+ FREG(ra) = r_add.f;
+ FREG(rs) = r_sub.f;
+ cpustate->astat |= AF;
+}
+
+/* Fm = Fxm * Fym, Fa = Fxa + Fya */
+INLINE void compute_fmul_fadd(SHARC_REGS *cpustate, int fm, int fxm, int fym, int fa, int fxa, int fya)
+{
+ SHARC_REG r_mul, r_add;
+ r_mul.f = FREG(fxm) * FREG(fym);
+ r_add.f = FREG(fxa) + FREG(fya);
+
+ CLEAR_MULTIPLIER_FLAGS();
+ SET_FLAG_MN(r_mul.r);
+ /* TODO: MV flag */
+ /* TODO: MU flag */
+ /* TODO: MI flag */
+
+ CLEAR_ALU_FLAGS();
+ cpustate->astat |= (r_add.f < 0.0f) ? AN : 0;
+ // AZ
+ cpustate->astat |= (IS_FLOAT_DENORMAL(r_add.r) || IS_FLOAT_ZERO(r_add.r)) ? AZ : 0;
+ // AU
+ cpustate->stky |= (IS_FLOAT_DENORMAL(r_add.r)) ? AUS : 0;
+ // AI
+ cpustate->astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0;
+ /* TODO: AV flag */
+
+ // AIS
+ if (cpustate->astat & AI) cpustate->stky |= AIS;
+
+ FREG(fm) = r_mul.f;
+ FREG(fa) = r_add.f;
+ cpustate->astat |= AF;
+}
+
+/* Fm = Fxm * Fym, Fa = Fxa - Fya */
+INLINE void compute_fmul_fsub(SHARC_REGS *cpustate, int fm, int fxm, int fym, int fa, int fxa, int fya)
+{
+ SHARC_REG r_mul, r_sub;
+ r_mul.f = FREG(fxm) * FREG(fym);
+ r_sub.f = FREG(fxa) - FREG(fya);
+
+ CLEAR_MULTIPLIER_FLAGS();
+ SET_FLAG_MN(r_mul.r);
+ /* TODO: MV flag */
+ /* TODO: MU flag */
+ /* TODO: MI flag */
+
+ CLEAR_ALU_FLAGS();
+ cpustate->astat |= (r_sub.f < 0.0f) ? AN : 0;
+ // AZ
+ cpustate->astat |= (IS_FLOAT_DENORMAL(r_sub.r) || IS_FLOAT_ZERO(r_sub.r)) ? AZ : 0;
+ // AU
+ cpustate->stky |= (IS_FLOAT_DENORMAL(r_sub.r)) ? AUS : 0;
+ // AI
+ cpustate->astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0;
+ /* TODO: AV flag */
+
+ // AIS
+ if (cpustate->astat & AI) cpustate->stky |= AIS;
+
+ FREG(fm) = r_mul.f;
+ FREG(fa) = r_sub.f;
+ cpustate->astat |= AF;
+}
+
+/* Fm = Fxm * Fym, Fa = FLOAT Fxa BY Fya */
+INLINE void compute_fmul_float_scaled(SHARC_REGS *cpustate, int fm, int fxm, int fym, int fa, int fxa, int fya)
+{
+ SHARC_REG x;
+ SHARC_REG r_mul, r_alu;
+ r_mul.f = FREG(fxm) * FREG(fym);
+
+ x.f = (float)(INT32)REG(fxa);
+
+ r_alu.r = SCALB(cpustate, x, fya);
+
+ CLEAR_MULTIPLIER_FLAGS();
+ SET_FLAG_MN(r_mul.r);
+ /* TODO: MV flag */
+ /* TODO: MU flag */
+ /* TODO: MI flag */
+
+ CLEAR_ALU_FLAGS();
+ cpustate->astat |= (r_alu.f < 0.0f) ? AN : 0;
+ // AZ
+ cpustate->astat |= (IS_FLOAT_DENORMAL(r_alu.r) || IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0;
+ // AU
+ cpustate->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
+ /* TODO: set AV if overflowed */
+
+ FREG(fm) = r_mul.f;
+ FREG(fa) = r_alu.f;
+ cpustate->astat |= AF;
+}
+
+/* Fm = Fxm * Fym, Fa = FIX Fxa BY Fya */
+INLINE void compute_fmul_fix_scaled(SHARC_REGS *cpustate, int fm, int fxm, int fym, int fa, int fxa, int fya)
+{
+ INT32 alu_i;
+ SHARC_REG r_mul, r_alu;
+ r_mul.f = FREG(fxm) * FREG(fym);
+
+ r_alu.r = SCALB(cpustate, cpustate->r[fxa], fya);
+
+ if (cpustate->mode1 & MODE1_TRUNCATE)
+ {
+ alu_i = (INT32)(r_alu.f);
+ }
+ else
+ {
+ alu_i = (INT32)(r_alu.f < 0 ? (r_alu.f - 0.5f) : (r_alu.f + 0.5f));
+ }
+
+ CLEAR_MULTIPLIER_FLAGS();
+ SET_FLAG_MN(r_mul.r);
+ /* TODO: MV flag */
+ /* TODO: MU flag */
+ /* TODO: MI flag */
+
+ CLEAR_ALU_FLAGS();
+ SET_FLAG_AN(alu_i);
+ // AZ
+ SET_FLAG_AZ(alu_i);
+ // AU
+ cpustate->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
+ // AI
+ cpustate->astat |= (IS_FLOAT_NAN(REG(fxa))) ? AI : 0;
+ /* TODO: AV flag */
+
+ FREG(fm) = r_mul.f;
+ REG(fa) = alu_i;
+ cpustate->astat |= AF;
+}
+
+
+/* Fm = Fxm * Fym, Fa = MAX(Fxa, Fya) */
+INLINE void compute_fmul_fmax(SHARC_REGS *cpustate, int fm, int fxm, int fym, int fa, int fxa, int fya)
+{
+ SHARC_REG r_mul, r_alu;
+ r_mul.f = FREG(fxm) * FREG(fym);
+
+ r_alu.f = MAX(FREG(fxa), FREG(fya));
+
+ CLEAR_MULTIPLIER_FLAGS();
+ SET_FLAG_MN(r_mul.r);
+ /* TODO: MV flag */
+ /* TODO: MU flag */
+ /* TODO: MI flag */
+
+ CLEAR_ALU_FLAGS();
+ cpustate->astat |= (r_alu.f < 0.0f) ? AN : 0;
+ // AZ
+ cpustate->astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0;
+ // AU
+ cpustate->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
+ // AI
+ cpustate->astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0;
+ /* TODO: AV flag */
+
+ FREG(fm) = r_mul.f;
+ FREG(fa) = r_alu.f;
+ cpustate->astat |= AF;
+}
+
+
+/* Fm = Fxm * Fym, Fa = MIN(Fxa, Fya) */
+INLINE void compute_fmul_fmin(SHARC_REGS *cpustate, int fm, int fxm, int fym, int fa, int fxa, int fya)
+{
+ SHARC_REG r_mul, r_alu;
+ r_mul.f = FREG(fxm) * FREG(fym);
+
+ r_alu.f = MIN(FREG(fxa), FREG(fya));
+
+ CLEAR_MULTIPLIER_FLAGS();
+ SET_FLAG_MN(r_mul.r);
+ /* TODO: MV flag */
+ /* TODO: MU flag */
+ /* TODO: MI flag */
+
+ CLEAR_ALU_FLAGS();
+ cpustate->astat |= (r_alu.f < 0.0f) ? AN : 0;
+ // AZ
+ cpustate->astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0;
+ // AU
+ cpustate->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
+ // AI
+ cpustate->astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0;
+ /* TODO: AV flag */
+
+ FREG(fm) = r_mul.f;
+ FREG(fa) = r_alu.f;
+ cpustate->astat |= AF;
+}
+
+
+
+/* Fm = Fxm * Fym, Fa = Fxa + Fya, Fs = Fxa - Fya */
+INLINE void compute_fmul_dual_fadd_fsub(SHARC_REGS *cpustate, int fm, int fxm, int fym, int fa, int fs, int fxa, int fya)
+{
+ SHARC_REG r_mul, r_add, r_sub;
+ r_mul.f = FREG(fxm) * FREG(fym);
+ r_add.f = FREG(fxa) + FREG(fya);
+ r_sub.f = FREG(fxa) - FREG(fya);
+
+ CLEAR_MULTIPLIER_FLAGS();
+ SET_FLAG_MN(r_mul.r);
+ /* TODO: MV flag */
+ /* TODO: MU flag */
+ /* TODO: MI flag */
+
+ CLEAR_ALU_FLAGS();
+ // AN
+ cpustate->astat |= ((r_add.r < 0.0f) || (r_sub.r < 0.0f)) ? AN : 0;
+ // AZ
+ cpustate->astat |= (IS_FLOAT_DENORMAL(r_add.r) || IS_FLOAT_ZERO(r_add.r) ||
+ IS_FLOAT_DENORMAL(r_sub.r) || IS_FLOAT_ZERO(r_sub.r)) ? AZ : 0;
+ // AUS
+ cpustate->stky |= (IS_FLOAT_DENORMAL(r_add.r) || IS_FLOAT_DENORMAL(r_sub.r)) ? AUS : 0;
+ // AI
+ cpustate->astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0;
+ /* TODO: AV flag */
+
+ // AIS
+ if (cpustate->astat & AI) cpustate->stky |= AIS;
+
+ FREG(fm) = r_mul.f;
+ FREG(fa) = r_add.f;
+ FREG(fs) = r_sub.f;
+ cpustate->astat |= AF;
+}
diff --git a/trunk/src/emu/cpu/sharc/sharc.c b/trunk/src/emu/cpu/sharc/sharc.c
new file mode 100644
index 00000000000..70fbdc3959e
--- /dev/null
+++ b/trunk/src/emu/cpu/sharc/sharc.c
@@ -0,0 +1,1322 @@
+/* Analog Devices ADSP-2106x SHARC emulator v2.0
+
+ Written by Ville Linde
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "sharc.h"
+
+CPU_DISASSEMBLE( sharc );
+
+enum
+{
+ SHARC_PC=1, SHARC_PCSTK, SHARC_MODE1, SHARC_MODE2,
+ SHARC_ASTAT, SHARC_STKY, SHARC_IRPTL, SHARC_IMASK,
+ SHARC_IMASKP, SHARC_USTAT1, SHARC_USTAT2, SHARC_LCNTR,
+ SHARC_R0, SHARC_R1, SHARC_R2, SHARC_R3,
+ SHARC_R4, SHARC_R5, SHARC_R6, SHARC_R7,
+ SHARC_R8, SHARC_R9, SHARC_R10, SHARC_R11,
+ SHARC_R12, SHARC_R13, SHARC_R14, SHARC_R15,
+ SHARC_SYSCON, SHARC_SYSSTAT, SHARC_MRF, SHARC_MRB,
+ SHARC_STSTKP, SHARC_PCSTKP, SHARC_LSTKP,
+ SHARC_FADDR, SHARC_DADDR,
+ SHARC_I0, SHARC_I1, SHARC_I2, SHARC_I3,
+ SHARC_I4, SHARC_I5, SHARC_I6, SHARC_I7,
+ SHARC_I8, SHARC_I9, SHARC_I10, SHARC_I11,
+ SHARC_I12, SHARC_I13, SHARC_I14, SHARC_I15,
+ SHARC_M0, SHARC_M1, SHARC_M2, SHARC_M3,
+ SHARC_M4, SHARC_M5, SHARC_M6, SHARC_M7,
+ SHARC_M8, SHARC_M9, SHARC_M10, SHARC_M11,
+ SHARC_M12, SHARC_M13, SHARC_M14, SHARC_M15,
+ SHARC_L0, SHARC_L1, SHARC_L2, SHARC_L3,
+ SHARC_L4, SHARC_L5, SHARC_L6, SHARC_L7,
+ SHARC_L8, SHARC_L9, SHARC_L10, SHARC_L11,
+ SHARC_L12, SHARC_L13, SHARC_L14, SHARC_L15,
+ SHARC_B0, SHARC_B1, SHARC_B2, SHARC_B3,
+ SHARC_B4, SHARC_B5, SHARC_B6, SHARC_B7,
+ SHARC_B8, SHARC_B9, SHARC_B10, SHARC_B11,
+ SHARC_B12, SHARC_B13, SHARC_B14, SHARC_B15,
+};
+
+typedef struct
+{
+ UINT32 i[8];
+ UINT32 m[8];
+ UINT32 b[8];
+ UINT32 l[8];
+} SHARC_DAG;
+
+typedef union
+{
+ INT32 r;
+ float f;
+} SHARC_REG;
+
+typedef struct
+{
+ UINT32 control;
+ UINT32 int_index;
+ UINT32 int_modifier;
+ UINT32 int_count;
+ UINT32 chain_ptr;
+ UINT32 gen_purpose;
+ UINT32 ext_index;
+ UINT32 ext_modifier;
+ UINT32 ext_count;
+} DMA_REGS;
+
+typedef struct _SHARC_REGS SHARC_REGS;
+struct _SHARC_REGS
+{
+ UINT32 pc;
+ SHARC_REG r[16];
+ SHARC_REG reg_alt[16];
+ UINT64 mrf;
+ UINT64 mrb;
+
+ UINT32 pcstack[32];
+ UINT32 lcstack[6];
+ UINT32 lastack[6];
+ UINT32 lstkp;
+
+ UINT32 faddr;
+ UINT32 daddr;
+ UINT32 pcstk;
+ UINT32 pcstkp;
+ UINT32 laddr;
+ UINT32 curlcntr;
+ UINT32 lcntr;
+
+ /* Data Address Generator (DAG) */
+ SHARC_DAG dag1; // (DM bus)
+ SHARC_DAG dag2; // (PM bus)
+ SHARC_DAG dag1_alt;
+ SHARC_DAG dag2_alt;
+
+ DMA_REGS dma[12];
+
+ /* System registers */
+ UINT32 mode1;
+ UINT32 mode2;
+ UINT32 astat;
+ UINT32 stky;
+ UINT32 irptl;
+ UINT32 imask;
+ UINT32 imaskp;
+ UINT32 ustat1;
+ UINT32 ustat2;
+
+ UINT32 flag[4];
+
+ UINT32 syscon;
+ UINT32 sysstat;
+
+ struct
+ {
+ UINT32 mode1;
+ UINT32 astat;
+ } status_stack[5];
+ INT32 status_stkp;
+
+ UINT64 px;
+
+ UINT16 *internal_ram;
+ UINT16 *internal_ram_block0, *internal_ram_block1;
+
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ address_space *data;
+ void (*opcode_handler)(SHARC_REGS *cpustate);
+ int icount;
+ UINT64 opcode;
+ UINT64 fetch_opcode;
+ UINT64 decode_opcode;
+
+ UINT32 nfaddr;
+
+ INT32 idle;
+ INT32 irq_active;
+ INT32 active_irq_num;
+
+ SHARC_BOOT_MODE boot_mode;
+
+ UINT32 dmaop_src;
+ UINT32 dmaop_dst;
+ UINT32 dmaop_chain_ptr;
+ INT32 dmaop_src_modifier;
+ INT32 dmaop_dst_modifier;
+ INT32 dmaop_src_count;
+ INT32 dmaop_dst_count;
+ INT32 dmaop_pmode;
+ INT32 dmaop_cycles;
+ INT32 dmaop_channel;
+ INT32 dmaop_chained_direction;
+
+ INT32 interrupt_active;
+
+ INT32 iop_latency_cycles;
+ INT32 iop_latency_reg;
+ UINT32 iop_latency_data;
+
+ UINT32 delay_slot1, delay_slot2;
+
+ INT32 systemreg_latency_cycles;
+ INT32 systemreg_latency_reg;
+ UINT32 systemreg_latency_data;
+ UINT32 systemreg_previous_data;
+
+ UINT32 astat_old;
+ UINT32 astat_old_old;
+ UINT32 astat_old_old_old;
+};
+
+
+static void sharc_dma_exec(SHARC_REGS *cpustate, int channel);
+static void check_interrupts(SHARC_REGS *cpustate);
+
+static void (* sharc_op[512])(SHARC_REGS *cpustate);
+
+
+
+#define ROPCODE(pc) ((UINT64)(cpustate->internal_ram[((pc-0x20000) * 3) + 0]) << 32) | \
+ ((UINT64)(cpustate->internal_ram[((pc-0x20000) * 3) + 1]) << 16) | \
+ ((UINT64)(cpustate->internal_ram[((pc-0x20000) * 3) + 2]) << 0)
+
+INLINE SHARC_REGS *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == ADSP21062);
+ return (SHARC_REGS *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+INLINE void CHANGE_PC(SHARC_REGS *cpustate, UINT32 newpc)
+{
+ cpustate->pc = newpc;
+ cpustate->daddr = newpc;
+ cpustate->faddr = newpc+1;
+ cpustate->nfaddr = newpc+2;
+
+ // next instruction to be executed
+ cpustate->decode_opcode = ROPCODE(cpustate->daddr);
+ // next instruction to be decoded
+ cpustate->fetch_opcode = ROPCODE(cpustate->faddr);
+}
+
+INLINE void CHANGE_PC_DELAYED(SHARC_REGS *cpustate, UINT32 newpc)
+{
+ cpustate->nfaddr = newpc;
+
+ cpustate->delay_slot1 = cpustate->pc;
+ cpustate->delay_slot2 = cpustate->daddr;
+}
+
+
+
+static void add_iop_write_latency_effect(SHARC_REGS *cpustate, int iop_reg, UINT32 data, int latency)
+{
+ cpustate->iop_latency_cycles = latency+1;
+ cpustate->iop_latency_reg = iop_reg;
+ cpustate->iop_latency_data = data;
+}
+
+static void iop_write_latency_effect(SHARC_REGS *cpustate)
+{
+ UINT32 data = cpustate->iop_latency_data;
+
+ switch (cpustate->iop_latency_reg)
+ {
+ case 0x1c:
+ {
+ if (data & 0x1)
+ {
+ sharc_dma_exec(cpustate, 6);
+ }
+ break;
+ }
+
+ case 0x1d:
+ {
+ if (data & 0x1)
+ {
+ sharc_dma_exec(cpustate, 7);
+ }
+ break;
+ }
+
+ default: fatalerror("SHARC: iop_write_latency_effect: unknown IOP register %02X", cpustate->iop_latency_reg);
+ }
+}
+
+
+
+/* IOP registers */
+static UINT32 sharc_iop_r(SHARC_REGS *cpustate, UINT32 address)
+{
+ switch (address)
+ {
+ case 0x00: return 0; // System configuration
+
+ case 0x37: // DMA status
+ {
+ UINT32 r = 0;
+ if (cpustate->dmaop_cycles > 0)
+ {
+ r |= 1 << cpustate->dmaop_channel;
+ }
+ return r;
+ }
+ default: fatalerror("sharc_iop_r: Unimplemented IOP reg %02X at %08X", address, cpustate->pc);
+ }
+ return 0;
+}
+
+static void sharc_iop_w(SHARC_REGS *cpustate, UINT32 address, UINT32 data)
+{
+ switch (address)
+ {
+ case 0x00: break; // System configuration
+ case 0x02: break; // External Memory Wait State Configuration
+
+ case 0x08: break; // Message Register 0
+ case 0x09: break; // Message Register 1
+ case 0x0a: break; // Message Register 2
+ case 0x0b: break; // Message Register 3
+ case 0x0c: break; // Message Register 4
+ case 0x0d: break; // Message Register 5
+ case 0x0e: break; // Message Register 6
+ case 0x0f: break; // Message Register 7
+
+ // DMA 6
+ case 0x1c:
+ {
+ cpustate->dma[6].control = data;
+ add_iop_write_latency_effect(cpustate, 0x1c, data, 1);
+ break;
+ }
+
+ case 0x20: break;
+
+ case 0x40: cpustate->dma[6].int_index = data; return;
+ case 0x41: cpustate->dma[6].int_modifier = data; return;
+ case 0x42: cpustate->dma[6].int_count = data; return;
+ case 0x43: cpustate->dma[6].chain_ptr = data; return;
+ case 0x44: cpustate->dma[6].gen_purpose = data; return;
+ case 0x45: cpustate->dma[6].ext_index = data; return;
+ case 0x46: cpustate->dma[6].ext_modifier = data; return;
+ case 0x47: cpustate->dma[6].ext_count = data; return;
+
+ // DMA 7
+ case 0x1d:
+ {
+ cpustate->dma[7].control = data;
+ add_iop_write_latency_effect(cpustate, 0x1d, data, 30);
+ break;
+ }
+
+ case 0x48: cpustate->dma[7].int_index = data; return;
+ case 0x49: cpustate->dma[7].int_modifier = data; return;
+ case 0x4a: cpustate->dma[7].int_count = data; return;
+ case 0x4b: cpustate->dma[7].chain_ptr = data; return;
+ case 0x4c: cpustate->dma[7].gen_purpose = data; return;
+ case 0x4d: cpustate->dma[7].ext_index = data; return;
+ case 0x4e: cpustate->dma[7].ext_modifier = data; return;
+ case 0x4f: cpustate->dma[7].ext_count = data; return;
+
+ default: fatalerror("sharc_iop_w: Unimplemented IOP reg %02X, %08X at %08X", address, data, cpustate->pc);
+ }
+}
+
+
+#include "sharcmem.c"
+#include "sharcdma.c"
+#include "sharcops.c"
+#include "sharcops.h"
+
+
+
+static void build_opcode_table(void)
+{
+ int i, j;
+ int num_ops = sizeof(sharc_opcode_table) / sizeof(SHARC_OP);
+
+ for (i=0; i < 512; i++)
+ {
+ sharc_op[i] = sharcop_unimplemented;
+ }
+
+ for (i=0; i < 512; i++)
+ {
+ UINT16 op = i << 7;
+
+ for (j=0; j < num_ops; j++)
+ {
+ if ((sharc_opcode_table[j].op_mask & op) == sharc_opcode_table[j].op_bits)
+ {
+ if (sharc_op[i] != sharcop_unimplemented)
+ {
+ fatalerror("build_opcode_table: table already filled! (i=%04X, j=%d)\n", i, j);
+ }
+ else
+ {
+ sharc_op[i] = sharc_opcode_table[j].handler;
+ }
+ }
+ }
+ }
+}
+
+/*****************************************************************************/
+
+void sharc_external_iop_write(device_t *device, UINT32 address, UINT32 data)
+{
+ SHARC_REGS *cpustate = get_safe_token(device);
+ if (address == 0x1c)
+ {
+ if (data != 0)
+ {
+ cpustate->dma[6].control = data;
+ }
+ }
+ else
+ {
+ mame_printf_debug("SHARC IOP write %08X, %08X\n", address, data);
+ sharc_iop_w(cpustate, address, data);
+ }
+}
+
+void sharc_external_dma_write(device_t *device, UINT32 address, UINT64 data)
+{
+ SHARC_REGS *cpustate = get_safe_token(device);
+ switch ((cpustate->dma[6].control >> 6) & 0x3)
+ {
+ case 2: // 16/48 packing
+ {
+ int shift = address % 3;
+ UINT64 r = pm_read48(cpustate, cpustate->dma[6].int_index);
+
+ r &= ~((UINT64)(0xffff) << (shift*16));
+ r |= (data & 0xffff) << (shift*16);
+
+ pm_write48(cpustate, cpustate->dma[6].int_index, r);
+
+ if (shift == 2)
+ {
+
+ cpustate->dma[6].int_index += cpustate->dma[6].int_modifier;
+ }
+ break;
+ }
+ default:
+ {
+ fatalerror("sharc_external_dma_write: unimplemented packing mode %d\n", (cpustate->dma[6].control >> 6) & 0x3);
+ }
+ }
+}
+
+static CPU_INIT( sharc )
+{
+ SHARC_REGS *cpustate = get_safe_token(device);
+ const sharc_config *cfg = (const sharc_config *)device->static_config();
+ int saveindex;
+
+ cpustate->boot_mode = cfg->boot_mode;
+
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->data = device->space(AS_DATA);
+
+ build_opcode_table();
+
+ cpustate->internal_ram = auto_alloc_array(device->machine(), UINT16, 2 * 0x10000); // 2x 128KB
+ cpustate->internal_ram_block0 = &cpustate->internal_ram[0];
+ cpustate->internal_ram_block1 = &cpustate->internal_ram[0x20000/2];
+
+ device->save_item(NAME(cpustate->pc));
+ device->save_pointer(NAME(&cpustate->r[0].r), ARRAY_LENGTH(cpustate->r));
+ device->save_pointer(NAME(&cpustate->reg_alt[0].r), ARRAY_LENGTH(cpustate->reg_alt));
+ device->save_item(NAME(cpustate->mrf));
+ device->save_item(NAME(cpustate->mrb));
+
+ device->save_item(NAME(cpustate->pcstack));
+ device->save_item(NAME(cpustate->lcstack));
+ device->save_item(NAME(cpustate->lastack));
+ device->save_item(NAME(cpustate->lstkp));
+
+ device->save_item(NAME(cpustate->faddr));
+ device->save_item(NAME(cpustate->daddr));
+ device->save_item(NAME(cpustate->pcstk));
+ device->save_item(NAME(cpustate->pcstkp));
+ device->save_item(NAME(cpustate->laddr));
+ device->save_item(NAME(cpustate->curlcntr));
+ device->save_item(NAME(cpustate->lcntr));
+
+ device->save_item(NAME(cpustate->dag1.i));
+ device->save_item(NAME(cpustate->dag1.m));
+ device->save_item(NAME(cpustate->dag1.b));
+ device->save_item(NAME(cpustate->dag1.l));
+ device->save_item(NAME(cpustate->dag2.i));
+ device->save_item(NAME(cpustate->dag2.m));
+ device->save_item(NAME(cpustate->dag2.b));
+ device->save_item(NAME(cpustate->dag2.l));
+ device->save_item(NAME(cpustate->dag1_alt.i));
+ device->save_item(NAME(cpustate->dag1_alt.m));
+ device->save_item(NAME(cpustate->dag1_alt.b));
+ device->save_item(NAME(cpustate->dag1_alt.l));
+ device->save_item(NAME(cpustate->dag2_alt.i));
+ device->save_item(NAME(cpustate->dag2_alt.m));
+ device->save_item(NAME(cpustate->dag2_alt.b));
+ device->save_item(NAME(cpustate->dag2_alt.l));
+
+ for (saveindex = 0; saveindex < ARRAY_LENGTH(cpustate->dma); saveindex++)
+ {
+ device->save_item(NAME(cpustate->dma[saveindex].control), saveindex);
+ device->save_item(NAME(cpustate->dma[saveindex].int_index), saveindex);
+ device->save_item(NAME(cpustate->dma[saveindex].int_modifier), saveindex);
+ device->save_item(NAME(cpustate->dma[saveindex].int_count), saveindex);
+ device->save_item(NAME(cpustate->dma[saveindex].chain_ptr), saveindex);
+ device->save_item(NAME(cpustate->dma[saveindex].gen_purpose), saveindex);
+ device->save_item(NAME(cpustate->dma[saveindex].ext_index), saveindex);
+ device->save_item(NAME(cpustate->dma[saveindex].ext_modifier), saveindex);
+ device->save_item(NAME(cpustate->dma[saveindex].ext_count), saveindex);
+ }
+
+ device->save_item(NAME(cpustate->mode1));
+ device->save_item(NAME(cpustate->mode2));
+ device->save_item(NAME(cpustate->astat));
+ device->save_item(NAME(cpustate->stky));
+ device->save_item(NAME(cpustate->irptl));
+ device->save_item(NAME(cpustate->imask));
+ device->save_item(NAME(cpustate->imaskp));
+ device->save_item(NAME(cpustate->ustat1));
+ device->save_item(NAME(cpustate->ustat2));
+
+ device->save_item(NAME(cpustate->flag));
+
+ device->save_item(NAME(cpustate->syscon));
+ device->save_item(NAME(cpustate->sysstat));
+
+ for (saveindex = 0; saveindex < ARRAY_LENGTH(cpustate->status_stack); saveindex++)
+ {
+ device->save_item(NAME(cpustate->status_stack[saveindex].mode1), saveindex);
+ device->save_item(NAME(cpustate->status_stack[saveindex].astat), saveindex);
+ }
+ device->save_item(NAME(cpustate->status_stkp));
+
+ device->save_item(NAME(cpustate->px));
+
+ device->save_pointer(NAME(cpustate->internal_ram), 2 * 0x10000);
+
+ device->save_item(NAME(cpustate->opcode));
+ device->save_item(NAME(cpustate->fetch_opcode));
+ device->save_item(NAME(cpustate->decode_opcode));
+
+ device->save_item(NAME(cpustate->nfaddr));
+
+ device->save_item(NAME(cpustate->idle));
+ device->save_item(NAME(cpustate->irq_active));
+ device->save_item(NAME(cpustate->active_irq_num));
+
+ device->save_item(NAME(cpustate->dmaop_src));
+ device->save_item(NAME(cpustate->dmaop_dst));
+ device->save_item(NAME(cpustate->dmaop_chain_ptr));
+ device->save_item(NAME(cpustate->dmaop_src_modifier));
+ device->save_item(NAME(cpustate->dmaop_dst_modifier));
+ device->save_item(NAME(cpustate->dmaop_src_count));
+ device->save_item(NAME(cpustate->dmaop_dst_count));
+ device->save_item(NAME(cpustate->dmaop_pmode));
+ device->save_item(NAME(cpustate->dmaop_cycles));
+ device->save_item(NAME(cpustate->dmaop_channel));
+ device->save_item(NAME(cpustate->dmaop_chained_direction));
+
+ device->save_item(NAME(cpustate->interrupt_active));
+
+ device->save_item(NAME(cpustate->iop_latency_cycles));
+ device->save_item(NAME(cpustate->iop_latency_reg));
+ device->save_item(NAME(cpustate->iop_latency_data));
+
+ device->save_item(NAME(cpustate->delay_slot1));
+ device->save_item(NAME(cpustate->delay_slot2));
+
+ device->save_item(NAME(cpustate->systemreg_latency_cycles));
+ device->save_item(NAME(cpustate->systemreg_latency_reg));
+ device->save_item(NAME(cpustate->systemreg_latency_data));
+ device->save_item(NAME(cpustate->systemreg_previous_data));
+
+ device->save_item(NAME(cpustate->astat_old));
+ device->save_item(NAME(cpustate->astat_old_old));
+ device->save_item(NAME(cpustate->astat_old_old_old));
+}
+
+static CPU_RESET( sharc )
+{
+ SHARC_REGS *cpustate = get_safe_token(device);
+ memset(cpustate->internal_ram, 0, 2 * 0x10000 * sizeof(UINT16));
+
+ switch(cpustate->boot_mode)
+ {
+ case BOOT_MODE_EPROM:
+ {
+ cpustate->dma[6].int_index = 0x20000;
+ cpustate->dma[6].int_modifier = 1;
+ cpustate->dma[6].int_count = 0x100;
+ cpustate->dma[6].ext_index = 0x400000;
+ cpustate->dma[6].ext_modifier = 1;
+ cpustate->dma[6].ext_count = 0x600;
+ cpustate->dma[6].control = 0x2a1;
+
+ sharc_dma_exec(cpustate, 6);
+ dma_op(cpustate, cpustate->dmaop_src, cpustate->dmaop_dst, cpustate->dmaop_src_modifier, cpustate->dmaop_dst_modifier,
+ cpustate->dmaop_src_count, cpustate->dmaop_dst_count, cpustate->dmaop_pmode);
+ cpustate->dmaop_cycles = 0;
+
+ break;
+ }
+
+ case BOOT_MODE_HOST:
+ break;
+
+ default:
+ fatalerror("SHARC: Unimplemented boot mode %d", cpustate->boot_mode);
+ }
+
+ cpustate->pc = 0x20004;
+ cpustate->daddr = cpustate->pc + 1;
+ cpustate->faddr = cpustate->daddr + 1;
+ cpustate->nfaddr = cpustate->faddr+1;
+
+ cpustate->idle = 0;
+ cpustate->stky = 0x5400000;
+
+ cpustate->interrupt_active = 0;
+}
+
+static CPU_EXIT( sharc )
+{
+ /* TODO */
+}
+
+static void sharc_set_irq_line(SHARC_REGS *cpustate, int irqline, int state)
+{
+ if (state)
+ {
+ cpustate->irq_active |= 1 << (8-irqline);
+ }
+}
+
+void sharc_set_flag_input(device_t *device, int flag_num, int state)
+{
+ SHARC_REGS *cpustate = get_safe_token(device);
+ if (flag_num >= 0 && flag_num < 4)
+ {
+ // Check if flag is set to input in MODE2 (bit == 0)
+ if ((cpustate->mode2 & (1 << (flag_num+15))) == 0)
+ {
+ cpustate->flag[flag_num] = state ? 1 : 0;
+ }
+ else
+ {
+ fatalerror("sharc_set_flag_input: flag %d is set output!", flag_num);
+ }
+ }
+}
+
+static void check_interrupts(SHARC_REGS *cpustate)
+{
+ int i;
+ if ((cpustate->imask & cpustate->irq_active) && (cpustate->mode1 & MODE1_IRPTEN) && !cpustate->interrupt_active &&
+ cpustate->pc != cpustate->delay_slot1 && cpustate->pc != cpustate->delay_slot2)
+ {
+ int which = 0;
+ for (i=0; i < 32; i++)
+ {
+ if (cpustate->irq_active & (1 << i))
+ {
+ break;
+ }
+ which++;
+ }
+
+ if (cpustate->idle)
+ {
+ PUSH_PC(cpustate, cpustate->pc+1);
+ }
+ else
+ {
+ PUSH_PC(cpustate, cpustate->daddr);
+ }
+
+ cpustate->irptl |= 1 << which;
+
+ if (which >= 6 && which <= 8)
+ {
+ PUSH_STATUS_STACK(cpustate);
+ }
+
+ CHANGE_PC(cpustate, 0x20000 + (which * 0x4));
+
+ /* TODO: alter IMASKP */
+
+ cpustate->active_irq_num = which;
+ cpustate->irq_active &= ~(1 << which);
+
+ cpustate->interrupt_active = 1;
+ }
+}
+
+static CPU_EXECUTE( sharc )
+{
+ SHARC_REGS *cpustate = get_safe_token(device);
+
+ if (cpustate->idle && cpustate->irq_active == 0)
+ {
+ // handle pending DMA transfers
+ if (cpustate->dmaop_cycles > 0)
+ {
+ cpustate->dmaop_cycles -= cpustate->icount;
+ if (cpustate->dmaop_cycles <= 0)
+ {
+ cpustate->dmaop_cycles = 0;
+ dma_op(cpustate, cpustate->dmaop_src, cpustate->dmaop_dst, cpustate->dmaop_src_modifier, cpustate->dmaop_dst_modifier, cpustate->dmaop_src_count, cpustate->dmaop_dst_count, cpustate->dmaop_pmode);
+ if (cpustate->dmaop_chain_ptr != 0)
+ {
+ schedule_chained_dma_op(cpustate, cpustate->dmaop_channel, cpustate->dmaop_chain_ptr, cpustate->dmaop_chained_direction);
+ }
+ }
+ }
+
+ cpustate->icount = 0;
+ debugger_instruction_hook(device, cpustate->daddr);
+ }
+ if (cpustate->irq_active != 0)
+ {
+ check_interrupts(cpustate);
+ cpustate->idle = 0;
+ }
+
+ // fill the initial pipeline
+
+ // next executed instruction
+ cpustate->opcode = ROPCODE(cpustate->daddr);
+ cpustate->opcode_handler = sharc_op[(cpustate->opcode >> 39) & 0x1ff];
+
+ // next decoded instruction
+ cpustate->fetch_opcode = ROPCODE(cpustate->faddr);
+
+ while (cpustate->icount > 0 && !cpustate->idle)
+ {
+ cpustate->pc = cpustate->daddr;
+ cpustate->daddr = cpustate->faddr;
+ cpustate->faddr = cpustate->nfaddr;
+ cpustate->nfaddr++;
+
+ cpustate->astat_old_old_old = cpustate->astat_old_old;
+ cpustate->astat_old_old = cpustate->astat_old;
+ cpustate->astat_old = cpustate->astat;
+
+ cpustate->decode_opcode = cpustate->fetch_opcode;
+
+ // fetch next instruction
+ cpustate->fetch_opcode = ROPCODE(cpustate->faddr);
+
+ debugger_instruction_hook(device, cpustate->pc);
+
+ // handle looping
+ if (cpustate->pc == (cpustate->laddr & 0xffffff))
+ {
+ switch (cpustate->laddr >> 30)
+ {
+ case 0: // arithmetic condition-based
+ {
+ int condition = (cpustate->laddr >> 24) & 0x1f;
+
+ {
+ UINT32 looptop = TOP_PC(cpustate);
+ if (cpustate->pc - looptop > 2)
+ {
+ cpustate->astat = cpustate->astat_old_old_old;
+ }
+ }
+
+ if (DO_CONDITION_CODE(cpustate, condition))
+ {
+ POP_LOOP(cpustate);
+ POP_PC(cpustate);
+ }
+ else
+ {
+ CHANGE_PC(cpustate, TOP_PC(cpustate));
+ }
+
+ cpustate->astat = cpustate->astat_old;
+ break;
+ }
+ case 1: // counter-based, length 1
+ {
+ //fatalerror("SHARC: counter-based loop, length 1 at %08X", cpustate->pc);
+ //break;
+ }
+ case 2: // counter-based, length 2
+ {
+ //fatalerror("SHARC: counter-based loop, length 2 at %08X", cpustate->pc);
+ //break;
+ }
+ case 3: // counter-based, length >2
+ {
+ --cpustate->lcstack[cpustate->lstkp];
+ --cpustate->curlcntr;
+ if (cpustate->curlcntr == 0)
+ {
+ POP_LOOP(cpustate);
+ POP_PC(cpustate);
+ }
+ else
+ {
+ CHANGE_PC(cpustate, TOP_PC(cpustate));
+ }
+ }
+ }
+ }
+
+ // execute current instruction
+ cpustate->opcode_handler(cpustate);
+
+ // decode next instruction
+ cpustate->opcode = cpustate->decode_opcode;
+ cpustate->opcode_handler = sharc_op[(cpustate->opcode >> 39) & 0x1ff];
+
+
+
+
+ // System register latency effect
+ if (cpustate->systemreg_latency_cycles > 0)
+ {
+ --cpustate->systemreg_latency_cycles;
+ if (cpustate->systemreg_latency_cycles <= 0)
+ {
+ systemreg_write_latency_effect(cpustate);
+ }
+ }
+
+ // IOP register latency effect
+ if (cpustate->iop_latency_cycles > 0)
+ {
+ --cpustate->iop_latency_cycles;
+ if (cpustate->iop_latency_cycles <= 0)
+ {
+ iop_write_latency_effect(cpustate);
+ }
+ }
+
+ // DMA transfer
+ if (cpustate->dmaop_cycles > 0)
+ {
+ --cpustate->dmaop_cycles;
+ if (cpustate->dmaop_cycles <= 0)
+ {
+ cpustate->irptl |= (1 << (cpustate->dmaop_channel+10));
+
+ /* DMA interrupt */
+ if (cpustate->imask & (1 << (cpustate->dmaop_channel+10)))
+ {
+ cpustate->irq_active |= 1 << (cpustate->dmaop_channel+10);
+ }
+
+ dma_op(cpustate, cpustate->dmaop_src, cpustate->dmaop_dst, cpustate->dmaop_src_modifier, cpustate->dmaop_dst_modifier, cpustate->dmaop_src_count, cpustate->dmaop_dst_count, cpustate->dmaop_pmode);
+ if (cpustate->dmaop_chain_ptr != 0)
+ {
+ schedule_chained_dma_op(cpustate, cpustate->dmaop_channel, cpustate->dmaop_chain_ptr, cpustate->dmaop_chained_direction);
+ }
+ }
+ }
+
+ --cpustate->icount;
+ };
+}
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( sharc )
+{
+ SHARC_REGS *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + SHARC_PC: cpustate->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_FADDR: cpustate->faddr = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_DADDR: cpustate->daddr = info->i; break;
+
+ case CPUINFO_INT_REGISTER + SHARC_R0: cpustate->r[0].r = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_R1: cpustate->r[1].r = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_R2: cpustate->r[2].r = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_R3: cpustate->r[3].r = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_R4: cpustate->r[4].r = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_R5: cpustate->r[5].r = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_R6: cpustate->r[6].r = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_R7: cpustate->r[7].r = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_R8: cpustate->r[8].r = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_R9: cpustate->r[9].r = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_R10: cpustate->r[10].r = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_R11: cpustate->r[11].r = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_R12: cpustate->r[12].r = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_R13: cpustate->r[13].r = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_R14: cpustate->r[14].r = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_R15: cpustate->r[15].r = info->i; break;
+
+ case CPUINFO_INT_REGISTER + SHARC_I0: cpustate->dag1.i[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_I1: cpustate->dag1.i[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_I2: cpustate->dag1.i[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_I3: cpustate->dag1.i[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_I4: cpustate->dag1.i[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_I5: cpustate->dag1.i[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_I6: cpustate->dag1.i[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_I7: cpustate->dag1.i[7] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_I8: cpustate->dag2.i[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_I9: cpustate->dag2.i[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_I10: cpustate->dag2.i[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_I11: cpustate->dag2.i[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_I12: cpustate->dag2.i[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_I13: cpustate->dag2.i[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_I14: cpustate->dag2.i[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_I15: cpustate->dag2.i[7] = info->i; break;
+
+ case CPUINFO_INT_REGISTER + SHARC_M0: cpustate->dag1.m[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_M1: cpustate->dag1.m[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_M2: cpustate->dag1.m[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_M3: cpustate->dag1.m[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_M4: cpustate->dag1.m[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_M5: cpustate->dag1.m[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_M6: cpustate->dag1.m[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_M7: cpustate->dag1.m[7] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_M8: cpustate->dag2.m[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_M9: cpustate->dag2.m[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_M10: cpustate->dag2.m[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_M11: cpustate->dag2.m[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_M12: cpustate->dag2.m[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_M13: cpustate->dag2.m[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_M14: cpustate->dag2.m[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_M15: cpustate->dag2.m[7] = info->i; break;
+
+ case CPUINFO_INT_REGISTER + SHARC_L0: cpustate->dag1.l[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_L1: cpustate->dag1.l[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_L2: cpustate->dag1.l[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_L3: cpustate->dag1.l[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_L4: cpustate->dag1.l[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_L5: cpustate->dag1.l[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_L6: cpustate->dag1.l[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_L7: cpustate->dag1.l[7] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_L8: cpustate->dag2.l[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_L9: cpustate->dag2.l[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_L10: cpustate->dag2.l[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_L11: cpustate->dag2.l[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_L12: cpustate->dag2.l[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_L13: cpustate->dag2.l[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_L14: cpustate->dag2.l[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_L15: cpustate->dag2.m[7] = info->i; break;
+
+ case CPUINFO_INT_REGISTER + SHARC_B0: cpustate->dag1.b[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_B1: cpustate->dag1.b[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_B2: cpustate->dag1.b[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_B3: cpustate->dag1.b[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_B4: cpustate->dag1.b[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_B5: cpustate->dag1.b[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_B6: cpustate->dag1.b[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_B7: cpustate->dag1.b[7] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_B8: cpustate->dag2.b[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_B9: cpustate->dag2.b[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_B10: cpustate->dag2.b[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_B11: cpustate->dag2.b[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_B12: cpustate->dag2.b[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_B13: cpustate->dag2.b[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_B14: cpustate->dag2.b[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + SHARC_B15: cpustate->dag2.b[7] = info->i; break;
+ }
+}
+
+static CPU_SET_INFO( adsp21062 )
+{
+ if (state >= CPUINFO_INT_INPUT_STATE && state <= CPUINFO_INT_INPUT_STATE + 2)
+ {
+ sharc_set_irq_line(get_safe_token(device), state-CPUINFO_INT_INPUT_STATE, info->i);
+ return;
+ }
+ else if (state >= CPUINFO_INT_INPUT_STATE + SHARC_INPUT_FLAG0 && state <= CPUINFO_INT_INPUT_STATE + SHARC_INPUT_FLAG3)
+ {
+ sharc_set_flag_input(device, state-(CPUINFO_INT_INPUT_STATE + SHARC_INPUT_FLAG0), info->i);
+ return;
+ }
+ switch(state)
+ {
+ default: CPU_SET_INFO_CALL(sharc); break;
+ }
+}
+
+
+static CPU_READ( sharc )
+{
+ SHARC_REGS *cpustate = get_safe_token(device);
+ if (space == AS_PROGRAM)
+ {
+ int address = offset >> 3;
+
+ if (address >= 0x20000 && address < 0x30000)
+ {
+ switch (size)
+ {
+ case 1:
+ {
+ int frac = offset & 7;
+ *value = (pm_read48(cpustate, offset >> 3) >> ((frac^7) * 8)) & 0xff;
+ break;
+ }
+ case 8:
+ {
+ *value = pm_read48(cpustate, offset >> 3);
+ break;
+ }
+ }
+ }
+ else
+ {
+ *value = 0;
+ }
+ }
+ else if (space == AS_DATA)
+ {
+ int address = offset >> 2;
+ if (address >= 0x20000)
+ {
+ switch (size)
+ {
+ case 1:
+ {
+ int frac = offset & 3;
+ *value = (dm_read32(cpustate, offset >> 2) >> ((frac^3) * 8)) & 0xff;
+ break;
+ }
+ case 2:
+ {
+ int frac = (offset >> 1) & 1;
+ *value = (dm_read32(cpustate, offset >> 2) >> ((frac^1) * 16)) & 0xffff;
+ break;
+ }
+ case 4:
+ {
+ *value = dm_read32(cpustate, offset >> 2);
+ break;
+ }
+ }
+ }
+ else
+ {
+ *value = 0;
+ }
+ }
+ return 1;
+}
+
+static CPU_READOP( sharc )
+{
+ SHARC_REGS *cpustate = get_safe_token(device);
+ UINT64 mask = (size < 8) ? (((UINT64)1 << (8 * size)) - 1) : ~(UINT64)0;
+ int shift = 8 * (offset & 7);
+ offset >>= 3;
+
+ if (offset >= 0x20000 && offset < 0x28000)
+ {
+ UINT64 op = ((UINT64)(cpustate->internal_ram_block0[((offset-0x20000) * 3) + 0]) << 32) |
+ ((UINT64)(cpustate->internal_ram_block0[((offset-0x20000) * 3) + 1]) << 16) |
+ ((UINT64)(cpustate->internal_ram_block0[((offset-0x20000) * 3) + 2]) << 0);
+ *value = (op >> shift) & mask;
+ }
+ else if (offset >= 0x28000 && offset < 0x30000)
+ {
+ UINT64 op = ((UINT64)(cpustate->internal_ram_block1[((offset-0x28000) * 3) + 0]) << 32) |
+ ((UINT64)(cpustate->internal_ram_block1[((offset-0x28000) * 3) + 1]) << 16) |
+ ((UINT64)(cpustate->internal_ram_block1[((offset-0x28000) * 3) + 2]) << 0);
+ *value = (op >> shift) & mask;
+ }
+
+ return 1;
+}
+
+// This is just used to stop the debugger from complaining about executing from I/O space
+static ADDRESS_MAP_START( internal_pgm, AS_PROGRAM, 64 )
+ AM_RANGE(0x20000, 0x7ffff) AM_RAM
+ADDRESS_MAP_END
+
+static CPU_GET_INFO( sharc )
+{
+ SHARC_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(SHARC_REGS); 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 = 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 = 40; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 64; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 24; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = -3; 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 = -2; 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:
+ case CPUINFO_INT_REGISTER + SHARC_PC: info->i = cpustate->pc; break;
+ case CPUINFO_INT_REGISTER + SHARC_PCSTK: info->i = cpustate->pcstk; break;
+ case CPUINFO_INT_REGISTER + SHARC_PCSTKP: info->i = cpustate->pcstkp; break;
+ case CPUINFO_INT_REGISTER + SHARC_LSTKP: info->i = cpustate->lstkp; break;
+ case CPUINFO_INT_REGISTER + SHARC_FADDR: info->i = cpustate->faddr; break;
+ case CPUINFO_INT_REGISTER + SHARC_DADDR: info->i = cpustate->daddr; break;
+ case CPUINFO_INT_REGISTER + SHARC_MODE1: info->i = cpustate->mode1; break;
+ case CPUINFO_INT_REGISTER + SHARC_MODE2: info->i = cpustate->mode2; break;
+ case CPUINFO_INT_REGISTER + SHARC_ASTAT: info->i = cpustate->astat; break;
+ case CPUINFO_INT_REGISTER + SHARC_IRPTL: info->i = cpustate->irptl; break;
+ case CPUINFO_INT_REGISTER + SHARC_IMASK: info->i = cpustate->imask; break;
+ case CPUINFO_INT_REGISTER + SHARC_USTAT1: info->i = cpustate->ustat1; break;
+ case CPUINFO_INT_REGISTER + SHARC_USTAT2: info->i = cpustate->ustat2; break;
+ case CPUINFO_INT_REGISTER + SHARC_STSTKP: info->i = cpustate->status_stkp; break;
+
+ case CPUINFO_INT_REGISTER + SHARC_R0: info->i = cpustate->r[0].r; break;
+ case CPUINFO_INT_REGISTER + SHARC_R1: info->i = cpustate->r[1].r; break;
+ case CPUINFO_INT_REGISTER + SHARC_R2: info->i = cpustate->r[2].r; break;
+ case CPUINFO_INT_REGISTER + SHARC_R3: info->i = cpustate->r[3].r; break;
+ case CPUINFO_INT_REGISTER + SHARC_R4: info->i = cpustate->r[4].r; break;
+ case CPUINFO_INT_REGISTER + SHARC_R5: info->i = cpustate->r[5].r; break;
+ case CPUINFO_INT_REGISTER + SHARC_R6: info->i = cpustate->r[6].r; break;
+ case CPUINFO_INT_REGISTER + SHARC_R7: info->i = cpustate->r[7].r; break;
+ case CPUINFO_INT_REGISTER + SHARC_R8: info->i = cpustate->r[8].r; break;
+ case CPUINFO_INT_REGISTER + SHARC_R9: info->i = cpustate->r[9].r; break;
+ case CPUINFO_INT_REGISTER + SHARC_R10: info->i = cpustate->r[10].r; break;
+ case CPUINFO_INT_REGISTER + SHARC_R11: info->i = cpustate->r[11].r; break;
+ case CPUINFO_INT_REGISTER + SHARC_R12: info->i = cpustate->r[12].r; break;
+ case CPUINFO_INT_REGISTER + SHARC_R13: info->i = cpustate->r[13].r; break;
+ case CPUINFO_INT_REGISTER + SHARC_R14: info->i = cpustate->r[14].r; break;
+ case CPUINFO_INT_REGISTER + SHARC_R15: info->i = cpustate->r[15].r; break;
+
+ case CPUINFO_INT_REGISTER + SHARC_I0: info->i = cpustate->dag1.i[0]; break;
+ case CPUINFO_INT_REGISTER + SHARC_I1: info->i = cpustate->dag1.i[1]; break;
+ case CPUINFO_INT_REGISTER + SHARC_I2: info->i = cpustate->dag1.i[2]; break;
+ case CPUINFO_INT_REGISTER + SHARC_I3: info->i = cpustate->dag1.i[3]; break;
+ case CPUINFO_INT_REGISTER + SHARC_I4: info->i = cpustate->dag1.i[4]; break;
+ case CPUINFO_INT_REGISTER + SHARC_I5: info->i = cpustate->dag1.i[5]; break;
+ case CPUINFO_INT_REGISTER + SHARC_I6: info->i = cpustate->dag1.i[6]; break;
+ case CPUINFO_INT_REGISTER + SHARC_I7: info->i = cpustate->dag1.i[7]; break;
+ case CPUINFO_INT_REGISTER + SHARC_I8: info->i = cpustate->dag2.i[0]; break;
+ case CPUINFO_INT_REGISTER + SHARC_I9: info->i = cpustate->dag2.i[1]; break;
+ case CPUINFO_INT_REGISTER + SHARC_I10: info->i = cpustate->dag2.i[2]; break;
+ case CPUINFO_INT_REGISTER + SHARC_I11: info->i = cpustate->dag2.i[3]; break;
+ case CPUINFO_INT_REGISTER + SHARC_I12: info->i = cpustate->dag2.i[4]; break;
+ case CPUINFO_INT_REGISTER + SHARC_I13: info->i = cpustate->dag2.i[5]; break;
+ case CPUINFO_INT_REGISTER + SHARC_I14: info->i = cpustate->dag2.i[6]; break;
+ case CPUINFO_INT_REGISTER + SHARC_I15: info->i = cpustate->dag2.i[7]; break;
+
+ case CPUINFO_INT_REGISTER + SHARC_M0: info->i = cpustate->dag1.m[0]; break;
+ case CPUINFO_INT_REGISTER + SHARC_M1: info->i = cpustate->dag1.m[1]; break;
+ case CPUINFO_INT_REGISTER + SHARC_M2: info->i = cpustate->dag1.m[2]; break;
+ case CPUINFO_INT_REGISTER + SHARC_M3: info->i = cpustate->dag1.m[3]; break;
+ case CPUINFO_INT_REGISTER + SHARC_M4: info->i = cpustate->dag1.m[4]; break;
+ case CPUINFO_INT_REGISTER + SHARC_M5: info->i = cpustate->dag1.m[5]; break;
+ case CPUINFO_INT_REGISTER + SHARC_M6: info->i = cpustate->dag1.m[6]; break;
+ case CPUINFO_INT_REGISTER + SHARC_M7: info->i = cpustate->dag1.m[7]; break;
+ case CPUINFO_INT_REGISTER + SHARC_M8: info->i = cpustate->dag2.m[0]; break;
+ case CPUINFO_INT_REGISTER + SHARC_M9: info->i = cpustate->dag2.m[1]; break;
+ case CPUINFO_INT_REGISTER + SHARC_M10: info->i = cpustate->dag2.m[2]; break;
+ case CPUINFO_INT_REGISTER + SHARC_M11: info->i = cpustate->dag2.m[3]; break;
+ case CPUINFO_INT_REGISTER + SHARC_M12: info->i = cpustate->dag2.m[4]; break;
+ case CPUINFO_INT_REGISTER + SHARC_M13: info->i = cpustate->dag2.m[5]; break;
+ case CPUINFO_INT_REGISTER + SHARC_M14: info->i = cpustate->dag2.m[6]; break;
+ case CPUINFO_INT_REGISTER + SHARC_M15: info->i = cpustate->dag2.m[7]; break;
+
+ case CPUINFO_INT_REGISTER + SHARC_L0: info->i = cpustate->dag1.l[0]; break;
+ case CPUINFO_INT_REGISTER + SHARC_L1: info->i = cpustate->dag1.l[1]; break;
+ case CPUINFO_INT_REGISTER + SHARC_L2: info->i = cpustate->dag1.l[2]; break;
+ case CPUINFO_INT_REGISTER + SHARC_L3: info->i = cpustate->dag1.l[3]; break;
+ case CPUINFO_INT_REGISTER + SHARC_L4: info->i = cpustate->dag1.l[4]; break;
+ case CPUINFO_INT_REGISTER + SHARC_L5: info->i = cpustate->dag1.l[5]; break;
+ case CPUINFO_INT_REGISTER + SHARC_L6: info->i = cpustate->dag1.l[6]; break;
+ case CPUINFO_INT_REGISTER + SHARC_L7: info->i = cpustate->dag1.l[7]; break;
+ case CPUINFO_INT_REGISTER + SHARC_L8: info->i = cpustate->dag2.l[0]; break;
+ case CPUINFO_INT_REGISTER + SHARC_L9: info->i = cpustate->dag2.l[1]; break;
+ case CPUINFO_INT_REGISTER + SHARC_L10: info->i = cpustate->dag2.l[2]; break;
+ case CPUINFO_INT_REGISTER + SHARC_L11: info->i = cpustate->dag2.l[3]; break;
+ case CPUINFO_INT_REGISTER + SHARC_L12: info->i = cpustate->dag2.l[4]; break;
+ case CPUINFO_INT_REGISTER + SHARC_L13: info->i = cpustate->dag2.l[5]; break;
+ case CPUINFO_INT_REGISTER + SHARC_L14: info->i = cpustate->dag2.l[6]; break;
+ case CPUINFO_INT_REGISTER + SHARC_L15: info->i = cpustate->dag2.l[7]; break;
+
+ case CPUINFO_INT_REGISTER + SHARC_B0: info->i = cpustate->dag1.b[0]; break;
+ case CPUINFO_INT_REGISTER + SHARC_B1: info->i = cpustate->dag1.b[1]; break;
+ case CPUINFO_INT_REGISTER + SHARC_B2: info->i = cpustate->dag1.b[2]; break;
+ case CPUINFO_INT_REGISTER + SHARC_B3: info->i = cpustate->dag1.b[3]; break;
+ case CPUINFO_INT_REGISTER + SHARC_B4: info->i = cpustate->dag1.b[4]; break;
+ case CPUINFO_INT_REGISTER + SHARC_B5: info->i = cpustate->dag1.b[5]; break;
+ case CPUINFO_INT_REGISTER + SHARC_B6: info->i = cpustate->dag1.b[6]; break;
+ case CPUINFO_INT_REGISTER + SHARC_B7: info->i = cpustate->dag1.b[7]; break;
+ case CPUINFO_INT_REGISTER + SHARC_B8: info->i = cpustate->dag2.b[0]; break;
+ case CPUINFO_INT_REGISTER + SHARC_B9: info->i = cpustate->dag2.b[1]; break;
+ case CPUINFO_INT_REGISTER + SHARC_B10: info->i = cpustate->dag2.b[2]; break;
+ case CPUINFO_INT_REGISTER + SHARC_B11: info->i = cpustate->dag2.b[3]; break;
+ case CPUINFO_INT_REGISTER + SHARC_B12: info->i = cpustate->dag2.b[4]; break;
+ case CPUINFO_INT_REGISTER + SHARC_B13: info->i = cpustate->dag2.b[5]; break;
+ case CPUINFO_INT_REGISTER + SHARC_B14: info->i = cpustate->dag2.b[6]; break;
+ case CPUINFO_INT_REGISTER + SHARC_B15: info->i = cpustate->dag2.b[7]; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(sharc); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(sharc); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(sharc); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(sharc);break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(sharc); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+ case CPUINFO_FCT_READ: info->read = CPU_READ_NAME(sharc); break;
+ case CPUINFO_FCT_READOP: info->readop = CPU_READOP_NAME(sharc); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map64 = ADDRESS_MAP_NAME(internal_pgm); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "SHARC"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "2.01"); 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: strcpy(info->s, " "); break;
+
+ case CPUINFO_STR_REGISTER + SHARC_PC: sprintf(info->s, "PC: %08X", cpustate->pc); break;
+ case CPUINFO_STR_REGISTER + SHARC_PCSTK: sprintf(info->s, "PCSTK: %08X", cpustate->pcstk); break;
+ case CPUINFO_STR_REGISTER + SHARC_PCSTKP: sprintf(info->s, "PCSTKP: %08X", cpustate->pcstkp); break;
+ case CPUINFO_STR_REGISTER + SHARC_LSTKP: sprintf(info->s, "LSTKP: %08X", cpustate->lstkp); break;
+ case CPUINFO_STR_REGISTER + SHARC_FADDR: sprintf(info->s, "FADDR: %08X", cpustate->faddr); break;
+ case CPUINFO_STR_REGISTER + SHARC_DADDR: sprintf(info->s, "DADDR: %08X", cpustate->daddr); break;
+ case CPUINFO_STR_REGISTER + SHARC_MODE1: sprintf(info->s, "MODE1: %08X", cpustate->mode1); break;
+ case CPUINFO_STR_REGISTER + SHARC_MODE2: sprintf(info->s, "MODE2: %08X", cpustate->mode2); break;
+ case CPUINFO_STR_REGISTER + SHARC_ASTAT: sprintf(info->s, "ASTAT: %08X", cpustate->astat); break;
+ case CPUINFO_STR_REGISTER + SHARC_IRPTL: sprintf(info->s, "IRPTL: %08X", cpustate->irptl); break;
+ case CPUINFO_STR_REGISTER + SHARC_IMASK: sprintf(info->s, "IMASK: %08X", cpustate->imask); break;
+ case CPUINFO_STR_REGISTER + SHARC_USTAT1: sprintf(info->s, "USTAT1: %08X", cpustate->ustat1); break;
+ case CPUINFO_STR_REGISTER + SHARC_USTAT2: sprintf(info->s, "USTAT2: %08X", cpustate->ustat2); break;
+ case CPUINFO_STR_REGISTER + SHARC_STSTKP: sprintf(info->s, "STSTKP: %08X", cpustate->status_stkp); break;
+
+ case CPUINFO_STR_REGISTER + SHARC_R0: sprintf(info->s, "R0: %08X", (UINT32)cpustate->r[0].r); break;
+ case CPUINFO_STR_REGISTER + SHARC_R1: sprintf(info->s, "R1: %08X", (UINT32)cpustate->r[1].r); break;
+ case CPUINFO_STR_REGISTER + SHARC_R2: sprintf(info->s, "R2: %08X", (UINT32)cpustate->r[2].r); break;
+ case CPUINFO_STR_REGISTER + SHARC_R3: sprintf(info->s, "R3: %08X", (UINT32)cpustate->r[3].r); break;
+ case CPUINFO_STR_REGISTER + SHARC_R4: sprintf(info->s, "R4: %08X", (UINT32)cpustate->r[4].r); break;
+ case CPUINFO_STR_REGISTER + SHARC_R5: sprintf(info->s, "R5: %08X", (UINT32)cpustate->r[5].r); break;
+ case CPUINFO_STR_REGISTER + SHARC_R6: sprintf(info->s, "R6: %08X", (UINT32)cpustate->r[6].r); break;
+ case CPUINFO_STR_REGISTER + SHARC_R7: sprintf(info->s, "R7: %08X", (UINT32)cpustate->r[7].r); break;
+ case CPUINFO_STR_REGISTER + SHARC_R8: sprintf(info->s, "R8: %08X", (UINT32)cpustate->r[8].r); break;
+ case CPUINFO_STR_REGISTER + SHARC_R9: sprintf(info->s, "R9: %08X", (UINT32)cpustate->r[9].r); break;
+ case CPUINFO_STR_REGISTER + SHARC_R10: sprintf(info->s, "R10: %08X", (UINT32)cpustate->r[10].r); break;
+ case CPUINFO_STR_REGISTER + SHARC_R11: sprintf(info->s, "R11: %08X", (UINT32)cpustate->r[11].r); break;
+ case CPUINFO_STR_REGISTER + SHARC_R12: sprintf(info->s, "R12: %08X", (UINT32)cpustate->r[12].r); break;
+ case CPUINFO_STR_REGISTER + SHARC_R13: sprintf(info->s, "R13: %08X", (UINT32)cpustate->r[13].r); break;
+ case CPUINFO_STR_REGISTER + SHARC_R14: sprintf(info->s, "R14: %08X", (UINT32)cpustate->r[14].r); break;
+ case CPUINFO_STR_REGISTER + SHARC_R15: sprintf(info->s, "R15: %08X", (UINT32)cpustate->r[15].r); break;
+
+ case CPUINFO_STR_REGISTER + SHARC_I0: sprintf(info->s, "I0: %08X", (UINT32)cpustate->dag1.i[0]); break;
+ case CPUINFO_STR_REGISTER + SHARC_I1: sprintf(info->s, "I1: %08X", (UINT32)cpustate->dag1.i[1]); break;
+ case CPUINFO_STR_REGISTER + SHARC_I2: sprintf(info->s, "I2: %08X", (UINT32)cpustate->dag1.i[2]); break;
+ case CPUINFO_STR_REGISTER + SHARC_I3: sprintf(info->s, "I3: %08X", (UINT32)cpustate->dag1.i[3]); break;
+ case CPUINFO_STR_REGISTER + SHARC_I4: sprintf(info->s, "I4: %08X", (UINT32)cpustate->dag1.i[4]); break;
+ case CPUINFO_STR_REGISTER + SHARC_I5: sprintf(info->s, "I5: %08X", (UINT32)cpustate->dag1.i[5]); break;
+ case CPUINFO_STR_REGISTER + SHARC_I6: sprintf(info->s, "I6: %08X", (UINT32)cpustate->dag1.i[6]); break;
+ case CPUINFO_STR_REGISTER + SHARC_I7: sprintf(info->s, "I7: %08X", (UINT32)cpustate->dag1.i[7]); break;
+ case CPUINFO_STR_REGISTER + SHARC_I8: sprintf(info->s, "I8: %08X", (UINT32)cpustate->dag2.i[0]); break;
+ case CPUINFO_STR_REGISTER + SHARC_I9: sprintf(info->s, "I9: %08X", (UINT32)cpustate->dag2.i[1]); break;
+ case CPUINFO_STR_REGISTER + SHARC_I10: sprintf(info->s, "I10: %08X", (UINT32)cpustate->dag2.i[2]); break;
+ case CPUINFO_STR_REGISTER + SHARC_I11: sprintf(info->s, "I11: %08X", (UINT32)cpustate->dag2.i[3]); break;
+ case CPUINFO_STR_REGISTER + SHARC_I12: sprintf(info->s, "I12: %08X", (UINT32)cpustate->dag2.i[4]); break;
+ case CPUINFO_STR_REGISTER + SHARC_I13: sprintf(info->s, "I13: %08X", (UINT32)cpustate->dag2.i[5]); break;
+ case CPUINFO_STR_REGISTER + SHARC_I14: sprintf(info->s, "I14: %08X", (UINT32)cpustate->dag2.i[6]); break;
+ case CPUINFO_STR_REGISTER + SHARC_I15: sprintf(info->s, "I15: %08X", (UINT32)cpustate->dag2.i[7]); break;
+
+ case CPUINFO_STR_REGISTER + SHARC_M0: sprintf(info->s, "M0: %08X", (UINT32)cpustate->dag1.m[0]); break;
+ case CPUINFO_STR_REGISTER + SHARC_M1: sprintf(info->s, "M1: %08X", (UINT32)cpustate->dag1.m[1]); break;
+ case CPUINFO_STR_REGISTER + SHARC_M2: sprintf(info->s, "M2: %08X", (UINT32)cpustate->dag1.m[2]); break;
+ case CPUINFO_STR_REGISTER + SHARC_M3: sprintf(info->s, "M3: %08X", (UINT32)cpustate->dag1.m[3]); break;
+ case CPUINFO_STR_REGISTER + SHARC_M4: sprintf(info->s, "M4: %08X", (UINT32)cpustate->dag1.m[4]); break;
+ case CPUINFO_STR_REGISTER + SHARC_M5: sprintf(info->s, "M5: %08X", (UINT32)cpustate->dag1.m[5]); break;
+ case CPUINFO_STR_REGISTER + SHARC_M6: sprintf(info->s, "M6: %08X", (UINT32)cpustate->dag1.m[6]); break;
+ case CPUINFO_STR_REGISTER + SHARC_M7: sprintf(info->s, "M7: %08X", (UINT32)cpustate->dag1.m[7]); break;
+ case CPUINFO_STR_REGISTER + SHARC_M8: sprintf(info->s, "M8: %08X", (UINT32)cpustate->dag2.m[0]); break;
+ case CPUINFO_STR_REGISTER + SHARC_M9: sprintf(info->s, "M9: %08X", (UINT32)cpustate->dag2.m[1]); break;
+ case CPUINFO_STR_REGISTER + SHARC_M10: sprintf(info->s, "M10: %08X", (UINT32)cpustate->dag2.m[2]); break;
+ case CPUINFO_STR_REGISTER + SHARC_M11: sprintf(info->s, "M11: %08X", (UINT32)cpustate->dag2.m[3]); break;
+ case CPUINFO_STR_REGISTER + SHARC_M12: sprintf(info->s, "M12: %08X", (UINT32)cpustate->dag2.m[4]); break;
+ case CPUINFO_STR_REGISTER + SHARC_M13: sprintf(info->s, "M13: %08X", (UINT32)cpustate->dag2.m[5]); break;
+ case CPUINFO_STR_REGISTER + SHARC_M14: sprintf(info->s, "M14: %08X", (UINT32)cpustate->dag2.m[6]); break;
+ case CPUINFO_STR_REGISTER + SHARC_M15: sprintf(info->s, "M15: %08X", (UINT32)cpustate->dag2.m[7]); break;
+
+ case CPUINFO_STR_REGISTER + SHARC_L0: sprintf(info->s, "L0: %08X", (UINT32)cpustate->dag1.l[0]); break;
+ case CPUINFO_STR_REGISTER + SHARC_L1: sprintf(info->s, "L1: %08X", (UINT32)cpustate->dag1.l[1]); break;
+ case CPUINFO_STR_REGISTER + SHARC_L2: sprintf(info->s, "L2: %08X", (UINT32)cpustate->dag1.l[2]); break;
+ case CPUINFO_STR_REGISTER + SHARC_L3: sprintf(info->s, "L3: %08X", (UINT32)cpustate->dag1.l[3]); break;
+ case CPUINFO_STR_REGISTER + SHARC_L4: sprintf(info->s, "L4: %08X", (UINT32)cpustate->dag1.l[4]); break;
+ case CPUINFO_STR_REGISTER + SHARC_L5: sprintf(info->s, "L5: %08X", (UINT32)cpustate->dag1.l[5]); break;
+ case CPUINFO_STR_REGISTER + SHARC_L6: sprintf(info->s, "L6: %08X", (UINT32)cpustate->dag1.l[6]); break;
+ case CPUINFO_STR_REGISTER + SHARC_L7: sprintf(info->s, "L7: %08X", (UINT32)cpustate->dag1.l[7]); break;
+ case CPUINFO_STR_REGISTER + SHARC_L8: sprintf(info->s, "L8: %08X", (UINT32)cpustate->dag2.l[0]); break;
+ case CPUINFO_STR_REGISTER + SHARC_L9: sprintf(info->s, "L9: %08X", (UINT32)cpustate->dag2.l[1]); break;
+ case CPUINFO_STR_REGISTER + SHARC_L10: sprintf(info->s, "L10: %08X", (UINT32)cpustate->dag2.l[2]); break;
+ case CPUINFO_STR_REGISTER + SHARC_L11: sprintf(info->s, "L11: %08X", (UINT32)cpustate->dag2.l[3]); break;
+ case CPUINFO_STR_REGISTER + SHARC_L12: sprintf(info->s, "L12: %08X", (UINT32)cpustate->dag2.l[4]); break;
+ case CPUINFO_STR_REGISTER + SHARC_L13: sprintf(info->s, "L13: %08X", (UINT32)cpustate->dag2.l[5]); break;
+ case CPUINFO_STR_REGISTER + SHARC_L14: sprintf(info->s, "L14: %08X", (UINT32)cpustate->dag2.l[6]); break;
+ case CPUINFO_STR_REGISTER + SHARC_L15: sprintf(info->s, "L15: %08X", (UINT32)cpustate->dag2.l[7]); break;
+
+ case CPUINFO_STR_REGISTER + SHARC_B0: sprintf(info->s, "B0: %08X", (UINT32)cpustate->dag1.b[0]); break;
+ case CPUINFO_STR_REGISTER + SHARC_B1: sprintf(info->s, "B1: %08X", (UINT32)cpustate->dag1.b[1]); break;
+ case CPUINFO_STR_REGISTER + SHARC_B2: sprintf(info->s, "B2: %08X", (UINT32)cpustate->dag1.b[2]); break;
+ case CPUINFO_STR_REGISTER + SHARC_B3: sprintf(info->s, "B3: %08X", (UINT32)cpustate->dag1.b[3]); break;
+ case CPUINFO_STR_REGISTER + SHARC_B4: sprintf(info->s, "B4: %08X", (UINT32)cpustate->dag1.b[4]); break;
+ case CPUINFO_STR_REGISTER + SHARC_B5: sprintf(info->s, "B5: %08X", (UINT32)cpustate->dag1.b[5]); break;
+ case CPUINFO_STR_REGISTER + SHARC_B6: sprintf(info->s, "B6: %08X", (UINT32)cpustate->dag1.b[6]); break;
+ case CPUINFO_STR_REGISTER + SHARC_B7: sprintf(info->s, "B7: %08X", (UINT32)cpustate->dag1.b[7]); break;
+ case CPUINFO_STR_REGISTER + SHARC_B8: sprintf(info->s, "B8: %08X", (UINT32)cpustate->dag2.b[0]); break;
+ case CPUINFO_STR_REGISTER + SHARC_B9: sprintf(info->s, "B9: %08X", (UINT32)cpustate->dag2.b[1]); break;
+ case CPUINFO_STR_REGISTER + SHARC_B10: sprintf(info->s, "B10: %08X", (UINT32)cpustate->dag2.b[2]); break;
+ case CPUINFO_STR_REGISTER + SHARC_B11: sprintf(info->s, "B11: %08X", (UINT32)cpustate->dag2.b[3]); break;
+ case CPUINFO_STR_REGISTER + SHARC_B12: sprintf(info->s, "B12: %08X", (UINT32)cpustate->dag2.b[4]); break;
+ case CPUINFO_STR_REGISTER + SHARC_B13: sprintf(info->s, "B13: %08X", (UINT32)cpustate->dag2.b[5]); break;
+ case CPUINFO_STR_REGISTER + SHARC_B14: sprintf(info->s, "B14: %08X", (UINT32)cpustate->dag2.b[6]); break;
+ case CPUINFO_STR_REGISTER + SHARC_B15: sprintf(info->s, "B15: %08X", (UINT32)cpustate->dag2.b[7]); break;
+ }
+}
+
+CPU_GET_INFO( adsp21062 )
+{
+ 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(adsp21062); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "ADSP21062"); break;
+
+ default: CPU_GET_INFO_CALL(sharc); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(ADSP21062, adsp21062);
diff --git a/trunk/src/emu/cpu/sharc/sharc.h b/trunk/src/emu/cpu/sharc/sharc.h
new file mode 100644
index 00000000000..1150c74bda4
--- /dev/null
+++ b/trunk/src/emu/cpu/sharc/sharc.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#ifndef __SHARC_H__
+#define __SHARC_H__
+
+
+#define SHARC_INPUT_FLAG0 3
+#define SHARC_INPUT_FLAG1 4
+#define SHARC_INPUT_FLAG2 5
+#define SHARC_INPUT_FLAG3 6
+
+typedef enum
+{
+ BOOT_MODE_EPROM,
+ BOOT_MODE_HOST,
+ BOOT_MODE_LINK,
+ BOOT_MODE_NOBOOT
+} SHARC_BOOT_MODE;
+
+typedef struct {
+ SHARC_BOOT_MODE boot_mode;
+} sharc_config;
+
+extern void sharc_set_flag_input(device_t *device, int flag_num, int state);
+
+extern void sharc_external_iop_write(device_t *device, UINT32 address, UINT32 data);
+extern void sharc_external_dma_write(device_t *device, UINT32 address, UINT64 data);
+
+DECLARE_LEGACY_CPU_DEVICE(ADSP21062, adsp21062);
+
+extern UINT32 sharc_dasm_one(char *buffer, offs_t pc, UINT64 opcode);
+
+#endif /* __SHARC_H__ */
diff --git a/trunk/src/emu/cpu/sharc/sharcdma.c b/trunk/src/emu/cpu/sharc/sharcdma.c
new file mode 100644
index 00000000000..740f68bda14
--- /dev/null
+++ b/trunk/src/emu/cpu/sharc/sharcdma.c
@@ -0,0 +1,204 @@
+/* SHARC DMA operations */
+
+#define DMA_PMODE_NO_PACKING 0
+#define DMA_PMODE_16_32 1
+#define DMA_PMODE_16_48 2
+#define DMA_PMODE_32_48 3
+#define DMA_PMODE_8_48 4
+
+static void schedule_chained_dma_op(SHARC_REGS *cpustate, int channel, UINT32 dma_chain_ptr, int chained_direction)
+{
+ UINT32 op_ptr = 0x20000 + dma_chain_ptr;
+
+ UINT32 int_index = dm_read32(cpustate, op_ptr - 0);
+ UINT32 int_modifier = dm_read32(cpustate, op_ptr - 1);
+ UINT32 int_count = dm_read32(cpustate, op_ptr - 2);
+ UINT32 chain_ptr = dm_read32(cpustate, op_ptr - 3);
+ //UINT32 gen_purpose = dm_read32(cpustate, op_ptr - 4);
+ UINT32 ext_index = dm_read32(cpustate, op_ptr - 5);
+ UINT32 ext_modifier = dm_read32(cpustate, op_ptr - 6);
+ UINT32 ext_count = dm_read32(cpustate, op_ptr - 7);
+
+ if (cpustate->dmaop_cycles > 0)
+ {
+ fatalerror("schedule_chained_dma_op: DMA operation already scheduled at %08X!", cpustate->pc);
+ }
+
+ if (chained_direction) // Transmit to external
+ {
+ cpustate->dmaop_dst = ext_index;
+ cpustate->dmaop_dst_modifier = ext_modifier;
+ cpustate->dmaop_dst_count = ext_count;
+ cpustate->dmaop_src = int_index;
+ cpustate->dmaop_src_modifier = int_modifier;
+ cpustate->dmaop_src_count = int_count;
+ }
+ else // Receive from external
+ {
+ cpustate->dmaop_src = ext_index;
+ cpustate->dmaop_src_modifier = ext_modifier;
+ cpustate->dmaop_src_count = ext_count;
+ cpustate->dmaop_dst = int_index;
+ cpustate->dmaop_dst_modifier = int_modifier;
+ cpustate->dmaop_dst_count = int_count;
+ }
+
+ cpustate->dmaop_pmode = 0;
+ cpustate->dmaop_channel = channel;
+ cpustate->dmaop_cycles = cpustate->dmaop_src_count / 4;
+ cpustate->dmaop_chain_ptr = chain_ptr;
+ cpustate->dmaop_chained_direction = chained_direction;
+}
+
+static void schedule_dma_op(SHARC_REGS *cpustate, int channel, UINT32 src, UINT32 dst, int src_modifier, int dst_modifier, int src_count, int dst_count, int pmode)
+{
+ if (cpustate->dmaop_cycles > 0)
+ {
+ fatalerror("schedule_dma_op: DMA operation already scheduled at %08X!", cpustate->pc);
+ }
+
+ cpustate->dmaop_channel = channel;
+ cpustate->dmaop_src = src;
+ cpustate->dmaop_dst = dst;
+ cpustate->dmaop_src_modifier = src_modifier;
+ cpustate->dmaop_dst_modifier = dst_modifier;
+ cpustate->dmaop_src_count = src_count;
+ cpustate->dmaop_dst_count = dst_count;
+ cpustate->dmaop_pmode = pmode;
+ cpustate->dmaop_chain_ptr = 0;
+ cpustate->dmaop_cycles = src_count / 4;
+}
+
+static void dma_op(SHARC_REGS *cpustate, UINT32 src, UINT32 dst, int src_modifier, int dst_modifier, int src_count, int dst_count, int pmode)
+{
+ int i;
+ //printf("dma_op: %08X, %08X, %08X, %08X, %08X, %08X, %d\n", src, dst, src_modifier, dst_modifier, src_count, dst_count, pmode);
+
+ switch (pmode)
+ {
+ case DMA_PMODE_NO_PACKING:
+ {
+ for (i=0; i < src_count; i++)
+ {
+ UINT32 data = dm_read32(cpustate, src);
+ dm_write32(cpustate, dst, data);
+ src += src_modifier;
+ dst += dst_modifier;
+ }
+ break;
+ }
+ case DMA_PMODE_16_32:
+ {
+ int length = src_count/2;
+ for (i=0; i < length; i++)
+ {
+ UINT32 data = ((dm_read32(cpustate, src+0) & 0xffff) << 16) | (dm_read32(cpustate, src+1) & 0xffff);
+
+ dm_write32(cpustate, dst, data);
+ src += src_modifier * 2;
+ dst += dst_modifier;
+ }
+ break;
+ }
+ case DMA_PMODE_8_48:
+ {
+ int length = src_count/6;
+ for (i=0; i < length; i++)
+ {
+ UINT64 data = ((UINT64)(dm_read32(cpustate, src+0) & 0xff) << 0) |
+ ((UINT64)(dm_read32(cpustate, src+1) & 0xff) << 8) |
+ ((UINT64)(dm_read32(cpustate, src+2) & 0xff) << 16) |
+ ((UINT64)(dm_read32(cpustate, src+3) & 0xff) << 24) |
+ ((UINT64)(dm_read32(cpustate, src+4) & 0xff) << 32) |
+ ((UINT64)(dm_read32(cpustate, src+5) & 0xff) << 40);
+
+ pm_write48(cpustate, dst, data);
+ src += src_modifier * 6;
+ dst += dst_modifier;
+ }
+ break;
+ }
+ default:
+ {
+ fatalerror("SHARC: dma_op: unimplemented packing mode %d\n", pmode);
+ }
+ }
+
+ if (cpustate->dmaop_channel == 6)
+ {
+ cpustate->irptl |= (1 << (cpustate->dmaop_channel+10));
+
+ /* DMA interrupt */
+ if (cpustate->imask & (1 << (cpustate->dmaop_channel+10)))
+ {
+ cpustate->irq_active |= 1 << (cpustate->dmaop_channel+10);
+ }
+ }
+}
+
+static void sharc_dma_exec(SHARC_REGS *cpustate, int channel)
+{
+ UINT32 src, dst;
+ UINT32 src_count, dst_count;
+ UINT32 src_modifier, dst_modifier;
+ int chen, tran, dtype, pmode, /*mswf, master,*/ ishake, intio/*, ext, flsh*/;
+
+ chen = (cpustate->dma[channel].control >> 1) & 0x1;
+ tran = (cpustate->dma[channel].control >> 2) & 0x1;
+ dtype = (cpustate->dma[channel].control >> 5) & 0x1;
+ pmode = (cpustate->dma[channel].control >> 6) & 0x3;
+ //mswf = (cpustate->dma[channel].control >> 8) & 0x1;
+ //master = (cpustate->dma[channel].control >> 9) & 0x1;
+ ishake = (cpustate->dma[channel].control >> 10) & 0x1;
+ intio = (cpustate->dma[channel].control >> 11) & 0x1;
+ //ext = (cpustate->dma[channel].control >> 12) & 0x1;
+ //flsh = (cpustate->dma[channel].control >> 13) & 0x1;
+
+ if (ishake)
+ fatalerror("SHARC: dma_exec: handshake not supported");
+ if (intio)
+ fatalerror("SHARC: dma_exec: single-word interrupt enable not supported");
+
+
+
+ if (chen) // Chained DMA
+ {
+ UINT32 dma_chain_ptr = cpustate->dma[channel].chain_ptr & 0x1ffff;
+
+ schedule_chained_dma_op(cpustate, channel, dma_chain_ptr, tran);
+ }
+ else
+ {
+ if (tran) // Transmit to external
+ {
+ dst = cpustate->dma[channel].ext_index;
+ dst_modifier = cpustate->dma[channel].ext_modifier;
+ dst_count = cpustate->dma[channel].ext_count;
+ src = cpustate->dma[channel].int_index;
+ src_modifier = cpustate->dma[channel].int_modifier;
+ src_count = cpustate->dma[channel].int_count;
+ }
+ else // Receive from external
+ {
+ src = cpustate->dma[channel].ext_index;
+ src_modifier = cpustate->dma[channel].ext_modifier;
+ src_count = cpustate->dma[channel].ext_count;
+ dst = cpustate->dma[channel].int_index;
+ dst_modifier = cpustate->dma[channel].int_modifier;
+ dst_count = cpustate->dma[channel].int_count;
+
+ if (dst < 0x20000)
+ {
+ dst |= 0x20000;
+ }
+ }
+
+ if (dtype)
+ //if (src_count != dst_count)
+ {
+ pmode = DMA_PMODE_8_48;
+ }
+
+ schedule_dma_op(cpustate, channel, src, dst, src_modifier, dst_modifier, src_count, dst_count, pmode);
+ }
+}
diff --git a/trunk/src/emu/cpu/sharc/sharcdsm.c b/trunk/src/emu/cpu/sharc/sharcdsm.c
new file mode 100644
index 00000000000..1c97125aa43
--- /dev/null
+++ b/trunk/src/emu/cpu/sharc/sharcdsm.c
@@ -0,0 +1,1197 @@
+/*
+ Analog Devices ADSP-2106x SHARC Disassembler
+
+ Written by Ville Linde for use in MAME
+*/
+
+#include "emu.h"
+#include "sharcdsm.h"
+
+static UINT32 (* sharcdasm_table[256])(UINT32, UINT64);
+static int dasm_table_built = 0;
+
+#define GET_UREG(x) (ureg_names[x])
+#define GET_SREG(x) (GET_UREG(0x70 | (x & 0xf)))
+#define GET_DREG(x) (GET_UREG(0x00 | (x & 0xf)))
+#define GET_DAG1_I(x) (GET_UREG(0x10 | (x & 0x7)))
+#define GET_DAG1_M(x) (GET_UREG(0x20 | (x & 0x7)))
+#define GET_DAG1_L(x) (GET_UREG(0x30 | (x & 0x7)))
+#define GET_DAG1_B(x) (GET_UREG(0x40 | (x & 0x7)))
+#define GET_DAG2_I(x) (GET_UREG(0x10 | (8 + (x & 0x7))))
+#define GET_DAG2_M(x) (GET_UREG(0x20 | (8 + (x & 0x7))))
+#define GET_DAG2_L(x) (GET_UREG(0x30 | (8 + (x & 0x7))))
+#define GET_DAG2_B(x) (GET_UREG(0x40 | (8 + (x & 0x7))))
+
+#define SIGN_EXTEND6(x) ((x & 0x20) ? (0xffffffc0 | x) : x)
+#define SIGN_EXTEND24(x) ((x & 0x800000) ? (0xff000000 | x) : x)
+
+
+static char *output;
+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 void compute(UINT32 opcode)
+{
+ int op = (opcode >> 12) & 0xff;
+ int cu = (opcode >> 20) & 0x3;
+ int rn = (opcode >> 8) & 0xf;
+ int rx = (opcode >> 4) & 0xf;
+ int ry = (opcode >> 0) & 0xf;
+ int rs = (opcode >> 12) & 0xf;
+ int ra = rn;
+ int rm = rs;
+
+ if (opcode & 0x400000) /* Multi-function opcode */
+ {
+ int multiop = (opcode >> 16) & 0x3f;
+ int rxm = (opcode >> 6) & 0x3;
+ int rym = (opcode >> 4) & 0x3;
+ int rxa = (opcode >> 2) & 0x3;
+ int rya = (opcode >> 0) & 0x3;
+
+ switch(multiop)
+ {
+ case 0x04: print("R%d = R%d * R%d (SSFR), R%d = R%d + R%d", rm, rxm, rym+4, ra, rxa+8, rya+12); break;
+ case 0x05: print("R%d = R%d * R%d (SSFR), R%d = R%d - R%d", rm, rxm, rym+4, ra, rxa+8, rya+12); break;
+ case 0x06: print("R%d = R%d * R%d (SSFR), R%d = (R%d + R%d)/2", rm, rxm, rym+4, ra, rxa+8, rya+12); break;
+ case 0x08: print("MRF = MRF + R%d * R%d (SSF), R%d = R%d + R%d", rxm, rym+4, ra, rxa+8, rya+12); break;
+ case 0x09: print("MRF = MRF + R%d * R%d (SSF), R%d = R%d - R%d", rxm, rym+4, ra, rxa+8, rya+12); break;
+ case 0x0a: print("MRF = MRF + R%d * R%d (SSF), R%d = (R%d + R%d)/2", rxm, rym+4, ra, rxa+8, rya+12); break;
+ case 0x0c: print("R%d = MRF + R%d * R%d (SSFR), R%d = R%d + R%d", rm, rxm, rym+4, ra, rxa+8, rya+12); break;
+ case 0x0d: print("R%d = MRF + R%d * R%d (SSFR), R%d = R%d - R%d", rm, rxm, rym+4, ra, rxa+8, rya+12); break;
+ case 0x0e: print("R%d = MRF + R%d * R%d (SSFR), R%d = (R%d + R%d)/2", rm, rxm, rym+4, ra, rxa+8, rya+12); break;
+ case 0x10: print("MRF = MRF - R%d * R%d (SSF), R%d = R%d + R%d", rxm, rym+4, ra, rxa+8, rya+12); break;
+ case 0x11: print("MRF = MRF - R%d * R%d (SSF), R%d = R%d - R%d", rxm, rym+4, ra, rxa+8, rya+12); break;
+ case 0x12: print("MRF = MRF - R%d * R%d (SSF), R%d = (R%d + R%d)/2", rxm, rym+4, ra, rxa+8, rya+12); break;
+ case 0x14: print("R%d = MRF - R%d * R%d (SSFR), R%d = R%d + R%d", rm, rxm, rym+4, ra, rxa+8, rya+12); break;
+ case 0x15: print("R%d = MRF - R%d * R%d (SSFR), R%d = R%d - R%d", rm, rxm, rym+4, ra, rxa+8, rya+12); break;
+ case 0x16: print("R%d = MRF - R%d * R%d (SSFR), R%d = (R%d + R%d)/2", rm, rxm, rym+4, ra, rxa+8, rya+12); break;
+ case 0x18: print("F%d = F%d * F%d, F%d = F%d + F%d", rm, rxm, rym+4, ra, rxa+8, rya+12); break;
+ case 0x19: print("F%d = F%d * F%d, F%d = F%d - F%d", rm, rxm, rym+4, ra, rxa+8, rya+12); break;
+ case 0x1a: print("F%d = F%d * F%d, F%d = FLOAT F%d BY F%d", rm, rxm, rym+4, ra, rxa+8, rya+12); break;
+ case 0x1b: print("F%d = F%d * F%d, F%d = FIX F%d BY F%d", rm, rxm, rym+4, ra, rxa+8, rya+12); break;
+ case 0x1c: print("F%d = F%d * F%d, F%d = (F%d + F%d)/2", rm, rxm, rym+4, ra, rxa+8, rya+12); break;
+ case 0x1d: print("F%d = F%d * F%d, F%d = ABS F%d", rm, rxm, rym+4, ra, rxa+8); break;
+ case 0x1e: print("F%d = F%d * F%d, F%d = MAX(F%d, F%d)", rm, rxm, rym+4, ra, rxa+8, rya+12); break;
+ case 0x1f: print("F%d = F%d * F%d, F%d = MIN(F%d, F%d)", rm, rxm, rym+4, ra, rxa+8, rya+12); break;
+
+ 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:
+ {
+ print("R%d = R%d * R%d (SSFR), R%d = R%d + R%d, R%d = R%d - R%d", rm, rxm, rym+4, ra, rxa+8, rya+12, rs, rxa+8, rya+12);
+ 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:
+ {
+ print("F%d = F%d * F%d, F%d = F%d + F%d, F%d = F%d - F%d", rm, rxm, rym+4, ra, rxa+8, rya+12, rs, rxa+8, rya+12);
+ break;
+ }
+
+ case 0x00:
+ {
+ int rk = (opcode >> 8) & 0xf;
+ int ai = (opcode >> 12) & 0xf;
+ print("R%d = %s", rk, mr_regnames[ai]);
+ break;
+ }
+ case 0x01:
+ {
+ int rk = (opcode >> 8) & 0xf;
+ int ai = (opcode >> 12) & 0xf;
+ print("%s = R%d", mr_regnames[ai], rk);
+ break;
+ }
+
+ default:
+ {
+ print("??? (COMPUTE, MULTIOP)");
+ break;
+ }
+ }
+ }
+ else /* Single-function */
+ {
+ switch(cu)
+ {
+ /******************/
+ /* ALU operations */
+ /******************/
+ case 0:
+ {
+ switch(op)
+ {
+ /* Fixed-point */
+ case 0x01: print("R%d = R%d + R%d", rn, rx, ry); break;
+ case 0x02: print("R%d = R%d - R%d", rn, rx, ry); break;
+ case 0x05: print("R%d = R%d + R%d + CI", rn, rx, ry); break;
+ case 0x06: print("R%d = R%d - R%d + CI - 1", rn, rx, ry); break;
+ case 0x09: print("R%d = (R%d + R%d)/2", rn, rx, ry); break;
+ case 0x0a: print("COMP(R%d, R%d)", rx, ry); break;
+ case 0x25: print("R%d = R%d + CI", rn, rx); break;
+ case 0x26: print("R%d = R%d + CI - 1", rn, rx); break;
+ case 0x29: print("R%d = R%d + 1", rn, rx); break;
+ case 0x2a: print("R%d = R%d - 1", rn, rx); break;
+ case 0x22: print("R%d = -R%d", rn, rx); break;
+ case 0x30: print("R%d = ABS R%d", rn, rx); break;
+ case 0x21: print("R%d = PASS R%d", rn, rx); break;
+ case 0x40: print("R%d = R%d AND R%d", rn, rx, ry); break;
+ case 0x41: print("R%d = R%d OR R%d", rn, rx, ry); break;
+ case 0x42: print("R%d = R%d XOR R%d", rn, rx, ry); break;
+ case 0x43: print("R%d = NOT R%d", rn, rx); break;
+ case 0x61: print("R%d = MIN(R%d, R%d)", rn, rx, ry); break;
+ case 0x62: print("R%d = MAX(R%d, R%d)", rn, rx, ry); break;
+ case 0x63: print("R%d = CLIP R%d BY R%d", rn, rx, ry); break;
+ /* Floating-point */
+ case 0x81: print("F%d = F%d + F%d", rn, rx, ry); break;
+ case 0x82: print("F%d = F%d - F%d", rn, rx, ry); break;
+ case 0x91: print("F%d = ABS(F%d + F%d)", rn, rx, ry); break;
+ case 0x92: print("F%d = ABS(F%d - F%d)", rn, rx, ry); break;
+ case 0x89: print("F%d = (F%d + F%d)/2", rn, rx, ry); break;
+ case 0x8a: print("COMP(F%d, F%d)", rx, ry); break;
+ case 0xa2: print("F%d = -F%d", rn, rx); break;
+ case 0xb0: print("F%d = ABS F%d", rn, rx); break;
+ case 0xa1: print("F%d = PASS F%d", rn, rx); break;
+ case 0xa5: print("F%d = RND R%d", rn, rx); break;
+ case 0xbd: print("F%d = SCALB F%d BY R%d", rn, rx, ry); break;
+ case 0xad: print("R%d = MANT F%d", rn, rx); break;
+ case 0xc1: print("R%d = LOGB F%d", rn, rx); break;
+ case 0xd9: print("R%d = FIX F%d BY R%d", rn, rx, ry); break;
+ case 0xc9: print("R%d = FIX F%d", rn, rx); break;
+ case 0xdd: print("R%d = TRUNC F%d BY R%d", rn, rx, ry); break;
+ case 0xcd: print("R%d = TRUNC F%d", rn, rx); break;
+ case 0xda: print("F%d = FLOAT R%d BY R%d", rn, rx, ry); break;
+ case 0xca: print("F%d = FLOAT R%d", rn, rx); break;
+ case 0xc4: print("F%d = RECIPS F%d", rn, rx); break;
+ case 0xc5: print("F%d = RSQRTS F%d", rn, rx); break;
+ case 0xe0: print("F%d = F%d COPYSIGN F%d", rn, rx, ry); break;
+ case 0xe1: print("F%d = MIN(F%d, F%d)", rn, rx, ry); break;
+ case 0xe2: print("F%d = MAX(F%d, F%d)", rn, rx, ry); break;
+ case 0xe3: print("F%d = CLIP F%d BY F%d", rn, rx, ry); 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:
+ {
+ print("R%d = R%d + R%d, R%d = R%d - R%d", ra, rx, ry, rs, rx, ry);
+ break;
+ }
+ 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:
+ {
+ print("F%d = F%d + F%d, F%d = F%d - F%d", ra, rx, ry, rs, rx, ry);
+ break;
+ }
+ default:
+ {
+ print("??? (COMPUTE, ALU)");
+ break;
+ }
+ }
+ break;
+ }
+
+ /*************************/
+ /* Multiplier operations */
+ /*************************/
+ case 1:
+ {
+ if( op == 0x30 ) {
+ print("F%d = F%d * F%d", rn, rx, ry);
+ return;
+ }
+
+ switch((op >> 1) & 0x3)
+ {
+ case 0:
+ case 1: print("R%d = ", rn); break;
+ case 2: print("MRF = "); break;
+ case 3: print("MRB = "); break;
+ }
+ switch((op >> 6) & 0x3)
+ {
+ case 0:
+ switch((op >> 4) & 0x3)
+ {
+ case 0: print("SAT %s", (op & 0x2) ? "MRB" : "MRF"); break;
+ case 1:
+ if (op & 0x8)
+ {
+ print("RND %s", (op & 0x2) ? "MRB" : "MRF");
+ }
+ else
+ {
+ print("0");
+ }
+ break;
+ }
+ break;
+
+ case 1:
+ print("R%d * R%d", rx, ry); break;
+
+ case 2:
+ print("%s +(R%d * R%d)", (op & 0x2) ? "MRB" : "MRF", rx, ry); break;
+
+ case 3:
+ print("%s -(R%d * R%d)", (op & 0x2) ? "MRB" : "MRF", rx, ry); break;
+ }
+ break;
+ }
+
+ /**********************/
+ /* Shifter operations */
+ /**********************/
+ case 2:
+ {
+ switch(op)
+ {
+ case 0x00: print("R%d = LSHIFT R%d BY R%d", rn, rx, ry); break;
+ case 0x20: print("R%d = R%d OR LSHIFT R%d BY R%d", rn, rn, rx, ry); break;
+ case 0x04: print("R%d = ASHIFT R%d BY R%d", rn, rx, ry); break;
+ case 0x24: print("R%d = R%d OR ASHIFT R%d BY R%d", rn, rn, rx, ry); break;
+ case 0x08: print("R%d = ROT R%d BY R%d", rn, rx, ry); break;
+ case 0xc4: print("R%d = BCLR R%d BY R%d", rn, rx, ry); break;
+ case 0xc0: print("R%d = BSET R%d BY R%d", rn, rx, ry); break;
+ case 0xc8: print("R%d = BTGL R%d BY R%d", rn, rx, ry); break;
+ case 0xcc: print("BTST R%d BY R%d", rx, ry); break;
+ case 0x44: print("R%d = FDEP R%d BY R%d", rn, rx, ry); break;
+ case 0x64: print("R%d = R%d OR FDEP R%d BY R%d", rn, rn, rx, ry); break;
+ case 0x4c: print("R%d = FDEP R%d BY R%d (SE)", rn, rx, ry); break;
+ case 0x6c: print("R%d = R%d OR FDEP R%d BY R%d (SE)", rn, rn, rx, ry); break;
+ case 0x40: print("R%d = FEXT R%d BY R%d", rn, rx, ry); break;
+ case 0x48: print("R%d = FEXT R%d BY R%d (SE)", rn, rx, ry); break;
+ case 0x80: print("R%d = EXP R%d", rn, rx); break;
+ case 0x84: print("R%d = EXP R%d (EX)", rn, rx); break;
+ case 0x88: print("R%d = LEFTZ R%d", rn, rx); break;
+ case 0x8c: print("R%d = LEFTO R%d", rn, rx); break;
+ case 0x90: print("R%d = FPACK F%d", rn, rx); break;
+ case 0x94: print("F%d = FUNPACK R%d", rn, rx); break;
+ default: print("??? (COMPUTE, SHIFT)"); break;
+ }
+ break;
+ }
+
+ default:
+ {
+ print("??? (COMPUTE)");
+ break;
+ }
+ }
+ }
+}
+
+static void get_if_condition(int cond)
+{
+ if (cond != 31)
+ {
+ print("IF %s, ", condition_codes_if[cond]);
+ }
+}
+
+static void pm_dm_ureg(int g, int d, int i, int m, int ureg, int update)
+{
+ if (update) // post-modify
+ {
+ if (d)
+ {
+ if (g)
+ {
+ print("PM(%s, %s) = %s", GET_DAG2_I(i), GET_DAG2_M(m), GET_UREG(ureg));
+ }
+ else
+ {
+ print("DM(%s, %s) = %s", GET_DAG1_I(i), GET_DAG1_M(m), GET_UREG(ureg));
+ }
+ }
+ else
+ {
+ if (g)
+ {
+ print("%s = PM(%s, %s)", GET_UREG(ureg), GET_DAG2_I(i), GET_DAG2_M(m));
+ }
+ else
+ {
+ print("%s = DM(%s, %s)", GET_UREG(ureg), GET_DAG1_I(i), GET_DAG1_M(m));
+ }
+ }
+
+ }
+ else // pre-modify
+ {
+ if (d)
+ {
+ if (g)
+ {
+ print("PM(%s, %s) = %s", GET_DAG2_M(m), GET_DAG2_I(i), GET_UREG(ureg));
+ }
+ else
+ {
+ print("DM(%s, %s) = %s", GET_DAG1_M(m), GET_DAG1_I(i), GET_UREG(ureg));
+ }
+ }
+ else
+ {
+ if (g)
+ {
+ print("%s = PM(%s, %s)", GET_UREG(ureg), GET_DAG2_M(m), GET_DAG2_I(i));
+ }
+ else
+ {
+ print("%s = DM(%s, %s)", GET_UREG(ureg), GET_DAG1_M(m), GET_DAG1_I(i));
+ }
+ }
+ }
+}
+
+static void pm_dm_imm_dreg(int g, int d, int i, int data, int dreg, int update)
+{
+ if (update) // post-modify
+ {
+ if (d)
+ {
+ if (g)
+ {
+ print("PM(%s, 0x%02X) = %s", GET_DAG2_I(i), data, GET_DREG(dreg));
+ }
+ else
+ {
+ print("DM(%s, 0x%02X) = %s", GET_DAG1_I(i), data, GET_DREG(dreg));
+ }
+ }
+ else
+ {
+ if (g)
+ {
+ print("%s = PM(%s, 0x%02X)", GET_DREG(dreg), GET_DAG2_I(i), data);
+ }
+ else
+ {
+ print("%s = DM(%s, 0x%02X)", GET_DREG(dreg), GET_DAG1_I(i), data);
+ }
+ }
+ }
+ else // pre-modify
+ {
+ if (d)
+ {
+ if (g)
+ {
+ print("PM(0x%02X, %s) = %s", data, GET_DAG2_I(i), GET_DREG(dreg));
+ }
+ else
+ {
+ print("DM(0x%02X, %s) = %s", data, GET_DAG1_I(i), GET_DREG(dreg));
+ }
+ }
+ else
+ {
+ if (g)
+ {
+ print("%s = PM(0x%02X, %s)", GET_DREG(dreg), data, GET_DAG2_I(i));
+ }
+ else
+ {
+ print("%s = DM(0x%02X, %s)", GET_DREG(dreg), data, GET_DAG1_I(i));
+ }
+ }
+ }
+}
+
+static void pm_dm_dreg(int g, int d, int i, int m, int dreg)
+{
+ if (d)
+ {
+ if (g)
+ {
+ print("PM(%s, %s) = %s", GET_DAG2_I(i), GET_DAG2_M(m), GET_DREG(dreg));
+ }
+ else
+ {
+ print("DM(%s, %s) = %s", GET_DAG1_I(i), GET_DAG1_M(m), GET_DREG(dreg));
+ }
+ }
+ else
+ {
+ if (g)
+ {
+ print("%s = PM(%s, %s)", GET_DREG(dreg), GET_DAG2_I(i), GET_DAG2_M(m));
+ }
+ else
+ {
+ print("%s = DM(%s, %s)", GET_DREG(dreg), GET_DAG1_I(i), GET_DAG1_M(m));
+ }
+ }
+}
+
+static void shiftop(int shift, int data, int rn, int rx)
+{
+ INT8 data8 = data & 0xff;
+ int bit6 = data & 0x3f;
+ int len = (data >> 6) & 0x3f;
+
+ switch(shift)
+ {
+ case 0x00: print("R%d = LSHIFT R%d BY %d", rn, rx, data8); break;
+ case 0x08: print("R%d = R%d OR LSHIFT R%d BY %d", rn, rn, rx, data8); break;
+ case 0x01: print("R%d = ASHIFT R%d BY %d", rn, rx, data8); break;
+ case 0x09: print("R%d = R%d OR ASHIFT R%d BY %d", rn, rn, rx, data8); break;
+ case 0x02: print("R%d = ROT R%d BY %d", rn, rx, data8); break;
+ case 0x31: print("R%d = BCLR R%d BY %d", rn, rx, data8); break;
+ case 0x30: print("R%d = BSET R%d BY %d", rn, rx, data8); break;
+ case 0x32: print("R%d = BTGL R%d BY %d", rn, rx, data8); break;
+ case 0x33: print("BTST R%d BY %d", rx, data8); break;
+ case 0x11: print("R%d = FDEP R%d BY %d:%d", rn, rx, bit6, len); break;
+ case 0x19: print("R%d = R%d OR FDEP R%d BY %d:%d", rn, rn, rx, bit6, len); break;
+ case 0x13: print("R%d = FDEP R%d BY %d:%d (SE)", rn, rx, bit6, len); break;
+ case 0x1b: print("R%d = R%d OR FDEP R%d BY %d:%d (SE)", rn, rn, rx, bit6, len); break;
+ case 0x10: print("R%d = FEXT R%d BY %d:%d", rn, rx, bit6, len); break;
+ case 0x12: print("R%d = FEXT R%d BY %d:%d (SE)", rn, rx, bit6, len); break;
+ case 0x20: print("R%d = EXP R%d", rn, rx); break;
+ case 0x21: print("R%d = EXP R%d (EX)", rn, rx); break;
+ case 0x22: print("R%d = LEFTZ R%d", rn, rx); break;
+ case 0x23: print("R%d = LEFTO R%d", rn, rx); break;
+ case 0x24: print("R%d = FPACK F%d", rn, rx); break;
+ case 0x25: print("F%d = FUNPACK R%d", rn, rx); break;
+ default: print("??? (SHIFTOP)"); break;
+ }
+}
+
+
+
+
+
+static UINT32 dasm_compute_dreg_dmpm(UINT32 pc, UINT64 opcode)
+{
+ int dmi = (opcode >> 41) & 0x7;
+ int dmm = (opcode >> 38) & 0x7;
+ int pmi = (opcode >> 30) & 0x7;
+ int pmm = (opcode >> 27) & 0x7;
+ int dmdreg = (opcode >> 33) & 0xf;
+ int pmdreg = (opcode >> 23) & 0xf;
+ int comp = opcode & 0x7fffff;
+
+ if (comp)
+ {
+ compute(comp);
+ print(", ");
+ }
+ print("DM(%s, %s) = R%d, ", GET_DAG1_I(dmi), GET_DAG1_M(dmm), dmdreg);
+ print("PM(%s, %s) = R%d", GET_DAG2_I(pmi), GET_DAG2_M(pmm), pmdreg);
+ return 0;
+}
+
+static UINT32 dasm_compute(UINT32 pc, UINT64 opcode)
+{
+ int cond = (opcode >> 33) & 0x1f;
+ int comp = opcode & 0x7fffff;
+
+ if (comp)
+ {
+ get_if_condition(cond);
+ compute(comp);
+ }
+ return 0;
+}
+
+static UINT32 dasm_compute_uregdmpm_regmod(UINT32 pc, UINT64 opcode)
+{
+ int cond = (opcode >> 33) & 0x1f;
+ int g = (opcode >> 32) & 0x1;
+ int d = (opcode >> 31) & 0x1;
+ int i = (opcode >> 41) & 0x7;
+ int m = (opcode >> 38) & 0x7;
+ int u = (opcode >> 44) & 0x1;
+ int ureg = (opcode >> 23) & 0xff;
+ int comp = opcode & 0x7fffff;
+
+ get_if_condition(cond);
+ if (comp)
+ {
+ compute(comp);
+ print(", ");
+ }
+ pm_dm_ureg(g,d,i,m, ureg, u);
+ return 0;
+}
+
+static UINT32 dasm_compute_dregdmpm_immmod(UINT32 pc, UINT64 opcode)
+{
+ int cond = (opcode >> 33) & 0x1f;
+ int g = (opcode >> 40) & 0x1;
+ int d = (opcode >> 39) & 0x1;
+ int i = (opcode >> 41) & 0x7;
+ int u = (opcode >> 38) & 0x1;
+ int dreg = (opcode >> 23) & 0xf;
+ int data = (opcode >> 27) & 0x3f;
+ int comp = opcode & 0x7fffff;
+
+ get_if_condition(cond);
+ if (comp)
+ {
+ compute(comp);
+ print(", ");
+ }
+ pm_dm_imm_dreg(g,d,i, data, dreg, u);
+ return 0;
+}
+
+static UINT32 dasm_compute_ureg_ureg(UINT32 pc, UINT64 opcode)
+{
+ int cond = (opcode >> 31) & 0x1f;
+ int uregs = (opcode >> 36) & 0xff;
+ int uregd = (opcode >> 23) & 0xff;
+ int comp = opcode & 0x7fffff;
+
+ get_if_condition(cond);
+ if (comp)
+ {
+ compute(comp);
+ print(", ");
+ }
+ print("%s = %s", GET_UREG(uregd), GET_UREG(uregs));
+ return 0;
+}
+
+static UINT32 dasm_immshift_dregdmpm(UINT32 pc, UINT64 opcode)
+{
+ int cond = (opcode >> 33) & 0x1f;
+ int g = (opcode >> 32) & 0x1;
+ int d = (opcode >> 31) & 0x1;
+ int i = (opcode >> 41) & 0x7;
+ int m = (opcode >> 38) & 0x7;
+ int rn = (opcode >> 4) & 0xf;
+ int rx = (opcode >> 0) & 0xf;
+ int shift = (opcode >> 16) & 0x3f;
+ int dreg = (opcode >> 23) & 0xf;
+ int data = (((opcode >> 27) & 0xf) << 8) | ((opcode >> 8) & 0xff);
+
+ get_if_condition(cond);
+ shiftop(shift, data, rn, rx);
+ print(", ");
+ pm_dm_dreg(g,d,i,m, dreg);
+ return 0;
+}
+
+static UINT32 dasm_immshift_dregdmpm_nodata(UINT32 pc, UINT64 opcode)
+{
+ int cond = (opcode >> 33) & 0x1f;
+ int rn = (opcode >> 4) & 0xf;
+ int rx = (opcode >> 0) & 0xf;
+ int shift = (opcode >> 16) & 0x3f;
+ int data = (((opcode >> 27) & 0xf) << 8) | ((opcode >> 8) & 0xff);
+
+ get_if_condition(cond);
+ shiftop(shift, data, rn, rx);
+ return 0;
+}
+
+static UINT32 dasm_compute_modify(UINT32 pc, UINT64 opcode)
+{
+ int cond = (opcode >> 33) & 0x1f;
+ int g = (opcode >> 38) & 0x7;
+ int i = (opcode >> 30) & 0x7;
+ int m = (opcode >> 27) & 0x7;
+ int comp = opcode & 0x7fffff;
+
+ get_if_condition(cond);
+ if (comp)
+ {
+ compute(comp);
+ print(", ");
+ }
+ print("MODIFY(I%d, M%d)", (g ? 8+i : i), (g ? 8+m : m));
+ return 0;
+}
+
+static UINT32 dasm_direct_jump(UINT32 pc, UINT64 opcode)
+{
+ int j = (opcode >> 26) & 0x1;
+ int cond = (opcode >> 33) & 0x1f;
+ int ci = (opcode >> 24) & 0x1;
+ UINT32 addr = opcode & 0xffffff;
+ UINT32 flags = 0;
+
+ get_if_condition(cond);
+ if (opcode & U64(0x8000000000))
+ {
+ print("CALL");
+ flags = DASMFLAG_STEP_OVER;
+ }
+ else
+ {
+ print("JUMP");
+ }
+
+ if (opcode & U64(0x10000000000)) /* PC-relative branch */
+ {
+ print(" (0x%08X)", pc + SIGN_EXTEND24(addr));
+ }
+ else /* Indirect branch */
+ {
+ print(" (0x%08X)", addr);
+ }
+ if (j)
+ {
+ print(" (DB)");
+ }
+ if (ci)
+ {
+ print(" (CI)");
+ }
+ return flags;
+}
+
+static UINT32 dasm_indirect_jump_compute(UINT32 pc, UINT64 opcode)
+{
+ int b = (opcode >> 39) & 0x1;
+ int j = (opcode >> 26) & 0x1;
+ int e = (opcode >> 25) & 0x1;
+ int ci = (opcode >> 24) & 0x1;
+ int cond = (opcode >> 33) & 0x1f;
+ int pmi = (opcode >> 30) & 0x7;
+ int pmm = (opcode >> 27) & 0x7;
+ int reladdr = (opcode >> 27) & 0x3f;
+ int comp = opcode & 0x7fffff;
+ UINT32 flags = 0;
+
+ get_if_condition(cond);
+ if (b)
+ {
+ print("CALL");
+ flags = DASMFLAG_STEP_OVER;
+ }
+ else
+ {
+ print("JUMP");
+ }
+
+ if (opcode & U64(0x10000000000)) /* PC-relative branch */
+ {
+ print(" (0x%08X)", pc + SIGN_EXTEND6(reladdr));
+ }
+ else /* Indirect branch */
+ {
+ print(" (%s, %s)", GET_DAG2_M(pmm), GET_DAG2_I(pmi));
+ }
+ if (j)
+ {
+ print(" (DB)");
+ }
+ if (ci)
+ {
+ print(" (CI)");
+ }
+
+ if (comp)
+ {
+ print(", ");
+ if (e)
+ {
+ print("ELSE ");
+ }
+
+ compute(comp);
+ }
+ return flags;
+}
+
+static UINT32 dasm_indirect_jump_compute_dregdm(UINT32 pc, UINT64 opcode)
+{
+ int d = (opcode >> 44) & 0x1;
+ int cond = (opcode >> 33) & 0x1f;
+ int pmi = (opcode >> 30) & 0x7;
+ int pmm = (opcode >> 27) & 0x7;
+ int dmi = (opcode >> 41) & 0x7;
+ int dmm = (opcode >> 38) & 0x7;
+ int reladdr = (opcode >> 27) & 0x3f;
+ int dreg = (opcode >> 23) & 0xf;
+ int comp = opcode & 0x7fffff;
+
+ get_if_condition(cond);
+ print("JUMP");
+
+ if (opcode & U64(0x200000000000)) /* PC-relative branch */
+ {
+ print(" (0x%08X)", pc + SIGN_EXTEND6(reladdr));
+ }
+ else /* Indirect branch */
+ {
+ print(" (%s, %s)", GET_DAG2_M(pmm), GET_DAG2_I(pmi));
+ }
+ print(", ELSE ");
+
+ if (comp)
+ {
+ compute(comp);
+ print(", ");
+ }
+ if (d)
+ {
+ print("%s = DM(%s, %s)", GET_DREG(dreg), GET_DAG1_I(dmi), GET_DAG1_M(dmm));
+ }
+ else
+ {
+ print("DM(%s, %s) = %s", GET_DAG1_I(dmi), GET_DAG1_M(dmm), GET_DREG(dreg));
+ }
+ return 0;
+}
+
+static UINT32 dasm_rts_compute(UINT32 pc, UINT64 opcode)
+{
+ int j = (opcode >> 26) & 0x1;
+ int e = (opcode >> 25) & 0x1;
+ int lr = (opcode >> 24) & 0x1;
+ int cond = (opcode >> 33) & 0x1f;
+ int comp = opcode & 0x7fffff;
+
+ get_if_condition(cond);
+
+ if (opcode & U64(0x10000000000))
+ {
+ print("RTI");
+ }
+ else
+ {
+ print("RTS");
+ }
+
+ if (j)
+ {
+ print(" (DB)");
+ }
+ if (lr)
+ {
+ print(" (LR)");
+ }
+
+ if (comp)
+ {
+ print(", ");
+ if (e)
+ {
+ print("ELSE ");
+ }
+
+ compute(comp);
+ }
+ return DASMFLAG_STEP_OUT;
+}
+
+static UINT32 dasm_do_until_counter(UINT32 pc, UINT64 opcode)
+{
+ int data = (opcode >> 24) & 0xffff;
+ int ureg = (opcode >> 32) & 0xff;
+ UINT32 addr = opcode & 0xffffff;
+
+ if (opcode & U64(0x10000000000)) /* Loop counter from universal register */
+ {
+ print("LCNTR = %s, ", GET_UREG(ureg));
+ print("DO (0x%08X)", pc + SIGN_EXTEND24(addr));
+ }
+ else /* Loop counter from immediate */
+ {
+ print("LCNTR = 0x%04X, ", data);
+ print("DO (0x%08X) UNTIL LCE", pc + SIGN_EXTEND24(addr));
+ }
+ return 0;
+}
+
+static UINT32 dasm_do_until(UINT32 pc, UINT64 opcode)
+{
+ int term = (opcode >> 33) & 0x1f;
+ UINT32 addr = opcode & 0xffffff;
+
+ print("DO (0x%08X) UNTIL %s", pc + SIGN_EXTEND24(addr), condition_codes_do[term]);
+ return 0;
+}
+
+static UINT32 dasm_immmove_uregdmpm(UINT32 pc, UINT64 opcode)
+{
+ int d = (opcode >> 40) & 0x1;
+ int g = (opcode >> 41) & 0x1;
+ int ureg = (opcode >> 32) & 0xff;
+ UINT32 addr = opcode & 0xffffffff;
+
+ if (g)
+ {
+ if (d)
+ {
+ print("PM(0x%08X) = %s", addr, GET_UREG(ureg));
+ }
+ else
+ {
+ print("%s = PM(0x%08X)", GET_UREG(ureg), addr);
+ }
+ }
+ else
+ {
+ if (d)
+ {
+ print("DM(0x%08X) = %s", addr, GET_UREG(ureg));
+ }
+ else
+ {
+ print("%s = DM(0x%08X)", GET_UREG(ureg), addr);
+ }
+ }
+ return 0;
+}
+
+static UINT32 dasm_immmove_uregdmpm_indirect(UINT32 pc, UINT64 opcode)
+{
+ int d = (opcode >> 40) & 0x1;
+ int g = (opcode >> 44) & 0x1;
+ int i = (opcode >> 41) & 0x7;
+ int ureg = (opcode >> 32) & 0xff;
+ UINT32 addr = opcode & 0xffffffff;
+
+ if (g)
+ {
+ if (d)
+ {
+ print("PM(0x%08X, %s) = %s", addr, GET_DAG2_I(i), GET_UREG(ureg));
+ }
+ else
+ {
+ print("%s = PM(0x%08X, %s)", GET_UREG(ureg), addr, GET_DAG2_I(i));
+ }
+ }
+ else
+ {
+ if (d)
+ {
+ print("DM(0x%08X, %s) = %s", addr, GET_DAG1_I(i), GET_UREG(ureg));
+ }
+ else
+ {
+ print("%s = DM(0x%08X, %s)", GET_UREG(ureg), addr, GET_DAG1_I(i));
+ }
+ }
+ return 0;
+}
+
+static UINT32 dasm_immmove_immdata_dmpm(UINT32 pc, UINT64 opcode)
+{
+ int g = (opcode >> 37) & 0x1;
+ int i = (opcode >> 41) & 0x7;
+ int m = (opcode >> 38) & 0x7;
+ UINT32 data = opcode & 0xffffffff;
+
+ if (g)
+ {
+ print("PM(%s, %s) = 0x%08X", GET_DAG2_I(i), GET_DAG2_M(m), data);
+ }
+ else
+ {
+ print("DM(%s, %s) = 0x%08X", GET_DAG1_I(i), GET_DAG1_M(m), data);
+ }
+ return 0;
+}
+
+static UINT32 dasm_immmove_immdata_ureg(UINT32 pc, UINT64 opcode)
+{
+ int ureg = (opcode >> 32) & 0xff;
+ UINT32 data = opcode & 0xffffffff;
+
+ print("%s = 0x%08X", GET_UREG(ureg), data);
+ return 0;
+}
+
+static UINT32 dasm_sysreg_bitop(UINT32 pc, UINT64 opcode)
+{
+ int bop = (opcode >> 37) & 0x7;
+ int sreg = (opcode >> 32) & 0xf;
+ UINT32 data = opcode & 0xffffffff;
+
+ print("BIT ");
+ print("%s ", bopnames[bop]);
+ print("%s ", GET_SREG(sreg));
+ print("0x%08X", data);
+ return 0;
+}
+
+static UINT32 dasm_ireg_modify(UINT32 pc, UINT64 opcode)
+{
+ int g = (opcode >> 38) & 0x1;
+ int i = (opcode >> 32) & 0x7;
+ UINT32 data = opcode & 0xffffffff;
+
+ if (opcode & U64(0x8000000000)) /* with bit-reverse */
+ {
+ if (g)
+ {
+ print("BITREV (%s, 0x%08X)", GET_DAG2_I(i), data);
+ }
+ else
+ {
+ print("BITREV (%s, 0x%08X)", GET_DAG1_I(i), data);
+ }
+ }
+ else /* without bit-reverse */
+ {
+ if (g)
+ {
+ print("MODIFY (%s, 0x%08X)", GET_DAG2_I(i), data);
+ }
+ else
+ {
+ print("MODIFY (%s, 0x%08X)", GET_DAG1_I(i), data);
+ }
+ }
+ return 0;
+}
+
+static UINT32 dasm_misc(UINT32 pc, UINT64 opcode)
+{
+ int bits = (opcode >> 33) & 0x7f;
+ int lpu = (opcode >> 39) & 0x1;
+ int lpo = (opcode >> 38) & 0x1;
+ int spu = (opcode >> 37) & 0x1;
+ int spo = (opcode >> 36) & 0x1;
+ int ppu = (opcode >> 35) & 0x1;
+ int ppo = (opcode >> 34) & 0x1;
+ int fc = (opcode >> 33) & 0x1;
+
+ if (lpu)
+ {
+ print("PUSH LOOP");
+ if (bits & 0x3f)
+ {
+ print(", ");
+ }
+ }
+ if (lpo)
+ {
+ print("POP LOOP");
+ if (bits & 0x1f)
+ {
+ print(", ");
+ }
+ }
+ if (spu)
+ {
+ print("PUSH STS");
+ if (bits & 0xf)
+ {
+ print(", ");
+ }
+ }
+ if (spo)
+ {
+ print("POP STS");
+ if (bits & 0x7)
+ {
+ print(", ");
+ }
+ }
+ if (ppu)
+ {
+ print("PUSH PCSTK");
+ if (bits & 0x3)
+ {
+ print(", ");
+ }
+ }
+ if (ppo)
+ {
+ print("POP PCSTK");
+ if (bits & 0x1)
+ {
+ print(", ");
+ }
+ }
+ if (fc)
+ {
+ print("FLUSH CACHE");
+ }
+ return 0;
+}
+
+static UINT32 dasm_idlenop(UINT32 pc, UINT64 opcode)
+{
+ if (opcode & U64(0x8000000000))
+ {
+ print("IDLE");
+ }
+ else
+ {
+ print("NOP");
+ }
+ return 0;
+}
+
+#ifdef UNUSED_FUNCTION
+static UINT32 dasm_cjump_rframe(UINT32 pc, UINT64 opcode)
+{
+ /* TODO */
+ if (opcode & U64(0x10000000000)) /* RFRAME */
+ {
+ print("TODO: RFRAME");
+ }
+ else
+ {
+ print("TODO: CJUMP");
+ }
+ return 0;
+}
+#endif
+
+static UINT32 dasm_invalid(UINT32 pc, UINT64 opcode)
+{
+ print("?");
+ return 0;
+}
+
+static const SHARC_DASM_OP sharc_dasm_ops[] =
+{
+ // |0 0 1|
+ { 0xe000, 0x2000, dasm_compute_dreg_dmpm },
+
+ // |0 0 0|0 0 0 0 1|
+ { 0xff00, 0x0100, dasm_compute },
+
+ // |0 1 0|
+ { 0xe000, 0x4000, dasm_compute_uregdmpm_regmod },
+
+ // |0 1 1|0|
+ { 0xf000, 0x6000, dasm_compute_dregdmpm_immmod },
+
+ // |0 1 1|1|
+ { 0xf000, 0x7000, dasm_compute_ureg_ureg },
+
+ // |1 0 0|0|
+ { 0xf000, 0x8000, dasm_immshift_dregdmpm },
+
+ // |0 0 0|0 0 0 1 0|
+ { 0xff00, 0x0200, dasm_immshift_dregdmpm_nodata },
+
+ // |0 0 0|0 0 1 0 0|
+ { 0xff00, 0x0400, dasm_compute_modify },
+
+ // |0 0 0|0 0 1 1 x|
+ { 0xfe00, 0x0600, dasm_direct_jump },
+
+ // |0 0 0|0 1 0 0 x|
+ { 0xfe00, 0x0800, dasm_indirect_jump_compute },
+
+ // |1 1 x|
+ { 0xc000, 0xc000, dasm_indirect_jump_compute_dregdm },
+
+ // |0 0 0|0 1 0 1 x|
+ { 0xfe00, 0x0a00, dasm_rts_compute },
+
+ // |0 0 0|0 1 1 0 x|
+ { 0xfe00, 0x0c00, dasm_do_until_counter },
+
+ // |0 0 0|0 1 1 1 0|
+ { 0xff00, 0x0e00, dasm_do_until },
+
+ // |0 0 0|1 0 0|x|x|
+ { 0xfc00, 0x1000, dasm_immmove_uregdmpm },
+
+ // |1 0 1|x|x x x|x|
+ { 0xe000, 0xa000, dasm_immmove_uregdmpm_indirect },
+
+ // |1 0 0|1|
+ { 0xf000, 0x9000, dasm_immmove_immdata_dmpm },
+
+ // |0 0 0|0 1 1 1 1|
+ { 0xff00, 0x0f00, dasm_immmove_immdata_ureg },
+
+ // |0 0 0|1 0 1 0 0|
+ { 0xff00, 0x1400, dasm_sysreg_bitop },
+
+ // |0 0 0|1 0 1 1 0|
+ { 0xff00, 0x1600, dasm_ireg_modify },
+
+ // |0 0 0|1 0 1 1 1|
+ { 0xff00, 0x1700, dasm_misc },
+
+ // |0 0 0|0 0 0 0 0|
+ { 0xff00, 0x0000, dasm_idlenop },
+};
+
+static void build_dasm_table(void)
+{
+ int i, j;
+ int num_ops = sizeof(sharc_dasm_ops) / sizeof(SHARC_DASM_OP);
+
+ for (i=0; i < 256; i++)
+ {
+ sharcdasm_table[i] = dasm_invalid;
+ }
+
+ for (i=0; i < 256; i++)
+ {
+ UINT16 op = i << 8;
+
+ for (j=0; j < num_ops; j++)
+ {
+ if ((sharc_dasm_ops[j].op_mask & op) == sharc_dasm_ops[j].op_bits)
+ {
+ if (sharcdasm_table[i] != dasm_invalid)
+ {
+ fatalerror("build_dasm_table: table already filled! (i=%04X, j=%d)\n", i, j);
+ }
+ else
+ {
+ sharcdasm_table[i] = sharc_dasm_ops[j].handler;
+ }
+ }
+ }
+ }
+}
+
+static UINT32 sharc_dasm_one(char *buffer, offs_t pc, UINT64 opcode)
+{
+ #define DEFAULT_DASM_WIDTH (64)
+
+ char dasm_buffer[2000];
+ int i;
+ int op = (opcode >> 40) & 0xff;
+ UINT32 flags;
+
+ if (!dasm_table_built)
+ {
+ build_dasm_table();
+ dasm_table_built = 1;
+ }
+
+ memset(dasm_buffer, 0, sizeof(dasm_buffer));
+
+ /* set buffer for print */
+ output = dasm_buffer;
+
+ flags = (*sharcdasm_table[op])(pc, opcode);
+
+ for (i=0; i < DEFAULT_DASM_WIDTH; i++)
+ {
+ buffer[i] = dasm_buffer[i];
+ }
+ return flags;
+}
+
+
+CPU_DISASSEMBLE( sharc )
+{
+ UINT64 op = 0;
+ UINT32 flags = 0;
+
+ op = ((UINT64)oprom[0] << 0) | ((UINT64)oprom[1] << 8) |
+ ((UINT64)oprom[2] << 16) | ((UINT64)oprom[3] << 24) |
+ ((UINT64)oprom[4] << 32) | ((UINT64)oprom[5] << 40);
+
+ flags = sharc_dasm_one(buffer, pc, op);
+ return 1 | flags | DASMFLAG_SUPPORTED;
+}
+
+
diff --git a/trunk/src/emu/cpu/sharc/sharcdsm.h b/trunk/src/emu/cpu/sharc/sharcdsm.h
new file mode 100644
index 00000000000..d84563943ad
--- /dev/null
+++ b/trunk/src/emu/cpu/sharc/sharcdsm.h
@@ -0,0 +1,77 @@
+static const char ureg_names[256][16] =
+{
+ "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
+ "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15",
+ "I0", "I1", "I2", "I3", "I4", "I5", "I6", "I7",
+ "I8", "I9", "I10", "I11", "I12", "I13", "I14", "I15",
+ "M0", "M1", "M2", "M3", "M4", "M5", "M6", "M7",
+ "M8", "M9", "M10", "M11", "M12", "M13", "M14", "M15",
+ "L0", "L1", "L2", "L3", "L4", "L5", "L6", "L7",
+ "L8", "L9", "L10", "L11", "L12", "L13", "L14", "L15",
+ "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7",
+ "B8", "B9", "B10", "B11", "B12", "B13", "B14", "B15",
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ "FADDR", "DADDR", "???", "PC", "PCSTK", "PCSTKP", "LADDR", "CURLCNTR",
+ "LCNTR", "???", "???", "???", "???", "???", "???", "???",
+ "USTAT1", "USTAT2", "???", "???", "???", "???", "???", "???",
+ "???", "IRPTL", "MODE2", "MODE1", "ASTAT", "IMASK", "STKY", "IMASKP",
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ "???", "???", "???", "PX", "PX1", "PX2", "TPERIOD", "TCOUNT",
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ "???", "???", "???", "???", "???", "???", "???", "???"
+};
+
+static const char bopnames[8][8] =
+{
+ "SET", "CLEAR", "TOGGLE", "???", "TEST", "XOR", "???", "???"
+};
+
+static const char condition_codes_if[32][32] =
+{
+ "EQ", "LT", "LE", "AC",
+ "AV", "MV", "MS", "SV",
+ "SZ", "FLAG0_IN", "FLAG1_IN", "FLAG2_IN",
+ "FLAG3_IN", "TF", "BM", "NOT LCE",
+ "NE", "GE", "GT", "NOT AC",
+ "NOT AV", "NOT MV", "NOT MS", "NOT SV",
+ "NOT SZ", "NOT FLAG0_IN", "NOT FLAG1_IN", "NOT FLAG2_IN",
+ "NOT FLAG3_IN", "NOT TF", "NBM", ""
+};
+
+static const char condition_codes_do[32][32] =
+{
+ "EQ", "LT", "LE", "AC",
+ "AV", "MV", "MS", "SV",
+ "SZ", "FLAG0_IN", "FLAG1_IN", "FLAG2_IN",
+ "FLAG3_IN", "TF", "BM", "LCE",
+ "NE", "GE", "GT", "NOT AC",
+ "NOT AV", "NOT MV", "NOT MS", "NOT SV",
+ "NOT SZ", "NOT FLAG0_IN", "NOT FLAG1_IN", "NOT FLAG2_IN",
+ "NOT FLAG3_IN", "NOT TF", "NBM", "FOREVER"
+};
+
+static const char mr_regnames[16][8] =
+{
+ "MR0F", "MR1F", "MR2F", "MR0B", "MR1B", "MR2B", "???", "???",
+ "???", "???", "???", "???", "???", "???", "???", "???"
+};
+
+typedef struct
+{
+ UINT32 op_mask;
+ UINT32 op_bits;
+ UINT32 (* handler)(UINT32, UINT64);
+} SHARC_DASM_OP;
diff --git a/trunk/src/emu/cpu/sharc/sharcmem.c b/trunk/src/emu/cpu/sharc/sharcmem.c
new file mode 100644
index 00000000000..79d8f3679a1
--- /dev/null
+++ b/trunk/src/emu/cpu/sharc/sharcmem.c
@@ -0,0 +1,202 @@
+/* SHARC memory operations */
+
+static UINT32 pm_read32(SHARC_REGS *cpustate, UINT32 address)
+{
+ if (address >= 0x20000 && address < 0x28000)
+ {
+ UINT32 addr = (address & 0x7fff) * 3;
+
+ return (UINT32)(cpustate->internal_ram_block0[addr + 0] << 16) |
+ (cpustate->internal_ram_block0[addr + 1]);
+ }
+ else if (address >= 0x28000 && address < 0x40000)
+ {
+ // block 1 is mirrored in 0x28000...2ffff, 0x30000...0x37fff and 0x38000...3ffff
+ UINT32 addr = (address & 0x7fff) * 3;
+
+ return (UINT32)(cpustate->internal_ram_block1[addr + 0] << 16) |
+ (cpustate->internal_ram_block1[addr + 1]);
+ }
+ else {
+ fatalerror("SHARC: PM Bus Read %08X at %08X", address, cpustate->pc);
+ }
+}
+
+static void pm_write32(SHARC_REGS *cpustate, UINT32 address, UINT32 data)
+{
+ if (address >= 0x20000 && address < 0x28000)
+ {
+ UINT32 addr = (address & 0x7fff) * 3;
+
+ cpustate->internal_ram_block0[addr + 0] = (UINT16)(data >> 16);
+ cpustate->internal_ram_block0[addr + 1] = (UINT16)(data);
+ return;
+ }
+ else if (address >= 0x28000 && address < 0x40000)
+ {
+ // block 1 is mirrored in 0x28000...2ffff, 0x30000...0x37fff and 0x38000...3ffff
+ UINT32 addr = (address & 0x7fff) * 3;
+
+ cpustate->internal_ram_block1[addr + 0] = (UINT16)(data >> 16);
+ cpustate->internal_ram_block1[addr + 1] = (UINT16)(data);
+ return;
+ }
+ else {
+ fatalerror("SHARC: PM Bus Write %08X, %08X at %08X", address, data, cpustate->pc);
+ }
+}
+
+static UINT64 pm_read48(SHARC_REGS *cpustate, UINT32 address)
+{
+ if (address >= 0x20000 && address < 0x28000)
+ {
+ UINT32 addr = (address & 0x7fff) * 3;
+
+ return ((UINT64)(cpustate->internal_ram_block0[addr + 0]) << 32) |
+ ((UINT64)(cpustate->internal_ram_block0[addr + 1]) << 16) |
+ ((UINT64)(cpustate->internal_ram_block0[addr + 2]) << 0);
+ }
+ else if (address >= 0x28000 && address < 0x40000)
+ {
+ // block 1 is mirrored in 0x28000...2ffff, 0x30000...0x37fff and 0x38000...3ffff
+ UINT32 addr = (address & 0x7fff) * 3;
+
+ return ((UINT64)(cpustate->internal_ram_block1[addr + 0]) << 32) |
+ ((UINT64)(cpustate->internal_ram_block1[addr + 1]) << 16) |
+ ((UINT64)(cpustate->internal_ram_block1[addr + 2]) << 0);
+ }
+ else {
+ fatalerror("SHARC: PM Bus Read %08X at %08X", address, cpustate->pc);
+ }
+
+ return 0;
+}
+
+static void pm_write48(SHARC_REGS *cpustate, UINT32 address, UINT64 data)
+{
+ if (address >= 0x20000 && address < 0x28000)
+ {
+ UINT32 addr = (address & 0x7fff) * 3;
+
+ cpustate->internal_ram_block0[addr + 0] = (UINT16)(data >> 32);
+ cpustate->internal_ram_block0[addr + 1] = (UINT16)(data >> 16);
+ cpustate->internal_ram_block0[addr + 2] = (UINT16)(data);
+ return;
+ }
+ else if (address >= 0x28000 && address < 0x40000)
+ {
+ // block 1 is mirrored in 0x28000...2ffff, 0x30000...0x37fff and 0x38000...3ffff
+ UINT32 addr = (address & 0x7fff) * 3;
+
+ cpustate->internal_ram_block1[addr + 0] = (UINT16)(data >> 32);
+ cpustate->internal_ram_block1[addr + 1] = (UINT16)(data >> 16);
+ cpustate->internal_ram_block1[addr + 2] = (UINT16)(data);
+ return;
+ }
+ else {
+ fatalerror("SHARC: PM Bus Write %08X, %04X%08X at %08X", address, (UINT16)(data >> 32),(UINT32)data, cpustate->pc);
+ }
+}
+
+static UINT32 dm_read32(SHARC_REGS *cpustate, UINT32 address)
+{
+ if (address < 0x100)
+ {
+ return sharc_iop_r(cpustate, address);
+ }
+ else if (address >= 0x20000 && address < 0x28000)
+ {
+ UINT32 addr = (address & 0x7fff) * 2;
+
+ return (UINT32)(cpustate->internal_ram_block0[addr + 0] << 16) |
+ (cpustate->internal_ram_block0[addr + 1]);
+ }
+ else if (address >= 0x28000 && address < 0x40000)
+ {
+ // block 1 is mirrored in 0x28000...2ffff, 0x30000...0x37fff and 0x38000...3ffff
+ UINT32 addr = (address & 0x7fff) * 2;
+
+ return (UINT32)(cpustate->internal_ram_block1[addr + 0] << 16) |
+ (cpustate->internal_ram_block1[addr + 1]);
+ }
+
+ // short word addressing
+ else if (address >= 0x40000 && address < 0x50000)
+ {
+ UINT32 addr = address & 0xffff;
+
+ UINT16 r = cpustate->internal_ram_block0[addr ^ 1];
+ if (cpustate->mode1 & 0x4000)
+ {
+ // sign-extend
+ return (INT32)(INT16)(r);
+ }
+ else
+ {
+ return (UINT32)(r);
+ }
+ }
+ else if (address >= 0x50000 && address < 0x80000)
+ {
+ // block 1 is mirrored in 0x50000...5ffff, 0x60000...0x6ffff and 0x70000...7ffff
+ UINT32 addr = address & 0xffff;
+
+ UINT16 r = cpustate->internal_ram_block1[addr ^ 1];
+ if (cpustate->mode1 & 0x4000)
+ {
+ // sign-extend
+ return (INT32)(INT16)(r);
+ }
+ else
+ {
+ return (UINT32)(r);
+ }
+ }
+
+ return cpustate->data->read_dword(address << 2);
+}
+
+static void dm_write32(SHARC_REGS *cpustate, UINT32 address, UINT32 data)
+{
+ if (address < 0x100)
+ {
+ sharc_iop_w(cpustate, address, data);
+ return;
+ }
+ else if (address >= 0x20000 && address < 0x28000)
+ {
+ UINT32 addr = (address & 0x7fff) * 2;
+
+ cpustate->internal_ram_block0[addr + 0] = (UINT16)(data >> 16);
+ cpustate->internal_ram_block0[addr + 1] = (UINT16)(data);
+ return;
+ }
+ else if (address >= 0x28000 && address < 0x40000)
+ {
+ // block 1 is mirrored in 0x28000...2ffff, 0x30000...0x37fff and 0x38000...3ffff
+ UINT32 addr = (address & 0x7fff) * 2;
+
+ cpustate->internal_ram_block1[addr + 0] = (UINT16)(data >> 16);
+ cpustate->internal_ram_block1[addr + 1] = (UINT16)(data);
+ return;
+ }
+
+ // short word addressing
+ else if (address >= 0x40000 && address < 0x50000)
+ {
+ UINT32 addr = address & 0xffff;
+
+ cpustate->internal_ram_block0[addr ^ 1] = data;
+ return;
+ }
+ else if (address >= 0x50000 && address < 0x80000)
+ {
+ // block 1 is mirrored in 0x50000...5ffff, 0x60000...0x6ffff and 0x70000...7ffff
+ UINT32 addr = address & 0xffff;
+
+ cpustate->internal_ram_block1[addr ^ 1] = data;
+ return;
+ }
+
+ cpustate->data->write_dword(address << 2, data);
+}
diff --git a/trunk/src/emu/cpu/sharc/sharcops.c b/trunk/src/emu/cpu/sharc/sharcops.c
new file mode 100644
index 00000000000..bbe2bc2414a
--- /dev/null
+++ b/trunk/src/emu/cpu/sharc/sharcops.c
@@ -0,0 +1,2754 @@
+#define SIGN_EXTEND6(x) (((x) & 0x20) ? (0xffffffc0 | (x)) : (x))
+#define SIGN_EXTEND24(x) (((x) & 0x800000) ? (0xff000000 | (x)) : (x))
+
+#define PM_REG_I(x) (cpustate->dag2.i[x])
+#define PM_REG_M(x) (cpustate->dag2.m[x])
+#define PM_REG_B(x) (cpustate->dag2.b[x])
+#define PM_REG_L(x) (cpustate->dag2.l[x])
+#define DM_REG_I(x) (cpustate->dag1.i[x])
+#define DM_REG_M(x) (cpustate->dag1.m[x])
+#define DM_REG_B(x) (cpustate->dag1.b[x])
+#define DM_REG_L(x) (cpustate->dag1.l[x])
+
+// ASTAT flags
+#define AZ 0x1 /* ALU result zero */
+#define AV 0x2 /* ALU overflow */
+#define AN 0x4 /* ALU result negative */
+#define AC 0x8 /* ALU fixed-point carry */
+#define AS 0x10 /* ALU X input sign */
+#define AI 0x20 /* ALU floating-point invalid operation */
+#define MN 0x40 /* Multiplier result negative */
+#define MV 0x80 /* Multiplier overflow */
+#define MU 0x100 /* Multiplier underflow */
+#define MI 0x200 /* Multiplier floating-point invalid operation */
+#define AF 0x400
+#define SV 0x800 /* Shifter overflow */
+#define SZ 0x1000 /* Shifter result zero */
+#define SS 0x2000 /* Shifter input sign */
+#define BTF 0x40000 /* Bit Test Flag */
+#define FLG0 0x80000 /* FLAG0 */
+#define FLG1 0x100000 /* FLAG1 */
+#define FLG2 0x200000 /* FLAG2 */
+#define FLG3 0x400000 /* FLAG3 */
+
+// STKY flags
+#define AUS 0x1 /* ALU floating-point underflow */
+#define AVS 0x2 /* ALU floating-point overflow */
+#define AOS 0x4 /* ALU fixed-point overflow */
+#define AIS 0x20 /* ALU floating-point invalid operation */
+
+// MODE1 flags
+#define MODE1_BR8 0x1 /* Bit-reverse for I8 */
+#define MODE1_BR0 0x2 /* Bit-reverse for I0 */
+#define MODE1_SRCU 0x4 /* Alternate register select for computational units */
+#define MODE1_SRD1H 0x8 /* DAG alternate register select (7-4) */
+#define MODE1_SRD1L 0x10 /* DAG alternate register select (3-0) */
+#define MODE1_SRD2H 0x20 /* DAG alternate register select (15-12) */
+#define MODE1_SRD2L 0x40 /* DAG alternate register select (11-8) */
+#define MODE1_SRRFH 0x80 /* Register file alternate select for R(15-8) */
+#define MODE1_SRRFL 0x400 /* Register file alternate select for R(7-0) */
+#define MODE1_NESTM 0x800 /* Interrupt nesting enable */
+#define MODE1_IRPTEN 0x1000 /* Global interrupt enable */
+#define MODE1_ALUSAT 0x2000 /* Enable ALU fixed-point saturation */
+#define MODE1_SSE 0x4000 /* Enable short word sign extension */
+#define MODE1_TRUNCATE 0x8000 /* (1) Floating-point truncation / (0) round to nearest */
+#define MODE1_RND32 0x10000 /* (1) 32-bit floating-point rounding / (0) 40-bit rounding */
+#define MODE1_CSEL 0x60000 /* CSelect */
+
+// MODE2 flags
+#define MODE2_IRQ0E 0x1 /* IRQ0 (1) Edge sens. / (0) Level sens. */
+#define MODE2_IRQ1E 0x2 /* IRQ1 (1) Edge sens. / (0) Level sens. */
+#define MODE2_IRQ2E 0x4 /* IRQ2 (1) Edge sens. / (0) Level sens. */
+#define MODE2_CADIS 0x10 /* Cache disable */
+#define MODE2_TIMEN 0x20 /* Timer enable */
+#define MODE2_BUSLK 0x40 /* External bus lock */
+#define MODE2_FLG0O 0x8000 /* FLAG0 (1) Output / (0) Input */
+#define MODE2_FLG1O 0x10000 /* FLAG1 (1) Output / (0) Input */
+#define MODE2_FLG2O 0x20000 /* FLAG2 (1) Output / (0) Input */
+#define MODE2_FLG3O 0x40000 /* FLAG3 (1) Output / (0) Input */
+#define MODE2_CAFRZ 0x80000 /* Cache freeze */
+
+
+#define REG_PC 0x63
+#define REG_PCSTK 0x64
+#define REG_PCSTKP 0x65
+#define REG_LADDR 0x66
+#define REG_CURLCNTR 0x67
+#define REG_LCNTR 0x68
+#define REG_USTAT1 0x70
+#define REG_USTAT2 0x71
+#define REG_IRPTL 0x79
+#define REG_MODE2 0x7a
+#define REG_MODE1 0x7b
+#define REG_ASTAT 0x7c
+#define REG_IMASK 0x7d
+#define REG_STKY 0x7e
+#define REG_IMASKP 0x7f
+
+
+
+#define REG(x) (cpustate->r[x].r)
+#define FREG(x) (cpustate->r[x].f)
+
+#define UPDATE_CIRCULAR_BUFFER_PM(x) \
+ { \
+ if (PM_REG_L(x) != 0) \
+ { \
+ if (PM_REG_I(x) > PM_REG_B(x)+PM_REG_L(x)) \
+ { \
+ PM_REG_I(x) -= PM_REG_L(x); \
+ } \
+ else if (PM_REG_I(x) < PM_REG_B(x)) \
+ { \
+ PM_REG_I(x) += PM_REG_L(x); \
+ } \
+ } \
+ }
+
+#define UPDATE_CIRCULAR_BUFFER_DM(x) \
+ { \
+ if (DM_REG_L(x) != 0) \
+ { \
+ if (DM_REG_I(x) > DM_REG_B(x)+DM_REG_L(x)) \
+ { \
+ DM_REG_I(x) -= DM_REG_L(x); \
+ } \
+ else if (DM_REG_I(x) < DM_REG_B(x)) \
+ { \
+ DM_REG_I(x) += DM_REG_L(x); \
+ } \
+ } \
+ }
+
+
+/*****************************************************************************/
+
+static void systemreg_write_latency_effect(SHARC_REGS *cpustate);
+
+static void add_systemreg_write_latency_effect(SHARC_REGS *cpustate, int sysreg, UINT32 data, UINT32 prev_data)
+{
+ if (cpustate->systemreg_latency_cycles > 0)
+ {
+ //fatalerror("SHARC: add_systemreg_write_latency_effect: already scheduled! (reg: %02X, data: %08X, PC: %08X)\n", systemreg_latency_reg, systemreg_latency_data, cpustate->pc);
+ systemreg_write_latency_effect(cpustate);
+ }
+
+ cpustate->systemreg_latency_cycles = 2;
+ cpustate->systemreg_latency_reg = sysreg;
+ cpustate->systemreg_latency_data = data;
+ cpustate->systemreg_previous_data = prev_data;
+}
+
+INLINE void swap_register(UINT32 *a, UINT32 *b)
+{
+ UINT32 temp = *a;
+ *a = *b;
+ *b = temp;
+}
+
+static void systemreg_write_latency_effect(SHARC_REGS *cpustate)
+{
+ int i;
+ UINT32 data = cpustate->systemreg_latency_data;
+ UINT32 old_data = cpustate->systemreg_previous_data;
+
+ switch(cpustate->systemreg_latency_reg)
+ {
+ case 0xb: /* MODE1 */
+ {
+ UINT32 oldreg = old_data;
+ cpustate->mode1 = data;
+
+ if ((data & 0x1) != (oldreg & 0x1))
+ {
+ fatalerror("SHARC: systemreg_latency_op: enable I8 bit-reversing");
+ }
+ if ((data & 0x2) != (oldreg & 0x2))
+ {
+ fatalerror("SHARC: systemreg_latency_op: enable I0 bit-reversing");
+ }
+ if ((data & 0x4) != (oldreg & 0x4))
+ {
+ fatalerror("SHARC: systemreg_latency_op: enable MR alternate");
+ }
+
+ if ((data & 0x8) != (oldreg & 0x8)) /* Switch DAG1 7-4 */
+ {
+ swap_register(&cpustate->dag1.i[4], &cpustate->dag1_alt.i[4]);
+ swap_register(&cpustate->dag1.i[5], &cpustate->dag1_alt.i[5]);
+ swap_register(&cpustate->dag1.i[6], &cpustate->dag1_alt.i[6]);
+ swap_register(&cpustate->dag1.i[7], &cpustate->dag1_alt.i[7]);
+ swap_register(&cpustate->dag1.m[4], &cpustate->dag1_alt.m[4]);
+ swap_register(&cpustate->dag1.m[5], &cpustate->dag1_alt.m[5]);
+ swap_register(&cpustate->dag1.m[6], &cpustate->dag1_alt.m[6]);
+ swap_register(&cpustate->dag1.m[7], &cpustate->dag1_alt.m[7]);
+ swap_register(&cpustate->dag1.l[4], &cpustate->dag1_alt.l[4]);
+ swap_register(&cpustate->dag1.l[5], &cpustate->dag1_alt.l[5]);
+ swap_register(&cpustate->dag1.l[6], &cpustate->dag1_alt.l[6]);
+ swap_register(&cpustate->dag1.l[7], &cpustate->dag1_alt.l[7]);
+ swap_register(&cpustate->dag1.b[4], &cpustate->dag1_alt.b[4]);
+ swap_register(&cpustate->dag1.b[5], &cpustate->dag1_alt.b[5]);
+ swap_register(&cpustate->dag1.b[6], &cpustate->dag1_alt.b[6]);
+ swap_register(&cpustate->dag1.b[7], &cpustate->dag1_alt.b[7]);
+ }
+ if ((data & 0x10) != (oldreg & 0x10)) /* Switch DAG1 3-0 */
+ {
+ swap_register(&cpustate->dag1.i[0], &cpustate->dag1_alt.i[0]);
+ swap_register(&cpustate->dag1.i[1], &cpustate->dag1_alt.i[1]);
+ swap_register(&cpustate->dag1.i[2], &cpustate->dag1_alt.i[2]);
+ swap_register(&cpustate->dag1.i[3], &cpustate->dag1_alt.i[3]);
+ swap_register(&cpustate->dag1.m[0], &cpustate->dag1_alt.m[0]);
+ swap_register(&cpustate->dag1.m[1], &cpustate->dag1_alt.m[1]);
+ swap_register(&cpustate->dag1.m[2], &cpustate->dag1_alt.m[2]);
+ swap_register(&cpustate->dag1.m[3], &cpustate->dag1_alt.m[3]);
+ swap_register(&cpustate->dag1.l[0], &cpustate->dag1_alt.l[0]);
+ swap_register(&cpustate->dag1.l[1], &cpustate->dag1_alt.l[1]);
+ swap_register(&cpustate->dag1.l[2], &cpustate->dag1_alt.l[2]);
+ swap_register(&cpustate->dag1.l[3], &cpustate->dag1_alt.l[3]);
+ swap_register(&cpustate->dag1.b[0], &cpustate->dag1_alt.b[0]);
+ swap_register(&cpustate->dag1.b[1], &cpustate->dag1_alt.b[1]);
+ swap_register(&cpustate->dag1.b[2], &cpustate->dag1_alt.b[2]);
+ swap_register(&cpustate->dag1.b[3], &cpustate->dag1_alt.b[3]);
+ }
+ if ((data & 0x20) != (oldreg & 0x20)) /* Switch DAG2 15-12 */
+ {
+ swap_register(&cpustate->dag2.i[4], &cpustate->dag2_alt.i[4]);
+ swap_register(&cpustate->dag2.i[5], &cpustate->dag2_alt.i[5]);
+ swap_register(&cpustate->dag2.i[6], &cpustate->dag2_alt.i[6]);
+ swap_register(&cpustate->dag2.i[7], &cpustate->dag2_alt.i[7]);
+ swap_register(&cpustate->dag2.m[4], &cpustate->dag2_alt.m[4]);
+ swap_register(&cpustate->dag2.m[5], &cpustate->dag2_alt.m[5]);
+ swap_register(&cpustate->dag2.m[6], &cpustate->dag2_alt.m[6]);
+ swap_register(&cpustate->dag2.m[7], &cpustate->dag2_alt.m[7]);
+ swap_register(&cpustate->dag2.l[4], &cpustate->dag2_alt.l[4]);
+ swap_register(&cpustate->dag2.l[5], &cpustate->dag2_alt.l[5]);
+ swap_register(&cpustate->dag2.l[6], &cpustate->dag2_alt.l[6]);
+ swap_register(&cpustate->dag2.l[7], &cpustate->dag2_alt.l[7]);
+ swap_register(&cpustate->dag2.b[4], &cpustate->dag2_alt.b[4]);
+ swap_register(&cpustate->dag2.b[5], &cpustate->dag2_alt.b[5]);
+ swap_register(&cpustate->dag2.b[6], &cpustate->dag2_alt.b[6]);
+ swap_register(&cpustate->dag2.b[7], &cpustate->dag2_alt.b[7]);
+ }
+ if ((data & 0x40) != (oldreg & 0x40)) /* Switch DAG2 11-8 */
+ {
+ swap_register(&cpustate->dag2.i[0], &cpustate->dag2_alt.i[0]);
+ swap_register(&cpustate->dag2.i[1], &cpustate->dag2_alt.i[1]);
+ swap_register(&cpustate->dag2.i[2], &cpustate->dag2_alt.i[2]);
+ swap_register(&cpustate->dag2.i[3], &cpustate->dag2_alt.i[3]);
+ swap_register(&cpustate->dag2.m[0], &cpustate->dag2_alt.m[0]);
+ swap_register(&cpustate->dag2.m[1], &cpustate->dag2_alt.m[1]);
+ swap_register(&cpustate->dag2.m[2], &cpustate->dag2_alt.m[2]);
+ swap_register(&cpustate->dag2.m[3], &cpustate->dag2_alt.m[3]);
+ swap_register(&cpustate->dag2.l[0], &cpustate->dag2_alt.l[0]);
+ swap_register(&cpustate->dag2.l[1], &cpustate->dag2_alt.l[1]);
+ swap_register(&cpustate->dag2.l[2], &cpustate->dag2_alt.l[2]);
+ swap_register(&cpustate->dag2.l[3], &cpustate->dag2_alt.l[3]);
+ swap_register(&cpustate->dag2.b[0], &cpustate->dag2_alt.b[0]);
+ swap_register(&cpustate->dag2.b[1], &cpustate->dag2_alt.b[1]);
+ swap_register(&cpustate->dag2.b[2], &cpustate->dag2_alt.b[2]);
+ swap_register(&cpustate->dag2.b[3], &cpustate->dag2_alt.b[3]);
+ }
+ if ((data & 0x80) != (oldreg & 0x80))
+ {
+ for (i=8; i<16; i++)
+ swap_register((UINT32*)&cpustate->r[i].r, (UINT32*)&cpustate->reg_alt[i].r);
+ }
+ if ((data & 0x400) != (oldreg & 0x400))
+ {
+ for (i=0; i<8; i++)
+ swap_register((UINT32*)&cpustate->r[i].r, (UINT32*)&cpustate->reg_alt[i].r);
+ }
+ break;
+ }
+ default: fatalerror("SHARC: systemreg_latency_op: unknown register %02X at %08X", cpustate->systemreg_latency_reg, cpustate->pc);
+ }
+
+ cpustate->systemreg_latency_reg = -1;
+}
+
+static UINT32 GET_UREG(SHARC_REGS *cpustate, int ureg)
+{
+ int reg = ureg & 0xf;
+ switch((ureg >> 4) & 0xf)
+ {
+ case 0x0: /* R0 - R15 */
+ {
+ return cpustate->r[reg].r;
+ }
+
+ case 0x1:
+ {
+ if (reg & 0x8) /* I8 - I15 */
+ {
+ return cpustate->dag2.i[reg & 0x7];
+ }
+ else /* I0 - I7 */
+ {
+ return cpustate->dag1.i[reg & 0x7];
+ }
+ }
+
+ case 0x2:
+ {
+ if (reg & 0x8) /* M8 - M15 */
+ {
+ INT32 r = cpustate->dag2.m[reg & 0x7];
+ if (r & 0x800000) r |= 0xff000000;
+
+ return r;
+ }
+ else /* M0 - M7 */
+ {
+ return cpustate->dag1.m[reg & 0x7];
+ }
+ }
+
+ case 0x3:
+ {
+ if (reg & 0x8) /* L8 - L15 */
+ {
+ return cpustate->dag2.l[reg & 0x7];
+ }
+ else /* L0 - L7 */
+ {
+ return cpustate->dag1.l[reg & 0x7];
+ }
+ }
+
+ case 0x4:
+ {
+ if (reg & 0x8) /* B8 - B15 */
+ {
+ return cpustate->dag2.b[reg & 0x7];
+ }
+ else /* B0 - B7 */
+ {
+ return cpustate->dag1.b[reg & 0x7];
+ }
+ }
+
+ case 0x6:
+ {
+ switch(reg)
+ {
+ case 0x4: return cpustate->pcstack[cpustate->pcstkp]; /* PCSTK */
+ default: fatalerror("SHARC: GET_UREG: unknown register %08X at %08X", ureg, cpustate->pc);
+ }
+ break;
+ }
+
+ case 0x7:
+ {
+ switch(reg)
+ {
+ case 0x0: return cpustate->ustat1; /* USTAT1 */
+ case 0x1: return cpustate->ustat2; /* USTAT2 */
+ case 0x9: return cpustate->irptl; /* IRPTL */
+ case 0xa: return cpustate->mode2; /* MODE2 */
+ case 0xb: return cpustate->mode1; /* MODE1 */
+ case 0xc: /* ASTAT */
+ {
+ UINT32 r = cpustate->astat;
+ r &= ~0x00780000;
+ r |= (cpustate->flag[0] << 19);
+ r |= (cpustate->flag[1] << 20);
+ r |= (cpustate->flag[2] << 21);
+ r |= (cpustate->flag[3] << 22);
+ return r;
+ }
+ case 0xd: return cpustate->imask; /* IMASK */
+ case 0xe: return cpustate->stky; /* STKY */
+ default: fatalerror("SHARC: GET_UREG: unknown register %08X at %08X", ureg, cpustate->pc);
+ }
+ break;
+ }
+
+ case 0xd:
+ {
+ switch(reg)
+ {
+ /* PX needs to be handled separately if the whole 48 bits are needed */
+ case 0xb: return (UINT32)(cpustate->px); /* PX */
+ case 0xc: return (UINT16)(cpustate->px); /* PX1 */
+ case 0xd: return (UINT32)(cpustate->px >> 16); /* PX2 */
+ default: fatalerror("SHARC: GET_UREG: unknown register %08X at %08X", ureg, cpustate->pc);
+ }
+ break;
+ }
+
+ default: fatalerror("SHARC: GET_UREG: unknown register %08X at %08X", ureg, cpustate->pc);
+ }
+}
+
+static void SET_UREG(SHARC_REGS *cpustate, int ureg, UINT32 data)
+{
+ int reg = ureg & 0xf;
+ switch((ureg >> 4) & 0xf)
+ {
+ case 0x0: /* R0 - R15 */
+ cpustate->r[reg].r = data;
+ break;
+
+ case 0x1:
+ if (reg & 0x8) /* I8 - I15 */
+ {
+ cpustate->dag2.i[reg & 0x7] = data;
+ }
+ else /* I0 - I7 */
+ {
+ cpustate->dag1.i[reg & 0x7] = data;
+ }
+ break;
+
+ case 0x2:
+ if (reg & 0x8) /* M8 - M15 */
+ {
+ cpustate->dag2.m[reg & 0x7] = data;
+ }
+ else /* M0 - M7 */
+ {
+ cpustate->dag1.m[reg & 0x7] = data;
+ }
+ break;
+
+ case 0x3:
+ if (reg & 0x8) /* L8 - L15 */
+ {
+ cpustate->dag2.l[reg & 0x7] = data;
+ }
+ else /* L0 - L7 */
+ {
+ cpustate->dag1.l[reg & 0x7] = data;
+ }
+ break;
+
+ case 0x4:
+ // Note: loading B also loads the same value in I
+ if (reg & 0x8) /* B8 - B15 */
+ {
+ cpustate->dag2.b[reg & 0x7] = data;
+ cpustate->dag2.i[reg & 0x7] = data;
+ }
+ else /* B0 - B7 */
+ {
+ cpustate->dag1.b[reg & 0x7] = data;
+ cpustate->dag1.i[reg & 0x7] = data;
+ }
+ break;
+
+ case 0x6:
+ switch (reg)
+ {
+ case 0x5: cpustate->pcstkp = data; break; /* PCSTKP */
+ case 0x8: cpustate->lcntr = data; break; /* LCNTR */
+ default: fatalerror("SHARC: SET_UREG: unknown register %08X at %08X", ureg, cpustate->pc);
+ }
+ break;
+
+ case 0x7: /* system regs */
+ switch(reg)
+ {
+ case 0x0: cpustate->ustat1 = data; break; /* USTAT1 */
+ case 0x1: cpustate->ustat2 = data; break; /* USTAT2 */
+
+ case 0x9: cpustate->irptl = data; break; /* IRPTL */
+ case 0xa: cpustate->mode2 = data; break; /* MODE2 */
+
+ case 0xb: /* MODE1 */
+ {
+ add_systemreg_write_latency_effect(cpustate, reg, data, cpustate->mode1);
+ cpustate->mode1 = data;
+ break;
+ }
+
+ case 0xc: cpustate->astat = data; break; /* ASTAT */
+
+ case 0xd: /* IMASK */
+ {
+ check_interrupts(cpustate);
+ cpustate->imask = data;
+ break;
+ }
+
+ case 0xe: cpustate->stky = data; break; /* STKY */
+ default: fatalerror("SHARC: SET_UREG: unknown register %08X at %08X", ureg, cpustate->pc);
+ }
+ break;
+
+ case 0xd:
+ switch(reg)
+ {
+ case 0xc: cpustate->px &= U64(0xffffffffffff0000); cpustate->px |= (data & 0xffff); break; /* PX1 */
+ case 0xd: cpustate->px &= U64(0x000000000000ffff); cpustate->px |= (UINT64)data << 16; break; /* PX2 */
+ default: fatalerror("SHARC: SET_UREG: unknown register %08X at %08X", ureg, cpustate->pc);
+ }
+ break;
+
+ default: fatalerror("SHARC: SET_UREG: unknown register %08X at %08X", ureg, cpustate->pc);
+ }
+}
+
+/*****************************************************************************/
+#define SET_FLAG_SV_LSHIFT(x, shift) if((x) & ((UINT32)0xffffffff << shift)) cpustate->astat |= SV
+#define SET_FLAG_SV_RSHIFT(x, shift) if((x) & ((UINT32)0xffffffff >> shift)) cpustate->astat |= SV
+
+#define SET_FLAG_SZ(x) if((x) == 0) cpustate->astat |= SZ
+
+#define MAKE_EXTRACT_MASK(start_bit, length) ((0xffffffff << start_bit) & (((UINT32)0xffffffff) >> (32 - (start_bit + length))))
+
+static void SHIFT_OPERATION_IMM(SHARC_REGS *cpustate, int shiftop, int data, int rn, int rx)
+{
+ INT8 shift = data & 0xff;
+ int bit = data & 0x3f;
+ int len = (data >> 6) & 0x3f;
+
+ cpustate->astat &= ~(SZ|SV|SS);
+
+ switch(shiftop)
+ {
+ case 0x00: /* LSHIFT Rx BY <data8>*/
+ {
+ if(shift < 0) {
+ REG(rn) = (shift > -32 ) ? (REG(rx) >> -shift) : 0;
+ } else {
+ REG(rn) = (shift < 32) ? (REG(rx) << shift) : 0;
+ if (shift > 0)
+ {
+ cpustate->astat |= SV;
+ }
+ }
+ SET_FLAG_SZ(REG(rn));
+ break;
+ }
+
+ case 0x01: /* ASHIFT Rx BY <data8> */
+ {
+ if (shift < 0)
+ {
+ REG(rn) = (shift > -32) ? ((INT32)REG(rx) >> -shift) : ((REG(rx) & 0x80000000) ? 0xffffffff : 0);
+ }
+ else
+ {
+ REG(rn) = (shift < 32) ? ((INT32)REG(rx) << shift) : 0;
+ if (shift > 0)
+ {
+ cpustate->astat |= SV;
+ }
+ }
+ SET_FLAG_SZ(REG(rn));
+ break;
+ }
+
+ case 0x02: /* ROT Rx BY <data8> */
+ {
+ if (shift < 0)
+ {
+ int s = (-shift) & 0x1f;
+ REG(rn) = (((UINT32)REG(rx) >> s) & ((UINT32)(0xffffffff) >> s)) |
+ (((UINT32)REG(rx) << (32-s)) & ((UINT32)(0xffffffff) << (32-s)));
+ }
+ else
+ {
+ int s = shift & 0x1f;
+ REG(rn) = (((UINT32)REG(rx) << s) & ((UINT32)(0xffffffff) << s)) |
+ (((UINT32)REG(rx) >> (32-s)) & ((UINT32)(0xffffffff) >> (32-s)));
+ }
+ SET_FLAG_SZ(REG(rn));
+ break;
+ }
+
+ case 0x08: /* Rn = Rn OR LSHIFT Rx BY <data8> */
+ {
+ UINT32 r = 0;
+ if(shift < 0) {
+ r = (shift > -32 ) ? (REG(rx) >> -shift) : 0;
+ } else {
+ r = (shift < 32) ? (REG(rx) << shift) : 0;
+ if (shift > 0)
+ {
+ cpustate->astat |= SV;
+ }
+ }
+ SET_FLAG_SZ(r);
+
+ REG(rn) = REG(rn) | r;
+ break;
+ }
+
+ case 0x10: /* FEXT Rx BY <bit6>:<len6> */
+ {
+ UINT32 ext = REG(rx) & MAKE_EXTRACT_MASK(bit, len);
+ REG(rn) = ext >> bit;
+
+ SET_FLAG_SZ(REG(rn));
+ if (bit+len > 32)
+ {
+ cpustate->astat |= SV;
+ }
+ break;
+ }
+
+ case 0x12: /* FEXT Rx BY <bit6>:<len6> (Sign Extended) */
+ {
+ UINT32 ext = (REG(rx) & MAKE_EXTRACT_MASK(bit, len)) >> bit;
+ if (ext & (1 << (len-1))) {
+ ext |= (UINT32)0xffffffff << (len-1);
+ }
+ REG(rn) = ext;
+
+ SET_FLAG_SZ(REG(rn));
+ if (bit+len > 32)
+ {
+ cpustate->astat |= SV;
+ }
+ break;
+ }
+
+ case 0x13: /* FDEP Rx BY Ry <bit6>:<len6> (Sign Extended) */
+ {
+ UINT32 ext = REG(rx) & MAKE_EXTRACT_MASK(0, len);
+ if (ext & (1 << (len-1))) {
+ ext |= (UINT32)0xffffffff << (len-1);
+ }
+ REG(rn) = ext << bit;
+
+ SET_FLAG_SZ(REG(rn));
+ if (bit+len > 32)
+ {
+ cpustate->astat |= SV;
+ }
+ break;
+ }
+
+ case 0x19: /* Rn = Rn OR FDEP Rx BY <bit6>:<len6> */
+ {
+ UINT32 ext = REG(rx) & MAKE_EXTRACT_MASK(0, len);
+
+ REG(rn) |= ext << bit;
+
+ SET_FLAG_SZ(REG(rn));
+ if (bit+len > 32)
+ {
+ cpustate->astat |= SV;
+ }
+ break;
+ }
+
+ case 0x30: /* BSET Rx BY <data8> */
+ {
+ REG(rn) = REG(rx);
+ if (data >= 0 && data < 32)
+ {
+ REG(rn) |= (1 << data);
+ }
+ else
+ {
+ cpustate->astat |= SV;
+ }
+ SET_FLAG_SZ(REG(rn));
+ break;
+ }
+
+ case 0x31: /* BCLR Rx BY <data8> */
+ {
+ REG(rn) = REG(rx);
+ if (data >= 0 && data < 32)
+ {
+ REG(rn) &= ~(1 << data);
+ }
+ else
+ {
+ cpustate->astat |= SV;
+ }
+ SET_FLAG_SZ(REG(rn));
+ break;
+ }
+
+ case 0x32: /* BTGL Rx BY <data8> */
+ {
+ REG(rn) = REG(rx);
+ if (data >= 0 && data < 32)
+ {
+ REG(rn) ^= (1 << data);
+ }
+ else
+ {
+ cpustate->astat |= SV;
+ }
+ SET_FLAG_SZ(REG(rn));
+ break;
+ }
+
+ case 0x33: /* BTST Rx BY <data8> */
+ {
+ if (data < 32)
+ {
+ UINT32 r = REG(rx) & (1 << data);
+
+ SET_FLAG_SZ(r);
+ }
+ else
+ {
+ cpustate->astat |= SZ | SV;
+ }
+ break;
+ }
+
+ default: fatalerror("SHARC: unimplemented shift operation %02X at %08X", shiftop, cpustate->pc);
+ }
+}
+
+#include "compute.c"
+
+static void COMPUTE(SHARC_REGS *cpustate, UINT32 opcode)
+{
+ int multiop;
+ int op = (opcode >> 12) & 0xff;
+ int cu = (opcode >> 20) & 0x3;
+ int rn = (opcode >> 8) & 0xf;
+ int rx = (opcode >> 4) & 0xf;
+ int ry = (opcode >> 0) & 0xf;
+ //int rs = (opcode >> 12) & 0xf;
+ //int ra = rn;
+ //int rm = rs;
+
+ if(opcode & 0x400000) /* Multi-function opcode */
+ {
+ int fm = (opcode >> 12) & 0xf;
+ int fa = (opcode >> 8) & 0xf;
+ int fxm = (opcode >> 6) & 0x3; // registers 0 - 3
+ int fym = ((opcode >> 4) & 0x3) + 4; // registers 4 - 7
+ int fxa = ((opcode >> 2) & 0x3) + 8; // registers 8 - 11
+ int fya = (opcode & 0x3) + 12; // registers 12 - 15
+
+ multiop = (opcode >> 16) & 0x3f;
+ switch(multiop)
+ {
+ case 0x00: compute_multi_mr_to_reg(cpustate, op & 0xf, rn); break;
+ case 0x01: compute_multi_reg_to_mr(cpustate, op & 0xf, rn); break;
+
+ case 0x04: /* Rm = Rxm * Rym (SSFR), Ra = Rxa + Rya */
+ {
+ compute_mul_ssfr_add(cpustate, fm, fxm, fym, fa, fxa, fya);
+ break;
+ }
+
+ case 0x05: /* Rm = Rxm * Rym (SSFR), Ra = Rxa - Rya */
+ {
+ compute_mul_ssfr_sub(cpustate, fm, fxm, fym, fa, fxa, fya);
+ break;
+ }
+
+ case 0x18: /* Fm = Fxm * Fym, Fa = Fxa + Fya */
+ {
+ compute_fmul_fadd(cpustate, fm, fxm, fym, fa, fxa, fya);
+ break;
+ }
+
+ case 0x19: /* Fm = Fxm * Fym, Fa = Fxa - Fya */
+ {
+ compute_fmul_fsub(cpustate, fm, fxm, fym, fa, fxa, fya);
+ break;
+ }
+
+ case 0x1a: /* Fm = Fxm * Fym, Fa = FLOAT Fxa BY Fya */
+ {
+ compute_fmul_float_scaled(cpustate, fm, fxm, fym, fa, fxa, fya);
+ break;
+ }
+
+ case 0x1b: /* Fm = Fxm * Fym, Fa = FIX Fxa BY Fya */
+ {
+ compute_fmul_fix_scaled(cpustate, fm, fxm, fym, fa, fxa, fya);
+ break;
+ }
+
+ case 0x1e: /* Fm = Fxm * Fym, Fa = MAX(Fxa, Fya) */
+ {
+ compute_fmul_fmax(cpustate, fm, fxm, fym, fa, fxa, fya);
+ break;
+ }
+
+ case 0x1f: /* Fm = Fxm * Fym, Fa = MIN(Fxa, Fya) */
+ {
+ compute_fmul_fmin(cpustate, fm, fxm, fym, fa, fxa, fya);
+ 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:
+ {
+ /* Parallel Multiplier & Dual Add/Subtract */
+ /* Floating-point */
+ int fs = (opcode >> 16) & 0xf;
+ compute_fmul_dual_fadd_fsub(cpustate, fm, fxm, fym, fa, fs, fxa, fya);
+ break;
+ }
+
+ default:
+ fatalerror("SHARC: compute: multi-function opcode %02X not implemented ! (%08X, %08X)", multiop, cpustate->pc, opcode);
+ break;
+ }
+ }
+ else /* Single-function opcode */
+ {
+ switch(cu)
+ {
+ /* ALU operations */
+ case 0:
+ {
+ switch(op)
+ {
+ case 0x01: compute_add(cpustate, rn, rx, ry); break;
+ case 0x02: compute_sub(cpustate, rn, rx, ry); break;
+ case 0x05: compute_add_ci(cpustate, rn, rx, ry); break;
+ case 0x06: compute_sub_ci(cpustate, rn, rx, ry); break;
+ case 0x0a: compute_comp(cpustate, rx, ry); break;
+ case 0x21: compute_pass(cpustate, rn, rx); break;
+ case 0x22: compute_neg(cpustate, rn, rx); break;
+ case 0x29: compute_inc(cpustate, rn, rx); break;
+ case 0x2a: compute_dec(cpustate, rn, rx); break;
+ case 0x40: compute_and(cpustate, rn, rx, ry); break;
+ case 0x41: compute_or(cpustate, rn, rx, ry); break;
+ case 0x42: compute_xor(cpustate, rn, rx, ry); break;
+ case 0x43: compute_not(cpustate, rn, rx); break;
+ case 0x61: compute_min(cpustate, rn, rx, ry); break;
+ case 0x62: compute_max(cpustate, rn, rx, ry); break;
+ case 0x81: compute_fadd(cpustate, rn, rx, ry); break;
+ case 0x82: compute_fsub(cpustate, rn, rx, ry); break;
+ case 0x8a: compute_fcomp(cpustate, rx, ry); break;
+ case 0x91: compute_fabs_plus(cpustate, rn, rx, ry); break;
+ case 0xa1: compute_fpass(cpustate, rn, rx); break;
+ case 0xa2: compute_fneg(cpustate, rn, rx); break;
+ case 0xb0: compute_fabs(cpustate, rn, rx); break;
+ case 0xbd: compute_scalb(cpustate, rn, rx, ry); break;
+ case 0xc1: compute_logb(cpustate, rn, rx); break;
+ case 0xc4: compute_recips(cpustate, rn, rx); break;
+ case 0xc5: compute_rsqrts(cpustate, rn, rx); break;
+ case 0xc9: compute_fix(cpustate, rn, rx); break;
+ case 0xca: compute_float(cpustate, rn, rx); break;
+ case 0xd9: compute_fix_scaled(cpustate, rn, rx, ry); break;
+ case 0xda: compute_float_scaled(cpustate, rn, rx, ry); break;
+ case 0xe1: compute_fmin(cpustate, rn, rx, ry); break;
+ case 0xe2: compute_fmax(cpustate, rn, rx, ry); break;
+ case 0xe3: compute_fclip(cpustate, rn, rx, ry); 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:
+ {
+ /* Fixed-point Dual Add/Subtract */
+ int rs = (opcode >> 12) & 0xf;
+ int ra = (opcode >> 8) & 0xf;
+ compute_dual_add_sub(cpustate, ra, rs, rx, ry);
+ break;
+ }
+
+ 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:
+ {
+ /* Floating-point Dual Add/Subtract */
+ int rs = (opcode >> 12) & 0xf;
+ int ra = (opcode >> 8) & 0xf;
+ compute_dual_fadd_fsub(cpustate, ra, rs, rx, ry);
+ break;
+ }
+
+ default: fatalerror("SHARC: compute: unimplemented ALU operation %02X (%08X, %08X)", op, cpustate->pc, opcode);
+ }
+ break;
+ }
+
+
+ /* Multiplier operations */
+ case 1:
+ {
+ switch(op)
+ {
+ case 0x14: cpustate->mrf = 0; break;
+ case 0x16: cpustate->mrb = 0; break;
+
+ case 0x30: compute_fmul(cpustate, rn, rx, ry); break;
+ case 0x40: compute_mul_uuin(cpustate, rn, rx, ry); break;
+ case 0x70: compute_mul_ssin(cpustate, rn, rx, ry); break;
+
+ case 0xb0: REG(rn) = compute_mrf_plus_mul_ssin(cpustate, rx, ry); break;
+ case 0xb2: REG(rn) = compute_mrb_plus_mul_ssin(cpustate, rx, ry); break;
+
+ default:
+ fatalerror("SHARC: compute: multiplier operation %02X not implemented ! (%08X, %08X)", op, cpustate->pc, opcode);
+ break;
+ }
+ break;
+ }
+
+
+ /* Shifter operations */
+ case 2:
+ {
+ cpustate->astat &= ~(SZ|SV|SS);
+
+ op >>= 2;
+ switch(op)
+ {
+ case 0x00: /* LSHIFT Rx BY Ry*/
+ {
+ int shift = REG(ry);
+ if(shift < 0)
+ {
+ REG(rn) = (shift > -32 ) ? (REG(rx) >> -shift) : 0;
+ }
+ else
+ {
+ REG(rn) = (shift < 32) ? (REG(rx) << shift) : 0;
+ if (shift > 0)
+ {
+ cpustate->astat |= SV;
+ }
+ }
+ SET_FLAG_SZ(REG(rn));
+ break;
+ }
+
+ case 0x02: /* ROT Rx BY Ry */
+ {
+ int shift = REG(ry);
+ if (shift < 0)
+ {
+ int s = (-shift) & 0x1f;
+ REG(rn) = (((UINT32)REG(rx) >> s) & ((UINT32)(0xffffffff) >> s)) |
+ (((UINT32)REG(rx) << (32-s)) & ((UINT32)(0xffffffff) << (32-s)));
+ }
+ else
+ {
+ int s = shift & 0x1f;
+ REG(rn) = (((UINT32)REG(rx) << s) & ((UINT32)(0xffffffff) << s)) |
+ (((UINT32)REG(rx) >> (32-s)) & ((UINT32)(0xffffffff) >> (32-s)));
+ if (shift > 0)
+ {
+ cpustate->astat |= SV;
+ }
+ }
+ SET_FLAG_SZ(REG(rn));
+ break;
+ }
+
+ case 0x08: /* Rn = Rn OR LSHIFT Rx BY Ry*/
+ {
+ INT8 shift = REG(ry);
+ if(shift < 0) {
+ REG(rn) = REG(rn) | ((shift > -32 ) ? (REG(rx) >> -shift) : 0);
+ } else {
+ REG(rn) = REG(rn) | ((shift < 32) ? (REG(rx) << shift) : 0);
+ if (shift > 0)
+ {
+ cpustate->astat |= SV;
+ }
+ }
+ SET_FLAG_SZ(REG(rn));
+ break;
+ }
+
+ case 0x10: /* FEXT Rx BY Ry */
+ {
+ int bit = REG(ry) & 0x3f;
+ int len = (REG(ry) >> 6) & 0x3f;
+ UINT32 ext = REG(rx) & MAKE_EXTRACT_MASK(bit, len);
+ REG(rn) = ext >> bit;
+
+ SET_FLAG_SZ(REG(rn));
+ if (bit+len > 32)
+ {
+ cpustate->astat |= SV;
+ }
+ break;
+ }
+
+ case 0x12: /* FEXT Rx BY Ry (Sign Extended) */
+ {
+ int bit = REG(ry) & 0x3f;
+ int len = (REG(ry) >> 6) & 0x3f;
+ UINT32 ext = (REG(rx) & MAKE_EXTRACT_MASK(bit, len)) >> bit;
+ if (ext & (1 << (len-1))) {
+ ext |= (UINT32)0xffffffff << (len-1);
+ }
+ REG(rn) = ext;
+
+ SET_FLAG_SZ(REG(rn));
+ if (bit+len > 32)
+ {
+ cpustate->astat |= SV;
+ }
+ break;
+ }
+
+ case 0x19: /* Rn = Rn OR FDEP Rx BY Ry */
+ {
+ int bit = REG(ry) & 0x3f;
+ int len = (REG(ry) >> 6) & 0x3f;
+ UINT32 ext = REG(rx) & MAKE_EXTRACT_MASK(0, len);
+
+ REG(rn) |= ext << bit;
+
+ SET_FLAG_SZ(REG(rn));
+ if (bit+len > 32)
+ {
+ cpustate->astat |= SV;
+ }
+ break;
+ }
+
+ case 0x30: /* BSET Rx BY Ry */
+ {
+ UINT32 shift = REG(ry);
+ REG(rn) = REG(rx);
+ if (shift < 32)
+ {
+ REG(rn) |= (1 << shift);
+ }
+ else
+ {
+ cpustate->astat |= SV;
+ }
+ SET_FLAG_SZ(REG(rn));
+ break;
+ }
+
+ case 0x31: /* BCLR Rx BY Ry */
+ {
+ UINT32 shift = REG(ry);
+ REG(rn) = REG(rx);
+ if (shift < 32)
+ {
+ REG(rn) &= ~(1 << shift);
+ }
+ else
+ {
+ cpustate->astat |= SV;
+ }
+ SET_FLAG_SZ(REG(rn));
+ break;
+ }
+
+ case 0x33: /* BTST Rx BY Ry */
+ {
+ UINT32 shift = REG(ry);
+ if (shift < 32)
+ {
+ UINT32 r = REG(rx) & (1 << shift);
+
+ SET_FLAG_SZ(r);
+ }
+ else
+ {
+ cpustate->astat |= SZ | SV;
+ }
+ break;
+ }
+
+ default:
+ fatalerror("SHARC: compute: shift operation %02X not implemented ! (%08X, %08X)", op, cpustate->pc, opcode);
+ }
+ break;
+ }
+
+ default:
+ fatalerror("SHARC: compute: invalid single-function operation %02X", cu);
+ }
+ }
+}
+
+INLINE void PUSH_PC(SHARC_REGS *cpustate, UINT32 pc)
+{
+ cpustate->pcstkp++;
+ if(cpustate->pcstkp >= 32)
+ {
+ fatalerror("SHARC: PC Stack overflow !");
+ }
+
+ if (cpustate->pcstkp == 0)
+ {
+ cpustate->stky |= 0x400000;
+ }
+ else
+ {
+ cpustate->stky &= ~0x400000;
+ }
+
+ cpustate->pcstk = pc;
+ cpustate->pcstack[cpustate->pcstkp] = pc;
+}
+
+INLINE UINT32 POP_PC(SHARC_REGS *cpustate)
+{
+ cpustate->pcstk = cpustate->pcstack[cpustate->pcstkp];
+
+ if(cpustate->pcstkp == 0)
+ {
+ fatalerror("SHARC: PC Stack underflow !");
+ }
+
+ cpustate->pcstkp--;
+
+ if (cpustate->pcstkp == 0)
+ {
+ cpustate->stky |= 0x400000;
+ }
+ else
+ {
+ cpustate->stky &= ~0x400000;
+ }
+
+ return cpustate->pcstk;
+}
+
+INLINE UINT32 TOP_PC(SHARC_REGS *cpustate)
+{
+ return cpustate->pcstack[cpustate->pcstkp];
+}
+
+INLINE void PUSH_LOOP(SHARC_REGS *cpustate, UINT32 pc, UINT32 count)
+{
+ cpustate->lstkp++;
+ if(cpustate->lstkp >= 6)
+ {
+ fatalerror("SHARC: Loop Stack overflow !");
+ }
+
+ if (cpustate->lstkp == 0)
+ {
+ cpustate->stky |= 0x4000000;
+ }
+ else
+ {
+ cpustate->stky &= ~0x4000000;
+ }
+
+ cpustate->lcstack[cpustate->lstkp] = count;
+ cpustate->lastack[cpustate->lstkp] = pc;
+ cpustate->curlcntr = count;
+ cpustate->laddr = pc;
+}
+
+INLINE void POP_LOOP(SHARC_REGS *cpustate)
+{
+ if(cpustate->lstkp == 0)
+ {
+ fatalerror("SHARC: Loop Stack underflow !");
+ }
+
+ cpustate->lstkp--;
+
+ if (cpustate->lstkp == 0)
+ {
+ cpustate->stky |= 0x4000000;
+ }
+ else
+ {
+ cpustate->stky &= ~0x4000000;
+ }
+
+ cpustate->curlcntr = cpustate->lcstack[cpustate->lstkp];
+ cpustate->laddr = cpustate->lastack[cpustate->lstkp];
+}
+
+INLINE void PUSH_STATUS_STACK(SHARC_REGS *cpustate)
+{
+ cpustate->status_stkp++;
+ if (cpustate->status_stkp >= 5)
+ {
+ fatalerror("SHARC: Status stack overflow !");
+ }
+
+ if (cpustate->status_stkp == 0)
+ {
+ cpustate->stky |= 0x1000000;
+ }
+ else
+ {
+ cpustate->stky &= ~0x1000000;
+ }
+
+ cpustate->status_stack[cpustate->status_stkp].mode1 = GET_UREG(cpustate, REG_MODE1);
+ cpustate->status_stack[cpustate->status_stkp].astat = GET_UREG(cpustate, REG_ASTAT);
+}
+
+INLINE void POP_STATUS_STACK(SHARC_REGS *cpustate)
+{
+ SET_UREG(cpustate, REG_MODE1, cpustate->status_stack[cpustate->status_stkp].mode1);
+ SET_UREG(cpustate, REG_ASTAT, cpustate->status_stack[cpustate->status_stkp].astat);
+
+ cpustate->status_stkp--;
+ if (cpustate->status_stkp < 0)
+ {
+ fatalerror("SHARC: Status stack underflow !");
+ }
+
+ if (cpustate->status_stkp == 0)
+ {
+ cpustate->stky |= 0x1000000;
+ }
+ else
+ {
+ cpustate->stky &= ~0x1000000;
+ }
+}
+
+INLINE int IF_CONDITION_CODE(SHARC_REGS *cpustate, int cond)
+{
+ switch(cond)
+ {
+ case 0x00: return cpustate->astat & AZ; /* EQ */
+ case 0x01: return !(cpustate->astat & AZ) && (cpustate->astat & AN); /* LT */
+ case 0x02: return (cpustate->astat & AZ) || (cpustate->astat & AN); /* LE */
+ case 0x03: return (cpustate->astat & AC); /* AC */
+ case 0x04: return (cpustate->astat & AV); /* AV */
+ case 0x05: return (cpustate->astat & MV); /* MV */
+ case 0x06: return (cpustate->astat & MN); /* MS */
+ case 0x07: return (cpustate->astat & SV); /* SV */
+ case 0x08: return (cpustate->astat & SZ); /* SZ */
+ case 0x09: return (cpustate->flag[0] != 0); /* FLAG0 */
+ case 0x0a: return (cpustate->flag[1] != 0); /* FLAG1 */
+ case 0x0b: return (cpustate->flag[2] != 0); /* FLAG2 */
+ case 0x0c: return (cpustate->flag[3] != 0); /* FLAG3 */
+ case 0x0d: return (cpustate->astat & BTF); /* TF */
+ case 0x0e: return 0; /* BM */
+ case 0x0f: return (cpustate->curlcntr!=1); /* NOT LCE */
+ case 0x10: return !(cpustate->astat & AZ); /* NOT EQUAL */
+ case 0x11: return (cpustate->astat & AZ) || !(cpustate->astat & AN); /* GE */
+ case 0x12: return !(cpustate->astat & AZ) && !(cpustate->astat & AN); /* GT */
+ case 0x13: return !(cpustate->astat & AC); /* NOT AC */
+ case 0x14: return !(cpustate->astat & AV); /* NOT AV */
+ case 0x15: return !(cpustate->astat & MV); /* NOT MV */
+ case 0x16: return !(cpustate->astat & MN); /* NOT MS */
+ case 0x17: return !(cpustate->astat & SV); /* NOT SV */
+ case 0x18: return !(cpustate->astat & SZ); /* NOT SZ */
+ case 0x19: return (cpustate->flag[0] == 0); /* NOT FLAG0 */
+ case 0x1a: return (cpustate->flag[1] == 0); /* NOT FLAG1 */
+ case 0x1b: return (cpustate->flag[2] == 0); /* NOT FLAG2 */
+ case 0x1c: return (cpustate->flag[3] == 0); /* NOT FLAG3 */
+ case 0x1d: return !(cpustate->astat & BTF); /* NOT TF */
+ case 0x1e: return 1; /* NOT BM */
+ case 0x1f: return 1; /* TRUE */
+ }
+ return 1;
+}
+
+INLINE int DO_CONDITION_CODE(SHARC_REGS *cpustate, int cond)
+{
+ switch(cond)
+ {
+ case 0x00: return cpustate->astat & AZ; /* EQ */
+ case 0x01: return !(cpustate->astat & AZ) && (cpustate->astat & AN); /* LT */
+ case 0x02: return (cpustate->astat & AZ) || (cpustate->astat & AN); /* LE */
+ case 0x03: return (cpustate->astat & AC); /* AC */
+ case 0x04: return (cpustate->astat & AV); /* AV */
+ case 0x05: return (cpustate->astat & MV); /* MV */
+ case 0x06: return (cpustate->astat & MN); /* MS */
+ case 0x07: return (cpustate->astat & SV); /* SV */
+ case 0x08: return (cpustate->astat & SZ); /* SZ */
+ case 0x09: return (cpustate->flag[0] != 0); /* FLAG0 */
+ case 0x0a: return (cpustate->flag[1] != 0); /* FLAG1 */
+ case 0x0b: return (cpustate->flag[2] != 0); /* FLAG2 */
+ case 0x0c: return (cpustate->flag[3] != 0); /* FLAG3 */
+ case 0x0d: return (cpustate->astat & BTF); /* TF */
+ case 0x0e: return 0; /* BM */
+ case 0x0f: return (cpustate->curlcntr==1); /* LCE */
+ case 0x10: return !(cpustate->astat & AZ); /* NOT EQUAL */
+ case 0x11: return (cpustate->astat & AZ) || !(cpustate->astat & AN); /* GE */
+ case 0x12: return !(cpustate->astat & AZ) && !(cpustate->astat & AN); /* GT */
+ case 0x13: return !(cpustate->astat & AC); /* NOT AC */
+ case 0x14: return !(cpustate->astat & AV); /* NOT AV */
+ case 0x15: return !(cpustate->astat & MV); /* NOT MV */
+ case 0x16: return !(cpustate->astat & MN); /* NOT MS */
+ case 0x17: return !(cpustate->astat & SV); /* NOT SV */
+ case 0x18: return !(cpustate->astat & SZ); /* NOT SZ */
+ case 0x19: return (cpustate->flag[0] == 0); /* NOT FLAG0 */
+ case 0x1a: return (cpustate->flag[1] == 0); /* NOT FLAG1 */
+ case 0x1b: return (cpustate->flag[2] == 0); /* NOT FLAG2 */
+ case 0x1c: return (cpustate->flag[3] == 0); /* NOT FLAG3 */
+ case 0x1d: return !(cpustate->astat & BTF); /* NOT TF */
+ case 0x1e: return 1; /* NOT BM */
+ case 0x1f: return 0; /* FALSE (FOREVER) */
+ }
+ return 1;
+}
+
+/*****************************************************************************/
+/* | 001xxxxxx | */
+
+/* compute / dreg <-> DM / dreg <-> PM */
+static void sharcop_compute_dreg_dm_dreg_pm(SHARC_REGS *cpustate)
+{
+ int pm_dreg = (cpustate->opcode >> 23) & 0xf;
+ int pmm = (cpustate->opcode >> 27) & 0x7;
+ int pmi = (cpustate->opcode >> 30) & 0x7;
+ int dm_dreg = (cpustate->opcode >> 33) & 0xf;
+ int dmm = (cpustate->opcode >> 38) & 0x7;
+ int dmi = (cpustate->opcode >> 41) & 0x7;
+ int pmd = (cpustate->opcode >> 37) & 0x1;
+ int dmd = (cpustate->opcode >> 44) & 0x1;
+ int compute = cpustate->opcode & 0x7fffff;
+
+ /* due to parallelity issues, source DREGs must be saved */
+ /* because the compute operation may change them */
+ UINT32 parallel_pm_dreg = REG(pm_dreg);
+ UINT32 parallel_dm_dreg = REG(dm_dreg);
+
+ if (compute)
+ {
+ COMPUTE(cpustate, compute);
+ }
+
+ if (pmd) // dreg -> PM
+ {
+ pm_write32(cpustate, PM_REG_I(pmi), parallel_pm_dreg);
+ PM_REG_I(pmi) += PM_REG_M(pmm);
+ UPDATE_CIRCULAR_BUFFER_PM(pmi);
+ }
+ else // PM -> dreg
+ {
+ REG(pm_dreg) = pm_read32(cpustate, PM_REG_I(pmi));
+ PM_REG_I(pmi) += PM_REG_M(pmm);
+ UPDATE_CIRCULAR_BUFFER_PM(pmi);
+ }
+
+ if (dmd) // dreg -> DM
+ {
+ dm_write32(cpustate, DM_REG_I(dmi), parallel_dm_dreg);
+ DM_REG_I(dmi) += DM_REG_M(dmm);
+ UPDATE_CIRCULAR_BUFFER_DM(dmi);
+ }
+ else // DM -> dreg
+ {
+ REG(dm_dreg) = dm_read32(cpustate, DM_REG_I(dmi));
+ DM_REG_I(dmi) += DM_REG_M(dmm);
+ UPDATE_CIRCULAR_BUFFER_DM(dmi);
+ }
+}
+
+/*****************************************************************************/
+/* | 00000001x | */
+
+/* compute */
+static void sharcop_compute(SHARC_REGS *cpustate)
+{
+ int cond = (cpustate->opcode >> 33) & 0x1f;
+ int compute = cpustate->opcode & 0x7fffff;
+
+ if (IF_CONDITION_CODE(cpustate, cond) && compute != 0)
+ {
+ COMPUTE(cpustate, compute);
+ }
+}
+
+/*****************************************************************************/
+/* | 010xxxxxx | */
+
+/* compute / ureg <-> DM|PM, pre-modify */
+static void sharcop_compute_ureg_dmpm_premod(SHARC_REGS *cpustate)
+{
+ int i = (cpustate->opcode >> 41) & 0x7;
+ int m = (cpustate->opcode >> 38) & 0x7;
+ int cond = (cpustate->opcode >> 33) & 0x1f;
+ int g = (cpustate->opcode >> 32) & 0x1;
+ int d = (cpustate->opcode >> 31) & 0x1;
+ int ureg = (cpustate->opcode >> 23) & 0xff;
+ int compute = cpustate->opcode & 0x7fffff;
+
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ /* due to parallelity issues, source UREG must be saved */
+ /* because the compute operation may change it */
+ UINT32 parallel_ureg = GET_UREG(cpustate, ureg);
+
+ if (compute)
+ {
+ COMPUTE(cpustate, compute);
+ }
+
+ if (g) /* PM */
+ {
+ if (d) /* ureg -> PM */
+ {
+ if (ureg == 0xdb) /* PX register access is always 48-bit */
+ {
+ pm_write48(cpustate, PM_REG_I(i)+PM_REG_M(m), cpustate->px);
+ }
+ else
+ {
+ pm_write32(cpustate, PM_REG_I(i)+PM_REG_M(m), parallel_ureg);
+ }
+ }
+ else /* PM <- ureg */
+ {
+ if (ureg == 0xdb) /* PX register access is always 48-bit */
+ {
+ cpustate->px = pm_read48(cpustate, PM_REG_I(i)+PM_REG_M(m));
+ }
+ else
+ {
+ SET_UREG(cpustate, ureg, pm_read32(cpustate, PM_REG_I(i)+PM_REG_M(m)));
+ }
+ }
+ }
+ else /* DM */
+ {
+ if (d) /* ureg -> DM */
+ {
+ dm_write32(cpustate, DM_REG_I(i)+DM_REG_M(m), parallel_ureg);
+ }
+ else /* DM <- ureg */
+ {
+ SET_UREG(cpustate, ureg, dm_read32(cpustate, DM_REG_I(i)+DM_REG_M(m)));
+ }
+ }
+ }
+}
+
+/* compute / ureg <-> DM|PM, post-modify */
+static void sharcop_compute_ureg_dmpm_postmod(SHARC_REGS *cpustate)
+{
+ int i = (cpustate->opcode >> 41) & 0x7;
+ int m = (cpustate->opcode >> 38) & 0x7;
+ int cond = (cpustate->opcode >> 33) & 0x1f;
+ int g = (cpustate->opcode >> 32) & 0x1;
+ int d = (cpustate->opcode >> 31) & 0x1;
+ int ureg = (cpustate->opcode >> 23) & 0xff;
+ int compute = cpustate->opcode & 0x7fffff;
+
+ if(IF_CONDITION_CODE(cpustate, cond))
+ {
+ /* due to parallelity issues, source UREG must be saved */
+ /* because the compute operation may change it */
+ UINT32 parallel_ureg = GET_UREG(cpustate, ureg);
+
+ if (compute)
+ {
+ COMPUTE(cpustate, compute);
+ }
+
+ if (g) /* PM */
+ {
+ if (d) /* ureg -> PM */
+ {
+ if (ureg == 0xdb) /* PX register access is always 48-bit */
+ {
+ pm_write48(cpustate, PM_REG_I(i), cpustate->px);
+ }
+ else
+ {
+ pm_write32(cpustate, PM_REG_I(i), parallel_ureg);
+ }
+ PM_REG_I(i) += PM_REG_M(m);
+ UPDATE_CIRCULAR_BUFFER_PM(i);
+ }
+ else /* PM <- ureg */
+ {
+ if (ureg == 0xdb) /* PX register access is always 48-bit */
+ {
+ cpustate->px = pm_read48(cpustate, PM_REG_I(i));
+ }
+ else
+ {
+ SET_UREG(cpustate, ureg, pm_read32(cpustate, PM_REG_I(i)));
+ }
+ PM_REG_I(i) += PM_REG_M(m);
+ UPDATE_CIRCULAR_BUFFER_PM(i);
+ }
+ }
+ else /* DM */
+ {
+ if (d) /* ureg -> DM */
+ {
+ dm_write32(cpustate, DM_REG_I(i), parallel_ureg);
+ DM_REG_I(i) += DM_REG_M(m);
+ UPDATE_CIRCULAR_BUFFER_DM(i);
+ }
+ else /* DM <- ureg */
+ {
+ SET_UREG(cpustate, ureg, dm_read32(cpustate, DM_REG_I(i)));
+ DM_REG_I(i) += DM_REG_M(m);
+ UPDATE_CIRCULAR_BUFFER_DM(i);
+ }
+ }
+ }
+}
+
+/*****************************************************************************/
+/* | 0110xxxxx | */
+
+/* compute / dreg <- DM, immediate modify */
+static void sharcop_compute_dm_to_dreg_immmod(SHARC_REGS *cpustate)
+{
+ int cond = (cpustate->opcode >> 33) & 0x1f;
+ int u = (cpustate->opcode >> 38) & 0x1;
+ int dreg = (cpustate->opcode >> 23) & 0xf;
+ int i = (cpustate->opcode >> 41) & 0x7;
+ int mod = SIGN_EXTEND6((cpustate->opcode >> 27) & 0x3f);
+ int compute = cpustate->opcode & 0x7fffff;
+
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ if (compute != 0)
+ {
+ COMPUTE(cpustate, compute);
+ }
+
+ if (u) /* post-modify with update */
+ {
+ REG(dreg) = dm_read32(cpustate, DM_REG_I(i));
+ DM_REG_I(i) += mod;
+ UPDATE_CIRCULAR_BUFFER_DM(i);
+ }
+ else /* pre-modify, no update */
+ {
+ REG(dreg) = dm_read32(cpustate, DM_REG_I(i) + mod);
+ }
+ }
+}
+
+/* compute / dreg -> DM, immediate modify */
+static void sharcop_compute_dreg_to_dm_immmod(SHARC_REGS *cpustate)
+{
+ int cond = (cpustate->opcode >> 33) & 0x1f;
+ int u = (cpustate->opcode >> 38) & 0x1;
+ int dreg = (cpustate->opcode >> 23) & 0xf;
+ int i = (cpustate->opcode >> 41) & 0x7;
+ int mod = SIGN_EXTEND6((cpustate->opcode >> 27) & 0x3f);
+ int compute = cpustate->opcode & 0x7fffff;
+
+ /* due to parallelity issues, source REG must be saved */
+ /* because the shift operation may change it */
+ UINT32 parallel_dreg = REG(dreg);
+
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ if (compute != 0)
+ {
+ COMPUTE(cpustate, compute);
+ }
+
+ if (u) /* post-modify with update */
+ {
+ dm_write32(cpustate, DM_REG_I(i), parallel_dreg);
+ DM_REG_I(i) += mod;
+ UPDATE_CIRCULAR_BUFFER_DM(i);
+ }
+ else /* pre-modify, no update */
+ {
+ dm_write32(cpustate, DM_REG_I(i) + mod, parallel_dreg);
+ }
+ }
+}
+
+/* compute / dreg <- PM, immediate modify */
+static void sharcop_compute_pm_to_dreg_immmod(SHARC_REGS *cpustate)
+{
+ int cond = (cpustate->opcode >> 33) & 0x1f;
+ int u = (cpustate->opcode >> 38) & 0x1;
+ int dreg = (cpustate->opcode >> 23) & 0xf;
+ int i = (cpustate->opcode >> 41) & 0x7;
+ int mod = SIGN_EXTEND6((cpustate->opcode >> 27) & 0x3f);
+ int compute = cpustate->opcode & 0x7fffff;
+
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ if (compute != 0)
+ {
+ COMPUTE(cpustate, compute);
+ }
+
+ if (u) /* post-modify with update */
+ {
+ REG(dreg) = pm_read32(cpustate, PM_REG_I(i));
+ PM_REG_I(i) += mod;
+ UPDATE_CIRCULAR_BUFFER_PM(i);
+ }
+ else /* pre-modify, no update */
+ {
+ REG(dreg) = pm_read32(cpustate, PM_REG_I(i) + mod);
+ }
+ }
+}
+
+/* compute / dreg -> PM, immediate modify */
+static void sharcop_compute_dreg_to_pm_immmod(SHARC_REGS *cpustate)
+{
+ int cond = (cpustate->opcode >> 33) & 0x1f;
+ int u = (cpustate->opcode >> 38) & 0x1;
+ int dreg = (cpustate->opcode >> 23) & 0xf;
+ int i = (cpustate->opcode >> 41) & 0x7;
+ int mod = SIGN_EXTEND6((cpustate->opcode >> 27) & 0x3f);
+ int compute = cpustate->opcode & 0x7fffff;
+
+ /* due to parallelity issues, source REG must be saved */
+ /* because the compute operation may change it */
+ UINT32 parallel_dreg = REG(dreg);
+
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ if (compute != 0)
+ {
+ COMPUTE(cpustate, compute);
+ }
+
+ if (u) /* post-modify with update */
+ {
+ pm_write32(cpustate, PM_REG_I(i), parallel_dreg);
+ PM_REG_I(i) += mod;
+ UPDATE_CIRCULAR_BUFFER_PM(i);
+ }
+ else /* pre-modify, no update */
+ {
+ pm_write32(cpustate, PM_REG_I(i) + mod, parallel_dreg);
+ }
+ }
+}
+
+/*****************************************************************************/
+/* | 0111xxxxx | */
+
+/* compute / ureg <-> ureg */
+static void sharcop_compute_ureg_to_ureg(SHARC_REGS *cpustate)
+{
+ int src_ureg = (cpustate->opcode >> 36) & 0xff;
+ int dst_ureg = (cpustate->opcode >> 23) & 0xff;
+ int cond = (cpustate->opcode >> 31) & 0x1f;
+ int compute = cpustate->opcode & 0x7fffff;
+
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ /* due to parallelity issues, source UREG must be saved */
+ /* because the compute operation may change it */
+ UINT32 parallel_ureg = GET_UREG(cpustate, src_ureg);
+
+ if (compute != 0)
+ {
+ COMPUTE(cpustate, compute);
+ }
+
+ SET_UREG(cpustate, dst_ureg, parallel_ureg);
+ }
+}
+
+/*****************************************************************************/
+/* | 1000xxxxx | */
+
+/* immediate shift / dreg <-> DM|PM */
+static void sharcop_imm_shift_dreg_dmpm(SHARC_REGS *cpustate)
+{
+ int i = (cpustate->opcode >> 41) & 0x7;
+ int m = (cpustate->opcode >> 38) & 0x7;
+ int g = (cpustate->opcode >> 32) & 0x1;
+ int d = (cpustate->opcode >> 31) & 0x1;
+ int dreg = (cpustate->opcode >> 23) & 0xf;
+ int cond = (cpustate->opcode >> 33) & 0x1f;
+ int data = ((cpustate->opcode >> 8) & 0xff) | ((cpustate->opcode >> 19) & 0xf00);
+ int shiftop = (cpustate->opcode >> 16) & 0x3f;
+ int rn = (cpustate->opcode >> 4) & 0xf;
+ int rx = (cpustate->opcode & 0xf);
+
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ /* due to parallelity issues, source REG must be saved */
+ /* because the shift operation may change it */
+ UINT32 parallel_dreg = REG(dreg);
+
+ SHIFT_OPERATION_IMM(cpustate, shiftop, data, rn, rx);
+
+ if (g) /* PM */
+ {
+ if (d) /* dreg -> PM */
+ {
+ pm_write32(cpustate, PM_REG_I(i), parallel_dreg);
+ PM_REG_I(i) += PM_REG_M(m);
+ UPDATE_CIRCULAR_BUFFER_PM(i);
+ }
+ else /* PM <- dreg */
+ {
+ REG(dreg) = pm_read32(cpustate, PM_REG_I(i));
+ PM_REG_I(i) += PM_REG_M(m);
+ UPDATE_CIRCULAR_BUFFER_PM(i);
+ }
+ }
+ else /* DM */
+ {
+ if (d) /* dreg -> DM */
+ {
+ dm_write32(cpustate, DM_REG_I(i), parallel_dreg);
+ DM_REG_I(i) += DM_REG_M(m);
+ UPDATE_CIRCULAR_BUFFER_DM(i);
+ }
+ else /* DM <- dreg */
+ {
+ REG(dreg) = dm_read32(cpustate, DM_REG_I(i));
+ DM_REG_I(i) += DM_REG_M(m);
+ UPDATE_CIRCULAR_BUFFER_DM(i);
+ }
+ }
+ }
+}
+
+/*****************************************************************************/
+/* | 00000010x | */
+
+/* immediate shift */
+static void sharcop_imm_shift(SHARC_REGS *cpustate)
+{
+ int cond = (cpustate->opcode >> 33) & 0x1f;
+ int data = ((cpustate->opcode >> 8) & 0xff) | ((cpustate->opcode >> 19) & 0xf00);
+ int shiftop = (cpustate->opcode >> 16) & 0x3f;
+ int rn = (cpustate->opcode >> 4) & 0xf;
+ int rx = (cpustate->opcode & 0xf);
+
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ SHIFT_OPERATION_IMM(cpustate, shiftop, data, rn, rx);
+ }
+}
+
+/*****************************************************************************/
+/* | 00000100x | */
+
+/* compute / modify */
+static void sharcop_compute_modify(SHARC_REGS *cpustate)
+{
+ int cond = (cpustate->opcode >> 33) & 0x1f;
+ int compute = cpustate->opcode & 0x7fffff;
+ int g = (cpustate->opcode >> 38) & 0x1;
+ int m = (cpustate->opcode >> 27) & 0x7;
+ int i = (cpustate->opcode >> 30) & 0x7;
+
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ if (compute != 0)
+ {
+ COMPUTE(cpustate, compute);
+ }
+
+ if (g) /* Modify PM */
+ {
+ PM_REG_I(i) += PM_REG_M(m);
+ UPDATE_CIRCULAR_BUFFER_PM(i);
+ }
+ else /* Modify DM */
+ {
+ DM_REG_I(i) += DM_REG_M(m);
+ UPDATE_CIRCULAR_BUFFER_DM(i);
+ }
+ }
+}
+
+/*****************************************************************************/
+/* | 00000110x | */
+
+/* direct call to absolute address */
+static void sharcop_direct_call(SHARC_REGS *cpustate)
+{
+ int j = (cpustate->opcode >> 26) & 0x1;
+ int cond = (cpustate->opcode >> 33) & 0x1f;
+ UINT32 address = cpustate->opcode & 0xffffff;
+
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ if (j)
+ {
+ //PUSH_PC(cpustate, cpustate->pc+3); /* 1 instruction + 2 delayed instructions */
+ PUSH_PC(cpustate, cpustate->nfaddr); /* 1 instruction + 2 delayed instructions */
+ CHANGE_PC_DELAYED(cpustate, address);
+ }
+ else
+ {
+ //PUSH_PC(cpustate, cpustate->pc+1);
+ PUSH_PC(cpustate, cpustate->daddr);
+ CHANGE_PC(cpustate, address);
+ }
+ }
+}
+
+/* direct jump to absolute address */
+static void sharcop_direct_jump(SHARC_REGS *cpustate)
+{
+ int la = (cpustate->opcode >> 38) & 0x1;
+ int ci = (cpustate->opcode >> 24) & 0x1;
+ int j = (cpustate->opcode >> 26) & 0x1;
+ int cond = (cpustate->opcode >> 33) & 0x1f;
+ UINT32 address = cpustate->opcode & 0xffffff;
+
+ if(IF_CONDITION_CODE(cpustate, cond))
+ {
+ // Clear Interrupt
+ if (ci)
+ {
+ // TODO: anything else?
+ if (cpustate->status_stkp > 0)
+ {
+ POP_STATUS_STACK(cpustate);
+ }
+
+ cpustate->interrupt_active = 0;
+ cpustate->irptl &= ~(1 << cpustate->active_irq_num);
+ }
+
+ if (la)
+ {
+ POP_PC(cpustate);
+ POP_LOOP(cpustate);
+ }
+
+ if (j)
+ {
+ CHANGE_PC_DELAYED(cpustate, address);
+ }
+ else
+ {
+ CHANGE_PC(cpustate, address);
+ }
+ }
+}
+
+/*****************************************************************************/
+/* | 00000111x | */
+
+/* direct call to relative address */
+static void sharcop_relative_call(SHARC_REGS *cpustate)
+{
+ int j = (cpustate->opcode >> 26) & 0x1;
+ int cond = (cpustate->opcode >> 33) & 0x1f;
+ UINT32 address = cpustate->opcode & 0xffffff;
+
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ if (j)
+ {
+ PUSH_PC(cpustate, cpustate->pc+3); /* 1 instruction + 2 delayed instructions */
+ CHANGE_PC_DELAYED(cpustate, cpustate->pc + SIGN_EXTEND24(address));
+ }
+ else
+ {
+ PUSH_PC(cpustate, cpustate->pc+1);
+ CHANGE_PC(cpustate, cpustate->pc + SIGN_EXTEND24(address));
+ }
+ }
+}
+
+/* direct jump to relative address */
+static void sharcop_relative_jump(SHARC_REGS *cpustate)
+{
+ int la = (cpustate->opcode >> 38) & 0x1;
+ int ci = (cpustate->opcode >> 24) & 0x1;
+ int j = (cpustate->opcode >> 26) & 0x1;
+ int cond = (cpustate->opcode >> 33) & 0x1f;
+ UINT32 address = cpustate->opcode & 0xffffff;
+
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ // Clear Interrupt
+ if (ci)
+ {
+ // TODO: anything else?
+ if (cpustate->status_stkp > 0)
+ {
+ POP_STATUS_STACK(cpustate);
+ }
+
+ cpustate->interrupt_active = 0;
+ cpustate->irptl &= ~(1 << cpustate->active_irq_num);
+ }
+
+ if (la)
+ {
+ POP_PC(cpustate);
+ POP_LOOP(cpustate);
+ }
+
+ if (j)
+ {
+ CHANGE_PC_DELAYED(cpustate, cpustate->pc + SIGN_EXTEND24(address));
+ }
+ else
+ {
+ CHANGE_PC(cpustate, cpustate->pc + SIGN_EXTEND24(address));
+ }
+ }
+}
+
+/*****************************************************************************/
+/* | 00001000x | */
+
+/* indirect jump */
+static void sharcop_indirect_jump(SHARC_REGS *cpustate)
+{
+ int la = (cpustate->opcode >> 38) & 0x1;
+ int ci = (cpustate->opcode >> 24) & 0x1;
+ int j = (cpustate->opcode >> 26) & 0x1;
+ int e = (cpustate->opcode >> 25) & 0x1;
+ int pmi = (cpustate->opcode >> 30) & 0x7;
+ int pmm = (cpustate->opcode >> 27) & 0x7;
+ int cond = (cpustate->opcode >> 33) & 0x1f;
+ int compute = cpustate->opcode & 0x7fffff;
+
+ // Clear Interrupt
+ if (ci)
+ {
+ // TODO: anything else?
+ if (cpustate->status_stkp > 0)
+ {
+ POP_STATUS_STACK(cpustate);
+ }
+
+ cpustate->interrupt_active = 0;
+ cpustate->irptl &= ~(1 << cpustate->active_irq_num);
+ }
+
+ if (e) /* IF...ELSE */
+ {
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ if (la)
+ {
+ POP_PC(cpustate);
+ POP_LOOP(cpustate);
+ }
+
+ if(j)
+ {
+ CHANGE_PC_DELAYED(cpustate, PM_REG_I(pmi) + PM_REG_M(pmm));
+ }
+ else
+ {
+ CHANGE_PC(cpustate, PM_REG_I(pmi) + PM_REG_M(pmm));
+ }
+ }
+ else
+ {
+ if (compute)
+ {
+ COMPUTE(cpustate, compute);
+ }
+ }
+ }
+ else /* IF */
+ {
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ if (compute)
+ {
+ COMPUTE(cpustate, compute);
+ }
+
+ if (la)
+ {
+ POP_PC(cpustate);
+ POP_LOOP(cpustate);
+ }
+
+ if(j)
+ {
+ CHANGE_PC_DELAYED(cpustate, PM_REG_I(pmi) + PM_REG_M(pmm));
+ }
+ else
+ {
+ CHANGE_PC(cpustate, PM_REG_I(pmi) + PM_REG_M(pmm));
+ }
+ }
+ }
+}
+
+/* indirect call */
+static void sharcop_indirect_call(SHARC_REGS *cpustate)
+{
+ int j = (cpustate->opcode >> 26) & 0x1;
+ int e = (cpustate->opcode >> 25) & 0x1;
+ int pmi = (cpustate->opcode >> 30) & 0x7;
+ int pmm = (cpustate->opcode >> 27) & 0x7;
+ int cond = (cpustate->opcode >> 33) & 0x1f;
+ int compute = cpustate->opcode & 0x7fffff;
+
+ if (e) /* IF...ELSE */
+ {
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ if (j)
+ {
+ //PUSH_PC(cpustate, cpustate->pc+3); /* 1 instruction + 2 delayed instructions */
+ PUSH_PC(cpustate, cpustate->nfaddr); /* 1 instruction + 2 delayed instructions */
+ CHANGE_PC_DELAYED(cpustate, PM_REG_I(pmi) + PM_REG_M(pmm));
+ }
+ else
+ {
+ //PUSH_PC(cpustate, cpustate->pc+1);
+ PUSH_PC(cpustate, cpustate->daddr);
+ CHANGE_PC(cpustate, PM_REG_I(pmi) + PM_REG_M(pmm));
+ }
+ }
+ else
+ {
+ if (compute)
+ {
+ COMPUTE(cpustate, compute);
+ }
+ }
+ }
+ else /* IF */
+ {
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ if (compute)
+ {
+ COMPUTE(cpustate, compute);
+ }
+
+ if (j)
+ {
+ //PUSH_PC(cpustate, cpustate->pc+3); /* 1 instruction + 2 delayed instructions */
+ PUSH_PC(cpustate, cpustate->nfaddr); /* 1 instruction + 2 delayed instructions */
+ CHANGE_PC_DELAYED(cpustate, PM_REG_I(pmi) + PM_REG_M(pmm));
+ }
+ else
+ {
+ //PUSH_PC(cpustate, cpustate->pc+1);
+ PUSH_PC(cpustate, cpustate->daddr);
+ CHANGE_PC(cpustate, PM_REG_I(pmi) + PM_REG_M(pmm));
+ }
+ }
+ }
+}
+
+/*****************************************************************************/
+/* | 00001001x | */
+
+/* indirect jump to relative address */
+static void sharcop_relative_jump_compute(SHARC_REGS *cpustate)
+{
+ int la = (cpustate->opcode >> 38) & 0x1;
+ int ci = (cpustate->opcode >> 24) & 0x1;
+ int j = (cpustate->opcode >> 26) & 0x1;
+ int e = (cpustate->opcode >> 25) & 0x1;
+ int cond = (cpustate->opcode >> 33) & 0x1f;
+ int compute = cpustate->opcode & 0x7fffff;
+
+ // Clear Interrupt
+ if (ci)
+ {
+ // TODO: anything else?
+ if (cpustate->status_stkp > 0)
+ {
+ POP_STATUS_STACK(cpustate);
+ }
+
+ cpustate->interrupt_active = 0;
+ cpustate->irptl &= ~(1 << cpustate->active_irq_num);
+ }
+
+ if (e) /* IF...ELSE */
+ {
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ if (la)
+ {
+ POP_PC(cpustate);
+ POP_LOOP(cpustate);
+ }
+
+ if (j)
+ {
+ CHANGE_PC_DELAYED(cpustate, cpustate->pc + SIGN_EXTEND6((cpustate->opcode >> 27) & 0x3f));
+ }
+ else
+ {
+ CHANGE_PC(cpustate, cpustate->pc + SIGN_EXTEND6((cpustate->opcode >> 27) & 0x3f));
+ }
+ }
+ else
+ {
+ if (compute)
+ {
+ COMPUTE(cpustate, compute);
+ }
+ }
+ }
+ else /* IF */
+ {
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ if (compute)
+ {
+ COMPUTE(cpustate, compute);
+ }
+
+ if (la)
+ {
+ POP_PC(cpustate);
+ POP_LOOP(cpustate);
+ }
+
+ if (j)
+ {
+ CHANGE_PC_DELAYED(cpustate, cpustate->pc + SIGN_EXTEND6((cpustate->opcode >> 27) & 0x3f));
+ }
+ else
+ {
+ CHANGE_PC(cpustate, cpustate->pc + SIGN_EXTEND6((cpustate->opcode >> 27) & 0x3f));
+ }
+ }
+ }
+}
+
+/* indirect call to relative address */
+static void sharcop_relative_call_compute(SHARC_REGS *cpustate)
+{
+ int j = (cpustate->opcode >> 26) & 0x1;
+ int e = (cpustate->opcode >> 25) & 0x1;
+ int cond = (cpustate->opcode >> 33) & 0x1f;
+ int compute = cpustate->opcode & 0x7fffff;
+
+ if (e) /* IF...ELSE */
+ {
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ if (j)
+ {
+ //PUSH_PC(cpustate, cpustate->pc+3); /* 1 instruction + 2 delayed instructions */
+ PUSH_PC(cpustate, cpustate->nfaddr); /* 1 instruction + 2 delayed instructions */
+ CHANGE_PC_DELAYED(cpustate, cpustate->pc + SIGN_EXTEND6((cpustate->opcode >> 27) & 0x3f));
+ }
+ else
+ {
+ //PUSH_PC(cpustate, cpustate->pc+1);
+ PUSH_PC(cpustate, cpustate->daddr);
+ CHANGE_PC(cpustate, cpustate->pc + SIGN_EXTEND6((cpustate->opcode >> 27) & 0x3f));
+ }
+ }
+ else
+ {
+ if (compute)
+ {
+ COMPUTE(cpustate, compute);
+ }
+ }
+ }
+ else /* IF */
+ {
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ if (compute)
+ {
+ COMPUTE(cpustate, compute);
+ }
+
+ if (j)
+ {
+ //PUSH_PC(cpustate, cpustate->pc+3); /* 1 instruction + 2 delayed instructions */
+ PUSH_PC(cpustate, cpustate->nfaddr); /* 1 instruction + 2 delayed instructions */
+ CHANGE_PC_DELAYED(cpustate, cpustate->pc + SIGN_EXTEND6((cpustate->opcode >> 27) & 0x3f));
+ }
+ else
+ {
+ //PUSH_PC(cpustate, cpustate->pc+1);
+ PUSH_PC(cpustate, cpustate->daddr);
+ CHANGE_PC(cpustate, cpustate->pc + SIGN_EXTEND6((cpustate->opcode >> 27) & 0x3f));
+ }
+ }
+ }
+}
+
+/*****************************************************************************/
+/* | 110xxxxxx | */
+
+/* indirect jump / compute / dreg <-> DM */
+static void sharcop_indirect_jump_compute_dreg_dm(SHARC_REGS *cpustate)
+{
+ int d = (cpustate->opcode >> 44) & 0x1;
+ int dmi = (cpustate->opcode >> 41) & 0x7;
+ int dmm = (cpustate->opcode >> 38) & 0x7;
+ int pmi = (cpustate->opcode >> 30) & 0x7;
+ int pmm = (cpustate->opcode >> 27) & 0x7;
+ int cond = (cpustate->opcode >> 33) & 0x1f;
+ int dreg = (cpustate->opcode >> 23) & 0xf;
+
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ CHANGE_PC(cpustate, PM_REG_I(pmi) + PM_REG_M(pmm));
+ }
+ else
+ {
+ UINT32 compute = cpustate->opcode & 0x7fffff;
+ /* due to parallelity issues, source REG must be saved */
+ /* because the compute operation may change it */
+ UINT32 parallel_dreg = REG(dreg);
+
+ if (compute)
+ {
+ COMPUTE(cpustate, compute);
+ }
+
+ if (d) /* dreg -> DM */
+ {
+ dm_write32(cpustate, DM_REG_I(dmi), parallel_dreg);
+ DM_REG_I(dmi) += DM_REG_M(dmm);
+ UPDATE_CIRCULAR_BUFFER_DM(dmi);
+ }
+ else /* DM <- dreg */
+ {
+ REG(dreg) = dm_read32(cpustate, DM_REG_I(dmi));
+ DM_REG_I(dmi) += DM_REG_M(dmm);
+ UPDATE_CIRCULAR_BUFFER_DM(dmi);
+ }
+ }
+}
+
+/*****************************************************************************/
+/* | 111xxxxxx | */
+
+/* relative jump / compute / dreg <-> DM */
+static void sharcop_relative_jump_compute_dreg_dm(SHARC_REGS *cpustate)
+{
+ int d = (cpustate->opcode >> 44) & 0x1;
+ int dmi = (cpustate->opcode >> 41) & 0x7;
+ int dmm = (cpustate->opcode >> 38) & 0x7;
+ int cond = (cpustate->opcode >> 33) & 0x1f;
+ int dreg = (cpustate->opcode >> 23) & 0xf;
+
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ CHANGE_PC(cpustate, cpustate->pc + SIGN_EXTEND6((cpustate->opcode >> 27) & 0x3f));
+ }
+ else
+ {
+ UINT32 compute = cpustate->opcode & 0x7fffff;
+ /* due to parallelity issues, source REG must be saved */
+ /* because the compute operation may change it */
+ UINT32 parallel_dreg = REG(dreg);
+
+ if (compute)
+ {
+ COMPUTE(cpustate, compute);
+ }
+
+ if (d) /* dreg -> DM */
+ {
+ dm_write32(cpustate, DM_REG_I(dmi), parallel_dreg);
+ DM_REG_I(dmi) += DM_REG_M(dmm);
+ UPDATE_CIRCULAR_BUFFER_DM(dmi);
+ }
+ else /* DM <- dreg */
+ {
+ REG(dreg) = dm_read32(cpustate, DM_REG_I(dmi));
+ DM_REG_I(dmi) += DM_REG_M(dmm);
+ UPDATE_CIRCULAR_BUFFER_DM(dmi);
+ }
+ }
+}
+
+/*****************************************************************************/
+/* | 00001010x | */
+
+/* return from subroutine / compute */
+static void sharcop_rts(SHARC_REGS *cpustate)
+{
+ int cond = (cpustate->opcode >> 33) & 0x1f;
+ int j = (cpustate->opcode >> 26) & 0x1;
+ int e = (cpustate->opcode >> 25) & 0x1;
+ //int lr = (cpustate->opcode >> 24) & 0x1;
+ int compute = cpustate->opcode & 0x7fffff;
+
+ //if(lr)
+ // fatalerror("SHARC: rts: loop reentry not implemented !");
+
+ if (e) /* IF...ELSE */
+ {
+ if(IF_CONDITION_CODE(cpustate, cond))
+ {
+ if (j)
+ {
+ CHANGE_PC_DELAYED(cpustate, POP_PC(cpustate));
+ }
+ else
+ {
+ CHANGE_PC(cpustate, POP_PC(cpustate));
+ }
+ }
+ else
+ {
+ if (compute)
+ {
+ COMPUTE(cpustate, compute);
+ }
+ }
+ }
+ else /* IF */
+ {
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ if (compute)
+ {
+ COMPUTE(cpustate, compute);
+ }
+
+ if (j)
+ {
+ CHANGE_PC_DELAYED(cpustate, POP_PC(cpustate));
+ }
+ else
+ {
+ CHANGE_PC(cpustate, POP_PC(cpustate));
+ }
+ }
+ }
+}
+
+/*****************************************************************************/
+/* | 00001011x | */
+
+/* return from interrupt / compute */
+static void sharcop_rti(SHARC_REGS *cpustate)
+{
+ int cond = (cpustate->opcode >> 33) & 0x1f;
+ int j = (cpustate->opcode >> 26) & 0x1;
+ int e = (cpustate->opcode >> 25) & 0x1;
+ int compute = cpustate->opcode & 0x7fffff;
+
+ cpustate->irptl &= ~(1 << cpustate->active_irq_num);
+
+ if(e) /* IF...ELSE */
+ {
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ if (j)
+ {
+ CHANGE_PC_DELAYED(cpustate, POP_PC(cpustate));
+ }
+ else
+ {
+ CHANGE_PC(cpustate, POP_PC(cpustate));
+ }
+ }
+ else
+ {
+ if (compute)
+ {
+ COMPUTE(cpustate, compute);
+ }
+ }
+ }
+ else /* IF */
+ {
+ if (IF_CONDITION_CODE(cpustate, cond))
+ {
+ if (compute)
+ {
+ COMPUTE(cpustate, compute);
+ }
+
+ if (j)
+ {
+ CHANGE_PC_DELAYED(cpustate, POP_PC(cpustate));
+ }
+ else
+ {
+ CHANGE_PC(cpustate, POP_PC(cpustate));
+ }
+ }
+ }
+
+ if (cpustate->status_stkp > 0)
+ {
+ POP_STATUS_STACK(cpustate);
+ }
+
+ cpustate->interrupt_active = 0;
+ check_interrupts(cpustate);
+}
+
+/*****************************************************************************/
+/* | 00001100x | */
+
+/* do until counter expired, LCNTR immediate */
+static void sharcop_do_until_counter_imm(SHARC_REGS *cpustate)
+{
+ UINT16 data = (UINT16)(cpustate->opcode >> 24);
+ int offset = SIGN_EXTEND24(cpustate->opcode & 0xffffff);
+ UINT32 address = cpustate->pc + offset;
+ int type;
+ int cond = 0xf; /* until LCE (loop counter expired */
+ int distance = abs(offset);
+
+ if (distance == 1)
+ {
+ type = 1;
+ }
+ else if (distance == 2)
+ {
+ type = 2;
+ }
+ else
+ {
+ type = 3;
+ }
+
+ cpustate->lcntr = data;
+ if (cpustate->lcntr > 0)
+ {
+ PUSH_PC(cpustate, cpustate->pc+1);
+ PUSH_LOOP(cpustate, address | (type << 30) | (cond << 24), cpustate->lcntr);
+ }
+}
+
+/*****************************************************************************/
+/* | 00001101x | */
+
+/* do until counter expired, LCNTR from UREG */
+static void sharcop_do_until_counter_ureg(SHARC_REGS *cpustate)
+{
+ int ureg = (cpustate->opcode >> 32) & 0xff;
+ int offset = SIGN_EXTEND24(cpustate->opcode & 0xffffff);
+ UINT32 address = cpustate->pc + offset;
+ int type;
+ int cond = 0xf; /* until LCE (loop counter expired */
+ int distance = abs(offset);
+
+ if (distance == 1)
+ {
+ type = 1;
+ }
+ else if (distance == 2)
+ {
+ type = 2;
+ }
+ else
+ {
+ type = 3;
+ }
+
+ cpustate->lcntr = GET_UREG(cpustate, ureg);
+ if (cpustate->lcntr > 0)
+ {
+ PUSH_PC(cpustate, cpustate->pc+1);
+ PUSH_LOOP(cpustate, address | (type << 30) | (cond << 24), cpustate->lcntr);
+ }
+}
+
+/*****************************************************************************/
+/* | 00001110x | */
+
+/* do until */
+static void sharcop_do_until(SHARC_REGS *cpustate)
+{
+ int cond = (cpustate->opcode >> 33) & 0x1f;
+ int offset = SIGN_EXTEND24(cpustate->opcode & 0xffffff);
+ UINT32 address = (cpustate->pc + offset);
+
+ PUSH_PC(cpustate, cpustate->pc+1);
+ PUSH_LOOP(cpustate, address | (cond << 24), 0);
+}
+
+/*****************************************************************************/
+/* | 000100 | G | D | */
+
+/* ureg <- DM (direct addressing) */
+static void sharcop_dm_to_ureg_direct(SHARC_REGS *cpustate)
+{
+ int ureg = (cpustate->opcode >> 32) & 0xff;
+ UINT32 address = (UINT32)(cpustate->opcode);
+
+ SET_UREG(cpustate, ureg, dm_read32(cpustate, address));
+}
+
+/* ureg -> DM (direct addressing) */
+static void sharcop_ureg_to_dm_direct(SHARC_REGS *cpustate)
+{
+ int ureg = (cpustate->opcode >> 32) & 0xff;
+ UINT32 address = (UINT32)(cpustate->opcode);
+
+ dm_write32(cpustate, address, GET_UREG(cpustate, ureg));
+}
+
+/* ureg <- PM (direct addressing) */
+static void sharcop_pm_to_ureg_direct(SHARC_REGS *cpustate)
+{
+ int ureg = (cpustate->opcode >> 32) & 0xff;
+ UINT32 address = (UINT32)(cpustate->opcode);
+
+ if (ureg == 0xdb) // PX is 48-bit
+ {
+ cpustate->px = pm_read48(cpustate, address);
+ }
+ else
+ {
+ SET_UREG(cpustate, ureg, pm_read32(cpustate, address));
+ }
+}
+
+/* ureg -> PM (direct addressing) */
+static void sharcop_ureg_to_pm_direct(SHARC_REGS *cpustate)
+{
+ int ureg = (cpustate->opcode >> 32) & 0xff;
+ UINT32 address = (UINT32)(cpustate->opcode);
+
+ if (ureg == 0xdb) // PX is 48-bit
+ {
+ pm_write48(cpustate, address, cpustate->px);
+ }
+ else
+ {
+ pm_write32(cpustate, address, GET_UREG(cpustate, ureg));
+ }
+}
+
+/*****************************************************************************/
+/* | 101 | G | III | D | */
+
+/* ureg <- DM (indirect addressing) */
+static void sharcop_dm_to_ureg_indirect(SHARC_REGS *cpustate)
+{
+ int ureg = (cpustate->opcode >> 32) & 0xff;
+ UINT32 offset = (UINT32)cpustate->opcode;
+ int i = (cpustate->opcode >> 41) & 0x7;
+
+ SET_UREG(cpustate, ureg, dm_read32(cpustate, DM_REG_I(i) + offset));
+}
+
+/* ureg -> DM (indirect addressing) */
+static void sharcop_ureg_to_dm_indirect(SHARC_REGS *cpustate)
+{
+ int ureg = (cpustate->opcode >> 32) & 0xff;
+ UINT32 offset = (UINT32)cpustate->opcode;
+ int i = (cpustate->opcode >> 41) & 0x7;
+
+ dm_write32(cpustate, DM_REG_I(i) + offset, GET_UREG(cpustate, ureg));
+}
+
+/* ureg <- PM (indirect addressing) */
+static void sharcop_pm_to_ureg_indirect(SHARC_REGS *cpustate)
+{
+ int ureg = (cpustate->opcode >> 32) & 0xff;
+ UINT32 offset = cpustate->opcode & 0xffffff;
+ int i = (cpustate->opcode >> 41) & 0x7;
+
+ if (ureg == 0xdb) /* PX is 48-bit */
+ {
+ cpustate->px = pm_read48(cpustate, PM_REG_I(i) + offset);
+ }
+ else
+ {
+ SET_UREG(cpustate, ureg, pm_read32(cpustate, PM_REG_I(i) + offset));
+ }
+}
+
+/* ureg -> PM (indirect addressing) */
+static void sharcop_ureg_to_pm_indirect(SHARC_REGS *cpustate)
+{
+ int ureg = (cpustate->opcode >> 32) & 0xff;
+ UINT32 offset = (UINT32)cpustate->opcode;
+ int i = (cpustate->opcode >> 41) & 0x7;
+
+ if (ureg == 0xdb) /* PX is 48-bit */
+ {
+ pm_write48(cpustate, PM_REG_I(i) + offset, cpustate->px);
+ }
+ else
+ {
+ pm_write32(cpustate, PM_REG_I(i) + offset, GET_UREG(cpustate, ureg));
+ }
+}
+
+/*****************************************************************************/
+/* | 1001xxxxx | */
+
+/* immediate data -> DM|PM */
+static void sharcop_imm_to_dmpm(SHARC_REGS *cpustate)
+{
+ int i = (cpustate->opcode >> 41) & 0x7;
+ int m = (cpustate->opcode >> 38) & 0x7;
+ int g = (cpustate->opcode >> 37) & 0x1;
+ UINT32 data = (UINT32)cpustate->opcode;
+
+ if (g)
+ {
+ /* program memory (PM) */
+ pm_write32(cpustate, PM_REG_I(i), data);
+ PM_REG_I(i) += PM_REG_M(m);
+ UPDATE_CIRCULAR_BUFFER_PM(i);
+ }
+ else
+ {
+ /* data memory (DM) */
+ dm_write32(cpustate, DM_REG_I(i), data);
+ DM_REG_I(i) += DM_REG_M(m);
+ UPDATE_CIRCULAR_BUFFER_DM(i);
+ }
+}
+
+/*****************************************************************************/
+/* | 00001111x | */
+
+/* immediate data -> ureg */
+static void sharcop_imm_to_ureg(SHARC_REGS *cpustate)
+{
+ int ureg = (cpustate->opcode >> 32) & 0xff;
+ UINT32 data = (UINT32)cpustate->opcode;
+
+ SET_UREG(cpustate, ureg, data);
+}
+
+/*****************************************************************************/
+/* | 00010100x | */
+
+/* system register bit manipulation */
+static void sharcop_sysreg_bitop(SHARC_REGS *cpustate)
+{
+ int bop = (cpustate->opcode >> 37) & 0x7;
+ int sreg = (cpustate->opcode >> 32) & 0xf;
+ UINT32 data = (UINT32)cpustate->opcode;
+
+ UINT32 src = GET_UREG(cpustate, 0x70 | sreg);
+
+ switch(bop)
+ {
+ case 0: /* SET */
+ {
+ src |= data;
+ break;
+ }
+ case 1: /* CLEAR */
+ {
+ src &= ~data;
+ break;
+ }
+ case 2: /* TOGGLE */
+ {
+ src ^= data;
+ break;
+ }
+ case 4: /* TEST */
+ {
+ if ((src & data) == data)
+ {
+ cpustate->astat |= BTF;
+ }
+ else
+ {
+ cpustate->astat &= ~BTF;
+ }
+ break;
+ }
+ case 5: /* XOR */
+ {
+ if (src == data)
+ {
+ cpustate->astat |= BTF;
+ }
+ else
+ {
+ cpustate->astat &= ~BTF;
+ }
+ break;
+ }
+ default:
+ fatalerror("SHARC: sysreg_bitop: invalid bitop %d", bop);
+ break;
+ }
+
+ SET_UREG(cpustate, 0x70 | sreg, src);
+}
+
+/*****************************************************************************/
+/* | 000101100 | */
+
+/* I register modify */
+static void sharcop_modify(SHARC_REGS *cpustate)
+{
+ int g = (cpustate->opcode >> 38) & 0x1;
+ int i = (cpustate->opcode >> 32) & 0x7;
+ INT32 data = (cpustate->opcode);
+
+ if (g) // PM
+ {
+ PM_REG_I(i) += data;
+ UPDATE_CIRCULAR_BUFFER_PM(i);
+ }
+ else // DM
+ {
+ DM_REG_I(i) += data;
+ UPDATE_CIRCULAR_BUFFER_DM(i);
+ }
+}
+
+/*****************************************************************************/
+/* | 000101101 | */
+
+/* I register bit-reverse */
+static void sharcop_bit_reverse(SHARC_REGS *cpustate)
+{
+ fatalerror("SHARC: sharcop_bit_reverse unimplemented");
+}
+
+/*****************************************************************************/
+/* | 00010111x | */
+
+/* push/pop stacks / flush cache */
+static void sharcop_push_pop_stacks(SHARC_REGS *cpustate)
+{
+ if (cpustate->opcode & U64(0x008000000000))
+ {
+ fatalerror("sharcop_push_pop_stacks: push loop not implemented");
+ }
+ if (cpustate->opcode & U64(0x004000000000))
+ {
+ fatalerror("sharcop_push_pop_stacks: pop loop not implemented");
+ }
+ if (cpustate->opcode & U64(0x002000000000))
+ {
+ //fatalerror("sharcop_push_pop_stacks: push sts not implemented");
+ PUSH_STATUS_STACK(cpustate);
+ }
+ if (cpustate->opcode & U64(0x001000000000))
+ {
+ //fatalerror("sharcop_push_pop_stacks: pop sts not implemented");
+ POP_STATUS_STACK(cpustate);
+ }
+ if (cpustate->opcode & U64(0x000800000000))
+ {
+ PUSH_PC(cpustate, cpustate->pcstk);
+ }
+ if (cpustate->opcode & U64(0x000400000000))
+ {
+ POP_PC(cpustate);
+ }
+}
+
+/*****************************************************************************/
+/* | 000000000 | */
+
+static void sharcop_nop(SHARC_REGS *cpustate)
+{
+
+}
+
+/*****************************************************************************/
+/* | 000000001 | */
+
+static void sharcop_idle(SHARC_REGS *cpustate)
+{
+ //CHANGE_PC(cpustate, cpustate->pc);
+
+ cpustate->daddr = cpustate->pc;
+ cpustate->faddr = cpustate->pc+1;
+ cpustate->nfaddr = cpustate->pc+2;
+
+ cpustate->decode_opcode = ROPCODE(cpustate->daddr);
+ cpustate->fetch_opcode = ROPCODE(cpustate->faddr);
+
+ cpustate->idle = 1;
+}
+
+/*****************************************************************************/
+
+static void sharcop_unimplemented(SHARC_REGS *cpustate)
+{
+ char dasm[1000];
+ CPU_DISASSEMBLE_NAME(sharc)(NULL, dasm, cpustate->pc, NULL, NULL, 0);
+ mame_printf_debug("SHARC: %08X: %s\n", cpustate->pc, dasm);
+ fatalerror("SHARC: Unimplemented opcode %04X%08X at %08X", (UINT16)(cpustate->opcode >> 32), (UINT32)(cpustate->opcode), cpustate->pc);
+}
diff --git a/trunk/src/emu/cpu/sharc/sharcops.h b/trunk/src/emu/cpu/sharc/sharcops.h
new file mode 100644
index 00000000000..115cfb757b9
--- /dev/null
+++ b/trunk/src/emu/cpu/sharc/sharcops.h
@@ -0,0 +1,138 @@
+typedef struct
+{
+ UINT32 op_mask;
+ UINT32 op_bits;
+ void (*handler)(SHARC_REGS *cpustate);
+} SHARC_OP;
+
+static const SHARC_OP sharc_opcode_table[] =
+{
+ // |0 0 1|
+ { 0xe000, 0x2000, sharcop_compute_dreg_dm_dreg_pm },
+
+ // |0 0 0|0 0 0 0 1|
+ { 0xff00, 0x0100, sharcop_compute },
+
+ // |0 1 0|0|
+ { 0xf000, 0x4000, sharcop_compute_ureg_dmpm_premod },
+
+ // |0 1 0|1|
+ { 0xf000, 0x5000, sharcop_compute_ureg_dmpm_postmod },
+
+ // |0 1 1|0|x x x|0|0|
+ { 0xf180, 0x6000, sharcop_compute_dm_to_dreg_immmod },
+
+ // |0 1 1|0|x x x|0|1|
+ { 0xf180, 0x6080, sharcop_compute_dreg_to_dm_immmod },
+
+ // |0 1 1|0|x x x|1|0|
+ { 0xf180, 0x6100, sharcop_compute_pm_to_dreg_immmod },
+
+ // |0 1 1|0|x x x|1|1|
+ { 0xf180, 0x6180, sharcop_compute_dreg_to_pm_immmod },
+
+ // |0 1 1|1|
+ { 0xf000, 0x7000, sharcop_compute_ureg_to_ureg },
+
+ // |1 0 0|0|
+ { 0xf000, 0x8000, sharcop_imm_shift_dreg_dmpm },
+
+ // |0 0 0|0 0 0 1 0|
+ { 0xff00, 0x0200, sharcop_imm_shift },
+
+ // |0 0 0|0 0 1 0 0|
+ { 0xff00, 0x0400, sharcop_compute_modify },
+
+ // |0 0 0|0 0 1 1 0|0|
+ { 0xff80, 0x0600, sharcop_direct_jump },
+
+ // |0 0 0|0 0 1 1 0|1|
+ { 0xff80, 0x0680, sharcop_direct_call },
+
+ // |0 0 0|0 0 1 1 1|0|
+ { 0xff80, 0x0700, sharcop_relative_jump },
+
+ // |0 0 0|0 0 1 1 1|1|
+ { 0xff80, 0x0780, sharcop_relative_call },
+
+ // |0 0 0|0 1 0 0 0|0|
+ { 0xff80, 0x0800, sharcop_indirect_jump },
+
+ // |0 0 0|0 1 0 0 0|1|
+ { 0xff80, 0x0880, sharcop_indirect_call },
+
+ // |0 0 0|0 1 0 0 1|0|
+ { 0xff80, 0x0900, sharcop_relative_jump_compute },
+
+ // |0 0 0|0 1 0 0 1|1|
+ { 0xff80, 0x0980, sharcop_relative_call_compute },
+
+ // |1 1 0|
+ { 0xe000, 0xc000, sharcop_indirect_jump_compute_dreg_dm },
+
+ // |1 1 1|
+ { 0xe000, 0xe000, sharcop_relative_jump_compute_dreg_dm },
+
+ // |0 0 0|0 1 0 1 0|
+ { 0xff00, 0x0a00, sharcop_rts },
+
+ // |0 0 0|0 1 0 1 1|
+ { 0xff00, 0x0b00, sharcop_rti },
+
+ // |0 0 0|0 1 1 0 0|
+ { 0xff00, 0x0c00, sharcop_do_until_counter_imm },
+
+ // |0 0 0|0 1 1 0 1|
+ { 0xff00, 0x0d00, sharcop_do_until_counter_ureg },
+
+ // |0 0 0|0 1 1 1 0|
+ { 0xff00, 0x0e00, sharcop_do_until },
+
+ // |0 0 0|1 0 0|0|0|
+ { 0xff00, 0x1000, sharcop_dm_to_ureg_direct },
+
+ // |0 0 0|1 0 0|0|1|
+ { 0xff00, 0x1100, sharcop_ureg_to_dm_direct },
+
+ // |0 0 0|1 0 0|1|0|
+ { 0xff00, 0x1200, sharcop_pm_to_ureg_direct },
+
+ // |0 0 0|1 0 0|1|1|
+ { 0xff00, 0x1300, sharcop_ureg_to_pm_direct },
+
+ // |1 0 1|0|x x x|0|
+ { 0xf100, 0xa000, sharcop_dm_to_ureg_indirect },
+
+ // |1 0 1|0|x x x|1|
+ { 0xf100, 0xa100, sharcop_ureg_to_dm_indirect },
+
+ // |1 0 1|1|x x x|0|
+ { 0xf100, 0xb000, sharcop_pm_to_ureg_indirect },
+
+ // |1 0 1|1|x x x|1|
+ { 0xf100, 0xb100, sharcop_ureg_to_pm_indirect },
+
+ // |1 0 0|1|
+ { 0xf000, 0x9000, sharcop_imm_to_dmpm },
+
+ // |0 0 0|0 1 1 1 1|
+ { 0xff00, 0x0f00, sharcop_imm_to_ureg },
+
+ // |0 0 0|1 0 1 0 0|
+ { 0xff00, 0x1400, sharcop_sysreg_bitop },
+
+ // |0 0 0|1 0 1 1 0|0|
+ { 0xff80, 0x1600, sharcop_modify },
+
+ // |0 0 0|1 0 1 1 0|1|
+ { 0xff80, 0x1680, sharcop_bit_reverse },
+
+ // |0 0 0|1 0 1 1 1|
+ { 0xff00, 0x1700, sharcop_push_pop_stacks },
+
+ // |0 0 0|0 0 0 0 0|0|
+ { 0xff80, 0x0000, sharcop_nop },
+
+ // |0 0 0|0 0 0 0 0|1|
+ { 0xff80, 0x0080, sharcop_idle },
+};
diff --git a/trunk/src/emu/cpu/sm8500/sm8500.c b/trunk/src/emu/cpu/sm8500/sm8500.c
new file mode 100644
index 00000000000..6ebe381ae82
--- /dev/null
+++ b/trunk/src/emu/cpu/sm8500/sm8500.c
@@ -0,0 +1,601 @@
+/*
+ Implementation for Sharp sm8500 cpu. There is hardly any information available
+ on this cpu. Currently we've only found documentation on the microcontroller
+ parts of the cpu, but nothing on the cpu itself.
+
+ Through looking at binary data we have attempted to figure out the opcodes for
+ this cpu, and made educated guesses on the number of cycles for each instruction.
+
+ Code by Wilbert Pol
+
+
+There is some internal ram for the main cpu registers. They are offset by an index value.
+The address is (PS0 & 0xF8) + register number. It is not known what happens when PS0 >= F8.
+The assumption is that F8 to 107 is used, but it might wrap around instead.
+The registers also mirror out to main RAM, appearing at 0000 to 000F regardless of where
+they are internally.
+
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "sm8500.h"
+
+#define FLAG_C 0x80
+#define FLAG_Z 0x40
+#define FLAG_S 0x20
+#define FLAG_V 0x10
+#define FLAG_D 0x08
+#define FLAG_H 0x04
+#define FLAG_B 0x02
+#define FLAG_I 0x01
+
+typedef struct _sm8500_state sm8500_state;
+struct _sm8500_state
+{
+ SM8500_CONFIG config;
+ UINT16 PC;
+ UINT8 IE0;
+ UINT8 IE1;
+ UINT8 IR0;
+ UINT8 IR1;
+ UINT8 SYS;
+ UINT8 CKC;
+ UINT8 clock_changed;
+ UINT16 SP;
+ UINT8 PS0;
+ UINT8 PS1;
+ UINT16 IFLAGS;
+ UINT8 CheckInterrupts;
+ int halted;
+ int icount;
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ UINT16 oldpc;
+ UINT8 register_ram[0x108];
+};
+
+INLINE sm8500_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == SM8500);
+ return (sm8500_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+static const UINT8 sm8500_b2w[8] = {
+ 0, 8, 2, 10, 4, 12, 6, 14
+};
+
+INLINE void sm8500_get_sp( sm8500_state *cpustate )
+{
+ UINT16 data = cpustate->program->read_byte(0x1c) << 8;
+ cpustate->SP = cpustate->program->read_byte(0x1d);
+ if (cpustate->SYS&0x40) cpustate->SP |= data;
+}
+
+static UINT8 sm85cpu_mem_readbyte( sm8500_state *cpustate, UINT32 offset )
+{
+ offset &= 0xffff;
+ return (offset < 0x10) ? cpustate->register_ram[offset + (cpustate->PS0 & 0xF8)]
+ : cpustate->program->read_byte( offset );
+}
+
+static void sm85cpu_mem_writebyte( sm8500_state *cpustate, UINT32 offset, UINT8 data )
+{
+ UINT8 i;
+ offset &= 0xffff;
+ if (offset < 0x10)
+ cpustate->register_ram[offset + (cpustate->PS0 & 0xF8)] = data;
+
+ cpustate->program->write_byte ( offset, data );
+
+ switch (offset)
+ {
+ case 0x10: cpustate->IE0 = data; break;
+ case 0x11: cpustate->IE1 = data; break;
+ case 0x12: cpustate->IR0 = data; break;
+ case 0x13: cpustate->IR1 = data; break;
+ case 0x19: cpustate->SYS = data; break;
+ case 0x1a: cpustate->CKC = data; break;
+ case 0x1c:
+ case 0x1d: sm8500_get_sp(cpustate); break;
+ case 0x1e: cpustate->PS0 = data;
+ for (i = 0; i < 16; i++) // refresh register contents in debugger
+ cpustate->program->write_byte(i, sm85cpu_mem_readbyte(cpustate, i)); break;
+ case 0x1f: cpustate->PS1 = data; break;
+ }
+}
+
+
+INLINE UINT16 sm85cpu_mem_readword( sm8500_state *cpustate, UINT32 address )
+{
+ return (sm85cpu_mem_readbyte( cpustate, address ) << 8) | (sm85cpu_mem_readbyte( cpustate, address+1 ));
+}
+
+INLINE void sm85cpu_mem_writeword( sm8500_state *cpustate, UINT32 address, UINT16 value )
+{
+ sm85cpu_mem_writebyte( cpustate, address, value >> 8 );
+ sm85cpu_mem_writebyte( cpustate, address+1, value );
+}
+
+static CPU_INIT( sm8500 )
+{
+ sm8500_state *cpustate = get_safe_token(device);
+
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ if ( device->static_config() != NULL ) {
+ cpustate->config.handle_dma = ((SM8500_CONFIG *)device->static_config())->handle_dma;
+ cpustate->config.handle_timers = ((SM8500_CONFIG *)device->static_config())->handle_timers;
+ } else {
+ cpustate->config.handle_dma = NULL;
+ cpustate->config.handle_timers = NULL;
+ }
+}
+
+static CPU_RESET( sm8500 )
+{
+ sm8500_state *cpustate = get_safe_token(device);
+
+ cpustate->PC = 0x1020;
+ cpustate->clock_changed = 0;
+ cpustate->halted = 0;
+ sm85cpu_mem_writeword(cpustate, 0x10, 0); // IE0, IE1
+ sm85cpu_mem_writeword(cpustate, 0x12, 0); // IR0, IR1
+ sm85cpu_mem_writeword(cpustate, 0x14, 0xffff); // P0, P1
+ sm85cpu_mem_writeword(cpustate, 0x16, 0xff00); // P2, P3
+ sm85cpu_mem_writebyte(cpustate, 0x19, 0); // SYS
+ sm85cpu_mem_writebyte(cpustate, 0x1a, 0); // CKC
+ sm85cpu_mem_writebyte(cpustate, 0x1f, 0); // PS1
+ sm85cpu_mem_writebyte(cpustate, 0x2b, 0xff); // URTT
+ sm85cpu_mem_writebyte(cpustate, 0x2d, 0x42); // URTS
+ sm85cpu_mem_writebyte(cpustate, 0x5f, 0x38); // WDTC
+}
+
+static CPU_EXIT( sm8500 )
+{
+}
+
+#define PUSH_BYTE(X) cpustate->SP--; \
+ if ( ( cpustate->SYS & 0x40 ) == 0 ) cpustate->SP &= 0xFF; \
+ sm85cpu_mem_writebyte( cpustate, cpustate->SP, X );
+
+INLINE void sm8500_do_interrupt(sm8500_state *cpustate, UINT16 vector) {
+ /* Get regs from ram */
+ sm8500_get_sp(cpustate);
+ cpustate->SYS = cpustate->program->read_byte(0x19);
+ cpustate->PS1 = cpustate->program->read_byte(0x1f);
+ /* Push PC */
+ PUSH_BYTE( cpustate->PC & 0xFF );
+ PUSH_BYTE( cpustate->PC >> 8 );
+ /* Push PS1 */
+ PUSH_BYTE( cpustate->PS1 );
+ /* Clear I flag */
+ cpustate->PS1 &= ~ 0x01;
+ /* save regs to ram */
+ cpustate->program->write_byte (0x1f, cpustate->PS1);
+ cpustate->program->write_byte (0x1d, cpustate->SP&0xFF);
+ if (cpustate->SYS&0x40) cpustate->program->write_byte(0x1c, cpustate->SP>>8);
+ /* Change PC to address stored at "vector" */
+ cpustate->PC = sm85cpu_mem_readword( cpustate, vector );
+}
+
+INLINE void sm8500_process_interrupts(sm8500_state *cpustate) {
+ if ( cpustate->CheckInterrupts ) {
+ int irqline = 0;
+ while( irqline < 11 ) {
+ if ( cpustate->IFLAGS & ( 1 << irqline ) ) {
+ cpustate->halted = 0;
+ cpustate->IE0 = cpustate->program->read_byte(0x10);
+ cpustate->IE1 = cpustate->program->read_byte(0x11);
+ cpustate->IR0 = cpustate->program->read_byte(0x12);
+ cpustate->IR1 = cpustate->program->read_byte(0x13);
+ cpustate->PS0 = cpustate->program->read_byte(0x1e);
+ cpustate->PS1 = cpustate->program->read_byte(0x1f);
+ switch( irqline ) {
+ case WDT_INT:
+ sm8500_do_interrupt( cpustate, 0x101C );
+ break;
+ case ILL_INT:
+ case NMI_INT:
+ sm8500_do_interrupt( cpustate, 0x101E );
+ break;
+ case DMA_INT:
+ cpustate->IR0 |= 0x80;
+ if ( ( cpustate->IE0 & 0x80 ) && ( ( cpustate->PS0 & 0x07 ) < 8 ) && ( cpustate->PS1 & 0x01 ) ) {
+ sm8500_do_interrupt( cpustate, 0x1000 );
+ }
+ break;
+ case TIM0_INT:
+ cpustate->IR0 |= 0x40;
+ if ( ( cpustate->IE0 & 0x40 ) && ( ( cpustate->PS0 & 0x07 ) < 8 ) && ( cpustate->PS1 & 0x01 ) ) {
+ sm8500_do_interrupt( cpustate, 0x1002 );
+ }
+ break;
+ case EXT_INT:
+ cpustate->IR0 |= 0x10;
+ if ( ( cpustate->IE0 & 0x10 ) && ( ( cpustate->PS0 & 0x07 ) < 7 ) && ( cpustate->PS1 & 0x01 ) ) {
+ sm8500_do_interrupt( cpustate, 0x1006 );
+ }
+ break;
+ case UART_INT:
+ cpustate->IR0 |= 0x08;
+ if ( ( cpustate->IE0 & 0x08 ) && ( ( cpustate->PS0 & 0x07 ) < 6 ) && ( cpustate->PS1 & 0x01 ) ) {
+ sm8500_do_interrupt( cpustate, 0x1008 );
+ }
+ break;
+ case LCDC_INT:
+ cpustate->IR0 |= 0x01;
+ if ( ( cpustate->IE0 & 0x01 ) && ( ( cpustate->PS0 & 0x07 ) < 5 ) && ( cpustate->PS1 & 0x01 ) ) {
+ sm8500_do_interrupt( cpustate, 0x100E );
+ }
+ break;
+ case TIM1_INT:
+ cpustate->IR1 |= 0x40;
+ if ( ( cpustate->IE1 & 0x40 ) && ( ( cpustate->PS0 & 0x07 ) < 4 ) && ( cpustate->PS1 & 0x01 ) ) {
+ sm8500_do_interrupt( cpustate, 0x1012 );
+ }
+ break;
+ case CK_INT:
+ cpustate->IR1 |= 0x10;
+ if ( ( cpustate->IE1 & 0x10 ) && ( ( cpustate->PS0 & 0x07 ) < 3 ) && ( cpustate->PS1 & 0x01 ) ) {
+ sm8500_do_interrupt( cpustate, 0x1016 );
+ }
+ break;
+ case PIO_INT:
+ cpustate->IR1 |= 0x04;
+ if ( ( cpustate->IE1 & 0x04 ) && ( ( cpustate->PS0 & 0x07 ) < 2 ) && ( cpustate->PS1 & 0x01 ) ) {
+ sm8500_do_interrupt( cpustate, 0x101A );
+ }
+ break;
+ }
+ cpustate->IFLAGS &= ~ ( 1 << irqline );
+ cpustate->program->write_byte(0x12, cpustate->IR0);
+ cpustate->program->write_byte(0x13, cpustate->IR1);
+ }
+ irqline++;
+ }
+ }
+}
+
+static CPU_EXECUTE( sm8500 )
+{
+ sm8500_state *cpustate = get_safe_token(device);
+ UINT8 op;
+ int mycycles;
+
+ do
+ {
+ UINT8 r1,r2;
+ UINT16 s1,s2;
+ UINT32 d1,d2;
+ UINT32 res;
+
+ debugger_instruction_hook(device, cpustate->PC);
+ cpustate->oldpc = cpustate->PC;
+ mycycles = 0;
+ sm8500_process_interrupts(cpustate);
+ if ( !cpustate->halted ) {
+ op = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ );
+ cpustate->SYS = cpustate->program->read_byte(0x19);
+ cpustate->PS0 = cpustate->program->read_byte(0x1e);
+ cpustate->PS1 = cpustate->program->read_byte(0x1f);
+ sm8500_get_sp(cpustate);
+ switch( op )
+ {
+#include "sm85ops.h"
+ }
+ if (cpustate->SYS&0x40) cpustate->program->write_byte(0x1c,cpustate->SP>>8);
+ cpustate->program->write_byte(0x1d,cpustate->SP&0xFF);
+ sm85cpu_mem_writebyte(cpustate,0x1e,cpustate->PS0); // need to update debugger
+ cpustate->program->write_byte(0x1f,cpustate->PS1);
+ } else {
+ mycycles = 4;
+ if ( cpustate->config.handle_dma ) {
+ cpustate->config.handle_dma( device, mycycles );
+ }
+ }
+ if ( cpustate->config.handle_timers ) {
+ cpustate->config.handle_timers( device, mycycles );
+ }
+ cpustate->icount -= mycycles;
+ } while ( cpustate->icount > 0 );
+}
+
+static CPU_BURN( sm8500 )
+{
+ sm8500_state *cpustate = get_safe_token(device);
+
+ if ( cycles > 0 ) {
+ /* burn a number of 4 cycles */
+ int n = ( cycles + 3 ) / 4;
+ cpustate->icount -= 4 * n;
+ }
+}
+
+static unsigned sm8500_get_reg( sm8500_state *cpustate, int regnum )
+{
+ switch( regnum )
+ {
+ case STATE_GENPC:
+ case SM8500_PC: return cpustate->PC;
+ case STATE_GENSP:
+ case SM8500_SP: return cpustate->SP;
+ case SM8500_PS: return sm85cpu_mem_readword( cpustate, 0x1e );
+ case SM8500_SYS16: return cpustate->SYS;
+ case SM8500_RR0: return sm85cpu_mem_readword( cpustate, 0x00 );
+ case SM8500_RR2: return sm85cpu_mem_readword( cpustate, 0x02 );
+ case SM8500_RR4: return sm85cpu_mem_readword( cpustate, 0x04 );
+ case SM8500_RR6: return sm85cpu_mem_readword( cpustate, 0x06 );
+ case SM8500_RR8: return sm85cpu_mem_readword( cpustate, 0x08 );
+ case SM8500_RR10: return sm85cpu_mem_readword( cpustate, 0x0A );
+ case SM8500_RR12: return sm85cpu_mem_readword( cpustate, 0x0C );
+ case SM8500_RR14: return sm85cpu_mem_readword( cpustate, 0x0E );
+ case SM8500_IE0: return sm85cpu_mem_readbyte( cpustate, 0x10 );
+ case SM8500_IE1: return sm85cpu_mem_readbyte( cpustate, 0x11 );
+ case SM8500_IR0: return sm85cpu_mem_readbyte( cpustate, 0x12 );
+ case SM8500_IR1: return sm85cpu_mem_readbyte( cpustate, 0x13 );
+ case SM8500_P0: return sm85cpu_mem_readbyte( cpustate, 0x14 );
+ case SM8500_P1: return sm85cpu_mem_readbyte( cpustate, 0x15 );
+ case SM8500_P2: return sm85cpu_mem_readbyte( cpustate, 0x16 );
+ case SM8500_P3: return sm85cpu_mem_readbyte( cpustate, 0x17 );
+ case SM8500_SYS: return sm85cpu_mem_readbyte( cpustate, 0x19 );
+ case SM8500_CKC: return sm85cpu_mem_readbyte( cpustate, 0x1a );
+ case SM8500_SPH: return sm85cpu_mem_readbyte( cpustate, 0x1c );
+ case SM8500_SPL: return sm85cpu_mem_readbyte( cpustate, 0x1d );
+ case SM8500_PS0: return sm85cpu_mem_readbyte( cpustate, 0x1e );
+ case SM8500_PS1: return sm85cpu_mem_readbyte( cpustate, 0x1f );
+ case SM8500_P0C: return sm85cpu_mem_readbyte( cpustate, 0x20 );
+ case SM8500_P1C: return sm85cpu_mem_readbyte( cpustate, 0x21 );
+ case SM8500_P2C: return sm85cpu_mem_readbyte( cpustate, 0x22 );
+ case SM8500_P3C: return sm85cpu_mem_readbyte( cpustate, 0x23 );
+ }
+ return 0;
+}
+
+static void sm8500_set_reg( sm8500_state *cpustate, int regnum, unsigned val )
+{
+ switch( regnum )
+ {
+ case STATE_GENPC:
+ case SM8500_PC: cpustate->PC = val; break;
+ case STATE_GENSP:
+ case SM8500_SP: cpustate->SP = val; cpustate->program->write_byte(0x1d, val&0xff); if (cpustate->SYS&0x40) cpustate->program->write_byte(0x1c, val>>8); break;
+ case SM8500_PS: sm85cpu_mem_writeword( cpustate, 0x1e, val); break;
+ case SM8500_SYS16: val&=0xff; sm85cpu_mem_writebyte( cpustate, 0x19, val); break;
+ case SM8500_RR0: sm85cpu_mem_writeword( cpustate, 0x00, val); break;
+ case SM8500_RR2: sm85cpu_mem_writeword( cpustate, 0x02, val); break;
+ case SM8500_RR4: sm85cpu_mem_writeword( cpustate, 0x04, val); break;
+ case SM8500_RR6: sm85cpu_mem_writeword( cpustate, 0x06, val); break;
+ case SM8500_RR8: sm85cpu_mem_writeword( cpustate, 0x08, val); break;
+ case SM8500_RR10: sm85cpu_mem_writeword( cpustate, 0x0A, val); break;
+ case SM8500_RR12: sm85cpu_mem_writeword( cpustate, 0x0C, val); break;
+ case SM8500_RR14: sm85cpu_mem_writeword( cpustate, 0x0E, val); break;
+ case SM8500_IE0: sm85cpu_mem_writebyte( cpustate, 0x10, val); break;
+ case SM8500_IE1: sm85cpu_mem_writebyte( cpustate, 0x11, val); break;
+ case SM8500_IR0: sm85cpu_mem_writebyte( cpustate, 0x12, val); break;
+ case SM8500_IR1: sm85cpu_mem_writebyte( cpustate, 0x13, val); break;
+ case SM8500_P0: sm85cpu_mem_writebyte( cpustate, 0x14, val); break;
+ case SM8500_P1: sm85cpu_mem_writebyte( cpustate, 0x15, val); break;
+ case SM8500_P2: sm85cpu_mem_writebyte( cpustate, 0x16, val); break;
+ case SM8500_P3: sm85cpu_mem_writebyte( cpustate, 0x17, val); break;
+ case SM8500_SYS: sm85cpu_mem_writebyte( cpustate, 0x19, val); break;
+ case SM8500_CKC: sm85cpu_mem_writebyte( cpustate, 0x1a, val); if ( val & 0x80 ) { cpustate->clock_changed = 1; }; break;
+ case SM8500_SPH: sm85cpu_mem_writebyte( cpustate, 0x1c, val); break;
+ case SM8500_SPL: sm85cpu_mem_writebyte( cpustate, 0x1d, val); break;
+ case SM8500_PS0: sm85cpu_mem_writebyte( cpustate, 0x1e, val); break;
+ case SM8500_PS1: sm85cpu_mem_writebyte( cpustate, 0x1f, val); break;
+ case SM8500_P0C: sm85cpu_mem_writebyte( cpustate, 0x20, val); break;
+ case SM8500_P1C: sm85cpu_mem_writebyte( cpustate, 0x21, val); break;
+ case SM8500_P2C: sm85cpu_mem_writebyte( cpustate, 0x22, val); break;
+ case SM8500_P3C: sm85cpu_mem_writebyte( cpustate, 0x23, val); break;
+ }
+}
+
+static void sm8500_set_irq_line( sm8500_state *cpustate, int irqline, int state )
+{
+ cpustate->IR0 = cpustate->program->read_byte(0x12);
+ cpustate->IR1 = cpustate->program->read_byte(0x13);
+ if ( state == ASSERT_LINE ) {
+ cpustate->IFLAGS |= ( 0x01 << irqline );
+ cpustate->CheckInterrupts = 1;
+ switch( irqline ) {
+ case DMA_INT: cpustate->IR0 |= 0x80; break;
+ case TIM0_INT: cpustate->IR0 |= 0x40; break;
+ case EXT_INT: cpustate->IR0 |= 0x10; break;
+ case UART_INT: cpustate->IR0 |= 0x08; break;
+ case LCDC_INT: cpustate->IR0 |= 0x01; break;
+ case TIM1_INT: cpustate->IR1 |= 0x40; break;
+ case CK_INT: cpustate->IR1 |= 0x10; break;
+ case PIO_INT: cpustate->IR1 |= 0x04; break;
+ }
+ } else {
+ cpustate->IFLAGS &= ~( 0x01 << irqline );
+ switch( irqline ) {
+ case DMA_INT: cpustate->IR0 &= ~0x80; break;
+ case TIM0_INT: cpustate->IR0 &= ~0x40; break;
+ case EXT_INT: cpustate->IR0 &= ~0x10; break;
+ case UART_INT: cpustate->IR0 &= ~0x08; break;
+ case LCDC_INT: cpustate->IR0 &= ~0x01; break;
+ case TIM1_INT: cpustate->IR1 &= ~0x40; break;
+ case CK_INT: cpustate->IR1 &= ~0x10; break;
+ case PIO_INT: cpustate->IR1 &= ~0x04; break;
+ }
+ if ( 0 == cpustate->IFLAGS ) {
+ cpustate->CheckInterrupts = 0;
+ }
+ }
+ cpustate->program->write_byte(0x12, cpustate->IR0);
+ cpustate->program->write_byte(0x13, cpustate->IR1);
+}
+
+static CPU_SET_INFO( sm8500 )
+{
+ sm8500_state *cpustate = get_safe_token(device);
+
+ switch(state)
+ {
+ 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:
+ sm8500_set_irq_line( cpustate, state - CPUINFO_INT_INPUT_STATE, info->i ); break;
+
+ case CPUINFO_INT_REGISTER + SM8500_RR0:
+ case CPUINFO_INT_REGISTER + SM8500_RR2:
+ case CPUINFO_INT_REGISTER + SM8500_RR4:
+ case CPUINFO_INT_REGISTER + SM8500_RR6:
+ case CPUINFO_INT_REGISTER + SM8500_RR8:
+ case CPUINFO_INT_REGISTER + SM8500_RR10:
+ case CPUINFO_INT_REGISTER + SM8500_RR12:
+ case CPUINFO_INT_REGISTER + SM8500_RR14:
+ case CPUINFO_INT_REGISTER + SM8500_PC:
+ case CPUINFO_INT_REGISTER + SM8500_SP:
+ case CPUINFO_INT_REGISTER + SM8500_PS:
+ case CPUINFO_INT_REGISTER + SM8500_SYS16:
+ case CPUINFO_INT_REGISTER + SM8500_SYS:
+ case CPUINFO_INT_REGISTER + SM8500_IE0:
+ case CPUINFO_INT_REGISTER + SM8500_IE1:
+ case CPUINFO_INT_REGISTER + SM8500_IR0:
+ case CPUINFO_INT_REGISTER + SM8500_IR1:
+ case CPUINFO_INT_REGISTER + SM8500_P0:
+ case CPUINFO_INT_REGISTER + SM8500_P1:
+ case CPUINFO_INT_REGISTER + SM8500_P2:
+ case CPUINFO_INT_REGISTER + SM8500_P3:
+ case CPUINFO_INT_REGISTER + SM8500_CKC:
+ case CPUINFO_INT_REGISTER + SM8500_SPH:
+ case CPUINFO_INT_REGISTER + SM8500_SPL:
+ case CPUINFO_INT_REGISTER + SM8500_PS0:
+ case CPUINFO_INT_REGISTER + SM8500_PS1:
+ case CPUINFO_INT_REGISTER + SM8500_P0C:
+ case CPUINFO_INT_REGISTER + SM8500_P1C:
+ case CPUINFO_INT_REGISTER + SM8500_P2C:
+ case CPUINFO_INT_REGISTER + SM8500_P3C:
+ sm8500_set_reg( cpustate, state - CPUINFO_INT_REGISTER, info->i ); break;
+
+ }
+}
+
+CPU_GET_INFO( sm8500 )
+{
+ sm8500_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch(state)
+ {
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(sm8500_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 8; 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 = 5; 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 = 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 + 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: info->i = cpustate->IFLAGS & ( 1 << (state - CPUINFO_INT_INPUT_STATE)); break;
+ case CPUINFO_INT_REGISTER + SM8500_RR0:
+ case CPUINFO_INT_REGISTER + SM8500_RR2:
+ case CPUINFO_INT_REGISTER + SM8500_RR4:
+ case CPUINFO_INT_REGISTER + SM8500_RR6:
+ case CPUINFO_INT_REGISTER + SM8500_RR8:
+ case CPUINFO_INT_REGISTER + SM8500_RR10:
+ case CPUINFO_INT_REGISTER + SM8500_RR12:
+ case CPUINFO_INT_REGISTER + SM8500_RR14:
+ case CPUINFO_INT_REGISTER + SM8500_PC:
+ case CPUINFO_INT_REGISTER + SM8500_SP:
+ case CPUINFO_INT_REGISTER + SM8500_PS:
+ case CPUINFO_INT_REGISTER + SM8500_SYS16:
+ case CPUINFO_INT_REGISTER + SM8500_SYS:
+ case CPUINFO_INT_REGISTER + SM8500_IE0:
+ case CPUINFO_INT_REGISTER + SM8500_IE1:
+ case CPUINFO_INT_REGISTER + SM8500_IR0:
+ case CPUINFO_INT_REGISTER + SM8500_IR1:
+ case CPUINFO_INT_REGISTER + SM8500_P0:
+ case CPUINFO_INT_REGISTER + SM8500_P1:
+ case CPUINFO_INT_REGISTER + SM8500_P2:
+ case CPUINFO_INT_REGISTER + SM8500_P3:
+ case CPUINFO_INT_REGISTER + SM8500_CKC:
+ case CPUINFO_INT_REGISTER + SM8500_SPH:
+ case CPUINFO_INT_REGISTER + SM8500_SPL:
+ case CPUINFO_INT_REGISTER + SM8500_PS0:
+ case CPUINFO_INT_REGISTER + SM8500_PS1:
+ case CPUINFO_INT_REGISTER + SM8500_P0C:
+ case CPUINFO_INT_REGISTER + SM8500_P1C:
+ case CPUINFO_INT_REGISTER + SM8500_P2C:
+ case CPUINFO_INT_REGISTER + SM8500_P3C:
+ info->i = sm8500_get_reg( cpustate, state - CPUINFO_INT_REGISTER ); break;
+ case CPUINFO_INT_REGISTER + STATE_GENPC: info->i = sm8500_get_reg( cpustate, SM8500_PC ); break;
+ case CPUINFO_INT_REGISTER + STATE_GENSP: info->i = sm8500_get_reg( cpustate, SM8500_SP ); break;
+ case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->oldpc; break;
+
+
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(sm8500); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(sm8500); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(sm8500); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(sm8500); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(sm8500); break;
+ case CPUINFO_FCT_BURN: info->burn = CPU_BURN_NAME(sm8500); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(sm8500); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ case DEVINFO_STR_NAME: strcpy( info->s, "sm8500" ); break;
+ case DEVINFO_STR_FAMILY: strcpy( info->s, "Sharp SM8500" ); 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",
+ cpustate->PS1 & FLAG_C ? 'C' : '.',
+ cpustate->PS1 & FLAG_Z ? 'Z' : '.',
+ cpustate->PS1 & FLAG_S ? 'S' : '.',
+ cpustate->PS1 & FLAG_V ? 'V' : '.',
+ cpustate->PS1 & FLAG_D ? 'D' : '.',
+ cpustate->PS1 & FLAG_H ? 'H' : '.',
+ cpustate->PS1 & FLAG_B ? 'B' : '.',
+ cpustate->PS1 & FLAG_I ? 'I' : '.' );
+ break;
+ case CPUINFO_STR_REGISTER + SM8500_RR0: sprintf(info->s, "RR0:%04X", sm85cpu_mem_readword( cpustate, 0x00 ) ); break;
+ case CPUINFO_STR_REGISTER + SM8500_RR2: sprintf(info->s, "RR2:%04X", sm85cpu_mem_readword( cpustate, 0x02 ) ); break;
+ case CPUINFO_STR_REGISTER + SM8500_RR4: sprintf(info->s, "RR4:%04X", sm85cpu_mem_readword( cpustate, 0x04 ) ); break;
+ case CPUINFO_STR_REGISTER + SM8500_RR6: sprintf(info->s, "RR6:%04X", sm85cpu_mem_readword( cpustate, 0x06 ) ); break;
+ case CPUINFO_STR_REGISTER + SM8500_RR8: sprintf(info->s, "RR8:%04X", sm85cpu_mem_readword( cpustate, 0x08 ) ); break;
+ case CPUINFO_STR_REGISTER + SM8500_RR10: sprintf(info->s, "RR10:%04X", sm85cpu_mem_readword( cpustate, 0x0A ) ); break;
+ case CPUINFO_STR_REGISTER + SM8500_RR12: sprintf(info->s, "RR12:%04X", sm85cpu_mem_readword( cpustate, 0x0C ) ); break;
+ case CPUINFO_STR_REGISTER + SM8500_RR14: sprintf(info->s, "RR14:%04X", sm85cpu_mem_readword( cpustate, 0x0E ) ); break;
+ case CPUINFO_STR_REGISTER + SM8500_PC: sprintf(info->s, "PC:%04X", cpustate->PC); break;
+ case CPUINFO_STR_REGISTER + SM8500_SP: sprintf(info->s, "SP:%04X", cpustate->SP); break;
+ case CPUINFO_STR_REGISTER + SM8500_PS: sprintf(info->s, "PS:%04X", ( cpustate->PS0 << 8 ) | cpustate->PS1 ); break;
+ case CPUINFO_STR_REGISTER + SM8500_SYS16: sprintf(info->s, "SYS:%02X", cpustate->SYS ); break;
+ }
+}
+
+
+DEFINE_LEGACY_CPU_DEVICE(SM8500, sm8500);
diff --git a/trunk/src/emu/cpu/sm8500/sm8500.h b/trunk/src/emu/cpu/sm8500/sm8500.h
new file mode 100644
index 00000000000..7e942b6b68f
--- /dev/null
+++ b/trunk/src/emu/cpu/sm8500/sm8500.h
@@ -0,0 +1,39 @@
+#pragma once
+
+#ifndef __SM8500_H__
+#define __SM8500_H__
+
+
+typedef struct {
+ void (*handle_dma)(device_t *device, int cycles);
+ void (*handle_timers)(device_t *device, int cycles);
+} SM8500_CONFIG;
+
+/* interrupts */
+#define ILL_INT 0
+#define DMA_INT 1
+#define TIM0_INT 2
+#define EXT_INT 3
+#define UART_INT 4
+#define LCDC_INT 5
+#define TIM1_INT 6
+#define CK_INT 7
+#define PIO_INT 8
+#define WDT_INT 9
+#define NMI_INT 10
+
+enum
+{
+ /* "main" 16 bit register */
+ SM8500_PC=1, SM8500_SP, SM8500_PS, SM8500_SYS16, SM8500_RR0, SM8500_RR2, SM8500_RR4, SM8500_RR6, SM8500_RR8, SM8500_RR10,
+ SM8500_RR12, SM8500_RR14,
+ /* additional internal 8 bit registers */
+ SM8500_IE0, SM8500_IE1, SM8500_IR0, SM8500_IR1, SM8500_P0, SM8500_P1, SM8500_P2, SM8500_P3, SM8500_SYS, SM8500_CKC,
+ SM8500_SPH, SM8500_SPL, SM8500_PS0, SM8500_PS1, SM8500_P0C, SM8500_P1C, SM8500_P2C, SM8500_P3C,
+};
+
+DECLARE_LEGACY_CPU_DEVICE(SM8500, sm8500);
+
+extern CPU_DISASSEMBLE( sm8500 );
+
+#endif /* __SM8500_H__ */
diff --git a/trunk/src/emu/cpu/sm8500/sm8500d.c b/trunk/src/emu/cpu/sm8500/sm8500d.c
new file mode 100644
index 00000000000..7ea4eb3fa58
--- /dev/null
+++ b/trunk/src/emu/cpu/sm8500/sm8500d.c
@@ -0,0 +1,582 @@
+/*******************************************************************
+
+sm8500d.c
+Sharp sm8500 CPU disassembly
+
+
+
+*******************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "sm8500.h"
+
+enum e_mnemonics
+{
+ zADC=0, zADCW, zADD, zADDW, zAND, zANDW, zBAND, zBBC, zBBS,
+ zBCLR, zBCMP, zBMOV, zBOR, zBR, zBTST, zBSET, zBXOR, zCALL, zCALS, zCLR,
+ zCLRC, zCMP, zCMPW, zCOM, zCOMC, zDA, zDBNZ, zDEC,
+ zDECW, zDI, zDIV, zEI, zEXTS, zHALT, zINC, zINCW,
+ zIRET, zJMP, zMOV, zMOVM, zMOVW, zMULT, zNEG, zNOP, zOR,
+ zORW, zPOP, zPOPW, zPUSH, zPUSHW, zRET, zRL, zRLC,
+ zRR, zRRC, zSBC, zSBCW, zSETC, zSLL, zSRA, zSRL, zSTOP,
+ zSUB, zSUBW, zSWAP, zXOR, zXORW, zMOVPS0, zINVLD, zDM,
+/* unknowns */
+z5A, z5B,
+
+/* more complicated instructions */
+z1A, z1B, z4F,
+};
+
+/* instructions not found:
+5A, 5B,
+*/
+
+static const char *const s_mnemonic[] =
+{
+ "adc", "adcw", "add", "addw", "and", "andw", "band", "bbc", "bbs",
+ "bclr", "bcmp", "bmov", "bor", "br", "btst", "bset", "bxor", "call", "cals", "clr",
+ "clrc", "cmp", "cmpw", "com", "comc", "da", "dbnz", "dec",
+ "decw", "di", "div", "ei", "exts", "halt", "inc", "incw",
+ "iret", "jmp", "mov", "movm", "movw", "mult", "neg", "nop", "or",
+ "orw", "pop", "popw", "push", "pushw", "ret", "rl", "rlc",
+ "rr", "rrc", "sbc", "sbcw", "setc", "sll", "sra", "srl", "stop",
+ "sub", "subw", "swap", "xor", "xorw", "mov PS0,", "invalid", "dm?",
+/* unknowns */
+"unk5A", "unk5B",
+
+/* more complicated instructions */
+"comp1A", "comp1B", "comp4F",
+};
+
+#define _OVER DASMFLAG_STEP_OVER
+#define _OUT DASMFLAG_STEP_OUT
+
+static const UINT32 s_flags[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, _OVER, _OVER, 0,
+ 0, 0, 0, 0, 0, 0, _OVER, 0,
+ 0, 0, 0, 0, 0, _OVER, 0, 0,
+ _OUT, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, _OUT, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,
+ 0, 0, 0
+};
+
+typedef struct
+{
+ UINT8 mnemonic;
+ UINT8 arguments;
+} sm8500dasm;
+
+static const char *const sm8500_cond[16] = {
+ "F", "LT", "LE", "ULE", "OV", "MI", "Z", "C",
+ "T", "GE", "GT", "UGT", "NOV", "PL", "NZ", "NC"
+};
+
+static const UINT8 sm8500_b2w[8] = {
+ 0, 8, 2, 10, 4, 12, 6, 14
+};
+
+enum e_addrmodes {
+ AM_R=1, AM_rr, AM_r1, AM_S, AM_rmb, AM_mbr, AM_Ri, AM_rmw, AM_mwr, AM_smw, AM_mws,
+ AM_Sw, AM_iR, AM_rbr, AM_riw, AM_cjp, AM_rib, AM_pi, AM_cbr, AM_i, AM_ii,
+ AM_ss, AM_RR, AM_2, AM_SS, AM_bR, AM_Rbr, AM_Rb, AM_rR, AM_Rr, AM_Rii, AM_RiR,
+ AM_riB, AM_iS, AM_CALS, AM_bid, AM_1A, AM_1B, AM_4F,
+};
+
+static const sm8500dasm mnemonic[256] = {
+ /* 00 - 0F */
+ {zCLR, AM_R}, {zNEG,AM_R}, {zCOM,AM_R}, {zRR,AM_R},
+ {zRL, AM_R}, {zRRC,AM_R}, {zRLC,AM_R}, {zSRL,AM_R},
+ {zINC, AM_R}, {zDEC,AM_R}, {zSRA,AM_R}, {zSLL,AM_R},
+ {zDA, AM_R}, {zSWAP,AM_R}, {zPUSH,AM_R}, {zPOP,AM_R},
+ /* 10 - 1F */
+ {zCMP,AM_rr}, {zADD,AM_rr}, {zSUB,AM_rr}, {zADC,AM_rr},
+ {zSBC,AM_rr}, {zAND,AM_rr}, {zOR,AM_rr}, {zXOR,AM_rr},
+ {zINCW,AM_S}, {zDECW,AM_S}, {z1A,AM_1A}, {z1B,AM_1B},
+ {zBCLR,AM_riB}, {zBSET,AM_riB}, {zPUSHW,AM_S}, {zPOPW,AM_S},
+ /* 20 - 2F */
+ {zCMP,AM_rmb}, {zADD,AM_rmb}, {zSUB,AM_rmb}, {zADC,AM_rmb},
+ {zSBC,AM_rmb}, {zAND,AM_rmb}, {zOR,AM_rmb}, {zXOR,AM_rmb},
+ {zMOV,AM_rmb}, {zMOV,AM_mbr}, {zBBC,AM_bid}, {zBBS,AM_bid},
+ {zEXTS,AM_R}, {zDM,AM_i}, {zMOVPS0,AM_i}, {zBTST,AM_Ri},
+ /* 30 - 3F */
+ {zCMP,AM_rmw}, {zADD,AM_rmw}, {zSUB,AM_rmw}, {zADC,AM_rmw},
+ {zSBC,AM_rmw}, {zAND,AM_rmw}, {zOR,AM_rmw}, {zXOR,AM_rmw},
+ {zMOV,AM_rmw}, {zMOV,AM_mwr}, {zMOVW,AM_smw}, {zMOVW,AM_mws},
+ {zMOVW,AM_ss}, {zDM,AM_R}, {zJMP,AM_2}, {zCALL,AM_2},
+ /* 40 - 4F */
+ {zCMP,AM_RR}, {zADD,AM_RR}, {zSUB,AM_RR}, {zADC,AM_RR},
+ {zSBC,AM_RR}, {zAND,AM_RR}, {zOR,AM_RR}, {zXOR,AM_RR},
+ {zMOV,AM_RR}, {zCALL,AM_ii}, {zMOVW,AM_SS}, {zMOVW,AM_Sw},
+ {zMULT,AM_RR}, {zMULT,AM_iR}, {zBMOV,AM_bR}, {z4F,AM_4F},
+ /* 50 - 5F */
+ {zCMP,AM_iR}, {zADD,AM_iR}, {zSUB,AM_iR}, {zADC,AM_iR},
+ {zSBC,AM_iR}, {zAND,AM_iR}, {zOR,AM_iR}, {zXOR,AM_iR},
+ {zMOV, AM_iR}, {zINVLD,0}, {z5A,AM_ii}, {z5B,AM_ii},
+ {zDIV,AM_SS}, {zDIV,AM_iS}, {zMOVM,AM_RiR}, {zMOVM,AM_Rii},
+ /* 60 - 6F */
+ {zCMPW,AM_SS}, {zADDW,AM_SS}, {zSUBW,AM_SS}, {zADCW,AM_SS},
+ {zSBCW,AM_SS}, {zANDW,AM_SS}, {zORW,AM_SS}, {zXORW,AM_SS},
+ {zCMPW,AM_Sw}, {zADDW,AM_Sw}, {zSUBW,AM_Sw}, {zADCW,AM_Sw},
+ {zSBCW,AM_Sw}, {zANDW,AM_Sw}, {zORW,AM_Sw}, {zXORW,AM_Sw},
+ /* 70 - 7F */
+ {zDBNZ,AM_rbr}, {zDBNZ,AM_rbr}, {zDBNZ,AM_rbr}, {zDBNZ,AM_rbr},
+ {zDBNZ,AM_rbr}, {zDBNZ,AM_rbr}, {zDBNZ,AM_rbr}, {zDBNZ,AM_rbr},
+ {zMOVW,AM_riw}, {zMOVW,AM_riw}, {zMOVW,AM_riw}, {zMOVW,AM_riw},
+ {zMOVW,AM_riw}, {zMOVW,AM_riw}, {zMOVW,AM_riw}, {zMOVW,AM_riw},
+ /* 80 - 8F */
+ {zBBC,AM_Rbr}, {zBBC,AM_Rbr}, {zBBC,AM_Rbr}, {zBBC,AM_Rbr},
+ {zBBC,AM_Rbr}, {zBBC,AM_Rbr}, {zBBC,AM_Rbr}, {zBBC,AM_Rbr},
+ {zBBS,AM_Rbr}, {zBBS,AM_Rbr}, {zBBS,AM_Rbr}, {zBBS,AM_Rbr},
+ {zBBS,AM_Rbr}, {zBBS,AM_Rbr}, {zBBS,AM_Rbr}, {zBBS,AM_Rbr},
+ /* 90 - 9F */
+ {zJMP,AM_cjp}, {zJMP,AM_cjp}, {zJMP,AM_cjp}, {zJMP,AM_cjp},
+ {zJMP,AM_cjp}, {zJMP,AM_cjp}, {zJMP,AM_cjp}, {zJMP,AM_cjp},
+ {zJMP,AM_cjp}, {zJMP,AM_cjp}, {zJMP,AM_cjp}, {zJMP,AM_cjp},
+ {zJMP,AM_cjp}, {zJMP,AM_cjp}, {zJMP,AM_cjp}, {zJMP,AM_cjp},
+ /* A0 - AF */
+ {zBCLR,AM_Rb}, {zBCLR,AM_Rb}, {zBCLR,AM_Rb}, {zBCLR,AM_Rb},
+ {zBCLR,AM_Rb}, {zBCLR,AM_Rb}, {zBCLR,AM_Rb}, {zBCLR,AM_Rb},
+ {zBSET,AM_Rb}, {zBSET,AM_Rb}, {zBSET,AM_Rb}, {zBSET,AM_Rb},
+ {zBSET,AM_Rb}, {zBSET,AM_Rb}, {zBSET,AM_Rb}, {zBSET,AM_Rb},
+ /* B0 - BF */
+ {zMOV,AM_rR}, {zMOV,AM_rR}, {zMOV,AM_rR}, {zMOV,AM_rR},
+ {zMOV,AM_rR}, {zMOV,AM_rR}, {zMOV,AM_rR}, {zMOV,AM_rR},
+ {zMOV,AM_Rr}, {zMOV,AM_Rr}, {zMOV,AM_Rr}, {zMOV,AM_Rr},
+ {zMOV,AM_Rr}, {zMOV,AM_Rr}, {zMOV,AM_Rr}, {zMOV,AM_Rr},
+ /* C0 - CF */
+ {zMOV,AM_rib}, {zMOV,AM_rib}, {zMOV,AM_rib}, {zMOV,AM_rib},
+ {zMOV,AM_rib}, {zMOV,AM_rib}, {zMOV,AM_rib}, {zMOV,AM_rib},
+ {zMOV,AM_pi}, {zMOV,AM_pi}, {zMOV,AM_pi}, {zMOV,AM_pi},
+ {zMOV,AM_pi}, {zMOV,AM_pi}, {zMOV,AM_pi}, {zMOV,AM_pi},
+ /* D0 - DF */
+ {zBR,AM_cbr}, {zBR,AM_cbr}, {zBR,AM_cbr}, {zBR,AM_cbr},
+ {zBR,AM_cbr}, {zBR,AM_cbr}, {zBR,AM_cbr}, {zBR,AM_cbr},
+ {zBR,AM_cbr}, {zBR,AM_cbr}, {zBR,AM_cbr}, {zBR,AM_cbr},
+ {zBR,AM_cbr}, {zBR,AM_cbr}, {zBR,AM_cbr}, {zBR,AM_cbr},
+ /* E0 - EF */
+ {zCALS,AM_CALS}, {zCALS,AM_CALS}, {zCALS,AM_CALS}, {zCALS,AM_CALS},
+ {zCALS,AM_CALS}, {zCALS,AM_CALS}, {zCALS,AM_CALS}, {zCALS,AM_CALS},
+ {zCALS,AM_CALS}, {zCALS,AM_CALS}, {zCALS,AM_CALS}, {zCALS,AM_CALS},
+ {zCALS,AM_CALS}, {zCALS,AM_CALS}, {zCALS,AM_CALS}, {zCALS,AM_CALS},
+ /* F0 - FF */
+ {zSTOP,0}, {zHALT,0}, {zINVLD,0}, {zINVLD,0},
+ {zINVLD,0}, {zINVLD,0}, {zINVLD,0}, {zINVLD,0},
+ {zRET,0}, {zIRET,0}, {zCLRC,0}, {zCOMC,0},
+ {zSETC,0}, {zEI,0}, {zDI,0}, {zNOP,0},
+
+};
+
+CPU_DISASSEMBLE( sm8500 )
+{
+ const sm8500dasm *instr;
+ char *dst;
+ UINT8 op;
+ INT8 offset = 0;
+ UINT16 ea = 0, ea2 = 0;
+ int pos = 0;
+
+ dst = buffer;
+
+ op = oprom[pos++];
+
+ instr = &mnemonic[op];
+
+ if ( instr->arguments )
+ {
+ if ( instr->arguments != AM_1A && instr->arguments != AM_1B && instr->arguments != AM_4F ) {
+ dst += sprintf( dst, "%-4s ", s_mnemonic[ instr->mnemonic ] );
+ }
+ switch( instr->arguments ) {
+ case AM_R:
+ ea = oprom[pos++];
+ dst += sprintf( dst, "R%02Xh", ea );
+ break;
+ case AM_iR:
+ dst += sprintf( dst, "R%02Xh, $%02X", oprom[pos + 1], oprom[pos + 0]);
+ pos += 2;
+ break;
+ case AM_iS:
+ dst += sprintf( dst, "RR%02Xh, $%02X", oprom[pos + 1], oprom[pos + 0]);
+ pos += 2;
+ break;
+ case AM_Sw:
+ ea2 = oprom[pos++];
+ ea = oprom[pos++] << 8;
+ ea += oprom[pos++];
+ dst+= sprintf( dst, "RR%02Xh, $%04X", ea2, ea );
+ break;
+ case AM_rib:
+ ea = oprom[pos++];
+ dst += sprintf( dst, "r%02Xh, $%02X", op & 0x07, ea );
+ break;
+ case AM_riw:
+ ea = oprom[pos++] << 8;
+ ea += oprom[pos++];
+ dst += sprintf( dst, "rr%02Xh, $%04X", sm8500_b2w[op & 0x07], ea );
+ break;
+ case AM_rmb:
+ ea = oprom[pos++];
+ dst += sprintf( dst, "r%02Xh,", ( ea >> 3 ) & 0x07 );
+ switch( ea & 0xC0 ) {
+ case 0x00:
+ dst += sprintf( dst, "@r%02Xh", ea & 0x07 ); break;
+ case 0x40:
+ dst += sprintf( dst, "(r%02Xh)+", ea & 0x07 ); break;
+ case 0x80:
+ ea2 = oprom[pos++];
+ if ( ea & 0x07 ) {
+ dst += sprintf( dst, "$%02X(r%02Xh)", ea2, ea & 0x07 );
+ } else {
+ dst += sprintf( dst, "@$%02X", ea2 );
+ }
+ break;
+ case 0xC0:
+ dst += sprintf( dst, "-(r%02Xh)", ea & 0x07 ); break;
+ }
+ break;
+ case AM_mbr:
+ ea = oprom[pos++];
+ switch( ea & 0xC0 ) {
+ case 0x00:
+ dst += sprintf( dst, "@r%02Xh", ea & 0x07 ); break;
+ case 0x40:
+ dst += sprintf( dst, "(r%02Xh)+", ea & 0x07 ); break;
+ case 0x80:
+ ea2 = oprom[pos++];
+ if ( ea & 0x07 ) {
+ dst += sprintf( dst, "$%02X(r%02Xh)", ea2, ea & 0x07 );
+ } else {
+ dst += sprintf( dst, "@$%02X", ea2 );
+ }
+ break;
+ case 0xC0:
+ dst += sprintf( dst, "-(r%02Xh)", ea & 0x07 ); break;
+ }
+ dst += sprintf( dst, ",r%02Xh", ( ea >> 3 ) & 0x07 );
+ break;
+ case AM_rmw:
+ ea = oprom[pos++];
+ dst += sprintf( dst, "r%02Xh,", ( ea >> 3 ) & 0x07 );
+ switch( ea & 0xC0 ) {
+ case 0x00:
+ dst += sprintf( dst, "@rr%02Xh", sm8500_b2w[ea & 0x07] ); break;
+ case 0x40:
+ dst += sprintf( dst, "(rr%02Xh)+", sm8500_b2w[ea & 0x07] ); break;
+ case 0x80:
+ ea2 = oprom[pos++] << 8;
+ ea2 += oprom[pos++];
+ if ( ea & 0x07 ) {
+ dst += sprintf( dst, "$%04X(rr%02Xh)", ea2, sm8500_b2w[ea & 0x07] );
+ } else {
+ dst += sprintf( dst, "@$%04X", ea2 );
+ }
+ break;
+ case 0xC0:
+ dst += sprintf( dst, "-(rr%02Xh)", sm8500_b2w[ea & 0x07] ); break;
+ }
+ break;
+ case AM_mwr:
+ ea = oprom[pos++];
+ switch( ea & 0xC0 ) {
+ case 0x00:
+ dst += sprintf( dst, "@rr%02Xh", sm8500_b2w[ea & 0x07] ); break;
+ case 0x40:
+ dst += sprintf( dst, "(rr%02Xh)+", sm8500_b2w[ea & 0x07] ); break;
+ case 0x80:
+ ea2 = oprom[pos++] << 8;
+ ea2 += oprom[pos++];
+ if ( ea & 0x07 ) {
+ dst += sprintf( dst, "$%04X(rr%02Xh)", ea2, sm8500_b2w[ea & 0x07] );
+ } else {
+ dst += sprintf( dst, "@$%04X", ea2 );
+ }
+ break;
+ case 0xC0:
+ dst += sprintf( dst, "-(rr%02Xh)", sm8500_b2w[ea & 0x07] ); break;
+ }
+ dst += sprintf( dst, ",r%02Xh", ( ea >> 3 ) & 0x07 );
+ break;
+ case AM_smw:
+ ea = oprom[pos++];
+ dst += sprintf( dst, "rr%02Xh,", sm8500_b2w[( ea >> 3 ) & 0x07] );
+ switch( ea & 0xC0 ) {
+ case 0x00:
+ dst += sprintf( dst, "@rr%02Xh", sm8500_b2w[ea & 0x07] ); break;
+ case 0x40:
+ dst += sprintf( dst, "(rr%02Xh)+", sm8500_b2w[ea & 0x07] ); break;
+ case 0x80:
+ ea2 = oprom[pos++] << 8;
+ ea2 += oprom[pos++];
+ if ( ea & 0x07 ) {
+ dst += sprintf( dst, "$%04X(rr%02Xh)", ea2, sm8500_b2w[ea & 0x07] );
+ } else {
+ dst += sprintf( dst, "@$%04X", ea2 );
+ }
+ break;
+ case 0xC0:
+ dst += sprintf( dst, "-(rr%02Xh)", sm8500_b2w[ea & 0x07] ); break;
+ }
+ break;
+ case AM_mws:
+ ea = oprom[pos++];
+ switch( ea & 0xC0 ) {
+ case 0x00:
+ dst += sprintf( dst, "@rr%02Xh", sm8500_b2w[ea & 0x07] ); break;
+ case 0x40:
+ dst += sprintf( dst, "(rr%02Xh)+", sm8500_b2w[ea & 0x07] ); break;
+ case 0x80:
+ ea2 = oprom[pos++] << 8;
+ ea2 += oprom[pos++];
+ if ( ea & 0x07 ) {
+ dst += sprintf( dst, "$%04X(rr%02Xh)", ea2, sm8500_b2w[ea & 0x07] );
+ } else {
+ dst += sprintf( dst, "@$%04X", ea2 );
+ }
+ break;
+ case 0xC0:
+ dst += sprintf( dst, "-(rr%02Xh)", sm8500_b2w[ea & 0x07] ); break;
+ }
+ dst += sprintf( dst, ",rr%02Xh", sm8500_b2w[( ea >> 3 ) & 0x07] );
+ break;
+ case AM_cbr:
+ offset = (INT8) oprom[pos++];
+ dst += sprintf( dst, "%s,$%04X", sm8500_cond[ op & 0x0F ], pc + pos + offset );
+ break;
+ case AM_rbr:
+ offset = (INT8) oprom[pos++];
+ dst += sprintf( dst, "r%02Xh,$%04X", op & 0x07, pc + pos + offset );
+ break;
+ case AM_cjp:
+ ea = oprom[pos++] << 8;
+ ea += oprom[pos++];
+ dst += sprintf( dst, "%s,$%04X", sm8500_cond[ op & 0x0F], ea );
+ break;
+ case AM_rr:
+ ea = oprom[pos++];
+ switch( ea & 0xc0 ) {
+ case 0x00:
+ dst += sprintf( dst, "r%02Xh,r%02Xh", (ea >> 3 ) & 0x07, ea & 0x07 );
+ break;
+ case 0x40:
+ case 0x80:
+ case 0xC0:
+ dst += sprintf( dst, "undef" );
+ break;
+ }
+ break;
+ case AM_r1:
+ ea = oprom[pos++];
+ switch( ea & 0xC0 ) {
+ case 0x00:
+ dst += sprintf( dst, "@r%02Xh", (ea >> 3 ) & 0x07 );
+ break;
+ case 0x40:
+ case 0x80:
+ case 0xC0:
+ dst += sprintf( dst, "undef" );
+ break;
+ }
+ break;
+ case AM_S:
+ ea = oprom[pos++];
+ dst += sprintf( dst, "RR%02Xh", ea );
+ break;
+ case AM_pi:
+ ea = oprom[pos++];
+ dst += sprintf( dst, "r%02Xh, $%02X", 0x10 + (op & 0x07), ea );
+ break;
+ case AM_Ri:
+ ea = oprom[pos++];
+ ea2 = oprom[pos++];
+ dst += sprintf( dst, "R%02Xh,$%02X", ea, ea2 );
+ break;
+ case AM_i:
+ ea = oprom[pos++];
+ dst += sprintf( dst, "$%02X", ea );
+ break;
+ case AM_ii:
+ ea = oprom[pos++] << 8;
+ ea += oprom[pos++];
+ dst += sprintf( dst, "$%04X", ea );
+ break;
+ case AM_ss:
+ ea = oprom[pos++];
+ switch( ea & 0xC0 ) {
+ case 0x00:
+ dst += sprintf( dst, "rr%02Xh,rr%02Xh", sm8500_b2w[( ea >> 3 ) & 0x07], sm8500_b2w[ea & 0x07] ); break;
+ case 0x40:
+ dst += sprintf( dst, "undef" ); break;
+ case 0x80:
+ dst += sprintf( dst, "undef" ); break;
+ case 0xC0:
+ dst += sprintf( dst, "undef" ); break;
+ }
+ break;
+ case AM_RR:
+ ea = oprom[pos++];
+ ea2 = oprom[pos++];
+ dst += sprintf( dst, "R%02Xh,R%02Xh", ea2, ea );
+ break;
+ case AM_2:
+ ea = oprom[pos++];
+ switch( ea & 0xC0 ) {
+ case 0x00:
+ dst += sprintf( dst, "rr%02Xh", sm8500_b2w[ea & 0x07] ); break;
+ case 0x40:
+ ea2 = oprom[pos++] << 8;
+ ea2 += oprom[pos++];
+ if ( ea & 0x38 ) {
+ dst += sprintf( dst, "@$%04X(r%02Xh)", ea2, ( ea >> 3 ) & 0x07 );
+ } else {
+ dst += sprintf( dst, "@$%04X", ea2 );
+ }
+ break;
+ case 0x80:
+ dst += sprintf( dst, "undef" ); break;
+ case 0xC0:
+ dst += sprintf( dst, "undef" ); break;
+ }
+ break;
+ case AM_SS:
+ ea = oprom[pos++];
+ ea2 = oprom[pos++];
+ dst += sprintf( dst, "RR%02Xh,RR%02Xh", ea2, ea );
+ break;
+ case AM_bR:
+ ea = oprom[pos++];
+ ea2 = oprom[pos++];
+ switch( ea & 0xC0 ) {
+ case 0x00:
+ dst += sprintf( dst, "BF,R%02Xh,#%d", ea2, ea & 0x07 ); break;
+ case 0x40:
+ dst += sprintf( dst, "R%02Xh,#%d,BF", ea2, ea & 0x07 ); break;
+ case 0x80:
+ dst += sprintf( dst, "undef" ); break;
+ case 0xC0:
+ dst += sprintf( dst, "undef" ); break;
+ }
+ break;
+ case AM_Rbr:
+ ea = oprom[pos++];
+ offset = (INT8) oprom[pos++];
+ dst += sprintf( dst, "R%02Xh,#%d,$%04X", ea, op & 0x07, pc + pos + offset );
+ break;
+ case AM_Rb:
+ ea = oprom[pos++];
+ dst += sprintf( dst, "R%02Xh,#%d", ea, op&0x07 );
+ break;
+ case AM_rR:
+ ea = oprom[pos++];
+ dst += sprintf( dst, "r%02Xh,R%02Xh", op & 0x07, ea );
+ break;
+ case AM_Rr:
+ ea = oprom[pos++];
+ dst += sprintf( dst, "R%02Xh,r%02Xh", ea, op & 0x07 );
+ break;
+ case AM_Rii:
+ ea = oprom[pos++];
+ dst += sprintf( dst, "R%02Xh,", ea );
+ ea = oprom[pos++];
+ dst += sprintf( dst, "$%02X,", ea );
+ ea = oprom[pos++];
+ dst += sprintf( dst, "$%02X", ea );
+ break;
+ case AM_RiR:
+ ea = oprom[pos++];
+ dst += sprintf( dst, "R%02Xh,", ea );
+ ea = oprom[pos++];
+ dst += sprintf( dst, "$%02X,", ea );
+ ea = oprom[pos++];
+ dst += sprintf( dst, "R%02Xh", ea );
+ break;
+ case AM_riB:
+ ea = oprom[pos++];
+ ea2 = oprom[pos++];
+ switch( ea & 0xC0 ) {
+ case 0x00:
+ dst += sprintf( dst, "#%2x(r%02Xh),#%d", ea2, ea >> 3, ea & 0x07 );
+ break;
+ case 0x40:
+ dst += sprintf( dst, "undef" ); break;
+ case 0x80:
+ dst += sprintf( dst, "undef" ); break;
+ case 0xC0:
+ dst += sprintf( dst, "undef" ); break;
+ }
+ break;
+ case AM_CALS:
+ ea = oprom[pos++];
+ dst += sprintf( dst, "$%04X", 0x1000 | ( ( op & 0x0f ) << 8 ) | ea );
+ break;
+ case AM_bid:
+ ea = oprom[pos++];
+ ea2 = oprom[pos++];
+ if ( ea & 0x38 ) {
+ dst += sprintf( dst, "$%02X(r%02Xh)", ea2, ( ea >> 3 ) & 0x07 );
+ } else {
+ dst += sprintf( dst, "$%04X", 0xFF00 + ea2 );
+ }
+ dst += sprintf( dst, ",#%d,", ea & 0x07 );
+ offset = (INT8) oprom[pos++];
+ dst += sprintf( dst, "$%04X", pc + pos + offset );
+ break;
+ case AM_1A:
+ ea = oprom[pos++];
+ switch( ea & 0x07 ) {
+ case 0x00: dst += sprintf( dst, "%-4s ", s_mnemonic[ zCLR ] ); break;
+ case 0x01: dst += sprintf( dst, "%-4s ", s_mnemonic[ zNEG ] ); break;
+ case 0x02: dst += sprintf( dst, "%-4s ", s_mnemonic[ zCOM ] ); break;
+ case 0x03: dst += sprintf( dst, "%-4s ", s_mnemonic[ zRR ] ); break;
+ case 0x04: dst += sprintf( dst, "%-4s ", s_mnemonic[ zRL ] ); break;
+ case 0x05: dst += sprintf( dst, "%-4s ", s_mnemonic[ zRRC ] ); break;
+ case 0x06: dst += sprintf( dst, "%-4s ", s_mnemonic[ zRLC ] ); break;
+ case 0x07: dst += sprintf( dst, "%-4s ", s_mnemonic[ zSRL ] ); break;
+ }
+ dst += sprintf( dst, "@r%02Xh", ( ea >> 3 ) & 0x07 );
+ break;
+ case AM_1B:
+ ea = oprom[pos++];
+ switch( ea & 0x07 ) {
+ case 0x00: dst += sprintf( dst, "%-4s ", s_mnemonic[ zINC ] ); break;
+ case 0x01: dst += sprintf( dst, "%-4s ", s_mnemonic[ zDEC ] ); break;
+ case 0x02: dst += sprintf( dst, "%-4s ", s_mnemonic[ zSRA ] ); break;
+ case 0x03: dst += sprintf( dst, "%-4s ", s_mnemonic[ zSLL ] ); break;
+ case 0x04: dst += sprintf( dst, "%-4s ", s_mnemonic[ zDA ] ); break;
+ case 0x05: dst += sprintf( dst, "%-4s ", s_mnemonic[ zSWAP ] ); break;
+ case 0x06: dst += sprintf( dst, "%-4s ", s_mnemonic[ zPUSH ] ); break;
+ case 0x07: dst += sprintf( dst, "%-4s ", s_mnemonic[ zPOP ] ); break;
+ }
+ dst += sprintf( dst, "@r%02Xh", ( ea >> 3 ) & 0x07 );
+ break;
+ case AM_4F:
+ ea = oprom[pos++];
+ ea2 = oprom[pos++];
+ switch( ea & 0xc0 ) {
+ case 0x00: dst += sprintf( dst, "%-4s ", s_mnemonic[ zBCMP ] ); break;
+ case 0x40: dst += sprintf( dst, "%-4s ", s_mnemonic[ zBAND ] ); break;
+ case 0x80: dst += sprintf( dst, "%-4s ", s_mnemonic[ zBOR ] ); break;
+ case 0xC0: dst += sprintf( dst, "%-4s ", s_mnemonic[ zBXOR ] ); break;
+ }
+ if ( ! ( ea & 0x80 ) ) {
+ dst += sprintf( dst, "BF," );
+ }
+ dst += sprintf( dst, "R%02Xh,$%02X", ea2, ea & 0x07 );
+ if ( ea & 0x80 ) {
+ dst += sprintf( dst, ",BF" );
+ }
+ break;
+ }
+ }
+ else
+ {
+ dst += sprintf( dst, "%s", s_mnemonic[ instr->mnemonic ] );
+ }
+
+ return pos | s_flags[instr->mnemonic] | DASMFLAG_SUPPORTED;
+}
+
diff --git a/trunk/src/emu/cpu/sm8500/sm85ops.h b/trunk/src/emu/cpu/sm8500/sm85ops.h
new file mode 100644
index 00000000000..87e55000d0a
--- /dev/null
+++ b/trunk/src/emu/cpu/sm8500/sm85ops.h
@@ -0,0 +1,1686 @@
+
+#define ARG_R r1 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ );
+
+#define ARG_RR r2 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ ); \
+ r1 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ );
+
+#define ARG_rR r1 = op & 0x07; \
+ r2 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ );
+
+#define ARG_iR r2 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ ); \
+ r1 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ );
+
+#define ARG_Sw r1 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ ); \
+ s2 = sm85cpu_mem_readword( cpustate, cpustate->PC ); cpustate->PC += 2;
+
+#define ARG_rrw r1 = sm8500_b2w[op & 0x07]; \
+ s2 = sm85cpu_mem_readword( cpustate, cpustate->PC ); cpustate->PC += 2;
+
+#define ARG_ri r1 = op & 0x07; \
+ r2 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ );
+
+#define ARG_pi r1 = 0x10 + ( op & 0x07 ); \
+ r2 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ );
+
+#define ARG_rmb r1 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ ); \
+ s2 = 0; \
+ switch( r1 & 0xC0 ) { \
+ case 0x00: \
+ s2 = sm85cpu_mem_readbyte( cpustate, r1 & 0x07 ); \
+ break; \
+ case 0x40: \
+ s2 = sm85cpu_mem_readbyte( cpustate, r1 & 0x07 ); \
+ sm85cpu_mem_writebyte( cpustate, r1 & 0x07, s2 + 1 ); \
+ break; \
+ case 0x80: \
+ s2 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ ); \
+ if ( r1 & 0x07 ) { \
+ s2 = s2 + sm85cpu_mem_readbyte( cpustate, r1 & 0x07 ); \
+ } \
+ break; \
+ case 0xC0: \
+ s2 = sm85cpu_mem_readbyte( cpustate, r1 & 0x07 ); \
+ sm85cpu_mem_writebyte( cpustate, r1 & 0x07, s2 - 1 ); \
+ break; \
+ } \
+ r2 = r1; \
+ r1 = ( r1 >> 3 ) & 0x07;
+
+#define ARG_rmw r1 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ ); \
+ s2 = 0; \
+ switch( r1 & 0xC0 ) { \
+ case 0x00: \
+ s2 = sm85cpu_mem_readword( cpustate, sm8500_b2w[r1 & 0x07] ); \
+ break; \
+ case 0x40: \
+ s2 = sm85cpu_mem_readword( cpustate, sm8500_b2w[r1 & 0x07] ); \
+ sm85cpu_mem_writeword( cpustate, sm8500_b2w[r1 & 0x07], s2 + 1 ); \
+ break; \
+ case 0x80: \
+ s2 = sm85cpu_mem_readword( cpustate, cpustate->PC ); cpustate->PC += 2; \
+ if ( r1 & 0x07 ) { \
+ s2 = s2 + sm85cpu_mem_readword( cpustate, sm8500_b2w[r1 & 0x07] ); \
+ } \
+ break; \
+ case 0xC0: \
+ s2 = sm85cpu_mem_readword( cpustate, sm8500_b2w[r1 & 0x07] ); \
+ sm85cpu_mem_writeword( cpustate, sm8500_b2w[r1 & 0x07], s2 - 1 ); \
+ break; \
+ } \
+ r2 = r1; \
+ r1 = ( r1 >> 3 ) & 0x07;
+
+#define ARG_smw r1 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ ); \
+ s2 = 0; \
+ switch( r1 & 0xC0 ) { \
+ case 0x00: \
+ s2 = sm85cpu_mem_readword( cpustate, sm8500_b2w[r1 & 0x07] ); \
+ break; \
+ case 0x40: \
+ s2 = sm85cpu_mem_readword( cpustate, sm8500_b2w[r1 & 0x07] ); \
+ sm85cpu_mem_writeword( cpustate, sm8500_b2w[r1 & 0x07], s2 + 1 ); \
+ break; \
+ case 0x80: \
+ s2 = sm85cpu_mem_readword( cpustate, cpustate->PC ); cpustate->PC += 2; \
+ if ( r1 & 0x07 ) { \
+ s2 = s2 + sm85cpu_mem_readword( cpustate, sm8500_b2w[r1 & 0x07] ); \
+ } \
+ break; \
+ case 0xC0: \
+ s2 = sm85cpu_mem_readword( cpustate, sm8500_b2w[ r1 & 0x07] ); \
+ sm85cpu_mem_writeword( cpustate, sm8500_b2w[r1 & 0x07], s2 - 1 ); \
+ break; \
+ } \
+ r2 = r1; \
+ r1 = sm8500_b2w[ ( r1 >> 3 ) & 0x07 ];
+
+#define ARG_d8 r1 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ ); \
+ s2 = cpustate->PC + ((INT8)r1);
+
+#define ARG_Rbr r1 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ ); \
+ r2 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ ); \
+ s2 = cpustate->PC + ((INT8)r2);
+
+#define ARG_ad16 s2 = sm85cpu_mem_readword( cpustate, cpustate->PC ); \
+ cpustate->PC += 2;
+
+#define ARG_rr r1 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ ); \
+ r2 = 0x00; \
+ switch( r1 & 0xC0 ) { \
+ case 0x00: \
+ r2 = r1 & 0x07; \
+ r1 = ( r1 >> 3 ) & 0x07; \
+ break; \
+ case 0x40: \
+ case 0x80: \
+ case 0xC0: \
+ break; \
+ }
+
+#define ARG_ss r1 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ ); \
+ r2 = 0x00; \
+ switch( r1 & 0xC0 ) { \
+ case 0x00: \
+ r2 = sm8500_b2w[r1 & 0x07]; \
+ r1 = sm8500_b2w[( r1 >> 3 ) & 0x07]; \
+ break; \
+ case 0x40: \
+ case 0x80: \
+ case 0xC0: \
+ break; \
+ }
+
+#define ARG_2 r1 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ ); \
+ s2 = 0; \
+ switch( r1 & 0xC0 ) { \
+ case 0x00: \
+ s2 = sm85cpu_mem_readword( cpustate, sm8500_b2w[ r1 & 0x07 ] ); \
+ break; \
+ case 0x40: \
+ s2 = sm85cpu_mem_readword( cpustate, cpustate->PC ); cpustate->PC += 2; \
+ if ( r1 & 0x38 ) { \
+ s2 = s2 + sm85cpu_mem_readbyte( cpustate, ( r1 >> 3 ) & 0x07 ); \
+ } \
+ s2 = sm85cpu_mem_readword( cpustate, s2 ); \
+ case 0x80: \
+ case 0xC0: \
+ break; \
+ }
+
+#define ARG_RiR r1 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ ); \
+ d1 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ ); \
+ r2 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ );
+
+#define ARG_Rii r1 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ ); \
+ d1 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ ); \
+ r2 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ );
+
+#define ARG_riB r1 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ ); \
+ s2 = 1 << ( r1 & 0x07 ); \
+ d1 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ ); \
+ if ( r1 & 0x38 ) { \
+ s1 = d1 + sm85cpu_mem_readbyte( cpustate, ( r1 >> 3 ) & 0x07 ); \
+ } else { \
+ s1 = 0xFF00 + d1; \
+ }
+
+#define ARG_riBd r1 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ ); \
+ s2 = 1 << ( r1 & 0x07 ); \
+ d1 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ ); \
+ if ( r1 & 0x38 ) { \
+ s1 = d1 + sm85cpu_mem_readbyte( cpustate, ( r1 >> 3 ) & 0x07 ); \
+ } else { \
+ s1 = 0xFF00 + d1; \
+ } \
+ d1 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ );
+
+#define OP_INTSUB8(X,Y,MASK) d1 = X; \
+ d2 = Y; \
+ res = d1 - d2; \
+ cpustate->PS1 = cpustate->PS1 & ( MASK ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res > 0xFF ) ? FLAG_C : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFF ) == 0 ) ? FLAG_Z : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res & 0x80 ) ? FLAG_S : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( ( d2 ^ d1 ) & ( res ^ d1 ) ) & 0x80 ) ? FLAG_V : 0 );
+
+#define OP_CMP8(X,Y) OP_INTSUB8( X, Y, (FLAG_B | FLAG_I | FLAG_H | FLAG_D ) );
+
+#define OP_SUB8(X,Y) OP_INTSUB8( X, Y, (FLAG_B | FLAG_I ) ); \
+ cpustate->PS1 = cpustate->PS1 | FLAG_D; \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( d1 ^ d2 ^ res ) & 0x10 ) ? FLAG_H : 0 );
+
+#define OP_INTSUB16(X,Y,MASK) d1 = X; \
+ d2 = Y; \
+ res = d1 - d2; \
+ cpustate->PS1 = cpustate->PS1 & ( MASK ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res > 0xFFFF ) ? FLAG_C : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFFFF ) == 0 ) ? FLAG_Z : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res & 0x8000 ) ? FLAG_S : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( ( d2 ^ d1 ) & (res ^ d1) ) & 0x8000 ) ? FLAG_V : 0 );
+
+#define OP_CMP16(X,Y) OP_INTSUB16( X, Y, ( FLAG_B | FLAG_I | FLAG_H | FLAG_D ) );
+
+#define OP_SUB16(X,Y) OP_INTSUB16( X, Y, ( FLAG_B | FLAG_I ) ); \
+ cpustate->PS1 = cpustate->PS1 | FLAG_D; \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( d1 ^ d2 ^ res ) & 0x0010 ) ? FLAG_H : 0 );
+
+#define OP_SBC8(X,Y) d1 = X; \
+ d2 = Y; \
+ res = d1 - d2 - ((cpustate->PS1 & FLAG_C) ? 1 : 0); \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_B | FLAG_I ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res > 0xFF ) ? FLAG_C : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFF ) == 0 ) ? FLAG_Z : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res & 0x80 ) ? FLAG_S : 0); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( ( d2 ^ d1 ) & (res ^ d1) ) & 0x80 ) ? FLAG_V : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | FLAG_D; \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( d1 ^ d2 ^ res ) & 0x10 ) ? FLAG_H : 0 );
+
+#define OP_SBC16(X,Y) d1 = X; \
+ d2 = Y; \
+ res = d1 - d2 - ((cpustate->PS1 & FLAG_C) ? 1 : 0); \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_B | FLAG_I ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res > 0xFFFF ) ? FLAG_C : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFFFF ) == 0 ) ? FLAG_Z : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res & 0x8000 ) ? FLAG_S : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( ( d2 ^ d1 ) & ( res ^ d1 ) ) & 0x8000 ) ? FLAG_V : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | FLAG_D; \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( d1 ^ d2 ^ res ) & 0x10 ) ? FLAG_H : 0 );
+
+#define OP_ADD8(X,Y) d1 = X; \
+ d2 = Y; \
+ res = d1 + d2; \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_B | FLAG_I ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res > 0xFF ) ? FLAG_C : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFF ) == 0 ) ? FLAG_Z : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res & 0x80 ) ? FLAG_S : 0); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( ( d2 ^ d1 ^ 0x80 ) & (res ^ d1) ) & 0x80 ) ? FLAG_V : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( d1 ^ d2 ^ res ) & 0x10 ) ? FLAG_H : 0 );
+
+#define OP_ADD16(X,Y) d1 = X; \
+ d2 = Y; \
+ res = d1 + d2; \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_B | FLAG_I ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res > 0xFFFF ) ? FLAG_C : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFFFF ) == 0 ) ? FLAG_Z : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res & 0x8000 ) ? FLAG_S : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( ( d2 ^ d1 ) & ( res ^ d1 ) ) & 0x8000 ) ? FLAG_V : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( d2 ^ d1 ^ res ) & 0x0010 ) ? FLAG_H : 0 );
+
+#define OP_ADC8(X,Y) d1 = X; \
+ d2 = Y; \
+ res = d1 + d2 + ((cpustate->PS1 & FLAG_C) ? 1 : 0); \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_B | FLAG_I ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res > 0xFF ) ? FLAG_C : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFF ) == 0 ) ? FLAG_Z : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res & 0x80 ) ? FLAG_S : 0); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( ( d2 ^ d1 ) & (res ^ d1) ) & 0x80 ) ? FLAG_V : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( d1 ^ d2 ^ res ) & 0x10 ) ? FLAG_H : 0 );
+
+#define OP_ADC16(X,Y) d1 = X; \
+ d2 = Y; \
+ res = d1 + d2 + ((cpustate->PS1 & FLAG_C) ? 1 : 0); \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_B | FLAG_I ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res > 0xFFFF ) ? FLAG_C : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFFFF ) == 0 ) ? FLAG_Z : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res & 0x8000 ) ? FLAG_S : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( ( d2 ^ d1 ) & ( res ^ d1) ) & 0x8000 ) ? FLAG_V : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( d1 ^ d2 ^ res ) & 0x10 ) ? FLAG_H : 0 );
+
+#define OP_NEG8(X) res = -X; \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_D | FLAG_H | FLAG_B | FLAG_I ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFF ) == 0 ) ? FLAG_C | FLAG_Z : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res & 0x80 ) ? FLAG_S : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFF ) == 0x80 ) ? FLAG_V : 0 );
+
+#define OP_COM8(X) res = ~X; \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_C | FLAG_D | FLAG_H | FLAG_B | FLAG_I ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFF ) == 0 ) ? FLAG_Z : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res & 0x80 ) ? FLAG_S : 0 );
+
+#define OP_RR8(X) d1 = X; \
+ res = d1 >> 1; \
+ if ( d1 & 0x01 ) { \
+ res |= 0x80; \
+ } \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_D | FLAG_H | FLAG_B | FLAG_I ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( d1 & 0x01 ) ? FLAG_C : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFF ) == 0 ) ? FLAG_Z : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res & 0x80 ) ? FLAG_S : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( ( d1 ^ res ) & 0x80 ) && ! ( res & 0x80 ) ) ? FLAG_V : 0 );
+
+#define OP_RL8(X) d1 = X; \
+ res = d1 << 1; \
+ if ( d1 & 0x80 ) { \
+ res |= 0x01; \
+ } \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_D | FLAG_H | FLAG_B | FLAG_I ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( d1 & 0x80 ) ? FLAG_C : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFF ) == 0 ) ? FLAG_Z : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res & 0x80 ) ? FLAG_S : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( d1 ^ res ) & 0x80 ) ? FLAG_V : 0 );
+
+#define OP_RRC8(X) d1 = X; \
+ res = d1 >> 1; \
+ if ( cpustate->PS1 & FLAG_C ) { \
+ res |= 0x80; \
+ } \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_D | FLAG_H | FLAG_B | FLAG_I ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( d1 & 0x01 ) ? FLAG_C : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFF ) == 0 ) ? FLAG_Z : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res & 0x80 ) ? FLAG_S : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( ( d1 ^ res ) & 0x80 ) && ! ( res & 0x80 ) ) ? FLAG_V : 0 );
+
+#define OP_RLC8(X) d1 = X; \
+ res = d1 << 1; \
+ if ( cpustate->PS1 & FLAG_C ) { \
+ res |= 0x01; \
+ } \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_D | FLAG_H | FLAG_B | FLAG_I ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( d1 & 0x80 ) ? FLAG_C : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFF ) == 0 ) ? FLAG_Z : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res & 0x80 ) ? FLAG_S : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( d1 ^ res ) & 0x80 ) ? FLAG_V : 0 );
+
+#define OP_SRL8(X) d1 = X; \
+ res = d1 >> 1; \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_D | FLAG_H | FLAG_B | FLAG_I ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( d1 & 0x01 ) ? FLAG_C : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFF ) == 0 ) ? FLAG_Z : 0 );
+
+#define OP_SRA8(X) d1 = X; \
+ res = d1 >> 1; \
+ if ( d1 & 0x80 ) { \
+ res |= 0x80; \
+ } \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_D | FLAG_H | FLAG_B | FLAG_I ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( d1 & 0x01 ) ? FLAG_C : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFF ) == 0 ) ? FLAG_Z : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res & 0x80 ) ? FLAG_S : 0 );
+
+#define OP_SLL8(X) d1 = X; \
+ res = d1 << 1; \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_D | FLAG_H | FLAG_B | FLAG_I ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( d1 & 0x80 ) ? FLAG_C : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFF ) == 0 ) ? FLAG_Z : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res & 0x80 ) ? FLAG_S : 0 );
+
+#define OP_INC8(X) d1 = X; \
+ res = d1 + 1; \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_C | FLAG_D | FLAG_H | FLAG_B | FLAG_I ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFF ) == 0 ) ? FLAG_Z : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res & 0x80 ) ? FLAG_S : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( ( d1 ^ res ) & 0x80 ) && ! ( res & 0x80 ) ) ? FLAG_V : 0 );
+
+#define OP_INC16(X) d1 = X; \
+ res = d1 + 1; \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_C | FLAG_D | FLAG_H | FLAG_B | FLAG_I ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFF ) == 0 ) ? FLAG_Z : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res & 0x8000 ) ? FLAG_S : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( ( d1 ^ res ) & 0x8000 ) && ! ( res & 0x8000 ) ) ? FLAG_V : 0 );
+
+#define OP_DEC8(X) d1 = X; \
+ res = d1 - 1; \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_C | FLAG_D | FLAG_H | FLAG_B | FLAG_I ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFF ) == 0 ) ? FLAG_Z : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res & 0x80 ) ? FLAG_S : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( ( d1 ^ res ) & 0x80 ) && ( res & 0x80 ) ) ? FLAG_V : 0 );
+
+#define OP_DEC16(X) d1 = X; \
+ res = d1 - 1; \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_C | FLAG_D | FLAG_H | FLAG_B | FLAG_I ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFFFF ) == 0 ) ? FLAG_Z : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res & 0x8000 ) ? FLAG_S : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( ( d1 ^ res ) & 0x8000 ) && ( res & 0x8000 ) ) ? FLAG_V : 0 );
+
+#define OP_AND8(X,Y) d1 = X; \
+ d2 = Y; \
+ res = d1 & d2; \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_B | FLAG_I | FLAG_H | FLAG_D ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFF ) == 0 ) ? FLAG_Z : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res & 0x80 ) ? FLAG_S : 0 );
+
+#define OP_AND16(X,Y) d1 = X; \
+ d2 = Y; \
+ res = d1 & d2; \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_C | FLAG_S | FLAG_B | FLAG_I | FLAG_H | FLAG_D ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFFFF ) == 0 ) ? FLAG_Z : 0 );
+
+#define OP_OR8(X,Y) d1 = X; \
+ d2 = Y; \
+ res = d1 | d2; \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_B | FLAG_I | FLAG_H | FLAG_D ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFF ) == 0 ) ? FLAG_Z : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res & 0x80 ) ? FLAG_S : 0 );
+
+#define OP_OR16(X,Y) d1 = X; \
+ d2 = Y; \
+ res = d1 | d2; \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_B | FLAG_I | FLAG_H | FLAG_D | FLAG_C | FLAG_S ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFFFF ) == 0 ) ? FLAG_Z : 0 );
+
+#define OP_XOR8(X,Y) d1 = X; \
+ d2 = Y; \
+ res = d1 ^ d2; \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_B | FLAG_I | FLAG_H | FLAG_D ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFF ) == 0 ) ? FLAG_Z : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res & 0x80 ) ? FLAG_S : 0 );
+
+#define OP_XOR16(X,Y) d1 = X; \
+ d2 = Y; \
+ res = d1 ^ d2; \
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_B | FLAG_I | FLAG_H | FLAG_D | FLAG_C | FLAG_S ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFFFF ) == 0 ) ? FLAG_Z : 0 );
+
+#define OP_DA8(X) d1 = X; \
+ res = d1; \
+ if ( cpustate->PS1 & FLAG_D ) { \
+ if ( cpustate->PS1 & FLAG_C ) { \
+ if ( cpustate->PS1 & FLAG_H ) { \
+ res += 0x9A; \
+ } else { \
+ res += 0xA0; \
+ } \
+ } else { \
+ if ( cpustate->PS1 & FLAG_H ) { \
+ res += 0xFA; \
+ } \
+ } \
+ } else { \
+ if ( cpustate->PS1 & FLAG_C ) { \
+ if ( cpustate->PS1 & FLAG_H ) { \
+ res += 0x66; \
+ } else { \
+ if ( ( res & 0x0F ) < 10 ) { \
+ res += 0x60; \
+ } else { \
+ res += 0x66; \
+ } \
+ } \
+ } else { \
+ if ( cpustate->PS1 & FLAG_H ) { \
+ if ( ( res & 0xF0 ) < 0xA0 ) { \
+ res += 0x06; \
+ } else { \
+ res += 0x66; \
+ cpustate->PS1 = cpustate->PS1 | FLAG_C; \
+ } \
+ } else { \
+ if ( ( res & 0x0F ) < 10 ) { \
+ if ( ( res & 0xF0 ) >= 0xA0 ) { \
+ res += 0x60; \
+ cpustate->PS1 = cpustate->PS1 | FLAG_C; \
+ } \
+ } else { \
+ if ( ( res & 0xF0 ) < 0x90 ) { \
+ res += 0x06; \
+ } else { \
+ res += 0x66; \
+ cpustate->PS1 = cpustate->PS1 | FLAG_C; \
+ } \
+ } \
+ } \
+ } \
+ } \
+ cpustate->PS1 = cpustate->PS1 & ~ ( FLAG_Z | FLAG_S ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( ( res & 0xFF ) == 0x00 ) ? FLAG_Z : 0 ); \
+ cpustate->PS1 = cpustate->PS1 | ( ( res & 0x80 ) ? FLAG_S : 0 );
+
+#define OP_SWAP8(X) d1 = X; \
+ res = ( d1 << 4 ) | ( d1 >> 4 );
+
+#define CHECK_CC res = 0; \
+ switch( op & 0x0F ) { \
+ case 0x00: /* F */ res = 0; break; \
+ case 0x01: /* LT */ if ( ( cpustate->PS1 & FLAG_S ) ^ ( ( cpustate->PS1 & FLAG_V ) << 1 ) ) res = 1; break; \
+ case 0x02: /* LE */ if ( ( ( cpustate->PS1 & FLAG_S ) && ! ( cpustate->PS1 & FLAG_V ) ) || ( ( cpustate->PS1 & FLAG_S ) && ( cpustate->PS1 & FLAG_V ) && ( cpustate->PS1 & FLAG_Z ) ) || ( ! ( cpustate->PS1 & FLAG_S ) && ( ( cpustate->PS1 & FLAG_Z ) || (cpustate->PS1 & FLAG_V ) ) ) ) res = 1; break; \
+ case 0x03: /* ULE */ if ( cpustate->PS1 & FLAG_Z || cpustate->PS1 & FLAG_C ) res = 1; break; \
+ case 0x04: /* OV */ if ( cpustate->PS1 & FLAG_V ) res = 1; break; \
+ case 0x05: /* MI */ if ( cpustate->PS1 & FLAG_S ) res = 1; break; \
+ case 0x06: /* Z */ if ( cpustate->PS1 & FLAG_Z ) res = 1; break; \
+ case 0x07: /* C */ if ( cpustate->PS1 & FLAG_C ) res = 1; break; \
+ case 0x08: /* T */ res = 1; break; \
+ case 0x09: /* GE */ if ( ! ( ( cpustate->PS1 & FLAG_S ) ^ ( ( cpustate->PS1 & FLAG_V ) << 1 ) ) ) res = 1; break; \
+ case 0x0A: /* GT */ if ( ( ! ( cpustate->PS1 & FLAG_Z ) && ( cpustate->PS1 & FLAG_S ) && ( cpustate->PS1 & FLAG_V ) ) || ( ! ( cpustate->PS1 & FLAG_Z ) && ! ( cpustate->PS1 & FLAG_V ) && ! ( cpustate->PS1 & FLAG_S ) ) ) res = 1; break; \
+ case 0x0B: /* UGT */ if ( ! ( cpustate->PS1 & FLAG_Z || cpustate->PS1 & FLAG_C ) ) res = 1; break; \
+ case 0x0C: /* NOV */ if ( ! (cpustate->PS1 & FLAG_V) ) res = 1; break; \
+ case 0x0D: /* PL */ if ( ! (cpustate->PS1 & FLAG_S) ) res = 1; break; \
+ case 0x0E: /* NZ */ if ( ! (cpustate->PS1 & FLAG_Z) ) res = 1; break; \
+ case 0x0F: /* NC */ if ( ! (cpustate->PS1 & FLAG_C) ) res = 1; break; \
+ }
+
+#define PUSH8(X) cpustate->SP--; \
+ if ( ( cpustate->SYS & 0x40 ) == 0 ) cpustate->SP &= 0xFF; \
+ sm85cpu_mem_writebyte( cpustate, cpustate->SP, X );
+
+#define POP8(X) X = sm85cpu_mem_readbyte( cpustate, cpustate->SP ); \
+ cpustate->SP++; \
+ if ( ( cpustate->SYS & 0x40 ) == 0 ) cpustate->SP &= 0xFF;
+
+case 0x00: /* CLR R - 4 cycles - Flags affected: -------- */
+ ARG_R;
+ sm85cpu_mem_writebyte( cpustate, r1, 0 );
+ mycycles += 4;
+ break;
+case 0x01: /* NEG R - 5 cycles - Flags affected: CZSV---- */
+ ARG_R;
+ OP_NEG8( sm85cpu_mem_readbyte( cpustate, r1 ) );
+ sm85cpu_mem_writebyte( cpustate, r1 , res & 0xFF );
+ mycycles += 5;
+ break;
+case 0x02: /* COM R - 4 cycles - Flags affected: -ZS0---- */
+ ARG_R;
+ OP_COM8( sm85cpu_mem_readbyte( cpustate, r1 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 4;
+ break;
+case 0x03: /* RR R - 4 cycles - Flags affected: CZSV---- */
+ ARG_R;
+ OP_RR8( sm85cpu_mem_readbyte( cpustate, r1 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 4;
+ break;
+case 0x04: /* RL R - 4 cycles - Flags affected: CZSV---- */
+ ARG_R;
+ OP_RL8( sm85cpu_mem_readbyte( cpustate, r1 ) );
+ sm85cpu_mem_writebyte( cpustate, r1 , res & 0xFF );
+ mycycles += 4;
+ break;
+case 0x05: /* RRC R - 4 cycles - Flags affected: CZSV---- */
+ ARG_R;
+ OP_RRC8( sm85cpu_mem_readbyte( cpustate, r1 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 4;
+ break;
+case 0x06: /* RLC R - 4 cycles - Flags affected: CZSV---- */
+ ARG_R;
+ OP_RLC8( sm85cpu_mem_readbyte( cpustate, r1 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 4;
+ break;
+case 0x07: /* SRL R - 4 cycles - Flags affected: CZ00---- */
+ ARG_R;
+ OP_SRL8( sm85cpu_mem_readbyte( cpustate, r1 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 4;
+ break;
+case 0x08: /* INC R - 4 cycles - Flags affected: -ZSV---- */
+ ARG_R;
+ OP_INC8( sm85cpu_mem_readbyte( cpustate, r1 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 4;
+ break;
+case 0x09: /* DEC R - 4 cycles - Flags affected: -ZSV---- */
+ ARG_R;
+ OP_DEC8( sm85cpu_mem_readbyte( cpustate, r1 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 4;
+ break;
+case 0x0A: /* SRA R - 4 cycles - Flags affected: CZS0---- */
+ ARG_R;
+ OP_SRA8( sm85cpu_mem_readbyte( cpustate, r1 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 4;
+ break;
+case 0x0B: /* SLL R - 4 cycles - Flags affected: CZS0---- */
+ ARG_R;
+ OP_SLL8( sm85cpu_mem_readbyte( cpustate, r1 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 4;
+ break;
+case 0x0C: /* DA R - 4 cycles - Flags affected: CZS----- */
+ ARG_R;
+ OP_DA8( sm85cpu_mem_readbyte( cpustate, r1 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 4;
+ break;
+case 0x0D: /* SWAP R - 7 cycles - Flags affected: -------- */
+ ARG_R;
+ OP_SWAP8( sm85cpu_mem_readbyte( cpustate, r1 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 7;
+ break;
+case 0x0E: /* PUSH R - 5?/12? (8bit SP),10 (16bit SP) cycles */
+ ARG_R;
+ PUSH8( sm85cpu_mem_readbyte( cpustate, r1 ) );
+ mycycles += ( ( cpustate->SYS & 0x40 ) ? 12 : 10 );
+ break;
+case 0x0F: /* POP R - 9,8 cycles */
+ ARG_R;
+ POP8( r2 );
+ sm85cpu_mem_writebyte( cpustate, r1, r2 );
+ mycycles += ( ( cpustate->SYS & 0x40 ) ? 9 : 8 );
+ break;
+case 0x10: /* CMP Rr,Rs - 5 cycles - Flags affected: CZSV---- */
+ ARG_rr;
+ OP_CMP8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, r2 ) );
+ mycycles += 5;
+ break;
+case 0x11: /* ADD Rr,Rs - 5 cycles - Flags affected: CZSV0H-- */
+ ARG_rr;
+ OP_ADD8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, r2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 5;
+ break;
+case 0x12: /* SUB Rr,Rs - 5 cycles - Flags affected: CZSV1H-- */
+ ARG_rr;
+ OP_SUB8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, r2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 5;
+ break;
+case 0x13: /* ADC Rr,Rs - 5 cycles - Flags affected: CZSV0H-- */
+ ARG_rr;
+ OP_ADC8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, r2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 5;
+ break;
+case 0x14: /* SBC Rr,Rs - 5 cycles - Flags affected: CZSV1H-- */
+ ARG_rr;
+ OP_SBC8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, r2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 5;
+ break;
+case 0x15: /* AND Rr,Rs - 5 cycles - Flags affected: -ZS0---- */
+ ARG_rr;
+ OP_AND8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, r2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 5;
+ break;
+case 0x16: /* OR Rr,Rs - 5 cycles - Flags affected: -ZS0---- */
+ ARG_rr;
+ OP_OR8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, r2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 5;
+ break;
+case 0x17: /* XOR Rr,Rs - 5 cycles - Flags affected: -ZS0---- */
+ ARG_rr;
+ OP_XOR8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, r2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 5;
+ break;
+case 0x18: /* INCW S - 8 cycles - Flags affected: -ZSV---- */
+ ARG_R;
+ OP_INC16( sm85cpu_mem_readword( cpustate, r1 ) );
+ sm85cpu_mem_writeword( cpustate, r1, res & 0xFFFF );
+ mycycles += 8;
+ break;
+case 0x19: /* DECW S - 8 cycles - Flags affected: -ZSV---- */
+ ARG_R;
+ OP_DEC16( sm85cpu_mem_readword( cpustate, r1 ) );
+ sm85cpu_mem_writeword( cpustate, r1, res & 0xFFFF );
+ mycycles += 8;
+ break;
+case 0x1A: /* CLR/NEG/COM/RR/RL/RRC/RLC/SRL @Rr - 7/8/7/7/7/7/7/6 cycles */
+ ARG_rr;
+ res = 0;
+ s1 = sm85cpu_mem_readbyte( cpustate, r1 );
+ switch( r2 ) {
+ case 0x00: /* Flags affected: -------- */
+ res = 0;
+ mycycles += 7;
+ break;
+ case 0x01: /* Flags affected: CZSV---- */
+ OP_NEG8( sm85cpu_mem_readbyte( cpustate, s1 ) );
+ mycycles += 8;
+ break;
+ case 0x02: /* Flags affected: -ZS0---- */
+ OP_COM8( sm85cpu_mem_readbyte( cpustate, s1 ) );
+ mycycles += 7;
+ break;
+ case 0x03: /* Flags affected: CZSV---- */
+ OP_RR8( sm85cpu_mem_readbyte( cpustate, s1 ) );
+ mycycles += 7;
+ break;
+ case 0x04: /* Flags affected: CZSV---- */
+ OP_RL8( sm85cpu_mem_readbyte( cpustate, s1 ) );
+ mycycles += 7;
+ break;
+ case 0x05: /* Flags affected: CZSV---- */
+ OP_RRC8( sm85cpu_mem_readbyte( cpustate, s1 ) );
+ mycycles += 7;
+ break;
+ case 0x06: /* Flags affected: CZSV---- */
+ OP_RLC8( sm85cpu_mem_readbyte( cpustate, s1 ) );
+ mycycles += 7;
+ break;
+ case 0x07: /* Flags affected: CZ00---- */
+ OP_SRL8( sm85cpu_mem_readbyte( cpustate, s1 ) );
+ mycycles += 6;
+ break;
+ }
+ sm85cpu_mem_writebyte( cpustate, s1, res & 0xFF );
+ break;
+case 0x1B: /* INC/DEC/SRA/SLL/DA/SWAP/PUSH/POP @Rr - 7,7,6,7,9,13,8,12,11 cycles */
+ ARG_rr;
+ s1 = sm85cpu_mem_readbyte( cpustate, r1 );
+ switch( r2 ) {
+ case 0x00: /* Flags affected: -ZSV---- */
+ OP_INC8( sm85cpu_mem_readbyte( cpustate, s1 ) );
+ sm85cpu_mem_writebyte( cpustate, s1, res & 0xFF );
+ mycycles += 7;
+ break;
+ case 0x01: /* Flags affected: -ZSV---- */
+ OP_DEC8( sm85cpu_mem_readbyte( cpustate, s1 ) );
+ sm85cpu_mem_writebyte( cpustate, s1, res & 0xFF );
+ mycycles += 7;
+ break;
+ case 0x02: /* Flags affected: CZS0---- */
+ OP_SRA8( sm85cpu_mem_readbyte( cpustate, s1 ) );
+ sm85cpu_mem_writebyte( cpustate, s1, res & 0xFF );
+ mycycles += 6;
+ break;
+ case 0x03: /* Flags affected: CZS0---- */
+ OP_SLL8( sm85cpu_mem_readbyte( cpustate, s1 ) );
+ sm85cpu_mem_writebyte( cpustate, s1, res & 0xFF );
+ mycycles += 6;
+ break;
+ case 0x04: /* Flags affected: CZS----- */
+ OP_DA8( sm85cpu_mem_readbyte( cpustate, s1 ) );
+ sm85cpu_mem_writebyte( cpustate, s1, res & 0xFF );
+ mycycles += 7;
+ break;
+ case 0x05: /* Flags affected: -------- */
+ OP_SWAP8( sm85cpu_mem_readbyte( cpustate, s1 ) );
+ sm85cpu_mem_writebyte( cpustate, s1, res & 0xFF );
+ mycycles += 9;
+ break;
+ case 0x06: /* Flags affected: -------- */
+ PUSH8( sm85cpu_mem_readbyte( cpustate, s1 ) );
+ mycycles += ( ( cpustate->SYS & 0x40 ) ? 13 : 8 );
+ break;
+ case 0x07: /* Flags affected: -------- */
+ POP8( res );
+ sm85cpu_mem_writebyte( cpustate, s1, res );
+ mycycles += ( ( cpustate->SYS & 0x40 ) ? 12 : 11 );
+ break;
+ }
+ break;
+case 0x1C: /* BCLR 0xFFdd/d8(r),#b - 12,8 cycles - Flags affected: -------- */
+ ARG_riB;
+ sm85cpu_mem_writebyte( cpustate, s1, sm85cpu_mem_readbyte( cpustate, s1 ) & ~s2 );
+ mycycles += ( ( r1 & 0x38 ) ? 8 : 12 );
+ break;
+case 0x1D: /* BSET 0xFFdd/d8(r),#b - 12,8 cycles - Flags affected: -------- */
+ ARG_riB;
+ sm85cpu_mem_writebyte( cpustate, s1, sm85cpu_mem_readbyte( cpustate, s1 ) | s2 );
+ mycycles += ( ( r1 & 0x38 ) ? 8 : 12 );
+ break;
+case 0x1E: /* PUSHW S - 12,9 cycles - Flags affected: -------- */
+ ARG_R;
+ PUSH8( sm85cpu_mem_readbyte( cpustate, r1 + 1 ) );
+ PUSH8( sm85cpu_mem_readbyte( cpustate, r1 ) );
+ mycycles += ( ( cpustate->SYS & 0x40 ) ? 12 : 9 );
+ break;
+case 0x1F: /* POPW S - 12,13 cycles - Flags affected: -------- */
+ ARG_R;
+ POP8( r2 );
+ sm85cpu_mem_writebyte( cpustate, r1, r2 );
+ POP8( r2 );
+ sm85cpu_mem_writebyte( cpustate, r1 + 1, r2 );
+ mycycles += ( ( cpustate->SYS & 0x40 ) ? 12 : 13 );
+ break;
+case 0x20: /* CMP r,@r / CMP r,(r)+ / CMP r,@w / CMP r,w(r) / CMP r,-(r) - 7,8,10,8,9 cycles - Flags affected: CZSV---- */
+ ARG_rmb;
+ OP_CMP8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, s2 ) );
+ switch( r2 & 0xC0 ) {
+ case 0x00: mycycles += 7; break;
+ case 0x40: mycycles += 8; break;
+ case 0x80: mycycles += ( ( r2 & 0x07 ) ? 8 : 10 ); break;
+ case 0xC0: mycycles += 9; break;
+ }
+ break;
+case 0x21: /* ADD r,@r / ADD r,(r)+ / ADD r,@w / ADD r,w(r) / ADD r,-(r) - 7,8,10,8,9 cycles - Flags affected: CZSV0H-- */
+ ARG_rmb;
+ OP_ADD8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, s2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ switch( r2 & 0xC0 ) {
+ case 0x00: mycycles += 7; break;
+ case 0x40: mycycles += 8; break;
+ case 0x80: mycycles += ( ( r2 & 0x07 ) ? 8 : 10 ); break;
+ case 0xC0: mycycles += 9; break;
+ }
+ break;
+case 0x22: /* SUB r,@r / SUB r,(r)+ / SUB r,@w / SUB r,w(r) / SUB r,-(r) - 7,8,10,8,9 cycles - Flags affected: CZSV1H-- */
+ ARG_rmb;
+ OP_SUB8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, s2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ switch( r2 & 0xC0 ) {
+ case 0x00: mycycles += 7; break;
+ case 0x40: mycycles += 8; break;
+ case 0x80: mycycles += ( ( r2 & 0x07 ) ? 8 : 10 ); break;
+ case 0xC0: mycycles += 9; break;
+ }
+ break;
+case 0x23: /* ADC r,@r / ADC r,(r)+ / ADC r,@w / ADC r,w(r) / ADC r,-(r) - 7,8,10,8,9 cycles - Flags affected: CZSV0H-- */
+ ARG_rmb;
+ OP_ADC8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, s2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ switch( r2 & 0xC0 ) {
+ case 0x00: mycycles += 7; break;
+ case 0x40: mycycles += 8; break;
+ case 0x80: mycycles += ( ( r2 & 0x07 ) ? 8 : 10 ); break;
+ case 0xC0: mycycles += 9; break;
+ }
+ break;
+case 0x24: /* SBC r,@r / SBC r,(r)+ / SBC r,@w / SBC r,w(r) / SBC r,-(r) - 7,8,10,8,9 cycles - Flags affected: CZSV1H-- */
+ ARG_rmb;
+ OP_SBC8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, s2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ switch( r2 & 0xC0 ) {
+ case 0x00: mycycles += 7; break;
+ case 0x40: mycycles += 8; break;
+ case 0x80: mycycles += ( ( r2 & 0x07 ) ? 8 : 10 ); break;
+ case 0xC0: mycycles += 9; break;
+ }
+ break;
+case 0x25: /* AND r,@r / AND r,(r)+ / AND r,@w / AND r,w(r) / AND r,-(r) - 7,8,10,8,9 cycles - Flags affected: -ZS0---- */
+ ARG_rmb;
+ OP_AND8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, s2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ switch( r2 & 0xC0 ) {
+ case 0x00: mycycles += 7; break;
+ case 0x40: mycycles += 8; break;
+ case 0x80: mycycles += ( ( r2 & 0x07 ) ? 8 : 10 ); break;
+ case 0xC0: mycycles += 9; break;
+ }
+ break;
+case 0x26: /* OR r,@r / OR r,(r)+ / OR r,@w / OR r,w(r) / OR r,-(r) - 7,8,10,8,9 cycles - Flags affected: -ZS0---- */
+ ARG_rmb;
+ OP_OR8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, s2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ switch( r2 & 0xC0 ) {
+ case 0x00: mycycles += 7; break;
+ case 0x40: mycycles += 8; break;
+ case 0x80: mycycles += ( ( r2 & 0x07 ) ? 8 : 10 ); break;
+ case 0xC0: mycycles += 9; break;
+ }
+ break;
+case 0x27: /* XOR r,@r / XOR r,(r)+ / XOR r,@w / XOR r,w(r) / XOR r,-(r) - 7,8,10,8,9 cycles - Flags affected: -ZS0---- */
+ ARG_rmb;
+ OP_XOR8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, s2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ switch( r2 & 0xC0 ) {
+ case 0x00: mycycles += 7; break;
+ case 0x40: mycycles += 8; break;
+ case 0x80: mycycles += ( ( r2 & 0x07 ) ? 8 : 10 ); break;
+ case 0xC0: mycycles += 9; break;
+ }
+ break;
+case 0x28: /* MOV r,@r / MOV r,(r)+ / MOV r,@w / MOV r,w(r) / MOV r,-(r) - 6,7,10,7,8 cycles - Flags affected: -------- */
+ ARG_rmb;
+ sm85cpu_mem_writebyte( cpustate, r1, sm85cpu_mem_readbyte( cpustate, s2 ) );
+ switch( r2 & 0xC0 ) {
+ case 0x00: mycycles += 6; break;
+ case 0x40: mycycles += 7; break;
+ case 0x80: mycycles += ( ( r2 & 0x07 ) ? 7 : 10 ); break;
+ case 0xC0: mycycles += 8; break;
+ }
+ break;
+case 0x29: /* MOV @r,r / MOV (r)+,r / MOV @w,r / MOV w(r),r / MOV -(r),r - 8,8,10,9,9 cycles - Flags affected: -------- */
+ ARG_rmb;
+ sm85cpu_mem_writebyte( cpustate, s2, sm85cpu_mem_readbyte( cpustate, r1 ) );
+ switch( r2 & 0xC0 ) {
+ case 0x00: mycycles += 8; break;
+ case 0x40: mycycles += 8; break;
+ case 0x80: mycycles += ( ( r2 & 0x07 ) ? 9 : 10 ); break;
+ case 0xC0: mycycles += 9; break;
+ }
+ break;
+case 0x2A: /* BBC FFii/i(Rr),#b,d8 - 16,12/14,10 cycles - Flags affected: -------- */
+ ARG_riBd;
+ if ( sm85cpu_mem_readbyte( cpustate, s1 ) & s2 ) {
+ mycycles += 10;
+ } else {
+ cpustate->PC = cpustate->PC + ((INT8)d1);
+ mycycles += 14;
+ }
+ if ( ( r1 & 0x38 ) == 0 ) {
+ mycycles += 2;
+ }
+ break;
+case 0x2B: /* BBS FFii/i(Rr),#b,d8 - 16,12/14,10 cycles - Flags affected: -------- */
+ ARG_riBd;
+ if ( sm85cpu_mem_readbyte( cpustate, s1 ) & s2 ) {
+ cpustate->PC = cpustate->PC + ((INT8)d1);
+ mycycles += 14;
+ } else {
+ mycycles += 10;
+ }
+ if ( ( r1 & 0x38 ) == 0 ) {
+ mycycles += 2;
+ }
+ break;
+case 0x2C: /* EXTS Rr - 6 cycles - Flags affected: -------- */
+ ARG_R;
+ res = sm85cpu_mem_readword( cpustate, r1 );
+ if ( res & 0x80 ) {
+ res = res | 0xFF00;
+ } else {
+ res = res & 0x00FF;
+ }
+ sm85cpu_mem_writeword( cpustate, r1, res );
+ mycycles += 6;
+ break;
+case 0x2D: /* unk2D - 4 cycles */
+logerror( "%04X: unk%02x\n", cpustate->PC-1,op );
+ mycycles += 4;
+ break;
+case 0x2E: /* MOV PS0,#00 - 4 cycles - Flags affected: -------- */
+ ARG_R;
+ cpustate->PS0 = r1;
+ mycycles += 4;
+ break;
+case 0x2F: /* BTST R,i - 6 cycles - Flags affected: -Z-0---- */
+ ARG_RR;
+ cpustate->PS1 = cpustate->PS1 & ~ FLAG_V;
+ if ( ( sm85cpu_mem_readbyte( cpustate, r2 ) & r1 ) == 0x00 ) {
+ cpustate->PS1 = cpustate->PS1 | FLAG_Z;
+ } else {
+ cpustate->PS1 = cpustate->PS1 & ( ~ FLAG_Z );
+ }
+ mycycles += 6;
+ break;
+case 0x30: /* CMP r,@rr / CMP r,(rr)+ / CMP r,@ww / CMP r,ww(rr) / CMP r,-(rr) - 8,13,11,15,13 cycles - Flags affected: CZSV---- */
+ ARG_rmw;
+ OP_CMP8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, s2 ) );
+ switch( r2 & 0xC0 ) {
+ case 0x00: mycycles += 8; break;
+ case 0x40: mycycles += 13; break;
+ case 0x80: mycycles += ( ( r2 & 0x07 ) ? 11 : 15 ); break;
+ case 0xC0: mycycles += 13; break;
+ }
+ break;
+case 0x31: /* ADD r,@rr / ADD r,(rr)+ / ADD r,@ww / ADD r,ww(rr) / ADD r,-(rr) - 8,13,11,15,13 cycles - Flags affected: CZSV0H-- */
+ ARG_rmw;
+ OP_ADD8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, s2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ switch( r2 & 0xC0 ) {
+ case 0x00: mycycles += 8; break;
+ case 0x40: mycycles += 13; break;
+ case 0x80: mycycles += ( ( r2 & 0x07 ) ? 11 : 15 ); break;
+ case 0xC0: mycycles += 13; break;
+ }
+ break;
+case 0x32: /* SUB r,@rr / SUB r,(rr)+ / SUB r,@ww / SUB r,ww(rr) / SUB r,-(rr) - 8,13,11,15,13 cycles - Flags affected: CZSV1H-- */
+ ARG_rmw;
+ OP_SUB8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, s2 ) );
+ switch( r2 & 0xC0 ) {
+ case 0x00: mycycles += 8; break;
+ case 0x40: mycycles += 13; break;
+ case 0x80: mycycles += ( ( r2 & 0x07 ) ? 11 : 15 ); break;
+ case 0xC0: mycycles += 13; break;
+ }
+ break;
+case 0x33: /* ADC r,@rr / ADC r,(rr)+ / ADC r,@ww / ADC r,ww(rr) / ADC r,-(rr) - 8,13,11,15,13 cycles - Flags affected: CZSV0H-- */
+ ARG_rmw;
+ OP_ADC8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, s2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ switch( r2 & 0xC0 ) {
+ case 0x00: mycycles += 8; break;
+ case 0x40: mycycles += 13; break;
+ case 0x80: mycycles += ( ( r2 & 0x07 ) ? 11 : 15 ); break;
+ case 0xC0: mycycles += 13; break;
+ }
+ break;
+case 0x34: /* SBC r,@rr / SBC r,(rr)+ / SBC r,@ww / SBC r,ww(rr) / SBC r,-(rr) - 8,13,11,15,13 cycles - Flags affected: CZSV1H-- */
+ ARG_rmw;
+ OP_SBC8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, s2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ switch( r2 & 0xC0 ) {
+ case 0x00: mycycles += 8; break;
+ case 0x40: mycycles += 13; break;
+ case 0x80: mycycles += ( ( r2 & 0x07 ) ? 11 : 15 ); break;
+ case 0xC0: mycycles += 13; break;
+ }
+ break;
+case 0x35: /* AND r,@rr / AND r,(rr)+ / AND r,@ww / AND r,ww(rr) / AND r,-(rr) - 8,13,11,15,13 cycles - Flags affected: -ZS0---- */
+ ARG_rmw;
+ OP_AND8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, s2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ switch( r2 & 0xC0 ) {
+ case 0x00: mycycles += 8; break;
+ case 0x40: mycycles += 13; break;
+ case 0x80: mycycles += ( ( r2 & 0x07 ) ? 11 : 15 ); break;
+ case 0xC0: mycycles += 13; break;
+ }
+ break;
+case 0x36: /* OR r,@rr / OR r,(rr)+ / OR r,@ww / OR r,ww(rr) / OR r,-(rr) - 8,13,11,15,13 cycles - Flags affected: -ZS0---- */
+ ARG_rmw;
+ OP_OR8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, s2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ switch( r2 & 0xC0 ) {
+ case 0x00: mycycles += 8; break;
+ case 0x40: mycycles += 13; break;
+ case 0x80: mycycles += ( ( r2 & 0x07 ) ? 11 : 15 ); break;
+ case 0xC0: mycycles += 13; break;
+ }
+ break;
+case 0x37: /* XOR? r,@rr / XOR r,(rr)+ / XOR r,@ww / XOR r,ww(rr) / XOR r,-(rr) - 8,13,11,15,13 cycles - Flagsaffected: -ZS0---- */
+ ARG_rmw;
+ OP_XOR8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, s2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ switch( r2 & 0xC0 ) {
+ case 0x00: mycycles += 8; break;
+ case 0x40: mycycles += 13; break;
+ case 0x80: mycycles += ( ( r2 & 0x07 ) ? 11 : 15 ); break;
+ case 0xC0: mycycles += 13; break;
+ }
+ break;
+case 0x38: /* MOV r,@rr / MOV r,(rr)+ / MOV r,@ww / MOV r,ww(rr) / MOV r,-(rr) - 8,13,11,15,13 cycles - Flags affected: -------- */
+ ARG_rmw;
+ sm85cpu_mem_writebyte( cpustate, r1, sm85cpu_mem_readbyte( cpustate, s2 ) );
+ switch( r2 & 0xC0 ) {
+ case 0x00: mycycles += 8; break;
+ case 0x40: mycycles += 13; break;
+ case 0x80: mycycles += ( ( r2 & 0x07 ) ? 11 : 15 ); break;
+ case 0xC0: mycycles += 13; break;
+ }
+ break;
+case 0x39: /* MOV @rr,r / MOV (rr)+,r / MOV @ww,r / MOV ww(rr),r / MOV -(rr),r - 8,13,11,15,13 cycles - Flags affected: -------- */
+ ARG_rmw;
+ sm85cpu_mem_writebyte( cpustate, s2, sm85cpu_mem_readbyte( cpustate, r1 ) );
+ switch( r2 & 0xC0 ) {
+ case 0x00: mycycles += 8; break;
+ case 0x40: mycycles += 13; break;
+ case 0x80: mycycles += ( ( r2 & 0x07 ) ? 11 : 15 ); break;
+ case 0xC0: mycycles += 13; break;
+ }
+ break;
+case 0x3A: /* MOVW rr,@rr / MOV rr,(rr)+ / MOV rr,@ww / MOV rr,ww(rr) / MOV rr,-(rr) - 11,16,14,18,16 cycles - Flags affected: -------- */
+ ARG_smw;
+ sm85cpu_mem_writeword( cpustate, r1, sm85cpu_mem_readword( cpustate, s2 ) );
+ switch( r2 & 0xC0 ) {
+ case 0x00: mycycles += 11; break;
+ case 0x40: mycycles += 16; break;
+ case 0x80: mycycles += ( ( r2 & 0x07 ) ? 18 : 14 ); break;
+ case 0xC0: mycycles += 16; break;
+ }
+ break;
+case 0x3B: /* MOVW @rr,rr / MOV (rr)+,rr / MOV @ww,rr / MOV ww(rr),rr / MOV -(rr),rr - 11,16,14,18,16 cycles - Flags affected: -------- */
+ ARG_smw;
+ sm85cpu_mem_writeword( cpustate, s2, sm85cpu_mem_readword( cpustate, r1 ) );
+ switch( r2 & 0xC0 ) {
+ case 0x00: mycycles += 11; break;
+ case 0x40: mycycles += 16; break;
+ case 0x80: mycycles += ( ( r2 & 0x07 ) ? 18 : 14 ); break;
+ case 0xC0: mycycles += 16; break;
+ }
+ break;
+case 0x3C: /* MOVW RRr,RRs - 7 cycles - Flags affected: -------- */
+ ARG_ss;
+ sm85cpu_mem_writeword( cpustate, r1, sm85cpu_mem_readword( cpustate, r2 ) );
+ mycycles += 7;
+ break;
+case 0x3D: /* unk3D DM??? 3D 0E -> DM R0Eh ?? - 4,4 cycles */
+logerror( "%04X: unk%02x\n", cpustate->PC-1,op );
+ mycycles += 4;
+ break;
+case 0x3E: /* JMP RRr/@ww/ww(RRr) - 7/15/19 cycles - Flags affected: -------- */
+ ARG_2;
+ cpustate->PC = s2;
+ switch( r1 & 0xc0 ) {
+ case 0x00: mycycles += 7; break;
+ case 0x40: mycycles += ( ( r1 & 0x38 ) ? 19 : 15 ); break;
+ default: mycycles += 4;
+ }
+ break;
+case 0x3F: /* CALL RRr/@ww/ww(RRr) - 11,14/22,19/26,23 cycles - Flags affected: -------- */
+ ARG_2;
+ PUSH8( cpustate->PC & 0xFF );
+ PUSH8( cpustate->PC >> 8 );
+ cpustate->PC = s2;
+ switch( r1 & 0xc0 ) {
+ case 0x00: mycycles += ( ( cpustate->SYS & 0x40 ) ? 14 : 11 ); break;
+ case 0x40: mycycles += ( ( r1 & 0x38 ) ? ( ( cpustate->SYS & 0x40 ) ? 26 : 23 ) : ( ( cpustate->SYS & 0x40 ) ? 22 : 19 ) );break;
+ default: mycycles += 4;
+ }
+ break;
+case 0x40: /* CMP Rr,Rs - 6 cycles - Flags affected: CZSV---- */
+ ARG_RR;
+ OP_CMP8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, r2 ) );
+ mycycles += 6;
+ break;
+case 0x41: /* ADD Rr,Rs - 6 cycles - Flags affected: CZSV0H-- */
+ ARG_RR;
+ OP_ADD8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, r2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 6;
+ break;
+case 0x42: /* SUB Rr,Rs - 6 cycles - Flags affected: CZSV1H-- */
+ ARG_RR;
+ OP_SUB8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, r2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 6;
+ break;
+case 0x43: /* ADC Rr,Rs - 6 cycles - Flags affected: CZSV0H-- */
+ ARG_RR;
+ OP_ADC8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, r2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 6;
+ break;
+case 0x44: /* SBC Rr,Rs - 6 cycles - Flags affected: CZSV1H-- */
+ ARG_RR;
+ OP_SBC8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, r2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 6;
+ break;
+case 0x45: /* AND Rr,Rs - 6 cycles - Flags affected: -ZS0---- */
+ ARG_RR;
+ OP_AND8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, r2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 6;
+ break;
+case 0x46: /* OR Rr,Rs - 6 cycles - Flags affected: -ZS0---- */
+ ARG_RR;
+ OP_OR8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, r2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 6;
+ break;
+case 0x47: /* XOR Rr,Rs - 6 cycles - Flags affected: -ZS0---- */
+ ARG_RR;
+ OP_XOR8( sm85cpu_mem_readbyte( cpustate, r1 ), sm85cpu_mem_readbyte( cpustate, r2 ) );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 6;
+ break;
+case 0x48: /* MOV Rr,Rs - 6 cycles - Flags affected: -------- */
+ ARG_RR;
+ sm85cpu_mem_writebyte( cpustate, r1, sm85cpu_mem_readbyte( cpustate, r2 ) );
+ mycycles += 6;
+ break;
+case 0x49: /* CALL ad16 - 12,10 - Flags affected: -------- */
+ ARG_ad16;
+ PUSH8( cpustate->PC & 0xFF );
+ PUSH8( cpustate->PC >> 8 );
+ cpustate->PC = s2;
+ mycycles += ( ( cpustate->SYS & 0x40 ) ? 12 : 10 );
+ break;
+case 0x4A: /* MOVW RRr,RRs - 8 cycles - Flags affected: -------- */
+ ARG_RR;
+ sm85cpu_mem_writeword( cpustate, r1, sm85cpu_mem_readword( cpustate, r2 ) );
+ mycycles += 8;
+ break;
+case 0x4B: /* MOVW RRr,ww - 9 cycles - Flags affected: -------- */
+ ARG_Sw;
+ sm85cpu_mem_writeword( cpustate, r1, s2 );
+ mycycles += 9;
+ break;
+case 0x4C: /* MULT Rrr,Rs - 24 cycles - Flags affected: -Z-0---- */
+ ARG_RR;
+ res = sm85cpu_mem_readword( cpustate, r1 ) * sm85cpu_mem_readbyte( cpustate, r2 );
+ sm85cpu_mem_writeword( cpustate, r1, res & 0xFFFF );
+ cpustate->PS1 = cpustate->PS1 & ~ ( FLAG_Z | FLAG_V );
+ cpustate->PS1 |= ( ( res & 0xFFFF ) == 0x00 ? FLAG_Z : 0 );
+ mycycles += 24;
+ break;
+case 0x4D: /* MULT RRr,i - 24 cycles - Flags affected: -Z-0---- */
+ ARG_iR;
+ res = sm85cpu_mem_readbyte( cpustate, r1 + 1 ) * r2;
+ sm85cpu_mem_writeword( cpustate, r1, res & 0xFFFF );
+ cpustate->PS1 = cpustate->PS1 & ~ ( FLAG_Z | FLAG_V );
+ cpustate->PS1 |= ( ( res & 0xFFFF ) == 0x00 ? FLAG_Z : 0 );
+ mycycles += 24;
+ break;
+case 0x4E: /* BMOV Rr,#b,BF/BF,Rr,#b - 6 cycles - Flags affected: --------/-Z-0--B- */
+ r2 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ );
+ r1 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ );
+ switch( r2 & 0xC0 ) {
+ case 0x00:
+ res = sm85cpu_mem_readbyte( cpustate, r1 );
+ if ( cpustate->PS1 & FLAG_B ) {
+ res = res | ( 1 << ( r2 & 0x07 ) );
+ } else {
+ res = res & ~( 1 << ( r2 & 0x07 ) );
+ }
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ break;
+ case 0x40:
+ cpustate->PS1 = cpustate->PS1 & ( FLAG_C | FLAG_S | FLAG_D | FLAG_H | FLAG_I );
+ if ( sm85cpu_mem_readbyte( cpustate, r1 ) & ( 1 << ( r2 & 0x07 ) ) ) {
+ cpustate->PS1 = cpustate->PS1 | FLAG_B;
+ } else {
+ cpustate->PS1 = cpustate->PS1 | FLAG_Z;
+ }
+ break;
+ case 0x80:
+ case 0xC0:
+ break;
+ }
+ mycycles += 6;
+ break;
+case 0x4F: /* BCMP/BAND/BOR/BXOR BF,Rr,#b - 6 cycles - Flags affected: -Z-0---- / -Z-0--B- */
+ r2 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ );
+ r1 = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ );
+ s1 = sm85cpu_mem_readbyte( cpustate, r1 ) & ( 1 << ( r2 & 0x07 ) );
+ s2 = ( ( cpustate->PS1 & FLAG_B ) >> 1 ) << ( r2 & 0x07 );
+ switch( r2 & 0xC0 ) {
+ case 0x00:
+ cpustate->PS1 = cpustate->PS1 & ~ ( FLAG_Z | FLAG_V );
+ if ( s1 == s2 ) {
+ cpustate->PS1 = cpustate->PS1 | FLAG_Z;
+ }
+ break;
+ case 0x40:
+ cpustate->PS1 = cpustate->PS1 & ~ ( FLAG_Z | FLAG_V | FLAG_B );
+ cpustate->PS1 = cpustate->PS1 | ( ( s1 & s2 ) ? FLAG_B : FLAG_Z );
+ break;
+ case 0x80:
+ cpustate->PS1 = cpustate->PS1 & ~ ( FLAG_Z | FLAG_V | FLAG_B );
+ cpustate->PS1 = cpustate->PS1 | ( ( s1 | s2 ) ? FLAG_B : FLAG_Z );
+ break;
+ case 0xC0:
+ cpustate->PS1 = cpustate->PS1 & ~ ( FLAG_Z | FLAG_V | FLAG_B );
+ cpustate->PS1 = cpustate->PS1 | ( ( s1 ^ s2 ) ? FLAG_B : FLAG_Z );
+ break;
+ }
+ mycycles += 6;
+ break;
+case 0x50: /* CMP Rr,i - 6 cycles - Flags affected: CZSV---- */
+ ARG_iR;
+ OP_CMP8( sm85cpu_mem_readbyte( cpustate, r1 ), r2 );
+ mycycles += 6;
+ break;
+case 0x51: /* ADD Rr,i - 6 cycles - Flags affected: CZSV0H-- */
+ ARG_iR;
+ OP_ADD8( sm85cpu_mem_readbyte( cpustate, r1 ), r2 );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 6;
+ break;
+case 0x52: /* SUB Rr,i - 6 cycles - Flags affected: CZSV1H-- */
+ ARG_iR;
+ OP_SUB8( sm85cpu_mem_readbyte( cpustate, r1 ), r2 );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 6;
+ break;
+case 0x53: /* ADC Rr,i - 6 cycles - Flags affected: CZSV0H-- */
+ ARG_iR;
+ OP_ADC8( sm85cpu_mem_readbyte( cpustate, r1 ), r2 );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 6;
+ break;
+case 0x54: /* SBC Rr,i - 6 cycles - Flags affected: CZSV1H-- */
+ ARG_iR;
+ OP_SBC8( sm85cpu_mem_readbyte( cpustate, r1 ), r2 );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 6;
+ break;
+case 0x55: /* AND Rr,i - 6 cycles - Flags affected: -ZS0---- */
+ ARG_iR;
+ OP_AND8( sm85cpu_mem_readbyte( cpustate, r1 ), r2 );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 6;
+ break;
+case 0x56: /* OR Rr,i - 6 cycles - Flags affected: -ZS0---- */
+ ARG_iR;
+ OP_OR8( sm85cpu_mem_readbyte( cpustate, r1 ), r2 );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 6;
+ break;
+case 0x57: /* XOR Rr,i - 6 cycles - Flags affected: -ZS0---- */
+ ARG_iR;
+ OP_XOR8( sm85cpu_mem_readbyte( cpustate, r1 ), r2 );
+ sm85cpu_mem_writebyte( cpustate, r1, res & 0xFF );
+ mycycles += 6;
+ break;
+case 0x58: /* MOV Rr,i - 6 cycles - Flags affected: -------- */
+ ARG_iR;
+ sm85cpu_mem_writebyte( cpustate, r1, r2 );
+ mycycles += 6;
+ break;
+case 0x59: /* Invalid - 2? cycles - Flags affected: --------? */
+ logerror( "%04X: 59h: Invalid instruction\n", cpustate->PC-1 );
+ mycycles += 2;
+ break;
+case 0x5A: /* unk5A - 7,8,12,9,8 cycles */
+logerror( "%04X: unk%02x\n", cpustate->PC-1,op );
+ ARG_ad16;
+ mycycles += 7;
+ break;
+case 0x5B: /* unk5B - 6,7,11,8,7 cycles */
+logerror( "%04X: unk%02x\n", cpustate->PC-1,op );
+/* NOTE: This unknown command is used in several carts, the code below allows those carts to boot */
+ ARG_iR;
+ r1 = r2 & 7;
+ res = sm85cpu_mem_readbyte( cpustate, r1 ) + 1;
+ sm85cpu_mem_writebyte( cpustate, r1, res );
+ mycycles += 6;
+ break;
+case 0x5C: /* DIV RRr,RRs - 47 cycles - Flags affected: -Z-V---- */
+ /* lower 8 bits of RRs is used to divide */
+ /* remainder in stored upper 8 bits of RRs */
+logerror( "%04X: DIV RRr,Rs!\n", cpustate->PC-1 );
+ ARG_RR;
+ cpustate->PS1 = cpustate->PS1 & ~ ( FLAG_Z | FLAG_V );
+ s1 = sm85cpu_mem_readbyte( cpustate, r2 + 1 );
+ if ( s1 ) {
+ UINT16 div = sm85cpu_mem_readword( cpustate, r1 );
+ res = div / s1;
+ sm85cpu_mem_writebyte( cpustate, r2, div % s1 );
+ sm85cpu_mem_writeword( cpustate, r1, res );
+ cpustate->PS1 = cpustate->PS1 | ( ( res == 0 ) ? FLAG_Z : 0 );
+ } else {
+ cpustate->PS1 = cpustate->PS1 | FLAG_V;
+ }
+ mycycles += 47;
+ break;
+case 0x5D: /* DIV RRr,i - 44 cycles - Flags affected: -Z-V---- */
+logerror( "%04X: DIV RRr,i!\n", cpustate->PC-1 );
+ ARG_iR;
+ cpustate->PS1 = cpustate->PS1 & ~ ( FLAG_Z | FLAG_V );
+ if ( r2 ) {
+ res = sm85cpu_mem_readword( cpustate, r1 ) / r2;
+ sm85cpu_mem_writeword( cpustate, r1, res );
+ cpustate->PS1 = cpustate->PS1 | ( ( res == 0 ) ? FLAG_Z : 0 );
+ } else {
+ cpustate->PS1 = cpustate->PS1 | FLAG_V;
+ }
+ mycycles += 44;
+ break;
+case 0x5E: /* MOVM Rr,i,Rs - 9 cycles - Flags affected: -------- */
+ ARG_RiR;
+ sm85cpu_mem_writebyte( cpustate, r1, ( sm85cpu_mem_readbyte( cpustate, r1 ) & d1 ) | sm85cpu_mem_readbyte( cpustate, r2 ) );
+ mycycles += 9;
+ break;
+case 0x5F: /* MOVM Rr,i,j - 8 cycles - Flags affected: -------- */
+ ARG_Rii;
+ sm85cpu_mem_writebyte( cpustate, r1, ( sm85cpu_mem_readbyte( cpustate, r1 ) & d1 ) | r2 );
+ mycycles += 8;
+ break;
+case 0x60: /* CMPW RRr,RRs - 9 cycles - Flags affected: CZSV---- */
+ ARG_RR;
+ OP_CMP16( sm85cpu_mem_readword( cpustate, r1 ), sm85cpu_mem_readword( cpustate, r2 ) );
+ mycycles += 9;
+ break;
+case 0x61: /* ADDW RRr,RRs - 10 cycles - Flags affected: CZSV0H-- */
+ ARG_RR;
+ OP_ADD16( sm85cpu_mem_readword( cpustate, r1 ), sm85cpu_mem_readword( cpustate, r2 ) );
+ sm85cpu_mem_writeword( cpustate, r1, res & 0xFFFF );
+ mycycles += 10;
+ break;
+case 0x62: /* SUBW RRr,RRs - 10 cycles - Flags affected: CZSV1H-- */
+ ARG_RR;
+ OP_SUB16( sm85cpu_mem_readword( cpustate, r1 ), sm85cpu_mem_readword( cpustate, r2 ) );
+ sm85cpu_mem_writeword( cpustate, r1, res & 0xFFFF );
+ mycycles += 10;
+ break;
+case 0x63: /* ADCW RRr,RRs - 10 cycles - Flags affected: CZSV0H-- */
+ ARG_RR;
+ OP_ADC16( sm85cpu_mem_readword( cpustate, r1 ), sm85cpu_mem_readword( cpustate, r2 ) );
+ sm85cpu_mem_writeword( cpustate, r1, res & 0xFFFF );
+ mycycles += 10;
+ break;
+case 0x64: /* SBCW RRr,RRs - 10 cycles - Flags affected: CZSV1H-- */
+ ARG_RR;
+ OP_SBC16( sm85cpu_mem_readword( cpustate, r1 ), sm85cpu_mem_readword( cpustate, r2 ) );
+ sm85cpu_mem_writeword( cpustate, r1, res & 0xFFFF );
+ mycycles += 10;
+ break;
+case 0x65: /* ANDW RRr,RRs - 14 cycles - Flags affected: -Z-0---- */
+ ARG_RR;
+ OP_AND16( sm85cpu_mem_readword( cpustate, r1 ), sm85cpu_mem_readword( cpustate, r2 ) );
+ sm85cpu_mem_writeword( cpustate, r1, res & 0xFFFF );
+ mycycles += 14;
+ break;
+case 0x66: /* ORW RRr,RRs - 14 cycles - Flags affected: -Z-0---- */
+ ARG_RR;
+ OP_OR16( sm85cpu_mem_readword( cpustate, r1 ), sm85cpu_mem_readword( cpustate, r2 ) );
+ sm85cpu_mem_writeword( cpustate, r1, res & 0xFFFF );
+ mycycles += 14;
+ break;
+case 0x67: /* XORW RRr,RRs - 14 cycles - Flags affected: -Z-0---- */
+ ARG_RR;
+ OP_XOR16( sm85cpu_mem_readword( cpustate, r1 ), sm85cpu_mem_readword( cpustate, r2 ) );
+ sm85cpu_mem_writeword( cpustate, r1, res & 0xFFFF );
+ mycycles += 14;
+ break;
+case 0x68: /* CMPW RRr,w - 9 cycles - Flags affected: CZSV---- */
+ ARG_Sw;
+ OP_CMP16( sm85cpu_mem_readword( cpustate, r1 ), s2 );
+ mycycles += 9;
+ break;
+case 0x69: /* ADDW RRr,w - 10 cycles - Flags affected: CZSV0H-- */
+ ARG_Sw;
+ OP_ADD16( sm85cpu_mem_readword( cpustate, r1 ), s2 );
+ sm85cpu_mem_writeword( cpustate, r1, res & 0xFFFF );
+ mycycles += 10;
+ break;
+case 0x6A: /* SUBW RRr,w - 10 cycles - Flags affected: CZSV1H-- */
+ ARG_Sw;
+ OP_SUB16( sm85cpu_mem_readword( cpustate, r1 ), s2 );
+ sm85cpu_mem_writeword( cpustate, r1, res & 0xFFFF );
+ mycycles += 10;
+ break;
+case 0x6B: /* ADCW RRr,w - 10 cycles - Flags affected: CZSV0H-- */
+ ARG_Sw;
+ OP_ADC16( sm85cpu_mem_readword( cpustate, r1 ), s2 );
+ sm85cpu_mem_writeword( cpustate, r1, res & 0xFFFF );
+ mycycles += 10;
+ break;
+case 0x6C: /* SBCW RRr,w - 10 cycles - Flags affected: CZSV1H-- */
+ ARG_Sw;
+ OP_SBC16( sm85cpu_mem_readword( cpustate, r1 ), s2 );
+ sm85cpu_mem_writeword( cpustate, r1, res & 0xFFFF );
+ mycycles += 10;
+ break;
+case 0x6D: /* ANDW RRr,w - 13 cycles - Flags affected: -Z-0---- */
+ ARG_Sw;
+ OP_AND16( sm85cpu_mem_readword( cpustate, r1 ), s2 );
+ sm85cpu_mem_writeword( cpustate, r1, res & 0xFFFF );
+ mycycles += 13;
+ break;
+case 0x6E: /* ORW RRr,w - 13 cycles - Flags affected: -Z-0---- */
+ ARG_Sw;
+ OP_OR16( sm85cpu_mem_readword( cpustate, r1 ), s2 );
+ sm85cpu_mem_writeword( cpustate, r1, res & 0xFFFF );
+ mycycles += 13;
+ break;
+case 0x6F: /* XORW RRr,w - 13 cycles - Flags affected: -Z-0---- */
+ ARG_Sw;
+ OP_XOR16( sm85cpu_mem_readword( cpustate, r1 ), s2 );
+ sm85cpu_mem_writeword( cpustate, r1, res & 0xFFFF);
+ mycycles += 13;
+ break;
+case 0x70: /* DBNZ r,rel8 - 10,6 cycles - Flags affected: -------- */
+case 0x71:
+case 0x72:
+case 0x73:
+case 0x74:
+case 0x75:
+case 0x76:
+case 0x77:
+ ARG_d8;
+ r1 = sm85cpu_mem_readbyte( cpustate, op & 0x07 );
+ r1--;
+ sm85cpu_mem_writebyte( cpustate, op & 0x07, r1 );
+ if ( r1 != 0 ) {
+ cpustate->PC = s2;
+ mycycles += 10;
+ } else {
+ mycycles += 6;
+ }
+ break;
+case 0x78: /* MOVW RRx,w - 6 cycles - Flags affected: -------- */
+case 0x79:
+case 0x7A:
+case 0x7B:
+case 0x7C:
+case 0x7D:
+case 0x7E:
+case 0x7F:
+ ARG_rrw;
+ sm85cpu_mem_writeword( cpustate, r1, s2 );
+ mycycles += 6;
+ break;
+case 0x80: /* BBC R,#b,d8 - 10,6 cycles - Flags affected: -------- */
+case 0x81:
+case 0x82:
+case 0x83:
+case 0x84:
+case 0x85:
+case 0x86:
+case 0x87:
+ ARG_Rbr;
+ if ( ( sm85cpu_mem_readbyte( cpustate, r1 ) & ( 1 << (op & 0x07) ) ) == 0 ) {
+ cpustate->PC = s2;
+ mycycles += 10;
+ } else {
+ mycycles += 6;
+ }
+ break;
+case 0x88: /* BBS R,#b,d8 - 10,6 cycles - Flags affected: -------- */
+case 0x89:
+case 0x8A:
+case 0x8B:
+case 0x8C:
+case 0x8D:
+case 0x8E:
+case 0x8F:
+ ARG_Rbr;
+ if ( ( sm85cpu_mem_readbyte( cpustate, r1 ) & ( 1 << (op & 0x07) ) ) ) {
+ cpustate->PC = s2;
+ mycycles += 10;
+ } else {
+ mycycles += 6;
+ }
+ break;
+case 0x90: /* JMP cc,ad16 - 6 cycles - Flags affected: -------- */
+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:
+ ARG_ad16;
+ CHECK_CC;
+ if ( res ) {
+ cpustate->PC = s2;
+ }
+ mycycles += 6;
+ break;
+case 0xA0: /* BCLR R,#b - 4 cycles - Flags affected: -------- */
+case 0xA1:
+case 0xA2:
+case 0xA3:
+case 0xA4:
+case 0xA5:
+case 0xA6:
+case 0xA7:
+ ARG_R;
+ sm85cpu_mem_writebyte( cpustate, r1, sm85cpu_mem_readbyte( cpustate, r1 ) & ~ ( 1 << (op & 0x07) ) );
+ mycycles += 4;
+ break;
+case 0xA8: /* BSET R,#b - 4 cycles - Flags affected: -------- */
+case 0xA9:
+case 0xAA:
+case 0xAB:
+case 0xAC:
+case 0xAD:
+case 0xAE:
+case 0xAF:
+ ARG_R;
+ sm85cpu_mem_writebyte( cpustate, r1, sm85cpu_mem_readbyte( cpustate, r1 ) | ( 1 << (op & 0x07) ) );
+ mycycles += 4;
+ break;
+case 0xB0: /* MOV Rx,Rr - 4 cycles - Flags affected: -------- */
+case 0xB1:
+case 0xB2:
+case 0xB3:
+case 0xB4:
+case 0xB5:
+case 0xB6:
+case 0xB7:
+ ARG_rR;
+ sm85cpu_mem_writebyte( cpustate, r1, sm85cpu_mem_readbyte( cpustate, r2 ) );
+ mycycles += 4;
+ break;
+case 0xB8: /* MOV Rr,Rx - 4 cycles - Flags affected: -------- */
+case 0xB9:
+case 0xBA:
+case 0xBB:
+case 0xBC:
+case 0xBD:
+case 0xBE:
+case 0xBF:
+ ARG_rR;
+ sm85cpu_mem_writebyte( cpustate, r2, sm85cpu_mem_readbyte( cpustate, r1 ) );
+ mycycles += 4;
+ break;
+case 0xC0: /* MOV Rx,i - 4 cycles - Flags affected: -------- */
+case 0xC1:
+case 0xC2:
+case 0xC3:
+case 0xC4:
+case 0xC5:
+case 0xC6:
+case 0xC7:
+ ARG_ri;
+ sm85cpu_mem_writebyte( cpustate, r1, r2 );
+ mycycles += 4;
+ break;
+case 0xC8: /* MOV IE0/IE1/IR0/IR1/P0/P1/P2/P3,i - 4 cycles - Flags affected: -------- */
+case 0xC9:
+case 0xCA:
+case 0xCB:
+case 0xCC:
+case 0xCD:
+case 0xCE:
+case 0xCF:
+ ARG_pi;
+ sm85cpu_mem_writebyte( cpustate, r1, r2 );
+ mycycles += 4;
+ break;
+case 0xD0: /* BR cc,rel8 - 8,4 cycles - Flags affected: -------- */
+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:
+ ARG_d8;
+ CHECK_CC;
+ if ( res ) {
+ cpustate->PC = s2;
+ mycycles += 8;
+ } else {
+ mycycles += 4;
+ }
+ break;
+case 0xE0: /* CALS - 12,9 cycles */
+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: /* CALS 1xWW - 12,9 cycles - Flags affected: -------- */
+ ARG_R;
+ s2 = 0x1000 + ( ( op & 0x0F ) << 8 ) + r1;
+ PUSH8( cpustate->PC & 0xFF );
+ PUSH8( cpustate->PC >> 8 );
+ cpustate->PC = s2;
+ mycycles += ( ( cpustate->SYS & 0x40 ) ? 12 : 9 );
+ break;
+case 0xF0: /* STOP - 2 cycles - Flags affected: -------- */
+ mycycles += 2;
+ if ( cpustate->clock_changed ) {
+ /* TODO: Set system clock divider */
+ /* TODO: Add a bunch of additional cycles */
+ cpustate->clock_changed = 0;
+ }
+ break;
+case 0xF1: /* HALT - 2 cycles - Flags affected: -------- */
+ cpustate->halted = 1;
+ mycycles += 2;
+ break;
+case 0xF2: /* Invalid - 2? cycles - Flags affected: --------? */
+case 0xF3:
+case 0xF4:
+case 0xF5:
+case 0xF6:
+case 0xF7:
+ mycycles += 2;
+ break;
+case 0xF8: /* RET - 10,8 cycles - Flags affected: -------- */
+ POP8( r1 );
+ POP8( r2 );
+ cpustate->PC = ( r1 << 8 ) | r2;
+ mycycles += ( ( cpustate->SYS & 0x40 ) ? 10 : 8 );
+ break;
+case 0xF9: /* IRET - 12,10 cycles - Flags affected: CZSVDHBI */
+ POP8( cpustate->PS1 );
+ POP8( r1 );
+ POP8( r2 );
+ cpustate->PC = ( r1 << 8 ) | r2;
+ mycycles += ( ( cpustate->SYS & 0x40 ) ? 12 : 10 );
+ break;
+case 0xFA: /* CLRC - 2 cycles - Flags affected: C------- */
+ cpustate->PS1 = cpustate->PS1 & ~ ( FLAG_C );
+ mycycles += 2;
+ break;
+case 0xFB: /* COMC - 2 cycles - Flags affected: C------- */
+ cpustate->PS1 = cpustate->PS1 ^ FLAG_C;
+ mycycles += 2;
+ break;
+case 0xFC: /* SETC - 2 cycles - Flags affected: C------- */
+ cpustate->PS1 = cpustate->PS1 | FLAG_C;
+ mycycles += 2;
+ break;
+case 0xFD: /* EI - 2 cycles - Flags affected: -------I */
+ cpustate->PS1 = cpustate->PS1 | FLAG_I;
+ mycycles += 2;
+ break;
+case 0xFE: /* DI - 2 cycles - Flags affected: -------I */
+ cpustate->PS1 = cpustate->PS1 & ~ ( FLAG_I );
+ mycycles += 2;
+ break;
+case 0xFF: /* NOP - 2 cycles - Flags affected: -------- */
+ mycycles += 2;
+ break;
+default:
+ mycycles += 2;
+ break;
+
diff --git a/trunk/src/emu/cpu/spc700/spc700.c b/trunk/src/emu/cpu/spc700/spc700.c
new file mode 100644
index 00000000000..9256361aa36
--- /dev/null
+++ b/trunk/src/emu/cpu/spc700/spc700.c
@@ -0,0 +1,1756 @@
+/* ======================================================================== */
+/* =============================== COPYRIGHT ============================== */
+/* ======================================================================== */
+/*
+
+ Sony/Nintendo SPC700 CPU Emulator
+
+ The SPC700 is 6502-based at heart but contains a lot of the extended
+ opcodes of the Mitsubishi 770 and 7700 series 65xxx-based MCUs, plus
+ a few special twists borrowed from the 68000.
+
+ It was designed by Sony's Ken Kutaragi, later the "father of the PlayStation".
+
+ Original emulation by Anthony Kruize and Lee Hammerton.
+ Substantially revised by R. Belmont.
+
+ Thanks to Anonymous, TRAC, Brad Martin, anomie, Blargg, and everyone
+ else on ZSNES Technical for probing the darker corners of the SNES
+ with test programs so we have a chance at getting things accurate.
+
+ MESS Bugzilla bugs:
+ - 804 ADC sets carry too late (FIXED)
+ - 805 ADDW/SUBW set V wrongly (FIXED)
+ - 806 BRK should modify PSW (FIXED)
+ - 807 DAA/DAS problem (FIXED)
+
+
+*/
+/* ======================================================================== */
+/* ================================= NOTES ================================ */
+/* ======================================================================== */
+/*
+
+snes mapped ports: f0-ff
+Address Function Register R/W When Reset Remarks
+
+00F0H (test) --- ------ Installed in sound-CPU
+00F1H Control W Control = "00-000"
+00F2H Register Add. R/W Indeterminate Installed in DSP
+00F3H Register Data R/W Indeterminate Installed in DSP
+00F4H Port-0 R/W Port0r = "00" Installed in sound-CPU
+ Port0w = "00"
+00F5H Port-1 R/W Port1r = "00" Installed in sound-CPU
+ Port1w = "00"
+00F6H Port-2 R/W Port2r = "00" Installed in sound-CPU
+ Port2w = "00"
+00F7H Port-3 R/W Port3r = "00" Installed in sound-CPU
+ Port3w = "00"
+00F8H ------ --- ---------- -------------------
+00F9H ------ --- ---------- -------------------
+00FAH Timer-0 W Indeterminate Installed in sound-CPU
+00FBH Timer-1 W Indeterminate Installed in sound-CPU
+00FCH Timer-2 W Indeterminate Installed in sound-CPU
+00FDH Counter-0 W Indeterminate Installed in sound-CPU
+00FEH Counter-1 W Indeterminate Installed in sound-CPU
+00FFH Counter-2 W Indeterminate Installed in sound-CPU
+
+*/
+/* ======================================================================== */
+/* ================================ INCLUDES ============================== */
+/* ======================================================================== */
+
+#include <limits.h>
+#include "emu.h"
+#include "debugger.h"
+#include "spc700.h"
+
+/* CPU Structure */
+typedef struct
+{
+ uint a; /* 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 flag_n; /* Negative Flag */
+ uint flag_z; /* Zero flag */
+ uint flag_v; /* Overflow Flag */
+ uint flag_p; /* Direct Page Flag */
+ uint flag_b; /* BRK Instruction Flag */
+ uint flag_h; /* Half-carry Flag */
+ uint flag_i; /* Interrupt Mask Flag */
+ uint flag_c; /* Carry Flag */
+ uint line_irq; /* Status of the IRQ line */
+ uint line_nmi; /* Status of the NMI line */
+ uint line_rst; /* Status of the RESET line */
+ uint ir; /* Instruction Register */
+ device_irq_callback int_ack;
+ legacy_cpu_device *device;
+ address_space *program;
+ uint stopped; /* stopped status */
+ int ICount;
+ uint source;
+ uint destination;
+ uint temp1, temp2, temp3;
+ short spc_int16;
+ int spc_int32;
+} spc700i_cpu;
+
+INLINE spc700i_cpu *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == SPC700);
+ return (spc700i_cpu *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/* ======================================================================== */
+/* ==================== ARCHITECTURE-DEPENDANT DEFINES ==================== */
+/* ======================================================================== */
+
+/* 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)
+
+/* ======================================================================== */
+/* ============================ GENERAL DEFINES =========================== */
+/* ======================================================================== */
+
+/* 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
+#define BIT_8 0x100
+
+/* Flag positions in Processor Status Register */
+#define FLAGPOS_N BIT_7 /* Negative */
+#define FLAGPOS_V BIT_6 /* Overflow */
+#define FLAGPOS_P BIT_5 /* Direct Page Selector */
+#define FLAGPOS_B BIT_4 /* Break */
+#define FLAGPOS_H BIT_3 /* Half-carry */
+#define FLAGPOS_I BIT_2 /* Interrupt */
+#define FLAGPOS_Z BIT_1 /* Zero */
+#define FLAGPOS_C BIT_0 /* Carry */
+
+#define NFLAG_SET FLAGPOS_N
+#define VFLAG_SET BIT_7
+#define PFLAG_SET BIT_8
+#define BFLAG_SET FLAGPOS_B
+#define HFLAG_SET BIT_3
+#define IFLAG_SET FLAGPOS_I
+#define ZFLAG_SET 0
+#define CFLAG_SET BIT_8
+#define NZFLAG_CLEAR 1
+#define VFLAG_CLEAR 0
+#define PFLAG_CLEAR 0
+#define BFLAG_CLEAR 0
+#define HFLAG_CLEAR 0
+#define IFLAG_CLEAR 0
+#define CFLAG_CLEAR 0
+
+#define NMI_SET 1
+#define NMI_CLEAR 0
+#define IRQ_SET IFLAG_CLEAR
+#define IRQ_CLEAR IFLAG_SET
+
+#define STACK_PAGE 0x100 /* Stack Page Offset */
+
+#define VECTOR_RST 0xfffe /* Reset */
+#define VECTOR_BRK 0xffde /* Break Instruction */
+#define VECTOR_IRQ 0xfffc /* IRQ ??? what is real vector? */
+#define VECTOR_NMI 0xfffa /* NMI ??? what is real vector? */
+
+#define REG_A cpustate->a /* Accumulator */
+#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_P cpustate->p /* Processor Status Register */
+#define FLAG_NZ cpustate->flag_n = cpustate->flag_z /* Negative Flag and inverted Zero flag */
+#define FLAG_N cpustate->flag_n /* Negative flag */
+#define FLAG_Z cpustate->flag_z /* Inverted Zero flag */
+#define FLAG_V cpustate->flag_v /* Overflow Flag */
+#define FLAG_P cpustate->flag_p /* Direct Page Flag */
+#define FLAG_B cpustate->flag_b /* BRK Instruction Flag */
+#define FLAG_H cpustate->flag_h /* Decimal Mode Flag */
+#define FLAG_I cpustate->flag_i /* Interrupt Mask Flag */
+#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 REG_IR cpustate->ir /* Instruction Register */
+#define INT_ACK cpustate->int_ack /* Interrupt Acknowledge function pointer */
+#define CLOCKS cpustate->ICount /* Clock cycles remaining */
+#define CPU_STOPPED cpustate->stopped /* Stopped status */
+
+#define SRC cpustate->source /* Source Operand */
+#define DST cpustate->destination /* Destination Operand */
+#define TMP1 cpustate->temp1 /* temporary result 1 */
+#define TMP2 cpustate->temp2 /* temporary result 2 */
+#define TMP3 cpustate->temp3 /* temporary result 3 */
+
+#define STOP_LEVEL_STOP 1
+#define STOP_LEVEL_SLEEP 2
+
+
+/* ======================================================================== */
+/* ============================ GENERAL MACROS ============================ */
+/* ======================================================================== */
+
+/* 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_AS_1() ((FLAG_C>>8)&1)
+#define CFLAG_AS_NOT_1() (!(FLAG_C&CFLAG_SET))
+
+#define NZFLAG_16(A) (((A)&0x7f) | (((A)>>1)&0x40) | (((A)>>8)&0xff))
+#define CFLAG_16(A) ((A)>>8)
+
+
+/* ======================================================================== */
+/* ================================= MAME ================================= */
+/* ======================================================================== */
+
+#define spc700_read_8(addr) cpustate->program->read_byte(addr)
+#define spc700_write_8(addr,data) cpustate->program->write_byte(addr,data)
+
+#define spc700_read_8_direct(A) spc700_read_8(A)
+#define spc700_write_8_direct(A, V) spc700_write_8(A, V)
+//#define spc700_read_instruction(A) memory_decrypted_read_byte(cpustate->program,A)
+//#define spc700_read_8_immediate(A) memory_raw_read_byte(cpustate->program,A)
+#define spc700_read_instruction(A) cpustate->program->read_byte(A)
+#define spc700_read_8_immediate(A) cpustate->program->read_byte(A)
+#define spc700_jumping(A)
+#define spc700_branching(A)
+
+
+
+/* ======================================================================== */
+/* ============================ UTILITY MACROS ============================ */
+/* ======================================================================== */
+
+/* Use up clock cycles */
+#define CLK(A) CLOCKS -= (A)
+#define CLK_ALL() CLOCKS = 0
+
+#define BREAKOUT break
+
+INLINE uint read_8_normal(spc700i_cpu *cpustate, uint address)
+{
+ address = MAKE_UINT_16(address);
+ return spc700_read_8(address);
+}
+
+INLINE uint read_8_immediate(spc700i_cpu *cpustate, uint address)
+{
+ address = MAKE_UINT_16(address);
+ return spc700_read_8_immediate(address);
+}
+
+#ifdef UNUSED_FUNCTION
+INLINE uint read_8_instruction(spc700i_cpu *cpustate, uint address)
+{
+ address = MAKE_UINT_16(address);
+ return spc700_read_instruction(address);
+}
+#endif
+
+INLINE uint read_8_direct(spc700i_cpu *cpustate, uint address)
+{
+ address = MAKE_UINT_8(address) | FLAG_P;
+ return spc700_read_8_direct(address);
+}
+
+INLINE void write_8_normal(spc700i_cpu *cpustate, uint address, uint value)
+{
+ address = MAKE_UINT_16(address);
+ value = MAKE_UINT_8(value);
+ spc700_write_8(address, value);
+}
+
+INLINE void write_8_direct(spc700i_cpu *cpustate, uint address, uint value)
+{
+ address = MAKE_UINT_8(address) | FLAG_P;
+ value = MAKE_UINT_8(value);
+ spc700_write_8_direct(address, value);
+}
+
+
+INLINE uint read_16_normal(spc700i_cpu *cpustate, uint address)
+{
+ return read_8_normal(cpustate, address) | (read_8_normal(cpustate, address+1)<<8);
+}
+
+INLINE uint read_16_immediate(spc700i_cpu *cpustate, uint address)
+{
+ return read_8_immediate(cpustate, address) | (read_8_immediate(cpustate, address+1)<<8);
+}
+
+INLINE uint read_16_direct(spc700i_cpu *cpustate, uint address)
+{
+ return read_8_direct(cpustate, address) | (read_8_direct(cpustate, address+1)<<8);
+}
+
+INLINE void write_16_direct(spc700i_cpu *cpustate, uint address, uint value)
+{
+ write_8_direct(cpustate, address, value);
+ write_8_direct(cpustate, address+1, value>>8);
+}
+
+/* Low level memory access macros */
+#define read_8_NORM(A) read_8_normal(cpustate, A)
+#define read_8_IMM(A) read_8_immediate(cpustate, A)
+#define read_8_ABS(A) read_8_normal(cpustate, A)
+#define read_8_ABX(A) read_8_normal(cpustate, A)
+#define read_8_ABY(A) read_8_normal(cpustate, A)
+#define read_8_AXI(A) read_8_normal(cpustate, A)
+#define read_8_DP(A) read_8_direct(cpustate, A)
+#define read_8_DPX(A) read_8_direct(cpustate, A)
+#define read_8_DPY(A) read_8_direct(cpustate, A)
+#define read_8_DPI(A) read_8_normal(cpustate, A)
+#define read_8_DXI(A) read_8_normal(cpustate, A)
+#define read_8_DIY(A) read_8_normal(cpustate, A)
+#define read_8_STK(A) read_8_normal(cpustate, A)
+#define read_8_XI(A) read_8_direct(cpustate, A)
+#define read_8_XII(A) read_8_direct(cpustate, A)
+#define read_8_YI(A) read_8_direct(cpustate, A)
+
+
+#define read_16_NORM(A) read_16_normal(cpustate, A)
+#define read_16_IMM(A) read_16_immediate(cpustate, A)
+#define read_16_ABS(A) read_16_absolute(cpustate, A)
+#define read_16_ABX(A) read_16_normal(cpustate, A)
+#define read_16_DP(A) read_16_direct(cpustate, A)
+#define read_16_DPX(A) read_16_direct(cpustate, A)
+#define read_16_DPY(A) read_16_direct(cpustate, A)
+#define read_16_DPI(A) read_16_normal(cpustate, A)
+#define read_16_VEC(A) read_16_normal(cpustate, A)
+#define read_16_XI(A) read_16_direct(cpustate, A)
+#define read_16_XII(A) read_16_direct(cpustate, A)
+#define read_16_YI(A) read_16_direct(cpustate, A)
+
+#define write_8_NORM(A, V) write_8_normal(cpustate, A, V)
+#define write_8_IMM(A, V) write_8_normal(cpustate, A, V)
+#define write_8_ABS(A, V) write_8_normal(cpustate, A, V)
+#define write_8_ABX(A, V) write_8_normal(cpustate, A, V)
+#define write_8_ABY(A, V) write_8_normal(cpustate, A, V)
+#define write_8_AXI(A, V) write_8_normal(cpustate, A, V)
+#define write_8_DP(A, V) write_8_direct(cpustate, A, V)
+#define write_8_DPX(A, V) write_8_direct(cpustate, A, V)
+#define write_8_DPY(A, V) write_8_direct(cpustate, A, V)
+#define write_8_DPI(A, V) write_8_normal(cpustate, A, V)
+#define write_8_DXI(A, V) write_8_normal(cpustate, A, V)
+#define write_8_DIY(A, V) write_8_normal(cpustate, A, V)
+#define write_8_STK(A, V) write_8_normal(cpustate, A, V)
+#define write_8_XI(A, V) write_8_direct(cpustate, A, V)
+#define write_8_XII(A, V) write_8_direct(cpustate, A, V)
+#define write_8_YI(A, V) write_8_direct(cpustate, A, V)
+
+#define write_16_NORM(A, V) write_16_normal(cpustate, A, V)
+#define write_16_ABS(A, V) write_16_normal(cpustate, A, V)
+#define write_16_ABX(A, V) write_16_normal(cpustate, A, V)
+#define write_16_ABY(A, V) write_16_normal(cpustate, A, V)
+#define write_16_AXI(A, V) write_16_normal(cpustate, A, V)
+#define write_16_DP(A, V) write_16_direct(cpustate, A, V)
+#define write_16_DPX(A, V) write_16_direct(cpustate, A, V)
+#define write_16_DPY(A, V) write_16_direct(cpustate, A, V)
+#define write_16_DPI(A, V) write_16_normal(cpustate, A, V)
+#define write_16_DXI(A, V) write_16_normal(cpustate, A, V)
+#define write_16_DIY(A, V) write_16_normal(cpustate, A, V)
+#define write_16_STK(A, V) write_16_normal(cpustate, A, V)
+#define write_16_XI(A, V) write_16_direct(cpustate, A, V)
+#define write_16_XII(A, V) write_16_direct(cpustate, A, V)
+#define write_16_YI(A, V) write_16_direct(cpustate, A, V)
+
+
+#define OPER_8_IMM(cpustate) read_8_IMM(EA_IMM(cpustate))
+#define OPER_8_ABS(cpustate) read_8_ABS(EA_ABS(cpustate))
+#define OPER_8_ABX(cpustate) read_8_ABX(EA_ABX(cpustate))
+#define OPER_8_ABY(cpustate) read_8_ABY(EA_ABY(cpustate))
+#define OPER_8_AXI(cpustate) read_8_IND(EA_IND(cpustate))
+#define OPER_8_DP(cpustate) read_8_DP(EA_DP(cpustate))
+#define OPER_8_DPX(cpustate) read_8_DPX(EA_DPX(cpustate))
+#define OPER_8_DPY(cpustate) read_8_DPY(EA_DPY(cpustate))
+#define OPER_8_DPI(cpustate) read_8_DPI(EA_DPI(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_XI(cpustate) read_8_XI(EA_XI(cpustate))
+#define OPER_8_XII(cpustate) read_8_XI(EA_XII(cpustate))
+#define OPER_8_YI(cpustate) read_8_YI(EA_YI(cpustate))
+
+#define OPER_16_IMM(cpustate) read_16_IMM(EA_IMM16(cpustate))
+#define OPER_16_ABS(cpustate) read_16_ABS(EA_ABS(cpustate))
+#define OPER_16_ABX(cpustate) read_16_ABX(EA_ABX(cpustate))
+#define OPER_16_ABY(cpustate) read_16_ABY(EA_ABY(cpustate))
+#define OPER_16_AXI(cpustate) read_16_IND(EA_IND(cpustate))
+#define OPER_16_DP(cpustate) read_16_DP(EA_DP(cpustate))
+#define OPER_16_DPX(cpustate) read_16_DPX(EA_DPX(cpustate))
+#define OPER_16_DPY(cpustate) read_16_DPY(EA_DPY(cpustate))
+#define OPER_16_DPI(cpustate) read_16_DPI(EA_DXI(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_XI(cpustate) read_16_XI(EA_XI(cpustate))
+#define OPER_16_XII(cpustate) read_16_XI(EA_XII(cpustate))
+#define OPER_16_YI(cpustate) read_16_YI(EA_YI(cpustate))
+
+/* Effective Address Caluclations */
+INLINE uint EA_IMM(spc700i_cpu *cpustate) {return REG_PC++;}
+INLINE uint EA_IMM16(spc700i_cpu *cpustate) {REG_PC += 2; return REG_PC-2;}
+INLINE uint EA_ABS(spc700i_cpu *cpustate) {return OPER_16_IMM(cpustate);}
+INLINE uint EA_ABX(spc700i_cpu *cpustate) {return EA_ABS(cpustate) + REG_X;}
+INLINE uint EA_ABY(spc700i_cpu *cpustate) {return EA_ABS(cpustate) + REG_Y;}
+INLINE uint EA_AXI(spc700i_cpu *cpustate) {return OPER_16_ABX(cpustate);}
+INLINE uint EA_DP(spc700i_cpu *cpustate) {return OPER_8_IMM(cpustate);}
+INLINE uint EA_DPX(spc700i_cpu *cpustate) {return (EA_DP(cpustate) + REG_X)&0xff;}
+INLINE uint EA_DPY(spc700i_cpu *cpustate) {return (EA_DP(cpustate) + REG_Y)&0xff;}
+INLINE uint EA_DXI(spc700i_cpu *cpustate) {return OPER_16_DPX(cpustate);}
+INLINE uint EA_DIY(spc700i_cpu *cpustate) {uint addr = OPER_16_DP(cpustate); if((addr&0xff00) != ((addr+REG_Y)&0xff00)) CLK(1); return addr + REG_Y;}
+INLINE uint EA_XI(spc700i_cpu *cpustate) {return REG_X;}
+INLINE uint EA_XII(spc700i_cpu *cpustate) {uint val = REG_X;REG_X = MAKE_UINT_8(REG_X+1);return val;}
+INLINE uint EA_YI(spc700i_cpu *cpustate) {return REG_Y;}
+
+
+
+/* Change the Program Counter */
+INLINE void JUMP(spc700i_cpu *cpustate, uint address)
+{
+ REG_PC = address;
+ spc700_jumping(REG_PC);
+}
+
+INLINE void BRANCH(spc700i_cpu *cpustate, uint offset)
+{
+ REG_PC = MAKE_UINT_16(REG_PC + MAKE_INT_8(offset));
+ spc700_branching(REG_PC);
+}
+
+
+#define GET_REG_YA() (REG_A | (REG_Y<<8))
+
+INLINE void SET_REG_YA(spc700i_cpu *cpustate, uint value)
+{
+ REG_A = MAKE_UINT_8(value);
+ REG_Y = MAKE_UINT_8(value>>8);
+}
+
+/* Get the Processor Status Register */
+#define GET_REG_P() \
+ ((FLAG_N & 0x80) | \
+ ((FLAG_V & 0x80) >> 1) | \
+ (FLAG_P>>3) | \
+ FLAG_B | \
+ (FLAG_H& HFLAG_SET) | \
+ FLAG_I | \
+ ((!FLAG_Z) << 1) | \
+ CFLAG_AS_1())
+
+/* Get Processor Status Register with B flag set (when executing BRK instruction) */
+#define GET_REG_P_BRK() \
+ ((FLAG_N & 0x80) | \
+ ((FLAG_V & 0x80) >> 1) | \
+ (FLAG_P>>3) | \
+ FLAGPOS_B | \
+ (FLAG_H & HFLAG_SET) | \
+ FLAG_I | \
+ ((!FLAG_Z) << 1) | \
+ CFLAG_AS_1())
+
+/* Get Processor Status Register with B flag cleared (when servicing an interrupt) */
+#define GET_REG_P_INT() \
+ ((FLAG_N & 0x80) | \
+ ((FLAG_V & 0x80) >> 1) | \
+ (FLAG_P>>3) | \
+ (FLAG_H & HFLAG_SET) | \
+ FLAG_I | \
+ ((!FLAG_Z) << 1) | \
+ CFLAG_AS_1())
+
+INLINE void SET_FLAG_I(spc700i_cpu *cpustate, uint value);
+
+/* Set the Process Status Register */
+INLINE void SET_REG_P(spc700i_cpu *cpustate, uint value)
+{
+ FLAG_N = (value & 0x80);
+ FLAG_Z = !(value & 2);
+ FLAG_V = value<<1;
+ FLAG_P = (value & FLAGPOS_P) << 3;
+ FLAG_B = value & FLAGPOS_B;
+ FLAG_H = value & HFLAG_SET;
+ FLAG_C = value << 8;
+ SET_FLAG_I(cpustate, value);
+}
+
+/* Push/Pull data to/from the stack */
+INLINE void PUSH_8(spc700i_cpu *cpustate, uint value)
+{
+ write_8_STK(REG_S+STACK_PAGE, value);
+ REG_S = MAKE_UINT_8(REG_S - 1);
+}
+
+INLINE uint PULL_8(spc700i_cpu *cpustate)
+{
+ REG_S = MAKE_UINT_8(REG_S + 1);
+ return read_8_STK(REG_S+STACK_PAGE);
+}
+
+INLINE void PUSH_16(spc700i_cpu *cpustate, uint value)
+{
+ PUSH_8(cpustate, value>>8);
+ PUSH_8(cpustate, value);
+}
+
+INLINE uint PULL_16(spc700i_cpu *cpustate)
+{
+ uint value = PULL_8(cpustate);
+ return value | (PULL_8(cpustate)<<8);
+}
+
+#if !SPC700_OPTIMIZE_SNES
+INLINE void CHECK_IRQ(spc700i_cpu *cpustate)
+{
+ if(FLAG_I & LINE_IRQ)
+ SERVICE_IRQ();
+}
+#endif /* SPC700_OPTIMIZE_SNES */
+
+INLINE void SET_FLAG_I(spc700i_cpu *cpustate, uint value)
+{
+ FLAG_I = value & IFLAG_SET;
+#if !SPC700_OPTIMIZE_SNES
+ CHECK_IRQ(cpustate);
+#endif
+}
+
+/* ======================================================================== */
+/* =========================== OPERATION MACROS =========================== */
+/* ======================================================================== */
+
+#define SUBOP_ADC(A, B) \
+ cpustate->spc_int16 = (A) + (B) + CFLAG_AS_1(); \
+ TMP1 = ((A) & 0x0f) + (CFLAG_AS_1()); \
+ FLAG_C = (cpustate->spc_int16 > 0xff) ? CFLAG_SET : 0; \
+ FLAG_V = (~((A) ^ (B))) & (((A) ^ cpustate->spc_int16) & 0x80); \
+ FLAG_H = (((cpustate->spc_int16 & 0x0f) - TMP1) & 0x10) >> 1; \
+ FLAG_NZ = (UINT8)cpustate->spc_int16
+
+
+/* Add With Carry */
+#define OP_ADC(BCLK, MODE) \
+ CLK(BCLK); \
+ SRC = OPER_8_##MODE(cpustate); \
+ SUBOP_ADC(SRC, REG_A); \
+ REG_A = (UINT8)cpustate->spc_int16;
+
+
+/* Add With Carry to memory */
+#define OP_ADCM(BCLK, SMODE, DMODE) \
+ CLK(BCLK); \
+ SRC = OPER_8_##SMODE(cpustate); \
+ DST = EA_##DMODE(cpustate); \
+ SUBOP_ADC(SRC, read_8_##DMODE(DST)); \
+ write_8_##DMODE(DST, (UINT8)cpustate->spc_int16)
+
+/* Add word */
+#define OP_ADDW(BCLK) \
+ CLK(BCLK); \
+ SRC = OPER_16_DP(cpustate); \
+ DST = GET_REG_YA(); \
+ TMP1 = ((SRC) & 0xff) + ((DST) & 0xff); \
+ TMP2 = (TMP1 > 0xff) ? 1 : 0; \
+ TMP3 = ((SRC) >> 8) + ((DST) >> 8) + TMP2; \
+ cpustate->spc_int16 = ((TMP1 & 0xff) + (TMP3 << 8)) & 0xffff; \
+ FLAG_C = (TMP3 > 0xff) ? CFLAG_SET : 0; \
+ FLAG_H = ((unsigned) ((((DST) >> 8) & 0x0F) + \
+ (((SRC) >> 8) & 0x0F) + TMP2)) > 0x0F ? HFLAG_SET : 0; \
+ FLAG_V = (~((DST) ^ (SRC)) & ((SRC) ^ (UINT16) cpustate->spc_int16) & 0x8000) ? VFLAG_SET : 0; \
+ FLAG_Z = (cpustate->spc_int16 != 0); \
+ FLAG_N = (cpustate->spc_int16>>8); \
+ SET_REG_YA(cpustate, cpustate->spc_int16);
+
+/* Logical AND with accumulator */
+#define OP_AND(BCLK, MODE) \
+ CLK(BCLK); \
+ FLAG_NZ = REG_A &= OPER_8_##MODE(cpustate)
+
+/* Logical AND operand */
+#define OP_ANDM(BCLK, SMODE, DMODE) \
+ CLK(BCLK); \
+ FLAG_NZ = OPER_8_##SMODE(cpustate); \
+ DST = EA_##DMODE(cpustate); \
+ FLAG_NZ &= read_8_##DMODE(DST); \
+ write_8_##DMODE(DST, FLAG_NZ)
+
+/* Logical AND bit to C */
+#define OP_AND1(BCLK) \
+ CLK(BCLK); \
+ DST = EA_IMM16(cpustate); \
+ if(FLAG_C & CFLAG_SET) \
+ { \
+ DST = read_16_IMM(DST); \
+ SRC = 1 << (DST >> 13); \
+ DST &= 0x1fff; \
+ if(!(read_8_NORM(DST) & SRC)) \
+ FLAG_C = CFLAG_CLEAR; \
+ }
+
+/* AND negated bit to C */
+#define OP_ANDN1(BCLK) \
+ CLK(BCLK); \
+ DST = EA_IMM16(cpustate); \
+ if(FLAG_C & CFLAG_SET) \
+ { \
+ DST = read_16_IMM(DST); \
+ SRC = 1 << (DST >> 13); \
+ DST &= 0x1fff; \
+ if(read_8_NORM(DST) & SRC) \
+ FLAG_C = CFLAG_CLEAR; \
+ }
+
+/* Arithmetic Shift Left accumulator */
+#define OP_ASL(BCLK) \
+ CLK(BCLK); \
+ FLAG_C = REG_A << 1; \
+ FLAG_NZ = REG_A = MAKE_UINT_8(FLAG_C)
+
+/* Arithmetic Shift Left operand */
+#define OP_ASLM(BCLK, MODE) \
+ CLK(BCLK); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_C = read_8_##MODE(DST) << 1; \
+ FLAG_NZ = MAKE_UINT_8(FLAG_C); \
+ write_8_##MODE(DST, FLAG_NZ)
+
+/* Branch if Bit Reset */
+#define OP_BBC(BCLK, BIT) \
+ CLK(BCLK); \
+ SRC = OPER_8_DP(cpustate); \
+ DST = OPER_8_IMM(cpustate); \
+ if(!(SRC & BIT)) \
+ { \
+ CLK(1); \
+ BRANCH(cpustate, DST); \
+ }
+
+/* Branch if Bit Set */
+#define OP_BBS(BCLK, BIT) \
+ CLK(BCLK); \
+ SRC = OPER_8_DP(cpustate); \
+ DST = OPER_8_IMM(cpustate); \
+ if(SRC & BIT) \
+ { \
+ CLK(1); \
+ BRANCH(cpustate, DST); \
+ }
+
+/* Branch on Condition Code */
+#define OP_BCC(BCLK, COND) \
+ CLK(BCLK); \
+ DST = OPER_8_IMM(cpustate); \
+ if(COND) \
+ { \
+ CLK(1); \
+ BRANCH(cpustate, DST); \
+ }
+
+/* Branch Unconditional */
+/* speed up busy loops */
+#define OP_BRA(BCLK) \
+ CLK(BCLK); \
+ BRANCH(cpustate, OPER_8_IMM(cpustate)); \
+ if(REG_PC == REG_PPC) \
+ CLK_ALL()
+
+/* Cause a Break interrupt */
+#define OP_BRK(BCLK) \
+ CLK(BCLK); \
+ PUSH_16(cpustate, REG_PC); \
+ PUSH_8(cpustate, GET_REG_P_BRK()); \
+ FLAG_B |= FLAGPOS_B; \
+ FLAG_I = IFLAG_CLEAR; \
+ JUMP(cpustate, read_16_VEC(VECTOR_BRK))
+
+/* Call subroutine */
+#define OP_CALL(BCLK) \
+ CLK(BCLK); \
+ DST = EA_ABS(cpustate); \
+ PUSH_16(cpustate, REG_PC); \
+ JUMP(cpustate, DST)
+
+/* Compare accumulator and branch if not equal */
+#define OP_CBNE(BCLK, MODE) \
+ CLK(BCLK); \
+ SRC = OPER_8_##MODE(cpustate); \
+ DST = EA_IMM(cpustate); \
+ if(SRC != REG_A) \
+ { \
+ CLK(1); \
+ BRANCH(cpustate, read_8_IMM(DST)); \
+ }
+
+/* Clear Carry flag */
+#define OP_CLRC(BCLK) \
+ CLK(BCLK); \
+ FLAG_C = CFLAG_CLEAR
+
+/* Clear Memory Bit */
+#define OP_CLR(BCLK, BIT) \
+ CLK(BCLK); \
+ DST = EA_DP(cpustate); \
+ SRC = read_8_DP(DST) & ~BIT; \
+ write_8_DP(DST, SRC)
+
+/* Clear Overflow flag (also clears half-carry) */
+#define OP_CLRV(BCLK) \
+ CLK(BCLK); \
+ FLAG_V = VFLAG_CLEAR; \
+ FLAG_H = 0;
+
+/* Clear the Page flag */
+#define OP_CLRP(BCLK) \
+ CLK(BCLK); \
+ FLAG_P = PFLAG_CLEAR
+
+/* Compare operand to register */
+#define OP_CMPR(BCLK, REG, MODE) \
+ CLK(BCLK); \
+ SRC = OPER_8_##MODE(cpustate); \
+ cpustate->spc_int16 = (short)REG - (short)SRC; \
+ FLAG_C = (cpustate->spc_int16 >= 0) ? CFLAG_SET : 0; \
+ FLAG_NZ = MAKE_UINT_8(cpustate->spc_int16);
+
+/* Compare memory */
+#define OP_CMPM(BCLK, SMODE, DMODE) \
+ CLK(BCLK); \
+ SRC = OPER_8_##SMODE(cpustate); \
+ cpustate->spc_int16 = (short)OPER_8_##DMODE(cpustate) - (short)SRC; \
+ FLAG_C = (cpustate->spc_int16 >= 0) ? CFLAG_SET : 0; \
+ FLAG_NZ = MAKE_UINT_8(cpustate->spc_int16);
+
+/* Compare word */
+#define OP_CMPW(BCLK, MODE) \
+ CLK(BCLK); \
+ SRC = OPER_16_##MODE(cpustate); \
+ cpustate->spc_int32 = (int)GET_REG_YA() - (int)SRC; \
+ FLAG_C = (cpustate->spc_int32 >= 0) ? CFLAG_SET : 0; \
+ FLAG_NZ = NZFLAG_16(cpustate->spc_int32);
+
+/* Decimal adjust for addition */
+#define OP_DAA(BCLK) \
+ CLK(BCLK); \
+ SRC = REG_A; \
+ if (((SRC & 0x0f) > 9) || (FLAG_H & HFLAG_SET)) \
+ { \
+ REG_A += 6; \
+ if (REG_A < 6) \
+ { \
+ FLAG_C = CFLAG_SET; \
+ } \
+ } \
+ if ((SRC > 0x99) || (FLAG_C & CFLAG_SET)) \
+ { \
+ REG_A += 0x60; \
+ FLAG_C = CFLAG_SET; \
+ } \
+ FLAG_NZ = REG_A = MAKE_UINT_8(REG_A);
+
+/* Decimal adjust for subtraction */
+#define OP_DAS(BCLK) \
+ CLK(BCLK); \
+ SRC = REG_A; \
+ if (!(FLAG_H & HFLAG_SET) || ((SRC & 0xf) > 9)) \
+ { \
+ REG_A -= 6; \
+ } \
+ if (!(FLAG_C & CFLAG_SET) || (SRC > 0x99)) \
+ { \
+ REG_A -= 0x60; \
+ FLAG_C = 0; \
+ } \
+ FLAG_NZ = REG_A = MAKE_UINT_8(REG_A)
+
+/* Decrement register and branch if not zero */
+/* speed up busy loops */
+#define OP_DBNZR(BCLK) \
+ CLK(BCLK); \
+ REG_Y = MAKE_UINT_8(REG_Y - 1); \
+ DST = EA_IMM(cpustate); \
+ if(REG_Y != 0) \
+ { \
+ CLK(1); \
+ BRANCH(cpustate, read_8_IMM(DST)); \
+ }
+
+/* Decrement operand and branch if not zero */
+/* Speed up busy loops but do reads/writes for compatibility */
+#define OP_DBNZM(BCLK) \
+ CLK(BCLK); \
+ DST = EA_DP(cpustate); \
+ SRC = MAKE_UINT_8(read_8_DP(DST) - 1); \
+ write_8_DP(DST, SRC); \
+ DST = EA_IMM(cpustate); \
+ if(SRC != 0) \
+ { \
+ CLK(1); \
+ BRANCH(cpustate, read_8_IMM(DST)); \
+ }
+
+/* Decrement register */
+#define OP_DECR(BCLK, REG) \
+ CLK(BCLK); \
+ FLAG_NZ = REG = MAKE_UINT_8(REG - 1)
+
+/* Decrement operand */
+#define OP_DECM(BCLK, MODE) \
+ CLK(BCLK); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_NZ = MAKE_UINT_8(read_8_##MODE(DST) - 1); \
+ write_8_##MODE(DST, FLAG_NZ)
+
+/* Decrement word */
+#define OP_DECW(BCLK) \
+ CLK(BCLK); \
+ DST = EA_DP(cpustate); \
+ FLAG_NZ = MAKE_UINT_16(read_16_DP(DST) - 1); \
+ write_16_DP(DST, FLAG_Z); \
+ FLAG_NZ = NZFLAG_16(FLAG_Z)
+
+/* Disable interrupts */
+#define OP_DI(BCLK) \
+ CLK(BCLK); \
+ FLAG_I = IFLAG_CLEAR
+
+/* Divide - should be almost exactly how the hardware works */
+#define OP_DIV(BCLK) \
+ CLK(BCLK); \
+ TMP1 = SRC = GET_REG_YA(); \
+ TMP2 = (REG_X << 9); \
+ FLAG_H = 0; \
+ if ((REG_Y & 0xf) >= (REG_X & 0xf)) FLAG_H = HFLAG_SET; \
+ for (TMP3 = 0; TMP3 < 9; TMP3++) \
+ { \
+ TMP1 <<= 1; \
+ if (TMP1 & 0x20000) TMP1 = (TMP1 & 0x1ffff) | 1; \
+ if (TMP1 >= TMP2) TMP1 ^= 1; \
+ if (TMP1 & 1) TMP1 = ((TMP1 - TMP2) & 0x1ffff); \
+ } \
+ FLAG_V = (TMP1 & 0x100) ? VFLAG_SET : 0; \
+ SET_REG_YA(cpustate, (((TMP1 >> 9) & 0xff) << 8) + (TMP1 & 0xff)); \
+ FLAG_NZ = MAKE_UINT_8(GET_REG_YA());
+
+/* Enable interrupts */
+#define OP_EI(BCLK) \
+ CLK(BCLK); \
+ FLAG_I = IFLAG_SET
+
+/* Exclusive Or operand to accumulator */
+#define OP_EOR(BCLK, MODE) \
+ CLK(BCLK); \
+ FLAG_NZ = REG_A ^= OPER_8_##MODE(cpustate)
+
+/* Logical EOR operand */
+#define OP_EORM(BCLK, SMODE, DMODE) \
+ CLK(BCLK); \
+ FLAG_NZ = OPER_8_##SMODE(cpustate); \
+ DST = EA_##DMODE(cpustate); \
+ FLAG_NZ ^= read_8_##DMODE(DST); \
+ write_8_##DMODE(DST, FLAG_NZ)
+
+/* Exclusive OR bit to C */
+#define OP_EOR1(BCLK) \
+ CLK(BCLK); \
+ DST = OPER_16_IMM(cpustate); \
+ SRC = 1 << (DST >> 13); \
+ DST &= 0x1fff; \
+ if(read_8_NORM(DST) & SRC) \
+ FLAG_C = ~FLAG_C
+
+/* Increment register */
+#define OP_INCR(BCLK, REG) \
+ CLK(BCLK); \
+ FLAG_NZ = REG = MAKE_UINT_8(REG + 1)
+
+/* Increment operand */
+#define OP_INCM(BCLK, MODE) \
+ CLK(BCLK); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_NZ = MAKE_UINT_8(read_8_##MODE(DST) + 1); \
+ write_8_##MODE(DST, FLAG_NZ)
+
+/* Increment word */
+#define OP_INCW(BCLK) \
+ CLK(BCLK); \
+ DST = EA_DP(cpustate); \
+ FLAG_NZ = MAKE_UINT_16(read_16_DP(DST) + 1); \
+ write_16_DP(DST, FLAG_Z); \
+ FLAG_NZ = NZFLAG_16(FLAG_Z)
+
+/* Jump */
+/* If we're in a busy loop, eat all clock cycles */
+#define OP_JMP(BCLK, MODE) \
+ CLK(BCLK); \
+ JUMP(cpustate, EA_##MODE(cpustate)); \
+ if(REG_PC == REG_PPC) \
+ CLK_ALL()
+
+/* Jump to Subroutine */
+#define OP_JSR(BCLK, MODE) \
+ CLK(BCLK); \
+ PUSH_16(cpustate, REG_PC); \
+ JUMP(cpustate, EA_##MODE(cpustate))
+
+/* Logical Shift Right accumulator */
+#define OP_LSR(BCLK) \
+ CLK(BCLK); \
+ FLAG_C = REG_A << 8; \
+ FLAG_NZ = REG_A >>= 1
+
+/* Logical Shift Right operand */
+#define OP_LSRM(BCLK, MODE) \
+ CLK(BCLK); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_NZ = read_8_##MODE(DST); \
+ FLAG_C = FLAG_NZ << 8; \
+ FLAG_NZ >>= 1; \
+ write_8_##MODE(DST, FLAG_NZ)
+
+/* Move from register to register */
+#define OP_MOVRR(BCLK, SREG, DREG) \
+ CLK(BCLK); \
+ FLAG_NZ = DREG = SREG
+
+/* Move from register to memory */
+#define OP_MOVRM(BCLK, SREG, DMODE) \
+ CLK(BCLK); \
+ write_8_##DMODE(EA_##DMODE(cpustate), SREG)
+
+/* Move from memory to register */
+#define OP_MOVMR(BCLK, SMODE, DREG) \
+ CLK(BCLK); \
+ FLAG_NZ = DREG = OPER_8_##SMODE(cpustate)
+
+/* Move from memory to memory */
+#define OP_MOVMM(BCLK, SMODE, DMODE) \
+ CLK(BCLK); \
+ SRC = OPER_8_##SMODE(cpustate); \
+ DST = EA_##DMODE(cpustate); \
+ write_8_##DMODE(DST, SRC)
+
+/* Move word register to memory */
+#define OP_MOVWRM(BCLK) \
+ CLK(BCLK); \
+ write_16_DP(EA_DP(cpustate), GET_REG_YA())
+
+/* Move word memory to register */
+#define OP_MOVWMR(BCLK) \
+ CLK(BCLK); \
+ FLAG_NZ = OPER_16_DP(cpustate); \
+ SET_REG_YA(cpustate, FLAG_Z); \
+ FLAG_NZ = NZFLAG_16(FLAG_Z)
+
+/* Move from Stack pointer to X */
+#define OP_MOVSX(BCLK) \
+ CLK(BCLK); \
+ FLAG_NZ = REG_X = REG_S
+
+/* Move from X to Stack pointer */
+#define OP_MOVXS(BCLK) \
+ CLK(BCLK); \
+ REG_S = REG_X
+
+/* Move bit from memory to C */
+#define OP_MOV1C(BCLK) \
+ CLK(BCLK); \
+ DST = OPER_16_IMM(cpustate); \
+ SRC = 1 << (DST >> 13); \
+ DST &= 0x1fff; \
+ FLAG_C = ((read_8_NORM(DST) & SRC) != 0) << 8
+
+/* Move bit from C to memory */
+#define OP_MOV1M(BCLK) \
+ CLK(BCLK); \
+ DST = OPER_16_IMM(cpustate); \
+ SRC = 1 << (DST >> 13); \
+ DST &= 0x1fff; \
+ if(FLAG_C & CFLAG_SET) \
+ write_8_NORM(DST, read_8_NORM(DST) | SRC); \
+ else \
+ write_8_NORM(DST, read_8_NORM(DST) & ~SRC)
+
+
+/* Multiply A and Y and store result in YA */
+#define OP_MUL(BCLK) \
+ CLK(BCLK); \
+ SRC = REG_Y * REG_A; \
+ REG_A = MAKE_UINT_8(SRC); \
+ FLAG_NZ = REG_Y = SRC >> 8;
+
+/* No Operation */
+#define OP_NOP(BCLK) \
+ CLK(BCLK)
+
+/* Invert the C flag */
+#define OP_NOTC(BCLK) \
+ CLK(BCLK); \
+ FLAG_C = ~FLAG_C
+
+/* NOT bit */
+#define OP_NOT1(BCLK) \
+ CLK(BCLK); \
+ DST = OPER_16_IMM(cpustate); \
+ SRC = 1 << (DST >> 13); \
+ DST &= 0x1fff; \
+ write_8_NORM(DST, read_8_NORM(DST) ^ SRC)
+
+/* Logical OR operand to accumulator */
+#define OP_OR(BCLK, MODE) \
+ CLK(BCLK); \
+ FLAG_NZ = REG_A |= OPER_8_##MODE(cpustate)
+
+/* Logical OR operand */
+#define OP_ORM(BCLK, SMODE, DMODE) \
+ CLK(BCLK); \
+ FLAG_NZ = OPER_8_##SMODE(cpustate); \
+ DST = EA_##DMODE(cpustate); \
+ FLAG_NZ |= read_8_##DMODE(DST); \
+ write_8_##DMODE(DST, FLAG_NZ)
+
+/* Logical OR bit to C */
+#define OP_OR1(BCLK) \
+ CLK(BCLK); \
+ DST = EA_IMM16(cpustate); \
+ if(!(FLAG_C & CFLAG_SET)) \
+ { \
+ DST = read_16_IMM(DST); \
+ SRC = 1 << (DST >> 13); \
+ DST &= 0x1fff; \
+ if(read_8_NORM(DST) & SRC) \
+ FLAG_C = CFLAG_SET; \
+ }
+
+/* OR negated bit to C */
+#define OP_ORN1(BCLK) \
+ CLK(BCLK); \
+ DST = EA_IMM16(cpustate); \
+ if(!(FLAG_C & CFLAG_SET)) \
+ { \
+ DST = read_16_IMM(DST); \
+ SRC = 1 << (DST >> 13); \
+ DST &= 0x1fff; \
+ if(!(read_8_NORM(DST) & SRC)) \
+ FLAG_C = CFLAG_SET; \
+ }
+
+/* UPage Call */
+#define OP_PCALL(BCLK) \
+ CLK(BCLK); \
+ DST = EA_DP(cpustate); \
+ PUSH_16(cpustate, REG_PC); \
+ JUMP(cpustate, 0xff00 | DST)
+
+/* Push a register to the stack */
+#define OP_PUSH(BCLK, REG) \
+ CLK(BCLK); \
+ PUSH_8(cpustate, REG)
+
+/* Push the Processor Status Register to the stack */
+#define OP_PHP(BCLK) \
+ CLK(BCLK); \
+ PUSH_8(cpustate, GET_REG_P())
+
+/* Pull a register from the stack */
+#define OP_PULL(BCLK, REG) \
+ CLK(BCLK); \
+ REG = PULL_8(cpustate)
+
+/* Pull the Processor Status Register from the stack */
+#define OP_PLP(BCLK) \
+ CLK(BCLK); \
+ SET_REG_P(cpustate, PULL_8(cpustate))
+
+/* Return from Subroutine */
+#define OP_RET(BCLK) \
+ CLK(BCLK); \
+ JUMP(cpustate, PULL_16(cpustate))
+
+/* Return from Interrupt */
+#define OP_RETI(BCLK) \
+ CLK(BCLK); \
+ SET_REG_P(cpustate, PULL_8(cpustate)); \
+ JUMP(cpustate, PULL_16(cpustate))
+
+/* Rotate Left the accumulator */
+#define OP_ROL(BCLK) \
+ CLK(BCLK); \
+ FLAG_C = (REG_A<<1) | CFLAG_AS_1(); \
+ FLAG_NZ = REG_A = MAKE_UINT_8(FLAG_C)
+
+/* Rotate Left an operand */
+#define OP_ROLM(BCLK, MODE) \
+ CLK(BCLK); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_C = (read_8_##MODE(DST)<<1) | CFLAG_AS_1(); \
+ FLAG_NZ = MAKE_UINT_8(FLAG_C); \
+ write_8_##MODE(DST, FLAG_NZ)
+
+/* Rotate Right the accumulator */
+#define OP_ROR(BCLK) \
+ CLK(BCLK); \
+ REG_A |= FLAG_C & 0x100; \
+ FLAG_C = REG_A << 8; \
+ FLAG_NZ = REG_A >>= 1
+
+/* Rotate Right an operand */
+#define OP_RORM(BCLK, MODE) \
+ CLK(BCLK); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_NZ = read_8_##MODE(DST) | (FLAG_C & 0x100); \
+ FLAG_C = FLAG_NZ << 8; \
+ FLAG_NZ >>= 1; \
+ write_8_##MODE(DST, FLAG_NZ)
+
+/* Subtract with Carry */
+#define OP_SBC(BCLK, MODE) \
+ CLK(BCLK); \
+ SRC = OPER_8_##MODE(cpustate); \
+ TMP2 = REG_A - SRC - (CFLAG_AS_1() ^ 1); \
+ SUBOP_ADC(REG_A, ~SRC); \
+ FLAG_C = (TMP2 <= 0xff) ? CFLAG_SET : 0; \
+ REG_A = (UINT8)cpustate->spc_int16;
+
+/* Subtract With Carry to memory */
+#define OP_SBCM(BCLK, SMODE, DMODE) \
+ CLK(BCLK); \
+ SRC = OPER_8_##SMODE(cpustate); \
+ DST = EA_##DMODE(cpustate); \
+ TMP3 = read_8_##DMODE(DST); \
+ TMP2 = TMP3 - SRC - (CFLAG_AS_1() ^ 1); \
+ SUBOP_ADC(~SRC, TMP3); \
+ FLAG_C = (TMP2 <= 0xff) ? CFLAG_SET : 0; \
+ write_8_##DMODE(DST, (UINT8)cpustate->spc_int16)
+
+/* Set Carry flag */
+#define OP_SETC(BCLK) \
+ CLK(BCLK); \
+ FLAG_C = CFLAG_SET
+
+/* Set Page flag */
+#define OP_SETP(BCLK) \
+ CLK(BCLK); \
+ FLAG_P = PFLAG_SET
+
+/* Set Memory Bit */
+#define OP_SET(BCLK, BIT) \
+ CLK(BCLK); \
+ DST = EA_DP(cpustate); \
+ SRC = read_8_DP(DST) | BIT; \
+ write_8_DP(DST, SRC)
+
+/* Put the CPU to sleep */
+#define OP_SLEEP(BCLK) \
+ CLK(BCLK); \
+ CPU_STOPPED |= STOP_LEVEL_SLEEP; \
+ CLK_ALL()
+
+/* Stop the CPU */
+#define OP_STOP(BCLK) \
+ CLK(BCLK); \
+ CPU_STOPPED |= STOP_LEVEL_STOP; \
+ CLK_ALL()
+
+/* Subtract word */
+#define OP_SUBW(BCLK) \
+ CLK(BCLK); \
+ SRC = OPER_16_DP(cpustate); \
+ DST = GET_REG_YA(); \
+ TMP1 = ((DST) & 0xff) - ((SRC) & 0xff); \
+ TMP2 = (TMP1 > 0xff) ? 1 : 0; \
+ TMP3 = ((DST) >> 8) - ((SRC) >> 8) - TMP2; \
+ cpustate->spc_int16 = ((TMP1 & 0xff) + (TMP3 << 8)) & 0xffff; \
+ FLAG_C = (TMP3 <= 0xff) ? CFLAG_SET : 0; \
+ FLAG_H = ((unsigned) ((((DST) >> 8) & 0x0F) - \
+ (((SRC) >> 8) & 0x0F) - TMP2)) > 0x0F ? 0: HFLAG_SET; \
+ FLAG_V = (((DST) ^ (SRC)) & ((DST) ^ (UINT16) cpustate->spc_int16) & 0x8000) ? VFLAG_SET : 0; \
+ FLAG_Z = (cpustate->spc_int16 != 0); \
+ FLAG_N = (cpustate->spc_int16>>8); \
+ SET_REG_YA(cpustate, cpustate->spc_int16);
+
+/* Table Call */
+#define OP_TCALL(BCLK, NUM) \
+ CLK(BCLK); \
+ PUSH_16(cpustate, REG_PC); \
+ JUMP(cpustate, read_16_NORM(0xffc0 + ((15-NUM)<<1)))
+
+/* Test and Clear Bits */
+#define OP_TCLR1(BCLK, MODE) \
+ CLK(BCLK); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_NZ = read_8_##MODE(DST); \
+ write_8_##MODE(DST, FLAG_NZ & ~REG_A); \
+ FLAG_NZ &= REG_A
+
+/* Test and Set Bits */
+#define OP_TSET1(BCLK, MODE) \
+ CLK(BCLK); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_NZ = read_8_##MODE(DST); \
+ write_8_##MODE(DST, FLAG_NZ | REG_A); \
+ FLAG_NZ &= REG_A
+
+/* Exchange high and low nybbles of accumulator */
+#define OP_XCN(BCLK) \
+ CLK(BCLK); \
+ FLAG_NZ = REG_A = MAKE_UINT_8((REG_A<<4) | (REG_A>>4))
+
+#define OP_ILLEGAL(BCLK) \
+ CLK(BCLK)
+
+
+/* ======================================================================== */
+/* ================================= API ================================== */
+/* ======================================================================== */
+
+static void state_register( legacy_cpu_device *device )
+{
+ spc700i_cpu *cpustate = get_safe_token(device);
+
+ device->save_item(NAME(cpustate->a));
+ 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->flag_n));
+ device->save_item(NAME(cpustate->flag_z));
+ device->save_item(NAME(cpustate->flag_v));
+ device->save_item(NAME(cpustate->flag_p));
+ device->save_item(NAME(cpustate->flag_b));
+ device->save_item(NAME(cpustate->flag_h));
+ device->save_item(NAME(cpustate->flag_i));
+ 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->line_rst));
+ device->save_item(NAME(cpustate->ir));
+ device->save_item(NAME(cpustate->stopped));
+ device->save_item(NAME(cpustate->ICount));
+ device->save_item(NAME(cpustate->source));
+ device->save_item(NAME(cpustate->destination));
+ device->save_item(NAME(cpustate->temp1));
+ device->save_item(NAME(cpustate->temp2));
+ device->save_item(NAME(cpustate->temp3));
+ device->save_item(NAME(cpustate->spc_int16));
+ device->save_item(NAME(cpustate->spc_int32));
+}
+
+static CPU_INIT( spc700 )
+{
+ spc700i_cpu *cpustate = get_safe_token(device);
+
+ state_register(device);
+
+ INT_ACK = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+}
+
+
+static CPU_RESET( spc700 )
+{
+ spc700i_cpu *cpustate = get_safe_token(device);
+
+ CPU_STOPPED = 0;
+#if !SPC700_OPTIMIZE_SNES
+ LINE_IRQ = 0;
+ LINE_NMI = 0;
+#endif /* SPC700_OPTIMIZE_SNES */
+ REG_S = 0;
+ FLAG_NZ = NZFLAG_CLEAR;
+ FLAG_V = VFLAG_CLEAR;
+ FLAG_P = PFLAG_CLEAR;
+ FLAG_B = BFLAG_CLEAR;
+ FLAG_H = HFLAG_CLEAR;
+ FLAG_I = IFLAG_CLEAR;
+ FLAG_C = CFLAG_CLEAR;
+ JUMP(cpustate, read_16_VEC(VECTOR_RST));
+}
+
+/* Exit and clean up */
+static CPU_EXIT( spc700 )
+{
+ /* nothing to do yet */
+}
+
+
+/* Assert or clear the NMI line of the CPU */
+static void spc700_set_nmi_line(spc700i_cpu *cpustate,int state)
+{
+#if !SPC700_OPTIMIZE_SNES
+ if(state == CLEAR_LINE)
+ LINE_NMI = 0;
+ else if(!LINE_NMI)
+ {
+ LINE_NMI = 1;
+ CLK(7);
+ PUSH_16(cpustate, REG_PC);
+ PUSH_8(cpustate, GET_REG_P_INT());
+ JUMP(cpustate, read_16_VEC(VECTOR_NMI));
+ }
+#endif /* SPC700_OPTIMIZE_SNES */
+}
+
+/* Assert or clear the IRQ line of the CPU */
+static void spc700_set_irq_line(spc700i_cpu *cpustate,int line, int state)
+{
+#if !SPC700_OPTIMIZE_SNES
+ LINE_IRQ = (state != CLEAR_LINE) ? IRQ_SET : IRQ_CLEAR;
+ CHECK_IRQ();
+#endif /* SPC700_OPTIMIZE_SNES */
+}
+
+#include "spc700ds.h"
+
+//int dump_flag = 0;
+
+/* Execute instructions for <clocks> cycles */
+static CPU_EXECUTE( spc700 )
+{
+ spc700i_cpu *cpustate = get_safe_token(device);
+
+ if (CPU_STOPPED)
+ {
+ CLOCKS = 0;
+ return;
+ }
+ while(CLOCKS > 0)
+ {
+ REG_PPC = REG_PC;
+ debugger_instruction_hook(device, REG_PC);
+ REG_PC++;
+
+ switch(REG_IR = read_8_immediate(cpustate, REG_PPC))
+ {
+ case 0x00: OP_NOP ( 2 ); break; /* NOP */
+ case 0x01: OP_TCALL ( 8, 0 ); break; /* TCALL 0 */
+ case 0x02: OP_SET ( 4, BIT_0 ); break; /* SET 0 */
+ case 0x03: OP_BBS ( 5, BIT_0 ); break; /* BBS 0 */
+ case 0x04: OP_OR ( 3, DP ); break; /* ORA dp */
+ case 0x05: OP_OR ( 4, ABS ); break; /* ORA abs */
+ case 0x06: OP_OR ( 3, XI ); break; /* ORA xi */
+ case 0x07: OP_OR ( 6, DXI ); break; /* ORA dxi */
+ case 0x08: OP_OR ( 2, IMM ); break; /* ORA imm */
+ case 0x09: OP_ORM ( 6, DP , DP ); break; /* ORM dp dp */
+ case 0x0a: OP_OR1 ( 5 ); break; /* OR1 bit */
+ case 0x0b: OP_ASLM ( 4, DP ); break; /* ASL dp */
+ case 0x0c: OP_ASLM ( 4, ABS ); break; /* ASL abs */
+ case 0x0d: OP_PHP ( 4 ); break; /* PHP */
+ case 0x0e: OP_TSET1 ( 6, ABS ); break; /* TSET1 abs */
+ case 0x0f: OP_BRK ( 8 ); break; /* BRK */
+ case 0x10: OP_BCC ( 2, COND_PL() ); break; /* BPL */
+ case 0x11: OP_TCALL ( 8, 1 ); break; /* TCALL 1 */
+ case 0x12: OP_CLR ( 4, BIT_0 ); break; /* CLR 0 */
+ case 0x13: OP_BBC ( 5, BIT_0 ); break; /* BBC 0 */
+ case 0x14: OP_OR ( 4, DPX ); break; /* ORA dpx */
+ case 0x15: OP_OR ( 5, ABX ); break; /* ORA abx */
+ case 0x16: OP_OR ( 5, ABY ); break; /* ORA aby */
+ case 0x17: OP_OR ( 6, DIY ); break; /* ORA diy */
+ case 0x18: OP_ORM ( 6, IMM, DP ); break; /* ORM dp, imm */
+ case 0x19: OP_ORM ( 6, YI, XI ); break; /* ORM xi, yi */
+ case 0x1a: OP_DECW ( 6 ); break; /* DECW di */
+ case 0x1b: OP_ASLM ( 5, DPX ); break; /* ASL dpx */
+ case 0x1c: OP_ASL ( 2 ); break; /* ASL a */
+ case 0x1d: OP_DECR ( 2, REG_X ); break; /* DEC x */
+ case 0x1e: OP_CMPR ( 4, REG_X, ABS ); break; /* CMP x, abs */
+ case 0x1f: OP_JMP ( 6, AXI ); break; /* JMP axi */
+ case 0x20: OP_CLRP ( 2 ); break; /* CLRP */
+ case 0x21: OP_TCALL ( 8, 2 ); break; /* TCALL 2 */
+ case 0x22: OP_SET ( 4, BIT_1 ); break; /* SET 1 */
+ case 0x23: OP_BBS ( 5, BIT_1 ); break; /* BBS 1 */
+ case 0x24: OP_AND ( 3, DP ); break; /* AND dp */
+ case 0x25: OP_AND ( 4, ABS ); break; /* AND abs */
+ case 0x26: OP_AND ( 3, XI ); break; /* AND xi */
+ case 0x27: OP_AND ( 6, DXI ); break; /* AND dxi */
+ case 0x28: OP_AND ( 2, IMM ); break; /* AND imm */
+ case 0x29: OP_ANDM ( 6, DP , DP ); break; /* AND dp, dp */
+ case 0x2a: OP_ORN1 ( 5 ); break; /* OR1 !bit */
+ case 0x2b: OP_ROLM ( 4, DP ); break; /* ROL dp */
+ case 0x2c: OP_ROLM ( 5, ABS ); break; /* ROL abs */
+ case 0x2d: OP_PUSH ( 4, REG_A ); break; /* PUSH a */
+ case 0x2e: OP_CBNE ( 5, DP ); break; /* CBNE dp */
+ case 0x2f: OP_BRA ( 4 ); break; /* BRA */
+ case 0x30: OP_BCC ( 2, COND_MI() ); break; /* BMI */
+ case 0x31: OP_TCALL ( 8, 3 ); break; /* TCALL 3 */
+ case 0x32: OP_CLR ( 4, BIT_1 ); break; /* CLR 1 */
+ case 0x33: OP_BBC ( 5, BIT_1 ); break; /* BBC 1 */
+ case 0x34: OP_AND ( 4, DPX ); break; /* AND dpx */
+ case 0x35: OP_AND ( 5, ABX ); break; /* AND abx */
+ case 0x36: OP_AND ( 5, ABY ); break; /* AND aby */
+ case 0x37: OP_AND ( 6, DIY ); break; /* AND diy */
+ case 0x38: OP_ANDM ( 5, IMM, DP ); break; /* AND dp, imm */
+ case 0x39: OP_ANDM ( 5, YI , XI ); break; /* AND xi, yi */
+ case 0x3a: OP_INCW ( 6 ); break; /* INCW di */
+ case 0x3b: OP_ROLM ( 5, DPX ); break; /* ROL dpx */
+ case 0x3c: OP_ROL ( 2 ); break; /* ROL acc */
+ case 0x3d: OP_INCR ( 2, REG_X ); break; /* INC x */
+ case 0x3e: OP_CMPR ( 3, REG_X, DP ); break; /* CMP x, dp */
+ case 0x3f: OP_CALL ( 8 ); break; /* CALL abs */
+ case 0x40: OP_SETP ( 2 ); break; /* RTI */
+ case 0x41: OP_TCALL ( 8, 4 ); break; /* TCALL 4 */
+ case 0x42: OP_SET ( 4, BIT_2 ); break; /* SET 2 */
+ case 0x43: OP_BBS ( 5, BIT_2 ); break; /* BBS 2 */
+ case 0x44: OP_EOR ( 3, DP ); break; /* EOR dp */
+ case 0x45: OP_EOR ( 4, ABS ); break; /* EOR abs */
+ case 0x46: OP_EOR ( 3, XI ); break; /* EOR xi */
+ case 0x47: OP_EOR ( 6, DXI ); break; /* EOR dxi */
+ case 0x48: OP_EOR ( 2, IMM ); break; /* EOR imm */
+ case 0x49: OP_EORM ( 6, DP, DP ); break; /* EOR dp, dp */
+ case 0x4a: OP_AND1 ( 5 ); break; /* AND1 bit */
+ case 0x4b: OP_LSRM ( 4, DP ); break; /* LSR dp */
+ case 0x4c: OP_LSRM ( 5, ABS ); break; /* LSR abs */
+ case 0x4d: OP_PUSH ( 4, REG_X ); break; /* PUSH x */
+ case 0x4e: OP_TCLR1 ( 6, ABS ); break; /* TCLR1 abs */
+ case 0x4f: OP_PCALL ( 6 ); break; /* PCALL */
+ case 0x50: OP_BCC ( 2, COND_VC() ); break; /* BVC */
+ case 0x51: OP_TCALL ( 8, 5 ); break; /* TCALL 5 */
+ case 0x52: OP_CLR ( 4, BIT_2 ); break; /* CLR 2 */
+ case 0x53: OP_BBC ( 5, BIT_2 ); break; /* BBC 2 */
+ case 0x54: OP_EOR ( 4, DPX ); break; /* EOR dpx */
+ case 0x55: OP_EOR ( 5, ABX ); break; /* EOR abx */
+ case 0x56: OP_EOR ( 5, ABY ); break; /* EOR aby */
+ case 0x57: OP_EOR ( 6, DIY ); break; /* EOR diy */
+ case 0x58: OP_EORM ( 5, IMM, DP ); break; /* EOR dp, imm */
+ case 0x59: OP_EORM ( 5, YI , XI ); break; /* EOR xi, yi */
+ case 0x5a: OP_CMPW ( 4, DP ); break; /* CMPW dp */
+ case 0x5b: OP_LSRM ( 5, DPX ); break; /* LSR dpx */
+ case 0x5c: OP_LSR ( 2 ); break; /* LSR */
+ case 0x5d: OP_MOVRR ( 2, REG_A, REG_X ); break; /* MOV X, A */
+ case 0x5e: OP_CMPR ( 4, REG_Y, ABS ); break; /* CMP Y, abs */
+ case 0x5f: OP_JMP ( 3, ABS ); break; /* JMP abs */
+ case 0x60: OP_CLRC ( 2 ); break; /* CLRC */
+ case 0x61: OP_TCALL ( 8, 6 ); break; /* TCALL 6 */
+ case 0x62: OP_SET ( 4, BIT_3 ); break; /* SET 3 */
+ case 0x63: OP_BBS ( 5, BIT_3 ); break; /* BBS 3 */
+ case 0x64: OP_CMPR ( 3, REG_A, DP ); break; /* CMP A, dp */
+ case 0x65: OP_CMPR ( 4, REG_A, ABS ); break; /* CMP A, abs */
+ case 0x66: OP_CMPR ( 3, REG_A, XI ); break; /* CMP A, xi */
+ case 0x67: OP_CMPR ( 6, REG_A, DXI ); break; /* CMP A, dxi */
+ case 0x68: OP_CMPR ( 2, REG_A, IMM ); break; /* CMP A, imm */
+ case 0x69: OP_CMPM ( 6, DP, DP ); break; /* CMP dp, dp */
+ case 0x6a: OP_ANDN1 ( 4 ); break; /* AND1 !bit */
+ case 0x6b: OP_RORM ( 4, DP ); break; /* ROR dp */
+ case 0x6c: OP_RORM ( 5, ABS ); break; /* ROR abs */
+ case 0x6d: OP_PUSH ( 4, REG_Y ); break; /* PUSH Y */
+ case 0x6e: OP_DBNZM ( 5 ); break; /* DBNZ dp */
+ case 0x6f: OP_RET ( 5 ); break; /* RET */
+ case 0x70: OP_BCC ( 2, COND_VS() ); break; /* BVS */
+ case 0x71: OP_TCALL ( 8, 7 ); break; /* TCALL 7 */
+ case 0x72: OP_CLR ( 4, BIT_3 ); break; /* CLR 3 */
+ case 0x73: OP_BBC ( 5, BIT_3 ); break; /* BBC 3 */
+ case 0x74: OP_CMPR ( 4, REG_A, DPX ); break; /* CMP A, dpx */
+ case 0x75: OP_CMPR ( 5, REG_A, ABX ); break; /* CMP A, abx */
+ case 0x76: OP_CMPR ( 5, REG_A, ABY ); break; /* CMP A, aby */
+ case 0x77: OP_CMPR ( 6, REG_A, DIY ); break; /* CMP A, diy */
+ case 0x78: OP_CMPM ( 5, IMM, DP ); break; /* CMP dp, imm */
+ case 0x79: OP_CMPM ( 5, YI, XI ); break; /* CMP xi, yi */
+ case 0x7a: OP_ADDW ( 5 ); break; /* ADDW di */
+ case 0x7b: OP_RORM ( 5, DPX ); break; /* ROR dpx */
+ case 0x7c: OP_ROR ( 2 ); break; /* ROR A */
+ case 0x7d: OP_MOVRR ( 2, REG_X, REG_A ); break; /* MOV A, X */
+ case 0x7e: OP_CMPR ( 3, REG_Y, DP ); break; /* CMP Y, dp */
+ case 0x7f: OP_RETI ( 6 ); break; /* RETI */
+ case 0x80: OP_SETC ( 2 ); break; /* SETC */
+ case 0x81: OP_TCALL ( 8, 8 ); break; /* TCALL 8 */
+ case 0x82: OP_SET ( 4, BIT_4 ); break; /* SET 4 */
+ case 0x83: OP_BBS ( 5, BIT_4 ); break; /* BBS 4 */
+ case 0x84: OP_ADC ( 3, DP ); break; /* ADC dp */
+ case 0x85: OP_ADC ( 4, ABS ); break; /* ADC abs */
+ case 0x86: OP_ADC ( 3, XI ); break; /* ADC xi */
+ case 0x87: OP_ADC ( 6, DXI ); break; /* ADC dxi */
+ case 0x88: OP_ADC ( 2, IMM ); break; /* ADC imm */
+ case 0x89: OP_ADCM ( 6, DP, DP ); break; /* ADC dp, dp */
+ case 0x8a: OP_EOR1 ( 4 ); break; /* EOR1 bit */
+ case 0x8b: OP_DECM ( 4, DP ); break; /* DEC dp */
+ case 0x8c: OP_DECM ( 5, ABS ); break; /* DEC abs */
+ case 0x8d: OP_MOVMR ( 2, IMM, REG_Y ); break; /* MOV Y, imm */
+ case 0x8e: OP_PLP ( 4 ); break; /* POP PSW */
+ case 0x8f: OP_MOVMM ( 5, IMM, DP ); break; /* MOV dp, imm */
+ case 0x90: OP_BCC ( 2, COND_CC() ); break; /* BCC */
+ case 0x91: OP_TCALL ( 8, 9 ); break; /* TCALL 9 */
+ case 0x92: OP_CLR ( 4, BIT_4 ); break; /* CLR 4 */
+ case 0x93: OP_BBC ( 5, BIT_4 ); break; /* BBC 4 */
+ case 0x94: OP_ADC ( 4, DPX ); break; /* ADC dpx */
+ case 0x95: OP_ADC ( 5, ABX ); break; /* ADC abx */
+ case 0x96: OP_ADC ( 5, ABY ); break; /* ADC aby */
+ case 0x97: OP_ADC ( 6, DIY ); break; /* ADC diy */
+ case 0x98: OP_ADCM ( 5, IMM, DP ); break; /* ADC dp, imm */
+ case 0x99: OP_ADCM ( 5, YI, XI ); break; /* ADC xi, yi */
+ case 0x9a: OP_SUBW ( 5 ); break; /* SUBW dp */
+ case 0x9b: OP_DECM ( 5, DPX ); break; /* DEC dpx */
+ case 0x9c: OP_DECR ( 2, REG_A ); break; /* DEC A */
+ case 0x9d: OP_MOVSX ( 2 ); break; /* MOV X, SP */
+ case 0x9e: OP_DIV (12 ); break; /* DIV YA, X */
+ case 0x9f: OP_XCN ( 5 ); break; /* XCN A */
+ case 0xa0: OP_EI ( 3 ); break; /* EI */
+ case 0xa1: OP_TCALL ( 8, 10 ); break; /* TCALL 10 */
+ case 0xa2: OP_SET ( 4, BIT_5 ); break; /* SET 5 */
+ case 0xa3: OP_BBS ( 5, BIT_5 ); break; /* BBS 5 */
+ case 0xa4: OP_SBC ( 3, DP ); break; /* SBC dp */
+ case 0xa5: OP_SBC ( 4, ABS ); break; /* SBC abs */
+ case 0xa6: OP_SBC ( 3, XI ); break; /* SBC xi */
+ case 0xa7: OP_SBC ( 6, DXI ); break; /* SBC dxi */
+ case 0xa8: OP_SBC ( 2, IMM ); break; /* SBC imm */
+ case 0xa9: OP_SBCM ( 6, DP, DP ); break; /* SBC dp, dp */
+ case 0xaa: OP_MOV1C ( 4 ); break; /* MOV1 bit->C */
+ case 0xab: OP_INCM ( 4, DP ); break; /* INC dp */
+ case 0xac: OP_INCM ( 5, ABS ); break; /* INC abs */
+ case 0xad: OP_CMPR ( 2, REG_Y, IMM ); break; /* CMP Y, imm */
+ case 0xae: OP_PULL ( 4, REG_A ); break; /* POP A */
+ case 0xaf: OP_MOVRM ( 4, REG_A, XII ); break; /* MOV xii, A */
+ case 0xb0: OP_BCC ( 2, COND_CS() ); break; /* BCS */
+ case 0xb1: OP_TCALL ( 8, 11 ); break; /* TCALL 11 */
+ case 0xb2: OP_CLR ( 4, BIT_5 ); break; /* CLR 5 */
+ case 0xb3: OP_BBC ( 5, BIT_5 ); break; /* BBC 5 */
+ case 0xb4: OP_SBC ( 4, DPX ); break; /* SBC dpx */
+ case 0xb5: OP_SBC ( 5, ABX ); break; /* SBC abx */
+ case 0xb6: OP_SBC ( 5, ABY ); break; /* SBC aby */
+ case 0xb7: OP_SBC ( 6, DIY ); break; /* SBC diy */
+ case 0xb8: OP_SBCM ( 5, IMM, DP ); break; /* SBC dp, imm */
+ case 0xb9: OP_SBCM ( 5, YI, XI ); break; /* SBC xi, yi */
+ case 0xba: OP_MOVWMR( 5 ); break; /* MOVW YA, dp */
+ case 0xbb: OP_INCM ( 5, DPX ); break; /* INC dpx */
+ case 0xbc: OP_INCR ( 2, REG_A ); break; /* INC A */
+ case 0xbd: OP_MOVXS ( 2 ); break; /* MOV SP, X */
+ case 0xbe: OP_DAS ( 3 ); break; /* DAS A */
+ case 0xbf: OP_MOVMR ( 4, XII, REG_A ); break; /* MOV A, xii */
+ case 0xc0: OP_DI ( 3 ); break; /* DI */
+ case 0xc1: OP_TCALL ( 8, 12 ); break; /* TCALL 12 */
+ case 0xc2: OP_SET ( 4, BIT_6 ); break; /* SET 6 */
+ case 0xc3: OP_BBS ( 5, BIT_6 ); break; /* BBS 6 */
+ case 0xc4: OP_MOVRM ( 4, REG_A, DP ); break; /* MOV dp, A */
+ case 0xc5: OP_MOVRM ( 5, REG_A, ABS ); break; /* MOV abs, A */
+ case 0xc6: OP_MOVRM ( 4, REG_A, XI ); break; /* MOV xi, A */
+ case 0xc7: OP_MOVRM ( 7, REG_A, DXI ); break; /* MOV dxi, A */
+ case 0xc8: OP_CMPR ( 2, REG_X, IMM ); break; /* CMP X, imm */
+ case 0xc9: OP_MOVRM ( 5, REG_X, ABS ); break; /* MOV abs, X */
+ case 0xca: OP_MOV1M ( 6 ); break; /* MOV1 C->bit */
+ case 0xcb: OP_MOVRM ( 4, REG_Y, DP ); break; /* MOV dp, Y */
+ case 0xcc: OP_MOVRM ( 5, REG_Y, ABS ); break; /* MOV abs, Y */
+ case 0xcd: OP_MOVMR ( 2, IMM, REG_X ); break; /* MOV X, imm */
+ case 0xce: OP_PULL ( 4, REG_X ); break; /* POP X */
+ case 0xcf: OP_MUL ( 9 ); break; /* MUL YA */
+ case 0xd0: OP_BCC ( 2, COND_NE() ); break; /* BNE */
+ case 0xd1: OP_TCALL ( 8, 13 ); break; /* TCALL 13 */
+ case 0xd2: OP_CLR ( 4, BIT_6 ); break; /* CLR 6 */
+ case 0xd3: OP_BBC ( 5, BIT_6 ); break; /* BBC 6 */
+ case 0xd4: OP_MOVRM ( 5, REG_A, DPX ); break; /* MOV dpx, A */
+ case 0xd5: OP_MOVRM ( 6, REG_A, ABX ); break; /* MOV abx, A */
+ case 0xd6: OP_MOVRM ( 6, REG_A, ABY ); break; /* MOV aby, A */
+ case 0xd7: OP_MOVRM ( 7, REG_A, DIY ); break; /* MOV diy, A */
+ case 0xd8: OP_MOVRM ( 4, REG_X, DP ); break; /* MOV dp, X */
+ case 0xd9: OP_MOVRM ( 5, REG_X, DPY ); break; /* MOV dpy, X */
+ case 0xda: OP_MOVWRM( 5 ); break; /* MOVW dp, YA */
+ case 0xdb: OP_MOVRM ( 5, REG_Y, DPX ); break; /* MOV dpx, Y */
+ case 0xdc: OP_DECR ( 2, REG_Y ); break; /* DEC Y */
+ case 0xdd: OP_MOVRR ( 2, REG_Y, REG_A ); break; /* MOV A, Y */
+ case 0xde: OP_CBNE ( 6, DPX ); break; /* CBNE dpx */
+ case 0xdf: OP_DAA ( 3 ); break; /* DAA */
+ case 0xe0: OP_CLRV ( 2 ); break; /* CLRV */
+ case 0xe1: OP_TCALL ( 8, 14 ); break; /* TCALL 14 */
+ case 0xe2: OP_SET ( 4, BIT_7 ); break; /* SET 7 */
+ case 0xe3: OP_BBS ( 5, BIT_7 ); break; /* BBS 7 */
+ case 0xe4: OP_MOVMR ( 3, DP, REG_A ); break; /* MOV A, dp */
+ case 0xe5: OP_MOVMR ( 4, ABS, REG_A ); break; /* MOV A, abs */
+ case 0xe6: OP_MOVMR ( 3, XI, REG_A ); break; /* MOV A, xi */
+ case 0xe7: OP_MOVMR ( 6, DXI, REG_A ); break; /* MOV A, dxi */
+ case 0xe8: OP_MOVMR ( 2, IMM, REG_A ); break; /* CMP A, imm */
+ case 0xe9: OP_MOVMR ( 4, ABS, REG_X ); break; /* MOV X, abs */
+ case 0xea: OP_NOT1 ( 5 ); break; /* NOT1 */
+ case 0xeb: OP_MOVMR ( 3, DP, REG_Y ); break; /* MOV Y, dp */
+ case 0xec: OP_MOVMR ( 4, ABS, REG_Y ); break; /* MOV Y, abs */
+ case 0xed: OP_NOTC ( 3 ); break; /* NOTC */
+ case 0xee: OP_PULL ( 4, REG_Y ); break; /* POP Y */
+ case 0xef: OP_SLEEP ( 3 ); break; /* SLEEP */
+ case 0xf0: OP_BCC ( 2, COND_EQ() ); break; /* BEQ */
+ case 0xf1: OP_TCALL ( 8, 15 ); break; /* TCALL1 5 */
+ case 0xf2: OP_CLR ( 4, BIT_7 ); break; /* CLR 7 */
+ case 0xf3: OP_BBC ( 5, BIT_7 ); break; /* BBC 7 */
+ case 0xf4: OP_MOVMR ( 4, DPX, REG_A ); break; /* MOV A, dpx */
+ case 0xf5: OP_MOVMR ( 5, ABX, REG_A ); break; /* MOV A, abx */
+ case 0xf6: OP_MOVMR ( 5, ABY, REG_A ); break; /* MOV A, aby */
+ case 0xf7: OP_MOVMR ( 6, DIY, REG_A ); break; /* MOV A, diy */
+ case 0xf8: OP_MOVMR ( 3, DP, REG_X ); break; /* MOV X, dp */
+ case 0xf9: OP_MOVMR ( 4, DPY, REG_X ); break; /* MOV X, dpy */
+ case 0xfa: OP_MOVMM ( 5, DP, DP ); break; /* MOV dp, dp */
+ case 0xfb: OP_MOVMR ( 4, DPX, REG_Y ); break; /* MOV Y, DPX */
+ case 0xfc: OP_INCR ( 2, REG_Y ); break; /* INC Y */
+ case 0xfd: OP_MOVRR ( 2, REG_A, REG_Y ); break; /* MOV Y, A */
+ case 0xfe: OP_DBNZR ( 4 ); break; /* DBNZ Y */
+ case 0xff: OP_STOP ( 3 ); break; /* STOP */
+ }
+ }
+}
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( spc700 )
+{
+ spc700i_cpu *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: spc700_set_irq_line(cpustate, 0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: spc700_set_nmi_line(cpustate, info->i); break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + SPC700_PC: REG_PC = MAKE_UINT_16(info->i); break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + SPC700_S: REG_S = MAKE_UINT_8(info->i); break;
+ case CPUINFO_INT_REGISTER + SPC700_P: SET_REG_P(cpustate, info->i); break;
+ case CPUINFO_INT_REGISTER + SPC700_A: REG_A = MAKE_UINT_8(info->i); break;
+ case CPUINFO_INT_REGISTER + SPC700_X: REG_X = MAKE_UINT_8(info->i); break;
+ case CPUINFO_INT_REGISTER + SPC700_Y: REG_Y = MAKE_UINT_8(info->i); break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( spc700 )
+{
+ spc700i_cpu *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+ uint p = 0;
+
+ if (cpustate != NULL)
+ {
+ p = ((cpustate->flag_n & 0x80) |
+ ((cpustate->flag_v & 0x80) >> 1) |
+ cpustate->flag_p>>3 |
+ cpustate->flag_b |
+ (cpustate->flag_h & HFLAG_SET) |
+ cpustate->flag_i |
+ ((!cpustate->flag_z) << 1) |
+ ((cpustate->flag_c >> 8)&1));
+ }
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(spc700i_cpu); 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 = 3; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 2; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 8; 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 + 0: info->i = (LINE_IRQ == IRQ_SET) ? ASSERT_LINE : CLEAR_LINE; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = REG_PPC; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + SPC700_PC: info->i = REG_PC; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + SPC700_S: info->i = REG_S + STACK_PAGE; break;
+ case CPUINFO_INT_REGISTER + SPC700_P: info->i = GET_REG_P(); break;
+ case CPUINFO_INT_REGISTER + SPC700_A: info->i = REG_A; break;
+ case CPUINFO_INT_REGISTER + SPC700_X: info->i = REG_X; break;
+ case CPUINFO_INT_REGISTER + SPC700_Y: info->i = REG_Y; 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(spc700); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(spc700); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(spc700); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(spc700); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(spc700); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(spc700); 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, "SPC700"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Sony SPC700"); 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 Nicola Salmoria and the MAME team, all rights reserved."); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c",
+ p & 0x80 ? 'N':'.',
+ p & 0x40 ? 'V':'.',
+ p & 0x20 ? 'P':'.',
+ p & 0x10 ? 'B':'.',
+ p & 0x08 ? 'H':'.',
+ p & 0x04 ? 'I':'.',
+ p & 0x02 ? 'Z':'.',
+ p & 0x01 ? 'C':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + SPC700_PC: sprintf(info->s, "PC:%04X", cpustate->pc); break;
+ case CPUINFO_STR_REGISTER + SPC700_S: sprintf(info->s, "S:%02X", cpustate->s); break;
+ case CPUINFO_STR_REGISTER + SPC700_P: sprintf(info->s, "P:%02X", p); break;
+ case CPUINFO_STR_REGISTER + SPC700_A: sprintf(info->s, "A:%02X", cpustate->a); break;
+ case CPUINFO_STR_REGISTER + SPC700_X: sprintf(info->s, "X:%02X", cpustate->x); break;
+ case CPUINFO_STR_REGISTER + SPC700_Y: sprintf(info->s, "Y:%02X", cpustate->y); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(SPC700, spc700);
+
+/* ======================================================================== */
+/* ============================== END OF FILE ============================= */
+/* ======================================================================== */
diff --git a/trunk/src/emu/cpu/spc700/spc700.h b/trunk/src/emu/cpu/spc700/spc700.h
new file mode 100644
index 00000000000..a5700a28aaf
--- /dev/null
+++ b/trunk/src/emu/cpu/spc700/spc700.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#ifndef __SPC700_H__
+#define __SPC700_H__
+
+
+DECLARE_LEGACY_CPU_DEVICE(SPC700, spc700);
+
+/* ======================================================================== */
+/* ============================= Configuration ============================ */
+/* ======================================================================== */
+
+#undef uint
+#define uint unsigned int
+
+/* Turn on optimizations for SNES since it doesn't hook up the interrupt lines */
+#define SPC700_OPTIMIZE_SNES 1
+
+
+/* ======================================================================== */
+/* ============================== PROTOTYPES ============================== */
+/* ======================================================================== */
+
+enum
+{
+ SPC700_PC=1, SPC700_S, SPC700_P, SPC700_A, SPC700_X, SPC700_Y
+};
+
+#define SPC700_INT_NONE 0
+#define SPC700_INT_IRQ 1
+#define SPC700_INT_NMI 2
+
+
+/* ======================================================================== */
+/* ============================== END OF FILE ============================= */
+/* ======================================================================== */
+
+#endif /* __SPC700_H__ */
diff --git a/trunk/src/emu/cpu/spc700/spc700ds.c b/trunk/src/emu/cpu/spc700/spc700ds.c
new file mode 100644
index 00000000000..d975f31c2d6
--- /dev/null
+++ b/trunk/src/emu/cpu/spc700/spc700ds.c
@@ -0,0 +1,433 @@
+/* ======================================================================== */
+/* =============================== COPYRIGHT ============================== */
+/* ======================================================================== */
+/*
+
+SPC700 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 "spc700ds.h"
+
+
+
+typedef struct
+{
+ unsigned char name;
+ unsigned char args[2];
+} opcode_struct;
+
+enum
+{
+ IMP , A , X , Y , YA , SP , PSW , C , REL , UPAG, IMM , XI ,
+ XII , YI , DP , DPX , DPY , DPI , DXI , DIY , ABS , ABX , ABY , AXI , N0 ,
+ N1 , N2 , N3 , N4 , N5 , N6 , N7 , N8 , N9 , N10 , N11 , N12 ,
+ N13 , N14 , N15 , DP0 , DP1 , DP2 , DP3 , DP4 , DP5 , DP6 , DP7 , MEMN,
+ MEMI
+};
+
+
+enum
+{
+ ADC , ADDW , AND , AND1 , ASL , BBC , BBS , BCC ,
+ BCS , BEQ , BMI , BNE , BPL , BRA , BRK , BVC ,
+ BVS , CALL , CBNE , CLR1 , CLRC , CLRP , CLRV , CMP ,
+ CMPW , DAA , DAS , DBNZ , DEC , DECW , DI , DIV ,
+ EI , EOR , EOR1 , INC , INCW , JMP , LSR , MOV ,
+ MOV1 , MOVW , MUL , NOP , NOT1 , NOTQ , NOTC , OR ,
+ OR1 , PCALL , POP , PUSH , RET , RETI , ROL , ROR ,
+ SBC , SET1 , SETC , SETP , SLEEP , STOP , SUBW , TCALL ,
+ TCLR1 , TSET1 , XCN
+};
+
+
+static const char *const g_opnames[] =
+{
+ "ADC ", "ADDW ", "AND ", "AND1 ", "ASL ", "BBC ", "BBS ", "BCC ",
+ "BCS ", "BEQ ", "BMI ", "BNE ", "BPL ", "BRA ", "BRK ", "BVC ",
+ "BVS ", "CALL ", "CBNE ", "CLR1 ", "CLRC ", "CLRP ", "CLRV ", "CMP ",
+ "CMPW ", "DAA ", "DAS ", "DBNZ ", "DEC ", "DECW ", "DI ", "DIV ",
+ "EI ", "EOR ", "EOR1 ", "INC ", "INCW ", "JMP ", "LSR ", "MOV ",
+ "MOV1 ", "MOVW ", "MUL ", "NOP ", "NOT1 ", "NOTQ ", "NOTC ", "OR ",
+ "OR1 ", "PCALL", "POP ", "PUSH ", "RET ", "RETI ", "ROL ", "ROR ",
+ "SBC ", "SET1 ", "SETC ", "SETP ", "SLEEP", "STOP ", "SUBW ", "TCALL",
+ "TCLR1", "TSET1", "XCN "
+};
+
+static const opcode_struct g_opcodes[256] =
+{
+/* 00 */ {NOP , {IMP , IMP }},
+/* 01 */ {TCALL , {N0 , IMP }},
+/* 02 */ {SET1 , {DP0 , IMP }},
+/* 03 */ {BBS , {DP0 , REL }},
+/* 04 */ {OR , {A , DP }},
+/* 05 */ {OR , {A , ABS }},
+/* 06 */ {OR , {A , XI }},
+/* 07 */ {OR , {A , DXI }},
+/* 08 */ {OR , {A , IMM }},
+/* 09 */ {OR , {DP , DP }},
+/* 0A */ {OR1 , {C , MEMN}},
+/* 0B */ {ASL , {DP , IMP }},
+/* 0C */ {ASL , {ABS , IMP }},
+/* 0D */ {PUSH , {PSW , IMP }},
+/* 0E */ {TSET1 , {ABS , IMP }},
+/* 0F */ {BRK , {IMM , IMP }},
+/* 10 */ {BPL , {REL , IMP }},
+/* 11 */ {TCALL , {N1 , IMP }},
+/* 12 */ {CLR1 , {DP0 , IMP }},
+/* 13 */ {BBC , {DP0 , REL }},
+/* 14 */ {OR , {A , DPX }},
+/* 15 */ {OR , {A , ABX }},
+/* 16 */ {OR , {A , ABY }},
+/* 17 */ {OR , {A , DIY }},
+/* 18 */ {OR , {DP , IMM }},
+/* 19 */ {OR , {XI , YI }},
+/* 1A */ {DECW , {DP , IMP }},
+/* 1B */ {ASL , {DPX , IMP }},
+/* 1C */ {ASL , {A , IMP }},
+/* 1D */ {DEC , {X , IMP }},
+/* 1E */ {CMP , {X , ABS }},
+/* 1F */ {JMP , {AXI , IMP }},
+/* 20 */ {CLRP , {IMP , IMP }},
+/* 21 */ {TCALL , {N2 , IMP }},
+/* 22 */ {SET1 , {DP1 , IMP }},
+/* 23 */ {BBS , {DP1 , REL }},
+/* 24 */ {AND , {A , DP }},
+/* 25 */ {AND , {A , ABS }},
+/* 26 */ {AND , {A , XI }},
+/* 27 */ {AND , {A , DXI }},
+/* 28 */ {AND , {A , IMM }},
+/* 29 */ {AND , {DP , DP }},
+/* 2A */ {OR1 , {C , MEMI}},
+/* 2B */ {ROL , {DP , IMP }},
+/* 2C */ {ROL , {ABS , IMP }},
+/* 2D */ {PUSH , {A , IMP }},
+/* 2E */ {CBNE , {DP , REL }},
+/* 2F */ {BRA , {REL , IMP }},
+/* 30 */ {BMI , {REL , IMP }},
+/* 31 */ {TCALL , {N3 , IMP }},
+/* 32 */ {CLR1 , {DP1 , IMP }},
+/* 33 */ {BBC , {DP1 , REL }},
+/* 34 */ {AND , {A , DPX }},
+/* 35 */ {AND , {A , ABX }},
+/* 36 */ {AND , {A , ABY }},
+/* 37 */ {AND , {A , DIY }},
+/* 38 */ {AND , {DP , IMM }},
+/* 39 */ {AND , {XI , YI }},
+/* 3A */ {INCW , {DI , IMP }},
+/* 3B */ {ROL , {DPX , IMP }},
+/* 3C */ {ROL , {A , IMP }},
+/* 3D */ {INC , {X , IMP }},
+/* 3E */ {CMP , {X , DP }},
+/* 3F */ {CALL , {ABS , IMP }},
+/* 40 */ {SETP , {IMP , IMP }},
+/* 41 */ {TCALL , {N4 , IMP }},
+/* 42 */ {SET1 , {DP2 , IMP }},
+/* 43 */ {BBS , {DP2 , REL }},
+/* 44 */ {EOR , {A , DP }},
+/* 45 */ {EOR , {A , ABS }},
+/* 46 */ {EOR , {A , XI }},
+/* 47 */ {EOR , {A , DXI }},
+/* 48 */ {EOR , {A , IMM }},
+/* 49 */ {EOR , {DP , DP }},
+/* 4A */ {AND1 , {C , MEMN}},
+/* 4B */ {LSR , {DP , IMP }},
+/* 4C */ {LSR , {ABS , IMP }},
+/* 4D */ {PUSH , {X , IMP }},
+/* 4E */ {TCLR1 , {ABS , IMP }},
+/* 4F */ {PCALL , {UPAG, IMP }},
+/* 50 */ {BVC , {REL , IMP }},
+/* 51 */ {TCALL , {N5 , IMP }},
+/* 52 */ {CLR1 , {DP2 , IMP }},
+/* 53 */ {BBC , {DP2 , REL }},
+/* 54 */ {EOR , {A , DPX }},
+/* 55 */ {EOR , {A , ABX }},
+/* 56 */ {EOR , {A , ABY }},
+/* 57 */ {EOR , {A , DIY }},
+/* 58 */ {EOR , {DP , IMM }},
+/* 59 */ {EOR , {XI , YI }},
+/* 5A */ {CMPW , {DP , IMP }},
+/* 5B */ {LSR , {DPX , IMP }},
+/* 5C */ {LSR , {A , IMP }},
+/* 5D */ {MOV , {X , A }},
+/* 5E */ {CMP , {Y , ABS }},
+/* 5F */ {JMP , {ABS , IMP }},
+/* 60 */ {CLRC , {IMP , IMP }},
+/* 61 */ {TCALL , {N6 , IMP }},
+/* 62 */ {SET1 , {DP3 , IMP }},
+/* 63 */ {BBS , {DP3 , REL }},
+/* 64 */ {CMP , {A , DP }},
+/* 65 */ {CMP , {A , ABS }},
+/* 66 */ {CMP , {A , XI }},
+/* 67 */ {CMP , {A , DXI }},
+/* 68 */ {CMP , {A , IMM }},
+/* 69 */ {CMP , {DP , DP }},
+/* 6A */ {AND1 , {C , MEMI}},
+/* 6B */ {ROR , {DP , IMP }},
+/* 6C */ {ROR , {ABS , IMP }},
+/* 6D */ {PUSH , {Y , IMP }},
+/* 6E */ {DBNZ , {DP , REL }},
+/* 6F */ {RET , {IMP , IMP }},
+/* 70 */ {BVS , {REL , IMP }},
+/* 71 */ {TCALL , {N7 , IMP }},
+/* 72 */ {CLR1 , {DP3 , IMP }},
+/* 73 */ {BBC , {DP3 , REL }},
+/* 74 */ {CMP , {A , DPX }},
+/* 75 */ {CMP , {A , ABX }},
+/* 76 */ {CMP , {A , ABY }},
+/* 77 */ {CMP , {A , DIY }},
+/* 78 */ {CMP , {IMM , DP }},
+/* 79 */ {CMP , {XI , YI }},
+/* 7A */ {ADDW , {DI , IMP }},
+/* 7B */ {ROR , {DPX , IMP }},
+/* 7C */ {ROR , {A , IMP }},
+/* 7D */ {MOV , {A , X }},
+/* 7E */ {CMP , {Y , DP }},
+/* 7F */ {RETI , {IMP , IMP }},
+/* 80 */ {SETC , {IMP , IMP }},
+/* 81 */ {TCALL , {N8 , IMP }},
+/* 82 */ {SET1 , {DP4 , IMP }},
+/* 83 */ {BBS , {DP4 , REL }},
+/* 84 */ {ADC , {A , DP }},
+/* 85 */ {ADC , {A , ABS }},
+/* 86 */ {ADC , {A , XI }},
+/* 87 */ {ADC , {A , DXI }},
+/* 88 */ {ADC , {A , IMM }},
+/* 89 */ {ADC , {DP , DP }},
+/* 8A */ {EOR1 , {C , MEMN}},
+/* 8B */ {DEC , {DP , IMP }},
+/* 8C */ {DEC , {ABS , IMP }},
+/* 8D */ {MOV , {Y , IMM }},
+/* 8E */ {POP , {PSW , IMP }},
+/* 8F */ {MOV , {IMM , DP }},
+/* 90 */ {BCC , {REL , IMP }},
+/* 91 */ {TCALL , {N9 , IMP }},
+/* 92 */ {CLR1 , {DP4 , IMP }},
+/* 93 */ {BBC , {DP4 , REL }},
+/* 94 */ {ADC , {A , DPX }},
+/* 95 */ {ADC , {A , ABX }},
+/* 96 */ {ADC , {A , ABY }},
+/* 97 */ {ADC , {A , DIY }},
+/* 98 */ {ADC , {DP , IMM }},
+/* 99 */ {ADC , {XI , YI }},
+/* 9A */ {SUBW , {DP , IMP }},
+/* 9B */ {DEC , {DPX , IMP }},
+/* 9C */ {DEC , {A , IMP }},
+/* 9D */ {MOV , {X , SP }},
+/* 9E */ {DIV , {YA , X }},
+/* 9F */ {XCN , {A , IMP }},
+/* A0 */ {EI , {IMP , IMP }},
+/* A1 */ {TCALL , {N10 , IMP }},
+/* A2 */ {SET1 , {DP5 , IMP }},
+/* A3 */ {BBS , {DP5 , REL }},
+/* A4 */ {SBC , {A , DP }},
+/* A5 */ {SBC , {A , ABS }},
+/* A6 */ {SBC , {A , XI }},
+/* A7 */ {SBC , {A , DXI }},
+/* A8 */ {SBC , {A , IMM }},
+/* A9 */ {SBC , {DP , DP }},
+/* AA */ {MOV1 , {C , MEMN}},
+/* AB */ {INC , {DP , IMP }},
+/* AC */ {INC , {ABS , IMP }},
+/* AD */ {CMP , {Y , IMM }},
+/* AE */ {POP , {A , IMP }},
+/* AF */ {MOV , {XII , A }},
+/* B0 */ {BCS , {REL , IMP }},
+/* B1 */ {TCALL , {N11 , IMP }},
+/* B2 */ {CLR1 , {DP5 , IMP }},
+/* B3 */ {BBC , {DP5 , REL }},
+/* B4 */ {SBC , {A , DPX }},
+/* B5 */ {SBC , {A , ABX }},
+/* B6 */ {SBC , {A , ABY }},
+/* B7 */ {SBC , {A , DIY }},
+/* B8 */ {SBC , {DP , IMM }},
+/* B9 */ {SBC , {XI , YI }},
+/* BA */ {MOVW , {YA , DP }},
+/* BB */ {INC , {DPX , IMP }},
+/* BC */ {INC , {A , IMP }},
+/* BD */ {MOV , {SP , X }},
+/* BE */ {DAS , {A , IMP }},
+/* BF */ {MOV , {A , XII }},
+/* C0 */ {DI , {IMP , IMP }},
+/* C1 */ {TCALL , {N12 , IMP }},
+/* C2 */ {SET1 , {DP6 , IMP }},
+/* C3 */ {BBS , {DP6 , REL }},
+/* C4 */ {MOV , {DP , A }},
+/* C5 */ {MOV , {ABS , A }},
+/* C6 */ {MOV , {XI , A }},
+/* C7 */ {MOV , {DXI , A }},
+/* C8 */ {CMP , {X , IMM }},
+/* C9 */ {MOV , {ABS , X }},
+/* CA */ {MOV1 , {MEMN, C }},
+/* CB */ {MOV , {DP , Y }},
+/* CC */ {MOV , {ABS , Y }},
+/* CD */ {MOV , {X , IMM }},
+/* CE */ {POP , {X , IMP }},
+/* CF */ {MUL , {YA , IMP }},
+/* D0 */ {BNE , {REL , IMP }},
+/* D1 */ {TCALL , {N13 , IMP }},
+/* D2 */ {CLR1 , {DP6 , IMP }},
+/* D3 */ {BBC , {DP6 , REL }},
+/* D4 */ {MOV , {DPX , A }},
+/* D5 */ {MOV , {ABX , A }},
+/* D6 */ {MOV , {ABY , A }},
+/* D7 */ {MOV , {DIY , A }},
+/* D8 */ {MOV , {DP , X }},
+/* D9 */ {MOV , {DPY , X }},
+/* DA */ {MOVW , {DP , YA }},
+/* DB */ {MOV , {DPX , Y }},
+/* DC */ {DEC , {Y , IMP }},
+/* DD */ {MOV , {A , Y }},
+/* DE */ {CBNE , {DPX , REL }},
+/* DF */ {DAA , {IMP , IMP }},
+/* E0 */ {CLRV , {IMP , IMP }},
+/* E1 */ {TCALL , {N14 , IMP }},
+/* E2 */ {SET1 , {DP7 , IMP }},
+/* E3 */ {BBS , {DP7 , REL }},
+/* E4 */ {MOV , {A , DP }},
+/* E5 */ {MOV , {A , ABS }},
+/* E6 */ {MOV , {A , XI }},
+/* E7 */ {MOV , {A , DXI }},
+/* E8 */ {MOV , {A , IMM }},
+/* E9 */ {MOV , {X , ABS }},
+/* EA */ {NOT1 , {IMP , IMP }},
+/* EB */ {MOV , {Y , DP }},
+/* EC */ {MOV , {Y , ABS }},
+/* ED */ {NOTC , {IMP , IMP }},
+/* EE */ {POP , {Y , IMP }},
+/* EF */ {SLEEP , {IMP , IMP }},
+/* F0 */ {BEQ , {REL , IMP }},
+/* F1 */ {TCALL , {N15 , IMP }},
+/* F2 */ {CLR1 , {DP7 , IMP }},
+/* F3 */ {BBC , {DP7 , REL }},
+/* F4 */ {MOV , {A , DPX }},
+/* F5 */ {MOV , {A , ABX }},
+/* F6 */ {MOV , {A , ABY }},
+/* F7 */ {MOV , {A , DIY }},
+/* F8 */ {MOV , {X , DP }},
+/* F9 */ {MOV , {X , DPY }},
+/* FA */ {MOV , {DP , DP }},
+/* FB */ {MOV , {Y , DPX }},
+/* FC */ {INC , {Y , IMP }},
+/* FD */ {MOV , {Y , A }},
+/* FE */ {DBNZ , {Y , REL }},
+/* FF */ {STOP , {IMP , IMP }},
+};
+
+static unsigned int g_pc;
+static const UINT8 *rombase;
+
+INLINE unsigned int read_8_immediate(void)
+{
+ g_pc++;
+ return *rombase++;
+}
+
+INLINE unsigned int read_16_immediate(void)
+{
+ unsigned int result;
+ g_pc += 2;
+ result = *rombase++;
+ return result | (*rombase++ << 8);
+}
+
+CPU_DISASSEMBLE( spc700 )
+{
+ const opcode_struct* opcode;
+ UINT32 flags = 0;
+ char* ptr;
+ int var;
+ int i;
+
+ g_pc = pc;
+ rombase = oprom;
+ opcode = g_opcodes + read_8_immediate();
+
+ sprintf(buffer, "%s ", g_opnames[opcode->name]);
+ ptr = buffer + strlen(buffer);
+
+ if (opcode->name == CALL)
+ flags = DASMFLAG_STEP_OVER;
+ else if (opcode->name == RET || opcode->name == RETI)
+ flags = DASMFLAG_STEP_OUT;
+
+ for(i=0;i<2;i++)
+ {
+ if(i == 1 && opcode->args[0] != IMP && opcode->args[1] != IMP)
+ {
+ sprintf(ptr, ",");
+ ptr += strlen(ptr);
+ }
+
+ switch(opcode->args[i])
+ {
+ case IMP: break;
+ case A: sprintf(ptr, "A"); break;
+ case X: sprintf(ptr, "X"); break;
+ case Y: sprintf(ptr, "Y"); break;
+ case YA: sprintf(ptr, "YA"); break;
+ case SP: sprintf(ptr, "SP"); break;
+ case PSW: sprintf(ptr, "PSW"); break;
+ case C: sprintf(ptr, "C"); break;
+ case REL: sprintf(ptr, "%04x", ((g_pc + (char)read_8_immediate())&0xffff)); break;
+ case UPAG: sprintf(ptr, "$%02x", read_8_immediate()); break;
+ case IMM: sprintf(ptr, "#$%02x", read_8_immediate()); break;
+ case XI: sprintf(ptr, "(X)"); break;
+ case XII: sprintf(ptr, "(X)+"); break;
+ case YI: sprintf(ptr, "(Y)"); break;
+ case DP: sprintf(ptr, "$%02x", read_8_immediate()); break;
+ case DPX: sprintf(ptr, "$%02x+X", read_8_immediate()); break;
+ case DPY: sprintf(ptr, "$%02x+Y", read_8_immediate()); break;
+ case DPI: sprintf(ptr, "($%02x)", read_8_immediate()); break;
+ case DXI: sprintf(ptr, "($%02x+X)", read_8_immediate()); break;
+ case DIY: sprintf(ptr, "($%02x)+Y", read_8_immediate()); break;
+ case ABS: sprintf(ptr, "$%04x", read_16_immediate()); break;
+ case ABX: sprintf(ptr, "$%04x+X", read_16_immediate()); break;
+ case ABY: sprintf(ptr, "$%04x+Y", read_16_immediate()); break;
+ case AXI: sprintf(ptr, "($%04x+X)", read_16_immediate()); break;
+ case N0: sprintf(ptr, "0"); break;
+ case N1: sprintf(ptr, "1"); break;
+ case N2: sprintf(ptr, "2"); break;
+ case N3: sprintf(ptr, "3"); break;
+ case N4: sprintf(ptr, "4"); break;
+ case N5: sprintf(ptr, "5"); break;
+ case N6: sprintf(ptr, "6"); break;
+ case N7: sprintf(ptr, "7"); break;
+ case N8: sprintf(ptr, "8"); break;
+ case N9: sprintf(ptr, "9"); break;
+ case N10: sprintf(ptr, "10"); break;
+ case N11: sprintf(ptr, "11"); break;
+ case N12: sprintf(ptr, "12"); break;
+ case N13: sprintf(ptr, "13"); break;
+ case N14: sprintf(ptr, "14"); break;
+ case N15: sprintf(ptr, "15"); break;
+ case DP0: sprintf(ptr, "$%02x.0", read_8_immediate()); break;
+ case DP1: sprintf(ptr, "$%02x.1", read_8_immediate()); break;
+ case DP2: sprintf(ptr, "$%02x.2", read_8_immediate()); break;
+ case DP3: sprintf(ptr, "$%02x.3", read_8_immediate()); break;
+ case DP4: sprintf(ptr, "$%02x.4", read_8_immediate()); break;
+ case DP5: sprintf(ptr, "$%02x.5", read_8_immediate()); break;
+ case DP6: sprintf(ptr, "$%02x.6", read_8_immediate()); break;
+ case DP7: sprintf(ptr, "$%02x.7", read_8_immediate()); break;
+ case MEMN:
+ var = read_16_immediate();
+ sprintf(ptr, "%04x.%d", var&0x1fff, var>>13);
+ break;
+ case MEMI:
+ var = read_16_immediate();
+ sprintf(ptr, "/%04x.%d", var&0x1fff, var>>13);
+ break;
+ }
+ ptr += strlen(ptr);
+ }
+ return (g_pc - pc) | flags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/spc700/spc700ds.h b/trunk/src/emu/cpu/spc700/spc700ds.h
new file mode 100644
index 00000000000..8dcbf56b629
--- /dev/null
+++ b/trunk/src/emu/cpu/spc700/spc700ds.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#ifndef __SPC700DS_H__
+#define __SPC700DS_H__
+/* ======================================================================== */
+/* =============================== COPYRIGHT ============================== */
+/* ======================================================================== */
+/*
+
+Sony SPC700 CPU Emulator V1.0
+
+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.
+
+
+*/
+
+
+CPU_DISASSEMBLE( spc700 );
+
+
+#endif /* __SPC700DS_H__ */
diff --git a/trunk/src/emu/cpu/ssem/ssem.c b/trunk/src/emu/cpu/ssem/ssem.c
new file mode 100644
index 00000000000..22f18c12983
--- /dev/null
+++ b/trunk/src/emu/cpu/ssem/ssem.c
@@ -0,0 +1,309 @@
+/*
+ Manchester Small-Scale Experimental Machine (SSEM) emulator
+
+ Written by MooglyGuy
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "ssem.h"
+
+CPU_DISASSEMBLE( ssem );
+
+
+#define SSEM_DISASM_ON_UNIMPL 0
+#define SSEM_DUMP_MEM_ON_UNIMPL 0
+
+typedef struct _ssem_state ssem_state;
+struct _ssem_state
+{
+ UINT32 pc;
+ UINT32 a;
+ UINT32 halt;
+
+ legacy_cpu_device *device;
+ address_space *program;
+ int icount;
+};
+
+INLINE ssem_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == SSEM);
+ return (ssem_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+#define INSTR ((op >> 13) & 7)
+#define ADDR (op & 0x1f)
+
+/*****************************************************************************/
+
+// The SSEM stores its data, visually, with the leftmost bit corresponding to the least significant bit.
+// The de facto snapshot format for other SSEM simulators stores the data physically in that format as well.
+// Therefore, in MESS, every 32-bit word has its bits reversed, too, and as a result the values must be
+// un-reversed before being used.
+INLINE UINT32 reverse(UINT32 v)
+{
+ // Taken from http://www-graphics.stanford.edu/~seander/bithacks.html#ReverseParallel
+ // swap odd and even bits
+ v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1);
+ // swap consecutive pairs
+ v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2);
+ // swap nibbles ...
+ v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);
+ // swap bytes
+ v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8);
+ // swap 2-byte long pairs
+ v = ( v >> 16 ) | ( v << 16);
+
+ return v;
+}
+
+INLINE UINT32 READ32(ssem_state *cpustate, UINT32 address)
+{
+ UINT32 v = 0;
+ // The MAME core does not have a good way of specifying a minimum datum size that is more than
+ // 8 bits in width. The minimum datum width on the SSEM is 32 bits, so we need to quadruple
+ // the address value to get the appropriate byte index.
+ address <<= 2;
+
+ v |= cpustate->program->read_byte(address + 0) << 24;
+ v |= cpustate->program->read_byte(address + 1) << 16;
+ v |= cpustate->program->read_byte(address + 2) << 8;
+ v |= cpustate->program->read_byte(address + 3) << 0;
+
+ return reverse(v);
+}
+
+INLINE void WRITE32(ssem_state *cpustate, UINT32 address, UINT32 data)
+{
+ UINT32 v = reverse(data);
+
+ // The MAME core does not have a good way of specifying a minimum datum size that is more than
+ // 8 bits in width. The minimum datum width on the SSEM is 32 bits, so we need to quadruple
+ // the address value to get the appropriate byte index.
+ address <<= 2;
+
+ cpustate->program->write_byte(address + 0, (v >> 24) & 0x000000ff);
+ cpustate->program->write_byte(address + 1, (v >> 16) & 0x000000ff);
+ cpustate->program->write_byte(address + 2, (v >> 8) & 0x000000ff);
+ cpustate->program->write_byte(address + 3, (v >> 0) & 0x000000ff);
+ return;
+}
+
+/*****************************************************************************/
+
+static void unimplemented_opcode(ssem_state *cpustate, UINT32 op)
+{
+ if((cpustate->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ {
+ char string[200];
+ ssem_dasm_one(string, cpustate->pc-1, op);
+ mame_printf_debug("%08X: %s\n", cpustate->pc-1, string);
+ }
+
+#if SSEM_DISASM_ON_UNIMPL
+ {
+ char string[200] = { 0 };
+ UINT32 i = 0;
+ FILE *disasm = fopen("ssemdasm.txt", "wt");
+
+ if(disasm)
+ {
+ for(i = 0; i < 0x20; i++)
+ {
+ UINT32 opcode = reverse(READ32(cpustate, i));
+ ssem_dasm_one(string, i, opcode);
+ fprintf(disasm, "%02X: %08X %s\n", i, opcode, string);
+ }
+
+ fclose(disasm);
+ }
+ }
+#endif
+#if SSEM_DUMP_MEM_ON_UNIMPL
+ {
+ UINT32 i = 0;
+ FILE *store = fopen("ssemmem.bin", "wb");
+
+ if(store)
+ {
+ for( i = 0; i < 0x80; i++ )
+ {
+ fputc(cpustate->program->read_byte(i), store);
+ }
+ fclose(store);
+ }
+ }
+#endif
+
+ fatalerror("SSEM: unknown opcode %d (%08X) at %d\n", reverse(op) & 7, reverse(op), cpustate->pc);
+}
+
+/*****************************************************************************/
+
+static CPU_INIT( ssem )
+{
+ ssem_state *cpustate = get_safe_token(device);
+ cpustate->pc = 1;
+ cpustate->a = 0;
+ cpustate->halt = 0;
+
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+}
+
+static CPU_EXIT( ssem )
+{
+}
+
+static CPU_RESET( ssem )
+{
+ ssem_state *cpustate = get_safe_token(device);
+
+ cpustate->pc = 1;
+ cpustate->a = 0;
+ cpustate->halt = 0;
+}
+
+static CPU_EXECUTE( ssem )
+{
+ ssem_state *cpustate = get_safe_token(device);
+ UINT32 op;
+
+ cpustate->pc &= 0x1f;
+
+ while (cpustate->icount > 0)
+ {
+ debugger_instruction_hook(device, cpustate->pc);
+
+ op = READ32(cpustate, cpustate->pc);
+
+ if( !cpustate->halt )
+ {
+ cpustate->pc++;
+ }
+ else
+ {
+ op = 0x0000e000;
+ }
+
+ switch (INSTR)
+ {
+ case 0:
+ // JMP: Move the value at the specified address into the Program Counter.
+ cpustate->pc = READ32(cpustate, ADDR) + 1;
+ break;
+ case 1:
+ // JRP: Add the value at the specified address to the Program Counter.
+ cpustate->pc += (INT32)READ32(cpustate, ADDR);
+ break;
+ case 2:
+ // LDN: Load the accumulator with the two's-complement negation of the value at the specified address.
+ cpustate->a = (UINT32)(0 - (INT32)READ32(cpustate, ADDR));
+ break;
+ case 3:
+ // STO: Store the value in the accumulator at the specified address.
+ WRITE32(cpustate, ADDR, cpustate->a);
+ break;
+ case 4:
+ case 5:
+ // SUB: Subtract the value at the specified address from the accumulator.
+ cpustate->a -= READ32(cpustate, ADDR);
+ break;
+ case 6:
+ // CMP: If the accumulator is less than zero, skip the next opcode.
+ if((INT32)(cpustate->a) < 0)
+ {
+ cpustate->pc++;
+ }
+ break;
+ case 7:
+ // STP: Halt the computer.
+ cpustate->halt = 1;
+ break;
+ default:
+ // This is impossible, but it's better to be safe than sorry.
+ unimplemented_opcode(cpustate, op);
+ }
+
+ --cpustate->icount;
+ }
+}
+
+
+/*****************************************************************************/
+
+static CPU_SET_INFO( ssem )
+{
+ ssem_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 + SSEM_PC: cpustate->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + SSEM_A: cpustate->a = info->i; break;
+ case CPUINFO_INT_REGISTER + SSEM_HALT: cpustate->halt = info->i; break;
+ }
+}
+
+CPU_GET_INFO( ssem )
+{
+ ssem_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(ssem_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 = 1; 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_PC: /* intentional fallthrough */
+ case CPUINFO_INT_REGISTER + SSEM_PC: info->i = cpustate->pc << 2; break;
+ case CPUINFO_INT_REGISTER + SSEM_A: info->i = cpustate->a; break;
+ case CPUINFO_INT_REGISTER + SSEM_HALT: info->i = cpustate->halt; 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(ssem); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(ssem); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(ssem); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(ssem); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(ssem); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(ssem); 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, "SSEM"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "SSEM"); 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 + SSEM_PC: sprintf(info->s, "PC: %08X", cpustate->pc); break;
+ case CPUINFO_STR_REGISTER + SSEM_A: sprintf(info->s, "A: %08X", cpustate->a); break;
+ case CPUINFO_STR_REGISTER + SSEM_HALT: sprintf(info->s, "HALT: %d", cpustate->halt); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(SSEM, ssem);
diff --git a/trunk/src/emu/cpu/ssem/ssem.h b/trunk/src/emu/cpu/ssem/ssem.h
new file mode 100644
index 00000000000..f75f7dc0b2a
--- /dev/null
+++ b/trunk/src/emu/cpu/ssem/ssem.h
@@ -0,0 +1,23 @@
+/*
+ Manchester Small-Scale Experimental Machine (SSEM) emulator
+
+ Written by MooglyGuy
+*/
+
+#pragma once
+
+#ifndef __SSEM_H__
+#define __SSEM_H__
+
+enum
+{
+ SSEM_PC = 1,
+ SSEM_A,
+ SSEM_HALT,
+};
+
+DECLARE_LEGACY_CPU_DEVICE(SSEM, ssem);
+
+extern offs_t ssem_dasm_one(char *buffer, offs_t pc, UINT32 op);
+
+#endif /* __SSEM_H__ */
diff --git a/trunk/src/emu/cpu/ssem/ssemdasm.c b/trunk/src/emu/cpu/ssem/ssemdasm.c
new file mode 100644
index 00000000000..aa9c7d3c333
--- /dev/null
+++ b/trunk/src/emu/cpu/ssem/ssemdasm.c
@@ -0,0 +1,85 @@
+/*
+ Manchester Small-Scale Experimental Machine (SSEM) disassembler
+
+ Written by MooglyGuy
+*/
+
+#include "emu.h"
+
+static char *output;
+
+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);
+}
+
+INLINE UINT32 reverse(UINT32 v)
+{
+ // Taken from http://www-graphics.stanford.edu/~seander/bithacks.html#ReverseParallel
+ // swap odd and even bits
+ v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1);
+ // swap consecutive pairs
+ v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2);
+ // swap nibbles ...
+ v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);
+ // swap bytes
+ v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8);
+ // swap 2-byte long pairs
+ v = ( v >> 16 ) | ( v << 16);
+
+ return v;
+}
+
+offs_t ssem_dasm_one(char *buffer, offs_t pc, UINT32 op)
+{
+ UINT8 instr = (reverse(op) >> 13) & 7;
+ UINT8 addr = reverse(op) & 0x1f;
+
+ output = buffer;
+
+ switch (instr)
+ {
+ case 0: // JMP S
+ print("JMP %d", addr);
+ break;
+ case 1: // JRP S
+ print("JRP %d", addr);
+ break;
+ case 2: // LDN S
+ print("LDN %d", addr);
+ break;
+ case 3: // STO S
+ print("STO %d", addr);
+ break;
+ case 4: // SUB S
+ case 5:
+ print("SUB %d", addr);
+ break;
+ case 6: // CMP
+ print("CMP");
+ break;
+ case 7: // STP
+ print("STP");
+ break;
+ default:
+ print("???");
+ break;
+ }
+
+ return 4 | DASMFLAG_SUPPORTED;
+}
+
+/*****************************************************************************/
+
+CPU_DISASSEMBLE( ssem )
+{
+ UINT32 op = (*(UINT8 *)(opram + 0) << 24) |
+ (*(UINT8 *)(opram + 1) << 16) |
+ (*(UINT8 *)(opram + 2) << 8) |
+ (*(UINT8 *)(opram + 3) << 0);
+ return ssem_dasm_one(buffer, pc, op);
+}
diff --git a/trunk/src/emu/cpu/ssp1601/ssp1601.c b/trunk/src/emu/cpu/ssp1601/ssp1601.c
new file mode 100644
index 00000000000..57ccefa36b7
--- /dev/null
+++ b/trunk/src/emu/cpu/ssp1601/ssp1601.c
@@ -0,0 +1,916 @@
+/*
+ * Samsung SSP1601 DSP emulator
+ *
+ * Copyright 2008, Grazvydas Ignotas
+ *
+ * This code is released under the MAME license.
+ *
+ *
+ * notes:
+ * not everything is implemented, but it is accurate enough to
+ * properly emulate Virtua Racing for Genesis/MegaDrive:
+ *
+ * only Z and N status flags are emulated (others unused by VR)
+ * so all condition checks except N and Z are ignored (not used by VR)
+ * modifiers for 'OP a, ri' and ((ri)) are ignored (not used by VR)
+ * loop repeat mode when destination is (ri) is ignored
+ * ops not used by VR are not implemented
+ */
+
+#include "emu.h"
+#include "debugger.h"
+#include "ssp1601.h"
+
+CPU_DISASSEMBLE( ssp1601 );
+
+/* detect ops with unimplemented/invalid fields.
+ * Useful for homebrew or if a new VR revision pops up. */
+//#define DO_CHECKS
+
+
+
+typedef struct _ssp1601_state_t ssp1601_state_t;
+struct _ssp1601_state_t
+{
+ PAIR gr[8]; /* general regs, some are 16bit, some 32bit */
+ union {
+ unsigned char r[8]; /* pointer registers, 4 for earch bank */
+ struct {
+ unsigned char r0[4];
+ unsigned char r1[4];
+ };
+ };
+ union {
+ unsigned short RAM[256*2]; /* 2 256-word internal RAM banks */
+ struct {
+ unsigned short RAM0[256];
+ unsigned short RAM1[256];
+ };
+ };
+ UINT16 stack[6]; /* 6-level hardware stack */
+ PAIR ppc;
+
+ int g_cycles;
+
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *io;
+};
+
+INLINE ssp1601_state_t *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == SSP1601);
+ return (ssp1601_state_t *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+
+
+// 0
+#define rX ssp1601_state->gr[SSP_X].w.h
+#define rY ssp1601_state->gr[SSP_Y].w.h
+#define rA ssp1601_state->gr[SSP_A].w.h
+#define rST ssp1601_state->gr[SSP_ST].w.h // 4
+#define rSTACK ssp1601_state->gr[SSP_STACK].w.h
+#define rPC ssp1601_state->gr[SSP_PC].w.h
+#define rP ssp1601_state->gr[SSP_P]
+
+#define rAL ssp1601_state->gr[SSP_A].w.l
+#define rA32 ssp1601_state->gr[SSP_A].d
+#define rIJ ssp1601_state->r
+
+#define IJind (((op>>6)&4)|(op&3))
+
+#define PPC ssp1601_state->ppc.w.h
+
+#define FETCH() ssp1601_state->direct->read_decrypted_word(rPC++ << 1)
+#define PROGRAM_WORD(a) ssp1601_state->program->read_word((a) << 1)
+#define GET_PPC_OFFS() PPC
+
+#define REG_READ(ssp1601_state,r) (((r) <= 4) ? ssp1601_state->gr[r].w.h : reg_read_handlers[r](ssp1601_state, r))
+#define REG_WRITE(ssp1601_state,r,d) { \
+ int r1 = r; \
+ if (r1 >= 4) reg_write_handlers[r1](ssp1601_state, r1,d); \
+ else if (r1 > 0) ssp1601_state->gr[r1].w.h = d; \
+}
+
+// flags
+#define SSP_FLAG_L (1<<0xc)
+#define SSP_FLAG_Z (1<<0xd)
+#define SSP_FLAG_V (1<<0xe)
+#define SSP_FLAG_N (1<<0xf)
+
+// update ZN according to 32bit ACC.
+#define UPD_ACC_ZN \
+ rST &= ~(SSP_FLAG_Z|SSP_FLAG_N); \
+ if (!rA32) rST |= SSP_FLAG_Z; \
+ else rST |= (rA32>>16)&SSP_FLAG_N;
+
+// it seems SVP code never checks for L and OV, so we leave them out.
+#define UPD_LZVN \
+ rST &= ~(SSP_FLAG_L|SSP_FLAG_Z|SSP_FLAG_V|SSP_FLAG_N); \
+ if (!rA32) rST |= SSP_FLAG_Z; \
+ else rST |= (rA32>>16)&SSP_FLAG_N;
+
+// standard cond processing.
+// again, only Z and N is checked, as VR doesn't seem to use any other conds.
+#define COND_CHECK \
+ switch (op&0xf0) { \
+ case 0x00: cond = 1; break; /* always true */ \
+ case 0x50: cond = !((rST ^ (op<<5)) & SSP_FLAG_Z); break; /* Z matches f(?) bit */ \
+ case 0x70: cond = !((rST ^ (op<<7)) & SSP_FLAG_N); break; /* N matches f(?) bit */ \
+ default:logerror(__FILE__ " FIXME: unimplemented cond @ %04x\n", GET_PPC_OFFS()); break; \
+ }
+
+// ops with accumulator.
+// note that 'ld A' doesn't affect flags
+#define OP_LDA(x) \
+ rA = x
+
+#define OP_LDA32(x) \
+ rA32 = x
+
+#define OP_SUBA(x) { \
+ rA32 -= (x) << 16; \
+ UPD_LZVN \
+}
+
+#define OP_SUBA32(x) { \
+ rA32 -= (x); \
+ UPD_LZVN \
+}
+
+#define OP_CMPA(x) { \
+ UINT32 t = rA32 - ((x) << 16); \
+ rST &= ~(SSP_FLAG_L|SSP_FLAG_Z|SSP_FLAG_V|SSP_FLAG_N); \
+ if (!t) rST |= SSP_FLAG_Z; \
+ else rST |= (t>>16)&SSP_FLAG_N; \
+}
+
+#define OP_CMPA32(x) { \
+ UINT32 t = rA32 - (x); \
+ rST &= ~(SSP_FLAG_L|SSP_FLAG_Z|SSP_FLAG_V|SSP_FLAG_N); \
+ if (!t) rST |= SSP_FLAG_Z; \
+ else rST |= (t>>16)&SSP_FLAG_N; \
+}
+
+#define OP_ADDA(x) { \
+ rA32 += (x) << 16; \
+ UPD_LZVN \
+}
+
+#define OP_ADDA32(x) { \
+ rA32 += (x); \
+ UPD_LZVN \
+}
+
+#define OP_ANDA(x) \
+ rA32 &= (x) << 16; \
+ UPD_ACC_ZN
+
+#define OP_ANDA32(x) \
+ rA32 &= (x); \
+ UPD_ACC_ZN
+
+#define OP_ORA(x) \
+ rA32 |= (x) << 16; \
+ UPD_ACC_ZN
+
+#define OP_ORA32(x) \
+ rA32 |= (x); \
+ UPD_ACC_ZN
+
+#define OP_EORA(x) \
+ rA32 ^= (x) << 16; \
+ UPD_ACC_ZN
+
+#define OP_EORA32(x) \
+ rA32 ^= (x); \
+ UPD_ACC_ZN
+
+
+#define OP_CHECK32(OP) { \
+ if ((op & 0x0f) == SSP_P) { /* A <- P */ \
+ update_P(ssp1601_state); \
+ OP(rP.d); \
+ break; \
+ } \
+ if ((op & 0x0f) == SSP_A) { /* A <- A */ \
+ OP(rA32); \
+ break; \
+ } \
+}
+
+
+#ifdef DO_CHECKS
+#define CHECK_IMM16() if (op&0x1ff) logerror(__FILE__ " imm bits! %04x @ %04x\n", op, GET_PPC_OFFS())
+#define CHECK_B_SET() if (op&0x100) logerror(__FILE__ " b set! %04x @ %04x\n", op, GET_PPC_OFFS())
+#define CHECK_B_CLEAR() if (!(op&0x100)) logerror(__FILE__ " b clear! %04x @ %04x\n", op, GET_PPC_OFFS())
+#define CHECK_MOD() if (op&0x00c) logerror(__FILE__ " mod bits! %04x @ %04x\n", op, GET_PPC_OFFS())
+#define CHECK_10f() if (op&0x10f) logerror(__FILE__ " bits 10f! %04x @ %04x\n", op, GET_PPC_OFFS())
+#define CHECK_008() if (op&0x008) logerror(__FILE__ " bits 008! %04x @ %04x\n", op, GET_PPC_OFFS())
+#define CHECK_00f() if (op&0x00f) logerror(__FILE__ " bits 00f! %04x @ %04x\n", op, GET_PPC_OFFS())
+#define CHECK_0f0() if (op&0x0f0) logerror(__FILE__ " bits 0f0! %04x @ %04x\n", op, GET_PPC_OFFS())
+#define CHECK_1f0() if (op&0x1f0) logerror(__FILE__ " bits 1f0! %04x @ %04x\n", op, GET_PPC_OFFS())
+#define CHECK_RPL() if (rST&7) logerror(__FILE__ " unhandled RPL! %04x @ %04x\n", op, GET_PPC_OFFS())
+#define CHECK_ST(d) if((rST^d)&0xf98)logerror(__FILE__ " ssp FIXME ST %04x -> %04x @ %04x\n", rST, d, GET_PPC_OFFS())
+#else
+#define CHECK_IMM16()
+#define CHECK_B_SET()
+#define CHECK_B_CLEAR()
+#define CHECK_MOD()
+#define CHECK_10f()
+#define CHECK_008()
+#define CHECK_00f()
+#define CHECK_0f0()
+#define CHECK_1f0()
+#define CHECK_RPL()
+#define CHECK_ST(d)
+#endif
+
+#define CHIP_NAME "SSP1601"
+
+// -----------------------------------------------------
+// register i/o handlers
+
+static void update_P(ssp1601_state_t *ssp1601_state)
+{
+ int m1 = (signed short)rX;
+ int m2 = (signed short)rY;
+ rP.d = (m1 * m2 * 2);
+}
+
+static UINT32 read_unknown(ssp1601_state_t *ssp1601_state, int reg)
+{
+ logerror("%s:%i FIXME\n", __FILE__, __LINE__);
+ return 0;
+}
+
+static void write_unknown(ssp1601_state_t *ssp1601_state, int reg, UINT32 d)
+{
+ logerror("%s:%i FIXME\n", __FILE__, __LINE__);
+}
+
+/* map EXT regs to virtual I/O range of 0x00-0x0f */
+static UINT32 read_ext(ssp1601_state_t *ssp1601_state, int reg)
+{
+ reg &= 7;
+ return ssp1601_state->io->read_word((reg << 1));
+}
+
+static void write_ext(ssp1601_state_t *ssp1601_state, int reg, UINT32 d)
+{
+ reg &= 7;
+ ssp1601_state->io->write_word((reg << 1), d);
+}
+
+// 4
+static void write_ST(ssp1601_state_t *ssp1601_state, int reg, UINT32 d)
+{
+ CHECK_ST(d);
+ rST = d;
+}
+
+// 5
+static UINT32 read_STACK(ssp1601_state_t *ssp1601_state, int reg)
+{
+ --rSTACK;
+ if ((signed short)rSTACK < 0) {
+ rSTACK = 5;
+ logerror(__FILE__ " FIXME: stack underflow! (%i) @ %04x\n", rSTACK, GET_PPC_OFFS());
+ }
+ return ssp1601_state->stack[rSTACK];
+}
+
+static void write_STACK(ssp1601_state_t *ssp1601_state, int reg, UINT32 d)
+{
+ if (rSTACK >= 6) {
+ logerror(__FILE__ " FIXME: stack overflow! (%i) @ %04x\n", rSTACK, GET_PPC_OFFS());
+ rSTACK = 0;
+ }
+ ssp1601_state->stack[rSTACK++] = d;
+}
+
+// 6
+static UINT32 read_PC(ssp1601_state_t *ssp1601_state, int reg)
+{
+ return rPC;
+}
+
+static void write_PC(ssp1601_state_t *ssp1601_state, int reg, UINT32 d)
+{
+ rPC = d;
+ ssp1601_state->g_cycles--;
+}
+
+// 7
+static UINT32 read_P(ssp1601_state_t *ssp1601_state, int reg)
+{
+ update_P(ssp1601_state);
+ return rP.w.h;
+}
+
+// 15
+static UINT32 read_AL(ssp1601_state_t *ssp1601_state, int reg)
+{
+ /* apparently reading AL causes some effect on EXT bus, VR depends on that.. */
+ read_ext(ssp1601_state, reg);
+ return rAL;
+}
+
+static void write_AL(ssp1601_state_t *ssp1601_state, int reg, UINT32 d)
+{
+ write_ext(ssp1601_state, reg, d);
+ rAL = d;
+}
+
+
+typedef UINT32 (*read_func_t)(ssp1601_state_t *ssp1601_state, int reg);
+typedef void (*write_func_t)(ssp1601_state_t *ssp1601_state, int reg, UINT32 d);
+
+static const read_func_t reg_read_handlers[16] =
+{
+ read_unknown, read_unknown, read_unknown, read_unknown, // -, X, Y, A
+ read_unknown, // 4 ST
+ read_STACK,
+ read_PC,
+ read_P,
+ read_ext, // 8
+ read_ext,
+ read_ext,
+ read_ext,
+ read_ext, // 12
+ read_ext,
+ read_ext,
+ read_AL
+};
+
+static const write_func_t reg_write_handlers[16] =
+{
+ write_unknown, write_unknown, write_unknown, write_unknown, // -, X, Y, A
+ write_ST,
+ write_STACK,
+ write_PC,
+ write_unknown, // 7 P (not writable)
+ write_ext, // 8
+ write_ext,
+ write_ext,
+ write_ext,
+ write_ext, // 12
+ write_ext,
+ write_ext,
+ write_AL
+};
+
+// -----------------------------------------------------
+// pointer register handlers
+
+//
+#define ptr1_read(ssp1601_state, op) ptr1_read_(ssp1601_state, op&3,(op>>6)&4,(op<<1)&0x18)
+
+static UINT32 ptr1_read_(ssp1601_state_t *ssp1601_state, int ri, int isj2, int modi3)
+{
+ //int t = (op&3) | ((op>>6)&4) | ((op<<1)&0x18);
+ UINT32 mask, add = 0, t = ri | isj2 | modi3;
+ unsigned char *rp = NULL;
+ switch (t)
+ {
+ // mod=0 (00)
+ case 0x00:
+ case 0x01:
+ case 0x02: return ssp1601_state->RAM0[ssp1601_state->r0[t&3]];
+ case 0x03: return ssp1601_state->RAM0[0];
+ case 0x04:
+ case 0x05:
+ case 0x06: return ssp1601_state->RAM1[ssp1601_state->r1[t&3]];
+ case 0x07: return ssp1601_state->RAM1[0];
+ // mod=1 (01), "+!"
+ case 0x08:
+ case 0x09:
+ case 0x0a: return ssp1601_state->RAM0[ssp1601_state->r0[t&3]++];
+ case 0x0b: return ssp1601_state->RAM0[1];
+ case 0x0c:
+ case 0x0d:
+ case 0x0e: return ssp1601_state->RAM1[ssp1601_state->r1[t&3]++];
+ case 0x0f: return ssp1601_state->RAM1[1];
+ // mod=2 (10), "-"
+ case 0x10:
+ case 0x11:
+ case 0x12: rp = &ssp1601_state->r0[t&3]; t = ssp1601_state->RAM0[*rp];
+ if (!(rST&7)) { (*rp)--; return t; }
+ add = -1; goto modulo;
+ case 0x13: return ssp1601_state->RAM0[2];
+ case 0x14:
+ case 0x15:
+ case 0x16: rp = &ssp1601_state->r1[t&3]; t = ssp1601_state->RAM1[*rp];
+ if (!(rST&7)) { (*rp)--; return t; }
+ add = -1; goto modulo;
+ case 0x17: return ssp1601_state->RAM1[2];
+ // mod=3 (11), "+"
+ case 0x18:
+ case 0x19:
+ case 0x1a: rp = &ssp1601_state->r0[t&3]; t = ssp1601_state->RAM0[*rp];
+ if (!(rST&7)) { (*rp)++; return t; }
+ add = 1; goto modulo;
+ case 0x1b: return ssp1601_state->RAM0[3];
+ case 0x1c:
+ case 0x1d:
+ case 0x1e: rp = &ssp1601_state->r1[t&3]; t = ssp1601_state->RAM1[*rp];
+ if (!(rST&7)) { (*rp)++; return t; }
+ add = 1; goto modulo;
+ case 0x1f: return ssp1601_state->RAM1[3];
+ }
+
+ return 0;
+
+modulo:
+ mask = (1 << (rST&7)) - 1;
+ *rp = (*rp & ~mask) | ((*rp + add) & mask);
+ return t;
+}
+
+static void ptr1_write(ssp1601_state_t *ssp1601_state, int op, UINT32 d)
+{
+ int t = (op&3) | ((op>>6)&4) | ((op<<1)&0x18);
+ switch (t)
+ {
+ // mod=0 (00)
+ case 0x00:
+ case 0x01:
+ case 0x02: ssp1601_state->RAM0[ssp1601_state->r0[t&3]] = d; return;
+ case 0x03: ssp1601_state->RAM0[0] = d; return;
+ case 0x04:
+ case 0x05:
+ case 0x06: ssp1601_state->RAM1[ssp1601_state->r1[t&3]] = d; return;
+ case 0x07: ssp1601_state->RAM1[0] = d; return;
+ // mod=1 (01), "+!"
+ // mod=3, "+"
+ case 0x08:
+ case 0x09:
+ case 0x0a: ssp1601_state->RAM0[ssp1601_state->r0[t&3]++] = d; return;
+ case 0x0b: ssp1601_state->RAM0[1] = d; return;
+ case 0x0c:
+ case 0x0d:
+ case 0x0e: ssp1601_state->RAM1[ssp1601_state->r1[t&3]++] = d; return;
+ case 0x0f: ssp1601_state->RAM1[1] = d; return;
+ // mod=2 (10), "-"
+ case 0x10:
+ case 0x11:
+ case 0x12: ssp1601_state->RAM0[ssp1601_state->r0[t&3]--] = d; CHECK_RPL(); return;
+ case 0x13: ssp1601_state->RAM0[2] = d; return;
+ case 0x14:
+ case 0x15:
+ case 0x16: ssp1601_state->RAM1[ssp1601_state->r1[t&3]--] = d; CHECK_RPL(); return;
+ case 0x17: ssp1601_state->RAM1[2] = d; return;
+ // mod=3 (11), "+"
+ case 0x18:
+ case 0x19:
+ case 0x1a: ssp1601_state->RAM0[ssp1601_state->r0[t&3]++] = d; CHECK_RPL(); return;
+ case 0x1b: ssp1601_state->RAM0[3] = d; return;
+ case 0x1c:
+ case 0x1d:
+ case 0x1e: ssp1601_state->RAM1[ssp1601_state->r1[t&3]++] = d; CHECK_RPL(); return;
+ case 0x1f: ssp1601_state->RAM1[3] = d; return;
+ }
+}
+
+static UINT32 ptr2_read(ssp1601_state_t *ssp1601_state, int op)
+{
+ int mv = 0, t = (op&3) | ((op>>6)&4) | ((op<<1)&0x18);
+ switch (t)
+ {
+ // mod=0 (00)
+ case 0x00:
+ case 0x01:
+ case 0x02: mv = ssp1601_state->RAM0[ssp1601_state->r0[t&3]]++; break;
+ case 0x03: mv = ssp1601_state->RAM0[0]++; break;
+ case 0x04:
+ case 0x05:
+ case 0x06: mv = ssp1601_state->RAM1[ssp1601_state->r1[t&3]]++; break;
+ case 0x07: mv = ssp1601_state->RAM1[0]++; break;
+ // mod=1 (01)
+ case 0x0b: mv = ssp1601_state->RAM0[1]++; break;
+ case 0x0f: mv = ssp1601_state->RAM1[1]++; break;
+ // mod=2 (10)
+ case 0x13: mv = ssp1601_state->RAM0[2]++; break;
+ case 0x17: mv = ssp1601_state->RAM1[2]++; break;
+ // mod=3 (11)
+ case 0x1b: mv = ssp1601_state->RAM0[3]++; break;
+ case 0x1f: mv = ssp1601_state->RAM1[3]++; break;
+ default: logerror(__FILE__ " FIXME: unimplemented mod in ((rX)) @ %04x\n", GET_PPC_OFFS());
+ return 0;
+ }
+
+ return PROGRAM_WORD(mv);
+}
+
+
+// -----------------------------------------------------
+
+
+static CPU_INIT( ssp1601 )
+{
+ ssp1601_state_t *ssp1601_state = get_safe_token(device);
+
+ device->save_item(NAME(rX));
+ device->save_item(NAME(rY));
+ device->save_item(NAME(rA32));
+ device->save_item(NAME(rST));
+ device->save_item(NAME(rSTACK));
+ device->save_item(NAME(rPC));
+ device->save_item(NAME(rP.d));
+ device->save_item(NAME(PPC));
+ device->save_item(NAME(ssp1601_state->stack));
+ device->save_item(NAME(ssp1601_state->r));
+ device->save_item(NAME(ssp1601_state->RAM));
+
+ /* clear the state */
+ memset(ssp1601_state, 0, sizeof(ssp1601_state_t));
+ ssp1601_state->gr[0].w.h = 0xffff; // constant reg
+ ssp1601_state->device = device;
+ ssp1601_state->program = device->space(AS_PROGRAM);
+ ssp1601_state->direct = &ssp1601_state->program->direct();
+ ssp1601_state->io = device->space(AS_IO);
+
+}
+
+static CPU_EXIT( ssp1601 )
+{
+ /* nothing to do */
+}
+
+static CPU_RESET( ssp1601 )
+{
+ ssp1601_state_t *ssp1601_state = get_safe_token(device);
+
+ rPC = 0x400;
+ rSTACK = 0; // ? using ascending stack
+ rST = 0;
+}
+
+
+static CPU_EXECUTE( ssp1601 )
+{
+ ssp1601_state_t *ssp1601_state = get_safe_token(device);
+
+ while (ssp1601_state->g_cycles > 0)
+ {
+ int op;
+ UINT32 tmpv;
+
+ PPC = rPC;
+
+ debugger_instruction_hook(device, rPC);
+
+ op = FETCH();
+
+ switch (op >> 9)
+ {
+ // ld d, s
+ case 0x00:
+ CHECK_B_SET();
+ if (op == 0) break; // nop
+ if (op == ((SSP_A<<4)|SSP_P)) { // A <- P
+ update_P(ssp1601_state);
+ rA32 = rP.d;
+ }
+ else
+ {
+ tmpv = REG_READ(ssp1601_state,op & 0x0f);
+ REG_WRITE(ssp1601_state,(op & 0xf0) >> 4, tmpv);
+ }
+ break;
+
+ // ld d, (ri)
+ case 0x01: tmpv = ptr1_read(ssp1601_state, op); REG_WRITE(ssp1601_state, (op & 0xf0) >> 4, tmpv); break;
+
+ // ld (ri), s
+ case 0x02: tmpv = REG_READ(ssp1601_state,(op & 0xf0) >> 4); ptr1_write(ssp1601_state, op, tmpv); break;
+
+ // ldi d, imm
+ case 0x04: CHECK_10f(); tmpv = FETCH(); REG_WRITE(ssp1601_state, (op & 0xf0) >> 4, tmpv);ssp1601_state->g_cycles--; break;
+
+ // ld d, ((ri))
+ case 0x05: CHECK_MOD(); tmpv = ptr2_read(ssp1601_state, op); REG_WRITE(ssp1601_state, (op & 0xf0) >> 4, tmpv); ssp1601_state->g_cycles -= 2; break;
+
+ // ldi (ri), imm
+ case 0x06: tmpv = FETCH(); ptr1_write(ssp1601_state, op, tmpv); ssp1601_state->g_cycles--; break;
+
+ // ld adr, a
+ case 0x07: ssp1601_state->RAM[op & 0x1ff] = rA; break;
+
+ // ld d, ri
+ case 0x09: CHECK_MOD(); tmpv = rIJ[(op&3)|((op>>6)&4)]; REG_WRITE(ssp1601_state,(op & 0xf0) >> 4, tmpv); break;
+
+ // ld ri, s
+ case 0x0a: CHECK_MOD(); rIJ[(op&3)|((op>>6)&4)] = REG_READ(ssp1601_state,(op & 0xf0) >> 4); break;
+
+ // ldi ri, simm
+ case 0x0c:
+ case 0x0d:
+ case 0x0e:
+ case 0x0f: rIJ[(op>>8)&7] = op; break;
+
+ // call cond, addr
+ case 0x24: {
+ int cond = 0;
+ CHECK_00f();
+ COND_CHECK
+ if (cond) { int new_PC = FETCH(); write_STACK(ssp1601_state, SSP_STACK, rPC); rPC = new_PC; }
+ else rPC++;
+ ssp1601_state->g_cycles--; // always 2 cycles
+ break;
+ }
+
+ // ld d, (a)
+ case 0x25:
+ CHECK_10f();
+ tmpv = PROGRAM_WORD(rA);
+ REG_WRITE(ssp1601_state,(op & 0xf0) >> 4, tmpv);
+ ssp1601_state->g_cycles -= 2; // 3 cycles total
+ break;
+
+ // bra cond, addr
+ case 0x26: {
+ int cond = 0;
+ CHECK_00f();
+ COND_CHECK
+ if (cond) { rPC = FETCH(); }
+ else rPC++;
+ ssp1601_state->g_cycles--;
+ break;
+ }
+
+ // mod cond, op
+ case 0x48: {
+ int cond = 0;
+ CHECK_008();
+ COND_CHECK
+ if (cond) {
+ switch (op & 7) {
+ case 2: rA32 = (signed int)rA32 >> 1; break; // shr (arithmetic)
+ case 3: rA32 <<= 1; break; // shl
+ case 6: rA32 = -(signed int)rA32; break; // neg
+ case 7: if ((int)rA32 < 0) rA32 = -(signed int)rA32; break; // abs
+ default: logerror(__FILE__ " FIXME: unhandled mod %i @ %04x\n",
+ op&7, GET_PPC_OFFS());
+ }
+ UPD_ACC_ZN
+ }
+ break;
+ }
+
+ // mpys?
+ case 0x1b:
+ CHECK_B_CLEAR();
+ update_P(ssp1601_state);
+ rA32 -= rP.d;
+ UPD_ACC_ZN
+ rX = ptr1_read_(ssp1601_state, op&3, 0, (op<<1)&0x18);
+ rY = ptr1_read_(ssp1601_state, (op>>4)&3, 4, (op>>3)&0x18);
+ break;
+
+ // mpya (rj), (ri), b
+ case 0x4b:
+ CHECK_B_CLEAR();
+ update_P(ssp1601_state);
+ rA32 += rP.d;
+ UPD_ACC_ZN
+ rX = ptr1_read_(ssp1601_state, op&3, 0, (op<<1)&0x18);
+ rY = ptr1_read_(ssp1601_state, (op>>4)&3, 4, (op>>3)&0x18);
+ break;
+
+ // mld (rj), (ri), b
+ case 0x5b:
+ CHECK_B_CLEAR();
+ rA32 = 0;
+ rST &= 0x0fff;
+ rST |= SSP_FLAG_Z;
+ rX = ptr1_read_(ssp1601_state, op&3, 0, (op<<1)&0x18);
+ rY = ptr1_read_(ssp1601_state, (op>>4)&3, 4, (op>>3)&0x18);
+ break;
+
+ // OP a, s
+ case 0x10: CHECK_1f0(); OP_CHECK32(OP_SUBA32); tmpv = REG_READ(ssp1601_state,op & 0x0f); OP_SUBA(tmpv); break;
+ case 0x30: CHECK_1f0(); OP_CHECK32(OP_CMPA32); tmpv = REG_READ(ssp1601_state,op & 0x0f); OP_CMPA(tmpv); break;
+ case 0x40: CHECK_1f0(); OP_CHECK32(OP_ADDA32); tmpv = REG_READ(ssp1601_state,op & 0x0f); OP_ADDA(tmpv); break;
+ case 0x50: CHECK_1f0(); OP_CHECK32(OP_ANDA32); tmpv = REG_READ(ssp1601_state,op & 0x0f); OP_ANDA(tmpv); break;
+ case 0x60: CHECK_1f0(); OP_CHECK32(OP_ORA32 ); tmpv = REG_READ(ssp1601_state,op & 0x0f); OP_ORA (tmpv); break;
+ case 0x70: CHECK_1f0(); OP_CHECK32(OP_EORA32); tmpv = REG_READ(ssp1601_state,op & 0x0f); OP_EORA(tmpv); break;
+
+ // OP a, (ri)
+ case 0x11: CHECK_0f0(); tmpv = ptr1_read(ssp1601_state, op); OP_SUBA(tmpv); break;
+ case 0x31: CHECK_0f0(); tmpv = ptr1_read(ssp1601_state, op); OP_CMPA(tmpv); break;
+ case 0x41: CHECK_0f0(); tmpv = ptr1_read(ssp1601_state, op); OP_ADDA(tmpv); break;
+ case 0x51: CHECK_0f0(); tmpv = ptr1_read(ssp1601_state, op); OP_ANDA(tmpv); break;
+ case 0x61: CHECK_0f0(); tmpv = ptr1_read(ssp1601_state, op); OP_ORA (tmpv); break;
+ case 0x71: CHECK_0f0(); tmpv = ptr1_read(ssp1601_state, op); OP_EORA(tmpv); break;
+
+ // OP a, adr
+ case 0x03: tmpv = ssp1601_state->RAM[op & 0x1ff]; OP_LDA (tmpv); break;
+ case 0x13: tmpv = ssp1601_state->RAM[op & 0x1ff]; OP_SUBA(tmpv); break;
+ case 0x33: tmpv = ssp1601_state->RAM[op & 0x1ff]; OP_CMPA(tmpv); break;
+ case 0x43: tmpv = ssp1601_state->RAM[op & 0x1ff]; OP_ADDA(tmpv); break;
+ case 0x53: tmpv = ssp1601_state->RAM[op & 0x1ff]; OP_ANDA(tmpv); break;
+ case 0x63: tmpv = ssp1601_state->RAM[op & 0x1ff]; OP_ORA (tmpv); break;
+ case 0x73: tmpv = ssp1601_state->RAM[op & 0x1ff]; OP_EORA(tmpv); break;
+
+ // OP a, imm
+ case 0x14: CHECK_IMM16(); tmpv = FETCH(); OP_SUBA(tmpv); ssp1601_state->g_cycles--; break;
+ case 0x34: CHECK_IMM16(); tmpv = FETCH(); OP_CMPA(tmpv); ssp1601_state->g_cycles--; break;
+ case 0x44: CHECK_IMM16(); tmpv = FETCH(); OP_ADDA(tmpv); ssp1601_state->g_cycles--; break;
+ case 0x54: CHECK_IMM16(); tmpv = FETCH(); OP_ANDA(tmpv); ssp1601_state->g_cycles--; break;
+ case 0x64: CHECK_IMM16(); tmpv = FETCH(); OP_ORA (tmpv); ssp1601_state->g_cycles--; break;
+ case 0x74: CHECK_IMM16(); tmpv = FETCH(); OP_EORA(tmpv); ssp1601_state->g_cycles--; break;
+
+ // OP a, ((ri))
+ case 0x15: CHECK_MOD(); tmpv = ptr2_read(ssp1601_state, op); OP_SUBA(tmpv); ssp1601_state->g_cycles -= 2; break;
+ case 0x35: CHECK_MOD(); tmpv = ptr2_read(ssp1601_state, op); OP_CMPA(tmpv); ssp1601_state->g_cycles -= 2; break;
+ case 0x45: CHECK_MOD(); tmpv = ptr2_read(ssp1601_state, op); OP_ADDA(tmpv); ssp1601_state->g_cycles -= 2; break;
+ case 0x55: CHECK_MOD(); tmpv = ptr2_read(ssp1601_state, op); OP_ANDA(tmpv); ssp1601_state->g_cycles -= 2; break;
+ case 0x65: CHECK_MOD(); tmpv = ptr2_read(ssp1601_state, op); OP_ORA (tmpv); ssp1601_state->g_cycles -= 2; break;
+ case 0x75: CHECK_MOD(); tmpv = ptr2_read(ssp1601_state, op); OP_EORA(tmpv); ssp1601_state->g_cycles -= 2; break;
+
+ // OP a, ri
+ case 0x19: CHECK_MOD(); tmpv = rIJ[IJind]; OP_SUBA(tmpv); break;
+ case 0x39: CHECK_MOD(); tmpv = rIJ[IJind]; OP_CMPA(tmpv); break;
+ case 0x49: CHECK_MOD(); tmpv = rIJ[IJind]; OP_ADDA(tmpv); break;
+ case 0x59: CHECK_MOD(); tmpv = rIJ[IJind]; OP_ANDA(tmpv); break;
+ case 0x69: CHECK_MOD(); tmpv = rIJ[IJind]; OP_ORA (tmpv); break;
+ case 0x79: CHECK_MOD(); tmpv = rIJ[IJind]; OP_EORA(tmpv); break;
+
+ // OP simm
+ case 0x1c: CHECK_B_SET(); OP_SUBA(op & 0xff); break;
+ case 0x3c: CHECK_B_SET(); OP_CMPA(op & 0xff); break;
+ case 0x4c: CHECK_B_SET(); OP_ADDA(op & 0xff); break;
+ case 0x5c: CHECK_B_SET(); OP_ANDA(op & 0xff); break;
+ case 0x6c: CHECK_B_SET(); OP_ORA (op & 0xff); break;
+ case 0x7c: CHECK_B_SET(); OP_EORA(op & 0xff); break;
+
+ default:
+ logerror(__FILE__ " FIXME unhandled op %04x @ %04x\n", op, GET_PPC_OFFS());
+ break;
+ }
+ ssp1601_state->g_cycles--;
+ }
+
+ update_P(ssp1601_state);
+}
+
+
+/**************************************************************************
+ * MAME interface
+ **************************************************************************/
+
+static CPU_SET_INFO( ssp1601 )
+{
+ ssp1601_state_t *ssp1601_state = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+
+ case CPUINFO_INT_REGISTER + SSP_X: rX = info->i; break;
+ case CPUINFO_INT_REGISTER + SSP_Y: rY = info->i; break;
+ case CPUINFO_INT_REGISTER + SSP_A: rA32 = info->i; break;
+ case CPUINFO_INT_REGISTER + SSP_ST: rST = info->i; break;
+ case CPUINFO_INT_REGISTER + SSP_STACK: rSTACK = info->i; break;
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + SSP_PC: rPC = info->i; break;
+ case CPUINFO_INT_REGISTER + SSP_P: rP.d = info->i; break;
+ case CPUINFO_INT_REGISTER + SSP_STACK0: ssp1601_state->stack[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + SSP_STACK1: ssp1601_state->stack[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + SSP_STACK2: ssp1601_state->stack[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + SSP_STACK3: ssp1601_state->stack[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + SSP_STACK4: ssp1601_state->stack[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + SSP_STACK5: ssp1601_state->stack[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + SSP_PR0: ssp1601_state->r[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + SSP_PR1: ssp1601_state->r[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + SSP_PR2: ssp1601_state->r[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + SSP_PR3: ssp1601_state->r[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + SSP_PR4: ssp1601_state->r[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + SSP_PR5: ssp1601_state->r[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + SSP_PR6: ssp1601_state->r[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + SSP_PR7: ssp1601_state->r[7] = info->i; break;
+
+// case CPUINFO_INT_INPUT_STATE + 0: set_irq_line(0, info->i); break;
+// case CPUINFO_INT_INPUT_STATE + 1: set_irq_line(1, info->i); break;
+// case CPUINFO_INT_INPUT_STATE + 2: set_irq_line(2, info->i); break;
+ }
+}
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( ssp1601 )
+{
+ ssp1601_state_t *ssp1601_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(ssp1601_state_t); 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_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 = 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 = 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 = 16; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 4; 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_REGISTER + SSP_R0: info->i = ssp1601_state->gr[0].w.h; break;
+ case CPUINFO_INT_REGISTER + SSP_X: info->i = rX; break;
+ case CPUINFO_INT_REGISTER + SSP_Y: info->i = rY; break;
+ case CPUINFO_INT_REGISTER + SSP_A: info->i = rA32; break;
+ case CPUINFO_INT_REGISTER + SSP_ST: info->i = rST; break;
+ case CPUINFO_INT_REGISTER + SSP_STACK: info->i = rSTACK; break;
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + SSP_PC: info->i = rPC; break;
+ case CPUINFO_INT_REGISTER + SSP_P: info->i = rP.d; break;
+ case CPUINFO_INT_REGISTER + SSP_STACK0: info->i = ssp1601_state->stack[0]; break;
+ case CPUINFO_INT_REGISTER + SSP_STACK1: info->i = ssp1601_state->stack[1]; break;
+ case CPUINFO_INT_REGISTER + SSP_STACK2: info->i = ssp1601_state->stack[2]; break;
+ case CPUINFO_INT_REGISTER + SSP_STACK3: info->i = ssp1601_state->stack[3]; break;
+ case CPUINFO_INT_REGISTER + SSP_STACK4: info->i = ssp1601_state->stack[4]; break;
+ case CPUINFO_INT_REGISTER + SSP_STACK5: info->i = ssp1601_state->stack[5]; break;
+ case CPUINFO_INT_REGISTER + SSP_PR0: info->i = ssp1601_state->r[0]; break;
+ case CPUINFO_INT_REGISTER + SSP_PR1: info->i = ssp1601_state->r[1]; break;
+ case CPUINFO_INT_REGISTER + SSP_PR2: info->i = ssp1601_state->r[2]; break;
+ case CPUINFO_INT_REGISTER + SSP_PR3: info->i = ssp1601_state->r[3]; break;
+ case CPUINFO_INT_REGISTER + SSP_PR4: info->i = ssp1601_state->r[4]; break;
+ case CPUINFO_INT_REGISTER + SSP_PR5: info->i = ssp1601_state->r[5]; break;
+ case CPUINFO_INT_REGISTER + SSP_PR6: info->i = ssp1601_state->r[6]; break;
+ case CPUINFO_INT_REGISTER + SSP_PR7: info->i = ssp1601_state->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(ssp1601); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(ssp1601); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(ssp1601); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(ssp1601); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(ssp1601); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(ssp1601); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &ssp1601_state->g_cycles; 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_NAME: strcpy(info->s, CHIP_NAME); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "SSP1601 DSP"); 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 Grazvydas Ignotas"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c", (rST&SSP_FLAG_N)?'N':'.', (rST&SSP_FLAG_V)?'V':'.',
+ (rST&SSP_FLAG_Z)?'Z':'.', (rST&SSP_FLAG_L)?'L':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + SSP_R0: sprintf(info->s, "REG0 :%04X", ssp1601_state->gr[0].w.h); break;
+ case CPUINFO_STR_REGISTER + SSP_X: sprintf(info->s, "X :%04X", rX); break;
+ case CPUINFO_STR_REGISTER + SSP_Y: sprintf(info->s, "Y :%04X", rY); break;
+ case CPUINFO_STR_REGISTER + SSP_A: sprintf(info->s, "A :%08X", rA32); break;
+ case CPUINFO_STR_REGISTER + SSP_ST: sprintf(info->s, "ST :%04X", rST); break;
+ case CPUINFO_STR_REGISTER + SSP_STACK: sprintf(info->s, "STACK :%04X", rSTACK); break;
+ case CPUINFO_STR_REGISTER + SSP_PC: sprintf(info->s, "PC :%04X", rPC); break;
+ case CPUINFO_STR_REGISTER + SSP_P: sprintf(info->s, "P :%08X", rP.d); break;
+ case CPUINFO_STR_REGISTER + SSP_STACK0: sprintf(info->s, "STACK0 :%04X", ssp1601_state->stack[0]); break;
+ case CPUINFO_STR_REGISTER + SSP_STACK1: sprintf(info->s, "STACK1 :%04X", ssp1601_state->stack[1]); break;
+ case CPUINFO_STR_REGISTER + SSP_STACK2: sprintf(info->s, "STACK2 :%04X", ssp1601_state->stack[2]); break;
+ case CPUINFO_STR_REGISTER + SSP_STACK3: sprintf(info->s, "STACK3 :%04X", ssp1601_state->stack[3]); break;
+ case CPUINFO_STR_REGISTER + SSP_STACK4: sprintf(info->s, "STACK4 :%04X", ssp1601_state->stack[4]); break;
+ case CPUINFO_STR_REGISTER + SSP_STACK5: sprintf(info->s, "STACK5 :%04X", ssp1601_state->stack[5]); break;
+ case CPUINFO_STR_REGISTER + SSP_PR0: sprintf(info->s, "R0 :%02X", ssp1601_state->r[0]); break;
+ case CPUINFO_STR_REGISTER + SSP_PR1: sprintf(info->s, "R1 :%02X", ssp1601_state->r[1]); break;
+ case CPUINFO_STR_REGISTER + SSP_PR2: sprintf(info->s, "R2 :%02X", ssp1601_state->r[2]); break;
+ case CPUINFO_STR_REGISTER + SSP_PR3: sprintf(info->s, "R3 :%02X", ssp1601_state->r[3]); break;
+ case CPUINFO_STR_REGISTER + SSP_PR4: sprintf(info->s, "R4 :%02X", ssp1601_state->r[4]); break;
+ case CPUINFO_STR_REGISTER + SSP_PR5: sprintf(info->s, "R5 :%02X", ssp1601_state->r[5]); break;
+ case CPUINFO_STR_REGISTER + SSP_PR6: sprintf(info->s, "R6 :%02X", ssp1601_state->r[6]); break;
+ case CPUINFO_STR_REGISTER + SSP_PR7: sprintf(info->s, "R7 :%02X", ssp1601_state->r[7]); break;
+ }
+}
+
+// vim:ts=4
+
+
+DEFINE_LEGACY_CPU_DEVICE(SSP1601, ssp1601);
diff --git a/trunk/src/emu/cpu/ssp1601/ssp1601.h b/trunk/src/emu/cpu/ssp1601/ssp1601.h
new file mode 100644
index 00000000000..5ba83a45143
--- /dev/null
+++ b/trunk/src/emu/cpu/ssp1601/ssp1601.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#ifndef __SSP1601_H__
+#define __SSP1601_H__
+
+
+enum
+{
+ /* general registers */
+ SSP_R0, SSP_X, SSP_Y, SSP_A,
+ SSP_ST, SSP_STACK, SSP_PC, SSP_P,
+ /* hardware stack */
+ SSP_STACK0, SSP_STACK1, SSP_STACK2, SSP_STACK3, SSP_STACK4, SSP_STACK5,
+ /* pointer registers */
+ SSP_PR0, SSP_PR1, SSP_PR2, SSP_PR3, SSP_PR4, SSP_PR5, SSP_PR6, SSP_PR7
+};
+
+DECLARE_LEGACY_CPU_DEVICE(SSP1601, ssp1601);
+
+extern unsigned dasm_ssp1601(char *buffer, unsigned pc, const UINT8 *oprom);
+
+#endif /* __SSP1601_H__ */
diff --git a/trunk/src/emu/cpu/ssp1601/ssp1601d.c b/trunk/src/emu/cpu/ssp1601/ssp1601d.c
new file mode 100644
index 00000000000..9952afe6db5
--- /dev/null
+++ b/trunk/src/emu/cpu/ssp1601/ssp1601d.c
@@ -0,0 +1,298 @@
+/*
+
+ SSP1601 disassembler
+ written by Pierpaolo Prazzoli
+ updated for SSP1601 by Grazvydas Ignotas
+
+*/
+
+#include "emu.h"
+#include "debugger.h"
+
+
+static const char *const reg[16] =
+{
+ "-", "X", "Y", "A",
+ "ST", "STACK", "PC", "P",
+ "EXT0", "EXT1", "EXT2", "EXT3",
+ "EXT4", "EXT5", "EXT6", "AL"
+};
+
+static const char *const rij[8] =
+{
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7"
+};
+
+static const char *const modifier[4] =
+{
+ "", "+!", "-", "+"
+};
+
+static const char *const modifier_sf[4] =
+{
+ "|00", "|01", "|10", "|11"
+};
+
+static const char *const cond[16] =
+{
+ "always", "RESERVED", "gpi0", "gpi1",
+ "l", "z", "ov", "n",
+ "diof", "gpi2", "gpi3", "RESERVED",
+ "RESERVED", "RESERVED", "RESERVED", "RESERVED",
+};
+
+static const char *const acc_op[8] =
+{
+ "ror", "rol", "shr", "shl", "inc", "dec", "neg", "abs"
+};
+
+// pag. 81 uses different addresses!
+static const char *const flag_op[16] =
+{
+ "?", "?", "resl", "setl", "resie", "setie", "?", "?", "resop", "setop", "?", "?", "?", "?", "res", "set"
+};
+
+static const char *const arith_ops[8] =
+{
+ "", "add", "", "cmp", "add", "and", "or", "eor"
+};
+
+
+#define BIT_B ((op >> 8) & 1)
+#define RIJ rij[(BIT_B << 2) + (op & 3)]
+#define RI(i) rij[(i) & 3]
+#define RJ(i) rij[((i) & 3) + 4]
+#define MODIFIER(mod,r3) (((r3) == 3) ? modifier_sf[mod] : modifier[mod])
+#define MODIFIER_LOW MODIFIER((op >> 2) & 3, op&3)
+#define MODIFIER_HIGH MODIFIER((op >> 6) & 3, (op >> 4)&3)
+
+#define READ_OP_DASM(p) ((base_oprom[p] << 8) | base_oprom[(p) + 1])
+
+static char *get_cond(int op)
+{
+ static char scond[16];
+ if (op&0xf0) sprintf(scond, "%s=%i", cond[(op >> 4) & 0xf], BIT_B);
+ else sprintf(scond, "%s", cond[(op >> 4) & 0xf]);
+ return scond;
+}
+
+
+static unsigned dasm_ssp1601(char *buffer, unsigned pc, const UINT8 *oprom)
+{
+ const UINT8 *base_oprom;
+ UINT16 op;
+ int size = 1;
+ int flags = 0;
+
+ base_oprom = oprom;
+
+ op = READ_OP_DASM(0);
+
+ switch (op >> 9)
+ {
+ case 0x00:
+ if(op == 0)
+ {
+ // nop
+ sprintf(buffer, "nop");
+ }
+ else if((op & 0xff) == 0x65)
+ {
+ // ret
+ sprintf(buffer, "ret");
+ flags |= DASMFLAG_STEP_OUT;
+ }
+ else
+ {
+ // ld d, s
+ sprintf(buffer, "ld %s, %s", reg[(op >> 4) & 0xf], reg[op & 0xf]);
+ }
+ break;
+
+ // ld d, (ri)
+ case 0x01:
+ sprintf(buffer, "ld %s, (%s%s)", reg[(op >> 4) & 0xf], RIJ, MODIFIER_LOW);
+ break;
+
+ // ld (ri), s
+ case 0x02:
+ sprintf(buffer, "ld (%s%s), %s", RIJ, MODIFIER_LOW, reg[(op >> 4) & 0xf]);
+ break;
+
+ // ld a, addr
+ case 0x03:
+ sprintf(buffer, "ld A, %X", op & 0x1ff);
+ break;
+
+ // ldi d, imm
+ case 0x04:
+ sprintf(buffer, "ld %s, %X", reg[(op >> 4) & 0xf], READ_OP_DASM(2));
+ size = 2;
+ break;
+
+ // ld d, ((ri))
+ case 0x05:
+ sprintf(buffer, "ld %s, ((%s%s))", reg[(op >> 4) & 0xf], RIJ, MODIFIER_LOW);
+ break;
+
+ // ldi (ri), imm
+ case 0x06:
+ sprintf(buffer, "ld (%s%s), %X", RIJ, MODIFIER_LOW, READ_OP_DASM(2));
+ size = 2;
+ break;
+
+ // ld addr, a
+ case 0x07:
+ sprintf(buffer, "ld %X, A", op & 0x1ff);
+ break;
+
+ // ld d, ri
+ case 0x09:
+ sprintf(buffer, "ld %s, %s%s", reg[(op >> 4) & 0xf], RIJ, MODIFIER_LOW);
+ break;
+
+ // ld ri, s
+ case 0x0a:
+ sprintf(buffer, "ld %s%s, %s", RIJ, MODIFIER_LOW, reg[(op >> 4) & 0xf]);
+ break;
+
+ // ldi ri, simm
+ case 0x0c:
+ case 0x0d:
+ case 0x0e:
+ case 0x0f:
+ sprintf(buffer, "ldi %s, %X", rij[(op >> 8) & 7], op & 0xff);
+ break;
+
+ // op a, s
+ case 0x10:
+ case 0x30:
+ case 0x40:
+ case 0x50:
+ case 0x60:
+ case 0x70:
+ sprintf(buffer, "%s A, %s", arith_ops[op >> 13], reg[op & 0xf]);
+ break;
+
+ // op a, (ri)
+ case 0x11:
+ case 0x31:
+ case 0x41:
+ case 0x51:
+ case 0x61:
+ case 0x71:
+ sprintf(buffer, "%s A, (%s%s)", arith_ops[op >> 13], RIJ, MODIFIER_LOW);
+ break;
+
+ // op a, adr
+ case 0x13:
+ case 0x33:
+ case 0x43:
+ case 0x53:
+ case 0x63:
+ case 0x73:
+ sprintf(buffer, "%s A, %X", arith_ops[op >> 13], op & 0x1ff);
+ break;
+
+ // subi a, imm
+ case 0x14:
+ case 0x34:
+ case 0x44:
+ case 0x54:
+ case 0x64:
+ case 0x74:
+ sprintf(buffer, "%si A, %X", arith_ops[op >> 13], READ_OP_DASM(2));
+ size = 2;
+ break;
+
+ // op a, ((ri))
+ case 0x15:
+ case 0x35:
+ case 0x45:
+ case 0x55:
+ case 0x65:
+ case 0x75:
+ sprintf(buffer, "%s A, ((%s%s))", arith_ops[op >> 13], RIJ, MODIFIER_LOW);
+ break;
+
+ // sub a, ri
+ case 0x19:
+ case 0x39:
+ case 0x49:
+ case 0x59:
+ case 0x69:
+ case 0x79:
+ sprintf(buffer, "%s A, %s%s", arith_ops[op >> 13], RIJ, MODIFIER_LOW);
+ break;
+
+ // mpys (rj), (ri), b
+ case 0x1b:
+ sprintf(buffer, "mpya (%s%s), (%s%s), %d", RJ(op >> 4), MODIFIER_HIGH, RI(op), MODIFIER_LOW, BIT_B);
+ break;
+
+ // subi simm
+ case 0x1c:
+ case 0x3c:
+ case 0x4c:
+ case 0x5c:
+ case 0x6c:
+ case 0x7c:
+ sprintf(buffer, "%si %X", arith_ops[op >> 13], op & 0xff);
+ break;
+
+ // call cond, addr
+ case 0x24:
+ sprintf(buffer, "call %s, %X", get_cond(op), READ_OP_DASM(2));
+ flags |= DASMFLAG_STEP_OVER;
+ size = 2;
+ break;
+
+ // ld d, (a)
+ case 0x25:
+ sprintf(buffer, "ld %s, (A)", reg[(op >> 4) & 0xf]);
+ break;
+
+ // bra cond, addr
+ case 0x26:
+ sprintf(buffer, "bra %s, %X", get_cond(op), READ_OP_DASM(2));
+ size = 2;
+ break;
+
+ // mod cond, op
+ case 0x48:
+ sprintf(buffer, "mod %s, %s", get_cond(op), acc_op[op & 7]);
+ break;
+
+ // mod f, op
+ case 0x4a:
+ sprintf(buffer, "%s", flag_op[op & 0xf]);
+ break;
+
+ // mpya (rj), (ri), b
+ case 0x4b:
+ sprintf(buffer, "mpya (%s%s), (%s%s), %d", RJ(op >> 4), MODIFIER_HIGH, RI(op), MODIFIER_LOW, BIT_B);
+ break;
+
+ // mld (rj), (ri), b
+ case 0x5b:
+ sprintf(buffer, "mld (%s%s), (%s%s), %d", RJ(op >> 4), MODIFIER_HIGH, RI(op), MODIFIER_LOW, BIT_B);
+ break;
+
+ default:
+ sprintf(buffer, "OP = %04X", op);
+ break;
+ }
+
+ return size | flags | DASMFLAG_SUPPORTED;
+}
+
+// vim:ts=4
+
+CPU_DISASSEMBLE( ssp1601 )
+{
+ //ssp1601_state_t *ssp1601_state = get_safe_token(device);
+
+ return dasm_ssp1601(buffer, pc, oprom);
+}
+
+
diff --git a/trunk/src/emu/cpu/superfx/sfx_dasm.c b/trunk/src/emu/cpu/superfx/sfx_dasm.c
new file mode 100644
index 00000000000..ce95f6e17a3
--- /dev/null
+++ b/trunk/src/emu/cpu/superfx/sfx_dasm.c
@@ -0,0 +1,423 @@
+#include "emu.h"
+#include "superfx.h"
+
+static char *output;
+
+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);
+}
+
+offs_t superfx_dasm_one(char *buffer, offs_t pc, UINT8 op, UINT8 param0, UINT8 param1, UINT16 alt)
+{
+ UINT8 bytes_consumed = 1;
+ output = buffer;
+
+ switch(op)
+ {
+ case 0x00: // STOP
+ print("STOP");
+ break;
+ case 0x01: // NOP
+ print("NOP");
+ break;
+ case 0x02: // CACHE
+ print("CACHE");
+ break;
+ case 0x03: // LSR
+ print("LSR");
+ break;
+ case 0x04: // ROL
+ print("ROL");
+ break;
+ case 0x05: // BRA
+ print("BRA %d", (INT8)param0);
+ bytes_consumed = 2;
+ break;
+ case 0x06: // BLT
+ print("BLT %d", (INT8)param0);
+ bytes_consumed = 2;
+ break;
+ case 0x07: // BGE
+ print("BGE %d", (INT8)param0);
+ bytes_consumed = 2;
+ break;
+ case 0x08: // BNE
+ print("BNE %d", (INT8)param0);
+ bytes_consumed = 2;
+ break;
+ case 0x09: // BEQ
+ print("BEQ %d", (INT8)param0);
+ bytes_consumed = 2;
+ break;
+ case 0x0a: // BPL
+ print("BPL %d", (INT8)param0);
+ bytes_consumed = 2;
+ break;
+ case 0x0b: // BMI
+ print("BMI %d", (INT8)param0);
+ bytes_consumed = 2;
+ break;
+ case 0x0c: // BCC
+ print("BCC %d", (INT8)param0);
+ bytes_consumed = 2;
+ break;
+ case 0x0d: // BCS
+ print("BCS %d", (INT8)param0);
+ bytes_consumed = 2;
+ break;
+ case 0x0e: // BVC
+ print("BVC %d", (INT8)param0);
+ bytes_consumed = 2;
+ break;
+ case 0x0f: // BVS
+ print("BVS %d", (INT8)param0);
+ bytes_consumed = 2;
+ 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: // TO
+ print("TO R%d", op & 0xf);
+ break;
+
+ 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: // WITH
+ print("WITH R%d", op & 0xf);
+ 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: // STW_IR / STB_IR
+ switch(alt)
+ {
+ case SUPERFX_SFR_ALT0:
+ case SUPERFX_SFR_ALT2:
+ print("STW (R%d)", op & 0xf);
+ break;
+ case SUPERFX_SFR_ALT1:
+ case SUPERFX_SFR_ALT3:
+ print("STB (R%d)", op & 0xf);
+ break;
+ }
+ break;
+
+ case 0x3c: // LOOP
+ print("LOOP");
+ break;
+ case 0x3d: // ALT1
+ print("ALT1");
+ break;
+ case 0x3e: // ALT2
+ print("ALT2");
+ break;
+ case 0x3f: // ALT3
+ print("ALT3");
+ 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: // LDW_IR / LDB_IR
+ switch(alt)
+ {
+ case SUPERFX_SFR_ALT0:
+ case SUPERFX_SFR_ALT2:
+ print("LDW (R%d)", op & 0xf);
+ break;
+ case SUPERFX_SFR_ALT1:
+ case SUPERFX_SFR_ALT3:
+ print("LDB (R%d)", op & 0xf);
+ break;
+ }
+ break;
+
+ case 0x4c: // PLOT / RPIX
+ switch(alt)
+ {
+ case SUPERFX_SFR_ALT0:
+ case SUPERFX_SFR_ALT2:
+ print("PLOT");
+ break;
+ case SUPERFX_SFR_ALT1:
+ case SUPERFX_SFR_ALT3:
+ print("RPIX");
+ break;
+ }
+ break;
+
+ case 0x4d: // SWAP
+ print("SWAP");
+ break;
+
+ case 0x4e: // COLOR / CMODE
+ switch(alt)
+ {
+ case SUPERFX_SFR_ALT0:
+ case SUPERFX_SFR_ALT2:
+ print("COLOR");
+ break;
+ case SUPERFX_SFR_ALT1:
+ case SUPERFX_SFR_ALT3:
+ print("CMODE");
+ break;
+ }
+ break;
+
+ case 0x4f: // NOT
+ print("NOT");
+ 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: // ADD / ADC / ADDI / ADCI
+ switch(alt)
+ {
+ case SUPERFX_SFR_ALT0:
+ print("ADD R%d", op &0xf);
+ break;
+ case SUPERFX_SFR_ALT1:
+ print("ADC R%d", op &0xf);
+ break;
+ case SUPERFX_SFR_ALT2:
+ print("ADDI R%d", op &0xf);
+ break;
+ case SUPERFX_SFR_ALT3:
+ print("ADCI R%d", op &0xf);
+ break;
+ }
+ 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: // SUB / SBC / SUBI / CMP
+ switch(alt)
+ {
+ case SUPERFX_SFR_ALT0:
+ print("SUB R%d", op &0xf);
+ break;
+ case SUPERFX_SFR_ALT1:
+ print("SBC R%d", op &0xf);
+ break;
+ case SUPERFX_SFR_ALT2:
+ print("SUBI R%d", op &0xf);
+ break;
+ case SUPERFX_SFR_ALT3:
+ print("CMP R%d", op &0xf);
+ break;
+ }
+ break;
+
+ case 0x70: // MERGE
+ print("MERGE");
+ break;
+
+ 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: // AND / BIC / ANDI / BICI
+ switch(alt)
+ {
+ case SUPERFX_SFR_ALT0:
+ print("AND R%d", op &0xf);
+ break;
+ case SUPERFX_SFR_ALT1:
+ print("BIC R%d", op &0xf);
+ break;
+ case SUPERFX_SFR_ALT2:
+ print("ANDI R%d", op &0xf);
+ break;
+ case SUPERFX_SFR_ALT3:
+ print("BICI R%d", op &0xf);
+ break;
+ }
+ 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: // MULT / UMULT / MULTI / UMULTI
+ switch(alt)
+ {
+ case SUPERFX_SFR_ALT0:
+ print("MULT R%d", op &0xf);
+ break;
+ case SUPERFX_SFR_ALT1:
+ print("UMULT R%d", op &0xf);
+ break;
+ case SUPERFX_SFR_ALT2:
+ print("MULTI R%d", op &0xf);
+ break;
+ case SUPERFX_SFR_ALT3:
+ print("UMULTI R%d", op &0xf);
+ break;
+ }
+ break;
+
+ case 0x90: // SBK
+ print("SBK");
+ break;
+
+ case 0x91: case 0x92: case 0x93: case 0x94: // LINK
+ print("LINK %d", op & 0xf);
+ break;
+
+ case 0x95: // SEX
+ print("SEX");
+ break;
+
+ case 0x96: // ASR / DIV2
+ switch(alt)
+ {
+ case SUPERFX_SFR_ALT0:
+ case SUPERFX_SFR_ALT2:
+ print("ASR");
+ break;
+ case SUPERFX_SFR_ALT1:
+ case SUPERFX_SFR_ALT3:
+ print("DIV2");
+ break;
+ }
+ break;
+
+ case 0x97: // ROR
+ print("ROR");
+ break;
+
+ case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: // JMP / LJMP
+ switch(alt)
+ {
+ case SUPERFX_SFR_ALT0:
+ case SUPERFX_SFR_ALT2:
+ print("JMP R%d", op & 0xf);
+ break;
+ case SUPERFX_SFR_ALT1:
+ case SUPERFX_SFR_ALT3:
+ print("LJMP R%d", op & 0xf);
+ break;
+ }
+ break;
+
+ case 0x9e: // LOB
+ print("LOB");
+ break;
+
+ case 0x9f: // FMULT / LMULT
+ switch(alt)
+ {
+ case SUPERFX_SFR_ALT0:
+ case SUPERFX_SFR_ALT2:
+ print("FMULT");
+ break;
+ case SUPERFX_SFR_ALT1:
+ case SUPERFX_SFR_ALT3:
+ print("LMULT");
+ break;
+ }
+ 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: // IBT / LMS / SMS / LML
+ switch(alt)
+ {
+ case SUPERFX_SFR_ALT0:
+ print("IBT R%d,0x%02x", op & 0xf, param0);
+ break;
+ case SUPERFX_SFR_ALT2:
+ print("SMS R%d,(0x%04x)", op & 0xf, param0 << 1);
+ break;
+ case SUPERFX_SFR_ALT1:
+ case SUPERFX_SFR_ALT3:
+ print("LMS R%d,(0x%04x)", op & 0xf, param0 << 1);
+ break;
+ }
+ bytes_consumed = 2;
+ 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: // FROM
+ print("FROM R%d", op & 0xf);
+ break;
+
+ case 0xc0: // HIB
+ print("HIB");
+ break;
+
+ 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: // OR / XOR / ORI / XORI
+ switch(alt)
+ {
+ case SUPERFX_SFR_ALT0:
+ print("OR R%d", op &0xf);
+ break;
+ case SUPERFX_SFR_ALT1:
+ print("XOR R%d", op &0xf);
+ break;
+ case SUPERFX_SFR_ALT2:
+ print("ORI R%d", op &0xf);
+ break;
+ case SUPERFX_SFR_ALT3:
+ print("XORI R%d", op &0xf);
+ break;
+ }
+ 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: // INC
+ print("INC R%d", op & 0xf);
+ break;
+
+ case 0xdf: // GETC / RAMB / ROMB
+ switch(alt)
+ {
+ case SUPERFX_SFR_ALT0:
+ case SUPERFX_SFR_ALT1:
+ print("GETC");
+ break;
+ case SUPERFX_SFR_ALT2:
+ print("RAMB");
+ break;
+ case SUPERFX_SFR_ALT3:
+ print("ROMB");
+ break;
+ }
+ break;
+
+ 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: // DEC
+ print("DEC R%d", op & 0xf);
+ break;
+
+ case 0xef: // GETB / GETBH / GETBL / GETBS
+ switch(alt)
+ {
+ case SUPERFX_SFR_ALT0:
+ print("GETB");
+ break;
+ case SUPERFX_SFR_ALT1:
+ print("GETBH");
+ break;
+ case SUPERFX_SFR_ALT2:
+ print("GETBL");
+ break;
+ case SUPERFX_SFR_ALT3:
+ print("GETBS");
+ break;
+ }
+ break;
+
+ 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: // IWT / LM / SM / LM
+ switch(alt)
+ {
+ case SUPERFX_SFR_ALT0:
+ print("IWT R%d,#%02x%02x", op & 0xf, param1, param0);
+ bytes_consumed = 3;
+ break;
+ case SUPERFX_SFR_ALT2:
+ print("SM R%d", op & 0xf);
+ break;
+ case SUPERFX_SFR_ALT1:
+ case SUPERFX_SFR_ALT3:
+ print("LM R%d", op & 0xf);
+ break;
+ }
+ break;
+ }
+
+ return bytes_consumed | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/superfx/superfx.c b/trunk/src/emu/cpu/superfx/superfx.c
new file mode 100644
index 00000000000..5c6ea18a2c7
--- /dev/null
+++ b/trunk/src/emu/cpu/superfx/superfx.c
@@ -0,0 +1,1680 @@
+#include "emu.h"
+#include "debugger.h"
+#include "superfx.h"
+
+typedef struct
+{
+ UINT16 offset;
+ UINT8 bitpend;
+ UINT8 data[8];
+} pixelcache_t;
+
+typedef struct
+{
+ UINT8 buffer[0x200];
+ UINT8 valid[0x20];
+} cache_t;
+
+typedef struct _superfx_state superfx_state;
+struct _superfx_state
+{
+ superfx_config config;
+
+ devcb_resolved_write_line out_irq_func;
+
+ UINT8 pipeline;
+ UINT16 ramaddr; // RAM Address
+
+ UINT16 r[16]; // GPRs
+ UINT16 sfr; // Status Flag Register
+ UINT8 pbr; // Program Bank Register
+ UINT8 rombr; // Game Pack ROM Bank Register
+ UINT8 rambr; // Game Pack RAM Bank Register
+ UINT16 cbr; // Cache Base Register
+ UINT8 scbr; // Screen Base Register
+ UINT8 scmr; // Screen Mode Register
+ UINT8 colr; // Color Register
+ UINT8 por; // Plot Option Register
+ UINT8 bramr; // Back-Up RAM Register
+ UINT8 vcr; // Version Code Register
+ UINT8 cfgr; // Config Register
+ UINT8 clsr; // Clock Select Register
+
+ UINT32 romcl; // Clock ticks until ROMDR is valid
+ UINT8 romdr; // ROM Buffer Data Register
+
+ UINT32 ramcl; // Clock ticks until RAMDR is valid;
+ UINT16 ramar; // RAM Buffer Address Register
+ UINT8 ramdr; // RAM Buffer Data Register
+
+ UINT16 *sreg; // Source Register (From)
+ UINT8 sreg_idx;// Source Register (To), index
+ UINT16 *dreg; // Destination Register (To)
+ UINT8 dreg_idx;// Destination Register (To), index
+ UINT8 r15_modified;
+
+ UINT8 irq; // IRQ Pending
+
+ UINT32 cache_access_speed;
+ UINT32 memory_access_speed;
+
+ cache_t cache;
+ pixelcache_t pixelcache[2];
+
+ legacy_cpu_device *device;
+ address_space *program;
+ int icount;
+};
+
+INLINE superfx_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == SUPERFX);
+ return (superfx_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/*****************************************************************************/
+
+INLINE void superfx_regs_reset(superfx_state *cpustate);
+static void superfx_update_speed(superfx_state *cpustate);
+static void superfx_cache_flush(superfx_state *cpustate);
+static UINT8 superfx_cache_mmio_read(superfx_state *cpustate, UINT32 addr);
+static void superfx_cache_mmio_write(superfx_state *cpustate, UINT32 addr, UINT8 data);
+static void superfx_memory_reset(superfx_state *cpustate);
+INLINE UINT8 superfx_bus_read(superfx_state *cpustate, UINT32 addr);
+INLINE void superfx_bus_write(superfx_state *cpustate, UINT32 addr, UINT8 data);
+INLINE void superfx_pixelcache_flush(superfx_state *cpustate, INT32 line);
+INLINE void superfx_plot(superfx_state *cpustate, UINT8 x, UINT8 y);
+static UINT8 superfx_rpix(superfx_state *cpustate, UINT8 r1, UINT8 r2);
+INLINE UINT8 superfx_color(superfx_state *cpustate, UINT8 source);
+
+INLINE void superfx_rambuffer_sync(superfx_state *cpustate);
+INLINE UINT8 superfx_rambuffer_read(superfx_state *cpustate, UINT16 addr);
+INLINE void superfx_rambuffer_write(superfx_state *cpustate, UINT16 addr, UINT8 val);
+
+INLINE void superfx_rombuffer_sync(superfx_state *cpustate);
+INLINE void superfx_rombuffer_update(superfx_state *cpustate);
+INLINE UINT8 superfx_rombuffer_read(superfx_state *cpustate);
+
+INLINE void superfx_gpr_write(superfx_state *cpustate, UINT8 r, UINT16 data);
+INLINE UINT8 superfx_op_read(superfx_state *cpustate, UINT16 addr);
+INLINE UINT8 superfx_peekpipe(superfx_state *cpustate);
+INLINE UINT8 superfx_pipe(superfx_state *cpustate);
+INLINE void superfx_add_clocks_internal(superfx_state *cpustate, UINT32 clocks);
+static void superfx_timing_reset(superfx_state *cpustate);
+
+/*****************************************************************************/
+
+#define SUPERFX_SFR_OV_SET ((cpustate->sfr & SUPERFX_SFR_OV) ? 1 : 0)
+#define SUPERFX_SFR_OV_CLEAR ((cpustate->sfr & SUPERFX_SFR_OV) ? 0 : 1)
+#define SUPERFX_SFR_S_SET ((cpustate->sfr & SUPERFX_SFR_S) ? 1 : 0)
+#define SUPERFX_SFR_S_CLEAR ((cpustate->sfr & SUPERFX_SFR_S) ? 0 : 1)
+#define SUPERFX_SFR_CY_SET ((cpustate->sfr & SUPERFX_SFR_CY) ? 1 : 0)
+#define SUPERFX_SFR_CY_CLEAR ((cpustate->sfr & SUPERFX_SFR_CY) ? 0 : 1)
+#define SUPERFX_SFR_Z_SET ((cpustate->sfr & SUPERFX_SFR_Z) ? 1 : 0)
+#define SUPERFX_SFR_Z_CLEAR ((cpustate->sfr & SUPERFX_SFR_Z) ? 0 : 1)
+
+INLINE void superfx_regs_reset(superfx_state *cpustate)
+{
+ cpustate->sfr &= ~(SUPERFX_SFR_B | SUPERFX_SFR_ALT3);
+
+ cpustate->sreg = &cpustate->r[0];
+ cpustate->dreg = &cpustate->r[0];
+ cpustate->dreg_idx = 0;
+ cpustate->sreg_idx = 0;
+}
+
+static void superfx_update_speed(superfx_state *cpustate)
+{
+ cpustate->cache_access_speed = (cpustate->clsr ? 1 : 2);
+ cpustate->memory_access_speed = (cpustate->clsr ? 5 : 6);
+ if(cpustate->clsr)
+ {
+ cpustate->cfgr &= ~SUPERFX_CFGR_MS0; // Cannot use high-speed multiplication in 21MHz mode
+ }
+}
+
+static void superfx_cache_flush(superfx_state *cpustate)
+{
+ UINT32 n = 0;
+ for(n = 0; n < 32; n++)
+ {
+ cpustate->cache.valid[n] = 0;
+ }
+}
+
+static UINT8 superfx_cache_mmio_read(superfx_state *cpustate, UINT32 addr)
+{
+ addr = (addr + cpustate->cbr) & 0x1ff;
+ return cpustate->cache.buffer[addr];
+}
+
+static void superfx_cache_mmio_write(superfx_state *cpustate, UINT32 addr, UINT8 data)
+{
+ addr = (addr + cpustate->cbr) & 0x1ff;
+ cpustate->cache.buffer[addr] = data;
+ if((addr & 15) == 15)
+ {
+ cpustate->cache.valid[addr >> 4] = 1;
+ }
+}
+
+static void superfx_memory_reset(superfx_state *cpustate)
+{
+ UINT32 n = 0;
+ for(n = 0; n < 0x200; n++)
+ {
+ cpustate->cache.buffer[n] = 0x00;
+ }
+ for(n = 0; n < 0x20; n++)
+ {
+ cpustate->cache.valid[n] = 0;
+ }
+ for(n = 0; n < 2; n++)
+ {
+ cpustate->pixelcache[n].offset = ~0;
+ cpustate->pixelcache[n].bitpend = 0x00;
+ }
+}
+
+INLINE UINT8 superfx_bus_read(superfx_state *cpustate, UINT32 addr)
+{
+ return cpustate->program->read_byte(addr);
+}
+
+INLINE void superfx_bus_write(superfx_state *cpustate, UINT32 addr, UINT8 data)
+{
+ cpustate->program->write_byte(addr, data);
+}
+
+INLINE void superfx_pixelcache_flush(superfx_state *cpustate, INT32 line)
+{
+ UINT8 x = cpustate->pixelcache[line].offset << 3;
+ UINT8 y = cpustate->pixelcache[line].offset >> 5;
+ UINT32 cn = 0;
+ UINT32 bpp = 2 << ((cpustate->scmr & SUPERFX_SCMR_MD) - ((cpustate->scmr & SUPERFX_SCMR_MD) >> 1)); // = [regs.scmr.md]{ 2, 4, 4, 8 };
+ UINT32 addr = 0;
+ UINT32 n = 0;
+
+ if(cpustate->pixelcache[line].bitpend == 0x00)
+ {
+ return;
+ }
+
+ switch(((cpustate->por & SUPERFX_POR_OBJ) ? SUPERFX_SCMR_HT3 : (cpustate->scmr & SUPERFX_SCMR_HT_MASK)))
+ {
+ case SUPERFX_SCMR_HT0:
+ cn = ((x & 0xf8) << 1) + ((y & 0xf8) >> 3);
+ break;
+ case SUPERFX_SCMR_HT1:
+ cn = ((x & 0xf8) << 1) + ((x & 0xf8) >> 1) + ((y & 0xf8) >> 3);
+ break;
+ case SUPERFX_SCMR_HT2:
+ cn = ((x & 0xf8) << 1) + ((x & 0xf8) << 0) + ((y & 0xf8) >> 3);
+ break;
+ case SUPERFX_SCMR_HT3:
+ cn = ((y & 0x80) << 2) + ((x & 0x80) << 1) + ((y & 0x78) << 1) + ((x & 0x78) >> 3);
+ break;
+ }
+
+ addr = 0x700000 + (cn * (bpp << 3)) + (cpustate->scbr << 10) + ((y & 0x07) * 2);
+
+ for(n = 0; n < bpp; n++)
+ {
+ UINT32 byte = ((n >> 1) << 4) + (n & 1); // = [n]{ 0, 1, 16, 17, 32, 33, 48, 49 };
+ UINT8 data = 0x00;
+ UINT32 x32 = 0;
+ for(x32 = 0; x32 < 8; x32++)
+ {
+ data |= ((cpustate->pixelcache[line].data[x32] >> n) & 1) << x32;
+ }
+ if(cpustate->pixelcache[line].bitpend != 0xff)
+ {
+ superfx_add_clocks_internal(cpustate, cpustate->memory_access_speed);
+ data &= cpustate->pixelcache[line].bitpend;
+ data |= superfx_bus_read(cpustate, addr + byte) & ~cpustate->pixelcache[line].bitpend;
+ }
+ superfx_add_clocks_internal(cpustate, cpustate->memory_access_speed);
+ superfx_bus_write(cpustate, addr + byte, data);
+ }
+
+ cpustate->pixelcache[line].bitpend = 0x00;
+}
+
+INLINE void superfx_plot(superfx_state *cpustate, UINT8 x, UINT8 y)
+{
+ UINT8 color = cpustate->colr;
+ UINT16 offset = (y << 5) + (x >> 3);
+
+ if((cpustate->por & SUPERFX_POR_DITHER) != 0 && (cpustate->scmr & SUPERFX_SCMR_MD) != 3)
+ {
+ if((x ^ y) & 1)
+ {
+ color >>= 4;
+ }
+ color &= 0x0f;
+ }
+
+ if((cpustate->por & SUPERFX_POR_TRANSPARENT) == 0)
+ {
+ if((cpustate->scmr & SUPERFX_SCMR_MD) == 3)
+ {
+ if(cpustate->por & SUPERFX_POR_FREEZEHIGH)
+ {
+ if((color & 0x0f) == 0)
+ {
+ return;
+ }
+ }
+ else
+ {
+ if(color == 0)
+ {
+ return;
+ }
+ }
+ }
+ else
+ {
+ if((color & 0x0f) == 0)
+ {
+ return;
+ }
+ }
+ }
+
+ if(offset != cpustate->pixelcache[0].offset)
+ {
+ superfx_pixelcache_flush(cpustate, 1);
+ cpustate->pixelcache[1] = cpustate->pixelcache[0];
+ cpustate->pixelcache[0].bitpend = 0x00;
+ cpustate->pixelcache[0].offset = offset;
+ }
+
+ x = (x & 7) ^ 7;
+ cpustate->pixelcache[0].data[x] = color;
+ cpustate->pixelcache[0].bitpend |= 1 << x;
+ if(cpustate->pixelcache[0].bitpend == 0xff)
+ {
+ superfx_pixelcache_flush(cpustate, 1);
+ cpustate->pixelcache[1] = cpustate->pixelcache[0];
+ cpustate->pixelcache[0].bitpend = 0x00;
+ }
+}
+
+static UINT8 superfx_rpix(superfx_state *cpustate, UINT8 x, UINT8 y)
+{
+ UINT32 cn = 0;
+ UINT32 bpp = 0;
+ UINT32 addr = 0;
+ UINT8 data = 0x00;
+ UINT32 n = 0;
+
+ superfx_pixelcache_flush(cpustate, 1);
+ superfx_pixelcache_flush(cpustate, 0);
+
+ bpp = 2 << ((cpustate->scmr & SUPERFX_SCMR_MD) - ((cpustate->scmr & SUPERFX_SCMR_MD) >> 1)); // = [regs.scmr.md]{ 2, 4, 4, 8 };
+
+ switch((cpustate->por & SUPERFX_POR_OBJ) ? SUPERFX_SCMR_HT3 : (cpustate->scmr & SUPERFX_SCMR_HT_MASK))
+ {
+ case SUPERFX_SCMR_HT0:
+ cn = ((x & 0xf8) << 1) + ((y & 0xf8) >> 3);
+ break;
+ case SUPERFX_SCMR_HT1:
+ cn = ((x & 0xf8) << 1) + ((x & 0xf8) >> 1) + ((y & 0xf8) >> 3);
+ break;
+ case SUPERFX_SCMR_HT2:
+ cn = ((x & 0xf8) << 1) + ((x & 0xf8) << 0) + ((y & 0xf8) >> 3);
+ break;
+ case SUPERFX_SCMR_HT3:
+ cn = ((y & 0x80) << 2) + ((x & 0x80) << 1) + ((y & 0x78) << 1) + ((x & 0x78) >> 3);
+ break;
+ }
+
+ addr = 0x700000 + (cn * (bpp << 3)) + (cpustate->scbr << 10) + ((y & 0x07) * 2);
+ x = (x & 7) ^ 7;
+
+ for(n = 0; n < bpp; n++)
+ {
+ UINT32 byte = ((n >> 1) << 4) + (n & 1); // = [n]{ 0, 1, 16, 17, 32, 33, 48, 49 };
+ superfx_add_clocks_internal(cpustate, cpustate->memory_access_speed);
+ data |= ((superfx_bus_read(cpustate, addr + byte) >> x) & 1) << n;
+ }
+
+ return data;
+}
+
+INLINE UINT8 superfx_color(superfx_state *cpustate, UINT8 source)
+{
+ if(cpustate->por & SUPERFX_POR_HIGHNIBBLE)
+ {
+ return (cpustate->colr & 0xf0) | (source >> 4);
+ }
+ if(cpustate->por & SUPERFX_POR_FREEZEHIGH)
+ {
+ return (cpustate->colr & 0xf0) | (source & 0x0f);
+ }
+ return source;
+}
+
+INLINE void superfx_rambuffer_sync(superfx_state *cpustate)
+{
+ if(cpustate->ramcl)
+ {
+ superfx_add_clocks_internal(cpustate, cpustate->ramcl);
+ }
+}
+
+INLINE UINT8 superfx_rambuffer_read(superfx_state *cpustate, UINT16 addr)
+{
+ superfx_rambuffer_sync(cpustate);
+ return superfx_bus_read(cpustate, 0x700000 + (cpustate->rambr << 16) + addr);
+}
+
+INLINE void superfx_rambuffer_write(superfx_state *cpustate, UINT16 addr, UINT8 data)
+{
+ superfx_rambuffer_sync(cpustate);
+ cpustate->ramcl = cpustate->memory_access_speed;
+ cpustate->ramar = addr;
+ cpustate->ramdr = data;
+}
+
+INLINE void superfx_rombuffer_sync(superfx_state *cpustate)
+{
+ if(cpustate->romcl)
+ {
+ superfx_add_clocks_internal(cpustate, cpustate->romcl);
+ }
+}
+
+INLINE void superfx_rombuffer_update(superfx_state *cpustate)
+{
+ cpustate->sfr |= SUPERFX_SFR_R;
+ cpustate->romcl = cpustate->memory_access_speed;
+}
+
+INLINE UINT8 superfx_rombuffer_read(superfx_state *cpustate)
+{
+ superfx_rombuffer_sync(cpustate);
+ return cpustate->romdr;
+}
+
+INLINE void superfx_gpr_write(superfx_state *cpustate, UINT8 r, UINT16 data)
+{
+ cpustate->r[r] = data;
+ if(r == 14)
+ {
+ superfx_rombuffer_update(cpustate);
+ }
+ else if(r == 15)
+ {
+ cpustate->r15_modified = 1;
+ }
+}
+
+INLINE UINT8 superfx_op_read(superfx_state *cpustate, UINT16 addr)
+{
+ UINT16 offset = addr - cpustate->cbr;
+ if(offset < 512)
+ {
+ if(!cpustate->cache.valid[offset >> 4])
+ {
+ UINT32 dp = offset & 0xfff0;
+ UINT32 sp = (cpustate->pbr << 16) + ((cpustate->cbr + dp) & 0xfff0);
+ UINT32 n = 0;
+ for(n = 0; n < 16; n++)
+ {
+ superfx_add_clocks_internal(cpustate, cpustate->memory_access_speed);
+ cpustate->cache.buffer[dp++] = superfx_bus_read(cpustate, sp++);
+ }
+ cpustate->cache.valid[offset >> 4] = 1;
+ }
+ else
+ {
+ superfx_add_clocks_internal(cpustate, cpustate->memory_access_speed);
+ }
+ return cpustate->cache.buffer[offset];
+ }
+
+ if(cpustate->pbr <= 0x5f)
+ {
+ //$[00-5f]:[0000-ffff] ROM
+ superfx_rombuffer_sync(cpustate);
+ superfx_add_clocks_internal(cpustate, cpustate->memory_access_speed);
+ return superfx_bus_read(cpustate, (cpustate->pbr << 16) + addr);
+ }
+ else
+ {
+ //$[60-7f]:[0000-ffff] RAM
+ superfx_rambuffer_sync(cpustate);
+ superfx_add_clocks_internal(cpustate, cpustate->memory_access_speed);
+ return superfx_bus_read(cpustate, (cpustate->pbr << 16) + addr);
+ }
+}
+
+INLINE UINT8 superfx_peekpipe(superfx_state *cpustate)
+{
+ UINT8 result = cpustate->pipeline;
+ cpustate->pipeline = superfx_op_read(cpustate, cpustate->r[15]);
+ cpustate->r15_modified = 0;
+ return result;
+}
+
+INLINE UINT8 superfx_pipe(superfx_state *cpustate)
+{
+ UINT8 result = cpustate->pipeline;
+ cpustate->pipeline = superfx_op_read(cpustate, ++cpustate->r[15]);
+ cpustate->r15_modified = 0;
+ return result;
+}
+
+/*****************************************************************************/
+
+/* reads to SuperFX RAM only happen if this returns 1 */
+int superfx_access_ram(device_t *cpu)
+{
+ superfx_state *cpustate = get_safe_token(cpu);
+
+ if ((cpustate->sfr & SUPERFX_SFR_G) && (cpustate->scmr & SUPERFX_SCMR_RAN))
+ return 0;
+
+ return 1;
+}
+
+/* reads to SuperFX ROM only happen if this returns 1 */
+int superfx_access_rom(device_t *cpu)
+{
+ superfx_state *cpustate = get_safe_token(cpu);
+
+ if ((cpustate->sfr & SUPERFX_SFR_G) && (cpustate->scmr & SUPERFX_SCMR_RON))
+ return 0;
+
+ return 1;
+}
+
+UINT8 superfx_mmio_read(device_t *cpu, UINT32 addr)
+{
+ superfx_state *cpustate = get_safe_token(cpu);
+
+ addr &= 0xffff;
+
+ if(addr >= 0x3100 && addr <= 0x32ff)
+ {
+ return superfx_cache_mmio_read(cpustate, addr - 0x3100);
+ }
+
+ if(addr >= 0x3000 && addr <= 0x301f)
+ {
+ return cpustate->r[(addr >> 1) & 0xf] >> ((addr & 1) << 3);
+ }
+
+ switch(addr)
+ {
+ case 0x3030:
+ return cpustate->sfr >> 0;
+
+ case 0x3031:
+ {
+ UINT8 r = cpustate->sfr >> 8;
+ cpustate->sfr &= ~SUPERFX_SFR_IRQ;
+ cpustate->irq = 0;
+ cpustate->out_irq_func(cpustate->irq);
+ return r;
+ }
+
+ case 0x3034:
+ return cpustate->pbr;
+
+ case 0x3036:
+ return cpustate->rombr;
+
+ case 0x303b:
+ return cpustate->vcr;
+
+ case 0x303c:
+ return cpustate->rambr;
+
+ case 0x303e:
+ return cpustate->cbr >> 0;
+
+ case 0x303f:
+ return cpustate->cbr >> 8;
+ }
+
+ return 0;
+}
+
+void superfx_mmio_write(device_t *cpu, UINT32 addr, UINT8 data)
+{
+ superfx_state *cpustate = get_safe_token(cpu);
+
+ addr &= 0xffff;
+
+ //printf( "superfx_mmio_write: %08x = %02x\n", addr, data );
+
+ if(addr >= 0x3100 && addr <= 0x32ff)
+ {
+ superfx_cache_mmio_write(cpustate, addr - 0x3100, data);
+ return;
+ }
+
+ if(addr >= 0x3000 && addr <= 0x301f)
+ {
+ UINT32 n = (addr >> 1) & 0xf;
+ if((addr & 1) == 0)
+ {
+ cpustate->r[n] = (cpustate->r[n] & 0xff00) | data;
+ }
+ else
+ {
+ cpustate->r[n] = (data << 8) | (cpustate->r[n] & 0xff);
+ }
+
+ if(addr == 0x301f)
+ {
+ cpustate->sfr |= SUPERFX_SFR_G;
+ }
+ return;
+ }
+
+ switch(addr)
+ {
+ case 0x3030:
+ {
+ UINT8 g = (cpustate->sfr & SUPERFX_SFR_G) ? 1 : 0;
+ cpustate->sfr = (cpustate->sfr & 0xff00) | (data << 0);
+ if(g == 1 && !(cpustate->sfr & SUPERFX_SFR_G))
+ {
+ cpustate->cbr = 0x0000;
+ superfx_cache_flush(cpustate);
+ }
+ break;
+ }
+
+ case 0x3031:
+ cpustate->sfr = (data << 8) | (cpustate->sfr & 0x00ff);
+ break;
+
+ case 0x3033:
+ cpustate->bramr = data & 1;
+ break;
+
+ case 0x3034:
+ cpustate->pbr = data & 0x7f;
+ superfx_cache_flush(cpustate);
+ break;
+
+ case 0x3037:
+ cpustate->cfgr = data;
+ superfx_update_speed(cpustate);
+ break;
+
+ case 0x3038:
+ cpustate->scbr = data;
+ break;
+
+ case 0x3039:
+ cpustate->clsr = data & 1;
+ superfx_update_speed(cpustate);
+ break;
+
+ case 0x303a:
+ cpustate->scmr = data;
+ break;
+ }
+}
+
+INLINE void superfx_add_clocks_internal(superfx_state *cpustate, UINT32 clocks)
+{
+ if(cpustate->romcl)
+ {
+ cpustate->romcl -= MIN(clocks, cpustate->romcl);
+ if(cpustate->romcl == 0)
+ {
+ cpustate->sfr &= ~SUPERFX_SFR_R;
+ cpustate->romdr = superfx_bus_read(cpustate, (cpustate->rombr << 16) + cpustate->r[14]);
+ }
+ }
+
+ if(cpustate->ramcl)
+ {
+ cpustate->ramcl -= MIN(clocks, cpustate->ramcl);
+ if(cpustate->ramcl == 0)
+ {
+ superfx_bus_write(cpustate, 0x700000 + (cpustate->rambr << 16) + cpustate->ramar, cpustate->ramdr);
+ }
+ }
+}
+
+static void superfx_timing_reset(superfx_state *cpustate)
+{
+ superfx_update_speed(cpustate);
+ cpustate->r15_modified = 0;
+
+ cpustate->romcl = 0;
+ cpustate->romdr = 0;
+
+ cpustate->ramcl = 0;
+ cpustate->ramar = 0;
+ cpustate->ramdr = 0;
+}
+
+void superfx_add_clocks(device_t *cpu, INT32 clocks)
+{
+ superfx_state *cpustate = get_safe_token(cpu);
+
+ superfx_add_clocks_internal(cpustate, clocks);
+}
+
+/*****************************************************************************/
+
+static void superfx_register_save( legacy_cpu_device *device )
+{
+ superfx_state *cpustate = get_safe_token(device);
+ int i;
+
+ device->save_item(NAME(cpustate->pipeline));
+ device->save_item(NAME(cpustate->ramaddr));
+
+ device->save_item(NAME(cpustate->r));
+ device->save_item(NAME(cpustate->sfr));
+ device->save_item(NAME(cpustate->pbr));
+ device->save_item(NAME(cpustate->rombr));
+ device->save_item(NAME(cpustate->rambr));
+ device->save_item(NAME(cpustate->cbr));
+ device->save_item(NAME(cpustate->scbr));
+ device->save_item(NAME(cpustate->scmr));
+ device->save_item(NAME(cpustate->colr));
+ device->save_item(NAME(cpustate->por));
+ device->save_item(NAME(cpustate->bramr));
+ device->save_item(NAME(cpustate->vcr));
+ device->save_item(NAME(cpustate->cfgr));
+ device->save_item(NAME(cpustate->clsr));
+
+ device->save_item(NAME(cpustate->romcl));
+ device->save_item(NAME(cpustate->romdr));
+
+ device->save_item(NAME(cpustate->ramcl));
+ device->save_item(NAME(cpustate->ramar));
+ device->save_item(NAME(cpustate->ramdr));
+
+ device->save_item(NAME(cpustate->sreg_idx));
+ device->save_item(NAME(cpustate->dreg_idx));
+ device->save_item(NAME(cpustate->r15_modified));
+
+ device->save_item(NAME(cpustate->irq));
+
+ device->save_item(NAME(cpustate->cache_access_speed));
+ device->save_item(NAME(cpustate->memory_access_speed));
+
+ device->save_item(NAME(cpustate->cache.buffer));
+ device->save_item(NAME(cpustate->cache.valid));
+
+ for (i = 0; i < 2; i++)
+ {
+ device->save_item(NAME(cpustate->pixelcache[i].offset), i);
+ device->save_item(NAME(cpustate->pixelcache[i].bitpend), i);
+ device->save_item(NAME(cpustate->pixelcache[i].data), i);
+ }
+
+ device->save_item(NAME(cpustate->icount));
+}
+
+static CPU_INIT( superfx )
+{
+ int i;
+ superfx_state *cpustate = get_safe_token(device);
+
+ for(i = 0; i < 16; i++)
+ {
+ cpustate->r[i] = 0;
+ }
+
+ cpustate->sfr = 0;
+ cpustate->pbr = 0;
+ cpustate->rombr = 0;
+ cpustate->rambr = 0;
+ cpustate->cbr = 0;
+ cpustate->scbr = 0;
+ cpustate->scmr = 0;
+ cpustate->colr = 0;
+ cpustate->por = 0;
+ cpustate->bramr = 0;
+ cpustate->vcr = 0x04;
+ cpustate->cfgr = 0;
+ cpustate->clsr = 0;
+ cpustate->pipeline = 0x01; // nop
+ cpustate->ramaddr = 0;
+ cpustate->r15_modified = 0;
+
+ superfx_regs_reset(cpustate);
+ superfx_memory_reset(cpustate);
+ superfx_update_speed(cpustate);
+
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+
+ if (device->static_config() != NULL)
+ {
+ cpustate->config = *(superfx_config *)device->static_config();
+ }
+
+ cpustate->out_irq_func.resolve(cpustate->config.out_irq_func, *device);
+
+ superfx_register_save(device);
+}
+
+static CPU_EXIT( superfx )
+{
+}
+
+static CPU_RESET( superfx )
+{
+ int i;
+
+ superfx_state *cpustate = get_safe_token(device);
+
+ for(i = 0; i < 16; i++)
+ {
+ cpustate->r[i] = 0;
+ }
+
+ cpustate->sfr = 0;
+ cpustate->pbr = 0;
+ cpustate->rombr = 0;
+ cpustate->rambr = 0;
+ cpustate->cbr = 0;
+ cpustate->scbr = 0;
+ cpustate->scmr = 0;
+ cpustate->colr = 0;
+ cpustate->por = 0;
+ cpustate->bramr = 0;
+ cpustate->vcr = 0x04;
+ cpustate->cfgr = 0;
+ cpustate->clsr = 0;
+ cpustate->pipeline = 0x01; // nop
+ cpustate->ramaddr = 0;
+
+ superfx_regs_reset(cpustate);
+ superfx_timing_reset(cpustate);
+}
+
+INLINE void superfx_dreg_sfr_sz_update(superfx_state *cpustate)
+{
+ cpustate->sfr &= ~(SUPERFX_SFR_S | SUPERFX_SFR_Z);
+ cpustate->sfr |= (*(cpustate->dreg) & 0x8000) ? SUPERFX_SFR_S : 0;
+ cpustate->sfr |= (*(cpustate->dreg) == 0) ? SUPERFX_SFR_Z : 0;
+}
+
+static CPU_EXECUTE( superfx )
+{
+ superfx_state *cpustate = get_safe_token(device);
+ UINT8 op;
+
+ if(!(cpustate->sfr & SUPERFX_SFR_G))
+ {
+ superfx_add_clocks_internal(cpustate, 6);
+ cpustate->icount = MIN(cpustate->icount, 0);
+ }
+
+ while (cpustate->icount > 0 && (cpustate->sfr & SUPERFX_SFR_G))
+ {
+ if(!(cpustate->sfr & SUPERFX_SFR_G))
+ {
+ superfx_add_clocks_internal(cpustate, 6);
+ cpustate->icount = MIN(cpustate->icount, 0);
+ break;
+ }
+
+ debugger_instruction_hook(device, (cpustate->pbr << 16) | cpustate->r[15]);
+
+ op = superfx_peekpipe(cpustate);
+
+ switch(op)
+ {
+ case 0x00: // STOP
+ if((cpustate->cfgr & SUPERFX_CFGR_IRQ) == 0)
+ {
+ cpustate->sfr |= SUPERFX_SFR_IRQ;
+ cpustate->irq = 1;
+ cpustate->out_irq_func(cpustate->irq ? ASSERT_LINE : CLEAR_LINE );
+ }
+ cpustate->sfr &= ~SUPERFX_SFR_G;
+ cpustate->pipeline = 0x01;
+ superfx_regs_reset(cpustate);
+ break;
+ case 0x01: // NOP
+ superfx_regs_reset(cpustate);
+ break;
+ case 0x02: // CACHE
+ if(cpustate->cbr != (cpustate->r[15] & 0xfff0))
+ {
+ cpustate->cbr = cpustate->r[15] & 0xfff0;
+ superfx_cache_flush(cpustate);
+ }
+ superfx_regs_reset(cpustate);
+ break;
+ case 0x03: // LSR
+ cpustate->sfr &= ~SUPERFX_SFR_CY;
+ cpustate->sfr |= (*(cpustate->sreg) & 1) ? SUPERFX_SFR_CY : 0;
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, *(cpustate->sreg) >> 1);
+ superfx_dreg_sfr_sz_update(cpustate);
+ superfx_regs_reset(cpustate);
+ break;
+ case 0x04: // ROL
+ {
+ UINT16 carry = *(cpustate->sreg) & 0x8000;
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, (*(cpustate->sreg) << 1) | (SUPERFX_SFR_CY_SET ? 1 : 0));
+ cpustate->sfr &= ~SUPERFX_SFR_CY;
+ cpustate->sfr |= carry ? SUPERFX_SFR_CY : 0;
+ superfx_dreg_sfr_sz_update(cpustate);
+ superfx_regs_reset(cpustate);
+ break;
+ }
+ case 0x05: // BRA
+ {
+ INT32 e = (INT8)superfx_pipe(cpustate);
+ superfx_gpr_write(cpustate, 15, cpustate->r[15] + e);
+ break;
+ }
+ case 0x06: // BLT
+ {
+ INT32 e = (INT8)superfx_pipe(cpustate);
+ if((SUPERFX_SFR_S_SET ^ SUPERFX_SFR_OV_SET) == 0)
+ {
+ superfx_gpr_write(cpustate, 15, cpustate->r[15] + e);
+ }
+ break;
+ }
+ case 0x07: // BGE
+ {
+ INT32 e = (INT8)superfx_pipe(cpustate);
+ if((SUPERFX_SFR_S_SET ^ SUPERFX_SFR_OV_SET) == 1)
+ {
+ superfx_gpr_write(cpustate, 15, cpustate->r[15] + e);
+ }
+ break;
+ }
+ case 0x08: // BNE
+ {
+ INT32 e = (INT8)superfx_pipe(cpustate);
+ if(SUPERFX_SFR_Z_SET == 0)
+ {
+ superfx_gpr_write(cpustate, 15, cpustate->r[15] + e);
+ }
+ break;
+ }
+ case 0x09: // BEQ
+ {
+ INT32 e = (INT8)superfx_pipe(cpustate);
+ if(SUPERFX_SFR_Z_SET == 1)
+ {
+ superfx_gpr_write(cpustate, 15, cpustate->r[15] + e);
+ }
+ break;
+ }
+ case 0x0a: // BPL
+ {
+ INT32 e = (INT8)superfx_pipe(cpustate);
+ if(SUPERFX_SFR_S_SET == 0)
+ {
+ superfx_gpr_write(cpustate, 15, cpustate->r[15] + e);
+ }
+ break;
+ }
+ case 0x0b: // BMI
+ {
+ INT32 e = (INT8)superfx_pipe(cpustate);
+ if(SUPERFX_SFR_S_SET == 1)
+ {
+ superfx_gpr_write(cpustate, 15, cpustate->r[15] + e);
+ }
+ break;
+ }
+ case 0x0c: // BCC
+ {
+ INT32 e = (INT8)superfx_pipe(cpustate);
+ if(SUPERFX_SFR_CY_SET == 0)
+ {
+ superfx_gpr_write(cpustate, 15, cpustate->r[15] + e);
+ }
+ break;
+ }
+ case 0x0d: // BCS
+ {
+ INT32 e = (INT8)superfx_pipe(cpustate);
+ if(SUPERFX_SFR_CY_SET == 1)
+ {
+ superfx_gpr_write(cpustate, 15, cpustate->r[15] + e);
+ }
+ break;
+ }
+ case 0x0e: // BVC
+ {
+ INT32 e = (INT8)superfx_pipe(cpustate);
+ if(SUPERFX_SFR_OV_SET == 0)
+ {
+ superfx_gpr_write(cpustate, 15, cpustate->r[15] + e);
+ }
+ break;
+ }
+ case 0x0f: // BVS
+ {
+ INT32 e = (INT8)superfx_pipe(cpustate);
+ if(SUPERFX_SFR_OV_SET == 1)
+ {
+ superfx_gpr_write(cpustate, 15, cpustate->r[15] + e);
+ }
+ 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: // TO
+ if((cpustate->sfr & SUPERFX_SFR_B) == 0)
+ {
+ cpustate->dreg = &cpustate->r[op & 0xf];
+ cpustate->dreg_idx = op & 0xf;
+ }
+ else
+ {
+ superfx_gpr_write(cpustate, op & 0xf, *(cpustate->sreg));
+ superfx_regs_reset(cpustate);
+ }
+ break;
+
+ 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: // WITH
+ cpustate->sreg = &cpustate->r[op & 0xf];
+ cpustate->sreg_idx = op & 0xf;
+ cpustate->dreg = &cpustate->r[op & 0xf];
+ cpustate->dreg_idx = op & 0xf;
+ cpustate->sfr |= SUPERFX_SFR_B;
+ 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: // STW_IR / STB_IR
+ if((cpustate->sfr & SUPERFX_SFR_ALT1) == 0)
+ { // STW_IR
+ cpustate->ramaddr = cpustate->r[op & 0xf];
+ superfx_rambuffer_write(cpustate, cpustate->ramaddr ^ 0, (*(cpustate->sreg)) >> 0);
+ superfx_rambuffer_write(cpustate, cpustate->ramaddr ^ 1, (*(cpustate->sreg)) >> 8);
+ superfx_regs_reset(cpustate);
+ }
+ else
+ { // STB_IR
+ cpustate->ramaddr = cpustate->r[op & 0xf];
+ superfx_rambuffer_write(cpustate, cpustate->ramaddr, *(cpustate->sreg));
+ superfx_regs_reset(cpustate);
+ }
+ break;
+
+ case 0x3c: // LOOP
+ superfx_gpr_write(cpustate, 12, cpustate->r[12] - 1);
+ cpustate->sfr &= ~(SUPERFX_SFR_S | SUPERFX_SFR_Z);
+ cpustate->sfr |= (cpustate->r[12] & 0x8000) ? SUPERFX_SFR_S : 0;
+ cpustate->sfr |= (cpustate->r[12] == 0) ? SUPERFX_SFR_Z : 0;
+ if(!(cpustate->sfr & SUPERFX_SFR_Z))
+ {
+ superfx_gpr_write(cpustate, 15, cpustate->r[13]);
+ }
+ superfx_regs_reset(cpustate);
+ break;
+ case 0x3d: // ALT1
+ cpustate->sfr &= ~SUPERFX_SFR_B;
+ cpustate->sfr |= SUPERFX_SFR_ALT1;
+ break;
+ case 0x3e: // ALT2
+ cpustate->sfr &= ~SUPERFX_SFR_B;
+ cpustate->sfr |= SUPERFX_SFR_ALT2;
+ break;
+ case 0x3f: // ALT3
+ cpustate->sfr &= ~SUPERFX_SFR_B;
+ cpustate->sfr |= SUPERFX_SFR_ALT1;
+ cpustate->sfr |= SUPERFX_SFR_ALT2;
+ 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: // LDW_IR / LDB_IR
+ if((cpustate->sfr & SUPERFX_SFR_ALT1) == 0)
+ { // LDW_IR
+ UINT16 data = 0;
+ cpustate->ramaddr = cpustate->r[op & 0xf];
+ data = superfx_rambuffer_read(cpustate, cpustate->ramaddr ^ 0) << 0;
+ data |= superfx_rambuffer_read(cpustate, cpustate->ramaddr ^ 1) << 8;
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, data);
+ superfx_regs_reset(cpustate);
+ }
+ else
+ { // LDB_IR
+ cpustate->ramaddr = cpustate->r[op & 0xf];
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, superfx_rambuffer_read(cpustate, cpustate->ramaddr));
+ superfx_regs_reset(cpustate);
+ }
+ break;
+
+ case 0x4c: // PLOT / RPIX
+ if((cpustate->sfr & SUPERFX_SFR_ALT1) == 0)
+ { // PLOT
+ superfx_plot(cpustate, cpustate->r[1], cpustate->r[2]);
+ superfx_gpr_write(cpustate, 1, cpustate->r[1] + 1);
+ superfx_regs_reset(cpustate);
+ }
+ else
+ { // RPIX
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, superfx_rpix(cpustate, cpustate->r[1], cpustate->r[2]));
+ superfx_dreg_sfr_sz_update(cpustate);
+ superfx_regs_reset(cpustate);
+ }
+ break;
+
+ case 0x4d: // SWAP
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, (*(cpustate->sreg) >> 8) | (*(cpustate->sreg) << 8));
+ superfx_dreg_sfr_sz_update(cpustate);
+ superfx_regs_reset(cpustate);
+ break;
+
+ case 0x4e: // COLOR / CMODE
+ if((cpustate->sfr & SUPERFX_SFR_ALT1) == 0)
+ { // COLOR
+ cpustate->colr = superfx_color(cpustate, *(cpustate->sreg));
+ superfx_regs_reset(cpustate);
+ }
+ else
+ { // CMODE
+ cpustate->por = *(cpustate->sreg);
+ superfx_regs_reset(cpustate);
+ }
+ break;
+
+ case 0x4f: // NOT
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, ~(*(cpustate->sreg)));
+ superfx_dreg_sfr_sz_update(cpustate);
+ superfx_regs_reset(cpustate);
+ 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: // ADD / ADC / ADDI / ADCI
+ {
+ INT32 r = *(cpustate->sreg);
+ cpustate->sfr &= ~(SUPERFX_SFR_OV | SUPERFX_SFR_S | SUPERFX_SFR_Z);
+ switch(cpustate->sfr & SUPERFX_SFR_ALT)
+ {
+ case SUPERFX_SFR_ALT0: // ADD
+ r += cpustate->r[op & 0xf];
+ cpustate->sfr |= (~(*(cpustate->sreg) ^ cpustate->r[op & 0xf]) & (cpustate->r[op & 0xf] ^ r) & 0x8000) ? SUPERFX_SFR_OV : 0;
+ break;
+ case SUPERFX_SFR_ALT1: // ADC
+ r += cpustate->r[op & 0xf] + ((cpustate->sfr & SUPERFX_SFR_CY) ? 1 : 0);
+ cpustate->sfr |= (~(*(cpustate->sreg) ^ cpustate->r[op & 0xf]) & (cpustate->r[op & 0xf] ^ r) & 0x8000) ? SUPERFX_SFR_OV : 0;
+ break;
+ case SUPERFX_SFR_ALT2: // ADDI
+ r += op & 0xf;
+ cpustate->sfr |= (~(*(cpustate->sreg) ^ (op & 0xf)) & ((op & 0xf) ^ r) & 0x8000) ? SUPERFX_SFR_OV : 0;
+ break;
+ case SUPERFX_SFR_ALT3: // ADCI
+ r += (op & 0xf) + ((cpustate->sfr & SUPERFX_SFR_CY) ? 1 : 0);
+ cpustate->sfr |= (~(*(cpustate->sreg) ^ (op & 0xf)) & ((op & 0xf) ^ r) & 0x8000) ? SUPERFX_SFR_OV : 0;
+ break;
+ }
+ cpustate->sfr &= ~SUPERFX_SFR_CY;
+ cpustate->sfr |= (r & 0x8000) ? SUPERFX_SFR_S : 0;
+ cpustate->sfr |= (r >= 0x10000) ? SUPERFX_SFR_CY : 0;
+ cpustate->sfr |= ((UINT16)r == 0) ? SUPERFX_SFR_Z : 0;
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, r);
+ superfx_regs_reset(cpustate);
+ 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: // SUB / SBC / SUBI / CMP
+ {
+ INT32 r = 0;
+ cpustate->sfr &= ~(SUPERFX_SFR_OV | SUPERFX_SFR_S | SUPERFX_SFR_Z);
+ switch(cpustate->sfr & SUPERFX_SFR_ALT)
+ {
+ case SUPERFX_SFR_ALT0: // SUB
+ r = *(cpustate->sreg) - cpustate->r[op & 0xf];
+ cpustate->sfr |= ((*(cpustate->sreg) ^ cpustate->r[op & 0xf]) & (*(cpustate->sreg) ^ r) & 0x8000) ? SUPERFX_SFR_OV : 0;
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, r);
+ break;
+ case SUPERFX_SFR_ALT1: // SBC
+ r = *(cpustate->sreg) - cpustate->r[op & 0xf] - ((cpustate->sfr & SUPERFX_SFR_CY) ? 0 : 1);
+ cpustate->sfr |= ((*(cpustate->sreg) ^ cpustate->r[op & 0xf]) & (*(cpustate->sreg) ^ r) & 0x8000) ? SUPERFX_SFR_OV : 0;
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, r);
+ break;
+ case SUPERFX_SFR_ALT2: // SUBI
+ r = *(cpustate->sreg) - (op & 0xf);
+ cpustate->sfr |= ((*(cpustate->sreg) ^ (op & 0xf)) & (*(cpustate->sreg) ^ r) & 0x8000) ? SUPERFX_SFR_OV : 0;
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, r);
+ break;
+ case SUPERFX_SFR_ALT3: // CMP
+ r = *(cpustate->sreg) - cpustate->r[op & 0xf];
+ cpustate->sfr |= ((*(cpustate->sreg) ^ cpustate->r[op & 0xf]) & (*(cpustate->sreg) ^ r) & 0x8000) ? SUPERFX_SFR_OV : 0;
+ break;
+ }
+ cpustate->sfr &= ~SUPERFX_SFR_CY;
+ cpustate->sfr |= (r & 0x8000) ? SUPERFX_SFR_S : 0;
+ cpustate->sfr |= (r >= 0x0) ? SUPERFX_SFR_CY : 0;
+ cpustate->sfr |= ((UINT16)r == 0) ? SUPERFX_SFR_Z : 0;
+ superfx_regs_reset(cpustate);
+ break;
+ }
+
+ case 0x70: // MERGE
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, (cpustate->r[7] & 0xff00) | (cpustate->r[8] >> 8));
+ cpustate->sfr &= ~(SUPERFX_SFR_OV | SUPERFX_SFR_S | SUPERFX_SFR_CY | SUPERFX_SFR_Z);
+ cpustate->sfr |= (*(cpustate->dreg) & 0xc0c0) ? SUPERFX_SFR_OV : 0;
+ cpustate->sfr |= (*(cpustate->dreg) & 0x8080) ? SUPERFX_SFR_S : 0;
+ cpustate->sfr |= (*(cpustate->dreg) & 0xe0e0) ? SUPERFX_SFR_CY : 0;
+ cpustate->sfr |= (*(cpustate->dreg) & 0xf0f0) ? SUPERFX_SFR_Z : 0;
+ superfx_regs_reset(cpustate);
+ break;
+
+ 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: // AND / BIC / ANDI / BICI
+ switch(cpustate->sfr & SUPERFX_SFR_ALT)
+ {
+ case SUPERFX_SFR_ALT0: // AND
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, *(cpustate->sreg) & cpustate->r[op & 0xf]);
+ break;
+ case SUPERFX_SFR_ALT1: // BIC
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, *(cpustate->sreg) & ~cpustate->r[op & 0xf]);
+ break;
+ case SUPERFX_SFR_ALT2: // ANDI
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, *(cpustate->sreg) & (op & 0xf));
+ break;
+ case SUPERFX_SFR_ALT3: // BICI
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, *(cpustate->sreg) & ~(op & 0xf));
+ break;
+ }
+ superfx_dreg_sfr_sz_update(cpustate);
+ superfx_regs_reset(cpustate);
+ 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: // MULT / UMULT / MULTI / UMULTI
+ switch(cpustate->sfr & SUPERFX_SFR_ALT)
+ {
+ case SUPERFX_SFR_ALT0: // MULT
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, (INT8)(*(cpustate->sreg)) * (INT8)(cpustate->r[op & 0xf]));
+ break;
+ case SUPERFX_SFR_ALT1: // UMULT
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, (UINT8)(*(cpustate->sreg)) * (UINT8)(cpustate->r[op & 0xf]));
+ break;
+ case SUPERFX_SFR_ALT2: // MULTI
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, (INT8)(*(cpustate->sreg)) * (INT8)(op & 0xf));
+ break;
+ case SUPERFX_SFR_ALT3: // UMULTI
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, (UINT8)(*(cpustate->sreg)) * (UINT8)(op & 0xf));
+ break;
+ }
+ superfx_dreg_sfr_sz_update(cpustate);
+ superfx_regs_reset(cpustate);
+ if(!(cpustate->cfgr & SUPERFX_CFGR_MS0))
+ {
+ superfx_add_clocks_internal(cpustate, 2);
+ }
+ break;
+
+ case 0x90: // SBK
+ superfx_rambuffer_write(cpustate, cpustate->ramaddr ^ 0, *(cpustate->sreg) >> 0);
+ superfx_rambuffer_write(cpustate, cpustate->ramaddr ^ 1, *(cpustate->sreg) >> 8);
+ superfx_regs_reset(cpustate);
+ break;
+
+ case 0x91: case 0x92: case 0x93: case 0x94: // LINK
+ superfx_gpr_write(cpustate, 11, cpustate->r[15] + (op & 0xf));
+ superfx_regs_reset(cpustate);
+ break;
+
+ case 0x95: // SEX
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, (INT8)(*(cpustate->sreg)));
+ superfx_dreg_sfr_sz_update(cpustate);
+ superfx_regs_reset(cpustate);
+ break;
+
+ case 0x96: // ASR / DIV2
+ if((cpustate->sfr & SUPERFX_SFR_ALT1) == 0)
+ { // ASR
+ cpustate->sfr &= ~SUPERFX_SFR_CY;
+ cpustate->sfr |= (*(cpustate->sreg) & 1) ? SUPERFX_SFR_CY : 0;
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, (INT16)(*(cpustate->sreg)) >> 1);
+ superfx_dreg_sfr_sz_update(cpustate);
+ superfx_regs_reset(cpustate);
+ }
+ else
+ { // DIV2
+ cpustate->sfr &= ~SUPERFX_SFR_CY;
+ cpustate->sfr |= (*(cpustate->sreg) & 1) ? SUPERFX_SFR_CY : 0;
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, ((INT16)(*(cpustate->sreg)) >> 1) + ((UINT32)(*(cpustate->sreg) + 1) >> 16));
+ superfx_dreg_sfr_sz_update(cpustate);
+ superfx_regs_reset(cpustate);
+ }
+ break;
+
+ case 0x97: // ROR
+ {
+ UINT16 carry = *(cpustate->sreg) & 1;
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, (SUPERFX_SFR_CY_SET << 15) | ((UINT16)(*(cpustate->sreg)) >> 1));
+ cpustate->sfr &= ~SUPERFX_SFR_CY;
+ cpustate->sfr |= carry ? SUPERFX_SFR_CY : 0;
+ superfx_dreg_sfr_sz_update(cpustate);
+ superfx_regs_reset(cpustate);
+ break;
+ }
+
+ case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: // JMP / LJMP
+ if((cpustate->sfr & SUPERFX_SFR_ALT1) == 0)
+ { // JMP
+ superfx_gpr_write(cpustate, 15, cpustate->r[op & 0xf]);
+ superfx_regs_reset(cpustate);
+ }
+ else
+ { // LJMP
+ cpustate->pbr = cpustate->r[op & 0xf] & 0x7f;
+ superfx_gpr_write(cpustate, 15, *(cpustate->sreg));
+ cpustate->cbr = cpustate->r[15] & 0xfff0;
+ superfx_cache_flush(cpustate);
+ superfx_regs_reset(cpustate);
+ }
+ break;
+
+ case 0x9e: // LOB
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, (UINT16)(*(cpustate->sreg)) & 0x00ff);
+ cpustate->sfr &= ~(SUPERFX_SFR_S | SUPERFX_SFR_Z);
+ cpustate->sfr |= (*(cpustate->dreg) & 0x80) ? SUPERFX_SFR_S : 0;
+ cpustate->sfr |= (*(cpustate->dreg) == 0) ? SUPERFX_SFR_Z : 0;
+ superfx_regs_reset(cpustate);
+ break;
+
+ case 0x9f: // FMULT / LMULT
+ {
+ UINT32 result = (INT16)(*(cpustate->sreg)) * (INT16)(cpustate->r[6]);
+ if(cpustate->sfr & SUPERFX_SFR_ALT1)
+ { // LMULT
+ superfx_gpr_write(cpustate, 4, result);
+ }
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, result >> 16);
+ cpustate->sfr &= ~SUPERFX_SFR_CY;
+ cpustate->sfr |= (result & 0x8000) ? SUPERFX_SFR_CY : 0;
+ superfx_dreg_sfr_sz_update(cpustate);
+ superfx_regs_reset(cpustate);
+ superfx_add_clocks_internal(cpustate, 4 + ((cpustate->cfgr & SUPERFX_CFGR_MS0) ? 4 : 0));
+ 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: // IBT / LMS / SMS / LMS
+ switch(cpustate->sfr & SUPERFX_SFR_ALT)
+ {
+ case SUPERFX_SFR_ALT0: // IBT
+ superfx_gpr_write(cpustate, op & 0xf, (INT8)superfx_pipe(cpustate));
+ superfx_regs_reset(cpustate);
+ break;
+ case SUPERFX_SFR_ALT2: // SMS
+ cpustate->ramaddr = superfx_pipe(cpustate) << 1;
+ superfx_rambuffer_write(cpustate, cpustate->ramaddr ^ 0, cpustate->r[op & 0xf] >> 0);
+ superfx_rambuffer_write(cpustate, cpustate->ramaddr ^ 1, cpustate->r[op & 0xf] >> 8);
+ superfx_regs_reset(cpustate);
+ break;
+ case SUPERFX_SFR_ALT1: // LMS
+ case SUPERFX_SFR_ALT3: // LMS
+ {
+ UINT16 data = 0;
+ cpustate->ramaddr = superfx_pipe(cpustate) << 1;
+ data = superfx_rambuffer_read(cpustate, cpustate->ramaddr ^ 0) << 0;
+ data |= superfx_rambuffer_read(cpustate, cpustate->ramaddr ^ 1) << 8;
+ superfx_gpr_write(cpustate, op & 0xf, data);
+ superfx_regs_reset(cpustate);
+ break;
+ }
+ }
+ 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: // FROM
+ if((cpustate->sfr & SUPERFX_SFR_B) == 0)
+ {
+ cpustate->sreg = &(cpustate->r[op & 0xf]);
+ cpustate->sreg_idx = op & 0xf;
+ }
+ else
+ {
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, cpustate->r[op & 0xf]);
+ cpustate->sfr &= ~SUPERFX_SFR_OV;
+ cpustate->sfr |= (*(cpustate->dreg) & 0x80) ? SUPERFX_SFR_OV : 0;
+ superfx_dreg_sfr_sz_update(cpustate);
+ superfx_regs_reset(cpustate);
+ }
+ break;
+
+ case 0xc0: // HIB
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, (*(cpustate->sreg)) >> 8);
+ cpustate->sfr &= ~(SUPERFX_SFR_S | SUPERFX_SFR_Z);
+ cpustate->sfr |= (*(cpustate->dreg) & 0x80) ? SUPERFX_SFR_S : 0;
+ cpustate->sfr |= (*(cpustate->dreg) == 0) ? SUPERFX_SFR_Z : 0;
+ superfx_regs_reset(cpustate);
+ break;
+
+ 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: // OR / XOR / ORI / XORI
+ switch(cpustate->sfr & SUPERFX_SFR_ALT)
+ {
+ case SUPERFX_SFR_ALT0: // OR
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, *(cpustate->sreg) | cpustate->r[op & 0xf]);
+ break;
+ case SUPERFX_SFR_ALT1: // XOR
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, *(cpustate->sreg) ^ cpustate->r[op & 0xf]);
+ break;
+ case SUPERFX_SFR_ALT2: // ORI
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, *(cpustate->sreg) | (op & 0xf));
+ break;
+ case SUPERFX_SFR_ALT3: // XORI
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, *(cpustate->sreg) ^ (op & 0xf));
+ break;
+ }
+ superfx_dreg_sfr_sz_update(cpustate);
+ superfx_regs_reset(cpustate);
+ 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: // INC
+ superfx_gpr_write(cpustate, op & 0xf, cpustate->r[op & 0xf] + 1);
+ cpustate->sfr &= ~(SUPERFX_SFR_S | SUPERFX_SFR_Z);
+ cpustate->sfr |= (cpustate->r[op & 0xf] & 0x8000) ? SUPERFX_SFR_S : 0;
+ cpustate->sfr |= (cpustate->r[op & 0xf] == 0) ? SUPERFX_SFR_Z : 0;
+ superfx_regs_reset(cpustate);
+ break;
+
+ case 0xdf: // GETC / RAMB / ROMB
+ switch(cpustate->sfr & SUPERFX_SFR_ALT)
+ {
+ case SUPERFX_SFR_ALT0: // GETC
+ case SUPERFX_SFR_ALT1: // GETC
+ cpustate->colr = superfx_color(cpustate, superfx_rombuffer_read(cpustate));
+ superfx_regs_reset(cpustate);
+ break;
+ case SUPERFX_SFR_ALT2: // RAMB
+ superfx_rambuffer_sync(cpustate);
+ cpustate->rambr = ((*(cpustate->sreg)) & 1) ? 1 : 0;
+ superfx_regs_reset(cpustate);
+ break;
+ case SUPERFX_SFR_ALT3: // ROMB
+ superfx_rombuffer_sync(cpustate);
+ cpustate->rombr = *(cpustate->sreg) & 0x7f;
+ superfx_regs_reset(cpustate);
+ break;
+ }
+ break;
+
+ 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: // DEC
+ superfx_gpr_write(cpustate, op & 0xf, cpustate->r[op & 0xf] - 1);
+ cpustate->sfr &= ~(SUPERFX_SFR_S | SUPERFX_SFR_Z);
+ cpustate->sfr |= (cpustate->r[op & 0xf] & 0x8000) ? SUPERFX_SFR_S : 0;
+ cpustate->sfr |= (cpustate->r[op & 0xf] == 0) ? SUPERFX_SFR_Z : 0;
+ superfx_regs_reset(cpustate);
+ break;
+
+ case 0xef: // GETB / GETBH / GETBL / GETBS
+ {
+ UINT8 byte = superfx_rombuffer_read(cpustate);
+ switch(cpustate->sfr & SUPERFX_SFR_ALT)
+ {
+ case SUPERFX_SFR_ALT0: // GETB
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, byte);
+ break;
+ case SUPERFX_SFR_ALT1: // GETBH
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, (byte << 8) | (*(cpustate->sreg) & 0x00ff));
+ break;
+ case SUPERFX_SFR_ALT2: // GETBL
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, (*(cpustate->sreg) & 0xff00) | (byte << 0));
+ break;
+ case SUPERFX_SFR_ALT3: // GETBS
+ superfx_gpr_write(cpustate, cpustate->dreg_idx, (INT8)byte);
+ break;
+ }
+ superfx_regs_reset(cpustate);
+ break;
+ }
+
+ 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: // IWT / LM / SM / LM
+ {
+ UINT16 data;
+ switch(cpustate->sfr & SUPERFX_SFR_ALT)
+ {
+ case SUPERFX_SFR_ALT0: // IWT
+ data = superfx_pipe(cpustate) << 0;
+ data |= superfx_pipe(cpustate) << 8;
+ superfx_gpr_write(cpustate, op & 0xf, data);
+ superfx_regs_reset(cpustate);
+ break;
+ case SUPERFX_SFR_ALT2: // SM
+ cpustate->ramaddr = superfx_pipe(cpustate) << 0;
+ cpustate->ramaddr |= superfx_pipe(cpustate) << 8;
+ superfx_rambuffer_write(cpustate, cpustate->ramaddr ^ 0, cpustate->r[op & 0xf] >> 0);
+ superfx_rambuffer_write(cpustate, cpustate->ramaddr ^ 1, cpustate->r[op & 0xf] >> 8);
+ superfx_regs_reset(cpustate);
+ break;
+ case SUPERFX_SFR_ALT1:
+ case SUPERFX_SFR_ALT3: // LM
+ cpustate->ramaddr = superfx_pipe(cpustate) << 0;
+ cpustate->ramaddr |= superfx_pipe(cpustate) << 8;
+ data = superfx_rambuffer_read(cpustate, cpustate->ramaddr ^ 0) << 0;
+ data |= superfx_rambuffer_read(cpustate, cpustate->ramaddr ^ 1) << 8;
+ superfx_gpr_write(cpustate, op & 0xf, data);
+ superfx_regs_reset(cpustate);
+ break;
+ }
+ break;
+ }
+ }
+
+ if(!cpustate->r15_modified)
+ {
+ cpustate->r[15]++;
+ }
+
+ //printf( " r0:%04x r1:%04x r2:%04x r3:%04x r4:%04x r5:%04x r6:%04x r7:%04x\n", cpustate->r[0], cpustate->r[1], cpustate->r[2], cpustate->r[3], cpustate->r[4], cpustate->r[5], cpustate->r[6], cpustate->r[7] );
+ //printf( " r8:%04x r9:%04x r10:%04x r11:%04x r12:%04x r13:%04x r14:%04x r15:%04x\n", cpustate->r[8], cpustate->r[9], cpustate->r[10], cpustate->r[11], cpustate->r[12], cpustate->r[13], cpustate->r[14], cpustate->r[15] );
+ //printf( "sfr:%04x\n", cpustate->sfr );
+
+ --cpustate->icount;
+ }
+}
+
+/*****************************************************************************/
+
+CPU_DISASSEMBLE( superfx )
+{
+ superfx_state *cpustate = get_safe_token(device);
+
+ UINT8 op = *(UINT8 *)(opram + 0);
+ UINT8 param0 = *(UINT8 *)(opram + 1);
+ UINT8 param1 = *(UINT8 *)(opram + 2);
+ UINT16 alt = cpustate->sfr & SUPERFX_SFR_ALT;
+
+ return superfx_dasm_one(buffer, pc, op, param0, param1, alt);
+}
+
+/*****************************************************************************/
+
+static CPU_SET_INFO( superfx )
+{
+ superfx_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 + SUPERFX_PC: cpustate->r[15] = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_DREG: info->i = cpustate->dreg_idx; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_SREG: info->i = cpustate->sreg_idx; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R0: cpustate->r[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R1: cpustate->r[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R2: cpustate->r[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R3: cpustate->r[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R4: cpustate->r[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R5: cpustate->r[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R6: cpustate->r[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R7: cpustate->r[7] = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R8: cpustate->r[8] = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R9: cpustate->r[9] = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R10: cpustate->r[10] = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R11: cpustate->r[11] = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R12: cpustate->r[12] = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R13: cpustate->r[13] = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R14: cpustate->r[14] = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R15: cpustate->r[15] = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_SFR: cpustate->sfr = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_PBR: cpustate->pbr = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_ROMBR: cpustate->rombr = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_RAMBR: cpustate->rambr = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_CBR: cpustate->cbr = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_SCBR: cpustate->scbr = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_SCMR: cpustate->scmr = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_COLR: cpustate->colr = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_POR: cpustate->por = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_BRAMR: cpustate->bramr = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_VCR: cpustate->vcr = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_CFGR: cpustate->cfgr = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_CLSR: cpustate->clsr = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_ROMCL: cpustate->romcl = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_ROMDR: cpustate->romdr = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_RAMCL: cpustate->ramcl = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_RAMAR: cpustate->ramar = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_RAMDR: cpustate->ramdr = info->i; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_RAMADDR: cpustate->ramaddr = info->i; break;
+ }
+}
+
+CPU_GET_INFO( superfx )
+{
+ superfx_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(superfx_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 = 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 = 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: /* intentional fallthrough */
+ case CPUINFO_INT_REGISTER + SUPERFX_PC: info->i = ((cpustate->pbr << 16) | cpustate->r[15]) - 1; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_DREG: info->i = cpustate->dreg_idx; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_SREG: info->i = cpustate->sreg_idx; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R0: info->i = cpustate->r[0]; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R1: info->i = cpustate->r[1]; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R2: info->i = cpustate->r[2]; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R3: info->i = cpustate->r[3]; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R4: info->i = cpustate->r[4]; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R5: info->i = cpustate->r[5]; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R6: info->i = cpustate->r[6]; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R7: info->i = cpustate->r[7]; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R8: info->i = cpustate->r[8]; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R9: info->i = cpustate->r[9]; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R10: info->i = cpustate->r[10]; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R11: info->i = cpustate->r[11]; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R12: info->i = cpustate->r[12]; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R13: info->i = cpustate->r[13]; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R14: info->i = cpustate->r[14]; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_R15: info->i = cpustate->r[15]; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_SFR: info->i = cpustate->sfr; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_PBR: info->i = cpustate->sfr; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_ROMBR: info->i = cpustate->rombr; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_RAMBR: info->i = cpustate->rambr; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_CBR: info->i = cpustate->cbr; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_SCBR: info->i = cpustate->scbr; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_SCMR: info->i = cpustate->scmr; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_COLR: info->i = cpustate->colr; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_POR: info->i = cpustate->por; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_BRAMR: info->i = cpustate->bramr; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_VCR: info->i = cpustate->vcr; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_CFGR: info->i = cpustate->cfgr; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_CLSR: info->i = cpustate->clsr; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_ROMCL: info->i = cpustate->romcl; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_ROMDR: info->i = cpustate->romdr; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_RAMCL: info->i = cpustate->ramcl; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_RAMAR: info->i = cpustate->ramar; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_RAMDR: info->i = cpustate->ramdr; break;
+ case CPUINFO_INT_REGISTER + SUPERFX_RAMADDR: info->i = cpustate->ramaddr; 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(superfx); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(superfx); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(superfx); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(superfx); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(superfx); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(superfx); 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, "SuperFX"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "SuperFX"); 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 + SUPERFX_PC: sprintf(info->s, "PC: %06X", (cpustate->pbr << 16) | cpustate->r[15]); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_DREG: sprintf(info->s, "DREG: R%d", cpustate->dreg_idx); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_SREG: sprintf(info->s, "SREG: R%d", cpustate->sreg_idx); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_R0: sprintf(info->s, "R0: %04X", cpustate->r[0]); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_R1: sprintf(info->s, "R1: %04X", cpustate->r[1]); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_R2: sprintf(info->s, "R2: %04X", cpustate->r[2]); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_R3: sprintf(info->s, "R3: %04X", cpustate->r[3]); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_R4: sprintf(info->s, "R4: %04X", cpustate->r[4]); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_R5: sprintf(info->s, "R5: %04X", cpustate->r[5]); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_R6: sprintf(info->s, "R6: %04X", cpustate->r[6]); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_R7: sprintf(info->s, "R7: %04X", cpustate->r[7]); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_R8: sprintf(info->s, "R8: %04X", cpustate->r[8]); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_R9: sprintf(info->s, "R9: %04X", cpustate->r[9]); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_R10: sprintf(info->s, "R10: %04X", cpustate->r[10]); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_R11: sprintf(info->s, "R11: %04X", cpustate->r[11]); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_R12: sprintf(info->s, "R12: %04X", cpustate->r[12]); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_R13: sprintf(info->s, "R13: %04X", cpustate->r[13]); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_R14: sprintf(info->s, "R14: %04X", cpustate->r[14]); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_R15: sprintf(info->s, "R15: %04X", cpustate->r[15]); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_SFR: sprintf(info->s, "SFR: %04X", cpustate->sfr); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_PBR: sprintf(info->s, "PBR: %02X", cpustate->sfr); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_ROMBR: sprintf(info->s, "ROMBR: %02X", cpustate->rombr); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_RAMBR: sprintf(info->s, "RAMBR: %02X", cpustate->rambr); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_CBR: sprintf(info->s, "CBR: %04X", cpustate->cbr); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_SCBR: sprintf(info->s, "SCBR: %02X", cpustate->scbr); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_SCMR: sprintf(info->s, "SCMR: %02X", cpustate->scmr); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_COLR: sprintf(info->s, "COLR %02X", cpustate->colr); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_POR: sprintf(info->s, "POR: %02X", cpustate->por); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_BRAMR: sprintf(info->s, "BRAMR: %02X", cpustate->bramr); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_VCR: sprintf(info->s, "VCR: %02X", cpustate->vcr); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_CFGR: sprintf(info->s, "CFGR: %02X", cpustate->cfgr); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_CLSR: sprintf(info->s, "CLSR: %02X", cpustate->clsr); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_ROMCL: sprintf(info->s, "ROMCL: %08X", cpustate->romcl); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_ROMDR: sprintf(info->s, "ROMDR: %02X", cpustate->romdr); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_RAMCL: sprintf(info->s, "RAMCL: %08X", cpustate->ramcl); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_RAMAR: sprintf(info->s, "RAMAR: %04X", cpustate->ramar); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_RAMDR: sprintf(info->s, "RAMDR: %02X", cpustate->ramdr); break;
+ case CPUINFO_STR_REGISTER + SUPERFX_RAMADDR: sprintf(info->s, "RAMADDR: %04X", cpustate->ramaddr); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(SUPERFX, superfx);
diff --git a/trunk/src/emu/cpu/superfx/superfx.h b/trunk/src/emu/cpu/superfx/superfx.h
new file mode 100644
index 00000000000..a6aafe82e26
--- /dev/null
+++ b/trunk/src/emu/cpu/superfx/superfx.h
@@ -0,0 +1,104 @@
+#ifndef __SUPERFX_H__
+#define __SUPERFX_H__
+
+
+enum
+{
+ SUPERFX_PC = 1,
+
+ SUPERFX_DREG,
+ SUPERFX_SREG,
+
+ SUPERFX_R0,
+ SUPERFX_R1,
+ SUPERFX_R2,
+ SUPERFX_R3,
+ SUPERFX_R4,
+ SUPERFX_R5,
+ SUPERFX_R6,
+ SUPERFX_R7,
+ SUPERFX_R8,
+ SUPERFX_R9,
+ SUPERFX_R10,
+ SUPERFX_R11,
+ SUPERFX_R12,
+ SUPERFX_R13,
+ SUPERFX_R14,
+ SUPERFX_R15,
+
+ SUPERFX_PBR,
+ SUPERFX_SFR,
+ SUPERFX_ROMBR,
+ SUPERFX_RAMBR,
+ SUPERFX_CBR,
+ SUPERFX_SCBR,
+ SUPERFX_SCMR,
+ SUPERFX_COLR,
+ SUPERFX_POR,
+ SUPERFX_BRAMR,
+ SUPERFX_VCR,
+ SUPERFX_CFGR,
+ SUPERFX_CLSR,
+
+ SUPERFX_ROMCL,
+ SUPERFX_ROMDR,
+
+ SUPERFX_RAMCL,
+ SUPERFX_RAMAR,
+ SUPERFX_RAMDR,
+ SUPERFX_RAMADDR,
+};
+
+#define SUPERFX_SFR_IRQ 0x8000 // Interrupt Flag
+#define SUPERFX_SFR_B 0x1000 // WITH Flag
+#define SUPERFX_SFR_IH 0x0800 // Immediate Higher 8-bit Flag
+#define SUPERFX_SFR_IL 0x0400 // Immediate Lower 8-bit Flag
+#define SUPERFX_SFR_ALT 0x0300 // ALT Mode, both bits
+#define SUPERFX_SFR_ALT0 0x0000 // ALT Mode, no bits
+#define SUPERFX_SFR_ALT1 0x0100 // ALT Mode, bit 0
+#define SUPERFX_SFR_ALT2 0x0200 // ALT Mode, bit 1
+#define SUPERFX_SFR_ALT3 0x0300 // ALT Mode, both bits (convenience dupe)
+#define SUPERFX_SFR_R 0x0040 // ROM R14 Read Flag
+#define SUPERFX_SFR_G 0x0020 // GO Flag
+#define SUPERFX_SFR_OV 0x0010 // Overflow Flag
+#define SUPERFX_SFR_S 0x0008 // Sign Flag
+#define SUPERFX_SFR_CY 0x0004 // Carry Flag
+#define SUPERFX_SFR_Z 0x0002 // Zero Flag
+
+#define SUPERFX_POR_OBJ 0x10
+#define SUPERFX_POR_FREEZEHIGH 0x08
+#define SUPERFX_POR_HIGHNIBBLE 0x04
+#define SUPERFX_POR_DITHER 0x02
+#define SUPERFX_POR_TRANSPARENT 0x01
+
+#define SUPERFX_SCMR_HT_MASK 0x24
+#define SUPERFX_SCMR_HT0 0x00
+#define SUPERFX_SCMR_HT1 0x04
+#define SUPERFX_SCMR_HT2 0x20
+#define SUPERFX_SCMR_HT3 0x24
+#define SUPERFX_SCMR_RON 0x10
+#define SUPERFX_SCMR_RAN 0x08
+#define SUPERFX_SCMR_MD 0x03
+
+#define SUPERFX_CFGR_IRQ 0x80 // IRQ
+#define SUPERFX_CFGR_MS0 0x20 // MS0
+
+typedef struct _superfx_config superfx_config;
+struct _superfx_config
+{
+ devcb_write_line out_irq_func; /* IRQ changed callback */
+};
+#define SUPERFX_CONFIG(name) const superfx_config (name) =
+
+DECLARE_LEGACY_CPU_DEVICE(SUPERFX, superfx);
+
+CPU_DISASSEMBLE( superfx );
+extern offs_t superfx_dasm_one(char *buffer, offs_t pc, UINT8 op, UINT8 param0, UINT8 param1, UINT16 alt);
+
+UINT8 superfx_mmio_read(device_t *cpu, UINT32 addr);
+void superfx_mmio_write(device_t *cpu, UINT32 addr, UINT8 data);
+void superfx_add_clocks(device_t *cpu, INT32 clocks);
+int superfx_access_ram(device_t *cpu);
+int superfx_access_rom(device_t *cpu);
+
+#endif /* __SUPERFX_H__ */
diff --git a/trunk/src/emu/cpu/t11/t11.c b/trunk/src/emu/cpu/t11/t11.c
new file mode 100644
index 00000000000..f89429ceb65
--- /dev/null
+++ b/trunk/src/emu/cpu/t11/t11.c
@@ -0,0 +1,499 @@
+/*** t11: Portable DEC T-11 emulator ******************************************
+
+ Copyright Aaron Giles
+
+ System dependencies: long must be at least 32 bits
+ word must be 16 bit unsigned int
+ byte must be 8 bit unsigned int
+ long must be more than 16 bits
+ arrays up to 65536 bytes must be supported
+ machine must be twos complement
+
+*****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "t11.h"
+
+
+/*************************************
+ *
+ * Internal state representation
+ *
+ *************************************/
+
+typedef struct _t11_state t11_state;
+struct _t11_state
+{
+ PAIR ppc; /* previous program counter */
+ PAIR reg[8];
+ PAIR psw;
+ UINT16 initial_pc;
+ UINT8 wait_state;
+ UINT8 irq_state;
+ int icount;
+ device_irq_callback irq_callback;
+ legacy_cpu_device * device;
+ address_space *program;
+ direct_read_data *direct;
+};
+
+
+INLINE t11_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == T11);
+ return (t11_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+
+
+/*************************************
+ *
+ * Macro shortcuts
+ *
+ *************************************/
+
+/* registers of various sizes */
+#define REGD(x) reg[x].d
+#define REGW(x) reg[x].w.l
+#define REGB(x) reg[x].b.l
+
+/* PC, SP, and PSW definitions */
+#define SP REGW(6)
+#define PC REGW(7)
+#define SPD REGD(6)
+#define PCD REGD(7)
+#define PSW psw.b.l
+
+
+/*************************************
+ *
+ * Low-level memory operations
+ *
+ *************************************/
+
+INLINE int ROPCODE(t11_state *cpustate)
+{
+ cpustate->PC &= 0xfffe;
+ int val = cpustate->direct->read_decrypted_word(cpustate->PC);
+ cpustate->PC += 2;
+ return val;
+}
+
+
+INLINE int RBYTE(t11_state *cpustate, int addr)
+{
+ return cpustate->program->read_byte(addr);
+}
+
+
+INLINE void WBYTE(t11_state *cpustate, int addr, int data)
+{
+ cpustate->program->write_byte(addr, data);
+}
+
+
+INLINE int RWORD(t11_state *cpustate, int addr)
+{
+ return cpustate->program->read_word(addr & 0xfffe);
+}
+
+
+INLINE void WWORD(t11_state *cpustate, int addr, int data)
+{
+ cpustate->program->write_word(addr & 0xfffe, data);
+}
+
+
+
+/*************************************
+ *
+ * Low-level stack operations
+ *
+ *************************************/
+
+INLINE void PUSH(t11_state *cpustate, int val)
+{
+ cpustate->SP -= 2;
+ WWORD(cpustate, cpustate->SPD, val);
+}
+
+
+INLINE int POP(t11_state *cpustate)
+{
+ int result = RWORD(cpustate, cpustate->SPD);
+ cpustate->SP += 2;
+ return result;
+}
+
+
+
+/*************************************
+ *
+ * Flag definitions and operations
+ *
+ *************************************/
+
+/* flag definitions */
+#define CFLAG 1
+#define VFLAG 2
+#define ZFLAG 4
+#define NFLAG 8
+
+/* extracts flags */
+#define GET_C (cpustate->PSW & CFLAG)
+#define GET_V (cpustate->PSW & VFLAG)
+#define GET_Z (cpustate->PSW & ZFLAG)
+#define GET_N (cpustate->PSW & NFLAG)
+
+/* clears flags */
+#define CLR_C (cpustate->PSW &= ~CFLAG)
+#define CLR_V (cpustate->PSW &= ~VFLAG)
+#define CLR_Z (cpustate->PSW &= ~ZFLAG)
+#define CLR_N (cpustate->PSW &= ~NFLAG)
+
+/* sets flags */
+#define SET_C (cpustate->PSW |= CFLAG)
+#define SET_V (cpustate->PSW |= VFLAG)
+#define SET_Z (cpustate->PSW |= ZFLAG)
+#define SET_N (cpustate->PSW |= NFLAG)
+
+
+
+/*************************************
+ *
+ * Interrupt handling
+ *
+ *************************************/
+
+struct irq_table_entry
+{
+ UINT8 priority;
+ UINT8 vector;
+};
+
+static const struct irq_table_entry irq_table[] =
+{
+ { 0<<5, 0x00 },
+ { 4<<5, 0x38 },
+ { 4<<5, 0x34 },
+ { 4<<5, 0x30 },
+ { 5<<5, 0x5c },
+ { 5<<5, 0x58 },
+ { 5<<5, 0x54 },
+ { 5<<5, 0x50 },
+ { 6<<5, 0x4c },
+ { 6<<5, 0x48 },
+ { 6<<5, 0x44 },
+ { 6<<5, 0x40 },
+ { 7<<5, 0x6c },
+ { 7<<5, 0x68 },
+ { 7<<5, 0x64 },
+ { 7<<5, 0x60 }
+};
+
+static void t11_check_irqs(t11_state *cpustate)
+{
+ const struct irq_table_entry *irq = &irq_table[cpustate->irq_state & 15];
+ int priority = cpustate->PSW & 0xe0;
+
+ /* compare the priority of the interrupt to the PSW */
+ if (irq->priority > priority)
+ {
+ int vector = irq->vector;
+ int new_pc, new_psw;
+
+ /* call the callback; if we don't get -1 back, use the return value as our vector */
+ if (cpustate->irq_callback != NULL)
+ {
+ int new_vector = (*cpustate->irq_callback)(cpustate->device, cpustate->irq_state & 15);
+ if (new_vector != -1)
+ vector = new_vector;
+ }
+
+ /* fetch the new PC and PSW from that vector */
+ assert((vector & 3) == 0);
+ new_pc = RWORD(cpustate, vector);
+ new_psw = RWORD(cpustate, vector + 2);
+
+ /* push the old state, set the new one */
+ PUSH(cpustate, cpustate->PSW);
+ PUSH(cpustate, cpustate->PC);
+ cpustate->PCD = new_pc;
+ cpustate->PSW = new_psw;
+ t11_check_irqs(cpustate);
+
+ /* count cycles and clear the WAIT flag */
+ cpustate->icount -= 114;
+ cpustate->wait_state = 0;
+ }
+}
+
+
+
+/*************************************
+ *
+ * Core opcodes
+ *
+ *************************************/
+
+/* includes the static function prototypes and the master opcode table */
+#include "t11table.c"
+
+/* includes the actual opcode implementations */
+#include "t11ops.c"
+
+
+
+/*************************************
+ *
+ * Low-level initialization/cleanup
+ *
+ *************************************/
+
+static CPU_INIT( t11 )
+{
+ static const UINT16 initial_pc[] =
+ {
+ 0xc000, 0x8000, 0x4000, 0x2000,
+ 0x1000, 0x0000, 0xf600, 0xf400
+ };
+ const struct t11_setup *setup = (const struct t11_setup *)device->static_config();
+ t11_state *cpustate = get_safe_token(device);
+
+ cpustate->initial_pc = initial_pc[setup->mode >> 13];
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+
+ device->save_item(NAME(cpustate->ppc.w.l));
+ device->save_item(NAME(cpustate->reg[0].w.l));
+ device->save_item(NAME(cpustate->reg[1].w.l));
+ device->save_item(NAME(cpustate->reg[2].w.l));
+ device->save_item(NAME(cpustate->reg[3].w.l));
+ device->save_item(NAME(cpustate->reg[4].w.l));
+ device->save_item(NAME(cpustate->reg[5].w.l));
+ device->save_item(NAME(cpustate->reg[6].w.l));
+ device->save_item(NAME(cpustate->reg[7].w.l));
+ device->save_item(NAME(cpustate->psw.w.l));
+ device->save_item(NAME(cpustate->initial_pc));
+ device->save_item(NAME(cpustate->wait_state));
+ device->save_item(NAME(cpustate->irq_state));
+}
+
+
+
+/*************************************
+ *
+ * CPU reset
+ *
+ *************************************/
+
+static CPU_RESET( t11 )
+{
+ t11_state *cpustate = get_safe_token(device);
+
+ /* initial SP is 376 octal, or 0xfe */
+ cpustate->SP = 0x00fe;
+
+ /* initial PC comes from the setup word */
+ cpustate->PC = cpustate->initial_pc;
+
+ /* PSW starts off at highest priority */
+ cpustate->PSW = 0xe0;
+
+ /* initialize the IRQ state */
+ cpustate->irq_state = 0;
+
+ /* reset the remaining state */
+ cpustate->REGD(0) = 0;
+ cpustate->REGD(1) = 0;
+ cpustate->REGD(2) = 0;
+ cpustate->REGD(3) = 0;
+ cpustate->REGD(4) = 0;
+ cpustate->REGD(5) = 0;
+ cpustate->ppc.d = 0;
+ cpustate->wait_state = 0;
+}
+
+
+
+/*************************************
+ *
+ * Interrupt handling
+ *
+ *************************************/
+
+static void set_irq_line(t11_state *cpustate, int irqline, int state)
+{
+ /* set the appropriate bit */
+ if (state == CLEAR_LINE)
+ cpustate->irq_state &= ~(1 << irqline);
+ else
+ cpustate->irq_state |= 1 << irqline;
+}
+
+
+
+/*************************************
+ *
+ * Core execution
+ *
+ *************************************/
+
+static CPU_EXECUTE( t11 )
+{
+ t11_state *cpustate = get_safe_token(device);
+
+ t11_check_irqs(cpustate);
+
+ if (cpustate->wait_state)
+ {
+ cpustate->icount = 0;
+ goto getout;
+ }
+
+ do
+ {
+ UINT16 op;
+
+ cpustate->ppc = cpustate->reg[7]; /* copy PC to previous PC */
+
+ debugger_instruction_hook(device, cpustate->PCD);
+
+ op = ROPCODE(cpustate);
+ (*opcode_table[op >> 3])(cpustate, op);
+
+ } while (cpustate->icount > 0);
+
+getout:
+ ;
+}
+
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( t11 )
+{
+ t11_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 + T11_IRQ0: set_irq_line(cpustate, T11_IRQ0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + T11_IRQ1: set_irq_line(cpustate, T11_IRQ1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + T11_IRQ2: set_irq_line(cpustate, T11_IRQ2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + T11_IRQ3: set_irq_line(cpustate, T11_IRQ3, info->i); break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + T11_PC: cpustate->PC = info->i; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + T11_SP: cpustate->SP = info->i; break;
+ case CPUINFO_INT_REGISTER + T11_PSW: cpustate->PSW = info->i; break;
+ case CPUINFO_INT_REGISTER + T11_R0: cpustate->REGW(0) = info->i; break;
+ case CPUINFO_INT_REGISTER + T11_R1: cpustate->REGW(1) = info->i; break;
+ case CPUINFO_INT_REGISTER + T11_R2: cpustate->REGW(2) = info->i; break;
+ case CPUINFO_INT_REGISTER + T11_R3: cpustate->REGW(3) = info->i; break;
+ case CPUINFO_INT_REGISTER + T11_R4: cpustate->REGW(4) = info->i; break;
+ case CPUINFO_INT_REGISTER + T11_R5: cpustate->REGW(5) = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( t11 )
+{
+ t11_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(t11_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 4; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = -1; 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 = 6; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 12; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 110; 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 = 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 + T11_IRQ0: info->i = (cpustate->irq_state & 1) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + T11_IRQ1: info->i = (cpustate->irq_state & 2) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + T11_IRQ2: info->i = (cpustate->irq_state & 4) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + T11_IRQ3: info->i = (cpustate->irq_state & 8) ? ASSERT_LINE : CLEAR_LINE; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->ppc.w.l; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + T11_PC: info->i = cpustate->PCD; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + T11_SP: info->i = cpustate->SPD; break;
+ case CPUINFO_INT_REGISTER + T11_PSW: info->i = cpustate->PSW; break;
+ case CPUINFO_INT_REGISTER + T11_R0: info->i = cpustate->REGD(0); break;
+ case CPUINFO_INT_REGISTER + T11_R1: info->i = cpustate->REGD(1); break;
+ case CPUINFO_INT_REGISTER + T11_R2: info->i = cpustate->REGD(2); break;
+ case CPUINFO_INT_REGISTER + T11_R3: info->i = cpustate->REGD(3); break;
+ case CPUINFO_INT_REGISTER + T11_R4: info->i = cpustate->REGD(4); break;
+ case CPUINFO_INT_REGISTER + T11_R5: info->i = cpustate->REGD(5); 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(t11); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(t11); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(t11); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(t11); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(t11); 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, "T11"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "DEC T-11"); 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",
+ cpustate->psw.b.l & 0x80 ? '?':'.',
+ cpustate->psw.b.l & 0x40 ? 'I':'.',
+ cpustate->psw.b.l & 0x20 ? 'I':'.',
+ cpustate->psw.b.l & 0x10 ? 'T':'.',
+ cpustate->psw.b.l & 0x08 ? 'N':'.',
+ cpustate->psw.b.l & 0x04 ? 'Z':'.',
+ cpustate->psw.b.l & 0x02 ? 'V':'.',
+ cpustate->psw.b.l & 0x01 ? 'C':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + T11_PC: sprintf(info->s, "PC:%04X", cpustate->reg[7].w.l); break;
+ case CPUINFO_STR_REGISTER + T11_SP: sprintf(info->s, "SP:%04X", cpustate->reg[6].w.l); break;
+ case CPUINFO_STR_REGISTER + T11_PSW: sprintf(info->s, "PSW:%02X", cpustate->psw.b.l); break;
+ case CPUINFO_STR_REGISTER + T11_R0: sprintf(info->s, "R0:%04X", cpustate->reg[0].w.l); break;
+ case CPUINFO_STR_REGISTER + T11_R1: sprintf(info->s, "R1:%04X", cpustate->reg[1].w.l); break;
+ case CPUINFO_STR_REGISTER + T11_R2: sprintf(info->s, "R2:%04X", cpustate->reg[2].w.l); break;
+ case CPUINFO_STR_REGISTER + T11_R3: sprintf(info->s, "R3:%04X", cpustate->reg[3].w.l); break;
+ case CPUINFO_STR_REGISTER + T11_R4: sprintf(info->s, "R4:%04X", cpustate->reg[4].w.l); break;
+ case CPUINFO_STR_REGISTER + T11_R5: sprintf(info->s, "R5:%04X", cpustate->reg[5].w.l); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(T11, t11);
diff --git a/trunk/src/emu/cpu/t11/t11.h b/trunk/src/emu/cpu/t11/t11.h
new file mode 100644
index 00000000000..962e2788776
--- /dev/null
+++ b/trunk/src/emu/cpu/t11/t11.h
@@ -0,0 +1,39 @@
+/*** T-11: Portable DEC T-11 emulator ******************************************/
+
+#pragma once
+
+#ifndef __T11_H__
+#define __T11_H__
+
+
+enum
+{
+ T11_R0=1, T11_R1, T11_R2, T11_R3, T11_R4, T11_R5, T11_SP, T11_PC, T11_PSW
+};
+
+#define T11_IRQ0 0 /* IRQ0 */
+#define T11_IRQ1 1 /* IRQ1 */
+#define T11_IRQ2 2 /* IRQ2 */
+#define T11_IRQ3 3 /* IRQ3 */
+
+#define T11_RESERVED 0x000 /* Reserved vector */
+#define T11_TIMEOUT 0x004 /* Time-out/system error vector */
+#define T11_ILLINST 0x008 /* Illegal and reserved instruction vector */
+#define T11_BPT 0x00C /* BPT instruction vector */
+#define T11_IOT 0x010 /* IOT instruction vector */
+#define T11_PWRFAIL 0x014 /* Power fail vector */
+#define T11_EMT 0x018 /* EMT instruction vector */
+#define T11_TRAP 0x01C /* TRAP instruction vector */
+
+
+struct t11_setup
+{
+ UINT16 mode; /* initial processor mode */
+};
+
+
+DECLARE_LEGACY_CPU_DEVICE(T11, t11);
+
+CPU_DISASSEMBLE( t11 );
+
+#endif /* __T11_H__ */
diff --git a/trunk/src/emu/cpu/t11/t11dasm.c b/trunk/src/emu/cpu/t11/t11dasm.c
new file mode 100644
index 00000000000..848375a178a
--- /dev/null
+++ b/trunk/src/emu/cpu/t11/t11dasm.c
@@ -0,0 +1,516 @@
+/*
+ * A T11 disassembler
+ *
+ * Note: this is probably not the most efficient disassembler in the world :-)
+ *
+ * This code written by Aaron Giles (agiles@sirius.com) for the MAME project
+ *
+ */
+
+#include "emu.h"
+#include "debugger.h"
+#include "t11.h"
+
+static const char *const regs[8] = { "R0", "R1", "R2", "R3", "R4", "R5", "SP", "PC" };
+
+static const UINT8 *rombase;
+static offs_t pcbase;
+
+#define PARAM_WORD(v) ((v) = rombase[pc - pcbase] | (rombase[pc + 1 - pcbase] << 8), pc += 2)
+
+static unsigned MakeEA (char *ea, int lo, unsigned pc, int width)
+{
+ int reg, pm;
+
+ assert (width == 2 || width == 4);
+
+ reg = lo & 7;
+
+ switch ((lo >> 3) & 7)
+ {
+ case 0:
+ sprintf (ea, "%s", regs[reg]);
+ break;
+ case 1:
+ sprintf (ea, "(%s)", regs[reg]);
+ break;
+ case 2:
+ if (reg == 7)
+ {
+ PARAM_WORD (pm);
+ sprintf (ea, "#$%0*X", width, pm & ((width == 2) ? 0xff : 0xffff));
+ }
+ else
+ {
+ sprintf (ea, "(%s)+", regs[reg]);
+ }
+ break;
+ case 3:
+ if (reg == 7)
+ {
+ PARAM_WORD (pm);
+ sprintf (ea, "$%04X", pm &= 0xffff);
+ }
+ else
+ {
+ sprintf (ea, "@(%s)+", regs[reg]);
+ }
+ break;
+ case 4:
+ sprintf (ea, "-(%s)", regs[reg]);
+ break;
+ case 5:
+ sprintf (ea, "@-(%s)", regs[reg]);
+ break;
+ case 6:
+ PARAM_WORD (pm);
+ sprintf(ea, "%s$%X(%s)",
+ (pm&0x8000)?"-":"",
+ (pm&0x8000)?-(signed short)pm:pm,
+ regs[reg]);
+ break;
+ case 7:
+ PARAM_WORD (pm);
+ sprintf(ea, "@%s$%X(%s)",
+ (pm&0x8000)?"-":"",
+ (pm&0x8000)?-(signed short)pm:pm,
+ regs[reg]);
+ break;
+ }
+
+ return pc;
+}
+
+
+CPU_DISASSEMBLE( t11 )
+{
+ char ea1[32], ea2[32];
+ unsigned PC = pc;
+ UINT16 op, lo, hi, addr;
+ INT16 offset;
+ UINT32 flags = 0;
+
+ rombase = oprom;
+ pcbase = pc;
+
+ PARAM_WORD(op);
+ lo = op & 077;
+ hi = (op >> 6) & 077;
+
+ switch (op & 0xffc0)
+ {
+ case 0x0000:
+ switch (lo)
+ {
+ case 0x00: sprintf (buffer, "HALT"); break;
+ case 0x01: sprintf (buffer, "WAIT"); break;
+ case 0x02: sprintf (buffer, "RTI"); flags = DASMFLAG_STEP_OUT; break;
+ case 0x03: sprintf (buffer, "BPT"); break;
+ case 0x04: sprintf (buffer, "IOT"); break;
+ case 0x05: sprintf (buffer, "RESET"); break;
+ case 0x06: sprintf (buffer, "RTT"); break;
+ default: sprintf (buffer, "???? (%04X)", op); break;
+ }
+ break;
+ case 0x0040:
+ pc = MakeEA (ea1, lo, pc, 4);
+ sprintf (buffer, "JMP %s", ea1);
+ break;
+ case 0x0080:
+ switch (lo & 070)
+ {
+ case 000:
+ if( (lo & 7) == 7 )
+ sprintf (buffer, "RTS");
+ else
+ sprintf (buffer, "RTS %s", regs[lo & 7]);
+ flags = DASMFLAG_STEP_OUT;
+ break;
+ case 040:
+ case 050:
+ switch( lo & 15 )
+ {
+ case 0x00: sprintf (buffer, "NOP"); break;
+ case 0x0f: sprintf (buffer, "CCC"); break;
+ case 0x01: sprintf (buffer, "CEC"); break;
+ case 0x02: sprintf (buffer, "CEV"); break;
+ case 0x04: sprintf (buffer, "CEZ"); break;
+ case 0x08: sprintf (buffer, "CEN"); break;
+ default: sprintf (buffer, "Ccc #$%X", lo & 15); break;
+ }
+ break;
+ case 060:
+ case 070:
+ switch( lo & 15 )
+ {
+ case 0x00: sprintf (buffer, "NOP"); break;
+ case 0x0f: sprintf (buffer, "SCC"); break;
+ case 0x01: sprintf (buffer, "SEC"); break;
+ case 0x02: sprintf (buffer, "SEV"); break;
+ case 0x04: sprintf (buffer, "SEZ"); break;
+ case 0x08: sprintf (buffer, "SEN"); break;
+ default: sprintf (buffer, "Scc #$%X", lo & 15); break;
+ }
+ break;
+ }
+ break;
+ case 0x00c0:
+ pc = MakeEA (ea1, lo, pc, 4);
+ sprintf (buffer, "SWAB %s", ea1);
+ break;
+ case 0x0100: case 0x0140: case 0x0180: case 0x01c0:
+ offset = 2 * (INT8)(op & 0xff);
+ sprintf (buffer, "BR $%04X", pc + offset);
+ break;
+ case 0x0200: case 0x0240: case 0x0280: case 0x02c0:
+ offset = 2 * (INT8)(op & 0xff);
+ sprintf (buffer, "BNE $%04X", pc + offset);
+ break;
+ case 0x0300: case 0x0340: case 0x0380: case 0x03c0:
+ offset = 2 * (INT8)(op & 0xff);
+ sprintf (buffer, "BEQ $%04X", pc + offset);
+ break;
+ case 0x0400: case 0x0440: case 0x0480: case 0x04c0:
+ offset = 2 * (INT8)(op & 0xff);
+ sprintf (buffer, "BGE $%04X", pc + offset);
+ break;
+ case 0x0500: case 0x0540: case 0x0580: case 0x05c0:
+ offset = 2 * (INT8)(op & 0xff);
+ sprintf (buffer, "BLT $%04X", pc + offset);
+ break;
+ case 0x0600: case 0x0640: case 0x0680: case 0x06c0:
+ offset = 2 * (INT8)(op & 0xff);
+ sprintf (buffer, "BGT $%04X", pc + offset);
+ break;
+ case 0x0700: case 0x0740: case 0x0780: case 0x07c0:
+ offset = 2 * (INT8)(op & 0xff);
+ sprintf (buffer, "BLE $%04X", pc + offset);
+ break;
+ case 0x0800: case 0x0840: case 0x0880: case 0x08c0:
+ case 0x0900: case 0x0940: case 0x0980: case 0x09c0:
+ pc = MakeEA (ea1, lo, pc, 4);
+ if ( (hi & 7) == 7 )
+ sprintf (buffer, "JSR %s", ea1);
+ else
+ sprintf (buffer, "JSR %s,%s", regs[hi & 7], ea1);
+ flags = DASMFLAG_STEP_OVER;
+ break;
+ case 0x0a00:
+ pc = MakeEA (ea1, lo, pc, 4);
+ sprintf (buffer, "CLR %s", ea1);
+ break;
+ case 0x0a40:
+ pc = MakeEA (ea1, lo, pc, 4);
+ sprintf (buffer, "COM %s", ea1);
+ break;
+ case 0x0a80:
+ pc = MakeEA (ea1, lo, pc, 4);
+ sprintf (buffer, "INC %s", ea1);
+ break;
+ case 0x0ac0:
+ pc = MakeEA (ea1, lo, pc, 4);
+ sprintf (buffer, "DEC %s", ea1);
+ break;
+ case 0x0b00:
+ pc = MakeEA (ea1, lo, pc, 4);
+ sprintf (buffer, "NEG %s", ea1);
+ break;
+ case 0x0b40:
+ pc = MakeEA (ea1, lo, pc, 4);
+ sprintf (buffer, "ADC %s", ea1);
+ break;
+ case 0x0b80:
+ pc = MakeEA (ea1, lo, pc, 4);
+ sprintf (buffer, "SBC %s", ea1);
+ break;
+ case 0x0bc0:
+ pc = MakeEA (ea1, lo, pc, 4);
+ sprintf (buffer, "TST %s", ea1);
+ break;
+ case 0x0c00:
+ pc = MakeEA (ea1, lo, pc, 4);
+ sprintf (buffer, "ROR %s", ea1);
+ break;
+ case 0x0c40:
+ pc = MakeEA (ea1, lo, pc, 4);
+ sprintf (buffer, "ROL %s", ea1);
+ break;
+ case 0x0c80:
+ pc = MakeEA (ea1, lo, pc, 4);
+ sprintf (buffer, "ASR %s", ea1);
+ break;
+ case 0x0cc0:
+ pc = MakeEA (ea1, lo, pc, 4);
+ sprintf (buffer, "ASL %s", ea1);
+ break;
+/* case 0x0d00:
+ sprintf (buffer, "MARK #$%X", lo);
+ break;*/
+ case 0x0dc0:
+ pc = MakeEA (ea1, lo, pc, 4);
+ sprintf (buffer, "SXT %s", ea1);
+ break;
+ case 0x1000: case 0x1040: case 0x1080: case 0x10c0: case 0x1100: case 0x1140: case 0x1180: case 0x11c0:
+ case 0x1200: case 0x1240: case 0x1280: case 0x12c0: case 0x1300: case 0x1340: case 0x1380: case 0x13c0:
+ case 0x1400: case 0x1440: case 0x1480: case 0x14c0: case 0x1500: case 0x1540: case 0x1580: case 0x15c0:
+ case 0x1600: case 0x1640: case 0x1680: case 0x16c0: case 0x1700: case 0x1740: case 0x1780: case 0x17c0:
+ case 0x1800: case 0x1840: case 0x1880: case 0x18c0: case 0x1900: case 0x1940: case 0x1980: case 0x19c0:
+ case 0x1a00: case 0x1a40: case 0x1a80: case 0x1ac0: case 0x1b00: case 0x1b40: case 0x1b80: case 0x1bc0:
+ case 0x1c00: case 0x1c40: case 0x1c80: case 0x1cc0: case 0x1d00: case 0x1d40: case 0x1d80: case 0x1dc0:
+ case 0x1e00: case 0x1e40: case 0x1e80: case 0x1ec0: case 0x1f00: case 0x1f40: case 0x1f80: case 0x1fc0:
+ pc = MakeEA (ea1, hi, pc, 4);
+ pc = MakeEA (ea2, lo, pc, 4);
+ if (lo == 046) /* MOV src,-(SP) */
+ sprintf (buffer, "PUSH %s", ea1);
+ else
+ if (hi == 026) /* MOV (SP)+,buffer */
+ sprintf (buffer, "POP %s", ea2);
+ else /* all other */
+ sprintf (buffer, "MOV %s,%s", ea1, ea2);
+ break;
+ case 0x2000: case 0x2040: case 0x2080: case 0x20c0: case 0x2100: case 0x2140: case 0x2180: case 0x21c0:
+ case 0x2200: case 0x2240: case 0x2280: case 0x22c0: case 0x2300: case 0x2340: case 0x2380: case 0x23c0:
+ case 0x2400: case 0x2440: case 0x2480: case 0x24c0: case 0x2500: case 0x2540: case 0x2580: case 0x25c0:
+ case 0x2600: case 0x2640: case 0x2680: case 0x26c0: case 0x2700: case 0x2740: case 0x2780: case 0x27c0:
+ case 0x2800: case 0x2840: case 0x2880: case 0x28c0: case 0x2900: case 0x2940: case 0x2980: case 0x29c0:
+ case 0x2a00: case 0x2a40: case 0x2a80: case 0x2ac0: case 0x2b00: case 0x2b40: case 0x2b80: case 0x2bc0:
+ case 0x2c00: case 0x2c40: case 0x2c80: case 0x2cc0: case 0x2d00: case 0x2d40: case 0x2d80: case 0x2dc0:
+ case 0x2e00: case 0x2e40: case 0x2e80: case 0x2ec0: case 0x2f00: case 0x2f40: case 0x2f80: case 0x2fc0:
+ pc = MakeEA (ea1, hi, pc, 4);
+ pc = MakeEA (ea2, lo, pc, 4);
+ sprintf (buffer, "CMP %s,%s", ea1, ea2);
+ break;
+ case 0x3000: case 0x3040: case 0x3080: case 0x30c0: case 0x3100: case 0x3140: case 0x3180: case 0x31c0:
+ case 0x3200: case 0x3240: case 0x3280: case 0x32c0: case 0x3300: case 0x3340: case 0x3380: case 0x33c0:
+ case 0x3400: case 0x3440: case 0x3480: case 0x34c0: case 0x3500: case 0x3540: case 0x3580: case 0x35c0:
+ case 0x3600: case 0x3640: case 0x3680: case 0x36c0: case 0x3700: case 0x3740: case 0x3780: case 0x37c0:
+ case 0x3800: case 0x3840: case 0x3880: case 0x38c0: case 0x3900: case 0x3940: case 0x3980: case 0x39c0:
+ case 0x3a00: case 0x3a40: case 0x3a80: case 0x3ac0: case 0x3b00: case 0x3b40: case 0x3b80: case 0x3bc0:
+ case 0x3c00: case 0x3c40: case 0x3c80: case 0x3cc0: case 0x3d00: case 0x3d40: case 0x3d80: case 0x3dc0:
+ case 0x3e00: case 0x3e40: case 0x3e80: case 0x3ec0: case 0x3f00: case 0x3f40: case 0x3f80: case 0x3fc0:
+ pc = MakeEA (ea1, hi, pc, 4);
+ pc = MakeEA (ea2, lo, pc, 4);
+ sprintf (buffer, "BIT %s,%s", ea1, ea2);
+ break;
+ case 0x4000: case 0x4040: case 0x4080: case 0x40c0: case 0x4100: case 0x4140: case 0x4180: case 0x41c0:
+ case 0x4200: case 0x4240: case 0x4280: case 0x42c0: case 0x4300: case 0x4340: case 0x4380: case 0x43c0:
+ case 0x4400: case 0x4440: case 0x4480: case 0x44c0: case 0x4500: case 0x4540: case 0x4580: case 0x45c0:
+ case 0x4600: case 0x4640: case 0x4680: case 0x46c0: case 0x4700: case 0x4740: case 0x4780: case 0x47c0:
+ case 0x4800: case 0x4840: case 0x4880: case 0x48c0: case 0x4900: case 0x4940: case 0x4980: case 0x49c0:
+ case 0x4a00: case 0x4a40: case 0x4a80: case 0x4ac0: case 0x4b00: case 0x4b40: case 0x4b80: case 0x4bc0:
+ case 0x4c00: case 0x4c40: case 0x4c80: case 0x4cc0: case 0x4d00: case 0x4d40: case 0x4d80: case 0x4dc0:
+ case 0x4e00: case 0x4e40: case 0x4e80: case 0x4ec0: case 0x4f00: case 0x4f40: case 0x4f80: case 0x4fc0:
+ pc = MakeEA (ea1, hi, pc, 4);
+ pc = MakeEA (ea2, lo, pc, 4);
+ sprintf (buffer, "BIC %s,%s", ea1, ea2);
+ break;
+ case 0x5000: case 0x5040: case 0x5080: case 0x50c0: case 0x5100: case 0x5140: case 0x5180: case 0x51c0:
+ case 0x5200: case 0x5240: case 0x5280: case 0x52c0: case 0x5300: case 0x5340: case 0x5380: case 0x53c0:
+ case 0x5400: case 0x5440: case 0x5480: case 0x54c0: case 0x5500: case 0x5540: case 0x5580: case 0x55c0:
+ case 0x5600: case 0x5640: case 0x5680: case 0x56c0: case 0x5700: case 0x5740: case 0x5780: case 0x57c0:
+ case 0x5800: case 0x5840: case 0x5880: case 0x58c0: case 0x5900: case 0x5940: case 0x5980: case 0x59c0:
+ case 0x5a00: case 0x5a40: case 0x5a80: case 0x5ac0: case 0x5b00: case 0x5b40: case 0x5b80: case 0x5bc0:
+ case 0x5c00: case 0x5c40: case 0x5c80: case 0x5cc0: case 0x5d00: case 0x5d40: case 0x5d80: case 0x5dc0:
+ case 0x5e00: case 0x5e40: case 0x5e80: case 0x5ec0: case 0x5f00: case 0x5f40: case 0x5f80: case 0x5fc0:
+ pc = MakeEA (ea1, hi, pc, 4);
+ pc = MakeEA (ea2, lo, pc, 4);
+ sprintf (buffer, "BIS %s,%s", ea1, ea2);
+ break;
+ case 0x6000: case 0x6040: case 0x6080: case 0x60c0: case 0x6100: case 0x6140: case 0x6180: case 0x61c0:
+ case 0x6200: case 0x6240: case 0x6280: case 0x62c0: case 0x6300: case 0x6340: case 0x6380: case 0x63c0:
+ case 0x6400: case 0x6440: case 0x6480: case 0x64c0: case 0x6500: case 0x6540: case 0x6580: case 0x65c0:
+ case 0x6600: case 0x6640: case 0x6680: case 0x66c0: case 0x6700: case 0x6740: case 0x6780: case 0x67c0:
+ case 0x6800: case 0x6840: case 0x6880: case 0x68c0: case 0x6900: case 0x6940: case 0x6980: case 0x69c0:
+ case 0x6a00: case 0x6a40: case 0x6a80: case 0x6ac0: case 0x6b00: case 0x6b40: case 0x6b80: case 0x6bc0:
+ case 0x6c00: case 0x6c40: case 0x6c80: case 0x6cc0: case 0x6d00: case 0x6d40: case 0x6d80: case 0x6dc0:
+ case 0x6e00: case 0x6e40: case 0x6e80: case 0x6ec0: case 0x6f00: case 0x6f40: case 0x6f80: case 0x6fc0:
+ pc = MakeEA (ea1, hi, pc, 4);
+ pc = MakeEA (ea2, lo, pc, 4);
+ sprintf (buffer, "ADD %s,%s", ea1, ea2);
+ break;
+
+ case 0x7800: case 0x7840: case 0x7880: case 0x78c0: case 0x7900: case 0x7940: case 0x7980: case 0x79c0:
+ pc = MakeEA (ea1, lo, pc, 4);
+ sprintf (buffer, "XOR %s,%s", regs[hi & 7], ea1);
+ break;
+
+ case 0x7e00: case 0x7e40: case 0x7e80: case 0x7ec0: case 0x7f00: case 0x7f40: case 0x7f80: case 0x7fc0:
+ addr = (pc + 2 - 2 * lo) & 0xffff;
+ sprintf (buffer, "SOB %s,$%X", regs[hi & 7], addr);
+ break;
+
+ case 0x8000: case 0x8040: case 0x8080: case 0x80c0:
+ offset = 2 * (INT8)(op & 0xff);
+ sprintf (buffer, "BPL $%04X", pc + offset);
+ break;
+ case 0x8100: case 0x8140: case 0x8180: case 0x81c0:
+ offset = 2 * (INT8)(op & 0xff);
+ sprintf (buffer, "BMI $%04X", pc + offset);
+ break;
+ case 0x8200: case 0x8240: case 0x8280: case 0x82c0:
+ offset = 2 * (INT8)(op & 0xff);
+ sprintf (buffer, "BHI $%04X", pc + offset);
+ break;
+ case 0x8300: case 0x8340: case 0x8380: case 0x83c0:
+ offset = 2 * (INT8)(op & 0xff);
+ sprintf (buffer, "BLOS $%04X", pc + offset);
+ break;
+ case 0x8400: case 0x8440: case 0x8480: case 0x84c0:
+ offset = 2 * (INT8)(op & 0xff);
+ sprintf (buffer, "BVC $%04X", pc + offset);
+ break;
+ case 0x8500: case 0x8540: case 0x8580: case 0x85c0:
+ offset = 2 * (INT8)(op & 0xff);
+ sprintf (buffer, "BVS $%04X", pc + offset);
+ break;
+ case 0x8600: case 0x8640: case 0x8680: case 0x86c0:
+ offset = 2 * (INT8)(op & 0xff);
+ sprintf (buffer, "BCC $%04X", pc + offset);
+ break;
+ case 0x8700: case 0x8740: case 0x8780: case 0x87c0:
+ offset = 2 * (INT8)(op & 0xff);
+ sprintf (buffer, "BCS $%04X", pc + offset);
+ break;
+ case 0x8800: case 0x8840: case 0x8880: case 0x88c0:
+ sprintf (buffer, "EMT #$%02X", op & 0xff);
+ break;
+ case 0x8900: case 0x8940: case 0x8980: case 0x89c0:
+ sprintf (buffer, "TRAP #$%02X", op & 0xff);
+ break;
+
+ case 0x8a00:
+ pc = MakeEA (ea1, lo, pc, 2);
+ sprintf (buffer, "CLRB %s", ea1);
+ break;
+ case 0x8a40:
+ pc = MakeEA (ea1, lo, pc, 2);
+ sprintf (buffer, "COMB %s", ea1);
+ break;
+ case 0x8a80:
+ pc = MakeEA (ea1, lo, pc, 2);
+ sprintf (buffer, "INCB %s", ea1);
+ break;
+ case 0x8ac0:
+ pc = MakeEA (ea1, lo, pc, 2);
+ sprintf (buffer, "DECB %s", ea1);
+ break;
+ case 0x8b00:
+ pc = MakeEA (ea1, lo, pc, 2);
+ sprintf (buffer, "NEGB %s", ea1);
+ break;
+ case 0x8b40:
+ pc = MakeEA (ea1, lo, pc, 2);
+ sprintf (buffer, "ADCB %s", ea1);
+ break;
+ case 0x8b80:
+ pc = MakeEA (ea1, lo, pc, 2);
+ sprintf (buffer, "SBCB %s", ea1);
+ break;
+ case 0x8bc0:
+ pc = MakeEA (ea1, lo, pc, 2);
+ sprintf (buffer, "TSTB %s", ea1);
+ break;
+ case 0x8c00:
+ pc = MakeEA (ea1, lo, pc, 2);
+ sprintf (buffer, "RORB %s", ea1);
+ break;
+ case 0x8c40:
+ pc = MakeEA (ea1, lo, pc, 2);
+ sprintf (buffer, "ROLB %s", ea1);
+ break;
+ case 0x8c80:
+ pc = MakeEA (ea1, lo, pc, 2);
+ sprintf (buffer, "ASRB %s", ea1);
+ break;
+ case 0x8cc0:
+ pc = MakeEA (ea1, lo, pc, 2);
+ sprintf (buffer, "ASLB %s", ea1);
+ break;
+ case 0x8d00:
+ pc = MakeEA (ea1, lo, pc, 2);
+ sprintf (buffer, "MTPS %s", ea1);
+ break;
+ case 0x8dc0:
+ pc = MakeEA (ea1, lo, pc, 2);
+ sprintf (buffer, "MFPS %s", ea1);
+ break;
+ case 0x9000: case 0x9040: case 0x9080: case 0x90c0: case 0x9100: case 0x9140: case 0x9180: case 0x91c0:
+ case 0x9200: case 0x9240: case 0x9280: case 0x92c0: case 0x9300: case 0x9340: case 0x9380: case 0x93c0:
+ case 0x9400: case 0x9440: case 0x9480: case 0x94c0: case 0x9500: case 0x9540: case 0x9580: case 0x95c0:
+ case 0x9600: case 0x9640: case 0x9680: case 0x96c0: case 0x9700: case 0x9740: case 0x9780: case 0x97c0:
+ case 0x9800: case 0x9840: case 0x9880: case 0x98c0: case 0x9900: case 0x9940: case 0x9980: case 0x99c0:
+ case 0x9a00: case 0x9a40: case 0x9a80: case 0x9ac0: case 0x9b00: case 0x9b40: case 0x9b80: case 0x9bc0:
+ case 0x9c00: case 0x9c40: case 0x9c80: case 0x9cc0: case 0x9d00: case 0x9d40: case 0x9d80: case 0x9dc0:
+ case 0x9e00: case 0x9e40: case 0x9e80: case 0x9ec0: case 0x9f00: case 0x9f40: case 0x9f80: case 0x9fc0:
+ pc = MakeEA (ea1, hi, pc, 2);
+ pc = MakeEA (ea2, lo, pc, 2);
+ sprintf (buffer, "MOVB %s,%s", ea1, ea2);
+ break;
+ case 0xa000: case 0xa040: case 0xa080: case 0xa0c0: case 0xa100: case 0xa140: case 0xa180: case 0xa1c0:
+ case 0xa200: case 0xa240: case 0xa280: case 0xa2c0: case 0xa300: case 0xa340: case 0xa380: case 0xa3c0:
+ case 0xa400: case 0xa440: case 0xa480: case 0xa4c0: case 0xa500: case 0xa540: case 0xa580: case 0xa5c0:
+ case 0xa600: case 0xa640: case 0xa680: case 0xa6c0: case 0xa700: case 0xa740: case 0xa780: case 0xa7c0:
+ case 0xa800: case 0xa840: case 0xa880: case 0xa8c0: case 0xa900: case 0xa940: case 0xa980: case 0xa9c0:
+ case 0xaa00: case 0xaa40: case 0xaa80: case 0xaac0: case 0xab00: case 0xab40: case 0xab80: case 0xabc0:
+ case 0xac00: case 0xac40: case 0xac80: case 0xacc0: case 0xad00: case 0xad40: case 0xad80: case 0xadc0:
+ case 0xae00: case 0xae40: case 0xae80: case 0xaec0: case 0xaf00: case 0xaf40: case 0xaf80: case 0xafc0:
+ pc = MakeEA (ea1, hi, pc, 2);
+ pc = MakeEA (ea2, lo, pc, 2);
+ sprintf (buffer, "CMPB %s,%s", ea1, ea2);
+ break;
+ case 0xb000: case 0xb040: case 0xb080: case 0xb0c0: case 0xb100: case 0xb140: case 0xb180: case 0xb1c0:
+ case 0xb200: case 0xb240: case 0xb280: case 0xb2c0: case 0xb300: case 0xb340: case 0xb380: case 0xb3c0:
+ case 0xb400: case 0xb440: case 0xb480: case 0xb4c0: case 0xb500: case 0xb540: case 0xb580: case 0xb5c0:
+ case 0xb600: case 0xb640: case 0xb680: case 0xb6c0: case 0xb700: case 0xb740: case 0xb780: case 0xb7c0:
+ case 0xb800: case 0xb840: case 0xb880: case 0xb8c0: case 0xb900: case 0xb940: case 0xb980: case 0xb9c0:
+ case 0xba00: case 0xba40: case 0xba80: case 0xbac0: case 0xbb00: case 0xbb40: case 0xbb80: case 0xbbc0:
+ case 0xbc00: case 0xbc40: case 0xbc80: case 0xbcc0: case 0xbd00: case 0xbd40: case 0xbd80: case 0xbdc0:
+ case 0xbe00: case 0xbe40: case 0xbe80: case 0xbec0: case 0xbf00: case 0xbf40: case 0xbf80: case 0xbfc0:
+ pc = MakeEA (ea1, hi, pc, 2);
+ pc = MakeEA (ea2, lo, pc, 2);
+ sprintf (buffer, "BITB %s,%s", ea1, ea2);
+ break;
+ case 0xc000: case 0xc040: case 0xc080: case 0xc0c0: case 0xc100: case 0xc140: case 0xc180: case 0xc1c0:
+ case 0xc200: case 0xc240: case 0xc280: case 0xc2c0: case 0xc300: case 0xc340: case 0xc380: case 0xc3c0:
+ case 0xc400: case 0xc440: case 0xc480: case 0xc4c0: case 0xc500: case 0xc540: case 0xc580: case 0xc5c0:
+ case 0xc600: case 0xc640: case 0xc680: case 0xc6c0: case 0xc700: case 0xc740: case 0xc780: case 0xc7c0:
+ case 0xc800: case 0xc840: case 0xc880: case 0xc8c0: case 0xc900: case 0xc940: case 0xc980: case 0xc9c0:
+ case 0xca00: case 0xca40: case 0xca80: case 0xcac0: case 0xcb00: case 0xcb40: case 0xcb80: case 0xcbc0:
+ case 0xcc00: case 0xcc40: case 0xcc80: case 0xccc0: case 0xcd00: case 0xcd40: case 0xcd80: case 0xcdc0:
+ case 0xce00: case 0xce40: case 0xce80: case 0xcec0: case 0xcf00: case 0xcf40: case 0xcf80: case 0xcfc0:
+ pc = MakeEA (ea1, hi, pc, 2);
+ pc = MakeEA (ea2, lo, pc, 2);
+ sprintf (buffer, "BICB %s,%s", ea1, ea2);
+ break;
+ case 0xd000: case 0xd040: case 0xd080: case 0xd0c0: case 0xd100: case 0xd140: case 0xd180: case 0xd1c0:
+ case 0xd200: case 0xd240: case 0xd280: case 0xd2c0: case 0xd300: case 0xd340: case 0xd380: case 0xd3c0:
+ case 0xd400: case 0xd440: case 0xd480: case 0xd4c0: case 0xd500: case 0xd540: case 0xd580: case 0xd5c0:
+ case 0xd600: case 0xd640: case 0xd680: case 0xd6c0: case 0xd700: case 0xd740: case 0xd780: case 0xd7c0:
+ case 0xd800: case 0xd840: case 0xd880: case 0xd8c0: case 0xd900: case 0xd940: case 0xd980: case 0xd9c0:
+ case 0xda00: case 0xda40: case 0xda80: case 0xdac0: case 0xdb00: case 0xdb40: case 0xdb80: case 0xdbc0:
+ case 0xdc00: case 0xdc40: case 0xdc80: case 0xdcc0: case 0xdd00: case 0xdd40: case 0xdd80: case 0xddc0:
+ case 0xde00: case 0xde40: case 0xde80: case 0xdec0: case 0xdf00: case 0xdf40: case 0xdf80: case 0xdfc0:
+ pc = MakeEA (ea1, hi, pc, 2);
+ pc = MakeEA (ea2, lo, pc, 2);
+ sprintf (buffer, "BISB %s,%s", ea1, ea2);
+ break;
+ case 0xe000: case 0xe040: case 0xe080: case 0xe0c0: case 0xe100: case 0xe140: case 0xe180: case 0xe1c0:
+ case 0xe200: case 0xe240: case 0xe280: case 0xe2c0: case 0xe300: case 0xe340: case 0xe380: case 0xe3c0:
+ case 0xe400: case 0xe440: case 0xe480: case 0xe4c0: case 0xe500: case 0xe540: case 0xe580: case 0xe5c0:
+ case 0xe600: case 0xe640: case 0xe680: case 0xe6c0: case 0xe700: case 0xe740: case 0xe780: case 0xe7c0:
+ case 0xe800: case 0xe840: case 0xe880: case 0xe8c0: case 0xe900: case 0xe940: case 0xe980: case 0xe9c0:
+ case 0xea00: case 0xea40: case 0xea80: case 0xeac0: case 0xeb00: case 0xeb40: case 0xeb80: case 0xebc0:
+ case 0xec00: case 0xec40: case 0xec80: case 0xecc0: case 0xed00: case 0xed40: case 0xed80: case 0xedc0:
+ case 0xee00: case 0xee40: case 0xee80: case 0xeec0: case 0xef00: case 0xef40: case 0xef80: case 0xefc0:
+ pc = MakeEA (ea1, hi, pc, 4);
+ pc = MakeEA (ea2, lo, pc, 4);
+ sprintf (buffer, "SUB %s,%s", ea1, ea2);
+ break;
+
+ default:
+ sprintf (buffer, "???? (%06o)", op);
+ break;
+ }
+
+ return (pc - PC) | flags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/t11/t11ops.c b/trunk/src/emu/cpu/t11/t11ops.c
new file mode 100644
index 00000000000..0b7c82617d8
--- /dev/null
+++ b/trunk/src/emu/cpu/t11/t11ops.c
@@ -0,0 +1,1414 @@
+/*** t11: Portable DEC T-11 emulator ******************************************
+
+ Copyright Aaron Giles
+
+ Actual opcode implementation. Excuse the excessive use of macros, it
+ was the only way I could bear to type all this in!
+
+*****************************************************************************/
+
+
+/* given a register index 'r', this computes the effective address for a byte-sized operation
+ and puts the result in 'ea' */
+#define MAKE_EAB_RGD(r) ea = cpustate->REGD(r)
+#define MAKE_EAB_IN(r) ea = cpustate->REGD(r); cpustate->REGW(r) += ((r) < 6 ? 1 : 2)
+#define MAKE_EAB_INS(r) ea = cpustate->REGD(r); cpustate->REGW(r) += ((r) < 6 ? 1 : 2)
+#define MAKE_EAB_IND(r) ea = cpustate->REGD(r); cpustate->REGW(r) += 2; ea = RWORD(cpustate, ea)
+#define MAKE_EAB_DE(r) cpustate->REGW(r) -= ((r) < 6 ? 1 : 2); ea = cpustate->REGD(r)
+#define MAKE_EAB_DED(r) cpustate->REGW(r) -= 2; ea = cpustate->REGD(r); ea = RWORD(cpustate, ea)
+#define MAKE_EAB_IX(r) ea = ROPCODE(cpustate); ea = (ea + cpustate->REGD(r)) & 0xffff
+#define MAKE_EAB_IXD(r) ea = ROPCODE(cpustate); ea = (ea + cpustate->REGD(r)) & 0xffff; ea = RWORD(cpustate, ea)
+
+/* given a register index 'r', this computes the effective address for a word-sized operation
+ and puts the result in 'ea' */
+/* note that word accesses ignore the low bit!! this fixes APB! */
+#define MAKE_EAW_RGD(r) MAKE_EAB_RGD(r)
+#define MAKE_EAW_IN(r) ea = cpustate->REGD(r); cpustate->REGW(r) += 2
+#define MAKE_EAW_IND(r) MAKE_EAB_IND(r)
+#define MAKE_EAW_DE(r) cpustate->REGW(r) -= 2; ea = cpustate->REGD(r)
+#define MAKE_EAW_DED(r) MAKE_EAB_DED(r)
+#define MAKE_EAW_IX(r) MAKE_EAB_IX(r)
+#define MAKE_EAW_IXD(r) MAKE_EAB_IXD(r)
+
+/* extracts the source/destination register index from the opcode into 'sreg' or 'dreg' */
+#define GET_SREG sreg = (op >> 6) & 7
+#define GET_DREG dreg = op & 7
+
+/* for a byte-sized source operand: extracts 'sreg', computes 'ea', and loads the value into 'source' */
+#define GET_SB_RG GET_SREG; source = cpustate->REGB(sreg)
+#define GET_SB_RGD GET_SREG; MAKE_EAB_RGD(sreg); source = RBYTE(cpustate, ea)
+#define GET_SB_IN GET_SREG; if (sreg == 7) { source = ROPCODE(cpustate); } else { MAKE_EAB_IN(sreg); source = RBYTE(cpustate, ea); }
+#define GET_SB_IND GET_SREG; if (sreg == 7) { ea = ROPCODE(cpustate); } else { MAKE_EAB_IND(sreg); } source = RBYTE(cpustate, ea)
+#define GET_SB_DE GET_SREG; MAKE_EAB_DE(sreg); source = RBYTE(cpustate, ea)
+#define GET_SB_DED GET_SREG; MAKE_EAB_DED(sreg); source = RBYTE(cpustate, ea)
+#define GET_SB_IX GET_SREG; MAKE_EAB_IX(sreg); source = RBYTE(cpustate, ea)
+#define GET_SB_IXD GET_SREG; MAKE_EAB_IXD(sreg); source = RBYTE(cpustate, ea)
+
+/* for a word-sized source operand: extracts 'sreg', computes 'ea', and loads the value into 'source' */
+#define GET_SW_RG GET_SREG; source = cpustate->REGD(sreg)
+#define GET_SW_RGD GET_SREG; MAKE_EAW_RGD(sreg); source = RWORD(cpustate, ea)
+#define GET_SW_IN GET_SREG; if (sreg == 7) { source = ROPCODE(cpustate); } else { MAKE_EAW_IN(sreg); source = RWORD(cpustate, ea); }
+#define GET_SW_IND GET_SREG; if (sreg == 7) { ea = ROPCODE(cpustate); } else { MAKE_EAW_IND(sreg); } source = RWORD(cpustate, ea)
+#define GET_SW_DE GET_SREG; MAKE_EAW_DE(sreg); source = RWORD(cpustate, ea)
+#define GET_SW_DED GET_SREG; MAKE_EAW_DED(sreg); source = RWORD(cpustate, ea)
+#define GET_SW_IX GET_SREG; MAKE_EAW_IX(sreg); source = RWORD(cpustate, ea)
+#define GET_SW_IXD GET_SREG; MAKE_EAW_IXD(sreg); source = RWORD(cpustate, ea)
+
+/* for a byte-sized destination operand: extracts 'dreg', computes 'ea', and loads the value into 'dest' */
+#define GET_DB_RG GET_DREG; dest = cpustate->REGB(dreg)
+#define GET_DB_RGD GET_DREG; MAKE_EAB_RGD(dreg); dest = RBYTE(cpustate, ea)
+#define GET_DB_IN GET_DREG; MAKE_EAB_IN(dreg); dest = RBYTE(cpustate, ea)
+#define GET_DB_IND GET_DREG; if (dreg == 7) { ea = ROPCODE(cpustate); } else { MAKE_EAB_IND(dreg); } dest = RBYTE(cpustate, ea)
+#define GET_DB_DE GET_DREG; MAKE_EAB_DE(dreg); dest = RBYTE(cpustate, ea)
+#define GET_DB_DED GET_DREG; MAKE_EAB_DED(dreg); dest = RBYTE(cpustate, ea)
+#define GET_DB_IX GET_DREG; MAKE_EAB_IX(dreg); dest = RBYTE(cpustate, ea)
+#define GET_DB_IXD GET_DREG; MAKE_EAB_IXD(dreg); dest = RBYTE(cpustate, ea)
+
+/* for a word-sized destination operand: extracts 'dreg', computes 'ea', and loads the value into 'dest' */
+#define GET_DW_RG GET_DREG; dest = cpustate->REGD(dreg)
+#define GET_DW_RGD GET_DREG; MAKE_EAW_RGD(dreg); dest = RWORD(cpustate, ea)
+#define GET_DW_IN GET_DREG; MAKE_EAW_IN(dreg); dest = RWORD(cpustate, ea)
+#define GET_DW_IND GET_DREG; if (dreg == 7) { ea = ROPCODE(cpustate); } else { MAKE_EAW_IND(dreg); } dest = RWORD(cpustate, ea)
+#define GET_DW_DE GET_DREG; MAKE_EAW_DE(dreg); dest = RWORD(cpustate, ea)
+#define GET_DW_DED GET_DREG; MAKE_EAW_DED(dreg); dest = RWORD(cpustate, ea)
+#define GET_DW_IX GET_DREG; MAKE_EAW_IX(dreg); dest = RWORD(cpustate, ea)
+#define GET_DW_IXD GET_DREG; MAKE_EAW_IXD(dreg); dest = RWORD(cpustate, ea)
+
+/* writes a value to a previously computed 'ea' */
+#define PUT_DB_EA(v) WBYTE(cpustate, ea, (v))
+#define PUT_DW_EA(v) WWORD(cpustate, ea, (v))
+
+/* writes a value to a previously computed 'dreg' register */
+#define PUT_DB_DREG(v) cpustate->REGB(dreg) = (v)
+#define PUT_DW_DREG(v) cpustate->REGW(dreg) = (v)
+
+/* for a byte-sized destination operand: extracts 'dreg', computes 'ea', and writes 'v' to it */
+#define PUT_DB_RG(v) GET_DREG; cpustate->REGB(dreg) = (v)
+#define PUT_DB_RGD(v) GET_DREG; MAKE_EAB_RGD(dreg); WBYTE(cpustate, ea, (v))
+#define PUT_DB_IN(v) GET_DREG; MAKE_EAB_IN(dreg); WBYTE(cpustate, ea, (v))
+#define PUT_DB_IND(v) GET_DREG; if (dreg == 7) { ea = ROPCODE(cpustate); } else { MAKE_EAB_IND(dreg); } WBYTE(cpustate, ea, (v))
+#define PUT_DB_DE(v) GET_DREG; MAKE_EAB_DE(dreg); WBYTE(cpustate, ea, (v))
+#define PUT_DB_DED(v) GET_DREG; MAKE_EAB_DED(dreg); WBYTE(cpustate, ea, (v))
+#define PUT_DB_IX(v) GET_DREG; MAKE_EAB_IX(dreg); WBYTE(cpustate, ea, (v))
+#define PUT_DB_IXD(v) GET_DREG; MAKE_EAB_IXD(dreg); WBYTE(cpustate, ea, (v))
+
+/* for a word-sized destination operand: extracts 'dreg', computes 'ea', and writes 'v' to it */
+#define PUT_DW_RG(v) GET_DREG; cpustate->REGW(dreg) = (v)
+#define PUT_DW_RGD(v) GET_DREG; MAKE_EAW_RGD(dreg); WWORD(cpustate, ea, (v))
+#define PUT_DW_IN(v) GET_DREG; MAKE_EAW_IN(dreg); WWORD(cpustate, ea, (v))
+#define PUT_DW_IND(v) GET_DREG; if (dreg == 7) { ea = ROPCODE(cpustate); } else { MAKE_EAW_IND(dreg); } WWORD(cpustate, ea, (v))
+#define PUT_DW_DE(v) GET_DREG; MAKE_EAW_DE(dreg); WWORD(cpustate, ea, (v))
+#define PUT_DW_DED(v) GET_DREG; MAKE_EAW_DED(dreg); WWORD(cpustate, ea, (v))
+#define PUT_DW_IX(v) GET_DREG; MAKE_EAW_IX(dreg); WWORD(cpustate, ea, (v))
+#define PUT_DW_IXD(v) GET_DREG; MAKE_EAW_IXD(dreg); WWORD(cpustate, ea, (v))
+
+/* flag clearing; must be done before setting */
+#define CLR_ZV (cpustate->PSW &= ~(ZFLAG | VFLAG))
+#define CLR_NZV (cpustate->PSW &= ~(NFLAG | ZFLAG | VFLAG))
+#define CLR_NZVC (cpustate->PSW &= ~(NFLAG | ZFLAG | VFLAG | CFLAG))
+
+/* set individual flags byte-sized */
+#define SETB_N (cpustate->PSW |= (result >> 4) & 0x08)
+#define SETB_Z (cpustate->PSW |= ((result & 0xff) == 0) << 2)
+#define SETB_V (cpustate->PSW |= ((source ^ dest ^ result ^ (result >> 1)) >> 6) & 0x02)
+#define SETB_C (cpustate->PSW |= (result >> 8) & 0x01)
+#define SETB_NZ SETB_N; SETB_Z
+#define SETB_NZV SETB_N; SETB_Z; SETB_V
+#define SETB_NZVC SETB_N; SETB_Z; SETB_V; SETB_C
+
+/* set individual flags word-sized */
+#define SETW_N (cpustate->PSW |= (result >> 12) & 0x08)
+#define SETW_Z (cpustate->PSW |= ((result & 0xffff) == 0) << 2)
+#define SETW_V (cpustate->PSW |= ((source ^ dest ^ result ^ (result >> 1)) >> 14) & 0x02)
+#define SETW_C (cpustate->PSW |= (result >> 16) & 0x01)
+#define SETW_NZ SETW_N; SETW_Z
+#define SETW_NZV SETW_N; SETW_Z; SETW_V
+#define SETW_NZVC SETW_N; SETW_Z; SETW_V; SETW_C
+
+/* operations */
+/* ADC: dst += C */
+#define ADC_R(d) int dreg, source, dest, result; source = GET_C; GET_DW_##d; CLR_NZVC; result = dest + source; SETW_NZVC; PUT_DW_DREG(result)
+#define ADC_M(d) int dreg, source, dest, result, ea; source = GET_C; GET_DW_##d; CLR_NZVC; result = dest + source; SETW_NZVC; PUT_DW_EA(result)
+#define ADCB_R(d) int dreg, source, dest, result; source = GET_C; GET_DB_##d; CLR_NZVC; result = dest + source; SETB_NZVC; PUT_DB_DREG(result)
+#define ADCB_M(d) int dreg, source, dest, result, ea; source = GET_C; GET_DB_##d; CLR_NZVC; result = dest + source; SETB_NZVC; PUT_DB_EA(result)
+/* ADD: dst += src */
+#define ADD_R(s,d) int sreg, dreg, source, dest, result; GET_SW_##s; GET_DW_##d; CLR_NZVC; result = dest + source; SETW_NZVC; PUT_DW_DREG(result)
+#define ADD_X(s,d) int sreg, dreg, source, dest, result, ea; GET_SW_##s; GET_DW_##d; CLR_NZVC; result = dest + source; SETW_NZVC; PUT_DW_DREG(result)
+#define ADD_M(s,d) int sreg, dreg, source, dest, result, ea; GET_SW_##s; GET_DW_##d; CLR_NZVC; result = dest + source; SETW_NZVC; PUT_DW_EA(result)
+/* ASL: dst = (dst << 1); C = (dst >> 7) */
+#define ASL_R(d) int dreg, dest, result; GET_DW_##d; CLR_NZVC; result = dest << 1; SETW_NZ; cpustate->PSW |= (dest >> 15) & 1; cpustate->PSW |= ((cpustate->PSW << 1) ^ (cpustate->PSW >> 2)) & 2; PUT_DW_DREG(result)
+#define ASL_M(d) int dreg, dest, result, ea; GET_DW_##d; CLR_NZVC; result = dest << 1; SETW_NZ; cpustate->PSW |= (dest >> 15) & 1; cpustate->PSW |= ((cpustate->PSW << 1) ^ (cpustate->PSW >> 2)) & 2; PUT_DW_EA(result)
+#define ASLB_R(d) int dreg, dest, result; GET_DB_##d; CLR_NZVC; result = dest << 1; SETB_NZ; cpustate->PSW |= (dest >> 7) & 1; cpustate->PSW |= ((cpustate->PSW << 1) ^ (cpustate->PSW >> 2)) & 2; PUT_DB_DREG(result)
+#define ASLB_M(d) int dreg, dest, result, ea; GET_DB_##d; CLR_NZVC; result = dest << 1; SETB_NZ; cpustate->PSW |= (dest >> 7) & 1; cpustate->PSW |= ((cpustate->PSW << 1) ^ (cpustate->PSW >> 2)) & 2; PUT_DB_EA(result)
+/* ASR: dst = (dst << 1); C = (dst >> 7) */
+#define ASR_R(d) int dreg, dest, result; GET_DW_##d; CLR_NZVC; result = (dest >> 1) | (dest & 0x8000); SETW_NZ; cpustate->PSW |= dest & 1; cpustate->PSW |= ((cpustate->PSW << 1) ^ (cpustate->PSW >> 2)) & 2; PUT_DW_DREG(result)
+#define ASR_M(d) int dreg, dest, result, ea; GET_DW_##d; CLR_NZVC; result = (dest >> 1) | (dest & 0x8000); SETW_NZ; cpustate->PSW |= dest & 1; cpustate->PSW |= ((cpustate->PSW << 1) ^ (cpustate->PSW >> 2)) & 2; PUT_DW_EA(result)
+#define ASRB_R(d) int dreg, dest, result; GET_DB_##d; CLR_NZVC; result = (dest >> 1) | (dest & 0x80); SETB_NZ; cpustate->PSW |= dest & 1; cpustate->PSW |= ((cpustate->PSW << 1) ^ (cpustate->PSW >> 2)) & 2; PUT_DB_DREG(result)
+#define ASRB_M(d) int dreg, dest, result, ea; GET_DB_##d; CLR_NZVC; result = (dest >> 1) | (dest & 0x80); SETB_NZ; cpustate->PSW |= dest & 1; cpustate->PSW |= ((cpustate->PSW << 1) ^ (cpustate->PSW >> 2)) & 2; PUT_DB_EA(result)
+/* BIC: dst &= ~src */
+#define BIC_R(s,d) int sreg, dreg, source, dest, result; GET_SW_##s; GET_DW_##d; CLR_NZV; result = dest & ~source; SETW_NZ; PUT_DW_DREG(result)
+#define BIC_X(s,d) int sreg, dreg, source, dest, result, ea; GET_SW_##s; GET_DW_##d; CLR_NZV; result = dest & ~source; SETW_NZ; PUT_DW_DREG(result)
+#define BIC_M(s,d) int sreg, dreg, source, dest, result, ea; GET_SW_##s; GET_DW_##d; CLR_NZV; result = dest & ~source; SETW_NZ; PUT_DW_EA(result)
+#define BICB_R(s,d) int sreg, dreg, source, dest, result; GET_SB_##s; GET_DB_##d; CLR_NZV; result = dest & ~source; SETB_NZ; PUT_DB_DREG(result)
+#define BICB_X(s,d) int sreg, dreg, source, dest, result, ea; GET_SB_##s; GET_DB_##d; CLR_NZV; result = dest & ~source; SETB_NZ; PUT_DB_DREG(result)
+#define BICB_M(s,d) int sreg, dreg, source, dest, result, ea; GET_SB_##s; GET_DB_##d; CLR_NZV; result = dest & ~source; SETB_NZ; PUT_DB_EA(result)
+/* BIS: dst |= src */
+#define BIS_R(s,d) int sreg, dreg, source, dest, result; GET_SW_##s; GET_DW_##d; CLR_NZV; result = dest | source; SETW_NZ; PUT_DW_DREG(result)
+#define BIS_X(s,d) int sreg, dreg, source, dest, result, ea; GET_SW_##s; GET_DW_##d; CLR_NZV; result = dest | source; SETW_NZ; PUT_DW_DREG(result)
+#define BIS_M(s,d) int sreg, dreg, source, dest, result, ea; GET_SW_##s; GET_DW_##d; CLR_NZV; result = dest | source; SETW_NZ; PUT_DW_EA(result)
+#define BISB_R(s,d) int sreg, dreg, source, dest, result; GET_SB_##s; GET_DB_##d; CLR_NZV; result = dest | source; SETB_NZ; PUT_DB_DREG(result)
+#define BISB_X(s,d) int sreg, dreg, source, dest, result, ea; GET_SB_##s; GET_DB_##d; CLR_NZV; result = dest | source; SETB_NZ; PUT_DB_DREG(result)
+#define BISB_M(s,d) int sreg, dreg, source, dest, result, ea; GET_SB_##s; GET_DB_##d; CLR_NZV; result = dest | source; SETB_NZ; PUT_DB_EA(result)
+/* BIT: flags = dst & src */
+#define BIT_R(s,d) int sreg, dreg, source, dest, result; GET_SW_##s; GET_DW_##d; CLR_NZV; result = dest & source; SETW_NZ;
+#define BIT_M(s,d) int sreg, dreg, source, dest, result, ea; GET_SW_##s; GET_DW_##d; CLR_NZV; result = dest & source; SETW_NZ;
+#define BITB_R(s,d) int sreg, dreg, source, dest, result; GET_SB_##s; GET_DB_##d; CLR_NZV; result = dest & source; SETB_NZ;
+#define BITB_M(s,d) int sreg, dreg, source, dest, result, ea; GET_SB_##s; GET_DB_##d; CLR_NZV; result = dest & source; SETB_NZ;
+/* BR: if (condition) branch */
+#define BR(c) if (c) { cpustate->PC += 2 * (signed char)(op & 0xff); }
+/* CLR: dst = 0 */
+#define CLR_R(d) int dreg; PUT_DW_##d(0); CLR_NZVC; SET_Z
+#define CLR_M(d) int dreg, ea; PUT_DW_##d(0); CLR_NZVC; SET_Z
+#define CLRB_R(d) int dreg; PUT_DB_##d(0); CLR_NZVC; SET_Z
+#define CLRB_M(d) int dreg, ea; PUT_DB_##d(0); CLR_NZVC; SET_Z
+/* CMP: flags = src - dst */
+#define CMP_R(s,d) int sreg, dreg, source, dest, result; GET_SW_##s; GET_DW_##d; CLR_NZVC; result = source - dest; SETW_NZVC;
+#define CMP_M(s,d) int sreg, dreg, source, dest, result, ea; GET_SW_##s; GET_DW_##d; CLR_NZVC; result = source - dest; SETW_NZVC;
+#define CMPB_R(s,d) int sreg, dreg, source, dest, result; GET_SB_##s; GET_DB_##d; CLR_NZVC; result = source - dest; SETB_NZVC;
+#define CMPB_M(s,d) int sreg, dreg, source, dest, result, ea; GET_SB_##s; GET_DB_##d; CLR_NZVC; result = source - dest; SETB_NZVC;
+/* COM: dst = ~dst */
+#define COM_R(d) int dreg, dest, result; GET_DW_##d; CLR_NZVC; result = ~dest; SETW_NZ; SET_C; PUT_DW_DREG(result)
+#define COM_M(d) int dreg, dest, result, ea; GET_DW_##d; CLR_NZVC; result = ~dest; SETW_NZ; SET_C; PUT_DW_EA(result)
+#define COMB_R(d) int dreg, dest, result; GET_DB_##d; CLR_NZVC; result = ~dest; SETB_NZ; SET_C; PUT_DB_DREG(result)
+#define COMB_M(d) int dreg, dest, result, ea; GET_DB_##d; CLR_NZVC; result = ~dest; SETB_NZ; SET_C; PUT_DB_EA(result)
+/* DEC: dst -= 1 */
+#define DEC_R(d) int dreg, dest, result; GET_DW_##d; CLR_NZV; result = dest - 1; SETW_NZ; if (dest == 0x8000) SET_V; PUT_DW_DREG(result)
+#define DEC_M(d) int dreg, dest, result, ea; GET_DW_##d; CLR_NZV; result = dest - 1; SETW_NZ; if (dest == 0x8000) SET_V; PUT_DW_EA(result)
+#define DECB_R(d) int dreg, dest, result; GET_DB_##d; CLR_NZV; result = dest - 1; SETB_NZ; if (dest == 0x80) SET_V; PUT_DB_DREG(result)
+#define DECB_M(d) int dreg, dest, result, ea; GET_DB_##d; CLR_NZV; result = dest - 1; SETB_NZ; if (dest == 0x80) SET_V; PUT_DB_EA(result)
+/* INC: dst += 1 */
+#define INC_R(d) int dreg, dest, result; GET_DW_##d; CLR_NZV; result = dest + 1; SETW_NZ; if (dest == 0x7fff) SET_V; PUT_DW_DREG(result)
+#define INC_M(d) int dreg, dest, result, ea; GET_DW_##d; CLR_NZV; result = dest + 1; SETW_NZ; if (dest == 0x7fff) SET_V; PUT_DW_EA(result)
+#define INCB_R(d) int dreg, dest, result; GET_DB_##d; CLR_NZV; result = dest + 1; SETB_NZ; if (dest == 0x7f) SET_V; PUT_DB_DREG(result)
+#define INCB_M(d) int dreg, dest, result, ea; GET_DB_##d; CLR_NZV; result = dest + 1; SETB_NZ; if (dest == 0x7f) SET_V; PUT_DB_EA(result)
+/* JMP: PC = ea */
+#define JMP(d) int dreg, ea; GET_DREG; MAKE_EAW_##d(dreg); cpustate->PC = ea
+/* JSR: PUSH src, src = PC, PC = ea */
+#define JSR(d) int sreg, dreg, ea; GET_SREG; GET_DREG; MAKE_EAW_##d(dreg); PUSH(cpustate, cpustate->REGW(sreg)); cpustate->REGW(sreg) = cpustate->PC; cpustate->PC = ea
+/* MFPS: dst = flags */
+#define MFPS_R(d) int dreg, result; result = cpustate->PSW; CLR_NZV; SETB_NZ; PUT_DW_##d((signed char)result)
+#define MFPS_M(d) int dreg, result, ea; result = cpustate->PSW; CLR_NZV; SETB_NZ; PUT_DB_##d(result)
+/* MOV: dst = src */
+#define MOV_R(s,d) int sreg, dreg, source, result; GET_SW_##s; CLR_NZV; result = source; SETW_NZ; PUT_DW_##d(result)
+#define MOV_M(s,d) int sreg, dreg, source, result, ea; GET_SW_##s; CLR_NZV; result = source; SETW_NZ; PUT_DW_##d(result)
+#define MOVB_R(s,d) int sreg, dreg, source, result; GET_SB_##s; CLR_NZV; result = source; SETB_NZ; PUT_DW_##d((signed char)result)
+#define MOVB_X(s,d) int sreg, dreg, source, result, ea; GET_SB_##s; CLR_NZV; result = source; SETB_NZ; PUT_DW_##d((signed char)result)
+#define MOVB_M(s,d) int sreg, dreg, source, result, ea; GET_SB_##s; CLR_NZV; result = source; SETB_NZ; PUT_DB_##d(result)
+/* MTPS: flags = src */
+#define MTPS_R(d) int dreg, dest; GET_DW_##d; cpustate->PSW = (cpustate->PSW & ~0xef) | (dest & 0xef); t11_check_irqs(cpustate)
+#define MTPS_M(d) int dreg, dest, ea; GET_DW_##d; cpustate->PSW = (cpustate->PSW & ~0xef) | (dest & 0xef); t11_check_irqs(cpustate)
+/* NEG: dst = -dst */
+#define NEG_R(d) int dreg, dest, result; GET_DW_##d; CLR_NZVC; result = -dest; SETW_NZ; if (dest == 0x8000) SET_V; if (result) SET_C; PUT_DW_DREG(result)
+#define NEG_M(d) int dreg, dest, result, ea; GET_DW_##d; CLR_NZVC; result = -dest; SETW_NZ; if (dest == 0x8000) SET_V; if (result) SET_C; PUT_DW_EA(result)
+#define NEGB_R(d) int dreg, dest, result; GET_DB_##d; CLR_NZVC; result = -dest; SETB_NZ; if (dest == 0x80) SET_V; if (result) SET_C; PUT_DB_DREG(result)
+#define NEGB_M(d) int dreg, dest, result, ea; GET_DB_##d; CLR_NZVC; result = -dest; SETB_NZ; if (dest == 0x80) SET_V; if (result) SET_C; PUT_DB_EA(result)
+/* ROL: dst = (dst << 1) | C; C = (dst >> 7) */
+#define ROL_R(d) int dreg, dest, result; GET_DW_##d; result = (dest << 1) | GET_C; CLR_NZVC; SETW_NZ; cpustate->PSW |= (dest >> 15) & 1; cpustate->PSW |= ((cpustate->PSW << 1) ^ (cpustate->PSW >> 2)) & 2; PUT_DW_DREG(result)
+#define ROL_M(d) int dreg, dest, result, ea; GET_DW_##d; result = (dest << 1) | GET_C; CLR_NZVC; SETW_NZ; cpustate->PSW |= (dest >> 15) & 1; cpustate->PSW |= ((cpustate->PSW << 1) ^ (cpustate->PSW >> 2)) & 2; PUT_DW_EA(result)
+#define ROLB_R(d) int dreg, dest, result; GET_DB_##d; result = (dest << 1) | GET_C; CLR_NZVC; SETB_NZ; cpustate->PSW |= (dest >> 7) & 1; cpustate->PSW |= ((cpustate->PSW << 1) ^ (cpustate->PSW >> 2)) & 2; PUT_DB_DREG(result)
+#define ROLB_M(d) int dreg, dest, result, ea; GET_DB_##d; result = (dest << 1) | GET_C; CLR_NZVC; SETB_NZ; cpustate->PSW |= (dest >> 7) & 1; cpustate->PSW |= ((cpustate->PSW << 1) ^ (cpustate->PSW >> 2)) & 2; PUT_DB_EA(result)
+/* ROR: dst = (dst >> 1) | (C << 7); C = dst & 1 */
+#define ROR_R(d) int dreg, dest, result; GET_DW_##d; result = (dest >> 1) | (GET_C << 15); CLR_NZVC; SETW_NZ; cpustate->PSW |= dest & 1; cpustate->PSW |= ((cpustate->PSW << 1) ^ (cpustate->PSW >> 2)) & 2; PUT_DW_DREG(result)
+#define ROR_M(d) int dreg, dest, result, ea; GET_DW_##d; result = (dest >> 1) | (GET_C << 15); CLR_NZVC; SETW_NZ; cpustate->PSW |= dest & 1; cpustate->PSW |= ((cpustate->PSW << 1) ^ (cpustate->PSW >> 2)) & 2; PUT_DW_EA(result)
+#define RORB_R(d) int dreg, dest, result; GET_DB_##d; result = (dest >> 1) | (GET_C << 7); CLR_NZVC; SETB_NZ; cpustate->PSW |= dest & 1; cpustate->PSW |= ((cpustate->PSW << 1) ^ (cpustate->PSW >> 2)) & 2; PUT_DB_DREG(result)
+#define RORB_M(d) int dreg, dest, result, ea; GET_DB_##d; result = (dest >> 1) | (GET_C << 7); CLR_NZVC; SETB_NZ; cpustate->PSW |= dest & 1; cpustate->PSW |= ((cpustate->PSW << 1) ^ (cpustate->PSW >> 2)) & 2; PUT_DB_EA(result)
+/* SBC: dst -= C */
+#define SBC_R(d) int dreg, source, dest, result; source = GET_C; GET_DW_##d; CLR_NZVC; result = dest - source; SETW_NZVC; PUT_DW_DREG(result)
+#define SBC_M(d) int dreg, source, dest, result, ea; source = GET_C; GET_DW_##d; CLR_NZVC; result = dest - source; SETW_NZVC; PUT_DW_EA(result)
+#define SBCB_R(d) int dreg, source, dest, result; source = GET_C; GET_DB_##d; CLR_NZVC; result = dest - source; SETB_NZVC; PUT_DB_DREG(result)
+#define SBCB_M(d) int dreg, source, dest, result, ea; source = GET_C; GET_DB_##d; CLR_NZVC; result = dest - source; SETB_NZVC; PUT_DB_EA(result)
+/* SUB: dst -= src */
+#define SUB_R(s,d) int sreg, dreg, source, dest, result; GET_SW_##s; GET_DW_##d; CLR_NZVC; result = dest - source; SETW_NZVC; PUT_DW_DREG(result)
+#define SUB_X(s,d) int sreg, dreg, source, dest, result, ea; GET_SW_##s; GET_DW_##d; CLR_NZVC; result = dest - source; SETW_NZVC; PUT_DW_DREG(result)
+#define SUB_M(s,d) int sreg, dreg, source, dest, result, ea; GET_SW_##s; GET_DW_##d; CLR_NZVC; result = dest - source; SETW_NZVC; PUT_DW_EA(result)
+#define SUBB_R(s,d) int sreg, dreg, source, dest, result; GET_SB_##s; GET_DB_##d; CLR_NZVC; result = dest - source; SETB_NZVC; PUT_DB_DREG(result)
+#define SUBB_X(s,d) int sreg, dreg, source, dest, result, ea; GET_SB_##s; GET_DB_##d; CLR_NZVC; result = dest - source; SETB_NZVC; PUT_DB_DREG(result)
+#define SUBB_M(s,d) int sreg, dreg, source, dest, result, ea; GET_SB_##s; GET_DB_##d; CLR_NZVC; result = dest - source; SETB_NZVC; PUT_DB_EA(result)
+/* SWAB: dst = (dst >> 8) + (dst << 8) */
+#define SWAB_R(d) int dreg, dest, result; GET_DW_##d; CLR_NZVC; result = ((dest >> 8) & 0xff) + (dest << 8); SETB_NZ; PUT_DW_DREG(result)
+#define SWAB_M(d) int dreg, dest, result, ea; GET_DW_##d; CLR_NZVC; result = ((dest >> 8) & 0xff) + (dest << 8); SETB_NZ; PUT_DW_EA(result)
+/* SXT: dst = sign-extend dst */
+#define SXT_R(d) int dreg, result; CLR_ZV; if (GET_N) result = -1; else { result = 0; SET_Z; } PUT_DW_##d(result)
+#define SXT_M(d) int dreg, result, ea; CLR_ZV; if (GET_N) result = -1; else { result = 0; SET_Z; } PUT_DW_##d(result)
+/* TST: dst = ~dst */
+#define TST_R(d) int dreg, dest, result; GET_DW_##d; CLR_NZVC; result = dest; SETW_NZ;
+#define TST_M(d) int dreg, dest, result, ea; GET_DW_##d; CLR_NZVC; result = dest; SETW_NZ;
+#define TSTB_R(d) int dreg, dest, result; GET_DB_##d; CLR_NZVC; result = dest; SETB_NZ;
+#define TSTB_M(d) int dreg, dest, result, ea; GET_DB_##d; CLR_NZVC; result = dest; SETB_NZ;
+/* XOR: dst ^= src */
+#define XOR_R(d) int sreg, dreg, source, dest, result; GET_SREG; source = cpustate->REGW(sreg); GET_DW_##d; CLR_NZV; result = dest ^ source; SETW_NZ; PUT_DW_DREG(result)
+#define XOR_M(d) int sreg, dreg, source, dest, result, ea; GET_SREG; source = cpustate->REGW(sreg); GET_DW_##d; CLR_NZV; result = dest ^ source; SETW_NZ; PUT_DW_EA(result)
+
+
+
+static void op_0000(t11_state *cpustate, UINT16 op)
+{
+ switch (op & 0x3f)
+ {
+ case 0x00: /* HALT */ halt(cpustate, op); break;
+ case 0x01: /* WAIT */ cpustate->icount = 0; cpustate->wait_state = 1; break;
+ case 0x02: /* RTI */ cpustate->icount -= 24; cpustate->PC = POP(cpustate); cpustate->PSW = POP(cpustate); t11_check_irqs(cpustate); break;
+ case 0x03: /* BPT */ cpustate->icount -= 48; PUSH(cpustate, cpustate->PSW); PUSH(cpustate, cpustate->PC); cpustate->PC = RWORD(cpustate, 0x0c); cpustate->PSW = RWORD(cpustate, 0x0e); t11_check_irqs(cpustate); break;
+ case 0x04: /* IOT */ cpustate->icount -= 48; PUSH(cpustate, cpustate->PSW); PUSH(cpustate, cpustate->PC); cpustate->PC = RWORD(cpustate, 0x10); cpustate->PSW = RWORD(cpustate, 0x12); t11_check_irqs(cpustate); break;
+ case 0x05: /* RESET */ cpustate->icount -= 110; break;
+ case 0x06: /* RTT */ cpustate->icount -= 33; cpustate->PC = POP(cpustate); cpustate->PSW = POP(cpustate); t11_check_irqs(cpustate); break;
+ default: illegal(cpustate, op); break;
+ }
+}
+
+static void halt(t11_state *cpustate, UINT16 op)
+{
+ cpustate->icount -= 48;
+ PUSH(cpustate, cpustate->PSW);
+ PUSH(cpustate, cpustate->PC);
+ cpustate->PC = RWORD(cpustate, 0x04);
+ cpustate->PSW = RWORD(cpustate, 0x06);
+ t11_check_irqs(cpustate);
+}
+
+static void illegal(t11_state *cpustate, UINT16 op)
+{
+ cpustate->icount -= 48;
+ PUSH(cpustate, cpustate->PSW);
+ PUSH(cpustate, cpustate->PC);
+ cpustate->PC = RWORD(cpustate, 0x08);
+ cpustate->PSW = RWORD(cpustate, 0x0a);
+ t11_check_irqs(cpustate);
+}
+
+static void mark(t11_state *cpustate, UINT16 op)
+{
+ cpustate->icount -= 36;
+
+ cpustate->SP = cpustate->SP + 2 * (op & 0x3f);
+ cpustate->PC = cpustate->REGW(5);
+ cpustate->REGW(5) = POP(cpustate);
+}
+
+static void jmp_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15; { JMP(RGD); } }
+static void jmp_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18; { JMP(IN); } }
+static void jmp_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18; { JMP(IND); } }
+static void jmp_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18; { JMP(DE); } }
+static void jmp_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { JMP(DED); } }
+static void jmp_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { JMP(IX); } }
+static void jmp_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { JMP(IXD); } }
+
+static void rts(t11_state *cpustate, UINT16 op)
+{
+ int dreg;
+ cpustate->icount -= 21;
+ GET_DREG;
+ cpustate->PC = cpustate->REGD(dreg);
+ cpustate->REGW(dreg) = POP(cpustate);
+}
+
+static void ccc(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18; { cpustate->PSW &= ~(op & 15); } }
+static void scc(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18; { cpustate->PSW |= (op & 15); } }
+
+static void swab_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { SWAB_R(RG); } }
+static void swab_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { SWAB_M(RGD); } }
+static void swab_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { SWAB_M(IN); } }
+static void swab_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { SWAB_M(IND); } }
+static void swab_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { SWAB_M(DE); } }
+static void swab_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { SWAB_M(DED); } }
+static void swab_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { SWAB_M(IX); } }
+static void swab_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { SWAB_M(IXD); } }
+
+static void br(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { BR(1); } }
+static void bne(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { BR(!GET_Z); } }
+static void beq(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { BR( GET_Z); } }
+static void bge(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { BR(!((GET_N >> 2) ^ GET_V)); } }
+static void blt(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { BR(((GET_N >> 2) ^ GET_V)); } }
+static void bgt(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { BR(!GET_Z && !((GET_N >> 2) ^ GET_V)); } }
+static void ble(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { BR( GET_Z || ((GET_N >> 2) ^ GET_V)); } }
+
+static void jsr_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { JSR(RGD); } }
+static void jsr_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { JSR(IN); } }
+static void jsr_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { JSR(IND); } }
+static void jsr_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { JSR(DE); } }
+static void jsr_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 33; { JSR(DED); } }
+static void jsr_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 33; { JSR(IX); } }
+static void jsr_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 39; { JSR(IXD); } }
+
+static void clr_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { CLR_R(RG); } }
+static void clr_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { CLR_M(RGD); } }
+static void clr_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { CLR_M(IN); } }
+static void clr_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { CLR_M(IND); } }
+static void clr_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { CLR_M(DE); } }
+static void clr_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { CLR_M(DED); } }
+static void clr_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { CLR_M(IX); } }
+static void clr_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { CLR_M(IXD); } }
+
+static void com_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { COM_R(RG); } }
+static void com_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { COM_M(RGD); } }
+static void com_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { COM_M(IN); } }
+static void com_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { COM_M(IND); } }
+static void com_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { COM_M(DE); } }
+static void com_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { COM_M(DED); } }
+static void com_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { COM_M(IX); } }
+static void com_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { COM_M(IXD); } }
+
+static void inc_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { INC_R(RG); } }
+static void inc_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { INC_M(RGD); } }
+static void inc_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { INC_M(IN); } }
+static void inc_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { INC_M(IND); } }
+static void inc_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { INC_M(DE); } }
+static void inc_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { INC_M(DED); } }
+static void inc_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { INC_M(IX); } }
+static void inc_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { INC_M(IXD); } }
+
+static void dec_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { DEC_R(RG); } }
+static void dec_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { DEC_M(RGD); } }
+static void dec_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { DEC_M(IN); } }
+static void dec_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { DEC_M(IND); } }
+static void dec_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { DEC_M(DE); } }
+static void dec_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { DEC_M(DED); } }
+static void dec_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { DEC_M(IX); } }
+static void dec_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { DEC_M(IXD); } }
+
+static void neg_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { NEG_R(RG); } }
+static void neg_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { NEG_M(RGD); } }
+static void neg_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { NEG_M(IN); } }
+static void neg_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { NEG_M(IND); } }
+static void neg_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { NEG_M(DE); } }
+static void neg_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { NEG_M(DED); } }
+static void neg_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { NEG_M(IX); } }
+static void neg_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { NEG_M(IXD); } }
+
+static void adc_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { ADC_R(RG); } }
+static void adc_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { ADC_M(RGD); } }
+static void adc_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { ADC_M(IN); } }
+static void adc_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { ADC_M(IND); } }
+static void adc_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { ADC_M(DE); } }
+static void adc_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { ADC_M(DED); } }
+static void adc_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { ADC_M(IX); } }
+static void adc_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { ADC_M(IXD); } }
+
+static void sbc_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { SBC_R(RG); } }
+static void sbc_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { SBC_M(RGD); } }
+static void sbc_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { SBC_M(IN); } }
+static void sbc_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { SBC_M(IND); } }
+static void sbc_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { SBC_M(DE); } }
+static void sbc_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { SBC_M(DED); } }
+static void sbc_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { SBC_M(IX); } }
+static void sbc_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { SBC_M(IXD); } }
+
+static void tst_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { TST_R(RG); } }
+static void tst_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18; { TST_M(RGD); } }
+static void tst_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18; { TST_M(IN); } }
+static void tst_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { TST_M(IND); } }
+static void tst_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { TST_M(DE); } }
+static void tst_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { TST_M(DED); } }
+static void tst_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { TST_M(IX); } }
+static void tst_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 33; { TST_M(IXD); } }
+
+static void ror_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { ROR_R(RG); } }
+static void ror_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { ROR_M(RGD); } }
+static void ror_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { ROR_M(IN); } }
+static void ror_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { ROR_M(IND); } }
+static void ror_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { ROR_M(DE); } }
+static void ror_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { ROR_M(DED); } }
+static void ror_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { ROR_M(IX); } }
+static void ror_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { ROR_M(IXD); } }
+
+static void rol_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { ROL_R(RG); } }
+static void rol_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { ROL_M(RGD); } }
+static void rol_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { ROL_M(IN); } }
+static void rol_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { ROL_M(IND); } }
+static void rol_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { ROL_M(DE); } }
+static void rol_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { ROL_M(DED); } }
+static void rol_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { ROL_M(IX); } }
+static void rol_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { ROL_M(IXD); } }
+
+static void asr_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { ASR_R(RG); } }
+static void asr_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { ASR_M(RGD); } }
+static void asr_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { ASR_M(IN); } }
+static void asr_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { ASR_M(IND); } }
+static void asr_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { ASR_M(DE); } }
+static void asr_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { ASR_M(DED); } }
+static void asr_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { ASR_M(IX); } }
+static void asr_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { ASR_M(IXD); } }
+
+static void asl_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { ASL_R(RG); } }
+static void asl_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { ASL_M(RGD); } }
+static void asl_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { ASL_M(IN); } }
+static void asl_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { ASL_M(IND); } }
+static void asl_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { ASL_M(DE); } }
+static void asl_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { ASL_M(DED); } }
+static void asl_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { ASL_M(IX); } }
+static void asl_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { ASL_M(IXD); } }
+
+static void sxt_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { SXT_R(RG); } }
+static void sxt_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { SXT_M(RGD); } }
+static void sxt_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { SXT_M(IN); } }
+static void sxt_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { SXT_M(IND); } }
+static void sxt_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { SXT_M(DE); } }
+static void sxt_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { SXT_M(DED); } }
+static void sxt_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { SXT_M(IX); } }
+static void sxt_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { SXT_M(IXD); } }
+
+static void mov_rg_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+ 3; { MOV_R(RG,RG); } }
+static void mov_rg_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+12; { MOV_M(RG,RGD); } }
+static void mov_rg_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+12; { MOV_M(RG,IN); } }
+static void mov_rg_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+18; { MOV_M(RG,IND); } }
+static void mov_rg_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+15; { MOV_M(RG,DE); } }
+static void mov_rg_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+21; { MOV_M(RG,DED); } }
+static void mov_rg_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+21; { MOV_M(RG,IX); } }
+static void mov_rg_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+27; { MOV_M(RG,IXD); } }
+static void mov_rgd_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 3; { MOV_M(RGD,RG); } }
+static void mov_rgd_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { MOV_M(RGD,RGD); } }
+static void mov_rgd_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { MOV_M(RGD,IN); } }
+static void mov_rgd_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { MOV_M(RGD,IND); } }
+static void mov_rgd_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+15; { MOV_M(RGD,DE); } }
+static void mov_rgd_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { MOV_M(RGD,DED); } }
+static void mov_rgd_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { MOV_M(RGD,IX); } }
+static void mov_rgd_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+27; { MOV_M(RGD,IXD); } }
+static void mov_in_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 3; { MOV_M(IN,RG); } }
+static void mov_in_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { MOV_M(IN,RGD); } }
+static void mov_in_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { MOV_M(IN,IN); } }
+static void mov_in_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { MOV_M(IN,IND); } }
+static void mov_in_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+15; { MOV_M(IN,DE); } }
+static void mov_in_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { MOV_M(IN,DED); } }
+static void mov_in_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { MOV_M(IN,IX); } }
+static void mov_in_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+27; { MOV_M(IN,IXD); } }
+static void mov_ind_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+ 3; { MOV_M(IND,RG); } }
+static void mov_ind_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+12; { MOV_M(IND,RGD); } }
+static void mov_ind_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+12; { MOV_M(IND,IN); } }
+static void mov_ind_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+18; { MOV_M(IND,IND); } }
+static void mov_ind_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+15; { MOV_M(IND,DE); } }
+static void mov_ind_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+21; { MOV_M(IND,DED); } }
+static void mov_ind_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+21; { MOV_M(IND,IX); } }
+static void mov_ind_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+27; { MOV_M(IND,IXD); } }
+static void mov_de_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+ 3; { MOV_M(DE,RG); } }
+static void mov_de_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+12; { MOV_M(DE,RGD); } }
+static void mov_de_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+12; { MOV_M(DE,IN); } }
+static void mov_de_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+18; { MOV_M(DE,IND); } }
+static void mov_de_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+15; { MOV_M(DE,DE); } }
+static void mov_de_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+21; { MOV_M(DE,DED); } }
+static void mov_de_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+21; { MOV_M(DE,IX); } }
+static void mov_de_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+27; { MOV_M(DE,IXD); } }
+static void mov_ded_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 3; { MOV_M(DED,RG); } }
+static void mov_ded_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { MOV_M(DED,RGD); } }
+static void mov_ded_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { MOV_M(DED,IN); } }
+static void mov_ded_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { MOV_M(DED,IND); } }
+static void mov_ded_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+15; { MOV_M(DED,DE); } }
+static void mov_ded_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { MOV_M(DED,DED); } }
+static void mov_ded_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { MOV_M(DED,IX); } }
+static void mov_ded_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+27; { MOV_M(DED,IXD); } }
+static void mov_ix_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 3; { MOV_M(IX,RG); } }
+static void mov_ix_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { MOV_M(IX,RGD); } }
+static void mov_ix_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { MOV_M(IX,IN); } }
+static void mov_ix_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { MOV_M(IX,IND); } }
+static void mov_ix_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+15; { MOV_M(IX,DE); } }
+static void mov_ix_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { MOV_M(IX,DED); } }
+static void mov_ix_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { MOV_M(IX,IX); } }
+static void mov_ix_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+27; { MOV_M(IX,IXD); } }
+static void mov_ixd_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+ 3; { MOV_M(IXD,RG); } }
+static void mov_ixd_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+12; { MOV_M(IXD,RGD); } }
+static void mov_ixd_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+12; { MOV_M(IXD,IN); } }
+static void mov_ixd_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+18; { MOV_M(IXD,IND); } }
+static void mov_ixd_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+15; { MOV_M(IXD,DE); } }
+static void mov_ixd_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+21; { MOV_M(IXD,DED); } }
+static void mov_ixd_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+21; { MOV_M(IXD,IX); } }
+static void mov_ixd_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+27; { MOV_M(IXD,IXD); } }
+
+static void cmp_rg_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+ 3; { CMP_R(RG,RG); } }
+static void cmp_rg_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+ 9; { CMP_M(RG,RGD); } }
+static void cmp_rg_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+ 9; { CMP_M(RG,IN); } }
+static void cmp_rg_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+15; { CMP_M(RG,IND); } }
+static void cmp_rg_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+12; { CMP_M(RG,DE); } }
+static void cmp_rg_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+18; { CMP_M(RG,DED); } }
+static void cmp_rg_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+18; { CMP_M(RG,IX); } }
+static void cmp_rg_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+24; { CMP_M(RG,IXD); } }
+static void cmp_rgd_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 3; { CMP_M(RGD,RG); } }
+static void cmp_rgd_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 9; { CMP_M(RGD,RGD); } }
+static void cmp_rgd_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 9; { CMP_M(RGD,IN); } }
+static void cmp_rgd_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+15; { CMP_M(RGD,IND); } }
+static void cmp_rgd_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { CMP_M(RGD,DE); } }
+static void cmp_rgd_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { CMP_M(RGD,DED); } }
+static void cmp_rgd_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { CMP_M(RGD,IX); } }
+static void cmp_rgd_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+24; { CMP_M(RGD,IXD); } }
+static void cmp_in_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 3; { CMP_M(IN,RG); } }
+static void cmp_in_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 9; { CMP_M(IN,RGD); } }
+static void cmp_in_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 9; { CMP_M(IN,IN); } }
+static void cmp_in_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+15; { CMP_M(IN,IND); } }
+static void cmp_in_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { CMP_M(IN,DE); } }
+static void cmp_in_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { CMP_M(IN,DED); } }
+static void cmp_in_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { CMP_M(IN,IX); } }
+static void cmp_in_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+24; { CMP_M(IN,IXD); } }
+static void cmp_ind_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+ 3; { CMP_M(IND,RG); } }
+static void cmp_ind_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+ 9; { CMP_M(IND,RGD); } }
+static void cmp_ind_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+ 9; { CMP_M(IND,IN); } }
+static void cmp_ind_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+15; { CMP_M(IND,IND); } }
+static void cmp_ind_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+12; { CMP_M(IND,DE); } }
+static void cmp_ind_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+18; { CMP_M(IND,DED); } }
+static void cmp_ind_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+18; { CMP_M(IND,IX); } }
+static void cmp_ind_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+24; { CMP_M(IND,IXD); } }
+static void cmp_de_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+ 3; { CMP_M(DE,RG); } }
+static void cmp_de_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+ 9; { CMP_M(DE,RGD); } }
+static void cmp_de_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+ 9; { CMP_M(DE,IN); } }
+static void cmp_de_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+15; { CMP_M(DE,IND); } }
+static void cmp_de_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+12; { CMP_M(DE,DE); } }
+static void cmp_de_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+18; { CMP_M(DE,DED); } }
+static void cmp_de_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+18; { CMP_M(DE,IX); } }
+static void cmp_de_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+24; { CMP_M(DE,IXD); } }
+static void cmp_ded_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 3; { CMP_M(DED,RG); } }
+static void cmp_ded_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 9; { CMP_M(DED,RGD); } }
+static void cmp_ded_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 9; { CMP_M(DED,IN); } }
+static void cmp_ded_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+15; { CMP_M(DED,IND); } }
+static void cmp_ded_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { CMP_M(DED,DE); } }
+static void cmp_ded_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { CMP_M(DED,DED); } }
+static void cmp_ded_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { CMP_M(DED,IX); } }
+static void cmp_ded_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+24; { CMP_M(DED,IXD); } }
+static void cmp_ix_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 3; { CMP_M(IX,RG); } }
+static void cmp_ix_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 9; { CMP_M(IX,RGD); } }
+static void cmp_ix_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 9; { CMP_M(IX,IN); } }
+static void cmp_ix_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+15; { CMP_M(IX,IND); } }
+static void cmp_ix_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { CMP_M(IX,DE); } }
+static void cmp_ix_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { CMP_M(IX,DED); } }
+static void cmp_ix_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { CMP_M(IX,IX); } }
+static void cmp_ix_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+24; { CMP_M(IX,IXD); } }
+static void cmp_ixd_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+ 3; { CMP_M(IXD,RG); } }
+static void cmp_ixd_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+ 9; { CMP_M(IXD,RGD); } }
+static void cmp_ixd_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+ 9; { CMP_M(IXD,IN); } }
+static void cmp_ixd_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+15; { CMP_M(IXD,IND); } }
+static void cmp_ixd_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+12; { CMP_M(IXD,DE); } }
+static void cmp_ixd_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+18; { CMP_M(IXD,DED); } }
+static void cmp_ixd_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+18; { CMP_M(IXD,IX); } }
+static void cmp_ixd_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+24; { CMP_M(IXD,IXD); } }
+
+static void bit_rg_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+ 3; { BIT_R(RG,RG); } }
+static void bit_rg_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+ 9; { BIT_M(RG,RGD); } }
+static void bit_rg_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+ 9; { BIT_M(RG,IN); } }
+static void bit_rg_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+15; { BIT_M(RG,IND); } }
+static void bit_rg_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+12; { BIT_M(RG,DE); } }
+static void bit_rg_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+18; { BIT_M(RG,DED); } }
+static void bit_rg_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+18; { BIT_M(RG,IX); } }
+static void bit_rg_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+24; { BIT_M(RG,IXD); } }
+static void bit_rgd_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 3; { BIT_M(RGD,RG); } }
+static void bit_rgd_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 9; { BIT_M(RGD,RGD); } }
+static void bit_rgd_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 9; { BIT_M(RGD,IN); } }
+static void bit_rgd_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+15; { BIT_M(RGD,IND); } }
+static void bit_rgd_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { BIT_M(RGD,DE); } }
+static void bit_rgd_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { BIT_M(RGD,DED); } }
+static void bit_rgd_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { BIT_M(RGD,IX); } }
+static void bit_rgd_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+24; { BIT_M(RGD,IXD); } }
+static void bit_in_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 3; { BIT_M(IN,RG); } }
+static void bit_in_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 9; { BIT_M(IN,RGD); } }
+static void bit_in_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 9; { BIT_M(IN,IN); } }
+static void bit_in_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+15; { BIT_M(IN,IND); } }
+static void bit_in_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { BIT_M(IN,DE); } }
+static void bit_in_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { BIT_M(IN,DED); } }
+static void bit_in_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { BIT_M(IN,IX); } }
+static void bit_in_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+24; { BIT_M(IN,IXD); } }
+static void bit_ind_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+ 3; { BIT_M(IND,RG); } }
+static void bit_ind_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+ 9; { BIT_M(IND,RGD); } }
+static void bit_ind_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+ 9; { BIT_M(IND,IN); } }
+static void bit_ind_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+15; { BIT_M(IND,IND); } }
+static void bit_ind_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+12; { BIT_M(IND,DE); } }
+static void bit_ind_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+18; { BIT_M(IND,DED); } }
+static void bit_ind_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+18; { BIT_M(IND,IX); } }
+static void bit_ind_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+24; { BIT_M(IND,IXD); } }
+static void bit_de_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+ 3; { BIT_M(DE,RG); } }
+static void bit_de_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+ 9; { BIT_M(DE,RGD); } }
+static void bit_de_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+ 9; { BIT_M(DE,IN); } }
+static void bit_de_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+15; { BIT_M(DE,IND); } }
+static void bit_de_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+12; { BIT_M(DE,DE); } }
+static void bit_de_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+18; { BIT_M(DE,DED); } }
+static void bit_de_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+18; { BIT_M(DE,IX); } }
+static void bit_de_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+24; { BIT_M(DE,IXD); } }
+static void bit_ded_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 3; { BIT_M(DED,RG); } }
+static void bit_ded_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 9; { BIT_M(DED,RGD); } }
+static void bit_ded_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 9; { BIT_M(DED,IN); } }
+static void bit_ded_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+15; { BIT_M(DED,IND); } }
+static void bit_ded_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { BIT_M(DED,DE); } }
+static void bit_ded_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { BIT_M(DED,DED); } }
+static void bit_ded_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { BIT_M(DED,IX); } }
+static void bit_ded_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+24; { BIT_M(DED,IXD); } }
+static void bit_ix_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 3; { BIT_M(IX,RG); } }
+static void bit_ix_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 9; { BIT_M(IX,RGD); } }
+static void bit_ix_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 9; { BIT_M(IX,IN); } }
+static void bit_ix_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+15; { BIT_M(IX,IND); } }
+static void bit_ix_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { BIT_M(IX,DE); } }
+static void bit_ix_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { BIT_M(IX,DED); } }
+static void bit_ix_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { BIT_M(IX,IX); } }
+static void bit_ix_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+24; { BIT_M(IX,IXD); } }
+static void bit_ixd_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+ 3; { BIT_M(IXD,RG); } }
+static void bit_ixd_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+ 9; { BIT_M(IXD,RGD); } }
+static void bit_ixd_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+ 9; { BIT_M(IXD,IN); } }
+static void bit_ixd_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+15; { BIT_M(IXD,IND); } }
+static void bit_ixd_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+12; { BIT_M(IXD,DE); } }
+static void bit_ixd_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+18; { BIT_M(IXD,DED); } }
+static void bit_ixd_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+18; { BIT_M(IXD,IX); } }
+static void bit_ixd_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+24; { BIT_M(IXD,IXD); } }
+
+static void bic_rg_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+ 3; { BIC_R(RG,RG); } }
+static void bic_rg_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+12; { BIC_M(RG,RGD); } }
+static void bic_rg_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+12; { BIC_M(RG,IN); } }
+static void bic_rg_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+18; { BIC_M(RG,IND); } }
+static void bic_rg_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+15; { BIC_M(RG,DE); } }
+static void bic_rg_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+21; { BIC_M(RG,DED); } }
+static void bic_rg_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+21; { BIC_M(RG,IX); } }
+static void bic_rg_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+27; { BIC_M(RG,IXD); } }
+static void bic_rgd_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 3; { BIC_X(RGD,RG); } }
+static void bic_rgd_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { BIC_M(RGD,RGD); } }
+static void bic_rgd_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { BIC_M(RGD,IN); } }
+static void bic_rgd_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { BIC_M(RGD,IND); } }
+static void bic_rgd_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+15; { BIC_M(RGD,DE); } }
+static void bic_rgd_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { BIC_M(RGD,DED); } }
+static void bic_rgd_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { BIC_M(RGD,IX); } }
+static void bic_rgd_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+27; { BIC_M(RGD,IXD); } }
+static void bic_in_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 3; { BIC_X(IN,RG); } }
+static void bic_in_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { BIC_M(IN,RGD); } }
+static void bic_in_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { BIC_M(IN,IN); } }
+static void bic_in_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { BIC_M(IN,IND); } }
+static void bic_in_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+15; { BIC_M(IN,DE); } }
+static void bic_in_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { BIC_M(IN,DED); } }
+static void bic_in_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { BIC_M(IN,IX); } }
+static void bic_in_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+27; { BIC_M(IN,IXD); } }
+static void bic_ind_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+ 3; { BIC_X(IND,RG); } }
+static void bic_ind_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+12; { BIC_M(IND,RGD); } }
+static void bic_ind_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+12; { BIC_M(IND,IN); } }
+static void bic_ind_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+18; { BIC_M(IND,IND); } }
+static void bic_ind_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+15; { BIC_M(IND,DE); } }
+static void bic_ind_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+21; { BIC_M(IND,DED); } }
+static void bic_ind_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+21; { BIC_M(IND,IX); } }
+static void bic_ind_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+27; { BIC_M(IND,IXD); } }
+static void bic_de_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+ 3; { BIC_X(DE,RG); } }
+static void bic_de_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+12; { BIC_M(DE,RGD); } }
+static void bic_de_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+12; { BIC_M(DE,IN); } }
+static void bic_de_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+18; { BIC_M(DE,IND); } }
+static void bic_de_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+15; { BIC_M(DE,DE); } }
+static void bic_de_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+21; { BIC_M(DE,DED); } }
+static void bic_de_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+21; { BIC_M(DE,IX); } }
+static void bic_de_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+27; { BIC_M(DE,IXD); } }
+static void bic_ded_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 3; { BIC_X(DED,RG); } }
+static void bic_ded_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { BIC_M(DED,RGD); } }
+static void bic_ded_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { BIC_M(DED,IN); } }
+static void bic_ded_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { BIC_M(DED,IND); } }
+static void bic_ded_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+15; { BIC_M(DED,DE); } }
+static void bic_ded_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { BIC_M(DED,DED); } }
+static void bic_ded_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { BIC_M(DED,IX); } }
+static void bic_ded_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+27; { BIC_M(DED,IXD); } }
+static void bic_ix_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 3; { BIC_X(IX,RG); } }
+static void bic_ix_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { BIC_M(IX,RGD); } }
+static void bic_ix_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { BIC_M(IX,IN); } }
+static void bic_ix_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { BIC_M(IX,IND); } }
+static void bic_ix_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+15; { BIC_M(IX,DE); } }
+static void bic_ix_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { BIC_M(IX,DED); } }
+static void bic_ix_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { BIC_M(IX,IX); } }
+static void bic_ix_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+27; { BIC_M(IX,IXD); } }
+static void bic_ixd_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+ 3; { BIC_X(IXD,RG); } }
+static void bic_ixd_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+12; { BIC_M(IXD,RGD); } }
+static void bic_ixd_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+12; { BIC_M(IXD,IN); } }
+static void bic_ixd_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+18; { BIC_M(IXD,IND); } }
+static void bic_ixd_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+15; { BIC_M(IXD,DE); } }
+static void bic_ixd_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+21; { BIC_M(IXD,DED); } }
+static void bic_ixd_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+21; { BIC_M(IXD,IX); } }
+static void bic_ixd_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+27; { BIC_M(IXD,IXD); } }
+
+static void bis_rg_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+ 3; { BIS_R(RG,RG); } }
+static void bis_rg_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+12; { BIS_M(RG,RGD); } }
+static void bis_rg_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+12; { BIS_M(RG,IN); } }
+static void bis_rg_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+18; { BIS_M(RG,IND); } }
+static void bis_rg_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+15; { BIS_M(RG,DE); } }
+static void bis_rg_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+21; { BIS_M(RG,DED); } }
+static void bis_rg_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+21; { BIS_M(RG,IX); } }
+static void bis_rg_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+27; { BIS_M(RG,IXD); } }
+static void bis_rgd_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 3; { BIS_X(RGD,RG); } }
+static void bis_rgd_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { BIS_M(RGD,RGD); } }
+static void bis_rgd_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { BIS_M(RGD,IN); } }
+static void bis_rgd_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { BIS_M(RGD,IND); } }
+static void bis_rgd_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+15; { BIS_M(RGD,DE); } }
+static void bis_rgd_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { BIS_M(RGD,DED); } }
+static void bis_rgd_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { BIS_M(RGD,IX); } }
+static void bis_rgd_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+27; { BIS_M(RGD,IXD); } }
+static void bis_in_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 3; { BIS_X(IN,RG); } }
+static void bis_in_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { BIS_M(IN,RGD); } }
+static void bis_in_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { BIS_M(IN,IN); } }
+static void bis_in_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { BIS_M(IN,IND); } }
+static void bis_in_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+15; { BIS_M(IN,DE); } }
+static void bis_in_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { BIS_M(IN,DED); } }
+static void bis_in_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { BIS_M(IN,IX); } }
+static void bis_in_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+27; { BIS_M(IN,IXD); } }
+static void bis_ind_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+ 3; { BIS_X(IND,RG); } }
+static void bis_ind_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+12; { BIS_M(IND,RGD); } }
+static void bis_ind_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+12; { BIS_M(IND,IN); } }
+static void bis_ind_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+18; { BIS_M(IND,IND); } }
+static void bis_ind_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+15; { BIS_M(IND,DE); } }
+static void bis_ind_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+21; { BIS_M(IND,DED); } }
+static void bis_ind_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+21; { BIS_M(IND,IX); } }
+static void bis_ind_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+27; { BIS_M(IND,IXD); } }
+static void bis_de_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+ 3; { BIS_X(DE,RG); } }
+static void bis_de_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+12; { BIS_M(DE,RGD); } }
+static void bis_de_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+12; { BIS_M(DE,IN); } }
+static void bis_de_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+18; { BIS_M(DE,IND); } }
+static void bis_de_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+15; { BIS_M(DE,DE); } }
+static void bis_de_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+21; { BIS_M(DE,DED); } }
+static void bis_de_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+21; { BIS_M(DE,IX); } }
+static void bis_de_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+27; { BIS_M(DE,IXD); } }
+static void bis_ded_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 3; { BIS_X(DED,RG); } }
+static void bis_ded_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { BIS_M(DED,RGD); } }
+static void bis_ded_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { BIS_M(DED,IN); } }
+static void bis_ded_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { BIS_M(DED,IND); } }
+static void bis_ded_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+15; { BIS_M(DED,DE); } }
+static void bis_ded_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { BIS_M(DED,DED); } }
+static void bis_ded_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { BIS_M(DED,IX); } }
+static void bis_ded_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+27; { BIS_M(DED,IXD); } }
+static void bis_ix_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 3; { BIS_X(IX,RG); } }
+static void bis_ix_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { BIS_M(IX,RGD); } }
+static void bis_ix_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { BIS_M(IX,IN); } }
+static void bis_ix_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { BIS_M(IX,IND); } }
+static void bis_ix_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+15; { BIS_M(IX,DE); } }
+static void bis_ix_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { BIS_M(IX,DED); } }
+static void bis_ix_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { BIS_M(IX,IX); } }
+static void bis_ix_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+27; { BIS_M(IX,IXD); } }
+static void bis_ixd_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+ 3; { BIS_X(IXD,RG); } }
+static void bis_ixd_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+12; { BIS_M(IXD,RGD); } }
+static void bis_ixd_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+12; { BIS_M(IXD,IN); } }
+static void bis_ixd_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+18; { BIS_M(IXD,IND); } }
+static void bis_ixd_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+15; { BIS_M(IXD,DE); } }
+static void bis_ixd_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+21; { BIS_M(IXD,DED); } }
+static void bis_ixd_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+21; { BIS_M(IXD,IX); } }
+static void bis_ixd_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+27; { BIS_M(IXD,IXD); } }
+
+static void add_rg_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+ 3; { ADD_R(RG,RG); } }
+static void add_rg_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+12; { ADD_M(RG,RGD); } }
+static void add_rg_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+12; { ADD_M(RG,IN); } }
+static void add_rg_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+18; { ADD_M(RG,IND); } }
+static void add_rg_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+15; { ADD_M(RG,DE); } }
+static void add_rg_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+21; { ADD_M(RG,DED); } }
+static void add_rg_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+21; { ADD_M(RG,IX); } }
+static void add_rg_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+27; { ADD_M(RG,IXD); } }
+static void add_rgd_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 3; { ADD_X(RGD,RG); } }
+static void add_rgd_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { ADD_M(RGD,RGD); } }
+static void add_rgd_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { ADD_M(RGD,IN); } }
+static void add_rgd_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { ADD_M(RGD,IND); } }
+static void add_rgd_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+15; { ADD_M(RGD,DE); } }
+static void add_rgd_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { ADD_M(RGD,DED); } }
+static void add_rgd_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { ADD_M(RGD,IX); } }
+static void add_rgd_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+27; { ADD_M(RGD,IXD); } }
+static void add_in_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 3; { ADD_X(IN,RG); } }
+static void add_in_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { ADD_M(IN,RGD); } }
+static void add_in_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { ADD_M(IN,IN); } }
+static void add_in_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { ADD_M(IN,IND); } }
+static void add_in_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+15; { ADD_M(IN,DE); } }
+static void add_in_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { ADD_M(IN,DED); } }
+static void add_in_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { ADD_M(IN,IX); } }
+static void add_in_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+27; { ADD_M(IN,IXD); } }
+static void add_ind_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+ 3; { ADD_X(IND,RG); } }
+static void add_ind_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+12; { ADD_M(IND,RGD); } }
+static void add_ind_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+12; { ADD_M(IND,IN); } }
+static void add_ind_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+18; { ADD_M(IND,IND); } }
+static void add_ind_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+15; { ADD_M(IND,DE); } }
+static void add_ind_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+21; { ADD_M(IND,DED); } }
+static void add_ind_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+21; { ADD_M(IND,IX); } }
+static void add_ind_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+27; { ADD_M(IND,IXD); } }
+static void add_de_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+ 3; { ADD_X(DE,RG); } }
+static void add_de_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+12; { ADD_M(DE,RGD); } }
+static void add_de_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+12; { ADD_M(DE,IN); } }
+static void add_de_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+18; { ADD_M(DE,IND); } }
+static void add_de_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+15; { ADD_M(DE,DE); } }
+static void add_de_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+21; { ADD_M(DE,DED); } }
+static void add_de_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+21; { ADD_M(DE,IX); } }
+static void add_de_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+27; { ADD_M(DE,IXD); } }
+static void add_ded_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 3; { ADD_X(DED,RG); } }
+static void add_ded_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { ADD_M(DED,RGD); } }
+static void add_ded_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { ADD_M(DED,IN); } }
+static void add_ded_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { ADD_M(DED,IND); } }
+static void add_ded_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+15; { ADD_M(DED,DE); } }
+static void add_ded_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { ADD_M(DED,DED); } }
+static void add_ded_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { ADD_M(DED,IX); } }
+static void add_ded_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+27; { ADD_M(DED,IXD); } }
+static void add_ix_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 3; { ADD_X(IX,RG); } }
+static void add_ix_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { ADD_M(IX,RGD); } }
+static void add_ix_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { ADD_M(IX,IN); } }
+static void add_ix_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { ADD_M(IX,IND); } }
+static void add_ix_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+15; { ADD_M(IX,DE); } }
+static void add_ix_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { ADD_M(IX,DED); } }
+static void add_ix_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { ADD_M(IX,IX); } }
+static void add_ix_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+27; { ADD_M(IX,IXD); } }
+static void add_ixd_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+ 3; { ADD_X(IXD,RG); } }
+static void add_ixd_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+12; { ADD_M(IXD,RGD); } }
+static void add_ixd_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+12; { ADD_M(IXD,IN); } }
+static void add_ixd_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+18; { ADD_M(IXD,IND); } }
+static void add_ixd_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+15; { ADD_M(IXD,DE); } }
+static void add_ixd_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+21; { ADD_M(IXD,DED); } }
+static void add_ixd_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+21; { ADD_M(IXD,IX); } }
+static void add_ixd_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+27; { ADD_M(IXD,IXD); } }
+
+static void xor_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { XOR_R(RG); } }
+static void xor_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { XOR_M(RGD); } }
+static void xor_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { XOR_M(IN); } }
+static void xor_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { XOR_M(IND); } }
+static void xor_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { XOR_M(DE); } }
+static void xor_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { XOR_M(DED); } }
+static void xor_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { XOR_M(IX); } }
+static void xor_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { XOR_M(IXD); } }
+
+static void sob(t11_state *cpustate, UINT16 op)
+{
+ int sreg, source;
+
+ cpustate->icount -= 18;
+ GET_SREG; source = cpustate->REGD(sreg);
+ source -= 1;
+ cpustate->REGW(sreg) = source;
+ if (source)
+ cpustate->PC -= 2 * (op & 0x3f);
+}
+
+static void bpl(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { BR(!GET_N); } }
+static void bmi(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { BR( GET_N); } }
+static void bhi(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { BR(!GET_C && !GET_Z); } }
+static void blos(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { BR( GET_C || GET_Z); } }
+static void bvc(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { BR(!GET_V); } }
+static void bvs(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { BR( GET_V); } }
+static void bcc(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { BR(!GET_C); } }
+static void bcs(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { BR( GET_C); } }
+
+static void emt(t11_state *cpustate, UINT16 op)
+{
+ cpustate->icount -= 48;
+ PUSH(cpustate, cpustate->PSW);
+ PUSH(cpustate, cpustate->PC);
+ cpustate->PC = RWORD(cpustate, 0x18);
+ cpustate->PSW = RWORD(cpustate, 0x1a);
+ t11_check_irqs(cpustate);
+}
+
+static void trap(t11_state *cpustate, UINT16 op)
+{
+ cpustate->icount -= 48;
+ PUSH(cpustate, cpustate->PSW);
+ PUSH(cpustate, cpustate->PC);
+ cpustate->PC = RWORD(cpustate, 0x1c);
+ cpustate->PSW = RWORD(cpustate, 0x1e);
+ t11_check_irqs(cpustate);
+}
+
+static void clrb_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { CLRB_R(RG); } }
+static void clrb_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { CLRB_M(RGD); } }
+static void clrb_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { CLRB_M(IN); } }
+static void clrb_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { CLRB_M(IND); } }
+static void clrb_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { CLRB_M(DE); } }
+static void clrb_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { CLRB_M(DED); } }
+static void clrb_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { CLRB_M(IX); } }
+static void clrb_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { CLRB_M(IXD); } }
+
+static void comb_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { COMB_R(RG); } }
+static void comb_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { COMB_M(RGD); } }
+static void comb_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { COMB_M(IN); } }
+static void comb_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { COMB_M(IND); } }
+static void comb_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { COMB_M(DE); } }
+static void comb_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { COMB_M(DED); } }
+static void comb_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { COMB_M(IX); } }
+static void comb_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { COMB_M(IXD); } }
+
+static void incb_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { INCB_R(RG); } }
+static void incb_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { INCB_M(RGD); } }
+static void incb_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { INCB_M(IN); } }
+static void incb_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { INCB_M(IND); } }
+static void incb_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { INCB_M(DE); } }
+static void incb_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { INCB_M(DED); } }
+static void incb_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { INCB_M(IX); } }
+static void incb_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { INCB_M(IXD); } }
+
+static void decb_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { DECB_R(RG); } }
+static void decb_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { DECB_M(RGD); } }
+static void decb_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { DECB_M(IN); } }
+static void decb_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { DECB_M(IND); } }
+static void decb_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { DECB_M(DE); } }
+static void decb_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { DECB_M(DED); } }
+static void decb_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { DECB_M(IX); } }
+static void decb_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { DECB_M(IXD); } }
+
+static void negb_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { NEGB_R(RG); } }
+static void negb_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { NEGB_M(RGD); } }
+static void negb_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { NEGB_M(IN); } }
+static void negb_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { NEGB_M(IND); } }
+static void negb_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { NEGB_M(DE); } }
+static void negb_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { NEGB_M(DED); } }
+static void negb_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { NEGB_M(IX); } }
+static void negb_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { NEGB_M(IXD); } }
+
+static void adcb_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { ADCB_R(RG); } }
+static void adcb_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { ADCB_M(RGD); } }
+static void adcb_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { ADCB_M(IN); } }
+static void adcb_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { ADCB_M(IND); } }
+static void adcb_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { ADCB_M(DE); } }
+static void adcb_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { ADCB_M(DED); } }
+static void adcb_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { ADCB_M(IX); } }
+static void adcb_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { ADCB_M(IXD); } }
+
+static void sbcb_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { SBCB_R(RG); } }
+static void sbcb_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { SBCB_M(RGD); } }
+static void sbcb_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { SBCB_M(IN); } }
+static void sbcb_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { SBCB_M(IND); } }
+static void sbcb_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { SBCB_M(DE); } }
+static void sbcb_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { SBCB_M(DED); } }
+static void sbcb_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { SBCB_M(IX); } }
+static void sbcb_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { SBCB_M(IXD); } }
+
+static void tstb_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { TSTB_R(RG); } }
+static void tstb_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18; { TSTB_M(RGD); } }
+static void tstb_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18; { TSTB_M(IN); } }
+static void tstb_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { TSTB_M(IND); } }
+static void tstb_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { TSTB_M(DE); } }
+static void tstb_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { TSTB_M(DED); } }
+static void tstb_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { TSTB_M(IX); } }
+static void tstb_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 33; { TSTB_M(IXD); } }
+
+static void rorb_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { RORB_R(RG); } }
+static void rorb_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { RORB_M(RGD); } }
+static void rorb_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { RORB_M(IN); } }
+static void rorb_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { RORB_M(IND); } }
+static void rorb_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { RORB_M(DE); } }
+static void rorb_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { RORB_M(DED); } }
+static void rorb_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { RORB_M(IX); } }
+static void rorb_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { RORB_M(IXD); } }
+
+static void rolb_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { ROLB_R(RG); } }
+static void rolb_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { ROLB_M(RGD); } }
+static void rolb_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { ROLB_M(IN); } }
+static void rolb_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { ROLB_M(IND); } }
+static void rolb_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { ROLB_M(DE); } }
+static void rolb_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { ROLB_M(DED); } }
+static void rolb_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { ROLB_M(IX); } }
+static void rolb_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { ROLB_M(IXD); } }
+
+static void asrb_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { ASRB_R(RG); } }
+static void asrb_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { ASRB_M(RGD); } }
+static void asrb_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { ASRB_M(IN); } }
+static void asrb_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { ASRB_M(IND); } }
+static void asrb_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { ASRB_M(DE); } }
+static void asrb_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { ASRB_M(DED); } }
+static void asrb_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { ASRB_M(IX); } }
+static void asrb_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { ASRB_M(IXD); } }
+
+static void aslb_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { ASLB_R(RG); } }
+static void aslb_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { ASLB_M(RGD); } }
+static void aslb_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { ASLB_M(IN); } }
+static void aslb_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { ASLB_M(IND); } }
+static void aslb_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { ASLB_M(DE); } }
+static void aslb_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { ASLB_M(DED); } }
+static void aslb_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { ASLB_M(IX); } }
+static void aslb_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { ASLB_M(IXD); } }
+
+static void mtps_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { MTPS_R(RG); } }
+static void mtps_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { MTPS_M(RGD); } }
+static void mtps_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { MTPS_M(IN); } }
+static void mtps_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { MTPS_M(IND); } }
+static void mtps_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 33; { MTPS_M(DE); } }
+static void mtps_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 39; { MTPS_M(DED); } }
+static void mtps_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 39; { MTPS_M(IX); } }
+static void mtps_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 45; { MTPS_M(IXD); } }
+
+static void mfps_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 12; { MFPS_R(RG); } }
+static void mfps_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { MFPS_M(RGD); } }
+static void mfps_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21; { MFPS_M(IN); } }
+static void mfps_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 27; { MFPS_M(IND); } }
+static void mfps_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24; { MFPS_M(DE); } }
+static void mfps_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { MFPS_M(DED); } }
+static void mfps_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30; { MFPS_M(IX); } }
+static void mfps_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 36; { MFPS_M(IXD); } }
+
+static void movb_rg_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+ 3; { MOVB_R(RG,RG); } }
+static void movb_rg_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+12; { MOVB_M(RG,RGD); } }
+static void movb_rg_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+12; { MOVB_M(RG,IN); } }
+static void movb_rg_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+18; { MOVB_M(RG,IND); } }
+static void movb_rg_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+15; { MOVB_M(RG,DE); } }
+static void movb_rg_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+21; { MOVB_M(RG,DED); } }
+static void movb_rg_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+21; { MOVB_M(RG,IX); } }
+static void movb_rg_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+27; { MOVB_M(RG,IXD); } }
+static void movb_rgd_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 3; { MOVB_X(RGD,RG); } }
+static void movb_rgd_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { MOVB_M(RGD,RGD); } }
+static void movb_rgd_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { MOVB_M(RGD,IN); } }
+static void movb_rgd_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { MOVB_M(RGD,IND); } }
+static void movb_rgd_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+15; { MOVB_M(RGD,DE); } }
+static void movb_rgd_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { MOVB_M(RGD,DED); } }
+static void movb_rgd_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { MOVB_M(RGD,IX); } }
+static void movb_rgd_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+27; { MOVB_M(RGD,IXD); } }
+static void movb_in_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 3; { MOVB_X(IN,RG); } }
+static void movb_in_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { MOVB_M(IN,RGD); } }
+static void movb_in_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { MOVB_M(IN,IN); } }
+static void movb_in_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { MOVB_M(IN,IND); } }
+static void movb_in_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+15; { MOVB_M(IN,DE); } }
+static void movb_in_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { MOVB_M(IN,DED); } }
+static void movb_in_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { MOVB_M(IN,IX); } }
+static void movb_in_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+27; { MOVB_M(IN,IXD); } }
+static void movb_ind_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+ 3; { MOVB_X(IND,RG); } }
+static void movb_ind_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+12; { MOVB_M(IND,RGD); } }
+static void movb_ind_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+12; { MOVB_M(IND,IN); } }
+static void movb_ind_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+18; { MOVB_M(IND,IND); } }
+static void movb_ind_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+15; { MOVB_M(IND,DE); } }
+static void movb_ind_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+21; { MOVB_M(IND,DED); } }
+static void movb_ind_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+21; { MOVB_M(IND,IX); } }
+static void movb_ind_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+27; { MOVB_M(IND,IXD); } }
+static void movb_de_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+ 3; { MOVB_X(DE,RG); } }
+static void movb_de_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+12; { MOVB_M(DE,RGD); } }
+static void movb_de_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+12; { MOVB_M(DE,IN); } }
+static void movb_de_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+18; { MOVB_M(DE,IND); } }
+static void movb_de_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+15; { MOVB_M(DE,DE); } }
+static void movb_de_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+21; { MOVB_M(DE,DED); } }
+static void movb_de_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+21; { MOVB_M(DE,IX); } }
+static void movb_de_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+27; { MOVB_M(DE,IXD); } }
+static void movb_ded_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 3; { MOVB_X(DED,RG); } }
+static void movb_ded_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { MOVB_M(DED,RGD); } }
+static void movb_ded_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { MOVB_M(DED,IN); } }
+static void movb_ded_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { MOVB_M(DED,IND); } }
+static void movb_ded_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+15; { MOVB_M(DED,DE); } }
+static void movb_ded_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { MOVB_M(DED,DED); } }
+static void movb_ded_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { MOVB_M(DED,IX); } }
+static void movb_ded_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+27; { MOVB_M(DED,IXD); } }
+static void movb_ix_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 3; { MOVB_X(IX,RG); } }
+static void movb_ix_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { MOVB_M(IX,RGD); } }
+static void movb_ix_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { MOVB_M(IX,IN); } }
+static void movb_ix_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { MOVB_M(IX,IND); } }
+static void movb_ix_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+15; { MOVB_M(IX,DE); } }
+static void movb_ix_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { MOVB_M(IX,DED); } }
+static void movb_ix_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { MOVB_M(IX,IX); } }
+static void movb_ix_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+27; { MOVB_M(IX,IXD); } }
+static void movb_ixd_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+ 3; { MOVB_X(IXD,RG); } }
+static void movb_ixd_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+12; { MOVB_M(IXD,RGD); } }
+static void movb_ixd_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+12; { MOVB_M(IXD,IN); } }
+static void movb_ixd_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+18; { MOVB_M(IXD,IND); } }
+static void movb_ixd_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+15; { MOVB_M(IXD,DE); } }
+static void movb_ixd_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+21; { MOVB_M(IXD,DED); } }
+static void movb_ixd_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+21; { MOVB_M(IXD,IX); } }
+static void movb_ixd_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+27; { MOVB_M(IXD,IXD); } }
+
+static void cmpb_rg_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+ 3; { CMPB_R(RG,RG); } }
+static void cmpb_rg_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+ 9; { CMPB_M(RG,RGD); } }
+static void cmpb_rg_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+ 9; { CMPB_M(RG,IN); } }
+static void cmpb_rg_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+15; { CMPB_M(RG,IND); } }
+static void cmpb_rg_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+12; { CMPB_M(RG,DE); } }
+static void cmpb_rg_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+18; { CMPB_M(RG,DED); } }
+static void cmpb_rg_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+18; { CMPB_M(RG,IX); } }
+static void cmpb_rg_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+24; { CMPB_M(RG,IXD); } }
+static void cmpb_rgd_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 3; { CMPB_M(RGD,RG); } }
+static void cmpb_rgd_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 9; { CMPB_M(RGD,RGD); } }
+static void cmpb_rgd_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 9; { CMPB_M(RGD,IN); } }
+static void cmpb_rgd_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+15; { CMPB_M(RGD,IND); } }
+static void cmpb_rgd_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { CMPB_M(RGD,DE); } }
+static void cmpb_rgd_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { CMPB_M(RGD,DED); } }
+static void cmpb_rgd_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { CMPB_M(RGD,IX); } }
+static void cmpb_rgd_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+24; { CMPB_M(RGD,IXD); } }
+static void cmpb_in_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 3; { CMPB_M(IN,RG); } }
+static void cmpb_in_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 9; { CMPB_M(IN,RGD); } }
+static void cmpb_in_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 9; { CMPB_M(IN,IN); } }
+static void cmpb_in_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+15; { CMPB_M(IN,IND); } }
+static void cmpb_in_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { CMPB_M(IN,DE); } }
+static void cmpb_in_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { CMPB_M(IN,DED); } }
+static void cmpb_in_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { CMPB_M(IN,IX); } }
+static void cmpb_in_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+24; { CMPB_M(IN,IXD); } }
+static void cmpb_ind_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+ 3; { CMPB_M(IND,RG); } }
+static void cmpb_ind_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+ 9; { CMPB_M(IND,RGD); } }
+static void cmpb_ind_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+ 9; { CMPB_M(IND,IN); } }
+static void cmpb_ind_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+15; { CMPB_M(IND,IND); } }
+static void cmpb_ind_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+12; { CMPB_M(IND,DE); } }
+static void cmpb_ind_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+18; { CMPB_M(IND,DED); } }
+static void cmpb_ind_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+18; { CMPB_M(IND,IX); } }
+static void cmpb_ind_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+24; { CMPB_M(IND,IXD); } }
+static void cmpb_de_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+ 3; { CMPB_M(DE,RG); } }
+static void cmpb_de_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+ 9; { CMPB_M(DE,RGD); } }
+static void cmpb_de_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+ 9; { CMPB_M(DE,IN); } }
+static void cmpb_de_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+15; { CMPB_M(DE,IND); } }
+static void cmpb_de_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+12; { CMPB_M(DE,DE); } }
+static void cmpb_de_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+18; { CMPB_M(DE,DED); } }
+static void cmpb_de_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+18; { CMPB_M(DE,IX); } }
+static void cmpb_de_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+24; { CMPB_M(DE,IXD); } }
+static void cmpb_ded_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 3; { CMPB_M(DED,RG); } }
+static void cmpb_ded_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 9; { CMPB_M(DED,RGD); } }
+static void cmpb_ded_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 9; { CMPB_M(DED,IN); } }
+static void cmpb_ded_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+15; { CMPB_M(DED,IND); } }
+static void cmpb_ded_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { CMPB_M(DED,DE); } }
+static void cmpb_ded_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { CMPB_M(DED,DED); } }
+static void cmpb_ded_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { CMPB_M(DED,IX); } }
+static void cmpb_ded_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+24; { CMPB_M(DED,IXD); } }
+static void cmpb_ix_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 3; { CMPB_M(IX,RG); } }
+static void cmpb_ix_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 9; { CMPB_M(IX,RGD); } }
+static void cmpb_ix_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 9; { CMPB_M(IX,IN); } }
+static void cmpb_ix_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+15; { CMPB_M(IX,IND); } }
+static void cmpb_ix_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { CMPB_M(IX,DE); } }
+static void cmpb_ix_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { CMPB_M(IX,DED); } }
+static void cmpb_ix_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { CMPB_M(IX,IX); } }
+static void cmpb_ix_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+24; { CMPB_M(IX,IXD); } }
+static void cmpb_ixd_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+ 3; { CMPB_M(IXD,RG); } }
+static void cmpb_ixd_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+ 9; { CMPB_M(IXD,RGD); } }
+static void cmpb_ixd_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+ 9; { CMPB_M(IXD,IN); } }
+static void cmpb_ixd_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+15; { CMPB_M(IXD,IND); } }
+static void cmpb_ixd_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+12; { CMPB_M(IXD,DE); } }
+static void cmpb_ixd_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+18; { CMPB_M(IXD,DED); } }
+static void cmpb_ixd_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+18; { CMPB_M(IXD,IX); } }
+static void cmpb_ixd_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+24; { CMPB_M(IXD,IXD); } }
+
+static void bitb_rg_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+ 3; { BITB_R(RG,RG); } }
+static void bitb_rg_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+ 9; { BITB_M(RG,RGD); } }
+static void bitb_rg_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+ 9; { BITB_M(RG,IN); } }
+static void bitb_rg_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+15; { BITB_M(RG,IND); } }
+static void bitb_rg_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+12; { BITB_M(RG,DE); } }
+static void bitb_rg_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+18; { BITB_M(RG,DED); } }
+static void bitb_rg_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+18; { BITB_M(RG,IX); } }
+static void bitb_rg_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+24; { BITB_M(RG,IXD); } }
+static void bitb_rgd_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 3; { BITB_M(RGD,RG); } }
+static void bitb_rgd_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 9; { BITB_M(RGD,RGD); } }
+static void bitb_rgd_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 9; { BITB_M(RGD,IN); } }
+static void bitb_rgd_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+15; { BITB_M(RGD,IND); } }
+static void bitb_rgd_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { BITB_M(RGD,DE); } }
+static void bitb_rgd_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { BITB_M(RGD,DED); } }
+static void bitb_rgd_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { BITB_M(RGD,IX); } }
+static void bitb_rgd_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+24; { BITB_M(RGD,IXD); } }
+static void bitb_in_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 3; { BITB_M(IN,RG); } }
+static void bitb_in_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 9; { BITB_M(IN,RGD); } }
+static void bitb_in_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 9; { BITB_M(IN,IN); } }
+static void bitb_in_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+15; { BITB_M(IN,IND); } }
+static void bitb_in_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { BITB_M(IN,DE); } }
+static void bitb_in_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { BITB_M(IN,DED); } }
+static void bitb_in_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { BITB_M(IN,IX); } }
+static void bitb_in_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+24; { BITB_M(IN,IXD); } }
+static void bitb_ind_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+ 3; { BITB_M(IND,RG); } }
+static void bitb_ind_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+ 9; { BITB_M(IND,RGD); } }
+static void bitb_ind_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+ 9; { BITB_M(IND,IN); } }
+static void bitb_ind_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+15; { BITB_M(IND,IND); } }
+static void bitb_ind_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+12; { BITB_M(IND,DE); } }
+static void bitb_ind_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+18; { BITB_M(IND,DED); } }
+static void bitb_ind_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+18; { BITB_M(IND,IX); } }
+static void bitb_ind_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+24; { BITB_M(IND,IXD); } }
+static void bitb_de_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+ 3; { BITB_M(DE,RG); } }
+static void bitb_de_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+ 9; { BITB_M(DE,RGD); } }
+static void bitb_de_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+ 9; { BITB_M(DE,IN); } }
+static void bitb_de_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+15; { BITB_M(DE,IND); } }
+static void bitb_de_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+12; { BITB_M(DE,DE); } }
+static void bitb_de_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+18; { BITB_M(DE,DED); } }
+static void bitb_de_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+18; { BITB_M(DE,IX); } }
+static void bitb_de_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+24; { BITB_M(DE,IXD); } }
+static void bitb_ded_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 3; { BITB_M(DED,RG); } }
+static void bitb_ded_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 9; { BITB_M(DED,RGD); } }
+static void bitb_ded_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 9; { BITB_M(DED,IN); } }
+static void bitb_ded_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+15; { BITB_M(DED,IND); } }
+static void bitb_ded_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { BITB_M(DED,DE); } }
+static void bitb_ded_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { BITB_M(DED,DED); } }
+static void bitb_ded_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { BITB_M(DED,IX); } }
+static void bitb_ded_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+24; { BITB_M(DED,IXD); } }
+static void bitb_ix_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 3; { BITB_M(IX,RG); } }
+static void bitb_ix_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 9; { BITB_M(IX,RGD); } }
+static void bitb_ix_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 9; { BITB_M(IX,IN); } }
+static void bitb_ix_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+15; { BITB_M(IX,IND); } }
+static void bitb_ix_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { BITB_M(IX,DE); } }
+static void bitb_ix_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { BITB_M(IX,DED); } }
+static void bitb_ix_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { BITB_M(IX,IX); } }
+static void bitb_ix_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+24; { BITB_M(IX,IXD); } }
+static void bitb_ixd_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+ 3; { BITB_M(IXD,RG); } }
+static void bitb_ixd_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+ 9; { BITB_M(IXD,RGD); } }
+static void bitb_ixd_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+ 9; { BITB_M(IXD,IN); } }
+static void bitb_ixd_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+15; { BITB_M(IXD,IND); } }
+static void bitb_ixd_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+12; { BITB_M(IXD,DE); } }
+static void bitb_ixd_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+18; { BITB_M(IXD,DED); } }
+static void bitb_ixd_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+18; { BITB_M(IXD,IX); } }
+static void bitb_ixd_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+24; { BITB_M(IXD,IXD); } }
+
+static void bicb_rg_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+ 3; { BICB_R(RG,RG); } }
+static void bicb_rg_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+12; { BICB_M(RG,RGD); } }
+static void bicb_rg_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+12; { BICB_M(RG,IN); } }
+static void bicb_rg_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+18; { BICB_M(RG,IND); } }
+static void bicb_rg_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+15; { BICB_M(RG,DE); } }
+static void bicb_rg_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+21; { BICB_M(RG,DED); } }
+static void bicb_rg_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+21; { BICB_M(RG,IX); } }
+static void bicb_rg_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+27; { BICB_M(RG,IXD); } }
+static void bicb_rgd_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 3; { BICB_X(RGD,RG); } }
+static void bicb_rgd_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { BICB_M(RGD,RGD); } }
+static void bicb_rgd_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { BICB_M(RGD,IN); } }
+static void bicb_rgd_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { BICB_M(RGD,IND); } }
+static void bicb_rgd_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+15; { BICB_M(RGD,DE); } }
+static void bicb_rgd_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { BICB_M(RGD,DED); } }
+static void bicb_rgd_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { BICB_M(RGD,IX); } }
+static void bicb_rgd_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+27; { BICB_M(RGD,IXD); } }
+static void bicb_in_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 3; { BICB_X(IN,RG); } }
+static void bicb_in_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { BICB_M(IN,RGD); } }
+static void bicb_in_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { BICB_M(IN,IN); } }
+static void bicb_in_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { BICB_M(IN,IND); } }
+static void bicb_in_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+15; { BICB_M(IN,DE); } }
+static void bicb_in_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { BICB_M(IN,DED); } }
+static void bicb_in_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { BICB_M(IN,IX); } }
+static void bicb_in_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+27; { BICB_M(IN,IXD); } }
+static void bicb_ind_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+ 3; { BICB_X(IND,RG); } }
+static void bicb_ind_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+12; { BICB_M(IND,RGD); } }
+static void bicb_ind_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+12; { BICB_M(IND,IN); } }
+static void bicb_ind_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+18; { BICB_M(IND,IND); } }
+static void bicb_ind_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+15; { BICB_M(IND,DE); } }
+static void bicb_ind_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+21; { BICB_M(IND,DED); } }
+static void bicb_ind_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+21; { BICB_M(IND,IX); } }
+static void bicb_ind_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+27; { BICB_M(IND,IXD); } }
+static void bicb_de_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+ 3; { BICB_X(DE,RG); } }
+static void bicb_de_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+12; { BICB_M(DE,RGD); } }
+static void bicb_de_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+12; { BICB_M(DE,IN); } }
+static void bicb_de_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+18; { BICB_M(DE,IND); } }
+static void bicb_de_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+15; { BICB_M(DE,DE); } }
+static void bicb_de_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+21; { BICB_M(DE,DED); } }
+static void bicb_de_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+21; { BICB_M(DE,IX); } }
+static void bicb_de_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+27; { BICB_M(DE,IXD); } }
+static void bicb_ded_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 3; { BICB_X(DED,RG); } }
+static void bicb_ded_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { BICB_M(DED,RGD); } }
+static void bicb_ded_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { BICB_M(DED,IN); } }
+static void bicb_ded_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { BICB_M(DED,IND); } }
+static void bicb_ded_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+15; { BICB_M(DED,DE); } }
+static void bicb_ded_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { BICB_M(DED,DED); } }
+static void bicb_ded_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { BICB_M(DED,IX); } }
+static void bicb_ded_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+27; { BICB_M(DED,IXD); } }
+static void bicb_ix_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 3; { BICB_X(IX,RG); } }
+static void bicb_ix_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { BICB_M(IX,RGD); } }
+static void bicb_ix_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { BICB_M(IX,IN); } }
+static void bicb_ix_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { BICB_M(IX,IND); } }
+static void bicb_ix_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+15; { BICB_M(IX,DE); } }
+static void bicb_ix_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { BICB_M(IX,DED); } }
+static void bicb_ix_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { BICB_M(IX,IX); } }
+static void bicb_ix_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+27; { BICB_M(IX,IXD); } }
+static void bicb_ixd_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+ 3; { BICB_X(IXD,RG); } }
+static void bicb_ixd_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+12; { BICB_M(IXD,RGD); } }
+static void bicb_ixd_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+12; { BICB_M(IXD,IN); } }
+static void bicb_ixd_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+18; { BICB_M(IXD,IND); } }
+static void bicb_ixd_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+15; { BICB_M(IXD,DE); } }
+static void bicb_ixd_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+21; { BICB_M(IXD,DED); } }
+static void bicb_ixd_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+21; { BICB_M(IXD,IX); } }
+static void bicb_ixd_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+27; { BICB_M(IXD,IXD); } }
+
+static void bisb_rg_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+ 3; { BISB_R(RG,RG); } }
+static void bisb_rg_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+12; { BISB_M(RG,RGD); } }
+static void bisb_rg_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+12; { BISB_M(RG,IN); } }
+static void bisb_rg_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+18; { BISB_M(RG,IND); } }
+static void bisb_rg_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+15; { BISB_M(RG,DE); } }
+static void bisb_rg_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+21; { BISB_M(RG,DED); } }
+static void bisb_rg_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+21; { BISB_M(RG,IX); } }
+static void bisb_rg_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+27; { BISB_M(RG,IXD); } }
+static void bisb_rgd_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 3; { BISB_X(RGD,RG); } }
+static void bisb_rgd_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { BISB_M(RGD,RGD); } }
+static void bisb_rgd_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { BISB_M(RGD,IN); } }
+static void bisb_rgd_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { BISB_M(RGD,IND); } }
+static void bisb_rgd_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+15; { BISB_M(RGD,DE); } }
+static void bisb_rgd_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { BISB_M(RGD,DED); } }
+static void bisb_rgd_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { BISB_M(RGD,IX); } }
+static void bisb_rgd_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+27; { BISB_M(RGD,IXD); } }
+static void bisb_in_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 3; { BISB_X(IN,RG); } }
+static void bisb_in_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { BISB_M(IN,RGD); } }
+static void bisb_in_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { BISB_M(IN,IN); } }
+static void bisb_in_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { BISB_M(IN,IND); } }
+static void bisb_in_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+15; { BISB_M(IN,DE); } }
+static void bisb_in_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { BISB_M(IN,DED); } }
+static void bisb_in_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { BISB_M(IN,IX); } }
+static void bisb_in_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+27; { BISB_M(IN,IXD); } }
+static void bisb_ind_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+ 3; { BISB_X(IND,RG); } }
+static void bisb_ind_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+12; { BISB_M(IND,RGD); } }
+static void bisb_ind_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+12; { BISB_M(IND,IN); } }
+static void bisb_ind_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+18; { BISB_M(IND,IND); } }
+static void bisb_ind_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+15; { BISB_M(IND,DE); } }
+static void bisb_ind_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+21; { BISB_M(IND,DED); } }
+static void bisb_ind_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+21; { BISB_M(IND,IX); } }
+static void bisb_ind_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+27; { BISB_M(IND,IXD); } }
+static void bisb_de_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+ 3; { BISB_X(DE,RG); } }
+static void bisb_de_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+12; { BISB_M(DE,RGD); } }
+static void bisb_de_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+12; { BISB_M(DE,IN); } }
+static void bisb_de_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+18; { BISB_M(DE,IND); } }
+static void bisb_de_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+15; { BISB_M(DE,DE); } }
+static void bisb_de_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+21; { BISB_M(DE,DED); } }
+static void bisb_de_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+21; { BISB_M(DE,IX); } }
+static void bisb_de_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+27; { BISB_M(DE,IXD); } }
+static void bisb_ded_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 3; { BISB_X(DED,RG); } }
+static void bisb_ded_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { BISB_M(DED,RGD); } }
+static void bisb_ded_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { BISB_M(DED,IN); } }
+static void bisb_ded_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { BISB_M(DED,IND); } }
+static void bisb_ded_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+15; { BISB_M(DED,DE); } }
+static void bisb_ded_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { BISB_M(DED,DED); } }
+static void bisb_ded_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { BISB_M(DED,IX); } }
+static void bisb_ded_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+27; { BISB_M(DED,IXD); } }
+static void bisb_ix_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 3; { BISB_X(IX,RG); } }
+static void bisb_ix_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { BISB_M(IX,RGD); } }
+static void bisb_ix_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { BISB_M(IX,IN); } }
+static void bisb_ix_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { BISB_M(IX,IND); } }
+static void bisb_ix_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+15; { BISB_M(IX,DE); } }
+static void bisb_ix_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { BISB_M(IX,DED); } }
+static void bisb_ix_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { BISB_M(IX,IX); } }
+static void bisb_ix_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+27; { BISB_M(IX,IXD); } }
+static void bisb_ixd_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+ 3; { BISB_X(IXD,RG); } }
+static void bisb_ixd_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+12; { BISB_M(IXD,RGD); } }
+static void bisb_ixd_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+12; { BISB_M(IXD,IN); } }
+static void bisb_ixd_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+18; { BISB_M(IXD,IND); } }
+static void bisb_ixd_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+15; { BISB_M(IXD,DE); } }
+static void bisb_ixd_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+21; { BISB_M(IXD,DED); } }
+static void bisb_ixd_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+21; { BISB_M(IXD,IX); } }
+static void bisb_ixd_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+27; { BISB_M(IXD,IXD); } }
+
+static void sub_rg_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+ 3; { SUB_R(RG,RG); } }
+static void sub_rg_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+12; { SUB_M(RG,RGD); } }
+static void sub_rg_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+12; { SUB_M(RG,IN); } }
+static void sub_rg_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+18; { SUB_M(RG,IND); } }
+static void sub_rg_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+15; { SUB_M(RG,DE); } }
+static void sub_rg_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+21; { SUB_M(RG,DED); } }
+static void sub_rg_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+21; { SUB_M(RG,IX); } }
+static void sub_rg_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 9+27; { SUB_M(RG,IXD); } }
+static void sub_rgd_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 3; { SUB_X(RGD,RG); } }
+static void sub_rgd_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { SUB_M(RGD,RGD); } }
+static void sub_rgd_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { SUB_M(RGD,IN); } }
+static void sub_rgd_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { SUB_M(RGD,IND); } }
+static void sub_rgd_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+15; { SUB_M(RGD,DE); } }
+static void sub_rgd_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { SUB_M(RGD,DED); } }
+static void sub_rgd_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { SUB_M(RGD,IX); } }
+static void sub_rgd_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+27; { SUB_M(RGD,IXD); } }
+static void sub_in_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+ 3; { SUB_X(IN,RG); } }
+static void sub_in_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { SUB_M(IN,RGD); } }
+static void sub_in_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+12; { SUB_M(IN,IN); } }
+static void sub_in_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+18; { SUB_M(IN,IND); } }
+static void sub_in_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+15; { SUB_M(IN,DE); } }
+static void sub_in_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { SUB_M(IN,DED); } }
+static void sub_in_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+21; { SUB_M(IN,IX); } }
+static void sub_in_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 15+27; { SUB_M(IN,IXD); } }
+static void sub_ind_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+ 3; { SUB_X(IND,RG); } }
+static void sub_ind_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+12; { SUB_M(IND,RGD); } }
+static void sub_ind_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+12; { SUB_M(IND,IN); } }
+static void sub_ind_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+18; { SUB_M(IND,IND); } }
+static void sub_ind_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+15; { SUB_M(IND,DE); } }
+static void sub_ind_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+21; { SUB_M(IND,DED); } }
+static void sub_ind_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+21; { SUB_M(IND,IX); } }
+static void sub_ind_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 21+27; { SUB_M(IND,IXD); } }
+static void sub_de_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+ 3; { SUB_X(DE,RG); } }
+static void sub_de_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+12; { SUB_M(DE,RGD); } }
+static void sub_de_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+12; { SUB_M(DE,IN); } }
+static void sub_de_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+18; { SUB_M(DE,IND); } }
+static void sub_de_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+15; { SUB_M(DE,DE); } }
+static void sub_de_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+21; { SUB_M(DE,DED); } }
+static void sub_de_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+21; { SUB_M(DE,IX); } }
+static void sub_de_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 18+27; { SUB_M(DE,IXD); } }
+static void sub_ded_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 3; { SUB_X(DED,RG); } }
+static void sub_ded_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { SUB_M(DED,RGD); } }
+static void sub_ded_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { SUB_M(DED,IN); } }
+static void sub_ded_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { SUB_M(DED,IND); } }
+static void sub_ded_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+15; { SUB_M(DED,DE); } }
+static void sub_ded_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { SUB_M(DED,DED); } }
+static void sub_ded_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { SUB_M(DED,IX); } }
+static void sub_ded_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+27; { SUB_M(DED,IXD); } }
+static void sub_ix_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+ 3; { SUB_X(IX,RG); } }
+static void sub_ix_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { SUB_M(IX,RGD); } }
+static void sub_ix_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+12; { SUB_M(IX,IN); } }
+static void sub_ix_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+18; { SUB_M(IX,IND); } }
+static void sub_ix_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+15; { SUB_M(IX,DE); } }
+static void sub_ix_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { SUB_M(IX,DED); } }
+static void sub_ix_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+21; { SUB_M(IX,IX); } }
+static void sub_ix_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 24+27; { SUB_M(IX,IXD); } }
+static void sub_ixd_rg(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+ 3; { SUB_X(IXD,RG); } }
+static void sub_ixd_rgd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+12; { SUB_M(IXD,RGD); } }
+static void sub_ixd_in(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+12; { SUB_M(IXD,IN); } }
+static void sub_ixd_ind(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+18; { SUB_M(IXD,IND); } }
+static void sub_ixd_de(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+15; { SUB_M(IXD,DE); } }
+static void sub_ixd_ded(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+21; { SUB_M(IXD,DED); } }
+static void sub_ixd_ix(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+21; { SUB_M(IXD,IX); } }
+static void sub_ixd_ixd(t11_state *cpustate, UINT16 op) { cpustate->icount -= 30+27; { SUB_M(IXD,IXD); } }
diff --git a/trunk/src/emu/cpu/t11/t11table.c b/trunk/src/emu/cpu/t11/t11table.c
new file mode 100644
index 00000000000..5bb263378de
--- /dev/null
+++ b/trunk/src/emu/cpu/t11/t11table.c
@@ -0,0 +1,2410 @@
+/*** t11: Portable DEC T-11 emulator ******************************************
+
+ Copyright Aaron Giles
+
+ Opcode table plus function prototypes
+
+*****************************************************************************/
+
+/*
+
+modes:
+ rg = register
+ rgd = register deferred
+ in = increment
+ ind = increment deferred
+ de = decrement
+ ded = decrement deferred
+ ix = index
+ ixd = index deferred
+
+*/
+
+static void op_0000(t11_state *cpustate, UINT16 op);
+static void halt(t11_state *cpustate, UINT16 op);
+static void illegal(t11_state *cpustate, UINT16 op);
+
+static void jmp_rgd(t11_state *cpustate, UINT16 op);
+static void jmp_in(t11_state *cpustate, UINT16 op);
+static void jmp_ind(t11_state *cpustate, UINT16 op);
+static void jmp_de(t11_state *cpustate, UINT16 op);
+static void jmp_ded(t11_state *cpustate, UINT16 op);
+static void jmp_ix(t11_state *cpustate, UINT16 op);
+static void jmp_ixd(t11_state *cpustate, UINT16 op);
+
+static void rts(t11_state *cpustate, UINT16 op);
+static void ccc(t11_state *cpustate, UINT16 op);
+static void scc(t11_state *cpustate, UINT16 op);
+
+static void swab_rg(t11_state *cpustate, UINT16 op);
+static void swab_rgd(t11_state *cpustate, UINT16 op);
+static void swab_in(t11_state *cpustate, UINT16 op);
+static void swab_ind(t11_state *cpustate, UINT16 op);
+static void swab_de(t11_state *cpustate, UINT16 op);
+static void swab_ded(t11_state *cpustate, UINT16 op);
+static void swab_ix(t11_state *cpustate, UINT16 op);
+static void swab_ixd(t11_state *cpustate, UINT16 op);
+
+static void br(t11_state *cpustate, UINT16 op);
+static void bne(t11_state *cpustate, UINT16 op);
+static void beq(t11_state *cpustate, UINT16 op);
+static void bge(t11_state *cpustate, UINT16 op);
+static void blt(t11_state *cpustate, UINT16 op);
+static void bgt(t11_state *cpustate, UINT16 op);
+static void ble(t11_state *cpustate, UINT16 op);
+
+static void jsr_rgd(t11_state *cpustate, UINT16 op);
+static void jsr_in(t11_state *cpustate, UINT16 op);
+static void jsr_ind(t11_state *cpustate, UINT16 op);
+static void jsr_de(t11_state *cpustate, UINT16 op);
+static void jsr_ded(t11_state *cpustate, UINT16 op);
+static void jsr_ix(t11_state *cpustate, UINT16 op);
+static void jsr_ixd(t11_state *cpustate, UINT16 op);
+
+static void clr_rg(t11_state *cpustate, UINT16 op);
+static void clr_rgd(t11_state *cpustate, UINT16 op);
+static void clr_in(t11_state *cpustate, UINT16 op);
+static void clr_ind(t11_state *cpustate, UINT16 op);
+static void clr_de(t11_state *cpustate, UINT16 op);
+static void clr_ded(t11_state *cpustate, UINT16 op);
+static void clr_ix(t11_state *cpustate, UINT16 op);
+static void clr_ixd(t11_state *cpustate, UINT16 op);
+
+static void com_rg(t11_state *cpustate, UINT16 op);
+static void com_rgd(t11_state *cpustate, UINT16 op);
+static void com_in(t11_state *cpustate, UINT16 op);
+static void com_ind(t11_state *cpustate, UINT16 op);
+static void com_de(t11_state *cpustate, UINT16 op);
+static void com_ded(t11_state *cpustate, UINT16 op);
+static void com_ix(t11_state *cpustate, UINT16 op);
+static void com_ixd(t11_state *cpustate, UINT16 op);
+
+static void inc_rg(t11_state *cpustate, UINT16 op);
+static void inc_rgd(t11_state *cpustate, UINT16 op);
+static void inc_in(t11_state *cpustate, UINT16 op);
+static void inc_ind(t11_state *cpustate, UINT16 op);
+static void inc_de(t11_state *cpustate, UINT16 op);
+static void inc_ded(t11_state *cpustate, UINT16 op);
+static void inc_ix(t11_state *cpustate, UINT16 op);
+static void inc_ixd(t11_state *cpustate, UINT16 op);
+
+static void dec_rg(t11_state *cpustate, UINT16 op);
+static void dec_rgd(t11_state *cpustate, UINT16 op);
+static void dec_in(t11_state *cpustate, UINT16 op);
+static void dec_ind(t11_state *cpustate, UINT16 op);
+static void dec_de(t11_state *cpustate, UINT16 op);
+static void dec_ded(t11_state *cpustate, UINT16 op);
+static void dec_ix(t11_state *cpustate, UINT16 op);
+static void dec_ixd(t11_state *cpustate, UINT16 op);
+
+static void neg_rg(t11_state *cpustate, UINT16 op);
+static void neg_rgd(t11_state *cpustate, UINT16 op);
+static void neg_in(t11_state *cpustate, UINT16 op);
+static void neg_ind(t11_state *cpustate, UINT16 op);
+static void neg_de(t11_state *cpustate, UINT16 op);
+static void neg_ded(t11_state *cpustate, UINT16 op);
+static void neg_ix(t11_state *cpustate, UINT16 op);
+static void neg_ixd(t11_state *cpustate, UINT16 op);
+
+static void adc_rg(t11_state *cpustate, UINT16 op);
+static void adc_rgd(t11_state *cpustate, UINT16 op);
+static void adc_in(t11_state *cpustate, UINT16 op);
+static void adc_ind(t11_state *cpustate, UINT16 op);
+static void adc_de(t11_state *cpustate, UINT16 op);
+static void adc_ded(t11_state *cpustate, UINT16 op);
+static void adc_ix(t11_state *cpustate, UINT16 op);
+static void adc_ixd(t11_state *cpustate, UINT16 op);
+
+static void sbc_rg(t11_state *cpustate, UINT16 op);
+static void sbc_rgd(t11_state *cpustate, UINT16 op);
+static void sbc_in(t11_state *cpustate, UINT16 op);
+static void sbc_ind(t11_state *cpustate, UINT16 op);
+static void sbc_de(t11_state *cpustate, UINT16 op);
+static void sbc_ded(t11_state *cpustate, UINT16 op);
+static void sbc_ix(t11_state *cpustate, UINT16 op);
+static void sbc_ixd(t11_state *cpustate, UINT16 op);
+
+static void tst_rg(t11_state *cpustate, UINT16 op);
+static void tst_rgd(t11_state *cpustate, UINT16 op);
+static void tst_in(t11_state *cpustate, UINT16 op);
+static void tst_ind(t11_state *cpustate, UINT16 op);
+static void tst_de(t11_state *cpustate, UINT16 op);
+static void tst_ded(t11_state *cpustate, UINT16 op);
+static void tst_ix(t11_state *cpustate, UINT16 op);
+static void tst_ixd(t11_state *cpustate, UINT16 op);
+
+static void ror_rg(t11_state *cpustate, UINT16 op);
+static void ror_rgd(t11_state *cpustate, UINT16 op);
+static void ror_in(t11_state *cpustate, UINT16 op);
+static void ror_ind(t11_state *cpustate, UINT16 op);
+static void ror_de(t11_state *cpustate, UINT16 op);
+static void ror_ded(t11_state *cpustate, UINT16 op);
+static void ror_ix(t11_state *cpustate, UINT16 op);
+static void ror_ixd(t11_state *cpustate, UINT16 op);
+
+static void rol_rg(t11_state *cpustate, UINT16 op);
+static void rol_rgd(t11_state *cpustate, UINT16 op);
+static void rol_in(t11_state *cpustate, UINT16 op);
+static void rol_ind(t11_state *cpustate, UINT16 op);
+static void rol_de(t11_state *cpustate, UINT16 op);
+static void rol_ded(t11_state *cpustate, UINT16 op);
+static void rol_ix(t11_state *cpustate, UINT16 op);
+static void rol_ixd(t11_state *cpustate, UINT16 op);
+
+static void asr_rg(t11_state *cpustate, UINT16 op);
+static void asr_rgd(t11_state *cpustate, UINT16 op);
+static void asr_in(t11_state *cpustate, UINT16 op);
+static void asr_ind(t11_state *cpustate, UINT16 op);
+static void asr_de(t11_state *cpustate, UINT16 op);
+static void asr_ded(t11_state *cpustate, UINT16 op);
+static void asr_ix(t11_state *cpustate, UINT16 op);
+static void asr_ixd(t11_state *cpustate, UINT16 op);
+
+static void asl_rg(t11_state *cpustate, UINT16 op);
+static void asl_rgd(t11_state *cpustate, UINT16 op);
+static void asl_in(t11_state *cpustate, UINT16 op);
+static void asl_ind(t11_state *cpustate, UINT16 op);
+static void asl_de(t11_state *cpustate, UINT16 op);
+static void asl_ded(t11_state *cpustate, UINT16 op);
+static void asl_ix(t11_state *cpustate, UINT16 op);
+static void asl_ixd(t11_state *cpustate, UINT16 op);
+
+static void mark(t11_state *cpustate, UINT16 op);
+
+static void sxt_rg(t11_state *cpustate, UINT16 op);
+static void sxt_rgd(t11_state *cpustate, UINT16 op);
+static void sxt_in(t11_state *cpustate, UINT16 op);
+static void sxt_ind(t11_state *cpustate, UINT16 op);
+static void sxt_de(t11_state *cpustate, UINT16 op);
+static void sxt_ded(t11_state *cpustate, UINT16 op);
+static void sxt_ix(t11_state *cpustate, UINT16 op);
+static void sxt_ixd(t11_state *cpustate, UINT16 op);
+
+static void mov_rg_rg(t11_state *cpustate, UINT16 op);
+static void mov_rg_rgd(t11_state *cpustate, UINT16 op);
+static void mov_rg_in(t11_state *cpustate, UINT16 op);
+static void mov_rg_ind(t11_state *cpustate, UINT16 op);
+static void mov_rg_de(t11_state *cpustate, UINT16 op);
+static void mov_rg_ded(t11_state *cpustate, UINT16 op);
+static void mov_rg_ix(t11_state *cpustate, UINT16 op);
+static void mov_rg_ixd(t11_state *cpustate, UINT16 op);
+static void mov_rgd_rg(t11_state *cpustate, UINT16 op);
+static void mov_rgd_rgd(t11_state *cpustate, UINT16 op);
+static void mov_rgd_in(t11_state *cpustate, UINT16 op);
+static void mov_rgd_ind(t11_state *cpustate, UINT16 op);
+static void mov_rgd_de(t11_state *cpustate, UINT16 op);
+static void mov_rgd_ded(t11_state *cpustate, UINT16 op);
+static void mov_rgd_ix(t11_state *cpustate, UINT16 op);
+static void mov_rgd_ixd(t11_state *cpustate, UINT16 op);
+static void mov_in_rg(t11_state *cpustate, UINT16 op);
+static void mov_in_rgd(t11_state *cpustate, UINT16 op);
+static void mov_in_in(t11_state *cpustate, UINT16 op);
+static void mov_in_ind(t11_state *cpustate, UINT16 op);
+static void mov_in_de(t11_state *cpustate, UINT16 op);
+static void mov_in_ded(t11_state *cpustate, UINT16 op);
+static void mov_in_ix(t11_state *cpustate, UINT16 op);
+static void mov_in_ixd(t11_state *cpustate, UINT16 op);
+static void mov_ind_rg(t11_state *cpustate, UINT16 op);
+static void mov_ind_rgd(t11_state *cpustate, UINT16 op);
+static void mov_ind_in(t11_state *cpustate, UINT16 op);
+static void mov_ind_ind(t11_state *cpustate, UINT16 op);
+static void mov_ind_de(t11_state *cpustate, UINT16 op);
+static void mov_ind_ded(t11_state *cpustate, UINT16 op);
+static void mov_ind_ix(t11_state *cpustate, UINT16 op);
+static void mov_ind_ixd(t11_state *cpustate, UINT16 op);
+static void mov_de_rg(t11_state *cpustate, UINT16 op);
+static void mov_de_rgd(t11_state *cpustate, UINT16 op);
+static void mov_de_in(t11_state *cpustate, UINT16 op);
+static void mov_de_ind(t11_state *cpustate, UINT16 op);
+static void mov_de_de(t11_state *cpustate, UINT16 op);
+static void mov_de_ded(t11_state *cpustate, UINT16 op);
+static void mov_de_ix(t11_state *cpustate, UINT16 op);
+static void mov_de_ixd(t11_state *cpustate, UINT16 op);
+static void mov_ded_rg(t11_state *cpustate, UINT16 op);
+static void mov_ded_rgd(t11_state *cpustate, UINT16 op);
+static void mov_ded_in(t11_state *cpustate, UINT16 op);
+static void mov_ded_ind(t11_state *cpustate, UINT16 op);
+static void mov_ded_de(t11_state *cpustate, UINT16 op);
+static void mov_ded_ded(t11_state *cpustate, UINT16 op);
+static void mov_ded_ix(t11_state *cpustate, UINT16 op);
+static void mov_ded_ixd(t11_state *cpustate, UINT16 op);
+static void mov_ix_rg(t11_state *cpustate, UINT16 op);
+static void mov_ix_rgd(t11_state *cpustate, UINT16 op);
+static void mov_ix_in(t11_state *cpustate, UINT16 op);
+static void mov_ix_ind(t11_state *cpustate, UINT16 op);
+static void mov_ix_de(t11_state *cpustate, UINT16 op);
+static void mov_ix_ded(t11_state *cpustate, UINT16 op);
+static void mov_ix_ix(t11_state *cpustate, UINT16 op);
+static void mov_ix_ixd(t11_state *cpustate, UINT16 op);
+static void mov_ixd_rg(t11_state *cpustate, UINT16 op);
+static void mov_ixd_rgd(t11_state *cpustate, UINT16 op);
+static void mov_ixd_in(t11_state *cpustate, UINT16 op);
+static void mov_ixd_ind(t11_state *cpustate, UINT16 op);
+static void mov_ixd_de(t11_state *cpustate, UINT16 op);
+static void mov_ixd_ded(t11_state *cpustate, UINT16 op);
+static void mov_ixd_ix(t11_state *cpustate, UINT16 op);
+static void mov_ixd_ixd(t11_state *cpustate, UINT16 op);
+
+static void cmp_rg_rg(t11_state *cpustate, UINT16 op);
+static void cmp_rg_rgd(t11_state *cpustate, UINT16 op);
+static void cmp_rg_in(t11_state *cpustate, UINT16 op);
+static void cmp_rg_ind(t11_state *cpustate, UINT16 op);
+static void cmp_rg_de(t11_state *cpustate, UINT16 op);
+static void cmp_rg_ded(t11_state *cpustate, UINT16 op);
+static void cmp_rg_ix(t11_state *cpustate, UINT16 op);
+static void cmp_rg_ixd(t11_state *cpustate, UINT16 op);
+static void cmp_rgd_rg(t11_state *cpustate, UINT16 op);
+static void cmp_rgd_rgd(t11_state *cpustate, UINT16 op);
+static void cmp_rgd_in(t11_state *cpustate, UINT16 op);
+static void cmp_rgd_ind(t11_state *cpustate, UINT16 op);
+static void cmp_rgd_de(t11_state *cpustate, UINT16 op);
+static void cmp_rgd_ded(t11_state *cpustate, UINT16 op);
+static void cmp_rgd_ix(t11_state *cpustate, UINT16 op);
+static void cmp_rgd_ixd(t11_state *cpustate, UINT16 op);
+static void cmp_in_rg(t11_state *cpustate, UINT16 op);
+static void cmp_in_rgd(t11_state *cpustate, UINT16 op);
+static void cmp_in_in(t11_state *cpustate, UINT16 op);
+static void cmp_in_ind(t11_state *cpustate, UINT16 op);
+static void cmp_in_de(t11_state *cpustate, UINT16 op);
+static void cmp_in_ded(t11_state *cpustate, UINT16 op);
+static void cmp_in_ix(t11_state *cpustate, UINT16 op);
+static void cmp_in_ixd(t11_state *cpustate, UINT16 op);
+static void cmp_ind_rg(t11_state *cpustate, UINT16 op);
+static void cmp_ind_rgd(t11_state *cpustate, UINT16 op);
+static void cmp_ind_in(t11_state *cpustate, UINT16 op);
+static void cmp_ind_ind(t11_state *cpustate, UINT16 op);
+static void cmp_ind_de(t11_state *cpustate, UINT16 op);
+static void cmp_ind_ded(t11_state *cpustate, UINT16 op);
+static void cmp_ind_ix(t11_state *cpustate, UINT16 op);
+static void cmp_ind_ixd(t11_state *cpustate, UINT16 op);
+static void cmp_de_rg(t11_state *cpustate, UINT16 op);
+static void cmp_de_rgd(t11_state *cpustate, UINT16 op);
+static void cmp_de_in(t11_state *cpustate, UINT16 op);
+static void cmp_de_ind(t11_state *cpustate, UINT16 op);
+static void cmp_de_de(t11_state *cpustate, UINT16 op);
+static void cmp_de_ded(t11_state *cpustate, UINT16 op);
+static void cmp_de_ix(t11_state *cpustate, UINT16 op);
+static void cmp_de_ixd(t11_state *cpustate, UINT16 op);
+static void cmp_ded_rg(t11_state *cpustate, UINT16 op);
+static void cmp_ded_rgd(t11_state *cpustate, UINT16 op);
+static void cmp_ded_in(t11_state *cpustate, UINT16 op);
+static void cmp_ded_ind(t11_state *cpustate, UINT16 op);
+static void cmp_ded_de(t11_state *cpustate, UINT16 op);
+static void cmp_ded_ded(t11_state *cpustate, UINT16 op);
+static void cmp_ded_ix(t11_state *cpustate, UINT16 op);
+static void cmp_ded_ixd(t11_state *cpustate, UINT16 op);
+static void cmp_ix_rg(t11_state *cpustate, UINT16 op);
+static void cmp_ix_rgd(t11_state *cpustate, UINT16 op);
+static void cmp_ix_in(t11_state *cpustate, UINT16 op);
+static void cmp_ix_ind(t11_state *cpustate, UINT16 op);
+static void cmp_ix_de(t11_state *cpustate, UINT16 op);
+static void cmp_ix_ded(t11_state *cpustate, UINT16 op);
+static void cmp_ix_ix(t11_state *cpustate, UINT16 op);
+static void cmp_ix_ixd(t11_state *cpustate, UINT16 op);
+static void cmp_ixd_rg(t11_state *cpustate, UINT16 op);
+static void cmp_ixd_rgd(t11_state *cpustate, UINT16 op);
+static void cmp_ixd_in(t11_state *cpustate, UINT16 op);
+static void cmp_ixd_ind(t11_state *cpustate, UINT16 op);
+static void cmp_ixd_de(t11_state *cpustate, UINT16 op);
+static void cmp_ixd_ded(t11_state *cpustate, UINT16 op);
+static void cmp_ixd_ix(t11_state *cpustate, UINT16 op);
+static void cmp_ixd_ixd(t11_state *cpustate, UINT16 op);
+
+static void bit_rg_rg(t11_state *cpustate, UINT16 op);
+static void bit_rg_rgd(t11_state *cpustate, UINT16 op);
+static void bit_rg_in(t11_state *cpustate, UINT16 op);
+static void bit_rg_ind(t11_state *cpustate, UINT16 op);
+static void bit_rg_de(t11_state *cpustate, UINT16 op);
+static void bit_rg_ded(t11_state *cpustate, UINT16 op);
+static void bit_rg_ix(t11_state *cpustate, UINT16 op);
+static void bit_rg_ixd(t11_state *cpustate, UINT16 op);
+static void bit_rgd_rg(t11_state *cpustate, UINT16 op);
+static void bit_rgd_rgd(t11_state *cpustate, UINT16 op);
+static void bit_rgd_in(t11_state *cpustate, UINT16 op);
+static void bit_rgd_ind(t11_state *cpustate, UINT16 op);
+static void bit_rgd_de(t11_state *cpustate, UINT16 op);
+static void bit_rgd_ded(t11_state *cpustate, UINT16 op);
+static void bit_rgd_ix(t11_state *cpustate, UINT16 op);
+static void bit_rgd_ixd(t11_state *cpustate, UINT16 op);
+static void bit_in_rg(t11_state *cpustate, UINT16 op);
+static void bit_in_rgd(t11_state *cpustate, UINT16 op);
+static void bit_in_in(t11_state *cpustate, UINT16 op);
+static void bit_in_ind(t11_state *cpustate, UINT16 op);
+static void bit_in_de(t11_state *cpustate, UINT16 op);
+static void bit_in_ded(t11_state *cpustate, UINT16 op);
+static void bit_in_ix(t11_state *cpustate, UINT16 op);
+static void bit_in_ixd(t11_state *cpustate, UINT16 op);
+static void bit_ind_rg(t11_state *cpustate, UINT16 op);
+static void bit_ind_rgd(t11_state *cpustate, UINT16 op);
+static void bit_ind_in(t11_state *cpustate, UINT16 op);
+static void bit_ind_ind(t11_state *cpustate, UINT16 op);
+static void bit_ind_de(t11_state *cpustate, UINT16 op);
+static void bit_ind_ded(t11_state *cpustate, UINT16 op);
+static void bit_ind_ix(t11_state *cpustate, UINT16 op);
+static void bit_ind_ixd(t11_state *cpustate, UINT16 op);
+static void bit_de_rg(t11_state *cpustate, UINT16 op);
+static void bit_de_rgd(t11_state *cpustate, UINT16 op);
+static void bit_de_in(t11_state *cpustate, UINT16 op);
+static void bit_de_ind(t11_state *cpustate, UINT16 op);
+static void bit_de_de(t11_state *cpustate, UINT16 op);
+static void bit_de_ded(t11_state *cpustate, UINT16 op);
+static void bit_de_ix(t11_state *cpustate, UINT16 op);
+static void bit_de_ixd(t11_state *cpustate, UINT16 op);
+static void bit_ded_rg(t11_state *cpustate, UINT16 op);
+static void bit_ded_rgd(t11_state *cpustate, UINT16 op);
+static void bit_ded_in(t11_state *cpustate, UINT16 op);
+static void bit_ded_ind(t11_state *cpustate, UINT16 op);
+static void bit_ded_de(t11_state *cpustate, UINT16 op);
+static void bit_ded_ded(t11_state *cpustate, UINT16 op);
+static void bit_ded_ix(t11_state *cpustate, UINT16 op);
+static void bit_ded_ixd(t11_state *cpustate, UINT16 op);
+static void bit_ix_rg(t11_state *cpustate, UINT16 op);
+static void bit_ix_rgd(t11_state *cpustate, UINT16 op);
+static void bit_ix_in(t11_state *cpustate, UINT16 op);
+static void bit_ix_ind(t11_state *cpustate, UINT16 op);
+static void bit_ix_de(t11_state *cpustate, UINT16 op);
+static void bit_ix_ded(t11_state *cpustate, UINT16 op);
+static void bit_ix_ix(t11_state *cpustate, UINT16 op);
+static void bit_ix_ixd(t11_state *cpustate, UINT16 op);
+static void bit_ixd_rg(t11_state *cpustate, UINT16 op);
+static void bit_ixd_rgd(t11_state *cpustate, UINT16 op);
+static void bit_ixd_in(t11_state *cpustate, UINT16 op);
+static void bit_ixd_ind(t11_state *cpustate, UINT16 op);
+static void bit_ixd_de(t11_state *cpustate, UINT16 op);
+static void bit_ixd_ded(t11_state *cpustate, UINT16 op);
+static void bit_ixd_ix(t11_state *cpustate, UINT16 op);
+static void bit_ixd_ixd(t11_state *cpustate, UINT16 op);
+
+static void bic_rg_rg(t11_state *cpustate, UINT16 op);
+static void bic_rg_rgd(t11_state *cpustate, UINT16 op);
+static void bic_rg_in(t11_state *cpustate, UINT16 op);
+static void bic_rg_ind(t11_state *cpustate, UINT16 op);
+static void bic_rg_de(t11_state *cpustate, UINT16 op);
+static void bic_rg_ded(t11_state *cpustate, UINT16 op);
+static void bic_rg_ix(t11_state *cpustate, UINT16 op);
+static void bic_rg_ixd(t11_state *cpustate, UINT16 op);
+static void bic_rgd_rg(t11_state *cpustate, UINT16 op);
+static void bic_rgd_rgd(t11_state *cpustate, UINT16 op);
+static void bic_rgd_in(t11_state *cpustate, UINT16 op);
+static void bic_rgd_ind(t11_state *cpustate, UINT16 op);
+static void bic_rgd_de(t11_state *cpustate, UINT16 op);
+static void bic_rgd_ded(t11_state *cpustate, UINT16 op);
+static void bic_rgd_ix(t11_state *cpustate, UINT16 op);
+static void bic_rgd_ixd(t11_state *cpustate, UINT16 op);
+static void bic_in_rg(t11_state *cpustate, UINT16 op);
+static void bic_in_rgd(t11_state *cpustate, UINT16 op);
+static void bic_in_in(t11_state *cpustate, UINT16 op);
+static void bic_in_ind(t11_state *cpustate, UINT16 op);
+static void bic_in_de(t11_state *cpustate, UINT16 op);
+static void bic_in_ded(t11_state *cpustate, UINT16 op);
+static void bic_in_ix(t11_state *cpustate, UINT16 op);
+static void bic_in_ixd(t11_state *cpustate, UINT16 op);
+static void bic_ind_rg(t11_state *cpustate, UINT16 op);
+static void bic_ind_rgd(t11_state *cpustate, UINT16 op);
+static void bic_ind_in(t11_state *cpustate, UINT16 op);
+static void bic_ind_ind(t11_state *cpustate, UINT16 op);
+static void bic_ind_de(t11_state *cpustate, UINT16 op);
+static void bic_ind_ded(t11_state *cpustate, UINT16 op);
+static void bic_ind_ix(t11_state *cpustate, UINT16 op);
+static void bic_ind_ixd(t11_state *cpustate, UINT16 op);
+static void bic_de_rg(t11_state *cpustate, UINT16 op);
+static void bic_de_rgd(t11_state *cpustate, UINT16 op);
+static void bic_de_in(t11_state *cpustate, UINT16 op);
+static void bic_de_ind(t11_state *cpustate, UINT16 op);
+static void bic_de_de(t11_state *cpustate, UINT16 op);
+static void bic_de_ded(t11_state *cpustate, UINT16 op);
+static void bic_de_ix(t11_state *cpustate, UINT16 op);
+static void bic_de_ixd(t11_state *cpustate, UINT16 op);
+static void bic_ded_rg(t11_state *cpustate, UINT16 op);
+static void bic_ded_rgd(t11_state *cpustate, UINT16 op);
+static void bic_ded_in(t11_state *cpustate, UINT16 op);
+static void bic_ded_ind(t11_state *cpustate, UINT16 op);
+static void bic_ded_de(t11_state *cpustate, UINT16 op);
+static void bic_ded_ded(t11_state *cpustate, UINT16 op);
+static void bic_ded_ix(t11_state *cpustate, UINT16 op);
+static void bic_ded_ixd(t11_state *cpustate, UINT16 op);
+static void bic_ix_rg(t11_state *cpustate, UINT16 op);
+static void bic_ix_rgd(t11_state *cpustate, UINT16 op);
+static void bic_ix_in(t11_state *cpustate, UINT16 op);
+static void bic_ix_ind(t11_state *cpustate, UINT16 op);
+static void bic_ix_de(t11_state *cpustate, UINT16 op);
+static void bic_ix_ded(t11_state *cpustate, UINT16 op);
+static void bic_ix_ix(t11_state *cpustate, UINT16 op);
+static void bic_ix_ixd(t11_state *cpustate, UINT16 op);
+static void bic_ixd_rg(t11_state *cpustate, UINT16 op);
+static void bic_ixd_rgd(t11_state *cpustate, UINT16 op);
+static void bic_ixd_in(t11_state *cpustate, UINT16 op);
+static void bic_ixd_ind(t11_state *cpustate, UINT16 op);
+static void bic_ixd_de(t11_state *cpustate, UINT16 op);
+static void bic_ixd_ded(t11_state *cpustate, UINT16 op);
+static void bic_ixd_ix(t11_state *cpustate, UINT16 op);
+static void bic_ixd_ixd(t11_state *cpustate, UINT16 op);
+
+static void bis_rg_rg(t11_state *cpustate, UINT16 op);
+static void bis_rg_rgd(t11_state *cpustate, UINT16 op);
+static void bis_rg_in(t11_state *cpustate, UINT16 op);
+static void bis_rg_ind(t11_state *cpustate, UINT16 op);
+static void bis_rg_de(t11_state *cpustate, UINT16 op);
+static void bis_rg_ded(t11_state *cpustate, UINT16 op);
+static void bis_rg_ix(t11_state *cpustate, UINT16 op);
+static void bis_rg_ixd(t11_state *cpustate, UINT16 op);
+static void bis_rgd_rg(t11_state *cpustate, UINT16 op);
+static void bis_rgd_rgd(t11_state *cpustate, UINT16 op);
+static void bis_rgd_in(t11_state *cpustate, UINT16 op);
+static void bis_rgd_ind(t11_state *cpustate, UINT16 op);
+static void bis_rgd_de(t11_state *cpustate, UINT16 op);
+static void bis_rgd_ded(t11_state *cpustate, UINT16 op);
+static void bis_rgd_ix(t11_state *cpustate, UINT16 op);
+static void bis_rgd_ixd(t11_state *cpustate, UINT16 op);
+static void bis_in_rg(t11_state *cpustate, UINT16 op);
+static void bis_in_rgd(t11_state *cpustate, UINT16 op);
+static void bis_in_in(t11_state *cpustate, UINT16 op);
+static void bis_in_ind(t11_state *cpustate, UINT16 op);
+static void bis_in_de(t11_state *cpustate, UINT16 op);
+static void bis_in_ded(t11_state *cpustate, UINT16 op);
+static void bis_in_ix(t11_state *cpustate, UINT16 op);
+static void bis_in_ixd(t11_state *cpustate, UINT16 op);
+static void bis_ind_rg(t11_state *cpustate, UINT16 op);
+static void bis_ind_rgd(t11_state *cpustate, UINT16 op);
+static void bis_ind_in(t11_state *cpustate, UINT16 op);
+static void bis_ind_ind(t11_state *cpustate, UINT16 op);
+static void bis_ind_de(t11_state *cpustate, UINT16 op);
+static void bis_ind_ded(t11_state *cpustate, UINT16 op);
+static void bis_ind_ix(t11_state *cpustate, UINT16 op);
+static void bis_ind_ixd(t11_state *cpustate, UINT16 op);
+static void bis_de_rg(t11_state *cpustate, UINT16 op);
+static void bis_de_rgd(t11_state *cpustate, UINT16 op);
+static void bis_de_in(t11_state *cpustate, UINT16 op);
+static void bis_de_ind(t11_state *cpustate, UINT16 op);
+static void bis_de_de(t11_state *cpustate, UINT16 op);
+static void bis_de_ded(t11_state *cpustate, UINT16 op);
+static void bis_de_ix(t11_state *cpustate, UINT16 op);
+static void bis_de_ixd(t11_state *cpustate, UINT16 op);
+static void bis_ded_rg(t11_state *cpustate, UINT16 op);
+static void bis_ded_rgd(t11_state *cpustate, UINT16 op);
+static void bis_ded_in(t11_state *cpustate, UINT16 op);
+static void bis_ded_ind(t11_state *cpustate, UINT16 op);
+static void bis_ded_de(t11_state *cpustate, UINT16 op);
+static void bis_ded_ded(t11_state *cpustate, UINT16 op);
+static void bis_ded_ix(t11_state *cpustate, UINT16 op);
+static void bis_ded_ixd(t11_state *cpustate, UINT16 op);
+static void bis_ix_rg(t11_state *cpustate, UINT16 op);
+static void bis_ix_rgd(t11_state *cpustate, UINT16 op);
+static void bis_ix_in(t11_state *cpustate, UINT16 op);
+static void bis_ix_ind(t11_state *cpustate, UINT16 op);
+static void bis_ix_de(t11_state *cpustate, UINT16 op);
+static void bis_ix_ded(t11_state *cpustate, UINT16 op);
+static void bis_ix_ix(t11_state *cpustate, UINT16 op);
+static void bis_ix_ixd(t11_state *cpustate, UINT16 op);
+static void bis_ixd_rg(t11_state *cpustate, UINT16 op);
+static void bis_ixd_rgd(t11_state *cpustate, UINT16 op);
+static void bis_ixd_in(t11_state *cpustate, UINT16 op);
+static void bis_ixd_ind(t11_state *cpustate, UINT16 op);
+static void bis_ixd_de(t11_state *cpustate, UINT16 op);
+static void bis_ixd_ded(t11_state *cpustate, UINT16 op);
+static void bis_ixd_ix(t11_state *cpustate, UINT16 op);
+static void bis_ixd_ixd(t11_state *cpustate, UINT16 op);
+
+static void add_rg_rg(t11_state *cpustate, UINT16 op);
+static void add_rg_rgd(t11_state *cpustate, UINT16 op);
+static void add_rg_in(t11_state *cpustate, UINT16 op);
+static void add_rg_ind(t11_state *cpustate, UINT16 op);
+static void add_rg_de(t11_state *cpustate, UINT16 op);
+static void add_rg_ded(t11_state *cpustate, UINT16 op);
+static void add_rg_ix(t11_state *cpustate, UINT16 op);
+static void add_rg_ixd(t11_state *cpustate, UINT16 op);
+static void add_rgd_rg(t11_state *cpustate, UINT16 op);
+static void add_rgd_rgd(t11_state *cpustate, UINT16 op);
+static void add_rgd_in(t11_state *cpustate, UINT16 op);
+static void add_rgd_ind(t11_state *cpustate, UINT16 op);
+static void add_rgd_de(t11_state *cpustate, UINT16 op);
+static void add_rgd_ded(t11_state *cpustate, UINT16 op);
+static void add_rgd_ix(t11_state *cpustate, UINT16 op);
+static void add_rgd_ixd(t11_state *cpustate, UINT16 op);
+static void add_in_rg(t11_state *cpustate, UINT16 op);
+static void add_in_rgd(t11_state *cpustate, UINT16 op);
+static void add_in_in(t11_state *cpustate, UINT16 op);
+static void add_in_ind(t11_state *cpustate, UINT16 op);
+static void add_in_de(t11_state *cpustate, UINT16 op);
+static void add_in_ded(t11_state *cpustate, UINT16 op);
+static void add_in_ix(t11_state *cpustate, UINT16 op);
+static void add_in_ixd(t11_state *cpustate, UINT16 op);
+static void add_ind_rg(t11_state *cpustate, UINT16 op);
+static void add_ind_rgd(t11_state *cpustate, UINT16 op);
+static void add_ind_in(t11_state *cpustate, UINT16 op);
+static void add_ind_ind(t11_state *cpustate, UINT16 op);
+static void add_ind_de(t11_state *cpustate, UINT16 op);
+static void add_ind_ded(t11_state *cpustate, UINT16 op);
+static void add_ind_ix(t11_state *cpustate, UINT16 op);
+static void add_ind_ixd(t11_state *cpustate, UINT16 op);
+static void add_de_rg(t11_state *cpustate, UINT16 op);
+static void add_de_rgd(t11_state *cpustate, UINT16 op);
+static void add_de_in(t11_state *cpustate, UINT16 op);
+static void add_de_ind(t11_state *cpustate, UINT16 op);
+static void add_de_de(t11_state *cpustate, UINT16 op);
+static void add_de_ded(t11_state *cpustate, UINT16 op);
+static void add_de_ix(t11_state *cpustate, UINT16 op);
+static void add_de_ixd(t11_state *cpustate, UINT16 op);
+static void add_ded_rg(t11_state *cpustate, UINT16 op);
+static void add_ded_rgd(t11_state *cpustate, UINT16 op);
+static void add_ded_in(t11_state *cpustate, UINT16 op);
+static void add_ded_ind(t11_state *cpustate, UINT16 op);
+static void add_ded_de(t11_state *cpustate, UINT16 op);
+static void add_ded_ded(t11_state *cpustate, UINT16 op);
+static void add_ded_ix(t11_state *cpustate, UINT16 op);
+static void add_ded_ixd(t11_state *cpustate, UINT16 op);
+static void add_ix_rg(t11_state *cpustate, UINT16 op);
+static void add_ix_rgd(t11_state *cpustate, UINT16 op);
+static void add_ix_in(t11_state *cpustate, UINT16 op);
+static void add_ix_ind(t11_state *cpustate, UINT16 op);
+static void add_ix_de(t11_state *cpustate, UINT16 op);
+static void add_ix_ded(t11_state *cpustate, UINT16 op);
+static void add_ix_ix(t11_state *cpustate, UINT16 op);
+static void add_ix_ixd(t11_state *cpustate, UINT16 op);
+static void add_ixd_rg(t11_state *cpustate, UINT16 op);
+static void add_ixd_rgd(t11_state *cpustate, UINT16 op);
+static void add_ixd_in(t11_state *cpustate, UINT16 op);
+static void add_ixd_ind(t11_state *cpustate, UINT16 op);
+static void add_ixd_de(t11_state *cpustate, UINT16 op);
+static void add_ixd_ded(t11_state *cpustate, UINT16 op);
+static void add_ixd_ix(t11_state *cpustate, UINT16 op);
+static void add_ixd_ixd(t11_state *cpustate, UINT16 op);
+
+static void xor_rg(t11_state *cpustate, UINT16 op);
+static void xor_rgd(t11_state *cpustate, UINT16 op);
+static void xor_in(t11_state *cpustate, UINT16 op);
+static void xor_ind(t11_state *cpustate, UINT16 op);
+static void xor_de(t11_state *cpustate, UINT16 op);
+static void xor_ded(t11_state *cpustate, UINT16 op);
+static void xor_ix(t11_state *cpustate, UINT16 op);
+static void xor_ixd(t11_state *cpustate, UINT16 op);
+
+static void sob(t11_state *cpustate, UINT16 op);
+
+static void bpl(t11_state *cpustate, UINT16 op);
+static void bmi(t11_state *cpustate, UINT16 op);
+static void bhi(t11_state *cpustate, UINT16 op);
+static void blos(t11_state *cpustate, UINT16 op);
+static void bvc(t11_state *cpustate, UINT16 op);
+static void bvs(t11_state *cpustate, UINT16 op);
+static void bcc(t11_state *cpustate, UINT16 op);
+static void bcs(t11_state *cpustate, UINT16 op);
+static void emt(t11_state *cpustate, UINT16 op);
+static void trap(t11_state *cpustate, UINT16 op);
+
+static void clrb_rg(t11_state *cpustate, UINT16 op);
+static void clrb_rgd(t11_state *cpustate, UINT16 op);
+static void clrb_in(t11_state *cpustate, UINT16 op);
+static void clrb_ind(t11_state *cpustate, UINT16 op);
+static void clrb_de(t11_state *cpustate, UINT16 op);
+static void clrb_ded(t11_state *cpustate, UINT16 op);
+static void clrb_ix(t11_state *cpustate, UINT16 op);
+static void clrb_ixd(t11_state *cpustate, UINT16 op);
+
+static void comb_rg(t11_state *cpustate, UINT16 op);
+static void comb_rgd(t11_state *cpustate, UINT16 op);
+static void comb_in(t11_state *cpustate, UINT16 op);
+static void comb_ind(t11_state *cpustate, UINT16 op);
+static void comb_de(t11_state *cpustate, UINT16 op);
+static void comb_ded(t11_state *cpustate, UINT16 op);
+static void comb_ix(t11_state *cpustate, UINT16 op);
+static void comb_ixd(t11_state *cpustate, UINT16 op);
+
+static void incb_rg(t11_state *cpustate, UINT16 op);
+static void incb_rgd(t11_state *cpustate, UINT16 op);
+static void incb_in(t11_state *cpustate, UINT16 op);
+static void incb_ind(t11_state *cpustate, UINT16 op);
+static void incb_de(t11_state *cpustate, UINT16 op);
+static void incb_ded(t11_state *cpustate, UINT16 op);
+static void incb_ix(t11_state *cpustate, UINT16 op);
+static void incb_ixd(t11_state *cpustate, UINT16 op);
+
+static void decb_rg(t11_state *cpustate, UINT16 op);
+static void decb_rgd(t11_state *cpustate, UINT16 op);
+static void decb_in(t11_state *cpustate, UINT16 op);
+static void decb_ind(t11_state *cpustate, UINT16 op);
+static void decb_de(t11_state *cpustate, UINT16 op);
+static void decb_ded(t11_state *cpustate, UINT16 op);
+static void decb_ix(t11_state *cpustate, UINT16 op);
+static void decb_ixd(t11_state *cpustate, UINT16 op);
+
+static void negb_rg(t11_state *cpustate, UINT16 op);
+static void negb_rgd(t11_state *cpustate, UINT16 op);
+static void negb_in(t11_state *cpustate, UINT16 op);
+static void negb_ind(t11_state *cpustate, UINT16 op);
+static void negb_de(t11_state *cpustate, UINT16 op);
+static void negb_ded(t11_state *cpustate, UINT16 op);
+static void negb_ix(t11_state *cpustate, UINT16 op);
+static void negb_ixd(t11_state *cpustate, UINT16 op);
+
+static void adcb_rg(t11_state *cpustate, UINT16 op);
+static void adcb_rgd(t11_state *cpustate, UINT16 op);
+static void adcb_in(t11_state *cpustate, UINT16 op);
+static void adcb_ind(t11_state *cpustate, UINT16 op);
+static void adcb_de(t11_state *cpustate, UINT16 op);
+static void adcb_ded(t11_state *cpustate, UINT16 op);
+static void adcb_ix(t11_state *cpustate, UINT16 op);
+static void adcb_ixd(t11_state *cpustate, UINT16 op);
+
+static void sbcb_rg(t11_state *cpustate, UINT16 op);
+static void sbcb_rgd(t11_state *cpustate, UINT16 op);
+static void sbcb_in(t11_state *cpustate, UINT16 op);
+static void sbcb_ind(t11_state *cpustate, UINT16 op);
+static void sbcb_de(t11_state *cpustate, UINT16 op);
+static void sbcb_ded(t11_state *cpustate, UINT16 op);
+static void sbcb_ix(t11_state *cpustate, UINT16 op);
+static void sbcb_ixd(t11_state *cpustate, UINT16 op);
+
+static void tstb_rg(t11_state *cpustate, UINT16 op);
+static void tstb_rgd(t11_state *cpustate, UINT16 op);
+static void tstb_in(t11_state *cpustate, UINT16 op);
+static void tstb_ind(t11_state *cpustate, UINT16 op);
+static void tstb_de(t11_state *cpustate, UINT16 op);
+static void tstb_ded(t11_state *cpustate, UINT16 op);
+static void tstb_ix(t11_state *cpustate, UINT16 op);
+static void tstb_ixd(t11_state *cpustate, UINT16 op);
+
+static void rorb_rg(t11_state *cpustate, UINT16 op);
+static void rorb_rgd(t11_state *cpustate, UINT16 op);
+static void rorb_in(t11_state *cpustate, UINT16 op);
+static void rorb_ind(t11_state *cpustate, UINT16 op);
+static void rorb_de(t11_state *cpustate, UINT16 op);
+static void rorb_ded(t11_state *cpustate, UINT16 op);
+static void rorb_ix(t11_state *cpustate, UINT16 op);
+static void rorb_ixd(t11_state *cpustate, UINT16 op);
+
+static void rolb_rg(t11_state *cpustate, UINT16 op);
+static void rolb_rgd(t11_state *cpustate, UINT16 op);
+static void rolb_in(t11_state *cpustate, UINT16 op);
+static void rolb_ind(t11_state *cpustate, UINT16 op);
+static void rolb_de(t11_state *cpustate, UINT16 op);
+static void rolb_ded(t11_state *cpustate, UINT16 op);
+static void rolb_ix(t11_state *cpustate, UINT16 op);
+static void rolb_ixd(t11_state *cpustate, UINT16 op);
+
+static void asrb_rg(t11_state *cpustate, UINT16 op);
+static void asrb_rgd(t11_state *cpustate, UINT16 op);
+static void asrb_in(t11_state *cpustate, UINT16 op);
+static void asrb_ind(t11_state *cpustate, UINT16 op);
+static void asrb_de(t11_state *cpustate, UINT16 op);
+static void asrb_ded(t11_state *cpustate, UINT16 op);
+static void asrb_ix(t11_state *cpustate, UINT16 op);
+static void asrb_ixd(t11_state *cpustate, UINT16 op);
+
+static void aslb_rg(t11_state *cpustate, UINT16 op);
+static void aslb_rgd(t11_state *cpustate, UINT16 op);
+static void aslb_in(t11_state *cpustate, UINT16 op);
+static void aslb_ind(t11_state *cpustate, UINT16 op);
+static void aslb_de(t11_state *cpustate, UINT16 op);
+static void aslb_ded(t11_state *cpustate, UINT16 op);
+static void aslb_ix(t11_state *cpustate, UINT16 op);
+static void aslb_ixd(t11_state *cpustate, UINT16 op);
+
+static void mtps_rg(t11_state *cpustate, UINT16 op);
+static void mtps_rgd(t11_state *cpustate, UINT16 op);
+static void mtps_in(t11_state *cpustate, UINT16 op);
+static void mtps_ind(t11_state *cpustate, UINT16 op);
+static void mtps_de(t11_state *cpustate, UINT16 op);
+static void mtps_ded(t11_state *cpustate, UINT16 op);
+static void mtps_ix(t11_state *cpustate, UINT16 op);
+static void mtps_ixd(t11_state *cpustate, UINT16 op);
+
+static void mfps_rg(t11_state *cpustate, UINT16 op);
+static void mfps_rgd(t11_state *cpustate, UINT16 op);
+static void mfps_in(t11_state *cpustate, UINT16 op);
+static void mfps_ind(t11_state *cpustate, UINT16 op);
+static void mfps_de(t11_state *cpustate, UINT16 op);
+static void mfps_ded(t11_state *cpustate, UINT16 op);
+static void mfps_ix(t11_state *cpustate, UINT16 op);
+static void mfps_ixd(t11_state *cpustate, UINT16 op);
+
+static void movb_rg_rg(t11_state *cpustate, UINT16 op);
+static void movb_rg_rgd(t11_state *cpustate, UINT16 op);
+static void movb_rg_in(t11_state *cpustate, UINT16 op);
+static void movb_rg_ind(t11_state *cpustate, UINT16 op);
+static void movb_rg_de(t11_state *cpustate, UINT16 op);
+static void movb_rg_ded(t11_state *cpustate, UINT16 op);
+static void movb_rg_ix(t11_state *cpustate, UINT16 op);
+static void movb_rg_ixd(t11_state *cpustate, UINT16 op);
+static void movb_rgd_rg(t11_state *cpustate, UINT16 op);
+static void movb_rgd_rgd(t11_state *cpustate, UINT16 op);
+static void movb_rgd_in(t11_state *cpustate, UINT16 op);
+static void movb_rgd_ind(t11_state *cpustate, UINT16 op);
+static void movb_rgd_de(t11_state *cpustate, UINT16 op);
+static void movb_rgd_ded(t11_state *cpustate, UINT16 op);
+static void movb_rgd_ix(t11_state *cpustate, UINT16 op);
+static void movb_rgd_ixd(t11_state *cpustate, UINT16 op);
+static void movb_in_rg(t11_state *cpustate, UINT16 op);
+static void movb_in_rgd(t11_state *cpustate, UINT16 op);
+static void movb_in_in(t11_state *cpustate, UINT16 op);
+static void movb_in_ind(t11_state *cpustate, UINT16 op);
+static void movb_in_de(t11_state *cpustate, UINT16 op);
+static void movb_in_ded(t11_state *cpustate, UINT16 op);
+static void movb_in_ix(t11_state *cpustate, UINT16 op);
+static void movb_in_ixd(t11_state *cpustate, UINT16 op);
+static void movb_ind_rg(t11_state *cpustate, UINT16 op);
+static void movb_ind_rgd(t11_state *cpustate, UINT16 op);
+static void movb_ind_in(t11_state *cpustate, UINT16 op);
+static void movb_ind_ind(t11_state *cpustate, UINT16 op);
+static void movb_ind_de(t11_state *cpustate, UINT16 op);
+static void movb_ind_ded(t11_state *cpustate, UINT16 op);
+static void movb_ind_ix(t11_state *cpustate, UINT16 op);
+static void movb_ind_ixd(t11_state *cpustate, UINT16 op);
+static void movb_de_rg(t11_state *cpustate, UINT16 op);
+static void movb_de_rgd(t11_state *cpustate, UINT16 op);
+static void movb_de_in(t11_state *cpustate, UINT16 op);
+static void movb_de_ind(t11_state *cpustate, UINT16 op);
+static void movb_de_de(t11_state *cpustate, UINT16 op);
+static void movb_de_ded(t11_state *cpustate, UINT16 op);
+static void movb_de_ix(t11_state *cpustate, UINT16 op);
+static void movb_de_ixd(t11_state *cpustate, UINT16 op);
+static void movb_ded_rg(t11_state *cpustate, UINT16 op);
+static void movb_ded_rgd(t11_state *cpustate, UINT16 op);
+static void movb_ded_in(t11_state *cpustate, UINT16 op);
+static void movb_ded_ind(t11_state *cpustate, UINT16 op);
+static void movb_ded_de(t11_state *cpustate, UINT16 op);
+static void movb_ded_ded(t11_state *cpustate, UINT16 op);
+static void movb_ded_ix(t11_state *cpustate, UINT16 op);
+static void movb_ded_ixd(t11_state *cpustate, UINT16 op);
+static void movb_ix_rg(t11_state *cpustate, UINT16 op);
+static void movb_ix_rgd(t11_state *cpustate, UINT16 op);
+static void movb_ix_in(t11_state *cpustate, UINT16 op);
+static void movb_ix_ind(t11_state *cpustate, UINT16 op);
+static void movb_ix_de(t11_state *cpustate, UINT16 op);
+static void movb_ix_ded(t11_state *cpustate, UINT16 op);
+static void movb_ix_ix(t11_state *cpustate, UINT16 op);
+static void movb_ix_ixd(t11_state *cpustate, UINT16 op);
+static void movb_ixd_rg(t11_state *cpustate, UINT16 op);
+static void movb_ixd_rgd(t11_state *cpustate, UINT16 op);
+static void movb_ixd_in(t11_state *cpustate, UINT16 op);
+static void movb_ixd_ind(t11_state *cpustate, UINT16 op);
+static void movb_ixd_de(t11_state *cpustate, UINT16 op);
+static void movb_ixd_ded(t11_state *cpustate, UINT16 op);
+static void movb_ixd_ix(t11_state *cpustate, UINT16 op);
+static void movb_ixd_ixd(t11_state *cpustate, UINT16 op);
+
+static void cmpb_rg_rg(t11_state *cpustate, UINT16 op);
+static void cmpb_rg_rgd(t11_state *cpustate, UINT16 op);
+static void cmpb_rg_in(t11_state *cpustate, UINT16 op);
+static void cmpb_rg_ind(t11_state *cpustate, UINT16 op);
+static void cmpb_rg_de(t11_state *cpustate, UINT16 op);
+static void cmpb_rg_ded(t11_state *cpustate, UINT16 op);
+static void cmpb_rg_ix(t11_state *cpustate, UINT16 op);
+static void cmpb_rg_ixd(t11_state *cpustate, UINT16 op);
+static void cmpb_rgd_rg(t11_state *cpustate, UINT16 op);
+static void cmpb_rgd_rgd(t11_state *cpustate, UINT16 op);
+static void cmpb_rgd_in(t11_state *cpustate, UINT16 op);
+static void cmpb_rgd_ind(t11_state *cpustate, UINT16 op);
+static void cmpb_rgd_de(t11_state *cpustate, UINT16 op);
+static void cmpb_rgd_ded(t11_state *cpustate, UINT16 op);
+static void cmpb_rgd_ix(t11_state *cpustate, UINT16 op);
+static void cmpb_rgd_ixd(t11_state *cpustate, UINT16 op);
+static void cmpb_in_rg(t11_state *cpustate, UINT16 op);
+static void cmpb_in_rgd(t11_state *cpustate, UINT16 op);
+static void cmpb_in_in(t11_state *cpustate, UINT16 op);
+static void cmpb_in_ind(t11_state *cpustate, UINT16 op);
+static void cmpb_in_de(t11_state *cpustate, UINT16 op);
+static void cmpb_in_ded(t11_state *cpustate, UINT16 op);
+static void cmpb_in_ix(t11_state *cpustate, UINT16 op);
+static void cmpb_in_ixd(t11_state *cpustate, UINT16 op);
+static void cmpb_ind_rg(t11_state *cpustate, UINT16 op);
+static void cmpb_ind_rgd(t11_state *cpustate, UINT16 op);
+static void cmpb_ind_in(t11_state *cpustate, UINT16 op);
+static void cmpb_ind_ind(t11_state *cpustate, UINT16 op);
+static void cmpb_ind_de(t11_state *cpustate, UINT16 op);
+static void cmpb_ind_ded(t11_state *cpustate, UINT16 op);
+static void cmpb_ind_ix(t11_state *cpustate, UINT16 op);
+static void cmpb_ind_ixd(t11_state *cpustate, UINT16 op);
+static void cmpb_de_rg(t11_state *cpustate, UINT16 op);
+static void cmpb_de_rgd(t11_state *cpustate, UINT16 op);
+static void cmpb_de_in(t11_state *cpustate, UINT16 op);
+static void cmpb_de_ind(t11_state *cpustate, UINT16 op);
+static void cmpb_de_de(t11_state *cpustate, UINT16 op);
+static void cmpb_de_ded(t11_state *cpustate, UINT16 op);
+static void cmpb_de_ix(t11_state *cpustate, UINT16 op);
+static void cmpb_de_ixd(t11_state *cpustate, UINT16 op);
+static void cmpb_ded_rg(t11_state *cpustate, UINT16 op);
+static void cmpb_ded_rgd(t11_state *cpustate, UINT16 op);
+static void cmpb_ded_in(t11_state *cpustate, UINT16 op);
+static void cmpb_ded_ind(t11_state *cpustate, UINT16 op);
+static void cmpb_ded_de(t11_state *cpustate, UINT16 op);
+static void cmpb_ded_ded(t11_state *cpustate, UINT16 op);
+static void cmpb_ded_ix(t11_state *cpustate, UINT16 op);
+static void cmpb_ded_ixd(t11_state *cpustate, UINT16 op);
+static void cmpb_ix_rg(t11_state *cpustate, UINT16 op);
+static void cmpb_ix_rgd(t11_state *cpustate, UINT16 op);
+static void cmpb_ix_in(t11_state *cpustate, UINT16 op);
+static void cmpb_ix_ind(t11_state *cpustate, UINT16 op);
+static void cmpb_ix_de(t11_state *cpustate, UINT16 op);
+static void cmpb_ix_ded(t11_state *cpustate, UINT16 op);
+static void cmpb_ix_ix(t11_state *cpustate, UINT16 op);
+static void cmpb_ix_ixd(t11_state *cpustate, UINT16 op);
+static void cmpb_ixd_rg(t11_state *cpustate, UINT16 op);
+static void cmpb_ixd_rgd(t11_state *cpustate, UINT16 op);
+static void cmpb_ixd_in(t11_state *cpustate, UINT16 op);
+static void cmpb_ixd_ind(t11_state *cpustate, UINT16 op);
+static void cmpb_ixd_de(t11_state *cpustate, UINT16 op);
+static void cmpb_ixd_ded(t11_state *cpustate, UINT16 op);
+static void cmpb_ixd_ix(t11_state *cpustate, UINT16 op);
+static void cmpb_ixd_ixd(t11_state *cpustate, UINT16 op);
+
+static void bitb_rg_rg(t11_state *cpustate, UINT16 op);
+static void bitb_rg_rgd(t11_state *cpustate, UINT16 op);
+static void bitb_rg_in(t11_state *cpustate, UINT16 op);
+static void bitb_rg_ind(t11_state *cpustate, UINT16 op);
+static void bitb_rg_de(t11_state *cpustate, UINT16 op);
+static void bitb_rg_ded(t11_state *cpustate, UINT16 op);
+static void bitb_rg_ix(t11_state *cpustate, UINT16 op);
+static void bitb_rg_ixd(t11_state *cpustate, UINT16 op);
+static void bitb_rgd_rg(t11_state *cpustate, UINT16 op);
+static void bitb_rgd_rgd(t11_state *cpustate, UINT16 op);
+static void bitb_rgd_in(t11_state *cpustate, UINT16 op);
+static void bitb_rgd_ind(t11_state *cpustate, UINT16 op);
+static void bitb_rgd_de(t11_state *cpustate, UINT16 op);
+static void bitb_rgd_ded(t11_state *cpustate, UINT16 op);
+static void bitb_rgd_ix(t11_state *cpustate, UINT16 op);
+static void bitb_rgd_ixd(t11_state *cpustate, UINT16 op);
+static void bitb_in_rg(t11_state *cpustate, UINT16 op);
+static void bitb_in_rgd(t11_state *cpustate, UINT16 op);
+static void bitb_in_in(t11_state *cpustate, UINT16 op);
+static void bitb_in_ind(t11_state *cpustate, UINT16 op);
+static void bitb_in_de(t11_state *cpustate, UINT16 op);
+static void bitb_in_ded(t11_state *cpustate, UINT16 op);
+static void bitb_in_ix(t11_state *cpustate, UINT16 op);
+static void bitb_in_ixd(t11_state *cpustate, UINT16 op);
+static void bitb_ind_rg(t11_state *cpustate, UINT16 op);
+static void bitb_ind_rgd(t11_state *cpustate, UINT16 op);
+static void bitb_ind_in(t11_state *cpustate, UINT16 op);
+static void bitb_ind_ind(t11_state *cpustate, UINT16 op);
+static void bitb_ind_de(t11_state *cpustate, UINT16 op);
+static void bitb_ind_ded(t11_state *cpustate, UINT16 op);
+static void bitb_ind_ix(t11_state *cpustate, UINT16 op);
+static void bitb_ind_ixd(t11_state *cpustate, UINT16 op);
+static void bitb_de_rg(t11_state *cpustate, UINT16 op);
+static void bitb_de_rgd(t11_state *cpustate, UINT16 op);
+static void bitb_de_in(t11_state *cpustate, UINT16 op);
+static void bitb_de_ind(t11_state *cpustate, UINT16 op);
+static void bitb_de_de(t11_state *cpustate, UINT16 op);
+static void bitb_de_ded(t11_state *cpustate, UINT16 op);
+static void bitb_de_ix(t11_state *cpustate, UINT16 op);
+static void bitb_de_ixd(t11_state *cpustate, UINT16 op);
+static void bitb_ded_rg(t11_state *cpustate, UINT16 op);
+static void bitb_ded_rgd(t11_state *cpustate, UINT16 op);
+static void bitb_ded_in(t11_state *cpustate, UINT16 op);
+static void bitb_ded_ind(t11_state *cpustate, UINT16 op);
+static void bitb_ded_de(t11_state *cpustate, UINT16 op);
+static void bitb_ded_ded(t11_state *cpustate, UINT16 op);
+static void bitb_ded_ix(t11_state *cpustate, UINT16 op);
+static void bitb_ded_ixd(t11_state *cpustate, UINT16 op);
+static void bitb_ix_rg(t11_state *cpustate, UINT16 op);
+static void bitb_ix_rgd(t11_state *cpustate, UINT16 op);
+static void bitb_ix_in(t11_state *cpustate, UINT16 op);
+static void bitb_ix_ind(t11_state *cpustate, UINT16 op);
+static void bitb_ix_de(t11_state *cpustate, UINT16 op);
+static void bitb_ix_ded(t11_state *cpustate, UINT16 op);
+static void bitb_ix_ix(t11_state *cpustate, UINT16 op);
+static void bitb_ix_ixd(t11_state *cpustate, UINT16 op);
+static void bitb_ixd_rg(t11_state *cpustate, UINT16 op);
+static void bitb_ixd_rgd(t11_state *cpustate, UINT16 op);
+static void bitb_ixd_in(t11_state *cpustate, UINT16 op);
+static void bitb_ixd_ind(t11_state *cpustate, UINT16 op);
+static void bitb_ixd_de(t11_state *cpustate, UINT16 op);
+static void bitb_ixd_ded(t11_state *cpustate, UINT16 op);
+static void bitb_ixd_ix(t11_state *cpustate, UINT16 op);
+static void bitb_ixd_ixd(t11_state *cpustate, UINT16 op);
+
+static void bicb_rg_rg(t11_state *cpustate, UINT16 op);
+static void bicb_rg_rgd(t11_state *cpustate, UINT16 op);
+static void bicb_rg_in(t11_state *cpustate, UINT16 op);
+static void bicb_rg_ind(t11_state *cpustate, UINT16 op);
+static void bicb_rg_de(t11_state *cpustate, UINT16 op);
+static void bicb_rg_ded(t11_state *cpustate, UINT16 op);
+static void bicb_rg_ix(t11_state *cpustate, UINT16 op);
+static void bicb_rg_ixd(t11_state *cpustate, UINT16 op);
+static void bicb_rgd_rg(t11_state *cpustate, UINT16 op);
+static void bicb_rgd_rgd(t11_state *cpustate, UINT16 op);
+static void bicb_rgd_in(t11_state *cpustate, UINT16 op);
+static void bicb_rgd_ind(t11_state *cpustate, UINT16 op);
+static void bicb_rgd_de(t11_state *cpustate, UINT16 op);
+static void bicb_rgd_ded(t11_state *cpustate, UINT16 op);
+static void bicb_rgd_ix(t11_state *cpustate, UINT16 op);
+static void bicb_rgd_ixd(t11_state *cpustate, UINT16 op);
+static void bicb_in_rg(t11_state *cpustate, UINT16 op);
+static void bicb_in_rgd(t11_state *cpustate, UINT16 op);
+static void bicb_in_in(t11_state *cpustate, UINT16 op);
+static void bicb_in_ind(t11_state *cpustate, UINT16 op);
+static void bicb_in_de(t11_state *cpustate, UINT16 op);
+static void bicb_in_ded(t11_state *cpustate, UINT16 op);
+static void bicb_in_ix(t11_state *cpustate, UINT16 op);
+static void bicb_in_ixd(t11_state *cpustate, UINT16 op);
+static void bicb_ind_rg(t11_state *cpustate, UINT16 op);
+static void bicb_ind_rgd(t11_state *cpustate, UINT16 op);
+static void bicb_ind_in(t11_state *cpustate, UINT16 op);
+static void bicb_ind_ind(t11_state *cpustate, UINT16 op);
+static void bicb_ind_de(t11_state *cpustate, UINT16 op);
+static void bicb_ind_ded(t11_state *cpustate, UINT16 op);
+static void bicb_ind_ix(t11_state *cpustate, UINT16 op);
+static void bicb_ind_ixd(t11_state *cpustate, UINT16 op);
+static void bicb_de_rg(t11_state *cpustate, UINT16 op);
+static void bicb_de_rgd(t11_state *cpustate, UINT16 op);
+static void bicb_de_in(t11_state *cpustate, UINT16 op);
+static void bicb_de_ind(t11_state *cpustate, UINT16 op);
+static void bicb_de_de(t11_state *cpustate, UINT16 op);
+static void bicb_de_ded(t11_state *cpustate, UINT16 op);
+static void bicb_de_ix(t11_state *cpustate, UINT16 op);
+static void bicb_de_ixd(t11_state *cpustate, UINT16 op);
+static void bicb_ded_rg(t11_state *cpustate, UINT16 op);
+static void bicb_ded_rgd(t11_state *cpustate, UINT16 op);
+static void bicb_ded_in(t11_state *cpustate, UINT16 op);
+static void bicb_ded_ind(t11_state *cpustate, UINT16 op);
+static void bicb_ded_de(t11_state *cpustate, UINT16 op);
+static void bicb_ded_ded(t11_state *cpustate, UINT16 op);
+static void bicb_ded_ix(t11_state *cpustate, UINT16 op);
+static void bicb_ded_ixd(t11_state *cpustate, UINT16 op);
+static void bicb_ix_rg(t11_state *cpustate, UINT16 op);
+static void bicb_ix_rgd(t11_state *cpustate, UINT16 op);
+static void bicb_ix_in(t11_state *cpustate, UINT16 op);
+static void bicb_ix_ind(t11_state *cpustate, UINT16 op);
+static void bicb_ix_de(t11_state *cpustate, UINT16 op);
+static void bicb_ix_ded(t11_state *cpustate, UINT16 op);
+static void bicb_ix_ix(t11_state *cpustate, UINT16 op);
+static void bicb_ix_ixd(t11_state *cpustate, UINT16 op);
+static void bicb_ixd_rg(t11_state *cpustate, UINT16 op);
+static void bicb_ixd_rgd(t11_state *cpustate, UINT16 op);
+static void bicb_ixd_in(t11_state *cpustate, UINT16 op);
+static void bicb_ixd_ind(t11_state *cpustate, UINT16 op);
+static void bicb_ixd_de(t11_state *cpustate, UINT16 op);
+static void bicb_ixd_ded(t11_state *cpustate, UINT16 op);
+static void bicb_ixd_ix(t11_state *cpustate, UINT16 op);
+static void bicb_ixd_ixd(t11_state *cpustate, UINT16 op);
+
+static void bisb_rg_rg(t11_state *cpustate, UINT16 op);
+static void bisb_rg_rgd(t11_state *cpustate, UINT16 op);
+static void bisb_rg_in(t11_state *cpustate, UINT16 op);
+static void bisb_rg_ind(t11_state *cpustate, UINT16 op);
+static void bisb_rg_de(t11_state *cpustate, UINT16 op);
+static void bisb_rg_ded(t11_state *cpustate, UINT16 op);
+static void bisb_rg_ix(t11_state *cpustate, UINT16 op);
+static void bisb_rg_ixd(t11_state *cpustate, UINT16 op);
+static void bisb_rgd_rg(t11_state *cpustate, UINT16 op);
+static void bisb_rgd_rgd(t11_state *cpustate, UINT16 op);
+static void bisb_rgd_in(t11_state *cpustate, UINT16 op);
+static void bisb_rgd_ind(t11_state *cpustate, UINT16 op);
+static void bisb_rgd_de(t11_state *cpustate, UINT16 op);
+static void bisb_rgd_ded(t11_state *cpustate, UINT16 op);
+static void bisb_rgd_ix(t11_state *cpustate, UINT16 op);
+static void bisb_rgd_ixd(t11_state *cpustate, UINT16 op);
+static void bisb_in_rg(t11_state *cpustate, UINT16 op);
+static void bisb_in_rgd(t11_state *cpustate, UINT16 op);
+static void bisb_in_in(t11_state *cpustate, UINT16 op);
+static void bisb_in_ind(t11_state *cpustate, UINT16 op);
+static void bisb_in_de(t11_state *cpustate, UINT16 op);
+static void bisb_in_ded(t11_state *cpustate, UINT16 op);
+static void bisb_in_ix(t11_state *cpustate, UINT16 op);
+static void bisb_in_ixd(t11_state *cpustate, UINT16 op);
+static void bisb_ind_rg(t11_state *cpustate, UINT16 op);
+static void bisb_ind_rgd(t11_state *cpustate, UINT16 op);
+static void bisb_ind_in(t11_state *cpustate, UINT16 op);
+static void bisb_ind_ind(t11_state *cpustate, UINT16 op);
+static void bisb_ind_de(t11_state *cpustate, UINT16 op);
+static void bisb_ind_ded(t11_state *cpustate, UINT16 op);
+static void bisb_ind_ix(t11_state *cpustate, UINT16 op);
+static void bisb_ind_ixd(t11_state *cpustate, UINT16 op);
+static void bisb_de_rg(t11_state *cpustate, UINT16 op);
+static void bisb_de_rgd(t11_state *cpustate, UINT16 op);
+static void bisb_de_in(t11_state *cpustate, UINT16 op);
+static void bisb_de_ind(t11_state *cpustate, UINT16 op);
+static void bisb_de_de(t11_state *cpustate, UINT16 op);
+static void bisb_de_ded(t11_state *cpustate, UINT16 op);
+static void bisb_de_ix(t11_state *cpustate, UINT16 op);
+static void bisb_de_ixd(t11_state *cpustate, UINT16 op);
+static void bisb_ded_rg(t11_state *cpustate, UINT16 op);
+static void bisb_ded_rgd(t11_state *cpustate, UINT16 op);
+static void bisb_ded_in(t11_state *cpustate, UINT16 op);
+static void bisb_ded_ind(t11_state *cpustate, UINT16 op);
+static void bisb_ded_de(t11_state *cpustate, UINT16 op);
+static void bisb_ded_ded(t11_state *cpustate, UINT16 op);
+static void bisb_ded_ix(t11_state *cpustate, UINT16 op);
+static void bisb_ded_ixd(t11_state *cpustate, UINT16 op);
+static void bisb_ix_rg(t11_state *cpustate, UINT16 op);
+static void bisb_ix_rgd(t11_state *cpustate, UINT16 op);
+static void bisb_ix_in(t11_state *cpustate, UINT16 op);
+static void bisb_ix_ind(t11_state *cpustate, UINT16 op);
+static void bisb_ix_de(t11_state *cpustate, UINT16 op);
+static void bisb_ix_ded(t11_state *cpustate, UINT16 op);
+static void bisb_ix_ix(t11_state *cpustate, UINT16 op);
+static void bisb_ix_ixd(t11_state *cpustate, UINT16 op);
+static void bisb_ixd_rg(t11_state *cpustate, UINT16 op);
+static void bisb_ixd_rgd(t11_state *cpustate, UINT16 op);
+static void bisb_ixd_in(t11_state *cpustate, UINT16 op);
+static void bisb_ixd_ind(t11_state *cpustate, UINT16 op);
+static void bisb_ixd_de(t11_state *cpustate, UINT16 op);
+static void bisb_ixd_ded(t11_state *cpustate, UINT16 op);
+static void bisb_ixd_ix(t11_state *cpustate, UINT16 op);
+static void bisb_ixd_ixd(t11_state *cpustate, UINT16 op);
+
+static void sub_rg_rg(t11_state *cpustate, UINT16 op);
+static void sub_rg_rgd(t11_state *cpustate, UINT16 op);
+static void sub_rg_in(t11_state *cpustate, UINT16 op);
+static void sub_rg_ind(t11_state *cpustate, UINT16 op);
+static void sub_rg_de(t11_state *cpustate, UINT16 op);
+static void sub_rg_ded(t11_state *cpustate, UINT16 op);
+static void sub_rg_ix(t11_state *cpustate, UINT16 op);
+static void sub_rg_ixd(t11_state *cpustate, UINT16 op);
+static void sub_rgd_rg(t11_state *cpustate, UINT16 op);
+static void sub_rgd_rgd(t11_state *cpustate, UINT16 op);
+static void sub_rgd_in(t11_state *cpustate, UINT16 op);
+static void sub_rgd_ind(t11_state *cpustate, UINT16 op);
+static void sub_rgd_de(t11_state *cpustate, UINT16 op);
+static void sub_rgd_ded(t11_state *cpustate, UINT16 op);
+static void sub_rgd_ix(t11_state *cpustate, UINT16 op);
+static void sub_rgd_ixd(t11_state *cpustate, UINT16 op);
+static void sub_in_rg(t11_state *cpustate, UINT16 op);
+static void sub_in_rgd(t11_state *cpustate, UINT16 op);
+static void sub_in_in(t11_state *cpustate, UINT16 op);
+static void sub_in_ind(t11_state *cpustate, UINT16 op);
+static void sub_in_de(t11_state *cpustate, UINT16 op);
+static void sub_in_ded(t11_state *cpustate, UINT16 op);
+static void sub_in_ix(t11_state *cpustate, UINT16 op);
+static void sub_in_ixd(t11_state *cpustate, UINT16 op);
+static void sub_ind_rg(t11_state *cpustate, UINT16 op);
+static void sub_ind_rgd(t11_state *cpustate, UINT16 op);
+static void sub_ind_in(t11_state *cpustate, UINT16 op);
+static void sub_ind_ind(t11_state *cpustate, UINT16 op);
+static void sub_ind_de(t11_state *cpustate, UINT16 op);
+static void sub_ind_ded(t11_state *cpustate, UINT16 op);
+static void sub_ind_ix(t11_state *cpustate, UINT16 op);
+static void sub_ind_ixd(t11_state *cpustate, UINT16 op);
+static void sub_de_rg(t11_state *cpustate, UINT16 op);
+static void sub_de_rgd(t11_state *cpustate, UINT16 op);
+static void sub_de_in(t11_state *cpustate, UINT16 op);
+static void sub_de_ind(t11_state *cpustate, UINT16 op);
+static void sub_de_de(t11_state *cpustate, UINT16 op);
+static void sub_de_ded(t11_state *cpustate, UINT16 op);
+static void sub_de_ix(t11_state *cpustate, UINT16 op);
+static void sub_de_ixd(t11_state *cpustate, UINT16 op);
+static void sub_ded_rg(t11_state *cpustate, UINT16 op);
+static void sub_ded_rgd(t11_state *cpustate, UINT16 op);
+static void sub_ded_in(t11_state *cpustate, UINT16 op);
+static void sub_ded_ind(t11_state *cpustate, UINT16 op);
+static void sub_ded_de(t11_state *cpustate, UINT16 op);
+static void sub_ded_ded(t11_state *cpustate, UINT16 op);
+static void sub_ded_ix(t11_state *cpustate, UINT16 op);
+static void sub_ded_ixd(t11_state *cpustate, UINT16 op);
+static void sub_ix_rg(t11_state *cpustate, UINT16 op);
+static void sub_ix_rgd(t11_state *cpustate, UINT16 op);
+static void sub_ix_in(t11_state *cpustate, UINT16 op);
+static void sub_ix_ind(t11_state *cpustate, UINT16 op);
+static void sub_ix_de(t11_state *cpustate, UINT16 op);
+static void sub_ix_ded(t11_state *cpustate, UINT16 op);
+static void sub_ix_ix(t11_state *cpustate, UINT16 op);
+static void sub_ix_ixd(t11_state *cpustate, UINT16 op);
+static void sub_ixd_rg(t11_state *cpustate, UINT16 op);
+static void sub_ixd_rgd(t11_state *cpustate, UINT16 op);
+static void sub_ixd_in(t11_state *cpustate, UINT16 op);
+static void sub_ixd_ind(t11_state *cpustate, UINT16 op);
+static void sub_ixd_de(t11_state *cpustate, UINT16 op);
+static void sub_ixd_ded(t11_state *cpustate, UINT16 op);
+static void sub_ixd_ix(t11_state *cpustate, UINT16 op);
+static void sub_ixd_ixd(t11_state *cpustate, UINT16 op);
+
+
+
+static void (*const opcode_table[65536 >> 3])(t11_state *cpustate, UINT16 op) =
+{
+ /* 0x0000 */
+ op_0000, halt, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, jmp_rgd, jmp_in, jmp_ind, jmp_de, jmp_ded, jmp_ix, jmp_ixd,
+ rts, illegal, illegal, illegal, ccc, ccc, scc, scc,
+ swab_rg, swab_rgd, swab_in, swab_ind, swab_de, swab_ded, swab_ix, swab_ixd,
+ /* 0x0100 */
+ br, br, br, br, br, br, br, br,
+ br, br, br, br, br, br, br, br,
+ br, br, br, br, br, br, br, br,
+ br, br, br, br, br, br, br, br,
+ /* 0x0200 */
+ bne, bne, bne, bne, bne, bne, bne, bne,
+ bne, bne, bne, bne, bne, bne, bne, bne,
+ bne, bne, bne, bne, bne, bne, bne, bne,
+ bne, bne, bne, bne, bne, bne, bne, bne,
+ /* 0x0300 */
+ beq, beq, beq, beq, beq, beq, beq, beq,
+ beq, beq, beq, beq, beq, beq, beq, beq,
+ beq, beq, beq, beq, beq, beq, beq, beq,
+ beq, beq, beq, beq, beq, beq, beq, beq,
+ /* 0x0400 */
+ bge, bge, bge, bge, bge, bge, bge, bge,
+ bge, bge, bge, bge, bge, bge, bge, bge,
+ bge, bge, bge, bge, bge, bge, bge, bge,
+ bge, bge, bge, bge, bge, bge, bge, bge,
+ /* 0x0500 */
+ blt, blt, blt, blt, blt, blt, blt, blt,
+ blt, blt, blt, blt, blt, blt, blt, blt,
+ blt, blt, blt, blt, blt, blt, blt, blt,
+ blt, blt, blt, blt, blt, blt, blt, blt,
+ /* 0x0600 */
+ bgt, bgt, bgt, bgt, bgt, bgt, bgt, bgt,
+ bgt, bgt, bgt, bgt, bgt, bgt, bgt, bgt,
+ bgt, bgt, bgt, bgt, bgt, bgt, bgt, bgt,
+ bgt, bgt, bgt, bgt, bgt, bgt, bgt, bgt,
+ /* 0x0700 */
+ ble, ble, ble, ble, ble, ble, ble, ble,
+ ble, ble, ble, ble, ble, ble, ble, ble,
+ ble, ble, ble, ble, ble, ble, ble, ble,
+ ble, ble, ble, ble, ble, ble, ble, ble,
+ /* 0x0800 */
+ illegal, jsr_rgd, jsr_in, jsr_ind, jsr_de, jsr_ded, jsr_ix, jsr_ixd,
+ illegal, jsr_rgd, jsr_in, jsr_ind, jsr_de, jsr_ded, jsr_ix, jsr_ixd,
+ illegal, jsr_rgd, jsr_in, jsr_ind, jsr_de, jsr_ded, jsr_ix, jsr_ixd,
+ illegal, jsr_rgd, jsr_in, jsr_ind, jsr_de, jsr_ded, jsr_ix, jsr_ixd,
+ /* 0x0900 */
+ illegal, jsr_rgd, jsr_in, jsr_ind, jsr_de, jsr_ded, jsr_ix, jsr_ixd,
+ illegal, jsr_rgd, jsr_in, jsr_ind, jsr_de, jsr_ded, jsr_ix, jsr_ixd,
+ illegal, jsr_rgd, jsr_in, jsr_ind, jsr_de, jsr_ded, jsr_ix, jsr_ixd,
+ illegal, jsr_rgd, jsr_in, jsr_ind, jsr_de, jsr_ded, jsr_ix, jsr_ixd,
+ /* 0x0a00 */
+ clr_rg, clr_rgd, clr_in, clr_ind, clr_de, clr_ded, clr_ix, clr_ixd,
+ com_rg, com_rgd, com_in, com_ind, com_de, com_ded, com_ix, com_ixd,
+ inc_rg, inc_rgd, inc_in, inc_ind, inc_de, inc_ded, inc_ix, inc_ixd,
+ dec_rg, dec_rgd, dec_in, dec_ind, dec_de, dec_ded, dec_ix, dec_ixd,
+ /* 0x0b00 */
+ neg_rg, neg_rgd, neg_in, neg_ind, neg_de, neg_ded, neg_ix, neg_ixd,
+ adc_rg, adc_rgd, adc_in, adc_ind, adc_de, adc_ded, adc_ix, adc_ixd,
+ sbc_rg, sbc_rgd, sbc_in, sbc_ind, sbc_de, sbc_ded, sbc_ix, sbc_ixd,
+ tst_rg, tst_rgd, tst_in, tst_ind, tst_de, tst_ded, tst_ix, tst_ixd,
+ /* 0x0c00 */
+ ror_rg, ror_rgd, ror_in, ror_ind, ror_de, ror_ded, ror_ix, ror_ixd,
+ rol_rg, rol_rgd, rol_in, rol_ind, rol_de, rol_ded, rol_ix, rol_ixd,
+ asr_rg, asr_rgd, asr_in, asr_ind, asr_de, asr_ded, asr_ix, asr_ixd,
+ asl_rg, asl_rgd, asl_in, asl_ind, asl_de, asl_ded, asl_ix, asl_ixd,
+ /* 0x0d00 */
+ mark, mark, mark, mark, mark, mark, mark, mark,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ sxt_rg, sxt_rgd, sxt_in, sxt_ind, sxt_de, sxt_ded, sxt_ix, sxt_ixd,
+ /* 0x0e00 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0x0f00 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+
+ /* 0x1000 */
+ mov_rg_rg, mov_rg_rgd, mov_rg_in, mov_rg_ind, mov_rg_de, mov_rg_ded, mov_rg_ix, mov_rg_ixd,
+ mov_rg_rg, mov_rg_rgd, mov_rg_in, mov_rg_ind, mov_rg_de, mov_rg_ded, mov_rg_ix, mov_rg_ixd,
+ mov_rg_rg, mov_rg_rgd, mov_rg_in, mov_rg_ind, mov_rg_de, mov_rg_ded, mov_rg_ix, mov_rg_ixd,
+ mov_rg_rg, mov_rg_rgd, mov_rg_in, mov_rg_ind, mov_rg_de, mov_rg_ded, mov_rg_ix, mov_rg_ixd,
+ /* 0x1100 */
+ mov_rg_rg, mov_rg_rgd, mov_rg_in, mov_rg_ind, mov_rg_de, mov_rg_ded, mov_rg_ix, mov_rg_ixd,
+ mov_rg_rg, mov_rg_rgd, mov_rg_in, mov_rg_ind, mov_rg_de, mov_rg_ded, mov_rg_ix, mov_rg_ixd,
+ mov_rg_rg, mov_rg_rgd, mov_rg_in, mov_rg_ind, mov_rg_de, mov_rg_ded, mov_rg_ix, mov_rg_ixd,
+ mov_rg_rg, mov_rg_rgd, mov_rg_in, mov_rg_ind, mov_rg_de, mov_rg_ded, mov_rg_ix, mov_rg_ixd,
+ /* 0x1200 */
+ mov_rgd_rg, mov_rgd_rgd,mov_rgd_in, mov_rgd_ind,mov_rgd_de, mov_rgd_ded,mov_rgd_ix, mov_rgd_ixd,
+ mov_rgd_rg, mov_rgd_rgd,mov_rgd_in, mov_rgd_ind,mov_rgd_de, mov_rgd_ded,mov_rgd_ix, mov_rgd_ixd,
+ mov_rgd_rg, mov_rgd_rgd,mov_rgd_in, mov_rgd_ind,mov_rgd_de, mov_rgd_ded,mov_rgd_ix, mov_rgd_ixd,
+ mov_rgd_rg, mov_rgd_rgd,mov_rgd_in, mov_rgd_ind,mov_rgd_de, mov_rgd_ded,mov_rgd_ix, mov_rgd_ixd,
+ /* 0x1300 */
+ mov_rgd_rg, mov_rgd_rgd,mov_rgd_in, mov_rgd_ind,mov_rgd_de, mov_rgd_ded,mov_rgd_ix, mov_rgd_ixd,
+ mov_rgd_rg, mov_rgd_rgd,mov_rgd_in, mov_rgd_ind,mov_rgd_de, mov_rgd_ded,mov_rgd_ix, mov_rgd_ixd,
+ mov_rgd_rg, mov_rgd_rgd,mov_rgd_in, mov_rgd_ind,mov_rgd_de, mov_rgd_ded,mov_rgd_ix, mov_rgd_ixd,
+ mov_rgd_rg, mov_rgd_rgd,mov_rgd_in, mov_rgd_ind,mov_rgd_de, mov_rgd_ded,mov_rgd_ix, mov_rgd_ixd,
+ /* 0x1400 */
+ mov_in_rg, mov_in_rgd, mov_in_in, mov_in_ind, mov_in_de, mov_in_ded, mov_in_ix, mov_in_ixd,
+ mov_in_rg, mov_in_rgd, mov_in_in, mov_in_ind, mov_in_de, mov_in_ded, mov_in_ix, mov_in_ixd,
+ mov_in_rg, mov_in_rgd, mov_in_in, mov_in_ind, mov_in_de, mov_in_ded, mov_in_ix, mov_in_ixd,
+ mov_in_rg, mov_in_rgd, mov_in_in, mov_in_ind, mov_in_de, mov_in_ded, mov_in_ix, mov_in_ixd,
+ /* 0x1500 */
+ mov_in_rg, mov_in_rgd, mov_in_in, mov_in_ind, mov_in_de, mov_in_ded, mov_in_ix, mov_in_ixd,
+ mov_in_rg, mov_in_rgd, mov_in_in, mov_in_ind, mov_in_de, mov_in_ded, mov_in_ix, mov_in_ixd,
+ mov_in_rg, mov_in_rgd, mov_in_in, mov_in_ind, mov_in_de, mov_in_ded, mov_in_ix, mov_in_ixd,
+ mov_in_rg, mov_in_rgd, mov_in_in, mov_in_ind, mov_in_de, mov_in_ded, mov_in_ix, mov_in_ixd,
+ /* 0x1600 */
+ mov_ind_rg, mov_ind_rgd,mov_ind_in, mov_ind_ind,mov_ind_de, mov_ind_ded,mov_ind_ix, mov_ind_ixd,
+ mov_ind_rg, mov_ind_rgd,mov_ind_in, mov_ind_ind,mov_ind_de, mov_ind_ded,mov_ind_ix, mov_ind_ixd,
+ mov_ind_rg, mov_ind_rgd,mov_ind_in, mov_ind_ind,mov_ind_de, mov_ind_ded,mov_ind_ix, mov_ind_ixd,
+ mov_ind_rg, mov_ind_rgd,mov_ind_in, mov_ind_ind,mov_ind_de, mov_ind_ded,mov_ind_ix, mov_ind_ixd,
+ /* 0x1700 */
+ mov_ind_rg, mov_ind_rgd,mov_ind_in, mov_ind_ind,mov_ind_de, mov_ind_ded,mov_ind_ix, mov_ind_ixd,
+ mov_ind_rg, mov_ind_rgd,mov_ind_in, mov_ind_ind,mov_ind_de, mov_ind_ded,mov_ind_ix, mov_ind_ixd,
+ mov_ind_rg, mov_ind_rgd,mov_ind_in, mov_ind_ind,mov_ind_de, mov_ind_ded,mov_ind_ix, mov_ind_ixd,
+ mov_ind_rg, mov_ind_rgd,mov_ind_in, mov_ind_ind,mov_ind_de, mov_ind_ded,mov_ind_ix, mov_ind_ixd,
+ /* 0x1800 */
+ mov_de_rg, mov_de_rgd, mov_de_in, mov_de_ind, mov_de_de, mov_de_ded, mov_de_ix, mov_de_ixd,
+ mov_de_rg, mov_de_rgd, mov_de_in, mov_de_ind, mov_de_de, mov_de_ded, mov_de_ix, mov_de_ixd,
+ mov_de_rg, mov_de_rgd, mov_de_in, mov_de_ind, mov_de_de, mov_de_ded, mov_de_ix, mov_de_ixd,
+ mov_de_rg, mov_de_rgd, mov_de_in, mov_de_ind, mov_de_de, mov_de_ded, mov_de_ix, mov_de_ixd,
+ /* 0x1900 */
+ mov_de_rg, mov_de_rgd, mov_de_in, mov_de_ind, mov_de_de, mov_de_ded, mov_de_ix, mov_de_ixd,
+ mov_de_rg, mov_de_rgd, mov_de_in, mov_de_ind, mov_de_de, mov_de_ded, mov_de_ix, mov_de_ixd,
+ mov_de_rg, mov_de_rgd, mov_de_in, mov_de_ind, mov_de_de, mov_de_ded, mov_de_ix, mov_de_ixd,
+ mov_de_rg, mov_de_rgd, mov_de_in, mov_de_ind, mov_de_de, mov_de_ded, mov_de_ix, mov_de_ixd,
+ /* 0x1a00 */
+ mov_ded_rg, mov_ded_rgd,mov_ded_in, mov_ded_ind,mov_ded_de, mov_ded_ded,mov_ded_ix, mov_ded_ixd,
+ mov_ded_rg, mov_ded_rgd,mov_ded_in, mov_ded_ind,mov_ded_de, mov_ded_ded,mov_ded_ix, mov_ded_ixd,
+ mov_ded_rg, mov_ded_rgd,mov_ded_in, mov_ded_ind,mov_ded_de, mov_ded_ded,mov_ded_ix, mov_ded_ixd,
+ mov_ded_rg, mov_ded_rgd,mov_ded_in, mov_ded_ind,mov_ded_de, mov_ded_ded,mov_ded_ix, mov_ded_ixd,
+ /* 0x1b00 */
+ mov_ded_rg, mov_ded_rgd,mov_ded_in, mov_ded_ind,mov_ded_de, mov_ded_ded,mov_ded_ix, mov_ded_ixd,
+ mov_ded_rg, mov_ded_rgd,mov_ded_in, mov_ded_ind,mov_ded_de, mov_ded_ded,mov_ded_ix, mov_ded_ixd,
+ mov_ded_rg, mov_ded_rgd,mov_ded_in, mov_ded_ind,mov_ded_de, mov_ded_ded,mov_ded_ix, mov_ded_ixd,
+ mov_ded_rg, mov_ded_rgd,mov_ded_in, mov_ded_ind,mov_ded_de, mov_ded_ded,mov_ded_ix, mov_ded_ixd,
+ /* 0x1c00 */
+ mov_ix_rg, mov_ix_rgd, mov_ix_in, mov_ix_ind, mov_ix_de, mov_ix_ded, mov_ix_ix, mov_ix_ixd,
+ mov_ix_rg, mov_ix_rgd, mov_ix_in, mov_ix_ind, mov_ix_de, mov_ix_ded, mov_ix_ix, mov_ix_ixd,
+ mov_ix_rg, mov_ix_rgd, mov_ix_in, mov_ix_ind, mov_ix_de, mov_ix_ded, mov_ix_ix, mov_ix_ixd,
+ mov_ix_rg, mov_ix_rgd, mov_ix_in, mov_ix_ind, mov_ix_de, mov_ix_ded, mov_ix_ix, mov_ix_ixd,
+ /* 0x1d00 */
+ mov_ix_rg, mov_ix_rgd, mov_ix_in, mov_ix_ind, mov_ix_de, mov_ix_ded, mov_ix_ix, mov_ix_ixd,
+ mov_ix_rg, mov_ix_rgd, mov_ix_in, mov_ix_ind, mov_ix_de, mov_ix_ded, mov_ix_ix, mov_ix_ixd,
+ mov_ix_rg, mov_ix_rgd, mov_ix_in, mov_ix_ind, mov_ix_de, mov_ix_ded, mov_ix_ix, mov_ix_ixd,
+ mov_ix_rg, mov_ix_rgd, mov_ix_in, mov_ix_ind, mov_ix_de, mov_ix_ded, mov_ix_ix, mov_ix_ixd,
+ /* 0x1e00 */
+ mov_ixd_rg, mov_ixd_rgd,mov_ixd_in, mov_ixd_ind,mov_ixd_de, mov_ixd_ded,mov_ixd_ix, mov_ixd_ixd,
+ mov_ixd_rg, mov_ixd_rgd,mov_ixd_in, mov_ixd_ind,mov_ixd_de, mov_ixd_ded,mov_ixd_ix, mov_ixd_ixd,
+ mov_ixd_rg, mov_ixd_rgd,mov_ixd_in, mov_ixd_ind,mov_ixd_de, mov_ixd_ded,mov_ixd_ix, mov_ixd_ixd,
+ mov_ixd_rg, mov_ixd_rgd,mov_ixd_in, mov_ixd_ind,mov_ixd_de, mov_ixd_ded,mov_ixd_ix, mov_ixd_ixd,
+ /* 0x1f00 */
+ mov_ixd_rg, mov_ixd_rgd,mov_ixd_in, mov_ixd_ind,mov_ixd_de, mov_ixd_ded,mov_ixd_ix, mov_ixd_ixd,
+ mov_ixd_rg, mov_ixd_rgd,mov_ixd_in, mov_ixd_ind,mov_ixd_de, mov_ixd_ded,mov_ixd_ix, mov_ixd_ixd,
+ mov_ixd_rg, mov_ixd_rgd,mov_ixd_in, mov_ixd_ind,mov_ixd_de, mov_ixd_ded,mov_ixd_ix, mov_ixd_ixd,
+ mov_ixd_rg, mov_ixd_rgd,mov_ixd_in, mov_ixd_ind,mov_ixd_de, mov_ixd_ded,mov_ixd_ix, mov_ixd_ixd,
+
+ /* 0x2000 */
+ cmp_rg_rg, cmp_rg_rgd, cmp_rg_in, cmp_rg_ind, cmp_rg_de, cmp_rg_ded, cmp_rg_ix, cmp_rg_ixd,
+ cmp_rg_rg, cmp_rg_rgd, cmp_rg_in, cmp_rg_ind, cmp_rg_de, cmp_rg_ded, cmp_rg_ix, cmp_rg_ixd,
+ cmp_rg_rg, cmp_rg_rgd, cmp_rg_in, cmp_rg_ind, cmp_rg_de, cmp_rg_ded, cmp_rg_ix, cmp_rg_ixd,
+ cmp_rg_rg, cmp_rg_rgd, cmp_rg_in, cmp_rg_ind, cmp_rg_de, cmp_rg_ded, cmp_rg_ix, cmp_rg_ixd,
+ /* 0x2100 */
+ cmp_rg_rg, cmp_rg_rgd, cmp_rg_in, cmp_rg_ind, cmp_rg_de, cmp_rg_ded, cmp_rg_ix, cmp_rg_ixd,
+ cmp_rg_rg, cmp_rg_rgd, cmp_rg_in, cmp_rg_ind, cmp_rg_de, cmp_rg_ded, cmp_rg_ix, cmp_rg_ixd,
+ cmp_rg_rg, cmp_rg_rgd, cmp_rg_in, cmp_rg_ind, cmp_rg_de, cmp_rg_ded, cmp_rg_ix, cmp_rg_ixd,
+ cmp_rg_rg, cmp_rg_rgd, cmp_rg_in, cmp_rg_ind, cmp_rg_de, cmp_rg_ded, cmp_rg_ix, cmp_rg_ixd,
+ /* 0x2200 */
+ cmp_rgd_rg, cmp_rgd_rgd,cmp_rgd_in, cmp_rgd_ind,cmp_rgd_de, cmp_rgd_ded,cmp_rgd_ix, cmp_rgd_ixd,
+ cmp_rgd_rg, cmp_rgd_rgd,cmp_rgd_in, cmp_rgd_ind,cmp_rgd_de, cmp_rgd_ded,cmp_rgd_ix, cmp_rgd_ixd,
+ cmp_rgd_rg, cmp_rgd_rgd,cmp_rgd_in, cmp_rgd_ind,cmp_rgd_de, cmp_rgd_ded,cmp_rgd_ix, cmp_rgd_ixd,
+ cmp_rgd_rg, cmp_rgd_rgd,cmp_rgd_in, cmp_rgd_ind,cmp_rgd_de, cmp_rgd_ded,cmp_rgd_ix, cmp_rgd_ixd,
+ /* 0x2300 */
+ cmp_rgd_rg, cmp_rgd_rgd,cmp_rgd_in, cmp_rgd_ind,cmp_rgd_de, cmp_rgd_ded,cmp_rgd_ix, cmp_rgd_ixd,
+ cmp_rgd_rg, cmp_rgd_rgd,cmp_rgd_in, cmp_rgd_ind,cmp_rgd_de, cmp_rgd_ded,cmp_rgd_ix, cmp_rgd_ixd,
+ cmp_rgd_rg, cmp_rgd_rgd,cmp_rgd_in, cmp_rgd_ind,cmp_rgd_de, cmp_rgd_ded,cmp_rgd_ix, cmp_rgd_ixd,
+ cmp_rgd_rg, cmp_rgd_rgd,cmp_rgd_in, cmp_rgd_ind,cmp_rgd_de, cmp_rgd_ded,cmp_rgd_ix, cmp_rgd_ixd,
+ /* 0x2400 */
+ cmp_in_rg, cmp_in_rgd, cmp_in_in, cmp_in_ind, cmp_in_de, cmp_in_ded, cmp_in_ix, cmp_in_ixd,
+ cmp_in_rg, cmp_in_rgd, cmp_in_in, cmp_in_ind, cmp_in_de, cmp_in_ded, cmp_in_ix, cmp_in_ixd,
+ cmp_in_rg, cmp_in_rgd, cmp_in_in, cmp_in_ind, cmp_in_de, cmp_in_ded, cmp_in_ix, cmp_in_ixd,
+ cmp_in_rg, cmp_in_rgd, cmp_in_in, cmp_in_ind, cmp_in_de, cmp_in_ded, cmp_in_ix, cmp_in_ixd,
+ /* 0x2500 */
+ cmp_in_rg, cmp_in_rgd, cmp_in_in, cmp_in_ind, cmp_in_de, cmp_in_ded, cmp_in_ix, cmp_in_ixd,
+ cmp_in_rg, cmp_in_rgd, cmp_in_in, cmp_in_ind, cmp_in_de, cmp_in_ded, cmp_in_ix, cmp_in_ixd,
+ cmp_in_rg, cmp_in_rgd, cmp_in_in, cmp_in_ind, cmp_in_de, cmp_in_ded, cmp_in_ix, cmp_in_ixd,
+ cmp_in_rg, cmp_in_rgd, cmp_in_in, cmp_in_ind, cmp_in_de, cmp_in_ded, cmp_in_ix, cmp_in_ixd,
+ /* 0x2600 */
+ cmp_ind_rg, cmp_ind_rgd,cmp_ind_in, cmp_ind_ind,cmp_ind_de, cmp_ind_ded,cmp_ind_ix, cmp_ind_ixd,
+ cmp_ind_rg, cmp_ind_rgd,cmp_ind_in, cmp_ind_ind,cmp_ind_de, cmp_ind_ded,cmp_ind_ix, cmp_ind_ixd,
+ cmp_ind_rg, cmp_ind_rgd,cmp_ind_in, cmp_ind_ind,cmp_ind_de, cmp_ind_ded,cmp_ind_ix, cmp_ind_ixd,
+ cmp_ind_rg, cmp_ind_rgd,cmp_ind_in, cmp_ind_ind,cmp_ind_de, cmp_ind_ded,cmp_ind_ix, cmp_ind_ixd,
+ /* 0x2700 */
+ cmp_ind_rg, cmp_ind_rgd,cmp_ind_in, cmp_ind_ind,cmp_ind_de, cmp_ind_ded,cmp_ind_ix, cmp_ind_ixd,
+ cmp_ind_rg, cmp_ind_rgd,cmp_ind_in, cmp_ind_ind,cmp_ind_de, cmp_ind_ded,cmp_ind_ix, cmp_ind_ixd,
+ cmp_ind_rg, cmp_ind_rgd,cmp_ind_in, cmp_ind_ind,cmp_ind_de, cmp_ind_ded,cmp_ind_ix, cmp_ind_ixd,
+ cmp_ind_rg, cmp_ind_rgd,cmp_ind_in, cmp_ind_ind,cmp_ind_de, cmp_ind_ded,cmp_ind_ix, cmp_ind_ixd,
+ /* 0x2800 */
+ cmp_de_rg, cmp_de_rgd, cmp_de_in, cmp_de_ind, cmp_de_de, cmp_de_ded, cmp_de_ix, cmp_de_ixd,
+ cmp_de_rg, cmp_de_rgd, cmp_de_in, cmp_de_ind, cmp_de_de, cmp_de_ded, cmp_de_ix, cmp_de_ixd,
+ cmp_de_rg, cmp_de_rgd, cmp_de_in, cmp_de_ind, cmp_de_de, cmp_de_ded, cmp_de_ix, cmp_de_ixd,
+ cmp_de_rg, cmp_de_rgd, cmp_de_in, cmp_de_ind, cmp_de_de, cmp_de_ded, cmp_de_ix, cmp_de_ixd,
+ /* 0x2900 */
+ cmp_de_rg, cmp_de_rgd, cmp_de_in, cmp_de_ind, cmp_de_de, cmp_de_ded, cmp_de_ix, cmp_de_ixd,
+ cmp_de_rg, cmp_de_rgd, cmp_de_in, cmp_de_ind, cmp_de_de, cmp_de_ded, cmp_de_ix, cmp_de_ixd,
+ cmp_de_rg, cmp_de_rgd, cmp_de_in, cmp_de_ind, cmp_de_de, cmp_de_ded, cmp_de_ix, cmp_de_ixd,
+ cmp_de_rg, cmp_de_rgd, cmp_de_in, cmp_de_ind, cmp_de_de, cmp_de_ded, cmp_de_ix, cmp_de_ixd,
+ /* 0x2a00 */
+ cmp_ded_rg, cmp_ded_rgd,cmp_ded_in, cmp_ded_ind,cmp_ded_de, cmp_ded_ded,cmp_ded_ix, cmp_ded_ixd,
+ cmp_ded_rg, cmp_ded_rgd,cmp_ded_in, cmp_ded_ind,cmp_ded_de, cmp_ded_ded,cmp_ded_ix, cmp_ded_ixd,
+ cmp_ded_rg, cmp_ded_rgd,cmp_ded_in, cmp_ded_ind,cmp_ded_de, cmp_ded_ded,cmp_ded_ix, cmp_ded_ixd,
+ cmp_ded_rg, cmp_ded_rgd,cmp_ded_in, cmp_ded_ind,cmp_ded_de, cmp_ded_ded,cmp_ded_ix, cmp_ded_ixd,
+ /* 0x2b00 */
+ cmp_ded_rg, cmp_ded_rgd,cmp_ded_in, cmp_ded_ind,cmp_ded_de, cmp_ded_ded,cmp_ded_ix, cmp_ded_ixd,
+ cmp_ded_rg, cmp_ded_rgd,cmp_ded_in, cmp_ded_ind,cmp_ded_de, cmp_ded_ded,cmp_ded_ix, cmp_ded_ixd,
+ cmp_ded_rg, cmp_ded_rgd,cmp_ded_in, cmp_ded_ind,cmp_ded_de, cmp_ded_ded,cmp_ded_ix, cmp_ded_ixd,
+ cmp_ded_rg, cmp_ded_rgd,cmp_ded_in, cmp_ded_ind,cmp_ded_de, cmp_ded_ded,cmp_ded_ix, cmp_ded_ixd,
+ /* 0x2c00 */
+ cmp_ix_rg, cmp_ix_rgd, cmp_ix_in, cmp_ix_ind, cmp_ix_de, cmp_ix_ded, cmp_ix_ix, cmp_ix_ixd,
+ cmp_ix_rg, cmp_ix_rgd, cmp_ix_in, cmp_ix_ind, cmp_ix_de, cmp_ix_ded, cmp_ix_ix, cmp_ix_ixd,
+ cmp_ix_rg, cmp_ix_rgd, cmp_ix_in, cmp_ix_ind, cmp_ix_de, cmp_ix_ded, cmp_ix_ix, cmp_ix_ixd,
+ cmp_ix_rg, cmp_ix_rgd, cmp_ix_in, cmp_ix_ind, cmp_ix_de, cmp_ix_ded, cmp_ix_ix, cmp_ix_ixd,
+ /* 0x2d00 */
+ cmp_ix_rg, cmp_ix_rgd, cmp_ix_in, cmp_ix_ind, cmp_ix_de, cmp_ix_ded, cmp_ix_ix, cmp_ix_ixd,
+ cmp_ix_rg, cmp_ix_rgd, cmp_ix_in, cmp_ix_ind, cmp_ix_de, cmp_ix_ded, cmp_ix_ix, cmp_ix_ixd,
+ cmp_ix_rg, cmp_ix_rgd, cmp_ix_in, cmp_ix_ind, cmp_ix_de, cmp_ix_ded, cmp_ix_ix, cmp_ix_ixd,
+ cmp_ix_rg, cmp_ix_rgd, cmp_ix_in, cmp_ix_ind, cmp_ix_de, cmp_ix_ded, cmp_ix_ix, cmp_ix_ixd,
+ /* 0x2e00 */
+ cmp_ixd_rg, cmp_ixd_rgd,cmp_ixd_in, cmp_ixd_ind,cmp_ixd_de, cmp_ixd_ded,cmp_ixd_ix, cmp_ixd_ixd,
+ cmp_ixd_rg, cmp_ixd_rgd,cmp_ixd_in, cmp_ixd_ind,cmp_ixd_de, cmp_ixd_ded,cmp_ixd_ix, cmp_ixd_ixd,
+ cmp_ixd_rg, cmp_ixd_rgd,cmp_ixd_in, cmp_ixd_ind,cmp_ixd_de, cmp_ixd_ded,cmp_ixd_ix, cmp_ixd_ixd,
+ cmp_ixd_rg, cmp_ixd_rgd,cmp_ixd_in, cmp_ixd_ind,cmp_ixd_de, cmp_ixd_ded,cmp_ixd_ix, cmp_ixd_ixd,
+ /* 0x2f00 */
+ cmp_ixd_rg, cmp_ixd_rgd,cmp_ixd_in, cmp_ixd_ind,cmp_ixd_de, cmp_ixd_ded,cmp_ixd_ix, cmp_ixd_ixd,
+ cmp_ixd_rg, cmp_ixd_rgd,cmp_ixd_in, cmp_ixd_ind,cmp_ixd_de, cmp_ixd_ded,cmp_ixd_ix, cmp_ixd_ixd,
+ cmp_ixd_rg, cmp_ixd_rgd,cmp_ixd_in, cmp_ixd_ind,cmp_ixd_de, cmp_ixd_ded,cmp_ixd_ix, cmp_ixd_ixd,
+ cmp_ixd_rg, cmp_ixd_rgd,cmp_ixd_in, cmp_ixd_ind,cmp_ixd_de, cmp_ixd_ded,cmp_ixd_ix, cmp_ixd_ixd,
+
+ /* 0x3000 */
+ bit_rg_rg, bit_rg_rgd, bit_rg_in, bit_rg_ind, bit_rg_de, bit_rg_ded, bit_rg_ix, bit_rg_ixd,
+ bit_rg_rg, bit_rg_rgd, bit_rg_in, bit_rg_ind, bit_rg_de, bit_rg_ded, bit_rg_ix, bit_rg_ixd,
+ bit_rg_rg, bit_rg_rgd, bit_rg_in, bit_rg_ind, bit_rg_de, bit_rg_ded, bit_rg_ix, bit_rg_ixd,
+ bit_rg_rg, bit_rg_rgd, bit_rg_in, bit_rg_ind, bit_rg_de, bit_rg_ded, bit_rg_ix, bit_rg_ixd,
+ /* 0x3100 */
+ bit_rg_rg, bit_rg_rgd, bit_rg_in, bit_rg_ind, bit_rg_de, bit_rg_ded, bit_rg_ix, bit_rg_ixd,
+ bit_rg_rg, bit_rg_rgd, bit_rg_in, bit_rg_ind, bit_rg_de, bit_rg_ded, bit_rg_ix, bit_rg_ixd,
+ bit_rg_rg, bit_rg_rgd, bit_rg_in, bit_rg_ind, bit_rg_de, bit_rg_ded, bit_rg_ix, bit_rg_ixd,
+ bit_rg_rg, bit_rg_rgd, bit_rg_in, bit_rg_ind, bit_rg_de, bit_rg_ded, bit_rg_ix, bit_rg_ixd,
+ /* 0x3200 */
+ bit_rgd_rg, bit_rgd_rgd,bit_rgd_in, bit_rgd_ind,bit_rgd_de, bit_rgd_ded,bit_rgd_ix, bit_rgd_ixd,
+ bit_rgd_rg, bit_rgd_rgd,bit_rgd_in, bit_rgd_ind,bit_rgd_de, bit_rgd_ded,bit_rgd_ix, bit_rgd_ixd,
+ bit_rgd_rg, bit_rgd_rgd,bit_rgd_in, bit_rgd_ind,bit_rgd_de, bit_rgd_ded,bit_rgd_ix, bit_rgd_ixd,
+ bit_rgd_rg, bit_rgd_rgd,bit_rgd_in, bit_rgd_ind,bit_rgd_de, bit_rgd_ded,bit_rgd_ix, bit_rgd_ixd,
+ /* 0x3300 */
+ bit_rgd_rg, bit_rgd_rgd,bit_rgd_in, bit_rgd_ind,bit_rgd_de, bit_rgd_ded,bit_rgd_ix, bit_rgd_ixd,
+ bit_rgd_rg, bit_rgd_rgd,bit_rgd_in, bit_rgd_ind,bit_rgd_de, bit_rgd_ded,bit_rgd_ix, bit_rgd_ixd,
+ bit_rgd_rg, bit_rgd_rgd,bit_rgd_in, bit_rgd_ind,bit_rgd_de, bit_rgd_ded,bit_rgd_ix, bit_rgd_ixd,
+ bit_rgd_rg, bit_rgd_rgd,bit_rgd_in, bit_rgd_ind,bit_rgd_de, bit_rgd_ded,bit_rgd_ix, bit_rgd_ixd,
+ /* 0x3400 */
+ bit_in_rg, bit_in_rgd, bit_in_in, bit_in_ind, bit_in_de, bit_in_ded, bit_in_ix, bit_in_ixd,
+ bit_in_rg, bit_in_rgd, bit_in_in, bit_in_ind, bit_in_de, bit_in_ded, bit_in_ix, bit_in_ixd,
+ bit_in_rg, bit_in_rgd, bit_in_in, bit_in_ind, bit_in_de, bit_in_ded, bit_in_ix, bit_in_ixd,
+ bit_in_rg, bit_in_rgd, bit_in_in, bit_in_ind, bit_in_de, bit_in_ded, bit_in_ix, bit_in_ixd,
+ /* 0x3500 */
+ bit_in_rg, bit_in_rgd, bit_in_in, bit_in_ind, bit_in_de, bit_in_ded, bit_in_ix, bit_in_ixd,
+ bit_in_rg, bit_in_rgd, bit_in_in, bit_in_ind, bit_in_de, bit_in_ded, bit_in_ix, bit_in_ixd,
+ bit_in_rg, bit_in_rgd, bit_in_in, bit_in_ind, bit_in_de, bit_in_ded, bit_in_ix, bit_in_ixd,
+ bit_in_rg, bit_in_rgd, bit_in_in, bit_in_ind, bit_in_de, bit_in_ded, bit_in_ix, bit_in_ixd,
+ /* 0x3600 */
+ bit_ind_rg, bit_ind_rgd,bit_ind_in, bit_ind_ind,bit_ind_de, bit_ind_ded,bit_ind_ix, bit_ind_ixd,
+ bit_ind_rg, bit_ind_rgd,bit_ind_in, bit_ind_ind,bit_ind_de, bit_ind_ded,bit_ind_ix, bit_ind_ixd,
+ bit_ind_rg, bit_ind_rgd,bit_ind_in, bit_ind_ind,bit_ind_de, bit_ind_ded,bit_ind_ix, bit_ind_ixd,
+ bit_ind_rg, bit_ind_rgd,bit_ind_in, bit_ind_ind,bit_ind_de, bit_ind_ded,bit_ind_ix, bit_ind_ixd,
+ /* 0x3700 */
+ bit_ind_rg, bit_ind_rgd,bit_ind_in, bit_ind_ind,bit_ind_de, bit_ind_ded,bit_ind_ix, bit_ind_ixd,
+ bit_ind_rg, bit_ind_rgd,bit_ind_in, bit_ind_ind,bit_ind_de, bit_ind_ded,bit_ind_ix, bit_ind_ixd,
+ bit_ind_rg, bit_ind_rgd,bit_ind_in, bit_ind_ind,bit_ind_de, bit_ind_ded,bit_ind_ix, bit_ind_ixd,
+ bit_ind_rg, bit_ind_rgd,bit_ind_in, bit_ind_ind,bit_ind_de, bit_ind_ded,bit_ind_ix, bit_ind_ixd,
+ /* 0x3800 */
+ bit_de_rg, bit_de_rgd, bit_de_in, bit_de_ind, bit_de_de, bit_de_ded, bit_de_ix, bit_de_ixd,
+ bit_de_rg, bit_de_rgd, bit_de_in, bit_de_ind, bit_de_de, bit_de_ded, bit_de_ix, bit_de_ixd,
+ bit_de_rg, bit_de_rgd, bit_de_in, bit_de_ind, bit_de_de, bit_de_ded, bit_de_ix, bit_de_ixd,
+ bit_de_rg, bit_de_rgd, bit_de_in, bit_de_ind, bit_de_de, bit_de_ded, bit_de_ix, bit_de_ixd,
+ /* 0x3900 */
+ bit_de_rg, bit_de_rgd, bit_de_in, bit_de_ind, bit_de_de, bit_de_ded, bit_de_ix, bit_de_ixd,
+ bit_de_rg, bit_de_rgd, bit_de_in, bit_de_ind, bit_de_de, bit_de_ded, bit_de_ix, bit_de_ixd,
+ bit_de_rg, bit_de_rgd, bit_de_in, bit_de_ind, bit_de_de, bit_de_ded, bit_de_ix, bit_de_ixd,
+ bit_de_rg, bit_de_rgd, bit_de_in, bit_de_ind, bit_de_de, bit_de_ded, bit_de_ix, bit_de_ixd,
+ /* 0x3a00 */
+ bit_ded_rg, bit_ded_rgd,bit_ded_in, bit_ded_ind,bit_ded_de, bit_ded_ded,bit_ded_ix, bit_ded_ixd,
+ bit_ded_rg, bit_ded_rgd,bit_ded_in, bit_ded_ind,bit_ded_de, bit_ded_ded,bit_ded_ix, bit_ded_ixd,
+ bit_ded_rg, bit_ded_rgd,bit_ded_in, bit_ded_ind,bit_ded_de, bit_ded_ded,bit_ded_ix, bit_ded_ixd,
+ bit_ded_rg, bit_ded_rgd,bit_ded_in, bit_ded_ind,bit_ded_de, bit_ded_ded,bit_ded_ix, bit_ded_ixd,
+ /* 0x3b00 */
+ bit_ded_rg, bit_ded_rgd,bit_ded_in, bit_ded_ind,bit_ded_de, bit_ded_ded,bit_ded_ix, bit_ded_ixd,
+ bit_ded_rg, bit_ded_rgd,bit_ded_in, bit_ded_ind,bit_ded_de, bit_ded_ded,bit_ded_ix, bit_ded_ixd,
+ bit_ded_rg, bit_ded_rgd,bit_ded_in, bit_ded_ind,bit_ded_de, bit_ded_ded,bit_ded_ix, bit_ded_ixd,
+ bit_ded_rg, bit_ded_rgd,bit_ded_in, bit_ded_ind,bit_ded_de, bit_ded_ded,bit_ded_ix, bit_ded_ixd,
+ /* 0x3c00 */
+ bit_ix_rg, bit_ix_rgd, bit_ix_in, bit_ix_ind, bit_ix_de, bit_ix_ded, bit_ix_ix, bit_ix_ixd,
+ bit_ix_rg, bit_ix_rgd, bit_ix_in, bit_ix_ind, bit_ix_de, bit_ix_ded, bit_ix_ix, bit_ix_ixd,
+ bit_ix_rg, bit_ix_rgd, bit_ix_in, bit_ix_ind, bit_ix_de, bit_ix_ded, bit_ix_ix, bit_ix_ixd,
+ bit_ix_rg, bit_ix_rgd, bit_ix_in, bit_ix_ind, bit_ix_de, bit_ix_ded, bit_ix_ix, bit_ix_ixd,
+ /* 0x3d00 */
+ bit_ix_rg, bit_ix_rgd, bit_ix_in, bit_ix_ind, bit_ix_de, bit_ix_ded, bit_ix_ix, bit_ix_ixd,
+ bit_ix_rg, bit_ix_rgd, bit_ix_in, bit_ix_ind, bit_ix_de, bit_ix_ded, bit_ix_ix, bit_ix_ixd,
+ bit_ix_rg, bit_ix_rgd, bit_ix_in, bit_ix_ind, bit_ix_de, bit_ix_ded, bit_ix_ix, bit_ix_ixd,
+ bit_ix_rg, bit_ix_rgd, bit_ix_in, bit_ix_ind, bit_ix_de, bit_ix_ded, bit_ix_ix, bit_ix_ixd,
+ /* 0x3e00 */
+ bit_ixd_rg, bit_ixd_rgd,bit_ixd_in, bit_ixd_ind,bit_ixd_de, bit_ixd_ded,bit_ixd_ix, bit_ixd_ixd,
+ bit_ixd_rg, bit_ixd_rgd,bit_ixd_in, bit_ixd_ind,bit_ixd_de, bit_ixd_ded,bit_ixd_ix, bit_ixd_ixd,
+ bit_ixd_rg, bit_ixd_rgd,bit_ixd_in, bit_ixd_ind,bit_ixd_de, bit_ixd_ded,bit_ixd_ix, bit_ixd_ixd,
+ bit_ixd_rg, bit_ixd_rgd,bit_ixd_in, bit_ixd_ind,bit_ixd_de, bit_ixd_ded,bit_ixd_ix, bit_ixd_ixd,
+ /* 0x3f00 */
+ bit_ixd_rg, bit_ixd_rgd,bit_ixd_in, bit_ixd_ind,bit_ixd_de, bit_ixd_ded,bit_ixd_ix, bit_ixd_ixd,
+ bit_ixd_rg, bit_ixd_rgd,bit_ixd_in, bit_ixd_ind,bit_ixd_de, bit_ixd_ded,bit_ixd_ix, bit_ixd_ixd,
+ bit_ixd_rg, bit_ixd_rgd,bit_ixd_in, bit_ixd_ind,bit_ixd_de, bit_ixd_ded,bit_ixd_ix, bit_ixd_ixd,
+ bit_ixd_rg, bit_ixd_rgd,bit_ixd_in, bit_ixd_ind,bit_ixd_de, bit_ixd_ded,bit_ixd_ix, bit_ixd_ixd,
+
+ /* 0x4000 */
+ bic_rg_rg, bic_rg_rgd, bic_rg_in, bic_rg_ind, bic_rg_de, bic_rg_ded, bic_rg_ix, bic_rg_ixd,
+ bic_rg_rg, bic_rg_rgd, bic_rg_in, bic_rg_ind, bic_rg_de, bic_rg_ded, bic_rg_ix, bic_rg_ixd,
+ bic_rg_rg, bic_rg_rgd, bic_rg_in, bic_rg_ind, bic_rg_de, bic_rg_ded, bic_rg_ix, bic_rg_ixd,
+ bic_rg_rg, bic_rg_rgd, bic_rg_in, bic_rg_ind, bic_rg_de, bic_rg_ded, bic_rg_ix, bic_rg_ixd,
+ /* 0x4100 */
+ bic_rg_rg, bic_rg_rgd, bic_rg_in, bic_rg_ind, bic_rg_de, bic_rg_ded, bic_rg_ix, bic_rg_ixd,
+ bic_rg_rg, bic_rg_rgd, bic_rg_in, bic_rg_ind, bic_rg_de, bic_rg_ded, bic_rg_ix, bic_rg_ixd,
+ bic_rg_rg, bic_rg_rgd, bic_rg_in, bic_rg_ind, bic_rg_de, bic_rg_ded, bic_rg_ix, bic_rg_ixd,
+ bic_rg_rg, bic_rg_rgd, bic_rg_in, bic_rg_ind, bic_rg_de, bic_rg_ded, bic_rg_ix, bic_rg_ixd,
+ /* 0x4200 */
+ bic_rgd_rg, bic_rgd_rgd,bic_rgd_in, bic_rgd_ind,bic_rgd_de, bic_rgd_ded,bic_rgd_ix, bic_rgd_ixd,
+ bic_rgd_rg, bic_rgd_rgd,bic_rgd_in, bic_rgd_ind,bic_rgd_de, bic_rgd_ded,bic_rgd_ix, bic_rgd_ixd,
+ bic_rgd_rg, bic_rgd_rgd,bic_rgd_in, bic_rgd_ind,bic_rgd_de, bic_rgd_ded,bic_rgd_ix, bic_rgd_ixd,
+ bic_rgd_rg, bic_rgd_rgd,bic_rgd_in, bic_rgd_ind,bic_rgd_de, bic_rgd_ded,bic_rgd_ix, bic_rgd_ixd,
+ /* 0x4300 */
+ bic_rgd_rg, bic_rgd_rgd,bic_rgd_in, bic_rgd_ind,bic_rgd_de, bic_rgd_ded,bic_rgd_ix, bic_rgd_ixd,
+ bic_rgd_rg, bic_rgd_rgd,bic_rgd_in, bic_rgd_ind,bic_rgd_de, bic_rgd_ded,bic_rgd_ix, bic_rgd_ixd,
+ bic_rgd_rg, bic_rgd_rgd,bic_rgd_in, bic_rgd_ind,bic_rgd_de, bic_rgd_ded,bic_rgd_ix, bic_rgd_ixd,
+ bic_rgd_rg, bic_rgd_rgd,bic_rgd_in, bic_rgd_ind,bic_rgd_de, bic_rgd_ded,bic_rgd_ix, bic_rgd_ixd,
+ /* 0x4400 */
+ bic_in_rg, bic_in_rgd, bic_in_in, bic_in_ind, bic_in_de, bic_in_ded, bic_in_ix, bic_in_ixd,
+ bic_in_rg, bic_in_rgd, bic_in_in, bic_in_ind, bic_in_de, bic_in_ded, bic_in_ix, bic_in_ixd,
+ bic_in_rg, bic_in_rgd, bic_in_in, bic_in_ind, bic_in_de, bic_in_ded, bic_in_ix, bic_in_ixd,
+ bic_in_rg, bic_in_rgd, bic_in_in, bic_in_ind, bic_in_de, bic_in_ded, bic_in_ix, bic_in_ixd,
+ /* 0x4500 */
+ bic_in_rg, bic_in_rgd, bic_in_in, bic_in_ind, bic_in_de, bic_in_ded, bic_in_ix, bic_in_ixd,
+ bic_in_rg, bic_in_rgd, bic_in_in, bic_in_ind, bic_in_de, bic_in_ded, bic_in_ix, bic_in_ixd,
+ bic_in_rg, bic_in_rgd, bic_in_in, bic_in_ind, bic_in_de, bic_in_ded, bic_in_ix, bic_in_ixd,
+ bic_in_rg, bic_in_rgd, bic_in_in, bic_in_ind, bic_in_de, bic_in_ded, bic_in_ix, bic_in_ixd,
+ /* 0x4600 */
+ bic_ind_rg, bic_ind_rgd,bic_ind_in, bic_ind_ind,bic_ind_de, bic_ind_ded,bic_ind_ix, bic_ind_ixd,
+ bic_ind_rg, bic_ind_rgd,bic_ind_in, bic_ind_ind,bic_ind_de, bic_ind_ded,bic_ind_ix, bic_ind_ixd,
+ bic_ind_rg, bic_ind_rgd,bic_ind_in, bic_ind_ind,bic_ind_de, bic_ind_ded,bic_ind_ix, bic_ind_ixd,
+ bic_ind_rg, bic_ind_rgd,bic_ind_in, bic_ind_ind,bic_ind_de, bic_ind_ded,bic_ind_ix, bic_ind_ixd,
+ /* 0x4700 */
+ bic_ind_rg, bic_ind_rgd,bic_ind_in, bic_ind_ind,bic_ind_de, bic_ind_ded,bic_ind_ix, bic_ind_ixd,
+ bic_ind_rg, bic_ind_rgd,bic_ind_in, bic_ind_ind,bic_ind_de, bic_ind_ded,bic_ind_ix, bic_ind_ixd,
+ bic_ind_rg, bic_ind_rgd,bic_ind_in, bic_ind_ind,bic_ind_de, bic_ind_ded,bic_ind_ix, bic_ind_ixd,
+ bic_ind_rg, bic_ind_rgd,bic_ind_in, bic_ind_ind,bic_ind_de, bic_ind_ded,bic_ind_ix, bic_ind_ixd,
+ /* 0x4800 */
+ bic_de_rg, bic_de_rgd, bic_de_in, bic_de_ind, bic_de_de, bic_de_ded, bic_de_ix, bic_de_ixd,
+ bic_de_rg, bic_de_rgd, bic_de_in, bic_de_ind, bic_de_de, bic_de_ded, bic_de_ix, bic_de_ixd,
+ bic_de_rg, bic_de_rgd, bic_de_in, bic_de_ind, bic_de_de, bic_de_ded, bic_de_ix, bic_de_ixd,
+ bic_de_rg, bic_de_rgd, bic_de_in, bic_de_ind, bic_de_de, bic_de_ded, bic_de_ix, bic_de_ixd,
+ /* 0x4900 */
+ bic_de_rg, bic_de_rgd, bic_de_in, bic_de_ind, bic_de_de, bic_de_ded, bic_de_ix, bic_de_ixd,
+ bic_de_rg, bic_de_rgd, bic_de_in, bic_de_ind, bic_de_de, bic_de_ded, bic_de_ix, bic_de_ixd,
+ bic_de_rg, bic_de_rgd, bic_de_in, bic_de_ind, bic_de_de, bic_de_ded, bic_de_ix, bic_de_ixd,
+ bic_de_rg, bic_de_rgd, bic_de_in, bic_de_ind, bic_de_de, bic_de_ded, bic_de_ix, bic_de_ixd,
+ /* 0x4a00 */
+ bic_ded_rg, bic_ded_rgd,bic_ded_in, bic_ded_ind,bic_ded_de, bic_ded_ded,bic_ded_ix, bic_ded_ixd,
+ bic_ded_rg, bic_ded_rgd,bic_ded_in, bic_ded_ind,bic_ded_de, bic_ded_ded,bic_ded_ix, bic_ded_ixd,
+ bic_ded_rg, bic_ded_rgd,bic_ded_in, bic_ded_ind,bic_ded_de, bic_ded_ded,bic_ded_ix, bic_ded_ixd,
+ bic_ded_rg, bic_ded_rgd,bic_ded_in, bic_ded_ind,bic_ded_de, bic_ded_ded,bic_ded_ix, bic_ded_ixd,
+ /* 0x4b00 */
+ bic_ded_rg, bic_ded_rgd,bic_ded_in, bic_ded_ind,bic_ded_de, bic_ded_ded,bic_ded_ix, bic_ded_ixd,
+ bic_ded_rg, bic_ded_rgd,bic_ded_in, bic_ded_ind,bic_ded_de, bic_ded_ded,bic_ded_ix, bic_ded_ixd,
+ bic_ded_rg, bic_ded_rgd,bic_ded_in, bic_ded_ind,bic_ded_de, bic_ded_ded,bic_ded_ix, bic_ded_ixd,
+ bic_ded_rg, bic_ded_rgd,bic_ded_in, bic_ded_ind,bic_ded_de, bic_ded_ded,bic_ded_ix, bic_ded_ixd,
+ /* 0x4c00 */
+ bic_ix_rg, bic_ix_rgd, bic_ix_in, bic_ix_ind, bic_ix_de, bic_ix_ded, bic_ix_ix, bic_ix_ixd,
+ bic_ix_rg, bic_ix_rgd, bic_ix_in, bic_ix_ind, bic_ix_de, bic_ix_ded, bic_ix_ix, bic_ix_ixd,
+ bic_ix_rg, bic_ix_rgd, bic_ix_in, bic_ix_ind, bic_ix_de, bic_ix_ded, bic_ix_ix, bic_ix_ixd,
+ bic_ix_rg, bic_ix_rgd, bic_ix_in, bic_ix_ind, bic_ix_de, bic_ix_ded, bic_ix_ix, bic_ix_ixd,
+ /* 0x4d00 */
+ bic_ix_rg, bic_ix_rgd, bic_ix_in, bic_ix_ind, bic_ix_de, bic_ix_ded, bic_ix_ix, bic_ix_ixd,
+ bic_ix_rg, bic_ix_rgd, bic_ix_in, bic_ix_ind, bic_ix_de, bic_ix_ded, bic_ix_ix, bic_ix_ixd,
+ bic_ix_rg, bic_ix_rgd, bic_ix_in, bic_ix_ind, bic_ix_de, bic_ix_ded, bic_ix_ix, bic_ix_ixd,
+ bic_ix_rg, bic_ix_rgd, bic_ix_in, bic_ix_ind, bic_ix_de, bic_ix_ded, bic_ix_ix, bic_ix_ixd,
+ /* 0x4e00 */
+ bic_ixd_rg, bic_ixd_rgd,bic_ixd_in, bic_ixd_ind,bic_ixd_de, bic_ixd_ded,bic_ixd_ix, bic_ixd_ixd,
+ bic_ixd_rg, bic_ixd_rgd,bic_ixd_in, bic_ixd_ind,bic_ixd_de, bic_ixd_ded,bic_ixd_ix, bic_ixd_ixd,
+ bic_ixd_rg, bic_ixd_rgd,bic_ixd_in, bic_ixd_ind,bic_ixd_de, bic_ixd_ded,bic_ixd_ix, bic_ixd_ixd,
+ bic_ixd_rg, bic_ixd_rgd,bic_ixd_in, bic_ixd_ind,bic_ixd_de, bic_ixd_ded,bic_ixd_ix, bic_ixd_ixd,
+ /* 0x4f00 */
+ bic_ixd_rg, bic_ixd_rgd,bic_ixd_in, bic_ixd_ind,bic_ixd_de, bic_ixd_ded,bic_ixd_ix, bic_ixd_ixd,
+ bic_ixd_rg, bic_ixd_rgd,bic_ixd_in, bic_ixd_ind,bic_ixd_de, bic_ixd_ded,bic_ixd_ix, bic_ixd_ixd,
+ bic_ixd_rg, bic_ixd_rgd,bic_ixd_in, bic_ixd_ind,bic_ixd_de, bic_ixd_ded,bic_ixd_ix, bic_ixd_ixd,
+ bic_ixd_rg, bic_ixd_rgd,bic_ixd_in, bic_ixd_ind,bic_ixd_de, bic_ixd_ded,bic_ixd_ix, bic_ixd_ixd,
+
+ /* 0x5000 */
+ bis_rg_rg, bis_rg_rgd, bis_rg_in, bis_rg_ind, bis_rg_de, bis_rg_ded, bis_rg_ix, bis_rg_ixd,
+ bis_rg_rg, bis_rg_rgd, bis_rg_in, bis_rg_ind, bis_rg_de, bis_rg_ded, bis_rg_ix, bis_rg_ixd,
+ bis_rg_rg, bis_rg_rgd, bis_rg_in, bis_rg_ind, bis_rg_de, bis_rg_ded, bis_rg_ix, bis_rg_ixd,
+ bis_rg_rg, bis_rg_rgd, bis_rg_in, bis_rg_ind, bis_rg_de, bis_rg_ded, bis_rg_ix, bis_rg_ixd,
+ /* 0x5100 */
+ bis_rg_rg, bis_rg_rgd, bis_rg_in, bis_rg_ind, bis_rg_de, bis_rg_ded, bis_rg_ix, bis_rg_ixd,
+ bis_rg_rg, bis_rg_rgd, bis_rg_in, bis_rg_ind, bis_rg_de, bis_rg_ded, bis_rg_ix, bis_rg_ixd,
+ bis_rg_rg, bis_rg_rgd, bis_rg_in, bis_rg_ind, bis_rg_de, bis_rg_ded, bis_rg_ix, bis_rg_ixd,
+ bis_rg_rg, bis_rg_rgd, bis_rg_in, bis_rg_ind, bis_rg_de, bis_rg_ded, bis_rg_ix, bis_rg_ixd,
+ /* 0x5200 */
+ bis_rgd_rg, bis_rgd_rgd,bis_rgd_in, bis_rgd_ind,bis_rgd_de, bis_rgd_ded,bis_rgd_ix, bis_rgd_ixd,
+ bis_rgd_rg, bis_rgd_rgd,bis_rgd_in, bis_rgd_ind,bis_rgd_de, bis_rgd_ded,bis_rgd_ix, bis_rgd_ixd,
+ bis_rgd_rg, bis_rgd_rgd,bis_rgd_in, bis_rgd_ind,bis_rgd_de, bis_rgd_ded,bis_rgd_ix, bis_rgd_ixd,
+ bis_rgd_rg, bis_rgd_rgd,bis_rgd_in, bis_rgd_ind,bis_rgd_de, bis_rgd_ded,bis_rgd_ix, bis_rgd_ixd,
+ /* 0x5300 */
+ bis_rgd_rg, bis_rgd_rgd,bis_rgd_in, bis_rgd_ind,bis_rgd_de, bis_rgd_ded,bis_rgd_ix, bis_rgd_ixd,
+ bis_rgd_rg, bis_rgd_rgd,bis_rgd_in, bis_rgd_ind,bis_rgd_de, bis_rgd_ded,bis_rgd_ix, bis_rgd_ixd,
+ bis_rgd_rg, bis_rgd_rgd,bis_rgd_in, bis_rgd_ind,bis_rgd_de, bis_rgd_ded,bis_rgd_ix, bis_rgd_ixd,
+ bis_rgd_rg, bis_rgd_rgd,bis_rgd_in, bis_rgd_ind,bis_rgd_de, bis_rgd_ded,bis_rgd_ix, bis_rgd_ixd,
+ /* 0x5400 */
+ bis_in_rg, bis_in_rgd, bis_in_in, bis_in_ind, bis_in_de, bis_in_ded, bis_in_ix, bis_in_ixd,
+ bis_in_rg, bis_in_rgd, bis_in_in, bis_in_ind, bis_in_de, bis_in_ded, bis_in_ix, bis_in_ixd,
+ bis_in_rg, bis_in_rgd, bis_in_in, bis_in_ind, bis_in_de, bis_in_ded, bis_in_ix, bis_in_ixd,
+ bis_in_rg, bis_in_rgd, bis_in_in, bis_in_ind, bis_in_de, bis_in_ded, bis_in_ix, bis_in_ixd,
+ /* 0x5500 */
+ bis_in_rg, bis_in_rgd, bis_in_in, bis_in_ind, bis_in_de, bis_in_ded, bis_in_ix, bis_in_ixd,
+ bis_in_rg, bis_in_rgd, bis_in_in, bis_in_ind, bis_in_de, bis_in_ded, bis_in_ix, bis_in_ixd,
+ bis_in_rg, bis_in_rgd, bis_in_in, bis_in_ind, bis_in_de, bis_in_ded, bis_in_ix, bis_in_ixd,
+ bis_in_rg, bis_in_rgd, bis_in_in, bis_in_ind, bis_in_de, bis_in_ded, bis_in_ix, bis_in_ixd,
+ /* 0x5600 */
+ bis_ind_rg, bis_ind_rgd,bis_ind_in, bis_ind_ind,bis_ind_de, bis_ind_ded,bis_ind_ix, bis_ind_ixd,
+ bis_ind_rg, bis_ind_rgd,bis_ind_in, bis_ind_ind,bis_ind_de, bis_ind_ded,bis_ind_ix, bis_ind_ixd,
+ bis_ind_rg, bis_ind_rgd,bis_ind_in, bis_ind_ind,bis_ind_de, bis_ind_ded,bis_ind_ix, bis_ind_ixd,
+ bis_ind_rg, bis_ind_rgd,bis_ind_in, bis_ind_ind,bis_ind_de, bis_ind_ded,bis_ind_ix, bis_ind_ixd,
+ /* 0x5700 */
+ bis_ind_rg, bis_ind_rgd,bis_ind_in, bis_ind_ind,bis_ind_de, bis_ind_ded,bis_ind_ix, bis_ind_ixd,
+ bis_ind_rg, bis_ind_rgd,bis_ind_in, bis_ind_ind,bis_ind_de, bis_ind_ded,bis_ind_ix, bis_ind_ixd,
+ bis_ind_rg, bis_ind_rgd,bis_ind_in, bis_ind_ind,bis_ind_de, bis_ind_ded,bis_ind_ix, bis_ind_ixd,
+ bis_ind_rg, bis_ind_rgd,bis_ind_in, bis_ind_ind,bis_ind_de, bis_ind_ded,bis_ind_ix, bis_ind_ixd,
+ /* 0x5800 */
+ bis_de_rg, bis_de_rgd, bis_de_in, bis_de_ind, bis_de_de, bis_de_ded, bis_de_ix, bis_de_ixd,
+ bis_de_rg, bis_de_rgd, bis_de_in, bis_de_ind, bis_de_de, bis_de_ded, bis_de_ix, bis_de_ixd,
+ bis_de_rg, bis_de_rgd, bis_de_in, bis_de_ind, bis_de_de, bis_de_ded, bis_de_ix, bis_de_ixd,
+ bis_de_rg, bis_de_rgd, bis_de_in, bis_de_ind, bis_de_de, bis_de_ded, bis_de_ix, bis_de_ixd,
+ /* 0x5900 */
+ bis_de_rg, bis_de_rgd, bis_de_in, bis_de_ind, bis_de_de, bis_de_ded, bis_de_ix, bis_de_ixd,
+ bis_de_rg, bis_de_rgd, bis_de_in, bis_de_ind, bis_de_de, bis_de_ded, bis_de_ix, bis_de_ixd,
+ bis_de_rg, bis_de_rgd, bis_de_in, bis_de_ind, bis_de_de, bis_de_ded, bis_de_ix, bis_de_ixd,
+ bis_de_rg, bis_de_rgd, bis_de_in, bis_de_ind, bis_de_de, bis_de_ded, bis_de_ix, bis_de_ixd,
+ /* 0x5a00 */
+ bis_ded_rg, bis_ded_rgd,bis_ded_in, bis_ded_ind,bis_ded_de, bis_ded_ded,bis_ded_ix, bis_ded_ixd,
+ bis_ded_rg, bis_ded_rgd,bis_ded_in, bis_ded_ind,bis_ded_de, bis_ded_ded,bis_ded_ix, bis_ded_ixd,
+ bis_ded_rg, bis_ded_rgd,bis_ded_in, bis_ded_ind,bis_ded_de, bis_ded_ded,bis_ded_ix, bis_ded_ixd,
+ bis_ded_rg, bis_ded_rgd,bis_ded_in, bis_ded_ind,bis_ded_de, bis_ded_ded,bis_ded_ix, bis_ded_ixd,
+ /* 0x5b00 */
+ bis_ded_rg, bis_ded_rgd,bis_ded_in, bis_ded_ind,bis_ded_de, bis_ded_ded,bis_ded_ix, bis_ded_ixd,
+ bis_ded_rg, bis_ded_rgd,bis_ded_in, bis_ded_ind,bis_ded_de, bis_ded_ded,bis_ded_ix, bis_ded_ixd,
+ bis_ded_rg, bis_ded_rgd,bis_ded_in, bis_ded_ind,bis_ded_de, bis_ded_ded,bis_ded_ix, bis_ded_ixd,
+ bis_ded_rg, bis_ded_rgd,bis_ded_in, bis_ded_ind,bis_ded_de, bis_ded_ded,bis_ded_ix, bis_ded_ixd,
+ /* 0x5c00 */
+ bis_ix_rg, bis_ix_rgd, bis_ix_in, bis_ix_ind, bis_ix_de, bis_ix_ded, bis_ix_ix, bis_ix_ixd,
+ bis_ix_rg, bis_ix_rgd, bis_ix_in, bis_ix_ind, bis_ix_de, bis_ix_ded, bis_ix_ix, bis_ix_ixd,
+ bis_ix_rg, bis_ix_rgd, bis_ix_in, bis_ix_ind, bis_ix_de, bis_ix_ded, bis_ix_ix, bis_ix_ixd,
+ bis_ix_rg, bis_ix_rgd, bis_ix_in, bis_ix_ind, bis_ix_de, bis_ix_ded, bis_ix_ix, bis_ix_ixd,
+ /* 0x5d00 */
+ bis_ix_rg, bis_ix_rgd, bis_ix_in, bis_ix_ind, bis_ix_de, bis_ix_ded, bis_ix_ix, bis_ix_ixd,
+ bis_ix_rg, bis_ix_rgd, bis_ix_in, bis_ix_ind, bis_ix_de, bis_ix_ded, bis_ix_ix, bis_ix_ixd,
+ bis_ix_rg, bis_ix_rgd, bis_ix_in, bis_ix_ind, bis_ix_de, bis_ix_ded, bis_ix_ix, bis_ix_ixd,
+ bis_ix_rg, bis_ix_rgd, bis_ix_in, bis_ix_ind, bis_ix_de, bis_ix_ded, bis_ix_ix, bis_ix_ixd,
+ /* 0x5e00 */
+ bis_ixd_rg, bis_ixd_rgd,bis_ixd_in, bis_ixd_ind,bis_ixd_de, bis_ixd_ded,bis_ixd_ix, bis_ixd_ixd,
+ bis_ixd_rg, bis_ixd_rgd,bis_ixd_in, bis_ixd_ind,bis_ixd_de, bis_ixd_ded,bis_ixd_ix, bis_ixd_ixd,
+ bis_ixd_rg, bis_ixd_rgd,bis_ixd_in, bis_ixd_ind,bis_ixd_de, bis_ixd_ded,bis_ixd_ix, bis_ixd_ixd,
+ bis_ixd_rg, bis_ixd_rgd,bis_ixd_in, bis_ixd_ind,bis_ixd_de, bis_ixd_ded,bis_ixd_ix, bis_ixd_ixd,
+ /* 0x5f00 */
+ bis_ixd_rg, bis_ixd_rgd,bis_ixd_in, bis_ixd_ind,bis_ixd_de, bis_ixd_ded,bis_ixd_ix, bis_ixd_ixd,
+ bis_ixd_rg, bis_ixd_rgd,bis_ixd_in, bis_ixd_ind,bis_ixd_de, bis_ixd_ded,bis_ixd_ix, bis_ixd_ixd,
+ bis_ixd_rg, bis_ixd_rgd,bis_ixd_in, bis_ixd_ind,bis_ixd_de, bis_ixd_ded,bis_ixd_ix, bis_ixd_ixd,
+ bis_ixd_rg, bis_ixd_rgd,bis_ixd_in, bis_ixd_ind,bis_ixd_de, bis_ixd_ded,bis_ixd_ix, bis_ixd_ixd,
+
+ /* 0x6000 */
+ add_rg_rg, add_rg_rgd, add_rg_in, add_rg_ind, add_rg_de, add_rg_ded, add_rg_ix, add_rg_ixd,
+ add_rg_rg, add_rg_rgd, add_rg_in, add_rg_ind, add_rg_de, add_rg_ded, add_rg_ix, add_rg_ixd,
+ add_rg_rg, add_rg_rgd, add_rg_in, add_rg_ind, add_rg_de, add_rg_ded, add_rg_ix, add_rg_ixd,
+ add_rg_rg, add_rg_rgd, add_rg_in, add_rg_ind, add_rg_de, add_rg_ded, add_rg_ix, add_rg_ixd,
+ /* 0x6100 */
+ add_rg_rg, add_rg_rgd, add_rg_in, add_rg_ind, add_rg_de, add_rg_ded, add_rg_ix, add_rg_ixd,
+ add_rg_rg, add_rg_rgd, add_rg_in, add_rg_ind, add_rg_de, add_rg_ded, add_rg_ix, add_rg_ixd,
+ add_rg_rg, add_rg_rgd, add_rg_in, add_rg_ind, add_rg_de, add_rg_ded, add_rg_ix, add_rg_ixd,
+ add_rg_rg, add_rg_rgd, add_rg_in, add_rg_ind, add_rg_de, add_rg_ded, add_rg_ix, add_rg_ixd,
+ /* 0x6200 */
+ add_rgd_rg, add_rgd_rgd,add_rgd_in, add_rgd_ind,add_rgd_de, add_rgd_ded,add_rgd_ix, add_rgd_ixd,
+ add_rgd_rg, add_rgd_rgd,add_rgd_in, add_rgd_ind,add_rgd_de, add_rgd_ded,add_rgd_ix, add_rgd_ixd,
+ add_rgd_rg, add_rgd_rgd,add_rgd_in, add_rgd_ind,add_rgd_de, add_rgd_ded,add_rgd_ix, add_rgd_ixd,
+ add_rgd_rg, add_rgd_rgd,add_rgd_in, add_rgd_ind,add_rgd_de, add_rgd_ded,add_rgd_ix, add_rgd_ixd,
+ /* 0x6300 */
+ add_rgd_rg, add_rgd_rgd,add_rgd_in, add_rgd_ind,add_rgd_de, add_rgd_ded,add_rgd_ix, add_rgd_ixd,
+ add_rgd_rg, add_rgd_rgd,add_rgd_in, add_rgd_ind,add_rgd_de, add_rgd_ded,add_rgd_ix, add_rgd_ixd,
+ add_rgd_rg, add_rgd_rgd,add_rgd_in, add_rgd_ind,add_rgd_de, add_rgd_ded,add_rgd_ix, add_rgd_ixd,
+ add_rgd_rg, add_rgd_rgd,add_rgd_in, add_rgd_ind,add_rgd_de, add_rgd_ded,add_rgd_ix, add_rgd_ixd,
+ /* 0x6400 */
+ add_in_rg, add_in_rgd, add_in_in, add_in_ind, add_in_de, add_in_ded, add_in_ix, add_in_ixd,
+ add_in_rg, add_in_rgd, add_in_in, add_in_ind, add_in_de, add_in_ded, add_in_ix, add_in_ixd,
+ add_in_rg, add_in_rgd, add_in_in, add_in_ind, add_in_de, add_in_ded, add_in_ix, add_in_ixd,
+ add_in_rg, add_in_rgd, add_in_in, add_in_ind, add_in_de, add_in_ded, add_in_ix, add_in_ixd,
+ /* 0x6500 */
+ add_in_rg, add_in_rgd, add_in_in, add_in_ind, add_in_de, add_in_ded, add_in_ix, add_in_ixd,
+ add_in_rg, add_in_rgd, add_in_in, add_in_ind, add_in_de, add_in_ded, add_in_ix, add_in_ixd,
+ add_in_rg, add_in_rgd, add_in_in, add_in_ind, add_in_de, add_in_ded, add_in_ix, add_in_ixd,
+ add_in_rg, add_in_rgd, add_in_in, add_in_ind, add_in_de, add_in_ded, add_in_ix, add_in_ixd,
+ /* 0x6600 */
+ add_ind_rg, add_ind_rgd,add_ind_in, add_ind_ind,add_ind_de, add_ind_ded,add_ind_ix, add_ind_ixd,
+ add_ind_rg, add_ind_rgd,add_ind_in, add_ind_ind,add_ind_de, add_ind_ded,add_ind_ix, add_ind_ixd,
+ add_ind_rg, add_ind_rgd,add_ind_in, add_ind_ind,add_ind_de, add_ind_ded,add_ind_ix, add_ind_ixd,
+ add_ind_rg, add_ind_rgd,add_ind_in, add_ind_ind,add_ind_de, add_ind_ded,add_ind_ix, add_ind_ixd,
+ /* 0x6700 */
+ add_ind_rg, add_ind_rgd,add_ind_in, add_ind_ind,add_ind_de, add_ind_ded,add_ind_ix, add_ind_ixd,
+ add_ind_rg, add_ind_rgd,add_ind_in, add_ind_ind,add_ind_de, add_ind_ded,add_ind_ix, add_ind_ixd,
+ add_ind_rg, add_ind_rgd,add_ind_in, add_ind_ind,add_ind_de, add_ind_ded,add_ind_ix, add_ind_ixd,
+ add_ind_rg, add_ind_rgd,add_ind_in, add_ind_ind,add_ind_de, add_ind_ded,add_ind_ix, add_ind_ixd,
+ /* 0x6800 */
+ add_de_rg, add_de_rgd, add_de_in, add_de_ind, add_de_de, add_de_ded, add_de_ix, add_de_ixd,
+ add_de_rg, add_de_rgd, add_de_in, add_de_ind, add_de_de, add_de_ded, add_de_ix, add_de_ixd,
+ add_de_rg, add_de_rgd, add_de_in, add_de_ind, add_de_de, add_de_ded, add_de_ix, add_de_ixd,
+ add_de_rg, add_de_rgd, add_de_in, add_de_ind, add_de_de, add_de_ded, add_de_ix, add_de_ixd,
+ /* 0x6900 */
+ add_de_rg, add_de_rgd, add_de_in, add_de_ind, add_de_de, add_de_ded, add_de_ix, add_de_ixd,
+ add_de_rg, add_de_rgd, add_de_in, add_de_ind, add_de_de, add_de_ded, add_de_ix, add_de_ixd,
+ add_de_rg, add_de_rgd, add_de_in, add_de_ind, add_de_de, add_de_ded, add_de_ix, add_de_ixd,
+ add_de_rg, add_de_rgd, add_de_in, add_de_ind, add_de_de, add_de_ded, add_de_ix, add_de_ixd,
+ /* 0x6a00 */
+ add_ded_rg, add_ded_rgd,add_ded_in, add_ded_ind,add_ded_de, add_ded_ded,add_ded_ix, add_ded_ixd,
+ add_ded_rg, add_ded_rgd,add_ded_in, add_ded_ind,add_ded_de, add_ded_ded,add_ded_ix, add_ded_ixd,
+ add_ded_rg, add_ded_rgd,add_ded_in, add_ded_ind,add_ded_de, add_ded_ded,add_ded_ix, add_ded_ixd,
+ add_ded_rg, add_ded_rgd,add_ded_in, add_ded_ind,add_ded_de, add_ded_ded,add_ded_ix, add_ded_ixd,
+ /* 0x6b00 */
+ add_ded_rg, add_ded_rgd,add_ded_in, add_ded_ind,add_ded_de, add_ded_ded,add_ded_ix, add_ded_ixd,
+ add_ded_rg, add_ded_rgd,add_ded_in, add_ded_ind,add_ded_de, add_ded_ded,add_ded_ix, add_ded_ixd,
+ add_ded_rg, add_ded_rgd,add_ded_in, add_ded_ind,add_ded_de, add_ded_ded,add_ded_ix, add_ded_ixd,
+ add_ded_rg, add_ded_rgd,add_ded_in, add_ded_ind,add_ded_de, add_ded_ded,add_ded_ix, add_ded_ixd,
+ /* 0x6c00 */
+ add_ix_rg, add_ix_rgd, add_ix_in, add_ix_ind, add_ix_de, add_ix_ded, add_ix_ix, add_ix_ixd,
+ add_ix_rg, add_ix_rgd, add_ix_in, add_ix_ind, add_ix_de, add_ix_ded, add_ix_ix, add_ix_ixd,
+ add_ix_rg, add_ix_rgd, add_ix_in, add_ix_ind, add_ix_de, add_ix_ded, add_ix_ix, add_ix_ixd,
+ add_ix_rg, add_ix_rgd, add_ix_in, add_ix_ind, add_ix_de, add_ix_ded, add_ix_ix, add_ix_ixd,
+ /* 0x6d00 */
+ add_ix_rg, add_ix_rgd, add_ix_in, add_ix_ind, add_ix_de, add_ix_ded, add_ix_ix, add_ix_ixd,
+ add_ix_rg, add_ix_rgd, add_ix_in, add_ix_ind, add_ix_de, add_ix_ded, add_ix_ix, add_ix_ixd,
+ add_ix_rg, add_ix_rgd, add_ix_in, add_ix_ind, add_ix_de, add_ix_ded, add_ix_ix, add_ix_ixd,
+ add_ix_rg, add_ix_rgd, add_ix_in, add_ix_ind, add_ix_de, add_ix_ded, add_ix_ix, add_ix_ixd,
+ /* 0x6e00 */
+ add_ixd_rg, add_ixd_rgd,add_ixd_in, add_ixd_ind,add_ixd_de, add_ixd_ded,add_ixd_ix, add_ixd_ixd,
+ add_ixd_rg, add_ixd_rgd,add_ixd_in, add_ixd_ind,add_ixd_de, add_ixd_ded,add_ixd_ix, add_ixd_ixd,
+ add_ixd_rg, add_ixd_rgd,add_ixd_in, add_ixd_ind,add_ixd_de, add_ixd_ded,add_ixd_ix, add_ixd_ixd,
+ add_ixd_rg, add_ixd_rgd,add_ixd_in, add_ixd_ind,add_ixd_de, add_ixd_ded,add_ixd_ix, add_ixd_ixd,
+ /* 0x6f00 */
+ add_ixd_rg, add_ixd_rgd,add_ixd_in, add_ixd_ind,add_ixd_de, add_ixd_ded,add_ixd_ix, add_ixd_ixd,
+ add_ixd_rg, add_ixd_rgd,add_ixd_in, add_ixd_ind,add_ixd_de, add_ixd_ded,add_ixd_ix, add_ixd_ixd,
+ add_ixd_rg, add_ixd_rgd,add_ixd_in, add_ixd_ind,add_ixd_de, add_ixd_ded,add_ixd_ix, add_ixd_ixd,
+ add_ixd_rg, add_ixd_rgd,add_ixd_in, add_ixd_ind,add_ixd_de, add_ixd_ded,add_ixd_ix, add_ixd_ixd,
+
+ /* 0x7000 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0x7100 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0x7200 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0x7300 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0x7400 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0x7500 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0x7600 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0x7700 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0x7800 */
+ xor_rg, xor_rgd, xor_in, xor_ind, xor_de, xor_ded, xor_ix, xor_ixd,
+ xor_rg, xor_rgd, xor_in, xor_ind, xor_de, xor_ded, xor_ix, xor_ixd,
+ xor_rg, xor_rgd, xor_in, xor_ind, xor_de, xor_ded, xor_ix, xor_ixd,
+ xor_rg, xor_rgd, xor_in, xor_ind, xor_de, xor_ded, xor_ix, xor_ixd,
+ /* 0x7900 */
+ xor_rg, xor_rgd, xor_in, xor_ind, xor_de, xor_ded, xor_ix, xor_ixd,
+ xor_rg, xor_rgd, xor_in, xor_ind, xor_de, xor_ded, xor_ix, xor_ixd,
+ xor_rg, xor_rgd, xor_in, xor_ind, xor_de, xor_ded, xor_ix, xor_ixd,
+ xor_rg, xor_rgd, xor_in, xor_ind, xor_de, xor_ded, xor_ix, xor_ixd,
+ /* 0x7a00 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0x7b00 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0x7c00 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0x7d00 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0x7e00 */
+ sob, sob, sob, sob, sob, sob, sob, sob,
+ sob, sob, sob, sob, sob, sob, sob, sob,
+ sob, sob, sob, sob, sob, sob, sob, sob,
+ sob, sob, sob, sob, sob, sob, sob, sob,
+ /* 0x7f00 */
+ sob, sob, sob, sob, sob, sob, sob, sob,
+ sob, sob, sob, sob, sob, sob, sob, sob,
+ sob, sob, sob, sob, sob, sob, sob, sob,
+ sob, sob, sob, sob, sob, sob, sob, sob,
+
+ /* 0x8000 */
+ bpl, bpl, bpl, bpl, bpl, bpl, bpl, bpl,
+ bpl, bpl, bpl, bpl, bpl, bpl, bpl, bpl,
+ bpl, bpl, bpl, bpl, bpl, bpl, bpl, bpl,
+ bpl, bpl, bpl, bpl, bpl, bpl, bpl, bpl,
+ /* 0x8100 */
+ bmi, bmi, bmi, bmi, bmi, bmi, bmi, bmi,
+ bmi, bmi, bmi, bmi, bmi, bmi, bmi, bmi,
+ bmi, bmi, bmi, bmi, bmi, bmi, bmi, bmi,
+ bmi, bmi, bmi, bmi, bmi, bmi, bmi, bmi,
+ /* 0x8200 */
+ bhi, bhi, bhi, bhi, bhi, bhi, bhi, bhi,
+ bhi, bhi, bhi, bhi, bhi, bhi, bhi, bhi,
+ bhi, bhi, bhi, bhi, bhi, bhi, bhi, bhi,
+ bhi, bhi, bhi, bhi, bhi, bhi, bhi, bhi,
+ /* 0x8300 */
+ blos, blos, blos, blos, blos, blos, blos, blos,
+ blos, blos, blos, blos, blos, blos, blos, blos,
+ blos, blos, blos, blos, blos, blos, blos, blos,
+ blos, blos, blos, blos, blos, blos, blos, blos,
+ /* 0x8400 */
+ bvc, bvc, bvc, bvc, bvc, bvc, bvc, bvc,
+ bvc, bvc, bvc, bvc, bvc, bvc, bvc, bvc,
+ bvc, bvc, bvc, bvc, bvc, bvc, bvc, bvc,
+ bvc, bvc, bvc, bvc, bvc, bvc, bvc, bvc,
+ /* 0x8500 */
+ bvs, bvs, bvs, bvs, bvs, bvs, bvs, bvs,
+ bvs, bvs, bvs, bvs, bvs, bvs, bvs, bvs,
+ bvs, bvs, bvs, bvs, bvs, bvs, bvs, bvs,
+ bvs, bvs, bvs, bvs, bvs, bvs, bvs, bvs,
+ /* 0x8600 */
+ bcc, bcc, bcc, bcc, bcc, bcc, bcc, bcc,
+ bcc, bcc, bcc, bcc, bcc, bcc, bcc, bcc,
+ bcc, bcc, bcc, bcc, bcc, bcc, bcc, bcc,
+ bcc, bcc, bcc, bcc, bcc, bcc, bcc, bcc,
+ /* 0x8700 */
+ bcs, bcs, bcs, bcs, bcs, bcs, bcs, bcs,
+ bcs, bcs, bcs, bcs, bcs, bcs, bcs, bcs,
+ bcs, bcs, bcs, bcs, bcs, bcs, bcs, bcs,
+ bcs, bcs, bcs, bcs, bcs, bcs, bcs, bcs,
+ /* 0x8800 */
+ emt, emt, emt, emt, emt, emt, emt, emt,
+ emt, emt, emt, emt, emt, emt, emt, emt,
+ emt, emt, emt, emt, emt, emt, emt, emt,
+ emt, emt, emt, emt, emt, emt, emt, emt,
+ /* 0x8900 */
+ trap, trap, trap, trap, trap, trap, trap, trap,
+ trap, trap, trap, trap, trap, trap, trap, trap,
+ trap, trap, trap, trap, trap, trap, trap, trap,
+ trap, trap, trap, trap, trap, trap, trap, trap,
+ /* 0x8a00 */
+ clrb_rg, clrb_rgd, clrb_in, clrb_ind, clrb_de, clrb_ded, clrb_ix, clrb_ixd,
+ comb_rg, comb_rgd, comb_in, comb_ind, comb_de, comb_ded, comb_ix, comb_ixd,
+ incb_rg, incb_rgd, incb_in, incb_ind, incb_de, incb_ded, incb_ix, incb_ixd,
+ decb_rg, decb_rgd, decb_in, decb_ind, decb_de, decb_ded, decb_ix, decb_ixd,
+ /* 0x8b00 */
+ negb_rg, negb_rgd, negb_in, negb_ind, negb_de, negb_ded, negb_ix, negb_ixd,
+ adcb_rg, adcb_rgd, adcb_in, adcb_ind, adcb_de, adcb_ded, adcb_ix, adcb_ixd,
+ sbcb_rg, sbcb_rgd, sbcb_in, sbcb_ind, sbcb_de, sbcb_ded, sbcb_ix, sbcb_ixd,
+ tstb_rg, tstb_rgd, tstb_in, tstb_ind, tstb_de, tstb_ded, tstb_ix, tstb_ixd,
+ /* 0x8c00 */
+ rorb_rg, rorb_rgd, rorb_in, rorb_ind, rorb_de, rorb_ded, rorb_ix, rorb_ixd,
+ rolb_rg, rolb_rgd, rolb_in, rolb_ind, rolb_de, rolb_ded, rolb_ix, rolb_ixd,
+ asrb_rg, asrb_rgd, asrb_in, asrb_ind, asrb_de, asrb_ded, asrb_ix, asrb_ixd,
+ aslb_rg, aslb_rgd, aslb_in, aslb_ind, aslb_de, aslb_ded, aslb_ix, aslb_ixd,
+ /* 0x8d00 */
+ mtps_rg, mtps_rgd, mtps_in, mtps_ind, mtps_de, mtps_ded, mtps_ix, mtps_ixd,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ mfps_rg, mfps_rgd, mfps_in, mfps_ind, mfps_de, mfps_ded, mfps_ix, mfps_ixd,
+ /* 0x8e00 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0x8f00 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+
+ /* 0x9000 */
+ movb_rg_rg, movb_rg_rgd,movb_rg_in, movb_rg_ind,movb_rg_de, movb_rg_ded,movb_rg_ix, movb_rg_ixd,
+ movb_rg_rg, movb_rg_rgd,movb_rg_in, movb_rg_ind,movb_rg_de, movb_rg_ded,movb_rg_ix, movb_rg_ixd,
+ movb_rg_rg, movb_rg_rgd,movb_rg_in, movb_rg_ind,movb_rg_de, movb_rg_ded,movb_rg_ix, movb_rg_ixd,
+ movb_rg_rg, movb_rg_rgd,movb_rg_in, movb_rg_ind,movb_rg_de, movb_rg_ded,movb_rg_ix, movb_rg_ixd,
+ /* 0x9100 */
+ movb_rg_rg, movb_rg_rgd,movb_rg_in, movb_rg_ind,movb_rg_de, movb_rg_ded,movb_rg_ix, movb_rg_ixd,
+ movb_rg_rg, movb_rg_rgd,movb_rg_in, movb_rg_ind,movb_rg_de, movb_rg_ded,movb_rg_ix, movb_rg_ixd,
+ movb_rg_rg, movb_rg_rgd,movb_rg_in, movb_rg_ind,movb_rg_de, movb_rg_ded,movb_rg_ix, movb_rg_ixd,
+ movb_rg_rg, movb_rg_rgd,movb_rg_in, movb_rg_ind,movb_rg_de, movb_rg_ded,movb_rg_ix, movb_rg_ixd,
+ /* 0x9200 */
+ movb_rgd_rg,movb_rgd_rgd,movb_rgd_in,movb_rgd_ind,movb_rgd_de,movb_rgd_ded,movb_rgd_ix,movb_rgd_ixd,
+ movb_rgd_rg,movb_rgd_rgd,movb_rgd_in,movb_rgd_ind,movb_rgd_de,movb_rgd_ded,movb_rgd_ix,movb_rgd_ixd,
+ movb_rgd_rg,movb_rgd_rgd,movb_rgd_in,movb_rgd_ind,movb_rgd_de,movb_rgd_ded,movb_rgd_ix,movb_rgd_ixd,
+ movb_rgd_rg,movb_rgd_rgd,movb_rgd_in,movb_rgd_ind,movb_rgd_de,movb_rgd_ded,movb_rgd_ix,movb_rgd_ixd,
+ /* 0x9300 */
+ movb_rgd_rg,movb_rgd_rgd,movb_rgd_in,movb_rgd_ind,movb_rgd_de,movb_rgd_ded,movb_rgd_ix,movb_rgd_ixd,
+ movb_rgd_rg,movb_rgd_rgd,movb_rgd_in,movb_rgd_ind,movb_rgd_de,movb_rgd_ded,movb_rgd_ix,movb_rgd_ixd,
+ movb_rgd_rg,movb_rgd_rgd,movb_rgd_in,movb_rgd_ind,movb_rgd_de,movb_rgd_ded,movb_rgd_ix,movb_rgd_ixd,
+ movb_rgd_rg,movb_rgd_rgd,movb_rgd_in,movb_rgd_ind,movb_rgd_de,movb_rgd_ded,movb_rgd_ix,movb_rgd_ixd,
+ /* 0x9400 */
+ movb_in_rg, movb_in_rgd,movb_in_in, movb_in_ind,movb_in_de, movb_in_ded,movb_in_ix, movb_in_ixd,
+ movb_in_rg, movb_in_rgd,movb_in_in, movb_in_ind,movb_in_de, movb_in_ded,movb_in_ix, movb_in_ixd,
+ movb_in_rg, movb_in_rgd,movb_in_in, movb_in_ind,movb_in_de, movb_in_ded,movb_in_ix, movb_in_ixd,
+ movb_in_rg, movb_in_rgd,movb_in_in, movb_in_ind,movb_in_de, movb_in_ded,movb_in_ix, movb_in_ixd,
+ /* 0x9500 */
+ movb_in_rg, movb_in_rgd,movb_in_in, movb_in_ind,movb_in_de, movb_in_ded,movb_in_ix, movb_in_ixd,
+ movb_in_rg, movb_in_rgd,movb_in_in, movb_in_ind,movb_in_de, movb_in_ded,movb_in_ix, movb_in_ixd,
+ movb_in_rg, movb_in_rgd,movb_in_in, movb_in_ind,movb_in_de, movb_in_ded,movb_in_ix, movb_in_ixd,
+ movb_in_rg, movb_in_rgd,movb_in_in, movb_in_ind,movb_in_de, movb_in_ded,movb_in_ix, movb_in_ixd,
+ /* 0x9600 */
+ movb_ind_rg,movb_ind_rgd,movb_ind_in,movb_ind_ind,movb_ind_de,movb_ind_ded,movb_ind_ix,movb_ind_ixd,
+ movb_ind_rg,movb_ind_rgd,movb_ind_in,movb_ind_ind,movb_ind_de,movb_ind_ded,movb_ind_ix,movb_ind_ixd,
+ movb_ind_rg,movb_ind_rgd,movb_ind_in,movb_ind_ind,movb_ind_de,movb_ind_ded,movb_ind_ix,movb_ind_ixd,
+ movb_ind_rg,movb_ind_rgd,movb_ind_in,movb_ind_ind,movb_ind_de,movb_ind_ded,movb_ind_ix,movb_ind_ixd,
+ /* 0x9700 */
+ movb_ind_rg,movb_ind_rgd,movb_ind_in,movb_ind_ind,movb_ind_de,movb_ind_ded,movb_ind_ix,movb_ind_ixd,
+ movb_ind_rg,movb_ind_rgd,movb_ind_in,movb_ind_ind,movb_ind_de,movb_ind_ded,movb_ind_ix,movb_ind_ixd,
+ movb_ind_rg,movb_ind_rgd,movb_ind_in,movb_ind_ind,movb_ind_de,movb_ind_ded,movb_ind_ix,movb_ind_ixd,
+ movb_ind_rg,movb_ind_rgd,movb_ind_in,movb_ind_ind,movb_ind_de,movb_ind_ded,movb_ind_ix,movb_ind_ixd,
+ /* 0x9800 */
+ movb_de_rg, movb_de_rgd,movb_de_in, movb_de_ind,movb_de_de, movb_de_ded,movb_de_ix, movb_de_ixd,
+ movb_de_rg, movb_de_rgd,movb_de_in, movb_de_ind,movb_de_de, movb_de_ded,movb_de_ix, movb_de_ixd,
+ movb_de_rg, movb_de_rgd,movb_de_in, movb_de_ind,movb_de_de, movb_de_ded,movb_de_ix, movb_de_ixd,
+ movb_de_rg, movb_de_rgd,movb_de_in, movb_de_ind,movb_de_de, movb_de_ded,movb_de_ix, movb_de_ixd,
+ /* 0x9900 */
+ movb_de_rg, movb_de_rgd,movb_de_in, movb_de_ind,movb_de_de, movb_de_ded,movb_de_ix, movb_de_ixd,
+ movb_de_rg, movb_de_rgd,movb_de_in, movb_de_ind,movb_de_de, movb_de_ded,movb_de_ix, movb_de_ixd,
+ movb_de_rg, movb_de_rgd,movb_de_in, movb_de_ind,movb_de_de, movb_de_ded,movb_de_ix, movb_de_ixd,
+ movb_de_rg, movb_de_rgd,movb_de_in, movb_de_ind,movb_de_de, movb_de_ded,movb_de_ix, movb_de_ixd,
+ /* 0x9a00 */
+ movb_ded_rg,movb_ded_rgd,movb_ded_in,movb_ded_ind,movb_ded_de,movb_ded_ded,movb_ded_ix,movb_ded_ixd,
+ movb_ded_rg,movb_ded_rgd,movb_ded_in,movb_ded_ind,movb_ded_de,movb_ded_ded,movb_ded_ix,movb_ded_ixd,
+ movb_ded_rg,movb_ded_rgd,movb_ded_in,movb_ded_ind,movb_ded_de,movb_ded_ded,movb_ded_ix,movb_ded_ixd,
+ movb_ded_rg,movb_ded_rgd,movb_ded_in,movb_ded_ind,movb_ded_de,movb_ded_ded,movb_ded_ix,movb_ded_ixd,
+ /* 0x9b00 */
+ movb_ded_rg,movb_ded_rgd,movb_ded_in,movb_ded_ind,movb_ded_de,movb_ded_ded,movb_ded_ix,movb_ded_ixd,
+ movb_ded_rg,movb_ded_rgd,movb_ded_in,movb_ded_ind,movb_ded_de,movb_ded_ded,movb_ded_ix,movb_ded_ixd,
+ movb_ded_rg,movb_ded_rgd,movb_ded_in,movb_ded_ind,movb_ded_de,movb_ded_ded,movb_ded_ix,movb_ded_ixd,
+ movb_ded_rg,movb_ded_rgd,movb_ded_in,movb_ded_ind,movb_ded_de,movb_ded_ded,movb_ded_ix,movb_ded_ixd,
+ /* 0x9c00 */
+ movb_ix_rg, movb_ix_rgd,movb_ix_in, movb_ix_ind,movb_ix_de, movb_ix_ded,movb_ix_ix, movb_ix_ixd,
+ movb_ix_rg, movb_ix_rgd,movb_ix_in, movb_ix_ind,movb_ix_de, movb_ix_ded,movb_ix_ix, movb_ix_ixd,
+ movb_ix_rg, movb_ix_rgd,movb_ix_in, movb_ix_ind,movb_ix_de, movb_ix_ded,movb_ix_ix, movb_ix_ixd,
+ movb_ix_rg, movb_ix_rgd,movb_ix_in, movb_ix_ind,movb_ix_de, movb_ix_ded,movb_ix_ix, movb_ix_ixd,
+ /* 0x9d00 */
+ movb_ix_rg, movb_ix_rgd,movb_ix_in, movb_ix_ind,movb_ix_de, movb_ix_ded,movb_ix_ix, movb_ix_ixd,
+ movb_ix_rg, movb_ix_rgd,movb_ix_in, movb_ix_ind,movb_ix_de, movb_ix_ded,movb_ix_ix, movb_ix_ixd,
+ movb_ix_rg, movb_ix_rgd,movb_ix_in, movb_ix_ind,movb_ix_de, movb_ix_ded,movb_ix_ix, movb_ix_ixd,
+ movb_ix_rg, movb_ix_rgd,movb_ix_in, movb_ix_ind,movb_ix_de, movb_ix_ded,movb_ix_ix, movb_ix_ixd,
+ /* 0x9e00 */
+ movb_ixd_rg,movb_ixd_rgd,movb_ixd_in,movb_ixd_ind,movb_ixd_de,movb_ixd_ded,movb_ixd_ix,movb_ixd_ixd,
+ movb_ixd_rg,movb_ixd_rgd,movb_ixd_in,movb_ixd_ind,movb_ixd_de,movb_ixd_ded,movb_ixd_ix,movb_ixd_ixd,
+ movb_ixd_rg,movb_ixd_rgd,movb_ixd_in,movb_ixd_ind,movb_ixd_de,movb_ixd_ded,movb_ixd_ix,movb_ixd_ixd,
+ movb_ixd_rg,movb_ixd_rgd,movb_ixd_in,movb_ixd_ind,movb_ixd_de,movb_ixd_ded,movb_ixd_ix,movb_ixd_ixd,
+ /* 0x9f00 */
+ movb_ixd_rg,movb_ixd_rgd,movb_ixd_in,movb_ixd_ind,movb_ixd_de,movb_ixd_ded,movb_ixd_ix,movb_ixd_ixd,
+ movb_ixd_rg,movb_ixd_rgd,movb_ixd_in,movb_ixd_ind,movb_ixd_de,movb_ixd_ded,movb_ixd_ix,movb_ixd_ixd,
+ movb_ixd_rg,movb_ixd_rgd,movb_ixd_in,movb_ixd_ind,movb_ixd_de,movb_ixd_ded,movb_ixd_ix,movb_ixd_ixd,
+ movb_ixd_rg,movb_ixd_rgd,movb_ixd_in,movb_ixd_ind,movb_ixd_de,movb_ixd_ded,movb_ixd_ix,movb_ixd_ixd,
+
+ /* 0xa000 */
+ cmpb_rg_rg, cmpb_rg_rgd,cmpb_rg_in, cmpb_rg_ind,cmpb_rg_de, cmpb_rg_ded,cmpb_rg_ix, cmpb_rg_ixd,
+ cmpb_rg_rg, cmpb_rg_rgd,cmpb_rg_in, cmpb_rg_ind,cmpb_rg_de, cmpb_rg_ded,cmpb_rg_ix, cmpb_rg_ixd,
+ cmpb_rg_rg, cmpb_rg_rgd,cmpb_rg_in, cmpb_rg_ind,cmpb_rg_de, cmpb_rg_ded,cmpb_rg_ix, cmpb_rg_ixd,
+ cmpb_rg_rg, cmpb_rg_rgd,cmpb_rg_in, cmpb_rg_ind,cmpb_rg_de, cmpb_rg_ded,cmpb_rg_ix, cmpb_rg_ixd,
+ /* 0xa100 */
+ cmpb_rg_rg, cmpb_rg_rgd,cmpb_rg_in, cmpb_rg_ind,cmpb_rg_de, cmpb_rg_ded,cmpb_rg_ix, cmpb_rg_ixd,
+ cmpb_rg_rg, cmpb_rg_rgd,cmpb_rg_in, cmpb_rg_ind,cmpb_rg_de, cmpb_rg_ded,cmpb_rg_ix, cmpb_rg_ixd,
+ cmpb_rg_rg, cmpb_rg_rgd,cmpb_rg_in, cmpb_rg_ind,cmpb_rg_de, cmpb_rg_ded,cmpb_rg_ix, cmpb_rg_ixd,
+ cmpb_rg_rg, cmpb_rg_rgd,cmpb_rg_in, cmpb_rg_ind,cmpb_rg_de, cmpb_rg_ded,cmpb_rg_ix, cmpb_rg_ixd,
+ /* 0xa200 */
+ cmpb_rgd_rg,cmpb_rgd_rgd,cmpb_rgd_in,cmpb_rgd_ind,cmpb_rgd_de,cmpb_rgd_ded,cmpb_rgd_ix,cmpb_rgd_ixd,
+ cmpb_rgd_rg,cmpb_rgd_rgd,cmpb_rgd_in,cmpb_rgd_ind,cmpb_rgd_de,cmpb_rgd_ded,cmpb_rgd_ix,cmpb_rgd_ixd,
+ cmpb_rgd_rg,cmpb_rgd_rgd,cmpb_rgd_in,cmpb_rgd_ind,cmpb_rgd_de,cmpb_rgd_ded,cmpb_rgd_ix,cmpb_rgd_ixd,
+ cmpb_rgd_rg,cmpb_rgd_rgd,cmpb_rgd_in,cmpb_rgd_ind,cmpb_rgd_de,cmpb_rgd_ded,cmpb_rgd_ix,cmpb_rgd_ixd,
+ /* 0xa300 */
+ cmpb_rgd_rg,cmpb_rgd_rgd,cmpb_rgd_in,cmpb_rgd_ind,cmpb_rgd_de,cmpb_rgd_ded,cmpb_rgd_ix,cmpb_rgd_ixd,
+ cmpb_rgd_rg,cmpb_rgd_rgd,cmpb_rgd_in,cmpb_rgd_ind,cmpb_rgd_de,cmpb_rgd_ded,cmpb_rgd_ix,cmpb_rgd_ixd,
+ cmpb_rgd_rg,cmpb_rgd_rgd,cmpb_rgd_in,cmpb_rgd_ind,cmpb_rgd_de,cmpb_rgd_ded,cmpb_rgd_ix,cmpb_rgd_ixd,
+ cmpb_rgd_rg,cmpb_rgd_rgd,cmpb_rgd_in,cmpb_rgd_ind,cmpb_rgd_de,cmpb_rgd_ded,cmpb_rgd_ix,cmpb_rgd_ixd,
+ /* 0xa400 */
+ cmpb_in_rg, cmpb_in_rgd,cmpb_in_in, cmpb_in_ind,cmpb_in_de, cmpb_in_ded,cmpb_in_ix, cmpb_in_ixd,
+ cmpb_in_rg, cmpb_in_rgd,cmpb_in_in, cmpb_in_ind,cmpb_in_de, cmpb_in_ded,cmpb_in_ix, cmpb_in_ixd,
+ cmpb_in_rg, cmpb_in_rgd,cmpb_in_in, cmpb_in_ind,cmpb_in_de, cmpb_in_ded,cmpb_in_ix, cmpb_in_ixd,
+ cmpb_in_rg, cmpb_in_rgd,cmpb_in_in, cmpb_in_ind,cmpb_in_de, cmpb_in_ded,cmpb_in_ix, cmpb_in_ixd,
+ /* 0xa500 */
+ cmpb_in_rg, cmpb_in_rgd,cmpb_in_in, cmpb_in_ind,cmpb_in_de, cmpb_in_ded,cmpb_in_ix, cmpb_in_ixd,
+ cmpb_in_rg, cmpb_in_rgd,cmpb_in_in, cmpb_in_ind,cmpb_in_de, cmpb_in_ded,cmpb_in_ix, cmpb_in_ixd,
+ cmpb_in_rg, cmpb_in_rgd,cmpb_in_in, cmpb_in_ind,cmpb_in_de, cmpb_in_ded,cmpb_in_ix, cmpb_in_ixd,
+ cmpb_in_rg, cmpb_in_rgd,cmpb_in_in, cmpb_in_ind,cmpb_in_de, cmpb_in_ded,cmpb_in_ix, cmpb_in_ixd,
+ /* 0xa600 */
+ cmpb_ind_rg,cmpb_ind_rgd,cmpb_ind_in,cmpb_ind_ind,cmpb_ind_de,cmpb_ind_ded,cmpb_ind_ix,cmpb_ind_ixd,
+ cmpb_ind_rg,cmpb_ind_rgd,cmpb_ind_in,cmpb_ind_ind,cmpb_ind_de,cmpb_ind_ded,cmpb_ind_ix,cmpb_ind_ixd,
+ cmpb_ind_rg,cmpb_ind_rgd,cmpb_ind_in,cmpb_ind_ind,cmpb_ind_de,cmpb_ind_ded,cmpb_ind_ix,cmpb_ind_ixd,
+ cmpb_ind_rg,cmpb_ind_rgd,cmpb_ind_in,cmpb_ind_ind,cmpb_ind_de,cmpb_ind_ded,cmpb_ind_ix,cmpb_ind_ixd,
+ /* 0xa700 */
+ cmpb_ind_rg,cmpb_ind_rgd,cmpb_ind_in,cmpb_ind_ind,cmpb_ind_de,cmpb_ind_ded,cmpb_ind_ix,cmpb_ind_ixd,
+ cmpb_ind_rg,cmpb_ind_rgd,cmpb_ind_in,cmpb_ind_ind,cmpb_ind_de,cmpb_ind_ded,cmpb_ind_ix,cmpb_ind_ixd,
+ cmpb_ind_rg,cmpb_ind_rgd,cmpb_ind_in,cmpb_ind_ind,cmpb_ind_de,cmpb_ind_ded,cmpb_ind_ix,cmpb_ind_ixd,
+ cmpb_ind_rg,cmpb_ind_rgd,cmpb_ind_in,cmpb_ind_ind,cmpb_ind_de,cmpb_ind_ded,cmpb_ind_ix,cmpb_ind_ixd,
+ /* 0xa800 */
+ cmpb_de_rg, cmpb_de_rgd,cmpb_de_in, cmpb_de_ind,cmpb_de_de, cmpb_de_ded,cmpb_de_ix, cmpb_de_ixd,
+ cmpb_de_rg, cmpb_de_rgd,cmpb_de_in, cmpb_de_ind,cmpb_de_de, cmpb_de_ded,cmpb_de_ix, cmpb_de_ixd,
+ cmpb_de_rg, cmpb_de_rgd,cmpb_de_in, cmpb_de_ind,cmpb_de_de, cmpb_de_ded,cmpb_de_ix, cmpb_de_ixd,
+ cmpb_de_rg, cmpb_de_rgd,cmpb_de_in, cmpb_de_ind,cmpb_de_de, cmpb_de_ded,cmpb_de_ix, cmpb_de_ixd,
+ /* 0xa900 */
+ cmpb_de_rg, cmpb_de_rgd,cmpb_de_in, cmpb_de_ind,cmpb_de_de, cmpb_de_ded,cmpb_de_ix, cmpb_de_ixd,
+ cmpb_de_rg, cmpb_de_rgd,cmpb_de_in, cmpb_de_ind,cmpb_de_de, cmpb_de_ded,cmpb_de_ix, cmpb_de_ixd,
+ cmpb_de_rg, cmpb_de_rgd,cmpb_de_in, cmpb_de_ind,cmpb_de_de, cmpb_de_ded,cmpb_de_ix, cmpb_de_ixd,
+ cmpb_de_rg, cmpb_de_rgd,cmpb_de_in, cmpb_de_ind,cmpb_de_de, cmpb_de_ded,cmpb_de_ix, cmpb_de_ixd,
+ /* 0xaa00 */
+ cmpb_ded_rg,cmpb_ded_rgd,cmpb_ded_in,cmpb_ded_ind,cmpb_ded_de,cmpb_ded_ded,cmpb_ded_ix,cmpb_ded_ixd,
+ cmpb_ded_rg,cmpb_ded_rgd,cmpb_ded_in,cmpb_ded_ind,cmpb_ded_de,cmpb_ded_ded,cmpb_ded_ix,cmpb_ded_ixd,
+ cmpb_ded_rg,cmpb_ded_rgd,cmpb_ded_in,cmpb_ded_ind,cmpb_ded_de,cmpb_ded_ded,cmpb_ded_ix,cmpb_ded_ixd,
+ cmpb_ded_rg,cmpb_ded_rgd,cmpb_ded_in,cmpb_ded_ind,cmpb_ded_de,cmpb_ded_ded,cmpb_ded_ix,cmpb_ded_ixd,
+ /* 0xab00 */
+ cmpb_ded_rg,cmpb_ded_rgd,cmpb_ded_in,cmpb_ded_ind,cmpb_ded_de,cmpb_ded_ded,cmpb_ded_ix,cmpb_ded_ixd,
+ cmpb_ded_rg,cmpb_ded_rgd,cmpb_ded_in,cmpb_ded_ind,cmpb_ded_de,cmpb_ded_ded,cmpb_ded_ix,cmpb_ded_ixd,
+ cmpb_ded_rg,cmpb_ded_rgd,cmpb_ded_in,cmpb_ded_ind,cmpb_ded_de,cmpb_ded_ded,cmpb_ded_ix,cmpb_ded_ixd,
+ cmpb_ded_rg,cmpb_ded_rgd,cmpb_ded_in,cmpb_ded_ind,cmpb_ded_de,cmpb_ded_ded,cmpb_ded_ix,cmpb_ded_ixd,
+ /* 0xac00 */
+ cmpb_ix_rg, cmpb_ix_rgd,cmpb_ix_in, cmpb_ix_ind,cmpb_ix_de, cmpb_ix_ded,cmpb_ix_ix, cmpb_ix_ixd,
+ cmpb_ix_rg, cmpb_ix_rgd,cmpb_ix_in, cmpb_ix_ind,cmpb_ix_de, cmpb_ix_ded,cmpb_ix_ix, cmpb_ix_ixd,
+ cmpb_ix_rg, cmpb_ix_rgd,cmpb_ix_in, cmpb_ix_ind,cmpb_ix_de, cmpb_ix_ded,cmpb_ix_ix, cmpb_ix_ixd,
+ cmpb_ix_rg, cmpb_ix_rgd,cmpb_ix_in, cmpb_ix_ind,cmpb_ix_de, cmpb_ix_ded,cmpb_ix_ix, cmpb_ix_ixd,
+ /* 0xad00 */
+ cmpb_ix_rg, cmpb_ix_rgd,cmpb_ix_in, cmpb_ix_ind,cmpb_ix_de, cmpb_ix_ded,cmpb_ix_ix, cmpb_ix_ixd,
+ cmpb_ix_rg, cmpb_ix_rgd,cmpb_ix_in, cmpb_ix_ind,cmpb_ix_de, cmpb_ix_ded,cmpb_ix_ix, cmpb_ix_ixd,
+ cmpb_ix_rg, cmpb_ix_rgd,cmpb_ix_in, cmpb_ix_ind,cmpb_ix_de, cmpb_ix_ded,cmpb_ix_ix, cmpb_ix_ixd,
+ cmpb_ix_rg, cmpb_ix_rgd,cmpb_ix_in, cmpb_ix_ind,cmpb_ix_de, cmpb_ix_ded,cmpb_ix_ix, cmpb_ix_ixd,
+ /* 0xae00 */
+ cmpb_ixd_rg,cmpb_ixd_rgd,cmpb_ixd_in,cmpb_ixd_ind,cmpb_ixd_de,cmpb_ixd_ded,cmpb_ixd_ix,cmpb_ixd_ixd,
+ cmpb_ixd_rg,cmpb_ixd_rgd,cmpb_ixd_in,cmpb_ixd_ind,cmpb_ixd_de,cmpb_ixd_ded,cmpb_ixd_ix,cmpb_ixd_ixd,
+ cmpb_ixd_rg,cmpb_ixd_rgd,cmpb_ixd_in,cmpb_ixd_ind,cmpb_ixd_de,cmpb_ixd_ded,cmpb_ixd_ix,cmpb_ixd_ixd,
+ cmpb_ixd_rg,cmpb_ixd_rgd,cmpb_ixd_in,cmpb_ixd_ind,cmpb_ixd_de,cmpb_ixd_ded,cmpb_ixd_ix,cmpb_ixd_ixd,
+ /* 0xaf00 */
+ cmpb_ixd_rg,cmpb_ixd_rgd,cmpb_ixd_in,cmpb_ixd_ind,cmpb_ixd_de,cmpb_ixd_ded,cmpb_ixd_ix,cmpb_ixd_ixd,
+ cmpb_ixd_rg,cmpb_ixd_rgd,cmpb_ixd_in,cmpb_ixd_ind,cmpb_ixd_de,cmpb_ixd_ded,cmpb_ixd_ix,cmpb_ixd_ixd,
+ cmpb_ixd_rg,cmpb_ixd_rgd,cmpb_ixd_in,cmpb_ixd_ind,cmpb_ixd_de,cmpb_ixd_ded,cmpb_ixd_ix,cmpb_ixd_ixd,
+ cmpb_ixd_rg,cmpb_ixd_rgd,cmpb_ixd_in,cmpb_ixd_ind,cmpb_ixd_de,cmpb_ixd_ded,cmpb_ixd_ix,cmpb_ixd_ixd,
+
+ /* 0xb000 */
+ bitb_rg_rg, bitb_rg_rgd,bitb_rg_in, bitb_rg_ind,bitb_rg_de, bitb_rg_ded,bitb_rg_ix, bitb_rg_ixd,
+ bitb_rg_rg, bitb_rg_rgd,bitb_rg_in, bitb_rg_ind,bitb_rg_de, bitb_rg_ded,bitb_rg_ix, bitb_rg_ixd,
+ bitb_rg_rg, bitb_rg_rgd,bitb_rg_in, bitb_rg_ind,bitb_rg_de, bitb_rg_ded,bitb_rg_ix, bitb_rg_ixd,
+ bitb_rg_rg, bitb_rg_rgd,bitb_rg_in, bitb_rg_ind,bitb_rg_de, bitb_rg_ded,bitb_rg_ix, bitb_rg_ixd,
+ /* 0xb100 */
+ bitb_rg_rg, bitb_rg_rgd,bitb_rg_in, bitb_rg_ind,bitb_rg_de, bitb_rg_ded,bitb_rg_ix, bitb_rg_ixd,
+ bitb_rg_rg, bitb_rg_rgd,bitb_rg_in, bitb_rg_ind,bitb_rg_de, bitb_rg_ded,bitb_rg_ix, bitb_rg_ixd,
+ bitb_rg_rg, bitb_rg_rgd,bitb_rg_in, bitb_rg_ind,bitb_rg_de, bitb_rg_ded,bitb_rg_ix, bitb_rg_ixd,
+ bitb_rg_rg, bitb_rg_rgd,bitb_rg_in, bitb_rg_ind,bitb_rg_de, bitb_rg_ded,bitb_rg_ix, bitb_rg_ixd,
+ /* 0xb200 */
+ bitb_rgd_rg,bitb_rgd_rgd,bitb_rgd_in,bitb_rgd_ind,bitb_rgd_de,bitb_rgd_ded,bitb_rgd_ix,bitb_rgd_ixd,
+ bitb_rgd_rg,bitb_rgd_rgd,bitb_rgd_in,bitb_rgd_ind,bitb_rgd_de,bitb_rgd_ded,bitb_rgd_ix,bitb_rgd_ixd,
+ bitb_rgd_rg,bitb_rgd_rgd,bitb_rgd_in,bitb_rgd_ind,bitb_rgd_de,bitb_rgd_ded,bitb_rgd_ix,bitb_rgd_ixd,
+ bitb_rgd_rg,bitb_rgd_rgd,bitb_rgd_in,bitb_rgd_ind,bitb_rgd_de,bitb_rgd_ded,bitb_rgd_ix,bitb_rgd_ixd,
+ /* 0xb300 */
+ bitb_rgd_rg,bitb_rgd_rgd,bitb_rgd_in,bitb_rgd_ind,bitb_rgd_de,bitb_rgd_ded,bitb_rgd_ix,bitb_rgd_ixd,
+ bitb_rgd_rg,bitb_rgd_rgd,bitb_rgd_in,bitb_rgd_ind,bitb_rgd_de,bitb_rgd_ded,bitb_rgd_ix,bitb_rgd_ixd,
+ bitb_rgd_rg,bitb_rgd_rgd,bitb_rgd_in,bitb_rgd_ind,bitb_rgd_de,bitb_rgd_ded,bitb_rgd_ix,bitb_rgd_ixd,
+ bitb_rgd_rg,bitb_rgd_rgd,bitb_rgd_in,bitb_rgd_ind,bitb_rgd_de,bitb_rgd_ded,bitb_rgd_ix,bitb_rgd_ixd,
+ /* 0xb400 */
+ bitb_in_rg, bitb_in_rgd,bitb_in_in, bitb_in_ind,bitb_in_de, bitb_in_ded,bitb_in_ix, bitb_in_ixd,
+ bitb_in_rg, bitb_in_rgd,bitb_in_in, bitb_in_ind,bitb_in_de, bitb_in_ded,bitb_in_ix, bitb_in_ixd,
+ bitb_in_rg, bitb_in_rgd,bitb_in_in, bitb_in_ind,bitb_in_de, bitb_in_ded,bitb_in_ix, bitb_in_ixd,
+ bitb_in_rg, bitb_in_rgd,bitb_in_in, bitb_in_ind,bitb_in_de, bitb_in_ded,bitb_in_ix, bitb_in_ixd,
+ /* 0xb500 */
+ bitb_in_rg, bitb_in_rgd,bitb_in_in, bitb_in_ind,bitb_in_de, bitb_in_ded,bitb_in_ix, bitb_in_ixd,
+ bitb_in_rg, bitb_in_rgd,bitb_in_in, bitb_in_ind,bitb_in_de, bitb_in_ded,bitb_in_ix, bitb_in_ixd,
+ bitb_in_rg, bitb_in_rgd,bitb_in_in, bitb_in_ind,bitb_in_de, bitb_in_ded,bitb_in_ix, bitb_in_ixd,
+ bitb_in_rg, bitb_in_rgd,bitb_in_in, bitb_in_ind,bitb_in_de, bitb_in_ded,bitb_in_ix, bitb_in_ixd,
+ /* 0xb600 */
+ bitb_ind_rg,bitb_ind_rgd,bitb_ind_in,bitb_ind_ind,bitb_ind_de,bitb_ind_ded,bitb_ind_ix,bitb_ind_ixd,
+ bitb_ind_rg,bitb_ind_rgd,bitb_ind_in,bitb_ind_ind,bitb_ind_de,bitb_ind_ded,bitb_ind_ix,bitb_ind_ixd,
+ bitb_ind_rg,bitb_ind_rgd,bitb_ind_in,bitb_ind_ind,bitb_ind_de,bitb_ind_ded,bitb_ind_ix,bitb_ind_ixd,
+ bitb_ind_rg,bitb_ind_rgd,bitb_ind_in,bitb_ind_ind,bitb_ind_de,bitb_ind_ded,bitb_ind_ix,bitb_ind_ixd,
+ /* 0xb700 */
+ bitb_ind_rg,bitb_ind_rgd,bitb_ind_in,bitb_ind_ind,bitb_ind_de,bitb_ind_ded,bitb_ind_ix,bitb_ind_ixd,
+ bitb_ind_rg,bitb_ind_rgd,bitb_ind_in,bitb_ind_ind,bitb_ind_de,bitb_ind_ded,bitb_ind_ix,bitb_ind_ixd,
+ bitb_ind_rg,bitb_ind_rgd,bitb_ind_in,bitb_ind_ind,bitb_ind_de,bitb_ind_ded,bitb_ind_ix,bitb_ind_ixd,
+ bitb_ind_rg,bitb_ind_rgd,bitb_ind_in,bitb_ind_ind,bitb_ind_de,bitb_ind_ded,bitb_ind_ix,bitb_ind_ixd,
+ /* 0xb800 */
+ bitb_de_rg, bitb_de_rgd,bitb_de_in, bitb_de_ind,bitb_de_de, bitb_de_ded,bitb_de_ix, bitb_de_ixd,
+ bitb_de_rg, bitb_de_rgd,bitb_de_in, bitb_de_ind,bitb_de_de, bitb_de_ded,bitb_de_ix, bitb_de_ixd,
+ bitb_de_rg, bitb_de_rgd,bitb_de_in, bitb_de_ind,bitb_de_de, bitb_de_ded,bitb_de_ix, bitb_de_ixd,
+ bitb_de_rg, bitb_de_rgd,bitb_de_in, bitb_de_ind,bitb_de_de, bitb_de_ded,bitb_de_ix, bitb_de_ixd,
+ /* 0xb900 */
+ bitb_de_rg, bitb_de_rgd,bitb_de_in, bitb_de_ind,bitb_de_de, bitb_de_ded,bitb_de_ix, bitb_de_ixd,
+ bitb_de_rg, bitb_de_rgd,bitb_de_in, bitb_de_ind,bitb_de_de, bitb_de_ded,bitb_de_ix, bitb_de_ixd,
+ bitb_de_rg, bitb_de_rgd,bitb_de_in, bitb_de_ind,bitb_de_de, bitb_de_ded,bitb_de_ix, bitb_de_ixd,
+ bitb_de_rg, bitb_de_rgd,bitb_de_in, bitb_de_ind,bitb_de_de, bitb_de_ded,bitb_de_ix, bitb_de_ixd,
+ /* 0xba00 */
+ bitb_ded_rg,bitb_ded_rgd,bitb_ded_in,bitb_ded_ind,bitb_ded_de,bitb_ded_ded,bitb_ded_ix,bitb_ded_ixd,
+ bitb_ded_rg,bitb_ded_rgd,bitb_ded_in,bitb_ded_ind,bitb_ded_de,bitb_ded_ded,bitb_ded_ix,bitb_ded_ixd,
+ bitb_ded_rg,bitb_ded_rgd,bitb_ded_in,bitb_ded_ind,bitb_ded_de,bitb_ded_ded,bitb_ded_ix,bitb_ded_ixd,
+ bitb_ded_rg,bitb_ded_rgd,bitb_ded_in,bitb_ded_ind,bitb_ded_de,bitb_ded_ded,bitb_ded_ix,bitb_ded_ixd,
+ /* 0xbb00 */
+ bitb_ded_rg,bitb_ded_rgd,bitb_ded_in,bitb_ded_ind,bitb_ded_de,bitb_ded_ded,bitb_ded_ix,bitb_ded_ixd,
+ bitb_ded_rg,bitb_ded_rgd,bitb_ded_in,bitb_ded_ind,bitb_ded_de,bitb_ded_ded,bitb_ded_ix,bitb_ded_ixd,
+ bitb_ded_rg,bitb_ded_rgd,bitb_ded_in,bitb_ded_ind,bitb_ded_de,bitb_ded_ded,bitb_ded_ix,bitb_ded_ixd,
+ bitb_ded_rg,bitb_ded_rgd,bitb_ded_in,bitb_ded_ind,bitb_ded_de,bitb_ded_ded,bitb_ded_ix,bitb_ded_ixd,
+ /* 0xbc00 */
+ bitb_ix_rg, bitb_ix_rgd,bitb_ix_in, bitb_ix_ind,bitb_ix_de, bitb_ix_ded,bitb_ix_ix, bitb_ix_ixd,
+ bitb_ix_rg, bitb_ix_rgd,bitb_ix_in, bitb_ix_ind,bitb_ix_de, bitb_ix_ded,bitb_ix_ix, bitb_ix_ixd,
+ bitb_ix_rg, bitb_ix_rgd,bitb_ix_in, bitb_ix_ind,bitb_ix_de, bitb_ix_ded,bitb_ix_ix, bitb_ix_ixd,
+ bitb_ix_rg, bitb_ix_rgd,bitb_ix_in, bitb_ix_ind,bitb_ix_de, bitb_ix_ded,bitb_ix_ix, bitb_ix_ixd,
+ /* 0xbd00 */
+ bitb_ix_rg, bitb_ix_rgd,bitb_ix_in, bitb_ix_ind,bitb_ix_de, bitb_ix_ded,bitb_ix_ix, bitb_ix_ixd,
+ bitb_ix_rg, bitb_ix_rgd,bitb_ix_in, bitb_ix_ind,bitb_ix_de, bitb_ix_ded,bitb_ix_ix, bitb_ix_ixd,
+ bitb_ix_rg, bitb_ix_rgd,bitb_ix_in, bitb_ix_ind,bitb_ix_de, bitb_ix_ded,bitb_ix_ix, bitb_ix_ixd,
+ bitb_ix_rg, bitb_ix_rgd,bitb_ix_in, bitb_ix_ind,bitb_ix_de, bitb_ix_ded,bitb_ix_ix, bitb_ix_ixd,
+ /* 0xbe00 */
+ bitb_ixd_rg,bitb_ixd_rgd,bitb_ixd_in,bitb_ixd_ind,bitb_ixd_de,bitb_ixd_ded,bitb_ixd_ix,bitb_ixd_ixd,
+ bitb_ixd_rg,bitb_ixd_rgd,bitb_ixd_in,bitb_ixd_ind,bitb_ixd_de,bitb_ixd_ded,bitb_ixd_ix,bitb_ixd_ixd,
+ bitb_ixd_rg,bitb_ixd_rgd,bitb_ixd_in,bitb_ixd_ind,bitb_ixd_de,bitb_ixd_ded,bitb_ixd_ix,bitb_ixd_ixd,
+ bitb_ixd_rg,bitb_ixd_rgd,bitb_ixd_in,bitb_ixd_ind,bitb_ixd_de,bitb_ixd_ded,bitb_ixd_ix,bitb_ixd_ixd,
+ /* 0xbf00 */
+ bitb_ixd_rg,bitb_ixd_rgd,bitb_ixd_in,bitb_ixd_ind,bitb_ixd_de,bitb_ixd_ded,bitb_ixd_ix,bitb_ixd_ixd,
+ bitb_ixd_rg,bitb_ixd_rgd,bitb_ixd_in,bitb_ixd_ind,bitb_ixd_de,bitb_ixd_ded,bitb_ixd_ix,bitb_ixd_ixd,
+ bitb_ixd_rg,bitb_ixd_rgd,bitb_ixd_in,bitb_ixd_ind,bitb_ixd_de,bitb_ixd_ded,bitb_ixd_ix,bitb_ixd_ixd,
+ bitb_ixd_rg,bitb_ixd_rgd,bitb_ixd_in,bitb_ixd_ind,bitb_ixd_de,bitb_ixd_ded,bitb_ixd_ix,bitb_ixd_ixd,
+
+ /* 0xc000 */
+ bicb_rg_rg, bicb_rg_rgd,bicb_rg_in, bicb_rg_ind,bicb_rg_de, bicb_rg_ded,bicb_rg_ix, bicb_rg_ixd,
+ bicb_rg_rg, bicb_rg_rgd,bicb_rg_in, bicb_rg_ind,bicb_rg_de, bicb_rg_ded,bicb_rg_ix, bicb_rg_ixd,
+ bicb_rg_rg, bicb_rg_rgd,bicb_rg_in, bicb_rg_ind,bicb_rg_de, bicb_rg_ded,bicb_rg_ix, bicb_rg_ixd,
+ bicb_rg_rg, bicb_rg_rgd,bicb_rg_in, bicb_rg_ind,bicb_rg_de, bicb_rg_ded,bicb_rg_ix, bicb_rg_ixd,
+ /* 0xc100 */
+ bicb_rg_rg, bicb_rg_rgd,bicb_rg_in, bicb_rg_ind,bicb_rg_de, bicb_rg_ded,bicb_rg_ix, bicb_rg_ixd,
+ bicb_rg_rg, bicb_rg_rgd,bicb_rg_in, bicb_rg_ind,bicb_rg_de, bicb_rg_ded,bicb_rg_ix, bicb_rg_ixd,
+ bicb_rg_rg, bicb_rg_rgd,bicb_rg_in, bicb_rg_ind,bicb_rg_de, bicb_rg_ded,bicb_rg_ix, bicb_rg_ixd,
+ bicb_rg_rg, bicb_rg_rgd,bicb_rg_in, bicb_rg_ind,bicb_rg_de, bicb_rg_ded,bicb_rg_ix, bicb_rg_ixd,
+ /* 0xc200 */
+ bicb_rgd_rg,bicb_rgd_rgd,bicb_rgd_in,bicb_rgd_ind,bicb_rgd_de,bicb_rgd_ded,bicb_rgd_ix,bicb_rgd_ixd,
+ bicb_rgd_rg,bicb_rgd_rgd,bicb_rgd_in,bicb_rgd_ind,bicb_rgd_de,bicb_rgd_ded,bicb_rgd_ix,bicb_rgd_ixd,
+ bicb_rgd_rg,bicb_rgd_rgd,bicb_rgd_in,bicb_rgd_ind,bicb_rgd_de,bicb_rgd_ded,bicb_rgd_ix,bicb_rgd_ixd,
+ bicb_rgd_rg,bicb_rgd_rgd,bicb_rgd_in,bicb_rgd_ind,bicb_rgd_de,bicb_rgd_ded,bicb_rgd_ix,bicb_rgd_ixd,
+ /* 0xc300 */
+ bicb_rgd_rg,bicb_rgd_rgd,bicb_rgd_in,bicb_rgd_ind,bicb_rgd_de,bicb_rgd_ded,bicb_rgd_ix,bicb_rgd_ixd,
+ bicb_rgd_rg,bicb_rgd_rgd,bicb_rgd_in,bicb_rgd_ind,bicb_rgd_de,bicb_rgd_ded,bicb_rgd_ix,bicb_rgd_ixd,
+ bicb_rgd_rg,bicb_rgd_rgd,bicb_rgd_in,bicb_rgd_ind,bicb_rgd_de,bicb_rgd_ded,bicb_rgd_ix,bicb_rgd_ixd,
+ bicb_rgd_rg,bicb_rgd_rgd,bicb_rgd_in,bicb_rgd_ind,bicb_rgd_de,bicb_rgd_ded,bicb_rgd_ix,bicb_rgd_ixd,
+ /* 0xc400 */
+ bicb_in_rg, bicb_in_rgd,bicb_in_in, bicb_in_ind,bicb_in_de, bicb_in_ded,bicb_in_ix, bicb_in_ixd,
+ bicb_in_rg, bicb_in_rgd,bicb_in_in, bicb_in_ind,bicb_in_de, bicb_in_ded,bicb_in_ix, bicb_in_ixd,
+ bicb_in_rg, bicb_in_rgd,bicb_in_in, bicb_in_ind,bicb_in_de, bicb_in_ded,bicb_in_ix, bicb_in_ixd,
+ bicb_in_rg, bicb_in_rgd,bicb_in_in, bicb_in_ind,bicb_in_de, bicb_in_ded,bicb_in_ix, bicb_in_ixd,
+ /* 0xc500 */
+ bicb_in_rg, bicb_in_rgd,bicb_in_in, bicb_in_ind,bicb_in_de, bicb_in_ded,bicb_in_ix, bicb_in_ixd,
+ bicb_in_rg, bicb_in_rgd,bicb_in_in, bicb_in_ind,bicb_in_de, bicb_in_ded,bicb_in_ix, bicb_in_ixd,
+ bicb_in_rg, bicb_in_rgd,bicb_in_in, bicb_in_ind,bicb_in_de, bicb_in_ded,bicb_in_ix, bicb_in_ixd,
+ bicb_in_rg, bicb_in_rgd,bicb_in_in, bicb_in_ind,bicb_in_de, bicb_in_ded,bicb_in_ix, bicb_in_ixd,
+ /* 0xc600 */
+ bicb_ind_rg,bicb_ind_rgd,bicb_ind_in,bicb_ind_ind,bicb_ind_de,bicb_ind_ded,bicb_ind_ix,bicb_ind_ixd,
+ bicb_ind_rg,bicb_ind_rgd,bicb_ind_in,bicb_ind_ind,bicb_ind_de,bicb_ind_ded,bicb_ind_ix,bicb_ind_ixd,
+ bicb_ind_rg,bicb_ind_rgd,bicb_ind_in,bicb_ind_ind,bicb_ind_de,bicb_ind_ded,bicb_ind_ix,bicb_ind_ixd,
+ bicb_ind_rg,bicb_ind_rgd,bicb_ind_in,bicb_ind_ind,bicb_ind_de,bicb_ind_ded,bicb_ind_ix,bicb_ind_ixd,
+ /* 0xc700 */
+ bicb_ind_rg,bicb_ind_rgd,bicb_ind_in,bicb_ind_ind,bicb_ind_de,bicb_ind_ded,bicb_ind_ix,bicb_ind_ixd,
+ bicb_ind_rg,bicb_ind_rgd,bicb_ind_in,bicb_ind_ind,bicb_ind_de,bicb_ind_ded,bicb_ind_ix,bicb_ind_ixd,
+ bicb_ind_rg,bicb_ind_rgd,bicb_ind_in,bicb_ind_ind,bicb_ind_de,bicb_ind_ded,bicb_ind_ix,bicb_ind_ixd,
+ bicb_ind_rg,bicb_ind_rgd,bicb_ind_in,bicb_ind_ind,bicb_ind_de,bicb_ind_ded,bicb_ind_ix,bicb_ind_ixd,
+ /* 0xc800 */
+ bicb_de_rg, bicb_de_rgd,bicb_de_in, bicb_de_ind,bicb_de_de, bicb_de_ded,bicb_de_ix, bicb_de_ixd,
+ bicb_de_rg, bicb_de_rgd,bicb_de_in, bicb_de_ind,bicb_de_de, bicb_de_ded,bicb_de_ix, bicb_de_ixd,
+ bicb_de_rg, bicb_de_rgd,bicb_de_in, bicb_de_ind,bicb_de_de, bicb_de_ded,bicb_de_ix, bicb_de_ixd,
+ bicb_de_rg, bicb_de_rgd,bicb_de_in, bicb_de_ind,bicb_de_de, bicb_de_ded,bicb_de_ix, bicb_de_ixd,
+ /* 0xc900 */
+ bicb_de_rg, bicb_de_rgd,bicb_de_in, bicb_de_ind,bicb_de_de, bicb_de_ded,bicb_de_ix, bicb_de_ixd,
+ bicb_de_rg, bicb_de_rgd,bicb_de_in, bicb_de_ind,bicb_de_de, bicb_de_ded,bicb_de_ix, bicb_de_ixd,
+ bicb_de_rg, bicb_de_rgd,bicb_de_in, bicb_de_ind,bicb_de_de, bicb_de_ded,bicb_de_ix, bicb_de_ixd,
+ bicb_de_rg, bicb_de_rgd,bicb_de_in, bicb_de_ind,bicb_de_de, bicb_de_ded,bicb_de_ix, bicb_de_ixd,
+ /* 0xca00 */
+ bicb_ded_rg,bicb_ded_rgd,bicb_ded_in,bicb_ded_ind,bicb_ded_de,bicb_ded_ded,bicb_ded_ix,bicb_ded_ixd,
+ bicb_ded_rg,bicb_ded_rgd,bicb_ded_in,bicb_ded_ind,bicb_ded_de,bicb_ded_ded,bicb_ded_ix,bicb_ded_ixd,
+ bicb_ded_rg,bicb_ded_rgd,bicb_ded_in,bicb_ded_ind,bicb_ded_de,bicb_ded_ded,bicb_ded_ix,bicb_ded_ixd,
+ bicb_ded_rg,bicb_ded_rgd,bicb_ded_in,bicb_ded_ind,bicb_ded_de,bicb_ded_ded,bicb_ded_ix,bicb_ded_ixd,
+ /* 0xcb00 */
+ bicb_ded_rg,bicb_ded_rgd,bicb_ded_in,bicb_ded_ind,bicb_ded_de,bicb_ded_ded,bicb_ded_ix,bicb_ded_ixd,
+ bicb_ded_rg,bicb_ded_rgd,bicb_ded_in,bicb_ded_ind,bicb_ded_de,bicb_ded_ded,bicb_ded_ix,bicb_ded_ixd,
+ bicb_ded_rg,bicb_ded_rgd,bicb_ded_in,bicb_ded_ind,bicb_ded_de,bicb_ded_ded,bicb_ded_ix,bicb_ded_ixd,
+ bicb_ded_rg,bicb_ded_rgd,bicb_ded_in,bicb_ded_ind,bicb_ded_de,bicb_ded_ded,bicb_ded_ix,bicb_ded_ixd,
+ /* 0xcc00 */
+ bicb_ix_rg, bicb_ix_rgd,bicb_ix_in, bicb_ix_ind,bicb_ix_de, bicb_ix_ded,bicb_ix_ix, bicb_ix_ixd,
+ bicb_ix_rg, bicb_ix_rgd,bicb_ix_in, bicb_ix_ind,bicb_ix_de, bicb_ix_ded,bicb_ix_ix, bicb_ix_ixd,
+ bicb_ix_rg, bicb_ix_rgd,bicb_ix_in, bicb_ix_ind,bicb_ix_de, bicb_ix_ded,bicb_ix_ix, bicb_ix_ixd,
+ bicb_ix_rg, bicb_ix_rgd,bicb_ix_in, bicb_ix_ind,bicb_ix_de, bicb_ix_ded,bicb_ix_ix, bicb_ix_ixd,
+ /* 0xcd00 */
+ bicb_ix_rg, bicb_ix_rgd,bicb_ix_in, bicb_ix_ind,bicb_ix_de, bicb_ix_ded,bicb_ix_ix, bicb_ix_ixd,
+ bicb_ix_rg, bicb_ix_rgd,bicb_ix_in, bicb_ix_ind,bicb_ix_de, bicb_ix_ded,bicb_ix_ix, bicb_ix_ixd,
+ bicb_ix_rg, bicb_ix_rgd,bicb_ix_in, bicb_ix_ind,bicb_ix_de, bicb_ix_ded,bicb_ix_ix, bicb_ix_ixd,
+ bicb_ix_rg, bicb_ix_rgd,bicb_ix_in, bicb_ix_ind,bicb_ix_de, bicb_ix_ded,bicb_ix_ix, bicb_ix_ixd,
+ /* 0xce00 */
+ bicb_ixd_rg,bicb_ixd_rgd,bicb_ixd_in,bicb_ixd_ind,bicb_ixd_de,bicb_ixd_ded,bicb_ixd_ix,bicb_ixd_ixd,
+ bicb_ixd_rg,bicb_ixd_rgd,bicb_ixd_in,bicb_ixd_ind,bicb_ixd_de,bicb_ixd_ded,bicb_ixd_ix,bicb_ixd_ixd,
+ bicb_ixd_rg,bicb_ixd_rgd,bicb_ixd_in,bicb_ixd_ind,bicb_ixd_de,bicb_ixd_ded,bicb_ixd_ix,bicb_ixd_ixd,
+ bicb_ixd_rg,bicb_ixd_rgd,bicb_ixd_in,bicb_ixd_ind,bicb_ixd_de,bicb_ixd_ded,bicb_ixd_ix,bicb_ixd_ixd,
+ /* 0xcf00 */
+ bicb_ixd_rg,bicb_ixd_rgd,bicb_ixd_in,bicb_ixd_ind,bicb_ixd_de,bicb_ixd_ded,bicb_ixd_ix,bicb_ixd_ixd,
+ bicb_ixd_rg,bicb_ixd_rgd,bicb_ixd_in,bicb_ixd_ind,bicb_ixd_de,bicb_ixd_ded,bicb_ixd_ix,bicb_ixd_ixd,
+ bicb_ixd_rg,bicb_ixd_rgd,bicb_ixd_in,bicb_ixd_ind,bicb_ixd_de,bicb_ixd_ded,bicb_ixd_ix,bicb_ixd_ixd,
+ bicb_ixd_rg,bicb_ixd_rgd,bicb_ixd_in,bicb_ixd_ind,bicb_ixd_de,bicb_ixd_ded,bicb_ixd_ix,bicb_ixd_ixd,
+
+ /* 0xd000 */
+ bisb_rg_rg, bisb_rg_rgd,bisb_rg_in, bisb_rg_ind,bisb_rg_de, bisb_rg_ded,bisb_rg_ix, bisb_rg_ixd,
+ bisb_rg_rg, bisb_rg_rgd,bisb_rg_in, bisb_rg_ind,bisb_rg_de, bisb_rg_ded,bisb_rg_ix, bisb_rg_ixd,
+ bisb_rg_rg, bisb_rg_rgd,bisb_rg_in, bisb_rg_ind,bisb_rg_de, bisb_rg_ded,bisb_rg_ix, bisb_rg_ixd,
+ bisb_rg_rg, bisb_rg_rgd,bisb_rg_in, bisb_rg_ind,bisb_rg_de, bisb_rg_ded,bisb_rg_ix, bisb_rg_ixd,
+ /* 0xd100 */
+ bisb_rg_rg, bisb_rg_rgd,bisb_rg_in, bisb_rg_ind,bisb_rg_de, bisb_rg_ded,bisb_rg_ix, bisb_rg_ixd,
+ bisb_rg_rg, bisb_rg_rgd,bisb_rg_in, bisb_rg_ind,bisb_rg_de, bisb_rg_ded,bisb_rg_ix, bisb_rg_ixd,
+ bisb_rg_rg, bisb_rg_rgd,bisb_rg_in, bisb_rg_ind,bisb_rg_de, bisb_rg_ded,bisb_rg_ix, bisb_rg_ixd,
+ bisb_rg_rg, bisb_rg_rgd,bisb_rg_in, bisb_rg_ind,bisb_rg_de, bisb_rg_ded,bisb_rg_ix, bisb_rg_ixd,
+ /* 0xd200 */
+ bisb_rgd_rg,bisb_rgd_rgd,bisb_rgd_in,bisb_rgd_ind,bisb_rgd_de,bisb_rgd_ded,bisb_rgd_ix,bisb_rgd_ixd,
+ bisb_rgd_rg,bisb_rgd_rgd,bisb_rgd_in,bisb_rgd_ind,bisb_rgd_de,bisb_rgd_ded,bisb_rgd_ix,bisb_rgd_ixd,
+ bisb_rgd_rg,bisb_rgd_rgd,bisb_rgd_in,bisb_rgd_ind,bisb_rgd_de,bisb_rgd_ded,bisb_rgd_ix,bisb_rgd_ixd,
+ bisb_rgd_rg,bisb_rgd_rgd,bisb_rgd_in,bisb_rgd_ind,bisb_rgd_de,bisb_rgd_ded,bisb_rgd_ix,bisb_rgd_ixd,
+ /* 0xd300 */
+ bisb_rgd_rg,bisb_rgd_rgd,bisb_rgd_in,bisb_rgd_ind,bisb_rgd_de,bisb_rgd_ded,bisb_rgd_ix,bisb_rgd_ixd,
+ bisb_rgd_rg,bisb_rgd_rgd,bisb_rgd_in,bisb_rgd_ind,bisb_rgd_de,bisb_rgd_ded,bisb_rgd_ix,bisb_rgd_ixd,
+ bisb_rgd_rg,bisb_rgd_rgd,bisb_rgd_in,bisb_rgd_ind,bisb_rgd_de,bisb_rgd_ded,bisb_rgd_ix,bisb_rgd_ixd,
+ bisb_rgd_rg,bisb_rgd_rgd,bisb_rgd_in,bisb_rgd_ind,bisb_rgd_de,bisb_rgd_ded,bisb_rgd_ix,bisb_rgd_ixd,
+ /* 0xd400 */
+ bisb_in_rg, bisb_in_rgd,bisb_in_in, bisb_in_ind,bisb_in_de, bisb_in_ded,bisb_in_ix, bisb_in_ixd,
+ bisb_in_rg, bisb_in_rgd,bisb_in_in, bisb_in_ind,bisb_in_de, bisb_in_ded,bisb_in_ix, bisb_in_ixd,
+ bisb_in_rg, bisb_in_rgd,bisb_in_in, bisb_in_ind,bisb_in_de, bisb_in_ded,bisb_in_ix, bisb_in_ixd,
+ bisb_in_rg, bisb_in_rgd,bisb_in_in, bisb_in_ind,bisb_in_de, bisb_in_ded,bisb_in_ix, bisb_in_ixd,
+ /* 0xd500 */
+ bisb_in_rg, bisb_in_rgd,bisb_in_in, bisb_in_ind,bisb_in_de, bisb_in_ded,bisb_in_ix, bisb_in_ixd,
+ bisb_in_rg, bisb_in_rgd,bisb_in_in, bisb_in_ind,bisb_in_de, bisb_in_ded,bisb_in_ix, bisb_in_ixd,
+ bisb_in_rg, bisb_in_rgd,bisb_in_in, bisb_in_ind,bisb_in_de, bisb_in_ded,bisb_in_ix, bisb_in_ixd,
+ bisb_in_rg, bisb_in_rgd,bisb_in_in, bisb_in_ind,bisb_in_de, bisb_in_ded,bisb_in_ix, bisb_in_ixd,
+ /* 0xd600 */
+ bisb_ind_rg,bisb_ind_rgd,bisb_ind_in,bisb_ind_ind,bisb_ind_de,bisb_ind_ded,bisb_ind_ix,bisb_ind_ixd,
+ bisb_ind_rg,bisb_ind_rgd,bisb_ind_in,bisb_ind_ind,bisb_ind_de,bisb_ind_ded,bisb_ind_ix,bisb_ind_ixd,
+ bisb_ind_rg,bisb_ind_rgd,bisb_ind_in,bisb_ind_ind,bisb_ind_de,bisb_ind_ded,bisb_ind_ix,bisb_ind_ixd,
+ bisb_ind_rg,bisb_ind_rgd,bisb_ind_in,bisb_ind_ind,bisb_ind_de,bisb_ind_ded,bisb_ind_ix,bisb_ind_ixd,
+ /* 0xd700 */
+ bisb_ind_rg,bisb_ind_rgd,bisb_ind_in,bisb_ind_ind,bisb_ind_de,bisb_ind_ded,bisb_ind_ix,bisb_ind_ixd,
+ bisb_ind_rg,bisb_ind_rgd,bisb_ind_in,bisb_ind_ind,bisb_ind_de,bisb_ind_ded,bisb_ind_ix,bisb_ind_ixd,
+ bisb_ind_rg,bisb_ind_rgd,bisb_ind_in,bisb_ind_ind,bisb_ind_de,bisb_ind_ded,bisb_ind_ix,bisb_ind_ixd,
+ bisb_ind_rg,bisb_ind_rgd,bisb_ind_in,bisb_ind_ind,bisb_ind_de,bisb_ind_ded,bisb_ind_ix,bisb_ind_ixd,
+ /* 0xd800 */
+ bisb_de_rg, bisb_de_rgd,bisb_de_in, bisb_de_ind,bisb_de_de, bisb_de_ded,bisb_de_ix, bisb_de_ixd,
+ bisb_de_rg, bisb_de_rgd,bisb_de_in, bisb_de_ind,bisb_de_de, bisb_de_ded,bisb_de_ix, bisb_de_ixd,
+ bisb_de_rg, bisb_de_rgd,bisb_de_in, bisb_de_ind,bisb_de_de, bisb_de_ded,bisb_de_ix, bisb_de_ixd,
+ bisb_de_rg, bisb_de_rgd,bisb_de_in, bisb_de_ind,bisb_de_de, bisb_de_ded,bisb_de_ix, bisb_de_ixd,
+ /* 0xd900 */
+ bisb_de_rg, bisb_de_rgd,bisb_de_in, bisb_de_ind,bisb_de_de, bisb_de_ded,bisb_de_ix, bisb_de_ixd,
+ bisb_de_rg, bisb_de_rgd,bisb_de_in, bisb_de_ind,bisb_de_de, bisb_de_ded,bisb_de_ix, bisb_de_ixd,
+ bisb_de_rg, bisb_de_rgd,bisb_de_in, bisb_de_ind,bisb_de_de, bisb_de_ded,bisb_de_ix, bisb_de_ixd,
+ bisb_de_rg, bisb_de_rgd,bisb_de_in, bisb_de_ind,bisb_de_de, bisb_de_ded,bisb_de_ix, bisb_de_ixd,
+ /* 0xda00 */
+ bisb_ded_rg,bisb_ded_rgd,bisb_ded_in,bisb_ded_ind,bisb_ded_de,bisb_ded_ded,bisb_ded_ix,bisb_ded_ixd,
+ bisb_ded_rg,bisb_ded_rgd,bisb_ded_in,bisb_ded_ind,bisb_ded_de,bisb_ded_ded,bisb_ded_ix,bisb_ded_ixd,
+ bisb_ded_rg,bisb_ded_rgd,bisb_ded_in,bisb_ded_ind,bisb_ded_de,bisb_ded_ded,bisb_ded_ix,bisb_ded_ixd,
+ bisb_ded_rg,bisb_ded_rgd,bisb_ded_in,bisb_ded_ind,bisb_ded_de,bisb_ded_ded,bisb_ded_ix,bisb_ded_ixd,
+ /* 0xdb00 */
+ bisb_ded_rg,bisb_ded_rgd,bisb_ded_in,bisb_ded_ind,bisb_ded_de,bisb_ded_ded,bisb_ded_ix,bisb_ded_ixd,
+ bisb_ded_rg,bisb_ded_rgd,bisb_ded_in,bisb_ded_ind,bisb_ded_de,bisb_ded_ded,bisb_ded_ix,bisb_ded_ixd,
+ bisb_ded_rg,bisb_ded_rgd,bisb_ded_in,bisb_ded_ind,bisb_ded_de,bisb_ded_ded,bisb_ded_ix,bisb_ded_ixd,
+ bisb_ded_rg,bisb_ded_rgd,bisb_ded_in,bisb_ded_ind,bisb_ded_de,bisb_ded_ded,bisb_ded_ix,bisb_ded_ixd,
+ /* 0xdc00 */
+ bisb_ix_rg, bisb_ix_rgd,bisb_ix_in, bisb_ix_ind,bisb_ix_de, bisb_ix_ded,bisb_ix_ix, bisb_ix_ixd,
+ bisb_ix_rg, bisb_ix_rgd,bisb_ix_in, bisb_ix_ind,bisb_ix_de, bisb_ix_ded,bisb_ix_ix, bisb_ix_ixd,
+ bisb_ix_rg, bisb_ix_rgd,bisb_ix_in, bisb_ix_ind,bisb_ix_de, bisb_ix_ded,bisb_ix_ix, bisb_ix_ixd,
+ bisb_ix_rg, bisb_ix_rgd,bisb_ix_in, bisb_ix_ind,bisb_ix_de, bisb_ix_ded,bisb_ix_ix, bisb_ix_ixd,
+ /* 0xdd00 */
+ bisb_ix_rg, bisb_ix_rgd,bisb_ix_in, bisb_ix_ind,bisb_ix_de, bisb_ix_ded,bisb_ix_ix, bisb_ix_ixd,
+ bisb_ix_rg, bisb_ix_rgd,bisb_ix_in, bisb_ix_ind,bisb_ix_de, bisb_ix_ded,bisb_ix_ix, bisb_ix_ixd,
+ bisb_ix_rg, bisb_ix_rgd,bisb_ix_in, bisb_ix_ind,bisb_ix_de, bisb_ix_ded,bisb_ix_ix, bisb_ix_ixd,
+ bisb_ix_rg, bisb_ix_rgd,bisb_ix_in, bisb_ix_ind,bisb_ix_de, bisb_ix_ded,bisb_ix_ix, bisb_ix_ixd,
+ /* 0xde00 */
+ bisb_ixd_rg,bisb_ixd_rgd,bisb_ixd_in,bisb_ixd_ind,bisb_ixd_de,bisb_ixd_ded,bisb_ixd_ix,bisb_ixd_ixd,
+ bisb_ixd_rg,bisb_ixd_rgd,bisb_ixd_in,bisb_ixd_ind,bisb_ixd_de,bisb_ixd_ded,bisb_ixd_ix,bisb_ixd_ixd,
+ bisb_ixd_rg,bisb_ixd_rgd,bisb_ixd_in,bisb_ixd_ind,bisb_ixd_de,bisb_ixd_ded,bisb_ixd_ix,bisb_ixd_ixd,
+ bisb_ixd_rg,bisb_ixd_rgd,bisb_ixd_in,bisb_ixd_ind,bisb_ixd_de,bisb_ixd_ded,bisb_ixd_ix,bisb_ixd_ixd,
+ /* 0xdf00 */
+ bisb_ixd_rg,bisb_ixd_rgd,bisb_ixd_in,bisb_ixd_ind,bisb_ixd_de,bisb_ixd_ded,bisb_ixd_ix,bisb_ixd_ixd,
+ bisb_ixd_rg,bisb_ixd_rgd,bisb_ixd_in,bisb_ixd_ind,bisb_ixd_de,bisb_ixd_ded,bisb_ixd_ix,bisb_ixd_ixd,
+ bisb_ixd_rg,bisb_ixd_rgd,bisb_ixd_in,bisb_ixd_ind,bisb_ixd_de,bisb_ixd_ded,bisb_ixd_ix,bisb_ixd_ixd,
+ bisb_ixd_rg,bisb_ixd_rgd,bisb_ixd_in,bisb_ixd_ind,bisb_ixd_de,bisb_ixd_ded,bisb_ixd_ix,bisb_ixd_ixd,
+
+ /* 0xe000 */
+ sub_rg_rg, sub_rg_rgd, sub_rg_in, sub_rg_ind, sub_rg_de, sub_rg_ded, sub_rg_ix, sub_rg_ixd,
+ sub_rg_rg, sub_rg_rgd, sub_rg_in, sub_rg_ind, sub_rg_de, sub_rg_ded, sub_rg_ix, sub_rg_ixd,
+ sub_rg_rg, sub_rg_rgd, sub_rg_in, sub_rg_ind, sub_rg_de, sub_rg_ded, sub_rg_ix, sub_rg_ixd,
+ sub_rg_rg, sub_rg_rgd, sub_rg_in, sub_rg_ind, sub_rg_de, sub_rg_ded, sub_rg_ix, sub_rg_ixd,
+ /* 0xe100 */
+ sub_rg_rg, sub_rg_rgd, sub_rg_in, sub_rg_ind, sub_rg_de, sub_rg_ded, sub_rg_ix, sub_rg_ixd,
+ sub_rg_rg, sub_rg_rgd, sub_rg_in, sub_rg_ind, sub_rg_de, sub_rg_ded, sub_rg_ix, sub_rg_ixd,
+ sub_rg_rg, sub_rg_rgd, sub_rg_in, sub_rg_ind, sub_rg_de, sub_rg_ded, sub_rg_ix, sub_rg_ixd,
+ sub_rg_rg, sub_rg_rgd, sub_rg_in, sub_rg_ind, sub_rg_de, sub_rg_ded, sub_rg_ix, sub_rg_ixd,
+ /* 0xe200 */
+ sub_rgd_rg, sub_rgd_rgd,sub_rgd_in, sub_rgd_ind,sub_rgd_de, sub_rgd_ded,sub_rgd_ix, sub_rgd_ixd,
+ sub_rgd_rg, sub_rgd_rgd,sub_rgd_in, sub_rgd_ind,sub_rgd_de, sub_rgd_ded,sub_rgd_ix, sub_rgd_ixd,
+ sub_rgd_rg, sub_rgd_rgd,sub_rgd_in, sub_rgd_ind,sub_rgd_de, sub_rgd_ded,sub_rgd_ix, sub_rgd_ixd,
+ sub_rgd_rg, sub_rgd_rgd,sub_rgd_in, sub_rgd_ind,sub_rgd_de, sub_rgd_ded,sub_rgd_ix, sub_rgd_ixd,
+ /* 0xe300 */
+ sub_rgd_rg, sub_rgd_rgd,sub_rgd_in, sub_rgd_ind,sub_rgd_de, sub_rgd_ded,sub_rgd_ix, sub_rgd_ixd,
+ sub_rgd_rg, sub_rgd_rgd,sub_rgd_in, sub_rgd_ind,sub_rgd_de, sub_rgd_ded,sub_rgd_ix, sub_rgd_ixd,
+ sub_rgd_rg, sub_rgd_rgd,sub_rgd_in, sub_rgd_ind,sub_rgd_de, sub_rgd_ded,sub_rgd_ix, sub_rgd_ixd,
+ sub_rgd_rg, sub_rgd_rgd,sub_rgd_in, sub_rgd_ind,sub_rgd_de, sub_rgd_ded,sub_rgd_ix, sub_rgd_ixd,
+ /* 0xe400 */
+ sub_in_rg, sub_in_rgd, sub_in_in, sub_in_ind, sub_in_de, sub_in_ded, sub_in_ix, sub_in_ixd,
+ sub_in_rg, sub_in_rgd, sub_in_in, sub_in_ind, sub_in_de, sub_in_ded, sub_in_ix, sub_in_ixd,
+ sub_in_rg, sub_in_rgd, sub_in_in, sub_in_ind, sub_in_de, sub_in_ded, sub_in_ix, sub_in_ixd,
+ sub_in_rg, sub_in_rgd, sub_in_in, sub_in_ind, sub_in_de, sub_in_ded, sub_in_ix, sub_in_ixd,
+ /* 0xe500 */
+ sub_in_rg, sub_in_rgd, sub_in_in, sub_in_ind, sub_in_de, sub_in_ded, sub_in_ix, sub_in_ixd,
+ sub_in_rg, sub_in_rgd, sub_in_in, sub_in_ind, sub_in_de, sub_in_ded, sub_in_ix, sub_in_ixd,
+ sub_in_rg, sub_in_rgd, sub_in_in, sub_in_ind, sub_in_de, sub_in_ded, sub_in_ix, sub_in_ixd,
+ sub_in_rg, sub_in_rgd, sub_in_in, sub_in_ind, sub_in_de, sub_in_ded, sub_in_ix, sub_in_ixd,
+ /* 0xe600 */
+ sub_ind_rg, sub_ind_rgd,sub_ind_in, sub_ind_ind,sub_ind_de, sub_ind_ded,sub_ind_ix, sub_ind_ixd,
+ sub_ind_rg, sub_ind_rgd,sub_ind_in, sub_ind_ind,sub_ind_de, sub_ind_ded,sub_ind_ix, sub_ind_ixd,
+ sub_ind_rg, sub_ind_rgd,sub_ind_in, sub_ind_ind,sub_ind_de, sub_ind_ded,sub_ind_ix, sub_ind_ixd,
+ sub_ind_rg, sub_ind_rgd,sub_ind_in, sub_ind_ind,sub_ind_de, sub_ind_ded,sub_ind_ix, sub_ind_ixd,
+ /* 0xe700 */
+ sub_ind_rg, sub_ind_rgd,sub_ind_in, sub_ind_ind,sub_ind_de, sub_ind_ded,sub_ind_ix, sub_ind_ixd,
+ sub_ind_rg, sub_ind_rgd,sub_ind_in, sub_ind_ind,sub_ind_de, sub_ind_ded,sub_ind_ix, sub_ind_ixd,
+ sub_ind_rg, sub_ind_rgd,sub_ind_in, sub_ind_ind,sub_ind_de, sub_ind_ded,sub_ind_ix, sub_ind_ixd,
+ sub_ind_rg, sub_ind_rgd,sub_ind_in, sub_ind_ind,sub_ind_de, sub_ind_ded,sub_ind_ix, sub_ind_ixd,
+ /* 0xe800 */
+ sub_de_rg, sub_de_rgd, sub_de_in, sub_de_ind, sub_de_de, sub_de_ded, sub_de_ix, sub_de_ixd,
+ sub_de_rg, sub_de_rgd, sub_de_in, sub_de_ind, sub_de_de, sub_de_ded, sub_de_ix, sub_de_ixd,
+ sub_de_rg, sub_de_rgd, sub_de_in, sub_de_ind, sub_de_de, sub_de_ded, sub_de_ix, sub_de_ixd,
+ sub_de_rg, sub_de_rgd, sub_de_in, sub_de_ind, sub_de_de, sub_de_ded, sub_de_ix, sub_de_ixd,
+ /* 0xe900 */
+ sub_de_rg, sub_de_rgd, sub_de_in, sub_de_ind, sub_de_de, sub_de_ded, sub_de_ix, sub_de_ixd,
+ sub_de_rg, sub_de_rgd, sub_de_in, sub_de_ind, sub_de_de, sub_de_ded, sub_de_ix, sub_de_ixd,
+ sub_de_rg, sub_de_rgd, sub_de_in, sub_de_ind, sub_de_de, sub_de_ded, sub_de_ix, sub_de_ixd,
+ sub_de_rg, sub_de_rgd, sub_de_in, sub_de_ind, sub_de_de, sub_de_ded, sub_de_ix, sub_de_ixd,
+ /* 0xea00 */
+ sub_ded_rg, sub_ded_rgd,sub_ded_in, sub_ded_ind,sub_ded_de, sub_ded_ded,sub_ded_ix, sub_ded_ixd,
+ sub_ded_rg, sub_ded_rgd,sub_ded_in, sub_ded_ind,sub_ded_de, sub_ded_ded,sub_ded_ix, sub_ded_ixd,
+ sub_ded_rg, sub_ded_rgd,sub_ded_in, sub_ded_ind,sub_ded_de, sub_ded_ded,sub_ded_ix, sub_ded_ixd,
+ sub_ded_rg, sub_ded_rgd,sub_ded_in, sub_ded_ind,sub_ded_de, sub_ded_ded,sub_ded_ix, sub_ded_ixd,
+ /* 0xeb00 */
+ sub_ded_rg, sub_ded_rgd,sub_ded_in, sub_ded_ind,sub_ded_de, sub_ded_ded,sub_ded_ix, sub_ded_ixd,
+ sub_ded_rg, sub_ded_rgd,sub_ded_in, sub_ded_ind,sub_ded_de, sub_ded_ded,sub_ded_ix, sub_ded_ixd,
+ sub_ded_rg, sub_ded_rgd,sub_ded_in, sub_ded_ind,sub_ded_de, sub_ded_ded,sub_ded_ix, sub_ded_ixd,
+ sub_ded_rg, sub_ded_rgd,sub_ded_in, sub_ded_ind,sub_ded_de, sub_ded_ded,sub_ded_ix, sub_ded_ixd,
+ /* 0xec00 */
+ sub_ix_rg, sub_ix_rgd, sub_ix_in, sub_ix_ind, sub_ix_de, sub_ix_ded, sub_ix_ix, sub_ix_ixd,
+ sub_ix_rg, sub_ix_rgd, sub_ix_in, sub_ix_ind, sub_ix_de, sub_ix_ded, sub_ix_ix, sub_ix_ixd,
+ sub_ix_rg, sub_ix_rgd, sub_ix_in, sub_ix_ind, sub_ix_de, sub_ix_ded, sub_ix_ix, sub_ix_ixd,
+ sub_ix_rg, sub_ix_rgd, sub_ix_in, sub_ix_ind, sub_ix_de, sub_ix_ded, sub_ix_ix, sub_ix_ixd,
+ /* 0xed00 */
+ sub_ix_rg, sub_ix_rgd, sub_ix_in, sub_ix_ind, sub_ix_de, sub_ix_ded, sub_ix_ix, sub_ix_ixd,
+ sub_ix_rg, sub_ix_rgd, sub_ix_in, sub_ix_ind, sub_ix_de, sub_ix_ded, sub_ix_ix, sub_ix_ixd,
+ sub_ix_rg, sub_ix_rgd, sub_ix_in, sub_ix_ind, sub_ix_de, sub_ix_ded, sub_ix_ix, sub_ix_ixd,
+ sub_ix_rg, sub_ix_rgd, sub_ix_in, sub_ix_ind, sub_ix_de, sub_ix_ded, sub_ix_ix, sub_ix_ixd,
+ /* 0xee00 */
+ sub_ixd_rg, sub_ixd_rgd,sub_ixd_in, sub_ixd_ind,sub_ixd_de, sub_ixd_ded,sub_ixd_ix, sub_ixd_ixd,
+ sub_ixd_rg, sub_ixd_rgd,sub_ixd_in, sub_ixd_ind,sub_ixd_de, sub_ixd_ded,sub_ixd_ix, sub_ixd_ixd,
+ sub_ixd_rg, sub_ixd_rgd,sub_ixd_in, sub_ixd_ind,sub_ixd_de, sub_ixd_ded,sub_ixd_ix, sub_ixd_ixd,
+ sub_ixd_rg, sub_ixd_rgd,sub_ixd_in, sub_ixd_ind,sub_ixd_de, sub_ixd_ded,sub_ixd_ix, sub_ixd_ixd,
+ /* 0xef00 */
+ sub_ixd_rg, sub_ixd_rgd,sub_ixd_in, sub_ixd_ind,sub_ixd_de, sub_ixd_ded,sub_ixd_ix, sub_ixd_ixd,
+ sub_ixd_rg, sub_ixd_rgd,sub_ixd_in, sub_ixd_ind,sub_ixd_de, sub_ixd_ded,sub_ixd_ix, sub_ixd_ixd,
+ sub_ixd_rg, sub_ixd_rgd,sub_ixd_in, sub_ixd_ind,sub_ixd_de, sub_ixd_ded,sub_ixd_ix, sub_ixd_ixd,
+ sub_ixd_rg, sub_ixd_rgd,sub_ixd_in, sub_ixd_ind,sub_ixd_de, sub_ixd_ded,sub_ixd_ix, sub_ixd_ixd,
+
+ /* 0xf000 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0xf100 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0xf200 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0xf300 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0xf400 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0xf500 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0xf600 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0xf700 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0xf800 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0xf900 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0xfa00 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0xfb00 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0xfc00 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0xfd00 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0xfe00 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ /* 0xff00 */
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal
+};
diff --git a/trunk/src/emu/cpu/tlcs90/tlcs90.c b/trunk/src/emu/cpu/tlcs90/tlcs90.c
new file mode 100644
index 00000000000..a1d57eb4f47
--- /dev/null
+++ b/trunk/src/emu/cpu/tlcs90/tlcs90.c
@@ -0,0 +1,2945 @@
+/*************************************************************************************************************
+
+ Toshiba TLCS-90 Series MCU's
+
+ emulation by Luca Elia, based on the Z80 core by Juergen Buchmueller
+
+*************************************************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "tlcs90.h"
+
+typedef enum { UNKNOWN, NOP, EX, EXX, LD, LDW, LDA, LDI, LDIR, LDD, LDDR, CPI, CPIR, CPD, CPDR, PUSH, POP, JP, JR, CALL, CALLR, RET, RETI, HALT, DI, EI, SWI, DAA, CPL, NEG, LDAR, RCF, SCF, CCF, TSET, BIT, SET, RES, INC, DEC, INCX, DECX, INCW, DECW, ADD, ADC, SUB, SBC, AND, XOR, OR, CP, RLC, RRC, RL, RR, SLA, SRA, SLL, SRL, RLD, RRD, DJNZ, MUL, DIV } _e_op;
+typedef UINT8 e_op;
+static const char *const op_names[] = { "??", "nop", "ex", "exx", "ld", "ldw", "lda", "ldi", "ldir", "ldd", "lddr", "cpi", "cpir", "cpd", "cpdr", "push", "pop", "jp", "jr", "call", "callr", "ret", "reti", "halt", "di", "ei", "swi", "daa", "cpl", "neg", "ldar", "rcf", "scf", "ccf", "tset", "bit", "set", "res", "inc", "dec", "incx", "decx", "incw", "decw", "add", "adc", "sub", "sbc", "and", "xor", "or", "cp", "rlc", "rrc", "rl", "rr", "sla", "sra", "sll", "srl", "rld", "rrd", "djnz", "mul", "div" };
+
+typedef enum {
+ MODE_NONE, MODE_BIT8, MODE_CC,
+ MODE_I8, MODE_D8, MODE_R8,
+ MODE_I16, MODE_D16, MODE_R16,
+ MODE_MI16, MODE_MR16, MODE_MR16D8, MODE_MR16R8,
+ MODE_R16D8, MODE_R16R8
+} e_mode;
+ALLOW_SAVE_TYPE(e_mode); // allow save_item on a non-fundamental type
+
+typedef UINT16 e_r;
+
+typedef struct
+{
+ PAIR prvpc,pc,sp,af,bc,de,hl,ix,iy;
+ PAIR af2,bc2,de2,hl2;
+ UINT8 halt, after_EI;
+ UINT16 irq_state, irq_mask;
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ address_space *io;
+ int icount;
+ int extra_cycles; // extra cycles for interrupts
+ UINT8 internal_registers[48];
+ UINT32 ixbase,iybase;
+
+ // Timers: 4 x 8-bit + 1 x 16-bit
+ emu_timer *timer[4+1];
+ UINT8 timer_value[4];
+ UINT16 timer4_value;
+ attotime timer_period;
+
+ // Work registers
+ e_op op;
+
+ e_mode mode1;
+ e_r r1,r1b;
+
+ e_mode mode2;
+ e_r r2,r2b;
+
+ int cyc_t,cyc_f;
+
+ UINT32 addr;
+
+} t90_Regs;
+
+INLINE t90_Regs *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == TMP90840 ||
+ device->type() == TMP90841 ||
+ device->type() == TMP91640 ||
+ device->type() == TMP91641);
+ return (t90_Regs *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+enum {
+ T90_B, T90_C, T90_D, T90_E, T90_H, T90_L, T90_A,
+ T90_BC, T90_DE, T90_HL, T90_XX, T90_IX, T90_IY, T90_SP,
+ T90_AF, T90_PC
+};
+
+// Regs
+
+#define B 0
+#define C 1
+#define D 2
+#define E 3
+#define H 4
+#define L 5
+#define A 6
+
+#define BC 0
+#define DE 1
+#define HL 2
+// 3
+#define IX 4
+#define IY 5
+#define SP 6
+
+#define AF 7
+#define AF2 8
+#define PC 9
+
+#define F cpustate->af.b.l
+
+static const char *const r8_names[] = { "b", "c", "d", "e", "h", "l", "a" };
+static const char *const r16_names[] = { "bc", "de", "hl", "??", "ix", "iy", "sp", "af", "af'", "pc" };
+
+// Condition Codes
+
+#define FLS 0x0
+#define LT 0x1
+#define LE 0x2
+#define ULE 0x3
+#define OV 0x4
+#define PE 0x4
+#define MI 0x5
+#define Z 0x6
+#define EQ 0x6
+#define CR 0x7
+#define ULT 0x7
+#define T 0x8
+#define GE 0x9
+#define GT 0xa
+#define UGT 0xb
+#define NOV 0xc
+#define PO 0xc
+#define PL 0xd
+#define NZ 0xe
+#define NE 0xe
+#define NC 0xf
+#define UGE 0xf
+
+#define CF 0x01
+#define NF 0x02
+#define PF 0x04
+#define VF PF
+#define XCF 0x08
+#define HF 0x10
+#define IF 0x20
+#define ZF 0x40
+#define SF 0x80
+
+static UINT8 SZ[256]; /* zero and sign flags */
+static UINT8 SZ_BIT[256]; /* zero, sign and parity/overflow (=zero) flags for BIT opcode */
+static UINT8 SZP[256]; /* zero, sign and parity flags */
+static UINT8 SZHV_inc[256]; /* zero, sign, half carry and overflow flags INC r8 */
+static UINT8 SZHV_dec[256]; /* zero, sign, half carry and overflow flags DEC r8 */
+
+static const char *const cc_names[] = { "f", "lt", "le", "ule", "ov", "mi", "z", "c", "", "ge", "gt", "ugt", "nov", "pl", "nz", "nc" };
+
+// Opcodes
+
+#define OP_16 0x80
+
+
+
+
+
+#define OP( X,CT ) cpustate->op = X; cpustate->cyc_t = (CT*2);
+#define OP16( X,CT ) OP( (X)|OP_16,CT )
+
+#define OPCC( X,CF,CT ) OP( X, CT ) cpustate->cyc_f = (CF*2);
+#define OPCC16( X,CF,CT ) OPCC( (X)|OP_16,CF,CT )
+
+#define BIT8( N,I ) cpustate->mode##N = MODE_BIT8; cpustate->r##N = I;
+#define I8( N,I ) cpustate->mode##N = MODE_I8; cpustate->r##N = I;
+#define D8( N,I ) cpustate->mode##N = MODE_D8; cpustate->r##N = I;
+#define I16( N,I ) cpustate->mode##N = MODE_I16; cpustate->r##N = I;
+#define D16( N,I ) cpustate->mode##N = MODE_D16; cpustate->r##N = I;
+#define R8( N,R ) cpustate->mode##N = MODE_R8; cpustate->r##N = R;
+#define R16( N,R ) cpustate->mode##N = MODE_R16; cpustate->r##N = R;
+#define Q16( N,R ) cpustate->mode##N = MODE_R16; cpustate->r##N = R; if (cpustate->r##N == SP) cpustate->r##N = AF;
+#define MI16( N,I ) cpustate->mode##N = MODE_MI16; cpustate->r##N = I;
+#define MR16( N,R ) cpustate->mode##N = MODE_MR16; cpustate->r##N = R;
+#define MR16D8( N,R,I ) cpustate->mode##N = MODE_MR16D8; cpustate->r##N = R; cpustate->r##N##b = I;
+#define MR16R8( N,R,g ) cpustate->mode##N = MODE_MR16R8; cpustate->r##N = R; cpustate->r##N##b = g;
+#define NONE( N ) cpustate->mode##N = MODE_NONE;
+#define CC( N,cc ) cpustate->mode##N = MODE_CC; cpustate->r##N = cc;
+#define R16D8( N,R,I ) cpustate->mode##N = MODE_R16D8; cpustate->r##N = R; cpustate->r##N##b = I;
+#define R16R8( N,R,g ) cpustate->mode##N = MODE_R16R8; cpustate->r##N = R; cpustate->r##N##b = g;
+
+INLINE UINT8 RM8 (t90_Regs *cpustate, UINT32 a) { return cpustate->program->read_byte( a ); }
+INLINE UINT16 RM16(t90_Regs *cpustate, UINT32 a) { return RM8(cpustate,a) | (RM8( cpustate, (a+1) & 0xffff ) << 8); }
+
+INLINE void WM8 (t90_Regs *cpustate, UINT32 a, UINT8 v) { cpustate->program->write_byte( a, v ); }
+INLINE void WM16(t90_Regs *cpustate, UINT32 a, UINT16 v) { WM8(cpustate,a,v); WM8( cpustate, (a+1) & 0xffff, v >> 8); }
+
+INLINE UINT8 RX8 (t90_Regs *cpustate, UINT32 a, UINT32 base) { return cpustate->program->read_byte( base | a ); }
+INLINE UINT16 RX16(t90_Regs *cpustate, UINT32 a, UINT32 base) { return RX8(cpustate,a,base) | (RX8( cpustate, (a+1) & 0xffff, base ) << 8); }
+
+INLINE void WX8 (t90_Regs *cpustate, UINT32 a, UINT8 v, UINT32 base) { cpustate->program->write_byte( base | a, v ); }
+INLINE void WX16(t90_Regs *cpustate, UINT32 a, UINT16 v, UINT32 base) { WX8(cpustate,a,v,base); WX8( cpustate, (a+1) & 0xffff, v >> 8, base); }
+
+INLINE UINT8 READ8(t90_Regs *cpustate) { UINT8 b0 = RM8( cpustate, cpustate->addr++ ); cpustate->addr &= 0xffff; return b0; }
+INLINE UINT16 READ16(t90_Regs *cpustate) { UINT8 b0 = READ8(cpustate); return b0 | (READ8(cpustate) << 8); }
+
+static void decode(t90_Regs *cpustate)
+{
+ UINT8 b0, b1, b2, b3;
+ UINT16 imm16;
+
+ b0 = READ8(cpustate);
+
+ switch ( b0 )
+ {
+ case 0x00:
+ OP( NOP,2 ) NONE( 1 ) NONE( 2 ) return; // NOP
+
+ case 0x01:
+ OP( HALT,4 ) NONE( 1 ) NONE( 2 ) return; // HALT
+ case 0x02:
+ OP( DI,2 ) NONE( 1 ) NONE( 2 ) return; // DI
+ case 0x03:
+ OP( EI,2 ) NONE( 1 ) NONE( 2 ) return; // EI
+
+ case 0x07:
+ OPCC( INCX,6,10 ) MI16( 1, 0xFF00|READ8(cpustate) ) NONE( 2 ) return; // INCX ($FF00+n)
+
+ case 0x08:
+ OP( EX,2 ) R16( 1, DE ) R16( 2, HL ) return; // EX DE,HL
+ case 0x09:
+ OP( EX,2 ) R16( 1, AF ) R16( 2, AF2 ) return; // EX AF,AF'
+ case 0x0a:
+ OP( EXX,2 ) NONE( 1 ) NONE( 2 ) return; // EXX
+
+ case 0x0b:
+ OP( DAA,4 ) R8( 1, A ) NONE( 2 ) return; // DAA A
+
+ case 0x0c:
+ OP( RCF,2 ) NONE( 1 ) NONE( 2 ) return; // RCF
+ case 0x0d:
+ OP( SCF,2 ) NONE( 1 ) NONE( 2 ) return; // SCF
+ case 0x0e:
+ OP( CCF,2 ) NONE( 1 ) NONE( 2 ) return; // CCF
+
+ case 0x0f:
+ OPCC( DECX,6,10 ) MI16( 1, 0xFF00|READ8(cpustate) ) NONE( 2 ) return; // DECX ($FF00+n)
+
+ case 0x10:
+ OP( CPL,2 ) R8( 1, A ) NONE( 2 ) return; // CPL A
+ case 0x11:
+ OP( NEG,2 ) R8( 1, A ) NONE( 2 ) return; // NEG A
+
+ case 0x12: // MUL HL,n
+ case 0x13: // DIV HL,n
+ OP( MUL+b0-0x12,16) R16( 1, HL ) I8( 2, READ8(cpustate) ) return;
+
+ case 0x14: case 0x15: case 0x16:
+ OP16( ADD,6 ) R16( 1, IX+b0-0x14 ) I16( 2, READ16(cpustate) ) return; // ADD ix,mn
+
+ case 0x17:
+ OP( LDAR,8 ) R16( 1, HL ) D16( 2, READ16(cpustate) ) return; // LDAR HL,+cd
+
+ case 0x18:
+ OP( DJNZ,10 ) D8( 1, READ8(cpustate) ) NONE( 2 ) return; // DJNZ +d
+ case 0x19:
+ OP16( DJNZ,10 ) R16( 1, BC ) D8( 2, READ8(cpustate) ) return; // DJNZ BC,+d
+
+ case 0x1a:
+ OPCC( JP,8,8 ) CC( 1, T ) I16( 2, READ16(cpustate) ) return; // JP T,mn
+ case 0x1b:
+ OPCC16( JR,10,10 ) CC( 1, T ) D16( 2, READ16(cpustate) ) return; // JR T,+cd
+
+ case 0x1c:
+ OPCC( CALL,14,14 ) CC( 1, T ) I16( 2, READ16(cpustate) ) return; // CALL T,mn
+ case 0x1d:
+ OP( CALLR,16 ) D16( 1, READ16(cpustate) ) NONE( 2 ) return; // CALLR +cd
+
+ case 0x1e:
+ OPCC( RET,10,10 ) CC( 1, T ) NONE( 2 ) return; // RET T
+ case 0x1f:
+ OP( RETI,14 ) NONE( 1 ) NONE( 2 ) return; // RETI
+
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26:
+ OP( LD,2 ) R8( 1, A ) R8( 2, b0 - 0x20 ) return; // LD A,r
+
+ case 0x27:
+ OP( LD,8 ) R8( 1, A ) MI16( 2, 0xFF00|READ8(cpustate) ) return; // LD A,($FF00+n)
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e:
+ OP( LD,2 ) R8( 1, b0 - 0x28 ) R8( 2, A ) return; // LD r,A
+
+ case 0x2f:
+ OP( LD,8 ) MI16( 1, 0xFF00|READ8(cpustate) ) R8( 2, A ) return; // LD ($FF00+n), A
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36:
+ OP( LD,4 ) R8( 1, b0 - 0x30 ) I8( 2, READ8(cpustate) ) return; // LD r,n
+
+ case 0x37:
+ OP( LD,10 ) MI16( 1, 0xFF00|READ8(cpustate) ) I8( 2, READ8(cpustate) ) return; // LD ($FF00+w),n
+
+ case 0x38: case 0x39: case 0x3a: /*case 0x3b:*/ case 0x3c: case 0x3d: case 0x3e:
+ OP16( LD,6 ) R16( 1, b0 - 0x38 ) I16( 2, READ16(cpustate) ) return; // LD rr,nn
+
+ case 0x3f:
+ OP( LDW,14 ) MI16( 1, 0xFF00|READ8(cpustate) ) I16( 2, READ16(cpustate) ) return; // LDW ($FF00+w),mn
+
+ case 0x40: case 0x41: case 0x42: /*case 0x43:*/ case 0x44: case 0x45: case 0x46:
+ OP16( LD,4 ) R16( 1, HL ) R16( 2, b0 - 0x40 ) return; // LD HL,rr
+
+ case 0x47:
+ OP16( LD,10 ) R16( 1, HL ) MI16( 2, 0xFF00|READ8(cpustate) ) return; // LD HL,($FF00+n)
+
+ case 0x48: case 0x49: case 0x4a: /*case 0x4b:*/ case 0x4c: case 0x4d: case 0x4e:
+ OP16( LD,4 ) R16( 1, b0 - 0x48 ) R16( 2, HL ) return; // LD rr,HL
+
+ case 0x4f:
+ OP16( LD,10 ) MI16( 1, 0xFF00|READ8(cpustate) ) R16( 2, HL ) return; // LD ($FF00+n), HL
+
+ case 0x50: case 0x51: case 0x52: /*case 0x53:*/ case 0x54: case 0x55: case 0x56:
+ OP( PUSH,8 ) Q16( 1, b0 - 0x50 ) NONE( 2 ) return; // PUSH qq
+ case 0x58: case 0x59: case 0x5a: /*case 0x5b:*/ case 0x5c: case 0x5d: case 0x5e:
+ OP( POP,10 ) Q16( 1, b0 - 0x58 ) NONE( 2 ) return; // POP qq
+
+ case 0x60: // ADD A,($FF00+n)
+ case 0x61: // ADC A,($FF00+n)
+ case 0x62: // SUB A,($FF00+n)
+ case 0x63: // SBC A,($FF00+n)
+ case 0x64: // AND A,($FF00+n)
+ case 0x65: // XOR A,($FF00+n)
+ case 0x66: // OR A,($FF00+n)
+ case 0x67: // CP A,($FF00+n)
+ OP( ADD+b0-0x60,8 ) R8( 1, A ) MI16( 2, 0xFF00|READ8(cpustate) ) return;
+
+ case 0x68: // ADD A,n
+ case 0x69: // ADC A,n
+ case 0x6a: // SUB A,n
+ case 0x6b: // SBC A,n
+ case 0x6c: // AND A,n
+ case 0x6d: // XOR A,n
+ case 0x6e: // OR A,n
+ case 0x6f: // CP A,n
+ OP( ADD+b0-0x68,4 ) R8( 1, A ) I8( 2, READ8(cpustate) ) return;
+
+ case 0x70: // ADD HL,($FF00+n)
+ case 0x71: // ADC HL,($FF00+n)
+ case 0x72: // SUB HL,($FF00+n)
+ case 0x73: // SBC HL,($FF00+n)
+ case 0x74: // AND HL,($FF00+n)
+ case 0x75: // XOR HL,($FF00+n)
+ case 0x76: // OR HL,($FF00+n)
+ case 0x77: // CP HL,($FF00+n)
+ OP16( ADD+b0-0x70,10 ) R16( 1, HL ) MI16( 2, 0xFF00|READ8(cpustate) ) return;
+
+ case 0x78: // ADD HL,mn
+ case 0x79: // ADC HL,mn
+ case 0x7a: // SUB HL,mn
+ case 0x7b: // SBC HL,mn
+ case 0x7c: // AND HL,mn
+ case 0x7d: // XOR HL,mn
+ case 0x7e: // OR HL,mn
+ case 0x7f: // CP HL,mn
+ OP16( ADD+b0-0x78,6 ) R16( 1, HL ) I16( 2, READ16(cpustate) ) return;
+
+ case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86:
+ OP( INC,2 ) R8( 1, b0 - 0x80 ) NONE( 2 ) return; // INC r
+ case 0x87:
+ OP( INC,10 ) MI16( 1, 0xFF00|READ8(cpustate) ) NONE( 2 ) return; // INC ($FF00+n)
+
+ case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e:
+ OP( DEC,2 ) R8( 1, b0 - 0x88 ) NONE( 2 ) return; // DEC r
+ case 0x8f:
+ OP( DEC,10 ) MI16( 1, 0xFF00|READ8(cpustate) ) NONE( 2 ) return; // DEC ($FF00+n)
+
+ case 0x90: case 0x91: case 0x92: /*case 0x93:*/ case 0x94: case 0x95: case 0x96:
+ OP16( INC,4 ) R16( 1, b0 - 0x90 ) NONE( 2 ) return; // INC rr
+ case 0x97:
+ OP( INCW,14 ) MI16( 1, 0xFF00|READ8(cpustate) ) NONE( 2 ) return; // INCW ($FF00+n)
+ case 0x98: case 0x99: case 0x9a: /*case 0x9b:*/ case 0x9c: case 0x9d: case 0x9e:
+ OP16( DEC,4 ) R16( 1, b0 - 0x98 ) NONE( 2 ) return; // DEC rr
+ case 0x9f:
+ OP( DECW,14 ) MI16( 1, 0xFF00|READ8(cpustate) ) NONE( 2 ) return; // DECW ($FF00+n)
+
+ case 0xa0: // RLC A
+ case 0xa1: // RRC A
+ case 0xa2: // RL A
+ case 0xa3: // RR A
+ case 0xa4: // SLA A
+ case 0xa5: // SRA A
+ case 0xa6: // SLL A
+ case 0xa7: // SRL A
+ OP( RLC+b0-0xa0,2 ) R8( 1, A ) NONE( 2 ) return;
+
+ case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
+ OP( BIT,8 ) BIT8( 1, b0 - 0xa8 ) MI16( 2, 0xFF00|READ8(cpustate) ) return; // BIT b,($FF00+n)
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ OP( RES,12 ) BIT8( 1, b0 - 0xb0 ) MI16( 2, 0xFF00|READ8(cpustate) ) return; // RES b,($FF00+n)
+ case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ OP( SET,12 ) BIT8( 1, b0 - 0xb8 ) MI16( 2, 0xFF00|READ8(cpustate) ) return; // SET b,($FF00+n)
+
+ 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:
+ OPCC( JR,4,8 ) CC( 1, b0 - 0xc0 ) D8( 2, READ8(cpustate) ) return; // JR cc,+d
+
+ case 0xe0: case 0xe1: case 0xe2: /*case 0xe3:*/ case 0xe4: case 0xe5: case 0xe6:
+ b1 = READ8(cpustate);
+ switch ( b1 ) {
+ case 0x10: // RLD (gg)
+ case 0x11: // RRD (gg)
+ OP( RLD+b1-0x10,12 ) MR16( 1, b0 - 0xe0 ) NONE( 2 ) return;
+
+ case 0x12: // MUL HL,(gg)
+ case 0x13: // DIV HL,(gg)
+ OP( MUL+b1-0x12,18 ) R16( 1, HL ) MR16( 2, b0 - 0xe0 ) return;
+
+ case 0x14: case 0x15: case 0x16:
+ OP16( ADD,8 ) R16( 1, IX+b1-0x14 ) MR16( 2, b0 - 0xe0 ) return; // ADD ix,(gg)
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e:
+ OP( LD,6 ) R8( 1, b1 - 0x28 ) MR16( 2, b0 - 0xe0 ) return; // LD r,(gg)
+ case 0x48: case 0x49: case 0x4a: /*case 0x4b:*/ case 0x4c: case 0x4d: case 0x4e:
+ OP16( LD,8 ) R16( 1, b1 - 0x48 ) MR16( 2, b0 - 0xe0 ) return; // LD rr,(gg)
+
+ case 0x50: case 0x51: case 0x52: /*case 0x53:*/ case 0x54: case 0x55: case 0x56:
+ OP( EX,14 ) MR16( 1, b0 - 0xe0 ) R16( 2, b1 - 0x50 ) return; // EX (gg),rr
+
+ case 0x60: // ADD A,(gg)
+ case 0x61: // ADC A,(gg)
+ case 0x62: // SUB A,(gg)
+ case 0x63: // SBC A,(gg)
+ case 0x64: // AND A,(gg)
+ case 0x65: // XOR A,(gg)
+ case 0x66: // OR A,(gg)
+ case 0x67: // CP A,(gg)
+ OP( ADD+b1-0x60,6 ) R8( 1, A ) MR16( 2, b0 - 0xe0 ) return;
+
+ case 0x70: // ADD HL,(gg)
+ case 0x71: // ADC HL,(gg)
+ case 0x72: // SUB HL,(gg)
+ case 0x73: // SBC HL,(gg)
+ case 0x74: // AND HL,(gg)
+ case 0x75: // XOR HL,(gg)
+ case 0x76: // OR HL,(gg)
+ case 0x77: // CP HL,(gg)
+ OP16( ADD+b1-0x70,8 ) R16( 1, HL ) MR16( 2, b0 - 0xe0 ) return;
+
+ case 0x87:
+ OP( INC,8 ) MR16( 1, b0 - 0xe0 ) NONE( 2 ) return; // INC (gg)
+ case 0x8f:
+ OP( DEC,8 ) MR16( 1, b0 - 0xe0 ) NONE( 2 ) return; // DEC (gg)
+
+ case 0x97:
+ OP( INCW,12 ) MR16( 1, b0 - 0xe0 ) NONE( 2 ) return; // INCW (gg)
+ case 0x9f:
+ OP( DECW,12 ) MR16( 1, b0 - 0xe0 ) NONE( 2 ) return; // DECW (gg)
+
+ case 0xa0: // RLC (gg)
+ case 0xa1: // RRC (gg)
+ case 0xa2: // RL (gg)
+ case 0xa3: // RR (gg)
+ case 0xa4: // SLA (gg)
+ case 0xa5: // SRA (gg)
+ case 0xa6: // SLL (gg)
+ case 0xa7: // SRL (gg)
+ OP( RLC+b1-0xa0,8 ) MR16( 1, b0 - 0xe0 ) NONE( 2 ) return;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ OP( TSET,12 ) BIT8( 1, b1 - 0x18 ) MR16( 2, b0 - 0xe0 ) return; // TSET b,(gg)
+ case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
+ OP( BIT,6 ) BIT8( 1, b1 - 0xa8 ) MR16( 2, b0 - 0xe0 ) return; // BIT b,(gg)
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ OP( RES,10 ) BIT8( 1, b1 - 0xb0 ) MR16( 2, b0 - 0xe0 ) return; // RES b,(gg)
+ case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ OP( SET,10 ) BIT8( 1, b1 - 0xb8 ) MR16( 2, b0 - 0xe0 ) return; // SET b,(gg)
+ } break;
+ case 0xe3:
+ imm16 = READ16(cpustate);
+ b3 = READ8(cpustate);
+ switch ( b3 ) {
+ case 0x10: // RLD (mn)
+ case 0x11: // RRD (mn)
+ OP( RLD+b3-0x10,16 ) MI16( 1, imm16 ) NONE( 2 ) return;
+
+ case 0x12: // MUL HL,(mn)
+ case 0x13: // DIV HL,(mn)
+ OP( MUL+b3-0x12,22 ) R16( 1, HL ) MI16( 2, imm16 ) return;
+
+ case 0x14: case 0x15: case 0x16:
+ OP16( ADD,12 ) R16( 1, IX+b3-0x14 ) MI16( 2, imm16 ) return; // ADD ix,(mn)
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e:
+ OP( LD,10 ) R8( 1, b3 - 0x28 ) MI16( 2, imm16 ) return; // LD r,(mn)
+ case 0x48: case 0x49: case 0x4a: /*case 0x4b:*/ case 0x4c: case 0x4d: case 0x4e:
+ OP16( LD,12 ) R16( 1, b3 - 0x48 ) MI16( 2, imm16 ) return; // LD rr,(mn)
+
+ case 0x50: case 0x51: case 0x52: /*case 0x53:*/ case 0x54: case 0x55: case 0x56:
+ OP( EX,18 ) MI16( 1, imm16 ) R16( 2, b3 - 0x50 ) return; // EX (mn),rr
+
+ case 0x60: // ADD A,(mn)
+ case 0x61: // ADC A,(mn)
+ case 0x62: // SUB A,(mn)
+ case 0x63: // SBC A,(mn)
+ case 0x64: // AND A,(mn)
+ case 0x65: // XOR A,(mn)
+ case 0x66: // OR A,(mn)
+ case 0x67: // CP A,(mn)
+ OP( ADD+b3-0x60,10 ) R8( 1, A ) MI16( 2, imm16 ) return;
+
+ case 0x70: // ADD HL,(mn)
+ case 0x71: // ADC HL,(mn)
+ case 0x72: // SUB HL,(mn)
+ case 0x73: // SBC HL,(mn)
+ case 0x74: // AND HL,(mn)
+ case 0x75: // XOR HL,(mn)
+ case 0x76: // OR HL,(mn)
+ case 0x77: // CP HL,(mn)
+ OP16( ADD+b3-0x70,12 ) R16( 1, HL ) MI16( 2, imm16 ) return;
+
+ case 0x87:
+ OP( INC,12 ) MI16( 1, imm16 ) NONE( 2 ) return; // INC (mn)
+ case 0x8f:
+ OP( DEC,12 ) MI16( 1, imm16 ) NONE( 2 ) return; // DEC (mn)
+
+ case 0x97:
+ OP( INCW,16 ) MI16( 1, imm16 ) NONE( 2 ) return; // INCW (mn)
+ case 0x9f:
+ OP( DECW,16 ) MI16( 1, imm16 ) NONE( 2 ) return; // DECW (mn)
+
+ case 0xa0: // RLC (mn)
+ case 0xa1: // RRC (mn)
+ case 0xa2: // RL (mn)
+ case 0xa3: // RR (mn)
+ case 0xa4: // SLA (mn)
+ case 0xa5: // SRA (mn)
+ case 0xa6: // SLL (mn)
+ case 0xa7: // SRL (mn)
+ OP( RLC+b3-0xa0,12 ) MI16( 1, imm16 ) NONE( 2 ) return;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ OP( TSET,16 ) BIT8( 1, b3 - 0x18 ) MI16( 2, imm16 ) return; // TSET b,(mn)
+ case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
+ OP( BIT,10 ) BIT8( 1, b3 - 0xa8 ) MI16( 2, imm16 ) return; // BIT b,(mn)
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ OP( RES,14 ) BIT8( 1, b3 - 0xb0 ) MI16( 2, imm16 ) return; // RES b,(mn)
+ case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ OP( SET,14 ) BIT8( 1, b3 - 0xb8 ) MI16( 2, imm16 ) return; // SET b,(mn)
+ } break;
+
+ case 0xe7:
+ b1 = READ8(cpustate);
+ b2 = READ8(cpustate);
+ switch ( b2 ) {
+ case 0x10: // RLD ($FF00+n)
+ case 0x11: // RRD ($FF00+n)
+ OP( RLD+b2-0x10,14 ) MI16( 1, 0xFF00|b1 ) NONE( 2 ) return;
+
+ case 0x12: // MUL HL,($FF00+n)
+ case 0x13: // DIV HL,($FF00+n)
+ OP( MUL+b2-0x12,20 ) R16( 1, HL ) MI16( 2, 0xFF00|b1 ) return;
+
+ case 0x14: case 0x15: case 0x16:
+ OP16( ADD,10 ) R16( 1, IX+b2-0x14 ) MI16( 2, 0xFF00|b1 ) return; // ADD ix,($FF00+n)
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ OP( TSET,14 ) BIT8( 1, b2 - 0x18 ) MI16( 2, 0xFF00|b1 ) return; // TSET b,($FF00+n)
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e:
+ OP( LD,8 ) R8( 1, b2 - 0x28 ) MI16( 2, 0xFF00|b1 ) return; // LD r,($FF00+n)
+ case 0x48: case 0x49: case 0x4a: /*case 0x4b:*/ case 0x4c: case 0x4d: case 0x4e:
+ OP16( LD,10 ) R16( 1, b2 - 0x48 ) MI16( 2, 0xFF00|b1 ) return; // LD rr,($FF00+n)
+
+ case 0x50: case 0x51: case 0x52: /*case 0x53:*/ case 0x54: case 0x55: case 0x56:
+ OP( EX,16 ) MI16( 1, 0xFF00|b1 ) R16( 2, b2 - 0x50 ) return; // EX ($FF00+n),rr
+
+ case 0xa0: // RLC ($FF00+n)
+ case 0xa1: // RRC ($FF00+n)
+ case 0xa2: // RL ($FF00+n)
+ case 0xa3: // RR ($FF00+n)
+ case 0xa4: // SLA ($FF00+n)
+ case 0xa5: // SRA ($FF00+n)
+ case 0xa6: // SLL ($FF00+n)
+ case 0xa7: // SRL ($FF00+n)
+ OP( RLC+b2-0xa0,10 ) MI16( 1, 0xFF00|b1 ) NONE( 2 ) return;
+ } break;
+
+ case 0xe8: case 0xe9: case 0xea: /*case 0xeb:*/ case 0xec: case 0xed: case 0xee:
+ b1 = READ8(cpustate);
+ switch ( b1 ) {
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26:
+ OP( LD,6 ) MR16( 1, b0 - 0xe8 ) R8( 2, b1 - 0x20 ) return; // LD (gg),r
+ case 0x37:
+ OP( LD,8 ) MR16( 1, b0 - 0xe8 ) I8( 2, READ8(cpustate) ) return; // LD (gg),n
+ case 0x3f:
+ OP( LDW,12 ) MR16( 1, b0 - 0xe8 ) I16( 2, READ16(cpustate) ) return; // LDW (gg),mn
+ case 0x40: case 0x41: case 0x42: /*case 0x43:*/ case 0x44: case 0x45: case 0x46:
+ OP16( LD,8 ) MR16( 1, b0 - 0xe8 ) R16( 2, b1 - 0x40 ) return; // LD (gg),rr
+
+ case 0x68: // ADD (gg),n
+ case 0x69: // ADC (gg),n
+ case 0x6a: // SUB (gg),n
+ case 0x6b: // SBC (gg),n
+ case 0x6c: // AND (gg),n
+ case 0x6d: // XOR (gg),n
+ case 0x6e: // OR (gg),n
+ OP( ADD+b1-0x68,10 ) MR16( 1, b0 - 0xe8 ) I8( 2, READ8(cpustate) ) return;
+ case 0x6f: // CP (gg),n
+ OP( CP,8 ) MR16( 1, b0 - 0xe8 ) I8( 2, READ8(cpustate) ) return;
+
+ 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:
+ OPCC( JP,6,8 ) CC( 1, b1 - 0xc0 ) R16( 2, b0 - 0xe8 ) return; // JP [cc,]gg
+ 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:
+ OPCC( CALL,6,14 ) CC( 1, b1 - 0xd0 ) R16( 2, b0 - 0xe8 ) return; // CALL [cc,]gg
+ } break;
+ case 0xeb:
+ imm16 = READ16(cpustate);
+ b3 = READ8(cpustate);
+ switch ( b3 ) {
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26:
+ OP( LD,10 ) MI16( 1, imm16 ) R8( 2, b3 - 0x20 ) return; // LD (mn),r
+ case 0x37:
+ OP( LD,12 ) MI16( 1, imm16 ) I8( 2, READ8(cpustate) ) return; // LD (vw),n
+ case 0x3f:
+ OP( LDW,16 ) MI16( 1, imm16 ) I16( 2, READ16(cpustate) ) return; // LDW (vw),mn
+ case 0x40: case 0x41: case 0x42: /*case 0x43:*/ case 0x44: case 0x45: case 0x46:
+ OP16( LD,12 ) MI16( 1, imm16 ) R16( 2, b3 - 0x40 ) return; // LD (mn),rr
+
+ case 0x68: // ADD (vw),n
+ case 0x69: // ADC (vw),n
+ case 0x6a: // SUB (vw),n
+ case 0x6b: // SBC (vw),n
+ case 0x6c: // AND (vw),n
+ case 0x6d: // XOR (vw),n
+ case 0x6e: // OR (vw),n
+ OP( ADD+b3-0x68,14 ) MI16( 1, imm16 ) I8( 2, READ8(cpustate) ) return;
+ case 0x6f: // CP (vw),n
+ OP( ADD+b3-0x68,12 ) MI16( 1, imm16 ) I8( 2, READ8(cpustate) ) return;
+
+ 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:
+ OPCC( JP,10,12 ) CC( 1, b3 - 0xc0 ) I16( 2, imm16 ) return; // JP cc,mn
+ 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:
+ OPCC( CALL,10,18 ) CC( 1, b3 - 0xd0 ) I16( 2, imm16 ) return; // CALL cc,mn
+ } break;
+
+ case 0xef:
+ b1 = READ8(cpustate);
+ b2 = READ8(cpustate);
+ switch ( b2 ) {
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26:
+ OP( LD,8 ) MI16( 1, 0xFF00|b1 ) R8( 2, b2 - 0x20 ) return; // LD ($FF00+n),r
+ case 0x40: case 0x41: case 0x42: /*case 0x43:*/ case 0x44: case 0x45: case 0x46:
+ OP16( LD,10 ) MI16( 1, 0xFF00|b1 ) R16( 2, b2 - 0x40 ) return; // LD ($FF00+n),rr
+
+ case 0x68: // ADD ($FF00+w),n
+ case 0x69: // ADC ($FF00+w),n
+ case 0x6a: // SUB ($FF00+w),n
+ case 0x6b: // SBC ($FF00+w),n
+ case 0x6c: // AND ($FF00+w),n
+ case 0x6d: // XOR ($FF00+w),n
+ case 0x6e: // OR ($FF00+w),n
+ OP( ADD+b2-0x68,12 ) MI16( 1, 0xFF00|b1 ) I8( 2, READ8(cpustate) ) return;
+ case 0x6f: // CP ($FF00+w),n
+ OP( ADD+b2-0x68,10 ) MI16( 1, 0xFF00|b1 ) I8( 2, READ8(cpustate) ) return;
+ } break;
+
+ case 0xf0: case 0xf1: case 0xf2:
+ b1 = READ8(cpustate);
+ b2 = READ8(cpustate);
+ switch ( b2 ) {
+ case 0x10: // RLD (ix+d)
+ case 0x11: // RRD (ix+d)
+ OP( RLD+b2-0x10,16 ) MR16D8( 1, IX + b0 - 0xf0, b1 ) NONE( 2 ) return;
+
+ case 0x12: // MUL HL,(ix+d)
+ case 0x13: // DIV HL,(ix+d)
+ OP( MUL+b2-0x12,22 ) R16( 1, HL ) MR16D8( 2, IX + b0 - 0xf0, b1 ) return;
+
+ case 0x14: case 0x15: case 0x16:
+ OP16( ADD,12 ) R16( 1, IX+b2-0x14 ) MR16D8( 2, IX + b0 - 0xf0, b1 ) return; // ADD ix,(jx+d)
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e:
+ OP( LD,10 ) R8( 1, b2 - 0x28 ) MR16D8( 2, IX + b0 - 0xf0, b1 ) return; // LD r,(ix+d)
+ case 0x48: case 0x49: case 0x4a: /*case 0x4b:*/ case 0x4c: case 0x4d: case 0x4e:
+ OP16( LD,12 ) R16( 1, b2 - 0x48 ) MR16D8( 2, IX + b0 - 0xf0, b1 ) return; // LD rr,(ix+d)
+
+ case 0x50: case 0x51: case 0x52: /*case 0x53:*/ case 0x54: case 0x55: case 0x56:
+ OP( EX,18 ) MR16D8( 1, IX + b0 - 0xf0, b1 ) R16( 2, b2 - 0x50 ) return; // EX (ix+d),rr
+
+ case 0x60: // ADD A,(ix+d)
+ case 0x61: // ADC A,(ix+d)
+ case 0x62: // SUB A,(ix+d)
+ case 0x63: // SBC A,(ix+d)
+ case 0x64: // AND A,(ix+d)
+ case 0x65: // XOR A,(ix+d)
+ case 0x66: // OR A,(ix+d)
+ case 0x67: // CP A,(ix+d)
+ OP( ADD+b2-0x60,10 ) R8( 1, A ) MR16D8( 2, IX + b0 - 0xf0, b1 ) return;
+
+ case 0x70: // ADD HL,(ix+d)
+ case 0x71: // ADC HL,(ix+d)
+ case 0x72: // SUB HL,(ix+d)
+ case 0x73: // SBC HL,(ix+d)
+ case 0x74: // AND HL,(ix+d)
+ case 0x75: // XOR HL,(ix+d)
+ case 0x76: // OR HL,(ix+d)
+ case 0x77: // CP HL,(ix+d)
+ OP16( ADD+b2-0x70,12 ) R16( 1, HL ) MR16D8( 2, IX + b0 - 0xf0, b1 ) return;
+
+ case 0x87:
+ OP( INC,12 ) MR16D8( 1, IX + b0 - 0xf0, b1 ) NONE( 2 ) return; // INC (ix+d)
+ case 0x8f:
+ OP( DEC,12 ) MR16D8( 1, IX + b0 - 0xf0, b1 ) NONE( 2 ) return; // DEC (ix+d)
+
+ case 0x97:
+ OP( INCW,16 ) MR16D8( 1, IX + b0 - 0xf0, b1 ) NONE( 2 ) return; // INCW (ix+d)
+ case 0x9f:
+ OP( DECW,16 ) MR16D8( 1, IX + b0 - 0xf0, b1 ) NONE( 2 ) return; // DECW (ix+d)
+
+ case 0xa0: // RLC (ix+d)
+ case 0xa1: // RRC (ix+d)
+ case 0xa2: // RL (ix+d)
+ case 0xa3: // RR (ix+d)
+ case 0xa4: // SLA (ix+d)
+ case 0xa5: // SRA (ix+d)
+ case 0xa6: // SLL (ix+d)
+ case 0xa7: // SRL (ix+d)
+ OP( RLC+b2-0xa0,12 ) MR16D8( 1, IX + b0 - 0xf0, b1 ) NONE( 2 ) return;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ OP( TSET,16 ) BIT8( 1, b2 - 0x18 ) MR16D8( 2, IX + b0 - 0xf0, b1 ) return; // TSET b,(ix+d)
+ case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
+ OP( BIT,10 ) BIT8( 1, b2 - 0xa8 ) MR16D8( 2, IX + b0 - 0xf0, b1 ) return; // BIT b,(ix+d)
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ OP( RES,14 ) BIT8( 1, b2 - 0xb0 ) MR16D8( 2, IX + b0 - 0xf0, b1 ) return; // RES b,(ix+d)
+ case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ OP( SET,14 ) BIT8( 1, b2 - 0xb8 ) MR16D8( 2, IX + b0 - 0xf0, b1 ) return; // SET b,(ix+d)
+ } break;
+
+ case 0xf3:
+ b1 = READ8(cpustate);
+ switch ( b1 ) {
+ case 0x10: // RLD (HL+A)
+ case 0x11: // RRD (HL+A)
+ OP( RLD+b1-0x10,20 ) MR16R8( 1, HL, A ) NONE( 2 ) return;
+
+ case 0x12: // MUL HL,(HL+A)
+ case 0x13: // DIV HL,(HL+A)
+ OP( MUL+b1-0x12,26 ) R16( 1, HL ) MR16R8( 2, HL, A ) return;
+
+ case 0x14: case 0x15: case 0x16:
+ OP16( ADD,16 ) R16( 1, IX+b1-0x14 ) MR16R8( 2, HL, A ) return; // ADD ix,(HL+A)
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e:
+ OP( LD,14 ) R8( 1, b1 - 0x28 ) MR16R8( 2, HL, A ) return; // LD r,(HL+A)
+ case 0x48: case 0x49: case 0x4a: /*case 0x4b:*/ case 0x4c: case 0x4d: case 0x4e:
+ OP16( LD,16 ) R16( 1, b1 - 0x48 ) MR16R8( 2, HL, A ) return; // LD rr,(HL+A)
+
+ case 0x50: case 0x51: case 0x52: /*case 0x53:*/ case 0x54: case 0x55: case 0x56:
+ OP( EX,22 ) MR16R8( 1, HL, A ) R16( 2, b1 - 0x50 ) return; // EX (HL+A),rr
+
+ case 0x60: // ADD A,(HL+A)
+ case 0x61: // ADC A,(HL+A)
+ case 0x62: // SUB A,(HL+A)
+ case 0x63: // SBC A,(HL+A)
+ case 0x64: // AND A,(HL+A)
+ case 0x65: // XOR A,(HL+A)
+ case 0x66: // OR A,(HL+A)
+ case 0x67: // CP A,(HL+A)
+ OP( ADD+b1-0x60,14 ) R8( 1, A ) MR16R8( 2, HL, A ) return;
+
+ case 0x70: // ADD HL,(HL+A)
+ case 0x71: // ADC HL,(HL+A)
+ case 0x72: // SUB HL,(HL+A)
+ case 0x73: // SBC HL,(HL+A)
+ case 0x74: // AND HL,(HL+A)
+ case 0x75: // XOR HL,(HL+A)
+ case 0x76: // OR HL,(HL+A)
+ case 0x77: // CP HL,(HL+A)
+ OP16( ADD+b1-0x70,16 ) R16( 1, HL ) MR16R8( 2, HL, A ) return;
+
+ case 0x87:
+ OP( INC,16 ) MR16R8( 1, HL, A ) NONE( 2 ) return; // INC (HL+A)
+ case 0x8f:
+ OP( DEC,16 ) MR16R8( 1, HL, A ) NONE( 2 ) return; // DEC (HL+A)
+
+ case 0x97:
+ OP( INCW,20 ) MR16R8( 1, HL, A ) NONE( 2 ) return; // INCW (HL+A)
+ case 0x9f:
+ OP( DECW,20 ) MR16R8( 1, HL, A ) NONE( 2 ) return; // DECW (HL+A)
+
+ case 0xa0: // RLC (HL+A)
+ case 0xa1: // RRC (HL+A)
+ case 0xa2: // RL (HL+A)
+ case 0xa3: // RR (HL+A)
+ case 0xa4: // SLA (HL+A)
+ case 0xa5: // SRA (HL+A)
+ case 0xa6: // SLL (HL+A)
+ case 0xa7: // SRL (HL+A)
+ OP( RLC+b1-0xa0,16 ) MR16R8( 1, HL, A ) NONE( 2 ) return;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ OP( TSET,20 ) BIT8( 1, b1 - 0x18 ) MR16R8( 2, HL, A ) return; // TSET b,(HL+A)
+ case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
+ OP( BIT,14 ) BIT8( 1, b1 - 0xa8 ) MR16R8( 2, HL, A ) return; // BIT b,(HL+A)
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ OP( RES,18 ) BIT8( 1, b1 - 0xb0 ) MR16R8( 2, HL, A ) return; // RES b,(HL+A)
+ case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ OP( SET,18 ) BIT8( 1, b1 - 0xb8 ) MR16R8( 2, HL, A ) return; // SET b,(HL+A)
+ } break;
+
+ case 0xf4: case 0xf5: case 0xf6:
+ b1 = READ8(cpustate);
+ b2 = READ8(cpustate);
+ switch ( b2 ) {
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26:
+ OP( LD,10 ) MR16D8( 1, IX + b0 - 0xf4, b1 ) R8( 2, b2 - 0x20 ) return; // LD (ix+d),r
+ case 0x37:
+ OP( LD,12 ) MR16D8( 1, IX + b0 - 0xf4, b1 ) I8( 2, READ8(cpustate) ) return; // LD (ix+d),n
+ case 0x38: case 0x39: case 0x3a: /*case 0x3b:*/ case 0x3c: case 0x3d: case 0x3e:
+ OP( LDA,10 ) R16( 1, b2 - 0x38 ) R16D8( 2, IX + b0 - 0xf4, b1 ) return; // LDA rr,ix+d
+ case 0x3f:
+ OP( LDW,16 ) MR16D8( 1, IX + b0 - 0xf4, b1 ) I16( 2, READ16(cpustate) ) return; // LDW (ix+d),mn
+ case 0x40: case 0x41: case 0x42: /*case 0x43:*/ case 0x44: case 0x45: case 0x46:
+ OP16( LD,12 ) MR16D8( 1, IX + b0 - 0xf4, b1 ) R16( 2, b2 - 0x40 ) return; // LD (ix+d),rr
+
+ case 0x68: // ADD (ix+d),n
+ case 0x69: // ADC (ix+d),n
+ case 0x6a: // SUB (ix+d),n
+ case 0x6b: // SBC (ix+d),n
+ case 0x6c: // AND (ix+d),n
+ case 0x6d: // XOR (ix+d),n
+ case 0x6e: // OR (ix+d),n
+ OP( ADD+b2-0x68,14) MR16D8( 1, IX + b0 - 0xf4, b1 ) I8( 2, READ8(cpustate) ) return;
+ case 0x6f: // CP (ix+d),n
+ OP( ADD+b2-0x68,12) MR16D8( 1, IX + b0 - 0xf4, b1 ) I8( 2, READ8(cpustate) ) return;
+
+ 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:
+ OPCC( JP,10,12 ) CC( 1, b2 - 0xc0 ) R16D8( 2, IX + b0 - 0xf4, b1 ) return; // JP [cc,]ix+d
+ 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:
+ OPCC( CALL,10,18 ) CC( 1, b2 - 0xd0 ) R16D8( 2, IX + b0 - 0xf4, b1 ) return; // CALL [cc,]ix+d
+ } break;
+
+ case 0xf7:
+ b1 = READ8(cpustate);
+ switch ( b1 ) {
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26:
+ OP( LD,14 ) MR16R8( 1, HL, A ) R8( 2, b1 - 0x20 ) return; // LD (HL+A),r
+ case 0x37:
+ OP( LD,16 ) MR16R8( 1, HL, A ) I8( 2, READ8(cpustate) ) return; // LD (HL+A),n
+ case 0x38: case 0x39: case 0x3a: /*case 0x3b:*/ case 0x3c: case 0x3d: case 0x3e:
+ OP( LDA,14 ) R16( 1, b1 - 0x38 ) R16R8( 2, HL, A ) return; // LDA rr,HL+A
+ case 0x3f:
+ OP( LDW,20 ) MR16R8( 1, HL, A ) I16( 2, READ16(cpustate) ) return; // LDW (HL+A),mn
+ case 0x40: case 0x41: case 0x42: /*case 0x43:*/ case 0x44: case 0x45: case 0x46:
+ OP16( LD,16 ) MR16R8( 1, HL, A ) R16( 2, b1 - 0x40 ) return; // LD (HL+A),rr
+
+ case 0x68: // ADD (HL+A),n
+ case 0x69: // ADC (HL+A),n
+ case 0x6a: // SUB (HL+A),n
+ case 0x6b: // SBC (HL+A),n
+ case 0x6c: // AND (HL+A),n
+ case 0x6d: // XOR (HL+A),n
+ case 0x6e: // OR (HL+A),n
+ OP( ADD+b1-0x68,18) MR16R8( 1, HL, A ) I8( 2, READ8(cpustate) ) return;
+ case 0x6f: // CP (HL+A),n
+ OP( ADD+b1-0x68,16) MR16R8( 1, HL, A ) I8( 2, READ8(cpustate) ) return;
+
+ 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:
+ OPCC( JP,14,16 ) CC( 1, b1 - 0xc0 ) R16R8( 2, HL, A ) return; // JP [cc,]HL+A
+ 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:
+ OPCC( CALL,14,22 ) CC( 1, b1 - 0xd0 ) R16R8( 2, HL, A ) return; // CALL [cc,]HL+A
+ } break;
+
+ case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe:
+ b1 = READ8(cpustate);
+ switch ( b1 ) {
+ case 0x12: // MUL HL,g
+ case 0x13: // DIV HL,g
+ OP( MUL+b1-0x12,18) R16( 1, HL ) R8( 2, b0 - 0xf8 ) return;
+
+ case 0x14: case 0x15: case 0x16:
+ OP16( ADD,8 ) R16( 1, IX+b1-0x14 ) R16( 2, b0 - 0xf8 ) return; // ADD ix,gg
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36:
+ OP( LD,4 ) R8( 1, b1 - 0x30 ) R8( 2, b0 - 0xf8 ) return; // LD r,g
+ case 0x38: case 0x39: case 0x3a: /*case 0x3b:*/ case 0x3c: case 0x3d: case 0x3e:
+ OP16( LD,6 ) R16( 1, b1 - 0x38 ) R16( 2, b0 - 0xf8 ) return; // LD rr,gg
+
+ case 0x58: // LDI
+ case 0x59: // LDIR
+ case 0x5a: // LDD
+ case 0x5b: // LDDR
+ case 0x5c: // CPI
+ case 0x5d: // CPIR
+ case 0x5e: // CPD
+ case 0x5f: // CPDR
+ if (b0 == 0xfe) {
+ OPCC( LDI+b1-0x58,14,18 ) NONE( 1 ) NONE( 2 ) return;
+ }
+
+ case 0x60: // ADD A,g
+ case 0x61: // ADC A,g
+ case 0x62: // SUB A,g
+ case 0x63: // SBC A,g
+ case 0x64: // AND A,g
+ case 0x65: // XOR A,g
+ case 0x66: // OR A,g
+ case 0x67: // CP A,g
+ OP( ADD+b1-0x60,4 ) R8( 1, A ) R8( 2, b0 - 0xf8 ) return;
+
+ case 0x68: // ADD g,n
+ case 0x69: // ADC g,n
+ case 0x6a: // SUB g,n
+ case 0x6b: // SBC g,n
+ case 0x6c: // AND g,n
+ case 0x6d: // XOR g,n
+ case 0x6e: // OR g,n
+ case 0x6f: // CP g,n
+ OP( ADD+b1-0x68,6 ) R8( 1, b0 - 0xf8 ) I8( 2, READ8(cpustate) ) return;
+
+ case 0x70: // ADD HL,gg
+ case 0x71: // ADC HL,gg
+ case 0x72: // SUB HL,gg
+ case 0x73: // SBC HL,gg
+ case 0x74: // AND HL,gg
+ case 0x75: // XOR HL,gg
+ case 0x76: // OR HL,gg
+ case 0x77: // CP HL,gg
+ OP16( ADD+b1-0x70,8 ) R16( 1, HL ) R16( 2, b0 - 0xf8 ) return;
+
+ case 0xa0: // RLC g
+ case 0xa1: // RRC g
+ case 0xa2: // RL g
+ case 0xa3: // RR g
+ case 0xa4: // SLA g
+ case 0xa5: // SRA g
+ case 0xa6: // SLL g
+ case 0xa7: // SRL g
+ OP( RLC+b1-0xa0,4 ) R8( 1, b0 - 0xf8 ) NONE( 2 ) return;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ OP( TSET,8 ) BIT8( 1, b1 - 0x18 ) R8( 2, b0 - 0xf8 ) return; // TSET b,g
+ case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
+ OP( BIT,4 ) BIT8( 1, b1 - 0xa8 ) R8( 2, b0 - 0xf8 ) return; // BIT b,g
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ OP( RES,4 ) BIT8( 1, b1 - 0xb0 ) R8( 2, b0 - 0xf8 ) return; // RES b,g
+ case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ OP( SET,4 ) BIT8( 1, b1 - 0xb8 ) R8( 2, b0 - 0xf8 ) return; // SET b,g
+
+ 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:
+ if (b0 == 0xfe) {
+ OPCC( RET,6,14 ) CC( 1, b1 - 0xd0 ) NONE( 2 ) return; // RET cc
+ }
+ } break;
+
+ case 0xff:
+ OP( SWI,20 ) NONE( 1 ) NONE( 2 ) return; // SWI
+ }
+
+ OP( UNKNOWN,2 ) NONE( 1 ) NONE( 2 )
+}
+
+static const char *const ir_names[] = {
+ "P0", "P1", "P01CR/IRFL", "IRFH", "P2", "P2CR", "P3", "P3CR",
+ "P4", "P4CR", "P5", "SMMOD", "P6", "P7", "P67CR", "SMCR",
+ "P8", "P8CR", "WDMOD", "WDCR", "TREG0", "TREG1", "TREG2", "TREG3",
+ "TCLK", "TFFCR", "TMOD", "TRUN", "CAP1L", "CAP1H", "CAP2L", "CAL2H",
+ "TREG4L", "TREG4H", "TREG5L", "TREG5H", "T4MOD", "T4FFCR", "INTEL", "INTEH",
+ "DMAEH", "SCMOD", "SCCR", "SCBUF", "BX", "BY", "ADREG", "ADMOD"
+};
+
+static const char *internal_registers_names(UINT16 x)
+{
+ int ir = x - T90_IOBASE;
+ if ( ir >= 0 && ir < sizeof(ir_names)/sizeof(ir_names[0]) )
+ return ir_names[ir];
+ return NULL;
+}
+static int sprint_arg(char *buffer, UINT32 pc, const char *pre, const e_mode mode, const e_r r, const e_r rb)
+{
+ const char *reg_name;
+ switch ( mode )
+ {
+ case MODE_NONE: return 0;
+
+ case MODE_BIT8: return sprintf( buffer, "%s%d", pre, r );
+ case MODE_I8: return sprintf( buffer, "%s$%02X", pre, r );
+ case MODE_D8: return sprintf( buffer, "%s$%04X", pre, (pc+2+(r&0x7f)-(r&0x80))&0xffff );
+ case MODE_I16: return sprintf( buffer, "%s$%04X", pre, r );
+ case MODE_D16: return sprintf( buffer, "%s$%04X", pre, (pc+2+(r&0x7fff)-(r&0x8000))&0xffff );
+ case MODE_MI16:
+ reg_name = internal_registers_names(r);
+ return (reg_name) ? sprintf( buffer, "%s(%s)", pre, reg_name ):
+ sprintf( buffer, "%s($%04X)", pre, r );
+ case MODE_R8: return sprintf( buffer, "%s%s", pre, r8_names[r] );
+ case MODE_R16: return sprintf( buffer, "%s%s", pre, r16_names[r] );
+ case MODE_MR16: return sprintf( buffer, "%s(%s)", pre, r16_names[r] );
+
+ case MODE_MR16R8: return sprintf( buffer, "%s(%s+%s)", pre, r16_names[r], r8_names[rb] );
+ case MODE_MR16D8: return sprintf( buffer, "%s(%s%c$%02X)", pre, r16_names[r], (rb&0x80)?'-':'+', (rb&0x80)?((rb^0xff)+1):rb );
+
+ case MODE_CC: return sprintf( buffer, "%s%s", pre, cc_names[r] );
+
+ case MODE_R16R8: return sprintf( buffer, "%s%s+%s", pre, r16_names[r], r8_names[rb] );
+ case MODE_R16D8: return sprintf( buffer, "%s%s%c$%02X", pre, r16_names[r], (rb&0x80)?'-':'+', (rb&0x80)?((rb^0xff)+1):rb );
+
+ default:
+ fatalerror("%04x: unimplemented addr mode = %d\n",pc,mode);
+ }
+
+ return 0;
+}
+
+CPU_DISASSEMBLE( t90 )
+{
+ t90_Regs *cpustate = get_safe_token(device);
+ int len;
+
+ cpustate->addr = pc;
+
+ decode(cpustate);
+ cpustate->op &= ~OP_16;
+
+ buffer += sprintf ( buffer, "%-5s", op_names[ cpustate->op ] ); // strlen("callr") == 5
+ len = sprint_arg ( buffer, pc, " ", cpustate->mode1, cpustate->r1, cpustate->r1b );
+ buffer += len;
+ buffer += sprint_arg ( buffer, pc, (len>1)?",":"", cpustate->mode2, cpustate->r2, cpustate->r2b );
+
+ return (cpustate->addr - pc) | DASMFLAG_SUPPORTED;
+}
+
+
+INLINE UINT16 r8( t90_Regs *cpustate, const e_r r )
+{
+ switch( r )
+ {
+ case A: return cpustate->af.b.h;
+ case B: return cpustate->bc.b.h;
+ case C: return cpustate->bc.b.l;
+ case D: return cpustate->de.b.h;
+ case E: return cpustate->de.b.l;
+ case H: return cpustate->hl.b.h;
+ case L: return cpustate->hl.b.l;
+
+ default:
+ fatalerror("%04x: unimplemented r8 register index = %d\n",cpustate->pc.w.l,r);
+ }
+}
+
+INLINE void w8( t90_Regs *cpustate, const e_r r, UINT16 value )
+{
+ switch( r )
+ {
+ case A: cpustate->af.b.h = value; return;
+ case B: cpustate->bc.b.h = value; return;
+ case C: cpustate->bc.b.l = value; return;
+ case D: cpustate->de.b.h = value; return;
+ case E: cpustate->de.b.l = value; return;
+ case H: cpustate->hl.b.h = value; return;
+ case L: cpustate->hl.b.l = value; return;
+
+ default:
+ fatalerror("%04x: unimplemented w8 register index = %d\n",cpustate->pc.w.l,r);
+ }
+}
+
+INLINE UINT16 r16( t90_Regs *cpustate, const e_r r )
+{
+ switch( r )
+ {
+ case BC: return cpustate->bc.w.l;
+ case DE: return cpustate->de.w.l;
+ case HL: return cpustate->hl.w.l;
+ case IX: return cpustate->ix.w.l;
+ case IY: return cpustate->iy.w.l;
+ case SP: return cpustate->sp.w.l;
+ case AF: return cpustate->af.w.l;
+// case AF2: return cpustate->af2.w.l;
+// one interrupt flip-flop? Needed by e.g. mjifb
+ case AF2: return (cpustate->af2.w.l & (~IF)) | (cpustate->af.w.l & IF);
+ case PC: return cpustate->pc.w.l;
+
+ default:
+ fatalerror("%04x: unimplemented r16 register index = %d\n",cpustate->pc.w.l,r);
+ }
+}
+
+INLINE void w16( t90_Regs *cpustate, const e_r r, UINT16 value )
+{
+ switch( r )
+ {
+ case BC: cpustate->bc.w.l = value; return;
+ case DE: cpustate->de.w.l = value; return;
+ case HL: cpustate->hl.w.l = value; return;
+ case IX: cpustate->ix.w.l = value; return;
+ case IY: cpustate->iy.w.l = value; return;
+ case SP: cpustate->sp.w.l = value; return;
+ case AF: cpustate->af.w.l = value; return;
+ case AF2: cpustate->af2.w.l = value; return;
+ case PC: cpustate->pc.d = value; return;
+
+ default:
+ fatalerror("%04x: unimplemented w16 register index = %d\n",cpustate->pc.w.l,r);
+ }
+}
+
+
+#define READ_FN( N ) \
+INLINE UINT8 Read##N##_8(t90_Regs *cpustate) { \
+ switch ( cpustate->mode##N ) { \
+ case MODE_CC: \
+ case MODE_BIT8: \
+ case MODE_I8: return (UINT8)cpustate->r##N; \
+ case MODE_D8: return (UINT8)cpustate->r##N; \
+ case MODE_R8: return (UINT8)r8(cpustate, cpustate->r##N); \
+ case MODE_MI16: return RM8(cpustate, cpustate->r##N); \
+ case MODE_MR16R8: return RM8(cpustate, (UINT16)(r16(cpustate, cpustate->r##N) + (INT8)r8(cpustate, cpustate->r##N##b))); \
+ case MODE_MR16: \
+ switch( cpustate->r##N ) { \
+ case IX: return RX8(cpustate, cpustate->ix.w.l,cpustate->ixbase); \
+ case IY: return RX8(cpustate, cpustate->iy.w.l,cpustate->iybase); \
+ } \
+ return RM8(cpustate, r16(cpustate, cpustate->r##N)); \
+ case MODE_MR16D8: \
+ switch( cpustate->r##N ) { \
+ case IX: return RX8(cpustate, (UINT16)(cpustate->ix.w.l + (INT8)cpustate->r##N##b),cpustate->ixbase); \
+ case IY: return RX8(cpustate, (UINT16)(cpustate->iy.w.l + (INT8)cpustate->r##N##b),cpustate->iybase); \
+ } \
+ return RM8(cpustate, (UINT16)(r16(cpustate, cpustate->r##N) + (INT8)cpustate->r##N##b)); \
+ default: \
+ fatalerror("%04x: unimplemented Read%d_8 mode = %d\n",cpustate->pc.w.l,N,cpustate->mode##N); \
+ } \
+ return 0; \
+} \
+INLINE UINT16 Read##N##_16(t90_Regs *cpustate) { \
+ switch ( cpustate->mode##N ) { \
+ case MODE_I16: return cpustate->r##N; \
+ case MODE_D16: return cpustate->r##N - 1; \
+ case MODE_R16: return r16(cpustate, cpustate->r##N); \
+ case MODE_R16D8: return r16(cpustate, cpustate->r##N) + (INT8)cpustate->r##N##b; \
+ case MODE_R16R8: return r16(cpustate, cpustate->r##N) + (INT8)r8(cpustate, cpustate->r##N##b); \
+ case MODE_MI16: return RM16(cpustate, cpustate->r##N); \
+ case MODE_MR16R8: return RM16(cpustate,(UINT16)(r16(cpustate, cpustate->r##N) + (INT8)r8(cpustate, cpustate->r##N##b))); \
+ case MODE_MR16: \
+ switch( cpustate->r##N ) { \
+ case IX: return RX16(cpustate, cpustate->ix.w.l,cpustate->ixbase); \
+ case IY: return RX16(cpustate, cpustate->iy.w.l,cpustate->iybase); \
+ } \
+ return RM16(cpustate,r16(cpustate, cpustate->r##N)); \
+ case MODE_MR16D8: \
+ switch( cpustate->r##N ) { \
+ case IX: return RX16(cpustate, (UINT16)(cpustate->ix.w.l + (INT8)cpustate->r##N##b),cpustate->ixbase); \
+ case IY: return RX16(cpustate, (UINT16)(cpustate->iy.w.l + (INT8)cpustate->r##N##b),cpustate->iybase); \
+ } \
+ return RM16(cpustate, (UINT16)(r16(cpustate, cpustate->r##N) + (INT8)cpustate->r##N##b)); \
+ default: \
+ fatalerror("%04x: unimplemented Read%d_16 modes = %d\n",cpustate->pc.w.l,N,cpustate->mode##N); \
+ } \
+ return 0; \
+}
+
+
+
+#define WRITE_FN( N ) \
+INLINE void Write##N##_8( t90_Regs *cpustate, UINT8 value ) { \
+ switch ( cpustate->mode##N ) { \
+ case MODE_R8: w8(cpustate, cpustate->r##N,value); return; \
+ case MODE_MI16: WM8(cpustate, cpustate->r##N, value); return; \
+ case MODE_MR16R8: WM8(cpustate, (UINT16)(r16(cpustate, cpustate->r##N) + (INT8)r8(cpustate, cpustate->r##N##b)), value); return; \
+ case MODE_MR16: \
+ switch( cpustate->r##N ) { \
+ case IX: WX8(cpustate, cpustate->ix.w.l,value,cpustate->ixbase); return; \
+ case IY: WX8(cpustate, cpustate->iy.w.l,value,cpustate->iybase); return; \
+ } \
+ WM8(cpustate, r16(cpustate, cpustate->r##N), value); return; \
+ case MODE_MR16D8: \
+ switch( cpustate->r##N ) { \
+ case IX: WX8(cpustate, (UINT16)(cpustate->ix.w.l + (INT8)cpustate->r##N##b),value,cpustate->ixbase); return; \
+ case IY: WX8(cpustate, (UINT16)(cpustate->iy.w.l + (INT8)cpustate->r##N##b),value,cpustate->iybase); return; \
+ } \
+ WM8(cpustate, (UINT16)(r16(cpustate, cpustate->r##N) + (INT8)cpustate->r##N##b), value); return; \
+ default: \
+ fatalerror("%04x: unimplemented Write%d_8 mode = %d\n",cpustate->pc.w.l,N,cpustate->mode##N); \
+ } \
+} \
+INLINE void Write##N##_16( t90_Regs *cpustate, UINT16 value ) \
+{ \
+ switch ( cpustate->mode##N ) { \
+ case MODE_R16: w16(cpustate, cpustate->r##N,value); return; \
+ case MODE_MI16: WM16(cpustate, cpustate->r##N, value); return; \
+ case MODE_MR16R8: WM16(cpustate, (UINT16)(r16(cpustate, cpustate->r##N) + (INT8)r8(cpustate, cpustate->r##N##b)), value); return; \
+ case MODE_MR16: \
+ switch( cpustate->r##N ) { \
+ case IX: WX16(cpustate, cpustate->ix.w.l,value,cpustate->ixbase); return; \
+ case IY: WX16(cpustate, cpustate->iy.w.l,value,cpustate->iybase); return; \
+ } \
+ WM16(cpustate, r16(cpustate, cpustate->r##N), value); return; \
+ case MODE_MR16D8: \
+ switch( cpustate->r##N ) { \
+ case IX: WX16(cpustate, (UINT16)(cpustate->ix.w.l + (INT8)cpustate->r##N##b),value,cpustate->ixbase); return; \
+ case IY: WX16(cpustate, (UINT16)(cpustate->iy.w.l + (INT8)cpustate->r##N##b),value,cpustate->iybase); return; \
+ } \
+ WM16(cpustate, (UINT16)(r16(cpustate, cpustate->r##N) + (INT8)cpustate->r##N##b), value); return; \
+ default: \
+ fatalerror("%04x: unimplemented Write%d_16 mode = %d\n",cpustate->pc.w.l,N,cpustate->mode##N); \
+ } \
+}
+
+READ_FN(1)
+READ_FN(2)
+WRITE_FN(1)
+WRITE_FN(2)
+
+INLINE int Test( t90_Regs *cpustate, UINT8 cond )
+{
+ int s,v;
+ switch ( cond )
+ {
+ case FLS: return 0;
+ case LT: s = F & SF; v = F & VF; return (s && !v) || (!s && v);
+ case LE: s = F & SF; v = F & VF; return (F & ZF) || (s && !v) || (!s && v);
+ case ULE: return (F & CF) || (F & ZF);
+ case OV: return F & VF;
+ case MI: return F & SF;
+ case Z: return F & ZF;
+ case CR: return F & CF;
+ case T: return 1;
+ case GE: s = F & SF; v = F & VF; return (s && v) || (!s && !v);
+ case GT: s = F & SF; v = F & VF; return !((F & ZF) || (s && !v) || (!s && v));
+ case UGT: return !(F & CF) && !(F & ZF);
+ case NOV: return !(F & VF);
+ case PL: return !(F & SF);
+ case NZ: return !(F & ZF);
+ case NC: return !(F & CF);
+ default:
+ fatalerror("%04x: unimplemented condition = %d\n",cpustate->pc.w.l,cond);
+ }
+ return 0;
+}
+
+INLINE void Push( t90_Regs *cpustate, e_r rr )
+{
+ cpustate->sp.w.l -= 2;
+ WM16( cpustate, cpustate->sp.w.l, r16(cpustate, rr) );
+}
+INLINE void Pop( t90_Regs *cpustate, e_r rr )
+{
+ w16( cpustate, rr, RM16( cpustate, cpustate->sp.w.l ) );
+ cpustate->sp.w.l += 2;
+}
+
+/*************************************************************************************************************
+
+Interrupts
+
+----------------------------------------------------------------------------------------------------------------
+Priority Type Interrupt Source Vector/8 Vector Address uDMA Address
+----------------------------------------------------------------------------------------------------------------
+1 Non Maskable SWI - 10 0010 -
+2 "" NMI - 18 0018 -
+3 "" INTWD Watch Dog - 20 0020 -
+4 Maskable INT0 External 0 05 28 0028 FF28
+5 "" INTT0 Timer 0 06 30 0030 FF30
+6 "" INTT1 Timer 1 07 38 0038 FF38
+7 "" INTAD A/D 08 40 0040 FF48
+"" "" INTT2 Timer 2 "" "" "" ""
+8 "" INTT3 Timer 3 09 48 0048 FF48
+9 "" INTT4 Timer 4 0A 50 0050 FF50
+10 "" INT1 External 1 0B 58 0058 FF58
+11 "" INTT5 Timer 5 0C 60 0060 FF60
+12 "" INT2 External 2 0D 68 0068 FF68
+13 "" INTRX End Serial Receive 0E 70 0070 FF70
+14 "" INTTX End Serial Transmit 0F 78 0078 FF78
+
+----------------------------------------------------------------------------------------------------------------
+Interrupt Terminal Mode How To Set
+----------------------------------------------------------------------------------------------------------------
+NMI - Falling Edge -
+INT0 P80 Level P8CR<EDGE> = 0
+ Rising Edge P8CR<EDGE> = 1
+INT1 P81 Rising Edge T4MOD<CAPM1,0> = 0,0 or 0,1 or 1,1
+ Falling Edge T4MOD<CAPM1,0> = 1,0
+INT2 P82 Rising Edge -
+
+*************************************************************************************************************/
+
+typedef enum { INTSWI = 0, INTNMI, INTWD, INT0, INTT0, INTT1, INTT2, INTT3, INTT4, INT1, INTT5, INT2, INTRX, INTTX, INTMAX } e_irq;
+DECLARE_ENUM_OPERATORS(e_irq)
+
+INLINE void leave_halt(t90_Regs *cpustate)
+{
+ if( cpustate->halt )
+ {
+ cpustate->halt = 0;
+ cpustate->pc.w.l++;
+ }
+}
+
+static void take_interrupt(t90_Regs *cpustate, e_irq irq)
+{
+ cpustate->irq_state &= ~(1 << irq);
+
+ leave_halt(cpustate);
+
+ Push( cpustate, PC );
+ Push( cpustate, AF );
+
+ F &= ~IF;
+
+ cpustate->pc.w.l = 0x10 + irq * 8;
+
+ cpustate->extra_cycles += 20*2;
+}
+
+static void check_interrupts(t90_Regs *cpustate)
+{
+ e_irq irq;
+
+ if (!(F & IF))
+ return;
+
+ for (irq = INT0; irq < INTMAX; irq++)
+ {
+ if ( cpustate->irq_state & cpustate->irq_mask & (1 << irq) )
+ {
+ take_interrupt( cpustate, irq );
+ return;
+ }
+ }
+}
+
+static void set_irq_line(t90_Regs *cpustate, int irq, int state)
+{
+ if ( ((cpustate->irq_state >> irq)&1) == state ) return;
+
+ if (state)
+ {
+ cpustate->irq_state |= 1 << irq;
+ check_interrupts(cpustate);
+ }
+ else
+ {
+ cpustate->irq_state &= ~(1 << irq);
+ }
+}
+
+INLINE void Cyc(t90_Regs *cpustate) { cpustate->icount -= cpustate->cyc_t; }
+INLINE void Cyc_f(t90_Regs *cpustate) { cpustate->icount -= cpustate->cyc_f; }
+
+static CPU_EXECUTE( t90 )
+{
+ t90_Regs *cpustate = get_safe_token(device);
+ UINT8 a8,b8;
+ UINT16 a16,b16;
+ unsigned a32;
+ PAIR tmp;
+
+ cpustate->icount -= cpustate->extra_cycles;
+ cpustate->extra_cycles = 0;
+
+ do
+ {
+ cpustate->prvpc.d = cpustate->pc.d;
+ debugger_instruction_hook(device, cpustate->pc.d);
+
+ check_interrupts(cpustate);
+
+ cpustate->addr = cpustate->pc.d;
+ decode(cpustate);
+ cpustate->pc.d = cpustate->addr;
+
+ switch ( cpustate->op )
+ {
+ case NOP:
+ Cyc(cpustate);
+ break;
+
+ case EX:
+ a16 = Read1_16(cpustate);
+ Write1_16( cpustate, Read2_16(cpustate) );
+ Write2_16( cpustate, a16 );
+ Cyc(cpustate);
+ break;
+ case EXX:
+ tmp = cpustate->bc; cpustate->bc = cpustate->bc2; cpustate->bc2 = tmp;
+ tmp = cpustate->de; cpustate->de = cpustate->de2; cpustate->de2 = tmp;
+ tmp = cpustate->hl; cpustate->hl = cpustate->hl2; cpustate->hl2 = tmp;
+ Cyc(cpustate);
+ break;
+
+ case LD:
+ Write1_8( cpustate, Read2_8(cpustate) );
+ Cyc(cpustate);
+ break;
+ case LDW:
+ case LD | OP_16:
+ Write1_16( cpustate, Read2_16(cpustate) );
+ Cyc(cpustate);
+ break;
+
+// case LDA:
+// Cyc(cpustate);
+// break;
+
+ case LDI:
+#define _LDI \
+ WM8( cpustate, cpustate->de.w.l, RM8(cpustate, cpustate->hl.w.l) ); \
+ cpustate->de.w.l++; \
+ cpustate->hl.w.l++; \
+ cpustate->bc.w.l--; \
+ F &= SF | ZF | IF | XCF | CF; \
+ if ( cpustate->bc.w.l ) F |= VF;
+
+ _LDI
+ Cyc(cpustate);
+ break;
+ case LDIR:
+ _LDI
+ if ( cpustate->bc.w.l )
+ {
+ cpustate->pc.w.l -= 2;
+ Cyc(cpustate);
+ }
+ else Cyc_f(cpustate);
+ break;
+
+ case LDD:
+#define _LDD \
+ WM8( cpustate, cpustate->de.w.l, RM8(cpustate, cpustate->hl.w.l) ); \
+ cpustate->de.w.l--; \
+ cpustate->hl.w.l--; \
+ cpustate->bc.w.l--; \
+ F &= SF | ZF | IF | XCF | CF; \
+ if ( cpustate->bc.w.l ) F |= VF;
+
+ _LDD
+ Cyc(cpustate);
+ break;
+ case LDDR:
+ _LDD
+ if ( cpustate->bc.w.l )
+ {
+ cpustate->pc.w.l -= 2;
+ Cyc(cpustate);
+ }
+ else Cyc_f(cpustate);
+ break;
+
+
+// case CPD:
+// Cyc(cpustate);
+// break;
+// case CPDR:
+// Cyc(cpustate);
+// break;
+ case CPI:
+ a8 = RM8(cpustate, cpustate->hl.w.l);
+ b8 = cpustate->af.b.h - a8;
+ cpustate->hl.w.l++;
+ cpustate->bc.w.l--;
+ F = (F & (IF | CF)) | SZ[b8] | ((cpustate->af.b.h^a8^b8)&HF) | NF;
+ if ( cpustate->bc.w.l ) F |= VF;
+ Cyc(cpustate);
+ break;
+ case CPIR:
+ a8 = RM8(cpustate, cpustate->hl.w.l);
+ b8 = cpustate->af.b.h - a8;
+ cpustate->hl.w.l++;
+ cpustate->bc.w.l--;
+ F = (F & (IF | CF)) | SZ[b8] | ((cpustate->af.b.h^a8^b8)&HF) | NF;
+ if ( cpustate->bc.w.l )
+ {
+ F |= VF;
+ cpustate->pc.w.l -= 2;
+ Cyc(cpustate);
+ }
+ else Cyc_f(cpustate);
+ break;
+
+ case PUSH:
+ Push( cpustate, cpustate->r1 );
+ Cyc(cpustate);
+ break;
+ case POP:
+ Pop( cpustate, cpustate->r1 );
+ Cyc(cpustate);
+ break;
+
+ case JP:
+ if ( Test( cpustate, Read1_8(cpustate) ) )
+ {
+ cpustate->pc.w.l = Read2_16(cpustate);
+ Cyc(cpustate);
+ }
+ else Cyc_f(cpustate);
+ break;
+ case JR:
+ if ( Test( cpustate, Read1_8(cpustate) ) )
+ {
+ cpustate->pc.w.l += /*2 +*/ (INT8)Read2_8(cpustate);
+ Cyc(cpustate);
+ }
+ else Cyc_f(cpustate);
+ break;
+ case JR | OP_16:
+ if ( Test( cpustate, Read1_8(cpustate) ) )
+ {
+ cpustate->pc.w.l += /*2 +*/ Read2_16(cpustate);
+ Cyc(cpustate);
+ }
+ else Cyc_f(cpustate);
+ break;
+
+
+ case CALL:
+ if ( Test( cpustate, Read1_8(cpustate) ) )
+ {
+ Push( cpustate, PC );
+ cpustate->pc.w.l = Read2_16(cpustate);
+ Cyc(cpustate);
+ }
+ else Cyc_f(cpustate);
+ break;
+ case CALLR:
+ Push( cpustate, PC );
+ cpustate->pc.w.l += /*2 +*/ Read1_16(cpustate);
+ Cyc(cpustate);
+ break;
+
+ case RET:
+ if ( Test( cpustate, Read1_8(cpustate) ) )
+ {
+ Pop( cpustate, PC );
+ Cyc(cpustate);
+ }
+ else Cyc_f(cpustate);
+ break;
+ case RETI:
+ Pop( cpustate, AF );
+ Pop( cpustate, PC );
+ Cyc(cpustate);
+ break;
+
+// case HALT:
+// Cyc(cpustate);
+// break;
+ case DI:
+ cpustate->after_EI = 0;
+ F &= ~IF;
+ Cyc(cpustate);
+ break;
+ case EI:
+ cpustate->after_EI = !(F & IF);
+ Cyc(cpustate);
+ break;
+
+ case SWI:
+ Cyc(cpustate);
+ take_interrupt( cpustate, INTSWI );
+ break;
+
+ case DAA:
+ {
+ UINT8 cf, nf, hf, lo, hi, diff;
+ cf = F & CF;
+ nf = F & NF;
+ hf = F & HF;
+ lo = cpustate->af.b.h & 15;
+ hi = cpustate->af.b.h / 16;
+
+ if (cf)
+ {
+ diff = (lo <= 9 && !hf) ? 0x60 : 0x66;
+ }
+ else
+ {
+ if (lo >= 10)
+ {
+ diff = hi <= 8 ? 0x06 : 0x66;
+ }
+ else
+ {
+ if (hi >= 10)
+ {
+ diff = hf ? 0x66 : 0x60;
+ }
+ else
+ {
+ diff = hf ? 0x06 : 0x00;
+ }
+ }
+ }
+ if (nf) cpustate->af.b.h -= diff;
+ else cpustate->af.b.h += diff;
+
+ F = SZP[A] | (F & (IF | NF));
+ if (cf || (lo <= 9 ? hi >= 10 : hi >= 9)) F |= XCF | CF;
+ if (nf ? hf && lo <= 5 : lo >= 10) F |= HF;
+ }
+ Cyc(cpustate);
+ break;
+
+
+ case CPL:
+ cpustate->af.b.h ^= 0xff;
+ F |= HF | NF;
+ Cyc(cpustate);
+ break;
+ case NEG:
+ a8 = 0;
+ b8 = cpustate->af.b.h;
+ a32 = a8 - b8;
+ F = (F & IF) | SZ[(UINT8)a32] | NF;
+ if (a32 & 0x100) F |= CF | XCF; //X?
+ if ((a8 ^ a32 ^ b8) & 0x10) F |= HF;
+ if ((b8 ^ a8) & (a8 ^ a32) & 0x80) F |= VF;
+ cpustate->af.b.h = a32;
+ Cyc(cpustate);
+ break;
+
+ case LDAR:
+ cpustate->hl.w.l = cpustate->pc.w.l + /*2 +*/ Read2_16(cpustate);
+ Cyc(cpustate);
+ break;
+
+ case RCF:
+ F &= SF | ZF | IF | VF;
+ Cyc(cpustate);
+ break;
+ case SCF:
+ F = (F & (SF | ZF | IF | VF)) | XCF | CF;
+ Cyc(cpustate);
+ break;
+ case CCF:
+ F = (F & (SF | ZF | IF | VF)) | ((F & CF)?HF:(XCF | CF));
+ Cyc(cpustate);
+ break;
+
+// case TSET:
+// Cyc(cpustate);
+// break;
+ case BIT:
+ F = (F & (IF | CF)) | HF | SZ_BIT[ Read2_8(cpustate) & (1 << Read1_8(cpustate)) ];
+ Cyc(cpustate);
+ break;
+ case SET:
+ Write2_8( cpustate, Read2_8(cpustate) | (1 << Read1_8(cpustate)) );
+ Cyc(cpustate);
+ break;
+ case RES:
+ Write2_8( cpustate, Read2_8(cpustate) & (~(1 << Read1_8(cpustate))) );
+ Cyc(cpustate);
+ break;
+
+ case INC:
+ a8 = Read1_8(cpustate) + 1;
+ Write1_8( cpustate, a8 );
+ F = (F & (IF | CF)) | SZHV_inc[a8];
+ if (a8 == 0) F |= XCF;
+ Cyc(cpustate);
+ break;
+ case INCX:
+ if ( F & XCF )
+ {
+ a8 = Read1_8(cpustate) + 1;
+ Write1_8( cpustate, a8 );
+ F = (F & (IF | CF)) | SZHV_inc[a8];
+ if (a8 == 0) F |= XCF;
+ Cyc(cpustate);
+ }
+ else Cyc_f(cpustate);
+ break;
+ case INC | OP_16:
+ a16 = Read1_16(cpustate) + 1;
+ Write1_16( cpustate, a16 );
+ if (a16 == 0) F |= XCF;
+ else F &= ~XCF;
+ Cyc(cpustate);
+ break;
+ case INCW:
+ a16 = Read1_16(cpustate);
+ a32 = a16 + 1;
+ Write1_16( cpustate, a32 );
+ F &= IF | CF;
+ if ((UINT16)a32 == 0) F |= ZF | XCF;
+ if (a32 & 0x8000) F |= SF;
+ if ((a16 ^ 0x8000) & a32 & 0x8000) F |= VF;
+ if ((a16 ^ a32 ^ 1) & 0x1000) F |= HF; //??
+ Cyc(cpustate);
+ break;
+
+
+ case DEC:
+ a8 = Read1_8(cpustate) - 1;
+ Write1_8( cpustate, a8 );
+ F = (F & (IF | CF)) | SZHV_dec[a8];
+ if (a8 == 0) F |= XCF;
+ Cyc(cpustate);
+ break;
+ case DECX:
+ if ( F & XCF )
+ {
+ a8 = Read1_8(cpustate) - 1;
+ Write1_8( cpustate, a8 );
+ F = (F & (IF | CF)) | SZHV_dec[a8];
+ if (a8 == 0) F |= XCF;
+ Cyc(cpustate);
+ }
+ else Cyc_f(cpustate);
+ break;
+ case DEC | OP_16:
+ a16 = Read1_16(cpustate) - 1;
+ Write1_16( cpustate, a16 );
+ if (a16 == 0) F |= XCF;
+ else F &= ~XCF;
+ Cyc(cpustate);
+ break;
+ case DECW:
+ a16 = Read1_16(cpustate);
+ a32 = a16 - 1;
+ Write1_16( cpustate, a32 );
+ F = (F & (IF | CF)) | NF;
+ if ((UINT16)a32 == 0) F |= ZF | XCF;
+ if (a32 & 0x8000) F |= SF;
+ if (a16 == 0x8000) F |= VF;
+ if ((a16 ^ a32 ^ 1) & 0x1000) F |= HF; //??
+ Cyc(cpustate);
+ break;
+
+ case ADD:
+ case ADC:
+ a8 = Read1_8(cpustate);
+ b8 = Read2_8(cpustate);
+ a32 = a8 + b8;
+ if ( (cpustate->op == ADC) && (F & CF) ) a32 += 1;
+ Write1_8( cpustate, a32 );
+ F = (F & IF) | SZ[(UINT8)a32];
+ if (a32 & 0x100) F |= CF | XCF; //X?
+ if ((a8 ^ a32 ^ b8) & 0x10) F |= HF;
+ if ((b8 ^ a8 ^ 0x80) & (b8 ^ a32) & 0x80) F |= VF;
+ Cyc(cpustate);
+ break;
+ case ADD | OP_16:
+ case ADC | OP_16:
+ a16 = Read1_16(cpustate);
+ b16 = Read2_16(cpustate);
+ a32 = a16 + b16;
+ if ( (cpustate->op == (ADC | OP_16)) && (F & CF) ) a32 += 1;
+ Write1_16( cpustate, a32 );
+ if ( (cpustate->op == (ADD | OP_16)) && cpustate->mode2 == MODE_R16 )
+ {
+ F &= SF | ZF | IF | VF;
+ }
+ else
+ {
+ F &= IF;
+ if ((UINT16)a32 == 0) F |= ZF;
+ if (a32 & 0x8000) F |= SF;
+ if ((b16 ^ a16 ^ 0x8000) & (b16 ^ a32) & 0x8000) F |= VF;
+ }
+ if (a32 & 0x10000) F |= CF | XCF; //X?
+ if ((a16 ^ a32 ^ b16) & 0x1000) F |= HF; //??
+ Cyc(cpustate);
+ break;
+
+ case CP:
+ case SUB:
+ case SBC:
+ a8 = Read1_8(cpustate);
+ b8 = Read2_8(cpustate);
+ a32 = a8 - b8;
+ if ( (cpustate->op == SBC) && (F & CF) ) a32 -= 1;
+ F = (F & IF) | SZ[(UINT8)a32] | NF;
+ if (a32 & 0x100) F |= CF | XCF; //X?
+ if ((a8 ^ a32 ^ b8) & 0x10) F |= HF;
+ if ((b8 ^ a8) & (a8 ^ a32) & 0x80) F |= VF;
+ if (cpustate->op != CP)
+ Write1_8( cpustate, a32 );
+ Cyc(cpustate);
+ break;
+ case CP | OP_16:
+ case SUB | OP_16:
+ case SBC | OP_16:
+ a16 = Read1_16(cpustate);
+ b16 = Read2_16(cpustate);
+ a32 = a16 - b16;
+ if ( (cpustate->op == (SBC | OP_16)) && (F & CF) ) a32 -= 1;
+ F = (F & IF) | NF;
+ if ((UINT16)a32 == 0) F |= ZF;
+ if (a32 & 0x8000) F |= SF;
+ if (a32 & 0x10000) F |= CF | XCF; //X?
+ if ((a16 ^ a32 ^ b16) & 0x1000) F |= HF; //??
+ if ((b16 ^ a16) & (a16 ^ a32) & 0x8000) F |= VF;
+ if (cpustate->op != (CP | OP_16))
+ Write1_16( cpustate, a32 );
+ Cyc(cpustate);
+ break;
+
+ case AND:
+ a8 = Read1_8(cpustate) & Read2_8(cpustate);
+ Write1_8( cpustate, a8 );
+ F = (F & IF) | SZP[a8] | HF;
+ Cyc(cpustate);
+ break;
+ case AND | OP_16:
+ a16 = Read1_16(cpustate) & Read2_16(cpustate);
+ Write1_16( cpustate, a16 );
+ F = (F & IF) | HF;
+ if (a16 == 0) F |= ZF;
+ if (a16 & 0x8000) F |= SF;
+ Cyc(cpustate);
+ break;
+ case XOR:
+ a8 = Read1_8(cpustate) ^ Read2_8(cpustate);
+ Write1_8( cpustate, a8 );
+ F = (F & IF) | SZP[a8];
+ Cyc(cpustate);
+ break;
+ case XOR | OP_16:
+ a16 = Read1_16(cpustate) ^ Read2_16(cpustate);
+ Write1_16( cpustate, a16 );
+ F &= IF;
+ if (a16 == 0) F |= ZF;
+ if (a16 & 0x8000) F |= SF;
+ Cyc(cpustate);
+ break;
+ case OR:
+ a8 = Read1_8(cpustate) | Read2_8(cpustate);
+ Write1_8( cpustate, a8 );
+ F = (F & IF) | SZP[a8];
+ Cyc(cpustate);
+ break;
+ case OR | OP_16:
+ a16 = Read1_16(cpustate) | Read2_16(cpustate);
+ Write1_16( cpustate, a16 );
+ F &= IF;
+ if (a16 == 0) F |= ZF;
+ if (a16 & 0x8000) F |= SF;
+ Cyc(cpustate);
+ break;
+
+ case RLC:
+ a8 = Read1_8(cpustate);
+ a8 = (a8 << 1) | (a8 >> 7);
+ Write1_8( cpustate, a8 );
+ if ( cpustate->mode1 == MODE_R8 && cpustate->r1 == A ) F &= SF | ZF | IF | PF;
+ else F = (F & IF) | SZP[a8];
+ if (a8 & 0x01) F |= CF | XCF; // X?
+ Cyc(cpustate);
+ break;
+ case RRC:
+ a8 = Read1_8(cpustate);
+ a8 = (a8 >> 1) | (a8 << 7);
+ Write1_8( cpustate, a8 );
+ if ( cpustate->mode1 == MODE_R8 && cpustate->r1 == A ) F &= SF | ZF | IF | PF;
+ else F = (F & IF) | SZP[a8];
+ if (a8 & 0x80) F |= CF | XCF; // X?
+ Cyc(cpustate);
+ break;
+ case RL:
+ a8 = Read1_8(cpustate);
+ b8 = a8 & 0x80;
+ a8 <<= 1;
+ if (F & CF) a8 |= 0x01;
+ Write1_8( cpustate, a8 );
+ if ( cpustate->mode1 == MODE_R8 && cpustate->r1 == A ) F &= SF | ZF | IF | PF;
+ else F = (F & IF) | SZP[a8];
+ if (b8) F |= CF | XCF; // X?
+ Cyc(cpustate);
+ break;
+ case RR:
+ a8 = Read1_8(cpustate);
+ b8 = a8 & 0x01;
+ a8 >>= 1;
+ if (F & CF) a8 |= 0x80;
+ Write1_8( cpustate, a8 );
+ if ( cpustate->mode1 == MODE_R8 && cpustate->r1 == A ) F &= SF | ZF | IF | PF;
+ else F = (F & IF) | SZP[a8];
+ if (b8) F |= CF | XCF; // X?
+ Cyc(cpustate);
+ break;
+
+ case SLA:
+ case SLL:
+ a8 = Read1_8(cpustate);
+ b8 = a8 & 0x80;
+ a8 <<= 1;
+ Write1_8( cpustate, a8 );
+ if ( cpustate->mode1 == MODE_R8 && cpustate->r1 == A ) F &= SF | ZF | IF | PF;
+ else F = (F & IF) | SZP[a8];
+ if (b8) F |= CF | XCF; // X?
+ Cyc(cpustate);
+ break;
+ case SRA:
+ a8 = Read1_8(cpustate);
+ b8 = a8 & 0x01;
+ a8 = (a8 & 0x80) | (a8 >> 1);
+ Write1_8( cpustate, a8 );
+ if ( cpustate->mode1 == MODE_R8 && cpustate->r1 == A ) F &= SF | ZF | IF | PF;
+ else F = (F & IF) | SZP[a8];
+ if (b8) F |= CF | XCF; // X?
+ Cyc(cpustate);
+ break;
+ case SRL:
+ a8 = Read1_8(cpustate);
+ b8 = a8 & 0x01;
+ a8 >>= 1;
+ Write1_8( cpustate, a8 );
+ if ( cpustate->mode1 == MODE_R8 && cpustate->r1 == A ) F &= SF | ZF | IF | PF;
+ else F = (F & IF) | SZP[a8];
+ if (b8) F |= CF | XCF; // X?
+ Cyc(cpustate);
+ break;
+ case RLD:
+ a8 = cpustate->af.b.h;
+ b8 = Read1_8(cpustate);
+ Write1_8( cpustate, (b8 << 4) | (a8 & 0x0f) );
+ a8 = (a8 & 0xf0) | (b8 >> 4);
+ F = (F & (IF | CF)) | SZP[a8];
+ cpustate->af.b.h = a8;
+ Cyc(cpustate);
+ break;
+ case RRD:
+ a8 = cpustate->af.b.h;
+ b8 = Read1_8(cpustate);
+ Write1_8( cpustate, (b8 >> 4) | (a8 << 4) );
+ a8 = (a8 & 0xf0) | (b8 & 0x0f);
+ F = (F & (IF | CF)) | SZP[a8];
+ cpustate->af.b.h = a8;
+ Cyc(cpustate);
+ break;
+
+ case DJNZ:
+ if ( --cpustate->bc.b.h )
+ {
+ cpustate->pc.w.l += /*2 +*/ (INT8)Read1_8(cpustate);
+ Cyc(cpustate);
+ }
+ else Cyc_f(cpustate);
+ break;
+ case DJNZ | OP_16:
+ if ( --cpustate->bc.w.l )
+ {
+ cpustate->pc.w.l += /*2 +*/ (INT8)Read2_8(cpustate);
+ Cyc(cpustate);
+ }
+ else Cyc_f(cpustate);
+ break;
+
+ case MUL:
+ cpustate->hl.w.l = (UINT16)cpustate->hl.b.l * (UINT16)Read2_8(cpustate);
+ Cyc(cpustate);
+ break;
+ case DIV:
+ a16 = cpustate->hl.w.l;
+ b16 = (UINT16)Read2_8(cpustate);
+ if (b16 == 0)
+ {
+ F |= VF;
+ cpustate->hl.w.l = (a16 << 8) | ((a16 >> 8) ^ 0xff);
+ }
+ else
+ {
+ cpustate->hl.b.h = a16 % b16;
+ a16 /= b16;
+ if (a16 > 0xff) F |= VF;
+ else F &= ~VF;
+ cpustate->hl.b.l = a16;
+ }
+ Cyc(cpustate);
+ break;
+
+ default:
+ fatalerror("%04x: unimplemented opcode, op=%02x\n",cpu_get_pc(device),cpustate->op);
+ }
+
+ if ( cpustate->op != EI )
+ if (cpustate->after_EI)
+ {
+ F |= IF;
+ cpustate->after_EI = 0;
+ }
+
+ } while( cpustate->icount > 0 );
+
+ cpustate->icount -= cpustate->extra_cycles;
+ cpustate->extra_cycles = 0;
+}
+
+static CPU_RESET( t90 )
+{
+ t90_Regs *cpustate = get_safe_token(device);
+ cpustate->irq_state = 0;
+ cpustate->irq_mask = 0;
+ cpustate->pc.d = 0x0000;
+ F &= ~IF;
+/*
+ P0/D0-D7 P1/A0-A7 P2/A8-A15 P6 P7 = INPUT
+ P35/~RD P36/~WR CLK = 1 (ALWAYS OUTPUTS)
+ P4/A16-A19 P83 = 0
+ dedicated input ports and registers remain unchanged,
+ but PC IFF BX BY = 0, A undefined
+*/
+}
+
+static CPU_EXIT( t90 )
+{
+}
+
+static CPU_BURN( t90 )
+{
+ t90_Regs *cpustate = get_safe_token(device);
+ cpustate->icount -= 4 * ((cycles + 3) / 4);
+}
+
+
+/*************************************************************************************************************
+
+
+----------------------------------------------------------------------------------------------------------------
+FFC0 P0 R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+7-0 P07-P00 R W IN I/O Port 0
+
+----------------------------------------------------------------------------------------------------------------
+FFC1 P1 R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+7-0 P17-P10 R W IN I/O Port 1
+
+----------------------------------------------------------------------------------------------------------------
+FFC2 P01CR/ R/W Reset Description * Prohibit Read-Modify-Write *
+ IRFL
+----------------------------------------------------------------------------------------------------------------
+ 7 - - 0 -
+ 6 IRF0 R 0 INT0 interrupt request (1 = asserted)
+ 5 IRFT0 R 0 INTT0 ""
+ 4 IRFT1 R 0 INTT1 ""
+ 3 - - 0 -
+ 2 EXT W 0 P1/P2 control: 0 = Port 1 = Address Bus
+ 1 P1CR W 0 P1 control: 0 = IN 1 = OUT |
+ 0 P0CR W 0 P0 control: 0 = IN 1 = OUT |
+ | |
+ Port 0 also functions as data bus (D0-D7),so P1: regardless of <P1CR>
+ P0CR is reset when external memory is accessed P2: only if P2CR is set to 1 (output)
+ TMP90C841A: always address bus
+
+----------------------------------------------------------------------------------------------------------------
+FFC3 IRFH R/W Reset Description * Prohibit Read-Modify-Write *
+----------------------------------------------------------------------------------------------------------------
+ 7 IRFT2 R W 0 INTT2 interrupt request (1 = asserted)
+ 6 IRFT3 R W 0 INTT3 ""
+ 5 IRFT4 R W 0 INTT4 ""
+ 4 IRF1 R W 0 INT1 ""
+ 3 IRFT5 R W 0 INTT5 ""
+ 2 IRF2 R W 0 INT2 ""
+ 1 IRFRX R W 0 INTRX ""
+ 0 IRFTX R W 0 INTTX ""
+ |__ Writing Vector/8 clears the request flip-flop for that interrupt
+
+----------------------------------------------------------------------------------------------------------------
+FFC4 P2 R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+7-0 P27-P20 R W IN I/O Port 2
+
+----------------------------------------------------------------------------------------------------------------
+FFC5 P2CR R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+7-0 P27C- W 0 Port 2 control: 0 = IN 1 = OUT
+ P20C
+
+----------------------------------------------------------------------------------------------------------------
+FFC6 P3 R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+ 7 P37 R IN P37 input
+ 6 P36 R W 1 ~WD
+ 5 P35 R W 1 ~RD
+ 4 P34 R IN P34 input
+ 3 P33 R W 1 TxD / P33 output
+ 2 P32 R W 1 TxD / P32 output
+ 1 P31 R IN RxD / P31 input
+ 0 P30 R IN RxD / P30 input
+
+----------------------------------------------------------------------------------------------------------------
+FFC7 P3CR R/W Reset Description * Prohibit Read-Modify-Write *
+----------------------------------------------------------------------------------------------------------------
+7-6 WAITC1-0R W 00 Wait control: 00 = 2state 01 = normal 10 = no wait 11 = reserved
+ 5 RDE R W 0 RD control: 0 = only external access 1 = always
+ 4 ODE R W 0 P33 control: 0 = CMOS 1 = Open Drain
+3-2 TXDC1-0 R W 00 P33-P32: 00 = OUT-OUT 01 = OUT-TxD 10 = TxD-OUT 11 = TxD-~RTS/SCLK
+1-0 RXDC1-0 R W 00 P31-P30: 00 = IN-IN 01 = IN-RxD 10 = RxD-IN 11 = not used
+
+----------------------------------------------------------------------------------------------------------------
+FFC8 P4 R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+7-4 -
+3-0 P43-P40 R W 0 I/O Port 4 bits 3-0 or address bus A16-A19
+
+----------------------------------------------------------------------------------------------------------------
+FFC9 P4CR R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+7-4 -
+3-0 P43C- W 0 Port 4 control: 0 = OUT 1 = Address Output
+ P40C
+
+----------------------------------------------------------------------------------------------------------------
+FFCA P5 R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+7 - R 0 Test bit, must be set to 0
+6 - R 0
+5-0 P55-P50 R 0 I/O Port 5 bits 5-0 / AN5-AN0 analog inputs
+
+----------------------------------------------------------------------------------------------------------------
+FFCB SMMOD R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+ 7 - R W -
+ 6 SM7M0 R W 0 Motor Step: 0 = Full 1 = Half
+ 5 P70C1 R W 0 Port 7 control: 0 = IN-OUT 0 = IN-OUT,TO3 1 = IN / M1 1 = Timer 4
+ 4 P70C0 R W 0 0 1 0 Timer 2,3 1
+ 3 - R W -
+ 2 SM6M0 R W 0 Motor Step: 0 = Full 1 = Half
+ 1 P60C1 R W 0 Port 6 control: 0 = IN-OUT 0 = IN-OUT,TO1 1 = IN / M0
+ 0 P60C0 R W 0 0 1 X Timer 0,1
+
+----------------------------------------------------------------------------------------------------------------
+FFCC P6 R/W Reset Description * Read-Modify-Write not available in Stepping Motor control *
+----------------------------------------------------------------------------------------------------------------
+7-4 SA60-63 W Undef Stepping motor Port 0 (M0) Shifter alternate reg.
+3-0 P63-P60 R W IN Bits 3-0 of I/O Port 6 or Stepping motor Port 0 (M0)
+
+----------------------------------------------------------------------------------------------------------------
+FFCD P7 R/W Reset Description * Read-Modify-Write not available in Stepping Motor control *
+----------------------------------------------------------------------------------------------------------------
+7-4 SA70-73 W Undef Stepping motor Port 1 (M1) Shifter alternate reg.
+3-0 P73-P70 R W IN Bits 3-0 of I/O Port 7 or Stepping motor Port 1 (M1)
+
+----------------------------------------------------------------------------------------------------------------
+FFCE P67CR R/W Reset Description * Prohibit Read-Modify-Write *
+----------------------------------------------------------------------------------------------------------------
+7-4 P73-70C W 0 Port 7: 0 = IN 1 = OUT
+3-0 P63-60C W 0 Port 6: 0 = IN 1 = OUT
+
+----------------------------------------------------------------------------------------------------------------
+FFD0 P8 R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+7-4 -
+ 3 P83 R W 0 P83 / TIO3 / TIO4 output
+ 2 P82 R IN P82 + INT2 input
+ 1 P81 R IN P81 + INT1 input
+ 0 P80 R IN P80 + INT0 input
+
+----------------------------------------------------------------------------------------------------------------
+FFD1 P8CR R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+7-4 -
+ 3 P83OC W 0 P83 out control: 0 = P83 1 = TO3 / TO4
+ 2 ZCE2 W 0 INT2/TI5 control: 0 = ZCD disable 1 = ZCD enable
+ 1 ZCE1 W 0 INT1/TI4 control: 0 = ZCD disable 1 = ZCD enable
+ 0 EDGE W 0 INT0 control: 0 = Level 1 = Rising edge
+
+----------------------------------------------------------------------------------------------------------------
+FFD2 WDMOD R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+ 7 WDTE R W 1 1 = WDT Enable
+ 6 WDTP1 R W 0 WDT detection time: 0 = 2^14/fc 0 = 2^16/fc 1 = 2^18/fc 1 = 2^20/fc
+ 5 WDTP0 R W 0 0 1 0 1
+ 4 WARM R W 0 Warming up time: 0 = 2^14/fc 1 = 2^16/fc
+ 3 HALTM1 R W 0 Standby mode: 0 = RUN 0 = STOP 1 = IDLE1 1 = IDLE2
+ 2 HALTM0 R W 0 0 1 0 1
+ 1 EXF R Undef Invert each time EXX instruction is executed
+ 0 DRIVE R W 0 1 to drive pins in stop mode
+
+----------------------------------------------------------------------------------------------------------------
+FFD4 TREG0 R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+7-0 - W 0 Timer 0 match value
+
+----------------------------------------------------------------------------------------------------------------
+FFD5 TREG1 R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+7-0 - W 0 Timer 0 match value
+
+----------------------------------------------------------------------------------------------------------------
+FFD6 TREG2 R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+7-0 - W 0 Timer 0 match value
+
+----------------------------------------------------------------------------------------------------------------
+FFD7 TREG3 R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+7-0 - W 0 Timer 0 match value
+
+----------------------------------------------------------------------------------------------------------------
+FFD8 TCLK R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+7-6 T3CLK1-0R W 00 Timer 3 clock: 00 = Timer 2 01 = clock 10 = clock/16 11 = clock/256 <- Timer 2 overflow output in 16 bit mode
+5-4 T2CLK1-0R W 00 Timer 2 clock: 00 = - 01 = clock 10 = clock/16 11 = clock/256
+3-2 T1CLK1-0R W 00 Timer 1 clock: 00 = Timer 0 01 = clock 10 = clock/16 11 = clock/256 <- Timer 0 overflow output in 16 bit mode
+1-0 T0CLK1-0R W 00 Timer 0 clock: 00 = - 01 = clock 10 = clock/16 11 = clock/256
+
+----------------------------------------------------------------------------------------------------------------
+FFD9 TFFCR R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+7-6 TFF3C1-0 W - Timer 3 flip-flop: 00 = Clear 01 = Set 10 = Invert 11 = Don't care <- Always read as 11
+5 TFF3IE R W 0 Timer 3 Invert: 0 = Disable 1 = Enable
+4 TFF3IS R W 0 Timer 3 Invert: 0 = Timer 2 1 = Timer 3
+3-2 TFF1C1-0 W - Timer 1 Flip-Flop: 00 = Clear 01 = Set 10 = Invert 11 = Don't care <- Always read as 11
+1 TFF1IE R W 0 Timer 1 Invert: 0 = Disable 1 = Enable
+0 TFF1IS R W 0 Timer 1 Invert: 0 = Timer 0 1 = Timer 1
+
+----------------------------------------------------------------------------------------------------------------
+FFDA TMOD R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+7-6 T32M1-0 R W 00 Timers 2 & 3: 00 = 8b x 2 01 = 16b(T3+T2) 10 = 8b PPG(T3) 11 = 8b PWM (T3) + 8b (T2)
+5-4 PWM21-0 R W 00 Timer 3 PWM freq: 00 = - 01 = 63/fc 10 = 127/fc 11 = 255/fc
+3-2 T10M1-0 R W 00 Timers 1 & 0: 00 = 8b x 2 01 = 16b(T1+T0) 10 = 8b PPG(T1) 11 = 8b PWM (T1) + 8b (T0)
+1-0 PWM01-0 R W 00 Timer 1 PWM freq: 00 = - 01 = 63/fc 10 = 127/fc 11 = 255/fc
+
+----------------------------------------------------------------------------------------------------------------
+FFDB TRUN R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+7-6 BRATE1-0R W 00 Serial baud rate: 00 = 300/150 01 = 1200/600 10 = 4800/2400 11 = 19200/9600
+ 5 PRRUN R W 0 Prescaler control: 0 = Stop & Clear 1 = Run
+ 4 T4RUN R W 0 Timer 4 control: 0 = Stop & Clear 1 = Run
+3-0 T4RUN-0 R W 00 Timers 3-0 control: 0 = Stop & Clear 1 = Run
+
+----------------------------------------------------------------------------------------------------------------
+FFE6 INTEL R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+ 7 DET2 R W 0 INTT2/INTAD interrupt enable flag (1 = enable)
+ 6 DET3 R W 0 INTT3 ""
+ 5 DET4 R W 0 INTT4 ""
+ 4 DE1 R W 0 INT1 ""
+ 3 DET5 R W 0 INTT5 ""
+ 2 DE2 R W 0 INT2 ""
+ 1 DERX R W 0 INTRX ""
+ 0 DETX R W 0 INTTX ""
+
+----------------------------------------------------------------------------------------------------------------
+FFE7 INTEH R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+ 7 - R W 0 Write "0"
+ 6 DE0 R W 0 INT0 DMA enable flag (1 = enable)
+ 5 DET0 R W 0 INTT0 ""
+ 4 DET1 R W 0 INTT1 ""
+ 3 ADIS R W 0 INTT2/INTAD selection (1 = INTAD)
+ 2 IE0 R W 0 INT0 interrupt enable flag (1 = enable)
+ 1 IET0 R W 0 INTT0 ""
+ 0 IET1 R W 0 INTT1 ""
+
+----------------------------------------------------------------------------------------------------------------
+FFE8 DMAEH R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+ 7 DET2 R W 0 INTT2/INTAD DMA enable flag (1 = enable)
+ 6 DET3 R W 0 INTT3 ""
+ 5 DET4 R W 0 INTT4 ""
+ 4 DE1 R W 0 INT1 ""
+ 3 DET5 R W 0 INTT5 ""
+ 2 DE2 R W 0 INT2 ""
+ 1 DERX R W 0 INTRX ""
+ 0 DETX R W 0 INTTX ""
+
+----------------------------------------------------------------------------------------------------------------
+FFEC BX R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+ 7 - R 1
+ 6 - R 1
+ 5 - R 1
+ 4 - R 1
+ 3 BX3 R W 0 IX bank register bit 3
+ 2 BX2 R W 0 IX bank register bit 2
+ 1 BX1 R w 0 IX bank register bit 1
+ 0 BX0 R W 0 IX bank register bit 0
+
+----------------------------------------------------------------------------------------------------------------
+FFED BX R/W Reset Description
+----------------------------------------------------------------------------------------------------------------
+ 7 - R 1
+ 6 - R 1
+ 5 - R 1
+ 4 - R 1
+ 3 BY3 R W 0 IY bank register bit 3
+ 2 BY2 R W 0 IY bank register bit 2
+ 1 BY1 R w 0 IY bank register bit 1
+ 0 BY0 R W 0 IY bank register bit 0
+
+*************************************************************************************************************/
+
+static READ8_HANDLER( t90_internal_registers_r )
+{
+ t90_Regs *cpustate = get_safe_token(&space->device());
+
+ #define RIO cpustate->io->read_byte( T90_IOBASE+offset )
+
+ UINT8 data = cpustate->internal_registers[offset];
+ switch ( T90_IOBASE + offset )
+ {
+ case T90_P3: // 7,4,1,0
+ return (data & 0x6c) | (RIO & 0x93);
+
+ case T90_P4: // only output
+ return data & 0x0f;
+
+ case T90_P5:
+ return (RIO & 0x3f);
+
+ case T90_P6:
+ case T90_P7:
+ return (data & 0xf0) | (RIO & 0x0f);
+
+ case T90_P8: // 2,1,0
+ return (data & 0x08) | (RIO & 0x07);
+
+ case T90_BX:
+ case T90_BY:
+ return 0xf0 | data;
+ }
+ return data;
+}
+
+static void t90_start_timer(t90_Regs *cpustate, int i)
+{
+ int prescaler;
+ attotime period;
+
+ cpustate->timer_value[i] = 0;
+
+ switch((cpustate->internal_registers[ T90_TMOD - T90_IOBASE ] >> (i * 2)) & 0x03)
+ {
+ case 0:
+ // 8-bit mode
+ break;
+ case 1:
+ // 16-bit mode
+ if (i & 1)
+ {
+ logerror("%04X: CPU Timer %d clocked by Timer %d overflow signal\n", cpustate->pc.w.l, i,i-1);
+ return;
+ }
+ break;
+ case 2:
+ logerror("%04X: CPU Timer %d, unsupported PPG mode\n", cpustate->pc.w.l, i);
+ return;
+ case 3:
+ logerror("%04X: CPU Timer %d, unsupported PWM mode\n", cpustate->pc.w.l, i);
+ return;
+ }
+
+ switch((cpustate->internal_registers[ T90_TCLK - T90_IOBASE ] >> (i * 2)) & 0x03)
+ {
+ case 0: if (i & 1) logerror("%04X: CPU Timer %d clocked by Timer %d match signal\n", cpustate->pc.w.l, i,i-1);
+ else logerror("%04X: CPU Timer %d, unsupported TCLK = 0\n", cpustate->pc.w.l, i);
+ return;
+ case 2: prescaler = 16; break;
+ case 3: prescaler = 256; break;
+ default:
+ case 1: prescaler = 1; break;
+ }
+
+
+ period = cpustate->timer_period * prescaler;
+
+ cpustate->timer[i]->adjust(period, i, period);
+
+ logerror("%04X: CPU Timer %d started at %lf Hz\n", cpustate->pc.w.l, i, 1.0 / period.as_double());
+}
+
+static void t90_start_timer4(t90_Regs *cpustate)
+{
+ int prescaler;
+ attotime period;
+
+ cpustate->timer4_value = 0;
+
+ switch(cpustate->internal_registers[ T90_T4MOD - T90_IOBASE ] & 0x03)
+ {
+ case 1: prescaler = 1; break;
+ case 2: prescaler = 16; break;
+ default: logerror("%04X: CPU Timer 4, unsupported T4MOD = %d\n", cpustate->pc.w.l,cpustate->internal_registers[ T90_T4MOD - T90_IOBASE ] & 0x03);
+ return;
+ }
+
+ period = cpustate->timer_period * prescaler;
+
+ cpustate->timer[4]->adjust(period, 4, period);
+
+ logerror("%04X: CPU Timer 4 started at %lf Hz\n", cpustate->pc.w.l, 1.0 / period.as_double());
+}
+
+
+static void t90_stop_timer(t90_Regs *cpustate, int i)
+{
+ cpustate->timer[i]->adjust(attotime::never, i);
+ logerror("%04X: CPU Timer %d stopped\n", cpustate->pc.w.l, i);
+}
+
+static void t90_stop_timer4(t90_Regs *cpustate)
+{
+ t90_stop_timer(cpustate, 4);
+}
+
+static TIMER_CALLBACK( t90_timer_callback )
+{
+ t90_Regs *cpustate = (t90_Regs *)ptr;
+ int is16bit;
+ int i = param;
+
+ if ( (cpustate->internal_registers[ T90_TRUN - T90_IOBASE ] & (1 << i)) == 0 )
+ return;
+
+// logerror("CPU Timer %d fired! value = %d\n", i,(unsigned)cpustate->timer_value[i]);
+
+ cpustate->timer_value[i]++;
+
+ is16bit = ((cpustate->internal_registers[ T90_TMOD - T90_IOBASE ] >> (i/2 * 2 + 2)) & 0x03) == 1;
+
+ // Match
+
+ if ( cpustate->timer_value[i] == cpustate->internal_registers[ T90_TREG0+i - T90_IOBASE ] )
+ {
+// logerror("CPU Timer %d match\n", i);
+
+ if (is16bit)
+ {
+ if (i & 1)
+ {
+ if ( cpustate->timer_value[i-1] == cpustate->internal_registers[ T90_TREG0+i-1 - T90_IOBASE ] )
+ {
+ cpustate->timer_value[i] = 0;
+ cpustate->timer_value[i-1] = 0;
+
+ set_irq_line(cpustate, INTT0 + i, 1);
+ }
+ }
+ else
+ set_irq_line(cpustate, INTT0 + i, 1);
+ }
+ else
+ {
+ cpustate->timer_value[i] = 0;
+ set_irq_line(cpustate, INTT0 + i, 1);
+ }
+
+ switch (i)
+ {
+ case 0:
+ case 2:
+ if ( !is16bit )
+ if ( (cpustate->internal_registers[ T90_TCLK - T90_IOBASE ] & (0x03 << (i * 2 + 2))) == 0 ) // T0/T1 match signal clocks T1/T3
+ t90_timer_callback(machine, cpustate, i+1);
+ break;
+ }
+ }
+
+ // Overflow
+
+ if ( cpustate->timer_value[i] == 0 )
+ {
+// logerror("CPU Timer %d overflow\n", i);
+
+ switch (i)
+ {
+ case 0:
+ case 2:
+ if ( is16bit ) // T0/T1 overflow signal clocks T1/T3
+ t90_timer_callback(machine, cpustate, i+1);
+ break;
+ }
+ }
+}
+
+static TIMER_CALLBACK( t90_timer4_callback )
+{
+// logerror("CPU Timer 4 fired! value = %d\n", (unsigned)cpustate->timer_value[4]);
+
+ t90_Regs *cpustate = (t90_Regs *)ptr;
+ cpustate->timer4_value++;
+
+ // Match
+
+ if ( cpustate->timer4_value == (cpustate->internal_registers[ T90_TREG4L - T90_IOBASE ] + (cpustate->internal_registers[ T90_TREG4H - T90_IOBASE ] << 8)) )
+ {
+// logerror("CPU Timer 4 matches TREG4\n");
+ set_irq_line(cpustate, INTT4, 1);
+ }
+ if ( cpustate->timer4_value == (cpustate->internal_registers[ T90_TREG5L - T90_IOBASE ] + (cpustate->internal_registers[ T90_TREG5H - T90_IOBASE ] << 8)) )
+ {
+// logerror("CPU Timer 4 matches TREG5\n");
+ set_irq_line(cpustate, INTT5, 1);
+ if (cpustate->internal_registers[ T90_T4MOD - T90_IOBASE ] & 0x04)
+ cpustate->timer4_value = 0;
+ }
+
+ // Overflow
+
+ if ( cpustate->timer_value == 0 )
+ {
+// logerror("CPU Timer 4 overflow\n");
+ }
+}
+
+static WRITE8_HANDLER( t90_internal_registers_w )
+{
+ #define WIO cpustate->io->write_byte( T90_IOBASE+offset, data )
+
+ t90_Regs *cpustate = get_safe_token(&space->device());
+ UINT8 out_mask;
+ UINT8 old = cpustate->internal_registers[offset];
+ switch ( T90_IOBASE + offset )
+ {
+ case T90_TRUN:
+ {
+ int i;
+ // Timers 0-3
+ for (i = 0; i < 4; i++)
+ {
+ if ( (old ^ data) & (0x20 | (1 << i)) ) // if timer bit or prescaler bit changed
+ {
+ if ( data == (0x20 | (1 << i)) ) t90_start_timer(cpustate, i);
+ else t90_stop_timer(cpustate, i);
+ }
+ }
+ // Timer 4
+ if ( (old ^ data) & (0x20 | 0x10) )
+ {
+ if ( data == (0x20 | 0x10) ) t90_start_timer4(cpustate);
+ else t90_stop_timer4(cpustate);
+ }
+ break;
+ }
+
+ case T90_INTEL:
+ cpustate->irq_mask &= ~( (1 << INTT2 ) |
+ (1 << INTT3 ) |
+ (1 << INTT4 ) |
+ (1 << INT1 ) |
+ (1 << INTT5 ) |
+ (1 << INT2 ) |
+ (1 << INTRX ) |
+ (1 << INTTX ) );
+
+ cpustate->irq_mask |= ((data & 0x80) ? (1 << INTT2 ) : 0) |
+ ((data & 0x40) ? (1 << INTT3 ) : 0) |
+ ((data & 0x20) ? (1 << INTT4 ) : 0) |
+ ((data & 0x10) ? (1 << INT1 ) : 0) |
+ ((data & 0x08) ? (1 << INTT5 ) : 0) |
+ ((data & 0x04) ? (1 << INT2 ) : 0) |
+ ((data & 0x02) ? (1 << INTRX ) : 0) |
+ ((data & 0x01) ? (1 << INTTX ) : 0) ;
+ break;
+
+ case T90_INTEH:
+ cpustate->irq_mask &= ~( (1 << INT0 ) |
+ (1 << INTT0) |
+ (1 << INTT1) );
+
+ cpustate->irq_mask |= ((data & 0x04) ? (1 << INT0 ) : 0) |
+ ((data & 0x02) ? (1 << INTT0) : 0) |
+ ((data & 0x01) ? (1 << INTT1) : 0) ;
+ break;
+
+ case T90_P3:
+ data &= 0x6c;
+ WIO;
+ break;
+
+ case T90_P4:
+ data &= 0x0f;
+ out_mask = (~cpustate->internal_registers[ T90_P4CR - T90_IOBASE ]) & 0x0f;
+ if (out_mask)
+ {
+ data &= out_mask;
+ WIO;
+ }
+ break;
+
+ case T90_P6:
+ out_mask = cpustate->internal_registers[ T90_P67CR - T90_IOBASE ] & 0x0f;
+ switch (cpustate->internal_registers[ T90_SMMOD - T90_IOBASE ] & 0x03)
+ {
+ case 1:
+ data &= ~0x01;
+ // add TO1 here
+ break;
+ case 2:
+ case 3:
+ data &= ~0x0f;
+ // add M0 here
+ break;
+ }
+
+ if (out_mask)
+ {
+ data &= out_mask;
+ WIO;
+ }
+ break;
+
+ case T90_P7:
+ out_mask = (cpustate->internal_registers[ T90_P67CR - T90_IOBASE ] & 0xf0) >> 4;
+ switch ((cpustate->internal_registers[ T90_SMMOD - T90_IOBASE ]>>4) & 0x03)
+ {
+ case 1:
+ data &= ~0x01;
+ // add TO3 here
+ break;
+ case 2:
+ case 3:
+ data &= ~0x0f;
+ // add M1 here
+ break;
+ }
+
+ if (out_mask)
+ {
+ data &= out_mask;
+ WIO;
+ }
+ break;
+
+ case T90_P8:
+ data &= 0x0f;
+ out_mask = (~cpustate->internal_registers[ T90_P8CR - T90_IOBASE ]) & 0x08;
+ if (out_mask)
+ {
+ data &= out_mask;
+ WIO;
+ }
+ break;
+
+ case T90_BX:
+ cpustate->ixbase = (data & 0xf) << 16;
+ break;
+ case T90_BY:
+ cpustate->iybase = (data & 0xf) << 16;
+ break;
+ }
+ cpustate->internal_registers[offset] = data;
+}
+
+static void state_register( legacy_cpu_device *device )
+{
+ t90_Regs *cpustate = get_safe_token(device);
+
+ device->save_item(NAME(cpustate->prvpc.w.l));
+ 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->ix.w.l));
+ device->save_item(NAME(cpustate->iy.w.l));
+ device->save_item(NAME(cpustate->af2.w.l));
+ device->save_item(NAME(cpustate->bc2.w.l));
+ device->save_item(NAME(cpustate->de2.w.l));
+ device->save_item(NAME(cpustate->hl2.w.l));
+ device->save_item(NAME(cpustate->halt));
+ device->save_item(NAME(cpustate->after_EI));
+ device->save_item(NAME(cpustate->irq_state));
+ device->save_item(NAME(cpustate->irq_mask));
+ device->save_item(NAME(cpustate->icount));
+ device->save_item(NAME(cpustate->extra_cycles));
+
+ device->save_item(NAME(cpustate->internal_registers));
+ device->save_item(NAME(cpustate->ixbase));
+ device->save_item(NAME(cpustate->iybase));
+
+ device->save_item(NAME(cpustate->timer_value));
+ device->save_item(NAME(cpustate->timer4_value));
+
+ // Work registers
+ device->save_item(NAME(cpustate->op));
+ device->save_item(NAME(cpustate->mode1));
+ device->save_item(NAME(cpustate->r1));
+ device->save_item(NAME(cpustate->r1b));
+ device->save_item(NAME(cpustate->mode2));
+ device->save_item(NAME(cpustate->r2));
+ device->save_item(NAME(cpustate->r2b));
+
+ device->save_item(NAME(cpustate->cyc_t));
+ device->save_item(NAME(cpustate->cyc_f));
+ device->save_item(NAME(cpustate->addr));
+}
+
+
+static CPU_INIT( t90 )
+{
+ t90_Regs *cpustate = get_safe_token(device);
+ int i, p;
+
+ state_register(device);
+
+ for (i = 0; i < 256; i++)
+ {
+ p = 0;
+ if( i&0x01 ) ++p;
+ if( i&0x02 ) ++p;
+ if( i&0x04 ) ++p;
+ if( i&0x08 ) ++p;
+ if( i&0x10 ) ++p;
+ if( i&0x20 ) ++p;
+ if( i&0x40 ) ++p;
+ if( i&0x80 ) ++p;
+ SZ[i] = i ? i & SF : ZF;
+// SZ[i] |= (i & (YF | XF)); /* undocumented flag bits 5+3 */
+ SZ_BIT[i] = i ? i & SF : ZF | PF;
+// SZ_BIT[i] |= (i & (YF | XF)); /* undocumented flag bits 5+3 */
+ SZP[i] = SZ[i] | ((p & 1) ? 0 : PF);
+ SZHV_inc[i] = SZ[i];
+ if( i == 0x80 ) SZHV_inc[i] |= VF;
+ if( (i & 0x0f) == 0x00 ) SZHV_inc[i] |= HF;
+ SZHV_dec[i] = SZ[i] | NF;
+ if( i == 0x7f ) SZHV_dec[i] |= VF;
+ if( (i & 0x0f) == 0x0f ) SZHV_dec[i] |= HF;
+ }
+
+ memset(cpustate, 0, sizeof(t90_Regs));
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->io = device->space(AS_IO);
+
+ cpustate->timer_period = attotime::from_hz(device->unscaled_clock()) * 8;
+
+ // Reset registers to their initial values
+
+// IX = IY = 0xffff;
+// F = ZF;
+
+ // Timers
+
+ for (i = 0; i < 4; i++)
+ cpustate->timer[i] = device->machine().scheduler().timer_alloc(FUNC(t90_timer_callback), cpustate);
+
+ cpustate->timer[4] = device->machine().scheduler().timer_alloc(FUNC(t90_timer4_callback), cpustate);
+}
+
+static ADDRESS_MAP_START(tmp90840_mem, AS_PROGRAM, 8)
+ AM_RANGE( 0x0000, 0x1fff ) AM_ROM // 8KB ROM (internal)
+ AM_RANGE( 0xfec0, 0xffc0 ) AM_RAM // 256b RAM (internal)
+ AM_RANGE( T90_IOBASE, T90_IOBASE+47 ) AM_READWRITE( t90_internal_registers_r, t90_internal_registers_w )
+ADDRESS_MAP_END
+static ADDRESS_MAP_START(tmp90841_mem, AS_PROGRAM, 8)
+// AM_RANGE( 0x0000, 0x1fff ) AM_ROM // rom-less
+ AM_RANGE( 0xfec0, 0xffc0 ) AM_RAM // 256b RAM (internal)
+ AM_RANGE( T90_IOBASE, T90_IOBASE+47 ) AM_READWRITE( t90_internal_registers_r, t90_internal_registers_w )
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START(tmp91640_mem, AS_PROGRAM, 8)
+ AM_RANGE( 0x0000, 0x3fff ) AM_ROM // 16KB ROM (internal)
+ AM_RANGE( 0xfdc0, 0xffc0 ) AM_RAM // 512b RAM (internal)
+ AM_RANGE( T90_IOBASE, T90_IOBASE+47 ) AM_READWRITE( t90_internal_registers_r, t90_internal_registers_w )
+ADDRESS_MAP_END
+static ADDRESS_MAP_START(tmp91641_mem, AS_PROGRAM, 8)
+// AM_RANGE( 0x0000, 0x3fff ) AM_ROM // rom-less
+ AM_RANGE( 0xfdc0, 0xffc0 ) AM_RAM // 512b RAM (internal)
+ AM_RANGE( T90_IOBASE, T90_IOBASE+47 ) AM_READWRITE( t90_internal_registers_r, t90_internal_registers_w )
+ADDRESS_MAP_END
+
+static CPU_SET_INFO( t90 )
+{
+ t90_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: set_irq_line(cpustate, INTNMI, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ0: set_irq_line(cpustate, INT0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ1: set_irq_line(cpustate, INT1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ2: set_irq_line(cpustate, INT2, info->i); break;
+
+ case CPUINFO_INT_PC: cpustate->pc.d = info->i; break;
+ case CPUINFO_INT_REGISTER + T90_PC: cpustate->pc.w.l = info->i; break;
+ case CPUINFO_INT_SP: cpustate->sp.w.l = info->i; break;
+ case CPUINFO_INT_REGISTER + T90_SP: cpustate->sp.w.l = info->i; break;
+ case CPUINFO_INT_REGISTER + T90_A: cpustate->af.b.h = info->i; break;
+ case CPUINFO_INT_REGISTER + T90_B: cpustate->bc.b.h = info->i; break;
+ case CPUINFO_INT_REGISTER + T90_C: cpustate->bc.b.l = info->i; break;
+ case CPUINFO_INT_REGISTER + T90_D: cpustate->de.b.h = info->i; break;
+ case CPUINFO_INT_REGISTER + T90_E: cpustate->de.b.l = info->i; break;
+ case CPUINFO_INT_REGISTER + T90_H: cpustate->hl.b.h = info->i; break;
+ case CPUINFO_INT_REGISTER + T90_L: cpustate->hl.b.l = info->i; break;
+ case CPUINFO_INT_REGISTER + T90_AF: cpustate->af.w.l = info->i; break;
+ case CPUINFO_INT_REGISTER + T90_BC: cpustate->bc.w.l = info->i; break;
+ case CPUINFO_INT_REGISTER + T90_DE: cpustate->de.w.l = info->i; break;
+ case CPUINFO_INT_REGISTER + T90_HL: cpustate->hl.w.l = info->i; break;
+ case CPUINFO_INT_REGISTER + T90_IX: cpustate->ix.w.l = info->i; break;
+ case CPUINFO_INT_REGISTER + T90_IY: cpustate->iy.w.l = info->i; break;
+ }
+}
+
+CPU_GET_INFO( tmp90840 )
+{
+ t90_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(t90_Regs); 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 = 6; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 2; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 26; 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 = 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 + INPUT_LINE_NMI: info->i = cpustate->irq_state & (1 << INTNMI); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ0: info->i = cpustate->irq_state & (1 << INT0); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ1: info->i = cpustate->irq_state & (1 << INT1); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ2: info->i = cpustate->irq_state & (1 << INT2); break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->prvpc.w.l; break;
+ case CPUINFO_INT_PC: info->i = cpustate->pc.d; break;
+ case CPUINFO_INT_REGISTER + T90_PC: info->i = cpustate->pc.w.l; break;
+ case CPUINFO_INT_SP: info->i = cpustate->sp.d; break;
+ case CPUINFO_INT_REGISTER + T90_SP: info->i = cpustate->sp.w.l; break;
+ case CPUINFO_INT_REGISTER + T90_A: info->i = cpustate->af.b.h; break;
+ case CPUINFO_INT_REGISTER + T90_B: info->i = cpustate->bc.b.h; break;
+ case CPUINFO_INT_REGISTER + T90_C: info->i = cpustate->bc.b.l; break;
+ case CPUINFO_INT_REGISTER + T90_D: info->i = cpustate->de.b.h; break;
+ case CPUINFO_INT_REGISTER + T90_E: info->i = cpustate->de.b.l; break;
+ case CPUINFO_INT_REGISTER + T90_H: info->i = cpustate->hl.b.h; break;
+ case CPUINFO_INT_REGISTER + T90_L: info->i = cpustate->hl.b.l; break;
+ case CPUINFO_INT_REGISTER + T90_AF: info->i = cpustate->af.w.l; break;
+ case CPUINFO_INT_REGISTER + T90_BC: info->i = cpustate->bc.w.l; break;
+ case CPUINFO_INT_REGISTER + T90_DE: info->i = cpustate->de.w.l; break;
+ case CPUINFO_INT_REGISTER + T90_HL: info->i = cpustate->hl.w.l; break;
+ case CPUINFO_INT_REGISTER + T90_IX: info->i = cpustate->ix.w.l; break;
+ case CPUINFO_INT_REGISTER + T90_IY: info->i = cpustate->iy.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(t90); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(t90); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(t90); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(t90); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(t90); break;
+ case CPUINFO_FCT_BURN: info->burn = CPU_BURN_NAME(t90); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(t90); 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(tmp90840_mem); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+
+ case DEVINFO_STR_NAME: strcpy(info->s, "TMP90840"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Toshiba TLCS-90"); 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, "Luca Elia"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c",
+ F & 0x80 ? 'S':'.',
+ F & 0x40 ? 'Z':'.',
+ F & 0x20 ? 'I':'.',
+ F & 0x10 ? 'H':'.',
+ F & 0x08 ? 'X':'.',
+ F & 0x04 ? 'P':'.',
+ F & 0x02 ? 'N':'.',
+ F & 0x01 ? 'C':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + T90_PC: sprintf(info->s, "PC:%04X", cpustate->pc.w.l); break;
+ case CPUINFO_STR_REGISTER + T90_SP: sprintf(info->s, "SP:%04X", cpustate->sp.w.l); break;
+ case CPUINFO_STR_REGISTER + T90_A: sprintf(info->s, "~A:%02X", cpustate->af.b.h); break;
+ case CPUINFO_STR_REGISTER + T90_B: sprintf(info->s, "~B:%02X", cpustate->bc.b.h); break;
+ case CPUINFO_STR_REGISTER + T90_C: sprintf(info->s, "~C:%02X", cpustate->bc.b.l); break;
+ case CPUINFO_STR_REGISTER + T90_D: sprintf(info->s, "~D:%02X", cpustate->de.b.h); break;
+ case CPUINFO_STR_REGISTER + T90_E: sprintf(info->s, "~E:%02X", cpustate->de.b.l); break;
+ case CPUINFO_STR_REGISTER + T90_H: sprintf(info->s, "~H:%02X", cpustate->hl.b.h); break;
+ case CPUINFO_STR_REGISTER + T90_L: sprintf(info->s, "~L:%02X", cpustate->hl.b.l); break;
+ case CPUINFO_STR_REGISTER + T90_AF: sprintf(info->s, "AF:%04X", cpustate->af.w.l); break;
+ case CPUINFO_STR_REGISTER + T90_BC: sprintf(info->s, "BC:%04X", cpustate->bc.w.l); break;
+ case CPUINFO_STR_REGISTER + T90_DE: sprintf(info->s, "DE:%04X", cpustate->de.w.l); break;
+ case CPUINFO_STR_REGISTER + T90_HL: sprintf(info->s, "HL:%04X", cpustate->hl.w.l); break;
+ case CPUINFO_STR_REGISTER + T90_IX: sprintf(info->s, "IX:%04X", cpustate->ix.w.l); break;
+ case CPUINFO_STR_REGISTER + T90_IY: sprintf(info->s, "IY:%04X", cpustate->iy.w.l); break;
+ }
+}
+
+CPU_GET_INFO( tmp90841 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(tmp90841_mem); return;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+
+ case DEVINFO_STR_NAME: strcpy(info->s, "TMP90841"); return;
+ }
+
+ CPU_GET_INFO_CALL(tmp90840);
+}
+
+CPU_GET_INFO( tmp91640 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(tmp91640_mem); return;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+
+ case DEVINFO_STR_NAME: strcpy(info->s, "TMP91640"); return;
+ }
+
+ CPU_GET_INFO_CALL(tmp90840);
+}
+
+CPU_GET_INFO( tmp91641 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(tmp91641_mem); return;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+
+ case DEVINFO_STR_NAME: strcpy(info->s, "TMP91641"); return;
+ }
+
+ CPU_GET_INFO_CALL(tmp90840);
+}
+
+DEFINE_LEGACY_CPU_DEVICE(TMP90840, tmp90840);
+DEFINE_LEGACY_CPU_DEVICE(TMP90841, tmp90841);
+DEFINE_LEGACY_CPU_DEVICE(TMP91640, tmp91640);
+DEFINE_LEGACY_CPU_DEVICE(TMP91641, tmp91641);
diff --git a/trunk/src/emu/cpu/tlcs90/tlcs90.h b/trunk/src/emu/cpu/tlcs90/tlcs90.h
new file mode 100644
index 00000000000..e584d444e97
--- /dev/null
+++ b/trunk/src/emu/cpu/tlcs90/tlcs90.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#ifndef __TLCS90_H__
+#define __TLCS90_H__
+
+
+DECLARE_LEGACY_CPU_DEVICE(TMP90840, tmp90840);
+DECLARE_LEGACY_CPU_DEVICE(TMP90841, tmp90841);
+DECLARE_LEGACY_CPU_DEVICE(TMP91640, tmp91640);
+DECLARE_LEGACY_CPU_DEVICE(TMP91641, tmp91641);
+
+CPU_DISASSEMBLE( t90 );
+
+#define T90_IOBASE 0xffc0
+
+typedef enum
+{
+ T90_P0=T90_IOBASE, T90_P1, T90_P01CR_IRFL, T90_IRFH, T90_P2, T90_P2CR, T90_P3, T90_P3CR,
+ T90_P4, T90_P4CR, T90_P5, T90_SMMOD, T90_P6, T90_P7, T90_P67CR, T90_SMCR,
+ T90_P8, T90_P8CR, T90_WDMOD, T90_WDCR, T90_TREG0, T90_TREG1, T90_TREG2, T90_TREG3,
+ T90_TCLK, T90_TFFCR, T90_TMOD, T90_TRUN, T90_CAP1L, T90_CAP1H, T90_CAP2L, T90_CAL2H,
+ T90_TREG4L, T90_TREG4H, T90_TREG5L, T90_TREG5H, T90_T4MOD, T90_T4FFCR, T90_INTEL, T90_INTEH,
+ T90_DMAEH, T90_SCMOD, T90_SCCR, T90_SCBUF, T90_BX, T90_BY, T90_ADREG, T90_ADMOD
+} e_ir;
+
+#endif /* __TLCS90_H__ */
diff --git a/trunk/src/emu/cpu/tlcs900/900tbl.c b/trunk/src/emu/cpu/tlcs900/900tbl.c
new file mode 100644
index 00000000000..e28ef8d5169
--- /dev/null
+++ b/trunk/src/emu/cpu/tlcs900/900tbl.c
@@ -0,0 +1,6023 @@
+/*******************************************************************
+
+TLCS-900/H instruction set
+
+*******************************************************************/
+
+
+enum e_operand
+{
+ _A=1, /* currect register set register A */
+ _C8, /* current register set byte */
+ _C16, /* current register set word */
+ _C32, /* current register set long word */
+ _MC16, /* current register set mul/div register word */
+ _CC, /* condition */
+ _CR8,
+ _CR16,
+ _CR32,
+ _D8, /* byte displacement */
+ _D16, /* word displacement */
+ _F, /* F register */
+ _I3, /* immediate 3 bit (part of last byte) */
+ _I8, /* immediate byte */
+ _I16, /* immediate word */
+ _I24, /* immediate 3 byte address */
+ _I32, /* immediate long word */
+ _M, /* memory location (defined by extension) */
+ _M8, /* (8) */
+ _M16, /* (i16) */
+ _R, /* register (defined by extension) */
+ _SR, /* status register */
+};
+
+
+INLINE int condition_true( tlcs900_state *cpustate, UINT8 cond )
+{
+ switch ( cond & 0x0f )
+ {
+ /* F */
+ case 0x00:
+ return 0;
+
+ /* LT */
+ case 0x01:
+ return ( ( ( cpustate->sr.b.l & ( FLAG_SF | FLAG_VF ) ) == FLAG_SF ) ||
+ ( ( cpustate->sr.b.l & ( FLAG_SF | FLAG_VF ) ) == FLAG_VF ) );
+
+ /* LE */
+ case 0x02:
+ return ( ( ( cpustate->sr.b.l & ( FLAG_SF | FLAG_VF ) ) == FLAG_SF ) ||
+ ( ( cpustate->sr.b.l & ( FLAG_SF | FLAG_VF ) ) == FLAG_VF ) ||
+ ( cpustate->sr.b.l & FLAG_ZF ) );
+
+ /* ULE */
+ case 0x03:
+ return ( cpustate->sr.b.l & ( FLAG_ZF | FLAG_CF ) );
+
+ /* OV */
+ case 0x04:
+ return ( cpustate->sr.b.l & FLAG_VF );
+
+ /* MI */
+ case 0x05:
+ return ( cpustate->sr.b.l & FLAG_SF );
+
+ /* Z */
+ case 0x06:
+ return ( cpustate->sr.b.l & FLAG_ZF );
+
+ /* C */
+ case 0x07:
+ return ( cpustate->sr.b.l & FLAG_CF );
+
+ /* T */
+ case 0x08:
+ return 1;
+
+ /* GE */
+ case 0x09:
+ return ! ( ( ( cpustate->sr.b.l & ( FLAG_SF | FLAG_VF ) ) == FLAG_SF ) ||
+ ( ( cpustate->sr.b.l & ( FLAG_SF | FLAG_VF ) ) == FLAG_VF ) );
+
+ /* GT */
+ case 0x0A:
+ return ! ( ( ( cpustate->sr.b.l & ( FLAG_SF | FLAG_VF ) ) == FLAG_SF ) ||
+ ( ( cpustate->sr.b.l & ( FLAG_SF | FLAG_VF ) ) == FLAG_VF ) ||
+ ( cpustate->sr.b.l & FLAG_ZF ) );
+
+ /* UGT */
+ case 0x0B:
+ return ! ( cpustate->sr.b.l & ( FLAG_ZF | FLAG_CF ) );
+
+ /* NOV */
+ case 0x0C:
+ return ! ( cpustate->sr.b.l & FLAG_VF );
+
+ /* PL */
+ case 0x0D:
+ return ! ( cpustate->sr.b.l & FLAG_SF );
+
+ /* NZ */
+ case 0x0E:
+ return ! ( cpustate->sr.b.l & FLAG_ZF );
+
+ /* NC */
+ case 0x0F:
+ return ! ( cpustate->sr.b.l & FLAG_CF );
+ }
+ return 0;
+}
+
+
+INLINE UINT8 *get_reg8_current( tlcs900_state *cpustate, UINT8 reg )
+{
+ switch( reg & 7 )
+ {
+ /* W */
+ case 0:
+ return &cpustate->xwa[cpustate->regbank].b.h;
+
+ /* A */
+ case 1:
+ return &cpustate->xwa[cpustate->regbank].b.l;
+
+ /* B */
+ case 2:
+ return &cpustate->xbc[cpustate->regbank].b.h;
+
+ /* C */
+ case 3:
+ return &cpustate->xbc[cpustate->regbank].b.l;
+
+ /* D */
+ case 4:
+ return &cpustate->xde[cpustate->regbank].b.h;
+
+ /* E */
+ case 5:
+ return &cpustate->xde[cpustate->regbank].b.l;
+
+ /* H */
+ case 6:
+ return &cpustate->xhl[cpustate->regbank].b.h;
+
+ /* L */
+ case 7:
+ return &cpustate->xhl[cpustate->regbank].b.l;
+ }
+ /* keep compiler happy */
+ return &cpustate->dummy.b.l;
+}
+
+
+INLINE UINT16 *get_reg16_current( tlcs900_state *cpustate, UINT8 reg )
+{
+ switch( reg & 7 )
+ {
+ /* WA */
+ case 0:
+ return &cpustate->xwa[cpustate->regbank].w.l;
+
+ /* BC */
+ case 1:
+ return &cpustate->xbc[cpustate->regbank].w.l;
+
+ /* DE */
+ case 2:
+ return &cpustate->xde[cpustate->regbank].w.l;
+
+ /* HL */
+ case 3:
+ return &cpustate->xhl[cpustate->regbank].w.l;
+
+ /* IX */
+ case 4:
+ return &cpustate->xix.w.l;
+
+ /* IY */
+ case 5:
+ return &cpustate->xiy.w.l;
+
+ /* IZ */
+ case 6:
+ return &cpustate->xiz.w.l;
+
+ /* SP */
+ /* TODO: Use correct user/system SP */
+ case 7:
+ return &cpustate->xssp.w.l;
+ }
+ /* keep compiler happy */
+ return &cpustate->dummy.w.l;
+}
+
+
+INLINE UINT32 *get_reg32_current( tlcs900_state *cpustate, UINT8 reg )
+{
+ switch( reg & 7 )
+ {
+ /* XWA */
+ case 0:
+ return &cpustate->xwa[cpustate->regbank].d;
+
+ /* XBC */
+ case 1:
+ return &cpustate->xbc[cpustate->regbank].d;
+
+ /* XDE */
+ case 2:
+ return &cpustate->xde[cpustate->regbank].d;
+
+ /* XHL */
+ case 3:
+ return &cpustate->xhl[cpustate->regbank].d;
+
+ /* XIX */
+ case 4:
+ return &cpustate->xix.d;
+
+ /* XIY */
+ case 5:
+ return &cpustate->xiy.d;
+
+ /* XIZ */
+ case 6:
+ return &cpustate->xiz.d;
+
+ /* XSP */
+ case 7:
+ /* TODO: Add selector for user/system stack pointer */
+ return &cpustate->xssp.d;
+ }
+ /* keep compiler happy */
+ return &cpustate->dummy.d;
+}
+
+
+INLINE PAIR *get_reg( tlcs900_state *cpustate, UINT8 reg )
+{
+ UINT8 regbank;
+
+ switch( reg & 0xf0 )
+ {
+ case 0x00: case 0x10: case 0x20: case 0x30: /* explicit register bank */
+ case 0xd0: /* "previous" register bank */
+ case 0xe0: /* current register bank */
+ regbank = ( reg & 0xf0 ) >> 4;
+ if ( regbank == 0x0d )
+ regbank = ( cpustate->regbank - 1 ) & 0x03;
+
+ if ( regbank == 0x0e )
+ regbank = cpustate->regbank;
+
+ switch ( reg & 0x0c )
+ {
+ case 0x00: return &cpustate->xwa[regbank];
+ case 0x04: return &cpustate->xbc[regbank];
+ case 0x08: return &cpustate->xde[regbank];
+ case 0x0c: return &cpustate->xhl[regbank];
+ }
+ break;
+ case 0xf0: /* index registers and sp */
+ switch ( reg & 0x0c )
+ {
+ case 0x00: return &cpustate->xix;
+ case 0x04: return &cpustate->xiy;
+ case 0x08: return &cpustate->xiz;
+ /* TODO: Use correct SP */
+ case 0x0c: return &cpustate->xssp;
+ }
+ break;
+ }
+
+ /* illegal/unknown register reference */
+ logerror( "Access to unknown tlcs-900 cpu register %02x\n", reg );
+ return &cpustate->dummy;
+}
+
+
+INLINE UINT8 *get_reg8( tlcs900_state *cpustate, UINT8 reg )
+{
+ PAIR *r = get_reg( cpustate, reg );
+
+ switch ( reg & 0x03 )
+ {
+ case 0x00: return &r->b.l;
+ case 0x01: return &r->b.h;
+ case 0x02: return &r->b.h2;
+ case 0x03: return &r->b.h3;
+ }
+
+ return &r->b.l;
+}
+
+
+INLINE UINT16 *get_reg16( tlcs900_state *cpustate, UINT8 reg )
+{
+ PAIR *r = get_reg( cpustate, reg );
+
+ return ( reg & 0x02 ) ? &r->w.h : &r->w.l;
+}
+
+
+INLINE UINT32 *get_reg32( tlcs900_state *cpustate, UINT8 reg )
+{
+ PAIR *r = get_reg( cpustate, reg );
+
+ return &r->d;
+}
+
+
+
+INLINE void parity8( tlcs900_state *cpustate, UINT8 a )
+{
+ int i, j;
+
+ j = 0;
+ for ( i = 0; i < 8; i++ )
+ {
+ if ( a & 1 ) j++;
+ a >>= 1;
+ }
+ cpustate->sr.b.l |= ( ( j & 1 ) ? 0 : FLAG_VF );
+}
+
+
+INLINE void parity16( tlcs900_state *cpustate, UINT16 a )
+{
+ int i, j;
+
+ j = 0;
+ for ( i = 0; i < 16; i++ )
+ {
+ if ( a & 1 ) j++;
+ a >>= 1;
+ }
+ cpustate->sr.b.l |= ( ( j & 1 ) ? 0 : FLAG_VF );
+}
+
+
+INLINE void parity32( tlcs900_state *cpustate, UINT32 a )
+{
+ int i, j;
+
+ j = 0;
+ for ( i = 0; i < 32; i++ )
+ {
+ if ( a & 1 ) j++;
+ a >>= 1;
+ }
+ cpustate->sr.b.l |= ( ( j & 1 ) ? 0 : FLAG_VF );
+}
+
+
+INLINE UINT8 adc8( tlcs900_state *cpustate, UINT8 a, UINT8 b)
+{
+ UINT8 cy = cpustate->sr.b.l & FLAG_CF;
+ UINT8 result = a + b + cy;
+
+ cpustate->sr.b.l &= ~(FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF | FLAG_CF);
+ cpustate->sr.b.l |= ( result & FLAG_SF ) | ( result ? 0 : FLAG_ZF ) |
+ ( ( ( a ^ b ) ^ result ) & FLAG_HF ) |
+ ( ( ( result ^ a ) & ( result ^ b ) & 0x80 ) ? FLAG_VF : 0 ) |
+ ( ( ( result < a ) || ( ( result == a ) && cy ) ) ? FLAG_CF : 0 );
+
+ return result;
+}
+
+
+INLINE UINT16 adc16( tlcs900_state *cpustate, UINT16 a, UINT16 b)
+{
+ UINT8 cy = cpustate->sr.b.l & FLAG_CF;
+ UINT16 result = a + b + cy;
+
+ cpustate->sr.b.l &= ~(FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF | FLAG_CF);
+ cpustate->sr.b.l |= ( ( result >> 8 ) & FLAG_SF ) | ( result ? 0 : FLAG_ZF ) |
+ ( ( ( a ^ b ) ^ result ) & FLAG_HF ) |
+ ( ( ( result ^ a ) & ( result ^ b ) & 0x8000 ) ? FLAG_VF : 0 ) |
+ ( ( ( result < a ) || ( ( result == a ) && cy ) ) ? FLAG_CF : 0 );
+
+ return result;
+}
+
+
+INLINE UINT32 adc32( tlcs900_state *cpustate, UINT32 a, UINT32 b)
+{
+ UINT8 cy = cpustate->sr.b.l & FLAG_CF;
+ UINT32 result = a + b + cy;
+
+ cpustate->sr.b.l &= ~(FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF | FLAG_CF);
+ cpustate->sr.b.l |= ( ( result >> 24 ) & FLAG_SF ) | ( result ? 0 : FLAG_ZF ) |
+ ( ( ( result ^ a ) & ( result ^ b ) & 0x80000000 ) ? FLAG_VF : 0 ) |
+ ( ( ( result < a ) || ( ( result == a ) && cy ) ) ? FLAG_CF : 0 );
+
+ return result;
+}
+
+
+INLINE UINT8 add8( tlcs900_state *cpustate, UINT8 a, UINT8 b)
+{
+ UINT8 result = a + b;
+
+ cpustate->sr.b.l &= ~(FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF | FLAG_CF);
+ cpustate->sr.b.l |= ( result & FLAG_SF ) | ( result ? 0 : FLAG_ZF ) |
+ ( ( ( a ^ b ) ^ result ) & FLAG_HF ) |
+ ( ( ( result ^ a ) & ( result ^ b ) & 0x80 ) ? FLAG_VF : 0 ) |
+ ( ( result < a ) ? FLAG_CF : 0 );
+
+ return result;
+}
+
+
+INLINE UINT16 add16( tlcs900_state *cpustate, UINT16 a, UINT16 b)
+{
+ UINT16 result = a + b;
+
+ cpustate->sr.b.l &= ~(FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF | FLAG_CF);
+ cpustate->sr.b.l |= ( ( result >> 8 ) & FLAG_SF ) | ( result ? 0 : FLAG_ZF ) |
+ ( ( ( a ^ b ) ^ result ) & FLAG_HF ) |
+ ( ( ( result ^ a ) & ( result ^ b ) & 0x8000 ) ? FLAG_VF : 0 ) |
+ ( ( result < a ) ? FLAG_CF : 0 );
+
+ return result;
+}
+
+
+INLINE UINT32 add32( tlcs900_state *cpustate, UINT32 a, UINT32 b)
+{
+ UINT32 result = a + b;
+
+ cpustate->sr.b.l &= ~(FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF | FLAG_CF);
+ cpustate->sr.b.l |= ( ( result >> 24 ) & FLAG_SF ) | ( result ? 0 : FLAG_ZF ) |
+ ( ( ( result ^ a ) & ( result ^ b ) & 0x80000000 ) ? FLAG_VF : 0 ) |
+ ( ( result < a ) ? FLAG_CF : 0 );
+
+ return result;
+}
+
+
+INLINE UINT8 sbc8( tlcs900_state *cpustate, UINT8 a, UINT8 b)
+{
+ UINT8 cy = cpustate->sr.b.l & FLAG_CF;
+ UINT8 result = a - b - cy;
+
+ cpustate->sr.b.l &= ~(FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_CF);
+ cpustate->sr.b.l |= ( result & FLAG_SF ) | ( result ? 0 : FLAG_ZF ) |
+ ( ( ( a ^ b ) ^ result ) & FLAG_HF ) |
+ ( ( ( result ^ a ) & ( a ^ b ) & 0x80 ) ? FLAG_VF : 0 ) |
+ ( ( ( result > a ) || ( cy && b == 0xFF ) ) ? FLAG_CF : 0 ) | FLAG_NF;
+
+ return result;
+}
+
+
+INLINE UINT16 sbc16( tlcs900_state *cpustate, UINT16 a, UINT16 b)
+{
+ UINT8 cy = cpustate->sr.b.l & FLAG_CF;
+ UINT16 result = a - b - cy;
+
+ cpustate->sr.b.l &= ~(FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_CF);
+ cpustate->sr.b.l |= ( ( result >> 8 ) & FLAG_SF ) | ( result ? 0 : FLAG_ZF ) |
+ ( ( ( a ^ b ) ^ result ) & FLAG_HF ) |
+ ( ( ( result ^ a ) & ( a ^ b ) & 0x8000 ) ? FLAG_VF : 0 ) |
+ ( ( ( result > a ) || ( cy && b == 0xFFFF ) ) ? FLAG_CF : 0 ) | FLAG_NF;
+
+ return result;
+}
+
+
+INLINE UINT32 sbc32( tlcs900_state *cpustate, UINT32 a, UINT32 b)
+{
+ UINT8 cy = cpustate->sr.b.l & FLAG_CF;
+ UINT32 result = a - b - cy;
+
+ cpustate->sr.b.l &= ~(FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_CF);
+ cpustate->sr.b.l |= ( ( result >> 24 ) & FLAG_SF ) | ( result ? 0 : FLAG_ZF ) |
+ ( ( ( result ^ a ) & ( a ^ b ) & 0x80000000 ) ? FLAG_VF : 0 ) |
+ ( ( ( result > a ) || ( cy && b == 0xFFFFFFFF ) ) ? FLAG_CF : 0 ) | FLAG_NF;
+
+ return result;
+}
+
+
+INLINE UINT8 sub8( tlcs900_state *cpustate, UINT8 a, UINT8 b)
+{
+ UINT8 result = a - b;
+
+ cpustate->sr.b.l &= ~(FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_CF);
+ cpustate->sr.b.l |= ( result & FLAG_SF ) | ( result ? 0 : FLAG_ZF ) |
+ ( ( ( a ^ b ) ^ result ) & FLAG_HF ) |
+ ( ( ( result ^ a ) & ( a ^ b ) & 0x80 ) ? FLAG_VF : 0 ) |
+ ( ( result > a ) ? FLAG_CF : 0 ) | FLAG_NF;
+
+ return result;
+}
+
+
+INLINE UINT16 sub16( tlcs900_state *cpustate, UINT16 a, UINT16 b)
+{
+ UINT16 result = a - b;
+
+ cpustate->sr.b.l &= ~(FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_CF);
+ cpustate->sr.b.l |= ( ( result >> 8 ) & FLAG_SF ) | ( result ? 0 : FLAG_ZF ) |
+ ( ( ( a ^ b ) ^ result ) & FLAG_HF ) |
+ ( ( ( result ^ a ) & ( a ^ b ) & 0x8000 ) ? FLAG_VF : 0 ) |
+ ( ( result > a ) ? FLAG_CF : 0 ) | FLAG_NF;
+
+ return result;
+}
+
+
+INLINE UINT32 sub32( tlcs900_state *cpustate, UINT32 a, UINT32 b)
+{
+ UINT32 result = a - b;
+
+ cpustate->sr.b.l &= ~(FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_CF);
+ cpustate->sr.b.l |= ( ( result >> 24 ) & FLAG_SF ) | ( result ? 0 : FLAG_ZF ) |
+ ( ( ( result ^ a ) & ( a ^ b ) & 0x80000000 ) ? FLAG_VF : 0 ) |
+ ( ( result > a ) ? FLAG_CF : 0 ) | FLAG_NF;
+
+ return result;
+}
+
+
+INLINE UINT8 and8( tlcs900_state *cpustate, UINT8 a, UINT8 b)
+{
+ UINT8 result = a & b;
+
+ cpustate->sr.b.l &= ~(FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF | FLAG_CF);
+ cpustate->sr.b.l |= ( result & FLAG_SF ) | ( result ? 0 : FLAG_ZF ) | FLAG_HF;
+
+ parity8( cpustate, result );
+
+ return result;
+}
+
+
+INLINE UINT16 and16( tlcs900_state *cpustate, UINT16 a, UINT16 b)
+{
+ UINT16 result = a & b;
+
+ cpustate->sr.b.l &= ~(FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF | FLAG_CF);
+ cpustate->sr.b.l |= ( ( result >> 8 ) & FLAG_SF ) | ( result ? 0 : FLAG_ZF ) | FLAG_HF;
+
+ parity16( cpustate, result );
+
+ return result;
+}
+
+
+INLINE UINT32 and32( tlcs900_state *cpustate, UINT32 a, UINT32 b)
+{
+ UINT32 result = a & b;
+
+ cpustate->sr.b.l &= ~(FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF | FLAG_CF);
+ cpustate->sr.b.l |= ( ( result >> 24 ) & FLAG_SF ) | ( result ? 0 : FLAG_ZF ) | FLAG_HF;
+
+ return result;
+}
+
+
+INLINE UINT8 or8( tlcs900_state *cpustate, UINT8 a, UINT8 b)
+{
+ UINT8 result = a | b;
+
+ cpustate->sr.b.l &= ~(FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF | FLAG_CF);
+ cpustate->sr.b.l |= ( result & FLAG_SF ) | ( result ? 0 : FLAG_ZF );
+
+ parity8( cpustate, result );
+
+ return result;
+}
+
+
+INLINE UINT16 or16( tlcs900_state *cpustate, UINT16 a, UINT16 b)
+{
+ UINT16 result = a | b;
+
+ cpustate->sr.b.l &= ~(FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF | FLAG_CF);
+ cpustate->sr.b.l |= ( ( result >> 8 ) & FLAG_SF ) | ( result ? 0 : FLAG_ZF );
+
+ parity16( cpustate, result );
+
+ return result;
+}
+
+
+INLINE UINT32 or32( tlcs900_state *cpustate, UINT32 a, UINT32 b)
+{
+ UINT32 result = a | b;
+
+ cpustate->sr.b.l &= ~(FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF | FLAG_CF);
+ cpustate->sr.b.l |= ( ( result >> 24 ) & FLAG_SF ) | ( result ? 0 : FLAG_ZF );
+
+ return result;
+}
+
+
+INLINE UINT8 xor8( tlcs900_state *cpustate, UINT8 a, UINT8 b)
+{
+ UINT8 result = a ^ b;
+
+ cpustate->sr.b.l &= ~(FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF | FLAG_CF);
+ cpustate->sr.b.l |= ( result & FLAG_SF ) | ( result ? 0 : FLAG_ZF );
+
+ parity8( cpustate, result );
+
+ return result;
+}
+
+
+INLINE UINT16 xor16( tlcs900_state *cpustate, UINT16 a, UINT16 b)
+{
+ UINT16 result = a ^ b;
+
+ cpustate->sr.b.l &= ~(FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF | FLAG_CF);
+ cpustate->sr.b.l |= ( ( result >> 8 ) & FLAG_SF ) | ( result ? 0 : FLAG_ZF );
+
+ parity16( cpustate, result );
+
+ return result;
+}
+
+
+INLINE UINT32 xor32( tlcs900_state *cpustate, UINT32 a, UINT32 b)
+{
+ UINT32 result = a ^ b;
+
+ cpustate->sr.b.l &= ~(FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF | FLAG_CF);
+ cpustate->sr.b.l |= ( ( result >> 24 ) & FLAG_SF ) | ( result ? 0 : FLAG_ZF );
+
+ return result;
+}
+
+
+INLINE void ldcf8( tlcs900_state *cpustate, UINT8 a, UINT8 b )
+{
+ if ( b & ( 1 << ( a & 0x07 ) ) )
+ cpustate->sr.b.l |= FLAG_CF;
+ else
+ cpustate->sr.b.l &= ~ FLAG_CF;
+}
+
+
+INLINE void ldcf16( tlcs900_state *cpustate, UINT8 a, UINT8 b )
+{
+ if ( b & ( 1 << ( a & 0x0f ) ) )
+ cpustate->sr.b.l |= FLAG_CF;
+ else
+ cpustate->sr.b.l &= ~ FLAG_CF;
+}
+
+
+INLINE void andcf8( tlcs900_state *cpustate, UINT8 a, UINT8 b )
+{
+ if ( ( b & ( 1 << ( a & 0x07 ) ) ) && ( cpustate->sr.b.l & FLAG_CF ) )
+ cpustate->sr.b.l |= FLAG_CF;
+ else
+ cpustate->sr.b.l &= ~ FLAG_CF;
+}
+
+
+INLINE void andcf16( tlcs900_state *cpustate, UINT8 a, UINT8 b )
+{
+ if ( ( b & ( 1 << ( a & 0x0f ) ) ) && ( cpustate->sr.b.l & FLAG_CF ) )
+ cpustate->sr.b.l |= FLAG_CF;
+ else
+ cpustate->sr.b.l &= ~ FLAG_CF;
+}
+
+
+INLINE void orcf8( tlcs900_state *cpustate, UINT8 a, UINT8 b )
+{
+ if ( b & ( 1 << ( a & 0x07 ) ) )
+ cpustate->sr.b.l |= FLAG_CF;
+}
+
+
+INLINE void orcf16( tlcs900_state *cpustate, UINT8 a, UINT8 b )
+{
+ if ( b & ( 1 << ( a & 0x0f ) ) )
+ cpustate->sr.b.l |= FLAG_CF;
+}
+
+
+INLINE void xorcf8( tlcs900_state *cpustate, UINT8 a, UINT8 b )
+{
+ if ( b & ( 1 << ( a & 0x07 ) ) )
+ cpustate->sr.b.l ^= FLAG_CF;
+}
+
+
+INLINE void xorcf16( tlcs900_state *cpustate, UINT8 a, UINT8 b )
+{
+ if ( b & ( 1 << ( a & 0x0f ) ) )
+ cpustate->sr.b.l ^= FLAG_CF;
+}
+
+
+INLINE UINT8 rl8( tlcs900_state *cpustate, UINT8 a, UINT8 s )
+{
+ UINT8 count = ( s & 0x0f ) ? ( s & 0x0f ) : 16;
+
+ for ( ; count > 0; count-- )
+ {
+ if ( a & 0x80 )
+ {
+ a = ( a << 1 ) | ( cpustate->sr.b.l & FLAG_CF );
+ cpustate->sr.b.l |= FLAG_CF;
+ }
+ else
+ {
+ a = ( a << 1 ) | ( cpustate->sr.b.l & FLAG_CF );
+ cpustate->sr.b.l &= ~ FLAG_CF;
+ }
+ }
+
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF );
+ cpustate->sr.b.l |= ( a & FLAG_SF ) | ( a ? 0 : FLAG_ZF );
+ parity8( cpustate, a );
+
+ return a;
+}
+
+
+INLINE UINT16 rl16( tlcs900_state *cpustate, UINT16 a, UINT8 s )
+{
+ UINT8 count = ( s & 0x0f ) ? ( s & 0x0f ) : 16;
+
+ for ( ; count > 0; count-- )
+ {
+ if ( a & 0x8000 )
+ {
+ a = ( a << 1 ) | ( cpustate->sr.b.l & FLAG_CF );
+ cpustate->sr.b.l |= FLAG_CF;
+ }
+ else
+ {
+ a = ( a << 1 ) | ( cpustate->sr.b.l & FLAG_CF );
+ cpustate->sr.b.l &= ~ FLAG_CF;
+ }
+ }
+
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF );
+ cpustate->sr.b.l |= ( ( a >> 8 ) & FLAG_SF ) | ( a ? 0 : FLAG_ZF );
+ parity16( cpustate, a );
+
+ return a;
+}
+
+
+INLINE UINT32 rl32( tlcs900_state *cpustate, UINT32 a, UINT8 s )
+{
+ UINT8 count = ( s & 0x0f ) ? ( s & 0x0f ) : 16;
+
+ for ( ; count > 0; count-- )
+ {
+ if ( a & 0x80000000 )
+ {
+ a = ( a << 1 ) | ( cpustate->sr.b.l & FLAG_CF );
+ cpustate->sr.b.l |= FLAG_CF;
+ }
+ else
+ {
+ a = ( a << 1 ) | ( cpustate->sr.b.l & FLAG_CF );
+ cpustate->sr.b.l &= ~ FLAG_CF;
+ }
+ cpustate->cycles += 2;
+ }
+
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF );
+ cpustate->sr.b.l |= ( ( a >> 24 ) & FLAG_SF ) | ( a ? 0 : FLAG_ZF );
+ parity32( cpustate, a );
+
+ return a;
+}
+
+INLINE UINT8 rlc8( tlcs900_state *cpustate, UINT8 a, UINT8 s )
+{
+ UINT8 count = ( s & 0x0f ) ? ( s & 0x0f ) : 16;
+
+ for ( ; count > 0; count-- )
+ {
+ a = ( a << 1 ) | ( ( a & 0x80 ) ? 1 : 0 );
+ }
+
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF | FLAG_CF );
+ cpustate->sr.b.l |= ( a & FLAG_SF ) | ( a ? 0 : FLAG_ZF ) | ( a & FLAG_CF );
+ parity8( cpustate, a );
+
+ return a;
+}
+
+
+INLINE UINT16 rlc16( tlcs900_state *cpustate, UINT16 a, UINT8 s )
+{
+ UINT8 count = ( s & 0x0f ) ? ( s & 0x0f ) : 16;
+
+ for ( ; count > 0; count-- )
+ {
+ a = ( a << 1 ) | ( ( a & 0x8000 ) ? 1 : 0 );
+ }
+
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF | FLAG_CF );
+ cpustate->sr.b.l |= ( ( a >> 8 ) & FLAG_SF ) | ( a ? 0 : FLAG_ZF ) | ( a & FLAG_CF );
+ parity16( cpustate, a );
+
+ return a;
+}
+
+
+INLINE UINT32 rlc32( tlcs900_state *cpustate, UINT32 a, UINT8 s )
+{
+ UINT8 count = ( s & 0x0f ) ? ( s & 0x0f ) : 16;
+
+ for ( ; count > 0; count-- )
+ {
+ a = ( a << 1 ) | ( ( a & 0x80000000 ) ? 1 : 0 );
+ cpustate->cycles += 2;
+ }
+
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF | FLAG_CF );
+ cpustate->sr.b.l |= ( ( a >> 24 ) & FLAG_SF ) | ( a ? 0 : FLAG_ZF ) | ( a & FLAG_CF );
+ parity32( cpustate, a );
+
+ return a;
+}
+
+
+INLINE UINT8 rr8( tlcs900_state *cpustate, UINT8 a, UINT8 s )
+{
+ UINT8 count = ( s & 0x0f ) ? ( s & 0x0f ) : 16;
+
+ for ( ; count > 0; count-- )
+ {
+ if ( cpustate->sr.b.l & FLAG_CF )
+ {
+ cpustate->sr.b.l = ( cpustate->sr.b.l & ~ FLAG_CF ) | ( a & FLAG_CF );
+ a = ( a >> 1 ) | 0x80;
+ }
+ else
+ {
+ cpustate->sr.b.l = ( cpustate->sr.b.l & ~ FLAG_CF ) | ( a & FLAG_CF );
+ a = ( a >> 1 );
+ }
+ }
+
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF );
+ cpustate->sr.b.l |= ( a & FLAG_SF ) | ( a ? 0 : FLAG_ZF );
+ parity8( cpustate, a );
+
+ return a;
+}
+
+
+INLINE UINT16 rr16( tlcs900_state *cpustate, UINT16 a, UINT8 s )
+{
+ UINT8 count = ( s & 0x0f ) ? ( s & 0x0f ) : 16;
+
+ for ( ; count > 0; count-- )
+ {
+ if ( cpustate->sr.b.l & FLAG_CF )
+ {
+ cpustate->sr.b.l = ( cpustate->sr.b.l & ~ FLAG_CF ) | ( a & FLAG_CF );
+ a = ( a >> 1 ) | 0x8000;
+ }
+ else
+ {
+ cpustate->sr.b.l = ( cpustate->sr.b.l & ~ FLAG_CF ) | ( a & FLAG_CF );
+ a = ( a >> 1 );
+ }
+ }
+
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF );
+ cpustate->sr.b.l |= ( ( a >> 8 ) & FLAG_SF ) | ( a ? 0 : FLAG_ZF );
+ parity16( cpustate, a );
+
+ return a;
+}
+
+
+INLINE UINT32 rr32( tlcs900_state *cpustate, UINT32 a, UINT8 s )
+{
+ UINT8 count = ( s & 0x0f ) ? ( s & 0x0f ) : 16;
+
+ for ( ; count > 0; count-- )
+ {
+ if ( cpustate->sr.b.l & FLAG_CF )
+ {
+ cpustate->sr.b.l = ( cpustate->sr.b.l & ~ FLAG_CF ) | ( a & FLAG_CF );
+ a = ( a >> 1 ) | 0x80000000;
+ }
+ else
+ {
+ cpustate->sr.b.l = ( cpustate->sr.b.l & ~ FLAG_CF ) | ( a & FLAG_CF );
+ a = ( a >> 1 );
+ }
+ cpustate->cycles += 2;
+ }
+
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF );
+ cpustate->sr.b.l |= ( ( a >> 24 ) & FLAG_SF ) | ( a ? 0 : FLAG_ZF );
+ parity32( cpustate, a );
+
+ return a;
+}
+
+
+INLINE UINT8 rrc8( tlcs900_state *cpustate, UINT8 a, UINT8 s )
+{
+ UINT8 count = ( s & 0x0f ) ? ( s & 0x0f ) : 16;
+
+ for ( ; count > 0; count-- )
+ {
+ a = ( a >> 1 ) | ( ( a & 0x01 ) ? 0x80 : 0 );
+ }
+
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF | FLAG_CF );
+ cpustate->sr.b.l |= ( ( a & FLAG_SF ) ? FLAG_CF | FLAG_SF : 0 ) | ( a ? 0 : FLAG_ZF );
+ parity8( cpustate, a );
+
+ return a;
+}
+
+
+INLINE UINT16 rrc16( tlcs900_state *cpustate, UINT16 a, UINT8 s )
+{
+ UINT8 count = ( s & 0x0f ) ? ( s & 0x0f ) : 16;
+
+ for ( ; count > 0; count-- )
+ {
+ a = ( a >> 1 ) | ( ( a & 0x0001 ) ? 0x8000 : 0 );
+ }
+
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF | FLAG_CF );
+ cpustate->sr.b.l |= ( ( ( a >> 8 ) & FLAG_SF ) ? FLAG_CF | FLAG_SF : 0 ) | ( a ? 0 : FLAG_ZF );
+ parity16( cpustate, a );
+
+ return a;
+}
+
+
+INLINE UINT32 rrc32( tlcs900_state *cpustate, UINT32 a, UINT8 s )
+{
+ UINT8 count = ( s & 0x0f ) ? ( s & 0x0f ) : 16;
+
+ for ( ; count > 0; count-- )
+ {
+ a = ( a >> 1 ) | ( ( a & 0x00000001 ) ? 0x80000000 : 0 );
+ cpustate->cycles += 2;
+ }
+
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF | FLAG_CF );
+ cpustate->sr.b.l |= ( ( ( a >> 24 ) & FLAG_SF ) ? FLAG_CF | FLAG_SF : 0 ) | ( a ? 0 : FLAG_ZF );
+ parity32( cpustate, a );
+
+ return a;
+}
+
+
+INLINE UINT8 sla8( tlcs900_state *cpustate, UINT8 a, UINT8 s )
+{
+ UINT8 count = ( s & 0x0f ) ? ( s & 0x0f ) : 16;
+
+ for ( ; count > 0; count-- )
+ {
+ cpustate->sr.b.l = ( cpustate->sr.b.l & ~ FLAG_CF ) | ( ( a & 0x80 ) ? FLAG_CF : 0 );
+ a = ( a << 1 );
+ }
+
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF );
+ cpustate->sr.b.l |= ( a & FLAG_SF ) | ( a ? 0 : FLAG_ZF );
+ parity8( cpustate, a );
+
+ return a;
+}
+
+
+INLINE UINT16 sla16( tlcs900_state *cpustate, UINT16 a, UINT8 s )
+{
+ UINT8 count = ( s & 0x0f ) ? ( s & 0x0f ) : 16;
+
+ for ( ; count > 0; count-- )
+ {
+ cpustate->sr.b.l = ( cpustate->sr.b.l & ~ FLAG_CF ) | ( ( a & 0x8000 ) ? FLAG_CF : 0 );
+ a = ( a << 1 );
+ }
+
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF );
+ cpustate->sr.b.l |= ( ( a >> 8 ) & FLAG_SF ) | ( a ? 0 : FLAG_ZF );
+ parity16( cpustate, a );
+
+ return a;
+}
+
+
+INLINE UINT32 sla32( tlcs900_state *cpustate, UINT32 a, UINT8 s )
+{
+ UINT8 count = ( s & 0x0f ) ? ( s & 0x0f ) : 16;
+
+ for ( ; count > 0; count-- )
+ {
+ cpustate->sr.b.l = ( cpustate->sr.b.l & ~ FLAG_CF ) | ( ( a & 0x80000000 ) ? FLAG_CF : 0 );
+ a = ( a << 1 );
+ cpustate->cycles += 2;
+ }
+
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF );
+ cpustate->sr.b.l |= ( ( a >> 24 ) & FLAG_SF ) | ( a ? 0 : FLAG_ZF );
+ parity32( cpustate, a );
+
+ return a;
+}
+
+
+INLINE UINT8 sra8( tlcs900_state *cpustate, UINT8 a, UINT8 s )
+{
+ UINT8 count = ( s & 0x0f ) ? ( s & 0x0f ) : 16;
+
+ for ( ; count > 0; count-- )
+ {
+ cpustate->sr.b.l = ( cpustate->sr.b.l & ~ FLAG_CF ) | ( a & FLAG_CF );
+ a = ( a & 0x80 ) | ( a >> 1 );
+ }
+
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF );
+ cpustate->sr.b.l |= ( a & FLAG_SF ) | ( a ? 0 : FLAG_ZF );
+ parity8( cpustate, a );
+
+ return a;
+}
+
+
+INLINE UINT16 sra16( tlcs900_state *cpustate, UINT16 a, UINT8 s )
+{
+ UINT8 count = ( s & 0x0f ) ? ( s & 0x0f ) : 16;
+
+ for ( ; count > 0; count-- )
+ {
+ cpustate->sr.b.l = ( cpustate->sr.b.l & ~ FLAG_CF ) | ( a & FLAG_CF );
+ a = ( a & 0x8000 ) | ( a >> 1 );
+ }
+
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF );
+ cpustate->sr.b.l |= ( ( a >> 8 ) & FLAG_SF ) | ( a ? 0 : FLAG_ZF );
+ parity16( cpustate, a );
+
+ return a;
+}
+
+
+INLINE UINT32 sra32( tlcs900_state *cpustate, UINT32 a, UINT8 s )
+{
+ UINT8 count = ( s & 0x0f ) ? ( s & 0x0f ) : 16;
+
+ for ( ; count > 0; count-- )
+ {
+ cpustate->sr.b.l = ( cpustate->sr.b.l & ~ FLAG_CF ) | ( a & FLAG_CF );
+ a = ( a & 0x80000000 ) | ( a >> 1 );
+ cpustate->cycles += 2;
+ }
+
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF );
+ cpustate->sr.b.l |= ( ( a >> 24 ) & FLAG_SF ) | ( a ? 0 : FLAG_ZF );
+ parity32( cpustate, a );
+
+ return a;
+}
+
+
+INLINE UINT8 srl8( tlcs900_state *cpustate, UINT8 a, UINT8 s )
+{
+ UINT8 count = ( s & 0x0f ) ? ( s & 0x0f ) : 16;
+
+ for ( ; count > 0; count-- )
+ {
+ cpustate->sr.b.l = ( cpustate->sr.b.l & ~ FLAG_CF ) | ( a & FLAG_CF );
+ a = ( a >> 1 );
+ }
+
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF );
+ cpustate->sr.b.l |= ( a & FLAG_SF ) | ( a ? 0 : FLAG_ZF );
+ parity8( cpustate, a );
+
+ return a;
+}
+
+
+INLINE UINT16 srl16( tlcs900_state *cpustate, UINT16 a, UINT8 s )
+{
+ UINT8 count = ( s & 0x0f ) ? ( s & 0x0f ) : 16;
+
+ for ( ; count > 0; count-- )
+ {
+ cpustate->sr.b.l = ( cpustate->sr.b.l & ~ FLAG_CF ) | ( a & FLAG_CF );
+ a = ( a >> 1 );
+ }
+
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF );
+ cpustate->sr.b.l |= ( ( a >> 8 ) & FLAG_SF ) | ( a ? 0 : FLAG_ZF );
+ parity16( cpustate, a );
+
+ return a;
+}
+
+
+INLINE UINT32 srl32( tlcs900_state *cpustate, UINT32 a, UINT8 s )
+{
+ UINT8 count = ( s & 0x0f ) ? ( s & 0x0f ) : 16;
+
+ for ( ; count > 0; count-- )
+ {
+ cpustate->sr.b.l = ( cpustate->sr.b.l & ~ FLAG_CF ) | ( a & FLAG_CF );
+ a = ( a >> 1 );
+ cpustate->cycles += 2;
+ }
+
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF );
+ cpustate->sr.b.l |= ( ( a >> 24 ) & FLAG_SF ) | ( a ? 0 : FLAG_ZF );
+ parity32( cpustate, a );
+
+ return a;
+}
+
+
+INLINE UINT16 div8( tlcs900_state *cpustate, UINT16 a, UINT8 b )
+{
+ ldiv_t result;
+
+ if ( !b )
+ {
+ cpustate->sr.b.l |= FLAG_VF;
+ return ( a << 8 ) | ( ( a >> 8 ) ^ 0xff );
+ }
+
+ if ( a >= ( 0x0200 * b ) ) {
+ UINT16 diff = a - ( 0x0200 * b );
+ UINT16 range = 0x100 - b;
+
+ result = ldiv( diff, range );
+ result.quot = 0x1ff - result.quot;
+ result.rem = result.rem + b;
+ }
+ else
+ {
+ result = ldiv( a, b );
+ }
+
+ if ( result.quot > 0xff )
+ cpustate->sr.b.l |= FLAG_VF;
+ else
+ cpustate->sr.b.l &= ~ FLAG_VF;
+
+ return ( result.quot & 0xff ) | ( ( result.rem & 0xff ) << 8 );
+}
+
+
+INLINE UINT32 div16( tlcs900_state *cpustate, UINT32 a, UINT16 b )
+{
+ ldiv_t result;
+
+ if ( !b )
+ {
+ cpustate->sr.b.l |= FLAG_VF;
+ return ( a << 16 ) | ( ( a >> 16 ) ^ 0xffff );
+ }
+
+// if ( a >= ( 0x02000000 * b ) ) {
+// UINT32 diff = a - ( 0x02000000 * b );
+// UINT32 range = 0x1000000 - b;
+//
+// result = ldiv( diff, range );
+// result.quot = 0x1ffffff - result.quot;
+// result.rem = result.rem + b;
+// }
+// else
+// {
+ result = ldiv( a, b );
+// }
+
+ if ( result.quot > 0xffff )
+ cpustate->sr.b.l |= FLAG_VF;
+ else
+ cpustate->sr.b.l &= ~ FLAG_VF;
+
+ return ( result.quot & 0xffff ) | ( ( result.rem & 0xffff ) << 16 );
+}
+
+
+INLINE UINT16 divs8( tlcs900_state *cpustate, INT16 a, INT8 b )
+{
+ ldiv_t result;
+
+ if ( !b )
+ {
+ cpustate->sr.b.l |= FLAG_VF;
+ return ( a << 8 ) | ( ( a >> 8 ) ^ 0xff );
+ }
+
+ result = ldiv( a, b );
+
+ if ( result.quot > 0xff )
+ cpustate->sr.b.l |= FLAG_VF;
+ else
+ cpustate->sr.b.l &= ~ FLAG_VF;
+
+ return ( result.quot & 0xff ) | ( ( result.rem & 0xff ) << 8 );
+}
+
+
+INLINE UINT32 divs16( tlcs900_state *cpustate, INT32 a, INT16 b )
+{
+ ldiv_t result;
+
+ if ( !b )
+ {
+ cpustate->sr.b.l |= FLAG_VF;
+ return ( a << 16 ) | ( ( a >> 16 ) ^ 0xffff );
+ }
+
+ result = ldiv( a, b );
+
+ if ( result.quot > 0xffff )
+ cpustate->sr.b.l |= FLAG_VF;
+ else
+ cpustate->sr.b.l &= ~ FLAG_VF;
+
+ return ( result.quot & 0xffff ) | ( ( result.rem & 0xffff ) << 16 );
+}
+
+
+static void _ADCBMI(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea1.d, adc8( cpustate, RDMEM( cpustate->ea1.d ), cpustate->imm2.b.l ) );
+}
+
+
+static void _ADCBMR(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea1.d, adc8( cpustate, RDMEM( cpustate->ea1.d ), *cpustate->p2_reg8 ) );
+}
+
+
+static void _ADCBRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = adc8( cpustate, *cpustate->p1_reg8, cpustate->imm2.b.l );
+}
+
+
+static void _ADCBRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = adc8( cpustate, *cpustate->p1_reg8, RDMEM( cpustate->ea2.d ) );
+}
+
+
+static void _ADCBRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = adc8( cpustate, *cpustate->p1_reg8, *cpustate->p2_reg8 );
+}
+
+
+static void _ADCWMI(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea1.d, adc16( cpustate, RDMEMW( cpustate->ea1.d ), cpustate->imm2.w.l ) );
+}
+
+
+static void _ADCWMR(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea1.d, adc16( cpustate, RDMEMW( cpustate->ea1.d ), *cpustate->p2_reg16 ) );
+}
+
+
+static void _ADCWRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = adc16( cpustate, *cpustate->p1_reg16, cpustate->imm2.w.l );
+}
+
+
+static void _ADCWRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = adc16( cpustate, *cpustate->p1_reg16, RDMEMW( cpustate->ea2.d ) );
+}
+
+
+static void _ADCWRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = adc16( cpustate, *cpustate->p1_reg16, *cpustate->p2_reg16 );
+}
+
+
+static void _ADCLMR(tlcs900_state *cpustate)
+{
+ WRMEML( cpustate->ea1.d, adc32( cpustate, RDMEML( cpustate->ea1.d ), *cpustate->p2_reg32 ) );
+}
+
+
+static void _ADCLRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = adc32( cpustate, *cpustate->p1_reg32, cpustate->imm2.d );
+}
+
+
+static void _ADCLRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = adc32( cpustate, *cpustate->p1_reg32, RDMEML( cpustate->ea2.d ) );
+}
+
+
+static void _ADCLRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = adc32( cpustate, *cpustate->p1_reg32, *cpustate->p2_reg32 );
+}
+
+
+static void _ADDBMI(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea1.d, add8( cpustate, RDMEM( cpustate->ea1.d ), cpustate->imm2.b.l ) );
+}
+
+
+static void _ADDBMR(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea1.d, add8( cpustate, RDMEM( cpustate->ea1.d ), *cpustate->p2_reg8 ) );
+}
+
+
+static void _ADDBRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = add8( cpustate, *cpustate->p1_reg8, cpustate->imm2.b.l );
+}
+
+
+static void _ADDBRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = add8( cpustate, *cpustate->p1_reg8, RDMEM( cpustate->ea2.d ) );
+}
+
+
+static void _ADDBRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = add8( cpustate, *cpustate->p1_reg8, *cpustate->p2_reg8 );
+}
+
+
+static void _ADDWMI(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea1.d, add16( cpustate, RDMEMW( cpustate->ea1.d ), cpustate->imm2.w.l ) );
+}
+
+
+static void _ADDWMR(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea1.d, add16( cpustate, RDMEMW( cpustate->ea1.d ), *cpustate->p2_reg16 ) );
+}
+
+
+static void _ADDWRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = add16( cpustate, *cpustate->p1_reg16, cpustate->imm2.w.l );
+}
+
+
+static void _ADDWRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = add16( cpustate, *cpustate->p1_reg16, RDMEMW( cpustate->ea2.d ) );
+}
+
+
+static void _ADDWRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = add16( cpustate, *cpustate->p1_reg16, *cpustate->p2_reg16 );
+}
+
+
+static void _ADDLMR(tlcs900_state *cpustate)
+{
+ WRMEML( cpustate->ea1.d, add32( cpustate, RDMEML( cpustate->ea1.d ), *cpustate->p2_reg32 ) );
+}
+
+
+static void _ADDLRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = add32( cpustate, *cpustate->p1_reg32, cpustate->imm2.d );
+}
+
+
+static void _ADDLRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = add32( cpustate, *cpustate->p1_reg32, RDMEML( cpustate->ea2.d ) );
+}
+
+
+static void _ADDLRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = add32( cpustate, *cpustate->p1_reg32, *cpustate->p2_reg32 );
+}
+
+
+static void _ANDBMI(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea1.d, and8( cpustate, RDMEM( cpustate->ea1.d ), cpustate->imm2.b.l ) );
+}
+
+
+static void _ANDBMR(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea1.d, and8( cpustate, RDMEM( cpustate->ea1.d ), *cpustate->p2_reg8 ) );
+}
+
+
+static void _ANDBRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = and8( cpustate, *cpustate->p1_reg8, cpustate->imm2.b.l );
+}
+
+
+static void _ANDBRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = and8( cpustate, *cpustate->p1_reg8, RDMEM( cpustate->ea2.d ) );
+}
+
+
+static void _ANDBRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = and8( cpustate, *cpustate->p1_reg8, *cpustate->p2_reg8 );
+}
+
+
+static void _ANDWMI(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea1.d, and16( cpustate, RDMEMW( cpustate->ea1.d ), cpustate->imm2.w.l ) );
+}
+
+
+static void _ANDWMR(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea1.d, and16( cpustate, RDMEMW( cpustate->ea1.d ), *cpustate->p2_reg16 ) );
+}
+
+
+static void _ANDWRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = and16( cpustate, *cpustate->p1_reg16, cpustate->imm2.w.l );
+}
+
+
+static void _ANDWRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = and16( cpustate, *cpustate->p1_reg16, RDMEMW( cpustate->ea2.d ) );
+}
+
+
+static void _ANDWRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = and16( cpustate, *cpustate->p1_reg16, *cpustate->p2_reg16 );
+}
+
+
+static void _ANDLMR(tlcs900_state *cpustate)
+{
+ WRMEML( cpustate->ea1.d, and32( cpustate, RDMEML( cpustate->ea1.d ), *cpustate->p2_reg32 ) );
+}
+
+
+static void _ANDLRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = and32( cpustate, *cpustate->p1_reg32, cpustate->imm2.d );
+}
+
+
+static void _ANDLRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = and32( cpustate, *cpustate->p1_reg32, RDMEML( cpustate->ea2.d ) );
+}
+
+
+static void _ANDLRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = and32( cpustate, *cpustate->p1_reg32, *cpustate->p2_reg32 );
+}
+
+
+static void _ANDCFBIM(tlcs900_state *cpustate)
+{
+ andcf8( cpustate, cpustate->imm1.b.l, RDMEM( cpustate->ea2.d ) );
+}
+
+
+static void _ANDCFBIR(tlcs900_state *cpustate)
+{
+ andcf8( cpustate, cpustate->imm1.b.l, *cpustate->p2_reg8 );
+}
+
+
+static void _ANDCFBRM(tlcs900_state *cpustate)
+{
+ andcf8( cpustate, *cpustate->p1_reg8, RDMEM( cpustate->ea2.d ) );
+}
+
+
+static void _ANDCFBRR(tlcs900_state *cpustate)
+{
+ andcf8( cpustate, *cpustate->p1_reg8, *cpustate->p2_reg8 );
+}
+
+
+static void _ANDCFWIR(tlcs900_state *cpustate)
+{
+ andcf16( cpustate, cpustate->imm1.b.l, *cpustate->p2_reg16 );
+}
+
+
+static void _ANDCFWRR(tlcs900_state *cpustate)
+{
+ andcf16( cpustate, *cpustate->p1_reg8, *cpustate->p2_reg16 );
+}
+
+
+static void _BITBIM(tlcs900_state *cpustate)
+{
+ cpustate->sr.b.l &= ~ ( FLAG_ZF | FLAG_NF );
+ if ( RDMEM( cpustate->ea2.d ) & ( 1 << ( cpustate->imm1.b.l & 0x07 ) ) )
+ cpustate->sr.b.l |= FLAG_HF;
+ else
+ cpustate->sr.b.l |= FLAG_HF | FLAG_ZF;
+}
+
+
+static void _BITBIR(tlcs900_state *cpustate)
+{
+ cpustate->sr.b.l &= ~ ( FLAG_ZF | FLAG_NF );
+ if ( *cpustate->p2_reg8 & ( 1 << ( cpustate->imm1.b.l & 0x07 ) ) )
+ cpustate->sr.b.l |= FLAG_HF;
+ else
+ cpustate->sr.b.l |= FLAG_HF | FLAG_ZF;
+}
+
+
+static void _BITWIR(tlcs900_state *cpustate)
+{
+ cpustate->sr.b.l &= ~ ( FLAG_ZF | FLAG_NF );
+ if ( *cpustate->p2_reg16 & ( 1 << ( cpustate->imm1.b.l & 0x0f ) ) )
+ cpustate->sr.b.l |= FLAG_HF;
+ else
+ cpustate->sr.b.l |= FLAG_HF | FLAG_ZF;
+}
+
+
+static void _BS1BRR(tlcs900_state *cpustate)
+{
+ UINT16 r = *cpustate->p2_reg16;
+
+ if ( r )
+ {
+ cpustate->sr.b.l &= ~ FLAG_VF;
+ *cpustate->p1_reg8 = 15;
+ while( r < 0x8000 )
+ {
+ r <<= 1;
+ *cpustate->p1_reg8 -= 1;
+ }
+ }
+ else
+ cpustate->sr.b.l |= FLAG_VF;
+}
+
+
+static void _BS1FRR(tlcs900_state *cpustate)
+{
+ UINT16 r = *cpustate->p2_reg16;
+
+ if ( r )
+ {
+ cpustate->sr.b.l &= ~ FLAG_VF;
+ *cpustate->p1_reg8 = 0;
+ while( ! ( r & 0x0001 ) )
+ {
+ r >>= 1;
+ *cpustate->p1_reg8 += 1;
+ }
+ }
+ else
+ cpustate->sr.b.l |= FLAG_VF;
+}
+
+
+static void _CALLI(tlcs900_state *cpustate)
+{
+ cpustate->xssp.d -= 4;
+ WRMEML( cpustate->xssp.d, cpustate->pc.d );
+ cpustate->pc.d = cpustate->imm1.d;
+}
+
+
+static void _CALLM(tlcs900_state *cpustate)
+{
+ if ( condition_true( cpustate, cpustate->op ) )
+ {
+ cpustate->xssp.d -= 4;
+ WRMEML( cpustate->xssp.d, cpustate->pc.d );
+ cpustate->pc.d = cpustate->ea2.d;
+ cpustate->cycles += 6;
+ }
+}
+
+
+static void _CALR(tlcs900_state *cpustate)
+{
+ cpustate->xssp.d -= 4;
+ WRMEML( cpustate->xssp.d, cpustate->pc.d );
+ cpustate->pc.d = cpustate->ea1.d;
+}
+
+
+static void _CCF(tlcs900_state *cpustate)
+{
+ cpustate->sr.b.l &= ~ FLAG_NF;
+ cpustate->sr.b.l ^= FLAG_CF;
+}
+
+
+static void _CHGBIM(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea2.d, RDMEM( cpustate->ea2.d ) ^ ( 1 << ( cpustate->imm1.b.l & 0x07 ) ) );
+}
+
+
+static void _CHGBIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg8 ^= ( 1 << ( cpustate->imm1.b.l & 0x07 ) );
+}
+
+
+static void _CHGWIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg16 ^= ( 1 << ( cpustate->imm1.b.l & 0x0f ) );
+}
+
+
+static void _CPBMI(tlcs900_state *cpustate)
+{
+ sub8( cpustate, RDMEM( cpustate->ea1.d ), cpustate->imm2.b.l );
+}
+
+
+static void _CPBMR(tlcs900_state *cpustate)
+{
+ sub8( cpustate, RDMEM( cpustate->ea1.d ), *cpustate->p2_reg8 );
+}
+
+
+static void _CPBRI(tlcs900_state *cpustate)
+{
+ sub8( cpustate, *cpustate->p1_reg8, cpustate->imm2.b.l );
+}
+
+
+static void _CPBRM(tlcs900_state *cpustate)
+{
+ sub8( cpustate, *cpustate->p1_reg8, RDMEM( cpustate->ea2.d ) );
+}
+
+
+static void _CPBRR(tlcs900_state *cpustate)
+{
+ sub8( cpustate, *cpustate->p1_reg8, *cpustate->p2_reg8 );
+}
+
+
+static void _CPWMI(tlcs900_state *cpustate)
+{
+ sub16( cpustate, RDMEMW( cpustate->ea1.d ), cpustate->imm2.w.l );
+}
+
+
+static void _CPWMR(tlcs900_state *cpustate)
+{
+ sub16( cpustate, RDMEMW( cpustate->ea1.d ), *cpustate->p2_reg16 );
+}
+
+
+static void _CPWRI(tlcs900_state *cpustate)
+{
+ sub16( cpustate, *cpustate->p1_reg16, cpustate->imm2.w.l );
+}
+
+
+static void _CPWRM(tlcs900_state *cpustate)
+{
+ sub16( cpustate, *cpustate->p1_reg16, RDMEMW( cpustate->ea2.d ) );
+}
+
+
+static void _CPWRR(tlcs900_state *cpustate)
+{
+ sub16( cpustate, *cpustate->p1_reg16, *cpustate->p2_reg16 );
+}
+
+
+static void _CPLMR(tlcs900_state *cpustate)
+{
+ sub32( cpustate, RDMEML( cpustate->ea1.d ), *cpustate->p2_reg32 );
+}
+
+
+static void _CPLRI(tlcs900_state *cpustate)
+{
+ sub32( cpustate, *cpustate->p1_reg32, cpustate->imm2.d );
+}
+
+
+static void _CPLRM(tlcs900_state *cpustate)
+{
+ sub32( cpustate, *cpustate->p1_reg32, RDMEML( cpustate->ea2.d ) );
+}
+
+
+static void _CPLRR(tlcs900_state *cpustate)
+{
+ sub32( cpustate, *cpustate->p1_reg32, *cpustate->p2_reg32 );
+}
+
+
+static void _CPD(tlcs900_state *cpustate)
+{
+ UINT8 result = *get_reg8_current( cpustate, 1 ) - RDMEM( *cpustate->p2_reg32 );
+ UINT16 *bc = get_reg16_current( cpustate, 1 );
+
+ *cpustate->p2_reg32 -= 1;
+ *bc -= 1;
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF );
+ cpustate->sr.b.l |= ( result & FLAG_SF ) | ( result ? FLAG_NF : FLAG_NF | FLAG_ZF ) |
+ ( *bc ? FLAG_VF : 0 );
+}
+
+
+static void _CPDR(tlcs900_state *cpustate)
+{
+ _CPD( cpustate );
+
+ if ( ( cpustate->sr.b.l & ( FLAG_ZF | FLAG_VF ) ) == FLAG_VF )
+ {
+ cpustate->pc.d -= 2;
+ cpustate->cycles += 4;
+ }
+}
+
+
+static void _CPDW(tlcs900_state *cpustate)
+{
+ UINT16 result = *get_reg16_current( cpustate, 0 ) - RDMEMW( *cpustate->p2_reg32 );
+ UINT16 *bc = get_reg16_current( cpustate, 1 );
+
+ *cpustate->p2_reg32 -= 2;
+ *bc -= 1;
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF );
+ cpustate->sr.b.l |= ( ( result >> 8 ) & FLAG_SF ) | ( result ? FLAG_NF : FLAG_NF | FLAG_ZF ) |
+ ( *bc ? FLAG_VF : 0 );
+}
+
+
+static void _CPDRW(tlcs900_state *cpustate)
+{
+ _CPDW( cpustate );
+
+ if ( ( cpustate->sr.b.l & ( FLAG_ZF | FLAG_VF ) ) == FLAG_VF )
+ {
+ cpustate->pc.d -= 2;
+ cpustate->cycles += 4;
+ }
+}
+
+
+static void _CPI(tlcs900_state *cpustate)
+{
+ UINT8 result = *get_reg8_current( cpustate, 1 ) - RDMEM( *cpustate->p2_reg32 );
+ UINT16 *bc = get_reg16_current( cpustate, 1 );
+
+ *cpustate->p2_reg32 += 1;
+ *bc -= 1;
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF );
+ cpustate->sr.b.l |= ( result & FLAG_SF ) | ( result ? FLAG_NF : FLAG_NF | FLAG_ZF ) |
+ ( *bc ? FLAG_VF : 0 );
+}
+
+
+static void _CPIR(tlcs900_state *cpustate)
+{
+ _CPI( cpustate );
+
+ if ( ( cpustate->sr.b.l & ( FLAG_ZF | FLAG_VF ) ) == FLAG_VF )
+ {
+ cpustate->pc.d -= 2;
+ cpustate->cycles += 4;
+ }
+}
+
+
+static void _CPIW(tlcs900_state *cpustate)
+{
+ UINT16 result = *get_reg16_current( cpustate, 0 ) - RDMEMW( *cpustate->p2_reg32 );
+ UINT16 *bc = get_reg16_current( cpustate, 1 );
+
+ *cpustate->p2_reg32 += 2;
+ *bc -= 1;
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF );
+ cpustate->sr.b.l |= ( ( result >> 8 ) & FLAG_SF ) | ( result ? FLAG_NF : FLAG_NF | FLAG_ZF ) |
+ ( *bc ? FLAG_VF : 0 );
+}
+
+
+static void _CPIRW(tlcs900_state *cpustate)
+{
+ _CPIW( cpustate );
+
+ if ( ( cpustate->sr.b.l & ( FLAG_ZF | FLAG_VF ) ) == FLAG_VF )
+ {
+ cpustate->pc.d -= 2;
+ cpustate->cycles += 4;
+ }
+}
+
+
+static void _CPLBR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = ~ *cpustate->p1_reg8;
+ cpustate->sr.b.l |= FLAG_HF | FLAG_NF;
+}
+
+
+static void _CPLWR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = ~ *cpustate->p1_reg16;
+ cpustate->sr.b.l |= FLAG_HF | FLAG_NF;
+}
+
+
+static void _DAABR(tlcs900_state *cpustate)
+{
+ UINT8 oldval = *cpustate->p1_reg8;
+ UINT8 fixval = 0;
+ UINT8 carry = 0;
+ UINT8 high = *cpustate->p1_reg8 & 0xf0;
+ UINT8 low = *cpustate->p1_reg8 & 0x0f;
+
+ if ( cpustate->sr.b.l & FLAG_CF )
+ {
+ if ( cpustate->sr.b.l & FLAG_HF )
+ {
+ fixval = 0x66;
+ }
+ else
+ {
+ if ( low < 0x0a )
+ fixval = 0x60;
+ else
+ fixval = 0x66;
+ }
+ carry = 1;
+ }
+ else
+ {
+ if ( cpustate->sr.b.l & FLAG_HF )
+ {
+ if ( *cpustate->p1_reg8 < 0x9a )
+ fixval = 0x06;
+ else
+ fixval = 0x66;
+ }
+ else
+ {
+ if ( high < 0x90 && low > 0x09 )
+ fixval = 0x06;
+ else if ( high > 0x80 && low > 0x09 )
+ fixval = 0x66;
+ else if ( high > 0x90 && low < 0x0a )
+ fixval = 0x60;
+ }
+ }
+ cpustate->sr.b.l &= ~ ( FLAG_VF | FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_CF );
+ if ( cpustate->sr.b.l & FLAG_NF )
+ {
+ /* after SUB, SBC, or NEG operation */
+ *cpustate->p1_reg8 -= fixval;
+ cpustate->sr.b.l |= ( ( *cpustate->p1_reg8 > oldval || carry ) ? FLAG_CF : 0 );
+ }
+ else
+ {
+ /* after ADD or ADC operation */
+ *cpustate->p1_reg8 += fixval;
+ cpustate->sr.b.l |= ( ( *cpustate->p1_reg8 < oldval || carry ) ? FLAG_CF : 0 );
+ }
+ cpustate->sr.b.l |= ( *cpustate->p1_reg8 & FLAG_SF ) | ( *cpustate->p1_reg8 ? 0 : FLAG_ZF ) |
+ ( ( ( oldval ^ fixval ) ^ *cpustate->p1_reg8 ) & FLAG_HF );
+
+ parity8( cpustate, *cpustate->p1_reg8 );
+}
+
+
+static void _DB(tlcs900_state *cpustate)
+{
+ logerror("%08x: invalid or illegal instruction\n", cpustate->pc.d );
+}
+
+
+static void _DECBIM(tlcs900_state *cpustate)
+{
+ UINT8 cy = cpustate->sr.b.l & FLAG_CF;
+
+ WRMEM( cpustate->ea2.d, sub8( cpustate, RDMEM( cpustate->ea2.d ), cpustate->imm1.b.l ? cpustate->imm1.b.l : 8 ) );
+ cpustate->sr.b.l = ( cpustate->sr.b.l & ~ FLAG_CF ) | cy;
+}
+
+
+static void _DECBIR(tlcs900_state *cpustate)
+{
+ UINT8 cy = cpustate->sr.b.l & FLAG_CF;
+
+ *cpustate->p2_reg8 = sub8( cpustate, *cpustate->p2_reg8, cpustate->imm1.b.l ? cpustate->imm1.b.l : 8 );
+ cpustate->sr.b.l = ( cpustate->sr.b.l & ~ FLAG_CF ) | cy;
+}
+
+
+static void _DECWIM(tlcs900_state *cpustate)
+{
+ UINT8 cy = cpustate->sr.b.l & FLAG_CF;
+
+ WRMEMW( cpustate->ea2.d, sub16( cpustate, RDMEMW( cpustate->ea2.d ), cpustate->imm1.b.l ? cpustate->imm1.b.l : 8 ) );
+ cpustate->sr.b.l = ( cpustate->sr.b.l & ~ FLAG_CF ) | cy;
+}
+
+
+static void _DECWIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg16 -= cpustate->imm1.b.l ? cpustate->imm1.b.l : 8;
+}
+
+
+static void _DECLIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg32 -= cpustate->imm1.b.l ? cpustate->imm1.b.l : 8;
+}
+
+
+static void _DECF(tlcs900_state *cpustate)
+{
+ /* 0x03 for MAX mode, 0x07 for MIN mode */
+ cpustate->sr.b.h = ( cpustate->sr.b.h & 0xf8 ) | ( ( cpustate->sr.b.h - 1 ) & 0x07 );
+ cpustate->regbank = cpustate->sr.b.h & 0x03;
+}
+
+
+static void _DIVBRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = div8( cpustate, *cpustate->p1_reg16, cpustate->imm2.b.l );
+}
+
+
+static void _DIVBRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = div8( cpustate, *cpustate->p1_reg16, RDMEM( cpustate->ea2.d ) );
+}
+
+
+static void _DIVBRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = div8( cpustate, *cpustate->p1_reg16, *cpustate->p2_reg8 );
+}
+
+
+static void _DIVWRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = div16( cpustate, *cpustate->p1_reg32, cpustate->imm2.w.l );
+}
+
+
+static void _DIVWRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = div16( cpustate, *cpustate->p1_reg32, RDMEMW( cpustate->ea2.d ) );
+}
+
+
+static void _DIVWRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = div16( cpustate, *cpustate->p1_reg32, *cpustate->p2_reg16 );
+}
+
+
+static void _DIVSBRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = divs8( cpustate, *cpustate->p1_reg16, cpustate->imm2.b.l );
+}
+
+
+static void _DIVSBRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = divs8( cpustate, *cpustate->p1_reg16, RDMEM( cpustate->ea2.d ) );
+}
+
+
+static void _DIVSBRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = divs8( cpustate, *cpustate->p1_reg16, *cpustate->p2_reg8 );
+}
+
+
+static void _DIVSWRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = divs16( cpustate, *cpustate->p1_reg32, cpustate->imm2.w.l );
+}
+
+
+static void _DIVSWRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = divs16( cpustate, *cpustate->p1_reg32, RDMEMW( cpustate->ea2.d ) );
+}
+
+
+static void _DIVSWRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = divs16( cpustate, *cpustate->p1_reg32, *cpustate->p2_reg16 );
+}
+
+
+static void _DJNZB(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 -= 1;
+ if ( *cpustate->p1_reg8 )
+ {
+ cpustate->pc.d = cpustate->ea2.d;
+ cpustate->cycles += 4;
+ }
+}
+
+
+static void _DJNZW(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 -= 1;
+ if ( *cpustate->p1_reg16 )
+ {
+ cpustate->pc.d = cpustate->ea2.d;
+ cpustate->cycles += 4;
+ }
+}
+
+
+static void _EI(tlcs900_state *cpustate)
+{
+ cpustate->sr.b.h = ( cpustate->sr.b.h & 0x8f ) | ( ( cpustate->imm1.b.l & 0x07 ) << 4 );
+ cpustate->check_irqs = 1;
+}
+
+
+static void _EXBMR(tlcs900_state *cpustate)
+{
+ UINT8 i = RDMEM( cpustate->ea1.d );
+
+ WRMEM( cpustate->ea1.d, *cpustate->p2_reg8 );
+ *cpustate->p2_reg8 = i;
+}
+
+
+static void _EXBRR(tlcs900_state *cpustate)
+{
+ UINT8 i = *cpustate->p2_reg8;
+
+ *cpustate->p2_reg8 = *cpustate->p1_reg8;
+ *cpustate->p1_reg8 = i;
+}
+
+
+static void _EXWMR(tlcs900_state *cpustate)
+{
+ UINT16 i = RDMEMW( cpustate->ea1.d );
+
+ WRMEMW( cpustate->ea1.d, *cpustate->p2_reg16 );
+ *cpustate->p2_reg16 = i;
+}
+
+
+static void _EXWRR(tlcs900_state *cpustate)
+{
+ UINT16 i = *cpustate->p2_reg16;
+
+ *cpustate->p2_reg16 = *cpustate->p1_reg16;
+ *cpustate->p1_reg16 = i;
+}
+
+
+static void _EXTSWR(tlcs900_state *cpustate)
+{
+ if ( *cpustate->p1_reg16 & 0x0080 )
+ *cpustate->p1_reg16 |= 0xff00;
+ else
+ *cpustate->p1_reg16 &= 0x00ff;
+}
+
+
+static void _EXTSLR(tlcs900_state *cpustate)
+{
+ if ( *cpustate->p1_reg32 & 0x00008000 )
+ *cpustate->p1_reg32 |= 0xffff0000;
+ else
+ *cpustate->p1_reg32 &= 0x0000ffff;
+}
+
+
+static void _EXTZWR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 &= 0x00ff;
+}
+
+
+static void _EXTZLR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 &= 0x0000ffff;
+}
+
+
+static void _HALT(tlcs900_state *cpustate)
+{
+ cpustate->halted = 1;
+}
+
+
+static void _INCBIM(tlcs900_state *cpustate)
+{
+ UINT8 cy = cpustate->sr.b.l & FLAG_CF;
+
+ WRMEM( cpustate->ea2.d, add8( cpustate, RDMEM( cpustate->ea2.d ), cpustate->imm1.b.l ? cpustate->imm1.b.l : 8 ) );
+ cpustate->sr.b.l = ( cpustate->sr.b.l & ~ FLAG_CF ) | cy;
+}
+
+
+static void _INCBIR(tlcs900_state *cpustate)
+{
+ UINT8 cy = cpustate->sr.b.l & FLAG_CF;
+
+ *cpustate->p2_reg8 = add8( cpustate, *cpustate->p2_reg8, cpustate->imm1.b.l ? cpustate->imm1.b.l : 8 );
+ cpustate->sr.b.l = ( cpustate->sr.b.l & ~ FLAG_CF ) | cy;
+}
+
+
+static void _INCWIM(tlcs900_state *cpustate)
+{
+ UINT8 cy = cpustate->sr.b.l & FLAG_CF;
+
+ WRMEMW( cpustate->ea2.d, add16( cpustate, RDMEMW( cpustate->ea2.d ), cpustate->imm1.b.l ? cpustate->imm1.b.l : 8 ) );
+ cpustate->sr.b.l = ( cpustate->sr.b.l & ~ FLAG_CF ) | cy;
+}
+
+
+static void _INCWIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg16 += cpustate->imm1.b.l ? cpustate->imm1.b.l : 8;
+}
+
+
+static void _INCLIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg32 += cpustate->imm1.b.l ? cpustate->imm1.b.l : 8;
+}
+
+
+static void _INCF(tlcs900_state *cpustate)
+{
+ /* 0x03 for MAX mode, 0x07 for MIN mode */
+ cpustate->sr.b.h = ( cpustate->sr.b.h & 0xf8 ) | ( ( cpustate->sr.b.h + 1 ) & 0x07 );
+ cpustate->regbank = cpustate->sr.b.h & 0x03;
+}
+
+
+static void _JPI(tlcs900_state *cpustate)
+{
+ cpustate->pc.d = cpustate->imm1.d;
+}
+
+
+static void _JPM(tlcs900_state *cpustate)
+{
+ if ( condition_true( cpustate, cpustate->op ) )
+ {
+ cpustate->pc.d = cpustate->ea2.d;
+ cpustate->cycles += 4;
+ }
+}
+
+
+static void _JR(tlcs900_state *cpustate)
+{
+ if ( condition_true( cpustate, cpustate->op ) )
+ {
+ cpustate->pc.d = cpustate->ea2.d;
+ cpustate->cycles += 4;
+ }
+}
+
+
+static void _JRL(tlcs900_state *cpustate)
+{
+ if ( condition_true( cpustate, cpustate->op ) )
+ {
+ cpustate->pc.d = cpustate->ea2.d;
+ cpustate->cycles += 4;
+ }
+}
+
+
+static void _LDBMI(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea1.d, cpustate->imm2.b.l );
+}
+
+
+static void _LDBMM(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea1.d, RDMEM( cpustate->ea2.d ) );
+}
+
+
+static void _LDBMR(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea1.d, *cpustate->p2_reg8 );
+}
+
+
+static void _LDBRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = cpustate->imm2.b.l;
+}
+
+
+static void _LDBRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = RDMEM( cpustate->ea2.d );
+}
+
+
+static void _LDBRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = *cpustate->p2_reg8;
+}
+
+
+static void _LDWMI(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea1.d, cpustate->imm2.w.l );
+}
+
+
+static void _LDWMM(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea1.d, RDMEMW( cpustate->ea2.d ) );
+}
+
+
+static void _LDWMR(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea1.d, *cpustate->p2_reg16 );
+}
+
+
+static void _LDWRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = cpustate->imm2.w.l;
+}
+
+
+static void _LDWRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = RDMEMW( cpustate->ea2.d );
+}
+
+
+static void _LDWRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = *cpustate->p2_reg16;
+}
+
+
+static void _LDLRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = cpustate->imm2.d;
+}
+
+
+static void _LDLRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = RDMEML( cpustate->ea2.d );
+}
+
+
+static void _LDLRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = *cpustate->p2_reg32;
+}
+
+
+static void _LDLMR(tlcs900_state *cpustate)
+{
+ WRMEML( cpustate->ea1.d, *cpustate->p2_reg32 );
+}
+
+
+static void _LDAW(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = cpustate->ea2.w.l;
+}
+
+
+static void _LDAL(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = cpustate->ea2.d;
+}
+
+
+static void _LDCBRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = *cpustate->p2_reg8;
+}
+
+
+static void _LDCWRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = *cpustate->p2_reg16;
+}
+
+
+static void _LDCLRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = *cpustate->p2_reg32;
+}
+
+
+static void _LDCFBIM(tlcs900_state *cpustate)
+{
+ ldcf8( cpustate, cpustate->imm1.b.l, RDMEM( cpustate->ea2.d ) );
+}
+
+
+static void _LDCFBIR(tlcs900_state *cpustate)
+{
+ ldcf8( cpustate, cpustate->imm1.b.l, *cpustate->p2_reg8 );
+}
+
+
+static void _LDCFBRM(tlcs900_state *cpustate)
+{
+ ldcf8( cpustate, *cpustate->p1_reg8, RDMEM( cpustate->ea2.d ) );
+}
+
+
+static void _LDCFBRR(tlcs900_state *cpustate)
+{
+ ldcf8( cpustate, *cpustate->p1_reg8, *cpustate->p2_reg8 );
+}
+
+
+static void _LDCFWIR(tlcs900_state *cpustate)
+{
+ ldcf16( cpustate, cpustate->imm1.b.l, *cpustate->p2_reg16 );
+}
+
+
+static void _LDCFWRR(tlcs900_state *cpustate)
+{
+ ldcf16( cpustate, *cpustate->p1_reg8, *cpustate->p2_reg16 );
+}
+
+
+static void _LDD(tlcs900_state *cpustate)
+{
+ UINT16 *bc = get_reg16_current( cpustate, 1 );
+
+ WRMEM( *cpustate->p1_reg32, RDMEM( *cpustate->p2_reg32 ) );
+ *cpustate->p1_reg32 -= 1;
+ *cpustate->p2_reg32 -= 1;
+ *bc -= 1;
+ cpustate->sr.b.l &= ~ ( FLAG_HF | FLAG_VF | FLAG_NF );
+ if ( *bc )
+ {
+ cpustate->sr.b.l |= FLAG_VF;
+ }
+}
+
+
+static void _LDDR(tlcs900_state *cpustate)
+{
+ UINT16 *bc = get_reg16_current( cpustate, 1 );
+
+ WRMEM( *cpustate->p1_reg32, RDMEM( *cpustate->p2_reg32 ) );
+ *cpustate->p1_reg32 -= 1;
+ *cpustate->p2_reg32 -= 1;
+ *bc -= 1;
+ cpustate->sr.b.l &= ~ ( FLAG_HF | FLAG_VF | FLAG_NF );
+ if ( *bc )
+ {
+ cpustate->sr.b.l |= FLAG_VF;
+ cpustate->pc.d -= 2;
+ cpustate->cycles += 4;
+ }
+}
+
+
+static void _LDDRW(tlcs900_state *cpustate)
+{
+ UINT16 *bc = get_reg16_current( cpustate, 1 );
+
+ WRMEMW( *cpustate->p1_reg32, RDMEMW( *cpustate->p2_reg32 ) );
+ *cpustate->p1_reg32 -= 2;
+ *cpustate->p2_reg32 -= 2;
+ *bc -= 1;
+ cpustate->sr.b.l &= ~ ( FLAG_HF | FLAG_VF | FLAG_NF );
+ if ( *bc )
+ {
+ cpustate->sr.b.l |= FLAG_VF;
+ cpustate->pc.d -= 2;
+ cpustate->cycles += 4;
+ }
+}
+
+
+static void _LDDW(tlcs900_state *cpustate)
+{
+ UINT16 *bc = get_reg16_current( cpustate, 1 );
+
+ WRMEMW( *cpustate->p1_reg32, RDMEMW( *cpustate->p2_reg32 ) );
+ *cpustate->p1_reg32 -= 2;
+ *cpustate->p2_reg32 -= 2;
+ *bc -= 1;
+ cpustate->sr.b.l &= ~ ( FLAG_HF | FLAG_VF | FLAG_NF );
+ if ( *bc )
+ {
+ cpustate->sr.b.l |= FLAG_VF;
+ }
+}
+
+
+static void _LDF(tlcs900_state *cpustate)
+{
+ cpustate->sr.b.h = ( cpustate->sr.b.h & 0xf8 ) | ( cpustate->imm1.b.l & 0x07 );
+ cpustate->regbank = cpustate->imm1.b.l & 0x03;
+}
+
+
+static void _LDI(tlcs900_state *cpustate)
+{
+ UINT16 *bc = get_reg16_current( cpustate, 1 );
+
+ WRMEM( *cpustate->p1_reg32, RDMEM( *cpustate->p2_reg32 ) );
+ *cpustate->p1_reg32 += 1;
+ *cpustate->p2_reg32 += 1;
+ *bc -= 1;
+ cpustate->sr.b.l &= ~ ( FLAG_HF | FLAG_VF | FLAG_NF );
+ if ( *bc )
+ {
+ cpustate->sr.b.l |= FLAG_VF;
+ }
+}
+
+
+static void _LDIR(tlcs900_state *cpustate)
+{
+ UINT16 *bc = get_reg16_current( cpustate, 1 );
+
+ WRMEM( *cpustate->p1_reg32, RDMEM( *cpustate->p2_reg32 ) );
+ *cpustate->p1_reg32 += 1;
+ *cpustate->p2_reg32 += 1;
+ *bc -= 1;
+ cpustate->sr.b.l &= ~ ( FLAG_HF | FLAG_VF | FLAG_NF );
+ if ( *bc )
+ {
+ cpustate->sr.b.l |= FLAG_VF;
+ cpustate->pc.d -= 2;
+ cpustate->cycles += 4;
+ }
+}
+
+
+static void _LDIRW(tlcs900_state *cpustate)
+{
+ UINT16 *bc = get_reg16_current( cpustate, 1 );
+
+ WRMEMW( *cpustate->p1_reg32, RDMEMW( *cpustate->p2_reg32 ) );
+ *cpustate->p1_reg32 += 2;
+ *cpustate->p2_reg32 += 2;
+ *bc -= 1;
+ cpustate->sr.b.l &= ~ ( FLAG_HF | FLAG_VF | FLAG_NF );
+ if ( *bc )
+ {
+ cpustate->sr.b.l |= FLAG_VF;
+ cpustate->pc.d -= 2;
+ cpustate->cycles += 4;
+ }
+}
+
+
+static void _LDIW(tlcs900_state *cpustate)
+{
+ UINT16 *bc = get_reg16_current( cpustate, 1 );
+
+ WRMEMW( *cpustate->p1_reg32, RDMEMW( *cpustate->p2_reg32 ) );
+ *cpustate->p1_reg32 += 2;
+ *cpustate->p2_reg32 += 2;
+ *bc -= 1;
+ cpustate->sr.b.l &= ~ ( FLAG_HF | FLAG_VF | FLAG_NF );
+ if ( *bc )
+ {
+ cpustate->sr.b.l |= FLAG_VF;
+ }
+}
+
+
+static void _LDX(tlcs900_state *cpustate)
+{
+ UINT8 a, b;
+
+ RDOP();
+ a = RDOP();
+ RDOP();
+ b = RDOP();
+ RDOP();
+ WRMEM( a, b );
+}
+
+
+static void _LINK(tlcs900_state *cpustate)
+{
+ cpustate->xssp.d -= 4;
+ WRMEML( cpustate->xssp.d, *cpustate->p1_reg32 );
+ *cpustate->p1_reg32 = cpustate->xssp.d;
+ cpustate->xssp.d += cpustate->imm2.sw.l;
+}
+
+
+static void _MAX(tlcs900_state *cpustate)
+{
+ cpustate->sr.b.h |= 0x04;
+}
+
+
+static void _MDEC1(tlcs900_state *cpustate)
+{
+ if ( ( *cpustate->p2_reg16 & cpustate->imm1.w.l ) == cpustate->imm1.w.l )
+ *cpustate->p2_reg16 += cpustate->imm1.w.l;
+ else
+ *cpustate->p2_reg16 -= 1;
+}
+
+
+static void _MDEC2(tlcs900_state *cpustate)
+{
+ if ( ( *cpustate->p2_reg16 & cpustate->imm1.w.l ) == cpustate->imm1.w.l )
+ *cpustate->p2_reg16 += cpustate->imm1.w.l;
+ else
+ *cpustate->p2_reg16 -= 2;
+}
+
+
+static void _MDEC4(tlcs900_state *cpustate)
+{
+ if ( ( *cpustate->p2_reg16 & cpustate->imm1.w.l ) == cpustate->imm1.w.l )
+ *cpustate->p2_reg16 += cpustate->imm1.w.l;
+ else
+ *cpustate->p2_reg16 -= 4;
+}
+
+
+static void _MINC1(tlcs900_state *cpustate)
+{
+ if ( ( *cpustate->p2_reg16 & cpustate->imm1.w.l ) == cpustate->imm1.w.l )
+ *cpustate->p2_reg16 -= cpustate->imm1.w.l;
+ else
+ *cpustate->p2_reg16 += 1;
+}
+
+
+static void _MINC2(tlcs900_state *cpustate)
+{
+ if ( ( *cpustate->p2_reg16 & cpustate->imm1.w.l ) == cpustate->imm1.w.l )
+ *cpustate->p2_reg16 -= cpustate->imm1.w.l;
+ else
+ *cpustate->p2_reg16 += 2;
+}
+
+
+static void _MINC4(tlcs900_state *cpustate)
+{
+ if ( ( *cpustate->p2_reg16 & cpustate->imm1.w.l ) == cpustate->imm1.w.l )
+ *cpustate->p2_reg16 -= cpustate->imm1.w.l;
+ else
+ *cpustate->p2_reg16 += 4;
+}
+
+
+static void _MIRRW(tlcs900_state *cpustate)
+{
+ UINT16 r = *cpustate->p1_reg16;
+ UINT16 s = ( r & 0x01 );
+ int i;
+
+
+ for ( i = 0; i < 15; i++ )
+ {
+ r >>= 1;
+ s <<= 1;
+ s |= ( r & 0x01 );
+ }
+
+ *cpustate->p1_reg16 = s;
+}
+
+
+static void _MULBRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = ( *cpustate->p1_reg16 & 0xff ) * cpustate->imm2.b.l;
+}
+
+
+static void _MULBRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = ( *cpustate->p1_reg16 & 0xff ) * RDMEM( cpustate->ea2.d );
+}
+
+
+static void _MULBRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = ( *cpustate->p1_reg16 & 0xff ) * *cpustate->p2_reg8;
+}
+
+
+static void _MULWRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = ( *cpustate->p1_reg32 & 0xffff ) * cpustate->imm2.w.l;
+}
+
+
+static void _MULWRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = ( *cpustate->p1_reg32 & 0xffff ) * RDMEMW( cpustate->ea2.d );
+}
+
+
+static void _MULWRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = ( *cpustate->p1_reg32 & 0xffff ) * *cpustate->p2_reg16;
+}
+
+
+static void _MULAR(tlcs900_state *cpustate)
+{
+ UINT32 *xde = get_reg32_current( cpustate, 2 );
+ UINT32 *xhl = get_reg32_current( cpustate, 3 );
+
+ *cpustate->p1_reg32 = *cpustate->p1_reg32 + ( ((INT16)RDMEMW( *xde )) * ((INT16)RDMEMW( *xhl )) );
+ *xhl -= 2;
+
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_VF );
+ cpustate->sr.b.l |= ( ( *cpustate->p1_reg32 >> 24 ) & FLAG_SF ) | ( *cpustate->p1_reg32 ? 0 : FLAG_ZF );
+}
+
+
+static void _MULSBRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = (INT8)( *cpustate->p1_reg16 & 0xff ) * cpustate->imm2.sb.l;
+}
+
+
+static void _MULSBRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = (INT8)( *cpustate->p1_reg16 & 0xff ) * (INT8)RDMEM( cpustate->ea2.d );
+}
+
+
+static void _MULSBRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = (INT8)( *cpustate->p1_reg16 & 0xff ) * (INT8)*cpustate->p2_reg8;
+}
+
+
+static void _MULSWRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = (INT16)( *cpustate->p1_reg32 & 0xffff ) * cpustate->imm2.sw.l;
+}
+
+
+static void _MULSWRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = (INT16)( *cpustate->p1_reg32 & 0xffff ) * (INT16)RDMEMW( cpustate->ea2.d );
+}
+
+
+static void _MULSWRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = (INT16)( *cpustate->p1_reg32 & 0xffff ) * (INT16)*cpustate->p2_reg16;
+}
+
+
+static void _NEGBR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = sub8( cpustate, 0, *cpustate->p1_reg8 );
+}
+
+
+static void _NEGWR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = sub16( cpustate, 0, *cpustate->p1_reg16 );
+}
+
+
+static void _NOP(tlcs900_state *cpustate)
+{
+ /* Do nothing */
+}
+
+
+static void _NORMAL(tlcs900_state *cpustate)
+{
+ cpustate->sr.b.h &= 0x7F;
+}
+
+
+static void _ORBMI(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea1.d, or8( cpustate, RDMEM( cpustate->ea1.d ), cpustate->imm2.b.l ) );
+}
+
+
+static void _ORBMR(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea1.d, or8( cpustate, RDMEM( cpustate->ea1.d ), *cpustate->p2_reg8 ) );
+}
+
+
+static void _ORBRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = or8( cpustate, *cpustate->p1_reg8, cpustate->imm2.b.l );
+}
+
+
+static void _ORBRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = or8( cpustate, *cpustate->p1_reg8, RDMEM( cpustate->ea2.d ) );
+}
+
+
+static void _ORBRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = or8( cpustate, *cpustate->p1_reg8, *cpustate->p2_reg8 );
+}
+
+
+static void _ORWMI(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea1.d, or16( cpustate, RDMEMW( cpustate->ea1.d ), cpustate->imm2.w.l ) );
+}
+
+
+static void _ORWMR(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea1.d, or16( cpustate, RDMEMW( cpustate->ea1.d ), *cpustate->p2_reg16 ) );
+}
+
+
+static void _ORWRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = or16( cpustate, *cpustate->p1_reg16, cpustate->imm2.w.l );
+}
+
+
+static void _ORWRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = or16( cpustate, *cpustate->p1_reg16, RDMEMW( cpustate->ea2.d ) );
+}
+
+
+static void _ORWRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = or16( cpustate, *cpustate->p1_reg16, *cpustate->p2_reg16 );
+}
+
+
+static void _ORLMR(tlcs900_state *cpustate)
+{
+ WRMEML( cpustate->ea1.d, or32( cpustate, RDMEML( cpustate->ea1.d ), *cpustate->p2_reg32 ) );
+}
+
+
+static void _ORLRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = or32( cpustate, *cpustate->p1_reg32, cpustate->imm2.d );
+}
+
+
+static void _ORLRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = or32( cpustate, *cpustate->p1_reg32, RDMEML( cpustate->ea2.d ) );
+}
+
+
+static void _ORLRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = or32( cpustate, *cpustate->p1_reg32, *cpustate->p2_reg32 );
+}
+
+
+static void _ORCFBIM(tlcs900_state *cpustate)
+{
+ orcf8( cpustate, cpustate->imm1.b.l, RDMEM( cpustate->ea2.d ) );
+}
+
+
+static void _ORCFBIR(tlcs900_state *cpustate)
+{
+ orcf8( cpustate, cpustate->imm1.b.l, *cpustate->p2_reg8 );
+}
+
+
+static void _ORCFBRM(tlcs900_state *cpustate)
+{
+ orcf8( cpustate, *cpustate->p1_reg8, RDMEM( cpustate->ea2.d ) );
+}
+
+
+static void _ORCFBRR(tlcs900_state *cpustate)
+{
+ orcf8( cpustate, *cpustate->p1_reg8, *cpustate->p2_reg8 );
+}
+
+
+static void _ORCFWIR(tlcs900_state *cpustate)
+{
+ orcf16( cpustate, cpustate->imm1.b.l, *cpustate->p2_reg16 );
+}
+
+
+static void _ORCFWRR(tlcs900_state *cpustate)
+{
+ orcf16( cpustate, *cpustate->p1_reg8, *cpustate->p2_reg16 );
+}
+
+
+static void _PAAWR(tlcs900_state *cpustate)
+{
+ if ( *cpustate->p1_reg16 & 1 )
+ *cpustate->p1_reg16 += 1;
+}
+
+
+static void _PAALR(tlcs900_state *cpustate)
+{
+ if ( *cpustate->p1_reg32 & 1 )
+ *cpustate->p1_reg32 += 1;
+}
+
+
+static void _POPBM(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea1.d, RDMEM( cpustate->xssp.d ) );
+ cpustate->xssp.d += 1;
+}
+
+
+static void _POPBR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = RDMEM( cpustate->xssp.d );
+ cpustate->xssp.d += 1;
+}
+
+
+static void _POPWM(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea1.d, RDMEMW( cpustate->xssp.d ) );
+ cpustate->xssp.d += 2;
+}
+
+
+static void _POPWR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = RDMEMW( cpustate->xssp.d );
+ cpustate->xssp.d += 2;
+}
+
+
+static void _POPWSR(tlcs900_state *cpustate)
+{
+ _POPWR( cpustate );
+ cpustate->regbank = cpustate->sr.b.h & 0x03;
+ cpustate->check_irqs = 1;
+}
+
+
+static void _POPLR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = RDMEML( cpustate->xssp.d );
+ cpustate->xssp.d += 4;
+}
+
+
+static void _PUSHBI(tlcs900_state *cpustate)
+{
+ cpustate->xssp.d -= 1;
+ WRMEM( cpustate->xssp.d, cpustate->imm1.b.l );
+}
+
+
+static void _PUSHBM(tlcs900_state *cpustate)
+{
+ cpustate->xssp.d -= 1;
+ WRMEM( cpustate->xssp.d, RDMEM( cpustate->ea1.d ) );
+}
+
+
+static void _PUSHBR(tlcs900_state *cpustate)
+{
+ cpustate->xssp.d -= 1;
+ WRMEM( cpustate->xssp.d, *cpustate->p1_reg8 );
+}
+
+
+static void _PUSHWI(tlcs900_state *cpustate)
+{
+ cpustate->xssp.d -= 2;
+ WRMEMW( cpustate->xssp.d, cpustate->imm1.w.l );
+}
+
+
+static void _PUSHWM(tlcs900_state *cpustate)
+{
+ cpustate->xssp.d -= 2;
+ WRMEMW( cpustate->xssp.d, RDMEMW( cpustate->ea1.d ) );
+}
+
+
+static void _PUSHWR(tlcs900_state *cpustate)
+{
+ cpustate->xssp.d -= 2;
+ WRMEMW( cpustate->xssp.d, *cpustate->p1_reg16 );
+}
+
+
+static void _PUSHLR(tlcs900_state *cpustate)
+{
+ cpustate->xssp.d -= 4;
+ WRMEML( cpustate->xssp.d, *cpustate->p1_reg32 );
+}
+
+
+static void _RCF(tlcs900_state *cpustate)
+{
+ cpustate->sr.b.l &= ~ ( FLAG_HF | FLAG_NF | FLAG_CF );
+}
+
+
+static void _RESBIM(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea2.d, RDMEM( cpustate->ea2.d ) & ~( 1 << ( cpustate->imm1.d & 0x07 ) ) );
+}
+
+
+static void _RESBIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg8 = *cpustate->p2_reg8 & ~( 1 << ( cpustate->imm1.d & 0x07 ) );
+}
+
+
+static void _RESWIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg16 = *cpustate->p2_reg16 & ~( 1 << ( cpustate->imm1.d & 0x0f ) );
+}
+
+
+static void _RET(tlcs900_state *cpustate)
+{
+ cpustate->pc.d = RDMEML( cpustate->xssp.d );
+ cpustate->xssp.d += 4;
+}
+
+
+static void _RETCC(tlcs900_state *cpustate)
+{
+ if ( condition_true( cpustate, cpustate->op ) )
+ {
+ cpustate->pc.d = RDMEML( cpustate->xssp.d );
+ cpustate->xssp.d += 4;
+ cpustate->cycles += 6;
+ }
+}
+
+
+static void _RETD(tlcs900_state *cpustate)
+{
+ cpustate->pc.d = RDMEML( cpustate->xssp.d );
+ cpustate->xssp.d += 4 + cpustate->imm1.sw.l;
+}
+
+
+static void _RETI(tlcs900_state *cpustate)
+{
+ cpustate->sr.w.l = RDMEMW( cpustate->xssp.d );
+ cpustate->xssp.d += 2;
+ cpustate->pc.d = RDMEML( cpustate->xssp.d );
+ cpustate->xssp.d += 4;
+ cpustate->regbank = cpustate->sr.b.h & 0x03;
+ cpustate->check_irqs = 1;
+}
+
+
+static void _RLBM(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea2.d, rl8( cpustate, RDMEM( cpustate->ea2.d ), 1 ) );
+}
+
+
+static void _RLWM(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea2.d, rl16( cpustate, RDMEMW( cpustate->ea2.d ), 1 ) );
+}
+
+
+static void _RLBIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg8 = rl8( cpustate, *cpustate->p2_reg8, cpustate->imm1.b.l );
+}
+
+
+static void _RLBRR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg8 = rl8( cpustate, *cpustate->p2_reg8, *cpustate->p1_reg8 );
+}
+
+
+static void _RLWIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg16 = rl16( cpustate, *cpustate->p2_reg16, cpustate->imm1.b.l );
+}
+
+
+static void _RLWRR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg16 = rl16( cpustate, *cpustate->p2_reg16, *cpustate->p1_reg8 );
+}
+
+
+static void _RLLIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg32 = rl32( cpustate, *cpustate->p2_reg32, cpustate->imm1.b.l );
+}
+
+
+static void _RLLRR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg32 = rl32( cpustate, *cpustate->p2_reg32, *cpustate->p1_reg8 );
+}
+
+
+static void _RLCBM(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea2.d, rlc8( cpustate, RDMEM( cpustate->ea2.d ), 1 ) );
+}
+
+
+static void _RLCWM(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea2.d, rlc16( cpustate, RDMEMW( cpustate->ea2.d ), 1 ) );
+}
+
+
+static void _RLCBIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg8 = rlc8( cpustate, *cpustate->p2_reg8, cpustate->imm1.b.l );
+}
+
+
+static void _RLCBRR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg8 = rlc8( cpustate, *cpustate->p2_reg8, *cpustate->p1_reg8 );
+}
+
+
+static void _RLCWIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg16 = rlc16( cpustate, *cpustate->p2_reg16, cpustate->imm1.b.l );
+}
+
+
+static void _RLCWRR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg16 = rlc16( cpustate, *cpustate->p2_reg16, *cpustate->p1_reg8 );
+}
+
+
+static void _RLCLIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg32 = rlc32( cpustate, *cpustate->p2_reg32, cpustate->imm1.b.l );
+}
+
+
+static void _RLCLRR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg32 = rlc32( cpustate, *cpustate->p2_reg32, *cpustate->p1_reg8 );
+}
+
+
+static void _RLDRM(tlcs900_state *cpustate)
+{
+ UINT8 a = *cpustate->p1_reg8 & 0x0f;
+ UINT8 b = RDMEM( cpustate->ea2.d );
+
+ *cpustate->p1_reg8 = ( *cpustate->p1_reg8 & 0xf0 ) | ( ( b & 0xf0 ) >> 4 );
+ WRMEM( cpustate->ea2.d, ( ( b & 0x0f ) << 4 ) | a );
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF | FLAG_CF );
+ cpustate->sr.b.l |= ( *cpustate->p1_reg8 & FLAG_SF ) | ( *cpustate->p1_reg8 ? 0 : FLAG_ZF );
+ parity8( cpustate, *cpustate->p1_reg8 );
+}
+
+
+static void _RRBM(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea2.d, rr8( cpustate, RDMEM( cpustate->ea2.d ), 1 ) );
+}
+
+
+static void _RRWM(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea2.d, rr16( cpustate, RDMEMW( cpustate->ea2.d ), 1 ) );
+}
+
+
+static void _RRBIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg8 = rr8( cpustate, *cpustate->p2_reg8, cpustate->imm1.b.l );
+}
+
+
+static void _RRBRR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg8 = rr8( cpustate, *cpustate->p2_reg8, *cpustate->p1_reg8 );
+}
+
+
+static void _RRWIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg16 = rr16( cpustate, *cpustate->p2_reg16, cpustate->imm1.b.l );
+}
+
+
+static void _RRWRR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg16 = rr16( cpustate, *cpustate->p2_reg16, *cpustate->p1_reg8 );
+}
+
+
+static void _RRLIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg32 = rr32( cpustate, *cpustate->p2_reg32, cpustate->imm1.b.l );
+}
+
+
+static void _RRLRR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg32 = rr32( cpustate, *cpustate->p2_reg32, *cpustate->p1_reg8 );
+}
+
+
+static void _RRCBM(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea2.d, rrc8( cpustate, RDMEM( cpustate->ea2.d ), 1 ) );
+}
+
+
+static void _RRCWM(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea2.d, rrc16( cpustate, RDMEMW( cpustate->ea2.d ), 1 ) );
+}
+
+
+static void _RRCBIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg8 = rrc8( cpustate, *cpustate->p2_reg8, cpustate->imm1.b.l );
+}
+
+
+static void _RRCBRR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg8 = rrc8( cpustate, *cpustate->p2_reg8, *cpustate->p1_reg8 );
+}
+
+
+static void _RRCWIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg16 = rrc16( cpustate, *cpustate->p2_reg16, cpustate->imm1.b.l );
+}
+
+
+static void _RRCWRR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg16 = rrc16( cpustate, *cpustate->p2_reg16, *cpustate->p1_reg8 );
+}
+
+
+static void _RRCLIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg32 = rrc32( cpustate, *cpustate->p2_reg32, cpustate->imm1.b.l );
+}
+
+
+static void _RRCLRR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg32 = rrc32( cpustate, *cpustate->p2_reg32, *cpustate->p1_reg8 );
+}
+
+
+static void _RRDRM(tlcs900_state *cpustate)
+{
+ UINT8 a = *cpustate->p1_reg8 & 0x0f;
+ UINT8 b = RDMEM( cpustate->ea2.d );
+
+ *cpustate->p1_reg8 = ( *cpustate->p1_reg8 & 0xf0 ) | ( b & 0x0f );
+ WRMEM( cpustate->ea2.d, ( ( b & 0xf0 ) >> 4 ) | ( a << 4 ) );
+ cpustate->sr.b.l &= ~ ( FLAG_SF | FLAG_ZF | FLAG_HF | FLAG_VF | FLAG_NF | FLAG_CF );
+ cpustate->sr.b.l |= ( *cpustate->p1_reg8 & FLAG_SF ) | ( *cpustate->p1_reg8 ? 0 : FLAG_ZF );
+ parity8( cpustate, *cpustate->p1_reg8 );
+}
+
+
+static void _SBCBMI(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea1.d, sbc8( cpustate, RDMEM( cpustate->ea1.d ), cpustate->imm2.b.l ) );
+}
+
+
+static void _SBCBMR(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea1.d, sbc8( cpustate, RDMEM( cpustate->ea1.d ), *cpustate->p2_reg8 ) );
+}
+
+
+static void _SBCBRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = sbc8( cpustate, *cpustate->p1_reg8, cpustate->imm2.b.l );
+}
+
+
+static void _SBCBRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = sbc8( cpustate, *cpustate->p1_reg8, RDMEM( cpustate->ea2.d ) );
+}
+
+
+static void _SBCBRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = sbc8( cpustate, *cpustate->p1_reg8, *cpustate->p2_reg8 );
+}
+
+
+static void _SBCWMI(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea1.d, sbc16( cpustate, RDMEMW( cpustate->ea1.d ), cpustate->imm2.w.l ) );
+}
+
+
+static void _SBCWMR(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea1.d, sbc16( cpustate, RDMEMW( cpustate->ea1.d ), *cpustate->p2_reg16 ) );
+}
+
+
+static void _SBCWRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = sbc16( cpustate, *cpustate->p1_reg16, cpustate->imm2.w.l );
+}
+
+
+static void _SBCWRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = sbc16( cpustate, *cpustate->p1_reg16, RDMEMW( cpustate->ea2.d ) );
+}
+
+
+static void _SBCWRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = sbc16( cpustate, *cpustate->p1_reg16, *cpustate->p2_reg16 );
+}
+
+
+static void _SBCLMR(tlcs900_state *cpustate)
+{
+ WRMEML( cpustate->ea1.d, sbc32( cpustate, RDMEML( cpustate->ea1.d ), *cpustate->p2_reg32 ) );
+}
+
+
+static void _SBCLRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = sbc32( cpustate, *cpustate->p1_reg32, cpustate->imm2.d );
+}
+
+
+static void _SBCLRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = sbc32( cpustate, *cpustate->p1_reg32, RDMEML( cpustate->ea2.d ) );
+}
+
+
+static void _SBCLRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = sbc32( cpustate, *cpustate->p1_reg32, *cpustate->p2_reg32 );
+}
+
+
+static void _SCCBR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg8 = condition_true( cpustate, cpustate->op ) ? 1 : 0;
+}
+
+
+static void _SCCWR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg16 = condition_true( cpustate, cpustate->op ) ? 1 : 0;
+}
+
+
+static void _SCF(tlcs900_state *cpustate)
+{
+ cpustate->sr.b.l &= ~ ( FLAG_HF | FLAG_NF );
+ cpustate->sr.b.l |= FLAG_CF;
+}
+
+
+static void _SETBIM(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea2.d, RDMEM( cpustate->ea2.d ) | ( 1 << ( cpustate->imm1.d & 0x07 ) ) );
+}
+
+
+static void _SETBIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg8 = *cpustate->p2_reg8 | ( 1 << ( cpustate->imm1.d & 0x07 ) );
+}
+
+
+static void _SETWIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg16 = *cpustate->p2_reg16 | ( 1 << ( cpustate->imm1.d & 0x0f ) );
+}
+
+
+static void _SLABM(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea2.d, sla8( cpustate, RDMEM( cpustate->ea2.d ), 1 ) );
+}
+
+
+static void _SLAWM(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea2.d, sla16( cpustate, RDMEMW( cpustate->ea2.d ), 1 ) );
+}
+
+
+static void _SLABIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg8 = sla8( cpustate, *cpustate->p2_reg8, cpustate->imm1.b.l );
+}
+
+
+static void _SLABRR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg8 = sla8( cpustate, *cpustate->p2_reg8, *cpustate->p1_reg8 );
+}
+
+
+static void _SLAWIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg16 = sla16( cpustate, *cpustate->p2_reg16, cpustate->imm1.b.l );
+}
+
+
+static void _SLAWRR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg16 = sla16( cpustate, *cpustate->p2_reg16, *cpustate->p1_reg8 );
+}
+
+
+static void _SLALIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg32 = sla32( cpustate, *cpustate->p2_reg32, cpustate->imm1.b.l );
+}
+
+
+static void _SLALRR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg32 = sla32( cpustate, *cpustate->p2_reg32, *cpustate->p1_reg8 );
+}
+
+
+static void _SLLBM(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea2.d, sla8( cpustate, RDMEM( cpustate->ea2.d ), 1 ) );
+}
+
+
+static void _SLLWM(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea2.d, sla16( cpustate, RDMEMW( cpustate->ea2.d ), 1 ) );
+}
+
+
+static void _SLLBIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg8 = sla8( cpustate, *cpustate->p2_reg8, cpustate->imm1.b.l );
+}
+
+
+static void _SLLBRR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg8 = sla8( cpustate, *cpustate->p2_reg8, *cpustate->p1_reg8 );
+}
+
+
+static void _SLLWIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg16 = sla16( cpustate, *cpustate->p2_reg16, cpustate->imm1.b.l );
+}
+
+
+static void _SLLWRR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg16 = sla16( cpustate, *cpustate->p2_reg16, *cpustate->p1_reg8 );
+}
+
+
+static void _SLLLIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg32 = sla32( cpustate, *cpustate->p2_reg32, cpustate->imm1.b.l );
+}
+
+
+static void _SLLLRR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg32 = sla32( cpustate, *cpustate->p2_reg32, *cpustate->p1_reg8 );
+}
+
+
+static void _SRABM(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea2.d, sra8( cpustate, RDMEM( cpustate->ea2.d ), 1 ) );
+}
+
+
+static void _SRAWM(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea2.d, sra16( cpustate, RDMEMW( cpustate->ea2.d ), 1 ) );
+}
+
+
+static void _SRABIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg8 = sra8( cpustate, *cpustate->p2_reg8, cpustate->imm1.b.l );
+}
+
+
+static void _SRABRR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg8 = sra8( cpustate, *cpustate->p2_reg8, *cpustate->p1_reg8 );
+}
+
+
+static void _SRAWIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg16 = sra16( cpustate, *cpustate->p2_reg16, cpustate->imm1.b.l );
+}
+
+
+static void _SRAWRR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg16 = sra16( cpustate, *cpustate->p2_reg16, *cpustate->p1_reg8 );
+}
+
+
+static void _SRALIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg32 = sra32( cpustate, *cpustate->p2_reg32, cpustate->imm1.b.l );
+}
+
+
+static void _SRALRR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg32 = sra32( cpustate, *cpustate->p2_reg32, *cpustate->p1_reg8 );
+}
+
+
+static void _SRLBM(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea2.d, srl8( cpustate, RDMEM( cpustate->ea2.d ), 1 ) );
+}
+
+
+static void _SRLWM(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea2.d, srl16( cpustate, RDMEMW( cpustate->ea2.d ), 1 ) );
+}
+
+
+static void _SRLBIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg8 = srl8( cpustate, *cpustate->p2_reg8, cpustate->imm1.b.l );
+}
+
+
+static void _SRLBRR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg8 = srl8( cpustate, *cpustate->p2_reg8, *cpustate->p1_reg8 );
+}
+
+
+static void _SRLWIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg16 = srl16( cpustate, *cpustate->p2_reg16, cpustate->imm1.b.l );
+}
+
+
+static void _SRLWRR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg16 = srl16( cpustate, *cpustate->p2_reg16, *cpustate->p1_reg8 );
+}
+
+
+static void _SRLLIR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg32 = srl32( cpustate, *cpustate->p2_reg32, cpustate->imm1.b.l );
+}
+
+
+static void _SRLLRR(tlcs900_state *cpustate)
+{
+ *cpustate->p2_reg32 = srl32( cpustate, *cpustate->p2_reg32, *cpustate->p1_reg8 );
+}
+
+
+static void _STCFBIM(tlcs900_state *cpustate)
+{
+ if ( cpustate->sr.b.l & FLAG_CF )
+ WRMEM( cpustate->ea2.d, RDMEM( cpustate->ea2.d ) | ( 1 << ( cpustate->imm1.b.l & 0x07 ) ) );
+ else
+ WRMEM( cpustate->ea2.d, RDMEM( cpustate->ea2.d ) & ~ ( 1 << ( cpustate->imm1.b.l & 0x07 ) ) );
+}
+
+
+static void _STCFBIR(tlcs900_state *cpustate)
+{
+ if ( cpustate->sr.b.l & FLAG_CF )
+ *cpustate->p2_reg8 |= ( 1 << ( cpustate->imm1.b.l & 0x07 ) );
+ else
+ *cpustate->p2_reg8 &= ~ ( 1 << ( cpustate->imm1.b.l & 0x07 ) );
+}
+
+
+static void _STCFBRM(tlcs900_state *cpustate)
+{
+ if ( cpustate->sr.b.l & FLAG_CF )
+ WRMEM( cpustate->ea2.d, RDMEM( cpustate->ea2.d ) | ( 1 << ( *cpustate->p1_reg8 & 0x07 ) ) );
+ else
+ WRMEM( cpustate->ea2.d, RDMEM( cpustate->ea2.d ) & ~ ( 1 << ( *cpustate->p1_reg8 & 0x07 ) ) );
+}
+
+
+static void _STCFBRR(tlcs900_state *cpustate)
+{
+ if ( cpustate->sr.b.l & FLAG_CF )
+ *cpustate->p2_reg8 |= ( 1 << ( *cpustate->p1_reg8 & 0x07 ) );
+ else
+ *cpustate->p2_reg8 &= ~ ( 1 << ( *cpustate->p1_reg8 & 0x07 ) );
+}
+
+
+static void _STCFWIR(tlcs900_state *cpustate)
+{
+ if ( cpustate->sr.b.l & FLAG_CF )
+ *cpustate->p2_reg16 |= ( 1 << ( cpustate->imm1.b.l & 0x0f ) );
+ else
+ *cpustate->p2_reg16 &= ~ ( 1 << ( cpustate->imm1.b.l & 0x0f ) );
+}
+
+
+static void _STCFWRR(tlcs900_state *cpustate)
+{
+ if ( cpustate->sr.b.l & FLAG_CF )
+ *cpustate->p2_reg16 |= ( 1 << ( *cpustate->p1_reg8 & 0x0f ) );
+ else
+ *cpustate->p2_reg16 &= ~ ( 1 << ( *cpustate->p1_reg8 & 0x0f ) );
+}
+
+
+static void _SUBBMI(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea1.d, sub8( cpustate, RDMEM( cpustate->ea1.d ), cpustate->imm2.b.l ) );
+}
+
+
+static void _SUBBMR(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea1.d, sub8( cpustate, RDMEM( cpustate->ea1.d ), *cpustate->p2_reg8 ) );
+}
+
+
+static void _SUBBRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = sub8( cpustate, *cpustate->p1_reg8, cpustate->imm2.b.l );
+}
+
+
+static void _SUBBRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = sub8( cpustate, *cpustate->p1_reg8, RDMEM( cpustate->ea2.d ) );
+}
+
+
+static void _SUBBRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = sub8( cpustate, *cpustate->p1_reg8, *cpustate->p2_reg8 );
+}
+
+
+static void _SUBWMI(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea1.d, sub16( cpustate, RDMEMW( cpustate->ea1.d ), cpustate->imm2.w.l ) );
+}
+
+
+static void _SUBWMR(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea1.d, sub16( cpustate, RDMEMW( cpustate->ea1.d ), *cpustate->p2_reg16 ) );
+}
+
+
+static void _SUBWRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = sub16( cpustate, *cpustate->p1_reg16, cpustate->imm2.w.l );
+}
+
+
+static void _SUBWRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = sub16( cpustate, *cpustate->p1_reg16, RDMEMW( cpustate->ea2.d ) );
+}
+
+
+static void _SUBWRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = sub16( cpustate, *cpustate->p1_reg16, *cpustate->p2_reg16 );
+}
+
+
+static void _SUBLMR(tlcs900_state *cpustate)
+{
+ WRMEML( cpustate->ea1.d, sub32( cpustate, RDMEML( cpustate->ea1.d ), *cpustate->p2_reg32 ) );
+}
+
+
+static void _SUBLRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = sub32( cpustate, *cpustate->p1_reg32, cpustate->imm2.d );
+}
+
+
+static void _SUBLRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = sub32( cpustate, *cpustate->p1_reg32, RDMEML( cpustate->ea2.d ) );
+}
+
+
+static void _SUBLRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = sub32( cpustate, *cpustate->p1_reg32, *cpustate->p2_reg32 );
+}
+
+
+static void _SWI(tlcs900_state *cpustate)
+{
+ cpustate->xssp.d -= 4;
+ WRMEML( cpustate->xssp.d, cpustate->pc.d );
+ cpustate->xssp.d -= 2;
+ WRMEMW( cpustate->xssp.d, cpustate->sr.w.l );
+ cpustate->pc.d = RDMEML( 0x00ffff00 + 4 * cpustate->imm1.b.l );
+}
+
+
+static void _TSETBIM(tlcs900_state *cpustate)
+{
+ UINT8 b = 1 << ( cpustate->imm1.b.l & 0x07 );
+ UINT8 a = RDMEM( cpustate->ea2.d );
+
+ cpustate->sr.b.l &= ~ ( FLAG_ZF | FLAG_NF );
+ cpustate->sr.b.l |= ( ( a & b ) ? 0 : FLAG_ZF ) | FLAG_HF;
+ WRMEM( cpustate->ea2.d, a | b );
+}
+
+
+static void _TSETBIR(tlcs900_state *cpustate)
+{
+ UINT8 b = 1 << ( cpustate->imm1.b.l & 0x07 );
+
+ cpustate->sr.b.l &= ~ ( FLAG_ZF | FLAG_NF );
+ cpustate->sr.b.l |= ( ( *cpustate->p2_reg8 & b ) ? 0 : FLAG_ZF ) | FLAG_HF;
+ *cpustate->p2_reg8 |= b;
+}
+
+
+static void _TSETWIR(tlcs900_state *cpustate)
+{
+ UINT16 b = 1 << ( cpustate->imm1.b.l & 0x0f );
+
+ cpustate->sr.b.l &= ~ ( FLAG_ZF | FLAG_NF );
+ cpustate->sr.b.l |= ( ( *cpustate->p2_reg16 & b ) ? 0 : FLAG_ZF ) | FLAG_HF;
+ *cpustate->p2_reg16 |= b;
+}
+
+
+static void _UNLK(tlcs900_state *cpustate)
+{
+ cpustate->xssp.d = *cpustate->p1_reg32;
+ *cpustate->p1_reg32 = RDMEML( cpustate->xssp.d );
+ cpustate->xssp.d += 4;
+}
+
+
+static void _XORBMI(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea1.d, xor8( cpustate, RDMEM( cpustate->ea1.d ), cpustate->imm2.b.l ) );
+}
+
+
+static void _XORBMR(tlcs900_state *cpustate)
+{
+ WRMEM( cpustate->ea1.d, xor8( cpustate, RDMEM( cpustate->ea1.d ), *cpustate->p2_reg8 ) );
+}
+
+
+static void _XORBRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = xor8( cpustate, *cpustate->p1_reg8, cpustate->imm2.b.l );
+}
+
+
+static void _XORBRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = xor8( cpustate, *cpustate->p1_reg8, RDMEM( cpustate->ea2.d ) );
+}
+
+
+static void _XORBRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg8 = xor8( cpustate, *cpustate->p1_reg8, *cpustate->p2_reg8 );
+}
+
+
+static void _XORWMI(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea1.d, xor16( cpustate, RDMEMW( cpustate->ea1.d ), cpustate->imm2.w.l ) );
+}
+
+
+static void _XORWMR(tlcs900_state *cpustate)
+{
+ WRMEMW( cpustate->ea1.d, xor16( cpustate, RDMEMW( cpustate->ea1.d ), *cpustate->p2_reg16 ) );
+}
+
+
+static void _XORWRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = xor16( cpustate, *cpustate->p1_reg16, cpustate->imm2.w.l );
+}
+
+
+static void _XORWRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = xor16( cpustate, *cpustate->p1_reg16, RDMEMW( cpustate->ea2.d ) );
+}
+
+
+static void _XORWRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg16 = xor16( cpustate, *cpustate->p1_reg16, *cpustate->p2_reg16 );
+}
+
+
+static void _XORLMR(tlcs900_state *cpustate)
+{
+ WRMEML( cpustate->ea1.d, xor32( cpustate, RDMEML( cpustate->ea1.d ), *cpustate->p2_reg32 ) );
+}
+
+
+static void _XORLRI(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = xor32( cpustate, *cpustate->p1_reg32, cpustate->imm2.d );
+}
+
+
+static void _XORLRM(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = xor32( cpustate, *cpustate->p1_reg32, RDMEML( cpustate->ea2.d ) );
+}
+
+
+static void _XORLRR(tlcs900_state *cpustate)
+{
+ *cpustate->p1_reg32 = xor32( cpustate, *cpustate->p1_reg32, *cpustate->p2_reg32 );
+}
+
+
+static void _XORCFBIM(tlcs900_state *cpustate)
+{
+ xorcf8( cpustate, cpustate->imm1.b.l, RDMEM( cpustate->ea2.d ) );
+}
+
+
+static void _XORCFBIR(tlcs900_state *cpustate)
+{
+ xorcf8( cpustate, cpustate->imm1.b.l, *cpustate->p2_reg8 );
+}
+
+
+static void _XORCFBRM(tlcs900_state *cpustate)
+{
+ xorcf8( cpustate, *cpustate->p1_reg8, RDMEM( cpustate->ea2.d ) );
+}
+
+
+static void _XORCFBRR(tlcs900_state *cpustate)
+{
+ xorcf8( cpustate, *cpustate->p1_reg8, *cpustate->p2_reg8 );
+}
+
+
+static void _XORCFWIR(tlcs900_state *cpustate)
+{
+ xorcf16( cpustate, cpustate->imm1.b.l, *cpustate->p2_reg16 );
+}
+
+
+static void _XORCFWRR(tlcs900_state *cpustate)
+{
+ xorcf16( cpustate, *cpustate->p1_reg8, *cpustate->p2_reg16 );
+}
+
+
+static void _ZCF(tlcs900_state *cpustate)
+{
+ cpustate->sr.b.l &= ~ ( FLAG_NF | FLAG_CF );
+ cpustate->sr.b.l |= ( ( cpustate->sr.b.l & FLAG_ZF ) ? 0 : FLAG_CF );
+}
+
+
+typedef struct
+{
+ void (*opfunc)(tlcs900_state *cpustate);
+ int operand1;
+ int operand2;
+ int cycles;
+} tlcs900inst;
+
+
+static void prepare_operands(tlcs900_state *cpustate, const tlcs900inst *inst)
+{
+ switch ( inst->operand1 )
+ {
+ case _A:
+ cpustate->p1_reg8 = &cpustate->xwa[cpustate->regbank].b.l;
+ break;
+ case _F:
+ cpustate->p1_reg8 = &cpustate->sr.b.l;
+ break;
+ case _SR:
+ cpustate->p1_reg16 = &cpustate->sr.w.l;
+ break;
+ case _C8:
+ cpustate->p1_reg8 = get_reg8_current( cpustate, cpustate->op );
+ break;
+ case _C16:
+ cpustate->p1_reg16 = get_reg16_current( cpustate, cpustate->op );
+ break;
+ case _MC16: /* For MUL and DIV operations */
+ cpustate->p1_reg16 = get_reg16_current( cpustate, ( cpustate->op >> 1 ) & 0x03 );
+ break;
+ case _C32:
+ cpustate->p1_reg32 = get_reg32_current( cpustate, cpustate->op );
+ break;
+ case _CR8:
+ cpustate->imm1.d = RDOP();
+ switch( cpustate->imm1.d )
+ {
+ case 0x22:
+ cpustate->p1_reg8 = &cpustate->dmam[0].b.l;
+ break;
+ case 0x26:
+ cpustate->p1_reg8 = &cpustate->dmam[1].b.l;
+ break;
+ case 0x2a:
+ cpustate->p1_reg8 = &cpustate->dmam[2].b.l;
+ break;
+ case 0x2e:
+ cpustate->p1_reg8 = &cpustate->dmam[3].b.l;
+ break;
+ default:
+ cpustate->p1_reg8 = &cpustate->dummy.b.l;
+ break;
+ }
+ break;
+ case _CR16:
+ cpustate->imm1.d = RDOP();
+ switch( cpustate->imm1.d )
+ {
+ case 0x20:
+ cpustate->p1_reg16 = &cpustate->dmac[0].w.l;
+ break;
+ case 0x24:
+ cpustate->p1_reg16 = &cpustate->dmac[1].w.l;
+ break;
+ case 0x28:
+ cpustate->p1_reg16 = &cpustate->dmac[2].w.l;
+ break;
+ case 0x2c:
+ cpustate->p1_reg16 = &cpustate->dmac[3].w.l;
+ break;
+ default:
+ cpustate->p1_reg16 = &cpustate->dummy.w.l;
+ break;
+ }
+ break;
+ case _CR32:
+ cpustate->imm1.d = RDOP();
+ switch( cpustate->imm1.d )
+ {
+ case 0x00:
+ cpustate->p1_reg32 = &cpustate->dmas[0].d;
+ break;
+ case 0x04:
+ cpustate->p1_reg32 = &cpustate->dmas[1].d;
+ break;
+ case 0x08:
+ cpustate->p1_reg32 = &cpustate->dmas[2].d;
+ break;
+ case 0x0c:
+ cpustate->p1_reg32 = &cpustate->dmas[3].d;
+ break;
+ case 0x10:
+ cpustate->p1_reg32 = &cpustate->dmad[0].d;
+ break;
+ case 0x14:
+ cpustate->p1_reg32 = &cpustate->dmad[1].d;
+ break;
+ case 0x18:
+ cpustate->p1_reg32 = &cpustate->dmad[2].d;
+ break;
+ case 0x1c:
+ cpustate->p1_reg32 = &cpustate->dmad[3].d;
+ break;
+ default:
+ cpustate->p1_reg32 = &cpustate->dummy.d;
+ break;
+ }
+ break;
+ case _D8:
+ cpustate->ea1.d = RDOP();
+ cpustate->ea1.d = cpustate->pc.d + cpustate->ea1.sb.l;
+ break;
+ case _D16:
+ cpustate->ea1.d = RDOP();
+ cpustate->ea1.b.h = RDOP();
+ cpustate->ea1.d = cpustate->pc.d + cpustate->ea1.sw.l;
+ break;
+ case _I3:
+ cpustate->imm1.d = cpustate->op & 0x07;
+ break;
+ case _I8:
+ cpustate->imm1.d = RDOP();
+ break;
+ case _I16:
+ cpustate->imm1.d = RDOP();
+ cpustate->imm1.b.h = RDOP();
+ break;
+ case _I24:
+ cpustate->imm1.d = RDOP();
+ cpustate->imm1.b.h = RDOP();
+ cpustate->imm1.b.h2 = RDOP();
+ break;
+ case _I32:
+ cpustate->imm1.d = RDOP();
+ cpustate->imm1.b.h = RDOP();
+ cpustate->imm1.b.h2 = RDOP();
+ cpustate->imm1.b.h3 = RDOP();
+ break;
+ case _M:
+ cpustate->ea1.d = cpustate->ea2.d;
+ break;
+ case _M8:
+ cpustate->ea1.d = RDOP();
+ break;
+ case _M16:
+ cpustate->ea1.d = RDOP();
+ cpustate->ea1.b.h = RDOP();
+ break;
+ case _R:
+ cpustate->p1_reg8 = cpustate->p2_reg8;
+ cpustate->p1_reg16 = cpustate->p2_reg16;
+ cpustate->p1_reg32 = cpustate->p2_reg32;
+ break;
+ }
+
+ switch ( inst->operand2 )
+ {
+ case _A:
+ cpustate->p2_reg8 = &cpustate->xwa[cpustate->regbank].b.l;
+ break;
+ case _F: /* F' */
+ cpustate->p2_reg8 = &cpustate->f2.b.l;
+ break;
+ case _SR:
+ cpustate->p2_reg16 = &cpustate->sr.w.l;
+ break;
+ case _C8:
+ cpustate->p2_reg8 = get_reg8_current( cpustate, cpustate->op );
+ break;
+ case _C16:
+ cpustate->p2_reg16 = get_reg16_current( cpustate, cpustate->op );
+ break;
+ case _C32:
+ cpustate->p2_reg32 = get_reg32_current( cpustate, cpustate->op );
+ break;
+ case _CR8:
+ cpustate->imm1.d = RDOP();
+ switch( cpustate->imm1.d )
+ {
+ case 0x22:
+ cpustate->p2_reg8 = &cpustate->dmam[0].b.l;
+ break;
+ case 0x26:
+ cpustate->p2_reg8 = &cpustate->dmam[1].b.l;
+ break;
+ case 0x2a:
+ cpustate->p2_reg8 = &cpustate->dmam[2].b.l;
+ break;
+ case 0x2e:
+ cpustate->p2_reg8 = &cpustate->dmam[3].b.l;
+ break;
+ default:
+ cpustate->p2_reg8 = &cpustate->dummy.b.l;
+ break;
+ }
+ break;
+ case _CR16:
+ cpustate->imm1.d = RDOP();
+ switch( cpustate->imm1.d )
+ {
+ case 0x20:
+ cpustate->p2_reg16 = &cpustate->dmac[0].w.l;
+ break;
+ case 0x24:
+ cpustate->p2_reg16 = &cpustate->dmac[1].w.l;
+ break;
+ case 0x28:
+ cpustate->p2_reg16 = &cpustate->dmac[2].w.l;
+ break;
+ case 0x2c:
+ cpustate->p2_reg16 = &cpustate->dmac[3].w.l;
+ break;
+ default:
+ cpustate->p2_reg16 = &cpustate->dummy.w.l;
+ break;
+ }
+ break;
+ case _CR32:
+ cpustate->imm1.d = RDOP();
+ switch( cpustate->imm1.d )
+ {
+ case 0x00:
+ cpustate->p2_reg32 = &cpustate->dmas[0].d;
+ break;
+ case 0x04:
+ cpustate->p2_reg32 = &cpustate->dmas[1].d;
+ break;
+ case 0x08:
+ cpustate->p2_reg32 = &cpustate->dmas[2].d;
+ break;
+ case 0x0c:
+ cpustate->p2_reg32 = &cpustate->dmas[3].d;
+ break;
+ case 0x10:
+ cpustate->p2_reg32 = &cpustate->dmad[0].d;
+ break;
+ case 0x14:
+ cpustate->p2_reg32 = &cpustate->dmad[1].d;
+ break;
+ case 0x18:
+ cpustate->p2_reg32 = &cpustate->dmad[2].d;
+ break;
+ case 0x1c:
+ cpustate->p2_reg32 = &cpustate->dmad[3].d;
+ break;
+ default:
+ cpustate->p2_reg32 = &cpustate->dummy.d;
+ break;
+ }
+ break;
+ case _D8:
+ cpustate->ea2.d = RDOP();
+ cpustate->ea2.d = cpustate->pc.d + cpustate->ea2.sb.l;
+ break;
+ case _D16:
+ cpustate->ea2.d = RDOP();
+ cpustate->ea2.b.h = RDOP();
+ cpustate->ea2.d = cpustate->pc.d + cpustate->ea2.sw.l;
+ break;
+ case _I3:
+ cpustate->imm2.d = cpustate->op & 0x07;
+ break;
+ case _I8:
+ cpustate->imm2.d = RDOP();
+ break;
+ case _I16:
+ cpustate->imm2.d = RDOP();
+ cpustate->imm2.b.h = RDOP();
+ break;
+ case _I32:
+ cpustate->imm2.d = RDOP();
+ cpustate->imm2.b.h = RDOP();
+ cpustate->imm2.b.h2 = RDOP();
+ cpustate->imm2.b.h3 = RDOP();
+ break;
+ case _M8:
+ cpustate->ea2.d = RDOP();
+ break;
+ case _M16:
+ cpustate->ea2.d = RDOP();
+ cpustate->ea2.b.h = RDOP();
+ break;
+ }
+}
+
+
+static const tlcs900inst mnemonic_80[256] =
+{
+ /* 00 - 1F */
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _PUSHBM, _M, 0, 7 }, { _DB, 0, 0, 1 }, { _RLDRM, _A, _M, 12 }, { _RRDRM, _A, _M, 12 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _LDI, 0, 0, 10 }, { _LDIR, 0, 0, 10 }, { _LDD, 0, 0, 10 }, { _LDDR, 0, 0, 10 },
+ { _CPI, 0, 0, 8 }, { _CPIR, 0, 0, 10 }, { _CPD, 0, 0, 8 }, { _CPDR, 0, 0, 10 },
+ { _DB, 0, 0, 1 }, { _LDBMM, _M16, _M, 8 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 20 - 3F */
+ { _LDBRM, _C8, _M, 4 }, { _LDBRM, _C8, _M, 4 }, { _LDBRM, _C8, _M, 4 }, { _LDBRM, _C8, _M, 4 },
+ { _LDBRM, _C8, _M, 4 }, { _LDBRM, _C8, _M, 4 }, { _LDBRM, _C8, _M, 4 }, { _LDBRM, _C8, _M, 4 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _EXBMR, _M, _C8, 6 }, { _EXBMR, _M, _C8, 6 }, { _EXBMR, _M, _C8, 6 }, { _EXBMR, _M, _C8, 6 },
+ { _EXBMR, _M, _C8, 6 }, { _EXBMR, _M, _C8, 6 }, { _EXBMR, _M, _C8, 6 }, { _EXBMR, _M, _C8, 6 },
+ { _ADDBMI, _M, _I8, 7 }, { _ADCBMI, _M, _I8, 7 }, { _SUBBMI, _M, _I8, 7 }, { _SBCBMI, _M, _I8, 7 },
+ { _ANDBMI, _M, _I8, 7 }, { _XORBMI, _M, _I8, 7 }, { _ORBMI, _M, _I8, 7 }, { _CPBMI, _M, _I8, 6 },
+
+ /* 40 - 5F */
+ { _MULBRM, _MC16, _M, 18}, { _MULBRM, _MC16, _M, 18 }, { _MULBRM, _MC16, _M, 18 }, { _MULBRM, _MC16, _M, 18 },
+ { _MULBRM, _MC16, _M, 18}, { _MULBRM, _MC16, _M, 18 }, { _MULBRM, _MC16, _M, 18 }, { _MULBRM, _MC16, _M, 18 },
+ { _MULSBRM, _MC16, _M, 18 }, { _MULSBRM, _MC16, _M, 18 }, { _MULSBRM, _MC16, _M, 18 }, { _MULSBRM, _MC16, _M, 18 },
+ { _MULSBRM, _MC16, _M, 18 }, { _MULSBRM, _MC16, _M, 18 }, { _MULSBRM, _MC16, _M, 18 }, { _MULSBRM, _MC16, _M, 18 },
+ { _DIVBRM, _MC16, _M, 22 }, { _DIVBRM, _MC16, _M, 22 }, { _DIVBRM, _MC16, _M, 22 }, { _DIVBRM, _MC16, _M, 22 },
+ { _DIVBRM, _MC16, _M, 22 }, { _DIVBRM, _MC16, _M, 22 }, { _DIVBRM, _MC16, _M, 22 }, { _DIVBRM, _MC16, _M, 22 },
+ { _DIVSBRM, _MC16, _M, 24 }, { _DIVSBRM, _MC16, _M, 24 }, { _DIVSBRM, _MC16, _M, 24 }, { _DIVSBRM, _MC16, _M, 24 },
+ { _DIVSBRM, _MC16, _M, 24 }, { _DIVSBRM, _MC16, _M, 24 }, { _DIVSBRM, _MC16, _M, 24 }, { _DIVSBRM, _MC16, _M, 24 },
+
+ /* 60 - 7F */
+ { _INCBIM, _I3, _M, 6 }, { _INCBIM, _I3, _M, 6 }, { _INCBIM, _I3, _M, 6 }, { _INCBIM, _I3, _M, 6 },
+ { _INCBIM, _I3, _M, 6 }, { _INCBIM, _I3, _M, 6 }, { _INCBIM, _I3, _M, 6 }, { _INCBIM, _I3, _M, 6 },
+ { _DECBIM, _I3, _M, 6 }, { _DECBIM, _I3, _M, 6 }, { _DECBIM, _I3, _M, 6 }, { _DECBIM, _I3, _M, 6 },
+ { _DECBIM, _I3, _M, 6 }, { _DECBIM, _I3, _M, 6 }, { _DECBIM, _I3, _M, 6 }, { _DECBIM, _I3, _M, 6 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _RLCBM, _M, 0, 8 }, { _RRCBM, _M, 0, 8 }, { _RLBM, _M, 0, 8 }, { _RRBM, _M, 0, 8 },
+ { _SLABM, _M, 0, 8 }, { _SRABM, _M, 0, 8 }, { _SLLBM, _M, 0, 8 }, { _SRLBM, _M, 0, 8 },
+
+ /* 80 - 9F */
+ { _ADDBRM, _C8, _M, 4 }, { _ADDBRM, _C8, _M, 4 }, { _ADDBRM, _C8, _M, 4 }, { _ADDBRM, _C8, _M, 4 },
+ { _ADDBRM, _C8, _M, 4 }, { _ADDBRM, _C8, _M, 4 }, { _ADDBRM, _C8, _M, 4 }, { _ADDBRM, _C8, _M, 4 },
+ { _ADDBMR, _M, _C8, 6 }, { _ADDBMR, _M, _C8, 6 }, { _ADDBMR, _M, _C8, 6 }, { _ADDBMR, _M, _C8, 6 },
+ { _ADDBMR, _M, _C8, 6 }, { _ADDBMR, _M, _C8, 6 }, { _ADDBMR, _M, _C8, 6 }, { _ADDBMR, _M, _C8, 6 },
+ { _ADCBRM, _C8, _M, 4 }, { _ADCBRM, _C8, _M, 4 }, { _ADCBRM, _C8, _M, 4 }, { _ADCBRM, _C8, _M, 4 },
+ { _ADCBRM, _C8, _M, 4 }, { _ADCBRM, _C8, _M, 4 }, { _ADCBRM, _C8, _M, 4 }, { _ADCBRM, _C8, _M, 4 },
+ { _ADCBMR, _M, _C8, 6 }, { _ADCBMR, _M, _C8, 6 }, { _ADCBMR, _M, _C8, 6 }, { _ADCBMR, _M, _C8, 6 },
+ { _ADCBMR, _M, _C8, 6 }, { _ADCBMR, _M, _C8, 6 }, { _ADCBMR, _M, _C8, 6 }, { _ADCBMR, _M, _C8, 6 },
+
+ /* A0 - BF */
+ { _SUBBRM, _C8, _M, 4 }, { _SUBBRM, _C8, _M, 4 }, { _SUBBRM, _C8, _M, 4 }, { _SUBBRM, _C8, _M, 4 },
+ { _SUBBRM, _C8, _M, 4 }, { _SUBBRM, _C8, _M, 4 }, { _SUBBRM, _C8, _M, 4 }, { _SUBBRM, _C8, _M, 4 },
+ { _SUBBMR, _M, _C8, 6 }, { _SUBBMR, _M, _C8, 6 }, { _SUBBMR, _M, _C8, 6 }, { _SUBBMR, _M, _C8, 6 },
+ { _SUBBMR, _M, _C8, 6 }, { _SUBBMR, _M, _C8, 6 }, { _SUBBMR, _M, _C8, 6 }, { _SUBBMR, _M, _C8, 6 },
+ { _SBCBRM, _C8, _M, 4 }, { _SBCBRM, _C8, _M, 4 }, { _SBCBRM, _C8, _M, 4 }, { _SBCBRM, _C8, _M, 4 },
+ { _SBCBRM, _C8, _M, 4 }, { _SBCBRM, _C8, _M, 4 }, { _SBCBRM, _C8, _M, 4 }, { _SBCBRM, _C8, _M, 4 },
+ { _SBCBMR, _M, _C8, 6 }, { _SBCBMR, _M, _C8, 6 }, { _SBCBMR, _M, _C8, 6 }, { _SBCBMR, _M, _C8, 6 },
+ { _SBCBMR, _M, _C8, 6 }, { _SBCBMR, _M, _C8, 6 }, { _SBCBMR, _M, _C8, 6 }, { _SBCBMR, _M, _C8, 6 },
+
+ /* C0 - DF */
+ { _ANDBRM, _C8, _M, 4 }, { _ANDBRM, _C8, _M, 4 }, { _ANDBRM, _C8, _M, 4 }, { _ANDBRM, _C8, _M, 4 },
+ { _ANDBRM, _C8, _M, 4 }, { _ANDBRM, _C8, _M, 4 }, { _ANDBRM, _C8, _M, 4 }, { _ANDBRM, _C8, _M, 4 },
+ { _ANDBMR, _M, _C8, 6 }, { _ANDBMR, _M, _C8, 6 }, { _ANDBMR, _M, _C8, 6 }, { _ANDBMR, _M, _C8, 6 },
+ { _ANDBMR, _M, _C8, 6 }, { _ANDBMR, _M, _C8, 6 }, { _ANDBMR, _M, _C8, 6 }, { _ANDBMR, _M, _C8, 6 },
+ { _XORBRM, _C8, _M, 4 }, { _XORBRM, _C8, _M, 4 }, { _XORBRM, _C8, _M, 4 }, { _XORBRM, _C8, _M, 4 },
+ { _XORBRM, _C8, _M, 4 }, { _XORBRM, _C8, _M, 4 }, { _XORBRM, _C8, _M, 4 }, { _XORBRM, _C8, _M, 4 },
+ { _XORBMR, _M, _C8, 6 }, { _XORBMR, _M, _C8, 6 }, { _XORBMR, _M, _C8, 6 }, { _XORBMR, _M, _C8, 6 },
+ { _XORBMR, _M, _C8, 6 }, { _XORBMR, _M, _C8, 6 }, { _XORBMR, _M, _C8, 6 }, { _XORBMR, _M, _C8, 6 },
+
+ /* E0 - FF */
+ { _ORBRM, _C8, _M, 4 }, { _ORBRM, _C8, _M, 4 }, { _ORBRM, _C8, _M, 4 }, { _ORBRM, _C8, _M, 4 },
+ { _ORBRM, _C8, _M, 4 }, { _ORBRM, _C8, _M, 4 }, { _ORBRM, _C8, _M, 4 }, { _ORBRM, _C8, _M, 4 },
+ { _ORBMR, _M, _C8, 6 }, { _ORBMR, _M, _C8, 6 }, { _ORBMR, _M, _C8, 6 }, { _ORBMR, _M, _C8, 6 },
+ { _ORBMR, _M, _C8, 6 }, { _ORBMR, _M, _C8, 6 }, { _ORBMR, _M, _C8, 6 }, { _ORBMR, _M, _C8, 6 },
+ { _CPBRM, _C8, _M, 4 }, { _CPBRM, _C8, _M, 4 }, { _CPBRM, _C8, _M, 4 }, { _CPBRM, _C8, _M, 4 },
+ { _CPBRM, _C8, _M, 4 }, { _CPBRM, _C8, _M, 4 }, { _CPBRM, _C8, _M, 4 }, { _CPBRM, _C8, _M, 4 },
+ { _CPBMR, _M, _C8, 6 }, { _CPBMR, _M, _C8, 6 }, { _CPBMR, _M, _C8, 6 }, { _CPBMR, _M, _C8, 6 },
+ { _CPBMR, _M, _C8, 6 }, { _CPBMR, _M, _C8, 6 }, { _CPBMR, _M, _C8, 6 }, { _CPBMR, _M, _C8, 6 },
+};
+
+
+static const tlcs900inst mnemonic_88[256] =
+{
+ /* 00 - 1F */
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _PUSHBM, _M, 0, 7 }, { _DB, 0, 0, 1 }, { _RLDRM, _A, _M, 12 }, { _RRDRM, _A, _M, 12 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _LDBMM, _M16, _M, 8 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 20 - 3F */
+ { _LDBRM, _C8, _M, 4 }, { _LDBRM, _C8, _M, 4 }, { _LDBRM, _C8, _M, 4 }, { _LDBRM, _C8, _M, 4 },
+ { _LDBRM, _C8, _M, 4 }, { _LDBRM, _C8, _M, 4 }, { _LDBRM, _C8, _M, 4 }, { _LDBRM, _C8, _M, 4 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _EXBMR, _M, _C8, 6 }, { _EXBMR, _M, _C8, 6 }, { _EXBMR, _M, _C8, 6 }, { _EXBMR, _M, _C8, 6 },
+ { _EXBMR, _M, _C8, 6 }, { _EXBMR, _M, _C8, 6 }, { _EXBMR, _M, _C8, 6 }, { _EXBMR, _M, _C8, 6 },
+ { _ADDBMI, _M, _I8, 7 }, { _ADCBMI, _M, _I8, 7 }, { _SUBBMI, _M, _I8, 7 }, { _SBCBMI, _M, _I8, 7 },
+ { _ANDBMI, _M, _I8, 7 }, { _XORBMI, _M, _I8, 7 }, { _ORBMI, _M, _I8, 7 }, { _CPBMI, _M, _I8, 6 },
+
+ /* 40 - 5F */
+ { _MULBRM, _MC16, _M, 18 }, { _MULBRM, _MC16, _M, 18 }, { _MULBRM, _MC16, _M, 18 }, { _MULBRM, _MC16, _M, 18 },
+ { _MULBRM, _MC16, _M, 18 }, { _MULBRM, _MC16, _M, 18 }, { _MULBRM, _MC16, _M, 18 }, { _MULBRM, _MC16, _M, 18 },
+ { _MULSBRM, _MC16, _M, 18 }, { _MULSBRM, _MC16, _M, 18 }, { _MULSBRM, _MC16, _M, 18 }, { _MULSBRM, _MC16, _M, 18 },
+ { _MULSBRM, _MC16, _M, 18 }, { _MULSBRM, _MC16, _M, 18 }, { _MULSBRM, _MC16, _M, 18 }, { _MULSBRM, _MC16, _M, 18 },
+ { _DIVBRM, _MC16, _M, 22 }, { _DIVBRM, _MC16, _M, 22 }, { _DIVBRM, _MC16, _M, 22 }, { _DIVBRM, _MC16, _M, 22 },
+ { _DIVBRM, _MC16, _M, 22 }, { _DIVBRM, _MC16, _M, 22 }, { _DIVBRM, _MC16, _M, 22 }, { _DIVBRM, _MC16, _M, 22 },
+ { _DIVSBRM, _MC16, _M, 24 }, { _DIVSBRM, _MC16, _M, 24 }, { _DIVSBRM, _MC16, _M, 24 }, { _DIVSBRM, _MC16, _M, 24 },
+ { _DIVSBRM, _MC16, _M, 24 }, { _DIVSBRM, _MC16, _M, 24 }, { _DIVSBRM, _MC16, _M, 24 }, { _DIVSBRM, _MC16, _M, 24 },
+
+ /* 60 - 7F */
+ { _INCBIM, _I3, _M, 6 }, { _INCBIM, _I3, _M, 6 }, { _INCBIM, _I3, _M, 6 }, { _INCBIM, _I3, _M, 6 },
+ { _INCBIM, _I3, _M, 6 }, { _INCBIM, _I3, _M, 6 }, { _INCBIM, _I3, _M, 6 }, { _INCBIM, _I3, _M, 6 },
+ { _DECBIM, _I3, _M, 6 }, { _DECBIM, _I3, _M, 6 }, { _DECBIM, _I3, _M, 6 }, { _DECBIM, _I3, _M, 6 },
+ { _DECBIM, _I3, _M, 6 }, { _DECBIM, _I3, _M, 6 }, { _DECBIM, _I3, _M, 6 }, { _DECBIM, _I3, _M, 6 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _RLCBM, _M, 0, 8 }, { _RRCBM, _M, 0, 8 }, { _RLBM, _M, 0, 8 }, { _RRBM, _M, 0, 8 },
+ { _SLABM, _M, 0, 8 }, { _SRABM, _M, 0, 8 }, { _SLLBM, _M, 0, 8 }, { _SRLBM, _M, 0, 8 },
+
+ /* 80 - 9F */
+ { _ADDBRM, _C8, _M, 4 }, { _ADDBRM, _C8, _M, 4 }, { _ADDBRM, _C8, _M, 4 }, { _ADDBRM, _C8, _M, 4 },
+ { _ADDBRM, _C8, _M, 4 }, { _ADDBRM, _C8, _M, 4 }, { _ADDBRM, _C8, _M, 4 }, { _ADDBRM, _C8, _M, 4 },
+ { _ADDBMR, _M, _C8, 6 }, { _ADDBMR, _M, _C8, 6 }, { _ADDBMR, _M, _C8, 6 }, { _ADDBMR, _M, _C8, 6 },
+ { _ADDBMR, _M, _C8, 6 }, { _ADDBMR, _M, _C8, 6 }, { _ADDBMR, _M, _C8, 6 }, { _ADDBMR, _M, _C8, 6 },
+ { _ADCBRM, _C8, _M, 4 }, { _ADCBRM, _C8, _M, 4 }, { _ADCBRM, _C8, _M, 4 }, { _ADCBRM, _C8, _M, 4 },
+ { _ADCBRM, _C8, _M, 4 }, { _ADCBRM, _C8, _M, 4 }, { _ADCBRM, _C8, _M, 4 }, { _ADCBRM, _C8, _M, 4 },
+ { _ADCBMR, _M, _C8, 6 }, { _ADCBMR, _M, _C8, 6 }, { _ADCBMR, _M, _C8, 6 }, { _ADCBMR, _M, _C8, 6 },
+ { _ADCBMR, _M, _C8, 6 }, { _ADCBMR, _M, _C8, 6 }, { _ADCBMR, _M, _C8, 6 }, { _ADCBMR, _M, _C8, 6 },
+
+ /* A0 - BF */
+ { _SUBBRM, _C8, _M, 4 }, { _SUBBRM, _C8, _M, 4 }, { _SUBBRM, _C8, _M, 4 }, { _SUBBRM, _C8, _M, 4 },
+ { _SUBBRM, _C8, _M, 4 }, { _SUBBRM, _C8, _M, 4 }, { _SUBBRM, _C8, _M, 4 }, { _SUBBRM, _C8, _M, 4 },
+ { _SUBBMR, _M, _C8, 6 }, { _SUBBMR, _M, _C8, 6 }, { _SUBBMR, _M, _C8, 6 }, { _SUBBMR, _M, _C8, 6 },
+ { _SUBBMR, _M, _C8, 6 }, { _SUBBMR, _M, _C8, 6 }, { _SUBBMR, _M, _C8, 6 }, { _SUBBMR, _M, _C8, 6 },
+ { _SBCBRM, _C8, _M, 4 }, { _SBCBRM, _C8, _M, 4 }, { _SBCBRM, _C8, _M, 4 }, { _SBCBRM, _C8, _M, 4 },
+ { _SBCBRM, _C8, _M, 4 }, { _SBCBRM, _C8, _M, 4 }, { _SBCBRM, _C8, _M, 4 }, { _SBCBRM, _C8, _M, 4 },
+ { _SBCBMR, _M, _C8, 6 }, { _SBCBMR, _M, _C8, 6 }, { _SBCBMR, _M, _C8, 6 }, { _SBCBMR, _M, _C8, 6 },
+ { _SBCBMR, _M, _C8, 6 }, { _SBCBMR, _M, _C8, 6 }, { _SBCBMR, _M, _C8, 6 }, { _SBCBMR, _M, _C8, 6 },
+
+ /* C0 - DF */
+ { _ANDBRM, _C8, _M, 4 }, { _ANDBRM, _C8, _M, 4 }, { _ANDBRM, _C8, _M, 4 }, { _ANDBRM, _C8, _M, 4 },
+ { _ANDBRM, _C8, _M, 4 }, { _ANDBRM, _C8, _M, 4 }, { _ANDBRM, _C8, _M, 4 }, { _ANDBRM, _C8, _M, 4 },
+ { _ANDBMR, _M, _C8, 6 }, { _ANDBMR, _M, _C8, 6 }, { _ANDBMR, _M, _C8, 6 }, { _ANDBMR, _M, _C8, 6 },
+ { _ANDBMR, _M, _C8, 6 }, { _ANDBMR, _M, _C8, 6 }, { _ANDBMR, _M, _C8, 6 }, { _ANDBMR, _M, _C8, 6 },
+ { _XORBRM, _C8, _M, 4 }, { _XORBRM, _C8, _M, 4 }, { _XORBRM, _C8, _M, 4 }, { _XORBRM, _C8, _M, 4 },
+ { _XORBRM, _C8, _M, 4 }, { _XORBRM, _C8, _M, 4 }, { _XORBRM, _C8, _M, 4 }, { _XORBRM, _C8, _M, 4 },
+ { _XORBMR, _M, _C8, 6 }, { _XORBMR, _M, _C8, 6 }, { _XORBMR, _M, _C8, 6 }, { _XORBMR, _M, _C8, 6 },
+ { _XORBMR, _M, _C8, 6 }, { _XORBMR, _M, _C8, 6 }, { _XORBMR, _M, _C8, 6 }, { _XORBMR, _M, _C8, 6 },
+
+ /* E0 - FF */
+ { _ORBRM, _C8, _M, 4 }, { _ORBRM, _C8, _M, 4 }, { _ORBRM, _C8, _M, 4 }, { _ORBRM, _C8, _M, 4 },
+ { _ORBRM, _C8, _M, 4 }, { _ORBRM, _C8, _M, 4 }, { _ORBRM, _C8, _M, 4 }, { _ORBRM, _C8, _M, 4 },
+ { _ORBMR, _M, _C8, 6 }, { _ORBMR, _M, _C8, 6 }, { _ORBMR, _M, _C8, 6 }, { _ORBMR, _M, _C8, 6 },
+ { _ORBMR, _M, _C8, 6 }, { _ORBMR, _M, _C8, 6 }, { _ORBMR, _M, _C8, 6 }, { _ORBMR, _M, _C8, 6 },
+ { _CPBRM, _C8, _M, 4 }, { _CPBRM, _C8, _M, 4 }, { _CPBRM, _C8, _M, 4 }, { _CPBRM, _C8, _M, 4 },
+ { _CPBRM, _C8, _M, 4 }, { _CPBRM, _C8, _M, 4 }, { _CPBRM, _C8, _M, 4 }, { _CPBRM, _C8, _M, 4 },
+ { _CPBMR, _M, _C8, 6 }, { _CPBMR, _M, _C8, 6 }, { _CPBMR, _M, _C8, 6 }, { _CPBMR, _M, _C8, 6 },
+ { _CPBMR, _M, _C8, 6 }, { _CPBMR, _M, _C8, 6 }, { _CPBMR, _M, _C8, 6 }, { _CPBMR, _M, _C8, 6 },
+};
+
+
+static const tlcs900inst mnemonic_90[256] =
+{
+ /* 00 - 1F */
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _PUSHWM, _M, 0, 7 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _LDIW, 0, 0, 10 }, { _LDIRW, 0, 0, 10 }, { _LDDW, 0, 0, 10 }, { _LDDRW, 0, 0, 10 },
+ { _CPIW, 0, 0, 8 }, { _CPIRW, 0, 0, 10 }, { _CPDW, 0, 0, 8 }, { _CPDRW, 0, 0, 10 },
+ { _DB, 0, 0, 1 }, { _LDWMM, _M16, _M, 8 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 20 - 3F */
+ { _LDWRM, _C16, _M, 4 }, { _LDWRM, _C16, _M, 4 }, { _LDWRM, _C16, _M, 4 }, { _LDWRM, _C16, _M, 4 },
+ { _LDWRM, _C16, _M, 4 }, { _LDWRM, _C16, _M, 4 }, { _LDWRM, _C16, _M, 4 }, { _LDWRM, _C16, _M, 4 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _EXWMR, _M, _C16, 6 }, { _EXWMR, _M, _C16, 6 }, { _EXWMR, _M, _C16, 6 }, { _EXWMR, _M, _C16, 6 },
+ { _EXWMR, _M, _C16, 6 }, { _EXWMR, _M, _C16, 6 }, { _EXWMR, _M, _C16, 6 }, { _EXWMR, _M, _C16, 6 },
+ { _ADDWMI, _M, _I16, 8 }, { _ADCWMI, _M, _I16, 8 }, { _SUBWMI, _M, _I16, 8 }, { _SBCWMI, _M, _I16, 8 },
+ { _ANDWMI, _M, _I16, 8 }, { _XORWMI, _M, _I16, 8 }, { _ORWMI, _M, _I16, 8 }, { _CPWMI, _M, _I16, 6 },
+
+ /* 40 - 5F */
+ { _MULWRM, _C32, _M, 26 }, { _MULWRM, _C32, _M, 26 }, { _MULWRM, _C32, _M, 26 }, { _MULWRM, _C32, _M, 26 },
+ { _MULWRM, _C32, _M, 26 }, { _MULWRM, _C32, _M, 26 }, { _MULWRM, _C32, _M, 26 }, { _MULWRM, _C32, _M, 26 },
+ { _MULSWRM, _C32, _M, 26 }, { _MULSWRM, _C32, _M, 26 }, { _MULSWRM, _C32, _M, 26 }, { _MULSWRM, _C32, _M, 26 },
+ { _MULSWRM, _C32, _M, 26 }, { _MULSWRM, _C32, _M, 26 }, { _MULSWRM, _C32, _M, 26 }, { _MULSWRM, _C32, _M, 26 },
+ { _DIVWRM, _C32, _M, 30 }, { _DIVWRM, _C32, _M, 30 }, { _DIVWRM, _C32, _M, 30 }, { _DIVWRM, _C32, _M, 30 },
+ { _DIVWRM, _C32, _M, 30 }, { _DIVWRM, _C32, _M, 30 }, { _DIVWRM, _C32, _M, 30 }, { _DIVWRM, _C32, _M, 30 },
+ { _DIVSWRM, _C32, _M, 32 }, { _DIVSWRM, _C32, _M, 32 }, { _DIVSWRM, _C32, _M, 32 }, { _DIVSWRM, _C32, _M, 32 },
+ { _DIVSWRM, _C32, _M, 32 }, { _DIVSWRM, _C32, _M, 32 }, { _DIVSWRM, _C32, _M, 32 }, { _DIVSWRM, _C32, _M, 32 },
+
+ /* 60 - 7F */
+ { _INCWIM, _I3, _M, 6 }, { _INCWIM, _I3, _M, 6 }, { _INCWIM, _I3, _M, 6 }, { _INCWIM, _I3, _M, 6 },
+ { _INCWIM, _I3, _M, 6 }, { _INCWIM, _I3, _M, 6 }, { _INCWIM, _I3, _M, 6 }, { _INCWIM, _I3, _M, 6 },
+ { _DECWIM, _I3, _M, 6 }, { _DECWIM, _I3, _M, 6 }, { _DECWIM, _I3, _M, 6 }, { _DECWIM, _I3, _M, 6 },
+ { _DECWIM, _I3, _M, 6 }, { _DECWIM, _I3, _M, 6 }, { _DECWIM, _I3, _M, 6 }, { _DECWIM, _I3, _M, 6 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _RLCWM, _M, 0, 8 }, { _RRCWM, _M, 0, 8 }, { _RLWM, _M, 0, 8 }, { _RRWM, _M, 0, 8 },
+ { _SLAWM, _M, 0, 8 }, { _SRAWM, _M, 0, 8 }, { _SLLWM, _M, 0, 8 }, { _SRLWM, _M, 0, 8 },
+
+ /* 80 - 9F */
+ { _ADDWRM, _C16, _M, 4 }, { _ADDWRM, _C16, _M, 4 }, { _ADDWRM, _C16, _M, 4 }, { _ADDWRM, _C16, _M, 4 },
+ { _ADDWRM, _C16, _M, 4 }, { _ADDWRM, _C16, _M, 4 }, { _ADDWRM, _C16, _M, 4 }, { _ADDWRM, _C16, _M, 4 },
+ { _ADDWMR, _M, _C16, 6 }, { _ADDWMR, _M, _C16, 6 }, { _ADDWMR, _M, _C16, 6 }, { _ADDWMR, _M, _C16, 6 },
+ { _ADDWMR, _M, _C16, 6 }, { _ADDWMR, _M, _C16, 6 }, { _ADDWMR, _M, _C16, 6 }, { _ADDWMR, _M, _C16, 6 },
+ { _ADCWRM, _C16, _M, 4 }, { _ADCWRM, _C16, _M, 4 }, { _ADCWRM, _C16, _M, 4 }, { _ADCWRM, _C16, _M, 4 },
+ { _ADCWRM, _C16, _M, 4 }, { _ADCWRM, _C16, _M, 4 }, { _ADCWRM, _C16, _M, 4 }, { _ADCWRM, _C16, _M, 4 },
+ { _ADCWMR, _M, _C16, 6 }, { _ADCWMR, _M, _C16, 6 }, { _ADCWMR, _M, _C16, 6 }, { _ADCWMR, _M, _C16, 6 },
+ { _ADCWMR, _M, _C16, 6 }, { _ADCWMR, _M, _C16, 6 }, { _ADCWMR, _M, _C16, 6 }, { _ADCWMR, _M, _C16, 6 },
+
+ /* A0 - BF */
+ { _SUBWRM, _C16, _M, 4 }, { _SUBWRM, _C16, _M, 4 }, { _SUBWRM, _C16, _M, 4 }, { _SUBWRM, _C16, _M, 4 },
+ { _SUBWRM, _C16, _M, 4 }, { _SUBWRM, _C16, _M, 4 }, { _SUBWRM, _C16, _M, 4 }, { _SUBWRM, _C16, _M, 4 },
+ { _SUBWMR, _M, _C16, 6 }, { _SUBWMR, _M, _C16, 6 }, { _SUBWMR, _M, _C16, 6 }, { _SUBWMR, _M, _C16, 6 },
+ { _SUBWMR, _M, _C16, 6 }, { _SUBWMR, _M, _C16, 6 }, { _SUBWMR, _M, _C16, 6 }, { _SUBWMR, _M, _C16, 6 },
+ { _SBCWRM, _C16, _M, 4 }, { _SBCWRM, _C16, _M, 4 }, { _SBCWRM, _C16, _M, 4 }, { _SBCWRM, _C16, _M, 4 },
+ { _SBCWRM, _C16, _M, 4 }, { _SBCWRM, _C16, _M, 4 }, { _SBCWRM, _C16, _M, 4 }, { _SBCWRM, _C16, _M, 4 },
+ { _SBCWMR, _M, _C16, 6 }, { _SBCWMR, _M, _C16, 6 }, { _SBCWMR, _M, _C16, 6 }, { _SBCWMR, _M, _C16, 6 },
+ { _SBCWMR, _M, _C16, 6 }, { _SBCWMR, _M, _C16, 6 }, { _SBCWMR, _M, _C16, 6 }, { _SBCWMR, _M, _C16, 6 },
+
+ /* C0 - DF */
+ { _ANDWRM, _C16, _M, 4 }, { _ANDWRM, _C16, _M, 4 }, { _ANDWRM, _C16, _M, 4 }, { _ANDWRM, _C16, _M, 4 },
+ { _ANDWRM, _C16, _M, 4 }, { _ANDWRM, _C16, _M, 4 }, { _ANDWRM, _C16, _M, 4 }, { _ANDWRM, _C16, _M, 4 },
+ { _ANDWMR, _M, _C16, 6 }, { _ANDWMR, _M, _C16, 6 }, { _ANDWMR, _M, _C16, 6 }, { _ANDWMR, _M, _C16, 6 },
+ { _ANDWMR, _M, _C16, 6 }, { _ANDWMR, _M, _C16, 6 }, { _ANDWMR, _M, _C16, 6 }, { _ANDWMR, _M, _C16, 6 },
+ { _XORWRM, _C16, _M, 4 }, { _XORWRM, _C16, _M, 4 }, { _XORWRM, _C16, _M, 4 }, { _XORWRM, _C16, _M, 4 },
+ { _XORWRM, _C16, _M, 4 }, { _XORWRM, _C16, _M, 4 }, { _XORWRM, _C16, _M, 4 }, { _XORWRM, _C16, _M, 4 },
+ { _XORWMR, _M, _C16, 6 }, { _XORWMR, _M, _C16, 6 }, { _XORWMR, _M, _C16, 6 }, { _XORWMR, _M, _C16, 6 },
+ { _XORWMR, _M, _C16, 6 }, { _XORWMR, _M, _C16, 6 }, { _XORWMR, _M, _C16, 6 }, { _XORWMR, _M, _C16, 6 },
+
+ /* E0 - FF */
+ { _ORWRM, _C16, _M, 4 }, { _ORWRM, _C16, _M, 4 }, { _ORWRM, _C16, _M, 4 }, { _ORWRM, _C16, _M, 4 },
+ { _ORWRM, _C16, _M, 4 }, { _ORWRM, _C16, _M, 4 }, { _ORWRM, _C16, _M, 4 }, { _ORWRM, _C16, _M, 4 },
+ { _ORWMR, _M, _C16, 6 }, { _ORWMR, _M, _C16, 6 }, { _ORWMR, _M, _C16, 6 }, { _ORWMR, _M, _C16, 6 },
+ { _ORWMR, _M, _C16, 6 }, { _ORWMR, _M, _C16, 6 }, { _ORWMR, _M, _C16, 6 }, { _ORWMR, _M, _C16, 6 },
+ { _CPWRM, _C16, _M, 4 }, { _CPWRM, _C16, _M, 4 }, { _CPWRM, _C16, _M, 4 }, { _CPWRM, _C16, _M, 4 },
+ { _CPWRM, _C16, _M, 4 }, { _CPWRM, _C16, _M, 4 }, { _CPWRM, _C16, _M, 4 }, { _CPWRM, _C16, _M, 4 },
+ { _CPWMR, _M, _C16, 6 }, { _CPWMR, _M, _C16, 6 }, { _CPWMR, _M, _C16, 6 }, { _CPWMR, _M, _C16, 6 },
+ { _CPWMR, _M, _C16, 6 }, { _CPWMR, _M, _C16, 6 }, { _CPWMR, _M, _C16, 6 }, { _CPWMR, _M, _C16, 6 },
+};
+
+
+static const tlcs900inst mnemonic_98[256] =
+{
+ /* 00 - 1F */
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _PUSHWM, _M, 0, 7 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _LDWMM, _M16, _M, 8 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 20 - 3F */
+ { _LDWRM, _C16, _M, 4 }, { _LDWRM, _C16, _M, 4 }, { _LDWRM, _C16, _M, 4 }, { _LDWRM, _C16, _M, 4 },
+ { _LDWRM, _C16, _M, 4 }, { _LDWRM, _C16, _M, 4 }, { _LDWRM, _C16, _M, 4 }, { _LDWRM, _C16, _M, 4 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _EXWMR, _M, _C16, 6 }, { _EXWMR, _M, _C16, 6 }, { _EXWMR, _M, _C16, 6 }, { _EXWMR, _M, _C16, 6 },
+ { _EXWMR, _M, _C16, 6 }, { _EXWMR, _M, _C16, 6 }, { _EXWMR, _M, _C16, 6 }, { _EXWMR, _M, _C16, 6 },
+ { _ADDWMI, _M, _I16, 8 }, { _ADCWMI, _M, _I16, 8 }, { _SUBWMI, _M, _I16, 8 }, { _SBCWMI, _M, _I16, 8 },
+ { _ANDWMI, _M, _I16, 8 }, { _XORWMI, _M, _I16, 8 }, { _ORWMI, _M, _I16, 8 }, { _CPWMI, _M, _I16, 6 },
+
+ /* 40 - 5F */
+ { _MULWRM, _C32, _M, 26 }, { _MULWRM, _C32, _M, 26 }, { _MULWRM, _C32, _M, 26 }, { _MULWRM, _C32, _M, 26 },
+ { _MULWRM, _C32, _M, 26 }, { _MULWRM, _C32, _M, 26 }, { _MULWRM, _C32, _M, 26 }, { _MULWRM, _C32, _M, 26 },
+ { _MULSWRM, _C32, _M, 26 }, { _MULSWRM, _C32, _M, 26 }, { _MULSWRM, _C32, _M, 26 }, { _MULSWRM, _C32, _M, 26 },
+ { _MULSWRM, _C32, _M, 26 }, { _MULSWRM, _C32, _M, 26 }, { _MULSWRM, _C32, _M, 26 }, { _MULSWRM, _C32, _M, 26 },
+ { _DIVWRM, _C32, _M, 30 }, { _DIVWRM, _C32, _M, 30 }, { _DIVWRM, _C32, _M, 30 }, { _DIVWRM, _C32, _M, 30 },
+ { _DIVWRM, _C32, _M, 30 }, { _DIVWRM, _C32, _M, 30 }, { _DIVWRM, _C32, _M, 30 }, { _DIVWRM, _C32, _M, 30 },
+ { _DIVSWRM, _C32, _M, 32 }, { _DIVSWRM, _C32, _M, 32 }, { _DIVSWRM, _C32, _M, 32 }, { _DIVSWRM, _C32, _M, 32 },
+ { _DIVSWRM, _C32, _M, 32 }, { _DIVSWRM, _C32, _M, 32 }, { _DIVSWRM, _C32, _M, 32 }, { _DIVSWRM, _C32, _M, 32 },
+
+ /* 60 - 7F */
+ { _INCWIM, _I3, _M, 6 }, { _INCWIM, _I3, _M, 6 }, { _INCWIM, _I3, _M, 6 }, { _INCWIM, _I3, _M, 6 },
+ { _INCWIM, _I3, _M, 6 }, { _INCWIM, _I3, _M, 6 }, { _INCWIM, _I3, _M, 6 }, { _INCWIM, _I3, _M, 6 },
+ { _DECWIM, _I3, _M, 6 }, { _DECWIM, _I3, _M, 6 }, { _DECWIM, _I3, _M, 6 }, { _DECWIM, _I3, _M, 6 },
+ { _DECWIM, _I3, _M, 6 }, { _DECWIM, _I3, _M, 6 }, { _DECWIM, _I3, _M, 6 }, { _DECWIM, _I3, _M, 6 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _RLCWM, _M, 0, 8 }, { _RRCWM, _M, 0, 8 }, { _RLWM, _M, 0, 8 }, { _RRWM, _M, 0, 8 },
+ { _SLAWM, _M, 0, 8 }, { _SRAWM, _M, 0, 8 }, { _SLLWM, _M, 0, 8 }, { _SRLWM, _M, 0, 8 },
+
+ /* 80 - 9F */
+ { _ADDWRM, _C16, _M, 4 }, { _ADDWRM, _C16, _M, 4 }, { _ADDWRM, _C16, _M, 4 }, { _ADDWRM, _C16, _M, 4 },
+ { _ADDWRM, _C16, _M, 4 }, { _ADDWRM, _C16, _M, 4 }, { _ADDWRM, _C16, _M, 4 }, { _ADDWRM, _C16, _M, 4 },
+ { _ADDWMR, _M, _C16, 6 }, { _ADDWMR, _M, _C16, 6 }, { _ADDWMR, _M, _C16, 6 }, { _ADDWMR, _M, _C16, 6 },
+ { _ADDWMR, _M, _C16, 6 }, { _ADDWMR, _M, _C16, 6 }, { _ADDWMR, _M, _C16, 6 }, { _ADDWMR, _M, _C16, 6 },
+ { _ADCWRM, _C16, _M, 4 }, { _ADCWRM, _C16, _M, 4 }, { _ADCWRM, _C16, _M, 4 }, { _ADCWRM, _C16, _M, 4 },
+ { _ADCWRM, _C16, _M, 4 }, { _ADCWRM, _C16, _M, 4 }, { _ADCWRM, _C16, _M, 4 }, { _ADCWRM, _C16, _M, 4 },
+ { _ADCWMR, _M, _C16, 6 }, { _ADCWMR, _M, _C16, 6 }, { _ADCWMR, _M, _C16, 6 }, { _ADCWMR, _M, _C16, 6 },
+ { _ADCWMR, _M, _C16, 6 }, { _ADCWMR, _M, _C16, 6 }, { _ADCWMR, _M, _C16, 6 }, { _ADCWMR, _M, _C16, 6 },
+
+ /* A0 - BF */
+ { _SUBWRM, _C16, _M, 4 }, { _SUBWRM, _C16, _M, 4 }, { _SUBWRM, _C16, _M, 4 }, { _SUBWRM, _C16, _M, 4 },
+ { _SUBWRM, _C16, _M, 4 }, { _SUBWRM, _C16, _M, 4 }, { _SUBWRM, _C16, _M, 4 }, { _SUBWRM, _C16, _M, 4 },
+ { _SUBWMR, _M, _C16, 6 }, { _SUBWMR, _M, _C16, 6 }, { _SUBWMR, _M, _C16, 6 }, { _SUBWMR, _M, _C16, 6 },
+ { _SUBWMR, _M, _C16, 6 }, { _SUBWMR, _M, _C16, 6 }, { _SUBWMR, _M, _C16, 6 }, { _SUBWMR, _M, _C16, 6 },
+ { _SBCWRM, _C16, _M, 4 }, { _SBCWRM, _C16, _M, 4 }, { _SBCWRM, _C16, _M, 4 }, { _SBCWRM, _C16, _M, 4 },
+ { _SBCWRM, _C16, _M, 4 }, { _SBCWRM, _C16, _M, 4 }, { _SBCWRM, _C16, _M, 4 }, { _SBCWRM, _C16, _M, 4 },
+ { _SBCWMR, _M, _C16, 6 }, { _SBCWMR, _M, _C16, 6 }, { _SBCWMR, _M, _C16, 6 }, { _SBCWMR, _M, _C16, 6 },
+ { _SBCWMR, _M, _C16, 6 }, { _SBCWMR, _M, _C16, 6 }, { _SBCWMR, _M, _C16, 6 }, { _SBCWMR, _M, _C16, 6 },
+
+ /* C0 - DF */
+ { _ANDWRM, _C16, _M, 4 }, { _ANDWRM, _C16, _M, 4 }, { _ANDWRM, _C16, _M, 4 }, { _ANDWRM, _C16, _M, 4 },
+ { _ANDWRM, _C16, _M, 4 }, { _ANDWRM, _C16, _M, 4 }, { _ANDWRM, _C16, _M, 4 }, { _ANDWRM, _C16, _M, 4 },
+ { _ANDWMR, _M, _C16, 6 }, { _ANDWMR, _M, _C16, 6 }, { _ANDWMR, _M, _C16, 6 }, { _ANDWMR, _M, _C16, 6 },
+ { _ANDWMR, _M, _C16, 6 }, { _ANDWMR, _M, _C16, 6 }, { _ANDWMR, _M, _C16, 6 }, { _ANDWMR, _M, _C16, 6 },
+ { _XORWRM, _C16, _M, 4 }, { _XORWRM, _C16, _M, 4 }, { _XORWRM, _C16, _M, 4 }, { _XORWRM, _C16, _M, 4 },
+ { _XORWRM, _C16, _M, 4 }, { _XORWRM, _C16, _M, 4 }, { _XORWRM, _C16, _M, 4 }, { _XORWRM, _C16, _M, 4 },
+ { _XORWMR, _M, _C16, 6 }, { _XORWMR, _M, _C16, 6 }, { _XORWMR, _M, _C16, 6 }, { _XORWMR, _M, _C16, 6 },
+ { _XORWMR, _M, _C16, 6 }, { _XORWMR, _M, _C16, 6 }, { _XORWMR, _M, _C16, 6 }, { _XORWMR, _M, _C16, 6 },
+
+ /* E0 - FF */
+ { _ORWRM, _C16, _M, 4 }, { _ORWRM, _C16, _M, 4 }, { _ORWRM, _C16, _M, 4 }, { _ORWRM, _C16, _M, 4 },
+ { _ORWRM, _C16, _M, 4 }, { _ORWRM, _C16, _M, 4 }, { _ORWRM, _C16, _M, 4 }, { _ORWRM, _C16, _M, 4 },
+ { _ORWMR, _M, _C16, 6 }, { _ORWMR, _M, _C16, 6 }, { _ORWMR, _M, _C16, 6 }, { _ORWMR, _M, _C16, 6 },
+ { _ORWMR, _M, _C16, 6 }, { _ORWMR, _M, _C16, 6 }, { _ORWMR, _M, _C16, 6 }, { _ORWMR, _M, _C16, 6 },
+ { _CPWRM, _C16, _M, 4 }, { _CPWRM, _C16, _M, 4 }, { _CPWRM, _C16, _M, 4 }, { _CPWRM, _C16, _M, 4 },
+ { _CPWRM, _C16, _M, 4 }, { _CPWRM, _C16, _M, 4 }, { _CPWRM, _C16, _M, 4 }, { _CPWRM, _C16, _M, 4 },
+ { _CPWMR, _M, _C16, 6 }, { _CPWMR, _M, _C16, 6 }, { _CPWMR, _M, _C16, 6 }, { _CPWMR, _M, _C16, 6 },
+ { _CPWMR, _M, _C16, 6 }, { _CPWMR, _M, _C16, 6 }, { _CPWMR, _M, _C16, 6 }, { _CPWMR, _M, _C16, 6 },
+};
+
+
+static const tlcs900inst mnemonic_a0[256] =
+{
+ /* 00 - 1F */
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 20 - 3F */
+ { _LDLRM, _C32, _M, 6 }, { _LDLRM, _C32, _M, 6 }, { _LDLRM, _C32, _M, 6 }, { _LDLRM, _C32, _M, 6 },
+ { _LDLRM, _C32, _M, 6 }, { _LDLRM, _C32, _M, 6 }, { _LDLRM, _C32, _M, 6 }, { _LDLRM, _C32, _M, 6 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 40 - 5F */
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 60 - 7F */
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 80 - 9F */
+ { _ADDLRM, _C32, _M, 6 }, { _ADDLRM, _C32, _M, 6 }, { _ADDLRM, _C32, _M, 6 }, { _ADDLRM, _C32, _M, 6 },
+ { _ADDLRM, _C32, _M, 6 }, { _ADDLRM, _C32, _M, 6 }, { _ADDLRM, _C32, _M, 6 }, { _ADDLRM, _C32, _M, 6 },
+ { _ADDLMR, _M, _C32, 10 }, { _ADDLMR, _M, _C32, 10 }, { _ADDLMR, _M, _C32, 10 }, { _ADDLMR, _M, _C32, 10 },
+ { _ADDLMR, _M, _C32, 10 }, { _ADDLMR, _M, _C32, 10 }, { _ADDLMR, _M, _C32, 10 }, { _ADDLMR, _M, _C32, 10 },
+ { _ADCLRM, _C32, _M, 6 }, { _ADCLRM, _C32, _M, 6 }, { _ADCLRM, _C32, _M, 6 }, { _ADCLRM, _C32, _M, 6 },
+ { _ADCLRM, _C32, _M, 6 }, { _ADCLRM, _C32, _M, 6 }, { _ADCLRM, _C32, _M, 6 }, { _ADCLRM, _C32, _M, 6 },
+ { _ADCLMR, _M, _C32, 10 }, { _ADCLMR, _M, _C32, 10 }, { _ADCLMR, _M, _C32, 10 }, { _ADCLMR, _M, _C32, 10 },
+ { _ADCLMR, _M, _C32, 10 }, { _ADCLMR, _M, _C32, 10 }, { _ADCLMR, _M, _C32, 10 }, { _ADCLMR, _M, _C32, 10 },
+
+ /* A0 - BF */
+ { _SUBLRM, _C32, _M, 6 }, { _SUBLRM, _C32, _M, 6 }, { _SUBLRM, _C32, _M, 6 }, { _SUBLRM, _C32, _M, 6 },
+ { _SUBLRM, _C32, _M, 6 }, { _SUBLRM, _C32, _M, 6 }, { _SUBLRM, _C32, _M, 6 }, { _SUBLRM, _C32, _M, 6 },
+ { _SUBLMR, _M, _C32, 10 }, { _SUBLMR, _M, _C32, 10 }, { _SUBLMR, _M, _C32, 10 }, { _SUBLMR, _M, _C32, 10 },
+ { _SUBLMR, _M, _C32, 10 }, { _SUBLMR, _M, _C32, 10 }, { _SUBLMR, _M, _C32, 10 }, { _SUBLMR, _M, _C32, 10 },
+ { _SBCLRM, _C32, _M, 6 }, { _SBCLRM, _C32, _M, 6 }, { _SBCLRM, _C32, _M, 6 }, { _SBCLRM, _C32, _M, 6 },
+ { _SBCLRM, _C32, _M, 6 }, { _SBCLRM, _C32, _M, 6 }, { _SBCLRM, _C32, _M, 6 }, { _SBCLRM, _C32, _M, 6 },
+ { _SBCLMR, _M, _C32, 10 }, { _SBCLMR, _M, _C32, 10 }, { _SBCLMR, _M, _C32, 10 }, { _SBCLMR, _M, _C32, 10 },
+ { _SBCLMR, _M, _C32, 10 }, { _SBCLMR, _M, _C32, 10 }, { _SBCLMR, _M, _C32, 10 }, { _SBCLMR, _M, _C32, 10 },
+
+ /* C0 - DF */
+ { _ANDLRM, _C32, _M, 6 }, { _ANDLRM, _C32, _M, 6 }, { _ANDLRM, _C32, _M, 6 }, { _ANDLRM, _C32, _M, 6 },
+ { _ANDLRM, _C32, _M, 6 }, { _ANDLRM, _C32, _M, 6 }, { _ANDLRM, _C32, _M, 6 }, { _ANDLRM, _C32, _M, 6 },
+ { _ANDLMR, _M, _C32, 10 }, { _ANDLMR, _M, _C32, 10 }, { _ANDLMR, _M, _C32, 10 }, { _ANDLMR, _M, _C32, 10 },
+ { _ANDLMR, _M, _C32, 10 }, { _ANDLMR, _M, _C32, 10 }, { _ANDLMR, _M, _C32, 10 }, { _ANDLMR, _M, _C32, 10 },
+ { _XORLRM, _C32, _M, 6 }, { _XORLRM, _C32, _M, 6 }, { _XORLRM, _C32, _M, 6 }, { _XORLRM, _C32, _M, 6 },
+ { _XORLRM, _C32, _M, 6 }, { _XORLRM, _C32, _M, 6 }, { _XORLRM, _C32, _M, 6 }, { _XORLRM, _C32, _M, 6 },
+ { _XORLMR, _M, _C32, 10 }, { _XORLMR, _M, _C32, 10 }, { _XORLMR, _M, _C32, 10 }, { _XORLMR, _M, _C32, 10 },
+ { _XORLMR, _M, _C32, 10 }, { _XORLMR, _M, _C32, 10 }, { _XORLMR, _M, _C32, 10 }, { _XORLMR, _M, _C32, 10 },
+
+ /* E0 - FF */
+ { _ORLRM, _C32, _M, 6 }, { _ORLRM, _C32, _M, 6 }, { _ORLRM, _C32, _M, 6 }, { _ORLRM, _C32, _M, 6 },
+ { _ORLRM, _C32, _M, 6 }, { _ORLRM, _C32, _M, 6 }, { _ORLRM, _C32, _M, 6 }, { _ORLRM, _C32, _M, 6 },
+ { _ORLMR, _M, _C32, 10 }, { _ORLMR, _M, _C32, 10 }, { _ORLMR, _M, _C32, 10 }, { _ORLMR, _M, _C32, 10 },
+ { _ORLMR, _M, _C32, 10 }, { _ORLMR, _M, _C32, 10 }, { _ORLMR, _M, _C32, 10 }, { _ORLMR, _M, _C32, 10 },
+ { _CPLRM, _C32, _M, 6 }, { _CPLRM, _C32, _M, 6 }, { _CPLRM, _C32, _M, 6 }, { _CPLRM, _C32, _M, 6 },
+ { _CPLRM, _C32, _M, 6 }, { _CPLRM, _C32, _M, 6 }, { _CPLRM, _C32, _M, 6 }, { _CPLRM, _C32, _M, 6 },
+ { _CPLMR, _M, _C32, 6 }, { _CPLMR, _M, _C32, 6 }, { _CPLMR, _M, _C32, 6 }, { _CPLMR, _M, _C32, 6 },
+ { _CPLMR, _M, _C32, 6 }, { _CPLMR, _M, _C32, 6 }, { _CPLMR, _M, _C32, 6 }, { _CPLMR, _M, _C32, 6 },
+};
+
+
+static const tlcs900inst mnemonic_b0[256] =
+{
+ /* 00 - 1F */
+ { _LDBMI, _M, _I8, 5 }, { _DB, 0, 0, 1 }, { _LDWMI, _M, _I16, 6 }, { _DB, 0, 0, 1 },
+ { _POPBM, _M, 0, 6 }, { _DB, 0, 0, 1 }, { _POPWM, _M, 0, 6 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _LDBMM, _M, _M16, 8 }, { _DB, 0, 0, 1 }, { _LDWMM, _M, _M16, 8 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 20 - 3F */
+ { _LDAW, _C16, _M, 4 }, { _LDAW, _C16, _M, 4 }, { _LDAW, _C16, _M, 4 }, { _LDAW, _C16, _M, 4 },
+ { _LDAW, _C16, _M, 4 }, { _LDAW, _C16, _M, 4 }, { _LDAW, _C16, _M, 4 }, { _LDAW, _C16, _M, 4 },
+ { _ANDCFBRM, _A, _M, 8 }, { _ORCFBRM, _A, _M, 8 }, { _XORCFBRM, _A, _M, 8 }, { _LDCFBRM, _A, _M, 8 },
+ { _STCFBRM, _A, _M, 8 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _LDAL, _C32, _M, 4 }, { _LDAL, _C32, _M, 4 }, { _LDAL, _C32, _M, 4 }, { _LDAL, _C32, _M, 4 },
+ { _LDAL, _C32, _M, 4 }, { _LDAL, _C32, _M, 4 }, { _LDAL, _C32, _M, 4 }, { _LDAL, _C32, _M, 4 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 40 - 5F */
+ { _LDBMR, _M, _C8, 4 }, { _LDBMR, _M, _C8, 4 }, { _LDBMR, _M, _C8, 4 }, { _LDBMR, _M, _C8, 4 },
+ { _LDBMR, _M, _C8, 4 }, { _LDBMR, _M, _C8, 4 }, { _LDBMR, _M, _C8, 4 }, { _LDBMR, _M, _C8, 4 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _LDWMR, _M, _C16, 4 }, { _LDWMR, _M, _C16, 4 }, { _LDWMR, _M, _C16, 4 }, { _LDWMR, _M, _C16, 4 },
+ { _LDWMR, _M, _C16, 4 }, { _LDWMR, _M, _C16, 4 }, { _LDWMR, _M, _C16, 4 }, { _LDWMR, _M, _C16, 4 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 60 - 7F */
+ { _LDLMR, _M, _C32, 6 }, { _LDLMR, _M, _C32, 6 }, { _LDLMR, _M, _C32, 6 }, { _LDLMR, _M, _C32, 6 },
+ { _LDLMR, _M, _C32, 6 }, { _LDLMR, _M, _C32, 6 }, { _LDLMR, _M, _C32, 6 }, { _LDLMR, _M, _C32, 6 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 80 - 9F */
+ { _ANDCFBIM, _I3, _M, 8 }, { _ANDCFBIM, _I3, _M, 8 }, { _ANDCFBIM, _I3, _M, 8 }, { _ANDCFBIM, _I3, _M, 8 },
+ { _ANDCFBIM, _I3, _M, 8 }, { _ANDCFBIM, _I3, _M, 8 }, { _ANDCFBIM, _I3, _M, 8 }, { _ANDCFBIM, _I3, _M, 8 },
+ { _ORCFBIM, _I3, _M, 8 }, { _ORCFBIM, _I3, _M, 8 }, { _ORCFBIM, _I3, _M, 8 }, { _ORCFBIM, _I3, _M, 8 },
+ { _ORCFBIM, _I3, _M, 8 }, { _ORCFBIM, _I3, _M, 8 }, { _ORCFBIM, _I3, _M, 8 }, { _ORCFBIM, _I3, _M, 8 },
+ { _XORCFBIM, _I3, _M, 8 }, { _XORCFBIM, _I3, _M, 8 }, { _XORCFBIM, _I3, _M, 8 }, { _XORCFBIM, _I3, _M, 8 },
+ { _XORCFBIM, _I3, _M, 8 }, { _XORCFBIM, _I3, _M, 8 }, { _XORCFBIM, _I3, _M, 8 }, { _XORCFBIM, _I3, _M, 8 },
+ { _LDCFBIM, _I3, _M, 8 }, { _LDCFBIM, _I3, _M, 8 }, { _LDCFBIM, _I3, _M, 8 }, { _LDCFBIM, _I3, _M, 8 },
+ { _LDCFBIM, _I3, _M, 8 }, { _LDCFBIM, _I3, _M, 8 }, { _LDCFBIM, _I3, _M, 8 }, { _LDCFBIM, _I3, _M, 8 },
+
+ /* A0 - BF */
+ { _STCFBIM, _I3, _M, 8 }, { _STCFBIM, _I3, _M, 8 }, { _STCFBIM, _I3, _M, 8 }, { _STCFBIM, _I3, _M, 8 },
+ { _STCFBIM, _I3, _M, 8 }, { _STCFBIM, _I3, _M, 8 }, { _STCFBIM, _I3, _M, 8 }, { _STCFBIM, _I3, _M, 8 },
+ { _TSETBIM, _I3, _M, 10 }, { _TSETBIM, _I3, _M, 10 }, { _TSETBIM, _I3, _M, 10 }, { _TSETBIM, _I3, _M, 10 },
+ { _TSETBIM, _I3, _M, 10 }, { _TSETBIM, _I3, _M, 10 }, { _TSETBIM, _I3, _M, 10 }, { _TSETBIM, _I3, _M, 10 },
+ { _RESBIM, _I3, _M, 8 }, { _RESBIM, _I3, _M, 8 }, { _RESBIM, _I3, _M, 8 }, { _RESBIM, _I3, _M, 8 },
+ { _RESBIM, _I3, _M, 8 }, { _RESBIM, _I3, _M, 8 }, { _RESBIM, _I3, _M, 8 }, { _RESBIM, _I3, _M, 8 },
+ { _SETBIM, _I3, _M, 8 }, { _SETBIM, _I3, _M, 8 }, { _SETBIM, _I3, _M, 8 }, { _SETBIM, _I3, _M, 8 },
+ { _SETBIM, _I3, _M, 8 }, { _SETBIM, _I3, _M, 8 }, { _SETBIM, _I3, _M, 8 }, { _SETBIM, _I3, _M, 8 },
+
+ /* C0 - DF */
+ { _CHGBIM, _I3, _M, 8 }, { _CHGBIM, _I3, _M, 8 }, { _CHGBIM, _I3, _M, 8 }, { _CHGBIM, _I3, _M, 8 },
+ { _CHGBIM, _I3, _M, 8 }, { _CHGBIM, _I3, _M, 8 }, { _CHGBIM, _I3, _M, 8 }, { _CHGBIM, _I3, _M, 8 },
+ { _BITBIM, _I3, _M, 8 }, { _BITBIM, _I3, _M, 8 }, { _BITBIM, _I3, _M, 8 }, { _BITBIM, _I3, _M, 8 },
+ { _BITBIM, _I3, _M, 8 }, { _BITBIM, _I3, _M, 8 }, { _BITBIM, _I3, _M, 8 }, { _BITBIM, _I3, _M, 8 },
+ { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 },
+ { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 },
+ { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 },
+ { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 },
+
+ /* E0 - FF */
+ { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 },
+ { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 },
+ { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 },
+ { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 },
+ { _RETCC, _CC, 0, 6 }, { _RETCC, _CC, 0, 6 }, { _RETCC, _CC, 0, 6 }, { _RETCC, _CC, 0, 6 },
+ { _RETCC, _CC, 0, 6 }, { _RETCC, _CC, 0, 6 }, { _RETCC, _CC, 0, 6 }, { _RETCC, _CC, 0, 6 },
+ { _RETCC, _CC, 0, 6 }, { _RETCC, _CC, 0, 6 }, { _RETCC, _CC, 0, 6 }, { _RETCC, _CC, 0, 6 },
+ { _RETCC, _CC, 0, 6 }, { _RETCC, _CC, 0, 6 }, { _RETCC, _CC, 0, 6 }, { _RETCC, _CC, 0, 6 }
+};
+
+
+static const tlcs900inst mnemonic_b8[256] =
+{
+ /* 00 - 1F */
+ { _LDBMI, _M, _I8, 5 }, { _DB, 0, 0, 1 }, { _LDWMI, _M, _I16, 6 }, { _DB, 0, 0, 1 },
+ { _POPBM, _M, 0, 6 }, { _DB, 0, 0, 1 }, { _POPWM, _M, 0, 6 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _LDBMM, _M, _M16, 8 }, { _DB, 0, 0, 1 }, { _LDWMM, _M, _M16, 8 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 20 - 3F */
+ { _LDAW, _C16, _M, 4 }, { _LDAW, _C16, _M, 4 }, { _LDAW, _C16, _M, 4 }, { _LDAW, _C16, _M, 4 },
+ { _LDAW, _C16, _M, 4 }, { _LDAW, _C16, _M, 4 }, { _LDAW, _C16, _M, 4 }, { _LDAW, _C16, _M, 4 },
+ { _ANDCFBRM, _A, _M, 8 }, { _ORCFBRM, _A, _M, 8 }, { _XORCFBRM, _A, _M, 8 }, { _LDCFBRM, _A, _M, 8 },
+ { _STCFBRM, _A, _M, 8 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _LDAL, _C32, _M, 4 }, { _LDAL, _C32, _M, 4 }, { _LDAL, _C32, _M, 4 }, { _LDAL, _C32, _M, 4 },
+ { _LDAL, _C32, _M, 4 }, { _LDAL, _C32, _M, 4 }, { _LDAL, _C32, _M, 4 }, { _LDAL, _C32, _M, 4 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 40 - 5F */
+ { _LDBMR, _M, _C8, 4 }, { _LDBMR, _M, _C8, 4 }, { _LDBMR, _M, _C8, 4 }, { _LDBMR, _M, _C8, 4 },
+ { _LDBMR, _M, _C8, 4 }, { _LDBMR, _M, _C8, 4 }, { _LDBMR, _M, _C8, 4 }, { _LDBMR, _M, _C8, 4 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _LDWMR, _M, _C16, 4 }, { _LDWMR, _M, _C16, 4 }, { _LDWMR, _M, _C16, 4 }, { _LDWMR, _M, _C16, 4 },
+ { _LDWMR, _M, _C16, 4 }, { _LDWMR, _M, _C16, 4 }, { _LDWMR, _M, _C16, 4 }, { _LDWMR, _M, _C16, 4 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 60 - 7F */
+ { _LDLMR, _M, _C32, 6 }, { _LDLMR, _M, _C32, 6 }, { _LDLMR, _M, _C32, 6 }, { _LDLMR, _M, _C32, 6 },
+ { _LDLMR, _M, _C32, 6 }, { _LDLMR, _M, _C32, 6 }, { _LDLMR, _M, _C32, 6 }, { _LDLMR, _M, _C32, 6 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 80 - 9F */
+ { _ANDCFBIM, _I3, _M, 8 }, { _ANDCFBIM, _I3, _M, 8 }, { _ANDCFBIM, _I3, _M, 8 }, { _ANDCFBIM, _I3, _M, 8 },
+ { _ANDCFBIM, _I3, _M, 8 }, { _ANDCFBIM, _I3, _M, 8 }, { _ANDCFBIM, _I3, _M, 8 }, { _ANDCFBIM, _I3, _M, 8 },
+ { _ORCFBIM, _I3, _M, 8 }, { _ORCFBIM, _I3, _M, 8 }, { _ORCFBIM, _I3, _M, 8 }, { _ORCFBIM, _I3, _M, 8 },
+ { _ORCFBIM, _I3, _M, 8 }, { _ORCFBIM, _I3, _M, 8 }, { _ORCFBIM, _I3, _M, 8 }, { _ORCFBIM, _I3, _M, 8 },
+ { _XORCFBIM, _I3, _M, 8 }, { _XORCFBIM, _I3, _M, 8 }, { _XORCFBIM, _I3, _M, 8 }, { _XORCFBIM, _I3, _M, 8 },
+ { _XORCFBIM, _I3, _M, 8 }, { _XORCFBIM, _I3, _M, 8 }, { _XORCFBIM, _I3, _M, 8 }, { _XORCFBIM, _I3, _M, 8 },
+ { _LDCFBIM, _I3, _M, 8 }, { _LDCFBIM, _I3, _M, 8 }, { _LDCFBIM, _I3, _M, 8 }, { _LDCFBIM, _I3, _M, 8 },
+ { _LDCFBIM, _I3, _M, 8 }, { _LDCFBIM, _I3, _M, 8 }, { _LDCFBIM, _I3, _M, 8 }, { _LDCFBIM, _I3, _M, 8 },
+
+ /* A0 - BF */
+ { _STCFBIM, _I3, _M, 8 }, { _STCFBIM, _I3, _M, 8 }, { _STCFBIM, _I3, _M, 8 }, { _STCFBIM, _I3, _M, 8 },
+ { _STCFBIM, _I3, _M, 8 }, { _STCFBIM, _I3, _M, 8 }, { _STCFBIM, _I3, _M, 8 }, { _STCFBIM, _I3, _M, 8 },
+ { _TSETBIM, _I3, _M, 10 }, { _TSETBIM, _I3, _M, 10 }, { _TSETBIM, _I3, _M, 10 }, { _TSETBIM, _I3, _M, 10 },
+ { _TSETBIM, _I3, _M, 10 }, { _TSETBIM, _I3, _M, 10 }, { _TSETBIM, _I3, _M, 10 }, { _TSETBIM, _I3, _M, 10 },
+ { _RESBIM, _I3, _M, 8 }, { _RESBIM, _I3, _M, 8 }, { _RESBIM, _I3, _M, 8 }, { _RESBIM, _I3, _M, 8 },
+ { _RESBIM, _I3, _M, 8 }, { _RESBIM, _I3, _M, 8 }, { _RESBIM, _I3, _M, 8 }, { _RESBIM, _I3, _M, 8 },
+ { _SETBIM, _I3, _M, 8 }, { _SETBIM, _I3, _M, 8 }, { _SETBIM, _I3, _M, 8 }, { _SETBIM, _I3, _M, 8 },
+ { _SETBIM, _I3, _M, 8 }, { _SETBIM, _I3, _M, 8 }, { _SETBIM, _I3, _M, 8 }, { _SETBIM, _I3, _M, 8 },
+
+ /* C0 - DF */
+ { _CHGBIM, _I3, _M, 8 }, { _CHGBIM, _I3, _M, 8 }, { _CHGBIM, _I3, _M, 8 }, { _CHGBIM, _I3, _M, 8 },
+ { _CHGBIM, _I3, _M, 8 }, { _CHGBIM, _I3, _M, 8 }, { _CHGBIM, _I3, _M, 8 }, { _CHGBIM, _I3, _M, 8 },
+ { _BITBIM, _I3, _M, 8 }, { _BITBIM, _I3, _M, 8 }, { _BITBIM, _I3, _M, 8 }, { _BITBIM, _I3, _M, 8 },
+ { _BITBIM, _I3, _M, 8 }, { _BITBIM, _I3, _M, 8 }, { _BITBIM, _I3, _M, 8 }, { _BITBIM, _I3, _M, 8 },
+ { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 },
+ { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 },
+ { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 },
+ { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 },
+
+ /* E0 - FF */
+ { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 },
+ { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 },
+ { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 },
+ { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }
+};
+
+
+static const tlcs900inst mnemonic_c0[256] =
+{
+ /* 00 - 1F */
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _PUSHBM, _M, 0, 7 }, { _DB, 0, 0, 1 }, { _RLDRM, _A, _M, 12 }, { _RRDRM, _A, _M, 12 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _LDBMM, _M16, _M, 8 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 20 - 3F */
+ { _LDBRM, _C8, _M, 4 }, { _LDBRM, _C8, _M, 4 }, { _LDBRM, _C8, _M, 4 }, { _LDBRM, _C8, _M, 4 },
+ { _LDBRM, _C8, _M, 4 }, { _LDBRM, _C8, _M, 4 }, { _LDBRM, _C8, _M, 4 }, { _LDBRM, _C8, _M, 4 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _EXBMR, _M, _C8, 6 }, { _EXBMR, _M, _C8, 6 }, { _EXBMR, _M, _C8, 6 }, { _EXBMR, _M, _C8, 6 },
+ { _EXBMR, _M, _C8, 6 }, { _EXBMR, _M, _C8, 6 }, { _EXBMR, _M, _C8, 6 }, { _EXBMR, _M, _C8, 6 },
+ { _ADDBMI, _M, _I8, 7 }, { _ADCBMI, _M, _I8, 7 }, { _SUBBMI, _M, _I8, 7 }, { _SBCBMI, _M, _I8, 7 },
+ { _ANDBMI, _M, _I8, 7 }, { _XORBMI, _M, _I8, 7 }, { _ORBMI, _M, _I8, 7 }, { _CPBMI, _M, _I8, 6 },
+
+ /* 40 - 5F */
+ { _MULBRM, _MC16, _M, 18 }, { _MULBRM, _MC16, _M, 18 }, { _MULBRM, _MC16, _M, 18 }, { _MULBRM, _MC16, _M, 18 },
+ { _MULBRM, _MC16, _M, 18 }, { _MULBRM, _MC16, _M, 18 }, { _MULBRM, _MC16, _M, 18 }, { _MULBRM, _MC16, _M, 18 },
+ { _MULSBRM, _MC16, _M, 18 }, { _MULSBRM, _MC16, _M, 18 }, { _MULSBRM, _MC16, _M, 18 }, { _MULSBRM, _MC16, _M, 18 },
+ { _MULSBRM, _MC16, _M, 18 }, { _MULSBRM, _MC16, _M, 18 }, { _MULSBRM, _MC16, _M, 18 }, { _MULSBRM, _MC16, _M, 18 },
+ { _DIVBRM, _MC16, _M, 22 }, { _DIVBRM, _MC16, _M, 22 }, { _DIVBRM, _MC16, _M, 22 }, { _DIVBRM, _MC16, _M, 22 },
+ { _DIVBRM, _MC16, _M, 22 }, { _DIVBRM, _MC16, _M, 22 }, { _DIVBRM, _MC16, _M, 22 }, { _DIVBRM, _MC16, _M, 22 },
+ { _DIVSBRM, _MC16, _M, 24 }, { _DIVSBRM, _MC16, _M, 24 }, { _DIVSBRM, _MC16, _M, 24 }, { _DIVSBRM, _MC16, _M, 24 },
+ { _DIVSBRM, _MC16, _M, 24 }, { _DIVSBRM, _MC16, _M, 24 }, { _DIVSBRM, _MC16, _M, 24 }, { _DIVSBRM, _MC16, _M, 24 },
+
+ /* 60 - 7F */
+ { _INCBIM, _I3, _M, 6 }, { _INCBIM, _I3, _M, 6 }, { _INCBIM, _I3, _M, 6 }, { _INCBIM, _I3, _M, 6 },
+ { _INCBIM, _I3, _M, 6 }, { _INCBIM, _I3, _M, 6 }, { _INCBIM, _I3, _M, 6 }, { _INCBIM, _I3, _M, 6 },
+ { _DECBIM, _I3, _M, 6 }, { _DECBIM, _I3, _M, 6 }, { _DECBIM, _I3, _M, 6 }, { _DECBIM, _I3, _M, 6 },
+ { _DECBIM, _I3, _M, 6 }, { _DECBIM, _I3, _M, 6 }, { _DECBIM, _I3, _M, 6 }, { _DECBIM, _I3, _M, 6 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _RLCBM, _M, 0, 8 }, { _RRCBM, _M, 0, 8 }, { _RLBM, _M, 0, 8 }, { _RRBM, _M, 0, 8 },
+ { _SLABM, _M, 0, 8 }, { _SRABM, _M, 0, 8 }, { _SLLBM, _M, 0, 8 }, { _SRLBM, _M, 0, 8 },
+
+ /* 80 - 9F */
+ { _ADDBRM, _C8, _M, 4 }, { _ADDBRM, _C8, _M, 4 }, { _ADDBRM, _C8, _M, 4 }, { _ADDBRM, _C8, _M, 4 },
+ { _ADDBRM, _C8, _M, 4 }, { _ADDBRM, _C8, _M, 4 }, { _ADDBRM, _C8, _M, 4 }, { _ADDBRM, _C8, _M, 4 },
+ { _ADDBMR, _M, _C8, 6 }, { _ADDBMR, _M, _C8, 6 }, { _ADDBMR, _M, _C8, 6 }, { _ADDBMR, _M, _C8, 6 },
+ { _ADDBMR, _M, _C8, 6 }, { _ADDBMR, _M, _C8, 6 }, { _ADDBMR, _M, _C8, 6 }, { _ADDBMR, _M, _C8, 6 },
+ { _ADCBRM, _C8, _M, 4 }, { _ADCBRM, _C8, _M, 4 }, { _ADCBRM, _C8, _M, 4 }, { _ADCBRM, _C8, _M, 4 },
+ { _ADCBRM, _C8, _M, 4 }, { _ADCBRM, _C8, _M, 4 }, { _ADCBRM, _C8, _M, 4 }, { _ADCBRM, _C8, _M, 4 },
+ { _ADCBMR, _M, _C8, 6 }, { _ADCBMR, _M, _C8, 6 }, { _ADCBMR, _M, _C8, 6 }, { _ADCBMR, _M, _C8, 6 },
+ { _ADCBMR, _M, _C8, 6 }, { _ADCBMR, _M, _C8, 6 }, { _ADCBMR, _M, _C8, 6 }, { _ADCBMR, _M, _C8, 6 },
+
+ /* A0 - BF */
+ { _SUBBRM, _C8, _M, 4 }, { _SUBBRM, _C8, _M, 4 }, { _SUBBRM, _C8, _M, 4 }, { _SUBBRM, _C8, _M, 4 },
+ { _SUBBRM, _C8, _M, 4 }, { _SUBBRM, _C8, _M, 4 }, { _SUBBRM, _C8, _M, 4 }, { _SUBBRM, _C8, _M, 4 },
+ { _SUBBMR, _M, _C8, 6 }, { _SUBBMR, _M, _C8, 6 }, { _SUBBMR, _M, _C8, 6 }, { _SUBBMR, _M, _C8, 6 },
+ { _SUBBMR, _M, _C8, 6 }, { _SUBBMR, _M, _C8, 6 }, { _SUBBMR, _M, _C8, 6 }, { _SUBBMR, _M, _C8, 6 },
+ { _SBCBRM, _C8, _M, 4 }, { _SBCBRM, _C8, _M, 4 }, { _SBCBRM, _C8, _M, 4 }, { _SBCBRM, _C8, _M, 4 },
+ { _SBCBRM, _C8, _M, 4 }, { _SBCBRM, _C8, _M, 4 }, { _SBCBRM, _C8, _M, 4 }, { _SBCBRM, _C8, _M, 4 },
+ { _SBCBMR, _M, _C8, 6 }, { _SBCBMR, _M, _C8, 6 }, { _SBCBMR, _M, _C8, 6 }, { _SBCBMR, _M, _C8, 6 },
+ { _SBCBMR, _M, _C8, 6 }, { _SBCBMR, _M, _C8, 6 }, { _SBCBMR, _M, _C8, 6 }, { _SBCBMR, _M, _C8, 6 },
+
+ /* C0 - DF */
+ { _ANDBRM, _C8, _M, 4 }, { _ANDBRM, _C8, _M, 4 }, { _ANDBRM, _C8, _M, 4 }, { _ANDBRM, _C8, _M, 4 },
+ { _ANDBRM, _C8, _M, 4 }, { _ANDBRM, _C8, _M, 4 }, { _ANDBRM, _C8, _M, 4 }, { _ANDBRM, _C8, _M, 4 },
+ { _ANDBMR, _M, _C8, 6 }, { _ANDBMR, _M, _C8, 6 }, { _ANDBMR, _M, _C8, 6 }, { _ANDBMR, _M, _C8, 6 },
+ { _ANDBMR, _M, _C8, 6 }, { _ANDBMR, _M, _C8, 6 }, { _ANDBMR, _M, _C8, 6 }, { _ANDBMR, _M, _C8, 6 },
+ { _XORBRM, _C8, _M, 4 }, { _XORBRM, _C8, _M, 4 }, { _XORBRM, _C8, _M, 4 }, { _XORBRM, _C8, _M, 4 },
+ { _XORBRM, _C8, _M, 4 }, { _XORBRM, _C8, _M, 4 }, { _XORBRM, _C8, _M, 4 }, { _XORBRM, _C8, _M, 4 },
+ { _XORBMR, _M, _C8, 6 }, { _XORBMR, _M, _C8, 6 }, { _XORBMR, _M, _C8, 6 }, { _XORBMR, _M, _C8, 6 },
+ { _XORBMR, _M, _C8, 6 }, { _XORBMR, _M, _C8, 6 }, { _XORBMR, _M, _C8, 6 }, { _XORBMR, _M, _C8, 6 },
+
+ /* E0 - FF */
+ { _ORBRM, _C8, _M, 4 }, { _ORBRM, _C8, _M, 4 }, { _ORBRM, _C8, _M, 4 }, { _ORBRM, _C8, _M, 4 },
+ { _ORBRM, _C8, _M, 4 }, { _ORBRM, _C8, _M, 4 }, { _ORBRM, _C8, _M, 4 }, { _ORBRM, _C8, _M, 4 },
+ { _ORBMR, _M, _C8, 6 }, { _ORBMR, _M, _C8, 6 }, { _ORBMR, _M, _C8, 6 }, { _ORBMR, _M, _C8, 6 },
+ { _ORBMR, _M, _C8, 6 }, { _ORBMR, _M, _C8, 6 }, { _ORBMR, _M, _C8, 6 }, { _ORBMR, _M, _C8, 6 },
+ { _CPBRM, _C8, _M, 4 }, { _CPBRM, _C8, _M, 4 }, { _CPBRM, _C8, _M, 4 }, { _CPBRM, _C8, _M, 4 },
+ { _CPBRM, _C8, _M, 4 }, { _CPBRM, _C8, _M, 4 }, { _CPBRM, _C8, _M, 4 }, { _CPBRM, _C8, _M, 4 },
+ { _CPBMR, _M, _C8, 6 }, { _CPBMR, _M, _C8, 6 }, { _CPBMR, _M, _C8, 6 }, { _CPBMR, _M, _C8, 6 },
+ { _CPBMR, _M, _C8, 6 }, { _CPBMR, _M, _C8, 6 }, { _CPBMR, _M, _C8, 6 }, { _CPBMR, _M, _C8, 6 },
+};
+
+
+static const tlcs900inst mnemonic_c8[256] =
+{
+ /* 00 - 1F */
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _LDBRI, _R, _I8, 4 },
+ { _PUSHBR, _R, 0, 6 }, { _POPBR, _R, 0, 6 }, { _CPLBR, _R, 0, 4 }, { _NEGBR, _R, 0, 5 },
+ { _MULBRI, _R, _I8, 18}, { _MULSBRI, _R, _I8, 18 }, { _DIVBRI, _R, _I8, 22 }, { _DIVSBRI, _R, _I8, 24 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DAABR, _R, 0, 6 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DJNZB, _R, _D8, 7 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 20 - 3F */
+ { _ANDCFBIR, _I8, _R, 4 }, { _ORCFBIR, _I8, _R, 4 }, { _XORCFBIR, _I8, _R, 4 }, { _LDCFBIR, _I8, _R, 4 },
+ { _STCFBIR, _I8, _R, 4 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _ANDCFBRR, _A, _R, 4 }, { _ORCFBRR, _A, _R, 4 }, { _XORCFBRR, _A, _R, 4 }, { _LDCFBRR, _A, _R, 4 },
+ { _STCFBRR, _A, _R, 4 }, { _DB, 0, 0, 1 }, { _LDCBRR, _CR8, _R, 1 }, { _LDCBRR, _R, _CR8, 1 },
+ { _RESBIR, _I8, _R, 4 }, { _SETBIR, _I8, _R, 4 }, { _CHGBIR, _I8, _R, 4 }, { _BITBIR, _I8, _R, 4 },
+ { _TSETBIR, _I8, _R, 6 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 40 - 5F */
+ { _MULBRR, _MC16, _R, 18 }, { _MULBRR, _MC16, _R, 18 }, { _MULBRR, _MC16, _R, 18 }, { _MULBRR, _MC16, _R, 18 },
+ { _MULBRR, _MC16, _R, 18 }, { _MULBRR, _MC16, _R, 18 }, { _MULBRR, _MC16, _R, 18 }, { _MULBRR, _MC16, _R, 18 },
+ { _MULSBRR, _MC16, _R, 18 }, { _MULSBRR, _MC16, _R, 18 }, { _MULSBRR, _MC16, _R, 18 }, { _MULSBRR, _MC16, _R, 18 },
+ { _MULSBRR, _MC16, _R, 18 }, { _MULSBRR, _MC16, _R, 18 }, { _MULSBRR, _MC16, _R, 18 }, { _MULSBRR, _MC16, _R, 18 },
+ { _DIVBRR, _MC16, _R, 22 }, { _DIVBRR, _MC16, _R, 22 }, { _DIVBRR, _MC16, _R, 22 }, { _DIVBRR, _MC16, _R, 22 },
+ { _DIVBRR, _MC16, _R, 22 }, { _DIVBRR, _MC16, _R, 22 }, { _DIVBRR, _MC16, _R, 22 }, { _DIVBRR, _MC16, _R, 22 },
+ { _DIVSBRR, _MC16, _R, 24 }, { _DIVSBRR, _MC16, _R, 24 }, { _DIVSBRR, _MC16, _R, 24 }, { _DIVSBRR, _MC16, _R, 24 },
+ { _DIVSBRR, _MC16, _R, 24 }, { _DIVSBRR, _MC16, _R, 24 }, { _DIVSBRR, _MC16, _R, 24 }, { _DIVSBRR, _MC16, _R, 24 },
+
+ /* 60 - 7F */
+ { _INCBIR, _I3, _R, 4 }, { _INCBIR, _I3, _R, 4 }, { _INCBIR, _I3, _R, 4 }, { _INCBIR, _I3, _R, 4 },
+ { _INCBIR, _I3, _R, 4 }, { _INCBIR, _I3, _R, 4 }, { _INCBIR, _I3, _R, 4 }, { _INCBIR, _I3, _R, 4 },
+ { _DECBIR, _I3, _R, 4 }, { _DECBIR, _I3, _R, 4 }, { _DECBIR, _I3, _R, 4 }, { _DECBIR, _I3, _R, 4 },
+ { _DECBIR, _I3, _R, 4 }, { _DECBIR, _I3, _R, 4 }, { _DECBIR, _I3, _R, 4 }, { _DECBIR, _I3, _R, 4 },
+ { _SCCBR, _CC, _R, 6 }, { _SCCBR, _CC, _R, 6 }, { _SCCBR, _CC, _R, 6 }, { _SCCBR, _CC, _R, 6 },
+ { _SCCBR, _CC, _R, 6 }, { _SCCBR, _CC, _R, 6 }, { _SCCBR, _CC, _R, 6 }, { _SCCBR, _CC, _R, 6 },
+ { _SCCBR, _CC, _R, 6 }, { _SCCBR, _CC, _R, 6 }, { _SCCBR, _CC, _R, 6 }, { _SCCBR, _CC, _R, 6 },
+ { _SCCBR, _CC, _R, 6 }, { _SCCBR, _CC, _R, 6 }, { _SCCBR, _CC, _R, 6 }, { _SCCBR, _CC, _R, 6 },
+
+ /* 80 - 9F */
+ { _ADDBRR, _C8, _R, 4 }, { _ADDBRR, _C8, _R, 4 }, { _ADDBRR, _C8, _R, 4 }, { _ADDBRR, _C8, _R, 4 },
+ { _ADDBRR, _C8, _R, 4 }, { _ADDBRR, _C8, _R, 4 }, { _ADDBRR, _C8, _R, 4 }, { _ADDBRR, _C8, _R, 4 },
+ { _LDBRR, _C8, _R, 4 }, { _LDBRR, _C8, _R, 4 }, { _LDBRR, _C8, _R, 4 }, { _LDBRR, _C8, _R, 4 },
+ { _LDBRR, _C8, _R, 4 }, { _LDBRR, _C8, _R, 4 }, { _LDBRR, _C8, _R, 4 }, { _LDBRR, _C8, _R, 4 },
+ { _ADCBRR, _C8, _R, 4 }, { _ADCBRR, _C8, _R, 4 }, { _ADCBRR, _C8, _R, 4 }, { _ADCBRR, _C8, _R, 4 },
+ { _ADCBRR, _C8, _R, 4 }, { _ADCBRR, _C8, _R, 4 }, { _ADCBRR, _C8, _R, 4 }, { _ADCBRR, _C8, _R, 4 },
+ { _LDBRR, _R, _C8, 4 }, { _LDBRR, _R, _C8, 4 }, { _LDBRR, _R, _C8, 4 }, { _LDBRR, _R, _C8, 4 },
+ { _LDBRR, _R, _C8, 4 }, { _LDBRR, _R, _C8, 4 }, { _LDBRR, _R, _C8, 4 }, { _LDBRR, _R, _C8, 4 },
+
+ /* A0 - BF */
+ { _SUBBRR, _C8, _R, 4 }, { _SUBBRR, _C8, _R, 4 }, { _SUBBRR, _C8, _R, 4 }, { _SUBBRR, _C8, _R, 4 },
+ { _SUBBRR, _C8, _R, 4 }, { _SUBBRR, _C8, _R, 4 }, { _SUBBRR, _C8, _R, 4 }, { _SUBBRR, _C8, _R, 4 },
+ { _LDBRI, _R, _I3, 4 }, { _LDBRI, _R, _I3, 4 }, { _LDBRI, _R, _I3, 4 }, { _LDBRI, _R, _I3, 4 },
+ { _LDBRI, _R, _I3, 4 }, { _LDBRI, _R, _I3, 4 }, { _LDBRI, _R, _I3, 4 }, { _LDBRI, _R, _I3, 4 },
+ { _SBCBRR, _C8, _R, 4 }, { _SBCBRR, _C8, _R, 4 }, { _SBCBRR, _C8, _R, 4 }, { _SBCBRR, _C8, _R, 4 },
+ { _SBCBRR, _C8, _R, 4 }, { _SBCBRR, _C8, _R, 4 }, { _SBCBRR, _C8, _R, 4 }, { _SBCBRR, _C8, _R, 4 },
+ { _EXBRR, _C8, _R, 5 }, { _EXBRR, _C8, _R, 5 }, { _EXBRR, _C8, _R, 5 }, { _EXBRR, _C8, _R, 5 },
+ { _EXBRR, _C8, _R, 5 }, { _EXBRR, _C8, _R, 5 }, { _EXBRR, _C8, _R, 5 }, { _EXBRR, _C8, _R, 5 },
+
+ /* C0 - DF */
+ { _ANDBRR, _C8, _R, 4 }, { _ANDBRR, _C8, _R, 4 }, { _ANDBRR, _C8, _R, 4 }, { _ANDBRR, _C8, _R, 4 },
+ { _ANDBRR, _C8, _R, 4 }, { _ANDBRR, _C8, _R, 4 }, { _ANDBRR, _C8, _R, 4 }, { _ANDBRR, _C8, _R, 4 },
+ { _ADDBRI, _R, _I8, 4 }, { _ADCBRI, _R, _I8, 4 }, { _SUBBRI, _R, _I8, 4 }, { _SBCBRI, _R, _I8, 4 },
+ { _ANDBRI, _R, _I8, 4 }, { _XORBRI, _R, _I8, 4 }, { _ORBRI, _R, _I8, 4 }, { _CPBRI, _R, _I8, 4 },
+ { _XORBRR, _C8, _R, 4 }, { _XORBRR, _C8, _R, 4 }, { _XORBRR, _C8, _R, 4 }, { _XORBRR, _C8, _R, 4 },
+ { _XORBRR, _C8, _R, 4 }, { _XORBRR, _C8, _R, 4 }, { _XORBRR, _C8, _R, 4 }, { _XORBRR, _C8, _R, 4 },
+ { _CPBRI, _R, _I3, 4 }, { _CPBRI, _R, _I3, 4 }, { _CPBRI, _R, _I3, 4 }, { _CPBRI, _R, _I3, 4 },
+ { _CPBRI, _R, _I3, 4 }, { _CPBRI, _R, _I3, 4 }, { _CPBRI, _R, _I3, 4 }, { _CPBRI, _R, _I3, 4 },
+
+ /* E0 - FF */
+ { _ORBRR, _C8, _R, 4 }, { _ORBRR, _C8, _R, 4 }, { _ORBRR, _C8, _R, 4 }, { _ORBRR, _C8, _R, 4 },
+ { _ORBRR, _C8, _R, 4 }, { _ORBRR, _C8, _R, 4 }, { _ORBRR, _C8, _R, 4 }, { _ORBRR, _C8, _R, 4 },
+ { _RLCBIR, _I8, _R, 6 }, { _RRCBIR, _I8, _R, 6 }, { _RLBIR, _I8, _R, 6 }, { _RRBIR, _I8, _R, 6 },
+ { _SLABIR, _I8, _R, 6 }, { _SRABIR, _I8, _R, 6 }, { _SLLBIR, _I8, _R, 6 }, { _SRLBIR, _I8, _R, 6 },
+ { _CPBRR, _C8, _R, 4 }, { _CPBRR, _C8, _R, 4 }, { _CPBRR, _C8, _R, 4 }, { _CPBRR, _C8, _R, 4 },
+ { _CPBRR, _C8, _R, 4 }, { _CPBRR, _C8, _R, 4 }, { _CPBRR, _C8, _R, 4 }, { _CPBRR, _C8, _R, 4 },
+ { _RLCBRR, _A, _R, 6 }, { _RRCBRR, _A, _R, 6 }, { _RLBRR, _A, _R, 6 }, { _RRBRR, _A, _R, 6 },
+ { _SLABRR, _A, _R, 6 }, { _SRABRR, _A, _R, 6 }, { _SLLBRR, _A, _R, 6 }, { _SRLBRR, _A, _R, 6 }
+};
+
+
+static const tlcs900inst mnemonic_d0[256] =
+{
+ /* 00 - 1F */
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _PUSHWM, _M, 0, 7 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _LDWMM, _M16, _M, 8 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 20 - 3F */
+ { _LDWRM, _C16, _M, 4 }, { _LDWRM, _C16, _M, 4 }, { _LDWRM, _C16, _M, 4 }, { _LDWRM, _C16, _M, 4 },
+ { _LDWRM, _C16, _M, 4 }, { _LDWRM, _C16, _M, 4 }, { _LDWRM, _C16, _M, 4 }, { _LDWRM, _C16, _M, 4 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _EXWMR, _M, _C16, 6 }, { _EXWMR, _M, _C16, 6 }, { _EXWMR, _M, _C16, 6 }, { _EXWMR, _M, _C16, 6 },
+ { _EXWMR, _M, _C16, 6 }, { _EXWMR, _M, _C16, 6 }, { _EXWMR, _M, _C16, 6 }, { _EXWMR, _M, _C16, 6 },
+ { _ADDWMI, _M, _I16, 8 }, { _ADCWMI, _M, _I16, 8 }, { _SUBWMI, _M, _I16, 8 }, { _SBCWMI, _M, _I16, 8 },
+ { _ANDWMI, _M, _I16, 8 }, { _XORWMI, _M, _I16, 8 }, { _ORWMI, _M, _I16, 8 }, { _CPWMI, _M, _I16, 6 },
+
+ /* 40 - 5F */
+ { _MULWRM, _C32, _M, 26 }, { _MULWRM, _C32, _M, 26 }, { _MULWRM, _C32, _M, 26 }, { _MULWRM, _C32, _M, 26 },
+ { _MULWRM, _C32, _M, 26 }, { _MULWRM, _C32, _M, 26 }, { _MULWRM, _C32, _M, 26 }, { _MULWRM, _C32, _M, 26 },
+ { _MULSWRM, _C32, _M, 26 }, { _MULSWRM, _C32, _M, 26 }, { _MULSWRM, _C32, _M, 26 }, { _MULSWRM, _C32, _M, 26 },
+ { _MULSWRM, _C32, _M, 26 }, { _MULSWRM, _C32, _M, 26 }, { _MULSWRM, _C32, _M, 26 }, { _MULSWRM, _C32, _M, 26 },
+ { _DIVWRM, _C32, _M, 30 }, { _DIVWRM, _C32, _M, 30 }, { _DIVWRM, _C32, _M, 30 }, { _DIVWRM, _C32, _M, 30 },
+ { _DIVWRM, _C32, _M, 30 }, { _DIVWRM, _C32, _M, 30 }, { _DIVWRM, _C32, _M, 30 }, { _DIVWRM, _C32, _M, 30 },
+ { _DIVSWRM, _C32, _M, 32 }, { _DIVSWRM, _C32, _M, 32 }, { _DIVSWRM, _C32, _M, 32 }, { _DIVSWRM, _C32, _M, 32 },
+ { _DIVSWRM, _C32, _M, 32 }, { _DIVSWRM, _C32, _M, 32 }, { _DIVSWRM, _C32, _M, 32 }, { _DIVSWRM, _C32, _M, 32 },
+
+ /* 60 - 7F */
+ { _INCWIM, _I3, _M, 6 }, { _INCWIM, _I3, _M, 6 }, { _INCWIM, _I3, _M, 6 }, { _INCWIM, _I3, _M, 6 },
+ { _INCWIM, _I3, _M, 6 }, { _INCWIM, _I3, _M, 6 }, { _INCWIM, _I3, _M, 6 }, { _INCWIM, _I3, _M, 6 },
+ { _DECWIM, _I3, _M, 6 }, { _DECWIM, _I3, _M, 6 }, { _DECWIM, _I3, _M, 6 }, { _DECWIM, _I3, _M, 6 },
+ { _DECWIM, _I3, _M, 6 }, { _DECWIM, _I3, _M, 6 }, { _DECWIM, _I3, _M, 6 }, { _DECWIM, _I3, _M, 6 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _RLCWM, _M, 0, 8 }, { _RRCWM, _M, 0, 8 }, { _RLWM, _M, 0, 8 }, { _RRWM, _M, 0, 8 },
+ { _SLAWM, _M, 0, 8 }, { _SRAWM, _M, 0, 8 }, { _SLLWM, _M, 0, 8 }, { _SRLWM, _M, 0, 8 },
+
+ /* 80 - 9F */
+ { _ADDWRM, _C16, _M, 4 }, { _ADDWRM, _C16, _M, 4 }, { _ADDWRM, _C16, _M, 4 }, { _ADDWRM, _C16, _M, 4 },
+ { _ADDWRM, _C16, _M, 4 }, { _ADDWRM, _C16, _M, 4 }, { _ADDWRM, _C16, _M, 4 }, { _ADDWRM, _C16, _M, 4 },
+ { _ADDWMR, _M, _C16, 6 }, { _ADDWMR, _M, _C16, 6 }, { _ADDWMR, _M, _C16, 6 }, { _ADDWMR, _M, _C16, 6 },
+ { _ADDWMR, _M, _C16, 6 }, { _ADDWMR, _M, _C16, 6 }, { _ADDWMR, _M, _C16, 6 }, { _ADDWMR, _M, _C16, 6 },
+ { _ADCWRM, _C16, _M, 4 }, { _ADCWRM, _C16, _M, 4 }, { _ADCWRM, _C16, _M, 4 }, { _ADCWRM, _C16, _M, 4 },
+ { _ADCWRM, _C16, _M, 4 }, { _ADCWRM, _C16, _M, 4 }, { _ADCWRM, _C16, _M, 4 }, { _ADCWRM, _C16, _M, 4 },
+ { _ADCWMR, _M, _C16, 6 }, { _ADCWMR, _M, _C16, 6 }, { _ADCWMR, _M, _C16, 6 }, { _ADCWMR, _M, _C16, 6 },
+ { _ADCWMR, _M, _C16, 6 }, { _ADCWMR, _M, _C16, 6 }, { _ADCWMR, _M, _C16, 6 }, { _ADCWMR, _M, _C16, 6 },
+
+ /* A0 - BF */
+ { _SUBWRM, _C16, _M, 4 }, { _SUBWRM, _C16, _M, 4 }, { _SUBWRM, _C16, _M, 4 }, { _SUBWRM, _C16, _M, 4 },
+ { _SUBWRM, _C16, _M, 4 }, { _SUBWRM, _C16, _M, 4 }, { _SUBWRM, _C16, _M, 4 }, { _SUBWRM, _C16, _M, 4 },
+ { _SUBWMR, _M, _C16, 6 }, { _SUBWMR, _M, _C16, 6 }, { _SUBWMR, _M, _C16, 6 }, { _SUBWMR, _M, _C16, 6 },
+ { _SUBWMR, _M, _C16, 6 }, { _SUBWMR, _M, _C16, 6 }, { _SUBWMR, _M, _C16, 6 }, { _SUBWMR, _M, _C16, 6 },
+ { _SBCWRM, _C16, _M, 4 }, { _SBCWRM, _C16, _M, 4 }, { _SBCWRM, _C16, _M, 4 }, { _SBCWRM, _C16, _M, 4 },
+ { _SBCWRM, _C16, _M, 4 }, { _SBCWRM, _C16, _M, 4 }, { _SBCWRM, _C16, _M, 4 }, { _SBCWRM, _C16, _M, 4 },
+ { _SBCWMR, _M, _C16, 6 }, { _SBCWMR, _M, _C16, 6 }, { _SBCWMR, _M, _C16, 6 }, { _SBCWMR, _M, _C16, 6 },
+ { _SBCWMR, _M, _C16, 6 }, { _SBCWMR, _M, _C16, 6 }, { _SBCWMR, _M, _C16, 6 }, { _SBCWMR, _M, _C16, 6 },
+
+ /* C0 - DF */
+ { _ANDWRM, _C16, _M, 4 }, { _ANDWRM, _C16, _M, 4 }, { _ANDWRM, _C16, _M, 4 }, { _ANDWRM, _C16, _M, 4 },
+ { _ANDWRM, _C16, _M, 4 }, { _ANDWRM, _C16, _M, 4 }, { _ANDWRM, _C16, _M, 4 }, { _ANDWRM, _C16, _M, 4 },
+ { _ANDWMR, _M, _C16, 6 }, { _ANDWMR, _M, _C16, 6 }, { _ANDWMR, _M, _C16, 6 }, { _ANDWMR, _M, _C16, 6 },
+ { _ANDWMR, _M, _C16, 6 }, { _ANDWMR, _M, _C16, 6 }, { _ANDWMR, _M, _C16, 6 }, { _ANDWMR, _M, _C16, 6 },
+ { _XORWRM, _C16, _M, 4 }, { _XORWRM, _C16, _M, 4 }, { _XORWRM, _C16, _M, 4 }, { _XORWRM, _C16, _M, 4 },
+ { _XORWRM, _C16, _M, 4 }, { _XORWRM, _C16, _M, 4 }, { _XORWRM, _C16, _M, 4 }, { _XORWRM, _C16, _M, 4 },
+ { _XORWMR, _M, _C16, 6 }, { _XORWMR, _M, _C16, 6 }, { _XORWMR, _M, _C16, 6 }, { _XORWMR, _M, _C16, 6 },
+ { _XORWMR, _M, _C16, 6 }, { _XORWMR, _M, _C16, 6 }, { _XORWMR, _M, _C16, 6 }, { _XORWMR, _M, _C16, 6 },
+
+ /* E0 - FF */
+ { _ORWRM, _C16, _M, 4 }, { _ORWRM, _C16, _M, 4 }, { _ORWRM, _C16, _M, 4 }, { _ORWRM, _C16, _M, 4 },
+ { _ORWRM, _C16, _M, 4 }, { _ORWRM, _C16, _M, 4 }, { _ORWRM, _C16, _M, 4 }, { _ORWRM, _C16, _M, 4 },
+ { _ORWMR, _M, _C16, 6 }, { _ORWMR, _M, _C16, 6 }, { _ORWMR, _M, _C16, 6 }, { _ORWMR, _M, _C16, 6 },
+ { _ORWMR, _M, _C16, 6 }, { _ORWMR, _M, _C16, 6 }, { _ORWMR, _M, _C16, 6 }, { _ORWMR, _M, _C16, 6 },
+ { _CPWRM, _C16, _M, 4 }, { _CPWRM, _C16, _M, 4 }, { _CPWRM, _C16, _M, 4 }, { _CPWRM, _C16, _M, 4 },
+ { _CPWRM, _C16, _M, 4 }, { _CPWRM, _C16, _M, 4 }, { _CPWRM, _C16, _M, 4 }, { _CPWRM, _C16, _M, 4 },
+ { _CPWMR, _M, _C16, 6 }, { _CPWMR, _M, _C16, 6 }, { _CPWMR, _M, _C16, 6 }, { _CPWMR, _M, _C16, 6 },
+ { _CPWMR, _M, _C16, 6 }, { _CPWMR, _M, _C16, 6 }, { _CPWMR, _M, _C16, 6 }, { _CPWMR, _M, _C16, 6 },
+};
+
+
+static const tlcs900inst mnemonic_d8[256] =
+{
+ /* 00 - 1F */
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _LDWRI, _R, _I16, 4 },
+ { _PUSHWR, _R, 0, 5 }, { _POPWR, _R, 0, 6 }, { _CPLWR, _R, 0, 4 }, { _NEGWR, _R, 0, 5 },
+ { _MULWRI, _R, _I16, 26 }, { _MULSWRI, _R, _I16, 26 }, { _DIVWRI, _R, _I16, 30 }, { _DIVSWRI, _R, _I16, 32 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _BS1FRR, _A, _R, 4 }, { _BS1BRR, _A, _R, 4 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _EXTZWR, _R, 0, 4 }, { _EXTSWR, _R, 0, 5 },
+ { _PAAWR, _R, 0, 4 }, { _DB, 0, 0, 1 }, { _MIRRW, _R, 0, 4 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _MULAR, _R, 0, 31 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DJNZW, _R, _D8, 7 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 20 - 3F */
+ { _ANDCFWIR, _I8, _R, 4 }, { _ORCFWIR, _I8, _R, 4 }, { _XORCFWIR, _I8, _R, 4 }, { _LDCFWIR, _I8, _R, 4 },
+ { _STCFWIR, _I8, _R, 4 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _ANDCFWRR, _A, _R, 4 }, { _ORCFWRR, _A, _R, 4 }, { _XORCFWRR, _A, _R, 4 }, { _LDCFWRR, _A, _R, 4 },
+ { _STCFWRR, _A, _R, 4 }, { _DB, 0, 0, 1 }, { _LDCWRR, _CR16, _R, 1 }, { _LDCWRR, _R, _CR16, 1 },
+ { _RESWIR, _I8, _R, 4 }, { _SETWIR, _I8, _R, 4 }, { _CHGWIR, _I8, _R, 4 }, { _BITWIR, _I8, _R, 4 },
+ { _TSETWIR, _I8, _R, 6 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _MINC1, _I16, _R, 8 }, { _MINC2, _I16, _R, 8 }, { _MINC4, _I16, _R, 8 }, { _DB, 0, 0, 1 },
+ { _MDEC1, _I16, _R, 7 }, { _MDEC2, _I16, _R, 7 }, { _MDEC4, _I16, _R, 7 }, { _DB, 0, 0, 1 },
+
+ /* 40 - 5F */
+ { _MULWRR, _C32, _R, 26 }, { _MULWRR, _C32, _R, 26 }, { _MULWRR, _C32, _R, 26 }, { _MULWRR, _C32, _R, 26 },
+ { _MULWRR, _C32, _R, 26 }, { _MULWRR, _C32, _R, 26 }, { _MULWRR, _C32, _R, 26 }, { _MULWRR, _C32, _R, 26 },
+ { _MULSWRR, _C32, _R, 26 }, { _MULSWRR, _C32, _R, 26 }, { _MULSWRR, _C32, _R, 26 }, { _MULSWRR, _C32, _R, 26 },
+ { _MULSWRR, _C32, _R, 26 }, { _MULSWRR, _C32, _R, 26 }, { _MULSWRR, _C32, _R, 26 }, { _MULSWRR, _C32, _R, 26 },
+ { _DIVWRR, _C32, _R, 30 }, { _DIVWRR, _C32, _R, 30 }, { _DIVWRR, _C32, _R, 30 }, { _DIVWRR, _C32, _R, 30 },
+ { _DIVWRR, _C32, _R, 30 }, { _DIVWRR, _C32, _R, 30 }, { _DIVWRR, _C32, _R, 30 }, { _DIVWRR, _C32, _R, 30 },
+ { _DIVSWRR, _C32, _R, 32 }, { _DIVSWRR, _C32, _R, 32 }, { _DIVSWRR, _C32, _R, 32 }, { _DIVSWRR, _C32, _R, 32 },
+ { _DIVSWRR, _C32, _R, 32 }, { _DIVSWRR, _C32, _R, 32 }, { _DIVSWRR, _C32, _R, 32 }, { _DIVSWRR, _C32, _R, 32 },
+
+ /* 60 - 7F */
+ { _INCWIR, _I3, _R, 4 }, { _INCWIR, _I3, _R, 4 }, { _INCWIR, _I3, _R, 4 }, { _INCWIR, _I3, _R, 4 },
+ { _INCWIR, _I3, _R, 4 }, { _INCWIR, _I3, _R, 4 }, { _INCWIR, _I3, _R, 4 }, { _INCWIR, _I3, _R, 4 },
+ { _DECWIR, _I3, _R, 4 }, { _DECWIR, _I3, _R, 4 }, { _DECWIR, _I3, _R, 4 }, { _DECWIR, _I3, _R, 4 },
+ { _DECWIR, _I3, _R, 4 }, { _DECWIR, _I3, _R, 4 }, { _DECWIR, _I3, _R, 4 }, { _DECWIR, _I3, _R, 4 },
+ { _SCCWR, _CC, _R, 6 }, { _SCCWR, _CC, _R, 6 }, { _SCCWR, _CC, _R, 6 }, { _SCCWR, _CC, _R, 6 },
+ { _SCCWR, _CC, _R, 6 }, { _SCCWR, _CC, _R, 6 }, { _SCCWR, _CC, _R, 6 }, { _SCCWR, _CC, _R, 6 },
+ { _SCCWR, _CC, _R, 6 }, { _SCCWR, _CC, _R, 6 }, { _SCCWR, _CC, _R, 6 }, { _SCCWR, _CC, _R, 6 },
+ { _SCCWR, _CC, _R, 6 }, { _SCCWR, _CC, _R, 6 }, { _SCCWR, _CC, _R, 6 }, { _SCCWR, _CC, _R, 6 },
+
+ /* 80 - 9F */
+ { _ADDWRR, _C16, _R, 4 }, { _ADDWRR, _C16, _R, 4 }, { _ADDWRR, _C16, _R, 4 }, { _ADDWRR, _C16, _R, 4 },
+ { _ADDWRR, _C16, _R, 4 }, { _ADDWRR, _C16, _R, 4 }, { _ADDWRR, _C16, _R, 4 }, { _ADDWRR, _C16, _R, 4 },
+ { _LDWRR, _C16, _R, 4 }, { _LDWRR, _C16, _R, 4 }, { _LDWRR, _C16, _R, 4 }, { _LDWRR, _C16, _R, 4 },
+ { _LDWRR, _C16, _R, 4 }, { _LDWRR, _C16, _R, 4 }, { _LDWRR, _C16, _R, 4 }, { _LDWRR, _C16, _R, 4 },
+ { _ADCWRR, _C16, _R, 4 }, { _ADCWRR, _C16, _R, 4 }, { _ADCWRR, _C16, _R, 4 }, { _ADCWRR, _C16, _R, 4 },
+ { _ADCWRR, _C16, _R, 4 }, { _ADCWRR, _C16, _R, 4 }, { _ADCWRR, _C16, _R, 4 }, { _ADCWRR, _C16, _R, 4 },
+ { _LDWRR, _R, _C16, 4 }, { _LDWRR, _R, _C16, 4 }, { _LDWRR, _R, _C16, 4 }, { _LDWRR, _R, _C16, 4 },
+ { _LDWRR, _R, _C16, 4 }, { _LDWRR, _R, _C16, 4 }, { _LDWRR, _R, _C16, 4 }, { _LDWRR, _R, _C16, 4 },
+
+ /* A0 - BF */
+ { _SUBWRR, _C16, _R, 4 }, { _SUBWRR, _C16, _R, 4 }, { _SUBWRR, _C16, _R, 4 }, { _SUBWRR, _C16, _R, 4 },
+ { _SUBWRR, _C16, _R, 4 }, { _SUBWRR, _C16, _R, 4 }, { _SUBWRR, _C16, _R, 4 }, { _SUBWRR, _C16, _R, 4 },
+ { _LDWRI, _R, _I3, 4 }, { _LDWRI, _R, _I3, 4 }, { _LDWRI, _R, _I3, 4 }, { _LDWRI, _R, _I3, 4 },
+ { _LDWRI, _R, _I3, 4 }, { _LDWRI, _R, _I3, 4 }, { _LDWRI, _R, _I3, 4 }, { _LDWRI, _R, _I3, 4 },
+ { _SBCWRR, _C16, _R, 4 }, { _SBCWRR, _C16, _R, 4 }, { _SBCWRR, _C16, _R, 4 }, { _SBCWRR, _C16, _R, 4 },
+ { _SBCWRR, _C16, _R, 4 }, { _SBCWRR, _C16, _R, 4 }, { _SBCWRR, _C16, _R, 4 }, { _SBCWRR, _C16, _R, 4 },
+ { _EXWRR, _C16, _R, 5 }, { _EXWRR, _C16, _R, 5 }, { _EXWRR, _C16, _R, 5 }, { _EXWRR, _C16, _R, 5 },
+ { _EXWRR, _C16, _R, 5 }, { _EXWRR, _C16, _R, 5 }, { _EXWRR, _C16, _R, 5 }, { _EXWRR, _C16, _R, 5 },
+
+ /* C0 - DF */
+ { _ANDWRR, _C16, _R, 4 }, { _ANDWRR, _C16, _R, 4 }, { _ANDWRR, _C16, _R, 4 }, { _ANDWRR, _C16, _R, 4 },
+ { _ANDWRR, _C16, _R, 4 }, { _ANDWRR, _C16, _R, 4 }, { _ANDWRR, _C16, _R, 4 }, { _ANDWRR, _C16, _R, 4 },
+ { _ADDWRI, _R, _I16, 4 }, { _ADCWRI, _R, _I16, 4 }, { _SUBWRI, _R, _I16, 4 }, { _SBCWRI, _R, _I16, 4 },
+ { _ANDWRI, _R, _I16, 4 }, { _XORWRI, _R, _I16, 4 }, { _ORWRI, _R, _I16, 4 }, { _CPWRI, _R, _I16, 4 },
+ { _XORWRR, _C16, _R, 4 }, { _XORWRR, _C16, _R, 4 }, { _XORWRR, _C16, _R, 4 }, { _XORWRR, _C16, _R, 4 },
+ { _XORWRR, _C16, _R, 4 }, { _XORWRR, _C16, _R, 4 }, { _XORWRR, _C16, _R, 4 }, { _XORWRR, _C16, _R, 4 },
+ { _CPWRI, _R, _I3, 4 }, { _CPWRI, _R, _I3, 4 }, { _CPWRI, _R, _I3, 4 }, { _CPWRI, _R, _I3, 4 },
+ { _CPWRI, _R, _I3, 4 }, { _CPWRI, _R, _I3, 4 }, { _CPWRI, _R, _I3, 4 }, { _CPWRI, _R, _I3, 4 },
+
+ /* E0 - FF */
+ { _ORWRR, _C16, _R, 4 }, { _ORWRR, _C16, _R, 4 }, { _ORWRR, _C16, _R, 4 }, { _ORWRR, _C16, _R, 4 },
+ { _ORWRR, _C16, _R, 4 }, { _ORWRR, _C16, _R, 4 }, { _ORWRR, _C16, _R, 4 }, { _ORWRR, _C16, _R, 4 },
+ { _RLCWIR, _I8, _R, 6 }, { _RRCWIR, _I8, _R, 6 }, { _RLWIR, _I8, _R, 6 }, { _RRWIR, _I8, _R, 6 },
+ { _SLAWIR, _I8, _R, 6 }, { _SRAWIR, _I8, _R, 6 }, { _SLLWIR, _I8, _R, 6 }, { _SRLWIR, _I8, _R, 6 },
+ { _CPWRR, _C16, _R, 4 }, { _CPWRR, _C16, _R, 4 }, { _CPWRR, _C16, _R, 4 }, { _CPWRR, _C16, _R, 4 },
+ { _CPWRR, _C16, _R, 4 }, { _CPWRR, _C16, _R, 4 }, { _CPWRR, _C16, _R, 4 }, { _CPWRR, _C16, _R, 4 },
+ { _RLCWRR, _A, _R, 6 }, { _RRCWRR, _A, _R, 6 }, { _RLWRR, _A, _R, 6 }, { _RRWRR, _A, _R, 6 },
+ { _SLAWRR, _A, _R, 6 }, { _SRAWRR, _A, _R, 6 }, { _SLLWRR, _A, _R, 6 }, { _SRLWRR, _A, _R, 6 }
+};
+
+
+static const tlcs900inst mnemonic_e0[256] =
+{
+ /* 00 - 1F */
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 20 - 3F */
+ { _LDLRM, _C32, _M, 6 }, { _LDLRM, _C32, _M, 6 }, { _LDLRM, _C32, _M, 6 }, { _LDLRM, _C32, _M, 6 },
+ { _LDLRM, _C32, _M, 6 }, { _LDLRM, _C32, _M, 6 }, { _LDLRM, _C32, _M, 6 }, { _LDLRM, _C32, _M, 6 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 40 - 5F */
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 60 - 7F */
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 80 - 9F */
+ { _ADDLRM, _C32, _M, 6 }, { _ADDLRM, _C32, _M, 6 }, { _ADDLRM, _C32, _M, 6 }, { _ADDLRM, _C32, _M, 6 },
+ { _ADDLRM, _C32, _M, 6 }, { _ADDLRM, _C32, _M, 6 }, { _ADDLRM, _C32, _M, 6 }, { _ADDLRM, _C32, _M, 6 },
+ { _ADDLMR, _M, _C32, 10 }, { _ADDLMR, _M, _C32, 10 }, { _ADDLMR, _M, _C32, 10 }, { _ADDLMR, _M, _C32, 10 },
+ { _ADDLMR, _M, _C32, 10 }, { _ADDLMR, _M, _C32, 10 }, { _ADDLMR, _M, _C32, 10 }, { _ADDLMR, _M, _C32, 10 },
+ { _ADCLRM, _C32, _M, 6 }, { _ADCLRM, _C32, _M, 6 }, { _ADCLRM, _C32, _M, 6 }, { _ADCLRM, _C32, _M, 6 },
+ { _ADCLRM, _C32, _M, 6 }, { _ADCLRM, _C32, _M, 6 }, { _ADCLRM, _C32, _M, 6 }, { _ADCLRM, _C32, _M, 6 },
+ { _ADCLMR, _M, _C32, 10 }, { _ADCLMR, _M, _C32, 10 }, { _ADCLMR, _M, _C32, 10 }, { _ADCLMR, _M, _C32, 10 },
+ { _ADCLMR, _M, _C32, 10 }, { _ADCLMR, _M, _C32, 10 }, { _ADCLMR, _M, _C32, 10 }, { _ADCLMR, _M, _C32, 10 },
+
+ /* A0 - BF */
+ { _SUBLRM, _C32, _M, 6 }, { _SUBLRM, _C32, _M, 6 }, { _SUBLRM, _C32, _M, 6 }, { _SUBLRM, _C32, _M, 6 },
+ { _SUBLRM, _C32, _M, 6 }, { _SUBLRM, _C32, _M, 6 }, { _SUBLRM, _C32, _M, 6 }, { _SUBLRM, _C32, _M, 6 },
+ { _SUBLMR, _M, _C32, 10 }, { _SUBLMR, _M, _C32, 10 }, { _SUBLMR, _M, _C32, 10 }, { _SUBLMR, _M, _C32, 10 },
+ { _SUBLMR, _M, _C32, 10 }, { _SUBLMR, _M, _C32, 10 }, { _SUBLMR, _M, _C32, 10 }, { _SUBLMR, _M, _C32, 10 },
+ { _SBCLRM, _C32, _M, 6 }, { _SBCLRM, _C32, _M, 6 }, { _SBCLRM, _C32, _M, 6 }, { _SBCLRM, _C32, _M, 6 },
+ { _SBCLRM, _C32, _M, 6 }, { _SBCLRM, _C32, _M, 6 }, { _SBCLRM, _C32, _M, 6 }, { _SBCLRM, _C32, _M, 6 },
+ { _SBCLMR, _M, _C32, 10 }, { _SBCLMR, _M, _C32, 10 }, { _SBCLMR, _M, _C32, 10 }, { _SBCLMR, _M, _C32, 10 },
+ { _SBCLMR, _M, _C32, 10 }, { _SBCLMR, _M, _C32, 10 }, { _SBCLMR, _M, _C32, 10 }, { _SBCLMR, _M, _C32, 10 },
+
+ /* C0 - DF */
+ { _ANDLRM, _C32, _M, 6 }, { _ANDLRM, _C32, _M, 6 }, { _ANDLRM, _C32, _M, 6 }, { _ANDLRM, _C32, _M, 6 },
+ { _ANDLRM, _C32, _M, 6 }, { _ANDLRM, _C32, _M, 6 }, { _ANDLRM, _C32, _M, 6 }, { _ANDLRM, _C32, _M, 6 },
+ { _ANDLMR, _M, _C32, 10 }, { _ANDLMR, _M, _C32, 10 }, { _ANDLMR, _M, _C32, 10 }, { _ANDLMR, _M, _C32, 10 },
+ { _ANDLMR, _M, _C32, 10 }, { _ANDLMR, _M, _C32, 10 }, { _ANDLMR, _M, _C32, 10 }, { _ANDLMR, _M, _C32, 10 },
+ { _XORLRM, _C32, _M, 6 }, { _XORLRM, _C32, _M, 6 }, { _XORLRM, _C32, _M, 6 }, { _XORLRM, _C32, _M, 6 },
+ { _XORLRM, _C32, _M, 6 }, { _XORLRM, _C32, _M, 6 }, { _XORLRM, _C32, _M, 6 }, { _XORLRM, _C32, _M, 6 },
+ { _XORLMR, _M, _C32, 10 }, { _XORLMR, _M, _C32, 10 }, { _XORLMR, _M, _C32, 10 }, { _XORLMR, _M, _C32, 10 },
+ { _XORLMR, _M, _C32, 10 }, { _XORLMR, _M, _C32, 10 }, { _XORLMR, _M, _C32, 10 }, { _XORLMR, _M, _C32, 10 },
+
+ /* E0 - FF */
+ { _ORLRM, _C32, _M, 6 }, { _ORLRM, _C32, _M, 6 }, { _ORLRM, _C32, _M, 6 }, { _ORLRM, _C32, _M, 6 },
+ { _ORLRM, _C32, _M, 6 }, { _ORLRM, _C32, _M, 6 }, { _ORLRM, _C32, _M, 6 }, { _ORLRM, _C32, _M, 6 },
+ { _ORLMR, _M, _C32, 10 }, { _ORLMR, _M, _C32, 10 }, { _ORLMR, _M, _C32, 10 }, { _ORLMR, _M, _C32, 10 },
+ { _ORLMR, _M, _C32, 10 }, { _ORLMR, _M, _C32, 10 }, { _ORLMR, _M, _C32, 10 }, { _ORLMR, _M, _C32, 10 },
+ { _CPLRM, _C32, _M, 6 }, { _CPLRM, _C32, _M, 6 }, { _CPLRM, _C32, _M, 6 }, { _CPLRM, _C32, _M, 6 },
+ { _CPLRM, _C32, _M, 6 }, { _CPLRM, _C32, _M, 6 }, { _CPLRM, _C32, _M, 6 }, { _CPLRM, _C32, _M, 6 },
+ { _CPLMR, _M, _C32, 6 }, { _CPLMR, _M, _C32, 6 }, { _CPLMR, _M, _C32, 6 }, { _CPLMR, _M, _C32, 6 },
+ { _CPLMR, _M, _C32, 6 }, { _CPLMR, _M, _C32, 6 }, { _CPLMR, _M, _C32, 6 }, { _CPLMR, _M, _C32, 6 },
+};
+
+
+static const tlcs900inst mnemonic_e8[256] =
+{
+ /* 00 - 1F */
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _LDLRI, _R, _I32, 6 },
+ { _PUSHLR, _R, 0, 7 }, { _POPLR, _R, 0, 8 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _LINK, _R, _I16, 10 }, { _UNLK, _R, 0, 8 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _EXTZLR, _R, 0, 4 }, { _EXTSLR, _R, 0, 5 },
+ { _PAALR, _R, 0, 4 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 20 - 3F */
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _LDCLRR, _CR32, _R, 1 }, { _LDCLRR, _R, _CR32, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 40 - 5F */
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 60 - 7F */
+ { _INCLIR, _I3, _R, 4 }, { _INCLIR, _I3, _R, 4 }, { _INCLIR, _I3, _R, 4 }, { _INCLIR, _I3, _R, 4 },
+ { _INCLIR, _I3, _R, 4 }, { _INCLIR, _I3, _R, 4 }, { _INCLIR, _I3, _R, 4 }, { _INCLIR, _I3, _R, 4 },
+ { _DECLIR, _I3, _R, 4 }, { _DECLIR, _I3, _R, 4 }, { _DECLIR, _I3, _R, 4 }, { _DECLIR, _I3, _R, 4 },
+ { _DECLIR, _I3, _R, 4 }, { _DECLIR, _I3, _R, 4 }, { _DECLIR, _I3, _R, 4 }, { _DECLIR, _I3, _R, 4 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 80 - 9F */
+ { _ADDLRR, _C32, _R, 7 }, { _ADDLRR, _C32, _R, 7 }, { _ADDLRR, _C32, _R, 7 }, { _ADDLRR, _C32, _R, 7 },
+ { _ADDLRR, _C32, _R, 7 }, { _ADDLRR, _C32, _R, 7 }, { _ADDLRR, _C32, _R, 7 }, { _ADDLRR, _C32, _R, 7 },
+ { _LDLRR, _C32, _R, 4 }, { _LDLRR, _C32, _R, 4 }, { _LDLRR, _C32, _R, 4 }, { _LDLRR, _C32, _R, 4 },
+ { _LDLRR, _C32, _R, 4 }, { _LDLRR, _C32, _R, 4 }, { _LDLRR, _C32, _R, 4 }, { _LDLRR, _C32, _R, 4 },
+ { _ADCLRR, _C32, _R, 7 }, { _ADCLRR, _C32, _R, 7 }, { _ADCLRR, _C32, _R, 7 }, { _ADCLRR, _C32, _R, 7 },
+ { _ADCLRR, _C32, _R, 7 }, { _ADCLRR, _C32, _R, 7 }, { _ADCLRR, _C32, _R, 7 }, { _ADCLRR, _C32, _R, 7 },
+ { _LDLRR, _R, _C32, 4 }, { _LDLRR, _R, _C32, 4 }, { _LDLRR, _R, _C32, 4 }, { _LDLRR, _R, _C32, 4 },
+ { _LDLRR, _R, _C32, 4 }, { _LDLRR, _R, _C32, 4 }, { _LDLRR, _R, _C32, 4 }, { _LDLRR, _R, _C32, 4 },
+
+ /* A0 - BF */
+ { _SUBLRR, _C32, _R, 7 }, { _SUBLRR, _C32, _R, 7 }, { _SUBLRR, _C32, _R, 7 }, { _SUBLRR, _C32, _R, 7 },
+ { _SUBLRR, _C32, _R, 7 }, { _SUBLRR, _C32, _R, 7 }, { _SUBLRR, _C32, _R, 7 }, { _SUBLRR, _C32, _R, 7 },
+ { _LDLRI, _R, _I3, 4 }, { _LDLRI, _R, _I3, 4 }, { _LDLRI, _R, _I3, 4 }, { _LDLRI, _R, _I3, 4 },
+ { _LDLRI, _R, _I3, 4 }, { _LDLRI, _R, _I3, 4 }, { _LDLRI, _R, _I3, 4 }, { _LDLRI, _R, _I3, 4 },
+ { _SBCLRR, _C32, _R, 7 }, { _SBCLRR, _C32, _R, 7 }, { _SBCLRR, _C32, _R, 7 }, { _SBCLRR, _C32, _R, 7 },
+ { _SBCLRR, _C32, _R, 7 }, { _SBCLRR, _C32, _R, 7 }, { _SBCLRR, _C32, _R, 7 }, { _SBCLRR, _C32, _R, 7 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* C0 - DF */
+ { _ANDLRR, _C32, _R, 7 }, { _ANDLRR, _C32, _R, 7 }, { _ANDLRR, _C32, _R, 7 }, { _ANDLRR, _C32, _R, 7 },
+ { _ANDLRR, _C32, _R, 7 }, { _ANDLRR, _C32, _R, 7 }, { _ANDLRR, _C32, _R, 7 }, { _ANDLRR, _C32, _R, 7 },
+ { _ADDLRI, _R, _I32, 7 }, { _ADCLRI, _R, _I32, 7 }, { _SUBLRI, _R, _I32, 7 }, { _SBCLRI, _R, _I32, 7 },
+ { _ANDLRI, _R, _I32, 7 }, { _XORLRI, _R, _I32, 7 }, { _ORLRI, _R, _I32, 7 }, { _CPLRI, _R, _I32, 7 },
+ { _XORLRR, _C32, _R, 7 }, { _XORLRR, _C32, _R, 7 }, { _XORLRR, _C32, _R, 7 }, { _XORLRR, _C32, _R, 7 },
+ { _XORLRR, _C32, _R, 7 }, { _XORLRR, _C32, _R, 7 }, { _XORLRR, _C32, _R, 7 }, { _XORLRR, _C32, _R, 7 },
+ { _CPLRI, _R, _I3, 6 }, { _CPLRI, _R, _I3, 6 }, { _CPLRI, _R, _I3, 6 }, { _CPLRI, _R, _I3, 6 },
+ { _CPLRI, _R, _I3, 6 }, { _CPLRI, _R, _I3, 6 }, { _CPLRI, _R, _I3, 6 }, { _CPLRI, _R, _I3, 6 },
+
+ /* E0 - FF */
+ { _ORLRR, _C32, _R, 7 }, { _ORLRR, _C32, _R, 7 }, { _ORLRR, _C32, _R, 7 }, { _ORLRR, _C32, _R, 7 },
+ { _ORLRR, _C32, _R, 7 }, { _ORLRR, _C32, _R, 7 }, { _ORLRR, _C32, _R, 7 }, { _ORLRR, _C32, _R, 7 },
+ { _RLCLIR, _I8, _R, 8 }, { _RRCLIR, _I8, _R, 8 }, { _RLLIR, _I8, _R, 8 }, { _RRLIR, _I8, _R, 8 },
+ { _SLALIR, _I8, _R, 8 }, { _SRALIR, _I8, _R, 8 }, { _SLLLIR, _I8, _R, 8 }, { _SRLLIR, _I8, _R, 8 },
+ { _CPLRR, _C32, _R, 7 }, { _CPLRR, _C32, _R, 7 }, { _CPLRR, _C32, _R, 7 }, { _CPLRR, _C32, _R, 7 },
+ { _CPLRR, _C32, _R, 7 }, { _CPLRR, _C32, _R, 7 }, { _CPLRR, _C32, _R, 7 }, { _CPLRR, _C32, _R, 7 },
+ { _RLCLRR, _A, _R, 8 }, { _RRCLRR, _A, _R, 8 }, { _RLLRR, _A, _R, 8 }, { _RRLRR, _A, _R, 8 },
+ { _SLALRR, _A, _R, 8 }, { _SRALRR, _A, _R, 8 }, { _SLLLRR, _A, _R, 8 }, { _SRLLRR, _A, _R, 8 }
+};
+
+
+static const tlcs900inst mnemonic_f0[256] =
+{
+ /* 00 - 1F */
+ { _LDBMI, _M, _I8, 5 }, { _DB, 0, 0, 1 }, { _LDWMI, _M, _I16, 6 }, { _DB, 0, 0, 1 },
+ { _POPBM, _M, 0, 6 }, { _DB, 0, 0, 1 }, { _POPWM, _M, 0, 6 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _LDBMM, _M, _M16, 8 }, { _DB, 0, 0, 1 }, { _LDWMM, _M, _M16, 8 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 20 - 3F */
+ { _LDAW, _C16, _M, 4 }, { _LDAW, _C16, _M, 4 }, { _LDAW, _C16, _M, 4 }, { _LDAW, _C16, _M, 4 },
+ { _LDAW, _C16, _M, 4 }, { _LDAW, _C16, _M, 4 }, { _LDAW, _C16, _M, 4 }, { _LDAW, _C16, _M, 4 },
+ { _ANDCFBRM, _A, _M, 4 }, { _ORCFBRM, _A, _M, 4 }, { _XORCFBRM, _A, _M, 4 }, { _LDCFBRM, _A, _M, 4 },
+ { _STCFBRM, _A, _M, 4 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _LDAL, _C32, _M, 4 }, { _LDAL, _C32, _M, 4 }, { _LDAL, _C32, _M, 4 }, { _LDAL, _C32, _M, 4 },
+ { _LDAL, _C32, _M, 4 }, { _LDAL, _C32, _M, 4 }, { _LDAL, _C32, _M, 4 }, { _LDAL, _C32, _M, 4 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 40 - 5F */
+ { _LDBMR, _M, _C8, 4 }, { _LDBMR, _M, _C8, 4 }, { _LDBMR, _M, _C8, 4 }, { _LDBMR, _M, _C8, 4 },
+ { _LDBMR, _M, _C8, 4 }, { _LDBMR, _M, _C8, 4 }, { _LDBMR, _M, _C8, 4 }, { _LDBMR, _M, _C8, 4 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _LDWMR, _M, _C16, 4 }, { _LDWMR, _M, _C16, 4 }, { _LDWMR, _M, _C16, 4 }, { _LDWMR, _M, _C16, 4 },
+ { _LDWMR, _M, _C16, 4 }, { _LDWMR, _M, _C16, 4 }, { _LDWMR, _M, _C16, 4 }, { _LDWMR, _M, _C16, 4 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 60 - 7F */
+ { _LDLMR, _M, _C32, 6 }, { _LDLMR, _M, _C32, 6 }, { _LDLMR, _M, _C32, 6 }, { _LDLMR, _M, _C32, 6 },
+ { _LDLMR, _M, _C32, 6 }, { _LDLMR, _M, _C32, 6 }, { _LDLMR, _M, _C32, 6 }, { _LDLMR, _M, _C32, 6 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+
+ /* 80 - 9F */
+ { _ANDCFBIM, _I3, _M, 4 }, { _ANDCFBIM, _I3, _M, 4 }, { _ANDCFBIM, _I3, _M, 4 }, { _ANDCFBIM, _I3, _M, 4 },
+ { _ANDCFBIM, _I3, _M, 4 }, { _ANDCFBIM, _I3, _M, 4 }, { _ANDCFBIM, _I3, _M, 4 }, { _ANDCFBIM, _I3, _M, 4 },
+ { _ORCFBIM, _I3, _M, 4 }, { _ORCFBIM, _I3, _M, 4 }, { _ORCFBIM, _I3, _M, 4 }, { _ORCFBIM, _I3, _M, 4 },
+ { _ORCFBIM, _I3, _M, 4 }, { _ORCFBIM, _I3, _M, 4 }, { _ORCFBIM, _I3, _M, 4 }, { _ORCFBIM, _I3, _M, 4 },
+ { _XORCFBIM, _I3, _M, 4 }, { _XORCFBIM, _I3, _M, 4 }, { _XORCFBIM, _I3, _M, 4 }, { _XORCFBIM, _I3, _M, 4 },
+ { _XORCFBIM, _I3, _M, 4 }, { _XORCFBIM, _I3, _M, 4 }, { _XORCFBIM, _I3, _M, 4 }, { _XORCFBIM, _I3, _M, 4 },
+ { _LDCFBIM, _I3, _M, 4 }, { _LDCFBIM, _I3, _M, 4 }, { _LDCFBIM, _I3, _M, 4 }, { _LDCFBIM, _I3, _M, 4 },
+ { _LDCFBIM, _I3, _M, 4 }, { _LDCFBIM, _I3, _M, 4 }, { _LDCFBIM, _I3, _M, 4 }, { _LDCFBIM, _I3, _M, 4 },
+
+ /* A0 - BF */
+ { _STCFBIM, _I3, _M, 4 }, { _STCFBIM, _I3, _M, 4 }, { _STCFBIM, _I3, _M, 4 }, { _STCFBIM, _I3, _M, 4 },
+ { _STCFBIM, _I3, _M, 4 }, { _STCFBIM, _I3, _M, 4 }, { _STCFBIM, _I3, _M, 4 }, { _STCFBIM, _I3, _M, 4 },
+ { _TSETBIM, _I3, _M, 10 }, { _TSETBIM, _I3, _M, 10 }, { _TSETBIM, _I3, _M, 10 }, { _TSETBIM, _I3, _M, 10 },
+ { _TSETBIM, _I3, _M, 10 }, { _TSETBIM, _I3, _M, 10 }, { _TSETBIM, _I3, _M, 10 }, { _TSETBIM, _I3, _M, 10 },
+ { _RESBIM, _I3, _M, 8 }, { _RESBIM, _I3, _M, 8 }, { _RESBIM, _I3, _M, 8 }, { _RESBIM, _I3, _M, 8 },
+ { _RESBIM, _I3, _M, 8 }, { _RESBIM, _I3, _M, 8 }, { _RESBIM, _I3, _M, 8 }, { _RESBIM, _I3, _M, 8 },
+ { _SETBIM, _I3, _M, 8 }, { _SETBIM, _I3, _M, 8 }, { _SETBIM, _I3, _M, 8 }, { _SETBIM, _I3, _M, 8 },
+ { _SETBIM, _I3, _M, 8 }, { _SETBIM, _I3, _M, 8 }, { _SETBIM, _I3, _M, 8 }, { _SETBIM, _I3, _M, 8 },
+
+ /* C0 - DF */
+ { _CHGBIM, _I3, _M, 8 }, { _CHGBIM, _I3, _M, 8 }, { _CHGBIM, _I3, _M, 8 }, { _CHGBIM, _I3, _M, 8 },
+ { _CHGBIM, _I3, _M, 8 }, { _CHGBIM, _I3, _M, 8 }, { _CHGBIM, _I3, _M, 8 }, { _CHGBIM, _I3, _M, 8 },
+ { _BITBIM, _I3, _M, 4 }, { _BITBIM, _I3, _M, 4 }, { _BITBIM, _I3, _M, 4 }, { _BITBIM, _I3, _M, 4 },
+ { _BITBIM, _I3, _M, 4 }, { _BITBIM, _I3, _M, 4 }, { _BITBIM, _I3, _M, 4 }, { _BITBIM, _I3, _M, 4 },
+ { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 },
+ { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 },
+ { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 },
+ { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 }, { _JPM, _CC, _M, 4 },
+
+ /* E0 - FF */
+ { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 },
+ { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 },
+ { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 },
+ { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 }, { _CALLM, _CC, _M, 6 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }
+};
+
+
+/* (XWA/XBC/XDE/XHL/XIX/XIY/XIZ/XSP) used as source in byte operations */
+static void _80(tlcs900_state *cpustate)
+{
+ const tlcs900inst *inst;
+
+ /* For CPI/CPIR/CPD/CPDR/LDI/LDD/LDIR/LDDR operations */
+ cpustate->p1_reg32 = get_reg32_current( cpustate, cpustate->op - 1 );
+ cpustate->p2_reg32 = get_reg32_current( cpustate, cpustate->op );
+
+ cpustate->ea2.d = *get_reg32_current( cpustate, cpustate->op );
+ cpustate->op = RDOP();
+ inst = &mnemonic_80[cpustate->op];
+ prepare_operands( cpustate, inst );
+ inst->opfunc( cpustate );
+ cpustate->cycles += inst->cycles;
+}
+
+
+/* (XWA/XBC/XDE/XHL/XIX/XIY/XIZ/XSP + d8) used as source in byte operations */
+static void _88(tlcs900_state *cpustate)
+{
+ const tlcs900inst *inst;
+
+ /* For CPI/CPIR/CPD/CPDR/LDI/LDD/LDIR/LDDR operations */
+ cpustate->p1_reg32 = get_reg32_current( cpustate, cpustate->op - 1 );
+ cpustate->p2_reg32 = get_reg32_current( cpustate, cpustate->op );
+
+ cpustate->ea2.d = *get_reg32_current( cpustate, cpustate->op );
+ cpustate->op = RDOP();
+ cpustate->ea2.d += (INT8)cpustate->op;
+ cpustate->cycles += 2;
+ cpustate->op = RDOP();
+ inst = &mnemonic_80[cpustate->op];
+ prepare_operands( cpustate, inst );
+ inst->opfunc( cpustate );
+ cpustate->cycles += inst->cycles;
+}
+
+
+/* (XWA/XBC/XDE/XHL/XIXI/XIY/XIZ/XSP) used as source in word operations */
+static void _90(tlcs900_state *cpustate)
+{
+ const tlcs900inst *inst;
+
+ /* For CPI/CPIR/CPD/CPDR/LDI/LDD/LDIR/LDDR operations */
+ cpustate->p1_reg32 = get_reg32_current( cpustate, cpustate->op - 1 );
+ cpustate->p2_reg32 = get_reg32_current( cpustate, cpustate->op );
+
+ cpustate->ea2.d = *get_reg32_current( cpustate, cpustate->op );
+ cpustate->op = RDOP();
+ inst = &mnemonic_90[cpustate->op];
+ prepare_operands( cpustate, inst );
+ inst->opfunc( cpustate );
+ cpustate->cycles += inst->cycles;
+}
+
+
+/* (XWA/XBC/XDE/XHL/XIX/XIY/XIZ/XSP + d8) used as source in word operations */
+static void _98(tlcs900_state *cpustate)
+{
+ const tlcs900inst *inst;
+
+ cpustate->ea2.d = *get_reg32_current( cpustate, cpustate->op );
+ cpustate->op = RDOP();
+ cpustate->ea2.d += (INT8)cpustate->op;
+ cpustate->cycles += 2;
+ cpustate->op = RDOP();
+ inst = &mnemonic_98[cpustate->op];
+ prepare_operands( cpustate, inst );
+ inst->opfunc( cpustate );
+ cpustate->cycles += inst->cycles;
+}
+
+
+/* (XWA/XBC/XDE/XHL/XIX/XIY/XIZ/XSP) used as source in long word operations */
+static void _A0(tlcs900_state *cpustate)
+{
+ const tlcs900inst *inst;
+
+ cpustate->ea2.d = *get_reg32_current( cpustate, cpustate->op );
+ cpustate->op = RDOP();
+ inst = &mnemonic_a0[cpustate->op];
+ prepare_operands( cpustate, inst );
+ inst->opfunc( cpustate );
+ cpustate->cycles += inst->cycles;
+}
+
+
+/* (XWA/XBC/XDE/XHL/XIX/XIY/XIZ/XSP + d8) used as source in long word operations */
+static void _A8(tlcs900_state *cpustate)
+{
+ const tlcs900inst *inst;
+
+ cpustate->ea2.d = *get_reg32_current( cpustate, cpustate->op );
+ cpustate->op = RDOP();
+ cpustate->ea2.d += (INT8)cpustate->op;
+ cpustate->cycles += 2;
+ cpustate->op = RDOP();
+ inst = &mnemonic_a0[cpustate->op];
+ prepare_operands( cpustate, inst );
+ inst->opfunc( cpustate );
+ cpustate->cycles += inst->cycles;
+}
+
+
+/* (XWA/XBC/XDE/XHL/XIX/XIY/XIZ/XSP) used as destination in operations */
+static void _B0(tlcs900_state *cpustate)
+{
+ const tlcs900inst *inst;
+
+ cpustate->ea2.d = *get_reg32_current( cpustate, cpustate->op );
+ cpustate->op = RDOP();
+ inst = &mnemonic_b0[cpustate->op];
+ prepare_operands( cpustate, inst );
+ inst->opfunc( cpustate );
+ cpustate->cycles += inst->cycles;
+}
+
+
+/* (XWA/XBC/XDE/XHL/XIX/XIY/XIZ/XSP + d8) used as destination in operations */
+static void _B8(tlcs900_state *cpustate)
+{
+ const tlcs900inst *inst;
+
+ cpustate->ea2.d = *get_reg32_current( cpustate, cpustate->op );
+ cpustate->op = RDOP();
+ cpustate->ea2.d += (INT8)cpustate->op;
+ cpustate->cycles += 2;
+ cpustate->op = RDOP();
+ inst = &mnemonic_b8[cpustate->op];
+ prepare_operands( cpustate, inst );
+ inst->opfunc( cpustate );
+ cpustate->cycles += inst->cycles;
+}
+
+
+/* memory used as source in byte operations */
+static void _C0(tlcs900_state *cpustate)
+{
+ const tlcs900inst *inst;
+ UINT32 *reg = NULL;
+
+ switch ( cpustate->op & 0x07 )
+ {
+ case 0x00: /* (n) */
+ cpustate->ea2.d = RDOP();
+ cpustate->cycles += 2;
+ break;
+
+ case 0x01: /* (nn) */
+ cpustate->ea2.d = RDOP();
+ cpustate->ea2.b.h = RDOP();
+ cpustate->cycles += 2;
+ break;
+
+ case 0x02: /* (nnn) */
+ cpustate->ea2.d = RDOP();
+ cpustate->ea2.b.h = RDOP();
+ cpustate->ea2.b.h2 = RDOP();
+ cpustate->cycles += 3;
+ break;
+
+ case 0x03:
+ cpustate->op = RDOP();
+ switch ( cpustate->op & 0x03 )
+ {
+ /* (xrr) */
+ case 0x00:
+ cpustate->ea2.d = *get_reg32( cpustate, cpustate->op );
+ cpustate->cycles += 5;
+ break;
+
+ /* (xrr+d16) */
+ case 0x01:
+ cpustate->ea2.b.l = RDOP();
+ cpustate->ea2.b.h = RDOP();
+ cpustate->ea2.d = *get_reg32( cpustate, cpustate->op ) + cpustate->ea2.sw.l;
+ cpustate->cycles += 5;
+ break;
+
+ /* unknown/illegal */
+ case 0x02:
+ break;
+
+ case 0x03:
+ switch ( cpustate->op )
+ {
+ /* (xrr+r8) */
+ case 0x03:
+ cpustate->op = RDOP();
+ cpustate->ea2.d = *get_reg32( cpustate, cpustate->op );
+ cpustate->op = RDOP();
+ cpustate->ea2.d += (INT8) *get_reg8( cpustate, cpustate->op );
+ cpustate->cycles += 8;
+ break;
+
+ /* (xrr+r16) */
+ case 0x07:
+ cpustate->op = RDOP();
+ cpustate->ea2.d = *get_reg32( cpustate, cpustate->op );
+ cpustate->op = RDOP();
+ cpustate->ea2.d += (INT16) *get_reg16( cpustate, cpustate->op );
+ cpustate->cycles += 8;
+ break;
+
+ /* (pc+d16) */
+ case 0x13:
+ cpustate->ea2.b.l = RDOP();
+ cpustate->ea2.b.h = RDOP();
+ cpustate->ea2.d = cpustate->pc.d + cpustate->ea2.sw.l;
+ cpustate->cycles += 5;
+ break;
+ }
+ }
+ break;
+
+ case 0x04: /* (-xrr) */
+ cpustate->op = RDOP();
+ reg = get_reg32( cpustate, cpustate->op );
+ *reg -= ( 1 << ( cpustate->op & 0x03 ) );
+ cpustate->ea2.d = *reg;
+ cpustate->cycles += 3;
+ break;
+
+ case 0x05: /* (xrr+) */
+ cpustate->op = RDOP();
+ reg = get_reg32( cpustate, cpustate->op );
+ cpustate->ea2.d = *reg;
+ *reg += ( 1 << ( cpustate->op & 0x03 ) );
+ cpustate->cycles += 3;
+ break;
+ }
+ cpustate->op = RDOP();
+ inst = &mnemonic_c0[cpustate->op];
+ prepare_operands( cpustate, inst );
+ inst->opfunc( cpustate );
+ cpustate->cycles += inst->cycles;
+}
+
+
+static void oC8(tlcs900_state *cpustate)
+{
+ const tlcs900inst *inst;
+
+ if ( cpustate->op & 0x08 )
+ {
+ cpustate->p2_reg8 = get_reg8_current( cpustate, cpustate->op );
+ /* For MUL and DIV operations */
+ cpustate->p2_reg16 = get_reg16_current( cpustate, ( cpustate->op >> 1 ) & 0x03 );
+ }
+ else
+ {
+ cpustate->op = RDOP();
+ cpustate->p2_reg8 = get_reg8( cpustate, cpustate->op );
+ /* For MUL and DIV operations */
+ cpustate->p2_reg16 = get_reg16( cpustate, cpustate->op );
+ }
+ cpustate->op = RDOP();
+ inst = &mnemonic_c8[cpustate->op];
+ prepare_operands( cpustate, inst );
+ inst->opfunc( cpustate );
+ cpustate->cycles += inst->cycles;
+}
+
+
+/* memory used as source in word operations */
+static void _D0(tlcs900_state *cpustate)
+{
+ const tlcs900inst *inst;
+ UINT32 *reg = NULL;
+
+ switch ( cpustate->op & 0x07 )
+ {
+ case 0x00: /* (n) */
+ cpustate->ea2.d = RDOP();
+ cpustate->cycles += 2;
+ break;
+
+ case 0x01: /* (nn) */
+ cpustate->ea2.d = RDOP();
+ cpustate->ea2.b.h = RDOP();
+ cpustate->cycles += 2;
+ break;
+
+ case 0x02: /* (nnn) */
+ cpustate->ea2.d = RDOP();
+ cpustate->ea2.b.h = RDOP();
+ cpustate->ea2.b.h2 = RDOP();
+ cpustate->cycles += 3;
+ break;
+
+ case 0x03:
+ cpustate->op = RDOP();
+ switch ( cpustate->op & 0x03 )
+ {
+ /* (xrr) */
+ case 0x00:
+ cpustate->ea2.d = *get_reg32( cpustate, cpustate->op );
+ cpustate->cycles += 5;
+ break;
+
+ /* (xrr+d16) */
+ case 0x01:
+ cpustate->ea2.b.l = RDOP();
+ cpustate->ea2.b.h = RDOP();
+ cpustate->ea2.d = *get_reg32( cpustate, cpustate->op ) + cpustate->ea2.sw.l;
+ cpustate->cycles += 5;
+ break;
+
+ /* unknown/illegal */
+ case 0x02:
+ break;
+
+ case 0x03:
+ switch ( cpustate->op )
+ {
+ /* (xrr+r8) */
+ case 0x03:
+ cpustate->op = RDOP();
+ cpustate->ea2.d = *get_reg32( cpustate, cpustate->op );
+ cpustate->op = RDOP();
+ cpustate->ea2.d += (INT8) *get_reg8( cpustate, cpustate->op );
+ cpustate->cycles += 8;
+ break;
+
+ /* (xrr+r16) */
+ case 0x07:
+ cpustate->op = RDOP();
+ cpustate->ea2.d = *get_reg32( cpustate, cpustate->op );
+ cpustate->op = RDOP();
+ cpustate->ea2.d += (INT16) *get_reg16( cpustate, cpustate->op );
+ cpustate->cycles += 8;
+ break;
+
+ /* (pc+d16) */
+ case 0x13:
+ cpustate->ea2.b.l = RDOP();
+ cpustate->ea2.b.h = RDOP();
+ cpustate->ea2.d = cpustate->pc.d + cpustate->ea2.sw.l;
+ cpustate->cycles += 5;
+ break;
+ }
+ }
+ break;
+
+ case 0x04: /* (-xrr) */
+ cpustate->op = RDOP();
+ reg = get_reg32( cpustate, cpustate->op );
+ *reg -= ( 1 << ( cpustate->op & 0x03 ) );
+ cpustate->ea2.d = *reg;
+ cpustate->cycles += 3;
+ break;
+
+ case 0x05: /* (xrr+) */
+ cpustate->op = RDOP();
+ reg = get_reg32( cpustate, cpustate->op );
+ cpustate->ea2.d = *reg;
+ *reg += ( 1 << ( cpustate->op & 0x03 ) );
+ cpustate->cycles += 3;
+ break;
+ }
+ cpustate->op = RDOP();
+ inst = &mnemonic_d0[cpustate->op];
+ prepare_operands( cpustate, inst );
+ inst->opfunc( cpustate );
+ cpustate->cycles += inst->cycles;
+}
+
+
+static void oD8(tlcs900_state *cpustate)
+{
+ const tlcs900inst *inst;
+
+ if ( cpustate->op & 0x08 )
+ {
+ cpustate->p2_reg16 = get_reg16_current( cpustate, cpustate->op );
+ cpustate->p2_reg32 = get_reg32_current( cpustate, cpustate->op );
+ }
+ else
+ {
+ cpustate->op = RDOP();
+ cpustate->p2_reg16 = get_reg16( cpustate, cpustate->op );
+ cpustate->p2_reg32 = get_reg32( cpustate, cpustate->op );
+ }
+ cpustate->op = RDOP();
+ inst = &mnemonic_d8[cpustate->op];
+ prepare_operands( cpustate, inst );
+ inst->opfunc( cpustate );
+ cpustate->cycles += inst->cycles;
+}
+
+
+/* memory used as source in long word operations */
+static void _E0(tlcs900_state *cpustate)
+{
+ const tlcs900inst *inst;
+ UINT32 *reg = NULL;
+
+ switch ( cpustate->op & 0x07 )
+ {
+ case 0x00: /* (n) */
+ cpustate->ea2.d = RDOP();
+ cpustate->cycles += 2;
+ break;
+
+ case 0x01: /* (nn) */
+ cpustate->ea2.d = RDOP();
+ cpustate->ea2.b.h = RDOP();
+ cpustate->cycles += 2;
+ break;
+
+ case 0x02: /* (nnn) */
+ cpustate->ea2.d = RDOP();
+ cpustate->ea2.b.h = RDOP();
+ cpustate->ea2.b.h2 = RDOP();
+ cpustate->cycles += 3;
+ break;
+
+ case 0x03:
+ cpustate->op = RDOP();
+ switch ( cpustate->op & 0x03 )
+ {
+ /* (xrr) */
+ case 0x00:
+ cpustate->ea2.d = *get_reg32( cpustate, cpustate->op );
+ cpustate->cycles += 5;
+ break;
+
+ /* (xrr+d16) */
+ case 0x01:
+ cpustate->ea2.b.l = RDOP();
+ cpustate->ea2.b.h = RDOP();
+ cpustate->ea2.d = *get_reg32( cpustate, cpustate->op ) + cpustate->ea2.sw.l;
+ cpustate->cycles += 5;
+ break;
+
+ /* unknown/illegal */
+ case 0x02:
+ break;
+
+ case 0x03:
+ switch ( cpustate->op )
+ {
+ /* (xrr+r8) */
+ case 0x03:
+ cpustate->op = RDOP();
+ cpustate->ea2.d = *get_reg32( cpustate, cpustate->op );
+ cpustate->op = RDOP();
+ cpustate->ea2.d += (INT8) *get_reg8( cpustate, cpustate->op );
+ cpustate->cycles += 8;
+ break;
+
+ /* (xrr+r16) */
+ case 0x07:
+ cpustate->op = RDOP();
+ cpustate->ea2.d = *get_reg32( cpustate, cpustate->op );
+ cpustate->op = RDOP();
+ cpustate->ea2.d += (INT16) *get_reg16( cpustate, cpustate->op );
+ cpustate->cycles += 8;
+ break;
+
+ /* (pc+d16) */
+ case 0x13:
+ cpustate->ea2.b.l = RDOP();
+ cpustate->ea2.b.h = RDOP();
+ cpustate->ea2.d = cpustate->pc.d + cpustate->ea2.sw.l;
+ cpustate->cycles += 5;
+ break;
+ }
+ }
+ break;
+
+ case 0x04: /* (-xrr) */
+ cpustate->op = RDOP();
+ reg = get_reg32( cpustate, cpustate->op );
+ *reg -= ( 1 << ( cpustate->op & 0x03 ) );
+ cpustate->ea2.d = *reg;
+ cpustate->cycles += 3;
+ break;
+
+ case 0x05: /* (xrr+) */
+ cpustate->op = RDOP();
+ reg = get_reg32( cpustate, cpustate->op );
+ cpustate->ea2.d = *reg;
+ *reg += ( 1 << ( cpustate->op & 0x03 ) );
+ cpustate->cycles += 3;
+ break;
+ }
+ cpustate->op = RDOP();
+ inst = &mnemonic_e0[cpustate->op];
+ prepare_operands( cpustate, inst );
+ inst->opfunc( cpustate );
+ cpustate->cycles += inst->cycles;
+}
+
+
+static void _E8(tlcs900_state *cpustate)
+{
+ const tlcs900inst *inst;
+
+ if ( cpustate->op & 0x08 )
+ {
+ cpustate->p2_reg32 = get_reg32_current( cpustate, cpustate->op );
+ }
+ else
+ {
+ cpustate->op = RDOP();
+ cpustate->p2_reg32 = get_reg32( cpustate, cpustate->op );
+ }
+ cpustate->op = RDOP();
+ inst = &mnemonic_e8[cpustate->op];
+ prepare_operands( cpustate, inst );
+ inst->opfunc( cpustate );
+ cpustate->cycles += inst->cycles;
+}
+
+
+/* memory used as destination operations */
+static void _F0(tlcs900_state *cpustate)
+{
+ const tlcs900inst *inst;
+ UINT32 *reg = NULL;
+
+ switch ( cpustate->op & 0x07 )
+ {
+ case 0x00: /* (n) */
+ cpustate->ea2.d = RDOP();
+ cpustate->cycles += 2;
+ break;
+
+ case 0x01: /* (nn) */
+ cpustate->ea2.d = RDOP();
+ cpustate->ea2.b.h = RDOP();
+ cpustate->cycles += 2;
+ break;
+
+ case 0x02: /* (nnn) */
+ cpustate->ea2.d = RDOP();
+ cpustate->ea2.b.h = RDOP();
+ cpustate->ea2.b.h2 = RDOP();
+ cpustate->cycles += 3;
+ break;
+
+ case 0x03:
+ cpustate->op = RDOP();
+ switch ( cpustate->op & 0x03 )
+ {
+ /* (xrr) */
+ case 0x00:
+ cpustate->ea2.d = *get_reg32( cpustate, cpustate->op );
+ cpustate->cycles += 5;
+ break;
+
+ /* (xrr+d16) */
+ case 0x01:
+ cpustate->ea2.b.l = RDOP();
+ cpustate->ea2.b.h = RDOP();
+ cpustate->ea2.d = *get_reg32( cpustate, cpustate->op ) + cpustate->ea2.sw.l;
+ cpustate->cycles += 5;
+ break;
+
+ /* unknown/illegal */
+ case 0x02:
+ break;
+
+ case 0x03:
+ switch ( cpustate->op )
+ {
+ /* (xrr+r8) */
+ case 0x03:
+ cpustate->op = RDOP();
+ cpustate->ea2.d = *get_reg32( cpustate, cpustate->op );
+ cpustate->op = RDOP();
+ cpustate->ea2.d += (INT8) *get_reg8( cpustate, cpustate->op );
+ cpustate->cycles += 8;
+ break;
+
+ /* (xrr+r16) */
+ case 0x07:
+ cpustate->op = RDOP();
+ cpustate->ea2.d = *get_reg32( cpustate, cpustate->op );
+ cpustate->op = RDOP();
+ cpustate->ea2.d += (INT16) *get_reg16( cpustate, cpustate->op );
+ cpustate->cycles += 8;
+ break;
+
+ /* (pc+d16) */
+ case 0x13:
+ cpustate->ea2.b.l = RDOP();
+ cpustate->ea2.b.h = RDOP();
+ cpustate->ea2.d = cpustate->pc.d + cpustate->ea2.sw.l;
+ cpustate->cycles += 5;
+ break;
+ }
+ }
+ break;
+
+ case 0x04: /* (-xrr) */
+ cpustate->op = RDOP();
+ reg = get_reg32( cpustate, cpustate->op );
+ *reg -= ( 1 << ( cpustate->op & 0x03 ) );
+ cpustate->ea2.d = *reg;
+ cpustate->cycles += 3;
+ break;
+
+ case 0x05: /* (xrr+) */
+ cpustate->op = RDOP();
+ reg = get_reg32( cpustate, cpustate->op );
+ cpustate->ea2.d = *reg;
+ *reg += ( 1 << ( cpustate->op & 0x03 ) );
+ cpustate->cycles += 3;
+ break;
+ }
+
+ cpustate->op = RDOP();
+ inst = &mnemonic_f0[cpustate->op];
+ prepare_operands( cpustate, inst );
+ inst->opfunc( cpustate );
+ cpustate->cycles += inst->cycles;
+}
+
+
+static const tlcs900inst mnemonic[256] =
+{
+ /* 00 - 1F */
+ { _NOP, 0, 0, 1 }, { _NORMAL, 0, 0, 4 }, { _PUSHWR, _SR, 0, 4 }, { _POPWSR, _SR, 0, 6 },
+ { _MAX, 0, 0, 4 }, { _HALT, 0, 0, 8 }, { _EI, _I8, 0, 5 }, { _RETI, 0, 0, 12 },
+ { _LDBMI, _M8, _I8, 5 }, { _PUSHBI, _I8, 0, 4 }, { _LDWMI, _M8, _I16, 6 }, { _PUSHWI, _I16, 0, 5 },
+ { _INCF, 0, 0, 2 }, { _DECF, 0, 0, 2 }, { _RET, 0, 0, 9 }, { _RETD, _I16, 0, 9 },
+ { _RCF, 0, 0, 2 }, { _SCF, 0, 0, 2 }, { _CCF, 0, 0, 2 }, { _ZCF, 0, 0, 2 },
+ { _PUSHBR, _A, 0, 3 }, { _POPBR, _A, 0, 4 }, { _EXBRR, _F, _F, 2 }, { _LDF, _I8, 0, 2 },
+ { _PUSHBR, _F, 0, 3 }, { _POPBR, _F, 0, 4 }, { _JPI, _I16, 0, 7 }, { _JPI, _I24, 0, 7 },
+ { _CALLI, _I16, 0, 12 }, { _CALLI, _I24, 0, 12 }, { _CALR, _D16, 0, 12 }, { _DB, 0, 0, 1 },
+
+ /* 20 - 3F */
+ { _LDBRI, _C8, _I8, 2 }, { _LDBRI, _C8, _I8, 2 }, { _LDBRI, _C8, _I8, 2 }, { _LDBRI, _C8, _I8, 2 },
+ { _LDBRI, _C8, _I8, 2 }, { _LDBRI, _C8, _I8, 2 }, { _LDBRI, _C8, _I8, 2 }, { _LDBRI, _C8, _I8, 2 },
+ { _PUSHWR, _C16, 0, 3 }, { _PUSHWR, _C16, 0, 3 }, { _PUSHWR, _C16, 0, 3 }, { _PUSHWR, _C16, 0, 3 },
+ { _PUSHWR, _C16, 0, 3 }, { _PUSHWR, _C16, 0, 3 }, { _PUSHWR, _C16, 0, 3 }, { _PUSHWR, _C16, 0, 3 },
+ { _LDWRI, _C16, _I16, 3 }, { _LDWRI, _C16, _I16, 3 }, { _LDWRI, _C16, _I16, 3 }, { _LDWRI, _C16, _I16, 3 },
+ { _LDWRI, _C16, _I16, 3 }, { _LDWRI, _C16, _I16, 3 }, { _LDWRI, _C16, _I16, 3 }, { _LDWRI, _C16, _I16, 3 },
+ { _PUSHLR, _C32, 0, 5 }, { _PUSHLR, _C32, 0, 5 }, { _PUSHLR, _C32, 0, 5 }, { _PUSHLR, _C32, 0, 5 },
+ { _PUSHLR, _C32, 0, 5 }, { _PUSHLR, _C32, 0, 5 }, { _PUSHLR, _C32, 0, 5 }, { _PUSHLR, _C32, 0, 5 },
+
+ /* 40 - 5F */
+ { _LDLRI, _C32, _I32, 5 }, { _LDLRI, _C32, _I32, 5 }, { _LDLRI, _C32, _I32, 5 }, { _LDLRI, _C32, _I32, 5 },
+ { _LDLRI, _C32, _I32, 5 }, { _LDLRI, _C32, _I32, 5 }, { _LDLRI, _C32, _I32, 5 }, { _LDLRI, _C32, _I32, 5 },
+ { _POPWR, _C16, 0, 4 }, { _POPWR, _C16, 0, 4 }, { _POPWR, _C16, 0, 4 }, { _POPWR, _C16, 0, 4 },
+ { _POPWR, _C16, 0, 4 }, { _POPWR, _C16, 0, 4 }, { _POPWR, _C16, 0, 4 }, { _POPWR, _C16, 0, 4 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 }, { _DB, 0, 0, 1 },
+ { _POPLR, _C32, 0, 6 }, { _POPLR, _C32, 0, 6 }, { _POPLR, _C32, 0, 6 }, { _POPLR, _C32, 0, 6 },
+ { _POPLR, _C32, 0, 6 }, { _POPLR, _C32, 0, 6 }, { _POPLR, _C32, 0, 6 }, { _POPLR, _C32, 0, 6 },
+
+ /* 60 - 7F */
+ { _JR, _CC, _D8, 4 }, { _JR, _CC, _D8, 4 }, { _JR, _CC, _D8, 4 }, { _JR, _CC, _D8, 4 },
+ { _JR, _CC, _D8, 4 }, { _JR, _CC, _D8, 4 }, { _JR, _CC, _D8, 4 }, { _JR, _CC, _D8, 4 },
+ { _JR, _CC, _D8, 4 }, { _JR, _CC, _D8, 4 }, { _JR, _CC, _D8, 4 }, { _JR, _CC, _D8, 4 },
+ { _JR, _CC, _D8, 4 }, { _JR, _CC, _D8, 4 }, { _JR, _CC, _D8, 4 }, { _JR, _CC, _D8, 4 },
+ { _JRL, _CC, _D16, 4 }, { _JRL, _CC, _D16, 4 }, { _JRL, _CC, _D16, 4 }, { _JRL, _CC, _D16, 4 },
+ { _JRL, _CC, _D16, 4 }, { _JRL, _CC, _D16, 4 }, { _JRL, _CC, _D16, 4 }, { _JRL, _CC, _D16, 4 },
+ { _JRL, _CC, _D16, 4 }, { _JRL, _CC, _D16, 4 }, { _JRL, _CC, _D16, 4 }, { _JRL, _CC, _D16, 4 },
+ { _JRL, _CC, _D16, 4 }, { _JRL, _CC, _D16, 4 }, { _JRL, _CC, _D16, 4 }, { _JRL, _CC, _D16, 4 },
+
+ /* 80 - 9F */
+ { _80, 0, 0, 0 }, { _80, 0, 0, 0 }, { _80, 0, 0, 0 }, { _80, 0, 0, 0 },
+ { _80, 0, 0, 0 }, { _80, 0, 0, 0 }, { _80, 0, 0, 0 }, { _80, 0, 0, 0 },
+ { _88, 0, 0, 0 }, { _88, 0, 0, 0 }, { _88, 0, 0, 0 }, { _88, 0, 0, 0 },
+ { _88, 0, 0, 0 }, { _88, 0, 0, 0 }, { _88, 0, 0, 0 }, { _88, 0, 0, 0 },
+ { _90, 0, 0, 0 }, { _90, 0, 0, 0 }, { _90, 0, 0, 0 }, { _90, 0, 0, 0 },
+ { _90, 0, 0, 0 }, { _90, 0, 0, 0 }, { _90, 0, 0, 0 }, { _90, 0, 0, 0 },
+ { _98, 0, 0, 0 }, { _98, 0, 0, 0 }, { _98, 0, 0, 0 }, { _98, 0, 0, 0 },
+ { _98, 0, 0, 0 }, { _98, 0, 0, 0 }, { _98, 0, 0, 0 }, { _98, 0, 0, 0 },
+
+ /* A0 - BF */
+ { _A0, 0, 0, 0 }, { _A0, 0, 0, 0 }, { _A0, 0, 0, 0 }, { _A0, 0, 0, 0 },
+ { _A0, 0, 0, 0 }, { _A0, 0, 0, 0 }, { _A0, 0, 0, 0 }, { _A0, 0, 0, 0 },
+ { _A8, 0, 0, 0 }, { _A8, 0, 0, 0 }, { _A8, 0, 0, 0 }, { _A8, 0, 0, 0 },
+ { _A8, 0, 0, 0 }, { _A8, 0, 0, 0 }, { _A8, 0, 0, 0 }, { _A8, 0, 0, 0 },
+ { _B0, 0, 0, 0 }, { _B0, 0, 0, 0 }, { _B0, 0, 0, 0 }, { _B0, 0, 0, 0 },
+ { _B0, 0, 0, 0 }, { _B0, 0, 0, 0 }, { _B0, 0, 0, 0 }, { _B0, 0, 0, 0 },
+ { _B8, 0, 0, 0 }, { _B8, 0, 0, 0 }, { _B8, 0, 0, 0 }, { _B8, 0, 0, 0 },
+ { _B8, 0, 0, 0 }, { _B8, 0, 0, 0 }, { _B8, 0, 0, 0 }, { _B8, 0, 0, 0 },
+
+ /* C0 - DF */
+ { _C0, 0, 0, 0 }, { _C0, 0, 0, 0 }, { _C0, 0, 0, 0 }, { _C0, 0, 0, 0 },
+ { _C0, 0, 0, 0 }, { _C0, 0, 0, 0 }, { _DB, 0, 0, 0 }, { oC8, 0, 0, 0 },
+ { oC8, 0, 0, 0 }, { oC8, 0, 0, 0 }, { oC8, 0, 0, 0 }, { oC8, 0, 0, 0 },
+ { oC8, 0, 0, 0 }, { oC8, 0, 0, 0 }, { oC8, 0, 0, 0 }, { oC8, 0, 0, 0 },
+ { _D0, 0, 0, 0 }, { _D0, 0, 0, 0 }, { _D0, 0, 0, 0 }, { _D0, 0, 0, 0 },
+ { _D0, 0, 0, 0 }, { _D0, 0, 0, 0 }, { _DB, 0, 0, 0 }, { oD8, 0, 0, 0 },
+ { oD8, 0, 0, 0 }, { oD8, 0, 0, 0 }, { oD8, 0, 0, 0 }, { oD8, 0, 0, 0 },
+ { oD8, 0, 0, 0 }, { oD8, 0, 0, 0 }, { oD8, 0, 0, 0 }, { oD8, 0, 0, 0 },
+
+ /* E0 - FF */
+ { _E0, 0, 0, 0 }, { _E0, 0, 0, 0 }, { _E0, 0, 0, 0 }, { _E0, 0, 0, 0 },
+ { _E0, 0, 0, 0 }, { _E0, 0, 0, 0 }, { _DB, 0, 0, 0 }, { _E8, 0, 0, 0 },
+ { _E8, 0, 0, 0 }, { _E8, 0, 0, 0 }, { _E8, 0, 0, 0 }, { _E8, 0, 0, 0 },
+ { _E8, 0, 0, 0 }, { _E8, 0, 0, 0 }, { _E8, 0, 0, 0 }, { _E8, 0, 0, 0 },
+ { _F0, 0, 0, 0 }, { _F0, 0, 0, 0 }, { _F0, 0, 0, 0 }, { _F0, 0, 0, 0 },
+ { _F0, 0, 0, 0 }, { _F0, 0, 0, 0 }, { _DB, 0, 0, 0 }, { _LDX, 0, 0, 9 },
+ { _SWI, _I3, 0, 16 }, { _SWI, _I3, 0, 16 }, { _SWI, _I3, 0, 16 }, { _SWI, _I3, 0, 16 },
+ { _SWI, _I3, 0, 16 }, { _SWI, _I3, 0, 16 }, { _SWI, _I3, 0, 16 }, { _SWI, _I3, 0, 16 }
+};
+
+
diff --git a/trunk/src/emu/cpu/tlcs900/dasm900.c b/trunk/src/emu/cpu/tlcs900/dasm900.c
new file mode 100644
index 00000000000..3eed2d317cc
--- /dev/null
+++ b/trunk/src/emu/cpu/tlcs900/dasm900.c
@@ -0,0 +1,2256 @@
+/*******************************************************************
+
+Toshiba TLCS-900/H disassembly
+
+*******************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "tlcs900.h"
+
+enum e_mnemonics
+{
+ M_ADC, M_ADD, M_AND, M_ANDCF, M_BIT, M_BS1B,
+ M_BS1F, M_CALL, M_CALR, M_CCF, M_CHG, M_CP,
+ M_CPD, M_CPDW, M_CPDR, M_CPDRW, M_CPI, M_CPIR,
+ M_CPIRW, M_CPIW, M_CPL, M_DAA, M_DB, M_DEC,
+ M_DECF, M_DECW, M_DIV, M_DIVS, M_DJNZ, M_EI,
+ M_EX, M_EXTS, M_EXTZ, M_HALT, M_INC, M_INCF,
+ M_INCW, M_JP, M_JR, M_JRL, M_LD, M_LDA,
+ M_LDC, M_LDCF, M_LDD, M_LDDR, M_LDDRW, M_LDDW,
+ M_LDF, M_LDI, M_LDIR, M_LDIRW, M_LDIW, M_LDW,
+ M_LDX, M_LINK, M_MAX, M_MDEC1, M_MDEC2, M_MDEC4,
+ M_MINC1, M_MINC2, M_MINC4, M_MIRR, M_MUL, M_MULA,
+ M_MULS, M_NEG, M_NOP, M_NORMAL, M_OR, M_ORCF,
+ M_PAA, M_POP, M_POPW, M_PUSH, M_PUSHW, M_RCF,
+ M_RES, M_RET, M_RETD, M_RETI, M_RL, M_RLC,
+ M_RLCW, M_RLD, M_RLW, M_RR, M_RRC, M_RRCW,
+ M_RRD, M_RRW, M_SBC, M_SCC, M_SCF, M_SET,
+ M_SLA, M_SLAW, M_SLL, M_SLLW, M_SRA, M_SRAW,
+ M_SRL, M_SRLW, M_STCF, M_SUB, M_SWI, M_TSET,
+ M_UNLK, M_XOR, M_XORCF, M_ZCF,
+ M_80, M_88, M_90, M_98, M_A0, M_A8, M_B0, M_B8,
+ M_C0, oC8, M_D0, oD8, M_E0, M_E8, M_F0
+};
+
+
+static const char *const s_mnemonic[] =
+{
+ "adc", "add", "and", "andcf", "bit", "bs1b",
+ "bs1f", "call", "calr", "ccf", "chg", "cp",
+ "cpd", "cpdw", "cpdr", "cpdrw", "cpi", "cpir",
+ "cpirw", "cpiw", "cpl", "daa", "db", "dec",
+ "decf", "decw", "div", "divs", "djnz", "ei",
+ "ex", "exts", "extz", "halt", "inc", "incf",
+ "incw", "jp" ,"jr", "jrl", "ld", "lda",
+ "ldc", "ldcf", "ldd", "lddr", "lddrw", "lddw",
+ "ldf", "ldi", "ldir", "ldirw", "ldiw", "ldw",
+ "ldx", "link", "max", "mdec1", "mdec2", "mdec4",
+ "minc1", "minc2", "minc4", "mirr", "mul", "mula",
+ "muls", "neg", "nop", "normal", "or", "orcf",
+ "paa", "pop", "popw", "push", "pushw", "rcf",
+ "res", "ret", "retd", "reti", "rl", "rlc",
+ "rlcw", "rld", "rlw", "rr", "rrc", "rrcw",
+ "rrd", "rrw", "sbc", "scc", "scf", "set",
+ "sla", "slaw", "sll", "sllw", "sra", "sraw",
+ "srl", "srlw", "stcf", "sub", "swi", "tset",
+ "unlk", "xor", "xorcf", "zcf",
+ "db", "db", "db", "db", "db", "db", "db", "db",
+ "db", "db", "db", "db", "db", "db", "db"
+};
+
+
+enum e_operand
+{
+ O_NONE,
+ O_A, /* currect register set register A */
+ O_C8, /* current register set byte */
+ O_C16, /* current register set word */
+ O_C32, /* current register set long word */
+ O_MC16, /* current register set mul/div register word */
+ O_CC, /* condition */
+ O_CR8, /* byte control register */
+ O_CR16, /* word control register */
+ O_CR32, /* long word control register */
+ O_D8, /* byte displacement */
+ O_D16, /* word displacement */
+ O_F, /* F register */
+ O_I3, /* immediate 3 bit (part of last byte) */
+ O_I8, /* immediate byte */
+ O_I16, /* immediate word */
+ O_I24, /* immediate 3 byte address */
+ O_I32, /* immediate long word */
+ O_M, /* memory location (defined by extension) */
+ O_M8, /* (8) */
+ O_M16, /* (i16) */
+ O_R, /* register */
+ O_SR, /* status register */
+};
+
+
+typedef struct
+{
+ e_mnemonics mnemonic;
+ e_operand operand1;
+ e_operand operand2;
+} tlcs900inst;
+
+
+static const tlcs900inst mnemonic_80[256] =
+{
+ /* 00 - 1F */
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_PUSH, O_M, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_RLD, O_A, O_M }, { M_RRD, O_A, O_M },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_LDI, O_NONE, O_NONE }, { M_LDIR, O_NONE, O_NONE }, { M_LDD, O_NONE, O_NONE }, { M_LDDR, O_NONE, O_NONE },
+ { M_CPI, O_NONE, O_NONE }, { M_CPIR, O_NONE, O_NONE }, { M_CPD, O_NONE, O_NONE }, { M_CPDR, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_LD, O_M16, O_M }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 20 - 3F */
+ { M_LD, O_C8, O_M }, { M_LD, O_C8, O_M }, { M_LD, O_C8, O_M }, { M_LD, O_C8, O_M },
+ { M_LD, O_C8, O_M }, { M_LD, O_C8, O_M }, { M_LD, O_C8, O_M }, { M_LD, O_C8, O_M },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_EX, O_M, O_C8 }, { M_EX, O_M, O_C8 }, { M_EX, O_M, O_C8 }, { M_EX, O_M, O_C8 },
+ { M_EX, O_M, O_C8 }, { M_EX, O_M, O_C8 }, { M_EX, O_M, O_C8 }, { M_EX, O_M, O_C8 },
+ { M_ADD, O_M, O_I8 }, { M_ADC, O_M, O_I8 }, { M_SUB, O_M, O_I8 }, { M_SBC, O_M, O_I8 },
+ { M_AND, O_M, O_I8 }, { M_XOR, O_M, O_I8 }, { M_OR, O_M, O_I8 }, { M_CP, O_M, O_I8 },
+
+ /* 40 - 5F */
+ { M_MUL, O_MC16, O_M }, { M_MUL, O_MC16, O_M }, { M_MUL, O_MC16, O_M }, { M_MUL, O_MC16, O_M },
+ { M_MUL, O_MC16, O_M }, { M_MUL, O_MC16, O_M }, { M_MUL, O_MC16, O_M }, { M_MUL, O_MC16, O_M },
+ { M_MULS, O_MC16, O_M }, { M_MULS, O_MC16, O_M }, { M_MULS, O_MC16, O_M }, { M_MULS, O_MC16, O_M },
+ { M_MULS, O_MC16, O_M }, { M_MULS, O_MC16, O_M }, { M_MULS, O_MC16, O_M }, { M_MULS, O_MC16, O_M },
+ { M_DIV, O_MC16, O_M }, { M_DIV, O_MC16, O_M }, { M_DIV, O_MC16, O_M }, { M_DIV, O_MC16, O_M },
+ { M_DIV, O_MC16, O_M }, { M_DIV, O_MC16, O_M }, { M_DIV, O_MC16, O_M }, { M_DIV, O_MC16, O_M },
+ { M_DIVS, O_MC16, O_M }, { M_DIVS, O_MC16, O_M }, { M_DIVS, O_MC16, O_M }, { M_DIVS, O_MC16, O_M },
+ { M_DIVS, O_MC16, O_M }, { M_DIVS, O_MC16, O_M }, { M_DIVS, O_MC16, O_M }, { M_DIVS, O_MC16, O_M },
+
+ /* 60 - 7F */
+ { M_INC, O_I3, O_M }, { M_INC, O_I3, O_M }, { M_INC, O_I3, O_M }, { M_INC, O_I3, O_M },
+ { M_INC, O_I3, O_M }, { M_INC, O_I3, O_M }, { M_INC, O_I3, O_M }, { M_INC, O_I3, O_M },
+ { M_DEC, O_I3, O_M }, { M_DEC, O_I3, O_M }, { M_DEC, O_I3, O_M }, { M_DEC, O_I3, O_M },
+ { M_DEC, O_I3, O_M }, { M_DEC, O_I3, O_M }, { M_DEC, O_I3, O_M }, { M_DEC, O_I3, O_M },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_RLC, O_M, O_NONE }, { M_RRC, O_M, O_NONE }, { M_RL, O_M, O_NONE }, { M_RR, O_M, O_NONE },
+ { M_SLA, O_M, O_NONE }, { M_SRA, O_M, O_NONE }, { M_SLL, O_M, O_NONE }, { M_SRL, O_M, O_NONE },
+
+ /* 80 - 9F */
+ { M_ADD, O_C8, O_M }, { M_ADD, O_C8, O_M }, { M_ADD, O_C8, O_M }, { M_ADD, O_C8, O_M },
+ { M_ADD, O_C8, O_M }, { M_ADD, O_C8, O_M }, { M_ADD, O_C8, O_M }, { M_ADD, O_C8, O_M },
+ { M_ADD, O_M, O_C8 }, { M_ADD, O_M, O_C8 }, { M_ADD, O_M, O_C8 }, { M_ADD, O_M, O_C8 },
+ { M_ADD, O_M, O_C8 }, { M_ADD, O_M, O_C8 }, { M_ADD, O_M, O_C8 }, { M_ADD, O_M, O_C8 },
+ { M_ADC, O_C8, O_M }, { M_ADC, O_C8, O_M }, { M_ADC, O_C8, O_M }, { M_ADC, O_C8, O_M },
+ { M_ADC, O_C8, O_M }, { M_ADC, O_C8, O_M }, { M_ADC, O_C8, O_M }, { M_ADC, O_C8, O_M },
+ { M_ADC, O_M, O_C8 }, { M_ADC, O_M, O_C8 }, { M_ADC, O_M, O_C8 }, { M_ADC, O_M, O_C8 },
+ { M_ADC, O_M, O_C8 }, { M_ADC, O_M, O_C8 }, { M_ADC, O_M, O_C8 }, { M_ADC, O_M, O_C8 },
+
+ /* A0 - BF */
+ { M_SUB, O_C8, O_M }, { M_SUB, O_C8, O_M }, { M_SUB, O_C8, O_M }, { M_SUB, O_C8, O_M },
+ { M_SUB, O_C8, O_M }, { M_SUB, O_C8, O_M }, { M_SUB, O_C8, O_M }, { M_SUB, O_C8, O_M },
+ { M_SUB, O_M, O_C8 }, { M_SUB, O_M, O_C8 }, { M_SUB, O_M, O_C8 }, { M_SUB, O_M, O_C8 },
+ { M_SUB, O_M, O_C8 }, { M_SUB, O_M, O_C8 }, { M_SUB, O_M, O_C8 }, { M_SUB, O_M, O_C8 },
+ { M_SBC, O_C8, O_M }, { M_SBC, O_C8, O_M }, { M_SBC, O_C8, O_M }, { M_SBC, O_C8, O_M },
+ { M_SBC, O_C8, O_M }, { M_SBC, O_C8, O_M }, { M_SBC, O_C8, O_M }, { M_SBC, O_C8, O_M },
+ { M_SBC, O_M, O_C8 }, { M_SBC, O_M, O_C8 }, { M_SBC, O_M, O_C8 }, { M_SBC, O_M, O_C8 },
+ { M_SBC, O_M, O_C8 }, { M_SBC, O_M, O_C8 }, { M_SBC, O_M, O_C8 }, { M_SBC, O_M, O_C8 },
+
+ /* C0 - DF */
+ { M_AND, O_C8, O_M }, { M_AND, O_C8, O_M }, { M_AND, O_C8, O_M }, { M_AND, O_C8, O_M },
+ { M_AND, O_C8, O_M }, { M_AND, O_C8, O_M }, { M_AND, O_C8, O_M }, { M_AND, O_C8, O_M },
+ { M_AND, O_M, O_C8 }, { M_AND, O_M, O_C8 }, { M_AND, O_M, O_C8 }, { M_AND, O_M, O_C8 },
+ { M_AND, O_M, O_C8 }, { M_AND, O_M, O_C8 }, { M_AND, O_M, O_C8 }, { M_AND, O_M, O_C8 },
+ { M_XOR, O_C8, O_M }, { M_XOR, O_C8, O_M }, { M_XOR, O_C8, O_M }, { M_XOR, O_C8, O_M },
+ { M_XOR, O_C8, O_M }, { M_XOR, O_C8, O_M }, { M_XOR, O_C8, O_M }, { M_XOR, O_C8, O_M },
+ { M_XOR, O_M, O_C8 }, { M_XOR, O_M, O_C8 }, { M_XOR, O_M, O_C8 }, { M_XOR, O_M, O_C8 },
+ { M_XOR, O_M, O_C8 }, { M_XOR, O_M, O_C8 }, { M_XOR, O_M, O_C8 }, { M_XOR, O_M, O_C8 },
+
+ /* E0 - FF */
+ { M_OR, O_C8, O_M }, { M_OR, O_C8, O_M }, { M_OR, O_C8, O_M }, { M_OR, O_C8, O_M },
+ { M_OR, O_C8, O_M }, { M_OR, O_C8, O_M }, { M_OR, O_C8, O_M }, { M_OR, O_C8, O_M },
+ { M_OR, O_M, O_C8 }, { M_OR, O_M, O_C8 }, { M_OR, O_M, O_C8 }, { M_OR, O_M, O_C8 },
+ { M_OR, O_M, O_C8 }, { M_OR, O_M, O_C8 }, { M_OR, O_M, O_C8 }, { M_OR, O_M, O_C8 },
+ { M_CP, O_C8, O_M }, { M_CP, O_C8, O_M }, { M_CP, O_C8, O_M }, { M_CP, O_C8, O_M },
+ { M_CP, O_C8, O_M }, { M_CP, O_C8, O_M }, { M_CP, O_C8, O_M }, { M_CP, O_C8, O_M },
+ { M_CP, O_M, O_C8 }, { M_CP, O_M, O_C8 }, { M_CP, O_M, O_C8 }, { M_CP, O_M, O_C8 },
+ { M_CP, O_M, O_C8 }, { M_CP, O_M, O_C8 }, { M_CP, O_M, O_C8 }, { M_CP, O_M, O_C8 },
+};
+
+
+static const tlcs900inst mnemonic_88[256] =
+{
+ /* 00 - 1F */
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_PUSH, O_M, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_RLD, O_A, O_M }, { M_RRD, O_A, O_M },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_LD, O_M16, O_M }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 20 - 3F */
+ { M_LD, O_C8, O_M }, { M_LD, O_C8, O_M }, { M_LD, O_C8, O_M }, { M_LD, O_C8, O_M },
+ { M_LD, O_C8, O_M }, { M_LD, O_C8, O_M }, { M_LD, O_C8, O_M }, { M_LD, O_C8, O_M },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_EX, O_M, O_C8 }, { M_EX, O_M, O_C8 }, { M_EX, O_M, O_C8 }, { M_EX, O_M, O_C8 },
+ { M_EX, O_M, O_C8 }, { M_EX, O_M, O_C8 }, { M_EX, O_M, O_C8 }, { M_EX, O_M, O_C8 },
+ { M_ADD, O_M, O_I8 }, { M_ADC, O_M, O_I8 }, { M_SUB, O_M, O_I8 }, { M_SBC, O_M, O_I8 },
+ { M_AND, O_M, O_I8 }, { M_XOR, O_M, O_I8 }, { M_OR, O_M, O_I8 }, { M_CP, O_M, O_I8 },
+
+ /* 40 - 5F */
+ { M_MUL, O_MC16, O_M }, { M_MUL, O_MC16, O_M }, { M_MUL, O_MC16, O_M }, { M_MUL, O_MC16, O_M },
+ { M_MUL, O_MC16, O_M }, { M_MUL, O_MC16, O_M }, { M_MUL, O_MC16, O_M }, { M_MUL, O_MC16, O_M },
+ { M_MULS, O_MC16, O_M }, { M_MULS, O_MC16, O_M }, { M_MULS, O_MC16, O_M }, { M_MULS, O_MC16, O_M },
+ { M_MULS, O_MC16, O_M }, { M_MULS, O_MC16, O_M }, { M_MULS, O_MC16, O_M }, { M_MULS, O_MC16, O_M },
+ { M_DIV, O_MC16, O_M }, { M_DIV, O_MC16, O_M }, { M_DIV, O_MC16, O_M }, { M_DIV, O_MC16, O_M },
+ { M_DIV, O_MC16, O_M }, { M_DIV, O_MC16, O_M }, { M_DIV, O_MC16, O_M }, { M_DIV, O_MC16, O_M },
+ { M_DIVS, O_MC16, O_M }, { M_DIVS, O_MC16, O_M }, { M_DIVS, O_MC16, O_M }, { M_DIVS, O_MC16, O_M },
+ { M_DIVS, O_MC16, O_M }, { M_DIVS, O_MC16, O_M }, { M_DIVS, O_MC16, O_M }, { M_DIVS, O_MC16, O_M },
+
+ /* 60 - 7F */
+ { M_INC, O_I3, O_M }, { M_INC, O_I3, O_M }, { M_INC, O_I3, O_M }, { M_INC, O_I3, O_M },
+ { M_INC, O_I3, O_M }, { M_INC, O_I3, O_M }, { M_INC, O_I3, O_M }, { M_INC, O_I3, O_M },
+ { M_DEC, O_I3, O_M }, { M_DEC, O_I3, O_M }, { M_DEC, O_I3, O_M }, { M_DEC, O_I3, O_M },
+ { M_DEC, O_I3, O_M }, { M_DEC, O_I3, O_M }, { M_DEC, O_I3, O_M }, { M_DEC, O_I3, O_M },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_RLC, O_M, O_NONE }, { M_RRC, O_M, O_NONE }, { M_RL, O_M, O_NONE }, { M_RR, O_M, O_NONE },
+ { M_SLA, O_M, O_NONE }, { M_SRA, O_M, O_NONE }, { M_SLL, O_M, O_NONE }, { M_SRL, O_M, O_NONE },
+
+ /* 80 - 9F */
+ { M_ADD, O_C8, O_M }, { M_ADD, O_C8, O_M }, { M_ADD, O_C8, O_M }, { M_ADD, O_C8, O_M },
+ { M_ADD, O_C8, O_M }, { M_ADD, O_C8, O_M }, { M_ADD, O_C8, O_M }, { M_ADD, O_C8, O_M },
+ { M_ADD, O_M, O_C8 }, { M_ADD, O_M, O_C8 }, { M_ADD, O_M, O_C8 }, { M_ADD, O_M, O_C8 },
+ { M_ADD, O_M, O_C8 }, { M_ADD, O_M, O_C8 }, { M_ADD, O_M, O_C8 }, { M_ADD, O_M, O_C8 },
+ { M_ADC, O_C8, O_M }, { M_ADC, O_C8, O_M }, { M_ADC, O_C8, O_M }, { M_ADC, O_C8, O_M },
+ { M_ADC, O_C8, O_M }, { M_ADC, O_C8, O_M }, { M_ADC, O_C8, O_M }, { M_ADC, O_C8, O_M },
+ { M_ADC, O_M, O_C8 }, { M_ADC, O_M, O_C8 }, { M_ADC, O_M, O_C8 }, { M_ADC, O_M, O_C8 },
+ { M_ADC, O_M, O_C8 }, { M_ADC, O_M, O_C8 }, { M_ADC, O_M, O_C8 }, { M_ADC, O_M, O_C8 },
+
+ /* A0 - BF */
+ { M_SUB, O_C8, O_M }, { M_SUB, O_C8, O_M }, { M_SUB, O_C8, O_M }, { M_SUB, O_C8, O_M },
+ { M_SUB, O_C8, O_M }, { M_SUB, O_C8, O_M }, { M_SUB, O_C8, O_M }, { M_SUB, O_C8, O_M },
+ { M_SUB, O_M, O_C8 }, { M_SUB, O_M, O_C8 }, { M_SUB, O_M, O_C8 }, { M_SUB, O_M, O_C8 },
+ { M_SUB, O_M, O_C8 }, { M_SUB, O_M, O_C8 }, { M_SUB, O_M, O_C8 }, { M_SUB, O_M, O_C8 },
+ { M_SBC, O_C8, O_M }, { M_SBC, O_C8, O_M }, { M_SBC, O_C8, O_M }, { M_SBC, O_C8, O_M },
+ { M_SBC, O_C8, O_M }, { M_SBC, O_C8, O_M }, { M_SBC, O_C8, O_M }, { M_SBC, O_C8, O_M },
+ { M_SBC, O_M, O_C8 }, { M_SBC, O_M, O_C8 }, { M_SBC, O_M, O_C8 }, { M_SBC, O_M, O_C8 },
+ { M_SBC, O_M, O_C8 }, { M_SBC, O_M, O_C8 }, { M_SBC, O_M, O_C8 }, { M_SBC, O_M, O_C8 },
+
+ /* C0 - DF */
+ { M_AND, O_C8, O_M }, { M_AND, O_C8, O_M }, { M_AND, O_C8, O_M }, { M_AND, O_C8, O_M },
+ { M_AND, O_C8, O_M }, { M_AND, O_C8, O_M }, { M_AND, O_C8, O_M }, { M_AND, O_C8, O_M },
+ { M_AND, O_M, O_C8 }, { M_AND, O_M, O_C8 }, { M_AND, O_M, O_C8 }, { M_AND, O_M, O_C8 },
+ { M_AND, O_M, O_C8 }, { M_AND, O_M, O_C8 }, { M_AND, O_M, O_C8 }, { M_AND, O_M, O_C8 },
+ { M_XOR, O_C8, O_M }, { M_XOR, O_C8, O_M }, { M_XOR, O_C8, O_M }, { M_XOR, O_C8, O_M },
+ { M_XOR, O_C8, O_M }, { M_XOR, O_C8, O_M }, { M_XOR, O_C8, O_M }, { M_XOR, O_C8, O_M },
+ { M_XOR, O_M, O_C8 }, { M_XOR, O_M, O_C8 }, { M_XOR, O_M, O_C8 }, { M_XOR, O_M, O_C8 },
+ { M_XOR, O_M, O_C8 }, { M_XOR, O_M, O_C8 }, { M_XOR, O_M, O_C8 }, { M_XOR, O_M, O_C8 },
+
+ /* E0 - FF */
+ { M_OR, O_C8, O_M }, { M_OR, O_C8, O_M }, { M_OR, O_C8, O_M }, { M_OR, O_C8, O_M },
+ { M_OR, O_C8, O_M }, { M_OR, O_C8, O_M }, { M_OR, O_C8, O_M }, { M_OR, O_C8, O_M },
+ { M_OR, O_M, O_C8 }, { M_OR, O_M, O_C8 }, { M_OR, O_M, O_C8 }, { M_OR, O_M, O_C8 },
+ { M_OR, O_M, O_C8 }, { M_OR, O_M, O_C8 }, { M_OR, O_M, O_C8 }, { M_OR, O_M, O_C8 },
+ { M_CP, O_C8, O_M }, { M_CP, O_C8, O_M }, { M_CP, O_C8, O_M }, { M_CP, O_C8, O_M },
+ { M_CP, O_C8, O_M }, { M_CP, O_C8, O_M }, { M_CP, O_C8, O_M }, { M_CP, O_C8, O_M },
+ { M_CP, O_M, O_C8 }, { M_CP, O_M, O_C8 }, { M_CP, O_M, O_C8 }, { M_CP, O_M, O_C8 },
+ { M_CP, O_M, O_C8 }, { M_CP, O_M, O_C8 }, { M_CP, O_M, O_C8 }, { M_CP, O_M, O_C8 },
+};
+
+
+static const tlcs900inst mnemonic_90[256] =
+{
+ /* 00 - 1F */
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_PUSHW, O_M, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_LDIW, O_NONE, O_NONE }, { M_LDIRW, O_NONE, O_NONE }, { M_LDDW, O_NONE, O_NONE }, { M_LDDRW, O_NONE, O_NONE },
+ { M_CPIW, O_NONE, O_NONE }, { M_CPIRW, O_NONE, O_NONE }, { M_CPDW, O_NONE, O_NONE }, { M_CPDRW, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_LDW, O_M16, O_M }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 20 - 3F */
+ { M_LD, O_C16, O_M }, { M_LD, O_C16, O_M }, { M_LD, O_C16, O_M }, { M_LD, O_C16, O_M },
+ { M_LD, O_C16, O_M }, { M_LD, O_C16, O_M }, { M_LD, O_C16, O_M }, { M_LD, O_C16, O_M },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_EX, O_M, O_C16 }, { M_EX, O_M, O_C16 }, { M_EX, O_M, O_C16 }, { M_EX, O_M, O_C16 },
+ { M_EX, O_M, O_C16 }, { M_EX, O_M, O_C16 }, { M_EX, O_M, O_C16 }, { M_EX, O_M, O_C16 },
+ { M_ADD, O_M, O_I16 }, { M_ADC, O_M, O_I16 }, { M_SUB, O_M, O_I16 }, { M_SBC, O_M, O_I16 },
+ { M_AND, O_M, O_I16 }, { M_XOR, O_M, O_I16 }, { M_OR, O_M, O_I16 }, { M_CP, O_M, O_I16 },
+
+ /* 40 - 5F */
+ { M_MUL, O_C32, O_M }, { M_MUL, O_C32, O_M }, { M_MUL, O_C32, O_M }, { M_MUL, O_C32, O_M },
+ { M_MUL, O_C32, O_M }, { M_MUL, O_C32, O_M }, { M_MUL, O_C32, O_M }, { M_MUL, O_C32, O_M },
+ { M_MULS, O_C32, O_M }, { M_MULS, O_C32, O_M }, { M_MULS, O_C32, O_M }, { M_MULS, O_C32, O_M },
+ { M_MULS, O_C32, O_M }, { M_MULS, O_C32, O_M }, { M_MULS, O_C32, O_M }, { M_MULS, O_C32, O_M },
+ { M_DIV, O_C32, O_M }, { M_DIV, O_C32, O_M }, { M_DIV, O_C32, O_M }, { M_DIV, O_C32, O_M },
+ { M_DIV, O_C32, O_M }, { M_DIV, O_C32, O_M }, { M_DIV, O_C32, O_M }, { M_DIV, O_C32, O_M },
+ { M_DIVS, O_C32, O_M }, { M_DIVS, O_C32, O_M }, { M_DIVS, O_C32, O_M }, { M_DIVS, O_C32, O_M },
+ { M_DIVS, O_C32, O_M }, { M_DIVS, O_C32, O_M }, { M_DIVS, O_C32, O_M }, { M_DIVS, O_C32, O_M },
+
+ /* 60 - 7F */
+ { M_INCW, O_I3, O_M }, { M_INCW, O_I3, O_M }, { M_INCW, O_I3, O_M }, { M_INCW, O_I3, O_M },
+ { M_INCW, O_I3, O_M }, { M_INCW, O_I3, O_M }, { M_INCW, O_I3, O_M }, { M_INCW, O_I3, O_M },
+ { M_DECW, O_I3, O_M }, { M_DECW, O_I3, O_M }, { M_DECW, O_I3, O_M }, { M_DECW, O_I3, O_M },
+ { M_DECW, O_I3, O_M }, { M_DECW, O_I3, O_M }, { M_DECW, O_I3, O_M }, { M_DECW, O_I3, O_M },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_RLCW, O_M, O_NONE }, { M_RRCW, O_M, O_NONE }, { M_RLW, O_M, O_NONE }, { M_RRW, O_M, O_NONE },
+ { M_SLAW, O_M, O_NONE }, { M_SRAW, O_M, O_NONE }, { M_SLLW, O_M, O_NONE }, { M_SRLW, O_M, O_NONE },
+
+ /* 80 - 9F */
+ { M_ADD, O_C16, O_M }, { M_ADD, O_C16, O_M }, { M_ADD, O_C16, O_M }, { M_ADD, O_C16, O_M },
+ { M_ADD, O_C16, O_M }, { M_ADD, O_C16, O_M }, { M_ADD, O_C16, O_M }, { M_ADD, O_C16, O_M },
+ { M_ADD, O_M, O_C16 }, { M_ADD, O_M, O_C16 }, { M_ADD, O_M, O_C16 }, { M_ADD, O_M, O_C16 },
+ { M_ADD, O_M, O_C16 }, { M_ADD, O_M, O_C16 }, { M_ADD, O_M, O_C16 }, { M_ADD, O_M, O_C16 },
+ { M_ADC, O_C16, O_M }, { M_ADC, O_C16, O_M }, { M_ADC, O_C16, O_M }, { M_ADC, O_C16, O_M },
+ { M_ADC, O_C16, O_M }, { M_ADC, O_C16, O_M }, { M_ADC, O_C16, O_M }, { M_ADC, O_C16, O_M },
+ { M_ADC, O_M, O_C16 }, { M_ADC, O_M, O_C16 }, { M_ADC, O_M, O_C16 }, { M_ADC, O_M, O_C16 },
+ { M_ADC, O_M, O_C16 }, { M_ADC, O_M, O_C16 }, { M_ADC, O_M, O_C16 }, { M_ADC, O_M, O_C16 },
+
+ /* A0 - BF */
+ { M_SUB, O_C16, O_M }, { M_SUB, O_C16, O_M }, { M_SUB, O_C16, O_M }, { M_SUB, O_C16, O_M },
+ { M_SUB, O_C16, O_M }, { M_SUB, O_C16, O_M }, { M_SUB, O_C16, O_M }, { M_SUB, O_C16, O_M },
+ { M_SUB, O_M, O_C16 }, { M_SUB, O_M, O_C16 }, { M_SUB, O_M, O_C16 }, { M_SUB, O_M, O_C16 },
+ { M_SUB, O_M, O_C16 }, { M_SUB, O_M, O_C16 }, { M_SUB, O_M, O_C16 }, { M_SUB, O_M, O_C16 },
+ { M_SBC, O_C16, O_M }, { M_SBC, O_C16, O_M }, { M_SBC, O_C16, O_M }, { M_SBC, O_C16, O_M },
+ { M_SBC, O_C16, O_M }, { M_SBC, O_C16, O_M }, { M_SBC, O_C16, O_M }, { M_SBC, O_C16, O_M },
+ { M_SBC, O_M, O_C16 }, { M_SBC, O_M, O_C16 }, { M_SBC, O_M, O_C16 }, { M_SBC, O_M, O_C16 },
+ { M_SBC, O_M, O_C16 }, { M_SBC, O_M, O_C16 }, { M_SBC, O_M, O_C16 }, { M_SBC, O_M, O_C16 },
+
+ /* C0 - DF */
+ { M_AND, O_C16, O_M }, { M_AND, O_C16, O_M }, { M_AND, O_C16, O_M }, { M_AND, O_C16, O_M },
+ { M_AND, O_C16, O_M }, { M_AND, O_C16, O_M }, { M_AND, O_C16, O_M }, { M_AND, O_C16, O_M },
+ { M_AND, O_M, O_C16 }, { M_AND, O_M, O_C16 }, { M_AND, O_M, O_C16 }, { M_AND, O_M, O_C16 },
+ { M_AND, O_M, O_C16 }, { M_AND, O_M, O_C16 }, { M_AND, O_M, O_C16 }, { M_AND, O_M, O_C16 },
+ { M_XOR, O_C16, O_M }, { M_XOR, O_C16, O_M }, { M_XOR, O_C16, O_M }, { M_XOR, O_C16, O_M },
+ { M_XOR, O_C16, O_M }, { M_XOR, O_C16, O_M }, { M_XOR, O_C16, O_M }, { M_XOR, O_C16, O_M },
+ { M_XOR, O_M, O_C16 }, { M_XOR, O_M, O_C16 }, { M_XOR, O_M, O_C16 }, { M_XOR, O_M, O_C16 },
+ { M_XOR, O_M, O_C16 }, { M_XOR, O_M, O_C16 }, { M_XOR, O_M, O_C16 }, { M_XOR, O_M, O_C16 },
+
+ /* E0 - FF */
+ { M_OR, O_C16, O_M }, { M_OR, O_C16, O_M }, { M_OR, O_C16, O_M }, { M_OR, O_C16, O_M },
+ { M_OR, O_C16, O_M }, { M_OR, O_C16, O_M }, { M_OR, O_C16, O_M }, { M_OR, O_C16, O_M },
+ { M_OR, O_M, O_C16 }, { M_OR, O_M, O_C16 }, { M_OR, O_M, O_C16 }, { M_OR, O_M, O_C16 },
+ { M_OR, O_M, O_C16 }, { M_OR, O_M, O_C16 }, { M_OR, O_M, O_C16 }, { M_OR, O_M, O_C16 },
+ { M_CP, O_C16, O_M }, { M_CP, O_C16, O_M }, { M_CP, O_C16, O_M }, { M_CP, O_C16, O_M },
+ { M_CP, O_C16, O_M }, { M_CP, O_C16, O_M }, { M_CP, O_C16, O_M }, { M_CP, O_C16, O_M },
+ { M_CP, O_M, O_C16 }, { M_CP, O_M, O_C16 }, { M_CP, O_M, O_C16 }, { M_CP, O_M, O_C16 },
+ { M_CP, O_M, O_C16 }, { M_CP, O_M, O_C16 }, { M_CP, O_M, O_C16 }, { M_CP, O_M, O_C16 },
+};
+
+
+static const tlcs900inst mnemonic_98[256] =
+{
+ /* 00 - 1F */
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_PUSHW, O_M, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_LDW, O_M16, O_M }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 20 - 3F */
+ { M_LD, O_C16, O_M }, { M_LD, O_C16, O_M }, { M_LD, O_C16, O_M }, { M_LD, O_C16, O_M },
+ { M_LD, O_C16, O_M }, { M_LD, O_C16, O_M }, { M_LD, O_C16, O_M }, { M_LD, O_C16, O_M },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_EX, O_M, O_C16 }, { M_EX, O_M, O_C16 }, { M_EX, O_M, O_C16 }, { M_EX, O_M, O_C16 },
+ { M_EX, O_M, O_C16 }, { M_EX, O_M, O_C16 }, { M_EX, O_M, O_C16 }, { M_EX, O_M, O_C16 },
+ { M_ADD, O_M, O_I16 }, { M_ADC, O_M, O_I16 }, { M_SUB, O_M, O_I16 }, { M_SBC, O_M, O_I16 },
+ { M_AND, O_M, O_I16 }, { M_XOR, O_M, O_I16 }, { M_OR, O_M, O_I16 }, { M_CP, O_M, O_I16 },
+
+ /* 40 - 5F */
+ { M_MUL, O_C32, O_M }, { M_MUL, O_C32, O_M }, { M_MUL, O_C32, O_M }, { M_MUL, O_C32, O_M },
+ { M_MUL, O_C32, O_M }, { M_MUL, O_C32, O_M }, { M_MUL, O_C32, O_M }, { M_MUL, O_C32, O_M },
+ { M_MULS, O_C32, O_M }, { M_MULS, O_C32, O_M }, { M_MULS, O_C32, O_M }, { M_MULS, O_C32, O_M },
+ { M_MULS, O_C32, O_M }, { M_MULS, O_C32, O_M }, { M_MULS, O_C32, O_M }, { M_MULS, O_C32, O_M },
+ { M_DIV, O_C32, O_M }, { M_DIV, O_C32, O_M }, { M_DIV, O_C32, O_M }, { M_DIV, O_C32, O_M },
+ { M_DIV, O_C32, O_M }, { M_DIV, O_C32, O_M }, { M_DIV, O_C32, O_M }, { M_DIV, O_C32, O_M },
+ { M_DIVS, O_C32, O_M }, { M_DIVS, O_C32, O_M }, { M_DIVS, O_C32, O_M }, { M_DIVS, O_C32, O_M },
+ { M_DIVS, O_C32, O_M }, { M_DIVS, O_C32, O_M }, { M_DIVS, O_C32, O_M }, { M_DIVS, O_C32, O_M },
+
+ /* 60 - 7F */
+ { M_INCW, O_I3, O_M }, { M_INCW, O_I3, O_M }, { M_INCW, O_I3, O_M }, { M_INCW, O_I3, O_M },
+ { M_INCW, O_I3, O_M }, { M_INCW, O_I3, O_M }, { M_INCW, O_I3, O_M }, { M_INCW, O_I3, O_M },
+ { M_DECW, O_I3, O_M }, { M_DECW, O_I3, O_M }, { M_DECW, O_I3, O_M }, { M_DECW, O_I3, O_M },
+ { M_DECW, O_I3, O_M }, { M_DECW, O_I3, O_M }, { M_DECW, O_I3, O_M }, { M_DECW, O_I3, O_M },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_RLCW, O_M, O_NONE }, { M_RRCW, O_M, O_NONE }, { M_RLW, O_M, O_NONE }, { M_RRW, O_M, O_NONE },
+ { M_SLAW, O_M, O_NONE }, { M_SRAW, O_M, O_NONE }, { M_SLLW, O_M, O_NONE }, { M_SRLW, O_M, O_NONE },
+
+ /* 80 - 9F */
+ { M_ADD, O_C16, O_M }, { M_ADD, O_C16, O_M }, { M_ADD, O_C16, O_M }, { M_ADD, O_C16, O_M },
+ { M_ADD, O_C16, O_M }, { M_ADD, O_C16, O_M }, { M_ADD, O_C16, O_M }, { M_ADD, O_C16, O_M },
+ { M_ADD, O_M, O_C16 }, { M_ADD, O_M, O_C16 }, { M_ADD, O_M, O_C16 }, { M_ADD, O_M, O_C16 },
+ { M_ADD, O_M, O_C16 }, { M_ADD, O_M, O_C16 }, { M_ADD, O_M, O_C16 }, { M_ADD, O_M, O_C16 },
+ { M_ADC, O_C16, O_M }, { M_ADC, O_C16, O_M }, { M_ADC, O_C16, O_M }, { M_ADC, O_C16, O_M },
+ { M_ADC, O_C16, O_M }, { M_ADC, O_C16, O_M }, { M_ADC, O_C16, O_M }, { M_ADC, O_C16, O_M },
+ { M_ADC, O_M, O_C16 }, { M_ADC, O_M, O_C16 }, { M_ADC, O_M, O_C16 }, { M_ADC, O_M, O_C16 },
+ { M_ADC, O_M, O_C16 }, { M_ADC, O_M, O_C16 }, { M_ADC, O_M, O_C16 }, { M_ADC, O_M, O_C16 },
+
+ /* A0 - BF */
+ { M_SUB, O_C16, O_M }, { M_SUB, O_C16, O_M }, { M_SUB, O_C16, O_M }, { M_SUB, O_C16, O_M },
+ { M_SUB, O_C16, O_M }, { M_SUB, O_C16, O_M }, { M_SUB, O_C16, O_M }, { M_SUB, O_C16, O_M },
+ { M_SUB, O_M, O_C16 }, { M_SUB, O_M, O_C16 }, { M_SUB, O_M, O_C16 }, { M_SUB, O_M, O_C16 },
+ { M_SUB, O_M, O_C16 }, { M_SUB, O_M, O_C16 }, { M_SUB, O_M, O_C16 }, { M_SUB, O_M, O_C16 },
+ { M_SBC, O_C16, O_M }, { M_SBC, O_C16, O_M }, { M_SBC, O_C16, O_M }, { M_SBC, O_C16, O_M },
+ { M_SBC, O_C16, O_M }, { M_SBC, O_C16, O_M }, { M_SBC, O_C16, O_M }, { M_SBC, O_C16, O_M },
+ { M_SBC, O_M, O_C16 }, { M_SBC, O_M, O_C16 }, { M_SBC, O_M, O_C16 }, { M_SBC, O_M, O_C16 },
+ { M_SBC, O_M, O_C16 }, { M_SBC, O_M, O_C16 }, { M_SBC, O_M, O_C16 }, { M_SBC, O_M, O_C16 },
+
+ /* C0 - DF */
+ { M_AND, O_C16, O_M }, { M_AND, O_C16, O_M }, { M_AND, O_C16, O_M }, { M_AND, O_C16, O_M },
+ { M_AND, O_C16, O_M }, { M_AND, O_C16, O_M }, { M_AND, O_C16, O_M }, { M_AND, O_C16, O_M },
+ { M_AND, O_M, O_C16 }, { M_AND, O_M, O_C16 }, { M_AND, O_M, O_C16 }, { M_AND, O_M, O_C16 },
+ { M_AND, O_M, O_C16 }, { M_AND, O_M, O_C16 }, { M_AND, O_M, O_C16 }, { M_AND, O_M, O_C16 },
+ { M_XOR, O_C16, O_M }, { M_XOR, O_C16, O_M }, { M_XOR, O_C16, O_M }, { M_XOR, O_C16, O_M },
+ { M_XOR, O_C16, O_M }, { M_XOR, O_C16, O_M }, { M_XOR, O_C16, O_M }, { M_XOR, O_C16, O_M },
+ { M_XOR, O_M, O_C16 }, { M_XOR, O_M, O_C16 }, { M_XOR, O_M, O_C16 }, { M_XOR, O_M, O_C16 },
+ { M_XOR, O_M, O_C16 }, { M_XOR, O_M, O_C16 }, { M_XOR, O_M, O_C16 }, { M_XOR, O_M, O_C16 },
+
+ /* E0 - FF */
+ { M_OR, O_C16, O_M }, { M_OR, O_C16, O_M }, { M_OR, O_C16, O_M }, { M_OR, O_C16, O_M },
+ { M_OR, O_C16, O_M }, { M_OR, O_C16, O_M }, { M_OR, O_C16, O_M }, { M_OR, O_C16, O_M },
+ { M_OR, O_M, O_C16 }, { M_OR, O_M, O_C16 }, { M_OR, O_M, O_C16 }, { M_OR, O_M, O_C16 },
+ { M_OR, O_M, O_C16 }, { M_OR, O_M, O_C16 }, { M_OR, O_M, O_C16 }, { M_OR, O_M, O_C16 },
+ { M_CP, O_C16, O_M }, { M_CP, O_C16, O_M }, { M_CP, O_C16, O_M }, { M_CP, O_C16, O_M },
+ { M_CP, O_C16, O_M }, { M_CP, O_C16, O_M }, { M_CP, O_C16, O_M }, { M_CP, O_C16, O_M },
+ { M_CP, O_M, O_C16 }, { M_CP, O_M, O_C16 }, { M_CP, O_M, O_C16 }, { M_CP, O_M, O_C16 },
+ { M_CP, O_M, O_C16 }, { M_CP, O_M, O_C16 }, { M_CP, O_M, O_C16 }, { M_CP, O_M, O_C16 },
+};
+
+
+static const tlcs900inst mnemonic_a0[256] =
+{
+ /* 00 - 1F */
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 20 - 3F */
+ { M_LD, O_C32, O_M }, { M_LD, O_C32, O_M }, { M_LD, O_C32, O_M }, { M_LD, O_C32, O_M },
+ { M_LD, O_C32, O_M }, { M_LD, O_C32, O_M }, { M_LD, O_C32, O_M }, { M_LD, O_C32, O_M },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 40 - 5F */
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 60 - 7F */
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 80 - 9F */
+ { M_ADD, O_C32, O_M }, { M_ADD, O_C32, O_M }, { M_ADD, O_C32, O_M }, { M_ADD, O_C32, O_M },
+ { M_ADD, O_C32, O_M }, { M_ADD, O_C32, O_M }, { M_ADD, O_C32, O_M }, { M_ADD, O_C32, O_M },
+ { M_ADD, O_M, O_C32 }, { M_ADD, O_M, O_C32 }, { M_ADD, O_M, O_C32 }, { M_ADD, O_M, O_C32 },
+ { M_ADD, O_M, O_C32 }, { M_ADD, O_M, O_C32 }, { M_ADD, O_M, O_C32 }, { M_ADD, O_M, O_C32 },
+ { M_ADC, O_C32, O_M }, { M_ADC, O_C32, O_M }, { M_ADC, O_C32, O_M }, { M_ADC, O_C32, O_M },
+ { M_ADC, O_C32, O_M }, { M_ADC, O_C32, O_M }, { M_ADC, O_C32, O_M }, { M_ADC, O_C32, O_M },
+ { M_ADC, O_M, O_C32 }, { M_ADC, O_M, O_C32 }, { M_ADC, O_M, O_C32 }, { M_ADC, O_M, O_C32 },
+ { M_ADC, O_M, O_C32 }, { M_ADC, O_M, O_C32 }, { M_ADC, O_M, O_C32 }, { M_ADC, O_M, O_C32 },
+
+ /* A0 - BF */
+ { M_SUB, O_C32, O_M }, { M_SUB, O_C32, O_M }, { M_SUB, O_C32, O_M }, { M_SUB, O_C32, O_M },
+ { M_SUB, O_C32, O_M }, { M_SUB, O_C32, O_M }, { M_SUB, O_C32, O_M }, { M_SUB, O_C32, O_M },
+ { M_SUB, O_M, O_C32 }, { M_SUB, O_M, O_C32 }, { M_SUB, O_M, O_C32 }, { M_SUB, O_M, O_C32 },
+ { M_SUB, O_M, O_C32 }, { M_SUB, O_M, O_C32 }, { M_SUB, O_M, O_C32 }, { M_SUB, O_M, O_C32 },
+ { M_SBC, O_C32, O_M }, { M_SBC, O_C32, O_M }, { M_SBC, O_C32, O_M }, { M_SBC, O_C32, O_M },
+ { M_SBC, O_C32, O_M }, { M_SBC, O_C32, O_M }, { M_SBC, O_C32, O_M }, { M_SBC, O_C32, O_M },
+ { M_SBC, O_M, O_C32 }, { M_SBC, O_M, O_C32 }, { M_SBC, O_M, O_C32 }, { M_SBC, O_M, O_C32 },
+ { M_SBC, O_M, O_C32 }, { M_SBC, O_M, O_C32 }, { M_SBC, O_M, O_C32 }, { M_SBC, O_M, O_C32 },
+
+ /* C0 - DF */
+ { M_AND, O_C32, O_M }, { M_AND, O_C32, O_M }, { M_AND, O_C32, O_M }, { M_AND, O_C32, O_M },
+ { M_AND, O_C32, O_M }, { M_AND, O_C32, O_M }, { M_AND, O_C32, O_M }, { M_AND, O_C32, O_M },
+ { M_AND, O_M, O_C32 }, { M_AND, O_M, O_C32 }, { M_AND, O_M, O_C32 }, { M_AND, O_M, O_C32 },
+ { M_AND, O_M, O_C32 }, { M_AND, O_M, O_C32 }, { M_AND, O_M, O_C32 }, { M_AND, O_M, O_C32 },
+ { M_XOR, O_C32, O_M }, { M_XOR, O_C32, O_M }, { M_XOR, O_C32, O_M }, { M_XOR, O_C32, O_M },
+ { M_XOR, O_C32, O_M }, { M_XOR, O_C32, O_M }, { M_XOR, O_C32, O_M }, { M_XOR, O_C32, O_M },
+ { M_XOR, O_M, O_C32 }, { M_XOR, O_M, O_C32 }, { M_XOR, O_M, O_C32 }, { M_XOR, O_M, O_C32 },
+ { M_XOR, O_M, O_C32 }, { M_XOR, O_M, O_C32 }, { M_XOR, O_M, O_C32 }, { M_XOR, O_M, O_C32 },
+
+ /* E0 - FF */
+ { M_OR, O_C32, O_M }, { M_OR, O_C32, O_M }, { M_OR, O_C32, O_M }, { M_OR, O_C32, O_M },
+ { M_OR, O_C32, O_M }, { M_OR, O_C32, O_M }, { M_OR, O_C32, O_M }, { M_OR, O_C32, O_M },
+ { M_OR, O_M, O_C32 }, { M_OR, O_M, O_C32 }, { M_OR, O_M, O_C32 }, { M_OR, O_M, O_C32 },
+ { M_OR, O_M, O_C32 }, { M_OR, O_M, O_C32 }, { M_OR, O_M, O_C32 }, { M_OR, O_M, O_C32 },
+ { M_CP, O_C32, O_M }, { M_CP, O_C32, O_M }, { M_CP, O_C32, O_M }, { M_CP, O_C32, O_M },
+ { M_CP, O_C32, O_M }, { M_CP, O_C32, O_M }, { M_CP, O_C32, O_M }, { M_CP, O_C32, O_M },
+ { M_CP, O_M, O_C32 }, { M_CP, O_M, O_C32 }, { M_CP, O_M, O_C32 }, { M_CP, O_M, O_C32 },
+ { M_CP, O_M, O_C32 }, { M_CP, O_M, O_C32 }, { M_CP, O_M, O_C32 }, { M_CP, O_M, O_C32 },
+};
+
+
+static const tlcs900inst mnemonic_b0[256] =
+{
+ /* 00 - 1F */
+ { M_LD, O_M, O_I8 }, { M_DB, O_NONE, O_NONE }, { M_LD, O_M, O_I16 }, { M_DB, O_NONE, O_NONE },
+ { M_POP, O_M, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_POPW, O_M, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_LD, O_M, O_M16 }, { M_DB, O_NONE, O_NONE }, { M_LDW, O_M, O_M16 }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 20 - 3F */
+ { M_LDA, O_C16, O_M }, { M_LDA, O_C16, O_M }, { M_LDA, O_C16, O_M }, { M_LDA, O_C16, O_M },
+ { M_LDA, O_C16, O_M }, { M_LDA, O_C16, O_M }, { M_LDA, O_C16, O_M }, { M_LDA, O_C16, O_M },
+ { M_ANDCF, O_A, O_M }, { M_ORCF, O_A, O_M }, { M_XORCF, O_A, O_M }, { M_LDCF, O_A, O_M },
+ { M_STCF, O_A, O_M }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_LDA, O_C32, O_M }, { M_LDA, O_C32, O_M }, { M_LDA, O_C32, O_M }, { M_LDA, O_C32, O_M },
+ { M_LDA, O_C32, O_M }, { M_LDA, O_C32, O_M }, { M_LDA, O_C32, O_M }, { M_LDA, O_C32, O_M },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 40 - 5F */
+ { M_LD, O_M, O_C8 }, { M_LD, O_M, O_C8 }, { M_LD, O_M, O_C8 }, { M_LD, O_M, O_C8 },
+ { M_LD, O_M, O_C8 }, { M_LD, O_M, O_C8 }, { M_LD, O_M, O_C8 }, { M_LD, O_M, O_C8 },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_LD, O_M, O_C16 }, { M_LD, O_M, O_C16 }, { M_LD, O_M, O_C16 }, { M_LD, O_M, O_C16 },
+ { M_LD, O_M, O_C16 }, { M_LD, O_M, O_C16 }, { M_LD, O_M, O_C16 }, { M_LD, O_M, O_C16 },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 60 - 7F */
+ { M_LD, O_M, O_C32 }, { M_LD, O_M, O_C32 }, { M_LD, O_M, O_C32 }, { M_LD, O_M, O_C32 },
+ { M_LD, O_M, O_C32 }, { M_LD, O_M, O_C32 }, { M_LD, O_M, O_C32 }, { M_LD, O_M, O_C32 },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 80 - 9F */
+ { M_ANDCF, O_I3, O_M }, { M_ANDCF, O_I3, O_M }, { M_ANDCF, O_I3, O_M }, { M_ANDCF, O_I3, O_M },
+ { M_ANDCF, O_I3, O_M }, { M_ANDCF, O_I3, O_M }, { M_ANDCF, O_I3, O_M }, { M_ANDCF, O_I3, O_M },
+ { M_ORCF, O_I3, O_M }, { M_ORCF, O_I3, O_M }, { M_ORCF, O_I3, O_M }, { M_ORCF, O_I3, O_M },
+ { M_ORCF, O_I3, O_M }, { M_ORCF, O_I3, O_M }, { M_ORCF, O_I3, O_M }, { M_ORCF, O_I3, O_M },
+ { M_XORCF, O_I3, O_M }, { M_XORCF, O_I3, O_M }, { M_XORCF, O_I3, O_M }, { M_XORCF, O_I3, O_M },
+ { M_XORCF, O_I3, O_M }, { M_XORCF, O_I3, O_M }, { M_XORCF, O_I3, O_M }, { M_XORCF, O_I3, O_M },
+ { M_LDCF, O_I3, O_M }, { M_LDCF, O_I3, O_M }, { M_LDCF, O_I3, O_M }, { M_LDCF, O_I3, O_M },
+ { M_LDCF, O_I3, O_M }, { M_LDCF, O_I3, O_M }, { M_LDCF, O_I3, O_M }, { M_LDCF, O_I3, O_M },
+
+ /* A0 - BF */
+ { M_STCF, O_I3, O_M }, { M_STCF, O_I3, O_M }, { M_STCF, O_I3, O_M }, { M_STCF, O_I3, O_M },
+ { M_STCF, O_I3, O_M }, { M_STCF, O_I3, O_M }, { M_STCF, O_I3, O_M }, { M_STCF, O_I3, O_M },
+ { M_TSET, O_I3, O_M }, { M_TSET, O_I3, O_M }, { M_TSET, O_I3, O_M }, { M_TSET, O_I3, O_M },
+ { M_TSET, O_I3, O_M }, { M_TSET, O_I3, O_M }, { M_TSET, O_I3, O_M }, { M_TSET, O_I3, O_M },
+ { M_RES, O_I3, O_M }, { M_RES, O_I3, O_M }, { M_RES, O_I3, O_M }, { M_RES, O_I3, O_M },
+ { M_RES, O_I3, O_M }, { M_RES, O_I3, O_M }, { M_RES, O_I3, O_M }, { M_RES, O_I3, O_M },
+ { M_SET, O_I3, O_M }, { M_SET, O_I3, O_M }, { M_SET, O_I3, O_M }, { M_SET, O_I3, O_M },
+ { M_SET, O_I3, O_M }, { M_SET, O_I3, O_M }, { M_SET, O_I3, O_M }, { M_SET, O_I3, O_M },
+
+ /* C0 - DF */
+ { M_CHG, O_I3, O_M }, { M_CHG, O_I3, O_M }, { M_CHG, O_I3, O_M }, { M_CHG, O_I3, O_M },
+ { M_CHG, O_I3, O_M }, { M_CHG, O_I3, O_M }, { M_CHG, O_I3, O_M }, { M_CHG, O_I3, O_M },
+ { M_BIT, O_I3, O_M }, { M_BIT, O_I3, O_M }, { M_BIT, O_I3, O_M }, { M_BIT, O_I3, O_M },
+ { M_BIT, O_I3, O_M }, { M_BIT, O_I3, O_M }, { M_BIT, O_I3, O_M }, { M_BIT, O_I3, O_M },
+ { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M },
+ { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M },
+ { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M },
+ { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M },
+
+ /* E0 - FF */
+ { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M },
+ { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M },
+ { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M },
+ { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M },
+ { M_RET, O_CC, O_NONE }, { M_RET, O_CC, O_NONE }, { M_RET, O_CC, O_NONE }, { M_RET, O_CC, O_NONE },
+ { M_RET, O_CC, O_NONE }, { M_RET, O_CC, O_NONE }, { M_RET, O_CC, O_NONE }, { M_RET, O_CC, O_NONE },
+ { M_RET, O_CC, O_NONE }, { M_RET, O_CC, O_NONE }, { M_RET, O_CC, O_NONE }, { M_RET, O_CC, O_NONE },
+ { M_RET, O_CC, O_NONE }, { M_RET, O_CC, O_NONE }, { M_RET, O_CC, O_NONE }, { M_RET, O_CC, O_NONE }
+};
+
+
+static const tlcs900inst mnemonic_b8[256] =
+{
+ /* 00 - 1F */
+ { M_LD, O_M, O_I8 }, { M_DB, O_NONE, O_NONE }, { M_LD, O_M, O_I16 }, { M_DB, O_NONE, O_NONE },
+ { M_POP, O_M, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_POPW, O_M, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_LD, O_M, O_M16 }, { M_DB, O_NONE, O_NONE }, { M_LDW, O_M, O_M16 }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 20 - 3F */
+ { M_LDA, O_C16, O_M }, { M_LDA, O_C16, O_M }, { M_LDA, O_C16, O_M }, { M_LDA, O_C16, O_M },
+ { M_LDA, O_C16, O_M }, { M_LDA, O_C16, O_M }, { M_LDA, O_C16, O_M }, { M_LDA, O_C16, O_M },
+ { M_ANDCF, O_A, O_M }, { M_ORCF, O_A, O_M }, { M_XORCF, O_A, O_M }, { M_LDCF, O_A, O_M },
+ { M_STCF, O_A, O_M }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_LDA, O_C32, O_M }, { M_LDA, O_C32, O_M }, { M_LDA, O_C32, O_M }, { M_LDA, O_C32, O_M },
+ { M_LDA, O_C32, O_M }, { M_LDA, O_C32, O_M }, { M_LDA, O_C32, O_M }, { M_LDA, O_C32, O_M },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 40 - 5F */
+ { M_LD, O_M, O_C8 }, { M_LD, O_M, O_C8 }, { M_LD, O_M, O_C8 }, { M_LD, O_M, O_C8 },
+ { M_LD, O_M, O_C8 }, { M_LD, O_M, O_C8 }, { M_LD, O_M, O_C8 }, { M_LD, O_M, O_C8 },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_LD, O_M, O_C16 }, { M_LD, O_M, O_C16 }, { M_LD, O_M, O_C16 }, { M_LD, O_M, O_C16 },
+ { M_LD, O_M, O_C16 }, { M_LD, O_M, O_C16 }, { M_LD, O_M, O_C16 }, { M_LD, O_M, O_C16 },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 60 - 7F */
+ { M_LD, O_M, O_C32 }, { M_LD, O_M, O_C32 }, { M_LD, O_M, O_C32 }, { M_LD, O_M, O_C32 },
+ { M_LD, O_M, O_C32 }, { M_LD, O_M, O_C32 }, { M_LD, O_M, O_C32 }, { M_LD, O_M, O_C32 },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 80 - 9F */
+ { M_ANDCF, O_I3, O_M }, { M_ANDCF, O_I3, O_M }, { M_ANDCF, O_I3, O_M }, { M_ANDCF, O_I3, O_M },
+ { M_ANDCF, O_I3, O_M }, { M_ANDCF, O_I3, O_M }, { M_ANDCF, O_I3, O_M }, { M_ANDCF, O_I3, O_M },
+ { M_ORCF, O_I3, O_M }, { M_ORCF, O_I3, O_M }, { M_ORCF, O_I3, O_M }, { M_ORCF, O_I3, O_M },
+ { M_ORCF, O_I3, O_M }, { M_ORCF, O_I3, O_M }, { M_ORCF, O_I3, O_M }, { M_ORCF, O_I3, O_M },
+ { M_XORCF, O_I3, O_M }, { M_XORCF, O_I3, O_M }, { M_XORCF, O_I3, O_M }, { M_XORCF, O_I3, O_M },
+ { M_XORCF, O_I3, O_M }, { M_XORCF, O_I3, O_M }, { M_XORCF, O_I3, O_M }, { M_XORCF, O_I3, O_M },
+ { M_LDCF, O_I3, O_M }, { M_LDCF, O_I3, O_M }, { M_LDCF, O_I3, O_M }, { M_LDCF, O_I3, O_M },
+ { M_LDCF, O_I3, O_M }, { M_LDCF, O_I3, O_M }, { M_LDCF, O_I3, O_M }, { M_LDCF, O_I3, O_M },
+
+ /* A0 - BF */
+ { M_STCF, O_I3, O_M }, { M_STCF, O_I3, O_M }, { M_STCF, O_I3, O_M }, { M_STCF, O_I3, O_M },
+ { M_STCF, O_I3, O_M }, { M_STCF, O_I3, O_M }, { M_STCF, O_I3, O_M }, { M_STCF, O_I3, O_M },
+ { M_TSET, O_I3, O_M }, { M_TSET, O_I3, O_M }, { M_TSET, O_I3, O_M }, { M_TSET, O_I3, O_M },
+ { M_TSET, O_I3, O_M }, { M_TSET, O_I3, O_M }, { M_TSET, O_I3, O_M }, { M_TSET, O_I3, O_M },
+ { M_RES, O_I3, O_M }, { M_RES, O_I3, O_M }, { M_RES, O_I3, O_M }, { M_RES, O_I3, O_M },
+ { M_RES, O_I3, O_M }, { M_RES, O_I3, O_M }, { M_RES, O_I3, O_M }, { M_RES, O_I3, O_M },
+ { M_SET, O_I3, O_M }, { M_SET, O_I3, O_M }, { M_SET, O_I3, O_M }, { M_SET, O_I3, O_M },
+ { M_SET, O_I3, O_M }, { M_SET, O_I3, O_M }, { M_SET, O_I3, O_M }, { M_SET, O_I3, O_M },
+
+ /* C0 - DF */
+ { M_CHG, O_I3, O_M }, { M_CHG, O_I3, O_M }, { M_CHG, O_I3, O_M }, { M_CHG, O_I3, O_M },
+ { M_CHG, O_I3, O_M }, { M_CHG, O_I3, O_M }, { M_CHG, O_I3, O_M }, { M_CHG, O_I3, O_M },
+ { M_BIT, O_I3, O_M }, { M_BIT, O_I3, O_M }, { M_BIT, O_I3, O_M }, { M_BIT, O_I3, O_M },
+ { M_BIT, O_I3, O_M }, { M_BIT, O_I3, O_M }, { M_BIT, O_I3, O_M }, { M_BIT, O_I3, O_M },
+ { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M },
+ { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M },
+ { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M },
+ { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M },
+
+ /* E0 - FF */
+ { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M },
+ { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M },
+ { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M },
+ { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }
+};
+
+
+static const tlcs900inst mnemonic_c0[256] =
+{
+ /* 00 - 1F */
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_PUSH, O_M, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_RLD, O_A, O_M }, { M_RRD, O_A, O_M },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_LD, O_M16, O_M }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 20 - 3F */
+ { M_LD, O_C8, O_M }, { M_LD, O_C8, O_M }, { M_LD, O_C8, O_M }, { M_LD, O_C8, O_M },
+ { M_LD, O_C8, O_M }, { M_LD, O_C8, O_M }, { M_LD, O_C8, O_M }, { M_LD, O_C8, O_M },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_EX, O_M, O_C8 }, { M_EX, O_M, O_C8 }, { M_EX, O_M, O_C8 }, { M_EX, O_M, O_C8 },
+ { M_EX, O_M, O_C8 }, { M_EX, O_M, O_C8 }, { M_EX, O_M, O_C8 }, { M_EX, O_M, O_C8 },
+ { M_ADD, O_M, O_I8 }, { M_ADC, O_M, O_I8 }, { M_SUB, O_M, O_I8 }, { M_SBC, O_M, O_I8 },
+ { M_AND, O_M, O_I8 }, { M_XOR, O_M, O_I8 }, { M_OR, O_M, O_I8 }, { M_CP, O_M, O_I8 },
+
+ /* 40 - 5F */
+ { M_MUL, O_MC16, O_M }, { M_MUL, O_MC16, O_M }, { M_MUL, O_MC16, O_M }, { M_MUL, O_MC16, O_M },
+ { M_MUL, O_MC16, O_M }, { M_MUL, O_MC16, O_M }, { M_MUL, O_MC16, O_M }, { M_MUL, O_MC16, O_M },
+ { M_MULS, O_MC16, O_M }, { M_MULS, O_MC16, O_M }, { M_MULS, O_MC16, O_M }, { M_MULS, O_MC16, O_M },
+ { M_MULS, O_MC16, O_M }, { M_MULS, O_MC16, O_M }, { M_MULS, O_MC16, O_M }, { M_MULS, O_MC16, O_M },
+ { M_DIV, O_MC16, O_M }, { M_DIV, O_MC16, O_M }, { M_DIV, O_MC16, O_M }, { M_DIV, O_MC16, O_M },
+ { M_DIV, O_MC16, O_M }, { M_DIV, O_MC16, O_M }, { M_DIV, O_MC16, O_M }, { M_DIV, O_MC16, O_M },
+ { M_DIVS, O_MC16, O_M }, { M_DIVS, O_MC16, O_M }, { M_DIVS, O_MC16, O_M }, { M_DIVS, O_MC16, O_M },
+ { M_DIVS, O_MC16, O_M }, { M_DIVS, O_MC16, O_M }, { M_DIVS, O_MC16, O_M }, { M_DIVS, O_MC16, O_M },
+
+ /* 60 - 7F */
+ { M_INC, O_I3, O_M }, { M_INC, O_I3, O_M }, { M_INC, O_I3, O_M }, { M_INC, O_I3, O_M },
+ { M_INC, O_I3, O_M }, { M_INC, O_I3, O_M }, { M_INC, O_I3, O_M }, { M_INC, O_I3, O_M },
+ { M_DEC, O_I3, O_M }, { M_DEC, O_I3, O_M }, { M_DEC, O_I3, O_M }, { M_DEC, O_I3, O_M },
+ { M_DEC, O_I3, O_M }, { M_DEC, O_I3, O_M }, { M_DEC, O_I3, O_M }, { M_DEC, O_I3, O_M },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_RLC, O_M, O_NONE }, { M_RRC, O_M, O_NONE }, { M_RL, O_M, O_NONE }, { M_RR, O_M, O_NONE },
+ { M_SLA, O_M, O_NONE }, { M_SRA, O_M, O_NONE }, { M_SLL, O_M, O_NONE }, { M_SRL, O_M, O_NONE },
+
+ /* 80 - 9F */
+ { M_ADD, O_C8, O_M }, { M_ADD, O_C8, O_M }, { M_ADD, O_C8, O_M }, { M_ADD, O_C8, O_M },
+ { M_ADD, O_C8, O_M }, { M_ADD, O_C8, O_M }, { M_ADD, O_C8, O_M }, { M_ADD, O_C8, O_M },
+ { M_ADD, O_M, O_C8 }, { M_ADD, O_M, O_C8 }, { M_ADD, O_M, O_C8 }, { M_ADD, O_M, O_C8 },
+ { M_ADD, O_M, O_C8 }, { M_ADD, O_M, O_C8 }, { M_ADD, O_M, O_C8 }, { M_ADD, O_M, O_C8 },
+ { M_ADC, O_C8, O_M }, { M_ADC, O_C8, O_M }, { M_ADC, O_C8, O_M }, { M_ADC, O_C8, O_M },
+ { M_ADC, O_C8, O_M }, { M_ADC, O_C8, O_M }, { M_ADC, O_C8, O_M }, { M_ADC, O_C8, O_M },
+ { M_ADC, O_M, O_C8 }, { M_ADC, O_M, O_C8 }, { M_ADC, O_M, O_C8 }, { M_ADC, O_M, O_C8 },
+ { M_ADC, O_M, O_C8 }, { M_ADC, O_M, O_C8 }, { M_ADC, O_M, O_C8 }, { M_ADC, O_M, O_C8 },
+
+ /* A0 - BF */
+ { M_SUB, O_C8, O_M }, { M_SUB, O_C8, O_M }, { M_SUB, O_C8, O_M }, { M_SUB, O_C8, O_M },
+ { M_SUB, O_C8, O_M }, { M_SUB, O_C8, O_M }, { M_SUB, O_C8, O_M }, { M_SUB, O_C8, O_M },
+ { M_SUB, O_M, O_C8 }, { M_SUB, O_M, O_C8 }, { M_SUB, O_M, O_C8 }, { M_SUB, O_M, O_C8 },
+ { M_SUB, O_M, O_C8 }, { M_SUB, O_M, O_C8 }, { M_SUB, O_M, O_C8 }, { M_SUB, O_M, O_C8 },
+ { M_SBC, O_C8, O_M }, { M_SBC, O_C8, O_M }, { M_SBC, O_C8, O_M }, { M_SBC, O_C8, O_M },
+ { M_SBC, O_C8, O_M }, { M_SBC, O_C8, O_M }, { M_SBC, O_C8, O_M }, { M_SBC, O_C8, O_M },
+ { M_SBC, O_M, O_C8 }, { M_SBC, O_M, O_C8 }, { M_SBC, O_M, O_C8 }, { M_SBC, O_M, O_C8 },
+ { M_SBC, O_M, O_C8 }, { M_SBC, O_M, O_C8 }, { M_SBC, O_M, O_C8 }, { M_SBC, O_M, O_C8 },
+
+ /* C0 - DF */
+ { M_AND, O_C8, O_M }, { M_AND, O_C8, O_M }, { M_AND, O_C8, O_M }, { M_AND, O_C8, O_M },
+ { M_AND, O_C8, O_M }, { M_AND, O_C8, O_M }, { M_AND, O_C8, O_M }, { M_AND, O_C8, O_M },
+ { M_AND, O_M, O_C8 }, { M_AND, O_M, O_C8 }, { M_AND, O_M, O_C8 }, { M_AND, O_M, O_C8 },
+ { M_AND, O_M, O_C8 }, { M_AND, O_M, O_C8 }, { M_AND, O_M, O_C8 }, { M_AND, O_M, O_C8 },
+ { M_XOR, O_C8, O_M }, { M_XOR, O_C8, O_M }, { M_XOR, O_C8, O_M }, { M_XOR, O_C8, O_M },
+ { M_XOR, O_C8, O_M }, { M_XOR, O_C8, O_M }, { M_XOR, O_C8, O_M }, { M_XOR, O_C8, O_M },
+ { M_XOR, O_M, O_C8 }, { M_XOR, O_M, O_C8 }, { M_XOR, O_M, O_C8 }, { M_XOR, O_M, O_C8 },
+ { M_XOR, O_M, O_C8 }, { M_XOR, O_M, O_C8 }, { M_XOR, O_M, O_C8 }, { M_XOR, O_M, O_C8 },
+
+ /* E0 - FF */
+ { M_OR, O_C8, O_M }, { M_OR, O_C8, O_M }, { M_OR, O_C8, O_M }, { M_OR, O_C8, O_M },
+ { M_OR, O_C8, O_M }, { M_OR, O_C8, O_M }, { M_OR, O_C8, O_M }, { M_OR, O_C8, O_M },
+ { M_OR, O_M, O_C8 }, { M_OR, O_M, O_C8 }, { M_OR, O_M, O_C8 }, { M_OR, O_M, O_C8 },
+ { M_OR, O_M, O_C8 }, { M_OR, O_M, O_C8 }, { M_OR, O_M, O_C8 }, { M_OR, O_M, O_C8 },
+ { M_CP, O_C8, O_M }, { M_CP, O_C8, O_M }, { M_CP, O_C8, O_M }, { M_CP, O_C8, O_M },
+ { M_CP, O_C8, O_M }, { M_CP, O_C8, O_M }, { M_CP, O_C8, O_M }, { M_CP, O_C8, O_M },
+ { M_CP, O_M, O_C8 }, { M_CP, O_M, O_C8 }, { M_CP, O_M, O_C8 }, { M_CP, O_M, O_C8 },
+ { M_CP, O_M, O_C8 }, { M_CP, O_M, O_C8 }, { M_CP, O_M, O_C8 }, { M_CP, O_M, O_C8 },
+};
+
+
+/* TODO: M_MUL_O_I8, M_MULS_O_I8, M_DIV_O_I8, M_DIVS_O_i8 need to be fixed */
+static const tlcs900inst mnemonic_c8[256] =
+{
+ /* 00 - 1F */
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_LD, O_R, O_I8 },
+ { M_PUSH, O_R, O_NONE }, { M_POP, O_R, O_NONE }, { M_CPL, O_R, O_NONE }, { M_NEG, O_R, O_NONE },
+ { M_MUL, O_R, O_I8 }, { M_MULS, O_R, O_I8 }, { M_DIV, O_R, O_I8 }, { M_DIVS, O_R, O_I8 },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DAA, O_R, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DJNZ, O_R, O_D8 }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 20 - 3F */
+ { M_ANDCF, O_I8, O_R }, { M_ORCF, O_I8, O_R }, { M_XORCF, O_I8, O_R }, { M_LDCF, O_I8, O_R },
+ { M_STCF, O_I8, O_R }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_ANDCF, O_A, O_R }, { M_ORCF, O_A, O_R }, { M_XORCF, O_A, O_R }, { M_LDCF, O_A, O_R },
+ { M_STCF, O_A, O_R }, { M_DB, O_NONE, O_NONE }, { M_LDC, O_CR8, O_R }, { M_LDC, O_R, O_CR8 },
+ { M_RES, O_I8, O_R }, { M_SET, O_I8, O_R }, { M_CHG, O_I8, O_R }, { M_BIT, O_I8, O_R },
+ { M_TSET, O_I8, O_R }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 40 - 5F */
+ { M_MUL, O_MC16, O_R }, { M_MUL, O_MC16, O_R }, { M_MUL, O_MC16, O_R }, { M_MUL, O_MC16, O_R },
+ { M_MUL, O_MC16, O_R }, { M_MUL, O_MC16, O_R }, { M_MUL, O_MC16, O_R }, { M_MUL, O_MC16, O_R },
+ { M_MULS, O_MC16, O_R }, { M_MULS, O_MC16, O_R }, { M_MULS, O_MC16, O_R }, { M_MULS, O_MC16, O_R },
+ { M_MULS, O_MC16, O_R }, { M_MULS, O_MC16, O_R }, { M_MULS, O_MC16, O_R }, { M_MULS, O_MC16, O_R },
+ { M_DIV, O_MC16, O_R }, { M_DIV, O_MC16, O_R }, { M_DIV, O_MC16, O_R }, { M_DIV, O_MC16, O_R },
+ { M_DIV, O_MC16, O_R }, { M_DIV, O_MC16, O_R }, { M_DIV, O_MC16, O_R }, { M_DIV, O_MC16, O_R },
+ { M_DIVS, O_MC16, O_R }, { M_DIVS, O_MC16, O_R }, { M_DIVS, O_MC16, O_R }, { M_DIVS, O_MC16, O_R },
+ { M_DIVS, O_MC16, O_R }, { M_DIVS, O_MC16, O_R }, { M_DIVS, O_MC16, O_R }, { M_DIVS, O_MC16, O_R },
+
+ /* 60 - 7F */
+ { M_INC, O_I3, O_R }, { M_INC, O_I3, O_R }, { M_INC, O_I3, O_R }, { M_INC, O_I3, O_R },
+ { M_INC, O_I3, O_R }, { M_INC, O_I3, O_R }, { M_INC, O_I3, O_R }, { M_INC, O_I3, O_R },
+ { M_DEC, O_I3, O_R }, { M_DEC, O_I3, O_R }, { M_DEC, O_I3, O_R }, { M_DEC, O_I3, O_R },
+ { M_DEC, O_I3, O_R }, { M_DEC, O_I3, O_R }, { M_DEC, O_I3, O_R }, { M_DEC, O_I3, O_R },
+ { M_SCC, O_CC, O_R }, { M_SCC, O_CC, O_R }, { M_SCC, O_CC, O_R }, { M_SCC, O_CC, O_R },
+ { M_SCC, O_CC, O_R }, { M_SCC, O_CC, O_R }, { M_SCC, O_CC, O_R }, { M_SCC, O_CC, O_R },
+ { M_SCC, O_CC, O_R }, { M_SCC, O_CC, O_R }, { M_SCC, O_CC, O_R }, { M_SCC, O_CC, O_R },
+ { M_SCC, O_CC, O_R }, { M_SCC, O_CC, O_R }, { M_SCC, O_CC, O_R }, { M_SCC, O_CC, O_R },
+
+ /* 80 - 9F */
+ { M_ADD, O_C8, O_R }, { M_ADD, O_C8, O_R }, { M_ADD, O_C8, O_R }, { M_ADD, O_C8, O_R },
+ { M_ADD, O_C8, O_R }, { M_ADD, O_C8, O_R }, { M_ADD, O_C8, O_R }, { M_ADD, O_C8, O_R },
+ { M_LD, O_C8, O_R }, { M_LD, O_C8, O_R }, { M_LD, O_C8, O_R }, { M_LD, O_C8, O_R },
+ { M_LD, O_C8, O_R }, { M_LD, O_C8, O_R }, { M_LD, O_C8, O_R }, { M_LD, O_C8, O_R },
+ { M_ADC, O_C8, O_R }, { M_ADC, O_C8, O_R }, { M_ADC, O_C8, O_R }, { M_ADC, O_C8, O_R },
+ { M_ADC, O_C8, O_R }, { M_ADC, O_C8, O_R }, { M_ADC, O_C8, O_R }, { M_ADC, O_C8, O_R },
+ { M_LD, O_R, O_C8 }, { M_LD, O_R, O_C8 }, { M_LD, O_R, O_C8 }, { M_LD, O_R, O_C8 },
+ { M_LD, O_R, O_C8 }, { M_LD, O_R, O_C8 }, { M_LD, O_R, O_C8 }, { M_LD, O_R, O_C8 },
+
+ /* A0 - BF */
+ { M_SUB, O_C8, O_R }, { M_SUB, O_C8, O_R }, { M_SUB, O_C8, O_R }, { M_SUB, O_C8, O_R },
+ { M_SUB, O_C8, O_R }, { M_SUB, O_C8, O_R }, { M_SUB, O_C8, O_R }, { M_SUB, O_C8, O_R },
+ { M_LD, O_R, O_I3 }, { M_LD, O_R, O_I3 }, { M_LD, O_R, O_I3 }, { M_LD, O_R, O_I3 },
+ { M_LD, O_R, O_I3 }, { M_LD, O_R, O_I3 }, { M_LD, O_R, O_I3 }, { M_LD, O_R, O_I3 },
+ { M_SBC, O_C8, O_R }, { M_SBC, O_C8, O_R }, { M_SBC, O_C8, O_R }, { M_SBC, O_C8, O_R },
+ { M_SBC, O_C8, O_R }, { M_SBC, O_C8, O_R }, { M_SBC, O_C8, O_R }, { M_SBC, O_C8, O_R },
+ { M_EX, O_C8, O_R }, { M_EX, O_C8, O_R }, { M_EX, O_C8, O_R }, { M_EX, O_C8, O_R },
+ { M_EX, O_C8, O_R }, { M_EX, O_C8, O_R }, { M_EX, O_C8, O_R }, { M_EX, O_C8, O_R },
+
+ /* C0 - DF */
+ { M_AND, O_C8, O_R }, { M_AND, O_C8, O_R }, { M_AND, O_C8, O_R }, { M_AND, O_C8, O_R },
+ { M_AND, O_C8, O_R }, { M_AND, O_C8, O_R }, { M_AND, O_C8, O_R }, { M_AND, O_C8, O_R },
+ { M_ADD, O_R, O_I8 }, { M_ADC, O_R, O_I8 }, { M_SUB, O_R, O_I8 }, { M_SBC, O_R, O_I8 },
+ { M_AND, O_R, O_I8 }, { M_XOR, O_R, O_I8 }, { M_OR, O_R, O_I8 }, { M_CP, O_R, O_I8 },
+ { M_XOR, O_C8, O_R }, { M_XOR, O_C8, O_R }, { M_XOR, O_C8, O_R }, { M_XOR, O_C8, O_R },
+ { M_XOR, O_C8, O_R }, { M_XOR, O_C8, O_R }, { M_XOR, O_C8, O_R }, { M_XOR, O_C8, O_R },
+ { M_CP, O_R, O_I3 }, { M_CP, O_R, O_I3 }, { M_CP, O_R, O_I3 }, { M_CP, O_R, O_I3 },
+ { M_CP, O_R, O_I3 }, { M_CP, O_R, O_I3 }, { M_CP, O_R, O_I3 }, { M_CP, O_R, O_I3 },
+
+ /* E0 - FF */
+ { M_OR, O_C8, O_R }, { M_OR, O_C8, O_R }, { M_OR, O_C8, O_R }, { M_OR, O_C8, O_R },
+ { M_OR, O_C8, O_R }, { M_OR, O_C8, O_R }, { M_OR, O_C8, O_R }, { M_OR, O_C8, O_R },
+ { M_RLC, O_I8, O_R }, { M_RRC, O_I8, O_R }, { M_RL, O_I8, O_R }, { M_RR, O_I8, O_R },
+ { M_SLA, O_I8, O_R }, { M_SRA, O_I8, O_R }, { M_SLL, O_I8, O_R }, { M_SRL, O_I8, O_R },
+ { M_CP, O_C8, O_R }, { M_CP, O_C8, O_R }, { M_CP, O_C8, O_R }, { M_CP, O_C8, O_R },
+ { M_CP, O_C8, O_R }, { M_CP, O_C8, O_R }, { M_CP, O_C8, O_R }, { M_CP, O_C8, O_R },
+ { M_RLC, O_A, O_R }, { M_RRC, O_A, O_R }, { M_RL, O_A, O_R }, { M_RR, O_A, O_R },
+ { M_SLA, O_A, O_R }, { M_SRA, O_A, O_R }, { M_SLL, O_A, O_R }, { M_SRL, O_A, O_R }
+};
+
+
+static const tlcs900inst mnemonic_d0[256] =
+{
+ /* 00 - 1F */
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_PUSHW, O_M, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_LDW, O_M16, O_M }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 20 - 3F */
+ { M_LD, O_C16, O_M }, { M_LD, O_C16, O_M }, { M_LD, O_C16, O_M }, { M_LD, O_C16, O_M },
+ { M_LD, O_C16, O_M }, { M_LD, O_C16, O_M }, { M_LD, O_C16, O_M }, { M_LD, O_C16, O_M },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_EX, O_M, O_C16 }, { M_EX, O_M, O_C16 }, { M_EX, O_M, O_C16 }, { M_EX, O_M, O_C16 },
+ { M_EX, O_M, O_C16 }, { M_EX, O_M, O_C16 }, { M_EX, O_M, O_C16 }, { M_EX, O_M, O_C16 },
+ { M_ADD, O_M, O_I16 }, { M_ADC, O_M, O_I16 }, { M_SUB, O_M, O_I16 }, { M_SBC, O_M, O_I16 },
+ { M_AND, O_M, O_I16 }, { M_XOR, O_M, O_I16 }, { M_OR, O_M, O_I16 }, { M_CP, O_M, O_I16 },
+
+ /* 40 - 5F */
+ { M_MUL, O_C32, O_M }, { M_MUL, O_C32, O_M }, { M_MUL, O_C32, O_M }, { M_MUL, O_C32, O_M },
+ { M_MUL, O_C32, O_M }, { M_MUL, O_C32, O_M }, { M_MUL, O_C32, O_M }, { M_MUL, O_C32, O_M },
+ { M_MULS, O_C32, O_M }, { M_MULS, O_C32, O_M }, { M_MULS, O_C32, O_M }, { M_MULS, O_C32, O_M },
+ { M_MULS, O_C32, O_M }, { M_MULS, O_C32, O_M }, { M_MULS, O_C32, O_M }, { M_MULS, O_C32, O_M },
+ { M_DIV, O_C32, O_M }, { M_DIV, O_C32, O_M }, { M_DIV, O_C32, O_M }, { M_DIV, O_C32, O_M },
+ { M_DIV, O_C32, O_M }, { M_DIV, O_C32, O_M }, { M_DIV, O_C32, O_M }, { M_DIV, O_C32, O_M },
+ { M_DIVS, O_C32, O_M }, { M_DIVS, O_C32, O_M }, { M_DIVS, O_C32, O_M }, { M_DIVS, O_C32, O_M },
+ { M_DIVS, O_C32, O_M }, { M_DIVS, O_C32, O_M }, { M_DIVS, O_C32, O_M }, { M_DIVS, O_C32, O_M },
+
+ /* 60 - 7F */
+ { M_INCW, O_I3, O_M }, { M_INCW, O_I3, O_M }, { M_INCW, O_I3, O_M }, { M_INCW, O_I3, O_M },
+ { M_INCW, O_I3, O_M }, { M_INCW, O_I3, O_M }, { M_INCW, O_I3, O_M }, { M_INCW, O_I3, O_M },
+ { M_DECW, O_I3, O_M }, { M_DECW, O_I3, O_M }, { M_DECW, O_I3, O_M }, { M_DECW, O_I3, O_M },
+ { M_DECW, O_I3, O_M }, { M_DECW, O_I3, O_M }, { M_DECW, O_I3, O_M }, { M_DECW, O_I3, O_M },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_RLCW, O_M, O_NONE }, { M_RRCW, O_M, O_NONE }, { M_RLW, O_M, O_NONE }, { M_RRW, O_M, O_NONE },
+ { M_SLAW, O_M, O_NONE }, { M_SRAW, O_M, O_NONE }, { M_SLLW, O_M, O_NONE }, { M_SRLW, O_M, O_NONE },
+
+ /* 80 - 9F */
+ { M_ADD, O_C16, O_M }, { M_ADD, O_C16, O_M }, { M_ADD, O_C16, O_M }, { M_ADD, O_C16, O_M },
+ { M_ADD, O_C16, O_M }, { M_ADD, O_C16, O_M }, { M_ADD, O_C16, O_M }, { M_ADD, O_C16, O_M },
+ { M_ADD, O_M, O_C16 }, { M_ADD, O_M, O_C16 }, { M_ADD, O_M, O_C16 }, { M_ADD, O_M, O_C16 },
+ { M_ADD, O_M, O_C16 }, { M_ADD, O_M, O_C16 }, { M_ADD, O_M, O_C16 }, { M_ADD, O_M, O_C16 },
+ { M_ADC, O_C16, O_M }, { M_ADC, O_C16, O_M }, { M_ADC, O_C16, O_M }, { M_ADC, O_C16, O_M },
+ { M_ADC, O_C16, O_M }, { M_ADC, O_C16, O_M }, { M_ADC, O_C16, O_M }, { M_ADC, O_C16, O_M },
+ { M_ADC, O_M, O_C16 }, { M_ADC, O_M, O_C16 }, { M_ADC, O_M, O_C16 }, { M_ADC, O_M, O_C16 },
+ { M_ADC, O_M, O_C16 }, { M_ADC, O_M, O_C16 }, { M_ADC, O_M, O_C16 }, { M_ADC, O_M, O_C16 },
+
+ /* A0 - BF */
+ { M_SUB, O_C16, O_M }, { M_SUB, O_C16, O_M }, { M_SUB, O_C16, O_M }, { M_SUB, O_C16, O_M },
+ { M_SUB, O_C16, O_M }, { M_SUB, O_C16, O_M }, { M_SUB, O_C16, O_M }, { M_SUB, O_C16, O_M },
+ { M_SUB, O_M, O_C16 }, { M_SUB, O_M, O_C16 }, { M_SUB, O_M, O_C16 }, { M_SUB, O_M, O_C16 },
+ { M_SUB, O_M, O_C16 }, { M_SUB, O_M, O_C16 }, { M_SUB, O_M, O_C16 }, { M_SUB, O_M, O_C16 },
+ { M_SBC, O_C16, O_M }, { M_SBC, O_C16, O_M }, { M_SBC, O_C16, O_M }, { M_SBC, O_C16, O_M },
+ { M_SBC, O_C16, O_M }, { M_SBC, O_C16, O_M }, { M_SBC, O_C16, O_M }, { M_SBC, O_C16, O_M },
+ { M_SBC, O_M, O_C16 }, { M_SBC, O_M, O_C16 }, { M_SBC, O_M, O_C16 }, { M_SBC, O_M, O_C16 },
+ { M_SBC, O_M, O_C16 }, { M_SBC, O_M, O_C16 }, { M_SBC, O_M, O_C16 }, { M_SBC, O_M, O_C16 },
+
+ /* C0 - DF */
+ { M_AND, O_C16, O_M }, { M_AND, O_C16, O_M }, { M_AND, O_C16, O_M }, { M_AND, O_C16, O_M },
+ { M_AND, O_C16, O_M }, { M_AND, O_C16, O_M }, { M_AND, O_C16, O_M }, { M_AND, O_C16, O_M },
+ { M_AND, O_M, O_C16 }, { M_AND, O_M, O_C16 }, { M_AND, O_M, O_C16 }, { M_AND, O_M, O_C16 },
+ { M_AND, O_M, O_C16 }, { M_AND, O_M, O_C16 }, { M_AND, O_M, O_C16 }, { M_AND, O_M, O_C16 },
+ { M_XOR, O_C16, O_M }, { M_XOR, O_C16, O_M }, { M_XOR, O_C16, O_M }, { M_XOR, O_C16, O_M },
+ { M_XOR, O_C16, O_M }, { M_XOR, O_C16, O_M }, { M_XOR, O_C16, O_M }, { M_XOR, O_C16, O_M },
+ { M_XOR, O_M, O_C16 }, { M_XOR, O_M, O_C16 }, { M_XOR, O_M, O_C16 }, { M_XOR, O_M, O_C16 },
+ { M_XOR, O_M, O_C16 }, { M_XOR, O_M, O_C16 }, { M_XOR, O_M, O_C16 }, { M_XOR, O_M, O_C16 },
+
+ /* E0 - FF */
+ { M_OR, O_C16, O_M }, { M_OR, O_C16, O_M }, { M_OR, O_C16, O_M }, { M_OR, O_C16, O_M },
+ { M_OR, O_C16, O_M }, { M_OR, O_C16, O_M }, { M_OR, O_C16, O_M }, { M_OR, O_C16, O_M },
+ { M_OR, O_M, O_C16 }, { M_OR, O_M, O_C16 }, { M_OR, O_M, O_C16 }, { M_OR, O_M, O_C16 },
+ { M_OR, O_M, O_C16 }, { M_OR, O_M, O_C16 }, { M_OR, O_M, O_C16 }, { M_OR, O_M, O_C16 },
+ { M_CP, O_C16, O_M }, { M_CP, O_C16, O_M }, { M_CP, O_C16, O_M }, { M_CP, O_C16, O_M },
+ { M_CP, O_C16, O_M }, { M_CP, O_C16, O_M }, { M_CP, O_C16, O_M }, { M_CP, O_C16, O_M },
+ { M_CP, O_M, O_C16 }, { M_CP, O_M, O_C16 }, { M_CP, O_M, O_C16 }, { M_CP, O_M, O_C16 },
+ { M_CP, O_M, O_C16 }, { M_CP, O_M, O_C16 }, { M_CP, O_M, O_C16 }, { M_CP, O_M, O_C16 },
+};
+
+
+static const tlcs900inst mnemonic_d8[256] =
+{
+ /* 00 - 1F */
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_LD, O_R, O_I16 },
+ { M_PUSH, O_R, O_NONE }, { M_POP, O_R, O_NONE }, { M_CPL, O_R, O_NONE }, { M_NEG, O_R, O_NONE },
+ { M_MUL, O_R, O_I16 }, { M_MULS, O_R, O_I16 }, { M_DIV, O_R, O_I16 }, { M_DIVS, O_R, O_I16 },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_BS1F, O_A, O_R }, { M_BS1B, O_A, O_R },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_EXTZ, O_R, O_NONE }, { M_EXTS, O_R, O_NONE },
+ { M_PAA, O_R, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_MIRR, O_R, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_MULA, O_R, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DJNZ, O_R, O_D8 }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 20 - 3F */
+ { M_ANDCF, O_I8, O_R }, { M_ORCF, O_I8, O_R }, { M_XORCF, O_I8, O_R }, { M_LDCF, O_I8, O_R },
+ { M_STCF, O_I8, O_R }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_ANDCF, O_A, O_R }, { M_ORCF, O_A, O_R }, { M_XORCF, O_A, O_R }, { M_LDCF, O_A, O_R },
+ { M_STCF, O_A, O_R }, { M_DB, O_NONE, O_NONE }, { M_LDC, O_CR16, O_R }, { M_LDC, O_R, O_CR16 },
+ { M_RES, O_I8, O_R }, { M_SET, O_I8, O_R }, { M_CHG, O_I8, O_R }, { M_BIT, O_I8, O_R },
+ { M_TSET, O_I8, O_R }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_MINC1, O_I16, O_R }, { M_MINC2, O_I16, O_R }, { M_MINC4, O_I16, O_R }, { M_DB, O_NONE, O_NONE },
+ { M_MDEC1, O_I16, O_R }, { M_MDEC2, O_I16, O_R }, { M_MDEC4, O_I16, O_R }, { M_DB, O_NONE, O_NONE },
+
+ /* 40 - 5F */
+ { M_MUL, O_C32, O_R }, { M_MUL, O_C32, O_R }, { M_MUL, O_C32, O_R }, { M_MUL, O_C32, O_R },
+ { M_MUL, O_C32, O_R }, { M_MUL, O_C32, O_R }, { M_MUL, O_C32, O_R }, { M_MUL, O_C32, O_R },
+ { M_MULS, O_C32, O_R }, { M_MULS, O_C32, O_R }, { M_MULS, O_C32, O_R }, { M_MULS, O_C32, O_R },
+ { M_MULS, O_C32, O_R }, { M_MULS, O_C32, O_R }, { M_MULS, O_C32, O_R }, { M_MULS, O_C32, O_R },
+ { M_DIV, O_C32, O_R }, { M_DIV, O_C32, O_R }, { M_DIV, O_C32, O_R }, { M_DIV, O_C32, O_R },
+ { M_DIV, O_C32, O_R }, { M_DIV, O_C32, O_R }, { M_DIV, O_C32, O_R }, { M_DIV, O_C32, O_R },
+ { M_DIVS, O_C32, O_R }, { M_DIVS, O_C32, O_R }, { M_DIVS, O_C32, O_R }, { M_DIVS, O_C32, O_R },
+ { M_DIVS, O_C32, O_R }, { M_DIVS, O_C32, O_R }, { M_DIVS, O_C32, O_R }, { M_DIVS, O_C32, O_R },
+
+ /* 60 - 7F */
+ { M_INC, O_I3, O_R }, { M_INC, O_I3, O_R }, { M_INC, O_I3, O_R }, { M_INC, O_I3, O_R },
+ { M_INC, O_I3, O_R }, { M_INC, O_I3, O_R }, { M_INC, O_I3, O_R }, { M_INC, O_I3, O_R },
+ { M_DEC, O_I3, O_R }, { M_DEC, O_I3, O_R }, { M_DEC, O_I3, O_R }, { M_DEC, O_I3, O_R },
+ { M_DEC, O_I3, O_R }, { M_DEC, O_I3, O_R }, { M_DEC, O_I3, O_R }, { M_DEC, O_I3, O_R },
+ { M_SCC, O_CC, O_R }, { M_SCC, O_CC, O_R }, { M_SCC, O_CC, O_R }, { M_SCC, O_CC, O_R },
+ { M_SCC, O_CC, O_R }, { M_SCC, O_CC, O_R }, { M_SCC, O_CC, O_R }, { M_SCC, O_CC, O_R },
+ { M_SCC, O_CC, O_R }, { M_SCC, O_CC, O_R }, { M_SCC, O_CC, O_R }, { M_SCC, O_CC, O_R },
+ { M_SCC, O_CC, O_R }, { M_SCC, O_CC, O_R }, { M_SCC, O_CC, O_R }, { M_SCC, O_CC, O_R },
+
+ /* 80 - 9F */
+ { M_ADD, O_C16, O_R }, { M_ADD, O_C16, O_R }, { M_ADD, O_C16, O_R }, { M_ADD, O_C16, O_R },
+ { M_ADD, O_C16, O_R }, { M_ADD, O_C16, O_R }, { M_ADD, O_C16, O_R }, { M_ADD, O_C16, O_R },
+ { M_LD, O_C16, O_R }, { M_LD, O_C16, O_R }, { M_LD, O_C16, O_R }, { M_LD, O_C16, O_R },
+ { M_LD, O_C16, O_R }, { M_LD, O_C16, O_R }, { M_LD, O_C16, O_R }, { M_LD, O_C16, O_R },
+ { M_ADC, O_C16, O_R }, { M_ADC, O_C16, O_R }, { M_ADC, O_C16, O_R }, { M_ADC, O_C16, O_R },
+ { M_ADC, O_C16, O_R }, { M_ADC, O_C16, O_R }, { M_ADC, O_C16, O_R }, { M_ADC, O_C16, O_R },
+ { M_LD, O_R, O_C16 }, { M_LD, O_R, O_C16 }, { M_LD, O_R, O_C16 }, { M_LD, O_R, O_C16 },
+ { M_LD, O_R, O_C16 }, { M_LD, O_R, O_C16 }, { M_LD, O_R, O_C16 }, { M_LD, O_R, O_C16 },
+
+ /* A0 - BF */
+ { M_SUB, O_C16, O_R }, { M_SUB, O_C16, O_R }, { M_SUB, O_C16, O_R }, { M_SUB, O_C16, O_R },
+ { M_SUB, O_C16, O_R }, { M_SUB, O_C16, O_R }, { M_SUB, O_C16, O_R }, { M_SUB, O_C16, O_R },
+ { M_LD, O_R, O_I3 }, { M_LD, O_R, O_I3 }, { M_LD, O_R, O_I3 }, { M_LD, O_R, O_I3 },
+ { M_LD, O_R, O_I3 }, { M_LD, O_R, O_I3 }, { M_LD, O_R, O_I3 }, { M_LD, O_R, O_I3 },
+ { M_SBC, O_C16, O_R }, { M_SBC, O_C16, O_R }, { M_SBC, O_C16, O_R }, { M_SBC, O_C16, O_R },
+ { M_SBC, O_C16, O_R }, { M_SBC, O_C16, O_R }, { M_SBC, O_C16, O_R }, { M_SBC, O_C16, O_R },
+ { M_EX, O_C16, O_R }, { M_EX, O_C16, O_R }, { M_EX, O_C16, O_R }, { M_EX, O_C16, O_R },
+ { M_EX, O_C16, O_R }, { M_EX, O_C16, O_R }, { M_EX, O_C16, O_R }, { M_EX, O_C16, O_R },
+
+ /* C0 - DF */
+ { M_AND, O_C16, O_R }, { M_AND, O_C16, O_R }, { M_AND, O_C16, O_R }, { M_AND, O_C16, O_R },
+ { M_AND, O_C16, O_R }, { M_AND, O_C16, O_R }, { M_AND, O_C16, O_R }, { M_AND, O_C16, O_R },
+ { M_ADD, O_R, O_I16 }, { M_ADC, O_R, O_I16 }, { M_SUB, O_R, O_I16 }, { M_SBC, O_R, O_I16 },
+ { M_AND, O_R, O_I16 }, { M_XOR, O_R, O_I16 }, { M_OR, O_R, O_I16 }, { M_CP, O_R, O_I16 },
+ { M_XOR, O_C16, O_R }, { M_XOR, O_C16, O_R }, { M_XOR, O_C16, O_R }, { M_XOR, O_C16, O_R },
+ { M_XOR, O_C16, O_R }, { M_XOR, O_C16, O_R }, { M_XOR, O_C16, O_R }, { M_XOR, O_C16, O_R },
+ { M_CP, O_R, O_I3 }, { M_CP, O_R, O_I3 }, { M_CP, O_R, O_I3 }, { M_CP, O_R, O_I3 },
+ { M_CP, O_R, O_I3 }, { M_CP, O_R, O_I3 }, { M_CP, O_R, O_I3 }, { M_CP, O_R, O_I3 },
+
+ /* E0 - FF */
+ { M_OR, O_C16, O_R }, { M_OR, O_C16, O_R }, { M_OR, O_C16, O_R }, { M_OR, O_C16, O_R },
+ { M_OR, O_C16, O_R }, { M_OR, O_C16, O_R }, { M_OR, O_C16, O_R }, { M_OR, O_C16, O_R },
+ { M_RLC, O_I8, O_R }, { M_RRC, O_I8, O_R }, { M_RL, O_I8, O_R }, { M_RR, O_I8, O_R },
+ { M_SLA, O_I8, O_R }, { M_SRA, O_I8, O_R }, { M_SLL, O_I8, O_R }, { M_SRL, O_I8, O_R },
+ { M_CP, O_C16, O_R }, { M_CP, O_C16, O_R }, { M_CP, O_C16, O_R }, { M_CP, O_C16, O_R },
+ { M_CP, O_C16, O_R }, { M_CP, O_C16, O_R }, { M_CP, O_C16, O_R }, { M_CP, O_C16, O_R },
+ { M_RLC, O_A, O_R }, { M_RRC, O_A, O_R }, { M_RL, O_A, O_R }, { M_RR, O_A, O_R },
+ { M_SLA, O_A, O_R }, { M_SRA, O_A, O_R }, { M_SLL, O_A, O_R }, { M_SRL, O_A, O_R }
+};
+
+
+static const tlcs900inst mnemonic_e0[256] =
+{
+ /* 00 - 1F */
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 20 - 3F */
+ { M_LD, O_C32, O_M }, { M_LD, O_C32, O_M }, { M_LD, O_C32, O_M }, { M_LD, O_C32, O_M },
+ { M_LD, O_C32, O_M }, { M_LD, O_C32, O_M }, { M_LD, O_C32, O_M }, { M_LD, O_C32, O_M },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 40 - 5F */
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 60 - 7F */
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 80 - 9F */
+ { M_ADD, O_C32, O_M }, { M_ADD, O_C32, O_M }, { M_ADD, O_C32, O_M }, { M_ADD, O_C32, O_M },
+ { M_ADD, O_C32, O_M }, { M_ADD, O_C32, O_M }, { M_ADD, O_C32, O_M }, { M_ADD, O_C32, O_M },
+ { M_ADD, O_M, O_C32 }, { M_ADD, O_M, O_C32 }, { M_ADD, O_M, O_C32 }, { M_ADD, O_M, O_C32 },
+ { M_ADD, O_M, O_C32 }, { M_ADD, O_M, O_C32 }, { M_ADD, O_M, O_C32 }, { M_ADD, O_M, O_C32 },
+ { M_ADC, O_C32, O_M }, { M_ADC, O_C32, O_M }, { M_ADC, O_C32, O_M }, { M_ADC, O_C32, O_M },
+ { M_ADC, O_C32, O_M }, { M_ADC, O_C32, O_M }, { M_ADC, O_C32, O_M }, { M_ADC, O_C32, O_M },
+ { M_ADC, O_M, O_C32 }, { M_ADC, O_M, O_C32 }, { M_ADC, O_M, O_C32 }, { M_ADC, O_M, O_C32 },
+ { M_ADC, O_M, O_C32 }, { M_ADC, O_M, O_C32 }, { M_ADC, O_M, O_C32 }, { M_ADC, O_M, O_C32 },
+
+ /* A0 - BF */
+ { M_SUB, O_C32, O_M }, { M_SUB, O_C32, O_M }, { M_SUB, O_C32, O_M }, { M_SUB, O_C32, O_M },
+ { M_SUB, O_C32, O_M }, { M_SUB, O_C32, O_M }, { M_SUB, O_C32, O_M }, { M_SUB, O_C32, O_M },
+ { M_SUB, O_M, O_C32 }, { M_SUB, O_M, O_C32 }, { M_SUB, O_M, O_C32 }, { M_SUB, O_M, O_C32 },
+ { M_SUB, O_M, O_C32 }, { M_SUB, O_M, O_C32 }, { M_SUB, O_M, O_C32 }, { M_SUB, O_M, O_C32 },
+ { M_SBC, O_C32, O_M }, { M_SBC, O_C32, O_M }, { M_SBC, O_C32, O_M }, { M_SBC, O_C32, O_M },
+ { M_SBC, O_C32, O_M }, { M_SBC, O_C32, O_M }, { M_SBC, O_C32, O_M }, { M_SBC, O_C32, O_M },
+ { M_SBC, O_M, O_C32 }, { M_SBC, O_M, O_C32 }, { M_SBC, O_M, O_C32 }, { M_SBC, O_M, O_C32 },
+ { M_SBC, O_M, O_C32 }, { M_SBC, O_M, O_C32 }, { M_SBC, O_M, O_C32 }, { M_SBC, O_M, O_C32 },
+
+ /* C0 - DF */
+ { M_AND, O_C32, O_M }, { M_AND, O_C32, O_M }, { M_AND, O_C32, O_M }, { M_AND, O_C32, O_M },
+ { M_AND, O_C32, O_M }, { M_AND, O_C32, O_M }, { M_AND, O_C32, O_M }, { M_AND, O_C32, O_M },
+ { M_AND, O_M, O_C32 }, { M_AND, O_M, O_C32 }, { M_AND, O_M, O_C32 }, { M_AND, O_M, O_C32 },
+ { M_AND, O_M, O_C32 }, { M_AND, O_M, O_C32 }, { M_AND, O_M, O_C32 }, { M_AND, O_M, O_C32 },
+ { M_XOR, O_C32, O_M }, { M_XOR, O_C32, O_M }, { M_XOR, O_C32, O_M }, { M_XOR, O_C32, O_M },
+ { M_XOR, O_C32, O_M }, { M_XOR, O_C32, O_M }, { M_XOR, O_C32, O_M }, { M_XOR, O_C32, O_M },
+ { M_XOR, O_M, O_C32 }, { M_XOR, O_M, O_C32 }, { M_XOR, O_M, O_C32 }, { M_XOR, O_M, O_C32 },
+ { M_XOR, O_M, O_C32 }, { M_XOR, O_M, O_C32 }, { M_XOR, O_M, O_C32 }, { M_XOR, O_M, O_C32 },
+
+ /* E0 - FF */
+ { M_OR, O_C32, O_M }, { M_OR, O_C32, O_M }, { M_OR, O_C32, O_M }, { M_OR, O_C32, O_M },
+ { M_OR, O_C32, O_M }, { M_OR, O_C32, O_M }, { M_OR, O_C32, O_M }, { M_OR, O_C32, O_M },
+ { M_OR, O_M, O_C32 }, { M_OR, O_M, O_C32 }, { M_OR, O_M, O_C32 }, { M_OR, O_M, O_C32 },
+ { M_OR, O_M, O_C32 }, { M_OR, O_M, O_C32 }, { M_OR, O_M, O_C32 }, { M_OR, O_M, O_C32 },
+ { M_CP, O_C32, O_M }, { M_CP, O_C32, O_M }, { M_CP, O_C32, O_M }, { M_CP, O_C32, O_M },
+ { M_CP, O_C32, O_M }, { M_CP, O_C32, O_M }, { M_CP, O_C32, O_M }, { M_CP, O_C32, O_M },
+ { M_CP, O_M, O_C32 }, { M_CP, O_M, O_C32 }, { M_CP, O_M, O_C32 }, { M_CP, O_M, O_C32 },
+ { M_CP, O_M, O_C32 }, { M_CP, O_M, O_C32 }, { M_CP, O_M, O_C32 }, { M_CP, O_M, O_C32 },
+};
+
+
+static const tlcs900inst mnemonic_e8[256] =
+{
+ /* 00 - 1F */
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_LD, O_R, O_I32 },
+ { M_PUSH, O_R, O_NONE }, { M_POP, O_R, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_LINK, O_R, O_I16 }, { M_UNLK, O_R, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_EXTZ, O_R, O_NONE }, { M_EXTS, O_R, O_NONE },
+ { M_PAA, O_R, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 20 - 3F */
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_LDC, O_CR32, O_R }, { M_LDC, O_R, O_CR32 },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 40 - 5F */
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 60 - 7F */
+ { M_INC, O_I3, O_R }, { M_INC, O_I3, O_R }, { M_INC, O_I3, O_R }, { M_INC, O_I3, O_R },
+ { M_INC, O_I3, O_R }, { M_INC, O_I3, O_R }, { M_INC, O_I3, O_R }, { M_INC, O_I3, O_R },
+ { M_DEC, O_I3, O_R }, { M_DEC, O_I3, O_R }, { M_DEC, O_I3, O_R }, { M_DEC, O_I3, O_R },
+ { M_DEC, O_I3, O_R }, { M_DEC, O_I3, O_R }, { M_DEC, O_I3, O_R }, { M_DEC, O_I3, O_R },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 80 - 9F */
+ { M_ADD, O_C32, O_R }, { M_ADD, O_C32, O_R }, { M_ADD, O_C32, O_R }, { M_ADD, O_C32, O_R },
+ { M_ADD, O_C32, O_R }, { M_ADD, O_C32, O_R }, { M_ADD, O_C32, O_R }, { M_ADD, O_C32, O_R },
+ { M_LD, O_C32, O_R }, { M_LD, O_C32, O_R }, { M_LD, O_C32, O_R }, { M_LD, O_C32, O_R },
+ { M_LD, O_C32, O_R }, { M_LD, O_C32, O_R }, { M_LD, O_C32, O_R }, { M_LD, O_C32, O_R },
+ { M_ADC, O_C32, O_R }, { M_ADC, O_C32, O_R }, { M_ADC, O_C32, O_R }, { M_ADC, O_C32, O_R },
+ { M_ADC, O_C32, O_R }, { M_ADC, O_C32, O_R }, { M_ADC, O_C32, O_R }, { M_ADC, O_C32, O_R },
+ { M_LD, O_R, O_C32 }, { M_LD, O_R, O_C32 }, { M_LD, O_R, O_C32 }, { M_LD, O_R, O_C32 },
+ { M_LD, O_R, O_C32 }, { M_LD, O_R, O_C32 }, { M_LD, O_R, O_C32 }, { M_LD, O_R, O_C32 },
+
+ /* A0 - BF */
+ { M_SUB, O_C32, O_R }, { M_SUB, O_C32, O_R }, { M_SUB, O_C32, O_R }, { M_SUB, O_C32, O_R },
+ { M_SUB, O_C32, O_R }, { M_SUB, O_C32, O_R }, { M_SUB, O_C32, O_R }, { M_SUB, O_C32, O_R },
+ { M_LD, O_R, O_I3 }, { M_LD, O_R, O_I3 }, { M_LD, O_R, O_I3 }, { M_LD, O_R, O_I3 },
+ { M_LD, O_R, O_I3 }, { M_LD, O_R, O_I3 }, { M_LD, O_R, O_I3 }, { M_LD, O_R, O_I3 },
+ { M_SBC, O_C32, O_R }, { M_SBC, O_C32, O_R }, { M_SBC, O_C32, O_R }, { M_SBC, O_C32, O_R },
+ { M_SBC, O_C32, O_R }, { M_SBC, O_C32, O_R }, { M_SBC, O_C32, O_R }, { M_SBC, O_C32, O_R },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* C0 - DF */
+ { M_AND, O_C32, O_R }, { M_AND, O_C32, O_R }, { M_AND, O_C32, O_R }, { M_AND, O_C32, O_R },
+ { M_AND, O_C32, O_R }, { M_AND, O_C32, O_R }, { M_AND, O_C32, O_R }, { M_AND, O_C32, O_R },
+ { M_ADD, O_R, O_I32 }, { M_ADC, O_R, O_I32 }, { M_SUB, O_R, O_I32 }, { M_SBC, O_R, O_I32 },
+ { M_AND, O_R, O_I32 }, { M_XOR, O_R, O_I32 }, { M_OR, O_R, O_I32 }, { M_CP, O_R, O_I32 },
+ { M_XOR, O_C32, O_R }, { M_XOR, O_C32, O_R }, { M_XOR, O_C32, O_R }, { M_XOR, O_C32, O_R },
+ { M_XOR, O_C32, O_R }, { M_XOR, O_C32, O_R }, { M_XOR, O_C32, O_R }, { M_XOR, O_C32, O_R },
+ { M_CP, O_R, O_I3 }, { M_CP, O_R, O_I3 }, { M_CP, O_R, O_I3 }, { M_CP, O_R, O_I3 },
+ { M_CP, O_R, O_I3 }, { M_CP, O_R, O_I3 }, { M_CP, O_R, O_I3 }, { M_CP, O_R, O_I3 },
+
+ /* E0 - FF */
+ { M_OR, O_C32, O_R }, { M_OR, O_C32, O_R }, { M_OR, O_C32, O_R }, { M_OR, O_C32, O_R },
+ { M_OR, O_C32, O_R }, { M_OR, O_C32, O_R }, { M_OR, O_C32, O_R }, { M_OR, O_C32, O_R },
+ { M_RLC, O_I8, O_R }, { M_RRC, O_I8, O_R }, { M_RL, O_I8, O_R }, { M_RR, O_I8, O_R },
+ { M_SLA, O_I8, O_R }, { M_SRA, O_I8, O_R }, { M_SLL, O_I8, O_R }, { M_SRL, O_I8, O_R },
+ { M_CP, O_C32, O_R }, { M_CP, O_C32, O_R }, { M_CP, O_C32, O_R }, { M_CP, O_C32, O_R },
+ { M_CP, O_C32, O_R }, { M_CP, O_C32, O_R }, { M_CP, O_C32, O_R }, { M_CP, O_C32, O_R },
+ { M_RLC, O_A, O_R }, { M_RRC, O_A, O_R }, { M_RL, O_A, O_R }, { M_RR, O_A, O_R },
+ { M_SLA, O_A, O_R }, { M_SRA, O_A, O_R }, { M_SLL, O_A, O_R }, { M_SRL, O_A, O_R }
+};
+
+
+static const tlcs900inst mnemonic_f0[256] =
+{
+ /* 00 - 1F */
+ { M_LD, O_M, O_I8 }, { M_DB, O_NONE, O_NONE }, { M_LD, O_M, O_I16 }, { M_DB, O_NONE, O_NONE },
+ { M_POP, O_M, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_POPW, O_M, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_LD, O_M, O_M16 }, { M_DB, O_NONE, O_NONE }, { M_LDW, O_M, O_M16 }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 20 - 3F */
+ { M_LDA, O_C16, O_M }, { M_LDA, O_C16, O_M }, { M_LDA, O_C16, O_M }, { M_LDA, O_C16, O_M },
+ { M_LDA, O_C16, O_M }, { M_LDA, O_C16, O_M }, { M_LDA, O_C16, O_M }, { M_LDA, O_C16, O_M },
+ { M_ANDCF, O_A, O_M }, { M_ORCF, O_A, O_M }, { M_XORCF, O_A, O_M }, { M_LDCF, O_A, O_M },
+ { M_STCF, O_A, O_M }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_LDA, O_C32, O_M }, { M_LDA, O_C32, O_M }, { M_LDA, O_C32, O_M }, { M_LDA, O_C32, O_M },
+ { M_LDA, O_C32, O_M }, { M_LDA, O_C32, O_M }, { M_LDA, O_C32, O_M }, { M_LDA, O_C32, O_M },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 40 - 5F */
+ { M_LD, O_M, O_C8 }, { M_LD, O_M, O_C8 }, { M_LD, O_M, O_C8 }, { M_LD, O_M, O_C8 },
+ { M_LD, O_M, O_C8 }, { M_LD, O_M, O_C8 }, { M_LD, O_M, O_C8 }, { M_LD, O_M, O_C8 },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_LD, O_M, O_C16 }, { M_LD, O_M, O_C16 }, { M_LD, O_M, O_C16 }, { M_LD, O_M, O_C16 },
+ { M_LD, O_M, O_C16 }, { M_LD, O_M, O_C16 }, { M_LD, O_M, O_C16 }, { M_LD, O_M, O_C16 },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 60 - 7F */
+ { M_LD, O_M, O_C32 }, { M_LD, O_M, O_C32 }, { M_LD, O_M, O_C32 }, { M_LD, O_M, O_C32 },
+ { M_LD, O_M, O_C32 }, { M_LD, O_M, O_C32 }, { M_LD, O_M, O_C32 }, { M_LD, O_M, O_C32 },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 80 - 9F */
+ { M_ANDCF, O_I3, O_M }, { M_ANDCF, O_I3, O_M }, { M_ANDCF, O_I3, O_M }, { M_ANDCF, O_I3, O_M },
+ { M_ANDCF, O_I3, O_M }, { M_ANDCF, O_I3, O_M }, { M_ANDCF, O_I3, O_M }, { M_ANDCF, O_I3, O_M },
+ { M_ORCF, O_I3, O_M }, { M_ORCF, O_I3, O_M }, { M_ORCF, O_I3, O_M }, { M_ORCF, O_I3, O_M },
+ { M_ORCF, O_I3, O_M }, { M_ORCF, O_I3, O_M }, { M_ORCF, O_I3, O_M }, { M_ORCF, O_I3, O_M },
+ { M_XORCF, O_I3, O_M }, { M_XORCF, O_I3, O_M }, { M_XORCF, O_I3, O_M }, { M_XORCF, O_I3, O_M },
+ { M_XORCF, O_I3, O_M }, { M_XORCF, O_I3, O_M }, { M_XORCF, O_I3, O_M }, { M_XORCF, O_I3, O_M },
+ { M_LDCF, O_I3, O_M }, { M_LDCF, O_I3, O_M }, { M_LDCF, O_I3, O_M }, { M_LDCF, O_I3, O_M },
+ { M_LDCF, O_I3, O_M }, { M_LDCF, O_I3, O_M }, { M_LDCF, O_I3, O_M }, { M_LDCF, O_I3, O_M },
+
+ /* A0 - BF */
+ { M_STCF, O_I3, O_M }, { M_STCF, O_I3, O_M }, { M_STCF, O_I3, O_M }, { M_STCF, O_I3, O_M },
+ { M_STCF, O_I3, O_M }, { M_STCF, O_I3, O_M }, { M_STCF, O_I3, O_M }, { M_STCF, O_I3, O_M },
+ { M_TSET, O_I3, O_M }, { M_TSET, O_I3, O_M }, { M_TSET, O_I3, O_M }, { M_TSET, O_I3, O_M },
+ { M_TSET, O_I3, O_M }, { M_TSET, O_I3, O_M }, { M_TSET, O_I3, O_M }, { M_TSET, O_I3, O_M },
+ { M_RES, O_I3, O_M }, { M_RES, O_I3, O_M }, { M_RES, O_I3, O_M }, { M_RES, O_I3, O_M },
+ { M_RES, O_I3, O_M }, { M_RES, O_I3, O_M }, { M_RES, O_I3, O_M }, { M_RES, O_I3, O_M },
+ { M_SET, O_I3, O_M }, { M_SET, O_I3, O_M }, { M_SET, O_I3, O_M }, { M_SET, O_I3, O_M },
+ { M_SET, O_I3, O_M }, { M_SET, O_I3, O_M }, { M_SET, O_I3, O_M }, { M_SET, O_I3, O_M },
+
+ /* C0 - DF */
+ { M_CHG, O_I3, O_M }, { M_CHG, O_I3, O_M }, { M_CHG, O_I3, O_M }, { M_CHG, O_I3, O_M },
+ { M_CHG, O_I3, O_M }, { M_CHG, O_I3, O_M }, { M_CHG, O_I3, O_M }, { M_CHG, O_I3, O_M },
+ { M_BIT, O_I3, O_M }, { M_BIT, O_I3, O_M }, { M_BIT, O_I3, O_M }, { M_BIT, O_I3, O_M },
+ { M_BIT, O_I3, O_M }, { M_BIT, O_I3, O_M }, { M_BIT, O_I3, O_M }, { M_BIT, O_I3, O_M },
+ { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M },
+ { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M },
+ { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M },
+ { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M }, { M_JP, O_CC, O_M },
+
+ /* E0 - FF */
+ { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M },
+ { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M },
+ { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M },
+ { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M }, { M_CALL, O_CC, O_M },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }
+};
+
+
+static const tlcs900inst mnemonic[256] =
+{
+ /* 00 - 1F */
+ { M_NOP, O_NONE, O_NONE }, { M_NORMAL, O_NONE, O_NONE }, { M_PUSH, O_SR, O_NONE }, { M_POP, O_SR, O_NONE },
+ { M_MAX, O_NONE, O_NONE }, { M_HALT, O_NONE, O_NONE }, { M_EI, O_I8, O_NONE }, { M_RETI, O_NONE, O_NONE },
+ { M_LD, O_M8, O_I8 }, { M_PUSH, O_I8, O_NONE }, { M_LD, O_M8, O_I16 }, { M_PUSH, O_I16, O_NONE },
+ { M_INCF, O_NONE, O_NONE }, { M_DECF, O_NONE, O_NONE }, { M_RET, O_NONE, O_NONE }, { M_RETD, O_I16, O_NONE },
+ { M_RCF, O_NONE, O_NONE }, { M_SCF, O_NONE, O_NONE }, { M_CCF, O_NONE, O_NONE }, { M_ZCF, O_NONE, O_NONE },
+ { M_PUSH, O_A, O_NONE }, { M_POP, O_A, O_NONE }, { M_EX, O_F, O_F }, { M_LDF, O_I8, O_NONE },
+ { M_PUSH, O_F, O_NONE }, { M_POP, O_F, O_NONE }, { M_JP, O_I16, O_NONE }, { M_JP, O_I24, O_NONE },
+ { M_CALL, O_I16, O_NONE }, { M_CALL, O_I24, O_NONE }, { M_CALR, O_D16, O_NONE }, { M_DB, O_NONE, O_NONE },
+
+ /* 20 - 3F */
+ { M_LD, O_C8, O_I8 }, { M_LD, O_C8, O_I8 }, { M_LD, O_C8, O_I8 }, { M_LD, O_C8, O_I8 },
+ { M_LD, O_C8, O_I8 }, { M_LD, O_C8, O_I8 }, { M_LD, O_C8, O_I8 }, { M_LD, O_C8, O_I8 },
+ { M_PUSH, O_C16, O_NONE }, { M_PUSH, O_C16, O_NONE }, { M_PUSH, O_C16, O_NONE }, { M_PUSH, O_C16, O_NONE },
+ { M_PUSH, O_C16, O_NONE }, { M_PUSH, O_C16, O_NONE }, { M_PUSH, O_C16, O_NONE }, { M_PUSH, O_C16, O_NONE },
+ { M_LD, O_C16, O_I16 }, { M_LD, O_C16, O_I16 }, { M_LD, O_C16, O_I16 }, { M_LD, O_C16, O_I16 },
+ { M_LD, O_C16, O_I16 }, { M_LD, O_C16, O_I16 }, { M_LD, O_C16, O_I16 }, { M_LD, O_C16, O_I16 },
+ { M_PUSH, O_C32, O_NONE }, { M_PUSH, O_C32, O_NONE }, { M_PUSH, O_C32, O_NONE }, { M_PUSH, O_C32, O_NONE },
+ { M_PUSH, O_C32, O_NONE }, { M_PUSH, O_C32, O_NONE }, { M_PUSH, O_C32, O_NONE }, { M_PUSH, O_C32, O_NONE },
+
+ /* 40 - 5F */
+ { M_LD, O_C32, O_I32 }, { M_LD, O_C32, O_I32 }, { M_LD, O_C32, O_I32 }, { M_LD, O_C32, O_I32 },
+ { M_LD, O_C32, O_I32 }, { M_LD, O_C32, O_I32 }, { M_LD, O_C32, O_I32 }, { M_LD, O_C32, O_I32 },
+ { M_POP, O_C16, O_NONE }, { M_POP, O_C16, O_NONE }, { M_POP, O_C16, O_NONE }, { M_POP, O_C16, O_NONE },
+ { M_POP, O_C16, O_NONE }, { M_POP, O_C16, O_NONE }, { M_POP, O_C16, O_NONE }, { M_POP, O_C16, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE },
+ { M_POP, O_C32, O_NONE }, { M_POP, O_C32, O_NONE }, { M_POP, O_C32, O_NONE }, { M_POP, O_C32, O_NONE },
+ { M_POP, O_C32, O_NONE }, { M_POP, O_C32, O_NONE }, { M_POP, O_C32, O_NONE }, { M_POP, O_C32, O_NONE },
+
+ /* 60 - 7F */
+ { M_JR, O_CC, O_D8 }, { M_JR, O_CC, O_D8 }, { M_JR, O_CC, O_D8 }, { M_JR, O_CC, O_D8 },
+ { M_JR, O_CC, O_D8 }, { M_JR, O_CC, O_D8 }, { M_JR, O_CC, O_D8 }, { M_JR, O_CC, O_D8 },
+ { M_JR, O_CC, O_D8 }, { M_JR, O_CC, O_D8 }, { M_JR, O_CC, O_D8 }, { M_JR, O_CC, O_D8 },
+ { M_JR, O_CC, O_D8 }, { M_JR, O_CC, O_D8 }, { M_JR, O_CC, O_D8 }, { M_JR, O_CC, O_D8 },
+ { M_JRL, O_CC, O_D16 }, { M_JRL, O_CC, O_D16 }, { M_JRL, O_CC, O_D16 }, { M_JRL, O_CC, O_D16 },
+ { M_JRL, O_CC, O_D16 }, { M_JRL, O_CC, O_D16 }, { M_JRL, O_CC, O_D16 }, { M_JRL, O_CC, O_D16 },
+ { M_JRL, O_CC, O_D16 }, { M_JRL, O_CC, O_D16 }, { M_JRL, O_CC, O_D16 }, { M_JRL, O_CC, O_D16 },
+ { M_JRL, O_CC, O_D16 }, { M_JRL, O_CC, O_D16 }, { M_JRL, O_CC, O_D16 }, { M_JRL, O_CC, O_D16 },
+
+ /* 80 - 9F */
+ { M_80, O_NONE, O_NONE }, { M_80, O_NONE, O_NONE }, { M_80, O_NONE, O_NONE }, { M_80, O_NONE, O_NONE },
+ { M_80, O_NONE, O_NONE }, { M_80, O_NONE, O_NONE }, { M_80, O_NONE, O_NONE }, { M_80, O_NONE, O_NONE },
+ { M_88, O_NONE, O_NONE }, { M_88, O_NONE, O_NONE }, { M_88, O_NONE, O_NONE }, { M_88, O_NONE, O_NONE },
+ { M_88, O_NONE, O_NONE }, { M_88, O_NONE, O_NONE }, { M_88, O_NONE, O_NONE }, { M_88, O_NONE, O_NONE },
+ { M_90, O_NONE, O_NONE }, { M_90, O_NONE, O_NONE }, { M_90, O_NONE, O_NONE }, { M_90, O_NONE, O_NONE },
+ { M_90, O_NONE, O_NONE }, { M_90, O_NONE, O_NONE }, { M_90, O_NONE, O_NONE }, { M_90, O_NONE, O_NONE },
+ { M_98, O_NONE, O_NONE }, { M_98, O_NONE, O_NONE }, { M_98, O_NONE, O_NONE }, { M_98, O_NONE, O_NONE },
+ { M_98, O_NONE, O_NONE }, { M_98, O_NONE, O_NONE }, { M_98, O_NONE, O_NONE }, { M_98, O_NONE, O_NONE },
+
+ /* A0 - BF */
+ { M_A0, O_NONE, O_NONE }, { M_A0, O_NONE, O_NONE }, { M_A0, O_NONE, O_NONE }, { M_A0, O_NONE, O_NONE },
+ { M_A0, O_NONE, O_NONE }, { M_A0, O_NONE, O_NONE }, { M_A0, O_NONE, O_NONE }, { M_A0, O_NONE, O_NONE },
+ { M_A8, O_NONE, O_NONE }, { M_A8, O_NONE, O_NONE }, { M_A8, O_NONE, O_NONE }, { M_A8, O_NONE, O_NONE },
+ { M_A8, O_NONE, O_NONE }, { M_A8, O_NONE, O_NONE }, { M_A8, O_NONE, O_NONE }, { M_A8, O_NONE, O_NONE },
+ { M_B0, O_NONE, O_NONE }, { M_B0, O_NONE, O_NONE }, { M_B0, O_NONE, O_NONE }, { M_B0, O_NONE, O_NONE },
+ { M_B0, O_NONE, O_NONE }, { M_B0, O_NONE, O_NONE }, { M_B0, O_NONE, O_NONE }, { M_B0, O_NONE, O_NONE },
+ { M_B8, O_NONE, O_NONE }, { M_B8, O_NONE, O_NONE }, { M_B8, O_NONE, O_NONE }, { M_B8, O_NONE, O_NONE },
+ { M_B8, O_NONE, O_NONE }, { M_B8, O_NONE, O_NONE }, { M_B8, O_NONE, O_NONE }, { M_B8, O_NONE, O_NONE },
+
+ /* C0 - DF */
+ { M_C0, O_NONE, O_NONE }, { M_C0, O_NONE, O_NONE }, { M_C0, O_NONE, O_NONE }, { M_C0, O_NONE, O_NONE },
+ { M_C0, O_NONE, O_NONE }, { M_C0, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { oC8, O_NONE, O_NONE },
+ { oC8, O_NONE, O_NONE }, { oC8, O_NONE, O_NONE }, { oC8, O_NONE, O_NONE }, { oC8, O_NONE, O_NONE },
+ { oC8, O_NONE, O_NONE }, { oC8, O_NONE, O_NONE }, { oC8, O_NONE, O_NONE }, { oC8, O_NONE, O_NONE },
+ { M_D0, O_NONE, O_NONE }, { M_D0, O_NONE, O_NONE }, { M_D0, O_NONE, O_NONE }, { M_D0, O_NONE, O_NONE },
+ { M_D0, O_NONE, O_NONE }, { M_D0, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { oD8, O_NONE, O_NONE },
+ { oD8, O_NONE, O_NONE }, { oD8, O_NONE, O_NONE }, { oD8, O_NONE, O_NONE }, { oD8, O_NONE, O_NONE },
+ { oD8, O_NONE, O_NONE }, { oD8, O_NONE, O_NONE }, { oD8, O_NONE, O_NONE }, { oD8, O_NONE, O_NONE },
+
+ /* E0 - FF */
+ { M_E0, O_NONE, O_NONE }, { M_E0, O_NONE, O_NONE }, { M_E0, O_NONE, O_NONE }, { M_E0, O_NONE, O_NONE },
+ { M_E0, O_NONE, O_NONE }, { M_E0, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_E8, O_NONE, O_NONE },
+ { M_E8, O_NONE, O_NONE }, { M_E8, O_NONE, O_NONE }, { M_E8, O_NONE, O_NONE }, { M_E8, O_NONE, O_NONE },
+ { M_E8, O_NONE, O_NONE }, { M_E8, O_NONE, O_NONE }, { M_E8, O_NONE, O_NONE }, { M_E8, O_NONE, O_NONE },
+ { M_F0, O_NONE, O_NONE }, { M_F0, O_NONE, O_NONE }, { M_F0, O_NONE, O_NONE }, { M_F0, O_NONE, O_NONE },
+ { M_F0, O_NONE, O_NONE }, { M_F0, O_NONE, O_NONE }, { M_DB, O_NONE, O_NONE }, { M_LDX, O_NONE, O_NONE },
+ { M_SWI, O_I3, O_NONE }, { M_SWI, O_I3, O_NONE }, { M_SWI, O_I3, O_NONE }, { M_SWI, O_I3, O_NONE },
+ { M_SWI, O_I3, O_NONE }, { M_SWI, O_I3, O_NONE }, { M_SWI, O_I3, O_NONE }, { M_SWI, O_I3, O_NONE }
+};
+
+
+
+static const char *const s_reg8[8] = { "W", "A", "B", "C", "D", "E", "H", "L" };
+static const char *const s_reg16[8] = { "WA", "BC", "DE", "HL", "IX", "IY", "IZ", "SP" };
+static const char *const s_reg32[8] = { "XWA", "XBC", "XDE", "XHL", "XIX", "XIY", "XIZ", "XSP" };
+static const char *const s_mulreg16[8] = { "??", "WA", "??", "BC", "??", "DE", "??", "HL" };
+static const char *const s_allreg8[256] =
+{
+ "RA0" ,"RW0" ,"QA0" ,"QW0" ,"RC0" ,"RB0" ,"QC0" ,"QB0" ,"RE0" ,"RD0" ,"QE0" ,"QD0" ,"RL0" ,"RH0" ,"QL0" ,"QH0" ,
+ "RA1" ,"RW1" ,"QA1" ,"QW1" ,"RC1" ,"RB1" ,"QC1" ,"QB1" ,"RE1" ,"RD1" ,"QE1" ,"QD1" ,"RL1" ,"RH1" ,"QL1" ,"QH1" ,
+ "RA2" ,"RW2" ,"QA2" ,"QW2" ,"RC2" ,"RB2" ,"QC2" ,"QB2" ,"RE2" ,"RD2" ,"QE2" ,"QD2" ,"RL2" ,"RH2" ,"QL2" ,"QH2" ,
+ "RA3" ,"RW3" ,"QA3" ,"QW3" ,"RC3" ,"RB3" ,"QC3" ,"QB3" ,"RE3" ,"RD3" ,"QE3" ,"QD3" ,"RL3" ,"RH3" ,"QL3" ,"QH3" ,
+ "r40B","r41B","r42B","r43B","r44B","r45B","r46B","r47B","r48B","r49B","r4AB","r4BB","r4CB","r4DB","r4EB","r4FB",
+ "r50B","r51B","r52B","r53B","r54B","r55B","r56B","r57B","r58B","r59B","r5AB","r5BB","r5CB","r5DB","r5EB","r5FB",
+ "r60B","r61B","r62B","r63B","r64B","r65B","r66B","r67B","r68B","r69B","r6AB","r6BB","r6CB","r6DB","r6EB","r6FB",
+ "r70B","r71B","r72B","r73B","r74B","r75B","r76B","r77B","r78B","r79B","r7AB","r7BB","r7CB","r7DB","r7EB","r7FB",
+ "r80B","r81B","r82B","r83B","r84B","r85B","r86B","r87B","r88B","r89B","r8AB","r8BB","r8CB","r8DB","r8EB","r8FB",
+ "r90B","r91B","r92B","r93B","r94B","r95B","r96B","r97B","r98B","r99B","r9AB","r9BB","r9CB","r9DB","r9EB","r9FB",
+ "rA0B","rA1B","rA2B","rA3B","rA4B","rA5B","rA6B","rA7B","rA8B","rA9B","rAAB","rABB","rACB","rADB","rAEB","rAFB",
+ "rB0B","rB1B","rB2B","rB3B","rB4B","rB5B","rB6B","rB7B","rB8B","rB9B","rBAB","rBBB","rBCB","rBDB","rBEB","rBFB",
+ "rC0B","rC1B","rC2B","rC3B","rC4B","rC5B","rC6B","rC7B","rC8B","rC9B","rCAB","rCBB","rCCB","rCDB","rCEB","rCFB",
+ "RA-1","RW-1","QA-1","QW-1","RC-1","RB-1","QC-1","QB-1","RE-1","RD-1","QE-1","QD-1","RL-1","RH-1","QL-1","QH-1",
+ "A" ,"W" ,"QA" ,"QW" ,"C" ,"B" ,"QC" ,"QB" ,"E" ,"D" ,"QE" ,"QD" ,"L" ,"H" ,"QL" ,"QH" ,
+ "IXL" ,"IXH" ,"QIXL","QIXH","IYL" ,"IYH" ,"QIYL","QIYH","IZL" ,"IZH" ,"QIZL","QIZH","SPL" ,"SPH" ,"QSPL","QSPH",
+};
+
+
+static const char *const s_allreg16[256] =
+{
+ "RWA0","r01W","QWA0","r03W","RBC0","r05W","QBC0","r07W","RDE0","r09W","QDE0","r0BW","RHL0","r0DW","QHL0","r0FW",
+ "RWA1","r11W","QWA1","r13W","RBC1","r15W","QBC1","r17W","RDE1","r19W","QDE1","r1BW","RHL1","r1DW","QHL1","r1FW",
+ "RWA2","r21W","QWA2","r23W","RBC2","r25W","QBC2","r27W","RDE2","r29W","QDE2","r2BW","RHL2","r2DW","QHL2","r2FW",
+ "RWA3","r31W","QWA3","r33W","RBC3","r35W","QBC3","r37W","RDE3","r39W","QDE3","r3BW","RHL3","r3DW","QHL3","r3FW",
+ "r40W","r41W","r42W","r43W","r44W","r45W","r46W","r47W","r48W","r49W","r4AW","r4BW","r4CW","r4DW","r4EW","r4FW",
+ "r50W","r51W","r52W","r53W","r54W","r55W","r56W","r57W","r58W","r59W","r5AW","r5BW","r5CW","r5DW","r5EW","r5FW",
+ "r60W","r61W","r62W","r63W","r64W","r65W","r66W","r67W","r68W","r69W","r6AW","r6BW","r6CW","r6DW","r6EW","r6FW",
+ "r70W","r71W","r72W","r73W","r74W","r75W","r76W","r77W","r78W","r79W","r7AW","r7BW","r7CW","r7DW","r7EW","r7FW",
+ "r80W","r81W","r82W","r83W","r84W","r85W","r86W","r87W","r88W","r89W","r8AW","r8BW","r8CW","r8DW","r8EW","r8FW",
+ "r90W","r91W","r92W","r93W","r94W","r95W","r96W","r97W","r98W","r99W","r9AW","r9BW","r9CW","r9DW","r9EW","r9FW",
+ "rA0W","rA1W","rA2W","rA3W","rA4W","rA5W","rA6W","rA7W","rA8W","rA9W","rAAW","rABW","rACW","rADW","rAEW","rAFW",
+ "rB0W","rB1W","rB2W","rB3W","rB4W","rB5W","rB6W","rB7W","rB8W","rB9W","rBAW","rBBW","rBCW","rBDW","rBEW","rBFW",
+ "rC0W","rC1W","rC2W","rC3W","rC4W","rC5W","rC6W","rC7W","rC8W","rC9W","rCAW","rCBW","rCCW","rCDW","rCEW","rCFW",
+ "RWA-1","rD1W","QWA-1","rD3W","RBC-1","rD5W","QBC-1","rD7W","RDE-1","rD9W","QDE-1","rDBW","RHL-1","rDDW","QHL-1","rDFW",
+ "WA" ,"rE1W","QWA" ,"rE3W","BC" ,"rE5W","QBC" ,"rE7W","DE" ,"rE9W","QDE" ,"rEBW","HL" ,"rEDW","QHL" ,"rEFW",
+ "IX" ,"rF1W","QIX" ,"rF3W","IY" ,"rF5W","QIY" ,"rF7W","IZ" ,"rF9W","QIZ" ,"rFBW","SP" ,"rFDW","QSP" ,"rFFW",
+};
+
+
+static const char *const s_allreg32[256] =
+{
+ "XWA0","XWA0","XWA0","r03L","XBC0","XBC0","XBC0","r07L","XDE0","XDE0","XDE0","r0BL","XHL0","XHL0","XHL0","r0FL",
+ "XWA1","XWA1","XWA1","r13L","XBC1","XBC1","XBC1","r17L","XDE1","XDE1","XDE1","r1BL","XHL1","XHL1","XHL1","r1FL",
+ "XWA2","XWA2","XWA2","r23L","XBC2","XBC2","XBC2","r27L","XDE2","XDE2","XDE2","r2BL","XHL2","XHL2","XHL2","r2FL",
+ "XWA3","XWA3","XWA3","r33L","XBC3","XBC3","XBC3","r37L","XDE3","XDE3","XDE3","r3BL","XHL3","XHL3","XHL3","r3FL",
+ "r40L","r41L","r42L","r43L","r44L","r45L","r46L","r47L","r48L","r49L","r4AL","r4BL","r4CL","r4DL","r4EL","r4FL",
+ "r50L","r51L","r52L","r53L","r54L","r55L","r56L","r57L","r58L","r59L","r5AL","r5BL","r5CL","r5DL","r5EL","r5FL",
+ "r60L","r61L","r62L","r63L","r64L","r65L","r66L","r67L","r68L","r69L","r6AL","r6BL","r6CL","r6DL","r6EL","r6FL",
+ "r70L","r71L","r72L","r73L","r74L","r75L","r76L","r77L","r78L","r79L","r7AL","r7BL","r7CL","r7DL","r7EL","r7FL",
+ "r80L","r81L","r82L","r83L","r84L","r85L","r86L","r87L","r88L","r89L","r8AL","r8BL","r8CL","r8DL","r8EL","r8FL",
+ "r90L","r91L","r92L","r93L","r94L","r95L","r96L","r97L","r98L","r99L","r9AL","r9BL","r9CL","r9DL","r9EL","r9FL",
+ "rA0L","rA1L","rA2L","rA3L","rA4L","rA5L","rA6L","rA7L","rA8L","rA9L","rAAL","rABL","rACL","rADL","rAEL","rAFL",
+ "rB0L","rB1L","rB2L","rB3L","rB4L","rB5L","rB6L","rB7L","rB8L","rB9L","rBAL","rBBL","rBCL","rBDL","rBEL","rBFL",
+ "rC0L","rC1L","rC2L","rC3L","rC4L","rC5L","rC6L","rC7L","rC8L","rC9L","rCAL","rCBL","rCCL","rCDL","rCEL","rCFL",
+ "XWA-1","XWA-1","XWA-1","rD3L","XBC-1","XBC-1","XBC-1","rD7L","XDE-1","XDE-1","XDE-1","rDBL","XHL-1","XHL-1","XHL-1","rDFL",
+ "XWA" ,"XWA" ,"XWA" ,"rE3L","XBC" ,"XBC", "XBC" ,"rE7L","XDE" ,"XDE" ,"XDE" ,"rEDL","XHL" ,"XHL" ,"XHL" ,"rEFL",
+ "XIX" ,"XIX" ,"XIX" ,"rF3L","XIY" ,"XIY" ,"XIY" ,"rF7L","XIZ" ,"XIZ" ,"XIZ" ,"rFBL","XSP" ,"XSP" ,"XSP" ,"rFFL",
+};
+
+
+static const char *const s_cond[16] =
+{
+ "F","LT","LE","ULE","PE/OV","M/MI","Z","C","T","GE","GT","UGT","PO/NOV","P/PL","NZ","NC"
+};
+
+
+CPU_DISASSEMBLE( tlcs900 )
+{
+ const tlcs900inst *dasm;
+ char *dst = buffer;
+ char buf[32];
+ UINT8 op, op1;
+ UINT32 imm;
+ int flags = 0;
+ int pos = 0;
+
+ op = oprom[ pos++ ];
+
+ dasm = &mnemonic[ op ];
+
+ /* Check for extended addressing modes */
+ switch( dasm->mnemonic )
+ {
+ default:
+ break;
+ case M_80:
+ sprintf( buf, "%s", s_reg32[op & 0x07] );
+ op = oprom[ pos++ ];
+ dasm = &mnemonic_80[ op ];
+ break;
+
+ case M_88:
+ imm = oprom[ pos++ ];
+ sprintf( buf, "%s+0x%02x", s_reg32[op & 0x07], imm );
+ op = oprom[ pos++ ];
+ dasm = &mnemonic_88[ op ];
+ break;
+
+ case M_90:
+ sprintf( buf, "%s", s_reg32[op & 0x07] );
+ op = oprom[ pos++ ];
+ dasm = &mnemonic_90[ op ];
+ break;
+
+ case M_98:
+ imm = oprom[ pos++ ];
+ sprintf( buf, "%s+0x%02x", s_reg32[op & 0x07], imm );
+ op = oprom[ pos++ ];
+ dasm = &mnemonic_98[ op ];
+ break;
+
+ case M_A0:
+ sprintf( buf, "%s", s_reg32[op & 0x07] );
+ op = oprom[ pos++ ];
+ dasm = &mnemonic_a0[ op ];
+ break;
+
+ case M_A8:
+ imm = oprom[ pos++ ];
+ sprintf( buf, "%s+0x%02x", s_reg32[op & 0x07], imm );
+ op = oprom[ pos++ ];
+ dasm = &mnemonic_a0[ op ];
+ break;
+
+ case M_B0:
+ sprintf( buf, "%s", s_reg32[op & 0x07] );
+ op = oprom[ pos++ ];
+ dasm = &mnemonic_b0[ op ];
+ break;
+
+ case M_B8:
+ imm = oprom[ pos++ ];
+ sprintf( buf, "%s+0x%02x", s_reg32[op & 0x07], imm );
+ op = oprom[ pos++ ];
+ dasm = &mnemonic_b8[ op ];
+ break;
+
+ case M_C0:
+ switch( op & 0x07 )
+ {
+ case 0x00: /* 0xC0 */
+ imm = oprom[ pos++ ];
+ sprintf( buf, "0x%02x", imm );
+ break;
+
+ case 0x01: /* 0xC1 */
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ sprintf( buf, "0x%04x", imm );
+ break;
+
+ case 0x02: /* 0xC2 */
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ imm = imm | ( oprom[ pos++ ] << 16 );
+ sprintf( buf, "0x%06x", imm );
+ break;
+
+ case 0x03: /* 0xC3 */
+ imm = oprom[ pos++ ];
+ switch( imm & 0x03 )
+ {
+ case 0x00:
+ sprintf( buf, "%s", s_allreg32[imm] );
+ break;
+
+ case 0x01:
+ op = imm;
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ sprintf( buf, "%s+0x%04x", s_allreg32[op], imm );
+ break;
+
+ case 0x02:
+ sprintf( buf, "unknown" );
+ break;
+
+ case 0x03:
+ switch( imm )
+ {
+ case 0x03:
+ op = oprom[ pos++ ];
+ op1 = oprom[ pos++ ];
+ sprintf( buf, "%s+%s", s_allreg32[op], s_allreg8[op1] );
+ break;
+
+ case 0x07:
+ op = oprom[ pos++ ];
+ op1 = oprom[ pos++ ];
+ sprintf( buf, "%s+%s", s_allreg32[op], s_allreg16[op1] );
+ break;
+
+ case 0x13:
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ sprintf( buf, "0x%06x", pc + pos + (INT16)imm );
+ break;
+ }
+ break;
+ }
+ break;
+
+ case 0x04: /* 0xC4 */
+ imm = oprom[ pos++ ];
+ sprintf( buf, "-%s", s_allreg32[imm] );
+ break;
+
+ case 0x05: /* 0xC5 */
+ imm = oprom[ pos++ ];
+ sprintf( buf, "%s+", s_allreg32[imm] );
+ break;
+ }
+ op = oprom[ pos++ ];
+ dasm = &mnemonic_c0[ op ];
+ break;
+
+ case oC8:
+ if ( op & 0x08 )
+ {
+ sprintf( buf, "%s", s_reg8[ op & 0x07 ] );
+ }
+ else
+ {
+ imm = oprom[ pos++ ];
+ sprintf( buf, "%s", s_allreg8[imm] );
+ }
+ op = oprom[ pos++ ];
+ dasm = &mnemonic_c8[ op ];
+ break;
+
+ case M_D0:
+ switch( op & 0x07 )
+ {
+ case 0x00: /* 0xD0 */
+ imm = oprom[ pos++ ];
+ sprintf( buf, "0x%02x", imm );
+ break;
+
+ case 0x01: /* 0xD1 */
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ sprintf( buf, "0x%04x", imm );
+ break;
+
+ case 0x02: /* 0xD2 */
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ imm = imm | ( oprom[ pos++ ] << 16 );
+ sprintf( buf, "0x%06x", imm );
+ break;
+
+ case 0x03: /* 0xD3 */
+ imm = oprom[ pos++ ];
+ switch( imm & 0x03 )
+ {
+ case 0x00:
+ sprintf( buf, "%s", s_allreg32[imm] );
+ break;
+
+ case 0x01:
+ op = imm;
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ sprintf( buf, "%s+0x%04x", s_allreg32[op], imm );
+ break;
+
+ case 0x02:
+ sprintf( buf, "unknown" );
+ break;
+
+ case 0x03:
+ switch( imm )
+ {
+ case 0x03:
+ op = oprom[ pos++ ];
+ op1 = oprom[ pos++ ];
+ sprintf( buf, "%s+%s", s_allreg32[op], s_allreg8[op1] );
+ break;
+
+ case 0x07:
+ op = oprom[ pos++ ];
+ op1 = oprom[ pos++ ];
+ sprintf( buf, "%s+%s", s_allreg32[op], s_allreg16[op1] );
+ break;
+
+ case 0x13:
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ sprintf( buf, "0x%06x", pc + pos + (INT16)imm );
+ break;
+ }
+ break;
+ }
+ break;
+
+ case 0x04: /* 0xD4 */
+ imm = oprom[ pos++ ];
+ sprintf( buf, "-%s", s_allreg32[imm] );
+ break;
+
+ case 0x05: /* 0xD5 */
+ imm = oprom[ pos++ ];
+ sprintf( buf, "%s+", s_allreg32[imm] );
+ break;
+ }
+ op = oprom[ pos++ ];
+ dasm = &mnemonic_d0[ op ];
+ break;
+
+ case oD8:
+ if ( op & 0x08 )
+ {
+ sprintf( buf, "%s", s_reg16[ op & 0x07 ] );
+ }
+ else
+ {
+ imm = oprom[ pos++ ];
+ sprintf( buf, "%s", s_allreg16[imm] );
+ }
+
+ op = oprom[ pos++ ];
+ dasm = &mnemonic_d8[ op ];
+ break;
+
+ case M_E0:
+ switch( op & 0x07 )
+ {
+ case 0x00: /* 0xE0 */
+ imm = oprom[ pos++ ];
+ sprintf( buf, "0x%02x", imm );
+ break;
+
+ case 0x01: /* 0xE1 */
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ sprintf( buf, "0x%04x", imm );
+ break;
+
+ case 0x02: /* 0xE2 */
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ imm = imm | ( oprom[ pos++ ] << 16 );
+ sprintf( buf, "0x%06x", imm );
+ break;
+
+ case 0x03: /* 0xE3 */
+ imm = oprom[ pos++ ];
+ switch( imm & 0x03 )
+ {
+ case 0x00:
+ sprintf( buf, "%s", s_allreg32[imm] );
+ break;
+
+ case 0x01:
+ op = imm;
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ sprintf( buf, "%s+0x%04x", s_allreg32[op], imm );
+ break;
+
+ case 0x02:
+ sprintf( buf, "unknown" );
+ break;
+
+ case 0x03:
+ switch( imm )
+ {
+ case 0x03:
+ op = oprom[ pos++ ];
+ op1 = oprom[ pos++ ];
+ sprintf( buf, "%s+%s", s_allreg32[op], s_allreg8[op1] );
+ break;
+
+ case 0x07:
+ op = oprom[ pos++ ];
+ op1 = oprom[ pos++ ];
+ sprintf( buf, "%s+%s", s_allreg32[op], s_allreg16[op1] );
+ break;
+
+ case 0x13:
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ sprintf( buf, "0x%06x", pc + pos + (INT16)imm );
+ break;
+ }
+ break;
+ }
+ break;
+
+ case 0x04: /* 0xE4 */
+ imm = oprom[ pos++ ];
+ sprintf( buf, "-%s", s_allreg32[imm] );
+ break;
+
+ case 0x05: /* 0xE5 */
+ imm = oprom[ pos++ ];
+ sprintf( buf, "%s+", s_allreg32[imm] );
+ break;
+ }
+ op = oprom[ pos++ ];
+ dasm = &mnemonic_e0[ op ];
+ break;
+
+ case M_E8:
+ if ( op & 0x08 )
+ {
+ sprintf( buf, "%s", s_reg32[ op & 0x07 ] );
+ }
+ else
+ {
+ imm = oprom[ pos++ ];
+ sprintf( buf, "%s", s_allreg32[imm] );
+ }
+ op = oprom[ pos++ ];
+ dasm = &mnemonic_e8[ op ];
+ break;
+
+ case M_F0:
+ switch( op & 0x07 )
+ {
+ case 0x00: /* 0xF0 */
+ imm = oprom[ pos++ ];
+ sprintf( buf, "0x%02x", imm );
+ break;
+
+ case 0x01: /* 0xF1 */
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ sprintf( buf, "0x%04x", imm );
+ break;
+
+ case 0x02: /* 0xF2 */
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ imm = imm | ( oprom[ pos++ ] << 16 );
+ sprintf( buf, "0x%06x", imm );
+ break;
+
+ case 0x03: /* 0xF3 */
+ imm = oprom[ pos++ ];
+ switch( imm & 0x03 )
+ {
+ case 0x00:
+ sprintf( buf, "%s", s_allreg32[imm] );
+ break;
+
+ case 0x01:
+ op = imm;
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ sprintf( buf, "%s+0x%04x", s_allreg32[op], imm );
+ break;
+
+ case 0x02:
+ sprintf( buf, "unknown" );
+ break;
+
+ case 0x03:
+ switch( imm )
+ {
+ case 0x03:
+ op = oprom[ pos++ ];
+ op1 = oprom[ pos++ ];
+ sprintf( buf, "%s+%s", s_allreg32[op], s_allreg8[op1] );
+ break;
+
+ case 0x07:
+ op = oprom[ pos++ ];
+ op1 = oprom[ pos++ ];
+ sprintf( buf, "%s+%s", s_allreg32[op], s_allreg16[op1] );
+ break;
+
+ case 0x13:
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ sprintf( buf, "0x%06x", pc + pos + (INT16)imm );
+ break;
+ }
+ break;
+ }
+ break;
+
+ case 0x04: /* 0xF4 */
+ imm = oprom[ pos++ ];
+ sprintf( buf, "-%s", s_allreg32[imm] );
+ break;
+
+ case 0x05: /* 0xF5 */
+ imm = oprom[ pos++ ];
+ sprintf( buf, "%s+", s_allreg32[imm] );
+ break;
+ }
+ op = oprom[ pos++ ];
+ dasm = &mnemonic_f0[ op ];
+ break;
+ }
+
+ dst += sprintf( dst, "%s", s_mnemonic[ dasm->mnemonic ] );
+
+ switch( dasm->mnemonic )
+ {
+ default:
+ /* maybe assert */
+ break;
+ case M_CALL:
+ case M_CALR:
+ flags = DASMFLAG_STEP_OVER;
+ break;
+ case M_RET:
+ case M_RETD:
+ case M_RETI:
+ flags = DASMFLAG_STEP_OUT;
+ break;
+ }
+
+ switch( dasm->operand1 )
+ {
+ case O_NONE:
+ break;
+
+ case O_A:
+ dst += sprintf( dst, " A" );
+ break;
+
+ case O_C8:
+ dst += sprintf( dst, " %s", s_reg8[op & 0x07] );
+ break;
+
+ case O_C16:
+ dst += sprintf( dst, " %s", s_reg16[op & 0x07] );
+ break;
+
+ case O_C32:
+ dst += sprintf( dst, " %s", s_reg32[op & 0x07] );
+ break;
+
+ case O_MC16:
+ dst += sprintf( dst, " %s", s_mulreg16[op & 0x07] );
+ break;
+
+ case O_CC:
+ dst += sprintf( dst, " %s", s_cond[op & 0x0F] );
+ break;
+
+ case O_CR8:
+ imm = oprom[ pos++ ];
+ switch( imm )
+ {
+ case 0x22:
+ dst += sprintf( dst, " DMAM0" );
+ break;
+ case 0x26:
+ dst += sprintf( dst, " DMAM1" );
+ break;
+ case 0x2a:
+ dst += sprintf( dst, " DMAM2" );
+ break;
+ case 0x2e:
+ dst += sprintf( dst, " DMAM3" );
+ break;
+ default:
+ dst += sprintf( dst, " unknown" );
+ break;
+ }
+ break;
+
+ case O_CR16:
+ imm = oprom[ pos++ ];
+ switch( imm )
+ {
+ case 0x20:
+ dst += sprintf( dst, " DMAC0" );
+ break;
+ case 0x24:
+ dst += sprintf( dst, " DMAC1" );
+ break;
+ case 0x28:
+ dst += sprintf( dst, " DMAC2" );
+ break;
+ case 0x2c:
+ dst += sprintf( dst, " DMAC3" );
+ break;
+ default:
+ dst += sprintf( dst, " unknown" );
+ break;
+ }
+ break;
+
+ case O_CR32:
+ imm = oprom[ pos++ ];
+ switch( imm )
+ {
+ case 0x00:
+ dst += sprintf( dst, " DMAS0" );
+ break;
+ case 0x04:
+ dst += sprintf( dst, " DMAS1" );
+ break;
+ case 0x08:
+ dst += sprintf( dst, " DMAS2" );
+ break;
+ case 0x0c:
+ dst += sprintf( dst, " DMAS3" );
+ break;
+ case 0x10:
+ dst += sprintf( dst, " DMAD0" );
+ break;
+ case 0x14:
+ dst += sprintf( dst, " DMAD1" );
+ break;
+ case 0x18:
+ dst += sprintf( dst, " DMAD2" );
+ break;
+ case 0x1c:
+ dst += sprintf( dst, " DMAD3" );
+ break;
+ default:
+ dst += sprintf( dst, " unknown" );
+ break;
+ }
+ break;
+
+ case O_D8:
+ imm = oprom[ pos++ ];
+ dst += sprintf( dst, " 0x%06x", ( pc + pos + (INT8)imm ) & 0xFFFFFF );
+ break;
+
+ case O_D16:
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ dst += sprintf( dst, " 0x%06x", ( pc + pos + (INT16)imm ) & 0xFFFFFF );
+ break;
+
+ case O_F:
+ dst += sprintf( dst, " F" );
+ break;
+
+ case O_I3:
+ dst += sprintf( dst, " %d", op & 0x07 );
+ break;
+
+ case O_I8:
+ imm = oprom[ pos++ ];
+ dst += sprintf( dst, " 0x%02x", imm );
+ break;
+
+ case O_I16:
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ dst += sprintf( dst, " 0x%04x", imm );
+ break;
+
+ case O_I24:
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ imm = imm | ( oprom[ pos++ ] << 16 );
+ dst += sprintf( dst, " 0x%06x", imm );
+ break;
+
+ case O_I32:
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ imm = imm | ( oprom[ pos++ ] << 16 );
+ imm = imm | ( oprom[ pos++ ] << 24 );
+ dst += sprintf( dst, "0x%08x", imm );
+ break;
+
+ case O_M:
+ switch( dasm->mnemonic )
+ {
+ case M_CALL:
+ case M_JP:
+ case M_LDA:
+ dst += sprintf( dst, " %s", buf );
+ break;
+ default:
+ dst += sprintf( dst, " (%s)", buf );
+ break;
+ }
+ break;
+
+ case O_M8:
+ imm = oprom[ pos++ ];
+ dst += sprintf( dst, " (0x%02x)", imm );
+ break;
+
+ case O_M16:
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ dst += sprintf( dst, " (0x%04x)", imm );
+ break;
+
+ case O_R:
+ dst += sprintf( dst, " %s", buf );
+ break;
+
+ case O_SR:
+ dst += sprintf( dst, " SR" );
+ break;
+ }
+
+ switch( dasm->operand2 )
+ {
+ case O_NONE:
+ break;
+
+ case O_A:
+ dst += sprintf( dst, ",A" );
+ break;
+
+ case O_C8:
+ dst += sprintf( dst, ",%s", s_reg8[op & 0x07] );
+ break;
+
+ case O_C16:
+ dst += sprintf( dst, ",%s", s_reg16[op & 0x07] );
+ break;
+
+ case O_C32:
+ dst += sprintf( dst, ",%s", s_reg32[op & 0x07] );
+ break;
+
+ case O_MC16:
+ dst += sprintf( dst, ",%s", s_mulreg16[op & 0x07] );
+ break;
+
+ case O_CC:
+ dst += sprintf( dst, ",%s", s_cond[op & 0x0F] );
+ break;
+
+ case O_CR8:
+ imm = oprom[ pos++ ];
+ switch( imm )
+ {
+ case 0x22:
+ dst += sprintf( dst, ",DMAM0" );
+ break;
+ case 0x26:
+ dst += sprintf( dst, ",DMAM1" );
+ break;
+ case 0x2a:
+ dst += sprintf( dst, ",DMAM2" );
+ break;
+ case 0x2e:
+ dst += sprintf( dst, ",DMAM3" );
+ break;
+ default:
+ dst += sprintf( dst, ",unknown" );
+ break;
+ }
+ break;
+
+ case O_CR16:
+ imm = oprom[ pos++ ];
+ switch( imm )
+ {
+ case 0x20:
+ dst += sprintf( dst, ",DMAC0" );
+ break;
+ case 0x24:
+ dst += sprintf( dst, ",DMAC1" );
+ break;
+ case 0x28:
+ dst += sprintf( dst, ",DMAC2" );
+ break;
+ case 0x2c:
+ dst += sprintf( dst, ",DMAC3" );
+ break;
+ default:
+ dst += sprintf( dst, ",unknown" );
+ break;
+ }
+ break;
+
+ case O_CR32:
+ imm = oprom[ pos++ ];
+ switch( imm )
+ {
+ case 0x00:
+ dst += sprintf( dst, ",DMAS0" );
+ break;
+ case 0x04:
+ dst += sprintf( dst, ",DMAS1" );
+ break;
+ case 0x08:
+ dst += sprintf( dst, ",DMAS2" );
+ break;
+ case 0x0c:
+ dst += sprintf( dst, ",DMAS3" );
+ break;
+ case 0x10:
+ dst += sprintf( dst, ",DMAD0" );
+ break;
+ case 0x14:
+ dst += sprintf( dst, ",DMAD1" );
+ break;
+ case 0x18:
+ dst += sprintf( dst, ",DMAD2" );
+ break;
+ case 0x1c:
+ dst += sprintf( dst, ",DMAD3" );
+ break;
+ default:
+ dst += sprintf( dst, ",unknown" );
+ break;
+ }
+ break;
+
+ case O_D8:
+ imm = oprom[ pos++ ];
+ dst += sprintf( dst, ",0x%06x", ( pc + pos + (INT8)imm ) & 0xFFFFFF );
+ break;
+
+ case O_D16:
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ dst += sprintf( dst, ",0x%06x", ( pc + pos + (INT16)imm ) & 0xFFFFFF );
+ break;
+
+ case O_F:
+ dst += sprintf( dst, ",F'" );
+ break;
+
+ case O_I3:
+ dst += sprintf( dst, ",%d", op & 0x07 );
+ break;
+
+ case O_I8:
+ imm = oprom[ pos++ ];
+ dst += sprintf( dst, ",0x%02x", imm );
+ break;
+
+ case O_I16:
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ dst += sprintf( dst, ",0x%04x", imm );
+ break;
+
+ case O_I24:
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ imm = imm | ( oprom[ pos++ ] << 16 );
+ dst += sprintf( dst, ",0x%06x", imm );
+ break;
+
+ case O_I32:
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ imm = imm | ( oprom[ pos++ ] << 16 );
+ imm = imm | ( oprom[ pos++ ] << 24 );
+ dst += sprintf( dst, ",0x%08x", imm );
+ break;
+
+ case O_M:
+ switch( dasm->mnemonic )
+ {
+ case M_CALL:
+ case M_JP:
+ case M_LDA:
+ dst += sprintf( dst, ",%s", buf );
+ break;
+ default:
+ dst += sprintf( dst, ",(%s)", buf );
+ break;
+ }
+ break;
+
+ case O_M8:
+ imm = oprom[ pos++ ];
+ dst += sprintf( dst, ",(0x%02x)", imm );
+ break;
+
+ case O_M16:
+ imm = oprom[ pos++ ];
+ imm = imm | ( oprom[ pos++ ] << 8 );
+ dst += sprintf( dst, ",(0x%04x)", imm );
+ break;
+
+ case O_R:
+ dst += sprintf( dst, ",%s", buf );
+ break;
+
+ case O_SR:
+ dst += sprintf( dst, ",SR" );
+ break;
+ }
+
+ return pos | flags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/tlcs900/tlcs900.c b/trunk/src/emu/cpu/tlcs900/tlcs900.c
new file mode 100644
index 00000000000..f43955c40c1
--- /dev/null
+++ b/trunk/src/emu/cpu/tlcs900/tlcs900.c
@@ -0,0 +1,1244 @@
+/*******************************************************************
+
+Toshiba TLCS-900/H emulation
+
+This code only supports the 900/H mode which is needed for Neogeo
+Pocket emulation. The 900 and 900/M modes are not supported yet.
+
+
+TODO:
+- review cycle counts
+- implement the remaining internal mcu features
+- add support for 900 and 900/M modes
+
+*******************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "tlcs900.h"
+
+typedef struct _tlcs900_state tlcs900_state;
+struct _tlcs900_state
+{
+ const tlcs900_interface *intf;
+
+ devcb_resolved_write8 to1;
+ devcb_resolved_write8 to3;
+
+ /* registers */
+ PAIR xwa[4];
+ PAIR xbc[4];
+ PAIR xde[4];
+ PAIR xhl[4];
+ PAIR xix;
+ PAIR xiy;
+ PAIR xiz;
+ PAIR xssp;
+ PAIR xnsp;
+ PAIR pc;
+ PAIR sr;
+ PAIR f2; /* f' */
+ /* DMA registers */
+ PAIR dmas[4];
+ PAIR dmad[4];
+ PAIR dmac[4];
+ PAIR dmam[4];
+
+ /* Internal timers, irqs, etc */
+ UINT8 reg[0x80];
+ UINT32 timer_pre;
+ UINT8 timer[6];
+ UINT8 tff1;
+ UINT8 tff3;
+ int timer_change[4];
+
+ /* Current state of input levels */
+ int level[TLCS900_NUM_INPUTS];
+ int check_irqs;
+ int ad_cycles_left;
+ int nmi_state;
+
+ /* used during execution */
+ PAIR dummy; /* for illegal register references */
+ UINT8 op;
+ PAIR ea1, ea2;
+ PAIR imm1, imm2;
+ int cycles;
+ UINT8 *p1_reg8, *p2_reg8;
+ UINT16 *p1_reg16, *p2_reg16;
+ UINT32 *p1_reg32, *p2_reg32;
+
+ int halted;
+ int icount;
+ int regbank;
+ device_irq_callback irqcallback;
+ legacy_cpu_device *device;
+ address_space *program;
+};
+
+
+/* Internal register defines */
+#define P1 0x01
+#define P1CR 0x02
+#define P2 0x06
+#define P2FC 0x09
+#define P5 0x0d
+#define P5CR 0x10
+#define P5FC 0x11
+#define P6 0x12
+#define P7 0x13
+#define P6FC 0x15
+#define P7CR 0x16
+#define P7FC 0x17
+#define P8 0x18
+#define P9 0x19
+#define P8CR 0x1a
+#define P8FC 0x1b
+#define PA 0x1e
+#define PB 0x1f
+#define TRUN 0x20
+#define TREG0 0x22
+#define TREG1 0x23
+#define T01MOD 0x24
+#define TFFCR 0x25
+#define TREG2 0x26
+#define TREG3 0x27
+#define T23MOD 0x28
+#define TRDC 0x29
+#define PACR 0x2c
+#define PAFC 0x2d
+#define PBCR 0x2e
+#define PBFC 0x2f
+#define TREG4L 0x30
+#define TREG4H 0x31
+#define TREG5L 0x32
+#define TREG5H 0x33
+#define CAP1L 0x34
+#define CAP1H 0x35
+#define CAP2L 0x36
+#define CAP2H 0x37
+#define T4MOD 0x38
+#define T4FFCR 0x39
+#define T45CR 0x3a
+#define MSAR0 0x3c
+#define MAMR0 0x3d
+#define MSAR1 0x3e
+#define MAMR1 0x3f
+#define TREG6L 0x40
+#define TREG6H 0x41
+#define TREG7L 0x42
+#define TREG7H 0x43
+#define CAP3L 0x44
+#define CAP3H 0x45
+#define CAP4L 0x46
+#define CAP4H 0x47
+#define T5MOD 0x48
+#define T5FFCR 0x49
+#define PG0REG 0x4c
+#define PG1REG 0x4d
+#define PG01CR 0x4e
+#define SC0BUF 0x50
+#define SC0CR 0x51
+#define SC0MOD 0x52
+#define BR0CR 0x53
+#define SC1BUF 0x54
+#define SC1CR 0x55
+#define SC1MOD 0x56
+#define BR1CR 0x57
+#define ODE 0x58
+#define DREFCR 0x5a
+#define DMEMCR 0x5b
+#define MSAR2 0x5c
+#define MAMR2 0x5d
+#define MSAR3 0x5e
+#define MAMR3 0x5f
+#define ADREG0L 0x60
+#define ADREG0H 0x61
+#define ADREG1L 0x62
+#define ADREG1H 0x63
+#define ADREG2L 0x64
+#define ADREG2H 0x65
+#define ADREG3L 0x66
+#define ADREG3H 0x67
+#define B0CS 0x68
+#define B1CS 0x69
+#define B2CS 0x6a
+#define B3CS 0x6b
+#define BEXCS 0x6c
+#define ADMOD 0x6d
+#define WDMOD 0x6e
+#define WDCR 0x6f
+#define INTE0AD 0x70
+#define INTE45 0x71
+#define INTE67 0x72
+#define INTET10 0x73
+#define INTET32 0x74
+#define INTET54 0x75
+#define INTET76 0x76
+#define INTES0 0x77
+#define INTES1 0x78
+#define INTETC10 0x79
+#define INTETC32 0x7a
+#define IIMC 0x7b
+#define DMA0V 0x7c
+#define DMA1V 0x7d
+#define DMA2V 0x7e
+#define DMA3V 0x7f
+
+
+/* Flag defines */
+#define FLAG_CF 0x01
+#define FLAG_NF 0x02
+#define FLAG_VF 0x04
+#define FLAG_HF 0x10
+#define FLAG_ZF 0x40
+#define FLAG_SF 0x80
+
+
+#define RDMEM(addr) cpustate->program->read_byte( addr )
+#define WRMEM(addr,data) cpustate->program->write_byte( addr, data )
+#define RDOP() RDMEM( cpustate->pc.d ); cpustate->pc.d++
+#define RDMEMW(addr) ( RDMEM(addr) | ( RDMEM(addr+1) << 8 ) )
+#define RDMEML(addr) ( RDMEMW(addr) | ( RDMEMW(addr+2) << 16 ) )
+#define WRMEMW(addr,data) { UINT16 dw = data; WRMEM(addr,dw & 0xff); WRMEM(addr+1,(dw >> 8 )); }
+#define WRMEML(addr,data) { UINT32 dl = data; WRMEMW(addr,dl); WRMEMW(addr+2,(dl >> 16)); }
+
+
+INLINE tlcs900_state *get_safe_token( device_t *device )
+{
+ assert( device != NULL );
+ assert( device->type() == TLCS900H );
+
+ return (tlcs900_state *) downcast<legacy_cpu_device *>(device)->token();
+}
+
+
+static CPU_INIT( tlcs900 )
+{
+ tlcs900_state *cpustate = get_safe_token(device);
+
+ cpustate->intf = (const tlcs900_interface *)device->static_config();
+ cpustate->irqcallback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space( AS_PROGRAM );
+
+ cpustate->to1.resolve(cpustate->intf->to1, *device );
+ cpustate->to3.resolve(cpustate->intf->to3, *device );
+
+ device->save_item( NAME(cpustate->xwa) );
+ device->save_item( NAME(cpustate->xbc) );
+ device->save_item( NAME(cpustate->xde) );
+ device->save_item( NAME(cpustate->xhl) );
+ device->save_item( NAME(cpustate->xix) );
+ device->save_item( NAME(cpustate->xiy) );
+ device->save_item( NAME(cpustate->xiz) );
+ device->save_item( NAME(cpustate->xssp) );
+ device->save_item( NAME(cpustate->xnsp) );
+ device->save_item( NAME(cpustate->pc) );
+ device->save_item( NAME(cpustate->sr) );
+ device->save_item( NAME(cpustate->f2) );
+ device->save_item( NAME(cpustate->dmas) );
+ device->save_item( NAME(cpustate->dmad) );
+ device->save_item( NAME(cpustate->dmac) );
+ device->save_item( NAME(cpustate->dmam) );
+ device->save_item( NAME(cpustate->reg) );
+ device->save_item( NAME(cpustate->timer_pre) );
+ device->save_item( NAME(cpustate->timer) );
+ device->save_item( NAME(cpustate->tff1) );
+ device->save_item( NAME(cpustate->tff3) );
+ device->save_item( NAME(cpustate->timer_change) );
+ device->save_item( NAME(cpustate->level) );
+ device->save_item( NAME(cpustate->check_irqs) );
+ device->save_item( NAME(cpustate->ad_cycles_left) );
+ device->save_item( NAME(cpustate->nmi_state) );
+}
+
+
+static CPU_RESET( tlcs900 )
+{
+ tlcs900_state *cpustate = get_safe_token(device);
+ int i;
+
+ cpustate->pc.b.l = RDMEM( 0xFFFF00 );
+ cpustate->pc.b.h = RDMEM( 0xFFFF01 );
+ cpustate->pc.b.h2 = RDMEM( 0xFFFF02 );
+ cpustate->pc.b.h3 = 0;
+ /* system mode, iff set to 111, max mode, register bank 0 */
+ cpustate->sr.d = 0xF800;
+ cpustate->regbank = 0;
+ cpustate->xssp.d = 0x0100;
+ cpustate->halted = 0;
+ cpustate->check_irqs = 0;
+ cpustate->ad_cycles_left = 0;
+ cpustate->nmi_state = CLEAR_LINE;
+ cpustate->timer_pre = 0;
+ cpustate->timer_change[0] = 0;
+ cpustate->timer_change[1] = 0;
+ cpustate->timer_change[2] = 0;
+ cpustate->timer_change[3] = 0;
+
+ cpustate->reg[P1] = 0x00;
+ cpustate->reg[P1CR] = 0x00;
+ cpustate->reg[P2] = 0xff;
+ cpustate->reg[P2FC] = 0x00;
+ cpustate->reg[P5] = 0x3d;
+ cpustate->reg[P5CR] = 0x00;
+ cpustate->reg[P5FC] = 0x00;
+ cpustate->reg[P6] = 0x3b;
+ cpustate->reg[P6FC] = 0x00;
+ cpustate->reg[P7] = 0xff;
+ cpustate->reg[P7CR] = 0x00;
+ cpustate->reg[P7FC] = 0x00;
+ cpustate->reg[P8] = 0x3f;
+ cpustate->reg[P8CR] = 0x00;
+ cpustate->reg[P8FC] = 0x00;
+ cpustate->reg[PA] = 0x0f;
+ cpustate->reg[PACR] = 0x00;
+ cpustate->reg[PAFC] = 0x00;
+ cpustate->reg[PB] = 0xff;
+ cpustate->reg[PBCR] = 0x00;
+ cpustate->reg[PBFC] = 0x00;
+ cpustate->reg[MSAR0] = 0xff;
+ cpustate->reg[MSAR1] = 0xff;
+ cpustate->reg[MSAR2] = 0xff;
+ cpustate->reg[MSAR3] = 0xff;
+ cpustate->reg[MAMR0] = 0xff;
+ cpustate->reg[MAMR1] = 0xff;
+ cpustate->reg[MAMR2] = 0xff;
+ cpustate->reg[MAMR3] = 0xff;
+ cpustate->reg[DREFCR] = 0x00;
+ cpustate->reg[DMEMCR] = 0x80;
+ cpustate->reg[T01MOD] = 0x00;
+ cpustate->reg[T23MOD] = 0x00;
+ cpustate->reg[TFFCR] = 0x00;
+ cpustate->reg[TRUN] = 0x00;
+ cpustate->reg[TRDC] = 0x00;
+ cpustate->reg[T4MOD] = 0x20;
+ cpustate->reg[T4FFCR] = 0x00;
+ cpustate->reg[T5MOD] = 0x20;
+ cpustate->reg[T5FFCR] = 0x00;
+ cpustate->reg[T45CR] = 0x00;
+ cpustate->reg[PG01CR] = 0x00;
+ cpustate->reg[PG0REG] = 0x00;
+ cpustate->reg[PG1REG] = 0x00;
+ cpustate->reg[SC0MOD] = 0x00;
+ cpustate->reg[SC0CR] = 0x00;
+ cpustate->reg[BR0CR] = 0x00;
+ cpustate->reg[SC1MOD] = 0x00;
+ cpustate->reg[SC1CR] = 0x00;
+ cpustate->reg[BR1CR] = 0x00;
+ cpustate->reg[P8FC] = 0x00;
+ cpustate->reg[ODE] = 0x00;
+ cpustate->reg[ADMOD] = 0x00;
+ cpustate->reg[ADREG0L] = 0x3f;
+ cpustate->reg[ADREG1L] = 0x3f;
+ cpustate->reg[ADREG2L] = 0x3f;
+ cpustate->reg[ADREG3L] = 0x3f;
+ cpustate->reg[WDMOD] = 0x80;
+
+ for ( i = 0; i < TLCS900_NUM_INPUTS; i++ )
+ {
+ cpustate->level[i] = CLEAR_LINE;
+ }
+}
+
+
+static CPU_EXIT( tlcs900 )
+{
+}
+
+
+#include "900tbl.c"
+
+
+#define NUM_MASKABLE_IRQS 22
+static const struct {
+ UINT8 reg;
+ UINT8 iff;
+ UINT8 vector;
+} irq_vector_map[NUM_MASKABLE_IRQS] =
+{
+ { INTETC32, 0x80, 0x80 }, /* INTTC3 */
+ { INTETC32, 0x08, 0x7c }, /* INTTC2 */
+ { INTETC10, 0x80, 0x78 }, /* INTTC1 */
+ { INTETC10, 0x08, 0x74 }, /* INTTC0 */
+ { INTE0AD, 0x80, 0x70 }, /* INTAD */
+ { INTES1, 0x80, 0x6c }, /* INTTX1 */
+ { INTES1, 0x08, 0x68 }, /* INTRX1 */
+ { INTES0, 0x80, 0x64 }, /* INTTX0 */
+ { INTES0, 0x08, 0x60 }, /* INTRX0 */
+ { INTET76, 0x80, 0x5c }, /* INTTR7 */
+ { INTET76, 0x08, 0x58 }, /* INTTR6 */
+ { INTET54, 0x80, 0x54 }, /* INTTR5 */
+ { INTET54, 0x08, 0x50 }, /* INTTR4 */
+ { INTET32, 0x80, 0x4c }, /* INTT3 */
+ { INTET32, 0x08, 0x48 }, /* INTT2 */
+ { INTET10, 0x80, 0x44 }, /* INTT1 */
+ { INTET10, 0x08, 0x40 }, /* INTT0 */
+ /* 0x3c - reserved */
+ { INTE67, 0x80, 0x38 }, /* INT7 */
+ { INTE67, 0x08, 0x34 }, /* INT6 */
+ { INTE45, 0x80, 0x30 }, /* INT5 */
+ { INTE45, 0x08, 0x2c }, /* INT4 */
+ { INTE0AD, 0x08, 0x28 } /* INT0 */
+};
+
+
+INLINE int tlcs900_process_hdma( tlcs900_state *cpustate, int channel )
+{
+ UINT8 vector = ( cpustate->reg[0x7c + channel] & 0x1f ) << 2;
+
+ /* Check if any HDMA actions should be performed */
+ if ( vector >= 0x28 && vector != 0x3C && vector < 0x74 )
+ {
+ int irq = 0;
+
+ while( irq < NUM_MASKABLE_IRQS && irq_vector_map[irq].vector != vector )
+ irq++;
+
+ /* Check if our interrupt flip-flop is set */
+ if ( irq < NUM_MASKABLE_IRQS && cpustate->reg[irq_vector_map[irq].reg] & irq_vector_map[irq].iff )
+ {
+ switch( cpustate->dmam[channel].b.l & 0x1f )
+ {
+ case 0x00:
+ WRMEM( cpustate->dmad[channel].d, RDMEM( cpustate->dmas[channel].d ) );
+ cpustate->dmad[channel].d += 1;
+ cpustate->cycles += 8;
+ break;
+ case 0x01:
+ WRMEMW( cpustate->dmad[channel].d, RDMEMW( cpustate->dmas[channel].d ) );
+ cpustate->dmad[channel].d += 2;
+ cpustate->cycles += 8;
+ break;
+ case 0x02:
+ WRMEML( cpustate->dmad[channel].d, RDMEML( cpustate->dmas[channel].d ) );
+ cpustate->dmad[channel].d += 4;
+ cpustate->cycles += 12;
+ break;
+ case 0x04:
+ WRMEM( cpustate->dmad[channel].d, RDMEM( cpustate->dmas[channel].d ) );
+ cpustate->dmad[channel].d -= 1;
+ cpustate->cycles += 8;
+ break;
+ case 0x05:
+ WRMEMW( cpustate->dmad[channel].d, RDMEMW( cpustate->dmas[channel].d ) );
+ cpustate->dmad[channel].d -= 2;
+ cpustate->cycles += 8;
+ break;
+ case 0x06:
+ WRMEML( cpustate->dmad[channel].d, RDMEML( cpustate->dmas[channel].d ) );
+ cpustate->dmad[channel].d -= 4;
+ cpustate->cycles += 12;
+ break;
+ case 0x08:
+ WRMEM( cpustate->dmad[channel].d, RDMEM( cpustate->dmas[channel].d ) );
+ cpustate->dmas[channel].d += 1;
+ cpustate->cycles += 8;
+ break;
+ case 0x09:
+ WRMEMW( cpustate->dmad[channel].d, RDMEMW( cpustate->dmas[channel].d ) );
+ cpustate->dmas[channel].d += 2;
+ cpustate->cycles += 8;
+ break;
+ case 0x0a:
+ WRMEML( cpustate->dmad[channel].d, RDMEML( cpustate->dmas[channel].d ) );
+ cpustate->dmas[channel].d += 4;
+ cpustate->cycles += 12;
+ break;
+ case 0x0c:
+ WRMEM( cpustate->dmad[channel].d, RDMEMW( cpustate->dmas[channel].d ) );
+ cpustate->dmas[channel].d -= 1;
+ cpustate->cycles += 8;
+ break;
+ case 0x0d:
+ WRMEMW( cpustate->dmad[channel].d, RDMEMW( cpustate->dmas[channel].d ) );
+ cpustate->dmas[channel].d -= 2;
+ cpustate->cycles += 8;
+ break;
+ case 0x0e:
+ WRMEML( cpustate->dmad[channel].d, RDMEML( cpustate->dmas[channel].d ) );
+ cpustate->dmas[channel].d -= 4;
+ cpustate->cycles += 12;
+ break;
+ case 0x10:
+ WRMEM( cpustate->dmad[channel].d, RDMEMW( cpustate->dmas[channel].d ) );
+ cpustate->cycles += 8;
+ break;
+ case 0x11:
+ WRMEMW( cpustate->dmad[channel].d, RDMEMW( cpustate->dmas[channel].d ) );
+ cpustate->cycles += 8;
+ break;
+ case 0x12:
+ WRMEML( cpustate->dmad[channel].d, RDMEML( cpustate->dmas[channel].d ) );
+ cpustate->cycles += 12;
+ break;
+ case 0x14:
+ cpustate->dmas[channel].d += 1;
+ cpustate->cycles += 5;
+ break;
+ }
+
+ cpustate->dmac[channel].w.l -= 1;
+
+ if ( cpustate->dmac[channel].w.l == 0 )
+ {
+ cpustate->reg[0x7c + channel] = 0;
+ switch( channel )
+ {
+ case 0:
+ cpustate->reg[INTETC10] |= 0x08;
+ break;
+ case 1:
+ cpustate->reg[INTETC10] |= 0x80;
+ break;
+ case 2:
+ cpustate->reg[INTETC32] |= 0x08;
+ break;
+ case 3:
+ cpustate->reg[INTETC32] |= 0x80;
+ break;
+ }
+ }
+
+ /* Clear the interrupt flip-flop */
+ cpustate->reg[irq_vector_map[irq].reg] &= ~irq_vector_map[irq].iff;
+
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+INLINE void tlcs900_check_hdma( tlcs900_state *cpustate )
+{
+ /* HDMA can only be performed if interrupts are allowed */
+ if ( ( cpustate->sr.b.h & 0x70 ) != 0x70 )
+ {
+ if ( ! tlcs900_process_hdma( cpustate, 0 ) )
+ {
+ if ( ! tlcs900_process_hdma( cpustate, 1 ) )
+ {
+ if ( ! tlcs900_process_hdma( cpustate, 2 ) )
+ {
+ tlcs900_process_hdma( cpustate, 3 );
+ }
+ }
+ }
+ }
+}
+
+
+INLINE void tlcs900_check_irqs( tlcs900_state *cpustate )
+{
+ int irq_vectors[9] = { -1, -1, -1, -1, -1, -1, -1, -1, -1 };
+ int level = 0;
+ int irq = -1;
+ int i;
+
+ /* Check for NMI */
+ if ( cpustate->nmi_state == ASSERT_LINE )
+ {
+ cpustate->xssp.d -= 4;
+ WRMEML( cpustate->xssp.d, cpustate->pc.d );
+ cpustate->xssp.d -= 2;
+ WRMEMW( cpustate->xssp.d, cpustate->sr.w.l );
+ cpustate->pc.d = RDMEML( 0xffff00 + 0x20 );
+ cpustate->cycles += 18;
+
+ cpustate->halted = 0;
+
+ cpustate->nmi_state = CLEAR_LINE;
+
+ return;
+ }
+
+ /* Check regular irqs */
+ for( i = 0; i < NUM_MASKABLE_IRQS; i++ )
+ {
+ if ( cpustate->reg[irq_vector_map[i].reg] & irq_vector_map[i].iff )
+ {
+ switch( irq_vector_map[i].iff )
+ {
+ case 0x80:
+ irq_vectors[ ( cpustate->reg[ irq_vector_map[i].reg ] >> 4 ) & 0x07 ] = i;
+ break;
+ case 0x08:
+ irq_vectors[ cpustate->reg[ irq_vector_map[i].reg ] & 0x07 ] = i;
+ break;
+ }
+ }
+ }
+
+ /* Check highest allowed priority irq */
+ for ( i = MAX( 1, ( ( cpustate->sr.b.h & 0x70 ) >> 4 ) ); i < 7; i++ )
+ {
+ if ( irq_vectors[i] >= 0 )
+ {
+ irq = irq_vectors[i];
+ level = i + 1;
+ }
+ }
+
+ /* Take irq */
+ if ( irq >= 0 )
+ {
+ UINT8 vector = irq_vector_map[irq].vector;
+
+ cpustate->xssp.d -= 4;
+ WRMEML( cpustate->xssp.d, cpustate->pc.d );
+ cpustate->xssp.d -= 2;
+ WRMEMW( cpustate->xssp.d, cpustate->sr.w.l );
+
+ /* Mask off any lower priority interrupts */
+ cpustate->sr.b.h = ( cpustate->sr.b.h & 0x8f ) | ( level << 4 );
+
+ cpustate->pc.d = RDMEML( 0xffff00 + vector );
+ cpustate->cycles += 18;
+
+ cpustate->halted = 0;
+
+ /* Clear taken IRQ */
+ cpustate->reg[ irq_vector_map[irq].reg ] &= ~ irq_vector_map[irq].iff;
+ }
+}
+
+
+INLINE void tlcs900_handle_ad( tlcs900_state *cpustate )
+{
+ if ( cpustate->ad_cycles_left > 0 )
+ {
+ cpustate->ad_cycles_left -= cpustate->cycles;
+ if ( cpustate->ad_cycles_left <= 0 )
+ {
+ /* Store A/D converted value */
+ switch( cpustate->reg[ADMOD] & 0x03 )
+ {
+ case 0x00: /* AN0 */
+ cpustate->reg[ADREG0L] |= 0xc0;
+ cpustate->reg[ADREG0H] = 0xff;
+ break;
+ case 0x01: /* AN1 */
+ case 0x02: /* AN2 */
+ case 0x03: /* AN3 */
+ break;
+ }
+
+ /* Clear BUSY flag, set END flag */
+ cpustate->reg[ADMOD] &= ~ 0x40;
+ cpustate->reg[ADMOD] |= 0x80;
+
+ cpustate->reg[INTE0AD] |= 0x80;
+ cpustate->check_irqs = 1;
+ }
+ }
+}
+
+
+enum ff_change
+{
+ FF_CLEAR,
+ FF_SET,
+ FF_INVERT
+};
+
+
+INLINE void tlcs900_change_tff( tlcs900_state *cpustate, int which, int change )
+{
+ switch( which )
+ {
+ case 1:
+ switch( change )
+ {
+ case FF_CLEAR:
+ cpustate->tff1 = 0;
+ break;
+ case FF_SET:
+ cpustate->tff1 = 1;
+ break;
+ case FF_INVERT:
+ cpustate->tff1 ^= 1;
+ break;
+ }
+ if ( !cpustate->to1.isnull() )
+ cpustate->to1(0, cpustate->tff1 );
+ break;
+
+ case 3:
+ switch( change )
+ {
+ case FF_CLEAR:
+ cpustate->tff3 = 0;
+ break;
+ case FF_SET:
+ cpustate->tff3 = 1;
+ break;
+ case FF_INVERT:
+ cpustate->tff3 ^= 1;
+ break;
+ }
+ if ( !cpustate->to3.isnull() )
+ cpustate->to3(0, cpustate->tff3 );
+ break;
+ }
+}
+
+
+INLINE void tlcs900_handle_timers( tlcs900_state *cpustate )
+{
+ UINT32 old_pre = cpustate->timer_pre;
+
+ /* Is the pre-scaler active */
+ if ( cpustate->reg[TRUN] & 0x80 )
+ cpustate->timer_pre += cpustate->cycles;
+
+ /* Timer 0 */
+ if ( cpustate->reg[TRUN] & 0x01 )
+ {
+ switch( cpustate->reg[T01MOD] & 0x03 )
+ {
+ case 0x00: /* TIO */
+ break;
+ case 0x01: /* T1 */
+ cpustate->timer_change[0] += ( cpustate->timer_pre >> 7 ) - ( old_pre >> 7 );
+ break;
+ case 0x02: /* T4 */
+ cpustate->timer_change[0] += ( cpustate->timer_pre >> 9 ) - ( old_pre >> 9 );
+ break;
+ case 0x03: /* T16 */
+ cpustate->timer_change[0] += ( cpustate->timer_pre >> 11 ) - ( old_pre >> 11 );
+ break;
+ }
+
+ for( ; cpustate->timer_change[0] > 0; cpustate->timer_change[0]-- )
+ {
+//printf("timer0 = %02x, TREG0 = %02x\n", cpustate->timer[0], cpustate->reg[TREG0] );
+ cpustate->timer[0] += 1;
+ if ( cpustate->timer[0] == cpustate->reg[TREG0] )
+ {
+ if ( ( cpustate->reg[T01MOD] & 0x0c ) == 0x00 )
+ {
+ cpustate->timer_change[1] += 1;
+ }
+
+ /* In 16bit timer mode the timer should not be reset */
+ if ( ( cpustate->reg[T01MOD] & 0xc0 ) != 0x40 )
+ {
+ cpustate->timer[0] = 0;
+ cpustate->reg[INTET10] |= 0x08;
+ }
+ }
+ }
+ }
+
+ /* Timer 1 */
+ if ( cpustate->reg[TRUN] & 0x02 )
+ {
+ switch( ( cpustate->reg[T01MOD] >> 2 ) & 0x03 )
+ {
+ case 0x00: /* TO0TRG */
+ break;
+ case 0x01: /* T1 */
+ cpustate->timer_change[1] += ( cpustate->timer_pre >> 7 ) - ( old_pre >> 7 );
+ break;
+ case 0x02: /* T16 */
+ cpustate->timer_change[1] += ( cpustate->timer_pre >> 11 ) - ( old_pre >> 11 );
+ break;
+ case 0x03: /* T256 */
+ cpustate->timer_change[1] += ( cpustate->timer_pre >> 15 ) - ( old_pre >> 15 );
+ break;
+ }
+
+ for( ; cpustate->timer_change[1] > 0; cpustate->timer_change[1]-- )
+ {
+ cpustate->timer[1] += 1;
+ if ( cpustate->timer[1] == cpustate->reg[TREG1] )
+ {
+ cpustate->timer[1] = 0;
+ cpustate->reg[INTET10] |= 0x80;
+
+ if ( cpustate->reg[TFFCR] & 0x02 )
+ {
+ tlcs900_change_tff( cpustate, 1, FF_INVERT );
+ }
+
+ /* In 16bit timer mode also reset timer 0 */
+ if ( ( cpustate->reg[T01MOD] & 0xc0 ) == 0x40 )
+ {
+ cpustate->timer[0] = 0;
+ }
+ }
+ }
+ }
+
+ /* Timer 2 */
+ if ( cpustate->reg[TRUN] & 0x04 )
+ {
+ switch( cpustate->reg[T23MOD] & 0x03 )
+ {
+ case 0x00: /* invalid */
+ case 0x01: /* T1 */
+ cpustate->timer_change[2] += ( cpustate->timer_pre >> 7 ) - ( old_pre >> 7 );
+ break;
+ case 0x02: /* T4 */
+ cpustate->timer_change[2] += ( cpustate->timer_pre >> 9 ) - ( old_pre >> 9 );
+ break;
+ case 0x03: /* T16 */
+ cpustate->timer_change[2] += ( cpustate->timer_pre >> 11 ) - ( old_pre >> 11 );
+ break;
+ }
+
+ for( ; cpustate->timer_change[2] > 0; cpustate->timer_change[2]-- )
+ {
+ cpustate->timer[2] += 1;
+ if ( cpustate->timer[2] == cpustate->reg[TREG2] )
+ {
+ if ( ( cpustate->reg[T23MOD] & 0x0c ) == 0x00 )
+ {
+ cpustate->timer_change[3] += 1;
+ }
+
+ /* In 16bit timer mode the timer should not be reset */
+ if ( ( cpustate->reg[T23MOD] & 0xc0 ) != 0x40 )
+ {
+ cpustate->timer[2] = 0;
+ cpustate->reg[INTET32] |= 0x08;
+ }
+ }
+ }
+ }
+
+ /* Timer 3 */
+ if ( cpustate->reg[TRUN] & 0x08 )
+ {
+ switch( ( cpustate->reg[T23MOD] >> 2 ) & 0x03 )
+ {
+ case 0x00: /* TO2TRG */
+ break;
+ case 0x01: /* T1 */
+ cpustate->timer_change[3] += ( cpustate->timer_pre >> 7 ) - ( old_pre >> 7 );
+ break;
+ case 0x02: /* T16 */
+ cpustate->timer_change[3] += ( cpustate->timer_pre >> 11 ) - ( old_pre >> 11 );
+ break;
+ case 0x03: /* T256 */
+ cpustate->timer_change[3] += ( cpustate->timer_pre >> 15 ) - ( old_pre >> 15 );
+ break;
+ }
+
+ for( ; cpustate->timer_change[3] > 0; cpustate->timer_change[3]-- )
+ {
+ cpustate->timer[3] += 1;
+ if ( cpustate->timer[3] == cpustate->reg[TREG3] )
+ {
+ cpustate->timer[3] = 0;
+ cpustate->reg[INTET32] |= 0x80;
+
+ if ( cpustate->reg[TFFCR] & 0x20 )
+ {
+ tlcs900_change_tff( cpustate, 3, FF_INVERT );
+ }
+
+ /* In 16bit timer mode also reset timer 2 */
+ if ( ( cpustate->reg[T23MOD] & 0xc0 ) == 0x40 )
+ {
+ cpustate->timer[2] = 0;
+ }
+ }
+ }
+ }
+
+ cpustate->timer_pre &= 0xffffff;
+}
+
+
+static CPU_EXECUTE( tlcs900 )
+{
+ tlcs900_state *cpustate = get_safe_token(device);
+
+ do
+ {
+ const tlcs900inst *inst;
+
+ cpustate->cycles = 0;
+
+ if ( cpustate->check_irqs )
+ {
+ tlcs900_check_irqs( cpustate );
+ cpustate->check_irqs = 0;
+ }
+
+ debugger_instruction_hook( device, cpustate->pc.d );
+
+ if ( cpustate->halted )
+ {
+ cpustate->cycles += 8;
+ }
+ else
+ {
+ cpustate->op = RDOP();
+ inst = &mnemonic[cpustate->op];
+ prepare_operands( cpustate, inst );
+
+ /* Execute the instruction */
+ inst->opfunc( cpustate );
+ cpustate->cycles += inst->cycles;
+ }
+
+ tlcs900_handle_ad( cpustate );
+
+ tlcs900_handle_timers( cpustate );
+
+ tlcs900_check_hdma( cpustate );
+
+ cpustate->icount -= cpustate->cycles;
+ } while ( cpustate->icount > 0 );
+}
+
+
+static void tlcs900_input_level_change( tlcs900_state *cpustate, int input, int level )
+{
+ switch( input )
+ {
+ case INPUT_LINE_NMI:
+ case TLCS900_NMI:
+ if ( cpustate->level[TLCS900_NMI] == CLEAR_LINE && level == ASSERT_LINE )
+ {
+ cpustate->nmi_state = level;
+ }
+ cpustate->level[TLCS900_NMI] = level;
+ break;
+
+ case TLCS900_INTWD:
+ break;
+
+ case TLCS900_INT0:
+ /* Is INT0 functionality enabled? */
+ if ( cpustate->reg[IIMC] & 0x04 )
+ {
+ if ( cpustate->reg[IIMC] & 0x02 )
+ {
+ /* Rising edge detect */
+ if ( cpustate->level[TLCS900_INT0] == CLEAR_LINE && level == ASSERT_LINE )
+ {
+ /* Leave HALT state */
+ cpustate->halted = 0;
+ cpustate->reg[INTE0AD] |= 0x08;
+ }
+ }
+ else
+ {
+ /* Level detect */
+ if ( level == ASSERT_LINE )
+ cpustate->reg[INTE0AD] |= 0x08;
+ else
+ cpustate->reg[INTE0AD] &= ~ 0x08;
+ }
+ }
+ cpustate->level[TLCS900_INT0] = level;
+ break;
+
+ case TLCS900_INT4:
+ if ( ! ( cpustate->reg[PBCR] & 0x01 ) )
+ {
+ if ( cpustate->level[TLCS900_INT4] == CLEAR_LINE && level == ASSERT_LINE )
+ {
+ cpustate->reg[INTE45] |= 0x08;
+ }
+ }
+ cpustate->level[TLCS900_INT4] = level;
+ break;
+
+ case TLCS900_INT5:
+ if ( ! ( cpustate->reg[PBCR] & 0x02 ) )
+ {
+ if ( cpustate->level[TLCS900_INT5] == CLEAR_LINE && level == ASSERT_LINE )
+ {
+ cpustate->reg[INTE45] |= 0x80;
+ }
+ }
+ cpustate->level[TLCS900_INT5] = level;
+ break;
+
+ case TLCS900_TIO: /* External timer input for timer 0 */
+ if ( ( cpustate->reg[TRUN] & 0x01 ) && ( cpustate->reg[T01MOD] & 0x03 ) == 0x00 )
+ {
+ if ( cpustate->level[TLCS900_TIO] == CLEAR_LINE && level == ASSERT_LINE )
+ {
+ cpustate->timer_change[0] += 1;
+ }
+ }
+ cpustate->level[TLCS900_TIO] = level;
+ break;
+ }
+ cpustate->check_irqs = 1;
+}
+
+
+static READ8_HANDLER( tlcs900_internal_r )
+{
+ tlcs900_state *cpustate = get_safe_token( &space->device() );
+
+ return cpustate->reg[ offset ];
+}
+
+
+static WRITE8_HANDLER( tlcs900_internal_w )
+{
+ tlcs900_state *cpustate = get_safe_token( &space->device() );
+
+ switch ( offset )
+ {
+ case TRUN:
+ if ( ! ( data & 0x01 ) )
+ {
+ cpustate->timer[0] = 0;
+ cpustate->timer_change[0] = 0;
+ }
+ if ( ! ( data & 0x02 ) )
+ {
+ cpustate->timer[1] = 0;
+ cpustate->timer_change[1] = 0;
+ }
+ if ( ! ( data & 0x04 ) )
+ {
+ cpustate->timer[2] = 0;
+ cpustate->timer_change[2] = 0;
+ }
+ if ( ! ( data & 0x08 ) )
+ {
+ cpustate->timer[3] = 0;
+ cpustate->timer_change[3] = 0;
+ }
+ if ( ! ( data & 0x10 ) )
+ cpustate->timer[4] = 0;
+ if ( ! ( data & 0x20 ) )
+ cpustate->timer[5] = 0;
+ break;
+
+ case TFFCR:
+ switch( data & 0x0c )
+ {
+ case 0x00:
+ tlcs900_change_tff( cpustate, 1, FF_INVERT );
+ break;
+ case 0x04:
+ tlcs900_change_tff( cpustate, 1, FF_SET );
+ break;
+ case 0x08:
+ tlcs900_change_tff( cpustate, 1, FF_CLEAR );
+ break;
+ }
+ switch( data & 0xc0 )
+ {
+ case 0x00:
+ tlcs900_change_tff( cpustate, 3, FF_INVERT );
+ break;
+ case 0x40:
+ tlcs900_change_tff( cpustate, 3, FF_SET );
+ break;
+ case 0x80:
+ tlcs900_change_tff( cpustate, 3, FF_CLEAR );
+ break;
+ }
+ break;
+ case MSAR0:
+ case MAMR0:
+ case MSAR1:
+ case MAMR1:
+ break;
+
+ case ADMOD:
+ /* Preserve read-only bits */
+ data = ( cpustate->reg[ADMOD] & 0xc0 ) | ( data & 0x3f );
+
+ /* Check for A/D request start */
+ if ( data & 0x04 )
+ {
+ data &= ~0x04;
+ data |= 0x40;
+ cpustate->ad_cycles_left = ( data & 0x08 ) ? 640 : 320;
+ }
+ break;
+
+ case WDMOD:
+ case WDCR:
+ break;
+
+ case INTE0AD:
+ case INTE45:
+ case INTE67:
+ case INTET10:
+ case INTET32:
+ case INTET54:
+ case INTET76:
+ case INTES0:
+ case INTES1:
+ case INTETC10:
+ case INTETC32:
+ if ( data & 0x80 )
+ data = ( data & 0x7f ) | ( cpustate->reg[offset] & 0x80 );
+ if ( data & 0x08 )
+ data = ( data & 0xf7 ) | ( cpustate->reg[offset] & 0x08 );
+ break;
+
+ case IIMC:
+ break;
+
+ default:
+ break;
+ }
+
+ cpustate->check_irqs = 1;
+ cpustate->reg[ offset ] = data;
+}
+
+
+static ADDRESS_MAP_START( tlcs900_mem, AS_PROGRAM, 8 )
+ AM_RANGE( 0x000000, 0x00007f ) AM_READWRITE( tlcs900_internal_r, tlcs900_internal_w )
+ADDRESS_MAP_END
+
+
+static CPU_SET_INFO( tlcs900 )
+{
+ tlcs900_state *cpustate = get_safe_token( device );
+
+ switch ( state )
+ {
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:
+ case CPUINFO_INT_INPUT_STATE + TLCS900_NMI:
+ case CPUINFO_INT_INPUT_STATE + TLCS900_INTWD:
+ case CPUINFO_INT_INPUT_STATE + TLCS900_INT0:
+ case CPUINFO_INT_INPUT_STATE + TLCS900_INT4:
+ case CPUINFO_INT_INPUT_STATE + TLCS900_INT5:
+ case CPUINFO_INT_INPUT_STATE + TLCS900_TIO:
+ tlcs900_input_level_change( cpustate, state - CPUINFO_INT_INPUT_STATE, info->i ); break;
+ }
+}
+
+
+CPU_GET_INFO( tlcs900h )
+{
+ tlcs900_state *cpustate = ( device != NULL && device->token() != NULL ) ? get_safe_token(device) : NULL;
+
+ switch( state )
+ {
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(tlcs900_state); 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; /* FIXME */
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; /* FIXME */
+ case CPUINFO_INT_MAX_CYCLES: info->i = 1; break; /* FIXME */
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; 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 CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:
+ case CPUINFO_INT_INPUT_STATE + TLCS900_NMI: info->i = cpustate->level[TLCS900_NMI]; break;
+ case CPUINFO_INT_INPUT_STATE + TLCS900_INTWD: info->i = cpustate->level[TLCS900_INTWD]; break;
+ case CPUINFO_INT_INPUT_STATE + TLCS900_INT0: info->i = cpustate->level[TLCS900_INT0]; break;
+ case CPUINFO_INT_INPUT_STATE + TLCS900_INT4: info->i = cpustate->level[TLCS900_INT4]; break;
+ case CPUINFO_INT_INPUT_STATE + TLCS900_INT5: info->i = cpustate->level[TLCS900_INT5]; break;
+ case CPUINFO_INT_INPUT_STATE + TLCS900_TIO: info->i = cpustate->level[TLCS900_TIO]; break;
+
+ case CPUINFO_INT_PC: info->i = cpustate->pc.d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_PC: info->i = cpustate->pc.d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_SR: info->i = cpustate->sr.d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XWA0: info->i = cpustate->xwa[0].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XBC0: info->i = cpustate->xbc[0].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XDE0: info->i = cpustate->xde[0].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XHL0: info->i = cpustate->xhl[0].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XWA1: info->i = cpustate->xwa[1].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XBC1: info->i = cpustate->xbc[1].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XDE1: info->i = cpustate->xde[1].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XHL1: info->i = cpustate->xhl[1].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XWA2: info->i = cpustate->xwa[2].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XBC2: info->i = cpustate->xbc[2].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XDE2: info->i = cpustate->xde[2].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XHL2: info->i = cpustate->xhl[2].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XWA3: info->i = cpustate->xwa[3].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XBC3: info->i = cpustate->xbc[3].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XDE3: info->i = cpustate->xde[3].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XHL3: info->i = cpustate->xhl[3].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XIX: info->i = cpustate->xix.d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XIY: info->i = cpustate->xiy.d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XIZ: info->i = cpustate->xiz.d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XNSP: info->i = cpustate->xnsp.d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XSSP: info->i = cpustate->xssp.d; break;
+
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(tlcs900); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(tlcs900); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(tlcs900); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(tlcs900); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(tlcs900); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(tlcs900); 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(tlcs900_mem); break;
+
+ case CPUINFO_STR_REGISTER + TLCS900_PC: sprintf( info->s, "PC:%08x", cpustate->pc.d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_SR: sprintf( info->s, "SR:%c%d%c%d%c%c%c%c%c%c%c%c",
+ cpustate->sr.w.l & 0x8000 ? 'S' : 'U',
+ ( cpustate->sr.w.l & 0x7000 ) >> 12,
+ cpustate->sr.w.l & 0x0800 ? 'M' : 'N',
+ ( cpustate->sr.w.l & 0x0700 ) >> 8,
+ cpustate->sr.w.l & 0x0080 ? 'S' : '.',
+ cpustate->sr.w.l & 0x0040 ? 'Z' : '.',
+ cpustate->sr.w.l & 0x0020 ? '1' : '.',
+ cpustate->sr.w.l & 0x0010 ? 'H' : '.',
+ cpustate->sr.w.l & 0x0008 ? '1' : '.',
+ cpustate->sr.w.l & 0x0004 ? 'V' : '.',
+ cpustate->sr.w.l & 0x0002 ? 'N' : '.',
+ cpustate->sr.w.l & 0x0001 ? 'C' : '.' );
+ break;
+ case CPUINFO_STR_REGISTER + TLCS900_XWA0: sprintf( info->s, "XWA0:%08x", cpustate->xwa[0].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XBC0: sprintf( info->s, "XBC0:%08x", cpustate->xbc[0].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XDE0: sprintf( info->s, "XDE0:%08x", cpustate->xde[0].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XHL0: sprintf( info->s, "XHL0:%08x", cpustate->xhl[0].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XWA1: sprintf( info->s, "XWA1:%08x", cpustate->xwa[1].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XBC1: sprintf( info->s, "XBC1:%08x", cpustate->xbc[1].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XDE1: sprintf( info->s, "XDE1:%08x", cpustate->xde[1].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XHL1: sprintf( info->s, "XHL1:%08x", cpustate->xhl[1].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XWA2: sprintf( info->s, "XWA2:%08x", cpustate->xwa[2].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XBC2: sprintf( info->s, "XBC2:%08x", cpustate->xbc[2].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XDE2: sprintf( info->s, "XDE2:%08x", cpustate->xde[2].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XHL2: sprintf( info->s, "XHL2:%08x", cpustate->xhl[2].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XWA3: sprintf( info->s, "XWA3:%08x", cpustate->xwa[3].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XBC3: sprintf( info->s, "XBC3:%08x", cpustate->xbc[3].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XDE3: sprintf( info->s, "XDE3:%08x", cpustate->xde[3].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XHL3: sprintf( info->s, "XHL3:%08x", cpustate->xhl[3].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XIX: sprintf( info->s, "XIX:%08x", cpustate->xix.d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XIY: sprintf( info->s, "XIY:%08x", cpustate->xiy.d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XIZ: sprintf( info->s, "XIZ:%08x", cpustate->xiz.d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XNSP: sprintf( info->s, "XNSP:%08x", cpustate->xnsp.d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XSSP: sprintf( info->s, "XSSP:%08x", cpustate->xssp.d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAS0: sprintf( info->s, "DMAS0:%08x", cpustate->dmas[0].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAD0: sprintf( info->s, "DMAD0:%08x", cpustate->dmad[0].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAC0: sprintf( info->s, "DMAC0:%04x", cpustate->dmac[0].w.l ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAM0: sprintf( info->s, "DMAM0:%02x", cpustate->dmam[0].b.l ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAS1: sprintf( info->s, "DMAS0:%08x", cpustate->dmas[1].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAD1: sprintf( info->s, "DMAD0:%08x", cpustate->dmad[1].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAC1: sprintf( info->s, "DMAC0:%04x", cpustate->dmac[1].w.l ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAM1: sprintf( info->s, "DMAM0:%02x", cpustate->dmam[1].b.l ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAS2: sprintf( info->s, "DMAS0:%08x", cpustate->dmas[2].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAD2: sprintf( info->s, "DMAD0:%08x", cpustate->dmad[2].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAC2: sprintf( info->s, "DMAC0:%04x", cpustate->dmac[2].w.l ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAM2: sprintf( info->s, "DMAM0:%02x", cpustate->dmam[2].b.l ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAS3: sprintf( info->s, "DMAS0:%08x", cpustate->dmas[3].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAD3: sprintf( info->s, "DMAD0:%08x", cpustate->dmad[3].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAC3: sprintf( info->s, "DMAC0:%04x", cpustate->dmac[3].w.l ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAM3: sprintf( info->s, "DMAM0:%02x", cpustate->dmam[3].b.l ); break;
+
+ case DEVINFO_STR_NAME: strcpy( info->s, "TLCS-900/H" ); break;
+ case DEVINFO_STR_FAMILY: strcpy( info->s, "Toshiba TLCS-900" ); 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 Wilbert Pol" ); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(TLCS900H, tlcs900h);
diff --git a/trunk/src/emu/cpu/tlcs900/tlcs900.h b/trunk/src/emu/cpu/tlcs900/tlcs900.h
new file mode 100644
index 00000000000..f950ba77afe
--- /dev/null
+++ b/trunk/src/emu/cpu/tlcs900/tlcs900.h
@@ -0,0 +1,46 @@
+#ifndef __TLCS900_H__
+#define __TLCS900_H__
+
+
+
+enum tlcs900_inputs
+{
+ TLCS900_NMI=0,
+ TLCS900_INTWD,
+ TLCS900_INT0,
+ TLCS900_INTAD,
+ TLCS900_INT4,
+ TLCS900_INT5,
+ TLCS900_TIO,
+ TLCS900_NUM_INPUTS
+};
+
+
+enum
+{
+ TLCS900_PC=1, TLCS900_SR,
+ TLCS900_XWA0, TLCS900_XBC0, TLCS900_XDE0, TLCS900_XHL0,
+ TLCS900_XWA1, TLCS900_XBC1, TLCS900_XDE1, TLCS900_XHL1,
+ TLCS900_XWA2, TLCS900_XBC2, TLCS900_XDE2, TLCS900_XHL2,
+ TLCS900_XWA3, TLCS900_XBC3, TLCS900_XDE3, TLCS900_XHL3,
+ TLCS900_XIX, TLCS900_XIY, TLCS900_XIZ, TLCS900_XNSP, TLCS900_XSSP,
+ TLCS900_DMAS0, TLCS900_DMAS1, TLCS900_DMAS2, TLCS900_DMAS3,
+ TLCS900_DMAD0, TLCS900_DMAD1, TLCS900_DMAD2, TLCS900_DMAD3,
+ TLCS900_DMAC0, TLCS900_DMAC1, TLCS900_DMAC2, TLCS900_DMAC3,
+ TLCS900_DMAM0, TLCS900_DMAM1, TLCS900_DMAM2, TLCS900_DMAM3
+};
+
+
+typedef struct _tlcs900_interface tlcs900_interface;
+struct _tlcs900_interface
+{
+ devcb_write8 to1;
+ devcb_write8 to3;
+};
+
+
+DECLARE_LEGACY_CPU_DEVICE(TLCS900H, tlcs900h);
+
+extern CPU_DISASSEMBLE( tlcs900 );
+
+#endif
diff --git a/trunk/src/emu/cpu/tms0980/tms0980.c b/trunk/src/emu/cpu/tms0980/tms0980.c
new file mode 100644
index 00000000000..084f5c3f662
--- /dev/null
+++ b/trunk/src/emu/cpu/tms0980/tms0980.c
@@ -0,0 +1,1285 @@
+/*
+
+
+TMS0980/TMS1000-family CPU cores
+
+The tms0980 and tms1000-family cpu cores are very similar. The tms0980 has a
+slightly bigger addressable area and uses 9bit instructions where the tms1000
+family uses 8bit instruction. The instruction set themselves are very similar
+though. The table below shows the differences between the different models.
+
+Mode | ROM | RAM | R pins | O pins | K pins | ids
+---------+-----------+----------+--------+--------+--------|----------
+tms0970* | 1024 * 8 | 64 * 4 | | | | tms0972
+tms0920* | 511?* 9 | 40 * 5 | | | | tmc0921
+tms0980 | 2048 * 9 | 64 * 9 | | | | tmc0981
+tms1000 | 1024 * 8 | 64 * 4 | 11 | 8 | 4 | tms1001
+tms1040* | 1024 * 8 | 64 * 4 | | | | tms1043
+tms1070 | 1024 * 8 | 64 * 4 | 11 | 8 | 4 | tms1071
+tms1100 | 2048 * 8 | 128 * 4 | 11 | 8 | 4 | tms1111/tms1115
+tms1170* | 2048 * 8 | 128 * 4 | | | | tmc1172
+tms1200 | 1024 * 8 | 64 * 4 | 13 | 8 | 4 | tms1215
+tms1270 | 1024 * 8 | 64 * 4 | 13 | 10 | 4 | tms1278
+tms1300 | 2048 * 8 | 128 * 4 | 16 | 8 | 4 | tms1309
+tms1370* | 2048 * 8 | 128 * 4 | | | | za0543
+tms1400* | 4096 * 8 | 128 * 4 | | | |
+tms1470* | 4096 * 8 | 128 * 4 | | | | tms1470
+tms1500* | 2048 * 13 | 64 * 20 | | | | tmc1501
+tms1600* | 4096 * 8 | 128 * 4 | | | |
+tms1670* | 4096 * 8 | 128 * 4 | | | |
+tms1700* | 512 * 8 | 32 * 4 | | | |
+tms1980* | 2048 * 9 | 64 * 9 | | | | tmc1982
+tms1990* | 1024 * 8 | 64 * 4 | | | | tmc1991
+tp0310* | 511?* 9 | 40 * 5 | | | | tp0311
+tp0320* | 2048 * 9 | 64 * 13 | | | | tp0321
+tp0455* | | | | | | cd4501
+tp0456* | | | | | | cd4555
+tp0458* | | | | | | cd4812
+tp0485* | | | | | | cd2901
+tp0530* | | | | | | cd5402
+
+* = not supported yet
+
+The TMS1000 core has been tested with some example code, the other models
+have not been tested lacking rom dumps.
+
+Each instruction takes 12 cycles to execute in 2 phases: a fetch phase and an
+execution phase. The execution phase takes place at the same time as the fetch
+phase of the next instruction. So, during execution there are both fetch and
+execution operations taking place. The operation can be split up as follows:
+cycle #0
+ - Fetch:
+ 1. ROM address 0
+ - Execute:
+ 1. Read RAM
+ 2. Clear ALU inputs
+ 3. Execute BRANCH/CALL/RETN part #2
+ 4. K input valid
+cycle #1
+ - Fetch:
+ 1. ROM address 1
+ - Execute:
+ 1. Update ALU inputs
+cycle #2
+ - Fetch:
+ 1. nothing/wait(?)
+ - Execute:
+ 1. Perform ALU operation
+ 2. Write RAM
+cycle #3
+ - Fetch:
+ 1. Fetch/Update PC/RAM address #1
+ - Execute:
+ 1. Register store part #1
+cycle #4
+ - Fetch:
+ 1. Fetch/Update PC/RAM address #2
+ - Execute:
+ 1. Register store part #2
+cycle #5
+ - Fetch:
+ 1. Instruction decode
+ - Execute:
+ 1. Execute BRANCH/CALL/RETN part #1
+
+
+The CPU cores contains a set of fixed instructions and a set of
+instructions created using microinstructions. A subset of the
+instruction set could be defined from the microinstructions by
+TI customers. Currently we only support the standard instruction
+set as defined by TI.
+
+The microinstructions are:
+15TN - 15 to -ALU
+ATN - ACC to -ALU
+AUTA - ALU to ACC
+AUTY - ALU to Y
+C8 - CARRY8 to STATUS
+CIN - Carry In to ALU
+CKM - CKB to MEM
+CKN - CKB to -ALU
+CKP - CKB to +ALU
+CME - Conditional Memory Enable
+DMTP - DAM to +ALU
+MTN - MEM to -ALU
+MTP - MEM to +ALU
+NATN - ~ACC to -ALU
+NDMTP - ~DAM to +ALU
+NE - COMP to STATUS
+SSE - Special Status Enable
+SSS - Special Status Sample
+STO - ACC to MEM
+YTP - Y to +ALU
+
+cycle #0: 15TN, ATN, CIN, CKN, CKP, DMTP, MTN, MTP, NATN, NDMTP, YTP
+cycle #2: C8(?), CKM, NE(?), STO
+cycle #3,#4: AUTA, AUTY
+
+unknown cycle: CME, SSE, SSS
+
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "tms0980.h"
+
+#define LOG 0
+
+#define MICRO_MASK 0x80000000
+#define FIXED_INSTRUCTION 0x00000000
+
+
+/* Standard/fixed intructions */
+#define F_ILL 0x00000000
+#define F_BR 0x00000001
+#define F_CALL 0x00000002
+#define F_CLO 0x00000004
+#define F_COMC 0x00000008
+#define F_COMX 0x00000010
+#define F_COMX8 0x00000020
+#define F_LDP 0x00000040
+#define F_LDX 0x00000080
+#define F_OFF 0x00000100
+#define F_RBIT 0x00000200
+#define F_REAC 0x00000400
+#define F_RETN 0x00000800
+#define F_RSTR 0x00001000
+#define F_SAL 0x00002000
+#define F_SBIT 0x00004000
+#define F_SBL 0x00008000
+#define F_SEAC 0x00010000
+#define F_SETR 0x00020000
+#define F_TDO 0x00040000
+
+
+/* Microinstructions */
+#define M_15TN 0x00000001
+#define M_ATN 0x00000002
+#define M_AUTA 0x00000004
+#define M_AUTY 0x00000008
+#define M_C8 0x00000010
+#define M_CIN 0x00000020
+#define M_CKM 0x00000040
+#define M_CKN 0x00000080
+#define M_CKP 0x00000100
+#define M_CME 0x00000200
+#define M_DMTP 0x00000400
+#define M_MTN 0x00000800
+#define M_MTP 0x00001000
+#define M_NATN 0x00002000
+#define M_NDMTP 0x00004000
+#define M_NE 0x00008000
+#define M_SSE 0x00010000
+#define M_SSS 0x00020000
+#define M_STO 0x00040000
+#define M_STSL 0x00080000
+#define M_YTP 0x00100000
+
+
+/* instructions built from microinstructions */
+#define I_AC1AC ( MICRO_MASK | M_CKP | M_ATN | M_CIN | M_C8 | M_AUTA )
+#define I_A6AAC I_ACACC
+#define I_A8AAC I_ACACC
+#define I_A10AAC I_ACACC
+#define I_ACACC ( MICRO_MASK | M_CKP | M_ATN | M_C8 | M_AUTA )
+#define I_ACNAA ( MICRO_MASK | M_CKP | M_NATN | M_AUTA )
+#define I_ALEC ( MICRO_MASK | M_CKP | M_NATN | M_CIN | M_C8 )
+#define I_ALEM ( MICRO_MASK | M_MTP | M_NATN | M_CIN | M_C8 )
+#define I_AMAAC ( MICRO_MASK | M_MTP | M_ATN | M_C8 | M_AUTA )
+#define I_CCLA ( MICRO_MASK | M_AUTA | M_SSS )
+#define I_CLA ( MICRO_MASK | M_AUTA )
+#define I_CPAIZ ( MICRO_MASK | M_NATN | M_CIN | M_C8 | M_AUTA )
+#define I_CTMDYN ( MICRO_MASK | M_YTP | M_15TN | M_C8 | M_AUTY | M_CME )
+#define I_DAN ( MICRO_MASK | M_CKP | M_ATN | M_CIN | M_C8 | M_AUTA )
+#define I_DMAN ( MICRO_MASK | M_MTP | M_15TN | M_C8 | M_AUTA )
+#define I_DMEA ( MICRO_MASK | M_MTP | M_DMTP | M_SSS | M_AUTA )
+#define I_DNAA ( MICRO_MASK | M_DMTP | M_NATN | M_SSS | M_AUTA )
+#define I_DYN ( MICRO_MASK | M_YTP | M_15TN | M_C8 | M_AUTY )
+#define I_IA ( MICRO_MASK | M_ATN | M_CIN | M_AUTA )
+#define I_IMAC ( MICRO_MASK | M_MTP | M_CIN | M_C8 | M_AUTA )
+#define I_IYC ( MICRO_MASK | M_YTP | M_CIN | M_C8 | M_AUTY )
+#define I_KNEZ ( MICRO_MASK | M_CKP | M_NE )
+#define I_MNEA ( MICRO_MASK | M_MTP | M_ATN | M_NE )
+#define I_MNEZ ( MICRO_MASK | M_MTP | M_NE )
+#define I_M_NDMEA ( MICRO_MASK | M_MTN | M_NDTMP | M_SSS | M_AUTA )
+#define I_SAMAN ( MICRO_MASK | M_MTP | M_NATN | M_CIN | M_C8 | M_AUTA )
+#define I_SETR ( MICRO_MASK | M_YTP | M_15TN | M_AUTY | M_C8 )
+#define I_TAM ( MICRO_MASK | M_STO )
+#define I_TAMACS ( MICRO_MASK | M_STO | M_ATN | M_CKP | M_AUTA | M_SSE )
+#define I_TAMDYN ( MICRO_MASK | M_STO | M_YTP | M_15TN | M_AUTY | M_C8 )
+#define I_TAMIY ( MICRO_MASK | M_STO | M_YTP | M_CIN | M_AUTY )
+#define I_TAMIYC ( MICRO_MASK | M_STO | M_YTP | M_CIN | M_C8 | M_AUTY )
+#define I_TAMZA ( MICRO_MASK | M_STO | M_AUTA )
+#define I_TAY ( MICRO_MASK | M_ATN | M_AUTY )
+#define I_TBIT ( MICRO_MASK | M_CKP | M_CKN | M_MTP | M_NE )
+#define I_TCY ( MICRO_MASK | M_CKP | M_AUTY )
+#define I_TCMIY ( MICRO_MASK | M_CKM | M_YTP | M_CIN | M_AUTY )
+#define I_TKA ( MICRO_MASK | M_CKP | M_AUTA )
+#define I_TKM ( MICRO_MASK | M_CKM )
+#define I_TMA ( MICRO_MASK | M_MTP | M_AUTA )
+#define I_TMY ( MICRO_MASK | M_MTP | M_AUTY )
+#define I_TYA ( MICRO_MASK | M_YTP | M_AUTA )
+#define I_XDA ( MICRO_MASK | M_DMTP | M_AUTA | M_STO )
+#define I_XMA ( MICRO_MASK | M_MTP | M_STO | M_AUTA )
+#define I_YMCY ( MICRO_MASK | M_CIN | M_YTP | M_CKN | M_AUTY )
+#define I_YNEA ( MICRO_MASK | M_YTP | M_ATN | M_NE )
+#define I_YNEC ( MICRO_MASK | M_YTP | M_CKN | M_NE )
+
+
+typedef struct _tms0980_state tms0980_state;
+struct _tms0980_state
+{
+ UINT8 prev_pc; /* previous program counter */
+ UINT8 prev_pa; /* previous page address register */
+ UINT8 pc; /* program counter is a 7 bit register on tms0980, 6 bit register on tms1000/1070/1200/1270/1100/1300 */
+ UINT8 pa; /* page address register is a 4 bit register */
+ UINT8 sr; /* subroutine return register is a 7 bit register */
+ UINT8 pb; /* page buffer register is a 4 bit register */
+ UINT8 a; /* Accumulator is a 4 bit register (?) */
+ UINT8 x; /* X-register is a 2 bit register */
+ UINT8 y; /* Y-register is a 4 bit register */
+ UINT8 dam; /* DAM register is a 4 bit register */
+ UINT8 ca; /* Chapter address bit */
+ UINT8 cb; /* Chapter buffer bit */
+ UINT8 cs; /* Chapter subroutine bit */
+ UINT16 r;
+ UINT8 o;
+ UINT8 cki_bus; /* CKI bus */
+ UINT8 p; /* adder p-input */
+ UINT8 n; /* adder n-input */
+ UINT8 adder_result; /* adder result */
+ UINT8 carry_in; /* carry in */
+ UINT8 status;
+ UINT8 status_latch;
+ UINT8 special_status;
+ UINT8 call_latch;
+ UINT8 add_latch;
+ UINT8 branch_latch;
+ int subcycle;
+ UINT8 ram_address;
+ UINT16 ram_data;
+ UINT16 rom_address;
+ UINT16 opcode;
+ UINT32 decode;
+ int icount;
+ UINT16 o_mask; /* mask to determine the number of O outputs */
+ UINT16 r_mask; /* mask to determine the number of R outputs */
+ UINT8 pc_size; /* how bits in the PC register */
+ UINT8 byte_size; /* 8 or 9 bit bytes */
+ const UINT32 *decode_table;
+ const tms0980_config *config;
+ address_space *program;
+ address_space *data;
+};
+
+
+static const UINT8 tms0980_c2_value[4] =
+{
+ 0x00, 0x02, 0x01, 0x03
+};
+static const UINT8 tms0980_c4_value[16] =
+{
+ 0x00, 0x08, 0x04, 0x0C, 0x02, 0x0A, 0x06, 0x0E, 0x01, 0x09, 0x05, 0x0D, 0x03, 0x0B, 0x07, 0x0F
+};
+static const UINT8 tms0980_bit_value[4] = { 1, 4, 2, 8 };
+static const UINT8 tms0980_nbit_value[4] = { 0x0E, 0x0B, 0x0D, 0x07 };
+
+
+static const UINT32 tms0980_decode[512] =
+{
+ /* 0x000 */
+ F_COMX, I_ALEM, I_YNEA, I_XMA, I_DYN, I_IYC, I_CLA, I_DMAN,
+ I_TKA, I_MNEA, I_TKM, F_ILL, F_ILL, F_SETR, I_KNEZ, F_ILL,
+ I_DMEA, I_DNAA, I_CCLA, I_DMEA, F_ILL, I_AMAAC, F_ILL, F_ILL,
+ I_CTMDYN, I_XDA, F_ILL, F_ILL, F_ILL, F_ILL, F_ILL, F_ILL,
+ I_TBIT, I_TBIT, I_TBIT, I_TBIT, F_ILL, F_ILL, F_ILL, F_ILL,
+ I_TAY, I_TMA, I_TMY, I_TYA, I_TAMDYN, I_TAMIYC, I_TAMZA, I_TAM,
+ I_SAMAN, I_CPAIZ, I_IMAC, I_MNEZ, F_ILL, F_ILL, F_ILL, F_ILL,
+ I_TCY, I_YNEC, I_TCMIY, I_ACACC, I_ACNAA, I_TAMACS, I_ALEC, I_YMCY,
+ /* 0x040 */
+ I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY,
+ I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY,
+ I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC,
+ I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC,
+ I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY,
+ I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY,
+ I_ACACC, I_ACACC, I_ACACC, I_ACACC, I_ACACC, I_ACACC, I_ACACC, I_ACACC,
+ I_ACACC, I_ACACC, I_ACACC, I_ACACC, I_ACACC, I_ACACC, I_ACACC, I_ACACC,
+ /* 0x080 */
+ F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP,
+ F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP,
+ F_LDX, F_LDX, F_LDX, F_LDX, F_LDX, F_LDX, F_LDX, F_LDX,
+ F_LDX, F_LDX, F_LDX, F_LDX, F_LDX, F_LDX, F_LDX, F_LDX,
+ F_SBIT, F_SBIT, F_SBIT, F_SBIT, F_RBIT, F_RBIT, F_RBIT, F_RBIT,
+ F_ILL, F_ILL, F_ILL, F_ILL, F_ILL, F_ILL, F_ILL, F_ILL,
+ F_TDO, F_SAL, F_COMX8, F_SBL, F_REAC, F_SEAC, F_OFF, F_ILL,
+ F_ILL, F_ILL, F_ILL, F_ILL, F_ILL, F_ILL, F_ILL, F_RETN,
+ /* 0x0c0 */
+ I_ACNAA, I_ACNAA, I_ACNAA, I_ACNAA, I_ACNAA, I_ACNAA, I_ACNAA, I_ACNAA,
+ I_ACNAA, I_ACNAA, I_ACNAA, I_ACNAA, I_ACNAA, I_ACNAA, I_ACNAA, I_ACNAA,
+ I_TAMACS, I_TAMACS, I_TAMACS, I_TAMACS, I_TAMACS, I_TAMACS, I_TAMACS, I_TAMACS,
+ I_TAMACS, I_TAMACS, I_TAMACS, I_TAMACS, I_TAMACS, I_TAMACS, I_TAMACS, I_TAMACS,
+ I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC,
+ I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC,
+ I_YMCY, I_YMCY, I_YMCY, I_YMCY, I_YMCY, I_YMCY, I_YMCY, I_YMCY,
+ I_YMCY, I_YMCY, I_YMCY, I_YMCY, I_YMCY, I_YMCY, I_YMCY, I_YMCY,
+ /* 0x100 */
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ /* 0x140 */
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ /* 0x180 */
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ /* 0x1c0 */
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL
+};
+
+
+static const UINT32 tms1000_default_decode[256] = {
+ /* 0x00 */
+ F_COMX, I_A8AAC, I_YNEA, I_TAM, I_TAMZA, I_A10AAC, I_A6AAC, I_DAN,
+ I_TKA, I_KNEZ, F_TDO, F_CLO, F_RSTR, F_SETR, I_IA, F_RETN,
+ F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP,
+ F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP,
+ /* 0x20 */
+ I_TAMIY, I_TMA, I_TMY, I_TYA, I_TAY, I_AMAAC, I_MNEZ, I_SAMAN,
+ I_IMAC, I_ALEM, I_DMAN, I_IYC, I_DYN, I_CPAIZ, I_XMA, I_CLA,
+ F_SBIT, F_SBIT, F_SBIT, F_SBIT, F_RBIT, F_RBIT, F_RBIT, F_RBIT,
+ I_TBIT, I_TBIT, I_TBIT, I_TBIT, F_LDX, F_LDX, F_LDX, F_LDX,
+ /* 0x40 */
+ I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY,
+ I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY,
+ I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC,
+ I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC,
+ /* 0x60 */
+ I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY,
+ I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY,
+ I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC,
+ I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC,
+ /* 0x80 */
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ /* 0xC0 */
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+};
+
+
+static const UINT32 tms1100_default_decode[256] = {
+ /* 0x00 */
+ I_MNEA, I_ALEM, I_YNEA, I_XMA, I_DYN, I_IYC, I_AMAAC, I_DMAN,
+ I_TKA, F_COMX, F_TDO, F_COMC, F_RSTR, F_SETR, I_KNEZ, F_RETN,
+ F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP,
+ F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP,
+ /* 0x20 */
+ I_TAY, I_TMA, I_TMY, I_TYA, I_TAMDYN, I_TAMIYC, I_TAMZA, I_TAM,
+ F_LDX, F_LDX, F_LDX, F_LDX, F_LDX, F_LDX, F_LDX, F_LDX,
+ F_SBIT, F_SBIT, F_SBIT, F_SBIT, F_RBIT, F_RBIT, F_RBIT, F_RBIT,
+ I_TBIT, I_TBIT, I_TBIT, I_TBIT, I_SAMAN, I_CPAIZ, I_IMAC, I_MNEZ,
+ /* 0x40 */
+ I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY,
+ I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY,
+ I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC,
+ I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC,
+ /* 0x60 */
+ I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY,
+ I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY,
+ I_AC1AC, I_AC1AC, I_AC1AC, I_AC1AC, I_AC1AC, I_AC1AC, I_AC1AC, I_AC1AC,
+ I_AC1AC, I_AC1AC, I_AC1AC, I_AC1AC, I_AC1AC, I_AC1AC, I_AC1AC, I_CLA,
+ /* 0x80 */
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ /* 0xC0 */
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+};
+
+
+INLINE tms0980_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == TMS0980 ||
+ device->type() == TMS1000 ||
+ device->type() == TMS1070 ||
+ device->type() == TMS1100 ||
+ device->type() == TMS1200 ||
+ device->type() == TMS1270 ||
+ device->type() == TMS1300 );
+ return (tms0980_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+
+static ADDRESS_MAP_START(tms0980_internal_rom, AS_PROGRAM, 16)
+ AM_RANGE( 0x0000, 0x0FFF ) AM_ROM
+ADDRESS_MAP_END
+
+
+static ADDRESS_MAP_START(tms0980_internal_ram, AS_DATA, 8)
+ AM_RANGE( 0x0000, 0x0FFF ) AM_RAM
+ADDRESS_MAP_END
+
+
+static ADDRESS_MAP_START(program_10bit_8, AS_PROGRAM, 8)
+ AM_RANGE( 0x000, 0x3ff ) AM_ROM
+ADDRESS_MAP_END
+
+
+static ADDRESS_MAP_START(program_11bit_8, 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
+
+
+static void cpu_init_tms_common( legacy_cpu_device *device, const UINT32* decode_table, UINT16 o_mask, UINT16 r_mask, UINT8 pc_size, UINT8 byte_size )
+{
+ tms0980_state *cpustate = get_safe_token( device );
+
+ cpustate->config = (const tms0980_config *) device->static_config();
+
+ assert( cpustate->config != NULL );
+
+ cpustate->decode_table = decode_table;
+ cpustate->o_mask = o_mask;
+ cpustate->r_mask = r_mask;
+ cpustate->pc_size = pc_size;
+ cpustate->byte_size = byte_size;
+
+ cpustate->program = device->space( AS_PROGRAM );
+ cpustate->data = device->space( AS_PROGRAM );
+
+ device->save_item( NAME(cpustate->prev_pc) );
+ device->save_item( NAME(cpustate->prev_pa) );
+ device->save_item( NAME(cpustate->pc) );
+ device->save_item( NAME(cpustate->pa) );
+ device->save_item( NAME(cpustate->sr) );
+ device->save_item( NAME(cpustate->pb) );
+ device->save_item( NAME(cpustate->a) );
+ device->save_item( NAME(cpustate->x) );
+ device->save_item( NAME(cpustate->y) );
+ device->save_item( NAME(cpustate->dam) );
+ device->save_item( NAME(cpustate->ca) );
+ device->save_item( NAME(cpustate->cb) );
+ device->save_item( NAME(cpustate->cs) );
+ device->save_item( NAME(cpustate->r) );
+ device->save_item( NAME(cpustate->o) );
+ device->save_item( NAME(cpustate->cki_bus) );
+ device->save_item( NAME(cpustate->p) );
+ device->save_item( NAME(cpustate->n) );
+ device->save_item( NAME(cpustate->adder_result) );
+ device->save_item( NAME(cpustate->carry_in) );
+ device->save_item( NAME(cpustate->status) );
+ device->save_item( NAME(cpustate->status_latch) );
+ device->save_item( NAME(cpustate->special_status) );
+ device->save_item( NAME(cpustate->call_latch) );
+ device->save_item( NAME(cpustate->add_latch) );
+ device->save_item( NAME(cpustate->branch_latch) );
+ device->save_item( NAME(cpustate->subcycle) );
+ device->save_item( NAME(cpustate->ram_address) );
+ device->save_item( NAME(cpustate->ram_data) );
+ device->save_item( NAME(cpustate->rom_address) );
+ device->save_item( NAME(cpustate->opcode) );
+ device->save_item( NAME(cpustate->decode) );
+}
+
+
+static CPU_INIT( tms0980 )
+{
+ cpu_init_tms_common( device, tms0980_decode, 0x00ff, 0x07ff, 7, 9 );
+}
+
+
+static CPU_INIT( tms1000 )
+{
+ cpu_init_tms_common( device, tms1000_default_decode, 0x00ff, 0x07ff, 6, 8 );
+}
+
+
+static CPU_INIT( tms1070 )
+{
+ cpu_init_tms_common( device, tms1000_default_decode, 0x00ff, 0x07ff, 6, 8 );
+}
+
+
+static CPU_INIT( tms1200 )
+{
+ cpu_init_tms_common( device, tms1000_default_decode, 0x00ff, 0x1fff, 6, 8 );
+}
+
+
+static CPU_INIT( tms1270 )
+{
+ cpu_init_tms_common( device, tms1000_default_decode, 0x03ff, 0x1fff, 6, 8 );
+}
+
+
+static CPU_INIT( tms1100 )
+{
+ cpu_init_tms_common( device, tms1100_default_decode, 0x00ff, 0x07ff, 6, 8 );
+}
+
+
+static CPU_INIT( tms1300 )
+{
+ cpu_init_tms_common( device, tms1100_default_decode, 0x00ff, 0xffff, 6, 8 );
+}
+
+
+static CPU_RESET( tms0980 )
+{
+ tms0980_state *cpustate = get_safe_token( device );
+
+ cpustate->pa = 0x0F;
+ cpustate->pb = 0x0F;
+ cpustate->pc = 0;
+ cpustate->dam = 0;
+ cpustate->ca = 0;
+ cpustate->cb = 0;
+ cpustate->cs = 0;
+ cpustate->subcycle = 0;
+ cpustate->status = 1;
+ cpustate->status_latch = 0;
+ cpustate->call_latch = 0;
+ cpustate->add_latch = 0;
+ cpustate->branch_latch = 0;
+ cpustate->r = 0;
+ cpustate->o = 0;
+ cpustate->ram_address = 0;
+ cpustate->decode = F_ILL;
+ cpustate->opcode = 0;
+}
+
+
+/*
+The program counter is implemented using PRNG logic and gets incremented as follows:
+
+00, 01, 03, 07, 0F, 1F, 3F, 3E,
+3D, 3B, 37, 2F, 1E, 3C, 39, 33
+27, 0E, 1D, 3A, 35, 2B, 16, 2C,
+18, 30, 21, 02, 05, 0B, 17, 2E,
+1C, 38, 31, 23, 06, 0D, 1B, 36,
+2D, 1A, 34, 29, 12, 24, 08, 11,
+22, 04, 09, 13, 26, 0C, 19, 32,
+25, 0A, 15, 2A, 14, 28, 10, 20
+
+There is also a strange address (AD) to location (LOC) mapping performed by the
+tms1000 family.
+
+From tms1000 family pdf:
+AD LOC
+000 000000 003 000011
+001 000001 004 000100
+003 000011 00C 001100
+007 000111 01C 011100
+00F 001111 03C 111100
+01F 011111 03F 111111
+03F 111111 03E 111110
+03E 111110 039 111001
+03D 111101 036 110110
+03B 111011 02E 101110
+037 110111 01E 011110
+02F 101111 03D 111101
+01E 011110 038 111000
+03C 111100 031 110001
+039 111001 026 100110
+033 110011 00E 001110
+027 100111 01D 011101
+00E 001110 03B 111011
+01D 011101 037 110111
+03A 111010 029 101001
+035 110101 016 010110
+02B 101011 02D 101101
+016 010110 018 011000
+02C 101100 032 110010
+018 011000 020 100000
+030 110000 001 000001
+021 100001 005 000101
+002 000010 00B 001011
+005 000101 014 010100
+00B 001011 02C 101100
+017 010111 01F 011111
+02E 101110 03A 111010
+01C 011100 030 110000
+038 111000 021 100001
+031 110001 006 000110
+023 100011 00D 001101
+006 000110 01B 011011
+00D 001101 034 110100
+01B 011011 02F 101111
+036 110110 019 011001
+02D 101101 035 110101
+01A 011010 028 101000
+034 110100 011 010001
+029 101001 025 100101
+012 010010 008 001000
+024 100100 012 010010
+008 001000 023 100011
+011 010001 007 000111
+022 100010 00A 001010
+004 000100 013 010011
+009 001001 024 100100
+013 010011 00F 001111
+026 100110 01A 011010
+00C 001100 033 110011
+019 011001 027 100111
+032 110010 009 001001
+025 100101 015 010101
+00A 001010 02B 101011
+015 010101 017 010111
+02A 101010 02A 101010
+014 010100 010 010000
+028 101000 022 100010
+010 010000 000 000000
+020 100000 002 000010
+
+The following formula seems to be used to decode a program counter
+into a rom address:
+location{5:2} = pc{3:0}
+location{1:0} = ( pc{5:4} == 00 && pc{0} == 0 ) => 11
+ ( pc{5:4} == 00 && pc{0} == 1 ) => 00
+ ( pc{5:4} == 01 && pc{0} == 0 ) => 00
+ ( pc{5:4} == 01 && pc{0} == 1 ) => 11
+ ( pc{5:4} == 10 && pc{0} == 0 ) => 10
+ ( pc{5:4} == 10 && pc{0} == 1 ) => 01
+ ( pc{5:4} == 11 && pc{0} == 0 ) => 01
+ ( pc{5:4} == 11 && pc{0} == 1 ) => 10
+
+*/
+static const UINT8 tms1000_next_pc[64] = {
+ 0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F,
+ 0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, 0x2E, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C, 0x3F,
+ 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E,
+ 0x21, 0x23, 0x25, 0x27, 0x29, 0x2B, 0x2D, 0x2F, 0x31, 0x33, 0x35, 0x37, 0x39, 0x3B, 0x3D, 0x3E,
+};
+
+/* emulator for the program counter increment on the tms0980/tmc0980 mcu;
+ see patent 4064554 figure 19 (on page 13) for an explanation of feedback:
+
+ nand324 = NAND of PC0 through pc4, i.e. output is true if ((pc&0x1f) != 0x1f)
+ nand323 = NAND of pc5, pc6 and nand324
+ i.e. output is true, if ((pc&0x1f)==0x1f) || pc5 is 0 || pc 6 is 0
+ or321 = OR of pc5 and pc6, i.e. output is true if ((pc&0x60) != 0)
+ nand322 = NAND of pc0 through pc5 plus /pc6,
+ i.e. output is true if (pc != 0x3f)
+ nand325 = nand pf nand323, or321 and nand322
+ This one is complex:
+ / or321 means if pc&0x60 is zero, output MUST be true
+ \ nand323 means if (pc&0x60=0x60) && (pc&0x1f != 0x1f), output MUST be true
+ nand322 means if pc = 0x3f, output MUST be true
+ hence, nand325 is if pc = 0x7f, false. if pc = 0x3f, true. if pc&0x60 is zero OR pc&0x60 is 0x60, true. otherwise, false.
+
+ tms0980_nect_pc below implements an indentical function to this in a somewhat more elegant way.
+*/
+INLINE void tms0980_next_pc( tms0980_state *cpustate )
+{
+ if ( cpustate->byte_size > 8 )
+ {
+ UINT8 xorval = ( cpustate->pc & 0x3F ) == 0x3F ? 1 : 0;
+ UINT8 new_bit = ( ( cpustate->pc ^ ( cpustate->pc << 1 ) ) & 0x40 ) ? xorval : 1 - xorval;
+
+ cpustate->pc = ( cpustate->pc << 1 ) | new_bit;
+ }
+ else
+ {
+ cpustate->pc = tms1000_next_pc[ cpustate->pc & 0x3f ];
+ }
+}
+
+
+static const UINT8 tms1000_pc_decode[64] =
+{
+ 0x03, 0x04, 0x0B, 0x0C, 0x13, 0x14, 0x1B, 0x1C,
+ 0x23, 0x24, 0x2B, 0x2C, 0x33, 0x34, 0x3B, 0x3C,
+ 0x00, 0x07, 0x08, 0x0F, 0x10, 0x17, 0x18, 0x1F,
+ 0x20, 0x27, 0x28, 0x2F, 0x30, 0x37, 0x38, 0x3F,
+ 0x02, 0x05, 0x0A, 0x0D, 0x12, 0x15, 0x1A, 0x1D,
+ 0x22, 0x25, 0x2A, 0x2D, 0x32, 0x35, 0x3A, 0x3D,
+ 0x01, 0x06, 0x09, 0x0E, 0x11, 0x16, 0x19, 0x1E,
+ 0x21, 0x26, 0x29, 0x2E, 0x31, 0x36, 0x39, 0x3E
+};
+
+
+static void tms0980_set_cki_bus( device_t *device )
+{
+ tms0980_state *cpustate = get_safe_token( device );
+
+ switch( cpustate->opcode & 0x1F8 )
+ {
+ case 0x008:
+ if ( cpustate->config->read_k )
+ {
+ cpustate->cki_bus = cpustate->config->read_k( device, 0 );
+ }
+ else
+ {
+ cpustate->cki_bus = 0x0F;
+ }
+ break;
+ case 0x020: case 0x028:
+ cpustate->cki_bus = 0;
+ break;
+ case 0x030: case 0x038:
+ cpustate->cki_bus = tms0980_nbit_value[ cpustate->opcode & 0x03 ];
+ break;
+ case 0x000:
+ case 0x040: case 0x048:
+ case 0x050: case 0x058:
+ case 0x060: case 0x068:
+ case 0x070: case 0x078:
+ case 0x080: case 0x088:
+ case 0x090: case 0x098:
+ case 0x0c0: case 0x0c8:
+ case 0x0d0: case 0x0d8:
+ case 0x0e0: case 0x0e8:
+ case 0x0f0: case 0x0f8:
+ cpustate->cki_bus = tms0980_c4_value[ cpustate->opcode & 0x0F ];
+ break;
+ default:
+ cpustate->cki_bus = 0x0F;
+ break;
+ }
+}
+
+
+static CPU_EXECUTE( tms0980 )
+{
+ tms0980_state *cpustate = get_safe_token( device );
+
+ do
+ {
+// debugger_instruction_hook( device, ( ( cpustate->pa << cpustate->pc_size ) | cpustate->pc ) << 1 );
+ cpustate->icount--;
+ switch( cpustate->subcycle )
+ {
+ case 0:
+ /* fetch: rom address 0 */
+ /* execute: read ram, alu input, execute br/call, k input valid */
+ tms0980_set_cki_bus( device );
+ cpustate->ram_data = cpustate->data->read_byte( cpustate->ram_address );
+ cpustate->status = 1;
+ cpustate->p = 0;
+ cpustate->n = 0;
+ cpustate->carry_in = 0;
+ break;
+ case 1:
+ /* fetch: rom address 1 */
+ if ( cpustate->pc_size == 6 )
+ cpustate->rom_address = ( cpustate->pa << 6 ) | tms1000_pc_decode[ cpustate->pc ];
+ else
+ cpustate->rom_address = ( cpustate->pa << 7 ) | cpustate->pc;
+ /* execute: k input valid */
+ if ( cpustate->decode & MICRO_MASK )
+ {
+ /* Check N inputs */
+ if ( cpustate->decode & ( M_15TN | M_ATN | M_CKN | M_MTN | M_NATN ) )
+ {
+ cpustate->n = 0;
+ if ( cpustate->decode & M_15TN )
+ {
+ cpustate->n |= 0x0F;
+ }
+ if ( cpustate->decode & M_ATN )
+ {
+ cpustate->n |= cpustate->a;
+ }
+ if ( cpustate->decode & M_CKN )
+ {
+ cpustate->n |= cpustate->cki_bus;
+ }
+ if ( cpustate->decode & M_MTN )
+ {
+ cpustate->n |= cpustate->ram_data;
+ }
+ if ( cpustate->decode & M_NATN )
+ {
+ cpustate->n |= ( ( ~cpustate->a ) & 0x0F );
+ }
+ }
+
+
+ /* Check P inputs */
+ if ( cpustate->decode & ( M_CKP | M_DMTP | M_MTP | M_NDMTP | M_YTP ) )
+ {
+ cpustate->p = 0;
+ if ( cpustate->decode & M_CKP )
+ {
+ cpustate->p |= cpustate->cki_bus;
+ }
+ if ( cpustate->decode & M_DMTP )
+ {
+ cpustate->p |= cpustate->dam;
+ }
+ if ( cpustate->decode & M_MTP )
+ {
+ cpustate->p |= cpustate->ram_data;
+ }
+ if ( cpustate->decode & M_NDMTP )
+ {
+ cpustate->p |= ( ( ~cpustate->dam ) & 0x0F );
+ }
+ if ( cpustate->decode & M_YTP )
+ {
+ cpustate->p |= cpustate->y;
+ }
+ }
+
+ /* Carry In input */
+ if ( cpustate->decode & M_CIN )
+ {
+ cpustate->carry_in = 1;
+ }
+ }
+ break;
+ case 2:
+ /* fetch: nothing */
+ /* execute: write ram */
+ /* perform adder logic */
+ cpustate->adder_result = cpustate->p + cpustate->n + cpustate->carry_in;
+ if ( cpustate->decode & MICRO_MASK )
+ {
+ if ( cpustate->decode & M_NE )
+ {
+ if ( cpustate->n == cpustate->p )
+ {
+ cpustate->status = 0;
+ }
+ }
+ if ( cpustate->decode & M_C8 )
+ {
+ cpustate->status = cpustate->adder_result >> 4;
+ }
+ if ( cpustate->decode & M_STO )
+ {
+ cpustate->data->write_byte( cpustate->ram_address, cpustate->a );
+ }
+ if ( cpustate->decode & M_CKM )
+ {
+ cpustate->data->write_byte( cpustate->ram_address, cpustate->cki_bus );
+ }
+ }
+ else
+ {
+ if ( cpustate->decode & F_SBIT )
+ {
+ cpustate->data->write_byte( cpustate->ram_address, cpustate->ram_data | tms0980_bit_value[ cpustate->opcode & 0x03 ] );
+ }
+ if ( cpustate->decode & F_RBIT )
+ {
+ cpustate->data->write_byte( cpustate->ram_address, cpustate->ram_data & tms0980_nbit_value[ cpustate->opcode & 0x03 ] );
+ }
+ if ( cpustate->decode & F_SETR )
+ {
+ cpustate->r = cpustate->r | ( 1 << cpustate->y );
+ if ( cpustate->config->write_r )
+ {
+ cpustate->config->write_r( device, 0, cpustate->r & cpustate->r_mask, 0xffff );
+ }
+ }
+ if ( cpustate->decode & F_RSTR )
+ {
+ cpustate->r = cpustate->r & ( ~( 1 << cpustate->y ) );
+ if ( cpustate->config->write_r )
+ {
+ cpustate->config->write_r( device, 0, cpustate->r & cpustate->r_mask, 0xffff );
+ }
+ }
+ if ( cpustate->decode & F_TDO )
+ {
+ int i = 0;
+
+ /* Calculate O-outputs based on status latch, A, and the output PLA configuration */
+ cpustate->o = 0;
+ for ( i = 0; i < 20; i++ )
+ {
+ if ( ( ( cpustate->status_latch << 4 ) | cpustate->a ) == cpustate->config->o_pla[i].value )
+ {
+ cpustate->o = cpustate->config->o_pla[i].output;
+ }
+ }
+
+ if ( cpustate->config->write_o )
+ {
+ cpustate->config->write_o( device, 0, cpustate->o & cpustate->o_mask, 0xffff );
+ }
+ }
+ if ( cpustate->decode & F_CLO )
+ {
+ cpustate->o = 0;
+ if ( cpustate->config->write_o )
+ {
+ cpustate->config->write_o( device, 0, cpustate->o & cpustate->o_mask, 0xffff );
+ }
+ }
+ if ( cpustate->decode & F_LDX )
+ {
+ cpustate->x = tms0980_c2_value[ cpustate->opcode & 0x03 ];
+ }
+ if ( cpustate->decode & F_COMX )
+ {
+ cpustate->x = cpustate->x ^ 0x03;
+ }
+ if ( cpustate->decode & F_COMC )
+ {
+ cpustate->cb = cpustate->cb ^ 0x01;
+ }
+ if ( cpustate->decode & F_LDP )
+ {
+ cpustate->pb = tms0980_c4_value[ cpustate->opcode & 0x0F ];
+ }
+ if ( cpustate->decode & F_REAC )
+ {
+ cpustate->special_status = 0;
+ }
+ if ( cpustate->decode & F_SEAC )
+ {
+ cpustate->special_status = 1;
+ }
+ if ( cpustate->decode == F_SAL )
+ {
+ cpustate->add_latch = 1;
+ }
+ if ( cpustate->decode == F_SBL )
+ {
+ cpustate->branch_latch = 1;
+ }
+ }
+ break;
+ case 3:
+ /* fetch: fetch, update pc, ram address */
+ /* execute: register store */
+ break;
+ case 4:
+ /* execute: register store */
+ if ( cpustate->decode & MICRO_MASK )
+ {
+ if ( cpustate->decode & M_AUTA )
+ {
+ cpustate->a = cpustate->adder_result & 0x0F;
+ }
+ if ( cpustate->decode & M_AUTY )
+ {
+ cpustate->y = cpustate->adder_result & 0x0F;
+ }
+ if ( cpustate->decode & M_STSL )
+ {
+ cpustate->status_latch = cpustate->status;
+ }
+ }
+ /* fetch: fetch, update pc, ram address */
+ if ( cpustate->byte_size > 8 )
+ {
+ debugger_instruction_hook( device, cpustate->rom_address << 1 );
+ cpustate->opcode = cpustate->program->read_word( cpustate->rom_address << 1 ) & 0x1FF;
+ }
+ else
+ {
+ debugger_instruction_hook( device, cpustate->rom_address );
+ cpustate->opcode = cpustate->program->read_word( cpustate->rom_address ) & 0xFF;
+ }
+ tms0980_next_pc( cpustate );
+ if (LOG)
+ logerror( "tms0980: read opcode %04x from %04x. Set pc to %04x\n", cpustate->opcode, cpustate->rom_address, cpustate->pc );
+
+ /* ram address */
+ cpustate->ram_address = ( cpustate->x << 4 ) | cpustate->y;
+ break;
+ case 5:
+ /* fetch: instruction decode */
+ cpustate->decode = cpustate->decode_table[ cpustate->opcode ];
+ /* execute: execute br/call */
+ if ( cpustate->status )
+ {
+ if ( cpustate->decode == F_BR )
+ {
+ if ( cpustate->call_latch == 0 )
+ {
+ cpustate->pa = cpustate->pb;
+ }
+ cpustate->pc = cpustate->opcode & ( ( 1 << cpustate->pc_size ) - 1 );
+ }
+ if ( cpustate->decode == F_CALL )
+ {
+ UINT8 t = cpustate->pa;
+ if ( cpustate->call_latch == 0 )
+ {
+ cpustate->sr = cpustate->pc;
+ cpustate->call_latch = 1;
+ cpustate->pa = cpustate->pb;
+ }
+ cpustate->pb = t;
+ cpustate->pc = cpustate->opcode & ( ( 1 << cpustate->pc_size ) - 1 );
+ }
+ }
+ if ( cpustate->decode == F_RETN )
+ {
+ if ( cpustate->call_latch == 1 )
+ {
+ cpustate->pc = cpustate->sr;
+ cpustate->call_latch = 0;
+ }
+ cpustate->add_latch = 0;
+ cpustate->pa = cpustate->pb;
+ } else {
+ cpustate->branch_latch = 0;
+ }
+ break;
+ }
+ cpustate->subcycle = ( cpustate->subcycle + 1 ) % 6;
+ } while( cpustate->icount > 0 );
+}
+
+
+static CPU_SET_INFO( tms0980 )
+{
+ tms0980_state *cpustate = get_safe_token( device );
+
+ switch( state )
+ {
+ case CPUINFO_INT_PC: cpustate->pc = ( info->i >> 1 ) & 0x7f; cpustate->pa = info->i >> 8; break;
+ case CPUINFO_INT_REGISTER + TMS0980_PC: cpustate->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS0980_SR: cpustate->sr = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS0980_PA: cpustate->pa = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS0980_PB: cpustate->pb = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS0980_A: cpustate->a = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS0980_X: cpustate->x = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS0980_Y: cpustate->y = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS0980_STATUS: cpustate->status = info->i; break;
+ }
+}
+
+
+static CPU_GET_INFO( tms_generic )
+{
+ tms0980_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch(state)
+ {
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(tms0980_state); break;
+ case CPUINFO_INT_INPUT_LINES: 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_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 6; break;
+
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 8 /* 4 */; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = ( ( cpustate->prev_pa << 7 ) | cpustate->prev_pc ) << 1; break;
+ case CPUINFO_INT_PC: info->i = ( ( cpustate->pa << 7 ) | cpustate->pc ) << 1; break;
+ case CPUINFO_INT_SP: info->i = 0xFFFF; break;
+ case CPUINFO_INT_REGISTER + TMS0980_PC: info->i = cpustate->pc; break;
+ case CPUINFO_INT_REGISTER + TMS0980_SR: info->i = cpustate->sr; break;
+ case CPUINFO_INT_REGISTER + TMS0980_PA: info->i = cpustate->pa; break;
+ case CPUINFO_INT_REGISTER + TMS0980_PB: info->i = cpustate->pb; break;
+ case CPUINFO_INT_REGISTER + TMS0980_A: info->i = cpustate->a; break;
+ case CPUINFO_INT_REGISTER + TMS0980_X: info->i = cpustate->x; break;
+ case CPUINFO_INT_REGISTER + TMS0980_Y: info->i = cpustate->y; break;
+ case CPUINFO_INT_REGISTER + TMS0980_STATUS: info->i = cpustate->status; break;
+
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME( tms0980 ); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME( tms0980 ); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME( tms0980 ); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME( tms0980 ); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ case DEVINFO_STR_FAMILY: strcpy( info->s, "Texas Instruments TMS0980/TMS1000" ); break;
+ case DEVINFO_STR_VERSION: strcpy( info->s, "0.2" ); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy( info->s, __FILE__ ); break;
+ case DEVINFO_STR_CREDITS: strcpy( info->s, "Copyright the MESS and MAME teams" ); break;
+
+ case CPUINFO_STR_FLAGS: strcpy( info->s, "N/A" ); break;
+
+ case CPUINFO_STR_REGISTER + TMS0980_PC: sprintf( info->s, "PC:%02X", cpustate->pc ); break;
+ case CPUINFO_STR_REGISTER + TMS0980_SR: sprintf( info->s, "SR:%01X", cpustate->sr ); break;
+ case CPUINFO_STR_REGISTER + TMS0980_PA: sprintf( info->s, "PA:%01X", cpustate->pa ); break;
+ case CPUINFO_STR_REGISTER + TMS0980_PB: sprintf( info->s, "PB:%01X", cpustate->pb ); break;
+ case CPUINFO_STR_REGISTER + TMS0980_A: sprintf( info->s, "A:%01X", cpustate->a ); break;
+ case CPUINFO_STR_REGISTER + TMS0980_X: sprintf( info->s, "X:%01X", cpustate->x ); break;
+ case CPUINFO_STR_REGISTER + TMS0980_Y: sprintf( info->s, "Y:%01X", cpustate->y ); break;
+ case CPUINFO_STR_REGISTER + TMS0980_STATUS: sprintf( info->s, "STATUS:%01X", cpustate->status ); break;
+
+ }
+}
+
+
+CPU_GET_INFO( tms0980 )
+{
+ tms0980_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch(state)
+ {
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 2; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16 /* 9 */; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 12; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 7; break;
+ case CPUINFO_INT_PREVIOUSPC: info->i = ( ( cpustate->prev_pa << 7 ) | cpustate->prev_pc ) << 1; break;
+ case CPUINFO_INT_PC: info->i = ( ( cpustate->pa << 7 ) | cpustate->pc ) << 1; break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME( tms0980_internal_rom ); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME( tms0980_internal_ram ); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME( tms0980 ); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME( tms0980 ); break;
+ case DEVINFO_STR_NAME: strcpy( info->s, "TMS0980" ); break;
+ default: CPU_GET_INFO_CALL( tms_generic );
+ }
+}
+
+
+CPU_GET_INFO( tms1000 )
+{
+ tms0980_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch(state)
+ {
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 1; 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_WIDTH + AS_DATA: info->i = 6; break;
+ case CPUINFO_INT_PREVIOUSPC: info->i = ( cpustate->prev_pa << 6 ) | tms1000_pc_decode[ cpustate->prev_pc ]; break;
+ case CPUINFO_INT_PC: info->i = ( cpustate->pa << 6 ) | tms1000_pc_decode[ cpustate->pc ]; break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME( program_10bit_8 ); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME( data_6bit ); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME( tms1000 ); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME( tms1000 ); break;
+ case DEVINFO_STR_NAME: strcpy( info->s, "TMS1000" ); break;
+ default: CPU_GET_INFO_CALL( tms_generic );
+ }
+}
+
+
+CPU_GET_INFO( tms1070 )
+{
+ switch(state)
+ {
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME( tms1070 ); break;
+ case DEVINFO_STR_NAME: strcpy( info->s, "TMS1070" ); break;
+ default: CPU_GET_INFO_CALL( tms1000 );
+ }
+}
+
+
+CPU_GET_INFO( tms1200 )
+{
+ switch(state)
+ {
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME( tms1200 ); break;
+ case DEVINFO_STR_NAME: strcpy( info->s, "TMS1200" ); break;
+ default: CPU_GET_INFO_CALL( tms1000 );
+ }
+}
+
+
+CPU_GET_INFO( tms1270 )
+{
+ switch(state)
+ {
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME( tms1270 ); break;
+ case DEVINFO_STR_NAME: strcpy( info->s, "TMS1270" ); break;
+ default: CPU_GET_INFO_CALL( tms1000 );
+ }
+}
+
+
+
+CPU_GET_INFO( tms1100 )
+{
+ tms0980_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch(state)
+ {
+ 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_WIDTH + AS_DATA: info->i = 7; break;
+ case CPUINFO_INT_PREVIOUSPC: info->i = ( cpustate->prev_pa << 6 ) | tms1000_pc_decode[ cpustate->prev_pc ]; break;
+ case CPUINFO_INT_PC: info->i = ( cpustate->pa << 6 ) | tms1000_pc_decode[ cpustate->pc ]; break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME( program_11bit_8 ); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME( data_7bit ); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME( tms1100 ); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME( tms1100 ); break;
+ case DEVINFO_STR_NAME: strcpy( info->s, "TMS1100" ); break;
+ default: CPU_GET_INFO_CALL( tms_generic );
+ }
+}
+
+
+CPU_GET_INFO( tms1300 )
+{
+ switch(state)
+ {
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME( tms1300 ); break;
+ case DEVINFO_STR_NAME: strcpy( info->s, "TMS1300" ); break;
+ default: CPU_GET_INFO_CALL( tms1100 );
+ }
+}
+
+
+DEFINE_LEGACY_CPU_DEVICE(TMS0980, tms0980);
+
+DEFINE_LEGACY_CPU_DEVICE(TMS1000, tms1000);
+DEFINE_LEGACY_CPU_DEVICE(TMS1070, tms1070);
+DEFINE_LEGACY_CPU_DEVICE(TMS1100, tms1100);
+DEFINE_LEGACY_CPU_DEVICE(TMS1200, tms1200);
+DEFINE_LEGACY_CPU_DEVICE(TMS1270, tms1270);
+DEFINE_LEGACY_CPU_DEVICE(TMS1300, tms1300);
diff --git a/trunk/src/emu/cpu/tms0980/tms0980.h b/trunk/src/emu/cpu/tms0980/tms0980.h
new file mode 100644
index 00000000000..a0ac1547df2
--- /dev/null
+++ b/trunk/src/emu/cpu/tms0980/tms0980.h
@@ -0,0 +1,42 @@
+#ifndef _TMS0980_H_
+#define _TMS0980_H_
+
+
+/* Registers */
+enum {
+ TMS0980_PC=1, TMS0980_SR, TMS0980_PA, TMS0980_PB,
+ TMS0980_A, TMS0980_X, TMS0980_Y, TMS0980_STATUS
+};
+
+
+typedef struct _tms0980_config tms0980_config;
+struct _tms0980_config {
+ /* O-output PLA configuration */
+ struct {
+ UINT8 value;
+ UINT16 output;
+ } o_pla[20];
+ read8_device_func read_k;
+ write16_device_func write_o; /* tms1270 has 10 O-outputs */
+ write16_device_func write_r;
+};
+
+
+/* 9-bit family */
+DECLARE_LEGACY_CPU_DEVICE(TMS0980, tms0980);
+
+extern CPU_DISASSEMBLE( tms0980 );
+
+/* 8-bit family */
+DECLARE_LEGACY_CPU_DEVICE(TMS1000, tms1000);
+DECLARE_LEGACY_CPU_DEVICE(TMS1070, tms1070);
+DECLARE_LEGACY_CPU_DEVICE(TMS1100, tms1100);
+DECLARE_LEGACY_CPU_DEVICE(TMS1200, tms1200);
+DECLARE_LEGACY_CPU_DEVICE(TMS1270, tms1270);
+DECLARE_LEGACY_CPU_DEVICE(TMS1300, tms1300);
+
+extern CPU_DISASSEMBLE( tms1000 );
+extern CPU_DISASSEMBLE( tms1100 );
+
+#endif /* _TMS0980_H_ */
+
diff --git a/trunk/src/emu/cpu/tms0980/tms0980d.c b/trunk/src/emu/cpu/tms0980/tms0980d.c
new file mode 100644
index 00000000000..18fe46d9c87
--- /dev/null
+++ b/trunk/src/emu/cpu/tms0980/tms0980d.c
@@ -0,0 +1,345 @@
+/*******************************************************************
+
+tms0980d.c
+TMS0980 disassembly
+
+*******************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "tms0980.h"
+
+
+#define _OVER DASMFLAG_STEP_OVER
+#define _OUT DASMFLAG_STEP_OUT
+
+
+enum e_mnemonics {
+ zA10AAC=0, zA6AAC, zA8AAC, zAC1AC, zACACC, zACNAA, zALEC, zALEM, zAMAAC, zBRANCH, zCALL, zCCLA,
+ zCLA, zCLO, zCOMC, zCOMX, zCOMX8, zCPAIZ, zCTMDYN, zDAN, zDMAN, zDMEA, zDNAA,
+ zDYN, zIA, zIMAC, zIYC, zKNE, zKNEZ, zLDP, zLDX, zLDX4, zMNEA, zMNEZ,
+ zNDMEA, zOFF, zRBIT, zREAC, zRETN, zRSTR, zSAL, zSAMAN, zSBIT,
+ zSBL, zSEAC, zSETR, zTAM, zTAMACS, zTAMDYN, zTAMIY, zTAMIYC, zTAMZA,
+ zTAY, zTBIT, zTCMIY, zTCY, zTDO, zTKA, zTKM, zTMA,
+ zTMY, zTYA, zXDA, zXMA, zYMCY, zYNEA, zYNEC,
+ zILL
+};
+
+
+enum e_addressing {
+ zB0=0, zB2, zI2, zI4, zB7
+};
+
+
+static const char *const s_mnemonic[] = {
+ "a10aac", "a6aac", "a8aac", "ac1ac", "acacc", "acnaa", "alec", "alem", "amaac", "branch", "call", "ccla",
+ "cla", "clo", "comc", "comx", "comx8", "cpaiz", "ctmdyn", "dan", "dman", "dmea", "dnaa",
+ "dyn", "ia", "imac", "iyc", "kne", "knez", "ldp", "ldx", "ldx", "mnea", "mnez",
+ "ndmea", "off", "rbit", "reac", "retn", "rstr", "sal", "saman", "sbit",
+ "sbl", "seac", "setr", "tam", "tamacs", "tamdyn", "tamiy", "tamiyc", "tamza",
+ "tay", "tbit", "tcmiy", "tcy", "tdo", "tka", "tkm", "tma",
+ "tmy", "tya", "xda", "xma", "ymcy", "ynea", "ynec",
+ "illegal"
+};
+
+
+static const UINT32 s_flags[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, _OUT, 0, 0, 0, 0,
+ 0, 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 UINT8 s_addressing[] = {
+ zB0, zB0, zB0, zI4, zI4, zI4, zI4, zB0, zB0, zB7, zB7, zB0,
+ zB0, zB0, zB0, zB0, zB0, zB0, zB0, zB0, zB0, zB0, zB0,
+ zB0, zB0, zB0, zB0, zB0, zB0, zI4, zI2, zI4, zB0, zB0,
+ zB0, zB0, zB0, zB0, zB0, zB0, zB0, zB0, zB0,
+ zB0, zB0, zB0, zB0, zI4, zB0, zB0, zB0, zB2,
+ zB0, zB2, zI4, zI4, zB0, zB0, zB0, zB0,
+ zB0, zB0, zB0, zB0, zI4, zB0, zI4,
+ zB0
+};
+
+
+static const UINT8 tms0980_mnemonic[512] = {
+ /* 0x000 */
+ zCOMX, zALEM, zYNEA, zXMA, zDYN, zIYC, zCLA, zDMAN,
+ zTKA, zMNEA, zTKM, zILL, zILL, zSETR, zKNE, zILL,
+ /* 0x010 */
+ zDMEA, zDNAA, zCCLA, zNDMEA, zILL, zAMAAC, zILL, zILL,
+ zCTMDYN, zXDA, zILL, zILL, zILL, zILL, zILL, zILL,
+ /* 0x020 */
+ zTBIT, zTBIT, zTBIT, zTBIT, zILL, zILL, zILL, zILL,
+ zTAY, zTMA, zTMY, zTYA, zTAMDYN, zTAMIYC, zTAMZA, zTAM,
+ /* 0x030 */
+ zSAMAN, zCPAIZ, zIMAC, zMNEZ, zILL, zILL, zILL, zILL,
+ zTCY, zYNEC, zTCMIY, zACACC, zACNAA, zTAMACS, zALEC, zYMCY,
+ /* 0x040 */
+ zTCY, zTCY, zTCY, zTCY, zTCY, zTCY, zTCY, zTCY,
+ zTCY, zTCY, zTCY, zTCY, zTCY, zTCY, zTCY, zTCY,
+ /* 0x050 */
+ zYNEC, zYNEC, zYNEC, zYNEC, zYNEC, zYNEC, zYNEC, zYNEC,
+ zYNEC, zYNEC, zYNEC, zYNEC, zYNEC, zYNEC, zYNEC, zYNEC,
+ /* 0x060 */
+ zTCMIY, zTCMIY, zTCMIY, zTCMIY, zTCMIY, zTCMIY, zTCMIY, zTCMIY,
+ zTCMIY, zTCMIY, zTCMIY, zTCMIY, zTCMIY, zTCMIY, zTCMIY, zTCMIY,
+ /* 0x070 */
+ zACACC, zACACC, zACACC, zACACC, zACACC, zACACC, zACACC, zACACC,
+ zACACC, zACACC, zACACC, zACACC, zACACC, zACACC, zACACC, zACACC,
+ /* 0x080 */
+ zLDP, zLDP, zLDP, zLDP, zLDP, zLDP, zLDP, zLDP,
+ zLDP, zLDP, zLDP, zLDP, zLDP, zLDP, zLDP, zLDP,
+ /* 0x090 */
+ zLDX4, zLDX4, zLDX4, zLDX4, zLDX4, zLDX4, zLDX4, zLDX4,
+ zLDX4, zLDX4, zLDX4, zLDX4, zLDX4, zLDX4, zLDX4, zLDX4,
+ /* 0x0A0 */
+ zSBIT, zSBIT, zSBIT, zSBIT, zRBIT, zRBIT, zRBIT, zRBIT,
+ zILL, zILL, zILL, zILL, zILL, zILL, zILL, zILL,
+ /* 0x0B0 */
+ zTDO, zSAL, zCOMX8, zSBL, zREAC, zSEAC, zOFF, zILL,
+ zILL, zILL, zILL, zILL, zILL, zILL, zILL, zRETN,
+ /* 0x0C0 */
+ zACNAA, zACNAA, zACNAA, zACNAA, zACNAA, zACNAA, zACNAA, zACNAA,
+ zACNAA, zACNAA, zACNAA, zACNAA, zACNAA, zACNAA, zACNAA, zACNAA,
+ /* 0x0D0 */
+ zTAMACS, zTAMACS, zTAMACS, zTAMACS, zTAMACS, zTAMACS, zTAMACS, zTAMACS,
+ zTAMACS, zTAMACS, zTAMACS, zTAMACS, zTAMACS, zTAMACS, zTAMACS, zTAMACS,
+ /* 0x0E0 */
+ zALEC, zALEC, zALEC, zALEC, zALEC, zALEC, zALEC, zALEC,
+ zALEC, zALEC, zALEC, zALEC, zALEC, zALEC, zALEC, zALEC,
+ /* 0x0F0 */
+ zYMCY, zYMCY, zYMCY, zYMCY, zYMCY, zYMCY, zYMCY, zYMCY,
+ zYMCY, zYMCY, zYMCY, zYMCY, zYMCY, zYMCY, zYMCY, zYMCY,
+ /* 0x100 */
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ /* 0x180 */
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL
+};
+
+
+static const UINT8 tms1000_mnemonic[256] = {
+ /* 0x00 */
+ zCOMX, zA8AAC, zYNEA, zTAM, zTAMZA, zA10AAC, zA6AAC, zDAN,
+ zTKA, zKNEZ, zTDO, zCLO, zRSTR, zSETR, zIA, zRETN,
+ zLDP, zLDP, zLDP, zLDP, zLDP, zLDP, zLDP, zLDP,
+ zLDP, zLDP, zLDP, zLDP, zLDP, zLDP, zLDP, zLDP,
+ zTAMIY, zTMA, zTMY, zTYA, zTAY, zAMAAC, zMNEZ, zSAMAN,
+ zIMAC, zALEM, zDMAN, zIYC, zDYN, zCPAIZ, zXMA, zCLA,
+ zSBIT, zSBIT, zSBIT, zSBIT, zRBIT, zRBIT, zRBIT, zRBIT,
+ zTBIT, zTBIT, zTBIT, zTBIT, zLDX, zLDX, zLDX, zLDX,
+ /* 0x40 */
+ zTCY, zTCY, zTCY, zTCY, zTCY, zTCY, zTCY, zTCY,
+ zTCY, zTCY, zTCY, zTCY, zTCY, zTCY, zTCY, zTCY,
+ zYNEC, zYNEC, zYNEC, zYNEC, zYNEC, zYNEC, zYNEC, zYNEC,
+ zYNEC, zYNEC, zYNEC, zYNEC, zYNEC, zYNEC, zYNEC, zYNEC,
+ zTCMIY, zTCMIY, zTCMIY, zTCMIY, zTCMIY, zTCMIY, zTCMIY, zTCMIY,
+ zTCMIY, zTCMIY, zTCMIY, zTCMIY, zTCMIY, zTCMIY, zTCMIY, zTCMIY,
+ zALEC, zALEC, zALEC, zALEC, zALEC, zALEC, zALEC, zALEC,
+ zALEC, zALEC, zALEC, zALEC, zALEC, zALEC, zALEC, zALEC,
+ /* 0x80 */
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ /* 0xc0 */
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL
+};
+
+
+static const UINT8 tms1100_mnemonic[256] = {
+ /* 0x00 */
+ zMNEA, zALEM, zYNEA, zXMA, zDYN, zIYC, zAMAAC, zDMAN,
+ zTKA, zCOMX, zTDO, zCOMC, zRSTR, zSETR, zKNEZ, zRETN,
+ zLDP, zLDP, zLDP, zLDP, zLDP, zLDP, zLDP, zLDP,
+ zLDP, zLDP, zLDP, zLDP, zLDP, zLDP, zLDP, zLDP,
+ /* 0x20 */
+ zTAY, zTMA, zTMY, zTYA, zTAMDYN, zTAMIYC, zTAMZA, zTAM,
+ zLDX, zLDX, zLDX, zLDX, zLDX, zLDX, zLDX, zLDX,
+ zSBIT, zSBIT, zSBIT, zSBIT, zRBIT, zRBIT, zRBIT, zRBIT,
+ zTBIT, zTBIT, zTBIT, zTBIT, zSAMAN, zCPAIZ, zIMAC, zMNEZ,
+ /* 0x40 */
+ zTCY, zTCY, zTCY, zTCY, zTCY, zTCY, zTCY, zTCY,
+ zTCY, zTCY, zTCY, zTCY, zTCY, zTCY, zTCY, zTCY,
+ zYNEC, zYNEC, zYNEC, zYNEC, zYNEC, zYNEC, zYNEC, zYNEC,
+ zYNEC, zYNEC, zYNEC, zYNEC, zYNEC, zYNEC, zYNEC, zYNEC,
+ /* 0x60 */
+ zTCMIY, zTCMIY, zTCMIY, zTCMIY, zTCMIY, zTCMIY, zTCMIY, zTCMIY,
+ zTCMIY, zTCMIY, zTCMIY, zTCMIY, zTCMIY, zTCMIY, zTCMIY, zTCMIY,
+ zAC1AC, zAC1AC, zAC1AC, zAC1AC, zAC1AC, zAC1AC, zAC1AC, zAC1AC,
+ zAC1AC, zAC1AC, zAC1AC, zAC1AC, zAC1AC, zAC1AC, zAC1AC, zCLA,
+ /* 0x80 */
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH, zBRANCH,
+ /* 0xC0 */
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+ zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL, zCALL,
+};
+
+static const UINT8 tms0980_i2_value[4] =
+{
+ 0x00, 0x02, 0x01, 0x03
+};
+static const UINT8 tms0980_i4_value[16] =
+{
+ 0x00, 0x08, 0x04, 0x0C, 0x02, 0x0A, 0x06, 0x0E, 0x01, 0x09, 0x05, 0x0D, 0x03, 0x0B, 0x07, 0x0F
+};
+static const UINT8 tms0980_bit_value[4] = { 1, 4, 2, 8 };
+
+
+CPU_DISASSEMBLE( tms0980 ) {
+ char *dst = buffer;
+ UINT16 op, instr;
+ int pos = 0;
+
+ op = ( ( oprom[pos] << 8 ) | oprom[pos + 1] ) & 0x01FF;
+ pos += 2;
+
+ instr = tms0980_mnemonic[op];
+
+ dst += sprintf( dst, "%-8s ", s_mnemonic[instr] );
+
+ switch( s_addressing[instr] ) {
+ case zB0:
+ break;
+ case zB2:
+ dst += sprintf( dst, "#$%d", tms0980_bit_value[ op & 3 ] );
+ break;
+ case zI2:
+ dst += sprintf( dst, "#$%01X", tms0980_i2_value[ op & 0x03 ] );
+ break;
+ case zI4:
+ dst += sprintf( dst, "#$%01X", tms0980_i4_value[ op & 0x0F ] );
+ break;
+ case zB7:
+ dst += sprintf( dst, "#$%02X", ( op & 0x7F ) << 1 );
+ break;
+ }
+
+ return pos | s_flags[instr] | DASMFLAG_SUPPORTED;
+}
+
+
+CPU_DISASSEMBLE( tms1000 ) {
+ char *dst = buffer;
+ UINT8 op, instr;
+ int pos = 0;
+
+ op = oprom[pos];
+ pos += 1;
+
+ instr = tms1000_mnemonic[op];
+
+ dst += sprintf( dst, "%-8s ", s_mnemonic[instr] );
+
+ switch( s_addressing[instr] ) {
+ case zB0:
+ break;
+ case zB2:
+ dst += sprintf( dst, "#$%d", tms0980_bit_value[ op & 3 ] );
+ break;
+ case zI2:
+ dst += sprintf( dst, "#$%01X", tms0980_i2_value[ op & 0x03 ] );
+ break;
+ case zI4:
+ dst += sprintf( dst, "#$%01X", tms0980_i4_value[ op & 0x0F ] );
+ break;
+ case zB7:
+ dst += sprintf( dst, "#$%02X", ( op & 0x3F ) );
+ break;
+ }
+
+ return pos | s_flags[instr] | DASMFLAG_SUPPORTED;
+}
+
+
+CPU_DISASSEMBLE( tms1100 ) {
+ char *dst = buffer;
+ UINT8 op, instr;
+ int pos = 0;
+
+ op = oprom[pos];
+ pos += 1;
+
+ instr = tms1100_mnemonic[op];
+
+ dst += sprintf( dst, "%-8s ", s_mnemonic[instr] );
+
+ switch( s_addressing[instr] ) {
+ case zB0:
+ break;
+ case zB2:
+ dst += sprintf( dst, "#$%d", tms0980_bit_value[ op & 3 ] );
+ break;
+ case zI2:
+ dst += sprintf( dst, "#$%01X", tms0980_i2_value[ op & 0x03 ] );
+ break;
+ case zI4:
+ dst += sprintf( dst, "#$%01X", tms0980_i4_value[ op & 0x0F ] );
+ break;
+ case zB7:
+ dst += sprintf( dst, "#$%02X", ( op & 0x3F ) );
+ break;
+ }
+
+ return pos | s_flags[instr] | DASMFLAG_SUPPORTED;
+}
+
diff --git a/trunk/src/emu/cpu/tms32010/32010dsm.c b/trunk/src/emu/cpu/tms32010/32010dsm.c
new file mode 100644
index 00000000000..5aea3812eaf
--- /dev/null
+++ b/trunk/src/emu/cpu/tms32010/32010dsm.c
@@ -0,0 +1,336 @@
+ /**************************************************************************\
+ * Texas Instruments TMS32010 DSP Disassembler *
+ * *
+ * Copyright Tony La Porta *
+ * To be used with TMS32010 DSP Emulator engine. *
+ * You are not allowed to distribute this software commercially. *
+ * Written for the MAME project. *
+ * *
+ * Many thanks to those involved in the i8039 Disassembler *
+ * as this was based on it. *
+ * *
+ * *
+ * *
+ * A Memory address *
+ * B Branch Address for Branch instructions (Requires next opcode read) *
+ * D Immediate byte load *
+ * K Immediate bit load *
+ * W Immediate word load (Actually 13 bit) *
+ * M AR[x] register modification type (for indirect addressing) *
+ * N ARP register to change ARP pointer to (for indirect addressing) *
+ * P I/O port address number *
+ * R AR[R] register to use *
+ * S Shift ALU left *
+ * *
+ \**************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include <ctype.h>
+
+#include "tms32010.h"
+
+
+
+typedef unsigned char byte;
+typedef unsigned short int word;
+
+#define FMT(a,b) a, b
+#define PTRS_PER_FORMAT 2
+
+static const char *const arith[4] = { "*" , "*-" , "*+" , "??" } ;
+static const char *const nextar[4] = { ",AR0" , ",AR1" , "" , "" } ;
+
+
+static const char *const TMS32010Formats[] = {
+ FMT("0000ssss0aaaaaaa", "add %A%S"),
+ FMT("0000ssss10mmn00n", "add %M%S%N"),
+ FMT("0001ssss0aaaaaaa", "sub %A%S"),
+ FMT("0001ssss10mmn00n", "sub %M%S%N"),
+ FMT("0010ssss0aaaaaaa", "lac %A%S"),
+ FMT("0010ssss10mmn00n", "lac %M%S%N"),
+ FMT("0011000r0aaaaaaa", "sar %R,%A"),
+ FMT("0011000r10mmn00n", "sar %R%M%N"),
+ FMT("0011100r0aaaaaaa", "lar %R,%A"),
+ FMT("0011100r10mmn00n", "lar %R%M%N"),
+ FMT("01000ppp0aaaaaaa", "in %A,%P"),
+ FMT("01000ppp10mmn00n", "in %M,%P%N"),
+ FMT("01001ppp0aaaaaaa", "out %A,%P"),
+ FMT("01001ppp10mmn00n", "out %M,%P%N"),
+ FMT("01010sss0aaaaaaa", "sacl %A"), /* This instruction has a shift but */
+ FMT("01010sss10mmn00n", "sacl %M%N"), /* is documented as not performed */
+ FMT("01011sss0aaaaaaa", "sach %A%S"),
+ FMT("01011sss10mmn00n", "sach %M%S%N"),
+ FMT("011000000aaaaaaa", "addh %A"),
+ FMT("0110000010mmn00n", "addh %M%N"),
+ FMT("011000010aaaaaaa", "adds %A"),
+ FMT("0110000110mmn00n", "adds %M%N"),
+ FMT("011000100aaaaaaa", "subh %A"),
+ FMT("0110001010mmn00n", "subh %M%N"),
+ FMT("011000110aaaaaaa", "subs %A"),
+ FMT("0110001110mmn00n", "subs %M%N"),
+ FMT("011001000aaaaaaa", "subc %A"),
+ FMT("0110010010mmn00n", "subc %M%N"),
+ FMT("011001010aaaaaaa", "zalh %A"),
+ FMT("0110010110mmn00n", "zalh %M%N"),
+ FMT("011001100aaaaaaa", "zals %A"),
+ FMT("0110011010mmn00n", "zals %M%N"),
+ FMT("011001110aaaaaaa", "tblr %A"),
+ FMT("0110011110mmn00n", "tblr %M%N"),
+ FMT("011010001000000k", "larp %K"),
+ FMT("011010000aaaaaaa", "mar %A"), /* Actually this is executed as a NOP */
+/* FMT("0110100010mmn00n", "mar %M%N"), */
+/* MAR indirect has been expanded out to all its variations because one of */
+/* its opcodes is the same as LARP (actually performs the same function) */
+
+ FMT("0110100010001000", "mar *"),
+ FMT("0110100010001001", "mar *"),
+ FMT("0110100010010000", "mar *-,AR0"),
+ FMT("0110100010010001", "mar *-,AR1"),
+ FMT("0110100010011000", "mar *-"),
+ FMT("0110100010011001", "mar *-"),
+ FMT("0110100010100000", "mar *+,AR0"),
+ FMT("0110100010100001", "mar *+,AR1"),
+ FMT("0110100010101000", "mar *+"),
+ FMT("0110100010101001", "mar *+"),
+ FMT("0110100010110000", "mar ??,AR0"),
+ FMT("0110100010110001", "mar ??,AR1"),
+ FMT("0110100010111000", "mar ??"),
+ FMT("0110100010111001", "mar ??"),
+
+ FMT("011010010aaaaaaa", "dmov %A"),
+ FMT("0110100110mmn00n", "dmov %M%N"),
+ FMT("011010100aaaaaaa", "lt %A"),
+ FMT("0110101010mmn00n", "lt %M%N"),
+ FMT("011010110aaaaaaa", "ltd %A"),
+ FMT("0110101110mmn00n", "ltd %M%N"),
+ FMT("011011000aaaaaaa", "lta %A"),
+ FMT("0110110010mmn00n", "lta %M%N"),
+ FMT("011011010aaaaaaa", "mpy %A"),
+ FMT("0110110110mmn00n", "mpy %M%N"),
+ FMT("011011100000000k", "ldpk %K"),
+ FMT("011011110aaaaaaa", "ldp %A"),
+ FMT("0110111110mmn00n", "ldp %M%N"),
+ FMT("0111000rdddddddd", "lark %R,%D"),
+ FMT("011110000aaaaaaa", "xor %A"),
+ FMT("0111100010mmn00n", "xor %M%N"),
+ FMT("011110010aaaaaaa", "and %A"),
+ FMT("0111100110mmn00n", "and %M%N"),
+ FMT("011110100aaaaaaa", "or %A"),
+ FMT("0111101010mmn00n", "or %M%N"),
+ FMT("011110110aaaaaaa", "lst %A"),
+ FMT("0111101110mmn00n", "lst %M%N"),
+ FMT("011111000aaaaaaa", "sst %A"),
+ FMT("0111110010mmn00n", "sst %M%N"),
+ FMT("011111010aaaaaaa", "tblw %A"),
+ FMT("0111110110mmn00n", "tblw %M%N"),
+ FMT("01111110dddddddd", "lack %D"),
+ FMT("0111111110000000", "nop"), /* 7F80 */
+ FMT("0111111110000001", "dint"),
+ FMT("0111111110000010", "eint"),
+ FMT("0111111110001000", "abs"), /* 7F88 */
+ FMT("0111111110001001", "zac"),
+ FMT("0111111110001010", "rovm"),
+ FMT("0111111110001011", "sovm"),
+ FMT("0111111110001100", "cala"),
+ FMT("0111111110001101", "ret"),
+ FMT("0111111110001110", "pac"),
+ FMT("0111111110001111", "apac"),
+ FMT("0111111110010000", "spac"),
+ FMT("0111111110011100", "push"),
+ FMT("0111111110011101", "pop"), /* 7F9D */
+ FMT("100wwwwwwwwwwwww", "mpyk %W"),
+ FMT("1111010000000000bbbbbbbbbbbbbbbb", "banz %B"),
+ FMT("1111010100000000bbbbbbbbbbbbbbbb", "bv %B"),
+ FMT("1111011000000000bbbbbbbbbbbbbbbb", "bioz %B"),
+ FMT("1111100000000000bbbbbbbbbbbbbbbb", "call %B"),
+ FMT("1111100100000000bbbbbbbbbbbbbbbb", "b %B"),
+ FMT("1111101000000000bbbbbbbbbbbbbbbb", "blz %B"),
+ FMT("1111101100000000bbbbbbbbbbbbbbbb", "blez %B"),
+ FMT("1111110000000000bbbbbbbbbbbbbbbb", "bgz %B"),
+ FMT("1111110100000000bbbbbbbbbbbbbbbb", "bgez %B"),
+ FMT("1111111000000000bbbbbbbbbbbbbbbb", "bnz %B"),
+ FMT("1111111100000000bbbbbbbbbbbbbbbb", "bz %B"),
+ NULL
+};
+
+#define MAX_OPS (((sizeof(TMS32010Formats) / sizeof(TMS32010Formats[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 */
+} TMS32010Opcode;
+
+static TMS32010Opcode Op[MAX_OPS+1];
+static int OpInizialized = 0;
+
+static void InitDasm32010(void)
+{
+ const char *p;
+ const char *const *ops;
+ word mask, bits;
+ int bit;
+ int i;
+
+ ops = TMS32010Formats; i = 0;
+ while (*ops)
+ {
+ p = *ops;
+ mask = 0; bits = 0; bit = 15;
+ 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 'k':
+ case 'm':
+ case 'n':
+ case 'p':
+ case 'r':
+ case 's':
+ case 'w':
+ 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( tms32010 )
+{
+ UINT32 flags = 0;
+ int a, b, d, k, m, n, p, r, s, w; /* 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 */
+
+ if (!OpInizialized) InitDasm32010();
+
+ op = -1; /* no matching opcode */
+ code = (oprom[0] << 8) | oprom[1];
+ 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 *(invalid op)", code);
+ return cnt | DASMFLAG_SUPPORTED;
+ }
+ //buffertmp = buffer;
+ if (Op[op].extcode)
+ {
+ bit = 31;
+ code <<= 16;
+ code |= (opram[2] << 8) | opram[3];
+ cnt++;
+ }
+ else
+ {
+ bit = 15;
+ }
+
+ /* shift out operands */
+ cp = Op[op].parse;
+ a = b = d = k = m = n = p = r = s = w = 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 'k': k <<=1; k |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 'm': m <<=1; m |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 'n': n <<=1; n |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 'p': p <<=1; p |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 'r': r <<=1; r |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 's': s <<=1; s |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 'w': w <<=1; w |= ((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, "cal", 3))
+ flags = DASMFLAG_STEP_OVER;
+ else if (!strncmp(cp, "ret", 3))
+ flags = DASMFLAG_STEP_OUT;
+
+ while (*cp)
+ {
+ if (*cp == '%')
+ {
+ char num[20], *q;
+ cp++;
+ switch (*cp++)
+ {
+ case 'A': sprintf(num,"%02Xh",a); break; // was $%02X
+ case 'B': sprintf(num,"%04Xh",b); break; // was $%04X
+ case 'D': sprintf(num,"%02Xh",d); break;
+ case 'K': sprintf(num,"%d",k); break;
+ case 'N': sprintf(num,"%s",nextar[n]); break;
+ case 'M': sprintf(num,"%s",arith[m]); break;
+ case 'P': sprintf(num,"PA%d",p); break;
+ case 'R': sprintf(num,"AR%d",r); break;
+ case 'S': sprintf(num,",%d",s); break;
+ case 'W': sprintf(num,"%04Xh",w); 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/tms32010/dis32010.c b/trunk/src/emu/cpu/tms32010/dis32010.c
new file mode 100644
index 00000000000..5b8d2a6d907
--- /dev/null
+++ b/trunk/src/emu/cpu/tms32010/dis32010.c
@@ -0,0 +1,136 @@
+ /**************************************************************************\
+ * Texas Instruments TMS32010 DSP Disassembler *
+ * *
+ * Copyright Tony La Porta *
+ * You are not allowed to distribute this software commercially. *
+ * Written for the MAME project. *
+ * *
+ * Notes : Data is expected to be read from source file as MSB first. *
+ * This is a word based microcontroller, with addressing *
+ * architecture based on the Harvard addressing scheme. *
+ * *
+ \**************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#include "32010dsm.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("TMS32010 Disassembler 1.1 by Tony La Porta (C)1999-2002+\n\n");
+ printf("Usage: dis32010 <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 = Dasm32010(String_Output,Counter);
+ printf("$%04lX: ",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)],Buffer[((Counter-1)*2)+1]);
+ }
+ else
+ {
+ printf("%02.2x%02.2x ",Buffer[(Counter*2)],Buffer[(Counter*2) + 1]);
+ }
+ 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/tms32010/tms32010.c b/trunk/src/emu/cpu/tms32010/tms32010.c
new file mode 100644
index 00000000000..b5579df843b
--- /dev/null
+++ b/trunk/src/emu/cpu/tms32010/tms32010.c
@@ -0,0 +1,1139 @@
+ /**************************************************************************\
+ * Texas Instruments TMS32010 DSP Emulator *
+ * *
+ * Copyright Tony La Porta *
+ * You are not allowed to distribute this software commercially. *
+ * Written for the MAME project. *
+ * *
+ * *
+ * Notes : The term 'DMA' within this document, is in reference *
+ * to Direct Memory Addressing, and NOT the usual term *
+ * of Direct Memory Access. *
+ * This is a word based microcontroller, with addressing *
+ * architecture based on the Harvard addressing scheme. *
+ * *
+ * *
+ * *
+ * **** Change Log **** *
+ * *
+ * TLP (13-Jul-2002) *
+ * - Added Save-State support *
+ * - Converted the pending_irq flag to INTF (a real flag in this device) *
+ * - Fixed the ignore Interrupt Request for previous critical *
+ * instructions requiring an extra instruction to be processed. For *
+ * this reason, instant IRQ servicing cannot be supported here, so *
+ * INTF needs to be polled within the instruction execution loop *
+ * - Removed IRQ callback (IRQ ACK not supported on this device) *
+ * - A pending IRQ will remain pending until it's serviced. De-asserting *
+ * the IRQ Pin does not remove a pending IRQ state *
+ * - BIO is no longer treated as an IRQ line. It's polled when required. *
+ * This is the true behaviour of the device *
+ * - Removed the Clear OV flag from overflow instructions. Overflow *
+ * instructions can only set the flag. Flag test instructions clear it *
+ * - Fixed the ABST, SUBC and SUBH instructions *
+ * - Fixed the signedness in many equation based instructions *
+ * - Added the missing Previous PC to the get_register function *
+ * - Changed Cycle timings to include clock ticks *
+ * - Converted some registers from ints to pairs for much cleaner code *
+ * TLP (20-Jul-2002) Ver 1.10 *
+ * - Fixed the dissasembly from the debugger *
+ * - Changed all references from TMS320C10 to TMS32010 *
+ * ASG (24-Sep-2002) Ver 1.20 *
+ * - Fixed overflow handling *
+ * - Simplified logic in a few locations *
+ * TLP (22-Feb-2004) Ver 1.21 *
+ * - Overflow for ADDH only affects upper 16bits (was modifying 32 bits) *
+ * - Internal Data Memory map is assigned here now *
+ * - Cycle counts for invalid opcodes 7F1E and 7F1F are now 0 *
+ * RK (23-Nov-2006) Ver 1.22 *
+ * - Fixed state of the Overflow Flag on reset *
+ * - Fixed the SUBC instruction which was incorrectly zeroing the divisor *
+ * TLP (13-Jul-2010) Ver 1.30 *
+ * - LST instruction was incorrectly setting an Indirect Addressing *
+ * feature when Direct Addressing mode was selected *
+ * - Added TMS32015 and TMS32016 variants *
+ * TLP (27-Jul-2010) Ver 1.31 *
+ * - Corrected cycle timing for conditional branch instructions *
+ * *
+ \**************************************************************************/
+
+
+#include "emu.h"
+#include "debugger.h"
+#include "tms32010.h"
+
+
+
+#define M_RDROM(A) TMS32010_ROM_RDMEM(A)
+#define M_WRTROM(A,V) TMS32010_ROM_WRMEM(A,V)
+#define M_RDRAM(A) TMS32010_RAM_RDMEM(A)
+#define M_WRTRAM(A,V) TMS32010_RAM_WRMEM(A,V)
+#define M_RDOP(A) TMS32010_RDOP(A)
+#define M_RDOP_ARG(A) TMS32010_RDOP_ARG(A)
+#define P_IN(A) TMS32010_In(A)
+#define P_OUT(A,V) TMS32010_Out(A,V)
+#define BIO_IN TMS32010_BIO_In
+
+
+
+typedef struct _tms32010_state tms32010_state; /* Page 3-6 shows all registers */
+struct _tms32010_state
+{
+ /******************** CPU Internal Registers *******************/
+ UINT16 PC;
+ UINT16 PREVPC; /* previous program counter */
+ UINT16 STR;
+ PAIR ACC;
+ PAIR ALU;
+ PAIR Preg;
+ UINT16 Treg;
+ UINT16 AR[2];
+ UINT16 STACK[4];
+
+ PAIR opcode;
+ int INTF; /* Pending Interrupt flag */
+ int icount;
+ PAIR oldacc;
+ UINT16 memaccess;
+ int addr_mask;
+
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *data;
+ address_space *io;
+};
+
+INLINE tms32010_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == TMS32010 ||
+ device->type() == TMS32015 ||
+ device->type() == TMS32016);
+ return (tms32010_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/* opcode table entry */
+typedef struct _tms32010_opcode tms32010_opcode;
+struct _tms32010_opcode
+{
+ UINT8 cycles;
+ void (*function)(tms32010_state *);
+};
+
+INLINE int add_branch_cycle(tms32010_state *cpustate);
+
+
+/********* The following is the Status (Flag) register definition. *********/
+/* 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 */
+/* OV | OVM | INTM | 1 | 1 | 1 | 1 | ARP | 1 | 1 | 1 | 1 | 1 | 1 | 1 | DP */
+#define OV_FLAG 0x8000 /* OV (Overflow flag) 1 indicates an overflow */
+#define OVM_FLAG 0x4000 /* OVM (Overflow Mode bit) 1 forces ACC overflow to greatest positive or negative saturation value */
+#define INTM_FLAG 0x2000 /* INTM (Interrupt Mask flag) 0 enables maskable interrupts */
+#define ARP_REG 0x0100 /* ARP (Auxiliary Register Pointer) */
+#define DP_REG 0x0001 /* DP (Data memory Pointer (bank) bit) */
+
+#define OV ( cpustate->STR & OV_FLAG) /* OV (Overflow flag) */
+#define OVM ( cpustate->STR & OVM_FLAG) /* OVM (Overflow Mode bit) 1 indicates an overflow */
+#define INTM ( cpustate->STR & INTM_FLAG) /* INTM (Interrupt enable flag) 0 enables maskable interrupts */
+#define ARP ((cpustate->STR & ARP_REG) >> 8) /* ARP (Auxiliary Register Pointer) */
+#define DP ((cpustate->STR & DP_REG) << 7) /* DP (Data memory Pointer bit) */
+
+#define DMA_DP (DP | (cpustate->opcode.b.l & 0x7f)) /* address used in direct memory access operations */
+#define DMA_DP1 (0x80 | cpustate->opcode.b.l) /* address used in direct memory access operations for sst instruction */
+#define IND (cpustate->AR[ARP] & 0xff) /* address used in indirect memory access operations */
+
+
+
+/****************************************************************************
+ * Read the state of the BIO pin
+ */
+
+#define TMS32010_BIO_In (cpustate->io->read_word(TMS32010_BIO<<1))
+
+
+/****************************************************************************
+ * Input a word from given I/O port
+ */
+
+#define TMS32010_In(Port) (cpustate->io->read_word((Port)<<1))
+
+
+/****************************************************************************
+ * Output a word to given I/O port
+ */
+
+#define TMS32010_Out(Port,Value) (cpustate->io->write_word((Port)<<1,Value))
+
+
+
+/****************************************************************************
+ * Read a word from given ROM memory location
+ */
+
+#define TMS32010_ROM_RDMEM(A) (cpustate->program->read_word((A)<<1))
+
+
+/****************************************************************************
+ * Write a word to given ROM memory location
+ */
+
+#define TMS32010_ROM_WRMEM(A,V) (cpustate->program->write_word((A)<<1,V))
+
+
+
+/****************************************************************************
+ * Read a word from given RAM memory location
+ */
+
+#define TMS32010_RAM_RDMEM(A) (cpustate->data->read_word((A)<<1))
+
+
+/****************************************************************************
+ * Write a word to given RAM memory location
+ */
+
+#define TMS32010_RAM_WRMEM(A,V) (cpustate->data->write_word((A)<<1,V))
+
+
+
+/****************************************************************************
+ * TMS32010_RDOP() is identical to TMS32010_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 TMS32010_RDOP(A) (cpustate->direct->read_decrypted_word((A)<<1))
+
+
+/****************************************************************************
+ * TMS32010_RDOP_ARG() is identical to TMS32010_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 TMS32010_RDOP_ARG(A) (cpustate->direct->read_raw_word((A)<<1))
+
+
+/************************************************************************
+ * Shortcuts
+ ************************************************************************/
+
+INLINE void CLR(tms32010_state *cpustate, UINT16 flag) { cpustate->STR &= ~flag; cpustate->STR |= 0x1efe; }
+INLINE void SET(tms32010_state *cpustate, UINT16 flag) { cpustate->STR |= flag; cpustate->STR |= 0x1efe; }
+
+
+INLINE void CALCULATE_ADD_OVERFLOW(tms32010_state *cpustate, INT32 addval)
+{
+ if ((INT32)(~(cpustate->oldacc.d ^ addval) & (cpustate->oldacc.d ^ cpustate->ACC.d)) < 0) {
+ SET(cpustate, OV_FLAG);
+ if (OVM)
+ cpustate->ACC.d = ((INT32)cpustate->oldacc.d < 0) ? 0x80000000 : 0x7fffffff;
+ }
+}
+INLINE void CALCULATE_SUB_OVERFLOW(tms32010_state *cpustate, INT32 subval)
+{
+ if ((INT32)((cpustate->oldacc.d ^ subval) & (cpustate->oldacc.d ^ cpustate->ACC.d)) < 0) {
+ SET(cpustate, OV_FLAG);
+ if (OVM)
+ cpustate->ACC.d = ((INT32)cpustate->oldacc.d < 0) ? 0x80000000 : 0x7fffffff;
+ }
+}
+
+INLINE UINT16 POP_STACK(tms32010_state *cpustate)
+{
+ UINT16 data = cpustate->STACK[3];
+ cpustate->STACK[3] = cpustate->STACK[2];
+ cpustate->STACK[2] = cpustate->STACK[1];
+ cpustate->STACK[1] = cpustate->STACK[0];
+ return (data & cpustate->addr_mask);
+}
+INLINE void PUSH_STACK(tms32010_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] = (data & cpustate->addr_mask);
+}
+
+INLINE void UPDATE_AR(tms32010_state *cpustate)
+{
+ if (cpustate->opcode.b.l & 0x30) {
+ UINT16 tmpAR = cpustate->AR[ARP];
+ if (cpustate->opcode.b.l & 0x20) tmpAR++ ;
+ if (cpustate->opcode.b.l & 0x10) tmpAR-- ;
+ cpustate->AR[ARP] = (cpustate->AR[ARP] & 0xfe00) | (tmpAR & 0x01ff);
+ }
+}
+INLINE void UPDATE_ARP(tms32010_state *cpustate)
+{
+ if (~cpustate->opcode.b.l & 0x08) {
+ if (cpustate->opcode.b.l & 0x01) SET(cpustate, ARP_REG);
+ else CLR(cpustate, ARP_REG);
+ }
+}
+
+
+INLINE void getdata(tms32010_state *cpustate, UINT8 shift,UINT8 signext)
+{
+ if (cpustate->opcode.b.l & 0x80)
+ cpustate->memaccess = IND;
+ else
+ cpustate->memaccess = DMA_DP;
+
+ cpustate->ALU.d = (UINT16)M_RDRAM(cpustate->memaccess);
+ if (signext) cpustate->ALU.d = (INT16)cpustate->ALU.d;
+ cpustate->ALU.d <<= shift;
+ if (cpustate->opcode.b.l & 0x80) {
+ UPDATE_AR(cpustate);
+ UPDATE_ARP(cpustate);
+ }
+}
+
+INLINE void putdata(tms32010_state *cpustate, UINT16 data)
+{
+ if (cpustate->opcode.b.l & 0x80)
+ cpustate->memaccess = IND;
+ else
+ cpustate->memaccess = DMA_DP;
+
+ if (cpustate->opcode.b.l & 0x80) {
+ UPDATE_AR(cpustate);
+ UPDATE_ARP(cpustate);
+ }
+ M_WRTRAM(cpustate->memaccess,data);
+}
+INLINE void putdata_sar(tms32010_state *cpustate, UINT8 data)
+{
+ if (cpustate->opcode.b.l & 0x80)
+ cpustate->memaccess = IND;
+ else
+ cpustate->memaccess = DMA_DP;
+
+ if (cpustate->opcode.b.l & 0x80) {
+ UPDATE_AR(cpustate);
+ UPDATE_ARP(cpustate);
+ }
+ M_WRTRAM(cpustate->memaccess,cpustate->AR[data]);
+}
+INLINE void putdata_sst(tms32010_state *cpustate, UINT16 data)
+{
+ if (cpustate->opcode.b.l & 0x80)
+ cpustate->memaccess = IND;
+ else
+ cpustate->memaccess = DMA_DP1; /* Page 1 only */
+
+ if (cpustate->opcode.b.l & 0x80) {
+ UPDATE_AR(cpustate);
+ }
+ M_WRTRAM(cpustate->memaccess,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 opcodes_7F(tms32010_state *cpustate) { }
+
+
+static void illegal(tms32010_state *cpustate)
+{
+ logerror("TMS32010: PC=%04x, Illegal opcode = %04x\n", (cpustate->PC-1), cpustate->opcode.w.l);
+}
+
+static void abst(tms32010_state *cpustate)
+{
+ if ( (INT32)(cpustate->ACC.d) < 0 ) {
+ cpustate->ACC.d = -cpustate->ACC.d;
+ if (OVM && (cpustate->ACC.d == 0x80000000)) cpustate->ACC.d-- ;
+ }
+}
+
+/*** The manual doesn't mention overflow with the ADD? instructions however ***
+ *** overflow is implemented here, because it makes little sense otherwise ****
+ *** while newer generations of this type of chip supported it. The ***********
+ *** manual may be wrong wrong (apart from other errors the manual has). ******
+
+static void add_sh(cpustate) { getdata(cpustate, cpustate->opcode.b.h,1); cpustate->ACC.d += cpustate->ALU.d; }
+static void addh(cpustate) { getdata(cpustate, 0,0); cpustate->ACC.d += (cpustate->ALU.d << 16); }
+ ***/
+
+static void add_sh(tms32010_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ getdata(cpustate, (cpustate->opcode.b.h & 0xf),1);
+ cpustate->ACC.d += cpustate->ALU.d;
+ CALCULATE_ADD_OVERFLOW(cpustate, cpustate->ALU.d);
+}
+static void addh(tms32010_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ getdata(cpustate, 0,0);
+ cpustate->ACC.w.h += cpustate->ALU.w.l;
+ if ((INT16)(~(cpustate->oldacc.w.h ^ cpustate->ALU.w.h) & (cpustate->oldacc.w.h ^ cpustate->ACC.w.h)) < 0) {
+ SET(cpustate, OV_FLAG);
+ if (OVM)
+ cpustate->ACC.w.h = ((INT16)cpustate->oldacc.w.h < 0) ? 0x8000 : 0x7fff;
+ }
+}
+static void adds(tms32010_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ getdata(cpustate, 0,0);
+ cpustate->ACC.d += cpustate->ALU.d;
+ CALCULATE_ADD_OVERFLOW(cpustate, cpustate->ALU.d);
+}
+static void and_(tms32010_state *cpustate)
+{
+ getdata(cpustate, 0,0);
+ cpustate->ACC.d &= cpustate->ALU.d;
+}
+static void apac(tms32010_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ cpustate->ACC.d += cpustate->Preg.d;
+ CALCULATE_ADD_OVERFLOW(cpustate, cpustate->Preg.d);
+}
+static void br(tms32010_state *cpustate)
+{
+ cpustate->PC = M_RDOP_ARG(cpustate->PC);
+}
+static void banz(tms32010_state *cpustate)
+{
+ if (cpustate->AR[ARP] & 0x01ff) {
+ cpustate->PC = M_RDOP_ARG(cpustate->PC);
+ cpustate->icount -= add_branch_cycle(cpustate);
+ }
+ else
+ cpustate->PC++ ;
+ cpustate->ALU.w.l = cpustate->AR[ARP];
+ cpustate->ALU.w.l-- ;
+ cpustate->AR[ARP] = (cpustate->AR[ARP] & 0xfe00) | (cpustate->ALU.w.l & 0x01ff);
+}
+static void bgez(tms32010_state *cpustate)
+{
+ if ( (INT32)(cpustate->ACC.d) >= 0 ) {
+ cpustate->PC = M_RDOP_ARG(cpustate->PC);
+ cpustate->icount -= add_branch_cycle(cpustate);
+ }
+ else
+ cpustate->PC++ ;
+}
+static void bgz(tms32010_state *cpustate)
+{
+ if ( (INT32)(cpustate->ACC.d) > 0 ) {
+ cpustate->PC = M_RDOP_ARG(cpustate->PC);
+ cpustate->icount -= add_branch_cycle(cpustate);
+ }
+ else
+ cpustate->PC++ ;
+}
+static void bioz(tms32010_state *cpustate)
+{
+ if (BIO_IN != CLEAR_LINE) {
+ cpustate->PC = M_RDOP_ARG(cpustate->PC);
+ cpustate->icount -= add_branch_cycle(cpustate);
+ }
+ else
+ cpustate->PC++ ;
+}
+static void blez(tms32010_state *cpustate)
+{
+ if ( (INT32)(cpustate->ACC.d) <= 0 ) {
+ cpustate->PC = M_RDOP_ARG(cpustate->PC);
+ cpustate->icount -= add_branch_cycle(cpustate);
+ }
+ else
+ cpustate->PC++ ;
+}
+static void blz(tms32010_state *cpustate)
+{
+ if ( (INT32)(cpustate->ACC.d) < 0 ) {
+ cpustate->PC = M_RDOP_ARG(cpustate->PC);
+ cpustate->icount -= add_branch_cycle(cpustate);
+ }
+ else
+ cpustate->PC++ ;
+}
+static void bnz(tms32010_state *cpustate)
+{
+ if (cpustate->ACC.d != 0) {
+ cpustate->PC = M_RDOP_ARG(cpustate->PC);
+ cpustate->icount -= add_branch_cycle(cpustate);
+ }
+ else
+ cpustate->PC++ ;
+}
+static void bv(tms32010_state *cpustate)
+{
+ if (OV) {
+ CLR(cpustate, OV_FLAG);
+ cpustate->PC = M_RDOP_ARG(cpustate->PC);
+ cpustate->icount -= add_branch_cycle(cpustate);
+ }
+ else
+ cpustate->PC++ ;
+}
+static void bz(tms32010_state *cpustate)
+{
+ if (cpustate->ACC.d == 0) {
+ cpustate->PC = M_RDOP_ARG(cpustate->PC);
+ cpustate->icount -= add_branch_cycle(cpustate);
+ }
+ else
+ cpustate->PC++ ;
+}
+static void cala(tms32010_state *cpustate)
+{
+ PUSH_STACK(cpustate, cpustate->PC);
+ cpustate->PC = cpustate->ACC.w.l & cpustate->addr_mask;
+}
+static void call(tms32010_state *cpustate)
+{
+ cpustate->PC++ ;
+ PUSH_STACK(cpustate, cpustate->PC);
+ cpustate->PC = M_RDOP_ARG((cpustate->PC - 1));
+}
+static void dint(tms32010_state *cpustate)
+{
+ SET(cpustate, INTM_FLAG);
+}
+static void dmov(tms32010_state *cpustate)
+{
+ getdata(cpustate, 0,0);
+ M_WRTRAM((cpustate->memaccess + 1),cpustate->ALU.w.l);
+}
+static void eint(tms32010_state *cpustate)
+{
+ CLR(cpustate, INTM_FLAG);
+}
+static void in_p(tms32010_state *cpustate)
+{
+ cpustate->ALU.w.l = P_IN( (cpustate->opcode.b.h & 7) );
+ putdata(cpustate, cpustate->ALU.w.l);
+}
+static void lac_sh(tms32010_state *cpustate)
+{
+ getdata(cpustate, (cpustate->opcode.b.h & 0x0f),1);
+ cpustate->ACC.d = cpustate->ALU.d;
+}
+static void lack(tms32010_state *cpustate)
+{
+ cpustate->ACC.d = cpustate->opcode.b.l;
+}
+static void lar_ar0(tms32010_state *cpustate)
+{
+ getdata(cpustate, 0,0);
+ cpustate->AR[0] = cpustate->ALU.w.l;
+}
+static void lar_ar1(tms32010_state *cpustate)
+{
+ getdata(cpustate, 0,0);
+ cpustate->AR[1] = cpustate->ALU.w.l;
+}
+static void lark_ar0(tms32010_state *cpustate)
+{
+ cpustate->AR[0] = cpustate->opcode.b.l;
+}
+static void lark_ar1(tms32010_state *cpustate)
+{
+ cpustate->AR[1] = cpustate->opcode.b.l;
+}
+static void larp_mar(tms32010_state *cpustate)
+{
+ if (cpustate->opcode.b.l & 0x80) {
+ UPDATE_AR(cpustate);
+ UPDATE_ARP(cpustate);
+ }
+}
+static void ldp(tms32010_state *cpustate)
+{
+ getdata(cpustate, 0,0);
+ if (cpustate->ALU.d & 1)
+ SET(cpustate, DP_REG);
+ else
+ CLR(cpustate, DP_REG);
+}
+static void ldpk(tms32010_state *cpustate)
+{
+ if (cpustate->opcode.b.l & 1)
+ SET(cpustate, DP_REG);
+ else
+ CLR(cpustate, DP_REG);
+}
+static void lst(tms32010_state *cpustate)
+{
+ if (cpustate->opcode.b.l & 0x80) {
+ cpustate->opcode.b.l |= 0x08; /* In Indirect Addressing mode, next ARP is not supported here so mask it */
+ }
+ getdata(cpustate, 0,0);
+ cpustate->ALU.w.l &= (~INTM_FLAG); /* Must not affect INTM */
+ cpustate->STR &= INTM_FLAG;
+ cpustate->STR |= cpustate->ALU.w.l;
+ cpustate->STR |= 0x1efe;
+}
+static void lt(tms32010_state *cpustate)
+{
+ getdata(cpustate, 0,0);
+ cpustate->Treg = cpustate->ALU.w.l;
+}
+static void lta(tms32010_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ getdata(cpustate, 0,0);
+ cpustate->Treg = cpustate->ALU.w.l;
+ cpustate->ACC.d += cpustate->Preg.d;
+ CALCULATE_ADD_OVERFLOW(cpustate, cpustate->Preg.d);
+}
+static void ltd(tms32010_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ getdata(cpustate, 0,0);
+ cpustate->Treg = cpustate->ALU.w.l;
+ M_WRTRAM((cpustate->memaccess + 1),cpustate->ALU.w.l);
+ cpustate->ACC.d += cpustate->Preg.d;
+ CALCULATE_ADD_OVERFLOW(cpustate, cpustate->Preg.d);
+}
+static void mpy(tms32010_state *cpustate)
+{
+ getdata(cpustate, 0,0);
+ cpustate->Preg.d = (INT16)cpustate->ALU.w.l * (INT16)cpustate->Treg;
+ if (cpustate->Preg.d == 0x40000000) cpustate->Preg.d = 0xc0000000;
+}
+static void mpyk(tms32010_state *cpustate)
+{
+ cpustate->Preg.d = (INT16)cpustate->Treg * ((INT16)(cpustate->opcode.w.l << 3) >> 3);
+}
+static void nop(tms32010_state *cpustate)
+{
+ /* Nothing to do */
+}
+static void or_(tms32010_state *cpustate)
+{
+ getdata(cpustate, 0,0);
+ cpustate->ACC.w.l |= cpustate->ALU.w.l;
+}
+static void out_p(tms32010_state *cpustate)
+{
+ getdata(cpustate, 0,0);
+ P_OUT( (cpustate->opcode.b.h & 7), cpustate->ALU.w.l );
+}
+static void pac(tms32010_state *cpustate)
+{
+ cpustate->ACC.d = cpustate->Preg.d;
+}
+static void pop(tms32010_state *cpustate)
+{
+ cpustate->ACC.w.l = POP_STACK(cpustate);
+ cpustate->ACC.w.h = 0x0000;
+}
+static void push(tms32010_state *cpustate)
+{
+ PUSH_STACK(cpustate, cpustate->ACC.w.l);
+}
+static void ret(tms32010_state *cpustate)
+{
+ cpustate->PC = POP_STACK(cpustate);
+}
+static void rovm(tms32010_state *cpustate)
+{
+ CLR(cpustate, OVM_FLAG);
+}
+static void sach_sh(tms32010_state *cpustate)
+{
+ cpustate->ALU.d = (cpustate->ACC.d << (cpustate->opcode.b.h & 7));
+ putdata(cpustate, cpustate->ALU.w.h);
+}
+static void sacl(tms32010_state *cpustate)
+{
+ putdata(cpustate, cpustate->ACC.w.l);
+}
+static void sar_ar0(tms32010_state *cpustate)
+{
+ putdata_sar(cpustate, 0);
+}
+static void sar_ar1(tms32010_state *cpustate)
+{
+ putdata_sar(cpustate, 1);
+}
+static void sovm(tms32010_state *cpustate)
+{
+ SET(cpustate, OVM_FLAG);
+}
+static void spac(tms32010_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ cpustate->ACC.d -= cpustate->Preg.d;
+ CALCULATE_SUB_OVERFLOW(cpustate, cpustate->Preg.d);
+}
+static void sst(tms32010_state *cpustate)
+{
+ putdata_sst(cpustate, cpustate->STR);
+}
+static void sub_sh(tms32010_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ getdata(cpustate, (cpustate->opcode.b.h & 0x0f),1);
+ cpustate->ACC.d -= cpustate->ALU.d;
+ CALCULATE_SUB_OVERFLOW(cpustate, cpustate->ALU.d);
+}
+static void subc(tms32010_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ getdata(cpustate, 15,0);
+ cpustate->ALU.d = (INT32) cpustate->ACC.d - cpustate->ALU.d;
+ if ((INT32)((cpustate->oldacc.d ^ cpustate->ALU.d) & (cpustate->oldacc.d ^ cpustate->ACC.d)) < 0)
+ SET(cpustate, OV_FLAG);
+ if ( (INT32)(cpustate->ALU.d) >= 0 )
+ cpustate->ACC.d = ((cpustate->ALU.d << 1) + 1);
+ else
+ cpustate->ACC.d = (cpustate->ACC.d << 1);
+}
+static void subh(tms32010_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ getdata(cpustate, 16,0);
+ cpustate->ACC.d -= cpustate->ALU.d;
+ CALCULATE_SUB_OVERFLOW(cpustate, cpustate->ALU.d);
+}
+static void subs(tms32010_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ getdata(cpustate, 0,0);
+ cpustate->ACC.d -= cpustate->ALU.d;
+ CALCULATE_SUB_OVERFLOW(cpustate, cpustate->ALU.d);
+}
+static void tblr(tms32010_state *cpustate)
+{
+ cpustate->ALU.d = M_RDROM((cpustate->ACC.w.l & cpustate->addr_mask));
+ putdata(cpustate, cpustate->ALU.w.l);
+ cpustate->STACK[0] = cpustate->STACK[1];
+}
+static void tblw(tms32010_state *cpustate)
+{
+ getdata(cpustate, 0,0);
+ M_WRTROM(((cpustate->ACC.w.l & cpustate->addr_mask)),cpustate->ALU.w.l);
+ cpustate->STACK[0] = cpustate->STACK[1];
+}
+static void xor_(tms32010_state *cpustate)
+{
+ getdata(cpustate, 0,0);
+ cpustate->ACC.w.l ^= cpustate->ALU.w.l;
+}
+static void zac(tms32010_state *cpustate)
+{
+ cpustate->ACC.d = 0;
+}
+static void zalh(tms32010_state *cpustate)
+{
+ getdata(cpustate, 0,0);
+ cpustate->ACC.w.h = cpustate->ALU.w.l;
+ cpustate->ACC.w.l = 0x0000;
+}
+static void zals(tms32010_state *cpustate)
+{
+ getdata(cpustate, 0,0);
+ cpustate->ACC.w.l = cpustate->ALU.w.l;
+ cpustate->ACC.w.h = 0x0000;
+}
+
+
+
+/***********************************************************************
+ * Opcode Table (Cycles, Instruction)
+ ***********************************************************************/
+
+/* Conditional Branch instructions take two cycles when the test condition is met and the branch performed */
+
+static const tms32010_opcode opcode_main[256]=
+{
+/*00*/ {1, add_sh },{1, add_sh },{1, add_sh },{1, add_sh },{1, add_sh },{1, add_sh },{1, add_sh },{1, add_sh },
+/*08*/ {1, add_sh },{1, add_sh },{1, add_sh },{1, add_sh },{1, add_sh },{1, add_sh },{1, add_sh },{1, add_sh },
+/*10*/ {1, sub_sh },{1, sub_sh },{1, sub_sh },{1, sub_sh },{1, sub_sh },{1, sub_sh },{1, sub_sh },{1, sub_sh },
+/*18*/ {1, sub_sh },{1, sub_sh },{1, sub_sh },{1, sub_sh },{1, sub_sh },{1, sub_sh },{1, sub_sh },{1, sub_sh },
+/*20*/ {1, lac_sh },{1, lac_sh },{1, lac_sh },{1, lac_sh },{1, lac_sh },{1, lac_sh },{1, lac_sh },{1, lac_sh },
+/*28*/ {1, lac_sh },{1, lac_sh },{1, lac_sh },{1, lac_sh },{1, lac_sh },{1, lac_sh },{1, lac_sh },{1, lac_sh },
+/*30*/ {1, sar_ar0 },{1, sar_ar1 },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },
+/*38*/ {1, lar_ar0 },{1, lar_ar1 },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },
+/*40*/ {2, in_p },{2, in_p },{2, in_p },{2, in_p },{2, in_p },{2, in_p },{2, in_p },{2, in_p },
+/*48*/ {2, out_p },{2, out_p },{2, out_p },{2, out_p },{2, out_p },{2, out_p },{2, out_p },{2, out_p },
+/*50*/ {1, sacl },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },
+/*58*/ {1, sach_sh },{1, sach_sh },{1, sach_sh },{1, sach_sh },{1, sach_sh },{1, sach_sh },{1, sach_sh },{1, sach_sh },
+/*60*/ {1, addh },{1, adds },{1, subh },{1, subs },{1, subc },{1, zalh },{1, zals },{3, tblr },
+/*68*/ {1, larp_mar},{1, dmov },{1, lt },{1, ltd },{1, lta },{1, mpy },{1, ldpk },{1, ldp },
+/*70*/ {1, lark_ar0},{1, lark_ar1 },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },
+/*78*/ {1, xor_ },{1, and_ },{1, or_ },{1, lst },{1, sst },{3, tblw },{1, lack },{0, opcodes_7F },
+/*80*/ {1, mpyk },{1, mpyk },{1, mpyk },{1, mpyk },{1, mpyk },{1, mpyk },{1, mpyk },{1, mpyk },
+/*88*/ {1, mpyk },{1, mpyk },{1, mpyk },{1, mpyk },{1, mpyk },{1, mpyk },{1, mpyk },{1, mpyk },
+/*90*/ {1, mpyk },{1, mpyk },{1, mpyk },{1, mpyk },{1, mpyk },{1, mpyk },{1, mpyk },{1, mpyk },
+/*98*/ {1, mpyk },{1, mpyk },{1, mpyk },{1, mpyk },{1, mpyk },{1, mpyk },{1, mpyk },{1, mpyk },
+/*A0*/ {0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },
+/*A8*/ {0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },
+/*B0*/ {0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },
+/*B8*/ {0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },
+/*C0*/ {0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },
+/*C8*/ {0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },
+/*D0*/ {0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },
+/*D8*/ {0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },
+/*E0*/ {0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },
+/*E8*/ {0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },
+/*F0*/ {0, illegal },{0, illegal },{0, illegal },{0, illegal },{1, banz },{1, bv },{1, bioz },{0, illegal },
+/*F8*/ {2, call },{2, br },{1, blz },{1, blez },{1, bgz },{1, bgez },{1, bnz },{1, bz }
+};
+
+static const tms32010_opcode opcode_7F[32]=
+{
+/*80*/ {1, nop },{1, dint },{1, eint },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },
+/*88*/ {1, abst },{1, zac },{1, rovm },{1, sovm },{2, cala },{2, ret },{1, pac },{1, apac },
+/*90*/ {1, spac },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },
+/*98*/ {0, illegal },{0, illegal },{0, illegal },{0, illegal },{2, push },{2, pop },{0, illegal },{0, illegal }
+};
+
+INLINE int add_branch_cycle(tms32010_state *cpustate)
+{
+ return opcode_main[cpustate->opcode.b.h].cycles;
+}
+
+/****************************************************************************
+ * Inits CPU emulation
+ ****************************************************************************/
+
+static CPU_INIT( tms32010 )
+{
+ tms32010_state *cpustate = get_safe_token(device);
+
+ device->save_item(NAME(cpustate->PC));
+ device->save_item(NAME(cpustate->PREVPC));
+ device->save_item(NAME(cpustate->STR));
+ device->save_item(NAME(cpustate->ACC.d));
+ device->save_item(NAME(cpustate->ALU.d));
+ device->save_item(NAME(cpustate->Preg.d));
+ device->save_item(NAME(cpustate->Treg));
+ device->save_item(NAME(cpustate->AR[0]));
+ device->save_item(NAME(cpustate->AR[1]));
+ 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->INTF));
+ device->save_item(NAME(cpustate->icount));
+ device->save_item(NAME(cpustate->opcode.d));
+ device->save_item(NAME(cpustate->oldacc.d));
+ device->save_item(NAME(cpustate->memaccess));
+ device->save_item(NAME(cpustate->addr_mask));
+
+ 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);
+}
+
+
+/****************************************************************************
+ * Shut down CPU emulation
+ ****************************************************************************/
+
+static CPU_EXIT( tms32010 ) { }
+
+
+/****************************************************************************
+ * Set IRQ line state
+ ****************************************************************************/
+
+static void set_irq_line(tms32010_state *cpustate, int irqline, int state)
+{
+ /* Pending Interrupts cannot be cleared! */
+ if (state == ASSERT_LINE) cpustate->INTF |= TMS32010_INT_PENDING;
+}
+
+
+
+/****************************************************************************
+ * Issue an interrupt if necessary
+ ****************************************************************************/
+
+static int Ext_IRQ(tms32010_state *cpustate)
+{
+ if (INTM == 0)
+ {
+ logerror("TMS32010: EXT INTERRUPT\n");
+ cpustate->INTF = TMS32010_INT_NONE;
+ SET(cpustate, INTM_FLAG);
+ PUSH_STACK(cpustate, cpustate->PC);
+ cpustate->PC = 0x0002;
+ return (opcode_7F[0x1c].cycles + opcode_7F[0x01].cycles); /* 3 cycles used due to PUSH and DINT operation ? */
+ }
+ return (0);
+}
+
+
+/****************************************************************************
+ * Execute IPeriod. Return 0 if emulation should be stopped
+ ****************************************************************************/
+
+static CPU_EXECUTE( tms32010 )
+{
+ tms32010_state *cpustate = get_safe_token(device);
+
+ do
+ {
+ if (cpustate->INTF) {
+ /* Dont service INT if previous instruction was MPY, MPYK or EINT */
+ if ((cpustate->opcode.b.h != 0x6d) && ((cpustate->opcode.b.h & 0xe0) != 0x80) && (cpustate->opcode.w.l != 0x7f82))
+ cpustate->icount -= Ext_IRQ(cpustate);
+ }
+
+ cpustate->PREVPC = cpustate->PC;
+
+ debugger_instruction_hook(device, cpustate->PC);
+
+ cpustate->opcode.d = M_RDOP(cpustate->PC);
+ cpustate->PC++;
+
+ if (cpustate->opcode.b.h != 0x7f) { /* Do all opcodes except the 7Fxx ones */
+ cpustate->icount -= opcode_main[cpustate->opcode.b.h].cycles;
+ (*opcode_main[cpustate->opcode.b.h].function)(cpustate);
+ }
+ else { /* Opcode major byte 7Fxx has many opcodes in its minor byte */
+ cpustate->icount -= opcode_7F[(cpustate->opcode.b.l & 0x1f)].cycles;
+ (*opcode_7F[(cpustate->opcode.b.l & 0x1f)].function)(cpustate);
+ }
+ } while (cpustate->icount > 0);
+}
+
+
+
+/****************************************************************************
+ * TMS32010 Internal Memory Map
+ ****************************************************************************/
+
+static ADDRESS_MAP_START( tms32010_ram, AS_DATA, 16 )
+ AM_RANGE(0x00, 0x7f) AM_RAM /* Page 0 */
+ AM_RANGE(0x80, 0x8f) AM_RAM /* Page 1 */
+ADDRESS_MAP_END
+
+
+/****************************************************************************
+ * TMS32010 Reset registers to their initial values
+ ****************************************************************************/
+
+static CPU_RESET( tms32010 )
+{
+ tms32010_state *cpustate = get_safe_token(device);
+
+ cpustate->PC = 0;
+ cpustate->ACC.d = 0;
+ cpustate->INTF = TMS32010_INT_NONE;
+ /* Setup Status Register : 7efe */
+ CLR(cpustate, (OV_FLAG | ARP_REG | DP_REG));
+ SET(cpustate, (OVM_FLAG | INTM_FLAG));
+
+ cpustate->addr_mask = 0x0fff;
+}
+
+
+/**************************************************************************
+ * TMS32010 set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( tms32010 )
+{
+ tms32010_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_PC:
+ case CPUINFO_INT_REGISTER + TMS32010_PC: cpustate->PC = info->i; break;
+ /* This is actually not a stack pointer, but the stack contents */
+ /* Stack is a 4 level First In Last Out stack */
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + TMS32010_STK3: cpustate->STACK[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32010_STR: cpustate->STR = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32010_ACC: cpustate->ACC.d = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32010_PREG: cpustate->Preg.d = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32010_TREG: cpustate->Treg = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32010_AR0: cpustate->AR[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32010_AR1: cpustate->AR[1] = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * TMS32010 get_info
+ **************************************************************************/
+
+CPU_GET_INFO( tms32010 )
+{
+ tms32010_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(tms32010_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 = 4; 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 = 3; 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 = 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 = 16; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 5; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = -1; break;
+
+ case CPUINFO_INT_INPUT_STATE + 0: info->i = (cpustate->INTF & TMS32010_INT_PENDING) ? ASSERT_LINE : CLEAR_LINE; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->PREVPC; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + TMS32010_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 + TMS32010_STK3: info->i = cpustate->STACK[3]; break;
+ case CPUINFO_INT_REGISTER + TMS32010_ACC: info->i = cpustate->ACC.d; break;
+ case CPUINFO_INT_REGISTER + TMS32010_STR: info->i = cpustate->STR; break;
+ case CPUINFO_INT_REGISTER + TMS32010_PREG: info->i = cpustate->Preg.d; break;
+ case CPUINFO_INT_REGISTER + TMS32010_TREG: info->i = cpustate->Treg; break;
+ case CPUINFO_INT_REGISTER + TMS32010_AR0: info->i = cpustate->AR[0]; break;
+ case CPUINFO_INT_REGISTER + TMS32010_AR1: info->i = cpustate->AR[1]; 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(tms32010); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(tms32010); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(tms32010); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(tms32010); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(tms32010); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(tms32010); 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(tms32010_ram); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "TMS32010"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Texas Instruments TMS32010"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.31"); 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, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
+ cpustate->STR & 0x8000 ? 'O':'.',
+ cpustate->STR & 0x4000 ? 'M':'.',
+ cpustate->STR & 0x2000 ? 'I':'.',
+ cpustate->STR & 0x1000 ? '.':'?',
+ cpustate->STR & 0x0800 ? 'a':'?',
+ cpustate->STR & 0x0400 ? 'r':'?',
+ cpustate->STR & 0x0200 ? 'p':'?',
+ cpustate->STR & 0x0100 ? '1':'0',
+ cpustate->STR & 0x0080 ? '.':'?',
+ cpustate->STR & 0x0040 ? '.':'?',
+ cpustate->STR & 0x0020 ? '.':'?',
+ cpustate->STR & 0x0010 ? '.':'?',
+ cpustate->STR & 0x0008 ? '.':'?',
+ cpustate->STR & 0x0004 ? 'd':'?',
+ cpustate->STR & 0x0002 ? 'p':'?',
+ cpustate->STR & 0x0001 ? '1':'0');
+ break;
+
+ case CPUINFO_STR_REGISTER + TMS32010_PC: sprintf(info->s, "PC:%04X", cpustate->PC); break;
+ case CPUINFO_STR_REGISTER + TMS32010_SP: sprintf(info->s, "SP:%X", 0); /* fake stack pointer */ break;
+ case CPUINFO_STR_REGISTER + TMS32010_STR: sprintf(info->s, "STR:%04X", cpustate->STR); break;
+ case CPUINFO_STR_REGISTER + TMS32010_ACC: sprintf(info->s, "ACC:%08X", cpustate->ACC.d); break;
+ case CPUINFO_STR_REGISTER + TMS32010_PREG: sprintf(info->s, "P:%08X", cpustate->Preg.d); break;
+ case CPUINFO_STR_REGISTER + TMS32010_TREG: sprintf(info->s, "T:%04X", cpustate->Treg); break;
+ case CPUINFO_STR_REGISTER + TMS32010_AR0: sprintf(info->s, "AR0:%04X", cpustate->AR[0]); break;
+ case CPUINFO_STR_REGISTER + TMS32010_AR1: sprintf(info->s, "AR1:%04X", cpustate->AR[1]); break;
+ case CPUINFO_STR_REGISTER + TMS32010_STK0: sprintf(info->s, "STK0:%04X", cpustate->STACK[0]); break;
+ case CPUINFO_STR_REGISTER + TMS32010_STK1: sprintf(info->s, "STK1:%04X", cpustate->STACK[1]); break;
+ case CPUINFO_STR_REGISTER + TMS32010_STK2: sprintf(info->s, "STK2:%04X", cpustate->STACK[2]); break;
+ case CPUINFO_STR_REGISTER + TMS32010_STK3: sprintf(info->s, "STK3:%04X", cpustate->STACK[3]); break;
+ }
+}
+
+
+/****************************************************************************
+ * TMS32015 Internal Memory Map
+ ****************************************************************************/
+
+static ADDRESS_MAP_START( tms32015_ram, AS_DATA, 16 )
+ AM_RANGE(0x00, 0x7f) AM_RAM /* Page 0 */
+ AM_RANGE(0x80, 0xff) AM_RAM /* Page 1 */
+ADDRESS_MAP_END
+
+
+/**************************************************************************
+ * TMS32015 CPU-specific get_info
+ **************************************************************************/
+
+CPU_GET_INFO( tms32015 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map16 = ADDRESS_MAP_NAME(tms32015_ram); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "TMS32015"); break;
+
+ default: CPU_GET_INFO_CALL(tms32010); break;
+ }
+}
+
+
+
+/****************************************************************************
+ * TMS32016 Reset registers to their initial values
+ ****************************************************************************/
+
+static CPU_RESET( tms32016 )
+{
+ tms32010_state *cpustate = get_safe_token(device);
+
+ CPU_RESET_CALL(tms32010);
+ cpustate->addr_mask = 0xffff;
+}
+
+
+/**************************************************************************
+ * TMS32016 CPU-specific get_info
+ **************************************************************************/
+
+CPU_GET_INFO( tms32016 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(tms32016); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map16 = ADDRESS_MAP_NAME(tms32015_ram); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "TMS32016"); break;
+
+ default: CPU_GET_INFO_CALL(tms32010); break;
+ }
+}
+
+
+
+DEFINE_LEGACY_CPU_DEVICE(TMS32010, tms32010);
+DEFINE_LEGACY_CPU_DEVICE(TMS32015, tms32015);
+DEFINE_LEGACY_CPU_DEVICE(TMS32016, tms32016);
diff --git a/trunk/src/emu/cpu/tms32010/tms32010.h b/trunk/src/emu/cpu/tms32010/tms32010.h
new file mode 100644
index 00000000000..bd715ebcb5e
--- /dev/null
+++ b/trunk/src/emu/cpu/tms32010/tms32010.h
@@ -0,0 +1,54 @@
+ /**************************************************************************\
+ * Texas Instruments TMS32010 DSP Emulator *
+ * *
+ * Copyright Tony La Porta *
+ * You are not allowed to distribute this software commercially. *
+ * Written for the MAME project. *
+ * *
+ * *
+ * Note : This is a word based microcontroller, with addressing *
+ * architecture based on the Harvard addressing scheme. *
+ * *
+ \**************************************************************************/
+
+#pragma once
+
+#ifndef __TMS32010_H__
+#define __TMS32010_H__
+
+
+
+
+/****************************************************************************
+ * Use this in the I/O port address fields of your driver for the BIO pin
+ * i.e,
+ * AM_RANGE(TMS32010_BIO, TMS32010_BIO) AM_READ(twincobr_bio_line_r)
+ */
+
+#define TMS32010_BIO 0x10 /* BIO input */
+
+
+#define TMS32010_INT_PENDING 0x80000000
+#define TMS32010_INT_NONE 0
+
+
+enum
+{
+ TMS32010_PC=1, TMS32010_SP, TMS32010_STR, TMS32010_ACC,
+ TMS32010_PREG, TMS32010_TREG, TMS32010_AR0, TMS32010_AR1,
+ TMS32010_STK0, TMS32010_STK1, TMS32010_STK2, TMS32010_STK3
+};
+
+
+/****************************************************************************
+ * Public Functions
+ */
+
+DECLARE_LEGACY_CPU_DEVICE(TMS32010, tms32010);
+DECLARE_LEGACY_CPU_DEVICE(TMS32015, tms32015);
+DECLARE_LEGACY_CPU_DEVICE(TMS32016, tms32016);
+
+
+CPU_DISASSEMBLE( tms32010 );
+
+#endif /* __TMS32010_H__ */
diff --git a/trunk/src/emu/cpu/tms32025/32025dsm.c b/trunk/src/emu/cpu/tms32025/32025dsm.c
new file mode 100644
index 00000000000..9388bf0a9d9
--- /dev/null
+++ b/trunk/src/emu/cpu/tms32025/32025dsm.c
@@ -0,0 +1,505 @@
+ /**************************************************************************\
+ * Texas Instruments TMS320x25 DSP Disassembler *
+ * *
+ * Copyright Tony La Porta *
+ * To be used with TMS320x25 DSP Emulator engine. *
+ * Written for the MAME project. *
+ * *
+ * Many thanks to those involved in the i8039 Disassembler *
+ * as the structure here was borrowed from it. *
+ * *
+ * Note : This is a word based microcontroller, with addressing *
+ * architecture based on the Harvard addressing scheme. *
+ * *
+ * *
+ * A Memory Address *
+ * B Opcode Address Argument (Requires next opcode read) *
+ * C Compare mode *
+ * D Immediate byte load *
+ * K Immediate bit load *
+ * W Immediate word load *
+ * M AR[x] register modification type (for indirect addressing) *
+ * N ARP register to change ARP pointer to (for indirect addressing) *
+ * P I/O port address number *
+ * R AR[R] register to use *
+ * S Shift ALU left *
+ * T Shift ALU left (Hex) / Nibble data *
+ * X Don't care bit *
+ * *
+ \**************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include <ctype.h>
+
+#include "tms32025.h"
+
+
+
+typedef unsigned char byte;
+typedef unsigned short int word;
+
+#define FMT(a,b) a, b
+#define PTRS_PER_FORMAT 2
+
+static const char *const arith[8] = { "*", "*-", "*+", "??", "BR0-", "*0-", "*0+", "*BR0+" } ;
+static const char *const nextar[16] = { "", "", "", "", "", "", "", "", ",AR0", ",AR1", ",AR2", ",AR3", ",AR4", ",AR5", ",AR6", ",AR7" } ;
+static const char *const cmpmode[4] = { "0 (ARx = AR0)" , "1 (ARx < AR0)" , "2 (ARx > AR0)" , "3 (ARx <> AR0)" } ;
+
+
+static const char *const TMS32025Formats[] = {
+ FMT("0000tttt0aaaaaaa", "add %A,%T"), /* 0xxx */
+ FMT("0000tttt1mmmnnnn", "add %M,%T%N"),
+ FMT("0001tttt0aaaaaaa", "sub %A,%T"), /* 1xxx */
+ FMT("0001tttt1mmmnnnn", "sub %M,%T%N"),
+ FMT("0010tttt0aaaaaaa", "lac %A,%T"), /* 2xxx */
+ FMT("0010tttt1mmmnnnn", "lac %M,%T%N"),
+ FMT("00110rrr0aaaaaaa", "lar %R,%A"), /* 3xxx */
+ FMT("00110rrr1mmmnnnn", "lar %R%M%N"),
+ FMT("001110000aaaaaaa", "mpy %A"), /* 38xx */
+ FMT("001110001mmmnnnn", "mpy %M%N"),
+ FMT("001110010aaaaaaa", "sqra %A"), /* 39xx */
+ FMT("001110011mmmnnnn", "sqra %M%N"),
+ FMT("001110100aaaaaaa", "mpya %A"), /* 3Axx */
+ FMT("001110101mmmnnnn", "mpya %M%N"),
+ FMT("001110110aaaaaaa", "mpys %A"), /* 3Bxx */
+ FMT("001110111mmmnnnn", "mpys %M%N"),
+ FMT("001111000aaaaaaa", "lt %A"), /* 3Cxx */
+ FMT("001111001mmmnnnn", "lt %M%N"),
+ FMT("001111010aaaaaaa", "lta %A"), /* 3Dxx */
+ FMT("001111011mmmnnnn", "lta %M%N"),
+ FMT("001111100aaaaaaa", "ltp %A"), /* 3Exx */
+ FMT("001111101mmmnnnn", "ltp %M%N"),
+ FMT("001111110aaaaaaa", "ltd %A"), /* 3Fxx */
+ FMT("001111111mmmnnnn", "ltd %M%N"),
+ FMT("010000000aaaaaaa", "zalh %A"), /* 40xx */
+ FMT("010000001mmmnnnn", "zalh %M%N"),
+ FMT("010000010aaaaaaa", "zals %A"), /* 41xx */
+ FMT("010000011mmmnnnn", "zals %M%N"),
+ FMT("010000100aaaaaaa", "lact %A"), /* 42xx */
+ FMT("010000101mmmnnnn", "lact %M%N"),
+ FMT("010000110aaaaaaa", "addc %A%S"), /* 43xx */
+ FMT("010000111mmmnnnn", "addc %M%S%N"),
+ FMT("010001000aaaaaaa", "subh %A"), /* 44xx */
+ FMT("010001001mmmnnnn", "subh %M%N"),
+ FMT("010001010aaaaaaa", "subs %A"), /* 45xx */
+ FMT("010001011mmmnnnn", "subs %M%N"),
+ FMT("010001100aaaaaaa", "subt %A"), /* 46xx */
+ FMT("010001101mmmnnnn", "subt %M%N"),
+ FMT("010001110aaaaaaa", "subc %A"), /* 47xx */
+ FMT("010001111mmmnnnn", "subc %M%N"),
+ FMT("010010000aaaaaaa", "addh %A"), /* 48xx */
+ FMT("010010001mmmnnnn", "addh %M%N"),
+ FMT("010010010aaaaaaa", "adds %A"), /* 49xx */
+ FMT("010010011mmmnnnn", "adds %M%N"),
+ FMT("010010100aaaaaaa", "addt %A"), /* 4Axx */
+ FMT("010010101mmmnnnn", "addt %M%N"),
+ FMT("010010110aaaaaaa", "rpt %A"), /* 4Bxx */
+ FMT("010010111mmmnnnn", "rpt %M%N"),
+ FMT("010011000aaaaaaa", "xor %A"), /* 4Cxx */
+ FMT("010011001mmmnnnn", "xor %M%N"),
+ FMT("010011010aaaaaaa", "or %A"), /* 4Dxx */
+ FMT("010011011mmmnnnn", "or %M%N"),
+ FMT("010011100aaaaaaa", "and %A"), /* 4Exx */
+ FMT("010011101mmmnnnn", "and %M%N"),
+ FMT("010011110aaaaaaa", "subb %A"), /* 4Fxx */
+ FMT("010011111mmmnnnn", "subb %M%N"),
+ FMT("010100000aaaaaaa", "lst %A"), /* 50xx */
+ FMT("010100001mmmnnnn", "lst %M%N"),
+ FMT("010100010aaaaaaa", "lst1 %A"), /* 51xx */
+ FMT("010100011mmmnnnn", "lst1 %M%N"),
+ FMT("010100100aaaaaaa", "ldp %A"), /* 52xx */
+ FMT("010100101mmmnnnn", "ldp %M%N"),
+ FMT("010100110aaaaaaa", "lph %A"), /* 53xx */
+ FMT("010100111mmmnnnn", "lph %M%N"),
+ FMT("010101000aaaaaaa", "pshd %A"), /* 54xx */
+ FMT("010101001mmmnnnn", "pshd %M%N"),
+
+/* FMT("010101010aaaaaaa", "mar %A"), 55xx */
+/* MAR direct has been expanded out to all its variations because one of its */
+/* its opcodes is the same as NOP. Actually MAR direct just performs a NOP */
+ FMT("0101010100000000", "nop"), /* 5500 */
+ FMT("0101010100000001", "mar $01"),
+ FMT("0101010100000010", "mar $02"),
+ FMT("0101010100000011", "mar $03"),
+ FMT("0101010100000100", "mar $04"),
+ FMT("0101010100000101", "mar $05"),
+ FMT("0101010100000110", "mar $06"),
+ FMT("0101010100000111", "mar $07"),
+ FMT("0101010100001000", "mar $08"),
+ FMT("0101010100001001", "mar $09"),
+ FMT("0101010100001010", "mar $0A"),
+ FMT("0101010100001011", "mar $0B"),
+ FMT("0101010100001100", "mar $0C"),
+ FMT("0101010100001101", "mar $0D"),
+ FMT("0101010100001110", "mar $0E"),
+ FMT("0101010100001111", "mar $0F"),
+ FMT("010101010001tttt", "mar $1%T"),
+ FMT("010101010010tttt", "mar $2%T"),
+ FMT("010101010011tttt", "mar $3%T"),
+ FMT("010101010100tttt", "mar $4%T"),
+ FMT("010101010101tttt", "mar $5%T"),
+ FMT("010101010110tttt", "mar $6%T"),
+ FMT("010101010111tttt", "mar $7%T"),
+
+/* FMT("010101011mmmnnnn", "mar %M%N"), 55xx */
+/* MAR indirect has been expanded out to all its variations because one of */
+/* its opcodes, is the same as LARP (actually performs the same function) */
+ FMT("0101010110000xxx", "mar *"), /* 558x */
+ FMT("0101010110001kkk", "larp %K"), /* 558x */
+ FMT("010101011001nnnn", "mar *-%N"), /* 558x */
+ FMT("010101011010nnnn", "mar *+%N"),
+ FMT("010101011011nnnn", "mar ??%N"),
+ FMT("010101011100nnnn", "mar *BR0-%N"),
+ FMT("010101011101nnnn", "mar *0-%N"),
+ FMT("010101011110nnnn", "mar *0+%N"),
+ FMT("010101011111nnnn", "mar *BR0+%N"),
+
+ FMT("010101100aaaaaaa", "dmov %A"), /* 56xx */
+ FMT("010101101mmmnnnn", "dmov %M%N"),
+ FMT("010101110aaaaaaa", "bitt %A"), /* 57xx */
+ FMT("010101111mmmnnnn", "bitt %M%N"),
+ FMT("010110000aaaaaaa", "tblr %A"), /* 58xx */
+ FMT("010110001mmmnnnn", "tblr %M%N"),
+ FMT("010110010aaaaaaa", "tblw %A"), /* 59xx */
+ FMT("010110011mmmnnnn", "tblw %M%N"),
+ FMT("010110100aaaaaaa", "sqrs %A"), /* 5Axx */
+ FMT("010110101mmmnnnn", "sqrs %M%N"),
+ FMT("010110110aaaaaaa", "lts %A"), /* 5Bxx */
+ FMT("010110111mmmnnnn", "lts %M%N"),
+ FMT("010111000aaaaaaabbbbbbbbbbbbbbbb", "macd %B,%A"), /* 5Cxx */
+ FMT("010111001mmmnnnnbbbbbbbbbbbbbbbb", "macd %B,%M%N"),
+ FMT("010111010aaaaaaabbbbbbbbbbbbbbbb", "mac %B,%A"), /* 5Dxx */
+ FMT("010111011mmmnnnnbbbbbbbbbbbbbbbb", "mac %B,%M%N"),
+ FMT("010111101mmmnnnnbbbbbbbbbbbbbbbb", "bc %B %M%N"), /* 5Exx */
+ FMT("010111111mmmnnnnbbbbbbbbbbbbbbbb", "bnc %B %M%N"), /* 5Fxx */
+ FMT("01100sss0aaaaaaa", "sacl %A%S"), /* 6xxx */
+ FMT("01100sss1mmmnnnn", "sacl %M%S%N"),
+ FMT("01101sss0aaaaaaa", "sach %A%S"), /* 6Xxx */
+ FMT("01101sss1mmmnnnn", "sach %M%S%N"),
+ FMT("01110rrr0aaaaaaa", "sar %R,%A"), /* 7xxx */
+ FMT("01110rrr1mmmnnnn", "sar %R%M%N"),
+ FMT("011110000aaaaaaa", "sst %A"), /* 78xx */
+ FMT("011110001mmmnnnn", "sst %M%N"),
+ FMT("011110010aaaaaaa", "sst1 %A"), /* 79xx */
+ FMT("011110011mmmnnnn", "sst1 %M%N"),
+ FMT("011110100aaaaaaa", "popd %A"), /* 7Axx */
+ FMT("011110101mmmnnnn", "popd %M%N"),
+ FMT("011110110aaaaaaa", "zalr %A"), /* 7Bxx */
+ FMT("011110111mmmnnnn", "zalr %M%N"),
+ FMT("011111000aaaaaaa", "spl %A"), /* 7Cxx */
+ FMT("011111001mmmnnnn", "spl %M%N"),
+ FMT("011111010aaaaaaa", "sph %A"), /* 7Dxx */
+ FMT("011111011mmmnnnn", "sph %M%N"),
+ FMT("011111100aaaaaaa", "adrk %A"), /* 7Exx */
+ FMT("011111101mmmnnnn", "adrk %M%N"),
+ FMT("011111110aaaaaaa", "sbrk %A"), /* 7Fxx */
+ FMT("011111111mmmnnnn", "sbrk %M%N"),
+ FMT("1000pppp0aaaaaaa", "in %A,%P"), /* 8xxx */
+ FMT("1000pppp1mmmnnnn", "in %M,%P%N"),
+ FMT("1001tttt0aaaaaaa", "bit %A,%T"), /* 9xxx */
+ FMT("1001tttt1mmmnnnn", "bit %M,%T%N"),
+ FMT("101wwwwwwwwwwwww", "mpyk %W"), /* Axxx-Bxxx */
+ FMT("11000rrrdddddddd", "lark %R,%D"), /* Cxxx */
+ FMT("1100100kdddddddd", "ldpk %K%D"), /* Cxxx */
+/* FMT("11001010dddddddd", "lack %D"), CAxx */
+/* LACK has been expanded out to all its variations because one of its */
+/* its opcodes is the same as ZAC. Actually, it performs the same function */
+ FMT("1100101000000000", "zac"), /* CA00 */
+ FMT("1100101000000001", "lack 01h"), /* CAxx */
+ FMT("1100101000000010", "lack 02h"),
+ FMT("1100101000000011", "lack 03h"),
+ FMT("1100101000000100", "lack 04h"),
+ FMT("1100101000000101", "lack 05h"),
+ FMT("1100101000000110", "lack 06h"),
+ FMT("1100101000000111", "lack 07h"),
+ FMT("1100101000001000", "lack 08h"),
+ FMT("1100101000001001", "lack 09h"),
+ FMT("1100101000001010", "lack 0Ah"),
+ FMT("1100101000001011", "lack 0Bh"),
+ FMT("1100101000001100", "lack 0Ch"),
+ FMT("1100101000001101", "lack 0Dh"),
+ FMT("1100101000001110", "lack 0Eh"),
+ FMT("1100101000001111", "lack 0Fh"),
+ FMT("110010100001tttt", "lack 1%T"),
+ FMT("110010100010tttt", "lack 2%T"),
+ FMT("110010100011tttt", "lack 3%T"),
+ FMT("110010100100tttt", "lack 4%T"),
+ FMT("110010100101tttt", "lack 5%T"),
+ FMT("110010100110tttt", "lack 6%T"),
+ FMT("110010100111tttt", "lack 7%T"),
+ FMT("110010101000tttt", "lack 8%T"),
+ FMT("110010101001tttt", "lack 9%T"),
+ FMT("110010101010tttt", "lack A%T"),
+ FMT("110010101011tttt", "lack B%T"),
+ FMT("110010101100tttt", "lack C%T"),
+ FMT("110010101101tttt", "lack D%T"),
+ FMT("110010101110tttt", "lack E%T"),
+ FMT("110010101111tttt", "lack F%T"),
+
+ FMT("11001011dddddddd", "rptk %D"), /* CBxx */
+ FMT("11001100dddddddd", "addk %D"), /* CCxx */
+ FMT("11001101dddddddd", "subk %D"), /* CDxx */
+ FMT("1100111000000000", "eint"), /* CE00 */
+ FMT("1100111000000001", "dint"), /* CE01 */
+ FMT("1100111000000010", "rovm"), /* CE02 */
+ FMT("1100111000000011", "sovm"), /* CE03 */
+ FMT("1100111000000100", "cnfd"), /* CE04 */
+ FMT("1100111000000101", "cnfp"), /* CE05 */
+ FMT("1100111000000110", "rsxm"), /* CE06 */
+ FMT("1100111000000111", "ssxm"), /* CE07 */
+ FMT("11001110000010kk", "spm %K"), /* CE0x */
+ FMT("1100111000001100", "rxf"), /* CE0C */
+ FMT("1100111000001101", "sxf"), /* CE0D */
+ FMT("110011100000111k", "fort %K"), /* CE0x */
+ FMT("1100111000010100", "pac"), /* CE14 */
+ FMT("1100111000010101", "apac"), /* CE15 */
+ FMT("1100111000010110", "spac"), /* CE16 */
+ FMT("1100111000011000", "sfl"), /* CE18 */
+ FMT("1100111000011001", "sfr"), /* CE19 */
+ FMT("1100111000011011", "abs"), /* CE1B */
+ FMT("1100111000011100", "push"), /* CE1C */
+ FMT("1100111000011101", "pop"), /* CE1D */
+ FMT("1100111000011110", "trap"), /* CE1E */
+ FMT("1100111000011111", "idle"), /* CE1F */
+ FMT("1100111000100000", "rtxm"), /* CE20 */
+ FMT("1100111000100001", "stxm"), /* CE21 */
+ FMT("1100111000100011", "neg"), /* CE23 */
+ FMT("1100111000100100", "cala"), /* CE24 */
+ FMT("1100111000100101", "bacc"), /* CE25 */
+ FMT("1100111000100110", "ret"), /* CE26 */
+ FMT("1100111000100111", "cmpl"), /* CE27 */
+ FMT("1100111000110000", "rc"), /* CE30 */
+ FMT("1100111000110001", "sc"), /* CE31 */
+ FMT("1100111000110010", "rtc"), /* CE32 */
+ FMT("1100111000110011", "stc"), /* CE33 */
+ FMT("1100111000110100", "rol"), /* CE34 */
+ FMT("1100111000110101", "ror"), /* CE35 */
+ FMT("1100111000110110", "rfsm"), /* CE36 */
+ FMT("1100111000110111", "sfsm"), /* CE37 */
+ FMT("1100111000111000", "rhm"), /* CE38 */
+ FMT("1100111000111001", "shm"), /* CE39 */
+ FMT("11001110001111kk", "conf %K"), /* CE3x */
+ FMT("11001110010100cc", "cmpr %C"), /* CE5x */
+ FMT("110011101mmm0010", "norm %M"), /* CEx2 */
+ FMT("110011110aaaaaaa", "mpys %A"), /* CFxx */
+ FMT("110011111mmmnnnn", "mpys %M%N"),
+ FMT("11010rrr00000000wwwwwwwwwwwwwwww", "lrlk %R,%W"), /* Dx00 */
+ FMT("1101tttt00000001wwwwwwwwwwwwwwww", "lalk %W,%T"), /* Dx01 */
+ FMT("1101tttt00000010wwwwwwwwwwwwwwww", "adlk %W,%T"), /* Dx02 */
+ FMT("1101tttt00000011wwwwwwwwwwwwwwww", "sblk %W,%T"), /* Dx03 */
+ FMT("1101tttt00000100wwwwwwwwwwwwwwww", "andk %W,%T"), /* Dx04 */
+ FMT("1101tttt00000101wwwwwwwwwwwwwwww", "ork %W,%T"), /* Dx05 */
+ FMT("1101tttt00000110wwwwwwwwwwwwwwww", "xork %W,%T"), /* Dx06 */
+ FMT("1110pppp0aaaaaaa", "out %A,%P"), /* Exxx */
+ FMT("1110pppp1mmmnnnn", "out %M,%P%N"),
+ FMT("111100001mmmnnnnbbbbbbbbbbbbbbbb", "bv %B %M%N"), /* F0xx */
+ FMT("111100011mmmnnnnbbbbbbbbbbbbbbbb", "bgz %B %M%N"), /* F1xx */
+ FMT("111100101mmmnnnnbbbbbbbbbbbbbbbb", "blez %B %M%N"), /* F2xx */
+ FMT("111100111mmmnnnnbbbbbbbbbbbbbbbb", "blz %B %M%N"), /* F3xx */
+ FMT("111101001mmmnnnnbbbbbbbbbbbbbbbb", "bgez %B %M%N"), /* F4xx */
+ FMT("111101011mmmnnnnbbbbbbbbbbbbbbbb", "bnz %B %M%N"), /* F5xx */
+ FMT("111101101mmmnnnnbbbbbbbbbbbbbbbb", "bz %B %M%N"), /* F6xx */
+ FMT("111101111mmmnnnnbbbbbbbbbbbbbbbb", "bnv %B %M%N"), /* F7xx */
+ FMT("111110001mmmnnnnbbbbbbbbbbbbbbbb", "bbz %B %M%N"), /* F8xx */
+ FMT("111110011mmmnnnnbbbbbbbbbbbbbbbb", "bbnz %B %M%N"), /* F9xx */
+ FMT("111110101mmmnnnnbbbbbbbbbbbbbbbb", "bioz %B %M%N"), /* FAxx */
+ FMT("111110111mmmnnnnbbbbbbbbbbbbbbbb", "banz %B %M%N"), /* FBxx */
+ FMT("111111000aaaaaaabbbbbbbbbbbbbbbb", "blkp %B,%A"), /* FCxx */
+ FMT("111111001mmmnnnnbbbbbbbbbbbbbbbb", "blkp %B,%M%N"),
+ FMT("111111010aaaaaaabbbbbbbbbbbbbbbb", "blkd %B,%A"), /* FDxx */
+ FMT("111111011mmmnnnnbbbbbbbbbbbbbbbb", "blkd %B,%M%N"),
+ FMT("111111101mmmnnnnbbbbbbbbbbbbbbbb", "call %B %M%N"), /* FExx */
+ FMT("111111111mmmnnnnbbbbbbbbbbbbbbbb", "b %B %M%N"), /* FFxx */
+ NULL
+};
+
+#define MAX_OPS (((sizeof(TMS32025Formats) / sizeof(TMS32025Formats[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 */
+} TMS32025Opcode;
+
+static TMS32025Opcode Op[MAX_OPS+1];
+static int OpInizialized = 0;
+
+static void InitDasm32025(void)
+{
+ const char *p;
+ const char *const *ops;
+ word mask, bits;
+ int bit;
+ int i;
+
+ ops = TMS32025Formats; i = 0;
+ while (*ops)
+ {
+ p = *ops;
+ mask = 0; bits = 0; bit = 15;
+ 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 'c':
+ case 'd':
+ case 'k':
+ case 'm':
+ case 'n':
+ case 'p':
+ case 'r':
+ case 's':
+ case 't':
+ case 'w':
+ 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( tms32025 )
+{
+ UINT32 flags = 0;
+ int a, b, c, d, k, m, n, p, r, s, t, w, x; /* 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 */
+
+ if (!OpInizialized) InitDasm32025();
+
+ op = -1; /* no matching opcode */
+ code = (oprom[0] << 8) | oprom[1];
+ 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 | DASMFLAG_SUPPORTED;
+ }
+ //buffertmp = buffer;
+ if (Op[op].extcode)
+ {
+ bit = 31;
+ code <<= 16;
+ code |= (opram[2] << 8) | opram[3];
+ cnt++;
+ }
+ else
+ {
+ bit = 15;
+ }
+
+ /* shift out operands */
+ cp = Op[op].parse;
+ a = b = c = d = k = m = n = p = r = s = t = w = x = 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 'c': c <<=1; c |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 'd': d <<=1; d |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 'k': k <<=1; k |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 'm': m <<=1; m |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 'n': n <<=1; n |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 'p': p <<=1; p |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 'r': r <<=1; r |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 's': s <<=1; s |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 't': t <<=1; t |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 'w': w <<=1; w |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 'x': 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, "cal", 3))
+ 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,"%02Xh",a); break;
+ case 'B': sprintf(num,"%04Xh",b); break;
+ case 'C': sprintf(num,"%s",cmpmode[c]); break;
+ case 'D': sprintf(num,"%02Xh",d); break;
+ case 'K': sprintf(num,"%d",k); break;
+ case 'M': sprintf(num,"%s",arith[m]); break;
+ case 'N': sprintf(num,"%s",nextar[n]); break;
+ case 'P': sprintf(num,"PA$%01X",p); break;
+ case 'R': sprintf(num,"AR%d",r); break;
+ case 'S': sprintf(num,",%d",s); break;
+ case 'T': sprintf(num,"%01Xh",t); break;
+ case 'W': sprintf(num,"%04Xh",w); break;
+ case 'X': 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/tms32025/dis32025.c b/trunk/src/emu/cpu/tms32025/dis32025.c
new file mode 100644
index 00000000000..44e458f3ede
--- /dev/null
+++ b/trunk/src/emu/cpu/tms32025/dis32025.c
@@ -0,0 +1,135 @@
+ /**************************************************************************\
+ * Texas Instruments TMS320x25 DSP Disassembler *
+ * *
+ * Copyright Tony La Porta *
+ * Written for the MAME project. *
+ * *
+ * Notes : Data is expected to be read from source file as MSB first. *
+ * This is a word based microcontroller, with addressing *
+ * architecture based on the Harvard addressing scheme. *
+ * *
+ \**************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#include "32025dsm.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("TMS32025 Disassembler 1.1 by Tony La Porta (C)2001-2002+\n\n");
+ printf("Usage: dis32025 <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 = Dasm32025(String_Output,Counter);
+ printf("$%04lX: ",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)],Buffer[((Counter-1)*2)+1]);
+ }
+ else
+ {
+ printf("%02.2x%02.2x ",Buffer[(Counter*2)],Buffer[(Counter*2) + 1]);
+ }
+ 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/tms32025/tms32025.c b/trunk/src/emu/cpu/tms32025/tms32025.c
new file mode 100644
index 00000000000..51e0ea0150d
--- /dev/null
+++ b/trunk/src/emu/cpu/tms32025/tms32025.c
@@ -0,0 +1,2479 @@
+ /**************************************************************************\
+ * Texas Instruments TMS320x25 DSP Emulator *
+ * *
+ * Copyright Tony La Porta *
+ * Written for the MAME project. *
+ * *
+ * *
+ * Three versions of the chip are available, and they are: *
+ * TMS320C25 Internal ROM one time programmed at TI *
+ * TMS320E25 Internal ROM programmable as a normal EPROM *
+ * TMS320P25 Internal ROM programmable once as a normal EPROM only *
+ * These devices can also be used as a MicroController with external ROM *
+ * *
+ * *
+ * Notes : The term 'DMA' within this document, is in reference *
+ * to Direct Memory Addressing, and NOT the usual term *
+ * of Direct Memory Access. *
+ * This is a word based microcontroller, with addressing *
+ * architecture based on the Harvard addressing scheme. *
+ * *
+ * *
+ * *
+ * **** Change Log **** *
+ * *
+ * TLP (2x-May-2001) *
+ * - Work began on this emulator *
+ * TLP (12-Jul-2001) *
+ * - First private release *
+ * TLP (xx-Dec-2001) Ver 0.11 *
+ * - Various undocumented fixes *
+ * TLP (13-Jul-2002) Ver 0.12 *
+ * - Corrected IRQ2 vector pointer *
+ * - Fixed the signedness in many equation based instructions *
+ * - Adjusted the level sensing for the Signal inputs *
+ * - Added the ability to view the CPU in the debugger when it's halted *
+ * TLP (16-Nov-2002) *
+ * - First public release after nearly 1.5 years! *
+ * - Adjusted more signedness instructions (ADDH, SUBC, SUBH, etc) *
+ * TLP (21-Dec-2002) *
+ * - Added memory banking for the CNFD, CNFP and CONF instructions *
+ * - Corrected IRQ masking checks *
+ * TLP (25-Dec-2002) Ver 1.10 *
+ * - Added internal timer *
+ * *
+ \**************************************************************************/
+
+/*****************************************************************************
+ To fix, or currently lacking from this emulator are:
+
+ Fix the levels for S_IN and S_OUT - use assert/release line
+
+ # Support for the built in Timer/Counter Page 91
+ When idling, Counter must still be activly counting down. When counter
+ reaches 0 it should issue a TINT (if it's not masked), then come out of
+ IDLE mode.
+ If TINT is masked, the Timer still needs to count down.
+
+ # Support for the built in Serial Port
+ # Support for the Global memory register
+ # Support for the switch for RAM block 0 banking between RAM and ROM space
+ # Correct the multi-cycle instruction cycle counts
+ # Add support to set ROM & RAM as Internal/External in order to correctly
+ compute cycle timings
+ # Check (read) Hold signal level during execution loop ?
+ # Fix bugs
+ # Fix more bugs :-)
+ # Add/fix other things I forgot
+*****************************************************************************/
+
+/*
+ TMS32025 CONF Mode Decoding Table
+|=======================================|
+| Status bit | Blocks |
+| CNF | B0 | B1 | B2 |
+|------------+---------+---------+------|
+| 0 0 | data | data | data |
+| 1 1 | program | data | data |
+|=======================================|
+
+
+ TMS32026 CONF Mode Decoding Table
+|==================================================|
+| Status bits | Blocks |
+| CNF1 | CNF0 | B0 | B1 | B2 | B3 |
+|------+------+---------+---------+------+---------|
+| 0 | 0 | data | data | data | data |
+| 0 | 1 | program | data | data | data |
+| 1 | 0 | program | program | data | data |
+| 1 | 1 | program | program | data | program |
+|==================================================|
+
+
+
+Table 3-2. TMS32025/26 Memory Blocks
+|=========================================================|
+| Configured As Data Memory |
+|-------+-------TMS320C25--------+-------TMS320C26--------|
+| | | Hexadecimal | | Hexadecimal |
+| Block | Pages | Address | Pages | Address |
+|-------+---------+--------------+---------+--------------|
+| B2 | 0 | 0060h-007Fh | 0 | 0060h-007Fh |
+| B0 | 4-5 | 0200h-02FFh | 4-7 | 0200h-03FFh |
+| B1 | 6-7 | 0300h-03FFh | 8-11 | 0400h-05FFh |
+| B3 | B3 does not exist | 12-15 | 0600h-07FFh |
+|=========================================================|
+| Configured As Program Memory |
+|-------+-------TMS320C25--------+-------TMS320C26--------|
+| | | Hexadecimal | | Hexadecimal |
+| Block | Pages | Address | Pages | Address |
+|-------+---------+--------------+---------+--------------|
+| B2 | B2 is not configurable | B2 is not configurable |
+| B0 | 510-511 | FF00h-FFFFh | 500-503 | FA00h-FBFFh |
+| B1 | B1 is not configurable | 504-507 | FC00h-FDFFh |
+| B3 | B3 does not exist | 508-511 | FE00h-FFFFh |
+|=========================================================|
+*/
+
+
+#include "emu.h"
+#include "debugger.h"
+#include "tms32025.h"
+
+
+#define CLK 4 /* 1 cycle equals 4 clock ticks */ /* PE/DI */
+
+
+
+#define SET_PC(x) do { cpustate->PC = (x); } while (0)
+
+#define P_IN(A) (cpustate->io->read_word((A)<<1))
+#define P_OUT(A,V) (cpustate->io->write_word(((A)<<1),(V)))
+#define S_IN(A) (cpustate->io->read_word((A)<<1))
+#define S_OUT(A,V) (cpustate->io->write_word(((A)<<1),(V)))
+
+#define M_RDOP(A) ((cpustate->pgmmap[(A) >> 7]) ? (cpustate->pgmmap[(A) >> 7][(A) & 0x7f]) : cpustate->direct->read_decrypted_word((A)<<1))
+#define M_RDOP_ARG(A) ((cpustate->pgmmap[(A) >> 7]) ? (cpustate->pgmmap[(A) >> 7][(A) & 0x7f]) : cpustate->direct->read_decrypted_word((A)<<1))
+
+
+
+typedef struct _tms32025_state tms32025_state; /* Page 3-6 (45) shows all registers */
+struct _tms32025_state
+
+{
+ /******************** CPU Internal Registers *******************/
+ UINT16 PREVPC; /* previous program counter */
+ UINT16 PC;
+ UINT16 PFC;
+ UINT16 STR0, STR1;
+ UINT8 IFR;
+ UINT8 RPTC;
+ PAIR ACC;
+ PAIR Preg;
+ UINT16 Treg;
+ UINT16 AR[8];
+ UINT16 STACK[8];
+ PAIR ALU;
+ UINT16 *intRAM;
+ UINT8 timerover;
+
+ /********************** Status data ****************************/
+ PAIR opcode;
+ int idle;
+ int hold;
+ int external_mem_access; /** required for hold mode. Implement it ! */
+ int init_load_addr; /* 0=No, 1=Yes, 2=Once for repeat mode */
+ int tms32025_irq_cycles;
+ int tms32025_dec_cycles;
+ device_irq_callback irq_callback;
+
+ PAIR oldacc;
+ UINT32 memaccess;
+ int icount;
+ int mHackIgnoreARP; /* special handling for lst, lst1 instructions */
+ int waiting_for_serial_frame;
+
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *data;
+ address_space *io;
+
+ UINT16 *pgmmap[0x200];
+ UINT16 *datamap[0x200];
+};
+
+INLINE tms32025_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == TMS32025 ||
+ device->type() == TMS32026);
+ return (tms32025_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/* opcode table entry */
+typedef struct _tms32025_opcode tms32025_opcode;
+struct _tms32025_opcode
+{
+ UINT8 cycles;
+ void (*function)(tms32025_state *);
+};
+/* opcode table entry (Opcode CE has sub-opcodes) */
+typedef struct _tms32025_opcode_CE tms32025_opcode_CE;
+struct _tms32025_opcode_CE
+{
+ UINT8 cycles;
+ void (*function)(tms32025_state *);
+};
+/* opcode table entry (Opcode Dx has sub-opcodes) */
+typedef struct _tms32025_opcode_Dx tms32025_opcode_Dx;
+struct _tms32025_opcode_Dx
+{
+ UINT8 cycles;
+ void (*function)(tms32025_state *);
+};
+
+
+
+/************************** Memory mapped registers ****************/
+#define DRR cpustate->intRAM[0]
+#define DXR cpustate->intRAM[1]
+#define TIM cpustate->intRAM[2]
+#define PRD cpustate->intRAM[3]
+#define IMR cpustate->intRAM[4]
+#define GREG cpustate->intRAM[5]
+
+
+
+/****************************************************************************
+ ******* The following is the Status (Flag) register 0 definition. ********
+| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+| <----ARP---> | OV | OVM | 1 | INTM | <--------------DP---------------> | */
+
+#define ARP_REG 0xe000 /* ARP (Auxiliary Register Pointer) */
+#define OV_FLAG 0x1000 /* OV (Overflow flag) 1 indicates an overflow */
+#define OVM_FLAG 0x0800 /* OVM (Overflow Mode bit) 1 forces ACC overflow to greatest positive or negative saturation value */
+#define INTM_FLAG 0x0200 /* INTM (Interrupt Mask flag) 0 enables maskable interrupts */
+#define DP_REG 0x01ff /* DP (Data bank memory Pointer) */
+
+
+/***********************************************************************************
+ *** The following is the Status (Flag) register 1 definition for TMS32025. ********
+| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+| <----ARB---> | CNF0 | TC | SXM | C | 1 | 1 | HM | FSM | XF | FO | TXM | <-PM-> | */
+
+/*** The following is the Status (Flag) register 1 definition for TMS32026. ***********
+| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+| <----ARB---> | CNF0 | TC | SXM | C | 1 | CNF1 | HM | FSM | XF | FO | TXM | <-PM-> | */
+
+#define ARB_REG 0xe000 /* ARB (Auxiliary Register pointer Backup) */
+#define CNF0_REG 0x1000 /* CNF0 (Onchip RAM CoNFiguration) 0 means B0=data memory, 1means B0=program memory */
+#define CNF1_REG 0x0080 /* CNF1 (Onchip RAM CoNFiguration) 0 means B0=data memory, 1means B0=program memory */
+#define TC_FLAG 0x0800 /* TC (Test Control flag) */
+#define SXM_FLAG 0x0400 /* SXM (Sign eXtension Mode) */
+#define C_FLAG 0x0200 /* C (Carry flag) */
+#define HM_FLAG 0x0040 /* HM (Processor Hold Mode) */
+#define FSM_FLAG 0x0020 /* FSM (Frame Synchronization Mode - for serial port) */
+#define XF_FLAG 0x0010 /* XF (XF output pin status) */
+#define FO_FLAG 0x0008 /* FO (Serial port Format In/Out mode) */
+#define TXM_FLAG 0x0004 /* TXM (Transmit Mode - for serial port) */
+#define PM_REG 0x0003 /* PM (Product shift Mode) */
+
+
+#define OV ( cpustate->STR0 & OV_FLAG) /* OV (Overflow flag) */
+#define OVM ( cpustate->STR0 & OVM_FLAG) /* OVM (Overflow Mode bit) 1 indicates an overflow */
+#define INTM ( cpustate->STR0 & INTM_FLAG) /* INTM (Interrupt enable flag) 0 enables maskable interrupts */
+#define ARP ((cpustate->STR0 & ARP_REG) >> 13) /* ARP (Auxiliary Register Pointer) */
+#define DP ((cpustate->STR0 & DP_REG) << 7) /* DP (Data memory Pointer bit) */
+#define ARB ( cpustate->STR1 & ARB_REG) /* ARB (Backup Auxiliary Register pointer) */
+#define CNF0 ( cpustate->STR1 & CNF0_REG) /* CNF0 (Onchip Ram Config register) */
+#define TC ( cpustate->STR1 & TC_FLAG) /* TC (Test Control Flag) */
+#define SXM ( cpustate->STR1 & SXM_FLAG) /* SXM (Sign Extension Mode) */
+#define CARRY ( cpustate->STR1 & C_FLAG) /* C (Carry Flag for accumulator) */
+#define HM ( cpustate->STR1 & HM_FLAG) /* HM (Processor Hold Mode) */
+#define FSM ( cpustate->STR1 & FSM_FLAG) /* FSM (Frame Synchronization Mode - for serial port) */
+#define XF ( cpustate->STR1 & FSM_FLAG) /* XF (XF output pin status) */
+#define FO ( cpustate->STR1 & FO_FLAG) /* FO (Serial port Format In/Out mode) */
+#define TXM ( cpustate->STR1 & TXM_FLAG) /* TXM (Transmit Mode - for serial port) */
+#define PM ( cpustate->STR1 & PM_REG) /* PM (P register shift Mode. See SHIFT_Preg_TO_ALU below )*/
+
+#define DMA (DP | (cpustate->opcode.b.l & 0x7f)) /* address used in direct memory access operations */
+#define DMApg0 (cpustate->opcode.b.l & 0x7f) /* address used in direct memory access operations for sst instruction */
+#define IND cpustate->AR[ARP] /* address used in indirect memory access operations */
+
+INLINE void CLR0(tms32025_state *cpustate, UINT16 flag) { cpustate->STR0 &= ~flag; cpustate->STR0 |= 0x0400; }
+INLINE void SET0(tms32025_state *cpustate, UINT16 flag) { cpustate->STR0 |= flag; cpustate->STR0 |= 0x0400; }
+INLINE void CLR1(tms32025_state *cpustate, UINT16 flag) { cpustate->STR1 &= ~flag; cpustate->STR1 |= 0x0180; }
+INLINE void SET1(tms32025_state *cpustate, UINT16 flag) { cpustate->STR1 |= flag; cpustate->STR1 |= 0x0180; }
+
+INLINE void MODIFY_DP(tms32025_state *cpustate, int data)
+{
+ cpustate->STR0 &= ~DP_REG;
+ cpustate->STR0 |= (data & DP_REG);
+ cpustate->STR0 |= 0x0400;
+}
+INLINE void MODIFY_PM(tms32025_state *cpustate, int data)
+{
+ cpustate->STR1 &= ~PM_REG;
+ cpustate->STR1 |= (data & PM_REG);
+ cpustate->STR1 |= 0x0180;
+}
+INLINE void MODIFY_ARP(tms32025_state *cpustate, int data)
+{
+ cpustate->STR1 &= ~ARB_REG;
+ cpustate->STR1 |= (cpustate->STR0 & ARP_REG);
+ cpustate->STR1 |= 0x0180;
+ cpustate->STR0 &= ~ARP_REG;
+ cpustate->STR0 |= ((data << 13) & ARP_REG);
+ cpustate->STR0 |= 0x0400;
+}
+
+
+#ifdef UNUSED_FUNCTION
+INLINE void MODIFY_ARB(tms32025_state *cpustate, int data)
+{
+ cpustate->STR1 &= ~ARB_REG;
+ cpustate->STR1 |= ((data << 13) & ARB_REG);
+ cpustate->STR1 |= 0x0180;
+}
+#endif
+
+
+INLINE UINT16 M_RDROM(tms32025_state *cpustate, offs_t addr)
+{
+ UINT16 *ram;
+ addr &= 0xffff;
+ ram = cpustate->pgmmap[addr >> 7];
+ if (ram) return ram[addr & 0x7f];
+ return cpustate->program->read_word(addr << 1);
+}
+
+INLINE void M_WRTROM(tms32025_state *cpustate, offs_t addr, UINT16 data)
+{
+ UINT16 *ram;
+ addr &= 0xffff;
+ ram = cpustate->pgmmap[addr >> 7];
+ if (ram) { ram[addr & 0x7f] = data; }
+ else cpustate->program->write_word(addr << 1, data);
+}
+
+INLINE UINT16 M_RDRAM(tms32025_state *cpustate, offs_t addr)
+{
+ UINT16 *ram;
+ addr &= 0xffff;
+ ram = cpustate->datamap[addr >> 7];
+ if (ram) return ram[addr & 0x7f];
+ return cpustate->data->read_word(addr << 1);
+}
+
+INLINE void M_WRTRAM(tms32025_state *cpustate, offs_t addr, UINT16 data)
+{
+ UINT16 *ram;
+ addr &= 0xffff;
+ ram = cpustate->datamap[addr >> 7];
+ if (ram) {
+ ram[addr & 0x7f] = data;
+ if(addr == 1 && ram == cpustate->intRAM && TXM) {
+ if(FSM)
+ cpustate->waiting_for_serial_frame = 1;
+ else
+ cpustate->IFR |= 0x20;
+ }
+ }
+ else cpustate->data->write_word(addr << 1, data);
+}
+
+
+static UINT16 reverse_carry_add(UINT16 arg0, UINT16 arg1 )
+{
+ UINT16 result = 0;
+ int carry = 0;
+ int count;
+ for( count=0; count<16; count++ )
+ {
+ int sum = (arg0>>15)+(arg1>>15)+carry;
+ result = (result<<1)|(sum&1);
+ carry = sum>>1;
+ arg0<<=1;
+ arg1<<=1;
+ }
+ return result;
+}
+
+INLINE void MODIFY_AR_ARP(tms32025_state *cpustate)
+{ /* modify address register referenced by ARP */
+ switch (cpustate->opcode.b.l & 0x70) /* Cases ordered by predicted useage */
+ {
+ case 0x00: /* 000 nop */
+ break;
+
+ case 0x10: /* 001 *- */
+ cpustate->AR[ARP] -- ;
+ break;
+
+ case 0x20: /* 010 *+ */
+ cpustate->AR[ARP] ++ ;
+ break;
+
+ case 0x30: /* 011 reserved */
+ break;
+
+ case 0x40: /* 100 *BR0- */
+ cpustate->AR[ARP] = reverse_carry_add(cpustate->AR[ARP],-cpustate->AR[0]);
+ break;
+
+ case 0x50: /* 101 *0- */
+ cpustate->AR[ARP] -= cpustate->AR[0];
+ break;
+
+ case 0x60: /* 110 *0+ */
+ cpustate->AR[ARP] += cpustate->AR[0];
+ break;
+
+ case 0x70: /* 111 *BR0+ */
+ cpustate->AR[ARP] += reverse_carry_add(cpustate->AR[ARP],cpustate->AR[0]);
+ break;
+
+ default:
+ break;
+ }
+
+ if( !cpustate->mHackIgnoreARP )
+ {
+ if (cpustate->opcode.b.l & 8)
+ { /* bit 3 determines if new value is loaded into ARP */
+ MODIFY_ARP(cpustate, (cpustate->opcode.b.l & 7) );
+ }
+ }
+}
+
+INLINE void CALCULATE_ADD_CARRY(tms32025_state *cpustate)
+{
+ if ( (UINT32)(cpustate->oldacc.d) > (UINT32)(cpustate->ACC.d) ) {
+ SET1(cpustate, C_FLAG);
+ }
+ else {
+ CLR1(cpustate, C_FLAG);
+ }
+}
+
+INLINE void CALCULATE_SUB_CARRY(tms32025_state *cpustate)
+{
+ if ( (UINT32)(cpustate->oldacc.d) < (UINT32)(cpustate->ACC.d) ) {
+ CLR1(cpustate, C_FLAG);
+ }
+ else {
+ SET1(cpustate, C_FLAG);
+ }
+}
+
+INLINE void CALCULATE_ADD_OVERFLOW(tms32025_state *cpustate, INT32 addval)
+{
+ if ((INT32)(~(cpustate->oldacc.d ^ addval) & (cpustate->oldacc.d ^ cpustate->ACC.d)) < 0)
+ {
+ SET0(cpustate, OV_FLAG);
+ if (OVM)
+ {
+ // Stroff:HACK! support for overflow capping as implemented results in bad DSP floating point math in many
+ // System22 games - for example, the score display in Prop Cycle.
+ // cpustate->ACC.d = ((INT32)cpustate->oldacc.d < 0) ? 0x80000000 : 0x7fffffff;
+ }
+ }
+}
+INLINE void CALCULATE_SUB_OVERFLOW(tms32025_state *cpustate, INT32 subval)
+{
+ if ((INT32)((cpustate->oldacc.d ^ subval) & (cpustate->oldacc.d ^ cpustate->ACC.d)) < 0)
+ {
+ SET0(cpustate, OV_FLAG);
+ if (OVM)
+ {
+ cpustate->ACC.d = ((INT32)cpustate->oldacc.d < 0) ? 0x80000000 : 0x7fffffff;
+ }
+ }
+}
+
+INLINE UINT16 POP_STACK(tms32025_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;
+}
+INLINE void PUSH_STACK(tms32025_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;
+}
+
+INLINE void SHIFT_Preg_TO_ALU(tms32025_state *cpustate)
+{
+ switch(PM) /* PM (in STR1) is the shift mode for Preg */
+ {
+ case 0: cpustate->ALU.d = cpustate->Preg.d; break;
+ case 1: cpustate->ALU.d = (cpustate->Preg.d << 1); break;
+ case 2: cpustate->ALU.d = (cpustate->Preg.d << 4); break;
+ case 3: cpustate->ALU.d = (cpustate->Preg.d >> 6); if (cpustate->Preg.d & 0x80000000) cpustate->ALU.d |= 0xfc000000; break;
+ default: break;
+ }
+}
+
+INLINE void GETDATA(tms32025_state *cpustate, int shift,int signext)
+{
+ if (cpustate->opcode.b.l & 0x80)
+ { /* indirect memory access */
+ cpustate->memaccess = IND;
+ }
+ else
+ { /* direct memory address */
+ cpustate->memaccess = DMA;
+ }
+
+ if (cpustate->memaccess >= 0x800)
+ {
+ cpustate->external_mem_access = 1; /* Pause if hold pin is active */
+ }
+ else
+ {
+ cpustate->external_mem_access = 0;
+ }
+
+ cpustate->ALU.d = (UINT16)M_RDRAM(cpustate, cpustate->memaccess);
+ if (signext) cpustate->ALU.d = (INT16)cpustate->ALU.d;
+ cpustate->ALU.d <<= shift;
+
+ /* next ARP */
+ if (cpustate->opcode.b.l & 0x80) MODIFY_AR_ARP(cpustate);
+}
+
+INLINE void PUTDATA(tms32025_state *cpustate, UINT16 data)
+{
+ if (cpustate->opcode.b.l & 0x80) {
+ if (cpustate->memaccess >= 0x800) cpustate->external_mem_access = 1; /* Pause if hold pin is active */
+ else cpustate->external_mem_access = 0;
+
+ M_WRTRAM(cpustate, IND, data);
+ MODIFY_AR_ARP(cpustate);
+ }
+ else {
+ if (cpustate->memaccess >= 0x800) cpustate->external_mem_access = 1; /* Pause if hold pin is active */
+ else cpustate->external_mem_access = 0;
+
+ M_WRTRAM(cpustate, DMA, data);
+ }
+}
+INLINE void PUTDATA_SST(tms32025_state *cpustate, UINT16 data)
+{
+ if (cpustate->opcode.b.l & 0x80) cpustate->memaccess = IND;
+ else cpustate->memaccess = DMApg0;
+
+ if (cpustate->memaccess >= 0x800) cpustate->external_mem_access = 1; /* Pause if hold pin is active */
+ else cpustate->external_mem_access = 0;
+
+ if (cpustate->opcode.b.l & 0x80) {
+ cpustate->opcode.b.l &= 0xf7; /* Stop ARP changes */
+ MODIFY_AR_ARP(cpustate);
+ }
+ M_WRTRAM(cpustate, cpustate->memaccess, data);
+}
+
+
+/* The following functions are here to fill the void for the */
+/* opcode call functions. These functions are never actually called. */
+static void opcodes_CE(tms32025_state *cpustate) { }
+static void opcodes_Dx(tms32025_state *cpustate) { }
+
+static void illegal(tms32025_state *cpustate)
+{
+ logerror("TMS32025: PC = %04x, Illegal opcode = %04x\n", (cpustate->PC-1), cpustate->opcode.w.l);
+}
+
+static void abst(tms32025_state *cpustate)
+{
+ if ( (INT32)(cpustate->ACC.d) < 0 ) {
+ cpustate->ACC.d = -cpustate->ACC.d;
+ if (cpustate->ACC.d == 0x80000000) {
+ SET0(cpustate, OV_FLAG);
+ if (OVM) cpustate->ACC.d-- ;
+ }
+ }
+ CLR1(cpustate, C_FLAG);
+}
+static void add(tms32025_state *cpustate) /* #### add carry support - see page 3-31 (70) #### */
+{ /* page 10-13 (348) spru031d */
+ cpustate->oldacc.d = cpustate->ACC.d;
+ GETDATA(cpustate, (cpustate->opcode.b.h & 0xf), SXM);
+ cpustate->ACC.d += cpustate->ALU.d;
+
+ CALCULATE_ADD_OVERFLOW(cpustate, cpustate->ALU.d);
+ CALCULATE_ADD_CARRY(cpustate);
+}
+static void addc(tms32025_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ GETDATA(cpustate, 0, 0);
+ if (CARRY) cpustate->ALU.d++;
+ cpustate->ACC.d += cpustate->ALU.d;
+ CALCULATE_ADD_OVERFLOW(cpustate, cpustate->ALU.d);
+ CALCULATE_ADD_CARRY(cpustate);
+}
+static void addh(tms32025_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ GETDATA(cpustate, 0, 0);
+ cpustate->ACC.w.h += cpustate->ALU.w.l;
+ if ((INT16)(~(cpustate->oldacc.w.h ^ cpustate->ALU.w.l) & (cpustate->oldacc.w.h ^ cpustate->ACC.w.h)) < 0) {
+ SET0(cpustate, OV_FLAG);
+ if (OVM)
+ cpustate->ACC.w.h = ((INT16)cpustate->oldacc.w.h < 0) ? 0x8000 : 0x7fff;
+ }
+ if ( ((INT16)(cpustate->oldacc.w.h) < 0) && ((INT16)(cpustate->ACC.w.h) >= 0) ) {
+ SET1(cpustate, C_FLAG);
+ }
+ /* Carry flag is not cleared, if no carry occurred */
+}
+static void addk(tms32025_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ cpustate->ALU.d = (UINT8)cpustate->opcode.b.l;
+ cpustate->ACC.d += cpustate->ALU.d;
+ CALCULATE_ADD_OVERFLOW(cpustate, cpustate->ALU.d);
+ CALCULATE_ADD_CARRY(cpustate);
+}
+static void adds(tms32025_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ GETDATA(cpustate, 0, 0);
+ cpustate->ACC.d += cpustate->ALU.d;
+ CALCULATE_ADD_OVERFLOW(cpustate, cpustate->ALU.d);
+ CALCULATE_ADD_CARRY(cpustate);
+}
+static void addt(tms32025_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ GETDATA(cpustate, (cpustate->Treg & 0xf), SXM);
+ cpustate->ACC.d += cpustate->ALU.d;
+ CALCULATE_ADD_OVERFLOW(cpustate, cpustate->ALU.d);
+ CALCULATE_ADD_CARRY(cpustate);
+}
+static void adlk(tms32025_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ if (SXM) cpustate->ALU.d = (INT16)M_RDOP_ARG(cpustate->PC);
+ else cpustate->ALU.d = (UINT16)M_RDOP_ARG(cpustate->PC);
+ cpustate->PC++;
+ cpustate->ALU.d <<= (cpustate->opcode.b.h & 0xf);
+ cpustate->ACC.d += cpustate->ALU.d;
+ CALCULATE_ADD_OVERFLOW(cpustate, cpustate->ALU.d);
+ CALCULATE_ADD_CARRY(cpustate);
+}
+static void adrk(tms32025_state *cpustate)
+{
+ cpustate->AR[ARP] += cpustate->opcode.b.l;
+}
+static void and_(tms32025_state *cpustate)
+{
+ GETDATA(cpustate, 0, 0);
+ cpustate->ACC.d &= cpustate->ALU.d;
+}
+static void andk(tms32025_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ cpustate->ALU.d = (UINT16)M_RDOP_ARG(cpustate->PC);
+ cpustate->PC++;
+ cpustate->ALU.d <<= (cpustate->opcode.b.h & 0xf);
+ cpustate->ACC.d &= cpustate->ALU.d;
+ cpustate->ACC.d &= 0x7fffffff;
+}
+static void apac(tms32025_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ SHIFT_Preg_TO_ALU(cpustate);
+ cpustate->ACC.d += cpustate->ALU.d;
+ CALCULATE_ADD_OVERFLOW(cpustate, cpustate->ALU.d);
+ CALCULATE_ADD_CARRY(cpustate);
+}
+static void br(tms32025_state *cpustate)
+{
+ SET_PC(M_RDOP_ARG(cpustate->PC));
+ MODIFY_AR_ARP(cpustate);
+}
+static void bacc(tms32025_state *cpustate)
+{
+ SET_PC(cpustate->ACC.w.l);
+}
+static void banz(tms32025_state *cpustate)
+{
+ if (cpustate->AR[ARP]) SET_PC(M_RDOP_ARG(cpustate->PC));
+ else cpustate->PC++ ;
+ MODIFY_AR_ARP(cpustate);
+}
+static void bbnz(tms32025_state *cpustate)
+{
+ if (TC) SET_PC(M_RDOP_ARG(cpustate->PC));
+ else cpustate->PC++ ;
+ MODIFY_AR_ARP(cpustate);
+}
+static void bbz(tms32025_state *cpustate)
+{
+ if (TC == 0) SET_PC(M_RDOP_ARG(cpustate->PC));
+ else cpustate->PC++ ;
+ MODIFY_AR_ARP(cpustate);
+}
+static void bc(tms32025_state *cpustate)
+{
+ if (CARRY) SET_PC(M_RDOP_ARG(cpustate->PC));
+ else cpustate->PC++ ;
+ MODIFY_AR_ARP(cpustate);
+}
+static void bgez(tms32025_state *cpustate)
+{
+ if ( (INT32)(cpustate->ACC.d) >= 0 ) SET_PC(M_RDOP_ARG(cpustate->PC));
+ else cpustate->PC++ ;
+ MODIFY_AR_ARP(cpustate);
+}
+static void bgz(tms32025_state *cpustate)
+{
+ if ( (INT32)(cpustate->ACC.d) > 0 ) SET_PC(M_RDOP_ARG(cpustate->PC));
+ else cpustate->PC++ ;
+ MODIFY_AR_ARP(cpustate);
+}
+static void bioz(tms32025_state *cpustate)
+{
+ if (S_IN(TMS32025_BIO) != CLEAR_LINE) SET_PC(M_RDOP_ARG(cpustate->PC));
+ else cpustate->PC++ ;
+ MODIFY_AR_ARP(cpustate);
+}
+static void bit(tms32025_state *cpustate)
+{
+ GETDATA(cpustate, 0, 0);
+ if (cpustate->ALU.d & (0x8000 >> (cpustate->opcode.b.h & 0xf))) SET1(cpustate, TC_FLAG);
+ else CLR1(cpustate, TC_FLAG);
+}
+static void bitt(tms32025_state *cpustate)
+{
+ GETDATA(cpustate, 0, 0);
+ if (cpustate->ALU.d & (0x8000 >> (cpustate->Treg & 0xf))) SET1(cpustate, TC_FLAG);
+ else CLR1(cpustate, TC_FLAG);
+}
+static void blez(tms32025_state *cpustate)
+{
+ if ( (INT32)(cpustate->ACC.d) <= 0 ) SET_PC(M_RDOP_ARG(cpustate->PC));
+ else cpustate->PC++ ;
+ MODIFY_AR_ARP(cpustate);
+}
+static void blkd(tms32025_state *cpustate)
+{ /** Fix cycle timing **/
+ if (cpustate->init_load_addr) {
+ cpustate->PFC = M_RDOP_ARG(cpustate->PC);
+ cpustate->PC++;
+ }
+ cpustate->ALU.d = M_RDRAM(cpustate, cpustate->PFC);
+ PUTDATA(cpustate, cpustate->ALU.d);
+ cpustate->PFC++;
+ cpustate->tms32025_dec_cycles += (1*CLK);
+}
+static void blkp(tms32025_state *cpustate)
+{ /** Fix cycle timing **/
+ if (cpustate->init_load_addr) {
+ cpustate->PFC = M_RDOP_ARG(cpustate->PC);
+ cpustate->PC++;
+ }
+ cpustate->ALU.d = M_RDROM(cpustate, cpustate->PFC);
+ PUTDATA(cpustate, cpustate->ALU.d);
+ cpustate->PFC++;
+ cpustate->tms32025_dec_cycles += (2*CLK);
+}
+static void blz(tms32025_state *cpustate)
+{
+ if ( (INT32)(cpustate->ACC.d) < 0 ) SET_PC(M_RDOP_ARG(cpustate->PC));
+ else cpustate->PC++ ;
+ MODIFY_AR_ARP(cpustate);
+}
+static void bnc(tms32025_state *cpustate)
+{
+ if (CARRY == 0) SET_PC(M_RDOP_ARG(cpustate->PC));
+ else cpustate->PC++ ;
+ MODIFY_AR_ARP(cpustate);
+}
+static void bnv(tms32025_state *cpustate)
+{
+ if (OV == 0) SET_PC(M_RDOP_ARG(cpustate->PC));
+ else {
+ cpustate->PC++ ;
+ CLR0(cpustate, OV_FLAG);
+ }
+ MODIFY_AR_ARP(cpustate);
+}
+static void bnz(tms32025_state *cpustate)
+{
+ if (cpustate->ACC.d != 0) SET_PC(M_RDOP_ARG(cpustate->PC));
+ else cpustate->PC++ ;
+ MODIFY_AR_ARP(cpustate);
+}
+static void bv(tms32025_state *cpustate)
+{
+ if (OV) {
+ SET_PC(M_RDOP_ARG(cpustate->PC));
+ CLR0(cpustate, OV_FLAG);
+ }
+ else cpustate->PC++ ;
+ MODIFY_AR_ARP(cpustate);
+}
+static void bz(tms32025_state *cpustate)
+{
+ if (cpustate->ACC.d == 0) SET_PC(M_RDOP_ARG(cpustate->PC));
+ else cpustate->PC++ ;
+ MODIFY_AR_ARP(cpustate);
+}
+static void cala(tms32025_state *cpustate)
+{
+ PUSH_STACK(cpustate, cpustate->PC);
+ SET_PC(cpustate->ACC.w.l);
+}
+static void call(tms32025_state *cpustate)
+{
+ cpustate->PC++ ;
+ PUSH_STACK(cpustate, cpustate->PC);
+ SET_PC(M_RDOP_ARG((cpustate->PC - 1)));
+ MODIFY_AR_ARP(cpustate);
+}
+static void cmpl(tms32025_state *cpustate)
+{
+ cpustate->ACC.d = (~cpustate->ACC.d);
+}
+static void cmpr(tms32025_state *cpustate)
+{
+ switch (cpustate->opcode.b.l & 3)
+ {
+ case 00: if ( (UINT16)(cpustate->AR[ARP]) == (UINT16)(cpustate->AR[0]) ) SET1(cpustate, TC_FLAG);
+ else CLR1(cpustate, TC_FLAG);
+ break;
+ case 01: if ( (UINT16)(cpustate->AR[ARP]) < (UINT16)(cpustate->AR[0]) ) SET1(cpustate, TC_FLAG);
+ else CLR1(cpustate, TC_FLAG);
+ break;
+ case 02: if ( (UINT16)(cpustate->AR[ARP]) > (UINT16)(cpustate->AR[0]) ) SET1(cpustate, TC_FLAG);
+ else CLR1(cpustate, TC_FLAG);
+ break;
+ case 03: if ( (UINT16)(cpustate->AR[ARP]) != (UINT16)(cpustate->AR[0]) ) SET1(cpustate, TC_FLAG);
+ else CLR1(cpustate, TC_FLAG);
+ break;
+ default: break;
+ }
+}
+static void cnfd(tms32025_state *cpustate) /** next two fetches need to use previous CNF value ! **/
+{
+ CLR1(cpustate, CNF0_REG);
+ cpustate->datamap[4] = &cpustate->intRAM[0x200]; /* B0 */
+ cpustate->datamap[5] = &cpustate->intRAM[0x280]; /* B0 */
+ cpustate->pgmmap[510] = NULL;
+ cpustate->pgmmap[511] = NULL;
+}
+static void cnfp(tms32025_state *cpustate) /** next two fetches need to use previous CNF value ! **/
+{
+ SET1(cpustate, CNF0_REG);
+ cpustate->datamap[4] = NULL; /* B0 */
+ cpustate->datamap[5] = NULL; /* B0 */
+ cpustate->pgmmap[510] = &cpustate->intRAM[0x200];
+ cpustate->pgmmap[511] = &cpustate->intRAM[0x280];
+}
+static void conf(tms32025_state *cpustate) /** Need to reconfigure the memory blocks */
+{
+ switch (cpustate->opcode.b.l & 3)
+ {
+ case 00: CLR1(cpustate, CNF1_REG); CLR1(cpustate, CNF0_REG);
+ cpustate->datamap[4] = &cpustate->intRAM[0x200]; /* B0 */
+ cpustate->datamap[5] = &cpustate->intRAM[0x280]; /* B0 */
+ cpustate->datamap[6] = &cpustate->intRAM[0x300]; /* B0 */
+ cpustate->datamap[7] = &cpustate->intRAM[0x380]; /* B0 */
+ cpustate->datamap[8] = &cpustate->intRAM[0x400]; /* B1 */
+ cpustate->datamap[9] = &cpustate->intRAM[0x480]; /* B1 */
+ cpustate->datamap[10] = &cpustate->intRAM[0x500]; /* B1 */
+ cpustate->datamap[11] = &cpustate->intRAM[0x580]; /* B1 */
+ cpustate->datamap[12] = &cpustate->intRAM[0x600]; /* B3 */
+ cpustate->datamap[13] = &cpustate->intRAM[0x680]; /* B3 */
+ cpustate->datamap[14] = &cpustate->intRAM[0x700]; /* B3 */
+ cpustate->datamap[15] = &cpustate->intRAM[0x780]; /* B3 */
+ cpustate->pgmmap[500] = NULL;
+ cpustate->pgmmap[501] = NULL;
+ cpustate->pgmmap[502] = NULL;
+ cpustate->pgmmap[503] = NULL;
+ cpustate->pgmmap[504] = NULL;
+ cpustate->pgmmap[505] = NULL;
+ cpustate->pgmmap[506] = NULL;
+ cpustate->pgmmap[507] = NULL;
+ cpustate->pgmmap[508] = NULL;
+ cpustate->pgmmap[509] = NULL;
+ cpustate->pgmmap[510] = NULL;
+ cpustate->pgmmap[511] = NULL;
+ break;
+
+ case 01: CLR1(cpustate, CNF1_REG); SET1(cpustate, CNF0_REG);
+ cpustate->datamap[4] = NULL;
+ cpustate->datamap[5] = NULL;
+ cpustate->datamap[6] = NULL;
+ cpustate->datamap[7] = NULL;
+ cpustate->datamap[8] = &cpustate->intRAM[0x400]; /* B1 */
+ cpustate->datamap[9] = &cpustate->intRAM[0x480]; /* B1 */
+ cpustate->datamap[10] = &cpustate->intRAM[0x500]; /* B1 */
+ cpustate->datamap[11] = &cpustate->intRAM[0x580]; /* B1 */
+ cpustate->datamap[12] = &cpustate->intRAM[0x600]; /* B3 */
+ cpustate->datamap[13] = &cpustate->intRAM[0x680]; /* B3 */
+ cpustate->datamap[14] = &cpustate->intRAM[0x700]; /* B3 */
+ cpustate->datamap[15] = &cpustate->intRAM[0x780]; /* B3 */
+ cpustate->pgmmap[500] = &cpustate->intRAM[0x200]; /* B0 */
+ cpustate->pgmmap[501] = &cpustate->intRAM[0x280]; /* B0 */
+ cpustate->pgmmap[502] = &cpustate->intRAM[0x300]; /* B0 */
+ cpustate->pgmmap[503] = &cpustate->intRAM[0x380]; /* B0 */
+ cpustate->pgmmap[504] = NULL;
+ cpustate->pgmmap[505] = NULL;
+ cpustate->pgmmap[506] = NULL;
+ cpustate->pgmmap[507] = NULL;
+ cpustate->pgmmap[508] = NULL;
+ cpustate->pgmmap[509] = NULL;
+ cpustate->pgmmap[510] = NULL;
+ cpustate->pgmmap[511] = NULL;
+ break;
+
+ case 02: SET1(cpustate, CNF1_REG); CLR1(cpustate, CNF0_REG);
+ cpustate->datamap[4] = NULL;
+ cpustate->datamap[5] = NULL;
+ cpustate->datamap[6] = NULL;
+ cpustate->datamap[7] = NULL;
+ cpustate->datamap[8] = NULL;
+ cpustate->datamap[9] = NULL;
+ cpustate->datamap[10] = NULL;
+ cpustate->datamap[11] = NULL;
+ cpustate->datamap[12] = &cpustate->intRAM[0x600]; /* B3 */
+ cpustate->datamap[13] = &cpustate->intRAM[0x680]; /* B3 */
+ cpustate->datamap[14] = &cpustate->intRAM[0x700]; /* B3 */
+ cpustate->datamap[15] = &cpustate->intRAM[0x780]; /* B3 */
+ cpustate->pgmmap[500] = &cpustate->intRAM[0x200]; /* B0 */
+ cpustate->pgmmap[501] = &cpustate->intRAM[0x280]; /* B0 */
+ cpustate->pgmmap[502] = &cpustate->intRAM[0x300]; /* B0 */
+ cpustate->pgmmap[503] = &cpustate->intRAM[0x380]; /* B0 */
+ cpustate->pgmmap[504] = &cpustate->intRAM[0x400]; /* B1 */
+ cpustate->pgmmap[505] = &cpustate->intRAM[0x480]; /* B1 */
+ cpustate->pgmmap[506] = &cpustate->intRAM[0x500]; /* B1 */
+ cpustate->pgmmap[507] = &cpustate->intRAM[0x580]; /* B1 */
+ cpustate->pgmmap[508] = NULL;
+ cpustate->pgmmap[509] = NULL;
+ cpustate->pgmmap[510] = NULL;
+ cpustate->pgmmap[511] = NULL;
+ break;
+
+ case 03: SET1(cpustate, CNF1_REG); SET1(cpustate, CNF0_REG);
+ cpustate->datamap[4] = NULL;
+ cpustate->datamap[5] = NULL;
+ cpustate->datamap[6] = NULL;
+ cpustate->datamap[7] = NULL;
+ cpustate->datamap[8] = NULL;
+ cpustate->datamap[9] = NULL;
+ cpustate->datamap[10] = NULL;
+ cpustate->datamap[11] = NULL;
+ cpustate->datamap[12] = NULL;
+ cpustate->datamap[13] = NULL;
+ cpustate->datamap[14] = NULL;
+ cpustate->datamap[15] = NULL;
+ cpustate->pgmmap[500] = &cpustate->intRAM[0x200]; /* B0 */
+ cpustate->pgmmap[501] = &cpustate->intRAM[0x280]; /* B0 */
+ cpustate->pgmmap[502] = &cpustate->intRAM[0x300]; /* B0 */
+ cpustate->pgmmap[503] = &cpustate->intRAM[0x380]; /* B0 */
+ cpustate->pgmmap[504] = &cpustate->intRAM[0x400]; /* B1 */
+ cpustate->pgmmap[505] = &cpustate->intRAM[0x480]; /* B1 */
+ cpustate->pgmmap[506] = &cpustate->intRAM[0x500]; /* B1 */
+ cpustate->pgmmap[507] = &cpustate->intRAM[0x580]; /* B1 */
+ cpustate->pgmmap[508] = &cpustate->intRAM[0x600]; /* B3 */
+ cpustate->pgmmap[509] = &cpustate->intRAM[0x680]; /* B3 */
+ cpustate->pgmmap[510] = &cpustate->intRAM[0x700]; /* B3 */
+ cpustate->pgmmap[511] = &cpustate->intRAM[0x780]; /* B3 */
+ break;
+
+ default: break;
+ }
+}
+static void dint(tms32025_state *cpustate)
+{
+ SET0(cpustate, INTM_FLAG);
+}
+static void dmov(tms32025_state *cpustate) /** Careful with how memory is configured !! */
+{
+ GETDATA(cpustate, 0, 0);
+ M_WRTRAM(cpustate, (cpustate->memaccess + 1), cpustate->ALU.w.l);
+}
+static void eint(tms32025_state *cpustate)
+{
+ CLR0(cpustate, INTM_FLAG);
+}
+static void fort(tms32025_state *cpustate)
+{
+ if (cpustate->opcode.b.l & 1) SET1(cpustate, FO_FLAG);
+ else CLR1(cpustate, FO_FLAG);
+}
+static void idle(tms32025_state *cpustate)
+{
+ CLR0(cpustate, INTM_FLAG);
+ cpustate->idle = 1;
+}
+static void in(tms32025_state *cpustate)
+{
+ cpustate->ALU.w.l = P_IN( (cpustate->opcode.b.h & 0xf) );
+ PUTDATA(cpustate, cpustate->ALU.w.l);
+}
+static void lac(tms32025_state *cpustate)
+{
+ GETDATA(cpustate, (cpustate->opcode.b.h & 0xf), SXM);
+ cpustate->ACC.d = cpustate->ALU.d;
+}
+static void lack(tms32025_state *cpustate) /* ZAC is a subset of this instruction */
+{
+ cpustate->ACC.d = (UINT8)cpustate->opcode.b.l;
+}
+static void lact(tms32025_state *cpustate)
+{
+ GETDATA(cpustate, (cpustate->Treg & 0xf), SXM);
+ cpustate->ACC.d = cpustate->ALU.d;
+}
+static void lalk(tms32025_state *cpustate)
+{
+ if (SXM) {
+ cpustate->ALU.d = (INT16)M_RDOP_ARG(cpustate->PC);
+ cpustate->ACC.d = cpustate->ALU.d << (cpustate->opcode.b.h & 0xf);
+ }
+ else {
+ cpustate->ALU.d = (UINT16)M_RDOP_ARG(cpustate->PC);
+ cpustate->ACC.d = cpustate->ALU.d << (cpustate->opcode.b.h & 0xf);
+ cpustate->ACC.d &= 0x7fffffff;
+ }
+ cpustate->PC++;
+}
+static void lar_ar0(tms32025_state *cpustate) { GETDATA(cpustate, 0, 0); cpustate->AR[0] = cpustate->ALU.w.l; }
+static void lar_ar1(tms32025_state *cpustate) { GETDATA(cpustate, 0, 0); cpustate->AR[1] = cpustate->ALU.w.l; }
+static void lar_ar2(tms32025_state *cpustate) { GETDATA(cpustate, 0, 0); cpustate->AR[2] = cpustate->ALU.w.l; }
+static void lar_ar3(tms32025_state *cpustate) { GETDATA(cpustate, 0, 0); cpustate->AR[3] = cpustate->ALU.w.l; }
+static void lar_ar4(tms32025_state *cpustate) { GETDATA(cpustate, 0, 0); cpustate->AR[4] = cpustate->ALU.w.l; }
+static void lar_ar5(tms32025_state *cpustate) { GETDATA(cpustate, 0, 0); cpustate->AR[5] = cpustate->ALU.w.l; }
+static void lar_ar6(tms32025_state *cpustate) { GETDATA(cpustate, 0, 0); cpustate->AR[6] = cpustate->ALU.w.l; }
+static void lar_ar7(tms32025_state *cpustate) { GETDATA(cpustate, 0, 0); cpustate->AR[7] = cpustate->ALU.w.l; }
+static void lark_ar0(tms32025_state *cpustate) { cpustate->AR[0] = cpustate->opcode.b.l; }
+static void lark_ar1(tms32025_state *cpustate) { cpustate->AR[1] = cpustate->opcode.b.l; }
+static void lark_ar2(tms32025_state *cpustate) { cpustate->AR[2] = cpustate->opcode.b.l; }
+static void lark_ar3(tms32025_state *cpustate) { cpustate->AR[3] = cpustate->opcode.b.l; }
+static void lark_ar4(tms32025_state *cpustate) { cpustate->AR[4] = cpustate->opcode.b.l; }
+static void lark_ar5(tms32025_state *cpustate) { cpustate->AR[5] = cpustate->opcode.b.l; }
+static void lark_ar6(tms32025_state *cpustate) { cpustate->AR[6] = cpustate->opcode.b.l; }
+static void lark_ar7(tms32025_state *cpustate) { cpustate->AR[7] = cpustate->opcode.b.l; }
+static void ldp(tms32025_state *cpustate)
+{
+ GETDATA(cpustate, 0, 0);
+ MODIFY_DP(cpustate, cpustate->ALU.d & 0x1ff);
+}
+static void ldpk(tms32025_state *cpustate)
+{
+ MODIFY_DP(cpustate, cpustate->opcode.w.l & 0x1ff);
+}
+static void lph(tms32025_state *cpustate)
+{
+ GETDATA(cpustate, 0, 0);
+ cpustate->Preg.w.h = cpustate->ALU.w.l;
+}
+static void lrlk(tms32025_state *cpustate)
+{
+ cpustate->ALU.d = (UINT16)M_RDOP_ARG(cpustate->PC);
+ cpustate->PC++;
+ cpustate->AR[cpustate->opcode.b.h & 7] = cpustate->ALU.w.l;
+}
+static void lst(tms32025_state *cpustate)
+{
+ cpustate->mHackIgnoreARP = 1;
+ GETDATA(cpustate, 0, 0);
+ cpustate->mHackIgnoreARP = 0;
+
+ cpustate->ALU.w.l &= (~INTM_FLAG);
+ cpustate->STR0 &= INTM_FLAG;
+ cpustate->STR0 |= cpustate->ALU.w.l; /* Must not affect INTM */
+ cpustate->STR0 |= 0x0400;
+}
+static void lst1(tms32025_state *cpustate)
+{
+ cpustate->mHackIgnoreARP = 1;
+ GETDATA(cpustate, 0, 0);
+ cpustate->mHackIgnoreARP = 0;
+
+ cpustate->STR1 = cpustate->ALU.w.l;
+ cpustate->STR1 |= 0x0180;
+ cpustate->STR0 &= (~ARP_REG); /* ARB also gets copied to ARP */
+ cpustate->STR0 |= (cpustate->STR1 & ARB_REG);
+}
+static void lt(tms32025_state *cpustate)
+{
+ GETDATA(cpustate, 0, 0);
+ cpustate->Treg = cpustate->ALU.w.l;
+}
+static void lta(tms32025_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ GETDATA(cpustate, 0, 0);
+ cpustate->Treg = cpustate->ALU.w.l;
+ SHIFT_Preg_TO_ALU(cpustate);
+ cpustate->ACC.d += cpustate->ALU.d;
+ CALCULATE_ADD_OVERFLOW(cpustate, cpustate->ALU.d);
+ CALCULATE_ADD_CARRY(cpustate);
+}
+static void ltd(tms32025_state *cpustate) /** Careful with how memory is configured !! */
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ GETDATA(cpustate, 0, 0);
+ cpustate->Treg = cpustate->ALU.w.l;
+ M_WRTRAM(cpustate, (cpustate->memaccess+1), cpustate->ALU.w.l);
+ SHIFT_Preg_TO_ALU(cpustate);
+ cpustate->ACC.d += cpustate->ALU.d;
+ CALCULATE_ADD_OVERFLOW(cpustate, cpustate->ALU.d);
+ CALCULATE_ADD_CARRY(cpustate);
+}
+static void ltp(tms32025_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ GETDATA(cpustate, 0, 0);
+ cpustate->Treg = cpustate->ALU.w.l;
+ SHIFT_Preg_TO_ALU(cpustate);
+ cpustate->ACC.d = cpustate->ALU.d;
+}
+static void lts(tms32025_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ GETDATA(cpustate, 0, 0);
+ cpustate->Treg = cpustate->ALU.w.l;
+ SHIFT_Preg_TO_ALU(cpustate);
+ cpustate->ACC.d -= cpustate->ALU.d;
+ CALCULATE_SUB_OVERFLOW(cpustate, cpustate->ALU.d);
+ CALCULATE_SUB_CARRY(cpustate);
+}
+static void mac(tms32025_state *cpustate) /** RAM blocks B0,B1,B2 may be important ! */
+{ /** Fix cycle timing **/
+ cpustate->oldacc.d = cpustate->ACC.d;
+ if (cpustate->init_load_addr) {
+ cpustate->PFC = M_RDOP_ARG(cpustate->PC);
+ cpustate->PC++;
+ }
+ SHIFT_Preg_TO_ALU(cpustate);
+ cpustate->ACC.d += cpustate->ALU.d;
+ CALCULATE_ADD_OVERFLOW(cpustate, cpustate->ALU.d);
+ CALCULATE_ADD_CARRY(cpustate);
+ GETDATA(cpustate, 0, 0);
+ cpustate->Treg = cpustate->ALU.w.l;
+ cpustate->Preg.d = ( (INT16)cpustate->ALU.w.l * (INT16)M_RDROM(cpustate, cpustate->PFC) );
+ cpustate->PFC++;
+ cpustate->tms32025_dec_cycles += (2*CLK);
+}
+static void macd(tms32025_state *cpustate) /** RAM blocks B0,B1,B2 may be important ! */
+{ /** Fix cycle timing **/
+ cpustate->oldacc.d = cpustate->ACC.d;
+ if (cpustate->init_load_addr) {
+ cpustate->PFC = M_RDOP_ARG(cpustate->PC);
+ cpustate->PC++;
+ }
+ SHIFT_Preg_TO_ALU(cpustate);
+ cpustate->ACC.d += cpustate->ALU.d;
+ CALCULATE_ADD_OVERFLOW(cpustate, cpustate->ALU.d);
+ CALCULATE_ADD_CARRY(cpustate);
+ GETDATA(cpustate, 0, 0);
+ if ( (cpustate->opcode.b.l & 0x80) || cpustate->init_load_addr ) { /* No writing during repitition, or DMA mode */
+ M_WRTRAM(cpustate, (cpustate->memaccess+1), cpustate->ALU.w.l);
+ }
+ cpustate->Treg = cpustate->ALU.w.l;
+ cpustate->Preg.d = ( (INT16)cpustate->ALU.w.l * (INT16)M_RDROM(cpustate, cpustate->PFC) );
+ cpustate->PFC++;
+ cpustate->tms32025_dec_cycles += (2*CLK);
+}
+static void mar(tms32025_state *cpustate) /* LARP and NOP are a subset of this instruction */
+{
+ if (cpustate->opcode.b.l & 0x80) MODIFY_AR_ARP(cpustate);
+}
+static void mpy(tms32025_state *cpustate)
+{
+ GETDATA(cpustate, 0, 0);
+ cpustate->Preg.d = (INT16)(cpustate->ALU.w.l) * (INT16)(cpustate->Treg);
+}
+static void mpya(tms32025_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ SHIFT_Preg_TO_ALU(cpustate);
+ cpustate->ACC.d += cpustate->ALU.d;
+ CALCULATE_ADD_OVERFLOW(cpustate, cpustate->ALU.d);
+ CALCULATE_ADD_CARRY(cpustate);
+ GETDATA(cpustate, 0, 0);
+ cpustate->Preg.d = (INT16)(cpustate->ALU.w.l) * (INT16)(cpustate->Treg);
+}
+static void mpyk(tms32025_state *cpustate)
+{
+ cpustate->Preg.d = (INT16)cpustate->Treg * ((INT16)(cpustate->opcode.w.l << 3) >> 3);
+
+}
+static void mpys(tms32025_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ SHIFT_Preg_TO_ALU(cpustate);
+ cpustate->ACC.d -= cpustate->ALU.d;
+ CALCULATE_SUB_OVERFLOW(cpustate, cpustate->ALU.d);
+ CALCULATE_SUB_CARRY(cpustate);
+ GETDATA(cpustate, 0, 0);
+ cpustate->Preg.d = (INT16)(cpustate->ALU.w.l) * (INT16)(cpustate->Treg);
+}
+static void mpyu(tms32025_state *cpustate)
+{
+ GETDATA(cpustate, 0, 0);
+ cpustate->Preg.d = (UINT16)(cpustate->ALU.w.l) * (UINT16)(cpustate->Treg);
+}
+static void neg(tms32025_state *cpustate)
+{
+ if (cpustate->ACC.d == 0x80000000) {
+ SET0(cpustate, OV_FLAG);
+ if (OVM) cpustate->ACC.d = 0x7fffffff;
+ }
+ else cpustate->ACC.d = -cpustate->ACC.d;
+ if (cpustate->ACC.d) CLR0(cpustate, C_FLAG);
+ else SET0(cpustate, C_FLAG);
+}
+/*
+static void nop(tms32025_state *cpustate) { } // NOP is a subset of the MAR instruction
+*/
+static void norm(tms32025_state *cpustate)
+{
+ UINT32 acc = cpustate->ACC.d;
+
+ if( acc == 0 || ((acc^(acc<<1))&(1<<31))!=0 ) {
+ SET1(cpustate, TC_FLAG); /* 1 -> TC */
+ }
+ else {
+ CLR1(cpustate, TC_FLAG); /* 0 -> TC */
+ cpustate->ACC.d <<= 1; /* (ACC)*2 -> ACC */
+ MODIFY_AR_ARP(cpustate);
+ }
+}
+static void or_(tms32025_state *cpustate)
+{
+ GETDATA(cpustate, 0, 0);
+ cpustate->ACC.w.l |= cpustate->ALU.w.l;
+}
+static void ork(tms32025_state *cpustate)
+{
+ cpustate->ALU.d = (UINT16)M_RDOP_ARG(cpustate->PC);
+ cpustate->PC++;
+ cpustate->ALU.d <<= (cpustate->opcode.b.h & 0xf);
+ cpustate->ACC.d |= (cpustate->ALU.d & 0x7fffffff);
+}
+static void out(tms32025_state *cpustate)
+{
+ GETDATA(cpustate, 0, 0);
+ P_OUT( (cpustate->opcode.b.h & 0xf), cpustate->ALU.w.l );
+}
+static void pac(tms32025_state *cpustate)
+{
+ SHIFT_Preg_TO_ALU(cpustate);
+ cpustate->ACC.d = cpustate->ALU.d;
+}
+static void pop(tms32025_state *cpustate)
+{
+ cpustate->ACC.d = (UINT16)POP_STACK(cpustate);
+}
+static void popd(tms32025_state *cpustate)
+{
+ cpustate->ALU.d = (UINT16)POP_STACK(cpustate);
+ PUTDATA(cpustate, cpustate->ALU.w.l);
+}
+static void pshd(tms32025_state *cpustate)
+{
+ GETDATA(cpustate, 0, 0);
+ PUSH_STACK(cpustate, cpustate->ALU.w.l);
+}
+static void push(tms32025_state *cpustate)
+{
+ PUSH_STACK(cpustate, cpustate->ACC.w.l);
+}
+static void rc(tms32025_state *cpustate)
+{
+ CLR1(cpustate, C_FLAG);
+}
+static void ret(tms32025_state *cpustate)
+{
+ SET_PC(POP_STACK(cpustate));
+}
+static void rfsm(tms32025_state *cpustate) /** serial port mode */
+{
+ CLR1(cpustate, FSM_FLAG);
+}
+static void rhm(tms32025_state *cpustate)
+{
+ CLR1(cpustate, HM_FLAG);
+}
+static void rol(tms32025_state *cpustate)
+{
+ cpustate->ALU.d = cpustate->ACC.d;
+ cpustate->ACC.d <<= 1;
+ if (CARRY) cpustate->ACC.d |= 1;
+ if (cpustate->ALU.d & 0x80000000) SET1(cpustate, C_FLAG);
+ else CLR1(cpustate, C_FLAG);
+}
+static void ror(tms32025_state *cpustate)
+{
+ cpustate->ALU.d = cpustate->ACC.d;
+ cpustate->ACC.d >>= 1;
+ if (CARRY) cpustate->ACC.d |= 0x80000000;
+ if (cpustate->ALU.d & 1) SET1(cpustate, C_FLAG);
+ else CLR1(cpustate, C_FLAG);
+}
+static void rovm(tms32025_state *cpustate)
+{
+ CLR0(cpustate, OVM_FLAG);
+}
+static void rpt(tms32025_state *cpustate)
+{
+ GETDATA(cpustate, 0, 0);
+ cpustate->RPTC = cpustate->ALU.b.l;
+ cpustate->init_load_addr = 2; /* Initiate repeat mode */
+}
+static void rptk(tms32025_state *cpustate)
+{
+ cpustate->RPTC = cpustate->opcode.b.l;
+ cpustate->init_load_addr = 2; /* Initiate repeat mode */
+}
+static void rsxm(tms32025_state *cpustate)
+{
+ CLR1(cpustate, SXM_FLAG);
+}
+static void rtc(tms32025_state *cpustate)
+{
+ CLR1(cpustate, TC_FLAG);
+}
+static void rtxm(tms32025_state *cpustate) /** Serial port stuff */
+{
+ CLR1(cpustate, TXM_FLAG);
+}
+static void rxf(tms32025_state *cpustate)
+{
+ CLR1(cpustate, XF_FLAG);
+ S_OUT(TMS32025_XF,CLEAR_LINE);
+}
+static void sach(tms32025_state *cpustate)
+{
+ cpustate->ALU.d = (cpustate->ACC.d << (cpustate->opcode.b.h & 7));
+ PUTDATA(cpustate, cpustate->ALU.w.h);
+}
+static void sacl(tms32025_state *cpustate)
+{
+ cpustate->ALU.d = (cpustate->ACC.d << (cpustate->opcode.b.h & 7));
+ PUTDATA(cpustate, cpustate->ALU.w.l);
+}
+static void sar_ar0(tms32025_state *cpustate) { PUTDATA(cpustate, cpustate->AR[0]); }
+static void sar_ar1(tms32025_state *cpustate) { PUTDATA(cpustate, cpustate->AR[1]); }
+static void sar_ar2(tms32025_state *cpustate) { PUTDATA(cpustate, cpustate->AR[2]); }
+static void sar_ar3(tms32025_state *cpustate) { PUTDATA(cpustate, cpustate->AR[3]); }
+static void sar_ar4(tms32025_state *cpustate) { PUTDATA(cpustate, cpustate->AR[4]); }
+static void sar_ar5(tms32025_state *cpustate) { PUTDATA(cpustate, cpustate->AR[5]); }
+static void sar_ar6(tms32025_state *cpustate) { PUTDATA(cpustate, cpustate->AR[6]); }
+static void sar_ar7(tms32025_state *cpustate) { PUTDATA(cpustate, cpustate->AR[7]); }
+
+static void sblk(tms32025_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ if (SXM) cpustate->ALU.d = (INT16)M_RDOP_ARG(cpustate->PC);
+ else cpustate->ALU.d = (UINT16)M_RDOP_ARG(cpustate->PC);
+ cpustate->PC++;
+ cpustate->ALU.d <<= (cpustate->opcode.b.h & 0xf);
+ cpustate->ACC.d -= cpustate->ALU.d;
+ CALCULATE_SUB_OVERFLOW(cpustate, cpustate->ALU.d);
+ CALCULATE_SUB_CARRY(cpustate);
+}
+static void sbrk_tms(tms32025_state *cpustate)
+{
+ cpustate->AR[ARP] -= cpustate->opcode.b.l;
+}
+static void sc(tms32025_state *cpustate)
+{
+ SET1(cpustate, C_FLAG);
+}
+static void sfl(tms32025_state *cpustate)
+{
+ cpustate->ALU.d = cpustate->ACC.d;
+ cpustate->ACC.d <<= 1;
+ if (cpustate->ALU.d & 0x80000000) SET1(cpustate, C_FLAG);
+ else CLR1(cpustate, C_FLAG);
+}
+static void sfr(tms32025_state *cpustate)
+{
+ cpustate->ALU.d = cpustate->ACC.d;
+ cpustate->ACC.d >>= 1;
+ if (SXM) {
+ if (cpustate->ALU.d & 0x80000000) cpustate->ACC.d |= 0x80000000;
+ }
+ if (cpustate->ALU.d & 1) SET1(cpustate, C_FLAG);
+ else CLR1(cpustate, C_FLAG);
+}
+static void sfsm(tms32025_state *cpustate) /** Serial port mode */
+{
+ SET1(cpustate, FSM_FLAG);
+}
+static void shm(tms32025_state *cpustate)
+{
+ SET1(cpustate, HM_FLAG);
+}
+static void sovm(tms32025_state *cpustate)
+{
+ SET0(cpustate, OVM_FLAG);
+}
+static void spac(tms32025_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ SHIFT_Preg_TO_ALU(cpustate);
+ cpustate->ACC.d -= cpustate->ALU.d;
+ CALCULATE_SUB_OVERFLOW(cpustate, cpustate->ALU.d);
+ CALCULATE_SUB_CARRY(cpustate);
+}
+static void sph(tms32025_state *cpustate)
+{
+ SHIFT_Preg_TO_ALU(cpustate);
+ PUTDATA(cpustate, cpustate->ALU.w.h);
+}
+static void spl(tms32025_state *cpustate)
+{
+ SHIFT_Preg_TO_ALU(cpustate);
+ PUTDATA(cpustate, cpustate->ALU.w.l);
+}
+static void spm(tms32025_state *cpustate)
+{
+ MODIFY_PM(cpustate, (cpustate->opcode.b.l & 3) );
+}
+static void sqra(tms32025_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ SHIFT_Preg_TO_ALU(cpustate);
+ cpustate->ACC.d += cpustate->ALU.d;
+ CALCULATE_ADD_OVERFLOW(cpustate, cpustate->ALU.d);
+ CALCULATE_ADD_CARRY(cpustate);
+ GETDATA(cpustate, 0, 0);
+ cpustate->Treg = cpustate->ALU.w.l;
+ cpustate->Preg.d = ((INT16)cpustate->ALU.w.l * (INT16)cpustate->ALU.w.l);
+}
+static void sqrs(tms32025_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ SHIFT_Preg_TO_ALU(cpustate);
+ cpustate->ACC.d -= cpustate->ALU.d;
+ CALCULATE_SUB_OVERFLOW(cpustate, cpustate->ALU.d);
+ CALCULATE_SUB_CARRY(cpustate);
+ GETDATA(cpustate, 0, 0);
+ cpustate->Treg = cpustate->ALU.w.l;
+ cpustate->Preg.d = ((INT16)cpustate->ALU.w.l * (INT16)cpustate->ALU.w.l);
+}
+static void sst(tms32025_state *cpustate)
+{
+ PUTDATA_SST(cpustate, cpustate->STR0);
+}
+static void sst1(tms32025_state *cpustate)
+{
+ PUTDATA_SST(cpustate, cpustate->STR1);
+}
+static void ssxm(tms32025_state *cpustate)
+{ /** Check instruction description, and make sure right instructions use SXM */
+ SET1(cpustate, SXM_FLAG);
+}
+static void stc(tms32025_state *cpustate)
+{
+ SET1(cpustate, TC_FLAG);
+}
+static void stxm(tms32025_state *cpustate) /** Serial port stuff */
+{
+ SET1(cpustate, TXM_FLAG);
+}
+static void sub(tms32025_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ GETDATA(cpustate, (cpustate->opcode.b.h & 0xf), SXM);
+ cpustate->ACC.d -= cpustate->ALU.d;
+ CALCULATE_SUB_OVERFLOW(cpustate, cpustate->ALU.d);
+ CALCULATE_SUB_CARRY(cpustate);
+}
+static void subb(tms32025_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ GETDATA(cpustate, 0, 0);
+ if (CARRY == 0) cpustate->ALU.d--;
+ cpustate->ACC.d -= cpustate->ALU.d;
+ CALCULATE_SUB_OVERFLOW(cpustate, cpustate->ALU.d);
+ CALCULATE_SUB_CARRY(cpustate);
+}
+
+
+static void subc(tms32025_state *cpustate)
+{
+ /**
+ * conditional subtraction, which may be used for division
+ * execute 16 times for 16-bit division
+ *
+ * input: 32 bit numerator in accumulator
+ * 16 bit denominator in data memory
+ *
+ * output: remainder in upper 16 bits
+ * quotient in lower 16 bits
+ */
+ GETDATA(cpustate, 15, SXM);
+ if( cpustate->ACC.d >= cpustate->ALU.d ) {
+ cpustate->ACC.d = (cpustate->ACC.d - cpustate->ALU.d)*2+1;
+ }
+ else {
+ cpustate->ACC.d = cpustate->ACC.d*2;
+ }
+// Stroff: HACK! support for overflow capping as implemented results in bad DSP floating point math in many
+// System22 games - for example, the score display in Prop Cycle.
+// cpustate->ACC.d = ((INT32)cpustate->oldacc.d < 0) ? 0x80000000 : 0x7fffffff;
+
+// if ((INT32)((cpustate->oldacc.d ^ subval ) & (cpustate->oldacc.d ^ cpustate->ALU.d)) < 0) {
+// SET0(cpustate, OV_FLAG);
+// }
+// CALCULATE_SUB_CARRY(cpustate);
+}
+
+static void subh(tms32025_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ GETDATA(cpustate, 0, 0);
+ cpustate->ACC.w.h -= cpustate->ALU.w.l;
+ if ((INT16)((cpustate->oldacc.w.h ^ cpustate->ALU.w.l) & (cpustate->oldacc.w.h ^ cpustate->ACC.w.h)) < 0) {
+ SET0(cpustate, OV_FLAG);
+ if (OVM)
+ cpustate->ACC.w.h = ((INT16)cpustate->oldacc.w.h < 0) ? 0x8000 : 0x7fff;
+ }
+ if ( ((INT16)(cpustate->oldacc.w.h) >= 0) && ((INT16)(cpustate->ACC.w.h) < 0) ) {
+ CLR1(cpustate, C_FLAG);
+ }
+ /* Carry flag is not affected, if no borrow occurred */
+}
+static void subk(tms32025_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ cpustate->ALU.d = (UINT8)cpustate->opcode.b.l;
+ cpustate->ACC.d -= cpustate->ALU.b.l;
+ CALCULATE_SUB_OVERFLOW(cpustate, cpustate->ALU.d);
+ CALCULATE_SUB_CARRY(cpustate);
+}
+static void subs(tms32025_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ GETDATA(cpustate, 0, 0);
+ cpustate->ACC.d -= cpustate->ALU.w.l;
+ CALCULATE_SUB_OVERFLOW(cpustate, cpustate->ALU.d);
+ CALCULATE_SUB_CARRY(cpustate);
+}
+static void subt(tms32025_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ GETDATA(cpustate, (cpustate->Treg & 0xf), SXM);
+ cpustate->ACC.d -= cpustate->ALU.d;
+ CALCULATE_SUB_OVERFLOW(cpustate, cpustate->ALU.d);
+ CALCULATE_SUB_CARRY(cpustate);
+}
+static void sxf(tms32025_state *cpustate)
+{
+ SET1(cpustate, XF_FLAG);
+ S_OUT(TMS32025_XF,ASSERT_LINE);
+}
+static void tblr(tms32025_state *cpustate)
+{
+ if (cpustate->init_load_addr) {
+ cpustate->PFC = cpustate->ACC.w.l;
+ }
+ cpustate->ALU.w.l = M_RDROM(cpustate, cpustate->PFC);
+ if ( (CNF0) && ( (UINT16)(cpustate->PFC) >= 0xff00 ) ) {} /** TMS32025 only */
+ else cpustate->tms32025_dec_cycles += (1*CLK);
+ PUTDATA(cpustate, cpustate->ALU.w.l);
+ cpustate->PFC++;
+}
+static void tblw(tms32025_state *cpustate)
+{
+ if (cpustate->init_load_addr) {
+ cpustate->PFC = cpustate->ACC.w.l;
+ }
+ cpustate->tms32025_dec_cycles += (1*CLK);
+ GETDATA(cpustate, 0, 0);
+ if (cpustate->external_mem_access) cpustate->tms32025_dec_cycles += (1*CLK);
+ M_WRTROM(cpustate, cpustate->PFC, cpustate->ALU.w.l);
+ cpustate->PFC++;
+}
+static void trap(tms32025_state *cpustate)
+{
+ PUSH_STACK(cpustate, cpustate->PC);
+ SET_PC(0x001E); /* Trap vector */
+}
+static void xor_(tms32025_state *cpustate)
+{
+ GETDATA(cpustate, 0, 0);
+ cpustate->ACC.w.l ^= cpustate->ALU.w.l;
+}
+static void xork(tms32025_state *cpustate)
+{
+ cpustate->oldacc.d = cpustate->ACC.d;
+ cpustate->ALU.d = M_RDOP_ARG(cpustate->PC);
+ cpustate->PC++;
+ cpustate->ALU.d <<= (cpustate->opcode.b.h & 0xf);
+ cpustate->ACC.d ^= cpustate->ALU.d;
+ cpustate->ACC.d |= (cpustate->oldacc.d & 0x80000000);
+}
+static void zalh(tms32025_state *cpustate)
+{
+ GETDATA(cpustate, 0, 0);
+ cpustate->ACC.w.h = cpustate->ALU.w.l;
+ cpustate->ACC.w.l = 0x0000;
+}
+static void zalr(tms32025_state *cpustate)
+{
+ GETDATA(cpustate, 0, 0);
+ cpustate->ACC.w.h = cpustate->ALU.w.l;
+ cpustate->ACC.w.l = 0x8000;
+}
+static void zals(tms32025_state *cpustate)
+{
+ GETDATA(cpustate, 0, 0);
+ cpustate->ACC.w.l = cpustate->ALU.w.l;
+ cpustate->ACC.w.h = 0x0000;
+}
+
+
+/***********************************************************************
+ * Opcode Table (Cycles, Instruction)
+ ***********************************************************************/
+
+static const tms32025_opcode opcode_main[256]=
+{
+/*00*/ {1*CLK, add },{1*CLK, add },{1*CLK, add },{1*CLK, add },{1*CLK, add },{1*CLK, add },{1*CLK, add },{1*CLK, add },
+/*08*/ {1*CLK, add },{1*CLK, add },{1*CLK, add },{1*CLK, add },{1*CLK, add },{1*CLK, add },{1*CLK, add },{1*CLK, add },
+/*10*/ {1*CLK, sub },{1*CLK, sub },{1*CLK, sub },{1*CLK, sub },{1*CLK, sub },{1*CLK, sub },{1*CLK, sub },{1*CLK, sub },
+/*18*/ {1*CLK, sub },{1*CLK, sub },{1*CLK, sub },{1*CLK, sub },{1*CLK, sub },{1*CLK, sub },{1*CLK, sub },{1*CLK, sub },
+/*20*/ {1*CLK, lac },{1*CLK, lac },{1*CLK, lac },{1*CLK, lac },{1*CLK, lac },{1*CLK, lac },{1*CLK, lac },{1*CLK, lac },
+/*28*/ {1*CLK, lac },{1*CLK, lac },{1*CLK, lac },{1*CLK, lac },{1*CLK, lac },{1*CLK, lac },{1*CLK, lac },{1*CLK, lac },
+/*30*/ {1*CLK, lar_ar0 },{1*CLK, lar_ar1 },{1*CLK, lar_ar2 },{1*CLK, lar_ar3 },{1*CLK, lar_ar4 },{1*CLK, lar_ar5 },{1*CLK, lar_ar6 },{1*CLK, lar_ar7 },
+/*38*/ {1*CLK, mpy },{1*CLK, sqra },{1*CLK, mpya },{1*CLK, mpys },{1*CLK, lt },{1*CLK, lta },{1*CLK, ltp },{1*CLK, ltd },
+/*40*/ {1*CLK, zalh },{1*CLK, zals },{1*CLK, lact },{1*CLK, addc },{1*CLK, subh },{1*CLK, subs },{1*CLK, subt },{1*CLK, subc },
+/*48*/ {1*CLK, addh },{1*CLK, adds },{1*CLK, addt },{1*CLK, rpt },{1*CLK, xor_ },{1*CLK, or_ },{1*CLK, and_ },{1*CLK, subb },
+/*50*/ {1*CLK, lst },{1*CLK, lst1 },{1*CLK, ldp },{1*CLK, lph },{1*CLK, pshd },{1*CLK, mar },{1*CLK, dmov },{1*CLK, bitt },
+/*58*/ {3*CLK, tblr },{2*CLK, tblw },{1*CLK, sqrs },{1*CLK, lts },{2*CLK, macd },{2*CLK, mac },{2*CLK, bc },{2*CLK, bnc },
+/*60*/ {1*CLK, sacl },{1*CLK, sacl },{1*CLK, sacl },{1*CLK, sacl },{1*CLK, sacl },{1*CLK, sacl },{1*CLK, sacl },{1*CLK, sacl },
+/*68*/ {1*CLK, sach },{1*CLK, sach },{1*CLK, sach },{1*CLK, sach },{1*CLK, sach },{1*CLK, sach },{1*CLK, sach },{1*CLK, sach },
+/*70*/ {1*CLK, sar_ar0 },{1*CLK, sar_ar1 },{1*CLK, sar_ar2 },{1*CLK, sar_ar3 },{1*CLK, sar_ar4 },{1*CLK, sar_ar5 },{1*CLK, sar_ar6 },{1*CLK, sar_ar7 },
+/*78*/ {1*CLK, sst },{1*CLK, sst1 },{1*CLK, popd },{1*CLK, zalr },{1*CLK, spl },{1*CLK, sph },{1*CLK, adrk },{1*CLK, sbrk_tms },
+/*80*/ {2*CLK, in },{2*CLK, in },{2*CLK, in },{2*CLK, in },{2*CLK, in },{2*CLK, in },{2*CLK, in },{2*CLK, in },
+/*88*/ {2*CLK, in },{2*CLK, in },{2*CLK, in },{2*CLK, in },{2*CLK, in },{2*CLK, in },{2*CLK, in },{2*CLK, in },
+/*90*/ {1*CLK, bit },{1*CLK, bit },{1*CLK, bit },{1*CLK, bit },{1*CLK, bit },{1*CLK, bit },{1*CLK, bit },{1*CLK, bit },
+/*98*/ {1*CLK, bit },{1*CLK, bit },{1*CLK, bit },{1*CLK, bit },{1*CLK, bit },{1*CLK, bit },{1*CLK, bit },{1*CLK, bit },
+/*A0*/ {1*CLK, mpyk },{1*CLK, mpyk },{1*CLK, mpyk },{1*CLK, mpyk },{1*CLK, mpyk },{1*CLK, mpyk },{1*CLK, mpyk },{1*CLK, mpyk },
+/*A8*/ {1*CLK, mpyk },{1*CLK, mpyk },{1*CLK, mpyk },{1*CLK, mpyk },{1*CLK, mpyk },{1*CLK, mpyk },{1*CLK, mpyk },{1*CLK, mpyk },
+/*B0*/ {1*CLK, mpyk },{1*CLK, mpyk },{1*CLK, mpyk },{1*CLK, mpyk },{1*CLK, mpyk },{1*CLK, mpyk },{1*CLK, mpyk },{1*CLK, mpyk },
+/*B8*/ {1*CLK, mpyk },{1*CLK, mpyk },{1*CLK, mpyk },{1*CLK, mpyk },{1*CLK, mpyk },{1*CLK, mpyk },{1*CLK, mpyk },{1*CLK, mpyk },
+/*C0*/ {1*CLK, lark_ar0 },{1*CLK, lark_ar1 },{1*CLK, lark_ar2 },{1*CLK, lark_ar3 },{1*CLK, lark_ar4 },{1*CLK, lark_ar5 },{1*CLK, lark_ar6 },{1*CLK, lark_ar7 },
+/*C8*/ {1*CLK, ldpk },{1*CLK, ldpk },{1*CLK, lack },{1*CLK, rptk },{1*CLK, addk },{1*CLK, subk },{1*CLK, opcodes_CE},{1*CLK, mpyu },
+/*D0*/ {1*CLK,opcodes_Dx},{1*CLK, opcodes_Dx},{1*CLK, opcodes_Dx},{1*CLK, opcodes_Dx},{1*CLK, opcodes_Dx},{1*CLK, opcodes_Dx},{1*CLK, opcodes_Dx},{0*CLK, opcodes_Dx},
+/*D8*/ {1*CLK,opcodes_Dx},{1*CLK, opcodes_Dx},{1*CLK, opcodes_Dx},{1*CLK, opcodes_Dx},{1*CLK, opcodes_Dx},{1*CLK, opcodes_Dx},{1*CLK, opcodes_Dx},{1*CLK, opcodes_Dx},
+/*E0*/ {2*CLK, out },{2*CLK, out },{2*CLK, out },{2*CLK, out },{2*CLK, out },{2*CLK, out },{2*CLK, out },{2*CLK, out },
+/*E8*/ {2*CLK, out },{2*CLK, out },{2*CLK, out },{2*CLK, out },{2*CLK, out },{2*CLK, out },{2*CLK, out },{2*CLK, out },
+/*F0*/ {2*CLK, bv },{2*CLK, bgz },{2*CLK, blez },{2*CLK, blz },{2*CLK, bgez },{2*CLK, bnz },{2*CLK, bz },{2*CLK, bnv },
+/*F8*/ {2*CLK, bbz },{2*CLK, bbnz },{2*CLK, bioz },{2*CLK, banz },{2*CLK, blkp },{2*CLK, blkd },{2*CLK, call },{2*CLK, br }
+};
+
+static const tms32025_opcode_CE opcode_CE_subset[256]= /* Instructions living under the CExx opcode */
+{
+/*00*/ {1*CLK, eint },{1*CLK, dint },{1*CLK, rovm },{1*CLK, sovm },{1*CLK, cnfd },{1*CLK, cnfp },{1*CLK, rsxm },{1*CLK, ssxm },
+/*08*/ {1*CLK, spm },{1*CLK, spm },{1*CLK, spm },{1*CLK, spm },{1*CLK, rxf },{1*CLK, sxf },{1*CLK, fort },{1*CLK, fort },
+/*10*/ {0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{1*CLK, pac },{1*CLK, apac },{1*CLK, spac },{0*CLK, illegal },
+/*18*/ {1*CLK, sfl },{1*CLK, sfr },{0*CLK, illegal },{1*CLK, abst },{1*CLK, push },{1*CLK, pop },{2*CLK, trap },{3*CLK, idle },
+/*20*/ {1*CLK, rtxm },{1*CLK, stxm },{0*CLK, illegal },{1*CLK, neg },{2*CLK, cala },{2*CLK, bacc },{2*CLK, ret },{1*CLK, cmpl },
+/*28*/ {0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },
+/*30*/ {1*CLK, rc },{1*CLK, sc },{1*CLK, rtc },{1*CLK, stc },{1*CLK, rol },{1*CLK, ror },{1*CLK, rfsm },{1*CLK, sfsm },
+/*38*/ {1*CLK, rhm },{1*CLK, shm },{0*CLK, illegal },{0*CLK, illegal },{1*CLK, conf },{1*CLK, conf },{1*CLK, conf },{1*CLK, conf },
+/*40*/ {0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },
+/*48*/ {0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },
+/*50*/ {1*CLK, cmpr },{1*CLK, cmpr },{1*CLK, cmpr },{1*CLK, cmpr },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },
+/*58*/ {0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },
+/*60*/ {0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },
+/*68*/ {0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },
+/*70*/ {0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },
+/*78*/ {0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },
+/*80*/ {0*CLK, illegal },{0*CLK, illegal },{1*CLK, norm },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },
+/*88*/ {0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },
+/*90*/ {0*CLK, illegal },{0*CLK, illegal },{1*CLK, norm },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },
+/*98*/ {0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },
+/*A0*/ {0*CLK, illegal },{0*CLK, illegal },{1*CLK, norm },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },
+/*A8*/ {0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },
+/*B0*/ {0*CLK, illegal },{0*CLK, illegal },{1*CLK, norm },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },
+/*B8*/ {0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },
+/*C0*/ {0*CLK, illegal },{0*CLK, illegal },{1*CLK, norm },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },
+/*C8*/ {0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },
+/*D0*/ {0*CLK, illegal },{0*CLK, illegal },{1*CLK, norm },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },
+/*D8*/ {0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },
+/*E0*/ {0*CLK, illegal },{0*CLK, illegal },{1*CLK, norm },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },
+/*E8*/ {0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },
+/*F0*/ {0*CLK, illegal },{0*CLK, illegal },{1*CLK, norm },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },
+/*F8*/ {0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal },{0*CLK, illegal }
+};
+
+static const tms32025_opcode_Dx opcode_Dx_subset[8]= /* Instructions living under the Dxxx opcode */
+{
+/*00*/ {2*CLK, lrlk },{2*CLK, lalk },{2*CLK, adlk },{2*CLK, sblk },{2*CLK, andk },{2*CLK, ork },{2*CLK, xork },{0*CLK, illegal }
+};
+
+
+
+/****************************************************************************
+ * Inits CPU emulation
+ ****************************************************************************/
+static CPU_INIT( tms32025 )
+{
+ tms32025_state *cpustate = get_safe_token(device);
+
+ cpustate->intRAM = auto_alloc_array(device->machine(), UINT16, 0x800);
+ 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);
+
+ device->save_item(NAME(cpustate->PC));
+ device->save_item(NAME(cpustate->STR0));
+ device->save_item(NAME(cpustate->STR1));
+ device->save_item(NAME(cpustate->PFC));
+ device->save_item(NAME(cpustate->IFR));
+ device->save_item(NAME(cpustate->RPTC));
+ device->save_item(NAME(cpustate->ACC.d));
+ device->save_item(NAME(cpustate->ALU.d));
+ device->save_item(NAME(cpustate->Preg.d));
+ device->save_item(NAME(cpustate->Treg));
+ device->save_item(NAME(cpustate->AR[0]));
+ device->save_item(NAME(cpustate->AR[1]));
+ device->save_item(NAME(cpustate->AR[2]));
+ device->save_item(NAME(cpustate->AR[3]));
+ device->save_item(NAME(cpustate->AR[4]));
+ device->save_item(NAME(cpustate->AR[5]));
+ device->save_item(NAME(cpustate->AR[6]));
+ device->save_item(NAME(cpustate->AR[7]));
+ 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->oldacc));
+ device->save_item(NAME(cpustate->memaccess));
+ device->save_item(NAME(cpustate->icount));
+ device->save_item(NAME(cpustate->mHackIgnoreARP));
+
+ device->save_item(NAME(cpustate->idle));
+ device->save_item(NAME(cpustate->hold));
+ device->save_item(NAME(cpustate->external_mem_access));
+ device->save_item(NAME(cpustate->init_load_addr));
+ device->save_item(NAME(cpustate->PREVPC));
+
+// device->save_pointer(NAME(cpustate->intRAM), 0x800*2);
+}
+
+/****************************************************************************
+ * Reset registers to their initial values
+ ****************************************************************************/
+static CPU_RESET( tms32025 )
+{
+ tms32025_state *cpustate = get_safe_token(device);
+
+ SET_PC(0); /* Starting address on a reset */
+ cpustate->STR0 |= 0x0600; /* INTM and unused bit set to 1 */
+ cpustate->STR0 &= 0xefff; /* OV cleared to 0. Remaining bits undefined */
+ cpustate->STR1 |= 0x07f0; /* SXM, C, HM, FSM, XF and unused bits set to 1 */
+ cpustate->STR1 &= 0xeff0; /* CNF, FO, TXM, PM bits cleared to 0. Remaining bits undefined */
+ cpustate->RPTC = 0; /* Reset repeat counter to 0 */
+ cpustate->IFR = 0; /* IRQ pending flags */
+
+ S_OUT(TMS32025_XF,ASSERT_LINE); /* XF flag is high. Must set the pin */
+
+ /* Set the internal memory mapped registers */
+ GREG = 0;
+ TIM = 0xffff;
+ PRD = 0xffff;
+ IMR = 0xffc0;
+
+ cpustate->idle = 0;
+ cpustate->hold = 0;
+ cpustate->init_load_addr = 1;
+
+ /* Reset the Data/Program address banks */
+ memset(cpustate->pgmmap, 0, sizeof(cpustate->pgmmap));
+ memset(cpustate->datamap, 0, sizeof(cpustate->datamap));
+
+ cpustate->datamap[0] = &cpustate->intRAM[0x000]; /* B2 */
+ cpustate->datamap[4] = &cpustate->intRAM[0x200]; /* B0 */
+ cpustate->datamap[5] = &cpustate->intRAM[0x280]; /* B0 */
+ cpustate->datamap[6] = &cpustate->intRAM[0x300]; /* B1 */
+ cpustate->datamap[7] = &cpustate->intRAM[0x380]; /* B1 */
+}
+
+static CPU_RESET( tms32026 )
+{
+ tms32025_state *cpustate = get_safe_token(device);
+
+ CPU_RESET_CALL(tms32025);
+
+ /* Reset the Data/Program address banks */
+ memset(cpustate->pgmmap, 0, sizeof(cpustate->pgmmap));
+ memset(cpustate->datamap, 0, sizeof(cpustate->datamap));
+
+ cpustate->datamap[0] = &cpustate->intRAM[0x000]; /* B2 */
+ cpustate->datamap[4] = &cpustate->intRAM[0x200]; /* B0 */
+ cpustate->datamap[5] = &cpustate->intRAM[0x280]; /* B0 */
+ cpustate->datamap[6] = &cpustate->intRAM[0x300]; /* B0 */
+ cpustate->datamap[7] = &cpustate->intRAM[0x380]; /* B0 */
+ cpustate->datamap[8] = &cpustate->intRAM[0x400]; /* B1 */
+ cpustate->datamap[9] = &cpustate->intRAM[0x480]; /* B1 */
+ cpustate->datamap[10] = &cpustate->intRAM[0x500]; /* B1 */
+ cpustate->datamap[11] = &cpustate->intRAM[0x580]; /* B1 */
+ cpustate->datamap[12] = &cpustate->intRAM[0x600]; /* B3 */
+ cpustate->datamap[13] = &cpustate->intRAM[0x680]; /* B3 */
+ cpustate->datamap[14] = &cpustate->intRAM[0x700]; /* B3 */
+ cpustate->datamap[15] = &cpustate->intRAM[0x780]; /* B3 */
+}
+
+
+/****************************************************************************
+ * Shut down CPU emulation
+ ****************************************************************************/
+static CPU_EXIT( tms32025 )
+{
+}
+
+
+/****************************************************************************
+ * Issue an interrupt if necessary
+ ****************************************************************************/
+static int process_IRQs(tms32025_state *cpustate)
+{
+ /********** Interrupt Flag Register (IFR) **********
+ | 5 | 4 | 3 | 2 | 1 | 0 |
+ | XINT| RINT| TINT| INT2| INT1| INT0|
+ */
+
+ cpustate->tms32025_irq_cycles = 0;
+
+ /* Dont service Interrupts if masked, or prev instruction was EINT ! */
+
+ if ( (INTM == 0) && (cpustate->opcode.w.l != 0xce00) && (cpustate->IFR & IMR) )
+ {
+ cpustate->tms32025_irq_cycles = (3*CLK); /* 3 clock cycles used due to PUSH and DINT operation ? */
+ PUSH_STACK(cpustate, cpustate->PC);
+
+ if ((cpustate->IFR & 0x01) && (IMR & 0x01)) { /* IRQ line 0 */
+ //logerror("TMS32025: Active INT0\n");
+ SET_PC(0x0002);
+ (*cpustate->irq_callback)(cpustate->device, 0);
+ cpustate->idle = 0;
+ cpustate->IFR &= (~0x01);
+ SET0(cpustate, INTM_FLAG);
+ return cpustate->tms32025_irq_cycles;
+ }
+ if ((cpustate->IFR & 0x02) && (IMR & 0x02)) { /* IRQ line 1 */
+ //logerror("TMS32025: Active INT1\n");
+ SET_PC(0x0004);
+ (*cpustate->irq_callback)(cpustate->device, 1);
+ cpustate->idle = 0;
+ cpustate->IFR &= (~0x02);
+ SET0(cpustate, INTM_FLAG);
+ return cpustate->tms32025_irq_cycles;
+ }
+ if ((cpustate->IFR & 0x04) && (IMR & 0x04)) { /* IRQ line 2 */
+ //logerror("TMS32025: Active INT2\n");
+ SET_PC(0x0006);
+ (*cpustate->irq_callback)(cpustate->device, 2);
+ cpustate->idle = 0;
+ cpustate->IFR &= (~0x04);
+ SET0(cpustate, INTM_FLAG);
+ return cpustate->tms32025_irq_cycles;
+ }
+ if ((cpustate->IFR & 0x08) && (IMR & 0x08)) { /* Timer IRQ (internal) */
+// logerror("TMS32025: Active TINT (Timer)\n");
+ SET_PC(0x0018);
+ cpustate->idle = 0;
+ cpustate->IFR &= (~0x08);
+ SET0(cpustate, INTM_FLAG);
+ return cpustate->tms32025_irq_cycles;
+ }
+ if ((cpustate->IFR & 0x10) && (IMR & 0x10)) { /* Serial port receive IRQ (internal) */
+// logerror("TMS32025: Active RINT (Serial receive)\n");
+ DRR = S_IN(TMS32025_DR);
+ SET_PC(0x001A);
+ cpustate->idle = 0;
+ cpustate->IFR &= (~0x10);
+ SET0(cpustate, INTM_FLAG);
+ return cpustate->tms32025_irq_cycles;
+ }
+ if ((cpustate->IFR & 0x20) && (IMR & 0x20)) { /* Serial port transmit IRQ (internal) */
+// logerror("TMS32025: Active XINT (Serial transmit)\n");
+ S_OUT(TMS32025_DX,DXR);
+ SET_PC(0x001C);
+ cpustate->idle = 0;
+ cpustate->IFR &= (~0x20);
+ SET0(cpustate, INTM_FLAG);
+ return cpustate->tms32025_irq_cycles;
+ }
+ }
+ return cpustate->tms32025_irq_cycles;
+}
+
+static void set_fsx_line(tms32025_state *cpustate, int state)
+{
+ if (state != CLEAR_LINE && cpustate->waiting_for_serial_frame)
+ {
+ cpustate->waiting_for_serial_frame = 0;
+ cpustate->IFR = 0x20;
+ }
+}
+
+INLINE void process_timer(tms32025_state *cpustate, int clocks)
+{
+ int preclocks, ticks;
+
+ /* easy case: no actual ticks */
+again:
+ preclocks = CLK - cpustate->timerover;
+ if (clocks < preclocks)
+ {
+ cpustate->timerover += clocks;
+ cpustate->icount -= clocks;
+ return;
+ }
+
+ /* if we're not going to overflow the timer, just count the clocks */
+ ticks = 1 + (clocks - preclocks) / CLK;
+ if (ticks <= TIM)
+ {
+ cpustate->icount -= clocks;
+ cpustate->timerover = clocks - (ticks - 1) * CLK - preclocks;
+ TIM -= ticks;
+ }
+
+ /* otherwise, overflow the timer and signal an interrupt */
+ else
+ {
+ cpustate->icount -= preclocks + CLK * TIM;
+ cpustate->timerover = 0;
+ TIM = PRD;
+
+ cpustate->IFR |= 0x08;
+ clocks = process_IRQs(cpustate); /* Handle Timer IRQ */
+ goto again;
+ }
+}
+
+
+/****************************************************************************
+ * Execute ICount cycles. Exit when 0 or less
+ ****************************************************************************/
+static CPU_EXECUTE( tms32025 )
+{
+ tms32025_state *cpustate = get_safe_token(device);
+
+
+ /**** Respond to external hold signal */
+ if (S_IN(TMS32025_HOLD) == ASSERT_LINE) {
+ if (cpustate->hold == 0) {
+ S_OUT(TMS32025_HOLDA,ASSERT_LINE); /* Hold-Ack (active low) */
+ }
+ cpustate->hold = 1;
+ if (HM) {
+ cpustate->icount = 0; /* Exit */
+ }
+ else {
+ if (cpustate->external_mem_access) {
+ cpustate->icount = 0; /* Exit */
+ }
+ }
+ }
+ else {
+ if (cpustate->hold == 1) {
+ S_OUT(TMS32025_HOLDA,CLEAR_LINE); /* Hold-Ack (active low) */
+ process_timer(cpustate, 3);
+ }
+ cpustate->hold = 0;
+ }
+
+ /**** If idling, update timer and/or exit execution, but test for irqs first */
+ if (cpustate->idle && cpustate->IFR && cpustate->icount > 0)
+ cpustate->icount -= process_IRQs(cpustate);
+
+ while (cpustate->idle && cpustate->icount > 0)
+ process_timer(cpustate, cpustate->icount);
+
+ if (cpustate->icount <= 0) debugger_instruction_hook(device, cpustate->PC);
+
+
+ while (cpustate->icount > 0)
+ {
+ cpustate->tms32025_dec_cycles = 0;
+
+ if (cpustate->IFR) { /* Check IRQ Flag Register for pending IRQs */
+ cpustate->tms32025_dec_cycles += process_IRQs(cpustate);
+ }
+
+ cpustate->PREVPC = cpustate->PC;
+
+ debugger_instruction_hook(device, cpustate->PC);
+
+ cpustate->opcode.d = M_RDOP(cpustate->PC);
+ cpustate->PC++;
+
+ if (cpustate->opcode.b.h == 0xCE) /* Opcode 0xCExx has many sub-opcodes in its minor byte */
+ {
+ cpustate->tms32025_dec_cycles += opcode_CE_subset[cpustate->opcode.b.l].cycles;
+ (*opcode_CE_subset[cpustate->opcode.b.l].function)(cpustate);
+ }
+ else if ((cpustate->opcode.w.l & 0xf0f8) == 0xd000) /* Opcode 0xDxxx has many sub-opcodes in its minor byte */
+ {
+ cpustate->tms32025_dec_cycles += opcode_Dx_subset[cpustate->opcode.b.l].cycles;
+ (*opcode_Dx_subset[cpustate->opcode.b.l].function)(cpustate);
+ }
+ else /* Do all opcodes except the CExx and Dxxx ones */
+ {
+ cpustate->tms32025_dec_cycles += opcode_main[cpustate->opcode.b.h].cycles;
+ (*opcode_main[cpustate->opcode.b.h].function)(cpustate);
+ }
+
+
+ if (cpustate->init_load_addr == 2) { /* Repeat next instruction */
+ cpustate->PREVPC = cpustate->PC;
+
+ debugger_instruction_hook(device, cpustate->PC);
+
+ cpustate->opcode.d = M_RDOP(cpustate->PC);
+ cpustate->PC++;
+ cpustate->tms32025_dec_cycles += (1*CLK);
+
+ do {
+ if (cpustate->opcode.b.h == 0xCE)
+ { /* Do all 0xCExx Opcodes */
+ if (cpustate->init_load_addr) {
+ cpustate->tms32025_dec_cycles += (1*CLK);
+ }
+ else {
+ cpustate->tms32025_dec_cycles += (1*CLK);
+ }
+ (*opcode_CE_subset[cpustate->opcode.b.l].function)(cpustate);
+ }
+ if ((cpustate->opcode.w.l & 0xf0f8) == 0xd000)
+ { /* Do all valid 0xDxxx Opcodes */
+ if (cpustate->init_load_addr) {
+ cpustate->tms32025_dec_cycles += (1*CLK);
+ }
+ else {
+ cpustate->tms32025_dec_cycles += (1*CLK);
+ }
+ (*opcode_Dx_subset[cpustate->opcode.b.l].function)(cpustate);
+ }
+ else
+ { /* Do all other opcodes */
+ if (cpustate->init_load_addr) {
+ cpustate->tms32025_dec_cycles += (1*CLK);
+ }
+ else {
+ cpustate->tms32025_dec_cycles += (1*CLK);
+ }
+ (*opcode_main[cpustate->opcode.b.h].function)(cpustate);
+ }
+ cpustate->init_load_addr = 0;
+ cpustate->RPTC-- ;
+ } while ((INT8)(cpustate->RPTC) != -1);
+ cpustate->RPTC = 0;
+ cpustate->PFC = cpustate->PC;
+ cpustate->init_load_addr = 1;
+ }
+
+ process_timer(cpustate, cpustate->tms32025_dec_cycles);
+
+ /**** If device is put into idle mode, exit and wait for an interrupt */
+ while (cpustate->idle && cpustate->icount > 0)
+ process_timer(cpustate, cpustate->icount);
+
+
+ /**** If hold pin is active, exit if accessing external memory or if HM is set */
+ if (cpustate->hold) {
+ if (cpustate->external_mem_access || (HM)) {
+ if (cpustate->icount > 0) {
+ cpustate->icount = 0;
+ }
+ }
+ }
+ }
+}
+
+
+
+/****************************************************************************
+ * Set IRQ line state
+ ****************************************************************************/
+static void set_irq_line(tms32025_state *cpustate, int irqline, int state)
+{
+ /* Pending IRQs cannot be cleared */
+
+ if (state != CLEAR_LINE)
+ {
+ cpustate->IFR |= (1 << irqline);
+// cpustate->IFR &= 0x07;
+ }
+}
+
+
+/****************************************************************************
+ * Opcode fetcher
+ ****************************************************************************/
+static CPU_READOP( tms32025 )
+{
+ tms32025_state *cpustate = get_safe_token(device);
+
+ void *ptr;
+
+ /* skip if not custom */
+ if (!cpustate->pgmmap[offset >> 8])
+ return 0;
+
+ ptr = &((UINT8 *)&cpustate->pgmmap[offset >> 8])[offset & 0xff];
+ switch (size)
+ {
+ case 1: *value = *((UINT8 *) ptr);
+ case 2: *value = *((UINT16 *) ptr);
+ case 4: *value = *((UINT32 *) ptr);
+ case 8: *value = *((UINT64 *) ptr);
+ }
+ return 1;
+}
+
+
+/****************************************************************************
+ * Memory reader
+ ****************************************************************************/
+static CPU_READ( tms32025 )
+{
+ tms32025_state *cpustate = get_safe_token(device);
+
+ void *ptr = NULL;
+ UINT64 temp = 0;
+
+ switch (space)
+ {
+ case AS_PROGRAM:
+ ptr = cpustate->pgmmap[offset >> 8];
+ if (!ptr)
+ return 0;
+ break;
+
+ case AS_DATA:
+ ptr = cpustate->datamap[offset >> 8];
+ if (!ptr)
+ return 0;
+ break;
+
+ default:
+ case AS_IO:
+ return 0;
+ }
+
+ switch (size)
+ {
+ case 1:
+ *value = ((UINT8 *)ptr)[BYTE_XOR_BE(offset & 0xff)];
+ break;
+ case 2:
+ *value = ((UINT16 *)ptr)[(offset & 0xff) / 2];
+ break;
+ case 4:
+ CPU_READ_NAME(tms32025)(device, space, offset + 0, 2, &temp);
+ *value = temp << 16;
+ CPU_READ_NAME(tms32025)(device, space, offset + 2, 2, &temp);
+ *value |= temp & 0xffff;
+ break;
+ case 8:
+ CPU_READ_NAME(tms32025)(device, space, offset + 0, 4, &temp);
+ *value = temp << 32;
+ CPU_READ_NAME(tms32025)(device, space, offset + 4, 4, &temp);
+ *value |= temp & 0xffffffff;
+ break;
+ }
+ return 1;
+}
+
+
+/****************************************************************************
+ * Memory writer
+ ****************************************************************************/
+static CPU_WRITE( tms32025 )
+{
+ tms32025_state *cpustate = get_safe_token(device);
+
+ void *ptr = NULL;
+
+ switch (space)
+ {
+ case AS_PROGRAM:
+ ptr = cpustate->pgmmap[offset >> 8];
+ if (!ptr)
+ return 0;
+ break;
+
+ case AS_DATA:
+ ptr = cpustate->datamap[offset >> 8];
+ if (!ptr)
+ return 0;
+ break;
+
+ default:
+ case AS_IO:
+ return 0;
+ }
+
+ switch (size)
+ {
+ case 1:
+ ((UINT8 *)ptr)[BYTE_XOR_BE(offset & 0xff)] = value;
+ break;
+ case 2:
+ ((UINT16 *)ptr)[(offset & 0xff) / 2] = value;
+ break;
+ case 4:
+ CPU_WRITE_NAME(tms32025)(device, space, offset + 0, 2, value >> 16);
+ CPU_WRITE_NAME(tms32025)(device, space, offset + 2, 2, value);
+ break;
+ case 8:
+ CPU_WRITE_NAME(tms32025)(device, space, offset + 0, 4, value >> 32);
+ CPU_WRITE_NAME(tms32025)(device, space, offset + 4, 4, value);
+ break;
+ }
+
+ return 1;
+}
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( tms32025 )
+{
+ tms32025_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 + TMS32025_INT0: set_irq_line(cpustate, TMS32025_INT0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + TMS32025_INT1: set_irq_line(cpustate, TMS32025_INT1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + TMS32025_INT2: set_irq_line(cpustate, TMS32025_INT2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + TMS32025_TINT: set_irq_line(cpustate, TMS32025_TINT, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + TMS32025_RINT: set_irq_line(cpustate, TMS32025_RINT, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + TMS32025_XINT: set_irq_line(cpustate, TMS32025_XINT, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + TMS32025_FSX: set_fsx_line(cpustate, info->i); break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + TMS32025_PC: cpustate->PC = info->i; break;
+ /* This is actually not a stack pointer, but the stack contents */
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + TMS32025_STK7: cpustate->STACK[7] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK6: cpustate->STACK[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK5: cpustate->STACK[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK4: cpustate->STACK[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK3: cpustate->STACK[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK2: cpustate->STACK[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK1: cpustate->STACK[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK0: cpustate->STACK[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STR0: cpustate->STR0 = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STR1: cpustate->STR1 = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_IFR: cpustate->IFR = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_RPTC: cpustate->RPTC = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_ACC: cpustate->ACC.d = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_PREG: cpustate->Preg.d = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_TREG: cpustate->Treg = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR0: cpustate->AR[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR1: cpustate->AR[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR2: cpustate->AR[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR3: cpustate->AR[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR4: cpustate->AR[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR5: cpustate->AR[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR6: cpustate->AR[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR7: cpustate->AR[7] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_DRR: M_WRTRAM(cpustate, 0,info->i); break;
+ case CPUINFO_INT_REGISTER + TMS32025_DXR: M_WRTRAM(cpustate, 1,info->i); break;
+ case CPUINFO_INT_REGISTER + TMS32025_TIM: M_WRTRAM(cpustate, 2,info->i); break;
+ case CPUINFO_INT_REGISTER + TMS32025_PRD: M_WRTRAM(cpustate, 3,info->i); break;
+ case CPUINFO_INT_REGISTER + TMS32025_IMR: M_WRTRAM(cpustate, 4,info->i); break;
+ case CPUINFO_INT_REGISTER + TMS32025_GREG: M_WRTRAM(cpustate, 5,info->i); break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( tms32025 )
+{
+ tms32025_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(tms32025_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_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 = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1*CLK; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 5*CLK; 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 = 16; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 17; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = -1; break;
+
+ case CPUINFO_INT_INPUT_STATE + TMS32025_INT0: info->i = (cpustate->IFR & 0x01) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + TMS32025_INT1: info->i = (cpustate->IFR & 0x02) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + TMS32025_INT2: info->i = (cpustate->IFR & 0x04) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + TMS32025_TINT: info->i = (cpustate->IFR & 0x08) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + TMS32025_RINT: info->i = (cpustate->IFR & 0x10) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + TMS32025_XINT: info->i = (cpustate->IFR & 0x20) ? ASSERT_LINE : CLEAR_LINE; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->PREVPC; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + TMS32025_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 + TMS32025_STK7: info->i = cpustate->STACK[7]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK6: info->i = cpustate->STACK[6]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK5: info->i = cpustate->STACK[5]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK4: info->i = cpustate->STACK[4]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK3: info->i = cpustate->STACK[3]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK2: info->i = cpustate->STACK[2]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK1: info->i = cpustate->STACK[1]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK0: info->i = cpustate->STACK[0]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STR0: info->i = cpustate->STR0; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STR1: info->i = cpustate->STR1; break;
+ case CPUINFO_INT_REGISTER + TMS32025_IFR: info->i = cpustate->IFR; break;
+ case CPUINFO_INT_REGISTER + TMS32025_RPTC: info->i = cpustate->RPTC; break;
+ case CPUINFO_INT_REGISTER + TMS32025_ACC: info->i = cpustate->ACC.d; break;
+ case CPUINFO_INT_REGISTER + TMS32025_PREG: info->i = cpustate->Preg.d; break;
+ case CPUINFO_INT_REGISTER + TMS32025_TREG: info->i = cpustate->Treg; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR0: info->i = cpustate->AR[0]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR1: info->i = cpustate->AR[1]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR2: info->i = cpustate->AR[2]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR3: info->i = cpustate->AR[3]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR4: info->i = cpustate->AR[4]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR5: info->i = cpustate->AR[5]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR6: info->i = cpustate->AR[6]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR7: info->i = cpustate->AR[7]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_DRR: info->i = M_RDRAM(cpustate, 0); break;
+ case CPUINFO_INT_REGISTER + TMS32025_DXR: info->i = M_RDRAM(cpustate, 1); break;
+ case CPUINFO_INT_REGISTER + TMS32025_TIM: info->i = M_RDRAM(cpustate, 2); break;
+ case CPUINFO_INT_REGISTER + TMS32025_PRD: info->i = M_RDRAM(cpustate, 3); break;
+ case CPUINFO_INT_REGISTER + TMS32025_IMR: info->i = M_RDRAM(cpustate, 4); break;
+ case CPUINFO_INT_REGISTER + TMS32025_GREG: info->i = M_RDRAM(cpustate, 5); 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(tms32025); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(tms32025); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(tms32025); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(tms32025); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(tms32025); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(tms32025); break;
+ case CPUINFO_FCT_READ: info->read = CPU_READ_NAME(tms32025); break;
+ case CPUINFO_FCT_WRITE: info->write = CPU_WRITE_NAME(tms32025); break;
+ case CPUINFO_FCT_READOP: info->readop = CPU_READOP_NAME(tms32025); 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, "TMS32025"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Texas Instruments TMS320x25"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.10"); 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, "arp%d%c%c%c%cdp%03x arb%d%c%c%c%c%c%c%c%c%c%c%cpm%d",
+ (cpustate->STR0 & 0xe000) >> 13,
+ cpustate->STR0 & 0x1000 ? 'O':'.',
+ cpustate->STR0 & 0x0800 ? 'M':'.',
+ cpustate->STR0 & 0x0400 ? '.':'?',
+ cpustate->STR0 & 0x0200 ? 'I':'.',
+ (cpustate->STR0 & 0x01ff),
+
+ (cpustate->STR1 & 0xe000) >> 13,
+ cpustate->STR1 & 0x1000 ? 'P':'D',
+ cpustate->STR1 & 0x0800 ? 'T':'.',
+ cpustate->STR1 & 0x0400 ? 'S':'.',
+ cpustate->STR1 & 0x0200 ? 'C':'?',
+ cpustate->STR0 & 0x0100 ? '.':'?',
+ cpustate->STR1 & 0x0080 ? '.':'?',
+ cpustate->STR1 & 0x0040 ? 'H':'.',
+ cpustate->STR1 & 0x0020 ? 'F':'.',
+ cpustate->STR1 & 0x0010 ? 'X':'.',
+ cpustate->STR1 & 0x0008 ? 'f':'.',
+ cpustate->STR1 & 0x0004 ? 'o':'i',
+ (cpustate->STR1 & 0x0003) );
+ break;
+
+ case CPUINFO_STR_REGISTER + TMS32025_PC: sprintf(info->s, "PC:%04X", cpustate->PC); break;
+ case CPUINFO_STR_REGISTER + TMS32025_STR0: sprintf(info->s, "STR0:%04X", cpustate->STR0); break;
+ case CPUINFO_STR_REGISTER + TMS32025_STR1: sprintf(info->s, "STR1:%04X", cpustate->STR1); break;
+ case CPUINFO_STR_REGISTER + TMS32025_IFR: sprintf(info->s, "IFR:%04X", cpustate->IFR); break;
+ case CPUINFO_STR_REGISTER + TMS32025_RPTC: sprintf(info->s, "RPTC:%02X", cpustate->RPTC); break;
+ case CPUINFO_STR_REGISTER + TMS32025_STK7: sprintf(info->s, "STK7:%04X", cpustate->STACK[7]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_STK6: sprintf(info->s, "STK6:%04X", cpustate->STACK[6]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_STK5: sprintf(info->s, "STK5:%04X", cpustate->STACK[5]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_STK4: sprintf(info->s, "STK4:%04X", cpustate->STACK[4]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_STK3: sprintf(info->s, "STK3:%04X", cpustate->STACK[3]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_STK2: sprintf(info->s, "STK2:%04X", cpustate->STACK[2]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_STK1: sprintf(info->s, "STK1:%04X", cpustate->STACK[1]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_STK0: sprintf(info->s, "STK0:%04X", cpustate->STACK[0]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_ACC: sprintf(info->s, "ACC:%08X", cpustate->ACC.d); break;
+ case CPUINFO_STR_REGISTER + TMS32025_PREG: sprintf(info->s, "P:%08X", cpustate->Preg.d); break;
+ case CPUINFO_STR_REGISTER + TMS32025_TREG: sprintf(info->s, "T:%04X", cpustate->Treg); break;
+ case CPUINFO_STR_REGISTER + TMS32025_AR0: sprintf(info->s, "AR0:%04X", cpustate->AR[0]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_AR1: sprintf(info->s, "AR1:%04X", cpustate->AR[1]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_AR2: sprintf(info->s, "AR2:%04X", cpustate->AR[2]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_AR3: sprintf(info->s, "AR3:%04X", cpustate->AR[3]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_AR4: sprintf(info->s, "AR4:%04X", cpustate->AR[4]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_AR5: sprintf(info->s, "AR5:%04X", cpustate->AR[5]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_AR6: sprintf(info->s, "AR6:%04X", cpustate->AR[6]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_AR7: sprintf(info->s, "AR7:%04X", cpustate->AR[7]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_DRR: sprintf(info->s, "DRR:%04X", M_RDRAM(cpustate, 0)); break;
+ case CPUINFO_STR_REGISTER + TMS32025_DXR: sprintf(info->s, "DXR:%04X", M_RDRAM(cpustate, 1)); break;
+ case CPUINFO_STR_REGISTER + TMS32025_TIM: sprintf(info->s, "TIM:%04X", M_RDRAM(cpustate, 2)); break;
+ case CPUINFO_STR_REGISTER + TMS32025_PRD: sprintf(info->s, "PRD:%04X", M_RDRAM(cpustate, 3)); break;
+ case CPUINFO_STR_REGISTER + TMS32025_IMR: sprintf(info->s, "IMR:%04X", M_RDRAM(cpustate, 4)); break;
+ case CPUINFO_STR_REGISTER + TMS32025_GREG: sprintf(info->s, "GREG:%04X", M_RDRAM(cpustate, 5)); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+CPU_GET_INFO( tms32026 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(tms32026); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "TMS32026"); break;
+
+ default: CPU_GET_INFO_CALL(tms32025); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(TMS32025, tms32025);
+DEFINE_LEGACY_CPU_DEVICE(TMS32026, tms32026);
diff --git a/trunk/src/emu/cpu/tms32025/tms32025.h b/trunk/src/emu/cpu/tms32025/tms32025.h
new file mode 100644
index 00000000000..01ecb8b5a8f
--- /dev/null
+++ b/trunk/src/emu/cpu/tms32025/tms32025.h
@@ -0,0 +1,74 @@
+ /**************************************************************************\
+ * Texas Instruments TMS320x25 DSP Emulator *
+ * *
+ * Copyright Tony La Porta *
+ * Written for the MAME project. *
+ * *
+ * Note : This is a word based microcontroller, with addressing *
+ * architecture based on the Harvard addressing scheme. *
+ * *
+ * Three versions of the chip are available, and they are: *
+ * TMS320C25 Internal ROM one time programmed at TI *
+ * TMS320E25 Internal ROM programmable as a normal EPROM *
+ * TMS320P25 Internal ROM programmable once as a normal EPROM only *
+ * These devices can also be used as a MicroController with external ROM *
+ * *
+ \***************************************************************************/
+
+#pragma once
+
+#ifndef __TMS32025_H__
+#define __TMS32025_H__
+
+
+
+
+#define TMS32025_BIO 0x10000 /* BIO input */
+#define TMS32025_HOLD 0x10001 /* HOLD input */
+#define TMS32025_HOLDA 0x10001 /* HOLD Acknowledge output */
+#define TMS32025_XF 0x10002 /* XF output */
+#define TMS32025_DR 0x10003 /* Serial Data Receive input */
+#define TMS32025_DX 0x10003 /* Serial Data Transmit output */
+
+
+
+/****************************************************************************
+ * Interrupt constants
+ */
+
+#define TMS32025_INT0 0 /* External INT0 */
+#define TMS32025_INT1 1 /* External INT1 */
+#define TMS32025_INT2 2 /* External INT2 */
+#define TMS32025_TINT 3 /* Internal Timer interrupt */
+#define TMS32025_RINT 4 /* Serial Port receive interrupt */
+#define TMS32025_XINT 5 /* Serial Port transmit interrupt */
+#define TMS32025_TRAP 6 /* Trap instruction */
+#define TMS32025_INT_NONE -1
+
+/* Non-irq line */
+#define TMS32025_FSX 7 /* Frame synchronisation */
+
+enum
+{
+ TMS32025_PC=1,
+ TMS32025_PFC, TMS32025_STR0, TMS32025_STR1, TMS32025_IFR,
+ TMS32025_RPTC, TMS32025_ACC, TMS32025_PREG, TMS32025_TREG,
+ TMS32025_AR0, TMS32025_AR1, TMS32025_AR2, TMS32025_AR3,
+ TMS32025_AR4, TMS32025_AR5, TMS32025_AR6, TMS32025_AR7,
+ TMS32025_STK0, TMS32025_STK1, TMS32025_STK2, TMS32025_STK3,
+ TMS32025_STK4, TMS32025_STK5, TMS32025_STK6, TMS32025_STK7,
+ TMS32025_DRR, TMS32025_DXR, TMS32025_TIM, TMS32025_PRD,
+ TMS32025_IMR, TMS32025_GREG
+};
+
+
+/****************************************************************************
+ * Public Functions
+ */
+
+DECLARE_LEGACY_CPU_DEVICE(TMS32025, tms32025);
+DECLARE_LEGACY_CPU_DEVICE(TMS32026, tms32026);
+
+CPU_DISASSEMBLE( tms32025 );
+
+#endif /* __TMS32025_H__ */
diff --git a/trunk/src/emu/cpu/tms32031/32031ops.c b/trunk/src/emu/cpu/tms32031/32031ops.c
new file mode 100644
index 00000000000..12f8a815f54
--- /dev/null
+++ b/trunk/src/emu/cpu/tms32031/32031ops.c
@@ -0,0 +1,6906 @@
+/***************************************************************************
+
+ 32031ops.c
+
+ TMS32031/2 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
+//**************************************************************************
+
+#define USE_FP 0
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+#define IREG(rnum) (m_r[rnum].i32[0])
+#define FREGEXP(rnum) (m_r[rnum].exponent())
+#define FREGMAN(rnum) (m_r[rnum].mantissa())
+
+#define FP2LONG(rnum) ((FREGEXP(rnum) << 24) | ((UINT32)FREGMAN(rnum) >> 8))
+#define LONG2FP(rnum,v) do { m_r[rnum].set_mantissa((v) << 8); m_r[rnum].set_exponent((INT32)(v) >> 24); } while (0)
+#define SHORT2FP(rnum,v) do { \
+ if ((UINT16)(v) == 0x8000) { m_r[rnum].set_mantissa(0); m_r[rnum].set_exponent(-128); } \
+ else { m_r[rnum].set_mantissa((v) << 20); m_r[rnum].set_exponent((INT16)(v) >> 12); } \
+ } while (0)
+
+#define DIRECT(op) (((IREG(TMR_DP) & 0xff) << 16) | ((UINT16)op))
+#define INDIRECT_D(op,o) ((this->*s_indirect_d[((o) >> 3) & 31])(op,o))
+#define INDIRECT_1(op,o) ((this->*s_indirect_1[((o) >> 3) & 31])(op,o))
+#define INDIRECT_1_DEF(op,o) ((this->*s_indirect_1_def[((o) >> 3) & 31])(op,o,defptr))
+
+#define SIGN(val) ((val) & 0x80000000)
+
+#define OVERFLOW_SUB(a,b,r) ((INT32)(((a) ^ (b)) & ((a) ^ (r))) < 0)
+#define OVERFLOW_ADD(a,b,r) ((INT32)(~((a) ^ (b)) & ((a) ^ (r))) < 0)
+
+#define CLR_FLAGS(f) do { IREG(TMR_ST) &= ~(f); } while (0)
+#define CLR_NVUF() CLR_FLAGS(NFLAG | VFLAG | UFFLAG)
+#define CLR_NZVUF() CLR_FLAGS(NFLAG | ZFLAG | VFLAG | UFFLAG)
+#define CLR_NZCVUF() CLR_FLAGS(NFLAG | ZFLAG | VFLAG | CFLAG | UFFLAG)
+
+#define OR_C(flag) do { IREG(TMR_ST) |= flag & CFLAG; } while (0)
+#define OR_NZ(val) do { IREG(TMR_ST) |= (((val) >> 28) & NFLAG) | (((val) == 0) << 2); } while (0)
+#define OR_NZF(reg) do { IREG(TMR_ST) |= ((reg.mantissa() >> 28) & NFLAG) | ((reg.exponent() == -128) << 2); } while (0)
+#define OR_NUF(reg) do { int temp = (reg.exponent() == -128) << 4; IREG(TMR_ST) |= ((reg.mantissa() >> 28) & NFLAG) | (temp) | (temp << 2); } while (0)
+#define OR_V_SUB(a,b,r) do { UINT32 temp = ((((a) ^ (b)) & ((a) ^ (r))) >> 30) & VFLAG; IREG(TMR_ST) |= temp | (temp << 4); } while (0)
+#define OR_V_ADD(a,b,r) do { UINT32 temp = ((~((a) ^ (b)) & ((a) ^ (r))) >> 30) & VFLAG; IREG(TMR_ST) |= temp | (temp << 4); } while (0)
+#define OR_C_SUB(a,b,r) do { IREG(TMR_ST) |= ((UINT32)(b) > (UINT32)(a)); } while (0)
+#define OR_C_ADD(a,b,r) do { IREG(TMR_ST) |= ((UINT32)(~(a)) < (UINT32)(b)); } while (0)
+#define OR_NZCV_SUB(a,b,r) do { OR_V_SUB(a,b,r); OR_C_SUB(a,b,r); OR_NZ(r); } while (0)
+#define OR_NZCV_ADD(a,b,r) do { OR_V_ADD(a,b,r); OR_C_ADD(a,b,r); OR_NZ(r); } while (0)
+
+#define OVM() (IREG(TMR_ST) & OVMFLAG)
+
+#define DECLARE_DEF UINT32 defval; UINT32 *defptr = &defval
+#define UPDATE_DEF() *defptr = defval
+
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void tms3203x_device::illegal(UINT32 op)
+{
+ if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ {
+ logerror("Illegal op @ %06X: %08X (tbl=%03X)\n", m_pc - 1, op, op >> 21);
+ debugger_break(machine());
+ }
+}
+
+
+void tms3203x_device::unimplemented(UINT32 op)
+{
+ fatalerror("Unimplemented op @ %06X: %08X (tbl=%03X)", m_pc - 1, op, op >> 21);
+}
+
+
+inline void tms3203x_device::execute_one()
+{
+ UINT32 op = ROPCODE(m_pc);
+ m_icount -= 2; // 2 clocks per cycle
+ m_pc++;
+#if (TMS_3203X_LOG_OPCODE_USAGE)
+ if (machine.primary_screen->frame_number() == 2003)
+ m_hits[op >> 21]++;
+#endif
+ (this->*s_tms32031ops[op >> 21])(op);
+}
+
+
+void tms3203x_device::update_special(int dreg)
+{
+ if (dreg == TMR_BK)
+ {
+ UINT32 temp = IREG(TMR_BK);
+ m_bkmask = temp;
+ while (temp >>= 1)
+ m_bkmask |= temp;
+ }
+ else if (dreg == TMR_IOF)
+ {
+ if (m_xf0_w != NULL && IREG(TMR_IOF) & 0x002)
+ (*m_xf0_w)(*this, (IREG(TMR_IOF) >> 2) & 1);
+ if (m_xf1_w != NULL && IREG(TMR_IOF) & 0x020)
+ (*m_xf1_w)(*this, (IREG(TMR_IOF) >> 6) & 1);
+ }
+ else if (dreg == TMR_ST || dreg == TMR_IF || dreg == TMR_IE)
+ check_irqs();
+}
+
+
+
+//**************************************************************************
+// CONDITION CODES
+//**************************************************************************
+
+const UINT32 C_LO = 1 << 1;
+const UINT32 C_LS = 1 << 2;
+const UINT32 C_HI = 1 << 3;
+const UINT32 C_HS = 1 << 4;
+const UINT32 C_EQ = 1 << 5;
+const UINT32 C_NE = 1 << 6;
+const UINT32 C_LT = 1 << 7;
+const UINT32 C_LE = 1 << 8;
+const UINT32 C_GT = 1 << 9;
+const UINT32 C_GE = 1 << 10;
+const UINT32 C_NV = 1 << 12;
+const UINT32 C_V = 1 << 13;
+const UINT32 C_NUF = 1 << 14;
+const UINT32 C_UF = 1 << 15;
+const UINT32 C_NLV = 1 << 16;
+const UINT32 C_LV = 1 << 17;
+const UINT32 C_NLUF = 1 << 18;
+const UINT32 C_LUF = 1 << 19;
+const UINT32 C_ZUF = 1 << 20;
+
+const UINT32 condition_table[0x80] =
+{
+/* ------- */ 1 | C_HI | C_HS | C_NE | C_GT | C_GE | C_NV | C_NUF | C_NLV | C_NLUF,
+/* ------C */ 1 | C_LO | C_LS | C_NE | C_GT | C_GE | C_NV | C_NUF | C_NLV | C_NLUF,
+/* -----V- */ 1 | C_HI | C_HS | C_NE | C_GT | C_GE | C_V | C_NUF | C_NLV | C_NLUF,
+/* -----VC */ 1 | C_LO | C_LS | C_NE | C_GT | C_GE | C_V | C_NUF | C_NLV | C_NLUF,
+/* ----Z-- */ 1 | C_LS | C_HS | C_EQ | C_LE | C_GE | C_NV | C_NUF | C_NLV | C_NLUF | C_ZUF,
+/* ----Z-C */ 1 | C_LO | C_LS | C_EQ | C_LE | C_GE | C_NV | C_NUF | C_NLV | C_NLUF | C_ZUF,
+/* ----ZV- */ 1 | C_LS | C_HS | C_EQ | C_LE | C_GE | C_V | C_NUF | C_NLV | C_NLUF | C_ZUF,
+/* ----ZVC */ 1 | C_LO | C_LS | C_EQ | C_LE | C_GE | C_V | C_NUF | C_NLV | C_NLUF | C_ZUF,
+/* ---N--- */ 1 | C_HI | C_HS | C_NE | C_LT | C_LE | C_NV | C_NUF | C_NLV | C_NLUF,
+/* ---N--C */ 1 | C_LO | C_LS | C_NE | C_LT | C_LE | C_NV | C_NUF | C_NLV | C_NLUF,
+/* ---N-V- */ 1 | C_HI | C_HS | C_NE | C_LT | C_LE | C_V | C_NUF | C_NLV | C_NLUF,
+/* ---N-VC */ 1 | C_LO | C_LS | C_NE | C_LT | C_LE | C_V | C_NUF | C_NLV | C_NLUF,
+/* ---NZ-- */ 1 | C_LS | C_HS | C_EQ | C_LT | C_LE | C_NV | C_NUF | C_NLV | C_NLUF | C_ZUF,
+/* ---NZ-C */ 1 | C_LO | C_LS | C_EQ | C_LT | C_LE | C_NV | C_NUF | C_NLV | C_NLUF | C_ZUF,
+/* ---NZV- */ 1 | C_LS | C_HS | C_EQ | C_LT | C_LE | C_V | C_NUF | C_NLV | C_NLUF | C_ZUF,
+/* ---NZVC */ 1 | C_LO | C_LS | C_EQ | C_LT | C_LE | C_V | C_NUF | C_NLV | C_NLUF | C_ZUF,
+/* --U---- */ 1 | C_HI | C_HS | C_NE | C_GT | C_GE | C_NV | C_UF | C_NLV | C_NLUF | C_ZUF,
+/* --U---C */ 1 | C_LO | C_LS | C_NE | C_GT | C_GE | C_NV | C_UF | C_NLV | C_NLUF | C_ZUF,
+/* --U--V- */ 1 | C_HI | C_HS | C_NE | C_GT | C_GE | C_V | C_UF | C_NLV | C_NLUF | C_ZUF,
+/* --U--VC */ 1 | C_LO | C_LS | C_NE | C_GT | C_GE | C_V | C_UF | C_NLV | C_NLUF | C_ZUF,
+/* --U-Z-- */ 1 | C_LS | C_HS | C_EQ | C_LE | C_GE | C_NV | C_UF | C_NLV | C_NLUF | C_ZUF,
+/* --U-Z-C */ 1 | C_LO | C_LS | C_EQ | C_LE | C_GE | C_NV | C_UF | C_NLV | C_NLUF | C_ZUF,
+/* --U-ZV- */ 1 | C_LS | C_HS | C_EQ | C_LE | C_GE | C_V | C_UF | C_NLV | C_NLUF | C_ZUF,
+/* --U-ZVC */ 1 | C_LO | C_LS | C_EQ | C_LE | C_GE | C_V | C_UF | C_NLV | C_NLUF | C_ZUF,
+/* --UN--- */ 1 | C_HI | C_HS | C_NE | C_LT | C_LE | C_NV | C_UF | C_NLV | C_NLUF | C_ZUF,
+/* --UN--C */ 1 | C_LO | C_LS | C_NE | C_LT | C_LE | C_NV | C_UF | C_NLV | C_NLUF | C_ZUF,
+/* --UN-V- */ 1 | C_HI | C_HS | C_NE | C_LT | C_LE | C_V | C_UF | C_NLV | C_NLUF | C_ZUF,
+/* --UN-VC */ 1 | C_LO | C_LS | C_NE | C_LT | C_LE | C_V | C_UF | C_NLV | C_NLUF | C_ZUF,
+/* --UNZ-- */ 1 | C_LS | C_HS | C_EQ | C_LT | C_LE | C_NV | C_UF | C_NLV | C_NLUF | C_ZUF,
+/* --UNZ-C */ 1 | C_LO | C_LS | C_EQ | C_LT | C_LE | C_NV | C_UF | C_NLV | C_NLUF | C_ZUF,
+/* --UNZV- */ 1 | C_LS | C_HS | C_EQ | C_LT | C_LE | C_V | C_UF | C_NLV | C_NLUF | C_ZUF,
+/* --UNZVC */ 1 | C_LO | C_LS | C_EQ | C_LT | C_LE | C_V | C_UF | C_NLV | C_NLUF | C_ZUF,
+/* -v----- */ 1 | C_HI | C_HS | C_NE | C_GT | C_GE | C_NV | C_NUF | C_LV | C_NLUF,
+/* -v----C */ 1 | C_LO | C_LS | C_NE | C_GT | C_GE | C_NV | C_NUF | C_LV | C_NLUF,
+/* -v---V- */ 1 | C_HI | C_HS | C_NE | C_GT | C_GE | C_V | C_NUF | C_LV | C_NLUF,
+/* -v---VC */ 1 | C_LO | C_LS | C_NE | C_GT | C_GE | C_V | C_NUF | C_LV | C_NLUF,
+/* -v--Z-- */ 1 | C_LS | C_HS | C_EQ | C_LE | C_GE | C_NV | C_NUF | C_LV | C_NLUF | C_ZUF,
+/* -v--Z-C */ 1 | C_LO | C_LS | C_EQ | C_LE | C_GE | C_NV | C_NUF | C_LV | C_NLUF | C_ZUF,
+/* -v--ZV- */ 1 | C_LS | C_HS | C_EQ | C_LE | C_GE | C_V | C_NUF | C_LV | C_NLUF | C_ZUF,
+/* -v--ZVC */ 1 | C_LO | C_LS | C_EQ | C_LE | C_GE | C_V | C_NUF | C_LV | C_NLUF | C_ZUF,
+/* -v-N--- */ 1 | C_HI | C_HS | C_NE | C_LT | C_LE | C_NV | C_NUF | C_LV | C_NLUF,
+/* -v-N--C */ 1 | C_LO | C_LS | C_NE | C_LT | C_LE | C_NV | C_NUF | C_LV | C_NLUF,
+/* -v-N-V- */ 1 | C_HI | C_HS | C_NE | C_LT | C_LE | C_V | C_NUF | C_LV | C_NLUF,
+/* -v-N-VC */ 1 | C_LO | C_LS | C_NE | C_LT | C_LE | C_V | C_NUF | C_LV | C_NLUF,
+/* -v-NZ-- */ 1 | C_LS | C_HS | C_EQ | C_LT | C_LE | C_NV | C_NUF | C_LV | C_NLUF | C_ZUF,
+/* -v-NZ-C */ 1 | C_LO | C_LS | C_EQ | C_LT | C_LE | C_NV | C_NUF | C_LV | C_NLUF | C_ZUF,
+/* -v-NZV- */ 1 | C_LS | C_HS | C_EQ | C_LT | C_LE | C_V | C_NUF | C_LV | C_NLUF | C_ZUF,
+/* -v-NZVC */ 1 | C_LO | C_LS | C_EQ | C_LT | C_LE | C_V | C_NUF | C_LV | C_NLUF | C_ZUF,
+/* -vU---- */ 1 | C_HI | C_HS | C_NE | C_GT | C_GE | C_NV | C_UF | C_LV | C_NLUF | C_ZUF,
+/* -vU---C */ 1 | C_LO | C_LS | C_NE | C_GT | C_GE | C_NV | C_UF | C_LV | C_NLUF | C_ZUF,
+/* -vU--V- */ 1 | C_HI | C_HS | C_NE | C_GT | C_GE | C_V | C_UF | C_LV | C_NLUF | C_ZUF,
+/* -vU--VC */ 1 | C_LO | C_LS | C_NE | C_GT | C_GE | C_V | C_UF | C_LV | C_NLUF | C_ZUF,
+/* -vU-Z-- */ 1 | C_LS | C_HS | C_EQ | C_LE | C_GE | C_NV | C_UF | C_LV | C_NLUF | C_ZUF,
+/* -vU-Z-C */ 1 | C_LO | C_LS | C_EQ | C_LE | C_GE | C_NV | C_UF | C_LV | C_NLUF | C_ZUF,
+/* -vU-ZV- */ 1 | C_LS | C_HS | C_EQ | C_LE | C_GE | C_V | C_UF | C_LV | C_NLUF | C_ZUF,
+/* -vU-ZVC */ 1 | C_LO | C_LS | C_EQ | C_LE | C_GE | C_V | C_UF | C_LV | C_NLUF | C_ZUF,
+/* -vUN--- */ 1 | C_HI | C_HS | C_NE | C_LT | C_LE | C_NV | C_UF | C_LV | C_NLUF | C_ZUF,
+/* -vUN--C */ 1 | C_LO | C_LS | C_NE | C_LT | C_LE | C_NV | C_UF | C_LV | C_NLUF | C_ZUF,
+/* -vUN-V- */ 1 | C_HI | C_HS | C_NE | C_LT | C_LE | C_V | C_UF | C_LV | C_NLUF | C_ZUF,
+/* -vUN-VC */ 1 | C_LO | C_LS | C_NE | C_LT | C_LE | C_V | C_UF | C_LV | C_NLUF | C_ZUF,
+/* -vUNZ-- */ 1 | C_LS | C_HS | C_EQ | C_LT | C_LE | C_NV | C_UF | C_LV | C_NLUF | C_ZUF,
+/* -vUNZ-C */ 1 | C_LO | C_LS | C_EQ | C_LT | C_LE | C_NV | C_UF | C_LV | C_NLUF | C_ZUF,
+/* -vUNZV- */ 1 | C_LS | C_HS | C_EQ | C_LT | C_LE | C_V | C_UF | C_LV | C_NLUF | C_ZUF,
+/* -vUNZVC */ 1 | C_LO | C_LS | C_EQ | C_LT | C_LE | C_V | C_UF | C_LV | C_NLUF | C_ZUF,
+/* u------ */ 1 | C_HI | C_HS | C_NE | C_GT | C_GE | C_NV | C_NUF | C_NLV | C_LUF,
+/* u-----C */ 1 | C_LO | C_LS | C_NE | C_GT | C_GE | C_NV | C_NUF | C_NLV | C_LUF,
+/* u----V- */ 1 | C_HI | C_HS | C_NE | C_GT | C_GE | C_V | C_NUF | C_NLV | C_LUF,
+/* u----VC */ 1 | C_LO | C_LS | C_NE | C_GT | C_GE | C_V | C_NUF | C_NLV | C_LUF,
+/* u---Z-- */ 1 | C_LS | C_HS | C_EQ | C_LE | C_GE | C_NV | C_NUF | C_NLV | C_LUF | C_ZUF,
+/* u---Z-C */ 1 | C_LO | C_LS | C_EQ | C_LE | C_GE | C_NV | C_NUF | C_NLV | C_LUF | C_ZUF,
+/* u---ZV- */ 1 | C_LS | C_HS | C_EQ | C_LE | C_GE | C_V | C_NUF | C_NLV | C_LUF | C_ZUF,
+/* u---ZVC */ 1 | C_LO | C_LS | C_EQ | C_LE | C_GE | C_V | C_NUF | C_NLV | C_LUF | C_ZUF,
+/* u--N--- */ 1 | C_HI | C_HS | C_NE | C_LT | C_LE | C_NV | C_NUF | C_NLV | C_LUF,
+/* u--N--C */ 1 | C_LO | C_LS | C_NE | C_LT | C_LE | C_NV | C_NUF | C_NLV | C_LUF,
+/* u--N-V- */ 1 | C_HI | C_HS | C_NE | C_LT | C_LE | C_V | C_NUF | C_NLV | C_LUF,
+/* u--N-VC */ 1 | C_LO | C_LS | C_NE | C_LT | C_LE | C_V | C_NUF | C_NLV | C_LUF,
+/* u--NZ-- */ 1 | C_LS | C_HS | C_EQ | C_LT | C_LE | C_NV | C_NUF | C_NLV | C_LUF | C_ZUF,
+/* u--NZ-C */ 1 | C_LO | C_LS | C_EQ | C_LT | C_LE | C_NV | C_NUF | C_NLV | C_LUF | C_ZUF,
+/* u--NZV- */ 1 | C_LS | C_HS | C_EQ | C_LT | C_LE | C_V | C_NUF | C_NLV | C_LUF | C_ZUF,
+/* u--NZVC */ 1 | C_LO | C_LS | C_EQ | C_LT | C_LE | C_V | C_NUF | C_NLV | C_LUF | C_ZUF,
+/* u-U---- */ 1 | C_HI | C_HS | C_NE | C_GT | C_GE | C_NV | C_UF | C_NLV | C_LUF | C_ZUF,
+/* u-U---C */ 1 | C_LO | C_LS | C_NE | C_GT | C_GE | C_NV | C_UF | C_NLV | C_LUF | C_ZUF,
+/* u-U--V- */ 1 | C_HI | C_HS | C_NE | C_GT | C_GE | C_V | C_UF | C_NLV | C_LUF | C_ZUF,
+/* u-U--VC */ 1 | C_LO | C_LS | C_NE | C_GT | C_GE | C_V | C_UF | C_NLV | C_LUF | C_ZUF,
+/* u-U-Z-- */ 1 | C_LS | C_HS | C_EQ | C_LE | C_GE | C_NV | C_UF | C_NLV | C_LUF | C_ZUF,
+/* u-U-Z-C */ 1 | C_LO | C_LS | C_EQ | C_LE | C_GE | C_NV | C_UF | C_NLV | C_LUF | C_ZUF,
+/* u-U-ZV- */ 1 | C_LS | C_HS | C_EQ | C_LE | C_GE | C_V | C_UF | C_NLV | C_LUF | C_ZUF,
+/* u-U-ZVC */ 1 | C_LO | C_LS | C_EQ | C_LE | C_GE | C_V | C_UF | C_NLV | C_LUF | C_ZUF,
+/* u-UN--- */ 1 | C_HI | C_HS | C_NE | C_LT | C_LE | C_NV | C_UF | C_NLV | C_LUF | C_ZUF,
+/* u-UN--C */ 1 | C_LO | C_LS | C_NE | C_LT | C_LE | C_NV | C_UF | C_NLV | C_LUF | C_ZUF,
+/* u-UN-V- */ 1 | C_HI | C_HS | C_NE | C_LT | C_LE | C_V | C_UF | C_NLV | C_LUF | C_ZUF,
+/* u-UN-VC */ 1 | C_LO | C_LS | C_NE | C_LT | C_LE | C_V | C_UF | C_NLV | C_LUF | C_ZUF,
+/* u-UNZ-- */ 1 | C_LS | C_HS | C_EQ | C_LT | C_LE | C_NV | C_UF | C_NLV | C_LUF | C_ZUF,
+/* u-UNZ-C */ 1 | C_LO | C_LS | C_EQ | C_LT | C_LE | C_NV | C_UF | C_NLV | C_LUF | C_ZUF,
+/* u-UNZV- */ 1 | C_LS | C_HS | C_EQ | C_LT | C_LE | C_V | C_UF | C_NLV | C_LUF | C_ZUF,
+/* u-UNZVC */ 1 | C_LO | C_LS | C_EQ | C_LT | C_LE | C_V | C_UF | C_NLV | C_LUF | C_ZUF,
+/* uv----- */ 1 | C_HI | C_HS | C_NE | C_GT | C_GE | C_NV | C_NUF | C_LV | C_LUF,
+/* uv----C */ 1 | C_LO | C_LS | C_NE | C_GT | C_GE | C_NV | C_NUF | C_LV | C_LUF,
+/* uv---V- */ 1 | C_HI | C_HS | C_NE | C_GT | C_GE | C_V | C_NUF | C_LV | C_LUF,
+/* uv---VC */ 1 | C_LO | C_LS | C_NE | C_GT | C_GE | C_V | C_NUF | C_LV | C_LUF,
+/* uv--Z-- */ 1 | C_LS | C_HS | C_EQ | C_LE | C_GE | C_NV | C_NUF | C_LV | C_LUF | C_ZUF,
+/* uv--Z-C */ 1 | C_LO | C_LS | C_EQ | C_LE | C_GE | C_NV | C_NUF | C_LV | C_LUF | C_ZUF,
+/* uv--ZV- */ 1 | C_LS | C_HS | C_EQ | C_LE | C_GE | C_V | C_NUF | C_LV | C_LUF | C_ZUF,
+/* uv--ZVC */ 1 | C_LO | C_LS | C_EQ | C_LE | C_GE | C_V | C_NUF | C_LV | C_LUF | C_ZUF,
+/* uv-N--- */ 1 | C_HI | C_HS | C_NE | C_LT | C_LE | C_NV | C_NUF | C_LV | C_LUF,
+/* uv-N--C */ 1 | C_LO | C_LS | C_NE | C_LT | C_LE | C_NV | C_NUF | C_LV | C_LUF,
+/* uv-N-V- */ 1 | C_HI | C_HS | C_NE | C_LT | C_LE | C_V | C_NUF | C_LV | C_LUF,
+/* uv-N-VC */ 1 | C_LO | C_LS | C_NE | C_LT | C_LE | C_V | C_NUF | C_LV | C_LUF,
+/* uv-NZ-- */ 1 | C_LS | C_HS | C_EQ | C_LT | C_LE | C_NV | C_NUF | C_LV | C_LUF | C_ZUF,
+/* uv-NZ-C */ 1 | C_LO | C_LS | C_EQ | C_LT | C_LE | C_NV | C_NUF | C_LV | C_LUF | C_ZUF,
+/* uv-NZV- */ 1 | C_LS | C_HS | C_EQ | C_LT | C_LE | C_V | C_NUF | C_LV | C_LUF | C_ZUF,
+/* uv-NZVC */ 1 | C_LO | C_LS | C_EQ | C_LT | C_LE | C_V | C_NUF | C_LV | C_LUF | C_ZUF,
+/* uvU---- */ 1 | C_HI | C_HS | C_NE | C_GT | C_GE | C_NV | C_UF | C_LV | C_LUF | C_ZUF,
+/* uvU---C */ 1 | C_LO | C_LS | C_NE | C_GT | C_GE | C_NV | C_UF | C_LV | C_LUF | C_ZUF,
+/* uvU--V- */ 1 | C_HI | C_HS | C_NE | C_GT | C_GE | C_V | C_UF | C_LV | C_LUF | C_ZUF,
+/* uvU--VC */ 1 | C_LO | C_LS | C_NE | C_GT | C_GE | C_V | C_UF | C_LV | C_LUF | C_ZUF,
+/* uvU-Z-- */ 1 | C_LS | C_HS | C_EQ | C_LE | C_GE | C_NV | C_UF | C_LV | C_LUF | C_ZUF,
+/* uvU-Z-C */ 1 | C_LO | C_LS | C_EQ | C_LE | C_GE | C_NV | C_UF | C_LV | C_LUF | C_ZUF,
+/* uvU-ZV- */ 1 | C_LS | C_HS | C_EQ | C_LE | C_GE | C_V | C_UF | C_LV | C_LUF | C_ZUF,
+/* uvU-ZVC */ 1 | C_LO | C_LS | C_EQ | C_LE | C_GE | C_V | C_UF | C_LV | C_LUF | C_ZUF,
+/* uvUN--- */ 1 | C_HI | C_HS | C_NE | C_LT | C_LE | C_NV | C_UF | C_LV | C_LUF | C_ZUF,
+/* uvUN--C */ 1 | C_LO | C_LS | C_NE | C_LT | C_LE | C_NV | C_UF | C_LV | C_LUF | C_ZUF,
+/* uvUN-V- */ 1 | C_HI | C_HS | C_NE | C_LT | C_LE | C_V | C_UF | C_LV | C_LUF | C_ZUF,
+/* uvUN-VC */ 1 | C_LO | C_LS | C_NE | C_LT | C_LE | C_V | C_UF | C_LV | C_LUF | C_ZUF,
+/* uvUNZ-- */ 1 | C_LS | C_HS | C_EQ | C_LT | C_LE | C_NV | C_UF | C_LV | C_LUF | C_ZUF,
+/* uvUNZ-C */ 1 | C_LO | C_LS | C_EQ | C_LT | C_LE | C_NV | C_UF | C_LV | C_LUF | C_ZUF,
+/* uvUNZV- */ 1 | C_LS | C_HS | C_EQ | C_LT | C_LE | C_V | C_UF | C_LV | C_LUF | C_ZUF,
+/* uvUNZVC */ 1 | C_LO | C_LS | C_EQ | C_LT | C_LE | C_V | C_UF | C_LV | C_LUF | C_ZUF,
+};
+
+#define CONDITION_LO() (IREG(TMR_ST) & CFLAG)
+#define CONDITION_LS() (IREG(TMR_ST) & (CFLAG | ZFLAG))
+#define CONDITION_HI() (!(IREG(TMR_ST) & (CFLAG | ZFLAG)))
+#define CONDITION_HS() (!(IREG(TMR_ST) & CFLAG))
+#define CONDITION_EQ() (IREG(TMR_ST) & ZFLAG)
+#define CONDITION_NE() (!(IREG(TMR_ST) & ZFLAG))
+#define CONDITION_LT() (IREG(TMR_ST) & NFLAG)
+#define CONDITION_LE() (IREG(TMR_ST) & (NFLAG | ZFLAG))
+#define CONDITION_GT() (!(IREG(TMR_ST) & (NFLAG | ZFLAG)))
+#define CONDITION_GE() (!(IREG(TMR_ST) & NFLAG))
+#define CONDITION_NV() (!(IREG(TMR_ST) & VFLAG))
+#define CONDITION_V() (IREG(TMR_ST) & VFLAG)
+#define CONDITION_NUF() (!(IREG(TMR_ST) & UFFLAG))
+#define CONDITION_UF() (IREG(TMR_ST) & UFFLAG)
+#define CONDITION_NLV() (!(IREG(TMR_ST) & LVFLAG))
+#define CONDITION_LV() (IREG(TMR_ST) & LVFLAG)
+#define CONDITION_NLUF() (!(IREG(TMR_ST) & LUFFLAG))
+#define CONDITION_LUF() (IREG(TMR_ST) & LUFFLAG)
+#define CONDITION_ZUF() (IREG(TMR_ST) & (UFFLAG | ZFLAG))
+
+inline bool tms3203x_device::condition(int which)
+{
+ return (condition_table[IREG(TMR_ST) & (LUFFLAG | LVFLAG | UFFLAG | NFLAG | ZFLAG | VFLAG | CFLAG)] >> (which & 31)) & 1;
+}
+
+
+
+//**************************************************************************
+// FLOATING POINT HELPERS
+//**************************************************************************
+
+#if USE_FP
+void tms3203x_device::double_to_dsp_with_flags(double val, tmsreg &result)
+{
+ int_double id;
+ id.d = val;
+
+ CLR_NZVUF();
+
+ int mantissa = ((id.i[BYTE_XOR_BE(0)] & 0x000fffff) << 11) | ((id.i[BYTE_XOR_BE(1)] & 0xffe00000) >> 21);
+ int exponent = ((id.i[BYTE_XOR_BE(0)] & 0x7ff00000) >> 20) - 1023;
+ if (exponent <= -128)
+ {
+ result.set_mantissa(0);
+ result.set_exponent(-128);
+ IREG(TMR_ST) |= UFFLAG | LUFFLAG | ZFLAG;
+ }
+ else if (exponent > 127)
+ {
+ if ((INT32)id.i[BYTE_XOR_BE(0)] >= 0)
+ result.set_mantissa(0x7fffffff);
+ else
+ {
+ result.set_mantissa(0x80000001);
+ IREG(TMR_ST) |= NFLAG;
+ }
+ result.set_exponent(127);
+ IREG(TMR_ST) |= VFLAG | LVFLAG;
+ }
+ else if (val == 0)
+ {
+ result.set_mantissa(0);
+ result.set_exponent(-128);
+ IREG(TMR_ST) |= ZFLAG;
+ }
+ else if ((INT32)id.i[BYTE_XOR_BE(0)] >= 0)
+ {
+ result.set_mantissa(mantissa);
+ result.set_exponent(exponent);
+ }
+ else if (mantissa != 0)
+ {
+ result.set_mantissa(0x80000000 | -mantissa);
+ result.set_exponent(exponent);
+ IREG(TMR_ST) |= NFLAG;
+ }
+ else
+ {
+ result.set_mantissa(0x80000000);
+ result.set_exponent(exponent - 1);
+ IREG(TMR_ST) |= NFLAG;
+ }
+}
+#endif
+
+// integer to floating point conversion
+#if USE_FP
+void tms3203x_device::int2float(tmsreg &srcdst)
+{
+ double val = srcdst.mantissa();
+ double_to_dsp_with_flags(val, srcdst);
+}
+#else
+void tms3203x_device::int2float(tmsreg &srcdst)
+{
+ UINT32 man = srcdst.mantissa();
+ int exp, cnt;
+
+ // never overflows or underflows
+ CLR_NZVUF();
+
+ // 0 always has exponent of -128
+ if (man == 0)
+ {
+ man = 0x80000000;
+ exp = -128;
+ }
+
+ // check for -1 here because count_leading_ones will infinite loop
+ else if (man == (UINT32)-1)
+ {
+ man = 0;
+ exp = -1;
+ }
+
+ // positive values; count leading zeros and shift
+ else if ((INT32)man > 0)
+ {
+ cnt = count_leading_zeros(man);
+ man <<= cnt;
+ exp = 31 - cnt;
+ }
+
+ // negative values; count leading ones and shift
+ else
+ {
+ cnt = count_leading_ones(man);
+ man <<= cnt;
+ exp = 31 - cnt;
+ }
+
+ // set the final results and compute NZ
+ srcdst.set_mantissa(man ^ 0x80000000);
+ srcdst.set_exponent(exp);
+ OR_NZF(srcdst);
+}
+#endif
+
+
+// floating point to integer conversion
+#if USE_FP
+void tms3203x_device::float2int(tmsreg &srcdst, int setflags)
+{
+ INT32 val;
+
+ if (setflags) CLR_NZVUF();
+ if (srcdst.exponent() > 30)
+ {
+ if ((INT32)srcdst.mantissa() >= 0)
+ val = 0x7fffffff;
+ else
+ val = 0x80000000;
+ if (setflags) IREG(TMR_ST) |= VFLAG | LVFLAG;
+ }
+ else
+ val = floor(srcdst.as_double());
+ srcdst.set_mantissa(val);
+ if (setflags) OR_NZ(val);
+}
+#else
+void tms3203x_device::float2int(tmsreg &srcdst, bool setflags)
+{
+ INT32 man = srcdst.mantissa();
+ int shift = 31 - srcdst.exponent();
+
+ // never underflows
+ if (setflags) CLR_NZVUF();
+
+ // if we've got too much to handle, overflow
+ if (shift <= 0)
+ {
+ srcdst.set_mantissa((man >= 0) ? 0x7fffffff : 0x80000000);
+ if (setflags) IREG(TMR_ST) |= VFLAG | LVFLAG;
+ }
+
+ // if we're too small, go to 0 or -1
+ else if (shift > 31)
+ srcdst.set_mantissa(man >> 31);
+
+ // we're in the middle; shift it
+ else
+ srcdst.set_mantissa((man >> shift) ^ (1 << (31 - shift)));
+
+ // set the NZ flags
+ if (setflags) OR_NZ(srcdst.mantissa());
+}
+#endif
+
+
+// compute the negative of a floating point value
+#if USE_FP
+void tms3203x_device::negf(tmsreg &dst, tmsreg tmsreg &src)
+{
+ double val = -src.as_double();
+ double_to_dsp_with_flags(val, dst);
+}
+#else
+void tms3203x_device::negf(tmsreg &dst, tmsreg &src)
+{
+ INT32 man = src.mantissa();
+
+ CLR_NZVUF();
+
+ if (src.exponent() == -128)
+ {
+ dst.set_mantissa(0);
+ dst.set_exponent(-128);
+ }
+ else if ((man & 0x7fffffff) != 0)
+ {
+ dst.set_mantissa(-man);
+ dst.set_exponent(src.exponent());
+ }
+ else
+ {
+ dst.set_mantissa(man ^ 0x80000000);
+ if (man == 0)
+ dst.set_exponent(src.exponent() - 1);
+ else
+ dst.set_exponent(src.exponent() + 1);
+ }
+ OR_NZF(dst);
+}
+#endif
+
+
+
+// add two floating point values
+#if USE_FP
+void tms3203x_device::addf(tmsreg &dst, tmsreg &src1, tmsreg &src2)
+{
+ double val = src1.as_double() + src2.as_double();
+ double_to_dsp_with_flags(val, dst);
+}
+#else
+void tms3203x_device::addf(tmsreg &dst, tmsreg &src1, tmsreg &src2)
+{
+ INT64 man;
+ INT64 m1, m2;
+ int exp, cnt;
+
+ // reset over/underflow conditions
+ CLR_NZVUF();
+
+ // first check for 0 operands
+ if (src1.exponent() == -128)
+ {
+ dst = src2;
+ OR_NZF(dst);
+ return;
+ }
+ if (src2.exponent() == -128)
+ {
+ dst = src1;
+ OR_NZF(dst);
+ return;
+ }
+
+ // extract mantissas from 1.0.31 values to 1.1.31 values
+ m1 = (INT64)src1.mantissa() ^ 0x80000000;
+ m2 = (INT64)src2.mantissa() ^ 0x80000000;
+
+ // normalize based on the exponent
+ if (src1.exponent() > src2.exponent())
+ {
+ exp = src1.exponent();
+ cnt = exp - src2.exponent();
+ if (cnt >= 32)
+ {
+ dst = src1;
+ OR_NZF(dst);
+ return;
+ }
+ m2 >>= cnt;
+ }
+ else
+ {
+ exp = src2.exponent();
+ cnt = exp - src1.exponent();
+ if (cnt >= 32)
+ {
+ dst = src2;
+ OR_NZF(dst);
+ return;
+ }
+ m1 >>= cnt;
+ }
+
+ // add
+ man = m1 + m2;
+
+ // if the mantissa is zero, set the exponent appropriately
+ if (man == 0 || exp == -128)
+ {
+ exp = -128;
+ man = 0x80000000;
+ }
+
+ // if the mantissa is >= 2.0 or < -2.0, normalize
+ else if (man >= ((INT64)2 << 31) || man < ((INT64)-2 << 31))
+ {
+ man >>= 1;
+ exp++;
+ }
+
+ // if the mantissa is < 1.0 and > -1.0, normalize
+ else if (man < ((INT64)1 << 31) && man >= ((INT64)-1 << 31))
+ {
+ if (man > 0)
+ {
+ cnt = count_leading_zeros((UINT32)man);
+ man <<= cnt;
+ exp -= cnt;
+ }
+ else
+ {
+ cnt = count_leading_ones((UINT32)man);
+ man <<= cnt;
+ exp -= cnt;
+ }
+ }
+
+ // check for underflow
+ if (exp <= -128)
+ {
+ man = 0x80000000;
+ exp = -128;
+ IREG(TMR_ST) |= UFFLAG | LUFFLAG;
+ }
+
+ // check for overflow
+ else if (exp > 127)
+ {
+ man = (man < 0) ? 0x00000000 : 0xffffffff;
+ exp = 127;
+ IREG(TMR_ST) |= VFLAG | LVFLAG;
+ }
+
+ // store the result back, removing the implicit one and putting
+ // back the sign bit
+ dst.set_mantissa((UINT32)man ^ 0x80000000);
+ dst.set_exponent(exp);
+ OR_NZF(dst);
+}
+#endif
+
+
+// subtract two floating point values
+#if USE_FP
+void tms3203x_device::subf(tmsreg &dst, tmsreg &src1, tmsreg &src2)
+{
+ double val = src1.as_double() - src2.as_double();
+ double_to_dsp_with_flags(val, dst);
+}
+#else
+void tms3203x_device::subf(tmsreg &dst, tmsreg &src1, tmsreg &src2)
+{
+ INT64 man;
+ INT64 m1, m2;
+ int exp, cnt;
+
+ // reset over/underflow conditions
+ CLR_NZVUF();
+
+ // first check for 0 operands
+ if (src2.exponent() == -128)
+ {
+ dst = src1;
+ OR_NZF(dst);
+ return;
+ }
+
+ // extract mantissas from 1.0.31 values to 1.1.31 values
+ m1 = (INT64)src1.mantissa() ^ 0x80000000;
+ m2 = (INT64)src2.mantissa() ^ 0x80000000;
+
+ // normalize based on the exponent
+ if (src1.exponent() > src2.exponent())
+ {
+ exp = src1.exponent();
+ cnt = exp - src2.exponent();
+ if (cnt >= 32)
+ {
+ dst = src1;
+ OR_NZF(dst);
+ return;
+ }
+ m2 >>= cnt;
+ }
+ else
+ {
+ exp = src2.exponent();
+ cnt = exp - src1.exponent();
+ if (cnt >= 32)
+ {
+ negf(dst, src2);
+ return;
+ }
+ m1 >>= cnt;
+ }
+
+ // subtract
+ man = m1 - m2;
+
+ // if the mantissa is zero, set the exponent appropriately
+ if (man == 0 || exp == -128)
+ {
+ exp = -128;
+ man = 0x80000000;
+ }
+
+ // if the mantissa is >= 2.0 or < -2.0, normalize
+ else if (man >= ((INT64)2 << 31) || man < ((INT64)-2 << 31))
+ {
+ man >>= 1;
+ exp++;
+ }
+
+ // if the mantissa is < 1.0 and > -1.0, normalize
+ else if (man < ((INT64)1 << 31) && man >= ((INT64)-1 << 31))
+ {
+ if (man > 0)
+ {
+ cnt = count_leading_zeros((UINT32)man);
+ man <<= cnt;
+ exp -= cnt;
+ }
+ else
+ {
+ cnt = count_leading_ones((UINT32)man);
+ man <<= cnt;
+ exp -= cnt;
+ }
+ }
+
+ // check for underflow
+ if (exp <= -128)
+ {
+ man = 0x80000000;
+ exp = -128;
+ IREG(TMR_ST) |= UFFLAG | LUFFLAG;
+ }
+
+ // check for overflow
+ else if (exp > 127)
+ {
+ man = (man < 0) ? 0x00000000 : 0xffffffff;
+ exp = 127;
+ IREG(TMR_ST) |= VFLAG | LVFLAG;
+ }
+
+ // store the result back, removing the implicit one and putting
+ // back the sign bit
+ dst.set_mantissa((UINT32)man ^ 0x80000000);
+ dst.set_exponent(exp);
+ OR_NZF(dst);
+}
+#endif
+
+
+// multiply two floating point values
+#if USE_FP
+void tms3203x_device::mpyf(tmsreg &dst, tmsreg &src1, tmsreg &src2)
+{
+ double val = (double)src1.as_float() * (double)src2.as_float();
+ double_to_dsp_with_flags(val, dst);
+}
+#else
+void tms3203x_device::mpyf(tmsreg &dst, tmsreg &src1, tmsreg &src2)
+{
+ // reset over/underflow conditions
+ CLR_NZVUF();
+
+ // first check for 0 multipliers and return 0 in any case
+ if (src1.exponent() == -128 || src2.exponent() == -128)
+ {
+ dst.set_mantissa(0);
+ dst.set_exponent(-128);
+ OR_NZF(dst);
+ return;
+ }
+
+ // convert the mantissas from 1.0.31 numbers to 1.1.23 numbers
+ INT32 m1 = (src1.mantissa() >> 8) ^ 0x800000;
+ INT32 m2 = (src2.mantissa() >> 8) ^ 0x800000;
+
+ // multiply the mantissas and add the exponents
+ INT64 man = (INT64)m1 * (INT64)m2;
+ int exp = src1.exponent() + src2.exponent();
+
+ // chop off the low bits, going from 1.2.46 down to 1.2.31
+ man >>= 46 - 31;
+
+ // if the mantissa is zero, set the exponent appropriately
+ if (man == 0)
+ {
+ exp = -128;
+ man = 0x80000000;
+ }
+
+ // if the mantissa is >= 2.0 or <= -2.0, normalize
+ else if (man >= ((INT64)2 << 31))
+ {
+ man >>= 1;
+ exp++;
+ if (man >= ((INT64)2 << 31))
+ {
+ man >>= 1;
+ exp++;
+ }
+ }
+
+ // if the mantissa is >= 2.0 or <= -2.0, normalize
+ else if (man < ((INT64)-2 << 31))
+ {
+ man >>= 1;
+ exp++;
+ }
+
+ // check for underflow
+ if (exp <= -128)
+ {
+ man = 0x80000000;
+ exp = -128;
+ IREG(TMR_ST) |= UFFLAG | LUFFLAG;
+ }
+
+ // check for overflow
+ else if (exp > 127)
+ {
+ man = (man < 0) ? 0x00000000 : 0xffffffff;
+ exp = 127;
+ IREG(TMR_ST) |= VFLAG | LVFLAG;
+ }
+
+ // store the result back, removing the implicit one and putting
+ // back the sign bit
+ dst.set_mantissa((UINT32)man ^ 0x80000000);
+ dst.set_exponent(exp);
+ OR_NZF(dst);
+}
+#endif
+
+
+// normalize a floating point value
+#if USE_FP
+void tms3203x_device::norm(tmsreg &dst, tmsreg &src)
+{
+ fatalerror("norm not implemented");
+}
+#else
+void tms3203x_device::norm(tmsreg &dst, tmsreg &src)
+{
+ INT32 man = src.mantissa();
+ int exp = src.exponent();
+
+ CLR_NZVUF();
+
+ if (exp == -128 || man == 0)
+ {
+ dst.set_mantissa(0);
+ dst.set_exponent(-128);
+ if (man != 0)
+ IREG(TMR_ST) |= UFFLAG | LUFFLAG;
+ }
+ else
+ {
+ int cnt;
+ if (man > 0)
+ {
+ cnt = count_leading_zeros((UINT32)man);
+ man <<= cnt;
+ exp -= cnt;
+ }
+ else
+ {
+ cnt = count_leading_ones((UINT32)man);
+ man <<= cnt;
+ exp -= cnt;
+ }
+
+ // check for underflow
+ if (exp <= -128)
+ {
+ man = 0x00000000;
+ exp = -128;
+ IREG(TMR_ST) |= UFFLAG | LUFFLAG;
+ }
+ }
+
+ dst.set_mantissa(man);
+ dst.set_exponent(exp);
+ OR_NZF(dst);
+}
+#endif
+
+
+
+
+//**************************************************************************
+// INDIRECT MEMORY REFS
+//**************************************************************************
+
+// immediate displacement variants
+
+UINT32 tms3203x_device::mod00_d(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ return IREG(reg) + (UINT8)op;
+}
+
+UINT32 tms3203x_device::mod01_d(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ return IREG(reg) - (UINT8)op;
+}
+
+UINT32 tms3203x_device::mod02_d(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ IREG(reg) += (UINT8)op;
+ return IREG(reg);
+}
+
+UINT32 tms3203x_device::mod03_d(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ IREG(reg) -= (UINT8)op;
+ return IREG(reg);
+}
+
+UINT32 tms3203x_device::mod04_d(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 result = IREG(reg);
+ IREG(reg) += (UINT8)op;
+ return result;
+}
+
+UINT32 tms3203x_device::mod05_d(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 result = IREG(reg);
+ IREG(reg) -= (UINT8)op;
+ return result;
+}
+
+UINT32 tms3203x_device::mod06_d(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 result = IREG(reg);
+ INT32 temp = (result & m_bkmask) + (UINT8)op;
+ if (temp >= IREG(TMR_BK))
+ temp -= IREG(TMR_BK);
+ IREG(reg) = (IREG(reg) & ~m_bkmask) | (temp & m_bkmask);
+ return result;
+}
+
+UINT32 tms3203x_device::mod07_d(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 result = IREG(reg);
+ INT32 temp = (result & m_bkmask) - (UINT8)op;
+ if (temp < 0)
+ temp += IREG(TMR_BK);
+ IREG(reg) = (IREG(reg) & ~m_bkmask) | (temp & m_bkmask);
+ return result;
+}
+
+
+// immediate displacement variants (implied 1)
+
+UINT32 tms3203x_device::mod00_1(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ return IREG(reg) + 1;
+}
+
+UINT32 tms3203x_device::mod01_1(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ return IREG(reg) - 1;
+}
+
+UINT32 tms3203x_device::mod02_1(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ return ++IREG(reg);
+}
+
+UINT32 tms3203x_device::mod03_1(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ return --IREG(reg);
+}
+
+UINT32 tms3203x_device::mod04_1(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ return IREG(reg)++;
+}
+
+UINT32 tms3203x_device::mod05_1(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ return IREG(reg)--;
+}
+
+UINT32 tms3203x_device::mod06_1(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 result = IREG(reg);
+ INT32 temp = (result & m_bkmask) + 1;
+ if (temp >= IREG(TMR_BK))
+ temp -= IREG(TMR_BK);
+ IREG(reg) = (IREG(reg) & ~m_bkmask) | (temp & m_bkmask);
+ return result;
+}
+
+UINT32 tms3203x_device::mod07_1(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 result = IREG(reg);
+ INT32 temp = (result & m_bkmask) - 1;
+ if (temp < 0)
+ temp += IREG(TMR_BK);
+ IREG(reg) = (IREG(reg) & ~m_bkmask) | (temp & m_bkmask);
+ return result;
+}
+
+
+// IR0 displacement variants
+
+UINT32 tms3203x_device::mod08(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ return IREG(reg) + IREG(TMR_IR0);
+}
+
+UINT32 tms3203x_device::mod09(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ return IREG(reg) - IREG(TMR_IR0);
+}
+
+UINT32 tms3203x_device::mod0a(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ IREG(reg) += IREG(TMR_IR0);
+ return IREG(reg);
+}
+
+UINT32 tms3203x_device::mod0b(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ IREG(reg) -= IREG(TMR_IR0);
+ return IREG(reg);
+}
+
+UINT32 tms3203x_device::mod0c(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 result = IREG(reg);
+ IREG(reg) += IREG(TMR_IR0);
+ return result;
+}
+
+UINT32 tms3203x_device::mod0d(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 result = IREG(reg);
+ IREG(reg) -= IREG(TMR_IR0);
+ return result;
+}
+
+UINT32 tms3203x_device::mod0e(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 result = IREG(reg);
+ INT32 temp = (result & m_bkmask) + IREG(TMR_IR0);
+ if (temp >= IREG(TMR_BK))
+ temp -= IREG(TMR_BK);
+ IREG(reg) = (IREG(reg) & ~m_bkmask) | (temp & m_bkmask);
+ return result;
+}
+
+UINT32 tms3203x_device::mod0f(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 result = IREG(reg);
+ INT32 temp = (result & m_bkmask) - IREG(TMR_IR0);
+ if (temp < 0)
+ temp += IREG(TMR_BK);
+ IREG(reg) = (IREG(reg) & ~m_bkmask) | (temp & m_bkmask);
+ return result;
+}
+
+
+// IR1 displacement variants
+
+UINT32 tms3203x_device::mod10(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ return IREG(reg) + IREG(TMR_IR1);
+}
+
+UINT32 tms3203x_device::mod11(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ return IREG(reg) - IREG(TMR_IR1);
+}
+
+UINT32 tms3203x_device::mod12(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ IREG(reg) += IREG(TMR_IR1);
+ return IREG(reg);
+}
+
+UINT32 tms3203x_device::mod13(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ IREG(reg) -= IREG(TMR_IR1);
+ return IREG(reg);
+}
+
+UINT32 tms3203x_device::mod14(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 result = IREG(reg);
+ IREG(reg) += IREG(TMR_IR1);
+ return result;
+}
+
+UINT32 tms3203x_device::mod15(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 result = IREG(reg);
+ IREG(reg) -= IREG(TMR_IR1);
+ return result;
+}
+
+UINT32 tms3203x_device::mod16(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 result = IREG(reg);
+ INT32 temp = (result & m_bkmask) + IREG(TMR_IR1);
+ if (temp >= IREG(TMR_BK))
+ temp -= IREG(TMR_BK);
+ IREG(reg) = (IREG(reg) & ~m_bkmask) | (temp & m_bkmask);
+ return result;
+}
+
+UINT32 tms3203x_device::mod17(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 result = IREG(reg);
+ INT32 temp = (result & m_bkmask) - IREG(TMR_IR1);
+ if (temp < 0)
+ temp += IREG(TMR_BK);
+ IREG(reg) = (IREG(reg) & ~m_bkmask) | (temp & m_bkmask);
+ return result;
+}
+
+
+// special variants
+
+UINT32 tms3203x_device::mod18(UINT32 op, UINT8 ar)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ return IREG(reg);
+}
+
+UINT32 tms3203x_device::mod19(UINT32 op, UINT8 ar)
+{
+ unimplemented(op);
+ return 0;
+}
+
+UINT32 tms3203x_device::modillegal(UINT32 op, UINT8 ar)
+{
+ illegal(op);
+ return 0;
+}
+
+
+// immediate displacement variants (implied 1)
+
+UINT32 tms3203x_device::mod00_1_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ return IREG(reg) + 1;
+}
+
+UINT32 tms3203x_device::mod01_1_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ return IREG(reg) - 1;
+}
+
+UINT32 tms3203x_device::mod02_1_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 defval = IREG(reg) + 1;
+ *defptrptr = defval;
+ defptrptr = &IREG(reg);
+ return defval;
+}
+
+UINT32 tms3203x_device::mod03_1_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 defval = IREG(reg) - 1;
+ *defptrptr = defval;
+ defptrptr = &IREG(reg);
+ return defval;
+}
+
+UINT32 tms3203x_device::mod04_1_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ *defptrptr = IREG(reg) + 1;
+ defptrptr = &IREG(reg);
+ return IREG(reg);
+}
+
+UINT32 tms3203x_device::mod05_1_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ *defptrptr = IREG(reg) - 1;
+ defptrptr = &IREG(reg);
+ return IREG(reg);
+}
+
+UINT32 tms3203x_device::mod06_1_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 result = IREG(reg);
+ INT32 temp = (result & m_bkmask) + 1;
+ if (temp >= IREG(TMR_BK))
+ temp -= IREG(TMR_BK);
+ *defptrptr = (IREG(reg) & ~m_bkmask) | (temp & m_bkmask);
+ defptrptr = &IREG(reg);
+ return result;
+}
+
+UINT32 tms3203x_device::mod07_1_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 result = IREG(reg);
+ INT32 temp = (result & m_bkmask) - 1;
+ if (temp < 0)
+ temp += IREG(TMR_BK);
+ *defptrptr = (IREG(reg) & ~m_bkmask) | (temp & m_bkmask);
+ defptrptr = &IREG(reg);
+ return result;
+}
+
+
+// IR0 displacement variants
+
+UINT32 tms3203x_device::mod08_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ return IREG(reg) + IREG(TMR_IR0);
+}
+
+UINT32 tms3203x_device::mod09_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ return IREG(reg) - IREG(TMR_IR0);
+}
+
+UINT32 tms3203x_device::mod0a_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 defval = IREG(reg) + IREG(TMR_IR0);
+ *defptrptr = defval;
+ defptrptr = &IREG(reg);
+ return defval;
+}
+
+UINT32 tms3203x_device::mod0b_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 defval = IREG(reg) - IREG(TMR_IR0);
+ *defptrptr = defval;
+ defptrptr = &IREG(reg);
+ return defval;
+}
+
+UINT32 tms3203x_device::mod0c_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ *defptrptr = IREG(reg) + IREG(TMR_IR0);
+ defptrptr = &IREG(reg);
+ return IREG(reg);
+}
+
+UINT32 tms3203x_device::mod0d_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ *defptrptr = IREG(reg) - IREG(TMR_IR0);
+ defptrptr = &IREG(reg);
+ return IREG(reg);
+}
+
+UINT32 tms3203x_device::mod0e_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 result = IREG(reg);
+ INT32 temp = (result & m_bkmask) + IREG(TMR_IR0);
+ if (temp >= IREG(TMR_BK))
+ temp -= IREG(TMR_BK);
+ *defptrptr = (IREG(reg) & ~m_bkmask) | (temp & m_bkmask);
+ defptrptr = &IREG(reg);
+ return result;
+}
+
+UINT32 tms3203x_device::mod0f_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 result = IREG(reg);
+ INT32 temp = (result & m_bkmask) - IREG(TMR_IR0);
+ if (temp < 0)
+ temp += IREG(TMR_BK);
+ *defptrptr = (IREG(reg) & ~m_bkmask) | (temp & m_bkmask);
+ defptrptr = &IREG(reg);
+ return result;
+}
+
+
+// IR1 displacement variants
+
+UINT32 tms3203x_device::mod10_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ return IREG(reg) + IREG(TMR_IR1);
+}
+
+UINT32 tms3203x_device::mod11_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ return IREG(reg) - IREG(TMR_IR1);
+}
+
+UINT32 tms3203x_device::mod12_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 defval = IREG(reg) + IREG(TMR_IR1);
+ *defptrptr = defval;
+ defptrptr = &IREG(reg);
+ return defval;
+}
+
+UINT32 tms3203x_device::mod13_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 defval = IREG(reg) - IREG(TMR_IR1);
+ *defptrptr = defval;
+ defptrptr = &IREG(reg);
+ return defval;
+}
+
+UINT32 tms3203x_device::mod14_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ *defptrptr = IREG(reg) + IREG(TMR_IR1);
+ defptrptr = &IREG(reg);
+ return IREG(reg);
+}
+
+UINT32 tms3203x_device::mod15_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ *defptrptr = IREG(reg) - IREG(TMR_IR1);
+ defptrptr = &IREG(reg);
+ return IREG(reg);
+}
+
+UINT32 tms3203x_device::mod16_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 result = IREG(reg);
+ INT32 temp = (result & m_bkmask) + IREG(TMR_IR1);
+ if (temp >= IREG(TMR_BK))
+ temp -= IREG(TMR_BK);
+ *defptrptr = (IREG(reg) & ~m_bkmask) | (temp & m_bkmask);
+ defptrptr = &IREG(reg);
+ return result;
+}
+
+UINT32 tms3203x_device::mod17_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ UINT32 result = IREG(reg);
+ INT32 temp = (result & m_bkmask) - IREG(TMR_IR1);
+ if (temp < 0)
+ temp += IREG(TMR_BK);
+ *defptrptr = (IREG(reg) & ~m_bkmask) | (temp & m_bkmask);
+ defptrptr = &IREG(reg);
+ return result;
+}
+
+UINT32 tms3203x_device::mod18_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ int reg = TMR_AR0 + (ar & 7);
+ return IREG(reg);
+}
+
+UINT32 tms3203x_device::mod19_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ unimplemented(op);
+ return 0;
+}
+
+UINT32 tms3203x_device::modillegal_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr)
+{
+ illegal(op);
+ return 0;
+}
+
+
+/*-----------------------------------------------------*/
+
+#define ABSF(dreg, sreg) \
+{ \
+ INT32 man = FREGMAN(sreg); \
+ CLR_NZVUF(); \
+ m_r[dreg] = m_r[sreg]; \
+ if (man < 0) \
+ { \
+ m_r[dreg].set_mantissa(~man); \
+ if (man == (INT32)0x80000000 && FREGEXP(sreg) == 127) \
+ IREG(TMR_ST) |= VFLAG | LVFLAG; \
+ } \
+ OR_NZF(m_r[dreg]); \
+}
+
+void tms3203x_device::absf_reg(UINT32 op)
+{
+ int dreg = (op >> 16) & 7;
+ int sreg = op & 7;
+ ABSF(dreg, sreg);
+}
+
+void tms3203x_device::absf_dir(UINT32 op)
+{
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(TMR_TEMP1, res);
+ ABSF(dreg, TMR_TEMP1);
+}
+
+void tms3203x_device::absf_ind(UINT32 op)
+{
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(TMR_TEMP1, res);
+ ABSF(dreg, TMR_TEMP1);
+}
+
+void tms3203x_device::absf_imm(UINT32 op)
+{
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(TMR_TEMP1, op);
+ ABSF(dreg, TMR_TEMP1);
+}
+
+/*-----------------------------------------------------*/
+
+#define ABSI(dreg, src) \
+{ \
+ UINT32 _res = ((INT32)src < 0) ? -src : src; \
+ if (!OVM() || _res != 0x80000000) \
+ IREG(dreg) = _res; \
+ else \
+ IREG(dreg) = 0x7fffffff; \
+ if (dreg < 8) \
+ { \
+ CLR_NZVUF(); \
+ OR_NZ(_res); \
+ if (_res == 0x80000000) \
+ IREG(TMR_ST) |= VFLAG | LVFLAG; \
+ } \
+ else if (dreg >= TMR_BK) \
+ update_special(dreg); \
+}
+
+void tms3203x_device::absi_reg(UINT32 op)
+{
+ UINT32 src = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ ABSI(dreg, src);
+}
+
+void tms3203x_device::absi_dir(UINT32 op)
+{
+ UINT32 src = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 31;
+ ABSI(dreg, src);
+}
+
+void tms3203x_device::absi_ind(UINT32 op)
+{
+ UINT32 src = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 31;
+ ABSI(dreg, src);
+}
+
+void tms3203x_device::absi_imm(UINT32 op)
+{
+ UINT32 src = (INT16)op;
+ int dreg = (op >> 16) & 31;
+ ABSI(dreg, src);
+}
+
+/*-----------------------------------------------------*/
+
+#define ADDC(dreg, src1, src2) \
+{ \
+ UINT32 _res = src1 + src2 + (IREG(TMR_ST) & CFLAG); \
+ if (!OVM() || !OVERFLOW_ADD(src1,src2,_res)) \
+ IREG(dreg) = _res; \
+ else \
+ IREG(dreg) = ((INT32)src1 < 0) ? 0x80000000 : 0x7fffffff; \
+ if (dreg < 8) \
+ { \
+ UINT32 tempc = src2 + (IREG(TMR_ST) & CFLAG); \
+ CLR_NZCVUF(); \
+ OR_NZCV_ADD(src1,tempc,_res); \
+ } \
+ else if (dreg >= TMR_BK) \
+ update_special(dreg); \
+}
+
+void tms3203x_device::addc_reg(UINT32 op)
+{
+ UINT32 src = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ ADDC(dreg, dst, src);
+}
+
+void tms3203x_device::addc_dir(UINT32 op)
+{
+ UINT32 src = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ ADDC(dreg, dst, src);
+}
+
+void tms3203x_device::addc_ind(UINT32 op)
+{
+ UINT32 src = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ ADDC(dreg, dst, src);
+}
+
+void tms3203x_device::addc_imm(UINT32 op)
+{
+ UINT32 src = (INT16)op;
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ ADDC(dreg, dst, src);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::addf_reg(UINT32 op)
+{
+ int dreg = (op >> 16) & 7;
+ addf(m_r[dreg], m_r[dreg], m_r[op & 7]);
+}
+
+void tms3203x_device::addf_dir(UINT32 op)
+{
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(TMR_TEMP1, res);
+ addf(m_r[dreg], m_r[dreg], m_r[TMR_TEMP1]);
+}
+
+void tms3203x_device::addf_ind(UINT32 op)
+{
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(TMR_TEMP1, res);
+ addf(m_r[dreg], m_r[dreg], m_r[TMR_TEMP1]);
+}
+
+void tms3203x_device::addf_imm(UINT32 op)
+{
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(TMR_TEMP1, op);
+ addf(m_r[dreg], m_r[dreg], m_r[TMR_TEMP1]);
+}
+
+/*-----------------------------------------------------*/
+
+#define ADDI(dreg, src1, src2) \
+{ \
+ UINT32 _res = src1 + src2; \
+ if (!OVM() || !OVERFLOW_ADD(src1,src2,_res)) \
+ IREG(dreg) = _res; \
+ else \
+ IREG(dreg) = ((INT32)src1 < 0) ? 0x80000000 : 0x7fffffff; \
+ if (dreg < 8) \
+ { \
+ CLR_NZCVUF(); \
+ OR_NZCV_ADD(src1,src2,_res); \
+ } \
+ else if (dreg >= TMR_BK) \
+ update_special(dreg); \
+}
+
+void tms3203x_device::addi_reg(UINT32 op)
+{
+ UINT32 src = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ ADDI(dreg, dst, src);
+}
+
+void tms3203x_device::addi_dir(UINT32 op)
+{
+ UINT32 src = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ ADDI(dreg, dst, src);
+}
+
+void tms3203x_device::addi_ind(UINT32 op)
+{
+ UINT32 src = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ ADDI(dreg, dst, src);
+}
+
+void tms3203x_device::addi_imm(UINT32 op)
+{
+ UINT32 src = (INT16)op;
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ ADDI(dreg, dst, src);
+}
+
+/*-----------------------------------------------------*/
+
+#define AND(dreg, src1, src2) \
+{ \
+ UINT32 _res = (src1) & (src2); \
+ IREG(dreg) = _res; \
+ if (dreg < 8) \
+ { \
+ CLR_NZVUF(); \
+ OR_NZ(_res); \
+ } \
+ else if (dreg >= TMR_BK) \
+ update_special(dreg); \
+}
+
+void tms3203x_device::and_reg(UINT32 op)
+{
+ UINT32 src = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ AND(dreg, dst, src);
+}
+
+void tms3203x_device::and_dir(UINT32 op)
+{
+ UINT32 src = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ AND(dreg, dst, src);
+}
+
+void tms3203x_device::and_ind(UINT32 op)
+{
+ UINT32 src = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ AND(dreg, dst, src);
+}
+
+void tms3203x_device::and_imm(UINT32 op)
+{
+ UINT32 src = (UINT16)op;
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ AND(dreg, dst, src);
+}
+
+/*-----------------------------------------------------*/
+
+#define ANDN(dreg, src1, src2) \
+{ \
+ UINT32 _res = (src1) & ~(src2); \
+ IREG(dreg) = _res; \
+ if (dreg < 8) \
+ { \
+ CLR_NZVUF(); \
+ OR_NZ(_res); \
+ } \
+ else if (dreg >= TMR_BK) \
+ update_special(dreg); \
+}
+
+void tms3203x_device::andn_reg(UINT32 op)
+{
+ UINT32 src = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ ANDN(dreg, dst, src);
+}
+
+void tms3203x_device::andn_dir(UINT32 op)
+{
+ UINT32 src = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ ANDN(dreg, dst, src);
+}
+
+void tms3203x_device::andn_ind(UINT32 op)
+{
+ UINT32 src = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ ANDN(dreg, dst, src);
+}
+
+void tms3203x_device::andn_imm(UINT32 op)
+{
+ UINT32 src = (UINT16)op;
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ ANDN(dreg, dst, src);
+}
+
+/*-----------------------------------------------------*/
+
+#define ASH(dreg, src, count) \
+{ \
+ UINT32 _res; \
+ INT32 _count = (INT16)(count << 9) >> 9; /* 7 LSBs */ \
+ if (_count < 0) \
+ { \
+ if (_count >= -31) \
+ _res = (INT32)src >> -_count; \
+ else \
+ _res = (INT32)src >> 31; \
+ } \
+ else \
+ { \
+ if (_count <= 31) \
+ _res = (INT32)src << _count; \
+ else \
+ _res = 0; \
+ } \
+ IREG(dreg) = _res; \
+ if (dreg < 8) \
+ { \
+ CLR_NZCVUF(); \
+ OR_NZ(_res); \
+ if (_count < 0) \
+ { \
+ if (_count >= -32) \
+ OR_C(((INT32)src >> (-_count - 1)) & 1); \
+ else \
+ OR_C(((INT32)src >> 31) & 1); \
+ } \
+ else if (_count > 0) \
+ { \
+ if (_count <= 32) \
+ OR_C(((UINT32)src << (_count - 1)) >> 31); \
+ } \
+ } \
+ else if (dreg >= TMR_BK) \
+ update_special(dreg); \
+}
+
+void tms3203x_device::ash_reg(UINT32 op)
+{
+ int dreg = (op >> 16) & 31;
+ int count = IREG(op & 31);
+ UINT32 src = IREG(dreg);
+ ASH(dreg, src, count);
+}
+
+void tms3203x_device::ash_dir(UINT32 op)
+{
+ int dreg = (op >> 16) & 31;
+ int count = RMEM(DIRECT(op));
+ UINT32 src = IREG(dreg);
+ ASH(dreg, src, count);
+}
+
+void tms3203x_device::ash_ind(UINT32 op)
+{
+ int dreg = (op >> 16) & 31;
+ int count = RMEM(INDIRECT_D(op, op >> 8));
+ UINT32 src = IREG(dreg);
+ ASH(dreg, src, count);
+}
+
+void tms3203x_device::ash_imm(UINT32 op)
+{
+ int dreg = (op >> 16) & 31;
+ int count = op;
+ UINT32 src = IREG(dreg);
+ ASH(dreg, src, count);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::cmpf_reg(UINT32 op)
+{
+ int dreg = (op >> 16) & 7;
+ subf(m_r[TMR_TEMP2], m_r[dreg], m_r[op & 7]);
+}
+
+void tms3203x_device::cmpf_dir(UINT32 op)
+{
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(TMR_TEMP1, res);
+ subf(m_r[TMR_TEMP2], m_r[dreg], m_r[TMR_TEMP1]);
+}
+
+void tms3203x_device::cmpf_ind(UINT32 op)
+{
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(TMR_TEMP1, res);
+ subf(m_r[TMR_TEMP2], m_r[dreg], m_r[TMR_TEMP1]);
+}
+
+void tms3203x_device::cmpf_imm(UINT32 op)
+{
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(TMR_TEMP1, op);
+ subf(m_r[TMR_TEMP2], m_r[dreg], m_r[TMR_TEMP1]);
+}
+
+/*-----------------------------------------------------*/
+
+#define CMPI(src1, src2) \
+{ \
+ UINT32 _res = src1 - src2; \
+ CLR_NZCVUF(); \
+ OR_NZCV_SUB(src1,src2,_res); \
+}
+
+void tms3203x_device::cmpi_reg(UINT32 op)
+{
+ UINT32 src = IREG(op & 31);
+ UINT32 dst = IREG((op >> 16) & 31);
+ CMPI(dst, src);
+}
+
+void tms3203x_device::cmpi_dir(UINT32 op)
+{
+ UINT32 src = RMEM(DIRECT(op));
+ UINT32 dst = IREG((op >> 16) & 31);
+ CMPI(dst, src);
+}
+
+void tms3203x_device::cmpi_ind(UINT32 op)
+{
+ UINT32 src = RMEM(INDIRECT_D(op, op >> 8));
+ UINT32 dst = IREG((op >> 16) & 31);
+ CMPI(dst, src);
+}
+
+void tms3203x_device::cmpi_imm(UINT32 op)
+{
+ UINT32 src = (INT16)op;
+ UINT32 dst = IREG((op >> 16) & 31);
+ CMPI(dst, src);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::fix_reg(UINT32 op)
+{
+ int dreg = (op >> 16) & 31;
+ m_r[dreg] = m_r[op & 7];
+ float2int(m_r[dreg], dreg < 8);
+}
+
+void tms3203x_device::fix_dir(UINT32 op)
+{
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 31;
+ LONG2FP(dreg, res);
+ float2int(m_r[dreg], dreg < 8);
+}
+
+void tms3203x_device::fix_ind(UINT32 op)
+{
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 31;
+ LONG2FP(dreg, res);
+ float2int(m_r[dreg], dreg < 8);
+}
+
+void tms3203x_device::fix_imm(UINT32 op)
+{
+ int dreg = (op >> 16) & 31;
+ SHORT2FP(dreg, op);
+ float2int(m_r[dreg], dreg < 8);
+}
+
+/*-----------------------------------------------------*/
+
+#define FLOAT(dreg, src) \
+{ \
+ IREG(dreg) = src; \
+ int2float(m_r[dreg]); \
+}
+
+void tms3203x_device::float_reg(UINT32 op)
+{
+ UINT32 src = IREG(op & 31);
+ int dreg = (op >> 16) & 7;
+ FLOAT(dreg, src);
+}
+
+void tms3203x_device::float_dir(UINT32 op)
+{
+ UINT32 src = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ FLOAT(dreg, src);
+}
+
+void tms3203x_device::float_ind(UINT32 op)
+{
+ UINT32 src = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ FLOAT(dreg, src);
+}
+
+void tms3203x_device::float_imm(UINT32 op)
+{
+ UINT32 src = (INT16)op;
+ int dreg = (op >> 16) & 7;
+ FLOAT(dreg, src);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::idle(UINT32 op)
+{
+ m_is_idling = true;
+ IREG(TMR_ST) |= GIEFLAG;
+ check_irqs();
+ if (m_is_idling)
+ m_icount = 0;
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::lde_reg(UINT32 op)
+{
+ int dreg = (op >> 16) & 7;
+ m_r[dreg].set_exponent(m_r[op & 7].exponent());
+ if (m_r[dreg].exponent() == -128)
+ m_r[dreg].set_mantissa(0);
+}
+
+void tms3203x_device::lde_dir(UINT32 op)
+{
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(TMR_TEMP1, res);
+ m_r[dreg].set_exponent(m_r[TMR_TEMP1].exponent());
+ if (m_r[dreg].exponent() == -128)
+ m_r[dreg].set_mantissa(0);
+}
+
+void tms3203x_device::lde_ind(UINT32 op)
+{
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(TMR_TEMP1, res);
+ m_r[dreg].set_exponent(m_r[TMR_TEMP1].exponent());
+ if (m_r[dreg].exponent() == -128)
+ m_r[dreg].set_mantissa(0);
+}
+
+void tms3203x_device::lde_imm(UINT32 op)
+{
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(TMR_TEMP1, op);
+ m_r[dreg].set_exponent(m_r[TMR_TEMP1].exponent());
+ if (m_r[dreg].exponent() == -128)
+ m_r[dreg].set_mantissa(0);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldf_reg(UINT32 op)
+{
+ int dreg = (op >> 16) & 7;
+ m_r[dreg] = m_r[op & 7];
+ CLR_NZVUF();
+ OR_NZF(m_r[dreg]);
+}
+
+void tms3203x_device::ldf_dir(UINT32 op)
+{
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ CLR_NZVUF();
+ OR_NZF(m_r[dreg]);
+}
+
+void tms3203x_device::ldf_ind(UINT32 op)
+{
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ CLR_NZVUF();
+ OR_NZF(m_r[dreg]);
+}
+
+void tms3203x_device::ldf_imm(UINT32 op)
+{
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(dreg, op);
+ CLR_NZVUF();
+ OR_NZF(m_r[dreg]);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldfi_dir(UINT32 op) { unimplemented(op); }
+void tms3203x_device::ldfi_ind(UINT32 op) { unimplemented(op); }
+
+/*-----------------------------------------------------*/
+
+#define LDI(dreg, src) \
+{ \
+ IREG(dreg) = src; \
+ if (dreg < 8) \
+ { \
+ CLR_NZVUF(); \
+ OR_NZ(src); \
+ } \
+ else if (dreg >= TMR_BK) \
+ update_special(dreg); \
+}
+
+void tms3203x_device::ldi_reg(UINT32 op)
+{
+ UINT32 src = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ LDI(dreg, src);
+}
+
+void tms3203x_device::ldi_dir(UINT32 op)
+{
+ UINT32 src = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 31;
+ LDI(dreg, src);
+}
+
+void tms3203x_device::ldi_ind(UINT32 op)
+{
+ UINT32 src = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 31;
+ LDI(dreg, src);
+}
+
+void tms3203x_device::ldi_imm(UINT32 op)
+{
+ UINT32 src = (INT16)op;
+ int dreg = (op >> 16) & 31;
+ LDI(dreg, src);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldii_dir(UINT32 op) { unimplemented(op); }
+void tms3203x_device::ldii_ind(UINT32 op) { unimplemented(op); }
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldm_reg(UINT32 op)
+{
+ int dreg = (op >> 16) & 7;
+ m_r[dreg].set_mantissa(m_r[op & 7].mantissa());
+}
+
+void tms3203x_device::ldm_dir(UINT32 op)
+{
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ m_r[dreg].set_mantissa(res);
+}
+
+void tms3203x_device::ldm_ind(UINT32 op)
+{
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ m_r[dreg].set_mantissa(res);
+}
+
+void tms3203x_device::ldm_imm(UINT32 op)
+{
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(TMR_TEMP1, op);
+ m_r[dreg].set_mantissa(m_r[TMR_TEMP1].mantissa());
+}
+
+/*-----------------------------------------------------*/
+
+#define LSH(dreg, src, count) \
+{ \
+ UINT32 _res; \
+ INT32 _count = (INT16)(count << 9) >> 9; /* 7 LSBs */ \
+ if (_count < 0) \
+ { \
+ if (_count >= -31) \
+ _res = (UINT32)src >> -_count; \
+ else \
+ _res = 0; \
+ } \
+ else \
+ { \
+ if (_count <= 31) \
+ _res = (UINT32)src << _count; \
+ else \
+ _res = 0; \
+ } \
+ IREG(dreg) = _res; \
+ if (dreg < 8) \
+ { \
+ CLR_NZCVUF(); \
+ OR_NZ(_res); \
+ if (_count < 0) \
+ { \
+ if (_count >= -32) \
+ OR_C(((UINT32)src >> (-_count - 1)) & 1); \
+ } \
+ else if (_count > 0) \
+ { \
+ if (_count <= 32) \
+ OR_C(((UINT32)src << (_count - 1)) >> 31); \
+ } \
+ } \
+ else if (dreg >= TMR_BK) \
+ update_special(dreg); \
+}
+
+void tms3203x_device::lsh_reg(UINT32 op)
+{
+ int dreg = (op >> 16) & 31;
+ int count = IREG(op & 31);
+ UINT32 src = IREG(dreg);
+ LSH(dreg, src, count);
+}
+
+void tms3203x_device::lsh_dir(UINT32 op)
+{
+ int dreg = (op >> 16) & 31;
+ int count = RMEM(DIRECT(op));
+ UINT32 src = IREG(dreg);
+ LSH(dreg, src, count);
+}
+
+void tms3203x_device::lsh_ind(UINT32 op)
+{
+ int dreg = (op >> 16) & 31;
+ int count = RMEM(INDIRECT_D(op, op >> 8));
+ UINT32 src = IREG(dreg);
+ LSH(dreg, src, count);
+}
+
+void tms3203x_device::lsh_imm(UINT32 op)
+{
+ int dreg = (op >> 16) & 31;
+ int count = op;
+ UINT32 src = IREG(dreg);
+ LSH(dreg, src, count);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::mpyf_reg(UINT32 op)
+{
+ int dreg = (op >> 16) & 31;
+ mpyf(m_r[dreg], m_r[dreg], m_r[op & 31]);
+}
+
+void tms3203x_device::mpyf_dir(UINT32 op)
+{
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 31;
+ LONG2FP(TMR_TEMP1, res);
+ mpyf(m_r[dreg], m_r[dreg], m_r[TMR_TEMP1]);
+}
+
+void tms3203x_device::mpyf_ind(UINT32 op)
+{
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 31;
+ LONG2FP(TMR_TEMP1, res);
+ mpyf(m_r[dreg], m_r[dreg], m_r[TMR_TEMP1]);
+}
+
+void tms3203x_device::mpyf_imm(UINT32 op)
+{
+ int dreg = (op >> 16) & 31;
+ SHORT2FP(TMR_TEMP1, op);
+ mpyf(m_r[dreg], m_r[dreg], m_r[TMR_TEMP1]);
+}
+
+/*-----------------------------------------------------*/
+
+#define MPYI(dreg, src1, src2) \
+{ \
+ INT64 _res = (INT64)((INT32)(src1 << 8) >> 8) * (INT64)((INT32)(src2 << 8) >> 8);\
+ if (!OVM() || (_res >= -0x80000000 && _res <= 0x7fffffff)) \
+ IREG(dreg) = _res; \
+ else \
+ IREG(dreg) = (_res < 0) ? 0x80000000 : 0x7fffffff; \
+ if (dreg < 8) \
+ { \
+ CLR_NZVUF(); \
+ OR_NZ((UINT32)_res); \
+ if (_res < -(INT64)0x80000000 || _res > (INT64)0x7fffffff) \
+ IREG(TMR_ST) |= VFLAG | LVFLAG; \
+ } \
+ else if (dreg >= TMR_BK) \
+ update_special(dreg); \
+}
+
+void tms3203x_device::mpyi_reg(UINT32 op)
+{
+ UINT32 src = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ MPYI(dreg, dst, src);
+}
+
+void tms3203x_device::mpyi_dir(UINT32 op)
+{
+ UINT32 src = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ MPYI(dreg, dst, src);
+}
+
+void tms3203x_device::mpyi_ind(UINT32 op)
+{
+ UINT32 src = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ MPYI(dreg, dst, src);
+}
+
+void tms3203x_device::mpyi_imm(UINT32 op)
+{
+ UINT32 src = (INT16)op;
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ MPYI(dreg, dst, src);
+}
+
+/*-----------------------------------------------------*/
+
+#define NEGB(dreg, src) \
+{ \
+ UINT32 temps = 0 - (IREG(TMR_ST) & CFLAG); \
+ UINT32 _res = temps - src; \
+ if (!OVM() || !OVERFLOW_SUB(temps,src,_res)) \
+ IREG(dreg) = _res; \
+ else \
+ IREG(dreg) = ((INT32)src < 0) ? 0x80000000 : 0x7fffffff; \
+ if (dreg < 8) \
+ { \
+ CLR_NZCVUF(); \
+ OR_NZCV_SUB(temps,src,_res); \
+ } \
+ else if (dreg >= TMR_BK) \
+ update_special(dreg); \
+}
+
+void tms3203x_device::negb_reg(UINT32 op)
+{
+ UINT32 src = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ NEGB(dreg, src);
+}
+
+void tms3203x_device::negb_dir(UINT32 op)
+{
+ UINT32 src = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 31;
+ NEGB(dreg, src);
+}
+
+void tms3203x_device::negb_ind(UINT32 op)
+{
+ UINT32 src = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 31;
+ NEGB(dreg, src);
+}
+
+void tms3203x_device::negb_imm(UINT32 op)
+{
+ UINT32 src = (INT16)op;
+ int dreg = (op >> 16) & 31;
+ NEGB(dreg, src);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::negf_reg(UINT32 op)
+{
+ int dreg = (op >> 16) & 7;
+ negf(m_r[dreg], m_r[op & 7]);
+}
+
+void tms3203x_device::negf_dir(UINT32 op)
+{
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(TMR_TEMP1, res);
+ negf(m_r[dreg], m_r[TMR_TEMP1]);
+}
+
+void tms3203x_device::negf_ind(UINT32 op)
+{
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(TMR_TEMP1, res);
+ negf(m_r[dreg], m_r[TMR_TEMP1]);
+}
+
+void tms3203x_device::negf_imm(UINT32 op)
+{
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(TMR_TEMP1, op);
+ negf(m_r[dreg], m_r[TMR_TEMP1]);
+}
+
+/*-----------------------------------------------------*/
+
+#define NEGI(dreg, src) \
+{ \
+ UINT32 _res = 0 - src; \
+ if (!OVM() || !OVERFLOW_SUB(0,src,_res)) \
+ IREG(dreg) = _res; \
+ else \
+ IREG(dreg) = ((INT32)src < 0) ? 0x80000000 : 0x7fffffff; \
+ if (dreg < 8) \
+ { \
+ CLR_NZCVUF(); \
+ OR_NZCV_SUB(0,src,_res); \
+ } \
+ else if (dreg >= TMR_BK) \
+ update_special(dreg); \
+}
+
+void tms3203x_device::negi_reg(UINT32 op)
+{
+ UINT32 src = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ NEGI(dreg, src);
+}
+
+void tms3203x_device::negi_dir(UINT32 op)
+{
+ UINT32 src = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 31;
+ NEGI(dreg, src);
+}
+
+void tms3203x_device::negi_ind(UINT32 op)
+{
+ UINT32 src = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 31;
+ NEGI(dreg, src);
+}
+
+void tms3203x_device::negi_imm(UINT32 op)
+{
+ UINT32 src = (INT16)op;
+ int dreg = (op >> 16) & 31;
+ NEGI(dreg, src);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::nop_reg(UINT32 op)
+{
+}
+
+void tms3203x_device::nop_ind(UINT32 op)
+{
+ RMEM(INDIRECT_D(op, op >> 8));
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::norm_reg(UINT32 op)
+{
+ int dreg = (op >> 16) & 7;
+ norm(m_r[dreg], m_r[op & 7]);
+}
+
+void tms3203x_device::norm_dir(UINT32 op)
+{
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(TMR_TEMP1, res);
+ norm(m_r[dreg], m_r[TMR_TEMP1]);
+}
+
+void tms3203x_device::norm_ind(UINT32 op)
+{
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(TMR_TEMP1, res);
+ norm(m_r[dreg], m_r[TMR_TEMP1]);
+}
+
+void tms3203x_device::norm_imm(UINT32 op)
+{
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(TMR_TEMP1, op);
+ norm(m_r[dreg], m_r[TMR_TEMP1]);
+}
+
+/*-----------------------------------------------------*/
+
+#define NOT(dreg, src) \
+{ \
+ UINT32 _res = ~(src); \
+ IREG(dreg) = _res; \
+ if (dreg < 8) \
+ { \
+ CLR_NZVUF(); \
+ OR_NZ(_res); \
+ } \
+ else if (dreg >= TMR_BK) \
+ update_special(dreg); \
+}
+
+void tms3203x_device::not_reg(UINT32 op)
+{
+ UINT32 src = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ NOT(dreg, src);
+}
+
+void tms3203x_device::not_dir(UINT32 op)
+{
+ UINT32 src = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 31;
+ NOT(dreg, src);
+}
+
+void tms3203x_device::not_ind(UINT32 op)
+{
+ UINT32 src = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 31;
+ NOT(dreg, src);
+}
+
+void tms3203x_device::not_imm(UINT32 op)
+{
+ UINT32 src = (UINT16)op;
+ int dreg = (op >> 16) & 31;
+ NOT(dreg, src);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::pop(UINT32 op)
+{
+ int dreg = (op >> 16) & 31;
+ UINT32 val = RMEM(IREG(TMR_SP)--);
+ IREG(dreg) = val;
+ if (dreg < 8)
+ {
+ CLR_NZVUF();
+ OR_NZ(val);
+ }
+ else if (dreg >= TMR_BK)
+ update_special(dreg);
+}
+
+void tms3203x_device::popf(UINT32 op)
+{
+ int dreg = (op >> 16) & 7;
+ UINT32 val = RMEM(IREG(TMR_SP)--);
+ LONG2FP(dreg, val);
+ CLR_NZVUF();
+ OR_NZF(m_r[dreg]);
+}
+
+void tms3203x_device::push(UINT32 op)
+{
+ WMEM(++IREG(TMR_SP), IREG((op >> 16) & 31));
+}
+
+void tms3203x_device::pushf(UINT32 op)
+{
+ int dreg = (op >> 16) & 7;
+ WMEM(++IREG(TMR_SP), FP2LONG(dreg));
+}
+
+/*-----------------------------------------------------*/
+
+#define OR(dreg, src1, src2) \
+{ \
+ UINT32 _res = (src1) | (src2); \
+ IREG(dreg) = _res; \
+ if (dreg < 8) \
+ { \
+ CLR_NZVUF(); \
+ OR_NZ(_res); \
+ } \
+ else if (dreg >= TMR_BK) \
+ update_special(dreg); \
+}
+
+void tms3203x_device::or_reg(UINT32 op)
+{
+ UINT32 src = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ OR(dreg, dst, src);
+}
+
+void tms3203x_device::or_dir(UINT32 op)
+{
+ UINT32 src = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ OR(dreg, dst, src);
+}
+
+void tms3203x_device::or_ind(UINT32 op)
+{
+ UINT32 src = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ OR(dreg, dst, src);
+}
+
+void tms3203x_device::or_imm(UINT32 op)
+{
+ UINT32 src = (UINT16)op;
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ OR(dreg, dst, src);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::maxspeed(UINT32 op) { unimplemented(op); }
+
+/*-----------------------------------------------------*/
+
+#define RND(dreg) \
+{ \
+ INT32 man = FREGMAN(dreg); \
+ CLR_NVUF(); \
+ if (man < 0x7fffff80) \
+ { \
+ m_r[dreg].set_mantissa(((UINT32)man + 0x80) & 0xffffff00); \
+ OR_NUF(m_r[dreg]); \
+ } \
+ else if (FREGEXP(dreg) < 127) \
+ { \
+ m_r[dreg].set_mantissa(((UINT32)man + 0x80) & 0x7fffff00); \
+ m_r[dreg].set_exponent(FREGEXP(dreg) + 1); \
+ OR_NUF(m_r[dreg]); \
+ } \
+ else \
+ { \
+ m_r[dreg].set_mantissa(0x7fffff00); \
+ IREG(TMR_ST) |= VFLAG | LVFLAG; \
+ } \
+}
+
+void tms3203x_device::rnd_reg(UINT32 op)
+{
+ int sreg = op & 7;
+ int dreg = (op >> 16) & 7;
+ m_r[dreg] = m_r[sreg];
+ RND(dreg);
+}
+
+void tms3203x_device::rnd_dir(UINT32 op)
+{
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ RND(dreg);
+}
+
+void tms3203x_device::rnd_ind(UINT32 op)
+{
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ RND(dreg);
+}
+
+void tms3203x_device::rnd_imm(UINT32 op)
+{
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(dreg, op);
+ RND(dreg);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::rol(UINT32 op)
+{
+ int dreg = (op >> 16) & 31;
+ UINT32 res = IREG(dreg);
+ int newcflag = res >> 31;
+ res = (res << 1) | newcflag;
+ IREG(dreg) = res;
+ if (dreg < 8)
+ {
+ CLR_NZCVUF();
+ OR_NZ(res);
+ OR_C(newcflag);
+ }
+ else if (dreg >= TMR_BK)
+ update_special(dreg);
+}
+
+void tms3203x_device::rolc(UINT32 op)
+{
+ int dreg = (op >> 16) & 31;
+ UINT32 res = IREG(dreg);
+ int newcflag = res >> 31;
+ res = (res << 1) | (IREG(TMR_ST) & CFLAG);
+ IREG(dreg) = res;
+ if (dreg < 8)
+ {
+ CLR_NZCVUF();
+ OR_NZ(res);
+ OR_C(newcflag);
+ }
+ else if (dreg >= TMR_BK)
+ update_special(dreg);
+}
+
+void tms3203x_device::ror(UINT32 op)
+{
+ int dreg = (op >> 16) & 31;
+ UINT32 res = IREG(dreg);
+ int newcflag = res & 1;
+ res = (res >> 1) | (newcflag << 31);
+ IREG(dreg) = res;
+ if (dreg < 8)
+ {
+ CLR_NZCVUF();
+ OR_NZ(res);
+ OR_C(newcflag);
+ }
+ else if (dreg >= TMR_BK)
+ update_special(dreg);
+}
+
+void tms3203x_device::rorc(UINT32 op)
+{
+ int dreg = (op >> 16) & 31;
+ UINT32 res = IREG(dreg);
+ int newcflag = res & 1;
+ res = (res >> 1) | ((IREG(TMR_ST) & CFLAG) << 31);
+ IREG(dreg) = res;
+ if (dreg < 8)
+ {
+ CLR_NZCVUF();
+ OR_NZ(res);
+ OR_C(newcflag);
+ }
+ else if (dreg >= TMR_BK)
+ update_special(dreg);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::rtps_reg(UINT32 op)
+{
+ IREG(TMR_RC) = IREG(op & 31);
+ IREG(TMR_RS) = m_pc;
+ IREG(TMR_RE) = m_pc;
+ IREG(TMR_ST) |= RMFLAG;
+ m_icount -= 3*2;
+ m_delayed = true;
+}
+
+void tms3203x_device::rtps_dir(UINT32 op)
+{
+ IREG(TMR_RC) = RMEM(DIRECT(op));
+ IREG(TMR_RS) = m_pc;
+ IREG(TMR_RE) = m_pc;
+ IREG(TMR_ST) |= RMFLAG;
+ m_icount -= 3*2;
+ m_delayed = true;
+}
+
+void tms3203x_device::rtps_ind(UINT32 op)
+{
+ IREG(TMR_RC) = RMEM(INDIRECT_D(op, op >> 8));
+ IREG(TMR_RS) = m_pc;
+ IREG(TMR_RE) = m_pc;
+ IREG(TMR_ST) |= RMFLAG;
+ m_icount -= 3*2;
+ m_delayed = true;
+}
+
+void tms3203x_device::rtps_imm(UINT32 op)
+{
+ IREG(TMR_RC) = (UINT16)op;
+ IREG(TMR_RS) = m_pc;
+ IREG(TMR_RE) = m_pc;
+ IREG(TMR_ST) |= RMFLAG;
+ m_icount -= 3*2;
+ m_delayed = true;
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::stf_dir(UINT32 op)
+{
+ WMEM(DIRECT(op), FP2LONG((op >> 16) & 7));
+}
+
+void tms3203x_device::stf_ind(UINT32 op)
+{
+ WMEM(INDIRECT_D(op, op >> 8), FP2LONG((op >> 16) & 7));
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::stfi_dir(UINT32 op) { unimplemented(op); }
+void tms3203x_device::stfi_ind(UINT32 op) { unimplemented(op); }
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::sti_dir(UINT32 op)
+{
+ WMEM(DIRECT(op), IREG((op >> 16) & 31));
+}
+
+void tms3203x_device::sti_ind(UINT32 op)
+{
+ WMEM(INDIRECT_D(op, op >> 8), IREG((op >> 16) & 31));
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::stii_dir(UINT32 op) { unimplemented(op); }
+void tms3203x_device::stii_ind(UINT32 op) { unimplemented(op); }
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::sigi(UINT32 op) { unimplemented(op); }
+
+/*-----------------------------------------------------*/
+
+#define SUBB(dreg, src1, src2) \
+{ \
+ UINT32 temps = src1 - (IREG(TMR_ST) & CFLAG); \
+ UINT32 _res = temps - src2; \
+ if (!OVM() || !OVERFLOW_SUB(temps,src2,_res)) \
+ IREG(dreg) = _res; \
+ else \
+ IREG(dreg) = ((INT32)src1 < 0) ? 0x80000000 : 0x7fffffff; \
+ if (dreg < 8) \
+ { \
+ CLR_NZCVUF(); \
+ OR_NZCV_SUB(temps,src2,_res); \
+ } \
+ else if (dreg >= TMR_BK) \
+ update_special(dreg); \
+}
+
+void tms3203x_device::subb_reg(UINT32 op)
+{
+ UINT32 src = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ SUBB(dreg, dst, src);
+}
+
+void tms3203x_device::subb_dir(UINT32 op)
+{
+ UINT32 src = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ SUBB(dreg, dst, src);
+}
+
+void tms3203x_device::subb_ind(UINT32 op)
+{
+ UINT32 src = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ SUBB(dreg, dst, src);
+}
+
+void tms3203x_device::subb_imm(UINT32 op)
+{
+ UINT32 src = (INT16)op;
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ SUBB(dreg, dst, src);
+}
+
+/*-----------------------------------------------------*/
+
+#define SUBC(dreg, src) \
+{ \
+ UINT32 dst = IREG(dreg); \
+ if (dst >= src) \
+ IREG(dreg) = ((dst - src) << 1) | 1; \
+ else \
+ IREG(dreg) = dst << 1; \
+ if (dreg >= TMR_BK) \
+ update_special(dreg); \
+}
+
+void tms3203x_device::subc_reg(UINT32 op)
+{
+ UINT32 src = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ SUBC(dreg, src);
+}
+
+void tms3203x_device::subc_dir(UINT32 op)
+{
+ UINT32 src = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 31;
+ SUBC(dreg, src);
+}
+
+void tms3203x_device::subc_ind(UINT32 op)
+{
+ UINT32 src = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 31;
+ SUBC(dreg, src);
+}
+
+void tms3203x_device::subc_imm(UINT32 op)
+{
+ UINT32 src = (INT16)op;
+ int dreg = (op >> 16) & 31;
+ SUBC(dreg, src);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::subf_reg(UINT32 op)
+{
+ int dreg = (op >> 16) & 7;
+ subf(m_r[dreg], m_r[dreg], m_r[op & 7]);
+}
+
+void tms3203x_device::subf_dir(UINT32 op)
+{
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(TMR_TEMP1, res);
+ subf(m_r[dreg], m_r[dreg], m_r[TMR_TEMP1]);
+}
+
+void tms3203x_device::subf_ind(UINT32 op)
+{
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(TMR_TEMP1, res);
+ subf(m_r[dreg], m_r[dreg], m_r[TMR_TEMP1]);
+}
+
+void tms3203x_device::subf_imm(UINT32 op)
+{
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(TMR_TEMP1, op);
+ subf(m_r[dreg], m_r[dreg], m_r[TMR_TEMP1]);
+}
+
+/*-----------------------------------------------------*/
+
+#define SUBI(dreg, src1, src2) \
+{ \
+ UINT32 _res = src1 - src2; \
+ if (!OVM() || !OVERFLOW_SUB(src1,src2,_res)) \
+ IREG(dreg) = _res; \
+ else \
+ IREG(dreg) = ((INT32)src1 < 0) ? 0x80000000 : 0x7fffffff; \
+ if (dreg < 8) \
+ { \
+ CLR_NZCVUF(); \
+ OR_NZCV_SUB(src1,src2,_res); \
+ } \
+ else if (dreg >= TMR_BK) \
+ update_special(dreg); \
+}
+
+void tms3203x_device::subi_reg(UINT32 op)
+{
+ UINT32 src = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ SUBI(dreg, dst, src);
+}
+
+void tms3203x_device::subi_dir(UINT32 op)
+{
+ UINT32 src = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ SUBI(dreg, dst, src);
+}
+
+void tms3203x_device::subi_ind(UINT32 op)
+{
+ UINT32 src = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ SUBI(dreg, dst, src);
+}
+
+void tms3203x_device::subi_imm(UINT32 op)
+{
+ UINT32 src = (INT16)op;
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ SUBI(dreg, dst, src);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::subrb_reg(UINT32 op)
+{
+ UINT32 src = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ SUBB(dreg, src, dst);
+}
+
+void tms3203x_device::subrb_dir(UINT32 op)
+{
+ UINT32 src = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ SUBB(dreg, src, dst);
+}
+
+void tms3203x_device::subrb_ind(UINT32 op)
+{
+ UINT32 src = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ SUBB(dreg, src, dst);
+}
+
+void tms3203x_device::subrb_imm(UINT32 op)
+{
+ UINT32 src = (INT16)op;
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ SUBB(dreg, src, dst);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::subrf_reg(UINT32 op)
+{
+ int dreg = (op >> 16) & 7;
+ subf(m_r[dreg], m_r[op & 7], m_r[dreg]);
+}
+
+void tms3203x_device::subrf_dir(UINT32 op)
+{
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(TMR_TEMP1, res);
+ subf(m_r[dreg], m_r[TMR_TEMP1], m_r[dreg]);
+}
+
+void tms3203x_device::subrf_ind(UINT32 op)
+{
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(TMR_TEMP1, res);
+ subf(m_r[dreg], m_r[TMR_TEMP1], m_r[dreg]);
+}
+
+void tms3203x_device::subrf_imm(UINT32 op)
+{
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(TMR_TEMP1, op);
+ subf(m_r[dreg], m_r[TMR_TEMP1], m_r[dreg]);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::subri_reg(UINT32 op)
+{
+ UINT32 src = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ SUBI(dreg, src, dst);
+}
+
+void tms3203x_device::subri_dir(UINT32 op)
+{
+ UINT32 src = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ SUBI(dreg, src, dst);
+}
+
+void tms3203x_device::subri_ind(UINT32 op)
+{
+ UINT32 src = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ SUBI(dreg, src, dst);
+}
+
+void tms3203x_device::subri_imm(UINT32 op)
+{
+ UINT32 src = (INT16)op;
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ SUBI(dreg, src, dst);
+}
+
+/*-----------------------------------------------------*/
+
+#define TSTB(src1, src2) \
+{ \
+ UINT32 _res = (src1) & (src2); \
+ CLR_NZVUF(); \
+ OR_NZ(_res); \
+}
+
+void tms3203x_device::tstb_reg(UINT32 op)
+{
+ UINT32 src = IREG(op & 31);
+ UINT32 dst = IREG((op >> 16) & 31);
+ TSTB(dst, src);
+}
+
+void tms3203x_device::tstb_dir(UINT32 op)
+{
+ UINT32 src = RMEM(DIRECT(op));
+ UINT32 dst = IREG((op >> 16) & 31);
+ TSTB(dst, src);
+}
+
+void tms3203x_device::tstb_ind(UINT32 op)
+{
+ UINT32 src = RMEM(INDIRECT_D(op, op >> 8));
+ UINT32 dst = IREG((op >> 16) & 31);
+ TSTB(dst, src);
+}
+
+void tms3203x_device::tstb_imm(UINT32 op)
+{
+ UINT32 src = (UINT16)op;
+ UINT32 dst = IREG((op >> 16) & 31);
+ TSTB(dst, src);
+}
+
+/*-----------------------------------------------------*/
+
+#define XOR(dreg, src1, src2) \
+{ \
+ UINT32 _res = (src1) ^ (src2); \
+ IREG(dreg) = _res; \
+ if (dreg < 8) \
+ { \
+ CLR_NZVUF(); \
+ OR_NZ(_res); \
+ } \
+ else if (dreg >= TMR_BK) \
+ update_special(dreg); \
+}
+
+void tms3203x_device::xor_reg(UINT32 op)
+{
+ UINT32 src = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ XOR(dreg, dst, src);
+}
+
+void tms3203x_device::xor_dir(UINT32 op)
+{
+ UINT32 src = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ XOR(dreg, dst, src);
+}
+
+void tms3203x_device::xor_ind(UINT32 op)
+{
+ UINT32 src = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ XOR(dreg, dst, src);
+}
+
+void tms3203x_device::xor_imm(UINT32 op)
+{
+ UINT32 src = (UINT16)op;
+ int dreg = (op >> 16) & 31;
+ UINT32 dst = IREG(dreg);
+ XOR(dreg, dst, src);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::iack_dir(UINT32 op)
+{
+ offs_t addr = DIRECT(op);
+ if (m_iack_w)
+ (*m_iack_w)(*this, ASSERT_LINE, addr);
+ RMEM(addr);
+ if (m_iack_w)
+ (*m_iack_w)(*this, CLEAR_LINE, addr);
+}
+
+void tms3203x_device::iack_ind(UINT32 op)
+{
+ offs_t addr = INDIRECT_D(op, op >> 8);
+ if (m_iack_w)
+ (*m_iack_w)(*this, ASSERT_LINE, addr);
+ RMEM(addr);
+ if (m_iack_w)
+ (*m_iack_w)(*this, CLEAR_LINE, addr);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::addc3_regreg(UINT32 op)
+{
+ UINT32 src1 = IREG((op >> 8) & 31);
+ UINT32 src2 = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ ADDC(dreg, src1, src2);
+}
+
+void tms3203x_device::addc3_indreg(UINT32 op)
+{
+ UINT32 src1 = RMEM(INDIRECT_1(op, op >> 8));
+ UINT32 src2 = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ ADDC(dreg, src1, src2);
+}
+
+void tms3203x_device::addc3_regind(UINT32 op)
+{
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ UINT32 src1 = IREG((op >> 8) & 31);
+ int dreg = (op >> 16) & 31;
+ ADDC(dreg, src1, src2);
+}
+
+void tms3203x_device::addc3_indind(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src1 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ int dreg = (op >> 16) & 31;
+ UPDATE_DEF();
+ ADDC(dreg, src1, src2);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::addf3_regreg(UINT32 op)
+{
+ int sreg1 = (op >> 8) & 7;
+ int sreg2 = op & 7;
+ int dreg = (op >> 16) & 7;
+ addf(m_r[dreg], m_r[sreg1], m_r[sreg2]);
+}
+
+void tms3203x_device::addf3_indreg(UINT32 op)
+{
+ UINT32 src1 = RMEM(INDIRECT_1(op, op >> 8));
+ int sreg2 = op & 7;
+ int dreg = (op >> 16) & 7;
+ LONG2FP(TMR_TEMP1, src1);
+ addf(m_r[dreg], m_r[TMR_TEMP1], m_r[sreg2]);
+}
+
+void tms3203x_device::addf3_regind(UINT32 op)
+{
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ int sreg1 = (op >> 8) & 7;
+ int dreg = (op >> 16) & 7;
+ LONG2FP(TMR_TEMP2, src2);
+ addf(m_r[dreg], m_r[sreg1], m_r[TMR_TEMP2]);
+}
+
+void tms3203x_device::addf3_indind(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src1 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ int dreg = (op >> 16) & 7;
+ UPDATE_DEF();
+ LONG2FP(TMR_TEMP1, src1);
+ LONG2FP(TMR_TEMP2, src2);
+ addf(m_r[dreg], m_r[TMR_TEMP1], m_r[TMR_TEMP2]);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::addi3_regreg(UINT32 op)
+{
+ UINT32 src1 = IREG((op >> 8) & 31);
+ UINT32 src2 = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ ADDI(dreg, src1, src2);
+}
+
+void tms3203x_device::addi3_indreg(UINT32 op)
+{
+ UINT32 src1 = RMEM(INDIRECT_1(op, op >> 8));
+ UINT32 src2 = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ ADDI(dreg, src1, src2);
+}
+
+void tms3203x_device::addi3_regind(UINT32 op)
+{
+ // Radikal Bikers confirms via ADDI3 AR3,*AR3++(1),R2 / SUB $0001,R2 sequence
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ UINT32 src1 = IREG((op >> 8) & 31);
+ int dreg = (op >> 16) & 31;
+ ADDI(dreg, src1, src2);
+}
+
+void tms3203x_device::addi3_indind(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src1 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ int dreg = (op >> 16) & 31;
+ UPDATE_DEF();
+ ADDI(dreg, src1, src2);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::and3_regreg(UINT32 op)
+{
+ UINT32 src1 = IREG((op >> 8) & 31);
+ UINT32 src2 = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ AND(dreg, src1, src2);
+}
+
+void tms3203x_device::and3_indreg(UINT32 op)
+{
+ UINT32 src1 = RMEM(INDIRECT_1(op, op >> 8));
+ UINT32 src2 = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ AND(dreg, src1, src2);
+}
+
+void tms3203x_device::and3_regind(UINT32 op)
+{
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ UINT32 src1 = IREG((op >> 8) & 31);
+ int dreg = (op >> 16) & 31;
+ AND(dreg, src1, src2);
+}
+
+void tms3203x_device::and3_indind(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src1 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ int dreg = (op >> 16) & 31;
+ UPDATE_DEF();
+ AND(dreg, src1, src2);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::andn3_regreg(UINT32 op)
+{
+ UINT32 src1 = IREG((op >> 8) & 31);
+ UINT32 src2 = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ ANDN(dreg, src1, src2);
+}
+
+void tms3203x_device::andn3_indreg(UINT32 op)
+{
+ UINT32 src1 = RMEM(INDIRECT_1(op, op >> 8));
+ UINT32 src2 = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ ANDN(dreg, src1, src2);
+}
+
+void tms3203x_device::andn3_regind(UINT32 op)
+{
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ UINT32 src1 = IREG((op >> 8) & 31);
+ int dreg = (op >> 16) & 31;
+ ANDN(dreg, src1, src2);
+}
+
+void tms3203x_device::andn3_indind(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src1 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ int dreg = (op >> 16) & 31;
+ UPDATE_DEF();
+ ANDN(dreg, src1, src2);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ash3_regreg(UINT32 op)
+{
+ UINT32 src1 = IREG((op >> 8) & 31);
+ UINT32 src2 = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ ASH(dreg, src1, src2);
+}
+
+void tms3203x_device::ash3_indreg(UINT32 op)
+{
+ UINT32 src1 = RMEM(INDIRECT_1(op, op >> 8));
+ UINT32 src2 = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ ASH(dreg, src1, src2);
+}
+
+void tms3203x_device::ash3_regind(UINT32 op)
+{
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ UINT32 src1 = IREG((op >> 8) & 31);
+ int dreg = (op >> 16) & 31;
+ ASH(dreg, src1, src2);
+}
+
+void tms3203x_device::ash3_indind(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src1 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ int dreg = (op >> 16) & 31;
+ UPDATE_DEF();
+ ASH(dreg, src1, src2);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::cmpf3_regreg(UINT32 op)
+{
+ int sreg1 = (op >> 8) & 7;
+ int sreg2 = op & 7;
+ subf(m_r[TMR_TEMP1], m_r[sreg1], m_r[sreg2]);
+}
+
+void tms3203x_device::cmpf3_indreg(UINT32 op)
+{
+ UINT32 src1 = RMEM(INDIRECT_1(op, op >> 8));
+ int sreg2 = op & 7;
+ LONG2FP(TMR_TEMP1, src1);
+ subf(m_r[TMR_TEMP1], m_r[TMR_TEMP1], m_r[sreg2]);
+}
+
+void tms3203x_device::cmpf3_regind(UINT32 op)
+{
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ int sreg1 = (op >> 8) & 7;
+ LONG2FP(TMR_TEMP2, src2);
+ subf(m_r[TMR_TEMP1], m_r[sreg1], m_r[TMR_TEMP2]);
+}
+
+void tms3203x_device::cmpf3_indind(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src1 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ UPDATE_DEF();
+ LONG2FP(TMR_TEMP1, src1);
+ LONG2FP(TMR_TEMP2, src2);
+ subf(m_r[TMR_TEMP1], m_r[TMR_TEMP1], m_r[TMR_TEMP2]);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::cmpi3_regreg(UINT32 op)
+{
+ UINT32 src1 = IREG((op >> 8) & 31);
+ UINT32 src2 = IREG(op & 31);
+ CMPI(src1, src2);
+}
+
+void tms3203x_device::cmpi3_indreg(UINT32 op)
+{
+ UINT32 src1 = RMEM(INDIRECT_1(op, op >> 8));
+ UINT32 src2 = IREG(op & 31);
+ CMPI(src1, src2);
+}
+
+void tms3203x_device::cmpi3_regind(UINT32 op)
+{
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ UINT32 src1 = IREG((op >> 8) & 31);
+ CMPI(src1, src2);
+}
+
+void tms3203x_device::cmpi3_indind(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src1 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ UPDATE_DEF();
+ CMPI(src1, src2);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::lsh3_regreg(UINT32 op)
+{
+ UINT32 src1 = IREG((op >> 8) & 31);
+ UINT32 src2 = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ LSH(dreg, src1, src2);
+}
+
+void tms3203x_device::lsh3_indreg(UINT32 op)
+{
+ UINT32 src1 = RMEM(INDIRECT_1(op, op >> 8));
+ UINT32 src2 = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ LSH(dreg, src1, src2);
+}
+
+void tms3203x_device::lsh3_regind(UINT32 op)
+{
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ UINT32 src1 = IREG((op >> 8) & 31);
+ int dreg = (op >> 16) & 31;
+ LSH(dreg, src1, src2);
+}
+
+void tms3203x_device::lsh3_indind(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src1 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ int dreg = (op >> 16) & 31;
+ UPDATE_DEF();
+ LSH(dreg, src1, src2);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::mpyf3_regreg(UINT32 op)
+{
+ int sreg1 = (op >> 8) & 7;
+ int sreg2 = op & 7;
+ int dreg = (op >> 16) & 7;
+ mpyf(m_r[dreg], m_r[sreg1], m_r[sreg2]);
+}
+
+void tms3203x_device::mpyf3_indreg(UINT32 op)
+{
+ UINT32 src1 = RMEM(INDIRECT_1(op, op >> 8));
+ int sreg2 = op & 7;
+ int dreg = (op >> 16) & 7;
+ LONG2FP(TMR_TEMP1, src1);
+ mpyf(m_r[dreg], m_r[TMR_TEMP1], m_r[sreg2]);
+}
+
+void tms3203x_device::mpyf3_regind(UINT32 op)
+{
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ int sreg1 = (op >> 8) & 7;
+ int dreg = (op >> 16) & 7;
+ LONG2FP(TMR_TEMP2, src2);
+ mpyf(m_r[dreg], m_r[sreg1], m_r[TMR_TEMP2]);
+}
+
+void tms3203x_device::mpyf3_indind(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src1 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ int dreg = (op >> 16) & 7;
+ UPDATE_DEF();
+ LONG2FP(TMR_TEMP1, src1);
+ LONG2FP(TMR_TEMP2, src2);
+ mpyf(m_r[dreg], m_r[TMR_TEMP1], m_r[TMR_TEMP2]);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::mpyi3_regreg(UINT32 op)
+{
+ UINT32 src1 = IREG((op >> 8) & 31);
+ UINT32 src2 = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ MPYI(dreg, src1, src2);
+}
+
+void tms3203x_device::mpyi3_indreg(UINT32 op)
+{
+ UINT32 src1 = RMEM(INDIRECT_1(op, op >> 8));
+ UINT32 src2 = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ MPYI(dreg, src1, src2);
+}
+
+void tms3203x_device::mpyi3_regind(UINT32 op)
+{
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ UINT32 src1 = IREG((op >> 8) & 31);
+ int dreg = (op >> 16) & 31;
+ MPYI(dreg, src1, src2);
+}
+
+void tms3203x_device::mpyi3_indind(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src1 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ int dreg = (op >> 16) & 31;
+ UPDATE_DEF();
+ MPYI(dreg, src1, src2);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::or3_regreg(UINT32 op)
+{
+ UINT32 src1 = IREG((op >> 8) & 31);
+ UINT32 src2 = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ OR(dreg, src1, src2);
+}
+
+void tms3203x_device::or3_indreg(UINT32 op)
+{
+ UINT32 src1 = RMEM(INDIRECT_1(op, op >> 8));
+ UINT32 src2 = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ OR(dreg, src1, src2);
+}
+
+void tms3203x_device::or3_regind(UINT32 op)
+{
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ UINT32 src1 = IREG((op >> 8) & 31);
+ int dreg = (op >> 16) & 31;
+ OR(dreg, src1, src2);
+}
+
+void tms3203x_device::or3_indind(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src1 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ int dreg = (op >> 16) & 31;
+ UPDATE_DEF();
+ OR(dreg, src1, src2);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::subb3_regreg(UINT32 op)
+{
+ UINT32 src1 = IREG((op >> 8) & 31);
+ UINT32 src2 = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ SUBB(dreg, src1, src2);
+}
+
+void tms3203x_device::subb3_indreg(UINT32 op)
+{
+ UINT32 src1 = RMEM(INDIRECT_1(op, op >> 8));
+ UINT32 src2 = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ SUBB(dreg, src1, src2);
+}
+
+void tms3203x_device::subb3_regind(UINT32 op)
+{
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ UINT32 src1 = IREG((op >> 8) & 31);
+ int dreg = (op >> 16) & 31;
+ SUBB(dreg, src1, src2);
+}
+
+void tms3203x_device::subb3_indind(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src1 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ int dreg = (op >> 16) & 31;
+ UPDATE_DEF();
+ SUBB(dreg, src1, src2);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::subf3_regreg(UINT32 op)
+{
+ int sreg1 = (op >> 8) & 7;
+ int sreg2 = op & 7;
+ int dreg = (op >> 16) & 7;
+ subf(m_r[dreg], m_r[sreg1], m_r[sreg2]);
+}
+
+void tms3203x_device::subf3_indreg(UINT32 op)
+{
+ UINT32 src1 = RMEM(INDIRECT_1(op, op >> 8));
+ int sreg2 = op & 7;
+ int dreg = (op >> 16) & 7;
+ LONG2FP(TMR_TEMP1, src1);
+ subf(m_r[dreg], m_r[TMR_TEMP1], m_r[sreg2]);
+}
+
+void tms3203x_device::subf3_regind(UINT32 op)
+{
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ int sreg1 = (op >> 8) & 7;
+ int dreg = (op >> 16) & 7;
+ LONG2FP(TMR_TEMP2, src2);
+ subf(m_r[dreg], m_r[sreg1], m_r[TMR_TEMP2]);
+}
+
+void tms3203x_device::subf3_indind(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src1 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ int dreg = (op >> 16) & 7;
+ UPDATE_DEF();
+ LONG2FP(TMR_TEMP1, src1);
+ LONG2FP(TMR_TEMP2, src2);
+ subf(m_r[dreg], m_r[TMR_TEMP1], m_r[TMR_TEMP2]);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::subi3_regreg(UINT32 op)
+{
+ UINT32 src1 = IREG((op >> 8) & 31);
+ UINT32 src2 = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ SUBI(dreg, src1, src2);
+}
+
+void tms3203x_device::subi3_indreg(UINT32 op)
+{
+ UINT32 src1 = RMEM(INDIRECT_1(op, op >> 8));
+ UINT32 src2 = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ SUBI(dreg, src1, src2);
+}
+
+void tms3203x_device::subi3_regind(UINT32 op)
+{
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ UINT32 src1 = IREG((op >> 8) & 31);
+ int dreg = (op >> 16) & 31;
+ SUBI(dreg, src1, src2);
+}
+
+void tms3203x_device::subi3_indind(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src1 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ int dreg = (op >> 16) & 31;
+ UPDATE_DEF();
+ SUBI(dreg, src1, src2);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::tstb3_regreg(UINT32 op)
+{
+ UINT32 src1 = IREG((op >> 8) & 31);
+ UINT32 src2 = IREG(op & 31);
+ TSTB(src1, src2);
+}
+
+void tms3203x_device::tstb3_indreg(UINT32 op)
+{
+ UINT32 src1 = RMEM(INDIRECT_1(op, op >> 8));
+ UINT32 src2 = IREG(op & 31);
+ TSTB(src1, src2);
+}
+
+void tms3203x_device::tstb3_regind(UINT32 op)
+{
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ UINT32 src1 = IREG((op >> 8) & 31);
+ TSTB(src1, src2);
+}
+
+void tms3203x_device::tstb3_indind(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src1 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ UPDATE_DEF();
+ TSTB(src1, src2);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::xor3_regreg(UINT32 op)
+{
+ UINT32 src1 = IREG((op >> 8) & 31);
+ UINT32 src2 = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ XOR(dreg, src1, src2);
+}
+
+void tms3203x_device::xor3_indreg(UINT32 op)
+{
+ UINT32 src1 = RMEM(INDIRECT_1(op, op >> 8));
+ UINT32 src2 = IREG(op & 31);
+ int dreg = (op >> 16) & 31;
+ XOR(dreg, src1, src2);
+}
+
+void tms3203x_device::xor3_regind(UINT32 op)
+{
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ UINT32 src1 = IREG((op >> 8) & 31);
+ int dreg = (op >> 16) & 31;
+ XOR(dreg, src1, src2);
+}
+
+void tms3203x_device::xor3_indind(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src1 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src2 = RMEM(INDIRECT_1(op, op));
+ int dreg = (op >> 16) & 31;
+ UPDATE_DEF();
+ XOR(dreg, src1, src2);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldfu_reg(UINT32 op)
+{
+ m_r[(op >> 16) & 7] = m_r[op & 7];
+}
+
+void tms3203x_device::ldfu_dir(UINT32 op)
+{
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+}
+
+void tms3203x_device::ldfu_ind(UINT32 op)
+{
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+}
+
+void tms3203x_device::ldfu_imm(UINT32 op)
+{
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(dreg, op);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldflo_reg(UINT32 op)
+{
+ if (CONDITION_LO())
+ m_r[(op >> 16) & 7] = m_r[op & 7];
+}
+
+void tms3203x_device::ldflo_dir(UINT32 op)
+{
+ if (CONDITION_LO())
+ {
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+}
+
+void tms3203x_device::ldflo_ind(UINT32 op)
+{
+ if (CONDITION_LO())
+ {
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+ else
+ INDIRECT_D(op, op >> 8);
+}
+
+void tms3203x_device::ldflo_imm(UINT32 op)
+{
+ if (CONDITION_LO())
+ {
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(dreg, op);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldfls_reg(UINT32 op)
+{
+ if (CONDITION_LS())
+ m_r[(op >> 16) & 7] = m_r[op & 7];
+}
+
+void tms3203x_device::ldfls_dir(UINT32 op)
+{
+ if (CONDITION_LS())
+ {
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+}
+
+void tms3203x_device::ldfls_ind(UINT32 op)
+{
+ if (CONDITION_LS())
+ {
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+ else
+ INDIRECT_D(op, op >> 8);
+}
+
+void tms3203x_device::ldfls_imm(UINT32 op)
+{
+ if (CONDITION_LS())
+ {
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(dreg, op);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldfhi_reg(UINT32 op)
+{
+ if (CONDITION_HI())
+ m_r[(op >> 16) & 7] = m_r[op & 7];
+}
+
+void tms3203x_device::ldfhi_dir(UINT32 op)
+{
+ if (CONDITION_HI())
+ {
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+}
+
+void tms3203x_device::ldfhi_ind(UINT32 op)
+{
+ if (CONDITION_HI())
+ {
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+ else
+ INDIRECT_D(op, op >> 8);
+}
+
+void tms3203x_device::ldfhi_imm(UINT32 op)
+{
+ if (CONDITION_HI())
+ {
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(dreg, op);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldfhs_reg(UINT32 op)
+{
+ if (CONDITION_HS())
+ m_r[(op >> 16) & 7] = m_r[op & 7];
+}
+
+void tms3203x_device::ldfhs_dir(UINT32 op)
+{
+ if (CONDITION_HS())
+ {
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+}
+
+void tms3203x_device::ldfhs_ind(UINT32 op)
+{
+ if (CONDITION_HS())
+ {
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+ else
+ INDIRECT_D(op, op >> 8);
+}
+
+void tms3203x_device::ldfhs_imm(UINT32 op)
+{
+ if (CONDITION_HS())
+ {
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(dreg, op);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldfeq_reg(UINT32 op)
+{
+ if (CONDITION_EQ())
+ m_r[(op >> 16) & 7] = m_r[op & 7];
+}
+
+void tms3203x_device::ldfeq_dir(UINT32 op)
+{
+ if (CONDITION_EQ())
+ {
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+}
+
+void tms3203x_device::ldfeq_ind(UINT32 op)
+{
+ if (CONDITION_EQ())
+ {
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+ else
+ INDIRECT_D(op, op >> 8);
+}
+
+void tms3203x_device::ldfeq_imm(UINT32 op)
+{
+ if (CONDITION_EQ())
+ {
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(dreg, op);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldfne_reg(UINT32 op)
+{
+ if (CONDITION_NE())
+ m_r[(op >> 16) & 7] = m_r[op & 7];
+}
+
+void tms3203x_device::ldfne_dir(UINT32 op)
+{
+ if (CONDITION_NE())
+ {
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+}
+
+void tms3203x_device::ldfne_ind(UINT32 op)
+{
+ if (CONDITION_NE())
+ {
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+ else
+ INDIRECT_D(op, op >> 8);
+}
+
+void tms3203x_device::ldfne_imm(UINT32 op)
+{
+ if (CONDITION_NE())
+ {
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(dreg, op);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldflt_reg(UINT32 op)
+{
+ if (CONDITION_LT())
+ m_r[(op >> 16) & 7] = m_r[op & 7];
+}
+
+void tms3203x_device::ldflt_dir(UINT32 op)
+{
+ if (CONDITION_LT())
+ {
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+}
+
+void tms3203x_device::ldflt_ind(UINT32 op)
+{
+ if (CONDITION_LT())
+ {
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+ else
+ INDIRECT_D(op, op >> 8);
+}
+
+void tms3203x_device::ldflt_imm(UINT32 op)
+{
+ if (CONDITION_LT())
+ {
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(dreg, op);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldfle_reg(UINT32 op)
+{
+ if (CONDITION_LE())
+ m_r[(op >> 16) & 7] = m_r[op & 7];
+}
+
+void tms3203x_device::ldfle_dir(UINT32 op)
+{
+ if (CONDITION_LE())
+ {
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+}
+
+void tms3203x_device::ldfle_ind(UINT32 op)
+{
+ if (CONDITION_LE())
+ {
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+ else
+ INDIRECT_D(op, op >> 8);
+}
+
+void tms3203x_device::ldfle_imm(UINT32 op)
+{
+ if (CONDITION_LE())
+ {
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(dreg, op);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldfgt_reg(UINT32 op)
+{
+ if (CONDITION_GT())
+ m_r[(op >> 16) & 7] = m_r[op & 7];
+}
+
+void tms3203x_device::ldfgt_dir(UINT32 op)
+{
+ if (CONDITION_GT())
+ {
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+}
+
+void tms3203x_device::ldfgt_ind(UINT32 op)
+{
+ if (CONDITION_GT())
+ {
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+ else
+ INDIRECT_D(op, op >> 8);
+}
+
+void tms3203x_device::ldfgt_imm(UINT32 op)
+{
+ if (CONDITION_GT())
+ {
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(dreg, op);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldfge_reg(UINT32 op)
+{
+ if (CONDITION_GE())
+ m_r[(op >> 16) & 7] = m_r[op & 7];
+}
+
+void tms3203x_device::ldfge_dir(UINT32 op)
+{
+ if (CONDITION_GE())
+ {
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+}
+
+void tms3203x_device::ldfge_ind(UINT32 op)
+{
+ if (CONDITION_GE())
+ {
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+ else
+ INDIRECT_D(op, op >> 8);
+}
+
+void tms3203x_device::ldfge_imm(UINT32 op)
+{
+ if (CONDITION_GE())
+ {
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(dreg, op);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldfnv_reg(UINT32 op)
+{
+ if (CONDITION_NV())
+ m_r[(op >> 16) & 7] = m_r[op & 7];
+}
+
+void tms3203x_device::ldfnv_dir(UINT32 op)
+{
+ if (CONDITION_NV())
+ {
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+}
+
+void tms3203x_device::ldfnv_ind(UINT32 op)
+{
+ if (CONDITION_NV())
+ {
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+ else
+ INDIRECT_D(op, op >> 8);
+}
+
+void tms3203x_device::ldfnv_imm(UINT32 op)
+{
+ if (CONDITION_NV())
+ {
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(dreg, op);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldfv_reg(UINT32 op)
+{
+ if (CONDITION_V())
+ m_r[(op >> 16) & 7] = m_r[op & 7];
+}
+
+void tms3203x_device::ldfv_dir(UINT32 op)
+{
+ if (CONDITION_V())
+ {
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+}
+
+void tms3203x_device::ldfv_ind(UINT32 op)
+{
+ if (CONDITION_V())
+ {
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+ else
+ INDIRECT_D(op, op >> 8);
+}
+
+void tms3203x_device::ldfv_imm(UINT32 op)
+{
+ if (CONDITION_V())
+ {
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(dreg, op);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldfnuf_reg(UINT32 op)
+{
+ if (CONDITION_NUF())
+ m_r[(op >> 16) & 7] = m_r[op & 7];
+}
+
+void tms3203x_device::ldfnuf_dir(UINT32 op)
+{
+ if (CONDITION_NUF())
+ {
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+}
+
+void tms3203x_device::ldfnuf_ind(UINT32 op)
+{
+ if (CONDITION_NUF())
+ {
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+ else
+ INDIRECT_D(op, op >> 8);
+}
+
+void tms3203x_device::ldfnuf_imm(UINT32 op)
+{
+ if (CONDITION_NUF())
+ {
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(dreg, op);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldfuf_reg(UINT32 op)
+{
+ if (CONDITION_UF())
+ m_r[(op >> 16) & 7] = m_r[op & 7];
+}
+
+void tms3203x_device::ldfuf_dir(UINT32 op)
+{
+ if (CONDITION_UF())
+ {
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+}
+
+void tms3203x_device::ldfuf_ind(UINT32 op)
+{
+ if (CONDITION_UF())
+ {
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+ else
+ INDIRECT_D(op, op >> 8);
+}
+
+void tms3203x_device::ldfuf_imm(UINT32 op)
+{
+ if (CONDITION_UF())
+ {
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(dreg, op);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldfnlv_reg(UINT32 op)
+{
+ if (CONDITION_NLV())
+ m_r[(op >> 16) & 7] = m_r[op & 7];
+}
+
+void tms3203x_device::ldfnlv_dir(UINT32 op)
+{
+ if (CONDITION_NLV())
+ {
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+}
+
+void tms3203x_device::ldfnlv_ind(UINT32 op)
+{
+ if (CONDITION_NLV())
+ {
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+ else
+ INDIRECT_D(op, op >> 8);
+}
+
+void tms3203x_device::ldfnlv_imm(UINT32 op)
+{
+ if (CONDITION_NLV())
+ {
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(dreg, op);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldflv_reg(UINT32 op)
+{
+ if (CONDITION_LV())
+ m_r[(op >> 16) & 7] = m_r[op & 7];
+}
+
+void tms3203x_device::ldflv_dir(UINT32 op)
+{
+ if (CONDITION_LV())
+ {
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+}
+
+void tms3203x_device::ldflv_ind(UINT32 op)
+{
+ if (CONDITION_LV())
+ {
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+ else
+ INDIRECT_D(op, op >> 8);
+}
+
+void tms3203x_device::ldflv_imm(UINT32 op)
+{
+ if (CONDITION_LV())
+ {
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(dreg, op);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldfnluf_reg(UINT32 op)
+{
+ if (CONDITION_NLUF())
+ m_r[(op >> 16) & 7] = m_r[op & 7];
+}
+
+void tms3203x_device::ldfnluf_dir(UINT32 op)
+{
+ if (CONDITION_NLUF())
+ {
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+}
+
+void tms3203x_device::ldfnluf_ind(UINT32 op)
+{
+ if (CONDITION_NLUF())
+ {
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+ else
+ INDIRECT_D(op, op >> 8);
+}
+
+void tms3203x_device::ldfnluf_imm(UINT32 op)
+{
+ if (CONDITION_NLUF())
+ {
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(dreg, op);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldfluf_reg(UINT32 op)
+{
+ if (CONDITION_LUF())
+ m_r[(op >> 16) & 7] = m_r[op & 7];
+}
+
+void tms3203x_device::ldfluf_dir(UINT32 op)
+{
+ if (CONDITION_LUF())
+ {
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+}
+
+void tms3203x_device::ldfluf_ind(UINT32 op)
+{
+ if (CONDITION_LUF())
+ {
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+ else
+ INDIRECT_D(op, op >> 8);
+}
+
+void tms3203x_device::ldfluf_imm(UINT32 op)
+{
+ if (CONDITION_LUF())
+ {
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(dreg, op);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldfzuf_reg(UINT32 op)
+{
+ if (CONDITION_ZUF())
+ m_r[(op >> 16) & 7] = m_r[op & 7];
+}
+
+void tms3203x_device::ldfzuf_dir(UINT32 op)
+{
+ if (CONDITION_ZUF())
+ {
+ UINT32 res = RMEM(DIRECT(op));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+}
+
+void tms3203x_device::ldfzuf_ind(UINT32 op)
+{
+ if (CONDITION_ZUF())
+ {
+ UINT32 res = RMEM(INDIRECT_D(op, op >> 8));
+ int dreg = (op >> 16) & 7;
+ LONG2FP(dreg, res);
+ }
+ else
+ INDIRECT_D(op, op >> 8);
+}
+
+void tms3203x_device::ldfzuf_imm(UINT32 op)
+{
+ if (CONDITION_ZUF())
+ {
+ int dreg = (op >> 16) & 7;
+ SHORT2FP(dreg, op);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldiu_reg(UINT32 op)
+{
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = IREG(op & 31);
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+}
+
+void tms3203x_device::ldiu_dir(UINT32 op)
+{
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = RMEM(DIRECT(op));
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+}
+
+void tms3203x_device::ldiu_ind(UINT32 op)
+{
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = RMEM(INDIRECT_D(op, op >> 8));
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+}
+
+void tms3203x_device::ldiu_imm(UINT32 op)
+{
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = (INT16)op;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldilo_reg(UINT32 op)
+{
+ if (CONDITION_LO())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = IREG(op & 31);
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldilo_dir(UINT32 op)
+{
+ UINT32 val = RMEM(DIRECT(op));
+ if (CONDITION_LO())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldilo_ind(UINT32 op)
+{
+ UINT32 val = RMEM(INDIRECT_D(op, op >> 8));
+ if (CONDITION_LO())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldilo_imm(UINT32 op)
+{
+ if (CONDITION_LO())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = (INT16)op;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldils_reg(UINT32 op)
+{
+ if (CONDITION_LS())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = IREG(op & 31);
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldils_dir(UINT32 op)
+{
+ UINT32 val = RMEM(DIRECT(op));
+ if (CONDITION_LS())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldils_ind(UINT32 op)
+{
+ UINT32 val = RMEM(INDIRECT_D(op, op >> 8));
+ if (CONDITION_LS())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldils_imm(UINT32 op)
+{
+ if (CONDITION_LS())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = (INT16)op;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldihi_reg(UINT32 op)
+{
+ if (CONDITION_HI())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = IREG(op & 31);
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldihi_dir(UINT32 op)
+{
+ UINT32 val = RMEM(DIRECT(op));
+ if (CONDITION_HI())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldihi_ind(UINT32 op)
+{
+ UINT32 val = RMEM(INDIRECT_D(op, op >> 8));
+ if (CONDITION_HI())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldihi_imm(UINT32 op)
+{
+ if (CONDITION_HI())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = (INT16)op;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldihs_reg(UINT32 op)
+{
+ if (CONDITION_HS())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = IREG(op & 31);
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldihs_dir(UINT32 op)
+{
+ UINT32 val = RMEM(DIRECT(op));
+ if (CONDITION_HS())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldihs_ind(UINT32 op)
+{
+ UINT32 val = RMEM(INDIRECT_D(op, op >> 8));
+ if (CONDITION_HS())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldihs_imm(UINT32 op)
+{
+ if (CONDITION_HS())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = (INT16)op;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldieq_reg(UINT32 op)
+{
+ if (CONDITION_EQ())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = IREG(op & 31);
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldieq_dir(UINT32 op)
+{
+ UINT32 val = RMEM(DIRECT(op));
+ if (CONDITION_EQ())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldieq_ind(UINT32 op)
+{
+ UINT32 val = RMEM(INDIRECT_D(op, op >> 8));
+ if (CONDITION_EQ())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldieq_imm(UINT32 op)
+{
+ if (CONDITION_EQ())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = (INT16)op;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldine_reg(UINT32 op)
+{
+ if (CONDITION_NE())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = IREG(op & 31);
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldine_dir(UINT32 op)
+{
+ UINT32 val = RMEM(DIRECT(op));
+ if (CONDITION_NE())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldine_ind(UINT32 op)
+{
+ UINT32 val = RMEM(INDIRECT_D(op, op >> 8));
+ if (CONDITION_NE())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldine_imm(UINT32 op)
+{
+ if (CONDITION_NE())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = (INT16)op;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldilt_reg(UINT32 op)
+{
+ if (CONDITION_LT())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = IREG(op & 31);
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldilt_dir(UINT32 op)
+{
+ UINT32 val = RMEM(DIRECT(op));
+ if (CONDITION_LT())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldilt_ind(UINT32 op)
+{
+ UINT32 val = RMEM(INDIRECT_D(op, op >> 8));
+ if (CONDITION_LT())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldilt_imm(UINT32 op)
+{
+ if (CONDITION_LT())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = (INT16)op;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldile_reg(UINT32 op)
+{
+ if (CONDITION_LE())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = IREG(op & 31);
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldile_dir(UINT32 op)
+{
+ UINT32 val = RMEM(DIRECT(op));
+ if (CONDITION_LE())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldile_ind(UINT32 op)
+{
+ UINT32 val = RMEM(INDIRECT_D(op, op >> 8));
+ if (CONDITION_LE())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldile_imm(UINT32 op)
+{
+ if (CONDITION_LE())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = (INT16)op;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldigt_reg(UINT32 op)
+{
+ if (CONDITION_GT())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = IREG(op & 31);
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldigt_dir(UINT32 op)
+{
+ UINT32 val = RMEM(DIRECT(op));
+ if (CONDITION_GT())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldigt_ind(UINT32 op)
+{
+ UINT32 val = RMEM(INDIRECT_D(op, op >> 8));
+ if (CONDITION_GT())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldigt_imm(UINT32 op)
+{
+ if (CONDITION_GT())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = (INT16)op;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldige_reg(UINT32 op)
+{
+ if (CONDITION_GE())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = IREG(op & 31);
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldige_dir(UINT32 op)
+{
+ UINT32 val = RMEM(DIRECT(op));
+ if (CONDITION_GE())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldige_ind(UINT32 op)
+{
+ UINT32 val = RMEM(INDIRECT_D(op, op >> 8));
+ if (CONDITION_GE())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldige_imm(UINT32 op)
+{
+ if (CONDITION_GE())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = (INT16)op;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldinv_reg(UINT32 op)
+{
+ if (CONDITION_NV())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = IREG(op & 31);
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldinv_dir(UINT32 op)
+{
+ UINT32 val = RMEM(DIRECT(op));
+ if (CONDITION_NV())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldinv_ind(UINT32 op)
+{
+ UINT32 val = RMEM(INDIRECT_D(op, op >> 8));
+ if (CONDITION_NV())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldinv_imm(UINT32 op)
+{
+ if (CONDITION_NV())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = (INT16)op;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldiuf_reg(UINT32 op)
+{
+ if (CONDITION_UF())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = IREG(op & 31);
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldiuf_dir(UINT32 op)
+{
+ UINT32 val = RMEM(DIRECT(op));
+ if (CONDITION_UF())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldiuf_ind(UINT32 op)
+{
+ UINT32 val = RMEM(INDIRECT_D(op, op >> 8));
+ if (CONDITION_UF())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldiuf_imm(UINT32 op)
+{
+ if (CONDITION_UF())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = (INT16)op;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldinuf_reg(UINT32 op)
+{
+ if (CONDITION_NUF())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = IREG(op & 31);
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldinuf_dir(UINT32 op)
+{
+ UINT32 val = RMEM(DIRECT(op));
+ if (CONDITION_NUF())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldinuf_ind(UINT32 op)
+{
+ UINT32 val = RMEM(INDIRECT_D(op, op >> 8));
+ if (CONDITION_NUF())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldinuf_imm(UINT32 op)
+{
+ if (CONDITION_NUF())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = (INT16)op;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldiv_reg(UINT32 op)
+{
+ if (CONDITION_V())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = IREG(op & 31);
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldiv_dir(UINT32 op)
+{
+ UINT32 val = RMEM(DIRECT(op));
+ if (CONDITION_V())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldiv_ind(UINT32 op)
+{
+ UINT32 val = RMEM(INDIRECT_D(op, op >> 8));
+ if (CONDITION_V())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldiv_imm(UINT32 op)
+{
+ if (CONDITION_V())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = (INT16)op;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldinlv_reg(UINT32 op)
+{
+ if (CONDITION_NLV())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = IREG(op & 31);
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldinlv_dir(UINT32 op)
+{
+ UINT32 val = RMEM(DIRECT(op));
+ if (CONDITION_NLV())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldinlv_ind(UINT32 op)
+{
+ UINT32 val = RMEM(INDIRECT_D(op, op >> 8));
+ if (CONDITION_NLV())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldinlv_imm(UINT32 op)
+{
+ if (CONDITION_NLV())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = (INT16)op;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldilv_reg(UINT32 op)
+{
+ if (CONDITION_LV())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = IREG(op & 31);
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldilv_dir(UINT32 op)
+{
+ UINT32 val = RMEM(DIRECT(op));
+ if (CONDITION_LV())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldilv_ind(UINT32 op)
+{
+ UINT32 val = RMEM(INDIRECT_D(op, op >> 8));
+ if (CONDITION_LV())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldilv_imm(UINT32 op)
+{
+ if (CONDITION_LV())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = (INT16)op;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldinluf_reg(UINT32 op)
+{
+ if (CONDITION_NLUF())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = IREG(op & 31);
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldinluf_dir(UINT32 op)
+{
+ UINT32 val = RMEM(DIRECT(op));
+ if (CONDITION_NLUF())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldinluf_ind(UINT32 op)
+{
+ UINT32 val = RMEM(INDIRECT_D(op, op >> 8));
+ if (CONDITION_NLUF())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldinluf_imm(UINT32 op)
+{
+ if (CONDITION_NLUF())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = (INT16)op;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldiluf_reg(UINT32 op)
+{
+ if (CONDITION_LUF())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = IREG(op & 31);
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldiluf_dir(UINT32 op)
+{
+ UINT32 val = RMEM(DIRECT(op));
+ if (CONDITION_LUF())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldiluf_ind(UINT32 op)
+{
+ UINT32 val = RMEM(INDIRECT_D(op, op >> 8));
+ if (CONDITION_LUF())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldiluf_imm(UINT32 op)
+{
+ if (CONDITION_LUF())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = (INT16)op;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldizuf_reg(UINT32 op)
+{
+ if (CONDITION_ZUF())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = IREG(op & 31);
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldizuf_dir(UINT32 op)
+{
+ UINT32 val = RMEM(DIRECT(op));
+ if (CONDITION_ZUF())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldizuf_ind(UINT32 op)
+{
+ UINT32 val = RMEM(INDIRECT_D(op, op >> 8));
+ if (CONDITION_ZUF())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = val;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+void tms3203x_device::ldizuf_imm(UINT32 op)
+{
+ if (CONDITION_ZUF())
+ {
+ int dreg = (op >> 16) & 31;
+ IREG(dreg) = (INT16)op;
+ if (dreg >= TMR_BK)
+ update_special(dreg);
+ }
+}
+
+/*-----------------------------------------------------*/
+
+inline void tms3203x_device::execute_delayed(UINT32 newpc)
+{
+ m_delayed = true;
+
+ if ((machine().debug_flags & DEBUG_FLAG_ENABLED) == 0)
+ {
+ execute_one();
+ execute_one();
+ execute_one();
+ }
+ else
+ {
+ debugger_instruction_hook(this, m_pc);
+ execute_one();
+ debugger_instruction_hook(this, m_pc);
+ execute_one();
+ debugger_instruction_hook(this, m_pc);
+ execute_one();
+ }
+
+ if (newpc != ~0)
+ m_pc = newpc;
+
+ m_delayed = false;
+ if (m_irq_pending)
+ {
+ m_irq_pending = false;
+ check_irqs();
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::br_imm(UINT32 op)
+{
+ m_pc = op & 0xffffff;
+ m_icount -= 3*2;
+}
+
+void tms3203x_device::brd_imm(UINT32 op)
+{
+ execute_delayed(op & 0xffffff);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::call_imm(UINT32 op)
+{
+ WMEM(++IREG(TMR_SP), m_pc);
+ m_pc = op & 0xffffff;
+ m_icount -= 3*2;
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::rptb_imm(UINT32 op)
+{
+ IREG(TMR_RS) = m_pc;
+ IREG(TMR_RE) = op & 0xffffff;
+ IREG(TMR_ST) |= RMFLAG;
+ m_icount -= 3*2;
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::swi(UINT32 op) { unimplemented(op); }
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::brc_reg(UINT32 op)
+{
+ if (condition(op >> 16))
+ {
+ m_pc = IREG(op & 31);
+ m_icount -= 3*2;
+ }
+}
+
+void tms3203x_device::brcd_reg(UINT32 op)
+{
+ if (condition(op >> 16))
+ execute_delayed(IREG(op & 31));
+ else
+ execute_delayed(~0);
+}
+
+void tms3203x_device::brc_imm(UINT32 op)
+{
+ if (condition(op >> 16))
+ {
+ m_pc += (INT16)op;
+ m_icount -= 3*2;
+ }
+}
+
+void tms3203x_device::brcd_imm(UINT32 op)
+{
+ if (condition(op >> 16))
+ execute_delayed(m_pc + 2 + (INT16)op);
+ else
+ execute_delayed(~0);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::dbc_reg(UINT32 op)
+{
+ int reg = TMR_AR0 + ((op >> 22) & 7);
+ int res = (IREG(reg) - 1) & 0xffffff;
+ IREG(reg) = res | (IREG(reg) & 0xff000000);
+ if (condition(op >> 16) && !(res & 0x800000))
+ {
+ m_pc = IREG(op & 31);
+ m_icount -= 3*2;
+ }
+}
+
+void tms3203x_device::dbcd_reg(UINT32 op)
+{
+ int reg = TMR_AR0 + ((op >> 22) & 7);
+ int res = (IREG(reg) - 1) & 0xffffff;
+ IREG(reg) = res | (IREG(reg) & 0xff000000);
+ if (condition(op >> 16) && !(res & 0x800000))
+ execute_delayed(IREG(op & 31));
+ else
+ execute_delayed(~0);
+}
+
+void tms3203x_device::dbc_imm(UINT32 op)
+{
+ int reg = TMR_AR0 + ((op >> 22) & 7);
+ int res = (IREG(reg) - 1) & 0xffffff;
+ IREG(reg) = res | (IREG(reg) & 0xff000000);
+ if (condition(op >> 16) && !(res & 0x800000))
+ {
+ m_pc += (INT16)op;
+ m_icount -= 3*2;
+ }
+}
+
+void tms3203x_device::dbcd_imm(UINT32 op)
+{
+ int reg = TMR_AR0 + ((op >> 22) & 7);
+ int res = (IREG(reg) - 1) & 0xffffff;
+ IREG(reg) = res | (IREG(reg) & 0xff000000);
+ if (condition(op >> 16) && !(res & 0x800000))
+ execute_delayed(m_pc + 2 + (INT16)op);
+ else
+ execute_delayed(~0);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::callc_reg(UINT32 op)
+{
+ if (condition(op >> 16))
+ {
+ WMEM(++IREG(TMR_SP), m_pc);
+ m_pc = IREG(op & 31);
+ m_icount -= 3*2;
+ }
+}
+
+void tms3203x_device::callc_imm(UINT32 op)
+{
+ if (condition(op >> 16))
+ {
+ WMEM(++IREG(TMR_SP), m_pc);
+ m_pc += (INT16)op;
+ m_icount -= 3*2;
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::trap(int trapnum)
+{
+ WMEM(++IREG(TMR_SP), m_pc);
+ IREG(TMR_ST) &= ~GIEFLAG;
+ if (m_chip_type == CHIP_TYPE_TMS32032)
+ m_pc = RMEM(((IREG(TMR_IF) >> 16) << 8) + trapnum);
+ else if (m_mcu_mode)
+ m_pc = 0x809fc0 + trapnum;
+ else
+ m_pc = RMEM(trapnum);
+ m_icount -= 4*2;
+}
+
+void tms3203x_device::trapc(UINT32 op)
+{
+ if (condition(op >> 16))
+ trap(op & 0x3f);
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::retic_reg(UINT32 op)
+{
+ if (condition(op >> 16))
+ {
+ m_pc = RMEM(IREG(TMR_SP)--);
+ IREG(TMR_ST) |= GIEFLAG;
+ m_icount -= 3*2;
+ check_irqs();
+ }
+}
+
+void tms3203x_device::retsc_reg(UINT32 op)
+{
+ if (condition(op >> 16))
+ {
+ m_pc = RMEM(IREG(TMR_SP)--);
+ m_icount -= 3*2;
+ }
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::mpyaddf_0(UINT32 op)
+{
+ // src3 * src4, src1 + src2
+ DECLARE_DEF;
+ UINT32 src3 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src4 = RMEM(INDIRECT_1(op, op));
+ LONG2FP(TMR_TEMP1, src3);
+ LONG2FP(TMR_TEMP2, src4);
+ mpyf(m_r[TMR_TEMP3], m_r[TMR_TEMP1], m_r[TMR_TEMP2]);
+ addf(m_r[((op >> 22) & 1) | 2], m_r[(op >> 19) & 7], m_r[(op >> 16) & 7]);
+ m_r[(op >> 23) & 1] = m_r[TMR_TEMP3];
+ UPDATE_DEF();
+}
+
+void tms3203x_device::mpyaddf_1(UINT32 op)
+{
+ // src3 * src1, src4 + src2
+ DECLARE_DEF;
+ UINT32 src3 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src4 = RMEM(INDIRECT_1(op, op));
+ LONG2FP(TMR_TEMP1, src3);
+ LONG2FP(TMR_TEMP2, src4);
+ mpyf(m_r[TMR_TEMP3], m_r[TMR_TEMP1], m_r[(op >> 19) & 7]);
+ addf(m_r[((op >> 22) & 1) | 2], m_r[TMR_TEMP2], m_r[(op >> 16) & 7]);
+ m_r[(op >> 23) & 1] = m_r[TMR_TEMP3];
+ UPDATE_DEF();
+}
+
+void tms3203x_device::mpyaddf_2(UINT32 op)
+{
+ // src1 * src2, src3 + src4
+ DECLARE_DEF;
+ UINT32 src3 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src4 = RMEM(INDIRECT_1(op, op));
+ LONG2FP(TMR_TEMP1, src3);
+ LONG2FP(TMR_TEMP2, src4);
+ mpyf(m_r[TMR_TEMP3], m_r[(op >> 19) & 7], m_r[(op >> 16) & 7]);
+ addf(m_r[((op >> 22) & 1) | 2], m_r[TMR_TEMP1], m_r[TMR_TEMP2]);
+ m_r[(op >> 23) & 1] = m_r[TMR_TEMP3];
+ UPDATE_DEF();
+}
+
+void tms3203x_device::mpyaddf_3(UINT32 op)
+{
+ // src3 * src1, src2 + src4
+ DECLARE_DEF;
+ UINT32 src3 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src4 = RMEM(INDIRECT_1(op, op));
+ LONG2FP(TMR_TEMP1, src3);
+ LONG2FP(TMR_TEMP2, src4);
+ mpyf(m_r[TMR_TEMP3], m_r[TMR_TEMP1], m_r[(op >> 19) & 7]);
+ addf(m_r[((op >> 22) & 1) | 2], m_r[(op >> 16) & 7], m_r[TMR_TEMP2]);
+ m_r[(op >> 23) & 1] = m_r[TMR_TEMP3];
+ UPDATE_DEF();
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::mpysubf_0(UINT32 op)
+{
+ // src3 * src4, src1 - src2
+ DECLARE_DEF;
+ UINT32 src3 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src4 = RMEM(INDIRECT_1(op, op));
+ LONG2FP(TMR_TEMP1, src3);
+ LONG2FP(TMR_TEMP2, src4);
+ mpyf(m_r[TMR_TEMP3], m_r[TMR_TEMP1], m_r[TMR_TEMP2]);
+ subf(m_r[((op >> 22) & 1) | 2], m_r[(op >> 19) & 7], m_r[(op >> 16) & 7]);
+ m_r[(op >> 23) & 1] = m_r[TMR_TEMP3];
+ UPDATE_DEF();
+}
+
+void tms3203x_device::mpysubf_1(UINT32 op)
+{
+ // src3 * src1, src4 - src2
+ DECLARE_DEF;
+ UINT32 src3 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src4 = RMEM(INDIRECT_1(op, op));
+ LONG2FP(TMR_TEMP1, src3);
+ LONG2FP(TMR_TEMP2, src4);
+ mpyf(m_r[TMR_TEMP3], m_r[TMR_TEMP1], m_r[(op >> 19) & 7]);
+ subf(m_r[((op >> 22) & 1) | 2], m_r[TMR_TEMP2], m_r[(op >> 16) & 7]);
+ m_r[(op >> 23) & 1] = m_r[TMR_TEMP3];
+ UPDATE_DEF();
+}
+
+void tms3203x_device::mpysubf_2(UINT32 op)
+{
+ // src1 * src2, src3 - src4
+ DECLARE_DEF;
+ UINT32 src3 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src4 = RMEM(INDIRECT_1(op, op));
+ LONG2FP(TMR_TEMP1, src3);
+ LONG2FP(TMR_TEMP2, src4);
+ mpyf(m_r[TMR_TEMP3], m_r[(op >> 19) & 7], m_r[(op >> 16) & 7]);
+ subf(m_r[((op >> 22) & 1) | 2], m_r[TMR_TEMP1], m_r[TMR_TEMP2]);
+ m_r[(op >> 23) & 1] = m_r[TMR_TEMP3];
+ UPDATE_DEF();
+}
+
+void tms3203x_device::mpysubf_3(UINT32 op)
+{
+ // src3 * src1, src2 - src4
+ DECLARE_DEF;
+ UINT32 src3 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src4 = RMEM(INDIRECT_1(op, op));
+ LONG2FP(TMR_TEMP1, src3);
+ LONG2FP(TMR_TEMP2, src4);
+ mpyf(m_r[TMR_TEMP3], m_r[TMR_TEMP1], m_r[(op >> 19) & 7]);
+ subf(m_r[((op >> 22) & 1) | 2], m_r[(op >> 16) & 7], m_r[TMR_TEMP2]);
+ m_r[(op >> 23) & 1] = m_r[TMR_TEMP3];
+ UPDATE_DEF();
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::mpyaddi_0(UINT32 op)
+{
+ // src3 * src4, src1 + src2
+ DECLARE_DEF;
+ UINT32 src1 = IREG((op >> 19) & 7);
+ UINT32 src2 = IREG((op >> 16) & 7);
+ UINT32 src3 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src4 = RMEM(INDIRECT_1(op, op));
+ INT64 mres = (INT64)((INT32)(src3 << 8) >> 8) * (INT64)((INT32)(src4 << 8) >> 8);
+ UINT32 ares = src1 + src2;
+
+ CLR_NZVUF();
+ if (OVM())
+ {
+ if (mres < -(INT64)0x80000000 || mres > (INT64)0x7fffffff)
+ mres = (mres < 0) ? 0x80000000 : 0x7fffffff;
+ if (OVERFLOW_ADD(src1,src2,ares))
+ ares = ((INT32)src1 < 0) ? 0x80000000 : 0x7fffffff;
+ }
+ IREG((op >> 23) & 1) = mres;
+ IREG(((op >> 22) & 1) | 2) = ares;
+ UPDATE_DEF();
+}
+
+void tms3203x_device::mpyaddi_1(UINT32 op)
+{
+ // src3 * src1, src4 + src2
+ DECLARE_DEF;
+ UINT32 src1 = IREG((op >> 19) & 7);
+ UINT32 src2 = IREG((op >> 16) & 7);
+ UINT32 src3 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src4 = RMEM(INDIRECT_1(op, op));
+ INT64 mres = (INT64)((INT32)(src3 << 8) >> 8) * (INT64)((INT32)(src1 << 8) >> 8);
+ UINT32 ares = src4 + src2;
+
+ CLR_NZVUF();
+ if (OVM())
+ {
+ if (mres < -(INT64)0x80000000 || mres > (INT64)0x7fffffff)
+ mres = (mres < 0) ? 0x80000000 : 0x7fffffff;
+ if (OVERFLOW_ADD(src4,src2,ares))
+ ares = ((INT32)src4 < 0) ? 0x80000000 : 0x7fffffff;
+ }
+ IREG((op >> 23) & 1) = mres;
+ IREG(((op >> 22) & 1) | 2) = ares;
+ UPDATE_DEF();
+}
+
+void tms3203x_device::mpyaddi_2(UINT32 op)
+{
+ // src1 * src2, src3 + src4
+ DECLARE_DEF;
+ UINT32 src1 = IREG((op >> 19) & 7);
+ UINT32 src2 = IREG((op >> 16) & 7);
+ UINT32 src3 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src4 = RMEM(INDIRECT_1(op, op));
+ INT64 mres = (INT64)((INT32)(src1 << 8) >> 8) * (INT64)((INT32)(src2 << 8) >> 8);
+ UINT32 ares = src3 + src4;
+
+ CLR_NZVUF();
+ if (OVM())
+ {
+ if (mres < -(INT64)0x80000000 || mres > (INT64)0x7fffffff)
+ mres = (mres < 0) ? 0x80000000 : 0x7fffffff;
+ if (OVERFLOW_ADD(src3,src4,ares))
+ ares = ((INT32)src3 < 0) ? 0x80000000 : 0x7fffffff;
+ }
+ IREG((op >> 23) & 1) = mres;
+ IREG(((op >> 22) & 1) | 2) = ares;
+ UPDATE_DEF();
+}
+
+void tms3203x_device::mpyaddi_3(UINT32 op)
+{
+ // src3 * src1, src2 + src4
+ DECLARE_DEF;
+ UINT32 src1 = IREG((op >> 19) & 7);
+ UINT32 src2 = IREG((op >> 16) & 7);
+ UINT32 src3 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src4 = RMEM(INDIRECT_1(op, op));
+ INT64 mres = (INT64)((INT32)(src3 << 8) >> 8) * (INT64)((INT32)(src1 << 8) >> 8);
+ UINT32 ares = src2 + src4;
+
+ CLR_NZVUF();
+ if (OVM())
+ {
+ if (mres < -(INT64)0x80000000 || mres > (INT64)0x7fffffff)
+ mres = (mres < 0) ? 0x80000000 : 0x7fffffff;
+ if (OVERFLOW_ADD(src2,src4,ares))
+ ares = ((INT32)src2 < 0) ? 0x80000000 : 0x7fffffff;
+ }
+ IREG((op >> 23) & 1) = mres;
+ IREG(((op >> 22) & 1) | 2) = ares;
+ UPDATE_DEF();
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::mpysubi_0(UINT32 op)
+{
+ // src3 * src4, src1 - src2
+ DECLARE_DEF;
+ UINT32 src1 = IREG((op >> 19) & 7);
+ UINT32 src2 = IREG((op >> 16) & 7);
+ UINT32 src3 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src4 = RMEM(INDIRECT_1(op, op));
+ INT64 mres = (INT64)((INT32)(src3 << 8) >> 8) * (INT64)((INT32)(src4 << 8) >> 8);
+ UINT32 ares = src1 - src2;
+
+ CLR_NZVUF();
+ if (OVM())
+ {
+ if (mres < -(INT64)0x80000000 || mres > (INT64)0x7fffffff)
+ mres = (mres < 0) ? 0x80000000 : 0x7fffffff;
+ if (OVERFLOW_SUB(src1,src2,ares))
+ ares = ((INT32)src1 < 0) ? 0x80000000 : 0x7fffffff;
+ }
+ IREG((op >> 23) & 1) = mres;
+ IREG(((op >> 22) & 1) | 2) = ares;
+ UPDATE_DEF();
+}
+
+void tms3203x_device::mpysubi_1(UINT32 op)
+{
+ // src3 * src1, src4 - src2
+ DECLARE_DEF;
+ UINT32 src1 = IREG((op >> 19) & 7);
+ UINT32 src2 = IREG((op >> 16) & 7);
+ UINT32 src3 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src4 = RMEM(INDIRECT_1(op, op));
+ INT64 mres = (INT64)((INT32)(src3 << 8) >> 8) * (INT64)((INT32)(src1 << 8) >> 8);
+ UINT32 ares = src4 - src2;
+
+ CLR_NZVUF();
+ if (OVM())
+ {
+ if (mres < -(INT64)0x80000000 || mres > (INT64)0x7fffffff)
+ mres = (mres < 0) ? 0x80000000 : 0x7fffffff;
+ if (OVERFLOW_SUB(src4,src2,ares))
+ ares = ((INT32)src4 < 0) ? 0x80000000 : 0x7fffffff;
+ }
+ IREG((op >> 23) & 1) = mres;
+ IREG(((op >> 22) & 1) | 2) = ares;
+ UPDATE_DEF();
+}
+
+void tms3203x_device::mpysubi_2(UINT32 op)
+{
+ // src1 * src2, src3 - src4
+ DECLARE_DEF;
+ UINT32 src1 = IREG((op >> 19) & 7);
+ UINT32 src2 = IREG((op >> 16) & 7);
+ UINT32 src3 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src4 = RMEM(INDIRECT_1(op, op));
+ INT64 mres = (INT64)((INT32)(src1 << 8) >> 8) * (INT64)((INT32)(src2 << 8) >> 8);
+ UINT32 ares = src3 - src4;
+
+ CLR_NZVUF();
+ if (OVM())
+ {
+ if (mres < -(INT64)0x80000000 || mres > (INT64)0x7fffffff)
+ mres = (mres < 0) ? 0x80000000 : 0x7fffffff;
+ if (OVERFLOW_SUB(src3,src4,ares))
+ ares = ((INT32)src3 < 0) ? 0x80000000 : 0x7fffffff;
+ }
+ IREG((op >> 23) & 1) = mres;
+ IREG(((op >> 22) & 1) | 2) = ares;
+ UPDATE_DEF();
+}
+
+void tms3203x_device::mpysubi_3(UINT32 op)
+{
+ // src3 * src1, src2 - src4
+ DECLARE_DEF;
+ UINT32 src1 = IREG((op >> 19) & 7);
+ UINT32 src2 = IREG((op >> 16) & 7);
+ UINT32 src3 = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ UINT32 src4 = RMEM(INDIRECT_1(op, op));
+ INT64 mres = (INT64)((INT32)(src3 << 8) >> 8) * (INT64)((INT32)(src1 << 8) >> 8);
+ UINT32 ares = src2 - src4;
+
+ CLR_NZVUF();
+ if (OVM())
+ {
+ if (mres < -(INT64)0x80000000 || mres > (INT64)0x7fffffff)
+ mres = (mres < 0) ? 0x80000000 : 0x7fffffff;
+ if (OVERFLOW_SUB(src2,src4,ares))
+ ares = ((INT32)src2 < 0) ? 0x80000000 : 0x7fffffff;
+ }
+ IREG((op >> 23) & 1) = mres;
+ IREG(((op >> 22) & 1) | 2) = ares;
+ UPDATE_DEF();
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::stfstf(UINT32 op)
+{
+ DECLARE_DEF;
+ WMEM(INDIRECT_1_DEF(op, op >> 8), FP2LONG((op >> 16) & 7));
+ WMEM(INDIRECT_1(op, op), FP2LONG((op >> 22) & 7));
+ UPDATE_DEF();
+}
+
+void tms3203x_device::stisti(UINT32 op)
+{
+ DECLARE_DEF;
+ WMEM(INDIRECT_1_DEF(op, op >> 8), IREG((op >> 16) & 7));
+ WMEM(INDIRECT_1(op, op), IREG((op >> 22) & 7));
+ UPDATE_DEF();
+}
+
+/*-----------------------------------------------------*/
+
+void tms3203x_device::ldfldf(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 res;
+ int dreg;
+
+ res = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ dreg = (op >> 19) & 7;
+ LONG2FP(dreg, res);
+ res = RMEM(INDIRECT_1(op, op));
+ dreg = (op >> 22) & 7;
+ LONG2FP(dreg, res);
+ UPDATE_DEF();
+}
+
+void tms3203x_device::ldildi(UINT32 op)
+{
+ DECLARE_DEF;
+ IREG((op >> 19) & 7) = RMEM(INDIRECT_1_DEF(op, op >> 8));
+ IREG((op >> 22) & 7) = RMEM(INDIRECT_1(op, op));
+ UPDATE_DEF();
+}
+
+/*-----------------------------------------------------*/
+
+// src2 = ind(op)
+// dst2 = ind(op >> 8)
+// sreg3 = ((op >> 16) & 7)
+// sreg1 = ((op >> 19) & 7)
+// dreg1 = ((op >> 22) & 7)
+
+void tms3203x_device::absfstf(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src3 = FP2LONG((op >> 16) & 7);
+ UINT32 src2 = RMEM(INDIRECT_1_DEF(op, op));
+ {
+ int dreg = (op >> 22) & 7;
+ LONG2FP(TMR_TEMP1, src2);
+ ABSF(dreg, TMR_TEMP1);
+ }
+ WMEM(INDIRECT_1(op, op >> 8), src3);
+ UPDATE_DEF();
+}
+
+void tms3203x_device::absisti(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src3 = IREG((op >> 16) & 7);
+ UINT32 src2 = RMEM(INDIRECT_1_DEF(op, op));
+ {
+ int dreg = (op >> 22) & 7;
+ ABSI(dreg, src2);
+ }
+ WMEM(INDIRECT_1(op, op >> 8), src3);
+ UPDATE_DEF();
+}
+
+void tms3203x_device::addf3stf(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src3 = FP2LONG((op >> 16) & 7);
+ UINT32 src2 = RMEM(INDIRECT_1_DEF(op, op));
+ {
+ LONG2FP(TMR_TEMP1, src2);
+ addf(m_r[(op >> 22) & 7], m_r[(op >> 19) & 7], m_r[TMR_TEMP1]);
+ }
+ WMEM(INDIRECT_1(op, op >> 8), src3);
+ UPDATE_DEF();
+}
+
+void tms3203x_device::addi3sti(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src3 = IREG((op >> 16) & 7);
+ UINT32 src2 = RMEM(INDIRECT_1_DEF(op, op));
+ {
+ int dreg = (op >> 22) & 7;
+ UINT32 src1 = IREG((op >> 19) & 7);
+ ADDI(dreg, src1, src2);
+ }
+ WMEM(INDIRECT_1(op, op >> 8), src3);
+ UPDATE_DEF();
+}
+
+void tms3203x_device::and3sti(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src3 = IREG((op >> 16) & 7);
+ UINT32 src2 = RMEM(INDIRECT_1_DEF(op, op));
+ {
+ int dreg = (op >> 22) & 7;
+ UINT32 src1 = IREG((op >> 19) & 7);
+ AND(dreg, src1, src2);
+ }
+ WMEM(INDIRECT_1(op, op >> 8), src3);
+ UPDATE_DEF();
+}
+
+void tms3203x_device::ash3sti(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src3 = IREG((op >> 16) & 7);
+ UINT32 src2 = RMEM(INDIRECT_1_DEF(op, op));
+ {
+ int dreg = (op >> 22) & 7;
+ UINT32 count = IREG((op >> 19) & 7);
+ ASH(dreg, src2, count);
+ }
+ WMEM(INDIRECT_1(op, op >> 8), src3);
+ UPDATE_DEF();
+}
+
+void tms3203x_device::fixsti(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src3 = IREG((op >> 16) & 7);
+ UINT32 src2 = RMEM(INDIRECT_1_DEF(op, op));
+ {
+ int dreg = (op >> 22) & 7;
+ LONG2FP(dreg, src2);
+ float2int(m_r[dreg], 1);
+ }
+ WMEM(INDIRECT_1(op, op >> 8), src3);
+ UPDATE_DEF();
+}
+
+void tms3203x_device::floatstf(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src3 = FP2LONG((op >> 16) & 7);
+ UINT32 src2 = RMEM(INDIRECT_1_DEF(op, op));
+ {
+ int dreg = (op >> 22) & 7;
+ IREG(dreg) = src2;
+ int2float(m_r[dreg]);
+ }
+ WMEM(INDIRECT_1(op, op >> 8), src3);
+ UPDATE_DEF();
+}
+
+void tms3203x_device::ldfstf(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src3 = FP2LONG((op >> 16) & 7);
+ UINT32 src2 = RMEM(INDIRECT_1_DEF(op, op));
+ {
+ int dreg = (op >> 22) & 7;
+ LONG2FP(dreg, src2);
+ }
+ WMEM(INDIRECT_1(op, op >> 8), src3);
+ UPDATE_DEF();
+}
+
+void tms3203x_device::ldisti(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src3 = IREG((op >> 16) & 7);
+ UINT32 src2 = RMEM(INDIRECT_1_DEF(op, op));
+ IREG((op >> 22) & 7) = src2;
+ WMEM(INDIRECT_1(op, op >> 8), src3);
+ UPDATE_DEF();
+}
+
+void tms3203x_device::lsh3sti(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src3 = IREG((op >> 16) & 7);
+ UINT32 src2 = RMEM(INDIRECT_1_DEF(op, op));
+ {
+ int dreg = (op >> 22) & 7;
+ UINT32 count = IREG((op >> 19) & 7);
+ LSH(dreg, src2, count);
+ }
+ WMEM(INDIRECT_1(op, op >> 8), src3);
+ UPDATE_DEF();
+}
+
+void tms3203x_device::mpyf3stf(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src3 = FP2LONG((op >> 16) & 7);
+ UINT32 src2 = RMEM(INDIRECT_1_DEF(op, op));
+ {
+ LONG2FP(TMR_TEMP1, src2);
+ mpyf(m_r[(op >> 22) & 7], m_r[(op >> 19) & 7], m_r[TMR_TEMP1]);
+ }
+ WMEM(INDIRECT_1(op, op >> 8), src3);
+ UPDATE_DEF();
+}
+
+void tms3203x_device::mpyi3sti(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src3 = IREG((op >> 16) & 7);
+ UINT32 src2 = RMEM(INDIRECT_1_DEF(op, op));
+ {
+ int dreg = (op >> 22) & 7;
+ UINT32 src1 = IREG((op >> 19) & 7);
+ MPYI(dreg, src1, src2);
+ }
+ WMEM(INDIRECT_1(op, op >> 8), src3);
+ UPDATE_DEF();
+}
+
+void tms3203x_device::negfstf(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src3 = FP2LONG((op >> 16) & 7);
+ UINT32 src2 = RMEM(INDIRECT_1_DEF(op, op));
+ {
+ LONG2FP(TMR_TEMP1, src2);
+ negf(m_r[(op >> 22) & 7], m_r[TMR_TEMP1]);
+ }
+ WMEM(INDIRECT_1(op, op >> 8), src3);
+ UPDATE_DEF();
+}
+
+void tms3203x_device::negisti(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src3 = IREG((op >> 16) & 7);
+ UINT32 src2 = RMEM(INDIRECT_1_DEF(op, op));
+ {
+ int dreg = (op >> 22) & 7;
+ NEGI(dreg, src2);
+ }
+ WMEM(INDIRECT_1(op, op >> 8), src3);
+ UPDATE_DEF();
+}
+
+void tms3203x_device::notsti(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src3 = IREG((op >> 16) & 7);
+ UINT32 src2 = RMEM(INDIRECT_1_DEF(op, op));
+ {
+ int dreg = (op >> 22) & 7;
+ NOT(dreg, src2);
+ }
+ WMEM(INDIRECT_1(op, op >> 8), src3);
+ UPDATE_DEF();
+}
+
+void tms3203x_device::or3sti(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src3 = IREG((op >> 16) & 7);
+ UINT32 src2 = RMEM(INDIRECT_1_DEF(op, op));
+ {
+ int dreg = (op >> 22) & 7;
+ UINT32 src1 = IREG((op >> 19) & 7);
+ OR(dreg, src1, src2);
+ }
+ WMEM(INDIRECT_1(op, op >> 8), src3);
+ UPDATE_DEF();
+}
+
+void tms3203x_device::subf3stf(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src3 = FP2LONG((op >> 16) & 7);
+ UINT32 src2 = RMEM(INDIRECT_1_DEF(op, op));
+ {
+ LONG2FP(TMR_TEMP1, src2);
+ subf(m_r[(op >> 22) & 7], m_r[TMR_TEMP1], m_r[(op >> 19) & 7]);
+ }
+ WMEM(INDIRECT_1(op, op >> 8), src3);
+ UPDATE_DEF();
+}
+
+void tms3203x_device::subi3sti(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src3 = IREG((op >> 16) & 7);
+ UINT32 src2 = RMEM(INDIRECT_1_DEF(op, op));
+ {
+ int dreg = (op >> 22) & 7;
+ UINT32 src1 = IREG((op >> 19) & 7);
+ SUBI(dreg, src2, src1);
+ }
+ WMEM(INDIRECT_1(op, op >> 8), src3);
+ UPDATE_DEF();
+}
+
+void tms3203x_device::xor3sti(UINT32 op)
+{
+ DECLARE_DEF;
+ UINT32 src3 = IREG((op >> 16) & 7);
+ UINT32 src2 = RMEM(INDIRECT_1_DEF(op, op));
+ {
+ int dreg = (op >> 22) & 7;
+ UINT32 src1 = IREG((op >> 19) & 7);
+ XOR(dreg, src1, src2);
+ }
+ WMEM(INDIRECT_1(op, op >> 8), src3);
+ UPDATE_DEF();
+}
+
+
+//**************************************************************************
+// FUNCTION TABLE
+//**************************************************************************
+
+UINT32 (tms3203x_device::*const tms3203x_device::s_indirect_d[0x20])(UINT32, UINT8) =
+{
+ &tms3203x_device::mod00_d, &tms3203x_device::mod01_d, &tms3203x_device::mod02_d, &tms3203x_device::mod03_d,
+ &tms3203x_device::mod04_d, &tms3203x_device::mod05_d, &tms3203x_device::mod06_d, &tms3203x_device::mod07_d,
+ &tms3203x_device::mod08, &tms3203x_device::mod09, &tms3203x_device::mod0a, &tms3203x_device::mod0b,
+ &tms3203x_device::mod0c, &tms3203x_device::mod0d, &tms3203x_device::mod0e, &tms3203x_device::mod0f,
+ &tms3203x_device::mod10, &tms3203x_device::mod11, &tms3203x_device::mod12, &tms3203x_device::mod13,
+ &tms3203x_device::mod14, &tms3203x_device::mod15, &tms3203x_device::mod16, &tms3203x_device::mod17,
+ &tms3203x_device::mod18, &tms3203x_device::mod19, &tms3203x_device::modillegal, &tms3203x_device::modillegal,
+ &tms3203x_device::modillegal, &tms3203x_device::modillegal, &tms3203x_device::modillegal, &tms3203x_device::modillegal
+};
+
+
+UINT32 (tms3203x_device::*const tms3203x_device::s_indirect_1[0x20])(UINT32, UINT8) =
+{
+ &tms3203x_device::mod00_1, &tms3203x_device::mod01_1, &tms3203x_device::mod02_1, &tms3203x_device::mod03_1,
+ &tms3203x_device::mod04_1, &tms3203x_device::mod05_1, &tms3203x_device::mod06_1, &tms3203x_device::mod07_1,
+ &tms3203x_device::mod08, &tms3203x_device::mod09, &tms3203x_device::mod0a, &tms3203x_device::mod0b,
+ &tms3203x_device::mod0c, &tms3203x_device::mod0d, &tms3203x_device::mod0e, &tms3203x_device::mod0f,
+ &tms3203x_device::mod10, &tms3203x_device::mod11, &tms3203x_device::mod12, &tms3203x_device::mod13,
+ &tms3203x_device::mod14, &tms3203x_device::mod15, &tms3203x_device::mod16, &tms3203x_device::mod17,
+ &tms3203x_device::mod18, &tms3203x_device::mod19, &tms3203x_device::modillegal, &tms3203x_device::modillegal,
+ &tms3203x_device::modillegal, &tms3203x_device::modillegal, &tms3203x_device::modillegal, &tms3203x_device::modillegal
+};
+
+
+UINT32 (tms3203x_device::*const tms3203x_device::s_indirect_1_def[0x20])(UINT32, UINT8, UINT32 *&) =
+{
+ &tms3203x_device::mod00_1_def, &tms3203x_device::mod01_1_def, &tms3203x_device::mod02_1_def, &tms3203x_device::mod03_1_def,
+ &tms3203x_device::mod04_1_def, &tms3203x_device::mod05_1_def, &tms3203x_device::mod06_1_def, &tms3203x_device::mod07_1_def,
+ &tms3203x_device::mod08_def, &tms3203x_device::mod09_def, &tms3203x_device::mod0a_def, &tms3203x_device::mod0b_def,
+ &tms3203x_device::mod0c_def, &tms3203x_device::mod0d_def, &tms3203x_device::mod0e_def, &tms3203x_device::mod0f_def,
+ &tms3203x_device::mod10_def, &tms3203x_device::mod11_def, &tms3203x_device::mod12_def, &tms3203x_device::mod13_def,
+ &tms3203x_device::mod14_def, &tms3203x_device::mod15_def, &tms3203x_device::mod16_def, &tms3203x_device::mod17_def,
+ &tms3203x_device::mod18_def, &tms3203x_device::mod19_def, &tms3203x_device::modillegal_def,&tms3203x_device::modillegal_def,
+ &tms3203x_device::modillegal_def,&tms3203x_device::modillegal_def,&tms3203x_device::modillegal_def,&tms3203x_device::modillegal_def
+};
+
+void (tms3203x_device::*const tms3203x_device::s_tms32031ops[])(UINT32 op) =
+{
+ &tms3203x_device::absf_reg, &tms3203x_device::absf_dir, &tms3203x_device::absf_ind, &tms3203x_device::absf_imm, // 0x00
+ &tms3203x_device::absi_reg, &tms3203x_device::absi_dir, &tms3203x_device::absi_ind, &tms3203x_device::absi_imm,
+ &tms3203x_device::addc_reg, &tms3203x_device::addc_dir, &tms3203x_device::addc_ind, &tms3203x_device::addc_imm,
+ &tms3203x_device::addf_reg, &tms3203x_device::addf_dir, &tms3203x_device::addf_ind, &tms3203x_device::addf_imm,
+ &tms3203x_device::addi_reg, &tms3203x_device::addi_dir, &tms3203x_device::addi_ind, &tms3203x_device::addi_imm,
+ &tms3203x_device::and_reg, &tms3203x_device::and_dir, &tms3203x_device::and_ind, &tms3203x_device::and_imm,
+ &tms3203x_device::andn_reg, &tms3203x_device::andn_dir, &tms3203x_device::andn_ind, &tms3203x_device::andn_imm,
+ &tms3203x_device::ash_reg, &tms3203x_device::ash_dir, &tms3203x_device::ash_ind, &tms3203x_device::ash_imm,
+ &tms3203x_device::cmpf_reg, &tms3203x_device::cmpf_dir, &tms3203x_device::cmpf_ind, &tms3203x_device::cmpf_imm, // 0x08
+ &tms3203x_device::cmpi_reg, &tms3203x_device::cmpi_dir, &tms3203x_device::cmpi_ind, &tms3203x_device::cmpi_imm,
+ &tms3203x_device::fix_reg, &tms3203x_device::fix_dir, &tms3203x_device::fix_ind, &tms3203x_device::fix_imm,
+ &tms3203x_device::float_reg, &tms3203x_device::float_dir, &tms3203x_device::float_ind, &tms3203x_device::float_imm,
+ &tms3203x_device::idle, &tms3203x_device::idle, &tms3203x_device::idle, &tms3203x_device::idle,
+ &tms3203x_device::lde_reg, &tms3203x_device::lde_dir, &tms3203x_device::lde_ind, &tms3203x_device::lde_imm,
+ &tms3203x_device::ldf_reg, &tms3203x_device::ldf_dir, &tms3203x_device::ldf_ind, &tms3203x_device::ldf_imm,
+ &tms3203x_device::illegal, &tms3203x_device::ldfi_dir, &tms3203x_device::ldfi_ind, &tms3203x_device::illegal,
+ &tms3203x_device::ldi_reg, &tms3203x_device::ldi_dir, &tms3203x_device::ldi_ind, &tms3203x_device::ldi_imm, // 0x10
+ &tms3203x_device::illegal, &tms3203x_device::ldii_dir, &tms3203x_device::ldii_ind, &tms3203x_device::illegal,
+ &tms3203x_device::ldm_reg, &tms3203x_device::ldm_dir, &tms3203x_device::ldm_ind, &tms3203x_device::ldm_imm,
+ &tms3203x_device::lsh_reg, &tms3203x_device::lsh_dir, &tms3203x_device::lsh_ind, &tms3203x_device::lsh_imm,
+ &tms3203x_device::mpyf_reg, &tms3203x_device::mpyf_dir, &tms3203x_device::mpyf_ind, &tms3203x_device::mpyf_imm,
+ &tms3203x_device::mpyi_reg, &tms3203x_device::mpyi_dir, &tms3203x_device::mpyi_ind, &tms3203x_device::mpyi_imm,
+ &tms3203x_device::negb_reg, &tms3203x_device::negb_dir, &tms3203x_device::negb_ind, &tms3203x_device::negb_imm,
+ &tms3203x_device::negf_reg, &tms3203x_device::negf_dir, &tms3203x_device::negf_ind, &tms3203x_device::negf_imm,
+ &tms3203x_device::negi_reg, &tms3203x_device::negi_dir, &tms3203x_device::negi_ind, &tms3203x_device::negi_imm, // 0x18
+ &tms3203x_device::nop_reg, &tms3203x_device::illegal, &tms3203x_device::nop_ind, &tms3203x_device::illegal,
+ &tms3203x_device::norm_reg, &tms3203x_device::norm_dir, &tms3203x_device::norm_ind, &tms3203x_device::norm_imm,
+ &tms3203x_device::not_reg, &tms3203x_device::not_dir, &tms3203x_device::not_ind, &tms3203x_device::not_imm,
+ &tms3203x_device::illegal, &tms3203x_device::pop, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::popf, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::push, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::pushf, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::or_reg, &tms3203x_device::or_dir, &tms3203x_device::or_ind, &tms3203x_device::or_imm, // 0x20
+ &tms3203x_device::maxspeed, &tms3203x_device::maxspeed, &tms3203x_device::maxspeed, &tms3203x_device::maxspeed,
+ &tms3203x_device::rnd_reg, &tms3203x_device::rnd_dir, &tms3203x_device::rnd_ind, &tms3203x_device::rnd_imm,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::rol,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::rolc,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::ror,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::rorc,
+ &tms3203x_device::rtps_reg, &tms3203x_device::rtps_dir, &tms3203x_device::rtps_ind, &tms3203x_device::rtps_imm,
+ &tms3203x_device::illegal, &tms3203x_device::stf_dir, &tms3203x_device::stf_ind, &tms3203x_device::illegal, // 0x28
+ &tms3203x_device::illegal, &tms3203x_device::stfi_dir, &tms3203x_device::stfi_ind, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::sti_dir, &tms3203x_device::sti_ind, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::stii_dir, &tms3203x_device::stii_ind, &tms3203x_device::illegal,
+ &tms3203x_device::sigi, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::subb_reg, &tms3203x_device::subb_dir, &tms3203x_device::subb_ind, &tms3203x_device::subb_imm,
+ &tms3203x_device::subc_reg, &tms3203x_device::subc_dir, &tms3203x_device::subc_ind, &tms3203x_device::subc_imm,
+ &tms3203x_device::subf_reg, &tms3203x_device::subf_dir, &tms3203x_device::subf_ind, &tms3203x_device::subf_imm,
+ &tms3203x_device::subi_reg, &tms3203x_device::subi_dir, &tms3203x_device::subi_ind, &tms3203x_device::subi_imm, // 0x30
+ &tms3203x_device::subrb_reg, &tms3203x_device::subrb_dir, &tms3203x_device::subrb_ind, &tms3203x_device::subrb_imm,
+ &tms3203x_device::subrf_reg, &tms3203x_device::subrf_dir, &tms3203x_device::subrf_ind, &tms3203x_device::subrf_imm,
+ &tms3203x_device::subri_reg, &tms3203x_device::subri_dir, &tms3203x_device::subri_ind, &tms3203x_device::subri_imm,
+ &tms3203x_device::tstb_reg, &tms3203x_device::tstb_dir, &tms3203x_device::tstb_ind, &tms3203x_device::tstb_imm,
+ &tms3203x_device::xor_reg, &tms3203x_device::xor_dir, &tms3203x_device::xor_ind, &tms3203x_device::xor_imm,
+ &tms3203x_device::illegal, &tms3203x_device::iack_dir, &tms3203x_device::iack_ind, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0x38
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+
+ &tms3203x_device::addc3_regreg, &tms3203x_device::addc3_indreg, &tms3203x_device::addc3_regind, &tms3203x_device::addc3_indind, // 0x40
+ &tms3203x_device::addf3_regreg, &tms3203x_device::addf3_indreg, &tms3203x_device::addf3_regind, &tms3203x_device::addf3_indind,
+ &tms3203x_device::addi3_regreg, &tms3203x_device::addi3_indreg, &tms3203x_device::addi3_regind, &tms3203x_device::addi3_indind,
+ &tms3203x_device::and3_regreg, &tms3203x_device::and3_indreg, &tms3203x_device::and3_regind, &tms3203x_device::and3_indind,
+ &tms3203x_device::andn3_regreg, &tms3203x_device::andn3_indreg, &tms3203x_device::andn3_regind, &tms3203x_device::andn3_indind,
+ &tms3203x_device::ash3_regreg, &tms3203x_device::ash3_indreg, &tms3203x_device::ash3_regind, &tms3203x_device::ash3_indind,
+ &tms3203x_device::cmpf3_regreg, &tms3203x_device::cmpf3_indreg, &tms3203x_device::cmpf3_regind, &tms3203x_device::cmpf3_indind,
+ &tms3203x_device::cmpi3_regreg, &tms3203x_device::cmpi3_indreg, &tms3203x_device::cmpi3_regind, &tms3203x_device::cmpi3_indind,
+ &tms3203x_device::lsh3_regreg, &tms3203x_device::lsh3_indreg, &tms3203x_device::lsh3_regind, &tms3203x_device::lsh3_indind, // 0x48
+ &tms3203x_device::mpyf3_regreg, &tms3203x_device::mpyf3_indreg, &tms3203x_device::mpyf3_regind, &tms3203x_device::mpyf3_indind,
+ &tms3203x_device::mpyi3_regreg, &tms3203x_device::mpyi3_indreg, &tms3203x_device::mpyi3_regind, &tms3203x_device::mpyi3_indind,
+ &tms3203x_device::or3_regreg, &tms3203x_device::or3_indreg, &tms3203x_device::or3_regind, &tms3203x_device::or3_indind,
+ &tms3203x_device::subb3_regreg, &tms3203x_device::subb3_indreg, &tms3203x_device::subb3_regind, &tms3203x_device::subb3_indind,
+ &tms3203x_device::subf3_regreg, &tms3203x_device::subf3_indreg, &tms3203x_device::subf3_regind, &tms3203x_device::subf3_indind,
+ &tms3203x_device::subi3_regreg, &tms3203x_device::subi3_indreg, &tms3203x_device::subi3_regind, &tms3203x_device::subi3_indind,
+ &tms3203x_device::tstb3_regreg, &tms3203x_device::tstb3_indreg, &tms3203x_device::tstb3_regind, &tms3203x_device::tstb3_indind,
+ &tms3203x_device::xor3_regreg, &tms3203x_device::xor3_indreg, &tms3203x_device::xor3_regind, &tms3203x_device::xor3_indind, // 0x50
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0x58
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0x60
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0x68
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0x70
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0x78
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+
+ &tms3203x_device::ldfu_reg, &tms3203x_device::ldfu_dir, &tms3203x_device::ldfu_ind, &tms3203x_device::ldfu_imm, // 0x80
+ &tms3203x_device::ldflo_reg, &tms3203x_device::ldflo_dir, &tms3203x_device::ldflo_ind, &tms3203x_device::ldflo_imm,
+ &tms3203x_device::ldfls_reg, &tms3203x_device::ldfls_dir, &tms3203x_device::ldfls_ind, &tms3203x_device::ldfls_imm,
+ &tms3203x_device::ldfhi_reg, &tms3203x_device::ldfhi_dir, &tms3203x_device::ldfhi_ind, &tms3203x_device::ldfhi_imm,
+ &tms3203x_device::ldfhs_reg, &tms3203x_device::ldfhs_dir, &tms3203x_device::ldfhs_ind, &tms3203x_device::ldfhs_imm,
+ &tms3203x_device::ldfeq_reg, &tms3203x_device::ldfeq_dir, &tms3203x_device::ldfeq_ind, &tms3203x_device::ldfeq_imm,
+ &tms3203x_device::ldfne_reg, &tms3203x_device::ldfne_dir, &tms3203x_device::ldfne_ind, &tms3203x_device::ldfne_imm,
+ &tms3203x_device::ldflt_reg, &tms3203x_device::ldflt_dir, &tms3203x_device::ldflt_ind, &tms3203x_device::ldflt_imm,
+ &tms3203x_device::ldfle_reg, &tms3203x_device::ldfle_dir, &tms3203x_device::ldfle_ind, &tms3203x_device::ldfle_imm, // 0x88
+ &tms3203x_device::ldfgt_reg, &tms3203x_device::ldfgt_dir, &tms3203x_device::ldfgt_ind, &tms3203x_device::ldfgt_imm,
+ &tms3203x_device::ldfge_reg, &tms3203x_device::ldfge_dir, &tms3203x_device::ldfge_ind, &tms3203x_device::ldfge_imm,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::ldfnv_reg, &tms3203x_device::ldfnv_dir, &tms3203x_device::ldfnv_ind, &tms3203x_device::ldfnv_imm,
+ &tms3203x_device::ldfv_reg, &tms3203x_device::ldfv_dir, &tms3203x_device::ldfv_ind, &tms3203x_device::ldfv_imm,
+ &tms3203x_device::ldfnuf_reg, &tms3203x_device::ldfnuf_dir, &tms3203x_device::ldfnuf_ind, &tms3203x_device::ldfnuf_imm,
+ &tms3203x_device::ldfuf_reg, &tms3203x_device::ldfuf_dir, &tms3203x_device::ldfuf_ind, &tms3203x_device::ldfuf_imm,
+ &tms3203x_device::ldfnlv_reg, &tms3203x_device::ldfnlv_dir, &tms3203x_device::ldfnlv_ind, &tms3203x_device::ldfnlv_imm, // 0x90
+ &tms3203x_device::ldflv_reg, &tms3203x_device::ldflv_dir, &tms3203x_device::ldflv_ind, &tms3203x_device::ldflv_imm,
+ &tms3203x_device::ldfnluf_reg, &tms3203x_device::ldfnluf_dir, &tms3203x_device::ldfnluf_ind, &tms3203x_device::ldfnluf_imm,
+ &tms3203x_device::ldfluf_reg, &tms3203x_device::ldfluf_dir, &tms3203x_device::ldfluf_ind, &tms3203x_device::ldfluf_imm,
+ &tms3203x_device::ldfzuf_reg, &tms3203x_device::ldfzuf_dir, &tms3203x_device::ldfzuf_ind, &tms3203x_device::ldfzuf_imm,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0x98
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::ldiu_reg, &tms3203x_device::ldiu_dir, &tms3203x_device::ldiu_ind, &tms3203x_device::ldiu_imm, // 0xa0
+ &tms3203x_device::ldilo_reg, &tms3203x_device::ldilo_dir, &tms3203x_device::ldilo_ind, &tms3203x_device::ldilo_imm,
+ &tms3203x_device::ldils_reg, &tms3203x_device::ldils_dir, &tms3203x_device::ldils_ind, &tms3203x_device::ldils_imm,
+ &tms3203x_device::ldihi_reg, &tms3203x_device::ldihi_dir, &tms3203x_device::ldihi_ind, &tms3203x_device::ldihi_imm,
+ &tms3203x_device::ldihs_reg, &tms3203x_device::ldihs_dir, &tms3203x_device::ldihs_ind, &tms3203x_device::ldihs_imm,
+ &tms3203x_device::ldieq_reg, &tms3203x_device::ldieq_dir, &tms3203x_device::ldieq_ind, &tms3203x_device::ldieq_imm,
+ &tms3203x_device::ldine_reg, &tms3203x_device::ldine_dir, &tms3203x_device::ldine_ind, &tms3203x_device::ldine_imm,
+ &tms3203x_device::ldilt_reg, &tms3203x_device::ldilt_dir, &tms3203x_device::ldilt_ind, &tms3203x_device::ldilt_imm,
+ &tms3203x_device::ldile_reg, &tms3203x_device::ldile_dir, &tms3203x_device::ldile_ind, &tms3203x_device::ldile_imm, // 0xa8
+ &tms3203x_device::ldigt_reg, &tms3203x_device::ldigt_dir, &tms3203x_device::ldigt_ind, &tms3203x_device::ldigt_imm,
+ &tms3203x_device::ldige_reg, &tms3203x_device::ldige_dir, &tms3203x_device::ldige_ind, &tms3203x_device::ldige_imm,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::ldinv_reg, &tms3203x_device::ldinv_dir, &tms3203x_device::ldinv_ind, &tms3203x_device::ldinv_imm,
+ &tms3203x_device::ldiv_reg, &tms3203x_device::ldiv_dir, &tms3203x_device::ldiv_ind, &tms3203x_device::ldiv_imm,
+ &tms3203x_device::ldinuf_reg, &tms3203x_device::ldinuf_dir, &tms3203x_device::ldinuf_ind, &tms3203x_device::ldinuf_imm,
+ &tms3203x_device::ldiuf_reg, &tms3203x_device::ldiuf_dir, &tms3203x_device::ldiuf_ind, &tms3203x_device::ldiuf_imm,
+ &tms3203x_device::ldinlv_reg, &tms3203x_device::ldinlv_dir, &tms3203x_device::ldinlv_ind, &tms3203x_device::ldinlv_imm, // 0xb0
+ &tms3203x_device::ldilv_reg, &tms3203x_device::ldilv_dir, &tms3203x_device::ldilv_ind, &tms3203x_device::ldilv_imm,
+ &tms3203x_device::ldinluf_reg, &tms3203x_device::ldinluf_dir, &tms3203x_device::ldinluf_ind, &tms3203x_device::ldinluf_imm,
+ &tms3203x_device::ldiluf_reg, &tms3203x_device::ldiluf_dir, &tms3203x_device::ldiluf_ind, &tms3203x_device::ldiluf_imm,
+ &tms3203x_device::ldizuf_reg, &tms3203x_device::ldizuf_dir, &tms3203x_device::ldizuf_ind, &tms3203x_device::ldizuf_imm,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0xb8
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+
+ &tms3203x_device::br_imm, &tms3203x_device::br_imm, &tms3203x_device::br_imm, &tms3203x_device::br_imm, // 0xc0
+ &tms3203x_device::br_imm, &tms3203x_device::br_imm, &tms3203x_device::br_imm, &tms3203x_device::br_imm,
+ &tms3203x_device::brd_imm, &tms3203x_device::brd_imm, &tms3203x_device::brd_imm, &tms3203x_device::brd_imm,
+ &tms3203x_device::brd_imm, &tms3203x_device::brd_imm, &tms3203x_device::brd_imm, &tms3203x_device::brd_imm,
+ &tms3203x_device::call_imm, &tms3203x_device::call_imm, &tms3203x_device::call_imm, &tms3203x_device::call_imm,
+ &tms3203x_device::call_imm, &tms3203x_device::call_imm, &tms3203x_device::call_imm, &tms3203x_device::call_imm,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::rptb_imm, &tms3203x_device::rptb_imm, &tms3203x_device::rptb_imm, &tms3203x_device::rptb_imm, // 0xc8
+ &tms3203x_device::rptb_imm, &tms3203x_device::rptb_imm, &tms3203x_device::rptb_imm, &tms3203x_device::rptb_imm,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::swi, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::brc_reg, &tms3203x_device::brcd_reg, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0xd0
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::brc_imm, &tms3203x_device::brcd_imm, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::dbc_reg, &tms3203x_device::dbcd_reg, &tms3203x_device::dbc_reg, &tms3203x_device::dbcd_reg, // 0xd8
+ &tms3203x_device::dbc_reg, &tms3203x_device::dbcd_reg, &tms3203x_device::dbc_reg, &tms3203x_device::dbcd_reg,
+ &tms3203x_device::dbc_reg, &tms3203x_device::dbcd_reg, &tms3203x_device::dbc_reg, &tms3203x_device::dbcd_reg,
+ &tms3203x_device::dbc_reg, &tms3203x_device::dbcd_reg, &tms3203x_device::dbc_reg, &tms3203x_device::dbcd_reg,
+ &tms3203x_device::dbc_imm, &tms3203x_device::dbcd_imm, &tms3203x_device::dbc_imm, &tms3203x_device::dbcd_imm,
+ &tms3203x_device::dbc_imm, &tms3203x_device::dbcd_imm, &tms3203x_device::dbc_imm, &tms3203x_device::dbcd_imm,
+ &tms3203x_device::dbc_imm, &tms3203x_device::dbcd_imm, &tms3203x_device::dbc_imm, &tms3203x_device::dbcd_imm,
+ &tms3203x_device::dbc_imm, &tms3203x_device::dbcd_imm, &tms3203x_device::dbc_imm, &tms3203x_device::dbcd_imm,
+ &tms3203x_device::callc_reg, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0xe0
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::callc_imm, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::trapc, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0xe8
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::retic_reg, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0xf0
+ &tms3203x_device::retsc_reg, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0xf8
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+
+ &tms3203x_device::mpyaddf_0, &tms3203x_device::mpyaddf_0, &tms3203x_device::mpyaddf_0, &tms3203x_device::mpyaddf_0, // 0x100
+ &tms3203x_device::mpyaddf_0, &tms3203x_device::mpyaddf_0, &tms3203x_device::mpyaddf_0, &tms3203x_device::mpyaddf_0,
+ &tms3203x_device::mpyaddf_1, &tms3203x_device::mpyaddf_1, &tms3203x_device::mpyaddf_1, &tms3203x_device::mpyaddf_1,
+ &tms3203x_device::mpyaddf_1, &tms3203x_device::mpyaddf_1, &tms3203x_device::mpyaddf_1, &tms3203x_device::mpyaddf_1,
+ &tms3203x_device::mpyaddf_2, &tms3203x_device::mpyaddf_2, &tms3203x_device::mpyaddf_2, &tms3203x_device::mpyaddf_2,
+ &tms3203x_device::mpyaddf_2, &tms3203x_device::mpyaddf_2, &tms3203x_device::mpyaddf_2, &tms3203x_device::mpyaddf_2,
+ &tms3203x_device::mpyaddf_3, &tms3203x_device::mpyaddf_3, &tms3203x_device::mpyaddf_3, &tms3203x_device::mpyaddf_3,
+ &tms3203x_device::mpyaddf_3, &tms3203x_device::mpyaddf_3, &tms3203x_device::mpyaddf_3, &tms3203x_device::mpyaddf_3,
+ &tms3203x_device::mpysubf_0, &tms3203x_device::mpysubf_0, &tms3203x_device::mpysubf_0, &tms3203x_device::mpysubf_0, // 0x108
+ &tms3203x_device::mpysubf_0, &tms3203x_device::mpysubf_0, &tms3203x_device::mpysubf_0, &tms3203x_device::mpysubf_0,
+ &tms3203x_device::mpysubf_1, &tms3203x_device::mpysubf_1, &tms3203x_device::mpysubf_1, &tms3203x_device::mpysubf_1,
+ &tms3203x_device::mpysubf_1, &tms3203x_device::mpysubf_1, &tms3203x_device::mpysubf_1, &tms3203x_device::mpysubf_1,
+ &tms3203x_device::mpysubf_2, &tms3203x_device::mpysubf_2, &tms3203x_device::mpysubf_2, &tms3203x_device::mpysubf_2,
+ &tms3203x_device::mpysubf_2, &tms3203x_device::mpysubf_2, &tms3203x_device::mpysubf_2, &tms3203x_device::mpysubf_2,
+ &tms3203x_device::mpysubf_3, &tms3203x_device::mpysubf_3, &tms3203x_device::mpysubf_3, &tms3203x_device::mpysubf_3,
+ &tms3203x_device::mpysubf_3, &tms3203x_device::mpysubf_3, &tms3203x_device::mpysubf_3, &tms3203x_device::mpysubf_3,
+ &tms3203x_device::mpyaddi_0, &tms3203x_device::mpyaddi_0, &tms3203x_device::mpyaddi_0, &tms3203x_device::mpyaddi_0, // 0x110
+ &tms3203x_device::mpyaddi_0, &tms3203x_device::mpyaddi_0, &tms3203x_device::mpyaddi_0, &tms3203x_device::mpyaddi_0,
+ &tms3203x_device::mpyaddi_1, &tms3203x_device::mpyaddi_1, &tms3203x_device::mpyaddi_1, &tms3203x_device::mpyaddi_1,
+ &tms3203x_device::mpyaddi_1, &tms3203x_device::mpyaddi_1, &tms3203x_device::mpyaddi_1, &tms3203x_device::mpyaddi_1,
+ &tms3203x_device::mpyaddi_2, &tms3203x_device::mpyaddi_2, &tms3203x_device::mpyaddi_2, &tms3203x_device::mpyaddi_2,
+ &tms3203x_device::mpyaddi_2, &tms3203x_device::mpyaddi_2, &tms3203x_device::mpyaddi_2, &tms3203x_device::mpyaddi_2,
+ &tms3203x_device::mpyaddi_3, &tms3203x_device::mpyaddi_3, &tms3203x_device::mpyaddi_3, &tms3203x_device::mpyaddi_3,
+ &tms3203x_device::mpyaddi_3, &tms3203x_device::mpyaddi_3, &tms3203x_device::mpyaddi_3, &tms3203x_device::mpyaddi_3,
+ &tms3203x_device::mpysubi_0, &tms3203x_device::mpysubi_0, &tms3203x_device::mpysubi_0, &tms3203x_device::mpysubi_0, // 0x118
+ &tms3203x_device::mpysubi_0, &tms3203x_device::mpysubi_0, &tms3203x_device::mpysubi_0, &tms3203x_device::mpysubi_0,
+ &tms3203x_device::mpysubi_1, &tms3203x_device::mpysubi_1, &tms3203x_device::mpysubi_1, &tms3203x_device::mpysubi_1,
+ &tms3203x_device::mpysubi_1, &tms3203x_device::mpysubi_1, &tms3203x_device::mpysubi_1, &tms3203x_device::mpysubi_1,
+ &tms3203x_device::mpysubi_2, &tms3203x_device::mpysubi_2, &tms3203x_device::mpysubi_2, &tms3203x_device::mpysubi_2,
+ &tms3203x_device::mpysubi_2, &tms3203x_device::mpysubi_2, &tms3203x_device::mpysubi_2, &tms3203x_device::mpysubi_2,
+ &tms3203x_device::mpysubi_3, &tms3203x_device::mpysubi_3, &tms3203x_device::mpysubi_3, &tms3203x_device::mpysubi_3,
+ &tms3203x_device::mpysubi_3, &tms3203x_device::mpysubi_3, &tms3203x_device::mpysubi_3, &tms3203x_device::mpysubi_3,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0x120
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0x128
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0x130
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0x138
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0x140
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0x148
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0x150
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0x158
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0x160
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0x168
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0x170
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0x178
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+
+ &tms3203x_device::stfstf, &tms3203x_device::stfstf, &tms3203x_device::stfstf, &tms3203x_device::stfstf, // 0x180
+ &tms3203x_device::stfstf, &tms3203x_device::stfstf, &tms3203x_device::stfstf, &tms3203x_device::stfstf,
+ &tms3203x_device::stfstf, &tms3203x_device::stfstf, &tms3203x_device::stfstf, &tms3203x_device::stfstf,
+ &tms3203x_device::stfstf, &tms3203x_device::stfstf, &tms3203x_device::stfstf, &tms3203x_device::stfstf,
+ &tms3203x_device::stisti, &tms3203x_device::stisti, &tms3203x_device::stisti, &tms3203x_device::stisti,
+ &tms3203x_device::stisti, &tms3203x_device::stisti, &tms3203x_device::stisti, &tms3203x_device::stisti,
+ &tms3203x_device::stisti, &tms3203x_device::stisti, &tms3203x_device::stisti, &tms3203x_device::stisti,
+ &tms3203x_device::stisti, &tms3203x_device::stisti, &tms3203x_device::stisti, &tms3203x_device::stisti,
+ &tms3203x_device::ldfldf, &tms3203x_device::ldfldf, &tms3203x_device::ldfldf, &tms3203x_device::ldfldf, // 0x188
+ &tms3203x_device::ldfldf, &tms3203x_device::ldfldf, &tms3203x_device::ldfldf, &tms3203x_device::ldfldf,
+ &tms3203x_device::ldfldf, &tms3203x_device::ldfldf, &tms3203x_device::ldfldf, &tms3203x_device::ldfldf,
+ &tms3203x_device::ldfldf, &tms3203x_device::ldfldf, &tms3203x_device::ldfldf, &tms3203x_device::ldfldf,
+ &tms3203x_device::ldildi, &tms3203x_device::ldildi, &tms3203x_device::ldildi, &tms3203x_device::ldildi,
+ &tms3203x_device::ldildi, &tms3203x_device::ldildi, &tms3203x_device::ldildi, &tms3203x_device::ldildi,
+ &tms3203x_device::ldildi, &tms3203x_device::ldildi, &tms3203x_device::ldildi, &tms3203x_device::ldildi,
+ &tms3203x_device::ldildi, &tms3203x_device::ldildi, &tms3203x_device::ldildi, &tms3203x_device::ldildi,
+ &tms3203x_device::absfstf, &tms3203x_device::absfstf, &tms3203x_device::absfstf, &tms3203x_device::absfstf, // 0x190
+ &tms3203x_device::absfstf, &tms3203x_device::absfstf, &tms3203x_device::absfstf, &tms3203x_device::absfstf,
+ &tms3203x_device::absfstf, &tms3203x_device::absfstf, &tms3203x_device::absfstf, &tms3203x_device::absfstf,
+ &tms3203x_device::absfstf, &tms3203x_device::absfstf, &tms3203x_device::absfstf, &tms3203x_device::absfstf,
+ &tms3203x_device::absisti, &tms3203x_device::absisti, &tms3203x_device::absisti, &tms3203x_device::absisti,
+ &tms3203x_device::absisti, &tms3203x_device::absisti, &tms3203x_device::absisti, &tms3203x_device::absisti,
+ &tms3203x_device::absisti, &tms3203x_device::absisti, &tms3203x_device::absisti, &tms3203x_device::absisti,
+ &tms3203x_device::absisti, &tms3203x_device::absisti, &tms3203x_device::absisti, &tms3203x_device::absisti,
+ &tms3203x_device::addf3stf, &tms3203x_device::addf3stf, &tms3203x_device::addf3stf, &tms3203x_device::addf3stf, // 0x198
+ &tms3203x_device::addf3stf, &tms3203x_device::addf3stf, &tms3203x_device::addf3stf, &tms3203x_device::addf3stf,
+ &tms3203x_device::addf3stf, &tms3203x_device::addf3stf, &tms3203x_device::addf3stf, &tms3203x_device::addf3stf,
+ &tms3203x_device::addf3stf, &tms3203x_device::addf3stf, &tms3203x_device::addf3stf, &tms3203x_device::addf3stf,
+ &tms3203x_device::addi3sti, &tms3203x_device::addi3sti, &tms3203x_device::addi3sti, &tms3203x_device::addi3sti,
+ &tms3203x_device::addi3sti, &tms3203x_device::addi3sti, &tms3203x_device::addi3sti, &tms3203x_device::addi3sti,
+ &tms3203x_device::addi3sti, &tms3203x_device::addi3sti, &tms3203x_device::addi3sti, &tms3203x_device::addi3sti,
+ &tms3203x_device::addi3sti, &tms3203x_device::addi3sti, &tms3203x_device::addi3sti, &tms3203x_device::addi3sti,
+ &tms3203x_device::and3sti, &tms3203x_device::and3sti, &tms3203x_device::and3sti, &tms3203x_device::and3sti, // 0x1a0
+ &tms3203x_device::and3sti, &tms3203x_device::and3sti, &tms3203x_device::and3sti, &tms3203x_device::and3sti,
+ &tms3203x_device::and3sti, &tms3203x_device::and3sti, &tms3203x_device::and3sti, &tms3203x_device::and3sti,
+ &tms3203x_device::and3sti, &tms3203x_device::and3sti, &tms3203x_device::and3sti, &tms3203x_device::and3sti,
+ &tms3203x_device::ash3sti, &tms3203x_device::ash3sti, &tms3203x_device::ash3sti, &tms3203x_device::ash3sti,
+ &tms3203x_device::ash3sti, &tms3203x_device::ash3sti, &tms3203x_device::ash3sti, &tms3203x_device::ash3sti,
+ &tms3203x_device::ash3sti, &tms3203x_device::ash3sti, &tms3203x_device::ash3sti, &tms3203x_device::ash3sti,
+ &tms3203x_device::ash3sti, &tms3203x_device::ash3sti, &tms3203x_device::ash3sti, &tms3203x_device::ash3sti,
+ &tms3203x_device::fixsti, &tms3203x_device::fixsti, &tms3203x_device::fixsti, &tms3203x_device::fixsti, // 0x1a8
+ &tms3203x_device::fixsti, &tms3203x_device::fixsti, &tms3203x_device::fixsti, &tms3203x_device::fixsti,
+ &tms3203x_device::fixsti, &tms3203x_device::fixsti, &tms3203x_device::fixsti, &tms3203x_device::fixsti,
+ &tms3203x_device::fixsti, &tms3203x_device::fixsti, &tms3203x_device::fixsti, &tms3203x_device::fixsti,
+ &tms3203x_device::floatstf, &tms3203x_device::floatstf, &tms3203x_device::floatstf, &tms3203x_device::floatstf,
+ &tms3203x_device::floatstf, &tms3203x_device::floatstf, &tms3203x_device::floatstf, &tms3203x_device::floatstf,
+ &tms3203x_device::floatstf, &tms3203x_device::floatstf, &tms3203x_device::floatstf, &tms3203x_device::floatstf,
+ &tms3203x_device::floatstf, &tms3203x_device::floatstf, &tms3203x_device::floatstf, &tms3203x_device::floatstf,
+ &tms3203x_device::ldfstf, &tms3203x_device::ldfstf, &tms3203x_device::ldfstf, &tms3203x_device::ldfstf, // 0x1b0
+ &tms3203x_device::ldfstf, &tms3203x_device::ldfstf, &tms3203x_device::ldfstf, &tms3203x_device::ldfstf,
+ &tms3203x_device::ldfstf, &tms3203x_device::ldfstf, &tms3203x_device::ldfstf, &tms3203x_device::ldfstf,
+ &tms3203x_device::ldfstf, &tms3203x_device::ldfstf, &tms3203x_device::ldfstf, &tms3203x_device::ldfstf,
+ &tms3203x_device::ldisti, &tms3203x_device::ldisti, &tms3203x_device::ldisti, &tms3203x_device::ldisti,
+ &tms3203x_device::ldisti, &tms3203x_device::ldisti, &tms3203x_device::ldisti, &tms3203x_device::ldisti,
+ &tms3203x_device::ldisti, &tms3203x_device::ldisti, &tms3203x_device::ldisti, &tms3203x_device::ldisti,
+ &tms3203x_device::ldisti, &tms3203x_device::ldisti, &tms3203x_device::ldisti, &tms3203x_device::ldisti,
+ &tms3203x_device::lsh3sti, &tms3203x_device::lsh3sti, &tms3203x_device::lsh3sti, &tms3203x_device::lsh3sti, // 0x1b8
+ &tms3203x_device::lsh3sti, &tms3203x_device::lsh3sti, &tms3203x_device::lsh3sti, &tms3203x_device::lsh3sti,
+ &tms3203x_device::lsh3sti, &tms3203x_device::lsh3sti, &tms3203x_device::lsh3sti, &tms3203x_device::lsh3sti,
+ &tms3203x_device::lsh3sti, &tms3203x_device::lsh3sti, &tms3203x_device::lsh3sti, &tms3203x_device::lsh3sti,
+ &tms3203x_device::mpyf3stf, &tms3203x_device::mpyf3stf, &tms3203x_device::mpyf3stf, &tms3203x_device::mpyf3stf,
+ &tms3203x_device::mpyf3stf, &tms3203x_device::mpyf3stf, &tms3203x_device::mpyf3stf, &tms3203x_device::mpyf3stf,
+ &tms3203x_device::mpyf3stf, &tms3203x_device::mpyf3stf, &tms3203x_device::mpyf3stf, &tms3203x_device::mpyf3stf,
+ &tms3203x_device::mpyf3stf, &tms3203x_device::mpyf3stf, &tms3203x_device::mpyf3stf, &tms3203x_device::mpyf3stf,
+
+ &tms3203x_device::mpyi3sti, &tms3203x_device::mpyi3sti, &tms3203x_device::mpyi3sti, &tms3203x_device::mpyi3sti, // 0x1c0
+ &tms3203x_device::mpyi3sti, &tms3203x_device::mpyi3sti, &tms3203x_device::mpyi3sti, &tms3203x_device::mpyi3sti,
+ &tms3203x_device::mpyi3sti, &tms3203x_device::mpyi3sti, &tms3203x_device::mpyi3sti, &tms3203x_device::mpyi3sti,
+ &tms3203x_device::mpyi3sti, &tms3203x_device::mpyi3sti, &tms3203x_device::mpyi3sti, &tms3203x_device::mpyi3sti,
+ &tms3203x_device::negfstf, &tms3203x_device::negfstf, &tms3203x_device::negfstf, &tms3203x_device::negfstf,
+ &tms3203x_device::negfstf, &tms3203x_device::negfstf, &tms3203x_device::negfstf, &tms3203x_device::negfstf,
+ &tms3203x_device::negfstf, &tms3203x_device::negfstf, &tms3203x_device::negfstf, &tms3203x_device::negfstf,
+ &tms3203x_device::negfstf, &tms3203x_device::negfstf, &tms3203x_device::negfstf, &tms3203x_device::negfstf,
+ &tms3203x_device::negisti, &tms3203x_device::negisti, &tms3203x_device::negisti, &tms3203x_device::negisti, // 0x1c8
+ &tms3203x_device::negisti, &tms3203x_device::negisti, &tms3203x_device::negisti, &tms3203x_device::negisti,
+ &tms3203x_device::negisti, &tms3203x_device::negisti, &tms3203x_device::negisti, &tms3203x_device::negisti,
+ &tms3203x_device::negisti, &tms3203x_device::negisti, &tms3203x_device::negisti, &tms3203x_device::negisti,
+ &tms3203x_device::notsti, &tms3203x_device::notsti, &tms3203x_device::notsti, &tms3203x_device::notsti,
+ &tms3203x_device::notsti, &tms3203x_device::notsti, &tms3203x_device::notsti, &tms3203x_device::notsti,
+ &tms3203x_device::notsti, &tms3203x_device::notsti, &tms3203x_device::notsti, &tms3203x_device::notsti,
+ &tms3203x_device::notsti, &tms3203x_device::notsti, &tms3203x_device::notsti, &tms3203x_device::notsti,
+ &tms3203x_device::or3sti, &tms3203x_device::or3sti, &tms3203x_device::or3sti, &tms3203x_device::or3sti, // 0x1d0
+ &tms3203x_device::or3sti, &tms3203x_device::or3sti, &tms3203x_device::or3sti, &tms3203x_device::or3sti,
+ &tms3203x_device::or3sti, &tms3203x_device::or3sti, &tms3203x_device::or3sti, &tms3203x_device::or3sti,
+ &tms3203x_device::or3sti, &tms3203x_device::or3sti, &tms3203x_device::or3sti, &tms3203x_device::or3sti,
+ &tms3203x_device::subf3stf, &tms3203x_device::subf3stf, &tms3203x_device::subf3stf, &tms3203x_device::subf3stf,
+ &tms3203x_device::subf3stf, &tms3203x_device::subf3stf, &tms3203x_device::subf3stf, &tms3203x_device::subf3stf,
+ &tms3203x_device::subf3stf, &tms3203x_device::subf3stf, &tms3203x_device::subf3stf, &tms3203x_device::subf3stf,
+ &tms3203x_device::subf3stf, &tms3203x_device::subf3stf, &tms3203x_device::subf3stf, &tms3203x_device::subf3stf,
+ &tms3203x_device::subi3sti, &tms3203x_device::subi3sti, &tms3203x_device::subi3sti, &tms3203x_device::subi3sti, // 0x1d8
+ &tms3203x_device::subi3sti, &tms3203x_device::subi3sti, &tms3203x_device::subi3sti, &tms3203x_device::subi3sti,
+ &tms3203x_device::subi3sti, &tms3203x_device::subi3sti, &tms3203x_device::subi3sti, &tms3203x_device::subi3sti,
+ &tms3203x_device::subi3sti, &tms3203x_device::subi3sti, &tms3203x_device::subi3sti, &tms3203x_device::subi3sti,
+ &tms3203x_device::xor3sti, &tms3203x_device::xor3sti, &tms3203x_device::xor3sti, &tms3203x_device::xor3sti,
+ &tms3203x_device::xor3sti, &tms3203x_device::xor3sti, &tms3203x_device::xor3sti, &tms3203x_device::xor3sti,
+ &tms3203x_device::xor3sti, &tms3203x_device::xor3sti, &tms3203x_device::xor3sti, &tms3203x_device::xor3sti,
+ &tms3203x_device::xor3sti, &tms3203x_device::xor3sti, &tms3203x_device::xor3sti, &tms3203x_device::xor3sti,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0x1e0
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0x1e8
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0x1f0
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, // 0x1f8
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal,
+ &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal, &tms3203x_device::illegal
+};
diff --git a/trunk/src/emu/cpu/tms32031/dis32031.c b/trunk/src/emu/cpu/tms32031/dis32031.c
new file mode 100644
index 00000000000..830a8426fe0
--- /dev/null
+++ b/trunk/src/emu/cpu/tms32031/dis32031.c
@@ -0,0 +1,741 @@
+/***************************************************************************
+
+ dis32031.c
+ Disassembler for the portable TMS32C031 emulator.
+ Written by Aaron Giles
+
+***************************************************************************/
+
+#include "emu.h"
+#include "tms32031.h"
+
+
+/***************************************************************************
+ MEMORY ACCESSORS
+***************************************************************************/
+
+#define INTEGER 0
+#define FLOAT 1
+#define NODEST 2
+#define NOSOURCE 4
+#define NOSOURCE1 NOSOURCE
+#define NOSOURCE2 8
+#define SWAPSRCDST 16
+#define UNSIGNED 32
+
+
+/***************************************************************************
+ CODE CODE
+***************************************************************************/
+
+INLINE char *signed_16bit(INT16 val)
+{
+ static char temp[10];
+ if (val < 0)
+ sprintf(temp, "-$%x", -val & 0xffff);
+ else
+ sprintf(temp, "$%x", val);
+ return temp;
+}
+
+static const char *const regname[32] =
+{
+ "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
+ "AR0", "AR1", "AR2", "AR3", "AR4", "AR5", "AR6", "AR7",
+ "DP", "IR0", "IR1", "BK", "SP", "ST", "IE", "IF",
+ "IOF", "RS", "RE", "RC", "??", "??", "??", "??"
+};
+
+static const char *const condition[32] =
+{
+ "U", "LO", "LS", "HI", "HS", "EQ", "NE", "LT",
+ "LE", "GT", "GE", "??", "NV", "V", "NUF", "UF",
+ "NLV", "LV", "NLUF", "LUF", "ZUF", "??", "??", "??",
+ "??", "??", "??", "??", "??", "??", "??", "??"
+};
+
+//
+// for instructions 0x000-0x3f
+// G = (op >> 21) & 3;
+// G == 0 -> register -> 000ooooo o00ddddd 00000000 000sssss
+// G == 1 -> direct -> 000ooooo o01ddddd DDDDDDDD DDDDDDDD
+// G == 2 -> indirect -> 000ooooo o10ddddd mmmmmaaa DDDDDDDD
+// G == 3 -> immediate -> 000ooooo o11ddddd iiiiiiii iiiiiiii
+//
+// for instructions 0x040-0x7f
+// T = (op >> 21) & 3; (src1) (src2)
+// T == 0 -> reg reg -> 001ooooo o00ddddd 000sssss 000SSSSS
+// T == 1 -> ind reg -> 001ooooo o01ddddd mmmmmaaa 000SSSSS
+// T == 2 -> reg ind -> 001ooooo o10ddddd 000sssss MMMMMAAA
+// T == 3 -> ind ind -> 001ooooo o11ddddd mmmmmaaa MMMMMAAA
+//
+// for instructions 0x100-0x1ff
+// 10ooooPP dDsssSSS mmmmmaaa MMMMMAAA
+// 10ooooPP dDsssSSS 111rrrrr 111RRRRR
+//
+// conditional branches
+// xxxxxxBa aaDccccc 00000000 000sssss
+// xxxxxxBa aaDccccc iiiiiiii iiiiiiii
+// D=0(standard) or 1(delayed)
+// B=0(register) or 1(immediate)
+//
+// status register
+// 31-14 = 0
+// 13 = GIE
+// 12 = CC
+// 11 = CE
+// 10 = CF
+// 9 = 0
+// 8 = RM
+// 7 = OVM
+// 6 = LUF (latched FP underflow)
+// 5 = LV (latched overflow)
+// 4 = UF (FP underflow)
+// 3 = N
+// 2 = Z
+// 1 = V
+// 0 = C
+//
+// conditions:
+// 0 = U (unconditional)
+// 1 = LO (C)
+// 2 = LS (C | Z)
+// 3 = HI (~C & ~Z)
+// 4 = HS (~C)
+// 5 = EQ (Z)
+// 6 = NE (~Z)
+// 7 = LT (N)
+// 8 = LE (N | Z)
+// 9 = GT (~N & ~Z)
+// 10 = GE (~N)
+// 12 = NV (~V)
+// 13 = V (V)
+// 14 = NUF (~UF)
+// 15 = UF (UF)
+// 16 = NLV (~LV)
+// 17 = LV (LV)
+// 18 = NLUF (~LUF)
+// 19 = LUF (LUF)
+// 20 = ZUF (Z | UF)
+
+static void append_indirect(UINT8 ma, INT8 disp, char *buffer)
+{
+ char *dst = &buffer[strlen(buffer)];
+ char dispstr[20];
+ int mode = (ma >> 3) & 0x1f;
+ int ar = ma & 7;
+
+ dispstr[0] = 0;
+ if (disp < 0)
+ sprintf(dispstr, "(-%X)", -disp & 0xffff);
+ else if (disp > 0)
+ sprintf(dispstr, "(%X)", disp);
+
+ switch (mode)
+ {
+ case 0: sprintf(dst, "*+AR%d%s", ar, dispstr); break;
+ case 1: sprintf(dst, "*-AR%d%s", ar, dispstr); break;
+ case 2: sprintf(dst, "*++AR%d%s", ar, dispstr); break;
+ case 3: sprintf(dst, "*--AR%d%s", ar, dispstr); break;
+ case 4: sprintf(dst, "*AR%d++%s", ar, dispstr); break;
+ case 5: sprintf(dst, "*AR%d--%s", ar, dispstr); break;
+ case 6: sprintf(dst, "*AR%d++%s%%", ar, dispstr); break;
+ case 7: sprintf(dst, "*AR%d--%s%%", ar, dispstr); break;
+
+ case 8: sprintf(dst, "*+AR%d(IR0)", ar); break;
+ case 9: sprintf(dst, "*-AR%d(IR0)", ar); break;
+ case 10: sprintf(dst, "*++AR%d(IR0)", ar); break;
+ case 11: sprintf(dst, "*--AR%d(IR0)", ar); break;
+ case 12: sprintf(dst, "*AR%d++(IR0)", ar); break;
+ case 13: sprintf(dst, "*AR%d--(IR0)", ar); break;
+ case 14: sprintf(dst, "*AR%d++(IR0)%%", ar); break;
+ case 15: sprintf(dst, "*AR%d--(IR0)%%", ar); break;
+
+ case 16: sprintf(dst, "*+AR%d(IR1)", ar); break;
+ case 17: sprintf(dst, "*-AR%d(IR1)", ar); break;
+ case 18: sprintf(dst, "*++AR%d(IR1)", ar); break;
+ case 19: sprintf(dst, "*--AR%d(IR1)", ar); break;
+ case 20: sprintf(dst, "*AR%d++(IR1)", ar); break;
+ case 21: sprintf(dst, "*AR%d--(IR1)", ar); break;
+ case 22: sprintf(dst, "*AR%d++(IR1)%%", ar); break;
+ case 23: sprintf(dst, "*AR%d--(IR1)%%", ar); break;
+
+ case 24: sprintf(dst, "*AR%d", ar); break;
+ case 25: sprintf(dst, "*AR%d++(IR0)B", ar); break;
+ case 28:
+ case 29:
+ case 30:
+ case 31: strcpy(dst, regname[ma & 31]); break;
+ default: sprintf(dst, "(unknown mode)"); break;
+ }
+}
+
+static void append_immediate(UINT16 data, int is_float, int is_unsigned, char *buffer)
+{
+ char *dst = &buffer[strlen(buffer)];
+
+ if (is_float)
+ {
+ int exp = ((INT16)data >> 12) + 127;
+ UINT32 expanded_data;
+ float float_val;
+
+ expanded_data = ((data & 0x0800) << 20) + ((exp << 23) & 0x7f800000);
+ if (data == 0x8000)
+ *(float *)&expanded_data = 0;
+ else if (!(data & 0x0800))
+ expanded_data += ((data & 0x0fff) << 12);
+ else
+ expanded_data += ((-data & 0x0fff) << 12);
+ float_val = *(float *)&expanded_data;
+ sprintf(dst, "%8f", float_val);
+ }
+ else if (!is_unsigned && (INT16)data < 0)
+ sprintf(dst, "-$%04X", -data & 0xffff);
+ else
+ sprintf(dst, "$%04X", data);
+}
+
+static void disasm_general(const char *opstring, UINT32 op, int flags, char *buffer)
+{
+ sprintf(buffer, "%-6s", opstring);
+
+ if (flags & SWAPSRCDST)
+ {
+ strcat(buffer, regname[(op >> 16) & 31]);
+ strcat(buffer, ",");
+ }
+
+ /* switch off of G */
+ if (!(flags & NOSOURCE))
+ {
+ switch ((op >> 21) & 3)
+ {
+ case 0:
+ strcat(buffer, regname[op & 31]);
+ break;
+
+ case 1:
+ sprintf(&buffer[strlen(buffer)], "($%04X)", op & 0xffff);
+ break;
+
+ case 2:
+ append_indirect((op >> 8) & 0xff, op, buffer);
+ break;
+
+ case 3:
+ append_immediate(op & 0xffff, (flags & FLOAT), (flags & UNSIGNED), buffer);
+ break;
+ }
+ }
+
+ /* add destination op */
+ if (!(flags & NODEST) && !(flags & SWAPSRCDST))
+ {
+ if (!(flags & NOSOURCE))
+ strcat(buffer, ",");
+ strcat(buffer, regname[(op >> 16) & 31]);
+ }
+}
+
+static void disasm_3op(const char *opstring, UINT32 op, int flags, char *buffer)
+{
+ sprintf(buffer, "%-6s", opstring);
+
+ /* switch off of T */
+ if (!(flags & NOSOURCE1))
+ {
+ switch ((op >> 21) & 1)
+ {
+ case 0:
+ strcat(buffer, regname[(op >> 8) & 31]);
+ break;
+
+ case 1:
+ append_indirect(op >> 8, 1, buffer);
+ break;
+ }
+ }
+
+ /* switch off of T */
+ if (!(flags & NOSOURCE2))
+ {
+ if (!(flags & NOSOURCE1))
+ strcat(buffer, ",");
+ switch ((op >> 22) & 1)
+ {
+ case 0:
+ strcat(buffer, regname[op & 31]);
+ break;
+
+ case 1:
+ append_indirect(op, 1, buffer);
+ break;
+ }
+ }
+
+ /* add destination op */
+ if (!(flags & NODEST))
+ {
+ if (!(flags & (NOSOURCE1 | NOSOURCE2)))
+ strcat(buffer, ",");
+ strcat(buffer, regname[(op >> 16) & 31]);
+ }
+}
+
+static void disasm_conditional(const char *opstring, UINT32 op, int flags, char *buffer)
+{
+ char temp[10];
+ sprintf(temp, "%s%s", opstring, condition[(op >> 23) & 31]);
+ disasm_general(temp, op, flags, buffer);
+}
+
+
+static void disasm_parallel_3op3op(const char *opstring1, const char *opstring2, UINT32 op, int flags, const UINT8 *srctable, char *buffer)
+{
+ const UINT8 *s = &srctable[((op >> 24) & 3) * 4];
+ int d1 = (op >> 23) & 1;
+ int d2 = 2 + ((op >> 22) & 1);
+ char src[5][20];
+
+ strcpy(src[1], regname[(op >> 19) & 7]);
+ strcpy(src[2], regname[(op >> 16) & 7]);
+
+ src[3][0] = 0;
+ append_indirect(op >> 8, 1, src[3]);
+
+ src[4][0] = 0;
+ append_indirect(op, 1, src[4]);
+
+ sprintf(buffer, "%s %s,%s,R%d || %s %s,%s,R%d",
+ opstring1, src[s[0]], src[s[1]], d1,
+ opstring2, src[s[2]], src[s[3]], d2);
+}
+
+
+static void disasm_parallel_3opstore(const char *opstring1, const char *opstring2, UINT32 op, int flags, char *buffer)
+{
+ int d1 = (op >> 22) & 7;
+ int s1 = (op >> 19) & 7;
+ int s3 = (op >> 16) & 7;
+ char dst2[20], src2[20];
+
+ dst2[0] = 0;
+ append_indirect(op >> 8, 1, dst2);
+
+ src2[0] = 0;
+ append_indirect(op, 1, src2);
+
+ if (!(flags & NOSOURCE1))
+ sprintf(buffer, "%s R%d,%s,R%d || %s R%d,%s",
+ opstring1, s1, src2, d1,
+ opstring2, s3, dst2);
+ else
+ sprintf(buffer, "%s %s,R%d || %s R%d,%s",
+ opstring1, src2, d1,
+ opstring2, s3, dst2);
+}
+
+
+static void disasm_parallel_loadload(const char *opstring1, const char *opstring2, UINT32 op, int flags, char *buffer)
+{
+ int d2 = (op >> 22) & 7;
+ int d1 = (op >> 19) & 7;
+ char src1[20], src2[20];
+
+ src1[0] = 0;
+ append_indirect(op >> 8, 1, src1);
+
+ src2[0] = 0;
+ append_indirect(op, 1, src2);
+
+ sprintf(buffer, "%s %s,R%d || %s %s,R%d",
+ opstring1, src2, d2,
+ opstring2, src1, d1);
+}
+
+
+static void disasm_parallel_storestore(const char *opstring1, const char *opstring2, UINT32 op, int flags, char *buffer)
+{
+ int s2 = (op >> 22) & 7;
+ int s1 = (op >> 16) & 7;
+ char dst1[20], dst2[20];
+
+ dst1[0] = 0;
+ append_indirect(op >> 8, 1, dst1);
+
+ dst2[0] = 0;
+ append_indirect(op, 1, dst2);
+
+ sprintf(buffer, "%s R%d,%s || %s R%d,%s",
+ opstring1, s2, dst2,
+ opstring2, s1, dst1);
+}
+
+
+
+static unsigned dasm_tms3203x(char *buffer, unsigned pc, UINT32 op)
+{
+ UINT32 flags = 0;
+
+ switch (op >> 23)
+ {
+ case 0x000: disasm_general("ABSF", op, FLOAT, buffer); break;
+ case 0x001: disasm_general("ABSI", op, INTEGER, buffer); break;
+ case 0x002: disasm_general("ADDC", op, INTEGER, buffer); break;
+ case 0x003: disasm_general("ADDF", op, FLOAT, buffer); break;
+ case 0x004: disasm_general("ADDI", op, INTEGER, buffer); break;
+ case 0x005: disasm_general("AND", op, INTEGER | UNSIGNED, buffer); break;
+ case 0x006: disasm_general("ANDN", op, INTEGER | UNSIGNED, buffer); break;
+ case 0x007: disasm_general("ASH", op, INTEGER, buffer); break;
+
+ case 0x008: disasm_general("CMPF", op, FLOAT, buffer); break;
+ case 0x009: disasm_general("CMPI", op, INTEGER, buffer); break;
+ case 0x00a: disasm_general("FIX", op, FLOAT, buffer); break;
+ case 0x00b: disasm_general("FLOAT", op, INTEGER, buffer); break;
+ case 0x00c: disasm_general((op & 1) ? "IDLE2" : "IDLE", op, NOSOURCE | NODEST, buffer); break;
+ case 0x00d: disasm_general("LDE", op, FLOAT, buffer); break;
+ case 0x00e: disasm_general("LDF", op, FLOAT, buffer); break;
+ case 0x00f: disasm_general("LDFI", op, FLOAT, buffer); break;
+
+ case 0x010: disasm_general("LDI", op, INTEGER, buffer); break;
+ case 0x011: disasm_general("LDII", op, INTEGER, buffer); break;
+ case 0x012: disasm_general("LDM", op, FLOAT, buffer); break;
+ case 0x013: disasm_general("LSH", op, INTEGER, buffer); break;
+ case 0x014: disasm_general("MPYF", op, FLOAT, buffer); break;
+ case 0x015: disasm_general("MPYI", op, INTEGER, buffer); break;
+ case 0x016: disasm_general("NEGB", op, INTEGER, buffer); break;
+ case 0x017: disasm_general("NEGF", op, FLOAT, buffer); break;
+
+ case 0x018: disasm_general("NEGI", op, INTEGER, buffer); break;
+ case 0x019: disasm_general("NOP", op, NODEST, buffer); break;
+ case 0x01a: disasm_general("NORM", op, FLOAT, buffer); break;
+ case 0x01b: disasm_general("NOT", op, INTEGER, buffer); break;
+ case 0x01c: disasm_general("POP", op, NOSOURCE, buffer); break;
+ case 0x01d: disasm_general("POPF", op, NOSOURCE, buffer); break;
+ case 0x01e: disasm_general("PUSH", op, NOSOURCE, buffer); break;
+ case 0x01f: disasm_general("PUSHF", op, NOSOURCE, buffer); break;
+
+ case 0x020: disasm_general("OR", op, INTEGER | UNSIGNED, buffer); break;
+ case 0x021: disasm_general((op & 1) ? "LOPOWER" : "MAXSPEED", op, NOSOURCE | NODEST, buffer); break;
+ case 0x022: disasm_general("RND", op, FLOAT, buffer); break;
+ case 0x023: disasm_general("ROL", op, INTEGER, buffer); break;
+ case 0x024: disasm_general("ROLC", op, INTEGER, buffer); break;
+ case 0x025: disasm_general("ROR", op, INTEGER, buffer); break;
+ case 0x026: disasm_general("RORC", op, INTEGER, buffer); break;
+ case 0x027: disasm_general("RTPS", op, INTEGER | NODEST, buffer); break;
+
+ case 0x028: disasm_general("STF", op, FLOAT | SWAPSRCDST, buffer); break;
+ case 0x029: disasm_general("STFI", op, FLOAT | SWAPSRCDST, buffer); break;
+ case 0x02a: disasm_general("STI", op, INTEGER | SWAPSRCDST, buffer); break;
+ case 0x02b: disasm_general("STII", op, INTEGER | SWAPSRCDST, buffer); break;
+ case 0x02c: disasm_general("SIGI", op, NOSOURCE | NODEST, buffer); break;
+ case 0x02d: disasm_general("SUBB", op, INTEGER, buffer); break;
+ case 0x02e: disasm_general("SUBC", op, INTEGER, buffer); break;
+ case 0x02f: disasm_general("SUBF", op, FLOAT, buffer); break;
+
+ case 0x030: disasm_general("SUBI", op, INTEGER, buffer); break;
+ case 0x031: disasm_general("SUBRB", op, INTEGER, buffer); break;
+ case 0x032: disasm_general("SUBRF", op, FLOAT, buffer); break;
+ case 0x033: disasm_general("SUBRI", op, INTEGER, buffer); break;
+ case 0x034: disasm_general("TSTB", op, INTEGER, buffer); break;
+ case 0x035: disasm_general("XOR", op, INTEGER | UNSIGNED, buffer); break;
+ case 0x036: disasm_general("IACK", op, INTEGER | NODEST, buffer); break;
+
+ case 0x040: disasm_3op("ADDC3", op, INTEGER, buffer); break;
+ case 0x041: disasm_3op("ADDF3", op, FLOAT, buffer); break;
+ case 0x042: disasm_3op("ADDI3", op, INTEGER, buffer); break;
+ case 0x043: disasm_3op("AND3", op, INTEGER, buffer); break;
+ case 0x044: disasm_3op("ANDN3", op, INTEGER, buffer); break;
+ case 0x045: disasm_3op("ASH3", op, INTEGER, buffer); break;
+ case 0x046: disasm_3op("CMPF3", op, FLOAT | NODEST, buffer); break;
+ case 0x047: disasm_3op("CMPI3", op, INTEGER | NODEST, buffer); break;
+
+ case 0x048: disasm_3op("LSH3", op, INTEGER, buffer); break;
+ case 0x049: disasm_3op("MPYF3", op, FLOAT, buffer); break;
+ case 0x04a: disasm_3op("MPYI3", op, INTEGER, buffer); break;
+ case 0x04b: disasm_3op("OR3", op, INTEGER, buffer); break;
+ case 0x04c: disasm_3op("SUBB3", op, INTEGER, buffer); break;
+ case 0x04d: disasm_3op("SUBF3", op, FLOAT, buffer); break;
+ case 0x04e: disasm_3op("SUBI3", op, INTEGER, buffer); break;
+ case 0x04f: disasm_3op("TSTB3", op, INTEGER, buffer); break;
+
+ case 0x050: disasm_3op("XOR3", op, INTEGER, buffer); break;
+
+ case 0x080: case 0x081: case 0x082: case 0x083:
+ case 0x084: case 0x085: case 0x086: case 0x087:
+ case 0x088: case 0x089: case 0x08a: case 0x08b:
+ case 0x08c: case 0x08d: case 0x08e: case 0x08f:
+ case 0x090: case 0x091: case 0x092: case 0x093:
+ case 0x094: case 0x095: case 0x096: case 0x097:
+ case 0x098: case 0x099: case 0x09a: case 0x09b:
+ case 0x09c: case 0x09d: case 0x09e: case 0x09f:
+ disasm_conditional("LDF", op, FLOAT, buffer);
+ break;
+
+ case 0x0a0: case 0x0a1: case 0x0a2: case 0x0a3:
+ case 0x0a4: case 0x0a5: case 0x0a6: case 0x0a7:
+ case 0x0a8: case 0x0a9: case 0x0aa: case 0x0ab:
+ case 0x0ac: case 0x0ad: case 0x0ae: case 0x0af:
+ case 0x0b0: case 0x0b1: case 0x0b2: case 0x0b3:
+ case 0x0b4: case 0x0b5: case 0x0b6: case 0x0b7:
+ case 0x0b8: case 0x0b9: case 0x0ba: case 0x0bb:
+ case 0x0bc: case 0x0bd: case 0x0be: case 0x0bf:
+ disasm_conditional("LDI", op, INTEGER, buffer);
+ break;
+
+
+ case 0x0c0: case 0x0c1:
+ sprintf(buffer, "BR $%06X", op & 0xffffff);
+ break;
+
+ case 0x0c2: case 0x0c3:
+ sprintf(buffer, "BRD $%06X", op & 0xffffff);
+ break;
+
+ case 0x0c4: case 0x0c5:
+ sprintf(buffer, "CALL $%06X", op & 0xffffff);
+ flags = DASMFLAG_STEP_OVER;
+ break;
+
+
+ case 0x0c8: case 0x0c9:
+ sprintf(buffer, "RPTB $%06X", op & 0xffffff);
+ break;
+
+ case 0x0cc: case 0x0cd: case 0x0ce: case 0x0cf:
+ sprintf(buffer, "SWI");
+ break;
+
+
+ case 0x0d0:
+ {
+ char temp[10];
+ sprintf(temp, "B%s%s", condition[(op >> 16) & 31], ((op >> 21) & 1) ? "D" : "");
+ sprintf(buffer, "%-6s%s", temp, regname[op & 31]);
+ break;
+ }
+
+ case 0x0d4:
+ {
+ char temp[10];
+ sprintf(temp, "B%s%s", condition[(op >> 16) & 31], ((op >> 21) & 1) ? "D" : "");
+ sprintf(buffer, "%-6s$%06X", temp, (pc + (((op >> 21) & 1) ? 3 : 1) + (INT16)op) & 0xffffff);
+ break;
+ }
+
+
+ case 0x0d8: case 0x0d9: case 0x0da: case 0x0db:
+ {
+ char temp[10];
+ sprintf(temp, "DB%s%s", condition[(op >> 16) & 31], ((op >> 21) & 1) ? "D" : "");
+ sprintf(buffer, "%-6sAR%d,%s", temp, (op >> 22) & 7, regname[op & 31]);
+ break;
+ }
+
+ case 0x0dc: case 0x0dd: case 0x0de: case 0x0df:
+ {
+ char temp[10];
+ sprintf(temp, "DB%s%s", condition[(op >> 16) & 31], ((op >> 21) & 1) ? "D" : "");
+ sprintf(buffer, "%-6sAR%d,$%06X", temp, (op >> 22) & 7, (pc + (((op >> 21) & 1) ? 3 : 1) + (INT16)op) & 0xffffff);
+ break;
+ }
+
+
+ case 0x0e0:
+ {
+ char temp[10];
+ sprintf(temp, "CALL%s", condition[(op >> 16) & 31]);
+ sprintf(buffer, "%-6s%s", temp, regname[op & 31]);
+ flags = DASMFLAG_STEP_OVER;
+ break;
+ }
+
+ case 0x0e4:
+ {
+ char temp[10];
+ sprintf(temp, "CALL%s", condition[(op >> 16) & 31]);
+ sprintf(buffer, "%-6s$%06X", temp, (pc + 1 + (INT16)op) & 0xffffff);
+ flags = DASMFLAG_STEP_OVER;
+ break;
+ }
+
+
+ case 0x0e8: case 0x0e9: case 0x0ea: case 0x0eb:
+ {
+ char temp[10];
+ sprintf(temp, "TRAP%s", condition[(op >> 16) & 31]);
+ sprintf(buffer, "%-6s$%02X", temp, op & 31);
+ flags = DASMFLAG_STEP_OVER;
+ break;
+ }
+
+
+ case 0x0f0:
+ sprintf(buffer, "RETI%s", condition[(op >> 16) & 31]);
+ flags = DASMFLAG_STEP_OUT;
+ break;
+
+ case 0x0f1:
+ sprintf(buffer, "RETS%s", condition[(op >> 16) & 31]);
+ flags = DASMFLAG_STEP_OUT;
+ break;
+
+
+ case 0x100: case 0x101: case 0x102: case 0x103:
+ case 0x104: case 0x105: case 0x106: case 0x107: // MPYF3||ADDF3
+ {
+ static const UINT8 srctable[] = { 3,4,1,2, 3,1,4,2, 1,2,3,4, 3,1,2,4 };
+ disasm_parallel_3op3op("MPYF3", "ADDF3", op, FLOAT, srctable, buffer);
+ break;
+ }
+
+
+ case 0x108: case 0x109: case 0x10a: case 0x10b:
+ case 0x10c: case 0x10d: case 0x10e: case 0x10f: // MPYF3||SUBF3
+ {
+ static const UINT8 srctable[] = { 3,4,1,2, 3,1,4,2, 1,2,3,4, 3,1,2,4 };
+ disasm_parallel_3op3op("MPYF3", "SUBF3", op, FLOAT, srctable, buffer);
+ break;
+ }
+
+
+ case 0x110: case 0x111: case 0x112: case 0x113:
+ case 0x114: case 0x115: case 0x116: case 0x117: // MPYI3||ADDI3
+ {
+ static const UINT8 srctable[] = { 3,4,1,2, 3,1,4,2, 1,2,3,4, 3,1,2,4 };
+ disasm_parallel_3op3op("MPYI3", "ADDI3", op, INTEGER, srctable, buffer);
+ break;
+ }
+
+
+ case 0x118: case 0x119: case 0x11a: case 0x11b:
+ case 0x11c: case 0x11d: case 0x11e: case 0x11f: // MPYI3||SUBI3
+ {
+ static const UINT8 srctable[] = { 3,4,1,2, 3,1,4,2, 1,2,3,4, 3,1,2,4 };
+ disasm_parallel_3op3op("MPYI3", "SUBI3", op, INTEGER, srctable, buffer);
+ break;
+ }
+
+
+ case 0x180: case 0x181: case 0x182: case 0x183: // STF||STF
+ disasm_parallel_storestore("STF", "STF", op, FLOAT, buffer);
+ break;
+
+ case 0x184: case 0x185: case 0x186: case 0x187: // STI||STI
+ disasm_parallel_storestore("STI", "STI", op, INTEGER, buffer);
+ break;
+
+
+ case 0x188: case 0x189: case 0x18a: case 0x18b: // LDF||LDF
+ disasm_parallel_loadload("LDF", "LDF", op, FLOAT, buffer);
+ break;
+
+ case 0x18c: case 0x18d: case 0x18e: case 0x18f: // LDI||LDI
+ disasm_parallel_loadload("LDI", "LDI", op, INTEGER, buffer);
+ break;
+
+
+ case 0x190: case 0x191: case 0x192: case 0x193: // ABSF||STF
+ disasm_parallel_3opstore("ABSF", "STF", op, FLOAT | NOSOURCE1, buffer);
+ break;
+
+ case 0x194: case 0x195: case 0x196: case 0x197: // ABSI||STI
+ disasm_parallel_3opstore("ABSI", "STI", op, INTEGER | NOSOURCE1, buffer);
+ break;
+
+
+ case 0x198: case 0x199: case 0x19a: case 0x19b: // ADDF3||STF
+ disasm_parallel_3opstore("ADDF3", "STF", op, FLOAT, buffer);
+ break;
+
+ case 0x19c: case 0x19d: case 0x19e: case 0x19f: // ADDI3||STI
+ disasm_parallel_3opstore("ADDI3", "STI", op, INTEGER, buffer);
+ break;
+
+
+ case 0x1a0: case 0x1a1: case 0x1a2: case 0x1a3: // AND3||STI
+ disasm_parallel_3opstore("AND3", "STI", op, INTEGER, buffer);
+ break;
+
+ case 0x1a4: case 0x1a5: case 0x1a6: case 0x1a7: // ASH3||STI
+ disasm_parallel_3opstore("ASH3", "STI", op, INTEGER, buffer);
+ break;
+
+
+ case 0x1a8: case 0x1a9: case 0x1aa: case 0x1ab: // FIX||STI
+ disasm_parallel_3opstore("FIX", "STF", op, FLOAT | NOSOURCE1, buffer);
+ break;
+
+ case 0x1ac: case 0x1ad: case 0x1ae: case 0x1af: // FLOAT||STF
+ disasm_parallel_3opstore("FLOAT", "STF", op, FLOAT | NOSOURCE1, buffer);
+ break;
+
+
+ case 0x1b0: case 0x1b1: case 0x1b2: case 0x1b3: // LDF||STF
+ disasm_parallel_3opstore("LDF", "STF", op, FLOAT | NOSOURCE1, buffer);
+ break;
+
+ case 0x1b4: case 0x1b5: case 0x1b6: case 0x1b7: // LDI||STI
+ disasm_parallel_3opstore("LDI", "STI", op, INTEGER | NOSOURCE1, buffer);
+ break;
+
+
+ case 0x1b8: case 0x1b9: case 0x1ba: case 0x1bb: // LSH3||STI
+ disasm_parallel_3opstore("LSH3", "STI", op, INTEGER, buffer);
+ break;
+
+ case 0x1bc: case 0x1bd: case 0x1be: case 0x1bf: // MPYF3||STF
+ disasm_parallel_3opstore("MPYF3", "STF", op, FLOAT, buffer);
+ break;
+
+
+ case 0x1c0: case 0x1c1: case 0x1c2: case 0x1c3: // MPYI3||STI
+ disasm_parallel_3opstore("MPYI3", "STI", op, INTEGER, buffer);
+ break;
+
+ case 0x1c4: case 0x1c5: case 0x1c6: case 0x1c7: // NEGF||STF
+ disasm_parallel_3opstore("NEGF", "STF", op, FLOAT | NOSOURCE1, buffer);
+ break;
+
+
+ case 0x1c8: case 0x1c9: case 0x1ca: case 0x1cb: // NEGI||STI
+ disasm_parallel_3opstore("NEGI", "STI", op, INTEGER | NOSOURCE1, buffer);
+ break;
+
+ case 0x1cc: case 0x1cd: case 0x1ce: case 0x1cf: // NOT||STI
+ disasm_parallel_3opstore("NOT", "STI", op, INTEGER | NOSOURCE1, buffer);
+ break;
+
+
+ case 0x1d0: case 0x1d1: case 0x1d2: case 0x1d3: // OR3||STI
+ disasm_parallel_3opstore("OR3", "STI", op, INTEGER, buffer);
+ break;
+
+ case 0x1d4: case 0x1d5: case 0x1d6: case 0x1d7: // SUBF3||STF
+ disasm_parallel_3opstore("SUBF3", "STF", op, FLOAT, buffer);
+ break;
+
+
+ case 0x1d8: case 0x1d9: case 0x1da: case 0x1db: // SUBI3||STI
+ disasm_parallel_3opstore("SUBI3", "STI", op, INTEGER, buffer);
+ break;
+
+ case 0x1dc: case 0x1dd: case 0x1de: case 0x1df: // XOR3||STI
+ disasm_parallel_3opstore("XOR3", "STI", op, INTEGER, buffer);
+ break;
+
+
+ default:
+ break;
+ }
+
+ return 1 | flags | DASMFLAG_SUPPORTED;
+}
+
+
+CPU_DISASSEMBLE( tms3203x )
+{
+ UINT32 op = oprom[0] | (oprom[1] << 8) | (oprom[2] << 16) | (oprom[3] << 24);
+ return dasm_tms3203x(buffer, pc, op);
+}
diff --git a/trunk/src/emu/cpu/tms32031/tms32031.c b/trunk/src/emu/cpu/tms32031/tms32031.c
new file mode 100644
index 00000000000..227e52f5e77
--- /dev/null
+++ b/trunk/src/emu/cpu/tms32031/tms32031.c
@@ -0,0 +1,898 @@
+/***************************************************************************
+
+ tms32031.c
+
+ TMS32031/2 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.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "tms32031.h"
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// indexes into the register file
+enum
+{
+ TMR_R0 = 0,
+ TMR_R1,
+ TMR_R2,
+ TMR_R3,
+ TMR_R4,
+ TMR_R5,
+ TMR_R6,
+ TMR_R7,
+ TMR_AR0,
+ TMR_AR1,
+ TMR_AR2,
+ TMR_AR3,
+ TMR_AR4,
+ TMR_AR5,
+ TMR_AR6,
+ TMR_AR7,
+ TMR_DP,
+ TMR_IR0,
+ TMR_IR1,
+ TMR_BK,
+ TMR_SP,
+ TMR_ST,
+ TMR_IE,
+ TMR_IF,
+ TMR_IOF,
+ TMR_RS,
+ TMR_RE,
+ TMR_RC,
+ TMR_R8, // 3204x only
+ TMR_R9, // 3204x only
+ TMR_R10, // 3204x only
+ TMR_R11, // 3204x only
+ TMR_TEMP1, // used by the interpreter
+ TMR_TEMP2, // used by the interpreter
+ TMR_TEMP3 // used by the interpreter
+};
+
+// flags
+const int CFLAG = 0x0001;
+const int VFLAG = 0x0002;
+const int ZFLAG = 0x0004;
+const int NFLAG = 0x0008;
+const int UFFLAG = 0x0010;
+const int LVFLAG = 0x0020;
+const int LUFFLAG = 0x0040;
+const int OVMFLAG = 0x0080;
+const int RMFLAG = 0x0100;
+const int CFFLAG = 0x0400;
+const int CEFLAG = 0x0800;
+const int CCFLAG = 0x1000;
+const int GIEFLAG = 0x2000;
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+#define IREG(rnum) (m_r[rnum].i32[0])
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+const device_type TMS32031 = &device_creator<tms32031_device>;
+const device_type TMS32032 = &device_creator<tms32032_device>;
+
+// internal memory maps
+static ADDRESS_MAP_START( internal_32031, AS_PROGRAM, 32 )
+ AM_RANGE(0x809800, 0x809fff) AM_RAM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( internal_32032, AS_PROGRAM, 32 )
+ AM_RANGE(0x87fe00, 0x87ffff) AM_RAM
+ADDRESS_MAP_END
+
+
+
+//**************************************************************************
+// TMSREG REGISTER
+//**************************************************************************
+
+//-------------------------------------------------
+// as_float - interpret the contents of a tmsreg
+// as a DSP-encoded floating-point value, and
+// extract a 32-bit IEEE float from it
+//-------------------------------------------------
+
+float tms3203x_device::tmsreg::as_float() const
+{
+ int_double id;
+
+ // map 0 to 0
+ if (mantissa() == 0 && exponent() == -128)
+ return 0;
+
+ // handle positive numbers
+ else if (mantissa() >= 0)
+ {
+ int exp = (exponent() + 127) << 23;
+ id.i[0] = exp + (mantissa() >> 8);
+ }
+
+ // handle negative numbers
+ else
+ {
+ int exp = (exponent() + 127) << 23;
+ INT32 man = -mantissa();
+ id.i[0] = 0x80000000 + exp + ((man >> 8) & 0x00ffffff);
+ }
+
+ // return the converted float
+ return id.f[0];
+}
+
+
+//-------------------------------------------------
+// as_double - interpret the contents of a tmsreg
+// as a DSP-encoded floating-point value, and
+// extract a 64-bit IEEE double from it
+//-------------------------------------------------
+
+double tms3203x_device::tmsreg::as_double() const
+{
+ int_double id;
+
+ // map 0 to 0
+ if (mantissa() == 0 && exponent() == -128)
+ return 0;
+
+ // handle positive numbers
+ else if (mantissa() >= 0)
+ {
+ int exp = (exponent() + 1023) << 20;
+ id.i[BYTE_XOR_BE(0)] = exp + (mantissa() >> 11);
+ id.i[BYTE_XOR_BE(1)] = (mantissa() << 21) & 0xffe00000;
+ }
+
+ // handle negative numbers
+ else
+ {
+ int exp = (exponent() + 1023) << 20;
+ INT32 man = -mantissa();
+ id.i[BYTE_XOR_BE(0)] = 0x80000000 + exp + ((man >> 11) & 0x001fffff);
+ id.i[BYTE_XOR_BE(1)] = (man << 21) & 0xffe00000;
+ }
+
+ // return the converted double
+ return id.d;
+}
+
+
+//-------------------------------------------------
+// from_double - import a 64-bit IEEE double into
+// the DSP's internal floating point format
+//-------------------------------------------------
+
+void tms3203x_device::tmsreg::from_double(double val)
+{
+ // extract mantissa and exponent from the IEEE input
+ int_double id;
+ id.d = val;
+ INT32 mantissa = ((id.i[BYTE_XOR_BE(0)] & 0x000fffff) << 11) | ((id.i[BYTE_XOR_BE(1)] & 0xffe00000) >> 21);
+ INT32 exponent = ((id.i[BYTE_XOR_BE(0)] & 0x7ff00000) >> 20) - 1023;
+
+ // if we're too small, map to 0
+ if (exponent < -128)
+ {
+ set_mantissa(0);
+ set_exponent(-128);
+ }
+
+ // if we're too large, map to the maximum value
+ else if (exponent > 127)
+ {
+ if ((INT32)id.i[BYTE_XOR_BE(0)] >= 0)
+ set_mantissa(0x7fffffff);
+ else
+ set_mantissa(0x80000001);
+ set_exponent(127);
+ }
+
+ // if we're positive, map directly
+ else if ((INT32)id.i[BYTE_XOR_BE(0)] >= 0)
+ {
+ set_mantissa(mantissa);
+ set_exponent(exponent);
+ }
+
+ // if we're negative with a non-zero mantissa, remove the leading sign bit
+ else if (mantissa != 0)
+ {
+ set_mantissa(0x80000000 | -mantissa);
+ set_exponent(exponent);
+ }
+
+ // if we're negative with a zero mantissa, normalize
+ else
+ {
+ set_mantissa(0x80000000);
+ set_exponent(exponent - 1);
+ }
+}
+
+
+
+//**************************************************************************
+// DEVICE INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// tms3203x_device - constructor
+//-------------------------------------------------
+
+tms3203x_device::tms3203x_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT32 chiptype, address_map_constructor internal_map)
+ : cpu_device(mconfig, type, name, tag, owner, clock),
+ m_program_config("program", ENDIANNESS_LITTLE, 32, 24, -2, internal_map),
+ m_chip_type(chiptype),
+ m_pc(0),
+ m_bkmask(0),
+ m_irq_state(0),
+ m_delayed(false),
+ m_irq_pending(false),
+ m_mcu_mode(false),
+ m_is_idling(false),
+ m_icount(0),
+ m_irq_callback(0),
+ m_program(0),
+ m_direct(0)
+{
+ m_bootoffset = 0;
+ m_xf0_w = NULL;
+ m_xf1_w = NULL;
+ m_iack_w = NULL;
+
+ // initialize remaining state
+ memset(&m_r, 0, sizeof(m_r));
+
+ // set our instruction counter
+ m_icountptr = &m_icount;
+
+#if (TMS_3203X_LOG_OPCODE_USAGE)
+ memset(m_hits, 0, sizeof(m_hits));
+#endif
+}
+
+tms32031_device::tms32031_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : tms3203x_device(mconfig, TMS32031, "TMS32031", tag, owner, clock, CHIP_TYPE_TMS32031, ADDRESS_MAP_NAME(internal_32031)) { }
+
+tms32032_device::tms32032_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : tms3203x_device(mconfig, TMS32032, "TMS32032", tag, owner, clock, CHIP_TYPE_TMS32032, ADDRESS_MAP_NAME(internal_32032)) { }
+
+
+//-------------------------------------------------
+// ~tms3203x_device - destructor
+//-------------------------------------------------
+
+tms3203x_device::~tms3203x_device()
+{
+#if (TMS_3203X_LOG_OPCODE_USAGE)
+ for (int i = 0; i < ARRAY_LENGTH(m_hits); i++)
+ if (m_hits[i] != 0)
+ printf("%10d - %03X.%X\n", m_hits[i], i / 4, i % 4);
+#endif
+}
+
+
+//-------------------------------------------------
+// static_set_config - set the configuration
+// structure
+//-------------------------------------------------
+
+void tms3203x_device::static_set_config(device_t &device, const tms3203x_config &config)
+{
+ tms3203x_device &tms = downcast<tms3203x_device &>(device);
+ static_cast<tms3203x_config &>(tms) = config;
+}
+
+
+//-------------------------------------------------
+// ROPCODE - fetch an opcode
+//-------------------------------------------------
+
+inline UINT32 tms3203x_device::ROPCODE(offs_t pc)
+{
+ return m_direct->read_decrypted_dword(pc << 2);
+}
+
+
+//-------------------------------------------------
+// RMEM - read memory
+//-------------------------------------------------
+
+inline UINT32 tms3203x_device::RMEM(offs_t addr)
+{
+ return m_program->read_dword(addr << 2);
+}
+
+
+//-------------------------------------------------
+// WMEM - write memory
+//-------------------------------------------------
+
+inline void tms3203x_device::WMEM(offs_t addr, UINT32 data)
+{
+ m_program->write_dword(addr << 2, data);
+}
+
+
+//-------------------------------------------------
+// device_start - start up the device
+//-------------------------------------------------
+
+void tms3203x_device::device_start()
+{
+ // find address spaces
+ m_program = space(AS_PROGRAM);
+ m_direct = &m_program->direct();
+
+ // save state
+ save_item(NAME(m_pc));
+ for (int regnum = 0; regnum < 36; regnum++)
+ save_item(NAME(m_r[regnum].i32), regnum);
+ save_item(NAME(m_bkmask));
+ save_item(NAME(m_irq_state));
+ save_item(NAME(m_delayed));
+ save_item(NAME(m_irq_pending));
+ save_item(NAME(m_mcu_mode));
+ save_item(NAME(m_is_idling));
+
+ // register our state for the debugger
+ state_add(TMS3203X_PC, "PC", m_pc);
+ state_add(STATE_GENPC, "GENPC", m_pc).noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_r[TMR_ST].i32[0]).mask(0xff).noshow().formatstr("%8s");
+ state_add(TMS3203X_R0, "R0", m_r[TMR_R0].i32[0]);
+ state_add(TMS3203X_R1, "R1", m_r[TMR_R1].i32[0]);
+ state_add(TMS3203X_R2, "R2", m_r[TMR_R2].i32[0]);
+ state_add(TMS3203X_R3, "R3", m_r[TMR_R3].i32[0]);
+ state_add(TMS3203X_R4, "R4", m_r[TMR_R4].i32[0]);
+ state_add(TMS3203X_R5, "R5", m_r[TMR_R5].i32[0]);
+ state_add(TMS3203X_R6, "R6", m_r[TMR_R6].i32[0]);
+ state_add(TMS3203X_R7, "R7", m_r[TMR_R7].i32[0]);
+ state_add(TMS3203X_R0F, "R0F", m_iotemp).callimport().callexport().formatstr("%12s");
+ state_add(TMS3203X_R1F, "R1F", m_iotemp).callimport().callexport().formatstr("%12s");
+ state_add(TMS3203X_R2F, "R2F", m_iotemp).callimport().callexport().formatstr("%12s");
+ state_add(TMS3203X_R3F, "R3F", m_iotemp).callimport().callexport().formatstr("%12s");
+ state_add(TMS3203X_R4F, "R4F", m_iotemp).callimport().callexport().formatstr("%12s");
+ state_add(TMS3203X_R5F, "R5F", m_iotemp).callimport().callexport().formatstr("%12s");
+ state_add(TMS3203X_R6F, "R6F", m_iotemp).callimport().callexport().formatstr("%12s");
+ state_add(TMS3203X_R7F, "R7F", m_iotemp).callimport().callexport().formatstr("%12s");
+ state_add(TMS3203X_AR0, "AR0", m_r[TMR_AR0].i32[0]);
+ state_add(TMS3203X_AR1, "AR1", m_r[TMR_AR1].i32[0]);
+ state_add(TMS3203X_AR2, "AR2", m_r[TMR_AR2].i32[0]);
+ state_add(TMS3203X_AR3, "AR3", m_r[TMR_AR3].i32[0]);
+ state_add(TMS3203X_AR4, "AR4", m_r[TMR_AR4].i32[0]);
+ state_add(TMS3203X_AR5, "AR5", m_r[TMR_AR5].i32[0]);
+ state_add(TMS3203X_AR6, "AR6", m_r[TMR_AR6].i32[0]);
+ state_add(TMS3203X_AR7, "AR7", m_r[TMR_AR7].i32[0]);
+ state_add(TMS3203X_DP, "DP", m_r[TMR_DP].i32[0]).mask(0xff);
+ state_add(TMS3203X_IR0, "IR0", m_r[TMR_IR0].i32[0]);
+ state_add(TMS3203X_IR1, "IR1", m_r[TMR_IR1].i32[0]);
+ state_add(TMS3203X_BK, "BK", m_r[TMR_BK].i32[0]);
+ state_add(TMS3203X_SP, "SP", m_r[TMR_SP].i32[0]);
+ state_add(TMS3203X_ST, "ST", m_r[TMR_ST].i32[0]);
+ state_add(TMS3203X_IE, "IE", m_r[TMR_IE].i32[0]);
+ state_add(TMS3203X_IF, "IF", m_r[TMR_IF].i32[0]);
+ state_add(TMS3203X_IOF, "IOF", m_r[TMR_IOF].i32[0]);
+ state_add(TMS3203X_RS, "RS", m_r[TMR_RS].i32[0]);
+ state_add(TMS3203X_RE, "RE", m_r[TMR_RE].i32[0]);
+ state_add(TMS3203X_RC, "RC", m_r[TMR_RC].i32[0]);
+}
+
+
+//-------------------------------------------------
+// device_reset - reset the device
+//-------------------------------------------------
+
+void tms3203x_device::device_reset()
+{
+ // if we have a config struct, get the boot ROM address
+ if (m_bootoffset != 0)
+ {
+ m_mcu_mode = true;
+ m_pc = boot_loader(m_bootoffset);
+ }
+ else
+ {
+ m_mcu_mode = false;
+ m_pc = RMEM(0);
+ }
+
+ // reset some registers
+ IREG(TMR_IE) = 0;
+ IREG(TMR_IF) = 0;
+ IREG(TMR_ST) = 0;
+ IREG(TMR_IOF) = 0;
+
+ // reset internal stuff
+ m_delayed = m_irq_pending = m_is_idling = false;
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return the configuration
+// of the specified address space, or NULL if
+// the space doesn't exist
+//-------------------------------------------------
+
+const address_space_config *tms3203x_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 tms3203x_device::state_import(const device_state_entry &entry)
+{
+ switch (entry.index())
+ {
+ case TMS3203X_R0F:
+ case TMS3203X_R1F:
+ case TMS3203X_R2F:
+ case TMS3203X_R3F:
+ case TMS3203X_R4F:
+ case TMS3203X_R5F:
+ case TMS3203X_R6F:
+ case TMS3203X_R7F:
+ m_r[TMR_R0 + (entry.index() - TMS3203X_R0F)].from_double(*(float *)&m_iotemp);
+ break;
+
+ default:
+ fatalerror("CPU_IMPORT_STATE(tms3203x) called for unexpected value\n");
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// state_export - export state into the device,
+// before returning it to the caller
+//-------------------------------------------------
+
+void tms3203x_device::state_export(const device_state_entry &entry)
+{
+ switch (entry.index())
+ {
+ case TMS3203X_R0F:
+ case TMS3203X_R1F:
+ case TMS3203X_R2F:
+ case TMS3203X_R3F:
+ case TMS3203X_R4F:
+ case TMS3203X_R5F:
+ case TMS3203X_R6F:
+ case TMS3203X_R7F:
+ *(float *)&m_iotemp = m_r[TMR_R0 + (entry.index() - TMS3203X_R0F)].as_float();
+ break;
+
+ default:
+ fatalerror("CPU_IMPORT_STATE(tms3203x) called for unexpected value\n");
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// state_string_export - export state as a string
+// for the debugger
+//-------------------------------------------------
+
+void tms3203x_device::state_string_export(const device_state_entry &entry, astring &string)
+{
+ switch (entry.index())
+ {
+ case TMS3203X_R0F:
+ case TMS3203X_R1F:
+ case TMS3203X_R2F:
+ case TMS3203X_R3F:
+ case TMS3203X_R4F:
+ case TMS3203X_R5F:
+ case TMS3203X_R6F:
+ case TMS3203X_R7F:
+ string.printf("%12g", m_r[TMR_R0 + (entry.index() - TMS3203X_R0F)].as_double());
+ break;
+
+ case STATE_GENFLAGS:
+ UINT32 temp = m_r[TMR_ST].i32[0];
+ string.printf("%c%c%c%c%c%c%c%c",
+ (temp & 0x80) ? 'O':'.',
+ (temp & 0x40) ? 'U':'.',
+ (temp & 0x20) ? 'V':'.',
+ (temp & 0x10) ? 'u':'.',
+ (temp & 0x08) ? 'n':'.',
+ (temp & 0x04) ? 'z':'.',
+ (temp & 0x02) ? 'v':'.',
+ (temp & 0x01) ? 'c':'.');
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// disasm_min_opcode_bytes - return the length
+// of the shortest instruction, in bytes
+//-------------------------------------------------
+
+UINT32 tms3203x_device::disasm_min_opcode_bytes() const
+{
+ return 4;
+}
+
+
+//-------------------------------------------------
+// disasm_max_opcode_bytes - return the length
+// of the longest instruction, in bytes
+//-------------------------------------------------
+
+UINT32 tms3203x_device::disasm_max_opcode_bytes() const
+{
+ return 4;
+}
+
+
+//-------------------------------------------------
+// disasm_disassemble - call the disassembly
+// helper function
+//-------------------------------------------------
+
+offs_t tms3203x_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+{
+ extern CPU_DISASSEMBLE( tms3203x );
+ return CPU_DISASSEMBLE_NAME(tms3203x)(NULL, buffer, pc, oprom, opram, 0);
+}
+
+
+
+//**************************************************************************
+// PUBLIC INTERFACES
+//**************************************************************************
+
+//-------------------------------------------------
+// fp_to_float - convert a 32-bit value from DSP
+// floating-point format a 32-bit IEEE float
+//-------------------------------------------------
+
+float tms3203x_device::fp_to_float(UINT32 floatdata)
+{
+ tmsreg gen(floatdata << 8, (INT32)floatdata >> 24);
+ return gen.as_float();
+}
+
+
+//-------------------------------------------------
+// fp_to_double - convert a 32-bit value from DSP
+// floating-point format a 64-bit IEEE double
+//-------------------------------------------------
+
+double tms3203x_device::fp_to_double(UINT32 floatdata)
+{
+ tmsreg gen(floatdata << 8, (INT32)floatdata >> 24);
+ return gen.as_double();
+}
+
+
+//-------------------------------------------------
+// float_to_fp - convert a 32-bit IEEE float to
+// a 32-bit DSP floating-point value
+//-------------------------------------------------
+
+UINT32 tms3203x_device::float_to_fp(float fval)
+{
+ tmsreg gen(fval);
+ return (gen.exponent() << 24) | ((UINT32)gen.mantissa() >> 8);
+}
+
+
+//-------------------------------------------------
+// double_to_fp - convert a 64-bit IEEE double to
+// a 32-bit DSP floating-point value
+//-------------------------------------------------
+
+UINT32 tms3203x_device::double_to_fp(double dval)
+{
+ tmsreg gen(dval);
+ return (gen.exponent() << 24) | ((UINT32)gen.mantissa() >> 8);
+}
+
+
+
+//**************************************************************************
+// EXECUTION
+//**************************************************************************
+
+//-------------------------------------------------
+// check_irqs - check for pending IRQs and take
+// them if enabled
+//-------------------------------------------------
+
+void tms3203x_device::check_irqs()
+{
+ // determine if we have any live interrupts
+ UINT16 validints = IREG(TMR_IF) & IREG(TMR_IE) & 0x0fff;
+ if (validints == 0 || (IREG(TMR_ST) & GIEFLAG) == 0)
+ return;
+
+ // find the lowest signalled value
+ int whichtrap = 0;
+ for (int i = 0; i < 12; i++)
+ if (validints & (1 << i))
+ {
+ whichtrap = i + 1;
+ break;
+ }
+
+ // no longer idling if we get here
+ m_is_idling = false;
+ if (!m_delayed)
+ {
+ UINT16 intmask = 1 << (whichtrap - 1);
+
+ // bit in IF is cleared when interrupt is taken
+ IREG(TMR_IF) &= ~intmask;
+ trap(whichtrap);
+
+ // after auto-clearing the interrupt bit, we need to re-trigger
+ // level-sensitive interrupts
+ if (m_chip_type == CHIP_TYPE_TMS32031 || (IREG(TMR_ST) & 0x4000) == 0)
+ IREG(TMR_IF) |= m_irq_state & 0x0f;
+ }
+ else
+ m_irq_pending = true;
+}
+
+
+//-------------------------------------------------
+// execute_min_cycles - return minimum number of
+// cycles it takes for one instruction to execute
+//-------------------------------------------------
+
+UINT32 tms3203x_device::execute_min_cycles() const
+{
+ return 1;
+}
+
+
+//-------------------------------------------------
+// execute_max_cycles - return maximum number of
+// cycles it takes for one instruction to execute
+//-------------------------------------------------
+
+UINT32 tms3203x_device::execute_max_cycles() const
+{
+ return 4;
+}
+
+
+//-------------------------------------------------
+// execute_input_lines - return the number of
+// input/interrupt lines
+//-------------------------------------------------
+
+UINT32 tms3203x_device::execute_input_lines() const
+{
+ return 11;
+}
+
+
+//-------------------------------------------------
+// execute_set_input - set input and IRQ lines
+//-------------------------------------------------
+
+void tms3203x_device::execute_set_input(int inputnum, int state)
+{
+ // ignore anything out of range
+ if (inputnum >= 12)
+ return;
+
+ // update the external state
+ UINT16 intmask = 1 << inputnum;
+ if (state == ASSERT_LINE)
+ {
+ m_irq_state |= intmask;
+ IREG(TMR_IF) |= intmask;
+ }
+ else
+ m_irq_state &= ~intmask;
+
+ // external interrupts are level-sensitive on the '31 and can be
+ // configured as such on the '32; in that case, if the external
+ // signal is high, we need to update the value in IF accordingly
+ if (m_chip_type == CHIP_TYPE_TMS32031 || (IREG(TMR_ST) & 0x4000) == 0)
+ IREG(TMR_IF) |= m_irq_state & 0x0f;
+}
+
+
+//-------------------------------------------------
+// execute_run - execute until our icount expires
+//-------------------------------------------------
+
+void tms3203x_device::execute_run()
+{
+ // check IRQs up front
+ check_irqs();
+
+ // if we're idling, just eat the cycles
+ if (m_is_idling)
+ {
+ m_icount = 0;
+ return;
+ }
+
+ // non-debug case
+ if ((machine().debug_flags & DEBUG_FLAG_ENABLED) == 0)
+ {
+ while (m_icount > 0)
+ {
+ if ((IREG(TMR_ST) & RMFLAG) && m_pc == IREG(TMR_RE) + 1)
+ {
+ if ((INT32)--IREG(TMR_RC) >= 0)
+ m_pc = IREG(TMR_RS);
+ else
+ {
+ IREG(TMR_ST) &= ~RMFLAG;
+ if (m_delayed)
+ {
+ m_delayed = false;
+ if (m_irq_pending)
+ {
+ m_irq_pending = false;
+ check_irqs();
+ }
+ }
+ }
+ continue;
+ }
+
+ execute_one();
+ }
+ }
+
+ // debugging case
+ else
+ {
+ while (m_icount > 0)
+ {
+ // watch for out-of-range stack pointers
+ if (IREG(TMR_SP) & 0xff000000)
+ debugger_break(machine());
+ if ((IREG(TMR_ST) & RMFLAG) && m_pc == IREG(TMR_RE) + 1)
+ {
+ if ((INT32)--IREG(TMR_RC) >= 0)
+ m_pc = IREG(TMR_RS);
+ else
+ {
+ IREG(TMR_ST) &= ~RMFLAG;
+ if (m_delayed)
+ {
+ m_delayed = false;
+ if (m_irq_pending)
+ {
+ m_irq_pending = false;
+ check_irqs();
+ }
+ }
+ }
+ continue;
+ }
+
+ debugger_instruction_hook(this, m_pc);
+ execute_one();
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// boot_loader - reset the state of the system
+// by simulating the internal boot loader
+//-------------------------------------------------
+
+UINT32 tms3203x_device::boot_loader(UINT32 boot_rom_addr)
+{
+ // read the size of the data
+ UINT32 bits = RMEM(boot_rom_addr);
+ if (bits != 8 && bits != 16 && bits != 32)
+ return 0;
+ UINT32 datamask = 0xffffffffUL >> (32 - bits);
+ UINT32 advance = 32 / bits;
+ boot_rom_addr += advance;
+
+ // read the control register
+ UINT32 control = RMEM(boot_rom_addr++) & datamask;
+ for (int i = 1; i < advance; i++)
+ control |= (RMEM(boot_rom_addr++) & datamask) << (bits * i);
+
+ // now parse the data
+ UINT32 start_offset = 0;
+ bool first = true;
+ while (1)
+ {
+ // read the length of this section
+ UINT32 len = RMEM(boot_rom_addr++) & datamask;
+ for (int i = 1; i < advance; i++)
+ len |= (RMEM(boot_rom_addr++) & datamask) << (bits * i);
+
+ // stop at 0
+ if (len == 0)
+ return start_offset;
+
+ // read the destination offset of this section
+ UINT32 offs = RMEM(boot_rom_addr++) & datamask;
+ for (int i = 1; i < advance; i++)
+ offs |= (RMEM(boot_rom_addr++) & datamask) << (bits * i);
+
+ // if this is the first block, that's where we boot to
+ if (first)
+ {
+ start_offset = offs;
+ first = false;
+ }
+
+ // now copy the data
+ while (len--)
+ {
+ // extract the 32-bit word
+ UINT32 data = RMEM(boot_rom_addr++) & datamask;
+ for (int i = 1; i < advance; i++)
+ data |= (RMEM(boot_rom_addr++) & datamask) << (bits * i);
+
+ // write it out
+ WMEM(offs++, data);
+ }
+ }
+}
+
+
+//**************************************************************************
+// CORE OPCODES
+//**************************************************************************
+
+#include "32031ops.c"
diff --git a/trunk/src/emu/cpu/tms32031/tms32031.h b/trunk/src/emu/cpu/tms32031/tms32031.h
new file mode 100644
index 00000000000..d34a122b544
--- /dev/null
+++ b/trunk/src/emu/cpu/tms32031/tms32031.h
@@ -0,0 +1,848 @@
+/***************************************************************************
+
+ tms32031.h
+
+ TMS32031/2 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 __TMS32031_H__
+#define __TMS32031_H__
+
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define TMS_3203X_LOG_OPCODE_USAGE (0)
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// interrupts
+const int TMS3203X_IRQ0 = 0; // IRQ0
+const int TMS3203X_IRQ1 = 1; // IRQ1
+const int TMS3203X_IRQ2 = 2; // IRQ2
+const int TMS3203X_IRQ3 = 3; // IRQ3
+const int TMS3203X_XINT0 = 4; // serial 0 transmit interrupt
+const int TMS3203X_RINT0 = 5; // serial 0 receive interrupt
+const int TMS3203X_XINT1 = 6; // serial 1 transmit interrupt
+const int TMS3203X_RINT1 = 7; // serial 1 receive interrupt
+const int TMS3203X_TINT0 = 8; // timer 0 interrupt
+const int TMS3203X_TINT1 = 9; // timer 1 interrupt
+const int TMS3203X_DINT = 10; // DMA interrupt
+const int TMS3203X_DINT0 = 10; // DMA 0 interrupt (32032 only)
+const int TMS3203X_DINT1 = 11; // DMA 1 interrupt (32032 only)
+
+// register enumeration
+enum
+{
+ TMS3203X_PC=1,
+ TMS3203X_R0,
+ TMS3203X_R1,
+ TMS3203X_R2,
+ TMS3203X_R3,
+ TMS3203X_R4,
+ TMS3203X_R5,
+ TMS3203X_R6,
+ TMS3203X_R7,
+ TMS3203X_R0F,
+ TMS3203X_R1F,
+ TMS3203X_R2F,
+ TMS3203X_R3F,
+ TMS3203X_R4F,
+ TMS3203X_R5F,
+ TMS3203X_R6F,
+ TMS3203X_R7F,
+ TMS3203X_AR0,
+ TMS3203X_AR1,
+ TMS3203X_AR2,
+ TMS3203X_AR3,
+ TMS3203X_AR4,
+ TMS3203X_AR5,
+ TMS3203X_AR6,
+ TMS3203X_AR7,
+ TMS3203X_DP,
+ TMS3203X_IR0,
+ TMS3203X_IR1,
+ TMS3203X_BK,
+ TMS3203X_SP,
+ TMS3203X_ST,
+ TMS3203X_IE,
+ TMS3203X_IF,
+ TMS3203X_IOF,
+ TMS3203X_RS,
+ TMS3203X_RE,
+ TMS3203X_RC
+};
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_TMS3203X_CONFIG(_config) \
+ tms3203x_device::static_set_config(*device, _config); \
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class tms3203x_device;
+
+// I/O callback types
+typedef void (*tms3203x_xf_func)(tms3203x_device &device, UINT8 val);
+typedef void (*tms3203x_iack_func)(tms3203x_device &device, UINT8 val, offs_t address);
+
+
+// ======================> tms3203x_config
+
+struct tms3203x_config
+{
+ UINT32 m_bootoffset;
+ tms3203x_xf_func m_xf0_w;
+ tms3203x_xf_func m_xf1_w;
+ tms3203x_iack_func m_iack_w;
+};
+
+
+
+// ======================> tms3203x_device
+
+class tms3203x_device : public cpu_device,
+ public tms3203x_config
+{
+ struct tmsreg
+ {
+ // constructors
+ tmsreg() { i32[0] = i32[1] = 0; }
+ tmsreg(double value) { from_double(value); }
+ tmsreg(INT32 mantissa, INT8 exponent) { set_mantissa(mantissa); set_exponent(exponent); }
+
+ // getters
+ UINT32 integer() const { return i32[0]; }
+ INT32 mantissa() const { return i32[0]; }
+ INT8 exponent() const { return i32[1]; }
+ void set_mantissa(INT32 man) { i32[0] = man; }
+ void set_exponent(INT8 exp) { i32[1] = exp; }
+
+ // exporters
+ float as_float() const;
+ double as_double() const;
+
+ // importers
+ void from_double(double);
+
+ UINT32 i32[2];
+ };
+
+protected:
+ enum
+ {
+ CHIP_TYPE_TMS32031,
+ CHIP_TYPE_TMS32032,
+ };
+
+ // construction/destruction
+ tms3203x_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT32 chiptype, address_map_constructor internal_map);
+ virtual ~tms3203x_device();
+
+public:
+ // inline configuration helpers
+ static void static_set_config(device_t &device, const tms3203x_config &config);
+
+ // public interfaces
+ static float fp_to_float(UINT32 floatdata);
+ static double fp_to_double(UINT32 floatdata);
+ static UINT32 float_to_fp(float fval);
+ static UINT32 double_to_fp(double dval);
+
+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 helpers
+ UINT32 ROPCODE(offs_t pc);
+ UINT32 RMEM(offs_t addr);
+ void WMEM(offs_t addr, UINT32 data);
+
+ // misc helpers
+ void check_irqs();
+ UINT32 boot_loader(UINT32 boot_rom_addr);
+ void execute_one();
+ void update_special(int dreg);
+ bool condition(int which);
+
+ // floating point helpers
+ void double_to_dsp_with_flags(double val, tmsreg &result);
+ void int2float(tmsreg &srcdst);
+ void float2int(tmsreg &srcdst, bool setflags);
+ void negf(tmsreg &dst, tmsreg &src);
+ void addf(tmsreg &dst, tmsreg &src1, tmsreg &src2);
+ void subf(tmsreg &dst, tmsreg &src1, tmsreg &src2);
+ void mpyf(tmsreg &dst, tmsreg &src1, tmsreg &src2);
+ void norm(tmsreg &dst, tmsreg &src);
+
+ // memory addressing
+ UINT32 mod00_d(UINT32 op, UINT8 ar);
+ UINT32 mod01_d(UINT32 op, UINT8 ar);
+ UINT32 mod02_d(UINT32 op, UINT8 ar);
+ UINT32 mod03_d(UINT32 op, UINT8 ar);
+ UINT32 mod04_d(UINT32 op, UINT8 ar);
+ UINT32 mod05_d(UINT32 op, UINT8 ar);
+ UINT32 mod06_d(UINT32 op, UINT8 ar);
+ UINT32 mod07_d(UINT32 op, UINT8 ar);
+
+ UINT32 mod00_1(UINT32 op, UINT8 ar);
+ UINT32 mod01_1(UINT32 op, UINT8 ar);
+ UINT32 mod02_1(UINT32 op, UINT8 ar);
+ UINT32 mod03_1(UINT32 op, UINT8 ar);
+ UINT32 mod04_1(UINT32 op, UINT8 ar);
+ UINT32 mod05_1(UINT32 op, UINT8 ar);
+ UINT32 mod06_1(UINT32 op, UINT8 ar);
+ UINT32 mod07_1(UINT32 op, UINT8 ar);
+
+ UINT32 mod08(UINT32 op, UINT8 ar);
+ UINT32 mod09(UINT32 op, UINT8 ar);
+ UINT32 mod0a(UINT32 op, UINT8 ar);
+ UINT32 mod0b(UINT32 op, UINT8 ar);
+ UINT32 mod0c(UINT32 op, UINT8 ar);
+ UINT32 mod0d(UINT32 op, UINT8 ar);
+ UINT32 mod0e(UINT32 op, UINT8 ar);
+ UINT32 mod0f(UINT32 op, UINT8 ar);
+
+ UINT32 mod10(UINT32 op, UINT8 ar);
+ UINT32 mod11(UINT32 op, UINT8 ar);
+ UINT32 mod12(UINT32 op, UINT8 ar);
+ UINT32 mod13(UINT32 op, UINT8 ar);
+ UINT32 mod14(UINT32 op, UINT8 ar);
+ UINT32 mod15(UINT32 op, UINT8 ar);
+ UINT32 mod16(UINT32 op, UINT8 ar);
+ UINT32 mod17(UINT32 op, UINT8 ar);
+
+ UINT32 mod18(UINT32 op, UINT8 ar);
+ UINT32 mod19(UINT32 op, UINT8 ar);
+ UINT32 modillegal(UINT32 op, UINT8 ar);
+
+ UINT32 mod00_1_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+ UINT32 mod01_1_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+ UINT32 mod02_1_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+ UINT32 mod03_1_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+ UINT32 mod04_1_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+ UINT32 mod05_1_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+ UINT32 mod06_1_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+ UINT32 mod07_1_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+
+ UINT32 mod08_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+ UINT32 mod09_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+ UINT32 mod0a_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+ UINT32 mod0b_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+ UINT32 mod0c_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+ UINT32 mod0d_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+ UINT32 mod0e_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+ UINT32 mod0f_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+
+ UINT32 mod10_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+ UINT32 mod11_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+ UINT32 mod12_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+ UINT32 mod13_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+ UINT32 mod14_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+ UINT32 mod15_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+ UINT32 mod16_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+ UINT32 mod17_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+ UINT32 mod18_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+ UINT32 mod19_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+ UINT32 modillegal_def(UINT32 op, UINT8 ar, UINT32 *&defptrptr);
+
+ // instructions
+ void illegal(UINT32 op);
+ void unimplemented(UINT32 op);
+
+ void absf_reg(UINT32 op);
+ void absf_dir(UINT32 op);
+ void absf_ind(UINT32 op);
+ void absf_imm(UINT32 op);
+ void absi_reg(UINT32 op);
+ void absi_dir(UINT32 op);
+ void absi_ind(UINT32 op);
+ void absi_imm(UINT32 op);
+ void addc_reg(UINT32 op);
+ void addc_dir(UINT32 op);
+ void addc_ind(UINT32 op);
+ void addc_imm(UINT32 op);
+ void addf_reg(UINT32 op);
+ void addf_dir(UINT32 op);
+ void addf_ind(UINT32 op);
+ void addf_imm(UINT32 op);
+ void addi_reg(UINT32 op);
+ void addi_dir(UINT32 op);
+ void addi_ind(UINT32 op);
+ void addi_imm(UINT32 op);
+ void and_reg(UINT32 op);
+ void and_dir(UINT32 op);
+ void and_ind(UINT32 op);
+ void and_imm(UINT32 op);
+ void andn_reg(UINT32 op);
+ void andn_dir(UINT32 op);
+ void andn_ind(UINT32 op);
+ void andn_imm(UINT32 op);
+ void ash_reg(UINT32 op);
+ void ash_dir(UINT32 op);
+ void ash_ind(UINT32 op);
+ void ash_imm(UINT32 op);
+ void cmpf_reg(UINT32 op);
+ void cmpf_dir(UINT32 op);
+ void cmpf_ind(UINT32 op);
+ void cmpf_imm(UINT32 op);
+ void cmpi_reg(UINT32 op);
+ void cmpi_dir(UINT32 op);
+ void cmpi_ind(UINT32 op);
+ void cmpi_imm(UINT32 op);
+ void fix_reg(UINT32 op);
+ void fix_dir(UINT32 op);
+ void fix_ind(UINT32 op);
+ void fix_imm(UINT32 op);
+ void float_reg(UINT32 op);
+ void float_dir(UINT32 op);
+ void float_ind(UINT32 op);
+ void float_imm(UINT32 op);
+ void idle(UINT32 op);
+ void lde_reg(UINT32 op);
+ void lde_dir(UINT32 op);
+ void lde_ind(UINT32 op);
+ void lde_imm(UINT32 op);
+ void ldf_reg(UINT32 op);
+ void ldf_dir(UINT32 op);
+ void ldf_ind(UINT32 op);
+ void ldf_imm(UINT32 op);
+ void ldfi_dir(UINT32 op);
+ void ldfi_ind(UINT32 op);
+ void ldi_reg(UINT32 op);
+ void ldi_dir(UINT32 op);
+ void ldi_ind(UINT32 op);
+ void ldi_imm(UINT32 op);
+ void ldii_dir(UINT32 op);
+ void ldii_ind(UINT32 op);
+ void ldm_reg(UINT32 op);
+ void ldm_dir(UINT32 op);
+ void ldm_ind(UINT32 op);
+ void ldm_imm(UINT32 op);
+ void lsh_reg(UINT32 op);
+ void lsh_dir(UINT32 op);
+ void lsh_ind(UINT32 op);
+ void lsh_imm(UINT32 op);
+ void mpyf_reg(UINT32 op);
+ void mpyf_dir(UINT32 op);
+ void mpyf_ind(UINT32 op);
+ void mpyf_imm(UINT32 op);
+ void mpyi_reg(UINT32 op);
+ void mpyi_dir(UINT32 op);
+ void mpyi_ind(UINT32 op);
+ void mpyi_imm(UINT32 op);
+ void negb_reg(UINT32 op);
+ void negb_dir(UINT32 op);
+ void negb_ind(UINT32 op);
+ void negb_imm(UINT32 op);
+ void negf_reg(UINT32 op);
+ void negf_dir(UINT32 op);
+ void negf_ind(UINT32 op);
+ void negf_imm(UINT32 op);
+ void negi_reg(UINT32 op);
+ void negi_dir(UINT32 op);
+ void negi_ind(UINT32 op);
+ void negi_imm(UINT32 op);
+ void nop_reg(UINT32 op);
+ void nop_ind(UINT32 op);
+ void norm_reg(UINT32 op);
+ void norm_dir(UINT32 op);
+ void norm_ind(UINT32 op);
+ void norm_imm(UINT32 op);
+ void not_reg(UINT32 op);
+ void not_dir(UINT32 op);
+ void not_ind(UINT32 op);
+ void not_imm(UINT32 op);
+ void pop(UINT32 op);
+ void popf(UINT32 op);
+ void push(UINT32 op);
+ void pushf(UINT32 op);
+ void or_reg(UINT32 op);
+ void or_dir(UINT32 op);
+ void or_ind(UINT32 op);
+ void or_imm(UINT32 op);
+ void maxspeed(UINT32 op);
+ void rnd_reg(UINT32 op);
+ void rnd_dir(UINT32 op);
+ void rnd_ind(UINT32 op);
+ void rnd_imm(UINT32 op);
+ void rol(UINT32 op);
+ void rolc(UINT32 op);
+ void ror(UINT32 op);
+ void rorc(UINT32 op);
+ void rtps_reg(UINT32 op);
+ void rtps_dir(UINT32 op);
+ void rtps_ind(UINT32 op);
+ void rtps_imm(UINT32 op);
+ void stf_dir(UINT32 op);
+ void stf_ind(UINT32 op);
+ void stfi_dir(UINT32 op);
+ void stfi_ind(UINT32 op);
+ void sti_dir(UINT32 op);
+ void sti_ind(UINT32 op);
+ void stii_dir(UINT32 op);
+ void stii_ind(UINT32 op);
+ void sigi(UINT32 op);
+ void subb_reg(UINT32 op);
+ void subb_dir(UINT32 op);
+ void subb_ind(UINT32 op);
+ void subb_imm(UINT32 op);
+ void subc_reg(UINT32 op);
+ void subc_dir(UINT32 op);
+ void subc_ind(UINT32 op);
+ void subc_imm(UINT32 op);
+ void subf_reg(UINT32 op);
+ void subf_dir(UINT32 op);
+ void subf_ind(UINT32 op);
+ void subf_imm(UINT32 op);
+ void subi_reg(UINT32 op);
+ void subi_dir(UINT32 op);
+ void subi_ind(UINT32 op);
+ void subi_imm(UINT32 op);
+ void subrb_reg(UINT32 op);
+ void subrb_dir(UINT32 op);
+ void subrb_ind(UINT32 op);
+ void subrb_imm(UINT32 op);
+ void subrf_reg(UINT32 op);
+ void subrf_dir(UINT32 op);
+ void subrf_ind(UINT32 op);
+ void subrf_imm(UINT32 op);
+ void subri_reg(UINT32 op);
+ void subri_dir(UINT32 op);
+ void subri_ind(UINT32 op);
+ void subri_imm(UINT32 op);
+ void tstb_reg(UINT32 op);
+ void tstb_dir(UINT32 op);
+ void tstb_ind(UINT32 op);
+ void tstb_imm(UINT32 op);
+ void xor_reg(UINT32 op);
+ void xor_dir(UINT32 op);
+ void xor_ind(UINT32 op);
+ void xor_imm(UINT32 op);
+ void iack_dir(UINT32 op);
+ void iack_ind(UINT32 op);
+ void addc3_regreg(UINT32 op);
+ void addc3_indreg(UINT32 op);
+ void addc3_regind(UINT32 op);
+ void addc3_indind(UINT32 op);
+ void addf3_regreg(UINT32 op);
+ void addf3_indreg(UINT32 op);
+ void addf3_regind(UINT32 op);
+ void addf3_indind(UINT32 op);
+ void addi3_regreg(UINT32 op);
+ void addi3_indreg(UINT32 op);
+ void addi3_regind(UINT32 op);
+ void addi3_indind(UINT32 op);
+ void and3_regreg(UINT32 op);
+ void and3_indreg(UINT32 op);
+ void and3_regind(UINT32 op);
+ void and3_indind(UINT32 op);
+ void andn3_regreg(UINT32 op);
+ void andn3_indreg(UINT32 op);
+ void andn3_regind(UINT32 op);
+ void andn3_indind(UINT32 op);
+ void ash3_regreg(UINT32 op);
+ void ash3_indreg(UINT32 op);
+ void ash3_regind(UINT32 op);
+ void ash3_indind(UINT32 op);
+ void cmpf3_regreg(UINT32 op);
+ void cmpf3_indreg(UINT32 op);
+ void cmpf3_regind(UINT32 op);
+ void cmpf3_indind(UINT32 op);
+ void cmpi3_regreg(UINT32 op);
+ void cmpi3_indreg(UINT32 op);
+ void cmpi3_regind(UINT32 op);
+ void cmpi3_indind(UINT32 op);
+ void lsh3_regreg(UINT32 op);
+ void lsh3_indreg(UINT32 op);
+ void lsh3_regind(UINT32 op);
+ void lsh3_indind(UINT32 op);
+ void mpyf3_regreg(UINT32 op);
+ void mpyf3_indreg(UINT32 op);
+ void mpyf3_regind(UINT32 op);
+ void mpyf3_indind(UINT32 op);
+ void mpyi3_regreg(UINT32 op);
+ void mpyi3_indreg(UINT32 op);
+ void mpyi3_regind(UINT32 op);
+ void mpyi3_indind(UINT32 op);
+ void or3_regreg(UINT32 op);
+ void or3_indreg(UINT32 op);
+ void or3_regind(UINT32 op);
+ void or3_indind(UINT32 op);
+ void subb3_regreg(UINT32 op);
+ void subb3_indreg(UINT32 op);
+ void subb3_regind(UINT32 op);
+ void subb3_indind(UINT32 op);
+ void subf3_regreg(UINT32 op);
+ void subf3_indreg(UINT32 op);
+ void subf3_regind(UINT32 op);
+ void subf3_indind(UINT32 op);
+ void subi3_regreg(UINT32 op);
+ void subi3_indreg(UINT32 op);
+ void subi3_regind(UINT32 op);
+ void subi3_indind(UINT32 op);
+ void tstb3_regreg(UINT32 op);
+ void tstb3_indreg(UINT32 op);
+ void tstb3_regind(UINT32 op);
+ void tstb3_indind(UINT32 op);
+ void xor3_regreg(UINT32 op);
+ void xor3_indreg(UINT32 op);
+ void xor3_regind(UINT32 op);
+ void xor3_indind(UINT32 op);
+ void ldfu_reg(UINT32 op);
+ void ldfu_dir(UINT32 op);
+ void ldfu_ind(UINT32 op);
+ void ldfu_imm(UINT32 op);
+ void ldflo_reg(UINT32 op);
+ void ldflo_dir(UINT32 op);
+ void ldflo_ind(UINT32 op);
+ void ldflo_imm(UINT32 op);
+ void ldfls_reg(UINT32 op);
+ void ldfls_dir(UINT32 op);
+ void ldfls_ind(UINT32 op);
+ void ldfls_imm(UINT32 op);
+ void ldfhi_reg(UINT32 op);
+ void ldfhi_dir(UINT32 op);
+ void ldfhi_ind(UINT32 op);
+ void ldfhi_imm(UINT32 op);
+ void ldfhs_reg(UINT32 op);
+ void ldfhs_dir(UINT32 op);
+ void ldfhs_ind(UINT32 op);
+ void ldfhs_imm(UINT32 op);
+ void ldfeq_reg(UINT32 op);
+ void ldfeq_dir(UINT32 op);
+ void ldfeq_ind(UINT32 op);
+ void ldfeq_imm(UINT32 op);
+ void ldfne_reg(UINT32 op);
+ void ldfne_dir(UINT32 op);
+ void ldfne_ind(UINT32 op);
+ void ldfne_imm(UINT32 op);
+ void ldflt_reg(UINT32 op);
+ void ldflt_dir(UINT32 op);
+ void ldflt_ind(UINT32 op);
+ void ldflt_imm(UINT32 op);
+ void ldfle_reg(UINT32 op);
+ void ldfle_dir(UINT32 op);
+ void ldfle_ind(UINT32 op);
+ void ldfle_imm(UINT32 op);
+ void ldfgt_reg(UINT32 op);
+ void ldfgt_dir(UINT32 op);
+ void ldfgt_ind(UINT32 op);
+ void ldfgt_imm(UINT32 op);
+ void ldfge_reg(UINT32 op);
+ void ldfge_dir(UINT32 op);
+ void ldfge_ind(UINT32 op);
+ void ldfge_imm(UINT32 op);
+ void ldfnv_reg(UINT32 op);
+ void ldfnv_dir(UINT32 op);
+ void ldfnv_ind(UINT32 op);
+ void ldfnv_imm(UINT32 op);
+ void ldfv_reg(UINT32 op);
+ void ldfv_dir(UINT32 op);
+ void ldfv_ind(UINT32 op);
+ void ldfv_imm(UINT32 op);
+ void ldfnuf_reg(UINT32 op);
+ void ldfnuf_dir(UINT32 op);
+ void ldfnuf_ind(UINT32 op);
+ void ldfnuf_imm(UINT32 op);
+ void ldfuf_reg(UINT32 op);
+ void ldfuf_dir(UINT32 op);
+ void ldfuf_ind(UINT32 op);
+ void ldfuf_imm(UINT32 op);
+ void ldfnlv_reg(UINT32 op);
+ void ldfnlv_dir(UINT32 op);
+ void ldfnlv_ind(UINT32 op);
+ void ldfnlv_imm(UINT32 op);
+ void ldflv_reg(UINT32 op);
+ void ldflv_dir(UINT32 op);
+ void ldflv_ind(UINT32 op);
+ void ldflv_imm(UINT32 op);
+ void ldfnluf_reg(UINT32 op);
+ void ldfnluf_dir(UINT32 op);
+ void ldfnluf_ind(UINT32 op);
+ void ldfnluf_imm(UINT32 op);
+ void ldfluf_reg(UINT32 op);
+ void ldfluf_dir(UINT32 op);
+ void ldfluf_ind(UINT32 op);
+ void ldfluf_imm(UINT32 op);
+ void ldfzuf_reg(UINT32 op);
+ void ldfzuf_dir(UINT32 op);
+ void ldfzuf_ind(UINT32 op);
+ void ldfzuf_imm(UINT32 op);
+ void ldiu_reg(UINT32 op);
+ void ldiu_dir(UINT32 op);
+ void ldiu_ind(UINT32 op);
+ void ldiu_imm(UINT32 op);
+ void ldilo_reg(UINT32 op);
+ void ldilo_dir(UINT32 op);
+ void ldilo_ind(UINT32 op);
+ void ldilo_imm(UINT32 op);
+ void ldils_reg(UINT32 op);
+ void ldils_dir(UINT32 op);
+ void ldils_ind(UINT32 op);
+ void ldils_imm(UINT32 op);
+ void ldihi_reg(UINT32 op);
+ void ldihi_dir(UINT32 op);
+ void ldihi_ind(UINT32 op);
+ void ldihi_imm(UINT32 op);
+ void ldihs_reg(UINT32 op);
+ void ldihs_dir(UINT32 op);
+ void ldihs_ind(UINT32 op);
+ void ldihs_imm(UINT32 op);
+ void ldieq_reg(UINT32 op);
+ void ldieq_dir(UINT32 op);
+ void ldieq_ind(UINT32 op);
+ void ldieq_imm(UINT32 op);
+ void ldine_reg(UINT32 op);
+ void ldine_dir(UINT32 op);
+ void ldine_ind(UINT32 op);
+ void ldine_imm(UINT32 op);
+ void ldilt_reg(UINT32 op);
+ void ldilt_dir(UINT32 op);
+ void ldilt_ind(UINT32 op);
+ void ldilt_imm(UINT32 op);
+ void ldile_reg(UINT32 op);
+ void ldile_dir(UINT32 op);
+ void ldile_ind(UINT32 op);
+ void ldile_imm(UINT32 op);
+ void ldigt_reg(UINT32 op);
+ void ldigt_dir(UINT32 op);
+ void ldigt_ind(UINT32 op);
+ void ldigt_imm(UINT32 op);
+ void ldige_reg(UINT32 op);
+ void ldige_dir(UINT32 op);
+ void ldige_ind(UINT32 op);
+ void ldige_imm(UINT32 op);
+ void ldinv_reg(UINT32 op);
+ void ldinv_dir(UINT32 op);
+ void ldinv_ind(UINT32 op);
+ void ldinv_imm(UINT32 op);
+ void ldiuf_reg(UINT32 op);
+ void ldiuf_dir(UINT32 op);
+ void ldiuf_ind(UINT32 op);
+ void ldiuf_imm(UINT32 op);
+ void ldinuf_reg(UINT32 op);
+ void ldinuf_dir(UINT32 op);
+ void ldinuf_ind(UINT32 op);
+ void ldinuf_imm(UINT32 op);
+ void ldiv_reg(UINT32 op);
+ void ldiv_dir(UINT32 op);
+ void ldiv_ind(UINT32 op);
+ void ldiv_imm(UINT32 op);
+ void ldinlv_reg(UINT32 op);
+ void ldinlv_dir(UINT32 op);
+ void ldinlv_ind(UINT32 op);
+ void ldinlv_imm(UINT32 op);
+ void ldilv_reg(UINT32 op);
+ void ldilv_dir(UINT32 op);
+ void ldilv_ind(UINT32 op);
+ void ldilv_imm(UINT32 op);
+ void ldinluf_reg(UINT32 op);
+ void ldinluf_dir(UINT32 op);
+ void ldinluf_ind(UINT32 op);
+ void ldinluf_imm(UINT32 op);
+ void ldiluf_reg(UINT32 op);
+ void ldiluf_dir(UINT32 op);
+ void ldiluf_ind(UINT32 op);
+ void ldiluf_imm(UINT32 op);
+ void ldizuf_reg(UINT32 op);
+ void ldizuf_dir(UINT32 op);
+ void ldizuf_ind(UINT32 op);
+ void ldizuf_imm(UINT32 op);
+ void execute_delayed(UINT32 newpc);
+ void br_imm(UINT32 op);
+ void brd_imm(UINT32 op);
+ void call_imm(UINT32 op);
+ void rptb_imm(UINT32 op);
+ void swi(UINT32 op);
+ void brc_reg(UINT32 op);
+ void brcd_reg(UINT32 op);
+ void brc_imm(UINT32 op);
+ void brcd_imm(UINT32 op);
+ void dbc_reg(UINT32 op);
+ void dbcd_reg(UINT32 op);
+ void dbc_imm(UINT32 op);
+ void dbcd_imm(UINT32 op);
+ void callc_reg(UINT32 op);
+ void callc_imm(UINT32 op);
+ void trap(int trapnum);
+ void trapc(UINT32 op);
+ void retic_reg(UINT32 op);
+ void retsc_reg(UINT32 op);
+ void mpyaddf_0(UINT32 op);
+ void mpyaddf_1(UINT32 op);
+ void mpyaddf_2(UINT32 op);
+ void mpyaddf_3(UINT32 op);
+ void mpysubf_0(UINT32 op);
+ void mpysubf_1(UINT32 op);
+ void mpysubf_2(UINT32 op);
+ void mpysubf_3(UINT32 op);
+ void mpyaddi_0(UINT32 op);
+ void mpyaddi_1(UINT32 op);
+ void mpyaddi_2(UINT32 op);
+ void mpyaddi_3(UINT32 op);
+ void mpysubi_0(UINT32 op);
+ void mpysubi_1(UINT32 op);
+ void mpysubi_2(UINT32 op);
+ void mpysubi_3(UINT32 op);
+ void stfstf(UINT32 op);
+ void stisti(UINT32 op);
+ void ldfldf(UINT32 op);
+ void ldildi(UINT32 op);
+ void absfstf(UINT32 op);
+ void absisti(UINT32 op);
+ void addf3stf(UINT32 op);
+ void addi3sti(UINT32 op);
+ void and3sti(UINT32 op);
+ void ash3sti(UINT32 op);
+ void fixsti(UINT32 op);
+ void floatstf(UINT32 op);
+ void ldfstf(UINT32 op);
+ void ldisti(UINT32 op);
+ void lsh3sti(UINT32 op);
+ void mpyf3stf(UINT32 op);
+ void mpyi3sti(UINT32 op);
+ void negfstf(UINT32 op);
+ void negisti(UINT32 op);
+ void notsti(UINT32 op);
+ void or3sti(UINT32 op);
+ void subf3stf(UINT32 op);
+ void subi3sti(UINT32 op);
+ void xor3sti(UINT32 op);
+
+ // configuration
+ const address_space_config m_program_config;
+ UINT32 m_chip_type;
+
+ union int_double
+ {
+ double d;
+ float f[2];
+ UINT32 i[2];
+ };
+
+ // core registers
+ UINT32 m_pc;
+ tmsreg m_r[36];
+ UINT32 m_bkmask;
+
+ // internal stuff
+ UINT16 m_irq_state;
+ bool m_delayed;
+ bool m_irq_pending;
+ bool m_mcu_mode;
+ bool m_is_idling;
+ int m_icount;
+
+ UINT32 m_iotemp;
+ device_irq_callback m_irq_callback;
+ address_space * m_program;
+ direct_read_data * m_direct;
+
+ // tables
+ static void (tms3203x_device::*const s_tms32031ops[])(UINT32 op);
+ static UINT32 (tms3203x_device::*const s_indirect_d[0x20])(UINT32, UINT8);
+ static UINT32 (tms3203x_device::*const s_indirect_1[0x20])(UINT32, UINT8);
+ static UINT32 (tms3203x_device::*const s_indirect_1_def[0x20])(UINT32, UINT8, UINT32 *&);
+
+#if (TMS_3203X_LOG_OPCODE_USAGE)
+ UINT32 m_hits[0x200*4];
+#endif
+};
+
+
+// ======================> tms32031_device
+
+class tms32031_device : public tms3203x_device
+{
+public:
+ // construction/destruction
+ tms32031_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+
+// ======================> tms32032_device
+
+class tms32032_device : public tms3203x_device
+{
+public:
+ // construction/destruction
+ tms32032_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+
+// device type definition
+extern const device_type TMS32031;
+extern const device_type TMS32032;
+
+
+
+#endif /* __TMS32031_H__ */
diff --git a/trunk/src/emu/cpu/tms32051/32051ops.c b/trunk/src/emu/cpu/tms32051/32051ops.c
new file mode 100644
index 00000000000..3643f6d12b0
--- /dev/null
+++ b/trunk/src/emu/cpu/tms32051/32051ops.c
@@ -0,0 +1,1961 @@
+INLINE void PUSH_STACK(tms32051_state *cpustate, UINT16 pc)
+{
+ if (cpustate->pcstack_ptr >= 8)
+ {
+ fatalerror("32051: stack overflow at %04X!\n", cpustate->pc);
+ }
+
+ cpustate->pcstack[cpustate->pcstack_ptr] = pc;
+ cpustate->pcstack_ptr++;
+}
+
+INLINE UINT16 POP_STACK(tms32051_state *cpustate)
+{
+ UINT16 pc;
+ cpustate->pcstack_ptr--;
+ if (cpustate->pcstack_ptr < 0)
+ {
+ fatalerror("32051: stack underflow at %04X!\n", cpustate->pc);
+ }
+
+ pc = cpustate->pcstack[cpustate->pcstack_ptr];
+ return pc;
+}
+
+INLINE INT32 SUB(tms32051_state *cpustate, INT32 a, INT32 b, int shift16)
+{
+ INT64 res = a - b;
+ if (cpustate->st0.ovm) // overflow saturation mode
+ {
+ if ((res & 0x80000000) && ((UINT32)(res >> 32) & 0xffffffff) != 0xffffffff)
+ {
+ res = 0x80000000;
+ }
+ else if (((res & 0x80000000) == 0) && ((UINT32)(res >> 32) & 0xffffffff) != 0)
+ {
+ res = 0x7fffffff;
+ }
+ }
+ else // normal mode, result is not modified
+ {
+ // set OV flag if overflow occurred, this is a sticky flag
+ if (((a) ^ (b)) & ((a) ^ ((INT32)res)) & 0x80000000)
+ {
+ cpustate->st0.ov = 1;
+ }
+ }
+
+ // set carry
+ if (!shift16)
+ {
+ // C is cleared if borrow was generated
+ if (((UINT64)(a) + (UINT64)(~b)) & U64(0x100000000))
+ {
+ cpustate->st1.c = 0;
+ }
+ else
+ {
+ cpustate->st1.c = 1;
+ }
+ }
+ else
+ {
+ // if 16-bit shift, C is cleared if borrow was generated, otherwise C is unaffected
+ if (((UINT64)(a) + (UINT64)(~b)) & U64(0x100000000))
+ {
+ cpustate->st1.c = 0;
+ }
+ }
+
+ return (INT32)(res);
+}
+
+INLINE INT32 ADD(tms32051_state *cpustate, INT32 a, INT32 b, int shift16)
+{
+ INT64 res = a + b;
+ if (cpustate->st0.ovm) // overflow saturation mode
+ {
+ if ((res & 0x80000000) && ((UINT32)(res >> 32) & 0xffffffff) != 0xffffffff)
+ {
+ res = 0x80000000;
+ }
+ else if (((res & 0x80000000) == 0) && ((UINT32)(res >> 32) & 0xffffffff) != 0)
+ {
+ res = 0x7fffffff;
+ }
+ }
+ else // normal mode, result is not modified
+ {
+ // set OV flag if overflow occurred, this is a sticky flag
+ if (((res) ^ (b)) & ((res) ^ (a)) & 0x80000000)
+ {
+ cpustate->st0.ov = 1;
+ }
+ }
+
+ // set carry
+ if (!shift16)
+ {
+ // C is set if carry was generated
+ if (res & U64(0x100000000))
+ {
+ cpustate->st1.c = 1;
+ }
+ else
+ {
+ cpustate->st1.c = 0;
+ }
+ }
+ else
+ {
+ // if 16-bit shift, C is set carry was generated, otherwise C is unaffected
+ if (res & U64(0x100000000))
+ {
+ cpustate->st1.c = 1;
+ }
+ }
+
+ return (INT32)(res);
+}
+
+
+INLINE void UPDATE_AR(tms32051_state *cpustate, int ar, int step)
+{
+ int cenb1 = (cpustate->cbcr >> 3) & 0x1;
+ int car1 = cpustate->cbcr & 0x7;
+ int cenb2 = (cpustate->cbcr >> 7) & 0x1;
+ int car2 = (cpustate->cbcr >> 4) & 0x7;
+
+ if (cenb1 && ar == car1)
+ {
+ // update circular buffer 1
+ if (cpustate->ar[ar] == cpustate->cber1)
+ {
+ cpustate->ar[ar] = cpustate->cbsr1;
+ }
+ else
+ {
+ cpustate->ar[ar] += step;
+ }
+ }
+ else if (cenb2 && ar == car2)
+ {
+ // update circular buffer 2
+ if (cpustate->ar[ar] == cpustate->cber2)
+ {
+ cpustate->ar[ar] = cpustate->cbsr2;
+ }
+ else
+ {
+ cpustate->ar[ar] += step;
+ }
+ }
+ else
+ {
+ cpustate->ar[ar] += step;
+ }
+}
+
+INLINE void UPDATE_ARP(tms32051_state *cpustate, int nar)
+{
+ cpustate->st1.arb = cpustate->st0.arp;
+ cpustate->st0.arp = nar;
+}
+
+static UINT16 GET_ADDRESS(tms32051_state *cpustate)
+{
+ if (cpustate->op & 0x80) // Indirect Addressing
+ {
+ UINT16 ea;
+ int arp = cpustate->st0.arp;
+ int nar = cpustate->op & 0x7;
+
+ ea = cpustate->ar[arp];
+
+ switch ((cpustate->op >> 3) & 0xf)
+ {
+ case 0x0: // * (no operation)
+ {
+ break;
+ }
+ case 0x1: // *, ARn (NAR -> ARP)
+ {
+ UPDATE_ARP(cpustate, nar);
+ break;
+ }
+ case 0x2: // *- ((CurrentAR)-1 -> CurrentAR)
+ {
+ UPDATE_AR(cpustate, arp, -1);
+ break;
+ }
+ case 0x3: // *-, ARn ((CurrentAR)-1 -> CurrentAR, NAR -> ARP)
+ {
+ UPDATE_AR(cpustate, arp, -1);
+ UPDATE_ARP(cpustate, nar);
+ break;
+ }
+ case 0x4: // *+ ((CurrentAR)+1 -> CurrentAR)
+ {
+ UPDATE_AR(cpustate, arp, 1);
+ break;
+ }
+ case 0x5: // *+, ARn ((CurrentAR)+1 -> CurrentAR, NAR -> ARP)
+ {
+ UPDATE_AR(cpustate, arp, 1);
+ UPDATE_ARP(cpustate, nar);
+ break;
+ }
+ case 0xa: // *0- ((CurrentAR) - INDX)
+ {
+ UPDATE_AR(cpustate, arp, -cpustate->indx);
+ break;
+ }
+ case 0xb: // *0-, ARn ((CurrentAR) - INDX -> CurrentAR, NAR -> ARP)
+ {
+ UPDATE_AR(cpustate, arp, -cpustate->indx);
+ UPDATE_ARP(cpustate, nar);
+ break;
+ }
+ case 0xc: // *0+ ((CurrentAR) + INDX -> CurrentAR)
+ {
+ UPDATE_AR(cpustate, arp, cpustate->indx);
+ break;
+ }
+ case 0xd: // *0+, ARn ((CurrentAR) + INDX -> CurrentAR, NAR -> ARP)
+ {
+ UPDATE_AR(cpustate, arp, cpustate->indx);
+ UPDATE_ARP(cpustate, nar);
+ break;
+ }
+
+ default: fatalerror("32051: GET_ADDRESS: unimplemented indirect addressing mode %d at %04X (%04X)\n", (cpustate->op >> 3) & 0xf, cpustate->pc, cpustate->op);
+ }
+
+ return ea;
+ }
+ else // Direct Addressing
+ {
+ return cpustate->st0.dp | (cpustate->op & 0x7f);
+ }
+}
+
+static int GET_ZLVC_CONDITION(tms32051_state *cpustate, int zlvc, int zlvc_mask)
+{
+ int condition = 0;
+
+ if (zlvc_mask & 0x8) // Z-bit
+ {
+ if ((zlvc & 0x8) && (INT32)(cpustate->acc) == 0) // EQ
+ {
+ condition = 1;
+ }
+ else if ((zlvc & 0x8) == 0 && (INT32)(cpustate->acc) != 0) // NEQ
+ {
+ condition = 1;
+ }
+ }
+ if (zlvc_mask & 0x4) // L-bit
+ {
+ if ((zlvc & 0x4) && (INT32)(cpustate->acc) < 0) // LT
+ {
+ condition = 1;
+ }
+ else if ((zlvc & 0x4) == 0 && (INT32)(cpustate->acc) > 0) // GT
+ {
+ condition = 1;
+ }
+ }
+ if (zlvc_mask & 0x2) // OV-bit
+ {
+ if ((zlvc & 0x2) && cpustate->st0.ov) // OV
+ {
+ condition = 1;
+ }
+ else if ((zlvc & 0x2) == 0 && cpustate->st0.ov == 0) // NOV
+ {
+ condition = 1;
+ }
+ }
+ if (zlvc_mask & 0x1) // C-bit
+ {
+ if ((zlvc & 0x1) && cpustate->st1.c) // C
+ {
+ condition = 1;
+ }
+ else if ((zlvc & 0x1) == 0 && cpustate->st1.c == 0) // NC
+ {
+ condition = 1;
+ }
+ }
+
+ return condition;
+}
+
+static int GET_TP_CONDITION(tms32051_state *cpustate, int tp)
+{
+ switch (tp)
+ {
+ case 0: // BIO pin low
+ {
+ // TODO
+ return 0;
+ }
+ case 1: // TC = 1
+ {
+ return (cpustate->st1.tc == 1) ? 1 : 0;
+ }
+ case 2: // TC = 0
+ {
+ return (cpustate->st1.tc == 0) ? 1 : 0;
+ }
+ case 3: // always false
+ {
+ return 0;
+ }
+ }
+ return 0;
+}
+
+INLINE INT32 PREG_PSCALER(tms32051_state *cpustate, INT32 preg)
+{
+ switch (cpustate->st1.pm & 3)
+ {
+ case 0: // No shift
+ {
+ return preg;
+ }
+ case 1: // Left-shifted 1 bit, LSB zero-filled
+ {
+ return preg << 1;
+ }
+ case 2: // Left-shifted 4 bits, 4 LSBs zero-filled
+ {
+ return preg << 4;
+ }
+ case 3: // Right-shifted 6 bits, sign-extended, 6 LSBs lost
+ {
+ return (INT32)(preg >> 6);
+ }
+ }
+ return 0;
+}
+
+
+
+static void op_invalid(tms32051_state *cpustate)
+{
+ fatalerror("32051: invalid op at %08X", cpustate->pc-1);
+}
+
+static void op_group_be(tms32051_state *cpustate);
+static void op_group_bf(tms32051_state *cpustate);
+
+/*****************************************************************************/
+
+static void op_abs(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op abs at %08X", cpustate->pc-1);
+}
+
+static void op_adcb(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op adcb at %08X", cpustate->pc-1);
+}
+
+static void op_add_mem(tms32051_state *cpustate)
+{
+ INT32 d;
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 data = DM_READ16(cpustate, ea);
+ int shift = (cpustate->op >> 8) & 0xf;
+
+ if (cpustate->st1.sxm)
+ {
+ d = (INT32)(INT16)(data) << shift;
+ }
+ else
+ {
+ d = (UINT32)(UINT16)(data) << shift;
+ }
+
+ cpustate->acc = ADD(cpustate, cpustate->acc, d, 0);
+
+ CYCLES(1);
+}
+
+static void op_add_simm(tms32051_state *cpustate)
+{
+ UINT16 imm = cpustate->op & 0xff;
+
+ cpustate->acc = ADD(cpustate, cpustate->acc, imm, 0);
+
+ CYCLES(1);
+}
+
+static void op_add_limm(tms32051_state *cpustate)
+{
+ INT32 d;
+ UINT16 imm = ROPCODE(cpustate);
+ int shift = cpustate->op & 0xf;
+
+ if (cpustate->st1.sxm)
+ {
+ d = (INT32)(INT16)(imm) << shift;
+ }
+ else
+ {
+ d = (UINT32)(UINT16)(imm) << shift;
+ }
+
+ cpustate->acc = ADD(cpustate, cpustate->acc, d, 0);
+
+ CYCLES(2);
+}
+
+static void op_add_s16_mem(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op add s16 mem at %08X", cpustate->pc-1);
+}
+
+static void op_addb(tms32051_state *cpustate)
+{
+ cpustate->acc = ADD(cpustate, cpustate->acc, cpustate->accb, 0);
+
+ CYCLES(1);
+}
+
+static void op_addc(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op addc at %08X", cpustate->pc-1);
+}
+
+static void op_adds(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op adds at %08X", cpustate->pc-1);
+}
+
+static void op_addt(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op addt at %08X", cpustate->pc-1);
+}
+
+static void op_and_mem(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op and mem at %08X", cpustate->pc-1);
+}
+
+static void op_and_limm(tms32051_state *cpustate)
+{
+ UINT32 imm = ROPCODE(cpustate);
+ int shift = cpustate->op & 0xf;
+
+ cpustate->acc &= imm << shift;
+
+ CYCLES(2);
+}
+
+static void op_and_s16_limm(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op and s16 limm at %08X", cpustate->pc-1);
+}
+
+static void op_andb(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op andb at %08X", cpustate->pc-1);
+}
+
+static void op_bsar(tms32051_state *cpustate)
+{
+ int shift = (cpustate->op & 0xf) + 1;
+
+ if (cpustate->st1.sxm)
+ {
+ cpustate->acc = (INT32)(cpustate->acc) >> shift;
+ }
+ else
+ {
+ cpustate->acc = (UINT32)(cpustate->acc) >> shift;
+ }
+
+ CYCLES(1);
+}
+
+static void op_cmpl(tms32051_state *cpustate)
+{
+ cpustate->acc = ~cpustate->acc;
+
+ CYCLES(1);
+}
+
+static void op_crgt(tms32051_state *cpustate)
+{
+ if (cpustate->acc > cpustate->accb)
+ {
+ cpustate->accb = cpustate->acc;
+ cpustate->st1.c = 1;
+ }
+ else if (cpustate->acc < cpustate->accb)
+ {
+ cpustate->acc = cpustate->accb;
+ cpustate->st1.c = 0;
+ }
+ else
+ {
+ cpustate->st1.c = 1;
+ }
+
+ CYCLES(1);
+}
+
+static void op_crlt(tms32051_state *cpustate)
+{
+ if (cpustate->acc < cpustate->accb)
+ {
+ cpustate->accb = cpustate->acc;
+ cpustate->st1.c = 1;
+ }
+ else if (cpustate->acc > cpustate->accb)
+ {
+ cpustate->acc = cpustate->accb;
+ cpustate->st1.c = 0;
+ }
+ else
+ {
+ cpustate->st1.c = 0;
+ }
+
+ CYCLES(1);
+}
+
+static void op_exar(tms32051_state *cpustate)
+{
+ INT32 tmp = cpustate->acc;
+ cpustate->acc = cpustate->accb;
+ cpustate->accb = tmp;
+
+ CYCLES(1);
+}
+
+static void op_lacb(tms32051_state *cpustate)
+{
+ cpustate->acc = cpustate->accb;
+
+ CYCLES(1);
+}
+
+static void op_lacc_mem(tms32051_state *cpustate)
+{
+ int shift = (cpustate->op >> 8) & 0xf;
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 data = DM_READ16(cpustate, ea);
+
+ if (cpustate->st1.sxm)
+ {
+ cpustate->acc = (INT32)(INT16)(data) << shift;
+ }
+ else
+ {
+ cpustate->acc = (UINT32)(UINT16)(data) << shift;
+ }
+
+ CYCLES(1);
+}
+
+static void op_lacc_limm(tms32051_state *cpustate)
+{
+ UINT16 imm = ROPCODE(cpustate);
+ int shift = cpustate->op & 0xf;
+
+ if (cpustate->st1.sxm)
+ {
+ cpustate->acc = (INT32)(INT16)(imm) << shift;
+ }
+ else
+ {
+ cpustate->acc = (UINT32)(UINT16)(imm) << shift;
+ }
+
+ CYCLES(1);
+}
+
+static void op_lacc_s16_mem(tms32051_state *cpustate)
+{
+ UINT16 ea = GET_ADDRESS(cpustate);
+
+ if (cpustate->st1.sxm)
+ {
+ cpustate->acc = (INT32)(INT16)(DM_READ16(cpustate, ea)) << 16;
+ }
+ else
+ {
+ cpustate->acc = (UINT32)(DM_READ16(cpustate, ea)) << 16;
+ }
+
+ CYCLES(1);
+}
+
+static void op_lacl_simm(tms32051_state *cpustate)
+{
+ cpustate->acc = cpustate->op & 0xff;
+
+ CYCLES(1);
+}
+
+static void op_lacl_mem(tms32051_state *cpustate)
+{
+ UINT16 ea = GET_ADDRESS(cpustate);
+ cpustate->acc = DM_READ16(cpustate, ea) & 0xffff;
+
+ CYCLES(1);
+}
+
+static void op_lact(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op lact at %08X", cpustate->pc-1);
+}
+
+static void op_lamm(tms32051_state *cpustate)
+{
+ UINT16 ea = GET_ADDRESS(cpustate);
+ ea &= 0x7f;
+
+ cpustate->acc = DM_READ16(cpustate, ea) & 0xffff;
+ CYCLES(1);
+}
+
+static void op_neg(tms32051_state *cpustate)
+{
+ if ((UINT32)(cpustate->acc) == 0x80000000)
+ {
+ cpustate->st0.ov = 1;
+ if (cpustate->st0.ovm)
+ {
+ cpustate->acc = 0x7fffffff;
+ }
+ else
+ {
+ cpustate->acc = 0x80000000;
+ }
+ }
+ else
+ {
+ cpustate->acc = 0 - (UINT32)(cpustate->acc);
+
+ if (cpustate->acc == 0)
+ {
+ cpustate->st1.c = 1;
+ }
+ else
+ {
+ cpustate->st1.c = 0;
+ }
+ }
+
+ CYCLES(1);
+}
+
+static void op_norm(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op norm at %08X", cpustate->pc-1);
+}
+
+static void op_or_mem(tms32051_state *cpustate)
+{
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 data = DM_READ16(cpustate, ea);
+
+ cpustate->acc |= (UINT32)(data);
+
+ CYCLES(1);
+}
+
+static void op_or_limm(tms32051_state *cpustate)
+{
+ UINT32 imm = ROPCODE(cpustate);
+ int shift = cpustate->op & 0xf;
+
+ cpustate->acc |= imm << shift;
+
+ CYCLES(1);
+}
+
+static void op_or_s16_limm(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op or s16 limm at %08X", cpustate->pc-1);
+}
+
+static void op_orb(tms32051_state *cpustate)
+{
+ cpustate->acc |= cpustate->accb;
+
+ CYCLES(1);
+}
+
+static void op_rol(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op rol at %08X", cpustate->pc-1);
+}
+
+static void op_rolb(tms32051_state *cpustate)
+{
+ UINT32 acc = cpustate->acc;
+ UINT32 accb = cpustate->accb;
+ UINT32 c = cpustate->st1.c & 1;
+
+ cpustate->acc = (acc << 1) | ((accb >> 31) & 1);
+ cpustate->accb = (accb << 1) | c;
+ cpustate->st1.c = (acc >> 31) & 1;
+
+ CYCLES(1);
+}
+
+static void op_ror(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op ror at %08X", cpustate->pc-1);
+}
+
+static void op_rorb(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op rorb at %08X", cpustate->pc-1);
+}
+
+static void op_sacb(tms32051_state *cpustate)
+{
+ cpustate->accb = cpustate->acc;
+
+ CYCLES(1);
+}
+
+static void op_sach(tms32051_state *cpustate)
+{
+ UINT16 ea = GET_ADDRESS(cpustate);
+ int shift = (cpustate->op >> 8) & 0x7;
+
+ DM_WRITE16(cpustate, ea, (UINT16)((cpustate->acc << shift) >> 16));
+ CYCLES(1);
+}
+
+static void op_sacl(tms32051_state *cpustate)
+{
+ UINT16 ea = GET_ADDRESS(cpustate);
+ int shift = (cpustate->op >> 8) & 0x7;
+
+ DM_WRITE16(cpustate, ea, (UINT16)(cpustate->acc << shift));
+ CYCLES(1);
+}
+
+static void op_samm(tms32051_state *cpustate)
+{
+ UINT16 ea = GET_ADDRESS(cpustate);
+ ea &= 0x7f;
+
+ DM_WRITE16(cpustate, ea, (UINT16)(cpustate->acc));
+ CYCLES(1);
+}
+
+static void op_sath(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op sath at %08X", cpustate->pc-1);
+}
+
+static void op_satl(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op satl at %08X", cpustate->pc-1);
+}
+
+static void op_sbb(tms32051_state *cpustate)
+{
+ cpustate->acc = SUB(cpustate, cpustate->acc, cpustate->accb, 0);
+
+ CYCLES(1);
+}
+
+static void op_sbbb(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op sbbb at %08X", cpustate->pc-1);
+}
+
+static void op_sfl(tms32051_state *cpustate)
+{
+ cpustate->st1.c = (cpustate->acc >> 31) & 1;
+ cpustate->acc = cpustate->acc << 1;
+
+ CYCLES(1);
+}
+
+static void op_sflb(tms32051_state *cpustate)
+{
+ UINT32 acc = cpustate->acc;
+ UINT32 accb = cpustate->accb;
+
+ cpustate->acc = (acc << 1) | ((accb >> 31) & 1);
+ cpustate->accb = (accb << 1);
+ cpustate->st1.c = (acc >> 31) & 1;
+
+ CYCLES(1);
+}
+
+static void op_sfr(tms32051_state *cpustate)
+{
+ cpustate->st1.c = cpustate->acc & 1;
+
+ if (cpustate->st1.sxm)
+ {
+ cpustate->acc = (INT32)(cpustate->acc) >> 1;
+ }
+ else
+ {
+ cpustate->acc = (UINT32)(cpustate->acc) >> 1;
+ }
+
+ CYCLES(1);
+}
+
+static void op_sfrb(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op sfrb at %08X", cpustate->pc-1);
+}
+
+static void op_sub_mem(tms32051_state *cpustate)
+{
+ INT32 d;
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 data = DM_READ16(cpustate, ea);
+ int shift = (cpustate->op >> 8) & 0xf;
+
+ if (cpustate->st1.sxm)
+ {
+ d = (INT32)(INT16)(data) << shift;
+ }
+ else
+ {
+ d = (UINT32)(UINT16)(data) << shift;
+ }
+
+ cpustate->acc = SUB(cpustate, cpustate->acc, d, 0);
+
+ CYCLES(1);
+}
+
+static void op_sub_s16_mem(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op sub s16 mem at %08X", cpustate->pc-1);
+}
+
+static void op_sub_simm(tms32051_state *cpustate)
+{
+ UINT16 imm = cpustate->op & 0xff;
+
+ cpustate->acc = SUB(cpustate, cpustate->acc, imm, 0);
+
+ CYCLES(1);
+}
+
+static void op_sub_limm(tms32051_state *cpustate)
+{
+ INT32 d;
+ UINT16 imm = ROPCODE(cpustate);
+ int shift = cpustate->op & 0xf;
+
+ if (cpustate->st1.sxm)
+ {
+ d = (INT32)(INT16)(imm) << shift;
+ }
+ else
+ {
+ d = (UINT32)(UINT16)(imm) << shift;
+ }
+
+ cpustate->acc = SUB(cpustate, cpustate->acc, d, 0);
+
+ CYCLES(2);
+}
+
+static void op_subb(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op subb at %08X", cpustate->pc-1);
+}
+
+static void op_subc(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op subc at %08X", cpustate->pc-1);
+}
+
+static void op_subs(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op subs at %08X", cpustate->pc-1);
+}
+
+static void op_subt(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op subt at %08X", cpustate->pc-1);
+}
+
+static void op_xor_mem(tms32051_state *cpustate)
+{
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 data = DM_READ16(cpustate, ea);
+
+ cpustate->acc ^= (UINT32)(data);
+
+ CYCLES(1);
+}
+
+static void op_xor_limm(tms32051_state *cpustate)
+{
+ UINT32 imm = ROPCODE(cpustate);
+ int shift = cpustate->op & 0xf;
+
+ cpustate->acc ^= imm << shift;
+
+ CYCLES(1);
+}
+
+static void op_xor_s16_limm(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op xor s16 limm at %08X", cpustate->pc-1);
+}
+
+static void op_xorb(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op xorb at %08X", cpustate->pc-1);
+}
+
+static void op_zalr(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op zalr at %08X", cpustate->pc-1);
+}
+
+static void op_zap(tms32051_state *cpustate)
+{
+ cpustate->acc = 0;
+ cpustate->preg = 0;
+
+ CYCLES(1);
+}
+
+/*****************************************************************************/
+
+static void op_adrk(tms32051_state *cpustate)
+{
+ UINT16 imm = cpustate->op & 0xff;
+ UPDATE_AR(cpustate, cpustate->st0.arp, imm);
+
+ CYCLES(1);
+}
+
+static void op_cmpr(tms32051_state *cpustate)
+{
+ cpustate->st1.tc = 0;
+
+ switch (cpustate->op & 0x3)
+ {
+ case 0: // (CurrentAR) == ARCR
+ {
+ if (cpustate->ar[cpustate->st0.arp] == cpustate->arcr)
+ {
+ cpustate->st1.tc = 1;
+ }
+ break;
+ }
+ case 1: // (CurrentAR) < ARCR
+ {
+ if (cpustate->ar[cpustate->st0.arp] < cpustate->arcr)
+ {
+ cpustate->st1.tc = 1;
+ }
+ break;
+ }
+ case 2: // (CurrentAR) > ARCR
+ {
+ if (cpustate->ar[cpustate->st0.arp] > cpustate->arcr)
+ {
+ cpustate->st1.tc = 1;
+ }
+ break;
+ }
+ case 3: // (CurrentAR) != ARCR
+ {
+ if (cpustate->ar[cpustate->st0.arp] != cpustate->arcr)
+ {
+ cpustate->st1.tc = 1;
+ }
+ break;
+ }
+ }
+
+ CYCLES(1);
+}
+
+static void op_lar_mem(tms32051_state *cpustate)
+{
+ int arx = (cpustate->op >> 8) & 0x7;
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 data = DM_READ16(cpustate, ea);
+
+ cpustate->ar[arx] = data;
+
+ CYCLES(2);
+}
+
+static void op_lar_simm(tms32051_state *cpustate)
+{
+ int arx = (cpustate->op >> 8) & 0x7;
+ cpustate->ar[arx] = cpustate->op & 0xff;
+
+ CYCLES(2);
+}
+
+static void op_lar_limm(tms32051_state *cpustate)
+{
+ int arx = cpustate->op & 0x7;
+ UINT16 imm = ROPCODE(cpustate);
+ cpustate->ar[arx] = imm;
+
+ CYCLES(2);
+}
+
+static void op_ldp_mem(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op ldp mem at %08X", cpustate->pc-1);
+}
+
+static void op_ldp_imm(tms32051_state *cpustate)
+{
+ cpustate->st0.dp = (cpustate->op & 0x1ff) << 7;
+ CYCLES(2);
+}
+
+static void op_mar(tms32051_state *cpustate)
+{
+ // direct addressing is NOP
+ if (cpustate->op & 0x80)
+ {
+ GET_ADDRESS(cpustate);
+ }
+ CYCLES(1);
+}
+
+static void op_sar(tms32051_state *cpustate)
+{
+ int arx = (cpustate->op >> 8) & 0x7;
+ UINT16 ar = cpustate->ar[arx];
+ UINT16 ea = GET_ADDRESS(cpustate);
+ DM_WRITE16(cpustate, ea, ar);
+
+ CYCLES(1);
+}
+
+static void op_sbrk(tms32051_state *cpustate)
+{
+ UINT16 imm = cpustate->op & 0xff;
+ UPDATE_AR(cpustate, cpustate->st0.arp, -imm);
+
+ CYCLES(1);
+}
+
+/*****************************************************************************/
+
+static void op_b(tms32051_state *cpustate)
+{
+ UINT16 pma = ROPCODE(cpustate);
+ GET_ADDRESS(cpustate); // update AR/ARP
+
+ CHANGE_PC(cpustate, pma);
+ CYCLES(4);
+}
+
+static void op_bacc(tms32051_state *cpustate)
+{
+ CHANGE_PC(cpustate, (UINT16)(cpustate->acc));
+
+ CYCLES(4);
+}
+
+static void op_baccd(tms32051_state *cpustate)
+{
+ UINT16 pc = (UINT16)(cpustate->acc);
+
+ delay_slot(cpustate, cpustate->pc);
+ CHANGE_PC(cpustate, pc);
+
+ CYCLES(2);
+}
+
+static void op_banz(tms32051_state *cpustate)
+{
+ UINT16 pma = ROPCODE(cpustate);
+
+ if (cpustate->ar[cpustate->st0.arp] != 0)
+ {
+ CHANGE_PC(cpustate, pma);
+ CYCLES(4);
+ }
+ else
+ {
+ CYCLES(2);
+ }
+
+ GET_ADDRESS(cpustate); // modify AR/ARP
+}
+
+static void op_banzd(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op banzd at %08X", cpustate->pc-1);
+}
+
+static void op_bcnd(tms32051_state *cpustate)
+{
+ UINT16 pma = ROPCODE(cpustate);
+
+ int zlvc_condition = GET_ZLVC_CONDITION(cpustate, (cpustate->op >> 4) & 0xf, cpustate->op & 0xf);
+ int tp_condition = GET_TP_CONDITION(cpustate, (cpustate->op >> 8) & 0x3);
+
+ if (zlvc_condition || tp_condition)
+ {
+ CHANGE_PC(cpustate, pma);
+ CYCLES(4);
+ }
+ else
+ {
+ CYCLES(2);
+ }
+}
+
+static void op_bcndd(tms32051_state *cpustate)
+{
+ UINT16 pma = ROPCODE(cpustate);
+
+ int zlvc_condition = GET_ZLVC_CONDITION(cpustate, (cpustate->op >> 4) & 0xf, cpustate->op & 0xf);
+ int tp_condition = GET_TP_CONDITION(cpustate, (cpustate->op >> 8) & 0x3);
+
+ if (zlvc_condition || tp_condition)
+ {
+ delay_slot(cpustate, cpustate->pc);
+ CHANGE_PC(cpustate, pma);
+ CYCLES(4);
+ }
+ else
+ {
+ CYCLES(2);
+ }
+}
+
+static void op_bd(tms32051_state *cpustate)
+{
+ UINT16 pma = ROPCODE(cpustate);
+ GET_ADDRESS(cpustate); // update AR/ARP
+
+ delay_slot(cpustate, cpustate->pc);
+ CHANGE_PC(cpustate, pma);
+ CYCLES(2);
+}
+
+static void op_cala(tms32051_state *cpustate)
+{
+ PUSH_STACK(cpustate, cpustate->pc);
+
+ CHANGE_PC(cpustate, cpustate->acc);
+
+ CYCLES(4);
+}
+
+static void op_calad(tms32051_state *cpustate)
+{
+ UINT16 pma = cpustate->acc;
+ PUSH_STACK(cpustate, cpustate->pc+2);
+
+ delay_slot(cpustate, cpustate->pc);
+ CHANGE_PC(cpustate, pma);
+
+ CYCLES(4);
+}
+
+static void op_call(tms32051_state *cpustate)
+{
+ UINT16 pma = ROPCODE(cpustate);
+ GET_ADDRESS(cpustate); // update AR/ARP
+ PUSH_STACK(cpustate, cpustate->pc);
+
+ CHANGE_PC(cpustate, pma);
+
+ CYCLES(4);
+}
+
+static void op_calld(tms32051_state *cpustate)
+{
+ UINT16 pma = ROPCODE(cpustate);
+ GET_ADDRESS(cpustate); // update AR/ARP
+ PUSH_STACK(cpustate, cpustate->pc+2);
+
+ delay_slot(cpustate, cpustate->pc);
+ CHANGE_PC(cpustate, pma);
+
+ CYCLES(4);
+}
+
+static void op_cc(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op cc at %08X", cpustate->pc-1);
+}
+
+static void op_ccd(tms32051_state *cpustate)
+{
+ UINT16 pma = ROPCODE(cpustate);
+ int zlvc_condition = GET_ZLVC_CONDITION(cpustate, (cpustate->op >> 4) & 0xf, cpustate->op & 0xf);
+ int tp_condition = GET_TP_CONDITION(cpustate, (cpustate->op >> 8) & 0x3);
+
+ if (zlvc_condition || tp_condition)
+ {
+ PUSH_STACK(cpustate, cpustate->pc+2);
+
+ delay_slot(cpustate, cpustate->pc);
+ CHANGE_PC(cpustate, pma);
+ }
+
+ CYCLES(2);
+}
+
+static void op_intr(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op intr at %08X", cpustate->pc-1);
+}
+
+static void op_nmi(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op nmi at %08X", cpustate->pc-1);
+}
+
+static void op_retc(tms32051_state *cpustate)
+{
+ int condition = 0;
+
+ if ((cpustate->op & 0x3ff) == 0x300) // RET
+ {
+ condition = 1;
+ }
+ else
+ {
+ int zlvc_condition = GET_ZLVC_CONDITION(cpustate, (cpustate->op >> 4) & 0xf, cpustate->op & 0xf);
+ int tp_condition = GET_TP_CONDITION(cpustate, (cpustate->op >> 8) & 0x3);
+ condition = zlvc_condition || tp_condition;
+ }
+
+ if (condition)
+ {
+ UINT16 pc = POP_STACK(cpustate);
+ CHANGE_PC(cpustate, pc);
+ CYCLES(4);
+ }
+ else
+ {
+ CYCLES(2);
+ }
+}
+
+static void op_retcd(tms32051_state *cpustate)
+{
+ int condition = 0;
+
+ if ((cpustate->op & 0x3ff) == 0x300) // RETD
+ {
+ condition = 1;
+ }
+ else
+ {
+ int zlvc_condition = GET_ZLVC_CONDITION(cpustate, (cpustate->op >> 4) & 0xf, cpustate->op & 0xf);
+ int tp_condition = GET_TP_CONDITION(cpustate, (cpustate->op >> 8) & 0x3);
+ condition = zlvc_condition || tp_condition;
+ }
+
+ if (condition)
+ {
+ UINT16 pc = POP_STACK(cpustate);
+ delay_slot(cpustate, cpustate->pc);
+ CHANGE_PC(cpustate, pc);
+ CYCLES(4);
+ }
+ else
+ {
+ CYCLES(2);
+ }
+}
+
+static void op_rete(tms32051_state *cpustate)
+{
+ UINT16 pc = POP_STACK(cpustate);
+ CHANGE_PC(cpustate, pc);
+
+ cpustate->st0.intm = 0;
+
+ restore_interrupt_context(cpustate);
+
+ CYCLES(4);
+}
+
+static void op_reti(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op reti at %08X", cpustate->pc-1);
+}
+
+static void op_trap(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op trap at %08X", cpustate->pc-1);
+}
+
+static void op_xc(tms32051_state *cpustate)
+{
+ int n = ((cpustate->op >> 12) & 0x1) + 1;
+ int zlvc_condition = GET_ZLVC_CONDITION(cpustate, (cpustate->op >> 4) & 0xf, cpustate->op & 0xf);
+ int tp_condition = GET_TP_CONDITION(cpustate, (cpustate->op >> 8) & 0x3);
+
+ if (zlvc_condition || tp_condition)
+ {
+ CYCLES(1);
+ }
+ else
+ {
+ CHANGE_PC(cpustate, cpustate->pc + n);
+ CYCLES(1 + n);
+ }
+}
+
+/*****************************************************************************/
+
+static void op_bldd_slimm(tms32051_state *cpustate)
+{
+ UINT16 pfc = ROPCODE(cpustate);
+
+ while (cpustate->rptc > -1)
+ {
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 data = DM_READ16(cpustate, pfc);
+ DM_WRITE16(cpustate, ea, data);
+ pfc++;
+ CYCLES(2);
+
+ cpustate->rptc--;
+ };
+}
+
+static void op_bldd_dlimm(tms32051_state *cpustate)
+{
+ UINT16 pfc = ROPCODE(cpustate);
+
+ while (cpustate->rptc > -1)
+ {
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 data = DM_READ16(cpustate, ea);
+ DM_WRITE16(cpustate, pfc, data);
+ pfc++;
+ CYCLES(2);
+
+ cpustate->rptc--;
+ };
+}
+
+static void op_bldd_sbmar(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op bldd sbmar at %08X", cpustate->pc-1);
+}
+
+static void op_bldd_dbmar(tms32051_state *cpustate)
+{
+ UINT16 pfc = cpustate->bmar;
+
+ while (cpustate->rptc > -1)
+ {
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 data = DM_READ16(cpustate, ea);
+ DM_WRITE16(cpustate, pfc, data);
+ pfc++;
+ CYCLES(2);
+
+ cpustate->rptc--;
+ };
+}
+
+static void op_bldp(tms32051_state *cpustate)
+{
+ UINT16 pfc = cpustate->bmar;
+
+ while (cpustate->rptc > -1)
+ {
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 data = DM_READ16(cpustate, ea);
+ PM_WRITE16(cpustate, pfc, data);
+ pfc++;
+ CYCLES(1);
+
+ cpustate->rptc--;
+ };
+}
+
+static void op_blpd_bmar(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op bpld bmar at %08X", cpustate->pc-1);
+}
+
+static void op_blpd_imm(tms32051_state *cpustate)
+{
+ UINT16 pfc = ROPCODE(cpustate);
+
+ while (cpustate->rptc > -1)
+ {
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 data = PM_READ16(cpustate, pfc);
+ DM_WRITE16(cpustate, ea, data);
+ pfc++;
+ CYCLES(2);
+
+ cpustate->rptc--;
+ };
+}
+
+/*****************************************************************************/
+
+static void op_dmov(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op dmov at %08X", cpustate->pc-1);
+}
+
+static void op_in(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op in at %08X", cpustate->pc-1);
+}
+
+static void op_lmmr(tms32051_state *cpustate)
+{
+ UINT16 pfc = ROPCODE(cpustate);
+
+ while (cpustate->rptc > -1)
+ {
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 data = DM_READ16(cpustate, pfc);
+ DM_WRITE16(cpustate, ea & 0x7f, data);
+ pfc++;
+ CYCLES(2);
+
+ cpustate->rptc--;
+ };
+}
+
+static void op_out(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op out at %08X", cpustate->pc-1);
+}
+
+static void op_smmr(tms32051_state *cpustate)
+{
+ UINT16 pfc = ROPCODE(cpustate);
+
+ while (cpustate->rptc > -1)
+ {
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 data = DM_READ16(cpustate, ea & 0x7f);
+ DM_WRITE16(cpustate, pfc, data);
+ pfc++;
+ CYCLES(2);
+
+ cpustate->rptc--;
+ };
+}
+
+static void op_tblr(tms32051_state *cpustate)
+{
+ UINT16 pfc = (UINT16)(cpustate->acc);
+
+ while (cpustate->rptc > -1)
+ {
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 data = PM_READ16(cpustate, pfc);
+ DM_WRITE16(cpustate, ea, data);
+ pfc++;
+ CYCLES(2);
+
+ cpustate->rptc--;
+ };
+}
+
+static void op_tblw(tms32051_state *cpustate)
+{
+ UINT16 pfc = (UINT16)(cpustate->acc);
+
+ while (cpustate->rptc > -1)
+ {
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 data = DM_READ16(cpustate, ea);
+ PM_WRITE16(cpustate, pfc, data);
+ pfc++;
+ CYCLES(2);
+
+ cpustate->rptc--;
+ };
+}
+
+/*****************************************************************************/
+
+static void op_apl_dbmr(tms32051_state *cpustate)
+{
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 data = DM_READ16(cpustate, ea);
+ data &= cpustate->dbmr;
+ DM_WRITE16(cpustate, ea, data);
+ CYCLES(1);
+}
+
+static void op_apl_imm(tms32051_state *cpustate)
+{
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 imm = ROPCODE(cpustate);
+ UINT16 data = DM_READ16(cpustate, ea);
+ data &= imm;
+ DM_WRITE16(cpustate, ea, data);
+ CYCLES(1);
+}
+
+static void op_cpl_dbmr(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op cpl dbmr at %08X", cpustate->pc-1);
+}
+
+static void op_cpl_imm(tms32051_state *cpustate)
+{
+ UINT16 imm = ROPCODE(cpustate);
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 data = DM_READ16(cpustate, ea);
+
+ if (data == imm)
+ {
+ cpustate->st1.tc = 1;
+ }
+ else
+ {
+ cpustate->st1.tc = 0;
+ }
+
+ CYCLES(1);
+}
+
+static void op_opl_dbmr(tms32051_state *cpustate)
+{
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 data = DM_READ16(cpustate, ea);
+ data |= cpustate->dbmr;
+ DM_WRITE16(cpustate, ea, data);
+ CYCLES(1);
+}
+
+static void op_opl_imm(tms32051_state *cpustate)
+{
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 imm = ROPCODE(cpustate);
+ UINT16 data = DM_READ16(cpustate, ea);
+ data |= imm;
+ DM_WRITE16(cpustate, ea, data);
+ CYCLES(1);
+}
+
+static void op_splk(tms32051_state *cpustate)
+{
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 imm = ROPCODE(cpustate);
+
+ DM_WRITE16(cpustate, ea, imm);
+
+ CYCLES(2);
+}
+
+static void op_xpl_dbmr(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op xpl dbmr at %08X", cpustate->pc-1);
+}
+
+static void op_xpl_imm(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op xpl imm at %08X", cpustate->pc-1);
+}
+
+static void op_apac(tms32051_state *cpustate)
+{
+ INT32 spreg = PREG_PSCALER(cpustate, cpustate->preg);
+ cpustate->acc = ADD(cpustate, cpustate->acc, spreg, 0);
+
+ CYCLES(1);
+}
+
+static void op_lph(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op lph at %08X", cpustate->pc-1);
+}
+
+static void op_lt(tms32051_state *cpustate)
+{
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 data = DM_READ16(cpustate, ea);
+
+ cpustate->treg0 = data;
+
+ CYCLES(1);
+}
+
+static void op_lta(tms32051_state *cpustate)
+{
+ INT32 spreg;
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 data = DM_READ16(cpustate, ea);
+
+ cpustate->treg0 = data;
+ spreg = PREG_PSCALER(cpustate, cpustate->preg);
+ cpustate->acc = ADD(cpustate, cpustate->acc, spreg, 0);
+
+ CYCLES(1);
+}
+
+static void op_ltd(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op ltd at %08X", cpustate->pc-1);
+}
+
+static void op_ltp(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op ltp at %08X", cpustate->pc-1);
+}
+
+static void op_lts(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op lts at %08X", cpustate->pc-1);
+}
+
+static void op_mac(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op mac at %08X", cpustate->pc-1);
+}
+
+static void op_macd(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op macd at %08X", cpustate->pc-1);
+}
+
+static void op_madd(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op madd at %08X", cpustate->pc-1);
+}
+
+static void op_mads(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op mads at %08X", cpustate->pc-1);
+}
+
+static void op_mpy_mem(tms32051_state *cpustate)
+{
+ UINT16 ea = GET_ADDRESS(cpustate);
+ INT16 data = DM_READ16(cpustate, ea);
+
+ cpustate->preg = (INT32)(data) * (INT32)(INT16)(cpustate->treg0);
+
+ CYCLES(1);
+}
+
+static void op_mpy_simm(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op mpy simm at %08X", cpustate->pc-1);
+}
+
+static void op_mpy_limm(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op mpy limm at %08X", cpustate->pc-1);
+}
+
+static void op_mpya(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op mpya at %08X", cpustate->pc-1);
+}
+
+static void op_mpys(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op mpys at %08X", cpustate->pc-1);
+}
+
+static void op_mpyu(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op mpyu at %08X", cpustate->pc-1);
+}
+
+static void op_pac(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op pac at %08X", cpustate->pc-1);
+}
+
+static void op_spac(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op spac at %08X", cpustate->pc-1);
+}
+
+static void op_sph(tms32051_state *cpustate)
+{
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 spreg = (UINT16)(PREG_PSCALER(cpustate, cpustate->preg) >> 16);
+ DM_WRITE16(cpustate, ea, spreg);
+
+ CYCLES(1);
+}
+
+static void op_spl(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op spl at %08X", cpustate->pc-1);
+}
+
+static void op_spm(tms32051_state *cpustate)
+{
+ cpustate->st1.pm = cpustate->op & 0x3;
+
+ CYCLES(1);
+}
+
+static void op_sqra(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op sqra at %08X", cpustate->pc-1);
+}
+
+static void op_sqrs(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op sqrs at %08X", cpustate->pc-1);
+}
+
+static void op_zpr(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op zpr at %08X", cpustate->pc-1);
+}
+
+static void op_bit(tms32051_state *cpustate)
+{
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 data = DM_READ16(cpustate, ea);
+ int bit = 15 - ((cpustate->op >> 8) & 0xf);
+
+ if (data & (1 << bit))
+ {
+ cpustate->st1.tc = 1;
+ }
+ else
+ {
+ cpustate->st1.tc = 0;
+ }
+
+ CYCLES(1);
+}
+
+static void op_bitt(tms32051_state *cpustate)
+{
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 data = DM_READ16(cpustate, ea);
+ int bit = 15 - (cpustate->treg2 & 0xf);
+
+ if (data & (1 << bit))
+ {
+ cpustate->st1.tc = 1;
+ }
+ else
+ {
+ cpustate->st1.tc = 0;
+ }
+
+ CYCLES(1);
+}
+
+static void op_clrc_ov(tms32051_state *cpustate)
+{
+ cpustate->st0.ovm = 0;
+
+ CYCLES(1);
+}
+
+static void op_clrc_ext(tms32051_state *cpustate)
+{
+ cpustate->st1.sxm = 0;
+
+ CYCLES(1);
+}
+
+static void op_clrc_hold(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op clrc hold at %08X", cpustate->pc-1);
+}
+
+static void op_clrc_tc(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op clrc tc at %08X", cpustate->pc-1);
+}
+
+static void op_clrc_carry(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op clrc carry at %08X", cpustate->pc-1);
+}
+
+static void op_clrc_cnf(tms32051_state *cpustate)
+{
+ cpustate->st1.cnf = 0;
+
+ CYCLES(1);
+}
+
+static void op_clrc_intm(tms32051_state *cpustate)
+{
+ cpustate->st0.intm = 0;
+
+ check_interrupts(cpustate);
+
+ CYCLES(1);
+}
+
+static void op_clrc_xf(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op clrc xf at %08X", cpustate->pc-1);
+}
+
+static void op_idle(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op idle at %08X", cpustate->pc-1);
+}
+
+static void op_idle2(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op idle2 at %08X", cpustate->pc-1);
+}
+
+static void op_lst_st0(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op lst st0 at %08X", cpustate->pc-1);
+}
+
+static void op_lst_st1(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op lst st1 at %08X", cpustate->pc-1);
+}
+
+static void op_pop(tms32051_state *cpustate)
+{
+ cpustate->acc = POP_STACK(cpustate);
+
+ CYCLES(1);
+}
+
+static void op_popd(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op popd at %08X", cpustate->pc-1);
+}
+
+static void op_pshd(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op pshd at %08X", cpustate->pc-1);
+}
+
+static void op_push(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op push at %08X", cpustate->pc-1);
+}
+
+static void op_rpt_mem(tms32051_state *cpustate)
+{
+ UINT16 ea = GET_ADDRESS(cpustate);
+ UINT16 data = DM_READ16(cpustate, ea);
+ cpustate->rptc = data;
+ cpustate->rpt_start = cpustate->pc;
+ cpustate->rpt_end = cpustate->pc;
+
+ CYCLES(1);
+}
+
+static void op_rpt_limm(tms32051_state *cpustate)
+{
+ cpustate->rptc = (UINT16)ROPCODE(cpustate);
+ cpustate->rpt_start = cpustate->pc;
+ cpustate->rpt_end = cpustate->pc;
+
+ CYCLES(2);
+}
+
+static void op_rpt_simm(tms32051_state *cpustate)
+{
+ cpustate->rptc = (cpustate->op & 0xff);
+ cpustate->rpt_start = cpustate->pc;
+ cpustate->rpt_end = cpustate->pc;
+
+ CYCLES(1);
+}
+
+static void op_rptb(tms32051_state *cpustate)
+{
+ UINT16 pma = ROPCODE(cpustate);
+ cpustate->pmst.braf = 1;
+ cpustate->pasr = cpustate->pc;
+ cpustate->paer = pma + 1;
+
+ CYCLES(2);
+}
+
+static void op_rptz(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op rptz at %08X", cpustate->pc-1);
+}
+
+static void op_setc_ov(tms32051_state *cpustate)
+{
+ cpustate->st0.ovm = 1;
+
+ CYCLES(1);
+}
+
+static void op_setc_ext(tms32051_state *cpustate)
+{
+ cpustate->st1.sxm = 1;
+
+ CYCLES(1);
+}
+
+static void op_setc_hold(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op setc hold at %08X", cpustate->pc-1);
+}
+
+static void op_setc_tc(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op setc tc at %08X", cpustate->pc-1);
+}
+
+static void op_setc_carry(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op setc carry at %08X", cpustate->pc-1);
+}
+
+static void op_setc_xf(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op setc xf at %08X", cpustate->pc-1);
+}
+
+static void op_setc_cnf(tms32051_state *cpustate)
+{
+ cpustate->st1.cnf = 1;
+
+ CYCLES(1);
+}
+
+static void op_setc_intm(tms32051_state *cpustate)
+{
+ cpustate->st0.intm = 1;
+
+ check_interrupts(cpustate);
+
+ CYCLES(1);
+}
+
+static void op_sst_st0(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op sst st0 at %08X", cpustate->pc-1);
+}
+
+static void op_sst_st1(tms32051_state *cpustate)
+{
+ fatalerror("32051: unimplemented op sst st1 at %08X", cpustate->pc-1);
+}
diff --git a/trunk/src/emu/cpu/tms32051/32051ops.h b/trunk/src/emu/cpu/tms32051/32051ops.h
new file mode 100644
index 00000000000..9517104f3ef
--- /dev/null
+++ b/trunk/src/emu/cpu/tms32051/32051ops.h
@@ -0,0 +1,251 @@
+static void (*const tms32051_opcode_table[256])(tms32051_state *cpustate) =
+{
+ /* 0x00 - 0x0f */
+ op_lar_mem, op_lar_mem, op_lar_mem, op_lar_mem,
+ op_lar_mem, op_lar_mem, op_lar_mem, op_lar_mem,
+ op_lamm, op_smmr, op_subc, op_rpt_mem,
+ op_out, op_ldp_mem, op_lst_st0, op_lst_st1,
+ /* 0x10 - 0x1f */
+ op_lacc_mem, op_lacc_mem, op_lacc_mem, op_lacc_mem,
+ op_lacc_mem, op_lacc_mem, op_lacc_mem, op_lacc_mem,
+ op_lacc_mem, op_lacc_mem, op_lacc_mem, op_lacc_mem,
+ op_lacc_mem, op_lacc_mem, op_lacc_mem, op_lacc_mem,
+ /* 0x20 - 0x2f */
+ op_add_mem, op_add_mem, op_add_mem, op_add_mem,
+ op_add_mem, op_add_mem, op_add_mem, op_add_mem,
+ op_add_mem, op_add_mem, op_add_mem, op_add_mem,
+ op_add_mem, op_add_mem, op_add_mem, op_add_mem,
+ /* 0x30 - 0x3f */
+ op_sub_mem, op_sub_mem, op_sub_mem, op_sub_mem,
+ op_sub_mem, op_sub_mem, op_sub_mem, op_sub_mem,
+ op_sub_mem, op_sub_mem, op_sub_mem, op_sub_mem,
+ op_sub_mem, op_sub_mem, op_sub_mem, op_sub_mem,
+ /* 0x40 - 0x4f */
+ op_bit, op_bit, op_bit, op_bit,
+ op_bit, op_bit, op_bit, op_bit,
+ op_bit, op_bit, op_bit, op_bit,
+ op_bit, op_bit, op_bit, op_bit,
+ /* 0x50 - 0x5f */
+ op_mpya, op_mpys, op_sqra, op_sqrs,
+ op_mpy_mem, op_mpyu, op_invalid, op_bldp,
+ op_xpl_dbmr, op_opl_dbmr, op_apl_dbmr, op_cpl_dbmr,
+ op_xpl_imm, op_opl_imm, op_apl_imm, op_cpl_imm,
+ /* 0x60 - 0x6f */
+ op_addc, op_add_s16_mem, op_adds, op_addt,
+ op_subb, op_sub_s16_mem, op_subs, op_subt,
+ op_zalr, op_lacl_mem, op_lacc_s16_mem,op_lact,
+ op_xor_mem, op_or_mem, op_and_mem, op_bitt,
+ /* 0x70 - 0x7f */
+ op_lta, op_ltp, op_ltd, op_lt,
+ op_lts, op_lph, op_pshd, op_dmov,
+ op_adrk, op_b, op_call, op_banz,
+ op_sbrk, op_bd, op_calld, op_banzd,
+ /* 0x80 - 0x8f */
+ op_sar, op_sar, op_sar, op_sar,
+ op_sar, op_sar, op_sar, op_sar,
+ op_samm, op_lmmr, op_popd, op_mar,
+ op_spl, op_sph, op_sst_st0, op_sst_st1,
+ /* 0x90 - 0x9f */
+ op_sacl, op_sacl, op_sacl, op_sacl,
+ op_sacl, op_sacl, op_sacl, op_sacl,
+ op_sach, op_sach, op_sach, op_sach,
+ op_sach, op_sach, op_sach, op_sach,
+ /* 0xa0 - 0xaf */
+ op_norm, op_invalid, op_mac, op_macd,
+ op_blpd_bmar, op_blpd_imm, op_tblr, op_tblw,
+ op_bldd_slimm, op_bldd_dlimm, op_mads, op_madd,
+ op_bldd_sbmar, op_bldd_dbmar, op_splk, op_in,
+ /* 0xb0 - 0xbf */
+ op_lar_simm, op_lar_simm, op_lar_simm, op_lar_simm,
+ op_lar_simm, op_lar_simm, op_lar_simm, op_lar_simm,
+ op_add_simm, op_lacl_simm, op_sub_simm, op_rpt_simm,
+ op_ldp_imm, op_ldp_imm, op_group_be, op_group_bf,
+ /* 0xc0 - 0xcf */
+ op_mpy_simm, op_mpy_simm, op_mpy_simm, op_mpy_simm,
+ op_mpy_simm, op_mpy_simm, op_mpy_simm, op_mpy_simm,
+ op_mpy_simm, op_mpy_simm, op_mpy_simm, op_mpy_simm,
+ op_mpy_simm, op_mpy_simm, op_mpy_simm, op_mpy_simm,
+ /* 0xd0 - 0xdf */
+ op_mpy_simm, op_mpy_simm, op_mpy_simm, op_mpy_simm,
+ op_mpy_simm, op_mpy_simm, op_mpy_simm, op_mpy_simm,
+ op_mpy_simm, op_mpy_simm, op_mpy_simm, op_mpy_simm,
+ op_mpy_simm, op_mpy_simm, op_mpy_simm, op_mpy_simm,
+ /* 0xe0 - 0xef */
+ op_bcnd, op_bcnd, op_bcnd, op_bcnd,
+ op_xc, op_xc, op_xc, op_xc,
+ op_cc, op_cc, op_cc, op_cc,
+ op_retc, op_retc, op_retc, op_retc,
+ /* 0xf0 - 0xff */
+ op_bcndd, op_bcndd, op_bcndd, op_bcndd,
+ op_xc, op_xc, op_xc, op_xc,
+ op_ccd, op_ccd, op_ccd, op_ccd,
+ op_retcd, op_retcd, op_retcd, op_retcd
+};
+
+static void (*const tms32051_opcode_table_be[256])(tms32051_state *cpustate) =
+{
+ /* 0x00 - 0x0f */
+ op_abs, op_cmpl, op_neg, op_pac,
+ op_apac, op_spac, op_invalid, op_invalid,
+ op_invalid, op_sfl, op_sfr, op_invalid,
+ op_rol, op_ror, op_invalid, op_invalid,
+ /* 0x10 - 0x1f */
+ op_addb, op_adcb, op_andb, op_orb,
+ op_rolb, op_rorb, op_sflb, op_sfrb,
+ op_sbb, op_sbbb, op_xorb, op_crgt,
+ op_crlt, op_exar, op_sacb, op_lacb,
+ /* 0x20 - 0x2f */
+ op_bacc, op_baccd, op_idle, op_idle2,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ /* 0x30 - 0x3f */
+ op_cala, op_invalid, op_pop, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_reti, op_invalid, op_rete, op_invalid,
+ op_push, op_calad, op_invalid, op_invalid,
+ /* 0x40 - 0x4f */
+ op_clrc_intm, op_setc_intm, op_clrc_ov, op_setc_ov,
+ op_clrc_cnf, op_setc_cnf, op_clrc_ext, op_setc_ext,
+ op_clrc_hold, op_setc_hold, op_clrc_tc, op_setc_tc,
+ op_clrc_xf, op_setc_xf, op_clrc_carry, op_setc_carry,
+ /* 0x50 - 0x5f */
+ op_invalid, op_trap, op_nmi, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_zpr, op_zap, op_sath, op_satl,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ /* 0x60 - 0x6f */
+ op_intr, op_intr, op_intr, op_intr,
+ op_intr, op_intr, op_intr, op_intr,
+ op_intr, op_intr, op_intr, op_intr,
+ op_intr, op_intr, op_intr, op_intr,
+ /* 0x70 - 0x7f */
+ op_intr, op_intr, op_intr, op_intr,
+ op_intr, op_intr, op_intr, op_intr,
+ op_intr, op_intr, op_intr, op_intr,
+ op_intr, op_intr, op_intr, op_intr,
+ /* 0x80 - 0x8f */
+ op_mpy_limm, op_and_s16_limm,op_or_s16_limm, op_xor_s16_limm,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ /* 0x90 - 0x9f */
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ /* 0xa0 - 0xaf */
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ /* 0xb0 - 0xbf */
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ /* 0xc0 - 0xcf */
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_rpt_limm, op_rptz, op_rptb, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ /* 0xd0 - 0xdf */
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ /* 0xe0 - 0xef */
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ /* 0xf0 - 0xff */
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+};
+
+static void (*const tms32051_opcode_table_bf[256])(tms32051_state *cpustate) =
+{
+ /* 0x00 - 0x0f */
+ op_spm, op_spm, op_spm, op_spm,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_lar_limm, op_lar_limm, op_lar_limm, op_lar_limm,
+ op_lar_limm, op_lar_limm, op_lar_limm, op_lar_limm,
+ /* 0x10 - 0x1f */
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ /* 0x20 - 0x2f */
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ /* 0x30 - 0x3f */
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ /* 0x40 - 0x4f */
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_cmpr, op_cmpr, op_cmpr, op_cmpr,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ /* 0x50 - 0x5f */
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ /* 0x60 - 0x6f */
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ /* 0x70 - 0x7f */
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ /* 0x80 - 0x8f */
+ op_lacc_limm, op_lacc_limm, op_lacc_limm, op_lacc_limm,
+ op_lacc_limm, op_lacc_limm, op_lacc_limm, op_lacc_limm,
+ op_lacc_limm, op_lacc_limm, op_lacc_limm, op_lacc_limm,
+ op_lacc_limm, op_lacc_limm, op_lacc_limm, op_lacc_limm,
+ /* 0x90 - 0x9f */
+ op_add_limm, op_add_limm, op_add_limm, op_add_limm,
+ op_add_limm, op_add_limm, op_add_limm, op_add_limm,
+ op_add_limm, op_add_limm, op_add_limm, op_add_limm,
+ op_add_limm, op_add_limm, op_add_limm, op_add_limm,
+ /* 0xa0 - 0xaf */
+ op_sub_limm, op_sub_limm, op_sub_limm, op_sub_limm,
+ op_sub_limm, op_sub_limm, op_sub_limm, op_sub_limm,
+ op_sub_limm, op_sub_limm, op_sub_limm, op_sub_limm,
+ op_sub_limm, op_sub_limm, op_sub_limm, op_sub_limm,
+ /* 0xb0 - 0xbf */
+ op_and_limm, op_and_limm, op_and_limm, op_and_limm,
+ op_and_limm, op_and_limm, op_and_limm, op_and_limm,
+ op_and_limm, op_and_limm, op_and_limm, op_and_limm,
+ op_and_limm, op_and_limm, op_and_limm, op_and_limm,
+ /* 0xc0 - 0xcf */
+ op_or_limm, op_or_limm, op_or_limm, op_or_limm,
+ op_or_limm, op_or_limm, op_or_limm, op_or_limm,
+ op_or_limm, op_or_limm, op_or_limm, op_or_limm,
+ op_or_limm, op_or_limm, op_or_limm, op_or_limm,
+ /* 0xd0 - 0xdf */
+ op_xor_limm, op_xor_limm, op_xor_limm, op_xor_limm,
+ op_xor_limm, op_xor_limm, op_xor_limm, op_xor_limm,
+ op_xor_limm, op_xor_limm, op_xor_limm, op_xor_limm,
+ op_xor_limm, op_xor_limm, op_xor_limm, op_xor_limm,
+ /* 0xe0 - 0xef */
+ op_bsar, op_bsar, op_bsar, op_bsar,
+ op_bsar, op_bsar, op_bsar, op_bsar,
+ op_bsar, op_bsar, op_bsar, op_bsar,
+ op_bsar, op_bsar, op_bsar, op_bsar,
+ /* 0xf0 - 0xff */
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+ op_invalid, op_invalid, op_invalid, op_invalid,
+};
diff --git a/trunk/src/emu/cpu/tms32051/dis32051.c b/trunk/src/emu/cpu/tms32051/dis32051.c
new file mode 100644
index 00000000000..82666e17052
--- /dev/null
+++ b/trunk/src/emu/cpu/tms32051/dis32051.c
@@ -0,0 +1,642 @@
+#include "emu.h"
+
+
+
+static const char *const zl_condition_codes[] =
+{
+ // bit 3, 2 (ZL), bit 1, 0 (MASK)
+ "", // Z=0, L=0, ZM=0, ZL=0
+ "gt", // Z=0, L=0, ZM=0, ZL=1
+ "neq", // Z=0, L=0, ZM=1, ZL=0
+ "gt", // Z=0, L=0, ZM=1, ZL=1
+ "", // Z=0, L=1, ZM=0, ZL=0
+ "lt", // Z=0, L=1, ZM=0, ZL=1
+ "neq", // Z=0, L=1, ZM=1, ZL=0
+ "lt", // Z=0, L=1, ZM=1, ZL=1
+ "", // Z=1, L=0, ZM=0, ZL=0
+ "gt", // Z=1, L=0, ZM=0, ZL=1
+ "eq", // Z=1, L=0, ZM=1, ZL=0
+ "geq", // Z=1, L=0, ZM=1, ZL=1
+ "", // Z=1, L=1, ZM=0, ZL=0
+ "lt", // Z=1, L=1, ZM=0, ZL=1
+ "eq", // Z=1, L=1, ZM=1, ZL=0
+ "leq", // Z=1, L=1, ZM=1, ZL=1
+};
+
+static const char *const cv_condition_codes[16] =
+{
+ "", // C=0, V=0, CM=0, VM=0
+ "nov", // C=0, V=0, CM=0, VM=1
+ "nc", // C=0, V=0, CM=1, VM=0
+ "nc nov", // C=0, V=0, CM=1, VM=1
+ "", // C=0, V=1, CM=0, VM=0
+ "ov", // C=0, V=1, CM=0, VM=1
+ "nc", // C=0, V=1, CM=1, VM=0
+ "nc ov", // C=0, V=1, CM=1, VM=1
+ "", // C=1, V=0, CM=0, VM=0
+ "nov", // C=1, V=0, CM=0, VM=1
+ "c", // C=1, V=0, CM=1, VM=0
+ "c nov", // C=1, V=0, CM=1, VM=1
+ "", // C=1, V=1, CM=0, VM=0
+ "ov", // C=1, V=1, CM=0, VM=1
+ "c", // C=1, V=1, CM=1, VM=0
+ "c ov", // C=1, V=1, CM=1, VM=1
+};
+
+static const char *const tp_condition_codes[4] =
+{
+ "bio",
+ "tc",
+ "ntc",
+ ""
+};
+
+
+static offs_t npc;
+static const UINT8 *rombase;
+static offs_t pcbase;
+
+static char *output;
+
+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 UINT16 FETCH(void)
+{
+ UINT16 result = rombase[(npc - pcbase) * 2 + 0] | (rombase[(npc - pcbase) * 2 + 1] << 8);
+ npc++;
+ return result;
+}
+
+static char *GET_ADDRESS(int addr_mode, int address)
+{
+ static char buffer[100];
+
+ if (addr_mode) // Indirect addressing
+ {
+ int nar = address & 0x7;
+
+
+ switch ((address >> 3) & 0xf)
+ {
+ case 0x0: sprintf(buffer, "*"); break;
+ case 0x1: sprintf(buffer, "*, ar%d", nar); break;
+ case 0x2: sprintf(buffer, "*-"); break;
+ case 0x3: sprintf(buffer, "*-, ar%d", nar); break;
+ case 0x4: sprintf(buffer, "*+"); break;
+ case 0x5: sprintf(buffer, "*+, ar%d", nar); break;
+ case 0x8: sprintf(buffer, "*br0-"); break;
+ case 0x9: sprintf(buffer, "*br0-, ar%d", nar); break;
+ case 0xa: sprintf(buffer, "*0-"); break;
+ case 0xb: sprintf(buffer, "*0-, ar%d", nar); break;
+ case 0xc: sprintf(buffer, "*0+"); break;
+ case 0xd: sprintf(buffer, "*0+, ar%d", nar); break;
+ case 0xe: sprintf(buffer, "*br0+"); break;
+ case 0xf: sprintf(buffer, "*br0+, ar%d", nar); break;
+
+ default: sprintf(buffer, "??? (indirect)"); break;
+ }
+ }
+ else // Direct addressing
+ {
+ sprintf(buffer, "#%02X", address);
+ }
+ return buffer;
+}
+
+static char *GET_SHIFT(int shift)
+{
+ static char buffer[100];
+
+ if (shift > 0)
+ {
+ sprintf(buffer, ", %d", shift);
+ }
+ else
+ {
+ memset(buffer, 0, sizeof(buffer));
+ }
+
+ return buffer;
+}
+
+static void dasm_group_be(UINT16 opcode)
+{
+ int subop = opcode & 0xff;
+
+ switch (subop)
+ {
+ case 0x00: print("abs"); break;
+ case 0x01: print("cmpl"); break;
+ case 0x02: print("neg"); break;
+ case 0x03: print("pac"); break;
+ case 0x04: print("apac"); break;
+ case 0x05: print("spac"); break;
+ case 0x09: print("sfl"); break;
+ case 0x0a: print("sfr"); break;
+ case 0x0c: print("rol"); break;
+ case 0x0d: print("ror"); break;
+ case 0x10: print("addb"); break;
+ case 0x11: print("adcb"); break;
+ case 0x12: print("andb"); break;
+ case 0x13: print("orb"); break;
+ case 0x14: print("rolb"); break;
+ case 0x15: print("rorb"); break;
+ case 0x16: print("sflb"); break;
+ case 0x17: print("sfrb"); break;
+ case 0x18: print("sbb"); break;
+ case 0x19: print("sbbb"); break;
+ case 0x1a: print("xorb"); break;
+ case 0x1b: print("crgt"); break;
+ case 0x1c: print("crlt"); break;
+ case 0x1d: print("exar"); break;
+ case 0x1e: print("sacb"); break;
+ case 0x1f: print("lacb"); break;
+ case 0x20: print("bacc"); break;
+ case 0x21: print("baccd"); break;
+ case 0x22: print("idle"); break;
+ case 0x23: print("idle2"); break;
+ case 0x30: print("cala"); break;
+ case 0x32: print("pop"); break;
+ case 0x38: print("reti"); break;
+ case 0x3a: print("rete"); break;
+ case 0x3c: print("push"); break;
+ case 0x3d: print("calad"); break;
+ case 0x40: print("clrc intm"); break;
+ case 0x41: print("setc intm"); break;
+ case 0x42: print("clrc ovm"); break;
+ case 0x43: print("setc ovm"); break;
+ case 0x44: print("clrc cnf"); break;
+ case 0x45: print("setc cnf"); break;
+ case 0x46: print("clrc sxm"); break;
+ case 0x47: print("setc sxm"); break;
+ case 0x48: print("clrc hold"); break;
+ case 0x49: print("setc hold"); break;
+ case 0x4a: print("clrc tc"); break;
+ case 0x4b: print("setc tc"); break;
+ case 0x4c: print("clrc xf"); break;
+ case 0x4d: print("setc xf"); break;
+ case 0x4e: print("clrc carry"); break;
+ case 0x4f: print("setc carry"); break;
+ case 0x51: print("trap"); break;
+ case 0x52: print("nmi"); break;
+ case 0x58: print("zpr"); break;
+ case 0x59: print("zap"); break;
+ case 0x5a: print("sath"); break;
+ case 0x5b: print("satl"); 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:
+ print("intr %d", opcode & 0x1f); break;
+
+ case 0x80: print("mpy #%04X", FETCH()); break;
+ case 0x81: print("and #%04X", FETCH() << 16); break;
+ case 0x82: print("or #%04X", FETCH() << 16); break;
+ case 0x83: print("xor #%04X", FETCH() << 16); break;
+ case 0xc4: print("rpt #%04X", FETCH()); break;
+ case 0xc5: print("rpt #%04X", FETCH()); break;
+ case 0xc6: print("rpt #%04X", FETCH()); break;
+
+ default: print("??? (group be)"); break;
+ }
+}
+
+static void dasm_group_bf(UINT16 opcode)
+{
+ int subop = (opcode >> 4) & 0xf;
+ int shift = opcode & 0xf;
+
+ switch (subop)
+ {
+ case 0x0:
+ {
+ if (opcode & 0x8)
+ {
+ print("lar ar%d, #%04X", opcode & 0x7, FETCH());
+ }
+ else
+ {
+ print("spm #%02X", opcode & 0x3);
+ }
+ break;
+ }
+
+ case 0x4:
+ {
+ switch (opcode & 0x3)
+ {
+ case 0: print("cmpr ar = arcr"); break;
+ case 1: print("cmpr ar < arcr"); break;
+ case 2: print("cmpr ar > arcr"); break;
+ case 3: print("cmpr ar != arcr"); break;
+ }
+ break;
+ }
+
+ case 0x8: print("lacc #%04X", FETCH() << shift); break;
+ case 0x9: print("add #%04X", FETCH() << shift); break;
+ case 0xa: print("sub #%04X", FETCH() << shift); break;
+ case 0xb: print("and #%04X", FETCH() << shift); break;
+ case 0xc: print("or #%04X", FETCH() << shift); break;
+ case 0xd: print("xor #%04X", FETCH() << shift); break;
+ case 0xe: print("bsar %d", shift+1); break;
+
+ default: print("??? (group bf)"); break;
+ }
+}
+
+CPU_DISASSEMBLE( tms32051 )
+{
+ UINT32 flags = 0;
+ UINT16 opcode;
+ int baseop;
+ int address, addr_mode;
+
+ pcbase = pc;
+ rombase = oprom;
+ npc = pc;
+ output = buffer;
+
+ opcode = FETCH();
+ baseop = (opcode >> 8) & 0xff;
+
+ addr_mode = (opcode >> 7) & 0x1;
+ address = opcode & 0x7f;
+
+ switch (baseop)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ case 0x04: case 0x05: case 0x06: case 0x07:
+ {
+ print("lar ar%d, %s", (opcode >> 8) & 0x7, GET_ADDRESS(addr_mode, address));
+ break;
+ }
+ case 0x08: print("lamm %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x09: print("smmr %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x0a: print("subc %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x0b: print("rpt %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x0c: print("out %s, #%04X", GET_ADDRESS(addr_mode, address), FETCH()); break;
+ case 0x0d: print("ldp %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x0e: print("lst 0, %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x0f: print("lst 1, %s", GET_ADDRESS(addr_mode, address)); 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:
+ {
+ print("lacc %s %s", GET_ADDRESS(addr_mode, address), GET_SHIFT((opcode >> 8) & 0xf));
+ break;
+ }
+
+ 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:
+ {
+ print("add %s %s", GET_ADDRESS(addr_mode, address), GET_SHIFT((opcode >> 8) & 0xf));
+ 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:
+ {
+ print("sub %s %s", GET_ADDRESS(addr_mode, address), GET_SHIFT((opcode >> 8) & 0xf));
+ 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:
+ {
+ print("bit %d, %s", (opcode >> 8) & 0xf, GET_ADDRESS(addr_mode, address));
+ break;
+ }
+
+ case 0x50: print("mpya %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x51: print("mpys %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x52: print("sqra %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x53: print("sqrs %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x54: print("mpy %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x55: print("mpyu %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x57: print("bldp %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x58: print("xpl %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x59: print("opl %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x5a: print("apl %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x5b: print("cpl %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x5c: print("xpl %s, #%04X", GET_ADDRESS(addr_mode, address), FETCH()); break;
+ case 0x5d: print("opl %s, #%04X", GET_ADDRESS(addr_mode, address), FETCH()); break;
+ case 0x5e: print("apl %s, #%04X", GET_ADDRESS(addr_mode, address), FETCH()); break;
+ case 0x5f: print("cpl %s, #%04X", GET_ADDRESS(addr_mode, address), FETCH()); break;
+
+ case 0x60: print("addc %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x61: print("add %s << 16", GET_ADDRESS(addr_mode, address)); break;
+ case 0x62: print("adds %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x63: print("addt %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x64: print("subb %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x65: print("sub %s << 16", GET_ADDRESS(addr_mode, address)); break;
+ case 0x66: print("subs %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x67: print("subt %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x68: print("zalr %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x69: print("lacl %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x6a: print("lacc %s << 16", GET_ADDRESS(addr_mode, address)); break;
+ case 0x6b: print("lact %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x6c: print("xor %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x6d: print("or %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x6e: print("and %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x6f: print("bitt %s", GET_ADDRESS(addr_mode, address)); break;
+
+ case 0x70: print("lta %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x71: print("ltp %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x72: print("ltd %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x73: print("lt %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x74: print("lts %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x75: print("lph %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x76: print("pshd %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x77: print("dmov %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x78: print("adrk #%02X", opcode & 0xff); break;
+ case 0x79: print("b %04X, %s", FETCH(), GET_ADDRESS(1, address)); break;
+ case 0x7a: print("call %04X, %s", FETCH(), GET_ADDRESS(1, address)); flags = DASMFLAG_STEP_OVER; break;
+ case 0x7b: print("banz %04X, %s", FETCH(), GET_ADDRESS(1, address)); break;
+ case 0x7c: print("sbrk #%02X", opcode & 0xff); break;
+ case 0x7d: print("bd %04X, %s", FETCH(), GET_ADDRESS(1, address)); break;
+ case 0x7e: print("calld %04X, %s", FETCH(), GET_ADDRESS(1, address)); flags = DASMFLAG_STEP_OVER; break;
+ case 0x7f: print("banzd %04X, %s", FETCH(), GET_ADDRESS(1, address)); break;
+
+ case 0x80: case 0x81: case 0x82: case 0x83:
+ case 0x84: case 0x85: case 0x86: case 0x87:
+ {
+ print("sar ar%d, %s", (opcode >> 8) & 0x7, GET_ADDRESS(addr_mode, address));
+ break;
+ }
+ case 0x88: print("samm %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x89: print("lmmr %s, #%04X", GET_ADDRESS(addr_mode, address), FETCH()); break;
+ case 0x8a: print("popd %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x8b:
+ {
+ if ((opcode & 0xff) == 0)
+ {
+ print("nop");
+ }
+ else
+ {
+ print("mar %s", GET_ADDRESS(addr_mode, address));
+ }
+ break;
+ }
+ case 0x8c: print("spl %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x8d: print("sph %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x8e: print("sst 0, %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0x8f: print("sst 1, %s", GET_ADDRESS(addr_mode, address)); break;
+
+ case 0x90: case 0x91: case 0x92: case 0x93:
+ case 0x94: case 0x95: case 0x96: case 0x97:
+ {
+ print("sacl %s %s", GET_ADDRESS(addr_mode, address), GET_SHIFT((opcode >> 8) & 0x7));
+ break;
+ }
+ case 0x98: case 0x99: case 0x9a: case 0x9b:
+ case 0x9c: case 0x9d: case 0x9e: case 0x9f:
+ {
+ print("sach %s %s", GET_ADDRESS(addr_mode, address), GET_SHIFT((opcode >> 8) & 0x7));
+ break;
+ }
+
+ case 0xa0: print("norm %s, #%04X", GET_ADDRESS(addr_mode, address), FETCH()); break;
+ case 0xa2: print("mac %s, #%04X", GET_ADDRESS(addr_mode, address), FETCH()); break;
+ case 0xa3: print("macd %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0xa4: print("blpd %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0xa5: print("blpd %s, #%04X", GET_ADDRESS(addr_mode, address), FETCH()); break;
+ case 0xa6: print("tblr %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0xa7: print("tblw %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0xa8: print("bldd %s, #%04X", GET_ADDRESS(addr_mode, address), FETCH()); break;
+ case 0xa9: print("bldd %s, #%04X", GET_ADDRESS(addr_mode, address), FETCH()); break;
+ case 0xaa: print("mads %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0xab: print("madd %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0xac: print("bldd %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0xad: print("bldd %s", GET_ADDRESS(addr_mode, address)); break;
+ case 0xae: print("splk %s, #%04X", GET_ADDRESS(addr_mode, address), FETCH()); break;
+ case 0xaf: print("in %s, #%04X", GET_ADDRESS(addr_mode, address), FETCH()); break;
+
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3:
+ case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ {
+ print("lar ar%d, #%02X", (opcode >> 8) & 0x7, opcode & 0xff);
+ break;
+ }
+ case 0xb8: print("add #%02X", opcode & 0xff); break;
+ case 0xb9: print("lacl #%02X", opcode & 0xff); break;
+ case 0xba: print("sub #%02X", opcode & 0xff); break;
+ case 0xbb: print("rpt #%02X", opcode & 0xff); break;
+
+ case 0xbc:
+ case 0xbd:
+ {
+ print("ldp #%03X", opcode & 0x1ff);
+ break;
+ }
+ case 0xbe: dasm_group_be(opcode); break;
+ case 0xbf: dasm_group_bf(opcode); break;
+
+ case 0xe0: case 0xe1: case 0xe2: case 0xe3:
+ {
+ int zlcvmask = opcode & 0xf;
+ int zlcv = (opcode >> 4) & 0xf;
+ int zl = (zlcv & 0xc) | ((zlcvmask >> 2) & 0x3);
+ int cv = ((zlcv << 2) & 0xc) | (zlcvmask & 0x3);
+ int tp = (opcode >> 8) & 0x3;
+
+ print("bcnd %04X", FETCH());
+
+ if (strlen(zl_condition_codes[zl]) > 0)
+ {
+ print(", %s", zl_condition_codes[zl]);
+ }
+ if (strlen(cv_condition_codes[cv]) > 0)
+ {
+ print(", %s", cv_condition_codes[cv]);
+ }
+ if (strlen(tp_condition_codes[tp]) > 0)
+ {
+ print(", %s", tp_condition_codes[tp]);
+ }
+ break;
+ }
+
+ case 0xe4: case 0xe5: case 0xe6: case 0xe7:
+ case 0xf4: case 0xf5: case 0xf6: case 0xf7:
+ {
+ int zlcvmask = opcode & 0xf;
+ int zlcv = (opcode >> 4) & 0xf;
+ int zl = (zlcv & 0xc) | ((zlcvmask >> 2) & 0x3);
+ int cv = ((zlcv << 2) & 0xc) | (zlcvmask & 0x3);
+ int tp = (opcode >> 8) & 0x3;
+ int n = ((opcode >> 12) & 0x1) + 1;
+
+ print("xc %d", n);
+
+ if (strlen(zl_condition_codes[zl]) > 0)
+ {
+ print(", %s", zl_condition_codes[zl]);
+ }
+ if (strlen(cv_condition_codes[cv]) > 0)
+ {
+ print(", %s", cv_condition_codes[cv]);
+ }
+ if (strlen(tp_condition_codes[tp]) > 0)
+ {
+ print(", %s", tp_condition_codes[tp]);
+ }
+ break;
+ }
+
+ case 0xe8: case 0xe9: case 0xea: case 0xeb:
+ {
+ int zlcvmask = opcode & 0xf;
+ int zlcv = (opcode >> 4) & 0xf;
+ int zl = (zlcv & 0xc) | ((zlcvmask >> 2) & 0x3);
+ int cv = ((zlcv << 2) & 0xc) | (zlcvmask & 0x3);
+ int tp = (opcode >> 8) & 0x3;
+
+ print("cc %04X", FETCH());
+
+ if (strlen(zl_condition_codes[zl]) > 0)
+ {
+ print(", %s", zl_condition_codes[zl]);
+ }
+ if (strlen(cv_condition_codes[cv]) > 0)
+ {
+ print(", %s", cv_condition_codes[cv]);
+ }
+ if (strlen(tp_condition_codes[tp]) > 0)
+ {
+ print(", %s", tp_condition_codes[tp]);
+ }
+ break;
+ }
+
+ case 0xec: case 0xed: case 0xee:
+ {
+ int zlcvmask = opcode & 0xf;
+ int zlcv = (opcode >> 4) & 0xf;
+ int zl = (zlcv & 0xc) | ((zlcvmask >> 2) & 0x3);
+ int cv = ((zlcv << 2) & 0xc) | (zlcvmask & 0x3);
+ int tp = (opcode >> 8) & 0x3;
+
+ print("retc ");
+
+ if (strlen(zl_condition_codes[zl]) > 0)
+ {
+ print(", %s", zl_condition_codes[zl]);
+ }
+ if (strlen(cv_condition_codes[cv]) > 0)
+ {
+ print(", %s", cv_condition_codes[cv]);
+ }
+ if (strlen(tp_condition_codes[tp]) > 0)
+ {
+ print(", %s", tp_condition_codes[tp]);
+ }
+ flags = DASMFLAG_STEP_OUT;
+ break;
+ }
+
+ case 0xef: print("ret"); flags = DASMFLAG_STEP_OUT; break;
+
+ case 0xf0: case 0xf1: case 0xf2: case 0xf3:
+ {
+ int zlcvmask = opcode & 0xf;
+ int zlcv = (opcode >> 4) & 0xf;
+ int zl = (zlcv & 0xc) | ((zlcvmask >> 2) & 0x3);
+ int cv = ((zlcv << 2) & 0xc) | (zlcvmask & 0x3);
+ int tp = (opcode >> 8) & 0x3;
+
+ print("bcndd %04X", FETCH());
+
+ if (strlen(zl_condition_codes[zl]) > 0)
+ {
+ print(", %s", zl_condition_codes[zl]);
+ }
+ if (strlen(cv_condition_codes[cv]) > 0)
+ {
+ print(", %s", cv_condition_codes[cv]);
+ }
+ if (strlen(tp_condition_codes[tp]) > 0)
+ {
+ print(", %s", tp_condition_codes[tp]);
+ }
+ break;
+ }
+
+ case 0xf8: case 0xf9: case 0xfa: case 0xfb:
+ {
+ int zlcvmask = opcode & 0xf;
+ int zlcv = (opcode >> 4) & 0xf;
+ int zl = (zlcv & 0xc) | ((zlcvmask >> 2) & 0x3);
+ int cv = ((zlcv << 2) & 0xc) | (zlcvmask & 0x3);
+ int tp = (opcode >> 8) & 0x3;
+
+ print("ccd %04X", FETCH());
+
+ if (strlen(zl_condition_codes[zl]) > 0)
+ {
+ print(", %s", zl_condition_codes[zl]);
+ }
+ if (strlen(cv_condition_codes[cv]) > 0)
+ {
+ print(", %s", cv_condition_codes[cv]);
+ }
+ if (strlen(tp_condition_codes[tp]) > 0)
+ {
+ print(", %s", tp_condition_codes[tp]);
+ }
+ break;
+ }
+
+ case 0xfc: case 0xfd: case 0xfe:
+ {
+ int zlcvmask = opcode & 0xf;
+ int zlcv = (opcode >> 4) & 0xf;
+ int zl = (zlcv & 0xc) | ((zlcvmask >> 2) & 0x3);
+ int cv = ((zlcv << 2) & 0xc) | (zlcvmask & 0x3);
+ int tp = (opcode >> 8) & 0x3;
+
+ print("retcd ");
+
+ if (strlen(zl_condition_codes[zl]) > 0)
+ {
+ print(", %s", zl_condition_codes[zl]);
+ }
+ if (strlen(cv_condition_codes[cv]) > 0)
+ {
+ print(", %s", cv_condition_codes[cv]);
+ }
+ if (strlen(tp_condition_codes[tp]) > 0)
+ {
+ print(", %s", tp_condition_codes[tp]);
+ }
+ flags = DASMFLAG_STEP_OUT;
+ break;
+ }
+
+ case 0xff: print("retd"); flags = DASMFLAG_STEP_OUT; break;
+
+ default: print("??? ($%04X)", opcode); break;
+ }
+
+ return (npc-pc) | flags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/tms32051/tms32051.c b/trunk/src/emu/cpu/tms32051/tms32051.c
new file mode 100644
index 00000000000..7af6f971f53
--- /dev/null
+++ b/trunk/src/emu/cpu/tms32051/tms32051.c
@@ -0,0 +1,739 @@
+/*
+ Texas Instruments TMS320C51 DSP Emulator
+
+ Written by Ville Linde
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "tms32051.h"
+
+#define INTERRUPT_INT1 0
+#define INTERRUPT_INT2 1
+#define INTERRUPT_INT3 2
+#define INTERRUPT_TINT 3
+#define INTERRUPT_RINT 4
+#define INTERRUPT_XINT 5
+#define INTERRUPT_TRNT 6
+#define INTERRUPT_TXNT 7
+#define INTERRUPT_INT4 8
+
+enum
+{
+ TMS32051_PC = 1,
+ TMS32051_ACC,
+ TMS32051_ACCB,
+ TMS32051_PREG,
+ TMS32051_TREG0,
+ TMS32051_TREG1,
+ TMS32051_TREG2,
+ TMS32051_BMAR,
+ TMS32051_RPTC,
+ TMS32051_BRCR,
+ TMS32051_INDX,
+ TMS32051_DBMR,
+ TMS32051_ARCR,
+ TMS32051_DP,
+ TMS32051_ARP,
+ TMS32051_ARB,
+ TMS32051_AR0,
+ TMS32051_AR1,
+ TMS32051_AR2,
+ TMS32051_AR3,
+ TMS32051_AR4,
+ TMS32051_AR5,
+ TMS32051_AR6,
+ TMS32051_AR7,
+};
+
+typedef struct
+{
+ UINT16 iptr;
+ UINT16 avis;
+ UINT16 ovly;
+ UINT16 ram;
+ UINT16 mpmc;
+ UINT16 ndx;
+ UINT16 trm;
+ UINT16 braf;
+} PMST;
+
+typedef struct
+{
+ UINT16 dp;
+ UINT16 intm;
+ UINT16 ovm;
+ UINT16 ov;
+ UINT16 arp;
+} ST0;
+
+typedef struct
+{
+ UINT16 arb;
+ UINT16 cnf;
+ UINT16 tc;
+ UINT16 sxm;
+ UINT16 c;
+ UINT16 hm;
+ UINT16 xf;
+ UINT16 pm;
+} ST1;
+
+typedef struct _tms32051_state tms32051_state;
+struct _tms32051_state
+{
+ UINT16 pc;
+ UINT16 op;
+ INT32 acc;
+ INT32 accb;
+ INT32 preg;
+ UINT16 treg0;
+ UINT16 treg1;
+ UINT16 treg2;
+ UINT16 ar[8];
+ INT32 rptc;
+
+ UINT16 bmar;
+ INT32 brcr;
+ UINT16 paer;
+ UINT16 pasr;
+ UINT16 indx;
+ UINT16 dbmr;
+ UINT16 arcr;
+
+ ST0 st0;
+ ST1 st1;
+ PMST pmst;
+
+ UINT16 ifr;
+ UINT16 imr;
+
+ UINT16 pcstack[8];
+ int pcstack_ptr;
+
+ UINT16 rpt_start, rpt_end;
+
+ UINT16 cbcr;
+ UINT16 cbsr1;
+ UINT16 cber1;
+ UINT16 cbsr2;
+ UINT16 cber2;
+
+ struct
+ {
+ int tddr;
+ int psc;
+ UINT16 tim;
+ UINT16 prd;
+ } timer;
+
+ struct
+ {
+ INT32 acc;
+ INT32 accb;
+ UINT16 arcr;
+ UINT16 indx;
+ PMST pmst;
+ INT32 preg;
+ ST0 st0;
+ ST1 st1;
+ INT32 treg0;
+ INT32 treg1;
+ INT32 treg2;
+ } shadow;
+
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *data;
+ int icount;
+};
+
+INLINE tms32051_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == TMS32051);
+ return (tms32051_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+static void delay_slot(tms32051_state *cpustate, UINT16 startpc);
+static void save_interrupt_context(tms32051_state *cpustate);
+static void restore_interrupt_context(tms32051_state *cpustate);
+static void check_interrupts(tms32051_state *cpustate);
+
+
+#define CYCLES(x) (cpustate->icount -= x)
+
+#define ROPCODE(cpustate) cpustate->direct->read_decrypted_word((cpustate->pc++) << 1)
+
+INLINE void CHANGE_PC(tms32051_state *cpustate, UINT16 new_pc)
+{
+ cpustate->pc = new_pc;
+}
+
+INLINE UINT16 PM_READ16(tms32051_state *cpustate, UINT16 address)
+{
+ return cpustate->program->read_word(address << 1);
+}
+
+INLINE void PM_WRITE16(tms32051_state *cpustate, UINT16 address, UINT16 data)
+{
+ cpustate->program->write_word(address << 1, data);
+}
+
+INLINE UINT16 DM_READ16(tms32051_state *cpustate, UINT16 address)
+{
+ return cpustate->data->read_word(address << 1);
+}
+
+INLINE void DM_WRITE16(tms32051_state *cpustate, UINT16 address, UINT16 data)
+{
+ cpustate->data->write_word(address << 1, data);
+}
+
+#include "32051ops.c"
+#include "32051ops.h"
+
+static void op_group_be(tms32051_state *cpustate)
+{
+ tms32051_opcode_table_be[cpustate->op & 0xff](cpustate);
+}
+
+static void op_group_bf(tms32051_state *cpustate)
+{
+ tms32051_opcode_table_bf[cpustate->op & 0xff](cpustate);
+}
+
+static void delay_slot(tms32051_state *cpustate, UINT16 startpc)
+{
+ cpustate->op = ROPCODE(cpustate);
+ tms32051_opcode_table[cpustate->op >> 8](cpustate);
+
+ while (cpustate->pc - startpc < 2)
+ {
+ cpustate->op = ROPCODE(cpustate);
+ tms32051_opcode_table[cpustate->op >> 8](cpustate);
+ }
+}
+
+/*****************************************************************************/
+
+static CPU_INIT( tms )
+{
+ tms32051_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);
+}
+
+static CPU_RESET( tms )
+{
+ tms32051_state *cpustate = get_safe_token(device);
+ int i;
+ UINT16 src, dst, length;
+
+ src = 0x7800;
+ dst = DM_READ16(cpustate, src++);
+ length = DM_READ16(cpustate, src++);
+
+ CHANGE_PC(cpustate, dst);
+
+ /* TODO: if you soft reset on Taito JC it tries to do a 0x7802->0x9007 (0xff00) transfer. */
+ for (i=0; i < (length & 0x7ff); i++)
+ {
+ UINT16 data = DM_READ16(cpustate, src++);
+ PM_WRITE16(cpustate, dst++, data);
+ }
+
+ cpustate->st0.intm = 1;
+ cpustate->st0.ov = 0;
+ cpustate->st1.c = 1;
+ cpustate->st1.cnf = 0;
+ cpustate->st1.hm = 1;
+ cpustate->st1.pm = 0;
+ cpustate->st1.sxm = 1;
+ cpustate->st1.xf = 1;
+ cpustate->pmst.avis = 0;
+ cpustate->pmst.braf = 0;
+ cpustate->pmst.iptr = 0;
+ cpustate->pmst.ndx = 0;
+ cpustate->pmst.ovly = 0;
+ cpustate->pmst.ram = 0;
+ cpustate->pmst.trm = 0;
+ cpustate->ifr = 0;
+ cpustate->cbcr = 0;
+ cpustate->rptc = -1;
+}
+
+static void check_interrupts(tms32051_state *cpustate)
+{
+ int i;
+
+ if (cpustate->st0.intm == 0 && cpustate->ifr != 0)
+ {
+ for (i=0; i < 16; i++)
+ {
+ if (cpustate->ifr & (1 << i))
+ {
+ cpustate->st0.intm = 1;
+ PUSH_STACK(cpustate, cpustate->pc);
+
+ cpustate->pc = (cpustate->pmst.iptr << 11) | ((i+1) << 1);
+ cpustate->ifr &= ~(1 << i);
+
+ save_interrupt_context(cpustate);
+ break;
+ }
+ }
+ }
+}
+
+static void save_interrupt_context(tms32051_state *cpustate)
+{
+ cpustate->shadow.acc = cpustate->acc;
+ cpustate->shadow.accb = cpustate->accb;
+ cpustate->shadow.arcr = cpustate->arcr;
+ cpustate->shadow.indx = cpustate->indx;
+ cpustate->shadow.preg = cpustate->preg;
+ cpustate->shadow.treg0 = cpustate->treg0;
+ cpustate->shadow.treg1 = cpustate->treg1;
+ cpustate->shadow.treg2 = cpustate->treg2;
+ memcpy(&cpustate->shadow.pmst, &cpustate->pmst, sizeof(PMST));
+ memcpy(&cpustate->shadow.st0, &cpustate->st0, sizeof(ST0));
+ memcpy(&cpustate->shadow.st1, &cpustate->st1, sizeof(ST1));
+}
+
+static void restore_interrupt_context(tms32051_state *cpustate)
+{
+ cpustate->acc = cpustate->shadow.acc;
+ cpustate->accb = cpustate->shadow.accb;
+ cpustate->arcr = cpustate->shadow.arcr;
+ cpustate->indx = cpustate->shadow.indx;
+ cpustate->preg = cpustate->shadow.preg;
+ cpustate->treg0 = cpustate->shadow.treg0;
+ cpustate->treg1 = cpustate->shadow.treg1;
+ cpustate->treg2 = cpustate->shadow.treg2;
+ memcpy(&cpustate->pmst, &cpustate->shadow.pmst, sizeof(PMST));
+ memcpy(&cpustate->st0, &cpustate->shadow.st0, sizeof(ST0));
+ memcpy(&cpustate->st1, &cpustate->shadow.st1, sizeof(ST1));
+}
+
+static void tms_interrupt(tms32051_state *cpustate, int irq)
+{
+ if ((cpustate->imr & (1 << irq)) != 0)
+ {
+ cpustate->ifr |= 1 << irq;
+ }
+
+ check_interrupts(cpustate);
+}
+
+static CPU_EXIT( tms )
+{
+ /* TODO */
+}
+
+static CPU_EXECUTE( tms )
+{
+ tms32051_state *cpustate = get_safe_token(device);
+
+ while(cpustate->icount > 0)
+ {
+ UINT16 ppc;
+
+ // handle block repeat
+ if (cpustate->pmst.braf)
+ {
+ if (cpustate->pc == cpustate->paer)
+ {
+ if (cpustate->brcr > 0)
+ {
+ CHANGE_PC(cpustate, cpustate->pasr);
+ }
+
+ cpustate->brcr--;
+ if (cpustate->brcr <= 0)
+ {
+ cpustate->pmst.braf = 0;
+ }
+ }
+ }
+
+ ppc = cpustate->pc;
+ debugger_instruction_hook(device, cpustate->pc);
+
+ cpustate->op = ROPCODE(cpustate);
+ tms32051_opcode_table[cpustate->op >> 8](cpustate);
+
+ // handle single repeat
+ if (cpustate->rptc > 0)
+ {
+ if (ppc == cpustate->rpt_end)
+ {
+ CHANGE_PC(cpustate, cpustate->rpt_start);
+ cpustate->rptc--;
+ }
+ }
+ else
+ {
+ cpustate->rptc = 0;
+ }
+
+ cpustate->timer.psc--;
+ if (cpustate->timer.psc <= 0)
+ {
+ cpustate->timer.psc = cpustate->timer.tddr;
+ cpustate->timer.tim--;
+ if (cpustate->timer.tim <= 0)
+ {
+ // reset timer
+ cpustate->timer.tim = cpustate->timer.prd;
+
+ tms_interrupt(cpustate, INTERRUPT_TINT);
+ }
+ }
+ }
+}
+
+
+/*****************************************************************************/
+
+static READ16_HANDLER( cpuregs_r )
+{
+ tms32051_state *cpustate = get_safe_token(&space->device());
+
+ switch (offset)
+ {
+ case 0x04: return cpustate->imr;
+ case 0x06: return cpustate->ifr;
+
+ case 0x07: // PMST
+ {
+ UINT16 r = 0;
+ r |= cpustate->pmst.iptr << 11;
+ r |= cpustate->pmst.avis << 7;
+ r |= cpustate->pmst.ovly << 5;
+ r |= cpustate->pmst.ram << 4;
+ r |= cpustate->pmst.mpmc << 3;
+ r |= cpustate->pmst.ndx << 2;
+ r |= cpustate->pmst.trm << 1;
+ r |= cpustate->pmst.braf << 0;
+ return r;
+ }
+
+ case 0x09: return cpustate->brcr;
+ case 0x10: return cpustate->ar[0];
+ case 0x11: return cpustate->ar[1];
+ case 0x12: return cpustate->ar[2];
+ case 0x13: return cpustate->ar[3];
+ case 0x14: return cpustate->ar[4];
+ case 0x15: return cpustate->ar[5];
+ case 0x16: return cpustate->ar[6];
+ case 0x17: return cpustate->ar[7];
+ case 0x1e: return cpustate->cbcr;
+ case 0x1f: return cpustate->bmar;
+ case 0x24: return cpustate->timer.tim;
+ case 0x25: return cpustate->timer.prd;
+
+ case 0x26: // TCR
+ {
+ UINT16 r = 0;
+ r |= (cpustate->timer.psc & 0xf) << 6;
+ r |= (cpustate->timer.tddr & 0xf);
+ return r;
+ }
+
+ case 0x28: return 0; // PDWSR
+ default:
+ if(!space->debugger_access())
+ fatalerror("32051: cpuregs_r: unimplemented memory-mapped register %02X at %04X\n", offset, cpustate->pc-1);
+ }
+
+ return 0;
+}
+
+static WRITE16_HANDLER( cpuregs_w )
+{
+ tms32051_state *cpustate = get_safe_token(&space->device());
+
+ switch (offset)
+ {
+ case 0x00: break;
+ case 0x04: cpustate->imr = data; break;
+ case 0x06: // IFR
+ {
+ int i;
+ for (i=0; i < 16; i++)
+ {
+ if (data & (1 << i))
+ {
+ cpustate->ifr &= ~(1 << i);
+ }
+ }
+ break;
+ }
+
+ case 0x07: // PMST
+ {
+ cpustate->pmst.iptr = (data >> 11) & 0x1f;
+ cpustate->pmst.avis = (data & 0x80) ? 1 : 0;
+ cpustate->pmst.ovly = (data & 0x20) ? 1 : 0;
+ cpustate->pmst.ram = (data & 0x10) ? 1 : 0;
+ cpustate->pmst.mpmc = (data & 0x08) ? 1 : 0;
+ cpustate->pmst.ndx = (data & 0x04) ? 1 : 0;
+ cpustate->pmst.trm = (data & 0x02) ? 1 : 0;
+ cpustate->pmst.braf = (data & 0x01) ? 1 : 0;
+ break;
+ }
+
+ case 0x09: cpustate->brcr = data; break;
+ case 0x0e: cpustate->treg2 = data; break;
+ case 0x0f: cpustate->dbmr = data; break;
+ case 0x10: cpustate->ar[0] = data; break;
+ case 0x11: cpustate->ar[1] = data; break;
+ case 0x12: cpustate->ar[2] = data; break;
+ case 0x13: cpustate->ar[3] = data; break;
+ case 0x14: cpustate->ar[4] = data; break;
+ case 0x15: cpustate->ar[5] = data; break;
+ case 0x16: cpustate->ar[6] = data; break;
+ case 0x17: cpustate->ar[7] = data; break;
+ case 0x18: cpustate->indx = data; break;
+ case 0x19: cpustate->arcr = data; break;
+ case 0x1a: cpustate->cbsr1 = data; break;
+ case 0x1b: cpustate->cber1 = data; break;
+ case 0x1c: cpustate->cbsr2 = data; break;
+ case 0x1d: cpustate->cber2 = data; break;
+ case 0x1e: cpustate->cbcr = data; break;
+ case 0x1f: cpustate->bmar = data; break;
+ case 0x24: cpustate->timer.tim = data; break;
+ case 0x25: cpustate->timer.prd = data; break;
+
+ case 0x26: // TCR
+ {
+ cpustate->timer.tddr = data & 0xf;
+ cpustate->timer.psc = (data >> 6) & 0xf;
+
+ if (data & 0x20)
+ {
+ cpustate->timer.tim = cpustate->timer.prd;
+ cpustate->timer.psc = cpustate->timer.tddr;
+ }
+ break;
+ }
+
+ case 0x28: break; // PDWSR
+ default:
+ if(!space->debugger_access())
+ fatalerror("32051: cpuregs_w: unimplemented memory-mapped register %02X, data %04X at %04X\n", offset, data, cpustate->pc-1);
+ }
+}
+
+/**************************************************************************
+ * Internal memory map
+ **************************************************************************/
+
+static ADDRESS_MAP_START( internal_pgm, AS_PROGRAM, 16 )
+ AM_RANGE(0x2000, 0x23ff) AM_RAM AM_SHARE("saram") // SARAM
+ AM_RANGE(0xfe00, 0xffff) AM_RAM AM_SHARE("daram_b0") // DARAM B0
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( internal_data, AS_DATA, 16 )
+ AM_RANGE(0x0000, 0x005f) AM_READWRITE(cpuregs_r, cpuregs_w)
+ AM_RANGE(0x0060, 0x007f) AM_RAM // DARAM B2
+ AM_RANGE(0x0100, 0x02ff) AM_RAM AM_SHARE("daram_b0") // DARAM B0
+ AM_RANGE(0x0300, 0x04ff) AM_RAM // DARAM B1
+ AM_RANGE(0x0800, 0x0bff) AM_RAM AM_SHARE("saram")
+ADDRESS_MAP_END
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( tms )
+{
+ tms32051_state *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + TMS32051_PC: cpustate->pc = info->i; break;
+ }
+}
+
+static CPU_READ( tms )
+{
+ tms32051_state *cpustate = get_safe_token(device);
+ /* TODO: alignment if offset is odd */
+ if (space == AS_PROGRAM)
+ {
+ *value = (PM_READ16(cpustate, offset>>1));
+ }
+ else if (space == AS_DATA)
+ {
+ *value = (DM_READ16(cpustate, offset>>1));
+ }
+ return 1;
+}
+
+static CPU_GET_INFO( tms )
+{
+ tms32051_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(tms32051_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 = 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 = 5; 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: info->i = CLEAR_LINE; break;
+
+ case CPUINFO_INT_PREVIOUSPC: /* not implemented */ break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + TMS32051_PC: info->i = cpustate->pc; break;
+ case CPUINFO_INT_REGISTER + TMS32051_ACC: info->i = cpustate->acc; break;
+ case CPUINFO_INT_REGISTER + TMS32051_ACCB: info->i = cpustate->accb; break;
+ case CPUINFO_INT_REGISTER + TMS32051_PREG: info->i = cpustate->preg; break;
+ case CPUINFO_INT_REGISTER + TMS32051_TREG0: info->i = cpustate->treg0; break;
+ case CPUINFO_INT_REGISTER + TMS32051_TREG1: info->i = cpustate->treg1; break;
+ case CPUINFO_INT_REGISTER + TMS32051_TREG2: info->i = cpustate->treg2; break;
+ case CPUINFO_INT_REGISTER + TMS32051_BMAR: info->i = cpustate->bmar; break;
+ case CPUINFO_INT_REGISTER + TMS32051_RPTC: info->i = cpustate->rptc; break;
+ case CPUINFO_INT_REGISTER + TMS32051_BRCR: info->i = cpustate->brcr; break;
+ case CPUINFO_INT_REGISTER + TMS32051_INDX: info->i = cpustate->indx; break;
+ case CPUINFO_INT_REGISTER + TMS32051_DBMR: info->i = cpustate->dbmr; break;
+ case CPUINFO_INT_REGISTER + TMS32051_ARCR: info->i = cpustate->arcr; break;
+ case CPUINFO_INT_REGISTER + TMS32051_DP: info->i = cpustate->st0.dp; break;
+ case CPUINFO_INT_REGISTER + TMS32051_ARP: info->i = cpustate->st0.arp; break;
+ case CPUINFO_INT_REGISTER + TMS32051_ARB: info->i = cpustate->st1.arb; break;
+ case CPUINFO_INT_REGISTER + TMS32051_AR0: info->i = cpustate->ar[0]; break;
+ case CPUINFO_INT_REGISTER + TMS32051_AR1: info->i = cpustate->ar[1]; break;
+ case CPUINFO_INT_REGISTER + TMS32051_AR2: info->i = cpustate->ar[2]; break;
+ case CPUINFO_INT_REGISTER + TMS32051_AR3: info->i = cpustate->ar[3]; break;
+ case CPUINFO_INT_REGISTER + TMS32051_AR4: info->i = cpustate->ar[4]; break;
+ case CPUINFO_INT_REGISTER + TMS32051_AR5: info->i = cpustate->ar[5]; break;
+ case CPUINFO_INT_REGISTER + TMS32051_AR6: info->i = cpustate->ar[6]; break;
+ case CPUINFO_INT_REGISTER + TMS32051_AR7: info->i = cpustate->ar[7]; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(tms); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(tms); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(tms); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(tms); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(tms32051); break;
+ case CPUINFO_FCT_READ: info->read = CPU_READ_NAME(tms); 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(internal_pgm); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map16 = ADDRESS_MAP_NAME(internal_data); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "TMS3205x"); 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: strcpy(info->s, " "); break;
+
+ case CPUINFO_STR_REGISTER + TMS32051_PC: sprintf(info->s, "PC: %04X", cpustate->pc); break;
+ case CPUINFO_STR_REGISTER + TMS32051_ACC: sprintf(info->s, "ACC: %08X", cpustate->acc); break;
+ case CPUINFO_STR_REGISTER + TMS32051_ACCB: sprintf(info->s, "ACCB: %08X", cpustate->accb); break;
+ case CPUINFO_STR_REGISTER + TMS32051_PREG: sprintf(info->s, "PREG: %08X", cpustate->preg); break;
+ case CPUINFO_STR_REGISTER + TMS32051_TREG0: sprintf(info->s, "TREG0: %04X", cpustate->treg0); break;
+ case CPUINFO_STR_REGISTER + TMS32051_TREG1: sprintf(info->s, "TREG1: %04X", cpustate->treg1); break;
+ case CPUINFO_STR_REGISTER + TMS32051_TREG2: sprintf(info->s, "TREG2: %04X", cpustate->treg2); break;
+ case CPUINFO_STR_REGISTER + TMS32051_BMAR: sprintf(info->s, "BMAR: %08X", cpustate->bmar); break;
+ case CPUINFO_STR_REGISTER + TMS32051_RPTC: sprintf(info->s, "RPTC: %08X", cpustate->rptc); break;
+ case CPUINFO_STR_REGISTER + TMS32051_BRCR: sprintf(info->s, "BRCR: %08X", cpustate->brcr); break;
+ case CPUINFO_STR_REGISTER + TMS32051_INDX: sprintf(info->s, "INDX: %04X", cpustate->indx); break;
+ case CPUINFO_STR_REGISTER + TMS32051_DBMR: sprintf(info->s, "DBMR: %04X", cpustate->dbmr); break;
+ case CPUINFO_STR_REGISTER + TMS32051_ARCR: sprintf(info->s, "ARCR: %04X", cpustate->arcr); break;
+ case CPUINFO_STR_REGISTER + TMS32051_DP: sprintf(info->s, "DP: %04X", cpustate->st0.dp); break;
+ case CPUINFO_STR_REGISTER + TMS32051_ARP: sprintf(info->s, "ARP: %04X", cpustate->st0.arp); break;
+ case CPUINFO_STR_REGISTER + TMS32051_ARB: sprintf(info->s, "ARB: %04X", cpustate->st1.arb); break;
+ case CPUINFO_STR_REGISTER + TMS32051_AR0: sprintf(info->s, "AR0: %04X", cpustate->ar[0]); break;
+ case CPUINFO_STR_REGISTER + TMS32051_AR1: sprintf(info->s, "AR1: %04X", cpustate->ar[1]); break;
+ case CPUINFO_STR_REGISTER + TMS32051_AR2: sprintf(info->s, "AR2: %04X", cpustate->ar[2]); break;
+ case CPUINFO_STR_REGISTER + TMS32051_AR3: sprintf(info->s, "AR3: %04X", cpustate->ar[3]); break;
+ case CPUINFO_STR_REGISTER + TMS32051_AR4: sprintf(info->s, "AR4: %04X", cpustate->ar[4]); break;
+ case CPUINFO_STR_REGISTER + TMS32051_AR5: sprintf(info->s, "AR5: %04X", cpustate->ar[5]); break;
+ case CPUINFO_STR_REGISTER + TMS32051_AR6: sprintf(info->s, "AR6: %04X", cpustate->ar[6]); break;
+ case CPUINFO_STR_REGISTER + TMS32051_AR7: sprintf(info->s, "AR7: %04X", cpustate->ar[7]); break;
+ }
+}
+
+static CPU_SET_INFO( tms32051 )
+{
+ tms32051_state *cpustate = get_safe_token(device);
+
+ if (state >= CPUINFO_INT_INPUT_STATE && state <= CPUINFO_INT_INPUT_STATE + 5)
+ {
+ return;
+ }
+ switch(state)
+ {
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + TMS32051_PC: cpustate->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32051_ACC: cpustate->acc = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32051_ACCB: cpustate->accb = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32051_PREG: cpustate->preg = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32051_TREG0: cpustate->treg0 = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32051_TREG1: cpustate->treg1 = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32051_TREG2: cpustate->treg2 = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32051_BMAR: cpustate->bmar = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32051_BRCR: cpustate->brcr = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32051_INDX: cpustate->indx = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32051_DBMR: cpustate->dbmr = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32051_ARCR: cpustate->arcr = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32051_DP: cpustate->st0.dp = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32051_ARP: cpustate->st0.arp = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32051_ARB: cpustate->st1.arb = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32051_AR0: cpustate->ar[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32051_AR1: cpustate->ar[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32051_AR2: cpustate->ar[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32051_AR3: cpustate->ar[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32051_AR4: cpustate->ar[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32051_AR5: cpustate->ar[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32051_AR6: cpustate->ar[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32051_AR7: cpustate->ar[7] = info->i; break;
+
+ default: CPU_SET_INFO_CALL(tms); break;
+ }
+}
+
+CPU_GET_INFO( tms32051 )
+{
+ 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(tms32051); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "TMS32051"); break;
+
+ default: CPU_GET_INFO_CALL(tms); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(TMS32051, tms32051);
diff --git a/trunk/src/emu/cpu/tms32051/tms32051.h b/trunk/src/emu/cpu/tms32051/tms32051.h
new file mode 100644
index 00000000000..3a8ca16cf7b
--- /dev/null
+++ b/trunk/src/emu/cpu/tms32051/tms32051.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#ifndef __TMS32051_H__
+#define __TMS32051_H__
+
+DECLARE_LEGACY_CPU_DEVICE(TMS32051, tms32051);
+
+CPU_DISASSEMBLE( tms32051 );
+
+#endif /* __TMS32051_H__ */
diff --git a/trunk/src/emu/cpu/tms34010/34010dsm.c b/trunk/src/emu/cpu/tms34010/34010dsm.c
new file mode 100644
index 00000000000..af9f3683fda
--- /dev/null
+++ b/trunk/src/emu/cpu/tms34010/34010dsm.c
@@ -0,0 +1,1760 @@
+/*
+ * A TMS34010 disassembler
+ *
+ * This code written by Zsolt Vasvari for the MAME project
+ *
+ */
+
+#include "emu.h"
+
+#ifdef STANDALONE
+#define PC __pc + (offset << 3)
+#define OP_WORD(v) { v = filebuf[_pc>>3]; _pc += 8; v = v | (filebuf[_pc>>3] << 8); _pc += 8;}
+#define PARAM_WORD(v) { v = filebuf[_pc>>3]; _pc += 8; v = v | (filebuf[_pc>>3] << 8); _pc += 8;}
+#define PARAM_LONG(v) { int v1, v2; PARAM_WORD(v1); PARAM_WORD(v2); v = v1 | (v2 << 16); }
+#else
+#define PC __pc
+#define OP_WORD(v) { v = rombase[(__pc - pcbase) >> 3] | (rombase[(__pc + 8 - pcbase) >> 3] << 8); _pc += 16; }
+#define PARAM_WORD(v) { v = rambase[(__pc + 16 - pcbase) >> 3] | (rambase[(__pc + 24 - pcbase) >> 3] << 8); _pc += 16; }
+#define PARAM_LONG(v) { v = rambase[(__pc + 16 - pcbase) >> 3] | (rambase[(__pc + 24 - pcbase) >> 3] << 8) | (rambase[(__pc + 32 - pcbase) >> 3] << 16) | (rambase[(__pc + 40 - pcbase) >> 3] << 24); _pc += 32; }
+#endif
+
+static UINT8 rf;
+static UINT32 __pc, _pc;
+static UINT16 op,rs,rd;
+
+static char *buffer;
+static char temp[20];
+
+static const UINT8 *rombase;
+static const UINT8 *rambase;
+static offs_t pcbase;
+
+
+static void print_reg(UINT8 reg)
+{
+ if (reg != 0x0f)
+ {
+ sprintf(temp, "%c%d", rf, reg);
+ strcat(buffer, temp);
+ }
+ else
+ {
+ strcat(buffer, "SP");
+ }
+}
+
+static void print_src_reg(void)
+{
+ print_reg(rs);
+}
+
+static void print_des_reg(void)
+{
+ print_reg(rd);
+}
+
+static void print_src_des_reg(void)
+{
+ print_src_reg();
+ strcat(buffer, ",");
+ print_des_reg();
+}
+
+static void print_word_parm(void)
+{
+ UINT16 w;
+
+ PARAM_WORD(w);
+
+ sprintf(temp, "%Xh", w);
+ strcat(buffer, temp);
+}
+
+static void print_word_parm_1s_comp(void)
+{
+ UINT16 w;
+
+ PARAM_WORD(w);
+ w = ~w;
+ sprintf(temp, "%Xh", w);
+ strcat(buffer, temp);
+}
+
+static void print_long_parm(void)
+{
+ UINT32 l;
+
+ PARAM_LONG(l);
+ sprintf(temp, "%Xh", l);
+ strcat(buffer, temp);
+}
+
+static void print_long_parm_1s_comp(void)
+{
+ UINT32 l;
+
+ PARAM_LONG(l);
+ sprintf(temp, "%Xh", ~l);
+ strcat(buffer, temp);
+}
+
+static void print_constant(void)
+{
+ UINT8 constant = (op >> 5) & 0x1f;
+
+ sprintf(temp, "%Xh", constant);
+ strcat(buffer, temp);
+}
+
+static void print_constant_1_32(void)
+{
+ UINT8 constant = (op >> 5) & 0x1f;
+ if (!constant) constant = 0x20;
+
+ sprintf(temp, "%Xh", constant);
+ strcat(buffer, temp);
+}
+
+static void print_constant_1s_comp(void)
+{
+ UINT8 constant = (~op >> 5) & 0x1f;
+
+ sprintf(temp, "%Xh", constant);
+ strcat(buffer, temp);
+}
+
+static void print_constant_2s_comp(void)
+{
+ UINT8 constant = 32 - ((op >> 5) & 0x1f);
+
+ sprintf(temp, "%Xh", constant);
+ strcat(buffer, temp);
+}
+
+static void print_relative(void)
+{
+ UINT16 l;
+ INT16 ls;
+
+ PARAM_WORD(l);
+ ls = (INT16)l;
+
+ sprintf(temp, "%Xh", PC + 32 + (ls << 4));
+ strcat(buffer, temp);
+}
+
+static void print_relative_8bit(void)
+{
+ INT8 ls = (INT8)op;
+
+ sprintf(temp, "%Xh", PC + 16 + (ls << 4));
+ strcat(buffer, temp);
+}
+
+static void print_relative_5bit(void)
+{
+ INT8 ls = (INT8)((op >> 5) & 0x1f);
+ if (op & 0x0400) ls = -ls;
+
+ sprintf(temp, "%Xh", PC + 16 + (ls << 4));
+ strcat(buffer, temp);
+}
+
+static void print_field(void)
+{
+ sprintf(temp, "%c", (op & 0x200) ? '1' : '0');
+ strcat(buffer, temp);
+}
+
+static void print_condition_code(void)
+{
+ switch (op & 0x0f00)
+ {
+ case 0x0000: strcat(buffer, " "); break; /* This is really UC (Unconditional) */
+ case 0x0100: strcat(buffer, "P "); break;
+ case 0x0200: strcat(buffer, "LS"); break;
+ case 0x0300: strcat(buffer, "HI"); break;
+ case 0x0400: strcat(buffer, "LT"); break;
+ case 0x0500: strcat(buffer, "GE"); break;
+ case 0x0600: strcat(buffer, "LE"); break;
+ case 0x0700: strcat(buffer, "GT"); break;
+ case 0x0800: strcat(buffer, "C "); break;
+ case 0x0900: strcat(buffer, "NC"); break;
+ case 0x0a00: strcat(buffer, "EQ"); break;
+ case 0x0b00: strcat(buffer, "NE"); break;
+ case 0x0c00: strcat(buffer, "V "); break;
+ case 0x0d00: strcat(buffer, "NV"); break;
+ case 0x0e00: strcat(buffer, "N "); break;
+ case 0x0f00: strcat(buffer, "NN"); break;
+ }
+}
+
+static void print_reg_list_range(INT8 first, INT8 last)
+{
+ if ((first != -1 ) && (first != last))
+ {
+ if ((last - first) == 1)
+ strcat(buffer, ",");
+ else
+ strcat(buffer, "-");
+ print_reg(last);
+ }
+}
+
+static void print_reg_list(UINT16 rev)
+{
+ UINT16 l;
+ UINT8 i;
+ INT8 first = -1, last = 0;
+
+ PARAM_WORD(l);
+
+ for (i = 0; i < 16; i++)
+ {
+ int moved;
+
+ if (rev)
+ {
+ moved = l & 0x8000;
+ l <<= 1;
+ }
+ else
+ {
+ moved = l & 0x01;
+ l >>= 1;
+ }
+
+ if (moved)
+ {
+ if (first == -1)
+ {
+ strcat(buffer, ",");
+ print_reg(i);
+ first = i;
+ }
+ last = i;
+ }
+ else
+ {
+ print_reg_list_range(first, last);
+ first = -1;
+ }
+ }
+
+ print_reg_list_range(first, last);
+}
+
+
+static unsigned Dasm340x0(char *buff, UINT32 pc, int is_34020)
+{
+ int flags = 0;
+ UINT8 bad = 0;
+ UINT16 subop;
+
+ __pc = _pc = pc;
+ buffer = buff;
+
+ OP_WORD(op);
+
+ subop = (op & 0x01e0);
+ rs = (op >> 5) & 0x0f; /* Source register */
+ rd = op & 0x0f; /* Destination register */
+ rf = ((op & 0x10) ? 'B' : 'A'); /* Register file */
+
+ switch (op & 0xfe00)
+ {
+ case 0x0000:
+ switch (subop)
+ {
+ case 0x0020:
+ sprintf (buffer, "REV ");
+ print_des_reg();
+ break;
+
+ case 0x0040:
+ if (is_34020)
+ sprintf (buffer, "IDLE ");
+ else
+ bad = 1;
+ break;
+
+ case 0x0080:
+ if (is_34020)
+ sprintf (buffer, "MWAIT ");
+ else
+ bad = 1;
+ break;
+
+ case 0x00e0:
+ if (is_34020)
+ sprintf (buffer, "BLMOVE %d,%d", (op >> 1) & 1, op & 1);
+ else
+ bad = 1;
+ break;
+
+ case 0x0100:
+ sprintf (buffer, "EMU ");
+ break;
+
+ case 0x0120:
+ sprintf (buffer, "EXGPC ");
+ print_des_reg();
+ break;
+
+ case 0x0140:
+ sprintf (buffer, "GETPC ");
+ print_des_reg();
+ break;
+
+ case 0x0160:
+ sprintf (buffer, "JUMP ");
+ print_des_reg();
+ break;
+
+ case 0x0180:
+ sprintf (buffer, "GETST ");
+ print_des_reg();
+ break;
+
+ case 0x01a0:
+ sprintf (buffer, "PUTST ");
+ print_des_reg();
+ break;
+
+ case 0x01c0:
+ sprintf (buffer, "POPST ");
+ break;
+
+ case 0x01e0:
+ sprintf (buffer, "PUSHST ");
+ break;
+
+ default:
+ bad = 1;
+ }
+ break;
+
+
+ case 0x0200:
+ switch (subop)
+ {
+ case 0x0040:
+ if (is_34020)
+ sprintf (buffer, "SETCSP ");
+ else
+ bad = 1;
+ break;
+
+ case 0x0060:
+ if (is_34020)
+ sprintf (buffer, "SETCDP ");
+ else
+ bad = 1;
+ break;
+
+ case 0x0080:
+ if (is_34020)
+ {
+ sprintf (buffer, "RPIX ");
+ print_des_reg();
+ }
+ else
+ bad = 1;
+ break;
+
+ case 0x00a0:
+ if (is_34020)
+ {
+ sprintf (buffer, "EXGPS ");
+ print_des_reg();
+ }
+ else
+ bad = 1;
+ break;
+
+ case 0x00c0:
+ if (is_34020)
+ {
+ sprintf (buffer, "GETPS ");
+ print_des_reg();
+ }
+ else
+ bad = 1;
+ break;
+
+ case 0x00e0:
+ if (is_34020)
+ sprintf (buffer, "SETCMP ");
+ else
+ bad = 1;
+ break;
+
+ case 0x0100:
+ sprintf (buffer, "NOP ");
+ break;
+
+ case 0x0120:
+ sprintf (buffer, "CLRC ");
+ break;
+
+ case 0x0140:
+ sprintf (buffer, "MOVB @");
+ print_long_parm();
+ strcat(buffer, ",@");
+ print_long_parm();
+ break;
+
+ case 0x0160:
+ sprintf (buffer, "DINT ");
+ break;
+
+ case 0x0180:
+ sprintf (buffer, "ABS ");
+ print_des_reg();
+ break;
+
+ case 0x01a0:
+ sprintf (buffer, "NEG ");
+ print_des_reg();
+ break;
+
+ case 0x01c0:
+ sprintf (buffer, "NEGB ");
+ print_des_reg();
+ break;
+
+ case 0x01e0:
+ sprintf (buffer, "NOT ");
+ print_des_reg();
+ break;
+
+ default:
+ bad = 1;
+ }
+ break;
+
+
+ case 0x0400:
+ case 0x0600:
+ switch (subop)
+ {
+ case 0x0000:
+ if (is_34020 && (op & 0xfe00) == 0x0600)
+ {
+ UINT32 x;
+ PARAM_LONG(x);
+ sprintf(buffer, "CEXEC %d,%06X,%d", (x >> 7) & 1, (x >> 8) & 0x1fffff, (x >> 29) & 7);
+ }
+ else
+ bad = 1;
+ break;
+
+ case 0x0020:
+ if (is_34020 && (op & 0xfe00) == 0x0600)
+ {
+ UINT32 x;
+ PARAM_LONG(x);
+ sprintf(buffer, "CMOVGC ");
+ print_des_reg();
+ sprintf(temp, ",%06X,%d", (x >> 8) & 0x1fffff, (x >> 29) & 7);
+ strcat(buffer, temp);
+ }
+ else
+ bad = 1;
+ break;
+
+ case 0x0040:
+ if (is_34020 && (op & 0xfe00) == 0x0600)
+ {
+ UINT32 x;
+ PARAM_LONG(x);
+ sprintf(buffer, "CMOVGC ");
+ print_des_reg();
+ strcat(buffer, ",");
+ rf = (x & 0x10) ? 'B' : 'A';
+ print_reg(x & 0x0f);
+ sprintf(temp, ",%d,%06X,%d", (x >> 7) & 1, (x >> 8) & 0x1fffff, (x >> 29) & 7);
+ strcat(buffer, temp);
+ }
+ else
+ bad = 1;
+ break;
+
+ case 0x0060:
+ if (is_34020 && (op & 0xfe00) == 0x0600)
+ {
+ UINT32 x;
+ PARAM_LONG(x);
+
+ if (op == 0x0660 && (x & 0xff) == 0x01)
+ {
+ sprintf(buffer, "CMOVCS ");
+ sprintf(temp, ",%06X,%d", (x >> 8) & 0x1fffff, (x >> 29) & 7);
+ strcat(buffer, temp);
+ }
+ else
+ {
+ sprintf(buffer, "CMOVCG ");
+ print_des_reg();
+ strcat(buffer, ",");
+ rf = (x & 0x10) ? 'B' : 'A';
+ print_reg(x & 0x0f);
+ sprintf(temp, ",%d,%06X,%d", (x >> 7) & 1, (x >> 8) & 0x1fffff, (x >> 29) & 7);
+ strcat(buffer, temp);
+ }
+ }
+ else
+ bad = 1;
+ break;
+
+ case 0x0080:
+ if (is_34020 && (op & 0xfe00) == 0x0600)
+ {
+ UINT32 x;
+ PARAM_LONG(x);
+ sprintf(buffer, "CMOVMC *");
+ rf = (x & 0x10) ? 'B' : 'A';
+ print_reg(x & 0x0f);
+ sprintf(temp, "+,%d,%d,%06X,%d", op & 0x1f, (x >> 7) & 1, (x >> 8) & 0x1fffff, (x >> 29) & 7);
+ strcat(buffer, temp);
+ }
+ else
+ bad = 1;
+ break;
+
+ case 0x00a0:
+ if (is_34020 && (op & 0xfe00) == 0x0600)
+ {
+ UINT32 x;
+ PARAM_LONG(x);
+ sprintf(buffer, "CMOVCM *");
+ print_des_reg();
+ sprintf(temp, "+,%d,%d,%06X,%d", x & 0x1f, (x >> 7) & 1, (x >> 8) & 0x1fffff, (x >> 29) & 7);
+ strcat(buffer, temp);
+ }
+ else
+ bad = 1;
+ break;
+
+ case 0x00c0:
+ if (is_34020 && (op & 0xfe00) == 0x0600)
+ {
+ UINT32 x;
+ PARAM_LONG(x);
+ sprintf(buffer, "CMOVCM *-");
+ print_des_reg();
+ sprintf(temp, ",%d,%d,%06X,%d", x & 0x1f, (x >> 7) & 1, (x >> 8) & 0x1fffff, (x >> 29) & 7);
+ strcat(buffer, temp);
+ }
+ else
+ bad = 1;
+ break;
+
+ case 0x00e0:
+ if (is_34020 && (op & 0xfe00) == 0x0600)
+ {
+ UINT32 x;
+ PARAM_LONG(x);
+ sprintf(buffer, "CMOVMC *");
+ rf = (x & 0x10) ? 'B' : 'A';
+ print_reg(x & 0x0f);
+ strcat(buffer, "+,");
+ rf = (op & 0x10) ? 'B' : 'A';
+ print_reg(op & 0x0f);
+ sprintf(temp, ",%d,%06X,%d", (x >> 7) & 1, (x >> 8) & 0x1fffff, (x >> 29) & 7);
+ strcat(buffer, temp);
+ }
+ else
+ bad = 1;
+ break;
+
+ case 0x0100:
+ sprintf (buffer, "SEXT ");
+ print_des_reg();
+ strcat(buffer, ",");
+ print_field();
+ break;
+
+ case 0x0120:
+ sprintf (buffer, "ZEXT ");
+ print_des_reg();
+ strcat(buffer, ",");
+ print_field();
+ break;
+
+ case 0x0140:
+ case 0x0160:
+ sprintf (buffer, "SETF %Xh,%X,",
+ (op & 0x1f) ? op & 0x1f : 0x20,
+ (op >> 5) & 1);
+ print_field();
+ break;
+
+ case 0x0180:
+ sprintf (buffer, "MOVE ");
+ print_des_reg();
+ strcat(buffer, ",@");
+ print_long_parm();
+ strcat(buffer, ",");
+ print_field();
+ break;
+
+ case 0x01a0:
+ sprintf (buffer, "MOVE @");
+ print_long_parm();
+ strcat(buffer, ",");
+ print_des_reg();
+ strcat(buffer, ",");
+ print_field();
+ break;
+
+ case 0x01c0:
+ sprintf (buffer, "MOVE @");
+ print_long_parm();
+ strcat(buffer, ",@");
+ print_long_parm();
+ strcat(buffer, ",");
+ print_field();
+ break;
+
+ case 0x01e0:
+ if (op & 0x200)
+ {
+ sprintf (buffer, "MOVE @");
+ print_long_parm();
+ strcat(buffer, ",");
+ print_des_reg();
+ }
+ else
+ {
+ sprintf (buffer, "MOVB ");
+ print_des_reg();
+ strcat(buffer, ",@");
+ print_long_parm();
+ }
+ break;
+
+ default:
+ bad = 1;
+ }
+ break;
+
+
+ case 0x0800:
+ switch (subop)
+ {
+ case 0x0000:
+ if (is_34020)
+ {
+ sprintf (buffer, "TRAPL ");
+ flags = DASMFLAG_STEP_OVER;
+ }
+ else
+ bad = 1;
+ break;
+
+ case 0x0020:
+ if (is_34020)
+ {
+ UINT32 x;
+ PARAM_LONG(x);
+ sprintf(buffer, "CMOVMC *-");
+ rf = (x & 0x10) ? 'B' : 'A';
+ print_reg(x & 0x0f);
+ sprintf(temp, ",%d,%d,%06X,%d", op & 0x1f, (x >> 7) & 1, (x >> 8) & 0x1fffff, (x >> 29) & 7);
+ strcat(buffer, temp);
+ }
+ else
+ bad = 1;
+ break;
+
+ case 0x0040:
+ if (is_34020)
+ sprintf (buffer, "VBLT B,L");
+ else
+ bad = 1;
+ break;
+
+ case 0x0060:
+ if (is_34020)
+ {
+ sprintf(buffer, "RETM ");
+ flags = DASMFLAG_STEP_OUT;
+ }
+ else
+ bad = 1;
+ break;
+
+ case 0x00e0:
+ if (is_34020)
+ sprintf (buffer, "CLIP ");
+ else
+ bad = 1;
+ break;
+
+ case 0x0100:
+ sprintf (buffer, "TRAP %Xh", op & 0x1f);
+ flags = DASMFLAG_STEP_OVER;
+ break;
+
+ case 0x0120:
+ sprintf (buffer, "CALL ");
+ print_des_reg();
+ flags = DASMFLAG_STEP_OVER;
+ break;
+
+ case 0x0140:
+ sprintf (buffer, "RETI ");
+ flags = DASMFLAG_STEP_OUT;
+ break;
+
+ case 0x0160:
+ sprintf (buffer, "RETS ");
+ flags = DASMFLAG_STEP_OUT;
+ if (op & 0x1f)
+ {
+ sprintf(temp, "%Xh", op & 0x1f);
+ strcat(buffer, temp);
+ }
+ break;
+
+ case 0x0180:
+ sprintf (buffer, "MMTM ");
+ print_des_reg();
+ print_reg_list(1);
+ break;
+
+ case 0x01a0:
+ sprintf (buffer, "MMFM ");
+ print_des_reg();
+ print_reg_list(0);
+ break;
+
+ case 0x01c0:
+ sprintf (buffer, "MOVI ");
+ print_word_parm();
+ strcat(buffer, ",");
+ print_des_reg();
+ break;
+
+ case 0x01e0:
+ sprintf (buffer, "MOVI ");
+ print_long_parm();
+ strcat(buffer, ",");
+ print_des_reg();
+ break;
+
+ default:
+ bad = 1;
+ }
+ break;
+
+
+ case 0x0a00:
+ switch (subop)
+ {
+ case 0x0000:
+ if (is_34020)
+ sprintf (buffer, "VLCOL ");
+ else
+ bad = 1;
+ break;
+
+ case 0x0020:
+ if (is_34020)
+ sprintf (buffer, "PFILL XY");
+ else
+ bad = 1;
+ break;
+
+ case 0x0040:
+ if (is_34020)
+ sprintf (buffer, "VFILL L");
+ else
+ bad = 1;
+ break;
+
+ case 0x0060:
+ if (is_34020)
+ {
+ sprintf (buffer, "CVMXYL ");
+ print_des_reg();
+ }
+ else
+ bad = 1;
+ break;
+
+ case 0x0080:
+ if (is_34020)
+ {
+ sprintf (buffer, "CVDXYL ");
+ print_des_reg();
+ }
+ else
+ bad = 1;
+ break;
+
+ case 0x00a0:
+ if (is_34020)
+ sprintf (buffer, "FPIXEQ ");
+ else
+ bad = 1;
+ break;
+
+ case 0x00c0:
+ if (is_34020)
+ sprintf (buffer, "FPIXNE ");
+ else
+ bad = 1;
+ break;
+
+ case 0x0100:
+ sprintf (buffer, "ADDI ");
+ print_word_parm();
+ strcat(buffer, ",");
+ print_des_reg();
+ break;
+
+ case 0x0120:
+ sprintf (buffer, "ADDI ");
+ print_long_parm();
+ strcat(buffer, ",");
+ print_des_reg();
+ break;
+
+ case 0x0140:
+ sprintf (buffer, "CMPI ");
+ print_word_parm_1s_comp();
+ strcat(buffer, ",");
+ print_des_reg();
+ break;
+
+ case 0x0160:
+ sprintf (buffer, "CMPI ");
+ print_long_parm_1s_comp();
+ strcat(buffer, ",");
+ print_des_reg();
+ break;
+
+ case 0x0180:
+ sprintf (buffer, "ANDI ");
+ print_long_parm_1s_comp();
+ strcat(buffer, ",");
+ print_des_reg();
+ break;
+
+ case 0x01a0:
+ sprintf (buffer, "ORI ");
+ print_long_parm();
+ strcat(buffer, ",");
+ print_des_reg();
+ break;
+
+ case 0x01c0:
+ sprintf (buffer, "XORI ");
+ print_long_parm();
+ strcat(buffer, ",");
+ print_des_reg();
+ break;
+
+ case 0x01e0:
+ sprintf (buffer, "SUBI ");
+ print_word_parm_1s_comp();
+ strcat(buffer, ",");
+ print_des_reg();
+ break;
+
+ default:
+ bad = 1;
+ }
+ break;
+
+
+ case 0x0c00:
+ switch (subop)
+ {
+ case 0x0000:
+ if (is_34020)
+ {
+ sprintf (buffer, "ADDXYI ");
+ print_long_parm();
+ strcat(buffer, ",");
+ print_des_reg();
+ }
+ else
+ bad = 1;
+ break;
+
+ case 0x0040:
+ if (is_34020)
+ sprintf (buffer, "LINIT ");
+ else
+ bad = 1;
+ break;
+
+ case 0x0100:
+ sprintf (buffer, "SUBI ");
+ print_long_parm_1s_comp();
+ strcat(buffer, ",");
+ print_des_reg();
+ break;
+
+ case 0x0120:
+ sprintf (buffer, "CALLR ");
+ print_relative();
+ flags = DASMFLAG_STEP_OVER;
+ break;
+
+ case 0x0140:
+ sprintf (buffer, "CALLA ");
+ print_long_parm();
+ flags = DASMFLAG_STEP_OVER;
+ break;
+
+ case 0x0160:
+ sprintf (buffer, "EINT ");
+ break;
+
+ case 0x0180:
+ sprintf (buffer, "DSJ ");
+ print_des_reg();
+ strcat(buffer, ",");
+ print_relative();
+ flags = DASMFLAG_STEP_OVER;
+ break;
+
+ case 0x01a0:
+ sprintf (buffer, "DSJEQ ");
+ print_des_reg();
+ strcat(buffer, ",");
+ print_relative();
+ flags = DASMFLAG_STEP_OVER;
+ break;
+
+ case 0x01c0:
+ sprintf (buffer, "DSJNE ");
+ print_des_reg();
+ strcat(buffer, ",");
+ print_relative();
+ flags = DASMFLAG_STEP_OVER;
+ break;
+
+ case 0x01e0:
+ sprintf (buffer, "SETC ");
+ break;
+
+ default:
+ bad = 1;
+ }
+ break;
+
+
+ case 0x0e00:
+ flags = DASMFLAG_STEP_OVER;
+ switch (subop)
+ {
+ case 0x0000:
+ if (is_34020)
+ sprintf (buffer, "PIXBLT L,M,L");
+ else
+ bad = 1;
+ break;
+
+ case 0x00e0:
+ if (is_34020)
+ sprintf (buffer, "TFILL XY");
+ else
+ bad = 1;
+ break;
+
+ case 0x0100:
+ sprintf (buffer, "PIXBLT L,L");
+ break;
+
+ case 0x0120:
+ sprintf (buffer, "PIXBLT L,XY");
+ break;
+
+ case 0x0140:
+ sprintf (buffer, "PIXBLT XY,L");
+ break;
+
+ case 0x0160:
+ sprintf (buffer, "PIXBLT XY,XY");
+ break;
+
+ case 0x0180:
+ sprintf (buffer, "PIXBLT B,L");
+ break;
+
+ case 0x01a0:
+ sprintf (buffer, "PIXBLT B,XY");
+ break;
+
+ case 0x01c0:
+ sprintf (buffer, "FILL L");
+ break;
+
+ case 0x01e0:
+ sprintf (buffer, "FILL XY");
+ break;
+
+ default:
+ bad = 1;
+ }
+ break;
+
+
+ case 0x1000:
+ case 0x1200:
+ if ((op & 0x03e0) != 0x0020)
+ {
+ sprintf (buffer, "ADDK ");
+ print_constant_1_32();
+ strcat(buffer, ",");
+ }
+ else
+ {
+ sprintf (buffer, "INC ");
+ }
+ print_des_reg();
+
+ break;
+
+
+ case 0x1400:
+ case 0x1600:
+ if ((op & 0x03e0) != 0x0020)
+ {
+ sprintf (buffer, "SUBK ");
+ print_constant_1_32();
+ strcat(buffer, ",");
+ }
+ else
+ {
+ sprintf (buffer, "DEC ");
+ }
+ print_des_reg();
+
+ break;
+
+
+ case 0x1800:
+ case 0x1a00:
+ sprintf (buffer, "MOVK ");
+ print_constant_1_32();
+ strcat(buffer, ",");
+ print_des_reg();
+ break;
+
+
+ case 0x1c00:
+ case 0x1e00:
+ sprintf (buffer, "BTST ");
+ print_constant_1s_comp();
+ strcat(buffer, ",");
+ print_des_reg();
+ break;
+
+
+ case 0x2000:
+ case 0x2200:
+ sprintf (buffer, "SLA ");
+ print_constant();
+ strcat(buffer, ",");
+ print_des_reg();
+ break;
+
+
+ case 0x2400:
+ case 0x2600:
+ sprintf (buffer, "SLL ");
+ print_constant();
+ strcat(buffer, ",");
+ print_des_reg();
+ break;
+
+
+ case 0x2800:
+ case 0x2a00:
+ sprintf (buffer, "SRA ");
+ print_constant_2s_comp();
+ strcat(buffer, ",");
+ print_des_reg();
+ break;
+
+
+ case 0x2c00:
+ case 0x2e00:
+ sprintf (buffer, "SRL ");
+ print_constant_2s_comp();
+ strcat(buffer, ",");
+ print_des_reg();
+ break;
+
+
+ case 0x3000:
+ case 0x3200:
+ sprintf (buffer, "RL ");
+ print_constant();
+ strcat(buffer, ",");
+ print_des_reg();
+ break;
+
+ case 0x3400:
+ case 0x3600:
+ if (is_34020)
+ {
+ sprintf (buffer, "CMPK ");
+ print_constant_1_32();
+ strcat(buffer, ",");
+ print_des_reg();
+ }
+ else
+ bad = 1;
+ break;
+
+ case 0x3800:
+ case 0x3a00:
+ case 0x3c00:
+ case 0x3e00:
+ sprintf (buffer, "DSJS ");
+ print_des_reg();
+ strcat(buffer, ",");
+ print_relative_5bit();
+ flags = DASMFLAG_STEP_OVER;
+ break;
+
+
+ case 0x4000:
+ sprintf (buffer, "ADD ");
+ print_src_des_reg();
+ break;
+
+
+ case 0x4200:
+ sprintf (buffer, "ADDC ");
+ print_src_des_reg();
+ break;
+
+
+ case 0x4400:
+ sprintf (buffer, "SUB ");
+ print_src_des_reg();
+ break;
+
+
+ case 0x4600:
+ sprintf (buffer, "SUBB ");
+ print_src_des_reg();
+ break;
+
+
+ case 0x4800:
+ sprintf (buffer, "CMP ");
+ print_src_des_reg();
+ break;
+
+
+ case 0x4a00:
+ sprintf (buffer, "BTST ");
+ print_src_des_reg();
+ break;
+
+
+ case 0x4c00:
+ case 0x4e00:
+ sprintf (buffer, "MOVE ");
+
+ if (!(op & 0x0200))
+ {
+ print_src_des_reg();
+ }
+ else
+ {
+ print_src_reg();
+ strcat(buffer, ",");
+
+ if (rf == 'A')
+ {
+ rf = 'B';
+ }
+ else
+ {
+ rf = 'A';
+ }
+
+ print_des_reg();
+ }
+ break;
+
+
+ case 0x5000:
+ sprintf (buffer, "AND ");
+ print_src_des_reg();
+ break;
+
+
+ case 0x5200:
+ sprintf (buffer, "ANDN ");
+ print_src_des_reg();
+ break;
+
+
+ case 0x5400:
+ sprintf (buffer, "OR ");
+ print_src_des_reg();
+ break;
+
+
+ case 0x5600:
+ if (rs != rd)
+ {
+ sprintf (buffer, "XOR ");
+ print_src_des_reg();
+ }
+ else
+ {
+ sprintf (buffer, "CLR ");
+ print_des_reg();
+ }
+ break;
+
+
+ case 0x5800:
+ sprintf (buffer, "DIVS ");
+ print_src_des_reg();
+ break;
+
+
+ case 0x5a00:
+ sprintf (buffer, "DIVU ");
+ print_src_des_reg();
+ break;
+
+
+ case 0x5c00:
+ sprintf (buffer, "MPYS ");
+ print_src_des_reg();
+ break;
+
+
+ case 0x5e00:
+ sprintf (buffer, "MPYU ");
+ print_src_des_reg();
+ break;
+
+
+ case 0x6000:
+ sprintf (buffer, "SLA ");
+ print_src_des_reg();
+ break;
+
+
+ case 0x6200:
+ sprintf (buffer, "SLL ");
+ print_src_des_reg();
+ break;
+
+
+ case 0x6400:
+ sprintf (buffer, "SRA ");
+ print_src_des_reg();
+ break;
+
+
+ case 0x6600:
+ sprintf (buffer, "SRL ");
+ print_src_des_reg();
+ break;
+
+
+ case 0x6800:
+ sprintf (buffer, "RL ");
+ print_src_des_reg();
+ break;
+
+
+ case 0x6a00:
+ sprintf (buffer, "LMO ");
+ print_src_des_reg();
+ break;
+
+
+ case 0x6c00:
+ sprintf (buffer, "MODS ");
+ print_src_des_reg();
+ break;
+
+
+ case 0x6e00:
+ sprintf (buffer, "MODU ");
+ print_src_des_reg();
+ break;
+
+
+ case 0x7a00:
+ if (is_34020)
+ {
+ sprintf (buffer, "RMO ");
+ print_src_des_reg();
+ }
+ else
+ bad = 1;
+ break;
+
+ case 0x7e00:
+ if (is_34020)
+ {
+ sprintf (buffer, "SWAPF *");
+ print_src_des_reg();
+ strcat(buffer, ",0");
+ }
+ else
+ bad = 1;
+ break;
+
+
+ case 0x8000:
+ case 0x8200:
+ sprintf (buffer, "MOVE ");
+ print_src_reg();
+ strcat(buffer, ",*");
+ print_des_reg();
+ strcat(buffer, ",");
+ print_field();
+ break;
+
+
+ case 0x8400:
+ case 0x8600:
+ sprintf (buffer, "MOVE *");
+ print_src_des_reg();
+ strcat(buffer, ",");
+ print_field();
+ break;
+
+
+ case 0x8800:
+ case 0x8a00:
+ sprintf (buffer, "MOVE *");
+ print_src_reg();
+ strcat(buffer, ",*");
+ print_des_reg();
+ strcat(buffer, ",");
+ print_field();
+ break;
+
+
+ case 0x8c00:
+ sprintf (buffer, "MOVB ");
+ print_src_reg();
+ strcat(buffer, ",*");
+ print_des_reg();
+ break;
+
+
+ case 0x8e00:
+ sprintf (buffer, "MOVB *");
+ print_src_des_reg();
+ break;
+
+
+ case 0x9000:
+ case 0x9200:
+ sprintf (buffer, "MOVE ");
+ print_src_reg();
+ strcat(buffer, ",*");
+ print_des_reg();
+ strcat(buffer, "+,");
+ print_field();
+ break;
+
+
+ case 0x9400:
+ case 0x9600:
+ sprintf (buffer, "MOVE *");
+ print_src_reg();
+ strcat(buffer, "+,");
+ print_des_reg();
+ strcat(buffer, ",");
+ print_field();
+ break;
+
+
+ case 0x9800:
+ case 0x9a00:
+ sprintf (buffer, "MOVE *");
+ print_src_reg();
+ strcat(buffer, "+,*");
+ print_des_reg();
+ strcat(buffer, "+,");
+ print_field();
+ break;
+
+
+ case 0x9c00:
+ sprintf (buffer, "MOVB *");
+ print_src_reg();
+ strcat(buffer, ",*");
+ print_des_reg();
+ break;
+
+
+ case 0xa000:
+ case 0xa200:
+ sprintf (buffer, "MOVE ");
+ print_src_reg();
+ strcat(buffer, ",-*");
+ print_des_reg();
+ strcat(buffer, ",");
+ print_field();
+ break;
+
+
+ case 0xa400:
+ case 0xa600:
+ sprintf (buffer, "MOVE -*");
+ print_src_des_reg();
+ strcat(buffer, ",");
+ print_field();
+ break;
+
+
+ case 0xa800:
+ case 0xaa00:
+ sprintf (buffer, "MOVE -*");
+ print_src_reg();
+ strcat(buffer, ",-*");
+ print_des_reg();
+ strcat(buffer, ",");
+ print_field();
+ break;
+
+
+ case 0xac00:
+ sprintf (buffer, "MOVB ");
+ print_src_reg();
+ strcat(buffer, ",*");
+ print_des_reg();
+ strcat(buffer, "(");
+ print_word_parm();
+ strcat(buffer, ")");
+ break;
+
+
+ case 0xae00:
+ sprintf (buffer, "MOVB *");
+ print_src_reg();
+ strcat(buffer, "(");
+ print_word_parm();
+ strcat(buffer, "),");
+ print_des_reg();
+ break;
+
+
+ case 0xb000:
+ case 0xb200:
+ sprintf (buffer, "MOVE ");
+ print_src_reg();
+ strcat(buffer, ",*");
+ print_des_reg();
+ strcat(buffer, "(");
+ print_word_parm();
+ strcat(buffer, "),");
+ print_field();
+ break;
+
+
+ case 0xb400:
+ case 0xb600:
+ sprintf (buffer, "MOVE *");
+ print_src_reg();
+ strcat(buffer, "(");
+ print_word_parm();
+ strcat(buffer, "),");
+ print_des_reg();
+ strcat(buffer, ",");
+ print_field();
+ break;
+
+
+ case 0xb800:
+ case 0xba00:
+ sprintf (buffer, "MOVE *");
+ print_src_reg();
+ strcat(buffer, "(");
+ print_word_parm();
+ strcat(buffer, "),*");
+ print_des_reg();
+ strcat(buffer, "(");
+ print_word_parm();
+ strcat(buffer, "),");
+ print_field();
+ break;
+
+
+ case 0xbc00:
+ sprintf (buffer, "MOVB *");
+ print_src_reg();
+ strcat(buffer, "(");
+ print_word_parm();
+ strcat(buffer, "),*");
+ print_des_reg();
+ strcat(buffer, "(");
+ print_word_parm();
+ strcat(buffer, ")");
+ break;
+
+
+ case 0xc000:
+ case 0xc200:
+ case 0xc400:
+ case 0xc600:
+ case 0xc800:
+ case 0xca00:
+ case 0xcc00:
+ case 0xce00:
+ if ((op & 0x00ff) == 0x80)
+ {
+ sprintf (buffer, "JA");
+ }
+ else
+ {
+ sprintf (buffer, "JR");
+ }
+
+ print_condition_code();
+ strcat (buffer, " ");
+
+ switch (op & 0x00ff)
+ {
+ case 0x00:
+ print_relative();
+ break;
+
+ case 0x80:
+ print_long_parm();
+ break;
+
+ default:
+ print_relative_8bit();
+ }
+ break;
+
+
+ case 0xd000:
+ case 0xd200:
+ sprintf (buffer, "MOVE *");
+ print_src_reg();
+ strcat(buffer, "(");
+ print_word_parm();
+ strcat(buffer, "),*");
+ print_des_reg();
+ strcat(buffer, "+,");
+ print_field();
+ break;
+
+
+ case 0xd400:
+ case 0xd600:
+ switch (subop)
+ {
+ case 0x0000:
+ sprintf (buffer, "MOVE @");
+ print_long_parm();
+ strcat(buffer, ",*");
+ print_des_reg();
+ strcat(buffer, "+,");
+ print_field();
+ break;
+
+ case 0x0100:
+ sprintf (buffer, "EXGF ");
+ print_des_reg();
+ strcat(buffer, ",");
+ print_field();
+ break;
+
+ default:
+ bad = 1;
+ }
+ break;
+
+ case 0xd800:
+ if (is_34020)
+ {
+ UINT32 x;
+ PARAM_WORD(x);
+ sprintf(buffer, "CEXEC %d,%06X,%d", op & 1, ((x << 5) & 0x1fffe0) | ((op >> 1) & 0x1f), (x >> 13) & 7);
+ }
+ else
+ bad = 1;
+ break;
+
+
+ case 0xde00:
+ switch (subop)
+ {
+ case 0x0000:
+ if (is_34020)
+ sprintf (buffer, "FLINE 0");
+ else
+ bad = 1;
+ break;
+
+ case 0x0080:
+ if (is_34020)
+ sprintf (buffer, "FLINE 1");
+ else
+ bad = 1;
+ break;
+
+ case 0x0100:
+ sprintf (buffer, "LINE 0");
+ break;
+
+ case 0x0180:
+ sprintf (buffer, "LINE 1");
+ break;
+
+ default:
+ bad = 1;
+ }
+ break;
+
+ case 0xe000:
+ sprintf (buffer, "ADDXY ");
+ print_src_des_reg();
+ break;
+
+
+ case 0xe200:
+ sprintf (buffer, "SUBXY ");
+ print_src_des_reg();
+ break;
+
+
+ case 0xe400:
+ sprintf (buffer, "CMPXY ");
+ print_src_des_reg();
+ break;
+
+
+ case 0xe600:
+ sprintf (buffer, "CPW ");
+ print_src_des_reg();
+ break;
+
+
+ case 0xe800:
+ sprintf (buffer, "CVXYL ");
+ print_src_des_reg();
+ break;
+
+
+ case 0xea00:
+ if (is_34020)
+ {
+ sprintf (buffer, "CVSXYL ");
+ print_src_des_reg();
+ }
+ else
+ bad = 1;
+ break;
+
+
+ case 0xec00:
+ sprintf (buffer, "MOVX ");
+ print_src_des_reg();
+ break;
+
+
+ case 0xee00:
+ sprintf (buffer, "MOVY ");
+ print_src_des_reg();
+ break;
+
+
+ case 0xf000:
+ sprintf (buffer, "PIXT ");
+ print_src_reg();
+ strcat(buffer, ",*");
+ print_des_reg();
+ strcat(buffer, ",XY");
+ break;
+
+
+ case 0xf200:
+ sprintf (buffer, "PIXT *");
+ print_src_reg();
+ strcat(buffer, ",XY,");
+ print_des_reg();
+ break;
+
+
+ case 0xf400:
+ sprintf (buffer, "PIXT *");
+ print_src_reg();
+ strcat(buffer, ",XY,*");
+ print_des_reg();
+ strcat(buffer, ",XY");
+ break;
+
+
+ case 0xf600:
+ sprintf (buffer, "DRAV ");
+ print_src_des_reg();
+ break;
+
+
+ case 0xf800:
+ sprintf (buffer, "PIXT ");
+ print_src_reg();
+ strcat(buffer, ",*");
+ print_des_reg();
+ break;
+
+
+ case 0xfa00:
+ sprintf (buffer, "PIXT *");
+ print_src_des_reg();
+ break;
+
+
+ case 0xfc00:
+ sprintf (buffer, "PIXT *");
+ print_src_reg();
+ strcat(buffer, ",*");
+ print_des_reg();
+ break;
+
+ default:
+ bad = 1;
+ }
+
+ if (bad)
+ {
+ sprintf (buffer, "DW %04Xh", op & 0xffff);
+ }
+
+ return (_pc - __pc) | flags | DASMFLAG_SUPPORTED;
+}
+
+CPU_DISASSEMBLE( tms34010 )
+{
+ rombase = oprom;
+ rambase = opram;
+ pcbase = pc;
+ return Dasm340x0(buffer, pc, 0);
+}
+
+CPU_DISASSEMBLE( tms34020 )
+{
+ rombase = oprom;
+ rambase = opram;
+ pcbase = pc;
+ return Dasm340x0(buffer, pc, 1);
+}
+
diff --git a/trunk/src/emu/cpu/tms34010/34010fld.c b/trunk/src/emu/cpu/tms34010/34010fld.c
new file mode 100644
index 00000000000..93897b295b1
--- /dev/null
+++ b/trunk/src/emu/cpu/tms34010/34010fld.c
@@ -0,0 +1,680 @@
+/***************************************************************************
+
+ TMS34010: Portable Texas Instruments TMS34010 emulator
+
+ Copyright Alex Pasadyn/Zsolt Vasvari
+ Parts based on code by Aaron Giles
+
+***************************************************************************/
+
+
+
+/***************************************************************************
+ FIELD WRITE FUNCTIONS
+***************************************************************************/
+
+static void wfield_01(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC(tms,0x01,16);
+}
+
+static void wfield_02(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC(tms,0x03,15);
+}
+
+static void wfield_03(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC(tms,0x07,14);
+}
+
+static void wfield_04(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC(tms,0x0f,13);
+}
+
+static void wfield_05(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC(tms,0x1f,12);
+}
+
+static void wfield_06(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC(tms,0x3f,11);
+}
+
+static void wfield_07(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC(tms,0x7f,10);
+}
+
+static void wfield_08(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC_8(tms);
+}
+
+static void wfield_09(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC(tms,0x1ff,8);
+}
+
+static void wfield_10(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC(tms,0x3ff,7);
+}
+
+static void wfield_11(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC(tms,0x7ff,6);
+}
+
+static void wfield_12(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC(tms,0xfff,5);
+}
+
+static void wfield_13(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC(tms,0x1fff,4);
+}
+
+static void wfield_14(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC(tms,0x3fff,3);
+}
+
+static void wfield_15(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC(tms,0x7fff,2);
+}
+
+static void wfield_16(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ if (offset & 0x0f)
+ {
+ WFIELDMAC(tms,0xffff,1);
+ }
+ else
+ {
+ TMS34010_WRMEM_WORD(tms,TOBYTE(offset),data);
+ }
+}
+
+static void wfield_17(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC(tms,0x1ffff,0);
+}
+
+static void wfield_18(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC_BIG(tms,0x3ffff,15);
+}
+
+static void wfield_19(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC_BIG(tms,0x7ffff,14);
+}
+
+static void wfield_20(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC_BIG(tms,0xfffff,13);
+}
+
+static void wfield_21(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC_BIG(tms,0x1fffff,12);
+}
+
+static void wfield_22(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC_BIG(tms,0x3fffff,11);
+}
+
+static void wfield_23(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC_BIG(tms,0x7fffff,10);
+}
+
+static void wfield_24(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC_BIG(tms,0xffffff,9);
+}
+
+static void wfield_25(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC_BIG(tms,0x1ffffff,8);
+}
+
+static void wfield_26(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC_BIG(tms,0x3ffffff,7);
+}
+
+static void wfield_27(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC_BIG(tms,0x7ffffff,6);
+}
+
+static void wfield_28(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC_BIG(tms,0xfffffff,5);
+}
+
+static void wfield_29(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC_BIG(tms,0x1fffffff,4);
+}
+
+static void wfield_30(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC_BIG(tms,0x3fffffff,3);
+}
+
+static void wfield_31(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC_BIG(tms,0x7fffffff,2);
+}
+
+static void wfield_32(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC_32(tms);
+}
+
+
+static void (*const tms34010_wfield_functions[32])(tms34010_state *tms, offs_t offset, UINT32 data) =
+{
+ wfield_32, wfield_01, wfield_02, wfield_03, wfield_04, wfield_05,
+ wfield_06, wfield_07, wfield_08, wfield_09, wfield_10, wfield_11,
+ wfield_12, wfield_13, wfield_14, wfield_15, wfield_16, wfield_17,
+ wfield_18, wfield_19, wfield_20, wfield_21, wfield_22, wfield_23,
+ wfield_24, wfield_25, wfield_26, wfield_27, wfield_28, wfield_29,
+ wfield_30, wfield_31
+};
+
+
+
+/***************************************************************************
+ FIELD READ FUNCTIONS (ZERO-EXTEND)
+***************************************************************************/
+
+static UINT32 rfield_z_01(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x01,16);
+ return ret;
+}
+
+static UINT32 rfield_z_02(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x03,15);
+ return ret;
+}
+
+static UINT32 rfield_z_03(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x07,14);
+ return ret;
+}
+
+static UINT32 rfield_z_04(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x0f,13);
+ return ret;
+}
+
+static UINT32 rfield_z_05(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x1f,12);
+ return ret;
+}
+
+static UINT32 rfield_z_06(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x3f,11);
+ return ret;
+}
+
+static UINT32 rfield_z_07(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x7f,10);
+ return ret;
+}
+
+static UINT32 rfield_z_08(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_8(tms);
+ return ret;
+}
+
+static UINT32 rfield_z_09(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x1ff,8);
+ return ret;
+}
+
+static UINT32 rfield_z_10(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x3ff,7);
+ return ret;
+}
+
+static UINT32 rfield_z_11(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x7ff,6);
+ return ret;
+}
+
+static UINT32 rfield_z_12(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0xfff,5);
+ return ret;
+}
+
+static UINT32 rfield_z_13(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x1fff,4);
+ return ret;
+}
+
+static UINT32 rfield_z_14(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x3fff,3);
+ return ret;
+}
+
+static UINT32 rfield_z_15(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x7fff,2);
+ return ret;
+}
+
+static UINT32 rfield_z_16(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ if (offset & 0x0f)
+ {
+ RFIELDMAC(tms,0xffff,1);
+ }
+
+ else
+ ret = TMS34010_RDMEM_WORD(tms,TOBYTE(offset));
+ return ret;
+}
+
+static UINT32 rfield_z_17(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x1ffff,0);
+ return ret;
+}
+
+static UINT32 rfield_z_18(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0x3ffff,15);
+ return ret;
+}
+
+static UINT32 rfield_z_19(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0x7ffff,14);
+ return ret;
+}
+
+static UINT32 rfield_z_20(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0xfffff,13);
+ return ret;
+}
+
+static UINT32 rfield_z_21(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0x1fffff,12);
+ return ret;
+}
+
+static UINT32 rfield_z_22(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0x3fffff,11);
+ return ret;
+}
+
+static UINT32 rfield_z_23(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0x7fffff,10);
+ return ret;
+}
+
+static UINT32 rfield_z_24(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0xffffff,9);
+ return ret;
+}
+
+static UINT32 rfield_z_25(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0x1ffffff,8);
+ return ret;
+}
+
+static UINT32 rfield_z_26(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0x3ffffff,7);
+ return ret;
+}
+
+static UINT32 rfield_z_27(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0x7ffffff,6);
+ return ret;
+}
+
+static UINT32 rfield_z_28(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0xfffffff,5);
+ return ret;
+}
+
+static UINT32 rfield_z_29(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0x1fffffff,4);
+ return ret;
+}
+
+static UINT32 rfield_z_30(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0x3fffffff,3);
+ return ret;
+}
+
+static UINT32 rfield_z_31(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0x7fffffff,2);
+ return ret;
+}
+
+static UINT32 rfield_32(tms34010_state *tms, offs_t offset)
+{
+ RFIELDMAC_32(tms);
+}
+
+
+/***************************************************************************
+ FIELD READ FUNCTIONS (SIGN-EXTEND)
+***************************************************************************/
+
+static UINT32 rfield_s_01(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x01,16);
+ return ((INT32)(ret << 31)) >> 31;
+}
+
+static UINT32 rfield_s_02(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x03,15);
+ return ((INT32)(ret << 30)) >> 30;
+}
+
+static UINT32 rfield_s_03(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x07,14);
+ return ((INT32)(ret << 29)) >> 29;
+}
+
+static UINT32 rfield_s_04(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x0f,13);
+ return ((INT32)(ret << 28)) >> 28;
+}
+
+static UINT32 rfield_s_05(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x1f,12);
+ return ((INT32)(ret << 27)) >> 27;
+}
+
+static UINT32 rfield_s_06(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x3f,11);
+ return ((INT32)(ret << 26)) >> 26;
+}
+
+static UINT32 rfield_s_07(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x7f,10);
+ return ((INT32)(ret << 25)) >> 25;
+}
+
+static UINT32 rfield_s_08(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ if (offset & 0x07)
+ {
+ RFIELDMAC(tms,0xff,9);
+ }
+
+ else
+ ret = TMS34010_RDMEM(tms,TOBYTE(offset));
+ return (INT32)(INT8)ret;
+}
+
+static UINT32 rfield_s_09(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x1ff,8);
+ return ((INT32)(ret << 23)) >> 23;
+}
+
+static UINT32 rfield_s_10(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x3ff,7);
+ return ((INT32)(ret << 22)) >> 22;
+}
+
+static UINT32 rfield_s_11(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x7ff,6);
+ return ((INT32)(ret << 21)) >> 21;
+}
+
+static UINT32 rfield_s_12(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0xfff,5);
+ return ((INT32)(ret << 20)) >> 20;
+}
+
+static UINT32 rfield_s_13(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x1fff,4);
+ return ((INT32)(ret << 19)) >> 19;
+}
+
+static UINT32 rfield_s_14(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x3fff,3);
+ return ((INT32)(ret << 18)) >> 18;
+}
+
+static UINT32 rfield_s_15(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x7fff,2);
+ return ((INT32)(ret << 17)) >> 17;
+}
+
+static UINT32 rfield_s_16(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ if (offset & 0x0f)
+ {
+ RFIELDMAC(tms,0xffff,1);
+ }
+
+ else
+ {
+ ret = TMS34010_RDMEM_WORD(tms,TOBYTE(offset));
+ }
+
+ return (INT32)(INT16)ret;
+}
+
+static UINT32 rfield_s_17(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC(tms,0x1ffff,0);
+ return ((INT32)(ret << 15)) >> 15;
+}
+
+static UINT32 rfield_s_18(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0x3ffff,15);
+ return ((INT32)(ret << 14)) >> 14;
+}
+
+static UINT32 rfield_s_19(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0x7ffff,14);
+ return ((INT32)(ret << 13)) >> 13;
+}
+
+static UINT32 rfield_s_20(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0xfffff,13);
+ return ((INT32)(ret << 12)) >> 12;
+}
+
+static UINT32 rfield_s_21(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0x1fffff,12);
+ return ((INT32)(ret << 11)) >> 11;
+}
+
+static UINT32 rfield_s_22(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0x3fffff,11);
+ return ((INT32)(ret << 10)) >> 10;
+}
+
+static UINT32 rfield_s_23(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0x7fffff,10);
+ return ((INT32)(ret << 9)) >> 9;
+}
+
+static UINT32 rfield_s_24(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0xffffff,9);
+ return ((INT32)(ret << 8)) >> 8;
+}
+
+static UINT32 rfield_s_25(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0x1ffffff,8);
+ return ((INT32)(ret << 7)) >> 7;
+}
+
+static UINT32 rfield_s_26(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0x3ffffff,7);
+ return ((INT32)(ret << 6)) >> 6;
+}
+
+static UINT32 rfield_s_27(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0x7ffffff,6);
+ return ((INT32)(ret << 5)) >> 5;
+}
+
+static UINT32 rfield_s_28(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0xfffffff,5);
+ return ((INT32)(ret << 4)) >> 4;
+}
+
+static UINT32 rfield_s_29(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0x1fffffff,4);
+ return ((INT32)(ret << 3)) >> 3;
+}
+
+static UINT32 rfield_s_30(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0x3fffffff,3);
+ return ((INT32)(ret << 2)) >> 2;
+}
+
+static UINT32 rfield_s_31(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_BIG(tms,0x7fffffff,2);
+ return ((INT32)(ret << 1)) >> 1;
+}
+
+static UINT32 (*const tms34010_rfield_functions[64])(tms34010_state *tms, offs_t offset) =
+{
+ rfield_32 , rfield_z_01, rfield_z_02, rfield_z_03, rfield_z_04, rfield_z_05,
+ rfield_z_06, rfield_z_07, rfield_z_08, rfield_z_09, rfield_z_10, rfield_z_11,
+ rfield_z_12, rfield_z_13, rfield_z_14, rfield_z_15, rfield_z_16, rfield_z_17,
+ rfield_z_18, rfield_z_19, rfield_z_20, rfield_z_21, rfield_z_22, rfield_z_23,
+ rfield_z_24, rfield_z_25, rfield_z_26, rfield_z_27, rfield_z_28, rfield_z_29,
+ rfield_z_30, rfield_z_31,
+ rfield_32 , rfield_s_01, rfield_s_02, rfield_s_03, rfield_s_04, rfield_s_05,
+ rfield_s_06, rfield_s_07, rfield_s_08, rfield_s_09, rfield_s_10, rfield_s_11,
+ rfield_s_12, rfield_s_13, rfield_s_14, rfield_s_15, rfield_s_16, rfield_s_17,
+ rfield_s_18, rfield_s_19, rfield_s_20, rfield_s_21, rfield_s_22, rfield_s_23,
+ rfield_s_24, rfield_s_25, rfield_s_26, rfield_s_27, rfield_s_28, rfield_s_29,
+ rfield_s_30, rfield_s_31
+};
+
diff --git a/trunk/src/emu/cpu/tms34010/34010gfx.c b/trunk/src/emu/cpu/tms34010/34010gfx.c
new file mode 100644
index 00000000000..39d02ad6d52
--- /dev/null
+++ b/trunk/src/emu/cpu/tms34010/34010gfx.c
@@ -0,0 +1,2043 @@
+/***************************************************************************
+
+ TMS34010: Portable Texas Instruments TMS34010 emulator
+
+ Copyright Alex Pasadyn/Zsolt Vasvari
+ Parts based on code by Aaron Giles
+
+***************************************************************************/
+
+#ifndef RECURSIVE_INCLUDE
+
+
+#define LOG_GFX_OPS 0
+#define LOGGFX(x) do { if (LOG_GFX_OPS && tms->device->machine().input().code_pressed(KEYCODE_L)) logerror x; } while (0)
+
+
+/* Graphics Instructions */
+
+static void line(tms34010_state *tms, UINT16 op)
+{
+ if (!P_FLAG(tms))
+ {
+ if (WINDOW_CHECKING(tms) != 0 && WINDOW_CHECKING(tms) != 3)
+ logerror("LINE XY %08X - Window Checking Mode %d not supported\n", tms->pc, WINDOW_CHECKING(tms));
+
+ tms->st |= STBIT_P;
+ TEMP(tms) = (op & 0x80) ? 1 : 0; /* boundary value depends on the algorithm */
+ LOGGFX(("%08X(%3d):LINE (%d,%d)-(%d,%d)\n", tms->pc, tms->screen->vpos(), DADDR_X(tms), DADDR_Y(tms), DADDR_X(tms) + DYDX_X(tms), DADDR_Y(tms) + DYDX_Y(tms)));
+ }
+
+ if (COUNT(tms) > 0)
+ {
+ INT16 x1,y1;
+
+ COUNT(tms)--;
+ if (WINDOW_CHECKING(tms) != 3 ||
+ (DADDR_X(tms) >= WSTART_X(tms) && DADDR_X(tms) <= WEND_X(tms) &&
+ DADDR_Y(tms) >= WSTART_Y(tms) && DADDR_Y(tms) <= WEND_Y(tms)))
+ WPIXEL(tms,DXYTOL(tms,DADDR_XY(tms)),COLOR1(tms));
+
+ if (SADDR(tms) >= TEMP(tms))
+ {
+ SADDR(tms) += DYDX_Y(tms)*2 - DYDX_X(tms)*2;
+ x1 = INC1_X(tms);
+ y1 = INC1_Y(tms);
+ }
+ else
+ {
+ SADDR(tms) += DYDX_Y(tms)*2;
+ x1 = INC2_X(tms);
+ y1 = INC2_Y(tms);
+ }
+ DADDR_X(tms) += x1;
+ DADDR_Y(tms) += y1;
+
+ COUNT_UNKNOWN_CYCLES(tms,2);
+ tms->pc -= 0x10; /* not done yet, check for interrupts and restart instruction */
+ return;
+ }
+ tms->st &= ~STBIT_P;
+}
+
+
+/*
+cases:
+* window modes (0,1,2,3)
+* boolean/arithmetic ops (16+6)
+* transparency (on/off)
+* plane masking
+* directions (left->right/right->left, top->bottom/bottom->top)
+*/
+
+static int apply_window(tms34010_state *tms, const char *inst_name,int srcbpp, UINT32 *srcaddr, XY *dst, int *dx, int *dy)
+{
+ /* apply the window */
+ if (WINDOW_CHECKING(tms) == 0)
+ return 0;
+ else
+ {
+ int sx = dst->x;
+ int sy = dst->y;
+ int ex = sx + *dx - 1;
+ int ey = sy + *dy - 1;
+ int diff, cycles = 3;
+
+ if (WINDOW_CHECKING(tms) == 2)
+ logerror("%08x: %s apply_window window mode %d not supported!\n", cpu_get_pc(tms->device), inst_name, WINDOW_CHECKING(tms));
+
+ CLR_V(tms);
+ if (WINDOW_CHECKING(tms) == 1)
+ SET_V_LOG(tms, 1);
+
+ /* clip X */
+ diff = WSTART_X(tms) - sx;
+ if (diff > 0)
+ {
+ if (srcaddr)
+ *srcaddr += diff * srcbpp;
+ sx += diff;
+ SET_V_LOG(tms, 1);
+ }
+ diff = ex - WEND_X(tms);
+ if (diff > 0)
+ {
+ ex -= diff;
+ SET_V_LOG(tms, 1);
+ }
+
+ /* clip Y */
+ diff = WSTART_Y(tms) - sy;
+ if (diff > 0)
+ {
+ if (srcaddr)
+ *srcaddr += diff * SPTCH(tms);
+ sy += diff;
+ SET_V_LOG(tms, 1);
+ }
+ diff = ey - WEND_Y(tms);
+ if (diff > 0)
+ {
+ ey -= diff;
+ SET_V_LOG(tms, 1);
+ }
+
+ /* compute cycles */
+ if (*dx != ex - sx + 1 || *dy != ey - sy + 1)
+ {
+ if (dst->x != sx || dst->y != sy)
+ cycles += 11;
+ else
+ cycles += 3;
+ }
+ else if (dst->x != sx || dst->y != sy)
+ cycles += 7;
+
+ /* update the values */
+ dst->x = sx;
+ dst->y = sy;
+ *dx = ex - sx + 1;
+ *dy = ey - sy + 1;
+ return cycles;
+ }
+}
+
+
+/*******************************************************************
+
+ About the timing of gfx operations:
+
+ The 34010 manual lists a fairly intricate and accurate way of
+ computing cycle timings for graphics ops. However, there are
+ enough typos and misleading statements to make the reliability
+ of the timing info questionable.
+
+ So, to address this, here is a simplified approximate version
+ of the timing.
+
+ timing = setup + (srcwords * 2 + dstwords * gfxop) * rows
+
+ Each read access takes 2 cycles. Each gfx operation has
+ its own timing as specified in the 34010 manual. So, it's 2
+ cycles per read plus gfxop cycles per operation. Pretty
+ simple, no?
+
+*******************************************************************/
+
+static int compute_fill_cycles(int left_partials, int right_partials, int full_words, int op_timing)
+{
+ int dstwords;
+
+ if (left_partials) full_words += 1;
+ if (right_partials) full_words += 1;
+ dstwords = full_words;
+
+ return (dstwords * op_timing);
+}
+
+static int compute_pixblt_cycles(int left_partials, int right_partials, int full_words, int op_timing)
+{
+ int srcwords, dstwords;
+
+ if (left_partials) full_words += 1;
+ if (right_partials) full_words += 1;
+ srcwords = full_words;
+ dstwords = full_words;
+
+ return (dstwords * op_timing + srcwords * 2) + 2;
+}
+
+static int compute_pixblt_b_cycles(int left_partials, int right_partials, int full_words, int rows, int op_timing, int bpp)
+{
+ int srcwords, dstwords;
+
+ if (left_partials) full_words += 1;
+ if (right_partials) full_words += 1;
+ srcwords = full_words * bpp / 16;
+ dstwords = full_words;
+
+ return (dstwords * op_timing + srcwords * 2) * rows + 2;
+}
+
+
+/* Shift register handling */
+static void memory_w(address_space *space, offs_t offset,UINT16 data)
+{
+ space->write_word(offset, data);
+}
+
+static UINT16 memory_r(address_space *space, offs_t offset)
+{
+ return space->read_word(offset);
+}
+
+static void shiftreg_w(address_space *space, offs_t offset,UINT16 data)
+{
+ tms34010_state *tms = get_safe_token(&space->device());
+ if (tms->config->from_shiftreg)
+ (*tms->config->from_shiftreg)(space, (UINT32)(offset << 3) & ~15, &tms->shiftreg[0]);
+ else
+ logerror("From ShiftReg function not set. PC = %08X\n", tms->pc);
+}
+
+static UINT16 shiftreg_r(address_space *space, offs_t offset)
+{
+ tms34010_state *tms = get_safe_token(&space->device());
+ if (tms->config->to_shiftreg)
+ (*tms->config->to_shiftreg)(space, (UINT32)(offset << 3) & ~15, &tms->shiftreg[0]);
+ else
+ logerror("To ShiftReg function not set. PC = %08X\n", tms->pc);
+ return tms->shiftreg[0];
+}
+
+static UINT16 dummy_shiftreg_r(address_space *space, offs_t offset)
+{
+ tms34010_state *tms = get_safe_token(&space->device());
+ return tms->shiftreg[0];
+}
+
+
+
+/* Pixel operations */
+static UINT32 pixel_op00(UINT32 dstpix, UINT32 mask, UINT32 srcpix) { return srcpix; }
+static UINT32 pixel_op01(UINT32 dstpix, UINT32 mask, UINT32 srcpix) { return srcpix & dstpix; }
+static UINT32 pixel_op02(UINT32 dstpix, UINT32 mask, UINT32 srcpix) { return srcpix & ~dstpix; }
+static UINT32 pixel_op03(UINT32 dstpix, UINT32 mask, UINT32 srcpix) { return 0; }
+static UINT32 pixel_op04(UINT32 dstpix, UINT32 mask, UINT32 srcpix) { return (srcpix | ~dstpix) & mask; }
+static UINT32 pixel_op05(UINT32 dstpix, UINT32 mask, UINT32 srcpix) { return ~(srcpix ^ dstpix) & mask; }
+static UINT32 pixel_op06(UINT32 dstpix, UINT32 mask, UINT32 srcpix) { return ~dstpix & mask; }
+static UINT32 pixel_op07(UINT32 dstpix, UINT32 mask, UINT32 srcpix) { return ~(srcpix | dstpix) & mask; }
+static UINT32 pixel_op08(UINT32 dstpix, UINT32 mask, UINT32 srcpix) { return (srcpix | dstpix) & mask; }
+static UINT32 pixel_op09(UINT32 dstpix, UINT32 mask, UINT32 srcpix) { return dstpix & mask; }
+static UINT32 pixel_op10(UINT32 dstpix, UINT32 mask, UINT32 srcpix) { return (srcpix ^ dstpix) & mask; }
+static UINT32 pixel_op11(UINT32 dstpix, UINT32 mask, UINT32 srcpix) { return (~srcpix & dstpix) & mask; }
+static UINT32 pixel_op12(UINT32 dstpix, UINT32 mask, UINT32 srcpix) { return mask; }
+static UINT32 pixel_op13(UINT32 dstpix, UINT32 mask, UINT32 srcpix) { return (~srcpix & dstpix) & mask; }
+static UINT32 pixel_op14(UINT32 dstpix, UINT32 mask, UINT32 srcpix) { return ~(srcpix & dstpix) & mask; }
+static UINT32 pixel_op15(UINT32 dstpix, UINT32 mask, UINT32 srcpix) { return srcpix ^ mask; }
+static UINT32 pixel_op16(UINT32 dstpix, UINT32 mask, UINT32 srcpix) { return (srcpix + dstpix) & mask; }
+static UINT32 pixel_op17(UINT32 dstpix, UINT32 mask, UINT32 srcpix) { INT32 tmp = srcpix + (dstpix & mask); return (tmp > mask) ? mask : tmp; }
+static UINT32 pixel_op18(UINT32 dstpix, UINT32 mask, UINT32 srcpix) { return (dstpix - srcpix) & mask; }
+static UINT32 pixel_op19(UINT32 dstpix, UINT32 mask, UINT32 srcpix) { INT32 tmp = srcpix - (dstpix & mask); return (tmp < 0) ? 0 : tmp; }
+static UINT32 pixel_op20(UINT32 dstpix, UINT32 mask, UINT32 srcpix) { dstpix &= mask; return (srcpix > dstpix) ? srcpix : dstpix; }
+static UINT32 pixel_op21(UINT32 dstpix, UINT32 mask, UINT32 srcpix) { dstpix &= mask; return (srcpix < dstpix) ? srcpix : dstpix; }
+
+static UINT32 (*const pixel_op_table[])(UINT32, UINT32, UINT32) =
+{
+ pixel_op00, pixel_op01, pixel_op02, pixel_op03, pixel_op04, pixel_op05, pixel_op06, pixel_op07,
+ pixel_op08, pixel_op09, pixel_op10, pixel_op11, pixel_op12, pixel_op13, pixel_op14, pixel_op15,
+ pixel_op16, pixel_op17, pixel_op18, pixel_op19, pixel_op20, pixel_op21, pixel_op00, pixel_op00,
+ pixel_op00, pixel_op00, pixel_op00, pixel_op00, pixel_op00, pixel_op00, pixel_op00, pixel_op00
+};
+static const UINT8 pixel_op_timing_table[] =
+{
+ 2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,6,5,5,2,2,2,2,2,2,2,2,2,2,2
+};
+static UINT32 (*pixel_op)(UINT32, UINT32, UINT32);
+static UINT32 pixel_op_timing;
+
+
+/* Blitters/fillers */
+static void pixblt_1_op0(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_2_op0(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_4_op0(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_8_op0(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_16_op0(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_r_1_op0(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_r_2_op0(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_r_4_op0(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_r_8_op0(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_r_16_op0(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_b_1_op0(tms34010_state *tms, int dst_is_linear);
+static void pixblt_b_2_op0(tms34010_state *tms, int dst_is_linear);
+static void pixblt_b_4_op0(tms34010_state *tms, int dst_is_linear);
+static void pixblt_b_8_op0(tms34010_state *tms, int dst_is_linear);
+static void pixblt_b_16_op0(tms34010_state *tms, int dst_is_linear);
+static void fill_1_op0(tms34010_state *tms, int dst_is_linear);
+static void fill_2_op0(tms34010_state *tms, int dst_is_linear);
+static void fill_4_op0(tms34010_state *tms, int dst_is_linear);
+static void fill_8_op0(tms34010_state *tms, int dst_is_linear);
+static void fill_16_op0(tms34010_state *tms, int dst_is_linear);
+
+static void pixblt_1_op0_trans(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_2_op0_trans(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_4_op0_trans(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_8_op0_trans(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_16_op0_trans(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_r_1_op0_trans(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_r_2_op0_trans(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_r_4_op0_trans(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_r_8_op0_trans(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_r_16_op0_trans(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_b_1_op0_trans(tms34010_state *tms, int dst_is_linear);
+static void pixblt_b_2_op0_trans(tms34010_state *tms, int dst_is_linear);
+static void pixblt_b_4_op0_trans(tms34010_state *tms, int dst_is_linear);
+static void pixblt_b_8_op0_trans(tms34010_state *tms, int dst_is_linear);
+static void pixblt_b_16_op0_trans(tms34010_state *tms, int dst_is_linear);
+static void fill_1_op0_trans(tms34010_state *tms, int dst_is_linear);
+static void fill_2_op0_trans(tms34010_state *tms, int dst_is_linear);
+static void fill_4_op0_trans(tms34010_state *tms, int dst_is_linear);
+static void fill_8_op0_trans(tms34010_state *tms, int dst_is_linear);
+static void fill_16_op0_trans(tms34010_state *tms, int dst_is_linear);
+
+static void pixblt_1_opx(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_2_opx(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_4_opx(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_8_opx(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_16_opx(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_r_1_opx(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_r_2_opx(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_r_4_opx(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_r_8_opx(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_r_16_opx(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_b_1_opx(tms34010_state *tms, int dst_is_linear);
+static void pixblt_b_2_opx(tms34010_state *tms, int dst_is_linear);
+static void pixblt_b_4_opx(tms34010_state *tms, int dst_is_linear);
+static void pixblt_b_8_opx(tms34010_state *tms, int dst_is_linear);
+static void pixblt_b_16_opx(tms34010_state *tms, int dst_is_linear);
+static void fill_1_opx(tms34010_state *tms, int dst_is_linear);
+static void fill_2_opx(tms34010_state *tms, int dst_is_linear);
+static void fill_4_opx(tms34010_state *tms, int dst_is_linear);
+static void fill_8_opx(tms34010_state *tms, int dst_is_linear);
+static void fill_16_opx(tms34010_state *tms, int dst_is_linear);
+
+static void pixblt_1_opx_trans(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_2_opx_trans(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_4_opx_trans(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_8_opx_trans(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_16_opx_trans(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_r_1_opx_trans(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_r_2_opx_trans(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_r_4_opx_trans(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_r_8_opx_trans(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_r_16_opx_trans(tms34010_state *tms, int src_is_linear, int dst_is_linear);
+static void pixblt_b_1_opx_trans(tms34010_state *tms, int dst_is_linear);
+static void pixblt_b_2_opx_trans(tms34010_state *tms, int dst_is_linear);
+static void pixblt_b_4_opx_trans(tms34010_state *tms, int dst_is_linear);
+static void pixblt_b_8_opx_trans(tms34010_state *tms, int dst_is_linear);
+static void pixblt_b_16_opx_trans(tms34010_state *tms, int dst_is_linear);
+static void fill_1_opx_trans(tms34010_state *tms, int dst_is_linear);
+static void fill_2_opx_trans(tms34010_state *tms, int dst_is_linear);
+static void fill_4_opx_trans(tms34010_state *tms, int dst_is_linear);
+static void fill_8_opx_trans(tms34010_state *tms, int dst_is_linear);
+static void fill_16_opx_trans(tms34010_state *tms, int dst_is_linear);
+
+
+/* tables */
+static void (*const pixblt_op_table[])(tms34010_state *, int, int) =
+{
+ pixblt_1_op0, pixblt_1_op0_trans, pixblt_1_opx, pixblt_1_opx_trans,
+ pixblt_1_opx, pixblt_1_opx_trans, pixblt_1_opx, pixblt_1_opx_trans,
+ pixblt_1_opx, pixblt_1_opx_trans, pixblt_1_opx, pixblt_1_opx_trans,
+ pixblt_1_opx, pixblt_1_opx_trans, pixblt_1_opx, pixblt_1_opx_trans,
+ pixblt_1_opx, pixblt_1_opx_trans, pixblt_1_opx, pixblt_1_opx_trans,
+ pixblt_1_opx, pixblt_1_opx_trans, pixblt_1_opx, pixblt_1_opx_trans,
+ pixblt_1_opx, pixblt_1_opx_trans, pixblt_1_opx, pixblt_1_opx_trans,
+ pixblt_1_opx, pixblt_1_opx_trans, pixblt_1_opx, pixblt_1_opx_trans,
+ pixblt_1_opx, pixblt_1_opx_trans, pixblt_1_opx, pixblt_1_opx_trans,
+ pixblt_1_opx, pixblt_1_opx_trans, pixblt_1_opx, pixblt_1_opx_trans,
+ pixblt_1_opx, pixblt_1_opx_trans, pixblt_1_opx, pixblt_1_opx_trans,
+ pixblt_1_opx, pixblt_1_opx_trans, pixblt_1_opx, pixblt_1_opx_trans,
+ pixblt_1_opx, pixblt_1_opx_trans, pixblt_1_opx, pixblt_1_opx_trans,
+ pixblt_1_opx, pixblt_1_opx_trans, pixblt_1_opx, pixblt_1_opx_trans,
+ pixblt_1_opx, pixblt_1_opx_trans, pixblt_1_opx, pixblt_1_opx_trans,
+ pixblt_1_opx, pixblt_1_opx_trans, pixblt_1_opx, pixblt_1_opx_trans,
+
+ pixblt_2_op0, pixblt_2_op0_trans, pixblt_2_opx, pixblt_2_opx_trans,
+ pixblt_2_opx, pixblt_2_opx_trans, pixblt_2_opx, pixblt_2_opx_trans,
+ pixblt_2_opx, pixblt_2_opx_trans, pixblt_2_opx, pixblt_2_opx_trans,
+ pixblt_2_opx, pixblt_2_opx_trans, pixblt_2_opx, pixblt_2_opx_trans,
+ pixblt_2_opx, pixblt_2_opx_trans, pixblt_2_opx, pixblt_2_opx_trans,
+ pixblt_2_opx, pixblt_2_opx_trans, pixblt_2_opx, pixblt_2_opx_trans,
+ pixblt_2_opx, pixblt_2_opx_trans, pixblt_2_opx, pixblt_2_opx_trans,
+ pixblt_2_opx, pixblt_2_opx_trans, pixblt_2_opx, pixblt_2_opx_trans,
+ pixblt_2_opx, pixblt_2_opx_trans, pixblt_2_opx, pixblt_2_opx_trans,
+ pixblt_2_opx, pixblt_2_opx_trans, pixblt_2_opx, pixblt_2_opx_trans,
+ pixblt_2_opx, pixblt_2_opx_trans, pixblt_2_opx, pixblt_2_opx_trans,
+ pixblt_2_opx, pixblt_2_opx_trans, pixblt_2_opx, pixblt_2_opx_trans,
+ pixblt_2_opx, pixblt_2_opx_trans, pixblt_2_opx, pixblt_2_opx_trans,
+ pixblt_2_opx, pixblt_2_opx_trans, pixblt_2_opx, pixblt_2_opx_trans,
+ pixblt_2_opx, pixblt_2_opx_trans, pixblt_2_opx, pixblt_2_opx_trans,
+ pixblt_2_opx, pixblt_2_opx_trans, pixblt_2_opx, pixblt_2_opx_trans,
+
+ pixblt_4_op0, pixblt_4_op0_trans, pixblt_4_opx, pixblt_4_opx_trans,
+ pixblt_4_opx, pixblt_4_opx_trans, pixblt_4_opx, pixblt_4_opx_trans,
+ pixblt_4_opx, pixblt_4_opx_trans, pixblt_4_opx, pixblt_4_opx_trans,
+ pixblt_4_opx, pixblt_4_opx_trans, pixblt_4_opx, pixblt_4_opx_trans,
+ pixblt_4_opx, pixblt_4_opx_trans, pixblt_4_opx, pixblt_4_opx_trans,
+ pixblt_4_opx, pixblt_4_opx_trans, pixblt_4_opx, pixblt_4_opx_trans,
+ pixblt_4_opx, pixblt_4_opx_trans, pixblt_4_opx, pixblt_4_opx_trans,
+ pixblt_4_opx, pixblt_4_opx_trans, pixblt_4_opx, pixblt_4_opx_trans,
+ pixblt_4_opx, pixblt_4_opx_trans, pixblt_4_opx, pixblt_4_opx_trans,
+ pixblt_4_opx, pixblt_4_opx_trans, pixblt_4_opx, pixblt_4_opx_trans,
+ pixblt_4_opx, pixblt_4_opx_trans, pixblt_4_opx, pixblt_4_opx_trans,
+ pixblt_4_opx, pixblt_4_opx_trans, pixblt_4_opx, pixblt_4_opx_trans,
+ pixblt_4_opx, pixblt_4_opx_trans, pixblt_4_opx, pixblt_4_opx_trans,
+ pixblt_4_opx, pixblt_4_opx_trans, pixblt_4_opx, pixblt_4_opx_trans,
+ pixblt_4_opx, pixblt_4_opx_trans, pixblt_4_opx, pixblt_4_opx_trans,
+ pixblt_4_opx, pixblt_4_opx_trans, pixblt_4_opx, pixblt_4_opx_trans,
+
+ pixblt_8_op0, pixblt_8_op0_trans, pixblt_8_opx, pixblt_8_opx_trans,
+ pixblt_8_opx, pixblt_8_opx_trans, pixblt_8_opx, pixblt_8_opx_trans,
+ pixblt_8_opx, pixblt_8_opx_trans, pixblt_8_opx, pixblt_8_opx_trans,
+ pixblt_8_opx, pixblt_8_opx_trans, pixblt_8_opx, pixblt_8_opx_trans,
+ pixblt_8_opx, pixblt_8_opx_trans, pixblt_8_opx, pixblt_8_opx_trans,
+ pixblt_8_opx, pixblt_8_opx_trans, pixblt_8_opx, pixblt_8_opx_trans,
+ pixblt_8_opx, pixblt_8_opx_trans, pixblt_8_opx, pixblt_8_opx_trans,
+ pixblt_8_opx, pixblt_8_opx_trans, pixblt_8_opx, pixblt_8_opx_trans,
+ pixblt_8_opx, pixblt_8_opx_trans, pixblt_8_opx, pixblt_8_opx_trans,
+ pixblt_8_opx, pixblt_8_opx_trans, pixblt_8_opx, pixblt_8_opx_trans,
+ pixblt_8_opx, pixblt_8_opx_trans, pixblt_8_opx, pixblt_8_opx_trans,
+ pixblt_8_opx, pixblt_8_opx_trans, pixblt_8_opx, pixblt_8_opx_trans,
+ pixblt_8_opx, pixblt_8_opx_trans, pixblt_8_opx, pixblt_8_opx_trans,
+ pixblt_8_opx, pixblt_8_opx_trans, pixblt_8_opx, pixblt_8_opx_trans,
+ pixblt_8_opx, pixblt_8_opx_trans, pixblt_8_opx, pixblt_8_opx_trans,
+ pixblt_8_opx, pixblt_8_opx_trans, pixblt_8_opx, pixblt_8_opx_trans,
+
+ pixblt_16_op0, pixblt_16_op0_trans, pixblt_16_opx, pixblt_16_opx_trans,
+ pixblt_16_opx, pixblt_16_opx_trans, pixblt_16_opx, pixblt_16_opx_trans,
+ pixblt_16_opx, pixblt_16_opx_trans, pixblt_16_opx, pixblt_16_opx_trans,
+ pixblt_16_opx, pixblt_16_opx_trans, pixblt_16_opx, pixblt_16_opx_trans,
+ pixblt_16_opx, pixblt_16_opx_trans, pixblt_16_opx, pixblt_16_opx_trans,
+ pixblt_16_opx, pixblt_16_opx_trans, pixblt_16_opx, pixblt_16_opx_trans,
+ pixblt_16_opx, pixblt_16_opx_trans, pixblt_16_opx, pixblt_16_opx_trans,
+ pixblt_16_opx, pixblt_16_opx_trans, pixblt_16_opx, pixblt_16_opx_trans,
+ pixblt_16_opx, pixblt_16_opx_trans, pixblt_16_opx, pixblt_16_opx_trans,
+ pixblt_16_opx, pixblt_16_opx_trans, pixblt_16_opx, pixblt_16_opx_trans,
+ pixblt_16_opx, pixblt_16_opx_trans, pixblt_16_opx, pixblt_16_opx_trans,
+ pixblt_16_opx, pixblt_16_opx_trans, pixblt_16_opx, pixblt_16_opx_trans,
+ pixblt_16_opx, pixblt_16_opx_trans, pixblt_16_opx, pixblt_16_opx_trans,
+ pixblt_16_opx, pixblt_16_opx_trans, pixblt_16_opx, pixblt_16_opx_trans,
+ pixblt_16_opx, pixblt_16_opx_trans, pixblt_16_opx, pixblt_16_opx_trans,
+ pixblt_16_opx, pixblt_16_opx_trans, pixblt_16_opx, pixblt_16_opx_trans
+};
+
+static void (*const pixblt_r_op_table[])(tms34010_state *, int, int) =
+{
+ pixblt_r_1_op0, pixblt_r_1_op0_trans, pixblt_r_1_opx, pixblt_r_1_opx_trans,
+ pixblt_r_1_opx, pixblt_r_1_opx_trans, pixblt_r_1_opx, pixblt_r_1_opx_trans,
+ pixblt_r_1_opx, pixblt_r_1_opx_trans, pixblt_r_1_opx, pixblt_r_1_opx_trans,
+ pixblt_r_1_opx, pixblt_r_1_opx_trans, pixblt_r_1_opx, pixblt_r_1_opx_trans,
+ pixblt_r_1_opx, pixblt_r_1_opx_trans, pixblt_r_1_opx, pixblt_r_1_opx_trans,
+ pixblt_r_1_opx, pixblt_r_1_opx_trans, pixblt_r_1_opx, pixblt_r_1_opx_trans,
+ pixblt_r_1_opx, pixblt_r_1_opx_trans, pixblt_r_1_opx, pixblt_r_1_opx_trans,
+ pixblt_r_1_opx, pixblt_r_1_opx_trans, pixblt_r_1_opx, pixblt_r_1_opx_trans,
+ pixblt_r_1_opx, pixblt_r_1_opx_trans, pixblt_r_1_opx, pixblt_r_1_opx_trans,
+ pixblt_r_1_opx, pixblt_r_1_opx_trans, pixblt_r_1_opx, pixblt_r_1_opx_trans,
+ pixblt_r_1_opx, pixblt_r_1_opx_trans, pixblt_r_1_opx, pixblt_r_1_opx_trans,
+ pixblt_r_1_opx, pixblt_r_1_opx_trans, pixblt_r_1_opx, pixblt_r_1_opx_trans,
+ pixblt_r_1_opx, pixblt_r_1_opx_trans, pixblt_r_1_opx, pixblt_r_1_opx_trans,
+ pixblt_r_1_opx, pixblt_r_1_opx_trans, pixblt_r_1_opx, pixblt_r_1_opx_trans,
+ pixblt_r_1_opx, pixblt_r_1_opx_trans, pixblt_r_1_opx, pixblt_r_1_opx_trans,
+ pixblt_r_1_opx, pixblt_r_1_opx_trans, pixblt_r_1_opx, pixblt_r_1_opx_trans,
+
+ pixblt_r_2_op0, pixblt_r_2_op0_trans, pixblt_r_2_opx, pixblt_r_2_opx_trans,
+ pixblt_r_2_opx, pixblt_r_2_opx_trans, pixblt_r_2_opx, pixblt_r_2_opx_trans,
+ pixblt_r_2_opx, pixblt_r_2_opx_trans, pixblt_r_2_opx, pixblt_r_2_opx_trans,
+ pixblt_r_2_opx, pixblt_r_2_opx_trans, pixblt_r_2_opx, pixblt_r_2_opx_trans,
+ pixblt_r_2_opx, pixblt_r_2_opx_trans, pixblt_r_2_opx, pixblt_r_2_opx_trans,
+ pixblt_r_2_opx, pixblt_r_2_opx_trans, pixblt_r_2_opx, pixblt_r_2_opx_trans,
+ pixblt_r_2_opx, pixblt_r_2_opx_trans, pixblt_r_2_opx, pixblt_r_2_opx_trans,
+ pixblt_r_2_opx, pixblt_r_2_opx_trans, pixblt_r_2_opx, pixblt_r_2_opx_trans,
+ pixblt_r_2_opx, pixblt_r_2_opx_trans, pixblt_r_2_opx, pixblt_r_2_opx_trans,
+ pixblt_r_2_opx, pixblt_r_2_opx_trans, pixblt_r_2_opx, pixblt_r_2_opx_trans,
+ pixblt_r_2_opx, pixblt_r_2_opx_trans, pixblt_r_2_opx, pixblt_r_2_opx_trans,
+ pixblt_r_2_opx, pixblt_r_2_opx_trans, pixblt_r_2_opx, pixblt_r_2_opx_trans,
+ pixblt_r_2_opx, pixblt_r_2_opx_trans, pixblt_r_2_opx, pixblt_r_2_opx_trans,
+ pixblt_r_2_opx, pixblt_r_2_opx_trans, pixblt_r_2_opx, pixblt_r_2_opx_trans,
+ pixblt_r_2_opx, pixblt_r_2_opx_trans, pixblt_r_2_opx, pixblt_r_2_opx_trans,
+ pixblt_r_2_opx, pixblt_r_2_opx_trans, pixblt_r_2_opx, pixblt_r_2_opx_trans,
+
+ pixblt_r_4_op0, pixblt_r_4_op0_trans, pixblt_r_4_opx, pixblt_r_4_opx_trans,
+ pixblt_r_4_opx, pixblt_r_4_opx_trans, pixblt_r_4_opx, pixblt_r_4_opx_trans,
+ pixblt_r_4_opx, pixblt_r_4_opx_trans, pixblt_r_4_opx, pixblt_r_4_opx_trans,
+ pixblt_r_4_opx, pixblt_r_4_opx_trans, pixblt_r_4_opx, pixblt_r_4_opx_trans,
+ pixblt_r_4_opx, pixblt_r_4_opx_trans, pixblt_r_4_opx, pixblt_r_4_opx_trans,
+ pixblt_r_4_opx, pixblt_r_4_opx_trans, pixblt_r_4_opx, pixblt_r_4_opx_trans,
+ pixblt_r_4_opx, pixblt_r_4_opx_trans, pixblt_r_4_opx, pixblt_r_4_opx_trans,
+ pixblt_r_4_opx, pixblt_r_4_opx_trans, pixblt_r_4_opx, pixblt_r_4_opx_trans,
+ pixblt_r_4_opx, pixblt_r_4_opx_trans, pixblt_r_4_opx, pixblt_r_4_opx_trans,
+ pixblt_r_4_opx, pixblt_r_4_opx_trans, pixblt_r_4_opx, pixblt_r_4_opx_trans,
+ pixblt_r_4_opx, pixblt_r_4_opx_trans, pixblt_r_4_opx, pixblt_r_4_opx_trans,
+ pixblt_r_4_opx, pixblt_r_4_opx_trans, pixblt_r_4_opx, pixblt_r_4_opx_trans,
+ pixblt_r_4_opx, pixblt_r_4_opx_trans, pixblt_r_4_opx, pixblt_r_4_opx_trans,
+ pixblt_r_4_opx, pixblt_r_4_opx_trans, pixblt_r_4_opx, pixblt_r_4_opx_trans,
+ pixblt_r_4_opx, pixblt_r_4_opx_trans, pixblt_r_4_opx, pixblt_r_4_opx_trans,
+ pixblt_r_4_opx, pixblt_r_4_opx_trans, pixblt_r_4_opx, pixblt_r_4_opx_trans,
+
+ pixblt_r_8_op0, pixblt_r_8_op0_trans, pixblt_r_8_opx, pixblt_r_8_opx_trans,
+ pixblt_r_8_opx, pixblt_r_8_opx_trans, pixblt_r_8_opx, pixblt_r_8_opx_trans,
+ pixblt_r_8_opx, pixblt_r_8_opx_trans, pixblt_r_8_opx, pixblt_r_8_opx_trans,
+ pixblt_r_8_opx, pixblt_r_8_opx_trans, pixblt_r_8_opx, pixblt_r_8_opx_trans,
+ pixblt_r_8_opx, pixblt_r_8_opx_trans, pixblt_r_8_opx, pixblt_r_8_opx_trans,
+ pixblt_r_8_opx, pixblt_r_8_opx_trans, pixblt_r_8_opx, pixblt_r_8_opx_trans,
+ pixblt_r_8_opx, pixblt_r_8_opx_trans, pixblt_r_8_opx, pixblt_r_8_opx_trans,
+ pixblt_r_8_opx, pixblt_r_8_opx_trans, pixblt_r_8_opx, pixblt_r_8_opx_trans,
+ pixblt_r_8_opx, pixblt_r_8_opx_trans, pixblt_r_8_opx, pixblt_r_8_opx_trans,
+ pixblt_r_8_opx, pixblt_r_8_opx_trans, pixblt_r_8_opx, pixblt_r_8_opx_trans,
+ pixblt_r_8_opx, pixblt_r_8_opx_trans, pixblt_r_8_opx, pixblt_r_8_opx_trans,
+ pixblt_r_8_opx, pixblt_r_8_opx_trans, pixblt_r_8_opx, pixblt_r_8_opx_trans,
+ pixblt_r_8_opx, pixblt_r_8_opx_trans, pixblt_r_8_opx, pixblt_r_8_opx_trans,
+ pixblt_r_8_opx, pixblt_r_8_opx_trans, pixblt_r_8_opx, pixblt_r_8_opx_trans,
+ pixblt_r_8_opx, pixblt_r_8_opx_trans, pixblt_r_8_opx, pixblt_r_8_opx_trans,
+ pixblt_r_8_opx, pixblt_r_8_opx_trans, pixblt_r_8_opx, pixblt_r_8_opx_trans,
+
+ pixblt_r_16_op0,pixblt_r_16_op0_trans, pixblt_r_16_opx,pixblt_r_16_opx_trans,
+ pixblt_r_16_opx,pixblt_r_16_opx_trans, pixblt_r_16_opx,pixblt_r_16_opx_trans,
+ pixblt_r_16_opx,pixblt_r_16_opx_trans, pixblt_r_16_opx,pixblt_r_16_opx_trans,
+ pixblt_r_16_opx,pixblt_r_16_opx_trans, pixblt_r_16_opx,pixblt_r_16_opx_trans,
+ pixblt_r_16_opx,pixblt_r_16_opx_trans, pixblt_r_16_opx,pixblt_r_16_opx_trans,
+ pixblt_r_16_opx,pixblt_r_16_opx_trans, pixblt_r_16_opx,pixblt_r_16_opx_trans,
+ pixblt_r_16_opx,pixblt_r_16_opx_trans, pixblt_r_16_opx,pixblt_r_16_opx_trans,
+ pixblt_r_16_opx,pixblt_r_16_opx_trans, pixblt_r_16_opx,pixblt_r_16_opx_trans,
+ pixblt_r_16_opx,pixblt_r_16_opx_trans, pixblt_r_16_opx,pixblt_r_16_opx_trans,
+ pixblt_r_16_opx,pixblt_r_16_opx_trans, pixblt_r_16_opx,pixblt_r_16_opx_trans,
+ pixblt_r_16_opx,pixblt_r_16_opx_trans, pixblt_r_16_opx,pixblt_r_16_opx_trans,
+ pixblt_r_16_opx,pixblt_r_16_opx_trans, pixblt_r_16_opx,pixblt_r_16_opx_trans,
+ pixblt_r_16_opx,pixblt_r_16_opx_trans, pixblt_r_16_opx,pixblt_r_16_opx_trans,
+ pixblt_r_16_opx,pixblt_r_16_opx_trans, pixblt_r_16_opx,pixblt_r_16_opx_trans,
+ pixblt_r_16_opx,pixblt_r_16_opx_trans, pixblt_r_16_opx,pixblt_r_16_opx_trans,
+ pixblt_r_16_opx,pixblt_r_16_opx_trans, pixblt_r_16_opx,pixblt_r_16_opx_trans
+};
+
+static void (*const pixblt_b_op_table[])(tms34010_state *, int) =
+{
+ pixblt_b_1_op0, pixblt_b_1_op0_trans, pixblt_b_1_opx, pixblt_b_1_opx_trans,
+ pixblt_b_1_opx, pixblt_b_1_opx_trans, pixblt_b_1_opx, pixblt_b_1_opx_trans,
+ pixblt_b_1_opx, pixblt_b_1_opx_trans, pixblt_b_1_opx, pixblt_b_1_opx_trans,
+ pixblt_b_1_opx, pixblt_b_1_opx_trans, pixblt_b_1_opx, pixblt_b_1_opx_trans,
+ pixblt_b_1_opx, pixblt_b_1_opx_trans, pixblt_b_1_opx, pixblt_b_1_opx_trans,
+ pixblt_b_1_opx, pixblt_b_1_opx_trans, pixblt_b_1_opx, pixblt_b_1_opx_trans,
+ pixblt_b_1_opx, pixblt_b_1_opx_trans, pixblt_b_1_opx, pixblt_b_1_opx_trans,
+ pixblt_b_1_opx, pixblt_b_1_opx_trans, pixblt_b_1_opx, pixblt_b_1_opx_trans,
+ pixblt_b_1_opx, pixblt_b_1_opx_trans, pixblt_b_1_opx, pixblt_b_1_opx_trans,
+ pixblt_b_1_opx, pixblt_b_1_opx_trans, pixblt_b_1_opx, pixblt_b_1_opx_trans,
+ pixblt_b_1_opx, pixblt_b_1_opx_trans, pixblt_b_1_opx, pixblt_b_1_opx_trans,
+ pixblt_b_1_opx, pixblt_b_1_opx_trans, pixblt_b_1_opx, pixblt_b_1_opx_trans,
+ pixblt_b_1_opx, pixblt_b_1_opx_trans, pixblt_b_1_opx, pixblt_b_1_opx_trans,
+ pixblt_b_1_opx, pixblt_b_1_opx_trans, pixblt_b_1_opx, pixblt_b_1_opx_trans,
+ pixblt_b_1_opx, pixblt_b_1_opx_trans, pixblt_b_1_opx, pixblt_b_1_opx_trans,
+ pixblt_b_1_opx, pixblt_b_1_opx_trans, pixblt_b_1_opx, pixblt_b_1_opx_trans,
+
+ pixblt_b_2_op0, pixblt_b_2_op0_trans, pixblt_b_2_opx, pixblt_b_2_opx_trans,
+ pixblt_b_2_opx, pixblt_b_2_opx_trans, pixblt_b_2_opx, pixblt_b_2_opx_trans,
+ pixblt_b_2_opx, pixblt_b_2_opx_trans, pixblt_b_2_opx, pixblt_b_2_opx_trans,
+ pixblt_b_2_opx, pixblt_b_2_opx_trans, pixblt_b_2_opx, pixblt_b_2_opx_trans,
+ pixblt_b_2_opx, pixblt_b_2_opx_trans, pixblt_b_2_opx, pixblt_b_2_opx_trans,
+ pixblt_b_2_opx, pixblt_b_2_opx_trans, pixblt_b_2_opx, pixblt_b_2_opx_trans,
+ pixblt_b_2_opx, pixblt_b_2_opx_trans, pixblt_b_2_opx, pixblt_b_2_opx_trans,
+ pixblt_b_2_opx, pixblt_b_2_opx_trans, pixblt_b_2_opx, pixblt_b_2_opx_trans,
+ pixblt_b_2_opx, pixblt_b_2_opx_trans, pixblt_b_2_opx, pixblt_b_2_opx_trans,
+ pixblt_b_2_opx, pixblt_b_2_opx_trans, pixblt_b_2_opx, pixblt_b_2_opx_trans,
+ pixblt_b_2_opx, pixblt_b_2_opx_trans, pixblt_b_2_opx, pixblt_b_2_opx_trans,
+ pixblt_b_2_opx, pixblt_b_2_opx_trans, pixblt_b_2_opx, pixblt_b_2_opx_trans,
+ pixblt_b_2_opx, pixblt_b_2_opx_trans, pixblt_b_2_opx, pixblt_b_2_opx_trans,
+ pixblt_b_2_opx, pixblt_b_2_opx_trans, pixblt_b_2_opx, pixblt_b_2_opx_trans,
+ pixblt_b_2_opx, pixblt_b_2_opx_trans, pixblt_b_2_opx, pixblt_b_2_opx_trans,
+ pixblt_b_2_opx, pixblt_b_2_opx_trans, pixblt_b_2_opx, pixblt_b_2_opx_trans,
+
+ pixblt_b_4_op0, pixblt_b_4_op0_trans, pixblt_b_4_opx, pixblt_b_4_opx_trans,
+ pixblt_b_4_opx, pixblt_b_4_opx_trans, pixblt_b_4_opx, pixblt_b_4_opx_trans,
+ pixblt_b_4_opx, pixblt_b_4_opx_trans, pixblt_b_4_opx, pixblt_b_4_opx_trans,
+ pixblt_b_4_opx, pixblt_b_4_opx_trans, pixblt_b_4_opx, pixblt_b_4_opx_trans,
+ pixblt_b_4_opx, pixblt_b_4_opx_trans, pixblt_b_4_opx, pixblt_b_4_opx_trans,
+ pixblt_b_4_opx, pixblt_b_4_opx_trans, pixblt_b_4_opx, pixblt_b_4_opx_trans,
+ pixblt_b_4_opx, pixblt_b_4_opx_trans, pixblt_b_4_opx, pixblt_b_4_opx_trans,
+ pixblt_b_4_opx, pixblt_b_4_opx_trans, pixblt_b_4_opx, pixblt_b_4_opx_trans,
+ pixblt_b_4_opx, pixblt_b_4_opx_trans, pixblt_b_4_opx, pixblt_b_4_opx_trans,
+ pixblt_b_4_opx, pixblt_b_4_opx_trans, pixblt_b_4_opx, pixblt_b_4_opx_trans,
+ pixblt_b_4_opx, pixblt_b_4_opx_trans, pixblt_b_4_opx, pixblt_b_4_opx_trans,
+ pixblt_b_4_opx, pixblt_b_4_opx_trans, pixblt_b_4_opx, pixblt_b_4_opx_trans,
+ pixblt_b_4_opx, pixblt_b_4_opx_trans, pixblt_b_4_opx, pixblt_b_4_opx_trans,
+ pixblt_b_4_opx, pixblt_b_4_opx_trans, pixblt_b_4_opx, pixblt_b_4_opx_trans,
+ pixblt_b_4_opx, pixblt_b_4_opx_trans, pixblt_b_4_opx, pixblt_b_4_opx_trans,
+ pixblt_b_4_opx, pixblt_b_4_opx_trans, pixblt_b_4_opx, pixblt_b_4_opx_trans,
+
+ pixblt_b_8_op0, pixblt_b_8_op0_trans, pixblt_b_8_opx, pixblt_b_8_opx_trans,
+ pixblt_b_8_opx, pixblt_b_8_opx_trans, pixblt_b_8_opx, pixblt_b_8_opx_trans,
+ pixblt_b_8_opx, pixblt_b_8_opx_trans, pixblt_b_8_opx, pixblt_b_8_opx_trans,
+ pixblt_b_8_opx, pixblt_b_8_opx_trans, pixblt_b_8_opx, pixblt_b_8_opx_trans,
+ pixblt_b_8_opx, pixblt_b_8_opx_trans, pixblt_b_8_opx, pixblt_b_8_opx_trans,
+ pixblt_b_8_opx, pixblt_b_8_opx_trans, pixblt_b_8_opx, pixblt_b_8_opx_trans,
+ pixblt_b_8_opx, pixblt_b_8_opx_trans, pixblt_b_8_opx, pixblt_b_8_opx_trans,
+ pixblt_b_8_opx, pixblt_b_8_opx_trans, pixblt_b_8_opx, pixblt_b_8_opx_trans,
+ pixblt_b_8_opx, pixblt_b_8_opx_trans, pixblt_b_8_opx, pixblt_b_8_opx_trans,
+ pixblt_b_8_opx, pixblt_b_8_opx_trans, pixblt_b_8_opx, pixblt_b_8_opx_trans,
+ pixblt_b_8_opx, pixblt_b_8_opx_trans, pixblt_b_8_opx, pixblt_b_8_opx_trans,
+ pixblt_b_8_opx, pixblt_b_8_opx_trans, pixblt_b_8_opx, pixblt_b_8_opx_trans,
+ pixblt_b_8_opx, pixblt_b_8_opx_trans, pixblt_b_8_opx, pixblt_b_8_opx_trans,
+ pixblt_b_8_opx, pixblt_b_8_opx_trans, pixblt_b_8_opx, pixblt_b_8_opx_trans,
+ pixblt_b_8_opx, pixblt_b_8_opx_trans, pixblt_b_8_opx, pixblt_b_8_opx_trans,
+ pixblt_b_8_opx, pixblt_b_8_opx_trans, pixblt_b_8_opx, pixblt_b_8_opx_trans,
+
+ pixblt_b_16_op0,pixblt_b_16_op0_trans, pixblt_b_16_opx,pixblt_b_16_opx_trans,
+ pixblt_b_16_opx,pixblt_b_16_opx_trans, pixblt_b_16_opx,pixblt_b_16_opx_trans,
+ pixblt_b_16_opx,pixblt_b_16_opx_trans, pixblt_b_16_opx,pixblt_b_16_opx_trans,
+ pixblt_b_16_opx,pixblt_b_16_opx_trans, pixblt_b_16_opx,pixblt_b_16_opx_trans,
+ pixblt_b_16_opx,pixblt_b_16_opx_trans, pixblt_b_16_opx,pixblt_b_16_opx_trans,
+ pixblt_b_16_opx,pixblt_b_16_opx_trans, pixblt_b_16_opx,pixblt_b_16_opx_trans,
+ pixblt_b_16_opx,pixblt_b_16_opx_trans, pixblt_b_16_opx,pixblt_b_16_opx_trans,
+ pixblt_b_16_opx,pixblt_b_16_opx_trans, pixblt_b_16_opx,pixblt_b_16_opx_trans,
+ pixblt_b_16_opx,pixblt_b_16_opx_trans, pixblt_b_16_opx,pixblt_b_16_opx_trans,
+ pixblt_b_16_opx,pixblt_b_16_opx_trans, pixblt_b_16_opx,pixblt_b_16_opx_trans,
+ pixblt_b_16_opx,pixblt_b_16_opx_trans, pixblt_b_16_opx,pixblt_b_16_opx_trans,
+ pixblt_b_16_opx,pixblt_b_16_opx_trans, pixblt_b_16_opx,pixblt_b_16_opx_trans,
+ pixblt_b_16_opx,pixblt_b_16_opx_trans, pixblt_b_16_opx,pixblt_b_16_opx_trans,
+ pixblt_b_16_opx,pixblt_b_16_opx_trans, pixblt_b_16_opx,pixblt_b_16_opx_trans,
+ pixblt_b_16_opx,pixblt_b_16_opx_trans, pixblt_b_16_opx,pixblt_b_16_opx_trans,
+ pixblt_b_16_opx,pixblt_b_16_opx_trans, pixblt_b_16_opx,pixblt_b_16_opx_trans
+};
+
+static void (*const fill_op_table[])(tms34010_state *tms, int) =
+{
+ fill_1_op0, fill_1_op0_trans, fill_1_opx, fill_1_opx_trans,
+ fill_1_opx, fill_1_opx_trans, fill_1_opx, fill_1_opx_trans,
+ fill_1_opx, fill_1_opx_trans, fill_1_opx, fill_1_opx_trans,
+ fill_1_opx, fill_1_opx_trans, fill_1_opx, fill_1_opx_trans,
+ fill_1_opx, fill_1_opx_trans, fill_1_opx, fill_1_opx_trans,
+ fill_1_opx, fill_1_opx_trans, fill_1_opx, fill_1_opx_trans,
+ fill_1_opx, fill_1_opx_trans, fill_1_opx, fill_1_opx_trans,
+ fill_1_opx, fill_1_opx_trans, fill_1_opx, fill_1_opx_trans,
+ fill_1_opx, fill_1_opx_trans, fill_1_opx, fill_1_opx_trans,
+ fill_1_opx, fill_1_opx_trans, fill_1_opx, fill_1_opx_trans,
+ fill_1_opx, fill_1_opx_trans, fill_1_opx, fill_1_opx_trans,
+ fill_1_opx, fill_1_opx_trans, fill_1_opx, fill_1_opx_trans,
+ fill_1_opx, fill_1_opx_trans, fill_1_opx, fill_1_opx_trans,
+ fill_1_opx, fill_1_opx_trans, fill_1_opx, fill_1_opx_trans,
+ fill_1_opx, fill_1_opx_trans, fill_1_opx, fill_1_opx_trans,
+ fill_1_opx, fill_1_opx_trans, fill_1_opx, fill_1_opx_trans,
+
+ fill_2_op0, fill_2_op0_trans, fill_2_opx, fill_2_opx_trans,
+ fill_2_opx, fill_2_opx_trans, fill_2_opx, fill_2_opx_trans,
+ fill_2_opx, fill_2_opx_trans, fill_2_opx, fill_2_opx_trans,
+ fill_2_opx, fill_2_opx_trans, fill_2_opx, fill_2_opx_trans,
+ fill_2_opx, fill_2_opx_trans, fill_2_opx, fill_2_opx_trans,
+ fill_2_opx, fill_2_opx_trans, fill_2_opx, fill_2_opx_trans,
+ fill_2_opx, fill_2_opx_trans, fill_2_opx, fill_2_opx_trans,
+ fill_2_opx, fill_2_opx_trans, fill_2_opx, fill_2_opx_trans,
+ fill_2_opx, fill_2_opx_trans, fill_2_opx, fill_2_opx_trans,
+ fill_2_opx, fill_2_opx_trans, fill_2_opx, fill_2_opx_trans,
+ fill_2_opx, fill_2_opx_trans, fill_2_opx, fill_2_opx_trans,
+ fill_2_opx, fill_2_opx_trans, fill_2_opx, fill_2_opx_trans,
+ fill_2_opx, fill_2_opx_trans, fill_2_opx, fill_2_opx_trans,
+ fill_2_opx, fill_2_opx_trans, fill_2_opx, fill_2_opx_trans,
+ fill_2_opx, fill_2_opx_trans, fill_2_opx, fill_2_opx_trans,
+ fill_2_opx, fill_2_opx_trans, fill_2_opx, fill_2_opx_trans,
+
+ fill_4_op0, fill_4_op0_trans, fill_4_opx, fill_4_opx_trans,
+ fill_4_opx, fill_4_opx_trans, fill_4_opx, fill_4_opx_trans,
+ fill_4_opx, fill_4_opx_trans, fill_4_opx, fill_4_opx_trans,
+ fill_4_opx, fill_4_opx_trans, fill_4_opx, fill_4_opx_trans,
+ fill_4_opx, fill_4_opx_trans, fill_4_opx, fill_4_opx_trans,
+ fill_4_opx, fill_4_opx_trans, fill_4_opx, fill_4_opx_trans,
+ fill_4_opx, fill_4_opx_trans, fill_4_opx, fill_4_opx_trans,
+ fill_4_opx, fill_4_opx_trans, fill_4_opx, fill_4_opx_trans,
+ fill_4_opx, fill_4_opx_trans, fill_4_opx, fill_4_opx_trans,
+ fill_4_opx, fill_4_opx_trans, fill_4_opx, fill_4_opx_trans,
+ fill_4_opx, fill_4_opx_trans, fill_4_opx, fill_4_opx_trans,
+ fill_4_opx, fill_4_opx_trans, fill_4_opx, fill_4_opx_trans,
+ fill_4_opx, fill_4_opx_trans, fill_4_opx, fill_4_opx_trans,
+ fill_4_opx, fill_4_opx_trans, fill_4_opx, fill_4_opx_trans,
+ fill_4_opx, fill_4_opx_trans, fill_4_opx, fill_4_opx_trans,
+ fill_4_opx, fill_4_opx_trans, fill_4_opx, fill_4_opx_trans,
+
+ fill_8_op0, fill_8_op0_trans, fill_8_opx, fill_8_opx_trans,
+ fill_8_opx, fill_8_opx_trans, fill_8_opx, fill_8_opx_trans,
+ fill_8_opx, fill_8_opx_trans, fill_8_opx, fill_8_opx_trans,
+ fill_8_opx, fill_8_opx_trans, fill_8_opx, fill_8_opx_trans,
+ fill_8_opx, fill_8_opx_trans, fill_8_opx, fill_8_opx_trans,
+ fill_8_opx, fill_8_opx_trans, fill_8_opx, fill_8_opx_trans,
+ fill_8_opx, fill_8_opx_trans, fill_8_opx, fill_8_opx_trans,
+ fill_8_opx, fill_8_opx_trans, fill_8_opx, fill_8_opx_trans,
+ fill_8_opx, fill_8_opx_trans, fill_8_opx, fill_8_opx_trans,
+ fill_8_opx, fill_8_opx_trans, fill_8_opx, fill_8_opx_trans,
+ fill_8_opx, fill_8_opx_trans, fill_8_opx, fill_8_opx_trans,
+ fill_8_opx, fill_8_opx_trans, fill_8_opx, fill_8_opx_trans,
+ fill_8_opx, fill_8_opx_trans, fill_8_opx, fill_8_opx_trans,
+ fill_8_opx, fill_8_opx_trans, fill_8_opx, fill_8_opx_trans,
+ fill_8_opx, fill_8_opx_trans, fill_8_opx, fill_8_opx_trans,
+ fill_8_opx, fill_8_opx_trans, fill_8_opx, fill_8_opx_trans,
+
+ fill_16_op0, fill_16_op0_trans, fill_16_opx, fill_16_opx_trans,
+ fill_16_opx, fill_16_opx_trans, fill_16_opx, fill_16_opx_trans,
+ fill_16_opx, fill_16_opx_trans, fill_16_opx, fill_16_opx_trans,
+ fill_16_opx, fill_16_opx_trans, fill_16_opx, fill_16_opx_trans,
+ fill_16_opx, fill_16_opx_trans, fill_16_opx, fill_16_opx_trans,
+ fill_16_opx, fill_16_opx_trans, fill_16_opx, fill_16_opx_trans,
+ fill_16_opx, fill_16_opx_trans, fill_16_opx, fill_16_opx_trans,
+ fill_16_opx, fill_16_opx_trans, fill_16_opx, fill_16_opx_trans,
+ fill_16_opx, fill_16_opx_trans, fill_16_opx, fill_16_opx_trans,
+ fill_16_opx, fill_16_opx_trans, fill_16_opx, fill_16_opx_trans,
+ fill_16_opx, fill_16_opx_trans, fill_16_opx, fill_16_opx_trans,
+ fill_16_opx, fill_16_opx_trans, fill_16_opx, fill_16_opx_trans,
+ fill_16_opx, fill_16_opx_trans, fill_16_opx, fill_16_opx_trans,
+ fill_16_opx, fill_16_opx_trans, fill_16_opx, fill_16_opx_trans,
+ fill_16_opx, fill_16_opx_trans, fill_16_opx, fill_16_opx_trans,
+ fill_16_opx, fill_16_opx_trans, fill_16_opx, fill_16_opx_trans
+};
+
+
+#define RECURSIVE_INCLUDE
+
+/* non-transparent replace ops */
+#define PIXEL_OP(src, mask, pixel) pixel = pixel
+#define PIXEL_OP_TIMING 2
+#define PIXEL_OP_REQUIRES_SOURCE 0
+#define TRANSPARENCY 0
+
+ /* 1bpp cases */
+ #define BITS_PER_PIXEL 1
+ #define FUNCTION_NAME(base) base##_1_op0
+ #include "34010gfx.c"
+ #undef FUNCTION_NAME
+ #undef BITS_PER_PIXEL
+
+ /* 2bpp cases */
+ #define BITS_PER_PIXEL 2
+ #define FUNCTION_NAME(base) base##_2_op0
+ #include "34010gfx.c"
+ #undef FUNCTION_NAME
+ #undef BITS_PER_PIXEL
+
+ /* 4bpp cases */
+ #define BITS_PER_PIXEL 4
+ #define FUNCTION_NAME(base) base##_4_op0
+ #include "34010gfx.c"
+ #undef FUNCTION_NAME
+ #undef BITS_PER_PIXEL
+
+ /* 8bpp cases */
+ #define BITS_PER_PIXEL 8
+ #define FUNCTION_NAME(base) base##_8_op0
+ #include "34010gfx.c"
+ #undef FUNCTION_NAME
+ #undef BITS_PER_PIXEL
+
+ /* 16bpp cases */
+ #define BITS_PER_PIXEL 16
+ #define FUNCTION_NAME(base) base##_16_op0
+ #include "34010gfx.c"
+ #undef FUNCTION_NAME
+ #undef BITS_PER_PIXEL
+
+#undef TRANSPARENCY
+#undef PIXEL_OP_REQUIRES_SOURCE
+#undef PIXEL_OP_TIMING
+#undef PIXEL_OP
+
+
+#define PIXEL_OP(src, mask, pixel) pixel = (*pixel_op)(src, mask, pixel)
+#define PIXEL_OP_TIMING pixel_op_timing
+#define PIXEL_OP_REQUIRES_SOURCE 1
+#define TRANSPARENCY 0
+
+ /* 1bpp cases */
+ #define BITS_PER_PIXEL 1
+ #define FUNCTION_NAME(base) base##_1_opx
+ #include "34010gfx.c"
+ #undef FUNCTION_NAME
+ #undef BITS_PER_PIXEL
+
+ /* 2bpp cases */
+ #define BITS_PER_PIXEL 2
+ #define FUNCTION_NAME(base) base##_2_opx
+ #include "34010gfx.c"
+ #undef FUNCTION_NAME
+ #undef BITS_PER_PIXEL
+
+ /* 4bpp cases */
+ #define BITS_PER_PIXEL 4
+ #define FUNCTION_NAME(base) base##_4_opx
+ #include "34010gfx.c"
+ #undef FUNCTION_NAME
+ #undef BITS_PER_PIXEL
+
+ /* 8bpp cases */
+ #define BITS_PER_PIXEL 8
+ #define FUNCTION_NAME(base) base##_8_opx
+ #include "34010gfx.c"
+ #undef FUNCTION_NAME
+ #undef BITS_PER_PIXEL
+
+ /* 16bpp cases */
+ #define BITS_PER_PIXEL 16
+ #define FUNCTION_NAME(base) base##_16_opx
+ #include "34010gfx.c"
+ #undef FUNCTION_NAME
+ #undef BITS_PER_PIXEL
+
+#undef TRANSPARENCY
+#undef PIXEL_OP_REQUIRES_SOURCE
+#undef PIXEL_OP_TIMING
+#undef PIXEL_OP
+
+
+/* transparent replace ops */
+#define PIXEL_OP(src, mask, pixel) pixel = pixel
+#define PIXEL_OP_REQUIRES_SOURCE 0
+#define PIXEL_OP_TIMING 4
+#define TRANSPARENCY 1
+
+ /* 1bpp cases */
+ #define BITS_PER_PIXEL 1
+ #define FUNCTION_NAME(base) base##_1_op0_trans
+ #include "34010gfx.c"
+ #undef FUNCTION_NAME
+ #undef BITS_PER_PIXEL
+
+ /* 2bpp cases */
+ #define BITS_PER_PIXEL 2
+ #define FUNCTION_NAME(base) base##_2_op0_trans
+ #include "34010gfx.c"
+ #undef FUNCTION_NAME
+ #undef BITS_PER_PIXEL
+
+ /* 4bpp cases */
+ #define BITS_PER_PIXEL 4
+ #define FUNCTION_NAME(base) base##_4_op0_trans
+ #include "34010gfx.c"
+ #undef FUNCTION_NAME
+ #undef BITS_PER_PIXEL
+
+ /* 8bpp cases */
+ #define BITS_PER_PIXEL 8
+ #define FUNCTION_NAME(base) base##_8_op0_trans
+ #include "34010gfx.c"
+ #undef FUNCTION_NAME
+ #undef BITS_PER_PIXEL
+
+ /* 16bpp cases */
+ #define BITS_PER_PIXEL 16
+ #define FUNCTION_NAME(base) base##_16_op0_trans
+ #include "34010gfx.c"
+ #undef FUNCTION_NAME
+ #undef BITS_PER_PIXEL
+
+#undef TRANSPARENCY
+#undef PIXEL_OP_REQUIRES_SOURCE
+#undef PIXEL_OP_TIMING
+#undef PIXEL_OP
+
+
+#define PIXEL_OP(src, mask, pixel) pixel = (*pixel_op)(src, mask, pixel)
+#define PIXEL_OP_REQUIRES_SOURCE 1
+#define PIXEL_OP_TIMING (2+pixel_op_timing)
+#define TRANSPARENCY 1
+
+ /* 1bpp cases */
+ #define BITS_PER_PIXEL 1
+ #define FUNCTION_NAME(base) base##_1_opx_trans
+ #include "34010gfx.c"
+ #undef FUNCTION_NAME
+ #undef BITS_PER_PIXEL
+
+ /* 2bpp cases */
+ #define BITS_PER_PIXEL 2
+ #define FUNCTION_NAME(base) base##_2_opx_trans
+ #include "34010gfx.c"
+ #undef FUNCTION_NAME
+ #undef BITS_PER_PIXEL
+
+ /* 4bpp cases */
+ #define BITS_PER_PIXEL 4
+ #define FUNCTION_NAME(base) base##_4_opx_trans
+ #include "34010gfx.c"
+ #undef FUNCTION_NAME
+ #undef BITS_PER_PIXEL
+
+ /* 8bpp cases */
+ #define BITS_PER_PIXEL 8
+ #define FUNCTION_NAME(base) base##_8_opx_trans
+ #include "34010gfx.c"
+ #undef FUNCTION_NAME
+ #undef BITS_PER_PIXEL
+
+ /* 16bpp cases */
+ #define BITS_PER_PIXEL 16
+ #define FUNCTION_NAME(base) base##_16_opx_trans
+ #include "34010gfx.c"
+ #undef FUNCTION_NAME
+ #undef BITS_PER_PIXEL
+
+#undef TRANSPARENCY
+#undef PIXEL_OP_REQUIRES_SOURCE
+#undef PIXEL_OP_TIMING
+#undef PIXEL_OP
+
+static const UINT8 pixelsize_lookup[32] =
+{
+ 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
+};
+
+
+static void pixblt_b_l(tms34010_state *tms, UINT16 op)
+{
+ int psize = pixelsize_lookup[IOREG(tms, REG_PSIZE) & 0x1f];
+ int trans = (IOREG(tms, REG_CONTROL) & 0x20) >> 5;
+ int rop = (IOREG(tms, REG_CONTROL) >> 10) & 0x1f;
+ int ix = trans | (rop << 1) | (psize << 6);
+ if (!P_FLAG(tms)) LOGGFX(("%08X(%3d):PIXBLT B,L (%dx%d) depth=%d\n", tms->pc, tms->screen->vpos(), DYDX_X(tms), DYDX_Y(tms), IOREG(tms, REG_PSIZE) ? IOREG(tms, REG_PSIZE) : 32));
+ pixel_op = pixel_op_table[rop];
+ pixel_op_timing = pixel_op_timing_table[rop];
+ (*pixblt_b_op_table[ix])(tms, 1);
+}
+
+static void pixblt_b_xy(tms34010_state *tms, UINT16 op)
+{
+ int psize = pixelsize_lookup[IOREG(tms, REG_PSIZE) & 0x1f];
+ int trans = (IOREG(tms, REG_CONTROL) & 0x20) >> 5;
+ int rop = (IOREG(tms, REG_CONTROL) >> 10) & 0x1f;
+ int ix = trans | (rop << 1) | (psize << 6);
+ if (!P_FLAG(tms)) LOGGFX(("%08X(%3d):PIXBLT B,XY (%d,%d) (%dx%d) depth=%d\n", tms->pc, tms->screen->vpos(), DADDR_X(tms), DADDR_Y(tms), DYDX_X(tms), DYDX_Y(tms), IOREG(tms, REG_PSIZE) ? IOREG(tms, REG_PSIZE) : 32));
+ pixel_op = pixel_op_table[rop];
+ pixel_op_timing = pixel_op_timing_table[rop];
+ (*pixblt_b_op_table[ix])(tms, 0);
+}
+
+static void pixblt_l_l(tms34010_state *tms, UINT16 op)
+{
+ int psize = pixelsize_lookup[IOREG(tms, REG_PSIZE) & 0x1f];
+ int trans = (IOREG(tms, REG_CONTROL) & 0x20) >> 5;
+ int rop = (IOREG(tms, REG_CONTROL) >> 10) & 0x1f;
+ int pbh = (IOREG(tms, REG_CONTROL) >> 8) & 1;
+ int ix = trans | (rop << 1) | (psize << 6);
+ if (!P_FLAG(tms)) LOGGFX(("%08X(%3d):PIXBLT L,L (%dx%d) depth=%d\n", tms->pc, tms->screen->vpos(), DYDX_X(tms), DYDX_Y(tms), IOREG(tms, REG_PSIZE) ? IOREG(tms, REG_PSIZE) : 32));
+ pixel_op = pixel_op_table[rop];
+ pixel_op_timing = pixel_op_timing_table[rop];
+ if (!pbh)
+ (*pixblt_op_table[ix])(tms, 1, 1);
+ else
+ (*pixblt_r_op_table[ix])(tms, 1, 1);
+}
+
+static void pixblt_l_xy(tms34010_state *tms, UINT16 op)
+{
+ int psize = pixelsize_lookup[IOREG(tms, REG_PSIZE) & 0x1f];
+ int trans = (IOREG(tms, REG_CONTROL) & 0x20) >> 5;
+ int rop = (IOREG(tms, REG_CONTROL) >> 10) & 0x1f;
+ int pbh = (IOREG(tms, REG_CONTROL) >> 8) & 1;
+ int ix = trans | (rop << 1) | (psize << 6);
+ if (!P_FLAG(tms)) LOGGFX(("%08X(%3d):PIXBLT L,XY (%d,%d) (%dx%d) depth=%d\n", tms->pc, tms->screen->vpos(), DADDR_X(tms), DADDR_Y(tms), DYDX_X(tms), DYDX_Y(tms), IOREG(tms, REG_PSIZE) ? IOREG(tms, REG_PSIZE) : 32));
+ pixel_op = pixel_op_table[rop];
+ pixel_op_timing = pixel_op_timing_table[rop];
+ if (!pbh)
+ (*pixblt_op_table[ix])(tms, 1, 0);
+ else
+ (*pixblt_r_op_table[ix])(tms, 1, 0);
+}
+
+static void pixblt_xy_l(tms34010_state *tms, UINT16 op)
+{
+ int psize = pixelsize_lookup[IOREG(tms, REG_PSIZE) & 0x1f];
+ int trans = (IOREG(tms, REG_CONTROL) & 0x20) >> 5;
+ int rop = (IOREG(tms, REG_CONTROL) >> 10) & 0x1f;
+ int pbh = (IOREG(tms, REG_CONTROL) >> 8) & 1;
+ int ix = trans | (rop << 1) | (psize << 6);
+ if (!P_FLAG(tms)) LOGGFX(("%08X(%3d):PIXBLT XY,L (%dx%d) depth=%d\n", tms->pc, tms->screen->vpos(), DYDX_X(tms), DYDX_Y(tms), IOREG(tms, REG_PSIZE) ? IOREG(tms, REG_PSIZE) : 32));
+ pixel_op = pixel_op_table[rop];
+ pixel_op_timing = pixel_op_timing_table[rop];
+ if (!pbh)
+ (*pixblt_op_table[ix])(tms, 0, 1);
+ else
+ (*pixblt_r_op_table[ix])(tms, 0, 1);
+}
+
+static void pixblt_xy_xy(tms34010_state *tms, UINT16 op)
+{
+ int psize = pixelsize_lookup[IOREG(tms, REG_PSIZE) & 0x1f];
+ int trans = (IOREG(tms, REG_CONTROL) & 0x20) >> 5;
+ int rop = (IOREG(tms, REG_CONTROL) >> 10) & 0x1f;
+ int pbh = (IOREG(tms, REG_CONTROL) >> 8) & 1;
+ int ix = trans | (rop << 1) | (psize << 6);
+ if (!P_FLAG(tms)) LOGGFX(("%08X(%3d):PIXBLT XY,XY (%dx%d) depth=%d\n", tms->pc, tms->screen->vpos(), DYDX_X(tms), DYDX_Y(tms), IOREG(tms, REG_PSIZE) ? IOREG(tms, REG_PSIZE) : 32));
+ pixel_op = pixel_op_table[rop];
+ pixel_op_timing = pixel_op_timing_table[rop];
+ if (!pbh)
+ (*pixblt_op_table[ix])(tms, 0, 0);
+ else
+ (*pixblt_r_op_table[ix])(tms, 0, 0);
+}
+
+static void fill_l(tms34010_state *tms, UINT16 op)
+{
+ int psize = pixelsize_lookup[IOREG(tms, REG_PSIZE) & 0x1f];
+ int trans = (IOREG(tms, REG_CONTROL) & 0x20) >> 5;
+ int rop = (IOREG(tms, REG_CONTROL) >> 10) & 0x1f;
+ int ix = trans | (rop << 1) | (psize << 6);
+ if (!P_FLAG(tms)) LOGGFX(("%08X(%3d):FILL L (%dx%d) depth=%d\n", tms->pc, tms->screen->vpos(), DYDX_X(tms), DYDX_Y(tms), IOREG(tms, REG_PSIZE) ? IOREG(tms, REG_PSIZE) : 32));
+ pixel_op = pixel_op_table[rop];
+ pixel_op_timing = pixel_op_timing_table[rop];
+ (*fill_op_table[ix])(tms, 1);
+}
+
+static void fill_xy(tms34010_state *tms, UINT16 op)
+{
+ int psize = pixelsize_lookup[IOREG(tms, REG_PSIZE) & 0x1f];
+ int trans = (IOREG(tms, REG_CONTROL) & 0x20) >> 5;
+ int rop = (IOREG(tms, REG_CONTROL) >> 10) & 0x1f;
+ int ix = trans | (rop << 1) | (psize << 6);
+ if (!P_FLAG(tms)) LOGGFX(("%08X(%3d):FILL XY (%d,%d) (%dx%d) depth=%d\n", tms->pc, tms->screen->vpos(), DADDR_X(tms), DADDR_Y(tms), DYDX_X(tms), DYDX_Y(tms), IOREG(tms, REG_PSIZE) ? IOREG(tms, REG_PSIZE) : 32));
+ pixel_op = pixel_op_table[rop];
+ pixel_op_timing = pixel_op_timing_table[rop];
+ (*fill_op_table[ix])(tms, 0);
+}
+
+
+#else
+
+
+#undef PIXELS_PER_WORD
+#undef PIXEL_MASK
+
+#define PIXELS_PER_WORD (16 / BITS_PER_PIXEL)
+#define PIXEL_MASK ((1 << BITS_PER_PIXEL) - 1)
+
+static void FUNCTION_NAME(pixblt)(tms34010_state *tms, int src_is_linear, int dst_is_linear)
+{
+ /* if this is the first time through, perform the operation */
+ if (!P_FLAG(tms))
+ {
+ int dx, dy, x, y, /*words,*/ yreverse;
+ void (*word_write)(address_space *space,offs_t address,UINT16 data);
+ UINT16 (*word_read)(address_space *space,offs_t address);
+ UINT32 readwrites = 0;
+ UINT32 saddr, daddr;
+ XY dstxy = { 0 };
+
+ /* determine read/write functions */
+ if (IOREG(tms, REG_DPYCTL) & 0x0800)
+ {
+ word_write = shiftreg_w;
+ word_read = shiftreg_r;
+ }
+ else
+ {
+ word_write = memory_w;
+ word_read = memory_r;
+ }
+
+ /* compute the starting addresses */
+ saddr = src_is_linear ? SADDR(tms) : SXYTOL(tms,SADDR_XY(tms));
+
+ /* compute the bounds of the operation */
+ dx = (INT16)DYDX_X(tms);
+ dy = (INT16)DYDX_Y(tms);
+
+ /* apply the window for non-linear destinations */
+ tms->gfxcycles = 7 + (src_is_linear ? 0 : 2);
+ if (!dst_is_linear)
+ {
+ dstxy = DADDR_XY(tms);
+ tms->gfxcycles += 2 + (!src_is_linear) + apply_window(tms, "PIXBLT", BITS_PER_PIXEL, &saddr, &dstxy, &dx, &dy);
+ daddr = DXYTOL(tms,dstxy);
+ }
+ else
+ daddr = DADDR(tms);
+ daddr &= ~(BITS_PER_PIXEL - 1);
+ LOGGFX((" saddr=%08X daddr=%08X sptch=%08X dptch=%08X\n", saddr, daddr, SPTCH(tms), DPTCH(tms)));
+
+ /* bail if we're clipped */
+ if (dx <= 0 || dy <= 0)
+ return;
+
+ /* window mode 1: just return and interrupt if we are within the window */
+ if (WINDOW_CHECKING(tms) == 1 && !dst_is_linear)
+ {
+ CLR_V(tms);
+ DADDR_XY(tms) = dstxy;
+ DYDX_X(tms) = dx;
+ DYDX_Y(tms) = dy;
+ IOREG(tms, REG_INTPEND) |= TMS34010_WV;
+ check_interrupt(tms);
+ return;
+ }
+
+ /* handle flipping the addresses */
+ yreverse = (IOREG(tms, REG_CONTROL) >> 9) & 1;
+ if (!src_is_linear || !dst_is_linear)
+ if (yreverse)
+ {
+ saddr += (dy - 1) * SPTCH(tms);
+ daddr += (dy - 1) * DPTCH(tms);
+ }
+
+ tms->st |= STBIT_P;
+
+ /* loop over rows */
+ for (y = 0; y < dy; y++)
+ {
+ UINT32 srcwordaddr = saddr >> 4;
+ UINT32 dstwordaddr = daddr >> 4;
+ UINT8 srcbit = saddr & 15;
+ UINT8 dstbit = daddr & 15;
+ UINT32 srcword, dstword = 0;
+
+ /* fetch the initial source word */
+ srcword = (*word_read)(tms->program, srcwordaddr++ << 1);
+ readwrites++;
+
+ /* fetch the initial dest word */
+ if (PIXEL_OP_REQUIRES_SOURCE || TRANSPARENCY || (daddr & 0x0f) != 0)
+ {
+ dstword = (*word_read)(tms->program, dstwordaddr << 1);
+ readwrites++;
+ }
+
+ /* loop over pixels */
+ for (x = 0; x < dx; x++)
+ {
+ UINT32 dstmask;
+ UINT32 pixel;
+
+ /* fetch more words if necessary */
+ if (srcbit + BITS_PER_PIXEL > 16)
+ {
+ srcword |= (*word_read)(tms->program, srcwordaddr++ << 1) << 16;
+ readwrites++;
+ }
+
+ /* extract pixel from source */
+ pixel = (srcword >> srcbit) & PIXEL_MASK;
+ srcbit += BITS_PER_PIXEL;
+ if (srcbit > 16)
+ {
+ srcbit -= 16;
+ srcword >>= 16;
+ }
+
+ /* fetch additional destination word if necessary */
+ if (PIXEL_OP_REQUIRES_SOURCE || TRANSPARENCY)
+ if (dstbit + BITS_PER_PIXEL > 16)
+ {
+ dstword |= (*word_read)(tms->program, (dstwordaddr + 1) << 1) << 16;
+ readwrites++;
+ }
+
+ /* apply pixel operations */
+ pixel <<= dstbit;
+ dstmask = PIXEL_MASK << dstbit;
+ PIXEL_OP(dstword, dstmask, pixel);
+ if (!TRANSPARENCY || pixel != 0)
+ dstword = (dstword & ~dstmask) | pixel;
+
+ /* flush destination words */
+ dstbit += BITS_PER_PIXEL;
+ if (dstbit > 16)
+ {
+ (*word_write)(tms->program, dstwordaddr++ << 1, dstword);
+ readwrites++;
+ dstbit -= 16;
+ dstword >>= 16;
+ }
+ }
+
+ /* flush any remaining words */
+ if (dstbit > 0)
+ {
+ /* if we're right-partial, read and mask the remaining bits */
+ if (dstbit != 16)
+ {
+ UINT16 origdst = (*word_read)(tms->program, dstwordaddr << 1);
+ UINT16 mask = 0xffff << dstbit;
+ dstword = (dstword & ~mask) | (origdst & mask);
+ readwrites++;
+ }
+
+ (*word_write)(tms->program, dstwordaddr++ << 1, dstword);
+ readwrites++;
+ }
+
+
+
+#if 0
+ int left_partials, right_partials, full_words, bitshift, bitshift_alt;
+ UINT16 srcword, srcmask, dstword, dstmask, pixel;
+ UINT32 swordaddr, dwordaddr;
+
+ /* determine the bit shift to get from source to dest */
+ bitshift = ((daddr & 15) - (saddr & 15)) & 15;
+ bitshift_alt = (16 - bitshift) & 15;
+
+ /* how many left and right partial pixels do we have? */
+ left_partials = (PIXELS_PER_WORD - ((daddr & 15) / BITS_PER_PIXEL)) & (PIXELS_PER_WORD - 1);
+ right_partials = ((daddr + dx * BITS_PER_PIXEL) & 15) / BITS_PER_PIXEL;
+ full_words = dx - left_partials - right_partials;
+ if (full_words < 0)
+ left_partials = dx, right_partials = full_words = 0;
+ else
+ full_words /= PIXELS_PER_WORD;
+
+ /* compute cycles */
+ tms->gfxcycles += compute_pixblt_cycles(left_partials, right_partials, full_words, PIXEL_OP_TIMING);
+
+ /* use word addresses each row */
+ swordaddr = saddr >> 4;
+ dwordaddr = daddr >> 4;
+
+ /* fetch the initial source word */
+ srcword = (*word_read)(tms->program, swordaddr++ << 1);
+ srcmask = PIXEL_MASK << (saddr & 15);
+
+ /* handle the left partial word */
+ if (left_partials != 0)
+ {
+ /* fetch the destination word */
+ dstword = (*word_read)(tms->program, dwordaddr << 1);
+ dstmask = PIXEL_MASK << (daddr & 15);
+
+ /* loop over partials */
+ for (x = 0; x < left_partials; x++)
+ {
+ /* fetch another word if necessary */
+ if (srcmask == 0)
+ {
+ srcword = (*word_read)(tms->program, swordaddr++ << 1);
+ srcmask = PIXEL_MASK;
+ }
+
+ /* process the pixel */
+ pixel = srcword & srcmask;
+ if (dstmask > srcmask)
+ pixel <<= bitshift;
+ else
+ pixel >>= bitshift_alt;
+ PIXEL_OP(dstword, dstmask, pixel);
+ if (!TRANSPARENCY || pixel != 0)
+ dstword = (dstword & ~dstmask) | pixel;
+
+ /* update the source */
+ srcmask <<= BITS_PER_PIXEL;
+
+ /* update the destination */
+ dstmask <<= BITS_PER_PIXEL;
+ }
+
+ /* write the result */
+ (*word_write)(tms->program, dwordaddr++ << 1, dstword);
+ }
+
+ /* loop over full words */
+ for (words = 0; words < full_words; words++)
+ {
+ /* fetch the destination word (if necessary) */
+ if (PIXEL_OP_REQUIRES_SOURCE || TRANSPARENCY)
+ dstword = (*word_read)(tms->program, dwordaddr << 1);
+ else
+ dstword = 0;
+ dstmask = PIXEL_MASK;
+
+ /* loop over partials */
+ for (x = 0; x < PIXELS_PER_WORD; x++)
+ {
+ /* fetch another word if necessary */
+ if (srcmask == 0)
+ {
+ srcword = (*word_read)(tms->program, swordaddr++ << 1);
+ srcmask = PIXEL_MASK;
+ }
+
+ /* process the pixel */
+ pixel = srcword & srcmask;
+ if (dstmask > srcmask)
+ pixel <<= bitshift;
+ else
+ pixel >>= bitshift_alt;
+ PIXEL_OP(dstword, dstmask, pixel);
+ if (!TRANSPARENCY || pixel != 0)
+ dstword = (dstword & ~dstmask) | pixel;
+
+ /* update the source */
+ srcmask <<= BITS_PER_PIXEL;
+
+ /* update the destination */
+ dstmask <<= BITS_PER_PIXEL;
+ }
+
+ /* write the result */
+ (*word_write)(tms->program, dwordaddr++ << 1, dstword);
+ }
+
+ /* handle the right partial word */
+ if (right_partials != 0)
+ {
+ /* fetch the destination word */
+ dstword = (*word_read)(tms->program, dwordaddr << 1);
+ dstmask = PIXEL_MASK;
+
+ /* loop over partials */
+ for (x = 0; x < right_partials; x++)
+ {
+ /* fetch another word if necessary */
+ if (srcmask == 0)
+ {
+ LOGGFX((" right fetch @ %08x\n", swordaddr));
+ srcword = (*word_read)(tms->program, swordaddr++ << 1);
+ srcmask = PIXEL_MASK;
+ }
+
+ /* process the pixel */
+ pixel = srcword & srcmask;
+ if (dstmask > srcmask)
+ pixel <<= bitshift;
+ else
+ pixel >>= bitshift_alt;
+ PIXEL_OP(dstword, dstmask, pixel);
+ if (!TRANSPARENCY || pixel != 0)
+ dstword = (dstword & ~dstmask) | pixel;
+
+ /* update the source */
+ srcmask <<= BITS_PER_PIXEL;
+
+ /* update the destination */
+ dstmask <<= BITS_PER_PIXEL;
+ }
+
+ /* write the result */
+ (*word_write)(tms->program, dwordaddr++ << 1, dstword);
+ }
+#endif
+
+ /* update for next row */
+ if (!yreverse)
+ {
+ saddr += SPTCH(tms);
+ daddr += DPTCH(tms);
+ }
+ else
+ {
+ saddr -= SPTCH(tms);
+ daddr -= DPTCH(tms);
+ }
+ }
+
+ tms->gfxcycles += readwrites * 2 + dx * dy * (PIXEL_OP_TIMING - 2);
+
+ LOGGFX((" (%d cycles)\n", tms->gfxcycles));
+ }
+
+ /* eat cycles */
+ if (tms->gfxcycles > tms->icount)
+ {
+ tms->gfxcycles -= tms->icount;
+ tms->icount = 0;
+ tms->pc -= 0x10;
+ }
+ else
+ {
+ tms->icount -= tms->gfxcycles;
+ tms->st &= ~STBIT_P;
+ if (src_is_linear && dst_is_linear)
+ SADDR(tms) += DYDX_Y(tms) * SPTCH(tms);
+ else if (src_is_linear)
+ SADDR(tms) += DYDX_Y(tms) * SPTCH(tms);
+ else
+ SADDR_Y(tms) += DYDX_Y(tms);
+ if (dst_is_linear)
+ DADDR(tms) += DYDX_Y(tms) * DPTCH(tms);
+ else
+ DADDR_Y(tms) += DYDX_Y(tms);
+ }
+}
+
+static void FUNCTION_NAME(pixblt_r)(tms34010_state *tms, int src_is_linear, int dst_is_linear)
+{
+ /* if this is the first time through, perform the operation */
+ if (!P_FLAG(tms))
+ {
+ int dx, dy, x, y, words, yreverse;
+ void (*word_write)(address_space *space,offs_t address,UINT16 data);
+ UINT16 (*word_read)(address_space *space,offs_t address);
+ UINT32 saddr, daddr;
+ XY dstxy = { 0 };
+
+ /* determine read/write functions */
+ if (IOREG(tms, REG_DPYCTL) & 0x0800)
+ {
+ word_write = shiftreg_w;
+ word_read = shiftreg_r;
+ }
+ else
+ {
+ word_write = memory_w;
+ word_read = memory_r;
+ }
+
+ /* compute the starting addresses */
+ saddr = src_is_linear ? SADDR(tms) : SXYTOL(tms,SADDR_XY(tms));
+if ((saddr & (BITS_PER_PIXEL - 1)) != 0) mame_printf_debug("PIXBLT_R%d with odd saddr\n", BITS_PER_PIXEL);
+ saddr &= ~(BITS_PER_PIXEL - 1);
+
+ /* compute the bounds of the operation */
+ dx = (INT16)DYDX_X(tms);
+ dy = (INT16)DYDX_Y(tms);
+
+ /* apply the window for non-linear destinations */
+ tms->gfxcycles = 7 + (src_is_linear ? 0 : 2);
+ if (!dst_is_linear)
+ {
+ dstxy = DADDR_XY(tms);
+ tms->gfxcycles += 2 + (!src_is_linear) + apply_window(tms, "PIXBLT R", BITS_PER_PIXEL, &saddr, &dstxy, &dx, &dy);
+ daddr = DXYTOL(tms,dstxy);
+ }
+ else
+ daddr = DADDR(tms);
+if ((daddr & (BITS_PER_PIXEL - 1)) != 0) mame_printf_debug("PIXBLT_R%d with odd daddr\n", BITS_PER_PIXEL);
+ daddr &= ~(BITS_PER_PIXEL - 1);
+ LOGGFX((" saddr=%08X daddr=%08X sptch=%08X dptch=%08X\n", saddr, daddr, SPTCH(tms), DPTCH(tms)));
+
+ /* bail if we're clipped */
+ if (dx <= 0 || dy <= 0)
+ return;
+
+ /* window mode 1: just return and interrupt if we are within the window */
+ if (WINDOW_CHECKING(tms) == 1 && !dst_is_linear)
+ {
+ CLR_V(tms);
+ DADDR_XY(tms) = dstxy;
+ DYDX_X(tms) = dx;
+ DYDX_Y(tms) = dy;
+ IOREG(tms, REG_INTPEND) |= TMS34010_WV;
+ check_interrupt(tms);
+ return;
+ }
+
+ /* handle flipping the addresses */
+ yreverse = (IOREG(tms, REG_CONTROL) >> 9) & 1;
+ if (!src_is_linear || !dst_is_linear)
+ {
+ saddr += dx * BITS_PER_PIXEL;
+ daddr += dx * BITS_PER_PIXEL;
+ if (yreverse)
+ {
+ saddr += (dy - 1) * SPTCH(tms);
+ daddr += (dy - 1) * DPTCH(tms);
+ }
+ }
+
+ tms->st |= STBIT_P;
+
+ /* loop over rows */
+ for (y = 0; y < dy; y++)
+ {
+ int left_partials, right_partials, full_words, bitshift, bitshift_alt;
+ UINT16 srcword, srcmask, dstword, dstmask, pixel;
+ UINT32 swordaddr, dwordaddr;
+
+ /* determine the bit shift to get from source to dest */
+ bitshift = ((daddr & 15) - (saddr & 15)) & 15;
+ bitshift_alt = (16 - bitshift) & 15;
+
+ /* how many left and right partial pixels do we have? */
+ left_partials = (PIXELS_PER_WORD - (((daddr - dx * BITS_PER_PIXEL) & 15) / BITS_PER_PIXEL)) & (PIXELS_PER_WORD - 1);
+ right_partials = (daddr & 15) / BITS_PER_PIXEL;
+ full_words = dx - left_partials - right_partials;
+ if (full_words < 0)
+ right_partials = dx, left_partials = full_words = 0;
+ else
+ full_words /= PIXELS_PER_WORD;
+
+ /* compute cycles */
+ tms->gfxcycles += compute_pixblt_cycles(left_partials, right_partials, full_words, PIXEL_OP_TIMING);
+
+ /* use word addresses each row */
+ swordaddr = (saddr + 15) >> 4;
+ dwordaddr = (daddr + 15) >> 4;
+
+ /* fetch the initial source word */
+ srcword = (*word_read)(tms->program, --swordaddr << 1);
+ srcmask = PIXEL_MASK << ((saddr - BITS_PER_PIXEL) & 15);
+
+ /* handle the right partial word */
+ if (right_partials != 0)
+ {
+ /* fetch the destination word */
+ dstword = (*word_read)(tms->program, --dwordaddr << 1);
+ dstmask = PIXEL_MASK << ((daddr - BITS_PER_PIXEL) & 15);
+
+ /* loop over partials */
+ for (x = 0; x < right_partials; x++)
+ {
+ /* fetch source pixel if necessary */
+ if (srcmask == 0)
+ {
+ srcword = (*word_read)(tms->program, --swordaddr << 1);
+ srcmask = PIXEL_MASK << (16 - BITS_PER_PIXEL);
+ }
+
+ /* process the pixel */
+ pixel = srcword & srcmask;
+ if (dstmask > srcmask)
+ pixel <<= bitshift;
+ else
+ pixel >>= bitshift_alt;
+ PIXEL_OP(dstword, dstmask, pixel);
+ if (!TRANSPARENCY || pixel != 0)
+ dstword = (dstword & ~dstmask) | pixel;
+
+ /* update the source */
+ srcmask >>= BITS_PER_PIXEL;
+
+ /* update the destination */
+ dstmask >>= BITS_PER_PIXEL;
+ }
+
+ /* write the result */
+ (*word_write)(tms->program, dwordaddr << 1, dstword);
+ }
+
+ /* loop over full words */
+ for (words = 0; words < full_words; words++)
+ {
+ /* fetch the destination word (if necessary) */
+ dwordaddr--;
+ if (PIXEL_OP_REQUIRES_SOURCE || TRANSPARENCY)
+ dstword = (*word_read)(tms->program, dwordaddr << 1);
+ else
+ dstword = 0;
+ dstmask = PIXEL_MASK << (16 - BITS_PER_PIXEL);
+
+ /* loop over partials */
+ for (x = 0; x < PIXELS_PER_WORD; x++)
+ {
+ /* fetch source pixel if necessary */
+ if (srcmask == 0)
+ {
+ srcword = (*word_read)(tms->program, --swordaddr << 1);
+ srcmask = PIXEL_MASK << (16 - BITS_PER_PIXEL);
+ }
+
+ /* process the pixel */
+ pixel = srcword & srcmask;
+ if (dstmask > srcmask)
+ pixel <<= bitshift;
+ else
+ pixel >>= bitshift_alt;
+ PIXEL_OP(dstword, dstmask, pixel);
+ if (!TRANSPARENCY || pixel != 0)
+ dstword = (dstword & ~dstmask) | pixel;
+
+ /* update the source */
+ srcmask >>= BITS_PER_PIXEL;
+
+ /* update the destination */
+ dstmask >>= BITS_PER_PIXEL;
+ }
+
+ /* write the result */
+ (*word_write)(tms->program, dwordaddr << 1, dstword);
+ }
+
+ /* handle the left partial word */
+ if (left_partials != 0)
+ {
+ /* fetch the destination word */
+ dstword = (*word_read)(tms->program, --dwordaddr << 1);
+ dstmask = PIXEL_MASK << (16 - BITS_PER_PIXEL);
+
+ /* loop over partials */
+ for (x = 0; x < left_partials; x++)
+ {
+ /* fetch the source pixel if necessary */
+ if (srcmask == 0)
+ {
+ srcword = (*word_read)(tms->program, --swordaddr << 1);
+ srcmask = PIXEL_MASK << (16 - BITS_PER_PIXEL);
+ }
+
+ /* process the pixel */
+ pixel = srcword & srcmask;
+ if (dstmask > srcmask)
+ pixel <<= bitshift;
+ else
+ pixel >>= bitshift_alt;
+ PIXEL_OP(dstword, dstmask, pixel);
+ if (!TRANSPARENCY || pixel != 0)
+ dstword = (dstword & ~dstmask) | pixel;
+
+ /* update the source */
+ srcmask >>= BITS_PER_PIXEL;
+
+ /* update the destination */
+ dstmask >>= BITS_PER_PIXEL;
+ }
+
+ /* write the result */
+ (*word_write)(tms->program, dwordaddr << 1, dstword);
+ }
+
+ /* update for next row */
+ if (!yreverse)
+ {
+ saddr += SPTCH(tms);
+ daddr += DPTCH(tms);
+ }
+ else
+ {
+ saddr -= SPTCH(tms);
+ daddr -= DPTCH(tms);
+ }
+ }
+ LOGGFX((" (%d cycles)\n", tms->gfxcycles));
+ }
+
+ /* eat cycles */
+ if (tms->gfxcycles > tms->icount)
+ {
+ tms->gfxcycles -= tms->icount;
+ tms->icount = 0;
+ tms->pc -= 0x10;
+ }
+ else
+ {
+ tms->icount -= tms->gfxcycles;
+ tms->st &= ~STBIT_P;
+ if (src_is_linear && dst_is_linear)
+ SADDR(tms) += DYDX_Y(tms) * SPTCH(tms);
+ else if (src_is_linear)
+ SADDR(tms) += DYDX_Y(tms) * SPTCH(tms);
+ else
+ SADDR_Y(tms) += DYDX_Y(tms);
+ if (dst_is_linear)
+ DADDR(tms) += DYDX_Y(tms) * DPTCH(tms);
+ else
+ DADDR_Y(tms) += DYDX_Y(tms);
+ }
+}
+
+static void FUNCTION_NAME(pixblt_b)(tms34010_state *tms, int dst_is_linear)
+{
+ /* if this is the first time through, perform the operation */
+ if (!P_FLAG(tms))
+ {
+ int dx, dy, x, y, words, left_partials, right_partials, full_words;
+ void (*word_write)(address_space *space,offs_t address,UINT16 data);
+ UINT16 (*word_read)(address_space *space,offs_t address);
+ UINT32 saddr, daddr;
+ XY dstxy = { 0 };
+
+ /* determine read/write functions */
+ if (IOREG(tms, REG_DPYCTL) & 0x0800)
+ {
+ word_write = shiftreg_w;
+ word_read = shiftreg_r;
+ }
+ else
+ {
+ word_write = memory_w;
+ word_read = memory_r;
+ }
+
+ /* compute the starting addresses */
+ saddr = SADDR(tms);
+
+ /* compute the bounds of the operation */
+ dx = (INT16)DYDX_X(tms);
+ dy = (INT16)DYDX_Y(tms);
+
+ /* apply the window for non-linear destinations */
+ tms->gfxcycles = 4;
+ if (!dst_is_linear)
+ {
+ dstxy = DADDR_XY(tms);
+ tms->gfxcycles += 2 + apply_window(tms, "PIXBLT B", 1, &saddr, &dstxy, &dx, &dy);
+ daddr = DXYTOL(tms,dstxy);
+ }
+ else
+ daddr = DADDR(tms);
+ daddr &= ~(BITS_PER_PIXEL - 1);
+ LOGGFX((" saddr=%08X daddr=%08X sptch=%08X dptch=%08X\n", saddr, daddr, SPTCH(tms), DPTCH(tms)));
+
+ /* bail if we're clipped */
+ if (dx <= 0 || dy <= 0)
+ return;
+
+ /* window mode 1: just return and interrupt if we are within the window */
+ if (WINDOW_CHECKING(tms) == 1 && !dst_is_linear)
+ {
+ CLR_V(tms);
+ DADDR_XY(tms) = dstxy;
+ DYDX_X(tms) = dx;
+ DYDX_Y(tms) = dy;
+ IOREG(tms, REG_INTPEND) |= TMS34010_WV;
+ check_interrupt(tms);
+ return;
+ }
+
+ /* how many left and right partial pixels do we have? */
+ left_partials = (PIXELS_PER_WORD - ((daddr & 15) / BITS_PER_PIXEL)) & (PIXELS_PER_WORD - 1);
+ right_partials = ((daddr + dx * BITS_PER_PIXEL) & 15) / BITS_PER_PIXEL;
+ full_words = dx - left_partials - right_partials;
+ if (full_words < 0)
+ left_partials = dx, right_partials = full_words = 0;
+ else
+ full_words /= PIXELS_PER_WORD;
+
+ /* compute cycles */
+ tms->gfxcycles += compute_pixblt_b_cycles(left_partials, right_partials, full_words, dy, PIXEL_OP_TIMING, BITS_PER_PIXEL);
+ tms->st |= STBIT_P;
+
+ /* loop over rows */
+ for (y = 0; y < dy; y++)
+ {
+ UINT16 srcword, srcmask, dstword, dstmask, pixel;
+ UINT32 swordaddr, dwordaddr;
+
+ /* use byte addresses each row */
+ swordaddr = saddr >> 4;
+ dwordaddr = daddr >> 4;
+
+ /* fetch the initial source word */
+ srcword = (*word_read)(tms->program, swordaddr++ << 1);
+ srcmask = 1 << (saddr & 15);
+
+ /* handle the left partial word */
+ if (left_partials != 0)
+ {
+ /* fetch the destination word */
+ dstword = (*word_read)(tms->program, dwordaddr << 1);
+ dstmask = PIXEL_MASK << (daddr & 15);
+
+ /* loop over partials */
+ for (x = 0; x < left_partials; x++)
+ {
+ /* process the pixel */
+ pixel = (srcword & srcmask) ? COLOR1(tms) : COLOR0(tms);
+ pixel &= dstmask;
+ PIXEL_OP(dstword, dstmask, pixel);
+ if (!TRANSPARENCY || pixel != 0)
+ dstword = (dstword & ~dstmask) | pixel;
+
+ /* update the source */
+ srcmask <<= 1;
+ if (srcmask == 0)
+ {
+ srcword = (*word_read)(tms->program, swordaddr++ << 1);
+ srcmask = 0x0001;
+ }
+
+ /* update the destination */
+ dstmask <<= BITS_PER_PIXEL;
+ }
+
+ /* write the result */
+ (*word_write)(tms->program, dwordaddr++ << 1, dstword);
+ }
+
+ /* loop over full words */
+ for (words = 0; words < full_words; words++)
+ {
+ /* fetch the destination word (if necessary) */
+ if (PIXEL_OP_REQUIRES_SOURCE || TRANSPARENCY)
+ dstword = (*word_read)(tms->program, dwordaddr << 1);
+ else
+ dstword = 0;
+ dstmask = PIXEL_MASK;
+
+ /* loop over partials */
+ for (x = 0; x < PIXELS_PER_WORD; x++)
+ {
+ /* process the pixel */
+ pixel = (srcword & srcmask) ? COLOR1(tms) : COLOR0(tms);
+ pixel &= dstmask;
+ PIXEL_OP(dstword, dstmask, pixel);
+ if (!TRANSPARENCY || pixel != 0)
+ dstword = (dstword & ~dstmask) | pixel;
+
+ /* update the source */
+ srcmask <<= 1;
+ if (srcmask == 0)
+ {
+ srcword = (*word_read)(tms->program, swordaddr++ << 1);
+ srcmask = 0x0001;
+ }
+
+ /* update the destination */
+ dstmask <<= BITS_PER_PIXEL;
+ }
+
+ /* write the result */
+ (*word_write)(tms->program, dwordaddr++ << 1, dstword);
+ }
+
+ /* handle the right partial word */
+ if (right_partials != 0)
+ {
+ /* fetch the destination word */
+ dstword = (*word_read)(tms->program, dwordaddr << 1);
+ dstmask = PIXEL_MASK;
+
+ /* loop over partials */
+ for (x = 0; x < right_partials; x++)
+ {
+ /* process the pixel */
+ pixel = (srcword & srcmask) ? COLOR1(tms) : COLOR0(tms);
+ pixel &= dstmask;
+ PIXEL_OP(dstword, dstmask, pixel);
+ if (!TRANSPARENCY || pixel != 0)
+ dstword = (dstword & ~dstmask) | pixel;
+
+ /* update the source */
+ srcmask <<= 1;
+ if (srcmask == 0)
+ {
+ srcword = (*word_read)(tms->program, swordaddr++ << 1);
+ srcmask = 0x0001;
+ }
+
+ /* update the destination */
+ dstmask <<= BITS_PER_PIXEL;
+ }
+
+ /* write the result */
+ (*word_write)(tms->program, dwordaddr++ << 1, dstword);
+ }
+
+ /* update for next row */
+ saddr += SPTCH(tms);
+ daddr += DPTCH(tms);
+ }
+ LOGGFX((" (%d cycles)\n", tms->gfxcycles));
+ }
+
+ /* eat cycles */
+ if (tms->gfxcycles > tms->icount)
+ {
+ tms->gfxcycles -= tms->icount;
+ tms->icount = 0;
+ tms->pc -= 0x10;
+ }
+ else
+ {
+ tms->icount -= tms->gfxcycles;
+ tms->st &= ~STBIT_P;
+ SADDR(tms) += DYDX_Y(tms) * SPTCH(tms);
+ if (dst_is_linear)
+ DADDR(tms) += DYDX_Y(tms) * DPTCH(tms);
+ else
+ DADDR_Y(tms) += DYDX_Y(tms);
+ }
+}
+
+static void FUNCTION_NAME(fill)(tms34010_state *tms, int dst_is_linear)
+{
+ /* if this is the first time through, perform the operation */
+ if (!P_FLAG(tms))
+ {
+ int dx, dy, x, y, words, left_partials, right_partials, full_words;
+ void (*word_write)(address_space *space,offs_t address,UINT16 data);
+ UINT16 (*word_read)(address_space *space,offs_t address);
+ UINT32 daddr;
+ XY dstxy = { 0 };
+
+ /* determine read/write functions */
+ if (IOREG(tms, REG_DPYCTL) & 0x0800)
+ {
+ word_write = shiftreg_w;
+ word_read = dummy_shiftreg_r;
+ }
+ else
+ {
+ word_write = memory_w;
+ word_read = memory_r;
+ }
+
+ /* compute the bounds of the operation */
+ dx = (INT16)DYDX_X(tms);
+ dy = (INT16)DYDX_Y(tms);
+
+ /* apply the window for non-linear destinations */
+ tms->gfxcycles = 4;
+ if (!dst_is_linear)
+ {
+ dstxy = DADDR_XY(tms);
+ tms->gfxcycles += 2 + apply_window(tms, "FILL", 0, NULL, &dstxy, &dx, &dy);
+ daddr = DXYTOL(tms,dstxy);
+ }
+ else
+ daddr = DADDR(tms);
+ daddr &= ~(BITS_PER_PIXEL - 1);
+ LOGGFX((" daddr=%08X\n", daddr));
+
+ /* bail if we're clipped */
+ if (dx <= 0 || dy <= 0)
+ return;
+
+ /* window mode 1: just return and interrupt if we are within the window */
+ if (WINDOW_CHECKING(tms) == 1 && !dst_is_linear)
+ {
+ CLR_V(tms);
+ DADDR_XY(tms) = dstxy;
+ DYDX_X(tms) = dx;
+ DYDX_Y(tms) = dy;
+ IOREG(tms, REG_INTPEND) |= TMS34010_WV;
+ check_interrupt(tms);
+ return;
+ }
+
+ /* how many left and right partial pixels do we have? */
+ left_partials = (PIXELS_PER_WORD - ((daddr & 15) / BITS_PER_PIXEL)) & (PIXELS_PER_WORD - 1);
+ right_partials = ((daddr + dx * BITS_PER_PIXEL) & 15) / BITS_PER_PIXEL;
+ full_words = dx - left_partials - right_partials;
+ if (full_words < 0)
+ left_partials = dx, right_partials = full_words = 0;
+ else
+ full_words /= PIXELS_PER_WORD;
+
+ /* compute cycles */
+ tms->gfxcycles += 2;
+ tms->st |= STBIT_P;
+
+ /* loop over rows */
+ for (y = 0; y < dy; y++)
+ {
+ UINT16 dstword, dstmask, pixel;
+ UINT32 dwordaddr;
+
+ /* use byte addresses each row */
+ dwordaddr = daddr >> 4;
+
+ /* compute cycles */
+ tms->gfxcycles += compute_fill_cycles(left_partials, right_partials, full_words, PIXEL_OP_TIMING);
+
+ /* handle the left partial word */
+ if (left_partials != 0)
+ {
+ /* fetch the destination word */
+ dstword = (*word_read)(tms->program, dwordaddr << 1);
+ dstmask = PIXEL_MASK << (daddr & 15);
+
+ /* loop over partials */
+ for (x = 0; x < left_partials; x++)
+ {
+ /* process the pixel */
+ pixel = COLOR1(tms) & dstmask;
+ PIXEL_OP(dstword, dstmask, pixel);
+ if (!TRANSPARENCY || pixel != 0)
+ dstword = (dstword & ~dstmask) | pixel;
+
+ /* update the destination */
+ dstmask <<= BITS_PER_PIXEL;
+ }
+
+ /* write the result */
+ (*word_write)(tms->program, dwordaddr++ << 1, dstword);
+ }
+
+ /* loop over full words */
+ for (words = 0; words < full_words; words++)
+ {
+ /* fetch the destination word (if necessary) */
+ if (PIXEL_OP_REQUIRES_SOURCE || TRANSPARENCY)
+ dstword = (*word_read)(tms->program, dwordaddr << 1);
+ else
+ dstword = 0;
+ dstmask = PIXEL_MASK;
+
+ /* loop over partials */
+ for (x = 0; x < PIXELS_PER_WORD; x++)
+ {
+ /* process the pixel */
+ pixel = COLOR1(tms) & dstmask;
+ PIXEL_OP(dstword, dstmask, pixel);
+ if (!TRANSPARENCY || pixel != 0)
+ dstword = (dstword & ~dstmask) | pixel;
+
+ /* update the destination */
+ dstmask <<= BITS_PER_PIXEL;
+ }
+
+ /* write the result */
+ (*word_write)(tms->program, dwordaddr++ << 1, dstword);
+ }
+
+ /* handle the right partial word */
+ if (right_partials != 0)
+ {
+ /* fetch the destination word */
+ dstword = (*word_read)(tms->program, dwordaddr << 1);
+ dstmask = PIXEL_MASK;
+
+ /* loop over partials */
+ for (x = 0; x < right_partials; x++)
+ {
+ /* process the pixel */
+ pixel = COLOR1(tms) & dstmask;
+ PIXEL_OP(dstword, dstmask, pixel);
+ if (!TRANSPARENCY || pixel != 0)
+ dstword = (dstword & ~dstmask) | pixel;
+
+ /* update the destination */
+ dstmask <<= BITS_PER_PIXEL;
+ }
+
+ /* write the result */
+ (*word_write)(tms->program, dwordaddr++ << 1, dstword);
+ }
+
+ /* update for next row */
+ daddr += DPTCH(tms);
+ }
+
+ LOGGFX((" (%d cycles)\n", tms->gfxcycles));
+ }
+
+ /* eat cycles */
+ if (tms->gfxcycles > tms->icount)
+ {
+ tms->gfxcycles -= tms->icount;
+ tms->icount = 0;
+ tms->pc -= 0x10;
+ }
+ else
+ {
+ tms->icount -= tms->gfxcycles;
+ tms->st &= ~STBIT_P;
+ if (dst_is_linear)
+ DADDR(tms) += DYDX_Y(tms) * DPTCH(tms);
+ else
+ DADDR_Y(tms) += DYDX_Y(tms);
+ }
+}
+
+#endif
+
diff --git a/trunk/src/emu/cpu/tms34010/34010ops.c b/trunk/src/emu/cpu/tms34010/34010ops.c
new file mode 100644
index 00000000000..66d5f8237b4
--- /dev/null
+++ b/trunk/src/emu/cpu/tms34010/34010ops.c
@@ -0,0 +1,2458 @@
+/***************************************************************************
+
+ TMS34010: Portable Texas Instruments TMS34010 emulator
+
+ Copyright Alex Pasadyn/Zsolt Vasvari
+ Parts based on code by Aaron Giles
+
+***************************************************************************/
+
+
+
+/***************************************************************************
+ MISC MACROS
+***************************************************************************/
+
+#define ZEXTEND(val,width) if (width) (val) &= ((UINT32)0xffffffff >> (32 - (width)))
+#define SEXTEND(val,width) if (width) (val) = (INT32)((val) << (32 - (width))) >> (32 - (width))
+
+#define SXYTOL(T,val) ((((INT16)(val).y * (T)->convsp) + ((INT16)(val).x << (T)->pixelshift)) + OFFSET(T))
+#define DXYTOL(T,val) ((((INT16)(val).y * (T)->convdp) + ((INT16)(val).x << (T)->pixelshift)) + OFFSET(T))
+#define MXYTOL(T,val) ((((INT16)(val).y * (T)->convmp) + ((INT16)(val).x << (T)->pixelshift)) + OFFSET(T))
+
+#define COUNT_CYCLES(T,x) (T)->icount -= x
+#define COUNT_UNKNOWN_CYCLES(T,x) COUNT_CYCLES(T,x)
+
+#define CORRECT_ODD_PC(T,x) do { if ((T)->pc & 0x0f) logerror("%s to PC=%08X\n", x, (T)->pc); (T)->pc &= ~0x0f; } while (0)
+
+
+
+/***************************************************************************
+ FLAG HANDLING MACROS
+***************************************************************************/
+
+#define SIGN(val) ((val) & 0x80000000)
+
+#define CLR_Z(T) (T)->st &= ~STBIT_Z
+#define CLR_V(T) (T)->st &= ~STBIT_V
+#define CLR_C(T) (T)->st &= ~STBIT_C
+#define CLR_N(T) (T)->st &= ~STBIT_N
+#define CLR_NZ(T) (T)->st &= ~(STBIT_N | STBIT_Z)
+#define CLR_CZ(T) (T)->st &= ~(STBIT_C | STBIT_Z)
+#define CLR_ZV(T) (T)->st &= ~(STBIT_Z | STBIT_V)
+#define CLR_NZV(T) (T)->st &= ~(STBIT_N | STBIT_Z | STBIT_V)
+#define CLR_NCZ(T) (T)->st &= ~(STBIT_N | STBIT_C | STBIT_Z)
+#define CLR_NCZV(T) (T)->st &= ~(STBIT_N | STBIT_C | STBIT_Z | STBIT_V)
+
+#define SET_V_BIT_LO(T,val,bit) (T)->st |= ((val) << (28 - (bit))) & STBIT_V
+#define SET_V_BIT_HI(T,val,bit) (T)->st |= ((val) >> ((bit) - 28)) & STBIT_V
+#define SET_V_LOG(T,val) (T)->st |= (val) << 28
+#define SET_Z_BIT_LO(T,val,bit) (T)->st |= ((val) << (29 - (bit))) & STBIT_Z
+#define SET_Z_BIT_HI(T,val,bit) (T)->st |= ((val) >> ((bit) - 29)) & STBIT_Z
+#define SET_Z_LOG(T,val) (T)->st |= (val) << 29
+#define SET_C_BIT_LO(T,val,bit) (T)->st |= ((val) << (30 - (bit))) & STBIT_C
+#define SET_C_BIT_HI(T,val,bit) (T)->st |= ((val) >> ((bit) - 30)) & STBIT_C
+#define SET_C_LOG(T,val) (T)->st |= (val) << 30
+#define SET_N_BIT(T,val,bit) (T)->st |= ((val) << (31 - (bit))) & STBIT_N
+#define SET_N_LOG(T,val) (T)->st |= (val) << 31
+
+#define SET_Z_VAL(T,val) SET_Z_LOG(T, (val) == 0)
+#define SET_N_VAL(T,val) SET_N_BIT(T, val, 31)
+#define SET_NZ_VAL(T,val) SET_Z_VAL(T, val); SET_N_VAL(T, val)
+#define SET_V_SUB(T,a,b,r) SET_V_BIT_HI(T, ((a) ^ (b)) & ((a) ^ (r)), 31)
+#define SET_V_ADD(T,a,b,r) SET_V_BIT_HI(T, ~((a) ^ (b)) & ((a) ^ (r)), 31)
+#define SET_C_SUB(T,a,b) SET_C_LOG(T, (UINT32)(b) > (UINT32)(a))
+#define SET_C_ADD(T,a,b) SET_C_LOG(T, (UINT32)~(a) < (UINT32)(b))
+#define SET_NZV_SUB(T,a,b,r) SET_NZ_VAL(T,r); SET_V_SUB(T,a,b,r)
+#define SET_NZCV_SUB(T,a,b,r) SET_NZV_SUB(T,a,b,r); SET_C_SUB(T,a,b)
+#define SET_NZCV_ADD(T,a,b,r) SET_NZ_VAL(T,r); SET_V_ADD(T,a,b,r); SET_C_ADD(T,a,b)
+
+static const UINT8 fw_inc[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 };
+
+
+/***************************************************************************
+ UNIMPLEMENTED INSTRUCTION
+***************************************************************************/
+
+static void unimpl(tms34010_state *tms, UINT16 op)
+{
+ /* kludge for Super High Impact -- this doesn't seem to cause */
+ /* an illegal opcode exception */
+ if (tms->direct->read_decrypted_word(TOBYTE(tms->pc - 0x10)) == 0x0007)
+ return;
+
+ /* 9 Ball Shootout calls to FFDF7468, expecting it */
+ /* to execute the next instruction from FFDF7470 */
+ /* but the instruction at FFDF7460 is an 0x0001 */
+ if (tms->direct->read_decrypted_word(TOBYTE(tms->pc - 0x10)) == 0x0001)
+ return;
+
+ PUSH(tms, tms->pc);
+ PUSH(tms, tms->st);
+ RESET_ST(tms);
+ tms->pc = RLONG(tms, 0xfffffc20);
+ COUNT_UNKNOWN_CYCLES(tms,16);
+
+ /* extra check to prevent bad things */
+ if (tms->pc == 0 || opcode_table[tms->direct->read_decrypted_word(TOBYTE(tms->pc)) >> 4] == unimpl)
+ {
+ device_set_input_line(tms->device, INPUT_LINE_HALT, ASSERT_LINE);
+ debugger_break(tms->device->machine());
+ }
+}
+
+
+
+/***************************************************************************
+ X/Y OPERATIONS
+***************************************************************************/
+
+#define ADD_XY(R) \
+{ \
+ XY a = R##REG_XY(tms,SRCREG(op)); \
+ XY *b = &R##REG_XY(tms,DSTREG(op)); \
+ CLR_NCZV(tms); \
+ b->x += a.x; \
+ b->y += a.y; \
+ SET_N_LOG(tms, b->x == 0); \
+ SET_C_BIT_LO(tms, b->y, 15); \
+ SET_Z_LOG(tms, b->y == 0); \
+ SET_V_BIT_LO(tms, b->x, 15); \
+ COUNT_CYCLES(tms,1); \
+}
+static void add_xy_a(tms34010_state *tms, UINT16 op) { ADD_XY(A); }
+static void add_xy_b(tms34010_state *tms, UINT16 op) { ADD_XY(B); }
+
+#define SUB_XY(R) \
+{ \
+ XY a = R##REG_XY(tms,SRCREG(op)); \
+ XY *b = &R##REG_XY(tms,DSTREG(op)); \
+ CLR_NCZV(tms); \
+ SET_N_LOG(tms, a.x == b->x); \
+ SET_C_LOG(tms, a.y > b->y); \
+ SET_Z_LOG(tms, a.y == b->y); \
+ SET_V_LOG(tms, a.x > b->x); \
+ b->x -= a.x; \
+ b->y -= a.y; \
+ COUNT_CYCLES(tms,1); \
+}
+static void sub_xy_a(tms34010_state *tms, UINT16 op) { SUB_XY(A); }
+static void sub_xy_b(tms34010_state *tms, UINT16 op) { SUB_XY(B); }
+
+#define CMP_XY(R) \
+{ \
+ INT16 res; \
+ XY a = R##REG_XY(tms,DSTREG(op)); \
+ XY b = R##REG_XY(tms,SRCREG(op)); \
+ CLR_NCZV(tms); \
+ res = a.x-b.x; \
+ SET_N_LOG(tms, res == 0); \
+ SET_V_BIT_LO(tms, res, 15); \
+ res = a.y-b.y; \
+ SET_Z_LOG(tms, res == 0); \
+ SET_C_BIT_LO(tms, res, 15); \
+ COUNT_CYCLES(tms,1); \
+}
+static void cmp_xy_a(tms34010_state *tms, UINT16 op) { CMP_XY(A); }
+static void cmp_xy_b(tms34010_state *tms, UINT16 op) { CMP_XY(B); }
+
+#define CPW(R) \
+{ \
+ INT32 res = 0; \
+ INT16 x = R##REG_X(tms,SRCREG(op)); \
+ INT16 y = R##REG_Y(tms,SRCREG(op)); \
+ \
+ CLR_V(tms); \
+ res |= ((WSTART_X(tms) > x) ? 0x20 : 0); \
+ res |= ((x > WEND_X(tms)) ? 0x40 : 0); \
+ res |= ((WSTART_Y(tms) > y) ? 0x80 : 0); \
+ res |= ((y > WEND_Y(tms)) ? 0x100 : 0); \
+ R##REG(tms,DSTREG(op)) = res; \
+ SET_V_LOG(tms, res != 0); \
+ COUNT_CYCLES(tms,1); \
+}
+static void cpw_a(tms34010_state *tms, UINT16 op) { CPW(A); }
+static void cpw_b(tms34010_state *tms, UINT16 op) { CPW(B); }
+
+#define CVXYL(R) \
+{ \
+ R##REG(tms,DSTREG(op)) = DXYTOL(tms,R##REG_XY(tms,SRCREG(op))); \
+ COUNT_CYCLES(tms,3); \
+}
+static void cvxyl_a(tms34010_state *tms, UINT16 op) { CVXYL(A); }
+static void cvxyl_b(tms34010_state *tms, UINT16 op) { CVXYL(B); }
+
+#define MOVX(R) \
+{ \
+ R##REG(tms,DSTREG(op)) = (R##REG(tms,DSTREG(op)) & 0xffff0000) | (UINT16)R##REG(tms,SRCREG(op)); \
+ COUNT_CYCLES(tms,1); \
+}
+static void movx_a(tms34010_state *tms, UINT16 op) { MOVX(A); }
+static void movx_b(tms34010_state *tms, UINT16 op) { MOVX(B); }
+
+#define MOVY(R) \
+{ \
+ R##REG(tms,DSTREG(op)) = (R##REG(tms,SRCREG(op)) & 0xffff0000) | (UINT16)R##REG(tms,DSTREG(op)); \
+ COUNT_CYCLES(tms,1); \
+}
+static void movy_a(tms34010_state *tms, UINT16 op) { MOVY(A); }
+static void movy_b(tms34010_state *tms, UINT16 op) { MOVY(B); }
+
+
+
+/***************************************************************************
+ PIXEL TRANSFER OPERATIONS
+***************************************************************************/
+
+#define PIXT_RI(R) \
+{ \
+ WPIXEL(tms,R##REG(tms,DSTREG(op)),R##REG(tms,SRCREG(op))); \
+ COUNT_UNKNOWN_CYCLES(tms,2); \
+}
+static void pixt_ri_a(tms34010_state *tms, UINT16 op) { PIXT_RI(A); }
+static void pixt_ri_b(tms34010_state *tms, UINT16 op) { PIXT_RI(B); }
+
+#define PIXT_RIXY(R) \
+{ \
+ if (WINDOW_CHECKING(tms) != 0) \
+ { \
+ CLR_V(tms); \
+ if (R##REG_X(tms,DSTREG(op)) < WSTART_X(tms) || R##REG_X(tms,DSTREG(op)) > WEND_X(tms) || \
+ R##REG_Y(tms,DSTREG(op)) < WSTART_Y(tms) || R##REG_Y(tms,DSTREG(op)) > WEND_Y(tms)) \
+ { \
+ SET_V_LOG(tms, 1); \
+ goto skip; \
+ } \
+ if (WINDOW_CHECKING(tms) == 1) goto skip; \
+ } \
+ WPIXEL(tms,DXYTOL(tms,R##REG_XY(tms,DSTREG(op))),R##REG(tms,SRCREG(op))); \
+skip: \
+ COUNT_UNKNOWN_CYCLES(tms,4); \
+}
+static void pixt_rixy_a(tms34010_state *tms, UINT16 op) { PIXT_RIXY(A); }
+static void pixt_rixy_b(tms34010_state *tms, UINT16 op) { PIXT_RIXY(B); }
+
+#define PIXT_IR(R) \
+{ \
+ INT32 temp = RPIXEL(tms,R##REG(tms,SRCREG(op))); \
+ CLR_V(tms); \
+ R##REG(tms,DSTREG(op)) = temp; \
+ SET_V_LOG(tms, temp != 0); \
+ COUNT_CYCLES(tms,4); \
+}
+static void pixt_ir_a(tms34010_state *tms, UINT16 op) { PIXT_IR(A); }
+static void pixt_ir_b(tms34010_state *tms, UINT16 op) { PIXT_IR(B); }
+
+#define PIXT_II(R) \
+{ \
+ WPIXEL(tms,R##REG(tms,DSTREG(op)),RPIXEL(tms,R##REG(tms,SRCREG(op)))); \
+ COUNT_UNKNOWN_CYCLES(tms,4); \
+}
+static void pixt_ii_a(tms34010_state *tms, UINT16 op) { PIXT_II(A); }
+static void pixt_ii_b(tms34010_state *tms, UINT16 op) { PIXT_II(B); }
+
+#define PIXT_IXYR(R) \
+{ \
+ INT32 temp = RPIXEL(tms,SXYTOL(tms,R##REG_XY(tms,SRCREG(op)))); \
+ CLR_V(tms); \
+ R##REG(tms,DSTREG(op)) = temp; \
+ SET_V_LOG(tms, temp != 0); \
+ COUNT_CYCLES(tms,6); \
+}
+static void pixt_ixyr_a(tms34010_state *tms, UINT16 op) { PIXT_IXYR(A); }
+static void pixt_ixyr_b(tms34010_state *tms, UINT16 op) { PIXT_IXYR(B); }
+
+#define PIXT_IXYIXY(R) \
+{ \
+ if (WINDOW_CHECKING(tms) != 0) \
+ { \
+ CLR_V(tms); \
+ if (R##REG_X(tms,DSTREG(op)) < WSTART_X(tms) || R##REG_X(tms,DSTREG(op)) > WEND_X(tms) || \
+ R##REG_Y(tms,DSTREG(op)) < WSTART_Y(tms) || R##REG_Y(tms,DSTREG(op)) > WEND_Y(tms)) \
+ { \
+ SET_V_LOG(tms, 1); \
+ goto skip; \
+ } \
+ if (WINDOW_CHECKING(tms) == 1) goto skip; \
+ } \
+ WPIXEL(tms,DXYTOL(tms,R##REG_XY(tms,DSTREG(op))),RPIXEL(tms,SXYTOL(tms,R##REG_XY(tms,SRCREG(op))))); \
+skip: \
+ COUNT_UNKNOWN_CYCLES(tms,7); \
+}
+static void pixt_ixyixy_a(tms34010_state *tms, UINT16 op) { PIXT_IXYIXY(A); }
+static void pixt_ixyixy_b(tms34010_state *tms, UINT16 op) { PIXT_IXYIXY(B); }
+
+#define DRAV(R) \
+{ \
+ if (WINDOW_CHECKING(tms) != 0) \
+ { \
+ CLR_V(tms); \
+ if (R##REG_X(tms,DSTREG(op)) < WSTART_X(tms) || R##REG_X(tms,DSTREG(op)) > WEND_X(tms) || \
+ R##REG_Y(tms,DSTREG(op)) < WSTART_Y(tms) || R##REG_Y(tms,DSTREG(op)) > WEND_Y(tms)) \
+ { \
+ SET_V_LOG(tms, 1); \
+ goto skip; \
+ } \
+ if (WINDOW_CHECKING(tms) == 1) goto skip; \
+ } \
+ WPIXEL(tms,DXYTOL(tms,R##REG_XY(tms,DSTREG(op))),COLOR1(tms)); \
+skip: \
+ R##REG_X(tms,DSTREG(op)) += R##REG_X(tms,SRCREG(op)); \
+ R##REG_Y(tms,DSTREG(op)) += R##REG_Y(tms,SRCREG(op)); \
+ COUNT_UNKNOWN_CYCLES(tms,4); \
+}
+static void drav_a(tms34010_state *tms, UINT16 op) { DRAV(A); }
+static void drav_b(tms34010_state *tms, UINT16 op) { DRAV(B); }
+
+
+
+/***************************************************************************
+ ARITHMETIC OPERATIONS
+***************************************************************************/
+
+#define ABS(R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 r = 0 - *rd; \
+ CLR_NZV(tms); \
+ if (r > 0) *rd = r; \
+ SET_NZ_VAL(tms, r); \
+ SET_V_LOG(tms, r == (INT32)0x80000000); \
+ COUNT_CYCLES(tms,1); \
+}
+static void abs_a(tms34010_state *tms, UINT16 op) { ABS(A); }
+static void abs_b(tms34010_state *tms, UINT16 op) { ABS(B); }
+
+#define ADD(R) \
+{ \
+ INT32 a = R##REG(tms,SRCREG(op)); \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 b = *rd; \
+ INT32 r = a + b; \
+ CLR_NCZV(tms); \
+ *rd = r; \
+ SET_NZCV_ADD(tms,a,b,r); \
+ COUNT_CYCLES(tms,1); \
+}
+static void add_a(tms34010_state *tms, UINT16 op) { ADD(A); }
+static void add_b(tms34010_state *tms, UINT16 op) { ADD(B); }
+
+#define ADDC(R) \
+{ \
+ /* I'm not sure to which side the carry is added to, should */ \
+ /* verify it against the examples */ \
+ INT32 a = R##REG(tms,SRCREG(op)); \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 b = *rd; \
+ INT32 r = a + b + (C_FLAG(tms) ? 1 : 0); \
+ CLR_NCZV(tms); \
+ *rd = r; \
+ SET_NZCV_ADD(tms,a,b,r); \
+ COUNT_CYCLES(tms,1); \
+}
+static void addc_a(tms34010_state *tms, UINT16 op) { ADDC(A); }
+static void addc_b(tms34010_state *tms, UINT16 op) { ADDC(B); }
+
+#define ADDI_W(R) \
+{ \
+ INT32 a = PARAM_WORD(tms); \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 b = *rd; \
+ INT32 r = a + b; \
+ CLR_NCZV(tms); \
+ *rd = r; \
+ SET_NZCV_ADD(tms,a,b,r); \
+ COUNT_CYCLES(tms,2); \
+}
+static void addi_w_a(tms34010_state *tms, UINT16 op) { ADDI_W(A); }
+static void addi_w_b(tms34010_state *tms, UINT16 op) { ADDI_W(B); }
+
+#define ADDI_L(R) \
+{ \
+ INT32 a = PARAM_LONG(tms); \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 b = *rd; \
+ INT32 r = a + b; \
+ CLR_NCZV(tms); \
+ *rd = r; \
+ SET_NZCV_ADD(tms,a,b,r); \
+ COUNT_CYCLES(tms,3); \
+}
+static void addi_l_a(tms34010_state *tms, UINT16 op) { ADDI_L(A); }
+static void addi_l_b(tms34010_state *tms, UINT16 op) { ADDI_L(B); }
+
+#define ADDK(R) \
+{ \
+ INT32 a = fw_inc[PARAM_K(op)]; \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 b = *rd; \
+ INT32 r = a + b; \
+ CLR_NCZV(tms); \
+ *rd = r; \
+ SET_NZCV_ADD(tms,a,b,r); \
+ COUNT_CYCLES(tms,1); \
+}
+static void addk_a(tms34010_state *tms, UINT16 op) { ADDK(A); }
+static void addk_b(tms34010_state *tms, UINT16 op) { ADDK(B); }
+
+#define AND(R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ CLR_Z(tms); \
+ *rd &= R##REG(tms,SRCREG(op)); \
+ SET_Z_VAL(tms, *rd); \
+ COUNT_CYCLES(tms,1); \
+}
+static void and_a(tms34010_state *tms, UINT16 op) { AND(A); }
+static void and_b(tms34010_state *tms, UINT16 op) { AND(B); }
+
+#define ANDI(R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ CLR_Z(tms); \
+ *rd &= ~PARAM_LONG(tms); \
+ SET_Z_VAL(tms, *rd); \
+ COUNT_CYCLES(tms,3); \
+}
+static void andi_a(tms34010_state *tms, UINT16 op) { ANDI(A); }
+static void andi_b(tms34010_state *tms, UINT16 op) { ANDI(B); }
+
+#define ANDN(R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ CLR_Z(tms); \
+ *rd &= ~R##REG(tms,SRCREG(op)); \
+ SET_Z_VAL(tms, *rd); \
+ COUNT_CYCLES(tms,1); \
+}
+static void andn_a(tms34010_state *tms, UINT16 op) { ANDN(A); }
+static void andn_b(tms34010_state *tms, UINT16 op) { ANDN(B); }
+
+#define BTST_K(R) \
+{ \
+ int bit = 31 - PARAM_K(op); \
+ CLR_Z(tms); \
+ if (bit <= 29) \
+ SET_Z_BIT_LO(tms, ~R##REG(tms,DSTREG(op)), bit); \
+ else \
+ SET_Z_BIT_HI(tms, ~R##REG(tms,DSTREG(op)), bit); \
+ COUNT_CYCLES(tms,1); \
+}
+static void btst_k_a(tms34010_state *tms, UINT16 op) { BTST_K(A); }
+static void btst_k_b(tms34010_state *tms, UINT16 op) { BTST_K(B); }
+
+#define BTST_R(R) \
+{ \
+ int bit = R##REG(tms,SRCREG(op)) & 0x1f; \
+ CLR_Z(tms); \
+ if (bit <= 29) \
+ SET_Z_BIT_LO(tms, ~R##REG(tms,DSTREG(op)), bit); \
+ else \
+ SET_Z_BIT_HI(tms, ~R##REG(tms,DSTREG(op)), bit); \
+ COUNT_CYCLES(tms,2); \
+}
+static void btst_r_a(tms34010_state *tms, UINT16 op) { BTST_R(A); }
+static void btst_r_b(tms34010_state *tms, UINT16 op) { BTST_R(B); }
+
+static void clrc(tms34010_state *tms, UINT16 op)
+{
+ CLR_C(tms);
+ COUNT_CYCLES(tms,1);
+}
+
+#define CMP(R) \
+{ \
+ INT32 *rs = &R##REG(tms,SRCREG(op)); \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 r = *rd - *rs; \
+ CLR_NCZV(tms); \
+ SET_NZCV_SUB(tms,*rd,*rs,r); \
+ COUNT_CYCLES(tms,1); \
+}
+static void cmp_a(tms34010_state *tms, UINT16 op) { CMP(A); }
+static void cmp_b(tms34010_state *tms, UINT16 op) { CMP(B); }
+
+#define CMPI_W(R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 t = (INT16)~PARAM_WORD(tms); \
+ INT32 r = *rd - t; \
+ CLR_NCZV(tms); \
+ SET_NZCV_SUB(tms,*rd,t,r); \
+ COUNT_CYCLES(tms,2); \
+}
+static void cmpi_w_a(tms34010_state *tms, UINT16 op) { CMPI_W(A); }
+static void cmpi_w_b(tms34010_state *tms, UINT16 op) { CMPI_W(B); }
+
+#define CMPI_L(R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 t = ~PARAM_LONG(tms); \
+ INT32 r = *rd - t; \
+ CLR_NCZV(tms); \
+ SET_NZCV_SUB(tms,*rd,t,r); \
+ COUNT_CYCLES(tms,3); \
+}
+static void cmpi_l_a(tms34010_state *tms, UINT16 op) { CMPI_L(A); }
+static void cmpi_l_b(tms34010_state *tms, UINT16 op) { CMPI_L(B); }
+
+static void dint(tms34010_state *tms, UINT16 op)
+{
+ tms->st &= ~STBIT_IE;
+ COUNT_CYCLES(tms,3);
+}
+
+#define DIVS(R) \
+{ \
+ INT32 *rs = &R##REG(tms,SRCREG(op)); \
+ INT32 *rd1 = &R##REG(tms,DSTREG(op)); \
+ CLR_NZV(tms); \
+ if (!(DSTREG(op) & 1)) \
+ { \
+ if (!*rs) \
+ { \
+ SET_V_LOG(tms, 1); \
+ } \
+ else \
+ { \
+ INT32 *rd2 = &R##REG(tms,DSTREG(op)+1); \
+ INT64 dividend = ((UINT64)*rd1 << 32) | (UINT32)*rd2; \
+ INT64 quotient = dividend / *rs; \
+ INT32 remainder = dividend % *rs; \
+ UINT32 signbits = (INT32)quotient >> 31; \
+ if (EXTRACT_64HI(quotient) != signbits) \
+ { \
+ SET_V_LOG(tms, 1); \
+ } \
+ else \
+ { \
+ *rd1 = quotient; \
+ *rd2 = remainder; \
+ SET_NZ_VAL(tms, *rd1); \
+ } \
+ } \
+ COUNT_CYCLES(tms,40); \
+ } \
+ else \
+ { \
+ if (!*rs) \
+ { \
+ SET_V_LOG(tms, 1); \
+ } \
+ else \
+ { \
+ *rd1 /= *rs; \
+ SET_NZ_VAL(tms, *rd1); \
+ } \
+ COUNT_CYCLES(tms,39); \
+ } \
+}
+static void divs_a(tms34010_state *tms, UINT16 op) { DIVS(A); }
+static void divs_b(tms34010_state *tms, UINT16 op) { DIVS(B); }
+
+#define DIVU(R) \
+{ \
+ INT32 *rs = &R##REG(tms,SRCREG(op)); \
+ INT32 *rd1 = &R##REG(tms,DSTREG(op)); \
+ CLR_ZV(tms); \
+ if (!(DSTREG(op) & 1)) \
+ { \
+ if (!*rs) \
+ { \
+ SET_V_LOG(tms, 1); \
+ } \
+ else \
+ { \
+ INT32 *rd2 = &R##REG(tms,DSTREG(op)+1); \
+ UINT64 dividend = ((UINT64)*rd1 << 32) | (UINT32)*rd2; \
+ UINT64 quotient = dividend / (UINT32)*rs; \
+ UINT32 remainder = dividend % (UINT32)*rs; \
+ if (EXTRACT_64HI(quotient) != 0) \
+ { \
+ SET_V_LOG(tms, 1); \
+ } \
+ else \
+ { \
+ *rd1 = quotient; \
+ *rd2 = remainder; \
+ SET_Z_VAL(tms, *rd1); \
+ } \
+ } \
+ } \
+ else \
+ { \
+ if (!*rs) \
+ { \
+ SET_V_LOG(tms, 1); \
+ } \
+ else \
+ { \
+ *rd1 = (UINT32)*rd1 / (UINT32)*rs; \
+ SET_Z_VAL(tms, *rd1); \
+ } \
+ } \
+ COUNT_CYCLES(tms,37); \
+}
+static void divu_a(tms34010_state *tms, UINT16 op) { DIVU(A); }
+static void divu_b(tms34010_state *tms, UINT16 op) { DIVU(B); }
+
+static void eint(tms34010_state *tms, UINT16 op)
+{
+ tms->st |= STBIT_IE;
+ check_interrupt(tms);
+ COUNT_CYCLES(tms,3);
+}
+
+#define EXGF(F,R) \
+{ \
+ UINT8 shift = F ? 6 : 0; \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ UINT32 temp = (tms->st >> shift) & 0x3f; \
+ tms->st &= ~(0x3f << shift); \
+ tms->st |= (*rd & 0x3f) << shift; \
+ *rd = temp; \
+ COUNT_CYCLES(tms,1); \
+}
+static void exgf0_a(tms34010_state *tms, UINT16 op) { EXGF(0,A); }
+static void exgf0_b(tms34010_state *tms, UINT16 op) { EXGF(0,B); }
+static void exgf1_a(tms34010_state *tms, UINT16 op) { EXGF(1,A); }
+static void exgf1_b(tms34010_state *tms, UINT16 op) { EXGF(1,B); }
+
+#define LMO(R) \
+{ \
+ UINT32 res = 0; \
+ UINT32 rs = R##REG(tms,SRCREG(op)); \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ CLR_Z(tms); \
+ SET_Z_VAL(tms, rs); \
+ if (rs) \
+ { \
+ while (!(rs & 0x80000000)) \
+ { \
+ res++; \
+ rs <<= 1; \
+ } \
+ } \
+ *rd = res; \
+ COUNT_CYCLES(tms,1); \
+}
+static void lmo_a(tms34010_state *tms, UINT16 op) { LMO(A); }
+static void lmo_b(tms34010_state *tms, UINT16 op) { LMO(B); }
+
+#define MMFM(R) \
+{ \
+ INT32 i; \
+ UINT16 l = (UINT16) PARAM_WORD(tms); \
+ COUNT_CYCLES(tms,3); \
+ { \
+ INT32 rd = DSTREG(op); \
+ for (i = 15; i >= 0 ; i--) \
+ { \
+ if (l & 0x8000) \
+ { \
+ R##REG(tms,i) = RLONG(tms, R##REG(tms,rd)); \
+ R##REG(tms,rd) += 0x20; \
+ COUNT_CYCLES(tms,4); \
+ } \
+ l <<= 1; \
+ } \
+ } \
+}
+static void mmfm_a(tms34010_state *tms, UINT16 op) { MMFM(A); }
+static void mmfm_b(tms34010_state *tms, UINT16 op) { MMFM(B); }
+
+#define MMTM(R) \
+{ \
+ UINT32 i; \
+ UINT16 l = (UINT16) PARAM_WORD(tms); \
+ COUNT_CYCLES(tms,2); \
+ { \
+ INT32 rd = DSTREG(op); \
+ if (tms->is_34020) \
+ { \
+ CLR_N(tms); \
+ SET_N_VAL(tms, R##REG(tms,rd) ^ 0x80000000); \
+ } \
+ for (i = 0; i < 16; i++) \
+ { \
+ if (l & 0x8000) \
+ { \
+ R##REG(tms,rd) -= 0x20; \
+ WLONG(tms, R##REG(tms,rd),R##REG(tms,i)); \
+ COUNT_CYCLES(tms,4); \
+ } \
+ l <<= 1; \
+ } \
+ } \
+}
+static void mmtm_a(tms34010_state *tms, UINT16 op) { MMTM(A); }
+static void mmtm_b(tms34010_state *tms, UINT16 op) { MMTM(B); }
+
+#define MODS(R) \
+{ \
+ INT32 *rs = &R##REG(tms,SRCREG(op)); \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ CLR_NZV(tms); \
+ if (*rs != 0) \
+ { \
+ *rd %= *rs; \
+ SET_NZ_VAL(tms, *rd); \
+ } \
+ else \
+ SET_V_LOG(tms, 1); \
+ COUNT_CYCLES(tms,40); \
+}
+static void mods_a(tms34010_state *tms, UINT16 op) { MODS(A); }
+static void mods_b(tms34010_state *tms, UINT16 op) { MODS(B); }
+
+#define MODU(R) \
+{ \
+ INT32 *rs = &R##REG(tms,SRCREG(op)); \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ CLR_ZV(tms); \
+ if (*rs != 0) \
+ { \
+ *rd = (UINT32)*rd % (UINT32)*rs; \
+ SET_Z_VAL(tms, *rd); \
+ } \
+ else \
+ SET_V_LOG(tms, 1); \
+ COUNT_CYCLES(tms,35); \
+}
+static void modu_a(tms34010_state *tms, UINT16 op) { MODU(A); }
+static void modu_b(tms34010_state *tms, UINT16 op) { MODU(B); }
+
+#define MPYS(R) \
+{ \
+ INT32 *rd1 = &R##REG(tms,DSTREG(op)); \
+ INT32 m1 = R##REG(tms,SRCREG(op)); \
+ INT64 product; \
+ \
+ SEXTEND(m1, FW(tms,1)); \
+ CLR_NZ(tms); \
+ product = mul_32x32(m1, *rd1); \
+ SET_Z_LOG(tms, product == 0); \
+ SET_N_BIT(tms, product >> 32, 31); \
+ \
+ *rd1 = EXTRACT_64HI(product); \
+ R##REG(tms,DSTREG(op)|1) = EXTRACT_64LO(product); \
+ \
+ COUNT_CYCLES(tms,20); \
+}
+static void mpys_a(tms34010_state *tms, UINT16 op) { MPYS(A); }
+static void mpys_b(tms34010_state *tms, UINT16 op) { MPYS(B); }
+
+#define MPYU(R) \
+{ \
+ INT32 *rd1 = &R##REG(tms,DSTREG(op)); \
+ UINT32 m1 = R##REG(tms,SRCREG(op)); \
+ UINT64 product; \
+ \
+ ZEXTEND(m1, FW(tms,1)); \
+ CLR_Z(tms); \
+ product = mulu_32x32(m1, *rd1); \
+ SET_Z_LOG(tms, product == 0); \
+ \
+ *rd1 = EXTRACT_64HI(product); \
+ R##REG(tms,DSTREG(op)|1) = EXTRACT_64LO(product); \
+ \
+ COUNT_CYCLES(tms,21); \
+}
+static void mpyu_a(tms34010_state *tms, UINT16 op) { MPYU(A); }
+static void mpyu_b(tms34010_state *tms, UINT16 op) { MPYU(B); }
+
+#define NEG(R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 r = 0 - *rd; \
+ CLR_NCZV(tms); \
+ SET_NZCV_SUB(tms,0,*rd,r); \
+ *rd = r; \
+ COUNT_CYCLES(tms,1); \
+}
+static void neg_a(tms34010_state *tms, UINT16 op) { NEG(A); }
+static void neg_b(tms34010_state *tms, UINT16 op) { NEG(B); }
+
+#define NEGB(R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 t = *rd + (C_FLAG(tms) ? 1 : 0); \
+ INT32 r = 0 - t; \
+ CLR_NCZV(tms); \
+ SET_NZCV_SUB(tms,0,t,r); \
+ *rd = r; \
+ COUNT_CYCLES(tms,1); \
+}
+static void negb_a(tms34010_state *tms, UINT16 op) { NEGB(A); }
+static void negb_b(tms34010_state *tms, UINT16 op) { NEGB(B); }
+
+static void nop(tms34010_state *tms, UINT16 op)
+{
+ COUNT_CYCLES(tms,1);
+}
+
+#define NOT(R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ CLR_Z(tms); \
+ *rd = ~(*rd); \
+ SET_Z_VAL(tms, *rd); \
+ COUNT_CYCLES(tms,1); \
+}
+static void not_a(tms34010_state *tms, UINT16 op) { NOT(A); }
+static void not_b(tms34010_state *tms, UINT16 op) { NOT(B); }
+
+#define OR(R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ CLR_Z(tms); \
+ *rd |= R##REG(tms,SRCREG(op)); \
+ SET_Z_VAL(tms, *rd); \
+ COUNT_CYCLES(tms,1); \
+}
+static void or_a(tms34010_state *tms, UINT16 op) { OR(A); }
+static void or_b(tms34010_state *tms, UINT16 op) { OR(B); }
+
+#define ORI(R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ CLR_Z(tms); \
+ *rd |= PARAM_LONG(tms); \
+ SET_Z_VAL(tms, *rd); \
+ COUNT_CYCLES(tms,3); \
+}
+static void ori_a(tms34010_state *tms, UINT16 op) { ORI(A); }
+static void ori_b(tms34010_state *tms, UINT16 op) { ORI(B); }
+
+static void setc(tms34010_state *tms, UINT16 op)
+{
+ SET_C_LOG(tms, 1);
+ COUNT_CYCLES(tms,1);
+}
+
+#define SETF(F) \
+{ \
+ UINT8 shift = F ? 6 : 0; \
+ tms->st &= ~(0x3f << shift); \
+ tms->st |= (op & 0x3f) << shift; \
+ COUNT_CYCLES(tms,1+F); \
+}
+static void setf0(tms34010_state *tms, UINT16 op) { SETF(0); }
+static void setf1(tms34010_state *tms, UINT16 op) { SETF(1); }
+
+#define SEXT(F,R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ CLR_NZ(tms); \
+ SEXTEND(*rd,FW(tms,F)); \
+ SET_NZ_VAL(tms, *rd); \
+ COUNT_CYCLES(tms,3); \
+}
+static void sext0_a(tms34010_state *tms, UINT16 op) { SEXT(0,A); }
+static void sext0_b(tms34010_state *tms, UINT16 op) { SEXT(0,B); }
+static void sext1_a(tms34010_state *tms, UINT16 op) { SEXT(1,A); }
+static void sext1_b(tms34010_state *tms, UINT16 op) { SEXT(1,B); }
+
+#define RL(R,K) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 res = *rd; \
+ INT32 k = (K); \
+ CLR_CZ(tms); \
+ if (k) \
+ { \
+ res<<=(k-1); \
+ SET_C_BIT_HI(tms, res, 31); \
+ res<<=1; \
+ res |= (((UINT32)*rd)>>((-k)&0x1f)); \
+ *rd = res; \
+ } \
+ SET_Z_VAL(tms, res); \
+ COUNT_CYCLES(tms,1); \
+}
+static void rl_k_a(tms34010_state *tms, UINT16 op) { RL(A,PARAM_K(op)); }
+static void rl_k_b(tms34010_state *tms, UINT16 op) { RL(B,PARAM_K(op)); }
+static void rl_r_a(tms34010_state *tms, UINT16 op) { RL(A,AREG(tms,SRCREG(op))&0x1f); }
+static void rl_r_b(tms34010_state *tms, UINT16 op) { RL(B,BREG(tms,SRCREG(op))&0x1f); }
+
+#define SLA(R,K) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ UINT32 res = *rd; \
+ INT32 k = K; \
+ CLR_NCZV(tms); \
+ if (k) \
+ { \
+ UINT32 mask = (0xffffffff<<(31-k))&0x7fffffff; \
+ UINT32 res2 = SIGN(res) ? res^mask : res; \
+ SET_V_LOG(tms, (res2 & mask) != 0); \
+ \
+ res<<=(k-1); \
+ SET_C_BIT_HI(tms, res, 31); \
+ res<<=1; \
+ *rd = res; \
+ } \
+ SET_NZ_VAL(tms, res); \
+ COUNT_CYCLES(tms,3); \
+}
+static void sla_k_a(tms34010_state *tms, UINT16 op) { SLA(A,PARAM_K(op)); }
+static void sla_k_b(tms34010_state *tms, UINT16 op) { SLA(B,PARAM_K(op)); }
+static void sla_r_a(tms34010_state *tms, UINT16 op) { SLA(A,AREG(tms,SRCREG(op))&0x1f); }
+static void sla_r_b(tms34010_state *tms, UINT16 op) { SLA(B,BREG(tms,SRCREG(op))&0x1f); }
+
+#define SLL(R,K) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ UINT32 res = *rd; \
+ INT32 k = K; \
+ CLR_CZ(tms); \
+ if (k) \
+ { \
+ res<<=(k-1); \
+ SET_C_BIT_HI(tms, res, 31); \
+ res<<=1; \
+ *rd = res; \
+ } \
+ SET_Z_VAL(tms, res); \
+ COUNT_CYCLES(tms,1); \
+}
+static void sll_k_a(tms34010_state *tms, UINT16 op) { SLL(A,PARAM_K(op)); }
+static void sll_k_b(tms34010_state *tms, UINT16 op) { SLL(B,PARAM_K(op)); }
+static void sll_r_a(tms34010_state *tms, UINT16 op) { SLL(A,AREG(tms,SRCREG(op))&0x1f); }
+static void sll_r_b(tms34010_state *tms, UINT16 op) { SLL(B,BREG(tms,SRCREG(op))&0x1f); }
+
+#define SRA(R,K) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 res = *rd; \
+ INT32 k = (-(K)) & 0x1f; \
+ CLR_NCZ(tms); \
+ if (k) \
+ { \
+ res>>=(k-1); \
+ SET_C_BIT_LO(tms, res, 0); \
+ res>>=1; \
+ *rd = res; \
+ } \
+ SET_NZ_VAL(tms, res); \
+ COUNT_CYCLES(tms,1); \
+}
+static void sra_k_a(tms34010_state *tms, UINT16 op) { SRA(A,PARAM_K(op)); }
+static void sra_k_b(tms34010_state *tms, UINT16 op) { SRA(B,PARAM_K(op)); }
+static void sra_r_a(tms34010_state *tms, UINT16 op) { SRA(A,AREG(tms,SRCREG(op))); }
+static void sra_r_b(tms34010_state *tms, UINT16 op) { SRA(B,BREG(tms,SRCREG(op))); }
+
+#define SRL(R,K) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ UINT32 res = *rd; \
+ INT32 k = (-(K)) & 0x1f; \
+ CLR_CZ(tms); \
+ if (k) \
+ { \
+ res>>=(k-1); \
+ SET_C_BIT_LO(tms, res, 0); \
+ res>>=1; \
+ *rd = res; \
+ } \
+ SET_Z_VAL(tms, res); \
+ COUNT_CYCLES(tms,1); \
+}
+static void srl_k_a(tms34010_state *tms, UINT16 op) { SRL(A,PARAM_K(op)); }
+static void srl_k_b(tms34010_state *tms, UINT16 op) { SRL(B,PARAM_K(op)); }
+static void srl_r_a(tms34010_state *tms, UINT16 op) { SRL(A,AREG(tms,SRCREG(op))); }
+static void srl_r_b(tms34010_state *tms, UINT16 op) { SRL(B,BREG(tms,SRCREG(op))); }
+
+#define SUB(R) \
+{ \
+ INT32 *rs = &R##REG(tms,SRCREG(op)); \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 r = *rd - *rs; \
+ CLR_NCZV(tms); \
+ SET_NZCV_SUB(tms,*rd,*rs,r); \
+ *rd = r; \
+ COUNT_CYCLES(tms,1); \
+}
+static void sub_a(tms34010_state *tms, UINT16 op) { SUB(A); }
+static void sub_b(tms34010_state *tms, UINT16 op) { SUB(B); }
+
+#define SUBB(R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 t = R##REG(tms,SRCREG(op)); \
+ INT32 r = *rd - t - (C_FLAG(tms) ? 1 : 0); \
+ CLR_NCZV(tms); \
+ SET_NZCV_SUB(tms,*rd,t,r); \
+ *rd = r; \
+ COUNT_CYCLES(tms,1); \
+}
+static void subb_a(tms34010_state *tms, UINT16 op) { SUBB(A); }
+static void subb_b(tms34010_state *tms, UINT16 op) { SUBB(B); }
+
+#define SUBI_W(R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 r; \
+ INT32 t = ~PARAM_WORD(tms); \
+ CLR_NCZV(tms); \
+ r = *rd - t; \
+ SET_NZCV_SUB(tms,*rd,t,r); \
+ *rd = r; \
+ COUNT_CYCLES(tms,2); \
+}
+static void subi_w_a(tms34010_state *tms, UINT16 op) { SUBI_W(A); }
+static void subi_w_b(tms34010_state *tms, UINT16 op) { SUBI_W(B); }
+
+#define SUBI_L(R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 t = ~PARAM_LONG(tms); \
+ INT32 r = *rd - t; \
+ CLR_NCZV(tms); \
+ SET_NZCV_SUB(tms,*rd,t,r); \
+ *rd = r; \
+ COUNT_CYCLES(tms,3); \
+}
+static void subi_l_a(tms34010_state *tms, UINT16 op) { SUBI_L(A); }
+static void subi_l_b(tms34010_state *tms, UINT16 op) { SUBI_L(B); }
+
+#define SUBK(R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 t = fw_inc[PARAM_K(op)]; \
+ INT32 r = *rd - t; \
+ CLR_NCZV(tms); \
+ SET_NZCV_SUB(tms,*rd,t,r); \
+ *rd = r; \
+ COUNT_CYCLES(tms,1); \
+}
+static void subk_a(tms34010_state *tms, UINT16 op) { SUBK(A); }
+static void subk_b(tms34010_state *tms, UINT16 op) { SUBK(B); }
+
+#define XOR(R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ CLR_Z(tms); \
+ *rd ^= R##REG(tms,SRCREG(op)); \
+ SET_Z_VAL(tms, *rd); \
+ COUNT_CYCLES(tms,1); \
+}
+static void xor_a(tms34010_state *tms, UINT16 op) { XOR(A); }
+static void xor_b(tms34010_state *tms, UINT16 op) { XOR(B); }
+
+#define XORI(R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ CLR_Z(tms); \
+ *rd ^= PARAM_LONG(tms); \
+ SET_Z_VAL(tms, *rd); \
+ COUNT_CYCLES(tms,3); \
+}
+static void xori_a(tms34010_state *tms, UINT16 op) { XORI(A); }
+static void xori_b(tms34010_state *tms, UINT16 op) { XORI(B); }
+
+#define ZEXT(F,R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ CLR_Z(tms); \
+ ZEXTEND(*rd,FW(tms,F)); \
+ SET_Z_VAL(tms, *rd); \
+ COUNT_CYCLES(tms,1); \
+}
+static void zext0_a(tms34010_state *tms, UINT16 op) { ZEXT(0,A); }
+static void zext0_b(tms34010_state *tms, UINT16 op) { ZEXT(0,B); }
+static void zext1_a(tms34010_state *tms, UINT16 op) { ZEXT(1,A); }
+static void zext1_b(tms34010_state *tms, UINT16 op) { ZEXT(1,B); }
+
+
+
+/***************************************************************************
+ MOVE INSTRUCTIONS
+***************************************************************************/
+
+#define MOVI_W(R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ CLR_NZV(tms); \
+ *rd=PARAM_WORD(tms); \
+ SET_NZ_VAL(tms, *rd); \
+ COUNT_CYCLES(tms,2); \
+}
+static void movi_w_a(tms34010_state *tms, UINT16 op) { MOVI_W(A); }
+static void movi_w_b(tms34010_state *tms, UINT16 op) { MOVI_W(B); }
+
+#define MOVI_L(R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ CLR_NZV(tms); \
+ *rd=PARAM_LONG(tms); \
+ SET_NZ_VAL(tms, *rd); \
+ COUNT_CYCLES(tms,3); \
+}
+static void movi_l_a(tms34010_state *tms, UINT16 op) { MOVI_L(A); }
+static void movi_l_b(tms34010_state *tms, UINT16 op) { MOVI_L(B); }
+
+#define MOVK(R) \
+{ \
+ INT32 k = PARAM_K(op); if (!k) k = 32; \
+ R##REG(tms,DSTREG(op)) = k; \
+ COUNT_CYCLES(tms,1); \
+}
+static void movk_a(tms34010_state *tms, UINT16 op) { MOVK(A); }
+static void movk_b(tms34010_state *tms, UINT16 op) { MOVK(B); }
+
+#define MOVB_RN(R) \
+{ \
+ WBYTE(tms, R##REG(tms,DSTREG(op)),R##REG(tms,SRCREG(op))); \
+ COUNT_CYCLES(tms,1); \
+}
+static void movb_rn_a(tms34010_state *tms, UINT16 op) { MOVB_RN(A); }
+static void movb_rn_b(tms34010_state *tms, UINT16 op) { MOVB_RN(B); }
+
+#define MOVB_NR(R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ CLR_NZV(tms); \
+ *rd = (INT8)RBYTE(tms, R##REG(tms,SRCREG(op))); \
+ SET_NZ_VAL(tms, *rd); \
+ COUNT_CYCLES(tms,3); \
+}
+static void movb_nr_a(tms34010_state *tms, UINT16 op) { MOVB_NR(A); }
+static void movb_nr_b(tms34010_state *tms, UINT16 op) { MOVB_NR(B); }
+
+#define MOVB_NN(R) \
+{ \
+ WBYTE(tms, R##REG(tms,DSTREG(op)),(UINT32)(UINT8)RBYTE(tms, R##REG(tms,SRCREG(op))));\
+ COUNT_CYCLES(tms,3); \
+}
+static void movb_nn_a(tms34010_state *tms, UINT16 op) { MOVB_NN(A); }
+static void movb_nn_b(tms34010_state *tms, UINT16 op) { MOVB_NN(B); }
+
+#define MOVB_R_NO(R) \
+{ \
+ INT32 o = PARAM_WORD(tms); \
+ WBYTE(tms, R##REG(tms,DSTREG(op))+o,R##REG(tms,SRCREG(op))); \
+ COUNT_CYCLES(tms,3); \
+}
+static void movb_r_no_a(tms34010_state *tms, UINT16 op) { MOVB_R_NO(A); }
+static void movb_r_no_b(tms34010_state *tms, UINT16 op) { MOVB_R_NO(B); }
+
+#define MOVB_NO_R(R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 o = PARAM_WORD(tms); \
+ CLR_NZV(tms); \
+ *rd = (INT8)RBYTE(tms, R##REG(tms,SRCREG(op))+o); \
+ SET_NZ_VAL(tms, *rd); \
+ COUNT_CYCLES(tms,5); \
+}
+static void movb_no_r_a(tms34010_state *tms, UINT16 op) { MOVB_NO_R(A); }
+static void movb_no_r_b(tms34010_state *tms, UINT16 op) { MOVB_NO_R(B); }
+
+#define MOVB_NO_NO(R) \
+{ \
+ INT32 o1 = PARAM_WORD(tms); \
+ INT32 o2 = PARAM_WORD(tms); \
+ WBYTE(tms, R##REG(tms,DSTREG(op))+o2,(UINT32)(UINT8)RBYTE(tms, R##REG(tms,SRCREG(op))+o1)); \
+ COUNT_CYCLES(tms,5); \
+}
+static void movb_no_no_a(tms34010_state *tms, UINT16 op) { MOVB_NO_NO(A); }
+static void movb_no_no_b(tms34010_state *tms, UINT16 op) { MOVB_NO_NO(B); }
+
+#define MOVB_RA(R) \
+{ \
+ WBYTE(tms, PARAM_LONG(tms),R##REG(tms,DSTREG(op))); \
+ COUNT_CYCLES(tms,1); \
+}
+static void movb_ra_a(tms34010_state *tms, UINT16 op) { MOVB_RA(A); }
+static void movb_ra_b(tms34010_state *tms, UINT16 op) { MOVB_RA(B); }
+
+#define MOVB_AR(R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ CLR_NZV(tms); \
+ *rd = (INT8)RBYTE(tms, PARAM_LONG(tms)); \
+ SET_NZ_VAL(tms, *rd); \
+ COUNT_CYCLES(tms,5); \
+}
+static void movb_ar_a(tms34010_state *tms, UINT16 op) { MOVB_AR(A); }
+static void movb_ar_b(tms34010_state *tms, UINT16 op) { MOVB_AR(B); }
+
+static void movb_aa(tms34010_state *tms, UINT16 op)
+{
+ UINT32 bitaddrs=PARAM_LONG(tms);
+ WBYTE(tms, PARAM_LONG(tms),(UINT32)(UINT8)RBYTE(tms, bitaddrs));
+ COUNT_CYCLES(tms,6);
+}
+
+#define MOVE_RR(RS,RD) \
+{ \
+ INT32 *rd = &RD##REG(tms,DSTREG(op)); \
+ CLR_NZV(tms); \
+ *rd = RS##REG(tms,SRCREG(op)); \
+ SET_NZ_VAL(tms, *rd); \
+ COUNT_CYCLES(tms,1); \
+}
+static void move_rr_a (tms34010_state *tms, UINT16 op) { MOVE_RR(A,A); }
+static void move_rr_b (tms34010_state *tms, UINT16 op) { MOVE_RR(B,B); }
+static void move_rr_ax(tms34010_state *tms, UINT16 op) { MOVE_RR(A,B); }
+static void move_rr_bx(tms34010_state *tms, UINT16 op) { MOVE_RR(B,A); }
+
+#define MOVE_RN(F,R) \
+{ \
+ WFIELD##F(tms,R##REG(tms,DSTREG(op)),R##REG(tms,SRCREG(op))); \
+ COUNT_CYCLES(tms,1); \
+}
+static void move0_rn_a (tms34010_state *tms, UINT16 op) { MOVE_RN(0,A); }
+static void move0_rn_b (tms34010_state *tms, UINT16 op) { MOVE_RN(0,B); }
+static void move1_rn_a (tms34010_state *tms, UINT16 op) { MOVE_RN(1,A); }
+static void move1_rn_b (tms34010_state *tms, UINT16 op) { MOVE_RN(1,B); }
+
+#define MOVE_R_DN(F,R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ *rd-=fw_inc[FW(tms,F)]; \
+ WFIELD##F(tms,*rd,R##REG(tms,SRCREG(op))); \
+ COUNT_CYCLES(tms,2); \
+}
+static void move0_r_dn_a (tms34010_state *tms, UINT16 op) { MOVE_R_DN(0,A); }
+static void move0_r_dn_b (tms34010_state *tms, UINT16 op) { MOVE_R_DN(0,B); }
+static void move1_r_dn_a (tms34010_state *tms, UINT16 op) { MOVE_R_DN(1,A); }
+static void move1_r_dn_b (tms34010_state *tms, UINT16 op) { MOVE_R_DN(1,B); }
+
+#define MOVE_R_NI(F,R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ WFIELD##F(tms,*rd,R##REG(tms,SRCREG(op))); \
+ *rd+=fw_inc[FW(tms,F)]; \
+ COUNT_CYCLES(tms,1); \
+}
+static void move0_r_ni_a (tms34010_state *tms, UINT16 op) { MOVE_R_NI(0,A); }
+static void move0_r_ni_b (tms34010_state *tms, UINT16 op) { MOVE_R_NI(0,B); }
+static void move1_r_ni_a (tms34010_state *tms, UINT16 op) { MOVE_R_NI(1,A); }
+static void move1_r_ni_b (tms34010_state *tms, UINT16 op) { MOVE_R_NI(1,B); }
+
+#define MOVE_NR(F,R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ CLR_NZV(tms); \
+ *rd = RFIELD##F(tms,R##REG(tms,SRCREG(op))); \
+ SET_NZ_VAL(tms, *rd); \
+ COUNT_CYCLES(tms,3); \
+}
+static void move0_nr_a (tms34010_state *tms, UINT16 op) { MOVE_NR(0,A); }
+static void move0_nr_b (tms34010_state *tms, UINT16 op) { MOVE_NR(0,B); }
+static void move1_nr_a (tms34010_state *tms, UINT16 op) { MOVE_NR(1,A); }
+static void move1_nr_b (tms34010_state *tms, UINT16 op) { MOVE_NR(1,B); }
+
+#define MOVE_DN_R(F,R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 *rs = &R##REG(tms,SRCREG(op)); \
+ CLR_NZV(tms); \
+ *rs-=fw_inc[FW(tms,F)]; \
+ *rd = RFIELD##F(tms,*rs); \
+ SET_NZ_VAL(tms, *rd); \
+ COUNT_CYCLES(tms,4); \
+}
+static void move0_dn_r_a (tms34010_state *tms, UINT16 op) { MOVE_DN_R(0,A); }
+static void move0_dn_r_b (tms34010_state *tms, UINT16 op) { MOVE_DN_R(0,B); }
+static void move1_dn_r_a (tms34010_state *tms, UINT16 op) { MOVE_DN_R(1,A); }
+static void move1_dn_r_b (tms34010_state *tms, UINT16 op) { MOVE_DN_R(1,B); }
+
+#define MOVE_NI_R(F,R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 *rs = &R##REG(tms,SRCREG(op)); \
+ INT32 data = RFIELD##F(tms,*rs); \
+ CLR_NZV(tms); \
+ *rs+=fw_inc[FW(tms,F)]; \
+ *rd = data; \
+ SET_NZ_VAL(tms, *rd); \
+ COUNT_CYCLES(tms,3); \
+}
+static void move0_ni_r_a (tms34010_state *tms, UINT16 op) { MOVE_NI_R(0,A); }
+static void move0_ni_r_b (tms34010_state *tms, UINT16 op) { MOVE_NI_R(0,B); }
+static void move1_ni_r_a (tms34010_state *tms, UINT16 op) { MOVE_NI_R(1,A); }
+static void move1_ni_r_b (tms34010_state *tms, UINT16 op) { MOVE_NI_R(1,B); }
+
+#define MOVE_NN(F,R) \
+{ \
+ WFIELD##F(tms,R##REG(tms,DSTREG(op)),RFIELD##F(tms,R##REG(tms,SRCREG(op)))); \
+ COUNT_CYCLES(tms,3); \
+}
+static void move0_nn_a (tms34010_state *tms, UINT16 op) { MOVE_NN(0,A); }
+static void move0_nn_b (tms34010_state *tms, UINT16 op) { MOVE_NN(0,B); }
+static void move1_nn_a (tms34010_state *tms, UINT16 op) { MOVE_NN(1,A); }
+static void move1_nn_b (tms34010_state *tms, UINT16 op) { MOVE_NN(1,B); }
+
+#define MOVE_DN_DN(F,R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 *rs = &R##REG(tms,SRCREG(op)); \
+ INT32 data; \
+ *rs-=fw_inc[FW(tms,F)]; \
+ data = RFIELD##F(tms,*rs); \
+ *rd-=fw_inc[FW(tms,F)]; \
+ WFIELD##F(tms,*rd,data); \
+ COUNT_CYCLES(tms,4); \
+}
+static void move0_dn_dn_a (tms34010_state *tms, UINT16 op) { MOVE_DN_DN(0,A); }
+static void move0_dn_dn_b (tms34010_state *tms, UINT16 op) { MOVE_DN_DN(0,B); }
+static void move1_dn_dn_a (tms34010_state *tms, UINT16 op) { MOVE_DN_DN(1,A); }
+static void move1_dn_dn_b (tms34010_state *tms, UINT16 op) { MOVE_DN_DN(1,B); }
+
+#define MOVE_NI_NI(F,R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 *rs = &R##REG(tms,SRCREG(op)); \
+ INT32 data = RFIELD##F(tms,*rs); \
+ *rs+=fw_inc[FW(tms,F)]; \
+ WFIELD##F(tms,*rd,data); \
+ *rd+=fw_inc[FW(tms,F)]; \
+ COUNT_CYCLES(tms,4); \
+}
+static void move0_ni_ni_a (tms34010_state *tms, UINT16 op) { MOVE_NI_NI(0,A); }
+static void move0_ni_ni_b (tms34010_state *tms, UINT16 op) { MOVE_NI_NI(0,B); }
+static void move1_ni_ni_a (tms34010_state *tms, UINT16 op) { MOVE_NI_NI(1,A); }
+static void move1_ni_ni_b (tms34010_state *tms, UINT16 op) { MOVE_NI_NI(1,B); }
+
+#define MOVE_R_NO(F,R) \
+{ \
+ INT32 o = PARAM_WORD(tms); \
+ WFIELD##F(tms,R##REG(tms,DSTREG(op))+o,R##REG(tms,SRCREG(op))); \
+ COUNT_CYCLES(tms,3); \
+}
+static void move0_r_no_a (tms34010_state *tms, UINT16 op) { MOVE_R_NO(0,A); }
+static void move0_r_no_b (tms34010_state *tms, UINT16 op) { MOVE_R_NO(0,B); }
+static void move1_r_no_a (tms34010_state *tms, UINT16 op) { MOVE_R_NO(1,A); }
+static void move1_r_no_b (tms34010_state *tms, UINT16 op) { MOVE_R_NO(1,B); }
+
+#define MOVE_NO_R(F,R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 o = PARAM_WORD(tms); \
+ CLR_NZV(tms); \
+ *rd = RFIELD##F(tms,R##REG(tms,SRCREG(op))+o); \
+ SET_NZ_VAL(tms, *rd); \
+ COUNT_CYCLES(tms,5); \
+}
+static void move0_no_r_a (tms34010_state *tms, UINT16 op) { MOVE_NO_R(0,A); }
+static void move0_no_r_b (tms34010_state *tms, UINT16 op) { MOVE_NO_R(0,B); }
+static void move1_no_r_a (tms34010_state *tms, UINT16 op) { MOVE_NO_R(1,A); }
+static void move1_no_r_b (tms34010_state *tms, UINT16 op) { MOVE_NO_R(1,B); }
+
+#define MOVE_NO_NI(F,R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 o = PARAM_WORD(tms); \
+ INT32 data = RFIELD##F(tms,R##REG(tms,SRCREG(op))+o); \
+ WFIELD##F(tms,*rd,data); \
+ *rd+=fw_inc[FW(tms,F)]; \
+ COUNT_CYCLES(tms,5); \
+}
+static void move0_no_ni_a (tms34010_state *tms, UINT16 op) { MOVE_NO_NI(0,A); }
+static void move0_no_ni_b (tms34010_state *tms, UINT16 op) { MOVE_NO_NI(0,B); }
+static void move1_no_ni_a (tms34010_state *tms, UINT16 op) { MOVE_NO_NI(1,A); }
+static void move1_no_ni_b (tms34010_state *tms, UINT16 op) { MOVE_NO_NI(1,B); }
+
+#define MOVE_NO_NO(F,R) \
+{ \
+ INT32 o1 = PARAM_WORD(tms); \
+ INT32 o2 = PARAM_WORD(tms); \
+ INT32 data = RFIELD##F(tms,R##REG(tms,SRCREG(op))+o1); \
+ WFIELD##F(tms,R##REG(tms,DSTREG(op))+o2,data); \
+ COUNT_CYCLES(tms,5); \
+}
+static void move0_no_no_a (tms34010_state *tms, UINT16 op) { MOVE_NO_NO(0,A); }
+static void move0_no_no_b (tms34010_state *tms, UINT16 op) { MOVE_NO_NO(0,B); }
+static void move1_no_no_a (tms34010_state *tms, UINT16 op) { MOVE_NO_NO(1,A); }
+static void move1_no_no_b (tms34010_state *tms, UINT16 op) { MOVE_NO_NO(1,B); }
+
+#define MOVE_RA(F,R) \
+{ \
+ WFIELD##F(tms,PARAM_LONG(tms),R##REG(tms,DSTREG(op))); \
+ COUNT_CYCLES(tms,3); \
+}
+static void move0_ra_a (tms34010_state *tms, UINT16 op) { MOVE_RA(0,A); }
+static void move0_ra_b (tms34010_state *tms, UINT16 op) { MOVE_RA(0,B); }
+static void move1_ra_a (tms34010_state *tms, UINT16 op) { MOVE_RA(1,A); }
+static void move1_ra_b (tms34010_state *tms, UINT16 op) { MOVE_RA(1,B); }
+
+#define MOVE_AR(F,R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ CLR_NZV(tms); \
+ *rd = RFIELD##F(tms,PARAM_LONG(tms)); \
+ SET_NZ_VAL(tms, *rd); \
+ COUNT_CYCLES(tms,5); \
+}
+static void move0_ar_a (tms34010_state *tms, UINT16 op) { MOVE_AR(0,A); }
+static void move0_ar_b (tms34010_state *tms, UINT16 op) { MOVE_AR(0,B); }
+static void move1_ar_a (tms34010_state *tms, UINT16 op) { MOVE_AR(1,A); }
+static void move1_ar_b (tms34010_state *tms, UINT16 op) { MOVE_AR(1,B); }
+
+#define MOVE_A_NI(F,R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ WFIELD##F(tms,*rd,RFIELD##F(tms,PARAM_LONG(tms))); \
+ *rd+=fw_inc[FW(tms,F)]; \
+ COUNT_CYCLES(tms,5); \
+}
+static void move0_a_ni_a (tms34010_state *tms, UINT16 op) { MOVE_A_NI(0,A); }
+static void move0_a_ni_b (tms34010_state *tms, UINT16 op) { MOVE_A_NI(0,B); }
+static void move1_a_ni_a (tms34010_state *tms, UINT16 op) { MOVE_A_NI(1,A); }
+static void move1_a_ni_b (tms34010_state *tms, UINT16 op) { MOVE_A_NI(1,B); }
+
+#define MOVE_AA(F) \
+{ \
+ UINT32 bitaddrs=PARAM_LONG(tms); \
+ WFIELD##F(tms,PARAM_LONG(tms),RFIELD##F(tms,bitaddrs)); \
+ COUNT_CYCLES(tms,7); \
+}
+static void move0_aa (tms34010_state *tms, UINT16 op) { MOVE_AA(0); }
+static void move1_aa (tms34010_state *tms, UINT16 op) { MOVE_AA(1); }
+
+
+
+/***************************************************************************
+ PROGRAM CONTROL INSTRUCTIONS
+***************************************************************************/
+
+#define CALL(R) \
+{ \
+ PUSH(tms, tms->pc); \
+ tms->pc = R##REG(tms,DSTREG(op)); \
+ CORRECT_ODD_PC(tms,"CALL"); \
+ COUNT_CYCLES(tms,3); \
+}
+static void call_a (tms34010_state *tms, UINT16 op) { CALL(A); }
+static void call_b (tms34010_state *tms, UINT16 op) { CALL(B); }
+
+static void callr(tms34010_state *tms, UINT16 op)
+{
+ PUSH(tms, tms->pc+0x10);
+ tms->pc += (PARAM_WORD_NO_INC(tms)<<4)+0x10;
+ COUNT_CYCLES(tms,3);
+}
+
+static void calla(tms34010_state *tms, UINT16 op)
+{
+ PUSH(tms, tms->pc+0x20);
+ tms->pc = PARAM_LONG_NO_INC(tms);
+ CORRECT_ODD_PC(tms,"CALLA");
+ COUNT_CYCLES(tms,4);
+}
+
+#define DSJ(R) \
+{ \
+ if (--R##REG(tms,DSTREG(op))) \
+ { \
+ tms->pc += (PARAM_WORD_NO_INC(tms)<<4)+0x10; \
+ COUNT_CYCLES(tms,3); \
+ } \
+ else \
+ { \
+ SKIP_WORD(tms); \
+ COUNT_CYCLES(tms,2); \
+ } \
+}
+static void dsj_a (tms34010_state *tms, UINT16 op) { DSJ(A); }
+static void dsj_b (tms34010_state *tms, UINT16 op) { DSJ(B); }
+
+#define DSJEQ(R) \
+{ \
+ if (Z_FLAG(tms)) \
+ { \
+ if (--R##REG(tms,DSTREG(op))) \
+ { \
+ tms->pc += (PARAM_WORD_NO_INC(tms)<<4)+0x10; \
+ COUNT_CYCLES(tms,3); \
+ } \
+ else \
+ { \
+ SKIP_WORD(tms); \
+ COUNT_CYCLES(tms,2); \
+ } \
+ } \
+ else \
+ { \
+ SKIP_WORD(tms); \
+ COUNT_CYCLES(tms,2); \
+ } \
+}
+static void dsjeq_a (tms34010_state *tms, UINT16 op) { DSJEQ(A); }
+static void dsjeq_b (tms34010_state *tms, UINT16 op) { DSJEQ(B); }
+
+#define DSJNE(R) \
+{ \
+ if (!Z_FLAG(tms)) \
+ { \
+ if (--R##REG(tms,DSTREG(op))) \
+ { \
+ tms->pc += (PARAM_WORD_NO_INC(tms)<<4)+0x10; \
+ COUNT_CYCLES(tms,3); \
+ } \
+ else \
+ { \
+ SKIP_WORD(tms); \
+ COUNT_CYCLES(tms,2); \
+ } \
+ } \
+ else \
+ { \
+ SKIP_WORD(tms); \
+ COUNT_CYCLES(tms,2); \
+ } \
+}
+static void dsjne_a (tms34010_state *tms, UINT16 op) { DSJNE(A); }
+static void dsjne_b (tms34010_state *tms, UINT16 op) { DSJNE(B); }
+
+#define DSJS(R) \
+{ \
+ if (op & 0x0400) \
+ { \
+ if (--R##REG(tms,DSTREG(op))) \
+ { \
+ tms->pc -= ((PARAM_K(op))<<4); \
+ COUNT_CYCLES(tms,2); \
+ } \
+ else \
+ COUNT_CYCLES(tms,3); \
+ } \
+ else \
+ { \
+ if (--R##REG(tms,DSTREG(op))) \
+ { \
+ tms->pc += ((PARAM_K(op))<<4); \
+ COUNT_CYCLES(tms,2); \
+ } \
+ else \
+ COUNT_CYCLES(tms,3); \
+ } \
+}
+static void dsjs_a (tms34010_state *tms, UINT16 op) { DSJS(A); }
+static void dsjs_b (tms34010_state *tms, UINT16 op) { DSJS(B); }
+
+static void emu(tms34010_state *tms, UINT16 op)
+{
+ /* in RUN state, this instruction is a NOP */
+ COUNT_CYCLES(tms,6);
+}
+
+#define EXGPC(R) \
+{ \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 temppc = *rd; \
+ *rd = tms->pc; \
+ tms->pc = temppc; \
+ CORRECT_ODD_PC(tms,"EXGPC"); \
+ COUNT_CYCLES(tms,2); \
+}
+static void exgpc_a (tms34010_state *tms, UINT16 op) { EXGPC(A); }
+static void exgpc_b (tms34010_state *tms, UINT16 op) { EXGPC(B); }
+
+#define GETPC(R) \
+{ \
+ R##REG(tms,DSTREG(op)) = tms->pc; \
+ COUNT_CYCLES(tms,1); \
+}
+static void getpc_a (tms34010_state *tms, UINT16 op) { GETPC(A); }
+static void getpc_b (tms34010_state *tms, UINT16 op) { GETPC(B); }
+
+#define GETST(R) \
+{ \
+ R##REG(tms,DSTREG(op)) = tms->st; \
+ COUNT_CYCLES(tms,1); \
+}
+static void getst_a (tms34010_state *tms, UINT16 op) { GETST(A); }
+static void getst_b (tms34010_state *tms, UINT16 op) { GETST(B); }
+
+#define j_xx_8(TAKE) \
+{ \
+ if (DSTREG(op)) \
+ { \
+ if (TAKE) \
+ { \
+ tms->pc += (PARAM_REL8(op) << 4); \
+ COUNT_CYCLES(tms,2); \
+ } \
+ else \
+ COUNT_CYCLES(tms,1); \
+ } \
+ else \
+ { \
+ if (TAKE) \
+ { \
+ tms->pc = PARAM_LONG_NO_INC(tms); \
+ CORRECT_ODD_PC(tms,"J_XX_8"); \
+ COUNT_CYCLES(tms,3); \
+ } \
+ else \
+ { \
+ SKIP_LONG(tms); \
+ COUNT_CYCLES(tms,4); \
+ } \
+ } \
+}
+
+#define j_xx_0(TAKE) \
+{ \
+ if (DSTREG(op)) \
+ { \
+ if (TAKE) \
+ { \
+ tms->pc += (PARAM_REL8(op) << 4); \
+ COUNT_CYCLES(tms,2); \
+ } \
+ else \
+ COUNT_CYCLES(tms,1); \
+ } \
+ else \
+ { \
+ if (TAKE) \
+ { \
+ tms->pc += (PARAM_WORD_NO_INC(tms)<<4)+0x10; \
+ COUNT_CYCLES(tms,3); \
+ } \
+ else \
+ { \
+ SKIP_WORD(tms); \
+ COUNT_CYCLES(tms,2); \
+ } \
+ } \
+}
+
+#define j_xx_x(TAKE) \
+{ \
+ if (TAKE) \
+ { \
+ tms->pc += (PARAM_REL8(op) << 4); \
+ COUNT_CYCLES(tms,2); \
+ } \
+ else \
+ COUNT_CYCLES(tms,1); \
+}
+
+static void j_UC_0(tms34010_state *tms, UINT16 op)
+{
+ j_xx_0(1);
+}
+static void j_UC_8(tms34010_state *tms, UINT16 op)
+{
+ j_xx_8(1);
+}
+static void j_UC_x(tms34010_state *tms, UINT16 op)
+{
+ j_xx_x(1);
+}
+static void j_P_0(tms34010_state *tms, UINT16 op)
+{
+ j_xx_0(!N_FLAG(tms) && !Z_FLAG(tms));
+}
+static void j_P_8(tms34010_state *tms, UINT16 op)
+{
+ j_xx_8(!N_FLAG(tms) && !Z_FLAG(tms));
+}
+static void j_P_x(tms34010_state *tms, UINT16 op)
+{
+ j_xx_x(!N_FLAG(tms) && !Z_FLAG(tms));
+}
+static void j_LS_0(tms34010_state *tms, UINT16 op)
+{
+ j_xx_0(C_FLAG(tms) || Z_FLAG(tms));
+}
+static void j_LS_8(tms34010_state *tms, UINT16 op)
+{
+ j_xx_8(C_FLAG(tms) || Z_FLAG(tms));
+}
+static void j_LS_x(tms34010_state *tms, UINT16 op)
+{
+ j_xx_x(C_FLAG(tms) || Z_FLAG(tms));
+}
+static void j_HI_0(tms34010_state *tms, UINT16 op)
+{
+ j_xx_0(!C_FLAG(tms) && !Z_FLAG(tms));
+}
+static void j_HI_8(tms34010_state *tms, UINT16 op)
+{
+ j_xx_8(!C_FLAG(tms) && !Z_FLAG(tms));
+}
+static void j_HI_x(tms34010_state *tms, UINT16 op)
+{
+ j_xx_x(!C_FLAG(tms) && !Z_FLAG(tms));
+}
+static void j_LT_0(tms34010_state *tms, UINT16 op)
+{
+ j_xx_0((N_FLAG(tms) && !V_FLAG(tms)) || (!N_FLAG(tms) && V_FLAG(tms)));
+}
+static void j_LT_8(tms34010_state *tms, UINT16 op)
+{
+ j_xx_8((N_FLAG(tms) && !V_FLAG(tms)) || (!N_FLAG(tms) && V_FLAG(tms)));
+}
+static void j_LT_x(tms34010_state *tms, UINT16 op)
+{
+ j_xx_x((N_FLAG(tms) && !V_FLAG(tms)) || (!N_FLAG(tms) && V_FLAG(tms)));
+}
+static void j_GE_0(tms34010_state *tms, UINT16 op)
+{
+ j_xx_0((N_FLAG(tms) && V_FLAG(tms)) || (!N_FLAG(tms) && !V_FLAG(tms)));
+}
+static void j_GE_8(tms34010_state *tms, UINT16 op)
+{
+ j_xx_8((N_FLAG(tms) && V_FLAG(tms)) || (!N_FLAG(tms) && !V_FLAG(tms)));
+}
+static void j_GE_x(tms34010_state *tms, UINT16 op)
+{
+ j_xx_x((N_FLAG(tms) && V_FLAG(tms)) || (!N_FLAG(tms) && !V_FLAG(tms)));
+}
+static void j_LE_0(tms34010_state *tms, UINT16 op)
+{
+ j_xx_0((N_FLAG(tms) && !V_FLAG(tms)) || (!N_FLAG(tms) && V_FLAG(tms)) || Z_FLAG(tms));
+}
+static void j_LE_8(tms34010_state *tms, UINT16 op)
+{
+ j_xx_8((N_FLAG(tms) && !V_FLAG(tms)) || (!N_FLAG(tms) && V_FLAG(tms)) || Z_FLAG(tms));
+}
+static void j_LE_x(tms34010_state *tms, UINT16 op)
+{
+ j_xx_x((N_FLAG(tms) && !V_FLAG(tms)) || (!N_FLAG(tms) && V_FLAG(tms)) || Z_FLAG(tms));
+}
+static void j_GT_0(tms34010_state *tms, UINT16 op)
+{
+ j_xx_0((N_FLAG(tms) && V_FLAG(tms) && !Z_FLAG(tms)) || (!N_FLAG(tms) && !V_FLAG(tms) && !Z_FLAG(tms)));
+}
+static void j_GT_8(tms34010_state *tms, UINT16 op)
+{
+ j_xx_8((N_FLAG(tms) && V_FLAG(tms) && !Z_FLAG(tms)) || (!N_FLAG(tms) && !V_FLAG(tms) && !Z_FLAG(tms)));
+}
+static void j_GT_x(tms34010_state *tms, UINT16 op)
+{
+ j_xx_x((N_FLAG(tms) && V_FLAG(tms) && !Z_FLAG(tms)) || (!N_FLAG(tms) && !V_FLAG(tms) && !Z_FLAG(tms)));
+}
+static void j_C_0(tms34010_state *tms, UINT16 op)
+{
+ j_xx_0(C_FLAG(tms));
+}
+static void j_C_8(tms34010_state *tms, UINT16 op)
+{
+ j_xx_8(C_FLAG(tms));
+}
+static void j_C_x(tms34010_state *tms, UINT16 op)
+{
+ j_xx_x(C_FLAG(tms));
+}
+static void j_NC_0(tms34010_state *tms, UINT16 op)
+{
+ j_xx_0(!C_FLAG(tms));
+}
+static void j_NC_8(tms34010_state *tms, UINT16 op)
+{
+ j_xx_8(!C_FLAG(tms));
+}
+static void j_NC_x(tms34010_state *tms, UINT16 op)
+{
+ j_xx_x(!C_FLAG(tms));
+}
+static void j_EQ_0(tms34010_state *tms, UINT16 op)
+{
+ j_xx_0(Z_FLAG(tms));
+}
+static void j_EQ_8(tms34010_state *tms, UINT16 op)
+{
+ j_xx_8(Z_FLAG(tms));
+}
+static void j_EQ_x(tms34010_state *tms, UINT16 op)
+{
+ j_xx_x(Z_FLAG(tms));
+}
+static void j_NE_0(tms34010_state *tms, UINT16 op)
+{
+ j_xx_0(!Z_FLAG(tms));
+}
+static void j_NE_8(tms34010_state *tms, UINT16 op)
+{
+ j_xx_8(!Z_FLAG(tms));
+}
+static void j_NE_x(tms34010_state *tms, UINT16 op)
+{
+ j_xx_x(!Z_FLAG(tms));
+}
+static void j_V_0(tms34010_state *tms, UINT16 op)
+{
+ j_xx_0(V_FLAG(tms));
+}
+static void j_V_8(tms34010_state *tms, UINT16 op)
+{
+ j_xx_8(V_FLAG(tms));
+}
+static void j_V_x(tms34010_state *tms, UINT16 op)
+{
+ j_xx_x(V_FLAG(tms));
+}
+static void j_NV_0(tms34010_state *tms, UINT16 op)
+{
+ j_xx_0(!V_FLAG(tms));
+}
+static void j_NV_8(tms34010_state *tms, UINT16 op)
+{
+ j_xx_8(!V_FLAG(tms));
+}
+static void j_NV_x(tms34010_state *tms, UINT16 op)
+{
+ j_xx_x(!V_FLAG(tms));
+}
+static void j_N_0(tms34010_state *tms, UINT16 op)
+{
+ j_xx_0(N_FLAG(tms));
+}
+static void j_N_8(tms34010_state *tms, UINT16 op)
+{
+ j_xx_8(N_FLAG(tms));
+}
+static void j_N_x(tms34010_state *tms, UINT16 op)
+{
+ j_xx_x(N_FLAG(tms));
+}
+static void j_NN_0(tms34010_state *tms, UINT16 op)
+{
+ j_xx_0(!N_FLAG(tms));
+}
+static void j_NN_8(tms34010_state *tms, UINT16 op)
+{
+ j_xx_8(!N_FLAG(tms));
+}
+static void j_NN_x(tms34010_state *tms, UINT16 op)
+{
+ j_xx_x(!N_FLAG(tms));
+}
+
+#define JUMP(R) \
+{ \
+ tms->pc = R##REG(tms,DSTREG(op)); \
+ CORRECT_ODD_PC(tms,"JUMP"); \
+ COUNT_CYCLES(tms,2); \
+}
+static void jump_a (tms34010_state *tms, UINT16 op) { JUMP(A); }
+static void jump_b (tms34010_state *tms, UINT16 op) { JUMP(B); }
+
+static void popst(tms34010_state *tms, UINT16 op)
+{
+ SET_ST(tms, POP(tms));
+ COUNT_CYCLES(tms,8);
+}
+
+static void pushst(tms34010_state *tms, UINT16 op)
+{
+ PUSH(tms, tms->st);
+ COUNT_CYCLES(tms,2);
+}
+
+#define PUTST(R) \
+{ \
+ SET_ST(tms, R##REG(tms,DSTREG(op))); \
+ COUNT_CYCLES(tms,3); \
+}
+static void putst_a (tms34010_state *tms, UINT16 op) { PUTST(A); }
+static void putst_b (tms34010_state *tms, UINT16 op) { PUTST(B); }
+
+static void reti(tms34010_state *tms, UINT16 op)
+{
+ INT32 st = POP(tms);
+ tms->pc = POP(tms);
+ CORRECT_ODD_PC(tms,"RETI");
+ SET_ST(tms, st);
+ COUNT_CYCLES(tms,11);
+}
+
+static void rets(tms34010_state *tms, UINT16 op)
+{
+ UINT32 offs;
+ tms->pc = POP(tms);
+ CORRECT_ODD_PC(tms,"RETS");
+ offs = PARAM_N(op);
+ if (offs)
+ {
+ SP(tms)+=(offs<<4);
+ }
+ COUNT_CYCLES(tms,7);
+}
+
+#define REV(R) \
+{ \
+ R##REG(tms,DSTREG(op)) = 0x0008; \
+ COUNT_CYCLES(tms,1); \
+}
+static void rev_a (tms34010_state *tms, UINT16 op) { REV(A); }
+static void rev_b (tms34010_state *tms, UINT16 op) { REV(B); }
+
+static void trap(tms34010_state *tms, UINT16 op)
+{
+ UINT32 t = PARAM_N(op);
+ if (t)
+ {
+ PUSH(tms, tms->pc);
+ PUSH(tms, tms->st);
+ }
+ RESET_ST(tms);
+ tms->pc = RLONG(tms, 0xffffffe0-(t<<5));
+ CORRECT_ODD_PC(tms,"TRAP");
+ COUNT_CYCLES(tms,16);
+}
+
+
+
+/***************************************************************************
+ 34020 INSTRUCTIONS
+***************************************************************************/
+
+/************************************
+
+New 34020 ops:
+
+ 0000 1100 000R dddd = ADDXYI IL,Rd
+ iiii iiii iiii iiii
+ iiii iiii iiii iiii
+
+ 0000 0000 1111 00SD = BLMOVE S,D
+
+ 0000 0110 0000 0000 = CEXEC S,c,ID,L
+ cccc cccc S000 0000
+ iiic cccc cccc cccc
+
+ 1101 1000 0ccc cccS = CEXEC S,c,ID
+ iiic cccc cccc cccc
+
+ 0000 1000 1111 0010 = CLIP
+
+ 0000 0110 011R dddd = CMOVCG Rd1,Rd2,S,c,ID
+ cccc cccc S00R dddd
+ iiic cccc cccc cccc
+
+ 0000 0110 101R dddd = CMOVCM *Rd+,n,S,c,ID
+ cccc cccc S00n nnnn
+ iiic cccc cccc cccc
+
+ 0000 0110 110R dddd = CMOVCM -*Rd,n,S,c,ID
+ cccc cccc S00n nnnn
+ iiic cccc cccc cccc
+
+ 0000 0110 0110 0000 = CMOVCS c,ID
+ cccc cccc 0000 0001
+ iiic cccc cccc cccc
+
+ 0000 0110 001R ssss = CMOVGC Rs,c,ID
+ cccc cccc 0000 0000
+ iiic cccc cccc cccc
+
+ 0000 0110 010R ssss = CMOVGC Rs1,Rs2,S,c,ID
+ cccc cccc S00R ssss
+ iiic cccc cccc cccc
+
+ 0000 0110 100n nnnn = CMOVMC *Rs+,n,S,c,ID
+ cccc cccc S00R ssss
+ iiic cccc cccc cccc
+
+ 0000 1000 001n nnnn = CMOVMC -*Rs,n,S,c,ID
+ cccc cccc S00R ssss
+ iiic cccc cccc cccc
+
+ 0000 0110 111R dddd = CMOVMC *Rs+,Rd,S,c,ID
+ cccc cccc S00R ssss
+ iiic cccc cccc cccc
+
+ 0011 01kk kkkR dddd = CMPK k,Rd
+
+ 0000 1010 100R dddd = CVDXYL Rd
+
+ 0000 1010 011R dddd = CVMXYL Rd
+
+ 1110 101s sssR dddd = CVSXYL Rs,Rd
+
+ 0000 0010 101R dddd = EXGPS Rd
+
+ 1101 1110 Z001 1010 = FLINE Z
+
+ 0000 1010 1011 1011 = FPIXEQ
+
+ 0000 1010 1101 1011 = FPIXNE
+
+ 0000 0010 110R dddd = GETPS Rd
+
+ 0000 0000 0100 0000 = IDLE
+
+ 0000 1100 0101 0111 = LINIT
+
+ 0000 0000 1000 0000 = MWAIT
+
+ 0000 1010 0011 0111 = PFILL XY
+
+ 0000 1110 0001 0111 = PIXBLT L,M,L
+
+ 0000 1000 0110 0000 = RETM
+
+ 0111 101s sssR dddd = RMO Rs,Rd
+
+ 0000 0010 100R dddd = RPIX Rd
+
+ 0000 0010 0111 0011 = SETCDP
+
+ 0000 0010 1111 1011 = SETCMP
+
+ 0000 0010 0101 0001 = SETCSP
+
+ 0111 111s sssR dddd = SWAPF *Rs,Rd,0
+
+ 0000 1110 1111 1010 = TFILL XY
+
+ 0000 1000 0000 1111 = TRAPL
+
+ 0000 1000 0101 0111 = VBLT B,L
+
+ 0000 1010 0101 0111 = VFILL L
+
+ 0000 1010 0000 0000 = VLCOL
+
+************************************/
+
+
+#define ADD_XYI(R) \
+{ \
+ UINT32 a = PARAM_LONG(tms); \
+ XY *b = &R##REG_XY(tms,DSTREG(op)); \
+ CLR_NCZV(tms); \
+ b->x += (INT16)(a & 0xffff); \
+ b->y += ((INT32)a >> 16); \
+ SET_N_LOG(tms, b->x == 0); \
+ SET_C_BIT_LO(tms, b->y, 15); \
+ SET_Z_LOG(tms, b->y == 0); \
+ SET_V_BIT_LO(tms, b->x, 15); \
+ COUNT_CYCLES(tms,1); \
+}
+static void addxyi_a(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ ADD_XYI(A);
+}
+static void addxyi_b(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ ADD_XYI(B);
+}
+
+static void blmove(tms34010_state *tms, UINT16 op)
+{
+ offs_t src = BREG(tms,0);
+ offs_t dst = BREG(tms,2);
+ offs_t bits = BREG(tms,7);
+
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+
+ /* src and dst are aligned */
+ if (!(src & 0x0f) && !(dst & 0x0f))
+ {
+ while (bits >= 16 && tms->icount > 0)
+ {
+ TMS34010_WRMEM_WORD(tms, TOBYTE(dst), TMS34010_RDMEM_WORD(tms, TOBYTE(src)));
+ src += 0x10;
+ dst += 0x10;
+ bits -= 0x10;
+ tms->icount -= 2;
+ }
+ if (bits != 0 && tms->icount > 0)
+ {
+ (*tms34010_wfield_functions[bits])(tms, dst, (*tms34010_rfield_functions[bits])(tms, src));
+ dst += bits;
+ src += bits;
+ bits = 0;
+ tms->icount -= 2;
+ }
+ }
+
+ /* src is aligned, dst is not */
+ else if (!(src & 0x0f))
+ {
+ logerror("020:BLMOVE with aligned src and unaligned dst\n");
+ }
+
+ /* dst is aligned, src is not */
+ else if (!(dst & 0x0f))
+ {
+ logerror("020:BLMOVE with unaligned src and aligned dst\n");
+ }
+
+ /* neither are aligned */
+ else
+ {
+ logerror("020:BLMOVE with completely unaligned src and dst\n");
+ }
+
+ /* update the final results */
+ BREG(tms,0) = src;
+ BREG(tms,2) = dst;
+ BREG(tms,7) = bits;
+
+ /* if we're not done yet, back up the PC */
+ if (bits != 0)
+ tms->pc -= 0x10;
+}
+
+static void cexec_l(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:cexec_l\n");
+}
+
+static void cexec_s(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:cexec_s\n");
+}
+
+static void clip(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:clip\n");
+}
+
+static void cmovcg_a(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:cmovcg_a\n");
+}
+
+static void cmovcg_b(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:cmovcg_b\n");
+}
+
+static void cmovcm_f(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:cmovcm_f\n");
+}
+
+static void cmovcm_b(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:cmovcm_b\n");
+}
+
+static void cmovgc_a(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:cmovgc_a\n");
+}
+
+static void cmovgc_b(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:cmovgc_b\n");
+}
+
+static void cmovgc_a_s(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:cmovgc_a_s\n");
+}
+
+static void cmovgc_b_s(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:cmovgc_b_s\n");
+}
+
+static void cmovmc_f(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:cmovmc_f\n");
+}
+
+static void cmovmc_f_va(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:cmovmc_f_va\n");
+}
+
+static void cmovmc_f_vb(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:cmovmc_f_vb\n");
+}
+
+static void cmovmc_b(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:cmovmc_b\n");
+}
+
+#define CMPK(R) \
+{ \
+ INT32 r; \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ INT32 t = PARAM_K(op); if (!t) t = 32; \
+ CLR_NCZV(tms); \
+ r = *rd - t; \
+ SET_NZCV_SUB(tms,*rd,t,r); \
+ COUNT_CYCLES(tms,1); \
+}
+static void cmp_k_a(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ CMPK(A);
+}
+static void cmp_k_b(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ CMPK(B);
+}
+
+static void cvdxyl_a(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:cvdxyl_a\n");
+}
+
+static void cvdxyl_b(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:cvdxyl_b\n");
+}
+
+static void cvmxyl_a(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:cvmxyl_a\n");
+}
+
+static void cvmxyl_b(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:cvmxyl_b\n");
+}
+
+static void cvsxyl_a(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:cvsxyl_a\n");
+}
+
+static void cvsxyl_b(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:cvsxyl_b\n");
+}
+
+static void exgps_a(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:exgps_a\n");
+}
+
+static void exgps_b(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:exgps_b\n");
+}
+
+static void fline(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:fline\n");
+}
+
+static void fpixeq(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:fpixeq\n");
+}
+
+static void fpixne(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:fpixne\n");
+}
+
+static void getps_a(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:getps_a\n");
+}
+
+static void getps_b(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:getps_b\n");
+}
+
+static void idle(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:idle\n");
+}
+
+static void linit(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:linit\n");
+}
+
+static void mwait(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+}
+
+static void pfill_xy(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:pfill_xy\n");
+}
+
+static void pixblt_l_m_l(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:pixblt_l_m_l\n");
+}
+
+static void retm(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:retm\n");
+}
+
+#define RMO(R) \
+{ \
+ UINT32 res = 0; \
+ UINT32 rs = R##REG(tms,SRCREG(op)); \
+ INT32 *rd = &R##REG(tms,DSTREG(op)); \
+ CLR_Z(tms); \
+ SET_Z_VAL(tms, rs); \
+ if (rs) \
+ { \
+ while (!(rs & 0x00000001)) \
+ { \
+ res++; \
+ rs >>= 1; \
+ } \
+ } \
+ *rd = res; \
+ COUNT_CYCLES(tms,1); \
+}
+
+static void rmo_a(tms34010_state *tms, UINT16 op) { RMO(A); }
+static void rmo_b(tms34010_state *tms, UINT16 op) { RMO(B); }
+
+#define RPIX(R) \
+{ \
+ UINT32 v = R##REG(tms,DSTREG(op)); \
+ switch (tms->pixelshift) \
+ { \
+ case 0: \
+ v = (v & 1) ? 0xffffffff : 0x00000000;\
+ COUNT_CYCLES(tms,8); \
+ break; \
+ case 1: \
+ v &= 3; \
+ v |= v << 2; \
+ v |= v << 4; \
+ v |= v << 8; \
+ v |= v << 16; \
+ COUNT_CYCLES(tms,7); \
+ break; \
+ case 2: \
+ v &= 0x0f; \
+ v |= v << 4; \
+ v |= v << 8; \
+ v |= v << 16; \
+ COUNT_CYCLES(tms,6); \
+ break; \
+ case 3: \
+ v &= 0xff; \
+ v |= v << 8; \
+ v |= v << 16; \
+ COUNT_CYCLES(tms,5); \
+ break; \
+ case 4: \
+ v &= 0xffff; \
+ v |= v << 16; \
+ COUNT_CYCLES(tms,4); \
+ break; \
+ case 5: \
+ COUNT_CYCLES(tms,2); \
+ break; \
+ } \
+ R##REG(tms,DSTREG(op)) = v; \
+}
+
+static void rpix_a(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ RPIX(A);
+}
+
+static void rpix_b(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ RPIX(B);
+}
+
+static void setcdp(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:setcdp\n");
+}
+
+static void setcmp(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:setcmp\n");
+}
+
+static void setcsp(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:setcsp\n");
+}
+
+static void swapf_a(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:swapf_a\n");
+}
+
+static void swapf_b(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:swapf_b\n");
+}
+
+static void tfill_xy(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:tfill_xy\n");
+}
+
+static void trapl(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:trapl\n");
+}
+
+static void vblt_b_l(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:vblt_b_l\n");
+}
+
+static void vfill_l(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:vfill_l\n");
+}
+
+static void vlcol(tms34010_state *tms, UINT16 op)
+{
+ if (!tms->is_34020) { unimpl(tms, op); return; }
+ logerror("020:vlcol\n");
+}
diff --git a/trunk/src/emu/cpu/tms34010/34010ops.h b/trunk/src/emu/cpu/tms34010/34010ops.h
new file mode 100644
index 00000000000..14a81bf22e3
--- /dev/null
+++ b/trunk/src/emu/cpu/tms34010/34010ops.h
@@ -0,0 +1,157 @@
+/***************************************************************************
+
+ TMS34010: Portable Texas Instruments TMS34010 emulator
+
+ Copyright Alex Pasadyn/Zsolt Vasvari
+ Parts based on code by Aaron Giles
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __34010OPS_H__
+#define __34010OPS_H__
+
+
+/* Size of the memory buffer allocated for the shiftr register */
+#define SHIFTREG_SIZE (8 * 512 * sizeof(UINT16))
+
+
+
+/***************************************************************************
+ MEMORY I/O MACROS
+***************************************************************************/
+
+#define TMS34010_RDMEM(T,A) ((unsigned)(T)->program->read_byte (A))
+#define TMS34010_RDMEM_WORD(T,A) ((unsigned)(T)->program->read_word (A))
+INLINE UINT32 TMS34010_RDMEM_DWORD(tms34010_state *tms, offs_t A)
+{
+ UINT32 result = tms->program->read_word(A);
+ return result | (tms->program->read_word(A+2)<<16);
+}
+
+#define TMS34010_WRMEM(T,A,V) ((T)->program->write_byte(A,V))
+#define TMS34010_WRMEM_WORD(T,A,V) ((T)->program->write_word(A,V))
+INLINE void TMS34010_WRMEM_DWORD(tms34010_state *tms, offs_t A,UINT32 V)
+{
+ tms->program->write_word(A,V);
+ tms->program->write_word(A+2,V>>16);
+}
+
+
+
+/* IO registers accessor */
+#define IOREG(T,reg) ((T)->IOregs[reg])
+#define SMART_IOREG(T,reg) ((T)->IOregs[(T)->is_34020 ? (int)REG020_##reg : (int)REG_##reg])
+#define PBH(T) (IOREG(T, REG_CONTROL) & 0x0100)
+#define PBV(T) (IOREG(T, REG_CONTROL) & 0x0200)
+
+
+
+/***************************************************************************
+ FIELD WRITE MACROS
+***************************************************************************/
+
+#define WFIELDMAC(T,MASK,MAX) \
+ UINT32 shift = offset & 0x0f; \
+ UINT32 masked_data = data & (MASK); \
+ UINT32 old; \
+ \
+ offset = TOBYTE(offset & 0xfffffff0); \
+ \
+ if (shift >= MAX) \
+ { \
+ old = (UINT32)TMS34010_RDMEM_DWORD(T, offset) & ~((MASK) << shift); \
+ TMS34010_WRMEM_DWORD(T, offset, (masked_data << shift) | old); \
+ } \
+ else \
+ { \
+ old = (UINT32)TMS34010_RDMEM_WORD(T, offset) & ~((MASK) << shift); \
+ TMS34010_WRMEM_WORD(T, offset, ((masked_data & (MASK)) << shift) | old); \
+ } \
+
+#define WFIELDMAC_BIG(T,MASK,MAX) \
+ UINT32 shift = offset & 0x0f; \
+ UINT32 masked_data = data & (MASK); \
+ UINT32 old; \
+ \
+ offset = TOBYTE(offset & 0xfffffff0); \
+ \
+ old = (UINT32)TMS34010_RDMEM_DWORD(T, offset) & ~(UINT32)((MASK) << shift); \
+ TMS34010_WRMEM_DWORD(T, offset, (UINT32)(masked_data << shift) | old); \
+ if (shift >= MAX) \
+ { \
+ shift = 32 - shift; \
+ old = (UINT32)TMS34010_RDMEM_WORD(T, offset + 4) & ~((MASK) >> shift); \
+ TMS34010_WRMEM_WORD(T, offset, (masked_data >> shift) | old); \
+ } \
+
+#define WFIELDMAC_8(T) \
+ if (offset & 0x07) \
+ { \
+ WFIELDMAC(T,0xff,9); \
+ } \
+ else \
+ TMS34010_WRMEM(T, TOBYTE(offset), data); \
+
+#define RFIELDMAC_8(T) \
+ if (offset & 0x07) \
+ { \
+ RFIELDMAC(T,0xff,9); \
+ } \
+ else \
+ return TMS34010_RDMEM(T, TOBYTE(offset)); \
+
+#define WFIELDMAC_32(T) \
+ if (offset & 0x0f) \
+ { \
+ UINT32 shift = offset&0x0f; \
+ UINT32 old; \
+ UINT32 hiword; \
+ offset &= 0xfffffff0; \
+ old = ((UINT32) TMS34010_RDMEM_DWORD (T, TOBYTE(offset ))&(0xffffffff>>(0x20-shift))); \
+ hiword = ((UINT32) TMS34010_RDMEM_DWORD (T, TOBYTE(offset+0x20))&(0xffffffff<<shift)); \
+ TMS34010_WRMEM_DWORD(T, TOBYTE(offset ),(data<< shift) |old); \
+ TMS34010_WRMEM_DWORD(T, TOBYTE(offset+0x20),(data>>(0x20-shift))|hiword); \
+ } \
+ else \
+ TMS34010_WRMEM_DWORD(T, TOBYTE(offset),data); \
+
+
+
+/***************************************************************************
+ FIELD READ MACROS
+***************************************************************************/
+
+#define RFIELDMAC(T,MASK,MAX) \
+ UINT32 shift = offset & 0x0f; \
+ offset = TOBYTE(offset & 0xfffffff0); \
+ \
+ if (shift >= MAX) \
+ ret = (TMS34010_RDMEM_DWORD(T, offset) >> shift) & (MASK); \
+ else \
+ ret = (TMS34010_RDMEM_WORD(T, offset) >> shift) & (MASK); \
+
+#define RFIELDMAC_BIG(T,MASK,MAX) \
+ UINT32 shift = offset & 0x0f; \
+ offset = TOBYTE(offset & 0xfffffff0); \
+ \
+ ret = (UINT32)TMS34010_RDMEM_DWORD(T, offset) >> shift; \
+ if (shift >= MAX) \
+ ret |= (TMS34010_RDMEM_WORD(T, offset + 4) << (32 - shift)); \
+ ret &= MASK; \
+
+#define RFIELDMAC_32(T) \
+ if (offset&0x0f) \
+ { \
+ UINT32 shift = offset&0x0f; \
+ offset &= 0xfffffff0; \
+ return (((UINT32)TMS34010_RDMEM_DWORD (T, TOBYTE(offset ))>> shift) | \
+ (TMS34010_RDMEM_DWORD (T, TOBYTE(offset+0x20))<<(0x20-shift)));\
+ } \
+ else \
+ return TMS34010_RDMEM_DWORD(T, TOBYTE(offset)); \
+
+
+
+#endif /* __34010OPS_H__ */
diff --git a/trunk/src/emu/cpu/tms34010/34010tbl.c b/trunk/src/emu/cpu/tms34010/34010tbl.c
new file mode 100644
index 00000000000..05b7369d94f
--- /dev/null
+++ b/trunk/src/emu/cpu/tms34010/34010tbl.c
@@ -0,0 +1,1167 @@
+/*** TMS34010: Portable TMS34010 emulator ***********************************
+
+ Copyright Alex Pasadyn/Zsolt Vasvari
+
+ Opcode Table
+
+*****************************************************************************/
+
+static void unimpl(tms34010_state *tms, UINT16 op);
+
+/* Graphics Instructions */
+
+static void pixblt_l_l(tms34010_state *tms, UINT16 op); /* 0f00 */
+static void pixblt_l_xy(tms34010_state *tms, UINT16 op); /* 0f20 */
+static void pixblt_xy_l(tms34010_state *tms, UINT16 op); /* 0f40 */
+static void pixblt_xy_xy(tms34010_state *tms, UINT16 op); /* 0f60 */
+static void pixblt_b_l(tms34010_state *tms, UINT16 op); /* 0f80 */
+static void pixblt_b_xy(tms34010_state *tms, UINT16 op); /* 0fa0 */
+static void fill_l(tms34010_state *tms, UINT16 op); /* 0fc0 */
+static void fill_xy(tms34010_state *tms, UINT16 op); /* 0fe0 */
+static void line(tms34010_state *tms, UINT16 op); /* df10/df90 */
+static void add_xy_a(tms34010_state *tms, UINT16 op); /* e000/e100 */
+static void add_xy_b(tms34010_state *tms, UINT16 op); /* e000/e100 */
+static void sub_xy_a(tms34010_state *tms, UINT16 op); /* e200/e300 */
+static void sub_xy_b(tms34010_state *tms, UINT16 op); /* e200/e300 */
+static void cmp_xy_a(tms34010_state *tms, UINT16 op); /* e400/e500 */
+static void cmp_xy_b(tms34010_state *tms, UINT16 op); /* e400/e500 */
+static void cpw_a(tms34010_state *tms, UINT16 op); /* e600/e700 */
+static void cpw_b(tms34010_state *tms, UINT16 op); /* e600/e700 */
+static void cvxyl_a(tms34010_state *tms, UINT16 op); /* e800/e900 */
+static void cvxyl_b(tms34010_state *tms, UINT16 op); /* e800/e900 */
+static void movx_a(tms34010_state *tms, UINT16 op); /* ec00/ed00 */
+static void movx_b(tms34010_state *tms, UINT16 op); /* ec00/ed00 */
+static void movy_a(tms34010_state *tms, UINT16 op); /* ee00/ef00 */
+static void movy_b(tms34010_state *tms, UINT16 op); /* ee00/ef00 */
+static void pixt_ri_a(tms34010_state *tms, UINT16 op); /* f800/f900 */
+static void pixt_ri_b(tms34010_state *tms, UINT16 op); /* f800/f900 */
+static void pixt_rixy_a(tms34010_state *tms, UINT16 op); /* f000/f100 */
+static void pixt_rixy_b(tms34010_state *tms, UINT16 op); /* f000/f100 */
+static void pixt_ir_a(tms34010_state *tms, UINT16 op); /* fa00/fb00 */
+static void pixt_ir_b(tms34010_state *tms, UINT16 op); /* fa00/fb00 */
+static void pixt_ii_a(tms34010_state *tms, UINT16 op); /* fc00/fd00 */
+static void pixt_ii_b(tms34010_state *tms, UINT16 op); /* fc00/fd00 */
+static void pixt_ixyr_a(tms34010_state *tms, UINT16 op); /* f200/f300 */
+static void pixt_ixyr_b(tms34010_state *tms, UINT16 op); /* f200/f300 */
+static void pixt_ixyixy_a(tms34010_state *tms, UINT16 op); /* f400/f500 */
+static void pixt_ixyixy_b(tms34010_state *tms, UINT16 op); /* f400/f500 */
+static void drav_a(tms34010_state *tms, UINT16 op); /* f600/f700 */
+static void drav_b(tms34010_state *tms, UINT16 op); /* f600/f700 */
+
+/* General Instructions */
+static void abs_a(tms34010_state *tms, UINT16 op); /* 0380 */
+static void abs_b(tms34010_state *tms, UINT16 op); /* 0390 */
+static void add_a(tms34010_state *tms, UINT16 op); /* 4000/4100 */
+static void add_b(tms34010_state *tms, UINT16 op); /* 4000/4100 */
+static void addc_a(tms34010_state *tms, UINT16 op); /* 4200/4200 */
+static void addc_b(tms34010_state *tms, UINT16 op); /* 4200/4200 */
+static void addi_w_a(tms34010_state *tms, UINT16 op); /* 0b00 */
+static void addi_w_b(tms34010_state *tms, UINT16 op); /* 0b10 */
+static void addi_l_a(tms34010_state *tms, UINT16 op); /* 0b20 */
+static void addi_l_b(tms34010_state *tms, UINT16 op); /* 0b30 */
+static void addk_a(tms34010_state *tms, UINT16 op); /* 1000-1300 */
+static void addk_b(tms34010_state *tms, UINT16 op); /* 1000-1300 */
+static void and_a(tms34010_state *tms, UINT16 op); /* 5000/5100 */
+static void and_b(tms34010_state *tms, UINT16 op); /* 5000/5100 */
+static void andi_a(tms34010_state *tms, UINT16 op); /* 0b80 */
+static void andi_b(tms34010_state *tms, UINT16 op); /* 0b90 */
+static void andn_a(tms34010_state *tms, UINT16 op); /* 5200-5300 */
+static void andn_b(tms34010_state *tms, UINT16 op); /* 5200-5300 */
+static void btst_k_a(tms34010_state *tms, UINT16 op); /* 1c00-1f00 */
+static void btst_k_b(tms34010_state *tms, UINT16 op); /* 1c00-1f00 */
+static void btst_r_a(tms34010_state *tms, UINT16 op); /* 4a00-4b00 */
+static void btst_r_b(tms34010_state *tms, UINT16 op); /* 4a00-4b00 */
+static void clrc(tms34010_state *tms, UINT16 op); /* 0320 */
+static void cmp_a(tms34010_state *tms, UINT16 op); /* 4800/4900 */
+static void cmp_b(tms34010_state *tms, UINT16 op); /* 4800/4900 */
+static void cmpi_w_a(tms34010_state *tms, UINT16 op); /* 0b40 */
+static void cmpi_w_b(tms34010_state *tms, UINT16 op); /* 0b50 */
+static void cmpi_l_a(tms34010_state *tms, UINT16 op); /* 0b60 */
+static void cmpi_l_b(tms34010_state *tms, UINT16 op); /* 0b70 */
+static void dint(tms34010_state *tms, UINT16 op);
+static void divs_a(tms34010_state *tms, UINT16 op); /* 5800/5900 */
+static void divs_b(tms34010_state *tms, UINT16 op); /* 5800/5900 */
+static void divu_a(tms34010_state *tms, UINT16 op); /* 5a00/5b00 */
+static void divu_b(tms34010_state *tms, UINT16 op); /* 5a00/5b00 */
+static void eint(tms34010_state *tms, UINT16 op);
+static void exgf0_a(tms34010_state *tms, UINT16 op); /* d500 */
+static void exgf0_b(tms34010_state *tms, UINT16 op); /* d510 */
+static void exgf1_a(tms34010_state *tms, UINT16 op); /* d700 */
+static void exgf1_b(tms34010_state *tms, UINT16 op); /* d710 */
+static void lmo_a(tms34010_state *tms, UINT16 op); /* 6a00/6b00 */
+static void lmo_b(tms34010_state *tms, UINT16 op); /* 6a00/6b00 */
+static void mmfm_a(tms34010_state *tms, UINT16 op); /* 09a0 */
+static void mmfm_b(tms34010_state *tms, UINT16 op); /* 09b0 */
+static void mmtm_a(tms34010_state *tms, UINT16 op); /* 0980 */
+static void mmtm_b(tms34010_state *tms, UINT16 op); /* 0990 */
+static void mods_a(tms34010_state *tms, UINT16 op); /* 6c00/6d00 */
+static void mods_b(tms34010_state *tms, UINT16 op); /* 6c00/6d00 */
+static void modu_a(tms34010_state *tms, UINT16 op); /* 6e00/6f00 */
+static void modu_b(tms34010_state *tms, UINT16 op); /* 6e00/6f00 */
+static void mpys_a(tms34010_state *tms, UINT16 op); /* 5c00/5d00 */
+static void mpys_b(tms34010_state *tms, UINT16 op); /* 5c00/5d00 */
+static void mpyu_a(tms34010_state *tms, UINT16 op); /* 5e00/5e00 */
+static void mpyu_b(tms34010_state *tms, UINT16 op); /* 5e00/5f00 */
+static void neg_a(tms34010_state *tms, UINT16 op); /* 03a0 */
+static void neg_b(tms34010_state *tms, UINT16 op); /* 03b0 */
+static void negb_a(tms34010_state *tms, UINT16 op); /* 03c0 */
+static void negb_b(tms34010_state *tms, UINT16 op); /* 03d0 */
+static void nop(tms34010_state *tms, UINT16 op); /* 0300 */
+static void not_a(tms34010_state *tms, UINT16 op); /* 03e0 */
+static void not_b(tms34010_state *tms, UINT16 op); /* 03f0 */
+static void or_a(tms34010_state *tms, UINT16 op); /* 5400-5500 */
+static void or_b(tms34010_state *tms, UINT16 op); /* 5400-5500 */
+static void ori_a(tms34010_state *tms, UINT16 op); /* 0ba0 */
+static void ori_b(tms34010_state *tms, UINT16 op); /* 0bb0 */
+static void rl_k_a(tms34010_state *tms, UINT16 op); /* 3000-3300 */
+static void rl_k_b(tms34010_state *tms, UINT16 op); /* 3000-3300 */
+static void rl_r_a(tms34010_state *tms, UINT16 op); /* 6800/6900 */
+static void rl_r_b(tms34010_state *tms, UINT16 op); /* 6800/6900 */
+static void setc(tms34010_state *tms, UINT16 op); /* 0de0 */
+static void setf0(tms34010_state *tms, UINT16 op);
+static void setf1(tms34010_state *tms, UINT16 op);
+static void sext0_a(tms34010_state *tms, UINT16 op); /* 0500 */
+static void sext0_b(tms34010_state *tms, UINT16 op); /* 0510 */
+static void sext1_a(tms34010_state *tms, UINT16 op); /* 0700 */
+static void sext1_b(tms34010_state *tms, UINT16 op); /* 0710 */
+static void sla_k_a(tms34010_state *tms, UINT16 op); /* 2000-2300 */
+static void sla_k_b(tms34010_state *tms, UINT16 op); /* 2000-2300 */
+static void sla_r_a(tms34010_state *tms, UINT16 op); /* 6000/6100 */
+static void sla_r_b(tms34010_state *tms, UINT16 op); /* 6000/6100 */
+static void sll_k_a(tms34010_state *tms, UINT16 op); /* 2400-2700 */
+static void sll_k_b(tms34010_state *tms, UINT16 op); /* 2400-2700 */
+static void sll_r_a(tms34010_state *tms, UINT16 op); /* 6200/6300 */
+static void sll_r_b(tms34010_state *tms, UINT16 op); /* 6200/6300 */
+static void sra_k_a(tms34010_state *tms, UINT16 op); /* 2800-2b00 */
+static void sra_k_b(tms34010_state *tms, UINT16 op); /* 2800-2b00 */
+static void sra_r_a(tms34010_state *tms, UINT16 op); /* 6400/6500 */
+static void sra_r_b(tms34010_state *tms, UINT16 op); /* 6400/6500 */
+static void srl_k_a(tms34010_state *tms, UINT16 op); /* 2c00-2f00 */
+static void srl_k_b(tms34010_state *tms, UINT16 op); /* 2c00-2f00 */
+static void srl_r_a(tms34010_state *tms, UINT16 op); /* 6600/6700 */
+static void srl_r_b(tms34010_state *tms, UINT16 op); /* 6600/6700 */
+static void sub_a(tms34010_state *tms, UINT16 op); /* 4400/4500 */
+static void sub_b(tms34010_state *tms, UINT16 op); /* 4400/4500 */
+static void subb_a(tms34010_state *tms, UINT16 op); /* 4600/4700 */
+static void subb_b(tms34010_state *tms, UINT16 op); /* 4600/4700 */
+static void subi_w_a(tms34010_state *tms, UINT16 op); /* 0be0 */
+static void subi_w_b(tms34010_state *tms, UINT16 op); /* 0bf0 */
+static void subi_l_a(tms34010_state *tms, UINT16 op); /* 0d00 */
+static void subi_l_b(tms34010_state *tms, UINT16 op); /* 0d10 */
+static void subk_a(tms34010_state *tms, UINT16 op); /* 1400-1700 */
+static void subk_b(tms34010_state *tms, UINT16 op); /* 1400-1700 */
+static void xor_a(tms34010_state *tms, UINT16 op); /* 5600-5700 */
+static void xor_b(tms34010_state *tms, UINT16 op); /* 5600-5700 */
+static void xori_a(tms34010_state *tms, UINT16 op); /* 0bc0 */
+static void xori_b(tms34010_state *tms, UINT16 op); /* 0bd0 */
+static void zext0_a(tms34010_state *tms, UINT16 op); /* 0520 */
+static void zext0_b(tms34010_state *tms, UINT16 op); /* 0530 */
+static void zext1_a(tms34010_state *tms, UINT16 op); /* 0720 */
+static void zext1_b(tms34010_state *tms, UINT16 op); /* 0720 */
+
+
+/* Move Instructions */
+static void movi_w_a(tms34010_state *tms, UINT16 op);
+static void movi_w_b(tms34010_state *tms, UINT16 op);
+static void movi_l_a(tms34010_state *tms, UINT16 op);
+static void movi_l_b(tms34010_state *tms, UINT16 op);
+static void movk_a(tms34010_state *tms, UINT16 op);
+static void movk_b(tms34010_state *tms, UINT16 op);
+static void movb_rn_a(tms34010_state *tms, UINT16 op); /* 8c00-8d00 */
+static void movb_rn_b(tms34010_state *tms, UINT16 op); /* 8c00-8d00 */
+static void movb_nr_a(tms34010_state *tms, UINT16 op); /* 8e00-8f00 */
+static void movb_nr_b(tms34010_state *tms, UINT16 op); /* 8e00-8f00 */
+static void movb_nn_a(tms34010_state *tms, UINT16 op); /* 9c00-9d00 */
+static void movb_nn_b(tms34010_state *tms, UINT16 op); /* 9c00-9d00 */
+static void movb_r_no_a(tms34010_state *tms, UINT16 op); /* ac00-ad00 */
+static void movb_r_no_b(tms34010_state *tms, UINT16 op); /* ac00-ad00 */
+static void movb_no_r_a(tms34010_state *tms, UINT16 op); /* ae00-af00 */
+static void movb_no_r_b(tms34010_state *tms, UINT16 op); /* ae00-af00 */
+static void movb_no_no_a(tms34010_state *tms, UINT16 op); /* bc00-bd00 */
+static void movb_no_no_b(tms34010_state *tms, UINT16 op); /* bc00-bd00 */
+static void movb_ra_a(tms34010_state *tms, UINT16 op);
+static void movb_ra_b(tms34010_state *tms, UINT16 op);
+static void movb_ar_a(tms34010_state *tms, UINT16 op);
+static void movb_ar_b(tms34010_state *tms, UINT16 op);
+static void movb_aa(tms34010_state *tms, UINT16 op);
+static void move_rr_a(tms34010_state *tms, UINT16 op); /* 4c00/d00 */
+static void move_rr_b(tms34010_state *tms, UINT16 op); /* 4c00/d00 */
+static void move_rr_ax(tms34010_state *tms, UINT16 op); /* 4e00/f00 */
+static void move_rr_bx(tms34010_state *tms, UINT16 op); /* 4e00/f00 */
+static void move0_rn_a(tms34010_state *tms, UINT16 op); /* 8000 */
+static void move0_rn_b(tms34010_state *tms, UINT16 op);
+static void move1_rn_a(tms34010_state *tms, UINT16 op);
+static void move1_rn_b(tms34010_state *tms, UINT16 op);
+static void move0_r_dn_a(tms34010_state *tms, UINT16 op); /* a000 */
+static void move0_r_dn_b(tms34010_state *tms, UINT16 op);
+static void move1_r_dn_a(tms34010_state *tms, UINT16 op);
+static void move1_r_dn_b(tms34010_state *tms, UINT16 op);
+static void move0_r_ni_a(tms34010_state *tms, UINT16 op); /* 9000 */
+static void move0_r_ni_b(tms34010_state *tms, UINT16 op);
+static void move1_r_ni_a(tms34010_state *tms, UINT16 op);
+static void move1_r_ni_b(tms34010_state *tms, UINT16 op);
+static void move0_nr_a(tms34010_state *tms, UINT16 op); /* 8400-500 */
+static void move0_nr_b(tms34010_state *tms, UINT16 op); /* 8400-500 */
+static void move1_nr_a(tms34010_state *tms, UINT16 op); /* 8600-700 */
+static void move1_nr_b(tms34010_state *tms, UINT16 op); /* 8600-700 */
+static void move0_dn_r_a(tms34010_state *tms, UINT16 op); /* A400-500 */
+static void move0_dn_r_b(tms34010_state *tms, UINT16 op); /* A400-500 */
+static void move1_dn_r_a(tms34010_state *tms, UINT16 op); /* A600-700 */
+static void move1_dn_r_b(tms34010_state *tms, UINT16 op); /* A600-700 */
+static void move0_ni_r_a(tms34010_state *tms, UINT16 op); /* 9400-500 */
+static void move0_ni_r_b(tms34010_state *tms, UINT16 op); /* 9400-500 */
+static void move1_ni_r_a(tms34010_state *tms, UINT16 op); /* 9600-700 */
+static void move1_ni_r_b(tms34010_state *tms, UINT16 op); /* 9600-700 */
+static void move0_nn_a(tms34010_state *tms, UINT16 op); /* 8800 */
+static void move0_nn_b(tms34010_state *tms, UINT16 op);
+static void move1_nn_a(tms34010_state *tms, UINT16 op);
+static void move1_nn_b(tms34010_state *tms, UINT16 op);
+static void move0_dn_dn_a(tms34010_state *tms, UINT16 op); /* a800 */
+static void move0_dn_dn_b(tms34010_state *tms, UINT16 op);
+static void move1_dn_dn_a(tms34010_state *tms, UINT16 op);
+static void move1_dn_dn_b(tms34010_state *tms, UINT16 op);
+static void move0_ni_ni_a(tms34010_state *tms, UINT16 op); /* 9800 */
+static void move0_ni_ni_b(tms34010_state *tms, UINT16 op);
+static void move1_ni_ni_a(tms34010_state *tms, UINT16 op);
+static void move1_ni_ni_b(tms34010_state *tms, UINT16 op);
+static void move0_r_no_a(tms34010_state *tms, UINT16 op); /* b000 */
+static void move0_r_no_b(tms34010_state *tms, UINT16 op);
+static void move1_r_no_a(tms34010_state *tms, UINT16 op);
+static void move1_r_no_b(tms34010_state *tms, UINT16 op);
+static void move0_no_r_a(tms34010_state *tms, UINT16 op); /* b400 */
+static void move0_no_r_b(tms34010_state *tms, UINT16 op);
+static void move1_no_r_a(tms34010_state *tms, UINT16 op);
+static void move1_no_r_b(tms34010_state *tms, UINT16 op);
+static void move0_no_ni_a(tms34010_state *tms, UINT16 op); /* d000 */
+static void move0_no_ni_b(tms34010_state *tms, UINT16 op);
+static void move1_no_ni_a(tms34010_state *tms, UINT16 op);
+static void move1_no_ni_b(tms34010_state *tms, UINT16 op);
+static void move0_no_no_a(tms34010_state *tms, UINT16 op); /* b800 */
+static void move0_no_no_b(tms34010_state *tms, UINT16 op);
+static void move1_no_no_a(tms34010_state *tms, UINT16 op);
+static void move1_no_no_b(tms34010_state *tms, UINT16 op);
+static void move0_ra_a(tms34010_state *tms, UINT16 op);
+static void move0_ra_b(tms34010_state *tms, UINT16 op);
+static void move1_ra_a(tms34010_state *tms, UINT16 op);
+static void move1_ra_b(tms34010_state *tms, UINT16 op);
+static void move0_ar_a(tms34010_state *tms, UINT16 op);
+static void move0_ar_b(tms34010_state *tms, UINT16 op);
+static void move1_ar_a(tms34010_state *tms, UINT16 op);
+static void move1_ar_b(tms34010_state *tms, UINT16 op);
+static void move0_a_ni_a(tms34010_state *tms, UINT16 op); /* d400 */
+static void move0_a_ni_b(tms34010_state *tms, UINT16 op); /* d410 */
+static void move1_a_ni_a(tms34010_state *tms, UINT16 op); /* d600 */
+static void move1_a_ni_b(tms34010_state *tms, UINT16 op); /* d610 */
+static void move0_aa(tms34010_state *tms, UINT16 op); /* 05c0 */
+static void move1_aa(tms34010_state *tms, UINT16 op); /* 07c0 */
+
+
+/* Program Control and Context Switching */
+static void call_a(tms34010_state *tms, UINT16 op); /* 0920 */
+static void call_b(tms34010_state *tms, UINT16 op); /* 0930 */
+static void callr(tms34010_state *tms, UINT16 op); /* 0d3f */
+static void calla(tms34010_state *tms, UINT16 op); /* 0d5f */
+static void dsj_a(tms34010_state *tms, UINT16 op); /* 0d80 */
+static void dsj_b(tms34010_state *tms, UINT16 op); /* 0d90 */
+static void dsjeq_a(tms34010_state *tms, UINT16 op); /* 0da0 */
+static void dsjeq_b(tms34010_state *tms, UINT16 op); /* 0db0 */
+static void dsjne_a(tms34010_state *tms, UINT16 op); /* 0dc0 */
+static void dsjne_b(tms34010_state *tms, UINT16 op); /* 0dd0 */
+static void dsjs_a(tms34010_state *tms, UINT16 op);
+static void dsjs_b(tms34010_state *tms, UINT16 op);
+static void emu(tms34010_state *tms, UINT16 op); /* 0100 */
+static void exgpc_a(tms34010_state *tms, UINT16 op); /* 0120 */
+static void exgpc_b(tms34010_state *tms, UINT16 op); /* 0130 */
+static void getpc_a(tms34010_state *tms, UINT16 op); /* 0140 */
+static void getpc_b(tms34010_state *tms, UINT16 op); /* 0150 */
+static void getst_a(tms34010_state *tms, UINT16 op); /* 0180 */
+static void getst_b(tms34010_state *tms, UINT16 op); /* 0190 */
+static void j_UC_0(tms34010_state *tms, UINT16 op);
+static void j_UC_8(tms34010_state *tms, UINT16 op);
+static void j_UC_x(tms34010_state *tms, UINT16 op);
+static void j_P_0(tms34010_state *tms, UINT16 op);
+static void j_P_8(tms34010_state *tms, UINT16 op);
+static void j_P_x(tms34010_state *tms, UINT16 op);
+static void j_LS_0(tms34010_state *tms, UINT16 op);
+static void j_LS_8(tms34010_state *tms, UINT16 op);
+static void j_LS_x(tms34010_state *tms, UINT16 op);
+static void j_HI_0(tms34010_state *tms, UINT16 op);
+static void j_HI_8(tms34010_state *tms, UINT16 op);
+static void j_HI_x(tms34010_state *tms, UINT16 op);
+static void j_LT_0(tms34010_state *tms, UINT16 op);
+static void j_LT_8(tms34010_state *tms, UINT16 op);
+static void j_LT_x(tms34010_state *tms, UINT16 op);
+static void j_GE_0(tms34010_state *tms, UINT16 op);
+static void j_GE_8(tms34010_state *tms, UINT16 op);
+static void j_GE_x(tms34010_state *tms, UINT16 op);
+static void j_LE_0(tms34010_state *tms, UINT16 op);
+static void j_LE_8(tms34010_state *tms, UINT16 op);
+static void j_LE_x(tms34010_state *tms, UINT16 op);
+static void j_GT_0(tms34010_state *tms, UINT16 op);
+static void j_GT_8(tms34010_state *tms, UINT16 op);
+static void j_GT_x(tms34010_state *tms, UINT16 op);
+static void j_C_0(tms34010_state *tms, UINT16 op);
+static void j_C_8(tms34010_state *tms, UINT16 op);
+static void j_C_x(tms34010_state *tms, UINT16 op);
+static void j_NC_0(tms34010_state *tms, UINT16 op);
+static void j_NC_8(tms34010_state *tms, UINT16 op);
+static void j_NC_x(tms34010_state *tms, UINT16 op);
+static void j_EQ_0(tms34010_state *tms, UINT16 op);
+static void j_EQ_8(tms34010_state *tms, UINT16 op);
+static void j_EQ_x(tms34010_state *tms, UINT16 op);
+static void j_NE_0(tms34010_state *tms, UINT16 op);
+static void j_NE_8(tms34010_state *tms, UINT16 op);
+static void j_NE_x(tms34010_state *tms, UINT16 op);
+static void j_V_0(tms34010_state *tms, UINT16 op);
+static void j_V_8(tms34010_state *tms, UINT16 op);
+static void j_V_x(tms34010_state *tms, UINT16 op);
+static void j_NV_0(tms34010_state *tms, UINT16 op);
+static void j_NV_8(tms34010_state *tms, UINT16 op);
+static void j_NV_x(tms34010_state *tms, UINT16 op);
+static void j_N_0(tms34010_state *tms, UINT16 op);
+static void j_N_8(tms34010_state *tms, UINT16 op);
+static void j_N_x(tms34010_state *tms, UINT16 op);
+static void j_NN_0(tms34010_state *tms, UINT16 op);
+static void j_NN_8(tms34010_state *tms, UINT16 op);
+static void j_NN_x(tms34010_state *tms, UINT16 op);
+static void jump_a(tms34010_state *tms, UINT16 op); /* 0160 */
+static void jump_b(tms34010_state *tms, UINT16 op); /* 0170 */
+static void popst(tms34010_state *tms, UINT16 op); /* 01c0 */
+static void pushst(tms34010_state *tms, UINT16 op); /* 01e0 */
+static void putst_a(tms34010_state *tms, UINT16 op); /* 01a0 */
+static void putst_b(tms34010_state *tms, UINT16 op); /* 01b0 */
+static void reti(tms34010_state *tms, UINT16 op); /* 0940 */
+static void rets(tms34010_state *tms, UINT16 op); /* 0960/70 */
+static void rev_a(tms34010_state *tms, UINT16 op); /* 0020 */
+static void rev_b(tms34010_state *tms, UINT16 op); /* 0030 */
+static void trap(tms34010_state *tms, UINT16 op); /* 0900/10 */
+
+
+/* 34020 instructions */
+static void addxyi_a(tms34010_state *tms, UINT16 op);
+static void addxyi_b(tms34010_state *tms, UINT16 op);
+static void blmove(tms34010_state *tms, UINT16 op);
+static void cexec_l(tms34010_state *tms, UINT16 op);
+static void cexec_s(tms34010_state *tms, UINT16 op);
+static void clip(tms34010_state *tms, UINT16 op);
+static void cmovcg_a(tms34010_state *tms, UINT16 op);
+static void cmovcg_b(tms34010_state *tms, UINT16 op);
+static void cmovcm_f(tms34010_state *tms, UINT16 op);
+static void cmovcm_b(tms34010_state *tms, UINT16 op);
+static void cmovgc_a(tms34010_state *tms, UINT16 op);
+static void cmovgc_b(tms34010_state *tms, UINT16 op);
+static void cmovgc_a_s(tms34010_state *tms, UINT16 op);
+static void cmovgc_b_s(tms34010_state *tms, UINT16 op);
+static void cmovmc_f(tms34010_state *tms, UINT16 op);
+static void cmovmc_f_va(tms34010_state *tms, UINT16 op);
+static void cmovmc_f_vb(tms34010_state *tms, UINT16 op);
+static void cmovmc_b(tms34010_state *tms, UINT16 op);
+static void cmp_k_a(tms34010_state *tms, UINT16 op);
+static void cmp_k_b(tms34010_state *tms, UINT16 op);
+static void cvdxyl_a(tms34010_state *tms, UINT16 op);
+static void cvdxyl_b(tms34010_state *tms, UINT16 op);
+static void cvmxyl_a(tms34010_state *tms, UINT16 op);
+static void cvmxyl_b(tms34010_state *tms, UINT16 op);
+static void cvsxyl_a(tms34010_state *tms, UINT16 op);
+static void cvsxyl_b(tms34010_state *tms, UINT16 op);
+static void exgps_a(tms34010_state *tms, UINT16 op);
+static void exgps_b(tms34010_state *tms, UINT16 op);
+static void fline(tms34010_state *tms, UINT16 op);
+static void fpixeq(tms34010_state *tms, UINT16 op);
+static void fpixne(tms34010_state *tms, UINT16 op);
+static void getps_a(tms34010_state *tms, UINT16 op);
+static void getps_b(tms34010_state *tms, UINT16 op);
+static void idle(tms34010_state *tms, UINT16 op);
+static void linit(tms34010_state *tms, UINT16 op);
+static void mwait(tms34010_state *tms, UINT16 op);
+static void pfill_xy(tms34010_state *tms, UINT16 op);
+static void pixblt_l_m_l(tms34010_state *tms, UINT16 op);
+static void retm(tms34010_state *tms, UINT16 op);
+static void rmo_a(tms34010_state *tms, UINT16 op);
+static void rmo_b(tms34010_state *tms, UINT16 op);
+static void rpix_a(tms34010_state *tms, UINT16 op);
+static void rpix_b(tms34010_state *tms, UINT16 op);
+static void setcdp(tms34010_state *tms, UINT16 op);
+static void setcmp(tms34010_state *tms, UINT16 op);
+static void setcsp(tms34010_state *tms, UINT16 op);
+static void swapf_a(tms34010_state *tms, UINT16 op);
+static void swapf_b(tms34010_state *tms, UINT16 op);
+static void tfill_xy(tms34010_state *tms, UINT16 op);
+static void trapl(tms34010_state *tms, UINT16 op);
+static void vblt_b_l(tms34010_state *tms, UINT16 op);
+static void vfill_l(tms34010_state *tms, UINT16 op);
+static void vlcol(tms34010_state *tms, UINT16 op);
+
+
+/* Opcode Table */
+static void (*const opcode_table[65536 >> 4])(tms34010_state *tms, UINT16 op) =
+{
+ /* 0x0000 0x0010 0x0020 0x0030 ... 0x00f0 */
+ unimpl, unimpl, rev_a, rev_b, idle, unimpl, unimpl, unimpl,
+ mwait, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, blmove,
+ /* 0x0100 */
+ emu, unimpl, exgpc_a, exgpc_b, getpc_a, getpc_b, jump_a, jump_b,
+ getst_a, getst_b, putst_a, putst_b, popst, unimpl, pushst, unimpl,
+ /* 0x0200 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, setcsp, unimpl, setcdp,
+ rpix_a, rpix_b, exgps_a, exgps_b, getps_a, getps_b, unimpl, setcmp,
+ /* 0x0300 */
+ nop, unimpl, clrc, unimpl, movb_aa, unimpl, dint, unimpl,
+ abs_a, abs_b, neg_a, neg_b, negb_a, negb_b, not_a, not_b,
+ /* 0x0400 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0x0500 */
+ sext0_a, sext0_b, zext0_a, zext0_b, setf0, setf0, setf0, setf0,
+ move0_ra_a, move0_ra_b, move0_ar_a, move0_ar_b, move0_aa, unimpl, movb_ra_a, movb_ra_b,
+ /* 0x0600 */
+ cexec_l, unimpl, cmovgc_a, cmovgc_b, cmovgc_a_s, cmovgc_b_s, cmovcg_a, cmovcg_b,
+ cmovmc_f, cmovmc_f, cmovcm_f, cmovcm_f, cmovcm_b, cmovcm_b, cmovmc_f_va,cmovmc_f_vb,
+ /* 0x0700 */
+ sext1_a, sext1_b, zext1_a, zext1_b, setf1, setf1, setf1, setf1,
+ move1_ra_a, move1_ra_b, move1_ar_a, move1_ar_b, move1_aa, unimpl, movb_ar_a, movb_ar_b,
+ /* 0x0800 */
+ trapl, unimpl, cmovmc_b, cmovmc_b, unimpl, vblt_b_l, retm, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, clip,
+ /* 0x0900 */
+ trap, trap, call_a, call_b, reti, unimpl, rets, rets,
+ mmtm_a, mmtm_b, mmfm_a, mmfm_b, movi_w_a, movi_w_b, movi_l_a, movi_l_b,
+ /* 0x0a00 */
+ vlcol, unimpl, unimpl, pfill_xy, unimpl, vfill_l, cvmxyl_a, cvmxyl_b,
+ cvdxyl_a, cvdxyl_b, unimpl, fpixeq, unimpl, fpixne, unimpl, unimpl,
+ /* 0x0b00 */
+ addi_w_a, addi_w_b, addi_l_a, addi_l_b, cmpi_w_a, cmpi_w_b, cmpi_l_a, cmpi_l_b,
+ andi_a, andi_b, ori_a, ori_b, xori_a, xori_b, subi_w_a, subi_w_b,
+ /* 0x0c00 */
+ addxyi_a, addxyi_b, unimpl, unimpl, unimpl, linit, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0x0d00 */
+ subi_l_a, subi_l_b, unimpl, callr, unimpl, calla, eint, unimpl,
+ dsj_a, dsj_b, dsjeq_a, dsjeq_b, dsjne_a, dsjne_b, setc, unimpl,
+ /* 0x0e00 */
+ unimpl, pixblt_l_m_l,unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, tfill_xy,
+ /* 0x0f00 */
+ pixblt_l_l, unimpl, pixblt_l_xy,unimpl, pixblt_xy_l,unimpl, pixblt_xy_xy,unimpl,
+ pixblt_b_l, unimpl, pixblt_b_xy,unimpl, fill_l, unimpl, fill_xy, unimpl,
+ /* 0x1000 */
+ addk_a, addk_b, addk_a, addk_b, addk_a, addk_b, addk_a, addk_b,
+ addk_a, addk_b, addk_a, addk_b, addk_a, addk_b, addk_a, addk_b,
+ /* 0x1100 */
+ addk_a, addk_b, addk_a, addk_b, addk_a, addk_b, addk_a, addk_b,
+ addk_a, addk_b, addk_a, addk_b, addk_a, addk_b, addk_a, addk_b,
+ /* 0x1200 */
+ addk_a, addk_b, addk_a, addk_b, addk_a, addk_b, addk_a, addk_b,
+ addk_a, addk_b, addk_a, addk_b, addk_a, addk_b, addk_a, addk_b,
+ /* 0x1300 */
+ addk_a, addk_b, addk_a, addk_b, addk_a, addk_b, addk_a, addk_b,
+ addk_a, addk_b, addk_a, addk_b, addk_a, addk_b, addk_a, addk_b,
+ /* 0x1400 */
+ subk_a, subk_b, subk_a, subk_b, subk_a, subk_b, subk_a, subk_b,
+ subk_a, subk_b, subk_a, subk_b, subk_a, subk_b, subk_a, subk_b,
+ /* 0x1500 */
+ subk_a, subk_b, subk_a, subk_b, subk_a, subk_b, subk_a, subk_b,
+ subk_a, subk_b, subk_a, subk_b, subk_a, subk_b, subk_a, subk_b,
+ /* 0x1600 */
+ subk_a, subk_b, subk_a, subk_b, subk_a, subk_b, subk_a, subk_b,
+ subk_a, subk_b, subk_a, subk_b, subk_a, subk_b, subk_a, subk_b,
+ /* 0x1700 */
+ subk_a, subk_b, subk_a, subk_b, subk_a, subk_b, subk_a, subk_b,
+ subk_a, subk_b, subk_a, subk_b, subk_a, subk_b, subk_a, subk_b,
+ /* 0x1800 */
+ movk_a, movk_b, movk_a, movk_b, movk_a, movk_b, movk_a, movk_b,
+ movk_a, movk_b, movk_a, movk_b, movk_a, movk_b, movk_a, movk_b,
+ /* 0x1900 */
+ movk_a, movk_b, movk_a, movk_b, movk_a, movk_b, movk_a, movk_b,
+ movk_a, movk_b, movk_a, movk_b, movk_a, movk_b, movk_a, movk_b,
+ /* 0x1a00 */
+ movk_a, movk_b, movk_a, movk_b, movk_a, movk_b, movk_a, movk_b,
+ movk_a, movk_b, movk_a, movk_b, movk_a, movk_b, movk_a, movk_b,
+ /* 0x1b00 */
+ movk_a, movk_b, movk_a, movk_b, movk_a, movk_b, movk_a, movk_b,
+ movk_a, movk_b, movk_a, movk_b, movk_a, movk_b, movk_a, movk_b,
+ /* 0x1c00 */
+ btst_k_a, btst_k_b, btst_k_a, btst_k_b, btst_k_a, btst_k_b, btst_k_a, btst_k_b,
+ btst_k_a, btst_k_b, btst_k_a, btst_k_b, btst_k_a, btst_k_b, btst_k_a, btst_k_b,
+ /* 0x1d00 */
+ btst_k_a, btst_k_b, btst_k_a, btst_k_b, btst_k_a, btst_k_b, btst_k_a, btst_k_b,
+ btst_k_a, btst_k_b, btst_k_a, btst_k_b, btst_k_a, btst_k_b, btst_k_a, btst_k_b,
+ /* 0x1e00 */
+ btst_k_a, btst_k_b, btst_k_a, btst_k_b, btst_k_a, btst_k_b, btst_k_a, btst_k_b,
+ btst_k_a, btst_k_b, btst_k_a, btst_k_b, btst_k_a, btst_k_b, btst_k_a, btst_k_b,
+ /* 0x1f00 */
+ btst_k_a, btst_k_b, btst_k_a, btst_k_b, btst_k_a, btst_k_b, btst_k_a, btst_k_b,
+ btst_k_a, btst_k_b, btst_k_a, btst_k_b, btst_k_a, btst_k_b, btst_k_a, btst_k_b,
+ /* 0x2000 */
+ sla_k_a, sla_k_b, sla_k_a, sla_k_b, sla_k_a, sla_k_b, sla_k_a, sla_k_b,
+ sla_k_a, sla_k_b, sla_k_a, sla_k_b, sla_k_a, sla_k_b, sla_k_a, sla_k_b,
+ /* 0x2100 */
+ sla_k_a, sla_k_b, sla_k_a, sla_k_b, sla_k_a, sla_k_b, sla_k_a, sla_k_b,
+ sla_k_a, sla_k_b, sla_k_a, sla_k_b, sla_k_a, sla_k_b, sla_k_a, sla_k_b,
+ /* 0x2200 */
+ sla_k_a, sla_k_b, sla_k_a, sla_k_b, sla_k_a, sla_k_b, sla_k_a, sla_k_b,
+ sla_k_a, sla_k_b, sla_k_a, sla_k_b, sla_k_a, sla_k_b, sla_k_a, sla_k_b,
+ /* 0x2300 */
+ sla_k_a, sla_k_b, sla_k_a, sla_k_b, sla_k_a, sla_k_b, sla_k_a, sla_k_b,
+ sla_k_a, sla_k_b, sla_k_a, sla_k_b, sla_k_a, sla_k_b, sla_k_a, sla_k_b,
+ /* 0x2400 */
+ sll_k_a, sll_k_b, sll_k_a, sll_k_b, sll_k_a, sll_k_b, sll_k_a, sll_k_b,
+ sll_k_a, sll_k_b, sll_k_a, sll_k_b, sll_k_a, sll_k_b, sll_k_a, sll_k_b,
+ /* 0x2500 */
+ sll_k_a, sll_k_b, sll_k_a, sll_k_b, sll_k_a, sll_k_b, sll_k_a, sll_k_b,
+ sll_k_a, sll_k_b, sll_k_a, sll_k_b, sll_k_a, sll_k_b, sll_k_a, sll_k_b,
+ /* 0x2600 */
+ sll_k_a, sll_k_b, sll_k_a, sll_k_b, sll_k_a, sll_k_b, sll_k_a, sll_k_b,
+ sll_k_a, sll_k_b, sll_k_a, sll_k_b, sll_k_a, sll_k_b, sll_k_a, sll_k_b,
+ /* 0x2700 */
+ sll_k_a, sll_k_b, sll_k_a, sll_k_b, sll_k_a, sll_k_b, sll_k_a, sll_k_b,
+ sll_k_a, sll_k_b, sll_k_a, sll_k_b, sll_k_a, sll_k_b, sll_k_a, sll_k_b,
+ /* 0x2800 */
+ sra_k_a, sra_k_b, sra_k_a, sra_k_b, sra_k_a, sra_k_b, sra_k_a, sra_k_b,
+ sra_k_a, sra_k_b, sra_k_a, sra_k_b, sra_k_a, sra_k_b, sra_k_a, sra_k_b,
+ /* 0x2900 */
+ sra_k_a, sra_k_b, sra_k_a, sra_k_b, sra_k_a, sra_k_b, sra_k_a, sra_k_b,
+ sra_k_a, sra_k_b, sra_k_a, sra_k_b, sra_k_a, sra_k_b, sra_k_a, sra_k_b,
+ /* 0x2a00 */
+ sra_k_a, sra_k_b, sra_k_a, sra_k_b, sra_k_a, sra_k_b, sra_k_a, sra_k_b,
+ sra_k_a, sra_k_b, sra_k_a, sra_k_b, sra_k_a, sra_k_b, sra_k_a, sra_k_b,
+ /* 0x2b00 */
+ sra_k_a, sra_k_b, sra_k_a, sra_k_b, sra_k_a, sra_k_b, sra_k_a, sra_k_b,
+ sra_k_a, sra_k_b, sra_k_a, sra_k_b, sra_k_a, sra_k_b, sra_k_a, sra_k_b,
+ /* 0x2c00 */
+ srl_k_a, srl_k_b, srl_k_a, srl_k_b, srl_k_a, srl_k_b, srl_k_a, srl_k_b,
+ srl_k_a, srl_k_b, srl_k_a, srl_k_b, srl_k_a, srl_k_b, srl_k_a, srl_k_b,
+ /* 0x2d00 */
+ srl_k_a, srl_k_b, srl_k_a, srl_k_b, srl_k_a, srl_k_b, srl_k_a, srl_k_b,
+ srl_k_a, srl_k_b, srl_k_a, srl_k_b, srl_k_a, srl_k_b, srl_k_a, srl_k_b,
+ /* 0x2e00 */
+ srl_k_a, srl_k_b, srl_k_a, srl_k_b, srl_k_a, srl_k_b, srl_k_a, srl_k_b,
+ srl_k_a, srl_k_b, srl_k_a, srl_k_b, srl_k_a, srl_k_b, srl_k_a, srl_k_b,
+ /* 0x2f00 */
+ srl_k_a, srl_k_b, srl_k_a, srl_k_b, srl_k_a, srl_k_b, srl_k_a, srl_k_b,
+ srl_k_a, srl_k_b, srl_k_a, srl_k_b, srl_k_a, srl_k_b, srl_k_a, srl_k_b,
+ /* 0x3000 */
+ rl_k_a, rl_k_b, rl_k_a, rl_k_b, rl_k_a, rl_k_b, rl_k_a, rl_k_b,
+ rl_k_a, rl_k_b, rl_k_a, rl_k_b, rl_k_a, rl_k_b, rl_k_a, rl_k_b,
+ /* 0x3100 */
+ rl_k_a, rl_k_b, rl_k_a, rl_k_b, rl_k_a, rl_k_b, rl_k_a, rl_k_b,
+ rl_k_a, rl_k_b, rl_k_a, rl_k_b, rl_k_a, rl_k_b, rl_k_a, rl_k_b,
+ /* 0x3200 */
+ rl_k_a, rl_k_b, rl_k_a, rl_k_b, rl_k_a, rl_k_b, rl_k_a, rl_k_b,
+ rl_k_a, rl_k_b, rl_k_a, rl_k_b, rl_k_a, rl_k_b, rl_k_a, rl_k_b,
+ /* 0x3300 */
+ rl_k_a, rl_k_b, rl_k_a, rl_k_b, rl_k_a, rl_k_b, rl_k_a, rl_k_b,
+ rl_k_a, rl_k_b, rl_k_a, rl_k_b, rl_k_a, rl_k_b, rl_k_a, rl_k_b,
+ /* 0x3400 */
+ cmp_k_a, cmp_k_b, cmp_k_a, cmp_k_b, cmp_k_a, cmp_k_b, cmp_k_a, cmp_k_b,
+ cmp_k_a, cmp_k_b, cmp_k_a, cmp_k_b, cmp_k_a, cmp_k_b, cmp_k_a, cmp_k_b,
+ /* 0x3500 */
+ cmp_k_a, cmp_k_b, cmp_k_a, cmp_k_b, cmp_k_a, cmp_k_b, cmp_k_a, cmp_k_b,
+ cmp_k_a, cmp_k_b, cmp_k_a, cmp_k_b, cmp_k_a, cmp_k_b, cmp_k_a, cmp_k_b,
+ /* 0x3600 */
+ cmp_k_a, cmp_k_b, cmp_k_a, cmp_k_b, cmp_k_a, cmp_k_b, cmp_k_a, cmp_k_b,
+ cmp_k_a, cmp_k_b, cmp_k_a, cmp_k_b, cmp_k_a, cmp_k_b, cmp_k_a, cmp_k_b,
+ /* 0x3700 */
+ cmp_k_a, cmp_k_b, cmp_k_a, cmp_k_b, cmp_k_a, cmp_k_b, cmp_k_a, cmp_k_b,
+ cmp_k_a, cmp_k_b, cmp_k_a, cmp_k_b, cmp_k_a, cmp_k_b, cmp_k_a, cmp_k_b,
+ /* 0x3800 */
+ dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b,
+ dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b,
+ /* 0x3900 */
+ dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b,
+ dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b,
+ /* 0x3a00 */
+ dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b,
+ dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b,
+ /* 0x3b00 */
+ dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b,
+ dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b,
+ /* 0x3c00 */
+ dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b,
+ dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b,
+ /* 0x3d00 */
+ dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b,
+ dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b,
+ /* 0x3e00 */
+ dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b,
+ dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b,
+ /* 0x3f00 */
+ dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b,
+ dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b, dsjs_a, dsjs_b,
+ /* 0x4000 */
+ add_a, add_b, add_a, add_b, add_a, add_b, add_a, add_b,
+ add_a, add_b, add_a, add_b, add_a, add_b, add_a, add_b,
+ /* 0x4100 */
+ add_a, add_b, add_a, add_b, add_a, add_b, add_a, add_b,
+ add_a, add_b, add_a, add_b, add_a, add_b, add_a, add_b,
+ /* 0x4200 */
+ addc_a, addc_b, addc_a, addc_b, addc_a, addc_b, addc_a, addc_b,
+ addc_a, addc_b, addc_a, addc_b, addc_a, addc_b, addc_a, addc_b,
+ /* 0x4300 */
+ addc_a, addc_b, addc_a, addc_b, addc_a, addc_b, addc_a, addc_b,
+ addc_a, addc_b, addc_a, addc_b, addc_a, addc_b, addc_a, addc_b,
+ /* 0x4400 */
+ sub_a, sub_b, sub_a, sub_b, sub_a, sub_b, sub_a, sub_b,
+ sub_a, sub_b, sub_a, sub_b, sub_a, sub_b, sub_a, sub_b,
+ /* 0x4500 */
+ sub_a, sub_b, sub_a, sub_b, sub_a, sub_b, sub_a, sub_b,
+ sub_a, sub_b, sub_a, sub_b, sub_a, sub_b, sub_a, sub_b,
+ /* 0x4600 */
+ subb_a, subb_b, subb_a, subb_b, subb_a, subb_b, subb_a, subb_b,
+ subb_a, subb_b, subb_a, subb_b, subb_a, subb_b, subb_a, subb_b,
+ /* 0x4700 */
+ subb_a, subb_b, subb_a, subb_b, subb_a, subb_b, subb_a, subb_b,
+ subb_a, subb_b, subb_a, subb_b, subb_a, subb_b, subb_a, subb_b,
+ /* 0x4800 */
+ cmp_a, cmp_b, cmp_a, cmp_b, cmp_a, cmp_b, cmp_a, cmp_b,
+ cmp_a, cmp_b, cmp_a, cmp_b, cmp_a, cmp_b, cmp_a, cmp_b,
+ /* 0x4900 */
+ cmp_a, cmp_b, cmp_a, cmp_b, cmp_a, cmp_b, cmp_a, cmp_b,
+ cmp_a, cmp_b, cmp_a, cmp_b, cmp_a, cmp_b, cmp_a, cmp_b,
+ /* 0x4a00 */
+ btst_r_a, btst_r_b, btst_r_a, btst_r_b, btst_r_a, btst_r_b, btst_r_a, btst_r_b,
+ btst_r_a, btst_r_b, btst_r_a, btst_r_b, btst_r_a, btst_r_b, btst_r_a, btst_r_b,
+ /* 0x4b00 */
+ btst_r_a, btst_r_b, btst_r_a, btst_r_b, btst_r_a, btst_r_b, btst_r_a, btst_r_b,
+ btst_r_a, btst_r_b, btst_r_a, btst_r_b, btst_r_a, btst_r_b, btst_r_a, btst_r_b,
+ /* 0x4c00 */
+ move_rr_a, move_rr_b, move_rr_a, move_rr_b, move_rr_a, move_rr_b, move_rr_a, move_rr_b,
+ move_rr_a, move_rr_b, move_rr_a, move_rr_b, move_rr_a, move_rr_b, move_rr_a, move_rr_b,
+ /* 0x4d00 */
+ move_rr_a, move_rr_b, move_rr_a, move_rr_b, move_rr_a, move_rr_b, move_rr_a, move_rr_b,
+ move_rr_a, move_rr_b, move_rr_a, move_rr_b, move_rr_a, move_rr_b, move_rr_a, move_rr_b,
+ /* 0x4e00 */
+ move_rr_ax, move_rr_bx, move_rr_ax, move_rr_bx, move_rr_ax, move_rr_bx, move_rr_ax, move_rr_bx,
+ move_rr_ax, move_rr_bx, move_rr_ax, move_rr_bx, move_rr_ax, move_rr_bx, move_rr_ax, move_rr_bx,
+ /* 0x4f00 */
+ move_rr_ax, move_rr_bx, move_rr_ax, move_rr_bx, move_rr_ax, move_rr_bx, move_rr_ax, move_rr_bx,
+ move_rr_ax, move_rr_bx, move_rr_ax, move_rr_bx, move_rr_ax, move_rr_bx, move_rr_ax, move_rr_bx,
+ /* 0x5000 */
+ and_a, and_b, and_a, and_b, and_a, and_b, and_a, and_b,
+ and_a, and_b, and_a, and_b, and_a, and_b, and_a, and_b,
+ /* 0x5100 */
+ and_a, and_b, and_a, and_b, and_a, and_b, and_a, and_b,
+ and_a, and_b, and_a, and_b, and_a, and_b, and_a, and_b,
+ /* 0x5200 */
+ andn_a, andn_b, andn_a, andn_b, andn_a, andn_b, andn_a, andn_b,
+ andn_a, andn_b, andn_a, andn_b, andn_a, andn_b, andn_a, andn_b,
+ /* 0x5300 */
+ andn_a, andn_b, andn_a, andn_b, andn_a, andn_b, andn_a, andn_b,
+ andn_a, andn_b, andn_a, andn_b, andn_a, andn_b, andn_a, andn_b,
+ /* 0x5400 */
+ or_a, or_b, or_a, or_b, or_a, or_b, or_a, or_b,
+ or_a, or_b, or_a, or_b, or_a, or_b, or_a, or_b,
+ /* 0x5500 */
+ or_a, or_b, or_a, or_b, or_a, or_b, or_a, or_b,
+ or_a, or_b, or_a, or_b, or_a, or_b, or_a, or_b,
+ /* 0x5600 */
+ xor_a, xor_b, xor_a, xor_b, xor_a, xor_b, xor_a, xor_b,
+ xor_a, xor_b, xor_a, xor_b, xor_a, xor_b, xor_a, xor_b,
+ /* 0x5700 */
+ xor_a, xor_b, xor_a, xor_b, xor_a, xor_b, xor_a, xor_b,
+ xor_a, xor_b, xor_a, xor_b, xor_a, xor_b, xor_a, xor_b,
+ /* 0x5800 */
+ divs_a, divs_b, divs_a, divs_b, divs_a, divs_b, divs_a, divs_b,
+ divs_a, divs_b, divs_a, divs_b, divs_a, divs_b, divs_a, divs_b,
+ /* 0x5900 */
+ divs_a, divs_b, divs_a, divs_b, divs_a, divs_b, divs_a, divs_b,
+ divs_a, divs_b, divs_a, divs_b, divs_a, divs_b, divs_a, divs_b,
+ /* 0x5a00 */
+ divu_a, divu_b, divu_a, divu_b, divu_a, divu_b, divu_a, divu_b,
+ divu_a, divu_b, divu_a, divu_b, divu_a, divu_b, divu_a, divu_b,
+ /* 0x5b00 */
+ divu_a, divu_b, divu_a, divu_b, divu_a, divu_b, divu_a, divu_b,
+ divu_a, divu_b, divu_a, divu_b, divu_a, divu_b, divu_a, divu_b,
+ /* 0x5c00 */
+ mpys_a, mpys_b, mpys_a, mpys_b, mpys_a, mpys_b, mpys_a, mpys_b,
+ mpys_a, mpys_b, mpys_a, mpys_b, mpys_a, mpys_b, mpys_a, mpys_b,
+ /* 0x5d00 */
+ mpys_a, mpys_b, mpys_a, mpys_b, mpys_a, mpys_b, mpys_a, mpys_b,
+ mpys_a, mpys_b, mpys_a, mpys_b, mpys_a, mpys_b, mpys_a, mpys_b,
+ /* 0x5e00 */
+ mpyu_a, mpyu_b, mpyu_a, mpyu_b, mpyu_a, mpyu_b, mpyu_a, mpyu_b,
+ mpyu_a, mpyu_b, mpyu_a, mpyu_b, mpyu_a, mpyu_b, mpyu_a, mpyu_b,
+ /* 0x5f00 */
+ mpyu_a, mpyu_b, mpyu_a, mpyu_b, mpyu_a, mpyu_b, mpyu_a, mpyu_b,
+ mpyu_a, mpyu_b, mpyu_a, mpyu_b, mpyu_a, mpyu_b, mpyu_a, mpyu_b,
+ /* 0x6000 */
+ sla_r_a, sla_r_b, sla_r_a, sla_r_b, sla_r_a, sla_r_b, sla_r_a, sla_r_b,
+ sla_r_a, sla_r_b, sla_r_a, sla_r_b, sla_r_a, sla_r_b, sla_r_a, sla_r_b,
+ /* 0x6100 */
+ sla_r_a, sla_r_b, sla_r_a, sla_r_b, sla_r_a, sla_r_b, sla_r_a, sla_r_b,
+ sla_r_a, sla_r_b, sla_r_a, sla_r_b, sla_r_a, sla_r_b, sla_r_a, sla_r_b,
+ /* 0x6200 */
+ sll_r_a, sll_r_b, sll_r_a, sll_r_b, sll_r_a, sll_r_b, sll_r_a, sll_r_b,
+ sll_r_a, sll_r_b, sll_r_a, sll_r_b, sll_r_a, sll_r_b, sll_r_a, sll_r_b,
+ /* 0x6300 */
+ sll_r_a, sll_r_b, sll_r_a, sll_r_b, sll_r_a, sll_r_b, sll_r_a, sll_r_b,
+ sll_r_a, sll_r_b, sll_r_a, sll_r_b, sll_r_a, sll_r_b, sll_r_a, sll_r_b,
+ /* 0x6400 */
+ sra_r_a, sra_r_b, sra_r_a, sra_r_b, sra_r_a, sra_r_b, sra_r_a, sra_r_b,
+ sra_r_a, sra_r_b, sra_r_a, sra_r_b, sra_r_a, sra_r_b, sra_r_a, sra_r_b,
+ /* 0x6500 */
+ sra_r_a, sra_r_b, sra_r_a, sra_r_b, sra_r_a, sra_r_b, sra_r_a, sra_r_b,
+ sra_r_a, sra_r_b, sra_r_a, sra_r_b, sra_r_a, sra_r_b, sra_r_a, sra_r_b,
+ /* 0x6600 */
+ srl_r_a, srl_r_b, srl_r_a, srl_r_b, srl_r_a, srl_r_b, srl_r_a, srl_r_b,
+ srl_r_a, srl_r_b, srl_r_a, srl_r_b, srl_r_a, srl_r_b, srl_r_a, srl_r_b,
+ /* 0x6700 */
+ srl_r_a, srl_r_b, srl_r_a, srl_r_b, srl_r_a, srl_r_b, srl_r_a, srl_r_b,
+ srl_r_a, srl_r_b, srl_r_a, srl_r_b, srl_r_a, srl_r_b, srl_r_a, srl_r_b,
+ /* 0x6800 */
+ rl_r_a, rl_r_b, rl_r_a, rl_r_b, rl_r_a, rl_r_b, rl_r_a, rl_r_b,
+ rl_r_a, rl_r_b, rl_r_a, rl_r_b, rl_r_a, rl_r_b, rl_r_a, rl_r_b,
+ /* 0x6900 */
+ rl_r_a, rl_r_b, rl_r_a, rl_r_b, rl_r_a, rl_r_b, rl_r_a, rl_r_b,
+ rl_r_a, rl_r_b, rl_r_a, rl_r_b, rl_r_a, rl_r_b, rl_r_a, rl_r_b,
+ /* 0x6a00 */
+ lmo_a, lmo_b, lmo_a, lmo_b, lmo_a, lmo_b, lmo_a, lmo_b,
+ lmo_a, lmo_b, lmo_a, lmo_b, lmo_a, lmo_b, lmo_a, lmo_b,
+ /* 0x6b00 */
+ lmo_a, lmo_b, lmo_a, lmo_b, lmo_a, lmo_b, lmo_a, lmo_b,
+ lmo_a, lmo_b, lmo_a, lmo_b, lmo_a, lmo_b, lmo_a, lmo_b,
+ /* 0x6c00 */
+ mods_a, mods_b, mods_a, mods_b, mods_a, mods_b, mods_a, mods_b,
+ mods_a, mods_b, mods_a, mods_b, mods_a, mods_b, mods_a, mods_b,
+ /* 0x6d00 */
+ mods_a, mods_b, mods_a, mods_b, mods_a, mods_b, mods_a, mods_b,
+ mods_a, mods_b, mods_a, mods_b, mods_a, mods_b, mods_a, mods_b,
+ /* 0x6e00 */
+ modu_a, modu_b, modu_a, modu_b, modu_a, modu_b, modu_a, modu_b,
+ modu_a, modu_b, modu_a, modu_b, modu_a, modu_b, modu_a, modu_b,
+ /* 0x6f00 */
+ modu_a, modu_b, modu_a, modu_b, modu_a, modu_b, modu_a, modu_b,
+ modu_a, modu_b, modu_a, modu_b, modu_a, modu_b, modu_a, modu_b,
+ /* 0x7000 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0x7100 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0x7200 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0x7300 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0x7400 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0x7500 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0x7600 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0x7700 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0x7800 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0x7900 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0x7a00 */
+ rmo_a, rmo_b, rmo_a, rmo_b, rmo_a, rmo_b, rmo_a, rmo_b,
+ rmo_a, rmo_b, rmo_a, rmo_b, rmo_a, rmo_b, rmo_a, rmo_b,
+ /* 0x7b00 */
+ rmo_a, rmo_b, rmo_a, rmo_b, rmo_a, rmo_b, rmo_a, rmo_b,
+ rmo_a, rmo_b, rmo_a, rmo_b, rmo_a, rmo_b, rmo_a, rmo_b,
+ /* 0x7c00 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0x7d00 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0x7e00 */
+ swapf_a, swapf_b, swapf_a, swapf_b, swapf_a, swapf_b, swapf_a, swapf_b,
+ swapf_a, swapf_b, swapf_a, swapf_b, swapf_a, swapf_b, swapf_a, swapf_b,
+ /* 0x7f00 */
+ swapf_a, swapf_b, swapf_a, swapf_b, swapf_a, swapf_b, swapf_a, swapf_b,
+ swapf_a, swapf_b, swapf_a, swapf_b, swapf_a, swapf_b, swapf_a, swapf_b,
+ /* 0x8000 */
+ move0_rn_a, move0_rn_b, move0_rn_a, move0_rn_b, move0_rn_a, move0_rn_b, move0_rn_a, move0_rn_b,
+ move0_rn_a, move0_rn_b, move0_rn_a, move0_rn_b, move0_rn_a, move0_rn_b, move0_rn_a, move0_rn_b,
+ /* 0x8100 */
+ move0_rn_a, move0_rn_b, move0_rn_a, move0_rn_b, move0_rn_a, move0_rn_b, move0_rn_a, move0_rn_b,
+ move0_rn_a, move0_rn_b, move0_rn_a, move0_rn_b, move0_rn_a, move0_rn_b, move0_rn_a, move0_rn_b,
+ /* 0x8200 */
+ move1_rn_a, move1_rn_b, move1_rn_a, move1_rn_b, move1_rn_a, move1_rn_b, move1_rn_a, move1_rn_b,
+ move1_rn_a, move1_rn_b, move1_rn_a, move1_rn_b, move1_rn_a, move1_rn_b, move1_rn_a, move1_rn_b,
+ /* 0x8300 */
+ move1_rn_a, move1_rn_b, move1_rn_a, move1_rn_b, move1_rn_a, move1_rn_b, move1_rn_a, move1_rn_b,
+ move1_rn_a, move1_rn_b, move1_rn_a, move1_rn_b, move1_rn_a, move1_rn_b, move1_rn_a, move1_rn_b,
+ /* 0x8400 */
+ move0_nr_a, move0_nr_b, move0_nr_a, move0_nr_b, move0_nr_a, move0_nr_b, move0_nr_a, move0_nr_b,
+ move0_nr_a, move0_nr_b, move0_nr_a, move0_nr_b, move0_nr_a, move0_nr_b, move0_nr_a, move0_nr_b,
+ /* 0x8500 */
+ move0_nr_a, move0_nr_b, move0_nr_a, move0_nr_b, move0_nr_a, move0_nr_b, move0_nr_a, move0_nr_b,
+ move0_nr_a, move0_nr_b, move0_nr_a, move0_nr_b, move0_nr_a, move0_nr_b, move0_nr_a, move0_nr_b,
+ /* 0x8600 */
+ move1_nr_a, move1_nr_b, move1_nr_a, move1_nr_b, move1_nr_a, move1_nr_b, move1_nr_a, move1_nr_b,
+ move1_nr_a, move1_nr_b, move1_nr_a, move1_nr_b, move1_nr_a, move1_nr_b, move1_nr_a, move1_nr_b,
+ /* 0x8700 */
+ move1_nr_a, move1_nr_b, move1_nr_a, move1_nr_b, move1_nr_a, move1_nr_b, move1_nr_a, move1_nr_b,
+ move1_nr_a, move1_nr_b, move1_nr_a, move1_nr_b, move1_nr_a, move1_nr_b, move1_nr_a, move1_nr_b,
+ /* 0x8800 */
+ move0_nn_a, move0_nn_b, move0_nn_a, move0_nn_b, move0_nn_a, move0_nn_b, move0_nn_a, move0_nn_b,
+ move0_nn_a, move0_nn_b, move0_nn_a, move0_nn_b, move0_nn_a, move0_nn_b, move0_nn_a, move0_nn_b,
+ /* 0x8900 */
+ move0_nn_a, move0_nn_b, move0_nn_a, move0_nn_b, move0_nn_a, move0_nn_b, move0_nn_a, move0_nn_b,
+ move0_nn_a, move0_nn_b, move0_nn_a, move0_nn_b, move0_nn_a, move0_nn_b, move0_nn_a, move0_nn_b,
+ /* 0x8a00 */
+ move1_nn_a, move1_nn_b, move1_nn_a, move1_nn_b, move1_nn_a, move1_nn_b, move1_nn_a, move1_nn_b,
+ move1_nn_a, move1_nn_b, move1_nn_a, move1_nn_b, move1_nn_a, move1_nn_b, move1_nn_a, move1_nn_b,
+ /* 0x8b00 */
+ move1_nn_a, move1_nn_b, move1_nn_a, move1_nn_b, move1_nn_a, move1_nn_b, move1_nn_a, move1_nn_b,
+ move1_nn_a, move1_nn_b, move1_nn_a, move1_nn_b, move1_nn_a, move1_nn_b, move1_nn_a, move1_nn_b,
+ /* 0x8c00 */
+ movb_rn_a, movb_rn_b, movb_rn_a, movb_rn_b, movb_rn_a, movb_rn_b, movb_rn_a, movb_rn_b,
+ movb_rn_a, movb_rn_b, movb_rn_a, movb_rn_b, movb_rn_a, movb_rn_b, movb_rn_a, movb_rn_b,
+ /* 0x8d00 */
+ movb_rn_a, movb_rn_b, movb_rn_a, movb_rn_b, movb_rn_a, movb_rn_b, movb_rn_a, movb_rn_b,
+ movb_rn_a, movb_rn_b, movb_rn_a, movb_rn_b, movb_rn_a, movb_rn_b, movb_rn_a, movb_rn_b,
+ /* 0x8e00 */
+ movb_nr_a, movb_nr_b, movb_nr_a, movb_nr_b, movb_nr_a, movb_nr_b, movb_nr_a, movb_nr_b,
+ movb_nr_a, movb_nr_b, movb_nr_a, movb_nr_b, movb_nr_a, movb_nr_b, movb_nr_a, movb_nr_b,
+ /* 0x8f00 */
+ movb_nr_a, movb_nr_b, movb_nr_a, movb_nr_b, movb_nr_a, movb_nr_b, movb_nr_a, movb_nr_b,
+ movb_nr_a, movb_nr_b, movb_nr_a, movb_nr_b, movb_nr_a, movb_nr_b, movb_nr_a, movb_nr_b,
+ /* 0x9000 */
+ move0_r_ni_a, move0_r_ni_b, move0_r_ni_a, move0_r_ni_b, move0_r_ni_a, move0_r_ni_b, move0_r_ni_a, move0_r_ni_b,
+ move0_r_ni_a, move0_r_ni_b, move0_r_ni_a, move0_r_ni_b, move0_r_ni_a, move0_r_ni_b, move0_r_ni_a, move0_r_ni_b,
+ /* 0x9100 */
+ move0_r_ni_a, move0_r_ni_b, move0_r_ni_a, move0_r_ni_b, move0_r_ni_a, move0_r_ni_b, move0_r_ni_a, move0_r_ni_b,
+ move0_r_ni_a, move0_r_ni_b, move0_r_ni_a, move0_r_ni_b, move0_r_ni_a, move0_r_ni_b, move0_r_ni_a, move0_r_ni_b,
+ /* 0x9200 */
+ move1_r_ni_a, move1_r_ni_b, move1_r_ni_a, move1_r_ni_b, move1_r_ni_a, move1_r_ni_b, move1_r_ni_a, move1_r_ni_b,
+ move1_r_ni_a, move1_r_ni_b, move1_r_ni_a, move1_r_ni_b, move1_r_ni_a, move1_r_ni_b, move1_r_ni_a, move1_r_ni_b,
+ /* 0x9300 */
+ move1_r_ni_a, move1_r_ni_b, move1_r_ni_a, move1_r_ni_b, move1_r_ni_a, move1_r_ni_b, move1_r_ni_a, move1_r_ni_b,
+ move1_r_ni_a, move1_r_ni_b, move1_r_ni_a, move1_r_ni_b, move1_r_ni_a, move1_r_ni_b, move1_r_ni_a, move1_r_ni_b,
+ /* 0x9400 */
+ move0_ni_r_a, move0_ni_r_b, move0_ni_r_a, move0_ni_r_b, move0_ni_r_a, move0_ni_r_b, move0_ni_r_a, move0_ni_r_b,
+ move0_ni_r_a, move0_ni_r_b, move0_ni_r_a, move0_ni_r_b, move0_ni_r_a, move0_ni_r_b, move0_ni_r_a, move0_ni_r_b,
+ /* 0x9500 */
+ move0_ni_r_a, move0_ni_r_b, move0_ni_r_a, move0_ni_r_b, move0_ni_r_a, move0_ni_r_b, move0_ni_r_a, move0_ni_r_b,
+ move0_ni_r_a, move0_ni_r_b, move0_ni_r_a, move0_ni_r_b, move0_ni_r_a, move0_ni_r_b, move0_ni_r_a, move0_ni_r_b,
+ /* 0x9600 */
+ move1_ni_r_a, move1_ni_r_b, move1_ni_r_a, move1_ni_r_b, move1_ni_r_a, move1_ni_r_b, move1_ni_r_a, move1_ni_r_b,
+ move1_ni_r_a, move1_ni_r_b, move1_ni_r_a, move1_ni_r_b, move1_ni_r_a, move1_ni_r_b, move1_ni_r_a, move1_ni_r_b,
+ /* 0x9700 */
+ move1_ni_r_a, move1_ni_r_b, move1_ni_r_a, move1_ni_r_b, move1_ni_r_a, move1_ni_r_b, move1_ni_r_a, move1_ni_r_b,
+ move1_ni_r_a, move1_ni_r_b, move1_ni_r_a, move1_ni_r_b, move1_ni_r_a, move1_ni_r_b, move1_ni_r_a, move1_ni_r_b,
+ /* 0x9800 */
+ move0_ni_ni_a, move0_ni_ni_b, move0_ni_ni_a, move0_ni_ni_b, move0_ni_ni_a, move0_ni_ni_b, move0_ni_ni_a, move0_ni_ni_b,
+ move0_ni_ni_a, move0_ni_ni_b, move0_ni_ni_a, move0_ni_ni_b, move0_ni_ni_a, move0_ni_ni_b, move0_ni_ni_a, move0_ni_ni_b,
+ /* 0x9900 */
+ move0_ni_ni_a, move0_ni_ni_b, move0_ni_ni_a, move0_ni_ni_b, move0_ni_ni_a, move0_ni_ni_b, move0_ni_ni_a, move0_ni_ni_b,
+ move0_ni_ni_a, move0_ni_ni_b, move0_ni_ni_a, move0_ni_ni_b, move0_ni_ni_a, move0_ni_ni_b, move0_ni_ni_a, move0_ni_ni_b,
+ /* 0x9a00 */
+ move1_ni_ni_a, move1_ni_ni_b, move1_ni_ni_a, move1_ni_ni_b, move1_ni_ni_a, move1_ni_ni_b, move1_ni_ni_a, move1_ni_ni_b,
+ move1_ni_ni_a, move1_ni_ni_b, move1_ni_ni_a, move1_ni_ni_b, move1_ni_ni_a, move1_ni_ni_b, move1_ni_ni_a, move1_ni_ni_b,
+ /* 0x9b00 */
+ move1_ni_ni_a, move1_ni_ni_b, move1_ni_ni_a, move1_ni_ni_b, move1_ni_ni_a, move1_ni_ni_b, move1_ni_ni_a, move1_ni_ni_b,
+ move1_ni_ni_a, move1_ni_ni_b, move1_ni_ni_a, move1_ni_ni_b, move1_ni_ni_a, move1_ni_ni_b, move1_ni_ni_a, move1_ni_ni_b,
+ /* 0x9c00 */
+ movb_nn_a, movb_nn_b, movb_nn_a, movb_nn_b, movb_nn_a, movb_nn_b, movb_nn_a, movb_nn_b,
+ movb_nn_a, movb_nn_b, movb_nn_a, movb_nn_b, movb_nn_a, movb_nn_b, movb_nn_a, movb_nn_b,
+ /* 0x9d00 */
+ movb_nn_a, movb_nn_b, movb_nn_a, movb_nn_b, movb_nn_a, movb_nn_b, movb_nn_a, movb_nn_b,
+ movb_nn_a, movb_nn_b, movb_nn_a, movb_nn_b, movb_nn_a, movb_nn_b, movb_nn_a, movb_nn_b,
+ /* 0x9e00 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0x9f00 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0xa000 */
+ move0_r_dn_a, move0_r_dn_b, move0_r_dn_a, move0_r_dn_b, move0_r_dn_a, move0_r_dn_b, move0_r_dn_a, move0_r_dn_b,
+ move0_r_dn_a, move0_r_dn_b, move0_r_dn_a, move0_r_dn_b, move0_r_dn_a, move0_r_dn_b, move0_r_dn_a, move0_r_dn_b,
+ /* 0xa100 */
+ move0_r_dn_a, move0_r_dn_b, move0_r_dn_a, move0_r_dn_b, move0_r_dn_a, move0_r_dn_b, move0_r_dn_a, move0_r_dn_b,
+ move0_r_dn_a, move0_r_dn_b, move0_r_dn_a, move0_r_dn_b, move0_r_dn_a, move0_r_dn_b, move0_r_dn_a, move0_r_dn_b,
+ /* 0xa200 */
+ move1_r_dn_a, move1_r_dn_b, move1_r_dn_a, move1_r_dn_b, move1_r_dn_a, move1_r_dn_b, move1_r_dn_a, move1_r_dn_b,
+ move1_r_dn_a, move1_r_dn_b, move1_r_dn_a, move1_r_dn_b, move1_r_dn_a, move1_r_dn_b, move1_r_dn_a, move1_r_dn_b,
+ /* 0xa300 */
+ move1_r_dn_a, move1_r_dn_b, move1_r_dn_a, move1_r_dn_b, move1_r_dn_a, move1_r_dn_b, move1_r_dn_a, move1_r_dn_b,
+ move1_r_dn_a, move1_r_dn_b, move1_r_dn_a, move1_r_dn_b, move1_r_dn_a, move1_r_dn_b, move1_r_dn_a, move1_r_dn_b,
+ /* 0xa400 */
+ move0_dn_r_a, move0_dn_r_b, move0_dn_r_a, move0_dn_r_b, move0_dn_r_a, move0_dn_r_b, move0_dn_r_a, move0_dn_r_b,
+ move0_dn_r_a, move0_dn_r_b, move0_dn_r_a, move0_dn_r_b, move0_dn_r_a, move0_dn_r_b, move0_dn_r_a, move0_dn_r_b,
+ /* 0xa500 */
+ move0_dn_r_a, move0_dn_r_b, move0_dn_r_a, move0_dn_r_b, move0_dn_r_a, move0_dn_r_b, move0_dn_r_a, move0_dn_r_b,
+ move0_dn_r_a, move0_dn_r_b, move0_dn_r_a, move0_dn_r_b, move0_dn_r_a, move0_dn_r_b, move0_dn_r_a, move0_dn_r_b,
+ /* 0xa600 */
+ move1_dn_r_a, move1_dn_r_b, move1_dn_r_a, move1_dn_r_b, move1_dn_r_a, move1_dn_r_b, move1_dn_r_a, move1_dn_r_b,
+ move1_dn_r_a, move1_dn_r_b, move1_dn_r_a, move1_dn_r_b, move1_dn_r_a, move1_dn_r_b, move1_dn_r_a, move1_dn_r_b,
+ /* 0xa700 */
+ move1_dn_r_a, move1_dn_r_b, move1_dn_r_a, move1_dn_r_b, move1_dn_r_a, move1_dn_r_b, move1_dn_r_a, move1_dn_r_b,
+ move1_dn_r_a, move1_dn_r_b, move1_dn_r_a, move1_dn_r_b, move1_dn_r_a, move1_dn_r_b, move1_dn_r_a, move1_dn_r_b,
+ /* 0xa800 */
+ move0_dn_dn_a, move0_dn_dn_b, move0_dn_dn_a, move0_dn_dn_b, move0_dn_dn_a, move0_dn_dn_b, move0_dn_dn_a, move0_dn_dn_b,
+ move0_dn_dn_a, move0_dn_dn_b, move0_dn_dn_a, move0_dn_dn_b, move0_dn_dn_a, move0_dn_dn_b, move0_dn_dn_a, move0_dn_dn_b,
+ /* 0xa900 */
+ move0_dn_dn_a, move0_dn_dn_b, move0_dn_dn_a, move0_dn_dn_b, move0_dn_dn_a, move0_dn_dn_b, move0_dn_dn_a, move0_dn_dn_b,
+ move0_dn_dn_a, move0_dn_dn_b, move0_dn_dn_a, move0_dn_dn_b, move0_dn_dn_a, move0_dn_dn_b, move0_dn_dn_a, move0_dn_dn_b,
+ /* 0xaa00 */
+ move1_dn_dn_a, move1_dn_dn_b, move1_dn_dn_a, move1_dn_dn_b, move1_dn_dn_a, move1_dn_dn_b, move1_dn_dn_a, move1_dn_dn_b,
+ move1_dn_dn_a, move1_dn_dn_b, move1_dn_dn_a, move1_dn_dn_b, move1_dn_dn_a, move1_dn_dn_b, move1_dn_dn_a, move1_dn_dn_b,
+ /* 0xab00 */
+ move1_dn_dn_a, move1_dn_dn_b, move1_dn_dn_a, move1_dn_dn_b, move1_dn_dn_a, move1_dn_dn_b, move1_dn_dn_a, move1_dn_dn_b,
+ move1_dn_dn_a, move1_dn_dn_b, move1_dn_dn_a, move1_dn_dn_b, move1_dn_dn_a, move1_dn_dn_b, move1_dn_dn_a, move1_dn_dn_b,
+ /* 0xac00 */
+ movb_r_no_a, movb_r_no_b, movb_r_no_a, movb_r_no_b, movb_r_no_a, movb_r_no_b, movb_r_no_a, movb_r_no_b,
+ movb_r_no_a, movb_r_no_b, movb_r_no_a, movb_r_no_b, movb_r_no_a, movb_r_no_b, movb_r_no_a, movb_r_no_b,
+ /* 0xad00 */
+ movb_r_no_a, movb_r_no_b, movb_r_no_a, movb_r_no_b, movb_r_no_a, movb_r_no_b, movb_r_no_a, movb_r_no_b,
+ movb_r_no_a, movb_r_no_b, movb_r_no_a, movb_r_no_b, movb_r_no_a, movb_r_no_b, movb_r_no_a, movb_r_no_b,
+ /* 0xae00 */
+ movb_no_r_a, movb_no_r_b, movb_no_r_a, movb_no_r_b, movb_no_r_a, movb_no_r_b, movb_no_r_a, movb_no_r_b,
+ movb_no_r_a, movb_no_r_b, movb_no_r_a, movb_no_r_b, movb_no_r_a, movb_no_r_b, movb_no_r_a, movb_no_r_b,
+ /* 0xaf00 */
+ movb_no_r_a, movb_no_r_b, movb_no_r_a, movb_no_r_b, movb_no_r_a, movb_no_r_b, movb_no_r_a, movb_no_r_b,
+ movb_no_r_a, movb_no_r_b, movb_no_r_a, movb_no_r_b, movb_no_r_a, movb_no_r_b, movb_no_r_a, movb_no_r_b,
+ /* 0xb000 */
+ move0_r_no_a, move0_r_no_b, move0_r_no_a, move0_r_no_b, move0_r_no_a, move0_r_no_b, move0_r_no_a, move0_r_no_b,
+ move0_r_no_a, move0_r_no_b, move0_r_no_a, move0_r_no_b, move0_r_no_a, move0_r_no_b, move0_r_no_a, move0_r_no_b,
+ /* 0xb100 */
+ move0_r_no_a, move0_r_no_b, move0_r_no_a, move0_r_no_b, move0_r_no_a, move0_r_no_b, move0_r_no_a, move0_r_no_b,
+ move0_r_no_a, move0_r_no_b, move0_r_no_a, move0_r_no_b, move0_r_no_a, move0_r_no_b, move0_r_no_a, move0_r_no_b,
+ /* 0xb200 */
+ move1_r_no_a, move1_r_no_b, move1_r_no_a, move1_r_no_b, move1_r_no_a, move1_r_no_b, move1_r_no_a, move1_r_no_b,
+ move1_r_no_a, move1_r_no_b, move1_r_no_a, move1_r_no_b, move1_r_no_a, move1_r_no_b, move1_r_no_a, move1_r_no_b,
+ /* 0xb300 */
+ move1_r_no_a, move1_r_no_b, move1_r_no_a, move1_r_no_b, move1_r_no_a, move1_r_no_b, move1_r_no_a, move1_r_no_b,
+ move1_r_no_a, move1_r_no_b, move1_r_no_a, move1_r_no_b, move1_r_no_a, move1_r_no_b, move1_r_no_a, move1_r_no_b,
+ /* 0xb400 */
+ move0_no_r_a, move0_no_r_b, move0_no_r_a, move0_no_r_b, move0_no_r_a, move0_no_r_b, move0_no_r_a, move0_no_r_b,
+ move0_no_r_a, move0_no_r_b, move0_no_r_a, move0_no_r_b, move0_no_r_a, move0_no_r_b, move0_no_r_a, move0_no_r_b,
+ /* 0xb500 */
+ move0_no_r_a, move0_no_r_b, move0_no_r_a, move0_no_r_b, move0_no_r_a, move0_no_r_b, move0_no_r_a, move0_no_r_b,
+ move0_no_r_a, move0_no_r_b, move0_no_r_a, move0_no_r_b, move0_no_r_a, move0_no_r_b, move0_no_r_a, move0_no_r_b,
+ /* 0xb600 */
+ move1_no_r_a, move1_no_r_b, move1_no_r_a, move1_no_r_b, move1_no_r_a, move1_no_r_b, move1_no_r_a, move1_no_r_b,
+ move1_no_r_a, move1_no_r_b, move1_no_r_a, move1_no_r_b, move1_no_r_a, move1_no_r_b, move1_no_r_a, move1_no_r_b,
+ /* 0xb700 */
+ move1_no_r_a, move1_no_r_b, move1_no_r_a, move1_no_r_b, move1_no_r_a, move1_no_r_b, move1_no_r_a, move1_no_r_b,
+ move1_no_r_a, move1_no_r_b, move1_no_r_a, move1_no_r_b, move1_no_r_a, move1_no_r_b, move1_no_r_a, move1_no_r_b,
+ /* 0xb800 */
+ move0_no_no_a, move0_no_no_b, move0_no_no_a, move0_no_no_b, move0_no_no_a, move0_no_no_b, move0_no_no_a, move0_no_no_b,
+ move0_no_no_a, move0_no_no_b, move0_no_no_a, move0_no_no_b, move0_no_no_a, move0_no_no_b, move0_no_no_a, move0_no_no_b,
+ /* 0xb900 */
+ move0_no_no_a, move0_no_no_b, move0_no_no_a, move0_no_no_b, move0_no_no_a, move0_no_no_b, move0_no_no_a, move0_no_no_b,
+ move0_no_no_a, move0_no_no_b, move0_no_no_a, move0_no_no_b, move0_no_no_a, move0_no_no_b, move0_no_no_a, move0_no_no_b,
+ /* 0xba00 */
+ move1_no_no_a, move1_no_no_b, move1_no_no_a, move1_no_no_b, move1_no_no_a, move1_no_no_b, move1_no_no_a, move1_no_no_b,
+ move1_no_no_a, move1_no_no_b, move1_no_no_a, move1_no_no_b, move1_no_no_a, move1_no_no_b, move1_no_no_a, move1_no_no_b,
+ /* 0xbb00 */
+ move1_no_no_a, move1_no_no_b, move1_no_no_a, move1_no_no_b, move1_no_no_a, move1_no_no_b, move1_no_no_a, move1_no_no_b,
+ move1_no_no_a, move1_no_no_b, move1_no_no_a, move1_no_no_b, move1_no_no_a, move1_no_no_b, move1_no_no_a, move1_no_no_b,
+ /* 0xbc00 */
+ movb_no_no_a, movb_no_no_b, movb_no_no_a, movb_no_no_b, movb_no_no_a, movb_no_no_b, movb_no_no_a, movb_no_no_b,
+ movb_no_no_a, movb_no_no_b, movb_no_no_a, movb_no_no_b, movb_no_no_a, movb_no_no_b, movb_no_no_a, movb_no_no_b,
+ /* 0xbd00 */
+ movb_no_no_a, movb_no_no_b, movb_no_no_a, movb_no_no_b, movb_no_no_a, movb_no_no_b, movb_no_no_a, movb_no_no_b,
+ movb_no_no_a, movb_no_no_b, movb_no_no_a, movb_no_no_b, movb_no_no_a, movb_no_no_b, movb_no_no_a, movb_no_no_b,
+ /* 0xbe00 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0xbf00 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0xc000 */
+ j_UC_0, j_UC_x, j_UC_x, j_UC_x, j_UC_x, j_UC_x, j_UC_x, j_UC_x,
+ j_UC_8, j_UC_x, j_UC_x, j_UC_x, j_UC_x, j_UC_x, j_UC_x, j_UC_x,
+ /* 0xc100 */
+ j_P_0, j_P_x, j_P_x, j_P_x, j_P_x, j_P_x, j_P_x, j_P_x,
+ j_P_8, j_P_x, j_P_x, j_P_x, j_P_x, j_P_x, j_P_x, j_P_x,
+ /* 0xc200 */
+ j_LS_0, j_LS_x, j_LS_x, j_LS_x, j_LS_x, j_LS_x, j_LS_x, j_LS_x,
+ j_LS_8, j_LS_x, j_LS_x, j_LS_x, j_LS_x, j_LS_x, j_LS_x, j_LS_x,
+ /* 0xc300 */
+ j_HI_0, j_HI_x, j_HI_x, j_HI_x, j_HI_x, j_HI_x, j_HI_x, j_HI_x,
+ j_HI_8, j_HI_x, j_HI_x, j_HI_x, j_HI_x, j_HI_x, j_HI_x, j_HI_x,
+ /* 0xc400 */
+ j_LT_0, j_LT_x, j_LT_x, j_LT_x, j_LT_x, j_LT_x, j_LT_x, j_LT_x,
+ j_LT_8, j_LT_x, j_LT_x, j_LT_x, j_LT_x, j_LT_x, j_LT_x, j_LT_x,
+ /* 0xc500 */
+ j_GE_0, j_GE_x, j_GE_x, j_GE_x, j_GE_x, j_GE_x, j_GE_x, j_GE_x,
+ j_GE_8, j_GE_x, j_GE_x, j_GE_x, j_GE_x, j_GE_x, j_GE_x, j_GE_x,
+ /* 0xc600 */
+ j_LE_0, j_LE_x, j_LE_x, j_LE_x, j_LE_x, j_LE_x, j_LE_x, j_LE_x,
+ j_LE_8, j_LE_x, j_LE_x, j_LE_x, j_LE_x, j_LE_x, j_LE_x, j_LE_x,
+ /* 0xc700 */
+ j_GT_0, j_GT_x, j_GT_x, j_GT_x, j_GT_x, j_GT_x, j_GT_x, j_GT_x,
+ j_GT_8, j_GT_x, j_GT_x, j_GT_x, j_GT_x, j_GT_x, j_GT_x, j_GT_x,
+ /* 0xc800 */
+ j_C_0, j_C_x, j_C_x, j_C_x, j_C_x, j_C_x, j_C_x, j_C_x,
+ j_C_8, j_C_x, j_C_x, j_C_x, j_C_x, j_C_x, j_C_x, j_C_x,
+ /* 0xc900 */
+ j_NC_0, j_NC_x, j_NC_x, j_NC_x, j_NC_x, j_NC_x, j_NC_x, j_NC_x,
+ j_NC_8, j_NC_x, j_NC_x, j_NC_x, j_NC_x, j_NC_x, j_NC_x, j_NC_x,
+ /* 0xca00 */
+ j_EQ_0, j_EQ_x, j_EQ_x, j_EQ_x, j_EQ_x, j_EQ_x, j_EQ_x, j_EQ_x,
+ j_EQ_8, j_EQ_x, j_EQ_x, j_EQ_x, j_EQ_x, j_EQ_x, j_EQ_x, j_EQ_x,
+ /* 0xcb00 */
+ j_NE_0, j_NE_x, j_NE_x, j_NE_x, j_NE_x, j_NE_x, j_NE_x, j_NE_x,
+ j_NE_8, j_NE_x, j_NE_x, j_NE_x, j_NE_x, j_NE_x, j_NE_x, j_NE_x,
+ /* 0xcc00 */
+ j_V_0, j_V_x, j_V_x, j_V_x, j_V_x, j_V_x, j_V_x, j_V_x,
+ j_V_8, j_V_x, j_V_x, j_V_x, j_V_x, j_V_x, j_V_x, j_V_x,
+ /* 0xcd00 */
+ j_NV_0, j_NV_x, j_NV_x, j_NV_x, j_NV_x, j_NV_x, j_NV_x, j_NV_x,
+ j_NV_8, j_NV_x, j_NV_x, j_NV_x, j_NV_x, j_NV_x, j_NV_x, j_NV_x,
+ /* 0xce00 */
+ j_N_0, j_N_x, j_N_x, j_N_x, j_N_x, j_N_x, j_N_x, j_N_x,
+ j_N_8, j_N_x, j_N_x, j_N_x, j_N_x, j_N_x, j_N_x, j_N_x,
+ /* 0xcf00 */
+ j_NN_0, j_NN_x, j_NN_x, j_NN_x, j_NN_x, j_NN_x, j_NN_x, j_NN_x,
+ j_NN_8, j_NN_x, j_NN_x, j_NN_x, j_NN_x, j_NN_x, j_NN_x, j_NN_x,
+ /* 0xd000 */
+ move0_no_ni_a, move0_no_ni_b, move0_no_ni_a, move0_no_ni_b, move0_no_ni_a, move0_no_ni_b, move0_no_ni_a, move0_no_ni_b,
+ move0_no_ni_a, move0_no_ni_b, move0_no_ni_a, move0_no_ni_b, move0_no_ni_a, move0_no_ni_b, move0_no_ni_a, move0_no_ni_b,
+ /* 0xd100 */
+ move0_no_ni_a, move0_no_ni_b, move0_no_ni_a, move0_no_ni_b, move0_no_ni_a, move0_no_ni_b, move0_no_ni_a, move0_no_ni_b,
+ move0_no_ni_a, move0_no_ni_b, move0_no_ni_a, move0_no_ni_b, move0_no_ni_a, move0_no_ni_b, move0_no_ni_a, move0_no_ni_b,
+ /* 0xd200 */
+ move1_no_ni_a, move1_no_ni_b, move1_no_ni_a, move1_no_ni_b, move1_no_ni_a, move1_no_ni_b, move1_no_ni_a, move1_no_ni_b,
+ move1_no_ni_a, move1_no_ni_b, move1_no_ni_a, move1_no_ni_b, move1_no_ni_a, move1_no_ni_b, move1_no_ni_a, move1_no_ni_b,
+ /* 0xd300 */
+ move1_no_ni_a, move1_no_ni_b, move1_no_ni_a, move1_no_ni_b, move1_no_ni_a, move1_no_ni_b, move1_no_ni_a, move1_no_ni_b,
+ move1_no_ni_a, move1_no_ni_b, move1_no_ni_a, move1_no_ni_b, move1_no_ni_a, move1_no_ni_b, move1_no_ni_a, move1_no_ni_b,
+ /* 0xd400 */
+ move0_a_ni_a,move0_a_ni_b,unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0xd500 */
+ exgf0_a, exgf0_b, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0xd600 */
+ move1_a_ni_a,move1_a_ni_b,unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0xd700 */
+ exgf1_a, exgf1_b, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0xd800 */
+ cexec_s, cexec_s, cexec_s, cexec_s, cexec_s, cexec_s, cexec_s, cexec_s,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0xd900 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0xda00 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0xdb00 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0xdc00 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0xdd00 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0xde00 */
+ unimpl, fline, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, fline, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0xdf00 */
+ unimpl, line, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, line, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0xe000 */
+ add_xy_a, add_xy_b, add_xy_a, add_xy_b, add_xy_a, add_xy_b, add_xy_a, add_xy_b,
+ add_xy_a, add_xy_b, add_xy_a, add_xy_b, add_xy_a, add_xy_b, add_xy_a, add_xy_b,
+ /* 0xe100 */
+ add_xy_a, add_xy_b, add_xy_a, add_xy_b, add_xy_a, add_xy_b, add_xy_a, add_xy_b,
+ add_xy_a, add_xy_b, add_xy_a, add_xy_b, add_xy_a, add_xy_b, add_xy_a, add_xy_b,
+ /* 0xe200 */
+ sub_xy_a, sub_xy_b, sub_xy_a, sub_xy_b, sub_xy_a, sub_xy_b, sub_xy_a, sub_xy_b,
+ sub_xy_a, sub_xy_b, sub_xy_a, sub_xy_b, sub_xy_a, sub_xy_b, sub_xy_a, sub_xy_b,
+ /* 0xe300 */
+ sub_xy_a, sub_xy_b, sub_xy_a, sub_xy_b, sub_xy_a, sub_xy_b, sub_xy_a, sub_xy_b,
+ sub_xy_a, sub_xy_b, sub_xy_a, sub_xy_b, sub_xy_a, sub_xy_b, sub_xy_a, sub_xy_b,
+ /* 0xe400 */
+ cmp_xy_a, cmp_xy_b, cmp_xy_a, cmp_xy_b, cmp_xy_a, cmp_xy_b, cmp_xy_a, cmp_xy_b,
+ cmp_xy_a, cmp_xy_b, cmp_xy_a, cmp_xy_b, cmp_xy_a, cmp_xy_b, cmp_xy_a, cmp_xy_b,
+ /* 0xe500 */
+ cmp_xy_a, cmp_xy_b, cmp_xy_a, cmp_xy_b, cmp_xy_a, cmp_xy_b, cmp_xy_a, cmp_xy_b,
+ cmp_xy_a, cmp_xy_b, cmp_xy_a, cmp_xy_b, cmp_xy_a, cmp_xy_b, cmp_xy_a, cmp_xy_b,
+ /* 0xe600 */
+ cpw_a, cpw_b, cpw_a, cpw_b, cpw_a, cpw_b, cpw_a, cpw_b,
+ cpw_a, cpw_b, cpw_a, cpw_b, cpw_a, cpw_b, cpw_a, cpw_b,
+ /* 0xe700 */
+ cpw_a, cpw_b, cpw_a, cpw_b, cpw_a, cpw_b, cpw_a, cpw_b,
+ cpw_a, cpw_b, cpw_a, cpw_b, cpw_a, cpw_b, cpw_a, cpw_b,
+ /* 0xe800 */
+ cvxyl_a, cvxyl_b, cvxyl_a, cvxyl_b, cvxyl_a, cvxyl_b, cvxyl_a, cvxyl_b,
+ cvxyl_a, cvxyl_b, cvxyl_a, cvxyl_b, cvxyl_a, cvxyl_b, cvxyl_a, cvxyl_b,
+ /* 0xe900 */
+ cvxyl_a, cvxyl_b, cvxyl_a, cvxyl_b, cvxyl_a, cvxyl_b, cvxyl_a, cvxyl_b,
+ cvxyl_a, cvxyl_b, cvxyl_a, cvxyl_b, cvxyl_a, cvxyl_b, cvxyl_a, cvxyl_b,
+ /* 0xea00 */
+ cvsxyl_a, cvsxyl_b, cvsxyl_a, cvsxyl_b, cvsxyl_a, cvsxyl_b, cvsxyl_a, cvsxyl_b,
+ cvsxyl_a, cvsxyl_b, cvsxyl_a, cvsxyl_b, cvsxyl_a, cvsxyl_b, cvsxyl_a, cvsxyl_b,
+ /* 0xeb00 */
+ cvsxyl_a, cvsxyl_b, cvsxyl_a, cvsxyl_b, cvsxyl_a, cvsxyl_b, cvsxyl_a, cvsxyl_b,
+ cvsxyl_a, cvsxyl_b, cvsxyl_a, cvsxyl_b, cvsxyl_a, cvsxyl_b, cvsxyl_a, cvsxyl_b,
+ /* 0xec00 */
+ movx_a, movx_b, movx_a, movx_b, movx_a, movx_b, movx_a, movx_b,
+ movx_a, movx_b, movx_a, movx_b, movx_a, movx_b, movx_a, movx_b,
+ /* 0xed00 */
+ movx_a, movx_b, movx_a, movx_b, movx_a, movx_b, movx_a, movx_b,
+ movx_a, movx_b, movx_a, movx_b, movx_a, movx_b, movx_a, movx_b,
+ /* 0xee00 */
+ movy_a, movy_b, movy_a, movy_b, movy_a, movy_b, movy_a, movy_b,
+ movy_a, movy_b, movy_a, movy_b, movy_a, movy_b, movy_a, movy_b,
+ /* 0xef00 */
+ movy_a, movy_b, movy_a, movy_b, movy_a, movy_b, movy_a, movy_b,
+ movy_a, movy_b, movy_a, movy_b, movy_a, movy_b, movy_a, movy_b,
+ /* 0xf000 */
+ pixt_rixy_a, pixt_rixy_b, pixt_rixy_a, pixt_rixy_b, pixt_rixy_a, pixt_rixy_b, pixt_rixy_a, pixt_rixy_b,
+ pixt_rixy_a, pixt_rixy_b, pixt_rixy_a, pixt_rixy_b, pixt_rixy_a, pixt_rixy_b, pixt_rixy_a, pixt_rixy_b,
+ /* 0xf100 */
+ pixt_rixy_a, pixt_rixy_b, pixt_rixy_a, pixt_rixy_b, pixt_rixy_a, pixt_rixy_b, pixt_rixy_a, pixt_rixy_b,
+ pixt_rixy_a, pixt_rixy_b, pixt_rixy_a, pixt_rixy_b, pixt_rixy_a, pixt_rixy_b, pixt_rixy_a, pixt_rixy_b,
+ /* 0xf200 */
+ pixt_ixyr_a, pixt_ixyr_b, pixt_ixyr_a, pixt_ixyr_b, pixt_ixyr_a, pixt_ixyr_b, pixt_ixyr_a, pixt_ixyr_b,
+ pixt_ixyr_a, pixt_ixyr_b, pixt_ixyr_a, pixt_ixyr_b, pixt_ixyr_a, pixt_ixyr_b, pixt_ixyr_a, pixt_ixyr_b,
+ /* 0xf300 */
+ pixt_ixyr_a, pixt_ixyr_b, pixt_ixyr_a, pixt_ixyr_b, pixt_ixyr_a, pixt_ixyr_b, pixt_ixyr_a, pixt_ixyr_b,
+ pixt_ixyr_a, pixt_ixyr_b, pixt_ixyr_a, pixt_ixyr_b, pixt_ixyr_a, pixt_ixyr_b, pixt_ixyr_a, pixt_ixyr_b,
+ /* 0xf400 */
+ pixt_ixyixy_a, pixt_ixyixy_b, pixt_ixyixy_a, pixt_ixyixy_b, pixt_ixyixy_a, pixt_ixyixy_b, pixt_ixyixy_a, pixt_ixyixy_b,
+ pixt_ixyixy_a, pixt_ixyixy_b, pixt_ixyixy_a, pixt_ixyixy_b, pixt_ixyixy_a, pixt_ixyixy_b, pixt_ixyixy_a, pixt_ixyixy_b,
+ /* 0xf500 */
+ pixt_ixyixy_a, pixt_ixyixy_b, pixt_ixyixy_a, pixt_ixyixy_b, pixt_ixyixy_a, pixt_ixyixy_b, pixt_ixyixy_a, pixt_ixyixy_b,
+ pixt_ixyixy_a, pixt_ixyixy_b, pixt_ixyixy_a, pixt_ixyixy_b, pixt_ixyixy_a, pixt_ixyixy_b, pixt_ixyixy_a, pixt_ixyixy_b,
+ /* 0xf600 */
+ drav_a, drav_b, drav_a, drav_b, drav_a, drav_b, drav_a, drav_b,
+ drav_a, drav_b, drav_a, drav_b, drav_a, drav_b, drav_a, drav_b,
+ /* 0xf700 */
+ drav_a, drav_b, drav_a, drav_b, drav_a, drav_b, drav_a, drav_b,
+ drav_a, drav_b, drav_a, drav_b, drav_a, drav_b, drav_a, drav_b,
+ /* 0xf800 */
+ pixt_ri_a, pixt_ri_b, pixt_ri_a, pixt_ri_b, pixt_ri_a, pixt_ri_b, pixt_ri_a, pixt_ri_b,
+ pixt_ri_a, pixt_ri_b, pixt_ri_a, pixt_ri_b, pixt_ri_a, pixt_ri_b, pixt_ri_a, pixt_ri_b,
+ /* 0xf900 */
+ pixt_ri_a, pixt_ri_b, pixt_ri_a, pixt_ri_b, pixt_ri_a, pixt_ri_b, pixt_ri_a, pixt_ri_b,
+ pixt_ri_a, pixt_ri_b, pixt_ri_a, pixt_ri_b, pixt_ri_a, pixt_ri_b, pixt_ri_a, pixt_ri_b,
+ /* 0xfa00 */
+ pixt_ir_a, pixt_ir_b, pixt_ir_a, pixt_ir_b, pixt_ir_a, pixt_ir_b, pixt_ir_a, pixt_ir_b,
+ pixt_ir_a, pixt_ir_b, pixt_ir_a, pixt_ir_b, pixt_ir_a, pixt_ir_b, pixt_ir_a, pixt_ir_b,
+ /* 0xfb00 */
+ pixt_ir_a, pixt_ir_b, pixt_ir_a, pixt_ir_b, pixt_ir_a, pixt_ir_b, pixt_ir_a, pixt_ir_b,
+ pixt_ir_a, pixt_ir_b, pixt_ir_a, pixt_ir_b, pixt_ir_a, pixt_ir_b, pixt_ir_a, pixt_ir_b,
+ /* 0xfc00 */
+ pixt_ii_a, pixt_ii_b, pixt_ii_a, pixt_ii_b, pixt_ii_a, pixt_ii_b, pixt_ii_a, pixt_ii_b,
+ pixt_ii_a, pixt_ii_b, pixt_ii_a, pixt_ii_b, pixt_ii_a, pixt_ii_b, pixt_ii_a, pixt_ii_b,
+ /* 0xfd00 */
+ pixt_ii_a, pixt_ii_b, pixt_ii_a, pixt_ii_b, pixt_ii_a, pixt_ii_b, pixt_ii_a, pixt_ii_b,
+ pixt_ii_a, pixt_ii_b, pixt_ii_a, pixt_ii_b, pixt_ii_a, pixt_ii_b, pixt_ii_a, pixt_ii_b,
+ /* 0xfe00 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ /* 0xff00 */
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl,
+ unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl, unimpl
+};
diff --git a/trunk/src/emu/cpu/tms34010/dis34010.c b/trunk/src/emu/cpu/tms34010/dis34010.c
new file mode 100644
index 00000000000..8e67de99624
--- /dev/null
+++ b/trunk/src/emu/cpu/tms34010/dis34010.c
@@ -0,0 +1,113 @@
+/* This program is based on DIS68k by Aaron Giles */
+
+#include "emu.h"
+
+static UINT8 *filebuf;
+static UINT32 offset;
+
+#define STANDALONE
+#include "34010dsm.c"
+
+
+static const char *const Options[]=
+{
+ "begin","end","offset",0
+};
+
+static void usage (void)
+{
+ printf ("Usage: DIS34010 [options] <filename>\n"
+ "Available options are:\n"
+ " -begin - Specify begin offset in file to disassemble in bits [0]\n"
+ " -end - Specify end offset in file to disassemble in bits [none]\n"
+ " -offset - Specify address to load program in bits [0]\n"
+ "All values should be entered in hexadecimal\n");
+ exit (1);
+}
+
+int main (int argc,char *argv[])
+{
+ UINT8 i,j,n;
+ char *filename=0,buf[80];
+ FILE *f;
+ UINT32 begin=0,end=(UINT32)-1,filelen,len,pc;
+ printf ("DIS34010\n"
+ "Copyright Zsolt Vasvari/Aaron Giles\n");
+
+ for (i=1,n=0;i<argc;++i)
+ {
+ if (argv[i][0]!='-')
+ {
+ switch (++n)
+ {
+ case 1: filename=argv[i]; break;
+ default: usage();
+ }
+ }
+ else
+ {
+ for (j=0;Options[j];++j)
+ if (!strcmp(argv[i]+1,Options[j])) break;
+
+ switch (j)
+ {
+ case 0: ++i; if (i>argc) usage();
+ begin=strtoul(argv[i],0,16) >> 3;
+ break;
+ case 1: ++i; if (i>argc) usage();
+ end=strtoul(argv[i],0,16) >> 3;
+ break;
+ case 2: ++i; if (i>argc) usage();
+ offset=strtoul(argv[i],0,16) >> 3;
+ break;
+ default: usage();
+ }
+ }
+ }
+
+ if (!filename)
+ {
+ usage();
+ return 1;
+ }
+ f=fopen (filename,"rb");
+ if (!f)
+ {
+ printf ("Unable to open %s\n",filename);
+ return 2;
+ }
+ fseek (f,0,SEEK_END);
+ filelen=ftell (f);
+ fseek (f,begin,SEEK_SET);
+ len=(filelen>end)? (end-begin+1):(filelen-begin);
+ filebuf=malloc(len+16);
+ if (!filebuf)
+ {
+ printf ("Memory allocation error\n");
+ fclose (f);
+ return 3;
+ }
+ memset (filebuf,0,len+16);
+ if (fread(filebuf,1,len,f)!=len)
+ {
+ printf ("Read error\n");
+ fclose (f);
+ free (filebuf);
+ return 4;
+ }
+ fclose (f);
+ pc=0;
+ while (pc<len-1)
+ {
+ i=(Dasm34010 (buf,pc<<3))>>3;
+
+ printf ("%08X: ",(pc+offset) << 3);
+ for (j=0;j<i ;++j) printf("%02X ",filebuf[pc+j]);
+ for ( ;j<10;++j) printf(" ");
+ printf(buf);
+ printf ("\n");
+ pc+=i;
+ }
+ free (filebuf);
+ return 0;
+}
diff --git a/trunk/src/emu/cpu/tms34010/makefile b/trunk/src/emu/cpu/tms34010/makefile
new file mode 100644
index 00000000000..9d2d0cedba9
--- /dev/null
+++ b/trunk/src/emu/cpu/tms34010/makefile
@@ -0,0 +1,6 @@
+dis34010.exe : dis34010.o -lalleg
+ gcc -m486 -O3 -ffast-math -fomit-frame-pointer -finline-functions dis34010.o -lalleg -o dis34010.exe
+
+dis34010.o : dis34010.c 34010dsm.c
+ gcc -c -m486 -O3 -ffast-math -fomit-frame-pointer -finline-functions -I/mame/src -I/mame/src/msdos dis34010.c
+
diff --git a/trunk/src/emu/cpu/tms34010/tms34010.c b/trunk/src/emu/cpu/tms34010/tms34010.c
new file mode 100644
index 00000000000..42f787213d3
--- /dev/null
+++ b/trunk/src/emu/cpu/tms34010/tms34010.c
@@ -0,0 +1,1791 @@
+/***************************************************************************
+
+ TMS34010: Portable Texas Instruments TMS34010 emulator
+
+ Copyright Alex Pasadyn/Zsolt Vasvari
+ Parts based on code by Aaron Giles
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "tms34010.h"
+
+
+/***************************************************************************
+ DEBUG STATE & STRUCTURES
+***************************************************************************/
+
+#define VERBOSE 0
+#define LOG_CONTROL_REGS 0
+#define LOG_GRAPHICS_OPS 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+
+
+/***************************************************************************
+ CORE STATE
+***************************************************************************/
+
+/* TMS34010 State */
+typedef struct _XY XY;
+struct _XY
+{
+#ifdef LSB_FIRST
+ INT16 x;
+ INT16 y;
+#else
+ INT16 y;
+ INT16 x;
+#endif
+};
+
+typedef struct _tms34010_state tms34010_state;
+struct _tms34010_state
+{
+ UINT32 pc;
+ UINT32 ppc;
+ UINT32 st;
+ void (*pixel_write)(tms34010_state *tms, offs_t offset, UINT32 data);
+ UINT32 (*pixel_read)(tms34010_state *tms, offs_t offset);
+ UINT32 (*raster_op)(tms34010_state *tms, UINT32 newpix, UINT32 oldpix);
+ UINT32 convsp;
+ UINT32 convdp;
+ UINT32 convmp;
+ UINT16 * shiftreg;
+ INT32 gfxcycles;
+ UINT8 pixelshift;
+ UINT8 is_34020;
+ UINT8 reset_deferred;
+ UINT8 hblank_stable;
+ UINT8 external_host_access;
+ UINT8 executing;
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ const tms34010_config *config;
+ screen_device *screen;
+ emu_timer * scantimer;
+ int icount;
+
+ /* A registers 0-15 map to regs[0]-regs[15] */
+ /* B registers 0-15 map to regs[30]-regs[15] */
+ union
+ {
+ INT32 reg;
+ XY xy;
+ } regs[31];
+
+ UINT16 IOregs[64];
+};
+
+INLINE tms34010_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == TMS34010 ||
+ device->type() == TMS34020);
+ return (tms34010_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+#include "34010ops.h"
+
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+/* default configuration */
+static const tms34010_config default_config =
+{
+ 0
+};
+
+static void check_interrupt(tms34010_state *tms);
+static TIMER_CALLBACK( scanline_callback );
+static void tms34010_state_postload(tms34010_state *tms);
+
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+/* status register definitions */
+#define STBIT_N (1 << 31)
+#define STBIT_C (1 << 30)
+#define STBIT_Z (1 << 29)
+#define STBIT_V (1 << 28)
+#define STBIT_P (1 << 25)
+#define STBIT_IE (1 << 21)
+#define STBIT_FE1 (1 << 11)
+#define STBITS_F1 (0x1f << 6)
+#define STBIT_FE0 (1 << 5)
+#define STBITS_F0 (0x1f << 0)
+
+/* register definitions and shortcuts */
+#define N_FLAG(T) ((T)->st & STBIT_N)
+#define Z_FLAG(T) ((T)->st & STBIT_Z)
+#define C_FLAG(T) ((T)->st & STBIT_C)
+#define V_FLAG(T) ((T)->st & STBIT_V)
+#define P_FLAG(T) ((T)->st & STBIT_P)
+#define IE_FLAG(T) ((T)->st & STBIT_IE)
+#define FE0_FLAG(T) ((T)->st & STBIT_FE0)
+#define FE1_FLAG(T) ((T)->st & STBIT_FE1)
+
+/* register file access */
+#define AREG(T,i) ((T)->regs[i].reg)
+#define AREG_XY(T,i) ((T)->regs[i].xy)
+#define AREG_X(T,i) ((T)->regs[i].xy.x)
+#define AREG_Y(T,i) ((T)->regs[i].xy.y)
+#define BREG(T,i) ((T)->regs[30 - (i)].reg)
+#define BREG_XY(T,i) ((T)->regs[30 - (i)].xy)
+#define BREG_X(T,i) ((T)->regs[30 - (i)].xy.x)
+#define BREG_Y(T,i) ((T)->regs[30 - (i)].xy.y)
+#define SP(T) AREG(T,15)
+#define FW(T,i) (((T)->st >> (i ? 6 : 0)) & 0x1f)
+#define FWEX(T,i) (((T)->st >> (i ? 6 : 0)) & 0x3f)
+
+/* opcode decode helpers */
+#define SRCREG(O) (((O) >> 5) & 0x0f)
+#define DSTREG(O) ((O) & 0x0f)
+#define SKIP_WORD(T) ((T)->pc += (2 << 3))
+#define SKIP_LONG(T) ((T)->pc += (4 << 3))
+#define PARAM_K(O) (((O) >> 5) & 0x1f)
+#define PARAM_N(O) ((O) & 0x1f)
+#define PARAM_REL8(O) ((INT8)(O))
+
+/* memory I/O */
+#define WFIELD0(T,a,b) (*tms34010_wfield_functions[FW(T,0)])(T,a,b)
+#define WFIELD1(T,a,b) (*tms34010_wfield_functions[FW(T,1)])(T,a,b)
+#define RFIELD0(T,a) (*tms34010_rfield_functions[FWEX(T,0)])(T,a)
+#define RFIELD1(T,a) (*tms34010_rfield_functions[FWEX(T,1)])(T,a)
+#define WPIXEL(T,a,b) (*(T)->pixel_write)(T,a,b)
+#define RPIXEL(T,a) (*(T)->pixel_read)(T,a)
+
+/* Implied Operands */
+#define SADDR(T) BREG(T,0)
+#define SADDR_X(T) BREG_X(T,0)
+#define SADDR_Y(T) BREG_Y(T,0)
+#define SADDR_XY(T) BREG_XY(T,0)
+#define SPTCH(T) BREG(T,1)
+#define DADDR(T) BREG(T,2)
+#define DADDR_X(T) BREG_X(T,2)
+#define DADDR_Y(T) BREG_Y(T,2)
+#define DADDR_XY(T) BREG_XY(T,2)
+#define DPTCH(T) BREG(T,3)
+#define OFFSET(T) BREG(T,4)
+#define WSTART_X(T) BREG_X(T,5)
+#define WSTART_Y(T) BREG_Y(T,5)
+#define WEND_X(T) BREG_X(T,6)
+#define WEND_Y(T) BREG_Y(T,6)
+#define DYDX_X(T) BREG_X(T,7)
+#define DYDX_Y(T) BREG_Y(T,7)
+#define COLOR0(T) BREG(T,8)
+#define COLOR1(T) BREG(T,9)
+#define COUNT(T) BREG(T,10)
+#define INC1_X(T) BREG_X(T,11)
+#define INC1_Y(T) BREG_Y(T,11)
+#define INC2_X(T) BREG_X(T,12)
+#define INC2_Y(T) BREG_Y(T,12)
+#define PATTRN(T) BREG(T,13)
+#define TEMP(T) BREG(T,14)
+
+/* I/O registers */
+#define WINDOW_CHECKING(T) ((IOREG(T, REG_CONTROL) >> 6) & 0x03)
+
+
+
+/***************************************************************************
+ INLINE SHORTCUTS
+***************************************************************************/
+
+/* Break up Status Register into indiviual flags */
+INLINE void SET_ST(tms34010_state *tms, UINT32 st)
+{
+ tms->st = st;
+ /* interrupts might have been enabled, check it */
+ check_interrupt(tms);
+}
+
+/* Intialize Status to 0x0010 */
+INLINE void RESET_ST(tms34010_state *tms)
+{
+ SET_ST(tms, 0x00000010);
+}
+
+/* shortcuts for reading opcodes */
+INLINE UINT32 ROPCODE(tms34010_state *tms)
+{
+ UINT32 pc = TOBYTE(tms->pc);
+ tms->pc += 2 << 3;
+ return tms->direct->read_decrypted_word(pc);
+}
+
+INLINE INT16 PARAM_WORD(tms34010_state *tms)
+{
+ UINT32 pc = TOBYTE(tms->pc);
+ tms->pc += 2 << 3;
+ return tms->direct->read_raw_word(pc);
+}
+
+INLINE INT32 PARAM_LONG(tms34010_state *tms)
+{
+ UINT32 pc = TOBYTE(tms->pc);
+ tms->pc += 4 << 3;
+ return (UINT16)tms->direct->read_raw_word(pc) | (tms->direct->read_raw_word(pc + 2) << 16);
+}
+
+INLINE INT16 PARAM_WORD_NO_INC(tms34010_state *tms)
+{
+ return tms->direct->read_raw_word(TOBYTE(tms->pc));
+}
+
+INLINE INT32 PARAM_LONG_NO_INC(tms34010_state *tms)
+{
+ UINT32 pc = TOBYTE(tms->pc);
+ return (UINT16)tms->direct->read_raw_word(pc) | (tms->direct->read_raw_word(pc + 2) << 16);
+}
+
+/* read memory byte */
+INLINE UINT32 RBYTE(tms34010_state *tms, offs_t offset)
+{
+ UINT32 ret;
+ RFIELDMAC_8(tms);
+ return ret;
+}
+
+/* write memory byte */
+INLINE void WBYTE(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC_8(tms);
+}
+
+/* read memory long */
+INLINE UINT32 RLONG(tms34010_state *tms, offs_t offset)
+{
+ RFIELDMAC_32(tms);
+}
+
+/* write memory long */
+INLINE void WLONG(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ WFIELDMAC_32(tms);
+}
+
+/* pushes/pops a value from the stack */
+INLINE void PUSH(tms34010_state *tms, UINT32 data)
+{
+ SP(tms) -= 0x20;
+ WLONG(tms, SP(tms), data);
+}
+
+INLINE INT32 POP(tms34010_state *tms)
+{
+ INT32 ret = RLONG(tms, SP(tms));
+ SP(tms) += 0x20;
+ return ret;
+}
+
+
+
+/***************************************************************************
+ PIXEL READS
+***************************************************************************/
+
+#define RP(T,m1,m2) \
+ /* TODO: Plane masking */ \
+ return (TMS34010_RDMEM_WORD(T, TOBYTE(offset & 0xfffffff0)) >> (offset & m1)) & m2;
+
+static UINT32 read_pixel_1(tms34010_state *tms, offs_t offset) { RP(tms,0x0f,0x01) }
+static UINT32 read_pixel_2(tms34010_state *tms, offs_t offset) { RP(tms,0x0e,0x03) }
+static UINT32 read_pixel_4(tms34010_state *tms, offs_t offset) { RP(tms,0x0c,0x0f) }
+static UINT32 read_pixel_8(tms34010_state *tms, offs_t offset) { RP(tms,0x08,0xff) }
+static UINT32 read_pixel_16(tms34010_state *tms, offs_t offset)
+{
+ /* TODO: Plane masking */
+ return TMS34010_RDMEM_WORD(tms, TOBYTE(offset & 0xfffffff0));
+}
+static UINT32 read_pixel_32(tms34010_state *tms, offs_t offset)
+{
+ /* TODO: Plane masking */
+ return TMS34010_RDMEM_DWORD(tms, TOBYTE(offset & 0xffffffe0));
+}
+
+/* Shift register read */
+static UINT32 read_pixel_shiftreg(tms34010_state *tms, offs_t offset)
+{
+ if (tms->config->to_shiftreg)
+ tms->config->to_shiftreg(tms->program, offset, &tms->shiftreg[0]);
+ else
+ fatalerror("To ShiftReg function not set. PC = %08X\n", tms->pc);
+ return tms->shiftreg[0];
+}
+
+
+
+/***************************************************************************
+ PIXEL WRITES
+***************************************************************************/
+
+/* No Raster Op + No Transparency */
+#define WP(T,m1,m2) \
+ UINT32 a = TOBYTE(offset & 0xfffffff0); \
+ UINT32 pix = TMS34010_RDMEM_WORD(T,a); \
+ UINT32 shiftcount = offset & m1; \
+ \
+ /* TODO: plane masking */ \
+ data &= m2; \
+ pix = (pix & ~(m2 << shiftcount)) | (data << shiftcount); \
+ TMS34010_WRMEM_WORD(T, a, pix); \
+
+/* No Raster Op + Transparency */
+#define WP_T(T,m1,m2) \
+ /* TODO: plane masking */ \
+ data &= m2; \
+ if (data) \
+ { \
+ UINT32 a = TOBYTE(offset & 0xfffffff0); \
+ UINT32 pix = TMS34010_RDMEM_WORD(T,a); \
+ UINT32 shiftcount = offset & m1; \
+ \
+ /* TODO: plane masking */ \
+ pix = (pix & ~(m2 << shiftcount)) | (data << shiftcount); \
+ TMS34010_WRMEM_WORD(T, a, pix); \
+ } \
+
+/* Raster Op + No Transparency */
+#define WP_R(T,m1,m2) \
+ UINT32 a = TOBYTE(offset & 0xfffffff0); \
+ UINT32 pix = TMS34010_RDMEM_WORD(T,a); \
+ UINT32 shiftcount = offset & m1; \
+ \
+ /* TODO: plane masking */ \
+ data = (*(T)->raster_op)(tms, data & m2, (pix >> shiftcount) & m2) & m2; \
+ pix = (pix & ~(m2 << shiftcount)) | (data << shiftcount); \
+ TMS34010_WRMEM_WORD(T, a, pix); \
+
+/* Raster Op + Transparency */
+#define WP_R_T(T,m1,m2) \
+ UINT32 a = TOBYTE(offset & 0xfffffff0); \
+ UINT32 pix = TMS34010_RDMEM_WORD(T,a); \
+ UINT32 shiftcount = offset & m1; \
+ \
+ /* TODO: plane masking */ \
+ data = (*(T)->raster_op)(tms, data & m2, (pix >> shiftcount) & m2) & m2; \
+ if (data) \
+ { \
+ pix = (pix & ~(m2 << shiftcount)) | (data << shiftcount); \
+ TMS34010_WRMEM_WORD(T, a, pix); \
+ } \
+
+
+/* No Raster Op + No Transparency */
+static void write_pixel_1(tms34010_state *tms, offs_t offset, UINT32 data) { WP(tms, 0x0f, 0x01); }
+static void write_pixel_2(tms34010_state *tms, offs_t offset, UINT32 data) { WP(tms, 0x0e, 0x03); }
+static void write_pixel_4(tms34010_state *tms, offs_t offset, UINT32 data) { WP(tms, 0x0c, 0x0f); }
+static void write_pixel_8(tms34010_state *tms, offs_t offset, UINT32 data) { WP(tms, 0x08, 0xff); }
+static void write_pixel_16(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ /* TODO: plane masking */
+ TMS34010_WRMEM_WORD(tms, TOBYTE(offset & 0xfffffff0), data);
+}
+static void write_pixel_32(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ /* TODO: plane masking */
+ TMS34010_WRMEM_WORD(tms, TOBYTE(offset & 0xffffffe0), data);
+}
+
+/* No Raster Op + Transparency */
+static void write_pixel_t_1(tms34010_state *tms, offs_t offset, UINT32 data) { WP_T(tms, 0x0f, 0x01); }
+static void write_pixel_t_2(tms34010_state *tms, offs_t offset, UINT32 data) { WP_T(tms, 0x0e, 0x03); }
+static void write_pixel_t_4(tms34010_state *tms, offs_t offset, UINT32 data) { WP_T(tms, 0x0c, 0x0f); }
+static void write_pixel_t_8(tms34010_state *tms, offs_t offset, UINT32 data) { WP_T(tms, 0x08, 0xff); }
+static void write_pixel_t_16(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ /* TODO: plane masking */
+ if (data)
+ TMS34010_WRMEM_WORD(tms, TOBYTE(offset & 0xfffffff0), data);
+}
+static void write_pixel_t_32(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ /* TODO: plane masking */
+ if (data)
+ TMS34010_WRMEM_DWORD(tms, TOBYTE(offset & 0xffffffe0), data);
+}
+
+/* Raster Op + No Transparency */
+static void write_pixel_r_1(tms34010_state *tms, offs_t offset, UINT32 data) { WP_R(tms, 0x0f, 0x01); }
+static void write_pixel_r_2(tms34010_state *tms, offs_t offset, UINT32 data) { WP_R(tms, 0x0e, 0x03); }
+static void write_pixel_r_4(tms34010_state *tms, offs_t offset, UINT32 data) { WP_R(tms, 0x0c, 0x0f); }
+static void write_pixel_r_8(tms34010_state *tms, offs_t offset, UINT32 data) { WP_R(tms, 0x08, 0xff); }
+static void write_pixel_r_16(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ /* TODO: plane masking */
+ UINT32 a = TOBYTE(offset & 0xfffffff0);
+ TMS34010_WRMEM_WORD(tms, a, (*tms->raster_op)(tms, data, TMS34010_RDMEM_WORD(tms, a)));
+}
+static void write_pixel_r_32(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ /* TODO: plane masking */
+ UINT32 a = TOBYTE(offset & 0xffffffe0);
+ TMS34010_WRMEM_DWORD(tms, a, (*tms->raster_op)(tms, data, TMS34010_RDMEM_DWORD(tms, a)));
+}
+
+/* Raster Op + Transparency */
+static void write_pixel_r_t_1(tms34010_state *tms, offs_t offset, UINT32 data) { WP_R_T(tms, 0x0f,0x01); }
+static void write_pixel_r_t_2(tms34010_state *tms, offs_t offset, UINT32 data) { WP_R_T(tms, 0x0e,0x03); }
+static void write_pixel_r_t_4(tms34010_state *tms, offs_t offset, UINT32 data) { WP_R_T(tms, 0x0c,0x0f); }
+static void write_pixel_r_t_8(tms34010_state *tms, offs_t offset, UINT32 data) { WP_R_T(tms, 0x08,0xff); }
+static void write_pixel_r_t_16(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ /* TODO: plane masking */
+ UINT32 a = TOBYTE(offset & 0xfffffff0);
+ data = (*tms->raster_op)(tms, data, TMS34010_RDMEM_WORD(tms, a));
+
+ if (data)
+ TMS34010_WRMEM_WORD(tms, a, data);
+}
+static void write_pixel_r_t_32(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ /* TODO: plane masking */
+ UINT32 a = TOBYTE(offset & 0xffffffe0);
+ data = (*tms->raster_op)(tms, data, TMS34010_RDMEM_DWORD(tms, a));
+
+ if (data)
+ TMS34010_WRMEM_DWORD(tms, a, data);
+}
+
+/* Shift register write */
+static void write_pixel_shiftreg(tms34010_state *tms, offs_t offset, UINT32 data)
+{
+ if (tms->config->from_shiftreg)
+ tms->config->from_shiftreg(tms->program, offset, &tms->shiftreg[0]);
+ else
+ fatalerror("From ShiftReg function not set. PC = %08X\n", tms->pc);
+}
+
+
+
+/***************************************************************************
+ RASTER OPS
+***************************************************************************/
+
+/* Raster operations */
+static UINT32 raster_op_1(tms34010_state *tms, UINT32 newpix, UINT32 oldpix) { return newpix & oldpix; }
+static UINT32 raster_op_2(tms34010_state *tms, UINT32 newpix, UINT32 oldpix) { return newpix & ~oldpix; }
+static UINT32 raster_op_3(tms34010_state *tms, UINT32 newpix, UINT32 oldpix) { return 0; }
+static UINT32 raster_op_4(tms34010_state *tms, UINT32 newpix, UINT32 oldpix) { return newpix | ~oldpix; }
+static UINT32 raster_op_5(tms34010_state *tms, UINT32 newpix, UINT32 oldpix) { return ~(newpix ^ oldpix); }
+static UINT32 raster_op_6(tms34010_state *tms, UINT32 newpix, UINT32 oldpix) { return ~oldpix; }
+static UINT32 raster_op_7(tms34010_state *tms, UINT32 newpix, UINT32 oldpix) { return ~(newpix | oldpix); }
+static UINT32 raster_op_8(tms34010_state *tms, UINT32 newpix, UINT32 oldpix) { return newpix | oldpix; }
+static UINT32 raster_op_9(tms34010_state *tms, UINT32 newpix, UINT32 oldpix) { return oldpix; }
+static UINT32 raster_op_10(tms34010_state *tms, UINT32 newpix, UINT32 oldpix) { return newpix ^ oldpix; }
+static UINT32 raster_op_11(tms34010_state *tms, UINT32 newpix, UINT32 oldpix) { return ~newpix & oldpix; }
+static UINT32 raster_op_12(tms34010_state *tms, UINT32 newpix, UINT32 oldpix) { return 0xffff; }
+static UINT32 raster_op_13(tms34010_state *tms, UINT32 newpix, UINT32 oldpix) { return ~newpix | oldpix; }
+static UINT32 raster_op_14(tms34010_state *tms, UINT32 newpix, UINT32 oldpix) { return ~(newpix & oldpix); }
+static UINT32 raster_op_15(tms34010_state *tms, UINT32 newpix, UINT32 oldpix) { return ~newpix; }
+static UINT32 raster_op_16(tms34010_state *tms, UINT32 newpix, UINT32 oldpix) { return newpix + oldpix; }
+static UINT32 raster_op_17(tms34010_state *tms, UINT32 newpix, UINT32 oldpix)
+{
+ UINT32 max = (UINT32)0xffffffff >> (32 - IOREG(tms, REG_PSIZE));
+ UINT32 res = newpix + oldpix;
+ return (res > max) ? max : res;
+}
+static UINT32 raster_op_18(tms34010_state *tms, UINT32 newpix, UINT32 oldpix) { return oldpix - newpix; }
+static UINT32 raster_op_19(tms34010_state *tms, UINT32 newpix, UINT32 oldpix) { return (oldpix > newpix) ? oldpix - newpix : 0; }
+static UINT32 raster_op_20(tms34010_state *tms, UINT32 newpix, UINT32 oldpix) { return (oldpix > newpix) ? oldpix : newpix; }
+static UINT32 raster_op_21(tms34010_state *tms, UINT32 newpix, UINT32 oldpix) { return (oldpix > newpix) ? newpix : oldpix; }
+
+
+
+/***************************************************************************
+ OPCODE TABLE & IMPLEMENTATIONS
+***************************************************************************/
+
+#include "34010fld.c"
+
+/* includes the static function prototypes and the master opcode table */
+#include "34010tbl.c"
+
+/* includes the actual opcode implementations */
+#include "34010ops.c"
+#include "34010gfx.c"
+
+
+
+/***************************************************************************
+ Internal interrupt check
+****************************************************************************/
+
+/* Generate pending interrupts. */
+static void check_interrupt(tms34010_state *tms)
+{
+ int vector = 0;
+ int irqline = -1;
+ int irq;
+
+ /* if we're not actively executing, skip it */
+ if (!tms->executing)
+ return;
+
+ /* check for NMI first */
+ if (IOREG(tms, REG_HSTCTLH) & 0x0100)
+ {
+ LOG(("TMS34010 '%s' takes NMI\n", tms->device->tag()));
+
+ /* ack the NMI */
+ IOREG(tms, REG_HSTCTLH) &= ~0x0100;
+
+ /* handle NMI mode bit */
+ if (!(IOREG(tms, REG_HSTCTLH) & 0x0200))
+ {
+ PUSH(tms, tms->pc);
+ PUSH(tms, tms->st);
+ }
+
+ /* leap to the vector */
+ RESET_ST(tms);
+ tms->pc = RLONG(tms, 0xfffffee0);
+ COUNT_CYCLES(tms,16);
+ return;
+ }
+
+ /* early out if everything else is disabled */
+ irq = IOREG(tms, REG_INTPEND) & IOREG(tms, REG_INTENB);
+ if (!IE_FLAG(tms) || !irq)
+ return;
+
+ /* host interrupt */
+ if (irq & TMS34010_HI)
+ {
+ LOG(("TMS34010 '%s' takes HI\n", tms->device->tag()));
+ vector = 0xfffffec0;
+ }
+
+ /* display interrupt */
+ else if (irq & TMS34010_DI)
+ {
+ LOG(("TMS34010 '%s' takes DI\n", tms->device->tag()));
+ vector = 0xfffffea0;
+ }
+
+ /* window violation interrupt */
+ else if (irq & TMS34010_WV)
+ {
+ LOG(("TMS34010 '%s' takes WV\n", tms->device->tag()));
+ vector = 0xfffffe80;
+ }
+
+ /* external 1 interrupt */
+ else if (irq & TMS34010_INT1)
+ {
+ LOG(("TMS34010 '%s' takes INT1\n", tms->device->tag()));
+ vector = 0xffffffc0;
+ irqline = 0;
+ }
+
+ /* external 2 interrupt */
+ else if (irq & TMS34010_INT2)
+ {
+ LOG(("TMS34010 '%s' takes INT2\n", tms->device->tag()));
+ vector = 0xffffffa0;
+ irqline = 1;
+ }
+
+ /* if we took something, generate it */
+ if (vector)
+ {
+ PUSH(tms, tms->pc);
+ PUSH(tms, tms->st);
+ RESET_ST(tms);
+ tms->pc = RLONG(tms, vector);
+ COUNT_CYCLES(tms,16);
+
+ /* call the callback for externals */
+ if (irqline >= 0)
+ (void)(*tms->irq_callback)(tms->device, irqline);
+ }
+}
+
+
+
+/***************************************************************************
+ Reset the CPU emulation
+***************************************************************************/
+
+static CPU_INIT( tms34010 )
+{
+ const tms34010_config *configdata = device->static_config() ? (const tms34010_config *)device->static_config() : &default_config;
+ tms34010_state *tms = get_safe_token(device);
+
+ tms->external_host_access = FALSE;
+
+ tms->config = configdata;
+ tms->irq_callback = irqcallback;
+ tms->device = device;
+ tms->program = device->space(AS_PROGRAM);
+ tms->direct = &tms->program->direct();
+ tms->screen = downcast<screen_device *>(device->machine().device(configdata->screen_tag));
+
+ /* set up the state table */
+ {
+ device_state_interface *state;
+ device->interface(state);
+ state->state_add(TMS34010_PC, "PC", tms->pc);
+ state->state_add(STATE_GENPC, "GENPC", tms->pc).noshow();
+ state->state_add(STATE_GENPCBASE, "GENPCBASE", tms->ppc).noshow();
+ state->state_add(TMS34010_SP, "SP", tms->regs[15].reg);
+ state->state_add(STATE_GENSP, "GENSP", tms->regs[15].reg).noshow();
+ state->state_add(TMS34010_ST, "ST", tms->st);
+ state->state_add(STATE_GENFLAGS, "GENFLAGS", tms->st).noshow().formatstr("%18s");
+
+ astring tempstr;
+ for (int regnum = 0; regnum < 15; regnum++)
+ state->state_add(TMS34010_A0 + regnum, tempstr.format("A%d", regnum), tms->regs[regnum].reg);
+ for (int regnum = 0; regnum < 15; regnum++)
+ state->state_add(TMS34010_B0 + regnum, tempstr.format("B%d", regnum), tms->regs[30 - regnum].reg);
+ }
+
+ /* allocate a scanline timer and set it to go off at the start */
+ tms->scantimer = device->machine().scheduler().timer_alloc(FUNC(scanline_callback), tms);
+ tms->scantimer->adjust(attotime::zero);
+
+ /* allocate the shiftreg */
+ tms->shiftreg = auto_alloc_array(device->machine(), UINT16, SHIFTREG_SIZE/2);
+
+ device->save_item(NAME(tms->pc));
+ device->save_item(NAME(tms->st));
+ device->save_item(NAME(tms->reset_deferred));
+ device->save_pointer(NAME(tms->shiftreg), SHIFTREG_SIZE / 2);
+ device->save_item(NAME(tms->IOregs));
+ device->save_item(NAME(tms->convsp));
+ device->save_item(NAME(tms->convdp));
+ device->save_item(NAME(tms->convmp));
+ device->save_item(NAME(tms->pixelshift));
+ device->save_item(NAME(tms->gfxcycles));
+ device->save_pointer(NAME(&tms->regs[0].reg), ARRAY_LENGTH(tms->regs));
+ device->machine().save().register_postload(save_prepost_delegate(FUNC(tms34010_state_postload), tms));
+}
+
+static CPU_RESET( tms34010 )
+{
+ /* zap the state and copy in the config pointer */
+ tms34010_state *tms = get_safe_token(device);
+ const tms34010_config *config = tms->config;
+ screen_device *screen = tms->screen;
+ UINT16 *shiftreg = tms->shiftreg;
+ device_irq_callback save_irqcallback = tms->irq_callback;
+ emu_timer *save_scantimer = tms->scantimer;
+
+ memset(tms, 0, sizeof(*tms));
+
+ tms->config = config;
+ tms->screen = screen;
+ tms->shiftreg = shiftreg;
+ tms->irq_callback = save_irqcallback;
+ tms->scantimer = save_scantimer;
+ tms->device = device;
+ tms->program = device->space(AS_PROGRAM);
+ tms->direct = &tms->program->direct();
+
+ /* fetch the initial PC and reset the state */
+ tms->pc = RLONG(tms, 0xffffffe0) & 0xfffffff0;
+ RESET_ST(tms);
+
+ /* HALT the CPU if requested, and remember to re-read the starting PC */
+ /* the first time we are run */
+ tms->reset_deferred = tms->config->halt_on_reset;
+ if (tms->config->halt_on_reset)
+ tms34010_io_register_w(device->space(AS_PROGRAM), REG_HSTCTLH, 0x8000, 0xffff);
+}
+
+
+static CPU_RESET( tms34020 )
+{
+ tms34010_state *tms = get_safe_token(device);
+ CPU_RESET_CALL(tms34010);
+ tms->is_34020 = 1;
+}
+
+
+
+/***************************************************************************
+ Shut down the CPU emulation
+***************************************************************************/
+
+static CPU_EXIT( tms34010 )
+{
+ tms34010_state *tms = get_safe_token(device);
+ tms->shiftreg = NULL;
+}
+
+
+
+/***************************************************************************
+ Set IRQ line state
+***************************************************************************/
+
+static void set_irq_line(tms34010_state *tms, int irqline, int linestate)
+{
+ LOG(("TMS34010 '%s' set irq line %d state %d\n", tms->device->tag(), irqline, linestate));
+
+ /* set the pending interrupt */
+ switch (irqline)
+ {
+ case 0:
+ if (linestate != CLEAR_LINE)
+ IOREG(tms, REG_INTPEND) |= TMS34010_INT1;
+ else
+ IOREG(tms, REG_INTPEND) &= ~TMS34010_INT1;
+ break;
+
+ case 1:
+ if (linestate != CLEAR_LINE)
+ IOREG(tms, REG_INTPEND) |= TMS34010_INT2;
+ else
+ IOREG(tms, REG_INTPEND) &= ~TMS34010_INT2;
+ break;
+ }
+}
+
+
+
+/***************************************************************************
+ Generate internal interrupt
+***************************************************************************/
+
+static TIMER_CALLBACK( internal_interrupt_callback )
+{
+ tms34010_state *tms = (tms34010_state *)ptr;
+ int type = param;
+
+ /* call through to the CPU to generate the int */
+ IOREG(tms, REG_INTPEND) |= type;
+ LOG(("TMS34010 '%s' set internal interrupt $%04x\n", tms->device->tag(), type));
+
+ /* generate triggers so that spin loops can key off them */
+ device_triggerint(tms->device);
+}
+
+
+
+/***************************************************************************
+ Execute
+***************************************************************************/
+
+static CPU_EXECUTE( tms34010 )
+{
+ tms34010_state *tms = get_safe_token(device);
+
+ /* Get out if CPU is halted. Absolutely no interrupts must be taken!!! */
+ if (IOREG(tms, REG_HSTCTLH) & 0x8000)
+ {
+ tms->icount = 0;
+ return;
+ }
+
+ /* if the CPU's reset was deferred, do it now */
+ if (tms->reset_deferred)
+ {
+ tms->reset_deferred = 0;
+ tms->pc = RLONG(tms, 0xffffffe0);
+ }
+
+ /* check interrupts first */
+ tms->executing = TRUE;
+ check_interrupt(tms);
+ if ((tms->device->machine().debug_flags & DEBUG_FLAG_ENABLED) == 0)
+ {
+ do
+ {
+ UINT16 op;
+ tms->ppc = tms->pc;
+ op = ROPCODE(tms);
+ (*opcode_table[op >> 4])(tms, op);
+ } while (tms->icount > 0);
+ }
+ else
+ {
+ do
+ {
+ UINT16 op;
+ debugger_instruction_hook(tms->device, tms->pc);
+ tms->ppc = tms->pc;
+ op = ROPCODE(tms);
+ (*opcode_table[op >> 4])(tms, op);
+ } while (tms->icount > 0);
+ }
+ tms->executing = FALSE;
+}
+
+
+
+/***************************************************************************
+ PIXEL OPS
+***************************************************************************/
+
+static void (*const pixel_write_ops[4][6])(tms34010_state *tms, offs_t offset, UINT32 data) =
+{
+ { write_pixel_1, write_pixel_2, write_pixel_4, write_pixel_8, write_pixel_16, write_pixel_32 },
+ { write_pixel_r_1, write_pixel_r_2, write_pixel_r_4, write_pixel_r_8, write_pixel_r_16, write_pixel_r_32 },
+ { write_pixel_t_1, write_pixel_t_2, write_pixel_t_4, write_pixel_t_8, write_pixel_t_16, write_pixel_t_32 },
+ { write_pixel_r_t_1, write_pixel_r_t_2, write_pixel_r_t_4, write_pixel_r_t_8, write_pixel_r_t_16, write_pixel_r_t_32 }
+};
+
+static UINT32 (*const pixel_read_ops[6])(tms34010_state *tms, offs_t offset) =
+{
+ read_pixel_1, read_pixel_2, read_pixel_4, read_pixel_8, read_pixel_16, read_pixel_32
+};
+
+
+static void set_pixel_function(tms34010_state *tms)
+{
+ UINT32 i1,i2;
+
+ if (IOREG(tms, REG_DPYCTL) & 0x0800)
+ {
+ /* Shift Register Transfer */
+ tms->pixel_write = write_pixel_shiftreg;
+ tms->pixel_read = read_pixel_shiftreg;
+ return;
+ }
+
+ switch (IOREG(tms, REG_PSIZE))
+ {
+ default:
+ case 0x01: i2 = 0; break;
+ case 0x02: i2 = 1; break;
+ case 0x04: i2 = 2; break;
+ case 0x08: i2 = 3; break;
+ case 0x10: i2 = 4; break;
+ case 0x20: i2 = 5; break;
+ }
+
+ if (IOREG(tms, REG_CONTROL) & 0x20)
+ i1 = tms->raster_op ? 3 : 2;
+ else
+ i1 = tms->raster_op ? 1 : 0;
+
+ tms->pixel_write = pixel_write_ops[i1][i2];
+ tms->pixel_read = pixel_read_ops [i2];
+}
+
+
+
+/***************************************************************************
+ RASTER OPS
+***************************************************************************/
+
+static UINT32 (*const raster_ops[32]) (tms34010_state *tms, UINT32 newpix, UINT32 oldpix) =
+{
+ 0, raster_op_1 , raster_op_2 , raster_op_3,
+ raster_op_4 , raster_op_5 , raster_op_6 , raster_op_7,
+ raster_op_8 , raster_op_9 , raster_op_10, raster_op_11,
+ raster_op_12, raster_op_13, raster_op_14, raster_op_15,
+ raster_op_16, raster_op_17, raster_op_18, raster_op_19,
+ raster_op_20, raster_op_21, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+};
+
+
+static void set_raster_op(tms34010_state *tms)
+{
+ tms->raster_op = raster_ops[(IOREG(tms, REG_CONTROL) >> 10) & 0x1f];
+}
+
+
+
+/***************************************************************************
+ VIDEO TIMING HELPERS
+***************************************************************************/
+
+static TIMER_CALLBACK( scanline_callback )
+{
+ tms34010_state *tms = (tms34010_state *)ptr;
+ int vsblnk, veblnk, vtotal;
+ int vcount = param;
+ int enabled;
+ int master;
+
+ /* fetch the core timing parameters */
+ const rectangle &current_visarea = tms->screen->visible_area();
+ enabled = SMART_IOREG(tms, DPYCTL) & 0x8000;
+ master = (tms->is_34020 || (SMART_IOREG(tms, DPYCTL) & 0x2000));
+ vsblnk = SMART_IOREG(tms, VSBLNK);
+ veblnk = SMART_IOREG(tms, VEBLNK);
+ vtotal = SMART_IOREG(tms, VTOTAL);
+ if (!master)
+ {
+ vtotal = MIN(tms->screen->height() - 1, vtotal);
+ vcount = tms->screen->vpos();
+ }
+
+ /* update the VCOUNT */
+ SMART_IOREG(tms, VCOUNT) = vcount;
+
+ /* if we match the display interrupt scanline, signal an interrupt */
+ if (enabled && vcount == SMART_IOREG(tms, DPYINT))
+ {
+ /* generate the display interrupt signal */
+ internal_interrupt_callback(machine, tms, TMS34010_DI);
+ }
+
+ /* at the start of VBLANK, load the starting display address */
+ if (vcount == vsblnk)
+ {
+ /* 34010 loads DPYADR with DPYSTRT, and inverts if the origin is 0 */
+ if (!tms->is_34020)
+ {
+ IOREG(tms, REG_DPYADR) = IOREG(tms, REG_DPYSTRT);
+ LOG(("Start of VBLANK, DPYADR = %04X\n", IOREG(tms, REG_DPYADR)));
+ }
+
+ /* 34020 loads DPYNXx with DPYSTx */
+ else
+ {
+ IOREG(tms, REG020_DPYNXL) = IOREG(tms, REG020_DPYSTL) & 0xffe0;
+ IOREG(tms, REG020_DPYNXH) = IOREG(tms, REG020_DPYSTH);
+ }
+ }
+
+ /* at the end of the screen, update the display parameters */
+ if (vcount == vtotal)
+ {
+ /* only do this if we have an incoming pixel clock */
+ /* also, only do it if the HEBLNK/HSBLNK values are stable */
+ if (master && tms->config->scanline_callback != NULL)
+ {
+ int htotal = SMART_IOREG(tms, HTOTAL);
+ if (htotal > 0 && vtotal > 0)
+ {
+ attoseconds_t refresh = HZ_TO_ATTOSECONDS(tms->config->pixclock) * (htotal + 1) * (vtotal + 1);
+ int width = (htotal + 1) * tms->config->pixperclock;
+ int height = vtotal + 1;
+ rectangle visarea;
+
+ /* extract the visible area */
+ visarea.min_x = SMART_IOREG(tms, HEBLNK) * tms->config->pixperclock;
+ visarea.max_x = SMART_IOREG(tms, HSBLNK) * tms->config->pixperclock - 1;
+ visarea.min_y = veblnk;
+ visarea.max_y = vsblnk - 1;
+
+ /* if everything looks good, set the info */
+ if (visarea.min_x < visarea.max_x && visarea.max_x <= width && visarea.min_y < visarea.max_y && visarea.max_y <= height)
+ {
+ /* because many games play with the HEBLNK/HSBLNK for effects, we don't change
+ if they are the only thing that has changed, unless they are stable for a couple
+ of frames */
+ int current_width = tms->screen->width();
+ int current_height = tms->screen->height();
+
+ if (width != current_width || height != current_height || visarea.min_y != current_visarea.min_y || visarea.max_y != current_visarea.max_y ||
+ (tms->hblank_stable > 2 && (visarea.min_x != current_visarea.min_x || visarea.max_x != current_visarea.max_x)))
+ {
+ tms->screen->configure(width, height, visarea, refresh);
+ }
+ tms->hblank_stable++;
+ }
+
+ LOG(("Configuring screen: HTOTAL=%3d BLANK=%3d-%3d VTOTAL=%3d BLANK=%3d-%3d refresh=%f\n",
+ htotal, SMART_IOREG(tms, HEBLNK), SMART_IOREG(tms, HSBLNK), vtotal, veblnk, vsblnk, ATTOSECONDS_TO_HZ(refresh)));
+
+ /* interlaced timing not supported */
+ if ((SMART_IOREG(tms, DPYCTL) & 0x4000) == 0)
+ fatalerror("Interlaced video configured on the TMS34010 (unsupported)");
+ }
+ }
+ }
+
+ /* force a partial update within the visible area */
+ if (vcount >= current_visarea.min_y && vcount <= current_visarea.max_y && tms->config->scanline_callback != NULL)
+ tms->screen->update_partial(vcount);
+
+ /* if we are in the visible area, increment DPYADR by DUDATE */
+ if (vcount >= veblnk && vcount < vsblnk)
+ {
+ /* 34010 increments by the DUDATE field in DPYCTL */
+ if (!tms->is_34020)
+ {
+ UINT16 dpyadr = IOREG(tms, REG_DPYADR);
+ if ((dpyadr & 3) == 0)
+ dpyadr = ((dpyadr & 0xfffc) - (IOREG(tms, REG_DPYCTL) & 0x03fc)) | (IOREG(tms, REG_DPYSTRT) & 0x0003);
+ else
+ dpyadr = (dpyadr & 0xfffc) | ((dpyadr - 1) & 3);
+ IOREG(tms, REG_DPYADR) = dpyadr;
+ }
+
+ /* 34020 updates based on the DINC register, including zoom */
+ else
+ {
+ UINT32 dpynx = IOREG(tms, REG020_DPYNXL) | (IOREG(tms, REG020_DPYNXH) << 16);
+ UINT32 dinc = IOREG(tms, REG020_DINCL) | (IOREG(tms, REG020_DINCH) << 16);
+ dpynx = (dpynx & 0xffffffe0) | ((dpynx + dinc) & 0x1f);
+ if ((dpynx & 0x1f) == 0)
+ dpynx += dinc & 0xffffffe0;
+ IOREG(tms, REG020_DPYNXL) = dpynx;
+ IOREG(tms, REG020_DPYNXH) = dpynx >> 16;
+ }
+ }
+
+ /* adjust for the next callback */
+ vcount++;
+ if (vcount > vtotal)
+ vcount = 0;
+
+ /* note that we add !master (0 or 1) as a attoseconds value; this makes no practical difference */
+ /* but helps ensure that masters are updated first before slaves */
+ tms->scantimer->adjust(tms->screen->time_until_pos(vcount) + attotime(0, !master), vcount);
+}
+
+
+void tms34010_get_display_params(device_t *cpu, tms34010_display_params *params)
+{
+ tms34010_state *tms = get_safe_token(cpu);
+
+ params->enabled = ((SMART_IOREG(tms, DPYCTL) & 0x8000) != 0);
+ params->vcount = SMART_IOREG(tms, VCOUNT);
+ params->veblnk = SMART_IOREG(tms, VEBLNK);
+ params->vsblnk = SMART_IOREG(tms, VSBLNK);
+ params->heblnk = SMART_IOREG(tms, HEBLNK) * tms->config->pixperclock;
+ params->hsblnk = SMART_IOREG(tms, HSBLNK) * tms->config->pixperclock;
+
+ /* 34010 gets its address from DPYADR and DPYTAP */
+ if (!tms->is_34020)
+ {
+ UINT16 dpyadr = IOREG(tms, REG_DPYADR);
+ if (!(IOREG(tms, REG_DPYCTL) & 0x0400))
+ dpyadr ^= 0xfffc;
+ params->rowaddr = dpyadr >> 4;
+ params->coladdr = ((dpyadr & 0x007c) << 4) | (IOREG(tms, REG_DPYTAP) & 0x3fff);
+ params->yoffset = (IOREG(tms, REG_DPYSTRT) - IOREG(tms, REG_DPYADR)) & 3;
+ }
+
+ /* 34020 gets its address from DPYNX */
+ else
+ {
+ params->rowaddr = IOREG(tms, REG020_DPYNXH);
+ params->coladdr = IOREG(tms, REG020_DPYNXL) & 0xffe0;
+ params->yoffset = 0;
+ if ((IOREG(tms, REG020_DINCL) & 0x1f) != 0)
+ params->yoffset = (IOREG(tms, REG020_DPYNXL) & 0x1f) / (IOREG(tms, REG020_DINCL) & 0x1f);
+ }
+}
+
+
+SCREEN_UPDATE( tms340x0 )
+{
+ pen_t blackpen = get_black_pen(screen->machine());
+ tms34010_display_params params;
+ tms34010_state *tms = NULL;
+ device_t *cpu;
+ int x;
+
+ /* find the owning CPU */
+ for (cpu = screen->machine().devicelist().first(); cpu != NULL; cpu = cpu->next())
+ {
+ device_type type = cpu->type();
+ if (type == TMS34010 || type == TMS34020)
+ {
+ tms = get_safe_token(cpu);
+ if (tms->config != NULL && tms->config->scanline_callback != NULL && tms->screen == screen)
+ break;
+ tms = NULL;
+ }
+ }
+ if (tms == NULL)
+ fatalerror("Unable to locate matching CPU for screen '%s'\n", screen->tag());
+
+ /* get the display parameters for the screen */
+ tms34010_get_display_params(tms->device, &params);
+
+ /* if the display is enabled, call the scanline callback */
+ if (params.enabled)
+ {
+ /* call through to the callback */
+ LOG((" Update: scan=%3d ROW=%04X COL=%04X\n", cliprect->min_y, params.rowaddr, params.coladdr));
+ (*tms->config->scanline_callback)(*screen, bitmap, cliprect->min_y, &params);
+ }
+
+ /* otherwise, just blank the current scanline */
+ else
+ params.heblnk = params.hsblnk = cliprect->max_x + 1;
+
+ /* blank out the blank regions */
+ if (bitmap->bpp == 16)
+ {
+ UINT16 *dest = BITMAP_ADDR16(bitmap, cliprect->min_y, 0);
+ for (x = cliprect->min_x; x < params.heblnk; x++)
+ dest[x] = blackpen;
+ for (x = params.hsblnk; x <= cliprect->max_y; x++)
+ dest[x] = blackpen;
+ }
+ else if (bitmap->bpp == 32)
+ {
+ UINT32 *dest = BITMAP_ADDR32(bitmap, cliprect->min_y, 0);
+ for (x = cliprect->min_x; x < params.heblnk; x++)
+ dest[x] = blackpen;
+ for (x = params.hsblnk; x <= cliprect->max_y; x++)
+ dest[x] = blackpen;
+ }
+ return 0;
+}
+
+
+/***************************************************************************
+ I/O REGISTER WRITES
+***************************************************************************/
+
+static const char *const ioreg_name[] =
+{
+ "HESYNC", "HEBLNK", "HSBLNK", "HTOTAL",
+ "VESYNC", "VEBLNK", "VSBLNK", "VTOTAL",
+ "DPYCTL", "DPYSTART", "DPYINT", "CONTROL",
+ "HSTDATA", "HSTADRL", "HSTADRH", "HSTCTLL",
+
+ "HSTCTLH", "INTENB", "INTPEND", "CONVSP",
+ "CONVDP", "PSIZE", "PMASK", "RESERVED",
+ "RESERVED", "RESERVED", "RESERVED", "DPYTAP",
+ "HCOUNT", "VCOUNT", "DPYADR", "REFCNT"
+};
+
+WRITE16_HANDLER( tms34010_io_register_w )
+{
+ tms34010_state *tms = get_safe_token(&space->device());
+ int oldreg, newreg;
+
+ /* Set register */
+ oldreg = IOREG(tms, offset);
+ IOREG(tms, offset) = data;
+
+ switch (offset)
+ {
+ case REG_CONTROL:
+ set_raster_op(tms);
+ set_pixel_function(tms);
+ break;
+
+ case REG_PSIZE:
+ set_pixel_function(tms);
+
+ switch (data)
+ {
+ default:
+ case 0x01: tms->pixelshift = 0; break;
+ case 0x02: tms->pixelshift = 1; break;
+ case 0x04: tms->pixelshift = 2; break;
+ case 0x08: tms->pixelshift = 3; break;
+ case 0x10: tms->pixelshift = 4; break;
+ }
+ break;
+
+ case REG_PMASK:
+ if (data) logerror("Plane masking not supported. PC=%08X\n", cpu_get_pc(&space->device()));
+ break;
+
+ case REG_DPYCTL:
+ set_pixel_function(tms);
+ break;
+
+ case REG_HSTCTLH:
+ /* if the CPU is halting itself, stop execution right away */
+ if ((data & 0x8000) && !tms->external_host_access)
+ tms->icount = 0;
+ device_set_input_line(tms->device, INPUT_LINE_HALT, (data & 0x8000) ? ASSERT_LINE : CLEAR_LINE);
+
+ /* NMI issued? */
+ if (data & 0x0100)
+ tms->device->machine().scheduler().synchronize(FUNC(internal_interrupt_callback), 0, tms);
+ break;
+
+ case REG_HSTCTLL:
+ /* the TMS34010 can change MSGOUT, can set INTOUT, and can clear INTIN */
+ if (!tms->external_host_access)
+ {
+ newreg = (oldreg & 0xff8f) | (data & 0x0070);
+ newreg |= data & 0x0080;
+ newreg &= data | ~0x0008;
+ }
+
+ /* the host can change MSGIN, can set INTIN, and can clear INTOUT */
+ else
+ {
+ newreg = (oldreg & 0xfff8) | (data & 0x0007);
+ newreg &= data | ~0x0080;
+ newreg |= data & 0x0008;
+ }
+ IOREG(tms, offset) = newreg;
+
+ /* the TMS34010 can set output interrupt? */
+ if (!(oldreg & 0x0080) && (newreg & 0x0080))
+ {
+ if (tms->config->output_int)
+ (*tms->config->output_int)(&space->device(), 1);
+ }
+ else if ((oldreg & 0x0080) && !(newreg & 0x0080))
+ {
+ if (tms->config->output_int)
+ (*tms->config->output_int)(&space->device(), 0);
+ }
+
+ /* input interrupt? (should really be state-based, but the functions don't exist!) */
+ if (!(oldreg & 0x0008) && (newreg & 0x0008))
+ tms->device->machine().scheduler().synchronize(FUNC(internal_interrupt_callback), TMS34010_HI, tms);
+ else if ((oldreg & 0x0008) && !(newreg & 0x0008))
+ IOREG(tms, REG_INTPEND) &= ~TMS34010_HI;
+ break;
+
+ case REG_CONVSP:
+ tms->convsp = 1 << (~data & 0x1f);
+ break;
+
+ case REG_CONVDP:
+ tms->convdp = 1 << (~data & 0x1f);
+ break;
+
+ case REG_INTENB:
+ check_interrupt(tms);
+ break;
+
+ case REG_INTPEND:
+ /* X1P, X2P and HIP are read-only */
+ /* WVP and DIP can only have 0's written to them */
+ IOREG(tms, REG_INTPEND) = oldreg;
+ if (!(data & TMS34010_WV))
+ IOREG(tms, REG_INTPEND) &= ~TMS34010_WV;
+ if (!(data & TMS34010_DI))
+ IOREG(tms, REG_INTPEND) &= ~TMS34010_DI;
+ break;
+
+ case REG_HEBLNK:
+ case REG_HSBLNK:
+ if (oldreg != data)
+ tms->hblank_stable = 0;
+ break;
+ }
+
+// if (LOG_CONTROL_REGS)
+// logerror("%s: %s = %04X (%d)\n", tms->device->machine().describe_context(), ioreg_name[offset], IOREG(tms, offset), tms->screen->vpos());
+}
+
+
+static const char *const ioreg020_name[] =
+{
+ "VESYNC", "HESYNC", "VEBLNK", "HEBLNK",
+ "VSBLNK", "HSBLNK", "VTOTAL", "HTOTAL",
+ "DPYCTL", "DPYSTRT", "DPYINT", "CONTROL",
+ "HSTDATA", "HSTADRL", "HSTADRH", "HSTCTLL",
+
+ "HSTCTLH", "INTENB", "INTPEND", "CONVSP",
+ "CONVDP", "PSIZE", "PMASKL", "PMASKH",
+ "CONVMP", "CONTROL2", "CONFIG", "DPYTAP",
+ "VCOUNT", "HCOUNT", "DPYADR", "REFADR",
+
+ "DPYSTL", "DPYSTH", "DPYNXL", "DPYNXH",
+ "DINCL", "DINCH", "RES0", "HESERR",
+ "RES1", "RES2", "RES3", "RES4",
+ "SCOUNT", "BSFLTST", "DPYMSK", "RES5",
+
+ "SETVCNT", "SETHCNT", "BSFLTDL", "BSFLTDH",
+ "RES6", "RES7", "RES8", "RES9",
+ "IHOST1L", "IHOST1H", "IHOST2L", "IHOST2H",
+ "IHOST3L", "IHOST3H", "IHOST4L", "IHOST4H"
+};
+
+WRITE16_HANDLER( tms34020_io_register_w )
+{
+ tms34010_state *tms = get_safe_token(&space->device());
+ int oldreg, newreg;
+
+ /* Set register */
+ oldreg = IOREG(tms, offset);
+ IOREG(tms, offset) = data;
+
+// if (LOG_CONTROL_REGS)
+// logerror("%s: %s = %04X (%d)\n", device->machine().describe_context(), ioreg020_name[offset], IOREG(tms, offset), tms->screen->vpos());
+
+ switch (offset)
+ {
+ case REG020_CONTROL:
+ case REG020_CONTROL2:
+ IOREG(tms, REG020_CONTROL) = data;
+ IOREG(tms, REG020_CONTROL2) = data;
+ set_raster_op(tms);
+ set_pixel_function(tms);
+ break;
+
+ case REG020_PSIZE:
+ set_pixel_function(tms);
+
+ switch (data)
+ {
+ default:
+ case 0x01: tms->pixelshift = 0; break;
+ case 0x02: tms->pixelshift = 1; break;
+ case 0x04: tms->pixelshift = 2; break;
+ case 0x08: tms->pixelshift = 3; break;
+ case 0x10: tms->pixelshift = 4; break;
+ case 0x20: tms->pixelshift = 5; break;
+ }
+ break;
+
+ case REG020_PMASKL:
+ case REG020_PMASKH:
+ if (data) logerror("Plane masking not supported. PC=%08X\n", cpu_get_pc(&space->device()));
+ break;
+
+ case REG020_DPYCTL:
+ set_pixel_function(tms);
+ break;
+
+ case REG020_HSTCTLH:
+ /* if the CPU is halting itself, stop execution right away */
+ if ((data & 0x8000) && !tms->external_host_access)
+ tms->icount = 0;
+ device_set_input_line(tms->device, INPUT_LINE_HALT, (data & 0x8000) ? ASSERT_LINE : CLEAR_LINE);
+
+ /* NMI issued? */
+ if (data & 0x0100)
+ tms->device->machine().scheduler().synchronize(FUNC(internal_interrupt_callback), 0, tms);
+ break;
+
+ case REG020_HSTCTLL:
+ /* the TMS34010 can change MSGOUT, can set INTOUT, and can clear INTIN */
+ if (!tms->external_host_access)
+ {
+ newreg = (oldreg & 0xff8f) | (data & 0x0070);
+ newreg |= data & 0x0080;
+ newreg &= data | ~0x0008;
+ }
+
+ /* the host can change MSGIN, can set INTIN, and can clear INTOUT */
+ else
+ {
+ newreg = (oldreg & 0xfff8) | (data & 0x0007);
+ newreg &= data | ~0x0080;
+ newreg |= data & 0x0008;
+ }
+ IOREG(tms, offset) = newreg;
+
+ /* the TMS34010 can set output interrupt? */
+ if (!(oldreg & 0x0080) && (newreg & 0x0080))
+ {
+ if (tms->config->output_int)
+ (*tms->config->output_int)(&space->device(), 1);
+ }
+ else if ((oldreg & 0x0080) && !(newreg & 0x0080))
+ {
+ if (tms->config->output_int)
+ (*tms->config->output_int)(&space->device(), 0);
+ }
+
+ /* input interrupt? (should really be state-based, but the functions don't exist!) */
+ if (!(oldreg & 0x0008) && (newreg & 0x0008))
+ tms->device->machine().scheduler().synchronize(FUNC(internal_interrupt_callback), TMS34010_HI, tms);
+ else if ((oldreg & 0x0008) && !(newreg & 0x0008))
+ IOREG(tms, REG020_INTPEND) &= ~TMS34010_HI;
+ break;
+
+ case REG020_INTENB:
+ check_interrupt(tms);
+ break;
+
+ case REG020_INTPEND:
+ /* X1P, X2P and HIP are read-only */
+ /* WVP and DIP can only have 0's written to them */
+ IOREG(tms, REG020_INTPEND) = oldreg;
+ if (!(data & TMS34010_WV))
+ IOREG(tms, REG020_INTPEND) &= ~TMS34010_WV;
+ if (!(data & TMS34010_DI))
+ IOREG(tms, REG020_INTPEND) &= ~TMS34010_DI;
+ break;
+
+ case REG020_CONVSP:
+ if (data & 0x001f)
+ {
+ if (data & 0x1f00)
+ tms->convsp = (1 << (~data & 0x1f)) + (1 << (~(data >> 8) & 0x1f));
+ else
+ tms->convsp = 1 << (~data & 0x1f);
+ }
+ else
+ tms->convsp = data;
+ break;
+
+ case REG020_CONVDP:
+ if (data & 0x001f)
+ {
+ if (data & 0x1f00)
+ tms->convdp = (1 << (~data & 0x1f)) + (1 << (~(data >> 8) & 0x1f));
+ else
+ tms->convdp = 1 << (~data & 0x1f);
+ }
+ else
+ tms->convdp = data;
+ break;
+
+ case REG020_CONVMP:
+ if (data & 0x001f)
+ {
+ if (data & 0x1f00)
+ tms->convmp = (1 << (~data & 0x1f)) + (1 << (~(data >> 8) & 0x1f));
+ else
+ tms->convmp = 1 << (~data & 0x1f);
+ }
+ else
+ tms->convmp = data;
+ break;
+
+ case REG020_DPYSTRT:
+ case REG020_DPYADR:
+ case REG020_DPYTAP:
+ break;
+
+ case REG020_HEBLNK:
+ case REG020_HSBLNK:
+ if (oldreg != data)
+ tms->hblank_stable = 0;
+ break;
+ }
+}
+
+
+
+/***************************************************************************
+ I/O REGISTER READS
+***************************************************************************/
+
+READ16_HANDLER( tms34010_io_register_r )
+{
+ tms34010_state *tms = get_safe_token(&space->device());
+ int result, total;
+
+// if (LOG_CONTROL_REGS)
+// logerror("%s: read %s\n", device->machine().describe_context(), ioreg_name[offset]);
+
+ switch (offset)
+ {
+ case REG_HCOUNT:
+ /* scale the horizontal position from screen width to HTOTAL */
+ result = tms->screen->hpos();
+ total = IOREG(tms, REG_HTOTAL) + 1;
+ result = result * total / tms->screen->width();
+
+ /* offset by the HBLANK end */
+ result += IOREG(tms, REG_HEBLNK);
+
+ /* wrap around */
+ if (result > total)
+ result -= total;
+ return result;
+
+ case REG_REFCNT:
+ return (tms->device->total_cycles() / 16) & 0xfffc;
+
+ case REG_INTPEND:
+ result = IOREG(tms, offset);
+
+ /* Cool Pool loops in mainline code on the appearance of the DI, even though they */
+ /* have an IRQ handler. For this reason, we return it signalled a bit early in order */
+ /* to make it past these loops. */
+ if (SMART_IOREG(tms, VCOUNT) + 1 == SMART_IOREG(tms, DPYINT) &&
+ tms->scantimer->remaining() < attotime::from_hz(40000000/8/3))
+ result |= TMS34010_DI;
+ return result;
+ }
+
+ return IOREG(tms, offset);
+}
+
+
+READ16_HANDLER( tms34020_io_register_r )
+{
+ tms34010_state *tms = get_safe_token(&space->device());
+ int result, total;
+
+// if (LOG_CONTROL_REGS)
+// logerror("%s: read %s\n", device->machine().describe_context(), ioreg_name[offset]);
+
+ switch (offset)
+ {
+ case REG020_HCOUNT:
+ /* scale the horizontal position from screen width to HTOTAL */
+ result = tms->screen->hpos();
+ total = IOREG(tms, REG020_HTOTAL) + 1;
+ result = result * total / tms->screen->width();
+
+ /* offset by the HBLANK end */
+ result += IOREG(tms, REG020_HEBLNK);
+
+ /* wrap around */
+ if (result > total)
+ result -= total;
+ return result;
+
+ case REG020_REFADR:
+ {
+ int refreshrate = (IOREG(tms, REG020_CONFIG) >> 8) & 7;
+ if (refreshrate < 6)
+ return (tms->device->total_cycles() / refreshrate) & 0xffff;
+ break;
+ }
+ }
+
+ return IOREG(tms, offset);
+}
+
+
+
+/***************************************************************************
+ SAVE STATE
+***************************************************************************/
+
+static void tms34010_state_postload(tms34010_state *tms)
+{
+ set_raster_op(tms);
+ set_pixel_function(tms);
+}
+
+
+/***************************************************************************
+ HOST INTERFACE WRITES
+***************************************************************************/
+
+void tms34010_host_w(device_t *cpu, int reg, int data)
+{
+ address_space *space;
+ tms34010_state *tms = get_safe_token(cpu);
+ unsigned int addr;
+
+ switch (reg)
+ {
+ /* upper 16 bits of the address */
+ case TMS34010_HOST_ADDRESS_H:
+ IOREG(tms, REG_HSTADRH) = data;
+ break;
+
+ /* lower 16 bits of the address */
+ case TMS34010_HOST_ADDRESS_L:
+ IOREG(tms, REG_HSTADRL) = data;
+ break;
+
+ /* actual data */
+ case TMS34010_HOST_DATA:
+
+ /* write to the address */
+ addr = (IOREG(tms, REG_HSTADRH) << 16) | IOREG(tms, REG_HSTADRL);
+ TMS34010_WRMEM_WORD(tms, TOBYTE(addr & 0xfffffff0), data);
+
+ /* optional postincrement */
+ if (IOREG(tms, REG_HSTCTLH) & 0x0800)
+ {
+ addr += 0x10;
+ IOREG(tms, REG_HSTADRH) = addr >> 16;
+ IOREG(tms, REG_HSTADRL) = (UINT16)addr;
+ }
+ break;
+
+ /* control register */
+ case TMS34010_HOST_CONTROL:
+ tms->external_host_access = TRUE;
+ space = tms->device->space(AS_PROGRAM);
+ tms34010_io_register_w(space, REG_HSTCTLH, data & 0xff00, 0xffff);
+ tms34010_io_register_w(space, REG_HSTCTLL, data & 0x00ff, 0xffff);
+ tms->external_host_access = FALSE;
+ break;
+
+ /* error case */
+ default:
+ logerror("tms34010_host_control_w called on invalid register %d\n", reg);
+ break;
+ }
+}
+
+
+
+/***************************************************************************
+ HOST INTERFACE READS
+***************************************************************************/
+
+int tms34010_host_r(device_t *cpu, int reg)
+{
+ tms34010_state *tms = get_safe_token(cpu);
+ unsigned int addr;
+ int result = 0;
+
+ /* swap to the target cpu */
+
+ switch (reg)
+ {
+ /* upper 16 bits of the address */
+ case TMS34010_HOST_ADDRESS_H:
+ result = IOREG(tms, REG_HSTADRH);
+ break;
+
+ /* lower 16 bits of the address */
+ case TMS34010_HOST_ADDRESS_L:
+ result = IOREG(tms, REG_HSTADRL);
+ break;
+
+ /* actual data */
+ case TMS34010_HOST_DATA:
+
+ /* read from the address */
+ addr = (IOREG(tms, REG_HSTADRH) << 16) | IOREG(tms, REG_HSTADRL);
+ result = TMS34010_RDMEM_WORD(tms, TOBYTE(addr & 0xfffffff0));
+
+ /* optional postincrement (it says preincrement, but data is preloaded, so it
+ is effectively a postincrement */
+ if (IOREG(tms, REG_HSTCTLH) & 0x1000)
+ {
+ addr += 0x10;
+ IOREG(tms, REG_HSTADRH) = addr >> 16;
+ IOREG(tms, REG_HSTADRL) = (UINT16)addr;
+ }
+ break;
+
+ /* control register */
+ case TMS34010_HOST_CONTROL:
+ result = (IOREG(tms, REG_HSTCTLH) & 0xff00) | (IOREG(tms, REG_HSTCTLL) & 0x00ff);
+ break;
+
+ /* error case */
+ default:
+ logerror("tms34010_host_control_r called on invalid register %d\n", reg);
+ break;
+ }
+
+ return result;
+}
+
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( tms34010 )
+{
+ tms34010_state *tms = 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(tms, 0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + 1: set_irq_line(tms, 1, info->i); break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_EXPORT_STRING( tms34010 )
+{
+ tms34010_state *tms = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ string.printf("%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
+ tms->st & 0x80000000 ? 'N':'.',
+ tms->st & 0x40000000 ? 'C':'.',
+ tms->st & 0x20000000 ? 'Z':'.',
+ tms->st & 0x10000000 ? 'V':'.',
+ tms->st & 0x02000000 ? 'P':'.',
+ tms->st & 0x00200000 ? 'I':'.',
+ tms->st & 0x00000800 ? 'E':'.',
+ tms->st & 0x00000400 ? 'F':'.',
+ tms->st & 0x00000200 ? 'F':'.',
+ tms->st & 0x00000100 ? 'F':'.',
+ tms->st & 0x00000080 ? 'F':'.',
+ tms->st & 0x00000040 ? 'F':'.',
+ tms->st & 0x00000020 ? 'E':'.',
+ tms->st & 0x00000010 ? 'F':'.',
+ tms->st & 0x00000008 ? 'F':'.',
+ tms->st & 0x00000004 ? 'F':'.',
+ tms->st & 0x00000002 ? 'F':'.',
+ tms->st & 0x00000001 ? 'F':'.');
+ break;
+ }
+}
+
+CPU_GET_INFO( tms34010 )
+{
+ tms34010_state *tms = (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(tms34010_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 = 8; 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 = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 10000; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 3; break;
+
+ case CPUINFO_INT_INPUT_STATE + 0: info->i = (IOREG(tms, REG_INTPEND) & TMS34010_INT1) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + 1: info->i = (IOREG(tms, REG_INTPEND) & TMS34010_INT2) ? ASSERT_LINE : CLEAR_LINE; break;
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(tms34010); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(tms34010); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(tms34010); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(tms34010); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(tms34010); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(tms34010); break;
+ case CPUINFO_FCT_EXPORT_STRING: info->export_string = CPU_EXPORT_STRING_NAME(tms34010); break;
+
+ /* --- the following bits of info are returned as pointers --- */
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &tms->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "TMS34010"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Texas Instruments 340x0"); 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 Alex Pasadyn/Zsolt Vasvari\nParts based on code by Aaron Giles"); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+CPU_GET_INFO( tms34020 )
+{
+ 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_RESET: info->reset = CPU_RESET_NAME(tms34020); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(tms34020); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "TMS34020"); break;
+
+ default: CPU_GET_INFO_CALL(tms34010); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(TMS34010, tms34010);
+DEFINE_LEGACY_CPU_DEVICE(TMS34020, tms34020);
diff --git a/trunk/src/emu/cpu/tms34010/tms34010.h b/trunk/src/emu/cpu/tms34010/tms34010.h
new file mode 100644
index 00000000000..44c6d512d4e
--- /dev/null
+++ b/trunk/src/emu/cpu/tms34010/tms34010.h
@@ -0,0 +1,241 @@
+/***************************************************************************
+
+ TMS34010: Portable Texas Instruments TMS34010 emulator
+
+ Copyright Alex Pasadyn/Zsolt Vasvari
+ Parts based on code by Aaron Giles
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __TMS34010_H__
+#define __TMS34010_H__
+
+
+/* register indexes for get_reg and set_reg */
+enum
+{
+ TMS34010_PC,
+ TMS34010_SP,
+ TMS34010_ST,
+ TMS34010_A0,
+ TMS34010_A1,
+ TMS34010_A2,
+ TMS34010_A3,
+ TMS34010_A4,
+ TMS34010_A5,
+ TMS34010_A6,
+ TMS34010_A7,
+ TMS34010_A8,
+ TMS34010_A9,
+ TMS34010_A10,
+ TMS34010_A11,
+ TMS34010_A12,
+ TMS34010_A13,
+ TMS34010_A14,
+ TMS34010_B0,
+ TMS34010_B1,
+ TMS34010_B2,
+ TMS34010_B3,
+ TMS34010_B4,
+ TMS34010_B5,
+ TMS34010_B6,
+ TMS34010_B7,
+ TMS34010_B8,
+ TMS34010_B9,
+ TMS34010_B10,
+ TMS34010_B11,
+ TMS34010_B12,
+ TMS34010_B13,
+ TMS34010_B14,
+
+ TMS34010_GENPC = STATE_GENPC,
+ TMS34010_GENSP = STATE_GENSP,
+ TMS34010_GENPCBASE = STATE_GENPCBASE
+};
+
+
+/***************************************************************************
+ INTERNAL I/O CONSTANTS
+***************************************************************************/
+
+enum
+{
+ REG_HESYNC = 0,
+ REG_HEBLNK,
+ REG_HSBLNK,
+ REG_HTOTAL,
+ REG_VESYNC,
+ REG_VEBLNK,
+ REG_VSBLNK,
+ REG_VTOTAL,
+ REG_DPYCTL,
+ REG_DPYSTRT,
+ REG_DPYINT,
+ REG_CONTROL,
+ REG_HSTDATA,
+ REG_HSTADRL,
+ REG_HSTADRH,
+ REG_HSTCTLL,
+
+ REG_HSTCTLH,
+ REG_INTENB,
+ REG_INTPEND,
+ REG_CONVSP,
+ REG_CONVDP,
+ REG_PSIZE,
+ REG_PMASK,
+ REG_UNK23,
+ REG_UNK24,
+ REG_UNK25,
+ REG_UNK26,
+ REG_DPYTAP,
+ REG_HCOUNT,
+ REG_VCOUNT,
+ REG_DPYADR,
+ REG_REFCNT
+};
+
+enum
+{
+ REG020_VESYNC,
+ REG020_HESYNC,
+ REG020_VEBLNK,
+ REG020_HEBLNK,
+ REG020_VSBLNK,
+ REG020_HSBLNK,
+ REG020_VTOTAL,
+ REG020_HTOTAL,
+ REG020_DPYCTL, /* matches 010 */
+ REG020_DPYSTRT, /* matches 010 */
+ REG020_DPYINT, /* matches 010 */
+ REG020_CONTROL, /* matches 010 */
+ REG020_HSTDATA, /* matches 010 */
+ REG020_HSTADRL, /* matches 010 */
+ REG020_HSTADRH, /* matches 010 */
+ REG020_HSTCTLL, /* matches 010 */
+
+ REG020_HSTCTLH, /* matches 010 */
+ REG020_INTENB, /* matches 010 */
+ REG020_INTPEND, /* matches 010 */
+ REG020_CONVSP, /* matches 010 */
+ REG020_CONVDP, /* matches 010 */
+ REG020_PSIZE, /* matches 010 */
+ REG020_PMASKL,
+ REG020_PMASKH,
+ REG020_CONVMP,
+ REG020_CONTROL2,
+ REG020_CONFIG,
+ REG020_DPYTAP, /* matches 010 */
+ REG020_VCOUNT,
+ REG020_HCOUNT,
+ REG020_DPYADR, /* matches 010 */
+ REG020_REFADR,
+
+ REG020_DPYSTL,
+ REG020_DPYSTH,
+ REG020_DPYNXL,
+ REG020_DPYNXH,
+ REG020_DINCL,
+ REG020_DINCH,
+ REG020_RES0,
+ REG020_HESERR,
+ REG020_RES1,
+ REG020_RES2,
+ REG020_RES3,
+ REG020_RES4,
+ REG020_SCOUNT,
+ REG020_BSFLTST,
+ REG020_DPYMSK,
+ REG020_RES5,
+
+ REG020_SETVCNT,
+ REG020_SETHCNT,
+ REG020_BSFLTDL,
+ REG020_BSFLTDH,
+ REG020_RES6,
+ REG020_RES7,
+ REG020_RES8,
+ REG020_RES9,
+ REG020_IHOST1L,
+ REG020_IHOST1H,
+ REG020_IHOST2L,
+ REG020_IHOST2H,
+ REG020_IHOST3L,
+ REG020_IHOST3H,
+ REG020_IHOST4L,
+ REG020_IHOST4H
+};
+
+/* Interrupts that are generated by the processor internally */
+#define TMS34010_INT1 0x0002 /* External Interrupt 1 */
+#define TMS34010_INT2 0x0004 /* External Interrupt 2 */
+#define TMS34010_HI 0x0200 /* Host Interrupt */
+#define TMS34010_DI 0x0400 /* Display Interrupt */
+#define TMS34010_WV 0x0800 /* Window Violation Interrupt */
+
+
+/* Configuration structure */
+typedef struct _tms34010_display_params tms34010_display_params;
+struct _tms34010_display_params
+{
+ UINT16 vcount; /* most recent VCOUNT */
+ UINT16 veblnk, vsblnk; /* start/end of VBLANK */
+ UINT16 heblnk, hsblnk; /* start/end of HBLANK */
+ UINT16 rowaddr, coladdr; /* row/column addresses */
+ UINT8 yoffset; /* y offset from addresses */
+ UINT8 enabled; /* video enabled */
+};
+
+
+typedef struct _tms34010_config tms34010_config;
+struct _tms34010_config
+{
+ UINT8 halt_on_reset; /* /HCS pin, which determines HALT state after reset */
+ const char *screen_tag; /* the screen operated on */
+ UINT32 pixclock; /* the pixel clock (0 means don't adjust screen size) */
+ int pixperclock; /* pixels per clock */
+ void (*scanline_callback)(screen_device &screen, bitmap_t *bitmap, int scanline, const tms34010_display_params *params);
+ void (*output_int)(device_t *device, int state); /* output interrupt callback */
+ void (*to_shiftreg)(address_space *space, offs_t, UINT16 *); /* shift register write */
+ void (*from_shiftreg)(address_space *space, offs_t, UINT16 *); /* shift register read */
+};
+
+
+/* PUBLIC FUNCTIONS - 34010 */
+SCREEN_UPDATE( tms340x0 );
+void tms34010_get_display_params(device_t *cpu, tms34010_display_params *params);
+
+DECLARE_LEGACY_CPU_DEVICE(TMS34010, tms34010);
+DECLARE_LEGACY_CPU_DEVICE(TMS34020, tms34020);
+
+
+/* Host control interface */
+#define TMS34010_HOST_ADDRESS_L 0
+#define TMS34010_HOST_ADDRESS_H 1
+#define TMS34010_HOST_DATA 2
+#define TMS34010_HOST_CONTROL 3
+
+void tms34010_host_w(device_t *cpu, int reg, int data);
+int tms34010_host_r(device_t *cpu, int reg);
+
+
+/* Reads & writes to the 34010 I/O registers; place at 0xc0000000 */
+WRITE16_HANDLER( tms34010_io_register_w );
+READ16_HANDLER( tms34010_io_register_r );
+
+/* Reads & writes to the 34020 I/O registers; place at 0xc0000000 */
+WRITE16_HANDLER( tms34020_io_register_w );
+READ16_HANDLER( tms34020_io_register_r );
+
+
+/* Use this macro in the memory definitions to specify bit-based addresses */
+#define TOBYTE(bitaddr) ((offs_t)(bitaddr) >> 3)
+#define TOWORD(bitaddr) ((offs_t)(bitaddr) >> 4)
+
+
+CPU_DISASSEMBLE( tms34010 );
+CPU_DISASSEMBLE( tms34020 );
+
+#endif /* __TMS34010_H__ */
diff --git a/trunk/src/emu/cpu/tms57002/57002dsm.c b/trunk/src/emu/cpu/tms57002/57002dsm.c
new file mode 100644
index 00000000000..1d5a3778dbf
--- /dev/null
+++ b/trunk/src/emu/cpu/tms57002/57002dsm.c
@@ -0,0 +1,91 @@
+#include "emu.h"
+#include "debugger.h"
+#include "tms57002.h"
+
+#ifdef __GNUC__
+#define noinline __attribute__((noinline))
+#else
+#define noinline /* */
+#endif
+
+static const char *tms57002_get_memadr(UINT32 opcode, char type)
+{
+ static char buff[2][10];
+ static int index = 0;
+ char *buf;
+
+ index = 1-index;
+ buf = buff[index];
+
+ if(((opcode & 0x400) && (type == 'c')) || (!(opcode & 0x400) && (type == 'd'))) {
+ if(opcode & 0x100)
+ sprintf(buf, "%c(%02x)", type, opcode & 0xff);
+ else if(opcode & 0x80)
+ sprintf(buf, "%c*+", type);
+ else
+ sprintf(buf, "%c*", type);
+ } else if(opcode & 0x200)
+ sprintf(buf, "%c*+", type);
+ else
+ sprintf(buf, "%c*", type);
+ return buf;
+}
+
+
+CPU_DISASSEMBLE(tms57002)
+{
+ UINT32 opcode = opram[0] | (opram[1] << 8) | (opram[2] << 16);
+ UINT8 fa = opcode >> 18;
+ char *buf = buffer;
+ if(fa == 0x3f) {
+ switch((opcode >> 11) & 0x7f) { // category 3
+
+#define DASM3
+#include "cpu/tms57002/tms57002.inc"
+#undef DASM3
+
+ default:
+ sprintf(buf, "unk c3 %02x", (opcode >> 11) & 0x7f);
+ break;
+ }
+ } else {
+ switch(fa) { // category 1
+ case 0x00:
+ buf[0] = 0;
+ break;
+
+#define DASM1
+#include "cpu/tms57002/tms57002.inc"
+#undef DASM1
+
+ default:
+ sprintf(buf, "unk c1 %02x", fa);
+ break;
+ }
+
+ buf += strlen(buf);
+ if(buf != buffer) {
+ strcpy(buf, " ; ");
+ buf += 3;
+ }
+
+ switch((opcode >> 11) & 0x7f) { // category 2
+ case 0x00:
+ if(buf != buffer)
+ buf[-3] = 0;
+ else
+ sprintf(buf, "nop");
+ break;
+
+#define DASM2
+#include "cpu/tms57002/tms57002.inc"
+#undef DASM2
+
+ default:
+ sprintf(buf, "unk c2 %02x", (opcode >> 11) & 0x7f);
+ break;
+ }
+ }
+
+ return 1;
+}
diff --git a/trunk/src/emu/cpu/tms57002/tms57002.c b/trunk/src/emu/cpu/tms57002/tms57002.c
new file mode 100644
index 00000000000..df63908023b
--- /dev/null
+++ b/trunk/src/emu/cpu/tms57002/tms57002.c
@@ -0,0 +1,1152 @@
+#include "emu.h"
+#include "debugger.h"
+#include "tms57002.h"
+#include "tms57kpr.h"
+
+INLINE tms57002_t *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == TMS57002);
+ return (tms57002_t *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+static void tms57002_cache_flush(tms57002_t *s);
+
+WRITE8_DEVICE_HANDLER(tms57002_pload_w)
+{
+ tms57002_t *s = get_safe_token(device);
+ UINT8 olds = s->sti;
+
+ if(data)
+ s->sti &= ~IN_PLOAD;
+ else
+ s->sti |= IN_PLOAD;
+
+ if(olds ^ s->sti)
+ s->hidx = 0;
+}
+
+WRITE8_DEVICE_HANDLER(tms57002_cload_w)
+{
+ tms57002_t *s = get_safe_token(device);
+ UINT8 olds = s->sti;
+ if(data)
+ s->sti &= ~IN_CLOAD;
+ else
+ s->sti |= IN_CLOAD;
+ if(olds ^ s->sti)
+ s->hidx = 0;
+}
+
+static CPU_RESET(tms57002)
+{
+ tms57002_t *s = get_safe_token(device);
+
+ s->sti = (s->sti & ~(SU_MASK|S_READ|S_WRITE|S_BRANCH|S_HOST)) | (SU_ST0|S_IDLE);
+ s->pc = 0;
+ s->ca = 0;
+ s->hidx = 0;
+ s->id = 0;
+ s->ba0 = 0;
+ s->ba1 = 0;
+ s->st0 &= ~(ST0_INCS | ST0_DIRI | ST0_FI | ST0_SIM | ST0_PLRI |
+ ST0_PBCI | ST0_DIRO | ST0_FO | ST0_SOM | ST0_PLRO |
+ ST0_PBCO | ST0_CNS);
+ s->st1 &= ~(ST1_AOV | ST1_SFAI | ST1_SFAO | ST1_MOVM | ST1_MOV |
+ ST1_SFMA | ST1_SFMO | ST1_RND | ST1_CRM | ST1_DBP);
+
+ s->xba = 0; // Not sure but makes sense
+
+ tms57002_cache_flush(s);
+}
+
+
+WRITE8_DEVICE_HANDLER(tms57002_data_w)
+{
+ tms57002_t *s = get_safe_token(device);
+
+ switch(s->sti & (IN_PLOAD|IN_CLOAD)) {
+ case 0:
+ s->hidx = 0;
+ s->sti &= ~SU_CVAL;
+ break;
+ case IN_PLOAD:
+ s->host[s->hidx++] = data;
+ if(s->hidx >= 3) {
+ UINT32 val = (s->host[0]<<16) | (s->host[1]<<8) | s->host[2];
+ s->hidx = 0;
+
+ switch(s->sti & SU_MASK) {
+ case SU_ST0:
+ s->st0 = val;
+ s->sti = (s->sti & ~SU_MASK) | SU_ST1;
+ break;
+ case SU_ST1:
+ s->st1 = val;
+ s->sti = (s->sti & ~SU_MASK) | SU_PRG;
+ break;
+ case SU_PRG:
+ s->program->write_dword((s->pc++) << 2, val);
+ break;
+ }
+ }
+ break;
+ case IN_CLOAD:
+ if(s->sti & SU_CVAL) {
+ s->host[s->hidx++] = data;
+ if(s->hidx >= 4) {
+ UINT32 val = (s->host[0]<<24) | (s->host[1]<<16) | (s->host[2]<<8) | s->host[3];
+ s->cmem[s->sa] = val;
+ s->sti &= ~SU_CVAL;
+ s->allow_update = 0;
+ }
+ } else {
+ s->sa = data;
+ s->hidx = 0;
+ s->sti |= SU_CVAL;
+ }
+
+ break;
+ case IN_PLOAD|IN_CLOAD:
+ s->host[s->hidx++] = data;
+ if(s->hidx >= 4) {
+ UINT32 val = (s->host[0]<<24) | (s->host[1]<<16) | (s->host[2]<<8) | s->host[3];
+ s->hidx = 0;
+ s->cmem[s->ca++] = val;
+ }
+ break;
+ };
+}
+
+READ8_DEVICE_HANDLER(tms57002_data_r)
+{
+ tms57002_t *s = get_safe_token(device);
+ UINT8 res;
+ if(!(s->sti & S_HOST))
+ return 0xff;
+
+ res = s->host[s->hidx];
+ s->hidx++;
+ if(s->hidx == 4) {
+ s->hidx = 0;
+ s->sti &= ~S_HOST;
+ }
+
+ return res;
+}
+
+READ8_DEVICE_HANDLER(tms57002_empty_r)
+{
+ return 1;
+}
+
+READ8_DEVICE_HANDLER(tms57002_dready_r)
+{
+ tms57002_t *s = get_safe_token(device);
+ return s->sti & S_HOST ? 0 : 1;
+}
+
+void tms57002_sync(device_t *device)
+{
+ tms57002_t *s = get_safe_token(device);
+
+ if(s->sti & (IN_PLOAD | IN_CLOAD))
+ return;
+
+ s->allow_update = 1;
+ s->pc = 0;
+ s->ca = 0;
+ s->id = 0;
+ if(!(s->st0 & ST0_INCS)) {
+ s->ba0--;
+ s->ba1++;
+ }
+ s->xba = (s->xba-1) & 0x7ffff;
+ s->st1 &= ~(ST1_AOV | ST1_MOV);
+ s->sti &= ~S_IDLE;
+}
+
+#ifdef UNUSED_FUNCTION
+static UINT32 tms57002_read_c(tms57002_t *s, UINT8 index)
+{
+ UINT32 v = s->cmem[index];
+ if((s->st1 & ST1_CRM) != ST1_CRM_32) {
+ if((s->st1 & ST1_CRM) == ST1_CRM_16H)
+ v &= 0xffff0000;
+ else if((s->st1 & ST1_CRM) == ST1_CRM_16L)
+ v <<= 16;
+ }
+ return v;
+}
+
+static void tms57002_write_c(tms57002_t *s, UINT8 index, UINT32 v)
+{
+ s->cmem[index] = v;
+}
+
+static void tms57002_write_d(tms57002_t *s, UINT8 index, UINT32 v)
+{
+ if(s->st1 & ST1_DBP)
+ s->dmem1[(s->ba1 + index) & 0x1f] = v;
+ else
+ s->dmem0[(s->ba0 + index) & 0xff] = v;
+}
+
+static UINT32 tms57002_read_d(tms57002_t *s, UINT8 index)
+{
+ if(s->st1 & ST1_DBP)
+ return s->dmem1[(s->ba1 + index) & 0x1f];
+ else
+ return s->dmem0[(s->ba0 + index) & 0xff];
+}
+
+static void tms57002_opc_write_c(tms57002_t *s, UINT32 opcode, UINT32 v)
+{
+ if(opcode & 0x400) {
+ if(opcode & 0x100)
+ tms57002_write_c(s, opcode & 0xff, v);
+ else if(opcode & 0x80)
+ tms57002_write_c(s, s->ca++, v);
+ else
+ tms57002_write_c(s, s->ca, v);
+ } else if(opcode & 0x200)
+ tms57002_write_c(s, s->ca++, v);
+ else
+ tms57002_write_c(s, s->ca, v);
+}
+
+static UINT32 tms57002_opc_read_c(tms57002_t *s, UINT32 opcode)
+{
+ if(opcode & 0x400) {
+ if(opcode & 0x100)
+ return tms57002_read_c(s, opcode & 0xff);
+ else if(opcode & 0x80)
+ return tms57002_read_c(s, s->ca++);
+ else
+ return tms57002_read_c(s, s->ca);
+ } else if(opcode & 0x200)
+ return tms57002_read_c(s, s->ca++);
+ else
+ return tms57002_read_c(s, s->ca);
+}
+
+static void tms57002_opc_write_d(tms57002_t *s, UINT32 opcode, UINT32 v)
+{
+ if(!(opcode & 0x400)) {
+ if(opcode & 0x100)
+ tms57002_write_d(s, opcode & 0xff, v);
+ else if(opcode & 0x80)
+ tms57002_write_d(s, s->id++, v);
+ else
+ tms57002_write_d(s, s->id, v);
+ } else if(opcode & 0x200)
+ tms57002_write_d(s, s->id++, v);
+ else
+ tms57002_write_d(s, s->id, v);
+}
+
+static UINT32 tms57002_opc_read_d(tms57002_t *s, UINT32 opcode)
+{
+ if(!(opcode & 0x400)) {
+ if(opcode & 0x100)
+ return tms57002_read_d(s, opcode & 0xff);
+ else if(opcode & 0x80)
+ return tms57002_read_d(s, s->id++);
+ else
+ return tms57002_read_d(s, s->id);
+ } else if(opcode & 0x200)
+ return tms57002_read_d(s, s->id++);
+ else
+ return tms57002_read_d(s, s->id);
+}
+#endif
+
+static void tms57002_xm_init(tms57002_t *s)
+{
+ UINT32 adr = s->xoa + s->xba;
+ UINT32 mask = 0;
+
+ switch(s->st0 & ST0_M) {
+ case ST0_M_64K: mask = 0x0ffff; break;
+ case ST0_M_256K: mask = 0x3ffff; break;
+ case ST0_M_1M: mask = 0xfffff; break;
+ }
+ if(s->st0 & ST0_WORD)
+ adr <<= 2;
+ else
+ adr <<= 1;
+
+ if(!(s->st0 & ST0_SEL))
+ adr <<= 1;
+
+ s->xm_adr = adr & mask;
+}
+
+static void tms57002_xm_step_read(tms57002_t *s)
+{
+ UINT32 adr = s->xm_adr;
+ UINT8 v = s->data->read_byte(adr);
+ int done;
+ if(s->st0 & ST0_WORD) {
+ if(s->st0 & ST0_SEL) {
+ int off = (adr & 3) << 3;
+ s->xrd = (s->xrd & ~(0xff << off)) | (v << off);
+ done = off == 16;
+ } else {
+ int off = (adr & 7) << 2;
+ s->xrd = (s->xrd & ~(0xf << off)) | ((v & 0xf) << off);
+ done = off == 20;
+ }
+ } else {
+ if(s->st0 & ST0_SEL) {
+ int off = (adr & 1) << 3;
+ s->xrd = (s->xrd & ~(0xff << off)) | (v << off);
+ done = off == 8;
+ if(done)
+ s->xrd &= 0x00ffff;
+ } else {
+ int off = (adr & 3) << 2;
+ s->xrd = (s->xrd & ~(0xf << off)) | ((v & 0xf) << off);
+ done = off == 12;
+ if(done)
+ s->xrd &= 0x00ffff;
+ }
+ }
+ if(done) {
+ s->sti &= ~S_READ;
+ s->xm_adr = 0;
+ } else
+ s->xm_adr = adr+1;
+}
+
+static void tms57002_xm_step_write(tms57002_t *s)
+{
+ UINT32 adr = s->xm_adr;
+ UINT8 v;
+ int done;
+ if(s->st0 & ST0_WORD) {
+ if(s->st0 & ST0_SEL) {
+ int off = (adr & 3) << 3;
+ v = s->xwr >> off;
+ done = off == 16;
+ } else {
+ int off = (adr & 7) << 2;
+ v = (s->xwr >> off) & 0xf;
+ done = off == 20;
+ }
+ } else {
+ if(s->st0 & ST0_SEL) {
+ int off = (adr & 1) << 3;
+ v = s->xwr >> off;
+ done = off == 8;
+ } else {
+ int off = (adr & 3) << 2;
+ v = (s->xwr >> off) & 0xf;
+ done = off == 12;
+ }
+ }
+ s->data->write_byte(adr, v);
+ if(done) {
+ s->sti &= ~S_WRITE;
+ s->xm_adr = 0;
+ } else
+ s->xm_adr = adr+1;
+}
+
+#ifdef UNUSED_FUNCTION
+static UINT32 tms57002_aacc_to_output(tms57002_t *s)
+{
+ if(s->st1 & ST1_SFAO)
+ return s->aacc << 7;
+ else
+ return s->aacc;
+}
+
+static INT64 tms57002_macc_to_output(tms57002_t *s)
+{
+ INT64 m = s->macc;
+ UINT64 m1;
+ int over = 0, rmode;
+ static const INT64 rounding[8] = {
+ 0,
+ 1LL << (48-32-1),
+ 1LL << (48-24-1),
+ 1LL << (48-30-1),
+ 1LL << (48-16-1),
+ 0, 0, 0
+ };
+ static const UINT64 rmask[8] = {
+ ~0ULL,
+ (~0ULL) << (48-32),
+ (~0ULL) << (48-24),
+ (~0ULL) << (48-30),
+ (~0ULL) << (48-16),
+ ~0ULL, ~0ULL, ~0ULL
+ };
+
+ // Overflow detection and shifting
+ switch((s->st1 & ST1_SFMO) >> ST1_SFMO_SHIFT) {
+ case 0: // sfmo 0
+ m1 = m & 0xf800000000000ULL;
+ if(m1 && m1 != 0xf800000000000ULL)
+ over = 1;
+ break;
+ case 1: // sfmo 2
+ m1 = m & 0xfe00000000000ULL;
+ if(m1 && m1 != 0xfe00000000000ULL)
+ over = 1;
+ m <<= 2;
+ break;
+ case 2: // sfmo 4
+ m1 = m & 0xff80000000000ULL;
+ if(m1 && m1 != 0xff80000000000ULL)
+ over = 1;
+ m <<= 4;
+ break;
+ case 3: // sfmo -8
+ m >>= 8;
+ break;
+ }
+
+ // Rounder
+ rmode = (s->st1 & ST1_RND) >> ST1_RND_SHIFT;
+ m = (m + rounding[rmode]) & rmask[rmode];
+
+ // Second overflow detection
+ m1 = m & 0xf800000000000ULL;
+ if(m1 && m1 != 0xf800000000000ULL)
+ over = 1;
+
+ // Overflow handling
+ if(over) {
+ s->st1 |= ST1_MOV;
+ if(s->st1 & ST1_MOVM) {
+ if(m & 0x8000000000000ULL)
+ m = 0xffff800000000000ULL;
+ else
+ m = 0x00007fffffffffffULL;
+ }
+ }
+ return m;
+}
+#endif
+
+static noinline INT64 tms57002_macc_to_output_0(tms57002_t *s, INT64 rounding, UINT64 rmask)
+{
+ INT64 m = s->macc;
+ UINT64 m1;
+ int over = 0;
+
+ // Overflow detection and shifting
+ m1 = m & 0xf800000000000ULL;
+ if(m1 && m1 != 0xf800000000000ULL)
+ over = 1;
+
+ m = (m + rounding) & rmask;
+
+ // Second overflow detection
+ m1 = m & 0xf800000000000ULL;
+ if(m1 && m1 != 0xf800000000000ULL)
+ over = 1;
+
+ // Overflow handling
+ if(over) {
+ s->st1 |= ST1_MOV;
+ }
+ return m;
+}
+
+static noinline INT64 tms57002_macc_to_output_1(tms57002_t *s, INT64 rounding, UINT64 rmask)
+{
+ INT64 m = s->macc;
+ UINT64 m1;
+ int over = 0;
+
+ // Overflow detection and shifting
+ m1 = m & 0xfe00000000000ULL;
+ if(m1 && m1 != 0xfe00000000000ULL)
+ over = 1;
+ m <<= 2;
+
+ m = (m + rounding) & rmask;
+
+ // Second overflow detection
+ m1 = m & 0xf800000000000ULL;
+ if(m1 && m1 != 0xf800000000000ULL)
+ over = 1;
+
+ // Overflow handling
+ if(over) {
+ s->st1 |= ST1_MOV;
+ }
+ return m;
+}
+
+static noinline INT64 tms57002_macc_to_output_2(tms57002_t *s, INT64 rounding, UINT64 rmask)
+{
+ INT64 m = s->macc;
+ UINT64 m1;
+ int over = 0;
+
+ // Overflow detection and shifting
+ m1 = m & 0xff80000000000ULL;
+ if(m1 && m1 != 0xff80000000000ULL)
+ over = 1;
+ m <<= 4;
+
+ m = (m + rounding) & rmask;
+
+ // Second overflow detection
+ m1 = m & 0xf800000000000ULL;
+ if(m1 && m1 != 0xf800000000000ULL)
+ over = 1;
+
+ // Overflow handling
+ if(over) {
+ s->st1 |= ST1_MOV;
+ }
+ return m;
+}
+
+static noinline INT64 tms57002_macc_to_output_3(tms57002_t *s, INT64 rounding, UINT64 rmask)
+{
+ INT64 m = s->macc;
+ UINT64 m1;
+ int over = 0;
+
+ // Overflow detection and shifting
+ m >>= 8;
+
+ m = (m + rounding) & rmask;
+
+ // Second overflow detection
+ m1 = m & 0xf800000000000ULL;
+ if(m1 && m1 != 0xf800000000000ULL)
+ over = 1;
+
+ // Overflow handling
+ if(over) {
+ s->st1 |= ST1_MOV;
+ }
+ return m;
+}
+
+static noinline INT64 tms57002_macc_to_output_0s(tms57002_t *s, INT64 rounding, UINT64 rmask)
+{
+ INT64 m = s->macc;
+ UINT64 m1;
+ int over = 0;
+
+ // Overflow detection and shifting
+ m1 = m & 0xf800000000000ULL;
+ if(m1 && m1 != 0xf800000000000ULL)
+ over = 1;
+
+ m = (m + rounding) & rmask;
+
+ // Second overflow detection
+ m1 = m & 0xf800000000000ULL;
+ if(m1 && m1 != 0xf800000000000ULL)
+ over = 1;
+
+ // Overflow handling
+ if(over) {
+ s->st1 |= ST1_MOV;
+ if(m & 0x8000000000000ULL)
+ m = 0xffff800000000000ULL;
+ else
+ m = 0x00007fffffffffffULL;
+ }
+ return m;
+}
+
+static noinline INT64 tms57002_macc_to_output_1s(tms57002_t *s, INT64 rounding, UINT64 rmask)
+{
+ INT64 m = s->macc;
+ UINT64 m1;
+ int over = 0;
+
+ // Overflow detection and shifting
+ m1 = m & 0xfe00000000000ULL;
+ if(m1 && m1 != 0xfe00000000000ULL)
+ over = 1;
+ m <<= 2;
+
+ m = (m + rounding) & rmask;
+
+ // Second overflow detection
+ m1 = m & 0xf800000000000ULL;
+ if(m1 && m1 != 0xf800000000000ULL)
+ over = 1;
+
+ // Overflow handling
+ if(over) {
+ s->st1 |= ST1_MOV;
+ if(m & 0x8000000000000ULL)
+ m = 0xffff800000000000ULL;
+ else
+ m = 0x00007fffffffffffULL;
+ }
+ return m;
+}
+
+static noinline INT64 tms57002_macc_to_output_2s(tms57002_t *s, INT64 rounding, UINT64 rmask)
+{
+ INT64 m = s->macc;
+ UINT64 m1;
+ int over = 0;
+
+ // Overflow detection and shifting
+ m1 = m & 0xff80000000000ULL;
+ if(m1 && m1 != 0xff80000000000ULL)
+ over = 1;
+ m <<= 4;
+
+ m = (m + rounding) & rmask;
+
+ // Second overflow detection
+ m1 = m & 0xf800000000000ULL;
+ if(m1 && m1 != 0xf800000000000ULL)
+ over = 1;
+
+ // Overflow handling
+ if(over) {
+ s->st1 |= ST1_MOV;
+ if(m & 0x8000000000000ULL)
+ m = 0xffff800000000000ULL;
+ else
+ m = 0x00007fffffffffffULL;
+ }
+ return m;
+}
+
+static noinline INT64 tms57002_macc_to_output_3s(tms57002_t *s, INT64 rounding, UINT64 rmask)
+{
+ INT64 m = s->macc;
+ UINT64 m1;
+ int over = 0;
+
+ // Overflow detection and shifting
+ m >>= 8;
+
+ m = (m + rounding) & rmask;
+
+ // Second overflow detection
+ m1 = m & 0xf800000000000ULL;
+ if(m1 && m1 != 0xf800000000000ULL)
+ over = 1;
+
+ // Overflow handling
+ if(over) {
+ s->st1 |= ST1_MOV;
+ if(m & 0x8000000000000ULL)
+ m = 0xffff800000000000ULL;
+ else
+ m = 0x00007fffffffffffULL;
+ }
+ return m;
+}
+
+#ifdef UNUSED_FUNCTION
+static INT64 tms57002_check_macc_overflow(tms57002_t *s)
+{
+ INT64 m = s->macc;
+ UINT64 m1;
+ int over = 0;
+
+ // Overflow detection
+ switch((s->st1 & ST1_SFMO) >> ST1_SFMO_SHIFT) {
+ case 0: // sfmo 0
+ m1 = m & 0xf800000000000ULL;
+ if(m1 && m1 != 0xf800000000000ULL)
+ over = 1;
+ break;
+ case 1: // sfmo 2
+ m1 = m & 0xfe00000000000ULL;
+ if(m1 && m1 != 0xfe00000000000ULL)
+ over = 1;
+ break;
+ case 2: // sfmo 4
+ m1 = m & 0xff80000000000ULL;
+ if(m1 && m1 != 0xff80000000000ULL)
+ over = 1;
+ break;
+ case 3: // sfmo -8
+ break;
+ }
+
+ // Overflow handling
+ if(over) {
+ s->st1 |= ST1_MOV;
+ if(s->st1 & ST1_MOVM) {
+ if(m & 0x8000000000000ULL)
+ m = 0xffff800000000000ULL;
+ else
+ m = 0x00007fffffffffffULL;
+ }
+ }
+ return m;
+}
+#endif
+
+static noinline INT64 tms57002_check_macc_overflow_0(tms57002_t *s)
+{
+ INT64 m = s->macc;
+ UINT64 m1;
+
+ // Overflow detection
+ m1 = m & 0xf800000000000ULL;
+ if(m1 && m1 != 0xf800000000000ULL) {
+ s->st1 |= ST1_MOV;
+ }
+ return m;
+}
+
+static noinline INT64 tms57002_check_macc_overflow_1(tms57002_t *s)
+{
+ INT64 m = s->macc;
+ UINT64 m1;
+
+ // Overflow detection
+ m1 = m & 0xfe00000000000ULL;
+ if(m1 && m1 != 0xfe00000000000ULL) {
+ s->st1 |= ST1_MOV;
+ }
+ return m;
+}
+
+static noinline INT64 tms57002_check_macc_overflow_2(tms57002_t *s)
+{
+ INT64 m = s->macc;
+ UINT64 m1;
+
+ // Overflow detection
+ m1 = m & 0xff80000000000ULL;
+ if(m1 && m1 != 0xff80000000000ULL) {
+ s->st1 |= ST1_MOV;
+ }
+ return m;
+}
+
+static INT64 tms57002_check_macc_overflow_3(tms57002_t *s)
+{
+ return s->macc;
+}
+
+static noinline INT64 tms57002_check_macc_overflow_0s(tms57002_t *s)
+{
+ INT64 m = s->macc;
+ UINT64 m1;
+
+ // Overflow detection
+ m1 = m & 0xf800000000000ULL;
+ if(m1 && m1 != 0xf800000000000ULL) {
+ s->st1 |= ST1_MOV;
+ if(m & 0x8000000000000ULL)
+ m = 0xffff800000000000ULL;
+ else
+ m = 0x00007fffffffffffULL;
+ }
+ return m;
+}
+
+static noinline INT64 tms57002_check_macc_overflow_1s(tms57002_t *s)
+{
+ INT64 m = s->macc;
+ UINT64 m1;
+
+ // Overflow detection
+ m1 = m & 0xfe00000000000ULL;
+ if(m1 && m1 != 0xfe00000000000ULL) {
+ s->st1 |= ST1_MOV;
+ if(m & 0x8000000000000ULL)
+ m = 0xffff800000000000ULL;
+ else
+ m = 0x00007fffffffffffULL;
+ }
+ return m;
+}
+
+static noinline INT64 tms57002_check_macc_overflow_2s(tms57002_t *s)
+{
+ INT64 m = s->macc;
+ UINT64 m1;
+
+ // Overflow detection
+ m1 = m & 0xff80000000000ULL;
+ if(m1 && m1 != 0xff80000000000ULL) {
+ s->st1 |= ST1_MOV;
+ if(m & 0x8000000000000ULL)
+ m = 0xffff800000000000ULL;
+ else
+ m = 0x00007fffffffffffULL;
+ }
+ return m;
+}
+
+static INT64 tms57002_check_macc_overflow_3s(tms57002_t *s)
+{
+ return s->macc;
+}
+
+#ifdef UNUSED_FUNCTION
+static INT64 tms57002_macc_to_loop(tms57002_t *s)
+{
+ INT64 m = s->macc;
+
+ // sfma shifting
+ switch((s->st1 & ST1_SFMA) >> ST1_SFMA_SHIFT) {
+ case 0: // sfma 0
+ break;
+ case 1: // sfma 2
+ m <<= 2;
+ break;
+ case 2: // sfma 4
+ m <<= 4;
+ break;
+ case 3: // sfma -16
+ if(m & 0x8000000000000ULL)
+ m |= 0xfff0000000000000ULL;
+ m >>= 16;
+ break;
+ }
+
+ return m;
+}
+
+static void tms57002_execute_cat1(tms57002_t *s, UINT32 opcode)
+{
+ UINT32 c, d;
+ INT64 r;
+ switch(opcode >> 18) {
+ case 0x00: // nop
+ break;
+
+#define INTRP1
+#include "cpu/tms57002/tms57002.inc"
+#undef INTRP1
+
+ default:
+ fatalerror("Unhandled case in tms57002_execute_cat1");
+ }
+}
+
+static void tms57002_execute_cat2_pre(tms57002_t *s, UINT32 opcode)
+{
+ switch((opcode >> 11) & 0x7f) {
+ case 0x00: // nop
+ break;
+
+#define INTRP2A
+#include "cpu/tms57002/tms57002.inc"
+#undef INTRP2A
+
+ default:
+ fatalerror("Unhandled case in tms57002_execute_cat2_pre");
+ }
+}
+
+static void tms57002_execute_cat2_post(tms57002_t *s, UINT32 opcode)
+{
+ UINT32 c;
+ switch((opcode >> 11) & 0x7f) {
+ case 0x00: // nop
+ break;
+
+#define INTRP2B
+#include "cpu/tms57002/tms57002.inc"
+#undef INTRP2B
+
+ default:
+ fatalerror("Unhandled case in tms57002_execute_cat2_post");
+ }
+}
+
+static void tms57002_execute_cat3(tms57002_t *s, UINT32 opcode)
+{
+ switch((opcode >> 11) & 0x7f) {
+ case 0x00: // nop
+ break;
+
+#define INTRP3
+#include "cpu/tms57002/tms57002.inc"
+#undef INTRP3
+
+ default:
+ fatalerror("Unhandled case in tms57002_execute_cat3");
+ }
+}
+
+void tms57002_execute(tms57002_t *s)
+{
+ while(!(s->sti & (S_IDLE | IN_PLOAD | IN_CLOAD))) {
+ UINT32 opcode = s->program->read_dword(s->pc << 2);
+
+ if(s->sti & (S_READ|S_WRITE)) {
+ if(s->sti & S_READ)
+ tms57002_xm_step_read(s);
+ else
+ tms57002_xm_step_write(s);
+ }
+
+ if((opcode & 0xfc0000) == 0xfc0000)
+ tms57002_execute_cat3(s, opcode);
+ else {
+ tms57002_execute_cat2_pre(s, opcode);
+ tms57002_execute_cat1(s, opcode);
+ tms57002_execute_cat2_post(s, opcode);
+ }
+
+ if(s->rptc)
+ s->rptc--;
+ else if(s->sti & S_BRANCH)
+ s->sti &= ~S_BRANCH;
+ else
+ s->pc++; // Wraps if it reaches 256
+
+ if(s->rptc_next) {
+ s->rptc = s->rptc_next;
+ s->rptc_next = 0;
+ }
+ }
+}
+#endif
+
+static void tms57002_cache_flush(tms57002_t *s)
+{
+ int i;
+ s->cache.hused = s->cache.iused = 0;
+ for(i=0; i != 256; i++)
+ s->cache.hashbase[i] = -1;
+ for(i=0; i != HBS; i++) {
+ s->cache.hashnode[i].st1 = 0;
+ s->cache.hashnode[i].ipc = -1;
+ s->cache.hashnode[i].next = -1;
+ }
+ for(i=0; i != IBS; i++) {
+ s->cache.inst[i].op = 0;
+ s->cache.inst[i].next = -1;
+ s->cache.inst[i].param = 0;
+ }
+}
+
+static void tms57002_add_one(tms57002_t *s, cstate *cs, unsigned short op, UINT8 param)
+{
+ short ipc = s->cache.iused++;
+ s->cache.inst[ipc].op = op;
+ s->cache.inst[ipc].param = param;
+ s->cache.inst[ipc].next = -1;
+ if(cs->ipc != -1)
+ s->cache.inst[cs->ipc].next = ipc;
+ cs->ipc = ipc;
+ if(cs->hnode != -1) {
+ s->cache.hashnode[cs->hnode].ipc = ipc;
+ cs->hnode = -1;
+ }
+}
+
+static void tms57002_decode_one(tms57002_t *s, UINT32 opcode, cstate *cs, void (*dec)(tms57002_t *s, UINT32 opcode, unsigned short *op, cstate *cs))
+{
+ unsigned short op = 0;
+ dec(s, opcode, &op, cs);
+ if(!op)
+ return;
+ tms57002_add_one(s, cs, op, opcode & 0xff);
+}
+
+static short tms57002_get_hash(tms57002_t *s, unsigned char adr, UINT32 st1, short *pnode)
+{
+ short hnode;
+ st1 &= ST1_CACHE;
+ *pnode = -1;
+ hnode = s->cache.hashbase[adr];
+ while(hnode != -1) {
+ if(s->cache.hashnode[hnode].st1 == st1)
+ return s->cache.hashnode[hnode].ipc;
+ *pnode = hnode;
+ hnode = s->cache.hashnode[hnode].next;
+ }
+ return -1;
+}
+
+static short tms57002_get_hashnode(tms57002_t *s, unsigned char adr, UINT32 st1, short pnode)
+{
+ short hnode = s->cache.hused++;
+ s->cache.hashnode[hnode].st1 = st1 & ST1_CACHE;
+ s->cache.hashnode[hnode].ipc = -1;
+ s->cache.hashnode[hnode].next = -1;
+ if(pnode == -1)
+ s->cache.hashbase[adr] = hnode;
+ else
+ s->cache.hashnode[pnode].next = hnode;
+ return hnode;
+}
+
+static int tms57002_decode_get_pc(tms57002_t *s)
+{
+ UINT32 st1 = s->st1;
+ short pnode, res;
+ cstate cs;
+ UINT8 adr = s->pc;
+
+ res = tms57002_get_hash(s, adr, st1, &pnode);
+ if(res != -1)
+ return res;
+
+ if(HBS - s->cache.hused < 256 || IBS - s->cache.iused < 256*3) {
+ tms57002_cache_flush(s);
+ pnode = -1;
+ }
+
+ cs.hnode = res = tms57002_get_hashnode(s, adr, st1, pnode);
+ cs.ipc = -1;
+ cs.branch = 0;
+
+ for(;;) {
+ short ipc;
+ UINT32 opcode = s->program->read_dword(adr << 2);
+
+ if((opcode & 0xfc0000) == 0xfc0000)
+ tms57002_decode_one(s, opcode, &cs, tms57002_decode_cat3);
+ else {
+ tms57002_decode_one(s, opcode, &cs, tms57002_decode_cat2_pre);
+ tms57002_decode_one(s, opcode, &cs, tms57002_decode_cat1);
+ tms57002_decode_one(s, opcode, &cs, tms57002_decode_cat2_post);
+ }
+ tms57002_add_one(s, &cs, 0, 0);
+
+ if(cs.branch)
+ break;
+
+ adr++;
+ ipc = tms57002_get_hash(s, adr, st1, &pnode);
+ if(ipc != -1) {
+ s->cache.inst[cs.ipc].next = ipc;
+ break;
+ }
+ cs.hnode = tms57002_get_hashnode(s, adr, s->st1, pnode);
+ }
+
+ s->st1 = st1;
+ return s->cache.hashnode[res].ipc;
+}
+
+static CPU_EXECUTE(tms57002)
+{
+ tms57002_t *s = get_safe_token(device);
+ int ipc = -1;
+
+ while(s->icount > 0 && !(s->sti & (S_IDLE | IN_PLOAD | IN_CLOAD))) {
+ int iipc;
+
+ debugger_instruction_hook(device, s->pc);
+
+ if(ipc == -1)
+ ipc = tms57002_decode_get_pc(s);
+
+ iipc = ipc;
+
+ if(s->sti & (S_READ|S_WRITE)) {
+ if(s->sti & S_READ)
+ tms57002_xm_step_read(s);
+ else
+ tms57002_xm_step_write(s);
+ }
+
+ for(;;) {
+ UINT32 c, d;
+ INT64 r;
+ const icd *i = s->cache.inst + ipc;
+
+ ipc = i->next;
+ switch(i->op) {
+ case 0:
+ goto inst;
+
+#define CINTRP
+#include "cpu/tms57002/tms57002.inc"
+#undef CINTRP
+
+ default:
+ fatalerror("Unhandled opcode in tms57002_execute");
+ }
+ }
+ inst:
+ s->icount--;
+
+ if(s->rptc) {
+ s->rptc--;
+ ipc = iipc;
+ } else if(s->sti & S_BRANCH) {
+ s->sti &= ~S_BRANCH;
+ ipc = -1;
+ } else
+ s->pc++; // Wraps if it reaches 256, next wraps too
+
+ if(s->rptc_next) {
+ s->rptc = s->rptc_next;
+ s->rptc_next = 0;
+ }
+ }
+
+ if(s->icount > 0)
+ s->icount = 0;
+}
+
+static CPU_INIT(tms57002)
+{
+ tms57002_t *s = get_safe_token(device);
+ tms57002_cache_flush(s);
+ s->sti = S_IDLE;
+ s->program = device->space(AS_PROGRAM);
+ s->data = device->space(AS_DATA);
+}
+
+
+static CPU_SET_INFO(tms57002)
+{
+}
+
+static ADDRESS_MAP_START(internal_pgm, AS_PROGRAM, 32)
+ AM_RANGE(0x000, 0x3ff) AM_RAM
+ADDRESS_MAP_END
+
+CPU_GET_INFO(tms57002)
+{
+ tms57002_t *s = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch(state) {
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(tms57002_t); break;
+ case CPUINFO_INT_INPUT_LINES: 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 = 3; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = -2; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 20; 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_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(tms57002); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(tms57002); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(tms57002); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(tms57002); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(tms57002); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &s->icount; break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM:info->internal_map32 = ADDRESS_MAP_NAME(internal_pgm); break;
+ case DEVINFO_STR_NAME: strcpy( info->s, "TMS57002" ); break;
+ case DEVINFO_STR_FAMILY: strcpy( info->s, "Texas Instruments TMS57002 (DASP)" ); 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 Olivier Galibert" ); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(TMS57002, tms57002);
diff --git a/trunk/src/emu/cpu/tms57002/tms57002.h b/trunk/src/emu/cpu/tms57002/tms57002.h
new file mode 100644
index 00000000000..f8ea1813c16
--- /dev/null
+++ b/trunk/src/emu/cpu/tms57002/tms57002.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#ifndef __TMS57002_H__
+#define __TMS57002_H__
+
+
+enum {
+ TMS57002_PC=1
+};
+
+DECLARE_LEGACY_CPU_DEVICE(TMS57002, tms57002);
+
+WRITE8_DEVICE_HANDLER(tms57002_data_w);
+READ8_DEVICE_HANDLER(tms57002_data_r);
+
+WRITE8_DEVICE_HANDLER(tms57002_pload_w);
+WRITE8_DEVICE_HANDLER(tms57002_cload_w);
+READ8_DEVICE_HANDLER(tms57002_empty_r);
+READ8_DEVICE_HANDLER(tms57002_dready_r);
+
+void tms57002_sync(device_t *cpu);
+
+#endif
+
diff --git a/trunk/src/emu/cpu/tms57002/tms57kdec.c b/trunk/src/emu/cpu/tms57002/tms57kdec.c
new file mode 100644
index 00000000000..cd6ad44c708
--- /dev/null
+++ b/trunk/src/emu/cpu/tms57002/tms57kdec.c
@@ -0,0 +1,91 @@
+#include "emu.h"
+#include "debugger.h"
+#include "tms57002.h"
+#include "tms57kpr.h"
+
+#ifdef __GNUC__
+#define noinline __attribute__((noinline))
+#else
+#define noinline /* */
+#endif
+
+static void tms57002_decode_error(tms57002_t *s, UINT32 opcode)
+{
+ char buf[256];
+ UINT8 opr[3];
+ if(s->unsupported_inst_warning)
+ return;
+
+ s->unsupported_inst_warning = 1;
+ opr[0] = opcode;
+ opr[1] = opcode >> 8;
+ opr[2] = opcode >> 16;
+
+ CPU_DISASSEMBLE_NAME(tms57002)(0, buf, s->pc, opr, opr, 0);
+ popmessage("tms57002: %s - Contact Mamedev", buf);
+}
+
+void tms57002_decode_cat1(tms57002_t *s, UINT32 opcode, unsigned short *op, cstate *cs)
+{
+ switch(opcode >> 18) {
+ case 0x00: // nop
+ break;
+
+#define CDEC1
+#include "cpu/tms57002/tms57002.inc"
+#undef CDEC1
+
+ default:
+ tms57002_decode_error(s, opcode);
+ break;
+ }
+}
+
+void tms57002_decode_cat2_pre(tms57002_t *s, UINT32 opcode, unsigned short *op, cstate *cs)
+{
+ switch((opcode >> 11) & 0x7f) {
+ case 0x00: // nop
+ break;
+
+#define CDEC2A
+#include "cpu/tms57002/tms57002.inc"
+#undef CDEC2A
+
+ default:
+ tms57002_decode_error(s, opcode);
+ break;
+ }
+}
+
+void tms57002_decode_cat2_post(tms57002_t *s, UINT32 opcode, unsigned short *op, cstate *cs)
+{
+ switch((opcode >> 11) & 0x7f) {
+ case 0x00: // nop
+ break;
+
+#define CDEC2B
+#include "cpu/tms57002/tms57002.inc"
+#undef CDEC2B
+
+ default:
+ tms57002_decode_error(s, opcode);
+ break;
+ }
+}
+
+void tms57002_decode_cat3(tms57002_t *s, UINT32 opcode, unsigned short *op, cstate *cs)
+{
+ switch((opcode >> 11) & 0x7f) {
+ case 0x00: // nop
+ break;
+
+#define CDEC3
+#include "cpu/tms57002/tms57002.inc"
+#undef CDEC3
+
+ default:
+ tms57002_decode_error(s, opcode);
+ break;
+ }
+}
+
diff --git a/trunk/src/emu/cpu/tms57002/tms57kpr.h b/trunk/src/emu/cpu/tms57002/tms57kpr.h
new file mode 100644
index 00000000000..5192974ae8c
--- /dev/null
+++ b/trunk/src/emu/cpu/tms57002/tms57kpr.h
@@ -0,0 +1,171 @@
+#ifndef TMS57KPRIVATE_H
+#define TMS57KPRIVATE_H
+
+CPU_DISASSEMBLE(tms57002);
+
+#ifdef __GNUC__
+#define noinline __attribute__((noinline))
+#else
+#define noinline /* */
+#endif
+
+enum {
+ IN_PLOAD = 0x00000001,
+ IN_CLOAD = 0x00000002,
+ SU_CVAL = 0x00000004,
+ SU_MASK = 0x00000018, SU_ST0 = 0x00, SU_ST1 = 0x08, SU_PRG = 0x10,
+ S_IDLE = 0x00000020,
+ S_READ = 0x00000040,
+ S_WRITE = 0x00000080,
+ S_BRANCH = 0x00000100,
+ S_HOST = 0x00000200
+};
+
+enum {
+ ST0_INCS = 0x000001,
+ ST0_DIRI = 0x000002,
+ ST0_FI = 0x000004,
+ ST0_SIM = 0x000008,
+ ST0_PLRI = 0x000020,
+ ST0_PBCI = 0x000040,
+ ST0_DIRO = 0x000080,
+ ST0_FO = 0x000100,
+ ST0_SOM = 0x000600,
+ ST0_PLRO = 0x000800,
+ ST0_PBCO = 0x001000,
+ ST0_CNS = 0x002000,
+ ST0_WORD = 0x004000,
+ ST0_SEL = 0x008000,
+ ST0_M = 0x030000, ST0_M_64K = 0x000000, ST0_M_256K = 0x010000, ST0_M_1M = 0x020000,
+ ST0_SRAM = 0x200000,
+
+ ST1_AOV = 0x000001,
+ ST1_SFAI = 0x000002,
+ ST1_SFAO = 0x000004,
+ ST1_MOVM = 0x000020,
+ ST1_MOV = 0x000040,
+ ST1_SFMA = 0x000180, ST1_SFMA_SHIFT = 7,
+ ST1_SFMO = 0x001800, ST1_SFMO_SHIFT = 11,
+ ST1_RND = 0x038000, ST1_RND_SHIFT = 15,
+ ST1_CRM = 0x0C0000, ST1_CRM_SHIFT = 18, ST1_CRM_32 = 0x000000, ST1_CRM_16H = 0x040000, ST1_CRM_16L = 0x080000,
+ ST1_DBP = 0x100000,
+ ST1_CAS = 0x200000,
+
+ ST1_CACHE = ST1_SFAI|ST1_SFAO|ST1_MOVM|ST1_SFMA|ST1_SFMO|ST1_RND|ST1_CRM|ST1_DBP
+};
+
+enum { BR_UB, BR_CB, BR_IDLE };
+
+enum { IBS = 8192, HBS = 4096 };
+
+typedef struct {
+ unsigned short op;
+ short next;
+ unsigned char param;
+} icd;
+
+typedef struct {
+ unsigned int st1;
+ short ipc;
+ short next;
+} hcd;
+
+typedef struct {
+ short hashbase[256];
+ hcd hashnode[HBS];
+ icd inst[IBS];
+ int hused, iused;
+} cd;
+
+typedef struct {
+ int branch;
+ short hnode;
+ short ipc;
+} cstate;
+
+typedef struct {
+ INT64 macc;
+
+ UINT32 cmem[256];
+ UINT32 dmem0[256];
+ UINT32 dmem1[32];
+
+ UINT32 si[4], so[4];
+
+ UINT32 st0, st1, sti;
+ UINT32 aacc, xoa, xba, xwr, xrd, creg;
+
+ UINT8 pc, ca, id, ba0, ba1, rptc, rptc_next, sa;
+
+ UINT32 xm_adr;
+
+ UINT8 host[4], hidx, allow_update;
+
+ cd cache;
+
+ address_space *program, *data;
+ int icount;
+ int unsupported_inst_warning;
+} tms57002_t;
+
+void tms57002_decode_cat1(tms57002_t *s, UINT32 opcode, unsigned short *op, cstate *cs);
+void tms57002_decode_cat2_pre(tms57002_t *s, UINT32 opcode, unsigned short *op, cstate *cs);
+void tms57002_decode_cat3(tms57002_t *s, UINT32 opcode, unsigned short *op, cstate *cs);
+void tms57002_decode_cat2_post(tms57002_t *s, UINT32 opcode, unsigned short *op, cstate *cs);
+
+INLINE int xmode(UINT32 opcode, char type)
+{
+ if(((opcode & 0x400) && (type == 'c')) || (!(opcode & 0x400) && (type == 'd'))) {
+ if(opcode & 0x100)
+ return 0;
+ else if(opcode & 0x80)
+ return 2;
+ else
+ return 1;
+ } else if(opcode & 0x200)
+ return 2;
+
+ return 1;
+}
+
+INLINE int sfao(UINT32 st1)
+{
+ return st1 & ST1_SFAO ? 1 : 0;
+}
+
+INLINE int dbp(UINT32 st1)
+{
+ return st1 & ST1_DBP ? 1 : 0;
+}
+
+INLINE int crm(UINT32 st1)
+{
+ return (st1 & ST1_CRM) >> ST1_CRM_SHIFT;
+}
+
+INLINE int sfai(UINT32 st1)
+{
+ return st1 & ST1_SFAI ? 1 : 0;
+}
+
+INLINE int sfmo(UINT32 st1)
+{
+ return (st1 & ST1_SFMO) >> ST1_SFMO_SHIFT;
+}
+
+INLINE int rnd(UINT32 st1)
+{
+ return (st1 & ST1_RND) >> ST1_RND_SHIFT;
+}
+
+INLINE int movm(UINT32 st1)
+{
+ return st1 & ST1_MOVM ? 1 : 0;
+}
+
+INLINE int sfma(UINT32 st1)
+{
+ return (st1 & ST1_SFMA) >> ST1_SFMA_SHIFT;
+}
+
+#endif
diff --git a/trunk/src/emu/cpu/tms57002/tmsinstr.lst b/trunk/src/emu/cpu/tms57002/tmsinstr.lst
new file mode 100644
index 00000000000..6c1583f1e4e
--- /dev/null
+++ b/trunk/src/emu/cpu/tms57002/tmsinstr.lst
@@ -0,0 +1,535 @@
+abs 1 01 1 n
+ abs
+ s->aacc = %a;
+ if(((INT32)s->aacc) < 0) {
+ s->aacc = - s->aacc;
+ if(((INT32)s->aacc) < 0)
+ s->st1 |= ST1_AOV;
+ }
+
+add 1 03 1 y
+ add %d,a
+ %wa((INT64)(INT32)%d + (INT64)(INT32)%a);
+
+add 1 04 1 y
+ add %c,a
+ %wa((INT64)(INT32)%c + (INT64)(INT32)%a);
+
+add 1 05 1 y
+ add %d,m
+ %sfai(d, %d);
+ %wa((INT64)(INT32)d + (%mo >> 16));
+
+add 1 06 1 y
+ add %c,m
+ %wa((INT64)(INT32)%c + (%mo >> 16));
+
+add 1 07 1 y
+ add %d,%c
+ %wa((INT64)(INT32)%d + (INT64)(INT32)%c);
+
+adds 1 08 1 y
+ adds %d
+
+amac 1 2d 2 y
+ amac %d,%c,a
+
+ampy 1 2c 2 y
+ ampy %d,%c,a
+
+and 1 14 1 n
+ and %d,a
+ %sfai(d, %d);
+ s->aacc &= d;
+
+and 1 15 1 n
+ and %c,a
+ s->aacc &= %c;
+
+and 1 16 1 n
+ and %d,%c
+ %sfai(d, %d);
+ s->aacc = %c & d;
+
+b 3 48 3 n b
+ b %i
+ %b(%i);
+
+bgz 3 50 3 n cb
+ bgz %i
+ if(((INT32)s->aacc) > 0) {
+ %b(%i);
+ }
+
+bioz 3 70 3 n cb
+ bioz %i
+
+blz 3 58 3 n cb
+ blz %i
+ if(((INT32)s->aacc) < 0) {
+ %b(%i);
+ }
+
+bnz 3 60 3 n cb
+ bnz %i
+ if(s->aacc) {
+ %b(%i);
+ }
+
+bv 3 78 3 n cb
+ bv %i
+ if(s->st1 & ST1_AOV) {
+ s->st1 &= ~ST1_AOV;
+ %b(%i);
+ }
+
+cmpl 1 13 1 n
+ cmpl
+
+dimh 2a 14 1 n
+ dimh si0_l
+
+dimh 2a 15 1 n
+ dimh si0_r
+
+dimh 2a 16 1 n
+ dimh si1_l
+
+dimh 2a 17 1 n
+ dimh si1_r
+
+diml 2a 18 1 n
+ diml si0_l
+
+diml 2a 19 1 n
+ diml si0_r
+
+diml 2a 1a 1 n
+ diml si1_l
+
+diml 2a 1b 1 n
+ diml si1_r
+
+dis 2a 10 1 n
+ dis si0_l,%d
+ %wd(s->si[0]);
+
+dis 2a 11 1 n
+ dis si0_r,%d
+ %wd(s->si[1]);
+
+dis 2a 12 1 n
+ dis si1_l,%d
+ %wd(s->si[2]);
+
+dis 2a 13 1 n
+ dis si1_r,%d
+ %wd(s->si[3]);
+
+domh 2a 20 1 n
+ domh so0_l
+ s->so[0] = (%mo >> 24) & 0xffffff;
+
+domh 2a 21 1 n
+ domh so0_r
+ s->so[1] = (%mo >> 24) & 0xffffff;
+
+domh 2a 22 1 n
+ domh so1_l
+ s->so[2] = (%mo >> 24) & 0xffffff;
+
+domh 2a 23 1 n
+ domh so1_r
+ s->so[3] = (%mo >> 24) & 0xffffff;
+
+doml 2a 24 1 n
+ doml so0_l
+
+doml 2a 25 1 n
+ doml so0_r
+
+doml 2a 26 1 n
+ doml so1_l
+
+doml 2a 27 1 n
+ doml so1_r
+
+dos 2b 1c 1 n
+ dos so0_l,%d
+
+dos 2b 1d 1 n
+ dos so0_r,%d
+
+dos 2b 1e 1 n
+ dos so1_l,%d
+
+dos 2b 1f 1 n
+ dos so1_r,%d
+
+idle 3 08 1 n i
+ idle
+ s->sti |= S_IDLE;
+
+incd 2a 42 1 y
+ incd
+
+lacc 1 12 1 n
+ lacc %c
+ s->aacc = %c;
+
+lacd 1 11 1 n
+ lacd %d
+ %sfai(d, %d);
+ s->aacc = d;
+
+lbrk 3 28 1 n
+ lbrk %i
+
+lcaa 2a 08 1 y
+ lcaa
+ s->ca = %a >> 24;
+
+lcac 3 40 1 n
+ lcac %i
+ if(((INT32)s->aacc) >= 0)
+ s->ca = %i;
+
+lcak 3 18 1 n
+ lcak %i
+ s->ca = %i;
+
+ldpk 2a 44 1 n f
+ ldpk 0
+ s->st1 &= ~ST1_DBP;
+
+ldpk 2a 45 1 n f
+ ldpk 1
+ s->st1 |= ST1_DBP;
+
+ld0t 2b 0c 1 y
+ ld0t %d
+
+lira 2a 09 1 y
+ lira
+ s->id = %a >> 24;
+
+lirk 3 20 1 n
+ lirk %i
+ s->id = %i;
+
+lmhc 1 33 1 n
+ lmhc %c
+ s->macc = ((INT64)(INT32)%c) << 16;
+
+lmhd 1 31 1 n
+ lmhd %d
+ s->macc = ((INT64)(INT32)%d) << 16;
+
+lmld 1 32 1 n
+ lmld %d
+ s->macc = (s->macc & ~0xffffffULL) | %d24;
+
+lpc 2b 31 1 n
+ lpc %c
+ if(s->sti & S_HOST)
+ break;
+ c = %c;
+ s->host[0] = c >> 24;
+ s->host[1] = c >> 16;
+ s->host[2] = c >> 8;
+ s->host[3] = c;
+ s->hidx = 0;
+ s->sti |= S_HOST;
+
+lpd 2b 30 1 n
+ lpd %d
+
+mac 1 24 1 y
+ mac %d,%c
+ d = %d24;
+ if(d & 0x00800000)
+ d |= 0xff000000;
+ s->creg = c = %c;
+ r = (INT64)(INT32)c * (INT64)(INT32)d;
+ s->macc = %ml + (r >> 7);
+
+mac 1 25 1 y
+ mac a,%d
+
+mac 1 26 1 y
+ mac %c,a
+ s->creg = c = %c;
+ r = (INT64)(INT32)c * (INT64)(INT32)%a;
+ s->macc = %ml + (r >> 15);
+
+macs 1 2e 1 y
+ macs %c,a
+ s->creg = c = %c;
+ r = (INT64)(INT32)c * (INT64)(INT32)%a;
+ s->macc = %ml + (r >> 14);
+
+macu 1 29 1 y
+ macu %d,%c
+ d = %d24; // d is 24bits unsigned
+ s->creg = c = %c;
+ r = (INT64)(INT32)c * (INT64)d;
+ s->macc = %ml + (r >> 7);
+
+macu 1 2a 1 y
+ macu a,%d
+ d = %d24; // d is 24bits unsigned
+ s->creg = c = %a;
+ r = (INT64)(INT32)c * (INT64)d;
+ s->macc = %ml + (r >> 7);
+
+mpy 1 21 1 y
+ mpy %d,%c
+ d = %d24;
+ if(d & 0x00800000)
+ d |= 0xff000000;
+ s->creg = c = %c;
+ r = (INT64)(INT32)c * (INT64)(INT32)d;
+ s->macc = r >> 7;
+
+mpy 1 22 1 y
+ mpy %c,a
+ s->creg = c = %c;
+ r = (INT64)(INT32)c * (INT64)(INT32)%a;
+ s->macc = r >> 15;
+
+mpy 1 23 1 y
+ mpy creg,%d
+
+mpyu 1 28 1 y
+ mpyu %d,%c
+ s->creg = c = %c;
+ d = %d24; // d is 24bits unsigned
+ r = (INT64)(INT32)c * (INT64)d;
+ s->macc = r >> 7;
+
+neg 1 02 1 n
+ neg
+
+or 1 17 1 n
+ or %d,a
+ %sfai(d, %d);
+ s->aacc |= d;
+
+or 1 18 1 n
+ or %c,a
+ s->aacc |= %c;
+
+or 1 19 1 n
+ or %d,%c
+ %sfai(d, %d);
+ s->aacc = %c | d;
+
+raov 2a 38 1 n
+ raov
+
+rde 1 39 1 n
+ rde %c
+ if(s->sti & (S_READ|S_WRITE))
+ break;
+ s->xoa = %c;
+ tms57002_xm_init(s);
+ s->sti |= S_READ;
+
+ref 2a 0e 1 n
+ ref
+ /* nothing to do */
+
+rmom 2a 40 1 n f
+ rmom
+ s->st1 &= ~ST1_MOVM;
+
+rmov 2a 3a 1 n
+ rmov
+ s->st1 &= ~ST1_MOV;
+
+rnd 2a 68 1 n f
+ rnd 48
+ s->st1 = (s->st1 & ~ST1_RND) | (0 << ST1_RND_SHIFT);
+
+rnd 2a 69 1 n f
+ rnd 32
+ s->st1 = (s->st1 & ~ST1_RND) | (1 << ST1_RND_SHIFT);
+
+rnd 2a 6a 1 n f
+ rnd 24
+ s->st1 = (s->st1 & ~ST1_RND) | (2 << ST1_RND_SHIFT);
+
+rnd 2a 6b 1 n f
+ rnd 20
+ s->st1 = (s->st1 & ~ST1_RND) | (3 << ST1_RND_SHIFT);
+
+rnd 2a 6c 1 n f
+ rnd 16
+ s->st1 = (s->st1 & ~ST1_RND) | (4 << ST1_RND_SHIFT);
+
+rnd 2a 6d 1 n f
+ rnd <5>
+ s->st1 = (s->st1 & ~ST1_RND) | (5 << ST1_RND_SHIFT);
+
+rnd 2a 6e 1 n f
+ rnd <6>
+ s->st1 = (s->st1 & ~ST1_RND) | (6 << ST1_RND_SHIFT);
+
+rnd 2a 6f 1 n f
+ rnd <7>
+ s->st1 = (s->st1 & ~ST1_RND) | (7 << ST1_RND_SHIFT);
+
+rptk 3 10 1 n
+ rptk %i
+ s->rptc_next = %i;
+
+sacc 2a 01 1 y
+ sacc %c
+ %wc(%a);
+
+sacd 2a 02 1 y
+ sacd %d
+ %wd(%a >> 8);
+
+scrm 2a 48 1 n f
+ scrm 32
+ s->st1 = (s->st1 & ~ST1_CRM) | (0 << ST1_CRM_SHIFT);
+
+scrm 2a 49 1 n f
+ scrm 16h
+ s->st1 = (s->st1 & ~ST1_CRM) | (1 << ST1_CRM_SHIFT);
+
+scrm 2a 4a 1 n f
+ scrm 16l
+ s->st1 = (s->st1 & ~ST1_CRM) | (2 << ST1_CRM_SHIFT);
+
+scrm 2a 4b 1 n f
+ scrm <3>
+ s->st1 = (s->st1 & ~ST1_CRM) | (3 << ST1_CRM_SHIFT);
+
+sfai 2b 54 1 n f
+ sfai 0
+ s->st1 &= ~ST1_SFAI;
+
+sfai 2b 55 1 n f
+ sfai -1
+ s->st1 |= ST1_SFAI;
+
+sfao 2a 50 1 n f
+ sfao 0
+ s->st1 &= ~ST1_SFAO;
+
+sfao 2a 51 1 n f
+ sfao 7
+ s->st1 |= ST1_SFAI;
+
+sfma 2b 58 1 n f
+ sfma 0
+ s->st1 = (s->st1 & ~ST1_SFMA) | (0 << ST1_SFMA_SHIFT);
+
+sfma 2b 59 1 n f
+ sfma 2
+ s->st1 = (s->st1 & ~ST1_SFMA) | (1 << ST1_SFMA_SHIFT);
+
+sfma 2b 5a 1 n f
+ sfma 4
+ s->st1 = (s->st1 & ~ST1_SFMA) | (2 << ST1_SFMA_SHIFT);
+
+sfma 2b 5b 1 n f
+ sfma -16
+ s->st1 = (s->st1 & ~ST1_SFMA) | (3 << ST1_SFMA_SHIFT);
+
+sfml 1 34 1 y
+ sfml
+ s->macc = (s->macc & 0x8000000000000ULL) | ((s->macc << 1) & 0x7ffffffffffffULL);
+
+sfmo 2a 60 1 n f
+ sfmo 0
+ s->st1 = (s->st1 & ~ST1_SFMO) | (0 << ST1_SFMO_SHIFT);
+
+sfmo 2a 61 1 n f
+ sfmo 2
+ s->st1 = (s->st1 & ~ST1_SFMO) | (1 << ST1_SFMO_SHIFT);
+
+sfmo 2a 62 1 n f
+ sfmo 4
+ s->st1 = (s->st1 & ~ST1_SFMO) | (2 << ST1_SFMO_SHIFT);
+
+sfmo 2a 63 1 n f
+ sfmo -8
+ s->st1 = (s->st1 & ~ST1_SFMO) | (3 << ST1_SFMO_SHIFT);
+
+sfmr 1 35 1 y
+ sfmr
+
+slmh 2a 06 1 y
+ slmh %d
+ %wd((%mv >> 24) & 0xffff00);
+
+slml 2a 07 1 y
+ slml %d
+ %wd((%mv >> 8) & 0xffffff);
+
+smhc 2a 05 1 y
+ smhc %c
+ %wc(%mo >> 16);
+
+smhd 2a 03 1 y
+ smhd %d
+ %wd((%mo >> 24) & 0xffffff);
+
+smld 2a 04 1 y
+ smld %d
+
+smom 2a 41 1 n f
+ smom
+ s->st1 |= ST1_MOVM;
+
+srbd 2a 0f 1 y
+ srbd %d
+ %wd(s->xrd);
+
+std1 2a 0d 1 y
+ std1 %d
+
+sub 1 09 1 y
+ sub %d,a
+ %wa((INT64)(INT32)%d - (INT64)(INT32)%a);
+
+sub 1 0a 1 y
+ sub %c,a
+ %wa((INT64)(INT32)%c - (INT64)(INT32)%a);
+
+sub 1 0b 1 y
+ sub %d,m
+
+sub 1 0c 1 y
+ sub %c,m
+
+sub 1 0d 1 y
+ sub %d,%c
+ %wa((INT64)(INT32)%d - (INT64)(INT32)%c);
+
+wre 1 38 1 n
+ wre %d,%c
+ if(s->sti & (S_READ|S_WRITE))
+ break;
+ s->xwr = %d24;
+ s->xoa = %c;
+ tms57002_xm_init(s);
+ s->sti |= S_WRITE;
+
+xor 1 1a 1 n
+ xor %d,a
+
+xor 1 1b 1 n
+ xor %c,a
+
+xor 1 1c 1 n
+ xor %d,%c
+
+zacc 1 10 1 n
+ zacc
+
+zmac 1 30 1 n
+ zmac
diff --git a/trunk/src/emu/cpu/tms57002/tmsmake.c b/trunk/src/emu/cpu/tms57002/tmsmake.c
new file mode 100644
index 00000000000..22cb92f16f3
--- /dev/null
+++ b/trunk/src/emu/cpu/tms57002/tmsmake.c
@@ -0,0 +1,959 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include "osdcomm.h"
+
+enum {
+ I_POST = 0x00000001,
+ I_REP = 0x00000002,
+ I_CMODE = 0x00000004,
+ I_DMODE = 0x00000008,
+ I_SFAI = 0x00000010,
+ I_CRM = 0x00000020,
+ I_DBP = 0x00000040,
+ I_SFAO = 0x00000080,
+ I_SFMO = 0x00000100,
+ I_RND = 0x00000200,
+ I_MOVM = 0x00000400,
+ I_SFMA = 0x00000800
+};
+
+enum {
+ T_STD,
+ T_BRANCH,
+ T_CBRANCH,
+ T_IDLE,
+ T_FLAGS
+};
+
+enum { PA, PC, PD, PD24, PI, PML, PMO, PMV, PB, PWA, PWC, PWD, SFAI };
+
+typedef struct {
+ char *name;
+ char *dasm;
+ char *run;
+ int line, cycles, type, baseval, variants;
+ unsigned int flags;
+} instr;
+
+typedef struct {
+ const char *opt;
+ int pcount, id;
+} pdesc;
+
+typedef struct {
+ const char *start;
+ int size;
+ int id;
+ int pcount;
+ int ppos[4];
+} pinf;
+
+static const pdesc pp_r[] = {
+ { "a", 0, PA },
+ { "c", 0, PC },
+ { "d", 0, PD },
+ { "d24", 0, PD24 },
+ { "i", 0, PI },
+ { "ml", 0, PML },
+ { "mo", 0, PMO },
+ { "mv", 0, PMV },
+ { "wa", 1, PWA },
+ { "wc", 1, PWC },
+ { "wd", 1, PWD },
+ { "b", 1, PB },
+ { "sfai", 2, SFAI },
+ { 0 }
+};
+
+static instr cat1[0x40], cat2[0x80], cat3[0x80];
+
+static pinf parse_res[4096];
+static int parse_count;
+
+typedef struct {
+ unsigned int mask;
+ int variants;
+ const char *name;
+ const char *getter;
+} vinfo;
+
+enum { IxCMODE, IxDMODE, IxSFAI, IxCRM, IxDBP, IxSFAO, IxSFMO, IxRND, IxMOVM, IxSFMA, IxCOUNT };
+
+static const vinfo vinf[] = {
+ { I_CMODE, 3, "cmode", "xmode(opcode, 'c')" },
+ { I_DMODE, 3, "dmode", "xmode(opcode, 'd')" },
+ { I_SFAI, 2, "sfai", "sfai(s->st1)" },
+ { I_CRM, 4, "crm", "crm(s->st1)" },
+ { I_DBP, 2, "dbp", "dbp(s->st1)" },
+ { I_SFAO, 2, "sfao", "sfao(s->st1)" },
+ { I_SFMO, 4, "sfmo", "sfmo(s->st1)" },
+ { I_RND, 8, "rnd", "rnd(s->st1)" },
+ { I_MOVM, 2, "movm", "movm(s->st1)" },
+ { I_SFMA, 4, "sfma", "sfma(s->st1)" },
+ { 0 }
+};
+
+static char *xstrdup(const char *str)
+{
+ char *cpy = NULL;
+ if (str != NULL) {
+ cpy = (char *)malloc(strlen(str) + 1);
+ if (cpy != NULL)
+ strcpy(cpy, str);
+ }
+ return cpy;
+}
+
+static char *sconcat(char *dest, const char *src)
+{
+ char *r;
+ int len = strlen(src);
+ int pos = dest ? strlen(dest) : 0;
+ r = (char *)realloc(dest, pos+len+2);
+ memcpy(r + pos, src, len);
+ r[pos+len] = '\n';
+ r[pos+len+1] = 0;
+ return r;
+}
+
+static void next(char **q)
+{
+ char *p = *q;
+ while(*p && *p != ' ')
+ p++;
+ while(*p == ' ')
+ *p++ = 0;
+ *q = p;
+}
+
+static void load(const char *fname)
+{
+ char buf[4096];
+ FILE *f;
+ instr *i = 0;
+ int line = 0;
+
+ sprintf(buf, "Error opening %s for reading\n", fname);
+ f = fopen(fname, "r");
+ if(!f) {
+ perror(buf);
+ exit(1);
+ }
+
+ while(fgets(buf, sizeof(buf), f)) {
+ char *p = buf;
+
+ while(*p && *p != '\r' && *p != '\n')
+ p++;
+ *p = 0;
+
+ line++;
+
+ if(!buf[0]) {
+ i = 0;
+ continue;
+ }
+ if(buf[0] == ' ' || buf[0] == '\t') {
+ if(!i) {
+ fprintf(stderr, "%s:%d: Text line without an instruction.\n", fname, line);
+ exit(1);
+ }
+ if(i->dasm)
+ i->run = sconcat(i->run, buf);
+ else {
+ p = buf;
+ while(*p == ' ' || *p == '\t')
+ p++;
+ i->dasm = xstrdup(p);
+ }
+ } else {
+ char *name=0, *cat=0, *id=0, *cyc=0, *rep=0, *type=0;
+ p = buf;
+ int pid, limit;
+ instr *bi;
+ unsigned int flags;
+
+ name = p;
+ next(&p);
+ cat = p;
+ next(&p);
+ id = p;
+ next(&p);
+ cyc = p;
+ next(&p);
+ rep = p;
+ next(&p);
+ type = p;
+ next(&p);
+ if(*p) {
+ fprintf(stderr, "%s:%d: Extra text at end of instruction description.\n", fname, line);
+ exit(1);
+ }
+ if(!rep[0]) {
+ fprintf(stderr, "%s:%d: Missing columns in instruction description.\n", fname, line);
+ exit(1);
+ }
+
+ flags = 0;
+ pid = strtol(id, 0, 16);
+ if(!strcmp(cat, "1")) {
+ bi = cat1;
+ limit = 0x40;
+ } else if(!strcmp(cat, "2a")) {
+ bi = cat2;
+ limit = 0x80;
+ } else if(!strcmp(cat, "2b")) {
+ bi = cat2;
+ limit = 0x80;
+ flags = I_POST;
+ } else if(!strcmp(cat, "3")) {
+ bi = cat3;
+ limit = 0x80;
+ } else {
+ fprintf(stderr, "%s:%d: Unknown category '%s'.\n", fname, line, cat);
+ exit(1);
+ }
+
+ if(pid<0 || pid >= limit) {
+ fprintf(stderr, "%s:%d: Index %s out of range for category %s.\n", fname, line, id, cat);
+ exit(1);
+ }
+
+ i = bi + pid;
+ if(i->name) {
+ fprintf(stderr, "%s:%d: Conflict with %s instruction line %d.\n", fname, line, i->name, i->line);
+ exit(1);
+ }
+
+ if(!strcmp(rep, "y"))
+ flags |= I_REP;
+ else if(strcmp(rep, "n")) {
+ fprintf(stderr, "%s:%d: Unknown repetition mode '%s'.\n", fname, line, rep);
+ exit(1);
+ }
+
+ i->name = xstrdup(name);
+ i->line = line;
+ i->cycles = strtol(cyc, 0, 10);
+ i->flags = flags;
+
+ if(type[0] == 0)
+ i->type = T_STD;
+ else if(!strcmp(type, "b"))
+ i->type = T_BRANCH;
+ else if(!strcmp(type, "cb"))
+ i->type = T_CBRANCH;
+ else if(!strcmp(type, "i"))
+ i->type = T_IDLE;
+ else if(!strcmp(type, "f"))
+ i->type = T_FLAGS;
+ else {
+ fprintf(stderr, "%s:%d: Unknown type '%s'.\n", fname, line, type);
+ exit(1);
+ }
+ }
+ }
+ fclose(f);
+}
+
+static void pstr(const char *s, const char *e)
+{
+ parse_res[parse_count].start = s;
+ parse_res[parse_count].size = e-s;
+ parse_res[parse_count].id = -1;
+ parse_res[parse_count].pcount = 0;
+ parse_count++;
+}
+
+static void parse_1(const char *start, const pdesc *inf, const char **str, int emode)
+{
+ const char *p = *str;
+ const char *s = p;
+ int depth = 0;
+ while(*p) {
+ char c = *p++;
+ if(!depth && ((c == ',' && emode == ',') || (c == ')' && emode == ')'))) {
+ if(s != p-1)
+ pstr(s, p-1);
+ *str = p;
+ return;
+ }
+ if(c == '(')
+ depth++;
+ else if(c == ')') {
+ depth--;
+ if(depth < 0) {
+ if(emode == ',')
+ fprintf(stderr, "Parse error, missing parameter in '%s'.\n", start);
+ else
+ fprintf(stderr, "Parse error, unbalanced parenthesis in '%s'.\n", start);
+ exit(1);
+ }
+ } else if(c == '%' && ((*p >= 'a' && *p <= 'z') || (*p >= '0' && *p <= '9'))) {
+ char buf[4096];
+ char *pp = buf;
+ int i, j;
+ int pos;
+
+ if(s != p-1)
+ pstr(s, p-1);
+
+ while((*p >= 'a' && *p <= 'z') || (*p >= '0' && *p <= '9'))
+ *pp++ = *p++;
+ *pp = 0;
+ for(i=0; inf[i].opt && strcmp(buf, inf[i].opt); i++);
+ if(!inf[i].opt) {
+ fprintf(stderr, "Parse error, unhandled parameter %%%s\n", buf);
+ exit(1);
+ }
+
+ pos = parse_count++;
+ parse_res[pos].start = 0;
+ parse_res[pos].size = 0;
+ parse_res[pos].id = inf[i].id;
+ parse_res[pos].pcount = inf[i].pcount;
+
+ if(inf[i].pcount) {
+ if(*p != '(') {
+ fprintf(stderr, "Parse error, missing opening parenthesis on %%%s\n", buf);
+ exit(1);
+ } else
+ p++;
+ }
+
+ *str = p;
+
+ for(j=0; j != inf[i].pcount; j++) {
+ parse_res[pos].ppos[j] = parse_count;
+ parse_1(start, inf, str, j == inf[i].pcount-1 ? ')' : ',');
+ }
+ p = *str;
+ parse_res[pos].ppos[j] = parse_count;
+ s = p;
+ }
+ }
+ if(s != p)
+ pstr(s, p);
+ *str = p;
+ switch(emode) {
+ case 0:
+ return;
+ case ',':
+ fprintf(stderr, "Parse error, missing parameter at end of string in '%s'.\n", start);
+ exit(1);
+ case ')':
+ fprintf(stderr, "Parse error, missing closing parenthesis at end of string in '%s'.\n", start);
+ exit(1);
+ }
+}
+
+static void parse(const char *str, const pdesc *inf)
+{
+ parse_count = 0;
+ parse_1(str, inf, &str, 0);
+}
+
+static void compute_cache_ids_cat(instr *il, int count, int *baseval)
+{
+ int i, j;
+ for(i=0; i != count; i++)
+ if(il[i].run) {
+ unsigned int flags = il[i].flags;
+ int variants = 1;
+ parse(il[i].run, pp_r);
+ for(j=0; j != parse_count; j++) {
+ switch(parse_res[j].id) {
+ case -1: break;
+ case PA: flags |= I_SFAO; break;
+ case PC: flags |= I_CMODE|I_CRM; break;
+ case PD: flags |= I_DMODE|I_DBP; break;
+ case PI: break;
+ case PD24: flags |= I_DMODE|I_DBP; break;
+ case PML: flags |= I_SFMA; break;
+ case PMO: flags |= I_SFMO|I_RND|I_MOVM; break;
+ case PMV: flags |= I_SFMO|I_MOVM; break;
+ case PB: break;
+ case PWA: break;
+ case PWC: flags |= I_CMODE; break;
+ case PWD: flags |= I_DMODE|I_DBP; break;
+ case SFAI: flags |= I_SFAI; break;
+ }
+ }
+ il[i].flags = flags;
+ il[i].baseval = *baseval;
+
+ for(j=0; vinf[j].mask; j++)
+ if(flags & vinf[j].mask)
+ variants *= vinf[j].variants;
+ il[i].variants = variants;
+
+ *baseval += variants;
+ }
+}
+
+
+static void scp(char **str, int idx)
+{
+ memcpy(*str, parse_res[idx].start, parse_res[idx].size);
+ (*str) += parse_res[idx].size;
+}
+
+static void scs(char **str, const char *s)
+{
+ int len = strlen(s);
+ memcpy(*str, s, len);
+ (*str) += len;
+}
+
+static void save_dasm_cat(FILE *f, const char *def, instr *il, int count)
+{
+ static const pdesc pp[] = {
+ { "c", 0, PC },
+ { "d", 0, PD },
+ { "i", 0, PI },
+ { 0 }
+ };
+
+ int i;
+ fprintf(f, "#ifdef %s\n", def);
+ for(i=0; i != count; i++)
+ if(il[i].name) {
+ int par[3];
+ int pc = 0;
+ int j;
+ char buf[4096], *p = buf;
+ parse(il[i].dasm, pp);
+ for(j=0; j<parse_count;j++) {
+ switch(parse_res[j].id) {
+ case -1:
+ scp(&p, j);
+ break;
+ case PC:
+ scs(&p, "%s");
+ par[pc++] = PC;
+ break;
+ case PD:
+ scs(&p, "%s");
+ par[pc++] = PD;
+ break;
+ case PI:
+ scs(&p, "%02x");
+ par[pc++] = PI;
+ break;
+ }
+ }
+ *p = 0;
+
+ fprintf(f, " case 0x%02x:\n", i);
+ fprintf(f, " sprintf(buf, \"%s\"", buf);
+ for(j=0; j != pc; j++)
+ switch(par[j]) {
+ case PC:
+ fprintf(f, ", tms57002_get_memadr(opcode, 'c')");
+ break;
+ case PD:
+ fprintf(f, ", tms57002_get_memadr(opcode, 'd')");
+ break;
+ case PI:
+ fprintf(f, ", opcode & 0xff");
+ break;
+ }
+
+
+ fprintf(f, ");\n");
+ fprintf(f, " break;\n");
+ fprintf(f, "\n");
+ }
+
+ fprintf(f, "#endif\n\n");
+}
+
+static void intrp_expand(char **p, int s, int e)
+{
+ int i;
+ for(i=s; i<e;) {
+ switch(parse_res[i].id) {
+ case -1:
+ scp(p, i);
+ break;
+
+ case PA:
+ scs(p, "tms57002_aacc_to_output(s)");
+ break;
+
+ case PC:
+ scs(p, "tms57002_opc_read_c(s, opcode)");
+ break;
+
+ case PD:
+ scs(p, "(tms57002_opc_read_d(s, opcode) << 8)");
+ break;
+
+ case PI:
+ scs(p, "(opcode & 0xff)");
+ break;
+
+ case PD24:
+ scs(p, "tms57002_opc_read_d(s, opcode)");
+ break;
+
+ case PML:
+ scs(p, "tms57002_macc_to_loop(s)");
+ break;
+
+ case PMO:
+ scs(p, "tms57002_macc_to_output(s)");
+ break;
+
+ case PMV:
+ scs(p, "tms57002_check_macc_overflow(s)");
+ break;
+
+ case PB:
+ scs(p, "s->pc = ");
+ intrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1]);
+ scs(p, ";\n");
+ scs(p, " s->sti |= S_BRANCH");
+ break;
+
+ case PWA:
+ scs(p, "r = ");
+ intrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1]);
+ scs(p, ";\n");
+ scs(p, " if(r < -0x80000000 || r > 0x7fffffff)\n");
+ scs(p, " s->st1 |= ST1_AOV;\n");
+ scs(p, " s->aacc = r");
+ break;
+
+ case PWC:
+ scs(p, "tms57002_opc_write_c(s, opcode, ");
+ intrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1]);
+ scs(p, ")");
+ break;
+
+ case PWD:
+ scs(p, "tms57002_opc_write_d(s, opcode, ");
+ intrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1]);
+ scs(p, ")");
+ break;
+
+ case SFAI:
+ intrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1]);
+ scs(p, " = ");
+ intrp_expand(p, parse_res[i].ppos[1], parse_res[i].ppos[2]);
+ scs(p, ";\n");
+ scs(p, " if(s->st1 & ST1_SFAI)\n");
+ scs(p, " ");
+ intrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1]);
+ scs(p, " = ((INT32)");
+ intrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1]);
+ scs(p, ") >> 1");
+ break;
+ }
+
+ if(parse_res[i].id == -1)
+ i++;
+ else
+ i = parse_res[i].ppos[parse_res[i].pcount];
+ }
+}
+
+static void save_intrp_cat(FILE *f, const char *def, instr *il, int count, unsigned int fmask, unsigned int fval)
+{
+ int i;
+ fprintf(f, "#ifdef %s\n", def);
+ for(i=0; i != count; i++)
+ if(il[i].run) {
+ fprintf(f, "case 0x%02x: // %s\n", i, il[i].name);
+ if((il[i].flags & fmask) == fval) {
+ char buf[4096], *p = buf;
+ parse(il[i].run, pp_r);
+ intrp_expand(&p, 0, parse_count);
+ *p = 0;
+
+ fprintf(f, "%s", buf);
+ }
+ fprintf(f, " break;\n\n");
+ }
+
+ fprintf(f, "#endif\n\n");
+}
+
+static void save_cdec_cat(FILE *f, const char *def, instr *il, int count, unsigned int fmask, unsigned int fval)
+{
+ int i;
+ fprintf(f, "#ifdef %s\n", def);
+ for(i=0; i != count; i++)
+ if(il[i].run) {
+ int m=1, j;
+ unsigned int flags = il[i].flags;
+ fprintf(f, "case 0x%02x: // %s\n", i, il[i].name);
+ if((il[i].flags & fmask) == fval) {
+ fprintf(f, " *op = %d", il[i].baseval);
+ for(j=0; vinf[j].mask; j++)
+ if(flags & vinf[j].mask) {
+ if(m != 1)
+ fprintf(f, " + %d*%s", m, vinf[j].getter);
+ else
+ fprintf(f, " + %s", vinf[j].getter);
+ m *= vinf[j].variants;
+ }
+ fprintf(f, ";\n");
+ switch(il[i].type) {
+ case T_FLAGS:
+ fprintf(f, "%s", il[i].run);
+ break;
+ case T_BRANCH:
+ fprintf(f, " cs->branch = BR_UB;\n");
+ break;
+ case T_CBRANCH:
+ fprintf(f, " cs->branch = BR_CB;\n");
+ break;
+ case T_IDLE:
+ fprintf(f, " cs->branch = BR_IDLE;\n");
+ break;
+ }
+ }
+ fprintf(f, " break;\n\n");
+ }
+
+ fprintf(f, "#endif\n\n");
+}
+
+
+static void cintrp_expand(char **p, int s, int e, const int *cv)
+{
+ int i;
+ for(i=s; i<e;) {
+ switch(parse_res[i].id) {
+ case -1:
+ scp(p, i);
+ break;
+
+ case PA:
+ if(cv[IxSFAO])
+ scs(p, "(s->aacc << 7)");
+ else
+ scs(p, "s->aacc");
+ break;
+
+ case PC: {
+ const char *r = NULL;
+ if(cv[IxCMODE] == 0)
+ r = "s->cmem[i->param]";
+ else if(cv[IxCMODE] == 1)
+ r = "s->cmem[s->ca]";
+ else if(cv[IxCMODE] == 2)
+ r = "s->cmem[s->ca++]";
+ else
+ abort();
+
+ if(cv[IxCRM] == 0 || cv[IxCRM] == 3)
+ scs(p, r);
+ else if(cv[IxCRM] == 1) {
+ scs(p, "(");
+ scs(p, r);
+ scs(p, " & 0xffff0000)");
+ } else if(cv[IxCRM] == 2) {
+ scs(p, "(");
+ scs(p, r);
+ scs(p, " << 16)");
+ } else
+ abort();
+ break;
+ }
+
+ case PD:
+ if(cv[IxDMODE] == 0)
+ if(cv[IxDBP])
+ scs(p, "(s->dmem1[(i->param + s->ba1) & 0x1f] << 8)");
+ else
+ scs(p, "(s->dmem0[(i->param + s->ba0) & 0xff] << 8)");
+ else if(cv[IxDMODE] == 1)
+ if(cv[IxDBP])
+ scs(p, "(s->dmem1[(s->id + s->ba1) & 0x1f] << 8)");
+ else
+ scs(p, "(s->dmem0[(s->id + s->ba0) & 0xff] << 8)");
+ else if(cv[IxDMODE] == 2)
+ if(cv[IxDBP])
+ scs(p, "(s->dmem1[((s->id++) + s->ba1) & 0x1f] << 8)");
+ else
+ scs(p, "(s->dmem0[((s->id++) + s->ba0) & 0xff] << 8)");
+ else
+ abort();
+ break;
+
+ case PI:
+ scs(p, "i->param");
+ break;
+
+ case PD24:
+ if(cv[IxDMODE] == 0)
+ if(cv[IxDBP])
+ scs(p, "s->dmem1[(i->param + s->ba1) & 0x1f]");
+ else
+ scs(p, "s->dmem0[(i->param + s->ba0) & 0xff]");
+ else if(cv[IxDMODE] == 1)
+ if(cv[IxDBP])
+ scs(p, "s->dmem1[(s->id + s->ba1) & 0x1f]");
+ else
+ scs(p, "s->dmem0[(s->id + s->ba0) & 0xff]");
+ else if(cv[IxDMODE] == 2)
+ if(cv[IxDBP])
+ scs(p, "s->dmem1[((s->id++) + s->ba1) & 0x1f]");
+ else
+ scs(p, "s->dmem0[((s->id++) + s->ba0) & 0xff]");
+ else
+ abort();
+ break;
+
+ case PML:
+ if(cv[IxSFMA] == 0)
+ scs(p, "s->macc");
+ else if(cv[IxSFMA] == 1)
+ scs(p, "(s->macc << 2)");
+ else if(cv[IxSFMA] == 2)
+ scs(p, "(s->macc << 4)");
+ else if(cv[IxSFMA] == 3)
+ scs(p, "(s->macc >> 16)");
+ else
+ abort();
+ break;
+
+ case PMO: {
+ static const long long rounding[8] = {
+ 0,
+ 1LL << (48-32-1),
+ 1LL << (48-24-1),
+ 1LL << (48-30-1),
+ 1LL << (48-16-1),
+ 0, 0, 0
+ };
+ static const unsigned long long rmask[8] = {
+ ~0ULL,
+ (~0ULL) << (48-32),
+ (~0ULL) << (48-24),
+ (~0ULL) << (48-30),
+ (~0ULL) << (48-16),
+ ~0ULL, ~0ULL, ~0ULL
+ };
+
+ char r[256];
+ sprintf(r, "tms57002_macc_to_output_%d%s(s, 0x%016" I64FMT "xULL, 0x%016" I64FMT "xULL)", cv[IxSFMO], cv[IxMOVM] ? "s" : "", rounding[cv[IxRND]], rmask[cv[IxRND]]);
+ scs(p, r);
+ break;
+ }
+
+ case PMV: {
+ char r[256];
+ sprintf(r, "tms57002_check_macc_overflow_%d%s(s)", cv[IxSFMO], cv[IxMOVM] ? "s" : "");
+ scs(p, r);
+ break;
+ }
+
+ case PB:
+ scs(p, "s->pc = ");
+ cintrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1], cv);
+ scs(p, ";\n");
+ scs(p, " s->sti |= S_BRANCH");
+ break;
+
+ case PWA:
+ scs(p, "r = ");
+ cintrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1], cv);
+ scs(p, ";\n");
+ scs(p, " if(r < -0x80000000 || r > 0x7fffffff)\n");
+ scs(p, " s->st1 |= ST1_AOV;\n");
+ scs(p, " s->aacc = r");
+ break;
+
+ case PWC:
+ if(cv[IxCMODE] == 0)
+ scs(p, "s->cmem[i->param] = ");
+ else if(cv[IxCMODE] == 1)
+ scs(p, "s->cmem[s->ca] = ");
+ else if(cv[IxCMODE] == 2)
+ scs(p, "s->cmem[s->ca++] = ");
+ else
+ abort();
+
+ cintrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1], cv);
+ break;
+
+ case PWD:
+ if(cv[IxDMODE] == 0)
+ if(cv[IxDBP])
+ scs(p, "s->dmem1[(i->param + s->ba1) & 0x1f] = ");
+ else
+ scs(p, "s->dmem0[(i->param + s->ba0) & 0xff] = ");
+ else if(cv[IxDMODE] == 1)
+ if(cv[IxDBP])
+ scs(p, "s->dmem1[(s->id + s->ba1) & 0x1f] = ");
+ else
+ scs(p, "s->dmem0[(s->id + s->ba0) & 0xff] = ");
+ else if(cv[IxDMODE] == 2)
+ if(cv[IxDBP])
+ scs(p, "s->dmem1[((s->id++) + s->ba1) & 0x1f] = ");
+ else
+ scs(p, "s->dmem0[((s->id++) + s->ba0) & 0xff] = ");
+ else
+ abort();
+
+ cintrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1], cv);
+ break;
+
+ case SFAI:
+ cintrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1], cv);
+ scs(p, " = ");
+ if(cv[IxSFAI])
+ scs(p, "((INT32)(");
+ cintrp_expand(p, parse_res[i].ppos[1], parse_res[i].ppos[2], cv);
+ if(cv[IxSFAI])
+ scs(p, ")) >> 1");
+ break;
+ }
+
+ if(parse_res[i].id == -1)
+ i++;
+ else
+ i = parse_res[i].ppos[parse_res[i].pcount];
+ }
+}
+
+static void save_cintrp_cat(FILE *f, instr *il, int count)
+{
+ int i;
+ for(i=0; i != count; i++)
+ if(il[i].run) {
+ int cv[IxCOUNT];
+ int j, k = 0;
+ unsigned int flags = il[i].flags;
+ char buf[16384];
+
+ memset(cv, 0, sizeof(cv));
+ parse(il[i].run, pp_r);
+
+ for(j=0; j != il[i].variants; j++) {
+ char *p = buf;
+ fprintf(f, "case %d: // %s", il[i].baseval + j, il[i].name);
+ for(k=0; k != IxCOUNT; k++)
+ if(flags & vinf[k].mask)
+ fprintf(f, " %s=%d", vinf[k].name, cv[k]);
+ fprintf(f, "\n");
+ cintrp_expand(&p, 0, parse_count, cv);
+ *p = 0;
+ fprintf(f, "%s", buf);
+ fprintf(f, " break;\n\n");
+
+ for(k=0; k != IxCOUNT; k++)
+ if(flags & vinf[k].mask) {
+ cv[k]++;
+ if(cv[k] != vinf[k].variants)
+ break;
+ cv[k] = 0;
+ }
+ }
+ assert(k == IxCOUNT);
+ }
+}
+
+static void compute_cache_ids(void)
+{
+ int baseval = 1;
+ compute_cache_ids_cat(cat1, 0x40, &baseval);
+ compute_cache_ids_cat(cat2, 0x80, &baseval);
+ compute_cache_ids_cat(cat3, 0x80, &baseval);
+}
+
+static void save_dasm(FILE *f)
+{
+ save_dasm_cat(f, "DASM1", cat1, 0x40);
+ save_dasm_cat(f, "DASM2", cat2, 0x80);
+ save_dasm_cat(f, "DASM3", cat3, 0x80);
+}
+
+static void save_intrp(FILE *f)
+{
+ save_intrp_cat(f, "INTRP1", cat1, 0x40, 0, 0);
+ save_intrp_cat(f, "INTRP2A", cat2, 0x80, I_POST, 0);
+ save_intrp_cat(f, "INTRP2B", cat2, 0x80, I_POST, I_POST);
+ save_intrp_cat(f, "INTRP3", cat3, 0x80, 0, 0);
+}
+
+static void save_cdec(FILE *f)
+{
+ save_cdec_cat(f, "CDEC1", cat1, 0x40, 0, 0);
+ save_cdec_cat(f, "CDEC2A", cat2, 0x80, I_POST, 0);
+ save_cdec_cat(f, "CDEC2B", cat2, 0x80, I_POST, I_POST);
+ save_cdec_cat(f, "CDEC3", cat3, 0x80, 0, 0);
+}
+
+static void save_cintrp(FILE *f)
+{
+ fprintf(f, "#ifdef CINTRP\n");
+ save_cintrp_cat(f, cat1, 0x40);
+ save_cintrp_cat(f, cat2, 0x80);
+ save_cintrp_cat(f, cat3, 0x80);
+ fprintf(f, "#endif\n");
+}
+
+static void save(const char *fname)
+{
+ char buf[4096];
+ FILE *f;
+
+ sprintf(buf, "Error opening %s for writing\n", fname);
+ f = fopen(fname, "w");
+ if(!f) {
+ perror(buf);
+ exit(1);
+ }
+
+ compute_cache_ids();
+
+ save_dasm(f);
+ save_intrp(f);
+ save_cdec(f);
+ save_cintrp(f);
+
+ fclose(f);
+}
+
+static void clear_cat(instr *il, int count)
+{
+ int i;
+ for(i=0; i != count; i++) {
+ free(il[i].name);
+ free(il[i].dasm);
+ free(il[i].run);
+ }
+}
+
+static void clear(void)
+{
+ clear_cat(cat1, 0x40);
+ clear_cat(cat2, 0x80);
+ clear_cat(cat3, 0x80);
+}
+
+int main(int argc, char *argv[])
+{
+ if(argc != 3) {
+ fprintf(stderr, "Usage:\n%s tmsinstr.lst tms57002.inc\n", argv[0]);
+ exit(1);
+ }
+
+ memset(cat1, 0, sizeof(cat1));
+ memset(cat2, 0, sizeof(cat2));
+ memset(cat3, 0, sizeof(cat3));
+
+ load(argv[1]);
+ save(argv[2]);
+ clear();
+
+ return 0;
+}
diff --git a/trunk/src/emu/cpu/tms7000/7000dasm.c b/trunk/src/emu/cpu/tms7000/7000dasm.c
new file mode 100644
index 00000000000..8ab0b0d94f6
--- /dev/null
+++ b/trunk/src/emu/cpu/tms7000/7000dasm.c
@@ -0,0 +1,446 @@
+#include "emu.h"
+#include "debugger.h"
+#include "tms7000.h"
+
+typedef enum { DONE, NONE, UI8, I8, UI16, I16, PCREL, PCABS, TRAP } operandtype;
+
+typedef struct {
+ char opstr[4][12];
+ operandtype decode[4];
+} oprandinfo;
+
+typedef struct {
+ int opcode;
+ char name[8];
+ int operand;
+ UINT32 s_flag;
+} opcodeinfo;
+
+static const oprandinfo of[] = {
+/* 00 */ { {" B,A", "", "", ""}, {NONE, DONE, DONE, DONE} },
+/* 01 */ { {" R%u", ",A", "", ""}, {UI8, NONE, DONE, DONE} },
+/* 02 */ { {" R%u", ",B", "", ""}, {UI8, NONE, DONE, DONE} },
+/* 03 */ { {" R%u", ",R%u", "", ""}, {UI8, UI8, DONE, DONE} },
+/* 04 */ { {" %%>%X", ",A", "", ""}, {UI8, NONE, DONE, DONE} },
+/* 05 */ { {" %%>%X", ",B", "", ""}, {UI8, NONE, DONE, DONE} },
+/* 06 */ { {" %%>%X", ",R%u", "", ""}, {UI8, UI8, DONE, DONE} },
+
+/* 07 */ { {" A", ",P%u", "", ""}, {NONE,UI8,DONE,DONE} },
+/* 08 */ { {" B", ",P%u", "", ""}, {NONE,UI8,DONE,DONE} },
+/* 09 */ { {" %%>%02X", ",P%u", "", ""}, {UI8,UI8,DONE,DONE} },
+
+/* 10 */ { {" @>%04X", "", "", ""}, {UI16,DONE,DONE,DONE} },
+/* 11 */ { {" R%u", "", "", ""}, {UI8, DONE, DONE, DONE} },
+/* 12 */ { {" @>%04X(B)","", "", ""}, {UI16, DONE, DONE, DONE} },
+
+/* 13 */ { {" B,A", ",%s", "", ""}, {NONE, PCREL, DONE, DONE} },
+/* 14 */ { {" R%u,A", ",%s", "", ""}, {UI8, PCREL, DONE, DONE} },
+/* 15 */ { {" R%u,B", ",%s", "", ""}, {UI8, PCREL, DONE, DONE} },
+/* 16 */ { {" R%u", ",R%u", ",%s", ""}, {UI8, UI8, PCREL, DONE} },
+/* 17 */ { {" %%>%X", ",A,%s", "", ""}, {UI8, PCREL, DONE, DONE} },
+/* 18 */ { {" %%>%X", ",B,%s", "", ""}, {UI8, PCREL, DONE, DONE} },
+/* 19 */ { {" %%>%X", ",R%u", ",%s", ""}, {UI8, UI8, PCREL, DONE} },
+
+/* 20 */ { {" A,P%u", ",%s", "", ""}, {UI8, PCREL, DONE, DONE} },
+/* 21 */ { {" B,P%u", ",%s", "", ""}, {UI8, PCREL, DONE, DONE} },
+/* 22 */ { {" %%>%02X", ",P%u", ",%s" ""}, {UI8, UI8, PCREL, DONE} },
+
+/* 23 */ { {"", "", "", ""}, {DONE, DONE, DONE, DONE} },
+/* 24 */ { {" R%u", "", "", ""}, {UI8, DONE, DONE, DONE} },
+
+/* 25 */ { {" A,%s", "", "", ""}, {PCREL, DONE, DONE, DONE} },
+/* 26 */ { {" B,%s", "", "", ""}, {PCREL, DONE, DONE, DONE} },
+/* 27 */ { {" R%u", ",%s", "", ""}, {UI8, PCREL, DONE, DONE} },
+
+/* 28 */ { {" %s", "", "", ""}, {PCREL, DONE, DONE, DONE} },
+
+/* 29 */ { {" A,B", "", "", ""}, {NONE, DONE, DONE, DONE} },
+/* 30 */ { {" B,A", "", "", ""}, {NONE, DONE, DONE, DONE} },
+/* 31 */ { {" A,R%u", "", "", ""}, {UI8, DONE, DONE, DONE} },
+/* 32 */ { {" B,R%u", "", "", ""}, {UI8, DONE, DONE, DONE} },
+/* 33 */ { {" R%u,A", "", "", ""}, {UI8, DONE, DONE, DONE} },
+/* 34 */ { {" R%u,B", "", "", ""}, {UI8, DONE, DONE, DONE} },
+/* 35 */ { {" R%u", ",R%u", "", ""}, {UI8, UI8, DONE, DONE} },
+/* 36 */ { {" %%>%X,A", "", "", ""}, {UI8, DONE, DONE, DONE} },
+/* 37 */ { {" %%>%X,B", "", "", ""}, {UI8, DONE, DONE, DONE} },
+/* 38 */ { {" %%>%X", ",R%u", "", ""}, {UI8, UI8, DONE, DONE} },
+
+/* 39 */ { {" %%>%04X",",R%u", "", ""}, {UI16, UI8, DONE, DONE} },
+/* 40 */ { {" %%>%04X(B)",",R%u", "", ""}, {UI16, UI8, DONE, DONE} },
+
+/* 41 */ { {" P%u,A", "", "", ""}, {UI8, DONE, DONE, DONE} },
+/* 42 */ { {" P%u,B", "", "", ""}, {UI8, DONE, DONE, DONE} },
+/* 43 */ { {" %s", "", "", ""}, {PCABS, DONE, DONE, DONE} },
+/* 44 */ { {"", "", "", ""}, {TRAP, DONE, DONE, DONE} }, /* Only For TRAP */
+
+/* 45 */ { {" *R%u", "", "", ""}, {UI8, DONE, DONE, DONE} }
+};
+
+static const opcodeinfo opcodes[] = {
+ {0x69, "ADC", 0, 0 },
+ {0x19, "ADC", 1, 0 },
+ {0x39, "ADC", 2, 0 },
+ {0x49, "ADC", 3, 0 },
+ {0x29, "ADC", 4, 0 },
+ {0x59, "ADC", 5, 0 },
+ {0x79, "ADC", 6, 0 },
+
+ {0x68, "ADD", 0, 0 },
+ {0x18, "ADD", 1, 0 },
+ {0x38, "ADD", 2, 0 },
+ {0x48, "ADD", 3, 0 },
+ {0x28, "ADD", 4, 0 },
+ {0x58, "ADD", 5, 0 },
+ {0x78, "ADD", 6, 0 },
+
+ {0x63, "AND", 0, 0 },
+ {0x13, "AND", 1, 0 },
+ {0x33, "AND", 2, 0 },
+ {0x43, "AND", 3, 0 },
+ {0x23, "AND", 4, 0 },
+ {0x53, "AND", 5, 0 },
+ {0x73, "AND", 6, 0 },
+
+ {0x83, "ANDP", 7, 0 },
+ {0x93, "ANDP", 8, 0 },
+ {0xA3, "ANDP", 9, 0 },
+
+ {0x8C, "BR", 43, 0 },
+ {0x9C, "BR", 45, 0 },
+ {0xAC, "BR", 12, 0 },
+
+ {0x66, "BTJO", 13, 0 },
+ {0x16, "BTJO", 14, 0 },
+ {0x36, "BTJO", 15, 0 },
+ {0x46, "BTJO", 16, 0 },
+ {0x26, "BTJO", 17, 0 },
+ {0x56, "BTJO", 18, 0 },
+ {0x76, "BTJO", 19, 0 },
+
+ {0x86, "BTJOP", 20, 0 },
+ {0x96, "BTJOP", 21, 0 },
+ {0xA6, "BTJOP", 22, 0 },
+
+ {0x67, "BTJZ", 13, 0 },
+ {0x17, "BTJZ", 14, 0 },
+ {0x37, "BTJZ", 15, 0 },
+ {0x47, "BTJZ", 16, 0 },
+ {0x27, "BTJZ", 17, 0 },
+ {0x57, "BTJZ", 18, 0 },
+ {0x77, "BTJZ", 19, 0 },
+
+ {0x87, "BTJZP", 20, 0 },
+ {0x97, "BTJZP", 21, 0 },
+ {0xA7, "BTJZP", 22, 0 },
+
+ {0x8E, "CALL", 43, DASMFLAG_STEP_OVER },
+ {0x9E, "CALL", 45, DASMFLAG_STEP_OVER },
+ {0xAE, "CALL", 12, DASMFLAG_STEP_OVER },
+
+ {0xB5, "CLR A", 23, 0 },
+ {0xC5, "CLR B", 23, 0 },
+ {0xD5, "CLR", 24, 0 },
+
+ {0xB0, "CLRC", 23, 0 },
+
+ {0x6D, "CMP", 0, 0 },
+ {0x1D, "CMP", 1, 0 },
+ {0x3D, "CMP", 2, 0 },
+ {0x4D, "CMP", 3, 0 },
+ {0x2D, "CMP", 4, 0 },
+ {0x5D, "CMP", 5, 0 },
+ {0x7D, "CMP", 6, 0 },
+
+ {0x8D, "CMPA", 10, 0 },
+ {0x9D, "CMPA", 45, 0 },
+ {0xAD, "CMPA", 12, 0 },
+
+ {0x6E, "DAC", 0, 0 },
+ {0x1E, "DAC", 1, 0 },
+ {0x3E, "DAC", 2, 0 },
+ {0x4E, "DAC", 3, 0 },
+ {0x2E, "DAC", 4, 0 },
+ {0x5E, "DAC", 5, 0 },
+ {0x7E, "DAC", 6, 0 },
+
+ {0xB2, "DEC A", 23, 0 },
+ {0xC2, "DEC B", 23, 0 },
+ {0xD2, "DEC", 24, 0 },
+
+ {0xBB, "DECD A", 23, 0 },
+ {0xCB, "DECD B", 23, 0 },
+ {0xDB, "DECD", 24, 0 },
+
+ {0x06, "DINT", 23, 0 },
+
+ {0xBA, "DJNZ", 25, 0 },
+ {0xCA, "DJNZ", 26, 0 },
+ {0xDA, "DJNZ", 27, 0 },
+
+ {0x6F, "DSB", 0, 0 },
+ {0x1F, "DSB", 1, 0 },
+ {0x3F, "DSB", 2, 0 },
+ {0x4F, "DSB", 3, 0 },
+ {0x2F, "DSB", 4, 0 },
+ {0x5F, "DSB", 5, 0 },
+ {0x7F, "DSB", 6, 0 },
+
+ {0x05, "EINT", 23, 0 },
+
+ {0x01, "IDLE", 23, 0 },
+
+ {0xB3, "INC A", 23, 0 },
+ {0xC3, "INC B", 23, 0 },
+ {0xD3, "INC", 24, 0 },
+
+ {0xB4, "INV A", 23, 0 },
+ {0xC4, "INV B", 23, 0 },
+ {0xD4, "INV", 24, 0 },
+
+ {0xE2, "JEQ", 28, 0 },
+ {0xE3, "JHS", 28, 0 },
+ {0xE7, "JL", 28, 0 },
+ {0xE0, "JMP", 28, 0 },
+ {0xE1, "JN", 28, 0 },
+ {0xE6, "JNZ", 28, 0 },
+ {0xE4, "JP", 28, 0 },
+ {0xE5, "JPI", 28, 0 },
+
+ {0x8A, "LDA", 10, 0 },
+ {0x9A, "LDA", 45, 0 },
+ {0xAA, "LDA", 12, 0 },
+
+ {0x0D, "LDSP", 23, 0 },
+
+ {0xC0, "MOV", 29, 0 },
+ {0x62, "MOV", 30, 0 },
+ {0xD0, "MOV", 31, 0 },
+ {0xD1, "MOV", 32, 0 },
+ {0x12, "MOV", 33, 0 },
+ {0x32, "MOV", 34, 0 },
+ {0x42, "MOV", 35, 0 },
+ {0x22, "MOV", 36, 0 },
+ {0x52, "MOV", 37, 0 },
+ {0x72, "MOV", 38, 0 },
+
+ {0x88, "MOVD", 39, 0 },
+ {0x98, "MOVD", 35, 0 },
+ {0xA8, "MOVD", 40, 0 },
+
+ {0x82, "MOVP", 7, 0 },
+ {0x92, "MOVP", 8, 0 },
+ {0xA2, "MOVP", 9, 0 },
+ {0x80, "MOVP", 41, 0 },
+ {0x91, "MOVP", 42, 0 },
+
+ {0x6C, "MPY", 00, 0 },
+ {0x1C, "MPY", 01, 0 },
+ {0x3C, "MPY", 02, 0 },
+ {0x4C, "MPY", 03, 0 },
+ {0x2C, "MPY", 04, 0 },
+ {0x5C, "MPY", 05, 0 },
+ {0x7C, "MPY", 06, 0 },
+
+ {0x00, "NOP", 23, 0 },
+
+ {0x64, "OR", 00, 0 },
+ {0x14, "OR", 01, 0 },
+ {0x34, "OR", 02, 0 },
+ {0x44, "OR", 03, 0 },
+ {0x24, "OR", 04, 0 },
+ {0x54, "OR", 05, 0 },
+ {0x74, "OR", 06, 0 },
+
+ {0x84, "ORP", 7, 0 },
+ {0x94, "ORP", 8, 0 },
+ {0xA4, "ORP", 9, 0 },
+
+ {0xB9, "POP A", 23, 0 },
+ {0xC9, "POP B", 23, 0 },
+ {0xD9, "POP", 24, 0 },
+ {0x08, "POP ST", 23, 0 },
+
+ {0xB8, "PUSH A", 23, 0 },
+ {0xC8, "PUSH B", 23, 0 },
+ {0xD8, "PUSH", 24, 0 },
+ {0x0E, "PUSH ST", 23, 0 },
+
+ {0x0B, "RETI", 23, DASMFLAG_STEP_OUT },
+ {0x0A, "RETS", 23, DASMFLAG_STEP_OUT },
+
+ {0xBE, "RL A", 23, 0 },
+ {0xCE, "RL B", 23, 0 },
+ {0xDE, "RL", 11, 0 },
+
+ {0xBF, "RLC A", 23, 0 },
+ {0xCF, "RLC B", 23, 0 },
+ {0xDF, "RLC", 11, 0 },
+
+ {0xBC, "RR A", 23, 0 },
+ {0xCC, "RR B", 23, 0 },
+ {0xDC, "RR", 11, 0 },
+
+ {0xBD, "RRC A", 23, 0 },
+ {0xCD, "RRC B", 23, 0 },
+ {0xDD, "RRC", 11, 0 },
+
+ {0x6B, "SBB", 0, 0 },
+ {0x1B, "SBB", 1, 0 },
+ {0x3B, "SBB", 2, 0 },
+ {0x4B, "SBB", 3, 0 },
+ {0x2B, "SBB", 4, 0 },
+ {0x5B, "SBB", 5, 0 },
+ {0x7B, "SBB", 6, 0 },
+
+ {0x07, "SETC", 23, 0 },
+
+ {0x8B, "STA", 10, 0 },
+ {0x9B, "STA", 45, 0 },
+ {0xAB, "STA", 12, 0 },
+
+ {0x09, "STSP", 23, 0 },
+
+ {0x6A, "SUB", 0, 0 },
+ {0x1A, "SUB", 1, 0 },
+ {0x3A, "SUB", 2, 0 },
+ {0x4A, "SUB", 3, 0 },
+ {0x2A, "SUB", 4, 0 },
+ {0x5A, "SUB", 5, 0 },
+ {0x7A, "SUB", 6, 0 },
+
+ {0xFF, "TRAP 0", 44, DASMFLAG_STEP_OVER },
+ {0xFE, "TRAP 1", 44, DASMFLAG_STEP_OVER },
+ {0xFD, "TRAP 2", 44, DASMFLAG_STEP_OVER },
+ {0xFC, "TRAP 3", 44, DASMFLAG_STEP_OVER },
+ {0xFB, "TRAP 4", 44, DASMFLAG_STEP_OVER },
+ {0xFA, "TRAP 5", 44, DASMFLAG_STEP_OVER },
+ {0xF9, "TRAP 6", 44, DASMFLAG_STEP_OVER },
+ {0xF8, "TRAP 7", 44, DASMFLAG_STEP_OVER },
+ {0xF7, "TRAP 8", 44, DASMFLAG_STEP_OVER },
+ {0xF6, "TRAP 9", 44, DASMFLAG_STEP_OVER },
+ {0xF5, "TRAP 10", 44, DASMFLAG_STEP_OVER },
+ {0xF4, "TRAP 11", 44, DASMFLAG_STEP_OVER },
+ {0xF3, "TRAP 12", 44, DASMFLAG_STEP_OVER },
+ {0xF2, "TRAP 13", 44, DASMFLAG_STEP_OVER },
+ {0xF1, "TRAP 14", 44, DASMFLAG_STEP_OVER },
+ {0xF0, "TRAP 15", 44, DASMFLAG_STEP_OVER },
+ {0xEF, "TRAP 16", 44, DASMFLAG_STEP_OVER },
+ {0xEE, "TRAP 17", 44, DASMFLAG_STEP_OVER },
+ {0xED, "TRAP 18", 44, DASMFLAG_STEP_OVER },
+ {0xEC, "TRAP 19", 44, DASMFLAG_STEP_OVER },
+ {0xEB, "TRAP 20", 44, DASMFLAG_STEP_OVER },
+ {0xEA, "TRAP 21", 44, DASMFLAG_STEP_OVER },
+ {0xE9, "TRAP 22", 44, DASMFLAG_STEP_OVER },
+ {0xE8, "TRAP 23", 44, DASMFLAG_STEP_OVER },
+
+ {0xB7, "SWAP A", 23, 0 },
+ {0xC7, "SWAP B", 23, 0 },
+ {0xD7, "SWAP", 11, 0 },
+
+ {0xB0, "TSTA", 23, 0 },
+ {0xC1, "TSTB", 23, 0 },
+
+ {0xB6, "XCHB A", 23, 0 },
+ {0xC6, "XCHB B", 23, 0 },
+ {0xD6, "XCHB", 11, 0 },
+
+ {0x65, "XOR", 0, 0 },
+ {0x15, "XOR", 1, 0 },
+ {0x35, "XOR", 2, 0 },
+ {0x45, "XOR", 3, 0 },
+ {0x25, "XOR", 4, 0 },
+ {0x55, "XOR", 5, 0 },
+ {0x75, "XOR", 6, 0 },
+
+ {0x85, "XORP", 7, 0 },
+ {0x95, "XORP", 8, 0 },
+ {0xA5, "XORP", 9, 0 },
+
+ {0x00, "NOP", 23, 0 }
+};
+
+CPU_DISASSEMBLE( tms7000 )
+{
+ int opcode, i/*, size = 1*/;
+ int pos = 0;
+ char tmpbuf[32];
+
+ opcode = oprom[pos++];
+
+ for( i=0; i<sizeof(opcodes) / sizeof(opcodeinfo); i++ )
+ {
+ if( opcode == opcodes[i].opcode )
+ {
+ /* We found a match */
+
+ int j,k,vector;
+ UINT8 a;
+ INT8 b;
+ UINT16 c;
+ INT16 d;
+
+ buffer += sprintf (buffer, "%s", opcodes[i].name);
+
+ j=opcodes[i].operand;
+
+ for( k=0; k<4; k++ )
+ {
+ switch( of[j].decode[k] )
+ {
+ case DONE:
+ break;
+ case NONE:
+ buffer += sprintf (buffer, "%s", of[j].opstr[k]);
+ break;
+ case UI8:
+ a = (UINT8)opram[pos++];
+ buffer += sprintf(buffer, of[j].opstr[k], (unsigned int)a);
+ //size += 1;
+ break;
+ case I8:
+ b = (INT8)opram[pos++];
+ buffer += sprintf (buffer, of[j].opstr[k], (INT8)b);
+ //size += 1;
+ break;
+ case UI16:
+ c = (UINT16)opram[pos++];
+ c <<= 8;
+ c += opram[pos++];
+ buffer += sprintf (buffer, of[j].opstr[k], (unsigned int)c);
+ //size += 2;
+ break;
+ case I16:
+ d = (INT16)opram[pos++];
+ d <<= 8;
+ d += opram[pos++];
+ buffer += sprintf (buffer, of[j].opstr[k], (signed int)d);
+ //size += 2;
+ break;
+ case PCREL:
+ b = (INT8)opram[pos++];
+ sprintf(tmpbuf, "$%04X", pc+2+k+b);
+ buffer += sprintf (buffer, of[j].opstr[k], tmpbuf);
+ //size += 1;
+ break;
+ case PCABS:
+ c = (UINT16)opram[pos++];
+ c <<= 8;
+ c += opram[pos++];
+ sprintf(tmpbuf, "$%04X", c);
+ buffer += sprintf (buffer, of[j].opstr[k], tmpbuf);
+ //size += 2;
+ break;
+ case TRAP:
+ vector = 0xffff - ((0xff - opcode) * 2);
+ c = vector;//(UINT16)((memory_decrypted_read_byte( vector-1 ) << 8) + memory_decrypted_read_byte( vector ));
+ break;
+ }
+ }
+ return pos | opcodes[i].s_flag | DASMFLAG_SUPPORTED;
+ }
+ }
+
+ /* No Match */
+ strcpy (buffer, "Illegal Opcode");
+ return pos | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/tms7000/tms7000.c b/trunk/src/emu/cpu/tms7000/tms7000.c
new file mode 100644
index 00000000000..25929f28ce9
--- /dev/null
+++ b/trunk/src/emu/cpu/tms7000/tms7000.c
@@ -0,0 +1,732 @@
+/*****************************************************************************
+ *
+ * tms7000.c
+ * Portable TMS7000 emulator (Texas Instruments 7000)
+ *
+ * Copyright tim lindner, 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
+ * tlindner@macmess.org
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************
+ * Currently this source emulates a TMS70x0, not any of the other variants
+ * Unimplemented is the MC pin which (in conjunection with IOCNT0 bits 7 and 6
+ * control the memory mapping.
+ *
+ * This source implements the MC pin at Vss and mode bits in single chip mode.
+ *****************************************************************************/
+
+// SJE: Changed all references to ICount to icount (to match MAME requirements)
+// SJE: Changed RM/WM macros to reference newly created tms7000 read/write handlers & removed unused SRM(cpustate) macro
+// SJE: Fixed a mistake in tms70x0_pf_w where the wrong register was referenced
+// SJE: Implemented internal register file
+
+#include "emu.h"
+#include "debugger.h"
+#include "tms7000.h"
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+typedef struct _tms7000_state tms7000_state;
+
+/* Private prototypes */
+
+static void tms7000_set_irq_line(tms7000_state *cpustate, int irqline, int state);
+static void tms7000_check_IRQ_lines(tms7000_state *cpustate);
+static void tms7000_do_interrupt( tms7000_state *cpustate, UINT16 address, UINT8 line );
+static CPU_EXECUTE( tms7000 );
+static CPU_EXECUTE( tms7000_exl );
+static void tms7000_service_timer1( device_t *device );
+static UINT16 bcd_add( UINT16 a, UINT16 b );
+static UINT16 bcd_tencomp( UINT16 a );
+static UINT16 bcd_sub( UINT16 a, UINT16 b);
+
+/* Static variables */
+
+#define RM(Addr) ((unsigned)cpustate->program->read_byte(Addr))
+#define WM(Addr,Value) (cpustate->program->write_byte(Addr, Value))
+
+#define IMMBYTE(b) b = ((unsigned)cpustate->direct->read_raw_byte(pPC)); pPC++
+#define SIMMBYTE(b) b = ((signed)cpustate->direct->read_raw_byte(pPC)); pPC++
+#define IMMWORD(w) w.b.h = (unsigned)cpustate->direct->read_raw_byte(pPC++); w.b.l = (unsigned)cpustate->direct->read_raw_byte(pPC++)
+
+#define PUSHBYTE(b) pSP++; WM(pSP,b)
+#define PUSHWORD(w) pSP++; WM(pSP,w.b.h); pSP++; WM(pSP,w.b.l)
+#define PULLBYTE(b) b = RM(pSP); pSP--
+#define PULLWORD(w) w.b.l = RM(pSP); pSP--; w.b.h = RM(pSP); pSP--
+
+struct _tms7000_state
+{
+ PAIR pc; /* Program counter */
+ UINT8 sp; /* Stack Pointer */
+ UINT8 sr; /* Status Register */
+ UINT8 irq_state[3]; /* State of the three IRQs */
+ UINT8 rf[0x80]; /* Register file (SJE) */
+ UINT8 pf[0x100]; /* Perpherial file */
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *io;
+ int icount;
+ int div_by_16_trigger;
+ int cycles_per_INT2;
+ UINT8 t1_capture_latch; /* Timer 1 capture latch */
+ INT8 t1_prescaler; /* Timer 1 prescaler (5 bits) */
+ INT16 t1_decrementer; /* Timer 1 decrementer (8 bits) */
+ UINT8 idle_state; /* Set after the execution of an idle instruction */
+};
+
+INLINE tms7000_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == TMS7000 ||
+ device->type() == TMS7000_EXL);
+ return (tms7000_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+#define pPC cpustate->pc.w.l
+#define PC cpustate->pc
+#define pSP cpustate->sp
+#define pSR cpustate->sr
+
+#define RDA RM(0x0000)
+#define RDB RM(0x0001)
+
+#define WRA(Value) (WM(0x0000,Value))
+#define WRB(Value) (WM(0x0001,Value))
+
+#define SR_C 0x80 /* Carry */
+#define SR_N 0x40 /* Negative */
+#define SR_Z 0x20 /* Zero */
+#define SR_I 0x10 /* Interrupt */
+
+#define CLR_NZC pSR&=~(SR_N|SR_Z|SR_C)
+#define CLR_NZCI pSR&=~(SR_N|SR_Z|SR_C|SR_I)
+#define SET_C8(a) pSR|=((a&0x0100)>>1)
+#define SET_N8(a) pSR|=((a&0x0080)>>1)
+#define SET_Z(a) if(!a)pSR|=SR_Z
+#define SET_Z8(a) SET_Z((UINT8)a)
+#define SET_Z16(a) SET_Z((UINT8)a>>8)
+#define GET_C (pSR >> 7)
+
+/* Not working */
+#define SET_C16(a) pSR|=((a&0x010000)>>9)
+
+#define SETC pSR |= SR_C
+#define SETZ pSR |= SR_Z
+#define SETN pSR |= SR_N
+
+static READ8_HANDLER( tms7000_internal_r );
+static WRITE8_HANDLER( tms7000_internal_w );
+static READ8_HANDLER( tms70x0_pf_r );
+static WRITE8_HANDLER( tms70x0_pf_w );
+
+static ADDRESS_MAP_START(tms7000_mem, AS_PROGRAM, 8)
+ AM_RANGE(0x0000, 0x007f) AM_READWRITE(tms7000_internal_r, tms7000_internal_w) /* tms7000 internal RAM */
+ AM_RANGE(0x0080, 0x00ff) AM_NOP /* reserved */
+ AM_RANGE(0x0100, 0x01ff) AM_READWRITE(tms70x0_pf_r, tms70x0_pf_w) /* tms7000 internal I/O ports */
+ADDRESS_MAP_END
+
+
+INLINE UINT16 RM16( tms7000_state *cpustate, UINT32 mAddr ) /* Read memory (16-bit) */
+{
+ UINT32 result = RM(mAddr) << 8;
+ return result | RM((mAddr+1)&0xffff);
+}
+
+INLINE UINT16 RRF16( tms7000_state *cpustate, UINT32 mAddr ) /*Read register file (16 bit) */
+{
+ PAIR result;
+ result.b.h = RM((mAddr-1)&0xffff);
+ result.b.l = RM(mAddr);
+ return result.w.l;
+}
+
+INLINE void WRF16( tms7000_state *cpustate, UINT32 mAddr, PAIR p ) /*Write register file (16 bit) */
+{
+ WM( (mAddr-1)&0xffff, p.b.h );
+ WM( mAddr, p.b.l );
+}
+
+
+static CPU_INIT( tms7000 )
+{
+ tms7000_state *cpustate = get_safe_token(device);
+
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->io = device->space(AS_IO);
+
+ memset(cpustate->pf, 0, 0x100);
+ memset(cpustate->rf, 0, 0x80);
+
+ /* Save register state */
+ device->save_item(NAME(pPC));
+ device->save_item(NAME(pSP));
+ device->save_item(NAME(pSR));
+
+ /* Save Interrupt state */
+ device->save_item(NAME(cpustate->irq_state));
+
+ /* Save register and perpherial file state */
+ device->save_item(NAME(cpustate->rf));
+ device->save_item(NAME(cpustate->pf));
+
+ /* Save timer state */
+ device->save_item(NAME(cpustate->t1_prescaler));
+ device->save_item(NAME(cpustate->t1_capture_latch));
+ device->save_item(NAME(cpustate->t1_decrementer));
+
+ device->save_item(NAME(cpustate->idle_state));
+}
+
+static CPU_RESET( tms7000 )
+{
+ tms7000_state *cpustate = get_safe_token(device);
+
+// cpustate->architecture = (int)param;
+
+ cpustate->idle_state = 0;
+ cpustate->irq_state[ TMS7000_IRQ1_LINE ] = CLEAR_LINE;
+ cpustate->irq_state[ TMS7000_IRQ2_LINE ] = CLEAR_LINE;
+ cpustate->irq_state[ TMS7000_IRQ3_LINE ] = CLEAR_LINE;
+
+ WM( 0x100 + 9, 0 ); /* Data direction regs are cleared */
+ WM( 0x100 + 11, 0 );
+
+// if( cpustate->architecture == TMS7000_NMOS )
+// {
+ WM( 0x100 + 4, 0xff ); /* Output 0xff on port A */
+ WM( 0x100 + 8, 0xff ); /* Output 0xff on port C */
+ WM( 0x100 + 10, 0xff ); /* Output 0xff on port D */
+// }
+// else
+// {
+// WM( 0x100 + 4, 0xff ); /* Output 0xff on port A */
+// }
+
+ pSP = 0x01; /* Set stack pointer to r1 */
+ pSR = 0x00; /* Clear status register (disabling interrupts */
+ WM( 0x100 + 0, 0 ); /* Write a zero to IOCNT0 */
+
+ /* On TMS70x2 and TMS70Cx2 IOCNT1 is zero */
+
+ WRA( cpustate->pc.b.h ); /* Write previous PC to A:B */
+ WRB( cpustate->pc.b.l );
+ pPC = RM16(cpustate, 0xfffe); /* Load reset vector */
+
+ cpustate->div_by_16_trigger = -16;
+}
+
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( tms7000 )
+{
+ tms7000_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 + TMS7000_IRQ1_LINE: tms7000_set_irq_line(cpustate, TMS7000_IRQ1_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + TMS7000_IRQ2_LINE: tms7000_set_irq_line(cpustate, TMS7000_IRQ2_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + TMS7000_IRQ3_LINE: tms7000_set_irq_line(cpustate, TMS7000_IRQ3_LINE, info->i); break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + TMS7000_PC: pPC = info->i; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + TMS7000_SP: pSP = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS7000_ST: pSR = info->i; tms7000_check_IRQ_lines(cpustate); break;
+ case CPUINFO_INT_REGISTER + TMS7000_IDLE: cpustate->idle_state = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS7000_T1_CL: cpustate->t1_capture_latch = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS7000_T1_PS: cpustate->t1_prescaler = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS7000_T1_DEC: cpustate->t1_decrementer = info->i; break;
+ }
+}
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( tms7000 )
+{
+ tms7000_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(tms7000_state); 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_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 = 48; break; /* 48 represents the multiply instruction, the next highest is 17 */
+
+ 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 + TMS7000_IRQ1_LINE: info->i = cpustate->irq_state[TMS7000_IRQ1_LINE]; break;
+ case CPUINFO_INT_INPUT_STATE + TMS7000_IRQ2_LINE: info->i = cpustate->irq_state[TMS7000_IRQ2_LINE]; break;
+ case CPUINFO_INT_INPUT_STATE + TMS7000_IRQ3_LINE: info->i = cpustate->irq_state[TMS7000_IRQ3_LINE]; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = 0; /* Not supported */ break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + TMS7000_PC: info->i = pPC; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + TMS7000_SP: info->i = pSP; break;
+ case CPUINFO_INT_REGISTER + TMS7000_ST: info->i = pSR; break;
+ case CPUINFO_INT_REGISTER + TMS7000_IDLE: info->i = cpustate->idle_state; break;
+ case CPUINFO_INT_REGISTER + TMS7000_T1_CL: info->i = cpustate->t1_capture_latch; break;
+ case CPUINFO_INT_REGISTER + TMS7000_T1_PS: info->i = cpustate->t1_prescaler; break;
+ case CPUINFO_INT_REGISTER + TMS7000_T1_DEC: info->i = cpustate->t1_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(tms7000); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(tms7000); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(tms7000); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(tms7000); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; /* Not supported */break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(tms7000); 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(tms7000_mem); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "TMS7000"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Texas Instriuments TMS7000"); 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 tim lindner"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c",
+ cpustate->sr & 0x80 ? 'C':'c',
+ cpustate->sr & 0x40 ? 'N':'n',
+ cpustate->sr & 0x20 ? 'Z':'z',
+ cpustate->sr & 0x10 ? 'I':'i',
+ cpustate->sr & 0x08 ? '?':'.',
+ cpustate->sr & 0x04 ? '?':'.',
+ cpustate->sr & 0x02 ? '?':'.',
+ cpustate->sr & 0x01 ? '?':'.' );
+ break;
+
+ case CPUINFO_STR_REGISTER + TMS7000_PC: sprintf(info->s, "PC:%04X", cpustate->pc.w.l); break;
+ case CPUINFO_STR_REGISTER + TMS7000_SP: sprintf(info->s, "S:%02X", cpustate->sp); break;
+ case CPUINFO_STR_REGISTER + TMS7000_ST: sprintf(info->s, "ST:%02X", cpustate->sr); break;
+ case CPUINFO_STR_REGISTER + TMS7000_IDLE: sprintf(info->s, "Idle:%02X", cpustate->idle_state); break;
+ case CPUINFO_STR_REGISTER + TMS7000_T1_CL: sprintf(info->s, "T1CL:%02X", cpustate->t1_capture_latch); break;
+ case CPUINFO_STR_REGISTER + TMS7000_T1_PS: sprintf(info->s, "T1PS:%02X", cpustate->t1_prescaler & 0x1f); break;
+ case CPUINFO_STR_REGISTER + TMS7000_T1_DEC: sprintf(info->s, "T1DEC:%02X", cpustate->t1_decrementer & 0xff); break;
+
+ }
+}
+
+CPU_GET_INFO( tms7000_exl )
+{
+ switch( state )
+ {
+ case CPUINFO_FCT_EXECUTE:
+ info->execute = CPU_EXECUTE_NAME(tms7000_exl);
+ break;
+ default:
+ CPU_GET_INFO_CALL(tms7000);
+ break;
+ }
+}
+
+void tms7000_set_irq_line(tms7000_state *cpustate, int irqline, int state)
+{
+ if (cpustate->irq_state[irqline] != state)
+ { /* check for transition */
+ cpustate->irq_state[irqline] = state;
+
+ LOG(("tms7000: (cpu '%s') set_irq_line (INT%d, state %d)\n", cpustate->device->tag(), irqline+1, state));
+
+ if (state == CLEAR_LINE)
+ {
+ return;
+ }
+
+ cpustate->pf[0] |= (0x02 << (irqline * 2)); /* Set INTx iocntl0 flag */
+
+ if( irqline == TMS7000_IRQ3_LINE )
+ {
+ /* Latch the value in perpherial file register 3 */
+ cpustate->t1_capture_latch = cpustate->t1_decrementer & 0x00ff;
+ }
+
+ tms7000_check_IRQ_lines(cpustate);
+ }
+}
+
+static void tms7000_check_IRQ_lines(tms7000_state *cpustate)
+{
+ if( pSR & SR_I ) /* Check Global Interrupt bit: Status register, bit 4 */
+ {
+ if ((cpustate->irq_state[TMS7000_IRQ1_LINE] == ASSERT_LINE) || (cpustate->pf[0] & 0x02))
+ {
+ if( cpustate->pf[0] & 0x01 ) /* INT1 Enable bit */
+ {
+ tms7000_do_interrupt( cpustate, 0xfffc, TMS7000_IRQ1_LINE );
+ cpustate->pf[0] &= ~0x02; /* Data Manual, page: 9-41 */
+ return;
+ }
+ }
+
+ if( cpustate->irq_state[ TMS7000_IRQ2_LINE ] == ASSERT_LINE )
+ {
+ if( cpustate->pf[0] & 0x04 ) /* INT2 Enable bit */
+ {
+ tms7000_do_interrupt( cpustate, 0xfffa, TMS7000_IRQ2_LINE );
+ return;
+ }
+ }
+
+ if ((cpustate->irq_state[TMS7000_IRQ3_LINE] == ASSERT_LINE) || (cpustate->pf[0] & 0x20))
+ {
+ if( cpustate->pf[0] & 0x10 ) /* INT3 Enable bit */
+ {
+ tms7000_do_interrupt( cpustate, 0xfff8, TMS7000_IRQ3_LINE );
+ cpustate->pf[0] &= ~0x20; /* Data Manual, page: 9-41 */
+ return;
+ }
+ }
+ }
+}
+
+static void tms7000_do_interrupt( tms7000_state *cpustate, UINT16 address, UINT8 line )
+{
+ PUSHBYTE( pSR ); /* Push Status register */
+ PUSHWORD( PC ); /* Push Program Counter */
+ pSR = 0; /* Clear Status register */
+ pPC = RM16(cpustate, address); /* Load PC with interrupt vector */
+
+ if( cpustate->idle_state == 0 )
+ cpustate->icount -= 19; /* 19 cycles used */
+ else
+ {
+ cpustate->icount -= 17; /* 17 if idled */
+ cpustate->idle_state = 0;
+ }
+
+ (void)(*cpustate->irq_callback)(cpustate->device, line);
+}
+
+#include "tms70op.c"
+#include "tms70tb.c"
+
+static CPU_EXECUTE( tms7000 )
+{
+ tms7000_state *cpustate = get_safe_token(device);
+ int op;
+
+ cpustate->div_by_16_trigger += cpustate->icount;
+
+ tms7000_check_IRQ_lines(cpustate);
+
+ do
+ {
+ debugger_instruction_hook(device, pPC);
+
+ if( cpustate->idle_state == 0 )
+ {
+ op = cpustate->direct->read_decrypted_byte(pPC++);
+
+ opfn[op](cpustate);
+ }
+ else
+ cpustate->icount -= 16;
+
+ /* Internal timer system */
+
+ while( cpustate->icount < cpustate->div_by_16_trigger )
+ {
+ cpustate->div_by_16_trigger -= 16;
+
+ if( (cpustate->pf[0x03] & 0x80) == 0x80 ) /* Is timer system active? */
+ {
+ if( (cpustate->pf[0x03] & 0x40) != 0x40) /* Is system clock (divided by 16) the timer source? */
+ tms7000_service_timer1(device);
+ }
+ }
+
+ } while( cpustate->icount > 0 );
+
+ cpustate->div_by_16_trigger -= cpustate->icount;
+}
+
+static CPU_EXECUTE( tms7000_exl )
+{
+ tms7000_state *cpustate = get_safe_token(device);
+ int op;
+
+ cpustate->div_by_16_trigger += cpustate->icount;
+
+ tms7000_check_IRQ_lines(cpustate);
+
+ do
+ {
+ debugger_instruction_hook(device, pPC);
+
+ if( cpustate->idle_state == 0 )
+ {
+
+ op = cpustate->direct->read_decrypted_byte(pPC++);
+
+ opfn_exl[op](cpustate);
+ }
+ else
+ cpustate->icount -= 16;
+
+ /* Internal timer system */
+
+ while( cpustate->icount < cpustate->div_by_16_trigger )
+ {
+ cpustate->div_by_16_trigger -= 16;
+
+ if( (cpustate->pf[0x03] & 0x80) == 0x80 ) /* Is timer system active? */
+ {
+ if( (cpustate->pf[0x03] & 0x40) != 0x40) /* Is system clock (divided by 16) the timer source? */
+ tms7000_service_timer1(device);
+ }
+ }
+
+ } while( cpustate->icount > 0 );
+
+ cpustate->div_by_16_trigger -= cpustate->icount;
+}
+
+/****************************************************************************
+ * Trigger the event counter
+ ****************************************************************************/
+void tms7000_A6EC1( device_t *device )
+{
+ tms7000_state *cpustate = get_safe_token(device);
+ if( (cpustate->pf[0x03] & 0x80) == 0x80 ) /* Is timer system active? */
+ {
+ if( (cpustate->pf[0x03] & 0x40) == 0x40) /* Is event counter the timer source? */
+ tms7000_service_timer1(device);
+ }
+}
+
+static void tms7000_service_timer1( device_t *device )
+{
+ tms7000_state *cpustate = get_safe_token(device);
+ if( --cpustate->t1_prescaler < 0 ) /* Decrement prescaler and check for underflow */
+ {
+ cpustate->t1_prescaler = cpustate->pf[3] & 0x1f; /* Reload prescaler (5 bit) */
+
+ if( --cpustate->t1_decrementer < 0 ) /* Decrement timer1 register and check for underflow */
+ {
+ cpustate->t1_decrementer = cpustate->pf[2]; /* Reload decrementer (8 bit) */
+ device_set_input_line(device, TMS7000_IRQ2_LINE, HOLD_LINE);
+ //LOG( ("tms7000: trigger int2 (cycles: %d)\t%d\tdelta %d\n", cpustate->device->total_cycles(), cpustate->device->total_cycles() - tick, cpustate->cycles_per_INT2-(cpustate->device->total_cycles() - tick) );
+ //tick = cpustate->device->total_cycles() );
+ /* Also, cascade out to timer 2 - timer 2 unimplemented */
+ }
+ }
+// LOG( ( "tms7000: service timer1. 0x%2.2x 0x%2.2x (cycles %d)\t%d\t\n", cpustate->t1_prescaler, cpustate->t1_decrementer, cpustate->device->total_cycles(), cpustate->device->total_cycles() - tick2 ) );
+// tick2 = cpustate->device->total_cycles();
+}
+
+static WRITE8_HANDLER( tms70x0_pf_w ) /* Perpherial file write */
+{
+ tms7000_state *cpustate = get_safe_token(&space->device());
+ UINT8 temp1, temp2, temp3;
+
+ switch( offset )
+ {
+ case 0x00: /* IOCNT0, Input/Ouput control */
+ temp1 = data & 0x2a; /* Record which bits to clear */
+ temp2 = cpustate->pf[0x00] & 0x2a; /* Get copy of current bits */
+ temp3 = (~temp1) & temp2; /* Clear the requested bits */
+ cpustate->pf[0x00] = temp3 | (data & (~0x2a) ); /* OR in the remaining data */
+ break;
+ case 0x02:
+ cpustate->t1_decrementer = cpustate->pf[0x02] = data;
+ cpustate->cycles_per_INT2 = 0x10*((cpustate->pf[3] & 0x1f)+1)*(cpustate->pf[0x02]+1);
+ LOG( ( "tms7000: Timer adjusted. Decrementer: 0x%2.2x (Cycles per interrupt: %d)\n", cpustate->t1_decrementer, cpustate->cycles_per_INT2 ) );
+ break;
+ case 0x03: /* T1CTL, timer 1 control */
+ if( ((cpustate->pf[0x03] & 0x80) == 0) && ((data & 0x80) == 0x80 ) ) /* Start timer? */
+ {
+ cpustate->pf[0x03] = data;
+ cpustate->t1_prescaler = cpustate->pf[3] & 0x1f; /* Reload prescaler (5 bit) */
+ cpustate->cycles_per_INT2 = 0x10*((cpustate->pf[3] & 0x1f)+1)*(cpustate->pf[0x02]+1);
+ LOG( ( "tms7000: Timer started. Prescaler: 0x%2.2x (Cycles per interrupt: %d)\n", cpustate->pf[3] & 0x1f, cpustate->cycles_per_INT2 ) );
+ }
+ else if( ((data & 0x80) == 0x80 ) && ((cpustate->pf[0x03] & 0x80) == 0) ) /* Timer Stopped? */
+ {
+ cpustate->pf[0x03] = data;
+ cpustate->t1_prescaler = cpustate->pf[3] & 0x1f; /* Reload prescaler (5 bit) */
+ cpustate->cycles_per_INT2 = 0x10*((cpustate->pf[3] & 0x1f)+1)*(cpustate->pf[0x02]+1);
+ LOG( ( "tms7000: Timer stopped. Prescaler: 0x%2.2x (Cycles per interrupt: %d)\n", cpustate->pf[3] & 0x1f, cpustate->cycles_per_INT2 ) );
+ }
+ else /* Don't modify timer state, but still store data */
+ {
+ cpustate->pf[0x03] = data;
+ cpustate->cycles_per_INT2 = 0x10*((cpustate->pf[3] & 0x1f)+1)*(cpustate->pf[0x02]+1);
+ LOG( ( "tms7000: Timer adjusted. Prescaler: 0x%2.2x (Cycles per interrupt: %d)\n", cpustate->pf[3] & 0x1f, cpustate->cycles_per_INT2 ) );
+ }
+ break;
+
+ case 0x04: /* Port A write */
+ /* Port A is read only so this is a NOP */
+ break;
+
+ case 0x06: /* Port B write */
+ cpustate->io->write_byte( TMS7000_PORTB, data );
+ cpustate->pf[ 0x06 ] = data;
+ break;
+
+ case 0x08: /* Port C write */
+ temp1 = data & cpustate->pf[ 0x09 ]; /* Mask off input bits */
+ cpustate->io->write_byte( TMS7000_PORTC, temp1 );
+ cpustate->pf[ 0x08 ] = temp1;
+ break;
+
+ case 0x0a: /* Port D write */
+ temp1 = data & cpustate->pf[ 0x0b ]; /* Mask off input bits */
+ cpustate->io->write_byte( TMS7000_PORTD, temp1 );
+ cpustate->pf[ 0x0a ] = temp1;
+ break;
+
+ default:
+ /* Just stuff the other registers */
+ cpustate->pf[ offset ] = data;
+ break;
+ }
+}
+
+static READ8_HANDLER( tms70x0_pf_r ) /* Perpherial file read */
+{
+ tms7000_state *cpustate = get_safe_token(&space->device());
+ UINT8 result;
+ UINT8 temp1, temp2, temp3;
+
+ switch( offset )
+ {
+ case 0x00: /* IOCNT0, Input/Ouput control */
+ result = cpustate->pf[0x00];
+ if (cpustate->irq_state[TMS7000_IRQ1_LINE] == ASSERT_LINE)
+ result |= 0x02;
+ if (cpustate->irq_state[TMS7000_IRQ3_LINE] == ASSERT_LINE)
+ result |= 0x20;
+ break;
+
+ case 0x02: /* T1DATA, timer 1 8-bit decrementer */
+ result = (cpustate->t1_decrementer & 0x00ff);
+ break;
+
+ case 0x03: /* T1CTL, timer 1 capture (latched by INT3) */
+ result = cpustate->t1_capture_latch;
+ break;
+
+ case 0x04: /* Port A read */
+ result = cpustate->io->read_byte( TMS7000_PORTA );
+ break;
+
+
+ case 0x06: /* Port B read */
+ /* Port B is write only, return a previous written value */
+ result = cpustate->pf[ 0x06 ];
+ break;
+
+ case 0x08: /* Port C read */
+ temp1 = cpustate->pf[ 0x08 ] & cpustate->pf[ 0x09 ]; /* Get previous output bits */
+ temp2 = cpustate->io->read_byte( TMS7000_PORTC ); /* Read port */
+ temp3 = temp2 & (~cpustate->pf[ 0x09 ]); /* Mask off output bits */
+ result = temp1 | temp3; /* OR together */
+ break;
+
+ case 0x0a: /* Port D read */
+ temp1 = cpustate->pf[ 0x0a ] & cpustate->pf[ 0x0b ]; /* Get previous output bits */
+ temp2 = cpustate->io->read_byte( TMS7000_PORTD ); /* Read port */
+ temp3 = temp2 & (~cpustate->pf[ 0x0b ]); /* Mask off output bits */
+ result = temp1 | temp3; /* OR together */
+ break;
+
+ default:
+ /* Just unstuff the other registers */
+ result = cpustate->pf[ offset ];
+ break;
+ }
+
+ return result;
+}
+
+// BCD arthrimetic handling
+static UINT16 bcd_add( UINT16 a, UINT16 b )
+{
+ UINT16 t1,t2,t3,t4,t5,t6;
+
+ /* Sure it is a lot of code, but it works! */
+ t1 = a + 0x0666;
+ t2 = t1 + b;
+ t3 = t1 ^ b;
+ t4 = t2 ^ t3;
+ t5 = ~t4 & 0x1110;
+ t6 = (t5 >> 2) | (t5 >> 3);
+ return t2-t6;
+}
+
+static UINT16 bcd_tencomp( UINT16 a )
+{
+ UINT16 t1,t2,t3,t4,t5,t6;
+
+ t1 = 0xffff - a;
+ t2 = -a;
+ t3 = t1 ^ 0x0001;
+ t4 = t2 ^ t3;
+ t5 = ~t4 & 0x1110;
+ t6 = (t5 >> 2)|(t5>>3);
+ return t2-t6;
+}
+
+/*
+ Compute difference a-b???
+*/
+static UINT16 bcd_sub( UINT16 a, UINT16 b)
+{
+ //return bcd_tencomp(b) - bcd_tencomp(a);
+ return bcd_add(a, bcd_tencomp(b) & 0xff);
+}
+
+static WRITE8_HANDLER( tms7000_internal_w ) {
+ tms7000_state *cpustate = get_safe_token(&space->device());
+ cpustate->rf[ offset ] = data;
+}
+
+static READ8_HANDLER( tms7000_internal_r ) {
+ tms7000_state *cpustate = get_safe_token(&space->device());
+ return cpustate->rf[ offset ];
+}
+
+DEFINE_LEGACY_CPU_DEVICE(TMS7000, tms7000);
+DEFINE_LEGACY_CPU_DEVICE(TMS7000_EXL, tms7000_exl);
diff --git a/trunk/src/emu/cpu/tms7000/tms7000.h b/trunk/src/emu/cpu/tms7000/tms7000.h
new file mode 100644
index 00000000000..db07f4fb36b
--- /dev/null
+++ b/trunk/src/emu/cpu/tms7000/tms7000.h
@@ -0,0 +1,56 @@
+/*****************************************************************************
+ *
+ * cpustate->h (c header file)
+ * Portable TMS7000 emulator (Texas Instruments 7000)
+ *
+ * Copyright tim lindner, 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
+ * tlindner@macmess.org
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+
+#pragma once
+
+#ifndef __TMS7000_H__
+#define __TMS7000_H__
+
+
+enum { TMS7000_PC=1, TMS7000_SP, TMS7000_ST, TMS7000_IDLE, TMS7000_T1_CL, TMS7000_T1_PS, TMS7000_T1_DEC };
+
+enum { TMS7000_VCC, TMS7000_VSS };
+
+enum { TMS7000_NMOS, TMS7000_CMOS };
+
+enum
+{
+ TMS7000_IRQ1_LINE = 0, /* INT1 */
+ TMS7000_IRQ2_LINE, /* INT2 */
+ TMS7000_IRQ3_LINE, /* INT3 */
+ TMS7000_IRQNONE = 255
+};
+
+enum
+{
+ TMS7000_PORTA = 0,
+ TMS7000_PORTB,
+ TMS7000_PORTC,
+ TMS7000_PORTD
+};
+
+/* PUBLIC FUNCTIONS */
+extern void tms7000_A6EC1( device_t *device ); /* External event counter */
+
+DECLARE_LEGACY_CPU_DEVICE(TMS7000, tms7000);
+DECLARE_LEGACY_CPU_DEVICE(TMS7000_EXL, tms7000_exl);
+
+extern CPU_DISASSEMBLE( tms7000 );
+
+#endif /* __TMS7000_H__ */
diff --git a/trunk/src/emu/cpu/tms7000/tms70op.c b/trunk/src/emu/cpu/tms7000/tms70op.c
new file mode 100644
index 00000000000..2b28f9755e9
--- /dev/null
+++ b/trunk/src/emu/cpu/tms7000/tms70op.c
@@ -0,0 +1,3903 @@
+/*****************************************************************************
+ *
+ * tms70op.c (Op code functions)
+ * Portable TMS7000 emulator (Texas Instruments 7000)
+ *
+ * Copyright tim lindner, 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
+ * tlindner@macmess.org
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+
+//SJE: Changed all references to ICount to icount (to match MAME requirements)
+//TJL: (From Gilles Fetis) JPZ in TI documentation was wrong:
+// if ((pSR & SR_N) == 0 && (pSR & SR_Z) != 0)
+// should be:
+// if ((pSR & SR_N) == 0)
+
+#include "emu.h"
+
+static void illegal(tms7000_state *cpustate)
+{
+ /* This is a guess */
+ cpustate->icount -= 4;
+}
+
+static void adc_b2a(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ t = RDA + RDB + GET_C;
+ WRA(t);
+
+ CLR_NZC;
+ SET_C8(t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 5;
+}
+
+static void adc_r2a(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+
+ t = RM(v) + RDA + GET_C;
+ WRA(t);
+
+ CLR_NZC;
+ SET_C8(t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 8;
+}
+
+static void adc_r2b(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+
+ t = RM(v) + RDB + GET_C;
+ WRB(t);
+
+ CLR_NZC;
+ SET_C8(t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 8;
+}
+
+static void adc_r2r(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 i,j;
+
+ IMMBYTE(i);
+ IMMBYTE(j);
+
+ t = RM(i)+RM(j) + GET_C;
+ WM(j,t);
+
+ CLR_NZC;
+ SET_C8(t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 10;
+}
+
+static void adc_i2a(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+
+ t = v + RDA + GET_C;
+ WRA(t);
+
+ CLR_NZC;
+ SET_C8(t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 7;
+}
+
+static void adc_i2b(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+
+ t = v + RDB + GET_C;
+ WRB(t);
+
+ CLR_NZC;
+ SET_C8(t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 7;
+}
+
+static void adc_i2r(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 i,j;
+
+ IMMBYTE(i);
+ IMMBYTE(j);
+
+ t = i+RM(j) + GET_C;
+ WM(j,t);
+
+ CLR_NZC;
+ SET_C8(t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 9;
+}
+
+static void add_b2a(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ t = RDA + RDB;
+ WRA(t);
+
+ CLR_NZC;
+ SET_C8(t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 5;
+}
+
+static void add_r2a(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+
+ t = RM(v) + RDA;
+ WRA(t);
+
+ CLR_NZC;
+ SET_C8(t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 8;
+}
+
+static void add_r2b(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+
+ t = RM(v) + RDB;
+ WRB(t);
+
+ CLR_NZC;
+ SET_C8(t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 8;
+}
+
+static void add_r2r(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 i,j;
+
+ IMMBYTE(i);
+ IMMBYTE(j);
+
+ t = RM(i)+RM(j);
+ WM(j,t);
+
+ CLR_NZC;
+ SET_C8(t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 10;
+}
+
+static void add_i2a(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+
+ t = v + RDA;
+ WRA(t);
+
+ CLR_NZC;
+ SET_C8(t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 7;
+}
+
+static void add_i2b(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+
+ t = v + RDB;
+ WRB(t);
+
+ CLR_NZC;
+ SET_C8(t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 7;
+}
+
+static void add_i2r(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 i,j;
+
+ IMMBYTE(i);
+ IMMBYTE(j);
+
+ t = i+RM(j);
+ WM(j,t);
+
+ CLR_NZC;
+ SET_C8(t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 9;
+}
+
+static void and_b2a(tms7000_state *cpustate)
+{
+ UINT8 t;
+
+ t = RDA & RDB;
+ WRA(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 5;
+}
+
+static void and_r2a(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+
+ t = RM(v) & RDA;
+ WRA(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 8;
+}
+
+static void and_r2b(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+
+ t = RM(v) & RDB;
+ WRB(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 8;
+}
+
+static void and_r2r(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 i,j;
+
+ IMMBYTE(i);
+ IMMBYTE(j);
+
+ t = RM(i) & RM(j);
+ WM(j,t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 10;
+}
+
+static void and_i2a(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+
+ t = v & RDA;
+ WRA(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 7;
+}
+
+static void and_i2b(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+
+ t = v & RDB;
+ WRB(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 7;
+}
+
+static void and_i2r(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 i,j;
+
+ IMMBYTE(i);
+ IMMBYTE(j);
+
+ t = i & RM(j);
+ WM(j,t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 9;
+}
+
+static void andp_a2p(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+ t = RDA & RM( 0x0100 + v);
+ WM( 0x0100+v, t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 10;
+}
+
+static void andp_b2p(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+ t = RDB & RM( 0x0100 + v);
+ WM( 0x0100+v, t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 9;
+}
+
+
+static void movp_i2p(tms7000_state *cpustate)
+{
+ UINT8 i,v;
+
+ IMMBYTE(i);
+ IMMBYTE(v);
+ WM( 0x0100+v, i);
+
+ CLR_NZC;
+ SET_N8(i);
+ SET_Z8(i);
+
+ cpustate->icount -= 11;
+}
+
+static void andp_i2p(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 i,v;
+
+ IMMBYTE(i);
+ IMMBYTE(v);
+ t = i & RM( 0x0100 + v);
+ WM( 0x0100+v, t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 11;
+}
+
+static void br_dir(tms7000_state *cpustate)
+{
+ PAIR p;
+
+ IMMWORD( p );
+ pPC = p.d;
+ cpustate->icount -= 10;
+}
+
+static void br_ind(tms7000_state *cpustate)
+{
+ UINT8 v;
+
+ IMMBYTE( v );
+ PC.w.l = RRF16(cpustate,v);
+
+ cpustate->icount -= 9;
+}
+
+static void br_inx(tms7000_state *cpustate)
+{
+ PAIR p;
+
+ IMMWORD( p );
+ pPC = p.w.l + RDB;
+ cpustate->icount -= 12;
+}
+
+static void btjo_b2a(tms7000_state *cpustate)
+{
+ UINT8 t;
+
+ t = RDB & RDA;
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if(t != 0)
+ {
+ INT8 j;
+
+ SIMMBYTE( j );
+ pPC += j;
+ cpustate->icount -= 9;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 7;
+ }
+}
+
+static void btjo_r2a(tms7000_state *cpustate)
+{
+ UINT8 t,r;
+
+ IMMBYTE( r );
+ t = RM( r ) & RDA;
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if(t != 0)
+ {
+ INT8 j;
+
+ SIMMBYTE( j );
+ pPC += j;
+ cpustate->icount -= 9;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 7;
+ }
+}
+
+static void btjo_r2b(tms7000_state *cpustate)
+{
+ UINT8 t,r;
+
+ IMMBYTE(r);
+ t = RM(r) & RDB;
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if(t != 0)
+ {
+ INT8 j;
+
+ SIMMBYTE(j);
+ pPC += j;
+ cpustate->icount -= 12;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 10;
+ }
+}
+
+static void btjo_r2r(tms7000_state *cpustate)
+{
+ UINT8 t,r,s;
+
+ IMMBYTE(r);
+ IMMBYTE(s);
+ t = RM(r) & RM(s);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if(t != 0)
+ {
+ INT8 j;
+
+ SIMMBYTE(j);
+ pPC += j;
+ cpustate->icount -= 14;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 12;
+ }
+}
+
+static void btjo_i2a(tms7000_state *cpustate)
+{
+ UINT8 t,r;
+
+ IMMBYTE(r);
+ t = r & RDA;
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if(t != 0)
+ {
+ INT8 j;
+
+ SIMMBYTE(j);
+ pPC += j;
+ cpustate->icount -= 11;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 9;
+ }
+}
+
+static void btjo_i2b(tms7000_state *cpustate)
+{
+ UINT8 t,i;
+
+ IMMBYTE(i);
+ t = i & RDB;
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if(t != 0)
+ {
+ INT8 j;
+
+ SIMMBYTE(j);
+ pPC += j;
+ cpustate->icount -= 11;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 9;
+ }
+}
+
+static void btjo_i2r(tms7000_state *cpustate)
+{
+ UINT8 t,i,r;
+
+ IMMBYTE(i);
+ IMMBYTE(r);
+ t = i & RM(r);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if(t != 0)
+ {
+ INT8 j;
+
+ SIMMBYTE(j);
+ pPC += j;
+ cpustate->icount -= 13;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 11;
+ }
+}
+
+static void btjop_ap(tms7000_state *cpustate)
+{
+ UINT8 t,p;
+
+ IMMBYTE(p);
+
+ t = RM(0x100+p) & RDA;
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if(t != 0)
+ {
+ INT8 j;
+
+ SIMMBYTE(j);
+ pPC += j;
+ cpustate->icount -= 13;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 11;
+ }
+}
+
+static void btjop_bp(tms7000_state *cpustate)
+{
+ UINT8 t,p;
+
+ IMMBYTE(p);
+
+ t = RM(0x100+p) & RDB;
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if(t != 0)
+ {
+ INT8 j;
+
+ SIMMBYTE(j);
+ pPC += j;
+ cpustate->icount -= 12;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 10;
+ }
+}
+
+static void btjop_ip(tms7000_state *cpustate)
+{
+ UINT8 t,p,i;
+
+ IMMBYTE(i);
+ IMMBYTE(p);
+
+ t = RM(0x100+p) & i;
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if(t != 0)
+ {
+ INT8 j;
+
+ SIMMBYTE(j);
+ pPC += j;
+ cpustate->icount -= 14;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 12;
+ }
+}
+
+static void btjz_b2a(tms7000_state *cpustate)
+{
+ UINT8 t;
+
+ t = RDB & ~RDA;
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if(t != 0)
+ {
+ INT8 j;
+
+ SIMMBYTE( j );
+ pPC += j;
+ cpustate->icount -= 9;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 7;
+ }
+}
+
+static void btjz_r2a(tms7000_state *cpustate)
+{
+ UINT8 t,r;
+
+ IMMBYTE( r );
+ t = RM( r ) & ~RDA;
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if(t != 0)
+ {
+ INT8 j;
+
+ SIMMBYTE( j );
+ pPC += j;
+ cpustate->icount -= 9;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 7;
+ }
+}
+
+static void btjz_r2b(tms7000_state *cpustate)
+{
+ UINT8 t,r;
+
+ IMMBYTE(r);
+ t = RM(r) & ~RDB;
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if(t != 0)
+ {
+ INT8 j;
+
+ SIMMBYTE(j);
+ pPC += j;
+ cpustate->icount -= 12;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 10;
+ }
+}
+
+static void btjz_r2r(tms7000_state *cpustate)
+{
+ UINT8 t,r,s;
+
+ IMMBYTE(r);
+ IMMBYTE(s);
+ t = RM(r) & ~RM(s);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if(t != 0)
+ {
+ INT8 j;
+
+ SIMMBYTE(j);
+ pPC += j;
+ cpustate->icount -= 14;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 12;
+ }
+}
+
+static void btjz_i2a(tms7000_state *cpustate)
+{
+ UINT8 t,r;
+
+ IMMBYTE(r);
+ t = r & ~RDA;
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if(t != 0)
+ {
+ INT8 j;
+
+ SIMMBYTE(j);
+ pPC += j;
+ cpustate->icount -= 11;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 9;
+ }
+}
+
+static void btjz_i2b(tms7000_state *cpustate)
+{
+ UINT8 t,i;
+
+ IMMBYTE(i);
+ t = i & ~RDB;
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if(t != 0)
+ {
+ INT8 j;
+
+ SIMMBYTE(j);
+ pPC += j;
+ cpustate->icount -= 11;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 9;
+ }
+}
+
+static void btjz_i2r(tms7000_state *cpustate)
+{
+ UINT8 t,i,r;
+
+ IMMBYTE(i);
+ IMMBYTE(r);
+ t = i & ~RM(r);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if(t != 0)
+ {
+ INT8 j;
+
+ SIMMBYTE(j);
+ pPC += j;
+ cpustate->icount -= 13;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 11;
+ }
+}
+
+static void btjzp_ap(tms7000_state *cpustate)
+{
+ UINT8 t,p;
+
+ IMMBYTE(p);
+
+ t = RDA & ~RM(0x100+p);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if(t != 0)
+ {
+ INT8 j;
+
+ SIMMBYTE(j);
+ pPC += j;
+ cpustate->icount -= 13;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 11;
+ }
+}
+
+static void btjzp_bp(tms7000_state *cpustate)
+{
+ UINT8 t,p;
+
+ IMMBYTE(p);
+
+ t = RDB & ~RM(0x100+p);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if(t != 0)
+ {
+ INT8 j;
+
+ SIMMBYTE(j);
+ pPC += j;
+ cpustate->icount -= 12;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 10;
+ }
+}
+
+static void btjzp_ip(tms7000_state *cpustate)
+{
+ UINT8 t,p,i;
+
+ IMMBYTE(i);
+ IMMBYTE(p);
+
+ t = i & ~RM(0x100+p);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if(t != 0)
+ {
+ INT8 j;
+
+ SIMMBYTE(j);
+ pPC += j;
+ cpustate->icount -= 14;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 12;
+ }
+}
+
+static void call_dir(tms7000_state *cpustate)
+{
+ PAIR tPC;
+
+ IMMWORD( tPC );
+ PUSHWORD( PC );
+ pPC = tPC.d;
+
+ cpustate->icount -= 14;
+}
+
+static void call_ind(tms7000_state *cpustate)
+{
+ UINT8 v;
+
+ IMMBYTE( v );
+ PUSHWORD( PC );
+ PC.w.l = RRF16(cpustate,v);
+
+ cpustate->icount -= 13;
+}
+
+static void call_inx(tms7000_state *cpustate)
+{
+ PAIR tPC;
+
+ IMMWORD( tPC );
+ PUSHWORD( PC );
+ pPC = tPC.w.l + RDB;
+ cpustate->icount -= 16;
+}
+
+static void clr_a(tms7000_state *cpustate)
+{
+ WRA(0);
+ cpustate->icount -= 5;
+}
+
+static void clr_b(tms7000_state *cpustate)
+{
+ WRB(0);
+ cpustate->icount -= 5;
+}
+
+static void clr_r(tms7000_state *cpustate)
+{
+ UINT8 r;
+
+ IMMBYTE(r);
+ WM(r,0);
+ cpustate->icount -= 7;
+}
+
+static void clrc(tms7000_state *cpustate)
+{
+ UINT8 a;
+
+ a = RDA;
+
+ CLR_NZC;
+ SET_N8(a);
+ SET_Z8(a);
+
+ cpustate->icount -= 6;
+}
+
+static void cmp_ba(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ t = RDA - RDB;
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if( t==0 )
+ SETC;
+ else
+ SET_C8( ~t );
+
+ cpustate->icount -= 5;
+}
+
+static void cmp_ra(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 r;
+
+ IMMBYTE(r);
+ t = RDA - RM(r);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if( t==0 )
+ SETC;
+ else
+ SET_C8( ~t );
+
+ cpustate->icount -= 8;
+}
+
+static void cmp_rb(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 r;
+
+ IMMBYTE(r);
+ t = RDB - RM(r);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if( t==0 )
+ SETC;
+ else
+ SET_C8( ~t );
+
+ cpustate->icount -= 8;
+}
+
+static void cmp_rr(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 r,s;
+
+ IMMBYTE(r);
+ IMMBYTE(s);
+ t = RM(s) - RM(r);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if( t==0 )
+ SETC;
+ else
+ SET_C8( ~t );
+
+ cpustate->icount -= 10;
+}
+
+static void cmp_ia(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 i;
+
+ IMMBYTE(i);
+ t = RDA - i;
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if( t==0 )
+ SETC;
+ else
+ SET_C8( ~t );
+
+ cpustate->icount -= 7;
+}
+
+static void cmp_ib(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 i;
+
+ IMMBYTE(i);
+ t = RDB - i;
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if( t==0 )
+ SETC;
+ else
+ SET_C8( ~t );
+
+ cpustate->icount -= 7;
+}
+
+static void cmp_ir(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 i,r;
+
+ IMMBYTE(i);
+ IMMBYTE(r);
+ t = RM(r) - i;
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if( t==0 )
+ SETC;
+ else
+ SET_C8( ~t );
+
+ cpustate->icount -= 9;
+}
+
+static void cmpa_dir(tms7000_state *cpustate)
+{
+ UINT16 t;
+ PAIR i;
+
+ IMMWORD( i );
+ t = RDA - RM(i.w.l);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if( t==0 )
+ SETC;
+ else
+ SET_C8( ~t );
+
+ cpustate->icount -= 12;
+}
+
+static void cmpa_ind(tms7000_state *cpustate)
+{
+ UINT16 t;
+ PAIR p;
+ INT8 i;
+
+ IMMBYTE(i);
+ p.w.l = RRF16(cpustate,i);
+ t = RDA - RM(p.w.l);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if( t==0 )
+ SETC;
+ else
+ SET_C8( ~t );
+
+ cpustate->icount -= 11;
+}
+
+static void cmpa_inx(tms7000_state *cpustate)
+{
+ UINT16 t;
+ PAIR i;
+
+ IMMWORD( i );
+ t = RDA - RM(i.w.l + RDB);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if( t==0 )
+ SETC;
+ else
+ SET_C8( ~t );
+
+ cpustate->icount -= 14;
+}
+
+static void dac_b2a(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ t = bcd_add( RDA, RDB );
+
+ if (pSR & SR_C)
+ t = bcd_add( t, 1 );
+
+ WRA(t);
+
+ CLR_NZC;
+ SET_C8(t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 7;
+}
+
+static void dac_r2a(tms7000_state *cpustate)
+{
+ UINT8 r;
+ UINT16 t;
+
+ IMMBYTE(r);
+
+ t = bcd_add( RDA, RM(r) );
+
+ if (pSR & SR_C)
+ t = bcd_add( t, 1 );
+
+ WRA(t);
+
+ CLR_NZC;
+ SET_C8(t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 10;
+}
+
+static void dac_r2b(tms7000_state *cpustate)
+{
+ UINT8 r;
+ UINT16 t;
+
+ IMMBYTE(r);
+
+ t = bcd_add( RDB, RM(r) );
+
+ if (pSR & SR_C)
+ t = bcd_add( t, 1 );
+
+ WRB(t);
+
+ CLR_NZC;
+ SET_C8(t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 10;
+}
+
+static void dac_r2r(tms7000_state *cpustate)
+{
+ UINT8 r,s;
+ UINT16 t;
+
+ IMMBYTE(s);
+ IMMBYTE(r);
+
+ t = bcd_add( RM(s), RM(r) );
+
+ if (pSR & SR_C)
+ t = bcd_add( t, 1 );
+
+ WM(r,t);
+
+ CLR_NZC;
+ SET_C8(t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 12;
+}
+
+static void dac_i2a(tms7000_state *cpustate)
+{
+ UINT8 i;
+ UINT16 t;
+
+ IMMBYTE(i);
+
+ t = bcd_add( i, RDA );
+
+ if (pSR & SR_C)
+ t = bcd_add( t, 1 );
+
+ WRA(t);
+
+ CLR_NZC;
+ SET_C8(t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 9;
+}
+
+static void dac_i2b(tms7000_state *cpustate)
+{
+ UINT8 i;
+ UINT16 t;
+
+ IMMBYTE(i);
+
+ t = bcd_add( i, RDB );
+
+ if (pSR & SR_C)
+ t = bcd_add( t, 1 );
+
+ WRB(t);
+
+ CLR_NZC;
+ SET_C8(t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 9;
+}
+
+static void dac_i2r(tms7000_state *cpustate)
+{
+ UINT8 i,r;
+ UINT16 t;
+
+ IMMBYTE(i);
+ IMMBYTE(r);
+
+ t = bcd_add( i, RM(r) );
+
+ if (pSR & SR_C)
+ t = bcd_add( t, 1 );
+
+ WM(r,t);
+
+ CLR_NZC;
+ SET_C8(t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 11;
+}
+
+static void dec_a(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ t = RDA - 1;
+
+ WRA( t );
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+ SET_C8(~t);
+
+ cpustate->icount -= 5;
+}
+
+static void dec_b(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ t = RDB - 1;
+
+ WRB( t );
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+ SET_C8(~t);
+
+ cpustate->icount -= 5;
+}
+
+static void dec_r(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 r;
+
+ IMMBYTE(r);
+
+ t = RM(r) - 1;
+
+ WM( r, t );
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+ SET_C8(~t);
+
+ cpustate->icount -= 7;
+}
+
+static void decd_a(tms7000_state *cpustate)
+{
+ PAIR t;
+
+ t.w.h = 0;
+ t.w.l = RRF16(cpustate,0);
+ t.d -= 1;
+ WRF16(cpustate,0,t);
+
+ CLR_NZC;
+ SET_N8(t.b.h);
+ SET_Z8(t.b.h);
+
+ SET_C16(~(t.d));
+
+ cpustate->icount -= 9;
+}
+
+static void decd_b(tms7000_state *cpustate)
+{
+ PAIR t;
+
+ t.w.h = 0;
+ t.w.l = RRF16(cpustate,1);
+ t.d -= 1;
+ WRF16(cpustate,1,t);
+
+ CLR_NZC;
+ SET_N8(t.b.h);
+ SET_Z8(t.b.h);
+
+ SET_C16(~(t.d));
+
+ cpustate->icount -= 9;
+}
+
+static void decd_r(tms7000_state *cpustate)
+{
+ UINT8 r;
+ PAIR t;
+
+ IMMBYTE(r);
+ t.w.h = 0;
+ t.w.l = RRF16(cpustate,r);
+ t.d -= 1;
+ WRF16(cpustate,r,t);
+
+ CLR_NZC;
+ SET_N8(t.b.h);
+ SET_Z8(t.b.h);
+
+ SET_C16(~(t.d));
+
+ cpustate->icount -= 11;
+}
+
+static void dint(tms7000_state *cpustate)
+{
+ CLR_NZCI;
+ cpustate->icount -= 5;
+}
+
+static void djnz_a(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ t = RDA - 1;
+
+ WRA( t );
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if( t != 0 )
+ {
+ INT8 s;
+
+ SIMMBYTE(s);
+ pPC += s;
+ cpustate->icount -= 7;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 2;
+ }
+}
+
+static void djnz_b(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ t = RDB - 1;
+
+ WRB( t );
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if( t != 0 )
+ {
+ INT8 s;
+
+ SIMMBYTE(s);
+ pPC += s;
+ cpustate->icount -= 7;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 2;
+ }
+}
+
+static void djnz_r(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 r;
+
+ IMMBYTE(r);
+
+ t = RM(r) - 1;
+
+ WM(r,t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ if( t != 0 )
+ {
+ INT8 s;
+
+ SIMMBYTE(s);
+ pPC += s;
+ cpustate->icount -= 9;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 3;
+ }
+}
+
+static void dsb_b2a(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ t = bcd_sub( RDA, RDB );
+
+ if( !(pSR & SR_C) )
+ t = bcd_sub( t, 1 );
+
+ WRA(t);
+
+ CLR_NZC;
+ SET_C8(~t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 7;
+}
+
+static void dsb_r2a(tms7000_state *cpustate)
+{
+ UINT8 r;
+ UINT16 t;
+
+ IMMBYTE(r);
+
+ t = bcd_sub( RDA, RM(r) );
+
+ if( !(pSR & SR_C) )
+ t = bcd_sub( t, 1 );
+
+ WRA(t);
+
+ CLR_NZC;
+ SET_C8(~t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 10;
+}
+
+static void dsb_r2b(tms7000_state *cpustate)
+{
+ UINT8 r;
+ UINT16 t;
+
+ IMMBYTE(r);
+
+ t = bcd_sub( RDB, RM(r) );
+
+ if( !(pSR & SR_C) )
+ t = bcd_sub( t, 1 );
+
+ WRB(t);
+
+ CLR_NZC;
+ SET_C8(~t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 10;
+}
+
+static void dsb_r2r(tms7000_state *cpustate)
+{
+ UINT8 r,s;
+ UINT16 t;
+
+ IMMBYTE(s);
+ IMMBYTE(r);
+
+ t = bcd_sub( RM(s), RM(r) );
+
+ if( !(pSR & SR_C) )
+ t = bcd_sub( t, 1 );
+
+ WM(r,t);
+
+ CLR_NZC;
+ SET_C8(~t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 12;
+}
+
+static void dsb_i2a(tms7000_state *cpustate)
+{
+ UINT8 i;
+ UINT16 t;
+
+ IMMBYTE(i);
+
+ t = bcd_sub( RDA, i );
+
+ if( !(pSR & SR_C) )
+ t = bcd_sub( t, 1 );
+
+ WRA(t);
+
+ CLR_NZC;
+ SET_C8(~t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 9;
+}
+
+static void dsb_i2b(tms7000_state *cpustate)
+{
+ UINT8 i;
+ UINT16 t;
+
+ IMMBYTE(i);
+
+ t = bcd_sub( RDB, i );
+
+ if( !(pSR & SR_C) )
+ t = bcd_sub( t, 1 );
+
+ WRB(t);
+
+ CLR_NZC;
+ SET_C8(~t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 9;
+}
+
+static void dsb_i2r(tms7000_state *cpustate)
+{
+ UINT8 r,i;
+ UINT16 t;
+
+ IMMBYTE(i);
+ IMMBYTE(r);
+
+ t = bcd_sub( RM(r), i );
+
+ if( !(pSR & SR_C) )
+ t = bcd_sub( t, 1 );
+
+ WM(r,t);
+
+ CLR_NZC;
+ SET_C8(~t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 11;
+}
+
+static void eint(tms7000_state *cpustate)
+{
+ pSR |= (SR_N|SR_Z|SR_C|SR_I);
+ cpustate->icount -= 5;
+ tms7000_check_IRQ_lines(cpustate);
+}
+
+static void idle(tms7000_state *cpustate)
+{
+ cpustate->idle_state = 1;
+ cpustate->icount -= 6;
+}
+
+static void inc_a(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ t = RDA + 1;
+
+ WRA( t );
+
+ CLR_NZC;
+ SET_C8(t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 5;
+}
+
+static void inc_b(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ t = RDB + 1;
+
+ WRB( t );
+
+ CLR_NZC;
+ SET_C8(t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 5;
+}
+
+static void inc_r(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 r;
+
+ IMMBYTE(r);
+
+ t = RM(r) + 1;
+
+ WM( r, t );
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+ SET_C8(t);
+
+ cpustate->icount -= 7;
+}
+
+static void inv_a(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ t = ~(RDA);
+ WRA(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 5;
+}
+
+static void inv_b(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ t = ~(RDB);
+ WRB(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 5;
+}
+
+static void inv_r(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 r;
+
+ IMMBYTE(r);
+
+ t = ~(RM(r));
+
+ WM( r, t );
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 7;
+}
+
+static void jc(tms7000_state *cpustate)
+{
+ if( pSR & SR_C )
+ {
+ INT8 s;
+
+ SIMMBYTE( s );
+ pPC += s;
+ cpustate->icount -= 7;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 5;
+ }
+}
+
+static void jeq(tms7000_state *cpustate)
+{
+ if( pSR & SR_Z )
+ {
+ INT8 s;
+
+ SIMMBYTE( s );
+ pPC += s;
+ cpustate->icount -= 7;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 5;
+ }
+}
+
+static void jl(tms7000_state *cpustate)
+{
+ if( pSR & SR_C )
+ {
+ pPC++;
+ cpustate->icount -= 5;
+ }
+ else
+ {
+ INT8 s;
+
+ SIMMBYTE( s );
+ pPC += s;
+ cpustate->icount -= 7;
+ }
+}
+
+static void jmp(tms7000_state *cpustate)
+{
+ INT8 s;
+
+ SIMMBYTE( s );
+ pPC += s;
+ cpustate->icount -= 7;
+}
+
+static void j_jn(tms7000_state *cpustate)
+{
+ if( pSR & SR_N )
+ {
+ INT8 s;
+
+ SIMMBYTE( s );
+ pPC += s;
+ cpustate->icount -= 7;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 5;
+ }
+
+}
+
+static void jne(tms7000_state *cpustate)
+{
+ if( pSR & SR_Z )
+ {
+ pPC++;
+ cpustate->icount -= 5;
+ }
+ else
+ {
+ INT8 s;
+
+ SIMMBYTE( s );
+ pPC += s;
+ cpustate->icount -= 7;
+ }
+}
+
+static void jp(tms7000_state *cpustate)
+{
+ if( pSR & (SR_Z|SR_N) )
+ {
+ pPC++;
+ cpustate->icount -= 5;
+ }
+ else
+ {
+ INT8 s;
+
+ SIMMBYTE( s );
+ pPC += s;
+ cpustate->icount -= 7;
+ }
+}
+
+static void jpz(tms7000_state *cpustate)
+{
+ if ((pSR & SR_N) == 0)
+ {
+ INT8 s;
+
+ SIMMBYTE( s );
+ pPC += s;
+ cpustate->icount -= 7;
+ }
+ else
+ {
+ pPC++;
+ cpustate->icount -= 5;
+ }
+}
+
+static void lda_dir(tms7000_state *cpustate)
+{
+ UINT16 t;
+ PAIR i;
+
+ IMMWORD( i );
+ t = RM(i.w.l);
+ WRA(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 11;
+}
+
+static void lda_ind(tms7000_state *cpustate)
+{
+ UINT16 t;
+ PAIR p;
+ INT8 i;
+
+ IMMBYTE(i);
+ p.w.l=RRF16(cpustate,i);
+ t = RM(p.w.l);
+ WRA(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 10;
+}
+
+static void lda_inx(tms7000_state *cpustate)
+{
+ UINT16 t;
+ PAIR i;
+
+ IMMWORD( i );
+ t = RM(i.w.l + RDB);
+ WRA(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 13;
+}
+
+static void ldsp(tms7000_state *cpustate)
+{
+ pSP = RDB;
+ cpustate->icount -= 5;
+}
+
+static void mov_a2b(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ t = RDA;
+ WRB(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 6;
+}
+
+static void mov_b2a(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ t = RDB;
+ WRA(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 5;
+}
+
+
+static void mov_a2r(tms7000_state *cpustate)
+{
+ UINT8 r;
+ UINT16 t;
+
+ IMMBYTE(r);
+
+ t = RDA;
+ WM(r,t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 8;
+}
+
+static void mov_b2r(tms7000_state *cpustate)
+{
+ UINT8 r;
+ UINT16 t;
+
+ IMMBYTE(r);
+
+ t = RDB;
+ WM(r,t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 7;
+}
+
+static void mov_r2a(tms7000_state *cpustate)
+{
+ UINT8 r;
+ UINT16 t;
+
+ IMMBYTE(r);
+ t = RM(r);
+ WRA(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 8;
+}
+
+static void mov_r2b(tms7000_state *cpustate)
+{
+ UINT8 r;
+ UINT16 t;
+
+ IMMBYTE(r);
+ t = RM(r);
+ WRB(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 8;
+}
+
+static void mov_r2r(tms7000_state *cpustate)
+{
+ UINT8 r,s;
+ UINT16 t;
+
+ IMMBYTE(r);
+ IMMBYTE(s);
+ t = RM(r);
+ WM(s,t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 10;
+}
+
+static void mov_i2a(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ IMMBYTE(t);
+ WRA(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 7;
+}
+
+static void mov_i2b(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ IMMBYTE(t);
+ WRB(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 7;
+}
+
+static void mov_i2r(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 r;
+
+ IMMBYTE(t);
+ IMMBYTE(r);
+ WM(r,t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 9;
+}
+
+static void movd_imm(tms7000_state *cpustate)
+{
+ PAIR t;
+ UINT8 r;
+
+ IMMWORD(t);
+ IMMBYTE(r);
+ WRF16(cpustate,r,t);
+
+ CLR_NZC;
+ SET_N8(t.b.h);
+ SET_Z8(t.b.h);
+
+ cpustate->icount -= 15;
+
+}
+
+static void movd_r(tms7000_state *cpustate)
+{
+ PAIR t;
+ UINT8 r,s;
+
+ IMMBYTE(r);
+ IMMBYTE(s);
+ t.w.l = RRF16(cpustate,r);
+ WRF16(cpustate,s,t);
+
+ CLR_NZC;
+ SET_N8(t.b.h);
+ SET_Z8(t.b.h);
+
+ cpustate->icount -= 14;
+
+}
+
+static void movd_inx(tms7000_state *cpustate)
+{
+ PAIR t;
+ UINT8 r;
+
+ IMMWORD(t);
+ t.w.l += RDB;
+ IMMBYTE(r);
+ WRF16(cpustate,r,t);
+
+ CLR_NZC;
+ SET_N8(t.b.h);
+ SET_Z8(t.b.h);
+
+ cpustate->icount -= 17;
+}
+
+static void movp_a2p(tms7000_state *cpustate)
+{
+ UINT8 p;
+ UINT16 t;
+
+ IMMBYTE(p);
+ t=RDA;
+ WM( 0x0100+p,t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 10;
+}
+
+static void movp_b2p(tms7000_state *cpustate)
+{
+ UINT8 p;
+ UINT16 t;
+
+ IMMBYTE(p);
+ t=RDB;
+ WM( 0x0100+p,t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 10;
+}
+
+#if 0
+/* this appears to be unused */
+static void movp_r2p(tms7000_state *cpustate)
+{
+ UINT8 p,r;
+ UINT16 t;
+
+ IMMBYTE(r);
+ IMMBYTE(p);
+ t=RM(r);
+ WM( 0x0100+p,t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 11;
+}
+#endif
+
+static void movp_p2a(tms7000_state *cpustate)
+{
+ UINT8 p;
+ UINT16 t;
+
+ IMMBYTE(p);
+ t=RM(0x0100+p);
+ WRA(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 9;
+}
+
+static void movp_p2b(tms7000_state *cpustate)
+{
+ UINT8 p;
+ UINT16 t;
+
+ IMMBYTE(p);
+ t=RM(0x0100+p);
+ WRB(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 8;
+}
+
+static void mpy_ba(tms7000_state *cpustate)
+{
+ PAIR t;
+
+ t.w.l = RDA * RDB;
+
+ WRF16(cpustate,0x01,t);
+
+ CLR_NZC;
+ SET_N8(t.b.h);
+ SET_Z8(t.b.h);
+
+ cpustate->icount -= 43;
+
+}
+
+static void mpy_ra(tms7000_state *cpustate)
+{
+ PAIR t;
+ UINT8 r;
+
+ IMMBYTE(r);
+
+ t.w.l = RDA * RM(r);
+
+ WRF16(cpustate,0x01,t);
+
+ CLR_NZC;
+ SET_N8(t.b.h);
+ SET_Z8(t.b.h);
+
+ cpustate->icount -= 46;
+
+}
+
+static void mpy_rb(tms7000_state *cpustate)
+{
+ PAIR t;
+ UINT8 r;
+
+ IMMBYTE(r);
+
+ t.w.l = RDB * RM(r);
+
+ WRF16(cpustate,0x01,t);
+
+ CLR_NZC;
+ SET_N8(t.b.h);
+ SET_Z8(t.b.h);
+
+ cpustate->icount -= 46;
+
+}
+
+static void mpy_rr(tms7000_state *cpustate)
+{
+ PAIR t;
+ UINT8 r,s;
+
+ IMMBYTE(r);
+ IMMBYTE(s);
+
+ t.w.l = RM(s) * RM(r);
+
+ WRF16(cpustate,0x01,t);
+
+ CLR_NZC;
+ SET_N8(t.b.h);
+ SET_Z8(t.b.h);
+
+ cpustate->icount -= 48;
+
+}
+
+static void mpy_ia(tms7000_state *cpustate)
+{
+ PAIR t;
+ UINT8 i;
+
+ IMMBYTE(i);
+
+ t.w.l = RDA * i;
+
+ WRF16(cpustate,0x01,t);
+
+ CLR_NZC;
+ SET_N8(t.b.h);
+ SET_Z8(t.b.h);
+
+ cpustate->icount -= 45;
+
+}
+
+static void mpy_ib(tms7000_state *cpustate)
+{
+ PAIR t;
+ UINT8 i;
+
+ IMMBYTE(i);
+
+ t.w.l = RDB * i;
+
+ WRF16(cpustate,0x01,t);
+
+ CLR_NZC;
+ SET_N8(t.b.h);
+ SET_Z8(t.b.h);
+
+ cpustate->icount -= 45;
+
+}
+
+static void mpy_ir(tms7000_state *cpustate)
+{
+ PAIR t;
+ UINT8 i,r;
+
+ IMMBYTE(i);
+ IMMBYTE(r);
+
+ t.w.l = RM(r) * i;
+
+ WRF16(cpustate,0x01,t);
+
+ CLR_NZC;
+ SET_N8(t.b.h);
+ SET_Z8(t.b.h);
+
+ cpustate->icount -= 47;
+
+}
+
+static void nop(tms7000_state *cpustate)
+{
+ cpustate->icount -= 4;
+}
+
+static void or_b2a(tms7000_state *cpustate)
+{
+ UINT8 t;
+
+ t = RDA | RDB;
+ WRA(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 5;
+}
+
+static void or_r2a(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+
+ t = RM(v) | RDA;
+ WRA(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 8;
+}
+
+static void or_r2b(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+
+ t = RM(v) | RDB;
+ WRB(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 8;
+}
+
+static void or_r2r(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 i,j;
+
+ IMMBYTE(i);
+ IMMBYTE(j);
+
+ t = RM(i) | RM(j);
+ WM(j,t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 10;
+}
+
+static void or_i2a(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+
+ t = v | RDA;
+ WRA(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 7;
+}
+
+static void or_i2b(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+
+ t = v | RDB;
+ WRB(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 7;
+}
+
+static void or_i2r(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 i,j;
+
+ IMMBYTE(i);
+ IMMBYTE(j);
+
+ t = i | RM(j);
+ WM(j,t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 9;
+}
+
+static void orp_a2p(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+ t = RDA | RM( 0x0100 + v);
+ WM( 0x0100+v, t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 10;
+}
+
+static void orp_b2p(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+ t = RDB | RM( 0x0100 + v);
+ WM( 0x0100+v, t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 9;
+}
+
+static void orp_i2p(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 i,v;
+
+ IMMBYTE(i);
+ IMMBYTE(v);
+ t = i | RM( 0x0100 + v);
+ WM( 0x0100+v, t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 11;
+}
+
+static void pop_a(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ PULLBYTE(t);
+ WRA(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 6;
+}
+
+static void pop_b(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ PULLBYTE(t);
+ WRB(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 6;
+}
+
+static void pop_r(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 r;
+
+ IMMBYTE(r);
+ PULLBYTE(t);
+ WM(r,t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 8;
+}
+
+static void pop_st(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ PULLBYTE(t);
+ pSR = t;
+
+ cpustate->icount -= 6;
+}
+
+static void push_a(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ t = RDA;
+ PUSHBYTE(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 6;
+}
+
+static void push_b(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ t = RDB;
+ PUSHBYTE(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 6;
+}
+
+static void push_r(tms7000_state *cpustate)
+{
+ UINT16 t;
+ INT8 r;
+
+ IMMBYTE(r);
+ t = RM(r);
+ PUSHBYTE(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 8;
+}
+
+static void push_st(tms7000_state *cpustate)
+{
+ UINT16 t;
+ t = pSR;
+ PUSHBYTE(t);
+
+ cpustate->icount -= 6;
+}
+
+static void reti(tms7000_state *cpustate)
+{
+ PULLWORD( PC );
+ PULLBYTE( pSR );
+
+ cpustate->icount -= 9;
+ tms7000_check_IRQ_lines(cpustate);
+}
+
+static void rets(tms7000_state *cpustate)
+{
+ PULLWORD( PC );
+ cpustate->icount -= 7;
+}
+
+static void rl_a(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ t = RDA << 1;
+
+ CLR_NZC;
+ SET_C8(t);
+
+ if( pSR & SR_C )
+ t |= 0x01;
+
+ SET_N8(t);
+ SET_Z8(t);
+ WRA(t);
+
+ cpustate->icount -= 5;
+}
+
+static void rl_b(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ t = RDB << 1;
+
+ CLR_NZC;
+ SET_C8(t);
+
+ if( pSR & SR_C )
+ t |= 0x01;
+
+ SET_N8(t);
+ SET_Z8(t);
+ WRB(t);
+
+ cpustate->icount -= 5;
+}
+
+static void rl_r(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 r;
+
+ IMMBYTE(r);
+ t = RM(r) << 1;
+
+ CLR_NZC;
+ SET_C8(t);
+
+ if( pSR & SR_C )
+ t |= 0x01;
+
+ SET_N8(t);
+ SET_Z8(t);
+ WM(r,t);
+
+ cpustate->icount -= 7;
+}
+
+static void rlc_a(tms7000_state *cpustate)
+{
+ UINT16 t;
+ int old_carry;
+
+ old_carry = (pSR & SR_C);
+
+ t = RDA << 1;
+
+ CLR_NZC;
+ SET_C8(t);
+
+ if( old_carry )
+ t |= 0x01;
+
+ SET_N8(t);
+ SET_Z8(t);
+ WRA(t);
+
+ cpustate->icount -= 5;
+}
+
+static void rlc_b(tms7000_state *cpustate)
+{
+ UINT16 t;
+ int old_carry;
+
+ old_carry = (pSR & SR_C);
+
+ t = RDB << 1;
+
+ CLR_NZC;
+ SET_C8(t);
+
+ if( old_carry )
+ t |= 0x01;
+
+ SET_N8(t);
+ SET_Z8(t);
+ WRB(t);
+
+ cpustate->icount -= 5;
+}
+
+static void rlc_r(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 r;
+ int old_carry;
+
+ old_carry = (pSR & SR_C);
+
+ IMMBYTE(r);
+ t = RM(r) << 1;
+
+ CLR_NZC;
+ SET_C8(t);
+
+ if( old_carry )
+ t |= 0x01;
+
+ SET_N8(t);
+ SET_Z8(t);
+ WM(r,t);
+
+ cpustate->icount -= 7;
+}
+
+static void rr_a(tms7000_state *cpustate)
+{
+ UINT16 t;
+ int old_bit0;
+
+ t = RDA;
+
+ old_bit0 = t & 0x0001;
+ t = t >> 1;
+
+ CLR_NZC;
+
+ if( old_bit0 )
+ {
+ SETC;
+ t |= 0x80;
+ }
+
+ SET_N8(t);
+ SET_Z8(t);
+
+ WRA(t);
+
+ cpustate->icount -= 5;
+}
+
+static void rr_b(tms7000_state *cpustate)
+{
+ UINT16 t;
+ int old_bit0;
+
+ t = RDB;
+
+ old_bit0 = t & 0x0001;
+ t = t >> 1;
+
+ CLR_NZC;
+
+ if( old_bit0 )
+ {
+ SETC;
+ t |= 0x80;
+ }
+
+ SET_N8(t);
+ SET_Z8(t);
+
+ WRB(t);
+
+ cpustate->icount -= 5;
+}
+
+static void rr_r(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 r;
+
+ int old_bit0;
+
+ IMMBYTE(r);
+ t = RM(r);
+
+ old_bit0 = t & 0x0001;
+ t = t >> 1;
+
+ CLR_NZC;
+
+ if( old_bit0 )
+ {
+ SETC;
+ t |= 0x80;
+ }
+
+ SET_N8(t);
+ SET_Z8(t);
+
+ WM(r,t);
+
+ cpustate->icount -= 7;
+}
+
+static void rrc_a(tms7000_state *cpustate)
+{
+ UINT16 t;
+ int old_bit0;
+
+ t = RDA;
+
+ old_bit0 = t & 0x0001;
+ /* Place carry bit in 9th position */
+ t |= ((pSR & SR_C) << 1);
+ t = t >> 1;
+
+ CLR_NZC;
+
+ if( old_bit0 )
+ SETC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ WRA(t);
+
+ cpustate->icount -= 5;
+}
+
+static void rrc_b(tms7000_state *cpustate)
+{
+ UINT16 t;
+ int old_bit0;
+
+ t = RDB;
+
+ old_bit0 = t & 0x0001;
+ /* Place carry bit in 9th position */
+ t |= ((pSR & SR_C) << 1);
+ t = t >> 1;
+
+ CLR_NZC;
+
+ if( old_bit0 )
+ SETC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ WRB(t);
+
+ cpustate->icount -= 5;
+}
+
+static void rrc_r(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 r;
+ int old_bit0;
+
+ IMMBYTE(r);
+ t = RM(r);
+
+ old_bit0 = t & 0x0001;
+ /* Place carry bit in 9th position */
+ t |= ((pSR & SR_C) << 1);
+ t = t >> 1;
+
+ CLR_NZC;
+
+ if( old_bit0 )
+ SETC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ WM(r,t);
+
+ cpustate->icount -= 7;
+}
+
+static void sbb_ba(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ t = RDA - RDB - ((pSR & SR_C) ? 0 : 1);
+ WRA(t);
+
+ CLR_NZC;
+ SET_C8(~t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 5;
+}
+
+static void sbb_ra(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 r;
+
+ IMMBYTE(r);
+ t = RDA - RM(r) - ((pSR & SR_C) ? 0 : 1);
+ WRA(t);
+
+ CLR_NZC;
+ SET_C8(~t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 8;
+}
+
+static void sbb_rb(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 r;
+
+ IMMBYTE(r);
+ t = RDB - RM(r) - ((pSR & SR_C) ? 0 : 1);
+ WRB(t);
+
+ CLR_NZC;
+ SET_C8(~t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 8;
+}
+
+static void sbb_rr(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 r,s;
+
+ IMMBYTE(s);
+ IMMBYTE(r);
+ t = RM(r) - RM(s) - ((pSR & SR_C) ? 0 : 1);
+ WM(r,t);
+
+ CLR_NZC;
+ SET_C8(~t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 10;
+}
+
+static void sbb_ia(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 i;
+
+ IMMBYTE(i);
+ t = RDA - i - ((pSR & SR_C) ? 0 : 1);
+ WRA(t);
+
+ CLR_NZC;
+ SET_C8(~t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 7;
+}
+
+static void sbb_ib(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 i;
+
+ IMMBYTE(i);
+ t = RDB - i - ((pSR & SR_C) ? 0 : 1);
+ WRB(t);
+
+ CLR_NZC;
+ SET_C8(~t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 7;
+}
+
+static void sbb_ir(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 r,i;
+
+ IMMBYTE(i);
+ IMMBYTE(r);
+ t = RM(r) - i - ((pSR & SR_C) ? 0 : 1);
+ WM(r,t);
+
+ CLR_NZC;
+ SET_C8(~t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 9;
+}
+
+static void setc(tms7000_state *cpustate)
+{
+ CLR_NZC;
+ pSR |= (SR_C|SR_Z);
+
+ cpustate->icount -= 5;
+}
+
+static void sta_dir(tms7000_state *cpustate)
+{
+ UINT16 t;
+ PAIR i;
+
+ t = RDA;
+ IMMWORD( i );
+
+ WM(i.w.l,t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 11;
+}
+
+static void sta_ind(tms7000_state *cpustate)
+{
+ UINT16 t;
+ PAIR p;
+ INT8 r;
+
+ IMMBYTE(r);
+ p.w.l = RRF16(cpustate,r);
+ t = RDA;
+ WM(p.w.l,t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 10;
+}
+
+static void sta_inx(tms7000_state *cpustate)
+{
+ UINT16 t;
+ PAIR i;
+
+ IMMWORD( i );
+ t = RDA;
+ WM(i.w.l+RDB,t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 13;
+}
+
+static void stsp(tms7000_state *cpustate)
+{
+ WRB(pSP);
+
+ cpustate->icount -= 6;
+}
+
+static void sub_ba(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ t = RDA - RDB;
+ WRA(t);
+
+ CLR_NZC;
+ SET_C8(~t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 5;
+}
+
+static void sub_ra(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 r;
+
+ IMMBYTE(r);
+ t = RDA - RM(r);
+ WRA(t);
+
+ CLR_NZC;
+ SET_C8(~t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 8;
+}
+
+static void sub_rb(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 r;
+
+ IMMBYTE(r);
+ t = RDB - RM(r);
+ WRB(t);
+
+ CLR_NZC;
+ SET_C8(~t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 8;
+}
+
+static void sub_rr(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 r,s;
+
+ IMMBYTE(s);
+ IMMBYTE(r);
+ t = RM(r) - RM(s);
+ WM(r,t);
+
+ CLR_NZC;
+ SET_C8(~t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 10;
+}
+
+static void sub_ia(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 i;
+
+ IMMBYTE(i);
+ t = RDA - i;
+ WRA(t);
+
+ CLR_NZC;
+ SET_C8(~t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 7;
+}
+
+static void sub_ib(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 i;
+
+ IMMBYTE(i);
+ t = RDB - i;
+ WRB(t);
+
+ CLR_NZC;
+ SET_C8(~t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 7;
+}
+
+static void sub_ir(tms7000_state *cpustate)
+{
+ UINT16 t;
+ UINT8 r,i;
+
+ IMMBYTE(i);
+ IMMBYTE(r);
+ t = RM(r) - i;
+ WM(r,t);
+
+ CLR_NZC;
+ SET_C8(~t);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 9;
+}
+
+static void trap_0(tms7000_state *cpustate)
+{
+ PUSHWORD( PC );
+ pPC = RM16(cpustate, 0xfffe);
+ cpustate->icount -= 14;
+}
+
+static void trap_1(tms7000_state *cpustate)
+{
+ PUSHWORD( PC );
+ pPC = RM16(cpustate, 0xfffc);
+ cpustate->icount -= 14;
+}
+
+static void trap_2(tms7000_state *cpustate)
+{
+ PUSHWORD( PC );
+ pPC = RM16(cpustate, 0xfffa);
+ cpustate->icount -= 14;
+}
+
+static void trap_3(tms7000_state *cpustate)
+{
+ PUSHWORD( PC );
+ pPC = RM16(cpustate, 0xfff8);
+ cpustate->icount -= 14;
+}
+
+static void trap_4(tms7000_state *cpustate)
+{
+ PUSHWORD( PC );
+ pPC = RM16(cpustate, 0xfff6);
+ cpustate->icount -= 14;
+}
+
+static void trap_5(tms7000_state *cpustate)
+{
+ PUSHWORD( PC );
+ pPC = RM16(cpustate, 0xfff4);
+ cpustate->icount -= 14;
+}
+
+static void trap_6(tms7000_state *cpustate)
+{
+ PUSHWORD( PC );
+ pPC = RM16(cpustate, 0xfff2);
+ cpustate->icount -= 14;
+}
+
+static void trap_7(tms7000_state *cpustate)
+{
+ PUSHWORD( PC );
+ pPC = RM16(cpustate, 0xfff0);
+ cpustate->icount -= 14;
+}
+
+static void trap_8(tms7000_state *cpustate)
+{
+ PUSHWORD( PC );
+ pPC = RM16(cpustate, 0xffee);
+ cpustate->icount -= 14;
+}
+
+static void trap_9(tms7000_state *cpustate)
+{
+ PUSHWORD( PC );
+ pPC = RM16(cpustate, 0xffec);
+ cpustate->icount -= 14;
+}
+
+static void trap_10(tms7000_state *cpustate)
+{
+ PUSHWORD( PC );
+ pPC = RM16(cpustate, 0xffea);
+ cpustate->icount -= 14;
+}
+
+static void trap_11(tms7000_state *cpustate)
+{
+ PUSHWORD( PC );
+ pPC = RM16(cpustate, 0xffe8);
+ cpustate->icount -= 14;
+}
+
+static void trap_12(tms7000_state *cpustate)
+{
+ PUSHWORD( PC );
+ pPC = RM16(cpustate, 0xffe6);
+ cpustate->icount -= 14;
+}
+
+static void trap_13(tms7000_state *cpustate)
+{
+ PUSHWORD( PC );
+ pPC = RM16(cpustate, 0xffe4);
+ cpustate->icount -= 14;
+}
+
+static void trap_14(tms7000_state *cpustate)
+{
+ PUSHWORD( PC );
+ pPC = RM16(cpustate, 0xffe2);
+ cpustate->icount -= 14;
+}
+
+static void trap_15(tms7000_state *cpustate)
+{
+ PUSHWORD( PC );
+ pPC = RM16(cpustate, 0xffe0);
+ cpustate->icount -= 14;
+}
+
+static void trap_16(tms7000_state *cpustate)
+{
+ PUSHWORD( PC );
+ pPC = RM16(cpustate, 0xffde);
+ cpustate->icount -= 14;
+}
+
+static void trap_17(tms7000_state *cpustate)
+{
+ PUSHWORD( PC );
+ pPC = RM16(cpustate, 0xffdc);
+ cpustate->icount -= 14;
+}
+
+static void trap_18(tms7000_state *cpustate)
+{
+ PUSHWORD( PC );
+ pPC = RM16(cpustate, 0xffda);
+ cpustate->icount -= 14;
+}
+
+static void trap_19(tms7000_state *cpustate)
+{
+ PUSHWORD( PC );
+ pPC = RM16(cpustate, 0xffd8);
+ cpustate->icount -= 14;
+}
+
+static void trap_20(tms7000_state *cpustate)
+{
+ PUSHWORD( PC );
+ pPC = RM16(cpustate, 0xffd6);
+ cpustate->icount -= 14;
+}
+
+static void trap_21(tms7000_state *cpustate)
+{
+ PUSHWORD( PC );
+ pPC = RM16(cpustate, 0xffd4);
+ cpustate->icount -= 14;
+}
+
+static void trap_22(tms7000_state *cpustate)
+{
+ PUSHWORD( PC );
+ pPC = RM16(cpustate, 0xffd2);
+ cpustate->icount -= 14;
+}
+
+static void trap_23(tms7000_state *cpustate)
+{
+ PUSHWORD( PC );
+ pPC = RM16(cpustate, 0xffd0);
+ cpustate->icount -= 14;
+}
+
+static void swap_a(tms7000_state *cpustate)
+{
+ UINT8 a,b;
+ UINT16 t;
+
+ a = b = RDA;
+
+ a <<= 4;
+ b >>= 4;
+ t = a+b;
+
+ WRA(t);
+
+ CLR_NZC;
+
+ pSR|=((t&0x0001)<<7);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -=8;
+}
+
+static void swap_b(tms7000_state *cpustate)
+{
+ UINT8 a,b;
+ UINT16 t;
+
+ a = b = RDB;
+
+ a <<= 4;
+ b >>= 4;
+ t = a+b;
+
+ WRB(t);
+
+ CLR_NZC;
+
+ pSR|=((t&0x0001)<<7);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -=8;
+}
+
+static void swap_r(tms7000_state *cpustate)
+{
+ UINT8 a,b,r;
+ UINT16 t;
+
+ IMMBYTE(r);
+ a = b = RM(r);
+
+ a <<= 4;
+ b >>= 4;
+ t = a+b;
+
+ WM(r,t);
+
+ CLR_NZC;
+
+ pSR|=((t&0x0001)<<7);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -=8;
+}
+
+static void swap_r_exl(tms7000_state *cpustate)
+{
+ UINT8 a,b,r;
+ UINT16 t;
+
+ IMMBYTE(r);
+
+ if (r == 0)
+ { /* opcode D7 00 (LVDP) mostly equivalent to MOVP P46,A??? (timings must
+ be different, possibly the microcode polls the state of the VDP RDY
+ line prior to doing the transfer) */
+ t=RM(0x012e);
+ WRA(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 9; /* ?????? */
+ }
+ else
+ { /* stright swap Rn instruction */
+ a = b = RM(r);
+
+ a <<= 4;
+ b >>= 4;
+ t = a+b;
+
+ WM(r,t);
+
+ CLR_NZC;
+
+ pSR|=((t&0x0001)<<7);
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -=8;
+ }
+}
+
+static void tstb(tms7000_state *cpustate)
+{
+ UINT16 t;
+
+ t=RDB;
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 6;
+}
+
+static void xchb_a(tms7000_state *cpustate)
+{
+ UINT16 t,u;
+
+ t = RDB;
+ u = RDA;
+
+ WRA(t);
+ WRB(u);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 6;
+}
+
+static void xchb_b(tms7000_state *cpustate)
+{
+ UINT16 t;
+/* UINT16 u; */
+
+ t = RDB;
+/* u = RDB; */
+
+/* WRB(t); */
+/* WRB(u); */
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 6;
+}
+
+static void xchb_r(tms7000_state *cpustate)
+{
+ UINT16 t,u;
+ UINT8 r;
+
+ IMMBYTE(r);
+
+ t = RDB;
+ u = RM(r);
+
+ WRA(t);
+ WRB(u);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 8;
+}
+
+static void xor_b2a(tms7000_state *cpustate)
+{
+ UINT8 t;
+
+ t = RDA ^ RDB;
+ WRA(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 5;
+}
+
+static void xor_r2a(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+
+ t = RM(v) ^ RDA;
+ WRA(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 8;
+}
+
+static void xor_r2b(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+
+ t = RM(v) ^ RDB;
+ WRB(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 8;
+}
+
+static void xor_r2r(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 i,j;
+
+ IMMBYTE(i);
+ IMMBYTE(j);
+
+ t = RM(i) ^ RM(j);
+ WM(j,t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 10;
+}
+
+static void xor_i2a(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+
+ t = v ^ RDA;
+ WRA(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 7;
+}
+
+static void xor_i2b(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+
+ t = v ^ RDB;
+ WRB(t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 7;
+}
+
+static void xor_i2r(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 i,j;
+
+ IMMBYTE(i);
+ IMMBYTE(j);
+
+ t = i ^ RM(j);
+ WM(j,t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 9;
+}
+
+static void xorp_a2p(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+ t = RDA ^ RM( 0x0100 + v);
+ WM( 0x0100+v, t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 10;
+}
+
+static void xorp_b2p(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 v;
+
+ IMMBYTE(v);
+ t = RDB ^ RM( 0x0100 + v);
+ WM( 0x0100+v, t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 9;
+}
+
+static void xorp_i2p(tms7000_state *cpustate)
+{
+ UINT8 t;
+ UINT8 i,v;
+
+ IMMBYTE(i);
+ IMMBYTE(v);
+ t = i ^ RM( 0x0100 + v);
+ WM( 0x0100+v, t);
+
+ CLR_NZC;
+ SET_N8(t);
+ SET_Z8(t);
+
+ cpustate->icount -= 11;
+}
diff --git a/trunk/src/emu/cpu/tms7000/tms70tb.c b/trunk/src/emu/cpu/tms7000/tms70tb.c
new file mode 100644
index 00000000000..b82bfadf54f
--- /dev/null
+++ b/trunk/src/emu/cpu/tms7000/tms70tb.c
@@ -0,0 +1,124 @@
+/*****************************************************************************
+ *
+ * tms70tb.c (function table)
+ * Portable TMS7000 emulator (Texas Instruments 7000)
+ *
+ * Copyright tim lindner, 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
+ * tlindner@macmess.org
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+
+static void (*const opfn[0x100])(tms7000_state *cpustate) = {
+/* 0xX0, 0xX1, 0xX2, 0xX3, 0xX4, 0xX5, 0xX6, 0xX7,
+ 0xX8, 0xX9, 0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF */
+
+/* 0x0X */ nop, idle, illegal, illegal, illegal, eint, dint, setc,
+ pop_st, stsp, rets, reti, illegal, ldsp, push_st, illegal,
+
+/* 0x1X */ illegal, illegal, mov_r2a, and_r2a, or_r2a, xor_r2a, btjo_r2a,btjz_r2a,
+ add_r2a, adc_r2a, sub_ra, sbb_ra, mpy_ra, cmp_ra, dac_r2a, dsb_r2a,
+
+/* 0x2X */ illegal, illegal, mov_i2a, and_i2a, or_i2a, xor_i2a, btjo_i2a,btjz_i2a,
+ add_i2a, adc_i2a, sub_ia, sbb_ia, mpy_ia, cmp_ia, dac_i2a, dsb_i2a,
+
+/* 0x3X */ illegal, illegal, mov_r2b, and_r2b, or_r2b, xor_r2b, btjo_r2b,btjz_r2b,
+ add_r2b, adc_r2b, sub_rb, sbb_rb, mpy_rb, cmp_rb, dac_r2b, dsb_r2b,
+
+/* 0x4X */ illegal, illegal, mov_r2r, and_r2r, or_r2r, xor_r2r, btjo_r2r,btjz_r2r,
+ add_r2r, adc_r2r, sub_rr, sbb_rr, mpy_rr, cmp_rr, dac_r2r, dsb_r2r,
+
+/* 0x5X */ illegal, illegal, mov_i2b, and_i2b, or_i2b, xor_i2b, btjo_i2b,btjz_i2b,
+ add_i2b, adc_i2b, sub_ib, sbb_ib, mpy_ib, cmp_ib, dac_i2b, dsb_i2b,
+
+/* 0x6X */ illegal, illegal, mov_b2a, and_b2a, or_b2a, xor_b2a, btjo_b2a,btjz_b2a,
+ add_b2a, adc_b2a, sub_ba, sbb_ba, mpy_ba, cmp_ba, dac_b2a, dsb_b2a,
+
+/* 0x7X */ illegal, illegal, mov_i2r, and_i2r, or_i2r, xor_i2r, btjo_i2r,btjz_i2r,
+ add_i2r, adc_i2r, sub_ir, sbb_ir, mpy_ir, cmp_ir, dac_i2r, dsb_i2r,
+
+/* 0x8X */ movp_p2a,illegal, movp_a2p,andp_a2p,orp_a2p, xorp_a2p,btjop_ap,btjzp_ap,
+ movd_imm,illegal, lda_dir, sta_dir, br_dir, cmpa_dir,call_dir,illegal,
+
+/* 0x9X */ illegal, movp_p2b,movp_b2p,andp_b2p,orp_b2p, xorp_b2p,btjop_bp,btjzp_bp,
+ movd_r, illegal, lda_ind, sta_ind, br_ind, cmpa_ind,call_ind,illegal,
+
+/* 0xAX */ illegal, illegal, movp_i2p,andp_i2p,orp_i2p, xorp_i2p,btjop_ip,btjzp_ip,
+ movd_inx,illegal, lda_inx, sta_inx, br_inx, cmpa_inx,call_inx,illegal,
+
+/* 0xBX */ clrc, illegal, dec_a, inc_a, inv_a, clr_a, xchb_a, swap_a,
+ push_a, pop_a, djnz_a, decd_a, rr_a, rrc_a, rl_a, rlc_a,
+
+/* 0xCX */ mov_a2b, tstb, dec_b, inc_b, inv_b, clr_b, xchb_b, swap_b,
+ push_b, pop_b, djnz_b, decd_b, rr_b, rrc_b, rl_b, rlc_b,
+
+/* 0xDX */ mov_a2r, mov_b2r, dec_r, inc_r, inv_r, clr_r, xchb_r, swap_r,
+ push_r, pop_r, djnz_r, decd_r, rr_r, rrc_r, rl_r, rlc_r,
+
+/* 0xEX */ jmp, j_jn, jeq, jc, jp, jpz, jne, jl,
+ trap_23, trap_22, trap_21, trap_20, trap_19, trap_18, trap_17, trap_16,
+
+/* 0xFX */ trap_15, trap_14, trap_13, trap_12, trap_11, trap_10, trap_9, trap_8,
+ trap_7, trap_6, trap_5, trap_4, trap_3, trap_2, trap_1, trap_0
+};
+
+static void (*const opfn_exl[0x100])(tms7000_state *cpustate) = {
+/* 0xX0, 0xX1, 0xX2, 0xX3, 0xX4, 0xX5, 0xX6, 0xX7,
+ 0xX8, 0xX9, 0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF */
+
+/* 0x0X */ nop, idle, illegal, illegal, illegal, eint, dint, setc,
+ pop_st, stsp, rets, reti, illegal, ldsp, push_st, illegal,
+
+/* 0x1X */ illegal, illegal, mov_r2a, and_r2a, or_r2a, xor_r2a, btjo_r2a,btjz_r2a,
+ add_r2a, adc_r2a, sub_ra, sbb_ra, mpy_ra, cmp_ra, dac_r2a, dsb_r2a,
+
+/* 0x2X */ illegal, illegal, mov_i2a, and_i2a, or_i2a, xor_i2a, btjo_i2a,btjz_i2a,
+ add_i2a, adc_i2a, sub_ia, sbb_ia, mpy_ia, cmp_ia, dac_i2a, dsb_i2a,
+
+/* 0x3X */ illegal, illegal, mov_r2b, and_r2b, or_r2b, xor_r2b, btjo_r2b,btjz_r2b,
+ add_r2b, adc_r2b, sub_rb, sbb_rb, mpy_rb, cmp_rb, dac_r2b, dsb_r2b,
+
+/* 0x4X */ illegal, illegal, mov_r2r, and_r2r, or_r2r, xor_r2r, btjo_r2r,btjz_r2r,
+ add_r2r, adc_r2r, sub_rr, sbb_rr, mpy_rr, cmp_rr, dac_r2r, dsb_r2r,
+
+/* 0x5X */ illegal, illegal, mov_i2b, and_i2b, or_i2b, xor_i2b, btjo_i2b,btjz_i2b,
+ add_i2b, adc_i2b, sub_ib, sbb_ib, mpy_ib, cmp_ib, dac_i2b, dsb_i2b,
+
+/* 0x6X */ illegal, illegal, mov_b2a, and_b2a, or_b2a, xor_b2a, btjo_b2a,btjz_b2a,
+ add_b2a, adc_b2a, sub_ba, sbb_ba, mpy_ba, cmp_ba, dac_b2a, dsb_b2a,
+
+/* 0x7X */ illegal, illegal, mov_i2r, and_i2r, or_i2r, xor_i2r, btjo_i2r,btjz_i2r,
+ add_i2r, adc_i2r, sub_ir, sbb_ir, mpy_ir, cmp_ir, dac_i2r, dsb_i2r,
+
+/* 0x8X */ movp_p2a,illegal, movp_a2p,andp_a2p,orp_a2p, xorp_a2p,btjop_ap,btjzp_ap,
+ movd_imm,illegal, lda_dir, sta_dir, br_dir, cmpa_dir,call_dir,illegal,
+
+/* 0x9X */ illegal, movp_p2b,movp_b2p,andp_b2p,orp_b2p, xorp_b2p,btjop_bp,btjzp_bp,
+ movd_r, illegal, lda_ind, sta_ind, br_ind, cmpa_ind,call_ind,illegal,
+
+/* 0xAX */ illegal, illegal, movp_i2p,andp_i2p,orp_i2p, xorp_i2p,btjop_ip,btjzp_ip,
+ movd_inx,illegal, lda_inx, sta_inx, br_inx, cmpa_inx,call_inx,illegal,
+
+/* 0xBX */ clrc, illegal, dec_a, inc_a, inv_a, clr_a, xchb_a, swap_a,
+ push_a, pop_a, djnz_a, decd_a, rr_a, rrc_a, rl_a, rlc_a,
+
+/* 0xCX */ mov_a2b, tstb, dec_b, inc_b, inv_b, clr_b, xchb_b, swap_b,
+ push_b, pop_b, djnz_b, decd_b, rr_b, rrc_b, rl_b, rlc_b,
+
+/* 0xDX */ mov_a2r, mov_b2r, dec_r, inc_r, inv_r, clr_r, xchb_r, swap_r_exl,
+ push_r, pop_r, djnz_r, decd_r, rr_r, rrc_r, rl_r, rlc_r,
+
+/* 0xEX */ jmp, j_jn, jeq, jc, jp, jpz, jne, jl,
+ trap_23, trap_22, trap_21, trap_20, trap_19, trap_18, trap_17, trap_16,
+
+/* 0xFX */ trap_15, trap_14, trap_13, trap_12, trap_11, trap_10, trap_9, trap_8,
+ trap_7, trap_6, trap_5, trap_4, trap_3, trap_2, trap_1, trap_0
+};
diff --git a/trunk/src/emu/cpu/tms9900/9900dasm.c b/trunk/src/emu/cpu/tms9900/9900dasm.c
new file mode 100644
index 00000000000..045d6431209
--- /dev/null
+++ b/trunk/src/emu/cpu/tms9900/9900dasm.c
@@ -0,0 +1,799 @@
+/*****************************************************************************
+ *
+ * 9900dasm.c
+ * TMS 9900 family disassembler
+ *
+ * Copyright Raphael Nabet
+ * Based on previous work Copyright John Butler.
+ * Based on 6502dasm.c 6502/65c02/6510 disassembler by Juergen Buchmueller
+ *
+ * - 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. :)
+ * - 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 "tms9900.h"
+
+#define MASK 0x0000ffff
+#define BITS(val,n1,n2) ((val>>(15-(n2))) & (MASK>>(15-((n2)-(n1)))))
+
+typedef enum
+{
+ format_1, /* 2 address instructions */
+ format_2a, /* jump instructions */
+ format_2b, /* bit I/O instructions */
+ format_3_9, /* logical, multiply, and divide instructions */
+ format_4, /* CRU instructions */
+ format_5, /* register shift instructions */
+ format_6, /* single address instructions */
+ format_7, /* instructions without operands */
+ format_8a, /* immediate instructions (destination register) */
+ format_8b, /* immediate instructions (no destination register) */
+ format_9, /* extended operation instruction */
+ format_10, /* memory map file instruction */
+ format_11, /* multiple precision instructions */
+ format_12, /* string instructions */
+ format_13, /* multiple precision shift instructions */
+ format_14, /* bit testing instructions */
+ format_15, /* invert order of field instruction */
+ format_16, /* field instructions */
+ format_17, /* alter register and jump instructions */
+ format_18, /* single register operand instructions */
+ format_liim,/* format for liim (looks like format 18) */
+ format_19, /* move address instruction */
+ format_20, /* list search instructions */
+ format_21, /* extend precision instruction */
+
+ illegal
+} format_t;
+
+/* definitions for flags */
+enum
+{
+ /* processor set on which opcodes are available */
+ ps_any = 0x01, /* every processor in the tms9900/ti990 family */
+ ps_mapper = 0x02, /* processors with memory mapper (ti990/10, ti990/12,
+ and tms99000 with mapper coprocessor) */
+ ps_tms9995 = 0x04, /* ti990/12, tms9995, and later */
+ ps_tms99000 = 0x08, /* ti990/12, tms99000, and later */
+ ps_ti990_12 = 0x10, /* ti990/12 only */
+
+ /* additional flags for special decoding */
+ sd_11 = 0x100, /* bit 11 should be cleared in li, ai, andi, ori, ci, stwp, stst */
+ sd_11_15 = 0x200 /* bits 11-15 should be cleared in lwpi, limi, idle, rset, rtwp, ckon, ckof, lrex */
+};
+
+typedef struct description_t
+{
+ const char *mnemonic;
+ format_t format;
+ int flags;
+} description_t;
+
+
+enum opcodes {
+ /* basic instruction set */
+ _a=0, _ab, _c, _cb, _s, _sb, _soc, _socb, _szc, _szcb,
+ _mov, _movb, _coc, _czc, _xor, _mpy, _div, _xop, _b, _bl,
+ _blwp, _clr, _seto, _inv, _neg, _abs, _swpb, _inc, _inct, _dec,
+ _dect, _x, _ldcr, _stcr, _sbo, _sbz, _tb, _jeq, _jgt, _jh,
+ _jhe, _jl, _jle, _jlt, _jmp, _jnc, _jne, _jno, _joc, _jop,
+ _sla, _sra, _src, _srl, _ai, _andi, _ci, _li, _ori, _lwpi,
+ _limi, _stst, _stwp, _rtwp, _idle, _rset, _ckof, _ckon, _lrex,
+
+ /* mapper instruction set */
+ _lds, _ldd, _lmf,
+
+ /* tms9995 instruction set */
+ _divs, _mpys, _lst, _lwp,
+
+ /* tms99000 instruction set */
+ _bind,
+
+ /* ti990/12 instruction set */
+ _sram, _slam, _rto, _lto, _cnto, _slsl, _slsp, _bdc, _dbc, _swpm,
+ _xorm, _orm, _andm, _sm, _am, _mova, _emd, _eint, _dint, _stpc,
+ _cs, _seqb, _movs, _lim, _lcs, _blsk, _mvsr, _mvsk, _pops, _pshs,
+
+ _cri, _cdi, _negr, _negd, _cre, _cde, _cer, _ced, _nrm, _tmb,
+ _tcmb, _tsmb, _srj, _arj, _xit, _insf, _xv, _xf, _ar, _cir,
+ _sr, _mr, _dr, _lr, _str, _iof, _sneb, _crc, _ts, _ad,
+ _cid, _sd, _md, _dd, _ld, _std, _ep,
+
+ /* tms9940-only instruction set */
+ _liim, _dca, _dcs,
+
+ _ill
+};
+
+
+static const description_t descriptions[144+3+1] =
+{
+ /* basic instruction set */
+ { "a", format_1, ps_any }, { "ab", format_1, ps_any },
+ { "c", format_1, ps_any }, { "cb", format_1, ps_any },
+ { "s", format_1, ps_any }, { "sb", format_1, ps_any },
+ { "soc", format_1, ps_any }, { "socb", format_1, ps_any },
+ { "szc", format_1, ps_any }, { "szcb", format_1, ps_any },
+ { "mov", format_1, ps_any }, { "movb", format_1, ps_any },
+ { "coc", format_3_9, ps_any }, { "czc", format_3_9, ps_any },
+ { "xor", format_3_9, ps_any }, { "mpy", format_3_9, ps_any },
+ { "div", format_3_9, ps_any }, { "xop", format_9, ps_any },
+ { "b", format_6, ps_any }, { "bl", format_6, ps_any },
+ { "blwp", format_6, ps_any }, { "clr", format_6, ps_any },
+ { "seto", format_6, ps_any }, { "inv", format_6, ps_any },
+ { "neg", format_6, ps_any }, { "abs", format_6, ps_any },
+ { "swpb", format_6, ps_any }, { "inc", format_6, ps_any },
+ { "inct", format_6, ps_any }, { "dec", format_6, ps_any },
+ { "dect", format_6, ps_any }, { "x", format_6, ps_any },
+ { "ldcr", format_4, ps_any }, { "stcr", format_4, ps_any },
+ { "sbo", format_2b, ps_any }, { "sbz", format_2b, ps_any },
+ { "tb", format_2b, ps_any }, { "jeq", format_2a, ps_any },
+ { "jgt", format_2a, ps_any }, { "jh", format_2a, ps_any },
+ { "jhe", format_2a, ps_any }, { "jl", format_2a, ps_any },
+ { "jle", format_2a, ps_any }, { "jlt", format_2a, ps_any },
+ { "jmp", format_2a, ps_any }, { "jnc", format_2a, ps_any },
+ { "jne", format_2a, ps_any }, { "jno", format_2a, ps_any },
+ { "joc", format_2a, ps_any }, { "jop", format_2a, ps_any },
+ { "sla", format_5, ps_any }, { "sra", format_5, ps_any },
+ { "src", format_5, ps_any }, { "srl", format_5, ps_any },
+ { "ai", format_8a, ps_any|sd_11 }, { "andi", format_8a, ps_any|sd_11 },
+ { "ci", format_8a, ps_any|sd_11 }, { "li", format_8a, ps_any|sd_11 },
+ { "ori", format_8a, ps_any|sd_11 }, { "lwpi", format_8b, ps_any|sd_11|sd_11_15 },
+ { "limi", format_8b, ps_any|sd_11|sd_11_15 }, { "stst", format_18, ps_any|sd_11 },
+ { "stwp", format_18, ps_any|sd_11 }, { "rtwp", format_7, ps_any|sd_11|sd_11_15 },
+ { "idle", format_7, ps_any|sd_11|sd_11_15 }, { "rset", format_7, ps_any|sd_11|sd_11_15 },
+ { "ckof", format_7, ps_any|sd_11|sd_11_15 }, { "ckon", format_7, ps_any|sd_11|sd_11_15 },
+ { "lrex", format_7, ps_any|sd_11|sd_11_15 },
+
+ /* mapper instruction set */
+ { "lds", format_6, ps_mapper }, { "ldd", format_6, ps_mapper },
+ { "lmf", format_10, ps_mapper },
+
+ /* tms9995 instruction set */
+ { "divs", format_6, ps_tms9995 }, { "mpys", format_6, ps_tms9995 },
+ { "lst", format_18, ps_tms9995 }, { "lwp", format_18, ps_tms9995 },
+
+ /* tms99000 instruction set */
+ { "bind", format_6, ps_tms99000 },
+
+ /* ti990/12 instruction set */
+ { "sram", format_13, ps_ti990_12 }, { "slam", format_13, ps_ti990_12 },
+ { "rto", format_11, ps_ti990_12 }, { "lto", format_11, ps_ti990_12 },
+ { "cnto", format_11, ps_ti990_12 }, { "slsl", format_20, ps_ti990_12 },
+ { "slsp", format_20, ps_ti990_12 }, { "bdc", format_11, ps_ti990_12 },
+ { "dbc", format_11, ps_ti990_12 }, { "swpm", format_11, ps_ti990_12 },
+ { "xorm", format_11, ps_ti990_12 }, { "orm", format_11, ps_ti990_12 },
+ { "andm", format_11, ps_ti990_12 }, { "sm", format_11, ps_ti990_12 },
+ { "am", format_11, ps_ti990_12 }, { "mova", format_19, ps_ti990_12 },
+ { "emd", format_7, ps_ti990_12 }, { "eint", format_7, ps_ti990_12 },
+ { "dint", format_7, ps_ti990_12 }, { "stpc", format_18, ps_ti990_12 },
+ { "cs", format_12, ps_ti990_12 }, { "seqb", format_12, ps_ti990_12 },
+ { "movs", format_12, ps_ti990_12 }, { "lim", format_18, ps_ti990_12 },
+ { "lcs", format_18, ps_ti990_12 }, { "blsk", format_8a, ps_ti990_12 },
+ { "mvsr", format_12, ps_ti990_12 }, { "mvsk", format_12, ps_ti990_12 },
+ { "pops", format_12, ps_ti990_12 }, { "pshs", format_12, ps_ti990_12 },
+ { "cri", format_7, ps_ti990_12 }, { "cdi", format_7, ps_ti990_12 },
+ { "negr", format_7, ps_ti990_12 }, { "negd", format_7, ps_ti990_12 },
+ { "cre", format_7, ps_ti990_12 }, { "cde", format_7, ps_ti990_12 },
+ { "cer", format_7, ps_ti990_12 }, { "ced", format_7, ps_ti990_12 },
+ { "nrm", format_11, ps_ti990_12 }, { "tmb", format_14, ps_ti990_12 },
+ { "tcmb", format_14, ps_ti990_12 }, { "tsmb", format_14, ps_ti990_12 },
+ { "srj", format_17, ps_ti990_12 }, { "arj", format_17, ps_ti990_12 },
+ { "xit", format_7, ps_ti990_12 }, { "insf", format_16, ps_ti990_12 },
+ { "xv", format_16, ps_ti990_12 }, { "xf", format_16, ps_ti990_12 },
+ { "ar", format_6, ps_ti990_12 }, { "cir", format_6, ps_ti990_12 },
+ { "sr", format_6, ps_ti990_12 }, { "mr", format_6, ps_ti990_12 },
+ { "dr", format_6, ps_ti990_12 }, { "lr", format_6, ps_ti990_12 },
+ { "str", format_6, ps_ti990_12 }, { "iof", format_15, ps_ti990_12 },
+ { "sneb", format_12, ps_ti990_12 }, { "crc", format_12, ps_ti990_12 },
+ { "ts", format_12, ps_ti990_12 }, { "ad", format_6, ps_ti990_12 },
+ { "cid", format_6, ps_ti990_12 }, { "sd", format_6, ps_ti990_12 },
+ { "md", format_6, ps_ti990_12 }, { "dd", format_6, ps_ti990_12 },
+ { "ld", format_6, ps_ti990_12 }, { "std", format_6, ps_ti990_12 },
+ { "ep", format_21, ps_ti990_12 },
+
+ /* tms9940-only instruction set */
+ /* these instructions are said to be format 9 (xop), but since the xop
+ level is interpreted as part of the opcode, dca and dcs should be handled
+ like format 6. liim looks like format 18, but slightly different,
+ therefore it is handled like a special format. */
+ { "liim", format_liim,/*ps_tms9940*/0 }, { "dca", format_6, /*ps_tms9940*/0 },
+ { "dcs", format_6, /*ps_tms9940*/0 },
+
+ { NULL, illegal, ps_any }
+};
+
+
+static const enum opcodes ops_4000_ffff_s12[12]=
+{
+ _szc, _szcb, _s, _sb, /*4000-7000*/
+ _c, _cb, _a, _ab, _mov, _movb, _soc, _socb /*8000-f000*/
+};
+
+
+static const enum opcodes ops_2000_3fff_s10[8]=
+{
+ _coc, _czc, _xor, _xop, _ldcr, _stcr, _mpy, _div /*2000-3800*/
+};
+
+
+static const enum opcodes ops_1000_1fff_s8[16]=
+{
+ _jmp, _jlt, _jle, _jeq, _jhe, _jgt, _jne, _jnc, /*1000-1700*/
+ _joc, _jno, _jl, _jh, _jop, _sbo, _sbz, _tb /*1800-1f00*/
+};
+
+
+static const enum opcodes ops_0e40_0fff_s6[7]=
+{
+ _ad, _cid, _sd, _md, _dd, _ld, _std /*0e40-0fc0*/
+};
+
+
+static const enum opcodes ops_0e00_0e3f_s4[4]=
+{
+ _iof, _sneb, _crc, _ts /*0e00-0e30*/
+};
+
+
+static const enum opcodes ops_0c40_0dff_s6[7]=
+{
+ _ar, _cir, _sr, _mr, _dr, _lr, _str /*0c40-0dc0*/
+};
+
+
+static const enum opcodes ops_0c10_0c3f_s4[3]=
+{
+ _insf, _xv, _xf /*0c10-0c30*/
+};
+
+
+static const enum opcodes ops_0c00_0c0f_s0[16]=
+{
+ _cri, _cdi, _negr, _negd, _cre, _cde, _cer, _ced, /*0c00-0c07*/
+ _nrm, _tmb, _tcmb, _tsmb, _srj, _arj, _xit, _xit /*0c08-0c0f*/
+};
+
+
+
+static const enum opcodes ops_0800_0bff_s8[4]=
+{
+ _sra, _srl, _sla, _src /*0800-0b00*/
+};
+
+
+static const enum opcodes ops_0400_07ff_s6[16]=
+{
+ _blwp, _b, _x, _clr, _neg, _inv, _inc, _inct, /*0400-05c0*/
+ _dec, _dect, _bl, _swpb, _seto, _abs, _lds, _ldd /*0600-07c0*/
+};
+
+
+static const enum opcodes ops_0200_03ff_s5[16]=
+{
+ _li, _ai, _andi, _ori, _ci, _stwp, _stst, _lwpi, /*0200-02e0*/
+ _limi, _lmf, _idle, _rset, _rtwp, _ckon, _ckof, _lrex /*0300-03e0*/
+};
+
+
+static const enum opcodes ops_0100_01ff_s6[4]=
+{
+ _ill, _bind, _divs, _mpys /*0100-01c0*/
+};
+
+
+static const enum opcodes ops_0030_00ff_s4[13]=
+{
+ _stpc, _cs, _seqb, _movs, _lim, /*0030-0070*/
+ _lst, _lwp, _lcs, _blsk, _mvsr, _mvsk, _pops, _pshs /*0080-00f0*/
+};
+
+
+static const enum opcodes ops_001c_002f_s0[20]=
+{
+ _sram, _slam, _rto, _lto, /*001c-001f*/
+ _cnto, _slsl, _slsp, _bdc, _dbc, _swpm, _xorm, _orm, /*0020-0027*/
+ _andm, _sm, _am, _mova, _ill, _emd, _eint, _dint /*0028-002f*/
+};
+
+
+
+static int PC;
+
+
+INLINE UINT16 readop_arg(const UINT8 *opram, unsigned pc)
+{
+ UINT16 result = opram[PC++ - pc] << 8;
+ return result | opram[PC++ - pc];
+}
+
+static int print_arg (char *dest, int mode, int arg, const UINT8 *opram, unsigned pc)
+{
+ int base;
+
+ switch (mode)
+ {
+ case 0x0: /* workspace register */
+ return sprintf (dest, "R%d", arg);
+ case 0x1: /* workspace register indirect */
+ return sprintf (dest, "*R%d", arg);
+ case 0x2: /* symbolic|indexed */
+ base = readop_arg(opram, pc);
+ if (arg) /* indexed */
+ return sprintf (dest, "@>%04x(R%d)", base, arg);
+ else /* symbolic (direct) */
+ return sprintf (dest, "@>%04x", base);
+ break;
+ case 0x3: /* workspace register indirect auto increment */
+ return sprintf (dest, "*R%d+", arg);
+ }
+
+ return 0;
+}
+
+
+/*****************************************************************************
+ * Disassemble a single command and return the number of bytes it uses.
+ *****************************************************************************/
+unsigned Dasm9900 (char *buffer, unsigned pc, int model_id, const UINT8 *oprom, const UINT8 *opram)
+{
+ int OP, OP2, opc;
+ int sarg, darg, smode, dmode;
+ signed char displacement;
+ int byte_count, checkpoint;
+ int bit_position, bit_width;
+ unsigned dasmflags = 0;
+
+ const char *mnemonic;
+ format_t format;
+ int flags;
+
+ /*
+ Under tms9900, opcodes >0400->07FF are incompletely decoded: bits 11 is ignored, and so are
+ bits 12-15 for instructions which do not require a register. On the other hand, ti990/10
+ generates an illegal instruction error when bit 11 is set, but still ignores bits 12-15.
+ Additionally, ti990/12 and tms9995 will generate an illegal error when bits 12-15 are
+ non-zero.
+ */
+ #define BETTER_0200_DECODING (model_id == TI990_10_ID)
+ #define COMPLETE_0200_DECODING (/*(model_id == TI990_12_ID) ||*/ (model_id >= TMS9995_ID))
+
+ int processor_mask = ps_any;
+
+ if ((model_id == TI990_10_ID) /*|| (model_id == TI990_12_ID)*/ || (model_id >= TMS99000_ID))
+ processor_mask |= ps_mapper; /* processors with memory mapper (ti990/10, ti990/12,
+ and tms99000 with mapper coprocessor) */
+ if (/*(model_id == TI990_12_ID) ||*/ (model_id >= TMS9995_ID))
+ processor_mask |= ps_tms9995; /* ti990/12, tms9995, and later */
+
+ if (/*(model_id == TI990_12_ID) ||*/ (model_id >= TMS99000_ID))
+ processor_mask |= ps_tms99000; /* ti990/12, tms99000, and later */
+
+ /*if ((model_id == TI990_12_ID))
+ processor_mask |= ps_ti990_12;*/ /* ti990/12, tms99000, and later */
+
+ PC = pc;
+ OP = oprom[PC++ - pc] << 8;
+ OP |= oprom[PC++ - pc];
+
+ /* let's identify the opcode */
+ if (OP >= 0x4000)
+ opc = ops_4000_ffff_s12[(OP - 0x4000) >> 12];
+ else if (OP >= 0x2000)
+ opc = ops_2000_3fff_s10[(OP - 0x2000) >> 10];
+ else if (OP >= 0x1000)
+ opc = ops_1000_1fff_s8[(OP - 0x1000) >> 8];
+ else if (OP >= 0x0C00)
+ {
+ if (OP >= 0x0E40)
+ opc = ops_0e40_0fff_s6[(OP - 0x0E40) >> 6];
+ else if (OP >= 0x0E00)
+ opc = ops_0e00_0e3f_s4[(OP - 0x0E00) >> 4];
+ else if (OP >= 0x0C40)
+ opc = ops_0c40_0dff_s6[(OP - 0x0C40) >> 6];
+ else if (OP >= 0x0C10)
+ opc = ops_0c10_0c3f_s4[(OP - 0x0C10) >> 4];
+ else
+ opc = ops_0c00_0c0f_s0[OP - 0x0C00];
+ }
+ else if (OP >= 0x0800)
+ opc = ops_0800_0bff_s8[(OP - 0x0800) >> 8];
+ else if (OP >= 0x0400)
+ opc = ops_0400_07ff_s6[(OP - 0x0400) >> 6];
+ else if (OP >= 0x0200)
+ {
+ opc = ops_0200_03ff_s5[(OP - 0x0200) >> 5];
+ if (BETTER_0200_DECODING || COMPLETE_0200_DECODING)
+ {
+ flags = descriptions[opc].flags;
+ if ( (COMPLETE_0200_DECODING && (flags & sd_11_15) && (OP & 0x001f))
+ || ((flags & sd_11) && (OP & 0x0010)) )
+ {
+ opc = _ill;
+ if (OP >= 0x03f0)
+ opc = _ep; /* the ep opcode is located in a "hole" */
+ }
+ }
+ }
+ else if (OP >= 0x0100)
+ opc = ops_0100_01ff_s6[(OP - 0x0100) >> 6];
+ else if (OP >= 0x0030)
+ opc = ops_0030_00ff_s4[(OP - 0x0030) >> 4];
+ else if (OP >= 0x001C)
+ opc = ops_001c_002f_s0[OP - 0x001C];
+ else
+ opc = _ill;
+
+ /* read flags */
+ flags = descriptions[opc].flags;
+ /* set as illegal if the processor does not implement this instruction */
+ if (! (flags & processor_mask))
+ {
+ opc = _ill;
+ flags = descriptions[opc].flags; /* read new flags */
+ }
+
+ /* tms9940 replace a few xops with custom instructions */
+ if ((opc == _xop) && ((model_id == TMS9940_ID) || (model_id == TMS9985_ID)))
+ {
+ switch (BITS(OP,6,9))
+ {
+ case 0:
+ /* opcode is dca */
+ opc = _dca;
+ break;
+
+ case 1:
+ /* opcode is dcs */
+ opc = _dcs;
+ break;
+
+ case 2:
+ case 3: /* should be 2, but instruction decoding is incomplete */
+ /* opcode is liim */
+ if (BITS(OP,12,15) == 0)
+ /* ts must be == 0 */
+ opc = _liim;
+ else
+ /* I don't know what happens when ts != 0. Maybe the CPU does
+ the complete address decoding, and liim gets a bogus value
+ instead of the immediate. Since I do not know, I handle this
+ as an illegal instruction. */
+ opc = _ill;
+ break;
+
+ default:
+ /* this is still a software xop */
+ break;
+ }
+ }
+
+ mnemonic = descriptions[opc].mnemonic;
+ format = descriptions[opc].format;
+
+ /* bl and blwp instructions are subroutines */
+ if (mnemonic != NULL && mnemonic[0] == 'b' && mnemonic[1] == 'l')
+ dasmflags = DASMFLAG_STEP_OVER;
+
+ /* b *r11 and rtwp are returns */
+ else if (opc == 0x045b || (mnemonic != NULL && strcmp(mnemonic, "rtwp") == 0))
+ dasmflags = DASMFLAG_STEP_OUT;
+
+ switch (format)
+ {
+ case format_1: /* 2 address instructions */
+ smode = BITS(OP,10,11);
+ sarg = BITS(OP,12,15);
+ dmode = BITS(OP,4,5);
+ darg = BITS(OP,6,9);
+
+ buffer += sprintf (buffer, "%-4s ", mnemonic);
+ buffer += print_arg (buffer, smode, sarg, opram, pc);
+ buffer += sprintf (buffer, ",");
+ buffer += print_arg (buffer, dmode, darg, opram, pc);
+ break;
+
+ case format_2a: /* jump instructions */
+ displacement = (signed char)BITS(OP,8,15);
+ sprintf (buffer, "%-4s >%04x", mnemonic, 0xffff & (PC + displacement * 2));
+ break;
+
+ case format_2b: /* bit I/O instructions */
+ displacement = (signed char)BITS(OP,8,15);
+ sprintf (buffer, "%-4s >%04x", mnemonic, 0xffff & displacement);
+ break;
+
+ case format_3_9: /* logical, multiply, and divide instructions */
+ case format_4: /* CRU instructions */
+ case format_9: /* extended operation instruction */
+ smode = BITS(OP,10,11);
+ sarg = BITS(OP,12,15);
+ darg = BITS(OP,6,9);
+
+ if ((darg == 0) && (format == format_4))
+ darg = 16;
+
+ if (format == format_3_9)
+ {
+ buffer += sprintf (buffer, "%-4s ", mnemonic);
+ buffer += print_arg (buffer, smode, sarg, opram, pc);
+ buffer += sprintf (buffer, ",R%d", darg);
+ }
+ else
+ {
+ buffer += sprintf (buffer, "%-4s ", mnemonic);
+ buffer += print_arg (buffer, smode, sarg, opram, pc);
+ buffer += sprintf (buffer, ",%d", darg);
+ }
+ break;
+
+ case format_5: /* register shift instructions */
+ sarg = BITS(OP,12,15);
+ darg = BITS(OP,8,11);
+
+ sprintf (buffer, darg ? "%-4s R%d,%d" : "%-4s R%d,R%d", mnemonic, sarg, darg);
+ break;
+
+ case format_6: /* single address instructions */
+ smode = BITS(OP,10,11);
+ sarg = BITS(OP,12,15);
+
+ buffer += sprintf (buffer, "%-4s ", mnemonic);
+ buffer += print_arg (buffer, smode, sarg, opram, pc);
+ break;
+
+ case format_7: /* instructions without operands */
+ sprintf (buffer, "%s", mnemonic);
+ break;
+
+ case format_8a: /* immediate instructions (destination register) */
+ darg = BITS(OP,12,15);
+ sarg = readop_arg(opram, pc);
+
+ sprintf (buffer, "%-4s R%d,>%04x", mnemonic, darg, sarg);
+ break;
+
+ case format_8b: /* immediate instructions (no destination register) */
+ sarg = readop_arg(opram, pc);
+
+ sprintf (buffer, "%-4s >%04x", mnemonic, sarg);
+ break;
+
+ case format_10: /* memory map file instruction */
+ sarg = BITS(OP,12,15);
+ darg = BITS(OP,11,11);
+
+ sprintf (buffer, "%-4s R%d,%d", mnemonic, sarg, darg);
+ break;
+
+ case format_11: /* multiple precision instructions */
+ OP2 = readop_arg(opram, pc);
+
+ smode = BITS(OP2,10,11);
+ sarg = BITS(OP2,12,15);
+ dmode = BITS(OP2,4,5);
+ darg = BITS(OP2,6,9);
+ byte_count = BITS(OP2,0,3);
+
+ buffer += sprintf (buffer, "%-4s ", mnemonic);
+ buffer += print_arg (buffer, smode, sarg, opram, pc);
+ buffer += sprintf (buffer, ",");
+ buffer += print_arg (buffer, dmode, darg, opram, pc);
+ buffer += sprintf (buffer, byte_count ? ",%d" : ",R%d", byte_count);
+ break;
+
+ case format_12: /* string instructions */
+ OP2 = readop_arg(opram, pc);
+
+ smode = BITS(OP2,10,11);
+ sarg = BITS(OP2,12,15);
+ dmode = BITS(OP2,4,5);
+ darg = BITS(OP2,6,9);
+ byte_count = BITS(OP2,0,3);
+ checkpoint = BITS(OP,12,15);
+
+ buffer += sprintf (buffer, "%-4s ", mnemonic);
+ buffer += print_arg (buffer, smode, sarg, opram, pc);
+ buffer += sprintf (buffer, ",");
+ buffer += print_arg (buffer, dmode, darg, opram, pc);
+ buffer += sprintf (buffer, byte_count ? ",%d,R%d" : ",R%d,R%d", byte_count, checkpoint);
+ break;
+
+ case format_13: /* multiple precision shift instructions */
+ OP2 = readop_arg(opram, pc);
+
+ smode = BITS(OP2,10,11);
+ sarg = BITS(OP2,12,15);
+ darg = BITS(OP2,6,9);
+ byte_count = BITS(OP2,0,3);
+
+ buffer += sprintf (buffer, "%-4s ", mnemonic);
+ buffer += print_arg (buffer, smode, sarg, opram, pc);
+ buffer += sprintf (buffer, byte_count ? ",%d" : ",R%d", byte_count);
+ buffer += sprintf (buffer, darg ? ",%d" : ",R%d", darg);
+ break;
+
+ case format_14: /* bit testing instructions */
+ OP2 = readop_arg(opram, pc);
+
+ smode = BITS(OP2,10,11);
+ sarg = BITS(OP2,12,15);
+ darg = BITS(OP2,0,9);
+
+ buffer += sprintf (buffer, "%-4s ", mnemonic);
+ buffer += print_arg (buffer, smode, sarg, opram, pc);
+ if (darg == 0x3ff)
+ buffer += sprintf (buffer, ",R0");
+ else
+ buffer += sprintf (buffer, ",%d", darg);
+ break;
+
+ case format_15: /* invert order of field instruction */
+ OP2 = readop_arg(opram, pc);
+
+ smode = BITS(OP2,10,11);
+ sarg = BITS(OP2,12,15);
+ bit_position = BITS(OP2,0,3);
+ bit_width = BITS(OP,12,15);
+
+ buffer += sprintf (buffer, "%-4s ", mnemonic);
+ buffer += print_arg (buffer, smode, sarg, opram, pc);
+ buffer += sprintf (buffer, bit_position ? ",(%d," : ",(R%d,", bit_position);
+ buffer += sprintf (buffer, bit_width ? "%d)" : "R%d)", bit_width);
+ break;
+
+ case format_16: /* field instructions */
+ OP2 = readop_arg(opram, pc);
+
+ smode = BITS(OP2,10,11);
+ sarg = BITS(OP2,12,15);
+ dmode = BITS(OP2,4,5);
+ darg = BITS(OP2,6,9);
+ bit_position = BITS(OP2,0,3);
+ bit_width = BITS(OP,12,15);
+
+ buffer += sprintf (buffer, "%-4s ", mnemonic);
+ buffer += print_arg (buffer, smode, sarg, opram, pc);
+ buffer += sprintf (buffer, ",");
+ buffer += print_arg (buffer, dmode, darg, opram, pc);
+ buffer += sprintf (buffer, bit_position ? ",(%d," : ",(%d,", bit_position);
+ buffer += sprintf (buffer, bit_width ? "%d)" : "R%d)", bit_width);
+ break;
+
+ case format_17: /* alter register and jump instructions */
+ OP2 = readop_arg(opram, pc);
+
+ displacement = (signed char)BITS(OP2,8,15);
+ sarg = BITS(OP2,4,7);
+ darg = BITS(OP2,0,3);
+ if (darg)
+ sprintf (buffer, darg ? "%-4s >%04x,%d,R%d" : "%-4s >%04x,R%d,R%d",
+ mnemonic, 0xffff & (PC + displacement * 2), sarg, darg);
+ break;
+
+ case format_18: /* single register operand instructions */
+ sarg = BITS(OP,12,15);
+
+ sprintf (buffer, "%-4s R%d", mnemonic, sarg);
+ break;
+
+ case format_liim: /* liim instruction */
+ sarg = BITS(OP,14,15);
+
+ sprintf (buffer, "%-4s %d", mnemonic, sarg);
+ break;
+
+ case format_19: /* move address instruction */
+ OP2 = readop_arg(opram, pc);
+
+ smode = BITS(OP2,10,11);
+ sarg = BITS(OP2,12,15);
+ dmode = BITS(OP2,4,5);
+ darg = BITS(OP2,6,9);
+
+ buffer += sprintf (buffer, "%-4s ", mnemonic);
+ buffer += print_arg (buffer, smode, sarg, opram, pc);
+ buffer += sprintf (buffer, ",");
+ buffer += print_arg (buffer, dmode, darg, opram, pc);
+ break;
+
+ case format_20: /* list search instructions */
+ {
+ const char *condition_code;
+
+ OP2 = readop_arg(opram, pc);
+
+ smode = BITS(OP2,10,11);
+ sarg = BITS(OP2,12,15);
+ dmode = BITS(OP2,4,5);
+ darg = BITS(OP2,6,9);
+
+ switch (BITS(OP2,0,3))
+ {
+ case 0:
+ condition_code = "eq";
+ break;
+ case 1:
+ condition_code = "ne";
+ break;
+ case 2:
+ condition_code = "he";
+ break;
+ case 3:
+ condition_code = "l";
+ break;
+ case 4:
+ condition_code = "ge";
+ break;
+ case 5:
+ condition_code = "lt";
+ break;
+ case 6:
+ condition_code = "le";
+ break;
+ case 7:
+ condition_code = "h";
+ break;
+ case 8:
+ condition_code = "lte";
+ break;
+ case 9:
+ condition_code = "gt";
+ break;
+ default:
+ condition_code = "??";
+ break;
+ }
+
+ buffer += sprintf (buffer, "%-4s %s,", mnemonic, condition_code);
+ buffer += print_arg (buffer, smode, sarg, opram, pc);
+ buffer += sprintf (buffer, ",");
+ buffer += print_arg (buffer, dmode, darg, opram, pc);
+ break;
+ }
+
+ case format_21: /* extend precision instruction */
+ {
+ int dest_byte_count;
+
+ OP2 = readop_arg(opram, pc);
+
+ smode = BITS(OP2,10,11);
+ sarg = BITS(OP2,12,15);
+ dmode = BITS(OP2,4,5);
+ darg = BITS(OP2,6,9);
+ byte_count = BITS(OP2,0,3);
+ dest_byte_count = BITS(OP,12,15);
+
+ buffer += sprintf (buffer, "%-4s ", mnemonic);
+ buffer += print_arg (buffer, smode, sarg, opram, pc);
+ buffer += sprintf (buffer, ",");
+ buffer += print_arg (buffer, dmode, darg, opram, pc);
+ buffer += sprintf (buffer, byte_count ? ",%d" : ",R%d", byte_count);
+ buffer += sprintf (buffer, dest_byte_count ? ",%d" : ",R%d", dest_byte_count);
+ break;
+ }
+
+ default:
+ logerror("debbugger internal error, file %s, line %d\n", __FILE__, __LINE__);
+ case illegal:
+ sprintf (buffer, "data >%04x", OP);
+ break;
+ }
+
+ return (PC - pc) | DASMFLAG_SUPPORTED | dasmflags;
+}
+
+
+
diff --git a/trunk/src/emu/cpu/tms9900/99xxcore.h b/trunk/src/emu/cpu/tms9900/99xxcore.h
new file mode 100644
index 00000000000..fb706ee797b
--- /dev/null
+++ b/trunk/src/emu/cpu/tms9900/99xxcore.h
@@ -0,0 +1,4816 @@
+/*
+ 99xxcore.h : generic tms99xx emulation
+
+ The TMS99XX_MODEL switch tells which emulator we want to build. Set the
+ switch, then include 99xxcore.h, and you will have an emulator for this
+ processor.
+
+ Only ti990/10, tms9900, tms9980a/9981, and tms9995 work OK for now. Note
+ that tms9995 has not been tested extensively.
+
+ tms9940 is WIP: it is probably still buggy (particularily the BCD support),
+ as it has not been tested. tms9985 has been implemented as a 9940 with
+ a data bus, which should be mostly correct.
+
+ I think all software aspects of tms9985 and tms9989 are implemented.
+ You just need to implement bus interfaces, provided you know them.
+ (I don't...)
+
+ tms99000 cannot be implemented fully yet, due to lack of documentation.
+
+ ti990/12 is not supported at all, and it should probably be implemented as
+ a separate processor core, anyway.
+
+ Original tms9900 emulator by Edward Swartz
+ Smoothed out by Raphael Nabet
+ Originally converted for Mame by M.Coates
+ Processor timing, support for tms9980 and tms9995, and many bug fixes by R Nabet
+*/
+
+/*
+ The first member of the family was actually the ti990/10 minicomputer,
+ released in 1975. tms9900 was released in 1976, and has the same
+ instruction set as ti990/10: however, tms9900 is slower, it does not
+ support privileges and memory mapping, and illegal instructions do not
+ cause an error interrupt.
+
+ The ti990 family later evoluted into the huge ti990/12 system, with support
+ for 144 different instructions, and microcode programming in case some user
+ found it was not enough. ti990/10 was eventually replaced by a cheaper
+ ti990/10a board, built around a tms99000 microprocessor.
+
+ The tms9980 processor is merely a tms9900 with a 8-bit data bus (instead of
+ 16-bit on tms9900).
+
+ tms9940 is a microcontroller, and is mostly similar to 9900/9980. The
+ variant I know has 2kb of ROM, 128 bytes of RAM, a timer, 32 I/O line, some
+ of which can be reconfigured as a CRU bus, but no external memory bus. It
+ includes three additional opcodes, which are not supported by any other
+ member of the family (with the probable exception of TMS9985).
+
+ tms9985 is similar to tms9940, but it supports an external 8-bit-wide
+ memory bus. At least one variant included 8kb of ROM, 256 bytes of RAM.
+ It was ill-fated, as it was never released due to technical problems.
+
+ tms9989 is mostly alien to me. I guess it is a close relative of tms9995,
+ although I am not sure. I have read that the SBP68689 supports tms9995
+ opcodes, but that tms9989 does not.
+
+ tms9995 belongs to another generation. It is quite faster than tms9900,
+ and supports 4 extra opcodes. Its external bus is 8-bit-wide, and it has
+ 256 bytes of internal 16-bit RAM.
+
+ tms99000 is the successor to both ti9900 and ti990/10. It supports
+ privileges, and has a coprocessor interface which enables the use of an
+ external memory mapper. Additionnally, it can use a Macrostore ROM to
+ emulate additional instructions.
+
+ This feature allowed TI to expand the 99000 family with the tms99105 (which
+ was said to support 84 instructions types), the tms99110 (which supported
+ floating point instructions), and possibly another chip (tms99220???) which
+ included parts of the UCSD P-system in Macrostore.
+
+References :
+* 9900 family systems design, chapter 6, 7, 8
+* TMS 9980A/ TMS 9981 Product Data Book
+* TMS 9995 16-Bit Microcomputer Data Manual
+* Model 990/10A computer general description, section 4 (p/n 2302633-9701 A)
+* 990/99000 assembly language reference manual (p/n 2270509-9701 A)
+* Chapter 18 of unidentified book is the only reference on tms9940 I have found so far (Paperport format)
+ <ftp://ftp.whtech.com//datasheets/Hardware manuals/tms9900 9901 9904 9940 9980 (by a osborne).max>
+
+Other references can be found on spies.com:
+<http://www.spies.com/arcade/simulation/processors/index.html>
+<http://www.spies.com/~aek/pdf/ti/>
+
+*/
+
+#include "tms9900.h"
+
+
+#if (TMS99XX_MODEL == TI990_10_ID)
+
+ #define TMS99XX_PREFIX ti990_10
+ #define TMS99XX_GET_INFO CPU_GET_INFO_NAME( ti990_10 )
+ #define TMS99XX_device_get_name "TI990/10"
+
+#elif (TMS99XX_MODEL == TMS9900_ID)
+
+ #define TMS99XX_PREFIX tms9900
+ #define TMS99XX_GET_INFO CPU_GET_INFO_NAME( tms9900 )
+ #define TMS99XX_device_get_name "TMS9900"
+
+#elif (TMS99XX_MODEL == TMS9940_ID)
+
+ #define TMS99XX_PREFIX tms9940
+ #define TMS99XX_GET_INFO CPU_GET_INFO_NAME( tms9940 )
+ #define TMS99XX_device_get_name "TMS9940"
+
+ #error "tms9940 is not yet supported"
+
+#elif (TMS99XX_MODEL == TMS9980_ID)
+
+ #define TMS99XX_PREFIX tms9980a
+ #define TMS99XX_GET_INFO CPU_GET_INFO_NAME( tms9980a )
+ #define TMS99XX_device_get_name "TMS9980A/TMS9981"
+
+#elif (TMS99XX_MODEL == TMS9985_ID)
+
+ #define TMS99XX_PREFIX tms9985
+ #define TMS99XX_GET_INFO CPU_GET_INFO_NAME( tms9985 )
+ #define TMS99XX_device_get_name "TMS9985"
+
+ #error "tms9985 is not yet supported"
+
+#elif (TMS99XX_MODEL == TMS9989_ID)
+
+ #define TMS99XX_PREFIX tms9989
+ #define TMS99XX_GET_INFO CPU_GET_INFO_NAME( tms9989 )
+ #define TMS99XX_device_get_name "TMS9989"
+
+ #error "tms9989 is not yet supported"
+
+#elif (TMS99XX_MODEL == TMS9995_ID)
+
+ #define TMS99XX_PREFIX tms9995
+ #define TMS99XX_GET_INFO CPU_GET_INFO_NAME( tms9995 )
+ #define TMS99XX_device_get_name "TMS9995"
+
+#elif (TMS99XX_MODEL == TMS99000_ID)
+
+ #define TMS99XX_PREFIX tms99000
+ #define TMS99XX_GET_INFO CPU_GET_INFO_NAME( tms99000 )
+ #define TMS99XX_device_get_name "TMS99000"
+
+ #error "tms99000 is not yet supported"
+
+#elif (TMS99XX_MODEL == TMS99105A_ID)
+
+ #define TMS99XX_PREFIX tms99105a
+ #define TMS99XX_GET_INFO CPU_GET_INFO_NAME( tms99105a )
+ #define TMS99XX_device_get_name "TMS99105A"
+
+ #error "tms99105a is not yet supported"
+
+#elif (TMS99XX_MODEL == TMS99110A_ID)
+
+ #define TMS99XX_PREFIX tms99110a
+ #define TMS99XX_GET_INFO CPU_GET_INFO_NAME( tms99110a )
+ #define TMS99XX_device_get_name "TMS99110A"
+
+ #error "tms99110a is not yet supported"
+
+#endif
+
+/*
+ Now for some preprocessor wizardry.
+*/
+#define concat2(a,b) a##b
+
+#define GET_INFO(prefix) concat2(prefix,_get_info)
+#define RESET_PARAM(prefix) concat2(prefix,reset_param)
+
+#define TMS99XX_RESET_PARAM RESET_PARAM(TMS99XX_PREFIX)
+
+
+
+/*
+ I include this macro because we may eventually support other 99000 variants such as tms99110,
+ and this macro will remain true for every 99000 family member, even when we have
+ (TMS99XX_MODEL != TMS99000_ID).
+*/
+#define IS_99000 (TMS99XX_MODEL == TMS99000_ID)
+
+/*
+ On microprocessor implementations (other than TMS9940 and, probably, TMS9985), the CKOF, CKON,
+ IDLE, LREX and RSET cause an external CRU write. CKOF, CKON and LREX do nothing apart of this,
+ therefore they must be implemented with external hardware (CKON and CKOF are supposed to
+ enable/disable a line clock interrupt, and LREX to trigger a LOAD interrupt). IDLE and RSET
+ are functional, but, on the one hand, the design allowed to light a diagnostic LED when
+ the processor is in IDLE state, and, on the other hand, the RSET instruction is supposed
+ to reset external devices as well.
+
+ On the TI990/10 and TI990/12 minicomputers, there is no such CRU write. The line clock
+ interrupt latch is part of the CPU board, LREX is fully functional, the IDLE led is connected
+ to the board, and the RSET line is part of the TILINE bus connector.
+
+ On the TMS9940, CKOF, CKON, LREX and RSET are not supported. IDLE, on the other hand, is
+ supported, and the CPU can be configured to output its IDLE state on the P16 I/O pin.
+*/
+#define EXTERNAL_INSTRUCTION_DECODING (TMS99XX_MODEL != TI990_10_ID) && (TMS99XX_MODEL != TI9940_ID) && (TMS99XX_MODEL != TI9985_ID)
+#define EXTERNAL_INSTRUCTION_CALLBACK (TMS99XX_MODEL == TI990_10_ID)
+
+/*
+ ti990/10, ti990/12 and tms99000 support privileges
+
+ privileged instructions:
+ CKOF, CKON, IDLE, LIMI, LREX, RSET,
+ LDD, LDS, LMF, (memory mapping instructions)
+ DINT, EINT, EMD , LCS, LIM, SLSP. (990/12 instructions)
+
+ instructions which are privileged when the effective CRU address is higher than 0xE00:
+ LDCR, SBO, SBZ, STCR, TB.
+
+ instructions whose behaviour is modified in user mode (only user flags in ST are affected):
+ RTWP,
+ LST. (ti990/12 and tms99000 instruction)
+*/
+#define HAS_PRIVILEGE ((TMS99XX_MODEL == TI990_10_ID) || IS_99000)
+
+/*
+ opcode groups
+
+ * 69 basic opcodes implemented on all family members
+ * 3 memory mapping opcodes implemented on ti990/10 with mapping option, ti990/12, and
+ the tim99610 mapper in conjunction with any tms99000 family member: LMF, LDS, LDD
+ * 3 opcodes implemented on tms9940 (and probably tms9985) only: DCA, DCS, LIIM
+ * 4 opcodes implemented on ti990/12, tms9989 and above: MPYS, DIVS, LST, LWP
+ * 1 opcode implemented on ti990/12, and tms99000: BIND
+ * 72 opcodes implemented on ti990/12 only (some of which are emulated by tms99105 & tms99110)
+*/
+
+#define HAS_MAPPING ((TMS99XX_MODEL == TI990_10_ID) /*|| IS_99000*/)
+#define HAS_9995_OPCODES ((TMS99XX_MODEL == TMS9989_ID) || (TMS99XX_MODEL == TMS9995_ID) || IS_99000)
+#define HAS_BIND_OPCODE IS_99000
+
+#define HAS_OVERFLOW_INTERRUPT ((TMS99XX_MODEL == TMS9995_ID) || IS_99000)
+
+/*
+ Under tms9900, opcodes >0200->03FF are incompletely decoded: bits 11 is ignored, and so are
+ bits 12-15 for instructions which do not require a register. On the other hand, ti990/10
+ generates an illegal instruction error when bit 11 is set, but still ignores bits 12-15.
+ Additionally, ti990/12 and tms9995 will generate an illegal error when bits 12-15 are
+ non-zero.
+*/
+#define BETTER_0200_DECODING (TMS99XX_MODEL == TI990_10_ID)
+#define COMPLETE_0200_DECODING (TMS99XX_MODEL >= TMS9995_ID)
+
+/*
+ TI990/10 and tms9900 force unused bits in the ST register to 0.
+ TMS9995 does not.
+*/
+#define USE_ST_MASK (TMS99XX_MODEL <= TMS9985_ID)
+
+/*
+ TI990/10, TMS9900 and TMS99000 have a 16-bit-wide memory bus, and use 16-bus accessors.
+ TMS9940 use 16-bit accessors, too, as it has an internal 16-bit bus, and no external bus.
+*/
+#define USE_16_BIT_ACCESSORS ((TMS99XX_MODEL == TI990_10_ID) || (TMS99XX_MODEL == TMS9900_ID) || (TMS99XX_MODEL == TMS9940_ID) || (IS_99000))
+
+typedef struct _tms99xx_state tms99xx_state;
+
+INLINE void execute(tms99xx_state *cpustate, UINT16 opcode);
+
+#if EXTERNAL_INSTRUCTION_DECODING
+static void external_instruction_notify(tms99xx_state *cpustate, int ext_op_ID);
+#endif
+static UINT16 decipheraddr(tms99xx_state *cpustate, UINT16 opcode);
+static UINT16 decipheraddrbyte(tms99xx_state *cpustate, UINT16 opcode);
+static void contextswitch(tms99xx_state *cpustate, UINT16 addr);
+#if HAS_MAPPING || HAS_PRIVILEGE
+static void contextswitchX(tms99xx_state *cpustate, UINT16 addr);
+#else
+#define contextswitchX(cs, addr) contextswitch(cs, addr)
+#endif
+static void field_interrupt(tms99xx_state *cpustate);
+
+/***************************/
+/* Mame Interface Routines */
+/***************************/
+
+
+/* tms9900 ST register bits. */
+
+/* These bits are set by every compare, move and arithmetic or logical operation : */
+/* (Well, COC, CZC and TB only set the E bit, but these are kind of exceptions.) */
+#define ST_LGT 0x8000 /* Logical Greater Than (strictly) */
+#define ST_AGT 0x4000 /* Arithmetical Greater Than (strictly) */
+#define ST_EQ 0x2000 /* Equal */
+
+/* These bits are set by arithmetic operations, when it makes sense to update them. */
+#define ST_C 0x1000 /* Carry */
+#define ST_OV 0x0800 /* OVerflow (overflow with operations on signed integers, */
+ /* and when the result of a 32bits:16bits division cannot fit in a 16-bit word.) */
+
+/* This bit is set by move and arithmetic operations WHEN THEY USE BYTE OPERANDS. */
+#define ST_OP 0x0400 /* Odd Parity */
+
+#if (TMS99XX_MODEL != TMS9940_ID)
+
+/* This bit is set by the XOP instruction. */
+#define ST_X 0x0200 /* Xop */
+
+#endif
+
+#if (TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID)
+
+/* This bit is set by arithmetic operations to support BCD */
+#define ST_DC 0x0100 /* Digit Carry */
+
+#endif
+
+#if HAS_PRIVILEGE
+
+/* This bit is set in user (i.e. non-supervisor) mode */
+#define ST_PR 0x0100 /* PRivilege */
+
+#endif
+
+#if HAS_MAPPING
+
+/* This tells which map is currently in use */
+#define ST_MF 0x0080 /* Map File */
+
+#endif
+
+#if (HAS_OVERFLOW_INTERRUPT)
+
+/* This bit is set in ti990/12, TMS9995 and later chips to generate a level-2 interrupt when
+the Overflow status bit is set */
+#define ST_OVIE 0x0020 /* OVerflow Interrupt Enable */
+
+#endif
+
+#if (IS_99000)
+
+/* This bit enables the macrostore feature on tms99000 */
+/* (It is used on ti990/12 with a different meaning.) */
+#define ST_EMR 0x0010 /* Enable Macrostore Rom */
+
+#endif
+
+#if (TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID)
+
+#define ST_IM 0x0003 /* Interrupt Mask */
+
+#else
+
+#define ST_IM 0x000F /* Interrupt Mask */
+
+#endif
+
+/* On models before TMS9995 (TMS9989 ?), unused ST bits are always forced to 0, so we define
+a ST_MASK */
+#if (USE_ST_MASK)
+ #if (TMS99XX_MODEL == TI990_10_ID)
+ #define ST_MASK 0xFF8F
+ #elif (TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID)
+#define ST_MASK 0xFD03
+ #else
+ #define ST_MASK 0xFE0F
+ #endif
+#endif
+
+
+/* error interrupt register bits */
+
+#if (TMS99XX_MODEL == TI990_10_ID)
+
+/* This bit is set in user (i.e. non-supervisor) mode */
+#define EIR_MAPERR 0x0800 /* memory MAPping ERRor */
+#define EIR_MER 0x1000 /* Memory parity ERRor */
+#define EIR_ILLOP 0x2000 /* ILLegal OPcode */
+#define EIR_PRIVOP 0x4000 /* PRiviledged OPeration */
+#define EIR_TIMEOUT 0x8000 /* TILINE TIMEOUT */
+
+#endif
+
+
+/* Offsets for registers. */
+#define R0 0
+#define R1 2
+#define R2 4
+#define R3 6
+#define R4 8
+#define R5 10
+#define R6 12
+#define R7 14
+#define R8 16
+#define R9 18
+#define R10 20
+#define R11 22
+#define R12 24
+#define R13 26
+#define R14 28
+#define R15 30
+
+typedef struct map_file_t
+{
+ UINT16 L[3], B[3]; /* actual registers */
+ UINT32 limit[3], bias[3]; /* equivalent in a more convenient form */
+} map_file_t;
+
+struct _tms99xx_state
+{
+/* "actual" tms9900 registers : */
+ UINT16 WP; /* Workspace pointer */
+ UINT16 PC; /* Program counter */
+ UINT16 STATUS; /* STatus register */
+
+/* Now, data used for emulation */
+ UINT8 lastparity;
+ char lds_flag, ldd_flag;
+ UINT16 IR; /* Instruction register, with the currently parsed opcode */
+
+ UINT8 interrupt_pending; /* true if an interrupt must be honored... */
+
+#if ! ((TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID))
+ UINT8 load_state; /* nonzero if the LOAD* line is active (low) */
+#endif
+
+#if (TMS99XX_MODEL == TI990_10_ID) || (TMS99XX_MODEL == TMS9900_ID) || (TMS99XX_MODEL == TMS9980_ID)
+ /* On tms9900, we cache the state of INTREQ* and IC0-IC3 here */
+ /* On tms9980/9981, we translate the state of IC0-IC2 to the equivalent state for a tms9900,
+ and store the result here */
+ UINT8 irq_level; /* when INTREQ* is active, interrupt level on IC0-IC3 ; else always 16 */
+ UINT8 irq_state; /* nonzero if the INTREQ* line is active (low) */
+ /* with TMS9940, bit 0 means INT1, bit 1 decrementer, bit 2 INT2 */
+#elif (TMS99XX_MODEL == TMS9995_ID)
+ /* tms9995 is quite different : it latches the interrupt inputs */
+ UINT8 irq_level; /* We store the level of the request with the highest level here */
+ UINT8 int_state; /* interrupt lines state */
+ UINT8 int_latch; /* interrupt latches state */
+#endif
+
+ /* interrupt callback */
+ /* note that this callback is used by tms9900_set_irq_line(cpustate) and tms9980a_set_irq_line(cpustate) to
+ retreive the value on IC0-IC3 (non-standard behaviour) */
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ address_space *io;
+ int icount;
+
+ UINT8 IDLE; /* nonzero if processor is IDLE - i.e waiting for interrupt while writing
+ special data on CRU bus */
+
+#if HAS_MAPPING
+ UINT8 mapping_on; /* set by a CRU write */
+ map_file_t map_files[3]; /* internal mapper registers */
+ UINT8 cur_map; /* equivalent to ST_MF status bit */
+ UINT8 cur_src_map; /* set to 2 by LDS */
+ UINT8 cur_dst_map; /* set to 2 by LDD */
+
+#if (TMS99XX_MODEL == TI990_10_ID)
+ UINT8 reset_maperr; /* reset mapper error flag line (reset flags in 945417-9701 p. 3-90) */
+
+ UINT32 mapper_address_latch; /* used to load the map file and for diagnostic purpose */
+ UINT16 mapper_cru_read_register; /* read register select code for mapper cru interface */
+ UINT8 diaglat; /* set when diagnostic address latch is done */
+ UINT8 latch_control[3]; /* latch control */
+
+#endif
+#endif
+
+#if (TMS99XX_MODEL == TI990_10_ID)
+ UINT16 error_interrupt_register; /* one flag for each interrupt condition */
+ ti99xx_error_interrupt_func error_interrupt_callback;
+#endif
+
+#if (TMS99XX_MODEL == TMS9985_ID) || (TMS99XX_MODEL == TMS9995_ID)
+ UINT8 RAM[256]; /* on-chip RAM (I know this is weird, but the internal bus is 16-bit-wide, whereas the external bus is 8-bit-wide) */
+#endif
+
+#if (TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID) || (TMS99XX_MODEL == TMS9995_ID)
+ /* on-chip event counter/timer*/
+ UINT8 decrementer_enabled;
+ UINT16 decrementer_interval;
+ UINT16 decrementer_count; /* used in event counter mode*/
+ emu_timer *timer; /* used in timer mode */
+#endif
+
+#if (TMS99XX_MODEL == TMS9995_ID)
+ /* additionnal registers */
+ UINT16 flag; /* flag register */
+ UINT8 MID_flag; /* MID flag register */
+
+ /* chip config, which can be set on reset */
+ UINT8 memory_wait_states_byte;
+ UINT8 memory_wait_states_word;
+
+ /* mask option (off on normal tms9995) */
+ UINT8 is_mp9537;
+#endif
+
+ /* Some instructions (i.e. XOP, BLWP, and MID) disable interrupt recognition until another
+ instruction is executed : so they set this flag */
+ UINT8 disable_interrupt_recognition;
+
+ /* notify the driver of changes in IDLE state */
+ ti99xx_idle_func idle_callback;
+
+#if EXTERNAL_INSTRUCTION_CALLBACK
+ ti99xx_rset_func rset_callback;
+ ti99xx_lrex_func lrex_callback;
+ ti99xx_ckon_ckof_func ckon_ckof_callback;
+#endif
+
+ int write_inhibit;
+ int extra_byte; /* buffer holding the unused byte in a word read */
+};
+
+INLINE tms99xx_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+// assert(device->type() == TMS99XX_GET_INFO);
+ return (tms99xx_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+#if (TMS99XX_MODEL == TMS9995_ID)
+static void reset_decrementer(tms99xx_state *cpustate);
+#endif
+
+
+#if (TMS99XX_MODEL == TI990_10_ID)
+
+/*
+ accessor for the internal ROM
+*/
+READ16_HANDLER(ti990_10_internal_r)
+{
+ //return cpustate->ROM[offset];
+ return space->read_word(0x1ffc00+offset);
+}
+
+#endif
+
+#if (TMS99XX_MODEL == TMS9995_ID)
+
+/*
+ accessor for the first 252 bytes of internal RAM
+*/
+READ8_HANDLER(tms9995_internal1_r)
+{
+ tms99xx_state *cpustate = get_safe_token(&space->device());
+ return cpustate->RAM[offset];
+}
+
+WRITE8_HANDLER(tms9995_internal1_w)
+{
+ tms99xx_state *cpustate = get_safe_token(&space->device());
+ cpustate->RAM[offset]=data;
+}
+
+/*
+ accessor for the last 4 bytes of internal RAM
+*/
+READ8_HANDLER(tms9995_internal2_r)
+{
+ tms99xx_state *cpustate = get_safe_token(&space->device());
+ return cpustate->RAM[offset+0xfc];
+}
+
+WRITE8_HANDLER(tms9995_internal2_w)
+{
+ tms99xx_state *cpustate = get_safe_token(&space->device());
+ cpustate->RAM[offset+0xfc]=data;
+}
+
+#endif
+
+#if (TMS99XX_MODEL == TI990_10_ID)
+
+ /* on-board ROMs are not emulated (we use a hack) */
+
+ #define readword(cs, addr) readwordX((cs), (addr), (cs)->cur_map)
+ static int readwordX(tms99xx_state *cpustate, int addr, int map_file)
+ {
+ if ((map_file == 0) && (addr >= 0xf800))
+ { /* intercept TPCS and CPU ROM */
+ if (addr < 0xfc00)
+ /* TPCS */
+ return cpustate->program->read_word(0x1f0000+addr);
+ else
+ /* CPU ROM */
+ return cpustate->program->read_word(0x1f0000+addr); /* hack... */
+ }
+ else if (! cpustate->mapping_on)
+ {
+ return cpustate->program->read_word(addr);
+ }
+ else
+ {
+ int map_index;
+
+ if (addr <= cpustate->map_files[map_file].limit[0])
+ map_index = 0;
+ else if (addr <= cpustate->map_files[map_file].limit[1])
+ map_index = 1;
+ else if (addr <= cpustate->map_files[map_file].limit[2])
+ map_index = 2;
+ else
+ { /* mapping error */
+ if ((! (cpustate->error_interrupt_register & EIR_MAPERR)) && ! (cpustate->diaglat))
+ cpustate->mapper_address_latch = addr;
+ if ((! cpustate->reset_maperr) && ! (cpustate->error_interrupt_register & EIR_MAPERR))
+ {
+ cpustate->error_interrupt_register |= EIR_MAPERR;
+ cpustate->write_inhibit = 1;
+ }
+ return cpustate->program->read_word(addr);
+ }
+ if ((! (cpustate->error_interrupt_register & EIR_MAPERR)) && ! (cpustate->diaglat))
+ cpustate->mapper_address_latch = cpustate->map_files[map_file].bias[map_index]+addr;
+ if ((cpustate->latch_control[map_index]) && (! cpustate->reset_maperr))
+ cpustate->diaglat = 1;
+ return cpustate->program->read_word(cpustate->map_files[map_file].bias[map_index]+addr);
+ }
+ }
+
+ #define writeword(cs, addr, data) writewordX((cs), (addr), (data), (cs)->cur_map)
+ static void writewordX(tms99xx_state *cpustate, int addr, int data, int map_file)
+ {
+ if ((map_file == 0) && (addr >= 0xf800))
+ { /* intercept TPCS and CPU ROM */
+ if (addr < 0xfc00)
+ /* TPCS */
+ cpustate->program->write_word(0x1f0000+addr, data);
+ else
+ /* CPU ROM */
+ cpustate->program->write_word(0x1f0000+addr, data); /* hack... */
+ }
+ else if (! cpustate->mapping_on)
+ {
+ cpustate->program->write_word(addr, data);
+ }
+ else
+ {
+ int map_index;
+
+ if (addr <= cpustate->map_files[map_file].limit[0])
+ map_index = 0;
+ else if (addr <= cpustate->map_files[map_file].limit[1])
+ map_index = 1;
+ else if (addr <= cpustate->map_files[map_file].limit[2])
+ map_index = 2;
+ else
+ { /* mapping error */
+ if ((! (cpustate->error_interrupt_register & EIR_MAPERR)) && ! (cpustate->diaglat))
+ cpustate->mapper_address_latch = addr;
+ if ((! cpustate->reset_maperr) && ! (cpustate->error_interrupt_register & EIR_MAPERR))
+ {
+ cpustate->error_interrupt_register |= EIR_MAPERR;
+ cpustate->write_inhibit = 1;
+ }
+ if (cpustate->write_inhibit)
+ (void)cpustate->program->read_word(addr);
+ else
+ cpustate->program->write_word(addr, data);
+ return;
+ }
+ if ((! (cpustate->error_interrupt_register & EIR_MAPERR)) && ! (cpustate->diaglat))
+ cpustate->mapper_address_latch = cpustate->map_files[map_file].bias[map_index]+addr;
+ if ((cpustate->latch_control[map_index]) && (! cpustate->reset_maperr))
+ cpustate->diaglat = 1;
+ cpustate->program->write_word(cpustate->map_files[map_file].bias[map_index]+addr, data);
+ }
+ }
+
+ #define readbyte(cs, addr) readbyteX((cs), (addr), (cs)->cur_map)
+ static int readbyteX(tms99xx_state *cpustate, int addr, int map_file)
+ {
+ if ((map_file == 0) && (addr >= 0xf800))
+ { /* intercept TPCS and CPU ROM */
+ if (addr < 0xfc00)
+ /* TPCS */
+ return cpustate->program->read_byte(0x1f0000+addr);
+ else
+ /* CPU ROM */
+ return cpustate->program->read_byte(0x1f0000+addr); /* hack... */
+ }
+ else if (! cpustate->mapping_on)
+ {
+ return cpustate->program->read_byte(addr);
+ }
+ else
+ {
+ int map_index;
+
+ if (addr <= cpustate->map_files[map_file].limit[0])
+ map_index = 0;
+ else if (addr <= cpustate->map_files[map_file].limit[1])
+ map_index = 1;
+ else if (addr <= cpustate->map_files[map_file].limit[2])
+ map_index = 2;
+ else
+ { /* mapping error */
+ if ((! (cpustate->error_interrupt_register & EIR_MAPERR)) && ! (cpustate->diaglat))
+ cpustate->mapper_address_latch = addr;
+ if ((! cpustate->reset_maperr) && ! (cpustate->error_interrupt_register & EIR_MAPERR))
+ {
+ cpustate->error_interrupt_register |= EIR_MAPERR;
+ cpustate->write_inhibit = 1;
+ }
+ return cpustate->program->read_byte(addr);
+ }
+ if ((! (cpustate->error_interrupt_register & EIR_MAPERR)) && ! (cpustate->diaglat))
+ cpustate->mapper_address_latch = cpustate->map_files[map_file].bias[map_index]+addr;
+ if ((cpustate->latch_control[map_index]) && (! cpustate->reset_maperr))
+ cpustate->diaglat = 1;
+ return cpustate->program->read_byte(cpustate->map_files[map_file].bias[map_index]+addr);
+ }
+ }
+
+ #define writebyte(cs, addr, data) writebyteX((cs), (addr), (data), (cs)->cur_map)
+ static void writebyteX(tms99xx_state *cpustate, int addr, int data, int map_file)
+ {
+ if ((map_file == 0) && (addr >= 0xf800))
+ { /* intercept TPCS and CPU ROM */
+ if (addr < 0xfc00)
+ /* TPCS */
+ cpustate->program->write_byte(0x1f0000+addr, data);
+ else
+ /* CPU ROM */
+ cpustate->program->write_byte(0x1f0000+addr, data); /* hack... */
+ }
+ else if (! cpustate->mapping_on)
+ {
+ cpustate->program->write_byte(addr, data);
+ }
+ else
+ {
+ int map_index;
+
+ if (addr <= cpustate->map_files[map_file].limit[0])
+ map_index = 0;
+ else if (addr <= cpustate->map_files[map_file].limit[1])
+ map_index = 1;
+ else if (addr <= cpustate->map_files[map_file].limit[2])
+ map_index = 2;
+ else
+ { /* mapping error */
+ if ((! (cpustate->error_interrupt_register & EIR_MAPERR)) && ! (cpustate->diaglat))
+ cpustate->mapper_address_latch = addr;
+ if ((! cpustate->reset_maperr) && ! (cpustate->error_interrupt_register & EIR_MAPERR))
+ {
+ cpustate->error_interrupt_register |= EIR_MAPERR;
+ cpustate->write_inhibit = 1;
+ }
+ if (cpustate->write_inhibit)
+ (void)cpustate->program->read_byte(addr);
+ else
+ cpustate->program->write_byte(addr, data);
+ return;
+ }
+ if ((! (cpustate->error_interrupt_register & EIR_MAPERR)) && ! (cpustate->diaglat))
+ cpustate->mapper_address_latch = cpustate->map_files[map_file].bias[map_index]+addr;
+ if ((cpustate->latch_control[map_index]) && (! cpustate->reset_maperr))
+ cpustate->diaglat = 1;
+ cpustate->program->write_byte(cpustate->map_files[map_file].bias[map_index]+addr, data);
+ }
+ }
+
+#elif (TMS99XX_MODEL == TMS9900_ID) || (TMS99XX_MODEL == TMS9940_ID)
+ /*16-bit data bus, 16-bit address bus (internal bus in the case of TMS9940)*/
+ /*Note that tms9900 actually never accesses a single byte : when performing byte operations,
+ it reads a 16-bit word, changes the revelant byte, then write a complete word. You should
+ remember this when writing memory handlers.*/
+ /*This does not apply to tms9995 and tms99xxx, but does apply to tms9980 (see below).*/
+
+ #define readword(cs, addr) (cs)->program->read_word(addr)
+ #define writeword(cs, addr,data) (cs)->program->write_word((addr), (data))
+
+ #define readbyte(cs, addr) (cs)->program->read_byte(addr)
+ #define writebyte(cs, addr,data) (cs)->program->write_byte((addr),(data))
+
+#elif (TMS99XX_MODEL == TMS9980_ID)
+ /*8-bit data bus, 14-bit address*/
+ /*Note that tms9980 never accesses a single byte (however crazy it may seem). Although this
+ makes memory access slower, I have emulated this feature, because if I did otherwise,
+ there would be some implementation problems in some driver sooner or later.*/
+
+ INLINE int readword(tms99xx_state *cpustate, int addr)
+ {
+ int val;
+
+ cpustate->icount -= 2;
+ val = cpustate->program->read_byte(addr);
+ return (val << 8) | cpustate->program->read_byte(addr+1);
+ }
+ #define writeword(cs, addr,data) { (cs)->icount -= 2; (cs)->program->write_byte((addr), (data) >> 8); cpustate->program->write_byte((addr) + 1, (data) & 0xff); }
+
+#if 0
+ #define readbyte(cs, addr) ((cs)->icount -= 2, (cs)->program->read_byte(addr))
+ #define writebyte(cs, addr,data) { (cs)->icount -= 2; (cs)->program->write_byte((addr),(data)); }
+#else
+ /*This is how it really works*/
+ /*Note that every writebyte must match a readbyte (which is indeed the case)*/
+
+ static int readbyte(tms99xx_state *cpustate, int addr)
+ {
+ cpustate->icount -= 2;
+ if (addr & 1)
+ {
+ cpustate->extra_byte = cpustate->program->read_byte(addr-1);
+ return cpustate->program->read_byte(addr);
+ }
+ else
+ {
+ int val = cpustate->program->read_byte(addr);
+ cpustate->extra_byte = cpustate->program->read_byte(addr+1);
+ return val;
+ }
+ }
+ static void writebyte (tms99xx_state *cpustate, int addr, int data)
+ {
+ cpustate->icount -= 2;
+ if (addr & 1)
+ {
+ cpustate->program->write_byte(addr-1, cpustate->extra_byte);
+ cpustate->program->write_byte(addr, data);
+ }
+ else
+ {
+ cpustate->program->write_byte(addr, data);
+ cpustate->program->write_byte(addr+1, cpustate->extra_byte);
+ }
+ }
+#endif
+
+#elif (TMS99XX_MODEL == TMS9985_ID)
+ /*Note that every writebyte must match a readbyte (which is indeed the case)*/
+
+ static int readword(tms99xx_state *cpustate, int addr)
+ {
+ if (addr < 0x2000)
+ {
+ }
+ else if ((addr >= 0x8300) && (addr < 0x8400))
+ {
+ }
+ else
+ {
+ cpustate->icount -= 2;
+ return (cpustate->program->read_byte(addr) << 8) + cpustate->program->read_byte(addr + 1);
+ }
+ }
+ static void writeword(tms99xx_state *cpustate, int addr, int data)
+ {
+ if ((addr >= 0x8300) && (addr < 0x8400))
+ {
+ }
+ else if (!(addr < 0x2000))
+ {
+ cpustate->icount -= 2;
+ cpustate->program->write_byte(addr, data >> 8);
+ cpustate->program->write_byte(addr + 1, data & 0xff);
+ }
+ }
+
+ static int readbyte(tms99xx_state *cpustate, int addr)
+ {
+ if (addr < 0x2000)
+ {
+ }
+ else if ((addr >= 0x8300) && (addr < 0x8400))
+ {
+ }
+ else
+ {
+ cpustate->icount -= 2;
+ if (addr & 1)
+ {
+ cpustate->extra_byte = cpustate->program->read_byte(addr-1);
+ return cpustate->program->read_byte(addr);
+ }
+ else
+ {
+ int val = cpustate->program->read_byte(addr);
+ cpustate->extra_byte = cpustate->program->read_byte(addr+1);
+ return val;
+ }
+ }
+ }
+ static void writebyte(tms99xx_state *cpustate, int addr, int data)
+ {
+ if ((addr >= 0x8300) && (addr < 0x8400))
+ {
+ }
+ else if (!(addr < 0x2000))
+ {
+ cpustate->icount -= 2;
+ if (addr & 1)
+ {
+ cpustate->program->write_byte(addr-1, cpustate->extra_byte);
+ cpustate->program->write_byte(addr, data);
+ }
+ else
+ {
+ cpustate->program->write_byte(addr, data);
+ cpustate->program->write_byte(addr+1, cpustate->extra_byte);
+ }
+ }
+ }
+
+#elif (TMS99XX_MODEL == TMS9995_ID)
+ /*8-bit external data bus, with on-chip 16-bit RAM, and 16-bit address bus*/
+ /*The code is complex, so we use functions rather than macros*/
+
+ static TIMER_CALLBACK( decrementer_callback );
+
+ static int readword(tms99xx_state *cpustate, int addr)
+ {
+ if ((addr < 0xf000) || (cpustate->is_mp9537))
+ {
+ int reply;
+ cpustate->icount -= cpustate->memory_wait_states_word;
+ reply = cpustate->program->read_byte(addr);
+ return (reply << 8) | cpustate->program->read_byte(addr + 1);
+ }
+ else if (addr < 0xf0fc)
+ {
+ return *(UINT16 *)(& cpustate->RAM[addr - 0xf000]);
+ }
+ else if (addr < 0xfffa)
+ {
+ int reply;
+ cpustate->icount -= cpustate->memory_wait_states_word;
+ reply = cpustate->program->read_byte(addr);
+ return (reply << 8) | cpustate->program->read_byte(addr + 1);
+ }
+ else if (addr < 0xfffc)
+ {
+ /* read decrementer */
+ if (cpustate->decrementer_enabled && !(cpustate->flag & 1))
+ /* timer mode, timer enabled */
+ return cpustate->device->attotime_to_cycles(cpustate->timer->remaining() / 16);
+ else
+ /* event counter mode or timer mode, timer disabled */
+ return cpustate->decrementer_count;
+ }
+ else
+ {
+ return *(UINT16 *)(& cpustate->RAM[addr - 0xff00]);
+ }
+ }
+
+ static void writeword (tms99xx_state *cpustate, int addr, int data)
+ {
+ if ((addr < 0xf000) || (cpustate->is_mp9537))
+ {
+ cpustate->icount -= cpustate->memory_wait_states_word;
+ cpustate->program->write_byte(addr, data >> 8);
+ cpustate->program->write_byte(addr + 1, data & 0xff);
+ }
+ else if (addr < 0xf0fc)
+ {
+ *(UINT16 *)(& cpustate->RAM[addr - 0xf000]) = data;
+ }
+ else if (addr < 0xfffa)
+ {
+ cpustate->icount -= cpustate->memory_wait_states_word;
+ cpustate->program->write_byte(addr, data >> 8);
+ cpustate->program->write_byte(addr + 1, data & 0xff);
+ }
+ else if (addr < 0xfffc)
+ {
+ /* write decrementer */
+ cpustate->decrementer_interval = data;
+ reset_decrementer(cpustate);
+ }
+ else
+ {
+ *(UINT16 *)(& cpustate->RAM[addr - 0xff00]) = data;
+ }
+ }
+
+ static int readbyte(tms99xx_state *cpustate, int addr)
+ {
+ if ((addr < 0xf000) || (cpustate->is_mp9537))
+ {
+ cpustate->icount -= cpustate->memory_wait_states_byte;
+ return cpustate->program->read_byte(addr);
+ }
+ else if (addr < 0xf0fc)
+ {
+ return cpustate->RAM[BYTE_XOR_BE(addr - 0xf000)];
+ }
+ else if (addr < 0xfffa)
+ {
+ cpustate->icount -= cpustate->memory_wait_states_byte;
+ return cpustate->program->read_byte(addr);
+ }
+ else if (addr < 0xfffc)
+ {
+ /* read decrementer */
+ int value;
+
+ if (cpustate->decrementer_enabled && !(cpustate->flag & 1))
+ /* timer mode, timer enabled */
+ value = cpustate->device->attotime_to_cycles(cpustate->timer->remaining() / 16);
+ else
+ /* event counter mode or timer mode, timer disabled */
+ value = cpustate->decrementer_count;
+
+ if (addr & 1)
+ return (value & 0xFF);
+ else
+ return (value >> 8);
+ }
+ else
+ {
+ return cpustate->RAM[BYTE_XOR_BE(addr - 0xff00)];
+ }
+ }
+
+ static void writebyte (tms99xx_state *cpustate, int addr, int data)
+ {
+ if ((addr < 0xf000) || (cpustate->is_mp9537))
+ {
+ cpustate->icount -= cpustate->memory_wait_states_byte;
+ cpustate->program->write_byte(addr, data);
+ }
+ else if (addr < 0xf0fc)
+ {
+ cpustate->RAM[BYTE_XOR_BE(addr - 0xf000)] = data;
+ }
+ else if (addr < 0xfffa)
+ {
+ cpustate->icount -= cpustate->memory_wait_states_byte;
+ cpustate->program->write_byte(addr, data);
+ }
+ else if (addr < 0xfffc)
+ {
+ /* write decrementer */
+ /* Note that a byte write to tms9995 timer messes everything up. */
+ cpustate->decrementer_interval = (data << 8) | data;
+ reset_decrementer(cpustate);
+ }
+ else
+ {
+ cpustate->RAM[BYTE_XOR_BE(addr - 0xff00)] = data;
+ }
+ }
+
+#else
+
+ #error "memory access not implemented"
+
+#endif
+
+#if !HAS_MAPPING
+ #define readwordX(cs, addr, map_file) readword(cs, addr)
+ #define writewordX(cs, addr, data, map_file) writeword(cs, (addr), (data))
+ #define readbyteX(cs, addr, map_file) readbyte(cs, addr)
+ #define writebyteX(cs, addr, data, map_file) writebyte(cs, (addr), (data))
+#endif
+
+#define READREG(reg) readword(cpustate, (cpustate->WP+(reg)) & 0xffff)
+#define WRITEREG(reg, data) writeword(cpustate, (cpustate->WP+(reg)) & 0xffff, (data))
+
+INLINE UINT16 READREG_DEBUG(tms99xx_state *cpustate, int reg)
+{
+ int temp = cpustate->icount;
+ UINT16 result = READREG(reg);
+ cpustate->icount = temp;
+ return result;
+}
+
+INLINE void WRITEREG_DEBUG(tms99xx_state *cpustate, int reg, UINT16 data)
+{
+ int temp = cpustate->icount;
+ WRITEREG(reg, data);
+ cpustate->icount = temp;
+}
+
+#if (TMS99XX_MODEL == TI990_10_ID)
+ READ8_HANDLER(ti990_10_mapper_cru_r)
+ {
+ tms99xx_state *cpustate = get_safe_token(&space->device());
+ int reply = 0;
+
+ switch(cpustate->mapper_cru_read_register)
+ {
+ case 0xb000:
+ reply = cpustate->map_files[cpustate->cur_map].B[0];
+ break;
+ case 0xb001:
+ reply = cpustate->map_files[cpustate->cur_map].B[1];
+ break;
+ case 0xb010:
+ reply = cpustate->map_files[cpustate->cur_map].B[2];
+ break;
+ case 0xb011:
+ reply = cpustate->map_files[cpustate->cur_map].L[0];
+ break;
+ case 0xb100:
+ reply = cpustate->map_files[cpustate->cur_map].L[1];
+ break;
+ case 0xb101:
+ reply = cpustate->map_files[cpustate->cur_map].L[2];
+ break;
+ case 0xb110:
+ reply = cpustate->mapper_address_latch;
+ break;
+ case 0xb111:
+ reply = cpustate->mapper_address_latch >> 16;
+ break;
+ }
+
+ if (offset)
+ return (reply >> 8) & 0xff;
+ else
+ return reply & 0xff;
+ }
+
+ WRITE8_HANDLER(ti990_10_mapper_cru_w)
+ {
+ tms99xx_state *cpustate = get_safe_token(&space->device());
+ switch (offset)
+ {
+ case 0:
+ case 1:
+ case 2:
+ /* read register select */
+ if (data)
+ cpustate->mapper_cru_read_register |= (1 << offset);
+ else
+ cpustate->mapper_cru_read_register &= ~ (1 << offset);
+ break;
+ case 3:
+ /* enable mapping */
+ cpustate->mapping_on = data;
+ break;
+ case 4:
+ /* reset flags */
+ cpustate->reset_maperr = data;
+ if (data)
+ {
+ cpustate->error_interrupt_register &= ~ EIR_MAPERR;
+ cpustate->diaglat = 0;
+ }
+ break;
+ case 5:
+ case 6:
+ case 7:
+ /* latch control */
+ cpustate->latch_control[7-offset] = data;
+ break;
+ }
+ }
+
+ INLINE void handle_error_interrupt(tms99xx_state *cpustate)
+ {
+ if (cpustate->error_interrupt_callback)
+ (*cpustate->error_interrupt_callback)(cpustate->device, cpustate->error_interrupt_register ? 1 : 0);
+ }
+
+ READ8_HANDLER(ti990_10_eir_cru_r)
+ {
+ tms99xx_state *cpustate = get_safe_token(&space->device());
+ return (offset == 1) ? (cpustate->error_interrupt_register & 0xff) : 0;
+ }
+
+ WRITE8_HANDLER(ti990_10_eir_cru_w)
+ {
+ tms99xx_state *cpustate = get_safe_token(&space->device());
+ if (offset < 4) /* does not work for EIR_MAPERR */
+ {
+ cpustate->error_interrupt_register &= ~ (1 << offset);
+
+ handle_error_interrupt(cpustate);
+ }
+ }
+
+
+#endif
+
+/* Interrupt mask */
+#define IMASK (cpustate->STATUS & ST_IM)
+
+/*
+ CYCLES macro : you provide timings for tms9900 and tms9995, and the macro chooses for you.
+
+ BTW, I have no idea what the timings are for tms9989 and tms99xxx...
+*/
+#if TMS99XX_MODEL == TI990_10_ID
+ /* Use TI990/10 timings*/
+ #define CYCLES(a,b,c) cpustate->icount -= a
+#elif TMS99XX_MODEL <= TMS9985_ID
+ /* Use TMS9900/TMS9980 timings*/
+ #define CYCLES(a,b,c) cpustate->icount -= b
+#else
+ /* Use TMS9995 timings*/
+ #define CYCLES(a,b,c) cpustate->icount -= c*4
+#endif
+
+#if (TMS99XX_MODEL == TMS9995_ID)
+
+static void set_flag0(tms99xx_state *cpustate, int val);
+static void set_flag1(tms99xx_state *cpustate, int val);
+
+#endif
+
+/************************************************************************
+ * Status register functions
+ ************************************************************************/
+#include "99xxstat.h"
+
+/**************************************************************************/
+
+static void register_for_save_state(device_t *device)
+{
+ tms99xx_state *cpustate = get_safe_token(device);
+ device->save_item(NAME(cpustate->WP));
+ device->save_item(NAME(cpustate->PC));
+ device->save_item(NAME(cpustate->STATUS));
+ device->save_item(NAME(cpustate->interrupt_pending));
+
+#if ! ((TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID))
+ device->save_item(NAME(cpustate->load_state));
+#endif
+
+#if (TMS99XX_MODEL == TI990_10_ID) || (TMS99XX_MODEL == TMS9900_ID) || (TMS99XX_MODEL == TMS9980_ID)
+ device->save_item(NAME(cpustate->irq_level));
+ device->save_item(NAME(cpustate->irq_state));
+#elif (TMS99XX_MODEL == TMS9995_ID)
+ device->save_item(NAME(cpustate->irq_level));
+ device->save_item(NAME(cpustate->int_state));
+ device->save_item(NAME(cpustate->int_latch));
+#endif
+
+ device->save_item(NAME(cpustate->IDLE));
+
+#if HAS_MAPPING
+ device->save_item(NAME(cpustate->mapping_on));
+ device->save_item(NAME(cpustate->map_files[0].L));
+ device->save_item(NAME(cpustate->map_files[0].B));
+ device->save_item(NAME(cpustate->map_files[0].limit));
+ device->save_item(NAME(cpustate->map_files[0].bias));
+ device->save_item(NAME(cpustate->map_files[1].L));
+ device->save_item(NAME(cpustate->map_files[1].B));
+ device->save_item(NAME(cpustate->map_files[1].limit));
+ device->save_item(NAME(cpustate->map_files[1].bias));
+ device->save_item(NAME(cpustate->map_files[2].L));
+ device->save_item(NAME(cpustate->map_files[2].B));
+ device->save_item(NAME(cpustate->map_files[2].limit));
+ device->save_item(NAME(cpustate->map_files[2].bias));
+ device->save_item(NAME(cpustate->cur_map));
+ device->save_item(NAME(cpustate->cur_src_map));
+ device->save_item(NAME(cpustate->cur_dst_map));
+
+#if (TMS99XX_MODEL == TI990_10_ID)
+ device->save_item(NAME(cpustate->reset_maperr));
+ device->save_item(NAME(cpustate->mapper_address_latch));
+ device->save_item(NAME(cpustate->mapper_cru_read_register));
+ device->save_item(NAME(cpustate->diaglat));
+ device->save_item(NAME(cpustate->latch_control));
+#endif
+#endif
+
+#if (TMS99XX_MODEL == TI990_10_ID)
+ device->save_item(NAME(cpustate->error_interrupt_register));
+#endif
+
+#if (TMS99XX_MODEL == TMS9985_ID) || (TMS99XX_MODEL == TMS9995_ID)
+ device->save_item(NAME(cpustate->RAM));
+#endif
+
+#if (TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID) || (TMS99XX_MODEL == TMS9995_ID)
+ device->save_item(NAME(cpustate->decrementer_enabled));
+ device->save_item(NAME(cpustate->decrementer_interval));
+ device->save_item(NAME(cpustate->decrementer_count));
+#endif
+
+#if (TMS99XX_MODEL == TMS9995_ID)
+ device->save_item(NAME(cpustate->flag));
+ device->save_item(NAME(cpustate->MID_flag));
+ device->save_item(NAME(cpustate->memory_wait_states_byte));
+ device->save_item(NAME(cpustate->memory_wait_states_word));
+ device->save_item(NAME(cpustate->is_mp9537));
+#endif
+
+ device->save_item(NAME(cpustate->disable_interrupt_recognition));
+}
+
+
+static CPU_INIT( tms99xx )
+{
+ const TMS99XX_RESET_PARAM *param = (const TMS99XX_RESET_PARAM *) device->static_config();
+ tms99xx_state *cpustate = get_safe_token(device);
+
+ register_for_save_state(device);
+
+ cpustate->irq_level = 16;
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->io = device->space(AS_IO);
+
+#if (TMS99XX_MODEL == TMS9995_ID)
+ cpustate->timer = device->machine().scheduler().timer_alloc(FUNC(decrementer_callback), cpustate);
+#endif
+
+ cpustate->idle_callback = param ? param->idle_callback : NULL;
+ #if (TMS99XX_MODEL == TI990_10_ID)
+ cpustate->rset_callback = param ? param->rset_callback : NULL;
+ cpustate->lrex_callback = param ? param->lrex_callback : NULL;
+ cpustate->ckon_ckof_callback = param ? param->ckon_ckof_callback : NULL;
+
+ cpustate->error_interrupt_callback = param ? param->error_interrupt_callback : NULL;
+ #endif
+
+#if (TMS99XX_MODEL == TMS9995_ID)
+ /* we can ask at reset time that the CPU always generates one wait state automatically */
+ if (param == NULL)
+ { /* if no param, the default is currently "wait state added" */
+ cpustate->memory_wait_states_byte = 4;
+ cpustate->memory_wait_states_word = 12;
+ cpustate->is_mp9537 = 0;
+ }
+ else
+ {
+ cpustate->memory_wait_states_byte = (param->auto_wait_state) ? 4 : 0;
+ cpustate->memory_wait_states_word = (param->auto_wait_state) ? 12 : 4;
+ cpustate->is_mp9537 = param->is_mp9537;
+ }
+#endif
+
+}
+
+/*
+ TMS9900 hard reset
+*/
+static CPU_RESET( tms99xx )
+{
+ tms99xx_state *cpustate = get_safe_token(device);
+
+ cpustate->STATUS = 0; /* TMS9980 and TMS9995 Data Books say so */
+ getstat(cpustate);
+
+ #if HAS_MAPPING
+ cpustate->mapping_on = 0;
+ {
+ int i,j;
+
+ for (i=0; i<3; i++)
+ for (j=0; j<3; j++)
+ {
+ cpustate->map_files[i].L[j] = 0;
+ cpustate->map_files[i].limit[j] = 0xffff;
+ cpustate->map_files[i].B[j] = 0;
+ cpustate->map_files[i].bias[j] = 0;
+ }
+ }
+ cpustate->cur_map = 0; /* equivalent to ST_MF status bit */
+ cpustate->cur_src_map = 0; /* set to 2 by LDS */
+ cpustate->cur_dst_map = 0; /* set to 2 by LDD */
+
+ cpustate->reset_maperr = 0;
+ #endif
+
+ if (cpustate->IDLE)
+ {
+ cpustate->IDLE = 0; /* clear IDLE condition */
+ if (cpustate->idle_callback)
+ (*cpustate->idle_callback)(device, 0);
+ }
+
+#if (TMS99XX_MODEL == TMS9995_ID)
+ cpustate->MID_flag = 0;
+
+ /* Clear flag bits 0 & 1 */
+ set_flag0(cpustate, 0);
+ set_flag1(cpustate, 0);
+
+ /* Clear internal interrupt latches */
+ cpustate->int_latch = 0;
+ cpustate->flag &= 0xFFE3;
+#endif
+
+ /* The ST register and interrupt latches changed, didn't they ? */
+ field_interrupt(cpustate);
+
+ contextswitchX(cpustate, 0x0000);
+
+ CYCLES(6, 26, 14);
+}
+
+static CPU_EXIT( tms99xx )
+{
+ /* nothing to do ? */
+}
+
+/* fetch : read one word at * PC, and increment PC. */
+INLINE UINT16 fetch(tms99xx_state *cpustate)
+{
+ UINT16 value = readword(cpustate, cpustate->PC);
+ cpustate->PC += 2;
+ return value;
+}
+
+
+static CPU_EXECUTE( tms99xx )
+{
+ tms99xx_state *cpustate = get_safe_token(device);
+
+ cpustate->lds_flag = 0;
+ cpustate->ldd_flag = 0;
+
+ do
+ {
+ /* all TMS9900 chips I know do not honor interrupts after XOP, BLWP or MID (after any
+ interrupt-like instruction, actually), and they do not either after LDS and LDD
+ (There are good reasons for this). */
+ if ((cpustate->interrupt_pending) && (! cpustate->disable_interrupt_recognition))
+ {
+ int level;
+
+ level = cpustate->irq_level;
+
+
+ if (cpustate->load_state)
+ { /* LOAD has the highest priority */
+
+ contextswitchX(cpustate, 0xFFFC); /* load vector, save PC, WP and ST */
+
+ cpustate->STATUS &= ~ST_IM; /* clear interrupt mask */
+
+ /* clear IDLE status if necessary */
+ if (cpustate->IDLE)
+ {
+ cpustate->IDLE = 0; /* clear IDLE condition */
+ if (cpustate->idle_callback)
+ (*cpustate->idle_callback)(device, 0);
+ }
+
+ CYCLES(6/*to be confirmed*/, 22, 14);
+ }
+ else if (level <= IMASK)
+ { /* a maskable interrupt is honored only if its level isn't greater than IMASK */
+
+ contextswitchX(cpustate, level*4); /* load vector, save PC, WP and ST */
+
+ /* change interrupt mask */
+ if (level)
+ {
+ cpustate->STATUS = (cpustate->STATUS & ~ST_IM) | (level -1); /* decrement mask */
+ cpustate->interrupt_pending = 0; /* as a consequence, the interrupt request will be subsequently ignored */
+ }
+ else
+ cpustate->STATUS &= ~ST_IM; /* clear mask (is this correct???) */
+
+#if (TMS99XX_MODEL == TMS9995_ID)
+ cpustate->STATUS &= 0xFE00;
+#endif
+
+ /* clear IDLE status if necessary */
+ if (cpustate->IDLE)
+ {
+ cpustate->IDLE = 0; /* clear IDLE condition */
+ if (cpustate->idle_callback)
+ (*cpustate->idle_callback)(device, 0);
+ }
+
+#if (TMS99XX_MODEL == TMS9995_ID)
+ /* Clear bit in latch */
+ /* I think tms9989 does this, too */
+ if (level != 2)
+ { /* Only do this on level 1, 3, 4 interrupts */
+ int mask = 1 << level;
+ int flag_mask = (level == 1) ? 4 : mask;
+
+ cpustate->int_latch &= ~ mask;
+ cpustate->flag &= ~ flag_mask;
+
+ /* unlike tms9900, we can call the callback */
+ if (level == 1)
+ (* cpustate->irq_callback)(cpustate->device, 0);
+ else if (level == 4)
+ (* cpustate->irq_callback)(cpustate->device, 1);
+ }
+#endif
+
+ CYCLES(6, 22, 14);
+ }
+ else
+ {
+ logerror("tms9900.c : the interrupt_pending flag was set incorrectly\n");
+ cpustate->interrupt_pending = 0;
+ }
+ }
+
+ debugger_instruction_hook(device, cpustate->PC);
+
+ if (cpustate->IDLE)
+ { /* IDLE instruction has halted execution */
+ #if EXTERNAL_INSTRUCTION_DECODING
+ external_instruction_notify(cpustate, 2);
+ CYCLES(Moof!, 2, 2); /* 2 cycles per CRU write */
+ #else
+ cpustate->icount = 0; /* much simpler... */
+ #endif
+ }
+ else
+ { /* we execute an instruction */
+ cpustate->disable_interrupt_recognition = 0; /* default value */
+ cpustate->IR = fetch(cpustate);
+ execute(cpustate, cpustate->IR);
+ #if HAS_MAPPING
+ if (cpustate->lds_flag)
+ {
+ cpustate->lds_flag = 0;
+ cpustate->cur_src_map = 2 /*(cpustate->cur_src_map != 2) ? 2 : cpustate->cur_map*/;
+ }
+ else
+ cpustate->cur_src_map = cpustate->cur_map;
+ if (cpustate->ldd_flag)
+ {
+ cpustate->ldd_flag = 0;
+ cpustate->cur_dst_map = 2 /*(cpustate->cur_src_map != 2) ? 2 : cpustate->cur_map*/;
+ }
+ else
+ cpustate->cur_dst_map = cpustate->cur_map;
+ #if (TMS99XX_MODEL == TI990_10_ID)
+ cpustate->write_inhibit = 0;
+ #endif
+ #endif
+
+ #if (HAS_OVERFLOW_INTERRUPT)
+ #if (TMS99XX_MODEL == TMS9995_ID)
+ /* Note that TI had some problem implementing this... I don't know if this feature works on
+ a real-world TMS9995. */
+ if ((cpustate->STATUS & ST_OVIE) && (cpustate->STATUS & ST_OV) && (cpustate->irq_level > 2))
+ cpustate->irq_level = 2; /* interrupt request */
+ #else
+ #warning "todo..."
+ #endif
+ #endif
+ }
+
+ } while (cpustate->icount > 0);
+}
+
+#if (TMS99XX_MODEL == TI990_10_ID)
+
+static void tms99xx_set_irq_line(tms99xx_state *cpustate, int irqline, int state)
+{
+ if (irqline == INPUT_LINE_NMI)
+ {
+ cpustate->load_state = state; /* save new state */
+
+ field_interrupt(cpustate); /* interrupt status changed */
+ }
+ else
+ {
+ /*if (cpustate->irq_state == state)
+ return;*/
+
+ cpustate->irq_state = state;
+
+ if (state == CLEAR_LINE)
+ cpustate->irq_level = 16;
+ /* trick : 16 will always be bigger than the IM (0-15), so there will never be interrupts */
+ else
+ cpustate->irq_level = (* cpustate->irq_callback)(cpustate->device, 0);
+
+ field_interrupt(cpustate); /* interrupt state is likely to have changed */
+ }
+}
+
+#elif (TMS99XX_MODEL == TMS9900_ID)
+
+/*
+void tms99xx_set_irq_line(cpustate, INPUT_LINE_NMI, int state) : change the state of the LOAD* line
+
+ state == 0 -> LOAD* goes high (inactive)
+ state != 0 -> LOAD* goes low (active)
+
+ While LOAD* is low, we keep triggering LOAD interrupts...
+
+ A problem : some peripherals lower the LOAD* line for a fixed time interval (causing the 1st
+ instruction of the LOAD interrupt routine to be repeated while the line is low), and will be
+ perfectly happy with the current scheme, but others might be more clever and wait for the IAQ
+ (Instruction acquisition) line to go high, and this needs a callback function to emulate.
+*/
+
+/*
+void tms99xx_set_irq_line(cpustate, int irqline, int state) : sets the state of the interrupt line.
+
+ irqline is ignored, and should always be 0.
+
+ state == 0 -> INTREQ* goes high (inactive)
+ state != 0 -> INTREQ* goes low (active)
+*/
+/*
+ R Nabet 991020, revised 991218 :
+ In short : interrupt code should call "cpu_set_irq_line(0, 0, ASSERT_LINE);" to set an
+ interrupt request (level-triggered interrupts). Also, there MUST be a call to
+ "cpu_set_irq_line(0, 0, CLEAR_LINE);" in the machine code, when the interrupt line is released by
+ the hardware (generally in response to an action performed by the interrupt routines).
+ On tms9995 (9989 ?), you can use PULSE_LINE, too, since the processor latches the line...
+
+ **Note** : HOLD_LINE *NEVER* makes sense on the TMS9900 (or 9980, 9995...). The reason is the
+ TMS9900 does NOT tell the world it acknoledges an interrupt, so no matter how much hardware you
+ use, you cannot know when the CPU takes the interrupt, hence you cannot release the line when
+ the CPU takes the interrupt. Generally, the interrupt condition is cleared by the interrupt
+ routine (with some CRU or memory access).
+
+ Note that cpu_generate_interrupt uses HOLD_LINE, so your driver interrupt code
+ should always use the new style, i.e. return "ignore_interrupt(cpustate)" and call
+ "cpu_set_irq_line(0, 0, ASSERT_LINE);" explicitely.
+
+ Last, many TMS9900-based hardware use a TMS9901 interrupt-handling chip. If anybody wants
+ to emulate some hardware which uses it, note that I am writing some emulation in the TI99/4(A)
+ driver in MESS, so you should ask me.
+*/
+/*
+ * HJB 990430: changed to use irq_callback(cpustate) to retrieve the vector
+ * instead of using 16 irqlines.
+ *
+ * R Nabet 990830 : My mistake, I rewrote all these once again ; I think it is now correct.
+ * A driver using the TMS9900 should do :
+ * cpu_0_irq_line_vector_w(0, level);
+ * cpu_set_irq_line(0,0,ASSERT_LINE);
+ *
+ * R Nabet 991108 : revised once again, with advice from Juergen Buchmueller, after a discussion
+ * with Nicola...
+ * We use the callback to retreive the interrupt level as soon as INTREQ* is asserted.
+ * As a consequence, I do not support HOLD_LINE normally... However, we do not really have to
+ * support HOLD_LINE, since no real world TMS9900-based system can support this.
+ * FYI, there are two alternatives to retreiving the interrupt level with the callback :
+ * a) using 16 pseudo-IRQ lines. Mostly OK, though it would require a few core changes.
+ * However, this could cause some problems if someone tried to set two lines simulteanously...
+ * And TMS9900 did NOT have 16 lines ! This is why Juergen and I did not retain this solution.
+ * b) modifying the interrupt system in order to provide an extra int to every xxx_set_irq_line
+ * function. I think this solution would be fine, but it would require quite a number of
+ * changes in the MAME core. (And I did not feel the courage to check out 4000 drivers and 25
+ * cpu cores ;-) .)
+ *
+ * Note that this does not apply to tms9995.
+*/
+static void tms99xx_set_irq_line(tms99xx_state *cpustate, int irqline, int state)
+{
+ if (irqline == INPUT_LINE_NMI)
+ {
+ cpustate->load_state = state; /* save new state */
+
+ field_interrupt(cpustate); /* interrupt status changed */
+ }
+ else
+ {
+ /*if (cpustate->irq_state == state)
+ return;*/
+
+ cpustate->irq_state = state;
+
+ if (state == CLEAR_LINE)
+ cpustate->irq_level = 16;
+ /* trick : 16 will always be bigger than the IM (0-15), so there will never be interrupts */
+ else
+ cpustate->irq_level = (* cpustate->irq_callback)(cpustate->device, 0);
+
+ field_interrupt(cpustate); /* interrupt state is likely to have changed */
+ }
+}
+
+#elif (TMS99XX_MODEL == TMS9980_ID)
+/*
+ interrupt system similar to tms9900, but only 3 interrupt pins (IC0-IC2)
+*/
+
+static void tms99xx_set_irq_line(tms99xx_state *cpustate, int irqline, int state)
+{
+ if (state == CLEAR_LINE)
+ {
+ cpustate->load_state = 0;
+ cpustate->irq_state = 0;
+ cpustate->irq_level = 16;
+ /* trick : 16 will always be bigger than the IM (0-15), so there will never be interrupts */
+ }
+ else
+ {
+ int level;
+
+ if (irqline == INPUT_LINE_NMI)
+ level = 2; /* translate MAME's convention to CPU's representation */
+ else
+ level = (* cpustate->irq_callback)(cpustate->device, 0);
+
+ switch (level)
+ {
+ case 0:
+ case 1:
+ cpustate->load_state = 0;
+ cpustate->irq_state = 0;
+ cpustate->irq_level = 16;
+ CPU_RESET_NAME(tms99xx)(cpustate->device);
+ break;
+ case 2:
+ cpustate->load_state = 1;
+ cpustate->irq_state = 0;
+ cpustate->irq_level = 16;
+ break;
+ case 7:
+ cpustate->load_state = 0;
+ cpustate->irq_state = 0;
+ cpustate->irq_level = 16;
+ break;
+ default: /* external levels 1, 2, 3, 4 */
+ cpustate->load_state = 0;
+ cpustate->irq_state = 1;
+ cpustate->irq_level = level - 2;
+ break;
+ }
+ }
+
+ field_interrupt(cpustate); /* interrupt state is likely to have changed */
+}
+
+#elif (TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID)
+/*
+ 2 interrupt pins (int1 and int2)
+*/
+
+static void tms99xx_set_irq_line(tms99xx_state *cpustate, int irqline, int state)
+{
+ int mask;
+
+ if (irqline == 0)
+ /* INT1 */
+ mask = 1;
+ else if (irqline == 1)
+ /* INT2 */
+ mask = 4;
+ else
+ /* What on earth??? */
+ return;
+
+ if (state)
+ cpustate->irq_state |= mask;
+ else
+ cpustate->irq_state &= ~mask;
+
+ field_interrupt(cpustate); /* interrupt state is likely to have changed */
+}
+
+#elif (TMS99XX_MODEL == TMS9995_ID)
+/*
+ this call-back is called by MESS timer system when the timer reaches 0.
+*/
+static TIMER_CALLBACK( decrementer_callback )
+{
+ tms99xx_state *cpustate = (tms99xx_state *)ptr;
+
+ /* request decrementer interrupt */
+ cpustate->int_latch |= 0x8;
+ cpustate->flag |= 0x8;
+
+ field_interrupt(cpustate);
+}
+
+
+/*
+ reset and load the timer/decrementer
+
+ Note that I don't know whether toggling flag0/flag1 causes the decrementer to be reloaded or not
+*/
+static void reset_decrementer(tms99xx_state *cpustate)
+{
+ cpustate->timer->adjust(attotime::never);
+
+ /* reload count */
+ cpustate->decrementer_count = cpustate->decrementer_interval;
+
+ /* decrementer / timer enabled ? */
+ cpustate->decrementer_enabled = ((cpustate->flag & 2) && (cpustate->decrementer_interval));
+
+ if (cpustate->decrementer_enabled && ! (cpustate->flag & 1))
+ { /* timer */
+ attotime period = cpustate->device->cycles_to_attotime(cpustate->decrementer_interval * 16L);
+ cpustate->timer->adjust(period, 0, period);
+ }
+}
+
+/*
+ You have two interrupt line : one triggers level-1 interrupts, the other triggers level-4
+ interrupts (or decrements the decrementer register).
+
+ According to the hardware, you may use PULSE_LINE (edge-triggered interrupts), or ASSERT_LINE
+ (level-triggered interrupts). Edge-triggered interrupts are way simpler, but if multiple devices
+ share the same line, they must use level-triggered interrupts.
+*/
+static void tms99xx_set_irq_line(tms99xx_state *cpustate, int irqline, int state)
+{
+ if (irqline == INPUT_LINE_NMI)
+ {
+ cpustate->load_state = state; /* save new state */
+
+ field_interrupt(cpustate); /* interrupt status changed */
+ }
+ else
+ {
+ int mask = (irqline == 0) ? 0x2 : 0x10;
+ int flag_mask = (irqline == 0) ? 0x4 : 0x10;
+
+ if (((cpustate->int_state & mask) != 0) ^ (state != 0))
+ { /* only if state changes */
+ if (state)
+ {
+ cpustate->int_state |= mask;
+
+ if ((irqline == 1) && (cpustate->flag & 1))
+ { /* event counter mode : INT4* triggers no interrupt... */
+ if (cpustate->decrementer_enabled)
+ { /* decrement, then interrupt if reach 0 */
+ if ((-- cpustate->decrementer_count) == 0)
+ {
+ decrementer_callback(cpustate->device->machine(), cpustate, 0);
+ cpustate->decrementer_count = cpustate->decrementer_interval; /* reload */
+ }
+ }
+ }
+ else
+ { /* plain interrupt mode */
+ cpustate->int_latch |= mask;
+ cpustate->flag |= flag_mask;
+ }
+ }
+ else
+ {
+ cpustate->int_state &= ~ mask;
+ }
+
+ field_interrupt(cpustate); /* interrupt status changed */
+ }
+ }
+}
+
+#else
+
+#error "interrupt system not implemented"
+
+#endif
+
+/*
+ * field_interrupt
+ *
+ * Determines whether if an interrupt is pending, and sets the revelant flag.
+ *
+ * Called when an interrupt pin (LOAD*, INTREQ*, IC0-IC3) is changed, and when the interrupt mask
+ * is modified.
+ *
+ * By using this flag, we save some compares in the execution loop. Subtle, isn't it ;-) ?
+ *
+ * R Nabet.
+ */
+#if (TMS99XX_MODEL == TI990_10_ID) || (TMS99XX_MODEL == TMS9900_ID) || (TMS99XX_MODEL == TMS9980_ID)
+
+static void field_interrupt(tms99xx_state *cpustate)
+{
+ cpustate->interrupt_pending = ((cpustate->irq_level <= IMASK) || (cpustate->load_state));
+}
+
+#elif (TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID)
+
+static void field_interrupt(tms99xx_state *cpustate)
+{
+ if (cpustate->irq_state & 1)
+ cpustate->irq_level = 1;
+ else if (cpustate->irq_state & 2)
+ cpustate->irq_level = 2;
+ else if (cpustate->irq_state & 4)
+ cpustate->irq_level = 3;
+ else
+ cpustate->irq_level = 4;
+ /* trick : 4 will always be bigger than the IM (0-3), so there will never be interrupts */
+
+ cpustate->interrupt_pending = ((cpustate->irq_level <= IMASK) || (cpustate->load_state));
+}
+
+#elif (TMS99XX_MODEL == TMS9995_ID)
+
+static void field_interrupt(tms99xx_state *cpustate)
+{
+ if (cpustate->load_state)
+ {
+ cpustate->interrupt_pending = 1;
+ }
+ else
+ {
+ int current_int;
+ int level;
+
+ if (cpustate->flag & 1)
+ /* event counter mode : ignore int4* line... */
+ current_int = (cpustate->int_state & ~0x10) | cpustate->int_latch;
+ else
+ /* normal behavior */
+ current_int = cpustate->int_state | cpustate->int_latch;
+
+ if (current_int)
+ /* find first bit to 1 */
+ /* possible values : 1, 3, 4 */
+ for (level=0; ! (current_int & 1); current_int >>= 1, level++)
+ ;
+ else
+ level=16;
+
+ cpustate->irq_level = level;
+
+ cpustate->interrupt_pending = (level <= IMASK);
+ }
+}
+
+#else
+
+#error "field_interrupt(cpustate) not written"
+
+#endif
+
+static CPU_DISASSEMBLE( tms99xx )
+{
+ return Dasm9900(buffer, pc, TMS99XX_MODEL, oprom, opram);
+}
+
+
+/*****************************************************************************/
+/*
+ CRU support code
+
+ The CRU bus is a 1-bit-wide I/O bus. The CPU can read or write bits at random address.
+ Special instructions are dedicated to reading and writing one or several consecutive bits.
+
+
+
+ Note that TMS99000 additionally supports parallel CRU operations, although I don't know how
+ this feature is implemented.
+*/
+
+enum
+{
+#if (TMS99XX_MODEL == TI990_10_ID)
+ /* 3 MSBs do exist, although they are not connected (don't ask...) */
+ CRUAddrBit = 15
+#elif (TMS99XX_MODEL == TMS9900_ID)
+ /* 3 MSBs are always 0 to support external instructions */
+ CRUAddrBit = 12
+#elif (TMS99XX_MODEL == TMS9980_ID)
+ /* 2 bits unused, and 2 MSBs are always 0 to support external instructions */
+ CRUAddrBit = 11
+#elif (TMS99XX_MODEL == TMS9940_ID)
+ /* 9 internal address lines (8 external) */
+ CRUAddrBit = 9
+#elif (TMS99XX_MODEL == TMS9995_ID)
+ /* no such problem here : data bus lines D0-D2 provide the external instruction code */
+ CRUAddrBit = 15
+#else
+ #warning "I don't know how your processor handles CRU."
+ CRUAddrBit = 15
+#endif
+};
+
+enum
+{
+ rCRUAddrMask = (1 << (CRUAddrBit - 3)) - 1,
+ wCRUAddrMask = (1 << CRUAddrBit) - 1
+};
+
+
+#if (TMS99XX_MODEL == TMS9995_ID)
+
+/* set decrementer mode flag */
+static void set_flag0(tms99xx_state *cpustate, int val)
+{
+ if (val)
+ cpustate->flag |= 1;
+ else
+ cpustate->flag &= ~ 1;
+
+ reset_decrementer(cpustate);
+}
+
+/* set decrementer enable flag */
+static void set_flag1(tms99xx_state *cpustate, int val)
+{
+ if (val)
+ cpustate->flag |= 2;
+ else
+ cpustate->flag &= ~ 2;
+
+ reset_decrementer(cpustate);
+}
+
+#endif
+
+typedef enum
+{
+ CRU_OK = 0,
+ CRU_PRIVILEGE_VIOLATION = -1
+} cru_error_code;
+
+#define WRITEPORT(cs, port, data) (cs)->io->write_byte(port, data)
+
+#if (TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID)
+/* on tms9940, we have to handle internal CRU ports */
+static void write_single_CRU(tms99xx_state *cpustate, int port, int data)
+{
+ int mask;
+
+ if (! (port & 0x100))
+ {
+ /*if (cpustate->config & CB0)*/
+ /* External CRU */
+ WRITEPORT(cpustate, port, (data & 0x01));
+ }
+ else
+ {
+ /* internal CRU */
+ switch ((port >> 4) & 0xf)
+ {
+ case 0x8:
+ if (port == 0x181)
+ {
+ /* clear decrementer interrupt */
+ cpustate->irq_state &= ~2;
+ }
+ if (port >= 0x183) && (port <= 0x186)
+ {
+ /* write configuration register */
+ mask = 1 << (port - 0x183);
+ /* ... */
+ }
+ break;
+
+ case 0x9:
+ if (port <= 0x19D)
+ {
+ /* write decrementer latch */
+ mask = 1 << (port - 0x190);
+ /* ... */
+ }
+ else if (port == 0x19E)
+ {
+ /* set decrementer as timer (1) or event counter (0) */
+ /* ... */
+ }
+ break;
+
+ case 0xA:
+ /* multiprocessor system interface */
+ mask = 1 << (port - 0x1A0);
+ /* ... */
+ break;
+
+ case 0xB:
+ /* flags */
+ mask = 1 << (port - 0x1B0);
+ /* ... */
+ break;
+
+ case 0xC:
+ case 0xD:
+ /* direction for P0-P31 */
+ mask = 1 << (port - 0x1C0);
+ /* ... */
+ break;
+
+ case 0xE:
+ case 0xF:
+ /* data for P0-P31 */
+ mask = 1 << (port - 0x1E0);
+ /* ... */
+ break;
+ }
+ }
+}
+#elif (TMS99XX_MODEL == TMS9995_ID)
+/* on tms9995, we have to handle internal CRU ports */
+static void write_single_CRU(tms99xx_state *cpustate, int port, int data)
+{
+ /* Internal CRU */
+ switch (port)
+ {
+ case 0xF70:
+ set_flag0(cpustate, data & 0x01);
+ break;
+ case 0xF71:
+ set_flag1(cpustate, data & 0x01);
+ break;
+ case 0xF72:
+ case 0xF73:
+ case 0xF74:
+ break; /* ignored */
+ case 0xF75:
+ case 0xF76:
+ case 0xF77:
+ case 0xF78:
+ case 0xF79:
+ case 0xF7A:
+ case 0xF7B:
+ case 0xF7C:
+ case 0xF7D:
+ case 0xF7E:
+ case 0xF7F:
+ { /* user defined flags */
+ int mask = 1 << (port - 0xF70);
+ if (data & 0x01)
+ cpustate->flag |= mask;
+ else
+ cpustate->flag &= ~ mask;
+ }
+ break;
+
+ case 0x0FED:
+ /* MID flag */
+ cpustate->MID_flag = data & 0x01;
+ break;
+ }
+ /* External CRU */
+ /* Even though all the registers above are implemented internally, accesses
+ are passed to the external bus, too, and an external device might respond
+ to a write to these CRU address as well (particularly a write to the user
+ flag registers). */
+ WRITEPORT(cpustate, port, (data & 0x01));
+}
+#else
+#define write_single_CRU(cs, port, data) WRITEPORT(cs, port, data)
+#endif
+
+/*
+ performs a normal write to CRU bus (used by SBZ, SBO, LDCR : address range 0 -> 0xFFF)
+*/
+static cru_error_code writeCRU(tms99xx_state *cpustate, int CRUAddr, int Number, UINT16 Value)
+{
+ int count;
+
+ /*logerror("PC %4.4x Write CRU %x for %x =%x\n",cpustate->PC,CRUAddr,Number,Value);*/
+
+ CRUAddr &= wCRUAddrMask;
+
+ /* Write Number bits from CRUAddr */
+
+ for(count=0; count<Number; count++)
+ {
+ #if HAS_PRIVILEGE
+ if ((cpustate->STATUS & ST_PR) && (CRUAddr >= 0xE00))
+ return CRU_PRIVILEGE_VIOLATION;
+ #endif
+
+ write_single_CRU(cpustate, CRUAddr, (Value & 0x01));
+ Value >>= 1;
+ CRUAddr = (CRUAddr + 1) & wCRUAddrMask;
+ }
+
+ return CRU_OK;
+}
+
+#if EXTERNAL_INSTRUCTION_DECODING
+/*
+ Some opcodes perform a dummy write to a special CRU address, so that an external function may be
+ triggered.
+
+ Only the first 3 MSBs of the address matter : other address bits and the written value itself
+ are undefined.
+
+ How should we support this ? With callback functions ? Actually, as long as we do not support
+ hardware which makes use of this feature, it does not really matter :-) .
+*/
+static void external_instruction_notify(tms99xx_state *cpustate, int ext_op_ID)
+{
+#if 1
+ /* I guess we can support this like normal CRU operations */
+#if (TMS99XX_MODEL == TMS9900_ID)
+ WRITEPORT(cpustate, ext_op_ID << 12, 0); /* or is it 1 ??? */
+#elif (TMS99XX_MODEL == TMS9980_ID)
+ WRITEPORT(cpustate, (ext_op_ID & 3) << 11, (ext_op_ID & 4) ? 1 : 0);
+#elif (TMS99XX_MODEL == TMS9995_ID)
+ WRITEPORT(cpustate, ext_op_ID << 15, 0); /* or is it 1 ??? */
+#else
+ #warning "I don't know how your processor handles external opcodes (maybe you don't need them, though)."
+#endif
+
+#else
+ switch (ext_op_ID)
+ {
+ case 2: /* IDLE */
+
+ break;
+ case 3: /* RSET */
+
+ break;
+ case 5: /* CKON */
+
+ break;
+ case 6: /* CKOF */
+
+ break;
+ case 7: /* LREX */
+
+ break;
+ case 0:
+ /* normal CRU write !!! */
+ logerror("PC %4.4x : external_instruction_notify : wrong ext_op_ID",cpustate->PC);
+ break;
+ default:
+ /* unknown address */
+ logerror("PC %4.4x : external_instruction_notify : unknown ext_op_ID",cpustate->PC);
+ break;
+ }
+#endif
+}
+#endif
+
+/*
+ performs a normal read to CRU bus (used by TB, STCR : address range 0->0xFFF)
+
+ Note that on some hardware, e.g. TI99/4(a), all normal memory operations cause unwanted CRU
+ read at the same address. This seems to be impossible to emulate efficiently, so, if you need
+ to emulate this, you're in trouble.
+*/
+#define READPORT(cs, port) (cs)->io->read_byte(port)
+
+
+#if (TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID)
+/* on tms9940, we have to handle internal CRU ports */
+static int read_single_CRU(tms99xx_state *cpustate, int port)
+{
+ int reply;
+ int shift;
+
+ if (! (port & 0x20))
+ {
+ /*if (cpustate->config & CB0)*/
+ /* External CRU */
+ reply = READPORT(cpustate, port, (data & 0x01));
+ }
+ else
+ {
+ /* internal CRU */
+ switch (port)
+ {
+ case 0x10:
+ /* read interrupt state */
+ reply = cpustate->irq_state;
+ break;
+
+ case 0x12:
+ /* read decrementer LSB */
+ /* ... */
+ break;
+ case 0x13:
+ /* read decrementer MSB */
+ /* ... */
+ break;
+
+ case 0x14:
+ /* read multiprocessor system interface LSB */
+ /* ... */
+ break;
+ case 0x15:
+ /* read multiprocessor system interface MSB */
+ /* ... */
+ break;
+
+ case 0x16:
+ /* read flags LSB */
+ /* ... */
+ break;
+ case 0x17:
+ /* read flags MSB */
+ /* ... */
+ break;
+
+ case 0x18:
+ case 0x19:
+ case 0x1A:
+ case 0x1B:
+ /* direction for P0-P31 */
+ shift = (port - 0x18) << 3;
+ /* ... */
+ break;
+
+ case 0x1C:
+ case 0x1D:
+ case 0x1E:
+ case 0x1F:
+ /* data for P0-P31 */
+ shift = (port - 0x1C) << 3;
+ /* ... */
+ break;
+
+ default:
+ reply = 0;
+ break;
+ }
+ }
+
+ return reply;
+}
+#elif (TMS99XX_MODEL == TMS9995_ID)
+/* on tms9995, we have to handle internal CRU ports */
+static int read_single_CRU(tms99xx_state *cpustate, int port)
+{
+ switch (port)
+ {
+ case 0x1EE:
+ /* flag, bits 0-7 */
+ return cpustate->flag & 0xFF;
+ case 0x1EF:
+ /* flag, bits 8-15 */
+ return (cpustate->flag >> 8) & 0xFF;
+ case 0x1FD:
+ /* MID flag, and external devices */
+ if (cpustate->MID_flag)
+ return READPORT(cpustate, port) | 0x10;
+ else
+ return READPORT(cpustate, port) & ~ 0x10;
+ default:
+ /* external devices */
+ return READPORT(cpustate, port);
+ }
+}
+#else
+#define read_single_CRU(cs, port) READPORT(cs, port)
+#endif
+
+static int readCRU(tms99xx_state *cpustate, int CRUAddr, int Number)
+{
+ static const int BitMask[] =
+ {
+ 0, /* filler - saves a subtract to find mask */
+ 0x0001,0x0003,0x0007,0x000F,0x001F,0x003F,0x007F,0x00FF,
+ 0x01FF,0x03FF,0x07FF,0x0FFF,0x1FFF,0x3FFF,0x7FFF,0xFFFF
+ };
+
+ int Offset,Location,Value;
+
+ /*logerror("Read CRU %x for %x\n",CRUAddr,Number);*/
+
+ Location = (CRUAddr >> 3) & rCRUAddrMask;
+ Offset = CRUAddr & 07;
+
+ /* Read 8 bits */
+ #if HAS_PRIVILEGE
+ if ((cpustate->STATUS & ST_PR) && (Location >= (0xE00 >> 3)))
+ return CRU_PRIVILEGE_VIOLATION;
+ #endif
+ Value = read_single_CRU(cpustate, Location);
+
+ if ((Offset+Number) > 8)
+ {
+ /* Read next 8 bits */
+ Location = (Location + 1) & rCRUAddrMask;
+ #if HAS_PRIVILEGE
+ if ((cpustate->STATUS & ST_PR) && (Location >= (0xE00 >> 3)))
+ return CRU_PRIVILEGE_VIOLATION;
+ #endif
+ Value |= read_single_CRU(cpustate, Location) << 8;
+
+ if ((Offset+Number) > 16)
+ {
+ /* Read next 8 bits */
+ Location = (Location + 1) & rCRUAddrMask;
+ #if HAS_PRIVILEGE
+ if ((cpustate->STATUS & ST_PR) && (Location >= (0xE00 >> 3)))
+ return CRU_PRIVILEGE_VIOLATION;
+ #endif
+ Value |= read_single_CRU(cpustate, Location) << 16;
+ }
+ }
+
+ /* Allow for Offset */
+ Value >>= Offset;
+
+ /* Mask out what we want */
+ Value &= BitMask[Number];
+
+ /* And update */
+ return Value;
+}
+
+/*****************************************************************************/
+
+#if HAS_MAPPING
+/* load a map file from memory */
+static void load_map_file(tms99xx_state *cpustate, UINT16 src_addr, int src_map_file, int dst_file)
+{
+ int i;
+
+
+ /* load mapped address into the memory address register */
+ if ((src_map_file == 0) && (src_addr >= 0xf800))
+ { /* intercept TPCS and CPU ROM */
+ if (src_addr < 0xfc00)
+ /* TPCS */
+ cpustate->mapper_address_latch = 0x1f0000+src_addr;
+ else
+ /* CPU ROM */
+ cpustate->mapper_address_latch = 0x1f0000+src_addr; /* hack... */
+ }
+ else if (! cpustate->mapping_on)
+ {
+ cpustate->mapper_address_latch = src_addr;
+ }
+ else
+ {
+ int map_index;
+
+ if (src_addr <= cpustate->map_files[src_map_file].limit[0])
+ map_index = 0;
+ else if (src_addr <= cpustate->map_files[src_map_file].limit[1])
+ map_index = 1;
+ else if (src_addr <= cpustate->map_files[src_map_file].limit[2])
+ map_index = 2;
+ else
+ {
+ if ((! cpustate->reset_maperr) && ! (cpustate->error_interrupt_register & EIR_MAPERR))
+ {
+ cpustate->error_interrupt_register |= EIR_MAPERR;
+ cpustate->write_inhibit = 1;
+ }
+ cpustate->mapper_address_latch = src_addr;
+ map_index = -1;
+ }
+ if (map_index != -1)
+ cpustate->mapper_address_latch = cpustate->map_files[src_map_file].bias[map_index]+src_addr;
+ }
+
+
+ for (i=0; i<3; i++)
+ {
+ cpustate->map_files[dst_file].L[i] = cpustate->program->read_word(cpustate->mapper_address_latch) & 0xffe0;
+ cpustate->map_files[dst_file].limit[i] = (cpustate->map_files[dst_file].L[i] ^ 0xffe0) | 0x001f;
+ cpustate->mapper_address_latch = (cpustate->mapper_address_latch+2) & 0x1fffff;
+ cpustate->map_files[dst_file].B[i] = cpustate->program->read_word(cpustate->mapper_address_latch);
+ cpustate->map_files[dst_file].bias[i] = ((unsigned int) cpustate->map_files[dst_file].B[i]) << 5;
+ cpustate->mapper_address_latch = (cpustate->mapper_address_latch+2) & 0x1fffff;
+ }
+}
+#endif
+
+/* contextswitch : performs a BLWP, i.e. load PC, WP, and save old PC, old WP and ST... */
+static void contextswitch(tms99xx_state *cpustate, UINT16 addr)
+{
+ UINT16 oldWP, oldpc;
+
+ /* save old state */
+ oldWP = cpustate->WP;
+ oldpc = cpustate->PC;
+
+ /* load vector */
+ cpustate->WP = readword(cpustate, addr) & ~1;
+ cpustate->PC = readword(cpustate, addr+2) & ~1;
+
+ /* write old state to regs */
+ WRITEREG(R13, oldWP);
+ WRITEREG(R14, oldpc);
+ setstat(cpustate);
+ WRITEREG(R15, cpustate->STATUS);
+}
+
+#if HAS_MAPPING || HAS_PRIVILEGE
+
+/* priviledged context switch, that occurs after a reset, interrupt or XOP:
+we enter priviledged mode and select map file 0 before doing the context switch */
+/* For CPU that have no priviledge support, contextswitchX would behave
+identically to contextswitch, so we can call contextswitch in all cases. */
+static void contextswitchX(tms99xx_state *cpustate, UINT16 addr)
+{
+ UINT16 oldWP, oldpc, oldST;
+
+ /* save old state */
+ oldWP = cpustate->WP;
+ oldpc = cpustate->PC;
+ setstat(cpustate);
+ oldST = cpustate->STATUS;
+
+ /* enter priviledged mode and select map file 0 */
+ #if HAS_PRIVILEGE
+ cpustate->STATUS &= ~ ST_PR;
+ #endif
+ #if HAS_MAPPING
+ cpustate->STATUS &= ~ ST_MF;
+ #endif
+ getstat(cpustate);
+
+ /* load vector */
+ cpustate->WP = readword(cpustate, addr) & ~1;
+ cpustate->PC = readword(cpustate, addr+2) & ~1;
+
+ /* write old state to regs */
+ WRITEREG(R13, oldWP);
+ WRITEREG(R14, oldpc);
+ WRITEREG(R15, oldST);
+}
+
+#endif
+
+/*
+ * decipheraddr : compute and return the effective address in word instructions.
+ *
+ * NOTA : the LSBit is always ignored in word addresses,
+ * but we do not set it to 0 because of XOP...
+ */
+static UINT16 decipheraddr(tms99xx_state *cpustate, UINT16 opcode)
+{
+ register UINT16 ts = opcode & 0x30;
+ register UINT16 reg = opcode & 0xF;
+
+ reg += reg;
+
+ if (ts == 0)
+ /* Rx */
+ return(reg + cpustate->WP);
+ else if (ts == 0x10)
+ { /* *Rx */
+ CYCLES(0, 4, 1);
+ return(readword(cpustate, reg + cpustate->WP));
+ }
+ else if (ts == 0x20)
+ {
+ register UINT16 imm;
+
+ imm = fetch(cpustate);
+
+ if (reg)
+ { /* @>xxxx(Rx) */
+ CYCLES(1, 8, 3);
+ return(readword(cpustate, reg + cpustate->WP) + imm);
+ }
+ else
+ { /* @>xxxx */
+ CYCLES(3, 8, 1);
+ return(imm);
+ }
+ }
+ else /*if (ts == 0x30)*/
+ { /* *Rx+ */
+ register UINT16 response;
+
+ reg += cpustate->WP; /* reg now contains effective address */
+
+ CYCLES(1, 8, 3);
+
+ response = readword(cpustate, reg);
+ writeword(cpustate, reg, response+2); /* we increment register content */
+ return(response);
+ }
+}
+
+/* decipheraddrbyte : compute and return the effective address in byte instructions. */
+static UINT16 decipheraddrbyte(tms99xx_state *cpustate, UINT16 opcode)
+{
+ register UINT16 ts = opcode & 0x30;
+ register UINT16 reg = opcode & 0xF;
+
+ reg += reg;
+
+ if (ts == 0)
+ /* Rx */
+ return(reg + cpustate->WP);
+ else if (ts == 0x10)
+ { /* *Rx */
+ CYCLES(0, 4, 1);
+ return(readword(cpustate, reg + cpustate->WP));
+ }
+ else if (ts == 0x20)
+ {
+ register UINT16 imm;
+
+ imm = fetch(cpustate);
+
+ if (reg)
+ { /* @>xxxx(Rx) */
+ CYCLES(1, 8, 3);
+ return(readword(cpustate, reg + cpustate->WP) + imm);
+ }
+ else
+ { /* @>xxxx */
+ CYCLES(3, 8, 1);
+ return(imm);
+ }
+ }
+ else /*if (ts == 0x30)*/
+ { /* *Rx+ */
+ register UINT16 response;
+
+ reg += cpustate->WP; /* reg now contains effective address */
+
+ CYCLES(1, 6, 3);
+
+ response = readword(cpustate, reg);
+ writeword(cpustate, reg, response+1); /* we increment register content */
+ return(response);
+ }
+}
+
+
+/*************************************************************************/
+
+#if (TMS99XX_MODEL == TI990_10_ID)
+ /* TI990/10 generates an error interrupt */
+ /* timings are unknown */
+ #define HANDLE_ILLEGAL \
+ { \
+ cpustate->error_interrupt_register |= EIR_ILLOP; \
+ if (cpustate->error_interrupt_callback) \
+ (*cpustate->error_interrupt_callback)(cpustate->device, 1); \
+ }
+#elif TMS99XX_MODEL <= TMS9989_ID
+ /* TMS9900/TMS9980 merely ignore the instruction */
+ #define HANDLE_ILLEGAL cpustate->icount -= 6
+#elif TMS99XX_MODEL == TMS9995_ID
+ /* TMS9995 generates a MID interrupt */
+ #define HANDLE_ILLEGAL \
+ { \
+ cpustate->MID_flag = 1; \
+ contextswitchX(cpustate, 0x0008); \
+ cpustate->STATUS = (cpustate->STATUS & 0xFE00) | 0x1; \
+ cpustate->disable_interrupt_recognition = 1; \
+ }
+#else
+#define HANDLE_ILLEGAL
+#warning "don't know"
+#endif
+
+#if HAS_PRIVILEGE
+ #if (TMS99XX_MODEL == TI990_10_ID)
+ /* TI990/10 generates an error interrupt */
+ /* timings are unknown */
+ #define HANDLE_PRIVILEGE_VIOLATION \
+ { \
+ cpustate->error_interrupt_register |= EIR_PRIVOP; \
+ if (cpustate->error_interrupt_callback) \
+ (*cpustate->error_interrupt_callback)(cpustate->device, 1); \
+ }
+ #else
+ #define HANDLE_PRIVILEGE_VIOLATION
+ #warning "don't know"
+ #endif
+#endif
+
+/*==========================================================================
+ Illegal instructions >0000->01FF (not for 9989 and later)
+ >0C00->0FFF (not for 990/12 and 99110)
+============================================================================*/
+
+static void illegal(tms99xx_state *cpustate, UINT16 opcode)
+{
+ HANDLE_ILLEGAL;
+}
+
+
+#if 0 /* ti990/12 only */
+/*==========================================================================
+ Additionnal instructions, >0000->002F
+ Additionnal single-register instruction, >0030->003F
+ ---------------------------------------------------------------------------
+
+ 0 1 2 3-4 5 6 7+8 9 A B-C D E F
+ ---------------------------------
+ | o p c o d e |
+ | o p c o d e | reg # |
+ ---------------------------------
+
+============================================================================*/
+static void h0000(tms99xx_state *cpustate, UINT16 opcode)
+{
+ if (opcode >= 0x30)
+ { /* STPC STore Program Counter */
+
+ }
+ else
+ {
+ switch (opcode /*& 0x3F*/)
+ {
+ case 0x1C: /* SRAM */
+ /* SRAM -- Shift Right Arithmetic Multiple precision */
+ case 0x1D: /* SLAM */
+ /* SLAM -- Shift Left Arithmetic Multiple precision */
+ case 0x1E:
+ /* RTO --- Right Test for Ones */
+ case 0x1F:
+ /* LTO --- Left Test for Ones */
+ case 0x20:
+ /* CNTO -- CouNT Ones */
+ case 0x21:
+ /* SLSL -- Search LiSt Logical address */
+ case 0x22:
+ /* SLSP -- Search LiSt Physical address */
+ case 0x23:
+ /* BDC --- Binary to Decimal ascii Conversion */
+ case 0x24:
+ /* DBC --- Decimal to Binary ascii Conversion */
+ case 0x25:
+ /* SWPM -- SWaP Multiple precision */
+ case 0x26:
+ /* XORM -- eXclusive OR Multiple precision */
+ case 0x27:
+ /* ORM --- OR Multiple precision */
+ case 0x28:
+ /* ANDM -- AND Multiple precision */
+ case 0x29: /* SM */
+ /* SM ---- Subtract Multiple precision integer */
+ case 0x2A: /* AM */
+ /* AM ---- Add Multiple precision integer */
+ case 0x2B:
+ /* MOVA -- MOVe Address */
+ case 0x2D:
+ /* EMD --- Execute Micro-Diagnostics */
+ case 0x2E:
+ /* EINT -- Enable INTerrupts */
+ case 0x2F:
+ /* DINT -- Disable INTerrupts */
+
+ break;
+
+ default:
+ HANDLE_ILLEGAL;
+ break;
+ }
+ }
+}
+#endif
+
+
+#if HAS_9995_OPCODES
+/*==========================================================================
+ Additionnal single-register instructions, >0040->00FF
+ ---------------------------------------------------------------------------
+
+ 0 1 2 3-4 5 6 7+8 9 A B-C D E F
+ ---------------------------------
+ | o p c o d e | reg # |
+ ---------------------------------
+
+tms9989 and later : LST, LWP
+============================================================================*/
+static void h0040(tms99xx_state *cpustate, UINT16 opcode)
+{
+ register UINT16 addr;
+
+ addr = opcode & 0xF;
+ addr = ((addr + addr) + cpustate->WP) & ~1;
+
+ switch ((opcode & 0xF0) >> 4)
+ {
+ case 8: /* LST */
+ /* LST --- Load STatus register */
+ /* ST = *Reg */
+ #if HAS_PRIVILEGE
+ if (cpustate->STATUS & ST_PR)
+ cpustate->STATUS = (cpustate->STATUS & 0x01DF) | (readword(cpustate, addr) & 0xFE20);
+ else
+ cpustate->STATUS = readword(cpustate, addr);
+ #else
+ cpustate->STATUS = readword(cpustate, addr);
+ #endif
+ getstat(cpustate); /* set last_parity */
+ break;
+
+ case 9: /* LWP */
+ /* LWP --- Load Workspace Pointer */
+ /* WP = *Reg */
+ cpustate->WP = readword(cpustate, addr) & ~1;
+ break;
+
+#if 0 /* 990/12 opcodes */
+ case 4:
+ /* CS ---- Compare Strings */
+ case 5:
+ /* SEQB -- Search string for EQual Byte */
+ case 6:
+ /* MOVS -- MOVe String */
+ case 7:
+ /* LIM --- Load Interrupt Mask */
+
+ case 10:
+ /* LCS --- Load writable Control Store */
+
+ case 11: /* BLSK */
+ /* BLSK -- Branch immediate and push Link to StacK */
+
+ case 12:
+ /* MVSR -- MoVe String Reverse */
+ case 13:
+ /* MVSK -- MoVe string from StacK */
+ case 14:
+ /* POPS -- POP String from stack */
+ case 15:
+ /* PSHS -- PuSH String to stack */
+
+ break;
+#endif
+
+ default:
+ HANDLE_ILLEGAL;
+ break;
+ }
+}
+
+
+/*==========================================================================
+ Additionnal single-operand instructions, >0100->01FF
+ ---------------------------------------------------------------------------
+
+ 0 1 2 3-4 5 6 7+8 9 A B-C D E F
+ ---------------------------------
+ | o p c o d e |TS | S |
+ ---------------------------------
+
+tms9989 and later : DIVS, MPYS
+tms99xxx : BIND
+============================================================================*/
+static void h0100(tms99xx_state *cpustate, UINT16 opcode)
+{
+ register UINT16 src;
+#if HAS_MAPPING
+ int src_map = (opcode & 0x0030) ? cpustate->cur_src_map : cpustate->cur_map;
+#endif
+
+ src = decipheraddr(cpustate, opcode) & ~1;
+
+ switch ((opcode & 0xC0) >> 6)
+ {
+#if HAS_BIND_OPCODE
+ case 1: /* BIND */
+ /* BIND -- Branch INDirect */
+ cpustate->PC = readwordX(cpustate, src, src_map) & ~1;
+ CYCLES(Mooof!, Mooof!, 4 /*don't know*/);
+ break;
+#endif
+
+ case 2: /* DIVS */
+ /* DIVS -- DIVide Signed */
+ /* R0 = (R0:R1)/S R1 = (R0:R1)%S */
+ {
+ INT16 d = readwordX(cpustate, src, src_map);
+ INT32 divq = (READREG(R0) << 16) | READREG(R1);
+ INT32 q = divq/d;
+
+ if ((q < -32768L) || (q > 32767L))
+ {
+ cpustate->STATUS |= ST_OV;
+ CYCLES(Mooof!, Mooof!, 10);
+ }
+ else
+ {
+ cpustate->STATUS &= ~ST_OV;
+ setst_lae(cpustate, q);
+ WRITEREG(R0, q);
+ WRITEREG(R1, divq%d);
+ /* tms9995 : 33 is the worst case */
+ CYCLES(Mooof!, Mooof!, 33);
+ }
+ }
+ break;
+
+ case 3: /* MPYS */
+ /* MPYS -- MultiPlY Signed */
+ /* Results: R0:R1 = R0*S */
+ {
+ INT32 prod = ((INT32) (INT16) readwordX(cpustate, src, src_map));
+ prod = prod*((INT32) (INT16) READREG(R0));
+
+ cpustate->STATUS &= ~ (ST_LGT | ST_AGT | ST_EQ);
+ if (prod > 0)
+ cpustate->STATUS |= (ST_LGT | ST_AGT);
+ else if (prod < 0)
+ cpustate->STATUS |= ST_LGT;
+ else
+ cpustate->STATUS |= ST_EQ;
+
+ WRITEREG(R0, prod >> 16);
+ WRITEREG(R1, prod);
+ }
+ CYCLES(Mooof!, Mooof!, 25);
+ break;
+
+#if 0 /* Origin unknown */
+ case 0: /* EVAD */
+ /* EVAD -- EValuate ADdress instruction */
+
+ break;
+#endif
+
+ default:
+ HANDLE_ILLEGAL;
+ break;
+ }
+}
+#endif
+
+
+/*==========================================================================
+ Immediate, Control instructions, >0200->03FF
+ ---------------------------------------------------------------------------
+
+ 0 1 2 3-4 5 6 7+8 9 A B-C D E F
+ ---------------------------------
+ | o p c o d e |0| reg # |
+ ---------------------------------
+
+ LI, AI, ANDI, ORI, CI, STWP, STST, LIMI, LWPI, IDLE, RSET, RTWP, CKON, CKOF, LREX
+systems with memory mapper: LMF
+============================================================================*/
+static void h0200(tms99xx_state *cpustate, UINT16 opcode)
+{
+ register UINT16 addr;
+ register UINT16 value; /* used for anything */
+
+ addr = opcode & 0xF;
+ addr = ((addr + addr) + cpustate->WP) & ~1;
+
+ #if HAS_MAPPING
+ if ((opcode >= 0x0320) && (opcode < 0x0340))
+ { /* LMF */
+ /* LMF --- Load memory Map File */
+ /* Used by the memory mapper on ti990/10 with mapping option, ti990/12, and the TIM99610
+ mapper chip to be associated with tms99000.
+ Syntax: "LMF Rn,m" loads map file m (0 or 1) with six words of memory, starting at address
+ specified in workspace register Rn (0 through 15). */
+ #if HAS_PRIVILEGE
+ if (cpustate->STATUS & ST_PR)
+ {
+ HANDLE_PRIVILEGE_VIOLATION
+ return;
+ }
+ #endif
+
+ /* read address pointer */
+ addr = readword(cpustate, addr);
+
+ load_map_file(cpustate, addr, cpustate->cur_map, (opcode & 0x10) ? 1 : 0);
+
+ CYCLES(3, Mooof!, Mooof!);
+ return;
+ }
+ #endif
+
+ #if BETTER_0200_DECODING
+ /* better instruction decoding on ti990/10 */
+ if (opcode & 0x10)
+ {
+ HANDLE_ILLEGAL;
+ return;
+ }
+ #elif COMPLETE_0200_DECODING
+ /* full instruction decoding on tms9995 */
+ if (((opcode < 0x2E0) && (opcode & 0x10)) || ((opcode >= 0x2E0) && (opcode & 0x1F)))
+ {
+#if 0
+ /* tms99110 opcode (not supported by 990/12) */
+ if (opcode == 0x0301)
+ { /* CR ---- Compare Reals */
+ }
+ else
+ /* tms99105+tms99110 opcode (not supported by 990/12) */
+ if (opcode == 0x0302)
+ { /* MM ---- Multiply Multiple */
+ }
+ else
+#endif
+ #if 0 /* ti990/12 only */
+ if (opcode >= 0x03F0)
+ { /* EP ---- Extended Precision */
+ }
+ else
+ #endif
+ HANDLE_ILLEGAL;
+ return;
+ }
+ #endif
+
+ switch ((opcode & 0x1e0) >> 5)
+ {
+ case 0: /* LI */
+ /* LI ---- Load Immediate */
+ /* *Reg = *PC+ */
+ value = fetch(cpustate);
+ writeword(cpustate, addr, value);
+ setst_lae(cpustate, value);
+ CYCLES(3, 12, 3);
+ break;
+
+ case 1: /* AI */
+ /* AI ---- Add Immediate */
+ /* *Reg += *PC+ */
+ value = fetch(cpustate);
+ value = setst_add_laeco(cpustate, readword(cpustate, addr), value);
+ writeword(cpustate, addr, value);
+ CYCLES(4, 14, 4);
+ break;
+
+ case 2: /* ANDI */
+ /* ANDI -- AND Immediate */
+ /* *Reg &= *PC+ */
+ value = fetch(cpustate);
+ value = readword(cpustate, addr) & value;
+ writeword(cpustate, addr, value);
+ setst_lae(cpustate, value);
+ CYCLES(4, 14, 4);
+ break;
+
+ case 3: /* ORI */
+ /* ORI --- OR Immediate */
+ /* *Reg |= *PC+ */
+ value = fetch(cpustate);
+ value = readword(cpustate, addr) | value;
+ writeword(cpustate, addr, value);
+ setst_lae(cpustate, value);
+ CYCLES(4, 14, 4);
+ break;
+
+ case 4: /* CI */
+ /* CI ---- Compare Immediate */
+ /* status = (*Reg-*PC+) */
+ value = fetch(cpustate);
+ setst_c_lae(cpustate, value, readword(cpustate, addr));
+ CYCLES(6, 14, 4);
+ break;
+
+ case 5: /* STWP */
+ /* STWP -- STore Workspace Pointer */
+ /* *Reg = WP */
+ writeword(cpustate, addr, cpustate->WP);
+ CYCLES(2, 8, 3);
+ break;
+
+ case 6: /* STST */
+ /* STST -- STore STatus register */
+ /* *Reg = ST */
+ setstat(cpustate);
+ writeword(cpustate, addr, cpustate->STATUS);
+ CYCLES(2, 8, 3);
+ break;
+
+ case 7: /* LWPI */
+ /* LWPI -- Load Workspace Pointer Immediate */
+ /* WP = *PC+ */
+ cpustate->WP = fetch(cpustate) & ~1;
+ CYCLES(3, 10, 4);
+ break;
+
+ case 8: /* LIMI */
+ /* LIMI -- Load Interrupt Mask Immediate */
+ /* ST&15 |= (*PC+)&15 */
+ #if HAS_PRIVILEGE
+ if (cpustate->STATUS & ST_PR)
+ {
+ HANDLE_PRIVILEGE_VIOLATION
+ break;
+ }
+ #endif
+
+ value = fetch(cpustate);
+ cpustate->STATUS = (cpustate->STATUS & ~ST_IM) | (value & ST_IM);
+ field_interrupt(cpustate); /*IM has been modified.*/
+ CYCLES(3, 16, 5);
+ break;
+
+ case 9: /* LMF is implemented elsewhere - when it is implemented */
+ HANDLE_ILLEGAL;
+ break;
+
+ case 10: /* IDLE */
+ /* IDLE -- IDLE until a reset, interrupt, load */
+ /* The TMS99000 locks until an interrupt happen (like with 68k STOP instruction),
+ and continuously performs a special CRU write (code 2). */
+ #if HAS_PRIVILEGE
+ if (cpustate->STATUS & ST_PR)
+ {
+ HANDLE_PRIVILEGE_VIOLATION
+ break;
+ }
+ #endif
+ cpustate->IDLE = 1;
+ #if EXTERNAL_INSTRUCTION_DECODING
+ external_instruction_notify(cpustate, 2);
+ #endif
+ if (cpustate->idle_callback)
+ (*cpustate->idle_callback)(cpustate->device, 1);
+ CYCLES(4, 12, 7);
+ /* we take care of further external_instruction_notify(cpustate, 2); in execute(cpustate) */
+ break;
+
+ case 12: /* RTWP */
+ /* RTWP -- Return with Workspace Pointer */
+ /* WP = R13, PC = R14, ST = R15 */
+ addr = (cpustate->WP + R13) & ~1;
+ cpustate->WP = readword(cpustate, addr) & ~1;
+ addr += 2;
+ cpustate->PC = readword(cpustate, addr) & ~1;
+ addr += 2;
+ #if HAS_PRIVILEGE
+ if (cpustate->STATUS & ST_PR)
+ cpustate->STATUS = (cpustate->STATUS & 0x01DF) | (readword(cpustate, addr) & 0xFE20);
+ else
+ cpustate->STATUS = readword(cpustate, addr);
+ #else
+ cpustate->STATUS = readword(cpustate, addr);
+ #endif
+ getstat(cpustate); /* set last_parity */
+
+ field_interrupt(cpustate); /*IM has been modified.*/
+ CYCLES(3, 14, 6);
+ break;
+
+#if (TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID)
+
+ case 11: /* RSET */
+ case 13: /* CKON */
+ case 14: /* CKOF */
+ case 15: /* LREX */
+ HANDLE_ILLEGAL; /* These instruction "have been deleted" on the TMS9940 */
+ break;
+
+#else
+
+ case 11: /* RSET */
+ /* RSET -- ReSET */
+ /* Reset the Interrupt Mask, and perform a special CRU write (code 3). */
+ /* The CRU write is supposed to reset external devices. */
+ #if HAS_PRIVILEGE
+ if (cpustate->STATUS & ST_PR)
+ {
+ HANDLE_PRIVILEGE_VIOLATION
+ break;
+ }
+ #endif
+
+ cpustate->STATUS &= 0xFFF0; /*clear IM.*/
+ field_interrupt(cpustate); /*IM has been modified.*/
+
+ #if (TMS99XX_MODEL == TMS9995_ID)
+ /*cpustate->MID_flag = 0;*/ /* not sure about this */
+ #endif
+ #if (TMS99XX_MODEL == TI990_10_ID)
+ cpustate->error_interrupt_register = 0;
+ cpustate->mapping_on = 0;
+
+ cpustate->reset_maperr = 0;
+ cpustate->mapper_cru_read_register = 0;
+ cpustate->latch_control[0] = cpustate->latch_control[1] = cpustate->latch_control[2] = 0;
+
+ cpustate->diaglat = 0;
+ #endif
+
+ #if EXTERNAL_INSTRUCTION_DECODING
+ external_instruction_notify(cpustate, 3);
+ #endif
+
+ #if EXTERNAL_INSTRUCTION_CALLBACK
+ if (cpustate->rset_callback)
+ (*cpustate->rset_callback)(cpustate->device);
+ #endif
+
+ CYCLES(5, 12, 7);
+ break;
+
+#if EXTERNAL_INSTRUCTION_DECODING
+
+ case 13: /* CKON */
+ case 14: /* CKOF */
+ case 15: /* LREX */
+ /* CKON -- ClocK ON */
+ /* Perform a special CRU write (code 5). */
+ /* An external circuitery could, for instance, enable the line clock interrupt (100Hz or 120Hz, depending on the electrical alimentation frequency). */
+ /* CKOF -- ClocK OFf */
+ /* Perform a special CRU write (code 6). */
+ /* An external circuitery could, for instance, disable the line clock interrupt. */
+ /* LREX -- Load or REstart eXecution */
+ /* Perform a special CRU write (code 7). */
+ /* An external circuitery could, for instance, activate the LOAD* line,
+ causing a non-maskable LOAD interrupt (vector -1). */
+ #if HAS_PRIVILEGE
+ if (cpustate->STATUS & ST_PR)
+ {
+ HANDLE_PRIVILEGE_VIOLATION
+ break;
+ }
+ #endif
+
+ external_instruction_notify(cpustate, (opcode & 0x00e0) >> 5);
+
+ #if EXTERNAL_INSTRUCTION_CALLBACK
+ #warning "todo..."
+ #endif
+
+ CYCLES(Mooof!, 12, 7);
+ break;
+
+#elif EXTERNAL_INSTRUCTION_CALLBACK
+
+ case 13: /* CKON */
+ case 14: /* CKOF */
+ /* CKON -- ClocK ON */
+ /* Enable the line clock interrupt (100Hz or 120Hz, depending on the electrical alimentation frequency). */
+ /* CKOF -- ClocK OFf */
+ /* Disable the line clock interrupt. */
+ /* We use a callback because the line clock is implemented in machine
+ code, not in the CPU core. */
+ #if HAS_PRIVILEGE
+ if (cpustate->STATUS & ST_PR)
+ {
+ HANDLE_PRIVILEGE_VIOLATION
+ break;
+ }
+ #endif
+
+ if (cpustate->ckon_ckof_callback)
+ (*cpustate->ckon_ckof_callback)(cpustate->device, (opcode & 0x0020) ? 1 : 0);
+
+
+ CYCLES(5, Mooof!, Mooof!);
+ break;
+
+ case 15: /* LREX */
+ /* LREX -- Load or REstart eXecution */
+ /* Trigger a LOAD interrupt (vector -1). (We use a callback, and I
+ have forgotten the reason why.) */
+ #if HAS_PRIVILEGE
+ if (cpustate->STATUS & ST_PR)
+ {
+ HANDLE_PRIVILEGE_VIOLATION
+ break;
+ }
+ #endif
+
+ if (cpustate->lrex_callback)
+ (*cpustate->lrex_callback)(cpustate->device);
+
+ CYCLES(6, Mooof!, Mooof!);
+ break;
+
+#else
+
+ #warning "Should not happen..."
+
+#endif
+
+#endif
+ }
+}
+
+
+/*==========================================================================
+ Single-operand instructions, >0400->07FF
+ ---------------------------------------------------------------------------
+
+ 0 1 2 3-4 5 6 7+8 9 A B-C D E F
+ ---------------------------------
+ | o p c o d e |TS | S |
+ ---------------------------------
+
+ BLWP, B, X, CLR, NEG, INV, INC, INCT, DEC, DECT, BL, SWPB, SETO, ABS
+systems with memory mapper: LDD, LDS
+============================================================================*/
+static void h0400(tms99xx_state *cpustate, UINT16 opcode)
+{
+ register UINT16 addr = decipheraddr(cpustate, opcode) & ~1;
+ register UINT16 value; /* used for anything */
+#if HAS_MAPPING
+ int src_map = (opcode & 0x0030) ? cpustate->cur_src_map : cpustate->cur_map;
+#endif
+
+ switch ((opcode & 0x3C0) >> 6)
+ {
+ case 0: /* BLWP */
+ /* BLWP -- Branch and Link with Workspace Pointer */
+ /* Result: WP = *S+, PC = *S */
+ /* New R13=old WP, New R14=Old PC, New R15=Old ST */
+ contextswitch(cpustate, addr);
+ CYCLES(3, 26, 11);
+ cpustate->disable_interrupt_recognition = 1;
+ break;
+ case 1: /* B */
+ /* B ----- Branch */
+ /* PC = S */
+#if ((TMS99XX_MODEL == TMS9900_ID) || (TMS99XX_MODEL == TMS9980_ID))
+ (void) readwordX(cpustate, addr, src_map);
+#endif
+ cpustate->PC = addr;
+ CYCLES(2, 8, 3);
+ break;
+ case 2: /* X */
+ /* X ----- eXecute */
+ /* Executes instruction *S */
+ execute(cpustate, readwordX(cpustate, addr, src_map));
+ /* On tms9900, the X instruction actually takes 8 cycles, but we gain 2 cycles on the next
+ instruction, as we don't need to fetch it. */
+ CYCLES(1, 6, 2);
+ break;
+ case 3: /* CLR */
+ /* CLR --- CLeaR */
+ /* *S = 0 */
+#if ((TMS99XX_MODEL == TMS9900_ID) || (TMS99XX_MODEL == TMS9980_ID))
+ (void) readwordX(cpustate, addr, src_map);
+#endif
+ writewordX(cpustate, addr, 0, src_map);
+ CYCLES(2, 10, 3);
+ break;
+ case 4: /* NEG */
+ /* NEG --- NEGate */
+ /* *S = -*S */
+ value = - (INT16) readwordX(cpustate, addr, src_map);
+ if (value)
+ cpustate->STATUS &= ~ ST_C;
+ else
+ cpustate->STATUS |= ST_C;
+
+ #if (TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID)
+ if (value & 0x0FFF)
+ cpustate->STATUS &= ~ ST_DC;
+ else
+ cpustate->STATUS |= ST_DC;
+ #endif
+
+ setst_laeo(cpustate, value);
+ writewordX(cpustate, addr, value, src_map);
+ CYCLES(3, 12, 3);
+ break;
+ case 5: /* INV */
+ /* INV --- INVert */
+ /* *S = ~*S */
+ value = ~ readwordX(cpustate, addr, src_map);
+ writewordX(cpustate, addr, value, src_map);
+ setst_lae(cpustate, value);
+ CYCLES(2, 10, 3);
+ break;
+ case 6: /* INC */
+ /* INC --- INCrement */
+ /* (*S)++ */
+ value = setst_add_laeco(cpustate, readwordX(cpustate, addr, src_map), 1);
+ writewordX(cpustate, addr, value, src_map);
+ CYCLES(2, 10, 3);
+ break;
+ case 7: /* INCT */
+ /* INCT -- INCrement by Two */
+ /* (*S) +=2 */
+ value = setst_add_laeco(cpustate, readwordX(cpustate, addr, src_map), 2);
+ writewordX(cpustate, addr, value, src_map);
+ CYCLES(2, 10, 3);
+ break;
+ case 8: /* DEC */
+ /* DEC --- DECrement */
+ /* (*S)-- */
+ value = setst_sub_laeco(cpustate, readwordX(cpustate, addr, src_map), 1);
+ writewordX(cpustate, addr, value, src_map);
+ CYCLES(2, 10, 3);
+ break;
+ case 9: /* DECT */
+ /* DECT -- DECrement by Two */
+ /* (*S) -= 2 */
+ value = setst_sub_laeco(cpustate, readwordX(cpustate, addr, src_map), 2);
+ writewordX(cpustate, addr, value, src_map);
+ CYCLES(2, 10, 3);
+ break;
+ case 10: /* BL */
+ /* BL ---- Branch and Link */
+ /* IP=S, R11=old IP */
+#if ((TMS99XX_MODEL == TMS9900_ID) || (TMS99XX_MODEL == TMS9980_ID))
+ (void) readwordX(cpustate, addr, src_map);
+#endif
+ WRITEREG(R11, cpustate->PC);
+ cpustate->PC = addr;
+ CYCLES(3, 12, 5);
+ break;
+ case 11: /* SWPB */
+ /* SWPB -- SWaP Bytes */
+ /* *S = swab(*S) */
+ value = readwordX(cpustate, addr, src_map);
+ value = logical_right_shift(value, 8) | (value << 8);
+ writewordX(cpustate, addr, value, src_map);
+ CYCLES(2, 10, 13);
+ break;
+ case 12: /* SETO */
+ /* SETO -- SET to Ones */
+ /* *S = #$FFFF */
+#if ((TMS99XX_MODEL == TMS9900_ID) || (TMS99XX_MODEL == TMS9980_ID))
+ (void) readwordX(cpustate, addr, src_map);
+#endif
+ writewordX(cpustate, addr, 0xFFFF, src_map);
+ CYCLES(2, 10, 3);
+ break;
+ case 13: /* ABS */
+ /* ABS --- ABSolute value */
+ /* *S = |*S| */
+ /* clearing ST_C seems to be necessary, although ABS will never set it. */
+#if (TMS99XX_MODEL <= TMS9985_ID)
+
+ /* ti990/10 and tms9900/tms9980 only write the result if it has changed */
+ cpustate->STATUS &= ~ (ST_LGT | ST_AGT | ST_EQ | ST_C | ST_OV);
+
+ #if (TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID)
+ /* I guess ST_DC is cleared here, too*/
+ cpustate->STATUS &= ~ ST_DC;
+ #endif
+
+ value = readwordX(cpustate, addr, src_map);
+
+ CYCLES(5, 12, Mooof!);
+
+ if (((INT16) value) > 0)
+ cpustate->STATUS |= ST_LGT | ST_AGT;
+ else if (((INT16) value) < 0)
+ {
+ cpustate->STATUS |= ST_LGT;
+ if (value == 0x8000)
+ cpustate->STATUS |= ST_OV;
+
+ #if (TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID)
+ if (! (value & 0x0FFF))
+ cpustate->STATUS |= ST_DC;
+ #endif
+
+ writewordX(cpustate, addr, - ((INT16) value), src_map);
+ CYCLES(0, 2, Mooof!);
+ }
+ else
+ cpustate->STATUS |= ST_EQ;
+
+ break;
+
+#else
+
+ /* tms9995 always write the result */
+ cpustate->STATUS &= ~ (ST_LGT | ST_AGT | ST_EQ | ST_C | ST_OV);
+ value = readwordX(cpustate, addr, src_map);
+
+ CYCLES(Mooof!, Mooof!, 3);
+ if (((INT16) value) > 0)
+ cpustate->STATUS |= ST_LGT | ST_AGT;
+ else if (((INT16) value) < 0)
+ {
+ cpustate->STATUS |= ST_LGT;
+ if (value == 0x8000)
+ cpustate->STATUS |= ST_OV;
+ value = - ((INT16) value);
+ }
+ else
+ cpustate->STATUS |= ST_EQ;
+
+ writewordX(cpustate, addr, value, src_map);
+
+ break;
+
+#endif
+
+
+#if HAS_MAPPING
+ /* Used by the memory mapper on ti990/10 with mapping option, ti990/12, and the TIM99610
+ mapper chip to be associated with tms99000. */
+ /* These opcode allow access to another page without the need of switching a page someplace. */
+ /* Note that, if I read the 990/10 schematics correctly, two consecutive LDS or LDD would
+ cause some trouble. */
+ case 14: /* LDS */
+ /* LDS --- Long Distance Source */
+
+ #if HAS_PRIVILEGE
+ if (cpustate->STATUS & ST_PR)
+ {
+ HANDLE_PRIVILEGE_VIOLATION
+ break;
+ }
+ #endif
+
+ load_map_file(cpustate, addr, src_map, 2);
+ cpustate->lds_flag = 1;
+ cpustate->disable_interrupt_recognition = 1;
+ break;
+ case 15: /* LDD */
+ /* LDD --- Long Distance Destination */
+ #if HAS_PRIVILEGE
+ if (cpustate->STATUS & ST_PR)
+ {
+ HANDLE_PRIVILEGE_VIOLATION
+ break;
+ }
+ #endif
+
+ load_map_file(cpustate, addr, src_map, 2);
+ cpustate->ldd_flag = 1;
+ cpustate->disable_interrupt_recognition = 1;
+ break;
+
+#else
+
+ default:
+ /* illegal instructions */
+ HANDLE_ILLEGAL;
+ break;
+
+#endif
+ }
+}
+
+
+/*==========================================================================
+ Shift instructions, >0800->0BFF
+ --------------------------------------------------------------------------
+
+ 0 1 2 3-4 5 6 7+8 9 A B-C D E F
+ ---------------------------------
+ | o p c o d e | C | W |
+ ---------------------------------
+
+ SRA, SRL, SLA, SRC
+============================================================================*/
+static void h0800(tms99xx_state *cpustate, UINT16 opcode)
+{
+ register UINT16 addr;
+ register UINT16 cnt = (opcode & 0xF0) >> 4;
+ register UINT16 value;
+
+ addr = (opcode & 0xF);
+ addr = ((addr+addr) + cpustate->WP) & ~1;
+
+ CYCLES(3, 12, 5);
+
+ if (cnt == 0)
+ {
+ CYCLES(2, 8, 2);
+
+ cnt = READREG(R0) & 0xF;
+
+ if (cnt == 0)
+ cnt = 16;
+ }
+
+ CYCLES(cnt, cnt+cnt, cnt);
+
+ switch ((opcode & 0x300) >> 8)
+ {
+ case 0: /* SRA */
+ /* SRA --- Shift Right Arithmetic */
+ /* *W >>= C (*W is filled on the left with a copy of the sign bit) */
+ value = setst_sra_laec(cpustate, readword(cpustate, addr), cnt);
+ writeword(cpustate, addr, value);
+ break;
+ case 1: /* SRL */
+ /* SRL --- Shift Right Logical */
+ /* *W >>= C (*W is filled on the left with 0) */
+ value = setst_srl_laec(cpustate, readword(cpustate, addr), cnt);
+ writeword(cpustate, addr, value);
+ break;
+ case 2: /* SLA */
+ /* SLA --- Shift Left Arithmetic */
+ /* *W <<= C */
+ value = setst_sla_laeco(cpustate, readword(cpustate, addr), cnt);
+ writeword(cpustate, addr, value);
+ break;
+ case 3: /* SRC */
+ /* SRC --- Shift Right Circular */
+ /* *W = rightcircularshift(*W, C) */
+ value = setst_src_laec(cpustate, readword(cpustate, addr), cnt);
+ writeword(cpustate, addr, value);
+ break;
+ }
+}
+
+
+#if 0 /* 990/12 opcodes */
+/*==========================================================================
+ Additionnal instructions, >0C00->0C0F
+ Additionnal single-register instructions, >0C10->0C3F
+ ---------------------------------------------------------------------------
+
+ 0 1 2 3-4 5 6 7+8 9 A B-C D E F
+ ---------------------------------
+ | o p c o d e |
+ | o p c o d e | reg # |
+ ---------------------------------
+
+============================================================================*/
+static void h0c00(tms99xx_state *cpustate, UINT16 opcode)
+{
+ if (opcode & 0x30)
+ {
+ switch ((opcode & 0x30) >> 4)
+ {
+ case 1:
+ /* INSF -- INSert Field */
+ break;
+ case 2:
+ /* XV ---- eXtract Value */
+ break;
+ case 3:
+ /* XF ---- eXtract Field */
+ break;
+ }
+ }
+ else
+ {
+ switch (opcode & 0x0F)
+ {
+ /* floating point instructions */
+ case 0:
+ /* CRI --- Convert Real to Integer */
+ break;
+ case 2:
+ /* NEGR -- NEGate Real */
+ break;
+ case 4:
+ /* CRE --- Convert Real to Extended integer */
+ break;
+ case 6:
+ /* CER --- Convert Extended integer to Real */
+ break;
+
+ case 1:
+ /* CDI --- Convert Double precision real to Integer */
+ break;
+ case 3:
+ /* NEGD -- NEGate Double precision real */
+ break;
+ case 5:
+ /* CDE --- Convert Double precision real to Extended integer */
+ break;
+ case 7:
+ /* CED --- Convert Extended integer to Double precision real */
+ break;
+
+ case 8:
+ /* NRM --- NoRMalize */
+ break;
+
+ case 9:
+ /* TMB --- Test Memory Bit */
+ break;
+ case 10:
+ /* TCMB -- Test and Clear Memory Bit */
+ break;
+ case 11:
+ /* TSMB -- Test and Set Memory Bit */
+ break;
+
+ case 12:
+ /* SRJ --- Subtract from Register and Jump */
+ case 13:
+ /* ARJ --- Add to Register and Jump */
+
+ case 14:
+ case 15:
+ /* XIT --- eXIT from floating point interpreter */
+ /* Generated by some compilers, but equivalent to NOP on TI990/12. May have been used
+ by some software floating-point emulators. */
+ break;
+
+ default:
+ HANDLE_ILLEGAL;
+ break;
+ }
+ }
+}
+
+
+/*==========================================================================
+ Additionnal single-operand instructions, >0C40->0DFF
+ >0E40->0FFF
+ ---------------------------------------------------------------------------
+
+ 0 1 2 3-4 5 6 7+8 9 A B-C D E F
+ ---------------------------------
+ | o p c o d e |TS | S |
+ ---------------------------------
+
+============================================================================*/
+static void h0c40(tms99xx_state *cpustate, UINT16 opcode)
+{
+ register UINT16 src;
+
+#if HAS_MAPPING
+ int src_map = (opcode & 0x0030) ? cpustate->cur_src_map : cpustate->cur_map;
+#endif
+
+ src = decipheraddr(cpustate, opcode) & ~1;
+
+ switch ((opcode & 0x03C0) >> 6)
+ {
+ case 1:
+ /* AR ---- Add Real */
+ break;
+ case 2:
+ /* CIR --- Convert Integer to Real */
+ break;
+ case 3:
+ /* SR ---- Subtract Real */
+ break;
+ case 4:
+ /* MR ---- Multiply Real */
+ break;
+ case 5:
+ /* DR ---- Divide Real */
+ break;
+ case 6:
+ /* LR ---- Load Real */
+ break;
+ case 7:
+ /* STR --- STore Real */
+ break;
+ case 9:
+ /* AD ---- Add Double */
+ break;
+ case 10:
+ /* CID --- Convert Integer to Double */
+ break;
+ case 11:
+ /* SD ---- Subtract Double */
+ break;
+ case 12:
+ /* MD ---- Multiply Double */
+ break;
+ case 13:
+ /* DD ---- Divide Double */
+ break;
+ case 14:
+ /* LD ---- Load Double */
+ break;
+ case 15:
+ /* SD ---- Store Double */
+ break;
+ default:
+ HANDLE_ILLEGAL;
+ break;
+ }
+}
+
+/*==========================================================================
+ Additionnal single-register instructions, >0E00->0E3F
+ ---------------------------------------------------------------------------
+
+ 0 1 2 3-4 5 6 7+8 9 A B-C D E F
+ ---------------------------------
+ | o p c o d e | reg # |
+ ---------------------------------
+
+============================================================================*/
+static void h0e00(tms99xx_state *cpustate, UINT16 opcode)
+{
+ switch ((opcode & 0x30) >> 4)
+ {
+ case 1:
+ /* IOF --- Invert Order of Field */
+ break;
+ case 1:
+ /* SNEB -- Search string for Not Equal Byte */
+ break;
+ case 2:
+ /* CRC --- Cyclic Redundancy Code calculation */
+ break;
+ case 3:
+ /* TS ---- Translate String */
+ break;
+ }
+}
+#endif
+
+
+/*==========================================================================
+ Jump, CRU bit instructions, >1000->1FFF
+ ---------------------------------------------------------------------------
+
+ 0 1 2 3-4 5 6 7+8 9 A B-C D E F
+ ---------------------------------
+ | o p c o d e | signed offset |
+ ---------------------------------
+
+ JMP, JLT, JLE, JEQ, JHE, JGT, JNE, JNC, JOC, JNO, JL, JH, JOP
+ SBO, SBZ, TB
+============================================================================*/
+static void h1000(tms99xx_state *cpustate, UINT16 opcode)
+{
+ /* we convert 8 bit signed word offset to a 16 bit effective word offset. */
+ register INT16 offset = ((INT8) opcode);
+
+
+ switch ((opcode & 0xF00) >> 8)
+ {
+ case 0: /* JMP */
+ /* JMP --- unconditional JuMP */
+ /* PC += offset */
+ cpustate->PC += (offset + offset);
+ CYCLES(3, 10, 3);
+ break;
+ case 1: /* JLT */
+ /* JLT --- Jump if Less Than (arithmetic) */
+ /* if (A==0 && EQ==0), PC += offset */
+ if (! (cpustate->STATUS & (ST_AGT | ST_EQ)))
+ {
+ cpustate->PC += (offset + offset);
+ CYCLES(3, 10, 3);
+ }
+ else
+ CYCLES(2, 8, 3);
+ break;
+ case 2: /* JLE */
+ /* JLE --- Jump if Lower or Equal (logical) */
+ /* if (L==0 || EQ==1), PC += offset */
+ if ((! (cpustate->STATUS & ST_LGT)) || (cpustate->STATUS & ST_EQ))
+ {
+ cpustate->PC += (offset + offset);
+ CYCLES(3, 10, 3);
+ }
+ else
+ CYCLES(2, 8, 3);
+ break;
+ case 3: /* JEQ */
+ /* JEQ --- Jump if EQual */
+ /* if (EQ==1), PC += offset */
+ if (cpustate->STATUS & ST_EQ)
+ {
+ cpustate->PC += (offset + offset);
+ CYCLES(3, 10, 3);
+ }
+ else
+ CYCLES(2, 8, 3);
+ break;
+ case 4: /* JHE */
+ /* JHE --- Jump if Higher or Equal (logical) */
+ /* if (L==1 || EQ==1), PC += offset */
+ if (cpustate->STATUS & (ST_LGT | ST_EQ))
+ {
+ cpustate->PC += (offset + offset);
+ CYCLES(3, 10, 3);
+ }
+ else
+ CYCLES(2, 8, 3);
+ break;
+ case 5: /* JGT */
+ /* JGT --- Jump if Greater Than (arithmetic) */
+ /* if (A==1), PC += offset */
+ if (cpustate->STATUS & ST_AGT)
+ {
+ cpustate->PC += (offset + offset);
+ CYCLES(3, 10, 3);
+ }
+ else
+ CYCLES(2, 8, 3);
+ break;
+ case 6: /* JNE */
+ /* JNE --- Jump if Not Equal */
+ /* if (EQ==0), PC += offset */
+ if (! (cpustate->STATUS & ST_EQ))
+ {
+ cpustate->PC += (offset + offset);
+ CYCLES(3, 10, 3);
+ }
+ else
+ CYCLES(2, 8, 3);
+ break;
+ case 7: /* JNC */
+ /* JNC --- Jump if No Carry */
+ /* if (C==0), PC += offset */
+ if (! (cpustate->STATUS & ST_C))
+ {
+ cpustate->PC += (offset + offset);
+ CYCLES(3, 10, 3);
+ }
+ else
+ CYCLES(2, 8, 3);
+ break;
+ case 8: /* JOC */
+ /* JOC --- Jump On Carry */
+ /* if (C==1), PC += offset */
+ if (cpustate->STATUS & ST_C)
+ {
+ cpustate->PC += (offset + offset);
+ CYCLES(3, 10, 3);
+ }
+ else
+ CYCLES(2, 8, 3);
+ break;
+ case 9: /* JNO */
+ /* JNO --- Jump if No Overflow */
+ /* if (OV==0), PC += offset */
+ if (! (cpustate->STATUS & ST_OV))
+ {
+ cpustate->PC += (offset + offset);
+ CYCLES(3, 10, 3);
+ }
+ else
+ CYCLES(2, 8, 3);
+ break;
+ case 10: /* JL */
+ /* JL ---- Jump if Lower (logical) */
+ /* if (L==0 && EQ==0), PC += offset */
+ if (! (cpustate->STATUS & (ST_LGT | ST_EQ)))
+ {
+ cpustate->PC += (offset + offset);
+ CYCLES(3, 10, 3);
+ }
+ else
+ CYCLES(2, 8, 3);
+ break;
+ case 11: /* JH */
+ /* JH ---- Jump if Higher (logical) */
+ /* if (L==1 && EQ==0), PC += offset */
+ if ((cpustate->STATUS & ST_LGT) && ! (cpustate->STATUS & ST_EQ))
+ {
+ cpustate->PC += (offset + offset);
+ CYCLES(3, 10, 3);
+ }
+ else
+ CYCLES(2, 8, 3);
+ break;
+ case 12: /* JOP */
+ /* JOP --- Jump On (odd) Parity */
+ /* if (P==1), PC += offset */
+ {
+ /* Let's set ST_OP. */
+ int i;
+ UINT8 a;
+ a = cpustate->lastparity;
+ i = 0;
+
+ while (a != 0)
+ {
+ if (a & 1) /* If current bit is set, */
+ i++; /* increment bit count. */
+ a >>= 1U; /* Next bit. */
+ }
+
+ /* Set ST_OP bit. */
+ /*if (i & 1)
+ cpustate->STATUS |= ST_OP;
+ else
+ cpustate->STATUS &= ~ ST_OP;*/
+
+ /* Jump accordingly. */
+ if (i & 1) /*(cpustate->STATUS & ST_OP)*/
+ {
+ cpustate->PC += (offset + offset);
+ CYCLES(3, 10, 3);
+ }
+ else
+ CYCLES(2, 8, 3);
+ }
+
+ break;
+ case 13: /* SBO */
+ /* SBO --- Set Bit to One */
+ /* CRU Bit = 1 */
+ #if HAS_PRIVILEGE
+ if (writeCRU(cpustate, (READREG(R12) >> 1) + offset, 1, 1) == CRU_PRIVILEGE_VIOLATION)
+ HANDLE_PRIVILEGE_VIOLATION
+ #else
+ writeCRU(cpustate, (READREG(R12) >> 1) + offset, 1, 1);
+ #endif
+
+ CYCLES(4, 12, 8);
+ break;
+
+ case 14: /* SBZ */
+ /* SBZ --- Set Bit to Zero */
+ /* CRU Bit = 0 */
+ #if HAS_PRIVILEGE
+ if (writeCRU(cpustate, (READREG(R12) >> 1) + offset, 1, 0) == CRU_PRIVILEGE_VIOLATION)
+ HANDLE_PRIVILEGE_VIOLATION
+ #else
+ writeCRU(cpustate, (READREG(R12) >> 1) + offset, 1, 0);
+ #endif
+
+ CYCLES(4, 12, 8);
+ break;
+
+ case 15: /* TB */
+ /* TB ---- Test Bit */
+ /* EQ = (CRU Bit == 1) */
+ #if HAS_PRIVILEGE
+ {
+ int value;
+
+ value = readCRU(cpustate, (READREG(R12)>> 1) + offset, 1);
+ if (value == CRU_PRIVILEGE_VIOLATION)
+ HANDLE_PRIVILEGE_VIOLATION
+ else
+ setst_e(cpustate, value & 1, 1);
+ }
+ #else
+ setst_e(cpustate, readCRU(cpustate, (READREG(R12)>> 1) + offset, 1) & 1, 1);
+ #endif
+ CYCLES(5, 12, 8);
+ break;
+ }
+}
+
+
+/*==========================================================================
+ General and One-Register instructions >2000->3FFF
+ ---------------------------------------------------------------------------
+
+ 0 1 2 3-4 5 6 7+8 9 A B-C D E F
+ ---------------------------------
+ | opcode | D |TS | S |
+ ---------------------------------
+
+ COC, CZC, XOR, LDCR, STCR, XOP, MPY, DIV
+tms9940 : DCA, DCS, LIIM
+==========================================================================*/
+
+/* xop, ldcr and stcr are handled elsewhere */
+static void h2000(tms99xx_state *cpustate, UINT16 opcode)
+{
+ register UINT16 dest = (opcode & 0x3C0) >> 6;
+ register UINT16 src;
+ register UINT16 value;
+
+#if HAS_MAPPING
+ int src_map = (opcode & 0x0030) ? cpustate->cur_src_map : cpustate->cur_map;
+#endif
+
+ src = decipheraddr(cpustate, opcode) & ~1;
+ dest = ((dest+dest) + cpustate->WP) & ~1;
+
+ switch ((opcode & 0x1C00) >> 10)
+ {
+ case 0: /* COC */
+ /* COC --- Compare Ones Corresponding */
+ /* status E bit = (S&D == S) */
+ value = readwordX(cpustate, src, src_map);
+ setst_e(cpustate, value & readword(cpustate, dest), value);
+ CYCLES(5, 14, 4);
+ break;
+ case 1: /* CZC */
+ /* CZC --- Compare Zeroes Corresponding */
+ /* status E bit = (S&~D == S) */
+ value = readwordX(cpustate, src, src_map);
+ setst_e(cpustate, value & (~ readword(cpustate, dest)), value);
+ CYCLES(5, 14, 4);
+ break;
+ case 2: /* XOR */
+ /* XOR --- eXclusive OR */
+ /* D ^= S */
+ value = readwordX(cpustate, src, src_map);
+ value ^= readword(cpustate, dest);
+ setst_lae(cpustate, value);
+ writeword(cpustate, dest,value);
+ CYCLES(3, 14, 4);
+ break;
+ /*case 3:*/ /* XOP is implemented elsewhere */
+ /*case 4:*/ /* LDCR is implemented elsewhere */
+ /*case 5:*/ /* STCR is implemented elsewhere */
+ case 6: /* MPY */
+ /* MPY --- MultiPlY (unsigned) */
+ /* Results: D:D+1 = D*S */
+ /* Note that early TMS9995 reportedly performs an extra dummy read in PC space */
+ {
+ unsigned long prod = ((unsigned long) readwordX(cpustate, src, src_map));
+ prod = prod * ((unsigned long) readword(cpustate, dest));
+ writeword(cpustate, dest, prod >> 16);
+ writeword(cpustate, (dest+2)&0xffff, prod);
+ }
+ /* ti990/10 : from 19 to 35, possibly 19 + (number of bits to 1 in one operand) */
+ CYCLES(35, 52, 23);
+ break;
+ case 7: /* DIV */
+ /* DIV --- DIVide (unsigned) */
+ /* D = D/S D+1 = D%S */
+ {
+ UINT16 d = readwordX(cpustate, src, src_map);
+ UINT16 hi = readword(cpustate, dest);
+ unsigned long divq = (((unsigned long) hi) << 16) | readword(cpustate, (dest+2)&0xffff);
+
+ if (d <= hi)
+ {
+ cpustate->STATUS |= ST_OV;
+ CYCLES(4, 16, 6);
+ }
+ else
+ {
+ cpustate->STATUS &= ~ST_OV;
+ writeword(cpustate, dest, divq/d);
+ writeword(cpustate, (dest+2)&0xffff, divq%d);
+ /* tms9900 : from 92 to 124, possibly 92 + 2*(number of bits to 1 (or 0?) in quotient) */
+ /* tms9995 : 28 is the worst case */
+ /* ti990/10 : from 41 to 58, possibly 41 + (number of bits to 1 (or 0?) in quotient) */
+ CYCLES(41, 92, 28);
+ }
+ }
+ break;
+ }
+}
+
+static void xop(tms99xx_state *cpustate, UINT16 opcode)
+{ /* XOP */
+ /* XOP --- eXtended OPeration */
+ /* WP = *(40h+D), PC = *(42h+D) */
+ /* New R13=old WP, New R14=Old IP, New R15=Old ST */
+ /* New R11=S */
+ /* Xop bit set */
+
+ register UINT16 immediate = (opcode & 0x3C0) >> 6;
+ register UINT16 operand;
+
+
+#if (TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID)
+ switch (immediate)
+ {
+ case 0: /* DCA */
+ /* DCA --- Decimal Correct Addition */
+ operand = decipheraddrbyte(cpustate, opcode);
+ {
+ int value = readbyte(cpustate, operand);
+ int X = (value >> 4) & 0xf;
+ int Y = value & 0xf;
+
+ if (Y >= 10)
+ {
+ Y -= 10;
+ cpustate->STATUS |= ST_DC;
+ X++;
+ }
+ else if (cpustate->STATUS & ST_DC)
+ {
+ Y += 6;
+ }
+
+ if (X >= 10)
+ {
+ X -= 10;
+ cpustate->STATUS |= ST_C;
+ }
+ else if (cpustate->STATUS & ST_C)
+ {
+ X += 6;
+ }
+
+ writebyte(cpustate, operand, (X << 4) | Y);
+ }
+ break;
+ case 1: /* DCS */
+ /* DCS --- Decimal Correct Substraction */
+ operand = decipheraddrbyte(cpustate, opcode);
+ {
+ int value = readbyte(cpustate, operand);
+
+ if (! (cpustate->STATUS & ST_DC))
+ {
+ value += 10;
+ }
+
+ if (! (cpustate->STATUS & ST_C))
+ {
+ value += 10 << 4;
+ }
+
+ cpustate->STATUS ^= ST_DC;
+
+ writebyte(cpustate, operand, value);
+ }
+ break;
+ case 2: /* LIIM */
+ case 3: /* LIIM */
+ /* LIIM - Load Immediate Interrupt Mask */
+ /* Does the same job as LIMI, with a different opcode format. */
+ /* Note that, unlike TMS9900, the interrupt mask is only 2-bit long. */
+ (void)decipheraddr(cpustate, opcode); /* dummy decode (personnal guess) */
+
+ cpustate->STATUS = (cpustate->STATUS & ~ST_IM) | (opcode & ST_IM);
+ break;
+ default: /* normal XOP */
+#endif
+
+ /* TODO : emulate 990/10 hardware XOP */
+ operand = decipheraddr(cpustate, opcode);
+
+ #if ((TMS99XX_MODEL <= TMS9989_ID) && (TMS99XX_MODEL != TI990_10_ID))
+ (void)readword(cpustate, operand & ~1); /*dummy read (personnal guess)*/
+ #endif
+
+ contextswitchX(cpustate, 0x40 + (immediate << 2));
+
+ #if ! ((TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID))
+ /* The bit is not set on tms9940 */
+ cpustate->STATUS |= ST_X;
+ #endif
+
+ WRITEREG(R11, operand);
+ CYCLES(7, 36, 15);
+ cpustate->disable_interrupt_recognition = 1;
+
+#if (TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID)
+ break;
+ }
+#endif
+}
+
+/* LDCR and STCR */
+static void ldcr_stcr(tms99xx_state *cpustate, UINT16 opcode)
+{
+ register UINT16 cnt = (opcode & 0x3C0) >> 6;
+ register UINT16 addr;
+ int value;
+
+#if HAS_MAPPING
+ int src_map = (opcode & 0x0030) ? cpustate->cur_src_map : cpustate->cur_map;
+#endif
+
+ if (cnt == 0)
+ cnt = 16;
+
+ if (cnt <= 8)
+ addr = decipheraddrbyte(cpustate, opcode);
+ else
+ addr = decipheraddr(cpustate, opcode) & ~1;
+
+ if (opcode < 0x3400)
+ { /* LDCR */
+ /* LDCR -- LoaD into CRu */
+ /* CRU R12--CRU R12+D-1 set to S */
+ if (cnt <= 8)
+ {
+#if (TMS99XX_MODEL != TMS9995_ID)
+ value = readbyteX(cpustate, addr, src_map);
+#else
+ /* just for once, tms9995 behaves like earlier 8-bit tms99xx chips */
+ /* this must be because instruction decoding is too complex */
+ value = readwordX(cpustate, addr & ~1, src_map);
+ if (addr & 1)
+ value &= 0xFF;
+ else
+ value = (value >> 8) & 0xFF;
+#endif
+
+ (void)READREG(cnt+cnt); /*dummy read (reasonnable guess for TMS9995 & TMS9900, ti990/10)*/
+
+ setst_byte_laep(cpustate, value);
+ }
+ else
+ {
+ value = readwordX(cpustate, addr, src_map);
+
+ (void)READREG(cnt+cnt); /*dummy read (reasonnable guess for TMS9995 & TMS9900, ti990/10)*/
+
+ setst_lae(cpustate, value);
+ }
+
+ #if HAS_PRIVILEGE
+ if (writeCRU(cpustate, (READREG(R12) >> 1), cnt, value) == CRU_PRIVILEGE_VIOLATION)
+ HANDLE_PRIVILEGE_VIOLATION
+ #else
+ writeCRU(cpustate, (READREG(R12) >> 1), cnt, value);
+ #endif
+
+ CYCLES(4+cnt, 20 + cnt+cnt, 9 + cnt+cnt);
+ }
+ else
+ { /* STCR */
+ /* STCR -- STore from CRu */
+ /* S = CRU R12--CRU R12+D-1 */
+ if (cnt <= 8)
+ {
+#if (TMS99XX_MODEL != TMS9995_ID)
+ (void)readbyteX(cpustate, addr, src_map); /*dummy read*/
+
+ (void)READREG(cnt+cnt); /*dummy read (reasonnable guess for TMS9995 & TMS9900, ti990/10)*/
+
+ #if HAS_PRIVILEGE
+ value = readCRU(cpustate, (READREG(R12) >> 1), cnt);
+ if (value == CRU_PRIVILEGE_VIOLATION)
+ HANDLE_PRIVILEGE_VIOLATION
+ else
+ {
+ setst_byte_laep(cpustate, value);
+ writebyteX(cpustate, addr, value, src_map);
+ }
+ #else
+ value = readCRU(cpustate, (READREG(R12) >> 1), cnt);
+ setst_byte_laep(cpustate, value);
+ writebyteX(cpustate, addr, value, src_map);
+ #endif
+ CYCLES(18+cnt, (cnt != 8) ? 42 : 44, 19 + cnt);
+#else
+ /* just for once, tms9995 behaves like earlier 8-bit tms99xx chips */
+ /* this must be because instruction decoding is too complex */
+ int value2 = readwordX(cpustate, addr & ~1, src_map);
+
+ (void)READREG(cnt+cnt); /*dummy read (reasonnable guess for TMS9995 & TMS9900, ti990/10)*/
+
+ value = readCRU(cpustate, (READREG(R12) >> 1), cnt);
+ setst_byte_laep(cpustate, value);
+
+ if (addr & 1)
+ writewordX(cpustate, addr & ~1, (value & 0x00FF) | (value2 & 0xFF00), src_map);
+ else
+ writewordX(cpustate, addr & ~1, (value2 & 0x00FF) | ((value << 8) & 0xFF00), src_map);
+
+ CYCLES(Mooof!, Mooof!, 19 + cnt);
+#endif
+ }
+ else
+ {
+ (void)readwordX(cpustate, addr, src_map); /*dummy read*/
+
+ (void)READREG(cnt+cnt); /*dummy read (reasonnable guess for TMS9995 & TMS9900, ti990/10)*/
+
+ #if HAS_PRIVILEGE
+ value = readCRU(cpustate, (READREG(R12) >> 1), cnt);
+ if (value == CRU_PRIVILEGE_VIOLATION)
+ HANDLE_PRIVILEGE_VIOLATION
+ else
+ {
+ setst_lae(cpustate, value);
+ writewordX(cpustate, addr, value, src_map);
+ }
+ #else
+ value = readCRU(cpustate, (READREG(R12) >> 1), cnt);
+ setst_lae(cpustate, value);
+ writewordX(cpustate, addr, value, src_map);
+ #endif
+ CYCLES(24+cnt, (cnt != 16) ? 58 : 60, 27 + cnt);
+ }
+ }
+}
+
+
+/*==========================================================================
+ Two-Operand instructions >4000->FFFF
+ ---------------------------------------------------------------------------
+
+ 0 1 2 3-4 5 6 7+8 9 A B-C D E F
+ ----------------------------------
+ |opcode|B|TD | D |TS | S |
+ ----------------------------------
+
+ SZC, SZCB, S, SB, C, CB, A, AB, MOV, MOVB, SOC, SOCB
+============================================================================*/
+
+/* word instructions */
+static void h4000w(tms99xx_state *cpustate, UINT16 opcode)
+{
+ register UINT16 src;
+ register UINT16 dest;
+ register UINT16 value;
+
+#if HAS_MAPPING
+ int src_map = (opcode & 0x0030) ? cpustate->cur_src_map : cpustate->cur_map;
+ int dst_map = (opcode & 0x0c00) ? cpustate->cur_dst_map : cpustate->cur_map;
+#endif
+
+ src = decipheraddr(cpustate, opcode) & ~1;
+ dest = decipheraddr(cpustate, opcode >> 6) & ~1;
+
+ value = readwordX(cpustate, src, src_map);
+
+ switch ((opcode >> 13) & 0x0007) /* ((opcode & 0xE000) >> 13) */
+ {
+ case 2: /* SZC */
+ /* SZC --- Set Zeros Corresponding */
+ /* D &= ~S */
+ value = readwordX(cpustate, dest, dst_map) & (~ value);
+ setst_lae(cpustate, value);
+ writewordX(cpustate, dest, value, dst_map);
+ CYCLES(2, 14, 4);
+ break;
+ case 3: /* S */
+ /* S ----- Subtract */
+ /* D -= S */
+ value = setst_sub_laeco(cpustate, readwordX(cpustate, dest, dst_map), value);
+ writewordX(cpustate, dest, value, dst_map);
+ CYCLES(2, 14, 4);
+ break;
+ case 4: /* C */
+ /* C ----- Compare */
+ /* ST = (D - S) */
+ setst_c_lae(cpustate, readwordX(cpustate, dest, dst_map), value);
+ CYCLES(5, 14, 4);
+ break;
+ case 5: /* A */
+ /* A ----- Add */
+ /* D += S */
+ value = setst_add_laeco(cpustate, readwordX(cpustate, dest, dst_map), value);
+ writewordX(cpustate, dest, value, dst_map);
+ CYCLES(2, 14, 4);
+ break;
+ case 6: /* MOV */
+ /* MOV --- MOVe */
+ /* D = S */
+ setst_lae(cpustate, value);
+ #if ((TMS99XX_MODEL >= TMS9900_ID) && (TMS99XX_MODEL <= TMS9985_ID))
+ /* MOV performs a dummy read with tms9900/9980 (but neither ti990/10 nor tms9995) */
+ (void)readwordX(cpustate, dest, dst_map);
+ #endif
+ writewordX(cpustate, dest, value, dst_map);
+ CYCLES(1, 14, 3);
+ break;
+ case 7: /* SOC */
+ /* SOC --- Set Ones Corresponding */
+ /* D |= S */
+ value = value | readwordX(cpustate, dest, dst_map);
+ setst_lae(cpustate, value);
+ writewordX(cpustate, dest, value, dst_map);
+ CYCLES(2, 14, 4);
+ break;
+ }
+}
+
+/* byte instruction */
+static void h4000b(tms99xx_state *cpustate, UINT16 opcode)
+{
+ register UINT16 src;
+ register UINT16 dest;
+ register UINT16 value;
+
+#if HAS_MAPPING
+ int src_map = (opcode & 0x0030) ? cpustate->cur_src_map : cpustate->cur_map;
+ int dst_map = (opcode & 0x0c00) ? cpustate->cur_dst_map : cpustate->cur_map;
+#endif
+
+ src = decipheraddrbyte(cpustate, opcode);
+ dest = decipheraddrbyte(cpustate, opcode >> 6);
+
+ value = readbyteX(cpustate, src, src_map);
+
+ switch ((opcode >> 13) & 0x0007) /* ((opcode & 0xE000) >> 13) */
+ {
+ case 2: /* SZCB */
+ /* SZCB -- Set Zeros Corresponding, Byte */
+ /* D &= ~S */
+ value = readbyteX(cpustate, dest, dst_map) & (~ value);
+ setst_byte_laep(cpustate, value);
+ writebyteX(cpustate, dest, value, dst_map);
+ CYCLES(3, 14, 4);
+ break;
+ case 3: /* SB */
+ /* SB ---- Subtract, Byte */
+ /* D -= S */
+ value = setst_subbyte_laecop(cpustate, readbyteX(cpustate, dest, dst_map), value);
+ writebyteX(cpustate, dest, value, dst_map);
+ CYCLES(3, 14, 4);
+ break;
+ case 4: /* CB */
+ /* CB ---- Compare Bytes */
+ /* ST = (D - S) */
+ setst_c_lae(cpustate, readbyteX(cpustate, dest, dst_map)<<8, value<<8);
+ cpustate->lastparity = value;
+ CYCLES(5, 14, 4);
+ break;
+ case 5: /* AB */
+ /* AB ---- Add, Byte */
+ /* D += S */
+ value = setst_addbyte_laecop(cpustate, readbyteX(cpustate, dest, dst_map), value);
+ writebyteX(cpustate, dest, value, dst_map);
+ CYCLES(3, 14, 4);
+ break;
+ case 6: /* MOVB */
+ /* MOVB -- MOVe Bytes */
+ /* D = S */
+ setst_byte_laep(cpustate, value);
+ #if (TMS99XX_MODEL <= TMS9985_ID)
+ /* On ti990/10 and tms9900, MOVB needs to read destination, because it cannot actually
+ read one single byte. It reads a word, replaces the revelant byte, then write
+ the result. A tms9980 should not need to do so, but still does, because it is just
+ a tms9900 with a 16 to 8 bit multiplexer (instead of a new chip design, like tms9995). */
+ (void)readbyteX(cpustate, dest, dst_map);
+ #endif
+ writebyteX(cpustate, dest, value, dst_map);
+ CYCLES(3, 14, 3);
+ break;
+ case 7: /* SOCB */
+ /* SOCB -- Set Ones Corresponding, Byte */
+ /* D |= S */
+ value = value | readbyteX(cpustate, dest, dst_map);
+ setst_byte_laep(cpustate, value);
+ writebyteX(cpustate, dest, value, dst_map);
+ CYCLES(3, 14, 4);
+ break;
+ }
+}
+
+
+INLINE void execute(tms99xx_state *cpustate, UINT16 opcode)
+{
+#if (! HAS_9995_OPCODES)
+
+ /* tms9900-like instruction set*/
+
+ static void (*const jumptable_short[128])(tms99xx_state *,UINT16) =
+ {
+ &illegal,&h0200,&h0400,&h0400,&h0800,&h0800,&illegal,&illegal,
+ &h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,
+ &h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&xop,&xop,
+ &ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&h2000,&h2000,&h2000,&h2000,
+ &h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
+ &h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
+ &h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
+ &h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
+ &h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
+ &h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
+ &h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
+ &h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
+ &h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
+ &h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
+ &h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
+ &h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b
+ };
+
+ (* jumptable_short[opcode >> 9])(cpustate, opcode);
+
+#else
+
+ /* tms9989 and tms9995 include 4 extra instructions, and one additionnal instruction type */
+ /* tms99000 includes yet another additional instruction */
+
+ static void (*const jumptable_long[256])(tms99xx_state *,UINT16) =
+ {
+ &h0040,&h0100,&h0200,&h0200,&h0400,&h0400,&h0400,&h0400,
+ &h0800,&h0800,&h0800,&h0800,&illegal,&illegal,&illegal,&illegal,
+ &h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,
+ &h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,
+ &h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,
+ &h2000,&h2000,&h2000,&h2000,&xop,&xop,&xop,&xop,
+ &ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,
+ &h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,
+ &h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
+ &h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
+ &h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
+ &h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
+ &h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
+ &h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
+ &h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
+ &h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
+ &h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
+ &h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
+ &h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
+ &h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
+ &h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
+ &h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
+ &h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
+ &h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
+ &h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
+ &h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
+ &h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
+ &h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
+ &h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
+ &h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
+ &h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
+ &h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b
+ };
+
+ (* jumptable_long[opcode >> 8])(cpustate, opcode);
+
+#endif
+}
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( tms99xx )
+{
+ tms99xx_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_NMI: tms99xx_set_irq_line(cpustate, INPUT_LINE_NMI, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + 0: tms99xx_set_irq_line(cpustate, 0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + 1: tms99xx_set_irq_line(cpustate, 1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + 2: tms99xx_set_irq_line(cpustate, 2, info->i); break;
+
+#if (TMS99XX_MODEL == TI990_10_ID)
+ case CPUINFO_INT_PC:
+ {
+ const unsigned top = (cpustate->cur_map == 0) ? 0xf800 : 0x10000;
+
+ if ((cpustate->cur_map == 0) && (info->i >= 0x1ff800))
+ /* intercept TPCS and CPU ROM */
+ cpustate->PC = info->i - 0x1f0000;
+ else if (! cpustate->mapping_on)
+ cpustate->PC = (info->i < top) ? info->i : 0;
+ else
+ {
+ if ((info->i >= cpustate->map_files[cpustate->cur_map].bias[0])
+ && (info->i <= (cpustate->map_files[cpustate->cur_map].bias[0]+cpustate->map_files[cpustate->cur_map].limit[0])))
+ cpustate->PC = info->i - cpustate->map_files[cpustate->cur_map].bias[0];
+ else if ((info->i > (cpustate->map_files[cpustate->cur_map].bias[1]+cpustate->map_files[cpustate->cur_map].limit[0]))
+ && (info->i <= (cpustate->map_files[cpustate->cur_map].bias[1]+cpustate->map_files[cpustate->cur_map].limit[1])))
+ cpustate->PC = info->i - cpustate->map_files[cpustate->cur_map].bias[1];
+ else if ((info->i > (cpustate->map_files[cpustate->cur_map].bias[2]+cpustate->map_files[cpustate->cur_map].limit[0]))
+ && (info->i > (cpustate->map_files[cpustate->cur_map].bias[2]+cpustate->map_files[cpustate->cur_map].limit[1]))
+ && (info->i <= (cpustate->map_files[cpustate->cur_map].bias[2]+cpustate->map_files[cpustate->cur_map].limit[2])))
+ cpustate->PC = info->i - cpustate->map_files[cpustate->cur_map].bias[2];
+ else
+ {
+ /*if ((info->i < top)
+ && (info->i > cpustate->map_files[cpustate->cur_map].limit[0])
+ && (info->i > cpustate->map_files[cpustate->cur_map].limit[1])
+ && (info->i > cpustate->map_files[cpustate->cur_map].limit[2]))
+ cpustate->PC = info->i;
+ else*/
+ cpustate->PC = 0;
+ }
+ /*if (info->i >= top)
+ cpustate->PC = 0;*/
+ }
+ cpustate->PC &= 0xfffe;
+ }
+ break;
+#else
+ case CPUINFO_INT_PC:
+#endif
+ case CPUINFO_INT_REGISTER + TMS9900_PC: cpustate->PC = info->i & 0xfffe; break;
+ case CPUINFO_INT_REGISTER + TMS9900_IR: cpustate->IR = info->i; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + TMS9900_WP: cpustate->WP = info->i & 0xfffe; break;
+ case CPUINFO_INT_REGISTER + TMS9900_STATUS: cpustate->STATUS = info->i; getstat(cpustate); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R0: WRITEREG_DEBUG(cpustate, R0, info->i); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R1: WRITEREG_DEBUG(cpustate, R1, info->i); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R2: WRITEREG_DEBUG(cpustate, R2, info->i); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R3: WRITEREG_DEBUG(cpustate, R3, info->i); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R4: WRITEREG_DEBUG(cpustate, R4, info->i); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R5: WRITEREG_DEBUG(cpustate, R5, info->i); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R6: WRITEREG_DEBUG(cpustate, R6, info->i); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R7: WRITEREG_DEBUG(cpustate, R7, info->i); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R8: WRITEREG_DEBUG(cpustate, R8, info->i); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R9: WRITEREG_DEBUG(cpustate, R9, info->i); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R10: WRITEREG_DEBUG(cpustate, R10, info->i); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R11: WRITEREG_DEBUG(cpustate, R11, info->i); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R12: WRITEREG_DEBUG(cpustate, R12, info->i); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R13: WRITEREG_DEBUG(cpustate, R13, info->i); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R14: WRITEREG_DEBUG(cpustate, R14, info->i); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R15: WRITEREG_DEBUG(cpustate, R15, info->i); break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+void TMS99XX_GET_INFO(legacy_cpu_device *device, UINT32 state, cpuinfo *info)
+{
+ tms99xx_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(tms99xx_state); 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_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;/*8 with 990/12, 99105, 99110*/break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 10;/*TODO: compute this value*/break;
+
+#if (USE_16_BIT_ACCESSORS)
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+#else
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+#endif
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM:
+#if (TMS99XX_MODEL == TI990_10_ID)
+ /* this CPU has a mapper to expand the address space */
+ info->i = 21;
+#elif (TMS99XX_MODEL == TMS9900_ID) || (TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID) || (TMS99XX_MODEL == TMS9995_ID)
+ /* basic 16-bit address bus */
+ info->i = 16;
+#elif (TMS99XX_MODEL == TMS9980_ID)
+ /* 2 address MSBits are unconnected */
+ info->i = 14;
+#else
+ #warning "Please check how many address bits your CPU has."
+ info->i = 16;
+#endif
+ 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:
+#if (TMS99XX_MODEL == TI990_10_ID)
+ /* 3 MSBs do exist, although they are not connected (don't ask...) */
+ info->i = 15;
+#elif (TMS99XX_MODEL == TMS9900_ID)
+ /* 3 MSBs are external instruction code */
+ info->i = 12;
+#elif (TMS99XX_MODEL == TMS9980_ID)
+ /* 2 bits unused, and 2 MSBs are external instruction code */
+ info->i = 13;
+#elif (TMS99XX_MODEL == TMS9940_ID)
+ /* 9 internal address lines (8 external) */
+ info->i = 9;
+#elif (TMS99XX_MODEL == TMS9995_ID)
+ /* 15-bit address and data bus lines D0-D2 provide the external instruction code */
+ info->i = 15+3;
+#else
+ #warning "I don't know how your processor handles CRU."
+ info->i = 15;
+#endif
+ break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+/* not implemented */
+/* case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = get_irq_line(INPUT_LINE_NMI); break;
+ case CPUINFO_INT_INPUT_STATE + 0: info->i = get_irq_line(0); break;
+ case CPUINFO_INT_INPUT_STATE + 1: info->i = get_irq_line(1); break;
+ case CPUINFO_INT_INPUT_STATE + 2: info->i = get_irq_line(2); break;*/
+
+ case CPUINFO_INT_PREVIOUSPC: /* not implemented */ break;
+
+#if (TMS99XX_MODEL == TI990_10_ID)
+ case CPUINFO_INT_PC:
+ if ((cpustate->cur_map == 0) && (cpustate->PC >= 0xf800))
+ /* intercept TPCS and CPU ROM */
+ info->i = 0x1f0000+cpustate->PC;
+ else if (! cpustate->mapping_on)
+ info->i = cpustate->PC;
+ else
+ {
+ int map_index;
+
+ if (cpustate->PC <= cpustate->map_files[cpustate->cur_map].limit[0])
+ map_index = 0;
+ else if (cpustate->PC <= cpustate->map_files[cpustate->cur_map].limit[1])
+ map_index = 1;
+ else if (cpustate->PC <= cpustate->map_files[cpustate->cur_map].limit[2])
+ map_index = 2;
+ else
+ {
+ info->i = cpustate->PC;
+ break;
+ }
+
+ info->i = cpustate->map_files[cpustate->cur_map].bias[map_index]+cpustate->PC;
+ }
+ break;
+#else
+ case CPUINFO_INT_PC:
+#endif
+ case CPUINFO_INT_REGISTER + TMS9900_PC: info->i = cpustate->PC; break;
+ case CPUINFO_INT_REGISTER + TMS9900_IR: info->i = cpustate->IR; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + TMS9900_WP: info->i = cpustate->WP; break;
+ case CPUINFO_INT_REGISTER + TMS9900_STATUS: setstat(cpustate); info->i = cpustate->STATUS; break;
+ case CPUINFO_INT_REGISTER + TMS9900_R0: info->i = READREG_DEBUG(cpustate, R0); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R1: info->i = READREG_DEBUG(cpustate, R1); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R2: info->i = READREG_DEBUG(cpustate, R2); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R3: info->i = READREG_DEBUG(cpustate, R3); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R4: info->i = READREG_DEBUG(cpustate, R4); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R5: info->i = READREG_DEBUG(cpustate, R5); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R6: info->i = READREG_DEBUG(cpustate, R6); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R7: info->i = READREG_DEBUG(cpustate, R7); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R8: info->i = READREG_DEBUG(cpustate, R8); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R9: info->i = READREG_DEBUG(cpustate, R9); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R10: info->i = READREG_DEBUG(cpustate, R10); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R11: info->i = READREG_DEBUG(cpustate, R11); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R12: info->i = READREG_DEBUG(cpustate, R12); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R13: info->i = READREG_DEBUG(cpustate, R13); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R14: info->i = READREG_DEBUG(cpustate, R14); break;
+ case CPUINFO_INT_REGISTER + TMS9900_R15: info->i = READREG_DEBUG(cpustate, R15); 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(tms99xx); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(tms99xx); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(tms99xx); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(tms99xx); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(tms99xx); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(tms99xx); 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, TMS99XX_device_get_name); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Texas Instruments 9900"); 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, "C TMS9900 emulator by Edward Swartz, initially converted for Mame by M.Coates, updated by R. Nabet"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
+ cpustate->WP & 0x8000 ? 'L':'.',
+ cpustate->WP & 0x4000 ? 'A':'.',
+ cpustate->WP & 0x2000 ? 'E':'.',
+ cpustate->WP & 0x1000 ? 'C':'.',
+ cpustate->WP & 0x0800 ? 'V':'.',
+ cpustate->WP & 0x0400 ? 'P':'.',
+ cpustate->WP & 0x0200 ? 'X':'.',
+ cpustate->WP & 0x0100 ? '?':'.',
+ cpustate->WP & 0x0080 ? '?':'.',
+ cpustate->WP & 0x0040 ? '?':'.',
+ cpustate->WP & 0x0020 ? '?':'.',
+ cpustate->WP & 0x0010 ? '?':'.',
+ cpustate->WP & 0x0008 ? 'I':'.',
+ cpustate->WP & 0x0004 ? 'I':'.',
+ cpustate->WP & 0x0002 ? 'I':'.',
+ cpustate->WP & 0x0001 ? 'I':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + TMS9900_PC: sprintf(info->s, "PC :%04X", cpustate->PC); break;
+ case CPUINFO_STR_REGISTER + TMS9900_IR: sprintf(info->s, "IR :%04X", cpustate->IR); break;
+ case CPUINFO_STR_REGISTER + TMS9900_WP: sprintf(info->s, "WP :%04X", cpustate->WP); break;
+ case CPUINFO_STR_REGISTER + TMS9900_STATUS: sprintf(info->s, "ST :%04X", cpustate->STATUS); break;
+
+ case CPUINFO_STR_REGISTER + TMS9900_R0: sprintf(info->s, "R0 :%04X", READREG_DEBUG(cpustate, R0)); break;
+ case CPUINFO_STR_REGISTER + TMS9900_R1: sprintf(info->s, "R1 :%04X", READREG_DEBUG(cpustate, R1)); break;
+ case CPUINFO_STR_REGISTER + TMS9900_R2: sprintf(info->s, "R2 :%04X", READREG_DEBUG(cpustate, R2)); break;
+ case CPUINFO_STR_REGISTER + TMS9900_R3: sprintf(info->s, "R3 :%04X", READREG_DEBUG(cpustate, R3)); break;
+ case CPUINFO_STR_REGISTER + TMS9900_R4: sprintf(info->s, "R4 :%04X", READREG_DEBUG(cpustate, R4)); break;
+ case CPUINFO_STR_REGISTER + TMS9900_R5: sprintf(info->s, "R5 :%04X", READREG_DEBUG(cpustate, R5)); break;
+ case CPUINFO_STR_REGISTER + TMS9900_R6: sprintf(info->s, "R6 :%04X", READREG_DEBUG(cpustate, R6)); break;
+ case CPUINFO_STR_REGISTER + TMS9900_R7: sprintf(info->s, "R7 :%04X", READREG_DEBUG(cpustate, R7)); break;
+ case CPUINFO_STR_REGISTER + TMS9900_R8: sprintf(info->s, "R8 :%04X", READREG_DEBUG(cpustate, R8)); break;
+ case CPUINFO_STR_REGISTER + TMS9900_R9: sprintf(info->s, "R9 :%04X", READREG_DEBUG(cpustate, R9)); break;
+ case CPUINFO_STR_REGISTER + TMS9900_R10: sprintf(info->s, "R10:%04X", READREG_DEBUG(cpustate, R10)); break;
+ case CPUINFO_STR_REGISTER + TMS9900_R11: sprintf(info->s, "R11:%04X", READREG_DEBUG(cpustate, R11)); break;
+ case CPUINFO_STR_REGISTER + TMS9900_R12: sprintf(info->s, "R12:%04X", READREG_DEBUG(cpustate, R12)); break;
+ case CPUINFO_STR_REGISTER + TMS9900_R13: sprintf(info->s, "R13:%04X", READREG_DEBUG(cpustate, R13)); break;
+ case CPUINFO_STR_REGISTER + TMS9900_R14: sprintf(info->s, "R14:%04X", READREG_DEBUG(cpustate, R14)); break;
+ case CPUINFO_STR_REGISTER + TMS9900_R15: sprintf(info->s, "R15:%04X", READREG_DEBUG(cpustate, R15)); break;
+ }
+}
diff --git a/trunk/src/emu/cpu/tms9900/99xxstat.h b/trunk/src/emu/cpu/tms9900/99xxstat.h
new file mode 100644
index 00000000000..bde84b39928
--- /dev/null
+++ b/trunk/src/emu/cpu/tms9900/99xxstat.h
@@ -0,0 +1,483 @@
+/************************************************************************
+
+ ST register functions
+
+************************************************************************/
+
+/*
+ remember that the OP ST bit is maintained in cpustate->lastparity
+*/
+
+/*
+ setstat sets the ST_OP bit according to cpustate->lastparity
+
+ It must be called before reading the ST register.
+*/
+
+static void setstat(tms99xx_state *cpustate)
+{
+ int i;
+ UINT8 a;
+
+ cpustate->STATUS &= ~ ST_OP;
+
+ /* We set the parity bit. */
+ a = cpustate->lastparity;
+
+ for (i=0; i<8; i++) /* 8 bits to test */
+ {
+ if (a & 1) /* If current bit is set */
+ cpustate->STATUS ^= ST_OP; /* we toggle the ST_OP bit */
+
+ a >>= 1; /* Next bit. */
+ }
+}
+
+/*
+ getstat sets emulator's cpustate->lastparity variable according to 9900's STATUS bits.
+ It must be called on interrupt return, or when, for some reason,
+ the emulated program sets the STATUS register directly.
+*/
+static void getstat(tms99xx_state *cpustate)
+{
+#if (USE_ST_MASK)
+ cpustate->STATUS &= ST_MASK; /* unused bits are forced to 0 */
+#endif
+
+ if (cpustate->STATUS & ST_OP)
+ cpustate->lastparity = 1;
+ else
+ cpustate->lastparity = 0;
+
+#if HAS_MAPPING
+ cpustate->cur_map = (cpustate->STATUS & ST_MF) ? 1 : 0;
+#endif
+}
+
+/*
+ A few words about the following functions.
+
+ A big portability issue is the behavior of the ">>" instruction with the sign bit, which has
+ not been normalised. Every compiler does whatever it thinks smartest.
+ My code assumed that when shifting right signed numbers, the operand is left-filled with a
+ copy of sign bit, and that when shifting unsigned variables, it is left-filled with 0s.
+ This is probably the most logical behaviour, and it is the behavior of CW PRO3 - most time
+ (the exception is that ">>=" instructions always copy the sign bit (!)). But some compilers
+ are bound to disagree.
+
+ So, I had to create special functions with predefined tables included, so that this code work
+ on every compiler. BUT this is a real slow-down.
+ So, you might have to include a few lines in assembly to make this work better.
+ Sorry about this, this problem is really unpleasant and absurd, but it is not my fault.
+*/
+
+
+static const UINT16 right_shift_mask_table[17] =
+{
+ 0xFFFF,
+ 0x7FFF,
+ 0x3FFF,
+ 0x1FFF,
+ 0x0FFF,
+ 0x07FF,
+ 0x03FF,
+ 0x01FF,
+ 0x00FF,
+ 0x007F,
+ 0x003F,
+ 0x001F,
+ 0x000F,
+ 0x0007,
+ 0x0003,
+ 0x0001,
+ 0x0000
+};
+
+static const UINT16 inverted_right_shift_mask_table[17] =
+{
+ 0x0000,
+ 0x8000,
+ 0xC000,
+ 0xE000,
+ 0xF000,
+ 0xF800,
+ 0xFC00,
+ 0xFE00,
+ 0xFF00,
+ 0xFF80,
+ 0xFFC0,
+ 0xFFE0,
+ 0xFFF0,
+ 0xFFF8,
+ 0xFFFC,
+ 0xFFFE,
+ 0xFFFF
+};
+
+INLINE UINT16 logical_right_shift(UINT16 val, int c)
+{
+ return((val>>c) & right_shift_mask_table[c]);
+}
+
+INLINE INT16 arithmetic_right_shift(INT16 val, int c)
+{
+ if (val < 0)
+ return((val>>c) | inverted_right_shift_mask_table[c]);
+ else
+ return((val>>c) & right_shift_mask_table[c]);
+}
+
+
+
+
+
+/*
+ Set lae
+*/
+INLINE void setst_lae(tms99xx_state *cpustate, INT16 val)
+{
+ cpustate->STATUS &= ~ (ST_LGT | ST_AGT | ST_EQ);
+
+ if (val > 0)
+ cpustate->STATUS |= (ST_LGT | ST_AGT);
+ else if (val < 0)
+ cpustate->STATUS |= ST_LGT;
+ else
+ cpustate->STATUS |= ST_EQ;
+}
+
+
+/*
+ Set laep (BYTE)
+*/
+INLINE void setst_byte_laep(tms99xx_state *cpustate, INT8 val)
+{
+ cpustate->STATUS &= ~ (ST_LGT | ST_AGT | ST_EQ);
+
+ if (val > 0)
+ cpustate->STATUS |= (ST_LGT | ST_AGT);
+ else if (val < 0)
+ cpustate->STATUS |= ST_LGT;
+ else
+ cpustate->STATUS |= ST_EQ;
+
+ cpustate->lastparity = val;
+}
+
+/*
+ For COC, CZC, and TB
+*/
+INLINE void setst_e(tms99xx_state *cpustate, UINT16 val, UINT16 to)
+{
+ if (val == to)
+ cpustate->STATUS |= ST_EQ;
+ else
+ cpustate->STATUS &= ~ ST_EQ;
+}
+
+/*
+ For CI, C, CB
+*/
+INLINE void setst_c_lae(tms99xx_state *cpustate, UINT16 to, UINT16 val)
+{
+ cpustate->STATUS &= ~ (ST_LGT | ST_AGT | ST_EQ);
+
+ if (val == to)
+ cpustate->STATUS |= ST_EQ;
+ else
+ {
+ if ( ((INT16) val) > ((INT16) to) )
+ cpustate->STATUS |= ST_AGT;
+ if ( ((UINT16) val) > ((UINT16) to) )
+ cpustate->STATUS |= ST_LGT;
+ }
+}
+
+/*
+ Set laeco for add
+*/
+INLINE INT16 setst_add_laeco(tms99xx_state *cpustate, int a, int b)
+{
+ UINT32 res;
+ INT16 res2;
+
+ cpustate->STATUS &= ~ (ST_LGT | ST_AGT | ST_EQ | ST_C | ST_OV);
+
+ res = (a & 0xffff) + (b & 0xffff);
+
+ if (res & 0x10000)
+ cpustate->STATUS |= ST_C;
+
+ if ((res ^ b) & (res ^ a) & 0x8000)
+ cpustate->STATUS |= ST_OV;
+
+#if (TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID)
+ if (((a & b) | ((a | b) & ~ res)) & 0x0800)
+ cpustate->STATUS |= ST_DC;
+#endif
+
+ res2 = (INT16) res;
+
+ if (res2 > 0)
+ cpustate->STATUS |= ST_LGT | ST_AGT;
+ else if (res2 < 0)
+ cpustate->STATUS |= ST_LGT;
+ else
+ cpustate->STATUS |= ST_EQ;
+
+ return res2;
+}
+
+
+/*
+ Set laeco for subtract
+*/
+INLINE INT16 setst_sub_laeco(tms99xx_state *cpustate, int a, int b)
+{
+ UINT32 res;
+ INT16 res2;
+
+ cpustate->STATUS &= ~ (ST_LGT | ST_AGT | ST_EQ | ST_C | ST_OV);
+
+ res = (a & 0xffff) - (b & 0xffff);
+
+ if (! (res & 0x10000))
+ cpustate->STATUS |= ST_C;
+
+ if ((a ^ b) & (a ^ res) & 0x8000)
+ cpustate->STATUS |= ST_OV;
+
+#if (TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID)
+ if (((a & ~ b) | ((a | ~ b) & ~ res)) & 0x0800)
+ cpustate->STATUS |= ST_DC;
+#endif
+
+ res2 = (INT16) res;
+
+ if (res2 > 0)
+ cpustate->STATUS |= ST_LGT | ST_AGT;
+ else if (res2 < 0)
+ cpustate->STATUS |= ST_LGT;
+ else
+ cpustate->STATUS |= ST_EQ;
+
+ return res2;
+}
+
+
+/*
+ Set laecop for add (BYTE)
+*/
+INLINE INT8 setst_addbyte_laecop(tms99xx_state *cpustate, int a, int b)
+{
+ unsigned int res;
+ INT8 res2;
+
+ cpustate->STATUS &= ~ (ST_LGT | ST_AGT | ST_EQ | ST_C | ST_OV | ST_OP);
+
+ res = (a & 0xff) + (b & 0xff);
+
+ if (res & 0x100)
+ cpustate->STATUS |= ST_C;
+
+ if ((res ^ b) & (res ^ a) & 0x80)
+ cpustate->STATUS |= ST_OV;
+
+#if (TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID)
+ if (((a & b) | ((a | b) & ~ res)) & 0x08)
+ cpustate->STATUS |= ST_DC;
+#endif
+
+ res2 = (INT8) res;
+
+ if (res2 > 0)
+ cpustate->STATUS |= ST_LGT | ST_AGT;
+ else if (res2 < 0)
+ cpustate->STATUS |= ST_LGT;
+ else
+ cpustate->STATUS |= ST_EQ;
+
+ cpustate->lastparity = res2;
+
+ return res2;
+}
+
+
+/*
+ Set laecop for subtract (BYTE)
+*/
+INLINE INT8 setst_subbyte_laecop(tms99xx_state *cpustate, int a, int b)
+{
+ unsigned int res;
+ INT8 res2;
+
+ cpustate->STATUS &= ~ (ST_LGT | ST_AGT | ST_EQ | ST_C | ST_OV | ST_OP);
+
+ res = (a & 0xff) - (b & 0xff);
+
+ if (! (res & 0x100))
+ cpustate->STATUS |= ST_C;
+
+ if ((a ^ b) & (a ^ res) & 0x80)
+ cpustate->STATUS |= ST_OV;
+
+#if (TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID)
+ if (((a & ~ b) | ((a | ~ b) & ~ res)) & 0x08)
+ cpustate->STATUS |= ST_DC;
+#endif
+
+ res2 = (INT8) res;
+
+ if (res2 > 0)
+ cpustate->STATUS |= ST_LGT | ST_AGT;
+ else if (res2 < 0)
+ cpustate->STATUS |= ST_LGT;
+ else
+ cpustate->STATUS |= ST_EQ;
+
+ cpustate->lastparity = res2;
+
+ return res2;
+}
+
+
+
+/*
+ For NEG
+*/
+INLINE void setst_laeo(tms99xx_state *cpustate, INT16 val)
+{
+ cpustate->STATUS &= ~ (ST_LGT | ST_AGT | ST_EQ | ST_OV);
+
+ if (val > 0)
+ cpustate->STATUS |= ST_LGT | ST_AGT;
+ else if (val < 0)
+ {
+ cpustate->STATUS |= ST_LGT;
+ if (((UINT16) val) == 0x8000)
+ cpustate->STATUS |= ST_OV;
+ }
+ else
+ cpustate->STATUS |= ST_EQ;
+}
+
+
+
+/*
+ Meat of SRA
+*/
+INLINE UINT16 setst_sra_laec(tms99xx_state *cpustate, INT16 a, UINT16 c)
+{
+ cpustate->STATUS &= ~ (ST_LGT | ST_AGT | ST_EQ | ST_C);
+
+ if (c != 0)
+ {
+ a = arithmetic_right_shift(a, c-1);
+ if (a & 1) // The carry bit equals the last bit that is shifted out
+ cpustate->STATUS |= ST_C;
+ a = arithmetic_right_shift(a, 1);
+ }
+
+ if (a > 0)
+ cpustate->STATUS |= ST_LGT | ST_AGT;
+ else if (a < 0)
+ cpustate->STATUS |= ST_LGT;
+ else
+ cpustate->STATUS |= ST_EQ;
+
+ return a;
+}
+
+
+/*
+ Meat of SRL. Same algorithm as SRA, except that we fills in with 0s.
+*/
+INLINE UINT16 setst_srl_laec(tms99xx_state *cpustate, UINT16 a,UINT16 c)
+{
+ cpustate->STATUS &= ~ (ST_LGT | ST_AGT | ST_EQ | ST_C);
+
+ if (c != 0)
+ {
+ a = logical_right_shift(a, c-1);
+ if (a & 1)
+ cpustate->STATUS |= ST_C;
+ a = logical_right_shift(a, 1);
+ }
+
+ if (((INT16) a) > 0)
+ cpustate->STATUS |= ST_LGT | ST_AGT;
+ else if (((INT16) a) < 0)
+ cpustate->STATUS |= ST_LGT;
+ else
+ cpustate->STATUS |= ST_EQ;
+
+ return a;
+}
+
+
+//
+// Meat of SRC
+//
+INLINE UINT16 setst_src_laec(tms99xx_state *cpustate, UINT16 a,UINT16 c)
+{
+ cpustate->STATUS &= ~ (ST_LGT | ST_AGT | ST_EQ | ST_C);
+
+ if (c != 0)
+ {
+ a = logical_right_shift(a, c) | (a << (16-c));
+ if (a & 0x8000) // The carry bit equals the last bit that is shifted out
+ cpustate->STATUS |= ST_C;
+ }
+
+ if (((INT16) a) > 0)
+ cpustate->STATUS |= ST_LGT | ST_AGT;
+ else if (((INT16) a) < 0)
+ cpustate->STATUS |= ST_LGT;
+ else
+ cpustate->STATUS |= ST_EQ;
+
+ return a;
+}
+
+
+//
+// Meat of SLA
+//
+INLINE UINT16 setst_sla_laeco(tms99xx_state *cpustate, UINT16 a, UINT16 c)
+{
+ cpustate->STATUS &= ~ (ST_LGT | ST_AGT | ST_EQ | ST_C | ST_OV);
+
+ if (c != 0)
+ {
+ {
+ register UINT16 mask;
+ register UINT16 ousted_bits;
+
+ mask = 0xFFFF << (16-c-1);
+ ousted_bits = a & mask;
+
+ if (ousted_bits) // If ousted_bits is neither all 0s
+ if (ousted_bits ^ mask) // nor all 1s,
+ cpustate->STATUS |= ST_OV; // we set overflow
+ }
+
+ a <<= c-1;
+ if (a & 0x8000) // The carry bit equals the last bit that is shifted out
+ cpustate->STATUS |= ST_C;
+
+ a <<= 1;
+ }
+
+ if (((INT16) a) > 0)
+ cpustate->STATUS |= ST_LGT | ST_AGT;
+ else if (((INT16) a) < 0)
+ cpustate->STATUS |= ST_LGT;
+ else
+ cpustate->STATUS |= ST_EQ;
+
+ return a;
+}
+
+
+/***********************************************************************/
+
diff --git a/trunk/src/emu/cpu/tms9900/ti990_10.c b/trunk/src/emu/cpu/tms9900/ti990_10.c
new file mode 100644
index 00000000000..c15efba995b
--- /dev/null
+++ b/trunk/src/emu/cpu/tms9900/ti990_10.c
@@ -0,0 +1,13 @@
+/*
+ Generate the tms9900 emulator
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "tms9900.h"
+
+#define TMS99XX_MODEL TI990_10_ID
+
+#include "99xxcore.h"
+
+DEFINE_LEGACY_CPU_DEVICE(TI990_10, ti990_10);
diff --git a/trunk/src/emu/cpu/tms9900/tms9900.c b/trunk/src/emu/cpu/tms9900/tms9900.c
new file mode 100644
index 00000000000..7d2c77878fc
--- /dev/null
+++ b/trunk/src/emu/cpu/tms9900/tms9900.c
@@ -0,0 +1,13 @@
+/*
+ Generate the tms9900 emulator
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "tms9900.h"
+
+#define TMS99XX_MODEL TMS9900_ID
+
+#include "99xxcore.h"
+
+DEFINE_LEGACY_CPU_DEVICE(TMS9900, tms9900);
diff --git a/trunk/src/emu/cpu/tms9900/tms9900.h b/trunk/src/emu/cpu/tms9900/tms9900.h
new file mode 100644
index 00000000000..c6decc93378
--- /dev/null
+++ b/trunk/src/emu/cpu/tms9900/tms9900.h
@@ -0,0 +1,210 @@
+/*
+ tms9900.h
+
+ C Header file for TMS9900 core
+*/
+
+#pragma once
+
+#ifndef __TMS9900_H__
+#define __TMS9900_H__
+
+
+/*#define TI990_9_ID 0*//* early implementation, used in a few real-world applications, 1974 */
+ /* very similar to mapper-less 990/10 and tms9900, but the Load process */
+ /* is different */
+ /* ("ti990/9" is likely to be a nickname) */
+#define TI990_10_ID 1 /* original multi-chip implementation for minicomputer systems, 1975 */
+/*#define TI990_12_ID 2*//* multi-chip implementation, faster than 990/10. huge instruction set */
+ /* (144 instructions, with up to 16 additional custom instructions simulteanously) */
+ /* 1979 (or before) */
+#define TMS9900_ID 3 /* mono-chip implementation, 1976 */
+#define TMS9940_ID 4 /* microcontroller with 2kb ROM, 128b RAM, decrementer, CRU bus, 1979 */
+#define TMS9980_ID 5 /* 8-bit variant of tms9900. Two distinct chips actually : tms9980a, */
+ /* and tms9981 with an extra clock and simplified power supply */
+#define TMS9985_ID 6 /* 9940 with 8kb ROM, 256b RAM, and a 8-bit external bus, c. 1978 (never released) */
+#define TMS9989_ID 7 /* improved 9980, used in bombs, missiles, and other *nice* hardware */
+/*#define SBP68689_ID 8*//* improved 9989, built as an ASIC as 9989 was running scarce */
+#define TMS9995_ID 9 /* tms9985-like, with many improvements (but no ROM) */
+#define TMS99000_ID 10/* improved mono-chip implementation, meant to replace 990/10, 1981 */
+ /* This chip is available in several variants (tms99105, tms99110...), */
+ /* which are similar but emulate additional instructions thanks */
+ /* to the so-called macrostore feature. */
+#define TMS99105A_ID 11
+#define TMS99110A_ID 12
+
+
+/* NPW 25-May-2002 - Added these to get it to compile under windows */
+#define TI9940_ID TMS9940_ID
+#define TI9985_ID TMS9985_ID
+
+
+enum
+{
+ TMS9900_PC=1, TMS9900_WP, TMS9900_STATUS, TMS9900_IR,
+ TMS9900_R0, TMS9900_R1, TMS9900_R2, TMS9900_R3,
+ TMS9900_R4, TMS9900_R5, TMS9900_R6, TMS9900_R7,
+ TMS9900_R8, TMS9900_R9, TMS9900_R10, TMS9900_R11,
+ TMS9900_R12, TMS9900_R13, TMS9900_R14, TMS9900_R15
+};
+
+typedef void (*ti99xx_idle_func)(device_t *device, int state);
+typedef void (*ti99xx_rset_func)(device_t *device);
+typedef void (*ti99xx_lrex_func)(device_t *device);
+typedef void (*ti99xx_ckon_ckof_func)(device_t *device, int state);
+typedef void (*ti99xx_error_interrupt_func)(device_t *device, int state);
+
+
+DECLARE_LEGACY_CPU_DEVICE(TI990_10, ti990_10);
+
+/*
+ structure with the parameters ti990_10_reset wants.
+*/
+
+typedef struct ti990_10reset_param
+{
+ ti99xx_idle_func idle_callback;
+ ti99xx_rset_func rset_callback;
+ ti99xx_lrex_func lrex_callback;
+ ti99xx_ckon_ckof_func ckon_ckof_callback;
+ ti99xx_error_interrupt_func error_interrupt_callback;
+} ti990_10reset_param;
+
+/* accessor for the internal ROM */
+extern READ16_HANDLER(ti990_10_internal_r);
+
+/* CRU accessor for the mapper registers (R12 base 0x1fa0) */
+extern READ8_HANDLER(ti990_10_mapper_cru_r);
+extern WRITE8_HANDLER(ti990_10_mapper_cru_w);
+/* CRU accessor for the error interrupt register (R12 base 0x1fc0) */
+extern READ8_HANDLER(ti990_10_eir_cru_r);
+extern WRITE8_HANDLER(ti990_10_eir_cru_w);
+
+
+
+DECLARE_LEGACY_CPU_DEVICE(TMS9900, tms9900);
+
+/*
+ structure with optional parameters for tms9900_reset.
+*/
+typedef struct tms9900reset_param
+{
+ ti99xx_idle_func idle_callback;
+} tms9900reset_param;
+
+
+
+//DECLARE_LEGACY_CPU_DEVICE(TMS9940, tms9940);
+
+/*
+ structure with optional parameters for tms9940_reset.
+*/
+typedef struct tms9940reset_param
+{
+ ti99xx_idle_func idle_callback;
+} tms9940reset_param;
+
+
+
+DECLARE_LEGACY_CPU_DEVICE(TMS9980, tms9980a);
+
+/*
+ structure with optional parameters for tms9980a_reset.
+*/
+typedef struct tms9980areset_param
+{
+ ti99xx_idle_func idle_callback;
+} tms9980areset_param;
+
+
+
+//DECLARE_LEGACY_CPU_DEVICE(TMS9985, tms9985);
+
+/*//
+ structure with optional parameters for tms9985_reset.
+*/
+typedef struct tms9985reset_param
+{
+ ti99xx_idle_func idle_callback;
+} tms9985reset_param;
+
+
+
+//DECLARE_LEGACY_CPU_DEVICE(TMS9989, tms9989);
+
+/*
+ structure with optional parameters for tms9989_reset.
+*/
+typedef struct tms9989reset_param
+{
+ ti99xx_idle_func idle_callback;
+} tms9989reset_param;
+
+
+
+DECLARE_LEGACY_CPU_DEVICE(TMS9995, tms9995);
+
+/*
+ structure with the parameters tms9995_reset wants.
+*/
+typedef struct tms9995reset_param
+{
+ /* auto_wait_state : a non-zero value makes tms9995 generate a wait state automatically on each
+ memory access */
+ int auto_wait_state;
+
+ ti99xx_idle_func idle_callback;
+
+ /* on the tms9995-mp9537, internal RAM and decrementer register are
+ disabled. This chip is used by the ti99/8 so that internal RAM does
+ not prevent the mapper from working correctly. */
+ int is_mp9537;
+} tms9995reset_param;
+
+/* accessor for the first 252 bytes of internal RAM */
+extern READ8_HANDLER(tms9995_internal1_r);
+extern WRITE8_HANDLER(tms9995_internal1_w);
+/* accessors for the last 4 bytes of internal RAM */
+extern READ8_HANDLER(tms9995_internal2_r);
+extern WRITE8_HANDLER(tms9995_internal2_w);
+
+
+
+//DECLARE_LEGACY_CPU_DEVICE(TMS99000, tms99000);
+
+/*
+ structure with optional parameters for tms99000_reset.
+*/
+typedef struct tms99000reset_param
+{
+ ti99xx_idle_func idle_callback;
+} tms99000reset_param;
+
+
+
+//DECLARE_LEGACY_CPU_DEVICE(TMS99105A, tms99105a);
+
+/*
+ structure with optional parameters for tms99105a_reset.
+*/
+typedef struct tms99105areset_param
+{
+ ti99xx_idle_func idle_callback;
+} tms99105areset_param;
+
+
+
+//DECLARE_LEGACY_CPU_DEVICE(TMS99110A, tms99110a);
+
+/*
+ structure with optional parameters for tms99110a_reset.
+*/
+typedef struct tms99110areset_param
+{
+ ti99xx_idle_func idle_callback;
+} tms99110areset_param;
+
+
+unsigned Dasm9900 (char *buffer, unsigned pc, int model_id, const UINT8 *oprom, const UINT8 *opram);
+
+#endif /* __TMS9900_H__ */
diff --git a/trunk/src/emu/cpu/tms9900/tms9980a.c b/trunk/src/emu/cpu/tms9900/tms9980a.c
new file mode 100644
index 00000000000..5ef7444fc86
--- /dev/null
+++ b/trunk/src/emu/cpu/tms9900/tms9980a.c
@@ -0,0 +1,13 @@
+/*
+ generate the tms9980a/tms9981 emulator
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "tms9900.h"
+
+#define TMS99XX_MODEL TMS9980_ID
+
+#include "99xxcore.h"
+
+DEFINE_LEGACY_CPU_DEVICE(TMS9980, tms9980a);
diff --git a/trunk/src/emu/cpu/tms9900/tms9995.c b/trunk/src/emu/cpu/tms9900/tms9995.c
new file mode 100644
index 00000000000..4e0c05a48a7
--- /dev/null
+++ b/trunk/src/emu/cpu/tms9900/tms9995.c
@@ -0,0 +1,13 @@
+/*
+ generate the tms9995 emulator
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "tms9900.h"
+
+#define TMS99XX_MODEL TMS9995_ID
+
+#include "99xxcore.h"
+
+DEFINE_LEGACY_CPU_DEVICE(TMS9995, tms9995);
diff --git a/trunk/src/emu/cpu/uml.c b/trunk/src/emu/cpu/uml.c
new file mode 100644
index 00000000000..7d2ef743a13
--- /dev/null
+++ b/trunk/src/emu/cpu/uml.c
@@ -0,0 +1,1059 @@
+/***************************************************************************
+
+ uml.c
+
+ Universal machine language definitions and classes.
+
+****************************************************************************
+
+ 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 "drcumlsh.h"
+#include <setjmp.h>
+
+using namespace uml;
+
+
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define VALIDATE_BACKEND (0)
+#define LOG_SIMPLIFICATIONS (0)
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// opcode validation condition/flag valid bitmasks
+#define OPFLAGS_NONE 0x00
+#define OPFLAGS_C FLAG_C
+#define OPFLAGS_SZ (FLAG_S | FLAG_Z)
+#define OPFLAGS_SZC (FLAG_S | FLAG_Z | FLAG_C)
+#define OPFLAGS_SZV (FLAG_S | FLAG_Z | FLAG_V)
+#define OPFLAGS_SZVC (FLAG_S | FLAG_Z | FLAG_V | FLAG_C)
+#define OPFLAGS_UZC (FLAG_U | FLAG_Z | FLAG_C)
+#define OPFLAGS_ALL 0x1f
+#define OPFLAGS_P1 0x81
+#define OPFLAGS_P2 0x82
+#define OPFLAGS_P3 0x83
+#define OPFLAGS_P4 0x84
+
+// parameter input/output states
+#define PIO_IN 0x01
+#define PIO_OUT 0x02
+#define PIO_INOUT (PIO_IN | PIO_OUT)
+
+// parameter sizes
+#define PSIZE_4 SIZE_DWORD
+#define PSIZE_8 SIZE_QWORD
+#define PSIZE_OP 0x80
+#define PSIZE_P1 0x81
+#define PSIZE_P2 0x82
+#define PSIZE_P3 0x83
+#define PSIZE_P4 0x84
+
+// basic parameter types
+#define PTYPES_NONE 0
+#define PTYPES_IMM (1 << parameter::PTYPE_IMMEDIATE)
+#define PTYPES_IREG (1 << parameter::PTYPE_INT_REGISTER)
+#define PTYPES_FREG (1 << parameter::PTYPE_FLOAT_REGISTER)
+#define PTYPES_VREG (1 << parameter::PTYPE_VECTOR_REGISTER)
+#define PTYPES_MVAR (1 << parameter::PTYPE_MAPVAR)
+#define PTYPES_MEM (1 << parameter::PTYPE_MEMORY)
+#define PTYPES_SIZE (1 << parameter::PTYPE_SIZE)
+#define PTYPES_SCSIZE (1 << parameter::PTYPE_SIZE_SCALE)
+#define PTYPES_SPSIZE (1 << parameter::PTYPE_SIZE_SPACE)
+#define PTYPES_HANDLE (1 << parameter::PTYPE_CODE_HANDLE)
+#define PTYPES_LABEL (1 << parameter::PTYPE_CODE_LABEL)
+#define PTYPES_CFUNC (1 << parameter::PTYPE_C_FUNCTION)
+#define PTYPES_ROUND (1 << parameter::PTYPE_ROUNDING)
+#define PTYPES_STR (1 << parameter::PTYPE_STRING)
+
+// special parameter types
+#define PTYPES_PTR (PTYPES_MEM | 0x1000)
+#define PTYPES_STATE (PTYPES_MEM | 0x2000)
+
+// combinations of types
+#define PTYPES_IRM (PTYPES_IREG | PTYPES_MEM)
+#define PTYPES_FRM (PTYPES_FREG | PTYPES_MEM)
+#define PTYPES_IMV (PTYPES_IMM | PTYPES_MVAR)
+#define PTYPES_IANY (PTYPES_IRM | PTYPES_IMV)
+#define PTYPES_FANY (PTYPES_FRM)
+
+
+
+//**************************************************************************
+// TABLES
+//**************************************************************************
+
+// macro to simplify the table
+#define PINFO(inout, size, types) { PIO_##inout, PSIZE_##size, PTYPES_##types }
+#define OPINFO0(op,str,sizes,cond,iflag,oflag,mflag) { OP_##op, str, sizes, cond, OPFLAGS_##iflag, OPFLAGS_##oflag, OPFLAGS_##mflag, { { 0 } } },
+#define OPINFO1(op,str,sizes,cond,iflag,oflag,mflag,p0) { OP_##op, str, sizes, cond, OPFLAGS_##iflag, OPFLAGS_##oflag, OPFLAGS_##mflag, { p0 } },
+#define OPINFO2(op,str,sizes,cond,iflag,oflag,mflag,p0,p1) { OP_##op, str, sizes, cond, OPFLAGS_##iflag, OPFLAGS_##oflag, OPFLAGS_##mflag, { p0, p1 } },
+#define OPINFO3(op,str,sizes,cond,iflag,oflag,mflag,p0,p1,p2) { OP_##op, str, sizes, cond, OPFLAGS_##iflag, OPFLAGS_##oflag, OPFLAGS_##mflag, { p0, p1, p2 } },
+#define OPINFO4(op,str,sizes,cond,iflag,oflag,mflag,p0,p1,p2,p3) { OP_##op, str, sizes, cond, OPFLAGS_##iflag, OPFLAGS_##oflag, OPFLAGS_##mflag, { p0, p1, p2, p3 } },
+
+// opcode validation table
+const opcode_info instruction::s_opcode_info_table[OP_MAX] =
+{
+ OPINFO0(INVALID, "invalid", 4, false, NONE, NONE, NONE)
+
+ // Compile-time opcodes
+ OPINFO1(HANDLE, "handle", 4, false, NONE, NONE, NONE, PINFO(IN, OP, HANDLE))
+ OPINFO2(HASH, "hash", 4, false, NONE, NONE, NONE, PINFO(IN, OP, IMV), PINFO(IN, OP, IMV))
+ OPINFO1(LABEL, "label", 4, false, NONE, NONE, NONE, PINFO(IN, OP, LABEL))
+ OPINFO1(COMMENT, "comment", 4, false, NONE, NONE, NONE, PINFO(IN, OP, STR))
+ OPINFO2(MAPVAR, "mapvar", 4, false, NONE, NONE, NONE, PINFO(OUT, OP, MVAR), PINFO(IN, OP, IMV))
+
+ // Control Flow Operations
+ OPINFO0(NOP, "nop", 4, false, NONE, NONE, NONE)
+ OPINFO1(DEBUG, "debug", 4, false, NONE, NONE, ALL, PINFO(IN, OP, IANY))
+ OPINFO1(EXIT, "exit", 4, true, NONE, NONE, ALL, PINFO(IN, OP, IANY))
+ OPINFO3(HASHJMP, "hashjmp", 4, false, NONE, NONE, ALL, PINFO(IN, OP, IANY), PINFO(IN, OP, IANY), PINFO(IN, OP, HANDLE))
+ OPINFO1(JMP, "jmp", 4, true, NONE, NONE, NONE, PINFO(IN, OP, LABEL))
+ OPINFO2(EXH, "exh", 4, true, NONE, NONE, ALL, PINFO(IN, OP, HANDLE), PINFO(IN, OP, IANY))
+ OPINFO1(CALLH, "callh", 4, true, NONE, NONE, ALL, PINFO(IN, OP, HANDLE))
+ OPINFO0(RET, "ret", 4, true, NONE, NONE, ALL)
+ OPINFO2(CALLC, "callc", 4, true, NONE, NONE, ALL, PINFO(IN, OP, CFUNC), PINFO(IN, OP, PTR))
+ OPINFO2(RECOVER, "recover", 4, false, NONE, NONE, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, MVAR))
+
+ // Internal Register Operations
+ OPINFO1(SETFMOD, "setfmod", 4, false, NONE, NONE, ALL, PINFO(IN, OP, IANY))
+ OPINFO1(GETFMOD, "getfmod", 4, false, NONE, NONE, ALL, PINFO(OUT, OP, IRM))
+ OPINFO1(GETEXP, "getexp", 4, false, NONE, NONE, ALL, PINFO(OUT, OP, IRM))
+ OPINFO2(GETFLGS, "getflgs", 4, false, P2, NONE, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IMV))
+ OPINFO1(SAVE, "save", 4, false, ALL, NONE, ALL, PINFO(OUT, OP, STATE))
+ OPINFO1(RESTORE, "restore", 4, false, NONE, ALL, ALL, PINFO(IN, OP, STATE))
+
+ // Integer Operations
+ OPINFO4(LOAD, "!load", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, PTR), PINFO(IN, 4, IANY), PINFO(IN, OP, SCSIZE))
+ OPINFO4(LOADS, "!loads", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, PTR), PINFO(IN, 4, IANY), PINFO(IN, OP, SCSIZE))
+ OPINFO4(STORE, "!store", 4|8, false, NONE, NONE, ALL, PINFO(IN, OP, PTR), PINFO(IN, 4, IANY), PINFO(IN, OP, IANY), PINFO(IN, OP, SCSIZE))
+ OPINFO3(READ, "!read", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, IRM), PINFO(IN, 4, IANY), PINFO(IN, OP, SPSIZE))
+ OPINFO4(READM, "!readm", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, IRM), PINFO(IN, 4, IANY), PINFO(IN, OP, IANY), PINFO(IN, OP, SPSIZE))
+ OPINFO3(WRITE, "!write", 4|8, false, NONE, NONE, ALL, PINFO(IN, 4, IANY), PINFO(IN, OP, IANY), PINFO(IN, OP, SPSIZE))
+ OPINFO4(WRITEM, "!writem", 4|8, false, NONE, NONE, ALL, PINFO(IN, 4, IANY), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY), PINFO(IN, OP, SPSIZE))
+ OPINFO2(CARRY, "!carry", 4|8, false, NONE, C, ALL, PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
+ OPINFO1(SET, "!set", 4|8, true, NONE, NONE, ALL, PINFO(OUT, OP, IRM))
+ OPINFO2(MOV, "!mov", 4|8, true, NONE, NONE, NONE, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY))
+ OPINFO3(SEXT, "!sext", 4|8, false, NONE, SZ, ALL, PINFO(OUT, OP, IRM), PINFO(IN, P3, IANY), PINFO(IN, OP, SIZE))
+ OPINFO4(ROLAND, "!roland", 4|8, false, NONE, SZ, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
+ OPINFO4(ROLINS, "!rolins", 4|8, false, NONE, SZ, ALL, PINFO(INOUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
+ OPINFO3(ADD, "!add", 4|8, false, NONE, SZVC, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
+ OPINFO3(ADDC, "!addc", 4|8, false, C, SZVC, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
+ OPINFO3(SUB, "!sub", 4|8, false, NONE, SZVC, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
+ OPINFO3(SUBB, "!subb", 4|8, false, C, SZVC, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
+ OPINFO2(CMP, "!cmp", 4|8, false, NONE, SZVC, ALL, PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
+ OPINFO4(MULU, "!mulu", 4|8, false, NONE, SZV, ALL, PINFO(OUT, OP, IRM), PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
+ OPINFO4(MULS, "!muls", 4|8, false, NONE, SZV, ALL, PINFO(OUT, OP, IRM), PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
+ OPINFO4(DIVU, "!divu", 4|8, false, NONE, SZV, ALL, PINFO(OUT, OP, IRM), PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
+ OPINFO4(DIVS, "!divs", 4|8, false, NONE, SZV, ALL, PINFO(OUT, OP, IRM), PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
+ OPINFO3(AND, "!and", 4|8, false, NONE, SZ, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
+ OPINFO2(TEST, "!test", 4|8, false, NONE, SZ, ALL, PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
+ OPINFO3(OR, "!or", 4|8, false, NONE, SZ, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
+ OPINFO3(XOR, "!xor", 4|8, false, NONE, SZ, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
+ OPINFO2(LZCNT, "!lzcnt", 4|8, false, NONE, SZ, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY))
+ OPINFO2(BSWAP, "!bswap", 4|8, false, NONE, SZ, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY))
+ OPINFO3(SHL, "!shl", 4|8, false, NONE, SZC, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
+ OPINFO3(SHR, "!shr", 4|8, false, NONE, SZC, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
+ OPINFO3(SAR, "!sar", 4|8, false, NONE, SZC, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
+ OPINFO3(ROL, "!rol", 4|8, false, NONE, SZC, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
+ OPINFO3(ROLC, "!rolc", 4|8, false, C, SZC, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
+ OPINFO3(ROR, "!ror", 4|8, false, NONE, SZC, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
+ OPINFO3(RORC, "!rorc", 4|8, false, C, SZC, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
+
+ // Floating Point Operations
+ OPINFO3(FLOAD, "f#load", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, OP, PTR), PINFO(IN, 4, IANY))
+ OPINFO3(FSTORE, "f#store", 4|8, false, NONE, NONE, ALL, PINFO(IN, OP, PTR), PINFO(IN, 4, IANY), PINFO(IN, OP, FRM))
+ OPINFO3(FREAD, "f#read", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, 4, IANY), PINFO(IN, OP, SPSIZE))
+ OPINFO3(FWRITE, "f#write", 4|8, false, NONE, NONE, ALL, PINFO(IN, 4, IANY), PINFO(IN, OP, FANY), PINFO(IN, OP, SPSIZE))
+ OPINFO2(FMOV, "f#mov", 4|8, true, NONE, NONE, NONE, PINFO(OUT, OP, FRM), PINFO(IN, OP, FANY))
+ OPINFO4(FTOINT, "f#toint", 4|8, false, NONE, NONE, ALL, PINFO(OUT, P3, IRM), PINFO(IN, OP, FANY), PINFO(IN, OP, SIZE), PINFO(IN, OP, ROUND))
+ OPINFO3(FFRINT, "f#frint", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, P3, IANY), PINFO(IN, OP, SIZE))
+ OPINFO3(FFRFLT, "f#frflt", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, P3, FANY), PINFO(IN, OP, SIZE))
+ OPINFO2(FRNDS, "f#rnds", 8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, P3, FANY))
+ OPINFO3(FADD, "f#add", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, OP, FANY), PINFO(IN, OP, FANY))
+ OPINFO3(FSUB, "f#sub", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, OP, FANY), PINFO(IN, OP, FANY))
+ OPINFO2(FCMP, "f#cmp", 4|8, false, NONE, UZC, ALL, PINFO(IN, OP, FANY), PINFO(IN, OP, FANY))
+ OPINFO3(FMUL, "f#mul", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, OP, FANY), PINFO(IN, OP, FANY))
+ OPINFO3(FDIV, "f#div", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, OP, FANY), PINFO(IN, OP, FANY))
+ OPINFO2(FNEG, "f#neg", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, OP, FANY))
+ OPINFO2(FABS, "f#abs", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, OP, FANY))
+ OPINFO2(FSQRT, "f#sqrt", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, OP, FANY))
+ OPINFO2(FRECIP, "f#recip", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, OP, FANY))
+ OPINFO2(FRSQRT, "f#rsqrt", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, OP, FANY))
+};
+
+
+
+//**************************************************************************
+// INLINE FUNCTIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// rol32 - perform a 32-bit left rotate
+//-------------------------------------------------
+
+inline UINT32 rol32(UINT32 source, UINT8 count)
+{
+ count &= 31;
+ return (source << count) | (source >> (32 - count));
+}
+
+
+//-------------------------------------------------
+// rol64 - perform a 64-bit left rotate
+//-------------------------------------------------
+
+inline UINT64 rol64(UINT64 source, UINT8 count)
+{
+ count &= 63;
+ return (source << count) | (source >> (64 - count));
+}
+
+
+
+//**************************************************************************
+// UML CODE HANDLE
+//**************************************************************************
+
+//-------------------------------------------------
+// code_handle - constructor
+//-------------------------------------------------
+
+uml::code_handle::code_handle(drcuml_state &drcuml, const char *name)
+ : m_code(reinterpret_cast<drccodeptr *>(drcuml.cache().alloc_near(sizeof(drccodeptr)))),
+ m_string(name),
+ m_next(NULL),
+ m_drcuml(drcuml)
+{
+ if (m_code == NULL)
+ throw std::bad_alloc();
+ *m_code = NULL;
+}
+
+
+//-------------------------------------------------
+// set_codeptr - set a new code pointer
+//-------------------------------------------------
+
+void uml::code_handle::set_codeptr(drccodeptr code)
+{
+ assert(*m_code == NULL);
+ assert_in_cache(m_drcuml.cache(), code);
+ *m_code = code;
+}
+
+
+
+//**************************************************************************
+// UML INSTRUCTION
+//**************************************************************************
+
+//-------------------------------------------------
+// instruction - constructor
+//-------------------------------------------------
+
+uml::instruction::instruction()
+ : m_opcode(OP_INVALID),
+ m_condition(COND_ALWAYS),
+ m_flags(0),
+ m_size(4),
+ m_numparams(0)
+{
+}
+
+
+//-------------------------------------------------
+// configure - configure an opcode with no
+// parameters
+//-------------------------------------------------
+
+void uml::instruction::configure(opcode_t op, UINT8 size, condition_t condition)
+{
+ // fill in the instruction
+ m_opcode = (opcode_t)(UINT8)op;
+ m_size = size;
+ m_condition = condition;
+ m_flags = 0;
+ m_numparams = 0;
+
+ // validate
+ validate();
+}
+
+
+//-------------------------------------------------
+// configure - configure an opcode with 1
+// parameter
+//-------------------------------------------------
+
+void uml::instruction::configure(opcode_t op, UINT8 size, parameter p0, condition_t condition)
+{
+ // fill in the instruction
+ m_opcode = (opcode_t)(UINT8)op;
+ m_size = size;
+ m_condition = condition;
+ m_flags = 0;
+ m_numparams = 1;
+ m_param[0] = p0;
+
+ // validate
+ validate();
+}
+
+
+//-------------------------------------------------
+// configure - configure an opcode with 2
+// parameters
+//-------------------------------------------------
+
+void uml::instruction::configure(opcode_t op, UINT8 size, parameter p0, parameter p1, condition_t condition)
+{
+ // fill in the instruction
+ m_opcode = (opcode_t)(UINT8)op;
+ m_size = size;
+ m_condition = condition;
+ m_flags = 0;
+ m_numparams = 2;
+ m_param[0] = p0;
+ m_param[1] = p1;
+
+ // validate
+ validate();
+}
+
+
+//-------------------------------------------------
+// configure - configure an opcode with 3
+// parameters
+//-------------------------------------------------
+
+void uml::instruction::configure(opcode_t op, UINT8 size, parameter p0, parameter p1, parameter p2, condition_t condition)
+{
+ // fill in the instruction
+ m_opcode = (opcode_t)(UINT8)op;
+ m_size = size;
+ m_condition = condition;
+ m_flags = 0;
+ m_numparams = 3;
+ m_param[0] = p0;
+ m_param[1] = p1;
+ m_param[2] = p2;
+
+ // validate
+ validate();
+}
+
+
+//-------------------------------------------------
+// configure - configure an opcode with 4
+// parameters
+//-------------------------------------------------
+
+void uml::instruction::configure(opcode_t op, UINT8 size, parameter p0, parameter p1, parameter p2, parameter p3, condition_t condition)
+{
+ // fill in the instruction
+ m_opcode = (opcode_t)(UINT8)op;
+ m_size = size;
+ m_condition = condition;
+ m_flags = 0;
+ m_numparams = 4;
+ m_param[0] = p0;
+ m_param[1] = p1;
+ m_param[2] = p2;
+ m_param[3] = p3;
+
+ // validate
+ validate();
+}
+
+
+//-------------------------------------------------
+// simplify - simplify instructions that have
+// immediate values we can evaluate at compile
+// time
+//-------------------------------------------------
+
+void uml::instruction::simplify()
+{
+ // can't simplify if flags are in play
+ if (m_flags != 0)
+ return;
+
+ static const UINT64 instsizemask[] = { 0, 0, 0, 0, 0xffffffff, 0, 0, 0, U64(0xffffffffffffffff) };
+ static const UINT64 paramsizemask[] = { 0xff, 0xffff, 0xffffffff, U64(0xffffffffffffffff) };
+
+ // loop until we've simplified all we can
+ opcode_t origop;
+ do
+ {
+ // switch off the opcode
+ origop = m_opcode;
+ switch (m_opcode)
+ {
+ // READM: convert to READ if the mask is wide open
+ case OP_READM:
+ if (m_param[2].is_immediate_value(paramsizemask[m_param[3].size()]))
+ {
+ m_opcode = OP_READ;
+ m_numparams = 2;
+ m_param[2] = m_param[3];
+ }
+ break;
+
+ // WRITEM: convert to WRITE if the mask is wide open
+ case OP_WRITEM:
+ if (m_param[2].is_immediate_value(paramsizemask[m_param[3].size()]))
+ {
+ m_opcode = OP_WRITE;
+ m_numparams = 2;
+ m_param[2] = m_param[3];
+ }
+ break;
+
+ // SET: convert to MOV if constant condition
+ case OP_SET:
+ if (m_condition == COND_ALWAYS)
+ convert_to_mov_immediate(1);
+ break;
+
+ // MOV: convert to NOP if move-to-self
+ case OP_MOV:
+ if (m_param[0] == m_param[1])
+ nop();
+ break;
+
+ // SEXT: convert immediates to MOV
+ case OP_SEXT:
+ if (m_param[1].is_immediate())
+ switch (m_param[2].size())
+ {
+ case SIZE_BYTE: convert_to_mov_immediate((INT8)m_param[1].immediate()); break;
+ case SIZE_WORD: convert_to_mov_immediate((INT16)m_param[1].immediate()); break;
+ case SIZE_DWORD: convert_to_mov_immediate((INT32)m_param[1].immediate()); break;
+ case SIZE_QWORD: convert_to_mov_immediate((INT64)m_param[1].immediate()); break;
+ case SIZE_DQWORD: fatalerror("Invalid SEXT target size"); break;
+ }
+ break;
+
+ // ROLAND: convert to MOV if all immediate, or to ROL or AND if one is not needed, or to SHL/SHR if the mask is right
+ case OP_ROLAND:
+ if (m_param[1].is_immediate() && m_param[2].is_immediate() && m_param[3].is_immediate())
+ {
+ assert(m_size == 4 || m_size == 8);
+ if (m_size == 4)
+ convert_to_mov_immediate(rol32(m_param[1].immediate(), m_param[2].immediate()) & m_param[3].immediate());
+ else
+ convert_to_mov_immediate(rol64(m_param[1].immediate(), m_param[2].immediate()) & m_param[3].immediate());
+ }
+ else if (m_param[2].is_immediate_value(0))
+ {
+ m_opcode = OP_AND;
+ m_numparams = 3;
+ m_param[2] = m_param[3];
+ }
+ else if (m_param[3].is_immediate_value(instsizemask[m_size]))
+ {
+ m_opcode = OP_ROL;
+ m_numparams = 3;
+ }
+ else if (m_param[2].is_immediate() && m_param[3].is_immediate_value((U64(0xffffffffffffffff) << m_param[2].immediate()) & instsizemask[m_size]))
+ {
+ m_opcode = OP_SHL;
+ m_numparams = 3;
+ }
+ else if (m_param[2].is_immediate() && m_param[3].is_immediate_value(instsizemask[m_size] >> (8 * m_size - m_param[2].immediate())))
+ {
+ m_opcode = OP_SHR;
+ m_numparams = 3;
+ m_param[2] = 8 * m_size - m_param[2].immediate();
+ }
+ break;
+
+ // ROLINS: convert to ROLAND if the mask is full
+ case OP_ROLINS:
+ if (m_param[3].is_immediate_value(instsizemask[m_size]))
+ m_opcode = OP_ROLAND;
+ break;
+
+ // ADD: convert to MOV if immediate, or if adding 0
+ case OP_ADD:
+ if (m_param[1].is_immediate() && m_param[2].is_immediate())
+ convert_to_mov_immediate(m_param[1].immediate() + m_param[2].immediate());
+ else if (m_param[1].is_immediate_value(0))
+ convert_to_mov_param(2);
+ else if (m_param[2].is_immediate_value(0))
+ convert_to_mov_param(1);
+ break;
+
+ // SUB: convert to MOV if immediate, or if subtracting 0
+ case OP_SUB:
+ if (m_param[1].is_immediate() && m_param[2].is_immediate())
+ convert_to_mov_immediate(m_param[1].immediate() - m_param[2].immediate());
+ else if (m_param[2].is_immediate_value(0))
+ convert_to_mov_param(1);
+ break;
+
+ // CMP: no-op if no flags needed, compare i0 to i0 if the parameters are equal
+ case OP_CMP:
+ if (m_flags == 0)
+ nop();
+ else if (m_param[0] == m_param[1])
+ cmp(I0, I0);
+ break;
+
+ // MULU: convert simple form to MOV if immediate, or if multiplying by 0
+ case OP_MULU:
+ if (m_param[0] == m_param[1])
+ {
+ if (m_param[2].is_immediate_value(0) || m_param[3].is_immediate_value(0))
+ convert_to_mov_immediate(0);
+ else if (m_param[2].is_immediate() && m_param[3].is_immediate())
+ {
+ if (m_size == 4)
+ convert_to_mov_immediate((UINT32)((UINT32)m_param[1].immediate() * (UINT32)m_param[2].immediate()));
+ else if (m_size == 8)
+ convert_to_mov_immediate((UINT64)((UINT64)m_param[1].immediate() * (UINT64)m_param[2].immediate()));
+ }
+ }
+ break;
+
+ // MULS: convert simple form to MOV if immediate, or if multiplying by 0
+ case OP_MULS:
+ if (m_param[0] == m_param[1])
+ {
+ if (m_param[2].is_immediate_value(0) || m_param[3].is_immediate_value(0))
+ convert_to_mov_immediate(0);
+ else if (m_param[2].is_immediate() && m_param[3].is_immediate())
+ {
+ if (m_size == 4)
+ convert_to_mov_immediate((INT32)((INT32)m_param[1].immediate() * (INT32)m_param[2].immediate()));
+ else if (m_size == 8)
+ convert_to_mov_immediate((INT64)((INT64)m_param[1].immediate() * (INT64)m_param[2].immediate()));
+ }
+ }
+ break;
+
+ // DIVU: convert simple form to MOV if immediate, or if dividing with 0
+ case OP_DIVU:
+ if (m_param[0] == m_param[1] && !m_param[3].is_immediate_value(0))
+ {
+ if (m_param[2].is_immediate_value(0))
+ convert_to_mov_immediate(0);
+ else if (m_param[2].is_immediate() && m_param[3].is_immediate())
+ {
+ if (m_size == 4)
+ convert_to_mov_immediate((UINT32)((UINT32)m_param[1].immediate() / (UINT32)m_param[2].immediate()));
+ else if (m_size == 8)
+ convert_to_mov_immediate((UINT64)((UINT64)m_param[1].immediate() / (UINT64)m_param[2].immediate()));
+ }
+ }
+ break;
+
+ // DIVS: convert simple form to MOV if immediate, or if dividing with 0
+ case OP_DIVS:
+ if (m_param[0] == m_param[1] && !m_param[3].is_immediate_value(0))
+ {
+ if (m_param[2].is_immediate_value(0))
+ convert_to_mov_immediate(0);
+ else if (m_param[2].is_immediate() && m_param[3].is_immediate())
+ {
+ if (m_size == 4)
+ convert_to_mov_immediate((INT32)((INT32)m_param[1].immediate() / (INT32)m_param[2].immediate()));
+ else if (m_size == 8)
+ convert_to_mov_immediate((INT64)((INT64)m_param[1].immediate() / (INT64)m_param[2].immediate()));
+ }
+ }
+ break;
+
+ // AND: convert to MOV if immediate, or if anding against 0 or 0xffffffff
+ case OP_AND:
+ if (m_param[1].is_immediate_value(0) || m_param[2].is_immediate_value(0))
+ convert_to_mov_immediate(0);
+ else if (m_param[1].is_immediate() && m_param[2].is_immediate())
+ convert_to_mov_immediate(m_param[1].immediate() & m_param[2].immediate());
+ else if (m_param[1].is_immediate_value(instsizemask[m_size]))
+ convert_to_mov_param(2);
+ else if (m_param[2].is_immediate_value(instsizemask[m_size]))
+ convert_to_mov_param(1);
+ break;
+
+ // TEST: no-op if no flags needed
+ case OP_TEST:
+ if (m_flags == 0)
+ nop();
+ break;
+
+ // OR: convert to MOV if immediate, or if oring against 0 or 0xffffffff
+ case OP_OR:
+ if (m_param[1].is_immediate_value(instsizemask[m_size]) || m_param[2].is_immediate_value(instsizemask[m_size]))
+ convert_to_mov_immediate(instsizemask[m_size]);
+ else if (m_param[1].is_immediate() && m_param[2].is_immediate())
+ convert_to_mov_immediate(m_param[1].immediate() | m_param[2].immediate());
+ else if (m_param[1].is_immediate_value(0))
+ convert_to_mov_param(2);
+ else if (m_param[2].is_immediate_value(0))
+ convert_to_mov_param(1);
+ break;
+
+ // XOR: convert to MOV if immediate, or if xoring against 0
+ case OP_XOR:
+ if (m_param[1].is_immediate() && m_param[2].is_immediate())
+ convert_to_mov_immediate(m_param[1].immediate() ^ m_param[2].immediate());
+ else if (m_param[1].is_immediate_value(0))
+ convert_to_mov_param(2);
+ else if (m_param[2].is_immediate_value(0))
+ convert_to_mov_param(1);
+ break;
+
+ // LZCNT: convert to MOV if immediate
+ case OP_LZCNT:
+ if (m_param[1].is_immediate())
+ {
+ if (m_size == 4)
+ convert_to_mov_immediate(count_leading_zeros(m_param[1].immediate()));
+ else if (m_size == 8)
+ {
+ if ((m_param[1].immediate() >> 32) == 0)
+ convert_to_mov_immediate(32 + count_leading_zeros(m_param[1].immediate()));
+ else
+ convert_to_mov_immediate(count_leading_zeros(m_param[1].immediate() >> 32));
+ }
+ }
+ break;
+
+ // BSWAP: convert to MOV if immediate
+ case OP_BSWAP:
+ if (m_param[1].is_immediate())
+ {
+ if (m_size == 4)
+ convert_to_mov_immediate(FLIPENDIAN_INT32(m_param[1].immediate()));
+ else if (m_size == 8)
+ convert_to_mov_immediate(FLIPENDIAN_INT64(m_param[1].immediate()));
+ }
+ break;
+
+ // SHL: convert to MOV if immediate or shifting by 0
+ case OP_SHL:
+ if (m_param[1].is_immediate() && m_param[2].is_immediate())
+ convert_to_mov_immediate(m_param[1].immediate() << m_param[2].immediate());
+ else if (m_param[2].is_immediate_value(0))
+ convert_to_mov_param(1);
+ break;
+
+ // SHR: convert to MOV if immediate or shifting by 0
+ case OP_SHR:
+ if (m_param[1].is_immediate() && m_param[2].is_immediate())
+ {
+ if (m_size == 4)
+ convert_to_mov_immediate((UINT32)m_param[1].immediate() >> m_param[2].immediate());
+ else if (m_size == 8)
+ convert_to_mov_immediate((UINT64)m_param[1].immediate() >> m_param[2].immediate());
+ }
+ else if (m_param[2].is_immediate_value(0))
+ convert_to_mov_param(1);
+ break;
+
+ // SAR: convert to MOV if immediate or shifting by 0
+ case OP_SAR:
+ if (m_param[1].is_immediate() && m_param[2].is_immediate())
+ {
+ if (m_size == 4)
+ convert_to_mov_immediate((INT32)m_param[1].immediate() >> m_param[2].immediate());
+ else if (m_size == 8)
+ convert_to_mov_immediate((INT64)m_param[1].immediate() >> m_param[2].immediate());
+ }
+ else if (m_param[2].is_immediate_value(0))
+ convert_to_mov_param(1);
+ break;
+
+ // ROL: convert to NOP if immediate or rotating by 0
+ case OP_ROL:
+ if (m_param[1].is_immediate() && m_param[2].is_immediate())
+ {
+ if (m_size == 4)
+ convert_to_mov_immediate(rol32(m_param[1].immediate(), m_param[2].immediate()));
+ else if (m_size == 8)
+ convert_to_mov_immediate(rol64(m_param[1].immediate(), m_param[2].immediate()));
+ }
+ else if (m_param[2].is_immediate_value(0))
+ convert_to_mov_param(1);
+ break;
+
+ // ROR: convert to NOP if immediate or rotating by 0
+ case OP_ROR:
+ if (m_param[1].is_immediate() && m_param[2].is_immediate())
+ {
+ if (m_size == 4)
+ convert_to_mov_immediate(rol32(m_param[1].immediate(), 32 - m_param[2].immediate()));
+ else if (m_size == 8)
+ convert_to_mov_immediate(rol64(m_param[1].immediate(), 64 - m_param[2].immediate()));
+ }
+ else if (m_param[2].is_immediate_value(0))
+ convert_to_mov_param(1);
+ break;
+
+ // FMOV: convert to NOP if move-to-self
+ case OP_FMOV:
+ if (m_param[0] == m_param[1])
+ nop();
+ break;
+
+ default:
+ break;
+ }
+
+ /*
+ if (LOG_SIMPLIFICATIONS && memcmp(&orig, inst, sizeof(orig)) != 0)
+ {
+ astring disasm1, disasm2;
+ orig.disasm(disasm1, block->drcuml);
+ inst->disasm(disasm2, block->drcuml);
+ mame_printf_debug("Simplified: %-50.50s -> %s\n", disasm1.cstr(), disasm2.cstr());
+ }
+ */
+
+ // loop until we stop changing opcodes
+ } while (m_opcode != origop);
+}
+
+
+//-------------------------------------------------
+// validate - verify that the instruction created
+// meets all requirements
+//-------------------------------------------------
+
+void uml::instruction::validate()
+{
+#ifdef MAME_DEBUG
+ const opcode_info &opinfo = s_opcode_info_table[m_opcode];
+ assert(opinfo.opcode == m_opcode);
+
+ // validate raw information
+ assert(m_opcode != OP_INVALID && m_opcode < OP_MAX);
+ assert(m_size == 1 || m_size == 2 || m_size == 4 || m_size == 8);
+
+ // validate against opcode limits
+ assert((opinfo.sizes & m_size) != 0);
+ assert(m_condition == COND_ALWAYS || opinfo.condition);
+
+ // validate each parameter
+ for (int pnum = 0; pnum < m_numparams; pnum++)
+ {
+ // ensure the type is valid
+ const parameter &param = m_param[pnum];
+ assert((opinfo.param[pnum].typemask >> param.type()) & 1);
+ }
+
+ // make sure we aren't missing any parameters
+ if (m_numparams < ARRAY_LENGTH(opinfo.param))
+ assert(opinfo.param[m_numparams].typemask == 0);
+#endif
+}
+
+
+//-------------------------------------------------
+// input_flags - return the effective input flags
+// based on any conditions encoded in an
+// instruction
+//-------------------------------------------------
+
+UINT8 uml::instruction::input_flags() const
+{
+ static const UINT8 flags_for_condition[] =
+ {
+ FLAG_Z, // COND_Z
+ FLAG_Z, // COND_NZ
+ FLAG_S, // COND_S
+ FLAG_S, // COND_NS
+ FLAG_C, // COND_C
+ FLAG_C, // COND_NC
+ FLAG_V, // COND_V
+ FLAG_V, // COND_NV
+ FLAG_U, // COND_U
+ FLAG_U, // COND_NU
+ FLAG_C | FLAG_Z, // COND_A
+ FLAG_C | FLAG_Z, // COND_BE
+ FLAG_S | FLAG_V | FLAG_Z, // COND_G
+ FLAG_S | FLAG_V | FLAG_Z, // COND_LE
+ FLAG_S | FLAG_V, // COND_L
+ FLAG_S | FLAG_V // COND_GE
+ };
+
+ UINT8 flags = s_opcode_info_table[m_opcode].inflags;
+ if (flags & 0x80)
+ flags = m_param[flags - OPFLAGS_P1].immediate() & OPFLAGS_ALL;
+ if (m_condition != COND_ALWAYS)
+ flags |= flags_for_condition[m_condition & 0x0f];
+ return flags;
+}
+
+
+//-------------------------------------------------
+// output_flags - return the effective output
+// flags based on any conditions encoded in an
+// instruction
+//-------------------------------------------------
+
+UINT8 uml::instruction::output_flags() const
+{
+ UINT8 flags = s_opcode_info_table[m_opcode].outflags;
+ if (flags & 0x80)
+ flags = m_param[flags - OPFLAGS_P1].immediate() & OPFLAGS_ALL;
+ return flags;
+}
+
+
+//-------------------------------------------------
+// modified_flags - return the effective output
+// flags based on any conditions encoded in an
+// instruction
+//-------------------------------------------------
+
+UINT8 uml::instruction::modified_flags() const
+{
+ return s_opcode_info_table[m_opcode].modflags;
+}
+
+
+//-------------------------------------------------
+// disasm - disassemble an instruction to the
+// given buffer
+//-------------------------------------------------
+
+const char *uml::instruction::disasm(astring &buffer, drcuml_state *drcuml) const
+{
+ static const char *const conditions[] = { "z", "nz", "s", "ns", "c", "nc", "v", "nv", "u", "nu", "a", "be", "g", "le", "l", "ge" };
+ static const char *const pound_size[] = { "?", "?", "?", "?", "s", "?", "?", "?", "d" };
+ static const char *const bang_size[] = { "?", "b", "h", "?", "", "?", "?", "?", "d" };
+ static const char *const fmods[] = { "trunc", "round", "ceil", "floor", "default" };
+ static const char *const spaces[] = { "program", "data", "io", "3", "4", "5", "6", "7" };
+ static const char *const sizes[] = { "byte", "word", "dword", "qword" };
+
+ const opcode_info &opinfo = s_opcode_info_table[m_opcode];
+
+ assert(m_opcode != OP_INVALID && m_opcode < OP_MAX);
+
+ // start with the raw mnemonic and substitute sizes
+ buffer.reset();
+ for (const char *opsrc = opinfo.mnemonic; *opsrc != 0; opsrc++)
+ if (*opsrc == '!')
+ buffer.catprintf("%s", bang_size[m_size]);
+ else if (*opsrc == '#')
+ buffer.catprintf("%s", pound_size[m_size]);
+ else
+ buffer.cat(*opsrc);
+
+ // pad to 8 spaces
+ int pad = 8 - buffer.len();
+ for (int ch = 0; ch < pad; ch++)
+ buffer.cat(' ');
+
+ // iterate through parameters
+ for (int pnum = 0; pnum < m_numparams; pnum++)
+ {
+ const parameter &param = m_param[pnum];
+
+ // start with a comma for all except the first parameter
+ if (pnum != 0)
+ buffer.cat(',');
+
+ // ouput based on type
+ switch (param.type())
+ {
+ // immediates have several special cases
+ case parameter::PTYPE_IMMEDIATE:
+ {
+ // determine the size of the immediate
+ int size;
+ switch (opinfo.param[pnum].size)
+ {
+ case PSIZE_4: size = 4; break;
+ case PSIZE_8: size = 8; break;
+ case PSIZE_P1: size = 1 << m_param[0].size(); break;
+ case PSIZE_P2: size = 1 << m_param[1].size(); break;
+ case PSIZE_P3: size = 1 << m_param[2].size(); break;
+ case PSIZE_P4: size = 1 << m_param[3].size(); break;
+ default:
+ case PSIZE_OP: size = m_size; break;
+ }
+
+ // truncate to size
+ UINT64 value = param.immediate();
+ if (size == 1) value = (UINT8)value;
+ if (size == 2) value = (UINT16)value;
+ if (size == 4) value = (UINT32)value;
+ if ((UINT32)value == value)
+ buffer.catprintf("$%X", (UINT32)value);
+ else
+ buffer.catprintf("$%X%08X", (UINT32)(value >> 32), (UINT32)value);
+ }
+ break;
+
+ // immediates have several special cases
+ case parameter::PTYPE_SIZE:
+ buffer.catprintf("%s", sizes[param.size()]);
+ break;
+
+ // size + address space immediate
+ case parameter::PTYPE_SIZE_SPACE:
+ buffer.catprintf("%s_%s", spaces[param.space()], sizes[param.size()]);
+ break;
+
+ // size + scale immediate
+ case parameter::PTYPE_SIZE_SCALE:
+ {
+ int scale = param.scale();
+ int size = param.size();
+ if (scale == size)
+ buffer.catprintf("%s", sizes[size]);
+ else
+ buffer.catprintf("%s_x%d", sizes[size], 1 << scale);
+ }
+ break;
+
+ // fmod immediate
+ case parameter::PTYPE_ROUNDING:
+ buffer.catprintf("%s", fmods[param.rounding()]);
+ break;
+
+ // integer registers
+ case parameter::PTYPE_INT_REGISTER:
+ buffer.catprintf("i%d", param.ireg() - REG_I0);
+ break;
+
+ // floating point registers
+ case parameter::PTYPE_FLOAT_REGISTER:
+ buffer.catprintf("f%d", param.freg() - REG_F0);
+ break;
+
+ // map variables
+ case parameter::PTYPE_MAPVAR:
+ buffer.catprintf("m%d", param.mapvar() - MAPVAR_M0);
+ break;
+
+ // memory
+ case parameter::PTYPE_MEMORY:
+ {
+ const char *symbol;
+ UINT32 symoffset;
+
+ // symbol
+ if (drcuml != NULL && (symbol = drcuml->symbol_find(param.memory(), &symoffset)) != NULL)
+ {
+ if (symoffset == 0)
+ buffer.catprintf("[%s]", symbol);
+ else
+ buffer.catprintf("[%s+$%X]", symbol, symoffset);
+ }
+
+ // cache memory
+ else if (drcuml != NULL && drcuml->cache().contains_pointer(param.memory()))
+ buffer.catprintf("[+$%X]", (UINT32)(FPTR)((drccodeptr)param.memory() - drcuml->cache().near()));
+
+ // general memory
+ else
+ buffer.catprintf("[[$%p]]", param.memory());
+ break;
+ }
+
+ // string pointer
+ case parameter::PTYPE_STRING:
+ buffer.catprintf("%s", (const char *)(FPTR)param.string());
+ break;
+
+ // handle pointer
+ case parameter::PTYPE_CODE_HANDLE:
+ buffer.catprintf("%s", param.handle().string());
+ break;
+
+ default:
+ buffer.catprintf("???");
+ break;
+ }
+ }
+
+ // if there's a condition, append it
+ if (m_condition != COND_ALWAYS)
+ buffer.catprintf(",%s", conditions[m_condition & 0x0f]);
+
+ // if there are flags, append them
+ if (m_flags != 0)
+ {
+ buffer.cat(',');
+ if (m_flags & FLAG_U)
+ buffer.cat('U');
+ if (m_flags & FLAG_S)
+ buffer.cat('S');
+ if (m_flags & FLAG_Z)
+ buffer.cat('Z');
+ if (m_flags & FLAG_V)
+ buffer.cat('V');
+ if (m_flags & FLAG_C)
+ buffer.cat('C');
+ }
+ return buffer;
+}
diff --git a/trunk/src/emu/cpu/uml.h b/trunk/src/emu/cpu/uml.h
new file mode 100644
index 00000000000..f90f8ccd7d6
--- /dev/null
+++ b/trunk/src/emu/cpu/uml.h
@@ -0,0 +1,690 @@
+/***************************************************************************
+
+ uml.h
+
+ Universal machine language definitions and classes.
+
+****************************************************************************
+
+ 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 __UML_H__
+#define __UML_H__
+
+#include "drccache.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// opaque structure describing UML generation state
+class drcuml_state;
+
+struct drcuml_machine_state;
+
+
+// use a namespace to wrap all the UML instruction concepts so that
+// we can keep names short
+namespace uml
+{
+ // integer registers
+ const int REG_I0 = 0x400;
+ const int REG_I_COUNT = 10;
+ const int REG_I_END = REG_I0 + REG_I_COUNT;
+
+ // floating point registers
+ const int REG_F0 = 0x800;
+ const int REG_F_COUNT = 10;
+ const int REG_F_END = REG_F0 + REG_F_COUNT;
+
+ // vector registers
+ const int REG_V0 = 0xc00;
+ const int REG_V_COUNT = 10;
+ const int REG_V_END = REG_V0 + REG_V_COUNT;
+
+ // map variables
+ const int MAPVAR_M0 = 0x1000;
+ const int MAPVAR_COUNT = 10;
+ const int MAPVAR_END = MAPVAR_M0 + MAPVAR_COUNT;
+
+ // flag definitions
+ const UINT8 FLAG_C = 0x01; // carry flag
+ const UINT8 FLAG_V = 0x02; // overflow flag (defined for integer only)
+ const UINT8 FLAG_Z = 0x04; // zero flag
+ const UINT8 FLAG_S = 0x08; // sign flag (defined for integer only)
+ const UINT8 FLAG_U = 0x10; // unordered flag (defined for FP only)
+
+ // testable conditions; note that these are defined such that (condition ^ 1) is
+ // always the opposite
+ enum condition_t
+ {
+ COND_ALWAYS = 0,
+
+ COND_Z = 0x80, // requires Z
+ COND_NZ, // requires Z
+ COND_S, // requires S
+ COND_NS, // requires S
+ COND_C, // requires C
+ COND_NC, // requires C
+ COND_V, // requires V
+ COND_NV, // requires V
+ COND_U, // requires U
+ COND_NU, // requires U
+ COND_A, // requires CZ
+ COND_BE, // requires CZ
+ COND_G, // requires SVZ
+ COND_LE, // requires SVZ
+ COND_L, // requires SV
+ COND_GE, // requires SV
+
+ COND_MAX,
+
+ // basic condition code aliases
+ COND_E = COND_Z,
+ COND_NE = COND_NZ,
+ COND_B = COND_C,
+ COND_AE = COND_NC
+ };
+
+ // floating point rounding modes
+ enum float_rounding_mode
+ {
+ ROUND_TRUNC = 0, // truncate
+ ROUND_ROUND, // round
+ ROUND_CEIL, // round up
+ ROUND_FLOOR, // round down
+ ROUND_DEFAULT
+ };
+
+ // operand sizes
+ enum operand_size
+ {
+ SIZE_BYTE = 0, // 1-byte
+ SIZE_WORD, // 2-byte
+ SIZE_DWORD, // 4-byte
+ SIZE_QWORD, // 8-byte
+ SIZE_DQWORD, // 16-byte (vector)
+ SIZE_SHORT = SIZE_DWORD, // 4-byte (float)
+ SIZE_DOUBLE = SIZE_QWORD // 8-byte (float)
+ };
+
+ // memory scale factors
+ enum memory_scale
+ {
+ SCALE_x1 = 0, // index * 1
+ SCALE_x2, // index * 2
+ SCALE_x4, // index * 4
+ SCALE_x8, // index * 8
+ SCALE_DEFAULT
+ };
+
+ // spaces
+ enum memory_space
+ {
+ SPACE_PROGRAM = AS_PROGRAM,
+ SPACE_DATA = AS_DATA,
+ SPACE_IO = AS_IO
+ };
+
+ // opcodes
+ enum opcode_t
+ {
+ OP_INVALID,
+
+ // compile-time opcodes
+ OP_HANDLE, // HANDLE handle
+ OP_HASH, // HASH mode,pc
+ OP_LABEL, // LABEL imm
+ OP_COMMENT, // COMMENT string
+ OP_MAPVAR, // MAPVAR mapvar,value
+
+ // control flow operations
+ OP_NOP, // NOP
+ OP_DEBUG, // DEBUG pc
+ OP_EXIT, // EXIT src1[,c]
+ OP_HASHJMP, // HASHJMP mode,pc,handle
+ OP_JMP, // JMP imm[,c]
+ OP_EXH, // EXH handle,param[,c]
+ OP_CALLH, // CALLH handle[,c]
+ OP_RET, // RET [c]
+ OP_CALLC, // CALLC func,ptr[,c]
+ OP_RECOVER, // RECOVER dst,mapvar
+
+ // internal register operations
+ OP_SETFMOD, // SETFMOD src
+ OP_GETFMOD, // GETFMOD dst
+ OP_GETEXP, // GETEXP dst
+ OP_GETFLGS, // GETFLGS dst[,f]
+ OP_SAVE, // SAVE mem
+ OP_RESTORE, // RESTORE mem
+
+ // integer operations
+ OP_LOAD, // LOAD dst,base,index,size
+ OP_LOADS, // LOADS dst,base,index,size
+ OP_STORE, // STORE base,index,src,size
+ OP_READ, // READ dst,src1,space/size
+ OP_READM, // READM dst,src1,mask,space/size
+ OP_WRITE, // WRITE dst,src1,space/size
+ OP_WRITEM, // WRITEM dst,mask,src1,space/size
+ OP_CARRY, // CARRY src,bitnum
+ OP_SET, // SET dst,c
+ OP_MOV, // MOV dst,src[,c]
+ OP_SEXT, // SEXT dst,src,size
+ OP_ROLAND, // ROLAND dst,src,shift,mask
+ OP_ROLINS, // ROLINS dst,src,shift,mask
+ OP_ADD, // ADD dst,src1,src2[,f]
+ OP_ADDC, // ADDC dst,src1,src2[,f]
+ OP_SUB, // SUB dst,src1,src2[,f]
+ OP_SUBB, // SUBB dst,src1,src2[,f]
+ OP_CMP, // CMP src1,src2[,f]
+ OP_MULU, // MULU dst,edst,src1,src2[,f]
+ OP_MULS, // MULS dst,edst,src1,src2[,f]
+ OP_DIVU, // DIVU dst,edst,src1,src2[,f]
+ OP_DIVS, // DIVS dst,edst,src1,src2[,f]
+ OP_AND, // AND dst,src1,src2[,f]
+ OP_TEST, // TEST src1,src2[,f]
+ OP_OR, // OR dst,src1,src2[,f]
+ OP_XOR, // XOR dst,src1,src2[,f]
+ OP_LZCNT, // LZCNT dst,src
+ OP_BSWAP, // BSWAP dst,src
+ OP_SHL, // SHL dst,src,count[,f]
+ OP_SHR, // SHR dst,src,count[,f]
+ OP_SAR, // SAR dst,src,count[,f]
+ OP_ROL, // ROL dst,src,count[,f]
+ OP_ROLC, // ROLC dst,src,count[,f]
+ OP_ROR, // ROL dst,src,count[,f]
+ OP_RORC, // ROLC dst,src,count[,f]
+
+ // floating point operations
+ OP_FLOAD, // FLOAD dst,base,index
+ OP_FSTORE, // FSTORE base,index,src
+ OP_FREAD, // FREAD dst,space,src1
+ OP_FWRITE, // FWRITE space,dst,src1
+ OP_FMOV, // FMOV dst,src1[,c]
+ OP_FTOINT, // FTOINT dst,src1,size,round
+ OP_FFRINT, // FFRINT dst,src1,size
+ OP_FFRFLT, // FFRFLT dst,src1,size
+ OP_FRNDS, // FRNDS dst,src1
+ OP_FADD, // FADD dst,src1,src2
+ OP_FSUB, // FSUB dst,src1,src2
+ OP_FCMP, // FCMP src1,src2
+ OP_FMUL, // FMUL dst,src1,src2
+ OP_FDIV, // FDIV dst,src1,src2
+ OP_FNEG, // FNEG dst,src1
+ OP_FABS, // FABS dst,src1
+ OP_FSQRT, // FSQRT dst,src1
+ OP_FRECIP, // FRECIP dst,src1
+ OP_FRSQRT, // FRSQRT dst,src1
+
+ OP_MAX
+ };
+
+ // C function callback deinition
+ typedef void (*c_function)(void *ptr);
+
+ // class describing a global code handle
+ class code_handle
+ {
+ friend class ::drcuml_state;
+ friend class ::simple_list<code_handle>;
+
+ // construction/destruction
+ code_handle(drcuml_state &drcuml, const char *name);
+
+ public:
+ // getters
+ code_handle *next() const { return m_next; }
+ drccodeptr codeptr() const { return *m_code; }
+ drccodeptr *codeptr_addr() { return m_code; }
+ const char *string() const { return m_string; }
+
+ // setters
+ void set_codeptr(drccodeptr code);
+
+ private:
+ // internal state
+ drccodeptr * m_code; // pointer in the cache to the associated code
+ astring m_string; // pointer to string attached to handle
+ code_handle * m_next; // link to next handle in the list
+ drcuml_state & m_drcuml; // pointer to owning object
+ };
+
+ // class describing a local code label
+ class code_label
+ {
+ public:
+ // construction
+ code_label(UINT32 label = 0) : m_label(label) { }
+
+ // operators
+ operator UINT32 &() { return m_label; }
+ bool operator==(const code_label &rhs) const { return (m_label == rhs.m_label); }
+ bool operator!=(const code_label &rhs) const { return (m_label != rhs.m_label); }
+
+ // getters
+ UINT32 label() const { return m_label; }
+
+ private:
+ UINT32 m_label;
+ };
+
+ // a parameter for a UML instructon is encoded like this
+ class parameter
+ {
+ public:
+ // opcode parameter types
+ enum parameter_type
+ {
+ PTYPE_NONE = 0, // invalid
+ PTYPE_IMMEDIATE, // immediate; value = sign-extended to 64 bits
+ PTYPE_INT_REGISTER, // integer register; value = REG_I0 - REG_I_END
+ PTYPE_FLOAT_REGISTER, // floating point register; value = REG_F0 - REG_F_END
+ PTYPE_VECTOR_REGISTER, // vector register; value = REG_V0 - REG_V_END
+ PTYPE_MAPVAR, // map variable; value = MAPVAR_M0 - MAPVAR_END
+ PTYPE_MEMORY, // memory; value = pointer to memory
+ PTYPE_SIZE, // size; value = operand_size
+ PTYPE_SIZE_SCALE, // scale + size; value = memory_scale * 16 + operand_size
+ PTYPE_SIZE_SPACE, // space + size; value = memory_space * 16 + operand_size
+ PTYPE_CODE_HANDLE, // code handle; value = pointer to handle
+ PTYPE_CODE_LABEL, // code label; value = label index
+ PTYPE_C_FUNCTION, // C function; value = pointer to C code
+ PTYPE_ROUNDING, // floating point rounding mode; value = float_rounding_mode
+ PTYPE_STRING, // string parameter; value = pointer to string
+ PTYPE_MAX
+ };
+
+ // represents the value of an opcode parameter
+ typedef UINT64 parameter_value;
+
+ // construction
+ parameter() : m_type(PTYPE_NONE), m_value(0) { }
+ parameter(const parameter &param) : m_type(param.m_type), m_value(param.m_value) { }
+ parameter(UINT64 val) : m_type(PTYPE_IMMEDIATE), m_value(val) { }
+ parameter(operand_size size, memory_scale scale) : m_type(PTYPE_SIZE_SCALE), m_value((scale << 4) | size) { assert(size >= SIZE_BYTE && size <= SIZE_DQWORD); assert(scale >= SCALE_x1 && scale <= SCALE_x8); }
+ parameter(operand_size size, memory_space space) : m_type(PTYPE_SIZE_SPACE), m_value((space << 4) | size) { assert(size >= SIZE_BYTE && size <= SIZE_DQWORD); assert(space >= SPACE_PROGRAM && space <= SPACE_IO); }
+ parameter(code_handle &handle) : m_type(PTYPE_CODE_HANDLE), m_value(reinterpret_cast<parameter_value>(&handle)) { }
+ parameter(code_label &label) : m_type(PTYPE_CODE_LABEL), m_value(label) { }
+
+ // creators for types that don't safely default
+ static inline parameter make_ireg(int regnum) { assert(regnum >= REG_I0 && regnum < REG_I_END); return parameter(PTYPE_INT_REGISTER, regnum); }
+ static inline parameter make_freg(int regnum) { assert(regnum >= REG_F0 && regnum < REG_F_END); return parameter(PTYPE_FLOAT_REGISTER, regnum); }
+ static inline parameter make_vreg(int regnum) { assert(regnum >= REG_V0 && regnum < REG_V_END); return parameter(PTYPE_VECTOR_REGISTER, regnum); }
+ static inline parameter make_mapvar(int mvnum) { assert(mvnum >= MAPVAR_M0 && mvnum < MAPVAR_END); return parameter(PTYPE_MAPVAR, mvnum); }
+ static inline parameter make_memory(void *base) { return parameter(PTYPE_MEMORY, reinterpret_cast<parameter_value>(base)); }
+ static inline parameter make_memory(const void *base) { return parameter(PTYPE_MEMORY, reinterpret_cast<parameter_value>(const_cast<void *>(base))); }
+ static inline parameter make_size(operand_size size) { assert(size >= SIZE_BYTE && size <= SIZE_DQWORD); return parameter(PTYPE_SIZE, size); }
+ static inline parameter make_string(const char *string) { return parameter(PTYPE_STRING, reinterpret_cast<parameter_value>(const_cast<char *>(string))); }
+ static inline parameter make_cfunc(c_function func) { return parameter(PTYPE_C_FUNCTION, reinterpret_cast<parameter_value>(func)); }
+ static inline parameter make_rounding(float_rounding_mode mode) { assert(mode >= ROUND_TRUNC && mode <= ROUND_DEFAULT); return parameter(PTYPE_ROUNDING, mode); }
+
+ // operators
+ bool operator==(const parameter &rhs) const { return (m_type == rhs.m_type && m_value == rhs.m_value); }
+ bool operator!=(const parameter &rhs) const { return (m_type != rhs.m_type || m_value != rhs.m_value); }
+
+ // getters
+ 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 >= REG_I0 && m_value < REG_I_END); return m_value; }
+ int freg() const { assert(m_type == PTYPE_FLOAT_REGISTER); assert(m_value >= REG_F0 && m_value < REG_F_END); return m_value; }
+ int vreg() const { assert(m_type == PTYPE_VECTOR_REGISTER); assert(m_value >= REG_V0 && m_value < REG_V_END); return m_value; }
+ int mapvar() const { assert(m_type == PTYPE_MAPVAR); assert(m_value >= MAPVAR_M0 && m_value < MAPVAR_END); return m_value; }
+ void *memory() const { assert(m_type == PTYPE_MEMORY); return reinterpret_cast<void *>(m_value); }
+ operand_size size() const { assert(m_type == PTYPE_SIZE || m_type == PTYPE_SIZE_SCALE || m_type == PTYPE_SIZE_SPACE); return operand_size(m_value & 15); }
+ memory_scale scale() const { assert(m_type == PTYPE_SIZE_SCALE); return memory_scale(m_value >> 4); }
+ memory_space space() const { assert(m_type == PTYPE_SIZE_SPACE); return memory_space(m_value >> 4); }
+ code_handle &handle() const { assert(m_type == PTYPE_CODE_HANDLE); return *reinterpret_cast<code_handle *>(m_value); }
+ code_label label() const { assert(m_type == PTYPE_CODE_LABEL); return code_label(m_value); }
+ c_function cfunc() const { assert(m_type == PTYPE_C_FUNCTION); return reinterpret_cast<c_function>(m_value); }
+ float_rounding_mode rounding() const { assert(m_type == PTYPE_ROUNDING); return float_rounding_mode(m_value); }
+ const char *string() const { assert(m_type == PTYPE_STRING); return reinterpret_cast<const char *>(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_mapvar() const { return (m_type == PTYPE_MAPVAR); }
+ bool is_memory() const { return (m_type == PTYPE_MEMORY); }
+ bool is_size() const { return (m_type == PTYPE_SIZE); }
+ bool is_size_scale() const { return (m_type == PTYPE_SIZE_SCALE); }
+ bool is_size_space() const { return (m_type == PTYPE_SIZE_SPACE); }
+ bool is_code_handle() const { return (m_type == PTYPE_CODE_HANDLE); }
+ bool is_code_label() const { return (m_type == PTYPE_CODE_LABEL); }
+ bool is_c_function() const { return (m_type == PTYPE_C_FUNCTION); }
+ bool is_rounding() const { return (m_type == PTYPE_ROUNDING); }
+ bool is_string() const { return (m_type == PTYPE_STRING); }
+
+ // other queries
+ bool is_immediate_value(UINT64 value) const { return (m_type == PTYPE_IMMEDIATE && m_value == value); }
+
+ private:
+ // private constructor
+ parameter(parameter_type type, parameter_value value) : m_type(type), m_value(value) { }
+
+ // internals
+ parameter_type m_type; // parameter type
+ parameter_value m_value; // parameter value
+ };
+
+ // structure describing rules for opcode encoding
+ struct opcode_info
+ {
+ struct parameter_info
+ {
+ UINT8 output; // input or output?
+ UINT8 size; // size of the parameter
+ UINT16 typemask; // types allowed
+ };
+
+ opcode_t opcode; // the opcode itself
+ const char * mnemonic; // mnemonic string
+ UINT8 sizes; // allowed sizes
+ bool condition; // conditions allowed?
+ UINT8 inflags; // input flags
+ UINT8 outflags; // output flags
+ UINT8 modflags; // modified flags
+ parameter_info param[4]; // information about parameters
+ };
+
+ // a single UML instructon is encoded like this
+ class instruction
+ {
+ public:
+ // construction/destruction
+ instruction();
+
+ // getters
+ opcode_t opcode() const { return m_opcode; }
+ condition_t condition() const { return m_condition; }
+ UINT8 flags() const { return m_flags; }
+ UINT8 size() const { return m_size; }
+ UINT8 numparams() const { return m_numparams; }
+ const parameter &param(int index) const { assert(index < m_numparams); return m_param[index]; }
+
+ // setters
+ void set_flags(UINT8 flags) { m_flags = flags; }
+ void set_mapvar(int paramnum, UINT32 value) { assert(paramnum < m_numparams); assert(m_param[paramnum].is_mapvar()); m_param[paramnum] = value; }
+
+ // misc
+ const char *disasm(astring &string, drcuml_state *drcuml = NULL) const;
+ UINT8 input_flags() const;
+ UINT8 output_flags() const;
+ UINT8 modified_flags() const;
+ void simplify();
+
+ // compile-time opcodes
+ void handle(code_handle &hand) { configure(OP_HANDLE, 4, hand); }
+ void hash(UINT32 mode, UINT32 pc) { configure(OP_HASH, 4, mode, pc); }
+ void label(code_label lab) { configure(OP_LABEL, 4, lab); }
+ void comment(const char *string) { configure(OP_COMMENT, 4, parameter::make_string(string)); }
+ void mapvar(parameter mapvar, UINT32 value) { assert(mapvar.is_mapvar()); configure(OP_MAPVAR, 4, mapvar, value); }
+
+ // control flow operations
+ void nop() { configure(OP_NOP, 4); }
+ void debug(UINT32 pc) { configure(OP_DEBUG, 4, pc); }
+ void exit(parameter param) { configure(OP_EXIT, 4, param); }
+ void exit(condition_t cond, parameter param) { configure(OP_EXIT, 4, param, cond); }
+ void hashjmp(parameter mode, parameter pc, code_handle &handle) { configure(OP_HASHJMP, 4, mode, pc, handle); }
+ void jmp(code_label label) { configure(OP_JMP, 4, label); }
+ void jmp(condition_t cond, code_label label) { configure(OP_JMP, 4, label, cond); }
+ void exh(code_handle &handle, parameter param) { configure(OP_EXH, 4, handle, param); }
+ void exh(condition_t cond, code_handle &handle, parameter param) { configure(OP_EXH, 4, handle, param, cond); }
+ void callh(code_handle &handle) { configure(OP_CALLH, 4, handle); }
+ void callh(condition_t cond, code_handle &handle) { configure(OP_CALLH, 4, handle, cond); }
+ void ret() { configure(OP_RET, 4); }
+ void ret(condition_t cond) { configure(OP_RET, 4, cond); }
+ void callc(c_function func, void *ptr) { configure(OP_CALLC, 4, parameter::make_cfunc(func), parameter::make_memory(ptr)); }
+ void callc(condition_t cond, c_function func, void *ptr) { configure(OP_CALLC, 4, parameter::make_cfunc(func), parameter::make_memory(ptr), cond); }
+ void recover(parameter dst, parameter mapvar) { assert(mapvar.is_mapvar()); configure(OP_RECOVER, 4, dst, mapvar); }
+
+ // internal register operations
+ void setfmod(parameter mode) { configure(OP_SETFMOD, 4, mode); }
+ void getfmod(parameter dst) { configure(OP_GETFMOD, 4, dst); }
+ void getexp(parameter dst) { configure(OP_GETEXP, 4, dst); }
+ void getflgs(parameter dst, UINT32 flags) { configure(OP_GETFLGS, 4, dst, flags); }
+ void save(drcuml_machine_state *dst) { configure(OP_SAVE, 4, parameter::make_memory(dst)); }
+ void restore(drcuml_machine_state *src) { configure(OP_RESTORE, 4, parameter::make_memory(src)); }
+
+ // 32-bit integer operations
+ void load(parameter dst, const void *base, parameter index, operand_size size, memory_scale scale = SCALE_DEFAULT) { configure(OP_LOAD, 4, dst, parameter::make_memory(base), index, parameter(size, scale)); }
+ void loads(parameter dst, const void *base, parameter index, operand_size size, memory_scale scale = SCALE_DEFAULT) { configure(OP_LOADS, 4, dst, parameter::make_memory(base), index, parameter(size, scale)); }
+ void store(void *base, parameter index, parameter src1, operand_size size, memory_scale scale = SCALE_DEFAULT) { configure(OP_STORE, 4, parameter::make_memory(base), index, src1, parameter(size, scale)); }
+ void read(parameter dst, parameter src1, operand_size size, memory_space space = SPACE_PROGRAM) { configure(OP_READ, 4, dst, src1, parameter(size, space)); }
+ void readm(parameter dst, parameter src1, parameter mask, operand_size size, memory_space space = SPACE_PROGRAM) { configure(OP_READM, 4, dst, src1, mask, parameter(size, space)); }
+ void write(parameter dst, parameter src1, operand_size size, memory_space space = SPACE_PROGRAM) { configure(OP_WRITE, 4, dst, src1, parameter(size, space)); }
+ void writem(parameter dst, parameter src1, parameter mask, operand_size size, memory_space space = SPACE_PROGRAM) { configure(OP_WRITEM, 4, dst, src1, mask, parameter(size, space)); }
+ void carry(parameter src, parameter bitnum) { configure(OP_CARRY, 4, src, bitnum); }
+ void set(condition_t cond, parameter dst) { configure(OP_SET, 4, dst, cond); }
+ void mov(parameter dst, parameter src1) { configure(OP_MOV, 4, dst, src1); }
+ void mov(condition_t cond, parameter dst, parameter src1) { configure(OP_MOV, 4, dst, src1, cond); }
+ void sext(parameter dst, parameter src1, operand_size size) { configure(OP_SEXT, 4, dst, src1, parameter::make_size(size)); }
+ void roland(parameter dst, parameter src, parameter shift, parameter mask) { configure(OP_ROLAND, 4, dst, src, shift, mask); }
+ void rolins(parameter dst, parameter src, parameter shift, parameter mask) { configure(OP_ROLINS, 4, dst, src, shift, mask); }
+ void add(parameter dst, parameter src1, parameter src2) { configure(OP_ADD, 4, dst, src1, src2); }
+ void addc(parameter dst, parameter src1, parameter src2) { configure(OP_ADDC, 4, dst, src1, src2); }
+ void sub(parameter dst, parameter src1, parameter src2) { configure(OP_SUB, 4, dst, src1, src2); }
+ void subb(parameter dst, parameter src1, parameter src2) { configure(OP_SUBB, 4, dst, src1, src2); }
+ void cmp(parameter src1, parameter src2) { configure(OP_CMP, 4, src1, src2); }
+ void mulu(parameter dst, parameter edst, parameter src1, parameter src2) { configure(OP_MULU, 4, dst, edst, src1, src2); }
+ void muls(parameter dst, parameter edst, parameter src1, parameter src2) { configure(OP_MULS, 4, dst, edst, src1, src2); }
+ void divu(parameter dst, parameter edst, parameter src1, parameter src2) { configure(OP_DIVU, 4, dst, edst, src1, src2); }
+ void divs(parameter dst, parameter edst, parameter src1, parameter src2) { configure(OP_DIVS, 4, dst, edst, src1, src2); }
+ void _and(parameter dst, parameter src1, parameter src2) { configure(OP_AND, 4, dst, src1, src2); }
+ void test(parameter src1, parameter src2) { configure(OP_TEST, 4, src1, src2); }
+ void _or(parameter dst, parameter src1, parameter src2) { configure(OP_OR, 4, dst, src1, src2); }
+ void _xor(parameter dst, parameter src1, parameter src2) { configure(OP_XOR, 4, dst, src1, src2); }
+ void lzcnt(parameter dst, parameter src) { configure(OP_LZCNT, 4, dst, src); }
+ void bswap(parameter dst, parameter src) { configure(OP_BSWAP, 4, dst, src); }
+ void shl(parameter dst, parameter src, parameter count) { configure(OP_SHL, 4, dst, src, count); }
+ void shr(parameter dst, parameter src, parameter count) { configure(OP_SHR, 4, dst, src, count); }
+ void sar(parameter dst, parameter src, parameter count) { configure(OP_SAR, 4, dst, src, count); }
+ void rol(parameter dst, parameter src, parameter count) { configure(OP_ROL, 4, dst, src, count); }
+ void rolc(parameter dst, parameter src, parameter count) { configure(OP_ROLC, 4, dst, src, count); }
+ void ror(parameter dst, parameter src, parameter count) { configure(OP_ROR, 4, dst, src, count); }
+ void rorc(parameter dst, parameter src, parameter count) { configure(OP_RORC, 4, dst, src, count); }
+
+ // 64-bit integer operations
+ void dload(parameter dst, const void *base, parameter index, operand_size size, memory_scale scale = SCALE_DEFAULT) { configure(OP_LOAD, 8, dst, parameter::make_memory(base), index, parameter(size, scale)); }
+ void dloads(parameter dst, const void *base, parameter index, operand_size size, memory_scale scale = SCALE_DEFAULT) { configure(OP_LOADS, 8, dst, parameter::make_memory(base), index, parameter(size, scale)); }
+ void dstore(void *base, parameter index, parameter src1, operand_size size, memory_scale scale = SCALE_DEFAULT) { configure(OP_STORE, 8, parameter::make_memory(base), index, src1, parameter(size, scale)); }
+ void dread(parameter dst, parameter src1, operand_size size, memory_space space = SPACE_PROGRAM) { configure(OP_READ, 8, dst, src1, parameter(size, space)); }
+ void dreadm(parameter dst, parameter src1, parameter mask, operand_size size, memory_space space = SPACE_PROGRAM) { configure(OP_READM, 8, dst, src1, mask, parameter(size, space)); }
+ void dwrite(parameter dst, parameter src1, operand_size size, memory_space space = SPACE_PROGRAM) { configure(OP_WRITE, 8, dst, src1, parameter(size, space)); }
+ void dwritem(parameter dst, parameter src1, parameter mask, operand_size size, memory_space space = SPACE_PROGRAM) { configure(OP_WRITEM, 8, dst, src1, mask, parameter(size, space)); }
+ void dcarry(parameter src, parameter bitnum) { configure(OP_CARRY, 8, src, bitnum); }
+ void dset(condition_t cond, parameter dst) { configure(OP_SET, 8, dst, cond); }
+ void dmov(parameter dst, parameter src1) { configure(OP_MOV, 8, dst, src1); }
+ void dmov(condition_t cond, parameter dst, parameter src1) { configure(OP_MOV, 8, dst, src1, cond); }
+ void dsext(parameter dst, parameter src1, operand_size size) { configure(OP_SEXT, 8, dst, src1, parameter::make_size(size)); }
+ void droland(parameter dst, parameter src, parameter shift, parameter mask) { configure(OP_ROLAND, 8, dst, src, shift, mask); }
+ void drolins(parameter dst, parameter src, parameter shift, parameter mask) { configure(OP_ROLINS, 8, dst, src, shift, mask); }
+ void dadd(parameter dst, parameter src1, parameter src2) { configure(OP_ADD, 8, dst, src1, src2); }
+ void daddc(parameter dst, parameter src1, parameter src2) { configure(OP_ADDC, 8, dst, src1, src2); }
+ void dsub(parameter dst, parameter src1, parameter src2) { configure(OP_SUB, 8, dst, src1, src2); }
+ void dsubb(parameter dst, parameter src1, parameter src2) { configure(OP_SUBB, 8, dst, src1, src2); }
+ void dcmp(parameter src1, parameter src2) { configure(OP_CMP, 8, src1, src2); }
+ void dmulu(parameter dst, parameter edst, parameter src1, parameter src2) { configure(OP_MULU, 8, dst, edst, src1, src2); }
+ void dmuls(parameter dst, parameter edst, parameter src1, parameter src2) { configure(OP_MULS, 8, dst, edst, src1, src2); }
+ void ddivu(parameter dst, parameter edst, parameter src1, parameter src2) { configure(OP_DIVU, 8, dst, edst, src1, src2); }
+ void ddivs(parameter dst, parameter edst, parameter src1, parameter src2) { configure(OP_DIVS, 8, dst, edst, src1, src2); }
+ void dand(parameter dst, parameter src1, parameter src2) { configure(OP_AND, 8, dst, src1, src2); }
+ void dtest(parameter src1, parameter src2) { configure(OP_TEST, 8, src1, src2); }
+ void dor(parameter dst, parameter src1, parameter src2) { configure(OP_OR, 8, dst, src1, src2); }
+ void dxor(parameter dst, parameter src1, parameter src2) { configure(OP_XOR, 8, dst, src1, src2); }
+ void dlzcnt(parameter dst, parameter src) { configure(OP_LZCNT, 8, dst, src); }
+ void dbswap(parameter dst, parameter src) { configure(OP_BSWAP, 8, dst, src); }
+ void dshl(parameter dst, parameter src, parameter count) { configure(OP_SHL, 8, dst, src, count); }
+ void dshr(parameter dst, parameter src, parameter count) { configure(OP_SHR, 8, dst, src, count); }
+ void dsar(parameter dst, parameter src, parameter count) { configure(OP_SAR, 8, dst, src, count); }
+ void drol(parameter dst, parameter src, parameter count) { configure(OP_ROL, 8, dst, src, count); }
+ void drolc(parameter dst, parameter src, parameter count) { configure(OP_ROLC, 8, dst, src, count); }
+ void dror(parameter dst, parameter src, parameter count) { configure(OP_ROR, 8, dst, src, count); }
+ void drorc(parameter dst, parameter src, parameter count) { configure(OP_RORC, 8, dst, src, count); }
+
+ // 32-bit floating point operations
+ void fsload(parameter dst, const void *base, parameter index) { configure(OP_FLOAD, 4, dst, parameter::make_memory(base), index); }
+ void fsstore(void *base, parameter index, parameter src1) { configure(OP_FSTORE, 4, parameter::make_memory(base), index, src1); }
+ void fsread(parameter dst, parameter src1, memory_space space) { configure(OP_FREAD, 4, dst, src1, parameter(SIZE_SHORT, space)); }
+ void fswrite(parameter dst, parameter src1, memory_space space) { configure(OP_FWRITE, 4, dst, src1, parameter(SIZE_SHORT, space)); }
+ void fsmov(parameter dst, parameter src1) { configure(OP_FMOV, 4, dst, src1); }
+ void fsmov(condition_t cond, parameter dst, parameter src1) { configure(OP_FMOV, 4, dst, src1, cond); }
+ void fstoint(parameter dst, parameter src1, operand_size size, float_rounding_mode round) { configure(OP_FTOINT, 4, dst, src1, parameter::make_size(size), parameter::make_rounding(round)); }
+ void fsfrint(parameter dst, parameter src1, operand_size size) { configure(OP_FFRINT, 4, dst, src1, parameter::make_size(size)); }
+ void fsfrflt(parameter dst, parameter src1, operand_size size) { configure(OP_FFRFLT, 4, dst, src1, parameter::make_size(size)); }
+ void fsadd(parameter dst, parameter src1, parameter src2) { configure(OP_FADD, 4, dst, src1, src2); }
+ void fssub(parameter dst, parameter src1, parameter src2) { configure(OP_FSUB, 4, dst, src1, src2); }
+ void fscmp(parameter src1, parameter src2) { configure(OP_FCMP, 4, src1, src2); }
+ void fsmul(parameter dst, parameter src1, parameter src2) { configure(OP_FMUL, 4, dst, src1, src2); }
+ void fsdiv(parameter dst, parameter src1, parameter src2) { configure(OP_FDIV, 4, dst, src1, src2); }
+ void fsneg(parameter dst, parameter src1) { configure(OP_FNEG, 4, dst, src1); }
+ void fsabs(parameter dst, parameter src1) { configure(OP_FABS, 4, dst, src1); }
+ void fssqrt(parameter dst, parameter src1) { configure(OP_FSQRT, 4, dst, src1); }
+ void fsrecip(parameter dst, parameter src1) { configure(OP_FRECIP, 4, dst, src1); }
+ void fsrsqrt(parameter dst, parameter src1) { configure(OP_FRSQRT, 4, dst, src1); }
+
+ // 64-bit floating point operations
+ void fdload(parameter dst, const void *base, parameter index) { configure(OP_FLOAD, 8, dst, parameter::make_memory(base), index); }
+ void fdstore(void *base, parameter index, parameter src1) { configure(OP_FSTORE, 8, parameter::make_memory(base), index, src1); }
+ void fdread(parameter dst, parameter src1, memory_space space) { configure(OP_FREAD, 8, dst, src1, parameter(SIZE_DOUBLE, space)); }
+ void fdwrite(parameter dst, parameter src1, memory_space space) { configure(OP_FWRITE, 8, dst, src1, parameter(SIZE_DOUBLE, space)); }
+ void fdmov(parameter dst, parameter src1) { configure(OP_FMOV, 8, dst, src1); }
+ void fdmov(condition_t cond, parameter dst, parameter src1) { configure(OP_FMOV, 8, dst, src1, cond); }
+ void fdtoint(parameter dst, parameter src1, operand_size size, float_rounding_mode round) { configure(OP_FTOINT, 8, dst, src1, parameter::make_size(size), parameter::make_rounding(round)); }
+ void fdfrint(parameter dst, parameter src1, operand_size size) { configure(OP_FFRINT, 8, dst, src1, parameter::make_size(size)); }
+ void fdfrflt(parameter dst, parameter src1, operand_size size) { configure(OP_FFRFLT, 8, dst, src1, parameter::make_size(size)); }
+ void fdrnds(parameter dst, parameter src1) { configure(OP_FRNDS, 8, dst, src1); }
+ void fdadd(parameter dst, parameter src1, parameter src2) { configure(OP_FADD, 8, dst, src1, src2); }
+ void fdsub(parameter dst, parameter src1, parameter src2) { configure(OP_FSUB, 8, dst, src1, src2); }
+ void fdcmp(parameter src1, parameter src2) { configure(OP_FCMP, 8, src1, src2); }
+ void fdmul(parameter dst, parameter src1, parameter src2) { configure(OP_FMUL, 8, dst, src1, src2); }
+ void fddiv(parameter dst, parameter src1, parameter src2) { configure(OP_FDIV, 8, dst, src1, src2); }
+ void fdneg(parameter dst, parameter src1) { configure(OP_FNEG, 8, dst, src1); }
+ void fdabs(parameter dst, parameter src1) { configure(OP_FABS, 8, dst, src1); }
+ void fdsqrt(parameter dst, parameter src1) { configure(OP_FSQRT, 8, dst, src1); }
+ void fdrecip(parameter dst, parameter src1) { configure(OP_FRECIP, 8, dst, src1); }
+ void fdrsqrt(parameter dst, parameter src1) { configure(OP_FRSQRT, 8, dst, src1); }
+
+ // constants
+ static const int MAX_PARAMS = 4;
+
+ private:
+ // internal configuration
+ void configure(opcode_t op, UINT8 size, condition_t cond = COND_ALWAYS);
+ void configure(opcode_t op, UINT8 size, parameter p0, condition_t cond = COND_ALWAYS);
+ void configure(opcode_t op, UINT8 size, parameter p0, parameter p1, condition_t cond = COND_ALWAYS);
+ void configure(opcode_t op, UINT8 size, parameter p0, parameter p1, parameter p2, condition_t cond = COND_ALWAYS);
+ void configure(opcode_t op, UINT8 size, parameter p0, parameter p1, parameter p2, parameter p3, condition_t cond = COND_ALWAYS);
+
+ // opcode validation and simplification
+ void validate();
+ void convert_to_mov_immediate(UINT64 immediate) { m_opcode = OP_MOV; m_numparams = 2; m_param[1] = immediate; }
+ void convert_to_mov_param(int pnum) { m_opcode = OP_MOV; m_numparams = 2; m_param[1] = m_param[pnum]; }
+
+ // internal state
+ opcode_t m_opcode; // opcode
+ condition_t m_condition; // condition
+ UINT8 m_flags; // flags
+ UINT8 m_size; // operation size
+ UINT8 m_numparams; // number of parameters
+ parameter m_param[MAX_PARAMS];// up to 4 parameters
+
+ static const opcode_info s_opcode_info_table[OP_MAX];
+ };
+
+ // structure describing rules for parameter encoding
+ struct parameter_info
+ {
+ UINT8 output; // input or output?
+ UINT8 size; // size of the parameter
+ UINT16 typemask; // types allowed
+ };
+
+ // global inline functions to specify a register parameter by index
+ inline parameter ireg(int n) { return parameter::make_ireg(REG_I0 + n); }
+ inline parameter freg(int n) { return parameter::make_freg(REG_F0 + n); }
+ inline parameter vreg(int n) { return parameter::make_vreg(REG_V0 + n); }
+ inline parameter mapvar(int n) { return parameter::make_mapvar(MAPVAR_M0 + n); }
+
+ // global inline functions to define memory parameters
+ inline parameter mem(const void *ptr) { return parameter::make_memory(ptr); }
+
+ // global register objects for direct access
+ const parameter I0(parameter::make_ireg(REG_I0 + 0));
+ const parameter I1(parameter::make_ireg(REG_I0 + 1));
+ const parameter I2(parameter::make_ireg(REG_I0 + 2));
+ const parameter I3(parameter::make_ireg(REG_I0 + 3));
+ const parameter I4(parameter::make_ireg(REG_I0 + 4));
+ const parameter I5(parameter::make_ireg(REG_I0 + 5));
+ const parameter I6(parameter::make_ireg(REG_I0 + 6));
+ const parameter I7(parameter::make_ireg(REG_I0 + 7));
+ const parameter I8(parameter::make_ireg(REG_I0 + 8));
+ const parameter I9(parameter::make_ireg(REG_I0 + 9));
+
+ const parameter F0(parameter::make_freg(REG_F0 + 0));
+ const parameter F1(parameter::make_freg(REG_F0 + 1));
+ const parameter F2(parameter::make_freg(REG_F0 + 2));
+ const parameter F3(parameter::make_freg(REG_F0 + 3));
+ const parameter F4(parameter::make_freg(REG_F0 + 4));
+ const parameter F5(parameter::make_freg(REG_F0 + 5));
+ const parameter F6(parameter::make_freg(REG_F0 + 6));
+ const parameter F7(parameter::make_freg(REG_F0 + 7));
+ const parameter F8(parameter::make_freg(REG_F0 + 8));
+ const parameter F9(parameter::make_freg(REG_F0 + 9));
+
+ const parameter V0(parameter::make_vreg(REG_V0 + 0));
+ const parameter V1(parameter::make_vreg(REG_V0 + 1));
+ const parameter V2(parameter::make_vreg(REG_V0 + 2));
+ const parameter V3(parameter::make_vreg(REG_V0 + 3));
+ const parameter V4(parameter::make_vreg(REG_V0 + 4));
+ const parameter V5(parameter::make_vreg(REG_V0 + 5));
+ const parameter V6(parameter::make_vreg(REG_V0 + 6));
+ const parameter V7(parameter::make_vreg(REG_V0 + 7));
+ const parameter V8(parameter::make_vreg(REG_V0 + 8));
+ const parameter V9(parameter::make_vreg(REG_V0 + 9));
+
+ const parameter M0(parameter::make_mapvar(MAPVAR_M0 + 0));
+ const parameter M1(parameter::make_mapvar(MAPVAR_M0 + 1));
+ const parameter M2(parameter::make_mapvar(MAPVAR_M0 + 2));
+ const parameter M3(parameter::make_mapvar(MAPVAR_M0 + 3));
+ const parameter M4(parameter::make_mapvar(MAPVAR_M0 + 4));
+ const parameter M5(parameter::make_mapvar(MAPVAR_M0 + 5));
+ const parameter M6(parameter::make_mapvar(MAPVAR_M0 + 6));
+ const parameter M7(parameter::make_mapvar(MAPVAR_M0 + 7));
+ const parameter M8(parameter::make_mapvar(MAPVAR_M0 + 8));
+ const parameter M9(parameter::make_mapvar(MAPVAR_M0 + 9));
+};
+
+
+#endif /* __UML_H__ */
diff --git a/trunk/src/emu/cpu/unsp/unsp.c b/trunk/src/emu/cpu/unsp/unsp.c
new file mode 100644
index 00000000000..4dc04d45bd5
--- /dev/null
+++ b/trunk/src/emu/cpu/unsp/unsp.c
@@ -0,0 +1,924 @@
+/**************************\
+*
+* SunPlus u'nSP core
+*
+* by Harmony
+*
+\**************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "unsp.h"
+
+INLINE unsp_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == UNSP);
+ return (unsp_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+static void unsp_set_irq_line(unsp_state *unsp, int irqline, int state);
+
+/*****************************************************************************/
+
+#define OP0 (op >> 12)
+#define OPA ((op >> 9) & 7)
+#define OP1 ((op >> 6) & 7)
+#define OPN ((op >> 3) & 7)
+#define OPB (op & 7)
+#define OPIMM (op & 0x3f)
+
+#define UNSP_LPC (((UNSP_REG(SR) & 0x3f) << 16) | UNSP_REG(PC))
+
+#define UNSP_REG(reg) unsp->r[UNSP_##reg - 1]
+#define UNSP_REG_I(reg) unsp->r[reg]
+#define UNSP_LREG_I(reg) (((UNSP_REG(SR) << 6) & 0x3f0000) | UNSP_REG_I(reg))
+
+#define UNSP_N 0x0200
+#define UNSP_Z 0x0100
+#define UNSP_S 0x0080
+#define UNSP_C 0x0040
+
+#define STANDARD_ALU_CASES \
+ case 0: \
+ lres = r0 + r1; \
+ unsp_update_nzsc(unsp, lres, r0, r1); \
+ break; \
+ case 1: \
+ lres = r0 + r1; \
+ if(UNSP_REG(SR) & UNSP_C) lres++; \
+ unsp_update_nzsc(unsp, lres, r0, r1); \
+ break; \
+ case 3: \
+ lres = r0 + (~r1 & 0x0000ffff); \
+ if(UNSP_REG(SR) & UNSP_C) lres++; \
+ unsp_update_nzsc(unsp, lres, r0, r1); \
+ break; \
+ case 2: \
+ case 4: \
+ lres = r0 + (~r1 & 0x0000ffff) + 1; \
+ unsp_update_nzsc(unsp, lres, r0, r1); \
+ break; \
+ case 6: \
+ lres = -r1; \
+ unsp_update_nz(unsp, lres); \
+ break; \
+ case 8: \
+ lres = r0 ^ r1; \
+ unsp_update_nz(unsp, lres); \
+ break; \
+ case 9: \
+ lres = r1; \
+ unsp_update_nz(unsp, lres); \
+ break; \
+ case 10: \
+ lres = r0 | r1; \
+ unsp_update_nz(unsp, lres); \
+ break; \
+ case 11: \
+ case 12: \
+ lres = r0 & r1; \
+ unsp_update_nz(unsp, lres); \
+ break
+
+#define WRITEBACK_OPA \
+ if(OP0 != 4 && OP0 < 12) \
+ { \
+ UNSP_REG_I(OPA) = (UINT16)lres; \
+ }
+
+/*****************************************************************************/
+
+static void unimplemented_opcode(unsp_state *unsp, UINT16 op)
+{
+ fatalerror("UNSP: unknown opcode %04x at %04x\n", op, UNSP_LPC << 1);
+}
+
+/*****************************************************************************/
+
+INLINE UINT16 READ16(unsp_state *unsp, UINT32 address)
+{
+ return unsp->program->read_word(address << 1);
+}
+
+INLINE void WRITE16(unsp_state *unsp, UINT32 address, UINT16 data)
+{
+ unsp->program->write_word(address << 1, data);
+}
+
+/*****************************************************************************/
+
+static CPU_INIT( unsp )
+{
+ unsp_state *unsp = get_safe_token(device);
+ memset(unsp->r, 0, sizeof(UINT16) * UNSP_GPR_COUNT);
+
+ unsp->device = device;
+ unsp->program = device->space(AS_PROGRAM);
+}
+
+static CPU_RESET( unsp )
+{
+ unsp_state *unsp = get_safe_token(device);
+ memset(unsp->r, 0, sizeof(UINT16) * UNSP_GPR_COUNT);
+
+ UNSP_REG(PC) = READ16(unsp, 0xfff7);
+ unsp->irq = 0;
+ unsp->fiq = 0;
+}
+
+/*****************************************************************************/
+
+static void unsp_update_nz(unsp_state *unsp, UINT32 value)
+{
+ UNSP_REG(SR) &= ~(UNSP_N | UNSP_Z);
+ if(value & 0x8000)
+ {
+ UNSP_REG(SR) |= UNSP_N;
+ }
+ if((UINT16)value == 0)
+ {
+ UNSP_REG(SR) |= UNSP_Z;
+ }
+}
+
+static void unsp_update_nzsc(unsp_state *unsp, UINT32 value, UINT16 r0, UINT16 r1)
+{
+ UNSP_REG(SR) &= ~(UNSP_C | UNSP_S);
+ unsp_update_nz(unsp, value);
+ if(value != (UINT16)value)
+ {
+ UNSP_REG(SR) |= UNSP_C;
+ }
+
+ if((INT16)r0 < (INT16)r1)
+ {
+ UNSP_REG(SR) |= UNSP_S;
+ }
+}
+
+static void unsp_push(unsp_state *unsp, UINT16 value, UINT16 *reg)
+{
+ WRITE16(unsp, (*reg)--, value);
+}
+
+static UINT16 unsp_pop(unsp_state *unsp, UINT16 *reg)
+{
+ return READ16(unsp, ++(*reg));
+}
+
+static CPU_EXECUTE( unsp )
+{
+ unsp_state *unsp = get_safe_token(device);
+ UINT32 op;
+ UINT32 lres;
+ UINT16 r0, r1;
+ lres = 0;
+
+ while (unsp->icount > 0)
+ {
+ debugger_instruction_hook(device, UNSP_LPC<<1);
+
+ op = READ16(unsp, UNSP_LPC);
+
+ UNSP_REG(PC)++;
+
+ if(OP0 < 0xf && OPA == 0x7 && OP1 < 2)
+ {
+ switch(OP0)
+ {
+ case 0: // JB
+ if(!(UNSP_REG(SR) & UNSP_C))
+ {
+ UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
+ }
+ break;
+ case 1: // JAE
+ if(UNSP_REG(SR) & UNSP_C)
+ {
+ UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
+ }
+ break;
+ case 2: // JGE
+ if(!(UNSP_REG(SR) & UNSP_S))
+ {
+ UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
+ }
+ break;
+ case 3: // JL
+ if(UNSP_REG(SR) & UNSP_S)
+ {
+ UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
+ }
+ break;
+ case 4: // JNE
+ if(!(UNSP_REG(SR) & UNSP_Z))
+ {
+ UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
+ }
+ break;
+ case 5: // JE
+ if(UNSP_REG(SR) & UNSP_Z)
+ {
+ UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
+ }
+ break;
+ case 6: // JPL
+ if(!(UNSP_REG(SR) & UNSP_N))
+ {
+ UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
+ }
+ break;
+ case 7: // JMI
+ if(UNSP_REG(SR) & UNSP_N)
+ {
+ UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
+ }
+ break;
+ case 8: // JBE
+ if((UNSP_REG(SR) & (UNSP_Z | UNSP_C)) != UNSP_C)
+ {
+ UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
+ }
+ break;
+ case 9: // JA
+ if((UNSP_REG(SR) & (UNSP_Z | UNSP_C)) == UNSP_C)
+ {
+ UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
+ }
+ break;
+ case 10: // JLE
+ if(UNSP_REG(SR) & (UNSP_Z | UNSP_S))
+ {
+ UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
+ }
+ break;
+ case 11: // JG
+ if(!(UNSP_REG(SR) & (UNSP_Z | UNSP_S)))
+ {
+ UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
+ }
+ break;
+ case 14: // JMP
+ UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
+ break;
+ }
+ }
+ else
+ {
+ switch((OP1 << 4) | OP0)
+ {
+ // r, [bp+imm6]
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x06: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d:
+ r0 = UNSP_REG_I(OPA);
+ r1 = READ16(unsp, UNSP_REG(BP) + OPIMM);
+ switch(OP0)
+ {
+ STANDARD_ALU_CASES;
+ case 13: // store r, [bp+imm6]
+ WRITE16(unsp, UNSP_REG(BP) + OPIMM, UNSP_REG_I(OPA));
+ break;
+ default:
+ unimplemented_opcode(unsp, op);
+ break;
+ }
+ WRITEBACK_OPA;
+ break;
+
+ // r, imm6
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x16: case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c:
+ r0 = UNSP_REG_I(OPA);
+ r1 = OPIMM;
+ switch(OP0)
+ {
+ STANDARD_ALU_CASES;
+ default:
+ unimplemented_opcode(unsp, op);
+ break;
+ }
+ WRITEBACK_OPA;
+ break;
+
+ // Pop / Interrupt return
+ case 0x29:
+ if(op == 0x9a90) // retf
+ {
+ UNSP_REG(SR) = unsp_pop(unsp, &UNSP_REG(SP));
+ UNSP_REG(PC) = unsp_pop(unsp, &UNSP_REG(SP));
+ break;
+ }
+ else if(op == 0x9a98) // reti
+ {
+ int i;
+ UNSP_REG(SR) = unsp_pop(unsp, &UNSP_REG(SP));
+ UNSP_REG(PC) = unsp_pop(unsp, &UNSP_REG(SP));
+ if(unsp->fiq & 2)
+ {
+ unsp->fiq &= 1;
+ }
+ else if(unsp->irq & 2)
+ {
+ unsp->irq &= 1;
+ }
+ unsp->sirq &= ~(1 << unsp->curirq);
+ for(i = 0; i < 9; i++)
+ {
+ if((unsp->sirq & (1 << i)) != 0 && i != unsp->curirq)
+ {
+ unsp->sirq &= ~(1 << i);
+ unsp->curirq = 0;
+ unsp_set_irq_line(unsp, UNSP_IRQ0_LINE + i, 1);
+ i = -1;
+ break;
+ }
+ }
+ if(i != -1)
+ {
+ unsp->curirq = 0;
+ }
+ break;
+ }
+ else
+ {
+ r0 = OPN;
+ r1 = OPA;
+ while(r0--)
+ {
+ UNSP_REG_I(++r1) = unsp_pop(unsp, &UNSP_REG_I(OPB));
+ }
+ }
+ break;
+
+ // Push
+ case 0x2d:
+ r0 = OPN;
+ r1 = OPA;
+ while(r0--)
+ {
+ unsp_push(unsp, UNSP_REG_I(r1--), &UNSP_REG_I(OPB));
+ }
+ break;
+
+ // ALU, Indirect
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x36: case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d:
+ switch(OPN & 3)
+ {
+ case 0: // r, [r]
+ r0 = UNSP_REG_I(OPA);
+ r1 = READ16(unsp, (OPN & 4) ? UNSP_LREG_I(OPB) : UNSP_REG_I(OPB));
+ switch(OP0)
+ {
+ STANDARD_ALU_CASES;
+ case 13: // store r, [r]
+ WRITE16(unsp, (OPN & 4) ? UNSP_LREG_I(OPB) : UNSP_REG_I(OPB), UNSP_REG_I(OPA));
+ break;
+ default:
+ unimplemented_opcode(unsp, op);
+ break;
+ }
+ WRITEBACK_OPA;
+ break;
+ case 1: // r, [<ds:>r--]
+ r0 = UNSP_REG_I(OPA);
+ r1 = READ16(unsp, (OPN & 4) ? UNSP_LREG_I(OPB) : UNSP_REG_I(OPB));
+ switch(OP0)
+ {
+ STANDARD_ALU_CASES;
+ case 13: // store r, [<ds:>r--]
+ WRITE16(unsp, (OPN & 4) ? UNSP_LREG_I(OPB) : UNSP_REG_I(OPB), UNSP_REG_I(OPA));
+ break;
+ default:
+ unimplemented_opcode(unsp, op);
+ break;
+ }
+ UNSP_REG_I(OPB)--;
+ WRITEBACK_OPA;
+ break;
+ case 2: // r, [<ds:>r++]
+ r0 = UNSP_REG_I(OPA);
+ r1 = READ16(unsp, (OPN & 4) ? UNSP_LREG_I(OPB) : UNSP_REG_I(OPB));
+ switch(OP0)
+ {
+ STANDARD_ALU_CASES;
+ case 13: // store r, [<ds:>r++]
+ WRITE16(unsp, (OPN & 4) ? UNSP_LREG_I(OPB) : UNSP_REG_I(OPB), UNSP_REG_I(OPA));
+ break;
+ default:
+ unimplemented_opcode(unsp, op);
+ break;
+ }
+ UNSP_REG_I(OPB)++;
+ WRITEBACK_OPA;
+ break;
+ case 3: // r, [<ds:>++r]
+ UNSP_REG_I(OPB)++;
+ r0 = UNSP_REG_I(OPA);
+ r1 = READ16(unsp, (OPN & 4) ? UNSP_LREG_I(OPB) : UNSP_REG_I(OPB));
+ switch(OP0)
+ {
+ STANDARD_ALU_CASES;
+ default:
+ unimplemented_opcode(unsp, op);
+ break;
+ }
+ WRITEBACK_OPA;
+ break;
+ }
+ break;
+
+ // ALU, 16-bit ops
+ case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x46: case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c:
+ switch(OPN)
+ {
+ // r, r
+ case 0:
+ r0 = UNSP_REG_I(OPA);
+ r1 = UNSP_REG_I(OPB);
+ switch(OP0)
+ {
+ STANDARD_ALU_CASES;
+ default:
+ unimplemented_opcode(unsp, op);
+ break;
+ }
+ WRITEBACK_OPA;
+ break;
+
+ // ALU, 16-bit Immediate
+ case 1: // r, r, imm16
+ if(!((OP0 == 4 || OP0 == 6 || OP0 == 9 || OP0 == 12) && OPA != OPB))
+ {
+ r0 = UNSP_REG_I(OPB);
+ r1 = READ16(unsp, UNSP_LPC);
+ UNSP_REG(PC)++;
+ switch(OP0)
+ {
+ STANDARD_ALU_CASES;
+ default:
+ unimplemented_opcode(unsp, op);
+ break;
+ }
+ WRITEBACK_OPA;
+ }
+ else
+ {
+ unimplemented_opcode(unsp, op);
+ }
+ break;
+
+ // ALU, Direct 16
+ case 2: // r, [imm16]
+ r0 = UNSP_REG_I(OPB);
+ r1 = READ16(unsp, READ16(unsp, UNSP_LPC));
+ UNSP_REG(PC)++;
+ switch(OP0)
+ {
+ STANDARD_ALU_CASES;
+ default:
+ unimplemented_opcode(unsp, op);
+ break;
+ }
+ WRITEBACK_OPA;
+ break;
+
+ // ALU, Direct 16
+ case 3: // [imm16], r
+ r0 = UNSP_REG_I(OPB);
+ r1 = UNSP_REG_I(OPA);
+ switch(OP0)
+ {
+ STANDARD_ALU_CASES;
+ default:
+ unimplemented_opcode(unsp, op);
+ break;
+ }
+ if(OP0 != 4 && OP0 < 12)
+ {
+ WRITE16(unsp, READ16(unsp, UNSP_LPC), (UINT16)lres);
+ }
+ UNSP_REG(PC)++;
+ break;
+
+ // ALU, Shifted
+ default:
+ {
+ UINT32 shift = (UNSP_REG_I(OPB) << 4) | unsp->sb;
+ if(shift & 0x80000)
+ {
+ shift |= 0xf00000;
+ }
+ shift >>= (OPN - 3);
+ unsp->sb = shift & 0x0f;
+ r1 = (shift >> 4) & 0x0000ffff;
+
+ switch(OP0)
+ {
+ case 9: // load r, r asr n
+ unsp_update_nz(unsp, r1);
+ UNSP_REG_I(OPA) = r1;
+ break;
+ default:
+ unimplemented_opcode(unsp, op);
+ break;
+ }
+ break;
+ }
+ }
+ break;
+
+ case 0x4d:
+ if(OPN == 3)
+ {
+ if(OPA == OPB)
+ {
+ WRITE16(unsp, READ16(unsp, UNSP_LPC), UNSP_REG_I(OPB));
+ UNSP_REG(PC)++;
+ }
+ else
+ {
+ unimplemented_opcode(unsp, op);
+ }
+ }
+ else
+ {
+ unimplemented_opcode(unsp, op);
+ }
+ break;
+
+ // ALU, Shifted
+ case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x56: case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c:
+ if(OPN & 4)
+ {
+ switch(OP0)
+ {
+ case 9: // load r, r >> imm2
+ lres = ((UNSP_REG_I(OPB) << 4) | unsp->sb) >> (OPN - 3);
+ unsp->sb = lres & 0x0f;
+ unsp_update_nz(unsp, (UINT16)(lres >> 4));
+ UNSP_REG_I(OPA) = (UINT16)(lres >> 4);
+ break;
+ default:
+ unimplemented_opcode(unsp, op);
+ break;
+ }
+ }
+ else
+ {
+ UINT32 shift = ((unsp->sb << 16) | UNSP_REG_I(OPB)) << (OPN + 1);
+ unsp->sb = (shift >> 16) & 0x0f;
+ r0 = UNSP_REG_I(OPA);
+ r1 = shift & 0x0000ffff;
+
+ switch(OP0)
+ {
+ case 0: // add r, r << imm2
+ lres = r0 + r1;
+ unsp_update_nzsc(unsp, lres, r0, r1);
+ UNSP_REG_I(OPA) = (UINT16)lres;
+ break;
+ case 9: // load r, r << imm2
+ lres = r1;
+ unsp_update_nz(unsp, lres);
+ UNSP_REG_I(OPA) = (UINT16)lres;
+ break;
+ case 10: // or r, r << imm2
+ lres = r0 | r1;
+ unsp_update_nz(unsp, lres);
+ UNSP_REG_I(OPA) = (UINT16)lres;
+ break;
+ default:
+ unimplemented_opcode(unsp, op);
+ break;
+ }
+ }
+ break;
+
+ // ALU, Rotated
+ case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x66: case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c:
+ if(OPN & 4) // ROR
+ {
+ lres = ((((unsp->sb << 16) | UNSP_REG_I(OPB)) << 4) | unsp->sb) >> (OPN - 3);
+ unsp->sb = lres & 0x0f;
+ r1 = (UINT16)(lres >> 4);
+ }
+ else
+ {
+ lres = ((((unsp->sb << 16) | UNSP_REG_I(OPB)) << 4) | unsp->sb) << (OPN + 1);
+ unsp->sb = (lres >> 20) & 0x0f;
+ r1 = (UINT16)(lres >> 4);
+ }
+
+ switch(OP0)
+ {
+ case 9: // load r, r ror imm2
+ unsp_update_nz(unsp, r1);
+ UNSP_REG_I(OPA) = r1;
+ break;
+ default:
+ unimplemented_opcode(unsp, op);
+ break;
+ }
+ break;
+
+ // ALU, Direct 8
+ case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x76: case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c:
+ //print("%s %s, [%02x]", alu[OP0], reg[OPA], OPIMM);
+ unimplemented_opcode(unsp, op);
+ break;
+
+ // Call
+ case 0x1f:
+ if(OPA == 0)
+ {
+ r1 = READ16(unsp, UNSP_LPC);
+ UNSP_REG(PC)++;
+ unsp_push(unsp, UNSP_REG(PC), &UNSP_REG(SP));
+ unsp_push(unsp, UNSP_REG(SR), &UNSP_REG(SP));
+ UNSP_REG(PC) = r1;
+ UNSP_REG(SR) &= 0xffc0;
+ UNSP_REG(SR) |= OPIMM;
+ }
+ else
+ {
+ unimplemented_opcode(unsp, op);
+ }
+ break;
+
+ // Far Jump
+ case 0x2f: case 0x3f: case 0x6f: case 0x7f:
+ if (OPA == 7 && OP1 == 2)
+ {
+ UNSP_REG(PC) = READ16(unsp, UNSP_LPC);
+ UNSP_REG(SR) &= 0xffc0;
+ UNSP_REG(SR) |= OPIMM;
+ }
+ break;
+
+ // Multiply, Unsigned * Signed
+ case 0x0f:
+ if(OPN == 1 && OPA != 7)
+ {
+ lres = UNSP_REG_I(OPA) * UNSP_REG_I(OPB);
+ if(UNSP_REG_I(OPB) & 0x8000)
+ {
+ lres -= UNSP_REG_I(OPA) << 16;
+ }
+ UNSP_REG(R4) = lres >> 16;
+ UNSP_REG(R3) = (UINT16)lres;
+ break;
+ }
+ else
+ {
+ unimplemented_opcode(unsp, op);
+ }
+ break;
+
+ // Multiply, Signed * Signed
+ case 0x4f:
+ if(OPN == 1 && OPA != 7)
+ {
+ lres = UNSP_REG_I(OPA) * UNSP_REG_I(OPB);
+ if(UNSP_REG_I(OPB) & 0x8000)
+ {
+ lres -= UNSP_REG_I(OPA) << 16;
+ }
+ if(UNSP_REG_I(OPA) & 0x8000)
+ {
+ lres -= UNSP_REG_I(OPB) << 16;
+ }
+ UNSP_REG(R4) = lres >> 16;
+ UNSP_REG(R3) = (UINT16)lres;
+ break;
+ }
+ else
+ {
+ unimplemented_opcode(unsp, op);
+ }
+ break;
+
+ // Interrupt flags
+ case 0x5f:
+ if(OPA == 0)
+ {
+ switch(OPIMM)
+ {
+ case 0:
+ unsp->irq &= ~1;
+ unsp->fiq &= ~1;
+ break;
+ case 1:
+ unsp->irq |= 1;
+ unsp->fiq &= ~1;
+ break;
+ case 2:
+ unsp->irq &= ~1;
+ unsp->fiq |= 1;
+ break;
+ case 3:
+ unsp->irq |= 1;
+ unsp->fiq |= 1;
+ break;
+ case 8: // irq off
+ unsp->irq &= ~1;
+ break;
+ case 9: // irq on
+ unsp->irq |= 1;
+ break;
+ case 12: // fiq off
+ unsp->fiq &= ~1;
+ break;
+ case 13: // fiq on
+ unsp->fiq |= 1;
+ break;
+ case 37: // nop
+ break;
+ }
+ }
+ else
+ {
+ unimplemented_opcode(unsp, op);
+ }
+ break;
+ }
+ }
+
+ unsp->icount -= 5;
+ unsp->icount = MAX(unsp->icount, 0);
+ }
+}
+
+
+/*****************************************************************************/
+
+static void unsp_set_irq_line(unsp_state *unsp, int irqline, int state)
+{
+ UINT16 irq_vector = 0;
+
+ unsp->sirq &= ~(1 << irqline);
+
+ if(!state)
+ {
+ logerror("clearing irq %d (%04x, %04x)\n", irqline, unsp->sirq, unsp->curirq);
+ return;
+ }
+
+ switch (irqline)
+ {
+ case UNSP_IRQ0_LINE:
+ case UNSP_IRQ1_LINE:
+ case UNSP_IRQ2_LINE:
+ case UNSP_IRQ3_LINE:
+ case UNSP_IRQ4_LINE:
+ case UNSP_IRQ5_LINE:
+ case UNSP_IRQ6_LINE:
+ case UNSP_IRQ7_LINE:
+ if(unsp->fiq & 2)
+ {
+ // FIQ is being serviced, ignore this IRQ trigger.
+ unsp->sirq |= state << irqline;
+ return;
+ }
+ if(unsp->irq != 1)
+ {
+ // IRQ is disabled, ignore this IRQ trigger.
+ unsp->sirq |= state << irqline;
+ return;
+ }
+ unsp->irq |= 2;
+ unsp->curirq |= (1 << irqline);
+ logerror("taking irq %d (%04x, %04x)\n", irqline, unsp->sirq, unsp->curirq);
+ irq_vector = 0xfff8 + (irqline - UNSP_IRQ0_LINE);
+ break;
+ case UNSP_FIQ_LINE:
+ if(unsp->fiq != 1)
+ {
+ // FIQ is disabled, ignore this FIQ trigger.
+ unsp->sirq |= state << irqline;
+ return;
+ }
+ unsp->fiq |= 2;
+ unsp->curirq |= (1 << irqline);
+ logerror("taking fiq %d (%04x, %04x)\n", irqline, unsp->sirq, unsp->curirq);
+ irq_vector = 0xfff6;
+ break;
+ case UNSP_BRK_LINE:
+ break;
+ }
+
+ unsp->saved_sb = unsp->sb;
+ unsp_push(unsp, UNSP_REG(PC), &UNSP_REG(SP));
+ unsp_push(unsp, UNSP_REG(SR), &UNSP_REG(SP));
+ UNSP_REG(PC) = READ16(unsp, irq_vector);
+ UNSP_REG(SR) = 0;
+}
+
+static CPU_SET_INFO( unsp )
+{
+ unsp_state *unsp = get_safe_token(device);
+
+ switch (state)
+ {
+ case CPUINFO_INT_INPUT_STATE + UNSP_IRQ0_LINE:
+ case CPUINFO_INT_INPUT_STATE + UNSP_IRQ1_LINE:
+ case CPUINFO_INT_INPUT_STATE + UNSP_IRQ2_LINE:
+ case CPUINFO_INT_INPUT_STATE + UNSP_IRQ3_LINE:
+ case CPUINFO_INT_INPUT_STATE + UNSP_IRQ4_LINE:
+ case CPUINFO_INT_INPUT_STATE + UNSP_IRQ5_LINE:
+ case CPUINFO_INT_INPUT_STATE + UNSP_IRQ6_LINE:
+ case CPUINFO_INT_INPUT_STATE + UNSP_IRQ7_LINE:
+ case CPUINFO_INT_INPUT_STATE + UNSP_FIQ_LINE:
+ case CPUINFO_INT_INPUT_STATE + UNSP_BRK_LINE:
+ unsp_set_irq_line(unsp, state - CPUINFO_INT_INPUT_STATE, (int)info->i);
+ break;
+
+ case CPUINFO_INT_REGISTER + UNSP_SP: UNSP_REG(SP) = info->i; break;
+ case CPUINFO_INT_REGISTER + UNSP_R1: UNSP_REG(R1) = info->i; break;
+ case CPUINFO_INT_REGISTER + UNSP_R2: UNSP_REG(R2) = info->i; break;
+ case CPUINFO_INT_REGISTER + UNSP_R3: UNSP_REG(R3) = info->i; break;
+ case CPUINFO_INT_REGISTER + UNSP_R4: UNSP_REG(R4) = info->i; break;
+ case CPUINFO_INT_REGISTER + UNSP_BP: UNSP_REG(BP) = info->i; break;
+ case CPUINFO_INT_REGISTER + UNSP_SR: UNSP_REG(SR) = info->i; break;
+ case CPUINFO_INT_PC: /* Intentional fallthrough */
+ case CPUINFO_INT_REGISTER + UNSP_PC:
+ UNSP_REG(PC) = (info->i & 0x0001fffe) >> 1;
+ UNSP_REG(SR) = (UNSP_REG(SR) & 0xffc0) | ((info->i & 0x007e0000) >> 17);
+ break;
+ case CPUINFO_INT_REGISTER + UNSP_IRQ: unsp->irq = info->i; break;
+ case CPUINFO_INT_REGISTER + UNSP_FIQ: unsp->fiq = info->i; break;
+ case CPUINFO_INT_REGISTER + UNSP_SB: unsp->sb = info->i; break;
+ }
+}
+
+CPU_GET_INFO( unsp )
+{
+ unsp_state *unsp = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch(state)
+ {
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(unsp_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 = 2; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 5; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 5; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 23; 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_REGISTER + UNSP_SP: info->i = UNSP_REG(SP); break;
+ case CPUINFO_INT_REGISTER + UNSP_R1: info->i = UNSP_REG(R1); break;
+ case CPUINFO_INT_REGISTER + UNSP_R2: info->i = UNSP_REG(R2); break;
+ case CPUINFO_INT_REGISTER + UNSP_R3: info->i = UNSP_REG(R3); break;
+ case CPUINFO_INT_REGISTER + UNSP_R4: info->i = UNSP_REG(R4); break;
+ case CPUINFO_INT_REGISTER + UNSP_BP: info->i = UNSP_REG(BP); break;
+ case CPUINFO_INT_REGISTER + UNSP_SR: info->i = UNSP_REG(SR); break;
+ case CPUINFO_INT_PC: /* Intentional fallthrough */
+ case CPUINFO_INT_REGISTER + UNSP_PC: info->i = UNSP_LPC << 1; break;
+ case CPUINFO_INT_REGISTER + UNSP_IRQ: info->i = unsp->irq; break;
+ case CPUINFO_INT_REGISTER + UNSP_FIQ: info->i = unsp->fiq; break;
+ case CPUINFO_INT_REGISTER + UNSP_SB: info->i = unsp->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(unsp); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(unsp); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(unsp); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(unsp); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(unsp); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &unsp->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "u'nSP"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "u'nSP"); 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 + UNSP_SP: sprintf(info->s, "SP: %04x", UNSP_REG(SP)); break;
+ case CPUINFO_STR_REGISTER + UNSP_R1: sprintf(info->s, "R1: %04x", UNSP_REG(R1)); break;
+ case CPUINFO_STR_REGISTER + UNSP_R2: sprintf(info->s, "R2: %04x", UNSP_REG(R2)); break;
+ case CPUINFO_STR_REGISTER + UNSP_R3: sprintf(info->s, "R3: %04x", UNSP_REG(R3)); break;
+ case CPUINFO_STR_REGISTER + UNSP_R4: sprintf(info->s, "R4: %04x", UNSP_REG(R4)); break;
+ case CPUINFO_STR_REGISTER + UNSP_BP: sprintf(info->s, "BP: %04x", UNSP_REG(BP)); break;
+ case CPUINFO_STR_REGISTER + UNSP_SR: sprintf(info->s, "SR: %04x", UNSP_REG(SR)); break;
+ case CPUINFO_STR_REGISTER + UNSP_PC: sprintf(info->s, "PC: %06x (%06x)", UNSP_LPC, UNSP_LPC << 1); break;
+ case CPUINFO_STR_REGISTER + UNSP_IRQ: sprintf(info->s, "IRQ: %d", unsp->irq); break;
+ case CPUINFO_STR_REGISTER + UNSP_FIQ: sprintf(info->s, "FIQ: %d", unsp->fiq); break;
+ case CPUINFO_STR_REGISTER + UNSP_SB: sprintf(info->s, "SB: %d", unsp->sb); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(UNSP, unsp);
diff --git a/trunk/src/emu/cpu/unsp/unsp.h b/trunk/src/emu/cpu/unsp/unsp.h
new file mode 100644
index 00000000000..cc2eb1df87e
--- /dev/null
+++ b/trunk/src/emu/cpu/unsp/unsp.h
@@ -0,0 +1,71 @@
+/**************************\
+*
+* SunPlus u'nSP emulator
+*
+* by Harmony
+*
+\**************************/
+
+#pragma once
+
+#ifndef __UNSP_H__
+#define __UNSP_H__
+
+typedef struct _unspimp_state unspimp_state;
+typedef struct _unsp_state unsp_state;
+struct _unsp_state
+{
+ UINT16 r[16];
+ UINT8 irq;
+ UINT8 fiq;
+ UINT16 curirq;
+ UINT16 sirq;
+ UINT8 sb;
+ UINT8 saved_sb;
+
+ legacy_cpu_device *device;
+ address_space *program;
+ int icount;
+
+ unspimp_state *impstate;
+};
+
+enum
+{
+ UNSP_SP = 1,
+ UNSP_R1,
+ UNSP_R2,
+ UNSP_R3,
+ UNSP_R4,
+ UNSP_BP,
+ UNSP_SR,
+ UNSP_PC,
+
+ UNSP_GPR_COUNT = UNSP_PC,
+
+ UNSP_IRQ,
+ UNSP_FIQ,
+ UNSP_SB,
+
+};
+
+enum
+{
+ UNSP_IRQ0_LINE = 0,
+ UNSP_IRQ1_LINE,
+ UNSP_IRQ2_LINE,
+ UNSP_IRQ3_LINE,
+ UNSP_IRQ4_LINE,
+ UNSP_IRQ5_LINE,
+ UNSP_IRQ6_LINE,
+ UNSP_IRQ7_LINE,
+ UNSP_FIQ_LINE,
+ UNSP_BRK_LINE,
+
+ UNSP_NUM_LINES
+};
+
+DECLARE_LEGACY_CPU_DEVICE(UNSP, unsp);
+CPU_DISASSEMBLE( unsp );
+
+#endif /* __UNSP_H__ */
diff --git a/trunk/src/emu/cpu/unsp/unspdasm.c b/trunk/src/emu/cpu/unsp/unspdasm.c
new file mode 100644
index 00000000000..aa591533ea5
--- /dev/null
+++ b/trunk/src/emu/cpu/unsp/unspdasm.c
@@ -0,0 +1,270 @@
+/**************************\
+*
+* SunPlus u'nSP disassembler
+*
+* by Harmony
+*
+\**************************/
+
+#include "emu.h"
+#include <stdarg.h>
+
+static char *output;
+
+static void ATTR_PRINTF(1,2) print(const char *fmt, ...)
+{
+ va_list vl;
+
+ va_start(vl, fmt);
+ vsprintf(output, fmt, vl);
+ va_end(vl);
+}
+
+/*****************************************************************************/
+
+static const char *reg[] =
+{
+ "sp", "r1", "r2", "r3", "r4", "bp", "sr", "pc"
+};
+
+static const char *jmp[] =
+{
+ "jb", "jae", "jge", "jl", "jne", "je", "jpl", "jmi",
+ "jbe", "ja", "jle", "jg", "jvc", "jvs", "jmp", "<inv>"
+};
+
+static const char *alu[] =
+{
+ "add", "adc", "sub", "sbc",
+ "cmp", "<inv>", "neg", "<inv>",
+ "xor", "load", "or", "and",
+ "test", "store", "<inv>", "<inv>"
+};
+
+/*****************************************************************************/
+
+#define OP0 (op >> 12)
+#define OPA ((op >> 9) & 7)
+#define OP1 ((op >> 6) & 7)
+#define OPN ((op >> 3) & 7)
+#define OPB (op & 7)
+#define OPIMM (op & 0x3f)
+#define OP2X ((OP0 < 14 && OP1 == 4 && (OPN >= 1 && OPN <= 3)) || (OP0 == 15 && (OP1 == 1 || OP1 == 2)))
+
+/*****************************************************************************/
+
+#define UNSP_DASM_OK ((2 * (OP2X ? 2 : 1)) | DASMFLAG_SUPPORTED)
+
+CPU_DISASSEMBLE( unsp )
+{
+ UINT16 op = *(UINT16 *)oprom;
+ UINT16 imm16 = *(UINT16 *)(oprom + 2);
+ op = BIG_ENDIANIZE_INT16(op);
+ imm16 = BIG_ENDIANIZE_INT16(imm16);
+
+ output = buffer;
+
+ print("<inv>");
+
+ if(OP0 < 0xf && OPA == 0x7 && OP1 < 2)
+ {
+ print("%s %04x", jmp[OP0], OP1 ? (pc - OPIMM*2) : (pc + OPIMM*2));
+ return UNSP_DASM_OK;
+ }
+
+ switch((OP1 << 4) | OP0)
+ {
+ // ALU, Indexed
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x06: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d:
+ print("%s %s, [bp+%02x]", alu[OP0], reg[OPA], OPIMM);
+ return UNSP_DASM_OK;
+
+ // ALU, Immediate
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x16: case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c:
+ print("%s %s, %02x", alu[OP0], reg[OPA], OPIMM);
+ return UNSP_DASM_OK;
+
+ // Pop / Interrupt return
+ case 0x29:
+ if(op == 0x9a90)
+ {
+ print("retf");
+ return UNSP_DASM_OK;
+ }
+ else if(op == 0x9a98)
+ {
+ print("reti");
+ return UNSP_DASM_OK;
+ }
+ else if((OPA + 1) < 8 && ((OPA + OPN) < 8))
+ {
+ print("pop %s, %s [%s]", reg[OPA+1], reg[OPA+OPN], reg[OPB]);
+ return UNSP_DASM_OK;
+ }
+ break;
+
+ // Push
+ case 0x2d:
+ if((OPA + 1) >= OPN && OPA < (OPN + 7))
+ {
+ print("push %s, %s [%s]", reg[(OPA+1)-OPN], reg[OPA], reg[OPB]);
+ return UNSP_DASM_OK;
+ }
+ break;
+
+ // ALU, Indirect
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x36: case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d:
+ switch(OPN & 3)
+ {
+ case 0:
+ print("%s %s, [%s%s]", alu[OP0], reg[OPA], (OPN & 4) ? "ds:" : "", reg[OPB]);
+ return UNSP_DASM_OK;
+ case 1:
+ print("%s %s, [%s%s--]", alu[OP0], reg[OPA], (OPN & 4) ? "ds:" : "", reg[OPB]);
+ return UNSP_DASM_OK;
+ case 2:
+ print("%s %s, [%s%s++]", alu[OP0], reg[OPA], (OPN & 4) ? "ds:" : "", reg[OPB]);
+ return UNSP_DASM_OK;
+ case 3:
+ print("%s %s, [%s++%s]", alu[OP0], reg[OPA], (OPN & 4) ? "ds:" : "", reg[OPB]);
+ return UNSP_DASM_OK;
+ }
+ return UNSP_DASM_OK;
+
+ // ALU, 16-bit ops
+ case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x46: case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c:
+ switch(OPN)
+ {
+ // ALU, Register
+ case 0:
+ print("%s %s, %s", alu[OP0], reg[OPA], reg[OPB]);
+ return UNSP_DASM_OK;
+
+ // ALU, 16-bit Immediate
+ case 1:
+ if(!((OP0 == 4 || OP0 == 6 || OP0 == 9 || OP0 == 12) && OPA != OPB))
+ {
+ if(OP0 != 4 && OP0 != 12)
+ {
+ print("%s %s, %s, %04x", alu[OP0], reg[OPA], reg[OPB], imm16);
+ return UNSP_DASM_OK;
+ }
+ else
+ {
+ print("%s %s, %04x", alu[OP0], reg[OPB], imm16);
+ return UNSP_DASM_OK;
+ }
+ }
+ break;
+
+ // ALU, Direct 16
+ case 2:
+ print("%s %s, [%04x]", alu[OP0], reg[OPA], imm16);
+ return UNSP_DASM_OK;
+
+ // ALU, Direct 16
+ case 3:
+ print("%s [%04x], %s, %s", alu[OP0], imm16, reg[OPA], reg[OPB]);
+ return UNSP_DASM_OK;
+
+ // ALU, Shifted
+ default:
+ print("%s %s, %s asr %d", alu[OP0], reg[OPA], reg[OPB], (OPN & 3) + 1);
+ return UNSP_DASM_OK;
+ }
+ case 0x4d:
+ if(OPN == 3)
+ {
+ if(OPA == OPB)
+ {
+ print("store [%04x], %s", imm16, reg[OPB]);
+ }
+ }
+ return UNSP_DASM_OK;
+
+ // ALU, Shifted
+ case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x56: case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c:
+ print("%s %s, %s %s %d", alu[OP0], reg[OPA], reg[OPB], (OPN & 4) ? ">>" : "<<", (OPN & 3) + 1);
+ return UNSP_DASM_OK;
+
+ // ALU, Rotated
+ case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x66: case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c:
+ print("%s %s, %s %s %d", alu[OP0], reg[OPA], reg[OPB], (OPN & 4) ? "ror" : "rol", (OPN & 3) + 1);
+ return UNSP_DASM_OK;
+
+ // ALU, Direct 8
+ case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x76: case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c:
+ print("%s %s, [%02x]", alu[OP0], reg[OPA], OPIMM);
+ return UNSP_DASM_OK;
+
+ // Call
+ case 0x1f:
+ if(OPA == 0)
+ {
+ print("call %06x", ((OPIMM << 16) | imm16) << 1);
+ }
+ return UNSP_DASM_OK;
+
+ // Far Jump
+ case 0x2f: case 0x3f: case 0x6f: case 0x7f:
+ if (OPA == 7 && OPA == 2)
+ {
+ print("goto %06x", ((OPIMM << 16) | imm16) << 1);
+ }
+ return UNSP_DASM_OK;
+
+ // Multiply, Unsigned * Signed
+ case 0x0f:
+ if(OPN == 1 && OPA != 7)
+ {
+ print("mulus %s, %s", reg[OPA], reg[OPB]);
+ }
+ return UNSP_DASM_OK;
+
+ // Multiply, Signed * Signed
+ case 0x4f:
+ if(OPN == 1 && OPA != 7)
+ {
+ print("mulss %s, %s", reg[OPA], reg[OPB]);
+ }
+ return UNSP_DASM_OK;
+
+ // Interrupt flags
+ case 0x5f:
+ if(OPA == 0)
+ {
+ switch(OPIMM)
+ {
+ case 0:
+ print("int off");
+ break;
+ case 1:
+ print("int irq");
+ break;
+ case 2:
+ print("int fiq");
+ break;
+ case 3:
+ print("int irq,fiq");
+ break;
+ case 8:
+ print("irq off");
+ break;
+ case 9:
+ print("irq on");
+ break;
+ case 12:
+ print("fiq off");
+ break;
+ case 14:
+ print("fiq on");
+ break;
+ case 37:
+ print("nop");
+ break;
+ }
+ }
+ return UNSP_DASM_OK;
+ }
+ return UNSP_DASM_OK;
+}
diff --git a/trunk/src/emu/cpu/upd7725/dasm7725.c b/trunk/src/emu/cpu/upd7725/dasm7725.c
new file mode 100755
index 00000000000..1e5a2bc435d
--- /dev/null
+++ b/trunk/src/emu/cpu/upd7725/dasm7725.c
@@ -0,0 +1,233 @@
+/***************************************************************************
+
+ dasm7725.c
+ Disassembler for the portable uPD7725 emulator.
+ Written by byuu
+ MAME conversion by R. Belmont
+
+***************************************************************************/
+
+#include "emu.h"
+#include "upd7725.h"
+
+CPU_DISASSEMBLE( upd7725 )
+{
+ static char output[256];
+ UINT32 opcode = oprom[2] | (oprom[1] << 8) | (oprom[0] << 16);
+ UINT32 type = (opcode >> 22);
+
+// printf("dasm: PC %x opcode %08x\n", pc, opcode);
+
+ memset(output, 0, sizeof(output));
+
+ if(type == 0 || type == 1) { //OP,RT
+ UINT8 pselect = (opcode >> 20)&0x3; //P select
+ UINT8 alu = (opcode >> 16)&0xf; //ALU operation mode
+ UINT8 asl = (opcode >> 15)&0x1; //accumulator select
+ UINT8 dpl = (opcode >> 13)&0x3; //DP low modify
+ UINT8 dphm = (opcode >> 9)&0xf; //DP high XOR modify
+ UINT8 rpdcr = (opcode >> 8)&0x1; //RP decrement
+ UINT8 src = (opcode >> 4)&0xf; //move source
+ UINT8 dst = (opcode >> 0)&0xf; //move destination
+
+ switch(alu) {
+ case 0: strcat(output, "nop "); break;
+ case 1: strcat(output, "or "); break;
+ case 2: strcat(output, "and "); break;
+ case 3: strcat(output, "xor "); break;
+ case 4: strcat(output, "sub "); break;
+ case 5: strcat(output, "add "); break;
+ case 6: strcat(output, "sbb "); break;
+ case 7: strcat(output, "adc "); break;
+ case 8: strcat(output, "dec "); break;
+ case 9: strcat(output, "inc "); break;
+ case 10: strcat(output, "cmp "); break;
+ case 11: strcat(output, "shr1 "); break;
+ case 12: strcat(output, "shl1 "); break;
+ case 13: strcat(output, "shl2 "); break;
+ case 14: strcat(output, "shl4 "); break;
+ case 15: strcat(output, "xchg "); break;
+ }
+
+ if(alu < 8) {
+ switch(pselect) {
+ case 0: strcat(output, "ram,"); break;
+ case 1: strcat(output, "idb,"); break;
+ case 2: strcat(output, "m,"); break;
+ case 3: strcat(output, "n,"); break;
+ }
+ }
+
+ switch(asl) {
+ case 0: strcat(output, "a"); break;
+ case 1: strcat(output, "b"); break;
+ }
+
+ if(dst) {
+ strcat(output, " | mov ");
+
+ switch(src) {
+ case 0: strcat(output, "trb,"); break;
+ case 1: strcat(output, "a,"); break;
+ case 2: strcat(output, "b,"); break;
+ case 3: strcat(output, "tr,"); break;
+ case 4: strcat(output, "dp,"); break;
+ case 5: strcat(output, "rp,"); break;
+ case 6: strcat(output, "ro,"); break;
+ case 7: strcat(output, "sgn,"); break;
+ case 8: strcat(output, "dr,"); break;
+ case 9: strcat(output, "drnf,"); break;
+ case 10: strcat(output, "sr,"); break;
+ case 11: strcat(output, "sim,"); break;
+ case 12: strcat(output, "sil,"); break;
+ case 13: strcat(output, "k,"); break;
+ case 14: strcat(output, "l,"); break;
+ case 15: strcat(output, "mem,"); break;
+ }
+
+ switch(dst) {
+ case 0: strcat(output, "non"); break;
+ case 1: strcat(output, "a"); break;
+ case 2: strcat(output, "b"); break;
+ case 3: strcat(output, "tr"); break;
+ case 4: strcat(output, "dp"); break;
+ case 5: strcat(output, "rp"); break;
+ case 6: strcat(output, "dr"); break;
+ case 7: strcat(output, "sr"); break;
+ case 8: strcat(output, "sol"); break;
+ case 9: strcat(output, "som"); break;
+ case 10: strcat(output, "k"); break;
+ case 11: strcat(output, "klr"); break;
+ case 12: strcat(output, "klm"); break;
+ case 13: strcat(output, "l"); break;
+ case 14: strcat(output, "trb"); break;
+ case 15: strcat(output, "mem"); break;
+ }
+ }
+
+ if(dpl) {
+ switch(dpl) {
+ case 0: strcat(output, " | dpnop"); break;
+ case 1: strcat(output, " | dpinc"); break;
+ case 2: strcat(output, " | dpdec"); break;
+ case 3: strcat(output, " | dpclr"); break;
+ }
+ }
+
+ if(dphm) {
+ switch(dphm) {
+ case 0: strcat(output, " | m0"); break;
+ case 1: strcat(output, " | m1"); break;
+ case 2: strcat(output, " | m2"); break;
+ case 3: strcat(output, " | m3"); break;
+ case 4: strcat(output, " | m4"); break;
+ case 5: strcat(output, " | m5"); break;
+ case 6: strcat(output, " | m6"); break;
+ case 7: strcat(output, " | m7"); break;
+ case 8: strcat(output, " | m8"); break;
+ case 9: strcat(output, " | m9"); break;
+ case 10: strcat(output, " | ma"); break;
+ case 11: strcat(output, " | mb"); break;
+ case 12: strcat(output, " | mc"); break;
+ case 13: strcat(output, " | md"); break;
+ case 14: strcat(output, " | me"); break;
+ case 15: strcat(output, " | mf"); break;
+ }
+ }
+
+ if(rpdcr == 1) {
+ strcat(output, " | rpdec");
+ }
+
+ if(type == 1) {
+ strcat(output, " | ret");
+ }
+ }
+
+ if(type == 2) { //JP
+ UINT16 brch = (opcode >> 13) & 0x1ff; //branch
+ UINT16 na = (opcode >> 2) & 0x7ff; //next address
+
+ switch(brch) {
+ case 0x000: strcat(output, "jmpso "); break;
+ case 0x080: strcat(output, "jnca "); break;
+ case 0x082: strcat(output, "jca "); break;
+ case 0x084: strcat(output, "jncb "); break;
+ case 0x086: strcat(output, "jcb "); break;
+ case 0x088: strcat(output, "jnza "); break;
+ case 0x08a: strcat(output, "jza "); break;
+ case 0x08c: strcat(output, "jnzb "); break;
+ case 0x08e: strcat(output, "jzb "); break;
+ case 0x090: strcat(output, "jnova0 "); break;
+ case 0x092: strcat(output, "jova0 "); break;
+ case 0x094: strcat(output, "jnovb0 "); break;
+ case 0x096: strcat(output, "jovb0 "); break;
+ case 0x098: strcat(output, "jnova1 "); break;
+ case 0x09a: strcat(output, "jova1 "); break;
+ case 0x09c: strcat(output, "jnovb1 "); break;
+ case 0x09e: strcat(output, "jovb1 "); break;
+ case 0x0a0: strcat(output, "jnsa0 "); break;
+ case 0x0a2: strcat(output, "jsa0 "); break;
+ case 0x0a4: strcat(output, "jnsb0 "); break;
+ case 0x0a6: strcat(output, "jsb0 "); break;
+ case 0x0a8: strcat(output, "jnsa1 "); break;
+ case 0x0aa: strcat(output, "jsa1 "); break;
+ case 0x0ac: strcat(output, "jnsb1 "); break;
+ case 0x0ae: strcat(output, "jsb1 "); break;
+ case 0x0b0: strcat(output, "jdpl0 "); break;
+ case 0x0b1: strcat(output, "jdpln0 "); break;
+ case 0x0b2: strcat(output, "jdplf "); break;
+ case 0x0b3: strcat(output, "jdplnf "); break;
+ case 0x0b4: strcat(output, "jnsiak "); break;
+ case 0x0b6: strcat(output, "jsiak "); break;
+ case 0x0b8: strcat(output, "jnsoak "); break;
+ case 0x0ba: strcat(output, "jsoak "); break;
+ case 0x0bc: strcat(output, "jnrqm "); break;
+ case 0x0be: strcat(output, "jrqm "); break;
+ case 0x100: strcat(output, "ljmp "); break;
+ case 0x101: strcat(output, "hjmp "); break;
+ case 0x140: strcat(output, "lcall "); break;
+ case 0x141: strcat(output, "hcall "); break;
+ default: strcat(output, "?????? "); break;
+ }
+
+ char temp[16];
+
+ sprintf(temp, "$%x", na);
+ strcat(output, temp);
+ }
+
+ if(type == 3) { //LD
+ strcat(output, "ld ");
+ UINT16 id = opcode >> 6;
+ UINT8 dst = (opcode >> 0) & 0xf; //destination
+
+ char temp[16];
+ sprintf(temp, "$%x,", id);
+ strcat(output, temp);
+
+ switch(dst) {
+ case 0: strcat(output, "non"); break;
+ case 1: strcat(output, "a"); break;
+ case 2: strcat(output, "b"); break;
+ case 3: strcat(output, "tr"); break;
+ case 4: strcat(output, "dp"); break;
+ case 5: strcat(output, "rp"); break;
+ case 6: strcat(output, "dr"); break;
+ case 7: strcat(output, "sr"); break;
+ case 8: strcat(output, "sol"); break;
+ case 9: strcat(output, "som"); break;
+ case 10: strcat(output, "k"); break;
+ case 11: strcat(output, "klr"); break;
+ case 12: strcat(output, "klm"); break;
+ case 13: strcat(output, "l"); break;
+ case 14: strcat(output, "trb"); break;
+ case 15: strcat(output, "mem"); break;
+ }
+ }
+
+ strcpy(buffer, output);
+
+ return 1 | DASMFLAG_SUPPORTED;
+}
+
diff --git a/trunk/src/emu/cpu/upd7725/upd7725.c b/trunk/src/emu/cpu/upd7725/upd7725.c
new file mode 100755
index 00000000000..1c7966ccf51
--- /dev/null
+++ b/trunk/src/emu/cpu/upd7725/upd7725.c
@@ -0,0 +1,639 @@
+/***************************************************************************
+
+ upd7725.c
+
+ Core implementation for the portable NEC uPD7725/uPD96050 emulator
+
+ Original by byuu in the public domain.
+ MAME conversion by R. Belmont
+
+****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "upd7725.h"
+
+
+//**************************************************************************
+// DEVICE INTERFACE
+//**************************************************************************
+
+// device type definition
+const device_type UPD7725 = &device_creator<upd7725_device>;
+const device_type UPD96050 = &device_creator<upd96050_device>;
+
+necdsp_device::necdsp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, UINT32 abits, UINT32 dbits, const char *name)
+ : cpu_device(mconfig, type, name, tag, owner, clock),
+ m_program_config("program", ENDIANNESS_BIG, 32, abits, -2), // data bus width, address bus width, -2 means DWORD-addressable
+ m_data_config("data", ENDIANNESS_BIG, 16, dbits, -1), // -1 for WORD-addressable
+ m_irq(0),
+ m_program(NULL),
+ m_data(NULL),
+ m_direct(NULL)
+{
+}
+
+
+upd7725_device::upd7725_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : necdsp_device(mconfig, UPD7725, tag, owner, clock, 11, 11, "uPD7725")
+{
+}
+
+upd96050_device::upd96050_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : necdsp_device(mconfig, UPD96050, tag, owner, clock, 14, 12, "uPD96050")
+{
+}
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void necdsp_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const necdsp_interface *intf = reinterpret_cast<const necdsp_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<necdsp_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_in_int_func, 0, sizeof(m_in_int_func));
+ //memset(&m_in_si_func, 0, sizeof(m_in_si_func));
+ //memset(&m_in_sck_func, 0, sizeof(m_in_sck_func));
+ //memset(&m_in_sien_func, 0, sizeof(m_in_sien_func));
+ //memset(&m_in_soen_func, 0, sizeof(m_in_soen_func));
+ //memset(&m_in_dack_func, 0, sizeof(m_in_dack_func));
+ memset(&m_out_p0_func, 0, sizeof(m_out_p0_func));
+ memset(&m_out_p1_func, 0, sizeof(m_out_p1_func));
+ //memset(&m_out_so_func, 0, sizeof(m_out_so_func));
+ //memset(&m_out_sorq_func, 0, sizeof(m_out_sorq_func));
+ //memset(&m_out_drq_func, 0, sizeof(m_out_drq_func));
+ }
+}
+//-------------------------------------------------
+// device_start - start up the device
+//-------------------------------------------------
+
+void necdsp_device::device_start()
+{
+ // get our address spaces
+ m_program = space(AS_PROGRAM);
+ m_data = space(AS_DATA);
+ m_direct = &m_program->direct();
+
+ // register our state for the debugger
+ astring tempstr;
+ state_add(STATE_GENPC, "GENPC", regs.pc).noshow();
+ state_add(UPD7725_PC, "PC", regs.pc);
+ state_add(UPD7725_RP, "RP", regs.rp);
+ state_add(UPD7725_DP, "DP", regs.dp);
+ state_add(UPD7725_SP, "SP", regs.sp);
+ state_add(UPD7725_K, "K", regs.k);
+ state_add(UPD7725_L, "L", regs.l);
+ state_add(UPD7725_M, "M", regs.m);
+ state_add(UPD7725_N, "N", regs.n);
+ state_add(UPD7725_A, "A", regs.a);
+ state_add(UPD7725_B, "B", regs.b);
+ state_add(UPD7725_TR, "TR", regs.tr);
+ state_add(UPD7725_TRB, "TRB", regs.trb);
+ state_add(UPD7725_DR, "DR", regs.dr);
+ state_add(UPD7725_SI, "SI", regs.si);
+ state_add(UPD7725_SO, "SO", regs.so);
+ state_add(UPD7725_IDB, "IDB", regs.idb);
+
+ // resolve callbacks
+ m_in_int_func.resolve(m_in_int_cb, *this);
+ //m_in_si_func.resolve(m_in_si_cb, *this);
+ //m_in_sck_func.resolve(m_in_sck_cb, *this);
+ //m_in_sien_func.resolve(m_in_sien_cb, *this);
+ //m_in_soen_func.resolve(m_in_soen_cb, *this);
+ //m_in_dack_func.resolve(m_in_dack_cb, *this);
+ m_out_p0_func.resolve(m_out_p0_cb, *this);
+ m_out_p1_func.resolve(m_out_p1_cb, *this);
+ //m_out_so_func.resolve(m_out_so_cb, *this);
+ //m_out_sorq_func.resolve(m_out_sorq_cb, *this);
+ //m_out_drq_func.resolve(m_out_drq_cb, *this);
+
+ // save state registrations
+ save_item(NAME(regs.pc));
+ save_item(NAME(regs.rp));
+ save_item(NAME(regs.dp));
+ save_item(NAME(regs.sp));
+ save_item(NAME(regs.k));
+ save_item(NAME(regs.l));
+ save_item(NAME(regs.m));
+ save_item(NAME(regs.n));
+ save_item(NAME(regs.a));
+ save_item(NAME(regs.b));
+ save_item(NAME(regs.tr));
+ save_item(NAME(regs.trb));
+ save_item(NAME(regs.dr));
+ save_item(NAME(regs.so));
+ save_item(NAME(regs.idb));
+ save_item(NAME(regs.sr.rqm));
+ save_item(NAME(regs.sr.usf0));
+ save_item(NAME(regs.sr.usf1));
+ save_item(NAME(regs.sr.drs));
+ save_item(NAME(regs.sr.dma));
+ save_item(NAME(regs.sr.drc));
+ save_item(NAME(regs.sr.soc));
+ save_item(NAME(regs.sr.sic));
+ save_item(NAME(regs.sr.ei));
+ save_item(NAME(regs.sr.p0));
+ save_item(NAME(regs.sr.p1));
+ save_item(NAME(regs.stack));
+ save_item(NAME(dataRAM));
+
+ m_icountptr = &m_icount;
+}
+
+//-------------------------------------------------
+// device_reset - reset the device
+//-------------------------------------------------
+
+void necdsp_device::device_reset()
+{
+ for (unsigned i = 0; i < 2048; i++)
+ {
+ dataRAM[i] = 0x0000;
+ }
+
+ regs.pc = 0x0000;
+ regs.rp = 0x0000;
+ regs.dp = 0x0000;
+ regs.sp = 0x0;
+ regs.k = 0x0000;
+ regs.l = 0x0000;
+ regs.m = 0x0000;
+ regs.n = 0x0000;
+ regs.a = 0x0000;
+ regs.b = 0x0000;
+ regs.flaga = 0x00;
+ regs.flagb = 0x00;
+ regs.tr = 0x0000;
+ regs.trb = 0x0000;
+ regs.sr = 0x0000;
+ regs.dr = 0x0000;
+ regs.si = 0x0000;
+ regs.so = 0x0000;
+ regs.idb = 0x0000;
+}
+
+//-------------------------------------------------
+// memory_space_config - return the configuration
+// of the specified address space, or NULL if
+// the space doesn't exist
+//-------------------------------------------------
+
+const address_space_config *necdsp_device::memory_space_config(address_spacenum spacenum) const
+{
+ return (spacenum == AS_PROGRAM) ? &m_program_config : &m_data_config;
+}
+
+
+//-------------------------------------------------
+// state_import - import state into the device,
+// after it has been set
+//-------------------------------------------------
+
+void necdsp_device::state_import(const device_state_entry &entry)
+{
+}
+
+
+//-------------------------------------------------
+// state_export - export state from the device,
+// to a known location where it can be read
+//-------------------------------------------------
+
+void necdsp_device::state_export(const device_state_entry &entry)
+{
+}
+
+
+//-------------------------------------------------
+// state_string_export - export state as a string
+// for the debugger
+//-------------------------------------------------
+
+void necdsp_device::state_string_export(const device_state_entry &entry, astring &string)
+{
+ switch (entry.index())
+ {
+ case UPD7725_FLAGA:
+ string.printf("%s %s %c%c %s %s",
+ regs.flaga.s1 ? "S1" : "s1",
+ regs.flaga.s0 ? "S0" : "s0",
+ regs.flaga.c ? "C" : "c",
+ regs.flaga.z ? "Z" : "z",
+ regs.flaga.ov1 ? "OV1" : "ov1",
+ regs.flaga.ov0 ? "OV0" : "ov0",
+ regs.flaga.ov0p ? "OV0P" : "ov0p",
+ regs.flaga.ov0pp ? "OV0PP" : "ov0pp");
+ break;
+
+ case UPD7725_FLAGB:
+ string.printf("%s %s %c%c %s %s",
+ regs.flagb.s1 ? "S1" : "s1",
+ regs.flagb.s0 ? "S0" : "s0",
+ regs.flagb.c ? "C" : "c",
+ regs.flagb.z ? "Z" : "z",
+ regs.flagb.ov1 ? "OV1" : "ov1",
+ regs.flagb.ov0 ? "OV0" : "ov0",
+ regs.flagb.ov0p ? "OV0P" : "ov0p",
+ regs.flagb.ov0pp ? "OV0PP" : "ov0pp");
+ break;
+ }
+}
+
+//-------------------------------------------------
+// execute_min_cycles - return minimum number of
+// cycles it takes for one instruction to execute
+//-------------------------------------------------
+
+UINT32 necdsp_device::execute_min_cycles() const
+{
+ return 4;
+}
+
+
+//-------------------------------------------------
+// execute_max_cycles - return maximum number of
+// cycles it takes for one instruction to execute
+//-------------------------------------------------
+
+UINT32 necdsp_device::execute_max_cycles() const
+{
+ return 4;
+}
+
+
+//-------------------------------------------------
+// execute_input_lines - return the number of
+// input/interrupt lines
+//-------------------------------------------------
+
+UINT32 necdsp_device::execute_input_lines() const
+{
+ return 3; // TODO: there should be 11: INT, SCK, /SIEN, /SOEN, SI, and /DACK, plus SO, /SORQ and DRQ; for now, just INT, P0, and P1 are enough.
+}
+
+
+//-------------------------------------------------
+// execute_set_input -
+//-------------------------------------------------
+
+void necdsp_device::execute_set_input(int inputnum, int state)
+{
+ switch (inputnum)
+ {
+ case NECDSP_INPUT_LINE_INT:
+ //TODO: detect rising edge; if rising edge found AND IE = 1, push PC, pc = 0x100; else do nothing
+ m_irq = state; // set old state to current state
+ break;
+ // add more when needed
+ }
+}
+
+//-------------------------------------------------
+// disasm_min_opcode_bytes - return the length
+// of the shortest instruction, in bytes
+//-------------------------------------------------
+
+UINT32 necdsp_device::disasm_min_opcode_bytes() const
+{
+ return 4;
+}
+
+
+//-------------------------------------------------
+// disasm_max_opcode_bytes - return the length
+// of the longest instruction, in bytes
+//-------------------------------------------------
+
+UINT32 necdsp_device::disasm_max_opcode_bytes() const
+{
+ return 4;
+}
+
+//-------------------------------------------------
+// disasm_disassemble - call the disassembly
+// helper function
+//-------------------------------------------------
+
+offs_t necdsp_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+{
+ extern CPU_DISASSEMBLE( upd7725 );
+ return CPU_DISASSEMBLE_NAME(upd7725)(NULL, buffer, pc, oprom, opram, 0);
+}
+
+void necdsp_device::execute_run()
+{
+ UINT32 opcode;
+
+ do
+ {
+ // call debugger hook if necessary
+ if (device_t::machine().debug_flags & DEBUG_FLAG_ENABLED)
+ {
+ debugger_instruction_hook(this, regs.pc);
+ }
+
+ opcode = m_direct->read_decrypted_dword(regs.pc<<2)>>8;
+ regs.pc++;
+ switch(opcode >> 22)
+ {
+ case 0: exec_op(opcode); break;
+ case 1: exec_rt(opcode); break;
+ case 2: exec_jp(opcode); break;
+ case 3: exec_ld(opcode); break;
+ }
+
+ INT32 result = (INT32)regs.k * regs.l; //sign + 30-bit result
+ regs.m = result >> 15; //store sign + top 15-bits
+ regs.n = result << 1; //store low 15-bits + zero
+
+ m_icount--;
+
+ } while (m_icount > 0);
+}
+
+void necdsp_device::exec_op(UINT32 opcode) {
+ UINT8 pselect = (opcode >> 20)&0x3; //P select
+ UINT8 alu = (opcode >> 16)&0xf; //ALU operation mode
+ UINT8 asl = (opcode >> 15)&0x1; //accumulator select
+ UINT8 dpl = (opcode >> 13)&0x3; //DP low modify
+ UINT8 dphm = (opcode >> 9)&0xf; //DP high XOR modify
+ UINT8 rpdcr = (opcode >> 8)&0x1; //RP decrement
+ UINT8 src = (opcode >> 4)&0xf; //move source
+ UINT8 dst = (opcode >> 0)&0xf; //move destination
+
+ switch(src) {
+ case 0: regs.idb = regs.trb; break;
+ case 1: regs.idb = regs.a; break;
+ case 2: regs.idb = regs.b; break;
+ case 3: regs.idb = regs.tr; break;
+ case 4: regs.idb = regs.dp; break;
+ case 5: regs.idb = regs.rp; break;
+ case 6: regs.idb = m_data->read_word(regs.rp<<1); break;
+ case 7: regs.idb = 0x8000 - regs.flaga.s1; break; //SGN
+ case 8: regs.idb = regs.dr; regs.sr.rqm = 1; break;
+ case 9: regs.idb = regs.dr; break;
+ case 10: regs.idb = regs.sr; break;
+ case 11: regs.idb = regs.si; break; //MSB
+ case 12: regs.idb = regs.si; break; //LSB
+ case 13: regs.idb = regs.k; break;
+ case 14: regs.idb = regs.l; break;
+ case 15: regs.idb = dataRAM[regs.dp]; break;
+ }
+
+ if(alu) {
+ UINT16 p=0, q=0, r=0;
+ Flag flag;
+ bool c=0;
+
+ flag.c = 0;
+ flag.s1 = 0;
+ flag.ov0 = 0;
+ flag.ov1 = 0;
+ flag.ov0p = 0;
+ flag.ov0pp = 0;
+
+ switch(pselect) {
+ case 0: p = dataRAM[regs.dp]; break;
+ case 1: p = regs.idb; break;
+ case 2: p = regs.m; break;
+ case 3: p = regs.n; break;
+ }
+
+ switch(asl) {
+ case 0: q = regs.a; flag = regs.flaga; c = regs.flagb.c; break;
+ case 1: q = regs.b; flag = regs.flagb; c = regs.flaga.c; break;
+ }
+
+ switch(alu) {
+ case 1: r = q | p; break; //OR
+ case 2: r = q & p; break; //AND
+ case 3: r = q ^ p; break; //XOR
+ case 4: r = q - p; break; //SUB
+ case 5: r = q + p; break; //ADD
+ case 6: r = q - p - c; break; //SBB
+ case 7: r = q + p + c; break; //ADC
+ case 8: r = q - 1; p = 1; break; //DEC
+ case 9: r = q + 1; p = 1; break; //INC
+ case 10: r = ~q; break; //CMP
+ case 11: r = (q >> 1) | (q & 0x8000); break; //SHR1 (ASR)
+ case 12: r = (q << 1) | (c ? 1 : 0); break; //SHL1 (ROL)
+ case 13: r = (q << 2) | 3; break; //SHL2
+ case 14: r = (q << 4) | 15; break; //SHL4
+ case 15: r = (q << 8) | (q >> 8); break; //XCHG
+ }
+
+ flag.s0 = (r & 0x8000);
+ flag.z = (r == 0);
+ flag.ov0pp = flag.ov0p;
+ flag.ov0p = flag.ov0;
+
+ switch(alu) {
+ case 1: case 2: case 3: case 10: case 13: case 14: case 15: {
+ flag.c = 0;
+ flag.ov0 = flag.ov0p = flag.ov0pp = 0; // ASSUMPTION: previous ov0 values are nulled here to make ov1 zero
+ break;
+ }
+ case 4: case 5: case 6: case 7: case 8: case 9: {
+ if(alu & 1) {
+ //addition
+ flag.ov0 = (q ^ r) & ~(q ^ p) & 0x8000;
+ flag.c = (r < q);
+ } else {
+ //subtraction
+ flag.ov0 = (q ^ r) & (q ^ p) & 0x8000;
+ flag.c = (r > q);
+ }
+ break;
+ }
+ case 11: {
+ flag.c = q & 1;
+ flag.ov0 = flag.ov0p = flag.ov0pp = 0; // ASSUMPTION: previous ov0 values are nulled here to make ov1 zero
+ break;
+ }
+ case 12: {
+ flag.c = q >> 15;
+ flag.ov0 = flag.ov0p = flag.ov0pp = 0; // ASSUMPTION: previous ov0 values are nulled here to make ov1 zero
+ break;
+ }
+ }
+ // flag.ov1 is only set if the number of overflows of the past 3 opcodes (of type 4,5,6,7,8,9) is odd
+ flag.ov1 = (flag.ov0 + flag.ov0p + flag.ov0pp) & 1;
+ // flag.s1 is based on ov1: s1 = ov1 ^ s0;
+ flag.s1 = flag.ov1 ^ flag.s0;
+
+ switch(asl) {
+ case 0: regs.a = r; regs.flaga = flag; break;
+ case 1: regs.b = r; regs.flagb = flag; break;
+ }
+ }
+
+ exec_ld((regs.idb << 6) + dst);
+
+ switch(dpl) {
+ case 1: regs.dp = (regs.dp & 0xf0) + ((regs.dp + 1) & 0x0f); break; //DPINC
+ case 2: regs.dp = (regs.dp & 0xf0) + ((regs.dp - 1) & 0x0f); break; //DPDEC
+ case 3: regs.dp = (regs.dp & 0xf0); break; //DPCLR
+ }
+
+ regs.dp ^= dphm << 4;
+
+ if(rpdcr) regs.rp--;
+}
+
+void necdsp_device::exec_rt(UINT32 opcode) {
+ exec_op(opcode);
+ regs.pc = regs.stack[--regs.sp];
+ regs.sp &= 0xf;
+}
+
+void necdsp_device::exec_jp(UINT32 opcode) {
+ UINT16 brch = (opcode >> 13) & 0x1ff; //branch
+ UINT16 na = (opcode >> 2) & 0x7ff; //next address
+ UINT16 bank = (opcode >> 0) & 0x3; //bank address
+
+ UINT16 jps = (regs.pc & 0x2000) | (bank << 11) | (na << 0);
+ UINT16 jpl = (bank << 11) | (na << 0);
+
+ switch(brch) {
+ case 0x000: regs.pc = regs.so; return; //JMPSO
+
+ case 0x080: if(regs.flaga.c == 0) regs.pc = jps; return; //JNCA
+ case 0x082: if(regs.flaga.c == 1) regs.pc = jps; return; //JCA
+ case 0x084: if(regs.flagb.c == 0) regs.pc = jps; return; //JNCB
+ case 0x086: if(regs.flagb.c == 1) regs.pc = jps; return; //JCB
+
+ case 0x088: if(regs.flaga.z == 0) regs.pc = jps; return; //JNZA
+ case 0x08a: if(regs.flaga.z == 1) regs.pc = jps; return; //JZA
+ case 0x08c: if(regs.flagb.z == 0) regs.pc = jps; return; //JNZB
+ case 0x08e: if(regs.flagb.z == 1) regs.pc = jps; return; //JZB
+
+ case 0x090: if(regs.flaga.ov0 == 0) regs.pc = jps; return; //JNOVA0
+ case 0x092: if(regs.flaga.ov0 == 1) regs.pc = jps; return; //JOVA0
+ case 0x094: if(regs.flagb.ov0 == 0) regs.pc = jps; return; //JNOVB0
+ case 0x096: if(regs.flagb.ov0 == 1) regs.pc = jps; return; //JOVB0
+
+ case 0x098: if(regs.flaga.ov1 == 0) regs.pc = jps; return; //JNOVA1
+ case 0x09a: if(regs.flaga.ov1 == 1) regs.pc = jps; return; //JOVA1
+ case 0x09c: if(regs.flagb.ov1 == 0) regs.pc = jps; return; //JNOVB1
+ case 0x09e: if(regs.flagb.ov1 == 1) regs.pc = jps; return; //JOVB1
+
+ case 0x0a0: if(regs.flaga.s0 == 0) regs.pc = jps; return; //JNSA0
+ case 0x0a2: if(regs.flaga.s0 == 1) regs.pc = jps; return; //JSA0
+ case 0x0a4: if(regs.flagb.s0 == 0) regs.pc = jps; return; //JNSB0
+ case 0x0a6: if(regs.flagb.s0 == 1) regs.pc = jps; return; //JSB0
+
+ case 0x0a8: if(regs.flaga.s1 == 0) regs.pc = jps; return; //JNSA1
+ case 0x0aa: if(regs.flaga.s1 == 1) regs.pc = jps; return; //JSA1
+ case 0x0ac: if(regs.flagb.s1 == 0) regs.pc = jps; return; //JNSB1
+ case 0x0ae: if(regs.flagb.s1 == 1) regs.pc = jps; return; //JSB1
+
+ case 0x0b0: if((regs.dp & 0x0f) == 0x00) regs.pc = jps; return; //JDPL0
+ case 0x0b1: if((regs.dp & 0x0f) != 0x00) regs.pc = jps; return; //JDPLN0
+ case 0x0b2: if((regs.dp & 0x0f) == 0x0f) regs.pc = jps; return; //JDPLF
+ case 0x0b3: if((regs.dp & 0x0f) != 0x0f) regs.pc = jps; return; //JDPLNF
+
+ case 0x0bc: if(regs.sr.rqm == 0) regs.pc = jps; return; //JNRQM
+ case 0x0be: if(regs.sr.rqm == 1) regs.pc = jps; return; //JRQM
+
+ case 0x100: regs.pc = 0x0000 | jpl; return; //LJMP
+ case 0x101: regs.pc = 0x2000 | jpl; return; //HJMP
+
+ case 0x140: regs.stack[regs.sp++] = regs.pc; regs.pc = 0x0000 | jpl; regs.sp &= 0xf; return; //LCALL
+ case 0x141: regs.stack[regs.sp++] = regs.pc; regs.pc = 0x2000 | jpl; regs.sp &= 0xf; return; //HCALL
+ }
+}
+
+void necdsp_device::exec_ld(UINT32 opcode) {
+ UINT16 id = opcode >> 6; //immediate data
+ UINT8 dst = (opcode >> 0) & 0xf; //destination
+
+ regs.idb = id;
+
+ switch(dst) {
+ case 0: break;
+ case 1: regs.a = id; break;
+ case 2: regs.b = id; break;
+ case 3: regs.tr = id; break;
+ case 4: regs.dp = id; break;
+ case 5: regs.rp = id; break;
+ case 6: regs.dr = id; regs.sr.rqm = 1; break;
+ case 7: regs.sr = (regs.sr & 0x907c) | (id & ~0x907c);
+ m_out_p0_func(regs.sr&0x1);
+ m_out_p1_func((regs.sr&0x2)>>1);
+ break;
+ case 8: regs.so = id; break; //LSB
+ case 9: regs.so = id; break; //MSB
+ case 10: regs.k = id; break;
+ case 11: regs.k = id; regs.l = m_data->read_word(regs.rp<<1); break;
+ case 12: regs.l = id; regs.k = dataRAM[regs.dp | 0x40]; break;
+ case 13: regs.l = id; break;
+ case 14: regs.trb = id; break;
+ case 15: dataRAM[regs.dp] = id; break;
+ }
+}
+
+UINT8 necdsp_device::snesdsp_read(bool mode) {
+
+ if (!mode)
+ {
+ return regs.sr >> 8;
+ }
+
+ if (regs.sr.drc == 0)
+ {
+ //16-bit
+ if(regs.sr.drs == 0)
+ {
+ regs.sr.drs = 1;
+ return regs.dr >> 0;
+ }
+ else
+ {
+ regs.sr.rqm = 0;
+ regs.sr.drs = 0;
+ return regs.dr >> 8;
+ }
+ }
+ else
+ {
+ //8-bit
+ regs.sr.rqm = 0;
+ return regs.dr >> 0;
+ }
+}
+
+void necdsp_device::snesdsp_write(bool mode, UINT8 data) {
+ if (!mode) return;
+
+ if (regs.sr.drc == 0)
+ {
+ //16-bit
+ if (regs.sr.drs == 0)
+ {
+ regs.sr.drs = 1;
+ regs.dr = (regs.dr & 0xff00) | (data << 0);
+ }
+ else
+ {
+ regs.sr.rqm = 0;
+ regs.sr.drs = 0;
+ regs.dr = (data << 8) | (regs.dr & 0x00ff);
+ }
+ }
+ else
+ {
+ //8-bit
+ regs.sr.rqm = 0;
+ regs.dr = (regs.dr & 0xff00) | (data << 0);
+ }
+}
diff --git a/trunk/src/emu/cpu/upd7725/upd7725.h b/trunk/src/emu/cpu/upd7725/upd7725.h
new file mode 100755
index 00000000000..1ad811144fa
--- /dev/null
+++ b/trunk/src/emu/cpu/upd7725/upd7725.h
@@ -0,0 +1,235 @@
+/***************************************************************************
+
+ upd7725.h
+
+ Core implementation for the portable NEC uPD7725/uPD96050 emulator
+
+****************************************************************************/
+
+#pragma once
+
+#ifndef __UPD7725_H__
+#define __UPD7725_H__
+
+//**************************************************************************
+// ENUMERATIONS
+//**************************************************************************
+
+// input lines
+enum
+{
+ NECDSP_INPUT_LINE_INT = 0
+ // add more here as needed
+};
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class necdsp_device;
+class upd7725_device;
+class upd96050_device;
+
+// ======================> necdsp_interface
+
+struct necdsp_interface
+{
+ devcb_read_line m_in_int_cb;
+ //devcb_read8 m_in_si_cb;
+ //devcb_read_line m_in_sck_cb;
+ //devcb_read_line m_in_sien_cb;
+ //devcb_read_line m_in_soen_cb;
+ //devcb_read_line m_in_dack_cb;
+ devcb_write_line m_out_p0_cb;
+ devcb_write_line m_out_p1_cb;
+ //devcb_write8 m_out_so_cb;
+ //devcb_write_line m_out_sorq_cb;
+ //devcb_write_line m_out_drq_cb;
+};
+
+#define NECDSP_INTERFACE(name) \
+ const necdsp_interface (name) =
+
+// ======================> necdsp_device
+
+class necdsp_device : public cpu_device, public necdsp_interface
+{
+protected:
+ // construction/destruction
+ necdsp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, UINT32 abits, UINT32 dbits, const char *name);
+
+public:
+ UINT8 snesdsp_read(bool mode);
+ void snesdsp_write(bool mode, UINT8 data);
+
+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);
+
+ // inline data
+ const address_space_config m_program_config, m_data_config;
+
+ UINT16 dataRAM[2048];
+
+private:
+ struct Flag
+ {
+ bool s1, s0, c, z, ov1, ov0, ov0p, ov0pp;
+
+ inline operator unsigned() const
+ {
+ return (s1 << 7) + (s0 << 6) + (c << 5) + (z << 4) + (ov1 << 3) + (ov0 << 2) + (ov0p << 1) + (ov0pp << 0);
+ }
+
+ inline unsigned operator=(unsigned d)
+ {
+ s1 = d & 0x80; s0 = d & 0x40; c = d & 0x20; z = d & 0x10; ov1 = d & 0x08; ov0 = d & 0x04; ov0p = d & 0x02; ov0pp = d & 0x01;
+ return d;
+ }
+ };
+
+ struct Status
+ {
+ bool rqm, usf1, usf0, drs, dma, drc, soc, sic, ei, p1, p0;
+
+ inline operator unsigned() const
+ {
+ return (rqm << 15) + (usf1 << 14) + (usf0 << 13) + (drs << 12)
+ + (dma << 11) + (drc << 10) + (soc << 9) + (sic << 8)
+ + (ei << 7) + (p1 << 1) + (p0 << 0);
+ }
+
+ inline unsigned operator=(unsigned d)
+ {
+ rqm = d & 0x8000; usf1 = d & 0x4000; usf0 = d & 0x2000; drs = d & 0x1000;
+ dma = d & 0x0800; drc = d & 0x0400; soc = d & 0x0200; sic = d & 0x0100;
+ ei = d & 0x0080; p1 = d & 0x0002; p0 = d & 0x0001;
+ return d;
+ }
+ };
+
+ struct Regs
+ {
+ UINT16 pc; //program counter
+ UINT16 stack[16]; //LIFO
+ UINT16 rp; //ROM pointer
+ UINT16 dp; //data pointer
+ UINT8 sp; //stack pointer
+ INT16 k;
+ INT16 l;
+ INT16 m;
+ INT16 n;
+ INT16 a; //accumulator
+ INT16 b; //accumulator
+ Flag flaga;
+ Flag flagb;
+ UINT16 tr; //temporary register
+ UINT16 trb; //temporary register
+ Status sr; //status register
+ UINT16 dr; //data register
+ UINT16 si;
+ UINT16 so;
+ UINT16 idb;
+ } regs;
+
+ void exec_op(UINT32 opcode);
+ void exec_rt(UINT32 opcode);
+ void exec_jp(UINT32 opcode);
+ void exec_ld(UINT32 opcode);
+
+ void stack_push();
+ void stack_pull();
+
+ int m_icount;
+ int m_irq; // old irq line state, for detecting rising edges.
+
+ address_space *m_program, *m_data;
+ direct_read_data *m_direct;
+
+protected:
+// device callbacks
+ devcb_resolved_read_line m_in_int_func;
+ //devcb_resolved_read8 m_in_si_func;
+ //devcb_resolved_read_line m_in_sck_func;
+ //devcb_resolved_read_line m_in_sien_func;
+ //devcb_resolved_read_line m_in_soen_func;
+ //devcb_resolved_read_line m_in_dack_func;
+ devcb_resolved_write_line m_out_p0_func;
+ devcb_resolved_write_line m_out_p1_func;
+ //devcb_resolved_write8 m_out_so_func;
+ //devcb_resolved_write_line m_out_sorq_func;
+ //devcb_resolved_write_line m_out_drq_func;
+};
+
+class upd7725_device : public necdsp_device
+{
+public:
+ // construction/destruction
+ upd7725_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class upd96050_device : public necdsp_device
+{
+public:
+ // construction/destruction
+ upd96050_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ UINT16 dataram_r(UINT16 addr) { return dataRAM[addr]; }
+ void dataram_w(UINT16 addr, UINT16 data) { dataRAM[addr] = data; }
+};
+
+// device type definition
+extern const device_type UPD7725;
+extern const device_type UPD96050;
+
+//**************************************************************************
+// ENUMERATIONS
+//**************************************************************************
+
+// registers
+enum
+{
+ UPD7725_PC = 1,
+ UPD7725_RP,
+ UPD7725_DP,
+ UPD7725_K,
+ UPD7725_L,
+ UPD7725_M,
+ UPD7725_N,
+ UPD7725_A,
+ UPD7725_B,
+ UPD7725_FLAGA,
+ UPD7725_FLAGB,
+ UPD7725_SR,
+ UPD7725_DR,
+ UPD7725_SP,
+ UPD7725_TR,
+ UPD7725_TRB,
+ UPD7725_SI,
+ UPD7725_SO,
+ UPD7725_IDB
+};
+
+#endif /* __UPD7725_H__ */
diff --git a/trunk/src/emu/cpu/upd7810/7810dasm.c b/trunk/src/emu/cpu/upd7810/7810dasm.c
new file mode 100644
index 00000000000..4bfe53fe67c
--- /dev/null
+++ b/trunk/src/emu/cpu/upd7810/7810dasm.c
@@ -0,0 +1,5466 @@
+/*****************************************************************************
+ *
+ * Portable uPD7810/11, 7810H/11H, 78C10/C11/C14 disassembler
+ * Copyright Juergen Buchmueller, all rights reserved.
+ *
+ * NS20030112: added 7807.
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "upd7810.h"
+
+struct dasm_s {
+ UINT8 token;
+ const void *args;
+};
+
+enum
+{
+ illegal=1,
+ ACI,
+ ADC,
+ ADCW,
+ ADCX,
+ ADD,
+ ADDNC,
+ ADDNCW,
+ ADDNCX,
+ ADDW,
+ ADDX,
+ ADI,
+ ADINC,
+ ANA,
+ ANAW,
+ ANAX,
+ AND,
+ ANI,
+ ANIW,
+ BIT,
+ BLOCK,
+ CALB,
+ CALF,
+ CALL,
+ CALT,
+ CLC,
+ CLR, /* 7807 */
+ CMC, /* 7807 */
+ DAA,
+ DADC,
+ DADD,
+ DADDNC,
+ DAN,
+ DCR,
+ DCRW,
+ DCX,
+ DEQ,
+ DGT,
+ DI,
+ DIV,
+ DLT,
+ DMOV,
+ DNE,
+ DOFF,
+ DON,
+ DOR,
+ DRLL,
+ DRLR,
+ DSBB,
+ DSLL,
+ DSLR,
+ DSUB,
+ DSUBNB,
+ DXR,
+ EADD,
+ EI,
+ EQA,
+ EQAW,
+ EQAX,
+ EQI,
+ EQIW,
+ ESUB,
+ EX, /* 7801 */
+ EXA,
+ EXH,
+ EXX,
+ EXR, /* 7807 */
+ GTA,
+ GTAW,
+ GTAX,
+ GTI,
+ GTIW,
+ HALT,
+ IN, /* 7801 */
+ INR,
+ INRW,
+ INX,
+ JB,
+ JEA,
+ JMP,
+ JR,
+ JRE,
+ LBCD,
+ LDAW,
+ LDAX,
+ LDEAX,
+ LDED,
+ LHLD,
+ LSPD,
+ LTA,
+ LTAW,
+ LTAX,
+ LTI,
+ LTIW,
+ LXI,
+ MOV,
+ MUL,
+ MVI,
+ MVIW,
+ MVIX,
+ NEA,
+ NEAW,
+ NEAX,
+ NEGA,
+ NEI,
+ NEIW,
+ NOP,
+ NOT, /* 7807 */
+ OFFA,
+ OFFAW,
+ OFFAX,
+ OFFI,
+ OFFIW,
+ ONA,
+ ONAW,
+ ONAX,
+ ONI,
+ ONIW,
+ OR, /* 7807 */
+ ORA,
+ ORAW,
+ ORAX,
+ ORI,
+ ORIW,
+ OUT, /* 7801 */
+ PER, /* 7801 */
+ PEX, /* 7801 */
+ POP,
+ PUSH,
+ RET,
+ RETI,
+ RETS,
+ RLD,
+ RLL,
+ RLR,
+ RRD,
+ SBB,
+ SBBW,
+ SBBX,
+ SBCD,
+ SBI,
+ SDED,
+ SETB, /* 7807 */
+ SHLD,
+ SIO, /* 7801 */
+ SK,
+ SKIT,
+ SKN,
+ SKNIT,
+ SLL,
+ SLLC,
+ SLR,
+ SLRC,
+ SOFTI,
+ SSPD,
+ STAW,
+ STAX,
+ STC,
+ STEAX,
+ STM, /* 7801 */
+ STOP,
+ SUB,
+ SUBNB,
+ SUBNBW,
+ SUBNBX,
+ SUBW,
+ SUBX,
+ SUI,
+ SUINB,
+ TABLE,
+ XOR, /* 7807 */
+ XRA,
+ XRAW,
+ XRAX,
+ XRI
+};
+
+static const char *const token[] =
+{
+ "",
+ "illegal",
+ "ACI",
+ "ADC",
+ "ADCW",
+ "ADCX",
+ "ADD",
+ "ADDNC",
+ "ADDNCW",
+ "ADDNCX",
+ "ADDW",
+ "ADDX",
+ "ADI",
+ "ADINC",
+ "ANA",
+ "ANAW",
+ "ANAX",
+ "AND",
+ "ANI",
+ "ANIW",
+ "BIT",
+ "BLOCK",
+ "CALB",
+ "CALF",
+ "CALL",
+ "CALT",
+ "CLC",
+ "CLR", /* 7807 */
+ "CMC", /* 7807 */
+ "DAA",
+ "DADC",
+ "DADD",
+ "DADDNC",
+ "DAN",
+ "DCR",
+ "DCRW",
+ "DCX",
+ "DEQ",
+ "DGT",
+ "DI",
+ "DIV",
+ "DLT",
+ "DMOV",
+ "DNE",
+ "DOFF",
+ "DON",
+ "DOR",
+ "DRLL",
+ "DRLR",
+ "DSBB",
+ "DSLL",
+ "DSLR",
+ "DSUB",
+ "DSUBNB",
+ "DXR",
+ "EADD",
+ "EI",
+ "EQA",
+ "EQAW",
+ "EQAX",
+ "EQI",
+ "EQIW",
+ "ESUB",
+ "EX", /* 7801 */
+ "EXA",
+ "EXH",
+ "EXX",
+ "EXR", /* 7807 */
+ "GTA",
+ "GTAW",
+ "GTAX",
+ "GTI",
+ "GTIW",
+ "HALT",
+ "IN", /* 7801 */
+ "INR",
+ "INRW",
+ "INX",
+ "JB",
+ "JEA",
+ "JMP",
+ "JR",
+ "JRE",
+ "LBCD",
+ "LDAW",
+ "LDAX",
+ "LDEAX",
+ "LDED",
+ "LHLD",
+ "LSPD",
+ "LTA",
+ "LTAW",
+ "LTAX",
+ "LTI",
+ "LTIW",
+ "LXI",
+ "MOV",
+ "MUL",
+ "MVI",
+ "MVIW",
+ "MVIX",
+ "NEA",
+ "NEAW",
+ "NEAX",
+ "NEGA",
+ "NEI",
+ "NEIW",
+ "NOP",
+ "NOT", /* 7807 */
+ "OFFA",
+ "OFFAW",
+ "OFFAX",
+ "OFFI",
+ "OFFIW",
+ "ONA",
+ "ONAW",
+ "ONAX",
+ "ONI",
+ "ONIW",
+ "OR", /* 7807 */
+ "ORA",
+ "ORAW",
+ "ORAX",
+ "ORI",
+ "ORIW",
+ "OUT", /* 7801 */
+ "PER", /* 7801 */
+ "PEX", /* 7801 */
+ "POP",
+ "PUSH",
+ "RET",
+ "RETI",
+ "RETS",
+ "RLD",
+ "RLL",
+ "RLR",
+ "RRD",
+ "SBB",
+ "SBBW",
+ "SBBX",
+ "SBCD",
+ "SBI",
+ "SDED",
+ "SETB", /* 7807 */
+ "SHLD",
+ "SIO", /* 7801 */
+ "SK",
+ "SKIT",
+ "SKN",
+ "SKNIT",
+ "SLL",
+ "SLLC",
+ "SLR",
+ "SLRC",
+ "SOFTI",
+ "SSPD",
+ "STAW",
+ "STAX",
+ "STC",
+ "STEAX",
+ "STM", /*7801 */
+ "STOP",
+ "SUB",
+ "SUBNB",
+ "SUBNBW",
+ "SUBNBX",
+ "SUBW",
+ "SUBX",
+ "SUI",
+ "SUINB",
+ "TABLE",
+ "XOR", /* 7807 */
+ "XRA",
+ "XRAW",
+ "XRAX",
+ "XRI"
+};
+
+
+/* prefix 48 */
+static const struct dasm_s dasm48_7810[256] =
+{
+ {illegal,0 }, /* 00: 0100 1000 0000 0000 */
+ {SLRC,"A" }, /* 01: 0100 1000 0000 0001 */
+ {SLRC,"B" }, /* 02: 0100 1000 0000 0010 */
+ {SLRC,"C" }, /* 03: 0100 1000 0000 0011 */
+ {illegal,0 }, /* 04: 0100 1000 0000 0100 */
+ {SLLC,"A" }, /* 05: 0100 1000 0000 0101 */
+ {SLLC,"B" }, /* 06: 0100 1000 0000 0110 */
+ {SLLC,"C" }, /* 07: 0100 1000 0000 0111 */
+ {SK,"NV" }, /* 08: 0100 1000 0000 1000 */
+ {illegal,0 }, /* 09: 0100 1000 0000 1001 */
+ {SK,"CY" }, /* 0a: 0100 1000 0000 1010 */
+ {SK,"HC" }, /* 0b: 0100 1000 0000 1011 */
+ {SK,"Z" }, /* 0c: 0100 1000 0000 1100 */
+ {illegal,0 }, /* 0d: 0100 1000 0000 1101 */
+ {illegal,0 }, /* 0e: 0100 1000 0000 1110 */
+ {illegal,0 }, /* 0f: 0100 1000 0000 1111 */
+
+ {illegal,0 }, /* 10: 0100 1000 0001 0000 */
+ {illegal,0 }, /* 11: 0100 1000 0001 0001 */
+ {illegal,0 }, /* 12: 0100 1000 0001 0010 */
+ {illegal,0 }, /* 13: 0100 1000 0001 0011 */
+ {illegal,0 }, /* 14: 0100 1000 0001 0100 */
+ {illegal,0 }, /* 15: 0100 1000 0001 0101 */
+ {illegal,0 }, /* 16: 0100 1000 0001 0110 */
+ {illegal,0 }, /* 17: 0100 1000 0001 0111 */
+ {SKN,"NV" }, /* 18: 0100 1000 0001 1000 */
+ {illegal,0 }, /* 19: 0100 1000 0001 1001 */
+ {SKN,"CY" }, /* 1a: 0100 1000 0001 1010 */
+ {SKN,"HC" }, /* 1b: 0100 1000 0001 1011 */
+ {SKN,"Z" }, /* 1c: 0100 1000 0001 1100 */
+ {illegal,0 }, /* 1d: 0100 1000 0001 1101 */
+ {illegal,0 }, /* 1e: 0100 1000 0001 1110 */
+ {illegal,0 }, /* 1f: 0100 1000 0001 1111 */
+
+ {illegal,0 }, /* 20: 0100 1000 0010 0000 */
+ {SLR,"A" }, /* 21: 0100 1000 0010 0001 */
+ {SLR,"B" }, /* 22: 0100 1000 0010 0010 */
+ {SLR,"C" }, /* 23: 0100 1000 0010 0011 */
+ {illegal,0 }, /* 24: 0100 1000 0010 0100 */
+ {SLL,"A" }, /* 25: 0100 1000 0010 0101 */
+ {SLL,"B" }, /* 26: 0100 1000 0010 0110 */
+ {SLL,"C" }, /* 27: 0100 1000 0010 0111 */
+ {JEA,0 }, /* 28: 0100 1000 0010 1000 */
+ {CALB,0 }, /* 29: 0100 1000 0010 1001 */
+ {CLC,0 }, /* 2a: 0100 1000 0010 1010 */
+ {STC,0 }, /* 2b: 0100 1000 0010 1011 */
+ {illegal,0 }, /* 2c: 0100 1000 0010 1100 */
+ {MUL,"A" }, /* 2d: 0100 1000 0010 1101 */
+ {MUL,"B" }, /* 2e: 0100 1000 0010 1110 */
+ {MUL,"C" }, /* 2f: 0100 1000 0010 1111 */
+
+ {illegal,0 }, /* 30: 0100 1000 0011 0000 */
+ {RLR,"A" }, /* 31: 0100 1000 0011 0001 */
+ {RLR,"B" }, /* 32: 0100 1000 0011 0010 */
+ {RLR,"C" }, /* 33: 0100 1000 0011 0011 */
+ {illegal,0 }, /* 34: 0100 1000 0011 0100 */
+ {RLL,"A" }, /* 35: 0100 1000 0011 0101 */
+ {RLL,"B" }, /* 36: 0100 1000 0011 0110 */
+ {RLL,"C" }, /* 37: 0100 1000 0011 0111 */
+ {RLD,0 }, /* 38: 0100 1000 0011 1000 */
+ {RRD,0 }, /* 39: 0100 1000 0011 1001 */
+ {NEGA,0 }, /* 3a: 0100 1000 0011 1010 */
+ {HALT,0 }, /* 3b: 0100 1000 0011 1011 */
+ {illegal,0 }, /* 3c: 0100 1000 0011 1100 */
+ {DIV,"A" }, /* 3d: 0100 1000 0011 1101 */
+ {DIV,"B" }, /* 3e: 0100 1000 0011 1110 */
+ {DIV,"C" }, /* 3f: 0100 1000 0011 1111 */
+
+ {SKIT,"NMI" }, /* 40: 0100 1000 0100 0000 */
+ {SKIT,"FT0" }, /* 41: 0100 1000 0100 0001 */
+ {SKIT,"FT1" }, /* 42: 0100 1000 0100 0010 */
+ {SKIT,"F1" }, /* 43: 0100 1000 0100 0011 */
+ {SKIT,"F2" }, /* 44: 0100 1000 0100 0100 */
+ {SKIT,"FE0" }, /* 45: 0100 1000 0100 0101 */
+ {SKIT,"FE1" }, /* 46: 0100 1000 0100 0110 */
+ {SKIT,"FEIN" }, /* 47: 0100 1000 0100 0111 */
+ {SKIT,"FAD" }, /* 48: 0100 1000 0100 1000 */
+ {SKIT,"FSR" }, /* 49: 0100 1000 0100 1001 */
+ {SKIT,"FST" }, /* 4a: 0100 1000 0100 1010 */
+ {SKIT,"ER" }, /* 4b: 0100 1000 0100 1011 */
+ {SKIT,"OV" }, /* 4c: 0100 1000 0100 1100 */
+ {illegal,0 }, /* 4d: 0100 1000 0100 1101 */
+ {illegal,0 }, /* 4e: 0100 1000 0100 1110 */
+ {illegal,0 }, /* 4f: 0100 1000 0100 1111 */
+
+ {SKIT,"AN4" }, /* 50: 0100 1000 0101 0000 */
+ {SKIT,"AN5" }, /* 51: 0100 1000 0101 0001 */
+ {SKIT,"AN6" }, /* 52: 0100 1000 0101 0010 */
+ {SKIT,"AN7" }, /* 53: 0100 1000 0101 0011 */
+ {SKIT,"SB" }, /* 54: 0100 1000 0101 0100 */
+ {illegal,0 }, /* 55: 0100 1000 0101 0101 */
+ {illegal,0 }, /* 56: 0100 1000 0101 0110 */
+ {illegal,0 }, /* 57: 0100 1000 0101 0111 */
+ {illegal,0 }, /* 58: 0100 1000 0101 1000 */
+ {illegal,0 }, /* 59: 0100 1000 0101 1001 */
+ {illegal,0 }, /* 5a: 0100 1000 0101 1010 */
+ {illegal,0 }, /* 5b: 0100 1000 0101 1011 */
+ {illegal,0 }, /* 5c: 0100 1000 0101 1100 */
+ {illegal,0 }, /* 5d: 0100 1000 0101 1101 */
+ {illegal,0 }, /* 5e: 0100 1000 0101 1110 */
+ {illegal,0 }, /* 5f: 0100 1000 0101 1111 */
+
+ {SKNIT,"NMI" }, /* 60: 0100 1000 0110 0000 */
+ {SKNIT,"FT0" }, /* 61: 0100 1000 0110 0001 */
+ {SKNIT,"FT1" }, /* 62: 0100 1000 0110 0010 */
+ {SKNIT,"F1" }, /* 63: 0100 1000 0110 0011 */
+ {SKNIT,"F2" }, /* 64: 0100 1000 0110 0100 */
+ {SKNIT,"FE0" }, /* 65: 0100 1000 0110 0101 */
+ {SKNIT,"FE1" }, /* 66: 0100 1000 0110 0110 */
+ {SKNIT,"FEIN" }, /* 67: 0100 1000 0110 0111 */
+ {SKNIT,"FAD" }, /* 68: 0100 1000 0110 1000 */
+ {SKNIT,"FSR" }, /* 69: 0100 1000 0110 1001 */
+ {SKNIT,"FST" }, /* 6a: 0100 1000 0110 1010 */
+ {SKNIT,"ER" }, /* 6b: 0100 1000 0110 1011 */
+ {SKNIT,"OV" }, /* 6c: 0100 1000 0110 1100 */
+ {illegal,0 }, /* 6d: 0100 1000 0110 1101 */
+ {illegal,0 }, /* 6e: 0100 1000 0110 1110 */
+ {illegal,0 }, /* 6f: 0100 1000 0110 1111 */
+
+ {SKNIT,"AN4" }, /* 70: 0100 1000 0111 0000 */
+ {SKNIT,"AN5" }, /* 71: 0100 1000 0111 0001 */
+ {SKNIT,"AN6" }, /* 72: 0100 1000 0111 0010 */
+ {SKNIT,"AN7" }, /* 73: 0100 1000 0111 0011 */
+ {SKNIT,"SB" }, /* 74: 0100 1000 0111 0100 */
+ {illegal,0 }, /* 75: 0100 1000 0111 0101 */
+ {illegal,0 }, /* 76: 0100 1000 0111 0110 */
+ {illegal,0 }, /* 77: 0100 1000 0111 0111 */
+ {illegal,0 }, /* 78: 0100 1000 0111 1000 */
+ {illegal,0 }, /* 79: 0100 1000 0111 1001 */
+ {illegal,0 }, /* 7a: 0100 1000 0111 1010 */
+ {illegal,0 }, /* 7b: 0100 1000 0111 1011 */
+ {illegal,0 }, /* 7c: 0100 1000 0111 1100 */
+ {illegal,0 }, /* 7d: 0100 1000 0111 1101 */
+ {illegal,0 }, /* 7e: 0100 1000 0111 1110 */
+ {illegal,0 }, /* 7f: 0100 1000 0111 1111 */
+
+ {illegal,0 }, /* 80: 0100 1000 1000 0000 */
+ {illegal,0 }, /* 81: 0100 1000 1000 0001 */
+ {LDEAX,"(DE)" }, /* 82: 0100 1000 1000 0010 */
+ {LDEAX,"(HL)" }, /* 83: 0100 1000 1000 0011 */
+ {LDEAX,"(DE++)" }, /* 84: 0100 1000 1000 0100 */
+ {LDEAX,"(HL++)" }, /* 85: 0100 1000 1000 0101 */
+ {illegal,0 }, /* 86: 0100 1000 1000 0110 */
+ {illegal,0 }, /* 87: 0100 1000 1000 0111 */
+ {illegal,0 }, /* 88: 0100 1000 1000 1000 */
+ {illegal,0 }, /* 89: 0100 1000 1000 1001 */
+ {illegal,0 }, /* 8a: 0100 1000 1000 1010 */
+ {LDEAX,"(DE+%b)"}, /* 8b: 0100 1000 1000 1011 xxxx xxxx */
+ {LDEAX,"(HL+A)" }, /* 8c: 0100 1000 1000 1100 */
+ {LDEAX,"(HL+B)" }, /* 8d: 0100 1000 1000 1101 */
+ {LDEAX,"(HL+EA)"}, /* 8e: 0100 1000 1000 1110 */
+ {LDEAX,"(HL+%b)"}, /* 8f: 0100 1000 1000 1111 xxxx xxxx */
+
+ {illegal,0 }, /* 90: 0100 1000 1000 0000 */
+ {illegal,0 }, /* 91: 0100 1000 1000 0001 */
+ {STEAX,"(DE)" }, /* 92: 0100 1000 1000 0010 */
+ {STEAX,"(HL)" }, /* 93: 0100 1000 1000 0011 */
+ {STEAX,"(DE++)" }, /* 94: 0100 1000 1000 0100 */
+ {STEAX,"(HL++)" }, /* 95: 0100 1000 1000 0101 */
+ {illegal,0 }, /* 96: 0100 1000 1000 0110 */
+ {illegal,0 }, /* 97: 0100 1000 1000 0111 */
+ {illegal,0 }, /* 98: 0100 1000 1000 1000 */
+ {illegal,0 }, /* 99: 0100 1000 1000 1001 */
+ {illegal,0 }, /* 9a: 0100 1000 1000 1010 */
+ {STEAX,"(DE+%b)"}, /* 9b: 0100 1000 1000 1011 xxxx xxxx */
+ {STEAX,"(HL+A)" }, /* 9c: 0100 1000 1000 1100 */
+ {STEAX,"(HL+B)" }, /* 9d: 0100 1000 1000 1101 */
+ {STEAX,"(HL+EA)"}, /* 9e: 0100 1000 1000 1110 */
+ {STEAX,"(HL+%b)"}, /* 9f: 0100 1000 1000 1111 xxxx xxxx */
+
+ {DSLR,"EA" }, /* a0: 0100 1000 1010 0000 */
+ {illegal,0 }, /* a1: 0100 1000 1010 0001 */
+ {illegal,0 }, /* a2: 0100 1000 1010 0010 */
+ {illegal,0 }, /* a3: 0100 1000 1010 0011 */
+ {DSLL,"EA" }, /* a4: 0100 1000 1010 0100 */
+ {illegal,0 }, /* a5: 0100 1000 1010 0101 */
+ {illegal,0 }, /* a6: 0100 1000 1010 0110 */
+ {illegal,0 }, /* a7: 0100 1000 1010 0111 */
+ {TABLE,0 }, /* a8: 0100 1000 1010 1000 */
+ {illegal,0 }, /* a9: 0100 1000 1010 1001 */
+ {illegal,0 }, /* aa: 0100 1000 1010 1010 */
+ {illegal,0 }, /* ab: 0100 1000 1010 1011 */
+ {illegal,0 }, /* ac: 0100 1000 1010 1100 */
+ {illegal,0 }, /* ad: 0100 1000 1010 1101 */
+ {illegal,0 }, /* ae: 0100 1000 1010 1110 */
+ {illegal,0 }, /* af: 0100 1000 1010 1111 */
+
+ {DRLR,"EA" }, /* b0: 0100 1000 1011 0000 */
+ {illegal,0 }, /* b1: 0100 1000 1011 0001 */
+ {illegal,0 }, /* b2: 0100 1000 1011 0010 */
+ {illegal,0 }, /* b3: 0100 1000 1011 0011 */
+ {DRLL,"EA" }, /* b4: 0100 1000 1011 0100 */
+ {illegal,0 }, /* b5: 0100 1000 1011 0101 */
+ {illegal,0 }, /* b6: 0100 1000 1011 0110 */
+ {illegal,0 }, /* b7: 0100 1000 1011 0111 */
+ {illegal,0 }, /* b8: 0100 1000 1011 1000 */
+ {illegal,0 }, /* b9: 0100 1000 1011 1001 */
+ {illegal,0 }, /* ba: 0100 1000 1011 1010 */
+ {STOP,0 }, /* bb: 0100 1000 1011 1011 */ /* 7810 */
+ {illegal,0 }, /* bc: 0100 1000 1011 1100 */
+ {illegal,0 }, /* bd: 0100 1000 1011 1101 */
+ {illegal,0 }, /* be: 0100 1000 1011 1110 */
+ {illegal,0 }, /* bf: 0100 1000 1011 1111 */
+
+ {DMOV,"EA,ECNT" }, /* c0: 0100 1000 1100 0000 */
+ {DMOV,"EA,ECPT" }, /* c1: 0100 1000 1100 0001 */ /* 7810 */
+ {illegal,0 }, /* c2: 0100 1000 1100 0010 */
+ {illegal,0 }, /* c3: 0100 1000 1100 0011 */
+ {illegal,0 }, /* c4: 0100 1000 1100 0100 */
+ {illegal,0 }, /* c5: 0100 1000 1100 0101 */
+ {illegal,0 }, /* c6: 0100 1000 1100 0110 */
+ {illegal,0 }, /* c7: 0100 1000 1100 0111 */
+ {illegal,0 }, /* c8: 0100 1000 1100 1000 */
+ {illegal,0 }, /* c9: 0100 1000 1100 1001 */
+ {illegal,0 }, /* ca: 0100 1000 1100 1010 */
+ {illegal,0 }, /* cb: 0100 1000 1100 1011 */
+ {illegal,0 }, /* cc: 0100 1000 1100 1100 */
+ {illegal,0 }, /* cd: 0100 1000 1100 1101 */
+ {illegal,0 }, /* ce: 0100 1000 1100 1110 */
+ {illegal,0 }, /* cf: 0100 1000 1100 1111 */
+
+ {illegal,0 }, /* d0: 0100 1000 1101 0000 */
+ {illegal,0 }, /* d1: 0100 1000 1101 0001 */
+ {DMOV,"ETM0,EA" }, /* d2: 0100 1000 1101 0010 */
+ {DMOV,"ETM1,EA" }, /* d3: 0100 1000 1101 0011 */
+ {illegal,0 }, /* d4: 0100 1000 1101 0100 */
+ {illegal,0 }, /* d5: 0100 1000 1101 0101 */
+ {illegal,0 }, /* d6: 0100 1000 1101 0110 */
+ {illegal,0 }, /* d7: 0100 1000 1101 0111 */
+ {illegal,0 }, /* d8: 0100 1000 1101 1000 */
+ {illegal,0 }, /* d9: 0100 1000 1101 1001 */
+ {illegal,0 }, /* da: 0100 1000 1101 1010 */
+ {illegal,0 }, /* db: 0100 1000 1101 1011 */
+ {illegal,0 }, /* dc: 0100 1000 1101 1100 */
+ {illegal,0 }, /* dd: 0100 1000 1101 1101 */
+ {illegal,0 }, /* de: 0100 1000 1101 1110 */
+ {illegal,0 }, /* df: 0100 1000 1101 1111 */
+
+ {illegal,0 }, /* e0: 0100 1000 1110 0000 */
+ {illegal,0 }, /* e1: 0100 1000 1110 0001 */
+ {illegal,0 }, /* e2: 0100 1000 1110 0010 */
+ {illegal,0 }, /* e3: 0100 1000 1110 0011 */
+ {illegal,0 }, /* e4: 0100 1000 1110 0100 */
+ {illegal,0 }, /* e5: 0100 1000 1110 0101 */
+ {illegal,0 }, /* e6: 0100 1000 1110 0110 */
+ {illegal,0 }, /* e7: 0100 1000 1110 0111 */
+ {illegal,0 }, /* e8: 0100 1000 1110 1000 */
+ {illegal,0 }, /* e9: 0100 1000 1110 1001 */
+ {illegal,0 }, /* ea: 0100 1000 1110 1010 */
+ {illegal,0 }, /* eb: 0100 1000 1110 1011 */
+ {illegal,0 }, /* ec: 0100 1000 1110 1100 */
+ {illegal,0 }, /* ed: 0100 1000 1110 1101 */
+ {illegal,0 }, /* ee: 0100 1000 1110 1110 */
+ {illegal,0 }, /* ef: 0100 1000 1110 1111 */
+
+ {illegal,0 }, /* f0: 0100 1000 1111 0000 */
+ {illegal,0 }, /* f1: 0100 1000 1111 0001 */
+ {illegal,0 }, /* f2: 0100 1000 1111 0010 */
+ {illegal,0 }, /* f3: 0100 1000 1111 0011 */
+ {illegal,0 }, /* f4: 0100 1000 1111 0100 */
+ {illegal,0 }, /* f5: 0100 1000 1111 0101 */
+ {illegal,0 }, /* f6: 0100 1000 1111 0110 */
+ {illegal,0 }, /* f7: 0100 1000 1111 0111 */
+ {illegal,0 }, /* f8: 0100 1000 1111 1000 */
+ {illegal,0 }, /* f9: 0100 1000 1111 1001 */
+ {illegal,0 }, /* fa: 0100 1000 1111 1010 */
+ {illegal,0 }, /* fb: 0100 1000 1111 1011 */
+ {illegal,0 }, /* fc: 0100 1000 1111 1100 */
+ {illegal,0 }, /* fd: 0100 1000 1111 1101 */
+ {illegal,0 }, /* fe: 0100 1000 1111 1110 */
+ {illegal,0 } /* ff: 0100 1000 1111 1111 */
+};
+
+static const struct dasm_s dasm48_7807[256] =
+{
+ {illegal,0 }, /* 00: 0100 1000 0000 0000 */
+ {SLRC,"A" }, /* 01: 0100 1000 0000 0001 */
+ {SLRC,"B" }, /* 02: 0100 1000 0000 0010 */
+ {SLRC,"C" }, /* 03: 0100 1000 0000 0011 */
+ {illegal,0 }, /* 04: 0100 1000 0000 0100 */
+ {SLLC,"A" }, /* 05: 0100 1000 0000 0101 */
+ {SLLC,"B" }, /* 06: 0100 1000 0000 0110 */
+ {SLLC,"C" }, /* 07: 0100 1000 0000 0111 */
+ {SK,"NV" }, /* 08: 0100 1000 0000 1000 */
+ {illegal,0 }, /* 09: 0100 1000 0000 1001 */
+ {SK,"CY" }, /* 0a: 0100 1000 0000 1010 */
+ {SK,"HC" }, /* 0b: 0100 1000 0000 1011 */
+ {SK,"Z" }, /* 0c: 0100 1000 0000 1100 */
+ {illegal,0 }, /* 0d: 0100 1000 0000 1101 */
+ {illegal,0 }, /* 0e: 0100 1000 0000 1110 */
+ {illegal,0 }, /* 0f: 0100 1000 0000 1111 */
+
+ {illegal,0 }, /* 10: 0100 1000 0001 0000 */
+ {illegal,0 }, /* 11: 0100 1000 0001 0001 */
+ {illegal,0 }, /* 12: 0100 1000 0001 0010 */
+ {illegal,0 }, /* 13: 0100 1000 0001 0011 */
+ {illegal,0 }, /* 14: 0100 1000 0001 0100 */
+ {illegal,0 }, /* 15: 0100 1000 0001 0101 */
+ {illegal,0 }, /* 16: 0100 1000 0001 0110 */
+ {illegal,0 }, /* 17: 0100 1000 0001 0111 */
+ {SKN,"NV" }, /* 18: 0100 1000 0001 1000 */
+ {illegal,0 }, /* 19: 0100 1000 0001 1001 */
+ {SKN,"CY" }, /* 1a: 0100 1000 0001 1010 */
+ {SKN,"HC" }, /* 1b: 0100 1000 0001 1011 */
+ {SKN,"Z" }, /* 1c: 0100 1000 0001 1100 */
+ {illegal,0 }, /* 1d: 0100 1000 0001 1101 */
+ {illegal,0 }, /* 1e: 0100 1000 0001 1110 */
+ {illegal,0 }, /* 1f: 0100 1000 0001 1111 */
+
+ {illegal,0 }, /* 20: 0100 1000 0010 0000 */
+ {SLR,"A" }, /* 21: 0100 1000 0010 0001 */
+ {SLR,"B" }, /* 22: 0100 1000 0010 0010 */
+ {SLR,"C" }, /* 23: 0100 1000 0010 0011 */
+ {illegal,0 }, /* 24: 0100 1000 0010 0100 */
+ {SLL,"A" }, /* 25: 0100 1000 0010 0101 */
+ {SLL,"B" }, /* 26: 0100 1000 0010 0110 */
+ {SLL,"C" }, /* 27: 0100 1000 0010 0111 */
+ {JEA,0 }, /* 28: 0100 1000 0010 1000 */
+ {CALB,0 }, /* 29: 0100 1000 0010 1001 */
+ {CLC,0 }, /* 2a: 0100 1000 0010 1010 */
+ {STC,0 }, /* 2b: 0100 1000 0010 1011 */
+ {illegal,0 }, /* 2c: 0100 1000 0010 1100 */
+ {MUL,"A" }, /* 2d: 0100 1000 0010 1101 */
+ {MUL,"B" }, /* 2e: 0100 1000 0010 1110 */
+ {MUL,"C" }, /* 2f: 0100 1000 0010 1111 */
+
+ {illegal,0 }, /* 30: 0100 1000 0011 0000 */
+ {RLR,"A" }, /* 31: 0100 1000 0011 0001 */
+ {RLR,"B" }, /* 32: 0100 1000 0011 0010 */
+ {RLR,"C" }, /* 33: 0100 1000 0011 0011 */
+ {illegal,0 }, /* 34: 0100 1000 0011 0100 */
+ {RLL,"A" }, /* 35: 0100 1000 0011 0101 */
+ {RLL,"B" }, /* 36: 0100 1000 0011 0110 */
+ {RLL,"C" }, /* 37: 0100 1000 0011 0111 */
+ {RLD,0 }, /* 38: 0100 1000 0011 1000 */
+ {RRD,0 }, /* 39: 0100 1000 0011 1001 */
+ {NEGA,0 }, /* 3a: 0100 1000 0011 1010 */
+ {HALT,0 }, /* 3b: 0100 1000 0011 1011 */
+ {illegal,0 }, /* 3c: 0100 1000 0011 1100 */
+ {DIV,"A" }, /* 3d: 0100 1000 0011 1101 */
+ {DIV,"B" }, /* 3e: 0100 1000 0011 1110 */
+ {DIV,"C" }, /* 3f: 0100 1000 0011 1111 */
+
+ {SKIT,"NMI" }, /* 40: 0100 1000 0100 0000 */
+ {SKIT,"FT0" }, /* 41: 0100 1000 0100 0001 */
+ {SKIT,"FT1" }, /* 42: 0100 1000 0100 0010 */
+ {SKIT,"F1" }, /* 43: 0100 1000 0100 0011 */
+ {SKIT,"F2" }, /* 44: 0100 1000 0100 0100 */
+ {SKIT,"FE0" }, /* 45: 0100 1000 0100 0101 */
+ {SKIT,"FE1" }, /* 46: 0100 1000 0100 0110 */
+ {SKIT,"FEIN" }, /* 47: 0100 1000 0100 0111 */
+ {SKIT,"FAD" }, /* 48: 0100 1000 0100 1000 */
+ {SKIT,"FSR" }, /* 49: 0100 1000 0100 1001 */
+ {SKIT,"FST" }, /* 4a: 0100 1000 0100 1010 */
+ {SKIT,"ER" }, /* 4b: 0100 1000 0100 1011 */
+ {SKIT,"OV" }, /* 4c: 0100 1000 0100 1100 */
+ {illegal,0 }, /* 4d: 0100 1000 0100 1101 */
+ {illegal,0 }, /* 4e: 0100 1000 0100 1110 */
+ {illegal,0 }, /* 4f: 0100 1000 0100 1111 */
+
+ {SKIT,"AN4" }, /* 50: 0100 1000 0101 0000 */
+ {SKIT,"AN5" }, /* 51: 0100 1000 0101 0001 */
+ {SKIT,"AN6" }, /* 52: 0100 1000 0101 0010 */
+ {SKIT,"AN7" }, /* 53: 0100 1000 0101 0011 */
+ {SKIT,"SB" }, /* 54: 0100 1000 0101 0100 */
+ {illegal,0 }, /* 55: 0100 1000 0101 0101 */
+ {illegal,0 }, /* 56: 0100 1000 0101 0110 */
+ {illegal,0 }, /* 57: 0100 1000 0101 0111 */
+ {illegal,0 }, /* 58: 0100 1000 0101 1000 */
+ {illegal,0 }, /* 59: 0100 1000 0101 1001 */
+ {illegal,0 }, /* 5a: 0100 1000 0101 1010 */
+ {illegal,0 }, /* 5b: 0100 1000 0101 1011 */
+ {illegal,0 }, /* 5c: 0100 1000 0101 1100 */
+ {illegal,0 }, /* 5d: 0100 1000 0101 1101 */
+ {illegal,0 }, /* 5e: 0100 1000 0101 1110 */
+ {illegal,0 }, /* 5f: 0100 1000 0101 1111 */
+
+ {SKNIT,"NMI" }, /* 60: 0100 1000 0110 0000 */
+ {SKNIT,"FT0" }, /* 61: 0100 1000 0110 0001 */
+ {SKNIT,"FT1" }, /* 62: 0100 1000 0110 0010 */
+ {SKNIT,"F1" }, /* 63: 0100 1000 0110 0011 */
+ {SKNIT,"F2" }, /* 64: 0100 1000 0110 0100 */
+ {SKNIT,"FE0" }, /* 65: 0100 1000 0110 0101 */
+ {SKNIT,"FE1" }, /* 66: 0100 1000 0110 0110 */
+ {SKNIT,"FEIN" }, /* 67: 0100 1000 0110 0111 */
+ {SKNIT,"FAD" }, /* 68: 0100 1000 0110 1000 */
+ {SKNIT,"FSR" }, /* 69: 0100 1000 0110 1001 */
+ {SKNIT,"FST" }, /* 6a: 0100 1000 0110 1010 */
+ {SKNIT,"ER" }, /* 6b: 0100 1000 0110 1011 */
+ {SKNIT,"OV" }, /* 6c: 0100 1000 0110 1100 */
+ {illegal,0 }, /* 6d: 0100 1000 0110 1101 */
+ {illegal,0 }, /* 6e: 0100 1000 0110 1110 */
+ {illegal,0 }, /* 6f: 0100 1000 0110 1111 */
+
+ {SKNIT,"AN4" }, /* 70: 0100 1000 0111 0000 */
+ {SKNIT,"AN5" }, /* 71: 0100 1000 0111 0001 */
+ {SKNIT,"AN6" }, /* 72: 0100 1000 0111 0010 */
+ {SKNIT,"AN7" }, /* 73: 0100 1000 0111 0011 */
+ {SKNIT,"SB" }, /* 74: 0100 1000 0111 0100 */
+ {illegal,0 }, /* 75: 0100 1000 0111 0101 */
+ {illegal,0 }, /* 76: 0100 1000 0111 0110 */
+ {illegal,0 }, /* 77: 0100 1000 0111 0111 */
+ {illegal,0 }, /* 78: 0100 1000 0111 1000 */
+ {illegal,0 }, /* 79: 0100 1000 0111 1001 */
+ {illegal,0 }, /* 7a: 0100 1000 0111 1010 */
+ {illegal,0 }, /* 7b: 0100 1000 0111 1011 */
+ {illegal,0 }, /* 7c: 0100 1000 0111 1100 */
+ {illegal,0 }, /* 7d: 0100 1000 0111 1101 */
+ {illegal,0 }, /* 7e: 0100 1000 0111 1110 */
+ {illegal,0 }, /* 7f: 0100 1000 0111 1111 */
+
+ {illegal,0 }, /* 80: 0100 1000 1000 0000 */
+ {illegal,0 }, /* 81: 0100 1000 1000 0001 */
+ {LDEAX,"(DE)" }, /* 82: 0100 1000 1000 0010 */
+ {LDEAX,"(HL)" }, /* 83: 0100 1000 1000 0011 */
+ {LDEAX,"(DE++)" }, /* 84: 0100 1000 1000 0100 */
+ {LDEAX,"(HL++)" }, /* 85: 0100 1000 1000 0101 */
+ {illegal,0 }, /* 86: 0100 1000 1000 0110 */
+ {illegal,0 }, /* 87: 0100 1000 1000 0111 */
+ {illegal,0 }, /* 88: 0100 1000 1000 1000 */
+ {illegal,0 }, /* 89: 0100 1000 1000 1001 */
+ {illegal,0 }, /* 8a: 0100 1000 1000 1010 */
+ {LDEAX,"(DE+%b)"}, /* 8b: 0100 1000 1000 1011 xxxx xxxx */
+ {LDEAX,"(HL+A)" }, /* 8c: 0100 1000 1000 1100 */
+ {LDEAX,"(HL+B)" }, /* 8d: 0100 1000 1000 1101 */
+ {LDEAX,"(HL+EA)"}, /* 8e: 0100 1000 1000 1110 */
+ {LDEAX,"(HL+%b)"}, /* 8f: 0100 1000 1000 1111 xxxx xxxx */
+
+ {illegal,0 }, /* 90: 0100 1000 1000 0000 */
+ {illegal,0 }, /* 91: 0100 1000 1000 0001 */
+ {STEAX,"(DE)" }, /* 92: 0100 1000 1000 0010 */
+ {STEAX,"(HL)" }, /* 93: 0100 1000 1000 0011 */
+ {STEAX,"(DE++)" }, /* 94: 0100 1000 1000 0100 */
+ {STEAX,"(HL++)" }, /* 95: 0100 1000 1000 0101 */
+ {illegal,0 }, /* 96: 0100 1000 1000 0110 */
+ {illegal,0 }, /* 97: 0100 1000 1000 0111 */
+ {illegal,0 }, /* 98: 0100 1000 1000 1000 */
+ {illegal,0 }, /* 99: 0100 1000 1000 1001 */
+ {illegal,0 }, /* 9a: 0100 1000 1000 1010 */
+ {STEAX,"(DE+%b)"}, /* 9b: 0100 1000 1000 1011 xxxx xxxx */
+ {STEAX,"(HL+A)" }, /* 9c: 0100 1000 1000 1100 */
+ {STEAX,"(HL+B)" }, /* 9d: 0100 1000 1000 1101 */
+ {STEAX,"(HL+EA)"}, /* 9e: 0100 1000 1000 1110 */
+ {STEAX,"(HL+%b)"}, /* 9f: 0100 1000 1000 1111 xxxx xxxx */
+
+ {DSLR,"EA" }, /* a0: 0100 1000 1010 0000 */
+ {illegal,0 }, /* a1: 0100 1000 1010 0001 */
+ {illegal,0 }, /* a2: 0100 1000 1010 0010 */
+ {illegal,0 }, /* a3: 0100 1000 1010 0011 */
+ {DSLL,"EA" }, /* a4: 0100 1000 1010 0100 */
+ {illegal,0 }, /* a5: 0100 1000 1010 0101 */
+ {illegal,0 }, /* a6: 0100 1000 1010 0110 */
+ {illegal,0 }, /* a7: 0100 1000 1010 0111 */
+ {TABLE,0 }, /* a8: 0100 1000 1010 1000 */
+ {illegal,0 }, /* a9: 0100 1000 1010 1001 */
+ {CMC,0 }, /* aa: 0100 1000 1010 1010 */ /* 7807 */
+ {illegal,0 }, /* ab: 0100 1000 1010 1011 */
+ {EXA,0 }, /* ac: 0100 1000 1010 1100 */ /* 7807 */
+ {EXR,0 }, /* ad: 0100 1000 1010 1101 */ /* 7807 */
+ {EXH,0 }, /* ae: 0100 1000 1010 1110 */ /* 7807 */
+ {EXX,0 }, /* af: 0100 1000 1010 1111 */ /* 7807 */
+
+ {DRLR,"EA" }, /* b0: 0100 1000 1011 0000 */
+ {illegal,0 }, /* b1: 0100 1000 1011 0001 */
+ {illegal,0 }, /* b2: 0100 1000 1011 0010 */
+ {illegal,0 }, /* b3: 0100 1000 1011 0011 */
+ {DRLL,"EA" }, /* b4: 0100 1000 1011 0100 */
+ {illegal,0 }, /* b5: 0100 1000 1011 0101 */
+ {illegal,0 }, /* b6: 0100 1000 1011 0110 */
+ {illegal,0 }, /* b7: 0100 1000 1011 0111 */
+ {illegal,0 }, /* b8: 0100 1000 1011 1000 */
+ {illegal,0 }, /* b9: 0100 1000 1011 1001 */
+ {illegal,0 }, /* ba: 0100 1000 1011 1010 */
+ {illegal,0 }, /* bb: 0100 1000 1011 1011 */
+ {illegal,0 }, /* bc: 0100 1000 1011 1100 */
+ {illegal,0 }, /* bd: 0100 1000 1011 1101 */
+ {illegal,0 }, /* be: 0100 1000 1011 1110 */
+ {illegal,0 }, /* bf: 0100 1000 1011 1111 */
+
+ {DMOV,"EA,ECNT" }, /* c0: 0100 1000 1100 0000 */
+ {DMOV,"EA,ECPT0"}, /* c1: 0100 1000 1100 0001 */ /* 7807 */
+ {DMOV,"EA,ECPT1"}, /* c2: 0100 1000 1100 0010 */ /* 7807 */
+ {illegal,0 }, /* c3: 0100 1000 1100 0011 */
+ {illegal,0 }, /* c4: 0100 1000 1100 0100 */
+ {illegal,0 }, /* c5: 0100 1000 1100 0101 */
+ {illegal,0 }, /* c6: 0100 1000 1100 0110 */
+ {illegal,0 }, /* c7: 0100 1000 1100 0111 */
+ {illegal,0 }, /* c8: 0100 1000 1100 1000 */
+ {illegal,0 }, /* c9: 0100 1000 1100 1001 */
+ {illegal,0 }, /* ca: 0100 1000 1100 1010 */
+ {illegal,0 }, /* cb: 0100 1000 1100 1011 */
+ {illegal,0 }, /* cc: 0100 1000 1100 1100 */
+ {illegal,0 }, /* cd: 0100 1000 1100 1101 */
+ {illegal,0 }, /* ce: 0100 1000 1100 1110 */
+ {illegal,0 }, /* cf: 0100 1000 1100 1111 */
+
+ {illegal,0 }, /* d0: 0100 1000 1101 0000 */
+ {illegal,0 }, /* d1: 0100 1000 1101 0001 */
+ {DMOV,"ETM0,EA" }, /* d2: 0100 1000 1101 0010 */
+ {DMOV,"ETM1,EA" }, /* d3: 0100 1000 1101 0011 */
+ {illegal,0 }, /* d4: 0100 1000 1101 0100 */
+ {illegal,0 }, /* d5: 0100 1000 1101 0101 */
+ {illegal,0 }, /* d6: 0100 1000 1101 0110 */
+ {illegal,0 }, /* d7: 0100 1000 1101 0111 */
+ {illegal,0 }, /* d8: 0100 1000 1101 1000 */
+ {illegal,0 }, /* d9: 0100 1000 1101 1001 */
+ {illegal,0 }, /* da: 0100 1000 1101 1010 */
+ {illegal,0 }, /* db: 0100 1000 1101 1011 */
+ {illegal,0 }, /* dc: 0100 1000 1101 1100 */
+ {illegal,0 }, /* dd: 0100 1000 1101 1101 */
+ {illegal,0 }, /* de: 0100 1000 1101 1110 */
+ {illegal,0 }, /* df: 0100 1000 1101 1111 */
+
+ {illegal,0 }, /* e0: 0100 1000 1110 0000 */
+ {illegal,0 }, /* e1: 0100 1000 1110 0001 */
+ {illegal,0 }, /* e2: 0100 1000 1110 0010 */
+ {illegal,0 }, /* e3: 0100 1000 1110 0011 */
+ {illegal,0 }, /* e4: 0100 1000 1110 0100 */
+ {illegal,0 }, /* e5: 0100 1000 1110 0101 */
+ {illegal,0 }, /* e6: 0100 1000 1110 0110 */
+ {illegal,0 }, /* e7: 0100 1000 1110 0111 */
+ {illegal,0 }, /* e8: 0100 1000 1110 1000 */
+ {illegal,0 }, /* e9: 0100 1000 1110 1001 */
+ {illegal,0 }, /* ea: 0100 1000 1110 1010 */
+ {illegal,0 }, /* eb: 0100 1000 1110 1011 */
+ {illegal,0 }, /* ec: 0100 1000 1110 1100 */
+ {illegal,0 }, /* ed: 0100 1000 1110 1101 */
+ {illegal,0 }, /* ee: 0100 1000 1110 1110 */
+ {illegal,0 }, /* ef: 0100 1000 1110 1111 */
+
+ {illegal,0 }, /* f0: 0100 1000 1111 0000 */
+ {illegal,0 }, /* f1: 0100 1000 1111 0001 */
+ {illegal,0 }, /* f2: 0100 1000 1111 0010 */
+ {illegal,0 }, /* f3: 0100 1000 1111 0011 */
+ {illegal,0 }, /* f4: 0100 1000 1111 0100 */
+ {illegal,0 }, /* f5: 0100 1000 1111 0101 */
+ {illegal,0 }, /* f6: 0100 1000 1111 0110 */
+ {illegal,0 }, /* f7: 0100 1000 1111 0111 */
+ {illegal,0 }, /* f8: 0100 1000 1111 1000 */
+ {illegal,0 }, /* f9: 0100 1000 1111 1001 */
+ {illegal,0 }, /* fa: 0100 1000 1111 1010 */
+ {illegal,0 }, /* fb: 0100 1000 1111 1011 */
+ {illegal,0 }, /* fc: 0100 1000 1111 1100 */
+ {illegal,0 }, /* fd: 0100 1000 1111 1101 */
+ {illegal,0 }, /* fe: 0100 1000 1111 1110 */
+ {illegal,0 } /* ff: 0100 1000 1111 1111 */
+};
+
+/* prefix 4C */
+static const struct dasm_s dasm4C_7810[256] =
+{
+ {illegal,0 }, /* 00: 0100 1100 0000 0000 */
+ {illegal,0 }, /* 01: 0100 1100 0000 0001 */
+ {illegal,0 }, /* 02: 0100 1100 0000 0010 */
+ {illegal,0 }, /* 03: 0100 1100 0000 0011 */
+ {illegal,0 }, /* 04: 0100 1100 0000 0100 */
+ {illegal,0 }, /* 05: 0100 1100 0000 0101 */
+ {illegal,0 }, /* 06: 0100 1100 0000 0110 */
+ {illegal,0 }, /* 07: 0100 1100 0000 0111 */
+ {illegal,0 }, /* 08: 0100 1100 0000 1000 */
+ {illegal,0 }, /* 09: 0100 1100 0000 1001 */
+ {illegal,0 }, /* 0a: 0100 1100 0000 1010 */
+ {illegal,0 }, /* 0b: 0100 1100 0000 1011 */
+ {illegal,0 }, /* 0c: 0100 1100 0000 1100 */
+ {illegal,0 }, /* 0d: 0100 1100 0000 1101 */
+ {illegal,0 }, /* 0e: 0100 1100 0000 1110 */
+ {illegal,0 }, /* 0f: 0100 1100 0000 1111 */
+
+ {illegal,0 }, /* 10: 0100 1100 0001 0000 */
+ {illegal,0 }, /* 11: 0100 1100 0001 0001 */
+ {illegal,0 }, /* 12: 0100 1100 0001 0010 */
+ {illegal,0 }, /* 13: 0100 1100 0001 0011 */
+ {illegal,0 }, /* 14: 0100 1100 0001 0100 */
+ {illegal,0 }, /* 15: 0100 1100 0001 0101 */
+ {illegal,0 }, /* 16: 0100 1100 0001 0110 */
+ {illegal,0 }, /* 17: 0100 1100 0001 0111 */
+ {illegal,0 }, /* 18: 0100 1100 0001 1000 */
+ {illegal,0 }, /* 19: 0100 1100 0001 1001 */
+ {illegal,0 }, /* 1a: 0100 1100 0001 1010 */
+ {illegal,0 }, /* 1b: 0100 1100 0001 1011 */
+ {illegal,0 }, /* 1c: 0100 1100 0001 1100 */
+ {illegal,0 }, /* 1d: 0100 1100 0001 1101 */
+ {illegal,0 }, /* 1e: 0100 1100 0001 1110 */
+ {illegal,0 }, /* 1f: 0100 1100 0001 1111 */
+
+ {illegal,0 }, /* 20: 0100 1100 0010 0000 */
+ {illegal,0 }, /* 21: 0100 1100 0010 0001 */
+ {illegal,0 }, /* 22: 0100 1100 0010 0010 */
+ {illegal,0 }, /* 23: 0100 1100 0010 0011 */
+ {illegal,0 }, /* 24: 0100 1100 0010 0100 */
+ {illegal,0 }, /* 25: 0100 1100 0010 0101 */
+ {illegal,0 }, /* 26: 0100 1100 0010 0110 */
+ {illegal,0 }, /* 27: 0100 1100 0010 0111 */
+ {illegal,0 }, /* 28: 0100 1100 0010 1000 */
+ {illegal,0 }, /* 29: 0100 1100 0010 1001 */
+ {illegal,0 }, /* 2a: 0100 1100 0010 1010 */
+ {illegal,0 }, /* 2b: 0100 1100 0010 1011 */
+ {illegal,0 }, /* 2c: 0100 1100 0010 1100 */
+ {illegal,0 }, /* 2d: 0100 1100 0010 1101 */
+ {illegal,0 }, /* 2e: 0100 1100 0010 1110 */
+ {illegal,0 }, /* 2f: 0100 1100 0010 1111 */
+
+ {illegal,0 }, /* 30: 0100 1100 0011 0000 */
+ {illegal,0 }, /* 31: 0100 1100 0011 0001 */
+ {illegal,0 }, /* 32: 0100 1100 0011 0010 */
+ {illegal,0 }, /* 33: 0100 1100 0011 0011 */
+ {illegal,0 }, /* 34: 0100 1100 0011 0100 */
+ {illegal,0 }, /* 35: 0100 1100 0011 0101 */
+ {illegal,0 }, /* 36: 0100 1100 0011 0110 */
+ {illegal,0 }, /* 37: 0100 1100 0011 0111 */
+ {illegal,0 }, /* 38: 0100 1100 0011 1000 */
+ {illegal,0 }, /* 39: 0100 1100 0011 1001 */
+ {illegal,0 }, /* 3a: 0100 1100 0011 1010 */
+ {illegal,0 }, /* 3b: 0100 1100 0011 1011 */
+ {illegal,0 }, /* 3c: 0100 1100 0011 1100 */
+ {illegal,0 }, /* 3d: 0100 1100 0011 1101 */
+ {illegal,0 }, /* 3e: 0100 1100 0011 1110 */
+ {illegal,0 }, /* 3f: 0100 1100 0011 1111 */
+
+ {illegal,0 }, /* 40: 0100 1100 0100 0000 */
+ {illegal,0 }, /* 41: 0100 1100 0100 0001 */
+ {illegal,0 }, /* 42: 0100 1100 0100 0010 */
+ {illegal,0 }, /* 43: 0100 1100 0100 0011 */
+ {illegal,0 }, /* 44: 0100 1100 0100 0100 */
+ {illegal,0 }, /* 45: 0100 1100 0100 0101 */
+ {illegal,0 }, /* 46: 0100 1100 0100 0110 */
+ {illegal,0 }, /* 47: 0100 1100 0100 0111 */
+ {illegal,0 }, /* 48: 0100 1100 0100 1000 */
+ {illegal,0 }, /* 49: 0100 1100 0100 1001 */
+ {illegal,0 }, /* 4a: 0100 1100 0100 1010 */
+ {illegal,0 }, /* 4b: 0100 1100 0100 1011 */
+ {illegal,0 }, /* 4c: 0100 1100 0100 1100 */
+ {illegal,0 }, /* 4d: 0100 1100 0100 1101 */
+ {illegal,0 }, /* 4e: 0100 1100 0100 1110 */
+ {illegal,0 }, /* 4f: 0100 1100 0100 1111 */
+
+ {illegal,0 }, /* 50: 0100 1100 0101 0000 */
+ {illegal,0 }, /* 51: 0100 1100 0101 0001 */
+ {illegal,0 }, /* 52: 0100 1100 0101 0010 */
+ {illegal,0 }, /* 53: 0100 1100 0101 0011 */
+ {illegal,0 }, /* 54: 0100 1100 0101 0100 */
+ {illegal,0 }, /* 55: 0100 1100 0101 0101 */
+ {illegal,0 }, /* 56: 0100 1100 0101 0110 */
+ {illegal,0 }, /* 57: 0100 1100 0101 0111 */
+ {illegal,0 }, /* 58: 0100 1100 0101 1000 */
+ {illegal,0 }, /* 59: 0100 1100 0101 1001 */
+ {illegal,0 }, /* 5a: 0100 1100 0101 1010 */
+ {illegal,0 }, /* 5b: 0100 1100 0101 1011 */
+ {illegal,0 }, /* 5c: 0100 1100 0101 1100 */
+ {illegal,0 }, /* 5d: 0100 1100 0101 1101 */
+ {illegal,0 }, /* 5e: 0100 1100 0101 1110 */
+ {illegal,0 }, /* 5f: 0100 1100 0101 1111 */
+
+ {illegal,0 }, /* 60: 0100 1100 0110 0000 */
+ {illegal,0 }, /* 61: 0100 1100 0110 0001 */
+ {illegal,0 }, /* 62: 0100 1100 0110 0010 */
+ {illegal,0 }, /* 63: 0100 1100 0110 0011 */
+ {illegal,0 }, /* 64: 0100 1100 0110 0100 */
+ {illegal,0 }, /* 65: 0100 1100 0110 0101 */
+ {illegal,0 }, /* 66: 0100 1100 0110 0110 */
+ {illegal,0 }, /* 67: 0100 1100 0110 0111 */
+ {illegal,0 }, /* 68: 0100 1100 0110 1000 */
+ {illegal,0 }, /* 69: 0100 1100 0110 1001 */
+ {illegal,0 }, /* 6a: 0100 1100 0110 1010 */
+ {illegal,0 }, /* 6b: 0100 1100 0110 1011 */
+ {illegal,0 }, /* 6c: 0100 1100 0110 1100 */
+ {illegal,0 }, /* 6d: 0100 1100 0110 1101 */
+ {illegal,0 }, /* 6e: 0100 1100 0110 1110 */
+ {illegal,0 }, /* 6f: 0100 1100 0110 1111 */
+
+ {illegal,0 }, /* 70: 0100 1100 0111 0000 */
+ {illegal,0 }, /* 71: 0100 1100 0111 0001 */
+ {illegal,0 }, /* 72: 0100 1100 0111 0010 */
+ {illegal,0 }, /* 73: 0100 1100 0111 0011 */
+ {illegal,0 }, /* 74: 0100 1100 0111 0100 */
+ {illegal,0 }, /* 75: 0100 1100 0111 0101 */
+ {illegal,0 }, /* 76: 0100 1100 0111 0110 */
+ {illegal,0 }, /* 77: 0100 1100 0111 0111 */
+ {illegal,0 }, /* 78: 0100 1100 0111 1000 */
+ {illegal,0 }, /* 79: 0100 1100 0111 1001 */
+ {illegal,0 }, /* 7a: 0100 1100 0111 1010 */
+ {illegal,0 }, /* 7b: 0100 1100 0111 1011 */
+ {illegal,0 }, /* 7c: 0100 1100 0111 1100 */
+ {illegal,0 }, /* 7d: 0100 1100 0111 1101 */
+ {illegal,0 }, /* 7e: 0100 1100 0111 1110 */
+ {illegal,0 }, /* 7f: 0100 1100 0111 1111 */
+
+ {illegal,0 }, /* 80: 0100 1100 1000 0000 */
+ {illegal,0 }, /* 81: 0100 1100 1000 0001 */
+ {illegal,0 }, /* 82: 0100 1100 1000 0010 */
+ {illegal,0 }, /* 83: 0100 1100 1000 0011 */
+ {illegal,0 }, /* 84: 0100 1100 1000 0100 */
+ {illegal,0 }, /* 85: 0100 1100 1000 0101 */
+ {illegal,0 }, /* 86: 0100 1100 1000 0110 */
+ {illegal,0 }, /* 87: 0100 1100 1000 0111 */
+ {illegal,0 }, /* 88: 0100 1100 1000 1000 */
+ {illegal,0 }, /* 89: 0100 1100 1000 1001 */
+ {illegal,0 }, /* 8a: 0100 1100 1000 1010 */
+ {illegal,0 }, /* 8b: 0100 1100 1000 1011 */
+ {illegal,0 }, /* 8c: 0100 1100 1000 1100 */
+ {illegal,0 }, /* 8d: 0100 1100 1000 1101 */
+ {illegal,0 }, /* 8e: 0100 1100 1000 1110 */
+ {illegal,0 }, /* 8f: 0100 1100 1000 1111 */
+
+ {illegal,0 }, /* 90: 0100 1100 1001 0000 */
+ {illegal,0 }, /* 91: 0100 1100 1001 0001 */
+ {illegal,0 }, /* 92: 0100 1100 1001 0010 */
+ {illegal,0 }, /* 93: 0100 1100 1001 0011 */
+ {illegal,0 }, /* 94: 0100 1100 1001 0100 */
+ {illegal,0 }, /* 95: 0100 1100 1001 0101 */
+ {illegal,0 }, /* 96: 0100 1100 1001 0110 */
+ {illegal,0 }, /* 97: 0100 1100 1001 0111 */
+ {illegal,0 }, /* 98: 0100 1100 1001 1000 */
+ {illegal,0 }, /* 99: 0100 1100 1001 1001 */
+ {illegal,0 }, /* 9a: 0100 1100 1001 1010 */
+ {illegal,0 }, /* 9b: 0100 1100 1001 1011 */
+ {illegal,0 }, /* 9c: 0100 1100 1001 1100 */
+ {illegal,0 }, /* 9d: 0100 1100 1001 1101 */
+ {illegal,0 }, /* 9e: 0100 1100 1001 1110 */
+ {illegal,0 }, /* 9f: 0100 1100 1001 1111 */
+
+ {illegal,0 }, /* a0: 0100 1100 1010 0000 */
+ {illegal,0 }, /* a1: 0100 1100 1010 0001 */
+ {illegal,0 }, /* a2: 0100 1100 1010 0010 */
+ {illegal,0 }, /* a3: 0100 1100 1010 0011 */
+ {illegal,0 }, /* a4: 0100 1100 1010 0100 */
+ {illegal,0 }, /* a5: 0100 1100 1010 0101 */
+ {illegal,0 }, /* a6: 0100 1100 1010 0110 */
+ {illegal,0 }, /* a7: 0100 1100 1010 0111 */
+ {illegal,0 }, /* a8: 0100 1100 1010 1000 */
+ {illegal,0 }, /* a9: 0100 1100 1010 1001 */
+ {illegal,0 }, /* aa: 0100 1100 1010 1010 */
+ {illegal,0 }, /* ab: 0100 1100 1010 1011 */
+ {illegal,0 }, /* ac: 0100 1100 1010 1100 */
+ {illegal,0 }, /* ad: 0100 1100 1010 1101 */
+ {illegal,0 }, /* ae: 0100 1100 1010 1110 */
+ {illegal,0 }, /* af: 0100 1100 1010 1111 */
+
+ {illegal,0 }, /* b0: 0100 1100 1011 0000 */
+ {illegal,0 }, /* b1: 0100 1100 1011 0001 */
+ {illegal,0 }, /* b2: 0100 1100 1011 0010 */
+ {illegal,0 }, /* b3: 0100 1100 1011 0011 */
+ {illegal,0 }, /* b4: 0100 1100 1011 0100 */
+ {illegal,0 }, /* b5: 0100 1100 1011 0101 */
+ {illegal,0 }, /* b6: 0100 1100 1011 0110 */
+ {illegal,0 }, /* b7: 0100 1100 1011 0111 */
+ {illegal,0 }, /* b8: 0100 1100 1011 1000 */
+ {illegal,0 }, /* b9: 0100 1100 1011 1001 */
+ {illegal,0 }, /* ba: 0100 1100 1011 1010 */
+ {illegal,0 }, /* bb: 0100 1100 1011 1011 */
+ {illegal,0 }, /* bc: 0100 1100 1011 1100 */
+ {illegal,0 }, /* bd: 0100 1100 1011 1101 */
+ {illegal,0 }, /* be: 0100 1100 1011 1110 */
+ {illegal,0 }, /* bf: 0100 1100 1011 1111 */
+
+ {MOV,"A,PA" }, /* c0: 0100 1100 1100 0000 */
+ {MOV,"A,PB" }, /* c1: 0100 1100 1100 0001 */
+ {MOV,"A,PC" }, /* c2: 0100 1100 1100 0010 */
+ {MOV,"A,PD" }, /* c3: 0100 1100 1100 0011 */
+ {illegal,0 }, /* c4: 0100 1100 1100 0100 */
+ {MOV,"A,PF" }, /* c5: 0100 1100 1100 0101 */
+ {MOV,"A,MKH" }, /* c6: 0100 1100 1100 0110 */
+ {MOV,"A,MKL" }, /* c7: 0100 1100 1100 0111 */
+ {MOV,"A,ANM" }, /* c8: 0100 1100 1100 1000 */ /* 7810 */
+ {MOV,"A,SMH" }, /* c9: 0100 1100 1100 1001 */
+ {illegal,0 }, /* ca: 0100 1100 1100 1010 */
+ {MOV,"A,EOM" }, /* cb: 0100 1100 1100 1011 */
+ {illegal,0 }, /* cc: 0100 1100 1100 1100 */
+ {MOV,"A,TMM" }, /* cd: 0100 1100 1100 1101 */
+ {illegal,0 }, /* ce: 0100 1100 1100 1110 */
+ {illegal,0 }, /* cf: 0100 1100 1100 1111 */
+
+ {illegal,0 }, /* d0: 0100 1100 1101 0000 */
+ {illegal,0 }, /* d1: 0100 1100 1101 0001 */
+ {illegal,0 }, /* d2: 0100 1100 1101 0010 */
+ {illegal,0 }, /* d3: 0100 1100 1101 0011 */
+ {illegal,0 }, /* d4: 0100 1100 1101 0100 */
+ {illegal,0 }, /* d5: 0100 1100 1101 0101 */
+ {illegal,0 }, /* d6: 0100 1100 1101 0110 */
+ {illegal,0 }, /* d7: 0100 1100 1101 0111 */
+ {illegal,0 }, /* d8: 0100 1100 1101 1000 */
+ {MOV,"A,RXB" }, /* d9: 0100 1100 1101 1001 */
+ {illegal,0 }, /* da: 0100 1100 1101 1010 */
+ {illegal,0 }, /* db: 0100 1100 1101 1011 */
+ {illegal,0 }, /* dc: 0100 1100 1101 1100 */
+ {illegal,0 }, /* dd: 0100 1100 1101 1101 */
+ {illegal,0 }, /* de: 0100 1100 1101 1110 */
+ {illegal,0 }, /* df: 0100 1100 1101 1111 */
+
+ {MOV,"A,CR0" }, /* e0: 0100 1100 1110 0000 */ /* 7810 */
+ {MOV,"A,CR1" }, /* e1: 0100 1100 1110 0001 */ /* 7810 */
+ {MOV,"A,CR2" }, /* e2: 0100 1100 1110 0010 */ /* 7810 */
+ {MOV,"A,CR3" }, /* e3: 0100 1100 1110 0011 */ /* 7810 */
+ {illegal,0 }, /* e4: 0100 1100 1110 0100 */
+ {illegal,0 }, /* e5: 0100 1100 1110 0101 */
+ {illegal,0 }, /* e6: 0100 1100 1110 0110 */
+ {illegal,0 }, /* e7: 0100 1100 1110 0111 */
+ {illegal,0 }, /* e8: 0100 1100 1110 1000 */
+ {illegal,0 }, /* e9: 0100 1100 1110 1001 */
+ {illegal,0 }, /* ea: 0100 1100 1110 1010 */
+ {illegal,0 }, /* eb: 0100 1100 1110 1011 */
+ {illegal,0 }, /* ec: 0100 1100 1110 1100 */
+ {illegal,0 }, /* ed: 0100 1100 1110 1101 */
+ {illegal,0 }, /* ee: 0100 1100 1110 1110 */
+ {illegal,0 }, /* ef: 0100 1100 1110 1111 */
+
+ {illegal,0 }, /* f0: 0100 1100 1111 0000 */
+ {illegal,0 }, /* f1: 0100 1100 1111 0001 */
+ {illegal,0 }, /* f2: 0100 1100 1111 0010 */
+ {illegal,0 }, /* f3: 0100 1100 1111 0011 */
+ {illegal,0 }, /* f4: 0100 1100 1111 0100 */
+ {illegal,0 }, /* f5: 0100 1100 1111 0101 */
+ {illegal,0 }, /* f6: 0100 1100 1111 0110 */
+ {illegal,0 }, /* f7: 0100 1100 1111 0111 */
+ {illegal,0 }, /* f8: 0100 1100 1111 1000 */
+ {illegal,0 }, /* f9: 0100 1100 1111 1001 */
+ {illegal,0 }, /* fa: 0100 1100 1111 1010 */
+ {illegal,0 }, /* fb: 0100 1100 1111 1011 */
+ {illegal,0 }, /* fc: 0100 1100 1111 1100 */
+ {illegal,0 }, /* fd: 0100 1100 1111 1101 */
+ {illegal,0 }, /* fe: 0100 1100 1111 1110 */
+ {illegal,0 } /* ff: 0100 1100 1111 1111 */
+};
+
+static const struct dasm_s dasm4C_7807[256] =
+{
+ {illegal,0 }, /* 00: 0100 1100 0000 0000 */
+ {illegal,0 }, /* 01: 0100 1100 0000 0001 */
+ {illegal,0 }, /* 02: 0100 1100 0000 0010 */
+ {illegal,0 }, /* 03: 0100 1100 0000 0011 */
+ {illegal,0 }, /* 04: 0100 1100 0000 0100 */
+ {illegal,0 }, /* 05: 0100 1100 0000 0101 */
+ {illegal,0 }, /* 06: 0100 1100 0000 0110 */
+ {illegal,0 }, /* 07: 0100 1100 0000 0111 */
+ {illegal,0 }, /* 08: 0100 1100 0000 1000 */
+ {illegal,0 }, /* 09: 0100 1100 0000 1001 */
+ {illegal,0 }, /* 0a: 0100 1100 0000 1010 */
+ {illegal,0 }, /* 0b: 0100 1100 0000 1011 */
+ {illegal,0 }, /* 0c: 0100 1100 0000 1100 */
+ {illegal,0 }, /* 0d: 0100 1100 0000 1101 */
+ {illegal,0 }, /* 0e: 0100 1100 0000 1110 */
+ {illegal,0 }, /* 0f: 0100 1100 0000 1111 */
+
+ {illegal,0 }, /* 10: 0100 1100 0001 0000 */
+ {illegal,0 }, /* 11: 0100 1100 0001 0001 */
+ {illegal,0 }, /* 12: 0100 1100 0001 0010 */
+ {illegal,0 }, /* 13: 0100 1100 0001 0011 */
+ {illegal,0 }, /* 14: 0100 1100 0001 0100 */
+ {illegal,0 }, /* 15: 0100 1100 0001 0101 */
+ {illegal,0 }, /* 16: 0100 1100 0001 0110 */
+ {illegal,0 }, /* 17: 0100 1100 0001 0111 */
+ {illegal,0 }, /* 18: 0100 1100 0001 1000 */
+ {illegal,0 }, /* 19: 0100 1100 0001 1001 */
+ {illegal,0 }, /* 1a: 0100 1100 0001 1010 */
+ {illegal,0 }, /* 1b: 0100 1100 0001 1011 */
+ {illegal,0 }, /* 1c: 0100 1100 0001 1100 */
+ {illegal,0 }, /* 1d: 0100 1100 0001 1101 */
+ {illegal,0 }, /* 1e: 0100 1100 0001 1110 */
+ {illegal,0 }, /* 1f: 0100 1100 0001 1111 */
+
+ {illegal,0 }, /* 20: 0100 1100 0010 0000 */
+ {illegal,0 }, /* 21: 0100 1100 0010 0001 */
+ {illegal,0 }, /* 22: 0100 1100 0010 0010 */
+ {illegal,0 }, /* 23: 0100 1100 0010 0011 */
+ {illegal,0 }, /* 24: 0100 1100 0010 0100 */
+ {illegal,0 }, /* 25: 0100 1100 0010 0101 */
+ {illegal,0 }, /* 26: 0100 1100 0010 0110 */
+ {illegal,0 }, /* 27: 0100 1100 0010 0111 */
+ {illegal,0 }, /* 28: 0100 1100 0010 1000 */
+ {illegal,0 }, /* 29: 0100 1100 0010 1001 */
+ {illegal,0 }, /* 2a: 0100 1100 0010 1010 */
+ {illegal,0 }, /* 2b: 0100 1100 0010 1011 */
+ {illegal,0 }, /* 2c: 0100 1100 0010 1100 */
+ {illegal,0 }, /* 2d: 0100 1100 0010 1101 */
+ {illegal,0 }, /* 2e: 0100 1100 0010 1110 */
+ {illegal,0 }, /* 2f: 0100 1100 0010 1111 */
+
+ {illegal,0 }, /* 30: 0100 1100 0011 0000 */
+ {illegal,0 }, /* 31: 0100 1100 0011 0001 */
+ {illegal,0 }, /* 32: 0100 1100 0011 0010 */
+ {illegal,0 }, /* 33: 0100 1100 0011 0011 */
+ {illegal,0 }, /* 34: 0100 1100 0011 0100 */
+ {illegal,0 }, /* 35: 0100 1100 0011 0101 */
+ {illegal,0 }, /* 36: 0100 1100 0011 0110 */
+ {illegal,0 }, /* 37: 0100 1100 0011 0111 */
+ {illegal,0 }, /* 38: 0100 1100 0011 1000 */
+ {illegal,0 }, /* 39: 0100 1100 0011 1001 */
+ {illegal,0 }, /* 3a: 0100 1100 0011 1010 */
+ {illegal,0 }, /* 3b: 0100 1100 0011 1011 */
+ {illegal,0 }, /* 3c: 0100 1100 0011 1100 */
+ {illegal,0 }, /* 3d: 0100 1100 0011 1101 */
+ {illegal,0 }, /* 3e: 0100 1100 0011 1110 */
+ {illegal,0 }, /* 3f: 0100 1100 0011 1111 */
+
+ {illegal,0 }, /* 40: 0100 1100 0100 0000 */
+ {illegal,0 }, /* 41: 0100 1100 0100 0001 */
+ {illegal,0 }, /* 42: 0100 1100 0100 0010 */
+ {illegal,0 }, /* 43: 0100 1100 0100 0011 */
+ {illegal,0 }, /* 44: 0100 1100 0100 0100 */
+ {illegal,0 }, /* 45: 0100 1100 0100 0101 */
+ {illegal,0 }, /* 46: 0100 1100 0100 0110 */
+ {illegal,0 }, /* 47: 0100 1100 0100 0111 */
+ {illegal,0 }, /* 48: 0100 1100 0100 1000 */
+ {illegal,0 }, /* 49: 0100 1100 0100 1001 */
+ {illegal,0 }, /* 4a: 0100 1100 0100 1010 */
+ {illegal,0 }, /* 4b: 0100 1100 0100 1011 */
+ {illegal,0 }, /* 4c: 0100 1100 0100 1100 */
+ {illegal,0 }, /* 4d: 0100 1100 0100 1101 */
+ {illegal,0 }, /* 4e: 0100 1100 0100 1110 */
+ {illegal,0 }, /* 4f: 0100 1100 0100 1111 */
+
+ {illegal,0 }, /* 50: 0100 1100 0101 0000 */
+ {illegal,0 }, /* 51: 0100 1100 0101 0001 */
+ {illegal,0 }, /* 52: 0100 1100 0101 0010 */
+ {illegal,0 }, /* 53: 0100 1100 0101 0011 */
+ {illegal,0 }, /* 54: 0100 1100 0101 0100 */
+ {illegal,0 }, /* 55: 0100 1100 0101 0101 */
+ {illegal,0 }, /* 56: 0100 1100 0101 0110 */
+ {illegal,0 }, /* 57: 0100 1100 0101 0111 */
+ {illegal,0 }, /* 58: 0100 1100 0101 1000 */
+ {illegal,0 }, /* 59: 0100 1100 0101 1001 */
+ {illegal,0 }, /* 5a: 0100 1100 0101 1010 */
+ {illegal,0 }, /* 5b: 0100 1100 0101 1011 */
+ {illegal,0 }, /* 5c: 0100 1100 0101 1100 */
+ {illegal,0 }, /* 5d: 0100 1100 0101 1101 */
+ {illegal,0 }, /* 5e: 0100 1100 0101 1110 */
+ {illegal,0 }, /* 5f: 0100 1100 0101 1111 */
+
+ {illegal,0 }, /* 60: 0100 1100 0110 0000 */
+ {illegal,0 }, /* 61: 0100 1100 0110 0001 */
+ {illegal,0 }, /* 62: 0100 1100 0110 0010 */
+ {illegal,0 }, /* 63: 0100 1100 0110 0011 */
+ {illegal,0 }, /* 64: 0100 1100 0110 0100 */
+ {illegal,0 }, /* 65: 0100 1100 0110 0101 */
+ {illegal,0 }, /* 66: 0100 1100 0110 0110 */
+ {illegal,0 }, /* 67: 0100 1100 0110 0111 */
+ {illegal,0 }, /* 68: 0100 1100 0110 1000 */
+ {illegal,0 }, /* 69: 0100 1100 0110 1001 */
+ {illegal,0 }, /* 6a: 0100 1100 0110 1010 */
+ {illegal,0 }, /* 6b: 0100 1100 0110 1011 */
+ {illegal,0 }, /* 6c: 0100 1100 0110 1100 */
+ {illegal,0 }, /* 6d: 0100 1100 0110 1101 */
+ {illegal,0 }, /* 6e: 0100 1100 0110 1110 */
+ {illegal,0 }, /* 6f: 0100 1100 0110 1111 */
+
+ {illegal,0 }, /* 70: 0100 1100 0111 0000 */
+ {illegal,0 }, /* 71: 0100 1100 0111 0001 */
+ {illegal,0 }, /* 72: 0100 1100 0111 0010 */
+ {illegal,0 }, /* 73: 0100 1100 0111 0011 */
+ {illegal,0 }, /* 74: 0100 1100 0111 0100 */
+ {illegal,0 }, /* 75: 0100 1100 0111 0101 */
+ {illegal,0 }, /* 76: 0100 1100 0111 0110 */
+ {illegal,0 }, /* 77: 0100 1100 0111 0111 */
+ {illegal,0 }, /* 78: 0100 1100 0111 1000 */
+ {illegal,0 }, /* 79: 0100 1100 0111 1001 */
+ {illegal,0 }, /* 7a: 0100 1100 0111 1010 */
+ {illegal,0 }, /* 7b: 0100 1100 0111 1011 */
+ {illegal,0 }, /* 7c: 0100 1100 0111 1100 */
+ {illegal,0 }, /* 7d: 0100 1100 0111 1101 */
+ {illegal,0 }, /* 7e: 0100 1100 0111 1110 */
+ {illegal,0 }, /* 7f: 0100 1100 0111 1111 */
+
+ {illegal,0 }, /* 80: 0100 1100 1000 0000 */
+ {illegal,0 }, /* 81: 0100 1100 1000 0001 */
+ {illegal,0 }, /* 82: 0100 1100 1000 0010 */
+ {illegal,0 }, /* 83: 0100 1100 1000 0011 */
+ {illegal,0 }, /* 84: 0100 1100 1000 0100 */
+ {illegal,0 }, /* 85: 0100 1100 1000 0101 */
+ {illegal,0 }, /* 86: 0100 1100 1000 0110 */
+ {illegal,0 }, /* 87: 0100 1100 1000 0111 */
+ {illegal,0 }, /* 88: 0100 1100 1000 1000 */
+ {illegal,0 }, /* 89: 0100 1100 1000 1001 */
+ {illegal,0 }, /* 8a: 0100 1100 1000 1010 */
+ {illegal,0 }, /* 8b: 0100 1100 1000 1011 */
+ {illegal,0 }, /* 8c: 0100 1100 1000 1100 */
+ {illegal,0 }, /* 8d: 0100 1100 1000 1101 */
+ {illegal,0 }, /* 8e: 0100 1100 1000 1110 */
+ {illegal,0 }, /* 8f: 0100 1100 1000 1111 */
+
+ {illegal,0 }, /* 90: 0100 1100 1001 0000 */
+ {illegal,0 }, /* 91: 0100 1100 1001 0001 */
+ {illegal,0 }, /* 92: 0100 1100 1001 0010 */
+ {illegal,0 }, /* 93: 0100 1100 1001 0011 */
+ {illegal,0 }, /* 94: 0100 1100 1001 0100 */
+ {illegal,0 }, /* 95: 0100 1100 1001 0101 */
+ {illegal,0 }, /* 96: 0100 1100 1001 0110 */
+ {illegal,0 }, /* 97: 0100 1100 1001 0111 */
+ {illegal,0 }, /* 98: 0100 1100 1001 1000 */
+ {illegal,0 }, /* 99: 0100 1100 1001 1001 */
+ {illegal,0 }, /* 9a: 0100 1100 1001 1010 */
+ {illegal,0 }, /* 9b: 0100 1100 1001 1011 */
+ {illegal,0 }, /* 9c: 0100 1100 1001 1100 */
+ {illegal,0 }, /* 9d: 0100 1100 1001 1101 */
+ {illegal,0 }, /* 9e: 0100 1100 1001 1110 */
+ {illegal,0 }, /* 9f: 0100 1100 1001 1111 */
+
+ {illegal,0 }, /* a0: 0100 1100 1010 0000 */
+ {illegal,0 }, /* a1: 0100 1100 1010 0001 */
+ {illegal,0 }, /* a2: 0100 1100 1010 0010 */
+ {illegal,0 }, /* a3: 0100 1100 1010 0011 */
+ {illegal,0 }, /* a4: 0100 1100 1010 0100 */
+ {illegal,0 }, /* a5: 0100 1100 1010 0101 */
+ {illegal,0 }, /* a6: 0100 1100 1010 0110 */
+ {illegal,0 }, /* a7: 0100 1100 1010 0111 */
+ {illegal,0 }, /* a8: 0100 1100 1010 1000 */
+ {illegal,0 }, /* a9: 0100 1100 1010 1001 */
+ {illegal,0 }, /* aa: 0100 1100 1010 1010 */
+ {illegal,0 }, /* ab: 0100 1100 1010 1011 */
+ {illegal,0 }, /* ac: 0100 1100 1010 1100 */
+ {illegal,0 }, /* ad: 0100 1100 1010 1101 */
+ {illegal,0 }, /* ae: 0100 1100 1010 1110 */
+ {illegal,0 }, /* af: 0100 1100 1010 1111 */
+
+ {illegal,0 }, /* b0: 0100 1100 1011 0000 */
+ {illegal,0 }, /* b1: 0100 1100 1011 0001 */
+ {illegal,0 }, /* b2: 0100 1100 1011 0010 */
+ {illegal,0 }, /* b3: 0100 1100 1011 0011 */
+ {illegal,0 }, /* b4: 0100 1100 1011 0100 */
+ {illegal,0 }, /* b5: 0100 1100 1011 0101 */
+ {illegal,0 }, /* b6: 0100 1100 1011 0110 */
+ {illegal,0 }, /* b7: 0100 1100 1011 0111 */
+ {illegal,0 }, /* b8: 0100 1100 1011 1000 */
+ {illegal,0 }, /* b9: 0100 1100 1011 1001 */
+ {illegal,0 }, /* ba: 0100 1100 1011 1010 */
+ {illegal,0 }, /* bb: 0100 1100 1011 1011 */
+ {illegal,0 }, /* bc: 0100 1100 1011 1100 */
+ {illegal,0 }, /* bd: 0100 1100 1011 1101 */
+ {illegal,0 }, /* be: 0100 1100 1011 1110 */
+ {illegal,0 }, /* bf: 0100 1100 1011 1111 */
+
+ {MOV,"A,PA" }, /* c0: 0100 1100 1100 0000 */
+ {MOV,"A,PB" }, /* c1: 0100 1100 1100 0001 */
+ {MOV,"A,PC" }, /* c2: 0100 1100 1100 0010 */
+ {MOV,"A,PD" }, /* c3: 0100 1100 1100 0011 */
+ {illegal,0 }, /* c4: 0100 1100 1100 0100 */
+ {MOV,"A,PF" }, /* c5: 0100 1100 1100 0101 */
+ {MOV,"A,MKH" }, /* c6: 0100 1100 1100 0110 */
+ {MOV,"A,MKL" }, /* c7: 0100 1100 1100 0111 */
+ {illegal,0 }, /* c8: 0100 1100 1100 1000 */
+ {MOV,"A,SMH" }, /* c9: 0100 1100 1100 1001 */
+ {illegal,0 }, /* ca: 0100 1100 1100 1010 */
+ {MOV,"A,EOM" }, /* cb: 0100 1100 1100 1011 */
+ {illegal,0 }, /* cc: 0100 1100 1100 1100 */
+ {MOV,"A,TMM" }, /* cd: 0100 1100 1100 1101 */
+ {MOV,"A,PT" }, /* ce: 0100 1100 1100 1110 */ /* 7807 */
+ {illegal,0 }, /* cf: 0100 1100 1100 1111 */
+
+ {illegal,0 }, /* d0: 0100 1100 1101 0000 */
+ {illegal,0 }, /* d1: 0100 1100 1101 0001 */
+ {illegal,0 }, /* d2: 0100 1100 1101 0010 */
+ {illegal,0 }, /* d3: 0100 1100 1101 0011 */
+ {illegal,0 }, /* d4: 0100 1100 1101 0100 */
+ {illegal,0 }, /* d5: 0100 1100 1101 0101 */
+ {illegal,0 }, /* d6: 0100 1100 1101 0110 */
+ {illegal,0 }, /* d7: 0100 1100 1101 0111 */
+ {illegal,0 }, /* d8: 0100 1100 1101 1000 */
+ {MOV,"A,RXB" }, /* d9: 0100 1100 1101 1001 */
+ {illegal,0 }, /* da: 0100 1100 1101 1010 */
+ {illegal,0 }, /* db: 0100 1100 1101 1011 */
+ {illegal,0 }, /* dc: 0100 1100 1101 1100 */
+ {illegal,0 }, /* dd: 0100 1100 1101 1101 */
+ {illegal,0 }, /* de: 0100 1100 1101 1110 */
+ {illegal,0 }, /* df: 0100 1100 1101 1111 */
+
+ {illegal,0 }, /* e0: 0100 1100 1110 0000 */
+ {illegal,0 }, /* e1: 0100 1100 1110 0001 */
+ {illegal,0 }, /* e2: 0100 1100 1110 0010 */
+ {illegal,0 }, /* e3: 0100 1100 1110 0011 */
+ {illegal,0 }, /* e4: 0100 1100 1110 0100 */
+ {illegal,0 }, /* e5: 0100 1100 1110 0101 */
+ {illegal,0 }, /* e6: 0100 1100 1110 0110 */
+ {illegal,0 }, /* e7: 0100 1100 1110 0111 */
+ {illegal,0 }, /* e8: 0100 1100 1110 1000 */
+ {illegal,0 }, /* e9: 0100 1100 1110 1001 */
+ {illegal,0 }, /* ea: 0100 1100 1110 1010 */
+ {illegal,0 }, /* eb: 0100 1100 1110 1011 */
+ {illegal,0 }, /* ec: 0100 1100 1110 1100 */
+ {illegal,0 }, /* ed: 0100 1100 1110 1101 */
+ {illegal,0 }, /* ee: 0100 1100 1110 1110 */
+ {illegal,0 }, /* ef: 0100 1100 1110 1111 */
+
+ {illegal,0 }, /* f0: 0100 1100 1111 0000 */
+ {illegal,0 }, /* f1: 0100 1100 1111 0001 */
+ {illegal,0 }, /* f2: 0100 1100 1111 0010 */
+ {illegal,0 }, /* f3: 0100 1100 1111 0011 */
+ {illegal,0 }, /* f4: 0100 1100 1111 0100 */
+ {illegal,0 }, /* f5: 0100 1100 1111 0101 */
+ {illegal,0 }, /* f6: 0100 1100 1111 0110 */
+ {illegal,0 }, /* f7: 0100 1100 1111 0111 */
+ {illegal,0 }, /* f8: 0100 1100 1111 1000 */
+ {illegal,0 }, /* f9: 0100 1100 1111 1001 */
+ {illegal,0 }, /* fa: 0100 1100 1111 1010 */
+ {illegal,0 }, /* fb: 0100 1100 1111 1011 */
+ {illegal,0 }, /* fc: 0100 1100 1111 1100 */
+ {illegal,0 }, /* fd: 0100 1100 1111 1101 */
+ {illegal,0 }, /* fe: 0100 1100 1111 1110 */
+ {illegal,0 } /* ff: 0100 1100 1111 1111 */
+};
+
+/* prefix 4D */
+static const struct dasm_s dasm4D_7810[256] =
+{
+ {illegal,0 }, /* 00: 0100 1101 0000 0000 */
+ {illegal,0 }, /* 01: 0100 1101 0000 0001 */
+ {illegal,0 }, /* 02: 0100 1101 0000 0010 */
+ {illegal,0 }, /* 03: 0100 1101 0000 0011 */
+ {illegal,0 }, /* 04: 0100 1101 0000 0100 */
+ {illegal,0 }, /* 05: 0100 1101 0000 0101 */
+ {illegal,0 }, /* 06: 0100 1101 0000 0110 */
+ {illegal,0 }, /* 07: 0100 1101 0000 0111 */
+ {illegal,0 }, /* 08: 0100 1101 0000 1000 */
+ {illegal,0 }, /* 09: 0100 1101 0000 1001 */
+ {illegal,0 }, /* 0a: 0100 1101 0000 1010 */
+ {illegal,0 }, /* 0b: 0100 1101 0000 1011 */
+ {illegal,0 }, /* 0c: 0100 1101 0000 1100 */
+ {illegal,0 }, /* 0d: 0100 1101 0000 1101 */
+ {illegal,0 }, /* 0e: 0100 1101 0000 1110 */
+ {illegal,0 }, /* 0f: 0100 1101 0000 1111 */
+
+ {illegal,0 }, /* 10: 0100 1101 0001 0000 */
+ {illegal,0 }, /* 11: 0100 1101 0001 0001 */
+ {illegal,0 }, /* 12: 0100 1101 0001 0010 */
+ {illegal,0 }, /* 13: 0100 1101 0001 0011 */
+ {illegal,0 }, /* 14: 0100 1101 0001 0100 */
+ {illegal,0 }, /* 15: 0100 1101 0001 0101 */
+ {illegal,0 }, /* 16: 0100 1101 0001 0110 */
+ {illegal,0 }, /* 17: 0100 1101 0001 0111 */
+ {illegal,0 }, /* 18: 0100 1101 0001 1000 */
+ {illegal,0 }, /* 19: 0100 1101 0001 1001 */
+ {illegal,0 }, /* 1a: 0100 1101 0001 1010 */
+ {illegal,0 }, /* 1b: 0100 1101 0001 1011 */
+ {illegal,0 }, /* 1c: 0100 1101 0001 1100 */
+ {illegal,0 }, /* 1d: 0100 1101 0001 1101 */
+ {illegal,0 }, /* 1e: 0100 1101 0001 1110 */
+ {illegal,0 }, /* 1f: 0100 1101 0001 1111 */
+
+ {illegal,0 }, /* 20: 0100 1101 0010 0000 */
+ {illegal,0 }, /* 21: 0100 1101 0010 0001 */
+ {illegal,0 }, /* 22: 0100 1101 0010 0010 */
+ {illegal,0 }, /* 23: 0100 1101 0010 0011 */
+ {illegal,0 }, /* 24: 0100 1101 0010 0100 */
+ {illegal,0 }, /* 25: 0100 1101 0010 0101 */
+ {illegal,0 }, /* 26: 0100 1101 0010 0110 */
+ {illegal,0 }, /* 27: 0100 1101 0010 0111 */
+ {illegal,0 }, /* 28: 0100 1101 0010 1000 */
+ {illegal,0 }, /* 29: 0100 1101 0010 1001 */
+ {illegal,0 }, /* 2a: 0100 1101 0010 1010 */
+ {illegal,0 }, /* 2b: 0100 1101 0010 1011 */
+ {illegal,0 }, /* 2c: 0100 1101 0010 1100 */
+ {illegal,0 }, /* 2d: 0100 1101 0010 1101 */
+ {illegal,0 }, /* 2e: 0100 1101 0010 1110 */
+ {illegal,0 }, /* 2f: 0100 1101 0010 1111 */
+
+ {illegal,0 }, /* 30: 0100 1101 0011 0000 */
+ {illegal,0 }, /* 31: 0100 1101 0011 0001 */
+ {illegal,0 }, /* 32: 0100 1101 0011 0010 */
+ {illegal,0 }, /* 33: 0100 1101 0011 0011 */
+ {illegal,0 }, /* 34: 0100 1101 0011 0100 */
+ {illegal,0 }, /* 35: 0100 1101 0011 0101 */
+ {illegal,0 }, /* 36: 0100 1101 0011 0110 */
+ {illegal,0 }, /* 37: 0100 1101 0011 0111 */
+ {illegal,0 }, /* 38: 0100 1101 0011 1000 */
+ {illegal,0 }, /* 39: 0100 1101 0011 1001 */
+ {illegal,0 }, /* 3a: 0100 1101 0011 1010 */
+ {illegal,0 }, /* 3b: 0100 1101 0011 1011 */
+ {illegal,0 }, /* 3c: 0100 1101 0011 1100 */
+ {illegal,0 }, /* 3d: 0100 1101 0011 1101 */
+ {illegal,0 }, /* 3e: 0100 1101 0011 1110 */
+ {illegal,0 }, /* 3f: 0100 1101 0011 1111 */
+
+ {illegal,0 }, /* 40: 0100 1101 0100 0000 */
+ {illegal,0 }, /* 41: 0100 1101 0100 0001 */
+ {illegal,0 }, /* 42: 0100 1101 0100 0010 */
+ {illegal,0 }, /* 43: 0100 1101 0100 0011 */
+ {illegal,0 }, /* 44: 0100 1101 0100 0100 */
+ {illegal,0 }, /* 45: 0100 1101 0100 0101 */
+ {illegal,0 }, /* 46: 0100 1101 0100 0110 */
+ {illegal,0 }, /* 47: 0100 1101 0100 0111 */
+ {illegal,0 }, /* 48: 0100 1101 0100 1000 */
+ {illegal,0 }, /* 49: 0100 1101 0100 1001 */
+ {illegal,0 }, /* 4a: 0100 1101 0100 1010 */
+ {illegal,0 }, /* 4b: 0100 1101 0100 1011 */
+ {illegal,0 }, /* 4c: 0100 1101 0100 1100 */
+ {illegal,0 }, /* 4d: 0100 1101 0100 1101 */
+ {illegal,0 }, /* 4e: 0100 1101 0100 1110 */
+ {illegal,0 }, /* 4f: 0100 1101 0100 1111 */
+
+ {illegal,0 }, /* 50: 0100 1101 0101 0000 */
+ {illegal,0 }, /* 51: 0100 1101 0101 0001 */
+ {illegal,0 }, /* 52: 0100 1101 0101 0010 */
+ {illegal,0 }, /* 53: 0100 1101 0101 0011 */
+ {illegal,0 }, /* 54: 0100 1101 0101 0100 */
+ {illegal,0 }, /* 55: 0100 1101 0101 0101 */
+ {illegal,0 }, /* 56: 0100 1101 0101 0110 */
+ {illegal,0 }, /* 57: 0100 1101 0101 0111 */
+ {illegal,0 }, /* 58: 0100 1101 0101 1000 */
+ {illegal,0 }, /* 59: 0100 1101 0101 1001 */
+ {illegal,0 }, /* 5a: 0100 1101 0101 1010 */
+ {illegal,0 }, /* 5b: 0100 1101 0101 1011 */
+ {illegal,0 }, /* 5c: 0100 1101 0101 1100 */
+ {illegal,0 }, /* 5d: 0100 1101 0101 1101 */
+ {illegal,0 }, /* 5e: 0100 1101 0101 1110 */
+ {illegal,0 }, /* 5f: 0100 1101 0101 1111 */
+
+ {illegal,0 }, /* 60: 0100 1101 0110 0000 */
+ {illegal,0 }, /* 61: 0100 1101 0110 0001 */
+ {illegal,0 }, /* 62: 0100 1101 0110 0010 */
+ {illegal,0 }, /* 63: 0100 1101 0110 0011 */
+ {illegal,0 }, /* 64: 0100 1101 0110 0100 */
+ {illegal,0 }, /* 65: 0100 1101 0110 0101 */
+ {illegal,0 }, /* 66: 0100 1101 0110 0110 */
+ {illegal,0 }, /* 67: 0100 1101 0110 0111 */
+ {illegal,0 }, /* 68: 0100 1101 0110 1000 */
+ {illegal,0 }, /* 69: 0100 1101 0110 1001 */
+ {illegal,0 }, /* 6a: 0100 1101 0110 1010 */
+ {illegal,0 }, /* 6b: 0100 1101 0110 1011 */
+ {illegal,0 }, /* 6c: 0100 1101 0110 1100 */
+ {illegal,0 }, /* 6d: 0100 1101 0110 1101 */
+ {illegal,0 }, /* 6e: 0100 1101 0110 1110 */
+ {illegal,0 }, /* 6f: 0100 1101 0110 1111 */
+
+ {illegal,0 }, /* 70: 0100 1101 0111 0000 */
+ {illegal,0 }, /* 71: 0100 1101 0111 0001 */
+ {illegal,0 }, /* 72: 0100 1101 0111 0010 */
+ {illegal,0 }, /* 73: 0100 1101 0111 0011 */
+ {illegal,0 }, /* 74: 0100 1101 0111 0100 */
+ {illegal,0 }, /* 75: 0100 1101 0111 0101 */
+ {illegal,0 }, /* 76: 0100 1101 0111 0110 */
+ {illegal,0 }, /* 77: 0100 1101 0111 0111 */
+ {illegal,0 }, /* 78: 0100 1101 0111 1000 */
+ {illegal,0 }, /* 79: 0100 1101 0111 1001 */
+ {illegal,0 }, /* 7a: 0100 1101 0111 1010 */
+ {illegal,0 }, /* 7b: 0100 1101 0111 1011 */
+ {illegal,0 }, /* 7c: 0100 1101 0111 1100 */
+ {illegal,0 }, /* 7d: 0100 1101 0111 1101 */
+ {illegal,0 }, /* 7e: 0100 1101 0111 1110 */
+ {illegal,0 }, /* 7f: 0100 1101 0111 1111 */
+
+ {illegal,0 }, /* 80: 0100 1101 1000 0000 */
+ {illegal,0 }, /* 81: 0100 1101 1000 0001 */
+ {illegal,0 }, /* 82: 0100 1101 1000 0010 */
+ {illegal,0 }, /* 83: 0100 1101 1000 0011 */
+ {illegal,0 }, /* 84: 0100 1101 1000 0100 */
+ {illegal,0 }, /* 85: 0100 1101 1000 0101 */
+ {illegal,0 }, /* 86: 0100 1101 1000 0110 */
+ {illegal,0 }, /* 87: 0100 1101 1000 0111 */
+ {illegal,0 }, /* 88: 0100 1101 1000 1000 */
+ {illegal,0 }, /* 89: 0100 1101 1000 1001 */
+ {illegal,0 }, /* 8a: 0100 1101 1000 1010 */
+ {illegal,0 }, /* 8b: 0100 1101 1000 1011 */
+ {illegal,0 }, /* 8c: 0100 1101 1000 1100 */
+ {illegal,0 }, /* 8d: 0100 1101 1000 1101 */
+ {illegal,0 }, /* 8e: 0100 1101 1000 1110 */
+ {illegal,0 }, /* 8f: 0100 1101 1000 1111 */
+
+ {illegal,0 }, /* 90: 0100 1101 1001 0000 */
+ {illegal,0 }, /* 91: 0100 1101 1001 0001 */
+ {illegal,0 }, /* 92: 0100 1101 1001 0010 */
+ {illegal,0 }, /* 93: 0100 1101 1001 0011 */
+ {illegal,0 }, /* 94: 0100 1101 1001 0100 */
+ {illegal,0 }, /* 95: 0100 1101 1001 0101 */
+ {illegal,0 }, /* 96: 0100 1101 1001 0110 */
+ {illegal,0 }, /* 97: 0100 1101 1001 0111 */
+ {illegal,0 }, /* 98: 0100 1101 1001 1000 */
+ {illegal,0 }, /* 99: 0100 1101 1001 1001 */
+ {illegal,0 }, /* 9a: 0100 1101 1001 1010 */
+ {illegal,0 }, /* 9b: 0100 1101 1001 1011 */
+ {illegal,0 }, /* 9c: 0100 1101 1001 1100 */
+ {illegal,0 }, /* 9d: 0100 1101 1001 1101 */
+ {illegal,0 }, /* 9e: 0100 1101 1001 1110 */
+ {illegal,0 }, /* 9f: 0100 1101 1001 1111 */
+
+ {illegal,0 }, /* a0: 0100 1101 1010 0000 */
+ {illegal,0 }, /* a1: 0100 1101 1010 0001 */
+ {illegal,0 }, /* a2: 0100 1101 1010 0010 */
+ {illegal,0 }, /* a3: 0100 1101 1010 0011 */
+ {illegal,0 }, /* a4: 0100 1101 1010 0100 */
+ {illegal,0 }, /* a5: 0100 1101 1010 0101 */
+ {illegal,0 }, /* a6: 0100 1101 1010 0110 */
+ {illegal,0 }, /* a7: 0100 1101 1010 0111 */
+ {illegal,0 }, /* a8: 0100 1101 1010 1000 */
+ {illegal,0 }, /* a9: 0100 1101 1010 1001 */
+ {illegal,0 }, /* aa: 0100 1101 1010 1010 */
+ {illegal,0 }, /* ab: 0100 1101 1010 1011 */
+ {illegal,0 }, /* ac: 0100 1101 1010 1100 */
+ {illegal,0 }, /* ad: 0100 1101 1010 1101 */
+ {illegal,0 }, /* ae: 0100 1101 1010 1110 */
+ {illegal,0 }, /* af: 0100 1101 1010 1111 */
+
+ {illegal,0 }, /* b0: 0100 1101 1011 0000 */
+ {illegal,0 }, /* b1: 0100 1101 1011 0001 */
+ {illegal,0 }, /* b2: 0100 1101 1011 0010 */
+ {illegal,0 }, /* b3: 0100 1101 1011 0011 */
+ {illegal,0 }, /* b4: 0100 1101 1011 0100 */
+ {illegal,0 }, /* b5: 0100 1101 1011 0101 */
+ {illegal,0 }, /* b6: 0100 1101 1011 0110 */
+ {illegal,0 }, /* b7: 0100 1101 1011 0111 */
+ {illegal,0 }, /* b8: 0100 1101 1011 1000 */
+ {illegal,0 }, /* b9: 0100 1101 1011 1001 */
+ {illegal,0 }, /* ba: 0100 1101 1011 1010 */
+ {illegal,0 }, /* bb: 0100 1101 1011 1011 */
+ {illegal,0 }, /* bc: 0100 1101 1011 1100 */
+ {illegal,0 }, /* bd: 0100 1101 1011 1101 */
+ {illegal,0 }, /* be: 0100 1101 1011 1110 */
+ {illegal,0 }, /* bf: 0100 1101 1011 1111 */
+
+ {MOV,"PA,A" }, /* c0: 0100 1101 1100 0000 */
+ {MOV,"PB,A" }, /* c1: 0100 1101 1100 0001 */
+ {MOV,"PC,A" }, /* c2: 0100 1101 1100 0010 */
+ {MOV,"PD,A" }, /* c3: 0100 1101 1100 0011 */
+ {illegal,0 }, /* c4: 0100 1101 1100 0100 */
+ {MOV,"PF,A" }, /* c5: 0100 1101 1100 0101 */
+ {MOV,"MKH,A" }, /* c6: 0100 1101 1100 0110 */
+ {MOV,"MKL,A" }, /* c7: 0100 1101 1100 0111 */
+ {MOV,"ANM,A" }, /* c8: 0100 1101 1100 1000 */ /* 7810 */
+ {MOV,"SMH,A" }, /* c9: 0100 1101 1100 1001 */
+ {MOV,"SML,A" }, /* ca: 0100 1101 1100 1010 */
+ {MOV,"EOM,A" }, /* cb: 0100 1101 1100 1011 */
+ {MOV,"ETMM,A" }, /* cc: 0100 1101 1100 1100 */
+ {MOV,"TMM,A" }, /* cd: 0100 1101 1100 1101 */
+ {illegal,0 }, /* ce: 0100 1101 1100 1110 */
+ {illegal,0 }, /* cf: 0100 1101 1100 1111 */
+
+ {MOV,"MM,A" }, /* d0: 0100 1101 1101 0000 */
+ {MOV,"MCC,A" }, /* d1: 0100 1101 1101 0001 */
+ {MOV,"MA,A" }, /* d2: 0100 1101 1101 0010 */
+ {MOV,"MB,A" }, /* d3: 0100 1101 1101 0011 */
+ {MOV,"MC,A" }, /* d4: 0100 1101 1101 0100 */
+ {illegal,0 }, /* d5: 0100 1101 1101 0101 */
+ {illegal,0 }, /* d6: 0100 1101 1101 0110 */
+ {MOV,"MF,A" }, /* d7: 0100 1101 1101 0111 */
+ {MOV,"TXB,A" }, /* d8: 0100 1101 1101 1000 */
+ {illegal,0 }, /* d9: 0100 1101 1101 1001 */
+ {MOV,"TM0,A" }, /* da: 0100 1101 1101 1010 */
+ {MOV,"TM1,A" }, /* db: 0100 1101 1101 1011 */
+ {illegal,0 }, /* dc: 0100 1101 1101 1100 */
+ {illegal,0 }, /* dd: 0100 1101 1101 1101 */
+ {illegal,0 }, /* de: 0100 1101 1101 1110 */
+ {illegal,0 }, /* df: 0100 1101 1101 1111 */
+
+ {illegal,0 }, /* e0: 0100 1101 1110 0000 */
+ {illegal,0 }, /* e1: 0100 1101 1110 0001 */
+ {illegal,0 }, /* e2: 0100 1101 1110 0010 */
+ {illegal,0 }, /* e3: 0100 1101 1110 0011 */
+ {illegal,0 }, /* e4: 0100 1101 1110 0100 */
+ {illegal,0 }, /* e5: 0100 1101 1110 0101 */
+ {illegal,0 }, /* e6: 0100 1101 1110 0110 */
+ {illegal,0 }, /* e7: 0100 1101 1110 0111 */
+ {MOV,"ZCM,A" }, /* e8: 0100 1101 1110 1000 */ /* 7810 */
+ {illegal,0 }, /* e9: 0100 1101 1110 1001 */
+ {illegal,0 }, /* ea: 0100 1101 1110 1010 */
+ {illegal,0 }, /* eb: 0100 1101 1110 1011 */
+ {illegal,0 }, /* ec: 0100 1101 1110 1100 */
+ {illegal,0 }, /* ed: 0100 1101 1110 1101 */
+ {illegal,0 }, /* ee: 0100 1101 1110 1110 */
+ {illegal,0 }, /* ef: 0100 1101 1110 1111 */
+
+ {illegal,0 }, /* f0: 0100 1101 1111 0000 */
+ {illegal,0 }, /* f1: 0100 1101 1111 0001 */
+ {illegal,0 }, /* f2: 0100 1101 1111 0010 */
+ {illegal,0 }, /* f3: 0100 1101 1111 0011 */
+ {illegal,0 }, /* f4: 0100 1101 1111 0100 */
+ {illegal,0 }, /* f5: 0100 1101 1111 0101 */
+ {illegal,0 }, /* f6: 0100 1101 1111 0110 */
+ {illegal,0 }, /* f7: 0100 1101 1111 0111 */
+ {illegal,0 }, /* f8: 0100 1101 1111 1000 */
+ {illegal,0 }, /* f9: 0100 1101 1111 1001 */
+ {illegal,0 }, /* fa: 0100 1101 1111 1010 */
+ {illegal,0 }, /* fb: 0100 1101 1111 1011 */
+ {illegal,0 }, /* fc: 0100 1101 1111 1100 */
+ {illegal,0 }, /* fd: 0100 1101 1111 1101 */
+ {illegal,0 }, /* fe: 0100 1101 1111 1110 */
+ {illegal,0 } /* ff: 0100 1101 1111 1111 */
+};
+
+static const struct dasm_s dasm4D_7807[256] =
+{
+ {illegal,0 }, /* 00: 0100 1101 0000 0000 */
+ {illegal,0 }, /* 01: 0100 1101 0000 0001 */
+ {illegal,0 }, /* 02: 0100 1101 0000 0010 */
+ {illegal,0 }, /* 03: 0100 1101 0000 0011 */
+ {illegal,0 }, /* 04: 0100 1101 0000 0100 */
+ {illegal,0 }, /* 05: 0100 1101 0000 0101 */
+ {illegal,0 }, /* 06: 0100 1101 0000 0110 */
+ {illegal,0 }, /* 07: 0100 1101 0000 0111 */
+ {illegal,0 }, /* 08: 0100 1101 0000 1000 */
+ {illegal,0 }, /* 09: 0100 1101 0000 1001 */
+ {illegal,0 }, /* 0a: 0100 1101 0000 1010 */
+ {illegal,0 }, /* 0b: 0100 1101 0000 1011 */
+ {illegal,0 }, /* 0c: 0100 1101 0000 1100 */
+ {illegal,0 }, /* 0d: 0100 1101 0000 1101 */
+ {illegal,0 }, /* 0e: 0100 1101 0000 1110 */
+ {illegal,0 }, /* 0f: 0100 1101 0000 1111 */
+
+ {illegal,0 }, /* 10: 0100 1101 0001 0000 */
+ {illegal,0 }, /* 11: 0100 1101 0001 0001 */
+ {illegal,0 }, /* 12: 0100 1101 0001 0010 */
+ {illegal,0 }, /* 13: 0100 1101 0001 0011 */
+ {illegal,0 }, /* 14: 0100 1101 0001 0100 */
+ {illegal,0 }, /* 15: 0100 1101 0001 0101 */
+ {illegal,0 }, /* 16: 0100 1101 0001 0110 */
+ {illegal,0 }, /* 17: 0100 1101 0001 0111 */
+ {illegal,0 }, /* 18: 0100 1101 0001 1000 */
+ {illegal,0 }, /* 19: 0100 1101 0001 1001 */
+ {illegal,0 }, /* 1a: 0100 1101 0001 1010 */
+ {illegal,0 }, /* 1b: 0100 1101 0001 1011 */
+ {illegal,0 }, /* 1c: 0100 1101 0001 1100 */
+ {illegal,0 }, /* 1d: 0100 1101 0001 1101 */
+ {illegal,0 }, /* 1e: 0100 1101 0001 1110 */
+ {illegal,0 }, /* 1f: 0100 1101 0001 1111 */
+
+ {illegal,0 }, /* 20: 0100 1101 0010 0000 */
+ {illegal,0 }, /* 21: 0100 1101 0010 0001 */
+ {illegal,0 }, /* 22: 0100 1101 0010 0010 */
+ {illegal,0 }, /* 23: 0100 1101 0010 0011 */
+ {illegal,0 }, /* 24: 0100 1101 0010 0100 */
+ {illegal,0 }, /* 25: 0100 1101 0010 0101 */
+ {illegal,0 }, /* 26: 0100 1101 0010 0110 */
+ {illegal,0 }, /* 27: 0100 1101 0010 0111 */
+ {illegal,0 }, /* 28: 0100 1101 0010 1000 */
+ {illegal,0 }, /* 29: 0100 1101 0010 1001 */
+ {illegal,0 }, /* 2a: 0100 1101 0010 1010 */
+ {illegal,0 }, /* 2b: 0100 1101 0010 1011 */
+ {illegal,0 }, /* 2c: 0100 1101 0010 1100 */
+ {illegal,0 }, /* 2d: 0100 1101 0010 1101 */
+ {illegal,0 }, /* 2e: 0100 1101 0010 1110 */
+ {illegal,0 }, /* 2f: 0100 1101 0010 1111 */
+
+ {illegal,0 }, /* 30: 0100 1101 0011 0000 */
+ {illegal,0 }, /* 31: 0100 1101 0011 0001 */
+ {illegal,0 }, /* 32: 0100 1101 0011 0010 */
+ {illegal,0 }, /* 33: 0100 1101 0011 0011 */
+ {illegal,0 }, /* 34: 0100 1101 0011 0100 */
+ {illegal,0 }, /* 35: 0100 1101 0011 0101 */
+ {illegal,0 }, /* 36: 0100 1101 0011 0110 */
+ {illegal,0 }, /* 37: 0100 1101 0011 0111 */
+ {illegal,0 }, /* 38: 0100 1101 0011 1000 */
+ {illegal,0 }, /* 39: 0100 1101 0011 1001 */
+ {illegal,0 }, /* 3a: 0100 1101 0011 1010 */
+ {illegal,0 }, /* 3b: 0100 1101 0011 1011 */
+ {illegal,0 }, /* 3c: 0100 1101 0011 1100 */
+ {illegal,0 }, /* 3d: 0100 1101 0011 1101 */
+ {illegal,0 }, /* 3e: 0100 1101 0011 1110 */
+ {illegal,0 }, /* 3f: 0100 1101 0011 1111 */
+
+ {illegal,0 }, /* 40: 0100 1101 0100 0000 */
+ {illegal,0 }, /* 41: 0100 1101 0100 0001 */
+ {illegal,0 }, /* 42: 0100 1101 0100 0010 */
+ {illegal,0 }, /* 43: 0100 1101 0100 0011 */
+ {illegal,0 }, /* 44: 0100 1101 0100 0100 */
+ {illegal,0 }, /* 45: 0100 1101 0100 0101 */
+ {illegal,0 }, /* 46: 0100 1101 0100 0110 */
+ {illegal,0 }, /* 47: 0100 1101 0100 0111 */
+ {illegal,0 }, /* 48: 0100 1101 0100 1000 */
+ {illegal,0 }, /* 49: 0100 1101 0100 1001 */
+ {illegal,0 }, /* 4a: 0100 1101 0100 1010 */
+ {illegal,0 }, /* 4b: 0100 1101 0100 1011 */
+ {illegal,0 }, /* 4c: 0100 1101 0100 1100 */
+ {illegal,0 }, /* 4d: 0100 1101 0100 1101 */
+ {illegal,0 }, /* 4e: 0100 1101 0100 1110 */
+ {illegal,0 }, /* 4f: 0100 1101 0100 1111 */
+
+ {illegal,0 }, /* 50: 0100 1101 0101 0000 */
+ {illegal,0 }, /* 51: 0100 1101 0101 0001 */
+ {illegal,0 }, /* 52: 0100 1101 0101 0010 */
+ {illegal,0 }, /* 53: 0100 1101 0101 0011 */
+ {illegal,0 }, /* 54: 0100 1101 0101 0100 */
+ {illegal,0 }, /* 55: 0100 1101 0101 0101 */
+ {illegal,0 }, /* 56: 0100 1101 0101 0110 */
+ {illegal,0 }, /* 57: 0100 1101 0101 0111 */
+ {illegal,0 }, /* 58: 0100 1101 0101 1000 */
+ {illegal,0 }, /* 59: 0100 1101 0101 1001 */
+ {illegal,0 }, /* 5a: 0100 1101 0101 1010 */
+ {illegal,0 }, /* 5b: 0100 1101 0101 1011 */
+ {illegal,0 }, /* 5c: 0100 1101 0101 1100 */
+ {illegal,0 }, /* 5d: 0100 1101 0101 1101 */
+ {illegal,0 }, /* 5e: 0100 1101 0101 1110 */
+ {illegal,0 }, /* 5f: 0100 1101 0101 1111 */
+
+ {illegal,0 }, /* 60: 0100 1101 0110 0000 */
+ {illegal,0 }, /* 61: 0100 1101 0110 0001 */
+ {illegal,0 }, /* 62: 0100 1101 0110 0010 */
+ {illegal,0 }, /* 63: 0100 1101 0110 0011 */
+ {illegal,0 }, /* 64: 0100 1101 0110 0100 */
+ {illegal,0 }, /* 65: 0100 1101 0110 0101 */
+ {illegal,0 }, /* 66: 0100 1101 0110 0110 */
+ {illegal,0 }, /* 67: 0100 1101 0110 0111 */
+ {illegal,0 }, /* 68: 0100 1101 0110 1000 */
+ {illegal,0 }, /* 69: 0100 1101 0110 1001 */
+ {illegal,0 }, /* 6a: 0100 1101 0110 1010 */
+ {illegal,0 }, /* 6b: 0100 1101 0110 1011 */
+ {illegal,0 }, /* 6c: 0100 1101 0110 1100 */
+ {illegal,0 }, /* 6d: 0100 1101 0110 1101 */
+ {illegal,0 }, /* 6e: 0100 1101 0110 1110 */
+ {illegal,0 }, /* 6f: 0100 1101 0110 1111 */
+
+ {illegal,0 }, /* 70: 0100 1101 0111 0000 */
+ {illegal,0 }, /* 71: 0100 1101 0111 0001 */
+ {illegal,0 }, /* 72: 0100 1101 0111 0010 */
+ {illegal,0 }, /* 73: 0100 1101 0111 0011 */
+ {illegal,0 }, /* 74: 0100 1101 0111 0100 */
+ {illegal,0 }, /* 75: 0100 1101 0111 0101 */
+ {illegal,0 }, /* 76: 0100 1101 0111 0110 */
+ {illegal,0 }, /* 77: 0100 1101 0111 0111 */
+ {illegal,0 }, /* 78: 0100 1101 0111 1000 */
+ {illegal,0 }, /* 79: 0100 1101 0111 1001 */
+ {illegal,0 }, /* 7a: 0100 1101 0111 1010 */
+ {illegal,0 }, /* 7b: 0100 1101 0111 1011 */
+ {illegal,0 }, /* 7c: 0100 1101 0111 1100 */
+ {illegal,0 }, /* 7d: 0100 1101 0111 1101 */
+ {illegal,0 }, /* 7e: 0100 1101 0111 1110 */
+ {illegal,0 }, /* 7f: 0100 1101 0111 1111 */
+
+ {illegal,0 }, /* 80: 0100 1101 1000 0000 */
+ {illegal,0 }, /* 81: 0100 1101 1000 0001 */
+ {illegal,0 }, /* 82: 0100 1101 1000 0010 */
+ {illegal,0 }, /* 83: 0100 1101 1000 0011 */
+ {illegal,0 }, /* 84: 0100 1101 1000 0100 */
+ {illegal,0 }, /* 85: 0100 1101 1000 0101 */
+ {illegal,0 }, /* 86: 0100 1101 1000 0110 */
+ {illegal,0 }, /* 87: 0100 1101 1000 0111 */
+ {illegal,0 }, /* 88: 0100 1101 1000 1000 */
+ {illegal,0 }, /* 89: 0100 1101 1000 1001 */
+ {illegal,0 }, /* 8a: 0100 1101 1000 1010 */
+ {illegal,0 }, /* 8b: 0100 1101 1000 1011 */
+ {illegal,0 }, /* 8c: 0100 1101 1000 1100 */
+ {illegal,0 }, /* 8d: 0100 1101 1000 1101 */
+ {illegal,0 }, /* 8e: 0100 1101 1000 1110 */
+ {illegal,0 }, /* 8f: 0100 1101 1000 1111 */
+
+ {illegal,0 }, /* 90: 0100 1101 1001 0000 */
+ {illegal,0 }, /* 91: 0100 1101 1001 0001 */
+ {illegal,0 }, /* 92: 0100 1101 1001 0010 */
+ {illegal,0 }, /* 93: 0100 1101 1001 0011 */
+ {illegal,0 }, /* 94: 0100 1101 1001 0100 */
+ {illegal,0 }, /* 95: 0100 1101 1001 0101 */
+ {illegal,0 }, /* 96: 0100 1101 1001 0110 */
+ {illegal,0 }, /* 97: 0100 1101 1001 0111 */
+ {illegal,0 }, /* 98: 0100 1101 1001 1000 */
+ {illegal,0 }, /* 99: 0100 1101 1001 1001 */
+ {illegal,0 }, /* 9a: 0100 1101 1001 1010 */
+ {illegal,0 }, /* 9b: 0100 1101 1001 1011 */
+ {illegal,0 }, /* 9c: 0100 1101 1001 1100 */
+ {illegal,0 }, /* 9d: 0100 1101 1001 1101 */
+ {illegal,0 }, /* 9e: 0100 1101 1001 1110 */
+ {illegal,0 }, /* 9f: 0100 1101 1001 1111 */
+
+ {illegal,0 }, /* a0: 0100 1101 1010 0000 */
+ {illegal,0 }, /* a1: 0100 1101 1010 0001 */
+ {illegal,0 }, /* a2: 0100 1101 1010 0010 */
+ {illegal,0 }, /* a3: 0100 1101 1010 0011 */
+ {illegal,0 }, /* a4: 0100 1101 1010 0100 */
+ {illegal,0 }, /* a5: 0100 1101 1010 0101 */
+ {illegal,0 }, /* a6: 0100 1101 1010 0110 */
+ {illegal,0 }, /* a7: 0100 1101 1010 0111 */
+ {illegal,0 }, /* a8: 0100 1101 1010 1000 */
+ {illegal,0 }, /* a9: 0100 1101 1010 1001 */
+ {illegal,0 }, /* aa: 0100 1101 1010 1010 */
+ {illegal,0 }, /* ab: 0100 1101 1010 1011 */
+ {illegal,0 }, /* ac: 0100 1101 1010 1100 */
+ {illegal,0 }, /* ad: 0100 1101 1010 1101 */
+ {illegal,0 }, /* ae: 0100 1101 1010 1110 */
+ {illegal,0 }, /* af: 0100 1101 1010 1111 */
+
+ {illegal,0 }, /* b0: 0100 1101 1011 0000 */
+ {illegal,0 }, /* b1: 0100 1101 1011 0001 */
+ {illegal,0 }, /* b2: 0100 1101 1011 0010 */
+ {illegal,0 }, /* b3: 0100 1101 1011 0011 */
+ {illegal,0 }, /* b4: 0100 1101 1011 0100 */
+ {illegal,0 }, /* b5: 0100 1101 1011 0101 */
+ {illegal,0 }, /* b6: 0100 1101 1011 0110 */
+ {illegal,0 }, /* b7: 0100 1101 1011 0111 */
+ {illegal,0 }, /* b8: 0100 1101 1011 1000 */
+ {illegal,0 }, /* b9: 0100 1101 1011 1001 */
+ {illegal,0 }, /* ba: 0100 1101 1011 1010 */
+ {illegal,0 }, /* bb: 0100 1101 1011 1011 */
+ {illegal,0 }, /* bc: 0100 1101 1011 1100 */
+ {illegal,0 }, /* bd: 0100 1101 1011 1101 */
+ {illegal,0 }, /* be: 0100 1101 1011 1110 */
+ {illegal,0 }, /* bf: 0100 1101 1011 1111 */
+
+ {MOV,"PA,A" }, /* c0: 0100 1101 1100 0000 */
+ {MOV,"PB,A" }, /* c1: 0100 1101 1100 0001 */
+ {MOV,"PC,A" }, /* c2: 0100 1101 1100 0010 */
+ {MOV,"PD,A" }, /* c3: 0100 1101 1100 0011 */
+ {illegal,0 }, /* c4: 0100 1101 1100 0100 */
+ {MOV,"PF,A" }, /* c5: 0100 1101 1100 0101 */
+ {MOV,"MKH,A" }, /* c6: 0100 1101 1100 0110 */
+ {MOV,"MKL,A" }, /* c7: 0100 1101 1100 0111 */
+ {illegal,0 }, /* c8: 0100 1101 1100 1000 */
+ {MOV,"SMH,A" }, /* c9: 0100 1101 1100 1001 */
+ {MOV,"SML,A" }, /* ca: 0100 1101 1100 1010 */
+ {MOV,"EOM,A" }, /* cb: 0100 1101 1100 1011 */
+ {MOV,"ETMM,A" }, /* cc: 0100 1101 1100 1100 */
+ {MOV,"TMM,A" }, /* cd: 0100 1101 1100 1101 */
+ {illegal,0 }, /* ce: 0100 1101 1100 1110 */
+ {illegal,0 }, /* cf: 0100 1101 1100 1111 */
+
+ {MOV,"MM,A" }, /* d0: 0100 1101 1101 0000 */
+ {MOV,"MCC,A" }, /* d1: 0100 1101 1101 0001 */
+ {MOV,"MA,A" }, /* d2: 0100 1101 1101 0010 */
+ {MOV,"MB,A" }, /* d3: 0100 1101 1101 0011 */
+ {MOV,"MC,A" }, /* d4: 0100 1101 1101 0100 */
+ {illegal,0 }, /* d5: 0100 1101 1101 0101 */
+ {illegal,0 }, /* d6: 0100 1101 1101 0110 */
+ {MOV,"MF,A" }, /* d7: 0100 1101 1101 0111 */
+ {MOV,"TXB,A" }, /* d8: 0100 1101 1101 1000 */
+ {illegal,0 }, /* d9: 0100 1101 1101 1001 */
+ {MOV,"TM0,A" }, /* da: 0100 1101 1101 1010 */
+ {MOV,"TM1,A" }, /* db: 0100 1101 1101 1011 */
+ {illegal,0 }, /* dc: 0100 1101 1101 1100 */
+ {illegal,0 }, /* dd: 0100 1101 1101 1101 */
+ {illegal,0 }, /* de: 0100 1101 1101 1110 */
+ {illegal,0 }, /* df: 0100 1101 1101 1111 */
+
+ {illegal,0 }, /* e0: 0100 1101 1110 0000 */
+ {illegal,0 }, /* e1: 0100 1101 1110 0001 */
+ {illegal,0 }, /* e2: 0100 1101 1110 0010 */
+ {illegal,0 }, /* e3: 0100 1101 1110 0011 */
+ {illegal,0 }, /* e4: 0100 1101 1110 0100 */
+ {MOV,"MT,A" }, /* e5: 0100 1101 1110 0101 */ /* 7807 */
+ {illegal,0 }, /* e6: 0100 1101 1110 0110 */
+ {illegal,0 }, /* e7: 0100 1101 1110 0111 */
+ {illegal,0 }, /* e8: 0100 1101 1110 1000 */
+ {illegal,0 }, /* e9: 0100 1101 1110 1001 */
+ {illegal,0 }, /* ea: 0100 1101 1110 1010 */
+ {illegal,0 }, /* eb: 0100 1101 1110 1011 */
+ {illegal,0 }, /* ec: 0100 1101 1110 1100 */
+ {illegal,0 }, /* ed: 0100 1101 1110 1101 */
+ {illegal,0 }, /* ee: 0100 1101 1110 1110 */
+ {illegal,0 }, /* ef: 0100 1101 1110 1111 */
+
+ {illegal,0 }, /* f0: 0100 1101 1111 0000 */
+ {illegal,0 }, /* f1: 0100 1101 1111 0001 */
+ {illegal,0 }, /* f2: 0100 1101 1111 0010 */
+ {illegal,0 }, /* f3: 0100 1101 1111 0011 */
+ {illegal,0 }, /* f4: 0100 1101 1111 0100 */
+ {illegal,0 }, /* f5: 0100 1101 1111 0101 */
+ {illegal,0 }, /* f6: 0100 1101 1111 0110 */
+ {illegal,0 }, /* f7: 0100 1101 1111 0111 */
+ {illegal,0 }, /* f8: 0100 1101 1111 1000 */
+ {illegal,0 }, /* f9: 0100 1101 1111 1001 */
+ {illegal,0 }, /* fa: 0100 1101 1111 1010 */
+ {illegal,0 }, /* fb: 0100 1101 1111 1011 */
+ {illegal,0 }, /* fc: 0100 1101 1111 1100 */
+ {illegal,0 }, /* fd: 0100 1101 1111 1101 */
+ {illegal,0 }, /* fe: 0100 1101 1111 1110 */
+ {illegal,0 } /* ff: 0100 1101 1111 1111 */
+};
+
+/* prefix 60 */
+static const struct dasm_s dasm60[256] =
+{
+ {illegal,0 }, /* 00: 0110 0000 0000 0000 */
+ {illegal,0 }, /* 01: 0110 0000 0000 0001 */
+ {illegal,0 }, /* 02: 0110 0000 0000 0010 */
+ {illegal,0 }, /* 03: 0110 0000 0000 0011 */
+ {illegal,0 }, /* 04: 0110 0000 0000 0100 */
+ {illegal,0 }, /* 05: 0110 0000 0000 0101 */
+ {illegal,0 }, /* 06: 0110 0000 0000 0110 */
+ {illegal,0 }, /* 07: 0110 0000 0000 0111 */
+ {ANA,"V,A" }, /* 08: 0110 0000 0000 1000 */
+ {ANA,"A,A" }, /* 09: 0110 0000 0000 1001 */
+ {ANA,"B,A" }, /* 0a: 0110 0000 0000 1010 */
+ {ANA,"C,A" }, /* 0b: 0110 0000 0000 1011 */
+ {ANA,"D,A" }, /* 0c: 0110 0000 0000 1100 */
+ {ANA,"E,A" }, /* 0d: 0110 0000 0000 1101 */
+ {ANA,"H,A" }, /* 0e: 0110 0000 0000 1110 */
+ {ANA,"L,A" }, /* 0f: 0110 0000 0000 1111 */
+
+ {XRA,"V,A" }, /* 10: 0110 0000 0001 0000 */
+ {XRA,"A,A" }, /* 11: 0110 0000 0001 0001 */
+ {XRA,"B,A" }, /* 12: 0110 0000 0001 0010 */
+ {XRA,"C,A" }, /* 13: 0110 0000 0001 0011 */
+ {XRA,"D,A" }, /* 14: 0110 0000 0001 0100 */
+ {XRA,"E,A" }, /* 15: 0110 0000 0001 0101 */
+ {XRA,"H,A" }, /* 16: 0110 0000 0001 0110 */
+ {XRA,"L,A" }, /* 17: 0110 0000 0001 0111 */
+ {ORA,"V,A" }, /* 18: 0110 0000 0001 1000 */
+ {ORA,"A,A" }, /* 19: 0110 0000 0001 1001 */
+ {ORA,"B,A" }, /* 1a: 0110 0000 0001 1010 */
+ {ORA,"C,A" }, /* 1b: 0110 0000 0001 1011 */
+ {ORA,"D,A" }, /* 1c: 0110 0000 0001 1100 */
+ {ORA,"E,A" }, /* 1d: 0110 0000 0001 1101 */
+ {ORA,"H,A" }, /* 1e: 0110 0000 0001 1110 */
+ {ORA,"L,A" }, /* 1f: 0110 0000 0001 1111 */
+
+ {ADDNC,"V,A" }, /* 20: 0110 0000 0010 0000 */
+ {ADDNC,"A,A" }, /* 21: 0110 0000 0010 0001 */
+ {ADDNC,"B,A" }, /* 22: 0110 0000 0010 0010 */
+ {ADDNC,"C,A" }, /* 23: 0110 0000 0010 0011 */
+ {ADDNC,"D,A" }, /* 24: 0110 0000 0010 0100 */
+ {ADDNC,"E,A" }, /* 25: 0110 0000 0010 0101 */
+ {ADDNC,"H,A" }, /* 26: 0110 0000 0010 0110 */
+ {ADDNC,"L,A" }, /* 27: 0110 0000 0010 0111 */
+ {GTA,"V,A" }, /* 28: 0110 0000 0010 1000 */
+ {GTA,"A,A" }, /* 29: 0110 0000 0010 1001 */
+ {GTA,"B,A" }, /* 2a: 0110 0000 0010 1010 */
+ {GTA,"C,A" }, /* 2b: 0110 0000 0010 1011 */
+ {GTA,"D,A" }, /* 2c: 0110 0000 0010 1100 */
+ {GTA,"E,A" }, /* 2d: 0110 0000 0010 1101 */
+ {GTA,"H,A" }, /* 2e: 0110 0000 0010 1110 */
+ {GTA,"L,A" }, /* 2f: 0110 0000 0010 1111 */
+
+ {SUBNB,"V,A" }, /* 30: 0110 0000 0011 0000 */
+ {SUBNB,"A,A" }, /* 31: 0110 0000 0011 0001 */
+ {SUBNB,"B,A" }, /* 32: 0110 0000 0011 0010 */
+ {SUBNB,"C,A" }, /* 33: 0110 0000 0011 0011 */
+ {SUBNB,"D,A" }, /* 34: 0110 0000 0011 0100 */
+ {SUBNB,"E,A" }, /* 35: 0110 0000 0011 0101 */
+ {SUBNB,"H,A" }, /* 36: 0110 0000 0011 0110 */
+ {SUBNB,"L,A" }, /* 37: 0110 0000 0011 0111 */
+ {LTA,"V,A" }, /* 38: 0110 0000 0011 1000 */
+ {LTA,"A,A" }, /* 39: 0110 0000 0011 1001 */
+ {LTA,"B,A" }, /* 3a: 0110 0000 0011 1010 */
+ {LTA,"C,A" }, /* 3b: 0110 0000 0011 1011 */
+ {LTA,"D,A" }, /* 3c: 0110 0000 0011 1100 */
+ {LTA,"E,A" }, /* 3d: 0110 0000 0011 1101 */
+ {LTA,"H,A" }, /* 3e: 0110 0000 0011 1110 */
+ {LTA,"L,A" }, /* 3f: 0110 0000 0011 1111 */
+
+ {ADD,"V,A" }, /* 40: 0110 0000 0100 0000 */
+ {ADD,"A,A" }, /* 41: 0110 0000 0100 0001 */
+ {ADD,"B,A" }, /* 42: 0110 0000 0100 0010 */
+ {ADD,"C,A" }, /* 43: 0110 0000 0100 0011 */
+ {ADD,"D,A" }, /* 44: 0110 0000 0100 0100 */
+ {ADD,"E,A" }, /* 45: 0110 0000 0100 0101 */
+ {ADD,"H,A" }, /* 46: 0110 0000 0100 0110 */
+ {ADD,"L,A" }, /* 47: 0110 0000 0100 0111 */
+ {illegal,0 }, /* 48: 0110 0000 0100 1000 */
+ {illegal,0 }, /* 49: 0110 0000 0100 1001 */
+ {illegal,0 }, /* 4a: 0110 0000 0100 1010 */
+ {illegal,0 }, /* 4b: 0110 0000 0100 1011 */
+ {illegal,0 }, /* 4c: 0110 0000 0100 1100 */
+ {illegal,0 }, /* 4d: 0110 0000 0100 1101 */
+ {illegal,0 }, /* 4e: 0110 0000 0100 1110 */
+ {illegal,0 }, /* 4f: 0110 0000 0100 1111 */
+
+ {ADC,"V,A" }, /* 50: 0110 0000 0101 0000 */
+ {ADC,"A,A" }, /* 51: 0110 0000 0101 0001 */
+ {ADC,"B,A" }, /* 52: 0110 0000 0101 0010 */
+ {ADC,"C,A" }, /* 53: 0110 0000 0101 0011 */
+ {ADC,"D,A" }, /* 54: 0110 0000 0101 0100 */
+ {ADC,"E,A" }, /* 55: 0110 0000 0101 0101 */
+ {ADC,"H,A" }, /* 56: 0110 0000 0101 0110 */
+ {ADC,"L,A" }, /* 57: 0110 0000 0101 0111 */
+ {illegal,0 }, /* 58: 0110 0000 0101 1000 */
+ {illegal,0 }, /* 59: 0110 0000 0101 1001 */
+ {illegal,0 }, /* 5a: 0110 0000 0101 1010 */
+ {illegal,0 }, /* 5b: 0110 0000 0101 1011 */
+ {illegal,0 }, /* 5c: 0110 0000 0101 1100 */
+ {illegal,0 }, /* 5d: 0110 0000 0101 1101 */
+ {illegal,0 }, /* 5e: 0110 0000 0101 1110 */
+ {illegal,0 }, /* 5f: 0110 0000 0101 1111 */
+
+ {SUB,"V,A" }, /* 60: 0110 0000 0110 0000 */
+ {SUB,"A,A" }, /* 61: 0110 0000 0110 0001 */
+ {SUB,"B,A" }, /* 62: 0110 0000 0110 0010 */
+ {SUB,"C,A" }, /* 63: 0110 0000 0110 0011 */
+ {SUB,"D,A" }, /* 64: 0110 0000 0110 0100 */
+ {SUB,"E,A" }, /* 65: 0110 0000 0110 0101 */
+ {SUB,"H,A" }, /* 66: 0110 0000 0110 0110 */
+ {SUB,"L,A" }, /* 67: 0110 0000 0110 0111 */
+ {NEA,"V,A" }, /* 68: 0110 0000 0110 1000 */
+ {NEA,"A,A" }, /* 69: 0110 0000 0110 1001 */
+ {NEA,"B,A" }, /* 6a: 0110 0000 0110 1010 */
+ {NEA,"C,A" }, /* 6b: 0110 0000 0110 1011 */
+ {NEA,"D,A" }, /* 6c: 0110 0000 0110 1100 */
+ {NEA,"E,A" }, /* 6d: 0110 0000 0110 1101 */
+ {NEA,"H,A" }, /* 6e: 0110 0000 0110 1110 */
+ {NEA,"L,A" }, /* 6f: 0110 0000 0110 1111 */
+
+ {SBB,"V,A" }, /* 70: 0110 0000 0111 0000 */
+ {SBB,"A,A" }, /* 71: 0110 0000 0111 0001 */
+ {SBB,"B,A" }, /* 72: 0110 0000 0111 0010 */
+ {SBB,"C,A" }, /* 73: 0110 0000 0111 0011 */
+ {SBB,"D,A" }, /* 74: 0110 0000 0111 0100 */
+ {SBB,"E,A" }, /* 75: 0110 0000 0111 0101 */
+ {SBB,"H,A" }, /* 76: 0110 0000 0111 0110 */
+ {SBB,"L,A" }, /* 77: 0110 0000 0111 0111 */
+ {EQA,"V,A" }, /* 78: 0110 0000 0111 1000 */
+ {EQA,"A,A" }, /* 79: 0110 0000 0111 1001 */
+ {EQA,"B,A" }, /* 7a: 0110 0000 0111 1010 */
+ {EQA,"C,A" }, /* 7b: 0110 0000 0111 1011 */
+ {EQA,"D,A" }, /* 7c: 0110 0000 0111 1100 */
+ {EQA,"E,A" }, /* 7d: 0110 0000 0111 1101 */
+ {EQA,"H,A" }, /* 7e: 0110 0000 0111 1110 */
+ {EQA,"L,A" }, /* 7f: 0110 0000 0111 1111 */
+
+ {illegal,0 }, /* 80: 0110 0000 1000 0000 */
+ {illegal,0 }, /* 81: 0110 0000 1000 0001 */
+ {illegal,0 }, /* 82: 0110 0000 1000 0010 */
+ {illegal,0 }, /* 83: 0110 0000 1000 0011 */
+ {illegal,0 }, /* 84: 0110 0000 1000 0100 */
+ {illegal,0 }, /* 85: 0110 0000 1000 0101 */
+ {illegal,0 }, /* 86: 0110 0000 1000 0110 */
+ {illegal,0 }, /* 87: 0110 0000 1000 0111 */
+ {ANA,"A,V" }, /* 88: 0110 0000 1000 1000 */
+ {ANA,"A,A" }, /* 89: 0110 0000 1000 1001 */
+ {ANA,"A,B" }, /* 8a: 0110 0000 1000 1010 */
+ {ANA,"A,C" }, /* 8b: 0110 0000 1000 1011 */
+ {ANA,"A,D" }, /* 8c: 0110 0000 1000 1100 */
+ {ANA,"A,E" }, /* 8d: 0110 0000 1000 1101 */
+ {ANA,"A,H" }, /* 8e: 0110 0000 1000 1110 */
+ {ANA,"A,L" }, /* 8f: 0110 0000 1000 1111 */
+
+ {XRA,"A,V" }, /* 90: 0110 0000 1001 0000 */
+ {XRA,"A,A" }, /* 91: 0110 0000 1001 0001 */
+ {XRA,"A,B" }, /* 92: 0110 0000 1001 0010 */
+ {XRA,"A,C" }, /* 93: 0110 0000 1001 0011 */
+ {XRA,"A,D" }, /* 94: 0110 0000 1001 0100 */
+ {XRA,"A,E" }, /* 95: 0110 0000 1001 0101 */
+ {XRA,"A,H" }, /* 96: 0110 0000 1001 0110 */
+ {XRA,"A,L" }, /* 97: 0110 0000 1001 0111 */
+ {ORA,"A,V" }, /* 98: 0110 0000 1001 1000 */
+ {ORA,"A,A" }, /* 99: 0110 0000 1001 1001 */
+ {ORA,"A,B" }, /* 9a: 0110 0000 1001 1010 */
+ {ORA,"A,C" }, /* 9b: 0110 0000 1001 1011 */
+ {ORA,"A,D" }, /* 9c: 0110 0000 1001 1100 */
+ {ORA,"A,E" }, /* 9d: 0110 0000 1001 1101 */
+ {ORA,"A,H" }, /* 9e: 0110 0000 1001 1110 */
+ {ORA,"A,L" }, /* 9f: 0110 0000 1001 1111 */
+
+ {ADDNC,"A,V" }, /* a0: 0110 0000 1010 0000 */
+ {ADDNC,"A,A" }, /* a1: 0110 0000 1010 0001 */
+ {ADDNC,"A,B" }, /* a2: 0110 0000 1010 0010 */
+ {ADDNC,"A,C" }, /* a3: 0110 0000 1010 0011 */
+ {ADDNC,"A,D" }, /* a4: 0110 0000 1010 0100 */
+ {ADDNC,"A,E" }, /* a5: 0110 0000 1010 0101 */
+ {ADDNC,"A,H" }, /* a6: 0110 0000 1010 0110 */
+ {ADDNC,"A,L" }, /* a7: 0110 0000 1010 0111 */
+ {GTA,"A,V" }, /* a8: 0110 0000 1010 1000 */
+ {GTA,"A,A" }, /* a9: 0110 0000 1010 1001 */
+ {GTA,"A,B" }, /* aa: 0110 0000 1010 1010 */
+ {GTA,"A,C" }, /* ab: 0110 0000 1010 1011 */
+ {GTA,"A,D" }, /* ac: 0110 0000 1010 1100 */
+ {GTA,"A,E" }, /* ad: 0110 0000 1010 1101 */
+ {GTA,"A,H" }, /* ae: 0110 0000 1010 1110 */
+ {GTA,"A,L" }, /* af: 0110 0000 1010 1111 */
+
+ {SUBNB,"A,V" }, /* b0: 0110 0000 1011 0000 */
+ {SUBNB,"A,A" }, /* b1: 0110 0000 1011 0001 */
+ {SUBNB,"A,B" }, /* b2: 0110 0000 1011 0010 */
+ {SUBNB,"A,C" }, /* b3: 0110 0000 1011 0011 */
+ {SUBNB,"A,D" }, /* b4: 0110 0000 1011 0100 */
+ {SUBNB,"A,E" }, /* b5: 0110 0000 1011 0101 */
+ {SUBNB,"A,H" }, /* b6: 0110 0000 1011 0110 */
+ {SUBNB,"A,L" }, /* b7: 0110 0000 1011 0111 */
+ {LTA,"A,V" }, /* b8: 0110 0000 1011 1000 */
+ {LTA,"A,A" }, /* b9: 0110 0000 1011 1001 */
+ {LTA,"A,B" }, /* ba: 0110 0000 1011 1010 */
+ {LTA,"A,C" }, /* bb: 0110 0000 1011 1011 */
+ {LTA,"A,D" }, /* bc: 0110 0000 1011 1100 */
+ {LTA,"A,E" }, /* bd: 0110 0000 1011 1101 */
+ {LTA,"A,H" }, /* be: 0110 0000 1011 1110 */
+ {LTA,"A,L" }, /* bf: 0110 0000 1011 1111 */
+
+ {ADD,"A,V" }, /* c0: 0110 0000 1100 0000 */
+ {ADD,"A,A" }, /* c1: 0110 0000 1100 0001 */
+ {ADD,"A,B" }, /* c2: 0110 0000 1100 0010 */
+ {ADD,"A,C" }, /* c3: 0110 0000 1100 0011 */
+ {ADD,"A,D" }, /* c4: 0110 0000 1100 0100 */
+ {ADD,"A,E" }, /* c5: 0110 0000 1100 0101 */
+ {ADD,"A,H" }, /* c6: 0110 0000 1100 0110 */
+ {ADD,"A,L" }, /* c7: 0110 0000 1100 0111 */
+ {ONA,"A,V" }, /* c8: 0110 0000 1100 1000 */
+ {ONA,"A,A" }, /* c9: 0110 0000 1100 1001 */
+ {ONA,"A,B" }, /* ca: 0110 0000 1100 1010 */
+ {ONA,"A,C" }, /* cb: 0110 0000 1100 1011 */
+ {ONA,"A,D" }, /* cc: 0110 0000 1100 1100 */
+ {ONA,"A,E" }, /* cd: 0110 0000 1100 1101 */
+ {ONA,"A,H" }, /* ce: 0110 0000 1100 1110 */
+ {ONA,"A,L" }, /* cf: 0110 0000 1100 1111 */
+
+ {ADC,"A,V" }, /* d0: 0110 0000 1101 0000 */
+ {ADC,"A,A" }, /* d1: 0110 0000 1101 0001 */
+ {ADC,"A,B" }, /* d2: 0110 0000 1101 0010 */
+ {ADC,"A,C" }, /* d3: 0110 0000 1101 0011 */
+ {ADC,"A,D" }, /* d4: 0110 0000 1101 0100 */
+ {ADC,"A,E" }, /* d5: 0110 0000 1101 0101 */
+ {ADC,"A,H" }, /* d6: 0110 0000 1101 0110 */
+ {ADC,"A,L" }, /* d7: 0110 0000 1101 0111 */
+ {OFFA,"A,V" }, /* d8: 0110 0000 1101 1000 */
+ {OFFA,"A,A" }, /* d9: 0110 0000 1101 1001 */
+ {OFFA,"A,B" }, /* da: 0110 0000 1101 1010 */
+ {OFFA,"A,C" }, /* db: 0110 0000 1101 1011 */
+ {OFFA,"A,D" }, /* dc: 0110 0000 1101 1100 */
+ {OFFA,"A,E" }, /* dd: 0110 0000 1101 1101 */
+ {OFFA,"A,H" }, /* de: 0110 0000 1101 1110 */
+ {OFFA,"A,L" }, /* df: 0110 0000 1101 1111 */
+
+ {SUB,"A,V" }, /* e0: 0110 0000 1110 0000 */
+ {SUB,"A,A" }, /* e1: 0110 0000 1110 0001 */
+ {SUB,"A,B" }, /* e2: 0110 0000 1110 0010 */
+ {SUB,"A,C" }, /* e3: 0110 0000 1110 0011 */
+ {SUB,"A,D" }, /* e4: 0110 0000 1110 0100 */
+ {SUB,"A,E" }, /* e5: 0110 0000 1110 0101 */
+ {SUB,"A,H" }, /* e6: 0110 0000 1110 0110 */
+ {SUB,"A,L" }, /* e7: 0110 0000 1110 0111 */
+ {NEA,"A,V" }, /* e8: 0110 0000 1110 1000 */
+ {NEA,"A,A" }, /* e9: 0110 0000 1110 1001 */
+ {NEA,"A,B" }, /* ea: 0110 0000 1110 1010 */
+ {NEA,"A,C" }, /* eb: 0110 0000 1110 1011 */
+ {NEA,"A,D" }, /* ec: 0110 0000 1110 1100 */
+ {NEA,"A,E" }, /* ed: 0110 0000 1110 1101 */
+ {NEA,"A,H" }, /* ee: 0110 0000 1110 1110 */
+ {NEA,"A,L" }, /* ef: 0110 0000 1110 1111 */
+
+ {SBB,"A,V" }, /* f0: 0110 0000 1111 0000 */
+ {SBB,"A,A" }, /* f1: 0110 0000 1111 0001 */
+ {SBB,"A,B" }, /* f2: 0110 0000 1111 0010 */
+ {SBB,"A,C" }, /* f3: 0110 0000 1111 0011 */
+ {SBB,"A,D" }, /* f4: 0110 0000 1111 0100 */
+ {SBB,"A,E" }, /* f5: 0110 0000 1111 0101 */
+ {SBB,"A,H" }, /* f6: 0110 0000 1111 0110 */
+ {SBB,"A,L" }, /* f7: 0110 0000 1111 0111 */
+ {EQA,"A,V" }, /* f8: 0110 0000 1111 1000 */
+ {EQA,"A,A" }, /* f9: 0110 0000 1111 1001 */
+ {EQA,"A,B" }, /* fa: 0110 0000 1111 1010 */
+ {EQA,"A,C" }, /* fb: 0110 0000 1111 1011 */
+ {EQA,"A,D" }, /* fc: 0110 0000 1111 1100 */
+ {EQA,"A,E" }, /* fd: 0110 0000 1111 1101 */
+ {EQA,"A,H" }, /* fe: 0110 0000 1111 1110 */
+ {EQA,"A,L" } /* ff: 0110 0000 1111 1111 */
+};
+
+/* prefix 64 */
+static const struct dasm_s dasm64_7810[256] =
+{
+ {MVI,"PA,%b" }, /* 00: 0110 0100 0000 0000 xxxx xxxx */
+ {MVI,"PB,%b" }, /* 01: 0110 0100 0000 0001 xxxx xxxx */
+ {MVI,"PC,%b" }, /* 02: 0110 0100 0000 0010 xxxx xxxx */
+ {MVI,"PD,%b" }, /* 03: 0110 0100 0000 0011 xxxx xxxx */
+ {illegal,0 }, /* 04: 0110 0100 0000 0100 xxxx xxxx */
+ {MVI,"PF,%b" }, /* 05: 0110 0100 0000 0101 xxxx xxxx */
+ {MVI,"MKH,%b" }, /* 06: 0110 0100 0000 0110 xxxx xxxx */
+ {MVI,"MKL,%b" }, /* 07: 0110 0100 0000 0111 xxxx xxxx */
+ {ANI,"PA,%b" }, /* 08: 0110 0100 0000 1000 xxxx xxxx */
+ {ANI,"PB,%b" }, /* 09: 0110 0100 0000 1001 xxxx xxxx */
+ {ANI,"PC,%b" }, /* 0a: 0110 0100 0000 1010 xxxx xxxx */
+ {ANI,"PD,%b" }, /* 0b: 0110 0100 0000 1011 xxxx xxxx */
+ {illegal,0 }, /* 0c: 0110 0100 0000 1100 xxxx xxxx */
+ {ANI,"PF,%b" }, /* 0d: 0110 0100 0000 1101 xxxx xxxx */
+ {ANI,"MKH,%b" }, /* 0e: 0110 0100 0000 1110 xxxx xxxx */
+ {ANI,"MKL,%b" }, /* 0f: 0110 0100 0000 1111 xxxx xxxx */
+
+ {XRI,"PA,%b" }, /* 10: 0110 0100 0001 0000 xxxx xxxx */
+ {XRI,"PB,%b" }, /* 11: 0110 0100 0001 0001 xxxx xxxx */
+ {XRI,"PC,%b" }, /* 12: 0110 0100 0001 0010 xxxx xxxx */
+ {XRI,"PD,%b" }, /* 13: 0110 0100 0001 0011 xxxx xxxx */
+ {illegal,0 }, /* 14: 0110 0100 0001 0100 xxxx xxxx */
+ {XRI,"PF,%b" }, /* 15: 0110 0100 0001 0101 xxxx xxxx */
+ {XRI,"MKH,%b" }, /* 16: 0110 0100 0001 0110 xxxx xxxx */
+ {XRI,"MKL,%b" }, /* 17: 0110 0100 0001 0111 xxxx xxxx */
+ {ORI,"PA,%b" }, /* 18: 0110 0100 0001 1000 xxxx xxxx */
+ {ORI,"PB,%b" }, /* 19: 0110 0100 0001 1001 xxxx xxxx */
+ {ORI,"PC,%b" }, /* 1a: 0110 0100 0001 1010 xxxx xxxx */
+ {ORI,"PD,%b" }, /* 1b: 0110 0100 0001 1011 xxxx xxxx */
+ {illegal,0 }, /* 1c: 0110 0100 0001 1100 xxxx xxxx */
+ {ORI,"PF,%b" }, /* 1d: 0110 0100 0001 1101 xxxx xxxx */
+ {ORI,"MKH,%b" }, /* 1e: 0110 0100 0001 1110 xxxx xxxx */
+ {ORI,"MKL,%b" }, /* 1f: 0110 0100 0001 1111 xxxx xxxx */
+
+ {ADINC,"PA,%b" }, /* 20: 0110 0100 0010 0000 xxxx xxxx */
+ {ADINC,"PB,%b" }, /* 21: 0110 0100 0010 0001 xxxx xxxx */
+ {ADINC,"PC,%b" }, /* 22: 0110 0100 0010 0010 xxxx xxxx */
+ {ADINC,"PD,%b" }, /* 23: 0110 0100 0010 0011 xxxx xxxx */
+ {illegal,0 }, /* 24: 0110 0100 0010 0100 xxxx xxxx */
+ {ADINC,"PF,%b" }, /* 25: 0110 0100 0010 0101 xxxx xxxx */
+ {ADINC,"MKH,%b" }, /* 26: 0110 0100 0010 0110 xxxx xxxx */
+ {ADINC,"MKL,%b" }, /* 27: 0110 0100 0010 0111 xxxx xxxx */
+ {GTI,"PA,%b" }, /* 28: 0110 0100 0010 1000 xxxx xxxx */
+ {GTI,"PB,%b" }, /* 29: 0110 0100 0010 1001 xxxx xxxx */
+ {GTI,"PC,%b" }, /* 2a: 0110 0100 0010 1010 xxxx xxxx */
+ {GTI,"PD,%b" }, /* 2b: 0110 0100 0010 1011 xxxx xxxx */
+ {illegal,0 }, /* 2c: 0110 0100 0010 1100 xxxx xxxx */
+ {GTI,"PF,%b" }, /* 2d: 0110 0100 0010 1101 xxxx xxxx */
+ {GTI,"MKH,%b" }, /* 2e: 0110 0100 0010 1110 xxxx xxxx */
+ {GTI,"MKL,%b" }, /* 2f: 0110 0100 0010 1111 xxxx xxxx */
+
+ {SUINB,"PA,%b" }, /* 30: 0110 0100 0011 0000 xxxx xxxx */
+ {SUINB,"PB,%b" }, /* 31: 0110 0100 0011 0001 xxxx xxxx */
+ {SUINB,"PC,%b" }, /* 32: 0110 0100 0011 0010 xxxx xxxx */
+ {SUINB,"PD,%b" }, /* 33: 0110 0100 0011 0011 xxxx xxxx */
+ {illegal,0 }, /* 34: 0110 0100 0011 0100 xxxx xxxx */
+ {SUINB,"PF,%b" }, /* 35: 0110 0100 0011 0101 xxxx xxxx */
+ {SUINB,"MKH,%b" }, /* 36: 0110 0100 0011 0110 xxxx xxxx */
+ {SUINB,"MKL,%b" }, /* 37: 0110 0100 0011 0111 xxxx xxxx */
+ {LTI,"PA,%b" }, /* 38: 0110 0100 0011 1000 xxxx xxxx */
+ {LTI,"PB,%b" }, /* 39: 0110 0100 0011 1001 xxxx xxxx */
+ {LTI,"PC,%b" }, /* 3a: 0110 0100 0011 1010 xxxx xxxx */
+ {LTI,"PD,%b" }, /* 3b: 0110 0100 0011 1011 xxxx xxxx */
+ {illegal,0 }, /* 3c: 0110 0100 0011 1100 xxxx xxxx */
+ {LTI,"PF,%b" }, /* 3d: 0110 0100 0011 1101 xxxx xxxx */
+ {LTI,"MKH,%b" }, /* 3e: 0110 0100 0011 1110 xxxx xxxx */
+ {LTI,"MKL,%b" }, /* 3f: 0110 0100 0011 1111 xxxx xxxx */
+
+ {ADI,"PA,%b" }, /* 40: 0110 0100 0100 0000 xxxx xxxx */
+ {ADI,"PB,%b" }, /* 41: 0110 0100 0100 0001 xxxx xxxx */
+ {ADI,"PC,%b" }, /* 42: 0110 0100 0100 0010 xxxx xxxx */
+ {ADI,"PD,%b" }, /* 43: 0110 0100 0100 0011 xxxx xxxx */
+ {illegal,0 }, /* 44: 0110 0100 0100 0100 xxxx xxxx */
+ {ADI,"PF,%b" }, /* 45: 0110 0100 0100 0101 xxxx xxxx */
+ {ADI,"MKH,%b" }, /* 46: 0110 0100 0100 0110 xxxx xxxx */
+ {ADI,"MKL,%b" }, /* 47: 0110 0100 0100 0111 xxxx xxxx */
+ {ONI,"PA,%b" }, /* 48: 0110 0100 0100 1000 xxxx xxxx */
+ {ONI,"PB,%b" }, /* 49: 0110 0100 0100 1001 xxxx xxxx */
+ {ONI,"PC,%b" }, /* 4a: 0110 0100 0100 1010 xxxx xxxx */
+ {ONI,"PD,%b" }, /* 4b: 0110 0100 0100 1011 xxxx xxxx */
+ {illegal,0 }, /* 4c: 0110 0100 0100 1100 xxxx xxxx */
+ {ONI,"PF,%b" }, /* 4d: 0110 0100 0100 1101 xxxx xxxx */
+ {ONI,"MKH,%b" }, /* 4e: 0110 0100 0100 1110 xxxx xxxx */
+ {ONI,"MKL,%b" }, /* 4f: 0110 0100 0100 1111 xxxx xxxx */
+
+ {ACI,"PA,%b" }, /* 50: 0110 0100 0101 0000 xxxx xxxx */
+ {ACI,"PB,%b" }, /* 51: 0110 0100 0101 0001 xxxx xxxx */
+ {ACI,"PC,%b" }, /* 52: 0110 0100 0101 0010 xxxx xxxx */
+ {ACI,"PD,%b" }, /* 53: 0110 0100 0101 0011 xxxx xxxx */
+ {illegal,0 }, /* 54: 0110 0100 0101 0100 xxxx xxxx */
+ {ACI,"PF,%b" }, /* 55: 0110 0100 0101 0101 xxxx xxxx */
+ {ACI,"MKH,%b" }, /* 56: 0110 0100 0101 0110 xxxx xxxx */
+ {ACI,"MKL,%b" }, /* 57: 0110 0100 0101 0111 xxxx xxxx */
+ {OFFI,"PA,%b" }, /* 58: 0110 0100 0101 1000 xxxx xxxx */
+ {OFFI,"PB,%b" }, /* 59: 0110 0100 0101 1001 xxxx xxxx */
+ {OFFI,"PC,%b" }, /* 5a: 0110 0100 0101 1010 xxxx xxxx */
+ {OFFI,"PD,%b" }, /* 5b: 0110 0100 0101 1011 xxxx xxxx */
+ {illegal,0 }, /* 5c: 0110 0100 0101 1100 xxxx xxxx */
+ {OFFI,"PF,%b" }, /* 5d: 0110 0100 0101 1101 xxxx xxxx */
+ {OFFI,"MKH,%b" }, /* 5e: 0110 0100 0101 1110 xxxx xxxx */
+ {OFFI,"MKL,%b" }, /* 5f: 0110 0100 0101 1111 xxxx xxxx */
+
+ {SUI,"PA,%b" }, /* 60: 0110 0100 0110 0000 xxxx xxxx */
+ {SUI,"PB,%b" }, /* 61: 0110 0100 0110 0001 xxxx xxxx */
+ {SUI,"PC,%b" }, /* 62: 0110 0100 0110 0010 xxxx xxxx */
+ {SUI,"PD,%b" }, /* 63: 0110 0100 0110 0011 xxxx xxxx */
+ {illegal,0 }, /* 64: 0110 0100 0110 0100 xxxx xxxx */
+ {SUI,"PF,%b" }, /* 65: 0110 0100 0110 0101 xxxx xxxx */
+ {SUI,"MKH,%b" }, /* 66: 0110 0100 0110 0110 xxxx xxxx */
+ {SUI,"MKL,%b" }, /* 67: 0110 0100 0110 0111 xxxx xxxx */
+ {NEI,"PA,%b" }, /* 68: 0110 0100 0110 1000 xxxx xxxx */
+ {NEI,"PB,%b" }, /* 69: 0110 0100 0110 1001 xxxx xxxx */
+ {NEI,"PC,%b" }, /* 6a: 0110 0100 0110 1010 xxxx xxxx */
+ {NEI,"PD,%b" }, /* 6b: 0110 0100 0110 1011 xxxx xxxx */
+ {illegal,0 }, /* 6c: 0110 0100 0110 1100 xxxx xxxx */
+ {NEI,"PF,%b" }, /* 6d: 0110 0100 0110 1101 xxxx xxxx */
+ {NEI,"MKH,%b" }, /* 6e: 0110 0100 0110 1110 xxxx xxxx */
+ {NEI,"MKL,%b" }, /* 6f: 0110 0100 0110 1111 xxxx xxxx */
+
+ {SBI,"PA,%b" }, /* 70: 0110 0100 0111 0000 xxxx xxxx */
+ {SBI,"PB,%b" }, /* 71: 0110 0100 0111 0001 xxxx xxxx */
+ {SBI,"PC,%b" }, /* 72: 0110 0100 0111 0010 xxxx xxxx */
+ {SBI,"PD,%b" }, /* 73: 0110 0100 0111 0011 xxxx xxxx */
+ {illegal,0 }, /* 74: 0110 0100 0111 0100 xxxx xxxx */
+ {SBI,"PF,%b" }, /* 75: 0110 0100 0111 0101 xxxx xxxx */
+ {SBI,"MKH,%b" }, /* 76: 0110 0100 0111 0110 xxxx xxxx */
+ {SBI,"MKL,%b" }, /* 77: 0110 0100 0111 0111 xxxx xxxx */
+ {EQI,"PA,%b" }, /* 78: 0110 0100 0111 1000 xxxx xxxx */
+ {EQI,"PB,%b" }, /* 79: 0110 0100 0111 1001 xxxx xxxx */
+ {EQI,"PC,%b" }, /* 7a: 0110 0100 0111 1010 xxxx xxxx */
+ {EQI,"PD,%b" }, /* 7b: 0110 0100 0111 1011 xxxx xxxx */
+ {illegal,0 }, /* 7c: 0110 0100 0111 1100 xxxx xxxx */
+ {EQI,"PF,%b" }, /* 7d: 0110 0100 0111 1101 xxxx xxxx */
+ {EQI,"MKH,%b" }, /* 7e: 0110 0100 0111 1110 xxxx xxxx */
+ {EQI,"MKL,%b" }, /* 7f: 0110 0100 0111 1111 xxxx xxxx */
+
+ {MVI,"ANM,%b" }, /* 80: 0110 0100 1000 0000 xxxx xxxx */ /* 7810 */
+ {MVI,"SMH,%b" }, /* 81: 0110 0100 1000 0001 xxxx xxxx */
+ {illegal,0 }, /* 82: 0110 0100 1000 0010 xxxx xxxx */
+ {MVI,"EOM,%b" }, /* 83: 0110 0100 1000 0011 xxxx xxxx */
+ {illegal,0 }, /* 84: 0110 0100 1000 0100 xxxx xxxx */
+ {MVI,"TMM,%b" }, /* 85: 0110 0100 1000 0101 xxxx xxxx */
+ {illegal,0 }, /* 86: 0110 0100 1000 0110 xxxx xxxx */
+ {illegal,0 }, /* 87: 0110 0100 1000 0111 xxxx xxxx */
+ {ANI,"ANM,%b" }, /* 88: 0110 0100 1000 1000 xxxx xxxx */ /* 7810 */
+ {ANI,"SMH,%b" }, /* 89: 0110 0100 1000 1001 xxxx xxxx */
+ {illegal,0 }, /* 8a: 0110 0100 1000 1010 xxxx xxxx */
+ {ANI,"EOM,%b" }, /* 8b: 0110 0100 1000 1011 xxxx xxxx */
+ {illegal,0 }, /* 8c: 0110 0100 1000 1100 xxxx xxxx */
+ {ANI,"TMM,%b" }, /* 8d: 0110 0100 1000 1101 xxxx xxxx */
+ {illegal,0 }, /* 8e: 0110 0100 1000 1110 xxxx xxxx */
+ {illegal,0 }, /* 8f: 0110 0100 1000 1111 xxxx xxxx */
+
+ {XRI,"ANM,%b" }, /* 90: 0110 0100 1001 0000 xxxx xxxx */ /* 7810 */
+ {XRI,"SMH,%b" }, /* 91: 0110 0100 1001 0001 xxxx xxxx */
+ {illegal,0 }, /* 92: 0110 0100 1001 0010 xxxx xxxx */
+ {XRI,"EOM,%b" }, /* 93: 0110 0100 1001 0011 xxxx xxxx */
+ {illegal,0 }, /* 94: 0110 0100 1001 0100 xxxx xxxx */
+ {XRI,"TMM,%b" }, /* 95: 0110 0100 1001 0101 xxxx xxxx */
+ {illegal,0 }, /* 96: 0110 0100 1001 0110 xxxx xxxx */
+ {illegal,0 }, /* 97: 0110 0100 1001 0111 xxxx xxxx */
+ {ORI,"ANM,%b" }, /* 98: 0110 0100 1001 1000 xxxx xxxx */ /* 7810 */
+ {ORI,"SMH,%b" }, /* 99: 0110 0100 1001 1001 xxxx xxxx */
+ {illegal,0 }, /* 9a: 0110 0100 1001 1010 xxxx xxxx */
+ {ORI,"EOM,%b" }, /* 9b: 0110 0100 1001 1011 xxxx xxxx */
+ {illegal,0 }, /* 9c: 0110 0100 1001 1100 xxxx xxxx */
+ {ORI,"TMM,%b" }, /* 9d: 0110 0100 1001 1101 xxxx xxxx */
+ {illegal,0 }, /* 9e: 0110 0100 1001 1110 xxxx xxxx */
+ {illegal,0 }, /* 9f: 0110 0100 1001 1111 xxxx xxxx */
+
+ {ADINC,"ANM,%b" }, /* a0: 0110 0100 1010 0000 xxxx xxxx */ /* 7810 */
+ {ADINC,"SMH,%b" }, /* a1: 0110 0100 1010 0001 xxxx xxxx */
+ {illegal,0 }, /* a2: 0110 0100 1010 0010 xxxx xxxx */
+ {ADINC,"EOM,%b" }, /* a3: 0110 0100 1010 0011 xxxx xxxx */
+ {illegal,0 }, /* a4: 0110 0100 1010 0100 xxxx xxxx */
+ {ADINC,"TMM,%b" }, /* a5: 0110 0100 1010 0101 xxxx xxxx */
+ {illegal,0 }, /* a6: 0110 0100 1010 0110 xxxx xxxx */
+ {illegal,0 }, /* a7: 0110 0100 1010 0111 xxxx xxxx */
+ {GTI,"ANM,%b" }, /* a8: 0110 0100 1010 1000 xxxx xxxx */ /* 7810 */
+ {GTI,"SMH,%b" }, /* a9: 0110 0100 1010 1001 xxxx xxxx */
+ {illegal,0 }, /* aa: 0110 0100 1010 1010 xxxx xxxx */
+ {GTI,"EOM,%b" }, /* ab: 0110 0100 1010 1011 xxxx xxxx */
+ {illegal,0 }, /* ac: 0110 0100 1010 1100 xxxx xxxx */
+ {GTI,"TMM,%b" }, /* ad: 0110 0100 1010 1101 xxxx xxxx */
+ {illegal,0 }, /* ae: 0110 0100 1010 1110 xxxx xxxx */
+ {illegal,0 }, /* af: 0110 0100 1010 1111 xxxx xxxx */
+
+ {SUINB,"ANM,%b" }, /* b0: 0110 0100 1011 0000 xxxx xxxx */ /* 7810 */
+ {SUINB,"SMH,%b" }, /* b1: 0110 0100 1011 0001 xxxx xxxx */
+ {illegal,0 }, /* b2: 0110 0100 1011 0010 xxxx xxxx */
+ {SUINB,"EOM,%b" }, /* b3: 0110 0100 1011 0011 xxxx xxxx */
+ {illegal,0 }, /* b4: 0110 0100 1011 0100 xxxx xxxx */
+ {SUINB,"TMM,%b" }, /* b5: 0110 0100 1011 0101 xxxx xxxx */
+ {illegal,0 }, /* b6: 0110 0100 1011 0110 xxxx xxxx */
+ {illegal,0 }, /* b7: 0110 0100 1011 0111 xxxx xxxx */
+ {LTI,"ANM,%b" }, /* b8: 0110 0100 1011 1000 xxxx xxxx */ /* 7810 */
+ {LTI,"SMH,%b" }, /* b9: 0110 0100 1011 1001 xxxx xxxx */
+ {illegal,0 }, /* ba: 0110 0100 1011 1010 xxxx xxxx */
+ {LTI,"EOM,%b" }, /* bb: 0110 0100 1011 1011 xxxx xxxx */
+ {illegal,0 }, /* bc: 0110 0100 1011 1100 xxxx xxxx */
+ {LTI,"TMM,%b" }, /* bd: 0110 0100 1011 1101 xxxx xxxx */
+ {illegal,0 }, /* be: 0110 0100 1011 1110 xxxx xxxx */
+ {illegal,0 }, /* bf: 0110 0100 1011 1111 xxxx xxxx */
+
+ {ADI,"ANM,%b" }, /* c0: 0110 0100 1100 0000 xxxx xxxx */ /* 7810 */
+ {ADI,"SMH,%b" }, /* c1: 0110 0100 1100 0001 xxxx xxxx */
+ {illegal,0 }, /* c2: 0110 0100 1100 0010 xxxx xxxx */
+ {ADI,"EOM,%b" }, /* c3: 0110 0100 1100 0011 xxxx xxxx */
+ {illegal,0 }, /* c4: 0110 0100 1100 0100 xxxx xxxx */
+ {ADI,"TMM,%b" }, /* c5: 0110 0100 1100 0101 xxxx xxxx */
+ {illegal,0 }, /* c6: 0110 0100 1100 0110 xxxx xxxx */
+ {illegal,0 }, /* c7: 0110 0100 1100 0111 xxxx xxxx */
+ {ONI,"ANM,%b" }, /* c8: 0110 0100 1100 1000 xxxx xxxx */ /* 7810 */
+ {ONI,"SMH,%b" }, /* c9: 0110 0100 1100 1001 xxxx xxxx */
+ {illegal,0 }, /* ca: 0110 0100 1100 1010 xxxx xxxx */
+ {ONI,"EOM,%b" }, /* cb: 0110 0100 1100 1011 xxxx xxxx */
+ {illegal,0 }, /* cc: 0110 0100 1100 1100 xxxx xxxx */
+ {ONI,"TMM,%b" }, /* cd: 0110 0100 1100 1101 xxxx xxxx */
+ {illegal,0 }, /* ce: 0110 0100 1100 1110 xxxx xxxx */
+ {illegal,0 }, /* cf: 0110 0100 1100 1111 xxxx xxxx */
+
+ {ACI,"ANM,%b" }, /* d0: 0110 0100 1101 0000 xxxx xxxx */ /* 7810 */
+ {ACI,"SMH,%b" }, /* d1: 0110 0100 1101 0001 xxxx xxxx */
+ {illegal,0 }, /* d2: 0110 0100 1101 0010 xxxx xxxx */
+ {ACI,"EOM,%b" }, /* d3: 0110 0100 1101 0011 xxxx xxxx */
+ {illegal,0 }, /* d4: 0110 0100 1101 0100 xxxx xxxx */
+ {ACI,"TMM,%b" }, /* d5: 0110 0100 1101 0101 xxxx xxxx */
+ {illegal,0 }, /* d6: 0110 0100 1101 0110 xxxx xxxx */
+ {illegal,0 }, /* d7: 0110 0100 1101 0111 xxxx xxxx */
+ {OFFI,"ANM,%b" }, /* d8: 0110 0100 1101 1000 xxxx xxxx */ /* 7810 */
+ {OFFI,"SMH,%b" }, /* d9: 0110 0100 1101 1001 xxxx xxxx */
+ {illegal,0 }, /* da: 0110 0100 1101 1010 xxxx xxxx */
+ {OFFI,"EOM,%b" }, /* db: 0110 0100 1101 1011 xxxx xxxx */
+ {illegal,0 }, /* dc: 0110 0100 1101 1100 xxxx xxxx */
+ {OFFI,"TMM,%b" }, /* dd: 0110 0100 1101 1101 xxxx xxxx */
+ {illegal,0 }, /* de: 0110 0100 1101 1110 xxxx xxxx */
+ {illegal,0 }, /* df: 0110 0100 1101 1111 xxxx xxxx */
+
+ {SUI,"ANM,%b" }, /* e0: 0110 0100 1110 0000 xxxx xxxx */ /* 7810 */
+ {SUI,"SMH,%b" }, /* e1: 0110 0100 1110 0001 xxxx xxxx */
+ {illegal,0 }, /* e2: 0110 0100 1110 0010 xxxx xxxx */
+ {SUI,"EOM,%b" }, /* e3: 0110 0100 1110 0011 xxxx xxxx */
+ {illegal,0 }, /* e4: 0110 0100 1110 0100 xxxx xxxx */
+ {SUI,"TMM,%b" }, /* e5: 0110 0100 1110 0101 xxxx xxxx */
+ {illegal,0 }, /* e6: 0110 0100 1110 0110 xxxx xxxx */
+ {illegal,0 }, /* e7: 0110 0100 1110 0111 xxxx xxxx */
+ {NEI,"ANM,%b" }, /* e8: 0110 0100 1110 1000 xxxx xxxx */ /* 7810 */
+ {NEI,"SMH,%b" }, /* e9: 0110 0100 1110 1001 xxxx xxxx */
+ {illegal,0 }, /* ea: 0110 0100 1110 1010 xxxx xxxx */
+ {NEI,"EOM,%b" }, /* eb: 0110 0100 1110 1011 xxxx xxxx */
+ {illegal,0 }, /* ec: 0110 0100 1110 1100 xxxx xxxx */
+ {NEI,"TMM,%b" }, /* ed: 0110 0100 1110 1101 xxxx xxxx */
+ {illegal,0 }, /* ee: 0110 0100 1110 1110 xxxx xxxx */
+ {illegal,0 }, /* ef: 0110 0100 1110 1111 xxxx xxxx */
+
+ {SBI,"ANM,%b" }, /* f0: 0110 0100 1111 0000 xxxx xxxx */ /* 7810 */
+ {SBI,"SMH,%b" }, /* f1: 0110 0100 1111 0001 xxxx xxxx */
+ {illegal,0 }, /* f2: 0110 0100 1111 0010 xxxx xxxx */
+ {SBI,"EOM,%b" }, /* f3: 0110 0100 1111 0011 xxxx xxxx */
+ {illegal,0 }, /* f4: 0110 0100 1111 0100 xxxx xxxx */
+ {SBI,"TMM,%b" }, /* f5: 0110 0100 1111 0101 xxxx xxxx */
+ {illegal,0 }, /* f6: 0110 0100 1111 0110 xxxx xxxx */
+ {illegal,0 }, /* f7: 0110 0100 1111 0111 xxxx xxxx */
+ {EQI,"ANM,%b" }, /* f8: 0110 0100 1111 1000 xxxx xxxx */ /* 7810 */
+ {EQI,"SMH,%b" }, /* f9: 0110 0100 1111 1001 xxxx xxxx */
+ {illegal,0 }, /* fa: 0110 0100 1111 1010 xxxx xxxx */
+ {EQI,"EOM,%b" }, /* fb: 0110 0100 1111 1011 xxxx xxxx */
+ {illegal,0 }, /* fc: 0110 0100 1111 1100 xxxx xxxx */
+ {EQI,"TMM,%b" }, /* fd: 0110 0100 1111 1101 xxxx xxxx */
+ {illegal,0 }, /* fe: 0110 0100 1111 1110 xxxx xxxx */
+ {illegal,0 } /* ff: 0110 0100 1111 1111 xxxx xxxx */
+};
+
+static const struct dasm_s dasm64_7807[256] =
+{
+ {MVI,"PA,%b" }, /* 00: 0110 0100 0000 0000 xxxx xxxx */
+ {MVI,"PB,%b" }, /* 01: 0110 0100 0000 0001 xxxx xxxx */
+ {MVI,"PC,%b" }, /* 02: 0110 0100 0000 0010 xxxx xxxx */
+ {MVI,"PD,%b" }, /* 03: 0110 0100 0000 0011 xxxx xxxx */
+ {illegal,0 }, /* 04: 0110 0100 0000 0100 xxxx xxxx */
+ {MVI,"PF,%b" }, /* 05: 0110 0100 0000 0101 xxxx xxxx */
+ {MVI,"MKH,%b" }, /* 06: 0110 0100 0000 0110 xxxx xxxx */
+ {MVI,"MKL,%b" }, /* 07: 0110 0100 0000 0111 xxxx xxxx */
+ {ANI,"PA,%b" }, /* 08: 0110 0100 0000 1000 xxxx xxxx */
+ {ANI,"PB,%b" }, /* 09: 0110 0100 0000 1001 xxxx xxxx */
+ {ANI,"PC,%b" }, /* 0a: 0110 0100 0000 1010 xxxx xxxx */
+ {ANI,"PD,%b" }, /* 0b: 0110 0100 0000 1011 xxxx xxxx */
+ {illegal,0 }, /* 0c: 0110 0100 0000 1100 xxxx xxxx */
+ {ANI,"PF,%b" }, /* 0d: 0110 0100 0000 1101 xxxx xxxx */
+ {ANI,"MKH,%b" }, /* 0e: 0110 0100 0000 1110 xxxx xxxx */
+ {ANI,"MKL,%b" }, /* 0f: 0110 0100 0000 1111 xxxx xxxx */
+
+ {XRI,"PA,%b" }, /* 10: 0110 0100 0001 0000 xxxx xxxx */
+ {XRI,"PB,%b" }, /* 11: 0110 0100 0001 0001 xxxx xxxx */
+ {XRI,"PC,%b" }, /* 12: 0110 0100 0001 0010 xxxx xxxx */
+ {XRI,"PD,%b" }, /* 13: 0110 0100 0001 0011 xxxx xxxx */
+ {illegal,0 }, /* 14: 0110 0100 0001 0100 xxxx xxxx */
+ {XRI,"PF,%b" }, /* 15: 0110 0100 0001 0101 xxxx xxxx */
+ {XRI,"MKH,%b" }, /* 16: 0110 0100 0001 0110 xxxx xxxx */
+ {XRI,"MKL,%b" }, /* 17: 0110 0100 0001 0111 xxxx xxxx */
+ {ORI,"PA,%b" }, /* 18: 0110 0100 0001 1000 xxxx xxxx */
+ {ORI,"PB,%b" }, /* 19: 0110 0100 0001 1001 xxxx xxxx */
+ {ORI,"PC,%b" }, /* 1a: 0110 0100 0001 1010 xxxx xxxx */
+ {ORI,"PD,%b" }, /* 1b: 0110 0100 0001 1011 xxxx xxxx */
+ {illegal,0 }, /* 1c: 0110 0100 0001 1100 xxxx xxxx */
+ {ORI,"PF,%b" }, /* 1d: 0110 0100 0001 1101 xxxx xxxx */
+ {ORI,"MKH,%b" }, /* 1e: 0110 0100 0001 1110 xxxx xxxx */
+ {ORI,"MKL,%b" }, /* 1f: 0110 0100 0001 1111 xxxx xxxx */
+
+ {ADINC,"PA,%b" }, /* 20: 0110 0100 0010 0000 xxxx xxxx */
+ {ADINC,"PB,%b" }, /* 21: 0110 0100 0010 0001 xxxx xxxx */
+ {ADINC,"PC,%b" }, /* 22: 0110 0100 0010 0010 xxxx xxxx */
+ {ADINC,"PD,%b" }, /* 23: 0110 0100 0010 0011 xxxx xxxx */
+ {illegal,0 }, /* 24: 0110 0100 0010 0100 xxxx xxxx */
+ {ADINC,"PF,%b" }, /* 25: 0110 0100 0010 0101 xxxx xxxx */
+ {ADINC,"MKH,%b" }, /* 26: 0110 0100 0010 0110 xxxx xxxx */
+ {ADINC,"MKL,%b" }, /* 27: 0110 0100 0010 0111 xxxx xxxx */
+ {GTI,"PA,%b" }, /* 28: 0110 0100 0010 1000 xxxx xxxx */
+ {GTI,"PB,%b" }, /* 29: 0110 0100 0010 1001 xxxx xxxx */
+ {GTI,"PC,%b" }, /* 2a: 0110 0100 0010 1010 xxxx xxxx */
+ {GTI,"PD,%b" }, /* 2b: 0110 0100 0010 1011 xxxx xxxx */
+ {illegal,0 }, /* 2c: 0110 0100 0010 1100 xxxx xxxx */
+ {GTI,"PF,%b" }, /* 2d: 0110 0100 0010 1101 xxxx xxxx */
+ {GTI,"MKH,%b" }, /* 2e: 0110 0100 0010 1110 xxxx xxxx */
+ {GTI,"MKL,%b" }, /* 2f: 0110 0100 0010 1111 xxxx xxxx */
+
+ {SUINB,"PA,%b" }, /* 30: 0110 0100 0011 0000 xxxx xxxx */
+ {SUINB,"PB,%b" }, /* 31: 0110 0100 0011 0001 xxxx xxxx */
+ {SUINB,"PC,%b" }, /* 32: 0110 0100 0011 0010 xxxx xxxx */
+ {SUINB,"PD,%b" }, /* 33: 0110 0100 0011 0011 xxxx xxxx */
+ {illegal,0 }, /* 34: 0110 0100 0011 0100 xxxx xxxx */
+ {SUINB,"PF,%b" }, /* 35: 0110 0100 0011 0101 xxxx xxxx */
+ {SUINB,"MKH,%b" }, /* 36: 0110 0100 0011 0110 xxxx xxxx */
+ {SUINB,"MKL,%b" }, /* 37: 0110 0100 0011 0111 xxxx xxxx */
+ {LTI,"PA,%b" }, /* 38: 0110 0100 0011 1000 xxxx xxxx */
+ {LTI,"PB,%b" }, /* 39: 0110 0100 0011 1001 xxxx xxxx */
+ {LTI,"PC,%b" }, /* 3a: 0110 0100 0011 1010 xxxx xxxx */
+ {LTI,"PD,%b" }, /* 3b: 0110 0100 0011 1011 xxxx xxxx */
+ {illegal,0 }, /* 3c: 0110 0100 0011 1100 xxxx xxxx */
+ {LTI,"PF,%b" }, /* 3d: 0110 0100 0011 1101 xxxx xxxx */
+ {LTI,"MKH,%b" }, /* 3e: 0110 0100 0011 1110 xxxx xxxx */
+ {LTI,"MKL,%b" }, /* 3f: 0110 0100 0011 1111 xxxx xxxx */
+
+ {ADI,"PA,%b" }, /* 40: 0110 0100 0100 0000 xxxx xxxx */
+ {ADI,"PB,%b" }, /* 41: 0110 0100 0100 0001 xxxx xxxx */
+ {ADI,"PC,%b" }, /* 42: 0110 0100 0100 0010 xxxx xxxx */
+ {ADI,"PD,%b" }, /* 43: 0110 0100 0100 0011 xxxx xxxx */
+ {illegal,0 }, /* 44: 0110 0100 0100 0100 xxxx xxxx */
+ {ADI,"PF,%b" }, /* 45: 0110 0100 0100 0101 xxxx xxxx */
+ {ADI,"MKH,%b" }, /* 46: 0110 0100 0100 0110 xxxx xxxx */
+ {ADI,"MKL,%b" }, /* 47: 0110 0100 0100 0111 xxxx xxxx */
+ {ONI,"PA,%b" }, /* 48: 0110 0100 0100 1000 xxxx xxxx */
+ {ONI,"PB,%b" }, /* 49: 0110 0100 0100 1001 xxxx xxxx */
+ {ONI,"PC,%b" }, /* 4a: 0110 0100 0100 1010 xxxx xxxx */
+ {ONI,"PD,%b" }, /* 4b: 0110 0100 0100 1011 xxxx xxxx */
+ {illegal,0 }, /* 4c: 0110 0100 0100 1100 xxxx xxxx */
+ {ONI,"PF,%b" }, /* 4d: 0110 0100 0100 1101 xxxx xxxx */
+ {ONI,"MKH,%b" }, /* 4e: 0110 0100 0100 1110 xxxx xxxx */
+ {ONI,"MKL,%b" }, /* 4f: 0110 0100 0100 1111 xxxx xxxx */
+
+ {ACI,"PA,%b" }, /* 50: 0110 0100 0101 0000 xxxx xxxx */
+ {ACI,"PB,%b" }, /* 51: 0110 0100 0101 0001 xxxx xxxx */
+ {ACI,"PC,%b" }, /* 52: 0110 0100 0101 0010 xxxx xxxx */
+ {ACI,"PD,%b" }, /* 53: 0110 0100 0101 0011 xxxx xxxx */
+ {illegal,0 }, /* 54: 0110 0100 0101 0100 xxxx xxxx */
+ {ACI,"PF,%b" }, /* 55: 0110 0100 0101 0101 xxxx xxxx */
+ {ACI,"MKH,%b" }, /* 56: 0110 0100 0101 0110 xxxx xxxx */
+ {ACI,"MKL,%b" }, /* 57: 0110 0100 0101 0111 xxxx xxxx */
+ {OFFI,"PA,%b" }, /* 58: 0110 0100 0101 1000 xxxx xxxx */
+ {OFFI,"PB,%b" }, /* 59: 0110 0100 0101 1001 xxxx xxxx */
+ {OFFI,"PC,%b" }, /* 5a: 0110 0100 0101 1010 xxxx xxxx */
+ {OFFI,"PD,%b" }, /* 5b: 0110 0100 0101 1011 xxxx xxxx */
+ {illegal,0 }, /* 5c: 0110 0100 0101 1100 xxxx xxxx */
+ {OFFI,"PF,%b" }, /* 5d: 0110 0100 0101 1101 xxxx xxxx */
+ {OFFI,"MKH,%b" }, /* 5e: 0110 0100 0101 1110 xxxx xxxx */
+ {OFFI,"MKL,%b" }, /* 5f: 0110 0100 0101 1111 xxxx xxxx */
+
+ {SUI,"PA,%b" }, /* 60: 0110 0100 0110 0000 xxxx xxxx */
+ {SUI,"PB,%b" }, /* 61: 0110 0100 0110 0001 xxxx xxxx */
+ {SUI,"PC,%b" }, /* 62: 0110 0100 0110 0010 xxxx xxxx */
+ {SUI,"PD,%b" }, /* 63: 0110 0100 0110 0011 xxxx xxxx */
+ {illegal,0 }, /* 64: 0110 0100 0110 0100 xxxx xxxx */
+ {SUI,"PF,%b" }, /* 65: 0110 0100 0110 0101 xxxx xxxx */
+ {SUI,"MKH,%b" }, /* 66: 0110 0100 0110 0110 xxxx xxxx */
+ {SUI,"MKL,%b" }, /* 67: 0110 0100 0110 0111 xxxx xxxx */
+ {NEI,"PA,%b" }, /* 68: 0110 0100 0110 1000 xxxx xxxx */
+ {NEI,"PB,%b" }, /* 69: 0110 0100 0110 1001 xxxx xxxx */
+ {NEI,"PC,%b" }, /* 6a: 0110 0100 0110 1010 xxxx xxxx */
+ {NEI,"PD,%b" }, /* 6b: 0110 0100 0110 1011 xxxx xxxx */
+ {illegal,0 }, /* 6c: 0110 0100 0110 1100 xxxx xxxx */
+ {NEI,"PF,%b" }, /* 6d: 0110 0100 0110 1101 xxxx xxxx */
+ {NEI,"MKH,%b" }, /* 6e: 0110 0100 0110 1110 xxxx xxxx */
+ {NEI,"MKL,%b" }, /* 6f: 0110 0100 0110 1111 xxxx xxxx */
+
+ {SBI,"PA,%b" }, /* 70: 0110 0100 0111 0000 xxxx xxxx */
+ {SBI,"PB,%b" }, /* 71: 0110 0100 0111 0001 xxxx xxxx */
+ {SBI,"PC,%b" }, /* 72: 0110 0100 0111 0010 xxxx xxxx */
+ {SBI,"PD,%b" }, /* 73: 0110 0100 0111 0011 xxxx xxxx */
+ {illegal,0 }, /* 74: 0110 0100 0111 0100 xxxx xxxx */
+ {SBI,"PF,%b" }, /* 75: 0110 0100 0111 0101 xxxx xxxx */
+ {SBI,"MKH,%b" }, /* 76: 0110 0100 0111 0110 xxxx xxxx */
+ {SBI,"MKL,%b" }, /* 77: 0110 0100 0111 0111 xxxx xxxx */
+ {EQI,"PA,%b" }, /* 78: 0110 0100 0111 1000 xxxx xxxx */
+ {EQI,"PB,%b" }, /* 79: 0110 0100 0111 1001 xxxx xxxx */
+ {EQI,"PC,%b" }, /* 7a: 0110 0100 0111 1010 xxxx xxxx */
+ {EQI,"PD,%b" }, /* 7b: 0110 0100 0111 1011 xxxx xxxx */
+ {illegal,0 }, /* 7c: 0110 0100 0111 1100 xxxx xxxx */
+ {EQI,"PF,%b" }, /* 7d: 0110 0100 0111 1101 xxxx xxxx */
+ {EQI,"MKH,%b" }, /* 7e: 0110 0100 0111 1110 xxxx xxxx */
+ {EQI,"MKL,%b" }, /* 7f: 0110 0100 0111 1111 xxxx xxxx */
+
+ {illegal,0 }, /* 80: 0110 0100 1000 0000 xxxx xxxx */
+ {MVI,"SMH,%b" }, /* 81: 0110 0100 1000 0001 xxxx xxxx */
+ {illegal,0 }, /* 82: 0110 0100 1000 0010 xxxx xxxx */
+ {MVI,"EOM,%b" }, /* 83: 0110 0100 1000 0011 xxxx xxxx */
+ {illegal,0 }, /* 84: 0110 0100 1000 0100 xxxx xxxx */
+ {MVI,"TMM,%b" }, /* 85: 0110 0100 1000 0101 xxxx xxxx */
+ {illegal,0 }, /* 86: 0110 0100 1000 0110 xxxx xxxx */
+ {illegal,0 }, /* 87: 0110 0100 1000 0111 xxxx xxxx */
+ {illegal,0 }, /* 88: 0110 0100 1000 1000 xxxx xxxx */
+ {ANI,"SMH,%b" }, /* 89: 0110 0100 1000 1001 xxxx xxxx */
+ {illegal,0 }, /* 8a: 0110 0100 1000 1010 xxxx xxxx */
+ {ANI,"EOM,%b" }, /* 8b: 0110 0100 1000 1011 xxxx xxxx */
+ {illegal,0 }, /* 8c: 0110 0100 1000 1100 xxxx xxxx */
+ {ANI,"TMM,%b" }, /* 8d: 0110 0100 1000 1101 xxxx xxxx */
+ {illegal,0 }, /* 8e: 0110 0100 1000 1110 xxxx xxxx */
+ {illegal,0 }, /* 8f: 0110 0100 1000 1111 xxxx xxxx */
+
+ {illegal,0 }, /* 90: 0110 0100 1001 0000 xxxx xxxx */
+ {XRI,"SMH,%b" }, /* 91: 0110 0100 1001 0001 xxxx xxxx */
+ {illegal,0 }, /* 92: 0110 0100 1001 0010 xxxx xxxx */
+ {XRI,"EOM,%b" }, /* 93: 0110 0100 1001 0011 xxxx xxxx */
+ {illegal,0 }, /* 94: 0110 0100 1001 0100 xxxx xxxx */
+ {XRI,"TMM,%b" }, /* 95: 0110 0100 1001 0101 xxxx xxxx */
+ {illegal,0 }, /* 96: 0110 0100 1001 0110 xxxx xxxx */
+ {illegal,0 }, /* 97: 0110 0100 1001 0111 xxxx xxxx */
+ {illegal,0 }, /* 98: 0110 0100 1001 1000 xxxx xxxx */
+ {ORI,"SMH,%b" }, /* 99: 0110 0100 1001 1001 xxxx xxxx */
+ {illegal,0 }, /* 9a: 0110 0100 1001 1010 xxxx xxxx */
+ {ORI,"EOM,%b" }, /* 9b: 0110 0100 1001 1011 xxxx xxxx */
+ {illegal,0 }, /* 9c: 0110 0100 1001 1100 xxxx xxxx */
+ {ORI,"TMM,%b" }, /* 9d: 0110 0100 1001 1101 xxxx xxxx */
+ {illegal,0 }, /* 9e: 0110 0100 1001 1110 xxxx xxxx */
+ {illegal,0 }, /* 9f: 0110 0100 1001 1111 xxxx xxxx */
+
+ {illegal,0 }, /* a0: 0110 0100 1010 0000 xxxx xxxx */
+ {ADINC,"SMH,%b" }, /* a1: 0110 0100 1010 0001 xxxx xxxx */
+ {illegal,0 }, /* a2: 0110 0100 1010 0010 xxxx xxxx */
+ {ADINC,"EOM,%b" }, /* a3: 0110 0100 1010 0011 xxxx xxxx */
+ {illegal,0 }, /* a4: 0110 0100 1010 0100 xxxx xxxx */
+ {ADINC,"TMM,%b" }, /* a5: 0110 0100 1010 0101 xxxx xxxx */
+ {illegal,0 }, /* a6: 0110 0100 1010 0110 xxxx xxxx */
+ {illegal,0 }, /* a7: 0110 0100 1010 0111 xxxx xxxx */
+ {illegal,0 }, /* a8: 0110 0100 1010 1000 xxxx xxxx */
+ {GTI,"SMH,%b" }, /* a9: 0110 0100 1010 1001 xxxx xxxx */
+ {illegal,0 }, /* aa: 0110 0100 1010 1010 xxxx xxxx */
+ {GTI,"EOM,%b" }, /* ab: 0110 0100 1010 1011 xxxx xxxx */
+ {illegal,0 }, /* ac: 0110 0100 1010 1100 xxxx xxxx */
+ {GTI,"TMM,%b" }, /* ad: 0110 0100 1010 1101 xxxx xxxx */
+ {GTI,"PT,%b" }, /* ae: 0110 0100 1010 1110 xxxx xxxx */
+ {illegal,0 }, /* af: 0110 0100 1010 1111 xxxx xxxx */
+
+ {illegal,0 }, /* b0: 0110 0100 1011 0000 xxxx xxxx */
+ {SUINB,"SMH,%b" }, /* b1: 0110 0100 1011 0001 xxxx xxxx */
+ {illegal,0 }, /* b2: 0110 0100 1011 0010 xxxx xxxx */
+ {SUINB,"EOM,%b" }, /* b3: 0110 0100 1011 0011 xxxx xxxx */
+ {illegal,0 }, /* b4: 0110 0100 1011 0100 xxxx xxxx */
+ {SUINB,"TMM,%b" }, /* b5: 0110 0100 1011 0101 xxxx xxxx */
+ {illegal,0 }, /* b6: 0110 0100 1011 0110 xxxx xxxx */
+ {illegal,0 }, /* b7: 0110 0100 1011 0111 xxxx xxxx */
+ {illegal,0 }, /* b8: 0110 0100 1011 1000 xxxx xxxx */
+ {LTI,"SMH,%b" }, /* b9: 0110 0100 1011 1001 xxxx xxxx */
+ {illegal,0 }, /* ba: 0110 0100 1011 1010 xxxx xxxx */
+ {LTI,"EOM,%b" }, /* bb: 0110 0100 1011 1011 xxxx xxxx */
+ {illegal,0 }, /* bc: 0110 0100 1011 1100 xxxx xxxx */
+ {LTI,"TMM,%b" }, /* bd: 0110 0100 1011 1101 xxxx xxxx */
+ {LTI,"PT,%b" }, /* be: 0110 0100 1011 1110 xxxx xxxx */
+ {illegal,0 }, /* bf: 0110 0100 1011 1111 xxxx xxxx */
+
+ {illegal,0 }, /* c0: 0110 0100 1100 0000 xxxx xxxx */
+ {ADI,"SMH,%b" }, /* c1: 0110 0100 1100 0001 xxxx xxxx */
+ {illegal,0 }, /* c2: 0110 0100 1100 0010 xxxx xxxx */
+ {ADI,"EOM,%b" }, /* c3: 0110 0100 1100 0011 xxxx xxxx */
+ {illegal,0 }, /* c4: 0110 0100 1100 0100 xxxx xxxx */
+ {ADI,"TMM,%b" }, /* c5: 0110 0100 1100 0101 xxxx xxxx */
+ {illegal,0 }, /* c6: 0110 0100 1100 0110 xxxx xxxx */
+ {illegal,0 }, /* c7: 0110 0100 1100 0111 xxxx xxxx */
+ {illegal,0 }, /* c8: 0110 0100 1100 1000 xxxx xxxx */
+ {ONI,"SMH,%b" }, /* c9: 0110 0100 1100 1001 xxxx xxxx */
+ {illegal,0 }, /* ca: 0110 0100 1100 1010 xxxx xxxx */
+ {ONI,"EOM,%b" }, /* cb: 0110 0100 1100 1011 xxxx xxxx */
+ {illegal,0 }, /* cc: 0110 0100 1100 1100 xxxx xxxx */
+ {ONI,"TMM,%b" }, /* cd: 0110 0100 1100 1101 xxxx xxxx */
+ {ONI,"PT,%b" }, /* ce: 0110 0100 1100 1110 xxxx xxxx */
+ {illegal,0 }, /* cf: 0110 0100 1100 1111 xxxx xxxx */
+
+ {illegal,0 }, /* d0: 0110 0100 1101 0000 xxxx xxxx */
+ {ACI,"SMH,%b" }, /* d1: 0110 0100 1101 0001 xxxx xxxx */
+ {illegal,0 }, /* d2: 0110 0100 1101 0010 xxxx xxxx */
+ {ACI,"EOM,%b" }, /* d3: 0110 0100 1101 0011 xxxx xxxx */
+ {illegal,0 }, /* d4: 0110 0100 1101 0100 xxxx xxxx */
+ {ACI,"TMM,%b" }, /* d5: 0110 0100 1101 0101 xxxx xxxx */
+ {illegal,0 }, /* d6: 0110 0100 1101 0110 xxxx xxxx */
+ {illegal,0 }, /* d7: 0110 0100 1101 0111 xxxx xxxx */
+ {illegal,0 }, /* d8: 0110 0100 1101 1000 xxxx xxxx */
+ {OFFI,"SMH,%b" }, /* d9: 0110 0100 1101 1001 xxxx xxxx */
+ {illegal,0 }, /* da: 0110 0100 1101 1010 xxxx xxxx */
+ {OFFI,"EOM,%b" }, /* db: 0110 0100 1101 1011 xxxx xxxx */
+ {illegal,0 }, /* dc: 0110 0100 1101 1100 xxxx xxxx */
+ {OFFI,"TMM,%b" }, /* dd: 0110 0100 1101 1101 xxxx xxxx */
+ {OFFI,"PT,%b" }, /* de: 0110 0100 1101 1110 xxxx xxxx */
+ {illegal,0 }, /* df: 0110 0100 1101 1111 xxxx xxxx */
+
+ {illegal,0 }, /* e0: 0110 0100 1110 0000 xxxx xxxx */
+ {SUI,"SMH,%b" }, /* e1: 0110 0100 1110 0001 xxxx xxxx */
+ {illegal,0 }, /* e2: 0110 0100 1110 0010 xxxx xxxx */
+ {SUI,"EOM,%b" }, /* e3: 0110 0100 1110 0011 xxxx xxxx */
+ {illegal,0 }, /* e4: 0110 0100 1110 0100 xxxx xxxx */
+ {SUI,"TMM,%b" }, /* e5: 0110 0100 1110 0101 xxxx xxxx */
+ {illegal,0 }, /* e6: 0110 0100 1110 0110 xxxx xxxx */
+ {illegal,0 }, /* e7: 0110 0100 1110 0111 xxxx xxxx */
+ {illegal,0 }, /* e8: 0110 0100 1110 1000 xxxx xxxx */
+ {NEI,"SMH,%b" }, /* e9: 0110 0100 1110 1001 xxxx xxxx */
+ {illegal,0 }, /* ea: 0110 0100 1110 1010 xxxx xxxx */
+ {NEI,"EOM,%b" }, /* eb: 0110 0100 1110 1011 xxxx xxxx */
+ {illegal,0 }, /* ec: 0110 0100 1110 1100 xxxx xxxx */
+ {NEI,"TMM,%b" }, /* ed: 0110 0100 1110 1101 xxxx xxxx */
+ {NEI,"PT,%b" }, /* ee: 0110 0100 1110 1110 xxxx xxxx */
+ {illegal,0 }, /* ef: 0110 0100 1110 1111 xxxx xxxx */
+
+ {illegal,0 }, /* f0: 0110 0100 1111 0000 xxxx xxxx */
+ {SBI,"SMH,%b" }, /* f1: 0110 0100 1111 0001 xxxx xxxx */
+ {illegal,0 }, /* f2: 0110 0100 1111 0010 xxxx xxxx */
+ {SBI,"EOM,%b" }, /* f3: 0110 0100 1111 0011 xxxx xxxx */
+ {illegal,0 }, /* f4: 0110 0100 1111 0100 xxxx xxxx */
+ {SBI,"TMM,%b" }, /* f5: 0110 0100 1111 0101 xxxx xxxx */
+ {illegal,0 }, /* f6: 0110 0100 1111 0110 xxxx xxxx */
+ {illegal,0 }, /* f7: 0110 0100 1111 0111 xxxx xxxx */
+ {illegal,0 }, /* f8: 0110 0100 1111 1000 xxxx xxxx */
+ {EQI,"SMH,%b" }, /* f9: 0110 0100 1111 1001 xxxx xxxx */
+ {illegal,0 }, /* fa: 0110 0100 1111 1010 xxxx xxxx */
+ {EQI,"EOM,%b" }, /* fb: 0110 0100 1111 1011 xxxx xxxx */
+ {illegal,0 }, /* fc: 0110 0100 1111 1100 xxxx xxxx */
+ {EQI,"TMM,%b" }, /* fd: 0110 0100 1111 1101 xxxx xxxx */
+ {EQI,"PT,%b" }, /* fe: 0110 0100 1111 1110 xxxx xxxx */
+ {illegal,0 } /* ff: 0110 0100 1111 1111 xxxx xxxx */
+};
+
+/* prefix 70 */
+static const struct dasm_s dasm70[256] =
+{
+ {illegal,0 }, /* 00: 0111 0000 0000 0000 */
+ {illegal,0 }, /* 01: 0111 0000 0000 0001 */
+ {illegal,0 }, /* 02: 0111 0000 0000 0010 */
+ {illegal,0 }, /* 03: 0111 0000 0000 0011 */
+ {illegal,0 }, /* 04: 0111 0000 0000 0100 */
+ {illegal,0 }, /* 05: 0111 0000 0000 0101 */
+ {illegal,0 }, /* 06: 0111 0000 0000 0110 */
+ {illegal,0 }, /* 07: 0111 0000 0000 0111 */
+ {illegal,0 }, /* 08: 0111 0000 0000 1000 */
+ {illegal,0 }, /* 09: 0111 0000 0000 1001 */
+ {illegal,0 }, /* 0a: 0111 0000 0000 1010 */
+ {illegal,0 }, /* 0b: 0111 0000 0000 1011 */
+ {illegal,0 }, /* 0c: 0111 0000 0000 1100 */
+ {illegal,0 }, /* 0d: 0111 0000 0000 1101 */
+ {SSPD,"%w" }, /* 0e: 0111 0000 0000 1110 llll llll hhhh hhhh */
+ {LSPD,"%w" }, /* 0f: 0111 0000 0000 1111 llll llll hhhh hhhh */
+
+ {illegal,0 }, /* 10: 0111 0000 0001 0000 */
+ {illegal,0 }, /* 11: 0111 0000 0001 0001 */
+ {illegal,0 }, /* 12: 0111 0000 0001 0010 */
+ {illegal,0 }, /* 13: 0111 0000 0001 0011 */
+ {illegal,0 }, /* 14: 0111 0000 0001 0100 */
+ {illegal,0 }, /* 15: 0111 0000 0001 0101 */
+ {illegal,0 }, /* 16: 0111 0000 0001 0110 */
+ {illegal,0 }, /* 17: 0111 0000 0001 0111 */
+ {illegal,0 }, /* 18: 0111 0000 0001 1000 */
+ {illegal,0 }, /* 19: 0111 0000 0001 1001 */
+ {illegal,0 }, /* 1a: 0111 0000 0001 1010 */
+ {illegal,0 }, /* 1b: 0111 0000 0001 1011 */
+ {illegal,0 }, /* 1c: 0111 0000 0001 1100 */
+ {illegal,0 }, /* 1d: 0111 0000 0001 1101 */
+ {SBCD,"%w" }, /* 1e: 0111 0000 0001 1110 llll llll hhhh hhhh */
+ {LBCD,"%w" }, /* 1f: 0111 0000 0001 1111 llll llll hhhh hhhh */
+
+ {illegal,0 }, /* 20: 0111 0000 0010 0000 */
+ {illegal,0 }, /* 21: 0111 0000 0010 0001 */
+ {illegal,0 }, /* 22: 0111 0000 0010 0010 */
+ {illegal,0 }, /* 23: 0111 0000 0010 0011 */
+ {illegal,0 }, /* 24: 0111 0000 0010 0100 */
+ {illegal,0 }, /* 25: 0111 0000 0010 0101 */
+ {illegal,0 }, /* 26: 0111 0000 0010 0110 */
+ {illegal,0 }, /* 27: 0111 0000 0010 0111 */
+ {illegal,0 }, /* 28: 0111 0000 0010 1000 */
+ {illegal,0 }, /* 29: 0111 0000 0010 1001 */
+ {illegal,0 }, /* 2a: 0111 0000 0010 1010 */
+ {illegal,0 }, /* 2b: 0111 0000 0010 1011 */
+ {illegal,0 }, /* 2c: 0111 0000 0010 1100 */
+ {illegal,0 }, /* 2d: 0111 0000 0010 1101 */
+ {SDED,"%w" }, /* 2e: 0111 0000 0010 1110 llll llll hhhh hhhh */
+ {LDED,"%w" }, /* 2f: 0111 0000 0010 1111 llll llll hhhh hhhh */
+
+ {illegal,0 }, /* 30: 0111 0000 0011 0000 */
+ {illegal,0 }, /* 31: 0111 0000 0011 0001 */
+ {illegal,0 }, /* 32: 0111 0000 0011 0010 */
+ {illegal,0 }, /* 33: 0111 0000 0011 0011 */
+ {illegal,0 }, /* 34: 0111 0000 0011 0100 */
+ {illegal,0 }, /* 35: 0111 0000 0011 0101 */
+ {illegal,0 }, /* 36: 0111 0000 0011 0110 */
+ {illegal,0 }, /* 37: 0111 0000 0011 0111 */
+ {illegal,0 }, /* 38: 0111 0000 0011 1000 */
+ {illegal,0 }, /* 39: 0111 0000 0011 1001 */
+ {illegal,0 }, /* 3a: 0111 0000 0011 1010 */
+ {illegal,0 }, /* 3b: 0111 0000 0011 1011 */
+ {illegal,0 }, /* 3c: 0111 0000 0011 1100 */
+ {illegal,0 }, /* 3d: 0111 0000 0011 1101 */
+ {SHLD,"%w" }, /* 3e: 0111 0000 0011 1110 llll llll hhhh hhhh */
+ {LHLD,"%w" }, /* 3f: 0111 0000 0011 1111 llll llll hhhh hhhh */
+
+ {EADD,"EA,V" }, /* 40: 0111 0000 0100 0000 */
+ {EADD,"EA,A" }, /* 41: 0111 0000 0100 0001 */
+ {EADD,"EA,B" }, /* 42: 0111 0000 0100 0010 */
+ {EADD,"EA,C" }, /* 43: 0111 0000 0100 0011 */
+ {illegal,0 }, /* 44: 0111 0000 0100 0100 */
+ {illegal,0 }, /* 45: 0111 0000 0100 0101 */
+ {illegal,0 }, /* 46: 0111 0000 0100 0110 */
+ {illegal,0 }, /* 47: 0111 0000 0100 0111 */
+ {illegal,0 }, /* 48: 0111 0000 0100 1000 */
+ {illegal,0 }, /* 49: 0111 0000 0100 1001 */
+ {illegal,0 }, /* 4a: 0111 0000 0100 1010 */
+ {illegal,0 }, /* 4b: 0111 0000 0100 1011 */
+ {illegal,0 }, /* 4c: 0111 0000 0100 1100 */
+ {illegal,0 }, /* 4d: 0111 0000 0100 1101 */
+ {illegal,0 }, /* 4e: 0111 0000 0100 1110 */
+ {illegal,0 }, /* 4f: 0111 0000 0100 1111 */
+
+ {illegal,0 }, /* 50: 0111 0000 0101 0000 */
+ {illegal,0 }, /* 51: 0111 0000 0101 0001 */
+ {illegal,0 }, /* 52: 0111 0000 0101 0010 */
+ {illegal,0 }, /* 53: 0111 0000 0101 0011 */
+ {illegal,0 }, /* 54: 0111 0000 0101 0100 */
+ {illegal,0 }, /* 55: 0111 0000 0101 0101 */
+ {illegal,0 }, /* 56: 0111 0000 0101 0110 */
+ {illegal,0 }, /* 57: 0111 0000 0101 0111 */
+ {illegal,0 }, /* 58: 0111 0000 0101 1000 */
+ {illegal,0 }, /* 59: 0111 0000 0101 1001 */
+ {illegal,0 }, /* 5a: 0111 0000 0101 1010 */
+ {illegal,0 }, /* 5b: 0111 0000 0101 1011 */
+ {illegal,0 }, /* 5c: 0111 0000 0101 1100 */
+ {illegal,0 }, /* 5d: 0111 0000 0101 1101 */
+ {illegal,0 }, /* 5e: 0111 0000 0101 1110 */
+ {illegal,0 }, /* 5f: 0111 0000 0101 1111 */
+
+ {ESUB,"EA,V" }, /* 60: 0111 0000 0110 0000 */
+ {ESUB,"EA,A" }, /* 61: 0111 0000 0110 0001 */
+ {ESUB,"EA,B" }, /* 62: 0111 0000 0110 0010 */
+ {ESUB,"EA,C" }, /* 63: 0111 0000 0110 0011 */
+ {illegal,0 }, /* 64: 0111 0000 0110 0100 */
+ {illegal,0 }, /* 65: 0111 0000 0110 0101 */
+ {illegal,0 }, /* 66: 0111 0000 0110 0110 */
+ {illegal,0 }, /* 67: 0111 0000 0110 0111 */
+ {MOV,"V,(%w)" }, /* 68: 0111 0000 0110 1000 llll llll hhhh hhhh */
+ {MOV,"A,(%w)" }, /* 69: 0111 0000 0110 1001 llll llll hhhh hhhh */
+ {MOV,"B,(%w)" }, /* 6a: 0111 0000 0110 1010 llll llll hhhh hhhh */
+ {MOV,"C,(%w)" }, /* 6b: 0111 0000 0110 1011 llll llll hhhh hhhh */
+ {MOV,"D,(%w)" }, /* 6c: 0111 0000 0110 1100 llll llll hhhh hhhh */
+ {MOV,"E,(%w)" }, /* 6d: 0111 0000 0110 1101 llll llll hhhh hhhh */
+ {MOV,"H,(%w)" }, /* 6e: 0111 0000 0110 1110 llll llll hhhh hhhh */
+ {MOV,"L,(%w)" }, /* 6f: 0111 0000 0110 1111 llll llll hhhh hhhh */
+
+ {illegal,0 }, /* 70: 0111 0000 0111 0000 */
+ {illegal,0 }, /* 71: 0111 0000 0111 0001 */
+ {illegal,0 }, /* 72: 0111 0000 0111 0010 */
+ {illegal,0 }, /* 73: 0111 0000 0111 0011 */
+ {illegal,0 }, /* 74: 0111 0000 0111 0100 */
+ {illegal,0 }, /* 75: 0111 0000 0111 0101 */
+ {illegal,0 }, /* 76: 0111 0000 0111 0110 */
+ {illegal,0 }, /* 77: 0111 0000 0111 0111 */
+ {MOV,"(%w),V" }, /* 78: 0111 0000 0111 1000 llll llll hhhh hhhh */
+ {MOV,"(%w),A" }, /* 79: 0111 0000 0111 1001 llll llll hhhh hhhh */
+ {MOV,"(%w),B" }, /* 7a: 0111 0000 0111 1010 llll llll hhhh hhhh */
+ {MOV,"(%w),C" }, /* 7b: 0111 0000 0111 1011 llll llll hhhh hhhh */
+ {MOV,"(%w),D" }, /* 7c: 0111 0000 0111 1100 llll llll hhhh hhhh */
+ {MOV,"(%w),E" }, /* 7d: 0111 0000 0111 1101 llll llll hhhh hhhh */
+ {MOV,"(%w),H" }, /* 7e: 0111 0000 0111 1110 llll llll hhhh hhhh */
+ {MOV,"(%w),L" }, /* 7f: 0111 0000 0111 1111 llll llll hhhh hhhh */
+
+ {illegal,0 }, /* 80: 0111 0000 1000 0000 */
+ {illegal,0 }, /* 81: 0111 0000 1000 0001 */
+ {illegal,0 }, /* 82: 0111 0000 1000 0010 */
+ {illegal,0 }, /* 83: 0111 0000 1000 0011 */
+ {illegal,0 }, /* 84: 0111 0000 1000 0100 */
+ {illegal,0 }, /* 85: 0111 0000 1000 0101 */
+ {illegal,0 }, /* 86: 0111 0000 1000 0110 */
+ {illegal,0 }, /* 87: 0111 0000 1000 0111 */
+ {illegal,0 }, /* 88: 0111 0000 1000 1000 */
+ {ANAX,"(BC)" }, /* 89: 0111 0000 1000 1001 */
+ {ANAX,"(DE)" }, /* 8a: 0111 0000 1000 1010 */
+ {ANAX,"(HL)" }, /* 8b: 0111 0000 1000 1011 */
+ {ANAX,"(DE+)" }, /* 8c: 0111 0000 1000 1100 */
+ {ANAX,"(HL+)" }, /* 8d: 0111 0000 1000 1101 */
+ {ANAX,"(DE-)" }, /* 8e: 0111 0000 1000 1110 */
+ {ANAX,"(HL-)" }, /* 8f: 0111 0000 1000 1111 */
+
+ {illegal,0 }, /* 90: 0111 0000 1001 0000 */
+ {XRAX,"(BC)" }, /* 91: 0111 0000 1001 0001 */
+ {XRAX,"(DE)" }, /* 92: 0111 0000 1001 0010 */
+ {XRAX,"(HL)" }, /* 93: 0111 0000 1001 0011 */
+ {XRAX,"(DE+)" }, /* 94: 0111 0000 1001 0100 */
+ {XRAX,"(HL+)" }, /* 95: 0111 0000 1001 0101 */
+ {XRAX,"(DE-)" }, /* 96: 0111 0000 1001 0110 */
+ {XRAX,"(HL-)" }, /* 97: 0111 0000 1001 0111 */
+ {illegal,0 }, /* 98: 0111 0000 1001 1000 */
+ {ORAX,"(BC)" }, /* 99: 0111 0000 1001 1001 */
+ {ORAX,"(DE)" }, /* 9a: 0111 0000 1001 1010 */
+ {ORAX,"(HL)" }, /* 9b: 0111 0000 1001 1011 */
+ {ORAX,"(DE+)" }, /* 9c: 0111 0000 1001 1100 */
+ {ORAX,"(HL+)" }, /* 9d: 0111 0000 1001 1101 */
+ {ORAX,"(DE-)" }, /* 9e: 0111 0000 1001 1110 */
+ {ORAX,"(HL-)" }, /* 9f: 0111 0000 1001 1111 */
+
+ {illegal,0 }, /* a0: 0111 0000 1010 0000 */
+ {ADDNCX,"(BC)" }, /* a1: 0111 0000 1010 0001 */
+ {ADDNCX,"(DE)" }, /* a2: 0111 0000 1010 0010 */
+ {ADDNCX,"(HL)" }, /* a3: 0111 0000 1010 0011 */
+ {ADDNCX,"(DE+)" }, /* a4: 0111 0000 1010 0100 */
+ {ADDNCX,"(HL+)" }, /* a5: 0111 0000 1010 0101 */
+ {ADDNCX,"(DE-)" }, /* a6: 0111 0000 1010 0110 */
+ {ADDNCX,"(HL-)" }, /* a7: 0111 0000 1010 0111 */
+ {illegal,0 }, /* a8: 0111 0000 1010 1000 */
+ {GTAX,"(BC)" }, /* a9: 0111 0000 1010 1001 */
+ {GTAX,"(DE)" }, /* aa: 0111 0000 1010 1010 */
+ {GTAX,"(HL)" }, /* ab: 0111 0000 1010 1011 */
+ {GTAX,"(DE+)" }, /* ac: 0111 0000 1010 1100 */
+ {GTAX,"(HL+)" }, /* ad: 0111 0000 1010 1101 */
+ {GTAX,"(DE-)" }, /* ae: 0111 0000 1010 1110 */
+ {GTAX,"(HL-)" }, /* af: 0111 0000 1010 1111 */
+
+ {illegal,0 }, /* b0: 0111 0000 1011 0000 */
+ {SUBNBX,"(BC)" }, /* b1: 0111 0000 1011 0001 */
+ {SUBNBX,"(DE)" }, /* b2: 0111 0000 1011 0010 */
+ {SUBNBX,"(HL)" }, /* b3: 0111 0000 1011 0011 */
+ {SUBNBX,"(DE+)" }, /* b4: 0111 0000 1011 0100 */
+ {SUBNBX,"(HL+)" }, /* b5: 0111 0000 1011 0101 */
+ {SUBNBX,"(DE-)" }, /* b6: 0111 0000 1011 0110 */
+ {SUBNBX,"(HL-)" }, /* b7: 0111 0000 1011 0111 */
+ {illegal,0 }, /* b8: 0111 0000 1011 1000 */
+ {LTAX,"(BC)" }, /* b9: 0111 0000 1011 1001 */
+ {LTAX,"(DE)" }, /* ba: 0111 0000 1011 1010 */
+ {LTAX,"(HL)" }, /* bb: 0111 0000 1011 1011 */
+ {LTAX,"(DE+)" }, /* bc: 0111 0000 1011 1100 */
+ {LTAX,"(HL+)" }, /* bd: 0111 0000 1011 1101 */
+ {LTAX,"(DE-)" }, /* be: 0111 0000 1011 1110 */
+ {LTAX,"(HL-)" }, /* bf: 0111 0000 1011 1111 */
+
+ {illegal,0 }, /* c0: 0111 0000 1100 0000 */
+ {ADDX,"(BC)" }, /* c1: 0111 0000 1100 0001 */
+ {ADDX,"(DE)" }, /* c2: 0111 0000 1100 0010 */
+ {ADDX,"(HL)" }, /* c3: 0111 0000 1100 0011 */
+ {ADDX,"(DE+)" }, /* c4: 0111 0000 1100 0100 */
+ {ADDX,"(HL+)" }, /* c5: 0111 0000 1100 0101 */
+ {ADDX,"(DE-)" }, /* c6: 0111 0000 1100 0110 */
+ {ADDX,"(HL-)" }, /* c7: 0111 0000 1100 0111 */
+ {illegal,0 }, /* c8: 0111 0000 1100 1000 */
+ {ONAX,"(BC)" }, /* c9: 0111 0000 1100 1001 */
+ {ONAX,"(DE)" }, /* ca: 0111 0000 1100 1010 */
+ {ONAX,"(HL)" }, /* cb: 0111 0000 1100 1011 */
+ {ONAX,"(DE+)" }, /* cc: 0111 0000 1100 1100 */
+ {ONAX,"(HL+)" }, /* cd: 0111 0000 1100 1101 */
+ {ONAX,"(DE-)" }, /* ce: 0111 0000 1100 1110 */
+ {ONAX,"(HL-)" }, /* cf: 0111 0000 1100 1111 */
+
+ {illegal,0 }, /* d0: 0111 0000 1101 0000 */
+ {ADCX,"(BC)" }, /* d1: 0111 0000 1101 0001 */
+ {ADCX,"(DE)" }, /* d2: 0111 0000 1101 0010 */
+ {ADCX,"(HL)" }, /* d3: 0111 0000 1101 0011 */
+ {ADCX,"(DE+)" }, /* d4: 0111 0000 1101 0100 */
+ {ADCX,"(HL+)" }, /* d5: 0111 0000 1101 0101 */
+ {ADCX,"(DE-)" }, /* d6: 0111 0000 1101 0110 */
+ {ADCX,"(HL-)" }, /* d7: 0111 0000 1101 0111 */
+ {illegal,0 }, /* d8: 0111 0000 1101 1000 */
+ {OFFAX,"(BC)" }, /* d9: 0111 0000 1101 1001 */
+ {OFFAX,"(DE)" }, /* da: 0111 0000 1101 1010 */
+ {OFFAX,"(HL)" }, /* db: 0111 0000 1101 1011 */
+ {OFFAX,"(DE+)" }, /* dc: 0111 0000 1101 1100 */
+ {OFFAX,"(HL+)" }, /* dd: 0111 0000 1101 1101 */
+ {OFFAX,"(DE-)" }, /* de: 0111 0000 1101 1110 */
+ {OFFAX,"(HL-)" }, /* df: 0111 0000 1101 1111 */
+
+ {illegal,0 }, /* e0: 0111 0000 1110 0000 */
+ {SUBX,"(BC)" }, /* e1: 0111 0000 1110 0001 */
+ {SUBX,"(DE)" }, /* e2: 0111 0000 1110 0010 */
+ {SUBX,"(HL)" }, /* e3: 0111 0000 1110 0011 */
+ {SUBX,"(DE+)" }, /* e4: 0111 0000 1110 0100 */
+ {SUBX,"(HL+)" }, /* e5: 0111 0000 1110 0101 */
+ {SUBX,"(DE-)" }, /* e6: 0111 0000 1110 0110 */
+ {SUBX,"(HL-)" }, /* e7: 0111 0000 1110 0111 */
+ {illegal,0 }, /* e8: 0111 0000 1110 1000 */
+ {NEAX,"(BC)" }, /* e9: 0111 0000 1110 1001 */
+ {NEAX,"(DE)" }, /* ea: 0111 0000 1110 1010 */
+ {NEAX,"(HL)" }, /* eb: 0111 0000 1110 1011 */
+ {NEAX,"(DE+)" }, /* ec: 0111 0000 1110 1100 */
+ {NEAX,"(HL+)" }, /* ed: 0111 0000 1110 1101 */
+ {NEAX,"(DE-)" }, /* ee: 0111 0000 1110 1110 */
+ {NEAX,"(HL-)" }, /* ef: 0111 0000 1110 1111 */
+
+ {illegal,0 }, /* f0: 0111 0000 1111 0000 */
+ {SBBX,"(BC)" }, /* f1: 0111 0000 1111 0001 */
+ {SBBX,"(DE)" }, /* f2: 0111 0000 1111 0010 */
+ {SBBX,"(HL)" }, /* f3: 0111 0000 1111 0011 */
+ {SBBX,"(DE+)" }, /* f4: 0111 0000 1111 0100 */
+ {SBBX,"(HL+)" }, /* f5: 0111 0000 1111 0101 */
+ {SBBX,"(DE-)" }, /* f6: 0111 0000 1111 0110 */
+ {SBBX,"(HL-)" }, /* f7: 0111 0000 1111 0111 */
+ {illegal,0 }, /* f8: 0111 0000 1111 1000 */
+ {EQAX,"(BC)" }, /* f9: 0111 0000 1111 1001 */
+ {EQAX,"(DE)" }, /* fa: 0111 0000 1111 1010 */
+ {EQAX,"(HL)" }, /* fb: 0111 0000 1111 1011 */
+ {EQAX,"(DE+)" }, /* fc: 0111 0000 1111 1100 */
+ {EQAX,"(HL+)" }, /* fd: 0111 0000 1111 1101 */
+ {EQAX,"(DE-)" }, /* fe: 0111 0000 1111 1110 */
+ {EQAX,"(HL-)" } /* ff: 0111 0000 1111 1111 */
+};
+
+/* prefix 74 */
+static const struct dasm_s dasm74[256] =
+{
+ {illegal,0 }, /* 00: 0111 0100 0000 0000 */
+ {illegal,0 }, /* 01: 0111 0100 0000 0001 */
+ {illegal,0 }, /* 02: 0111 0100 0000 0010 */
+ {illegal,0 }, /* 03: 0111 0100 0000 0011 */
+ {illegal,0 }, /* 04: 0111 0100 0000 0100 */
+ {illegal,0 }, /* 05: 0111 0100 0000 0101 */
+ {illegal,0 }, /* 06: 0111 0100 0000 0110 */
+ {illegal,0 }, /* 07: 0111 0100 0000 0111 */
+ {ANI,"V,%b" }, /* 08: 0111 0100 0000 1000 xxxx xxxx */
+ {ANI,"A,%b" }, /* 09: 0111 0100 0000 1001 xxxx xxxx */
+ {ANI,"B,%b" }, /* 0a: 0111 0100 0000 1010 xxxx xxxx */
+ {ANI,"C,%b" }, /* 0b: 0111 0100 0000 1011 xxxx xxxx */
+ {ANI,"D,%b" }, /* 0c: 0111 0100 0000 1100 xxxx xxxx */
+ {ANI,"E,%b" }, /* 0d: 0111 0100 0000 1101 xxxx xxxx */
+ {ANI,"H,%b" }, /* 0e: 0111 0100 0000 1110 xxxx xxxx */
+ {ANI,"L,%b" }, /* 0f: 0111 0100 0000 1111 xxxx xxxx */
+
+ {XRI,"V,%b" }, /* 10: 0111 0100 0001 0000 xxxx xxxx */
+ {XRI,"A,%b" }, /* 11: 0111 0100 0001 0001 xxxx xxxx */
+ {XRI,"B,%b" }, /* 12: 0111 0100 0001 0010 xxxx xxxx */
+ {XRI,"C,%b" }, /* 13: 0111 0100 0001 0011 xxxx xxxx */
+ {XRI,"D,%b" }, /* 14: 0111 0100 0001 0100 xxxx xxxx */
+ {XRI,"E,%b" }, /* 15: 0111 0100 0001 0101 xxxx xxxx */
+ {XRI,"H,%b" }, /* 16: 0111 0100 0001 0110 xxxx xxxx */
+ {XRI,"L,%b" }, /* 17: 0111 0100 0001 0111 xxxx xxxx */
+ {ORI,"V,%b" }, /* 18: 0111 0100 0001 1000 xxxx xxxx */
+ {ORI,"A,%b" }, /* 19: 0111 0100 0001 1001 xxxx xxxx */
+ {ORI,"B,%b" }, /* 1a: 0111 0100 0001 1010 xxxx xxxx */
+ {ORI,"C,%b" }, /* 1b: 0111 0100 0001 1011 xxxx xxxx */
+ {ORI,"D,%b" }, /* 1c: 0111 0100 0001 1100 xxxx xxxx */
+ {ORI,"E,%b" }, /* 1d: 0111 0100 0001 1101 xxxx xxxx */
+ {ORI,"H,%b" }, /* 1e: 0111 0100 0001 1110 xxxx xxxx */
+ {ORI,"L,%b" }, /* 1f: 0111 0100 0001 1111 xxxx xxxx */
+
+ {ADINC,"V,%b" }, /* 20: 0111 0100 0010 0000 xxxx xxxx */
+ {ADINC,"A,%b" }, /* 21: 0111 0100 0010 0001 xxxx xxxx */
+ {ADINC,"B,%b" }, /* 22: 0111 0100 0010 0010 xxxx xxxx */
+ {ADINC,"C,%b" }, /* 23: 0111 0100 0010 0011 xxxx xxxx */
+ {ADINC,"D,%b" }, /* 24: 0111 0100 0010 0100 xxxx xxxx */
+ {ADINC,"E,%b" }, /* 25: 0111 0100 0010 0101 xxxx xxxx */
+ {ADINC,"H,%b" }, /* 26: 0111 0100 0010 0110 xxxx xxxx */
+ {ADINC,"L,%b" }, /* 27: 0111 0100 0010 0111 xxxx xxxx */
+ {GTI,"V,%b" }, /* 28: 0111 0100 0010 1000 xxxx xxxx */
+ {GTI,"A,%b" }, /* 29: 0111 0100 0010 1001 xxxx xxxx */
+ {GTI,"B,%b" }, /* 2a: 0111 0100 0010 1010 xxxx xxxx */
+ {GTI,"C,%b" }, /* 2b: 0111 0100 0010 1011 xxxx xxxx */
+ {GTI,"D,%b" }, /* 2c: 0111 0100 0010 1100 xxxx xxxx */
+ {GTI,"E,%b" }, /* 2d: 0111 0100 0010 1101 xxxx xxxx */
+ {GTI,"H,%b" }, /* 2e: 0111 0100 0010 1110 xxxx xxxx */
+ {GTI,"L,%b" }, /* 2f: 0111 0100 0010 1111 xxxx xxxx */
+
+ {SUINB,"V,%b" }, /* 30: 0111 0100 0011 0000 xxxx xxxx */
+ {SUINB,"A,%b" }, /* 31: 0111 0100 0011 0001 xxxx xxxx */
+ {SUINB,"B,%b" }, /* 32: 0111 0100 0011 0010 xxxx xxxx */
+ {SUINB,"C,%b" }, /* 33: 0111 0100 0011 0011 xxxx xxxx */
+ {SUINB,"D,%b" }, /* 34: 0111 0100 0011 0100 xxxx xxxx */
+ {SUINB,"E,%b" }, /* 35: 0111 0100 0011 0101 xxxx xxxx */
+ {SUINB,"H,%b" }, /* 36: 0111 0100 0011 0110 xxxx xxxx */
+ {SUINB,"L,%b" }, /* 37: 0111 0100 0011 0111 xxxx xxxx */
+ {LTI,"V,%b" }, /* 38: 0111 0100 0011 1000 xxxx xxxx */
+ {LTI,"A,%b" }, /* 39: 0111 0100 0011 1001 xxxx xxxx */
+ {LTI,"B,%b" }, /* 3a: 0111 0100 0011 1010 xxxx xxxx */
+ {LTI,"C,%b" }, /* 3b: 0111 0100 0011 1011 xxxx xxxx */
+ {LTI,"D,%b" }, /* 3c: 0111 0100 0011 1100 xxxx xxxx */
+ {LTI,"E,%b" }, /* 3d: 0111 0100 0011 1101 xxxx xxxx */
+ {LTI,"H,%b" }, /* 3e: 0111 0100 0011 1110 xxxx xxxx */
+ {LTI,"L,%b" }, /* 3f: 0111 0100 0011 1111 xxxx xxxx */
+
+ {ADI,"V,%b" }, /* 40: 0111 0100 0100 0000 xxxx xxxx */
+ {ADI,"A,%b" }, /* 41: 0111 0100 0100 0001 xxxx xxxx */
+ {ADI,"B,%b" }, /* 42: 0111 0100 0100 0010 xxxx xxxx */
+ {ADI,"C,%b" }, /* 43: 0111 0100 0100 0011 xxxx xxxx */
+ {ADI,"D,%b" }, /* 44: 0111 0100 0100 0100 xxxx xxxx */
+ {ADI,"E,%b" }, /* 45: 0111 0100 0100 0101 xxxx xxxx */
+ {ADI,"H,%b" }, /* 46: 0111 0100 0100 0110 xxxx xxxx */
+ {ADI,"L,%b" }, /* 47: 0111 0100 0100 0111 xxxx xxxx */
+ {ONI,"V,%b" }, /* 48: 0111 0100 0100 1000 xxxx xxxx */
+ {ONI,"A,%b" }, /* 49: 0111 0100 0100 1001 xxxx xxxx */
+ {ONI,"B,%b" }, /* 4a: 0111 0100 0100 1010 xxxx xxxx */
+ {ONI,"C,%b" }, /* 4b: 0111 0100 0100 1011 xxxx xxxx */
+ {ONI,"D,%b" }, /* 4c: 0111 0100 0100 1100 xxxx xxxx */
+ {ONI,"E,%b" }, /* 4d: 0111 0100 0100 1101 xxxx xxxx */
+ {ONI,"H,%b" }, /* 4e: 0111 0100 0100 1110 xxxx xxxx */
+ {ONI,"L,%b" }, /* 4f: 0111 0100 0100 1111 xxxx xxxx */
+
+ {ACI,"V,%b" }, /* 50: 0111 0100 0101 0000 xxxx xxxx */
+ {ACI,"A,%b" }, /* 51: 0111 0100 0101 0001 xxxx xxxx */
+ {ACI,"B,%b" }, /* 52: 0111 0100 0101 0010 xxxx xxxx */
+ {ACI,"C,%b" }, /* 53: 0111 0100 0101 0011 xxxx xxxx */
+ {ACI,"D,%b" }, /* 54: 0111 0100 0101 0100 xxxx xxxx */
+ {ACI,"E,%b" }, /* 55: 0111 0100 0101 0101 xxxx xxxx */
+ {ACI,"H,%b" }, /* 56: 0111 0100 0101 0110 xxxx xxxx */
+ {ACI,"L,%b" }, /* 57: 0111 0100 0101 0111 xxxx xxxx */
+ {OFFI,"V,%b" }, /* 58: 0111 0100 0101 1000 xxxx xxxx */
+ {OFFI,"A,%b" }, /* 59: 0111 0100 0101 1001 xxxx xxxx */
+ {OFFI,"B,%b" }, /* 5a: 0111 0100 0101 1010 xxxx xxxx */
+ {OFFI,"C,%b" }, /* 5b: 0111 0100 0101 1011 xxxx xxxx */
+ {OFFI,"D,%b" }, /* 5c: 0111 0100 0101 1100 xxxx xxxx */
+ {OFFI,"E,%b" }, /* 5d: 0111 0100 0101 1101 xxxx xxxx */
+ {OFFI,"H,%b" }, /* 5e: 0111 0100 0101 1110 xxxx xxxx */
+ {OFFI,"L,%b" }, /* 5f: 0111 0100 0101 1111 xxxx xxxx */
+
+ {SUI,"V,%b" }, /* 60: 0111 0100 0110 0000 xxxx xxxx */
+ {SUI,"A,%b" }, /* 61: 0111 0100 0110 0001 xxxx xxxx */
+ {SUI,"B,%b" }, /* 62: 0111 0100 0110 0010 xxxx xxxx */
+ {SUI,"C,%b" }, /* 63: 0111 0100 0110 0011 xxxx xxxx */
+ {SUI,"D,%b" }, /* 64: 0111 0100 0110 0100 xxxx xxxx */
+ {SUI,"E,%b" }, /* 65: 0111 0100 0110 0101 xxxx xxxx */
+ {SUI,"H,%b" }, /* 66: 0111 0100 0110 0110 xxxx xxxx */
+ {SUI,"L,%b" }, /* 67: 0111 0100 0110 0111 xxxx xxxx */
+ {NEI,"V,%b" }, /* 68: 0111 0100 0110 1000 xxxx xxxx */
+ {NEI,"A,%b" }, /* 69: 0111 0100 0110 1001 xxxx xxxx */
+ {NEI,"B,%b" }, /* 6a: 0111 0100 0110 1010 xxxx xxxx */
+ {NEI,"C,%b" }, /* 6b: 0111 0100 0110 1011 xxxx xxxx */
+ {NEI,"D,%b" }, /* 6c: 0111 0100 0110 1100 xxxx xxxx */
+ {NEI,"E,%b" }, /* 6d: 0111 0100 0110 1101 xxxx xxxx */
+ {NEI,"H,%b" }, /* 6e: 0111 0100 0110 1110 xxxx xxxx */
+ {NEI,"L,%b" }, /* 6f: 0111 0100 0110 1111 xxxx xxxx */
+
+ {SBI,"V,%b" }, /* 70: 0111 0100 0111 0000 xxxx xxxx */
+ {SBI,"A,%b" }, /* 71: 0111 0100 0111 0001 xxxx xxxx */
+ {SBI,"B,%b" }, /* 72: 0111 0100 0111 0010 xxxx xxxx */
+ {SBI,"C,%b" }, /* 73: 0111 0100 0111 0011 xxxx xxxx */
+ {SBI,"D,%b" }, /* 74: 0111 0100 0111 0100 xxxx xxxx */
+ {SBI,"E,%b" }, /* 75: 0111 0100 0111 0101 xxxx xxxx */
+ {SBI,"H,%b" }, /* 76: 0111 0100 0111 0110 xxxx xxxx */
+ {SBI,"L,%b" }, /* 77: 0111 0100 0111 0111 xxxx xxxx */
+ {EQI,"V,%b" }, /* 78: 0111 0100 0111 1000 xxxx xxxx */
+ {EQI,"A,%b" }, /* 79: 0111 0100 0111 1001 xxxx xxxx */
+ {EQI,"B,%b" }, /* 7a: 0111 0100 0111 1010 xxxx xxxx */
+ {EQI,"C,%b" }, /* 7b: 0111 0100 0111 1011 xxxx xxxx */
+ {EQI,"D,%b" }, /* 7c: 0111 0100 0111 1100 xxxx xxxx */
+ {EQI,"E,%b" }, /* 7d: 0111 0100 0111 1101 xxxx xxxx */
+ {EQI,"H,%b" }, /* 7e: 0111 0100 0111 1110 xxxx xxxx */
+ {EQI,"L,%b" }, /* 7f: 0111 0100 0111 1111 xxxx xxxx */
+
+ {illegal,0 }, /* 80: 0111 0100 1000 0000 */
+ {illegal,0 }, /* 81: 0111 0100 1000 0001 */
+ {illegal,0 }, /* 82: 0111 0100 1000 0010 */
+ {illegal,0 }, /* 83: 0111 0100 1000 0011 */
+ {illegal,0 }, /* 84: 0111 0100 1000 0100 */
+ {illegal,0 }, /* 85: 0111 0100 1000 0101 */
+ {illegal,0 }, /* 86: 0111 0100 1000 0110 */
+ {illegal,0 }, /* 87: 0111 0100 1000 0111 */
+ {ANAW,"%a" }, /* 88: 0111 0100 1000 1000 oooo oooo */
+ {illegal,0 }, /* 89: 0111 0100 1000 1001 */
+ {illegal,0 }, /* 8a: 0111 0100 1000 1010 */
+ {illegal,0 }, /* 8b: 0111 0100 1000 1011 */
+ {illegal,0 }, /* 8c: 0111 0100 1000 1100 */
+ {DAN,"EA,BC" }, /* 8d: 0111 0100 1000 1101 */
+ {DAN,"EA,DE" }, /* 8e: 0111 0100 1000 1110 */
+ {DAN,"EA,HL" }, /* 8f: 0111 0100 1000 1111 */
+
+ {XRAW,"%a" }, /* 90: 0111 0100 1001 0000 oooo oooo */
+ {illegal,0 }, /* 91: 0111 0100 1001 0001 */
+ {illegal,0 }, /* 92: 0111 0100 1001 0010 */
+ {illegal,0 }, /* 93: 0111 0100 1001 0011 */
+ {illegal,0 }, /* 94: 0111 0100 1001 0100 */
+ {DXR,"EA,BC" }, /* 95: 0111 0100 1001 0101 */
+ {DXR,"EA,DE" }, /* 96: 0111 0100 1001 0110 */
+ {DXR,"EA,HL" }, /* 97: 0111 0100 1001 0111 */
+ {ORAW,"%a" }, /* 98: 0111 0100 1001 1000 oooo oooo */
+ {illegal,0 }, /* 99: 0111 0100 1001 1001 */
+ {illegal,0 }, /* 9a: 0111 0100 1001 1010 */
+ {illegal,0 }, /* 9b: 0111 0100 1001 1011 */
+ {illegal,0 }, /* 9c: 0111 0100 1001 1100 */
+ {DOR,"EA,BC" }, /* 9d: 0111 0100 1001 1101 */
+ {DOR,"EA,DE" }, /* 9e: 0111 0100 1001 1110 */
+ {DOR,"EA,HL" }, /* 9f: 0111 0100 1001 1111 */
+
+ {ADDNCW,"%a" }, /* a0: 0111 0100 1010 0000 oooo oooo */
+ {illegal,0 }, /* a1: 0111 0100 1010 0001 */
+ {illegal,0 }, /* a2: 0111 0100 1010 0010 */
+ {illegal,0 }, /* a3: 0111 0100 1010 0011 */
+ {illegal,0 }, /* a4: 0111 0100 1010 0100 */
+ {DADDNC,"EA,BC" }, /* a5: 0111 0100 1010 0101 */
+ {DADDNC,"EA,DE" }, /* a6: 0111 0100 1010 0110 */
+ {DADDNC,"EA,HL" }, /* a7: 0111 0100 1010 0111 */
+ {GTAW,"%a" }, /* a8: 0111 0100 1010 1000 oooo oooo */
+ {illegal,0 }, /* a9: 0111 0100 1010 1001 */
+ {illegal,0 }, /* aa: 0111 0100 1010 1010 */
+ {illegal,0 }, /* ab: 0111 0100 1010 1011 */
+ {illegal,0 }, /* ac: 0111 0100 1010 1100 */
+ {DGT,"EA,BC" }, /* ad: 0111 0100 1010 1101 */
+ {DGT,"EA,DE" }, /* ae: 0111 0100 1010 1110 */
+ {DGT,"EA,HL" }, /* af: 0111 0100 1010 1111 */
+
+ {SUBNBW,"%a" }, /* b0: 0111 0100 1011 0000 oooo oooo */
+ {illegal,0 }, /* b1: 0111 0100 1011 0001 */
+ {illegal,0 }, /* b2: 0111 0100 1011 0010 */
+ {illegal,0 }, /* b3: 0111 0100 1011 0011 */
+ {illegal,0 }, /* b4: 0111 0100 1011 0100 */
+ {DSUBNB,"EA,BC" }, /* b5: 0111 0100 1011 0101 */
+ {DSUBNB,"EA,DE" }, /* b6: 0111 0100 1011 0110 */
+ {DSUBNB,"EA,HL" }, /* b7: 0111 0100 1011 0111 */
+ {LTAW,"%a" }, /* b8: 0111 0100 1011 1000 oooo oooo */
+ {illegal,0 }, /* b9: 0111 0100 1011 1001 */
+ {illegal,0 }, /* ba: 0111 0100 1011 1010 */
+ {illegal,0 }, /* bb: 0111 0100 1011 1011 */
+ {illegal,0 }, /* bc: 0111 0100 1011 1100 */
+ {DLT,"EA,BC" }, /* bd: 0111 0100 1011 1101 */
+ {DLT,"EA,DE" }, /* be: 0111 0100 1011 1110 */
+ {DLT,"EA,HL" }, /* bf: 0111 0100 1011 1111 */
+
+ {ADDW,"%a" }, /* c0: 0111 0100 1100 0000 oooo oooo */
+ {illegal,0 }, /* c1: 0111 0100 1100 0001 */
+ {illegal,0 }, /* c2: 0111 0100 1100 0010 */
+ {illegal,0 }, /* c3: 0111 0100 1100 0011 */
+ {illegal,0 }, /* c4: 0111 0100 1100 0100 */
+ {DADD,"EA,BC" }, /* c5: 0111 0100 1100 0101 */
+ {DADD,"EA,DE" }, /* c6: 0111 0100 1100 0110 */
+ {DADD,"EA,HL" }, /* c7: 0111 0100 1100 0111 */
+ {ONAW,"%a" }, /* c8: 0111 0100 1100 1000 oooo oooo */
+ {illegal,0 }, /* c9: 0111 0100 1100 1001 */
+ {illegal,0 }, /* ca: 0111 0100 1100 1010 */
+ {illegal,0 }, /* cb: 0111 0100 1100 1011 */
+ {illegal,0 }, /* cc: 0111 0100 1100 1100 */
+ {DON,"EA,BC" }, /* cd: 0111 0100 1100 1101 */
+ {DON,"EA,DE" }, /* ce: 0111 0100 1100 1110 */
+ {DON,"EA,HL" }, /* cf: 0111 0100 1100 1111 */
+
+ {ADCW,"%a" }, /* d0: 0111 0100 1101 0000 oooo oooo */
+ {illegal,0 }, /* d1: 0111 0100 1101 0001 */
+ {illegal,0 }, /* d2: 0111 0100 1101 0010 */
+ {illegal,0 }, /* d3: 0111 0100 1101 0011 */
+ {illegal,0 }, /* d4: 0111 0100 1101 0100 */
+ {DADC,"EA,BC" }, /* d5: 0111 0100 1101 0101 */
+ {DADC,"EA,DE" }, /* d6: 0111 0100 1101 0110 */
+ {DADC,"EA,HL" }, /* d7: 0111 0100 1101 0111 */
+ {OFFAW,"%a" }, /* d8: 0111 0100 1101 1000 oooo oooo */
+ {illegal,0 }, /* d9: 0111 0100 1101 1001 */
+ {illegal,0 }, /* da: 0111 0100 1101 1010 */
+ {illegal,0 }, /* db: 0111 0100 1101 1011 */
+ {illegal,0 }, /* dc: 0111 0100 1101 1100 */
+ {DOFF,"EA,BC" }, /* dd: 0111 0100 1101 1101 */
+ {DOFF,"EA,DE" }, /* de: 0111 0100 1101 1110 */
+ {DOFF,"EA,HL" }, /* df: 0111 0100 1101 1111 */
+
+ {SUBW,"%a" }, /* e0: 0111 0100 1110 0000 oooo oooo */
+ {illegal,0 }, /* e1: 0111 0100 1110 0001 */
+ {illegal,0 }, /* e2: 0111 0100 1110 0010 */
+ {illegal,0 }, /* e3: 0111 0100 1110 0011 */
+ {illegal,0 }, /* e4: 0111 0100 1110 0100 */
+ {DSUB,"EA,BC" }, /* e5: 0111 0100 1110 0101 */
+ {DSUB,"EA,DE" }, /* e6: 0111 0100 1110 0110 */
+ {DSUB,"EA,HL" }, /* e7: 0111 0100 1110 0111 */
+ {NEAW,"%a" }, /* e8: 0111 0100 1110 1000 oooo oooo */
+ {illegal,0 }, /* e9: 0111 0100 1110 1001 */
+ {illegal,0 }, /* ea: 0111 0100 1110 1010 */
+ {illegal,0 }, /* eb: 0111 0100 1110 1011 */
+ {illegal,0 }, /* ec: 0111 0100 1110 1100 */
+ {DNE,"EA,BC" }, /* ed: 0111 0100 1110 1101 */
+ {DNE,"EA,DE" }, /* ee: 0111 0100 1110 1110 */
+ {DNE,"EA,HL" }, /* ef: 0111 0100 1110 1111 */
+
+ {SBBW,"%a" }, /* f0: 0111 0100 1111 0000 oooo oooo */
+ {illegal,0 }, /* f1: 0111 0100 1111 0001 */
+ {illegal,0 }, /* f2: 0111 0100 1111 0010 */
+ {illegal,0 }, /* f3: 0111 0100 1111 0011 */
+ {illegal,0 }, /* f4: 0111 0100 1111 0100 */
+ {DSBB,"EA,BC" }, /* f5: 0111 0100 1111 0101 */
+ {DSBB,"EA,DE" }, /* f6: 0111 0100 1111 0110 */
+ {DSBB,"EA,HL" }, /* f7: 0111 0100 1111 0111 */
+ {EQAW,"%a" }, /* f8: 0111 0100 1111 1000 oooo oooo */
+ {illegal,0 }, /* f9: 0111 0100 1111 1001 */
+ {illegal,0 }, /* fa: 0111 0100 1111 1010 */
+ {illegal,0 }, /* fb: 0111 0100 1111 1011 */
+ {illegal,0 }, /* fc: 0111 0100 1111 1100 */
+ {DEQ,"EA,BC" }, /* fd: 0111 0100 1111 1101 */
+ {DEQ,"EA,DE" }, /* fe: 0111 0100 1111 1110 */
+ {DEQ,"EA,HL" } /* ff: 0111 0100 1111 1111 */
+};
+
+/* main opcodes */
+static const struct dasm_s dasmXX_7810[256] =
+{
+ {NOP,0 }, /* 00: 0000 0000 */
+ {LDAW,"%a" }, /* 01: 0000 0001 oooo oooo */
+ {INX,"SP" }, /* 02: 0000 0010 */
+ {DCX,"SP" }, /* 03: 0000 0011 */
+ {LXI,"SP,%w" }, /* 04: 0000 0100 llll llll hhhh hhhh */
+ {ANIW,"%a,%b" }, /* 05: 0000 0101 oooo oooo xxxx xxxx */
+ {illegal,0 }, /* 06: */
+ {ANI,"A,%b" }, /* 07: 0000 0111 xxxx xxxx */
+ {MOV,"A,EAH" }, /* 08: 0000 1000 */
+ {MOV,"A,EAL" }, /* 09: 0000 1001 */
+ {MOV,"A,B" }, /* 0a: 0000 1010 */
+ {MOV,"A,C" }, /* 0b: 0000 1011 */
+ {MOV,"A,D" }, /* 0c: 0000 1100 */
+ {MOV,"A,E" }, /* 0d: 0000 1101 */
+ {MOV,"A,H" }, /* 0e: 0000 1110 */
+ {MOV,"A,L" }, /* 0f: 0000 1111 */
+
+ {EXA,0 }, /* 10: 0001 0000 */ /* 7810 */
+ {EXX,0 }, /* 11: 0001 0001 */ /* 7810 */
+ {INX,"BC" }, /* 12: 0001 0010 */
+ {DCX,"BC" }, /* 13: 0001 0011 */
+ {LXI,"BC,%w" }, /* 14: 0001 0100 llll llll hhhh hhhh */
+ {ORIW,"%a,%b" }, /* 15: 0001 0101 oooo oooo xxxx xxxx */
+ {XRI,"A,%b" }, /* 16: 0001 0110 xxxx xxxx */
+ {ORI,"A,%b" }, /* 17: 0001 0111 xxxx xxxx */
+ {MOV,"EAH,A" }, /* 18: 0001 1000 */
+ {MOV,"EAL,A" }, /* 19: 0001 1001 */
+ {MOV,"B,A" }, /* 1a: 0001 1010 */
+ {MOV,"C,A" }, /* 1b: 0001 1011 */
+ {MOV,"D,A" }, /* 1c: 0001 1100 */
+ {MOV,"E,A" }, /* 1d: 0001 1101 */
+ {MOV,"H,A" }, /* 1e: 0001 1110 */
+ {MOV,"L,A" }, /* 1f: 0001 1111 */
+
+ {INRW,"%a" }, /* 20: 0010 0000 oooo oooo */
+ {JB,0 }, /* 21: 0010 0001 */
+ {INX,"DE" }, /* 22: 0010 0010 */
+ {DCX,"DE" }, /* 23: 0010 0011 */
+ {LXI,"DE,%w" }, /* 24: 0010 0100 llll llll hhhh hhhh */
+ {GTIW,"%a,%b" }, /* 25: 0010 0101 oooo oooo xxxx xxxx */
+ {ADINC,"A,%b" }, /* 26: 0010 0110 xxxx xxxx */
+ {GTI,"A,%b" }, /* 27: 0010 0111 xxxx xxxx */
+ {illegal,0 }, /* 28: 0010 1000 */
+ {LDAX,"(BC)" }, /* 29: 0010 1001 */
+ {LDAX,"(DE)" }, /* 2a: 0010 1010 */
+ {LDAX,"(HL)" }, /* 2b: 0010 1011 */
+ {LDAX,"(DE+)" }, /* 2c: 0010 1100 */
+ {LDAX,"(HL+)" }, /* 2d: 0010 1101 */
+ {LDAX,"(DE-)" }, /* 2e: 0010 1110 */
+ {LDAX,"(HL-)" }, /* 2f: 0010 1111 */
+
+ {DCRW,"%a" }, /* 30: 0011 0000 oooo oooo */
+ {BLOCK,0 }, /* 31: 0011 0001 */ /* 7810 */
+ {INX,"HL", }, /* 32: 0011 0010 */
+ {DCX,"HL", }, /* 33: 0011 0011 */
+ {LXI,"HL,%w" }, /* 34: 0011 0100 llll llll hhhh hhhh */
+ {LTIW,"%a,%b" }, /* 35: 0011 0101 oooo oooo xxxx xxxx */
+ {SUINB,"A,%b" }, /* 36: 0011 0110 xxxx xxxx */
+ {LTI,"A,%b" }, /* 37: 0011 0111 xxxx xxxx */
+ {illegal,0 }, /* 38: */
+ {STAX,"(BC)" }, /* 39: 0011 1001 */
+ {STAX,"(DE)" }, /* 3a: 0011 1010 */
+ {STAX,"(HL)" }, /* 3b: 0011 1011 */
+ {STAX,"(DE+)" }, /* 3c: 0011 1100 */
+ {STAX,"(HL+)" }, /* 3d: 0011 1101 */
+ {STAX,"(DE-)" }, /* 3e: 0011 1110 */
+ {STAX,"(HL-)" }, /* 3f: 0011 1111 */
+
+ {CALL,"%w" }, /* 40: 0100 0000 llll llll hhhh hhhh */
+ {INR,"A" }, /* 41: 0100 0001 */
+ {INR,"B" }, /* 42: 0100 0010 */
+ {INR,"C" }, /* 43: 0100 0011 */
+ {LXI,"EA,%w" }, /* 44: 0100 0100 llll llll hhhh hhhh */
+ {ONIW,"%a,%b" }, /* 45: 0100 0101 oooo oooo xxxx xxxx */
+ {ADI,"A,%b" }, /* 46: 0100 0110 xxxx xxxx */
+ {ONI,"A,%b" }, /* 47: 0100 0111 xxxx xxxx */
+ {0,dasm48_7810 }, /* 48: prefix */
+ {MVIX,"BC,%b" }, /* 49: 0100 1001 xxxx xxxx */
+ {MVIX,"DE,%b" }, /* 4a: 0100 1010 xxxx xxxx */
+ {MVIX,"HL,%b" }, /* 4b: 0100 1011 xxxx xxxx */
+ {0,dasm4C_7810 }, /* 4c: prefix */
+ {0,dasm4D_7810 }, /* 4d: prefix */
+ {JRE,"%d" }, /* 4e: 0100 111d dddd dddd */
+ {JRE,"%d" }, /* 4f: 0100 111d dddd dddd */
+
+ {EXH,0 }, /* 50: 0101 0000 */ /* 7810 */
+ {DCR,"A" }, /* 51: 0101 0001 */
+ {DCR,"B" }, /* 52: 0101 0010 */
+ {DCR,"C" }, /* 53: 0101 0011 */
+ {JMP,"%w" }, /* 54: 0101 0100 llll llll hhhh hhhh */
+ {OFFIW,"%a,%b" }, /* 55: 0101 0101 oooo oooo xxxx xxxx */
+ {ACI,"A,%b" }, /* 56: 0101 0110 xxxx xxxx */
+ {OFFI,"A,%b" }, /* 57: 0101 0111 xxxx xxxx */
+ {BIT,"0,%a", }, /* 58: 0101 1000 oooo oooo */ /* 7810 */
+ {BIT,"1,%a", }, /* 59: 0101 1001 oooo oooo */ /* 7810 */
+ {BIT,"2,%a", }, /* 5a: 0101 1010 oooo oooo */ /* 7810 */
+ {BIT,"3,%a", }, /* 5b: 0101 1011 oooo oooo */ /* 7810 */
+ {BIT,"4,%a", }, /* 5c: 0101 1100 oooo oooo */ /* 7810 */
+ {BIT,"5,%a", }, /* 5d: 0101 1101 oooo oooo */ /* 7810 */
+ {BIT,"6,%a", }, /* 5e: 0101 1110 oooo oooo */ /* 7810 */
+ {BIT,"7,%a", }, /* 5f: 0101 1111 oooo oooo */ /* 7810 */
+
+ {0,dasm60 }, /* 60: prefix */
+ {DAA,0 }, /* 61: 0110 0001 */
+ {RETI,0 }, /* 62: 0110 0010 */
+ {STAW,"%a" }, /* 63: 0110 0011 oooo oooo */
+ {0,dasm64_7810 }, /* 64: prefix */
+ {NEIW,"%a,%b" }, /* 65: 0110 0101 oooo oooo xxxx xxxx */
+ {SUI,"A,%b" }, /* 66: 0110 0110 xxxx xxxx */
+ {NEI,"A,%b" }, /* 67: 0110 0111 xxxx xxxx */
+ {MVI,"V,%b" }, /* 68: 0110 1000 xxxx xxxx */
+ {MVI,"A,%b" }, /* 69: 0110 1001 xxxx xxxx */
+ {MVI,"B,%b" }, /* 6a: 0110 1010 xxxx xxxx */
+ {MVI,"C,%b" }, /* 6b: 0110 1011 xxxx xxxx */
+ {MVI,"D,%b" }, /* 6c: 0110 1100 xxxx xxxx */
+ {MVI,"E,%b" }, /* 6d: 0110 1101 xxxx xxxx */
+ {MVI,"H,%b" }, /* 6e: 0110 1110 xxxx xxxx */
+ {MVI,"L,%b" }, /* 6f: 0110 1111 xxxx xxxx */
+
+ {0,dasm70 }, /* 70: prefix */
+ {MVIW,"%a,%b" }, /* 71: 0111 0001 oooo oooo xxxx xxxx */
+ {SOFTI,0 }, /* 72: 0111 0010 */
+ {illegal,0 }, /* 73: */
+ {0,dasm74 }, /* 74: prefix */
+ {EQIW,"%a,%b" }, /* 75: 0111 0101 oooo oooo xxxx xxxx */
+ {SBI,"A,%b" }, /* 76: 0111 0110 xxxx xxxx */
+ {EQI,"A,%b" }, /* 77: 0111 0111 xxxx xxxx */
+ {CALF,"%f" }, /* 78: 0111 1ddd dddd dddd */
+ {CALF,"%f" }, /* 79: 0111 1ddd dddd dddd */
+ {CALF,"%f" }, /* 7a: 0111 1ddd dddd dddd */
+ {CALF,"%f" }, /* 7b: 0111 1ddd dddd dddd */
+ {CALF,"%f" }, /* 7c: 0111 1ddd dddd dddd */
+ {CALF,"%f" }, /* 7d: 0111 1ddd dddd dddd */
+ {CALF,"%f" }, /* 7e: 0111 1ddd dddd dddd */
+ {CALF,"%f" }, /* 7f: 0111 1ddd dddd dddd */
+
+ {CALT,"%t" }, /* 80: 100t tttt */
+ {CALT,"%t" }, /* 81: 100t tttt */
+ {CALT,"%t" }, /* 82: 100t tttt */
+ {CALT,"%t" }, /* 83: 100t tttt */
+ {CALT,"%t" }, /* 84: 100t tttt */
+ {CALT,"%t" }, /* 85: 100t tttt */
+ {CALT,"%t" }, /* 86: 100t tttt */
+ {CALT,"%t" }, /* 87: 100t tttt */
+ {CALT,"%t" }, /* 88: 100t tttt */
+ {CALT,"%t" }, /* 89: 100t tttt */
+ {CALT,"%t" }, /* 8a: 100t tttt */
+ {CALT,"%t" }, /* 8b: 100t tttt */
+ {CALT,"%t" }, /* 8c: 100t tttt */
+ {CALT,"%t" }, /* 8d: 100t tttt */
+ {CALT,"%t" }, /* 8e: 100t tttt */
+ {CALT,"%t" }, /* 8f: 100t tttt */
+
+ {CALT,"%t" }, /* 90: 100t tttt */
+ {CALT,"%t" }, /* 91: 100t tttt */
+ {CALT,"%t" }, /* 92: 100t tttt */
+ {CALT,"%t" }, /* 93: 100t tttt */
+ {CALT,"%t" }, /* 94: 100t tttt */
+ {CALT,"%t" }, /* 95: 100t tttt */
+ {CALT,"%t" }, /* 96: 100t tttt */
+ {CALT,"%t" }, /* 97: 100t tttt */
+ {CALT,"%t" }, /* 98: 100t tttt */
+ {CALT,"%t" }, /* 99: 100t tttt */
+ {CALT,"%t" }, /* 9a: 100t tttt */
+ {CALT,"%t" }, /* 9b: 100t tttt */
+ {CALT,"%t" }, /* 9c: 100t tttt */
+ {CALT,"%t" }, /* 9d: 100t tttt */
+ {CALT,"%t" }, /* 9e: 100t tttt */
+ {CALT,"%t" }, /* 9f: 100t tttt */
+
+ {POP,"VA" }, /* a0: 1010 0000 */
+ {POP,"BC" }, /* a1: 1010 0001 */
+ {POP,"DE" }, /* a2: 1010 0010 */
+ {POP,"HL", }, /* a3: 1010 0011 */
+ {POP,"EA" }, /* a4: 1010 0100 */
+ {DMOV,"EA,BC" }, /* a5: 1010 0101 */
+ {DMOV,"EA,DE" }, /* a6: 1010 0110 */
+ {DMOV,"EA,HL" }, /* a7: 1010 0111 */
+ {INX,"EA" }, /* a8: 1010 1000 */
+ {DCX,"EA" }, /* a9: 1010 1001 */
+ {EI,0 }, /* aa: 1010 1010 */
+ {LDAX,"(DE+%b)" }, /* ab: 1010 1011 dddd dddd */
+ {LDAX,"(HL+A)" }, /* ac: 1010 1100 */
+ {LDAX,"(HL+B)" }, /* ad: 1010 1101 */
+ {LDAX,"(HL+EA)" }, /* ae: 1010 1110 */
+ {LDAX,"(HL+%b)" }, /* af: 1010 1111 dddd dddd */
+
+ {PUSH,"VA" }, /* b0: 1011 0000 */
+ {PUSH,"BC" }, /* b1: 1011 0001 */
+ {PUSH,"DE" }, /* b2: 1011 0010 */
+ {PUSH,"HL", }, /* b3: 1011 0011 */
+ {PUSH,"EA" }, /* b4: 1011 0100 */
+ {DMOV,"BC,EA" }, /* b5: 1011 0101 */
+ {DMOV,"DE,EA" }, /* b6: 1011 0110 */
+ {DMOV,"HL,EA" }, /* b7: 1011 0111 */
+ {RET,0 }, /* b8: 1011 1000 */
+ {RETS,0 }, /* b9: 1011 1001 */
+ {DI,0 }, /* ba: 1011 1010 */
+ {STAX,"(DE+%b)" }, /* bb: 1011 1011 dddd dddd */
+ {STAX,"(HL+A)" }, /* bc: 1011 1100 */
+ {STAX,"(HL+B)" }, /* bd: 1011 1101 */
+ {STAX,"(HL+EA)" }, /* be: 1011 1110 */
+ {STAX,"(HL+%b)" }, /* bf: 1011 1111 dddd dddd */
+
+ {JR,"%o" }, /* c0: 11oo oooo */
+ {JR,"%o" }, /* c1: 11oo oooo */
+ {JR,"%o" }, /* c2: 11oo oooo */
+ {JR,"%o" }, /* c3: 11oo oooo */
+ {JR,"%o" }, /* c4: 11oo oooo */
+ {JR,"%o" }, /* c5: 11oo oooo */
+ {JR,"%o" }, /* c6: 11oo oooo */
+ {JR,"%o" }, /* c7: 11oo oooo */
+ {JR,"%o" }, /* c8: 11oo oooo */
+ {JR,"%o" }, /* c9: 11oo oooo */
+ {JR,"%o" }, /* ca: 11oo oooo */
+ {JR,"%o" }, /* cb: 11oo oooo */
+ {JR,"%o" }, /* cc: 11oo oooo */
+ {JR,"%o" }, /* cd: 11oo oooo */
+ {JR,"%o" }, /* ce: 11oo oooo */
+ {JR,"%o" }, /* cf: 11oo oooo */
+
+ {JR,"%o" }, /* d0: 11oo oooo */
+ {JR,"%o" }, /* d1: 11oo oooo */
+ {JR,"%o" }, /* d2: 11oo oooo */
+ {JR,"%o" }, /* d3: 11oo oooo */
+ {JR,"%o" }, /* d4: 11oo oooo */
+ {JR,"%o" }, /* d5: 11oo oooo */
+ {JR,"%o" }, /* d6: 11oo oooo */
+ {JR,"%o" }, /* d7: 11oo oooo */
+ {JR,"%o" }, /* d8: 11oo oooo */
+ {JR,"%o" }, /* d9: 11oo oooo */
+ {JR,"%o" }, /* da: 11oo oooo */
+ {JR,"%o" }, /* db: 11oo oooo */
+ {JR,"%o" }, /* dc: 11oo oooo */
+ {JR,"%o" }, /* dd: 11oo oooo */
+ {JR,"%o" }, /* de: 11oo oooo */
+ {JR,"%o" }, /* df: 11oo oooo */
+
+ {JR,"%o" }, /* e0: 11oo oooo */
+ {JR,"%o" }, /* e1: 11oo oooo */
+ {JR,"%o" }, /* e2: 11oo oooo */
+ {JR,"%o" }, /* e3: 11oo oooo */
+ {JR,"%o" }, /* e4: 11oo oooo */
+ {JR,"%o" }, /* e5: 11oo oooo */
+ {JR,"%o" }, /* e6: 11oo oooo */
+ {JR,"%o" }, /* e7: 11oo oooo */
+ {JR,"%o" }, /* e8: 11oo oooo */
+ {JR,"%o" }, /* e9: 11oo oooo */
+ {JR,"%o" }, /* ea: 11oo oooo */
+ {JR,"%o" }, /* eb: 11oo oooo */
+ {JR,"%o" }, /* ec: 11oo oooo */
+ {JR,"%o" }, /* ed: 11oo oooo */
+ {JR,"%o" }, /* ee: 11oo oooo */
+ {JR,"%o" }, /* ef: 11oo oooo */
+
+ {JR,"%o" }, /* f0: 11oo oooo */
+ {JR,"%o" }, /* f1: 11oo oooo */
+ {JR,"%o" }, /* f2: 11oo oooo */
+ {JR,"%o" }, /* f3: 11oo oooo */
+ {JR,"%o" }, /* f4: 11oo oooo */
+ {JR,"%o" }, /* f5: 11oo oooo */
+ {JR,"%o" }, /* f6: 11oo oooo */
+ {JR,"%o" }, /* f7: 11oo oooo */
+ {JR,"%o" }, /* f8: 11oo oooo */
+ {JR,"%o" }, /* f9: 11oo oooo */
+ {JR,"%o" }, /* fa: 11oo oooo */
+ {JR,"%o" }, /* fb: 11oo oooo */
+ {JR,"%o" }, /* fc: 11oo oooo */
+ {JR,"%o" }, /* fd: 11oo oooo */
+ {JR,"%o" }, /* fe: 11oo oooo */
+ {JR,"%o" } /* ff: 11oo oooo */
+};
+
+static const struct dasm_s dasmXX_7807[256] =
+{
+ {NOP,0 }, /* 00: 0000 0000 */
+ {LDAW,"%a" }, /* 01: 0000 0001 oooo oooo */
+ {INX,"SP" }, /* 02: 0000 0010 */
+ {DCX,"SP" }, /* 03: 0000 0011 */
+ {LXI,"SP,%w" }, /* 04: 0000 0100 llll llll hhhh hhhh */
+ {ANIW,"%a,%b" }, /* 05: 0000 0101 oooo oooo xxxx xxxx */
+ {illegal,0 }, /* 06: */
+ {ANI,"A,%b" }, /* 07: 0000 0111 xxxx xxxx */
+ {MOV,"A,EAH" }, /* 08: 0000 1000 */
+ {MOV,"A,EAL" }, /* 09: 0000 1001 */
+ {MOV,"A,B" }, /* 0a: 0000 1010 */
+ {MOV,"A,C" }, /* 0b: 0000 1011 */
+ {MOV,"A,D" }, /* 0c: 0000 1100 */
+ {MOV,"A,E" }, /* 0d: 0000 1101 */
+ {MOV,"A,H" }, /* 0e: 0000 1110 */
+ {MOV,"A,L" }, /* 0f: 0000 1111 */
+
+ {BLOCK,"D+" }, /* 10: 0001 0000 */ /* 7807 */
+ {BLOCK,"D-" }, /* 11: 0001 0001 */ /* 7807 */
+ {INX,"BC" }, /* 12: 0001 0010 */
+ {DCX,"BC" }, /* 13: 0001 0011 */
+ {LXI,"BC,%w" }, /* 14: 0001 0100 llll llll hhhh hhhh */
+ {ORIW,"%a,%b" }, /* 15: 0001 0101 oooo oooo xxxx xxxx */
+ {XRI,"A,%b" }, /* 16: 0001 0110 xxxx xxxx */
+ {ORI,"A,%b" }, /* 17: 0001 0111 xxxx xxxx */
+ {MOV,"EAH,A" }, /* 18: 0001 1000 */
+ {MOV,"EAL,A" }, /* 19: 0001 1001 */
+ {MOV,"B,A" }, /* 1a: 0001 1010 */
+ {MOV,"C,A" }, /* 1b: 0001 1011 */
+ {MOV,"D,A" }, /* 1c: 0001 1100 */
+ {MOV,"E,A" }, /* 1d: 0001 1101 */
+ {MOV,"H,A" }, /* 1e: 0001 1110 */
+ {MOV,"L,A" }, /* 1f: 0001 1111 */
+
+ {INRW,"%a" }, /* 20: 0010 0000 oooo oooo */
+ {JB,0 }, /* 21: 0010 0001 */
+ {INX,"DE" }, /* 22: 0010 0010 */
+ {DCX,"DE" }, /* 23: 0010 0011 */
+ {LXI,"DE,%w" }, /* 24: 0010 0100 llll llll hhhh hhhh */
+ {GTIW,"%a,%b" }, /* 25: 0010 0101 oooo oooo xxxx xxxx */
+ {ADINC,"A,%b" }, /* 26: 0010 0110 xxxx xxxx */
+ {GTI,"A,%b" }, /* 27: 0010 0111 xxxx xxxx */
+ {illegal,0 }, /* 28: 0010 1000 */
+ {LDAX,"(BC)" }, /* 29: 0010 1001 */
+ {LDAX,"(DE)" }, /* 2a: 0010 1010 */
+ {LDAX,"(HL)" }, /* 2b: 0010 1011 */
+ {LDAX,"(DE+)" }, /* 2c: 0010 1100 */
+ {LDAX,"(HL+)" }, /* 2d: 0010 1101 */
+ {LDAX,"(DE-)" }, /* 2e: 0010 1110 */
+ {LDAX,"(HL-)" }, /* 2f: 0010 1111 */
+
+ {DCRW,"%a" }, /* 30: 0011 0000 oooo oooo */
+ {AND,"CY,%i" }, /* 31: 0011 0001 bbbb bbbb */ /* 7807 */
+ {INX,"HL", }, /* 32: 0011 0010 */
+ {DCX,"HL", }, /* 33: 0011 0011 */
+ {LXI,"HL,%w" }, /* 34: 0011 0100 llll llll hhhh hhhh */
+ {LTIW,"%a,%b" }, /* 35: 0011 0101 oooo oooo xxxx xxxx */
+ {SUINB,"A,%b" }, /* 36: 0011 0110 xxxx xxxx */
+ {LTI,"A,%b" }, /* 37: 0011 0111 xxxx xxxx */
+ {illegal,0 }, /* 38: */
+ {STAX,"(BC)" }, /* 39: 0011 1001 */
+ {STAX,"(DE)" }, /* 3a: 0011 1010 */
+ {STAX,"(HL)" }, /* 3b: 0011 1011 */
+ {STAX,"(DE+)" }, /* 3c: 0011 1100 */
+ {STAX,"(HL+)" }, /* 3d: 0011 1101 */
+ {STAX,"(DE-)" }, /* 3e: 0011 1110 */
+ {STAX,"(HL-)" }, /* 3f: 0011 1111 */
+
+ {CALL,"%w" }, /* 40: 0100 0000 llll llll hhhh hhhh */
+ {INR,"A" }, /* 41: 0100 0001 */
+ {INR,"B" }, /* 42: 0100 0010 */
+ {INR,"C" }, /* 43: 0100 0011 */
+ {LXI,"EA,%w" }, /* 44: 0100 0100 llll llll hhhh hhhh */
+ {ONIW,"%a,%b" }, /* 45: 0100 0101 oooo oooo xxxx xxxx */
+ {ADI,"A,%b" }, /* 46: 0100 0110 xxxx xxxx */
+ {ONI,"A,%b" }, /* 47: 0100 0111 xxxx xxxx */
+ {0,dasm48_7807 }, /* 48: prefix */
+ {MVIX,"BC,%b" }, /* 49: 0100 1001 xxxx xxxx */
+ {MVIX,"DE,%b" }, /* 4a: 0100 1010 xxxx xxxx */
+ {MVIX,"HL,%b" }, /* 4b: 0100 1011 xxxx xxxx */
+ {0,dasm4C_7807 }, /* 4c: prefix */
+ {0,dasm4D_7807 }, /* 4d: prefix */
+ {JRE,"%d" }, /* 4e: 0100 111d dddd dddd */
+ {JRE,"%d" }, /* 4f: 0100 111d dddd dddd */
+ {SKN,"%i" }, /* 50: 0101 0000 bbbb bbbb */ /* 7807 */
+ {DCR,"A" }, /* 51: 0101 0001 */
+ {DCR,"B" }, /* 52: 0101 0010 */
+ {DCR,"C" }, /* 53: 0101 0011 */
+ {JMP,"%w" }, /* 54: 0101 0100 llll llll hhhh hhhh */
+ {OFFIW,"%a,%b" }, /* 55: 0101 0101 oooo oooo xxxx xxxx */
+ {ACI,"A,%b" }, /* 56: 0101 0110 xxxx xxxx */
+ {OFFI,"A,%b" }, /* 57: 0101 0111 xxxx xxxx */
+ {SETB,"%i" }, /* 58: 0101 1000 bbbb bbbb */ /* 7807 */
+ {NOT,"%i" }, /* 59: 0101 1001 bbbb bbbb */ /* 7807 */
+ {MOV,"%i,CY" }, /* 5a: 0101 1010 bbbb bbbb */ /* 7807 */
+ {CLR,"%i" }, /* 5b: 0101 1011 bbbb bbbb */ /* 7807 */
+ {OR,"CY,%i" }, /* 5c: 0101 1100 bbbb bbbb */ /* 7807 */
+ {SK,"%i" }, /* 5d: 0101 1101 bbbb bbbb */ /* 7807 */
+ {XOR,"CY,%i" }, /* 5e: 0101 1110 bbbb bbbb */ /* 7807 */
+ {MOV,"CY,%i" }, /* 5f: 0101 1111 bbbb bbbb */ /* 7807 */
+
+ {0,dasm60 }, /* 60: prefix */
+ {DAA,0 }, /* 61: 0110 0001 */
+ {RETI,0 }, /* 62: 0110 0010 */
+ {STAW,"%a" }, /* 63: 0110 0011 oooo oooo */
+ {0,dasm64_7807 }, /* 64: prefix */
+ {NEIW,"%a,%b" }, /* 65: 0110 0101 oooo oooo xxxx xxxx */
+ {SUI,"A,%b" }, /* 66: 0110 0110 xxxx xxxx */
+ {NEI,"A,%b" }, /* 67: 0110 0111 xxxx xxxx */
+ {MVI,"V,%b" }, /* 68: 0110 1000 xxxx xxxx */
+ {MVI,"A,%b" }, /* 69: 0110 1001 xxxx xxxx */
+ {MVI,"B,%b" }, /* 6a: 0110 1010 xxxx xxxx */
+ {MVI,"C,%b" }, /* 6b: 0110 1011 xxxx xxxx */
+ {MVI,"D,%b" }, /* 6c: 0110 1100 xxxx xxxx */
+ {MVI,"E,%b" }, /* 6d: 0110 1101 xxxx xxxx */
+ {MVI,"H,%b" }, /* 6e: 0110 1110 xxxx xxxx */
+ {MVI,"L,%b" }, /* 6f: 0110 1111 xxxx xxxx */
+
+ {0,dasm70 }, /* 70: prefix */
+ {MVIW,"%a,%b" }, /* 71: 0111 0001 oooo oooo xxxx xxxx */
+ {SOFTI,0 }, /* 72: 0111 0010 */
+ {illegal,0 }, /* 73: */
+ {0,dasm74 }, /* 74: prefix */
+ {EQIW,"%a,%b" }, /* 75: 0111 0101 oooo oooo xxxx xxxx */
+ {SBI,"A,%b" }, /* 76: 0111 0110 xxxx xxxx */
+ {EQI,"A,%b" }, /* 77: 0111 0111 xxxx xxxx */
+ {CALF,"%f" }, /* 78: 0111 1ddd dddd dddd */
+ {CALF,"%f" }, /* 79: 0111 1ddd dddd dddd */
+ {CALF,"%f" }, /* 7a: 0111 1ddd dddd dddd */
+ {CALF,"%f" }, /* 7b: 0111 1ddd dddd dddd */
+ {CALF,"%f" }, /* 7c: 0111 1ddd dddd dddd */
+ {CALF,"%f" }, /* 7d: 0111 1ddd dddd dddd */
+ {CALF,"%f" }, /* 7e: 0111 1ddd dddd dddd */
+ {CALF,"%f" }, /* 7f: 0111 1ddd dddd dddd */
+
+ {CALT,"%t" }, /* 80: 100t tttt */
+ {CALT,"%t" }, /* 81: 100t tttt */
+ {CALT,"%t" }, /* 82: 100t tttt */
+ {CALT,"%t" }, /* 83: 100t tttt */
+ {CALT,"%t" }, /* 84: 100t tttt */
+ {CALT,"%t" }, /* 85: 100t tttt */
+ {CALT,"%t" }, /* 86: 100t tttt */
+ {CALT,"%t" }, /* 87: 100t tttt */
+ {CALT,"%t" }, /* 88: 100t tttt */
+ {CALT,"%t" }, /* 89: 100t tttt */
+ {CALT,"%t" }, /* 8a: 100t tttt */
+ {CALT,"%t" }, /* 8b: 100t tttt */
+ {CALT,"%t" }, /* 8c: 100t tttt */
+ {CALT,"%t" }, /* 8d: 100t tttt */
+ {CALT,"%t" }, /* 8e: 100t tttt */
+ {CALT,"%t" }, /* 8f: 100t tttt */
+
+ {CALT,"%t" }, /* 90: 100t tttt */
+ {CALT,"%t" }, /* 91: 100t tttt */
+ {CALT,"%t" }, /* 92: 100t tttt */
+ {CALT,"%t" }, /* 93: 100t tttt */
+ {CALT,"%t" }, /* 94: 100t tttt */
+ {CALT,"%t" }, /* 95: 100t tttt */
+ {CALT,"%t" }, /* 96: 100t tttt */
+ {CALT,"%t" }, /* 97: 100t tttt */
+ {CALT,"%t" }, /* 98: 100t tttt */
+ {CALT,"%t" }, /* 99: 100t tttt */
+ {CALT,"%t" }, /* 9a: 100t tttt */
+ {CALT,"%t" }, /* 9b: 100t tttt */
+ {CALT,"%t" }, /* 9c: 100t tttt */
+ {CALT,"%t" }, /* 9d: 100t tttt */
+ {CALT,"%t" }, /* 9e: 100t tttt */
+ {CALT,"%t" }, /* 9f: 100t tttt */
+
+ {POP,"VA" }, /* a0: 1010 0000 */
+ {POP,"BC" }, /* a1: 1010 0001 */
+ {POP,"DE" }, /* a2: 1010 0010 */
+ {POP,"HL", }, /* a3: 1010 0011 */
+ {POP,"EA" }, /* a4: 1010 0100 */
+ {DMOV,"EA,BC" }, /* a5: 1010 0101 */
+ {DMOV,"EA,DE" }, /* a6: 1010 0110 */
+ {DMOV,"EA,HL" }, /* a7: 1010 0111 */
+ {INX,"EA" }, /* a8: 1010 1000 */
+ {DCX,"EA" }, /* a9: 1010 1001 */
+ {EI,0 }, /* aa: 1010 1010 */
+ {LDAX,"(DE+%b)" }, /* ab: 1010 1011 dddd dddd */
+ {LDAX,"(HL+A)" }, /* ac: 1010 1100 */
+ {LDAX,"(HL+B)" }, /* ad: 1010 1101 */
+ {LDAX,"(HL+EA)" }, /* ae: 1010 1110 */
+ {LDAX,"(HL+%b)" }, /* af: 1010 1111 dddd dddd */
+
+ {PUSH,"VA" }, /* b0: 1011 0000 */
+ {PUSH,"BC" }, /* b1: 1011 0001 */
+ {PUSH,"DE" }, /* b2: 1011 0010 */
+ {PUSH,"HL", }, /* b3: 1011 0011 */
+ {PUSH,"EA" }, /* b4: 1011 0100 */
+ {DMOV,"BC,EA" }, /* b5: 1011 0101 */
+ {DMOV,"DE,EA" }, /* b6: 1011 0110 */
+ {DMOV,"HL,EA" }, /* b7: 1011 0111 */
+ {RET,0 }, /* b8: 1011 1000 */
+ {RETS,0 }, /* b9: 1011 1001 */
+ {DI,0 }, /* ba: 1011 1010 */
+ {STAX,"(DE+%b)" }, /* bb: 1011 1011 dddd dddd */
+ {STAX,"(HL+A)" }, /* bc: 1011 1100 */
+ {STAX,"(HL+B)" }, /* bd: 1011 1101 */
+ {STAX,"(HL+EA)" }, /* be: 1011 1110 */
+ {STAX,"(HL+%b)" }, /* bf: 1011 1111 dddd dddd */
+
+ {JR,"%o" }, /* c0: 11oo oooo */
+ {JR,"%o" }, /* c1: 11oo oooo */
+ {JR,"%o" }, /* c2: 11oo oooo */
+ {JR,"%o" }, /* c3: 11oo oooo */
+ {JR,"%o" }, /* c4: 11oo oooo */
+ {JR,"%o" }, /* c5: 11oo oooo */
+ {JR,"%o" }, /* c6: 11oo oooo */
+ {JR,"%o" }, /* c7: 11oo oooo */
+ {JR,"%o" }, /* c8: 11oo oooo */
+ {JR,"%o" }, /* c9: 11oo oooo */
+ {JR,"%o" }, /* ca: 11oo oooo */
+ {JR,"%o" }, /* cb: 11oo oooo */
+ {JR,"%o" }, /* cc: 11oo oooo */
+ {JR,"%o" }, /* cd: 11oo oooo */
+ {JR,"%o" }, /* ce: 11oo oooo */
+ {JR,"%o" }, /* cf: 11oo oooo */
+
+ {JR,"%o" }, /* d0: 11oo oooo */
+ {JR,"%o" }, /* d1: 11oo oooo */
+ {JR,"%o" }, /* d2: 11oo oooo */
+ {JR,"%o" }, /* d3: 11oo oooo */
+ {JR,"%o" }, /* d4: 11oo oooo */
+ {JR,"%o" }, /* d5: 11oo oooo */
+ {JR,"%o" }, /* d6: 11oo oooo */
+ {JR,"%o" }, /* d7: 11oo oooo */
+ {JR,"%o" }, /* d8: 11oo oooo */
+ {JR,"%o" }, /* d9: 11oo oooo */
+ {JR,"%o" }, /* da: 11oo oooo */
+ {JR,"%o" }, /* db: 11oo oooo */
+ {JR,"%o" }, /* dc: 11oo oooo */
+ {JR,"%o" }, /* dd: 11oo oooo */
+ {JR,"%o" }, /* de: 11oo oooo */
+ {JR,"%o" }, /* df: 11oo oooo */
+
+ {JR,"%o" }, /* e0: 11oo oooo */
+ {JR,"%o" }, /* e1: 11oo oooo */
+ {JR,"%o" }, /* e2: 11oo oooo */
+ {JR,"%o" }, /* e3: 11oo oooo */
+ {JR,"%o" }, /* e4: 11oo oooo */
+ {JR,"%o" }, /* e5: 11oo oooo */
+ {JR,"%o" }, /* e6: 11oo oooo */
+ {JR,"%o" }, /* e7: 11oo oooo */
+ {JR,"%o" }, /* e8: 11oo oooo */
+ {JR,"%o" }, /* e9: 11oo oooo */
+ {JR,"%o" }, /* ea: 11oo oooo */
+ {JR,"%o" }, /* eb: 11oo oooo */
+ {JR,"%o" }, /* ec: 11oo oooo */
+ {JR,"%o" }, /* ed: 11oo oooo */
+ {JR,"%o" }, /* ee: 11oo oooo */
+ {JR,"%o" }, /* ef: 11oo oooo */
+
+ {JR,"%o" }, /* f0: 11oo oooo */
+ {JR,"%o" }, /* f1: 11oo oooo */
+ {JR,"%o" }, /* f2: 11oo oooo */
+ {JR,"%o" }, /* f3: 11oo oooo */
+ {JR,"%o" }, /* f4: 11oo oooo */
+ {JR,"%o" }, /* f5: 11oo oooo */
+ {JR,"%o" }, /* f6: 11oo oooo */
+ {JR,"%o" }, /* f7: 11oo oooo */
+ {JR,"%o" }, /* f8: 11oo oooo */
+ {JR,"%o" }, /* f9: 11oo oooo */
+ {JR,"%o" }, /* fa: 11oo oooo */
+ {JR,"%o" }, /* fb: 11oo oooo */
+ {JR,"%o" }, /* fc: 11oo oooo */
+ {JR,"%o" }, /* fd: 11oo oooo */
+ {JR,"%o" }, /* fe: 11oo oooo */
+ {JR,"%o" } /* ff: 11oo oooo */
+};
+
+/*********************************************************
+ *
+ * uPD7801
+ *
+ *********************************************************/
+
+static const struct dasm_s dasm48_7801[256] = {
+ /* 0x00 - 0x3F */
+ { SKIT, "F0" }, { SKIT, "FT" }, { SKIT, "F1" }, { SKIT, "F2" },
+ { SKIT, "FS" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { SK, "CY" }, { illegal, 0 },
+ { SK, "Z" }, { illegal, 0 }, { PUSH, "VA" }, { POP, "VA" },
+
+ { SKNIT, "F0" }, { SKNIT, "FT" }, { SKNIT, "F1" }, { SKNIT, "F2" },
+ { SKNIT, "FS" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { SKN, "CY" }, { illegal, 0 },
+ { SKN, "Z" }, { illegal, 0 }, { PUSH, "BC" }, { POP, "BC" },
+
+ { EI, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { DI, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { CLC, 0 }, { STC, 0 },
+ { PER, 0 }, { PEX, 0 }, { PUSH, "DE" }, { POP, "DE" },
+
+ { RLL, "A" }, { RLR, "A" }, { RLL, "C" }, { RLR, "C" },
+ { SLL, "A" }, { SLR, "A" }, { SLL, "C" }, { SLR, "C" },
+ { RLD, 0 }, { RRD, 0 }, { illegal, 0 }, { illegal, 0 },
+ { PER, 0 }, { illegal, 0 }, { PUSH, "HL" }, { POP, "HL" },
+
+ /* 0x40 - 0x7F */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ /* 0x80 - 0xBF */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ /* 0xC0 - 0xFF */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 }
+};
+
+static const struct dasm_s dasm4c_7801[256] = {
+ /* 0x00 - 0x3F */
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+
+ /* 0x40 - 0x7F */
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+
+ /* 0x80 - 0xBF */
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+ { IN, 0 }, { IN, 0 }, { IN, 0 }, { IN, 0 },
+
+ /* 0xC0 - 0xFF */
+ { MOV, "A,PA" }, { MOV, "A,PB" }, { MOV, "A,PC" }, { MOV, "A,MK" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { MOV, "A,S" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 }
+};
+
+static const struct dasm_s dasm4d_7801[256] = {
+ /* 0x00 - 0x3F */
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+
+ /* 0x40 - 0x7F */
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+
+ /* 0x80 - 0xBF */
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+ { OUT, 0 }, { OUT, 0 }, { OUT, 0 }, { OUT, 0 },
+
+ /* 0xC0 - 0xFF */
+ { MOV, "PA,A" }, { MOV, "PB,A" }, { MOV, "PC,A" }, { MOV, "MK,A" },
+ { MOV, "MB,A" }, { MOV, "MC,A" }, { MOV, "TM0,A" }, { MOV, "TM1,A" },
+ { MOV, "S,A" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 }
+};
+
+static const struct dasm_s dasm60_7801[256] = {
+ /* 0x00 - 0x3F */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { ANA, "V,A" }, { ANA, "A,A" }, { ANA, "B,A" }, { ANA, "C,A" },
+ { ANA, "D,A" }, { ANA, "E,A" }, { ANA, "H,A" }, { ANA, "L,A" },
+
+ { XRA, "V,A" }, { XRA, "A,A" }, { XRA, "B,A" }, { XRA, "C,A" },
+ { XRA, "D,A" }, { XRA, "E,A" }, { XRA, "H,A" }, { XRA, "L,A" },
+ { ORA, "V,A" }, { ORA, "A,A" }, { ORA, "B,A" }, { ORA, "C,A" },
+ { ORA, "D,A" }, { ORA, "E,A" }, { ORA, "H,A" }, { ORA, "L,A" },
+
+ { ADDNC, "V,A" }, { ADDNC, "A,A" }, { ADDNC, "B,A" }, { ADDNC, "C,A" },
+ { ADDNC, "D,A" }, { ADDNC, "E,A" }, { ADDNC, "H,A" }, { ADDNC, "L,A" },
+ { GTA, "V,A" }, { GTA, "A,A" }, { GTA, "B,A" }, { GTA, "C,A" },
+ { GTA, "D,A" }, { GTA, "E,A" }, { GTA, "H,A" }, { GTA, "L,A" },
+
+ { SUBNB, "V,A" }, { SUBNB, "A,A" }, { SUBNB, "B,A" }, { SUBNB, "C,A" },
+ { SUBNB, "D,A" }, { SUBNB, "E,A" }, { SUBNB, "H,A" }, { SUBNB, "L,A" },
+ { LTA, "V,A" }, { LTA, "A,A" }, { LTA, "B,A" }, { LTA, "C,A" },
+ { LTA, "D,A" }, { LTA, "E,A" }, { LTA, "H,A" }, { LTA, "L,A" },
+
+ /* 0x40 - 0x7F */
+ { ADD, "V,A" }, { ADD, "A,A" }, { ADD, "B,A" }, { ADD, "C,A" },
+ { ADD, "D,A" }, { ADD, "E,A" }, { ADD, "H,A" }, { ADD, "L,A" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { ADC, "V,A" }, { ADC, "A,A" }, { ADC, "B,A" }, { ADC, "C,A" },
+ { ADC, "D,A" }, { ADC, "E,A" }, { ADC, "H,A" }, { ADC, "L,A" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { SUB, "V,A" }, { SUB, "A,A" }, { SUB, "B,A" }, { SUB, "C,A" },
+ { SUB, "D,A" }, { SUB, "E,A" }, { SUB, "H,A" }, { SUB, "L,A" },
+ { NEA, "V,A" }, { NEA, "A,A" }, { NEA, "B,A" }, { NEA, "C,A" },
+ { NEA, "D,A" }, { NEA, "E,A" }, { NEA, "H,A" }, { NEA, "L,A" },
+
+ { SBB, "V,A" }, { SBB, "A,A" }, { SBB, "B,A" }, { SBB, "C,A" },
+ { SBB, "D,A" }, { SBB, "E,A" }, { SBB, "H,A" }, { SBB, "L,A" },
+ { EQA, "V,A" }, { EQA, "A,A" }, { EQA, "B,A" }, { EQA, "C,A" },
+ { EQA, "D,A" }, { EQA, "E,A" }, { EQA, "H,A" }, { EQA, "L,A" },
+
+ /* 0x80 - 0xBF */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { ANA, "A,V" }, { ANA, "A,A" }, { ANA, "A,B" }, { ANA, "A,C" },
+ { ANA, "A,D" }, { ANA, "A,E" }, { ANA, "A,H" }, { ANA, "A,L" },
+
+ { XRA, "A,V" }, { XRA, "A,A" }, { XRA, "A,B" }, { XRA, "A,C" },
+ { XRA, "A,D" }, { XRA, "A,E" }, { XRA, "A,H" }, { XRA, "A,L" },
+ { ORA, "A,V" }, { ORA, "A,A" }, { ORA, "A,B" }, { ORA, "A,C" },
+ { ORA, "A,D" }, { ORA, "A,E" }, { ORA, "A,H" }, { ORA, "A,L" },
+
+ { ADDNC, "A,V" }, { ADDNC, "A,A" }, { ADDNC, "A,B" }, { ADDNC, "A,C" },
+ { ADDNC, "A,D" }, { ADDNC, "A,E" }, { ADDNC, "A,H" }, { ADDNC, "A,L" },
+ { GTA, "A,V" }, { GTA, "A,A" }, { GTA, "A,B" }, { GTA, "A,C" },
+ { GTA, "A,D" }, { GTA, "A,E" }, { GTA, "A,H" }, { GTA, "A,L" },
+
+ { SUBNB, "A,V" }, { SUBNB, "A,A" }, { SUBNB, "A,B" }, { SUBNB, "A,C" },
+ { SUBNB, "A,D" }, { SUBNB, "A,E" }, { SUBNB, "A,H" }, { SUBNB, "A,L" },
+ { LTA, "A,V" }, { LTA, "A,A" }, { LTA, "A,B" }, { LTA, "A,C" },
+ { LTA, "A,D" }, { LTA, "A,E" }, { LTA, "A,H" }, { LTA, "A,L" },
+
+ /* 0xC0 - 0xFF */
+ { ADD, "A,V" }, { ADD, "A,A" }, { ADD, "A,B" }, { ADD, "A,C" },
+ { ADD, "A,D" }, { ADD, "A,E" }, { ADD, "A,H" }, { ADD, "A,L" },
+ { ONA, "A,V" }, { ONA, "A,A" }, { ONA, "A,B" }, { ONA, "A,C" },
+ { ONA, "A,D" }, { ONA, "A,E" }, { ONA, "A,H" }, { ONA, "A,L" },
+
+ { ADC, "A,V" }, { ADC, "A,A" }, { ADC, "A,B" }, { ADC, "A,C" },
+ { ADC, "A,D" }, { ADC, "A,E" }, { ADC, "A,H" }, { ADC, "A,L" },
+ { OFFA, "A,V" }, { OFFA, "A,A" }, { OFFA, "A,B" }, { OFFA, "A,C" },
+ { OFFA, "A,D" }, { OFFA, "A,E" }, { OFFA, "A,H" }, { OFFA, "A,L" },
+
+ { SUB, "A,V" }, { SUB, "A,A" }, { SUB, "A,B" }, { SUB, "A,C" },
+ { SUB, "A,D" }, { SUB, "A,E" }, { SUB, "A,H" }, { SUB, "A,L" },
+ { NEA, "A,V" }, { NEA, "A,A" }, { NEA, "A,B" }, { NEA, "A,C" },
+ { NEA, "A,D" }, { NEA, "A,E" }, { NEA, "A,H" }, { NEA, "A,L" },
+
+ { SBB, "A,V" }, { SBB, "A,A" }, { SBB, "A,B" }, { SBB, "A,C" },
+ { SBB, "A,D" }, { SBB, "A,E" }, { SBB, "A,H" }, { SBB, "A,L" },
+ { EQA, "A,V" }, { EQA, "A,A" }, { EQA, "A,B" }, { EQA, "A,C" },
+ { EQA, "A,D" }, { EQA, "A,E" }, { EQA, "A,H" }, { EQA, "A,L" }
+};
+
+static const struct dasm_s dasm64_7801[256] = {
+ /* 0x00 - 0x3F */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { ANI, "V,%b" }, { ANI, "A,%b" }, { ANI, "B,%b" }, { ANI, "C,%b" },
+ { ANI, "D,%b" }, { ANI, "E,%b" }, { ANI, "H,%b" }, { ANI, "L,%b" },
+
+ { XRI, "V,%b" }, { XRI, "A,%b" }, { XRI, "B,%b" }, { XRI, "C,%b" },
+ { XRI, "D,%b" }, { XRI, "E,%b" }, { XRI, "H,%b" }, { XRI, "L,%b" },
+ { ORI, "V,%b" }, { ORI, "A,%b" }, { ORI, "B,%b" }, { ORI, "C,%b" },
+ { ORI, "D,%b" }, { ORI, "E,%b" }, { ORI, "H,%b" }, { ORI, "L,%b" },
+
+ { ADINC, "V,%b" }, { ADINC, "A,%b" }, { ADINC, "B,%b" }, { ADINC, "C,%b" },
+ { ADINC, "D,%b" }, { ADINC, "E,%b" }, { ADINC, "H,%b" }, { ADINC, "L,%b" },
+ { GTI, "V,%b" }, { GTI, "A,%b" }, { GTI, "B,%b" }, { GTI, "C,%b" },
+ { GTI, "D,%b" }, { GTI, "E,%b" }, { GTI, "H,%b" }, { GTI, "L,%b" },
+
+ { SUINB, "V,%b" }, { SUINB, "A,%b" }, { SUINB, "B,%b" }, { SUINB, "C,%b" },
+ { SUINB, "D,%b" }, { SUINB, "E,%b" }, { SUINB, "H,%b" }, { SUINB, "L,%b" },
+ { LTI, "V,%b" }, { LTI, "A,%b" }, { LTI, "B,%b" }, { LTI, "C,%b" },
+ { LTI, "D,%b" }, { LTI, "E,%b" }, { LTI, "H,%b" }, { LTI, "L,%b" },
+
+ /* 0x40 - 0x7F */
+ { ADI, "V,%b" }, { ADI, "A,%b" }, { ADI, "B,%b" }, { ADI, "C,%b" },
+ { ADI, "D,%b" }, { ADI, "E,%b" }, { ADI, "H,%b" }, { ADI, "L,%b" },
+ { ONI, "V,%b" }, { ONI, "A,%b" }, { ONI, "B,%b" }, { ONI, "C,%b" },
+ { ONI, "D,%b" }, { ONI, "E,%b" }, { ONI, "H,%b" }, { ONI, "L,%b" },
+
+ { ACI, "V,%b" }, { ACI, "A,%b" }, { ACI, "B,%b" }, { ACI, "C,%b" },
+ { ACI, "D,%b" }, { ACI, "E,%b" }, { ACI, "H,%b" }, { ACI, "L,%b" },
+ { OFFI, "V,%b" }, { OFFI, "A,%b" }, { OFFI, "B,%b" }, { OFFI, "C,%b" },
+ { OFFI, "D,%b" }, { OFFI, "E,%b" }, { OFFI, "H,%b" }, { OFFI, "L,%b" },
+
+ { SUI, "V,%b" }, { SUI, "A,%b" }, { SUI, "B,%b" }, { SUI, "C,%b" },
+ { SUI, "D,%b" }, { SUI, "E,%b" }, { SUI, "H,%b" }, { SUI, "L,%b" },
+ { NEI, "V,%b" }, { NEI, "A,%b" }, { NEI, "B,%b" }, { NEI, "C,%b" },
+ { NEI, "D,%b" }, { NEI, "E,%b" }, { NEI, "H,%b" }, { NEI, "L,%b" },
+
+ { SBI, "V,%b" }, { SBI, "A,%b" }, { SBI, "B,%b" }, { SBI, "C,%b" },
+ { SBI, "D,%b" }, { SBI, "E,%b" }, { SBI, "H,%b" }, { SBI, "L,%b" },
+ { EQI, "V,%b" }, { EQI, "A,%b" }, { EQI, "B,%b" }, { EQI, "C,%b" },
+ { EQI, "D,%b" }, { EQI, "E,%b" }, { EQI, "H,%b" }, { EQI, "L,%b" },
+
+ /* 0x80 - 0xBF */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { ANI, "PA,%b" }, { ANI, "PB,%b" }, { ANI, "PC,%b" }, { ANI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { XRI, "PA,%b" }, { XRI, "PB,%b" }, { XRI, "PC,%b" }, { XRI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { ORI, "PA,%b" }, { ORI, "PB,%b" }, { ORI, "PC,%b" }, { ORI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { ADINC, "PA,%b" }, { ADINC, "PB,%b" }, { ADINC, "PC,%b" }, { ADINC, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { GTI, "PA,%b" }, { GTI, "PB,%b" }, { GTI, "PC,%b" }, { GTI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { SUINB, "PA,%b" }, { SUINB, "PB,%b" }, { SUINB, "PC,%b" }, { SUINB, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { LTI, "PA,%b" }, { LTI, "PB,%b" }, { LTI, "PC,%b" }, { LTI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ /* 0xC0 - 0xFF */
+ { ADI, "PA,%b" }, { ADI, "PB,%b" }, { ADI, "PC,%b" }, { ADI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { ONI, "PA,%b" }, { ONI, "PB,%b" }, { ONI, "PC,%b" }, { ONI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { ACI, "PA,%b" }, { ACI, "PB,%b" }, { ACI, "PC,%b" }, { ACI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { OFFI, "PA,%b" }, { OFFI, "PB,%b" }, { OFFI, "PC,%b" }, { OFFI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { SUI, "PA,%b" }, { SUI, "PB,%b" }, { SUI, "PC,%b" }, { SUI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { NEI, "PA,%b" }, { NEI, "PB,%b" }, { NEI, "PC,%b" }, { NEI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { SBI, "PA,%b" }, { SBI, "PB,%b" }, { SBI, "PC,%b" }, { SBI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { EQI, "PA,%b" }, { EQI, "PB,%b" }, { EQI, "PC,%b" }, { EQI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 }
+};
+
+static const struct dasm_s dasm70_7801[256] = {
+ /* 0x00 - 0x3F */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { SSPD, "%w" }, { LSPD, "%w" },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { SBCD, "%w" }, { LBCD, "%w" },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { SDED, "%w" }, { LDED, "%w" },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { SHLD, "%w" }, { LHLD, "%w" },
+
+ /* 0x40 - 0x7F */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { MOV, "V,%w" }, { MOV, "A,%w" }, { MOV, "B,%w" }, { MOV, "C,%w" },
+ { MOV, "D,%w" }, { MOV, "E,%w" }, { MOV, "H,%w" }, { MOV, "L,%w" },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { MOV, "%w,V" }, { MOV, "%w,A" }, { MOV, "%w,B" }, { MOV, "%w,C" },
+ { MOV, "%w,D" }, { MOV, "%w,E" }, { MOV, "%w,H" }, { MOV, "%w,L" },
+
+ /* 0x80 - 0xBF */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { ANAX, "BC" }, { ANAX, "DE" }, { ANAX, "HL" },
+ { ANAX, "DE+" }, { ANAX, "HL+" }, { ANAX, "DE-" }, { ANAX, "HL-" },
+
+ { illegal, 0 }, { XRAX, "BC" }, { XRAX, "DE" }, { XRAX, "HL" },
+ { XRAX, "DE+" }, { XRAX, "HL+" }, { XRAX, "DE-" }, { XRAX, "HL-" },
+ { illegal, 0 }, { ORAX, "BC" }, { ORAX, "DE" }, { ORAX, "HL" },
+ { ORAX, "DE+" }, { ORAX, "HL+" }, { ORAX, "DE-" }, { ORAX, "HL-" },
+
+ { illegal, 0 }, { ADDNCX, "BC" }, { ADDNCX, "DE" }, { ADDNCX, "HL" },
+ { ADDNCX, "DE+" }, { ADDNCX, "HL+" }, { ADDNCX, "DE-" }, { ADDNCX, "HL-" },
+ { illegal, 0 }, { GTAX, "BC" }, { GTAX, "DE" }, { GTAX, "HL" },
+ { GTAX, "DE+" }, { GTAX, "HL+" }, { GTAX, "DE-" }, { GTAX, "HL-" },
+
+ { illegal, 0 }, { SUBNBX, "BC" }, { SUBNBX, "DE" }, { SUBNBX, "HL" },
+ { SUBNBX, "DE+" }, { SUBNBX, "HL+" }, { SUBNBX, }, { SUBNBX, "HL-" },
+ { illegal, 0 }, { LTAX, "BC" }, { LTAX, "DE" }, { LTAX, "HL" },
+ { LTAX, "DE+" }, { LTAX, "HL+" }, { LTAX, "DE-" }, { LTAX, "HL-" },
+
+ /* 0xC0 - 0xFF */
+ { illegal, 0 }, { ADDX, "BC" }, { ADDX, "DE" }, { ADDX, "HL" },
+ { ADDX, "DE+" }, { ADDX, "HL+" }, { ADDX, "DE-" }, { ADDX, "HL-" },
+ { illegal, 0 }, { ONAX, "BC" }, { ONAX, "DE" }, { ONAX, "HL" },
+ { ONAX, "DE+" }, { ONAX, "HL+" }, { ONAX, "DE-" }, { ONAX, "HL-" },
+
+ { illegal, 0 }, { ADCX, "BC" }, { ADCX, "DE" }, { ADCX, "HL" },
+ { ADCX, "DE+" }, { ADCX, "HL+" }, { ADCX, "DE-" }, { ADCX, "HL-" },
+ { illegal, 0 }, { OFFAX, "BC" }, { OFFAX, "DE" }, { OFFAX, "HL" },
+ { OFFAX, "DE+" }, { OFFAX, "HL+" }, { OFFAX, "DE-" }, { OFFAX, "HL-" },
+
+ { illegal, 0 }, { SUBX, "BC" }, { SUBX, "DE" }, { SUBX, "HL" },
+ { SUBX, "DE+" }, { SUBX, "HL+" }, { SUBX, "DE-" }, { SUBX, "HL-" },
+ { illegal, 0 }, { NEAX, "BC" }, { NEAX, "DE" }, { NEAX, "HL" },
+ { NEAX, "DE+" }, { NEAX, "HL+" }, { NEAX, "DE-" }, { NEAX, "HL-" },
+
+ { illegal, 0 }, { SBBX, "BC" }, { SBBX, "DE" }, { SBBX, "HL" },
+ { SBBX, "DE+" }, { SBBX, "HL+" }, { SBBX, "DE-" }, { SBBX, "HL-" },
+ { illegal, 0 }, { EQAX, "BC" }, { EQAX, "DE" }, { EQAX, "HL" },
+ { EQAX, "DE+" }, { EQAX, "HL+" }, { EQAX, "DE-" }, { EQAX, "HL-" },
+};
+
+static const struct dasm_s dasm74_7801[256] = {
+ /* 0x00 - 0x3F */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ /* 0x40 - 0x7F */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ /* 0x80 - 0xBF */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { ANAW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { XRAW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { ORAW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { ADDNCW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { GTAW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { SUBNBW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { LTAW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ /* 0xC0 - 0xFF */
+ { ADDW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { ONAW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { ADCW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { OFFAW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { SUBW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { NEAW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { SBBW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { EQAW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 }
+};
+
+static const struct dasm_s dasmXX_7801[256] = {
+ /* 0x00 - 0x3F */
+ { NOP, 0 }, { HALT, 0 }, { INX, "SP" }, { DCX, "SP" },
+ { LXI, "SP,%w" }, { ANIW, "%a,%b" }, { illegal, 0 }, { ANI, "A,%b" },
+ { RET, 0 }, { SIO, 0 }, { MOV, "A,B" }, { MOV, "A,C" },
+ { MOV, "A,D" }, { MOV, "A,E" }, { MOV, "A,H" }, { MOV, "A,L" },
+
+ { EX, 0 }, { EXX, 0 }, { INX, "BC" }, { DCX, "BC" },
+ { LXI, "BC,%w" }, { ORIW, "%a,%b" }, { XRI, "A,%b" }, { ORI, "A,%b" },
+ { RETS, 0 }, { STM, 0 }, { MOV, "B,A" }, { MOV, "C,A" },
+ { MOV, "D,A" }, { MOV, "E,A" }, { MOV, "H,A" }, { MOV, "L,A" },
+
+ { INRW, "%a" }, { TABLE, 0 }, { INX, "DE" }, { DCX, "DE" },
+ { LXI, "DE,%w" }, { GTIW, "%a,%b" }, { ADINC, "A,%b" }, { GTI, "A,%b" },
+ { LDAW, "%a" }, { LDAX, "BC" }, { LDAX, "DE" }, { LDAX, "HL" },
+ { LDAX, "DE+" }, { LDAX, "HL+" }, { LDAX, "DE-" }, { LDAX, "HL-" },
+
+ { DCRW, "%a" }, { BLOCK, 0 }, { INX, "HL" }, { DCX, "HL" },
+ { LXI, "HL,%w" }, { LTIW, "%a,%b" }, { SUINB, "A,%b" }, { LTI, "A,%b" },
+ { STAW, "%a" }, { STAX, "BC" }, { STAX, "DE" }, { STAX, "HL" },
+ { STAX, "DE+" }, { STAX, "HL+" }, { STAX, "DE-" }, { STAX, "HL-" },
+
+ /* 0x40 - 0x7F */
+ { illegal, 0 }, { INR, "A" }, { INR, "B" }, { INR, "C" },
+ { CALL, "%w" }, { ONIW, "%a,%b" }, { ADI, "A,%b" }, { ONI, "A,%b" },
+ { 0, dasm48_7801 }, { MVIX, "BC,%b" }, { MVIX, "DE,%b" }, { MVIX, "HL,%b" },
+ { 0, dasm4c_7801 }, { 0, dasm4d_7801 }, { JRE, "%d" }, { JRE, "%d" },
+
+ { illegal, 0 }, { DCR, "A" }, { DCR, "B" }, { DCR, "C" },
+ { JMP, "%w" }, { OFFIW, "%a,%b" }, { ACI, "A,%b" }, { OFFI, "A,%b" },
+ { BIT, "0,%a" }, { BIT, "1,%a" }, { BIT," 2,%a" }, { BIT, "3,%a" },
+ { BIT, "4,%a" }, { BIT, "5,%a" }, { BIT, "6,%a" }, { BIT, "7,%a" },
+
+ { 0, dasm60_7801 }, { DAA, 0 }, { RETI, 0 }, { CALB, 0 },
+ { 0, dasm64_7801 }, { NEIW, "%a,%b" }, { SUI, "A,%b" }, { NEI, "A,%b" },
+ { MVI, "V,%b" }, { MVI, "A,%b" }, { MVI, "B,%b" }, { MVI, "C,%b" },
+ { MVI, "D,%b" }, { MVI, "E,%b" }, { MVI, "H,%b" }, { MVI, "L,%b" },
+
+ { 0, dasm70_7801 }, { MVIW, "%a,%b" }, { SOFTI, 0 }, { JB, 0 },
+ { 0, dasm74_7801 }, { EQIW, "%a,%b" }, { SBI, "A,%b" }, { EQI, "A,%b" },
+ { CALF, "%f" }, { CALF, "%f" }, { CALF, "%f" }, { CALF, "%f" },
+ { CALF, "%f" }, { CALF, "%f" }, { CALF, "%f" }, { CALF, "%f" },
+
+ /* 0x80 - 0xBF */
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+
+ /* 0xC0 - 0xFF */
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" }
+};
+
+/*********************************************************
+ *
+ * uPD7801
+ *
+ *********************************************************/
+
+static const struct dasm_s dasm48_78c05[256] = {
+ /* 0x00 - 0x3F */
+ { SKIT, "F0" }, { SKIT, "FT" }, { SKIT, "F1" }, { illegal, 0 }, /* TODO: PDF doesn't mention SKIT and SK */
+ { SKIT, "FS" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { SK, "CY" }, { illegal, 0 },
+ { SK, "Z" }, { illegal, 0 }, { PUSH, "VA" }, { POP, "VA" },
+
+ { SKNIT, "F0" }, { SKNIT, "FT" }, { SKNIT, "F1" }, { illegal, 0 },
+ { SKNIT, "FS" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { SKN, "CY" }, { illegal, 0 },
+ { SKN, "Z" }, { illegal, 0 }, { PUSH, "BC" }, { POP, "BC" },
+
+ { EI, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { DI, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { CLC, 0 }, { STC, 0 },
+ { illegal, 0 }, { PEX, 0 }, { PUSH, "DE" }, { POP, "DE" },
+
+ { RLL, "A" }, { RLR, "A" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { RLD, 0 }, { RRD, 0 }, { illegal, 0 }, { illegal, 0 },
+ { PER, 0 }, { illegal, 0 }, { PUSH, "HL" }, { POP, "HL" },
+
+ /* 0x40 - 0x7F */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ /* 0x80 - 0xBF */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ /* 0xC0 - 0xFF */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 }
+};
+
+static const struct dasm_s dasm4c_78c05[256] = {
+ /* 0x00 - 0x3F */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ /* 0x40 - 0x7F */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ /* 0x80 - 0xBF */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ /* 0xC0 - 0xFF */
+ { MOV, "A,PA" }, { MOV, "A,PB" }, { MOV, "A,PC" }, { MOV, "A,MK" },
+ { MOV, "A,MB" }, { MOV, "A,MC" }, { MOV, "A,TM0" }, { MOV, "A,TM1" },
+ { MOV, "A,S" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, /* TODO: Figure out what regsiter C9 indicates */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 }
+};
+
+static const struct dasm_s dasm4d_78c05[256] = {
+ /* 0x00 - 0x3F */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ /* 0x40 - 0x7F */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ /* 0x80 - 0xBF */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ /* 0xC0 - 0xFF */
+ { MOV, "PA,A" }, { MOV, "PB,A" }, { MOV, "PC,A" }, { MOV, "MK,A" },
+ { MOV, "MB,A" }, { MOV, "MC,A" }, { MOV, "TM0,A" }, { MOV, "TM1,A" },
+ { MOV, "S,A" }, { MOV, "TMM,A" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 }
+};
+
+static const struct dasm_s dasm60_78c05[256] = {
+ /* 0x00 - 0x3F */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { ANA, "A,A" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { XRA, "A,A" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { ORA, "A,A" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { ADDNC, "A,A" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { GTA, "A,A" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { SUBNB, "A,A" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { LTA, "A,A" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ /* 0x40 - 0x7F */
+ { illegal, 0 }, { ADD, "A,A" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { ADC, "A,A" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { SUB, "A,A" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { NEA, "A,A" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { SBB, "A,A" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { EQA, "A,A" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ /* 0x80 - 0xBF */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { ANA, "A,A" }, { ANA, "A,B" }, { ANA, "A,C" },
+ { ANA, "A,D" }, { ANA, "A,E" }, { ANA, "A,H" }, { ANA, "A,L" },
+
+ { illegal, 0 }, { XRA, "A,A" }, { XRA, "A,B" }, { XRA, "A,C" },
+ { XRA, "A,D" }, { XRA, "A,E" }, { XRA, "A,H" }, { XRA, "A,L" },
+ { illegal, 0 }, { ORA, "A,A" }, { ORA, "A,B" }, { ORA, "A,C" },
+ { ORA, "A,D" }, { ORA, "A,E" }, { ORA, "A,H" }, { ORA, "A,L" },
+
+ { illegal, 0 }, { ADDNC, "A,A" }, { ADDNC, "A,B" }, { ADDNC, "A,C" },
+ { ADDNC, "A,D" }, { ADDNC, "A,E" }, { ADDNC, "A,H" }, { ADDNC, "A,L" },
+ { illegal, 0 }, { GTA, "A,A" }, { GTA, "A,B" }, { GTA, "A,C" },
+ { GTA, "A,D" }, { GTA, "A,E" }, { GTA, "A,H" }, { GTA, "A,L" },
+
+ { illegal, 0 }, { SUBNB, "A,A" }, { SUBNB, "A,B" }, { SUBNB, "A,C" },
+ { SUBNB, "A,D" }, { SUBNB, "A,E" }, { SUBNB, "A,H" }, { SUBNB, "A,L" },
+ { illegal, 0 }, { LTA, "A,A" }, { LTA, "A,B" }, { LTA, "A,C" },
+ { LTA, "A,D" }, { LTA, "A,E" }, { LTA, "A,H" }, { LTA, "A,L" },
+
+ /* 0xC0 - 0xFF */
+ { illegal, 0 }, { ADD, "A,A" }, { ADD, "A,B" }, { ADD, "A,C" },
+ { ADD, "A,D" }, { ADD, "A,E" }, { ADD, "A,H" }, { ADD, "A,L" },
+ { illegal, 0 }, { ONA, "A,A" }, { ONA, "A,B" }, { ONA, "A,C" },
+ { ONA, "A,D" }, { ONA, "A,E" }, { ONA, "A,H" }, { ONA, "A,L" },
+
+ { illegal, 0 }, { ADC, "A,A" }, { ADC, "A,B" }, { ADC, "A,C" },
+ { ADC, "A,D" }, { ADC, "A,E" }, { ADC, "A,H" }, { ADC, "A,L" },
+ { illegal, 0 }, { OFFA, "A,A" }, { OFFA, "A,B" }, { OFFA, "A,C" },
+ { OFFA, "A,D" }, { OFFA, "A,E" }, { OFFA, "A,H" }, { OFFA, "A,L" },
+
+ { illegal, 0 }, { SUB, "A,A" }, { SUB, "A,B" }, { SUB, "A,C" },
+ { SUB, "A,D" }, { SUB, "A,E" }, { SUB, "A,H" }, { SUB, "A,L" },
+ { illegal, 0 }, { NEA, "A,A" }, { NEA, "A,B" }, { NEA, "A,C" },
+ { NEA, "A,D" }, { NEA, "A,E" }, { NEA, "A,H" }, { NEA, "A,L" },
+
+ { illegal, 0 }, { SBB, "A,A" }, { SBB, "A,B" }, { SBB, "A,C" },
+ { SBB, "A,D" }, { SBB, "A,E" }, { SBB, "A,H" }, { SBB, "A,L" },
+ { illegal, 0 }, { EQA, "A,A" }, { EQA, "A,B" }, { EQA, "A,C" },
+ { EQA, "A,D" }, { EQA, "A,E" }, { EQA, "A,H" }, { EQA, "A,L" }
+};
+
+static const struct dasm_s dasm64_78c05[256] = {
+ /* 0x00 - 0x3F */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { ANI, "A,%b" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { XRI, "A,%b" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { ORI, "A,%b" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { ADINC, "A,%b" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { GTI, "A,%b" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { SUINB, "A,%b" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { LTI, "A,%b" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ /* 0x40 - 0x7F */
+ { illegal, 0 }, { ADI, "A,%b" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { ONI, "A,%b" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { ACI, "A,%b" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { OFFI, "A,%b" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { SUI, "A,%b" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { NEI, "A,%b" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { SBI, "A,%b" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { EQI, "A,%b" }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ /* 0x80 - 0xBF */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { ANI, "PA,%b" }, { ANI, "PB,%b" }, { ANI, "PC,%b" }, { ANI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { XRI, "PA,%b" }, { XRI, "PB,%b" }, { XRI, "PC,%b" }, { XRI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { ORI, "PA,%b" }, { ORI, "PB,%b" }, { ORI, "PC,%b" }, { ORI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { ADINC, "PA,%b" }, { ADINC, "PB,%b" }, { ADINC, "PC,%b" }, { ADINC, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { GTI, "PA,%b" }, { GTI, "PB,%b" }, { GTI, "PC,%b" }, { GTI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { SUINB, "PA,%b" }, { SUINB, "PB,%b" }, { SUINB, "PC,%b" }, { SUINB, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { LTI, "PA,%b" }, { LTI, "PB,%b" }, { LTI, "PC,%b" }, { LTI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ /* 0xC0 - 0xFF */
+ { ADI, "PA,%b" }, { ADI, "PB,%b" }, { ADI, "PC,%b" }, { ADI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { ONI, "PA,%b" }, { ONI, "PB,%b" }, { ONI, "PC,%b" }, { ONI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { ACI, "PA,%b" }, { ACI, "PB,%b" }, { ACI, "PC,%b" }, { ACI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { SUI, "PA,%b" }, { SUI, "PB,%b" }, { SUI, "PC,%b" }, { SUI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { NEI, "PA,%b" }, { NEI, "PB,%b" }, { NEI, "PC,%b" }, { NEI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { SBI, "PA,%b" }, { SBI, "PB,%b" }, { SBI, "PC,%b" }, { SBI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { SBI, "PA,%b" }, { SBI, "PB,%b" }, { SBI, "PC,%b" }, { SBI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { EQI, "PA,%b" }, { EQI, "PB,%b" }, { EQI, "PC,%b" }, { EQI, "MK,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 }
+};
+
+static const struct dasm_s dasm70_78c05[256] = {
+ /* 0x00 - 0x3F */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { SSPD, "%w" }, { LSPD, "%w" },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { SBCD, "%w" }, { LBCD, "%w" },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { SDED, "%w" }, { LDED, "%w" },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { SHLD, "%w" }, { LHLD, "%w" },
+
+ /* 0x40 - 0x7F */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { MOV, "A,%w" }, { MOV, "B,%w" }, { MOV, "C,%w" },
+ { MOV, "D,%w" }, { MOV, "E,%w" }, { MOV, "H,%w" }, { MOV, "L,%w" },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { MOV, "%w,A" }, { MOV, "%w,B" }, { MOV, "%w,C" },
+ { MOV, "%w,D" }, { MOV, "%w,E" }, { MOV, "%w,H" }, { MOV, "%w,L" },
+
+ /* 0x80 - 0xBF */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { ANAX, "BC" }, { ANAX, "DE" }, { ANAX, "HL" },
+ { ANAX, "DE+" }, { ANAX, "HL+" }, { ANAX, "DE-" }, { ANAX, "HL-" },
+
+ { illegal, 0 }, { XRAX, "BC" }, { XRAX, "DE" }, { XRAX, "HL" },
+ { XRAX, "DE+" }, { XRAX, "HL+" }, { XRAX, "DE-" }, { XRAX, "HL-" },
+ { illegal, 0 }, { ORAX, "BC" }, { ORAX, "DE" }, { ORAX, "HL" },
+ { ORAX, "DE+" }, { ORAX, "HL+" }, { ORAX, "DE-" }, { ORAX, "HL-" },
+
+ { illegal, 0 }, { ADDNCX, "BC" }, { ADDNCX, "DE" }, { ADDNCX, "HL" },
+ { ADDNCX, "DE+" }, { ADDNCX, "HL+" }, { ADDNCX, "DE-" }, { ADDNCX, "HL-" },
+ { illegal, 0 }, { GTAX, "BC" }, { GTAX, "DE" }, { GTAX, "HL" },
+ { GTAX, "DE+" }, { GTAX, "HL+" }, { GTAX, "DE-" }, { GTAX, "HL-" },
+
+ { illegal, 0 }, { SUBNBX, "BC" }, { SUBNBX, "DE" }, { SUBNBX, "HL" },
+ { SUBNBX, "DE+" }, { SUBNBX, "HL+" }, { SUBNBX, "DE-" }, { SUBNBX, "HL-" },
+ { illegal, 0 }, { LTAX, "BC" }, { LTAX, "DE" }, { LTAX, "HL" },
+ { LTAX, "DE+" }, { LTAX, "HL+" }, { LTAX, "DE-" }, { LTAX, "HL-" },
+
+ /* 0xC0 - 0xFF */
+ { illegal, 0 }, { ADDX, "BC" }, { ADDX, "DE" }, { ADDX, "HL" },
+ { ADDX, "DE+" }, { ADDX, "HL+" }, { ADDX, "DE-" }, { ADDX, "HL-" },
+ { illegal, 0 }, { ONAX, "BC" }, { ONAX, "DE" }, { ONAX, "HL" },
+ { ONAX, "DE+" }, { ONAX, "HL+" }, { ONAX, "DE-" }, { ONAX, "HL-" },
+
+ { illegal, 0 }, { ADCX, "BC" }, { ADCX, "DE" }, { ADCX, "HL" },
+ { ADCX, "DE+" }, { ADCX, "HL+" }, { ADCX, "DE-" }, { ADCX, "HL-" },
+ { illegal, 0 }, { OFFAX, "BC" }, { OFFAX, "DE" }, { OFFAX, "HL" },
+ { OFFAX, "DE+" }, { OFFAX, "HL+" }, { OFFAX, "DE-" }, { OFFAX, "HL-" },
+
+ { illegal, 0 }, { SUBX, "BC" }, { SUBX, "DE" }, { SUBX, "HL" },
+ { SUBX, "DE+" }, { SUBX, "HL+" }, { SUBX, "DE-" }, { SUBX, "HL-" },
+ { illegal, 0 }, { NEAX, "BC" }, { NEAX, "DE" }, { NEAX, "HL" },
+ { NEAX, "DE+" }, { NEAX, "HL+" }, { NEAX, "DE-" }, { NEAX, "HL-" },
+
+ { illegal, 0 }, { SBBX, "BC" }, { SBBX, "DE" }, { SBBX, "HL" },
+ { SBBX, "DE+" }, { SBBX, "HL+" }, { SBBX, "DE-" }, { SBBX, "HL-" },
+ { illegal, 0 }, { EQAX, "BC" }, { EQAX, "DE" }, { EQAX, "HL" },
+ { EQAX, "DE+" }, { EQAX, "HL+" }, { EQAX, "DE-" }, { EQAX, "HL-" },
+};
+
+static const struct dasm_s dasm74_78c05[256] = {
+ /* 0x00 - 0x3F */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ /* 0x40 - 0x7F */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ /* 0x80 - 0xBF */
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { ANAW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { XRAW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { ORAW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { ADDNCW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { GTAW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { SUBNBW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { LTAW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ /* 0xC0 - 0xFF */
+ { ADDW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { ONAW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { ADCW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { OFFAW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { SUBW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { NEAW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { SBBW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { EQAW, "%a" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+};
+
+static const struct dasm_s dasmXX_78c05[256] = {
+ /* 0x00 - 0x3F */
+ { NOP, 0 }, { HALT, 0 }, { INX, "SP" }, { DCX, "SP" },
+ { LXI, "SP,%w" }, { ANIW, "%a,%b" }, { illegal, 0 }, { ANI, "A,%b" },
+ { RET, 0 }, { SIO, 0 }, { MOV, "A,B" }, { MOV, "A,C" },
+ { MOV, "A,D" }, { MOV, "A,E" }, { MOV, "A,H" }, { MOV, "A,L" },
+
+ { illegal, 0 }, { illegal, 0 }, { INX, "BC" }, { DCX, "BC" },
+ { LXI, "BC,%w" }, { ORIW, "%a,%b" }, { XRI, "A,%b" }, { ORI, "A,%b" },
+ { RETS, 0 }, { STM, 0 }, { MOV, "B,A" }, { MOV, "C,A" },
+ { MOV, "D,A" }, { MOV, "E,A" }, { MOV, "H,A" }, { MOV, "L,A" },
+
+ { INRW, "%a" }, { illegal, 0 }, { INX, "DE" }, { DCX, "DE" },
+ { LXI, "DE,%w" }, { GTIW, "%a,%b" }, { ADINC, "A,%b" }, { GTI, "A,%b" },
+ { LDAW, "%a" }, { LDAX, "BC" }, { LDAX, "DE" }, { LDAX, "HL" },
+ { LDAX, "DE+" }, { LDAX, "HL+" }, { LDAX, "DE-" }, { LDAX, "HL-" },
+
+ { DCRW, "%a" }, { illegal, 0 }, { INX, "HL" }, { DCX, "HL" },
+ { LXI, "HL,%w" }, { LTIW, "%a,%b" }, { SUINB, "A,%b" }, { LTI, "A,%b" },
+ { STAW, "%a" }, { STAX, "BC" }, { STAX, "DE" }, { STAX, "HL" },
+ { STAX, "DE+" }, { STAX, "HL+" }, { STAX, "DE-" }, { STAX, "HL-" },
+
+ /* 0x40 - 0x7F */
+ { illegal, 0 }, { INR, "A" }, { INR, "B" }, { INR, "C" },
+ { CALL, "%w" }, { ONIW, "%a,%b" }, { ADI, "A,%b" }, { ONI, "A,%b" },
+ { 0, dasm48_78c05 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { 0, dasm4c_78c05 }, { 0, dasm4d_78c05 }, { JRE, "%d" }, { JRE, "%d" },
+
+ { illegal, 0 }, { DCR, "A" }, { DCR, "B" }, { DCR, "C" },
+ { JMP, "%w" }, { OFFIW, "%a,%b" }, { ACI, "A,%b" }, { OFFI, "A,%b" },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+ { illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
+
+ { 0, dasm60_78c05 }, { DAA, 0 }, { RETI, 0 }, { CALB, 0 },
+ { 0, dasm64_78c05 }, { NEIW, "%a,%b" }, { SUI, "A,%b" }, { NEI, "A,%b" },
+ { illegal, 0 }, { MVI, "A,%b" }, { MVI, "B,%b" }, { MVI, "C,%b" },
+ { MVI, "D,%b" }, { MVI, "E,%b" }, { MVI, "H,%b" }, { MVI, "L,%b" },
+
+ { 0, dasm70_78c05 }, { MVIW, "%a,%b" }, { SOFTI, 0 }, { JB, 0 },
+ { 0, dasm74_78c05 }, { EQIW, "%a,%b" }, { SBI, "A,%b" }, { EQI, "A,%b" },
+ { CALF, "%f" }, { CALF, "%f" }, { CALF, "%f" }, { CALF, "%f" },
+ { CALF, "%f" }, { CALF, "%f" }, { CALF, "%f" }, { CALF, "%f" },
+
+ /* 0x80 - 0xBF */
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+ { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" }, { CALT, "%t" },
+
+ /* 0xC0 - 0xFF */
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" },
+ { JR, "%o" }, { JR, "%o" }, { JR, "%o" }, { JR, "%o" }
+};
+
+
+/* register names for bit manipulation instructions */
+static const char *const regname[32] =
+{
+ "illegal", "illegal", "illegal", "illegal",
+ "illegal", "illegal", "illegal", "illegal",
+ "illegal", "illegal", "illegal", "illegal",
+ "illegal", "illegal", "illegal", "illegal",
+ "PA", "PB", "PC", "PD",
+ "illegal", "PF", "MKH", "MKL",
+ "illegal", "SMH", "illegal", "EOM",
+ "illegal", "TMM", "PT", "illegal"
+};
+
+static offs_t Dasm( char *buffer, offs_t pc, const struct dasm_s *dasmXX, const UINT8 *oprom, const UINT8 *opram, int is_7810 )
+{
+ int idx = 0;
+ UINT8 op = oprom[idx++], op2, t;
+ int offset;
+ UINT16 ea;
+ const char *a;
+ UINT32 flags = 0;
+
+ t = dasmXX[op].token;
+ a = (const char *)dasmXX[op].args;
+
+ /* 0 token means prefix opcode (use table from args) */
+ if (0 == t)
+ {
+ struct dasm_s *p_dasm = (struct dasm_s *)a;
+
+ op2 = oprom[idx++];
+ t = p_dasm[op2].token;
+ a = (const char *)p_dasm[op2].args;
+ }
+
+ buffer += sprintf(buffer, "%-8.8s", token[t]);
+
+ if (t == CALB || t == CALF || t == CALL || t == CALT)
+ flags = DASMFLAG_STEP_OVER;
+ else if (t == RET || t == RETI)
+ flags = DASMFLAG_STEP_OUT;
+
+ while (a && *a)
+ {
+ if ('%' == *a)
+ {
+ a++;
+ switch (*a)
+ {
+ case 'a': /* address V * 256 + offset */
+ op2 = opram[idx++];
+ buffer += sprintf(buffer, "VV:%02X", op2);
+ break;
+ case 'b': /* immediate byte */
+ buffer += sprintf(buffer, "$%02X", opram[idx++]);
+ break;
+ case 'w': /* immediate word */
+ ea = opram[idx++];
+ ea += opram[idx++] << 8;
+ buffer += sprintf(buffer, "$%04X", ea);
+ break;
+ case 'd': /* JRE address */
+ op2 = oprom[idx++];
+ offset = (op & 1) ? -(256 - op2): + op2;
+ buffer += sprintf(buffer, "$%04X", ( pc + idx + offset ) & 0xFFFF );
+ break;
+ case 't': /* CALT address */
+ ea = 0x80 + 2 * (op & (is_7810 ? 0x1f : 0x3f));
+ buffer += sprintf(buffer, "($%04X)", ea);
+ break;
+ case 'f': /* CALF address */
+ op2 = oprom[idx++];
+ ea = 0x800 + 0x100 * (op & 0x07) + op2;
+ buffer += sprintf(buffer, "$%04X", ea);
+ break;
+ case 'o': /* JR offset */
+ offset = ( ( op & 0x20 ) ? -0x20 : 0 ) + ( op & 0x1F );
+ buffer += sprintf(buffer, "$%04X", ( pc + idx + offset ) & 0xFFFF );
+ break;
+ case 'i': /* bit manipulation */
+ op2 = oprom[idx++];
+ buffer += sprintf(buffer, "%s,%d", regname[op2 & 0x1f], op2 >> 5);
+ break;
+ default:
+ *buffer++ = *a;
+ }
+ }
+ else
+ *buffer++ = *a;
+ a++;
+ }
+ *buffer = '\0';
+
+ return idx | flags | DASMFLAG_SUPPORTED;
+}
+
+CPU_DISASSEMBLE( upd7810 )
+{
+ return Dasm( buffer, pc, dasmXX_7810, oprom, opram, 1 );
+}
+
+CPU_DISASSEMBLE( upd7807 )
+{
+ return Dasm( buffer, pc, dasmXX_7807, oprom, opram, 1 );
+}
+
+CPU_DISASSEMBLE( upd7801 )
+{
+ return Dasm( buffer, pc, dasmXX_7801, oprom, opram, 0 );
+}
+
+CPU_DISASSEMBLE( upd78c05 )
+{
+ return Dasm( buffer, pc, dasmXX_78c05, oprom, opram, 0 );
+}
+
+
diff --git a/trunk/src/emu/cpu/upd7810/7810ops.c b/trunk/src/emu/cpu/upd7810/7810ops.c
new file mode 100644
index 00000000000..2621c051482
--- /dev/null
+++ b/trunk/src/emu/cpu/upd7810/7810ops.c
@@ -0,0 +1,9488 @@
+/*****************************************************************************
+ *
+ * Portable uPD7810/11, 7810H/11H, 78C10/C11/C14 emulator V0.2
+ * Copyright Juergen Buchmueller, all rights reserved.
+ *
+ * 7810ops.c - opcode functions
+ *
+ *****************************************************************************/
+
+static void illegal(upd7810_state *cpustate)
+{
+ logerror("uPD7810 '%s': illegal opcode %02x at PC:%04x\n", cpustate->device->tag(), OP, PC);
+}
+
+static void illegal2(upd7810_state *cpustate)
+{
+ logerror("uPD7810 '%s': illegal opcode %02x %02x at PC:%04x\n", cpustate->device->tag(), OP, OP2, PC);
+}
+
+/* prefix 48 */
+
+/* 48 01: 0100 1000 0000 0001 */
+static void SLRC_A(upd7810_state *cpustate)
+{
+ PSW = (PSW & ~CY) | (A & CY);
+ A >>= 1;
+ SKIP_CY;
+}
+
+/* 48 02: 0100 1000 0000 0010 */
+static void SLRC_B(upd7810_state *cpustate)
+{
+ PSW = (PSW & ~CY) | (B & CY);
+ B >>= 1;
+ SKIP_CY;
+}
+
+/* 48 03: 0100 1000 0000 0011 */
+static void SLRC_C(upd7810_state *cpustate)
+{
+ PSW = (PSW & ~CY) | (C & CY);
+ C >>= 1;
+ SKIP_CY;
+}
+
+
+/* 48 05: 0100 1000 0000 0101 */
+static void SLLC_A(upd7810_state *cpustate)
+{
+ PSW = (PSW & ~CY) | ((A >> 7) & CY);
+ A <<= 1;
+ SKIP_CY;
+}
+
+/* 48 06: 0100 1000 0000 0110 */
+static void SLLC_B(upd7810_state *cpustate)
+{
+ PSW = (PSW & ~CY) | ((B >> 7) & CY);
+ B <<= 1;
+ SKIP_CY;
+}
+
+/* 48 07: 0100 1000 0000 0111 */
+static void SLLC_C(upd7810_state *cpustate)
+{
+ PSW = (PSW & ~CY) | ((C >> 7) & CY);
+ C <<= 1;
+ SKIP_CY;
+}
+
+/* 48 08: 0100 1000 0000 1000 */
+static void SK_NV(upd7810_state *cpustate)
+{
+ /* 48 skip never */
+}
+
+/* 48 0a: 0100 1000 0000 1010 */
+static void SK_CY(upd7810_state *cpustate)
+{
+ if (CY == (PSW & CY))
+ PSW |= SK;
+}
+
+/* 48 0b: 0100 1000 0000 1011 */
+static void SK_HC(upd7810_state *cpustate)
+{
+ if (HC == (PSW & HC))
+ PSW |= SK;
+}
+
+/* 48 0c: 0100 1000 0000 1100 */
+static void SK_Z(upd7810_state *cpustate)
+{
+ if (Z == (PSW & Z))
+ PSW |= SK;
+}
+
+/* 48 18: 0100 1000 0001 1000 */
+static void SKN_NV(upd7810_state *cpustate)
+{
+ /* skip not never -> skip always ;-) */
+ PSW |= SK;
+}
+
+/* 48 1a: 0100 1000 0001 1010 */
+static void SKN_CY(upd7810_state *cpustate)
+{
+ if (0 == (PSW & CY))
+ PSW |= SK;
+}
+
+/* 48 1b: 0100 1000 0001 1011 */
+static void SKN_HC(upd7810_state *cpustate)
+{
+ if (0 == (PSW & HC))
+ PSW |= SK;
+}
+
+/* 48 1c: 0100 1000 0001 1100 */
+static void SKN_Z(upd7810_state *cpustate)
+{
+ if (0 == (PSW & Z))
+ PSW |= SK;
+}
+
+/* 48 21: 0100 1000 0010 0001 */
+static void SLR_A(upd7810_state *cpustate)
+{
+ PSW = (PSW & ~CY) | (A & CY);
+ A >>= 1;
+}
+
+/* 48 22: 0100 1000 0010 0010 */
+static void SLR_B(upd7810_state *cpustate)
+{
+ PSW = (PSW & ~CY) | (B & CY);
+ B >>= 1;
+}
+
+/* 48 23: 0100 1000 0010 0011 */
+static void SLR_C(upd7810_state *cpustate)
+{
+ PSW = (PSW & ~CY) | (C & CY);
+ C >>= 1;
+}
+
+/* 48 25: 0100 1000 0010 0101 */
+static void SLL_A(upd7810_state *cpustate)
+{
+ PSW = (PSW & ~CY) | ((A >> 7) & CY);
+ A <<= 1;
+}
+
+/* 48 26: 0100 1000 0010 0110 */
+static void SLL_B(upd7810_state *cpustate)
+{
+ PSW = (PSW & ~CY) | ((B >> 7) & CY);
+ B <<= 1;
+}
+
+/* 48 27: 0100 1000 0010 0111 */
+static void SLL_C(upd7810_state *cpustate)
+{
+ PSW = (PSW & ~CY) | ((C >> 7) & CY);
+ C <<= 1;
+}
+
+/* 48 28: 0100 1000 0010 1000 */
+static void JEA(upd7810_state *cpustate)
+{
+ PC = EA;
+}
+
+/* 48 29: 0100 1000 0010 1001 */
+static void CALB(upd7810_state *cpustate)
+{
+ SP--;
+ WM( SPD, PCH );
+ SP--;
+ WM( SPD, PCL );
+
+ PC = BC;
+}
+
+/* 48 2a: 0100 1000 0010 1010 */
+static void CLC(upd7810_state *cpustate)
+{
+ PSW &= ~CY;
+}
+
+/* 48 2b: 0100 1000 0010 1011 */
+static void STC(upd7810_state *cpustate)
+{
+ PSW |= CY;
+}
+
+/* 48 2d: 0100 1000 0010 1101 */
+static void MUL_A(upd7810_state *cpustate)
+{
+ EA = A * A;
+}
+
+/* 48 2e: 0100 1000 0010 1110 */
+static void MUL_B(upd7810_state *cpustate)
+{
+ EA = A * B;
+}
+
+/* 48 2f: 0100 1000 0010 1111 */
+static void MUL_C(upd7810_state *cpustate)
+{
+ EA = A * C;
+}
+
+/* 48 31: 0100 1000 0011 0001 */
+static void RLR_A(upd7810_state *cpustate)
+{
+ UINT8 carry=(PSW&CY)<<7;
+ PSW = (PSW & ~CY) | (A & CY);
+ A = (A >> 1) | carry;
+}
+
+/* 48 32: 0100 1000 0011 0010 */
+static void RLR_B(upd7810_state *cpustate)
+{
+ UINT8 carry=(PSW&CY)<<7;
+ PSW = (PSW & ~CY) | (B & CY);
+ B = (B >> 1) | carry;
+}
+
+/* 48 33: 0100 1000 0011 0011 */
+static void RLR_C(upd7810_state *cpustate)
+{
+ UINT8 carry=(PSW&CY)<<7;
+ PSW = (PSW & ~CY) | (C & CY);
+ C = (C >> 1) | carry;
+}
+
+/* 48 35: 0100 1000 0011 0101 */
+static void RLL_A(upd7810_state *cpustate)
+{
+ UINT8 carry=PSW&CY;
+ PSW = (PSW & ~CY) | ((A >> 7) & CY);
+ A = (A << 1) | carry;
+}
+
+/* 48 36: 0100 1000 0011 0110 */
+static void RLL_B(upd7810_state *cpustate)
+{
+ UINT8 carry=PSW&CY;
+ PSW = (PSW & ~CY) | ((B >> 7) & CY);
+ B = (B << 1) | carry;
+}
+
+/* 48 37: 0100 1000 0011 0111 */
+static void RLL_C(upd7810_state *cpustate)
+{
+ UINT8 carry=PSW&CY;
+ PSW = (PSW & ~CY) | ((C >> 7) & CY);
+ C = (C << 1) | carry;
+}
+
+/* 48 38: 0100 1000 0011 1000 */
+static void RLD(upd7810_state *cpustate)
+{
+ UINT8 m = RM( HL ), tmp;
+ tmp = (m << 4) | (A & 0x0f);
+ A = (A & 0xf0) | (m >> 4);
+ WM( HL, tmp );
+}
+
+/* 48 39: 0100 1000 0011 1001 */
+static void RRD(upd7810_state *cpustate)
+{
+ UINT8 m = RM( HL ), tmp;
+ tmp = (A << 4) | (m >> 4);
+ A = (A & 0xf0) | (m & 0x0f);
+ WM( HL, tmp );
+}
+
+/* 48 3a: 0100 1000 0011 1010 */
+static void NEGA(upd7810_state *cpustate)
+{
+ A = ~A + 1;
+}
+
+/* 48 3b: 0100 1000 0011 1011 */
+static void HALT(upd7810_state *cpustate)
+{
+ int cycles = (cpustate->icount / 4) * 4;
+ cpustate->icount -= cycles;
+ cpustate->handle_timers(cpustate, cycles);
+ PC -= 1; /* continue executing HALT */
+}
+
+/* 48 3d: 0100 1000 0011 1101 */
+static void DIV_A(upd7810_state *cpustate)
+{
+ if (A)
+ {
+ UINT8 remainder;
+ remainder = EA % A;
+ EA /= A;
+ A = remainder;
+ }
+ else
+ EA = 0xffff; /* guess */
+}
+
+/* 48 3e: 0100 1000 0011 1110 */
+static void DIV_B(upd7810_state *cpustate)
+{
+ if (B)
+ {
+ UINT8 remainder;
+ remainder = EA % B;
+ EA /= B;
+ B = remainder;
+ }
+ else
+ EA = 0xffff; /* guess */
+}
+
+/* 48 3f: 0100 1000 0011 1111 */
+static void DIV_C(upd7810_state *cpustate)
+{
+ if (C)
+ {
+ UINT8 remainder;
+ remainder = EA % C;
+ EA /= C;
+ C = remainder;
+ }
+ else
+ EA = 0xffff; /* guess */
+}
+
+/* 48 40: 0100 1000 0100 0000 */
+static void SKIT_NMI(upd7810_state *cpustate)
+{
+ if (IRR & INTNMI)
+ PSW |= SK;
+ IRR &= ~INTNMI;
+}
+
+/* 48 41: 0100 1000 0100 0001 */
+static void SKIT_FT0(upd7810_state *cpustate)
+{
+ if (IRR & INTFT0)
+ PSW |= SK;
+ IRR &= ~INTFT0;
+}
+
+/* 48 42: 0100 1000 0100 0010 */
+static void SKIT_FT1(upd7810_state *cpustate)
+{
+ if (IRR & INTFT1)
+ PSW |= SK;
+ IRR &= ~INTFT1;
+}
+
+/* 48 43: 0100 1000 0100 0011 */
+static void SKIT_F1(upd7810_state *cpustate)
+{
+ if (IRR & INTF1)
+ PSW |= SK;
+ IRR &= ~INTF1;
+}
+
+/* 48 44: 0100 1000 0100 0100 */
+static void SKIT_F2(upd7810_state *cpustate)
+{
+ if (IRR & INTF2)
+ PSW |= SK;
+ IRR &= ~INTF2;
+}
+
+/* 48 45: 0100 1000 0100 0101 */
+static void SKIT_FE0(upd7810_state *cpustate)
+{
+ if (IRR & INTFE0)
+ PSW |= SK;
+ IRR &= ~INTFE0;
+}
+
+/* 48 46: 0100 1000 0100 0110 */
+static void SKIT_FE1(upd7810_state *cpustate)
+{
+ if (IRR & INTFE1)
+ PSW |= SK;
+ IRR &= ~INTFE1;
+}
+
+/* 48 47: 0100 1000 0100 0111 */
+static void SKIT_FEIN(upd7810_state *cpustate)
+{
+ if (IRR & INTFEIN)
+ PSW |= SK;
+ IRR &= ~INTFEIN;
+}
+
+/* 48 48: 0100 1000 0100 1000 */
+static void SKIT_FAD(upd7810_state *cpustate)
+{
+ if (IRR & INTFAD)
+ PSW |= SK;
+ IRR &= ~INTFAD;
+}
+
+/* 48 49: 0100 1000 0100 1001 */
+static void SKIT_FSR(upd7810_state *cpustate)
+{
+ if (IRR & INTFSR)
+ PSW |= SK;
+ IRR &= ~INTFSR;
+}
+
+/* 48 4a: 0100 1000 0100 1010 */
+static void SKIT_FST(upd7810_state *cpustate)
+{
+ if (IRR & INTFST)
+ PSW |= SK;
+ IRR &= ~INTFST;
+}
+
+/* 48 4b: 0100 1000 0100 1011 */
+static void SKIT_ER(upd7810_state *cpustate)
+{
+ if (IRR & INTER)
+ PSW |= SK;
+ IRR &= ~INTER;
+}
+
+/* 48 4c: 0100 1000 0100 1100 */
+static void SKIT_OV(upd7810_state *cpustate)
+{
+ if (IRR & INTOV)
+ PSW |= SK;
+ IRR &= ~INTOV;
+}
+
+/* 48 50: 0100 1000 0101 0000 */
+static void SKIT_AN4(upd7810_state *cpustate)
+{
+ if (ITF & INTAN4)
+ PSW |= SK;
+ ITF &= ~INTAN4;
+}
+
+/* 48 51: 0100 1000 0101 0001 */
+static void SKIT_AN5(upd7810_state *cpustate)
+{
+ if (ITF & INTAN5)
+ PSW |= SK;
+ ITF &= ~INTAN5;
+}
+
+/* 48 52: 0100 1000 0101 0010 */
+static void SKIT_AN6(upd7810_state *cpustate)
+{
+ if (ITF & INTAN6)
+ PSW |= SK;
+ ITF &= ~INTAN6;
+}
+
+/* 48 53: 0100 1000 0101 0011 */
+static void SKIT_AN7(upd7810_state *cpustate)
+{
+ if (ITF & INTAN7)
+ PSW |= SK;
+ ITF &= ~INTAN7;
+}
+
+/* 48 54: 0100 1000 0101 0100 */
+static void SKIT_SB(upd7810_state *cpustate)
+{
+ if (ITF & INTSB)
+ PSW |= SK;
+ ITF &= ~INTSB;
+}
+
+/* 48 60: 0100 1000 0110 0000 */
+static void SKNIT_NMI(upd7810_state *cpustate)
+{
+ if (0 == (IRR & INTNMI))
+ PSW |= SK;
+ IRR &= ~INTNMI;
+}
+
+/* 48 61: 0100 1000 0110 0001 */
+static void SKNIT_FT0(upd7810_state *cpustate)
+{
+ if (0 == (IRR & INTFT0))
+ PSW |= SK;
+ IRR &= ~INTFT0;
+}
+
+/* 48 62: 0100 1000 0110 0010 */
+static void SKNIT_FT1(upd7810_state *cpustate)
+{
+ if (0 == (IRR & INTFT1))
+ PSW |= SK;
+ IRR &= ~INTFT1;
+}
+
+/* 48 63: 0100 1000 0110 0011 */
+static void SKNIT_F1(upd7810_state *cpustate)
+{
+ if (0 == (IRR & INTF1))
+ PSW |= SK;
+ IRR &= ~INTF1;
+}
+
+/* 48 64: 0100 1000 0110 0100 */
+static void SKNIT_F2(upd7810_state *cpustate)
+{
+ if (0 == (IRR & INTF2))
+ PSW |= SK;
+ IRR &= ~INTF2;
+}
+
+/* 48 65: 0100 1000 0110 0101 */
+static void SKNIT_FE0(upd7810_state *cpustate)
+{
+ if (0 == (IRR & INTFE0))
+ PSW |= SK;
+ IRR &= ~INTFE0;
+}
+
+/* 48 66: 0100 1000 0110 0110 */
+static void SKNIT_FE1(upd7810_state *cpustate)
+{
+ if (0 == (IRR & INTFE1))
+ PSW |= SK;
+ IRR &= ~INTFE1;
+}
+
+/* 48 67: 0100 1000 0110 0111 */
+static void SKNIT_FEIN(upd7810_state *cpustate)
+{
+ if (0 == (IRR & INTFEIN))
+ PSW |= SK;
+ IRR &= ~INTFEIN;
+}
+
+/* 48 68: 0100 1000 0110 1000 */
+static void SKNIT_FAD(upd7810_state *cpustate)
+{
+ if (0 == (IRR & INTFAD))
+ PSW |= SK;
+ IRR &= ~INTFAD;
+}
+
+/* 48 69: 0100 1000 0110 1001 */
+static void SKNIT_FSR(upd7810_state *cpustate)
+{
+ if (0 == (IRR & INTFSR))
+ PSW |= SK;
+ IRR &= ~INTFSR;
+}
+
+/* 48 6a: 0100 1000 0110 1010 */
+static void SKNIT_FST(upd7810_state *cpustate)
+{
+ if (0 == (IRR & INTFST))
+ PSW |= SK;
+ IRR &= ~INTFST;
+}
+
+/* 48 6b: 0100 1000 0110 1011 */
+static void SKNIT_ER(upd7810_state *cpustate)
+{
+ if (0 == (IRR & INTER))
+ PSW |= SK;
+ IRR &= ~INTER;
+}
+
+/* 48 6c: 0100 1000 0110 1100 */
+static void SKNIT_OV(upd7810_state *cpustate)
+{
+ if (0 == (IRR & INTOV))
+ PSW |= SK;
+ IRR &= ~INTOV;
+}
+
+/* 48 70: 0100 1000 0111 0000 */
+static void SKNIT_AN4(upd7810_state *cpustate)
+{
+ if (0 == (ITF & INTAN4))
+ PSW |= SK;
+ ITF &= ~INTAN4;
+}
+
+/* 48 71: 0100 1000 0111 0001 */
+static void SKNIT_AN5(upd7810_state *cpustate)
+{
+ if (0 == (ITF & INTAN5))
+ PSW |= SK;
+ ITF &= ~INTAN5;
+}
+
+/* 48 72: 0100 1000 0111 0010 */
+static void SKNIT_AN6(upd7810_state *cpustate)
+{
+ if (0 == (ITF & INTAN6))
+ PSW |= SK;
+ ITF &= ~INTAN6;
+}
+
+/* 48 73: 0100 1000 0111 0011 */
+static void SKNIT_AN7(upd7810_state *cpustate)
+{
+ if (0 == (ITF & INTAN7))
+ PSW |= SK;
+ ITF &= ~INTAN7;
+}
+
+/* 48 74: 0100 1000 0111 0100 */
+static void SKNIT_SB(upd7810_state *cpustate)
+{
+ if (0 == (ITF & INTSB))
+ PSW |= SK;
+ ITF &= ~INTSB;
+}
+
+/* 48 82: 0100 1000 1000 0010 */
+static void LDEAX_D(upd7810_state *cpustate)
+{
+ EAL = RM( DE );
+ EAH = RM( DE + 1 );
+}
+
+/* 48 83: 0100 1000 1000 0011 */
+static void LDEAX_H(upd7810_state *cpustate)
+{
+ EAL = RM( HL );
+ EAH = RM( HL + 1 );
+}
+
+/* 48 84: 0100 1000 1000 0100 */
+static void LDEAX_Dp(upd7810_state *cpustate)
+{
+ EAL = RM( DE );
+ EAH = RM( DE + 1 );
+ DE += 2;
+}
+
+/* 48 85: 0100 1000 1000 0101 */
+static void LDEAX_Hp(upd7810_state *cpustate)
+{
+ EAL = RM( HL );
+ EAH = RM( HL + 1 );
+ HL += 2;
+}
+
+/* 48 8b: 0100 1000 1000 1011 xxxx xxxx */
+static void LDEAX_D_xx(upd7810_state *cpustate)
+{
+ UINT16 ea;
+ RDOPARG( ea );
+ ea += DE;
+ EAL = RM( ea );
+ EAH = RM( ea + 1 );
+}
+
+/* 48 8c: 0100 1000 1000 1100 */
+static void LDEAX_H_A(upd7810_state *cpustate)
+{
+ UINT16 ea = HL + A;
+ EAL = RM( ea );
+ EAH = RM( ea + 1 );
+}
+
+/* 48 8d: 0100 1000 1000 1101 */
+static void LDEAX_H_B(upd7810_state *cpustate)
+{
+ UINT16 ea = HL + B;
+ EAL = RM( ea );
+ EAH = RM( ea + 1 );
+}
+
+/* 48 8e: 0100 1000 1000 1110 */
+static void LDEAX_H_EA(upd7810_state *cpustate)
+{
+ UINT16 ea = HL + EA;
+ EAL = RM( ea );
+ EAH = RM( ea + 1 );
+}
+
+/* 48 8f: 0100 1000 1000 1111 xxxx xxxx */
+static void LDEAX_H_xx(upd7810_state *cpustate)
+{
+ UINT16 ea;
+ RDOPARG( ea );
+ ea += HL;
+ EAL = RM( ea );
+ EAH = RM( ea + 1 );
+}
+
+/* 48 92: 0100 1000 1000 0010 */
+static void STEAX_D(upd7810_state *cpustate)
+{
+ WM( DE, EAL );
+ WM( DE + 1, EAH );
+}
+
+/* 48 93: 0100 1000 1000 0011 */
+static void STEAX_H(upd7810_state *cpustate)
+{
+ WM( HL, EAL );
+ WM( HL + 1, EAH );
+}
+
+/* 48 94: 0100 1000 1000 0100 */
+static void STEAX_Dp(upd7810_state *cpustate)
+{
+ WM( DE, EAL );
+ WM( DE + 1, EAH );
+ DE += 2;
+}
+
+/* 48 95: 0100 1000 1000 0101 */
+static void STEAX_Hp(upd7810_state *cpustate)
+{
+ WM( HL, EAL );
+ WM( HL + 1, EAH );
+ HL += 2;
+}
+
+/* 48 9b: 0100 1000 1000 1011 xxxx xxxx */
+static void STEAX_D_xx(upd7810_state *cpustate)
+{
+ UINT16 ea;
+ RDOPARG( ea );
+ ea += DE;
+ WM( ea, EAL );
+ WM( ea + 1, EAH );
+}
+
+/* 48 9c: 0100 1000 1000 1100 */
+static void STEAX_H_A(upd7810_state *cpustate)
+{
+ UINT16 ea = HL + A;
+ WM( ea, EAL );
+ WM( ea + 1, EAH );
+}
+
+/* 48 9d: 0100 1000 1000 1101 */
+static void STEAX_H_B(upd7810_state *cpustate)
+{
+ UINT16 ea = HL + B;
+ WM( ea, EAL );
+ WM( ea + 1, EAH );
+}
+
+/* 48 9e: 0100 1000 1000 1110 */
+static void STEAX_H_EA(upd7810_state *cpustate)
+{
+ UINT16 ea = HL + EA;
+ WM( ea, EAL );
+ WM( ea + 1, EAH );
+}
+
+/* 48 9f: 0100 1000 1000 1111 xxxx xxxx */
+static void STEAX_H_xx(upd7810_state *cpustate)
+{
+ UINT16 ea;
+ RDOPARG( ea );
+ ea += HL;
+ WM( ea, EAL );
+ WM( ea + 1, EAH );
+}
+
+/* 48 a0: 0100 1000 1010 0000 */
+static void DSLR_EA(upd7810_state *cpustate)
+{
+ PSW = (PSW & ~CY) | (EA & CY);
+ EA >>= 1;
+}
+
+/* 48 a4: 0100 1000 1010 0100 */
+static void DSLL_EA(upd7810_state *cpustate)
+{
+ PSW = (PSW & ~CY) | ((EA >> 15) & CY);
+ EA <<= 1;
+}
+
+/* 48 a8: 0100 1000 1010 1000 */
+static void TABLE(upd7810_state *cpustate)
+{
+ UINT16 ea = PC + A + 1;
+ C = RM( ea );
+ B = RM( ea + 1 );
+}
+
+/* 48 b0: 0100 1000 1011 0000 */
+static void DRLR_EA(upd7810_state *cpustate)
+{
+ UINT8 carry=PSW&CY;
+ PSW = (PSW & ~CY) | (EA & CY);
+ EA = (EA >> 1) | (carry << 15);
+}
+
+/* 48 b4: 0100 1000 1011 0100 */
+static void DRLL_EA(upd7810_state *cpustate)
+{
+ UINT8 carry=PSW&CY;
+ PSW = (PSW & ~CY) | ((EA >> 15) & CY);
+ EA = (EA << 1) | carry;
+}
+
+/* 48 bb: 0100 1000 1011 1011 */
+static void STOP(upd7810_state *cpustate)
+{
+ int cycles = (cpustate->icount / 4) * 4;
+ cpustate->icount -= cycles;
+ cpustate->handle_timers(cpustate, cycles);
+ PC -= 1;
+}
+
+/* 48 c0: 0100 1000 1100 0000 */
+static void DMOV_EA_ECNT(upd7810_state *cpustate)
+{
+ EA = ECNT;
+}
+
+/* 48 c1: 0100 1000 1100 0001 */
+static void DMOV_EA_ECPT(upd7810_state *cpustate)
+{
+ EA = ECPT;
+}
+
+/* 48 d2: 0100 1000 1101 0010 */
+static void DMOV_ETM0_EA(upd7810_state *cpustate)
+{
+ ETM0 = EA;
+}
+
+/* 48 d3: 0100 1000 1101 0011 */
+static void DMOV_ETM1_EA(upd7810_state *cpustate)
+{
+ ETM1 = EA;
+}
+
+/* prefix 4C */
+/* 4c c0: 0100 1100 1100 0000 */
+static void MOV_A_PA(upd7810_state *cpustate)
+{
+ A = RP( cpustate, UPD7810_PORTA );
+}
+
+/* 4c c1: 0100 1100 1100 0001 */
+static void MOV_A_PB(upd7810_state *cpustate)
+{
+ A = RP( cpustate, UPD7810_PORTB );
+}
+
+/* 4c c2: 0100 1100 1100 0010 */
+static void MOV_A_PC(upd7810_state *cpustate)
+{
+ A = RP( cpustate, UPD7810_PORTC );
+}
+
+/* 4c c3: 0100 1100 1100 0011 */
+static void MOV_A_PD(upd7810_state *cpustate)
+{
+ A = RP( cpustate, UPD7810_PORTD );
+}
+
+/* 4c c5: 0100 1100 1100 0101 */
+static void MOV_A_PF(upd7810_state *cpustate)
+{
+ A = RP( cpustate, UPD7810_PORTF );
+}
+
+/* 4c c6: 0100 1100 1100 0110 */
+static void MOV_A_MKH(upd7810_state *cpustate)
+{
+ A = MKH;
+}
+
+/* 4c c7: 0100 1100 1100 0111 */
+static void MOV_A_MKL(upd7810_state *cpustate)
+{
+ A = MKL;
+}
+
+/* 4c c8: 0100 1100 1100 1000 */
+static void MOV_A_ANM(upd7810_state *cpustate)
+{
+ A = ANM;
+}
+
+/* 4c c9: 0100 1100 1100 1001 */
+static void MOV_A_SMH(upd7810_state *cpustate)
+{
+ A = SMH;
+}
+
+/* 4c cb: 0100 1100 1100 1011 */
+static void MOV_A_EOM(upd7810_state *cpustate)
+{
+ /* only bits #1 and #5 can be read */
+ UINT8 eom = EOM & 0x22;
+ A = eom;
+}
+
+/* 4c cd: 0100 1100 1100 1101 */
+static void MOV_A_TMM(upd7810_state *cpustate)
+{
+ A = TMM;
+}
+
+/* 4c ce: 0100 1100 1110 0000 (7807 only) */
+static void MOV_A_PT(upd7810_state *cpustate)
+{
+ A = RP( cpustate, UPD7807_PORTT );
+}
+
+/* 4c d9: 0100 1100 1101 1001 */
+static void MOV_A_RXB(upd7810_state *cpustate)
+{
+ A = RXB;
+}
+
+/* 4c e0: 0100 1100 1110 0000 */
+static void MOV_A_CR0(upd7810_state *cpustate)
+{
+ A = CR0;
+}
+
+/* 4c e1: 0100 1100 1110 0001 */
+static void MOV_A_CR1(upd7810_state *cpustate)
+{
+ A = CR1;
+}
+
+/* 4c e2: 0100 1100 1110 0010 */
+static void MOV_A_CR2(upd7810_state *cpustate)
+{
+ A = CR2;
+}
+
+/* 4c e3: 0100 1100 1110 0011 */
+static void MOV_A_CR3(upd7810_state *cpustate)
+{
+ A = CR3;
+}
+
+/* prefix 4D */
+/* 4d c0: 0100 1101 1100 0000 */
+static void MOV_PA_A(upd7810_state *cpustate)
+{
+ WP( cpustate, UPD7810_PORTA, A );
+}
+
+/* 4d c1: 0100 1101 1100 0001 */
+static void MOV_PB_A(upd7810_state *cpustate)
+{
+ WP( cpustate, UPD7810_PORTB, A );
+}
+
+/* 4d c2: 0100 1101 1100 0010 */
+static void MOV_PC_A(upd7810_state *cpustate)
+{
+ WP( cpustate, UPD7810_PORTC, A );
+}
+
+/* 4d c3: 0100 1101 1100 0011 */
+static void MOV_PD_A(upd7810_state *cpustate)
+{
+ WP( cpustate, UPD7810_PORTD, A );
+}
+
+/* 4d c5: 0100 1101 1100 0101 */
+static void MOV_PF_A(upd7810_state *cpustate)
+{
+ WP( cpustate, UPD7810_PORTF, A );
+}
+
+/* 4d c6: 0100 1101 1100 0110 */
+static void MOV_MKH_A(upd7810_state *cpustate)
+{
+ MKH = A;
+}
+
+/* 4d c7: 0100 1101 1100 0111 */
+static void MOV_MKL_A(upd7810_state *cpustate)
+{
+ MKL = A;
+}
+
+/* 4d c8: 0100 1101 1100 1000 */
+static void MOV_ANM_A(upd7810_state *cpustate)
+{
+ ANM = A;
+}
+
+/* 4d c9: 0100 1101 1100 1001 */
+static void MOV_SMH_A(upd7810_state *cpustate)
+{
+ SMH = A;
+}
+
+/* 4d ca: 0100 1101 1100 1010 */
+static void MOV_SML_A(upd7810_state *cpustate)
+{
+ SML = A;
+}
+
+/* 4d cb: 0100 1101 1100 1011 */
+static void MOV_EOM_A(upd7810_state *cpustate)
+{
+ EOM = A;
+ upd7810_write_EOM(cpustate);
+}
+
+/* 4d cc: 0100 1101 1100 1100 */
+static void MOV_ETMM_A(upd7810_state *cpustate)
+{
+ ETMM = A;
+}
+
+/* 4d cd: 0100 1101 1100 1101 */
+static void MOV_TMM_A(upd7810_state *cpustate)
+{
+ TMM = A;
+}
+
+/* 4d d0: 0100 1101 1101 0000 */
+static void MOV_MM_A(upd7810_state *cpustate)
+{
+ MM = A;
+}
+
+/* 4d d1: 0100 1101 1101 0001 */
+static void MOV_MCC_A(upd7810_state *cpustate)
+{
+ MCC = A;
+}
+
+/* 4d d2: 0100 1101 1101 0010 */
+static void MOV_MA_A(upd7810_state *cpustate)
+{
+ MA = A;
+}
+
+/* 4d d3: 0100 1101 1101 0011 */
+static void MOV_MB_A(upd7810_state *cpustate)
+{
+ MB = A;
+}
+
+/* 4d d4: 0100 1101 1101 0100 */
+static void MOV_MC_A(upd7810_state *cpustate)
+{
+ MC = A;
+}
+
+/* 4d d7: 0100 1101 1101 0111 */
+static void MOV_MF_A(upd7810_state *cpustate)
+{
+ MF = A;
+}
+
+/* 4d d8: 0100 1101 1101 1000 */
+static void MOV_TXB_A(upd7810_state *cpustate)
+{
+ TXB = A;
+ upd7810_write_TXB(cpustate);
+}
+
+/* 4d da: 0100 1101 1101 1010 */
+static void MOV_TM0_A(upd7810_state *cpustate)
+{
+ TM0 = A;
+}
+
+/* 4d db: 0100 1101 1101 1011 */
+static void MOV_TM1_A(upd7810_state *cpustate)
+{
+ TM1 = A;
+}
+
+/* 4d e8: 0100 1101 1110 1000 */
+static void MOV_ZCM_A(upd7810_state *cpustate)
+{
+ ZCM = A;
+}
+
+/* prefix 60 */
+/* 60 08: 0110 0000 0000 1000 */
+static void ANA_V_A(upd7810_state *cpustate)
+{
+ V &= A;
+ SET_Z(V);
+}
+
+/* 60 09: 0110 0000 0000 1001 */
+static void ANA_A_A(upd7810_state *cpustate)
+{
+ A &= A;
+ SET_Z(A);
+}
+
+/* 60 0a: 0110 0000 0000 1010 */
+static void ANA_B_A(upd7810_state *cpustate)
+{
+ B &= A;
+ SET_Z(B);
+}
+
+/* 60 0b: 0110 0000 0000 1011 */
+static void ANA_C_A(upd7810_state *cpustate)
+{
+ C &= A;
+ SET_Z(C);
+}
+
+/* 60 0c: 0110 0000 0000 1100 */
+static void ANA_D_A(upd7810_state *cpustate)
+{
+ D &= A;
+ SET_Z(D);
+}
+
+/* 60 0d: 0110 0000 0000 1101 */
+static void ANA_E_A(upd7810_state *cpustate)
+{
+ E &= A;
+ SET_Z(E);
+}
+
+/* 60 0e: 0110 0000 0000 1110 */
+static void ANA_H_A(upd7810_state *cpustate)
+{
+ H &= A;
+ SET_Z(H);
+}
+
+/* 60 0f: 0110 0000 0000 1111 */
+static void ANA_L_A(upd7810_state *cpustate)
+{
+ L &= A;
+ SET_Z(L);
+}
+
+/* 60 10: 0110 0000 0001 0000 */
+static void XRA_V_A(upd7810_state *cpustate)
+{
+ V ^= A;
+ SET_Z(V);
+}
+
+/* 60 11: 0110 0000 0001 0001 */
+static void XRA_A_A(upd7810_state *cpustate)
+{
+ A ^= A;
+ SET_Z(A);
+}
+
+/* 60 12: 0110 0000 0001 0010 */
+static void XRA_B_A(upd7810_state *cpustate)
+{
+ B ^= A;
+ SET_Z(B);
+}
+
+/* 60 13: 0110 0000 0001 0011 */
+static void XRA_C_A(upd7810_state *cpustate)
+{
+ C ^= A;
+ SET_Z(C);
+}
+
+/* 60 14: 0110 0000 0001 0100 */
+static void XRA_D_A(upd7810_state *cpustate)
+{
+ D ^= A;
+ SET_Z(D);
+}
+
+/* 60 15: 0110 0000 0001 0101 */
+static void XRA_E_A(upd7810_state *cpustate)
+{
+ E ^= A;
+ SET_Z(E);
+}
+
+/* 60 16: 0110 0000 0001 0110 */
+static void XRA_H_A(upd7810_state *cpustate)
+{
+ H ^= A;
+ SET_Z(H);
+}
+
+/* 60 17: 0110 0000 0001 0111 */
+static void XRA_L_A(upd7810_state *cpustate)
+{
+ L ^= A;
+ SET_Z(L);
+}
+
+/* 60 18: 0110 0000 0001 1000 */
+static void ORA_V_A(upd7810_state *cpustate)
+{
+ V |= A;
+ SET_Z(V);
+}
+
+/* 60 19: 0110 0000 0001 1001 */
+static void ORA_A_A(upd7810_state *cpustate)
+{
+ A |= A;
+ SET_Z(A);
+}
+
+/* 60 1a: 0110 0000 0001 1010 */
+static void ORA_B_A(upd7810_state *cpustate)
+{
+ B |= A;
+ SET_Z(B);
+}
+
+/* 60 1b: 0110 0000 0001 1011 */
+static void ORA_C_A(upd7810_state *cpustate)
+{
+ C |= A;
+ SET_Z(C);
+}
+
+/* 60 1c: 0110 0000 0001 1100 */
+static void ORA_D_A(upd7810_state *cpustate)
+{
+ D |= A;
+ SET_Z(D);
+}
+
+/* 60 1d: 0110 0000 0001 1101 */
+static void ORA_E_A(upd7810_state *cpustate)
+{
+ E |= A;
+ SET_Z(E);
+}
+
+/* 60 1e: 0110 0000 0001 1110 */
+static void ORA_H_A(upd7810_state *cpustate)
+{
+ H |= A;
+ SET_Z(H);
+}
+
+/* 60 1f: 0110 0000 0001 1111 */
+static void ORA_L_A(upd7810_state *cpustate)
+{
+ L |= A;
+ SET_Z(L);
+}
+
+/* 60 20: 0110 0000 0010 0000 */
+static void ADDNC_V_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = V + A;
+ ZHC_ADD( tmp, V, 0 );
+ V = tmp;
+ SKIP_NC;
+}
+
+/* 60 21: 0110 0000 0010 0001 */
+static void ADDNC_A_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + A;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 60 22: 0110 0000 0010 0010 */
+static void ADDNC_B_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = B + A;
+ ZHC_ADD( tmp, B, 0 );
+ B = tmp;
+ SKIP_NC;
+}
+
+/* 60 23: 0110 0000 0010 0011 */
+static void ADDNC_C_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = C + A;
+ ZHC_ADD( tmp, C, 0 );
+ C = tmp;
+ SKIP_NC;
+}
+
+/* 60 24: 0110 0000 0010 0100 */
+static void ADDNC_D_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = D + A;
+ ZHC_ADD( tmp, D, 0 );
+ D = tmp;
+ SKIP_NC;
+}
+
+/* 60 25: 0110 0000 0010 0101 */
+static void ADDNC_E_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = E + A;
+ ZHC_ADD( tmp, E, 0 );
+ E = tmp;
+ SKIP_NC;
+}
+
+/* 60 26: 0110 0000 0010 0110 */
+static void ADDNC_H_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = H + A;
+ ZHC_ADD( tmp, H, 0 );
+ H = tmp;
+ SKIP_NC;
+}
+
+/* 60 27: 0110 0000 0010 0111 */
+static void ADDNC_L_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = L + A;
+ ZHC_ADD( tmp, L, 0 );
+ L = tmp;
+ SKIP_NC;
+}
+
+/* 60 28: 0110 0000 0010 1000 */
+static void GTA_V_A(upd7810_state *cpustate)
+{
+ UINT16 tmp = V - A - 1;
+ ZHC_SUB( tmp, V, 0 );
+ SKIP_NC;
+}
+
+/* 60 29: 0110 0000 0010 1001 */
+static void GTA_A_A(upd7810_state *cpustate)
+{
+ UINT16 tmp = A - A - 1;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NC;
+}
+
+/* 60 2a: 0110 0000 0010 1010 */
+static void GTA_B_A(upd7810_state *cpustate)
+{
+ UINT16 tmp = B - A - 1;
+ ZHC_SUB( tmp, B, 0 );
+ SKIP_NC;
+}
+
+/* 60 2b: 0110 0000 0010 1011 */
+static void GTA_C_A(upd7810_state *cpustate)
+{
+ UINT16 tmp = C - A - 1;
+ ZHC_SUB( tmp, C, 0 );
+ SKIP_NC;
+}
+
+/* 60 2c: 0110 0000 0010 1100 */
+static void GTA_D_A(upd7810_state *cpustate)
+{
+ UINT16 tmp = D - A - 1;
+ ZHC_SUB( tmp, D, 0 );
+ SKIP_NC;
+}
+
+/* 60 2d: 0110 0000 0010 1101 */
+static void GTA_E_A(upd7810_state *cpustate)
+{
+ UINT16 tmp = E - A - 1;
+ ZHC_SUB( tmp, E, 0 );
+ SKIP_NC;
+}
+
+/* 60 2e: 0110 0000 0010 1110 */
+static void GTA_H_A(upd7810_state *cpustate)
+{
+ UINT16 tmp = H - A - 1;
+ ZHC_SUB( tmp, H, 0 );
+ SKIP_NC;
+}
+
+/* 60 2f: 0110 0000 0010 1111 */
+static void GTA_L_A(upd7810_state *cpustate)
+{
+ UINT16 tmp = L - A - 1;
+ ZHC_SUB( tmp, L, 0 );
+ SKIP_NC;
+}
+
+/* 60 30: 0110 0000 0011 0000 */
+static void SUBNB_V_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = V - A;
+ ZHC_SUB( tmp, V, 0 );
+ V = tmp;
+ SKIP_NC;
+}
+
+/* 60 31: 0110 0000 0011 0001 */
+static void SUBNB_A_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - A;
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 60 32: 0110 0000 0011 0010 */
+static void SUBNB_B_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = B - A;
+ ZHC_SUB( tmp, B, 0 );
+ B = tmp;
+ SKIP_NC;
+}
+
+/* 60 33: 0110 0000 0011 0011 */
+static void SUBNB_C_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = C - A;
+ ZHC_SUB( tmp, C, 0 );
+ C = tmp;
+ SKIP_NC;
+}
+
+/* 60 34: 0110 0000 0011 0100 */
+static void SUBNB_D_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = D - A;
+ ZHC_SUB( tmp, D, 0 );
+ D = tmp;
+ SKIP_NC;
+}
+
+/* 60 35: 0110 0000 0011 0101 */
+static void SUBNB_E_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = E - A;
+ ZHC_SUB( tmp, E, 0 );
+ E = tmp;
+ SKIP_NC;
+}
+
+/* 60 36: 0110 0000 0011 0110 */
+static void SUBNB_H_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = H - A;
+ ZHC_SUB( tmp, H, 0 );
+ H = tmp;
+ SKIP_NC;
+}
+
+/* 60 37: 0110 0000 0011 0111 */
+static void SUBNB_L_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = L - A;
+ ZHC_SUB( tmp, L, 0 );
+ L = tmp;
+ SKIP_NC;
+}
+
+/* 60 38: 0110 0000 0011 1000 */
+static void LTA_V_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = V - A;
+ ZHC_SUB( tmp, V, 0 );
+ SKIP_CY;
+}
+
+/* 60 39: 0110 0000 0011 1001 */
+static void LTA_A_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - A;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_CY;
+}
+
+/* 60 3a: 0110 0000 0011 1010 */
+static void LTA_B_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = B - A;
+ ZHC_SUB( tmp, B, 0 );
+ SKIP_CY;
+}
+
+/* 60 3b: 0110 0000 0011 1011 */
+static void LTA_C_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = C - A;
+ ZHC_SUB( tmp, C, 0 );
+ SKIP_CY;
+}
+
+/* 60 3c: 0110 0000 0011 1100 */
+static void LTA_D_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = D - A;
+ ZHC_SUB( tmp, D, 0 );
+ SKIP_CY;
+}
+
+/* 60 3d: 0110 0000 0011 1101 */
+static void LTA_E_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = E - A;
+ ZHC_SUB( tmp, E, 0 );
+ SKIP_CY;
+}
+
+/* 60 3e: 0110 0000 0011 1110 */
+static void LTA_H_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = H - A;
+ ZHC_SUB( tmp, H, 0 );
+ SKIP_CY;
+}
+
+/* 60 3f: 0110 0000 0011 1111 */
+static void LTA_L_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = L - A;
+ ZHC_SUB( tmp, L, 0 );
+ SKIP_CY;
+}
+
+/* 60 40: 0110 0000 0100 0000 */
+static void ADD_V_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = V + A;
+ ZHC_ADD( tmp, V, 0 );
+ V = tmp;
+}
+
+/* 60 41: 0110 0000 0100 0001 */
+static void ADD_A_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + A;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 60 42: 0110 0000 0100 0010 */
+static void ADD_B_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = B + A;
+ ZHC_ADD( tmp, B, 0 );
+ B = tmp;
+}
+
+/* 60 43: 0110 0000 0100 0011 */
+static void ADD_C_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = C + A;
+ ZHC_ADD( tmp, C, 0 );
+ C = tmp;
+}
+
+/* 60 44: 0110 0000 0100 0100 */
+static void ADD_D_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = D + A;
+ ZHC_ADD( tmp, D, 0 );
+ D = tmp;
+}
+
+/* 60 45: 0110 0000 0100 0101 */
+static void ADD_E_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = E + A;
+ ZHC_ADD( tmp, E, 0 );
+ E = tmp;
+}
+
+/* 60 46: 0110 0000 0100 0110 */
+static void ADD_H_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = H + A;
+ ZHC_ADD( tmp, H, 0 );
+ H = tmp;
+}
+
+/* 60 47: 0110 0000 0100 0111 */
+static void ADD_L_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = L + A;
+ ZHC_ADD( tmp, L, 0 );
+ L = tmp;
+}
+
+/* 60 50: 0110 0000 0101 0000 */
+static void ADC_V_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = V + A + (PSW & CY);
+ ZHC_ADD( tmp, V, (PSW & CY) );
+ V = tmp;
+}
+
+/* 60 51: 0110 0000 0101 0001 */
+static void ADC_A_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + A + (PSW & CY);
+ ZHC_ADD( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 60 52: 0110 0000 0101 0010 */
+static void ADC_B_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = B + A + (PSW & CY);
+ ZHC_ADD( tmp, B, (PSW & CY) );
+ B = tmp;
+}
+
+/* 60 53: 0110 0000 0101 0011 */
+static void ADC_C_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = C + A + (PSW & CY);
+ ZHC_ADD( tmp, C, (PSW & CY) );
+ C = tmp;
+}
+
+/* 60 54: 0110 0000 0101 0100 */
+static void ADC_D_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = D + A + (PSW & CY);
+ ZHC_ADD( tmp, D, (PSW & CY) );
+ D = tmp;
+}
+
+/* 60 55: 0110 0000 0101 0101 */
+static void ADC_E_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = E + A + (PSW & CY);
+ ZHC_ADD( tmp, E, (PSW & CY) );
+ E = tmp;
+}
+
+/* 60 56: 0110 0000 0101 0110 */
+static void ADC_H_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = H + A + (PSW & CY);
+ ZHC_ADD( tmp, H, (PSW & CY) );
+ H = tmp;
+}
+
+/* 60 57: 0110 0000 0101 0111 */
+static void ADC_L_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = L + A + (PSW & CY);
+ ZHC_ADD( tmp, L, (PSW & CY) );
+ L = tmp;
+}
+
+/* 60 60: 0110 0000 0110 0000 */
+static void SUB_V_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = V - A;
+ ZHC_SUB( tmp, V, 0 );
+ V = tmp;
+}
+
+/* 60 61: 0110 0000 0110 0001 */
+static void SUB_A_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - A;
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 60 62: 0110 0000 0110 0010 */
+static void SUB_B_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = B - A;
+ ZHC_SUB( tmp, B, 0 );
+ B = tmp;
+}
+
+/* 60 63: 0110 0000 0110 0011 */
+static void SUB_C_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = C - A;
+ ZHC_SUB( tmp, C, 0 );
+ C = tmp;
+}
+
+/* 60 64: 0110 0000 0110 0100 */
+static void SUB_D_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = D - A;
+ ZHC_SUB( tmp, D, 0 );
+ D = tmp;
+}
+
+/* 60 65: 0110 0000 0110 0101 */
+static void SUB_E_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = E - A;
+ ZHC_SUB( tmp, E, 0 );
+ E = tmp;
+}
+
+/* 60 66: 0110 0000 0110 0110 */
+static void SUB_H_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = H - A;
+ ZHC_SUB( tmp, H, 0 );
+ H = tmp;
+}
+
+/* 60 67: 0110 0000 0110 0111 */
+static void SUB_L_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = L - A;
+ ZHC_SUB( tmp, L, 0 );
+ L = tmp;
+}
+
+/* 60 68: 0110 0000 0110 1000 */
+static void NEA_V_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = V - A;
+ ZHC_SUB( tmp, V, 0 );
+ SKIP_NZ;
+}
+
+/* 60 69: 0110 0000 0110 1001 */
+static void NEA_A_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - A;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NZ;
+}
+
+/* 60 6a: 0110 0000 0110 1010 */
+static void NEA_B_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = B - A;
+ ZHC_SUB( tmp, B, 0 );
+ SKIP_NZ;
+}
+
+/* 60 6b: 0110 0000 0110 1011 */
+static void NEA_C_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = C - A;
+ ZHC_SUB( tmp, C, 0 );
+ SKIP_NZ;
+}
+
+/* 60 6c: 0110 0000 0110 1100 */
+static void NEA_D_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = D - A;
+ ZHC_SUB( tmp, D, 0 );
+ SKIP_NZ;
+}
+
+/* 60 6d: 0110 0000 0110 1101 */
+static void NEA_E_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = E - A;
+ ZHC_SUB( tmp, E, 0 );
+ SKIP_NZ;
+}
+
+/* 60 6e: 0110 0000 0110 1110 */
+static void NEA_H_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = H - A;
+ ZHC_SUB( tmp, H, 0 );
+ SKIP_NZ;
+}
+
+/* 60 6f: 0110 0000 0110 1111 */
+static void NEA_L_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = L - A;
+ ZHC_SUB( tmp, L, 0 );
+ SKIP_NZ;
+}
+
+/* 60 70: 0110 0000 0111 0000 */
+static void SBB_V_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = V - A - (PSW & CY);
+ ZHC_SUB( tmp, V, (PSW & CY) );
+ V = tmp;
+}
+
+/* 60 71: 0110 0000 0111 0001 */
+static void SBB_A_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - A - (PSW & CY);
+ ZHC_SUB( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 60 72: 0110 0000 0111 0010 */
+static void SBB_B_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = B - A - (PSW & CY);
+ ZHC_SUB( tmp, B, (PSW & CY) );
+ B = tmp;
+}
+
+/* 60 73: 0110 0000 0111 0011 */
+static void SBB_C_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = C - A - (PSW & CY);
+ ZHC_SUB( tmp, C, (PSW & CY) );
+ C = tmp;
+}
+
+/* 60 74: 0110 0000 0111 0100 */
+static void SBB_D_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = D - A - (PSW & CY);
+ ZHC_SUB( tmp, D, (PSW & CY) );
+ D = tmp;
+}
+
+/* 60 75: 0110 0000 0111 0101 */
+static void SBB_E_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = E - A - (PSW & CY);
+ ZHC_SUB( tmp, E, (PSW & CY) );
+ E = tmp;
+}
+
+/* 60 76: 0110 0000 0111 0110 */
+static void SBB_H_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = H - A - (PSW & CY);
+ ZHC_SUB( tmp, H, (PSW & CY) );
+ H = tmp;
+}
+
+/* 60 77: 0110 0000 0111 0111 */
+static void SBB_L_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = L - A - (PSW & CY);
+ ZHC_SUB( tmp, L, (PSW & CY) );
+ L = tmp;
+}
+
+/* 60 78: 0110 0000 0111 1000 */
+static void EQA_V_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = V - A;
+ ZHC_SUB( tmp, V, 0 );
+ SKIP_Z;
+}
+
+/* 60 79: 0110 0000 0111 1001 */
+static void EQA_A_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - A;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_Z;
+}
+
+/* 60 7a: 0110 0000 0111 1010 */
+static void EQA_B_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = B - A;
+ ZHC_SUB( tmp, B, 0 );
+ SKIP_Z;
+}
+
+/* 60 7b: 0110 0000 0111 1011 */
+static void EQA_C_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = C - A;
+ ZHC_SUB( tmp, C, 0 );
+ SKIP_Z;
+}
+
+/* 60 7c: 0110 0000 0111 1100 */
+static void EQA_D_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = D - A;
+ ZHC_SUB( tmp, D, 0 );
+ SKIP_Z;
+}
+
+/* 60 7d: 0110 0000 0111 1101 */
+static void EQA_E_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = E - A;
+ ZHC_SUB( tmp, E, 0 );
+ SKIP_Z;
+}
+
+/* 60 7e: 0110 0000 0111 1110 */
+static void EQA_H_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = H - A;
+ ZHC_SUB( tmp, H, 0 );
+ SKIP_Z;
+}
+
+/* 60 7f: 0110 0000 0111 1111 */
+static void EQA_L_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = L - A;
+ ZHC_SUB( tmp, L, 0 );
+ SKIP_Z;
+}
+
+/* 60 88: 0110 0000 1000 1000 */
+static void ANA_A_V(upd7810_state *cpustate)
+{
+ A &= V;
+ SET_Z(A);
+}
+
+/* 60 89: 0110 0000 1000 1001 */
+/* ANA_A_A already defined */
+
+/* 60 8a: 0110 0000 1000 1010 */
+static void ANA_A_B(upd7810_state *cpustate)
+{
+ A &= B;
+ SET_Z(A);
+}
+
+/* 60 8b: 0110 0000 1000 1011 */
+static void ANA_A_C(upd7810_state *cpustate)
+{
+ A &= C;
+ SET_Z(A);
+}
+
+/* 60 8c: 0110 0000 1000 1100 */
+static void ANA_A_D(upd7810_state *cpustate)
+{
+ A &= D;
+ SET_Z(A);
+}
+
+/* 60 8d: 0110 0000 1000 1101 */
+static void ANA_A_E(upd7810_state *cpustate)
+{
+ A &= E;
+ SET_Z(A);
+}
+
+/* 60 8e: 0110 0000 1000 1110 */
+static void ANA_A_H(upd7810_state *cpustate)
+{
+ A &= H;
+ SET_Z(A);
+}
+
+/* 60 8f: 0110 0000 1000 1111 */
+static void ANA_A_L(upd7810_state *cpustate)
+{
+ A &= L;
+ SET_Z(A);
+}
+
+/* 60 90: 0110 0000 1001 0000 */
+static void XRA_A_V(upd7810_state *cpustate)
+{
+ A ^= V;
+ SET_Z(A);
+}
+
+/* 60 91: 0110 0000 1001 0001 */
+/* XRA_A_A already defined */
+
+/* 60 92: 0110 0000 1001 0010 */
+static void XRA_A_B(upd7810_state *cpustate)
+{
+ A ^= B;
+ SET_Z(A);
+}
+
+/* 60 93: 0110 0000 1001 0011 */
+static void XRA_A_C(upd7810_state *cpustate)
+{
+ A ^= C;
+ SET_Z(A);
+}
+
+/* 60 94: 0110 0000 1001 0100 */
+static void XRA_A_D(upd7810_state *cpustate)
+{
+ A ^= D;
+ SET_Z(A);
+}
+
+/* 60 95: 0110 0000 1001 0101 */
+static void XRA_A_E(upd7810_state *cpustate)
+{
+ A ^= E;
+ SET_Z(A);
+}
+
+/* 60 96: 0110 0000 1001 0110 */
+static void XRA_A_H(upd7810_state *cpustate)
+{
+ A ^= H;
+ SET_Z(A);
+}
+
+/* 60 97: 0110 0000 1001 0111 */
+static void XRA_A_L(upd7810_state *cpustate)
+{
+ A ^= L;
+ SET_Z(A);
+}
+
+/* 60 98: 0110 0000 1001 1000 */
+static void ORA_A_V(upd7810_state *cpustate)
+{
+ A |= V;
+ SET_Z(A);
+}
+
+/* 60 99: 0110 0000 1001 1001 */
+/* ORA_A_A already defined */
+
+/* 60 9a: 0110 0000 1001 1010 */
+static void ORA_A_B(upd7810_state *cpustate)
+{
+ A |= B;
+ SET_Z(A);
+}
+
+/* 60 9b: 0110 0000 1001 1011 */
+static void ORA_A_C(upd7810_state *cpustate)
+{
+ A |= C;
+ SET_Z(A);
+}
+
+/* 60 9c: 0110 0000 1001 1100 */
+static void ORA_A_D(upd7810_state *cpustate)
+{
+ A |= D;
+ SET_Z(A);
+}
+
+/* 60 9d: 0110 0000 1001 1101 */
+static void ORA_A_E(upd7810_state *cpustate)
+{
+ A |= E;
+ SET_Z(A);
+}
+
+/* 60 9e: 0110 0000 1001 1110 */
+static void ORA_A_H(upd7810_state *cpustate)
+{
+ A |= H;
+ SET_Z(A);
+}
+
+/* 60 9f: 0110 0000 1001 1111 */
+static void ORA_A_L(upd7810_state *cpustate)
+{
+ A |= L;
+ SET_Z(A);
+}
+
+/* 60 a0: 0110 0000 1010 0000 */
+static void ADDNC_A_V(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + V;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 60 a1: 0110 0000 1010 0001 */
+/* ADDNC_A_A already defined */
+
+/* 60 a2: 0110 0000 1010 0010 */
+static void ADDNC_A_B(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + B;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 60 a3: 0110 0000 1010 0011 */
+static void ADDNC_A_C(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + C;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 60 a4: 0110 0000 1010 0100 */
+static void ADDNC_A_D(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + D;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 60 a5: 0110 0000 1010 0101 */
+static void ADDNC_A_E(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + E;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 60 a6: 0110 0000 1010 0110 */
+static void ADDNC_A_H(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + H;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 60 a7: 0110 0000 1010 0111 */
+static void ADDNC_A_L(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + L;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 60 a8: 0110 0000 1010 1000 */
+static void GTA_A_V(upd7810_state *cpustate)
+{
+ UINT16 tmp = A - V - 1;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NC;
+}
+
+/* 60 a9: 0110 0000 1010 1001 */
+/* GTA_A_A already defined */
+
+/* 60 aa: 0110 0000 1010 1010 */
+static void GTA_A_B(upd7810_state *cpustate)
+{
+ UINT16 tmp = A - B - 1;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NC;
+}
+
+/* 60 ab: 0110 0000 1010 1011 */
+static void GTA_A_C(upd7810_state *cpustate)
+{
+ UINT16 tmp = A - C - 1;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NC;
+}
+
+/* 60 ac: 0110 0000 1010 1100 */
+static void GTA_A_D(upd7810_state *cpustate)
+{
+ UINT16 tmp = A - D - 1;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NC;
+}
+
+/* 60 ad: 0110 0000 1010 1101 */
+static void GTA_A_E(upd7810_state *cpustate)
+{
+ UINT16 tmp = A - E - 1;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NC;
+}
+
+/* 60 ae: 0110 0000 1010 1110 */
+static void GTA_A_H(upd7810_state *cpustate)
+{
+ UINT16 tmp = A - H - 1;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NC;
+}
+
+/* 60 af: 0110 0000 1010 1111 */
+static void GTA_A_L(upd7810_state *cpustate)
+{
+ UINT16 tmp = A - L - 1;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NC;
+}
+
+/* 60 b0: 0110 0000 1011 0000 */
+static void SUBNB_A_V(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - V;
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 60 b1: 0110 0000 1011 0001 */
+/* SUBNB_A_A already defined */
+
+/* 60 b2: 0110 0000 1011 0010 */
+static void SUBNB_A_B(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - B;
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 60 b3: 0110 0000 1011 0011 */
+static void SUBNB_A_C(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - C;
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 60 b4: 0110 0000 1011 0100 */
+static void SUBNB_A_D(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - D;
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 60 b5: 0110 0000 1011 0101 */
+static void SUBNB_A_E(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - E;
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 60 b6: 0110 0000 1011 0110 */
+static void SUBNB_A_H(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - H;
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 60 b7: 0110 0000 1011 0111 */
+static void SUBNB_A_L(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - L;
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 60 b8: 0110 0000 1011 1000 */
+static void LTA_A_V(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - V;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_CY;
+}
+
+/* 60 b9: 0110 0000 1011 1001 */
+/* LTA_A_A already defined */
+
+/* 60 ba: 0110 0000 1011 1010 */
+static void LTA_A_B(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - B;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_CY;
+}
+
+/* 60 bb: 0110 0000 1011 1011 */
+static void LTA_A_C(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - C;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_CY;
+}
+
+/* 60 bc: 0110 0000 1011 1100 */
+static void LTA_A_D(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - D;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_CY;
+}
+
+/* 60 bd: 0110 0000 1011 1101 */
+static void LTA_A_E(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - E;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_CY;
+}
+
+/* 60 be: 0110 0000 1011 1110 */
+static void LTA_A_H(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - H;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_CY;
+}
+
+/* 60 bf: 0110 0000 1011 1111 */
+static void LTA_A_L(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - L;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_CY;
+}
+
+/* 60 c0: 0110 0000 1100 0000 */
+static void ADD_A_V(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + V;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 60 c1: 0110 0000 1100 0001 */
+/* ADD_A_A already defined */
+
+/* 60 c2: 0110 0000 1100 0010 */
+static void ADD_A_B(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + B;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 60 c3: 0110 0000 1100 0011 */
+static void ADD_A_C(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + C;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 60 c4: 0110 0000 1100 0100 */
+static void ADD_A_D(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + D;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 60 c5: 0110 0000 1100 0101 */
+static void ADD_A_E(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + E;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 60 c6: 0110 0000 1100 0110 */
+static void ADD_A_H(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + H;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 60 c7: 0110 0000 1100 0111 */
+static void ADD_A_L(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + L;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 60 c8: 0110 0000 1100 1000 */
+static void ONA_A_V(upd7810_state *cpustate)
+{
+ if (A & V)
+ PSW = (PSW & ~Z) | SK;
+ else
+ PSW |= Z;
+}
+
+/* 60 c9: 0110 0000 1100 1001 */
+static void ONA_A_A(upd7810_state *cpustate)
+{
+ if (A & A)
+ PSW = (PSW & ~Z) | SK;
+ else
+ PSW |= Z;
+}
+
+/* 60 ca: 0110 0000 1100 1010 */
+static void ONA_A_B(upd7810_state *cpustate)
+{
+ if (A & B)
+ PSW = (PSW & ~Z) | SK;
+ else
+ PSW |= Z;
+}
+
+/* 60 cb: 0110 0000 1100 1011 */
+static void ONA_A_C(upd7810_state *cpustate)
+{
+ if (A & C)
+ PSW = (PSW & ~Z) | SK;
+ else
+ PSW |= Z;
+}
+
+/* 60 cc: 0110 0000 1100 1100 */
+static void ONA_A_D(upd7810_state *cpustate)
+{
+ if (A & D)
+ PSW = (PSW & ~Z) | SK;
+ else
+ PSW |= Z;
+}
+
+/* 60 cd: 0110 0000 1100 1101 */
+static void ONA_A_E(upd7810_state *cpustate)
+{
+ if (A & E)
+ PSW = (PSW & ~Z) | SK;
+ else
+ PSW |= Z;
+}
+
+/* 60 ce: 0110 0000 1100 1110 */
+static void ONA_A_H(upd7810_state *cpustate)
+{
+ if (A & H)
+ PSW = (PSW & ~Z) | SK;
+ else
+ PSW |= Z;
+}
+
+/* 60 cf: 0110 0000 1100 1111 */
+static void ONA_A_L(upd7810_state *cpustate)
+{
+ if (A & L)
+ PSW = (PSW & ~Z) | SK;
+ else
+ PSW |= Z;
+}
+
+/* 60 d0: 0110 0000 1101 0000 */
+static void ADC_A_V(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + V + (PSW & CY);
+ ZHC_ADD( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 60 d1: 0110 0000 1101 0001 */
+/* ADC_A_A already defined */
+
+/* 60 d2: 0110 0000 1101 0010 */
+static void ADC_A_B(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + B + (PSW & CY);
+ ZHC_ADD( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 60 d3: 0110 0000 1101 0011 */
+static void ADC_A_C(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + C + (PSW & CY);
+ ZHC_ADD( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 60 d4: 0110 0000 1101 0100 */
+static void ADC_A_D(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + D + (PSW & CY);
+ ZHC_ADD( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 60 d5: 0110 0000 1101 0101 */
+static void ADC_A_E(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + E + (PSW & CY);
+ ZHC_ADD( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 60 d6: 0110 0000 1101 0110 */
+static void ADC_A_H(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + H + (PSW & CY);
+ ZHC_ADD( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 60 d7: 0110 0000 1101 0111 */
+static void ADC_A_L(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + L + (PSW & CY);
+ ZHC_ADD( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 60 d8: 0110 0000 1101 1000 */
+static void OFFA_A_V(upd7810_state *cpustate)
+{
+ if ( A & V )
+ PSW &= ~Z;
+ else
+ PSW = PSW | Z | SK;
+}
+
+/* 60 d9: 0110 0000 1101 1001 */
+static void OFFA_A_A(upd7810_state *cpustate)
+{
+ if ( A & A )
+ PSW &= ~Z;
+ else
+ PSW = PSW | Z | SK;
+}
+
+/* 60 da: 0110 0000 1101 1010 */
+static void OFFA_A_B(upd7810_state *cpustate)
+{
+ if ( A & B )
+ PSW &= ~Z;
+ else
+ PSW = PSW | Z | SK;
+}
+
+/* 60 db: 0110 0000 1101 1011 */
+static void OFFA_A_C(upd7810_state *cpustate)
+{
+ if ( A & C )
+ PSW &= ~Z;
+ else
+ PSW = PSW | Z | SK;
+}
+
+/* 60 dc: 0110 0000 1101 1100 */
+static void OFFA_A_D(upd7810_state *cpustate)
+{
+ if ( A & D )
+ PSW &= ~Z;
+ else
+ PSW = PSW | Z | SK;
+}
+
+/* 60 dd: 0110 0000 1101 1101 */
+static void OFFA_A_E(upd7810_state *cpustate)
+{
+ if ( A & E )
+ PSW &= ~Z;
+ else
+ PSW = PSW | Z | SK;
+}
+
+/* 60 de: 0110 0000 1101 1110 */
+static void OFFA_A_H(upd7810_state *cpustate)
+{
+ if ( A & H )
+ PSW &= ~Z;
+ else
+ PSW = PSW | Z | SK;
+}
+
+/* 60 df: 0110 0000 1101 1111 */
+static void OFFA_A_L(upd7810_state *cpustate)
+{
+ if ( A & L )
+ PSW &= ~Z;
+ else
+ PSW = PSW | Z | SK;
+}
+
+/* 60 e0: 0110 0000 1110 0000 */
+static void SUB_A_V(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - V;
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 60 e1: 0110 0000 1110 0001 */
+/* SUB_A_A already defined */
+
+/* 60 e2: 0110 0000 1110 0010 */
+static void SUB_A_B(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - B;
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 60 e3: 0110 0000 1110 0011 */
+static void SUB_A_C(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - C;
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 60 e4: 0110 0000 1110 0100 */
+static void SUB_A_D(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - D;
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 60 e5: 0110 0000 1110 0101 */
+static void SUB_A_E(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - E;
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 60 e6: 0110 0000 1110 0110 */
+static void SUB_A_H(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - H;
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 60 e7: 0110 0000 1110 0111 */
+static void SUB_A_L(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - L;
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 60 e8: 0110 0000 1110 1000 */
+static void NEA_A_V(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - V;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NZ;
+}
+
+/* 60 e9: 0110 0000 1110 1001 */
+/* NEA_A_A already defined */
+
+/* 60 ea: 0110 0000 1110 1010 */
+static void NEA_A_B(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - B;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NZ;
+}
+
+/* 60 eb: 0110 0000 1110 1011 */
+static void NEA_A_C(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - C;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NZ;
+}
+
+/* 60 ec: 0110 0000 1110 1100 */
+static void NEA_A_D(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - D;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NZ;
+}
+
+/* 60 ed: 0110 0000 1110 1101 */
+static void NEA_A_E(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - E;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NZ;
+}
+
+/* 60 ee: 0110 0000 1110 1110 */
+static void NEA_A_H(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - H;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NZ;
+}
+
+/* 60 ef: 0110 0000 1110 1111 */
+static void NEA_A_L(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - L;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NZ;
+}
+
+/* 60 f0: 0110 0000 1111 0000 */
+static void SBB_A_V(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - V - (PSW & CY);
+ ZHC_SUB( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 60 f1: 0110 0000 1111 0001 */
+/* SBB_A_A already defined */
+
+/* 60 f2: 0110 0000 1111 0010 */
+static void SBB_A_B(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - B - (PSW & CY);
+ ZHC_SUB( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 60 f3: 0110 0000 1111 0011 */
+static void SBB_A_C(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - C - (PSW & CY);
+ ZHC_SUB( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 60 f4: 0110 0000 1111 0100 */
+static void SBB_A_D(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - D - (PSW & CY);
+ ZHC_SUB( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 60 f5: 0110 0000 1111 0101 */
+static void SBB_A_E(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - E - (PSW & CY);
+ ZHC_SUB( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 60 f6: 0110 0000 1111 0110 */
+static void SBB_A_H(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - H - (PSW & CY);
+ ZHC_SUB( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 60 f7: 0110 0000 1111 0111 */
+static void SBB_A_L(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - L - (PSW & CY);
+ ZHC_SUB( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 60 f8: 0110 0000 1111 1000 */
+static void EQA_A_V(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - V;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_Z;
+}
+
+/* 60 f9: 0110 0000 1111 1001 */
+/* EQA_A_A already defined */
+
+/* 60 fa: 0110 0000 1111 1010 */
+static void EQA_A_B(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - B;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_Z;
+}
+
+/* 60 fb: 0110 0000 1111 1011 */
+static void EQA_A_C(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - C;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_Z;
+}
+
+/* 60 fc: 0110 0000 1111 1100 */
+static void EQA_A_D(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - D;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_Z;
+}
+
+/* 60 fd: 0110 0000 1111 1101 */
+static void EQA_A_E(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - E;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_Z;
+}
+
+/* 60 fe: 0110 0000 1111 1110 */
+static void EQA_A_H(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - H;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_Z;
+}
+
+/* 60 ff: 0110 0000 1111 1111 */
+static void EQA_A_L(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - L;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_Z;
+}
+
+/* prefix 64 */
+/* 64 00: 0110 0100 0000 0000 xxxx xxxx */
+static void MVI_PA_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ WP( cpustate, UPD7810_PORTA, imm );
+}
+
+/* 64 01: 0110 0100 0000 0001 xxxx xxxx */
+static void MVI_PB_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ WP( cpustate, UPD7810_PORTB, imm );
+}
+
+/* 64 02: 0110 0100 0000 0010 xxxx xxxx */
+static void MVI_PC_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ WP( cpustate, UPD7810_PORTC, imm );
+}
+
+/* 64 03: 0110 0100 0000 0011 xxxx xxxx */
+static void MVI_PD_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ WP( cpustate, UPD7810_PORTD, imm );
+}
+
+/* 64 05: 0110 0100 0000 0101 xxxx xxxx */
+static void MVI_PF_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ WP( cpustate, UPD7810_PORTF, imm );
+}
+
+/* 64 06: 0110 0100 0000 0110 xxxx xxxx */
+static void MVI_MKH_xx(upd7810_state *cpustate)
+{
+ RDOPARG( MKH );
+}
+
+/* 64 07: 0110 0100 0000 0111 xxxx xxxx */
+static void MVI_MKL_xx(upd7810_state *cpustate)
+{
+ RDOPARG( MKL );
+}
+
+/* 64 08: 0110 0100 0000 1000 xxxx xxxx */
+static void ANI_PA_xx(upd7810_state *cpustate)
+{
+ UINT8 pa = RP( cpustate, UPD7810_PORTA), imm;
+ RDOPARG( imm );
+ pa &= imm;
+ WP( cpustate, UPD7810_PORTA, pa );
+ SET_Z(pa);
+}
+
+/* 64 09: 0110 0100 0000 1001 xxxx xxxx */
+static void ANI_PB_xx(upd7810_state *cpustate)
+{
+ UINT8 pb = RP( cpustate, UPD7810_PORTB), imm;
+ RDOPARG( imm );
+ pb &= imm;
+ WP( cpustate, UPD7810_PORTB, pb );
+ SET_Z(pb);
+}
+
+/* 64 0a: 0110 0100 0000 1010 xxxx xxxx */
+static void ANI_PC_xx(upd7810_state *cpustate)
+{
+ UINT8 pc = RP( cpustate, UPD7810_PORTC), imm;
+ RDOPARG( imm );
+ pc &= imm;
+ WP( cpustate, UPD7810_PORTC, pc );
+ SET_Z(pc);
+}
+
+/* 64 0b: 0110 0100 0000 1011 xxxx xxxx */
+static void ANI_PD_xx(upd7810_state *cpustate)
+{
+ UINT8 pd = RP( cpustate, UPD7810_PORTD ), imm;
+ RDOPARG( imm );
+ pd &= imm;
+ WP( cpustate, UPD7810_PORTD, pd );
+ SET_Z(pd);
+}
+
+/* 64 0d: 0110 0100 0000 1101 xxxx xxxx */
+static void ANI_PF_xx(upd7810_state *cpustate)
+{
+ UINT8 pf = RP( cpustate, UPD7810_PORTF ), imm;
+ RDOPARG( imm );
+ pf &= imm;
+ WP( cpustate, UPD7810_PORTF, pf );
+ SET_Z(pf);
+}
+
+/* 64 0e: 0110 0100 0000 1110 xxxx xxxx */
+static void ANI_MKH_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ MKH &= imm;
+ SET_Z(MKH);
+}
+
+/* 64 0f: 0110 0100 0000 1111 xxxx xxxx */
+static void ANI_MKL_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ MKL &= imm;
+ SET_Z(MKL);
+}
+
+/* 64 10: 0110 0100 0001 0000 xxxx xxxx */
+static void XRI_PA_xx(upd7810_state *cpustate)
+{
+ UINT8 pa = RP( cpustate, UPD7810_PORTA ), imm;
+ RDOPARG( imm );
+ pa ^= imm;
+ WP( cpustate, UPD7810_PORTA, pa );
+ SET_Z(pa);
+}
+
+/* 64 11: 0110 0100 0001 0001 xxxx xxxx */
+static void XRI_PB_xx(upd7810_state *cpustate)
+{
+ UINT8 pb = RP( cpustate, UPD7810_PORTB ), imm;
+ RDOPARG( imm );
+ pb ^= imm;
+ WP( cpustate, UPD7810_PORTB, pb );
+ SET_Z(pb);
+}
+
+/* 64 12: 0110 0100 0001 0010 xxxx xxxx */
+static void XRI_PC_xx(upd7810_state *cpustate)
+{
+ UINT8 pc = RP( cpustate, UPD7810_PORTC ), imm;
+ RDOPARG( imm );
+ pc ^= imm;
+ WP( cpustate, UPD7810_PORTC, pc );
+ SET_Z(pc);
+}
+
+/* 64 13: 0110 0100 0001 0011 xxxx xxxx */
+static void XRI_PD_xx(upd7810_state *cpustate)
+{
+ UINT8 pd = RP( cpustate, UPD7810_PORTD ), imm;
+ RDOPARG( imm );
+ pd ^= imm;
+ WP( cpustate, UPD7810_PORTD, pd );
+ SET_Z(pd);
+}
+
+/* 64 15: 0110 0100 0001 0101 xxxx xxxx */
+static void XRI_PF_xx(upd7810_state *cpustate)
+{
+ UINT8 pf = RP( cpustate, UPD7810_PORTF ), imm;
+ RDOPARG( imm );
+ pf ^= imm;
+ WP( cpustate, UPD7810_PORTF, pf );
+ SET_Z(pf);
+}
+
+/* 64 16: 0110 0100 0001 0110 xxxx xxxx */
+static void XRI_MKH_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ MKH ^= imm;
+ SET_Z(MKH);
+}
+
+/* 64 17: 0110 0100 0001 0111 xxxx xxxx */
+static void XRI_MKL_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ MKL ^= imm;
+ SET_Z(MKL);
+}
+
+/* 64 18: 0110 0100 0001 1000 xxxx xxxx */
+static void ORI_PA_xx(upd7810_state *cpustate)
+{
+ UINT8 pa = RP( cpustate, UPD7810_PORTA ), imm;
+ RDOPARG( imm );
+ pa |= imm;
+ WP( cpustate, UPD7810_PORTA, pa );
+ SET_Z(pa);
+}
+
+/* 64 19: 0110 0100 0001 1001 xxxx xxxx */
+static void ORI_PB_xx(upd7810_state *cpustate)
+{
+ UINT8 pb = RP( cpustate, UPD7810_PORTB ), imm;
+ RDOPARG( imm );
+ pb |= imm;
+ WP( cpustate, UPD7810_PORTB, pb );
+ SET_Z(pb);
+}
+
+/* 64 1a: 0110 0100 0001 1010 xxxx xxxx */
+static void ORI_PC_xx(upd7810_state *cpustate)
+{
+ UINT8 pc = RP( cpustate, UPD7810_PORTC ), imm;
+ RDOPARG( imm );
+ pc |= imm;
+ WP( cpustate, UPD7810_PORTC, pc );
+ SET_Z(pc);
+}
+
+/* 64 1b: 0110 0100 0001 1011 xxxx xxxx */
+static void ORI_PD_xx(upd7810_state *cpustate)
+{
+ UINT8 pd = RP( cpustate, UPD7810_PORTD ), imm;
+ RDOPARG( imm );
+ pd |= imm;
+ WP( cpustate, UPD7810_PORTD, pd );
+ SET_Z(pd);
+}
+
+/* 64 1d: 0110 0100 0001 1101 xxxx xxxx */
+static void ORI_PF_xx(upd7810_state *cpustate)
+{
+ UINT8 pf = RP( cpustate, UPD7810_PORTF ), imm;
+ RDOPARG( imm );
+ pf |= imm;
+ WP( cpustate, UPD7810_PORTF, pf );
+ SET_Z(pf);
+}
+
+/* 64 1e: 0110 0100 0001 1110 xxxx xxxx */
+static void ORI_MKH_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ MKH |= imm;
+ SET_Z(MKH);
+}
+
+/* 64 1f: 0110 0100 0001 1111 xxxx xxxx */
+static void ORI_MKL_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ MKL |= imm;
+ SET_Z(MKL);
+}
+
+/* 64 20: 0110 0100 0010 0000 xxxx xxxx */
+static void ADINC_PA_xx(upd7810_state *cpustate)
+{
+ UINT8 pa = RP( cpustate, UPD7810_PORTA );
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pa + imm;
+
+ ZHC_ADD( tmp, pa, 0 );
+ WP( cpustate, UPD7810_PORTA , tmp );
+ SKIP_NC;
+}
+
+/* 64 21: 0110 0100 0010 0001 xxxx xxxx */
+static void ADINC_PB_xx(upd7810_state *cpustate)
+{
+ UINT8 pb = RP( cpustate, UPD7810_PORTB );
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pb + imm;
+
+ ZHC_ADD( tmp, pb, 0 );
+ WP( cpustate, UPD7810_PORTB, tmp );
+ SKIP_NC;
+}
+
+/* 64 22: 0110 0100 0010 0010 xxxx xxxx */
+static void ADINC_PC_xx(upd7810_state *cpustate)
+{
+ UINT8 pc = RP( cpustate, UPD7810_PORTC );
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pc + imm;
+
+ ZHC_ADD( tmp, pc, 0 );
+ WP( cpustate, UPD7810_PORTC, tmp );
+ SKIP_NC;
+}
+
+/* 64 23: 0110 0100 0010 0011 xxxx xxxx */
+static void ADINC_PD_xx(upd7810_state *cpustate)
+{
+ UINT8 pd = RP( cpustate, UPD7810_PORTD );
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pd + imm;
+
+ ZHC_ADD( tmp, pd, 0 );
+ WP( cpustate, UPD7810_PORTD, tmp );
+ SKIP_NC;
+}
+
+/* 64 25: 0110 0100 0010 0101 xxxx xxxx */
+static void ADINC_PF_xx(upd7810_state *cpustate)
+{
+ UINT8 pf = RP( cpustate, UPD7810_PORTF );
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pf + imm;
+
+ ZHC_ADD( tmp, pf, 0 );
+ WP( cpustate, UPD7810_PORTF, tmp );
+ SKIP_NC;
+}
+
+/* 64 26: 0110 0100 0010 0110 xxxx xxxx */
+static void ADINC_MKH_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = MKH + imm;
+
+ ZHC_ADD( tmp, MKH, 0 );
+ MKH = tmp;
+ SKIP_NC;
+}
+
+/* 64 27: 0110 0100 0010 0111 xxxx xxxx */
+static void ADINC_MKL_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = MKL + imm;
+
+ ZHC_ADD( tmp, MKL, 0 );
+ MKL = tmp;
+ SKIP_NC;
+}
+
+/* 64 28: 0110 0100 0010 1000 xxxx xxxx */
+static void GTI_PA_xx(upd7810_state *cpustate)
+{
+ UINT8 pa = RP( cpustate, UPD7810_PORTA ), imm;
+ UINT16 tmp;
+
+ RDOPARG( imm );
+ tmp = pa - imm - 1;
+ ZHC_SUB( tmp, pa, 0 );
+
+ SKIP_NC;
+}
+
+/* 64 29: 0110 0100 0010 1001 xxxx xxxx */
+static void GTI_PB_xx(upd7810_state *cpustate)
+{
+ UINT8 pb = RP( cpustate, UPD7810_PORTB ), imm;
+ UINT16 tmp;
+
+ RDOPARG( imm );
+ tmp = pb - imm - 1;
+ ZHC_SUB( tmp, pb, 0 );
+
+ SKIP_NC;
+}
+
+/* 64 2a: 0110 0100 0010 1010 xxxx xxxx */
+static void GTI_PC_xx(upd7810_state *cpustate)
+{
+ UINT8 pc = RP( cpustate, UPD7810_PORTC ), imm;
+ UINT16 tmp;
+
+ RDOPARG( imm );
+ tmp = pc - imm - 1;
+ ZHC_SUB( tmp, pc, 0 );
+
+ SKIP_NC;
+}
+
+/* 64 2b: 0110 0100 0010 1011 xxxx xxxx */
+static void GTI_PD_xx(upd7810_state *cpustate)
+{
+ UINT8 pd = RP( cpustate, UPD7810_PORTD ), imm;
+ UINT16 tmp;
+
+ RDOPARG( imm );
+ tmp = pd - imm - 1;
+ ZHC_SUB( tmp, pd, 0 );
+
+ SKIP_NC;
+}
+
+/* 64 2d: 0110 0100 0010 1101 xxxx xxxx */
+static void GTI_PF_xx(upd7810_state *cpustate)
+{
+ UINT8 pf = RP( cpustate, UPD7810_PORTF ), imm;
+ UINT16 tmp;
+
+ RDOPARG( imm );
+ tmp = pf - imm - 1;
+ ZHC_SUB( tmp, pf, 0 );
+
+ SKIP_NC;
+}
+
+/* 64 2e: 0110 0100 0010 1110 xxxx xxxx */
+static void GTI_MKH_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ UINT16 tmp;
+
+ RDOPARG( imm );
+ tmp = MKH - imm - 1;
+ ZHC_SUB( tmp, MKH, 0 );
+
+ SKIP_NC;
+}
+
+/* 64 2f: 0110 0100 0010 1111 xxxx xxxx */
+static void GTI_MKL_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ UINT16 tmp;
+
+ RDOPARG( imm );
+ tmp = MKL - imm - 1;
+ ZHC_SUB( tmp, MKL, 0 );
+
+ SKIP_NC;
+}
+
+/* 64 30: 0110 0100 0011 0000 xxxx xxxx */
+static void SUINB_PA_xx(upd7810_state *cpustate)
+{
+ UINT8 pa = RP( cpustate, UPD7810_PORTA ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pa - imm;
+ ZHC_SUB( tmp, pa, 0 );
+ pa = tmp;
+ WP( cpustate, UPD7810_PORTA, pa );
+ SKIP_NC;
+}
+
+/* 64 31: 0110 0100 0011 0001 xxxx xxxx */
+static void SUINB_PB_xx(upd7810_state *cpustate)
+{
+ UINT8 pb = RP( cpustate, UPD7810_PORTB ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pb - imm;
+ ZHC_SUB( tmp, pb, 0 );
+ pb = tmp;
+ WP( cpustate, UPD7810_PORTB, pb );
+ SKIP_NC;
+}
+
+/* 64 32: 0110 0100 0011 0010 xxxx xxxx */
+static void SUINB_PC_xx(upd7810_state *cpustate)
+{
+ UINT8 pc = RP( cpustate, UPD7810_PORTC ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pc - imm;
+ ZHC_SUB( tmp, pc, 0 );
+ pc = tmp;
+ WP( cpustate, UPD7810_PORTC, pc );
+ SKIP_NC;
+}
+
+/* 64 33: 0110 0100 0011 0011 xxxx xxxx */
+static void SUINB_PD_xx(upd7810_state *cpustate)
+{
+ UINT8 pd = RP( cpustate, UPD7810_PORTD ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pd - imm;
+ ZHC_SUB( tmp, pd, 0 );
+ pd = tmp;
+ WP( cpustate, UPD7810_PORTD, pd );
+ SKIP_NC;
+}
+
+/* 64 35: 0110 0100 0011 0101 xxxx xxxx */
+static void SUINB_PF_xx(upd7810_state *cpustate)
+{
+ UINT8 pf = RP( cpustate, UPD7810_PORTF ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pf - imm;
+ ZHC_SUB( tmp, pf, 0 );
+ pf = tmp;
+ WP( cpustate, UPD7810_PORTF, pf );
+ SKIP_NC;
+}
+
+/* 64 36: 0110 0100 0011 0110 xxxx xxxx */
+static void SUINB_MKH_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = MKH - imm;
+ ZHC_SUB( tmp, MKH, 0 );
+ MKH = tmp;
+ SKIP_NC;
+}
+
+/* 64 37: 0110 0100 0011 0111 xxxx xxxx */
+static void SUINB_MKL_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = MKL - imm;
+ ZHC_SUB( tmp, MKL, 0 );
+ MKL = tmp;
+ SKIP_NC;
+}
+
+/* 64 38: 0110 0100 0011 1000 xxxx xxxx */
+static void LTI_PA_xx(upd7810_state *cpustate)
+{
+ UINT8 pa = RP( cpustate, UPD7810_PORTA ), tmp, imm;
+ RDOPARG( imm );
+ tmp = pa - imm;
+ ZHC_SUB( tmp, pa, 0 );
+ SKIP_CY;
+}
+
+/* 64 39: 0110 0100 0011 1001 xxxx xxxx */
+static void LTI_PB_xx(upd7810_state *cpustate)
+{
+ UINT8 pb = RP( cpustate, UPD7810_PORTB ), tmp, imm;
+ RDOPARG( imm );
+ tmp = pb - imm;
+ ZHC_SUB( tmp, pb, 0 );
+ SKIP_CY;
+}
+
+/* 64 3a: 0110 0100 0011 1010 xxxx xxxx */
+static void LTI_PC_xx(upd7810_state *cpustate)
+{
+ UINT8 pc = RP( cpustate, UPD7810_PORTC ), tmp, imm;
+ RDOPARG( imm );
+ tmp = pc - imm;
+ ZHC_SUB( tmp, pc, 0 );
+ SKIP_CY;
+}
+
+/* 64 3b: 0110 0100 0011 1011 xxxx xxxx */
+static void LTI_PD_xx(upd7810_state *cpustate)
+{
+ UINT8 pd = RP( cpustate, UPD7810_PORTD ), tmp, imm;
+ RDOPARG( imm );
+ tmp = pd - imm;
+ ZHC_SUB( tmp, pd, 0 );
+ SKIP_CY;
+}
+
+/* 64 3d: 0110 0100 0011 1101 xxxx xxxx */
+static void LTI_PF_xx(upd7810_state *cpustate)
+{
+ UINT8 pf = RP( cpustate, UPD7810_PORTF ), tmp, imm;
+ RDOPARG( imm );
+ tmp = pf - imm;
+ ZHC_SUB( tmp, pf, 0 );
+ SKIP_CY;
+}
+
+/* 64 3e: 0110 0100 0011 1110 xxxx xxxx */
+static void LTI_MKH_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = MKH - imm;
+ ZHC_SUB( tmp, MKH, 0 );
+ SKIP_CY;
+}
+
+/* 64 3f: 0110 0100 0011 1111 xxxx xxxx */
+static void LTI_MKL_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = MKL - imm;
+ ZHC_SUB( tmp, MKL, 0 );
+ SKIP_CY;
+}
+
+/* 64 40: 0110 0100 0100 0000 xxxx xxxx */
+static void ADI_PA_xx(upd7810_state *cpustate)
+{
+ UINT8 pa = RP( cpustate, UPD7810_PORTA ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pa + imm;
+ ZHC_ADD( tmp, pa, 0 );
+ pa = tmp;
+ WP( cpustate, UPD7810_PORTA, pa );
+}
+
+/* 64 41: 0110 0100 0100 0001 xxxx xxxx */
+static void ADI_PB_xx(upd7810_state *cpustate)
+{
+ UINT8 pb = RP( cpustate, UPD7810_PORTB ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pb + imm;
+ ZHC_ADD( tmp, pb, 0 );
+ pb = tmp;
+ WP( cpustate, UPD7810_PORTB, pb );
+}
+
+/* 64 42: 0110 0100 0100 0010 xxxx xxxx */
+static void ADI_PC_xx(upd7810_state *cpustate)
+{
+ UINT8 pc = RP( cpustate, UPD7810_PORTC ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pc + imm;
+ ZHC_ADD( tmp, pc, 0 );
+ pc = tmp;
+ WP( cpustate, UPD7810_PORTC, pc );
+}
+
+/* 64 43: 0110 0100 0100 0011 xxxx xxxx */
+static void ADI_PD_xx(upd7810_state *cpustate)
+{
+ UINT8 pd = RP( cpustate, UPD7810_PORTD ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pd + imm;
+ ZHC_ADD( tmp, pd, 0 );
+ pd = tmp;
+ WP( cpustate, UPD7810_PORTD, pd );
+}
+
+/* 64 45: 0110 0100 0100 0101 xxxx xxxx */
+static void ADI_PF_xx(upd7810_state *cpustate)
+{
+ UINT8 pf = RP( cpustate, UPD7810_PORTF ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pf + imm;
+ ZHC_ADD( tmp, pf, 0 );
+ pf = tmp;
+ WP( cpustate, UPD7810_PORTF, pf );
+}
+
+/* 64 46: 0110 0100 0100 0110 xxxx xxxx */
+static void ADI_MKH_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = MKH + imm;
+ ZHC_ADD( tmp, MKH, 0 );
+ MKH = tmp;
+}
+
+/* 64 47: 0110 0100 0100 0111 xxxx xxxx */
+static void ADI_MKL_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = MKL + imm;
+ ZHC_ADD( tmp, MKL, 0 );
+ MKL = tmp;
+}
+
+/* 64 48: 0110 0100 0100 1000 xxxx xxxx */
+static void ONI_PA_xx(upd7810_state *cpustate)
+{
+ UINT8 pa = RP( cpustate, UPD7810_PORTA ), imm;
+
+ RDOPARG( imm );
+ if (pa & imm)
+ PSW |= SK;
+}
+
+/* 64 49: 0110 0100 0100 1001 xxxx xxxx */
+static void ONI_PB_xx(upd7810_state *cpustate)
+{
+ UINT8 pb = RP( cpustate, UPD7810_PORTB ), imm;
+
+ RDOPARG( imm );
+ if (pb & imm)
+ PSW |= SK;
+}
+
+/* 64 4a: 0110 0100 0100 1010 xxxx xxxx */
+static void ONI_PC_xx(upd7810_state *cpustate)
+{
+ UINT8 pc = RP( cpustate, UPD7810_PORTC ), imm;
+
+ RDOPARG( imm );
+ if (pc & imm)
+ PSW |= SK;
+}
+
+/* 64 4b: 0110 0100 0100 1011 xxxx xxxx */
+static void ONI_PD_xx(upd7810_state *cpustate)
+{
+ UINT8 pd = RP( cpustate, UPD7810_PORTD ), imm;
+
+ RDOPARG( imm );
+ if (pd & imm)
+ PSW |= SK;
+}
+
+/* 64 4d: 0110 0100 0100 1101 xxxx xxxx */
+static void ONI_PF_xx(upd7810_state *cpustate)
+{
+ UINT8 pf = RP( cpustate, UPD7810_PORTF ), imm;
+
+ RDOPARG( imm );
+ if (pf & imm)
+ PSW |= SK;
+}
+
+/* 64 4e: 0110 0100 0100 1110 xxxx xxxx */
+static void ONI_MKH_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (MKH & imm)
+ PSW |= SK;
+}
+
+/* 64 4f: 0110 0100 0100 1111 xxxx xxxx */
+static void ONI_MKL_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (MKL & imm)
+ PSW |= SK;
+}
+
+/* 64 50: 0110 0100 0101 0000 xxxx xxxx */
+static void ACI_PA_xx(upd7810_state *cpustate)
+{
+ UINT8 pa = RP( cpustate, UPD7810_PORTA ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pa + imm + (PSW & CY);
+ ZHC_ADD( tmp, pa, (PSW & CY) );
+ pa = tmp;
+ WP( cpustate, UPD7810_PORTA, pa );
+}
+
+/* 64 51: 0110 0100 0101 0001 xxxx xxxx */
+static void ACI_PB_xx(upd7810_state *cpustate)
+{
+ UINT8 pb = RP( cpustate, UPD7810_PORTB ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pb + imm + (PSW & CY);
+ ZHC_ADD( tmp, pb, (PSW & CY) );
+ pb = tmp;
+ WP( cpustate, UPD7810_PORTB, pb );
+}
+
+/* 64 52: 0110 0100 0101 0010 xxxx xxxx */
+static void ACI_PC_xx(upd7810_state *cpustate)
+{
+ UINT8 pc = RP( cpustate, UPD7810_PORTC ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pc + imm + (PSW & CY);
+ ZHC_ADD( tmp, pc, (PSW & CY) );
+ pc = tmp;
+ WP( cpustate, UPD7810_PORTC, pc );
+}
+
+/* 64 53: 0110 0100 0101 0011 xxxx xxxx */
+static void ACI_PD_xx(upd7810_state *cpustate)
+{
+ UINT8 pd = RP( cpustate, UPD7810_PORTD ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pd + imm + (PSW & CY);
+ ZHC_ADD( tmp, pd, (PSW & CY) );
+ pd = tmp;
+ WP( cpustate, UPD7810_PORTD, pd );
+}
+
+/* 64 55: 0110 0100 0101 0101 xxxx xxxx */
+static void ACI_PF_xx(upd7810_state *cpustate)
+{
+ UINT8 pf = RP( cpustate, UPD7810_PORTF ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pf + imm + (PSW & CY);
+ ZHC_ADD( tmp, pf, (PSW & CY) );
+ pf = tmp;
+ WP( cpustate, UPD7810_PORTF, pf );
+}
+
+/* 64 56: 0110 0100 0101 0110 xxxx xxxx */
+static void ACI_MKH_xx(upd7810_state *cpustate)
+{
+ UINT8 imm, tmp;
+
+ RDOPARG( imm );
+ tmp = MKH + imm + (PSW & CY);
+ ZHC_ADD( tmp, MKH, (PSW & CY) );
+ MKH = tmp;
+}
+
+/* 64 57: 0110 0100 0101 0111 xxxx xxxx */
+static void ACI_MKL_xx(upd7810_state *cpustate)
+{
+ UINT8 imm, tmp;
+
+ RDOPARG( imm );
+ tmp = MKL + imm + (PSW & CY);
+ ZHC_ADD( tmp, MKL, (PSW & CY) );
+ MKL = tmp;
+}
+
+/* 64 58: 0110 0100 0101 1000 xxxx xxxx */
+static void OFFI_PA_xx(upd7810_state *cpustate)
+{
+ UINT8 pa = RP( cpustate, UPD7810_PORTA ), imm;
+
+ RDOPARG( imm );
+ if (0 == (pa & imm))
+ PSW |= SK;
+}
+
+/* 64 59: 0110 0100 0101 1001 xxxx xxxx */
+static void OFFI_PB_xx(upd7810_state *cpustate)
+{
+ UINT8 pb = RP( cpustate, UPD7810_PORTB ), imm;
+
+ RDOPARG( imm );
+ if (0 == (pb & imm))
+ PSW |= SK;
+}
+
+/* 64 5a: 0110 0100 0101 1010 xxxx xxxx */
+static void OFFI_PC_xx(upd7810_state *cpustate)
+{
+ UINT8 pc = RP( cpustate, UPD7810_PORTC ), imm;
+
+ RDOPARG( imm );
+ if (0 == (pc & imm))
+ PSW |= SK;
+}
+
+/* 64 5b: 0110 0100 0101 1011 xxxx xxxx */
+static void OFFI_PD_xx(upd7810_state *cpustate)
+{
+ UINT8 pd = RP( cpustate, UPD7810_PORTD ), imm;
+
+ RDOPARG( imm );
+ if (0 == (pd & imm))
+ PSW |= SK;
+}
+
+/* 64 5d: 0110 0100 0101 1101 xxxx xxxx */
+static void OFFI_PF_xx(upd7810_state *cpustate)
+{
+ UINT8 pf = RP( cpustate, UPD7810_PORTF ), imm;
+
+ RDOPARG( imm );
+ if (0 == (pf & imm))
+ PSW |= SK;
+}
+
+/* 64 5e: 0110 0100 0101 1110 xxxx xxxx */
+static void OFFI_MKH_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (0 == (MKH & imm))
+ PSW |= SK;
+}
+
+/* 64 5f: 0110 0100 0101 1111 xxxx xxxx */
+static void OFFI_MKL_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (0 == (MKL & imm))
+ PSW |= SK;
+}
+
+/* 64 60: 0110 0100 0110 0000 xxxx xxxx */
+static void SUI_PA_xx(upd7810_state *cpustate)
+{
+ UINT8 pa = RP( cpustate, UPD7810_PORTA ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pa - imm;
+ ZHC_SUB( tmp, pa, 0 );
+ pa = tmp;
+ WP( cpustate, UPD7810_PORTA, pa );
+}
+
+/* 64 61: 0110 0100 0110 0001 xxxx xxxx */
+static void SUI_PB_xx(upd7810_state *cpustate)
+{
+ UINT8 pb = RP( cpustate, UPD7810_PORTB ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pb - imm;
+ ZHC_SUB( tmp, pb, 0 );
+ pb = tmp;
+ WP( cpustate, UPD7810_PORTB, pb );
+}
+
+/* 64 62: 0110 0100 0110 0010 xxxx xxxx */
+static void SUI_PC_xx(upd7810_state *cpustate)
+{
+ UINT8 pc = RP( cpustate, UPD7810_PORTC ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pc - imm;
+ ZHC_SUB( tmp, pc, 0 );
+ pc = tmp;
+ WP( cpustate, UPD7810_PORTC, pc );
+}
+
+/* 64 63: 0110 0100 0110 0011 xxxx xxxx */
+static void SUI_PD_xx(upd7810_state *cpustate)
+{
+ UINT8 pd = RP( cpustate, UPD7810_PORTD ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pd - imm;
+ ZHC_SUB( tmp, pd, 0 );
+ pd = tmp;
+ WP( cpustate, UPD7810_PORTD, pd );
+}
+
+/* 64 65: 0110 0100 0110 0101 xxxx xxxx */
+static void SUI_PF_xx(upd7810_state *cpustate)
+{
+ UINT8 pf = RP( cpustate, UPD7810_PORTF ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pf - imm;
+ ZHC_SUB( tmp, pf, 0 );
+ pf = tmp;
+ WP( cpustate, UPD7810_PORTF, pf );
+}
+
+/* 64 66: 0110 0100 0110 0110 xxxx xxxx */
+static void SUI_MKH_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = MKH - imm;
+ ZHC_SUB( tmp, MKH, 0 );
+ MKH = tmp;
+}
+
+/* 64 67: 0110 0100 0110 0111 xxxx xxxx */
+static void SUI_MKL_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = MKL - imm;
+ ZHC_SUB( tmp, MKL, 0 );
+ MKL = tmp;
+}
+
+/* 64 68: 0110 0100 0110 1000 xxxx xxxx */
+static void NEI_PA_xx(upd7810_state *cpustate)
+{
+ UINT8 pa = RP( cpustate, UPD7810_PORTA ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pa - imm;
+ ZHC_SUB( tmp, pa, 0 );
+ SKIP_NZ;
+}
+
+/* 64 69: 0110 0100 0110 1001 xxxx xxxx */
+static void NEI_PB_xx(upd7810_state *cpustate)
+{
+ UINT8 pb = RP( cpustate, UPD7810_PORTB ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pb - imm;
+ ZHC_SUB( tmp, pb, 0 );
+ SKIP_NZ;
+}
+
+/* 64 6a: 0110 0100 0110 1010 xxxx xxxx */
+static void NEI_PC_xx(upd7810_state *cpustate)
+{
+ UINT8 pc = RP( cpustate, UPD7810_PORTC ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pc - imm;
+ ZHC_SUB( tmp, pc, 0 );
+ SKIP_NZ;
+}
+
+/* 64 6b: 0110 0100 0110 1011 xxxx xxxx */
+static void NEI_PD_xx(upd7810_state *cpustate)
+{
+ UINT8 pd = RP( cpustate, UPD7810_PORTD ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pd - imm;
+ ZHC_SUB( tmp, pd, 0 );
+ SKIP_NZ;
+}
+
+/* 64 6d: 0110 0100 0110 1101 xxxx xxxx */
+static void NEI_PF_xx(upd7810_state *cpustate)
+{
+ UINT8 pf = RP( cpustate, UPD7810_PORTF ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pf - imm;
+ ZHC_SUB( tmp, pf, 0 );
+ SKIP_NZ;
+}
+
+/* 64 6e: 0110 0100 0110 1110 xxxx xxxx */
+static void NEI_MKH_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = MKH - imm;
+ ZHC_SUB( tmp, MKH, 0 );
+ SKIP_NZ;
+}
+
+/* 64 6f: 0110 0100 0110 1111 xxxx xxxx */
+static void NEI_MKL_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = MKL - imm;
+ ZHC_SUB( tmp, MKL, 0 );
+ SKIP_NZ;
+}
+
+/* 64 70: 0110 0100 0111 0000 xxxx xxxx */
+static void SBI_PA_xx(upd7810_state *cpustate)
+{
+ UINT8 pa = RP( cpustate, UPD7810_PORTA ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pa - imm - (PSW & CY);
+ ZHC_SUB( tmp, pa, (PSW & CY) );
+ pa = tmp;
+ WP( cpustate, UPD7810_PORTA, pa );
+}
+
+/* 64 71: 0110 0100 0111 0001 xxxx xxxx */
+static void SBI_PB_xx(upd7810_state *cpustate)
+{
+ UINT8 pb = RP( cpustate, UPD7810_PORTB ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pb - imm - (PSW & CY);
+ ZHC_SUB( tmp, pb, (PSW & CY) );
+ pb = tmp;
+ WP( cpustate, UPD7810_PORTB, pb );
+}
+
+/* 64 72: 0110 0100 0111 0010 xxxx xxxx */
+static void SBI_PC_xx(upd7810_state *cpustate)
+{
+ UINT8 pc = RP( cpustate, UPD7810_PORTC ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pc - imm - (PSW & CY);
+ ZHC_SUB( tmp, pc, (PSW & CY) );
+ pc = tmp;
+ WP( cpustate, UPD7810_PORTC, pc );
+}
+
+/* 64 73: 0110 0100 0111 0011 xxxx xxxx */
+static void SBI_PD_xx(upd7810_state *cpustate)
+{
+ UINT8 pd = RP( cpustate, UPD7810_PORTD ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pd - imm - (PSW & CY);
+ ZHC_SUB( tmp, pd, (PSW & CY) );
+ pd = tmp;
+ WP( cpustate, UPD7810_PORTD, pd );
+}
+
+/* 64 75: 0110 0100 0111 0101 xxxx xxxx */
+static void SBI_PF_xx(upd7810_state *cpustate)
+{
+ UINT8 pf = RP( cpustate, UPD7810_PORTF ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pf - imm - (PSW & CY);
+ ZHC_SUB( tmp, pf, (PSW & CY) );
+ pf = tmp;
+ WP( cpustate, UPD7810_PORTF, pf );
+}
+
+/* 64 76: 0110 0100 0111 0110 xxxx xxxx */
+static void SBI_MKH_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = MKH - imm - (PSW & CY);
+ ZHC_SUB( tmp, MKH, (PSW & CY) );
+ MKH = tmp;
+}
+
+/* 64 77: 0110 0100 0111 0111 xxxx xxxx */
+static void SBI_MKL_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = MKL - imm - (PSW & CY);
+ ZHC_SUB( tmp, MKL, (PSW & CY) );
+ MKL = tmp;
+}
+
+/* 64 78: 0110 0100 0111 1000 xxxx xxxx */
+static void EQI_PA_xx(upd7810_state *cpustate)
+{
+ UINT8 pa = RP( cpustate, UPD7810_PORTA ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pa - imm;
+ ZHC_SUB( tmp, pa, 0 );
+ SKIP_Z;
+}
+
+/* 64 79: 0110 0100 0111 1001 xxxx xxxx */
+static void EQI_PB_xx(upd7810_state *cpustate)
+{
+ UINT8 pb = RP( cpustate, UPD7810_PORTB ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pb - imm;
+ ZHC_SUB( tmp, pb, 0 );
+ SKIP_Z;
+}
+
+/* 64 7a: 0110 0100 0111 1010 xxxx xxxx */
+static void EQI_PC_xx(upd7810_state *cpustate)
+{
+ UINT8 pc = RP( cpustate, UPD7810_PORTC ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pc - imm;
+ ZHC_SUB( tmp, pc, 0 );
+ SKIP_Z;
+}
+
+/* 64 7b: 0110 0100 0111 1011 xxxx xxxx */
+static void EQI_PD_xx(upd7810_state *cpustate)
+{
+ UINT8 pd = RP( cpustate, UPD7810_PORTD ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pd - imm;
+ ZHC_SUB( tmp, pd, 0 );
+ SKIP_Z;
+}
+
+/* 64 7d: 0110 0100 0111 1101 xxxx xxxx */
+static void EQI_PF_xx(upd7810_state *cpustate)
+{
+ UINT8 pf = RP( cpustate, UPD7810_PORTF ), tmp, imm;
+
+ RDOPARG( imm );
+ tmp = pf - imm;
+ ZHC_SUB( tmp, pf, 0 );
+ SKIP_Z;
+}
+
+/* 64 7e: 0110 0100 0111 1110 xxxx xxxx */
+static void EQI_MKH_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = MKH - imm;
+ ZHC_SUB( tmp, MKH, 0 );
+ SKIP_Z;
+}
+
+/* 64 7f: 0110 0100 0111 1111 xxxx xxxx */
+static void EQI_MKL_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = MKL - imm;
+ ZHC_SUB( tmp, MKL, 0 );
+ SKIP_Z;
+}
+
+/* 64 80: 0110 0100 1000 0000 xxxx xxxx */
+static void MVI_ANM_xx(upd7810_state *cpustate)
+{
+ RDOPARG( ANM );
+}
+
+/* 64 81: 0110 0100 1000 0001 xxxx xxxx */
+static void MVI_SMH_xx(upd7810_state *cpustate)
+{
+ RDOPARG( SMH );
+}
+
+/* 64 83: 0110 0100 1000 0011 xxxx xxxx */
+static void MVI_EOM_xx(upd7810_state *cpustate)
+{
+ RDOPARG( EOM );
+ upd7810_write_EOM(cpustate);
+}
+
+/* 64 85: 0110 0100 1000 0101 xxxx xxxx */
+static void MVI_TMM_xx(upd7810_state *cpustate)
+{
+ RDOPARG( TMM );
+}
+
+/* 64 88: 0110 0100 1000 1000 xxxx xxxx */
+static void ANI_ANM_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ ANM &= imm;
+ SET_Z(ANM);
+}
+
+/* 64 89: 0110 0100 1000 1001 xxxx xxxx */
+static void ANI_SMH_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ SMH &= imm;
+ SET_Z(SMH);
+}
+
+/* 64 8b: 0110 0100 1000 1011 xxxx xxxx */
+static void ANI_EOM_xx(upd7810_state *cpustate)
+{
+ /* only bits #1 and #5 can be read */
+ UINT8 eom = EOM & 0x22;
+ UINT8 imm;
+
+ RDOPARG( imm );
+ /* only bits #1 and #5 can be read */
+ EOM = eom & imm;
+ SET_Z(EOM);
+ upd7810_write_EOM(cpustate);
+}
+
+/* 64 8d: 0110 0100 1000 1101 xxxx xxxx */
+static void ANI_TMM_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ TMM &= imm;
+ SET_Z(TMM);
+}
+
+/* 64 90: 0110 0100 1001 0000 xxxx xxxx */
+static void XRI_ANM_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ ANM ^= imm;
+ SET_Z(ANM);
+}
+
+/* 64 91: 0110 0100 1001 0001 xxxx xxxx */
+static void XRI_SMH_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ SMH ^= imm;
+ SET_Z(SMH);
+}
+
+/* 64 93: 0110 0100 1001 0011 xxxx xxxx */
+static void XRI_EOM_xx(upd7810_state *cpustate)
+{
+ /* only bits #1 and #5 can be read */
+ UINT8 eom = EOM & 0x22;
+ UINT8 imm;
+
+ RDOPARG( imm );
+ /* only bits #1 and #5 can be read */
+ EOM = eom ^ imm;
+ SET_Z(EOM);
+ upd7810_write_EOM(cpustate);
+}
+
+/* 64 95: 0110 0100 1001 0101 xxxx xxxx */
+static void XRI_TMM_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ TMM ^= imm;
+ SET_Z(TMM);
+}
+
+/* 64 98: 0110 0100 1001 1000 xxxx xxxx */
+static void ORI_ANM_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ ANM |= imm;
+ SET_Z(ANM);
+}
+
+/* 64 99: 0110 0100 1001 1001 xxxx xxxx */
+static void ORI_SMH_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ SMH |= imm;
+ SET_Z(SMH);
+}
+
+/* 64 9b: 0110 0100 1001 1011 xxxx xxxx */
+static void ORI_EOM_xx(upd7810_state *cpustate)
+{
+ /* only bits #1 and #5 can be read */
+ UINT8 eom = EOM & 0x22;
+ UINT8 imm;
+
+ RDOPARG( imm );
+ /* only bits #1 and #5 can be read */
+ EOM = eom | imm;
+ SET_Z(EOM);
+ upd7810_write_EOM(cpustate);
+}
+
+/* 64 9d: 0110 0100 1001 1101 xxxx xxxx */
+static void ORI_TMM_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ TMM |= imm;
+ SET_Z(TMM);
+}
+
+/* 64 a0: 0110 0100 1010 0000 xxxx xxxx */
+static void ADINC_ANM_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = ANM + imm;
+
+ ZHC_ADD( tmp, ANM, 0 );
+ ANM = tmp;
+ SKIP_NC;
+}
+
+/* 64 a1: 0110 0100 1010 0001 xxxx xxxx */
+static void ADINC_SMH_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = SMH + imm;
+
+ ZHC_ADD( tmp, SMH, 0 );
+ SMH = tmp;
+ SKIP_NC;
+}
+
+/* 64 a3: 0110 0100 1010 0011 xxxx xxxx */
+static void ADINC_EOM_xx(upd7810_state *cpustate)
+{
+ /* only bits #1 and #5 can be read */
+ UINT8 eom = EOM & 0x22;
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ /* only bits #1 and #5 can be read */
+ tmp = eom + imm;
+
+ ZHC_ADD( tmp, eom, 0 );
+ EOM = tmp;
+ SKIP_NC;
+ upd7810_write_EOM(cpustate);
+}
+
+/* 64 a5: 0110 0100 1010 0101 xxxx xxxx */
+static void ADINC_TMM_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = TMM + imm;
+
+ ZHC_ADD( tmp, TMM, 0 );
+ TMM = tmp;
+ SKIP_NC;
+}
+
+/* 64 a8: 0110 0100 1010 1000 xxxx xxxx */
+static void GTI_ANM_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ UINT16 tmp;
+
+ RDOPARG( imm );
+ tmp = ANM - imm - 1;
+ ZHC_SUB( tmp, ANM, 0 );
+
+ SKIP_NC;
+}
+
+/* 64 a9: 0110 0100 1010 1001 xxxx xxxx */
+static void GTI_SMH_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ UINT16 tmp;
+
+ RDOPARG( imm );
+ tmp = SMH - imm - 1;
+ ZHC_SUB( tmp, SMH, 0 );
+
+ SKIP_NC;
+}
+
+/* 64 ab: 0110 0100 1010 1011 xxxx xxxx */
+static void GTI_EOM_xx(upd7810_state *cpustate)
+{
+ /* only bits #1 and #5 can be read */
+ UINT8 eom = EOM & 0x22;
+ UINT8 imm;
+ UINT16 tmp;
+
+ RDOPARG( imm );
+ tmp = eom - imm - 1;
+ ZHC_SUB( tmp, eom, 0 );
+
+ SKIP_NC;
+}
+
+/* 64 ad: 0110 0100 1010 1101 xxxx xxxx */
+static void GTI_TMM_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ UINT16 tmp;
+
+ RDOPARG( imm );
+ tmp = TMM - imm - 1;
+ ZHC_SUB( tmp, TMM, 0 );
+
+ SKIP_NC;
+}
+
+/* 64 b0: 0110 0100 1011 0000 xxxx xxxx */
+static void SUINB_ANM_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = ANM - imm;
+ ZHC_SUB( tmp, ANM, 0 );
+ ANM = tmp;
+ SKIP_NC;
+}
+
+/* 64 b1: 0110 0100 1011 0001 xxxx xxxx */
+static void SUINB_SMH_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = SMH - imm;
+ ZHC_SUB( tmp, SMH, 0 );
+ SMH = tmp;
+ SKIP_NC;
+}
+
+/* 64 b3: 0110 0100 1011 0011 xxxx xxxx */
+static void SUINB_EOM_xx(upd7810_state *cpustate)
+{
+ /* only bits #1 and #5 can be read */
+ UINT8 eom = EOM & 0x22;
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = eom - imm;
+ ZHC_SUB( tmp, eom, 0 );
+ EOM = tmp;
+ SKIP_NC;
+ upd7810_write_EOM(cpustate);
+}
+
+/* 64 b5: 0110 0100 1011 0101 xxxx xxxx */
+static void SUINB_TMM_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = TMM - imm;
+ ZHC_SUB( tmp, TMM, 0 );
+ TMM = tmp;
+ SKIP_NC;
+}
+
+/* 64 b8: 0110 0100 1011 1000 xxxx xxxx */
+static void LTI_ANM_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = ANM - imm;
+ ZHC_SUB( tmp, ANM, 0 );
+ SKIP_CY;
+}
+
+/* 64 b9: 0110 0100 1011 1001 xxxx xxxx */
+static void LTI_SMH_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = SMH - imm;
+ ZHC_SUB( tmp, SMH, 0 );
+ SKIP_CY;
+}
+
+/* 64 bb: 0110 0100 1011 1011 xxxx xxxx */
+static void LTI_EOM_xx(upd7810_state *cpustate)
+{
+ /* only bits #1 and #5 can be read */
+ UINT8 eom = EOM & 0x22;
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = eom - imm;
+ ZHC_SUB( tmp, eom, 0 );
+ SKIP_CY;
+}
+
+/* 64 bd: 0110 0100 1011 1101 xxxx xxxx */
+static void LTI_TMM_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = TMM - imm;
+ ZHC_SUB( tmp, TMM, 0 );
+ SKIP_CY;
+}
+
+/* 64 c0: 0110 0100 1100 0000 xxxx xxxx */
+static void ADI_ANM_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = ANM + imm;
+
+ ZHC_ADD( tmp, ANM, 0 );
+ ANM = tmp;
+}
+
+/* 64 c1: 0110 0100 1100 0001 xxxx xxxx */
+static void ADI_SMH_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = SMH + imm;
+
+ ZHC_ADD( tmp, SMH, 0 );
+ SMH = tmp;
+}
+
+/* 64 c3: 0110 0100 1100 0011 xxxx xxxx */
+static void ADI_EOM_xx(upd7810_state *cpustate)
+{
+ /* only bits #1 and #5 can be read */
+ UINT8 eom = EOM & 0x22;
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = eom + imm;
+
+ ZHC_ADD( tmp, eom, 0 );
+ EOM = tmp;
+ upd7810_write_EOM(cpustate);
+}
+
+/* 64 c5: 0110 0100 1100 0101 xxxx xxxx */
+static void ADI_TMM_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = TMM + imm;
+
+ ZHC_ADD( tmp, TMM, 0 );
+ TMM = tmp;
+}
+
+/* 64 c8: 0110 0100 1100 1000 xxxx xxxx */
+static void ONI_ANM_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (ANM & imm)
+ PSW |= SK;
+}
+
+/* 64 c9: 0110 0100 1100 1001 xxxx xxxx */
+static void ONI_SMH_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (SMH & imm)
+ PSW |= SK;
+}
+
+/* 64 cb: 0110 0100 1100 1011 xxxx xxxx */
+static void ONI_EOM_xx(upd7810_state *cpustate)
+{
+ /* only bits #1 and #5 can be read */
+ UINT8 eom = EOM & 0x22;
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (eom & imm)
+ PSW |= SK;
+}
+
+/* 64 cd: 0110 0100 1100 1101 xxxx xxxx */
+static void ONI_TMM_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (TMM & imm)
+ PSW |= SK;
+}
+
+/* 64 d0: 0110 0100 1101 0000 xxxx xxxx */
+static void ACI_ANM_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = ANM + imm + (PSW & CY);
+
+ ZHC_ADD( tmp, ANM, (PSW & CY) );
+ ANM = tmp;
+}
+
+/* 64 d1: 0110 0100 1101 0001 xxxx xxxx */
+static void ACI_SMH_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = SMH + imm + (PSW & CY);
+
+ ZHC_ADD( tmp, SMH, (PSW & CY) );
+ SMH = tmp;
+}
+
+/* 64 d3: 0110 0100 1101 0011 xxxx xxxx */
+static void ACI_EOM_xx(upd7810_state *cpustate)
+{
+ /* only bits #1 and #5 can be read */
+ UINT8 eom = EOM & 0x22;
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = eom + imm + (PSW & CY);
+
+ ZHC_ADD( tmp, eom, (PSW & CY) );
+ EOM = tmp;
+ upd7810_write_EOM(cpustate);
+}
+
+/* 64 d5: 0110 0100 1101 0101 xxxx xxxx */
+static void ACI_TMM_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = TMM + imm + (PSW & CY);
+
+ ZHC_ADD( tmp, TMM, (PSW & CY) );
+ TMM = tmp;
+}
+
+/* 64 d8: 0110 0100 1101 1000 xxxx xxxx */
+static void OFFI_ANM_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (0 == (ANM & imm))
+ PSW |= SK;
+}
+
+/* 64 d9: 0110 0100 1101 1001 xxxx xxxx */
+static void OFFI_SMH_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (0 == (SMH & imm))
+ PSW |= SK;
+}
+
+/* 64 db: 0110 0100 1101 1011 xxxx xxxx */
+static void OFFI_EOM_xx(upd7810_state *cpustate)
+{
+ /* only bits #1 and #5 can be read */
+ UINT8 eom = EOM & 0x22;
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (0 == (eom & imm))
+ PSW |= SK;
+}
+
+/* 64 dd: 0110 0100 1101 1101 xxxx xxxx */
+static void OFFI_TMM_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (0 == (TMM & imm))
+ PSW |= SK;
+}
+
+/* 64 e0: 0110 0100 1110 0000 xxxx xxxx */
+static void SUI_ANM_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = ANM - imm;
+ ZHC_SUB( tmp, ANM, 0 );
+ ANM = tmp;
+}
+
+/* 64 e1: 0110 0100 1110 0001 xxxx xxxx */
+static void SUI_SMH_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = SMH - imm;
+ ZHC_SUB( tmp, SMH, 0 );
+ SMH = tmp;
+}
+
+/* 64 e3: 0110 0100 1110 0011 xxxx xxxx */
+static void SUI_EOM_xx(upd7810_state *cpustate)
+{
+ /* only bits #1 and #5 can be read */
+ UINT8 eom = EOM & 0x22;
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = eom - imm;
+ ZHC_SUB( tmp, eom, 0 );
+ EOM = tmp;
+ upd7810_write_EOM(cpustate);
+}
+
+/* 64 e5: 0110 0100 1110 0101 xxxx xxxx */
+static void SUI_TMM_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = TMM - imm;
+ ZHC_SUB( tmp, TMM, 0 );
+ TMM = tmp;
+}
+
+/* 64 e8: 0110 0100 1110 1000 xxxx xxxx */
+static void NEI_ANM_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = ANM - imm;
+ ZHC_SUB( tmp, ANM, 0 );
+ SKIP_NZ;
+}
+
+/* 64 e9: 0110 0100 1110 1001 xxxx xxxx */
+static void NEI_SMH_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = SMH - imm;
+ ZHC_SUB( tmp, SMH, 0 );
+ SKIP_NZ;
+}
+
+/* 64 eb: 0110 0100 1110 1011 xxxx xxxx */
+static void NEI_EOM_xx(upd7810_state *cpustate)
+{
+ /* only bits #1 and #5 can be read */
+ UINT8 eom = EOM & 0x22;
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = eom - imm;
+ ZHC_SUB( tmp, eom, 0 );
+ SKIP_NZ;
+}
+
+/* 64 ed: 0110 0100 1110 1101 xxxx xxxx */
+static void NEI_TMM_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = TMM - imm;
+ ZHC_SUB( tmp, TMM, 0 );
+ SKIP_NZ;
+}
+
+/* 64 f0: 0110 0100 1111 0000 xxxx xxxx */
+static void SBI_ANM_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = ANM - imm - (PSW & CY);
+ ZHC_SUB( tmp, ANM, (PSW & CY) );
+ ANM = tmp;
+}
+
+/* 64 f1: 0110 0100 1111 0001 xxxx xxxx */
+static void SBI_SMH_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = SMH - imm - (PSW & CY);
+ ZHC_SUB( tmp, SMH, (PSW & CY) );
+ SMH = tmp;
+}
+
+/* 64 f3: 0110 0100 1111 0011 xxxx xxxx */
+static void SBI_EOM_xx(upd7810_state *cpustate)
+{
+ /* only bits #1 and #5 can be read */
+ UINT8 eom = EOM & 0x22;
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = eom - imm - (PSW & CY);
+ ZHC_SUB( tmp, eom, (PSW & CY) );
+ EOM = tmp;
+ upd7810_write_EOM(cpustate);
+}
+
+/* 64 f5: 0110 0100 1111 0101 xxxx xxxx */
+static void SBI_TMM_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = TMM - imm - (PSW & CY);
+ ZHC_SUB( tmp, TMM, (PSW & CY) );
+ TMM = tmp;
+}
+
+/* 64 f8: 0110 0100 1111 1000 xxxx xxxx */
+static void EQI_ANM_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = ANM - imm;
+ ZHC_SUB( tmp, ANM, 0 );
+ SKIP_Z;
+}
+
+/* 64 f9: 0110 0100 1111 1001 xxxx xxxx */
+static void EQI_SMH_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = SMH - imm;
+ ZHC_SUB( tmp, SMH, 0 );
+ SKIP_Z;
+}
+
+/* 64 fb: 0110 0100 1111 1011 xxxx xxxx */
+static void EQI_EOM_xx(upd7810_state *cpustate)
+{
+ /* only bits #1 and #5 can be read */
+ UINT8 eom = EOM & 0x22;
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = eom - imm;
+ ZHC_SUB( tmp, eom, 0 );
+ SKIP_Z;
+}
+
+/* 64 fd: 0110 0100 1111 1101 xxxx xxxx */
+static void EQI_TMM_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = TMM - imm;
+ ZHC_SUB( tmp, TMM, 0 );
+ SKIP_Z;
+}
+
+/* prefix 70 */
+/* 70 0e: 0111 0000 0000 1110 llll llll hhhh hhhh */
+static void SSPD_w(upd7810_state *cpustate)
+{
+ PAIR ea;
+ ea.d = 0;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( ea.b.h );
+ WM( ea.d, SPL );
+ WM( ea.d + 1, SPH );
+}
+
+/* 70 0f: 0111 0000 0000 1111 llll llll hhhh hhhh */
+static void LSPD_w(upd7810_state *cpustate)
+{
+ PAIR ea;
+ ea.d = 0;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( ea.b.h );
+ SPL = RM( ea.d );
+ SPH = RM( ea.d + 1 );
+}
+
+/* 70 1e: 0111 0000 0001 1110 llll llll hhhh hhhh */
+static void SBCD_w(upd7810_state *cpustate)
+{
+ PAIR ea;
+ ea.d = 0;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( ea.b.h );
+ WM( ea.d, C );
+ WM( ea.d + 1, B );
+}
+
+/* 70 1f: 0111 0000 0001 1111 llll llll hhhh hhhh */
+static void LBCD_w(upd7810_state *cpustate)
+{
+ PAIR ea;
+ ea.d = 0;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( ea.b.h );
+ C = RM( ea.d );
+ B = RM( ea.d + 1 );
+}
+
+/* 70 2e: 0111 0000 0010 1110 llll llll hhhh hhhh */
+static void SDED_w(upd7810_state *cpustate)
+{
+ PAIR ea;
+ ea.d = 0;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( ea.b.h );
+ WM( ea.d, E );
+ WM( ea.d + 1, D );
+}
+
+/* 70 2f: 0111 0000 0010 1111 llll llll hhhh hhhh */
+static void LDED_w(upd7810_state *cpustate)
+{
+ PAIR ea;
+ ea.d = 0;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( ea.b.h );
+ E = RM( ea.d );
+ D = RM( ea.d + 1 );
+}
+
+/* 70 3e: 0111 0000 0011 1110 llll llll hhhh hhhh */
+static void SHLD_w(upd7810_state *cpustate)
+{
+ PAIR ea;
+ ea.d = 0;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( ea.b.h );
+ WM( ea.d, L );
+ WM( ea.d + 1, H );
+}
+
+/* 70 3f: 0111 0000 0011 1111 llll llll hhhh hhhh */
+static void LHLD_w(upd7810_state *cpustate)
+{
+ PAIR ea;
+ ea.d = 0;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( ea.b.h );
+ L = RM( ea.d );
+ H = RM( ea.d + 1 );
+}
+
+/* 70 41: 0111 0000 0100 0001 */
+static void EADD_EA_A(upd7810_state *cpustate)
+{
+ UINT16 tmp;
+ tmp = EA + A;
+ ZHC_ADD( tmp, EA, 0 );
+ EA = tmp;
+}
+
+/* 70 42: 0111 0000 0100 0010 */
+static void EADD_EA_B(upd7810_state *cpustate)
+{
+ UINT16 tmp;
+ tmp = EA + B;
+ ZHC_ADD( tmp, EA, 0 );
+ EA = tmp;
+}
+
+/* 70 43: 0111 0000 0100 0011 */
+static void EADD_EA_C(upd7810_state *cpustate)
+{
+ UINT16 tmp;
+ tmp = EA + C;
+ ZHC_ADD( tmp, EA, 0 );
+ EA = tmp;
+}
+
+/* 70 61: 0111 0000 0110 0001 */
+static void ESUB_EA_A(upd7810_state *cpustate)
+{
+ UINT16 tmp;
+ tmp = EA - A;
+ ZHC_SUB( tmp, EA, 0 );
+ EA = tmp;
+}
+
+/* 70 62: 0111 0000 0110 0010 */
+static void ESUB_EA_B(upd7810_state *cpustate)
+{
+ UINT16 tmp;
+ tmp = EA - B;
+ ZHC_SUB( tmp, EA, 0 );
+ EA = tmp;
+}
+
+/* 70 63: 0111 0000 0110 0011 */
+static void ESUB_EA_C(upd7810_state *cpustate)
+{
+ UINT16 tmp;
+ tmp = EA - C;
+ ZHC_SUB( tmp, EA, 0 );
+ EA = tmp;
+}
+
+/* 70 68: 0111 0000 0110 1000 llll llll hhhh hhhh */
+static void MOV_V_w(upd7810_state *cpustate)
+{
+ PAIR ea;
+ ea.d = 0;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( ea.b.h );
+ V = RM( ea.d );
+}
+
+/* 70 69: 0111 0000 0110 1001 llll llll hhhh hhhh */
+static void MOV_A_w(upd7810_state *cpustate)
+{
+ PAIR ea;
+ ea.d = 0;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( ea.b.h );
+ A = RM( ea.d );
+}
+
+/* 70 6a: 0111 0000 0110 1010 llll llll hhhh hhhh */
+static void MOV_B_w(upd7810_state *cpustate)
+{
+ PAIR ea;
+ ea.d = 0;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( ea.b.h );
+ B = RM( ea.d );
+}
+
+/* 70 6b: 0111 0000 0110 1011 llll llll hhhh hhhh */
+static void MOV_C_w(upd7810_state *cpustate)
+{
+ PAIR ea;
+ ea.d = 0;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( ea.b.h );
+ C = RM( ea.d );
+}
+
+/* 70 6c: 0111 0000 0110 1100 llll llll hhhh hhhh */
+static void MOV_D_w(upd7810_state *cpustate)
+{
+ PAIR ea;
+ ea.d = 0;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( ea.b.h );
+ D = RM( ea.d );
+}
+
+/* 70 6d: 0111 0000 0110 1101 llll llll hhhh hhhh */
+static void MOV_E_w(upd7810_state *cpustate)
+{
+ PAIR ea;
+ ea.d = 0;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( ea.b.h );
+ E = RM( ea.d );
+}
+
+/* 70 6e: 0111 0000 0110 1110 llll llll hhhh hhhh */
+static void MOV_H_w(upd7810_state *cpustate)
+{
+ PAIR ea;
+ ea.d = 0;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( ea.b.h );
+ H = RM( ea.d );
+}
+
+/* 70 6f: 0111 0000 0110 1111 llll llll hhhh hhhh */
+static void MOV_L_w(upd7810_state *cpustate)
+{
+ PAIR ea;
+ ea.d = 0;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( ea.b.h );
+ L = RM( ea.d );
+}
+
+/* 70 78: 0111 0000 0111 1000 llll llll hhhh hhhh */
+static void MOV_w_V(upd7810_state *cpustate)
+{
+ PAIR ea;
+ ea.d = 0;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( ea.b.h );
+ WM( ea.d, V );
+}
+
+/* 70 79: 0111 0000 0111 1001 llll llll hhhh hhhh */
+static void MOV_w_A(upd7810_state *cpustate)
+{
+ PAIR ea;
+ ea.d = 0;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( ea.b.h );
+ WM( ea.d, A );
+}
+
+/* 70 7a: 0111 0000 0111 1010 llll llll hhhh hhhh */
+static void MOV_w_B(upd7810_state *cpustate)
+{
+ PAIR ea;
+ ea.d = 0;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( ea.b.h );
+ WM( ea.d, B );
+}
+
+/* 70 7b: 0111 0000 0111 1011 llll llll hhhh hhhh */
+static void MOV_w_C(upd7810_state *cpustate)
+{
+ PAIR ea;
+ ea.d = 0;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( ea.b.h );
+ WM( ea.d, C );
+}
+
+/* 70 7c: 0111 0000 0111 1100 llll llll hhhh hhhh */
+static void MOV_w_D(upd7810_state *cpustate)
+{
+ PAIR ea;
+ ea.d = 0;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( ea.b.h );
+ WM( ea.d, D );
+}
+
+/* 70 7d: 0111 0000 0111 1101 llll llll hhhh hhhh */
+static void MOV_w_E(upd7810_state *cpustate)
+{
+ PAIR ea;
+ ea.d = 0;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( ea.b.h );
+ WM( ea.d, E );
+}
+
+/* 70 7e: 0111 0000 0111 1110 llll llll hhhh hhhh */
+static void MOV_w_H(upd7810_state *cpustate)
+{
+ PAIR ea;
+ ea.d = 0;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( ea.b.h );
+ WM( ea.d, H );
+}
+
+/* 70 7f: 0111 0000 0111 1111 llll llll hhhh hhhh */
+static void MOV_w_L(upd7810_state *cpustate)
+{
+ PAIR ea;
+ ea.d = 0;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( ea.b.h );
+ WM( ea.d, L );
+}
+
+/* 70 89: 0111 0000 1000 1001 */
+static void ANAX_B(upd7810_state *cpustate)
+{
+ A &= RM( BC );
+ SET_Z(A);
+}
+
+/* 70 8a: 0111 0000 1000 1010 */
+static void ANAX_D(upd7810_state *cpustate)
+{
+ A &= RM( DE );
+ SET_Z(A);
+}
+
+/* 70 8b: 0111 0000 1000 1011 */
+static void ANAX_H(upd7810_state *cpustate)
+{
+ A &= RM( HL );
+ SET_Z(A);
+}
+
+/* 70 8c: 0111 0000 1000 1100 */
+static void ANAX_Dp(upd7810_state *cpustate)
+{
+ A &= RM( DE );
+ DE++;
+ SET_Z(A);
+}
+
+/* 70 8d: 0111 0000 1000 1101 */
+static void ANAX_Hp(upd7810_state *cpustate)
+{
+ A &= RM( HL );
+ HL++;
+ SET_Z(A);
+}
+
+/* 70 8e: 0111 0000 1000 1110 */
+static void ANAX_Dm(upd7810_state *cpustate)
+{
+ A &= RM( DE );
+ DE--;
+ SET_Z(A);
+}
+
+/* 70 8f: 0111 0000 1000 1111 */
+static void ANAX_Hm(upd7810_state *cpustate)
+{
+ A &= RM( HL );
+ HL--;
+ SET_Z(A);
+}
+
+/* 70 91: 0111 0000 1001 0001 */
+static void XRAX_B(upd7810_state *cpustate)
+{
+ A ^= RM( BC );
+ SET_Z(A);
+}
+
+/* 70 92: 0111 0000 1001 0010 */
+static void XRAX_D(upd7810_state *cpustate)
+{
+ A ^= RM( DE );
+ SET_Z(A);
+}
+
+/* 70 93: 0111 0000 1001 0011 */
+static void XRAX_H(upd7810_state *cpustate)
+{
+ A ^= RM( HL );
+ SET_Z(A);
+}
+
+/* 70 94: 0111 0000 1001 0100 */
+static void XRAX_Dp(upd7810_state *cpustate)
+{
+ A ^= RM( DE );
+ DE++;
+ SET_Z(A);
+}
+
+/* 70 95: 0111 0000 1001 0101 */
+static void XRAX_Hp(upd7810_state *cpustate)
+{
+ A ^= RM( HL );
+ HL++;
+ SET_Z(A);
+}
+
+/* 70 96: 0111 0000 1001 0110 */
+static void XRAX_Dm(upd7810_state *cpustate)
+{
+ A ^= RM( DE );
+ DE--;
+ SET_Z(A);
+}
+
+/* 70 97: 0111 0000 1001 0111 */
+static void XRAX_Hm(upd7810_state *cpustate)
+{
+ A ^= RM( HL );
+ HL--;
+ SET_Z(A);
+}
+
+/* 70 99: 0111 0000 1001 1001 */
+static void ORAX_B(upd7810_state *cpustate)
+{
+ A |= RM( BC );
+ SET_Z(A);
+}
+
+/* 70 9a: 0111 0000 1001 1010 */
+static void ORAX_D(upd7810_state *cpustate)
+{
+ A |= RM( DE );
+ SET_Z(A);
+}
+
+/* 70 9b: 0111 0000 1001 1011 */
+static void ORAX_H(upd7810_state *cpustate)
+{
+ A |= RM( HL );
+ SET_Z(A);
+}
+
+/* 70 9c: 0111 0000 1001 0100 */
+static void ORAX_Dp(upd7810_state *cpustate)
+{
+ A |= RM( DE );
+ DE++;
+ SET_Z(A);
+}
+
+/* 70 9d: 0111 0000 1001 1101 */
+static void ORAX_Hp(upd7810_state *cpustate)
+{
+ A |= RM( HL );
+ HL++;
+ SET_Z(A);
+}
+
+/* 70 9e: 0111 0000 1001 1110 */
+static void ORAX_Dm(upd7810_state *cpustate)
+{
+ A |= RM( DE );
+ DE--;
+ SET_Z(A);
+}
+
+/* 70 9f: 0111 0000 1001 1111 */
+static void ORAX_Hm(upd7810_state *cpustate)
+{
+ A |= RM( HL );
+ HL--;
+ SET_Z(A);
+}
+
+/* 70 a1: 0111 0000 1010 0001 */
+static void ADDNCX_B(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + RM( BC );
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 70 a2: 0111 0000 1010 0010 */
+static void ADDNCX_D(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + RM( DE );
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 70 a3: 0111 0000 1010 0011 */
+static void ADDNCX_H(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + RM( HL );
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 70 a4: 0111 0000 1010 0100 */
+static void ADDNCX_Dp(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + RM( DE );
+ DE++;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 70 a5: 0111 0000 1010 0101 */
+static void ADDNCX_Hp(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + RM( HL );
+ HL++;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 70 a6: 0111 0000 1010 0110 */
+static void ADDNCX_Dm(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + RM( DE );
+ DE--;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 70 a7: 0111 0000 1010 0111 */
+static void ADDNCX_Hm(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + RM( HL );
+ HL--;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 70 a9: 0111 0000 1010 1001 */
+static void GTAX_B(upd7810_state *cpustate)
+{
+ UINT16 tmp = A - RM( BC ) - 1;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NC;
+}
+
+/* 70 aa: 0111 0000 1010 1010 */
+static void GTAX_D(upd7810_state *cpustate)
+{
+ UINT16 tmp = A - RM( DE ) - 1;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NC;
+}
+
+/* 70 ab: 0111 0000 1010 1011 */
+static void GTAX_H(upd7810_state *cpustate)
+{
+ UINT16 tmp = A - RM( HL ) - 1;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NC;
+}
+
+/* 70 ac: 0111 0000 1010 1100 */
+static void GTAX_Dp(upd7810_state *cpustate)
+{
+ UINT16 tmp = A - RM( DE ) - 1;
+ DE++;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NC;
+}
+
+/* 70 ad: 0111 0000 1010 1101 */
+static void GTAX_Hp(upd7810_state *cpustate)
+{
+ UINT16 tmp = A - RM( HL ) - 1;
+ HL++;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NC;
+}
+
+/* 70 ae: 0111 0000 1010 1110 */
+static void GTAX_Dm(upd7810_state *cpustate)
+{
+ UINT16 tmp = A - RM( DE ) - 1;
+ DE--;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NC;
+}
+
+/* 70 af: 0111 0000 1010 1111 */
+static void GTAX_Hm(upd7810_state *cpustate)
+{
+ UINT16 tmp = A - RM( HL ) - 1;
+ HL--;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NC;
+}
+
+/* 70 b1: 0111 0000 1011 0001 */
+static void SUBNBX_B(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( BC );
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 70 b2: 0111 0000 1011 0010 */
+static void SUBNBX_D(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( DE );
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 70 b3: 0111 0000 1011 0011 */
+static void SUBNBX_H(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( HL );
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 70 b4: 0111 0000 1011 0100 */
+static void SUBNBX_Dp(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( DE );
+ DE++;
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 70 b5: 0111 0000 1011 0101 */
+static void SUBNBX_Hp(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( HL );
+ HL++;
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 70 b6: 0111 0000 1011 0110 */
+static void SUBNBX_Dm(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( DE );
+ DE--;
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 70 b7: 0111 0000 1011 0111 */
+static void SUBNBX_Hm(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( HL );
+ HL--;
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 70 b9: 0111 0000 1011 1001 */
+static void LTAX_B(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( BC );
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_CY;
+}
+
+/* 70 ba: 0111 0000 1011 1010 */
+static void LTAX_D(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( DE );
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_CY;
+}
+
+/* 70 bb: 0111 0000 1011 1011 */
+static void LTAX_H(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( HL );
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_CY;
+}
+
+/* 70 bc: 0111 0000 1011 1100 */
+static void LTAX_Dp(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( DE );
+ DE++;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_CY;
+}
+
+/* 70 bd: 0111 0000 1011 1101 */
+static void LTAX_Hp(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( HL );
+ HL++;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_CY;
+}
+
+/* 70 be: 0111 0000 1011 1110 */
+static void LTAX_Dm(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( DE );
+ DE--;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_CY;
+}
+
+/* 70 bf: 0111 0000 1011 1111 */
+static void LTAX_Hm(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( HL );
+ HL--;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_CY;
+}
+
+/* 70 c1: 0111 0000 1100 0001 */
+static void ADDX_B(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + RM( BC );
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 70 c2: 0111 0000 1100 0010 */
+static void ADDX_D(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + RM( DE );
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 70 c3: 0111 0000 1100 0011 */
+static void ADDX_H(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + RM( HL );
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 70 c4: 0111 0000 1100 0100 */
+static void ADDX_Dp(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + RM( DE );
+ DE++;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 70 c5: 0111 0000 1100 0101 */
+static void ADDX_Hp(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + RM( HL );
+ HL++;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 70 c6: 0111 0000 1100 0110 */
+static void ADDX_Dm(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + RM( DE );
+ DE--;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 70 c7: 0111 0000 1100 0111 */
+static void ADDX_Hm(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + RM( HL );
+ HL--;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 70 c9: 0111 0000 1100 1001 */
+static void ONAX_B(upd7810_state *cpustate)
+{
+ if (A & RM( BC ))
+ PSW = (PSW & ~Z) | SK;
+ else
+ PSW |= Z;
+}
+
+/* 70 ca: 0111 0000 1100 1010 */
+static void ONAX_D(upd7810_state *cpustate)
+{
+ if (A & RM( DE ))
+ PSW = (PSW & ~Z) | SK;
+ else
+ PSW |= Z;
+}
+
+/* 70 cb: 0111 0000 1100 1011 */
+static void ONAX_H(upd7810_state *cpustate)
+{
+ if (A & RM( HL ))
+ PSW = (PSW & ~Z) | SK;
+ else
+ PSW |= Z;
+}
+
+/* 70 cc: 0111 0000 1100 1100 */
+static void ONAX_Dp(upd7810_state *cpustate)
+{
+ if (A & RM( DE ))
+ PSW = (PSW & ~Z) | SK;
+ else
+ PSW |= Z;
+ DE++;
+}
+
+/* 70 cd: 0111 0000 1100 1101 */
+static void ONAX_Hp(upd7810_state *cpustate)
+{
+ if (A & RM( HL ))
+ PSW = (PSW & ~Z) | SK;
+ else
+ PSW |= Z;
+ HL++;
+}
+
+/* 70 ce: 0111 0000 1100 1110 */
+static void ONAX_Dm(upd7810_state *cpustate)
+{
+ if (A & RM( DE ))
+ PSW = (PSW & ~Z) | SK;
+ else
+ PSW |= Z;
+ DE--;
+}
+
+/* 70 cf: 0111 0000 1100 1111 */
+static void ONAX_Hm(upd7810_state *cpustate)
+{
+ if (A & RM( HL ))
+ PSW = (PSW & ~Z) | SK;
+ else
+ PSW |= Z;
+ HL--;
+}
+
+/* 70 d1: 0111 0000 1101 0001 */
+static void ADCX_B(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + RM( BC ) + (PSW & CY);
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 70 d2: 0111 0000 1101 0010 */
+static void ADCX_D(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + RM( DE ) + (PSW & CY);
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 70 d3: 0111 0000 1101 0011 */
+static void ADCX_H(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + RM( HL ) + (PSW & CY);
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 70 d4: 0111 0000 1101 0100 */
+static void ADCX_Dp(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + RM( DE ) + (PSW & CY);
+ DE++;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 70 d5: 0111 0000 1101 0101 */
+static void ADCX_Hp(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + RM( HL ) + (PSW & CY);
+ HL++;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 70 d6: 0111 0000 1101 0110 */
+static void ADCX_Dm(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + RM( DE ) + (PSW & CY);
+ DE--;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 70 d7: 0111 0000 1101 0111 */
+static void ADCX_Hm(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + RM( HL ) + (PSW & CY);
+ HL--;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 70 d9: 0111 0000 1101 1001 */
+static void OFFAX_B(upd7810_state *cpustate)
+{
+ if ( A & RM( BC ) )
+ PSW &= ~Z;
+ else
+ PSW = PSW | Z | SK;
+}
+
+/* 70 da: 0111 0000 1101 1010 */
+static void OFFAX_D(upd7810_state *cpustate)
+{
+ if ( A & RM( DE ) )
+ PSW &= ~Z;
+ else
+ PSW = PSW | Z | SK;
+}
+
+/* 70 db: 0111 0000 1101 1011 */
+static void OFFAX_H(upd7810_state *cpustate)
+{
+ if ( A & RM( HL ) )
+ PSW &= ~Z;
+ else
+ PSW = PSW | Z | SK;
+}
+
+/* 70 dc: 0111 0000 1101 1100 */
+static void OFFAX_Dp(upd7810_state *cpustate)
+{
+ if ( A & RM( DE ) )
+ PSW &= ~Z;
+ else
+ PSW = PSW | Z | SK;
+ DE++;
+}
+
+/* 70 dd: 0111 0000 1101 1101 */
+static void OFFAX_Hp(upd7810_state *cpustate)
+{
+ if ( A & RM( HL ) )
+ PSW &= ~Z;
+ else
+ PSW = PSW | Z | SK;
+ HL++;
+}
+
+/* 70 de: 0111 0000 1101 1110 */
+static void OFFAX_Dm(upd7810_state *cpustate)
+{
+ if ( A & RM( DE ) )
+ PSW &= ~Z;
+ else
+ PSW = PSW | Z | SK;
+ DE--;
+}
+
+/* 70 df: 0111 0000 1101 1111 */
+static void OFFAX_Hm(upd7810_state *cpustate)
+{
+ if ( A & RM( HL ) )
+ PSW &= ~Z;
+ else
+ PSW = PSW | Z | SK;
+ HL--;
+}
+
+/* 70 e1: 0111 0000 1110 0001 */
+static void SUBX_B(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( BC );
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 70 e2: 0111 0000 1110 0010 */
+static void SUBX_D(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( DE );
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 70 e3: 0111 0000 1110 0011 */
+static void SUBX_H(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( HL );
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 70 e4: 0111 0000 1110 0100 */
+static void SUBX_Dp(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( DE );
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+ DE++;
+}
+
+/* 70 e5: 0111 0000 1110 0101 */
+static void SUBX_Hp(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( HL );
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+ HL++;
+}
+
+/* 70 e6: 0111 0000 1110 0110 */
+static void SUBX_Dm(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( DE );
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+ DE--;
+}
+
+/* 70 e7: 0111 0000 1110 0111 */
+static void SUBX_Hm(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( HL );
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+ HL--;
+}
+
+/* 70 e9: 0111 0000 1110 1001 */
+static void NEAX_B(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( BC );
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NZ;
+}
+
+/* 70 ea: 0111 0000 1110 1010 */
+static void NEAX_D(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( DE );
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NZ;
+}
+
+/* 70 eb: 0111 0000 1110 1011 */
+static void NEAX_H(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( HL );
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NZ;
+}
+
+/* 70 ec: 0111 0000 1110 1100 */
+static void NEAX_Dp(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( DE );
+ DE++;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NZ;
+}
+
+/* 70 ed: 0111 0000 1110 1101 */
+static void NEAX_Hp(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( HL );
+ HL++;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NZ;
+}
+
+/* 70 ee: 0111 0000 1110 1110 */
+static void NEAX_Dm(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( DE );
+ DE--;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NZ;
+}
+
+/* 70 ef: 0111 0000 1110 1111 */
+static void NEAX_Hm(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( HL );
+ HL--;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NZ;
+}
+
+/* 70 f1: 0111 0000 1111 0001 */
+static void SBBX_B(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( BC ) - (PSW & CY);
+ ZHC_SUB( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 70 f2: 0111 0000 1111 0010 */
+static void SBBX_D(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( DE ) - (PSW & CY);
+ ZHC_SUB( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 70 f3: 0111 0000 1111 0011 */
+static void SBBX_H(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( HL ) - (PSW & CY);
+ ZHC_SUB( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 70 f4: 0111 0000 1111 0100 */
+static void SBBX_Dp(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( DE ) - (PSW & CY);
+ DE++;
+ ZHC_SUB( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 70 f5: 0111 0000 1111 0101 */
+static void SBBX_Hp(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( HL ) - (PSW & CY);
+ HL++;
+ ZHC_SUB( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 70 f6: 0111 0000 1111 0110 */
+static void SBBX_Dm(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( DE ) - (PSW & CY);
+ DE--;
+ ZHC_SUB( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 70 f7: 0111 0000 1111 0111 */
+static void SBBX_Hm(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( HL ) - (PSW & CY);
+ HL--;
+ ZHC_SUB( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 70 f9: 0111 0000 1111 1001 */
+static void EQAX_B(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( BC );
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_Z;
+}
+
+/* 70 fa: 0111 0000 1111 1010 */
+static void EQAX_D(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( DE );
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_Z;
+}
+
+/* 70 fb: 0111 0000 1111 1011 */
+static void EQAX_H(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( HL );
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_Z;
+}
+
+/* 70 fc: 0111 0000 1111 1100 */
+static void EQAX_Dp(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( DE );
+ DE++;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_Z;
+}
+
+/* 70 fd: 0111 0000 1111 1101 */
+static void EQAX_Hp(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( HL );
+ HL++;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_Z;
+}
+
+/* 70 fe: 0111 0000 1111 1110 */
+static void EQAX_Dm(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( DE );
+ DE--;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_Z;
+}
+
+/* 70 ff: 0111 0000 1111 1111 */
+static void EQAX_Hm(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - RM( HL );
+ HL--;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_Z;
+}
+
+/* prefix 74 */
+/* 74 08: 0111 0100 0000 1000 xxxx xxxx */
+static void ANI_V_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ V &= imm;
+ SET_Z(V);
+}
+
+/* 74 09: 0111 0100 0000 1001 xxxx xxxx */
+static void ANI_A_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ A &= imm;
+ SET_Z(A);
+}
+
+/* 74 0a: 0111 0100 0000 1010 xxxx xxxx */
+static void ANI_B_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ B &= imm;
+ SET_Z(B);
+}
+
+/* 74 0b: 0111 0100 0000 1011 xxxx xxxx */
+static void ANI_C_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ C &= imm;
+ SET_Z(C);
+}
+
+/* 74 0c: 0111 0100 0000 1100 xxxx xxxx */
+static void ANI_D_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ D &= imm;
+ SET_Z(D);
+}
+
+/* 74 0d: 0111 0100 0000 1101 xxxx xxxx */
+static void ANI_E_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ E &= imm;
+ SET_Z(E);
+}
+
+/* 74 0e: 0111 0100 0000 1110 xxxx xxxx */
+static void ANI_H_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ H &= imm;
+ SET_Z(H);
+}
+
+/* 74 0f: 0111 0100 0000 1111 xxxx xxxx */
+static void ANI_L_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ L &= imm;
+ SET_Z(L);
+}
+
+/* 74 10: 0111 0100 0001 0000 xxxx xxxx */
+static void XRI_V_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ V ^= imm;
+ SET_Z(V);
+}
+
+/* 74 11: 0111 0100 0001 0001 xxxx xxxx */
+static void XRI_A_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ A ^= imm;
+ SET_Z(A);
+}
+
+/* 74 12: 0111 0100 0001 0010 xxxx xxxx */
+static void XRI_B_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ B ^= imm;
+ SET_Z(B);
+}
+
+/* 74 13: 0111 0100 0001 0011 xxxx xxxx */
+static void XRI_C_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ C ^= imm;
+ SET_Z(C);
+}
+
+/* 74 14: 0111 0100 0001 0100 xxxx xxxx */
+static void XRI_D_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ D ^= imm;
+ SET_Z(D);
+}
+
+/* 74 15: 0111 0100 0001 0101 xxxx xxxx */
+static void XRI_E_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ E ^= imm;
+ SET_Z(E);
+}
+
+/* 74 16: 0111 0100 0001 0110 xxxx xxxx */
+static void XRI_H_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ H ^= imm;
+ SET_Z(H);
+}
+
+/* 74 17: 0111 0100 0001 0111 xxxx xxxx */
+static void XRI_L_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ L ^= imm;
+ SET_Z(L);
+}
+
+/* 74 18: 0111 0100 0001 1000 xxxx xxxx */
+static void ORI_V_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ V |= imm;
+ SET_Z(V);
+}
+
+/* 74 19: 0111 0100 0001 1001 xxxx xxxx */
+static void ORI_A_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ A |= imm;
+ SET_Z(A);
+}
+
+/* 74 1a: 0111 0100 0001 1010 xxxx xxxx */
+static void ORI_B_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ B |= imm;
+ SET_Z(B);
+}
+
+/* 74 1b: 0111 0100 0001 1011 xxxx xxxx */
+static void ORI_C_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ C |= imm;
+ SET_Z(C);
+}
+
+/* 74 1c: 0111 0100 0001 1100 xxxx xxxx */
+static void ORI_D_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ D |= imm;
+ SET_Z(D);
+}
+
+/* 74 1d: 0111 0100 0001 1101 xxxx xxxx */
+static void ORI_E_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ E |= imm;
+ SET_Z(E);
+}
+
+/* 74 1e: 0111 0100 0001 1110 xxxx xxxx */
+static void ORI_H_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ H |= imm;
+ SET_Z(H);
+}
+
+/* 74 1f: 0111 0100 0001 1111 xxxx xxxx */
+static void ORI_L_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ L |= imm;
+ SET_Z(L);
+}
+
+/* 74 20: 0111 0100 0010 0000 xxxx xxxx */
+static void ADINC_V_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = V + imm;
+
+ ZHC_ADD( tmp, V, 0 );
+ V = tmp;
+ SKIP_NC;
+}
+
+/* 74 21: 0111 0100 0010 0001 xxxx xxxx */
+static void ADINC_A_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = A + imm;
+
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 74 22: 0111 0100 0010 0010 xxxx xxxx */
+static void ADINC_B_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = B + imm;
+
+ ZHC_ADD( tmp, B, 0 );
+ B = tmp;
+ SKIP_NC;
+}
+
+/* 74 23: 0111 0100 0010 0011 xxxx xxxx */
+static void ADINC_C_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = C + imm;
+
+ ZHC_ADD( tmp, C, 0 );
+ C = tmp;
+ SKIP_NC;
+}
+
+/* 74 24: 0111 0100 0010 0100 xxxx xxxx */
+static void ADINC_D_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = D + imm;
+
+ ZHC_ADD( tmp, D, 0 );
+ D = tmp;
+ SKIP_NC;
+}
+
+/* 74 25: 0111 0100 0010 0101 xxxx xxxx */
+static void ADINC_E_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = E + imm;
+
+ ZHC_ADD( tmp, E, 0 );
+ E = tmp;
+ SKIP_NC;
+}
+
+/* 74 26: 0111 0100 0010 0110 xxxx xxxx */
+static void ADINC_H_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = H + imm;
+
+ ZHC_ADD( tmp, H, 0 );
+ H = tmp;
+ SKIP_NC;
+}
+
+/* 74 27: 0111 0100 0010 0111 xxxx xxxx */
+static void ADINC_L_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = L + imm;
+
+ ZHC_ADD( tmp, L, 0 );
+ L = tmp;
+ SKIP_NC;
+}
+
+/* 74 28: 0111 0100 0010 1000 xxxx xxxx */
+static void GTI_V_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ UINT16 tmp;
+
+ RDOPARG( imm );
+ tmp = V - imm - 1;
+ ZHC_SUB( tmp, V, 0 );
+
+ SKIP_NC;
+}
+
+/* 74 29: 0111 0100 0010 1001 xxxx xxxx */
+static void GTI_A_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ UINT16 tmp;
+
+ RDOPARG( imm );
+ tmp = A - imm - 1;
+ ZHC_SUB( tmp, A, 0 );
+
+ SKIP_NC;
+}
+
+/* 74 2a: 0111 0100 0010 1010 xxxx xxxx */
+static void GTI_B_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ UINT16 tmp;
+
+ RDOPARG( imm );
+ tmp = B - imm - 1;
+ ZHC_SUB( tmp, B, 0 );
+
+ SKIP_NC;
+}
+
+/* 74 2b: 0111 0100 0010 1011 xxxx xxxx */
+static void GTI_C_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ UINT16 tmp;
+
+ RDOPARG( imm );
+ tmp = C - imm - 1;
+ ZHC_SUB( tmp, C, 0 );
+
+ SKIP_NC;
+}
+
+/* 74 2c: 0111 0100 0010 1100 xxxx xxxx */
+static void GTI_D_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ UINT16 tmp;
+
+ RDOPARG( imm );
+ tmp = D - imm - 1;
+ ZHC_SUB( tmp, D, 0 );
+
+ SKIP_NC;
+}
+
+/* 74 2d: 0111 0100 0010 1101 xxxx xxxx */
+static void GTI_E_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ UINT16 tmp;
+
+ RDOPARG( imm );
+ tmp = E - imm - 1;
+ ZHC_SUB( tmp, E, 0 );
+
+ SKIP_NC;
+}
+
+/* 74 2e: 0111 0100 0010 1110 xxxx xxxx */
+static void GTI_H_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ UINT16 tmp;
+
+ RDOPARG( imm );
+ tmp = H - imm - 1;
+ ZHC_SUB( tmp, H, 0 );
+
+ SKIP_NC;
+}
+
+/* 74 2f: 0111 0100 0010 1111 xxxx xxxx */
+static void GTI_L_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ UINT16 tmp;
+
+ RDOPARG( imm );
+ tmp = L - imm - 1;
+ ZHC_SUB( tmp, L, 0 );
+
+ SKIP_NC;
+}
+
+/* 74 30: 0111 0100 0011 0000 xxxx xxxx */
+static void SUINB_V_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = V - imm;
+ ZHC_SUB( tmp, V, 0 );
+ V = tmp;
+ SKIP_NC;
+}
+
+/* 74 31: 0111 0100 0011 0001 xxxx xxxx */
+static void SUINB_A_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = A - imm;
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 74 32: 0111 0100 0011 0010 xxxx xxxx */
+static void SUINB_B_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = B - imm;
+ ZHC_SUB( tmp, B, 0 );
+ B = tmp;
+ SKIP_NC;
+}
+
+/* 74 33: 0111 0100 0011 0011 xxxx xxxx */
+static void SUINB_C_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = C - imm;
+ ZHC_SUB( tmp, C, 0 );
+ C = tmp;
+ SKIP_NC;
+}
+
+/* 74 34: 0111 0100 0011 0100 xxxx xxxx */
+static void SUINB_D_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = D - imm;
+ ZHC_SUB( tmp, D, 0 );
+ D = tmp;
+ SKIP_NC;
+}
+
+/* 74 35: 0111 0100 0011 0101 xxxx xxxx */
+static void SUINB_E_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = E - imm;
+ ZHC_SUB( tmp, E, 0 );
+ E = tmp;
+ SKIP_NC;
+}
+
+/* 74 36: 0111 0100 0011 0110 xxxx xxxx */
+static void SUINB_H_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = H - imm;
+ ZHC_SUB( tmp, H, 0 );
+ H = tmp;
+ SKIP_NC;
+}
+
+/* 74 37: 0111 0100 0011 0111 xxxx xxxx */
+static void SUINB_L_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = L - imm;
+ ZHC_SUB( tmp, L, 0 );
+ L = tmp;
+ SKIP_NC;
+}
+
+/* 74 38: 0111 0100 0011 1000 xxxx xxxx */
+static void LTI_V_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = V - imm;
+ ZHC_SUB( tmp, V, 0 );
+ SKIP_CY;
+}
+
+/* 74 39: 0111 0100 0011 1001 xxxx xxxx */
+static void LTI_A_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = A - imm;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_CY;
+}
+
+/* 74 3a: 0111 0100 0011 1010 xxxx xxxx */
+static void LTI_B_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = B - imm;
+ ZHC_SUB( tmp, B, 0 );
+ SKIP_CY;
+}
+
+/* 74 3b: 0111 0100 0011 1011 xxxx xxxx */
+static void LTI_C_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = C - imm;
+ ZHC_SUB( tmp, C, 0 );
+ SKIP_CY;
+}
+
+/* 74 3c: 0111 0100 0011 1100 xxxx xxxx */
+static void LTI_D_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = D - imm;
+ ZHC_SUB( tmp, D, 0 );
+ SKIP_CY;
+}
+
+/* 74 3d: 0111 0100 0011 1101 xxxx xxxx */
+static void LTI_E_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = E - imm;
+ ZHC_SUB( tmp, E, 0 );
+ SKIP_CY;
+}
+
+/* 74 3e: 0111 0100 0011 1110 xxxx xxxx */
+static void LTI_H_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = H - imm;
+ ZHC_SUB( tmp, H, 0 );
+ SKIP_CY;
+}
+
+/* 74 3f: 0111 0100 0011 1111 xxxx xxxx */
+static void LTI_L_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = L - imm;
+ ZHC_SUB( tmp, L, 0 );
+ SKIP_CY;
+}
+
+/* 74 40: 0111 0100 0100 0000 xxxx xxxx */
+static void ADI_V_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = V + imm;
+
+ ZHC_ADD( tmp, V, 0 );
+ V = tmp;
+}
+
+/* 74 41: 0111 0100 0100 0001 xxxx xxxx */
+static void ADI_A_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = A + imm;
+
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 74 42: 0111 0100 0100 0010 xxxx xxxx */
+static void ADI_B_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = B + imm;
+
+ ZHC_ADD( tmp, B, 0 );
+ B = tmp;
+}
+
+/* 74 43: 0111 0100 0100 0011 xxxx xxxx */
+static void ADI_C_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = C + imm;
+
+ ZHC_ADD( tmp, C, 0 );
+ C = tmp;
+}
+
+/* 74 44: 0111 0100 0100 0100 xxxx xxxx */
+static void ADI_D_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = D + imm;
+
+ ZHC_ADD( tmp, D, 0 );
+ D = tmp;
+}
+
+/* 74 45: 0111 0100 0100 0101 xxxx xxxx */
+static void ADI_E_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = E + imm;
+
+ ZHC_ADD( tmp, E, 0 );
+ E = tmp;
+}
+
+/* 74 46: 0111 0100 0100 0110 xxxx xxxx */
+static void ADI_H_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = H + imm;
+
+ ZHC_ADD( tmp, H, 0 );
+ H = tmp;
+}
+
+/* 74 47: 0111 0100 0100 0111 xxxx xxxx */
+static void ADI_L_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = L + imm;
+
+ ZHC_ADD( tmp, L, 0 );
+ L = tmp;
+}
+
+/* 74 48: 0111 0100 0100 1000 xxxx xxxx */
+static void ONI_V_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (V & imm)
+ PSW |= SK;
+}
+
+/* 74 49: 0111 0100 0100 1001 xxxx xxxx */
+static void ONI_A_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (A & imm)
+ PSW |= SK;
+}
+
+/* 74 4a: 0111 0100 0100 1010 xxxx xxxx */
+static void ONI_B_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (B & imm)
+ PSW |= SK;
+}
+
+/* 74 4b: 0111 0100 0100 1011 xxxx xxxx */
+static void ONI_C_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (C & imm)
+ PSW |= SK;
+}
+
+/* 74 4c: 0111 0100 0100 1100 xxxx xxxx */
+static void ONI_D_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (D & imm)
+ PSW |= SK;
+}
+
+/* 74 4d: 0111 0100 0100 1101 xxxx xxxx */
+static void ONI_E_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (E & imm)
+ PSW |= SK;
+}
+
+/* 74 4e: 0111 0100 0100 1110 xxxx xxxx */
+static void ONI_H_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (H & imm)
+ PSW |= SK;
+}
+
+/* 74 4f: 0111 0100 0100 1111 xxxx xxxx */
+static void ONI_L_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (L & imm)
+ PSW |= SK;
+}
+
+/* 74 50: 0111 0100 0101 0000 xxxx xxxx */
+static void ACI_V_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = V + imm + (PSW & CY);
+ ZHC_SUB( tmp, V, (PSW & CY) );
+ V = tmp;
+}
+
+/* 74 51: 0111 0100 0101 0001 xxxx xxxx */
+static void ACI_A_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = A + imm + (PSW & CY);
+ ZHC_SUB( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 74 52: 0111 0100 0101 0010 xxxx xxxx */
+static void ACI_B_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = B + imm + (PSW & CY);
+ ZHC_SUB( tmp, B, (PSW & CY) );
+ B = tmp;
+}
+
+/* 74 53: 0111 0100 0101 0011 xxxx xxxx */
+static void ACI_C_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = C + imm + (PSW & CY);
+ ZHC_SUB( tmp, C, (PSW & CY) );
+ C = tmp;
+}
+
+/* 74 54: 0111 0100 0101 0100 xxxx xxxx */
+static void ACI_D_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = D + imm + (PSW & CY);
+ ZHC_SUB( tmp, D, (PSW & CY) );
+ D = tmp;
+}
+
+/* 74 55: 0111 0100 0101 0101 xxxx xxxx */
+static void ACI_E_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = E + imm + (PSW & CY);
+ ZHC_SUB( tmp, E, (PSW & CY) );
+ E = tmp;
+}
+
+/* 74 56: 0111 0100 0101 0110 xxxx xxxx */
+static void ACI_H_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = H + imm + (PSW & CY);
+ ZHC_SUB( tmp, H, (PSW & CY) );
+ H = tmp;
+}
+
+/* 74 57: 0111 0100 0101 0111 xxxx xxxx */
+static void ACI_L_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = L + imm + (PSW & CY);
+ ZHC_SUB( tmp, L, (PSW & CY) );
+ L = tmp;
+}
+
+/* 74 58: 0111 0100 0101 1000 xxxx xxxx */
+static void OFFI_V_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (0 == (V & imm))
+ PSW |= SK;
+}
+
+/* 74 59: 0111 0100 0101 1001 xxxx xxxx */
+static void OFFI_A_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (0 == (A & imm))
+ PSW |= SK;
+}
+
+/* 74 5a: 0111 0100 0101 1010 xxxx xxxx */
+static void OFFI_B_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (0 == (B & imm))
+ PSW |= SK;
+}
+
+/* 74 5b: 0111 0100 0101 1011 xxxx xxxx */
+static void OFFI_C_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (0 == (C & imm))
+ PSW |= SK;
+}
+
+/* 74 5c: 0111 0100 0101 1100 xxxx xxxx */
+static void OFFI_D_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (0 == (D & imm))
+ PSW |= SK;
+}
+
+/* 74 5d: 0111 0100 0101 1101 xxxx xxxx */
+static void OFFI_E_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (0 == (E & imm))
+ PSW |= SK;
+}
+
+/* 74 5e: 0111 0100 0101 1110 xxxx xxxx */
+static void OFFI_H_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (0 == (H & imm))
+ PSW |= SK;
+}
+
+/* 74 5f: 0111 0100 0101 1111 xxxx xxxx */
+static void OFFI_L_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+
+ RDOPARG( imm );
+ if (0 == (L & imm))
+ PSW |= SK;
+}
+
+/* 74 60: 0111 0100 0110 0000 xxxx xxxx */
+static void SUI_V_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = V - imm;
+ ZHC_SUB( tmp, V, 0 );
+ V = tmp;
+}
+
+/* 74 61: 0111 0100 0110 0001 xxxx xxxx */
+static void SUI_A_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = A - imm;
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 74 62: 0111 0100 0110 0010 xxxx xxxx */
+static void SUI_B_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = B - imm;
+ ZHC_SUB( tmp, B, 0 );
+ B = tmp;
+}
+
+/* 74 63: 0111 0100 0110 0011 xxxx xxxx */
+static void SUI_C_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = C - imm;
+ ZHC_SUB( tmp, C, 0 );
+ C = tmp;
+}
+
+/* 74 64: 0111 0100 0110 0100 xxxx xxxx */
+static void SUI_D_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = D - imm;
+ ZHC_SUB( tmp, D, 0 );
+ D = tmp;
+}
+
+/* 74 65: 0111 0100 0110 0101 xxxx xxxx */
+static void SUI_E_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = E - imm;
+ ZHC_SUB( tmp, E, 0 );
+ E = tmp;
+}
+
+/* 74 66: 0111 0100 0110 0110 xxxx xxxx */
+static void SUI_H_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = H - imm;
+ ZHC_SUB( tmp, H, 0 );
+ H = tmp;
+}
+
+/* 74 67: 0111 0100 0110 0111 xxxx xxxx */
+static void SUI_L_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = L - imm;
+ ZHC_SUB( tmp, L, 0 );
+ L = tmp;
+}
+
+/* 74 68: 0111 0100 0110 1000 xxxx xxxx */
+static void NEI_V_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = V - imm;
+ ZHC_SUB( tmp, V, 0 );
+ SKIP_NZ;
+}
+
+/* 74 69: 0111 0100 0110 1001 xxxx xxxx */
+static void NEI_A_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = A - imm;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NZ;
+}
+
+/* 74 6a: 0111 0100 0110 1010 xxxx xxxx */
+static void NEI_B_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = B - imm;
+ ZHC_SUB( tmp, B, 0 );
+ SKIP_NZ;
+}
+
+/* 74 6b: 0111 0100 0110 1011 xxxx xxxx */
+static void NEI_C_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = C - imm;
+ ZHC_SUB( tmp, C, 0 );
+ SKIP_NZ;
+}
+
+/* 74 6c: 0111 0100 0110 1100 xxxx xxxx */
+static void NEI_D_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = D - imm;
+ ZHC_SUB( tmp, D, 0 );
+ SKIP_NZ;
+}
+
+/* 74 6d: 0111 0100 0110 1101 xxxx xxxx */
+static void NEI_E_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = E - imm;
+ ZHC_SUB( tmp, E, 0 );
+ SKIP_NZ;
+}
+
+/* 74 6e: 0111 0100 0110 1110 xxxx xxxx */
+static void NEI_H_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = H - imm;
+ ZHC_SUB( tmp, H, 0 );
+ SKIP_NZ;
+}
+
+/* 74 6f: 0111 0100 0110 1111 xxxx xxxx */
+static void NEI_L_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = L - imm;
+ ZHC_SUB( tmp, L, 0 );
+ SKIP_NZ;
+}
+
+/* 74 70: 0111 0100 0111 0000 xxxx xxxx */
+static void SBI_V_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = V - imm - (PSW & CY);
+ ZHC_SUB( tmp, V, (PSW & CY) );
+ V = tmp;
+}
+
+/* 74 71: 0111 0100 0111 0001 xxxx xxxx */
+static void SBI_A_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = A - imm - (PSW & CY);
+ ZHC_SUB( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 74 72: 0111 0100 0111 0010 xxxx xxxx */
+static void SBI_B_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = B - imm - (PSW & CY);
+ ZHC_SUB( tmp, B, (PSW & CY) );
+ B = tmp;
+}
+
+/* 74 73: 0111 0100 0111 0011 xxxx xxxx */
+static void SBI_C_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = C - imm - (PSW & CY);
+ ZHC_SUB( tmp, C, (PSW & CY) );
+ C = tmp;
+}
+
+/* 74 74: 0111 0100 0111 0100 xxxx xxxx */
+static void SBI_D_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = D - imm - (PSW & CY);
+ ZHC_SUB( tmp, D, (PSW & CY) );
+ D = tmp;
+}
+
+/* 74 75: 0111 0100 0111 0101 xxxx xxxx */
+static void SBI_E_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = E - imm - (PSW & CY);
+ ZHC_SUB( tmp, E, (PSW & CY) );
+ E = tmp;
+}
+
+/* 74 76: 0111 0100 0111 0110 xxxx xxxx */
+static void SBI_H_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = H - imm - (PSW & CY);
+ ZHC_SUB( tmp, H, (PSW & CY) );
+ H = tmp;
+}
+
+/* 74 77: 0111 0100 0111 0111 xxxx xxxx */
+static void SBI_L_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = L - imm - (PSW & CY);
+ ZHC_SUB( tmp, L, (PSW & CY) );
+ L = tmp;
+}
+
+/* 74 78: 0111 0100 0111 1000 xxxx xxxx */
+static void EQI_V_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = V - imm;
+ ZHC_SUB( tmp, V, 0 );
+ SKIP_Z;
+}
+
+/* 74 79: 0111 0100 0111 1001 xxxx xxxx */
+static void EQI_A_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = A - imm;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_Z;
+}
+
+/* 74 7a: 0111 0100 0111 1010 xxxx xxxx */
+static void EQI_B_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = B - imm;
+ ZHC_SUB( tmp, B, 0 );
+ SKIP_Z;
+}
+
+/* 74 7b: 0111 0100 0111 1011 xxxx xxxx */
+static void EQI_C_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = C - imm;
+ ZHC_SUB( tmp, C, 0 );
+ SKIP_Z;
+}
+
+/* 74 7c: 0111 0100 0111 1100 xxxx xxxx */
+static void EQI_D_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = D - imm;
+ ZHC_SUB( tmp, D, 0 );
+ SKIP_Z;
+}
+
+/* 74 7d: 0111 0100 0111 1101 xxxx xxxx */
+static void EQI_E_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = E - imm;
+ ZHC_SUB( tmp, E, 0 );
+ SKIP_Z;
+}
+
+/* 74 7e: 0111 0100 0111 1110 xxxx xxxx */
+static void EQI_H_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = H - imm;
+ ZHC_SUB( tmp, H, 0 );
+ SKIP_Z;
+}
+
+/* 74 7f: 0111 0100 0111 1111 xxxx xxxx */
+static void EQI_L_xx(upd7810_state *cpustate)
+{
+ UINT8 tmp, imm;
+
+ RDOPARG( imm );
+ tmp = L - imm;
+ ZHC_SUB( tmp, L, 0 );
+ SKIP_Z;
+}
+
+/* 74 88: 0111 0100 1000 1000 oooo oooo */
+static void ANAW_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ RDOPARG( ea.b.l );
+
+ A &= RM( ea.d );
+ SET_Z(A);
+}
+
+/* 74 8d: 0111 0100 1000 1101 */
+static void DAN_EA_BC(upd7810_state *cpustate)
+{
+ EA &= BC;
+ SET_Z(EA);
+}
+
+/* 74 8e: 0111 0100 1000 1110 */
+static void DAN_EA_DE(upd7810_state *cpustate)
+{
+ EA &= DE;
+ SET_Z(EA);
+}
+
+/* 74 8f: 0111 0100 1000 1111 */
+static void DAN_EA_HL(upd7810_state *cpustate)
+{
+ EA &= HL;
+ SET_Z(EA);
+}
+
+/* 74 90: 0111 0100 1001 0000 oooo oooo */
+static void XRAW_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ RDOPARG( ea.b.l );
+
+ A ^= RM( ea.d );
+ SET_Z(A);
+}
+
+/* 74 95: 0111 0100 1001 0101 */
+static void DXR_EA_BC(upd7810_state *cpustate)
+{
+ EA ^= BC;
+ SET_Z(EA);
+}
+
+/* 74 96: 0111 0100 1001 0110 */
+static void DXR_EA_DE(upd7810_state *cpustate)
+{
+ EA ^= DE;
+ SET_Z(EA);
+}
+
+/* 74 97: 0111 0100 1001 0111 */
+static void DXR_EA_HL(upd7810_state *cpustate)
+{
+ EA ^= HL;
+ SET_Z(EA);
+}
+
+/* 74 98: 0111 0100 1001 1000 oooo oooo */
+static void ORAW_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ RDOPARG( ea.b.l );
+
+ A |= RM( ea.d );
+ SET_Z(A);
+}
+
+/* 74 9d: 0111 0100 1001 1101 */
+static void DOR_EA_BC(upd7810_state *cpustate)
+{
+ EA |= BC;
+ SET_Z(EA);
+}
+
+/* 74 9e: 0111 0100 1001 1110 */
+static void DOR_EA_DE(upd7810_state *cpustate)
+{
+ EA |= DE;
+ SET_Z(EA);
+}
+
+/* 74 9f: 0111 0100 1001 1111 */
+static void DOR_EA_HL(upd7810_state *cpustate)
+{
+ EA |= HL;
+ SET_Z(EA);
+}
+
+/* 74 a0: 0111 0100 1010 0000 oooo oooo */
+static void ADDNCW_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ UINT8 tmp;
+
+ RDOPARG( ea.b.l );
+
+ tmp = A + RM( ea.d );
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 74 a5: 0111 0100 1010 0101 */
+static void DADDNC_EA_BC(upd7810_state *cpustate)
+{
+ UINT16 tmp = EA + BC;
+
+ ZHC_ADD( tmp, EA, 0 );
+ EA = tmp;
+ SKIP_NC;
+}
+
+/* 74 a6: 0111 0100 1010 0110 */
+static void DADDNC_EA_DE(upd7810_state *cpustate)
+{
+ UINT16 tmp = EA + DE;
+
+ ZHC_ADD( tmp, EA, 0 );
+ EA = tmp;
+ SKIP_NC;
+}
+
+/* 74 a7: 0111 0100 1010 0111 */
+static void DADDNC_EA_HL(upd7810_state *cpustate)
+{
+ UINT16 tmp = EA + HL;
+
+ ZHC_ADD( tmp, EA, 0 );
+ EA = tmp;
+ SKIP_NC;
+}
+
+/* 74 a8: 0111 0100 1010 1000 oooo oooo */
+static void GTAW_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ UINT16 tmp;
+
+ RDOPARG( ea.b.l );
+ tmp = A - RM( ea.d ) - 1;
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NC;
+}
+
+/* 74 ad: 0111 0100 1010 1101 */
+static void DGT_EA_BC(upd7810_state *cpustate)
+{
+ UINT32 tmp = EA - BC - 1;
+ ZHC_SUB( tmp, EA, 0 );
+ SKIP_NC;
+}
+
+/* 74 ae: 0111 0100 1010 1110 */
+static void DGT_EA_DE(upd7810_state *cpustate)
+{
+ UINT32 tmp = EA - DE - 1;
+ ZHC_SUB( tmp, EA, 0 );
+ SKIP_NC;
+}
+
+/* 74 af: 0111 0100 1010 1111 */
+static void DGT_EA_HL(upd7810_state *cpustate)
+{
+ UINT32 tmp = EA - HL - 1;
+ ZHC_SUB( tmp, EA, 0 );
+ SKIP_NC;
+}
+
+/* 74 b0: 0111 0100 1011 0000 oooo oooo */
+static void SUBNBW_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ UINT8 tmp;
+
+ RDOPARG( ea.b.l );
+ tmp = A - RM( ea.d );
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+ SKIP_NC;
+}
+
+/* 74 b5: 0111 0100 1011 0101 */
+static void DSUBNB_EA_BC(upd7810_state *cpustate)
+{
+ UINT16 tmp = EA - BC;
+ ZHC_SUB( tmp, EA, 0 );
+ EA = tmp;
+ SKIP_NC;
+}
+
+/* 74 b6: 0111 0100 1011 0110 */
+static void DSUBNB_EA_DE(upd7810_state *cpustate)
+{
+ UINT16 tmp = EA - DE;
+ ZHC_SUB( tmp, EA, 0 );
+ EA = tmp;
+ SKIP_NC;
+}
+
+/* 74 b7: 0111 0100 1011 0111 */
+static void DSUBNB_EA_HL(upd7810_state *cpustate)
+{
+ UINT16 tmp;
+
+ tmp = EA - HL;
+ ZHC_SUB( tmp, EA, 0 );
+ EA = tmp;
+ SKIP_NC;
+}
+
+/* 74 b8: 0111 0100 1011 1000 oooo oooo */
+static void LTAW_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ UINT8 tmp;
+
+ RDOPARG( ea.b.l );
+ tmp = A - RM( ea.d );
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_CY;
+}
+
+/* 74 bd: 0111 0100 1011 1101 */
+static void DLT_EA_BC(upd7810_state *cpustate)
+{
+ UINT16 tmp = EA - BC;
+ ZHC_SUB( tmp, EA, 0 );
+ SKIP_CY;
+}
+
+/* 74 be: 0111 0100 1011 1110 */
+static void DLT_EA_DE(upd7810_state *cpustate)
+{
+ UINT16 tmp = EA - DE;
+ ZHC_SUB( tmp, EA, 0 );
+ SKIP_CY;
+}
+
+/* 74 bf: 0111 0100 1011 1111 */
+static void DLT_EA_HL(upd7810_state *cpustate)
+{
+ UINT16 tmp = EA - HL;
+ ZHC_SUB( tmp, EA, 0 );
+ SKIP_CY;
+}
+
+/* 74 c0: 0111 0100 1100 0000 oooo oooo */
+static void ADDW_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ UINT8 tmp;
+ RDOPARG( ea.b.l );
+ tmp = A + RM( ea.d );
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 74 c5: 0111 0100 1100 0101 */
+static void DADD_EA_BC(upd7810_state *cpustate)
+{
+ UINT16 tmp = EA + BC;
+ ZHC_ADD( tmp, EA, 0 );
+ EA = tmp;
+}
+
+/* 74 c6: 0111 0100 1100 0110 */
+static void DADD_EA_DE(upd7810_state *cpustate)
+{
+ UINT16 tmp = EA + DE;
+ ZHC_ADD( tmp, EA, 0 );
+ EA = tmp;
+}
+
+/* 74 c7: 0111 0100 1100 0111 */
+static void DADD_EA_HL(upd7810_state *cpustate)
+{
+ UINT16 tmp = EA + HL;
+ ZHC_ADD( tmp, EA, 0 );
+ EA = tmp;
+}
+
+/* 74 c8: 0111 0100 1100 1000 oooo oooo */
+static void ONAW_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ RDOPARG( ea.b.l );
+
+ if (A & RM( ea.d ))
+ PSW = (PSW & ~Z) | SK;
+ else
+ PSW |= Z;
+}
+
+/* 74 cd: 0111 0100 1100 1101 */
+static void DON_EA_BC(upd7810_state *cpustate)
+{
+ if (EA & BC)
+ PSW = (PSW & ~Z) | SK;
+ else
+ PSW |= Z;
+}
+
+/* 74 ce: 0111 0100 1100 1110 */
+static void DON_EA_DE(upd7810_state *cpustate)
+{
+ if (EA & DE)
+ PSW = (PSW & ~Z) | SK;
+ else
+ PSW |= Z;
+}
+
+/* 74 cf: 0111 0100 1100 1111 */
+static void DON_EA_HL(upd7810_state *cpustate)
+{
+ if (EA & HL)
+ PSW = (PSW & ~Z) | SK;
+ else
+ PSW |= Z;
+}
+
+/* 74 d0: 0111 0100 1101 0000 oooo oooo */
+static void ADCW_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ UINT8 tmp;
+
+ RDOPARG( ea.b.l );
+ tmp = A + RM( ea.d ) + (PSW & CY);
+ ZHC_ADD( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 74 d5: 0111 0100 1101 0101 */
+static void DADC_EA_BC(upd7810_state *cpustate)
+{
+ UINT16 tmp = EA + BC + (PSW & CY);
+ ZHC_ADD( tmp, EA, (PSW & CY) );
+ EA = tmp;
+}
+
+/* 74 d6: 0111 0100 1101 0110 */
+static void DADC_EA_DE(upd7810_state *cpustate)
+{
+ UINT16 tmp = EA + DE + (PSW & CY);
+ ZHC_ADD( tmp, EA, (PSW & CY) );
+ EA = tmp;
+}
+
+/* 74 d7: 0111 0100 1101 0111 */
+static void DADC_EA_HL(upd7810_state *cpustate)
+{
+ UINT16 tmp = EA + HL + (PSW & CY);
+ ZHC_ADD( tmp, EA, (PSW & CY) );
+ EA = tmp;
+}
+
+/* 74 d8: 0111 0100 1101 1000 oooo oooo */
+static void OFFAW_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ RDOPARG( ea.b.l );
+
+ if ( A & RM( ea.d ) )
+ PSW &= ~Z;
+ else
+ PSW = PSW | Z | SK;
+}
+
+/* 74 dd: 0111 0100 1101 1101 */
+static void DOFF_EA_BC(upd7810_state *cpustate)
+{
+ if ( EA & BC )
+ PSW &= ~Z;
+ else
+ PSW = PSW | Z | SK;
+}
+
+/* 74 de: 0111 0100 1101 1110 */
+static void DOFF_EA_DE(upd7810_state *cpustate)
+{
+ if ( EA & DE )
+ PSW &= ~Z;
+ else
+ PSW = PSW | Z | SK;
+}
+
+/* 74 df: 0111 0100 1101 1111 */
+static void DOFF_EA_HL(upd7810_state *cpustate)
+{
+ if ( EA & HL )
+ PSW &= ~Z;
+ else
+ PSW = PSW | Z | SK;
+}
+
+/* 74 e0: 0111 0100 1110 0000 oooo oooo */
+static void SUBW_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ UINT8 tmp;
+
+ RDOPARG( ea.b.l );
+ tmp = A - RM( ea.d );
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+}
+
+/* 74 e5: 0111 0100 1110 0101 */
+static void DSUB_EA_BC(upd7810_state *cpustate)
+{
+ UINT16 tmp = EA - BC;
+ ZHC_SUB( tmp, EA, 0 );
+ EA = tmp;
+}
+
+/* 74 e6: 0111 0100 1110 0110 */
+static void DSUB_EA_DE(upd7810_state *cpustate)
+{
+ UINT16 tmp = EA - DE;
+ ZHC_SUB( tmp, EA, 0 );
+ EA = tmp;
+}
+
+/* 74 e7: 0111 0100 1110 0111 */
+static void DSUB_EA_HL(upd7810_state *cpustate)
+{
+ UINT16 tmp = EA - HL;
+ ZHC_SUB( tmp, EA, 0 );
+ EA = tmp;
+}
+
+/* 74 e8: 0111 0100 1110 1000 oooo oooo */
+static void NEAW_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ UINT8 tmp;
+
+ RDOPARG( ea.b.l );
+ tmp = A - RM( ea.d );
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_NZ;
+}
+
+/* 74 ed: 0111 0100 1110 1101 */
+static void DNE_EA_BC(upd7810_state *cpustate)
+{
+ UINT16 tmp;
+
+ tmp = EA - BC;
+ ZHC_SUB( tmp, EA, 0 );
+ SKIP_NZ;
+}
+
+/* 74 ee: 0111 0100 1110 1110 */
+static void DNE_EA_DE(upd7810_state *cpustate)
+{
+ UINT16 tmp;
+
+ tmp = EA - DE;
+ ZHC_SUB( tmp, EA, 0 );
+ SKIP_NZ;
+}
+
+/* 74 ef: 0111 0100 1110 1111 */
+static void DNE_EA_HL(upd7810_state *cpustate)
+{
+ UINT16 tmp;
+
+ tmp = EA - HL;
+ ZHC_SUB( tmp, EA, 0 );
+ SKIP_NZ;
+}
+
+/* 74 f0: 0111 0100 1111 0000 oooo oooo */
+static void SBBW_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ UINT8 tmp;
+
+ RDOPARG( ea.b.l );
+ tmp = A - RM( ea.d ) - (PSW & CY);
+ ZHC_SUB( tmp, A, (PSW & CY) );
+ A = tmp;
+}
+
+/* 74 f5: 0111 0100 1111 0101 */
+static void DSBB_EA_BC(upd7810_state *cpustate)
+{
+ UINT16 tmp = EA - BC - (PSW & CY);
+ ZHC_SUB( tmp, EA, (PSW & CY) );
+ EA = tmp;
+}
+
+/* 74 f6: 0111 0100 1111 0110 */
+static void DSBB_EA_DE(upd7810_state *cpustate)
+{
+ UINT16 tmp = EA - DE - (PSW & CY);
+ ZHC_SUB( tmp, EA, (PSW & CY) );
+ EA = tmp;
+}
+
+/* 74 f7: 0111 0100 1111 0111 */
+static void DSBB_EA_HL(upd7810_state *cpustate)
+{
+ UINT16 tmp = EA - HL - (PSW & CY);
+ ZHC_SUB( tmp, EA, (PSW & CY) );
+ EA = tmp;
+}
+
+/* 74 f8: 0111 0100 1111 1000 oooo oooo */
+static void EQAW_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ UINT8 tmp;
+
+ RDOPARG( ea.b.l );
+ tmp = A - RM( ea.d );
+ ZHC_SUB( tmp, A, 0 );
+ SKIP_Z;
+}
+
+/* 74 fd: 0111 0100 1111 1101 */
+static void DEQ_EA_BC(upd7810_state *cpustate)
+{
+ UINT16 tmp;
+
+ tmp = EA - BC;
+ ZHC_SUB( tmp, EA, 0 );
+ SKIP_Z;
+}
+
+/* 74 fe: 0111 0100 1111 1110 */
+static void DEQ_EA_DE(upd7810_state *cpustate)
+{
+ UINT16 tmp;
+
+ tmp = EA - DE;
+ ZHC_SUB( tmp, EA, 0 );
+ SKIP_Z;
+}
+
+/* 74 ff: 0111 0100 1111 1111 */
+static void DEQ_EA_HL(upd7810_state *cpustate)
+{
+ UINT16 tmp;
+
+ tmp = EA - HL;
+ ZHC_SUB( tmp, EA, 0 );
+ SKIP_Z;
+}
+
+/************************************************
+ * main opcodes
+ ************************************************/
+
+/* 00: 0000 0000 */
+static void NOP(upd7810_state *cpustate)
+{
+}
+
+/* 01: 0000 0001 oooo oooo */
+static void LDAW_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+
+ RDOPARG( ea.b.l );
+
+ A = RM( ea.d );
+}
+
+/* 02: 0000 0010 */
+static void INX_SP(upd7810_state *cpustate)
+{
+ SP++;
+}
+
+/* 03: 0000 0011 */
+static void DCX_SP(upd7810_state *cpustate)
+{
+ SP--;
+}
+
+/* 04: 0000 0100 llll llll hhhh hhhh */
+static void LXI_S_w(upd7810_state *cpustate)
+{
+ RDOPARG( SPL );
+ RDOPARG( SPH );
+}
+
+/* 05: 0000 0101 oooo oooo xxxx xxxx */
+static void ANIW_wa_xx(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ UINT8 m, imm;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( imm );
+ m = RM( ea.d );
+ m &= imm;
+ WM( ea.d, m );
+ SET_Z(m);
+}
+
+/* 07: 0000 0111 xxxx xxxx */
+/* ANI_A_xx already defined (long form) */
+
+/* 08: 0000 1000 */
+static void MOV_A_EAH(upd7810_state *cpustate)
+{
+ A = EAH;
+}
+
+/* 09: 0000 1001 */
+static void MOV_A_EAL(upd7810_state *cpustate)
+{
+ A = EAL;
+}
+
+/* 0a: 0000 1010 */
+static void MOV_A_B(upd7810_state *cpustate)
+{
+ A = B;
+}
+
+/* 0b: 0000 1011 */
+static void MOV_A_C(upd7810_state *cpustate)
+{
+ A = C;
+}
+
+/* 0c: 0000 1100 */
+static void MOV_A_D(upd7810_state *cpustate)
+{
+ A = D;
+}
+
+/* 0d: 0000 1101 */
+static void MOV_A_E(upd7810_state *cpustate)
+{
+ A = E;
+}
+
+/* 0e: 0000 1110 */
+static void MOV_A_H(upd7810_state *cpustate)
+{
+ A = H;
+}
+
+/* 0f: 0000 1111 */
+static void MOV_A_L(upd7810_state *cpustate)
+{
+ A = L;
+}
+
+/* 10: 0001 0000 */
+static void EXA(upd7810_state *cpustate)
+{
+ UINT16 tmp;
+ tmp = EA; EA = EA2; EA2 = tmp;
+ tmp = VA; VA = VA2; VA2 = tmp;
+}
+
+/* 11: 0001 0001 */
+static void EXX(upd7810_state *cpustate)
+{
+ UINT16 tmp;
+ tmp = BC; BC = BC2; BC2 = tmp;
+ tmp = DE; DE = DE2; DE2 = tmp;
+ tmp = HL; HL = HL2; HL2 = tmp;
+}
+
+/* 48 AD (7807 only) */
+static void EXR(upd7810_state *cpustate)
+{
+ UINT16 tmp;
+ tmp = BC; BC = BC2; BC2 = tmp;
+ tmp = DE; DE = DE2; DE2 = tmp;
+ tmp = HL; HL = HL2; HL2 = tmp;
+ tmp = EA; EA = EA2; EA2 = tmp;
+ tmp = VA; VA = VA2; VA2 = tmp;
+}
+
+/* 12: 0001 0010 */
+static void INX_BC(upd7810_state *cpustate)
+{
+ BC++;
+}
+
+/* 13: 0001 0011 */
+static void DCX_BC(upd7810_state *cpustate)
+{
+ BC--;
+}
+
+/* 14: 0001 0100 llll llll hhhh hhhh */
+static void LXI_B_w(upd7810_state *cpustate)
+{
+ RDOPARG( C );
+ RDOPARG( B );
+}
+
+/* 15: 0001 0101 oooo oooo xxxx xxxx */
+static void ORIW_wa_xx(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ UINT8 m, imm;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( imm );
+ m = RM( ea.d );
+ m |= imm;
+ WM( ea.d, m );
+ SET_Z(m);
+}
+
+/* 16: 0001 0110 xxxx xxxx */
+/* XRI_A_xx already defined (long form) */
+
+/* 17: 0001 0111 xxxx xxxx */
+/* ORI_A_xx already defined (long form) */
+
+/* 18: 0001 1000 */
+static void MOV_EAH_A(upd7810_state *cpustate)
+{
+ EAH = A;
+}
+
+/* 19: 0001 1001 */
+static void MOV_EAL_A(upd7810_state *cpustate)
+{
+ EAL = A;
+}
+
+/* 1a: 0001 1010 */
+static void MOV_B_A(upd7810_state *cpustate)
+{
+ B = A;
+}
+
+/* 1b: 0001 1011 */
+static void MOV_C_A(upd7810_state *cpustate)
+{
+ C = A;
+}
+
+/* 1c: 0001 1100 */
+static void MOV_D_A(upd7810_state *cpustate)
+{
+ D = A;
+}
+
+/* 1d: 0001 1101 */
+static void MOV_E_A(upd7810_state *cpustate)
+{
+ E = A;
+}
+
+/* 1e: 0001 1110 */
+static void MOV_H_A(upd7810_state *cpustate)
+{
+ H = A;
+}
+
+/* 1f: 0001 1111 */
+static void MOV_L_A(upd7810_state *cpustate)
+{
+ L = A;
+}
+
+/* 20: 0010 0000 oooo oooo */
+static void INRW_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ UINT8 tmp, m;
+
+ RDOPARG( ea.b.l );
+ m = RM( ea.d );
+ tmp = m + 1;
+ ZHC_ADD( tmp, m, 0 );
+ WM( ea.d, tmp );
+ SKIP_CY;
+}
+
+/* 21: 0010 0001 */
+static void JB(upd7810_state *cpustate)
+{
+ PC = BC;
+}
+
+/* 22: 0010 0010 */
+static void INX_DE(upd7810_state *cpustate)
+{
+ DE++;
+}
+
+/* 23: 0010 0011 */
+static void DCX_DE(upd7810_state *cpustate)
+{
+ DE--;
+}
+
+/* 24: 0010 0100 llll llll hhhh hhhh */
+static void LXI_D_w(upd7810_state *cpustate)
+{
+ RDOPARG( E );
+ RDOPARG( D );
+}
+
+/* 25: 0010 0101 oooo oooo xxxx xxxx */
+static void GTIW_wa_xx(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ UINT8 m, imm;
+ UINT16 tmp;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( imm );
+ m = RM( ea.d );
+ tmp = m - imm - 1;
+ ZHC_SUB( tmp, m, 0 );
+ SKIP_NC;
+}
+
+/* 26: 0010 0110 xxxx xxxx */
+/* ADINC_A_xx already defined (long form) */
+
+/* 27: 0010 0111 xxxx xxxx */
+/* GTI_A_xx already defined (long form) */
+
+/* 29: 0010 1001 */
+static void LDAX_B(upd7810_state *cpustate)
+{
+ A = RM( BC );
+}
+
+/* 2a: 0010 1010 */
+static void LDAX_D(upd7810_state *cpustate)
+{
+ A = RM( DE );
+}
+
+/* 2b: 0010 1011 */
+static void LDAX_H(upd7810_state *cpustate)
+{
+ A = RM( HL );
+}
+
+/* 2c: 0010 1100 */
+static void LDAX_Dp(upd7810_state *cpustate)
+{
+ A = RM( DE );
+ DE++;
+}
+
+/* 2d: 0010 1101 dddd dddd */
+static void LDAX_Hp(upd7810_state *cpustate)
+{
+ A = RM( HL );
+ HL++;
+}
+
+/* 2e: 0010 1110 dddd dddd */
+static void LDAX_Dm(upd7810_state *cpustate)
+{
+ A = RM( DE );
+ DE--;
+}
+
+/* 2f: 0010 1111 dddd dddd */
+static void LDAX_Hm(upd7810_state *cpustate)
+{
+ A = RM( HL );
+ HL--;
+}
+
+/* 30: 0011 0000 oooo oooo */
+static void DCRW_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ UINT8 tmp, m;
+
+ RDOPARG( ea.b.l );
+ m = RM( ea.d );
+ tmp = m - 1;
+ ZHC_SUB( tmp, m, 0 );
+ WM( ea.d, tmp );
+ SKIP_CY;
+}
+
+/* 31: 0011 0001 */
+static void BLOCK(upd7810_state *cpustate)
+{
+ WM( DE, RM( HL ) );
+ DE++;
+ HL++;
+ C--;
+ if (C == 0xff)
+ PSW |= CY;
+ else
+ {
+ PSW &= ~CY;
+ PC--;
+ }
+}
+
+/* 32: 0011 0010 */
+static void INX_HL(upd7810_state *cpustate)
+{
+ HL++;
+}
+
+/* 33: 0011 0011 */
+static void DCX_HL(upd7810_state *cpustate)
+{
+ HL--;
+}
+
+/* 34: 0011 0100 llll llll hhhh hhhh */
+static void LXI_H_w(upd7810_state *cpustate)
+{
+ if (PSW & L0) { /* overlay active? */
+ PC+=2;
+ return;
+ }
+ RDOPARG( L );
+ RDOPARG( H );
+ PSW |= L0;
+}
+
+/* 35: 0011 0101 oooo oooo xxxx xxxx */
+static void LTIW_wa_xx(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ UINT8 tmp, m, imm;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( imm );
+ m = RM( ea.d );
+ tmp = m - imm;
+ ZHC_SUB( tmp, m, 0 );
+ SKIP_CY;
+}
+
+/* 36: 0011 0110 xxxx xxxx */
+/* SUINB_A_xx already defined (long form) */
+
+/* 37: 0011 0111 xxxx xxxx */
+/* LTI_A_xx already defined (long form) */
+
+/* 39: 0011 1001 */
+static void STAX_B(upd7810_state *cpustate)
+{
+ WM( BC, A );
+}
+
+/* 3a: 0011 1010 */
+static void STAX_D(upd7810_state *cpustate)
+{
+ WM( DE, A );
+}
+
+/* 3b: 0011 1011 */
+static void STAX_H(upd7810_state *cpustate)
+{
+ WM( HL, A );
+}
+
+/* 3c: 0011 1100 */
+static void STAX_Dp(upd7810_state *cpustate)
+{
+ WM( DE, A );
+ DE++;
+}
+
+/* 3d: 0011 1101 */
+static void STAX_Hp(upd7810_state *cpustate)
+{
+ WM( HL, A );
+ HL++;
+}
+
+/* 3e: 0011 1110 */
+static void STAX_Dm(upd7810_state *cpustate)
+{
+ WM( DE, A );
+ DE--;
+}
+
+/* 3f: 0011 1111 */
+static void STAX_Hm(upd7810_state *cpustate)
+{
+ WM( HL, A );
+ HL--;
+}
+
+/* 40: 0100 0000 llll llll hhhh hhhh */
+static void CALL_w(upd7810_state *cpustate)
+{
+ PAIR w;
+ w.d = 0;
+
+ RDOPARG( w.b.l );
+ RDOPARG( w.b.h );
+
+ SP--;
+ WM( SPD, PCH );
+ SP--;
+ WM( SPD, PCL );
+
+ PC = w.w.l;
+}
+
+/* 41: 0100 0001 */
+static void INR_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = A + 1;
+ ZHC_ADD( tmp, A, 0 );
+ A = tmp;
+ SKIP_CY;
+}
+
+/* 42: 0100 0010 */
+static void INR_B(upd7810_state *cpustate)
+{
+ UINT8 tmp = B + 1;
+ ZHC_ADD( tmp, B, 0 );
+ B = tmp;
+ SKIP_CY;
+}
+
+/* 43: 0100 0011 */
+static void INR_C(upd7810_state *cpustate)
+{
+ UINT8 tmp = C + 1;
+ ZHC_ADD( tmp, C, 0 );
+ C = tmp;
+ SKIP_CY;
+}
+
+/* 44: 0100 0100 llll llll hhhh hhhh */
+static void LXI_EA_s(upd7810_state *cpustate)
+{
+ RDOPARG( EAL );
+ RDOPARG( EAH );
+}
+
+/* 45: 0100 0101 oooo oooo xxxx xxxx */
+static void ONIW_wa_xx(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ UINT8 imm;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( imm );
+
+ if (RM( ea.d ) & imm)
+ PSW |= SK;
+}
+
+/* 46: 0100 0110 xxxx xxxx */
+/* ADI_A_xx already defined (long form) */
+
+/* 47: 0100 0111 xxxx xxxx */
+/* ONI_A_xx already defined (long form) */
+
+/* 48: prefix */
+static void PRE_48(upd7810_state *cpustate)
+{
+ RDOP(OP2);
+ cpustate->icount -= cpustate->op48[OP2].cycles;
+ cpustate->handle_timers(cpustate, cpustate->op48[OP2].cycles);
+ (*cpustate->op48[OP2].opfunc)(cpustate);
+}
+
+/* 49: 0100 1001 xxxx xxxx */
+static void MVIX_BC_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ WM( BC, imm );
+}
+
+/* 4a: 0100 1010 xxxx xxxx */
+static void MVIX_DE_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ WM( DE, imm );
+}
+
+/* 4b: 0100 1011 xxxx xxxx */
+static void MVIX_HL_xx(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ RDOPARG( imm );
+ WM( HL, imm );
+}
+
+/* 4c: prefix */
+static void PRE_4C(upd7810_state *cpustate)
+{
+ RDOP(OP2);
+ cpustate->icount -= cpustate->op4C[OP2].cycles;
+ cpustate->handle_timers(cpustate, cpustate->op4C[OP2].cycles);
+ (*cpustate->op4C[OP2].opfunc)(cpustate);
+}
+
+/* 4d: prefix */
+static void PRE_4D(upd7810_state *cpustate)
+{
+ RDOP(OP2);
+ cpustate->icount -= cpustate->op4D[OP2].cycles;
+ cpustate->handle_timers(cpustate, cpustate->op4D[OP2].cycles);
+ (*cpustate->op4D[OP2].opfunc)(cpustate);
+}
+
+/* 4e: 0100 111d dddd dddd */
+static void JRE(upd7810_state *cpustate)
+{
+ UINT8 offs;
+ RDOPARG( offs );
+ if (OP & 0x01)
+ PC -= 256 - offs;
+ else
+ PC += offs;
+}
+
+/* 50: 0101 0000 */
+static void EXH(upd7810_state *cpustate)
+{
+ UINT16 tmp;
+ tmp = HL; HL = HL2; HL2 = tmp;
+}
+
+/* 51: 0101 0001 */
+static void DCR_A(upd7810_state *cpustate)
+{
+ UINT8 tmp = A - 1;
+ ZHC_SUB( tmp, A, 0 );
+ A = tmp;
+ SKIP_CY;
+}
+
+/* 52: 0101 0010 */
+static void DCR_B(upd7810_state *cpustate)
+{
+ UINT8 tmp = B - 1;
+ ZHC_SUB( tmp, B, 0 );
+ B = tmp;
+ SKIP_CY;
+}
+
+/* 53: 0101 0011 */
+static void DCR_C(upd7810_state *cpustate)
+{
+ UINT8 tmp = C - 1;
+ ZHC_SUB( tmp, C, 0 );
+ C = tmp;
+ SKIP_CY;
+}
+
+/* 54: 0101 0100 llll llll hhhh hhhh */
+static void JMP_w(upd7810_state *cpustate)
+{
+ PAIR w;
+ w.d = 0;
+
+ RDOPARG( w.b.l );
+ RDOPARG( w.b.h );
+
+ PCD = w.d;
+}
+
+/* 55: 0101 0101 oooo oooo xxxx xxxx */
+static void OFFIW_wa_xx(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ UINT8 imm;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( imm );
+
+ if (0 == (RM( ea.d ) & imm))
+ PSW |= SK;
+}
+
+/* 56: 0101 0110 xxxx xxxx */
+/* ACI_A_xx already defined (long form) */
+
+/* 57: 0101 0111 xxxx xxxx */
+/* OFFI_A_xx already defined (long form) */
+
+/* 58: 0101 1000 oooo oooo (7810 only) */
+static void BIT_0_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+
+ RDOPARG( ea.b.l );
+
+ if (RM( ea.d ) & 0x01)
+ PSW |= SK;
+}
+
+/* 59: 0101 1001 oooo oooo (7810 only) */
+static void BIT_1_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+
+ RDOPARG( ea.b.l );
+
+ if (RM( ea.d ) & 0x02)
+ PSW |= SK;
+}
+
+/* 5a: 0101 1010 oooo oooo (7810 only) */
+static void BIT_2_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+
+ RDOPARG( ea.b.l );
+
+ if (RM( ea.d ) & 0x04)
+ PSW |= SK;
+}
+
+/* 5b: 0101 1011 oooo oooo (7810 only) */
+static void BIT_3_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+
+ RDOPARG( ea.b.l );
+
+ if (RM( ea.d ) & 0x08)
+ PSW |= SK;
+}
+
+/* 5c: 0101 1100 oooo oooo (7810 only) */
+static void BIT_4_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+
+ RDOPARG( ea.b.l );
+
+ if (RM( ea.d ) & 0x10)
+ PSW |= SK;
+}
+
+/* 5d: 0101 1101 oooo oooo (7810 only) */
+static void BIT_5_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+
+ RDOPARG( ea.b.l );
+
+ if (RM( ea.d ) & 0x20)
+ PSW |= SK;
+}
+
+/* 5e: 0101 1110 oooo oooo (7810 only) */
+static void BIT_6_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+
+ RDOPARG( ea.b.l );
+
+ if (RM( ea.d ) & 0x40)
+ PSW |= SK;
+}
+
+/* 5f: 0101 1111 oooo oooo (7810 only) */
+static void BIT_7_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+
+ RDOPARG( ea.b.l );
+
+ if (RM( ea.d ) & 0x80)
+ PSW |= SK;
+}
+
+/* 5d: 0101 1111 bbbb bbbb (7807 only) */
+static void SKN_bit(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ int val;
+
+ RDOPARG( imm );
+
+ switch( imm & 0x1f )
+ {
+ case 0x10: /* PA */
+ val = RP( cpustate, UPD7810_PORTA );
+ break;
+ case 0x11: /* PB */
+ val = RP( cpustate, UPD7810_PORTB );
+ break;
+ case 0x12: /* PC */
+ val = RP( cpustate, UPD7810_PORTC );
+ break;
+ case 0x13: /* PD */
+ val = RP( cpustate, UPD7810_PORTD );
+ break;
+ case 0x15: /* PF */
+ val = RP( cpustate, UPD7810_PORTF );
+ break;
+ case 0x16: /* MKH */
+ val = MKH;
+ break;
+ case 0x17: /* MKL */
+ val = MKL;
+ break;
+ case 0x19: /* SMH */
+ val = SMH;
+ break;
+ case 0x1b: /* EOM */
+ val = EOM;
+ break;
+ case 0x1d: /* TMM */
+ val = TMM;
+ break;
+ case 0x1e: /* PT */
+ val = RP( cpustate, UPD7807_PORTT );
+ break;
+ default:
+ logerror("uPD7810 '%s': illegal opcode %02x %02x at PC:%04x\n", cpustate->device->tag(), OP, imm, PC);
+ val = 0;
+ break;
+ }
+
+ if (~val & (1 << (imm >> 5)))
+ PSW |= SK;
+}
+
+/* 58: 0101 1000 bbbb bbbb (7807 only) */
+static void SETB(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ int bit;
+
+ RDOPARG( imm );
+ bit = imm >> 5;
+
+ switch( imm & 0x1f )
+ {
+ case 0x10: /* PA */
+ WP( cpustate, UPD7810_PORTA, RP( cpustate, UPD7810_PORTA ) | (1 << bit));
+ break;
+ case 0x11: /* PB */
+ WP( cpustate, UPD7810_PORTB, RP( cpustate, UPD7810_PORTB ) | (1 << bit));
+ break;
+ case 0x12: /* PC */
+ WP( cpustate, UPD7810_PORTC, RP( cpustate, UPD7810_PORTC ) | (1 << bit));
+ break;
+ case 0x13: /* PD */
+ WP( cpustate, UPD7810_PORTD, RP( cpustate, UPD7810_PORTD ) | (1 << bit));
+ break;
+ case 0x15: /* PF */
+ WP( cpustate, UPD7810_PORTF, RP( cpustate, UPD7810_PORTF ) | (1 << bit));
+ break;
+ case 0x16: /* MKH */
+ MKH |= (1 << bit);
+ break;
+ case 0x17: /* MKL */
+ MKL |= (1 << bit);
+ break;
+ case 0x19: /* SMH */
+ SMH |= (1 << bit);
+ break;
+ case 0x1b: /* EOM */
+ EOM |= (1 << bit);
+ break;
+ case 0x1d: /* TMM */
+ TMM |= (1 << bit);
+ break;
+// case 0x1e: /* PT */
+// PT is input only
+// break;
+ default:
+ logerror("uPD7810 '%s': illegal opcode %02x %02x at PC:%04x\n", cpustate->device->tag(), OP, imm, PC);
+ break;
+ }
+}
+
+/* 5b: 0101 1011 bbbb bbbb (7807 only) */
+static void CLR(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ int bit;
+
+ RDOPARG( imm );
+ bit = imm >> 5;
+
+ switch( imm & 0x1f )
+ {
+ case 0x10: /* PA */
+ WP( cpustate, UPD7810_PORTA, RP( cpustate, UPD7810_PORTA ) & ~(1 << bit));
+ break;
+ case 0x11: /* PB */
+ WP( cpustate, UPD7810_PORTB, RP( cpustate, UPD7810_PORTB ) & ~(1 << bit));
+ break;
+ case 0x12: /* PC */
+ WP( cpustate, UPD7810_PORTC, RP( cpustate, UPD7810_PORTC ) & ~(1 << bit));
+ break;
+ case 0x13: /* PD */
+ WP( cpustate, UPD7810_PORTD, RP( cpustate, UPD7810_PORTD ) & ~(1 << bit));
+ break;
+ case 0x15: /* PF */
+ WP( cpustate, UPD7810_PORTF, RP( cpustate, UPD7810_PORTF ) & ~(1 << bit));
+ break;
+ case 0x16: /* MKH */
+ MKH &= ~(1 << bit);
+ break;
+ case 0x17: /* MKL */
+ MKL &= ~(1 << bit);
+ break;
+ case 0x19: /* SMH */
+ SMH &= ~(1 << bit);
+ break;
+ case 0x1b: /* EOM */
+ EOM &= ~(1 << bit);
+ break;
+ case 0x1d: /* TMM */
+ TMM &= ~(1 << bit);
+ break;
+// case 0x1e: /* PT */
+// PT is input only
+// break;
+ default:
+ logerror("uPD7810 '%s': illegal opcode %02x %02x at PC:%04x\n", cpustate->device->tag(), OP, imm, PC);
+ break;
+ }
+}
+
+/* 5d: 0101 1111 bbbb bbbb (7807 only) */
+static void SK_bit(upd7810_state *cpustate)
+{
+ UINT8 imm;
+ int val;
+
+ RDOPARG( imm );
+
+ switch( imm & 0x1f )
+ {
+ case 0x10: /* PA */
+ val = RP( cpustate, UPD7810_PORTA );
+ break;
+ case 0x11: /* PB */
+ val = RP( cpustate, UPD7810_PORTB );
+ break;
+ case 0x12: /* PC */
+ val = RP( cpustate, UPD7810_PORTC );
+ break;
+ case 0x13: /* PD */
+ val = RP( cpustate, UPD7810_PORTD );
+ break;
+ case 0x15: /* PF */
+ val = RP( cpustate, UPD7810_PORTF );
+ break;
+ case 0x16: /* MKH */
+ val = MKH;
+ break;
+ case 0x17: /* MKL */
+ val = MKL;
+ break;
+ case 0x19: /* SMH */
+ val = SMH;
+ break;
+ case 0x1b: /* EOM */
+ val = EOM;
+ break;
+ case 0x1d: /* TMM */
+ val = TMM;
+ break;
+ case 0x1e: /* PT */
+ val = RP( cpustate, UPD7807_PORTT );
+ break;
+ default:
+ logerror("uPD7810 '%s': illegal opcode %02x %02x at PC:%04x\n", cpustate->device->tag(), OP, imm, PC);
+ val = 0;
+ break;
+ }
+
+ if (val & (1 << (imm >> 5)))
+ PSW |= SK;
+}
+
+/* 60:*/
+static void PRE_60(upd7810_state *cpustate)
+{
+ RDOP(OP2);
+ cpustate->icount -= cpustate->op60[OP2].cycles;
+ cpustate->handle_timers(cpustate, cpustate->op60[OP2].cycles);
+ (*cpustate->op60[OP2].opfunc)(cpustate);
+}
+
+/* 61: 0110 0001 */
+static void DAA(upd7810_state *cpustate)
+{
+ UINT8 l = A & 0x0f, h = A >> 4, tmp, adj = 0x00;
+ if (0 == (PSW & HC))
+ {
+ if (l < 10)
+ {
+ if (!(h < 10 && 0 == (PSW & CY)))
+ adj = 0x60;
+ }
+ else
+ {
+ if (h < 9 && 0 == (PSW & CY))
+ adj = 0x06;
+ else
+ adj = 0x66;
+ }
+ }
+ else
+ if (l < 3)
+ {
+ if (h < 10 && 0 == (PSW & CY))
+ adj = 0x06;
+ else
+ adj = 0x66;
+ }
+ tmp = A + adj;
+ ZHC_ADD( tmp, A, PSW & CY );
+ A = tmp;
+}
+
+/* 62: 0110 0010 */
+static void RETI(upd7810_state *cpustate)
+{
+ PCL = RM( SPD );
+ SP++;
+ PCH = RM( SPD );
+ SP++;
+ PSW = RM( SPD );
+ SP++;
+}
+
+/* 63: 0110 0011 oooo oooo */
+static void STAW_wa(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+
+ RDOPARG( ea.b.l );
+
+ WM( ea.d, A );
+}
+
+/* 64: prefix */
+static void PRE_64(upd7810_state *cpustate)
+{
+ RDOP(OP2);
+ cpustate->icount -= cpustate->op64[OP2].cycles;
+ cpustate->handle_timers(cpustate, cpustate->op64[OP2].cycles);
+ (*cpustate->op64[OP2].opfunc)(cpustate);
+}
+
+/* 65: 0110 0101 oooo oooo xxxx xxxx */
+static void NEIW_wa_xx(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ UINT8 tmp, m, imm;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( imm );
+ m = RM( ea.d );
+ tmp = m - imm;
+ ZHC_SUB( tmp, m, 0 );
+ SKIP_NZ;
+}
+
+/* 66: 0110 0110 xxxx xxxx */
+/* SUI_A_xx already defined (long form) */
+
+/* 67: 0110 0111 xxxx xxxx */
+/* NEI_A_xx already defined (long form) */
+
+/* 68: 0110 1000 xxxx xxxx */
+static void MVI_V_xx(upd7810_state *cpustate)
+{
+ RDOPARG( V );
+}
+
+/* 69: 0110 1001 xxxx xxxx */
+static void MVI_A_xx(upd7810_state *cpustate)
+{
+ if (PSW & L1) { /* overlay active? */
+ PC++;
+ return; /* NOP */
+ }
+ RDOPARG( A );
+ PSW |= L1;
+}
+
+/* 6a: 0110 1010 xxxx xxxx */
+static void MVI_B_xx(upd7810_state *cpustate)
+{
+ RDOPARG( B );
+}
+
+/* 6b: 0110 1011 xxxx xxxx */
+static void MVI_C_xx(upd7810_state *cpustate)
+{
+ RDOPARG( C );
+}
+
+/* 6c: 0110 1100 xxxx xxxx */
+static void MVI_D_xx(upd7810_state *cpustate)
+{
+ RDOPARG( D );
+}
+
+/* 6d: 0110 1101 xxxx xxxx */
+static void MVI_E_xx(upd7810_state *cpustate)
+{
+ RDOPARG( E );
+}
+
+/* 6e: 0110 1110 xxxx xxxx */
+static void MVI_H_xx(upd7810_state *cpustate)
+{
+ RDOPARG( H );
+}
+
+/* 6f: 0110 1111 xxxx xxxx */
+static void MVI_L_xx(upd7810_state *cpustate)
+{
+ if (PSW & L0) { /* overlay active? */
+ PC++;
+ return; /* NOP */
+ }
+ RDOPARG( L );
+ PSW |= L0;
+}
+
+/* 70: prefix */
+static void PRE_70(upd7810_state *cpustate)
+{
+ RDOP(OP2);
+ cpustate->icount -= cpustate->op70[OP2].cycles;
+ cpustate->handle_timers(cpustate, cpustate->op70[OP2].cycles);
+ (*cpustate->op70[OP2].opfunc)(cpustate);
+}
+
+/* 71: 0111 0001 oooo oooo xxxx xxxx */
+static void MVIW_wa_xx(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ UINT8 imm;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( imm );
+
+ WM( ea.d, imm );
+}
+
+/* 72: 0111 0010 */
+static void SOFTI(upd7810_state *cpustate)
+{
+ SP--;
+ WM( SPD, PSW );
+ SP--;
+ WM( SPD, PCH );
+ SP--;
+ WM( SPD, PCL );
+
+ PC = 0x0060;
+}
+
+/* 74: prefix */
+static void PRE_74(upd7810_state *cpustate)
+{
+ RDOP(OP2);
+ cpustate->icount -= cpustate->op74[OP2].cycles;
+ cpustate->handle_timers(cpustate, cpustate->op74[OP2].cycles);
+ (*cpustate->op74[OP2].opfunc)(cpustate);
+}
+
+/* 75: 0111 0101 oooo oooo xxxx xxxx */
+static void EQIW_wa_xx(upd7810_state *cpustate)
+{
+ PAIR ea = cpustate->va;
+ UINT8 tmp, m, imm;
+
+ RDOPARG( ea.b.l );
+ RDOPARG( imm );
+ m = RM( ea.d );
+ tmp = m - imm;
+ ZHC_SUB( tmp, m, 0 );
+ SKIP_Z;
+}
+
+/* 76: 0111 0110 xxxx xxxx */
+/* SBI_A_xx already defined (long form) */
+
+/* 77: 0111 0111 xxxx xxxx */
+/* EQI_A_xx already defined (long form) */
+
+/* 78: 0111 1ddd dddd dddd */
+static void CALF(upd7810_state *cpustate)
+{
+ PAIR w;
+ w.d = 0;
+
+ RDOPARG( w.b.l );
+ w.b.h = 0x08 + (OP & 0x07);
+
+ SP--;
+ WM( SPD, PCH );
+ SP--;
+ WM( SPD, PCL );
+
+ PCD = w.d;
+}
+
+/* 80: 100t tttt */
+static void CALT(upd7810_state *cpustate)
+{
+ PAIR w;
+ w.d = 0;
+
+ switch (cpustate->config.type) {
+ case TYPE_7810_GAMEMASTER:
+ logerror ("!!!!!!!%.4x calt %.2x game master table position not known\n",PPC, OP);
+ break;
+ default:
+ w.w.l = 0x80 + 2 * (OP & 0x1f);
+ }
+
+ if (cpustate->config.type!=TYPE_7810_GAMEMASTER) {
+ SP--;
+ WM( SPD, PCH );
+ SP--;
+ WM( SPD, PCL );
+
+ PCL=RM(w.w.l);
+ PCH=RM(w.w.l+1);
+ }
+}
+
+/* a0: 1010 0000 */
+static void POP_VA(upd7810_state *cpustate)
+{
+ A = RM( SPD );
+ SP++;
+ V = RM( SPD );
+ SP++;
+}
+
+/* a1: 1010 0001 */
+static void POP_BC(upd7810_state *cpustate)
+{
+ C = RM( SPD );
+ SP++;
+ B = RM( SPD );
+ SP++;
+}
+
+/* a2: 1010 0010 */
+static void POP_DE(upd7810_state *cpustate)
+{
+ E = RM( SPD );
+ SP++;
+ D = RM( SPD );
+ SP++;
+}
+
+/* a3: 1010 0011 */
+static void POP_HL(upd7810_state *cpustate)
+{
+ L = RM( SPD );
+ SP++;
+ H = RM( SPD );
+ SP++;
+}
+
+/* a4: 1010 0100 */
+static void POP_EA(upd7810_state *cpustate)
+{
+ EAL = RM( SPD );
+ SP++;
+ EAH = RM( SPD );
+ SP++;
+}
+
+/* a5: 1010 0101 */
+static void DMOV_EA_BC(upd7810_state *cpustate)
+{
+ EA = BC;
+}
+
+/* a6: 1010 0110 */
+static void DMOV_EA_DE(upd7810_state *cpustate)
+{
+ EA = DE;
+}
+
+/* a7: 1010 0111 */
+static void DMOV_EA_HL(upd7810_state *cpustate)
+{
+ EA = HL;
+}
+
+/* a8: 1010 1000 */
+static void INX_EA(upd7810_state *cpustate)
+{
+ EA++;
+}
+
+/* a9: 1010 1001 */
+static void DCX_EA(upd7810_state *cpustate)
+{
+ EA--;
+}
+
+/* aa: 1010 1010 */
+static void EI(upd7810_state *cpustate)
+{
+ IFF = 1;
+}
+
+/* ab: 1010 1011 dddd dddd */
+static void LDAX_D_xx(upd7810_state *cpustate)
+{
+ UINT16 ea;
+ RDOPARG( ea );
+ ea += DE;
+ A = RM( ea );
+}
+
+/* ac: 1010 1100 */
+static void LDAX_H_A(upd7810_state *cpustate)
+{
+ UINT16 ea;
+ ea = HL + A;
+ A = RM( ea );
+}
+
+/* ad: 1010 1101 */
+static void LDAX_H_B(upd7810_state *cpustate)
+{
+ UINT16 ea;
+ ea = HL + B;
+ A = RM( ea );
+}
+
+/* ae: 1010 1110 */
+static void LDAX_H_EA(upd7810_state *cpustate)
+{
+ UINT16 ea;
+ ea = HL + EA;
+ A = RM( ea );
+}
+
+/* af: 1010 1111 dddd dddd */
+static void LDAX_H_xx(upd7810_state *cpustate)
+{
+ UINT16 ea;
+ RDOPARG( ea );
+ ea += HL;
+ A = RM( ea );
+}
+
+/* b0: 1011 0000 */
+static void PUSH_VA(upd7810_state *cpustate)
+{
+ SP--;
+ WM( SPD, V );
+ SP--;
+ WM( SPD, A );
+}
+
+/* b1: 1011 0001 */
+static void PUSH_BC(upd7810_state *cpustate)
+{
+ SP--;
+ WM( SPD, B );
+ SP--;
+ WM( SPD, C );
+}
+
+/* b2: 1011 0010 */
+static void PUSH_DE(upd7810_state *cpustate)
+{
+ SP--;
+ WM( SPD, D );
+ SP--;
+ WM( SPD, E );
+}
+
+/* b3: 1011 0011 */
+static void PUSH_HL(upd7810_state *cpustate)
+{
+ SP--;
+ WM( SPD, H );
+ SP--;
+ WM( SPD, L );
+}
+
+/* b4: 1011 0100 */
+static void PUSH_EA(upd7810_state *cpustate)
+{
+ SP--;
+ WM( SPD, EAH );
+ SP--;
+ WM( SPD, EAL );
+}
+
+/* b5: 1011 0101 */
+static void DMOV_BC_EA(upd7810_state *cpustate)
+{
+ BC = EA;
+}
+
+/* b6: 1011 0110 */
+static void DMOV_DE_EA(upd7810_state *cpustate)
+{
+ DE = EA;
+}
+
+/* b7: 1011 0111 */
+static void DMOV_HL_EA(upd7810_state *cpustate)
+{
+ HL = EA;
+}
+
+/* b8: 1011 1000 */
+static void RET(upd7810_state *cpustate)
+{
+ PCL = RM( SPD );
+ SP++;
+ PCH = RM( SPD );
+ SP++;
+}
+
+/* b9: 1011 1001 */
+static void RETS(upd7810_state *cpustate)
+{
+ PCL = RM( SPD );
+ SP++;
+ PCH = RM( SPD );
+ SP++;
+ PSW|=SK; /* skip one instruction */
+}
+
+/* ba: 1011 1010 */
+static void DI(upd7810_state *cpustate)
+{
+ IFF = 0;
+}
+
+/* bb: 1011 1011 dddd dddd */
+static void STAX_D_xx(upd7810_state *cpustate)
+{
+ UINT16 ea;
+ RDOPARG(ea);
+ ea += DE;
+ WM( ea, A );
+}
+
+/* bc: 1011 1100 */
+static void STAX_H_A(upd7810_state *cpustate)
+{
+ UINT16 ea = A;
+ ea += HL;
+ WM( ea, A );
+}
+
+/* bd: 1011 1101 */
+static void STAX_H_B(upd7810_state *cpustate)
+{
+ UINT16 ea = B;
+ ea += HL;
+ WM( ea, A );
+}
+
+/* be: 1011 1110 */
+static void STAX_H_EA(upd7810_state *cpustate)
+{
+ UINT16 ea = EA;
+ ea += HL;
+ WM( ea, A );
+}
+
+/* bf: 1011 1111 dddd dddd */
+static void STAX_H_xx(upd7810_state *cpustate)
+{
+ UINT16 ea;
+ RDOPARG( ea );
+ ea += HL;
+ WM( ea, A );
+}
+
+/* c0: 11dd dddd */
+static void JR(upd7810_state *cpustate)
+{
+ INT8 offs = (INT8)(OP << 2) >> 2;
+ PC += offs;
+}
+
+/*********************/
+/* */
+/* 7801 instructions */
+/* */
+/*********************/
+
+static void CALT_7801(upd7810_state *cpustate)
+{
+ PAIR w;
+ w.d = 0;
+
+ w.w.l = 0x80 + 2 * (OP & 0x3f);
+
+ SP--;
+ WM( SPD, PCH );
+ SP--;
+ WM( SPD, PCL );
+
+ PCL=RM(w.w.l);
+ PCH=RM(w.w.l+1);
+}
+
+/* DCR(W) and INR(W) instructions do not modify the CY register on at least 78c05 and 78c06 */
+static void DCR_A_7801(upd7810_state *cpustate)
+{
+ UINT32 old_CY = PSW & CY;
+ DCR_A(cpustate);
+ PSW = ( PSW & ~CY ) | old_CY;
+}
+
+static void DCR_B_7801(upd7810_state *cpustate)
+{
+ UINT32 old_CY = PSW & CY;
+ DCR_B(cpustate);
+ PSW = ( PSW & ~CY ) | old_CY;
+}
+
+static void DCR_C_7801(upd7810_state *cpustate)
+{
+ UINT32 old_CY = PSW & CY;
+ DCR_C(cpustate);
+ PSW = ( PSW & ~CY ) | old_CY;
+}
+
+static void DCRW_wa_7801(upd7810_state *cpustate)
+{
+ UINT32 old_CY = PSW & CY;
+ DCRW_wa(cpustate);
+ PSW = ( PSW & ~CY ) | old_CY;
+}
+
+static void INR_A_7801(upd7810_state *cpustate)
+{
+ UINT32 old_CY = PSW & CY;
+ INR_A(cpustate);
+ PSW = ( PSW & ~CY ) | old_CY;
+}
+
+static void INR_B_7801(upd7810_state *cpustate)
+{
+ UINT32 old_CY = PSW & CY;
+ INR_B(cpustate);
+ PSW = ( PSW & ~CY ) | old_CY;
+}
+
+static void INR_C_7801(upd7810_state *cpustate)
+{
+ UINT32 old_CY = PSW & CY;
+ INR_C(cpustate);
+ PSW = ( PSW & ~CY ) | old_CY;
+}
+
+static void INRW_wa_7801(upd7810_state *cpustate)
+{
+ UINT32 old_CY = PSW & CY;
+ INRW_wa(cpustate);
+ PSW = ( PSW & ~CY ) | old_CY;
+}
+
+static void IN(upd7810_state *cpustate)
+{
+ logerror("unimplemented instruction: IN\n");
+}
+
+static void OUT(upd7810_state *cpustate)
+{
+ logerror("unimplemented instruction: OUT\n");
+}
+
+static void MOV_A_S(upd7810_state *cpustate)
+{
+ logerror("unimplemented instruction: MOV_A_S\n");
+}
+
+static void MOV_S_A(upd7810_state *cpustate)
+{
+ logerror("unimplemented instruction: MOV_A_S\n");
+}
+
+static void PEN(upd7810_state *cpustate)
+{
+ logerror("unimplemented instruction: PEN\n");
+}
+
+static void PER(upd7810_state *cpustate)
+{
+ logerror("unimplemented instruction: PER\n");
+}
+
+static void PEX(upd7810_state *cpustate)
+{
+ logerror("unimplemented instruction: PEX\n");
+}
+
+static void SIO(upd7810_state *cpustate)
+{
+ logerror("unimplemented instruction: SIO\n");
+}
+
+static void SKIT_F0(upd7810_state *cpustate)
+{
+ if (IRR & INTF0)
+ PSW |= SK;
+ IRR &= ~INTF0;
+}
+
+static void SKNIT_F0(upd7810_state *cpustate)
+{
+ logerror("unimplemented instruction: SKNIT_F0\n");
+}
+
+static void STM(upd7810_state *cpustate)
+{
+ cpustate->ovc0 = ( ( TMM & 0x04 ) ? 16 * 8 : 8 ) * TM0;
+}
+
+static void STM_7801(upd7810_state *cpustate)
+{
+ /* Set the timer flip/fliop */
+ TO = 1;
+ if ( cpustate->config.io_callback)
+ (*cpustate->config.io_callback)(cpustate->device,UPD7810_TO,TO);
+
+ /* Reload the timer */
+ cpustate->ovc0 = 16 * ( TM0 + ( ( TM1 & 0x0f ) << 8 ) );
+}
+
+static void MOV_MC_A_7801(upd7810_state *cpustate)
+{
+ /* On the 7801 the mode C bits function as follows: */
+ /* Cn=1 Cn=0 */
+ /* PC0 Input Output */
+ /* PC1 Input Output */
+ /* PC2 Input -SCS Input */
+ /* PC3 Output SAK Output */
+ /* PC4 Output To Output */
+ /* PC5 Output IO/-M Output */
+ /* PC6 Output HLDA Output */
+ /* PC7 Input HOLD Input */
+ MC = 0x84 | ( ( A & 0x02 ) ? 0x02 : 0x00 ) | ( ( A & 0x01 ) ? 0x01 : 0x00 );
+}
+
diff --git a/trunk/src/emu/cpu/upd7810/7810tbl.c b/trunk/src/emu/cpu/upd7810/7810tbl.c
new file mode 100644
index 00000000000..fd3cc4f0af3
--- /dev/null
+++ b/trunk/src/emu/cpu/upd7810/7810tbl.c
@@ -0,0 +1,7288 @@
+/*****************************************************************************
+ *
+ * Portable uPD7810/11, 7810H/11H, 78C10/C11/C14 emulator V0.2
+ * Copyright Juergen Buchmueller, all rights reserved.
+ *
+ * 7810tbl.c - function pointer tables
+ *
+ *****************************************************************************/
+
+static void illegal(upd7810_state *cpustate);
+static void illegal2(upd7810_state *cpustate);
+
+static void ACI_ANM_xx(upd7810_state *cpustate);
+static void ACI_A_xx(upd7810_state *cpustate);
+static void ACI_B_xx(upd7810_state *cpustate);
+static void ACI_C_xx(upd7810_state *cpustate);
+static void ACI_D_xx(upd7810_state *cpustate);
+static void ACI_EOM_xx(upd7810_state *cpustate);
+static void ACI_E_xx(upd7810_state *cpustate);
+static void ACI_H_xx(upd7810_state *cpustate);
+static void ACI_L_xx(upd7810_state *cpustate);
+static void ACI_MKH_xx(upd7810_state *cpustate);
+static void ACI_MKL_xx(upd7810_state *cpustate);
+static void ACI_PA_xx(upd7810_state *cpustate);
+static void ACI_PB_xx(upd7810_state *cpustate);
+static void ACI_PC_xx(upd7810_state *cpustate);
+static void ACI_PD_xx(upd7810_state *cpustate);
+static void ACI_PF_xx(upd7810_state *cpustate);
+static void ACI_SMH_xx(upd7810_state *cpustate);
+static void ACI_TMM_xx(upd7810_state *cpustate);
+static void ACI_V_xx(upd7810_state *cpustate);
+static void ADCW_wa(upd7810_state *cpustate);
+static void ADCX_B(upd7810_state *cpustate);
+static void ADCX_D(upd7810_state *cpustate);
+static void ADCX_Dm(upd7810_state *cpustate);
+static void ADCX_Dp(upd7810_state *cpustate);
+static void ADCX_H(upd7810_state *cpustate);
+static void ADCX_Hm(upd7810_state *cpustate);
+static void ADCX_Hp(upd7810_state *cpustate);
+static void ADC_A_A(upd7810_state *cpustate);
+static void ADC_A_A(upd7810_state *cpustate);
+static void ADC_A_B(upd7810_state *cpustate);
+static void ADC_A_C(upd7810_state *cpustate);
+static void ADC_A_D(upd7810_state *cpustate);
+static void ADC_A_E(upd7810_state *cpustate);
+static void ADC_A_H(upd7810_state *cpustate);
+static void ADC_A_L(upd7810_state *cpustate);
+static void ADC_A_V(upd7810_state *cpustate);
+static void ADC_B_A(upd7810_state *cpustate);
+static void ADC_C_A(upd7810_state *cpustate);
+static void ADC_D_A(upd7810_state *cpustate);
+static void ADC_E_A(upd7810_state *cpustate);
+static void ADC_H_A(upd7810_state *cpustate);
+static void ADC_L_A(upd7810_state *cpustate);
+static void ADC_V_A(upd7810_state *cpustate);
+static void ADDNCW_wa(upd7810_state *cpustate);
+static void ADDNCX_B(upd7810_state *cpustate);
+static void ADDNCX_D(upd7810_state *cpustate);
+static void ADDNCX_Dm(upd7810_state *cpustate);
+static void ADDNCX_Dp(upd7810_state *cpustate);
+static void ADDNCX_H(upd7810_state *cpustate);
+static void ADDNCX_Hm(upd7810_state *cpustate);
+static void ADDNCX_Hp(upd7810_state *cpustate);
+static void ADDNC_A_A(upd7810_state *cpustate);
+static void ADDNC_A_A(upd7810_state *cpustate);
+static void ADDNC_A_B(upd7810_state *cpustate);
+static void ADDNC_A_C(upd7810_state *cpustate);
+static void ADDNC_A_D(upd7810_state *cpustate);
+static void ADDNC_A_E(upd7810_state *cpustate);
+static void ADDNC_A_H(upd7810_state *cpustate);
+static void ADDNC_A_L(upd7810_state *cpustate);
+static void ADDNC_A_V(upd7810_state *cpustate);
+static void ADDNC_B_A(upd7810_state *cpustate);
+static void ADDNC_C_A(upd7810_state *cpustate);
+static void ADDNC_D_A(upd7810_state *cpustate);
+static void ADDNC_E_A(upd7810_state *cpustate);
+static void ADDNC_H_A(upd7810_state *cpustate);
+static void ADDNC_L_A(upd7810_state *cpustate);
+static void ADDNC_V_A(upd7810_state *cpustate);
+static void ADDW_wa(upd7810_state *cpustate);
+static void ADDX_B(upd7810_state *cpustate);
+static void ADDX_D(upd7810_state *cpustate);
+static void ADDX_Dm(upd7810_state *cpustate);
+static void ADDX_Dp(upd7810_state *cpustate);
+static void ADDX_H(upd7810_state *cpustate);
+static void ADDX_Hm(upd7810_state *cpustate);
+static void ADDX_Hp(upd7810_state *cpustate);
+static void ADD_A_A(upd7810_state *cpustate);
+static void ADD_A_A(upd7810_state *cpustate);
+static void ADD_A_B(upd7810_state *cpustate);
+static void ADD_A_C(upd7810_state *cpustate);
+static void ADD_A_D(upd7810_state *cpustate);
+static void ADD_A_E(upd7810_state *cpustate);
+static void ADD_A_H(upd7810_state *cpustate);
+static void ADD_A_L(upd7810_state *cpustate);
+static void ADD_A_V(upd7810_state *cpustate);
+static void ADD_B_A(upd7810_state *cpustate);
+static void ADD_C_A(upd7810_state *cpustate);
+static void ADD_D_A(upd7810_state *cpustate);
+static void ADD_E_A(upd7810_state *cpustate);
+static void ADD_H_A(upd7810_state *cpustate);
+static void ADD_L_A(upd7810_state *cpustate);
+static void ADD_V_A(upd7810_state *cpustate);
+static void ADINC_ANM_xx(upd7810_state *cpustate);
+static void ADINC_A_xx(upd7810_state *cpustate);
+static void ADINC_A_xx(upd7810_state *cpustate);
+static void ADINC_B_xx(upd7810_state *cpustate);
+static void ADINC_C_xx(upd7810_state *cpustate);
+static void ADINC_D_xx(upd7810_state *cpustate);
+static void ADINC_EOM_xx(upd7810_state *cpustate);
+static void ADINC_E_xx(upd7810_state *cpustate);
+static void ADINC_H_xx(upd7810_state *cpustate);
+static void ADINC_L_xx(upd7810_state *cpustate);
+static void ADINC_MKH_xx(upd7810_state *cpustate);
+static void ADINC_MKL_xx(upd7810_state *cpustate);
+static void ADINC_PA_xx(upd7810_state *cpustate);
+static void ADINC_PB_xx(upd7810_state *cpustate);
+static void ADINC_PC_xx(upd7810_state *cpustate);
+static void ADINC_PD_xx(upd7810_state *cpustate);
+static void ADINC_PF_xx(upd7810_state *cpustate);
+static void ADINC_SMH_xx(upd7810_state *cpustate);
+static void ADINC_TMM_xx(upd7810_state *cpustate);
+static void ADINC_V_xx(upd7810_state *cpustate);
+static void ADI_ANM_xx(upd7810_state *cpustate);
+static void ADI_A_xx(upd7810_state *cpustate);
+static void ADI_A_xx(upd7810_state *cpustate);
+static void ADI_B_xx(upd7810_state *cpustate);
+static void ADI_C_xx(upd7810_state *cpustate);
+static void ADI_D_xx(upd7810_state *cpustate);
+static void ADI_EOM_xx(upd7810_state *cpustate);
+static void ADI_E_xx(upd7810_state *cpustate);
+static void ADI_H_xx(upd7810_state *cpustate);
+static void ADI_L_xx(upd7810_state *cpustate);
+static void ADI_MKH_xx(upd7810_state *cpustate);
+static void ADI_MKL_xx(upd7810_state *cpustate);
+static void ADI_PA_xx(upd7810_state *cpustate);
+static void ADI_PB_xx(upd7810_state *cpustate);
+static void ADI_PC_xx(upd7810_state *cpustate);
+static void ADI_PD_xx(upd7810_state *cpustate);
+static void ADI_PF_xx(upd7810_state *cpustate);
+static void ADI_SMH_xx(upd7810_state *cpustate);
+static void ADI_TMM_xx(upd7810_state *cpustate);
+static void ADI_V_xx(upd7810_state *cpustate);
+static void ANAW_wa(upd7810_state *cpustate);
+static void ANAX_B(upd7810_state *cpustate);
+static void ANAX_D(upd7810_state *cpustate);
+static void ANAX_Dm(upd7810_state *cpustate);
+static void ANAX_Dp(upd7810_state *cpustate);
+static void ANAX_H(upd7810_state *cpustate);
+static void ANAX_Hm(upd7810_state *cpustate);
+static void ANAX_Hp(upd7810_state *cpustate);
+static void ANA_A_A(upd7810_state *cpustate);
+static void ANA_A_A(upd7810_state *cpustate);
+static void ANA_A_B(upd7810_state *cpustate);
+static void ANA_A_C(upd7810_state *cpustate);
+static void ANA_A_D(upd7810_state *cpustate);
+static void ANA_A_E(upd7810_state *cpustate);
+static void ANA_A_H(upd7810_state *cpustate);
+static void ANA_A_L(upd7810_state *cpustate);
+static void ANA_A_V(upd7810_state *cpustate);
+static void ANA_B_A(upd7810_state *cpustate);
+static void ANA_C_A(upd7810_state *cpustate);
+static void ANA_D_A(upd7810_state *cpustate);
+static void ANA_E_A(upd7810_state *cpustate);
+static void ANA_H_A(upd7810_state *cpustate);
+static void ANA_L_A(upd7810_state *cpustate);
+static void ANA_V_A(upd7810_state *cpustate);
+static void ANIW_wa_xx(upd7810_state *cpustate);
+static void ANI_ANM_xx(upd7810_state *cpustate);
+static void ANI_A_xx(upd7810_state *cpustate);
+static void ANI_A_xx(upd7810_state *cpustate);
+static void ANI_B_xx(upd7810_state *cpustate);
+static void ANI_C_xx(upd7810_state *cpustate);
+static void ANI_D_xx(upd7810_state *cpustate);
+static void ANI_EOM_xx(upd7810_state *cpustate);
+static void ANI_E_xx(upd7810_state *cpustate);
+static void ANI_H_xx(upd7810_state *cpustate);
+static void ANI_L_xx(upd7810_state *cpustate);
+static void ANI_MKH_xx(upd7810_state *cpustate);
+static void ANI_MKL_xx(upd7810_state *cpustate);
+static void ANI_PA_xx(upd7810_state *cpustate);
+static void ANI_PB_xx(upd7810_state *cpustate);
+static void ANI_PC_xx(upd7810_state *cpustate);
+static void ANI_PD_xx(upd7810_state *cpustate);
+static void ANI_PF_xx(upd7810_state *cpustate);
+static void ANI_SMH_xx(upd7810_state *cpustate);
+static void ANI_TMM_xx(upd7810_state *cpustate);
+static void ANI_V_xx(upd7810_state *cpustate);
+static void BIT_0_wa(upd7810_state *cpustate);
+static void BIT_1_wa(upd7810_state *cpustate);
+static void BIT_2_wa(upd7810_state *cpustate);
+static void BIT_3_wa(upd7810_state *cpustate);
+static void BIT_4_wa(upd7810_state *cpustate);
+static void BIT_5_wa(upd7810_state *cpustate);
+static void BIT_6_wa(upd7810_state *cpustate);
+static void BIT_7_wa(upd7810_state *cpustate);
+static void BLOCK(upd7810_state *cpustate);
+static void CALB(upd7810_state *cpustate);
+static void CALF(upd7810_state *cpustate);
+static void CALL_w(upd7810_state *cpustate);
+static void CALT(upd7810_state *cpustate);
+static void CLC(upd7810_state *cpustate);
+static void CLR(upd7810_state *cpustate);
+static void DAA(upd7810_state *cpustate);
+static void DADC_EA_BC(upd7810_state *cpustate);
+static void DADC_EA_DE(upd7810_state *cpustate);
+static void DADC_EA_HL(upd7810_state *cpustate);
+static void DADDNC_EA_BC(upd7810_state *cpustate);
+static void DADDNC_EA_DE(upd7810_state *cpustate);
+static void DADDNC_EA_HL(upd7810_state *cpustate);
+static void DADD_EA_BC(upd7810_state *cpustate);
+static void DADD_EA_DE(upd7810_state *cpustate);
+static void DADD_EA_HL(upd7810_state *cpustate);
+static void DAN_EA_BC(upd7810_state *cpustate);
+static void DAN_EA_DE(upd7810_state *cpustate);
+static void DAN_EA_HL(upd7810_state *cpustate);
+static void DCRW_wa(upd7810_state *cpustate);
+static void DCR_A(upd7810_state *cpustate);
+static void DCR_B(upd7810_state *cpustate);
+static void DCR_C(upd7810_state *cpustate);
+static void DCX_BC(upd7810_state *cpustate);
+static void DCX_DE(upd7810_state *cpustate);
+static void DCX_EA(upd7810_state *cpustate);
+static void DCX_HL(upd7810_state *cpustate);
+static void DCX_SP(upd7810_state *cpustate);
+static void DEQ_EA_BC(upd7810_state *cpustate);
+static void DEQ_EA_DE(upd7810_state *cpustate);
+static void DEQ_EA_HL(upd7810_state *cpustate);
+static void DGT_EA_BC(upd7810_state *cpustate);
+static void DGT_EA_DE(upd7810_state *cpustate);
+static void DGT_EA_HL(upd7810_state *cpustate);
+static void DI(upd7810_state *cpustate);
+static void DIV_A(upd7810_state *cpustate);
+static void DIV_B(upd7810_state *cpustate);
+static void DIV_C(upd7810_state *cpustate);
+static void DLT_EA_BC(upd7810_state *cpustate);
+static void DLT_EA_DE(upd7810_state *cpustate);
+static void DLT_EA_HL(upd7810_state *cpustate);
+static void DMOV_BC_EA(upd7810_state *cpustate);
+static void DMOV_DE_EA(upd7810_state *cpustate);
+static void DMOV_EA_BC(upd7810_state *cpustate);
+static void DMOV_EA_DE(upd7810_state *cpustate);
+static void DMOV_EA_ECNT(upd7810_state *cpustate);
+static void DMOV_EA_ECPT(upd7810_state *cpustate);
+static void DMOV_EA_HL(upd7810_state *cpustate);
+static void DMOV_ETM0_EA(upd7810_state *cpustate);
+static void DMOV_ETM1_EA(upd7810_state *cpustate);
+static void DMOV_HL_EA(upd7810_state *cpustate);
+static void DNE_EA_BC(upd7810_state *cpustate);
+static void DNE_EA_DE(upd7810_state *cpustate);
+static void DNE_EA_HL(upd7810_state *cpustate);
+static void DOFF_EA_BC(upd7810_state *cpustate);
+static void DOFF_EA_DE(upd7810_state *cpustate);
+static void DOFF_EA_HL(upd7810_state *cpustate);
+static void DON_EA_BC(upd7810_state *cpustate);
+static void DON_EA_DE(upd7810_state *cpustate);
+static void DON_EA_HL(upd7810_state *cpustate);
+static void DOR_EA_BC(upd7810_state *cpustate);
+static void DOR_EA_DE(upd7810_state *cpustate);
+static void DOR_EA_HL(upd7810_state *cpustate);
+static void DRLL_EA(upd7810_state *cpustate);
+static void DRLR_EA(upd7810_state *cpustate);
+static void DSBB_EA_BC(upd7810_state *cpustate);
+static void DSBB_EA_DE(upd7810_state *cpustate);
+static void DSBB_EA_HL(upd7810_state *cpustate);
+static void DSLL_EA(upd7810_state *cpustate);
+static void DSLR_EA(upd7810_state *cpustate);
+static void DSUBNB_EA_BC(upd7810_state *cpustate);
+static void DSUBNB_EA_DE(upd7810_state *cpustate);
+static void DSUBNB_EA_HL(upd7810_state *cpustate);
+static void DSUB_EA_BC(upd7810_state *cpustate);
+static void DSUB_EA_DE(upd7810_state *cpustate);
+static void DSUB_EA_HL(upd7810_state *cpustate);
+static void DXR_EA_BC(upd7810_state *cpustate);
+static void DXR_EA_DE(upd7810_state *cpustate);
+static void DXR_EA_HL(upd7810_state *cpustate);
+static void EADD_EA_A(upd7810_state *cpustate);
+static void EADD_EA_B(upd7810_state *cpustate);
+static void EADD_EA_C(upd7810_state *cpustate);
+static void EI(upd7810_state *cpustate);
+static void EQAW_wa(upd7810_state *cpustate);
+static void EQAX_B(upd7810_state *cpustate);
+static void EQAX_D(upd7810_state *cpustate);
+static void EQAX_Dm(upd7810_state *cpustate);
+static void EQAX_Dp(upd7810_state *cpustate);
+static void EQAX_H(upd7810_state *cpustate);
+static void EQAX_Hm(upd7810_state *cpustate);
+static void EQAX_Hp(upd7810_state *cpustate);
+static void EQA_A_A(upd7810_state *cpustate);
+static void EQA_A_A(upd7810_state *cpustate);
+static void EQA_A_B(upd7810_state *cpustate);
+static void EQA_A_C(upd7810_state *cpustate);
+static void EQA_A_D(upd7810_state *cpustate);
+static void EQA_A_E(upd7810_state *cpustate);
+static void EQA_A_H(upd7810_state *cpustate);
+static void EQA_A_L(upd7810_state *cpustate);
+static void EQA_A_V(upd7810_state *cpustate);
+static void EQA_B_A(upd7810_state *cpustate);
+static void EQA_C_A(upd7810_state *cpustate);
+static void EQA_D_A(upd7810_state *cpustate);
+static void EQA_E_A(upd7810_state *cpustate);
+static void EQA_H_A(upd7810_state *cpustate);
+static void EQA_L_A(upd7810_state *cpustate);
+static void EQA_V_A(upd7810_state *cpustate);
+static void EQIW_wa_xx(upd7810_state *cpustate);
+static void EQI_ANM_xx(upd7810_state *cpustate);
+static void EQI_A_xx(upd7810_state *cpustate);
+static void EQI_A_xx(upd7810_state *cpustate);
+static void EQI_B_xx(upd7810_state *cpustate);
+static void EQI_C_xx(upd7810_state *cpustate);
+static void EQI_D_xx(upd7810_state *cpustate);
+static void EQI_EOM_xx(upd7810_state *cpustate);
+static void EQI_E_xx(upd7810_state *cpustate);
+static void EQI_H_xx(upd7810_state *cpustate);
+static void EQI_L_xx(upd7810_state *cpustate);
+static void EQI_MKH_xx(upd7810_state *cpustate);
+static void EQI_MKL_xx(upd7810_state *cpustate);
+static void EQI_PA_xx(upd7810_state *cpustate);
+static void EQI_PB_xx(upd7810_state *cpustate);
+static void EQI_PC_xx(upd7810_state *cpustate);
+static void EQI_PD_xx(upd7810_state *cpustate);
+static void EQI_PF_xx(upd7810_state *cpustate);
+static void EQI_SMH_xx(upd7810_state *cpustate);
+static void EQI_TMM_xx(upd7810_state *cpustate);
+static void EQI_V_xx(upd7810_state *cpustate);
+static void ESUB_EA_A(upd7810_state *cpustate);
+static void ESUB_EA_B(upd7810_state *cpustate);
+static void ESUB_EA_C(upd7810_state *cpustate);
+static void EXA(upd7810_state *cpustate);
+static void EXH(upd7810_state *cpustate);
+static void EXX(upd7810_state *cpustate);
+static void EXR(upd7810_state *cpustate);
+static void GTAW_wa(upd7810_state *cpustate);
+static void GTAX_B(upd7810_state *cpustate);
+static void GTAX_D(upd7810_state *cpustate);
+static void GTAX_Dm(upd7810_state *cpustate);
+static void GTAX_Dp(upd7810_state *cpustate);
+static void GTAX_H(upd7810_state *cpustate);
+static void GTAX_Hm(upd7810_state *cpustate);
+static void GTAX_Hp(upd7810_state *cpustate);
+static void GTA_A_A(upd7810_state *cpustate);
+static void GTA_A_A(upd7810_state *cpustate);
+static void GTA_A_B(upd7810_state *cpustate);
+static void GTA_A_C(upd7810_state *cpustate);
+static void GTA_A_D(upd7810_state *cpustate);
+static void GTA_A_E(upd7810_state *cpustate);
+static void GTA_A_H(upd7810_state *cpustate);
+static void GTA_A_L(upd7810_state *cpustate);
+static void GTA_A_V(upd7810_state *cpustate);
+static void GTA_B_A(upd7810_state *cpustate);
+static void GTA_C_A(upd7810_state *cpustate);
+static void GTA_D_A(upd7810_state *cpustate);
+static void GTA_E_A(upd7810_state *cpustate);
+static void GTA_H_A(upd7810_state *cpustate);
+static void GTA_L_A(upd7810_state *cpustate);
+static void GTA_V_A(upd7810_state *cpustate);
+static void GTIW_wa_xx(upd7810_state *cpustate);
+static void GTI_ANM_xx(upd7810_state *cpustate);
+static void GTI_A_xx(upd7810_state *cpustate);
+static void GTI_A_xx(upd7810_state *cpustate);
+static void GTI_B_xx(upd7810_state *cpustate);
+static void GTI_C_xx(upd7810_state *cpustate);
+static void GTI_D_xx(upd7810_state *cpustate);
+static void GTI_EOM_xx(upd7810_state *cpustate);
+static void GTI_E_xx(upd7810_state *cpustate);
+static void GTI_H_xx(upd7810_state *cpustate);
+static void GTI_L_xx(upd7810_state *cpustate);
+static void GTI_MKH_xx(upd7810_state *cpustate);
+static void GTI_MKL_xx(upd7810_state *cpustate);
+static void GTI_PA_xx(upd7810_state *cpustate);
+static void GTI_PB_xx(upd7810_state *cpustate);
+static void GTI_PC_xx(upd7810_state *cpustate);
+static void GTI_PD_xx(upd7810_state *cpustate);
+static void GTI_PF_xx(upd7810_state *cpustate);
+static void GTI_SMH_xx(upd7810_state *cpustate);
+static void GTI_TMM_xx(upd7810_state *cpustate);
+static void GTI_V_xx(upd7810_state *cpustate);
+static void HALT(upd7810_state *cpustate);
+static void IN(upd7810_state *cpustate);
+static void INRW_wa(upd7810_state *cpustate);
+static void INR_A(upd7810_state *cpustate);
+static void INR_B(upd7810_state *cpustate);
+static void INR_C(upd7810_state *cpustate);
+static void INX_BC(upd7810_state *cpustate);
+static void INX_DE(upd7810_state *cpustate);
+static void INX_EA(upd7810_state *cpustate);
+static void INX_HL(upd7810_state *cpustate);
+static void INX_SP(upd7810_state *cpustate);
+static void JB(upd7810_state *cpustate);
+static void JEA(upd7810_state *cpustate);
+static void JMP_w(upd7810_state *cpustate);
+static void JR(upd7810_state *cpustate);
+static void JRE(upd7810_state *cpustate);
+static void LBCD_w(upd7810_state *cpustate);
+static void LDAW_wa(upd7810_state *cpustate);
+static void LDAX_B(upd7810_state *cpustate);
+static void LDAX_D(upd7810_state *cpustate);
+static void LDAX_D_xx(upd7810_state *cpustate);
+static void LDAX_Dm(upd7810_state *cpustate);
+static void LDAX_Dp(upd7810_state *cpustate);
+static void LDAX_H(upd7810_state *cpustate);
+static void LDAX_H_A(upd7810_state *cpustate);
+static void LDAX_H_B(upd7810_state *cpustate);
+static void LDAX_H_EA(upd7810_state *cpustate);
+static void LDAX_H_xx(upd7810_state *cpustate);
+static void LDAX_Hm(upd7810_state *cpustate);
+static void LDAX_Hp(upd7810_state *cpustate);
+static void LDEAX_D(upd7810_state *cpustate);
+static void LDEAX_D_xx(upd7810_state *cpustate);
+static void LDEAX_Dp(upd7810_state *cpustate);
+static void LDEAX_H(upd7810_state *cpustate);
+static void LDEAX_H_A(upd7810_state *cpustate);
+static void LDEAX_H_B(upd7810_state *cpustate);
+static void LDEAX_H_EA(upd7810_state *cpustate);
+static void LDEAX_H_xx(upd7810_state *cpustate);
+static void LDEAX_Hp(upd7810_state *cpustate);
+static void LDED_w(upd7810_state *cpustate);
+static void LHLD_w(upd7810_state *cpustate);
+static void LSPD_w(upd7810_state *cpustate);
+static void LTAW_wa(upd7810_state *cpustate);
+static void LTAX_B(upd7810_state *cpustate);
+static void LTAX_D(upd7810_state *cpustate);
+static void LTAX_Dm(upd7810_state *cpustate);
+static void LTAX_Dp(upd7810_state *cpustate);
+static void LTAX_H(upd7810_state *cpustate);
+static void LTAX_Hm(upd7810_state *cpustate);
+static void LTAX_Hp(upd7810_state *cpustate);
+static void LTA_A_A(upd7810_state *cpustate);
+static void LTA_A_A(upd7810_state *cpustate);
+static void LTA_A_B(upd7810_state *cpustate);
+static void LTA_A_C(upd7810_state *cpustate);
+static void LTA_A_D(upd7810_state *cpustate);
+static void LTA_A_E(upd7810_state *cpustate);
+static void LTA_A_H(upd7810_state *cpustate);
+static void LTA_A_L(upd7810_state *cpustate);
+static void LTA_A_V(upd7810_state *cpustate);
+static void LTA_B_A(upd7810_state *cpustate);
+static void LTA_C_A(upd7810_state *cpustate);
+static void LTA_D_A(upd7810_state *cpustate);
+static void LTA_E_A(upd7810_state *cpustate);
+static void LTA_H_A(upd7810_state *cpustate);
+static void LTA_L_A(upd7810_state *cpustate);
+static void LTA_V_A(upd7810_state *cpustate);
+static void LTIW_wa_xx(upd7810_state *cpustate);
+static void LTI_ANM_xx(upd7810_state *cpustate);
+static void LTI_A_xx(upd7810_state *cpustate);
+static void LTI_A_xx(upd7810_state *cpustate);
+static void LTI_B_xx(upd7810_state *cpustate);
+static void LTI_C_xx(upd7810_state *cpustate);
+static void LTI_D_xx(upd7810_state *cpustate);
+static void LTI_EOM_xx(upd7810_state *cpustate);
+static void LTI_E_xx(upd7810_state *cpustate);
+static void LTI_H_xx(upd7810_state *cpustate);
+static void LTI_L_xx(upd7810_state *cpustate);
+static void LTI_MKH_xx(upd7810_state *cpustate);
+static void LTI_MKL_xx(upd7810_state *cpustate);
+static void LTI_PA_xx(upd7810_state *cpustate);
+static void LTI_PB_xx(upd7810_state *cpustate);
+static void LTI_PC_xx(upd7810_state *cpustate);
+static void LTI_PD_xx(upd7810_state *cpustate);
+static void LTI_PF_xx(upd7810_state *cpustate);
+static void LTI_SMH_xx(upd7810_state *cpustate);
+static void LTI_TMM_xx(upd7810_state *cpustate);
+static void LTI_V_xx(upd7810_state *cpustate);
+static void LXI_B_w(upd7810_state *cpustate);
+static void LXI_D_w(upd7810_state *cpustate);
+static void LXI_EA_s(upd7810_state *cpustate);
+static void LXI_H_w(upd7810_state *cpustate);
+static void LXI_S_w(upd7810_state *cpustate);
+static void MOV_ANM_A(upd7810_state *cpustate);
+static void MOV_A_ANM(upd7810_state *cpustate);
+static void MOV_A_B(upd7810_state *cpustate);
+static void MOV_A_C(upd7810_state *cpustate);
+static void MOV_A_CR0(upd7810_state *cpustate);
+static void MOV_A_CR1(upd7810_state *cpustate);
+static void MOV_A_CR2(upd7810_state *cpustate);
+static void MOV_A_CR3(upd7810_state *cpustate);
+static void MOV_A_D(upd7810_state *cpustate);
+static void MOV_A_E(upd7810_state *cpustate);
+static void MOV_A_EAH(upd7810_state *cpustate);
+static void MOV_A_EAL(upd7810_state *cpustate);
+static void MOV_A_EOM(upd7810_state *cpustate);
+static void MOV_A_H(upd7810_state *cpustate);
+static void MOV_A_L(upd7810_state *cpustate);
+static void MOV_A_MKH(upd7810_state *cpustate);
+static void MOV_A_MKL(upd7810_state *cpustate);
+static void MOV_A_PA(upd7810_state *cpustate);
+static void MOV_A_PB(upd7810_state *cpustate);
+static void MOV_A_PC(upd7810_state *cpustate);
+static void MOV_A_PD(upd7810_state *cpustate);
+static void MOV_A_PF(upd7810_state *cpustate);
+static void MOV_A_RXB(upd7810_state *cpustate);
+static void MOV_A_S(upd7810_state *cpustate);
+static void MOV_A_SMH(upd7810_state *cpustate);
+static void MOV_A_TMM(upd7810_state *cpustate);
+static void MOV_A_PT(upd7810_state *cpustate);
+static void MOV_A_w(upd7810_state *cpustate);
+static void MOV_B_A(upd7810_state *cpustate);
+static void MOV_B_w(upd7810_state *cpustate);
+static void MOV_C_A(upd7810_state *cpustate);
+static void MOV_C_w(upd7810_state *cpustate);
+static void MOV_D_A(upd7810_state *cpustate);
+static void MOV_D_w(upd7810_state *cpustate);
+static void MOV_EAH_A(upd7810_state *cpustate);
+static void MOV_EAL_A(upd7810_state *cpustate);
+static void MOV_EOM_A(upd7810_state *cpustate);
+static void MOV_ETMM_A(upd7810_state *cpustate);
+static void MOV_E_A(upd7810_state *cpustate);
+static void MOV_E_w(upd7810_state *cpustate);
+static void MOV_H_A(upd7810_state *cpustate);
+static void MOV_H_w(upd7810_state *cpustate);
+static void MOV_L_A(upd7810_state *cpustate);
+static void MOV_L_w(upd7810_state *cpustate);
+static void MOV_MA_A(upd7810_state *cpustate);
+static void MOV_MB_A(upd7810_state *cpustate);
+static void MOV_MCC_A(upd7810_state *cpustate);
+static void MOV_MC_A(upd7810_state *cpustate);
+static void MOV_MF_A(upd7810_state *cpustate);
+static void MOV_MKH_A(upd7810_state *cpustate);
+static void MOV_MKL_A(upd7810_state *cpustate);
+static void MOV_MM_A(upd7810_state *cpustate);
+static void MOV_PA_A(upd7810_state *cpustate);
+static void MOV_PB_A(upd7810_state *cpustate);
+static void MOV_PC_A(upd7810_state *cpustate);
+static void MOV_PD_A(upd7810_state *cpustate);
+static void MOV_PF_A(upd7810_state *cpustate);
+static void MOV_S_A(upd7810_state *cpustate);
+static void MOV_SMH_A(upd7810_state *cpustate);
+static void MOV_SML_A(upd7810_state *cpustate);
+static void MOV_TM0_A(upd7810_state *cpustate);
+static void MOV_TM1_A(upd7810_state *cpustate);
+static void MOV_TMM_A(upd7810_state *cpustate);
+static void MOV_TXB_A(upd7810_state *cpustate);
+static void MOV_V_w(upd7810_state *cpustate);
+static void MOV_ZCM_A(upd7810_state *cpustate);
+static void MOV_w_A(upd7810_state *cpustate);
+static void MOV_w_B(upd7810_state *cpustate);
+static void MOV_w_C(upd7810_state *cpustate);
+static void MOV_w_D(upd7810_state *cpustate);
+static void MOV_w_E(upd7810_state *cpustate);
+static void MOV_w_H(upd7810_state *cpustate);
+static void MOV_w_L(upd7810_state *cpustate);
+static void MOV_w_V(upd7810_state *cpustate);
+static void MUL_A(upd7810_state *cpustate);
+static void MUL_B(upd7810_state *cpustate);
+static void MUL_C(upd7810_state *cpustate);
+static void MVIW_wa_xx(upd7810_state *cpustate);
+static void MVIX_BC_xx(upd7810_state *cpustate);
+static void MVIX_DE_xx(upd7810_state *cpustate);
+static void MVIX_HL_xx(upd7810_state *cpustate);
+static void MVI_ANM_xx(upd7810_state *cpustate);
+static void MVI_A_xx(upd7810_state *cpustate);
+static void MVI_B_xx(upd7810_state *cpustate);
+static void MVI_C_xx(upd7810_state *cpustate);
+static void MVI_D_xx(upd7810_state *cpustate);
+static void MVI_EOM_xx(upd7810_state *cpustate);
+static void MVI_E_xx(upd7810_state *cpustate);
+static void MVI_H_xx(upd7810_state *cpustate);
+static void MVI_L_xx(upd7810_state *cpustate);
+static void MVI_MKH_xx(upd7810_state *cpustate);
+static void MVI_MKL_xx(upd7810_state *cpustate);
+static void MVI_PA_xx(upd7810_state *cpustate);
+static void MVI_PB_xx(upd7810_state *cpustate);
+static void MVI_PC_xx(upd7810_state *cpustate);
+static void MVI_PD_xx(upd7810_state *cpustate);
+static void MVI_PF_xx(upd7810_state *cpustate);
+static void MVI_SMH_xx(upd7810_state *cpustate);
+static void MVI_TMM_xx(upd7810_state *cpustate);
+static void MVI_V_xx(upd7810_state *cpustate);
+static void NEAW_wa(upd7810_state *cpustate);
+static void NEAX_B(upd7810_state *cpustate);
+static void NEAX_D(upd7810_state *cpustate);
+static void NEAX_Dm(upd7810_state *cpustate);
+static void NEAX_Dp(upd7810_state *cpustate);
+static void NEAX_H(upd7810_state *cpustate);
+static void NEAX_Hm(upd7810_state *cpustate);
+static void NEAX_Hp(upd7810_state *cpustate);
+static void NEA_A_A(upd7810_state *cpustate);
+static void NEA_A_A(upd7810_state *cpustate);
+static void NEA_A_B(upd7810_state *cpustate);
+static void NEA_A_C(upd7810_state *cpustate);
+static void NEA_A_D(upd7810_state *cpustate);
+static void NEA_A_E(upd7810_state *cpustate);
+static void NEA_A_H(upd7810_state *cpustate);
+static void NEA_A_L(upd7810_state *cpustate);
+static void NEA_A_V(upd7810_state *cpustate);
+static void NEA_B_A(upd7810_state *cpustate);
+static void NEA_C_A(upd7810_state *cpustate);
+static void NEA_D_A(upd7810_state *cpustate);
+static void NEA_E_A(upd7810_state *cpustate);
+static void NEA_H_A(upd7810_state *cpustate);
+static void NEA_L_A(upd7810_state *cpustate);
+static void NEA_V_A(upd7810_state *cpustate);
+static void NEGA(upd7810_state *cpustate);
+static void NEIW_wa_xx(upd7810_state *cpustate);
+static void NEI_ANM_xx(upd7810_state *cpustate);
+static void NEI_A_xx(upd7810_state *cpustate);
+static void NEI_A_xx(upd7810_state *cpustate);
+static void NEI_B_xx(upd7810_state *cpustate);
+static void NEI_C_xx(upd7810_state *cpustate);
+static void NEI_D_xx(upd7810_state *cpustate);
+static void NEI_EOM_xx(upd7810_state *cpustate);
+static void NEI_E_xx(upd7810_state *cpustate);
+static void NEI_H_xx(upd7810_state *cpustate);
+static void NEI_L_xx(upd7810_state *cpustate);
+static void NEI_MKH_xx(upd7810_state *cpustate);
+static void NEI_MKL_xx(upd7810_state *cpustate);
+static void NEI_PA_xx(upd7810_state *cpustate);
+static void NEI_PB_xx(upd7810_state *cpustate);
+static void NEI_PC_xx(upd7810_state *cpustate);
+static void NEI_PD_xx(upd7810_state *cpustate);
+static void NEI_PF_xx(upd7810_state *cpustate);
+static void NEI_SMH_xx(upd7810_state *cpustate);
+static void NEI_TMM_xx(upd7810_state *cpustate);
+static void NEI_V_xx(upd7810_state *cpustate);
+static void NOP(upd7810_state *cpustate);
+static void OFFAW_wa(upd7810_state *cpustate);
+static void OFFAX_B(upd7810_state *cpustate);
+static void OFFAX_D(upd7810_state *cpustate);
+static void OFFAX_Dm(upd7810_state *cpustate);
+static void OFFAX_Dp(upd7810_state *cpustate);
+static void OFFAX_H(upd7810_state *cpustate);
+static void OFFAX_Hm(upd7810_state *cpustate);
+static void OFFAX_Hp(upd7810_state *cpustate);
+static void OFFA_A_A(upd7810_state *cpustate);
+static void OFFA_A_B(upd7810_state *cpustate);
+static void OFFA_A_C(upd7810_state *cpustate);
+static void OFFA_A_D(upd7810_state *cpustate);
+static void OFFA_A_E(upd7810_state *cpustate);
+static void OFFA_A_H(upd7810_state *cpustate);
+static void OFFA_A_L(upd7810_state *cpustate);
+static void OFFA_A_V(upd7810_state *cpustate);
+static void OFFIW_wa_xx(upd7810_state *cpustate);
+static void OFFI_ANM_xx(upd7810_state *cpustate);
+static void OFFI_A_xx(upd7810_state *cpustate);
+static void OFFI_A_xx(upd7810_state *cpustate);
+static void OFFI_B_xx(upd7810_state *cpustate);
+static void OFFI_C_xx(upd7810_state *cpustate);
+static void OFFI_D_xx(upd7810_state *cpustate);
+static void OFFI_EOM_xx(upd7810_state *cpustate);
+static void OFFI_E_xx(upd7810_state *cpustate);
+static void OFFI_H_xx(upd7810_state *cpustate);
+static void OFFI_L_xx(upd7810_state *cpustate);
+static void OFFI_MKH_xx(upd7810_state *cpustate);
+static void OFFI_MKL_xx(upd7810_state *cpustate);
+static void OFFI_PA_xx(upd7810_state *cpustate);
+static void OFFI_PB_xx(upd7810_state *cpustate);
+static void OFFI_PC_xx(upd7810_state *cpustate);
+static void OFFI_PD_xx(upd7810_state *cpustate);
+static void OFFI_PF_xx(upd7810_state *cpustate);
+static void OFFI_SMH_xx(upd7810_state *cpustate);
+static void OFFI_TMM_xx(upd7810_state *cpustate);
+static void OFFI_V_xx(upd7810_state *cpustate);
+static void ONAW_wa(upd7810_state *cpustate);
+static void ONAX_B(upd7810_state *cpustate);
+static void ONAX_D(upd7810_state *cpustate);
+static void ONAX_Dm(upd7810_state *cpustate);
+static void ONAX_Dp(upd7810_state *cpustate);
+static void ONAX_H(upd7810_state *cpustate);
+static void ONAX_Hm(upd7810_state *cpustate);
+static void ONAX_Hp(upd7810_state *cpustate);
+static void ONA_A_A(upd7810_state *cpustate);
+static void ONA_A_B(upd7810_state *cpustate);
+static void ONA_A_C(upd7810_state *cpustate);
+static void ONA_A_D(upd7810_state *cpustate);
+static void ONA_A_E(upd7810_state *cpustate);
+static void ONA_A_H(upd7810_state *cpustate);
+static void ONA_A_L(upd7810_state *cpustate);
+static void ONA_A_V(upd7810_state *cpustate);
+static void ONIW_wa_xx(upd7810_state *cpustate);
+static void ONI_ANM_xx(upd7810_state *cpustate);
+static void ONI_A_xx(upd7810_state *cpustate);
+static void ONI_A_xx(upd7810_state *cpustate);
+static void ONI_B_xx(upd7810_state *cpustate);
+static void ONI_C_xx(upd7810_state *cpustate);
+static void ONI_D_xx(upd7810_state *cpustate);
+static void ONI_EOM_xx(upd7810_state *cpustate);
+static void ONI_E_xx(upd7810_state *cpustate);
+static void ONI_H_xx(upd7810_state *cpustate);
+static void ONI_L_xx(upd7810_state *cpustate);
+static void ONI_MKH_xx(upd7810_state *cpustate);
+static void ONI_MKL_xx(upd7810_state *cpustate);
+static void ONI_PA_xx(upd7810_state *cpustate);
+static void ONI_PB_xx(upd7810_state *cpustate);
+static void ONI_PC_xx(upd7810_state *cpustate);
+static void ONI_PD_xx(upd7810_state *cpustate);
+static void ONI_PF_xx(upd7810_state *cpustate);
+static void ONI_SMH_xx(upd7810_state *cpustate);
+static void ONI_TMM_xx(upd7810_state *cpustate);
+static void ONI_V_xx(upd7810_state *cpustate);
+static void ORAW_wa(upd7810_state *cpustate);
+static void ORAX_B(upd7810_state *cpustate);
+static void ORAX_D(upd7810_state *cpustate);
+static void ORAX_Dm(upd7810_state *cpustate);
+static void ORAX_Dp(upd7810_state *cpustate);
+static void ORAX_H(upd7810_state *cpustate);
+static void ORAX_Hm(upd7810_state *cpustate);
+static void ORAX_Hp(upd7810_state *cpustate);
+static void ORA_A_A(upd7810_state *cpustate);
+static void ORA_A_A(upd7810_state *cpustate);
+static void ORA_A_B(upd7810_state *cpustate);
+static void ORA_A_C(upd7810_state *cpustate);
+static void ORA_A_D(upd7810_state *cpustate);
+static void ORA_A_E(upd7810_state *cpustate);
+static void ORA_A_H(upd7810_state *cpustate);
+static void ORA_A_L(upd7810_state *cpustate);
+static void ORA_A_V(upd7810_state *cpustate);
+static void ORA_B_A(upd7810_state *cpustate);
+static void ORA_C_A(upd7810_state *cpustate);
+static void ORA_D_A(upd7810_state *cpustate);
+static void ORA_E_A(upd7810_state *cpustate);
+static void ORA_H_A(upd7810_state *cpustate);
+static void ORA_L_A(upd7810_state *cpustate);
+static void ORA_V_A(upd7810_state *cpustate);
+static void ORIW_wa_xx(upd7810_state *cpustate);
+static void ORI_ANM_xx(upd7810_state *cpustate);
+static void ORI_A_xx(upd7810_state *cpustate);
+static void ORI_A_xx(upd7810_state *cpustate);
+static void ORI_B_xx(upd7810_state *cpustate);
+static void ORI_C_xx(upd7810_state *cpustate);
+static void ORI_D_xx(upd7810_state *cpustate);
+static void ORI_EOM_xx(upd7810_state *cpustate);
+static void ORI_E_xx(upd7810_state *cpustate);
+static void ORI_H_xx(upd7810_state *cpustate);
+static void ORI_L_xx(upd7810_state *cpustate);
+static void ORI_MKH_xx(upd7810_state *cpustate);
+static void ORI_MKL_xx(upd7810_state *cpustate);
+static void ORI_PA_xx(upd7810_state *cpustate);
+static void ORI_PB_xx(upd7810_state *cpustate);
+static void ORI_PC_xx(upd7810_state *cpustate);
+static void ORI_PD_xx(upd7810_state *cpustate);
+static void ORI_PF_xx(upd7810_state *cpustate);
+static void ORI_SMH_xx(upd7810_state *cpustate);
+static void ORI_TMM_xx(upd7810_state *cpustate);
+static void ORI_V_xx(upd7810_state *cpustate);
+static void OUT(upd7810_state *cpustate);
+static void PEN(upd7810_state *cpustate);
+static void PER(upd7810_state *cpustate);
+static void PEX(upd7810_state *cpustate);
+static void POP_BC(upd7810_state *cpustate);
+static void POP_DE(upd7810_state *cpustate);
+static void POP_EA(upd7810_state *cpustate);
+static void POP_HL(upd7810_state *cpustate);
+static void POP_VA(upd7810_state *cpustate);
+static void PRE_48(upd7810_state *cpustate);
+static void PRE_4C(upd7810_state *cpustate);
+static void PRE_4D(upd7810_state *cpustate);
+static void PRE_60(upd7810_state *cpustate);
+static void PRE_64(upd7810_state *cpustate);
+static void PRE_70(upd7810_state *cpustate);
+static void PRE_74(upd7810_state *cpustate);
+static void PUSH_BC(upd7810_state *cpustate);
+static void PUSH_DE(upd7810_state *cpustate);
+static void PUSH_EA(upd7810_state *cpustate);
+static void PUSH_HL(upd7810_state *cpustate);
+static void PUSH_VA(upd7810_state *cpustate);
+static void RET(upd7810_state *cpustate);
+static void RETI(upd7810_state *cpustate);
+static void RETS(upd7810_state *cpustate);
+static void RLD(upd7810_state *cpustate);
+static void RLL_A(upd7810_state *cpustate);
+static void RLL_B(upd7810_state *cpustate);
+static void RLL_C(upd7810_state *cpustate);
+static void RLR_A(upd7810_state *cpustate);
+static void RLR_B(upd7810_state *cpustate);
+static void RLR_C(upd7810_state *cpustate);
+static void RRD(upd7810_state *cpustate);
+static void SBBW_wa(upd7810_state *cpustate);
+static void SBBX_B(upd7810_state *cpustate);
+static void SBBX_D(upd7810_state *cpustate);
+static void SBBX_Dm(upd7810_state *cpustate);
+static void SBBX_Dp(upd7810_state *cpustate);
+static void SBBX_H(upd7810_state *cpustate);
+static void SBBX_Hm(upd7810_state *cpustate);
+static void SBBX_Hp(upd7810_state *cpustate);
+static void SBB_A_A(upd7810_state *cpustate);
+static void SBB_A_A(upd7810_state *cpustate);
+static void SBB_A_B(upd7810_state *cpustate);
+static void SBB_A_C(upd7810_state *cpustate);
+static void SBB_A_D(upd7810_state *cpustate);
+static void SBB_A_E(upd7810_state *cpustate);
+static void SBB_A_H(upd7810_state *cpustate);
+static void SBB_A_L(upd7810_state *cpustate);
+static void SBB_A_V(upd7810_state *cpustate);
+static void SBB_B_A(upd7810_state *cpustate);
+static void SBB_C_A(upd7810_state *cpustate);
+static void SBB_D_A(upd7810_state *cpustate);
+static void SBB_E_A(upd7810_state *cpustate);
+static void SBB_H_A(upd7810_state *cpustate);
+static void SBB_L_A(upd7810_state *cpustate);
+static void SBB_V_A(upd7810_state *cpustate);
+static void SBCD_w(upd7810_state *cpustate);
+static void SBI_ANM_xx(upd7810_state *cpustate);
+static void SBI_A_xx(upd7810_state *cpustate);
+static void SBI_A_xx(upd7810_state *cpustate);
+static void SBI_B_xx(upd7810_state *cpustate);
+static void SBI_C_xx(upd7810_state *cpustate);
+static void SBI_D_xx(upd7810_state *cpustate);
+static void SBI_EOM_xx(upd7810_state *cpustate);
+static void SBI_E_xx(upd7810_state *cpustate);
+static void SBI_H_xx(upd7810_state *cpustate);
+static void SBI_L_xx(upd7810_state *cpustate);
+static void SBI_MKH_xx(upd7810_state *cpustate);
+static void SBI_MKL_xx(upd7810_state *cpustate);
+static void SBI_PA_xx(upd7810_state *cpustate);
+static void SBI_PB_xx(upd7810_state *cpustate);
+static void SBI_PC_xx(upd7810_state *cpustate);
+static void SBI_PD_xx(upd7810_state *cpustate);
+static void SBI_PF_xx(upd7810_state *cpustate);
+static void SBI_SMH_xx(upd7810_state *cpustate);
+static void SBI_TMM_xx(upd7810_state *cpustate);
+static void SBI_V_xx(upd7810_state *cpustate);
+static void SDED_w(upd7810_state *cpustate);
+static void SETB(upd7810_state *cpustate);
+static void SHLD_w(upd7810_state *cpustate);
+static void SIO(upd7810_state *cpustate);
+static void SK_bit(upd7810_state *cpustate);
+static void SKN_bit(upd7810_state *cpustate);
+static void SKIT_AN4(upd7810_state *cpustate);
+static void SKIT_AN5(upd7810_state *cpustate);
+static void SKIT_AN6(upd7810_state *cpustate);
+static void SKIT_AN7(upd7810_state *cpustate);
+static void SKIT_ER(upd7810_state *cpustate);
+static void SKIT_F0(upd7810_state *cpustate);
+static void SKIT_F1(upd7810_state *cpustate);
+static void SKIT_F2(upd7810_state *cpustate);
+static void SKIT_FAD(upd7810_state *cpustate);
+static void SKIT_FE0(upd7810_state *cpustate);
+static void SKIT_FE1(upd7810_state *cpustate);
+static void SKIT_FEIN(upd7810_state *cpustate);
+static void SKIT_FSR(upd7810_state *cpustate);
+static void SKIT_FST(upd7810_state *cpustate);
+static void SKIT_FT0(upd7810_state *cpustate);
+static void SKIT_FT1(upd7810_state *cpustate);
+static void SKIT_NMI(upd7810_state *cpustate);
+static void SKIT_OV(upd7810_state *cpustate);
+static void SKIT_SB(upd7810_state *cpustate);
+static void SKNIT_AN4(upd7810_state *cpustate);
+static void SKNIT_AN5(upd7810_state *cpustate);
+static void SKNIT_AN6(upd7810_state *cpustate);
+static void SKNIT_AN7(upd7810_state *cpustate);
+static void SKNIT_ER(upd7810_state *cpustate);
+static void SKNIT_F0(upd7810_state *cpustate);
+static void SKNIT_F1(upd7810_state *cpustate);
+static void SKNIT_F2(upd7810_state *cpustate);
+static void SKNIT_FAD(upd7810_state *cpustate);
+static void SKNIT_FE0(upd7810_state *cpustate);
+static void SKNIT_FE1(upd7810_state *cpustate);
+static void SKNIT_FEIN(upd7810_state *cpustate);
+static void SKNIT_FSR(upd7810_state *cpustate);
+static void SKNIT_FST(upd7810_state *cpustate);
+static void SKNIT_FT0(upd7810_state *cpustate);
+static void SKNIT_FT1(upd7810_state *cpustate);
+static void SKNIT_NMI(upd7810_state *cpustate);
+static void SKNIT_OV(upd7810_state *cpustate);
+static void SKNIT_SB(upd7810_state *cpustate);
+static void SKN_CY(upd7810_state *cpustate);
+static void SKN_HC(upd7810_state *cpustate);
+static void SKN_NV(upd7810_state *cpustate);
+static void SKN_Z(upd7810_state *cpustate);
+static void SK_CY(upd7810_state *cpustate);
+static void SK_HC(upd7810_state *cpustate);
+static void SK_NV(upd7810_state *cpustate);
+static void SK_Z(upd7810_state *cpustate);
+static void SLLC_A(upd7810_state *cpustate);
+static void SLLC_B(upd7810_state *cpustate);
+static void SLLC_C(upd7810_state *cpustate);
+static void SLL_A(upd7810_state *cpustate);
+static void SLL_B(upd7810_state *cpustate);
+static void SLL_C(upd7810_state *cpustate);
+static void SLRC_A(upd7810_state *cpustate);
+static void SLRC_B(upd7810_state *cpustate);
+static void SLRC_C(upd7810_state *cpustate);
+static void SLR_A(upd7810_state *cpustate);
+static void SLR_B(upd7810_state *cpustate);
+static void SLR_C(upd7810_state *cpustate);
+static void SOFTI(upd7810_state *cpustate);
+static void SSPD_w(upd7810_state *cpustate);
+static void STAW_wa(upd7810_state *cpustate);
+static void STAX_B(upd7810_state *cpustate);
+static void STAX_D(upd7810_state *cpustate);
+static void STAX_D_xx(upd7810_state *cpustate);
+static void STAX_Dm(upd7810_state *cpustate);
+static void STAX_Dp(upd7810_state *cpustate);
+static void STAX_H(upd7810_state *cpustate);
+static void STAX_H_A(upd7810_state *cpustate);
+static void STAX_H_B(upd7810_state *cpustate);
+static void STAX_H_EA(upd7810_state *cpustate);
+static void STAX_H_xx(upd7810_state *cpustate);
+static void STAX_Hm(upd7810_state *cpustate);
+static void STAX_Hp(upd7810_state *cpustate);
+static void STC(upd7810_state *cpustate);
+static void STEAX_D(upd7810_state *cpustate);
+static void STEAX_D_xx(upd7810_state *cpustate);
+static void STEAX_Dp(upd7810_state *cpustate);
+static void STEAX_H(upd7810_state *cpustate);
+static void STEAX_H_A(upd7810_state *cpustate);
+static void STEAX_H_B(upd7810_state *cpustate);
+static void STEAX_H_EA(upd7810_state *cpustate);
+static void STEAX_H_xx(upd7810_state *cpustate);
+static void STEAX_Hp(upd7810_state *cpustate);
+static void STM(upd7810_state *cpustate);
+static void STOP(upd7810_state *cpustate);
+static void SUBNBW_wa(upd7810_state *cpustate);
+static void SUBNBX_B(upd7810_state *cpustate);
+static void SUBNBX_D(upd7810_state *cpustate);
+static void SUBNBX_Dm(upd7810_state *cpustate);
+static void SUBNBX_Dp(upd7810_state *cpustate);
+static void SUBNBX_H(upd7810_state *cpustate);
+static void SUBNBX_Hm(upd7810_state *cpustate);
+static void SUBNBX_Hp(upd7810_state *cpustate);
+static void SUBNB_A_A(upd7810_state *cpustate);
+static void SUBNB_A_A(upd7810_state *cpustate);
+static void SUBNB_A_B(upd7810_state *cpustate);
+static void SUBNB_A_C(upd7810_state *cpustate);
+static void SUBNB_A_D(upd7810_state *cpustate);
+static void SUBNB_A_E(upd7810_state *cpustate);
+static void SUBNB_A_H(upd7810_state *cpustate);
+static void SUBNB_A_L(upd7810_state *cpustate);
+static void SUBNB_A_V(upd7810_state *cpustate);
+static void SUBNB_B_A(upd7810_state *cpustate);
+static void SUBNB_C_A(upd7810_state *cpustate);
+static void SUBNB_D_A(upd7810_state *cpustate);
+static void SUBNB_E_A(upd7810_state *cpustate);
+static void SUBNB_H_A(upd7810_state *cpustate);
+static void SUBNB_L_A(upd7810_state *cpustate);
+static void SUBNB_V_A(upd7810_state *cpustate);
+static void SUBW_wa(upd7810_state *cpustate);
+static void SUBX_B(upd7810_state *cpustate);
+static void SUBX_D(upd7810_state *cpustate);
+static void SUBX_Dm(upd7810_state *cpustate);
+static void SUBX_Dp(upd7810_state *cpustate);
+static void SUBX_H(upd7810_state *cpustate);
+static void SUBX_Hm(upd7810_state *cpustate);
+static void SUBX_Hp(upd7810_state *cpustate);
+static void SUB_A_A(upd7810_state *cpustate);
+static void SUB_A_A(upd7810_state *cpustate);
+static void SUB_A_B(upd7810_state *cpustate);
+static void SUB_A_C(upd7810_state *cpustate);
+static void SUB_A_D(upd7810_state *cpustate);
+static void SUB_A_E(upd7810_state *cpustate);
+static void SUB_A_H(upd7810_state *cpustate);
+static void SUB_A_L(upd7810_state *cpustate);
+static void SUB_A_V(upd7810_state *cpustate);
+static void SUB_B_A(upd7810_state *cpustate);
+static void SUB_C_A(upd7810_state *cpustate);
+static void SUB_D_A(upd7810_state *cpustate);
+static void SUB_E_A(upd7810_state *cpustate);
+static void SUB_H_A(upd7810_state *cpustate);
+static void SUB_L_A(upd7810_state *cpustate);
+static void SUB_V_A(upd7810_state *cpustate);
+static void SUINB_ANM_xx(upd7810_state *cpustate);
+static void SUINB_A_xx(upd7810_state *cpustate);
+static void SUINB_A_xx(upd7810_state *cpustate);
+static void SUINB_B_xx(upd7810_state *cpustate);
+static void SUINB_C_xx(upd7810_state *cpustate);
+static void SUINB_D_xx(upd7810_state *cpustate);
+static void SUINB_EOM_xx(upd7810_state *cpustate);
+static void SUINB_E_xx(upd7810_state *cpustate);
+static void SUINB_H_xx(upd7810_state *cpustate);
+static void SUINB_L_xx(upd7810_state *cpustate);
+static void SUINB_MKH_xx(upd7810_state *cpustate);
+static void SUINB_MKL_xx(upd7810_state *cpustate);
+static void SUINB_PA_xx(upd7810_state *cpustate);
+static void SUINB_PB_xx(upd7810_state *cpustate);
+static void SUINB_PC_xx(upd7810_state *cpustate);
+static void SUINB_PD_xx(upd7810_state *cpustate);
+static void SUINB_PF_xx(upd7810_state *cpustate);
+static void SUINB_SMH_xx(upd7810_state *cpustate);
+static void SUINB_TMM_xx(upd7810_state *cpustate);
+static void SUINB_V_xx(upd7810_state *cpustate);
+static void SUI_ANM_xx(upd7810_state *cpustate);
+static void SUI_A_xx(upd7810_state *cpustate);
+static void SUI_A_xx(upd7810_state *cpustate);
+static void SUI_B_xx(upd7810_state *cpustate);
+static void SUI_C_xx(upd7810_state *cpustate);
+static void SUI_D_xx(upd7810_state *cpustate);
+static void SUI_EOM_xx(upd7810_state *cpustate);
+static void SUI_E_xx(upd7810_state *cpustate);
+static void SUI_H_xx(upd7810_state *cpustate);
+static void SUI_L_xx(upd7810_state *cpustate);
+static void SUI_MKH_xx(upd7810_state *cpustate);
+static void SUI_MKL_xx(upd7810_state *cpustate);
+static void SUI_PA_xx(upd7810_state *cpustate);
+static void SUI_PB_xx(upd7810_state *cpustate);
+static void SUI_PC_xx(upd7810_state *cpustate);
+static void SUI_PD_xx(upd7810_state *cpustate);
+static void SUI_PF_xx(upd7810_state *cpustate);
+static void SUI_SMH_xx(upd7810_state *cpustate);
+static void SUI_TMM_xx(upd7810_state *cpustate);
+static void SUI_V_xx(upd7810_state *cpustate);
+static void TABLE(upd7810_state *cpustate);
+static void XRAW_wa(upd7810_state *cpustate);
+static void XRAX_B(upd7810_state *cpustate);
+static void XRAX_D(upd7810_state *cpustate);
+static void XRAX_Dm(upd7810_state *cpustate);
+static void XRAX_Dp(upd7810_state *cpustate);
+static void XRAX_H(upd7810_state *cpustate);
+static void XRAX_Hm(upd7810_state *cpustate);
+static void XRAX_Hp(upd7810_state *cpustate);
+static void XRA_A_A(upd7810_state *cpustate);
+static void XRA_A_A(upd7810_state *cpustate);
+static void XRA_A_B(upd7810_state *cpustate);
+static void XRA_A_C(upd7810_state *cpustate);
+static void XRA_A_D(upd7810_state *cpustate);
+static void XRA_A_E(upd7810_state *cpustate);
+static void XRA_A_H(upd7810_state *cpustate);
+static void XRA_A_L(upd7810_state *cpustate);
+static void XRA_A_V(upd7810_state *cpustate);
+static void XRA_B_A(upd7810_state *cpustate);
+static void XRA_C_A(upd7810_state *cpustate);
+static void XRA_D_A(upd7810_state *cpustate);
+static void XRA_E_A(upd7810_state *cpustate);
+static void XRA_H_A(upd7810_state *cpustate);
+static void XRA_L_A(upd7810_state *cpustate);
+static void XRA_V_A(upd7810_state *cpustate);
+static void XRI_ANM_xx(upd7810_state *cpustate);
+static void XRI_A_xx(upd7810_state *cpustate);
+static void XRI_A_xx(upd7810_state *cpustate);
+static void XRI_B_xx(upd7810_state *cpustate);
+static void XRI_C_xx(upd7810_state *cpustate);
+static void XRI_D_xx(upd7810_state *cpustate);
+static void XRI_EOM_xx(upd7810_state *cpustate);
+static void XRI_E_xx(upd7810_state *cpustate);
+static void XRI_H_xx(upd7810_state *cpustate);
+static void XRI_L_xx(upd7810_state *cpustate);
+static void XRI_MKH_xx(upd7810_state *cpustate);
+static void XRI_MKL_xx(upd7810_state *cpustate);
+static void XRI_PA_xx(upd7810_state *cpustate);
+static void XRI_PB_xx(upd7810_state *cpustate);
+static void XRI_PC_xx(upd7810_state *cpustate);
+static void XRI_PD_xx(upd7810_state *cpustate);
+static void XRI_PF_xx(upd7810_state *cpustate);
+static void XRI_SMH_xx(upd7810_state *cpustate);
+static void XRI_TMM_xx(upd7810_state *cpustate);
+static void XRI_V_xx(upd7810_state *cpustate);
+static void CALT_7801(upd7810_state *cpustate);
+static void DCR_A_7801(upd7810_state *cpustate);
+static void DCR_B_7801(upd7810_state *cpustate);
+static void DCR_C_7801(upd7810_state *cpustate);
+static void DCRW_wa_7801(upd7810_state *cpustate);
+static void INR_A_7801(upd7810_state *cpustate);
+static void INR_B_7801(upd7810_state *cpustate);
+static void INR_C_7801(upd7810_state *cpustate);
+static void INRW_wa_7801(upd7810_state *cpustate);
+static void STM_7801(upd7810_state *cpustate);
+static void MOV_MC_A_7801(upd7810_state *cpustate);
+
+
+static const struct opcode_s op48[256] =
+{
+ {illegal, 2, 8, 8,L0|L1}, /* 00: 0100 1000 0000 0000 */
+ {SLRC_A, 2, 8, 8,L0|L1}, /* 01: 0100 1000 0000 0001 */
+ {SLRC_B, 2, 8, 8,L0|L1}, /* 02: 0100 1000 0000 0010 */
+ {SLRC_C, 2, 8, 8,L0|L1}, /* 03: 0100 1000 0000 0011 */
+ {illegal, 2, 8, 8,L0|L1}, /* 04: 0100 1000 0000 0100 */
+ {SLLC_A, 2, 8, 8,L0|L1}, /* 05: 0100 1000 0000 0101 */
+ {SLLC_B, 2, 8, 8,L0|L1}, /* 06: 0100 1000 0000 0110 */
+ {SLLC_C, 2, 8, 8,L0|L1}, /* 07: 0100 1000 0000 0111 */
+ {SK_NV, 2, 8, 8,L0|L1}, /* 08: 0100 1000 0000 1000 */
+ {illegal, 2, 8, 8,L0|L1}, /* 09: 0100 1000 0000 1001 */
+ {SK_CY, 2, 8, 8,L0|L1}, /* 0a: 0100 1000 0000 1010 */
+ {SK_HC, 2, 8, 8,L0|L1}, /* 0b: 0100 1000 0000 1011 */
+ {SK_Z, 2, 8, 8,L0|L1}, /* 0c: 0100 1000 0000 1100 */
+ {illegal, 2, 8, 8,L0|L1}, /* 0d: 0100 1000 0000 1101 */
+ {illegal, 2, 8, 8,L0|L1}, /* 0e: 0100 1000 0000 1110 */
+ {illegal, 2, 8, 8,L0|L1}, /* 0f: 0100 1000 0000 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 10: 0100 1000 0001 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 11: 0100 1000 0001 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 12: 0100 1000 0001 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 13: 0100 1000 0001 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 14: 0100 1000 0001 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 15: 0100 1000 0001 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 16: 0100 1000 0001 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 17: 0100 1000 0001 0111 */
+ {SKN_NV, 2, 8, 8,L0|L1}, /* 18: 0100 1000 0001 1000 */
+ {illegal, 2, 8, 8,L0|L1}, /* 19: 0100 1000 0001 1001 */
+ {SKN_CY, 2, 8, 8,L0|L1}, /* 1a: 0100 1000 0001 1010 */
+ {SKN_HC, 2, 8, 8,L0|L1}, /* 1b: 0100 1000 0001 1011 */
+ {SKN_Z, 2, 8, 8,L0|L1}, /* 1c: 0100 1000 0001 1100 */
+ {illegal, 2, 8, 8,L0|L1}, /* 1d: 0100 1000 0001 1101 */
+ {illegal, 2, 8, 8,L0|L1}, /* 1e: 0100 1000 0001 1110 */
+ {illegal, 2, 8, 8,L0|L1}, /* 1f: 0100 1000 0001 1111 */
+
+ {illegal, 2, 8, 8,L0|L1}, /* 20: 0100 1000 0010 0000 */
+ {SLR_A, 2, 8, 8,L0|L1}, /* 21: 0100 1000 0010 0001 */
+ {SLR_B, 2, 8, 8,L0|L1}, /* 22: 0100 1000 0010 0010 */
+ {SLR_C, 2, 8, 8,L0|L1}, /* 23: 0100 1000 0010 0011 */
+ {illegal, 2, 8, 8,L0|L1}, /* 24: 0100 1000 0010 0100 */
+ {SLL_A, 2, 8, 8,L0|L1}, /* 25: 0100 1000 0010 0101 */
+ {SLL_B, 2, 8, 8,L0|L1}, /* 26: 0100 1000 0010 0110 */
+ {SLL_C, 2, 8, 8,L0|L1}, /* 27: 0100 1000 0010 0111 */
+ {JEA, 2, 8, 8,L0|L1}, /* 28: 0100 1000 0010 1000 */
+ {CALB, 2,17,17,L0|L1}, /* 29: 0100 1000 0010 1001 */
+ {CLC, 2, 8, 8,L0|L1}, /* 2a: 0100 1000 0010 1010 */
+ {STC, 2, 8, 8,L0|L1}, /* 2b: 0100 1000 0010 1011 */
+ {illegal, 2,32,32,L0|L1}, /* 2c: 0100 1000 0010 1100 */
+ {MUL_A, 2,32,32,L0|L1}, /* 2d: 0100 1000 0010 1101 */
+ {MUL_B, 2,32,32,L0|L1}, /* 2e: 0100 1000 0010 1110 */
+ {MUL_C, 2,32,32,L0|L1}, /* 2f: 0100 1000 0010 1111 */
+
+ {illegal, 2, 8, 8,L0|L1}, /* 30: 0100 1000 0011 0000 */
+ {RLR_A, 2, 8, 8,L0|L1}, /* 31: 0100 1000 0011 0001 */
+ {RLR_B, 2, 8, 8,L0|L1}, /* 32: 0100 1000 0011 0010 */
+ {RLR_C, 2, 8, 8,L0|L1}, /* 33: 0100 1000 0011 0011 */
+ {illegal, 2, 8, 8,L0|L1}, /* 34: 0100 1000 0011 0100 */
+ {RLL_A, 2, 8, 8,L0|L1}, /* 35: 0100 1000 0011 0101 */
+ {RLL_B, 2, 8, 8,L0|L1}, /* 36: 0100 1000 0011 0110 */
+ {RLL_C, 2, 8, 8,L0|L1}, /* 37: 0100 1000 0011 0111 */
+ {RLD, 2,17,17,L0|L1}, /* 38: 0100 1000 0011 1000 */
+ {RRD, 2,17,17,L0|L1}, /* 39: 0100 1000 0011 1001 */
+ {NEGA, 2, 8, 8,L0|L1}, /* 3a: 0100 1000 0011 1010 */
+ {HALT, 2,12,12,L0|L1}, /* 3b: 0100 1000 0011 1011 */
+ {illegal, 2, 8, 8,L0|L1}, /* 3c: 0100 1000 0011 1100 */
+ {DIV_A, 2,59,59,L0|L1}, /* 3d: 0100 1000 0011 1101 */
+ {DIV_B, 2,59,59,L0|L1}, /* 3e: 0100 1000 0011 1110 */
+ {DIV_C, 2,59,59,L0|L1}, /* 3f: 0100 1000 0011 1111 */
+
+ {SKIT_NMI, 2, 8, 8,L0|L1}, /* 40: 0100 1000 0100 0000 */
+ {SKIT_FT0, 2, 8, 8,L0|L1}, /* 41: 0100 1000 0100 0001 */
+ {SKIT_FT1, 2, 8, 8,L0|L1}, /* 42: 0100 1000 0100 0010 */
+ {SKIT_F1, 2, 8, 8,L0|L1}, /* 43: 0100 1000 0100 0011 */
+ {SKIT_F2, 2, 8, 8,L0|L1}, /* 44: 0100 1000 0100 0100 */
+ {SKIT_FE0, 2, 8, 8,L0|L1}, /* 45: 0100 1000 0100 0101 */
+ {SKIT_FE1, 2, 8, 8,L0|L1}, /* 46: 0100 1000 0100 0110 */
+ {SKIT_FEIN, 2, 8, 8,L0|L1}, /* 47: 0100 1000 0100 0111 */
+ {SKIT_FAD, 2, 8, 8,L0|L1}, /* 48: 0100 1000 0100 1000 */
+ {SKIT_FSR, 2, 8, 8,L0|L1}, /* 49: 0100 1000 0100 1001 */
+ {SKIT_FST, 2, 8, 8,L0|L1}, /* 4a: 0100 1000 0100 1010 */
+ {SKIT_ER, 2, 8, 8,L0|L1}, /* 4b: 0100 1000 0100 1011 */
+ {SKIT_OV, 2, 8, 8,L0|L1}, /* 4c: 0100 1000 0100 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4d: 0100 1000 0100 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4e: 0100 1000 0100 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4f: 0100 1000 0100 1111 */
+
+ {SKIT_AN4, 2, 8, 8,L0|L1}, /* 50: 0100 1000 0101 0000 */
+ {SKIT_AN5, 2, 8, 8,L0|L1}, /* 51: 0100 1000 0101 0001 */
+ {SKIT_AN6, 2, 8, 8,L0|L1}, /* 52: 0100 1000 0101 0010 */
+ {SKIT_AN7, 2, 8, 8,L0|L1}, /* 53: 0100 1000 0101 0011 */
+ {SKIT_SB, 2, 8, 8,L0|L1}, /* 54: 0100 1000 0101 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 55: 0100 1000 0101 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 56: 0100 1000 0101 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 57: 0100 1000 0101 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 58: 0100 1000 0101 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 59: 0100 1000 0101 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5a: 0100 1000 0101 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5b: 0100 1000 0101 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5c: 0100 1000 0101 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5d: 0100 1000 0101 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5e: 0100 1000 0101 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5f: 0100 1000 0101 1111 */
+
+ {SKNIT_NMI, 2, 8, 8,L0|L1}, /* 60: 0100 1000 0110 0000 */
+ {SKNIT_FT0, 2, 8, 8,L0|L1}, /* 61: 0100 1000 0110 0001 */
+ {SKNIT_FT1, 2, 8, 8,L0|L1}, /* 62: 0100 1000 0110 0010 */
+ {SKNIT_F1, 2, 8, 8,L0|L1}, /* 63: 0100 1000 0110 0011 */
+ {SKNIT_F2, 2, 8, 8,L0|L1}, /* 64: 0100 1000 0110 0100 */
+ {SKNIT_FE0, 2, 8, 8,L0|L1}, /* 65: 0100 1000 0110 0101 */
+ {SKNIT_FE1, 2, 8, 8,L0|L1}, /* 66: 0100 1000 0110 0110 */
+ {SKNIT_FEIN, 2, 8, 8,L0|L1}, /* 67: 0100 1000 0110 0111 */
+ {SKNIT_FAD, 2, 8, 8,L0|L1}, /* 68: 0100 1000 0110 1000 */
+ {SKNIT_FSR, 2, 8, 8,L0|L1}, /* 69: 0100 1000 0110 1001 */
+ {SKNIT_FST, 2, 8, 8,L0|L1}, /* 6a: 0100 1000 0110 1010 */
+ {SKNIT_ER, 2, 8, 8,L0|L1}, /* 6b: 0100 1000 0110 1011 */
+ {SKNIT_OV, 2, 8, 8,L0|L1}, /* 6c: 0100 1000 0110 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 6d: 0100 1000 0110 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 6e: 0100 1000 0110 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 6f: 0100 1000 0110 1111 */
+
+ {SKNIT_AN4, 2, 8, 8,L0|L1}, /* 70: 0100 1000 0111 0000 */
+ {SKNIT_AN5, 2, 8, 8,L0|L1}, /* 71: 0100 1000 0111 0001 */
+ {SKNIT_AN6, 2, 8, 8,L0|L1}, /* 72: 0100 1000 0111 0010 */
+ {SKNIT_AN7, 2, 8, 8,L0|L1}, /* 73: 0100 1000 0111 0011 */
+ {SKNIT_SB, 2, 8, 8,L0|L1}, /* 74: 0100 1000 0111 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 75: 0100 1000 0111 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 76: 0100 1000 0111 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 77: 0100 1000 0111 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 78: 0100 1000 0111 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 79: 0100 1000 0111 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 7a: 0100 1000 0111 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 7b: 0100 1000 0111 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 7c: 0100 1000 0111 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 7d: 0100 1000 0111 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 7e: 0100 1000 0111 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 7f: 0100 1000 0111 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 80: 0100 1000 1000 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 81: 0100 1000 1000 0001 */
+ {LDEAX_D, 2,14,11,L0|L1}, /* 82: 0100 1000 1000 0010 */
+ {LDEAX_H, 2,14,11,L0|L1}, /* 83: 0100 1000 1000 0011 */
+ {LDEAX_Dp, 2,14,11,L0|L1}, /* 84: 0100 1000 1000 0100 */
+ {LDEAX_Hp, 2,14,11,L0|L1}, /* 85: 0100 1000 1000 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 86: 0100 1000 1000 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 87: 0100 1000 1000 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 88: 0100 1000 1000 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 89: 0100 1000 1000 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 8a: 0100 1000 1000 1010 */
+ {LDEAX_D_xx, 3,20,20,L0|L1}, /* 8b: 0100 1000 1000 1011 xxxx xxxx */
+ {LDEAX_H_A, 2,20,20,L0|L1}, /* 8c: 0100 1000 1000 1100 */
+ {LDEAX_H_B, 2,20,20,L0|L1}, /* 8d: 0100 1000 1000 1101 */
+ {LDEAX_H_EA, 2,20,20,L0|L1}, /* 8e: 0100 1000 1000 1110 */
+ {LDEAX_H_xx, 3,20,20,L0|L1}, /* 8f: 0100 1000 1000 1111 xxxx xxxx */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 90: 0100 1000 1000 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 91: 0100 1000 1000 0001 */
+ {STEAX_D, 2,14,11,L0|L1}, /* 92: 0100 1000 1000 0010 */
+ {STEAX_H, 2,14,11,L0|L1}, /* 93: 0100 1000 1000 0011 */
+ {STEAX_Dp, 2,14,11,L0|L1}, /* 94: 0100 1000 1000 0100 */
+ {STEAX_Hp, 2,14,11,L0|L1}, /* 95: 0100 1000 1000 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 96: 0100 1000 1000 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 97: 0100 1000 1000 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 98: 0100 1000 1000 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 99: 0100 1000 1000 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 9a: 0100 1000 1000 1010 */
+ {STEAX_D_xx, 3,20,20,L0|L1}, /* 9b: 0100 1000 1000 1011 xxxx xxxx */
+ {STEAX_H_A, 2,20,20,L0|L1}, /* 9c: 0100 1000 1000 1100 */
+ {STEAX_H_B, 2,20,20,L0|L1}, /* 9d: 0100 1000 1000 1101 */
+ {STEAX_H_EA, 2,20,20,L0|L1}, /* 9e: 0100 1000 1000 1110 */
+ {STEAX_H_xx, 3,20,20,L0|L1}, /* 9f: 0100 1000 1000 1111 xxxx xxxx */
+
+ {DSLR_EA, 2, 8, 8,L0|L1}, /* a0: 0100 1000 1010 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a1: 0100 1000 1010 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a2: 0100 1000 1010 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a3: 0100 1000 1010 0011 */
+ {DSLL_EA, 2, 8, 8,L0|L1}, /* a4: 0100 1000 1010 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a5: 0100 1000 1010 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a6: 0100 1000 1010 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a7: 0100 1000 1010 0111 */
+ {TABLE, 2,17,17,L0|L1}, /* a8: 0100 1000 1010 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a9: 0100 1000 1010 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* aa: 0100 1000 1010 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ab: 0100 1000 1010 1011 */
+// {illegal2, 2, 8, 8,L0|L1}, /* ac: 0100 1000 1010 1100 */
+// {illegal2, 2, 8, 8,L0|L1}, /* ad: 0100 1000 1010 1101 */
+// {illegal2, 2, 8, 8,L0|L1}, /* ae: 0100 1000 1010 1110 */
+// {illegal2, 2, 8, 8,L0|L1}, /* af: 0100 1000 1010 1111 */
+ {EXA, 2, 8, 8,L0|L1}, /* ac: 0100 1000 1010 1100 */ /* 7807 */
+ {EXR, 2, 8, 8,L0|L1}, /* ad: 0100 1000 1010 1101 */ /* 7807 */
+ {EXH, 2, 8, 8,L0|L1}, /* ae: 0100 1000 1010 1110 */ /* 7807 */
+ {EXX, 2, 8, 8,L0|L1}, /* af: 0100 1000 1010 1111 */ /* 7807 */
+ {DRLR_EA, 2, 8, 8,L0|L1}, /* b0: 0100 1000 1011 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b1: 0100 1000 1011 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b2: 0100 1000 1011 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b3: 0100 1000 1011 0011 */
+ {DRLL_EA, 2, 8, 8,L0|L1}, /* b4: 0100 1000 1011 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b5: 0100 1000 1011 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b6: 0100 1000 1011 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b7: 0100 1000 1011 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b8: 0100 1000 1011 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b9: 0100 1000 1011 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ba: 0100 1000 1011 1010 */
+ {STOP, 2,12,12,L0|L1}, /* bb: 0100 1000 1011 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* bc: 0100 1000 1011 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* bd: 0100 1000 1011 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* be: 0100 1000 1011 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* bf: 0100 1000 1011 1111 */
+
+ {DMOV_EA_ECNT, 2,14,11,L0|L1}, /* c0: 0100 1000 1100 0000 */
+ {DMOV_EA_ECPT, 2,14,11,L0|L1}, /* c1: 0100 1000 1100 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* c2: 0100 1000 1100 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* c3: 0100 1000 1100 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* c4: 0100 1000 1100 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* c5: 0100 1000 1100 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* c6: 0100 1000 1100 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* c7: 0100 1000 1100 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* c8: 0100 1000 1100 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* c9: 0100 1000 1100 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ca: 0100 1000 1100 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* cb: 0100 1000 1100 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* cc: 0100 1000 1100 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* cd: 0100 1000 1100 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ce: 0100 1000 1100 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* cf: 0100 1000 1100 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* d0: 0100 1000 1101 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* d1: 0100 1000 1101 0001 */
+ {DMOV_ETM0_EA, 2,14,11,L0|L1}, /* d2: 0100 1000 1101 0010 */
+ {DMOV_ETM1_EA, 2,14,11,L0|L1}, /* d3: 0100 1000 1101 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* d4: 0100 1000 1101 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* d5: 0100 1000 1101 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* d6: 0100 1000 1101 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* d7: 0100 1000 1101 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* d8: 0100 1000 1101 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* d9: 0100 1000 1101 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* da: 0100 1000 1101 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* db: 0100 1000 1101 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* dc: 0100 1000 1101 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* dd: 0100 1000 1101 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* de: 0100 1000 1101 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* df: 0100 1000 1101 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* e0: 0100 1000 1110 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* e1: 0100 1000 1110 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* e2: 0100 1000 1110 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* e3: 0100 1000 1110 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* e4: 0100 1000 1110 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* e5: 0100 1000 1110 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* e6: 0100 1000 1110 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* e7: 0100 1000 1110 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* e8: 0100 1000 1110 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* e9: 0100 1000 1110 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ea: 0100 1000 1110 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* eb: 0100 1000 1110 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ec: 0100 1000 1110 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ed: 0100 1000 1110 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ee: 0100 1000 1110 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ef: 0100 1000 1110 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* f0: 0100 1000 1111 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* f1: 0100 1000 1111 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* f2: 0100 1000 1111 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* f3: 0100 1000 1111 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* f4: 0100 1000 1111 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* f5: 0100 1000 1111 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* f6: 0100 1000 1111 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* f7: 0100 1000 1111 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* f8: 0100 1000 1111 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* f9: 0100 1000 1111 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* fa: 0100 1000 1111 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* fb: 0100 1000 1111 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* fc: 0100 1000 1111 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* fd: 0100 1000 1111 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* fe: 0100 1000 1111 1110 */
+ {illegal2, 2, 8, 8,L0|L1} /* ff: 0100 1000 1111 1111 */
+};
+
+/* prefix 4C */
+static const struct opcode_s op4C[256] =
+{
+ {illegal2, 2, 8, 8,L0|L1}, /* 00: 0100 1100 0000 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 01: 0100 1100 0000 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 02: 0100 1100 0000 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 03: 0100 1100 0000 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 04: 0100 1100 0000 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 05: 0100 1100 0000 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 06: 0100 1100 0000 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 07: 0100 1100 0000 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 08: 0100 1100 0000 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 09: 0100 1100 0000 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 0a: 0100 1100 0000 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 0b: 0100 1100 0000 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 0c: 0100 1100 0000 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 0d: 0100 1100 0000 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 0e: 0100 1100 0000 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 0f: 0100 1100 0000 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 10: 0100 1100 0001 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 11: 0100 1100 0001 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 12: 0100 1100 0001 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 13: 0100 1100 0001 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 14: 0100 1100 0001 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 15: 0100 1100 0001 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 16: 0100 1100 0001 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 17: 0100 1100 0001 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 18: 0100 1100 0001 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 19: 0100 1100 0001 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 1a: 0100 1100 0001 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 1b: 0100 1100 0001 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 1c: 0100 1100 0001 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 1d: 0100 1100 0001 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 1e: 0100 1100 0001 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 1f: 0100 1100 0001 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 20: 0100 1100 0010 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 21: 0100 1100 0010 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 22: 0100 1100 0010 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 23: 0100 1100 0010 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 24: 0100 1100 0010 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 25: 0100 1100 0010 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 26: 0100 1100 0010 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 27: 0100 1100 0010 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 28: 0100 1100 0010 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 29: 0100 1100 0010 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 2a: 0100 1100 0010 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 2b: 0100 1100 0010 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 2c: 0100 1100 0010 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 2d: 0100 1100 0010 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 2e: 0100 1100 0010 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 2f: 0100 1100 0010 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 30: 0100 1100 0011 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 31: 0100 1100 0011 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 32: 0100 1100 0011 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 33: 0100 1100 0011 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 34: 0100 1100 0011 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 35: 0100 1100 0011 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 36: 0100 1100 0011 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 37: 0100 1100 0011 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 38: 0100 1100 0011 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 39: 0100 1100 0011 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 3a: 0100 1100 0011 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 3b: 0100 1100 0011 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 3c: 0100 1100 0011 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 3d: 0100 1100 0011 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 3e: 0100 1100 0011 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 3f: 0100 1100 0011 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 40: 0100 1100 0100 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 41: 0100 1100 0100 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 42: 0100 1100 0100 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 43: 0100 1100 0100 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 44: 0100 1100 0100 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 45: 0100 1100 0100 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 46: 0100 1100 0100 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 47: 0100 1100 0100 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 48: 0100 1100 0100 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 49: 0100 1100 0100 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4a: 0100 1100 0100 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4b: 0100 1100 0100 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4c: 0100 1100 0100 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4d: 0100 1100 0100 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4e: 0100 1100 0100 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4f: 0100 1100 0100 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 50: 0100 1100 0101 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 51: 0100 1100 0101 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 52: 0100 1100 0101 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 53: 0100 1100 0101 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 54: 0100 1100 0101 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 55: 0100 1100 0101 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 56: 0100 1100 0101 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 57: 0100 1100 0101 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 58: 0100 1100 0101 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 59: 0100 1100 0101 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5a: 0100 1100 0101 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5b: 0100 1100 0101 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5c: 0100 1100 0101 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5d: 0100 1100 0101 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5e: 0100 1100 0101 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5f: 0100 1100 0101 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 60: 0100 1100 0110 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 61: 0100 1100 0110 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 62: 0100 1100 0110 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 63: 0100 1100 0110 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 64: 0100 1100 0110 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 65: 0100 1100 0110 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 66: 0100 1100 0110 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 67: 0100 1100 0110 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 68: 0100 1100 0110 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 69: 0100 1100 0110 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 6a: 0100 1100 0110 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 6b: 0100 1100 0110 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 6c: 0100 1100 0110 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 6d: 0100 1100 0110 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 6e: 0100 1100 0110 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 6f: 0100 1100 0110 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 70: 0100 1100 0111 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 71: 0100 1100 0111 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 72: 0100 1100 0111 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 73: 0100 1100 0111 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 74: 0100 1100 0111 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 75: 0100 1100 0111 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 76: 0100 1100 0111 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 77: 0100 1100 0111 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 78: 0100 1100 0111 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 79: 0100 1100 0111 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 7a: 0100 1100 0111 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 7b: 0100 1100 0111 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 7c: 0100 1100 0111 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 7d: 0100 1100 0111 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 7e: 0100 1100 0111 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 7f: 0100 1100 0111 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 80: 0100 1100 1000 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 81: 0100 1100 1000 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 82: 0100 1100 1000 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 83: 0100 1100 1000 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 84: 0100 1100 1000 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 85: 0100 1100 1000 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 86: 0100 1100 1000 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 87: 0100 1100 1000 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 88: 0100 1100 1000 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 89: 0100 1100 1000 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 8a: 0100 1100 1000 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 8b: 0100 1100 1000 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 8c: 0100 1100 1000 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 8d: 0100 1100 1000 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 8e: 0100 1100 1000 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 8f: 0100 1100 1000 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 90: 0100 1100 1001 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 91: 0100 1100 1001 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 92: 0100 1100 1001 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 93: 0100 1100 1001 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 94: 0100 1100 1001 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 95: 0100 1100 1001 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 96: 0100 1100 1001 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 97: 0100 1100 1001 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 98: 0100 1100 1001 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 99: 0100 1100 1001 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 9a: 0100 1100 1001 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 9b: 0100 1100 1001 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 9c: 0100 1100 1001 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 9d: 0100 1100 1001 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 9e: 0100 1100 1001 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 9f: 0100 1100 1001 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* a0: 0100 1100 1010 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a1: 0100 1100 1010 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a2: 0100 1100 1010 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a3: 0100 1100 1010 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a4: 0100 1100 1010 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a5: 0100 1100 1010 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a6: 0100 1100 1010 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a7: 0100 1100 1010 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a8: 0100 1100 1010 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a9: 0100 1100 1010 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* aa: 0100 1100 1010 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ab: 0100 1100 1010 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ac: 0100 1100 1010 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ad: 0100 1100 1010 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ae: 0100 1100 1010 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* af: 0100 1100 1010 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* b0: 0100 1100 1011 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b1: 0100 1100 1011 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b2: 0100 1100 1011 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b3: 0100 1100 1011 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b4: 0100 1100 1011 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b5: 0100 1100 1011 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b6: 0100 1100 1011 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b7: 0100 1100 1011 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b8: 0100 1100 1011 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b9: 0100 1100 1011 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ba: 0100 1100 1011 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* bb: 0100 1100 1011 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* bc: 0100 1100 1011 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* bd: 0100 1100 1011 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* be: 0100 1100 1011 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* bf: 0100 1100 1011 1111 */
+
+ {MOV_A_PA, 2,10,10,L0|L1}, /* c0: 0100 1100 1100 0000 */
+ {MOV_A_PB, 2,10,10,L0|L1}, /* c1: 0100 1100 1100 0001 */
+ {MOV_A_PC, 2,10,10,L0|L1}, /* c2: 0100 1100 1100 0010 */
+ {MOV_A_PD, 2,10,10,L0|L1}, /* c3: 0100 1100 1100 0011 */
+ {illegal2, 2,10,10,L0|L1}, /* c4: 0100 1100 1100 0100 */
+ {MOV_A_PF, 2,10,10,L0|L1}, /* c5: 0100 1100 1100 0101 */
+ {MOV_A_MKH, 2,10,10,L0|L1}, /* c6: 0100 1100 1100 0110 */
+ {MOV_A_MKL, 2,10,10,L0|L1}, /* c7: 0100 1100 1100 0111 */
+ {MOV_A_ANM, 2,10,10,L0|L1}, /* c8: 0100 1100 1100 1000 */
+ {MOV_A_SMH, 2,10,10,L0|L1}, /* c9: 0100 1100 1100 1001 */
+ {illegal2, 2,10,10,L0|L1}, /* ca: 0100 1100 1100 1010 */
+ {MOV_A_EOM, 2,10,10,L0|L1}, /* cb: 0100 1100 1100 1011 */
+ {illegal2, 2,10,10,L0|L1}, /* cc: 0100 1100 1100 1100 */
+ {MOV_A_TMM, 2,10,10,L0|L1}, /* cd: 0100 1100 1100 1101 */
+// {illegal2, 2,10,10,L0|L1}, /* ce: 0100 1100 1100 1110 */
+ {MOV_A_PT, 2,10,10,L0|L1}, /* ce: 0100 1100 1100 1110 */ /* 7807 */
+ {illegal2, 2,10,10,L0|L1}, /* cf: 0100 1100 1100 1111 */
+
+ {illegal2, 2,10,10,L0|L1}, /* d0: 0100 1100 1101 0000 */
+ {illegal2, 2,10,10,L0|L1}, /* d1: 0100 1100 1101 0001 */
+ {illegal2, 2,10,10,L0|L1}, /* d2: 0100 1100 1101 0010 */
+ {illegal2, 2,10,10,L0|L1}, /* d3: 0100 1100 1101 0011 */
+ {illegal2, 2,10,10,L0|L1}, /* d4: 0100 1100 1101 0100 */
+ {illegal2, 2,10,10,L0|L1}, /* d5: 0100 1100 1101 0101 */
+ {illegal2, 2,10,10,L0|L1}, /* d6: 0100 1100 1101 0110 */
+ {illegal2, 2,10,10,L0|L1}, /* d7: 0100 1100 1101 0111 */
+ {illegal2, 2,10,10,L0|L1}, /* d8: 0100 1100 1101 1000 */
+ {MOV_A_RXB, 2,10,10,L0|L1}, /* d9: 0100 1100 1101 1001 */
+ {illegal2, 2,10,10,L0|L1}, /* da: 0100 1100 1101 1010 */
+ {illegal2, 2,10,10,L0|L1}, /* db: 0100 1100 1101 1011 */
+ {illegal2, 2,10,10,L0|L1}, /* dc: 0100 1100 1101 1100 */
+ {illegal2, 2,10,10,L0|L1}, /* dd: 0100 1100 1101 1101 */
+ {illegal2, 2,10,10,L0|L1}, /* de: 0100 1100 1101 1110 */
+ {illegal2, 2,10,10,L0|L1}, /* df: 0100 1100 1101 1111 */
+
+ {MOV_A_CR0, 2,10,10,L0|L1}, /* e0: 0100 1100 1110 0000 */
+ {MOV_A_CR1, 2,10,10,L0|L1}, /* e1: 0100 1100 1110 0001 */
+ {MOV_A_CR2, 2,10,10,L0|L1}, /* e2: 0100 1100 1110 0010 */
+ {MOV_A_CR3, 2,10,10,L0|L1}, /* e3: 0100 1100 1110 0011 */
+ {illegal2, 2,10,10,L0|L1}, /* e4: 0100 1100 1110 0100 */
+ {illegal2, 2,10,10,L0|L1}, /* e5: 0100 1100 1110 0101 */
+ {illegal2, 2,10,10,L0|L1}, /* e6: 0100 1100 1110 0110 */
+ {illegal2, 2,10,10,L0|L1}, /* e7: 0100 1100 1110 0111 */
+ {illegal2, 2,10,10,L0|L1}, /* e8: 0100 1100 1110 1000 */
+ {illegal2, 2,10,10,L0|L1}, /* e9: 0100 1100 1110 1001 */
+ {illegal2, 2,10,10,L0|L1}, /* ea: 0100 1100 1110 1010 */
+ {illegal2, 2,10,10,L0|L1}, /* eb: 0100 1100 1110 1011 */
+ {illegal2, 2,10,10,L0|L1}, /* ec: 0100 1100 1110 1100 */
+ {illegal2, 2,10,10,L0|L1}, /* ed: 0100 1100 1110 1101 */
+ {illegal2, 2,10,10,L0|L1}, /* ee: 0100 1100 1110 1110 */
+ {illegal2, 2,10,10,L0|L1}, /* ef: 0100 1100 1110 1111 */
+
+ {illegal2, 2,10,10,L0|L1}, /* f0: 0100 1100 1111 0000 */
+ {illegal2, 2,10,10,L0|L1}, /* f1: 0100 1100 1111 0001 */
+ {illegal2, 2,10,10,L0|L1}, /* f2: 0100 1100 1111 0010 */
+ {illegal2, 2,10,10,L0|L1}, /* f3: 0100 1100 1111 0011 */
+ {illegal2, 2,10,10,L0|L1}, /* f4: 0100 1100 1111 0100 */
+ {illegal2, 2,10,10,L0|L1}, /* f5: 0100 1100 1111 0101 */
+ {illegal2, 2,10,10,L0|L1}, /* f6: 0100 1100 1111 0110 */
+ {illegal2, 2,10,10,L0|L1}, /* f7: 0100 1100 1111 0111 */
+ {illegal2, 2,10,10,L0|L1}, /* f8: 0100 1100 1111 1000 */
+ {illegal2, 2,10,10,L0|L1}, /* f9: 0100 1100 1111 1001 */
+ {illegal2, 2,10,10,L0|L1}, /* fa: 0100 1100 1111 1010 */
+ {illegal2, 2,10,10,L0|L1}, /* fb: 0100 1100 1111 1011 */
+ {illegal2, 2,10,10,L0|L1}, /* fc: 0100 1100 1111 1100 */
+ {illegal2, 2,10,10,L0|L1}, /* fd: 0100 1100 1111 1101 */
+ {illegal2, 2,10,10,L0|L1}, /* fe: 0100 1100 1111 1110 */
+ {illegal2, 2,10,10,L0|L1}, /* ff: 0100 1100 1111 1111 */
+};
+
+/* prefix 4D */
+static const struct opcode_s op4D[256] =
+{
+ {illegal2, 2, 8, 8,L0|L1}, /* 00: 0100 1101 0000 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 01: 0100 1101 0000 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 02: 0100 1101 0000 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 03: 0100 1101 0000 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 04: 0100 1101 0000 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 05: 0100 1101 0000 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 06: 0100 1101 0000 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 07: 0100 1101 0000 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 08: 0100 1101 0000 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 09: 0100 1101 0000 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 0a: 0100 1101 0000 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 0b: 0100 1101 0000 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 0c: 0100 1101 0000 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 0d: 0100 1101 0000 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 0e: 0100 1101 0000 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 0f: 0100 1101 0000 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 10: 0100 1101 0001 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 11: 0100 1101 0001 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 12: 0100 1101 0001 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 13: 0100 1101 0001 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 14: 0100 1101 0001 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 15: 0100 1101 0001 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 16: 0100 1101 0001 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 17: 0100 1101 0001 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 18: 0100 1101 0001 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 19: 0100 1101 0001 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 1a: 0100 1101 0001 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 1b: 0100 1101 0001 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 1c: 0100 1101 0001 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 1d: 0100 1101 0001 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 1e: 0100 1101 0001 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 1f: 0100 1101 0001 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 20: 0100 1101 0010 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 21: 0100 1101 0010 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 22: 0100 1101 0010 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 23: 0100 1101 0010 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 24: 0100 1101 0010 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 25: 0100 1101 0010 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 26: 0100 1101 0010 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 27: 0100 1101 0010 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 28: 0100 1101 0010 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 29: 0100 1101 0010 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 2a: 0100 1101 0010 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 2b: 0100 1101 0010 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 2c: 0100 1101 0010 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 2d: 0100 1101 0010 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 2e: 0100 1101 0010 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 2f: 0100 1101 0010 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 30: 0100 1101 0011 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 31: 0100 1101 0011 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 32: 0100 1101 0011 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 33: 0100 1101 0011 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 34: 0100 1101 0011 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 35: 0100 1101 0011 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 36: 0100 1101 0011 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 37: 0100 1101 0011 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 38: 0100 1101 0011 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 39: 0100 1101 0011 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 3a: 0100 1101 0011 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 3b: 0100 1101 0011 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 3c: 0100 1101 0011 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 3d: 0100 1101 0011 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 3e: 0100 1101 0011 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 3f: 0100 1101 0011 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 40: 0100 1101 0100 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 41: 0100 1101 0100 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 42: 0100 1101 0100 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 43: 0100 1101 0100 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 44: 0100 1101 0100 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 45: 0100 1101 0100 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 46: 0100 1101 0100 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 47: 0100 1101 0100 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 48: 0100 1101 0100 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 49: 0100 1101 0100 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4a: 0100 1101 0100 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4b: 0100 1101 0100 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4c: 0100 1101 0100 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4d: 0100 1101 0100 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4e: 0100 1101 0100 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4f: 0100 1101 0100 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 50: 0100 1101 0101 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 51: 0100 1101 0101 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 52: 0100 1101 0101 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 53: 0100 1101 0101 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 54: 0100 1101 0101 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 55: 0100 1101 0101 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 56: 0100 1101 0101 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 57: 0100 1101 0101 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 58: 0100 1101 0101 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 59: 0100 1101 0101 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5a: 0100 1101 0101 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5b: 0100 1101 0101 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5c: 0100 1101 0101 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5d: 0100 1101 0101 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5e: 0100 1101 0101 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5f: 0100 1101 0101 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 60: 0100 1101 0110 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 61: 0100 1101 0110 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 62: 0100 1101 0110 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 63: 0100 1101 0110 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 64: 0100 1101 0110 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 65: 0100 1101 0110 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 66: 0100 1101 0110 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 67: 0100 1101 0110 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 68: 0100 1101 0110 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 69: 0100 1101 0110 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 6a: 0100 1101 0110 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 6b: 0100 1101 0110 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 6c: 0100 1101 0110 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 6d: 0100 1101 0110 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 6e: 0100 1101 0110 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 6f: 0100 1101 0110 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 70: 0100 1101 0111 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 71: 0100 1101 0111 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 72: 0100 1101 0111 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 73: 0100 1101 0111 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 74: 0100 1101 0111 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 75: 0100 1101 0111 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 76: 0100 1101 0111 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 77: 0100 1101 0111 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 78: 0100 1101 0111 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 79: 0100 1101 0111 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 7a: 0100 1101 0111 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 7b: 0100 1101 0111 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 7c: 0100 1101 0111 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 7d: 0100 1101 0111 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 7e: 0100 1101 0111 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 7f: 0100 1101 0111 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 80: 0100 1101 1000 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 81: 0100 1101 1000 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 82: 0100 1101 1000 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 83: 0100 1101 1000 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 84: 0100 1101 1000 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 85: 0100 1101 1000 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 86: 0100 1101 1000 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 87: 0100 1101 1000 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 88: 0100 1101 1000 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 89: 0100 1101 1000 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 8a: 0100 1101 1000 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 8b: 0100 1101 1000 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 8c: 0100 1101 1000 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 8d: 0100 1101 1000 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 8e: 0100 1101 1000 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 8f: 0100 1101 1000 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 90: 0100 1101 1001 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 91: 0100 1101 1001 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 92: 0100 1101 1001 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 93: 0100 1101 1001 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 94: 0100 1101 1001 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 95: 0100 1101 1001 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 96: 0100 1101 1001 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 97: 0100 1101 1001 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 98: 0100 1101 1001 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 99: 0100 1101 1001 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 9a: 0100 1101 1001 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 9b: 0100 1101 1001 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 9c: 0100 1101 1001 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 9d: 0100 1101 1001 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 9e: 0100 1101 1001 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 9f: 0100 1101 1001 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* a0: 0100 1101 1010 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a1: 0100 1101 1010 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a2: 0100 1101 1010 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a3: 0100 1101 1010 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a4: 0100 1101 1010 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a5: 0100 1101 1010 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a6: 0100 1101 1010 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a7: 0100 1101 1010 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a8: 0100 1101 1010 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a9: 0100 1101 1010 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* aa: 0100 1101 1010 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ab: 0100 1101 1010 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ac: 0100 1101 1010 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ad: 0100 1101 1010 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ae: 0100 1101 1010 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* af: 0100 1101 1010 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* b0: 0100 1101 1011 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b1: 0100 1101 1011 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b2: 0100 1101 1011 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b3: 0100 1101 1011 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b4: 0100 1101 1011 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b5: 0100 1101 1011 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b6: 0100 1101 1011 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b7: 0100 1101 1011 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b8: 0100 1101 1011 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b9: 0100 1101 1011 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ba: 0100 1101 1011 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* bb: 0100 1101 1011 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* bc: 0100 1101 1011 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* bd: 0100 1101 1011 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* be: 0100 1101 1011 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* bf: 0100 1101 1011 1111 */
+
+ {MOV_PA_A, 2,10,10,L0|L1}, /* c0: 0100 1101 1100 0000 */
+ {MOV_PB_A, 2,10,10,L0|L1}, /* c1: 0100 1101 1100 0001 */
+ {MOV_PC_A, 2,10,10,L0|L1}, /* c2: 0100 1101 1100 0010 */
+ {MOV_PD_A, 2,10,10,L0|L1}, /* c3: 0100 1101 1100 0011 */
+ {illegal2, 2,10,10,L0|L1}, /* c4: 0100 1101 1100 0100 */
+ {MOV_PF_A, 2,10,10,L0|L1}, /* c5: 0100 1101 1100 0101 */
+ {MOV_MKH_A, 2,10,10,L0|L1}, /* c6: 0100 1101 1100 0110 */
+ {MOV_MKL_A, 2,10,10,L0|L1}, /* c7: 0100 1101 1100 0111 */
+ {MOV_ANM_A, 2,10,10,L0|L1}, /* c8: 0100 1101 1100 1000 */
+ {MOV_SMH_A, 2,10,10,L0|L1}, /* c9: 0100 1101 1100 1001 */
+ {MOV_SML_A, 2,10,10,L0|L1}, /* ca: 0100 1101 1100 1010 */
+ {MOV_EOM_A, 2,10,10,L0|L1}, /* cb: 0100 1101 1100 1011 */
+ {MOV_ETMM_A, 2,10,10,L0|L1}, /* cc: 0100 1101 1100 1100 */
+ {MOV_TMM_A, 2,10,10,L0|L1}, /* cd: 0100 1101 1100 1101 */
+ {illegal2, 2,10,10,L0|L1}, /* ce: 0100 1101 1100 1110 */
+ {illegal2, 2,10,10,L0|L1}, /* cf: 0100 1101 1100 1111 */
+
+ {MOV_MM_A, 2,10,10,L0|L1}, /* d0: 0100 1101 1101 0000 */
+ {MOV_MCC_A, 2,10,10,L0|L1}, /* d1: 0100 1101 1101 0001 */
+ {MOV_MA_A, 2,10,10,L0|L1}, /* d2: 0100 1101 1101 0010 */
+ {MOV_MB_A, 2,10,10,L0|L1}, /* d3: 0100 1101 1101 0011 */
+ {MOV_MC_A, 2,10,10,L0|L1}, /* d4: 0100 1101 1101 0100 */
+ {illegal2, 2,10,10,L0|L1}, /* d5: 0100 1101 1101 0101 */
+ {illegal2, 2,10,10,L0|L1}, /* d6: 0100 1101 1101 0110 */
+ {MOV_MF_A, 2,10,10,L0|L1}, /* d7: 0100 1101 1101 0111 */
+ {MOV_TXB_A, 2,10,10,L0|L1}, /* d8: 0100 1101 1101 1000 */
+ {illegal2, 2,10,10,L0|L1}, /* d9: 0100 1101 1101 1001 */
+ {MOV_TM0_A, 2,10,10,L0|L1}, /* da: 0100 1101 1101 1010 */
+ {MOV_TM1_A, 2,10,10,L0|L1}, /* db: 0100 1101 1101 1011 */
+ {illegal2, 2,10,10,L0|L1}, /* dc: 0100 1101 1101 1100 */
+ {illegal2, 2,10,10,L0|L1}, /* dd: 0100 1101 1101 1101 */
+ {illegal2, 2,10,10,L0|L1}, /* de: 0100 1101 1101 1110 */
+ {illegal2, 2,10,10,L0|L1}, /* df: 0100 1101 1101 1111 */
+
+ {illegal2, 2,10,10,L0|L1}, /* e0: 0100 1101 1110 0000 */
+ {illegal2, 2,10,10,L0|L1}, /* e1: 0100 1101 1110 0001 */
+ {illegal2, 2,10,10,L0|L1}, /* e2: 0100 1101 1110 0010 */
+ {illegal2, 2,10,10,L0|L1}, /* e3: 0100 1101 1110 0011 */
+ {illegal2, 2,10,10,L0|L1}, /* e4: 0100 1101 1110 0100 */
+ {illegal2, 2,10,10,L0|L1}, /* e5: 0100 1101 1110 0101 */
+ {illegal2, 2,10,10,L0|L1}, /* e6: 0100 1101 1110 0110 */
+ {illegal2, 2,10,10,L0|L1}, /* e7: 0100 1101 1110 0111 */
+ {MOV_ZCM_A, 2,10,10,L0|L1}, /* e8: 0100 1101 1110 1000 */
+ {illegal2, 2,10,10,L0|L1}, /* e9: 0100 1101 1110 1001 */
+ {illegal2, 2,10,10,L0|L1}, /* ea: 0100 1101 1110 1010 */
+ {illegal2, 2,10,10,L0|L1}, /* eb: 0100 1101 1110 1011 */
+ {illegal2, 2,10,10,L0|L1}, /* ec: 0100 1101 1110 1100 */
+ {illegal2, 2,10,10,L0|L1}, /* ed: 0100 1101 1110 1101 */
+ {illegal2, 2,10,10,L0|L1}, /* ee: 0100 1101 1110 1110 */
+ {illegal2, 2,10,10,L0|L1}, /* ef: 0100 1101 1110 1111 */
+
+ {illegal2, 2,10,10,L0|L1}, /* f0: 0100 1101 1111 0000 */
+ {illegal2, 2,10,10,L0|L1}, /* f1: 0100 1101 1111 0001 */
+ {illegal2, 2,10,10,L0|L1}, /* f2: 0100 1101 1111 0010 */
+ {illegal2, 2,10,10,L0|L1}, /* f3: 0100 1101 1111 0011 */
+ {illegal2, 2,10,10,L0|L1}, /* f4: 0100 1101 1111 0100 */
+ {illegal2, 2,10,10,L0|L1}, /* f5: 0100 1101 1111 0101 */
+ {illegal2, 2,10,10,L0|L1}, /* f6: 0100 1101 1111 0110 */
+ {illegal2, 2,10,10,L0|L1}, /* f7: 0100 1101 1111 0111 */
+ {illegal2, 2,10,10,L0|L1}, /* f8: 0100 1101 1111 1000 */
+ {illegal2, 2,10,10,L0|L1}, /* f9: 0100 1101 1111 1001 */
+ {illegal2, 2,10,10,L0|L1}, /* fa: 0100 1101 1111 1010 */
+ {illegal2, 2,10,10,L0|L1}, /* fb: 0100 1101 1111 1011 */
+ {illegal2, 2,10,10,L0|L1}, /* fc: 0100 1101 1111 1100 */
+ {illegal2, 2,10,10,L0|L1}, /* fd: 0100 1101 1111 1101 */
+ {illegal2, 2,10,10,L0|L1}, /* fe: 0100 1101 1111 1110 */
+ {illegal2, 2,10,10,L0|L1} /* ff: 0100 1101 1111 1111 */
+};
+
+/* prefix 60 */
+static const struct opcode_s op60[256] =
+{
+ {illegal2, 2, 8, 8,L0|L1}, /* 00: 0110 0000 0000 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 01: 0110 0000 0000 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 02: 0110 0000 0000 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 03: 0110 0000 0000 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 04: 0110 0000 0000 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 05: 0110 0000 0000 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 06: 0110 0000 0000 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 07: 0110 0000 0000 0111 */
+ {ANA_V_A, 2, 8, 8,L0|L1}, /* 08: 0110 0000 0000 1000 */
+ {ANA_A_A, 2, 8, 8,L0|L1}, /* 09: 0110 0000 0000 1001 */
+ {ANA_B_A, 2, 8, 8,L0|L1}, /* 0a: 0110 0000 0000 1010 */
+ {ANA_C_A, 2, 8, 8,L0|L1}, /* 0b: 0110 0000 0000 1011 */
+ {ANA_D_A, 2, 8, 8,L0|L1}, /* 0c: 0110 0000 0000 1100 */
+ {ANA_E_A, 2, 8, 8,L0|L1}, /* 0d: 0110 0000 0000 1101 */
+ {ANA_H_A, 2, 8, 8,L0|L1}, /* 0e: 0110 0000 0000 1110 */
+ {ANA_L_A, 2, 8, 8,L0|L1}, /* 0f: 0110 0000 0000 1111 */
+
+ {XRA_V_A, 2, 8, 8,L0|L1}, /* 10: 0110 0000 0001 0000 */
+ {XRA_A_A, 2, 8, 8,L0|L1}, /* 11: 0110 0000 0001 0001 */
+ {XRA_B_A, 2, 8, 8,L0|L1}, /* 12: 0110 0000 0001 0010 */
+ {XRA_C_A, 2, 8, 8,L0|L1}, /* 13: 0110 0000 0001 0011 */
+ {XRA_D_A, 2, 8, 8,L0|L1}, /* 14: 0110 0000 0001 0100 */
+ {XRA_E_A, 2, 8, 8,L0|L1}, /* 15: 0110 0000 0001 0101 */
+ {XRA_H_A, 2, 8, 8,L0|L1}, /* 16: 0110 0000 0001 0110 */
+ {XRA_L_A, 2, 8, 8,L0|L1}, /* 17: 0110 0000 0001 0111 */
+ {ORA_V_A, 2, 8, 8,L0|L1}, /* 18: 0110 0000 0001 1000 */
+ {ORA_A_A, 2, 8, 8,L0|L1}, /* 19: 0110 0000 0001 1001 */
+ {ORA_B_A, 2, 8, 8,L0|L1}, /* 1a: 0110 0000 0001 1010 */
+ {ORA_C_A, 2, 8, 8,L0|L1}, /* 1b: 0110 0000 0001 1011 */
+ {ORA_D_A, 2, 8, 8,L0|L1}, /* 1c: 0110 0000 0001 1100 */
+ {ORA_E_A, 2, 8, 8,L0|L1}, /* 1d: 0110 0000 0001 1101 */
+ {ORA_H_A, 2, 8, 8,L0|L1}, /* 1e: 0110 0000 0001 1110 */
+ {ORA_L_A, 2, 8, 8,L0|L1}, /* 1f: 0110 0000 0001 1111 */
+
+ {ADDNC_V_A, 2, 8, 8,L0|L1}, /* 20: 0110 0000 0010 0000 */
+ {ADDNC_A_A, 2, 8, 8,L0|L1}, /* 21: 0110 0000 0010 0001 */
+ {ADDNC_B_A, 2, 8, 8,L0|L1}, /* 22: 0110 0000 0010 0010 */
+ {ADDNC_C_A, 2, 8, 8,L0|L1}, /* 23: 0110 0000 0010 0011 */
+ {ADDNC_D_A, 2, 8, 8,L0|L1}, /* 24: 0110 0000 0010 0100 */
+ {ADDNC_E_A, 2, 8, 8,L0|L1}, /* 25: 0110 0000 0010 0101 */
+ {ADDNC_H_A, 2, 8, 8,L0|L1}, /* 26: 0110 0000 0010 0110 */
+ {ADDNC_L_A, 2, 8, 8,L0|L1}, /* 27: 0110 0000 0010 0111 */
+ {GTA_V_A, 2, 8, 8,L0|L1}, /* 28: 0110 0000 0010 1000 */
+ {GTA_A_A, 2, 8, 8,L0|L1}, /* 29: 0110 0000 0010 1001 */
+ {GTA_B_A, 2, 8, 8,L0|L1}, /* 2a: 0110 0000 0010 1010 */
+ {GTA_C_A, 2, 8, 8,L0|L1}, /* 2b: 0110 0000 0010 1011 */
+ {GTA_D_A, 2, 8, 8,L0|L1}, /* 2c: 0110 0000 0010 1100 */
+ {GTA_E_A, 2, 8, 8,L0|L1}, /* 2d: 0110 0000 0010 1101 */
+ {GTA_H_A, 2, 8, 8,L0|L1}, /* 2e: 0110 0000 0010 1110 */
+ {GTA_L_A, 2, 8, 8,L0|L1}, /* 2f: 0110 0000 0010 1111 */
+
+ {SUBNB_V_A, 2, 8, 8,L0|L1}, /* 30: 0110 0000 0011 0000 */
+ {SUBNB_A_A, 2, 8, 8,L0|L1}, /* 31: 0110 0000 0011 0001 */
+ {SUBNB_B_A, 2, 8, 8,L0|L1}, /* 32: 0110 0000 0011 0010 */
+ {SUBNB_C_A, 2, 8, 8,L0|L1}, /* 33: 0110 0000 0011 0011 */
+ {SUBNB_D_A, 2, 8, 8,L0|L1}, /* 34: 0110 0000 0011 0100 */
+ {SUBNB_E_A, 2, 8, 8,L0|L1}, /* 35: 0110 0000 0011 0101 */
+ {SUBNB_H_A, 2, 8, 8,L0|L1}, /* 36: 0110 0000 0011 0110 */
+ {SUBNB_L_A, 2, 8, 8,L0|L1}, /* 37: 0110 0000 0011 0111 */
+ {LTA_V_A, 2, 8, 8,L0|L1}, /* 38: 0110 0000 0011 1000 */
+ {LTA_A_A, 2, 8, 8,L0|L1}, /* 39: 0110 0000 0011 1001 */
+ {LTA_B_A, 2, 8, 8,L0|L1}, /* 3a: 0110 0000 0011 1010 */
+ {LTA_C_A, 2, 8, 8,L0|L1}, /* 3b: 0110 0000 0011 1011 */
+ {LTA_D_A, 2, 8, 8,L0|L1}, /* 3c: 0110 0000 0011 1100 */
+ {LTA_E_A, 2, 8, 8,L0|L1}, /* 3d: 0110 0000 0011 1101 */
+ {LTA_H_A, 2, 8, 8,L0|L1}, /* 3e: 0110 0000 0011 1110 */
+ {LTA_L_A, 2, 8, 8,L0|L1}, /* 3f: 0110 0000 0011 1111 */
+
+ {ADD_V_A, 2, 8, 8,L0|L1}, /* 40: 0110 0000 0100 0000 */
+ {ADD_A_A, 2, 8, 8,L0|L1}, /* 41: 0110 0000 0100 0001 */
+ {ADD_B_A, 2, 8, 8,L0|L1}, /* 42: 0110 0000 0100 0010 */
+ {ADD_C_A, 2, 8, 8,L0|L1}, /* 43: 0110 0000 0100 0011 */
+ {ADD_D_A, 2, 8, 8,L0|L1}, /* 44: 0110 0000 0100 0100 */
+ {ADD_E_A, 2, 8, 8,L0|L1}, /* 45: 0110 0000 0100 0101 */
+ {ADD_H_A, 2, 8, 8,L0|L1}, /* 46: 0110 0000 0100 0110 */
+ {ADD_L_A, 2, 8, 8,L0|L1}, /* 47: 0110 0000 0100 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 48: 0110 0000 0100 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 49: 0110 0000 0100 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4a: 0110 0000 0100 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4b: 0110 0000 0100 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4c: 0110 0000 0100 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4d: 0110 0000 0100 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4e: 0110 0000 0100 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4f: 0110 0000 0100 1111 */
+
+ {ADC_V_A, 2, 8, 8,L0|L1}, /* 50: 0110 0000 0101 0000 */
+ {ADC_A_A, 2, 8, 8,L0|L1}, /* 51: 0110 0000 0101 0001 */
+ {ADC_B_A, 2, 8, 8,L0|L1}, /* 52: 0110 0000 0101 0010 */
+ {ADC_C_A, 2, 8, 8,L0|L1}, /* 53: 0110 0000 0101 0011 */
+ {ADC_D_A, 2, 8, 8,L0|L1}, /* 54: 0110 0000 0101 0100 */
+ {ADC_E_A, 2, 8, 8,L0|L1}, /* 55: 0110 0000 0101 0101 */
+ {ADC_H_A, 2, 8, 8,L0|L1}, /* 56: 0110 0000 0101 0110 */
+ {ADC_L_A, 2, 8, 8,L0|L1}, /* 57: 0110 0000 0101 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 58: 0110 0000 0101 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 59: 0110 0000 0101 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5a: 0110 0000 0101 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5b: 0110 0000 0101 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5c: 0110 0000 0101 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5d: 0110 0000 0101 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5e: 0110 0000 0101 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5f: 0110 0000 0101 1111 */
+
+ {SUB_V_A, 2, 8, 8,L0|L1}, /* 60: 0110 0000 0110 0000 */
+ {SUB_A_A, 2, 8, 8,L0|L1}, /* 61: 0110 0000 0110 0001 */
+ {SUB_B_A, 2, 8, 8,L0|L1}, /* 62: 0110 0000 0110 0010 */
+ {SUB_C_A, 2, 8, 8,L0|L1}, /* 63: 0110 0000 0110 0011 */
+ {SUB_D_A, 2, 8, 8,L0|L1}, /* 64: 0110 0000 0110 0100 */
+ {SUB_E_A, 2, 8, 8,L0|L1}, /* 65: 0110 0000 0110 0101 */
+ {SUB_H_A, 2, 8, 8,L0|L1}, /* 66: 0110 0000 0110 0110 */
+ {SUB_L_A, 2, 8, 8,L0|L1}, /* 67: 0110 0000 0110 0111 */
+ {NEA_V_A, 2, 8, 8,L0|L1}, /* 68: 0110 0000 0110 1000 */
+ {NEA_A_A, 2, 8, 8,L0|L1}, /* 69: 0110 0000 0110 1001 */
+ {NEA_B_A, 2, 8, 8,L0|L1}, /* 6a: 0110 0000 0110 1010 */
+ {NEA_C_A, 2, 8, 8,L0|L1}, /* 6b: 0110 0000 0110 1011 */
+ {NEA_D_A, 2, 8, 8,L0|L1}, /* 6c: 0110 0000 0110 1100 */
+ {NEA_E_A, 2, 8, 8,L0|L1}, /* 6d: 0110 0000 0110 1101 */
+ {NEA_H_A, 2, 8, 8,L0|L1}, /* 6e: 0110 0000 0110 1110 */
+ {NEA_L_A, 2, 8, 8,L0|L1}, /* 6f: 0110 0000 0110 1111 */
+
+ {SBB_V_A, 2, 8, 8,L0|L1}, /* 70: 0110 0000 0111 0000 */
+ {SBB_A_A, 2, 8, 8,L0|L1}, /* 71: 0110 0000 0111 0001 */
+ {SBB_B_A, 2, 8, 8,L0|L1}, /* 72: 0110 0000 0111 0010 */
+ {SBB_C_A, 2, 8, 8,L0|L1}, /* 73: 0110 0000 0111 0011 */
+ {SBB_D_A, 2, 8, 8,L0|L1}, /* 74: 0110 0000 0111 0100 */
+ {SBB_E_A, 2, 8, 8,L0|L1}, /* 75: 0110 0000 0111 0101 */
+ {SBB_H_A, 2, 8, 8,L0|L1}, /* 76: 0110 0000 0111 0110 */
+ {SBB_L_A, 2, 8, 8,L0|L1}, /* 77: 0110 0000 0111 0111 */
+ {EQA_V_A, 2, 8, 8,L0|L1}, /* 78: 0110 0000 0111 1000 */
+ {EQA_A_A, 2, 8, 8,L0|L1}, /* 79: 0110 0000 0111 1001 */
+ {EQA_B_A, 2, 8, 8,L0|L1}, /* 7a: 0110 0000 0111 1010 */
+ {EQA_C_A, 2, 8, 8,L0|L1}, /* 7b: 0110 0000 0111 1011 */
+ {EQA_D_A, 2, 8, 8,L0|L1}, /* 7c: 0110 0000 0111 1100 */
+ {EQA_E_A, 2, 8, 8,L0|L1}, /* 7d: 0110 0000 0111 1101 */
+ {EQA_H_A, 2, 8, 8,L0|L1}, /* 7e: 0110 0000 0111 1110 */
+ {EQA_L_A, 2, 8, 8,L0|L1}, /* 7f: 0110 0000 0111 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 80: 0110 0000 1000 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 81: 0110 0000 1000 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 82: 0110 0000 1000 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 83: 0110 0000 1000 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 84: 0110 0000 1000 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 85: 0110 0000 1000 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 86: 0110 0000 1000 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 87: 0110 0000 1000 0111 */
+ {ANA_A_V, 2, 8, 8,L0|L1}, /* 88: 0110 0000 1000 1000 */
+ {ANA_A_A, 2, 8, 8,L0|L1}, /* 89: 0110 0000 1000 1001 */
+ {ANA_A_B, 2, 8, 8,L0|L1}, /* 8a: 0110 0000 1000 1010 */
+ {ANA_A_C, 2, 8, 8,L0|L1}, /* 8b: 0110 0000 1000 1011 */
+ {ANA_A_D, 2, 8, 8,L0|L1}, /* 8c: 0110 0000 1000 1100 */
+ {ANA_A_E, 2, 8, 8,L0|L1}, /* 8d: 0110 0000 1000 1101 */
+ {ANA_A_H, 2, 8, 8,L0|L1}, /* 8e: 0110 0000 1000 1110 */
+ {ANA_A_L, 2, 8, 8,L0|L1}, /* 8f: 0110 0000 1000 1111 */
+
+ {XRA_A_V, 2, 8, 8,L0|L1}, /* 90: 0110 0000 1001 0000 */
+ {XRA_A_A, 2, 8, 8,L0|L1}, /* 91: 0110 0000 1001 0001 */
+ {XRA_A_B, 2, 8, 8,L0|L1}, /* 92: 0110 0000 1001 0010 */
+ {XRA_A_C, 2, 8, 8,L0|L1}, /* 93: 0110 0000 1001 0011 */
+ {XRA_A_D, 2, 8, 8,L0|L1}, /* 94: 0110 0000 1001 0100 */
+ {XRA_A_E, 2, 8, 8,L0|L1}, /* 95: 0110 0000 1001 0101 */
+ {XRA_A_H, 2, 8, 8,L0|L1}, /* 96: 0110 0000 1001 0110 */
+ {XRA_A_L, 2, 8, 8,L0|L1}, /* 97: 0110 0000 1001 0111 */
+ {ORA_A_V, 2, 8, 8,L0|L1}, /* 98: 0110 0000 1001 1000 */
+ {ORA_A_A, 2, 8, 8,L0|L1}, /* 99: 0110 0000 1001 1001 */
+ {ORA_A_B, 2, 8, 8,L0|L1}, /* 9a: 0110 0000 1001 1010 */
+ {ORA_A_C, 2, 8, 8,L0|L1}, /* 9b: 0110 0000 1001 1011 */
+ {ORA_A_D, 2, 8, 8,L0|L1}, /* 9c: 0110 0000 1001 1100 */
+ {ORA_A_E, 2, 8, 8,L0|L1}, /* 9d: 0110 0000 1001 1101 */
+ {ORA_A_H, 2, 8, 8,L0|L1}, /* 9e: 0110 0000 1001 1110 */
+ {ORA_A_L, 2, 8, 8,L0|L1}, /* 9f: 0110 0000 1001 1111 */
+
+ {ADDNC_A_V, 2, 8, 8,L0|L1}, /* a0: 0110 0000 1010 0000 */
+ {ADDNC_A_A, 2, 8, 8,L0|L1}, /* a1: 0110 0000 1010 0001 */
+ {ADDNC_A_B, 2, 8, 8,L0|L1}, /* a2: 0110 0000 1010 0010 */
+ {ADDNC_A_C, 2, 8, 8,L0|L1}, /* a3: 0110 0000 1010 0011 */
+ {ADDNC_A_D, 2, 8, 8,L0|L1}, /* a4: 0110 0000 1010 0100 */
+ {ADDNC_A_E, 2, 8, 8,L0|L1}, /* a5: 0110 0000 1010 0101 */
+ {ADDNC_A_H, 2, 8, 8,L0|L1}, /* a6: 0110 0000 1010 0110 */
+ {ADDNC_A_L, 2, 8, 8,L0|L1}, /* a7: 0110 0000 1010 0111 */
+ {GTA_A_V, 2, 8, 8,L0|L1}, /* a8: 0110 0000 1010 1000 */
+ {GTA_A_A, 2, 8, 8,L0|L1}, /* a9: 0110 0000 1010 1001 */
+ {GTA_A_B, 2, 8, 8,L0|L1}, /* aa: 0110 0000 1010 1010 */
+ {GTA_A_C, 2, 8, 8,L0|L1}, /* ab: 0110 0000 1010 1011 */
+ {GTA_A_D, 2, 8, 8,L0|L1}, /* ac: 0110 0000 1010 1100 */
+ {GTA_A_E, 2, 8, 8,L0|L1}, /* ad: 0110 0000 1010 1101 */
+ {GTA_A_H, 2, 8, 8,L0|L1}, /* ae: 0110 0000 1010 1110 */
+ {GTA_A_L, 2, 8, 8,L0|L1}, /* af: 0110 0000 1010 1111 */
+
+ {SUBNB_A_V, 2, 8, 8,L0|L1}, /* b0: 0110 0000 1011 0000 */
+ {SUBNB_A_A, 2, 8, 8,L0|L1}, /* b1: 0110 0000 1011 0001 */
+ {SUBNB_A_B, 2, 8, 8,L0|L1}, /* b2: 0110 0000 1011 0010 */
+ {SUBNB_A_C, 2, 8, 8,L0|L1}, /* b3: 0110 0000 1011 0011 */
+ {SUBNB_A_D, 2, 8, 8,L0|L1}, /* b4: 0110 0000 1011 0100 */
+ {SUBNB_A_E, 2, 8, 8,L0|L1}, /* b5: 0110 0000 1011 0101 */
+ {SUBNB_A_H, 2, 8, 8,L0|L1}, /* b6: 0110 0000 1011 0110 */
+ {SUBNB_A_L, 2, 8, 8,L0|L1}, /* b7: 0110 0000 1011 0111 */
+ {LTA_A_V, 2, 8, 8,L0|L1}, /* b8: 0110 0000 1011 1000 */
+ {LTA_A_A, 2, 8, 8,L0|L1}, /* b9: 0110 0000 1011 1001 */
+ {LTA_A_B, 2, 8, 8,L0|L1}, /* ba: 0110 0000 1011 1010 */
+ {LTA_A_C, 2, 8, 8,L0|L1}, /* bb: 0110 0000 1011 1011 */
+ {LTA_A_D, 2, 8, 8,L0|L1}, /* bc: 0110 0000 1011 1100 */
+ {LTA_A_E, 2, 8, 8,L0|L1}, /* bd: 0110 0000 1011 1101 */
+ {LTA_A_H, 2, 8, 8,L0|L1}, /* be: 0110 0000 1011 1110 */
+ {LTA_A_L, 2, 8, 8,L0|L1}, /* bf: 0110 0000 1011 1111 */
+
+ {ADD_A_V, 2, 8, 8,L0|L1}, /* c0: 0110 0000 1100 0000 */
+ {ADD_A_A, 2, 8, 8,L0|L1}, /* c1: 0110 0000 1100 0001 */
+ {ADD_A_B, 2, 8, 8,L0|L1}, /* c2: 0110 0000 1100 0010 */
+ {ADD_A_C, 2, 8, 8,L0|L1}, /* c3: 0110 0000 1100 0011 */
+ {ADD_A_D, 2, 8, 8,L0|L1}, /* c4: 0110 0000 1100 0100 */
+ {ADD_A_E, 2, 8, 8,L0|L1}, /* c5: 0110 0000 1100 0101 */
+ {ADD_A_H, 2, 8, 8,L0|L1}, /* c6: 0110 0000 1100 0110 */
+ {ADD_A_L, 2, 8, 8,L0|L1}, /* c7: 0110 0000 1100 0111 */
+ {ONA_A_V, 2, 8, 8,L0|L1}, /* c8: 0110 0000 1100 1000 */
+ {ONA_A_A, 2, 8, 8,L0|L1}, /* c9: 0110 0000 1100 1001 */
+ {ONA_A_B, 2, 8, 8,L0|L1}, /* ca: 0110 0000 1100 1010 */
+ {ONA_A_C, 2, 8, 8,L0|L1}, /* cb: 0110 0000 1100 1011 */
+ {ONA_A_D, 2, 8, 8,L0|L1}, /* cc: 0110 0000 1100 1100 */
+ {ONA_A_E, 2, 8, 8,L0|L1}, /* cd: 0110 0000 1100 1101 */
+ {ONA_A_H, 2, 8, 8,L0|L1}, /* ce: 0110 0000 1100 1110 */
+ {ONA_A_L, 2, 8, 8,L0|L1}, /* cf: 0110 0000 1100 1111 */
+
+ {ADC_A_V, 2, 8, 8,L0|L1}, /* d0: 0110 0000 1101 0000 */
+ {ADC_A_A, 2, 8, 8,L0|L1}, /* d1: 0110 0000 1101 0001 */
+ {ADC_A_B, 2, 8, 8,L0|L1}, /* d2: 0110 0000 1101 0010 */
+ {ADC_A_C, 2, 8, 8,L0|L1}, /* d3: 0110 0000 1101 0011 */
+ {ADC_A_D, 2, 8, 8,L0|L1}, /* d4: 0110 0000 1101 0100 */
+ {ADC_A_E, 2, 8, 8,L0|L1}, /* d5: 0110 0000 1101 0101 */
+ {ADC_A_H, 2, 8, 8,L0|L1}, /* d6: 0110 0000 1101 0110 */
+ {ADC_A_L, 2, 8, 8,L0|L1}, /* d7: 0110 0000 1101 0111 */
+ {OFFA_A_V, 2, 8, 8,L0|L1}, /* d8: 0110 0000 1101 1000 */
+ {OFFA_A_A, 2, 8, 8,L0|L1}, /* d9: 0110 0000 1101 1001 */
+ {OFFA_A_B, 2, 8, 8,L0|L1}, /* da: 0110 0000 1101 1010 */
+ {OFFA_A_C, 2, 8, 8,L0|L1}, /* db: 0110 0000 1101 1011 */
+ {OFFA_A_D, 2, 8, 8,L0|L1}, /* dc: 0110 0000 1101 1100 */
+ {OFFA_A_E, 2, 8, 8,L0|L1}, /* dd: 0110 0000 1101 1101 */
+ {OFFA_A_H, 2, 8, 8,L0|L1}, /* de: 0110 0000 1101 1110 */
+ {OFFA_A_L, 2, 8, 8,L0|L1}, /* df: 0110 0000 1101 1111 */
+
+ {SUB_A_V, 2, 8, 8,L0|L1}, /* e0: 0110 0000 1110 0000 */
+ {SUB_A_A, 2, 8, 8,L0|L1}, /* e1: 0110 0000 1110 0001 */
+ {SUB_A_B, 2, 8, 8,L0|L1}, /* e2: 0110 0000 1110 0010 */
+ {SUB_A_C, 2, 8, 8,L0|L1}, /* e3: 0110 0000 1110 0011 */
+ {SUB_A_D, 2, 8, 8,L0|L1}, /* e4: 0110 0000 1110 0100 */
+ {SUB_A_E, 2, 8, 8,L0|L1}, /* e5: 0110 0000 1110 0101 */
+ {SUB_A_H, 2, 8, 8,L0|L1}, /* e6: 0110 0000 1110 0110 */
+ {SUB_A_L, 2, 8, 8,L0|L1}, /* e7: 0110 0000 1110 0111 */
+ {NEA_A_V, 2, 8, 8,L0|L1}, /* e8: 0110 0000 1110 1000 */
+ {NEA_A_A, 2, 8, 8,L0|L1}, /* e9: 0110 0000 1110 1001 */
+ {NEA_A_B, 2, 8, 8,L0|L1}, /* ea: 0110 0000 1110 1010 */
+ {NEA_A_C, 2, 8, 8,L0|L1}, /* eb: 0110 0000 1110 1011 */
+ {NEA_A_D, 2, 8, 8,L0|L1}, /* ec: 0110 0000 1110 1100 */
+ {NEA_A_E, 2, 8, 8,L0|L1}, /* ed: 0110 0000 1110 1101 */
+ {NEA_A_H, 2, 8, 8,L0|L1}, /* ee: 0110 0000 1110 1110 */
+ {NEA_A_L, 2, 8, 8,L0|L1}, /* ef: 0110 0000 1110 1111 */
+
+ {SBB_A_V, 2, 8, 8,L0|L1}, /* f0: 0110 0000 1111 0000 */
+ {SBB_A_A, 2, 8, 8,L0|L1}, /* f1: 0110 0000 1111 0001 */
+ {SBB_A_B, 2, 8, 8,L0|L1}, /* f2: 0110 0000 1111 0010 */
+ {SBB_A_C, 2, 8, 8,L0|L1}, /* f3: 0110 0000 1111 0011 */
+ {SBB_A_D, 2, 8, 8,L0|L1}, /* f4: 0110 0000 1111 0100 */
+ {SBB_A_E, 2, 8, 8,L0|L1}, /* f5: 0110 0000 1111 0101 */
+ {SBB_A_H, 2, 8, 8,L0|L1}, /* f6: 0110 0000 1111 0110 */
+ {SBB_A_L, 2, 8, 8,L0|L1}, /* f7: 0110 0000 1111 0111 */
+ {EQA_A_V, 2, 8, 8,L0|L1}, /* f8: 0110 0000 1111 1000 */
+ {EQA_A_A, 2, 8, 8,L0|L1}, /* f9: 0110 0000 1111 1001 */
+ {EQA_A_B, 2, 8, 8,L0|L1}, /* fa: 0110 0000 1111 1010 */
+ {EQA_A_C, 2, 8, 8,L0|L1}, /* fb: 0110 0000 1111 1011 */
+ {EQA_A_D, 2, 8, 8,L0|L1}, /* fc: 0110 0000 1111 1100 */
+ {EQA_A_E, 2, 8, 8,L0|L1}, /* fd: 0110 0000 1111 1101 */
+ {EQA_A_H, 2, 8, 8,L0|L1}, /* fe: 0110 0000 1111 1110 */
+ {EQA_A_L, 2, 8, 8,L0|L1} /* ff: 0110 0000 1111 1111 */
+};
+
+/* prefix 64 */
+static const struct opcode_s op64[256] =
+{
+ {MVI_PA_xx, 3,14,11,L0|L1}, /* 00: 0110 0100 0000 0000 xxxx xxxx */
+ {MVI_PB_xx, 3,14,11,L0|L1}, /* 01: 0110 0100 0000 0001 xxxx xxxx */
+ {MVI_PC_xx, 3,14,11,L0|L1}, /* 02: 0110 0100 0000 0010 xxxx xxxx */
+ {MVI_PD_xx, 3,14,11,L0|L1}, /* 03: 0110 0100 0000 0011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 04: 0110 0100 0000 0100 xxxx xxxx */
+ {MVI_PF_xx, 3,14,11,L0|L1}, /* 05: 0110 0100 0000 0101 xxxx xxxx */
+ {MVI_MKH_xx, 3,14,11,L0|L1}, /* 06: 0110 0100 0000 0110 xxxx xxxx */
+ {MVI_MKL_xx, 3,14,11,L0|L1}, /* 07: 0110 0100 0000 0111 xxxx xxxx */
+ {ANI_PA_xx, 3,20,11,L0|L1}, /* 08: 0110 0100 0000 1000 xxxx xxxx */
+ {ANI_PB_xx, 3,20,11,L0|L1}, /* 09: 0110 0100 0000 1001 xxxx xxxx */
+ {ANI_PC_xx, 3,20,11,L0|L1}, /* 0a: 0110 0100 0000 1010 xxxx xxxx */
+ {ANI_PD_xx, 3,20,11,L0|L1}, /* 0b: 0110 0100 0000 1011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 0c: 0110 0100 0000 1100 xxxx xxxx */
+ {ANI_PF_xx, 3,20,11,L0|L1}, /* 0d: 0110 0100 0000 1101 xxxx xxxx */
+ {ANI_MKH_xx, 3,20,11,L0|L1}, /* 0e: 0110 0100 0000 1110 xxxx xxxx */
+ {ANI_MKL_xx, 3,20,11,L0|L1}, /* 0f: 0110 0100 0000 1111 xxxx xxxx */
+
+ {XRI_PA_xx, 3,20,11,L0|L1}, /* 10: 0110 0100 0001 0000 xxxx xxxx */
+ {XRI_PB_xx, 3,20,11,L0|L1}, /* 11: 0110 0100 0001 0001 xxxx xxxx */
+ {XRI_PC_xx, 3,20,11,L0|L1}, /* 12: 0110 0100 0001 0010 xxxx xxxx */
+ {XRI_PD_xx, 3,20,11,L0|L1}, /* 13: 0110 0100 0001 0011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 14: 0110 0100 0001 0100 xxxx xxxx */
+ {XRI_PF_xx, 3,20,11,L0|L1}, /* 15: 0110 0100 0001 0101 xxxx xxxx */
+ {XRI_MKH_xx, 3,20,11,L0|L1}, /* 16: 0110 0100 0001 0110 xxxx xxxx */
+ {XRI_MKL_xx, 3,20,11,L0|L1}, /* 17: 0110 0100 0001 0111 xxxx xxxx */
+ {ORI_PA_xx, 3,20,11,L0|L1}, /* 18: 0110 0100 0001 1000 xxxx xxxx */
+ {ORI_PB_xx, 3,20,11,L0|L1}, /* 19: 0110 0100 0001 1001 xxxx xxxx */
+ {ORI_PC_xx, 3,20,11,L0|L1}, /* 1a: 0110 0100 0001 1010 xxxx xxxx */
+ {ORI_PD_xx, 3,20,11,L0|L1}, /* 1b: 0110 0100 0001 1011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 1c: 0110 0100 0001 1100 xxxx xxxx */
+ {ORI_PF_xx, 3,20,11,L0|L1}, /* 1d: 0110 0100 0001 1101 xxxx xxxx */
+ {ORI_MKH_xx, 3,20,11,L0|L1}, /* 1e: 0110 0100 0001 1110 xxxx xxxx */
+ {ORI_MKL_xx, 3,20,11,L0|L1}, /* 1f: 0110 0100 0001 1111 xxxx xxxx */
+
+ {ADINC_PA_xx, 3,20,11,L0|L1}, /* 20: 0110 0100 0010 0000 xxxx xxxx */
+ {ADINC_PB_xx, 3,20,11,L0|L1}, /* 21: 0110 0100 0010 0001 xxxx xxxx */
+ {ADINC_PC_xx, 3,20,11,L0|L1}, /* 22: 0110 0100 0010 0010 xxxx xxxx */
+ {ADINC_PD_xx, 3,20,11,L0|L1}, /* 23: 0110 0100 0010 0011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 24: 0110 0100 0010 0100 xxxx xxxx */
+ {ADINC_PF_xx, 3,20,11,L0|L1}, /* 25: 0110 0100 0010 0101 xxxx xxxx */
+ {ADINC_MKH_xx, 3,20,11,L0|L1}, /* 26: 0110 0100 0010 0110 xxxx xxxx */
+ {ADINC_MKL_xx, 3,20,11,L0|L1}, /* 27: 0110 0100 0010 0111 xxxx xxxx */
+ {GTI_PA_xx, 3,20,11,L0|L1}, /* 28: 0110 0100 0010 1000 xxxx xxxx */
+ {GTI_PB_xx, 3,20,11,L0|L1}, /* 29: 0110 0100 0010 1001 xxxx xxxx */
+ {GTI_PC_xx, 3,20,11,L0|L1}, /* 2a: 0110 0100 0010 1010 xxxx xxxx */
+ {GTI_PD_xx, 3,20,11,L0|L1}, /* 2b: 0110 0100 0010 1011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 2c: 0110 0100 0010 1100 xxxx xxxx */
+ {GTI_PF_xx, 3,20,11,L0|L1}, /* 2d: 0110 0100 0010 1101 xxxx xxxx */
+ {GTI_MKH_xx, 3,20,11,L0|L1}, /* 2e: 0110 0100 0010 1110 xxxx xxxx */
+ {GTI_MKL_xx, 3,20,11,L0|L1}, /* 2f: 0110 0100 0010 1111 xxxx xxxx */
+
+ {SUINB_PA_xx, 3,20,11,L0|L1}, /* 30: 0110 0100 0011 0000 xxxx xxxx */
+ {SUINB_PB_xx, 3,20,11,L0|L1}, /* 31: 0110 0100 0011 0001 xxxx xxxx */
+ {SUINB_PC_xx, 3,20,11,L0|L1}, /* 32: 0110 0100 0011 0010 xxxx xxxx */
+ {SUINB_PD_xx, 3,20,11,L0|L1}, /* 33: 0110 0100 0011 0011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 34: 0110 0100 0011 0100 xxxx xxxx */
+ {SUINB_PF_xx, 3,20,11,L0|L1}, /* 35: 0110 0100 0011 0101 xxxx xxxx */
+ {SUINB_MKH_xx, 3,20,11,L0|L1}, /* 36: 0110 0100 0011 0110 xxxx xxxx */
+ {SUINB_MKL_xx, 3,20,11,L0|L1}, /* 37: 0110 0100 0011 0111 xxxx xxxx */
+ {LTI_PA_xx, 3,20,11,L0|L1}, /* 38: 0110 0100 0011 1000 xxxx xxxx */
+ {LTI_PB_xx, 3,20,11,L0|L1}, /* 39: 0110 0100 0011 1001 xxxx xxxx */
+ {LTI_PC_xx, 3,20,11,L0|L1}, /* 3a: 0110 0100 0011 1010 xxxx xxxx */
+ {LTI_PD_xx, 3,20,11,L0|L1}, /* 3b: 0110 0100 0011 1011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 3c: 0110 0100 0011 1100 xxxx xxxx */
+ {LTI_PF_xx, 3,20,11,L0|L1}, /* 3d: 0110 0100 0011 1101 xxxx xxxx */
+ {LTI_MKH_xx, 3,20,11,L0|L1}, /* 3e: 0110 0100 0011 1110 xxxx xxxx */
+ {LTI_MKL_xx, 3,20,11,L0|L1}, /* 3f: 0110 0100 0011 1111 xxxx xxxx */
+
+ {ADI_PA_xx, 3,20,11,L0|L1}, /* 40: 0110 0100 0100 0000 xxxx xxxx */
+ {ADI_PB_xx, 3,20,11,L0|L1}, /* 41: 0110 0100 0100 0001 xxxx xxxx */
+ {ADI_PC_xx, 3,20,11,L0|L1}, /* 42: 0110 0100 0100 0010 xxxx xxxx */
+ {ADI_PD_xx, 3,20,11,L0|L1}, /* 43: 0110 0100 0100 0011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 44: 0110 0100 0100 0100 xxxx xxxx */
+ {ADI_PF_xx, 3,20,11,L0|L1}, /* 45: 0110 0100 0100 0101 xxxx xxxx */
+ {ADI_MKH_xx, 3,20,11,L0|L1}, /* 46: 0110 0100 0100 0110 xxxx xxxx */
+ {ADI_MKL_xx, 3,20,11,L0|L1}, /* 47: 0110 0100 0100 0111 xxxx xxxx */
+ {ONI_PA_xx, 3,20,11,L0|L1}, /* 48: 0110 0100 0100 1000 xxxx xxxx */
+ {ONI_PB_xx, 3,20,11,L0|L1}, /* 49: 0110 0100 0100 1001 xxxx xxxx */
+ {ONI_PC_xx, 3,20,11,L0|L1}, /* 4a: 0110 0100 0100 1010 xxxx xxxx */
+ {ONI_PD_xx, 3,20,11,L0|L1}, /* 4b: 0110 0100 0100 1011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 4c: 0110 0100 0100 1100 xxxx xxxx */
+ {ONI_PF_xx, 3,20,11,L0|L1}, /* 4d: 0110 0100 0100 1101 xxxx xxxx */
+ {ONI_MKH_xx, 3,20,11,L0|L1}, /* 4e: 0110 0100 0100 1110 xxxx xxxx */
+ {ONI_MKL_xx, 3,20,11,L0|L1}, /* 4f: 0110 0100 0100 1111 xxxx xxxx */
+
+ {ACI_PA_xx, 3,20,11,L0|L1}, /* 50: 0110 0100 0101 0000 xxxx xxxx */
+ {ACI_PB_xx, 3,20,11,L0|L1}, /* 51: 0110 0100 0101 0001 xxxx xxxx */
+ {ACI_PC_xx, 3,20,11,L0|L1}, /* 52: 0110 0100 0101 0010 xxxx xxxx */
+ {ACI_PD_xx, 3,20,11,L0|L1}, /* 53: 0110 0100 0101 0011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 54: 0110 0100 0101 0100 xxxx xxxx */
+ {ACI_PF_xx, 3,20,11,L0|L1}, /* 55: 0110 0100 0101 0101 xxxx xxxx */
+ {ACI_MKH_xx, 3,20,11,L0|L1}, /* 56: 0110 0100 0101 0110 xxxx xxxx */
+ {ACI_MKL_xx, 3,20,11,L0|L1}, /* 57: 0110 0100 0101 0111 xxxx xxxx */
+ {OFFI_PA_xx, 3,20,11,L0|L1}, /* 58: 0110 0100 0101 1000 xxxx xxxx */
+ {OFFI_PB_xx, 3,20,11,L0|L1}, /* 59: 0110 0100 0101 1001 xxxx xxxx */
+ {OFFI_PC_xx, 3,20,11,L0|L1}, /* 5a: 0110 0100 0101 1010 xxxx xxxx */
+ {OFFI_PD_xx, 3,20,11,L0|L1}, /* 5b: 0110 0100 0101 1011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 5c: 0110 0100 0101 1100 xxxx xxxx */
+ {OFFI_PF_xx, 3,20,11,L0|L1}, /* 5d: 0110 0100 0101 1101 xxxx xxxx */
+ {OFFI_MKH_xx, 3,20,11,L0|L1}, /* 5e: 0110 0100 0101 1110 xxxx xxxx */
+ {OFFI_MKL_xx, 3,20,11,L0|L1}, /* 5f: 0110 0100 0101 1111 xxxx xxxx */
+
+ {SUI_PA_xx, 3,20,11,L0|L1}, /* 60: 0110 0100 0110 0000 xxxx xxxx */
+ {SUI_PB_xx, 3,20,11,L0|L1}, /* 61: 0110 0100 0110 0001 xxxx xxxx */
+ {SUI_PC_xx, 3,20,11,L0|L1}, /* 62: 0110 0100 0110 0010 xxxx xxxx */
+ {SUI_PD_xx, 3,20,11,L0|L1}, /* 63: 0110 0100 0110 0011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 64: 0110 0100 0110 0100 xxxx xxxx */
+ {SUI_PF_xx, 3,20,11,L0|L1}, /* 65: 0110 0100 0110 0101 xxxx xxxx */
+ {SUI_MKH_xx, 3,20,11,L0|L1}, /* 66: 0110 0100 0110 0110 xxxx xxxx */
+ {SUI_MKL_xx, 3,20,11,L0|L1}, /* 67: 0110 0100 0110 0111 xxxx xxxx */
+ {NEI_PA_xx, 3,20,11,L0|L1}, /* 68: 0110 0100 0110 1000 xxxx xxxx */
+ {NEI_PB_xx, 3,20,11,L0|L1}, /* 69: 0110 0100 0110 1001 xxxx xxxx */
+ {NEI_PC_xx, 3,20,11,L0|L1}, /* 6a: 0110 0100 0110 1010 xxxx xxxx */
+ {NEI_PD_xx, 3,20,11,L0|L1}, /* 6b: 0110 0100 0110 1011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 6c: 0110 0100 0110 1100 xxxx xxxx */
+ {NEI_PF_xx, 3,20,11,L0|L1}, /* 6d: 0110 0100 0110 1101 xxxx xxxx */
+ {NEI_MKH_xx, 3,20,11,L0|L1}, /* 6e: 0110 0100 0110 1110 xxxx xxxx */
+ {NEI_MKL_xx, 3,20,11,L0|L1}, /* 6f: 0110 0100 0110 1111 xxxx xxxx */
+
+ {SBI_PA_xx, 3,20,11,L0|L1}, /* 70: 0110 0100 0111 0000 xxxx xxxx */
+ {SBI_PB_xx, 3,20,11,L0|L1}, /* 71: 0110 0100 0111 0001 xxxx xxxx */
+ {SBI_PC_xx, 3,20,11,L0|L1}, /* 72: 0110 0100 0111 0010 xxxx xxxx */
+ {SBI_PD_xx, 3,20,11,L0|L1}, /* 73: 0110 0100 0111 0011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 74: 0110 0100 0111 0100 xxxx xxxx */
+ {SBI_PF_xx, 3,20,11,L0|L1}, /* 75: 0110 0100 0111 0101 xxxx xxxx */
+ {SBI_MKH_xx, 3,20,11,L0|L1}, /* 76: 0110 0100 0111 0110 xxxx xxxx */
+ {SBI_MKL_xx, 3,20,11,L0|L1}, /* 77: 0110 0100 0111 0111 xxxx xxxx */
+ {EQI_PA_xx, 3,20,11,L0|L1}, /* 78: 0110 0100 0111 1000 xxxx xxxx */
+ {EQI_PB_xx, 3,20,11,L0|L1}, /* 79: 0110 0100 0111 1001 xxxx xxxx */
+ {EQI_PC_xx, 3,20,11,L0|L1}, /* 7a: 0110 0100 0111 1010 xxxx xxxx */
+ {EQI_PD_xx, 3,20,11,L0|L1}, /* 7b: 0110 0100 0111 1011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 7c: 0110 0100 0111 1100 xxxx xxxx */
+ {EQI_PF_xx, 3,20,11,L0|L1}, /* 7d: 0110 0100 0111 1101 xxxx xxxx */
+ {EQI_MKH_xx, 3,20,11,L0|L1}, /* 7e: 0110 0100 0111 1110 xxxx xxxx */
+ {EQI_MKL_xx, 3,20,11,L0|L1}, /* 7f: 0110 0100 0111 1111 xxxx xxxx */
+
+ {MVI_ANM_xx, 3,14,11,L0|L1}, /* 80: 0110 0100 1000 0000 xxxx xxxx */
+ {MVI_SMH_xx, 3,14,11,L0|L1}, /* 81: 0110 0100 1000 0001 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 82: 0110 0100 1000 0010 xxxx xxxx */
+ {MVI_EOM_xx, 3,14,11,L0|L1}, /* 83: 0110 0100 1000 0011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 84: 0110 0100 1000 0100 xxxx xxxx */
+ {MVI_TMM_xx, 3,14,11,L0|L1}, /* 85: 0110 0100 1000 0101 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 86: 0110 0100 1000 0110 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 87: 0110 0100 1000 0111 xxxx xxxx */
+ {ANI_ANM_xx, 3,20,11,L0|L1}, /* 88: 0110 0100 1000 1000 xxxx xxxx */
+ {ANI_SMH_xx, 3,20,11,L0|L1}, /* 89: 0110 0100 1000 1001 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 8a: 0110 0100 1000 1010 xxxx xxxx */
+ {ANI_EOM_xx, 3,20,11,L0|L1}, /* 8b: 0110 0100 1000 1011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 8c: 0110 0100 1000 1100 xxxx xxxx */
+ {ANI_TMM_xx, 3,20,11,L0|L1}, /* 8d: 0110 0100 1000 1101 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 8e: 0110 0100 1000 1110 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 8f: 0110 0100 1000 1111 xxxx xxxx */
+
+ {XRI_ANM_xx, 3,20,11,L0|L1}, /* 90: 0110 0100 1001 0000 xxxx xxxx */
+ {XRI_SMH_xx, 3,20,11,L0|L1}, /* 91: 0110 0100 1001 0001 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 92: 0110 0100 1001 0010 xxxx xxxx */
+ {XRI_EOM_xx, 3,20,11,L0|L1}, /* 93: 0110 0100 1001 0011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 94: 0110 0100 1001 0100 xxxx xxxx */
+ {XRI_TMM_xx, 3,20,11,L0|L1}, /* 95: 0110 0100 1001 0101 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 96: 0110 0100 1001 0110 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 97: 0110 0100 1001 0111 xxxx xxxx */
+ {ORI_ANM_xx, 3,20,11,L0|L1}, /* 98: 0110 0100 1001 1000 xxxx xxxx */
+ {ORI_SMH_xx, 3,20,11,L0|L1}, /* 99: 0110 0100 1001 1001 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 9a: 0110 0100 1001 1010 xxxx xxxx */
+ {ORI_EOM_xx, 3,20,11,L0|L1}, /* 9b: 0110 0100 1001 1011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 9c: 0110 0100 1001 1100 xxxx xxxx */
+ {ORI_TMM_xx, 3,20,11,L0|L1}, /* 9d: 0110 0100 1001 1101 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 9e: 0110 0100 1001 1110 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* 9f: 0110 0100 1001 1111 xxxx xxxx */
+
+ {ADINC_ANM_xx, 3,20,11,L0|L1}, /* a0: 0110 0100 1010 0000 xxxx xxxx */
+ {ADINC_SMH_xx, 3,20,11,L0|L1}, /* a1: 0110 0100 1010 0001 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* a2: 0110 0100 1010 0010 xxxx xxxx */
+ {ADINC_EOM_xx, 3,20,11,L0|L1}, /* a3: 0110 0100 1010 0011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* a4: 0110 0100 1010 0100 xxxx xxxx */
+ {ADINC_TMM_xx, 3,20,11,L0|L1}, /* a5: 0110 0100 1010 0101 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* a6: 0110 0100 1010 0110 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* a7: 0110 0100 1010 0111 xxxx xxxx */
+ {GTI_ANM_xx, 3,20,11,L0|L1}, /* a8: 0110 0100 1010 1000 xxxx xxxx */
+ {GTI_SMH_xx, 3,20,11,L0|L1}, /* a9: 0110 0100 1010 1001 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* aa: 0110 0100 1010 1010 xxxx xxxx */
+ {GTI_EOM_xx, 3,20,11,L0|L1}, /* ab: 0110 0100 1010 1011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* ac: 0110 0100 1010 1100 xxxx xxxx */
+ {GTI_TMM_xx, 3,20,11,L0|L1}, /* ad: 0110 0100 1010 1101 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* ae: 0110 0100 1010 1110 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* af: 0110 0100 1010 1111 xxxx xxxx */
+
+ {SUINB_ANM_xx, 3,20,11,L0|L1}, /* b0: 0110 0100 1011 0000 xxxx xxxx */
+ {SUINB_SMH_xx, 3,20,11,L0|L1}, /* b1: 0110 0100 1011 0001 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* b2: 0110 0100 1011 0010 xxxx xxxx */
+ {SUINB_EOM_xx, 3,20,11,L0|L1}, /* b3: 0110 0100 1011 0011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* b4: 0110 0100 1011 0100 xxxx xxxx */
+ {SUINB_TMM_xx, 3,20,11,L0|L1}, /* b5: 0110 0100 1011 0101 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* b6: 0110 0100 1011 0110 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* b7: 0110 0100 1011 0111 xxxx xxxx */
+ {LTI_ANM_xx, 3,20,11,L0|L1}, /* b8: 0110 0100 1011 1000 xxxx xxxx */
+ {LTI_SMH_xx, 3,20,11,L0|L1}, /* b9: 0110 0100 1011 1001 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* ba: 0110 0100 1011 1010 xxxx xxxx */
+ {LTI_EOM_xx, 3,20,11,L0|L1}, /* bb: 0110 0100 1011 1011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* bc: 0110 0100 1011 1100 xxxx xxxx */
+ {LTI_TMM_xx, 3,20,11,L0|L1}, /* bd: 0110 0100 1011 1101 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* be: 0110 0100 1011 1110 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* bf: 0110 0100 1011 1111 xxxx xxxx */
+
+ {ADI_ANM_xx, 3,20,11,L0|L1}, /* c0: 0110 0100 1100 0000 xxxx xxxx */
+ {ADI_SMH_xx, 3,20,11,L0|L1}, /* c1: 0110 0100 1100 0001 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* c2: 0110 0100 1100 0010 xxxx xxxx */
+ {ADI_EOM_xx, 3,20,11,L0|L1}, /* c3: 0110 0100 1100 0011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* c4: 0110 0100 1100 0100 xxxx xxxx */
+ {ADI_TMM_xx, 3,20,11,L0|L1}, /* c5: 0110 0100 1100 0101 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* c6: 0110 0100 1100 0110 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* c7: 0110 0100 1100 0111 xxxx xxxx */
+ {ONI_ANM_xx, 3,20,11,L0|L1}, /* c8: 0110 0100 1100 1000 xxxx xxxx */
+ {ONI_SMH_xx, 3,20,11,L0|L1}, /* c9: 0110 0100 1100 1001 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* ca: 0110 0100 1100 1010 xxxx xxxx */
+ {ONI_EOM_xx, 3,20,11,L0|L1}, /* cb: 0110 0100 1100 1011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* cc: 0110 0100 1100 1100 xxxx xxxx */
+ {ONI_TMM_xx, 3,20,11,L0|L1}, /* cd: 0110 0100 1100 1101 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* ce: 0110 0100 1100 1110 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* cf: 0110 0100 1100 1111 xxxx xxxx */
+
+ {ACI_ANM_xx, 3,20,11,L0|L1}, /* d0: 0110 0100 1101 0000 xxxx xxxx */
+ {ACI_SMH_xx, 3,20,11,L0|L1}, /* d1: 0110 0100 1101 0001 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* d2: 0110 0100 1101 0010 xxxx xxxx */
+ {ACI_EOM_xx, 3,20,11,L0|L1}, /* d3: 0110 0100 1101 0011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* d4: 0110 0100 1101 0100 xxxx xxxx */
+ {ACI_TMM_xx, 3,20,11,L0|L1}, /* d5: 0110 0100 1101 0101 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* d6: 0110 0100 1101 0110 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* d7: 0110 0100 1101 0111 xxxx xxxx */
+ {OFFI_ANM_xx, 3,20,11,L0|L1}, /* d8: 0110 0100 1101 1000 xxxx xxxx */
+ {OFFI_SMH_xx, 3,20,11,L0|L1}, /* d9: 0110 0100 1101 1001 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* da: 0110 0100 1101 1010 xxxx xxxx */
+ {OFFI_EOM_xx, 3,20,11,L0|L1}, /* db: 0110 0100 1101 1011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* dc: 0110 0100 1101 1100 xxxx xxxx */
+ {OFFI_TMM_xx, 3,20,11,L0|L1}, /* dd: 0110 0100 1101 1101 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* de: 0110 0100 1101 1110 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* df: 0110 0100 1101 1111 xxxx xxxx */
+
+ {SUI_ANM_xx, 3,20,11,L0|L1}, /* e0: 0110 0100 1110 0000 xxxx xxxx */
+ {SUI_SMH_xx, 3,20,11,L0|L1}, /* e1: 0110 0100 1110 0001 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* e2: 0110 0100 1110 0010 xxxx xxxx */
+ {SUI_EOM_xx, 3,20,11,L0|L1}, /* e3: 0110 0100 1110 0011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* e4: 0110 0100 1110 0100 xxxx xxxx */
+ {SUI_TMM_xx, 3,20,11,L0|L1}, /* e5: 0110 0100 1110 0101 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* e6: 0110 0100 1110 0110 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* e7: 0110 0100 1110 0111 xxxx xxxx */
+ {NEI_ANM_xx, 3,20,11,L0|L1}, /* e8: 0110 0100 1110 1000 xxxx xxxx */
+ {NEI_SMH_xx, 3,20,11,L0|L1}, /* e9: 0110 0100 1110 1001 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* ea: 0110 0100 1110 1010 xxxx xxxx */
+ {NEI_EOM_xx, 3,20,11,L0|L1}, /* eb: 0110 0100 1110 1011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* ec: 0110 0100 1110 1100 xxxx xxxx */
+ {NEI_TMM_xx, 3,20,11,L0|L1}, /* ed: 0110 0100 1110 1101 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* ee: 0110 0100 1110 1110 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* ef: 0110 0100 1110 1111 xxxx xxxx */
+
+ {SBI_ANM_xx, 3,20,11,L0|L1}, /* f0: 0110 0100 1111 0000 xxxx xxxx */
+ {SBI_SMH_xx, 3,20,11,L0|L1}, /* f1: 0110 0100 1111 0001 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* f2: 0110 0100 1111 0010 xxxx xxxx */
+ {SBI_EOM_xx, 3,20,11,L0|L1}, /* f3: 0110 0100 1111 0011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* f4: 0110 0100 1111 0100 xxxx xxxx */
+ {SBI_TMM_xx, 3,20,11,L0|L1}, /* f5: 0110 0100 1111 0101 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* f6: 0110 0100 1111 0110 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* f7: 0110 0100 1111 0111 xxxx xxxx */
+ {EQI_ANM_xx, 3,20,11,L0|L1}, /* f8: 0110 0100 1111 1000 xxxx xxxx */
+ {EQI_SMH_xx, 3,20,11,L0|L1}, /* f9: 0110 0100 1111 1001 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* fa: 0110 0100 1111 1010 xxxx xxxx */
+ {EQI_EOM_xx, 3,20,11,L0|L1}, /* fb: 0110 0100 1111 1011 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* fc: 0110 0100 1111 1100 xxxx xxxx */
+ {EQI_TMM_xx, 3,20,11,L0|L1}, /* fd: 0110 0100 1111 1101 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1}, /* fe: 0110 0100 1111 1110 xxxx xxxx */
+ {illegal2, 3,11,11,L0|L1} /* ff: 0110 0100 1111 1111 xxxx xxxx */
+};
+
+/* prefix 70 */
+static const struct opcode_s op70[256] =
+{
+ {illegal2, 2, 8, 8,L0|L1}, /* 00: 0111 0000 0000 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 01: 0111 0000 0000 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 02: 0111 0000 0000 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 03: 0111 0000 0000 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 04: 0111 0000 0000 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 05: 0111 0000 0000 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 06: 0111 0000 0000 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 07: 0111 0000 0000 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 08: 0111 0000 0000 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 09: 0111 0000 0000 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 0a: 0111 0000 0000 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 0b: 0111 0000 0000 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 0c: 0111 0000 0000 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 0d: 0111 0000 0000 1101 */
+ {SSPD_w, 4,20,20,L0|L1}, /* 0e: 0111 0000 0000 1110 llll llll hhhh hhhh */
+ {LSPD_w, 4,20,20,L0|L1}, /* 0f: 0111 0000 0000 1111 llll llll hhhh hhhh */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 10: 0111 0000 0001 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 11: 0111 0000 0001 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 12: 0111 0000 0001 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 13: 0111 0000 0001 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 14: 0111 0000 0001 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 15: 0111 0000 0001 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 16: 0111 0000 0001 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 17: 0111 0000 0001 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 18: 0111 0000 0001 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 19: 0111 0000 0001 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 1a: 0111 0000 0001 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 1b: 0111 0000 0001 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 1c: 0111 0000 0001 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 1d: 0111 0000 0001 1101 */
+ {SBCD_w, 4,20,20,L0|L1}, /* 1e: 0111 0000 0001 1110 llll llll hhhh hhhh */
+ {LBCD_w, 4,20,20,L0|L1}, /* 1f: 0111 0000 0001 1111 llll llll hhhh hhhh */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 20: 0111 0000 0010 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 21: 0111 0000 0010 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 22: 0111 0000 0010 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 23: 0111 0000 0010 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 24: 0111 0000 0010 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 25: 0111 0000 0010 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 26: 0111 0000 0010 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 27: 0111 0000 0010 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 28: 0111 0000 0010 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 29: 0111 0000 0010 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 2a: 0111 0000 0010 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 2b: 0111 0000 0010 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 2c: 0111 0000 0010 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 2d: 0111 0000 0010 1101 */
+ {SDED_w, 4,20,20,L0|L1}, /* 2e: 0111 0000 0010 1110 llll llll hhhh hhhh */
+ {LDED_w, 4,20,20,L0|L1}, /* 2f: 0111 0000 0010 1111 llll llll hhhh hhhh */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 30: 0111 0000 0011 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 31: 0111 0000 0011 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 32: 0111 0000 0011 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 33: 0111 0000 0011 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 34: 0111 0000 0011 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 35: 0111 0000 0011 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 36: 0111 0000 0011 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 37: 0111 0000 0011 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 38: 0111 0000 0011 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 39: 0111 0000 0011 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 3a: 0111 0000 0011 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 3b: 0111 0000 0011 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 3c: 0111 0000 0011 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 3d: 0111 0000 0011 1101 */
+ {SHLD_w, 4,20,20,L0|L1}, /* 3e: 0111 0000 0011 1110 llll llll hhhh hhhh */
+ {LHLD_w, 4,20,20,L0|L1}, /* 3f: 0111 0000 0011 1111 llll llll hhhh hhhh */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 40: 0111 0000 0100 0000 */
+ {EADD_EA_A, 2,11,11,L0|L1}, /* 41: 0111 0000 0100 0001 */
+ {EADD_EA_B, 2,11,11,L0|L1}, /* 42: 0111 0000 0100 0010 */
+ {EADD_EA_C, 2,11,11,L0|L1}, /* 43: 0111 0000 0100 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 44: 0111 0000 0100 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 45: 0111 0000 0100 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 46: 0111 0000 0100 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 47: 0111 0000 0100 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 48: 0111 0000 0100 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 49: 0111 0000 0100 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4a: 0111 0000 0100 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4b: 0111 0000 0100 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4c: 0111 0000 0100 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4d: 0111 0000 0100 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4e: 0111 0000 0100 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 4f: 0111 0000 0100 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 50: 0111 0000 0101 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 51: 0111 0000 0101 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 52: 0111 0000 0101 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 53: 0111 0000 0101 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 54: 0111 0000 0101 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 55: 0111 0000 0101 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 56: 0111 0000 0101 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 57: 0111 0000 0101 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 58: 0111 0000 0101 1000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 59: 0111 0000 0101 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5a: 0111 0000 0101 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5b: 0111 0000 0101 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5c: 0111 0000 0101 1100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5d: 0111 0000 0101 1101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5e: 0111 0000 0101 1110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 5f: 0111 0000 0101 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 60: 0111 0000 0110 0000 */
+ {ESUB_EA_A, 2,11,11,L0|L1}, /* 61: 0111 0000 0110 0001 */
+ {ESUB_EA_B, 2,11,11,L0|L1}, /* 62: 0111 0000 0110 0010 */
+ {ESUB_EA_C, 2,11,11,L0|L1}, /* 63: 0111 0000 0110 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 64: 0111 0000 0110 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 65: 0111 0000 0110 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 66: 0111 0000 0110 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 67: 0111 0000 0110 0111 */
+ {MOV_V_w, 4,17,17,L0|L1}, /* 68: 0111 0000 0110 1000 llll llll hhhh hhhh */
+ {MOV_A_w, 4,17,17,L0|L1}, /* 69: 0111 0000 0110 1001 llll llll hhhh hhhh */
+ {MOV_B_w, 4,17,17,L0|L1}, /* 6a: 0111 0000 0110 1010 llll llll hhhh hhhh */
+ {MOV_C_w, 4,17,17,L0|L1}, /* 6b: 0111 0000 0110 1011 llll llll hhhh hhhh */
+ {MOV_D_w, 4,17,17,L0|L1}, /* 6c: 0111 0000 0110 1100 llll llll hhhh hhhh */
+ {MOV_E_w, 4,17,17,L0|L1}, /* 6d: 0111 0000 0110 1101 llll llll hhhh hhhh */
+ {MOV_H_w, 4,17,17,L0|L1}, /* 6e: 0111 0000 0110 1110 llll llll hhhh hhhh */
+ {MOV_L_w, 4,17,17,L0|L1}, /* 6f: 0111 0000 0110 1111 llll llll hhhh hhhh */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 70: 0111 0000 0111 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 71: 0111 0000 0111 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 72: 0111 0000 0111 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 73: 0111 0000 0111 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 74: 0111 0000 0111 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 75: 0111 0000 0111 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 76: 0111 0000 0111 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 77: 0111 0000 0111 0111 */
+ {MOV_w_V, 4,17,17,L0|L1}, /* 78: 0111 0000 0111 1000 llll llll hhhh hhhh */
+ {MOV_w_A, 4,17,17,L0|L1}, /* 79: 0111 0000 0111 1001 llll llll hhhh hhhh */
+ {MOV_w_B, 4,17,17,L0|L1}, /* 7a: 0111 0000 0111 1010 llll llll hhhh hhhh */
+ {MOV_w_C, 4,17,17,L0|L1}, /* 7b: 0111 0000 0111 1011 llll llll hhhh hhhh */
+ {MOV_w_D, 4,17,17,L0|L1}, /* 7c: 0111 0000 0111 1100 llll llll hhhh hhhh */
+ {MOV_w_E, 4,17,17,L0|L1}, /* 7d: 0111 0000 0111 1101 llll llll hhhh hhhh */
+ {MOV_w_H, 4,17,17,L0|L1}, /* 7e: 0111 0000 0111 1110 llll llll hhhh hhhh */
+ {MOV_w_L, 4,17,17,L0|L1}, /* 7f: 0111 0000 0111 1111 llll llll hhhh hhhh */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 80: 0111 0000 1000 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 81: 0111 0000 1000 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 82: 0111 0000 1000 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 83: 0111 0000 1000 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 84: 0111 0000 1000 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 85: 0111 0000 1000 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 86: 0111 0000 1000 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 87: 0111 0000 1000 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 88: 0111 0000 1000 1000 */
+ {ANAX_B, 2,11,11,L0|L1}, /* 89: 0111 0000 1000 1001 */
+ {ANAX_D, 2,11,11,L0|L1}, /* 8a: 0111 0000 1000 1010 */
+ {ANAX_H, 2,11,11,L0|L1}, /* 8b: 0111 0000 1000 1011 */
+ {ANAX_Dp, 2,11,11,L0|L1}, /* 8c: 0111 0000 1000 1100 */
+ {ANAX_Hp, 2,11,11,L0|L1}, /* 8d: 0111 0000 1000 1101 */
+ {ANAX_Dm, 2,11,11,L0|L1}, /* 8e: 0111 0000 1000 1110 */
+ {ANAX_Hm, 2,11,11,L0|L1}, /* 8f: 0111 0000 1000 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 90: 0111 0000 1001 0000 */
+ {XRAX_B, 2,11,11,L0|L1}, /* 91: 0111 0000 1001 0001 */
+ {XRAX_D, 2,11,11,L0|L1}, /* 92: 0111 0000 1001 0010 */
+ {XRAX_H, 2,11,11,L0|L1}, /* 93: 0111 0000 1001 0011 */
+ {XRAX_Dp, 2,11,11,L0|L1}, /* 94: 0111 0000 1001 0100 */
+ {XRAX_Hp, 2,11,11,L0|L1}, /* 95: 0111 0000 1001 0101 */
+ {XRAX_Dm, 2,11,11,L0|L1}, /* 96: 0111 0000 1001 0110 */
+ {XRAX_Hm, 2,11,11,L0|L1}, /* 97: 0111 0000 1001 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 98: 0111 0000 1001 1000 */
+// orax added, timings not verified
+ {ORAX_B, 2,11, 8,L0|L1}, /* 99: 0111 0000 1001 1001 */
+ {ORAX_D, 2,11, 8,L0|L1}, /* 9a: 0111 0000 1001 1010 */
+ {ORAX_H, 2,11, 8,L0|L1}, /* 9b: 0111 0000 1001 1011 */
+ {ORAX_Dp, 2,11, 8,L0|L1}, /* 9c: 0111 0000 1001 1100 */
+ {ORAX_Hp, 2,11, 8,L0|L1}, /* 9d: 0111 0000 1001 1101 */
+ {ORAX_Dm, 2,11, 8,L0|L1}, /* 9e: 0111 0000 1001 1110 */
+ {ORAX_Hm, 2,11, 8,L0|L1}, /* 9f: 0111 0000 1001 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* a0: 0111 0000 1010 0000 */
+ {ADDNCX_B, 2,11, 8,L0|L1}, /* a1: 0111 0000 1010 0001 */
+ {ADDNCX_D, 2,11, 8,L0|L1}, /* a2: 0111 0000 1010 0010 */
+ {ADDNCX_H, 2,11, 8,L0|L1}, /* a3: 0111 0000 1010 0011 */
+ {ADDNCX_Dp, 2,11, 8,L0|L1}, /* a4: 0111 0000 1010 0100 */
+ {ADDNCX_Hp, 2,11, 8,L0|L1}, /* a5: 0111 0000 1010 0101 */
+ {ADDNCX_Dm, 2,11, 8,L0|L1}, /* a6: 0111 0000 1010 0110 */
+ {ADDNCX_Hm, 2,11, 8,L0|L1}, /* a7: 0111 0000 1010 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a8: 0111 0000 1010 1000 */
+ {GTAX_B, 2,11,11,L0|L1}, /* a9: 0111 0000 1010 1001 */
+ {GTAX_D, 2,11,11,L0|L1}, /* aa: 0111 0000 1010 1010 */
+ {GTAX_H, 2,11,11,L0|L1}, /* ab: 0111 0000 1010 1011 */
+ {GTAX_Dp, 2,11,11,L0|L1}, /* ac: 0111 0000 1010 1100 */
+ {GTAX_Hp, 2,11,11,L0|L1}, /* ad: 0111 0000 1010 1101 */
+ {GTAX_Dm, 2,11,11,L0|L1}, /* ae: 0111 0000 1010 1110 */
+ {GTAX_Hm, 2,11,11,L0|L1}, /* af: 0111 0000 1010 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* b0: 0111 0000 1011 0000 */
+ {SUBNBX_B, 2,11,11,L0|L1}, /* b1: 0111 0000 1011 0001 */
+ {SUBNBX_D, 2,11,11,L0|L1}, /* b2: 0111 0000 1011 0010 */
+ {SUBNBX_H, 2,11,11,L0|L1}, /* b3: 0111 0000 1011 0011 */
+ {SUBNBX_Dp, 2,11,11,L0|L1}, /* b4: 0111 0000 1011 0100 */
+ {SUBNBX_Hp, 2,11,11,L0|L1}, /* b5: 0111 0000 1011 0101 */
+ {SUBNBX_Dm, 2,11,11,L0|L1}, /* b6: 0111 0000 1011 0110 */
+ {SUBNBX_Hm, 2,11,11,L0|L1}, /* b7: 0111 0000 1011 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b8: 0111 0000 1011 1000 */
+ {LTAX_B, 2,11,11,L0|L1}, /* b9: 0111 0000 1011 1001 */
+ {LTAX_D, 2,11,11,L0|L1}, /* ba: 0111 0000 1011 1010 */
+ {LTAX_H, 2,11,11,L0|L1}, /* bb: 0111 0000 1011 1011 */
+ {LTAX_Dp, 2,11,11,L0|L1}, /* bc: 0111 0000 1011 1100 */
+ {LTAX_Hp, 2,11,11,L0|L1}, /* bd: 0111 0000 1011 1101 */
+ {LTAX_Dm, 2,11,11,L0|L1}, /* be: 0111 0000 1011 1110 */
+ {LTAX_Hm, 2,11,11,L0|L1}, /* bf: 0111 0000 1011 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* c0: 0111 0000 1100 0000 */
+ {ADDX_B, 2,11, 8,L0|L1}, /* c1: 0111 0000 1100 0001 */
+ {ADDX_D, 2,11, 8,L0|L1}, /* c2: 0111 0000 1100 0010 */
+ {ADDX_H, 2,11, 8,L0|L1}, /* c3: 0111 0000 1100 0011 */
+ {ADDX_Dp, 2,11, 8,L0|L1}, /* c4: 0111 0000 1100 0100 */
+ {ADDX_Hp, 2,11, 8,L0|L1}, /* c5: 0111 0000 1100 0101 */
+ {ADDX_Dm, 2,11, 8,L0|L1}, /* c6: 0111 0000 1100 0110 */
+ {ADDX_Hm, 2,11, 8,L0|L1}, /* c7: 0111 0000 1100 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* c8: 0111 0000 1100 1000 */
+ {ONAX_B, 2,11, 8,L0|L1}, /* c9: 0111 0000 1100 1001 */
+ {ONAX_D, 2,11, 8,L0|L1}, /* ca: 0111 0000 1100 1010 */
+ {ONAX_H, 2,11, 8,L0|L1}, /* cb: 0111 0000 1100 1011 */
+ {ONAX_Dp, 2,11, 8,L0|L1}, /* cc: 0111 0000 1100 1100 */
+ {ONAX_Hp, 2,11, 8,L0|L1}, /* cd: 0111 0000 1100 1101 */
+ {ONAX_Dm, 2,11, 8,L0|L1}, /* ce: 0111 0000 1100 1110 */
+ {ONAX_Hm, 2,11, 8,L0|L1}, /* cf: 0111 0000 1100 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* d0: 0111 0000 1101 0000 */
+ {ADCX_B, 2,11, 8,L0|L1}, /* d1: 0111 0000 1101 0001 */
+ {ADCX_D, 2,11, 8,L0|L1}, /* d2: 0111 0000 1101 0010 */
+ {ADCX_H, 2,11, 8,L0|L1}, /* d3: 0111 0000 1101 0011 */
+ {ADCX_Dp, 2,11, 8,L0|L1}, /* d4: 0111 0000 1101 0100 */
+ {ADCX_Hp, 2,11, 8,L0|L1}, /* d5: 0111 0000 1101 0101 */
+ {ADCX_Dm, 2,11, 8,L0|L1}, /* d6: 0111 0000 1101 0110 */
+ {ADCX_Hm, 2,11, 8,L0|L1}, /* d7: 0111 0000 1101 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* d8: 0111 0000 1101 1000 */
+ {OFFAX_B, 2,11, 8,L0|L1}, /* d9: 0111 0000 1101 1001 */
+ {OFFAX_D, 2,11, 8,L0|L1}, /* da: 0111 0000 1101 1010 */
+ {OFFAX_H, 2,11, 8,L0|L1}, /* db: 0111 0000 1101 1011 */
+ {OFFAX_Dp, 2,11, 8,L0|L1}, /* dc: 0111 0000 1101 1100 */
+ {OFFAX_Hp, 2,11, 8,L0|L1}, /* dd: 0111 0000 1101 1101 */
+ {OFFAX_Dm, 2,11, 8,L0|L1}, /* de: 0111 0000 1101 1110 */
+ {OFFAX_Hm, 2,11, 8,L0|L1}, /* df: 0111 0000 1101 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* e0: 0111 0000 1110 0000 */
+ {SUBX_B, 2,11,11,L0|L1}, /* e1: 0111 0000 1110 0001 */
+ {SUBX_D, 2,11,11,L0|L1}, /* e2: 0111 0000 1110 0010 */
+ {SUBX_H, 2,11,11,L0|L1}, /* e3: 0111 0000 1110 0011 */
+ {SUBX_Dp, 2,11,11,L0|L1}, /* e4: 0111 0000 1110 0100 */
+ {SUBX_Hp, 2,11,11,L0|L1}, /* e5: 0111 0000 1110 0101 */
+ {SUBX_Dm, 2,11,11,L0|L1}, /* e6: 0111 0000 1110 0110 */
+ {SUBX_Hm, 2,11,11,L0|L1}, /* e7: 0111 0000 1110 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* e8: 0111 0000 1110 1000 */
+ {NEAX_B, 2,11,11,L0|L1}, /* e9: 0111 0000 1110 1001 */
+ {NEAX_D, 2,11,11,L0|L1}, /* ea: 0111 0000 1110 1010 */
+ {NEAX_H, 2,11,11,L0|L1}, /* eb: 0111 0000 1110 1011 */
+ {NEAX_Dp, 2,11,11,L0|L1}, /* ec: 0111 0000 1110 1100 */
+ {NEAX_Hp, 2,11,11,L0|L1}, /* ed: 0111 0000 1110 1101 */
+ {NEAX_Dm, 2,11,11,L0|L1}, /* ee: 0111 0000 1110 1110 */
+ {NEAX_Hm, 2,11,11,L0|L1}, /* ef: 0111 0000 1110 1111 */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* f0: 0111 0000 1111 0000 */
+ {SBBX_B, 2,11,11,L0|L1}, /* f1: 0111 0000 1111 0001 */
+ {SBBX_D, 2,11,11,L0|L1}, /* f2: 0111 0000 1111 0010 */
+ {SBBX_H, 2,11,11,L0|L1}, /* f3: 0111 0000 1111 0011 */
+ {SBBX_Dp, 2,11,11,L0|L1}, /* f4: 0111 0000 1111 0100 */
+ {SBBX_Hp, 2,11,11,L0|L1}, /* f5: 0111 0000 1111 0101 */
+ {SBBX_Dm, 2,11,11,L0|L1}, /* f6: 0111 0000 1111 0110 */
+ {SBBX_Hm, 2,11,11,L0|L1}, /* f7: 0111 0000 1111 0111 */
+ {illegal2, 2, 8, 8,L0|L1}, /* f8: 0111 0000 1111 1000 */
+ {EQAX_B, 2,11,11,L0|L1}, /* f9: 0111 0000 1111 1001 */
+ {EQAX_D, 2,11,11,L0|L1}, /* fa: 0111 0000 1111 1010 */
+ {EQAX_H, 2,11,11,L0|L1}, /* fb: 0111 0000 1111 1011 */
+ {EQAX_Dp, 2,11,11,L0|L1}, /* fc: 0111 0000 1111 1100 */
+ {EQAX_Hp, 2,11,11,L0|L1}, /* fd: 0111 0000 1111 1101 */
+ {EQAX_Dm, 2,11,11,L0|L1}, /* fe: 0111 0000 1111 1110 */
+ {EQAX_Hm, 2,11,11,L0|L1} /* ff: 0111 0000 1111 1111 */
+};
+
+/* prefix 74 */
+static const struct opcode_s op74[256] =
+{
+ {illegal2, 2, 8, 8,L0|L1}, /* 00: 0111 0100 0000 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 01: 0111 0100 0000 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 02: 0111 0100 0000 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 03: 0111 0100 0000 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 04: 0111 0100 0000 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 05: 0111 0100 0000 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 06: 0111 0100 0000 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 07: 0111 0100 0000 0111 */
+ {ANI_V_xx, 3,11,11,L0|L1}, /* 08: 0111 0100 0000 1000 xxxx xxxx */
+ {ANI_A_xx, 3,11,11,L0|L1}, /* 09: 0111 0100 0000 1001 xxxx xxxx */
+ {ANI_B_xx, 3,11,11,L0|L1}, /* 0a: 0111 0100 0000 1010 xxxx xxxx */
+ {ANI_C_xx, 3,11,11,L0|L1}, /* 0b: 0111 0100 0000 1011 xxxx xxxx */
+ {ANI_D_xx, 3,11,11,L0|L1}, /* 0c: 0111 0100 0000 1100 xxxx xxxx */
+ {ANI_E_xx, 3,11,11,L0|L1}, /* 0d: 0111 0100 0000 1101 xxxx xxxx */
+ {ANI_H_xx, 3,11,11,L0|L1}, /* 0e: 0111 0100 0000 1110 xxxx xxxx */
+ {ANI_L_xx, 3,11,11,L0|L1}, /* 0f: 0111 0100 0000 1111 xxxx xxxx */
+
+ {XRI_V_xx, 3,11,11,L0|L1}, /* 10: 0111 0100 0001 0000 xxxx xxxx */
+ {XRI_A_xx, 3,11,11,L0|L1}, /* 11: 0111 0100 0001 0001 xxxx xxxx */
+ {XRI_B_xx, 3,11,11,L0|L1}, /* 12: 0111 0100 0001 0010 xxxx xxxx */
+ {XRI_C_xx, 3,11,11,L0|L1}, /* 13: 0111 0100 0001 0011 xxxx xxxx */
+ {XRI_D_xx, 3,11,11,L0|L1}, /* 14: 0111 0100 0001 0100 xxxx xxxx */
+ {XRI_E_xx, 3,11,11,L0|L1}, /* 15: 0111 0100 0001 0101 xxxx xxxx */
+ {XRI_H_xx, 3,11,11,L0|L1}, /* 16: 0111 0100 0001 0110 xxxx xxxx */
+ {XRI_L_xx, 3,11,11,L0|L1}, /* 17: 0111 0100 0001 0111 xxxx xxxx */
+ {ORI_V_xx, 3,11,11,L0|L1}, /* 18: 0111 0100 0001 1000 xxxx xxxx */
+ {ORI_A_xx, 3,11,11,L0|L1}, /* 19: 0111 0100 0001 1001 xxxx xxxx */
+ {ORI_B_xx, 3,11,11,L0|L1}, /* 1a: 0111 0100 0001 1010 xxxx xxxx */
+ {ORI_C_xx, 3,11,11,L0|L1}, /* 1b: 0111 0100 0001 1011 xxxx xxxx */
+ {ORI_D_xx, 3,11,11,L0|L1}, /* 1c: 0111 0100 0001 1100 xxxx xxxx */
+ {ORI_E_xx, 3,11,11,L0|L1}, /* 1d: 0111 0100 0001 1101 xxxx xxxx */
+ {ORI_H_xx, 3,11,11,L0|L1}, /* 1e: 0111 0100 0001 1110 xxxx xxxx */
+ {ORI_L_xx, 3,11,11,L0|L1}, /* 1f: 0111 0100 0001 1111 xxxx xxxx */
+
+ {ADINC_V_xx, 3,11,11,L0|L1}, /* 20: 0111 0100 0010 0000 xxxx xxxx */
+ {ADINC_A_xx, 3,11,11,L0|L1}, /* 21: 0111 0100 0010 0001 xxxx xxxx */
+ {ADINC_B_xx, 3,11,11,L0|L1}, /* 22: 0111 0100 0010 0010 xxxx xxxx */
+ {ADINC_C_xx, 3,11,11,L0|L1}, /* 23: 0111 0100 0010 0011 xxxx xxxx */
+ {ADINC_D_xx, 3,11,11,L0|L1}, /* 24: 0111 0100 0010 0100 xxxx xxxx */
+ {ADINC_E_xx, 3,11,11,L0|L1}, /* 25: 0111 0100 0010 0101 xxxx xxxx */
+ {ADINC_H_xx, 3,11,11,L0|L1}, /* 26: 0111 0100 0010 0110 xxxx xxxx */
+ {ADINC_L_xx, 3,11,11,L0|L1}, /* 27: 0111 0100 0010 0111 xxxx xxxx */
+ {GTI_V_xx, 3,11,11,L0|L1}, /* 28: 0111 0100 0010 1000 xxxx xxxx */
+ {GTI_A_xx, 3,11,11,L0|L1}, /* 29: 0111 0100 0010 1001 xxxx xxxx */
+ {GTI_B_xx, 3,11,11,L0|L1}, /* 2a: 0111 0100 0010 1010 xxxx xxxx */
+ {GTI_C_xx, 3,11,11,L0|L1}, /* 2b: 0111 0100 0010 1011 xxxx xxxx */
+ {GTI_D_xx, 3,11,11,L0|L1}, /* 2c: 0111 0100 0010 1100 xxxx xxxx */
+ {GTI_E_xx, 3,11,11,L0|L1}, /* 2d: 0111 0100 0010 1101 xxxx xxxx */
+ {GTI_H_xx, 3,11,11,L0|L1}, /* 2e: 0111 0100 0010 1110 xxxx xxxx */
+ {GTI_L_xx, 3,11,11,L0|L1}, /* 2f: 0111 0100 0010 1111 xxxx xxxx */
+
+ {SUINB_V_xx, 3,11,11,L0|L1}, /* 30: 0111 0100 0011 0000 xxxx xxxx */
+ {SUINB_A_xx, 3,11,11,L0|L1}, /* 31: 0111 0100 0011 0001 xxxx xxxx */
+ {SUINB_B_xx, 3,11,11,L0|L1}, /* 32: 0111 0100 0011 0010 xxxx xxxx */
+ {SUINB_C_xx, 3,11,11,L0|L1}, /* 33: 0111 0100 0011 0011 xxxx xxxx */
+ {SUINB_D_xx, 3,11,11,L0|L1}, /* 34: 0111 0100 0011 0100 xxxx xxxx */
+ {SUINB_E_xx, 3,11,11,L0|L1}, /* 35: 0111 0100 0011 0101 xxxx xxxx */
+ {SUINB_H_xx, 3,11,11,L0|L1}, /* 36: 0111 0100 0011 0110 xxxx xxxx */
+ {SUINB_L_xx, 3,11,11,L0|L1}, /* 37: 0111 0100 0011 0111 xxxx xxxx */
+ {LTI_V_xx, 3,11,11,L0|L1}, /* 38: 0111 0100 0011 1000 xxxx xxxx */
+ {LTI_A_xx, 3,11,11,L0|L1}, /* 39: 0111 0100 0011 1001 xxxx xxxx */
+ {LTI_B_xx, 3,11,11,L0|L1}, /* 3a: 0111 0100 0011 1010 xxxx xxxx */
+ {LTI_C_xx, 3,11,11,L0|L1}, /* 3b: 0111 0100 0011 1011 xxxx xxxx */
+ {LTI_D_xx, 3,11,11,L0|L1}, /* 3c: 0111 0100 0011 1100 xxxx xxxx */
+ {LTI_E_xx, 3,11,11,L0|L1}, /* 3d: 0111 0100 0011 1101 xxxx xxxx */
+ {LTI_H_xx, 3,11,11,L0|L1}, /* 3e: 0111 0100 0011 1110 xxxx xxxx */
+ {LTI_L_xx, 3,11,11,L0|L1}, /* 3f: 0111 0100 0011 1111 xxxx xxxx */
+
+ {ADI_V_xx, 3,11,11,L0|L1}, /* 40: 0111 0100 0100 0000 xxxx xxxx */
+ {ADI_A_xx, 3,11,11,L0|L1}, /* 41: 0111 0100 0100 0001 xxxx xxxx */
+ {ADI_B_xx, 3,11,11,L0|L1}, /* 42: 0111 0100 0100 0010 xxxx xxxx */
+ {ADI_C_xx, 3,11,11,L0|L1}, /* 43: 0111 0100 0100 0011 xxxx xxxx */
+ {ADI_D_xx, 3,11,11,L0|L1}, /* 44: 0111 0100 0100 0100 xxxx xxxx */
+ {ADI_E_xx, 3,11,11,L0|L1}, /* 45: 0111 0100 0100 0101 xxxx xxxx */
+ {ADI_H_xx, 3,11,11,L0|L1}, /* 46: 0111 0100 0100 0110 xxxx xxxx */
+ {ADI_L_xx, 3,11,11,L0|L1}, /* 47: 0111 0100 0100 0111 xxxx xxxx */
+ {ONI_V_xx, 3,11,11,L0|L1}, /* 48: 0111 0100 0100 1000 xxxx xxxx */
+ {ONI_A_xx, 3,11,11,L0|L1}, /* 49: 0111 0100 0100 1001 xxxx xxxx */
+ {ONI_B_xx, 3,11,11,L0|L1}, /* 4a: 0111 0100 0100 1010 xxxx xxxx */
+ {ONI_C_xx, 3,11,11,L0|L1}, /* 4b: 0111 0100 0100 1011 xxxx xxxx */
+ {ONI_D_xx, 3,11,11,L0|L1}, /* 4c: 0111 0100 0100 1100 xxxx xxxx */
+ {ONI_E_xx, 3,11,11,L0|L1}, /* 4d: 0111 0100 0100 1101 xxxx xxxx */
+ {ONI_H_xx, 3,11,11,L0|L1}, /* 4e: 0111 0100 0100 1110 xxxx xxxx */
+ {ONI_L_xx, 3,11,11,L0|L1}, /* 4f: 0111 0100 0100 1111 xxxx xxxx */
+
+ {ACI_V_xx, 3,11,11,L0|L1}, /* 50: 0111 0100 0101 0000 xxxx xxxx */
+ {ACI_A_xx, 3,11,11,L0|L1}, /* 51: 0111 0100 0101 0001 xxxx xxxx */
+ {ACI_B_xx, 3,11,11,L0|L1}, /* 52: 0111 0100 0101 0010 xxxx xxxx */
+ {ACI_C_xx, 3,11,11,L0|L1}, /* 53: 0111 0100 0101 0011 xxxx xxxx */
+ {ACI_D_xx, 3,11,11,L0|L1}, /* 54: 0111 0100 0101 0100 xxxx xxxx */
+ {ACI_E_xx, 3,11,11,L0|L1}, /* 55: 0111 0100 0101 0101 xxxx xxxx */
+ {ACI_H_xx, 3,11,11,L0|L1}, /* 56: 0111 0100 0101 0110 xxxx xxxx */
+ {ACI_L_xx, 3,11,11,L0|L1}, /* 57: 0111 0100 0101 0111 xxxx xxxx */
+ {OFFI_V_xx, 3,11,11,L0|L1}, /* 58: 0111 0100 0101 1000 xxxx xxxx */
+ {OFFI_A_xx, 3,11,11,L0|L1}, /* 59: 0111 0100 0101 1001 xxxx xxxx */
+ {OFFI_B_xx, 3,11,11,L0|L1}, /* 5a: 0111 0100 0101 1010 xxxx xxxx */
+ {OFFI_C_xx, 3,11,11,L0|L1}, /* 5b: 0111 0100 0101 1011 xxxx xxxx */
+ {OFFI_D_xx, 3,11,11,L0|L1}, /* 5c: 0111 0100 0101 1100 xxxx xxxx */
+ {OFFI_E_xx, 3,11,11,L0|L1}, /* 5d: 0111 0100 0101 1101 xxxx xxxx */
+ {OFFI_H_xx, 3,11,11,L0|L1}, /* 5e: 0111 0100 0101 1110 xxxx xxxx */
+ {OFFI_L_xx, 3,11,11,L0|L1}, /* 5f: 0111 0100 0101 1111 xxxx xxxx */
+
+ {SUI_V_xx, 3,11,11,L0|L1}, /* 60: 0111 0100 0110 0000 xxxx xxxx */
+ {SUI_A_xx, 3,11,11,L0|L1}, /* 61: 0111 0100 0110 0001 xxxx xxxx */
+ {SUI_B_xx, 3,11,11,L0|L1}, /* 62: 0111 0100 0110 0010 xxxx xxxx */
+ {SUI_C_xx, 3,11,11,L0|L1}, /* 63: 0111 0100 0110 0011 xxxx xxxx */
+ {SUI_D_xx, 3,11,11,L0|L1}, /* 64: 0111 0100 0110 0100 xxxx xxxx */
+ {SUI_E_xx, 3,11,11,L0|L1}, /* 65: 0111 0100 0110 0101 xxxx xxxx */
+ {SUI_H_xx, 3,11,11,L0|L1}, /* 66: 0111 0100 0110 0110 xxxx xxxx */
+ {SUI_L_xx, 3,11,11,L0|L1}, /* 67: 0111 0100 0110 0111 xxxx xxxx */
+ {NEI_V_xx, 3,11,11,L0|L1}, /* 68: 0111 0100 0110 1000 xxxx xxxx */
+ {NEI_A_xx, 3,11,11,L0|L1}, /* 69: 0111 0100 0110 1001 xxxx xxxx */
+ {NEI_B_xx, 3,11,11,L0|L1}, /* 6a: 0111 0100 0110 1010 xxxx xxxx */
+ {NEI_C_xx, 3,11,11,L0|L1}, /* 6b: 0111 0100 0110 1011 xxxx xxxx */
+ {NEI_D_xx, 3,11,11,L0|L1}, /* 6c: 0111 0100 0110 1100 xxxx xxxx */
+ {NEI_E_xx, 3,11,11,L0|L1}, /* 6d: 0111 0100 0110 1101 xxxx xxxx */
+ {NEI_H_xx, 3,11,11,L0|L1}, /* 6e: 0111 0100 0110 1110 xxxx xxxx */
+ {NEI_L_xx, 3,11,11,L0|L1}, /* 6f: 0111 0100 0110 1111 xxxx xxxx */
+
+ {SBI_V_xx, 3,11,11,L0|L1}, /* 70: 0111 0100 0111 0000 xxxx xxxx */
+ {SBI_A_xx, 3,11,11,L0|L1}, /* 71: 0111 0100 0111 0001 xxxx xxxx */
+ {SBI_B_xx, 3,11,11,L0|L1}, /* 72: 0111 0100 0111 0010 xxxx xxxx */
+ {SBI_C_xx, 3,11,11,L0|L1}, /* 73: 0111 0100 0111 0011 xxxx xxxx */
+ {SBI_D_xx, 3,11,11,L0|L1}, /* 74: 0111 0100 0111 0100 xxxx xxxx */
+ {SBI_E_xx, 3,11,11,L0|L1}, /* 75: 0111 0100 0111 0101 xxxx xxxx */
+ {SBI_H_xx, 3,11,11,L0|L1}, /* 76: 0111 0100 0111 0110 xxxx xxxx */
+ {SBI_L_xx, 3,11,11,L0|L1}, /* 77: 0111 0100 0111 0111 xxxx xxxx */
+ {EQI_V_xx, 3,11,11,L0|L1}, /* 78: 0111 0100 0111 1000 xxxx xxxx */
+ {EQI_A_xx, 3,11,11,L0|L1}, /* 79: 0111 0100 0111 1001 xxxx xxxx */
+ {EQI_B_xx, 3,11,11,L0|L1}, /* 7a: 0111 0100 0111 1010 xxxx xxxx */
+ {EQI_C_xx, 3,11,11,L0|L1}, /* 7b: 0111 0100 0111 1011 xxxx xxxx */
+ {EQI_D_xx, 3,11,11,L0|L1}, /* 7c: 0111 0100 0111 1100 xxxx xxxx */
+ {EQI_E_xx, 3,11,11,L0|L1}, /* 7d: 0111 0100 0111 1101 xxxx xxxx */
+ {EQI_H_xx, 3,11,11,L0|L1}, /* 7e: 0111 0100 0111 1110 xxxx xxxx */
+ {EQI_L_xx, 3,11,11,L0|L1}, /* 7f: 0111 0100 0111 1111 xxxx xxxx */
+
+ {illegal2, 2, 8, 8,L0|L1}, /* 80: 0111 0100 1000 0000 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 81: 0111 0100 1000 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 82: 0111 0100 1000 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 83: 0111 0100 1000 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 84: 0111 0100 1000 0100 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 85: 0111 0100 1000 0101 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 86: 0111 0100 1000 0110 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 87: 0111 0100 1000 0111 */
+ {ANAW_wa, 3,14,11,L0|L1}, /* 88: 0111 0100 1000 1000 oooo oooo */
+ {illegal2, 2, 8, 8,L0|L1}, /* 89: 0111 0100 1000 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 8a: 0111 0100 1000 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 8b: 0111 0100 1000 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 8c: 0111 0100 1000 1100 */
+ {DAN_EA_BC, 2,11,11,L0|L1}, /* 8d: 0111 0100 1000 1101 */
+ {DAN_EA_DE, 2,11,11,L0|L1}, /* 8e: 0111 0100 1000 1110 */
+ {DAN_EA_HL, 2,11,11,L0|L1}, /* 8f: 0111 0100 1000 1111 */
+
+ {XRAW_wa, 3,14,11,L0|L1}, /* 90: 0111 0100 1001 0000 oooo oooo */
+ {illegal2, 2, 8, 8,L0|L1}, /* 91: 0111 0100 1001 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 92: 0111 0100 1001 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 93: 0111 0100 1001 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 94: 0111 0100 1001 0100 */
+ {DXR_EA_BC, 2,11,11,L0|L1}, /* 95: 0111 0100 1001 0101 */
+ {DXR_EA_DE, 2,11,11,L0|L1}, /* 96: 0111 0100 1001 0110 */
+ {DXR_EA_HL, 2,11,11,L0|L1}, /* 97: 0111 0100 1001 0111 */
+ {ORAW_wa, 3,14,11,L0|L1}, /* 98: 0111 0100 1001 1000 oooo oooo */
+ {illegal2, 2, 8, 8,L0|L1}, /* 99: 0111 0100 1001 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 9a: 0111 0100 1001 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 9b: 0111 0100 1001 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* 9c: 0111 0100 1001 1100 */
+ {DOR_EA_BC, 2,11,11,L0|L1}, /* 9d: 0111 0100 1001 1101 */
+ {DOR_EA_DE, 2,11,11,L0|L1}, /* 9e: 0111 0100 1001 1110 */
+ {DOR_EA_HL, 2,11,11,L0|L1}, /* 9f: 0111 0100 1001 1111 */
+
+ {ADDNCW_wa, 3,14,11,L0|L1}, /* a0: 0111 0100 1010 0000 oooo oooo */
+ {illegal2, 2, 8, 8,L0|L1}, /* a1: 0111 0100 1010 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a2: 0111 0100 1010 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a3: 0111 0100 1010 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* a4: 0111 0100 1010 0100 */
+ {DADDNC_EA_BC, 2,11,11,L0|L1}, /* a5: 0111 0100 1010 0101 */
+ {DADDNC_EA_DE, 2,11,11,L0|L1}, /* a6: 0111 0100 1010 0110 */
+ {DADDNC_EA_HL, 2,11,11,L0|L1}, /* a7: 0111 0100 1010 0111 */
+ {GTAW_wa, 3,14,11,L0|L1}, /* a8: 0111 0100 1010 1000 oooo oooo */
+ {illegal2, 2, 8, 8,L0|L1}, /* a9: 0111 0100 1010 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* aa: 0111 0100 1010 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ab: 0111 0100 1010 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ac: 0111 0100 1010 1100 */
+ {DGT_EA_BC, 2,11,11,L0|L1}, /* ad: 0111 0100 1010 1101 */
+ {DGT_EA_DE, 2,11,11,L0|L1}, /* ae: 0111 0100 1010 1110 */
+ {DGT_EA_HL, 2,11,11,L0|L1}, /* af: 0111 0100 1010 1111 */
+
+ {SUBNBW_wa, 3,14,11,L0|L1}, /* b0: 0111 0100 1011 0000 oooo oooo */
+ {illegal2, 2, 8, 8,L0|L1}, /* b1: 0111 0100 1011 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b2: 0111 0100 1011 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b3: 0111 0100 1011 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* b4: 0111 0100 1011 0100 */
+ {DSUBNB_EA_BC, 2,11,11,L0|L1}, /* b5: 0111 0100 1011 0101 */
+ {DSUBNB_EA_DE, 2,11,11,L0|L1}, /* b6: 0111 0100 1011 0110 */
+ {DSUBNB_EA_HL, 2,11,11,L0|L1}, /* b7: 0111 0100 1011 0111 */
+ {LTAW_wa, 3,14,11,L0|L1}, /* b8: 0111 0100 1011 1000 oooo oooo */
+ {illegal2, 2, 8, 8,L0|L1}, /* b9: 0111 0100 1011 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ba: 0111 0100 1011 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* bb: 0111 0100 1011 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* bc: 0111 0100 1011 1100 */
+ {DLT_EA_BC, 2,11,11,L0|L1}, /* bd: 0111 0100 1011 1101 */
+ {DLT_EA_DE, 2,11,11,L0|L1}, /* be: 0111 0100 1011 1110 */
+ {DLT_EA_HL, 2,11,11,L0|L1}, /* bf: 0111 0100 1011 1111 */
+
+ {ADDW_wa, 3,14,11,L0|L1}, /* c0: 0111 0100 1100 0000 oooo oooo */
+ {illegal2, 2, 8, 8,L0|L1}, /* c1: 0111 0100 1100 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* c2: 0111 0100 1100 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* c3: 0111 0100 1100 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* c4: 0111 0100 1100 0100 */
+ {DADD_EA_BC, 2,11,11,L0|L1}, /* c5: 0111 0100 1100 0101 */
+ {DADD_EA_DE, 2,11,11,L0|L1}, /* c6: 0111 0100 1100 0110 */
+ {DADD_EA_HL, 2,11,11,L0|L1}, /* c7: 0111 0100 1100 0111 */
+ {ONAW_wa, 3,14,11,L0|L1}, /* c8: 0111 0100 1100 1000 oooo oooo */
+ {illegal2, 2, 8, 8,L0|L1}, /* c9: 0111 0100 1100 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ca: 0111 0100 1100 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* cb: 0111 0100 1100 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* cc: 0111 0100 1100 1100 */
+ {DON_EA_BC, 2,11,11,L0|L1}, /* cd: 0111 0100 1100 1101 */
+ {DON_EA_DE, 2,11,11,L0|L1}, /* ce: 0111 0100 1100 1110 */
+ {DON_EA_HL, 2,11,11,L0|L1}, /* cf: 0111 0100 1100 1111 */
+
+ {ADCW_wa, 3,14,11,L0|L1}, /* d0: 0111 0100 1101 0000 oooo oooo */
+ {illegal2, 2, 8, 8,L0|L1}, /* d1: 0111 0100 1101 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* d2: 0111 0100 1101 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* d3: 0111 0100 1101 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* d4: 0111 0100 1101 0100 */
+ {DADC_EA_BC, 2,11,11,L0|L1}, /* d5: 0111 0100 1101 0101 */
+ {DADC_EA_DE, 2,11,11,L0|L1}, /* d6: 0111 0100 1101 0110 */
+ {DADC_EA_HL, 2,11,11,L0|L1}, /* d7: 0111 0100 1101 0111 */
+ {OFFAW_wa, 3,14,11,L0|L1}, /* d8: 0111 0100 1101 1000 oooo oooo */
+ {illegal2, 2, 8, 8,L0|L1}, /* d9: 0111 0100 1101 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* da: 0111 0100 1101 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* db: 0111 0100 1101 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* dc: 0111 0100 1101 1100 */
+ {DOFF_EA_BC, 2,11,11,L0|L1}, /* dd: 0111 0100 1101 1101 */
+ {DOFF_EA_DE, 2,11,11,L0|L1}, /* de: 0111 0100 1101 1110 */
+ {DOFF_EA_HL, 2,11,11,L0|L1}, /* df: 0111 0100 1101 1111 */
+
+ {SUBW_wa, 3,14,11,L0|L1}, /* e0: 0111 0100 1110 0000 oooo oooo */
+ {illegal2, 2, 8, 8,L0|L1}, /* e1: 0111 0100 1110 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* e2: 0111 0100 1110 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* e3: 0111 0100 1110 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* e4: 0111 0100 1110 0100 */
+ {DSUB_EA_BC, 2,11,11,L0|L1}, /* e5: 0111 0100 1110 0101 */
+ {DSUB_EA_DE, 2,11,11,L0|L1}, /* e6: 0111 0100 1110 0110 */
+ {DSUB_EA_HL, 2,11,11,L0|L1}, /* e7: 0111 0100 1110 0111 */
+ {NEAW_wa, 3,14,11,L0|L1}, /* e8: 0111 0100 1110 1000 oooo oooo */
+ {illegal2, 2, 8, 8,L0|L1}, /* e9: 0111 0100 1110 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ea: 0111 0100 1110 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* eb: 0111 0100 1110 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* ec: 0111 0100 1110 1100 */
+ {DNE_EA_BC, 2,11,11,L0|L1}, /* ed: 0111 0100 1110 1101 */
+ {DNE_EA_DE, 2,11,11,L0|L1}, /* ee: 0111 0100 1110 1110 */
+ {DNE_EA_HL, 2,11,11,L0|L1}, /* ef: 0111 0100 1110 1111 */
+
+ {SBBW_wa, 3,14,11,L0|L1}, /* f0: 0111 0100 1111 0000 oooo oooo */
+ {illegal2, 2, 8, 8,L0|L1}, /* f1: 0111 0100 1111 0001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* f2: 0111 0100 1111 0010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* f3: 0111 0100 1111 0011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* f4: 0111 0100 1111 0100 */
+ {DSBB_EA_BC, 2,11,11,L0|L1}, /* f5: 0111 0100 1111 0101 */
+ {DSBB_EA_DE, 2,11,11,L0|L1}, /* f6: 0111 0100 1111 0110 */
+ {DSBB_EA_HL, 2,11,11,L0|L1}, /* f7: 0111 0100 1111 0111 */
+ {EQAW_wa, 3,14,11,L0|L1}, /* f8: 0111 0100 1111 1000 oooo oooo */
+ {illegal2, 2, 8, 8,L0|L1}, /* f9: 0111 0100 1111 1001 */
+ {illegal2, 2, 8, 8,L0|L1}, /* fa: 0111 0100 1111 1010 */
+ {illegal2, 2, 8, 8,L0|L1}, /* fb: 0111 0100 1111 1011 */
+ {illegal2, 2, 8, 8,L0|L1}, /* fc: 0111 0100 1111 1100 */
+ {DEQ_EA_BC, 2,11,11,L0|L1}, /* fd: 0111 0100 1111 1101 */
+ {DEQ_EA_DE, 2,11,11,L0|L1}, /* fe: 0111 0100 1111 1110 */
+ {DEQ_EA_HL, 2,11,11,L0|L1} /* ff: 0111 0100 1111 1111 */
+};
+
+/* main opcodes */
+static const struct opcode_s opXX_7810[256] =
+{
+ {NOP, 1, 4, 4,L0|L1}, /* 00: 0000 0000 */
+ {LDAW_wa, 2,10,10,L0|L1}, /* 01: 0000 0001 oooo oooo */
+ {INX_SP, 1, 7, 7,L0|L1}, /* 02: 0000 0010 */
+ {DCX_SP, 1, 7, 7,L0|L1}, /* 03: 0000 0011 */
+ {LXI_S_w, 3,10,10,L0|L1}, /* 04: 0000 0100 llll llll hhhh hhhh */
+ {ANIW_wa_xx, 3,19,19,L0|L1}, /* 05: 0000 0101 oooo oooo xxxx xxxx */
+ {illegal, 1, 4, 4,L0|L1}, /* 06: */
+ {ANI_A_xx, 2, 7, 7,L0|L1}, /* 07: 0000 0111 xxxx xxxx */
+ {MOV_A_EAH, 1, 4, 4,L0|L1}, /* 08: 0000 1000 */
+ {MOV_A_EAL, 1, 4, 4,L0|L1}, /* 09: 0000 1001 */
+ {MOV_A_B, 1, 4, 4,L0|L1}, /* 0a: 0000 1010 */
+ {MOV_A_C, 1, 4, 4,L0|L1}, /* 0b: 0000 1011 */
+ {MOV_A_D, 1, 4, 4,L0|L1}, /* 0c: 0000 1100 */
+ {MOV_A_E, 1, 4, 4,L0|L1}, /* 0d: 0000 1101 */
+ {MOV_A_H, 1, 4, 4,L0|L1}, /* 0e: 0000 1110 */
+ {MOV_A_L, 1, 4, 4,L0|L1}, /* 0f: 0000 1111 */
+
+ {EXA, 1, 4, 4,L0|L1}, /* 10: 0001 0000 */
+ {EXX, 1, 4, 4,L0|L1}, /* 11: 0001 0001 */
+ {INX_BC, 1, 7, 7,L0|L1}, /* 12: 0001 0010 */
+ {DCX_BC, 1, 7, 7,L0|L1}, /* 13: 0001 0011 */
+ {LXI_B_w, 3,10,10,L0|L1}, /* 14: 0001 0100 llll llll hhhh hhhh */
+ {ORIW_wa_xx, 3,19,19,L0|L1}, /* 15: 0001 0101 oooo oooo xxxx xxxx */
+ {XRI_A_xx, 2, 7, 7,L0|L1}, /* 16: 0001 0110 xxxx xxxx */
+ {ORI_A_xx, 2, 7, 7,L0|L1}, /* 17: 0001 0111 xxxx xxxx */
+ {MOV_EAH_A, 1, 4, 4,L0|L1}, /* 18: 0001 1000 */
+ {MOV_EAL_A, 1, 4, 4,L0|L1}, /* 19: 0001 1001 */
+ {MOV_B_A, 1, 4, 4,L0|L1}, /* 1a: 0001 1010 */
+ {MOV_C_A, 1, 4, 4,L0|L1}, /* 1b: 0001 1011 */
+ {MOV_D_A, 1, 4, 4,L0|L1}, /* 1c: 0001 1100 */
+ {MOV_E_A, 1, 4, 4,L0|L1}, /* 1d: 0001 1101 */
+ {MOV_H_A, 1, 4, 4,L0|L1}, /* 1e: 0001 1110 */
+ {MOV_L_A, 1, 4, 4,L0|L1}, /* 1f: 0001 1111 */
+
+ {INRW_wa, 2,16,16,L0|L1}, /* 20: 0010 0000 oooo oooo */
+ {JB, 1, 4, 4,L0|L1}, /* 21: 0010 0001 */
+ {INX_DE, 1, 7, 7,L0|L1}, /* 22: 0010 0010 */
+ {DCX_DE, 1, 7, 7,L0|L1}, /* 23: 0010 0011 */
+ {LXI_D_w, 3,10,10,L0|L1}, /* 24: 0010 0100 llll llll hhhh hhhh */
+ {GTIW_wa_xx, 3,19,19,L0|L1}, /* 25: 0010 0101 oooo oooo xxxx xxxx */
+ {ADINC_A_xx, 2, 7, 7,L0|L1}, /* 26: 0010 0110 xxxx xxxx */
+ {GTI_A_xx, 2, 7, 7,L0|L1}, /* 27: 0010 0111 xxxx xxxx */
+ {illegal, 1, 4, 4,L0|L1}, /* 28: */
+ {LDAX_B, 2, 7, 7,L0|L1}, /* 29: 0010 1001 dddd dddd */
+ {LDAX_D, 2, 7, 7,L0|L1}, /* 2a: 0010 1010 dddd dddd */
+ {LDAX_H, 2, 7, 7,L0|L1}, /* 2b: 0010 1011 dddd dddd */
+ {LDAX_Dp, 2, 7, 7,L0|L1}, /* 2c: 0010 1100 dddd dddd */
+ {LDAX_Hp, 2, 7, 7,L0|L1}, /* 2d: 0010 1101 dddd dddd */
+ {LDAX_Dm, 2, 7, 7,L0|L1}, /* 2e: 0010 1110 dddd dddd */
+ {LDAX_Hm, 2, 7, 7,L0|L1}, /* 2f: 0010 1111 dddd dddd */
+
+ {DCRW_wa, 2,16,16,L0|L1}, /* 30: 0011 0000 oooo oooo */
+ {BLOCK, 1,13,13,L0|L1}, /* 31: 0011 0001 */ /* 7810 */
+ {INX_HL, 1, 7, 7,L0|L1}, /* 32: 0011 0010 */
+ {DCX_HL, 1, 7, 7,L0|L1}, /* 33: 0011 0011 */
+ {LXI_H_w, 3,10,10, L1}, /* 34: 0011 0100 llll llll hhhh hhhh */
+ {LTIW_wa_xx, 3,19,19,L0|L1}, /* 35: 0011 0101 oooo oooo xxxx xxxx */
+ {SUINB_A_xx, 2, 7, 7,L0|L1}, /* 36: 0011 0110 xxxx xxxx */
+ {LTI_A_xx, 2, 7, 7,L0|L1}, /* 37: 0011 0111 xxxx xxxx */
+ {illegal, 1, 4, 4,L0|L1}, /* 38: */
+ {STAX_B, 2, 7, 7,L0|L1}, /* 39: 0011 1001 dddd dddd */
+ {STAX_D, 2, 7, 7,L0|L1}, /* 3a: 0011 1010 dddd dddd */
+ {STAX_H, 2, 7, 7,L0|L1}, /* 3b: 0011 1011 dddd dddd */
+ {STAX_Dp, 2, 7, 7,L0|L1}, /* 3c: 0011 1100 dddd dddd */
+ {STAX_Hp, 2, 7, 7,L0|L1}, /* 3d: 0011 1101 dddd dddd */
+ {STAX_Dm, 2, 7, 7,L0|L1}, /* 3e: 0011 1110 dddd dddd */
+ {STAX_Hm, 2, 7, 7,L0|L1}, /* 3f: 0011 1111 dddd dddd */
+
+ {CALL_w, 3,16,16,L0|L1}, /* 40: 0100 0000 llll llll hhhh hhhh */
+ {INR_A, 1, 4, 4,L0|L1}, /* 41: 0100 0001 */
+ {INR_B, 1, 4, 4,L0|L1}, /* 42: 0100 0010 */
+ {INR_C, 1, 4, 4,L0|L1}, /* 43: 0100 0011 */
+ {LXI_EA_s, 3,10,10,L0|L1}, /* 44: 0100 0100 llll llll hhhh hhhh */
+ {ONIW_wa_xx, 3,19,19,L0|L1}, /* 45: 0100 0101 oooo oooo xxxx xxxx */
+ {ADI_A_xx, 2, 7, 7,L0|L1}, /* 46: 0100 0110 xxxx xxxx */
+ {ONI_A_xx, 2, 7, 7,L0|L1}, /* 47: 0100 0111 xxxx xxxx */
+ {PRE_48, 1, 0, 0,L0|L1}, /* 48: prefix */
+ {MVIX_BC_xx, 2,10,10,L0|L1}, /* 49: 0100 1001 xxxx xxxx */
+ {MVIX_DE_xx, 2,10,10,L0|L1}, /* 4a: 0100 1010 xxxx xxxx */
+ {MVIX_HL_xx, 2,10,10,L0|L1}, /* 4b: 0100 1011 xxxx xxxx */
+ {PRE_4C, 1, 0, 0,L0|L1}, /* 4c: prefix */
+ {PRE_4D, 1, 4, 4,L0|L1}, /* 4d: prefix */
+ {JRE, 2,10,10,L0|L1}, /* 4e: 0100 111d dddd dddd */
+ {JRE, 2,10,10,L0|L1}, /* 4f: 0100 111d dddd dddd */
+
+ {EXH, 1, 4, 4,L0|L1}, /* 50: 0101 0000 */ /* 7810 */
+ {DCR_A, 1, 4, 4,L0|L1}, /* 51: 0101 0001 */
+ {DCR_B, 1, 4, 4,L0|L1}, /* 52: 0101 0010 */
+ {DCR_C, 1, 4, 4,L0|L1}, /* 53: 0101 0011 */
+ {JMP_w, 3,10,10,L0|L1}, /* 54: 0101 0100 llll llll hhhh hhhh */
+ {OFFIW_wa_xx, 3,19,19,L0|L1}, /* 55: 0101 0101 oooo oooo xxxx xxxx */
+ {ACI_A_xx, 2, 7, 7,L0|L1}, /* 56: 0101 0110 xxxx xxxx */
+ {OFFI_A_xx, 2, 7, 7,L0|L1}, /* 57: 0101 0111 xxxx xxxx */
+ {BIT_0_wa, 2,10,10,L0|L1}, /* 58: 0101 1000 oooo oooo */ /* 7810 */
+ {BIT_1_wa, 2,10,10,L0|L1}, /* 59: 0101 1001 oooo oooo */ /* 7810 */
+ {BIT_2_wa, 2,10,10,L0|L1}, /* 5a: 0101 1010 oooo oooo */ /* 7810 */
+ {BIT_3_wa, 2,10,10,L0|L1}, /* 5b: 0101 1011 oooo oooo */ /* 7810 */
+ {BIT_4_wa, 2,10,10,L0|L1}, /* 5c: 0101 1100 oooo oooo */ /* 7810 */
+ {BIT_5_wa, 2,10,10,L0|L1}, /* 5d: 0101 1101 oooo oooo */ /* 7810 */
+ {BIT_6_wa, 2,10,10,L0|L1}, /* 5e: 0101 1110 oooo oooo */ /* 7810 */
+ {BIT_7_wa, 2,10,10,L0|L1}, /* 5f: 0101 1111 oooo oooo */ /* 7810 */
+
+ {PRE_60, 1, 0, 0,L0|L1}, /* 60: */
+ {DAA, 1, 4, 4,L0|L1}, /* 61: 0110 0001 */
+ {RETI, 1,13,13,L0|L1}, /* 62: 0110 0010 */
+ {STAW_wa, 2,10,10,L0|L1}, /* 63: 0110 0011 oooo oooo */
+ {PRE_64, 1, 0, 0,L0|L1}, /* 64: */
+ {NEIW_wa_xx, 3,19,19,L0|L1}, /* 65: 0110 0101 oooo oooo xxxx xxxx */
+ {SUI_A_xx, 2, 7, 7,L0|L1}, /* 66: 0110 0110 xxxx xxxx */
+ {NEI_A_xx, 2, 7, 7,L0|L1}, /* 67: 0110 0111 xxxx xxxx */
+ {MVI_V_xx, 2, 7, 7,L0|L1}, /* 68: 0110 1000 xxxx xxxx */
+ {MVI_A_xx, 2, 7, 7,L0 }, /* 69: 0110 1001 xxxx xxxx */
+ {MVI_B_xx, 2, 7, 7,L0|L1}, /* 6a: 0110 1010 xxxx xxxx */
+ {MVI_C_xx, 2, 7, 7,L0|L1}, /* 6b: 0110 1011 xxxx xxxx */
+ {MVI_D_xx, 2, 7, 7,L0|L1}, /* 6c: 0110 1100 xxxx xxxx */
+ {MVI_E_xx, 2, 7, 7,L0|L1}, /* 6d: 0110 1101 xxxx xxxx */
+ {MVI_H_xx, 2, 7, 7,L0|L1}, /* 6e: 0110 1110 xxxx xxxx */
+ {MVI_L_xx, 2, 7, 7, L1}, /* 6f: 0110 1111 xxxx xxxx */
+
+ {PRE_70, 1, 0, 0,L0|L1}, /* 70: */
+ {MVIW_wa_xx, 3,13,13,L0|L1}, /* 71: 0111 0001 oooo oooo xxxx xxxx */
+ {SOFTI, 1,16,16,L0|L1}, /* 72: 0111 0010 */
+ {illegal, 1, 0, 0,L0|L1}, /* 73: */
+ {PRE_74, 1, 0, 0,L0|L1}, /* 74: prefix */
+ {EQIW_wa_xx, 3,19,19,L0|L1}, /* 75: 0111 0101 oooo oooo xxxx xxxx */
+ {SBI_A_xx, 2, 7, 7,L0|L1}, /* 76: 0111 0110 xxxx xxxx */
+ {EQI_A_xx, 2, 7, 7,L0|L1}, /* 77: 0111 0111 xxxx xxxx */
+ {CALF, 2,13,13,L0|L1}, /* 78: 0111 1xxx xxxx xxxx */
+ {CALF, 2,13,13,L0|L1}, /* 79: 0111 1xxx xxxx xxxx */
+ {CALF, 2,13,13,L0|L1}, /* 7a: 0111 1xxx xxxx xxxx */
+ {CALF, 2,13,13,L0|L1}, /* 7b: 0111 1xxx xxxx xxxx */
+ {CALF, 2,13,13,L0|L1}, /* 7c: 0111 1xxx xxxx xxxx */
+ {CALF, 2,13,13,L0|L1}, /* 7d: 0111 1xxx xxxx xxxx */
+ {CALF, 2,13,13,L0|L1}, /* 7e: 0111 1xxx xxxx xxxx */
+ {CALF, 2,13,13,L0|L1}, /* 7f: 0111 1xxx xxxx xxxx */
+
+ {CALT, 1,16,16,L0|L1}, /* 80: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 81: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 82: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 83: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 84: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 85: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 86: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 87: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 88: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 89: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 8a: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 8b: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 8c: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 8d: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 8e: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 8f: 100x xxxx */
+
+ {CALT, 1,16,16,L0|L1}, /* 90: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 91: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 92: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 93: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 94: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 95: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 96: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 97: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 98: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 99: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 9a: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 9b: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 9c: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 9d: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 9e: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 9f: 100x xxxx */
+
+ {POP_VA, 1,10,10,L0|L1}, /* a0: 1010 0000 */
+ {POP_BC, 1,10,10,L0|L1}, /* a1: 1010 0001 */
+ {POP_DE, 1,10,10,L0|L1}, /* a2: 1010 0010 */
+ {POP_HL, 1,10,10,L0|L1}, /* a3: 1010 0011 */
+ {POP_EA, 1,10,10,L0|L1}, /* a4: 1010 0100 */
+ {DMOV_EA_BC, 1, 4, 4,L0|L1}, /* a5: 1010 0101 */
+ {DMOV_EA_DE, 1, 4, 4,L0|L1}, /* a6: 1010 0110 */
+ {DMOV_EA_HL, 1, 4, 4,L0|L1}, /* a7: 1010 0111 */
+ {INX_EA, 1, 7, 7,L0|L1}, /* a8: 1010 1000 */
+ {DCX_EA, 1, 7, 7,L0|L1}, /* a9: 1010 1001 */
+ {EI, 1, 4, 4,L0|L1}, /* aa: 1010 1010 */
+ {LDAX_D_xx, 2, 7, 7,L0|L1}, /* ab: 1010 1011 dddd dddd */
+ {LDAX_H_A, 1, 7, 7,L0|L1}, /* ac: 1010 1100 */
+ {LDAX_H_B, 1, 7, 7,L0|L1}, /* ad: 1010 1101 */
+ {LDAX_H_EA, 1, 7, 7,L0|L1}, /* ae: 1010 1110 */
+ {LDAX_H_xx, 2, 7, 7,L0|L1}, /* af: 1010 1111 dddd dddd */
+
+ {PUSH_VA, 1,13,13,L0|L1}, /* b0: 1011 0000 */
+ {PUSH_BC, 1,13,13,L0|L1}, /* b1: 1011 0001 */
+ {PUSH_DE, 1,13,13,L0|L1}, /* b2: 1011 0010 */
+ {PUSH_HL, 1,13,13,L0|L1}, /* b3: 1011 0011 */
+ {PUSH_EA, 1,13,13,L0|L1}, /* b4: 1011 0100 */
+ {DMOV_BC_EA, 1, 4, 4,L0|L1}, /* b5: 1011 0101 */
+ {DMOV_DE_EA, 1, 4, 4,L0|L1}, /* b6: 1011 0110 */
+ {DMOV_HL_EA, 1, 4, 4,L0|L1}, /* b7: 1011 0111 */
+ {RET, 1,10,10,L0|L1}, /* b8: 1011 1000 */
+ {RETS, 1,10,10,L0|L1}, /* b9: 1011 1001 */
+ {DI, 1, 4, 4,L0|L1}, /* ba: 1011 1010 */
+ {STAX_D_xx, 2, 7, 7,L0|L1}, /* bb: 1011 1011 dddd dddd */
+ {STAX_H_A, 1, 7, 7,L0|L1}, /* bc: 1011 1100 */
+ {STAX_H_B, 1, 7, 7,L0|L1}, /* bd: 1011 1101 */
+ {STAX_H_EA, 1, 7, 7,L0|L1}, /* be: 1011 1110 */
+ {STAX_H_xx, 2, 7, 7,L0|L1}, /* bf: 1011 1111 dddd dddd */
+
+ {JR, 1,10,10,L0|L1}, /* c0: 1100 0000 */
+ {JR, 1,10,10,L0|L1}, /* c1: 1100 0001 */
+ {JR, 1,10,10,L0|L1}, /* c2: 1100 0010 */
+ {JR, 1,10,10,L0|L1}, /* c3: 1100 0011 */
+ {JR, 1,10,10,L0|L1}, /* c4: 1100 0100 */
+ {JR, 1,10,10,L0|L1}, /* c5: 1100 0101 */
+ {JR, 1,10,10,L0|L1}, /* c6: 1100 0110 */
+ {JR, 1,10,10,L0|L1}, /* c7: 1100 0111 */
+ {JR, 1,10,10,L0|L1}, /* c8: 1100 1000 */
+ {JR, 1,10,10,L0|L1}, /* c9: 1100 1001 */
+ {JR, 1,10,10,L0|L1}, /* ca: 1100 1010 */
+ {JR, 1,10,10,L0|L1}, /* cb: 1100 1011 */
+ {JR, 1,10,10,L0|L1}, /* cc: 1100 1100 */
+ {JR, 1,10,10,L0|L1}, /* cd: 1100 1101 */
+ {JR, 1,10,10,L0|L1}, /* ce: 1100 1110 */
+ {JR, 1,10,10,L0|L1}, /* cf: 1100 1111 */
+
+ {JR, 1,10,10,L0|L1}, /* d0: 1101 0000 */
+ {JR, 1,10,10,L0|L1}, /* d1: 1101 0001 */
+ {JR, 1,10,10,L0|L1}, /* d2: 1101 0010 */
+ {JR, 1,10,10,L0|L1}, /* d3: 1101 0011 */
+ {JR, 1,10,10,L0|L1}, /* d4: 1101 0100 */
+ {JR, 1,10,10,L0|L1}, /* d5: 1101 0101 */
+ {JR, 1,10,10,L0|L1}, /* d6: 1101 0110 */
+ {JR, 1,10,10,L0|L1}, /* d7: 1101 0111 */
+ {JR, 1,10,10,L0|L1}, /* d8: 1101 1000 */
+ {JR, 1,10,10,L0|L1}, /* d9: 1101 1001 */
+ {JR, 1,10,10,L0|L1}, /* da: 1101 1010 */
+ {JR, 1,10,10,L0|L1}, /* db: 1101 1011 */
+ {JR, 1,10,10,L0|L1}, /* dc: 1101 1100 */
+ {JR, 1,10,10,L0|L1}, /* dd: 1101 1101 */
+ {JR, 1,10,10,L0|L1}, /* de: 1101 1110 */
+ {JR, 1,10,10,L0|L1}, /* df: 1101 1111 */
+
+ {JR, 1,10,10,L0|L1}, /* e0: 1110 0000 */
+ {JR, 1,10,10,L0|L1}, /* e1: 1110 0001 */
+ {JR, 1,10,10,L0|L1}, /* e2: 1110 0010 */
+ {JR, 1,10,10,L0|L1}, /* e3: 1110 0011 */
+ {JR, 1,10,10,L0|L1}, /* e4: 1110 0100 */
+ {JR, 1,10,10,L0|L1}, /* e5: 1110 0101 */
+ {JR, 1,10,10,L0|L1}, /* e6: 1110 0110 */
+ {JR, 1,10,10,L0|L1}, /* e7: 1110 0111 */
+ {JR, 1,10,10,L0|L1}, /* e8: 1110 1000 */
+ {JR, 1,10,10,L0|L1}, /* e9: 1110 1001 */
+ {JR, 1,10,10,L0|L1}, /* ea: 1110 1010 */
+ {JR, 1,10,10,L0|L1}, /* eb: 1110 1011 */
+ {JR, 1,10,10,L0|L1}, /* ec: 1110 1100 */
+ {JR, 1,10,10,L0|L1}, /* ed: 1110 1101 */
+ {JR, 1,10,10,L0|L1}, /* ee: 1110 1110 */
+ {JR, 1,10,10,L0|L1}, /* ef: 1110 1111 */
+
+ {JR, 1,10,10,L0|L1}, /* f0: 1111 0000 */
+ {JR, 1,10,10,L0|L1}, /* f1: 1111 0001 */
+ {JR, 1,10,10,L0|L1}, /* f2: 1111 0010 */
+ {JR, 1,10,10,L0|L1}, /* f3: 1111 0011 */
+ {JR, 1,10,10,L0|L1}, /* f4: 1111 0100 */
+ {JR, 1,10,10,L0|L1}, /* f5: 1111 0101 */
+ {JR, 1,10,10,L0|L1}, /* f6: 1111 0110 */
+ {JR, 1,10,10,L0|L1}, /* f7: 1111 0111 */
+ {JR, 1,10,10,L0|L1}, /* f8: 1111 1000 */
+ {JR, 1,10,10,L0|L1}, /* f9: 1111 1001 */
+ {JR, 1,10,10,L0|L1}, /* fa: 1111 1010 */
+ {JR, 1,10,10,L0|L1}, /* fb: 1111 1011 */
+ {JR, 1,10,10,L0|L1}, /* fc: 1111 1100 */
+ {JR, 1,10,10,L0|L1}, /* fd: 1111 1101 */
+ {JR, 1,10,10,L0|L1}, /* fe: 1111 1110 */
+ {JR, 1,10,10,L0|L1} /* ff: 1111 1111 */
+};
+
+static const struct opcode_s opXX_7807[256] =
+{
+ {NOP, 1, 4, 4,L0|L1}, /* 00: 0000 0000 */
+ {LDAW_wa, 2,10,10,L0|L1}, /* 01: 0000 0001 oooo oooo */
+ {INX_SP, 1, 7, 7,L0|L1}, /* 02: 0000 0010 */
+ {DCX_SP, 1, 7, 7,L0|L1}, /* 03: 0000 0011 */
+ {LXI_S_w, 3,10,10,L0|L1}, /* 04: 0000 0100 llll llll hhhh hhhh */
+ {ANIW_wa_xx, 3,19,19,L0|L1}, /* 05: 0000 0101 oooo oooo xxxx xxxx */
+ {illegal, 1, 4, 4,L0|L1}, /* 06: */
+ {ANI_A_xx, 2, 7, 7,L0|L1}, /* 07: 0000 0111 xxxx xxxx */
+ {MOV_A_EAH, 1, 4, 4,L0|L1}, /* 08: 0000 1000 */
+ {MOV_A_EAL, 1, 4, 4,L0|L1}, /* 09: 0000 1001 */
+ {MOV_A_B, 1, 4, 4,L0|L1}, /* 0a: 0000 1010 */
+ {MOV_A_C, 1, 4, 4,L0|L1}, /* 0b: 0000 1011 */
+ {MOV_A_D, 1, 4, 4,L0|L1}, /* 0c: 0000 1100 */
+ {MOV_A_E, 1, 4, 4,L0|L1}, /* 0d: 0000 1101 */
+ {MOV_A_H, 1, 4, 4,L0|L1}, /* 0e: 0000 1110 */
+ {MOV_A_L, 1, 4, 4,L0|L1}, /* 0f: 0000 1111 */
+
+ {illegal, 1,13, 4,L0|L1}, /* 10: 0001 0000 */ /* 7807 */
+ {illegal, 1,13, 4,L0|L1}, /* 11: 0001 0001 */ /* 7807 */
+ {INX_BC, 1, 7, 7,L0|L1}, /* 12: 0001 0010 */
+ {DCX_BC, 1, 7, 7,L0|L1}, /* 13: 0001 0011 */
+ {LXI_B_w, 3,10,10,L0|L1}, /* 14: 0001 0100 llll llll hhhh hhhh */
+ {ORIW_wa_xx, 3,19,19,L0|L1}, /* 15: 0001 0101 oooo oooo xxxx xxxx */
+ {XRI_A_xx, 2, 7, 7,L0|L1}, /* 16: 0001 0110 xxxx xxxx */
+ {ORI_A_xx, 2, 7, 7,L0|L1}, /* 17: 0001 0111 xxxx xxxx */
+ {MOV_EAH_A, 1, 4, 4,L0|L1}, /* 18: 0001 1000 */
+ {MOV_EAL_A, 1, 4, 4,L0|L1}, /* 19: 0001 1001 */
+ {MOV_B_A, 1, 4, 4,L0|L1}, /* 1a: 0001 1010 */
+ {MOV_C_A, 1, 4, 4,L0|L1}, /* 1b: 0001 1011 */
+ {MOV_D_A, 1, 4, 4,L0|L1}, /* 1c: 0001 1100 */
+ {MOV_E_A, 1, 4, 4,L0|L1}, /* 1d: 0001 1101 */
+ {MOV_H_A, 1, 4, 4,L0|L1}, /* 1e: 0001 1110 */
+ {MOV_L_A, 1, 4, 4,L0|L1}, /* 1f: 0001 1111 */
+
+ {INRW_wa, 2,16,16,L0|L1}, /* 20: 0010 0000 oooo oooo */
+ {JB, 1, 4, 4,L0|L1}, /* 21: 0010 0001 */
+ {INX_DE, 1, 7, 7,L0|L1}, /* 22: 0010 0010 */
+ {DCX_DE, 1, 7, 7,L0|L1}, /* 23: 0010 0011 */
+ {LXI_D_w, 3,10,10,L0|L1}, /* 24: 0010 0100 llll llll hhhh hhhh */
+ {GTIW_wa_xx, 3,19,19,L0|L1}, /* 25: 0010 0101 oooo oooo xxxx xxxx */
+ {ADINC_A_xx, 2, 7, 7,L0|L1}, /* 26: 0010 0110 xxxx xxxx */
+ {GTI_A_xx, 2, 7, 7,L0|L1}, /* 27: 0010 0111 xxxx xxxx */
+ {illegal, 1, 4, 4,L0|L1}, /* 28: */
+ {LDAX_B, 2, 7, 7,L0|L1}, /* 29: 0010 1001 dddd dddd */
+ {LDAX_D, 2, 7, 7,L0|L1}, /* 2a: 0010 1010 dddd dddd */
+ {LDAX_H, 2, 7, 7,L0|L1}, /* 2b: 0010 1011 dddd dddd */
+ {LDAX_Dp, 2, 7, 7,L0|L1}, /* 2c: 0010 1100 dddd dddd */
+ {LDAX_Hp, 2, 7, 7,L0|L1}, /* 2d: 0010 1101 dddd dddd */
+ {LDAX_Dm, 2, 7, 7,L0|L1}, /* 2e: 0010 1110 dddd dddd */
+ {LDAX_Hm, 2, 7, 7,L0|L1}, /* 2f: 0010 1111 dddd dddd */
+
+ {DCRW_wa, 2,16,16,L0|L1}, /* 30: 0011 0000 oooo oooo */
+ {illegal, 2, 8, 8,L0|L1}, /* 31: 0011 0001 bbbb bbbb */ /* 7807 */
+ {INX_HL, 1, 7, 7,L0|L1}, /* 32: 0011 0010 */
+ {DCX_HL, 1, 7, 7,L0|L1}, /* 33: 0011 0011 */
+ {LXI_H_w, 3,10,10, L1}, /* 34: 0011 0100 llll llll hhhh hhhh */
+ {LTIW_wa_xx, 3,19,19,L0|L1}, /* 35: 0011 0101 oooo oooo xxxx xxxx */
+ {SUINB_A_xx, 2, 7, 7,L0|L1}, /* 36: 0011 0110 xxxx xxxx */
+ {LTI_A_xx, 2, 7, 7,L0|L1}, /* 37: 0011 0111 xxxx xxxx */
+ {illegal, 1, 4, 4,L0|L1}, /* 38: */
+ {STAX_B, 2, 7, 7,L0|L1}, /* 39: 0011 1001 dddd dddd */
+ {STAX_D, 2, 7, 7,L0|L1}, /* 3a: 0011 1010 dddd dddd */
+ {STAX_H, 2, 7, 7,L0|L1}, /* 3b: 0011 1011 dddd dddd */
+ {STAX_Dp, 2, 7, 7,L0|L1}, /* 3c: 0011 1100 dddd dddd */
+ {STAX_Hp, 2, 7, 7,L0|L1}, /* 3d: 0011 1101 dddd dddd */
+ {STAX_Dm, 2, 7, 7,L0|L1}, /* 3e: 0011 1110 dddd dddd */
+ {STAX_Hm, 2, 7, 7,L0|L1}, /* 3f: 0011 1111 dddd dddd */
+
+ {CALL_w, 3,16,16,L0|L1}, /* 40: 0100 0000 llll llll hhhh hhhh */
+ {INR_A, 1, 4, 4,L0|L1}, /* 41: 0100 0001 */
+ {INR_B, 1, 4, 4,L0|L1}, /* 42: 0100 0010 */
+ {INR_C, 1, 4, 4,L0|L1}, /* 43: 0100 0011 */
+ {LXI_EA_s, 3,10,10,L0|L1}, /* 44: 0100 0100 llll llll hhhh hhhh */
+ {ONIW_wa_xx, 3,19,19,L0|L1}, /* 45: 0100 0101 oooo oooo xxxx xxxx */
+ {ADI_A_xx, 2, 7, 7,L0|L1}, /* 46: 0100 0110 xxxx xxxx */
+ {ONI_A_xx, 2, 7, 7,L0|L1}, /* 47: 0100 0111 xxxx xxxx */
+ {PRE_48, 1, 0, 0,L0|L1}, /* 48: prefix */
+ {MVIX_BC_xx, 2,10,10,L0|L1}, /* 49: 0100 1001 xxxx xxxx */
+ {MVIX_DE_xx, 2,10,10,L0|L1}, /* 4a: 0100 1010 xxxx xxxx */
+ {MVIX_HL_xx, 2,10,10,L0|L1}, /* 4b: 0100 1011 xxxx xxxx */
+ {PRE_4C, 1, 0, 0,L0|L1}, /* 4c: prefix */
+ {PRE_4D, 1, 4, 4,L0|L1}, /* 4d: prefix */
+ {JRE, 2,10,10,L0|L1}, /* 4e: 0100 111d dddd dddd */
+ {JRE, 2,10,10,L0|L1}, /* 4f: 0100 111d dddd dddd */
+
+ {SKN_bit, 2,13,13,L0|L1}, /* 50: 0101 0000 bbbb bbbb */ /* 7807 */
+ {DCR_A, 1, 4, 4,L0|L1}, /* 51: 0101 0001 */
+ {DCR_B, 1, 4, 4,L0|L1}, /* 52: 0101 0010 */
+ {DCR_C, 1, 4, 4,L0|L1}, /* 53: 0101 0011 */
+ {JMP_w, 3,10,10,L0|L1}, /* 54: 0101 0100 llll llll hhhh hhhh */
+ {OFFIW_wa_xx, 3,19,19,L0|L1}, /* 55: 0101 0101 oooo oooo xxxx xxxx */
+ {ACI_A_xx, 2, 7, 7,L0|L1}, /* 56: 0101 0110 xxxx xxxx */
+ {OFFI_A_xx, 2, 7, 7,L0|L1}, /* 57: 0101 0111 xxxx xxxx */
+ {SETB, 2,13,13,L0|L1}, /* 58: 0101 1000 bbbb bbbb */ /* 7807 */
+ {illegal, 2, 8, 8,L0|L1}, /* 59: 0101 1001 bbbb bbbb */ /* 7807 */
+ {illegal, 2, 8, 8,L0|L1}, /* 5a: 0101 1010 bbbb bbbb */ /* 7807 */
+ {CLR, 2,13,13,L0|L1}, /* 5b: 0101 1011 bbbb bbbb */ /* 7807 */
+ {illegal, 2, 8, 8,L0|L1}, /* 5c: 0101 1100 bbbb bbbb */ /* 7807 */
+ {SK_bit, 2,10,10,L0|L1}, /* 5d: 0101 1101 bbbb bbbb */ /* 7807 */
+ {illegal, 2, 8, 8,L0|L1}, /* 5e: 0101 1110 bbbb bbbb */ /* 7807 */
+ {illegal, 2, 8, 8,L0|L1}, /* 5f: 0101 1111 bbbb bbbb */ /* 7807 */
+
+ {PRE_60, 1, 0, 0,L0|L1}, /* 60: */
+ {DAA, 1, 4, 4,L0|L1}, /* 61: 0110 0001 */
+ {RETI, 1,13,13,L0|L1}, /* 62: 0110 0010 */
+ {STAW_wa, 2,10,10,L0|L1}, /* 63: 0110 0011 oooo oooo */
+ {PRE_64, 1, 0, 0,L0|L1}, /* 64: */
+ {NEIW_wa_xx, 3,19,19,L0|L1}, /* 65: 0110 0101 oooo oooo xxxx xxxx */
+ {SUI_A_xx, 2, 7, 7,L0|L1}, /* 66: 0110 0110 xxxx xxxx */
+ {NEI_A_xx, 2, 7, 7,L0|L1}, /* 67: 0110 0111 xxxx xxxx */
+ {MVI_V_xx, 2, 7, 7,L0|L1}, /* 68: 0110 1000 xxxx xxxx */
+ {MVI_A_xx, 2, 7, 7,L0 }, /* 69: 0110 1001 xxxx xxxx */
+ {MVI_B_xx, 2, 7, 7,L0|L1}, /* 6a: 0110 1010 xxxx xxxx */
+ {MVI_C_xx, 2, 7, 7,L0|L1}, /* 6b: 0110 1011 xxxx xxxx */
+ {MVI_D_xx, 2, 7, 7,L0|L1}, /* 6c: 0110 1100 xxxx xxxx */
+ {MVI_E_xx, 2, 7, 7,L0|L1}, /* 6d: 0110 1101 xxxx xxxx */
+ {MVI_H_xx, 2, 7, 7,L0|L1}, /* 6e: 0110 1110 xxxx xxxx */
+ {MVI_L_xx, 2, 7, 7, L1}, /* 6f: 0110 1111 xxxx xxxx */
+
+ {PRE_70, 1, 0, 0,L0|L1}, /* 70: */
+ {MVIW_wa_xx, 3,13,13,L0|L1}, /* 71: 0111 0001 oooo oooo xxxx xxxx */
+ {SOFTI, 1,16,16,L0|L1}, /* 72: 0111 0010 */
+ {illegal, 1, 0, 0,L0|L1}, /* 73: */
+ {PRE_74, 1, 0, 0,L0|L1}, /* 74: prefix */
+ {EQIW_wa_xx, 3,19,19,L0|L1}, /* 75: 0111 0101 oooo oooo xxxx xxxx */
+ {SBI_A_xx, 2, 7, 7,L0|L1}, /* 76: 0111 0110 xxxx xxxx */
+ {EQI_A_xx, 2, 7, 7,L0|L1}, /* 77: 0111 0111 xxxx xxxx */
+ {CALF, 2,13,13,L0|L1}, /* 78: 0111 1xxx xxxx xxxx */
+ {CALF, 2,13,13,L0|L1}, /* 79: 0111 1xxx xxxx xxxx */
+ {CALF, 2,13,13,L0|L1}, /* 7a: 0111 1xxx xxxx xxxx */
+ {CALF, 2,13,13,L0|L1}, /* 7b: 0111 1xxx xxxx xxxx */
+ {CALF, 2,13,13,L0|L1}, /* 7c: 0111 1xxx xxxx xxxx */
+ {CALF, 2,13,13,L0|L1}, /* 7d: 0111 1xxx xxxx xxxx */
+ {CALF, 2,13,13,L0|L1}, /* 7e: 0111 1xxx xxxx xxxx */
+ {CALF, 2,13,13,L0|L1}, /* 7f: 0111 1xxx xxxx xxxx */
+
+ {CALT, 1,16,16,L0|L1}, /* 80: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 81: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 82: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 83: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 84: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 85: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 86: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 87: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 88: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 89: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 8a: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 8b: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 8c: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 8d: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 8e: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 8f: 100x xxxx */
+
+ {CALT, 1,16,16,L0|L1}, /* 90: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 91: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 92: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 93: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 94: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 95: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 96: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 97: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 98: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 99: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 9a: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 9b: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 9c: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 9d: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 9e: 100x xxxx */
+ {CALT, 1,16,16,L0|L1}, /* 9f: 100x xxxx */
+
+ {POP_VA, 1,10,10,L0|L1}, /* a0: 1010 0000 */
+ {POP_BC, 1,10,10,L0|L1}, /* a1: 1010 0001 */
+ {POP_DE, 1,10,10,L0|L1}, /* a2: 1010 0010 */
+ {POP_HL, 1,10,10,L0|L1}, /* a3: 1010 0011 */
+ {POP_EA, 1,10,10,L0|L1}, /* a4: 1010 0100 */
+ {DMOV_EA_BC, 1, 4, 4,L0|L1}, /* a5: 1010 0101 */
+ {DMOV_EA_DE, 1, 4, 4,L0|L1}, /* a6: 1010 0110 */
+ {DMOV_EA_HL, 1, 4, 4,L0|L1}, /* a7: 1010 0111 */
+ {INX_EA, 1, 7, 7,L0|L1}, /* a8: 1010 1000 */
+ {DCX_EA, 1, 7, 7,L0|L1}, /* a9: 1010 1001 */
+ {EI, 1, 4, 4,L0|L1}, /* aa: 1010 1010 */
+ {LDAX_D_xx, 2, 7, 7,L0|L1}, /* ab: 1010 1011 dddd dddd */
+ {LDAX_H_A, 1, 7, 7,L0|L1}, /* ac: 1010 1100 */
+ {LDAX_H_B, 1, 7, 7,L0|L1}, /* ad: 1010 1101 */
+ {LDAX_H_EA, 1, 7, 7,L0|L1}, /* ae: 1010 1110 */
+ {LDAX_H_xx, 2, 7, 7,L0|L1}, /* af: 1010 1111 dddd dddd */
+
+ {PUSH_VA, 1,13,13,L0|L1}, /* b0: 1011 0000 */
+ {PUSH_BC, 1,13,13,L0|L1}, /* b1: 1011 0001 */
+ {PUSH_DE, 1,13,13,L0|L1}, /* b2: 1011 0010 */
+ {PUSH_HL, 1,13,13,L0|L1}, /* b3: 1011 0011 */
+ {PUSH_EA, 1,13,13,L0|L1}, /* b4: 1011 0100 */
+ {DMOV_BC_EA, 1, 4, 4,L0|L1}, /* b5: 1011 0101 */
+ {DMOV_DE_EA, 1, 4, 4,L0|L1}, /* b6: 1011 0110 */
+ {DMOV_HL_EA, 1, 4, 4,L0|L1}, /* b7: 1011 0111 */
+ {RET, 1,10,10,L0|L1}, /* b8: 1011 1000 */
+ {RETS, 1,10,10,L0|L1}, /* b9: 1011 1001 */
+ {DI, 1, 4, 4,L0|L1}, /* ba: 1011 1010 */
+ {STAX_D_xx, 2, 7, 7,L0|L1}, /* bb: 1011 1011 dddd dddd */
+ {STAX_H_A, 1, 7, 7,L0|L1}, /* bc: 1011 1100 */
+ {STAX_H_B, 1, 7, 7,L0|L1}, /* bd: 1011 1101 */
+ {STAX_H_EA, 1, 7, 7,L0|L1}, /* be: 1011 1110 */
+ {STAX_H_xx, 2, 7, 7,L0|L1}, /* bf: 1011 1111 dddd dddd */
+
+ {JR, 1,10,10,L0|L1}, /* c0: 1100 0000 */
+ {JR, 1,10,10,L0|L1}, /* c1: 1100 0001 */
+ {JR, 1,10,10,L0|L1}, /* c2: 1100 0010 */
+ {JR, 1,10,10,L0|L1}, /* c3: 1100 0011 */
+ {JR, 1,10,10,L0|L1}, /* c4: 1100 0100 */
+ {JR, 1,10,10,L0|L1}, /* c5: 1100 0101 */
+ {JR, 1,10,10,L0|L1}, /* c6: 1100 0110 */
+ {JR, 1,10,10,L0|L1}, /* c7: 1100 0111 */
+ {JR, 1,10,10,L0|L1}, /* c8: 1100 1000 */
+ {JR, 1,10,10,L0|L1}, /* c9: 1100 1001 */
+ {JR, 1,10,10,L0|L1}, /* ca: 1100 1010 */
+ {JR, 1,10,10,L0|L1}, /* cb: 1100 1011 */
+ {JR, 1,10,10,L0|L1}, /* cc: 1100 1100 */
+ {JR, 1,10,10,L0|L1}, /* cd: 1100 1101 */
+ {JR, 1,10,10,L0|L1}, /* ce: 1100 1110 */
+ {JR, 1,10,10,L0|L1}, /* cf: 1100 1111 */
+
+ {JR, 1,10,10,L0|L1}, /* d0: 1101 0000 */
+ {JR, 1,10,10,L0|L1}, /* d1: 1101 0001 */
+ {JR, 1,10,10,L0|L1}, /* d2: 1101 0010 */
+ {JR, 1,10,10,L0|L1}, /* d3: 1101 0011 */
+ {JR, 1,10,10,L0|L1}, /* d4: 1101 0100 */
+ {JR, 1,10,10,L0|L1}, /* d5: 1101 0101 */
+ {JR, 1,10,10,L0|L1}, /* d6: 1101 0110 */
+ {JR, 1,10,10,L0|L1}, /* d7: 1101 0111 */
+ {JR, 1,10,10,L0|L1}, /* d8: 1101 1000 */
+ {JR, 1,10,10,L0|L1}, /* d9: 1101 1001 */
+ {JR, 1,10,10,L0|L1}, /* da: 1101 1010 */
+ {JR, 1,10,10,L0|L1}, /* db: 1101 1011 */
+ {JR, 1,10,10,L0|L1}, /* dc: 1101 1100 */
+ {JR, 1,10,10,L0|L1}, /* dd: 1101 1101 */
+ {JR, 1,10,10,L0|L1}, /* de: 1101 1110 */
+ {JR, 1,10,10,L0|L1}, /* df: 1101 1111 */
+
+ {JR, 1,10,10,L0|L1}, /* e0: 1110 0000 */
+ {JR, 1,10,10,L0|L1}, /* e1: 1110 0001 */
+ {JR, 1,10,10,L0|L1}, /* e2: 1110 0010 */
+ {JR, 1,10,10,L0|L1}, /* e3: 1110 0011 */
+ {JR, 1,10,10,L0|L1}, /* e4: 1110 0100 */
+ {JR, 1,10,10,L0|L1}, /* e5: 1110 0101 */
+ {JR, 1,10,10,L0|L1}, /* e6: 1110 0110 */
+ {JR, 1,10,10,L0|L1}, /* e7: 1110 0111 */
+ {JR, 1,10,10,L0|L1}, /* e8: 1110 1000 */
+ {JR, 1,10,10,L0|L1}, /* e9: 1110 1001 */
+ {JR, 1,10,10,L0|L1}, /* ea: 1110 1010 */
+ {JR, 1,10,10,L0|L1}, /* eb: 1110 1011 */
+ {JR, 1,10,10,L0|L1}, /* ec: 1110 1100 */
+ {JR, 1,10,10,L0|L1}, /* ed: 1110 1101 */
+ {JR, 1,10,10,L0|L1}, /* ee: 1110 1110 */
+ {JR, 1,10,10,L0|L1}, /* ef: 1110 1111 */
+
+ {JR, 1,10,10,L0|L1}, /* f0: 1111 0000 */
+ {JR, 1,10,10,L0|L1}, /* f1: 1111 0001 */
+ {JR, 1,10,10,L0|L1}, /* f2: 1111 0010 */
+ {JR, 1,10,10,L0|L1}, /* f3: 1111 0011 */
+ {JR, 1,10,10,L0|L1}, /* f4: 1111 0100 */
+ {JR, 1,10,10,L0|L1}, /* f5: 1111 0101 */
+ {JR, 1,10,10,L0|L1}, /* f6: 1111 0110 */
+ {JR, 1,10,10,L0|L1}, /* f7: 1111 0111 */
+ {JR, 1,10,10,L0|L1}, /* f8: 1111 1000 */
+ {JR, 1,10,10,L0|L1}, /* f9: 1111 1001 */
+ {JR, 1,10,10,L0|L1}, /* fa: 1111 1010 */
+ {JR, 1,10,10,L0|L1}, /* fb: 1111 1011 */
+ {JR, 1,10,10,L0|L1}, /* fc: 1111 1100 */
+ {JR, 1,10,10,L0|L1}, /* fd: 1111 1101 */
+ {JR, 1,10,10,L0|L1}, /* fe: 1111 1110 */
+ {JR, 1,10,10,L0|L1} /* ff: 1111 1111 */
+};
+
+
+/***********************************************************************
+ *
+ * uPD7801
+ *
+ **********************************************************************/
+
+static const struct opcode_s op48_7801[256] =
+{
+ /* 0x00 - 0x1F */
+ {SKIT_F0, 2, 8, 8,L0|L1}, {SKIT_FT0, 2, 8, 8,L0|L1},
+ {SKIT_F1, 2, 8, 8,L0|L1}, {SKIT_F2, 2, 8, 8,L0|L1},
+ {SKIT_FST, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {SK_CY, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {SK_Z, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {PUSH_VA, 2,17,17,L0|L1}, {POP_VA, 2,15,15,L0|L1},
+
+ {SKNIT_F0, 2, 8, 8,L0|L1}, {SKNIT_FT0, 2, 8, 8,L0|L1},
+ {SKNIT_F1, 2, 8, 8,L0|L1}, {SKNIT_F2, 2, 8, 8,L0|L1},
+ {SKNIT_FST, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal, 2, 8, 8,L0|L1},
+ {SKN_CY, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {SKN_Z, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {PUSH_BC, 2,17,17,L0|L1}, {POP_BC, 2,15,15,L0|L1},
+
+ /* 0x20 - 0x3F */
+ {EI, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {DI, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {CLC, 2, 8, 8,L0|L1}, {STC, 2, 8, 8,L0|L1},
+ {PEN, 2,11,11,L0|L1}, {PEX, 2,11,11,L0|L1},
+ {PUSH_DE, 2,17,17,L0|L1}, {POP_DE, 2,15,15,L0|L1},
+
+ {RLL_A, 2, 8, 8,L0|L1}, {RLR_A, 2, 8, 8,L0|L1},
+ {RLL_C, 2, 8, 8,L0|L1}, {RLR_C, 2, 8, 8,L0|L1},
+ {SLL_A, 2, 8, 8,L0|L1}, {SLR_A, 2, 8, 8,L0|L1},
+ {SLL_C, 2, 8, 8,L0|L1}, {SLR_C, 2, 8, 8,L0|L1},
+ {RLD, 2,17,17,L0|L1}, {RRD, 2,17,17,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {PER, 2,11,11,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {PUSH_HL, 2,17,17,L0|L1}, {POP_HL, 2,15,15,L0|L1},
+
+ /* 0x40 - 0x5F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x60 - 0x7F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x80 - 0x9F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xA0 - 0xBF */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xC0 - 0xDF */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xE0 - 0xFF */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1}
+};
+
+static const struct opcode_s op4C_7801[256] =
+{
+ /* 0x00 - 0x1F */
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+
+ /* 0x20 - 0x3F */
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+
+ /* 0x40 - 0x5F */
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+
+ /* 0x60 - 0x7F */
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+
+ /* 0x80 - 0x9F */
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+
+ /* 0xA0 - 0xBF */
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+ {IN, 2,10,10,L0|L1}, {IN, 2,10,10,L0|L1},
+
+ /* 0xC0 - 0xDF */
+ {MOV_A_PA, 2,10,10,L0|L1}, {MOV_A_PB, 2,10,10,L0|L1},
+ {MOV_A_PC, 2,10,10,L0|L1}, {MOV_A_MKL, 2,10,10,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {MOV_A_S, 2,10,10,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xE0 - 0xFF */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1}
+};
+
+/* prefix 4D */
+static const struct opcode_s op4D_7801[256] =
+{
+ /* 0x00 - 0x1F */
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+
+ /* 0x20 - 0x3F */
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+
+ /* 0x40 - 0x5F */
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+
+ /* 0x60 - 0x7F */
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+
+ /* 0x80 - 0x9F */
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+
+ /* 0xA0 - 0xBF */
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+ {OUT, 2,10,10,L0|L1}, {OUT, 2,10,10,L0|L1},
+
+ /* 0xC0 - 0xDF */
+ {MOV_PA_A, 2,10,10,L0|L1}, {MOV_PB_A, 2,10,10,L0|L1},
+ {MOV_PC_A, 2,10,10,L0|L1}, {MOV_MKL_A, 2,10,10,L0|L1},
+ {MOV_MB_A, 2,10,10,L0|L1}, {MOV_MC_A_7801, 2,10,10,L0|L1},
+ {MOV_TM0_A, 2,10,10,L0|L1}, {MOV_TM1_A, 2,10,10,L0|L1},
+ {MOV_S_A, 2,10,10,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xE0 - 0xFF */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1}
+};
+
+/* prefix 60 */
+static const struct opcode_s op60_7801[256] =
+{
+ /* 0x00 - 0x1F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {ANA_V_A, 2, 8, 8,L0|L1}, {ANA_A_A, 2, 8, 8,L0|L1},
+ {ANA_B_A, 2, 8, 8,L0|L1}, {ANA_C_A, 2, 8, 8,L0|L1},
+ {ANA_D_A, 2, 8, 8,L0|L1}, {ANA_E_A, 2, 8, 8,L0|L1},
+ {ANA_H_A, 2, 8, 8,L0|L1}, {ANA_L_A, 2, 8, 8,L0|L1},
+
+ {XRA_V_A, 2, 8, 8,L0|L1}, {XRA_A_A, 2, 8, 8,L0|L1},
+ {XRA_B_A, 2, 8, 8,L0|L1}, {XRA_C_A, 2, 8, 8,L0|L1},
+ {XRA_D_A, 2, 8, 8,L0|L1}, {XRA_E_A, 2, 8, 8,L0|L1},
+ {XRA_H_A, 2, 8, 8,L0|L1}, {XRA_L_A, 2, 8, 8,L0|L1},
+ {ORA_V_A, 2, 8, 8,L0|L1}, {ORA_A_A, 2, 8, 8,L0|L1},
+ {ORA_B_A, 2, 8, 8,L0|L1}, {ORA_C_A, 2, 8, 8,L0|L1},
+ {ORA_D_A, 2, 8, 8,L0|L1}, {ORA_E_A, 2, 8, 8,L0|L1},
+ {ORA_H_A, 2, 8, 8,L0|L1}, {ORA_L_A, 2, 8, 8,L0|L1},
+
+ /* 0x20 - 0x3F */
+ {ADDNC_V_A, 2, 8, 8,L0|L1}, {ADDNC_A_A, 2, 8, 8,L0|L1},
+ {ADDNC_B_A, 2, 8, 8,L0|L1}, {ADDNC_C_A, 2, 8, 8,L0|L1},
+ {ADDNC_D_A, 2, 8, 8,L0|L1}, {ADDNC_E_A, 2, 8, 8,L0|L1},
+ {ADDNC_H_A, 2, 8, 8,L0|L1}, {ADDNC_L_A, 2, 8, 8,L0|L1},
+ {GTA_V_A, 2, 8, 8,L0|L1}, {GTA_A_A, 2, 8, 8,L0|L1},
+ {GTA_B_A, 2, 8, 8,L0|L1}, {GTA_C_A, 2, 8, 8,L0|L1},
+ {GTA_D_A, 2, 8, 8,L0|L1}, {GTA_E_A, 2, 8, 8,L0|L1},
+ {GTA_H_A, 2, 8, 8,L0|L1}, {GTA_L_A, 2, 8, 8,L0|L1},
+
+ {SUBNB_V_A, 2, 8, 8,L0|L1}, {SUBNB_A_A, 2, 8, 8,L0|L1},
+ {SUBNB_B_A, 2, 8, 8,L0|L1}, {SUBNB_C_A, 2, 8, 8,L0|L1},
+ {SUBNB_D_A, 2, 8, 8,L0|L1}, {SUBNB_E_A, 2, 8, 8,L0|L1},
+ {SUBNB_H_A, 2, 8, 8,L0|L1}, {SUBNB_L_A, 2, 8, 8,L0|L1},
+ {LTA_V_A, 2, 8, 8,L0|L1}, {LTA_A_A, 2, 8, 8,L0|L1},
+ {LTA_B_A, 2, 8, 8,L0|L1}, {LTA_C_A, 2, 8, 8,L0|L1},
+ {LTA_D_A, 2, 8, 8,L0|L1}, {LTA_E_A, 2, 8, 8,L0|L1},
+ {LTA_H_A, 2, 8, 8,L0|L1}, {LTA_L_A, 2, 8, 8,L0|L1},
+
+ /* 0x40 - 0x5F */
+ {ADD_V_A, 2, 8, 8,L0|L1}, {ADD_A_A, 2, 8, 8,L0|L1},
+ {ADD_B_A, 2, 8, 8,L0|L1}, {ADD_C_A, 2, 8, 8,L0|L1},
+ {ADD_D_A, 2, 8, 8,L0|L1}, {ADD_E_A, 2, 8, 8,L0|L1},
+ {ADD_H_A, 2, 8, 8,L0|L1}, {ADD_L_A, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {ADC_V_A, 2, 8, 8,L0|L1}, {ADC_A_A, 2, 8, 8,L0|L1},
+ {ADC_B_A, 2, 8, 8,L0|L1}, {ADC_C_A, 2, 8, 8,L0|L1},
+ {ADC_D_A, 2, 8, 8,L0|L1}, {ADC_E_A, 2, 8, 8,L0|L1},
+ {ADC_H_A, 2, 8, 8,L0|L1}, {ADC_L_A, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x60 - 0x7F */
+ {SUB_V_A, 2, 8, 8,L0|L1}, {SUB_A_A, 2, 8, 8,L0|L1},
+ {SUB_B_A, 2, 8, 8,L0|L1}, {SUB_C_A, 2, 8, 8,L0|L1},
+ {SUB_D_A, 2, 8, 8,L0|L1}, {SUB_E_A, 2, 8, 8,L0|L1},
+ {SUB_H_A, 2, 8, 8,L0|L1}, {SUB_L_A, 2, 8, 8,L0|L1},
+ {NEA_V_A, 2, 8, 8,L0|L1}, {NEA_A_A, 2, 8, 8,L0|L1},
+ {NEA_B_A, 2, 8, 8,L0|L1}, {NEA_C_A, 2, 8, 8,L0|L1},
+ {NEA_D_A, 2, 8, 8,L0|L1}, {NEA_E_A, 2, 8, 8,L0|L1},
+ {NEA_H_A, 2, 8, 8,L0|L1}, {NEA_L_A, 2, 8, 8,L0|L1},
+
+ {SBB_V_A, 2, 8, 8,L0|L1}, {SBB_A_A, 2, 8, 8,L0|L1},
+ {SBB_B_A, 2, 8, 8,L0|L1}, {SBB_C_A, 2, 8, 8,L0|L1},
+ {SBB_D_A, 2, 8, 8,L0|L1}, {SBB_E_A, 2, 8, 8,L0|L1},
+ {SBB_H_A, 2, 8, 8,L0|L1}, {SBB_L_A, 2, 8, 8,L0|L1},
+ {EQA_V_A, 2, 8, 8,L0|L1}, {EQA_A_A, 2, 8, 8,L0|L1},
+ {EQA_B_A, 2, 8, 8,L0|L1}, {EQA_C_A, 2, 8, 8,L0|L1},
+ {EQA_D_A, 2, 8, 8,L0|L1}, {EQA_E_A, 2, 8, 8,L0|L1},
+ {EQA_H_A, 2, 8, 8,L0|L1}, {EQA_L_A, 2, 8, 8,L0|L1},
+
+ /* 0x80 - 0x9F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {ANA_A_V, 2, 8, 8,L0|L1}, {ANA_A_A, 2, 8, 8,L0|L1},
+ {ANA_A_B, 2, 8, 8,L0|L1}, {ANA_A_C, 2, 8, 8,L0|L1},
+ {ANA_A_D, 2, 8, 8,L0|L1}, {ANA_A_E, 2, 8, 8,L0|L1},
+ {ANA_A_H, 2, 8, 8,L0|L1}, {ANA_A_L, 2, 8, 8,L0|L1},
+
+ {XRA_A_V, 2, 8, 8,L0|L1}, {XRA_A_A, 2, 8, 8,L0|L1},
+ {XRA_A_B, 2, 8, 8,L0|L1}, {XRA_A_C, 2, 8, 8,L0|L1},
+ {XRA_A_D, 2, 8, 8,L0|L1}, {XRA_A_E, 2, 8, 8,L0|L1},
+ {XRA_A_H, 2, 8, 8,L0|L1}, {XRA_A_L, 2, 8, 8,L0|L1},
+ {ORA_A_V, 2, 8, 8,L0|L1}, {ORA_A_A, 2, 8, 8,L0|L1},
+ {ORA_A_B, 2, 8, 8,L0|L1}, {ORA_A_C, 2, 8, 8,L0|L1},
+ {ORA_A_D, 2, 8, 8,L0|L1}, {ORA_A_E, 2, 8, 8,L0|L1},
+ {ORA_A_H, 2, 8, 8,L0|L1}, {ORA_A_L, 2, 8, 8,L0|L1},
+
+ /* 0xA0 - 0xBF */
+ {ADDNC_A_V, 2, 8, 8,L0|L1}, {ADDNC_A_A, 2, 8, 8,L0|L1},
+ {ADDNC_A_B, 2, 8, 8,L0|L1}, {ADDNC_A_C, 2, 8, 8,L0|L1},
+ {ADDNC_A_D, 2, 8, 8,L0|L1}, {ADDNC_A_E, 2, 8, 8,L0|L1},
+ {ADDNC_A_H, 2, 8, 8,L0|L1}, {ADDNC_A_L, 2, 8, 8,L0|L1},
+ {GTA_A_V, 2, 8, 8,L0|L1}, {GTA_A_A, 2, 8, 8,L0|L1},
+ {GTA_A_B, 2, 8, 8,L0|L1}, {GTA_A_C, 2, 8, 8,L0|L1},
+ {GTA_A_D, 2, 8, 8,L0|L1}, {GTA_A_E, 2, 8, 8,L0|L1},
+ {GTA_A_H, 2, 8, 8,L0|L1}, {GTA_A_L, 2, 8, 8,L0|L1},
+
+ {SUBNB_A_V, 2, 8, 8,L0|L1}, {SUBNB_A_A, 2, 8, 8,L0|L1},
+ {SUBNB_A_B, 2, 8, 8,L0|L1}, {SUBNB_A_C, 2, 8, 8,L0|L1},
+ {SUBNB_A_D, 2, 8, 8,L0|L1}, {SUBNB_A_E, 2, 8, 8,L0|L1},
+ {SUBNB_A_H, 2, 8, 8,L0|L1}, {SUBNB_A_L, 2, 8, 8,L0|L1},
+ {LTA_A_V, 2, 8, 8,L0|L1}, {LTA_A_A, 2, 8, 8,L0|L1},
+ {LTA_A_B, 2, 8, 8,L0|L1}, {LTA_A_C, 2, 8, 8,L0|L1},
+ {LTA_A_D, 2, 8, 8,L0|L1}, {LTA_A_E, 2, 8, 8,L0|L1},
+ {LTA_A_H, 2, 8, 8,L0|L1}, {LTA_A_L, 2, 8, 8,L0|L1},
+
+ /* 0xC0 - 0xDF */
+ {ADD_A_V, 2, 8, 8,L0|L1}, {ADD_A_A, 2, 8, 8,L0|L1},
+ {ADD_A_B, 2, 8, 8,L0|L1}, {ADD_A_C, 2, 8, 8,L0|L1},
+ {ADD_A_D, 2, 8, 8,L0|L1}, {ADD_A_E, 2, 8, 8,L0|L1},
+ {ADD_A_H, 2, 8, 8,L0|L1}, {ADD_A_L, 2, 8, 8,L0|L1},
+ {ONA_A_V, 2, 8, 8,L0|L1}, {ONA_A_A, 2, 8, 8,L0|L1},
+ {ONA_A_B, 2, 8, 8,L0|L1}, {ONA_A_C, 2, 8, 8,L0|L1},
+ {ONA_A_D, 2, 8, 8,L0|L1}, {ONA_A_E, 2, 8, 8,L0|L1},
+ {ONA_A_H, 2, 8, 8,L0|L1}, {ONA_A_L, 2, 8, 8,L0|L1},
+
+ {ADC_A_V, 2, 8, 8,L0|L1}, {ADC_A_A, 2, 8, 8,L0|L1},
+ {ADC_A_B, 2, 8, 8,L0|L1}, {ADC_A_C, 2, 8, 8,L0|L1},
+ {ADC_A_D, 2, 8, 8,L0|L1}, {ADC_A_E, 2, 8, 8,L0|L1},
+ {ADC_A_H, 2, 8, 8,L0|L1}, {ADC_A_L, 2, 8, 8,L0|L1},
+ {OFFA_A_V, 2, 8, 8,L0|L1}, {OFFA_A_A, 2, 8, 8,L0|L1},
+ {OFFA_A_B, 2, 8, 8,L0|L1}, {OFFA_A_C, 2, 8, 8,L0|L1},
+ {OFFA_A_D, 2, 8, 8,L0|L1}, {OFFA_A_E, 2, 8, 8,L0|L1},
+ {OFFA_A_H, 2, 8, 8,L0|L1}, {OFFA_A_L, 2, 8, 8,L0|L1},
+
+ /* 0xE0 - 0xFF */
+ {SUB_A_V, 2, 8, 8,L0|L1}, {SUB_A_A, 2, 8, 8,L0|L1},
+ {SUB_A_B, 2, 8, 8,L0|L1}, {SUB_A_C, 2, 8, 8,L0|L1},
+ {SUB_A_D, 2, 8, 8,L0|L1}, {SUB_A_E, 2, 8, 8,L0|L1},
+ {SUB_A_H, 2, 8, 8,L0|L1}, {SUB_A_L, 2, 8, 8,L0|L1},
+ {NEA_A_V, 2, 8, 8,L0|L1}, {NEA_A_A, 2, 8, 8,L0|L1},
+ {NEA_A_B, 2, 8, 8,L0|L1}, {NEA_A_C, 2, 8, 8,L0|L1},
+ {NEA_A_D, 2, 8, 8,L0|L1}, {NEA_A_E, 2, 8, 8,L0|L1},
+ {NEA_A_H, 2, 8, 8,L0|L1}, {NEA_A_L, 2, 8, 8,L0|L1},
+
+ {SBB_A_V, 2, 8, 8,L0|L1}, {SBB_A_A, 2, 8, 8,L0|L1},
+ {SBB_A_B, 2, 8, 8,L0|L1}, {SBB_A_C, 2, 8, 8,L0|L1},
+ {SBB_A_D, 2, 8, 8,L0|L1}, {SBB_A_E, 2, 8, 8,L0|L1},
+ {SBB_A_H, 2, 8, 8,L0|L1}, {SBB_A_L, 2, 8, 8,L0|L1},
+ {EQA_A_V, 2, 8, 8,L0|L1}, {EQA_A_A, 2, 8, 8,L0|L1},
+ {EQA_A_B, 2, 8, 8,L0|L1}, {EQA_A_C, 2, 8, 8,L0|L1},
+ {EQA_A_D, 2, 8, 8,L0|L1}, {EQA_A_E, 2, 8, 8,L0|L1},
+ {EQA_A_H, 2, 8, 8,L0|L1}, {EQA_A_L, 2, 8, 8,L0|L1}
+};
+
+/* prefix 64 */
+static const struct opcode_s op64_7801[256] =
+{
+ /* 0x00 - 0x1F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {ANI_V_xx, 3,11,11,L0|L1}, {ANI_A_xx, 3,11,11,L0|L1},
+ {ANI_B_xx, 3,11,11,L0|L1}, {ANI_C_xx, 3,11,11,L0|L1},
+ {ANI_D_xx, 3,11,11,L0|L1}, {ANI_E_xx, 3,11,11,L0|L1},
+ {ANI_H_xx, 3,11,11,L0|L1}, {ANI_L_xx, 3,11,11,L0|L1},
+
+ {XRI_V_xx, 3,11,11,L0|L1}, {XRI_A_xx, 3,11,11,L0|L1},
+ {XRI_B_xx, 3,11,11,L0|L1}, {XRI_C_xx, 3,11,11,L0|L1},
+ {XRI_D_xx, 3,11,11,L0|L1}, {XRI_E_xx, 3,11,11,L0|L1},
+ {XRI_H_xx, 3,11,11,L0|L1}, {XRI_L_xx, 3,11,11,L0|L1},
+ {ORI_V_xx, 3,11,11,L0|L1}, {ORI_A_xx, 3,11,11,L0|L1},
+ {ORI_B_xx, 3,11,11,L0|L1}, {ORI_C_xx, 3,11,11,L0|L1},
+ {ORI_D_xx, 3,11,11,L0|L1}, {ORI_E_xx, 3,11,11,L0|L1},
+ {ORI_H_xx, 3,11,11,L0|L1}, {ORI_L_xx, 3,11,11,L0|L1},
+
+ /* 0x20 - 0x3F */
+ {ADINC_V_xx, 3,11,11,L0|L1}, {ADINC_A_xx, 3,11,11,L0|L1},
+ {ADINC_B_xx, 3,11,11,L0|L1}, {ADINC_C_xx, 3,11,11,L0|L1},
+ {ADINC_D_xx, 3,11,11,L0|L1}, {ADINC_E_xx, 3,11,11,L0|L1},
+ {ADINC_H_xx, 3,11,11,L0|L1}, {ADINC_L_xx, 3,11,11,L0|L1},
+ {GTI_V_xx, 3,11,11,L0|L1}, {GTI_A_xx, 3,11,11,L0|L1},
+ {GTI_B_xx, 3,11,11,L0|L1}, {GTI_C_xx, 3,11,11,L0|L1},
+ {GTI_D_xx, 3,11,11,L0|L1}, {GTI_E_xx, 3,11,11,L0|L1},
+ {GTI_H_xx, 3,11,11,L0|L1}, {GTI_L_xx, 3,11,11,L0|L1},
+
+ {SUINB_V_xx, 3,11,11,L0|L1}, {SUINB_A_xx, 3,11,11,L0|L1},
+ {SUINB_B_xx, 3,11,11,L0|L1}, {SUINB_C_xx, 3,11,11,L0|L1},
+ {SUINB_D_xx, 3,11,11,L0|L1}, {SUINB_E_xx, 3,11,11,L0|L1},
+ {SUINB_H_xx, 3,11,11,L0|L1}, {SUINB_L_xx, 3,11,11,L0|L1},
+ {LTI_V_xx, 3,11,11,L0|L1}, {LTI_A_xx, 3,11,11,L0|L1},
+ {LTI_B_xx, 3,11,11,L0|L1}, {LTI_C_xx, 3,11,11,L0|L1},
+ {LTI_D_xx, 3,11,11,L0|L1}, {LTI_E_xx, 3,11,11,L0|L1},
+ {LTI_H_xx, 3,11,11,L0|L1}, {LTI_L_xx, 3,11,11,L0|L1},
+
+ /* 0x40 - 0x5F */
+ {ADI_V_xx, 3,11,11,L0|L1}, {ADI_A_xx, 3,11,11,L0|L1},
+ {ADI_B_xx, 3,11,11,L0|L1}, {ADI_C_xx, 3,11,11,L0|L1},
+ {ADI_D_xx, 3,11,11,L0|L1}, {ADI_E_xx, 3,11,11,L0|L1},
+ {ADI_H_xx, 3,11,11,L0|L1}, {ADI_L_xx, 3,11,11,L0|L1},
+ {ONI_V_xx, 3,11,11,L0|L1}, {ONI_A_xx, 3,11,11,L0|L1},
+ {ONI_B_xx, 3,11,11,L0|L1}, {ONI_C_xx, 3,11,11,L0|L1},
+ {ONI_D_xx, 3,11,11,L0|L1}, {ONI_E_xx, 3,11,11,L0|L1},
+ {ONI_H_xx, 3,11,11,L0|L1}, {ONI_L_xx, 3,11,11,L0|L1},
+
+ {ACI_V_xx, 3,11,11,L0|L1}, {ACI_A_xx, 3,11,11,L0|L1},
+ {ACI_B_xx, 3,11,11,L0|L1}, {ACI_C_xx, 3,11,11,L0|L1},
+ {ACI_D_xx, 3,11,11,L0|L1}, {ACI_E_xx, 3,11,11,L0|L1},
+ {ACI_H_xx, 3,11,11,L0|L1}, {ACI_L_xx, 3,11,11,L0|L1},
+ {OFFI_V_xx, 3,11,11,L0|L1}, {OFFI_A_xx, 3,11,11,L0|L1},
+ {OFFI_B_xx, 3,11,11,L0|L1}, {OFFI_C_xx, 3,11,11,L0|L1},
+ {OFFI_D_xx, 3,11,11,L0|L1}, {OFFI_E_xx, 3,11,11,L0|L1},
+ {OFFI_H_xx, 3,11,11,L0|L1}, {OFFI_L_xx, 3,11,11,L0|L1},
+
+ /* 0x60 - 0x7F */
+ {SUI_V_xx, 3,11,11,L0|L1}, {SUI_A_xx, 3,11,11,L0|L1},
+ {SUI_B_xx, 3,11,11,L0|L1}, {SUI_C_xx, 3,11,11,L0|L1},
+ {SUI_D_xx, 3,11,11,L0|L1}, {SUI_E_xx, 3,11,11,L0|L1},
+ {SUI_H_xx, 3,11,11,L0|L1}, {SUI_L_xx, 3,11,11,L0|L1},
+ {NEI_V_xx, 3,11,11,L0|L1}, {NEI_A_xx, 3,11,11,L0|L1},
+ {NEI_B_xx, 3,11,11,L0|L1}, {NEI_C_xx, 3,11,11,L0|L1},
+ {NEI_D_xx, 3,11,11,L0|L1}, {NEI_E_xx, 3,11,11,L0|L1},
+ {NEI_H_xx, 3,11,11,L0|L1}, {NEI_L_xx, 3,11,11,L0|L1},
+
+ {SBI_V_xx, 3,11,11,L0|L1}, {SBI_A_xx, 3,11,11,L0|L1},
+ {SBI_B_xx, 3,11,11,L0|L1}, {SBI_C_xx, 3,11,11,L0|L1},
+ {SBI_D_xx, 3,11,11,L0|L1}, {SBI_E_xx, 3,11,11,L0|L1},
+ {SBI_H_xx, 3,11,11,L0|L1}, {SBI_L_xx, 3,11,11,L0|L1},
+ {EQI_V_xx, 3,11,11,L0|L1}, {EQI_A_xx, 3,11,11,L0|L1},
+ {EQI_B_xx, 3,11,11,L0|L1}, {EQI_C_xx, 3,11,11,L0|L1},
+ {EQI_D_xx, 3,11,11,L0|L1}, {EQI_E_xx, 3,11,11,L0|L1},
+ {EQI_H_xx, 3,11,11,L0|L1}, {EQI_L_xx, 3,11,11,L0|L1},
+
+ /* 0x80 - 0x9F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {ANI_PA_xx, 3,17,17,L0|L1}, {ANI_PB_xx, 3,17,17,L0|L1},
+ {ANI_PC_xx, 3,17,17,L0|L1}, {ANI_MKL_xx, 3,17,17,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {XRI_PA_xx, 3,17,17,L0|L1}, {XRI_PB_xx, 3,17,17,L0|L1},
+ {XRI_PC_xx, 3,17,17,L0|L1}, {XRI_MKL_xx, 3,17,17,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {ORI_PA_xx, 3,17,17,L0|L1}, {ORI_PB_xx, 3,17,17,L0|L1},
+ {ORI_PC_xx, 3,17,17,L0|L1}, {ORI_MKL_xx, 3,17,17,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xA0 - 0xBF */
+ {ADINC_PA_xx, 3,17,17,L0|L1}, {ADINC_PB_xx, 3,17,17,L0|L1},
+ {ADINC_PC_xx, 3,17,17,L0|L1}, {ADINC_MKL_xx, 3,17,17,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {GTI_PA_xx, 3,14,14,L0|L1}, {GTI_PB_xx, 3,14,14,L0|L1},
+ {GTI_PC_xx, 3,14,14,L0|L1}, {GTI_MKL_xx, 3,14,14,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {SUINB_PA_xx, 3,17,17,L0|L1}, {SUINB_PB_xx, 3,17,17,L0|L1},
+ {SUINB_PC_xx, 3,17,17,L0|L1}, {SUINB_MKL_xx, 3,17,17,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {LTI_PA_xx, 3,14,14,L0|L1}, {LTI_PB_xx, 3,14,14,L0|L1},
+ {LTI_PC_xx, 3,14,14,L0|L1}, {LTI_MKL_xx, 3,14,14,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xC0 - 0xDF */
+ {ADI_PA_xx, 3,17,17,L0|L1}, {ADI_PB_xx, 3,17,17,L0|L1},
+ {ADI_PC_xx, 3,17,17,L0|L1}, {ADI_MKL_xx, 3,17,17,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {ONI_PA_xx, 3,14,14,L0|L1}, {ONI_PB_xx, 3,14,14,L0|L1},
+ {ONI_PC_xx, 3,14,14,L0|L1}, {ONI_MKL_xx, 3,14,14,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {ACI_PA_xx, 3,17,17,L0|L1}, {ACI_PB_xx, 3,17,17,L0|L1},
+ {ACI_PC_xx, 3,17,17,L0|L1}, {ACI_MKL_xx, 3,17,17,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {OFFI_PA_xx, 3,14,14,L0|L1}, {OFFI_PB_xx, 3,14,14,L0|L1},
+ {OFFI_PC_xx, 3,14,14,L0|L1}, {OFFI_MKL_xx, 3,14,14,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xE0 - 0xFF */
+ {SUI_PA_xx, 3,17,17,L0|L1}, {SUI_PB_xx, 3,17,17,L0|L1},
+ {SUI_PC_xx, 3,17,17,L0|L1}, {SUI_MKL_xx, 3,17,17,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {NEI_PA_xx, 3,14,14,L0|L1}, {NEI_PB_xx, 3,14,14,L0|L1},
+ {NEI_PC_xx, 3,14,14,L0|L1}, {NEI_MKL_xx, 3,14,14,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {SBI_PA_xx, 3,17,17,L0|L1}, {SBI_PB_xx, 3,17,17,L0|L1},
+ {SBI_PC_xx, 3,17,17,L0|L1}, {SBI_MKL_xx, 3,17,17,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {EQI_PA_xx, 3,14,14,L0|L1}, {EQI_PB_xx, 3,14,14,L0|L1},
+ {EQI_PC_xx, 3,14,14,L0|L1}, {EQI_MKL_xx, 3,14,14,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1}
+};
+
+/* prefix 70 */
+static const struct opcode_s op70_7801[256] =
+{
+ /* 0x00 - 0x1F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {SSPD_w, 4,20,20,L0|L1}, {LSPD_w, 4,20,20,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {SBCD_w, 4,20,20,L0|L1}, {LBCD_w, 4,20,20,L0|L1},
+
+ /* 0x20 - 0x3F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {SDED_w, 4,20,20,L0|L1}, {LDED_w, 4,20,20,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {SHLD_w, 4,20,20,L0|L1}, {LHLD_w, 4,20,20,L0|L1},
+
+ /* 0x40 - 0x5F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x60 - 0x7F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {MOV_V_w, 4,17,17,L0|L1}, {MOV_A_w, 4,17,17,L0|L1},
+ {MOV_B_w, 4,17,17,L0|L1}, {MOV_C_w, 4,17,17,L0|L1},
+ {MOV_D_w, 4,17,17,L0|L1}, {MOV_E_w, 4,17,17,L0|L1},
+ {MOV_H_w, 4,17,17,L0|L1}, {MOV_L_w, 4,17,17,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {MOV_w_V, 4,17,17,L0|L1}, {MOV_w_A, 4,17,17,L0|L1},
+ {MOV_w_B, 4,17,17,L0|L1}, {MOV_w_C, 4,17,17,L0|L1},
+ {MOV_w_D, 4,17,17,L0|L1}, {MOV_w_E, 4,17,17,L0|L1},
+ {MOV_w_H, 4,17,17,L0|L1}, {MOV_w_L, 4,17,17,L0|L1},
+
+ /* 0x80 - 0x9F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {ANAX_B, 2,11,11,L0|L1},
+ {ANAX_D, 2,11,11,L0|L1}, {ANAX_H, 2,11,11,L0|L1},
+ {ANAX_Dp, 2,11,11,L0|L1}, {ANAX_Hp, 2,11,11,L0|L1},
+ {ANAX_Dm, 2,11,11,L0|L1}, {ANAX_Hm, 2,11,11,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {XRAX_B, 2,11,11,L0|L1},
+ {XRAX_D, 2,11,11,L0|L1}, {XRAX_H, 2,11,11,L0|L1},
+ {XRAX_Dp, 2,11,11,L0|L1}, {XRAX_Hp, 2,11,11,L0|L1},
+ {XRAX_Dm, 2,11,11,L0|L1}, {XRAX_Hm, 2,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {ORAX_B, 2,11,11,L0|L1},
+ {ORAX_D, 2,11,11,L0|L1}, {ORAX_H, 2,11,11,L0|L1},
+ {ORAX_Dp, 2,11,11,L0|L1}, {ORAX_Hp, 2,11,11,L0|L1},
+ {ORAX_Dm, 2,11,11,L0|L1}, {ORAX_Hm, 2,11,11,L0|L1},
+
+ /* 0xA0 - 0xBF */
+ {illegal2, 2, 8, 8,L0|L1}, {ADDNCX_B, 2,11,11,L0|L1},
+ {ADDNCX_D, 2,11,11,L0|L1}, {ADDNCX_H, 2,11,11,L0|L1},
+ {ADDNCX_Dp, 2,11,11,L0|L1}, {ADDNCX_Hp, 2,11,11,L0|L1},
+ {ADDNCX_Dm, 2,11,11,L0|L1}, {ADDNCX_Hm, 2,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {GTAX_B, 2,11,11,L0|L1},
+ {GTAX_D, 2,11,11,L0|L1}, {GTAX_H, 2,11,11,L0|L1},
+ {GTAX_Dp, 2,11,11,L0|L1}, {GTAX_Hp, 2,11,11,L0|L1},
+ {GTAX_Dm, 2,11,11,L0|L1}, {GTAX_Hm, 2,11,11,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {SUBNBX_B, 2,11,11,L0|L1},
+ {SUBNBX_D, 2,11,11,L0|L1}, {SUBNBX_H, 2,11,11,L0|L1},
+ {SUBNBX_Dp, 2,11,11,L0|L1}, {SUBNBX_Hp, 2,11,11,L0|L1},
+ {SUBNBX_Dm, 2,11,11,L0|L1}, {SUBNBX_Hm, 2,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {LTAX_B, 2,11,11,L0|L1},
+ {LTAX_D, 2,11,11,L0|L1}, {LTAX_H, 2,11,11,L0|L1},
+ {LTAX_Dp, 2,11,11,L0|L1}, {LTAX_Hp, 2,11,11,L0|L1},
+ {LTAX_Dm, 2,11,11,L0|L1}, {LTAX_Hm, 2,11,11,L0|L1},
+
+ /* 0xC0 - 0xDF */
+ {illegal2, 2, 8, 8,L0|L1}, {ADDX_B, 2,11,11,L0|L1},
+ {ADDX_D, 2,11,11,L0|L1}, {ADDX_H, 2,11,11,L0|L1},
+ {ADDX_Dp, 2,11,11,L0|L1}, {ADDX_Hp, 2,11,11,L0|L1},
+ {ADDX_Dm, 2,11,11,L0|L1}, {ADDX_Hm, 2,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {ONAX_B, 2,11,11,L0|L1},
+ {ONAX_D, 2,11,11,L0|L1}, {ONAX_H, 2,11,11,L0|L1},
+ {ONAX_Dp, 2,11,11,L0|L1}, {ONAX_Hp, 2,11,11,L0|L1},
+ {ONAX_Dm, 2,11,11,L0|L1}, {ONAX_Hm, 2,11,11,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {ADCX_B, 2,11,11,L0|L1},
+ {ADCX_D, 2,11,11,L0|L1}, {ADCX_H, 2,11,11,L0|L1},
+ {ADCX_Dp, 2,11,11,L0|L1}, {ADCX_Hp, 2,11,11,L0|L1},
+ {ADCX_Dm, 2,11,11,L0|L1}, {ADCX_Hm, 2,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {OFFAX_B, 2,11,11,L0|L1},
+ {OFFAX_D, 2,11,11,L0|L1}, {OFFAX_H, 2,11,11,L0|L1},
+ {OFFAX_Dp, 2,11,11,L0|L1}, {OFFAX_Hp, 2,11,11,L0|L1},
+ {OFFAX_Dm, 2,11,11,L0|L1}, {OFFAX_Hm, 2,11,11,L0|L1},
+
+ /* 0xE0 - 0xFF */
+ {illegal2, 2, 8, 8,L0|L1}, {SUBX_B, 2,11,11,L0|L1},
+ {SUBX_D, 2,11,11,L0|L1}, {SUBX_H, 2,11,11,L0|L1},
+ {SUBX_Dp, 2,11,11,L0|L1}, {SUBX_Hp, 2,11,11,L0|L1},
+ {SUBX_Dm, 2,11,11,L0|L1}, {SUBX_Hm, 2,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {NEAX_B, 2,11,11,L0|L1},
+ {NEAX_D, 2,11,11,L0|L1}, {NEAX_H, 2,11,11,L0|L1},
+ {NEAX_Dp, 2,11,11,L0|L1}, {NEAX_Hp, 2,11,11,L0|L1},
+ {NEAX_Dm, 2,11,11,L0|L1}, {NEAX_Hm, 2,11,11,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {SBBX_B, 2,11,11,L0|L1},
+ {SBBX_D, 2,11,11,L0|L1}, {SBBX_H, 2,11,11,L0|L1},
+ {SBBX_Dp, 2,11,11,L0|L1}, {SBBX_Hp, 2,11,11,L0|L1},
+ {SBBX_Dm, 2,11,11,L0|L1}, {SBBX_Hm, 2,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {EQAX_B, 2,11,11,L0|L1},
+ {EQAX_D, 2,11,11,L0|L1}, {EQAX_H, 2,11,11,L0|L1},
+ {EQAX_Dp, 2,11,11,L0|L1}, {EQAX_Hp, 2,11,11,L0|L1},
+ {EQAX_Dm, 2,11,11,L0|L1}, {EQAX_Hm, 2,11,11,L0|L1}
+};
+
+/* prefix 74 */
+static const struct opcode_s op74_7801[256] =
+{
+ /* 0x00 - 0x1F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x20 - 0x3F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x40 - 0x5F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x60 - 0x7F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x80 - 0x9F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {ANAW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {XRAW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {ORAW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xA0 - 0xBF */
+ {ADDNCW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {GTAW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {SUBNBW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {LTAW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xC0 - 0xDF */
+ {ADDW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {ONAW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {ADCW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {OFFAW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xE0 - 0xFF */
+ {SUBW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {NEAW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {SBBW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {EQAW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1}
+};
+
+static const struct opcode_s opXX_7801[256] =
+{
+ /* 0x00 - 0x1F */
+ {NOP, 1, 4, 4,L0|L1}, {HALT, 1, 6, 6,L0|L1},
+ {INX_SP, 1, 7, 7,L0|L1}, {DCX_SP, 1, 7, 7,L0|L1},
+ {LXI_S_w, 3,10,10,L0|L1}, {ANIW_wa_xx, 3,16,16,L0|L1},
+ {illegal, 1, 4, 4,L0|L1}, {ANI_A_xx, 2, 7, 7,L0|L1},
+ {RET, 1,11,11,L0|L1}, {SIO, 1, 4, 4,L0|L1},
+ {MOV_A_B, 1, 4, 4,L0|L1}, {MOV_A_C, 1, 4, 4,L0|L1},
+ {MOV_A_D, 1, 4, 4,L0|L1}, {MOV_A_E, 1, 4, 4,L0|L1},
+ {MOV_A_H, 1, 4, 4,L0|L1}, {MOV_A_L, 1, 4, 4,L0|L1},
+
+ {EXA, 1, 4, 4,L0|L1}, {EXX, 1, 4, 4,L0|L1},
+ {INX_BC, 1, 7, 7,L0|L1}, {DCX_BC, 1, 7, 7,L0|L1},
+ {LXI_B_w, 3,10,10,L0|L1}, {ORIW_wa_xx, 3,16,16,L0|L1},
+ {XRI_A_xx, 2, 7, 7,L0|L1}, {ORI_A_xx, 2, 7, 7,L0|L1},
+ {RETS, 1,11,11,L0|L1}, {STM_7801, 1, 4, 4,L0|L1},
+ {MOV_B_A, 1, 4, 4,L0|L1}, {MOV_C_A, 1, 4, 4,L0|L1},
+ {MOV_D_A, 1, 4, 4,L0|L1}, {MOV_E_A, 1, 4, 4,L0|L1},
+ {MOV_H_A, 1, 4, 4,L0|L1}, {MOV_L_A, 1, 4, 4,L0|L1},
+
+ /* 0x20 - 0x3F */
+ {INRW_wa_7801, 2,13,13,L0|L1}, {TABLE, 1,19,19,L0|L1},
+ {INX_DE, 1, 7, 7,L0|L1}, {DCX_DE, 1, 7, 7,L0|L1},
+ {LXI_D_w, 3,10,10,L0|L1}, {GTIW_wa_xx, 3,13,13,L0|L1},
+ {ADINC_A_xx, 2, 7, 7,L0|L1}, {GTI_A_xx, 2, 7, 7,L0|L1},
+ {LDAW_wa, 2,10,10,L0|L1}, {LDAX_B, 1, 7, 7,L0|L1},
+ {LDAX_D, 1, 7, 7,L0|L1}, {LDAX_H, 1, 7, 7,L0|L1},
+ {LDAX_Dp, 1, 7, 7,L0|L1}, {LDAX_Hp, 1, 7, 7,L0|L1},
+ {LDAX_Dm, 1, 7, 7,L0|L1}, {LDAX_Hm, 1, 7, 7,L0|L1},
+
+ {DCRW_wa_7801, 2,13,13,L0|L1}, {BLOCK, 1,13,13,L0|L1},
+ {INX_HL, 1, 7, 7,L0|L1}, {DCX_HL, 1, 7, 7,L0|L1},
+ {LXI_H_w, 3,10,10, L1}, {LTIW_wa_xx, 3,13,13,L0|L1},
+ {SUINB_A_xx, 2, 7, 7,L0|L1}, {LTI_A_xx, 2, 7, 7,L0|L1},
+ {STAW_wa, 2,10,10,L0|L1}, {STAX_B, 1, 7, 7,L0|L1},
+ {STAX_D, 1, 7, 7,L0|L1}, {STAX_H, 1, 7, 7,L0|L1},
+ {STAX_Dp, 1, 7, 7,L0|L1}, {STAX_Hp, 1, 7, 7,L0|L1},
+ {STAX_Dm, 1, 7, 7,L0|L1}, {STAX_Hm, 1, 7, 7,L0|L1},
+
+ /* 0x40 - 0x5F */
+ {illegal, 1, 4, 4,L0|L1}, {INR_A_7801, 1, 4, 4,L0|L1},
+ {INR_B_7801, 1, 4, 4,L0|L1}, {INR_C_7801, 1, 4, 4,L0|L1},
+ {CALL_w, 3,16,16,L0|L1}, {ONIW_wa_xx, 3,13,13,L0|L1},
+ {ADI_A_xx, 2, 7, 7,L0|L1}, {ONI_A_xx, 2, 7, 7,L0|L1},
+ {PRE_48, 1, 0, 0,L0|L1}, {MVIX_BC_xx, 2,10,10,L0|L1},
+ {MVIX_DE_xx, 2,10,10,L0|L1}, {MVIX_HL_xx, 2,10,10,L0|L1},
+ {PRE_4C, 1, 0, 0,L0|L1}, {PRE_4D, 1, 0, 0,L0|L1},
+ {JRE, 2,17,17,L0|L1}, {JRE, 2,17,17,L0|L1},
+
+ {illegal, 1, 4, 4,L0|L1}, {DCR_A_7801, 1, 4, 4,L0|L1},
+ {DCR_B_7801, 1, 4, 4,L0|L1}, {DCR_C_7801, 1, 4, 4,L0|L1},
+ {JMP_w, 3,10,10,L0|L1}, {OFFIW_wa_xx, 3,13,13,L0|L1},
+ {ACI_A_xx, 2, 7, 7,L0|L1}, {OFFI_A_xx, 2, 7, 7,L0|L1},
+ {BIT_0_wa, 2,10,10,L0|L1}, {BIT_1_wa, 2,10,10,L0|L1},
+ {BIT_2_wa, 2,10,10,L0|L1}, {BIT_3_wa, 2,10,10,L0|L1},
+ {BIT_4_wa, 2,10,10,L0|L1}, {BIT_5_wa, 2,10,10,L0|L1},
+ {BIT_6_wa, 2,10,10,L0|L1}, {BIT_7_wa, 2,10,10,L0|L1},
+
+ /* 0x60 - 0x7F */
+ {PRE_60, 1, 0, 0,L0|L1}, {DAA, 1, 4, 4,L0|L1},
+ {RETI, 1,15,15,L0|L1}, {CALB, 2,13,13,L0|L1},
+ {PRE_64, 1, 0, 0,L0|L1}, {NEIW_wa_xx, 3,13,13,L0|L1},
+ {SUI_A_xx, 2, 7, 7,L0|L1}, {NEI_A_xx, 2, 7, 7,L0|L1},
+ {MVI_V_xx, 2, 7, 7,L0|L1}, {MVI_A_xx, 2, 7, 7,L0 },
+ {MVI_B_xx, 2, 7, 7,L0|L1}, {MVI_C_xx, 2, 7, 7,L0|L1},
+ {MVI_D_xx, 2, 7, 7,L0|L1}, {MVI_E_xx, 2, 7, 7,L0|L1},
+ {MVI_H_xx, 2, 7, 7,L0|L1}, {MVI_L_xx, 2, 7, 7, L1},
+
+ {PRE_70, 1, 0, 0,L0|L1}, {MVIW_wa_xx, 3,13,13,L0|L1},
+ {SOFTI, 1,19,19,L0|L1}, {JB, 1, 4, 4,L0|L1},
+ {PRE_74, 1, 0, 0,L0|L1}, {EQIW_wa_xx, 3,13,13,L0|L1},
+ {SBI_A_xx, 2, 7, 7,L0|L1}, {EQI_A_xx, 2, 7, 7,L0|L1},
+ {CALF, 2,16,16,L0|L1}, {CALF, 2,16,16,L0|L1},
+ {CALF, 2,16,16,L0|L1}, {CALF, 2,16,16,L0|L1},
+ {CALF, 2,16,16,L0|L1}, {CALF, 2,16,16,L0|L1},
+ {CALF, 2,16,16,L0|L1}, {CALF, 2,16,16,L0|L1},
+
+ /* 0x80 - 0x9F */
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+
+ /* 0xA0 - 0xBF */
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+
+ /* 0xC0 - 0xDF */
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+
+ /* 0xE0 - 0xFF */
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1},
+ {JR, 1,13,13,L0|L1}, {JR, 1,13,13,L0|L1}
+};
+
+/***********************************************************************
+ *
+ * uPD78C05(A)
+ *
+ **********************************************************************/
+
+static const struct opcode_s op48_78c05[256] =
+{
+ /* 0x00 - 0x1F */
+ {SKIT_F0, 2, 8, 8,L0|L1}, {SKIT_FT0, 2, 8, 8,L0|L1},
+ {SKIT_F1, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {SKIT_FST, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {SK_CY, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {SK_Z, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {PUSH_VA, 2,17,17,L0|L1}, {POP_VA, 2,14,14,L0|L1},
+
+ {SKNIT_F0, 2, 8, 8,L0|L1}, {SKNIT_FT0, 2, 8, 8,L0|L1},
+ {SKNIT_F1, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {SKNIT_FST, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {SKN_CY, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {SKN_Z, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {PUSH_BC, 2,17,17,L0|L1}, {POP_BC, 2,14,14,L0|L1},
+
+ /* 0x20 - 0x3F */
+ {EI, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {DI, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {CLC, 2, 8, 8,L0|L1}, {STC, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {PEX, 2,11,11,L0|L1},
+ {PUSH_DE, 2,17,17,L0|L1}, {POP_DE, 2,14,14,L0|L1},
+
+ {RLL_A, 2, 8, 8,L0|L1}, {RLR_A, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {RLD, 2,17,17,L0|L1}, {RRD, 2,17,17,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {PER, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {PUSH_HL, 2,17,17,L0|L1}, {POP_HL, 2,14,14,L0|L1},
+
+ /* 0x40 - 0x5F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x60 - 0x7F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x80 - 0x9F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xA0 - 0xBF */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xC0 - 0xDF */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xE0 - 0xFF */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1}
+};
+
+static const struct opcode_s op4C_78c05[256] =
+{
+ /* 0x00 - 0x1F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x20 - 0x3F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x40 - 0x5F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x60 - 0x7F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x80 - 0x9F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xA0 - 0xBF */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xC0 - 0xDF */
+ {MOV_A_PA, 2,10,10,L0|L1}, {MOV_A_PB, 2,10,10,L0|L1},
+ {MOV_A_PC, 2,10,10,L0|L1}, {MOV_A_MKL, 2,10,10,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {MOV_A_S, 2,10,10,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xE0 - 0xFF */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1}
+};
+
+/* prefix 4D */
+static const struct opcode_s op4D_78c05[256] =
+{
+ /* 0x00 - 0x1F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x20 - 0x3F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x40 - 0x5F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x60 - 0x7F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x80 - 0x9F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xA0 - 0xBF */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xC0 - 0xDF */
+ {MOV_PA_A, 2,10,10,L0|L1}, {MOV_PB_A, 2,10,10,L0|L1},
+ {MOV_PC_A, 2,10,10,L0|L1}, {MOV_MKL_A, 2,10,10,L0|L1},
+ {MOV_MB_A, 2,10,10,L0|L1}, {MOV_MC_A, 2,10,10,L0|L1},
+ {MOV_TM0_A, 2,10,10,L0|L1}, {MOV_TM1_A, 2,10,10,L0|L1},
+ {MOV_S_A, 2,10,10,L0|L1}, {MOV_TMM_A, 2,10,10,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xE0 - 0xFF */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1}
+};
+
+/* prefix 60 */
+static const struct opcode_s op60_78c05[256] =
+{
+ /* 0x00 - 0x1F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {ANA_A_A, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {XRA_A_A, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {ORA_A_A, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x20 - 0x3F */
+ {illegal2, 2, 8, 8,L0|L1}, {ADDNC_A_A, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {GTA_A_A, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {SUBNB_A_A, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {LTA_A_A, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x40 - 0x5F */
+ {illegal2, 2, 8, 8,L0|L1}, {ADD_A_A, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {ADC_A_A, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ /* 0x60 - 0x7F */
+ {illegal2, 2, 8, 8,L0|L1}, {SUB_A_A, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {NEA_A_A, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {SBB_A_A, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {EQA_A_A, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x80 - 0x9F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {ANA_A_A, 2, 8, 8,L0|L1},
+ {ANA_A_B, 2, 8, 8,L0|L1}, {ANA_A_C, 2, 8, 8,L0|L1},
+ {ANA_A_D, 2, 8, 8,L0|L1}, {ANA_A_E, 2, 8, 8,L0|L1},
+ {ANA_A_H, 2, 8, 8,L0|L1}, {ANA_A_L, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {XRA_A_A, 2, 8, 8,L0|L1},
+ {XRA_A_B, 2, 8, 8,L0|L1}, {XRA_A_C, 2, 8, 8,L0|L1},
+ {XRA_A_D, 2, 8, 8,L0|L1}, {XRA_A_E, 2, 8, 8,L0|L1},
+ {XRA_A_H, 2, 8, 8,L0|L1}, {XRA_A_L, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {ORA_A_A, 2, 8, 8,L0|L1},
+ {ORA_A_B, 2, 8, 8,L0|L1}, {ORA_A_C, 2, 8, 8,L0|L1},
+ {ORA_A_D, 2, 8, 8,L0|L1}, {ORA_A_E, 2, 8, 8,L0|L1},
+ {ORA_A_H, 2, 8, 8,L0|L1}, {ORA_A_L, 2, 8, 8,L0|L1},
+
+ /* 0xA0 - 0xBF */
+ {illegal2, 2, 8, 8,L0|L1}, {ADDNC_A_A, 2, 8, 8,L0|L1},
+ {ADDNC_A_B, 2, 8, 8,L0|L1}, {ADDNC_A_C, 2, 8, 8,L0|L1},
+ {ADDNC_A_D, 2, 8, 8,L0|L1}, {ADDNC_A_E, 2, 8, 8,L0|L1},
+ {ADDNC_A_H, 2, 8, 8,L0|L1}, {ADDNC_A_L, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {GTA_A_A, 2, 8, 8,L0|L1},
+ {GTA_A_B, 2, 8, 8,L0|L1}, {GTA_A_C, 2, 8, 8,L0|L1},
+ {GTA_A_D, 2, 8, 8,L0|L1}, {GTA_A_E, 2, 8, 8,L0|L1},
+ {GTA_A_H, 2, 8, 8,L0|L1}, {GTA_A_L, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {SUBNB_A_A, 2, 8, 8,L0|L1},
+ {SUBNB_A_B, 2, 8, 8,L0|L1}, {SUBNB_A_C, 2, 8, 8,L0|L1},
+ {SUBNB_A_D, 2, 8, 8,L0|L1}, {SUBNB_A_E, 2, 8, 8,L0|L1},
+ {SUBNB_A_H, 2, 8, 8,L0|L1}, {SUBNB_A_L, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {LTA_A_A, 2, 8, 8,L0|L1},
+ {LTA_A_B, 2, 8, 8,L0|L1}, {LTA_A_C, 2, 8, 8,L0|L1},
+ {LTA_A_D, 2, 8, 8,L0|L1}, {LTA_A_E, 2, 8, 8,L0|L1},
+ {LTA_A_H, 2, 8, 8,L0|L1}, {LTA_A_L, 2, 8, 8,L0|L1},
+
+ /* 0xC0 - 0xDF */
+ {illegal2, 2, 8, 8,L0|L1}, {ADD_A_A, 2, 8, 8,L0|L1},
+ {ADD_A_B, 2, 8, 8,L0|L1}, {ADD_A_C, 2, 8, 8,L0|L1},
+ {ADD_A_D, 2, 8, 8,L0|L1}, {ADD_A_E, 2, 8, 8,L0|L1},
+ {ADD_A_H, 2, 8, 8,L0|L1}, {ADD_A_L, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {ONA_A_A, 2, 8, 8,L0|L1},
+ {ONA_A_B, 2, 8, 8,L0|L1}, {ONA_A_C, 2, 8, 8,L0|L1},
+ {ONA_A_D, 2, 8, 8,L0|L1}, {ONA_A_E, 2, 8, 8,L0|L1},
+ {ONA_A_H, 2, 8, 8,L0|L1}, {ONA_A_L, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {ADC_A_A, 2, 8, 8,L0|L1},
+ {ADC_A_B, 2, 8, 8,L0|L1}, {ADC_A_C, 2, 8, 8,L0|L1},
+ {ADC_A_D, 2, 8, 8,L0|L1}, {ADC_A_E, 2, 8, 8,L0|L1},
+ {ADC_A_H, 2, 8, 8,L0|L1}, {ADC_A_L, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {OFFA_A_A, 2, 8, 8,L0|L1},
+ {OFFA_A_B, 2, 8, 8,L0|L1}, {OFFA_A_C, 2, 8, 8,L0|L1},
+ {OFFA_A_D, 2, 8, 8,L0|L1}, {OFFA_A_E, 2, 8, 8,L0|L1},
+ {OFFA_A_H, 2, 8, 8,L0|L1}, {OFFA_A_L, 2, 8, 8,L0|L1},
+
+ /* 0xE0 - 0xFF */
+ {illegal2, 2, 8, 8,L0|L1}, {SUB_A_A, 2, 8, 8,L0|L1},
+ {SUB_A_B, 2, 8, 8,L0|L1}, {SUB_A_C, 2, 8, 8,L0|L1},
+ {SUB_A_D, 2, 8, 8,L0|L1}, {SUB_A_E, 2, 8, 8,L0|L1},
+ {SUB_A_H, 2, 8, 8,L0|L1}, {SUB_A_L, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {NEA_A_A, 2, 8, 8,L0|L1},
+ {NEA_A_B, 2, 8, 8,L0|L1}, {NEA_A_C, 2, 8, 8,L0|L1},
+ {NEA_A_D, 2, 8, 8,L0|L1}, {NEA_A_E, 2, 8, 8,L0|L1},
+ {NEA_A_H, 2, 8, 8,L0|L1}, {NEA_A_L, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {SBB_A_A, 2, 8, 8,L0|L1},
+ {SBB_A_B, 2, 8, 8,L0|L1}, {SBB_A_C, 2, 8, 8,L0|L1},
+ {SBB_A_D, 2, 8, 8,L0|L1}, {SBB_A_E, 2, 8, 8,L0|L1},
+ {SBB_A_H, 2, 8, 8,L0|L1}, {SBB_A_L, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {EQA_A_A, 2, 8, 8,L0|L1},
+ {EQA_A_B, 2, 8, 8,L0|L1}, {EQA_A_C, 2, 8, 8,L0|L1},
+ {EQA_A_D, 2, 8, 8,L0|L1}, {EQA_A_E, 2, 8, 8,L0|L1},
+ {EQA_A_H, 2, 8, 8,L0|L1}, {EQA_A_L, 2, 8, 8,L0|L1}
+};
+
+/* prefix 64 */
+static const struct opcode_s op64_78c05[256] =
+{
+ /* 0x00 - 0x1F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {ANI_A_xx, 3,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {XRI_A_xx, 3,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {ORI_A_xx, 3,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x20 - 0x3F */
+ {illegal2, 2, 8, 8,L0|L1}, {ADINC_A_xx, 3,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {GTI_A_xx, 3,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {SUINB_A_xx, 3,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 3, 8, 8,L0|L1}, {LTI_A_xx, 3,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x40 - 0x5F */
+ {illegal2, 2, 8, 8,L0|L1}, {ADI_A_xx, 3,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {ONI_A_xx, 3,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 3, 8, 8,L0|L1}, {ACI_A_xx, 3,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 3, 8, 8,L0|L1}, {OFFI_A_xx, 3,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x60 - 0x7F */
+ {illegal2, 2, 8, 8,L0|L1}, {SUI_A_xx, 3,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {NEI_A_xx, 3,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {SBI_A_xx, 3,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {EQI_A_xx, 3,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x80 - 0x9F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {ANI_PA_xx, 3,17,17,L0|L1}, {ANI_PB_xx, 3,17,17,L0|L1},
+ {ANI_PC_xx, 3,17,17,L0|L1}, {ANI_MKL_xx, 3,17,17,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {XRI_PA_xx, 3,17,17,L0|L1}, {XRI_PB_xx, 3,17,17,L0|L1},
+ {XRI_PC_xx, 3,17,17,L0|L1}, {XRI_MKL_xx, 3,17,17,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {ORI_PA_xx, 3,17,17,L0|L1}, {ORI_PB_xx, 3,17,17,L0|L1},
+ {ORI_PC_xx, 3,17,17,L0|L1}, {ORI_MKL_xx, 3,17,17,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xA0 - 0xBF */
+ {ADINC_PA_xx, 3,17,17,L0|L1}, {ADINC_PB_xx, 3,17,17,L0|L1},
+ {ADINC_PC_xx, 3,17,17,L0|L1}, {ADINC_MKL_xx, 3,17,17,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {GTI_PA_xx, 3,14,14,L0|L1}, {GTI_PB_xx, 3,14,14,L0|L1},
+ {GTI_PC_xx, 3,14,14,L0|L1}, {GTI_MKL_xx, 3,14,14,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {SUINB_PA_xx, 3,17,17,L0|L1}, {SUINB_PB_xx, 3,17,17,L0|L1},
+ {SUINB_PC_xx, 3,17,17,L0|L1}, {SUINB_MKL_xx, 3,17,17,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {LTI_PA_xx, 3,14,14,L0|L1}, {LTI_PB_xx, 3,14,14,L0|L1},
+ {LTI_PC_xx, 3,14,14,L0|L1}, {LTI_MKL_xx, 3,14,14,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xC0 - 0xDF */
+ {ADI_PA_xx, 3,17,17,L0|L1}, {ADI_PB_xx, 3,17,17,L0|L1},
+ {ADI_PC_xx, 3,17,17,L0|L1}, {ADI_MKL_xx, 3,17,17,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {ONI_PA_xx, 3,14,14,L0|L1}, {ONI_PB_xx, 3,14,14,L0|L1},
+ {ONI_PC_xx, 3,14,14,L0|L1}, {ONI_MKL_xx, 3,14,14,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {ACI_PA_xx, 3,17,17,L0|L1}, {ACI_PB_xx, 3,17,17,L0|L1},
+ {ACI_PC_xx, 3,17,17,L0|L1}, {ACI_MKL_xx, 3,17,17,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {OFFI_PA_xx, 3,14,14,L0|L1}, {OFFI_PB_xx, 3,14,14,L0|L1},
+ {OFFI_PC_xx, 3,14,14,L0|L1}, {OFFI_MKL_xx, 3,14,14,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xE0 - 0xFF */
+ {SUI_PA_xx, 3,17,17,L0|L1}, {SUI_PB_xx, 3,17,17,L0|L1},
+ {SUI_PC_xx, 3,17,17,L0|L1}, {SUI_MKL_xx, 3,17,17,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {NEI_PA_xx, 3,14,14,L0|L1}, {NEI_PB_xx, 3,14,14,L0|L1},
+ {NEI_PC_xx, 3,14,14,L0|L1}, {NEI_MKL_xx, 3,14,14,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {SBI_PA_xx, 3,17,17,L0|L1}, {SBI_PB_xx, 3,17,17,L0|L1},
+ {SBI_PC_xx, 3,17,17,L0|L1}, {SBI_MKL_xx, 3,17,17,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {EQI_PA_xx, 3,14,14,L0|L1}, {EQI_PB_xx, 3,14,14,L0|L1},
+ {EQI_PC_xx, 3,14,14,L0|L1}, {EQI_MKL_xx, 3,14,14,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1}
+};
+
+/* prefix 70 */
+static const struct opcode_s op70_78c05[256] =
+{
+ /* 0x00 - 0x1F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {SSPD_w, 4,20,20,L0|L1}, {LSPD_w, 4,20,20,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {SBCD_w, 4,20,20,L0|L1}, {LBCD_w, 4,20,20,L0|L1},
+
+ /* 0x20 - 0x3F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {SDED_w, 4,20,20,L0|L1}, {LDED_w, 4,20,20,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {SHLD_w, 4,20,20,L0|L1}, {LHLD_w, 4,20,20,L0|L1},
+
+ /* 0x40 - 0x5F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x60 - 0x7F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {MOV_A_w, 4,17,17,L0|L1},
+ {MOV_B_w, 4,17,17,L0|L1}, {MOV_C_w, 4,17,17,L0|L1},
+ {MOV_D_w, 4,17,17,L0|L1}, {MOV_E_w, 4,17,17,L0|L1},
+ {MOV_H_w, 4,17,17,L0|L1}, {MOV_L_w, 4,17,17,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {MOV_w_A, 4,17,17,L0|L1},
+ {MOV_w_B, 4,17,17,L0|L1}, {MOV_w_C, 4,17,17,L0|L1},
+ {MOV_w_D, 4,17,17,L0|L1}, {MOV_w_E, 4,17,17,L0|L1},
+ {MOV_w_H, 4,17,17,L0|L1}, {MOV_w_L, 4,17,17,L0|L1},
+
+ /* 0x80 - 0x9F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {ANAX_B, 2,11,11,L0|L1},
+ {ANAX_D, 2,11,11,L0|L1}, {ANAX_H, 2,11,11,L0|L1},
+ {ANAX_Dp, 2,11,11,L0|L1}, {ANAX_Hp, 2,11,11,L0|L1},
+ {ANAX_Dm, 2,11,11,L0|L1}, {ANAX_Hm, 2,11,11,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {XRAX_B, 2,11,11,L0|L1},
+ {XRAX_D, 2,11,11,L0|L1}, {XRAX_H, 2,11,11,L0|L1},
+ {XRAX_Dp, 2,11,11,L0|L1}, {XRAX_Hp, 2,11,11,L0|L1},
+ {XRAX_Dm, 2,11,11,L0|L1}, {XRAX_Hm, 2,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {ORAX_B, 2,11,11,L0|L1},
+ {ORAX_D, 2,11,11,L0|L1}, {ORAX_H, 2,11,11,L0|L1},
+ {ORAX_Dp, 2,11,11,L0|L1}, {ORAX_Hp, 2,11,11,L0|L1},
+ {ORAX_Dm, 2,11,11,L0|L1}, {ORAX_Hm, 2,11,11,L0|L1},
+
+ /* 0xA0 - 0xBF */
+ {illegal2, 2, 8, 8,L0|L1}, {ADDNCX_B, 2,11,11,L0|L1},
+ {ADDNCX_D, 2,11,11,L0|L1}, {ADDNCX_H, 2,11,11,L0|L1},
+ {ADDNCX_Dp, 2,11,11,L0|L1}, {ADDNCX_Hp, 2,11,11,L0|L1},
+ {ADDNCX_Dm, 2,11,11,L0|L1}, {ADDNCX_Hm, 2,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {GTAX_B, 2,11,11,L0|L1},
+ {GTAX_D, 2,11,11,L0|L1}, {GTAX_H, 2,11,11,L0|L1},
+ {GTAX_Dp, 2,11,11,L0|L1}, {GTAX_Hp, 2,11,11,L0|L1},
+ {GTAX_Dm, 2,11,11,L0|L1}, {GTAX_Hm, 2,11,11,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {SUBNBX_B, 2,11,11,L0|L1},
+ {SUBNBX_D, 2,11,11,L0|L1}, {SUBNBX_H, 2,11,11,L0|L1},
+ {SUBNBX_Dp, 2,11,11,L0|L1}, {SUBNBX_Hp, 2,11,11,L0|L1},
+ {SUBNBX_Dm, 2,11,11,L0|L1}, {SUBNBX_Hm, 2,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {LTAX_B, 2,11,11,L0|L1},
+ {LTAX_D, 2,11,11,L0|L1}, {LTAX_H, 2,11,11,L0|L1},
+ {LTAX_Dp, 2,11,11,L0|L1}, {LTAX_Hp, 2,11,11,L0|L1},
+ {LTAX_Dm, 2,11,11,L0|L1}, {LTAX_Hm, 2,11,11,L0|L1},
+
+ /* 0xC0 - 0xDF */
+ {illegal2, 2, 8, 8,L0|L1}, {ADDX_B, 2,11,11,L0|L1},
+ {ADDX_D, 2,11,11,L0|L1}, {ADDX_H, 2,11,11,L0|L1},
+ {ADDX_Dp, 2,11,11,L0|L1}, {ADDX_Hp, 2,11,11,L0|L1},
+ {ADDX_Dm, 2,11,11,L0|L1}, {ADDX_Hm, 2,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {ONAX_B, 2,11,11,L0|L1},
+ {ONAX_D, 2,11,11,L0|L1}, {ONAX_H, 2,11,11,L0|L1},
+ {ONAX_Dp, 2,11,11,L0|L1}, {ONAX_Hp, 2,11,11,L0|L1},
+ {ONAX_Dm, 2,11,11,L0|L1}, {ONAX_Hm, 2,11,11,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {ADCX_B, 2,11,11,L0|L1},
+ {ADCX_D, 2,11,11,L0|L1}, {ADCX_H, 2,11,11,L0|L1},
+ {ADCX_Dp, 2,11,11,L0|L1}, {ADCX_Hp, 2,11,11,L0|L1},
+ {ADCX_Dm, 2,11,11,L0|L1}, {ADCX_Hm, 2,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {OFFAX_B, 2,11,11,L0|L1},
+ {OFFAX_D, 2,11,11,L0|L1}, {OFFAX_H, 2,11,11,L0|L1},
+ {OFFAX_Dp, 2,11,11,L0|L1}, {OFFAX_Hp, 2,11,11,L0|L1},
+ {OFFAX_Dm, 2,11,11,L0|L1}, {OFFAX_Hm, 2,11,11,L0|L1},
+
+ /* 0xE0 - 0xFF */
+ {illegal2, 2, 8, 8,L0|L1}, {SUBX_B, 2,11,11,L0|L1},
+ {SUBX_D, 2,11,11,L0|L1}, {SUBX_H, 2,11,11,L0|L1},
+ {SUBX_Dp, 2,11,11,L0|L1}, {SUBX_Hp, 2,11,11,L0|L1},
+ {SUBX_Dm, 2,11,11,L0|L1}, {SUBX_Hm, 2,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {NEAX_B, 2,11,11,L0|L1},
+ {NEAX_D, 2,11,11,L0|L1}, {NEAX_H, 2,11,11,L0|L1},
+ {NEAX_Dp, 2,11,11,L0|L1}, {NEAX_Hp, 2,11,11,L0|L1},
+ {NEAX_Dm, 2,11,11,L0|L1}, {NEAX_Hm, 2,11,11,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {SBBX_B, 2,11,11,L0|L1},
+ {SBBX_D, 2,11,11,L0|L1}, {SBBX_H, 2,11,11,L0|L1},
+ {SBBX_Dp, 2,11,11,L0|L1}, {SBBX_Hp, 2,11,11,L0|L1},
+ {SBBX_Dm, 2,11,11,L0|L1}, {SBBX_Hm, 2,11,11,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {EQAX_B, 2,11,11,L0|L1},
+ {EQAX_D, 2,11,11,L0|L1}, {EQAX_H, 2,11,11,L0|L1},
+ {EQAX_Dp, 2,11,11,L0|L1}, {EQAX_Hp, 2,11,11,L0|L1},
+ {EQAX_Dm, 2,11,11,L0|L1}, {EQAX_Hm, 2,11,11,L0|L1}
+};
+
+/* prefix 74 */
+static const struct opcode_s op74_78c05[256] =
+{
+ /* 0x00 - 0x1F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x20 - 0x3F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x40 - 0x5F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x60 - 0x7F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0x80 - 0x9F */
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {ANAW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {XRAW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {ORAW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xA0 - 0xBF */
+ {ADDNCW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {GTAW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {SUBNBW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {LTAW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xC0 - 0xDF */
+ {ADDW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {ONAW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {ADCW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {OFFAW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ /* 0xE0 - 0xFF */
+ {SUBW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {NEAW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+
+ {SBBW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {EQAW_wa, 3,14,14,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
+ {illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1}
+};
+
+static const struct opcode_s opXX_78c05[256] =
+{
+ /* 0x00 - 0x1F */
+ {NOP, 1, 4, 4,L0|L1}, {HALT, 1, 6, 6,L0|L1},
+ {INX_SP, 1, 7, 7,L0|L1}, {DCX_SP, 1, 7, 7,L0|L1},
+ {LXI_S_w, 3,10,10,L0|L1}, {ANIW_wa_xx, 3,16,16,L0|L1},
+ {illegal, 1, 4, 4,L0|L1}, {ANI_A_xx, 2, 7, 7,L0|L1},
+ {RET, 1,10,10,L0|L1}, {SIO, 1, 4, 4,L0|L1},
+ {MOV_A_B, 1, 4, 4,L0|L1}, {MOV_A_C, 1, 4, 4,L0|L1},
+ {MOV_A_D, 1, 4, 4,L0|L1}, {MOV_A_E, 1, 4, 4,L0|L1},
+ {MOV_A_H, 1, 4, 4,L0|L1}, {MOV_A_L, 1, 4, 4,L0|L1},
+
+ {illegal, 1, 4, 4,L0|L1}, {illegal, 1, 4, 4,L0|L1},
+ {INX_BC, 1, 7, 7,L0|L1}, {DCX_BC, 1, 7, 7,L0|L1},
+ {LXI_B_w, 3,10,10,L0|L1}, {ORIW_wa_xx, 3,16,16,L0|L1},
+ {XRI_A_xx, 2, 7, 7,L0|L1}, {ORI_A_xx, 2, 7, 7,L0|L1},
+ {RETS, 1,10,10,L0|L1}, {STM, 1, 4, 4,L0|L1},
+ {MOV_B_A, 1, 4, 4,L0|L1}, {MOV_C_A, 1, 4, 4,L0|L1},
+ {MOV_D_A, 1, 4, 4,L0|L1}, {MOV_E_A, 1, 4, 4,L0|L1},
+ {MOV_H_A, 1, 4, 4,L0|L1}, {MOV_L_A, 1, 4, 4,L0|L1},
+
+ /* 0x20 - 0x3F */
+ {INRW_wa_7801, 2,13,13,L0|L1}, {illegal, 1, 4, 4,L0|L1},
+ {INX_DE, 1, 7, 7,L0|L1}, {DCX_DE, 1, 7, 7,L0|L1},
+ {LXI_D_w, 3,10,10,L0|L1}, {GTIW_wa_xx, 3,13,13,L0|L1},
+ {ADINC_A_xx, 2, 7, 7,L0|L1}, {GTI_A_xx, 2, 7, 7,L0|L1},
+ {LDAW_wa, 2,10,10,L0|L1}, {LDAX_B, 1, 7, 7,L0|L1},
+ {LDAX_D, 1, 7, 7,L0|L1}, {LDAX_H, 1, 7, 7,L0|L1},
+ {LDAX_Dp, 1, 7, 7,L0|L1}, {LDAX_Hp, 1, 7, 7,L0|L1},
+ {LDAX_Dm, 1, 7, 7,L0|L1}, {LDAX_Hm, 1, 7, 7,L0|L1},
+
+ {DCRW_wa_7801, 2,13,13,L0|L1}, {illegal, 1, 4, 4,L0|L1},
+ {INX_HL, 1, 7, 7,L0|L1}, {DCX_HL, 1, 7, 7,L0|L1},
+ {LXI_H_w, 3,10,10, L1}, {LTIW_wa_xx, 3,13,13,L0|L1},
+ {SUINB_A_xx, 2, 7, 7,L0|L1}, {LTI_A_xx, 2, 7, 7,L0|L1},
+ {STAW_wa, 2,10,10,L0|L1}, {STAX_B, 1, 7, 7,L0|L1},
+ {STAX_D, 1, 7, 7,L0|L1}, {STAX_H, 1, 7, 7,L0|L1},
+ {STAX_Dp, 1, 7, 7,L0|L1}, {STAX_Hp, 1, 7, 7,L0|L1},
+ {STAX_Dm, 1, 7, 7,L0|L1}, {STAX_Hm, 1, 7, 7,L0|L1},
+
+ /* 0x40 - 0x5F */
+ {illegal, 1, 4, 4,L0|L1}, {INR_A_7801, 1, 4, 4,L0|L1},
+ {INR_B_7801, 1, 4, 4,L0|L1}, {INR_C_7801, 1, 4, 4,L0|L1},
+ {CALL_w, 3,16,16,L0|L1}, {ONIW_wa_xx, 3,13,13,L0|L1},
+ {ADI_A_xx, 2, 7, 7,L0|L1}, {ONI_A_xx, 2, 7, 7,L0|L1},
+ {PRE_48, 1, 0, 0,L0|L1}, {illegal, 1, 4, 4,L0|L1},
+ {illegal, 1, 4, 4,L0|L1}, {illegal, 1, 4, 4,L0|L1},
+ {PRE_4C, 1, 0, 0,L0|L1}, {PRE_4D, 1, 0, 0,L0|L1},
+ {JRE, 2,13,13,L0|L1}, {JRE, 2,13,13,L0|L1},
+
+ {illegal, 1, 4, 4,L0|L1}, {DCR_A_7801, 1, 4, 4,L0|L1},
+ {DCR_B_7801, 1, 4, 4,L0|L1}, {DCR_C_7801, 1, 4, 4,L0|L1},
+ {JMP_w, 3,10,10,L0|L1}, {OFFIW_wa_xx, 3,13,13,L0|L1},
+ {ACI_A_xx, 2, 7, 7,L0|L1}, {OFFI_A_xx, 2, 7, 7,L0|L1},
+ {illegal, 1, 4, 4,L0|L1}, {illegal, 1, 4, 4,L0|L1},
+ {illegal, 1, 4, 4,L0|L1}, {illegal, 1, 4, 4,L0|L1},
+ {illegal, 1, 4, 4,L0|L1}, {illegal, 1, 4, 4,L0|L1},
+ {illegal, 1, 4, 4,L0|L1}, {illegal, 1, 4, 4,L0|L1},
+
+ /* 0x60 - 0x7F */
+ {PRE_60, 1, 0, 0,L0|L1}, {DAA, 1, 4, 4,L0|L1},
+ {RETI, 1,13,13,L0|L1}, {CALB, 2,13,13,L0|L1},
+ {PRE_64, 1, 0, 0,L0|L1}, {NEIW_wa_xx, 3,13,13,L0|L1},
+ {SUI_A_xx, 2, 7, 7,L0|L1}, {NEI_A_xx, 2, 7, 7,L0|L1},
+ {illegal, 1, 4, 4,L0|L1}, {MVI_A_xx, 2, 7, 7,L0 },
+ {MVI_B_xx, 2, 7, 7,L0|L1}, {MVI_C_xx, 2, 7, 7,L0|L1},
+ {MVI_D_xx, 2, 7, 7,L0|L1}, {MVI_E_xx, 2, 7, 7,L0|L1},
+ {MVI_H_xx, 2, 7, 7,L0|L1}, {MVI_L_xx, 2, 7, 7, L1},
+
+ {PRE_70, 1, 0, 0,L0|L1}, {MVIW_wa_xx, 3,13,13,L0|L1},
+ {SOFTI, 1,19,19,L0|L1}, {JB, 1, 4, 4,L0|L1},
+ {PRE_74, 1, 0, 0,L0|L1}, {EQIW_wa_xx, 3,13,13,L0|L1},
+ {SBI_A_xx, 2, 7, 7,L0|L1}, {EQI_A_xx, 2, 7, 7,L0|L1},
+ {CALF, 2,13,13,L0|L1}, {CALF, 2,13,13,L0|L1},
+ {CALF, 2,13,13,L0|L1}, {CALF, 2,13,13,L0|L1},
+ {CALF, 2,13,13,L0|L1}, {CALF, 2,13,13,L0|L1},
+ {CALF, 2,13,13,L0|L1}, {CALF, 2,13,13,L0|L1},
+
+ /* 0x80 - 0x9F */
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+
+ /* 0xA0 - 0xBF */
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+
+ /* 0xC0 - 0xDF */
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+
+ /* 0xE0 - 0xFF */
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1},
+ {JR, 1,10,10,L0|L1}, {JR, 1,10,10,L0|L1}
+};
+
+/***********************************************************************
+ *
+ * uPD78C06(A) - Same as uPD78C05 but with different instruction timing
+ *
+ **********************************************************************/
+
+static const struct opcode_s op48_78c06[256] =
+{
+ /* 0x00 - 0x1F */
+ {SKIT_F0, 2,12,12,L0|L1}, {SKIT_FT0, 2,12,12,L0|L1},
+ {SKIT_F1, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {SKIT_FST, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {SK_CY, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {SK_Z, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {PUSH_VA, 2,21,21,L0|L1}, {POP_VA, 2,18,18,L0|L1},
+
+ {SKNIT_F0, 2,12,12,L0|L1}, {SKNIT_FT0, 2,12,12,L0|L1},
+ {SKNIT_F1, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {SKNIT_FST, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {SKN_CY, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {SKN_Z, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {PUSH_BC, 2,21,21,L0|L1}, {POP_BC, 2,18,18,L0|L1},
+
+ /* 0x20 - 0x3F */
+ {EI, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {DI, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {CLC, 2,12,12,L0|L1}, {STC, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {PEX, 2,15,15,L0|L1},
+ {PUSH_DE, 2,21,21,L0|L1}, {POP_DE, 2,18,18,L0|L1},
+
+ {RLL_A, 2,12,12,L0|L1}, {RLR_A, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {RLD, 2,21,21,L0|L1}, {RRD, 2,21,21,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {PER, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {PUSH_HL, 2,21,21,L0|L1}, {POP_HL, 2,18,18,L0|L1},
+
+ /* 0x40 - 0x5F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0x60 - 0x7F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0x80 - 0x9F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0xA0 - 0xBF */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0xC0 - 0xDF */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0xE0 - 0xFF */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1}
+};
+
+static const struct opcode_s op4C_78c06[256] =
+{
+ /* 0x00 - 0x1F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0x20 - 0x3F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0x40 - 0x5F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0x60 - 0x7F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0x80 - 0x9F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0xA0 - 0xBF */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0xC0 - 0xDF */
+ {MOV_A_PA, 2,14,14,L0|L1}, {MOV_A_PB, 2,14,14,L0|L1},
+ {MOV_A_PC, 2,14,14,L0|L1}, {MOV_A_MKL, 2,14,14,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {MOV_A_S, 2,14,14,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0xE0 - 0xFF */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1}
+};
+
+/* prefix 4D */
+static const struct opcode_s op4D_78c06[256] =
+{
+ /* 0x00 - 0x1F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0x20 - 0x3F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0x40 - 0x5F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0x60 - 0x7F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0x80 - 0x9F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0xA0 - 0xBF */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0xC0 - 0xDF */
+ {MOV_PA_A, 2,14,14,L0|L1}, {MOV_PB_A, 2,14,14,L0|L1},
+ {MOV_PC_A, 2,14,14,L0|L1}, {MOV_MKL_A, 2,14,14,L0|L1},
+ {MOV_MB_A, 2,14,14,L0|L1}, {MOV_MC_A, 2,14,14,L0|L1},
+ {MOV_TM0_A, 2,14,14,L0|L1}, {MOV_TM1_A, 2,14,14,L0|L1},
+ {MOV_S_A, 2,14,14,L0|L1}, {MOV_TMM_A, 2,14,14,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0xE0 - 0xFF */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1}
+};
+
+/* prefix 60 */
+static const struct opcode_s op60_78c06[256] =
+{
+ /* 0x00 - 0x1F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {ANA_A_A, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {XRA_A_A, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {ORA_A_A, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0x20 - 0x3F */
+ {illegal2, 2,12,12,L0|L1}, {ADDNC_A_A, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {GTA_A_A, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {SUBNB_A_A, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {LTA_A_A, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0x40 - 0x5F */
+ {illegal2, 2,12,12,L0|L1}, {ADD_A_A, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {ADC_A_A, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0x60 - 0x7F */
+ {illegal2, 2, 8, 8,L0|L1}, {SUB_A_A, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {NEA_A_A, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {SBB_A_A, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {EQA_A_A, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0x80 - 0x9F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {ANA_A_A, 2,12,12,L0|L1},
+ {ANA_A_B, 2,12,12,L0|L1}, {ANA_A_C, 2,12,12,L0|L1},
+ {ANA_A_D, 2,12,12,L0|L1}, {ANA_A_E, 2,12,12,L0|L1},
+ {ANA_A_H, 2,12,12,L0|L1}, {ANA_A_L, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {XRA_A_A, 2,12,12,L0|L1},
+ {XRA_A_B, 2,12,12,L0|L1}, {XRA_A_C, 2,12,12,L0|L1},
+ {XRA_A_D, 2,12,12,L0|L1}, {XRA_A_E, 2,12,12,L0|L1},
+ {XRA_A_H, 2,12,12,L0|L1}, {XRA_A_L, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {ORA_A_A, 2,12,12,L0|L1},
+ {ORA_A_B, 2,12,12,L0|L1}, {ORA_A_C, 2,12,12,L0|L1},
+ {ORA_A_D, 2,12,12,L0|L1}, {ORA_A_E, 2,12,12,L0|L1},
+ {ORA_A_H, 2,12,12,L0|L1}, {ORA_A_L, 2,12,12,L0|L1},
+
+ /* 0xA0 - 0xBF */
+ {illegal2, 2,12,12,L0|L1}, {ADDNC_A_A, 2,12,12,L0|L1},
+ {ADDNC_A_B, 2,12,12,L0|L1}, {ADDNC_A_C, 2,12,12,L0|L1},
+ {ADDNC_A_D, 2,12,12,L0|L1}, {ADDNC_A_E, 2,12,12,L0|L1},
+ {ADDNC_A_H, 2,12,12,L0|L1}, {ADDNC_A_L, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {GTA_A_A, 2,12,12,L0|L1},
+ {GTA_A_B, 2,12,12,L0|L1}, {GTA_A_C, 2,12,12,L0|L1},
+ {GTA_A_D, 2,12,12,L0|L1}, {GTA_A_E, 2,12,12,L0|L1},
+ {GTA_A_H, 2,12,12,L0|L1}, {GTA_A_L, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {SUBNB_A_A, 2,12,12,L0|L1},
+ {SUBNB_A_B, 2,12,12,L0|L1}, {SUBNB_A_C, 2,12,12,L0|L1},
+ {SUBNB_A_D, 2,12,12,L0|L1}, {SUBNB_A_E, 2,12,12,L0|L1},
+ {SUBNB_A_H, 2,12,12,L0|L1}, {SUBNB_A_L, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {LTA_A_A, 2,12,12,L0|L1},
+ {LTA_A_B, 2,12,12,L0|L1}, {LTA_A_C, 2,12,12,L0|L1},
+ {LTA_A_D, 2,12,12,L0|L1}, {LTA_A_E, 2,12,12,L0|L1},
+ {LTA_A_H, 2,12,12,L0|L1}, {LTA_A_L, 2,12,12,L0|L1},
+
+ /* 0xC0 - 0xDF */
+ {illegal2, 2,12,12,L0|L1}, {ADD_A_A, 2,12,12,L0|L1},
+ {ADD_A_B, 2,12,12,L0|L1}, {ADD_A_C, 2,12,12,L0|L1},
+ {ADD_A_D, 2,12,12,L0|L1}, {ADD_A_E, 2,12,12,L0|L1},
+ {ADD_A_H, 2,12,12,L0|L1}, {ADD_A_L, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {ONA_A_A, 2,12,12,L0|L1},
+ {ONA_A_B, 2,12,12,L0|L1}, {ONA_A_C, 2,12,12,L0|L1},
+ {ONA_A_D, 2,12,12,L0|L1}, {ONA_A_E, 2,12,12,L0|L1},
+ {ONA_A_H, 2,12,12,L0|L1}, {ONA_A_L, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {ADC_A_A, 2,12,12,L0|L1},
+ {ADC_A_B, 2,12,12,L0|L1}, {ADC_A_C, 2,12,12,L0|L1},
+ {ADC_A_D, 2,12,12,L0|L1}, {ADC_A_E, 2,12,12,L0|L1},
+ {ADC_A_H, 2,12,12,L0|L1}, {ADC_A_L, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {OFFA_A_A, 2,12,12,L0|L1},
+ {OFFA_A_B, 2,12,12,L0|L1}, {OFFA_A_C, 2,12,12,L0|L1},
+ {OFFA_A_D, 2,12,12,L0|L1}, {OFFA_A_E, 2,12,12,L0|L1},
+ {OFFA_A_H, 2,12,12,L0|L1}, {OFFA_A_L, 2,12,12,L0|L1},
+
+ /* 0xE0 - 0xFF */
+ {illegal2, 2,12,12,L0|L1}, {SUB_A_A, 2,12,12,L0|L1},
+ {SUB_A_B, 2,12,12,L0|L1}, {SUB_A_C, 2,12,12,L0|L1},
+ {SUB_A_D, 2,12,12,L0|L1}, {SUB_A_E, 2,12,12,L0|L1},
+ {SUB_A_H, 2,12,12,L0|L1}, {SUB_A_L, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {NEA_A_A, 2,12,12,L0|L1},
+ {NEA_A_B, 2,12,12,L0|L1}, {NEA_A_C, 2,12,12,L0|L1},
+ {NEA_A_D, 2,12,12,L0|L1}, {NEA_A_E, 2,12,12,L0|L1},
+ {NEA_A_H, 2,12,12,L0|L1}, {NEA_A_L, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {SBB_A_A, 2,12,12,L0|L1},
+ {SBB_A_B, 2,12,12,L0|L1}, {SBB_A_C, 2,12,12,L0|L1},
+ {SBB_A_D, 2,12,12,L0|L1}, {SBB_A_E, 2,12,12,L0|L1},
+ {SBB_A_H, 2,12,12,L0|L1}, {SBB_A_L, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {EQA_A_A, 2,12,12,L0|L1},
+ {EQA_A_B, 2,12,12,L0|L1}, {EQA_A_C, 2,12,12,L0|L1},
+ {EQA_A_D, 2,12,12,L0|L1}, {EQA_A_E, 2,12,12,L0|L1},
+ {EQA_A_H, 2,12,12,L0|L1}, {EQA_A_L, 2,12,12,L0|L1}
+};
+
+/* prefix 64 */
+static const struct opcode_s op64_78c06[256] =
+{
+ /* 0x00 - 0x1F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {ANI_A_xx, 3,17,17,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {XRI_A_xx, 3,17,17,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {ORI_A_xx, 3,17,17,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0x20 - 0x3F */
+ {illegal2, 2,12,12,L0|L1}, {ADINC_A_xx, 3,17,17,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {GTI_A_xx, 3,17,17,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {SUINB_A_xx, 3,17,17,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 3,12,12,L0|L1}, {LTI_A_xx, 3,17,17,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0x40 - 0x5F */
+ {illegal2, 2,12,12,L0|L1}, {ADI_A_xx, 3,17,17,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {ONI_A_xx, 3,17,17,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 3,12,12,L0|L1}, {ACI_A_xx, 3,17,17,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 3,12,12,L0|L1}, {OFFI_A_xx, 3,17,17,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0x60 - 0x7F */
+ {illegal2, 2,12,12,L0|L1}, {SUI_A_xx, 3,17,17,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {NEI_A_xx, 3,17,17,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {SBI_A_xx, 3,17,17,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {EQI_A_xx, 3,17,17,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0x80 - 0x9F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {ANI_PA_xx, 3,23,23,L0|L1}, {ANI_PB_xx, 3,23,23,L0|L1},
+ {ANI_PC_xx, 3,23,23,L0|L1}, {ANI_MKL_xx, 3,23,23,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {XRI_PA_xx, 3,23,23,L0|L1}, {XRI_PB_xx, 3,23,23,L0|L1},
+ {XRI_PC_xx, 3,23,23,L0|L1}, {XRI_MKL_xx, 3,23,23,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {ORI_PA_xx, 3,23,23,L0|L1}, {ORI_PB_xx, 3,23,23,L0|L1},
+ {ORI_PC_xx, 3,23,23,L0|L1}, {ORI_MKL_xx, 3,23,23,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0xA0 - 0xBF */
+ {ADINC_PA_xx, 3,23,23,L0|L1}, {ADINC_PB_xx, 3,23,23,L0|L1},
+ {ADINC_PC_xx, 3,23,23,L0|L1}, {ADINC_MKL_xx, 3,23,23,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {GTI_PA_xx, 3,20,20,L0|L1}, {GTI_PB_xx, 3,20,20,L0|L1},
+ {GTI_PC_xx, 3,20,20,L0|L1}, {GTI_MKL_xx, 3,20,20,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {SUINB_PA_xx, 3,23,23,L0|L1}, {SUINB_PB_xx, 3,23,23,L0|L1},
+ {SUINB_PC_xx, 3,23,23,L0|L1}, {SUINB_MKL_xx, 3,23,23,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {LTI_PA_xx, 3,20,20,L0|L1}, {LTI_PB_xx, 3,20,20,L0|L1},
+ {LTI_PC_xx, 3,20,20,L0|L1}, {LTI_MKL_xx, 3,20,20,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0xC0 - 0xDF */
+ {ADI_PA_xx, 3,23,23,L0|L1}, {ADI_PB_xx, 3,23,23,L0|L1},
+ {ADI_PC_xx, 3,23,23,L0|L1}, {ADI_MKL_xx, 3,23,23,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {ONI_PA_xx, 3,20,20,L0|L1}, {ONI_PB_xx, 3,20,20,L0|L1},
+ {ONI_PC_xx, 3,20,20,L0|L1}, {ONI_MKL_xx, 3,20,20,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {ACI_PA_xx, 3,23,23,L0|L1}, {ACI_PB_xx, 3,23,23,L0|L1},
+ {ACI_PC_xx, 3,23,23,L0|L1}, {ACI_MKL_xx, 3,23,23,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {OFFI_PA_xx, 3,20,20,L0|L1}, {OFFI_PB_xx, 3,20,20,L0|L1},
+ {OFFI_PC_xx, 3,20,20,L0|L1}, {OFFI_MKL_xx, 3,20,20,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0xE0 - 0xFF */
+ {SUI_PA_xx, 3,23,23,L0|L1}, {SUI_PB_xx, 3,23,23,L0|L1},
+ {SUI_PC_xx, 3,23,23,L0|L1}, {SUI_MKL_xx, 3,23,23,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {NEI_PA_xx, 3,20,20,L0|L1}, {NEI_PB_xx, 3,20,20,L0|L1},
+ {NEI_PC_xx, 3,20,20,L0|L1}, {NEI_MKL_xx, 3,20,20,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {SBI_PA_xx, 3,23,23,L0|L1}, {SBI_PB_xx, 3,23,23,L0|L1},
+ {SBI_PC_xx, 3,23,23,L0|L1}, {SBI_MKL_xx, 3,23,23,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {EQI_PA_xx, 3,20,20,L0|L1}, {EQI_PB_xx, 3,20,20,L0|L1},
+ {EQI_PC_xx, 3,20,20,L0|L1}, {EQI_MKL_xx, 3,20,20,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1}
+};
+
+/* prefix 70 */
+static const struct opcode_s op70_78c06[256] =
+{
+ /* 0x00 - 0x1F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {SSPD_w, 4,28,28,L0|L1}, {LSPD_w, 4,28,28,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {SBCD_w, 4,28,28,L0|L1}, {LBCD_w, 4,28,28,L0|L1},
+
+ /* 0x20 - 0x3F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {SDED_w, 4,28,28,L0|L1}, {LDED_w, 4,28,28,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {SHLD_w, 4,28,28,L0|L1}, {LHLD_w, 4,28,28,L0|L1},
+
+ /* 0x40 - 0x5F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0x60 - 0x7F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {MOV_A_w, 4,25,25,L0|L1},
+ {MOV_B_w, 4,25,25,L0|L1}, {MOV_C_w, 4,25,25,L0|L1},
+ {MOV_D_w, 4,25,25,L0|L1}, {MOV_E_w, 4,25,25,L0|L1},
+ {MOV_H_w, 4,25,25,L0|L1}, {MOV_L_w, 4,25,25,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {MOV_w_A, 4,25,25,L0|L1},
+ {MOV_w_B, 4,25,25,L0|L1}, {MOV_w_C, 4,25,25,L0|L1},
+ {MOV_w_D, 4,25,25,L0|L1}, {MOV_w_E, 4,25,25,L0|L1},
+ {MOV_w_H, 4,25,25,L0|L1}, {MOV_w_L, 4,25,25,L0|L1},
+
+ /* 0x80 - 0x9F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {ANAX_B, 2,15,15,L0|L1},
+ {ANAX_D, 2,15,15,L0|L1}, {ANAX_H, 2,15,15,L0|L1},
+ {ANAX_Dp, 2,15,15,L0|L1}, {ANAX_Hp, 2,15,15,L0|L1},
+ {ANAX_Dm, 2,15,15,L0|L1}, {ANAX_Hm, 2,15,15,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {XRAX_B, 2,15,15,L0|L1},
+ {XRAX_D, 2,15,15,L0|L1}, {XRAX_H, 2,15,15,L0|L1},
+ {XRAX_Dp, 2,15,15,L0|L1}, {XRAX_Hp, 2,15,15,L0|L1},
+ {XRAX_Dm, 2,15,15,L0|L1}, {XRAX_Hm, 2,15,15,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {ORAX_B, 2,15,15,L0|L1},
+ {ORAX_D, 2,15,15,L0|L1}, {ORAX_H, 2,15,15,L0|L1},
+ {ORAX_Dp, 2,15,15,L0|L1}, {ORAX_Hp, 2,15,15,L0|L1},
+ {ORAX_Dm, 2,15,15,L0|L1}, {ORAX_Hm, 2,15,15,L0|L1},
+
+ /* 0xA0 - 0xBF */
+ {illegal2, 2,12,12,L0|L1}, {ADDNCX_B, 2,15,15,L0|L1},
+ {ADDNCX_D, 2,15,15,L0|L1}, {ADDNCX_H, 2,15,15,L0|L1},
+ {ADDNCX_Dp, 2,15,15,L0|L1}, {ADDNCX_Hp, 2,15,15,L0|L1},
+ {ADDNCX_Dm, 2,15,15,L0|L1}, {ADDNCX_Hm, 2,15,15,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {GTAX_B, 2,15,15,L0|L1},
+ {GTAX_D, 2,15,15,L0|L1}, {GTAX_H, 2,15,15,L0|L1},
+ {GTAX_Dp, 2,15,15,L0|L1}, {GTAX_Hp, 2,15,15,L0|L1},
+ {GTAX_Dm, 2,15,15,L0|L1}, {GTAX_Hm, 2,15,15,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {SUBNBX_B, 2,15,15,L0|L1},
+ {SUBNBX_D, 2,15,15,L0|L1}, {SUBNBX_H, 2,15,15,L0|L1},
+ {SUBNBX_Dp, 2,15,15,L0|L1}, {SUBNBX_Hp, 2,15,15,L0|L1},
+ {SUBNBX_Dm, 2,15,15,L0|L1}, {SUBNBX_Hm, 2,15,15,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {LTAX_B, 2,15,15,L0|L1},
+ {LTAX_D, 2,15,15,L0|L1}, {LTAX_H, 2,15,15,L0|L1},
+ {LTAX_Dp, 2,15,15,L0|L1}, {LTAX_Hp, 2,15,15,L0|L1},
+ {LTAX_Dm, 2,15,15,L0|L1}, {LTAX_Hm, 2,15,15,L0|L1},
+
+ /* 0xC0 - 0xDF */
+ {illegal2, 2,12,12,L0|L1}, {ADDX_B, 2,15,15,L0|L1},
+ {ADDX_D, 2,15,15,L0|L1}, {ADDX_H, 2,15,15,L0|L1},
+ {ADDX_Dp, 2,15,15,L0|L1}, {ADDX_Hp, 2,15,15,L0|L1},
+ {ADDX_Dm, 2,15,15,L0|L1}, {ADDX_Hm, 2,15,15,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {ONAX_B, 2,15,15,L0|L1},
+ {ONAX_D, 2,15,15,L0|L1}, {ONAX_H, 2,15,15,L0|L1},
+ {ONAX_Dp, 2,15,15,L0|L1}, {ONAX_Hp, 2,15,15,L0|L1},
+ {ONAX_Dm, 2,15,15,L0|L1}, {ONAX_Hm, 2,15,15,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {ADCX_B, 2,15,15,L0|L1},
+ {ADCX_D, 2,15,15,L0|L1}, {ADCX_H, 2,15,15,L0|L1},
+ {ADCX_Dp, 2,15,15,L0|L1}, {ADCX_Hp, 2,15,15,L0|L1},
+ {ADCX_Dm, 2,15,15,L0|L1}, {ADCX_Hm, 2,15,15,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {OFFAX_B, 2,15,15,L0|L1},
+ {OFFAX_D, 2,15,15,L0|L1}, {OFFAX_H, 2,15,15,L0|L1},
+ {OFFAX_Dp, 2,15,15,L0|L1}, {OFFAX_Hp, 2,15,15,L0|L1},
+ {OFFAX_Dm, 2,15,15,L0|L1}, {OFFAX_Hm, 2,15,15,L0|L1},
+
+ /* 0xE0 - 0xFF */
+ {illegal2, 2,12,12,L0|L1}, {SUBX_B, 2,15,15,L0|L1},
+ {SUBX_D, 2,15,15,L0|L1}, {SUBX_H, 2,15,15,L0|L1},
+ {SUBX_Dp, 2,15,15,L0|L1}, {SUBX_Hp, 2,15,15,L0|L1},
+ {SUBX_Dm, 2,15,15,L0|L1}, {SUBX_Hm, 2,15,15,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {NEAX_B, 2,15,15,L0|L1},
+ {NEAX_D, 2,15,15,L0|L1}, {NEAX_H, 2,15,15,L0|L1},
+ {NEAX_Dp, 2,15,15,L0|L1}, {NEAX_Hp, 2,15,15,L0|L1},
+ {NEAX_Dm, 2,15,15,L0|L1}, {NEAX_Hm, 2,15,15,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {SBBX_B, 2,15,15,L0|L1},
+ {SBBX_D, 2,15,15,L0|L1}, {SBBX_H, 2,15,15,L0|L1},
+ {SBBX_Dp, 2,15,15,L0|L1}, {SBBX_Hp, 2,15,15,L0|L1},
+ {SBBX_Dm, 2,15,15,L0|L1}, {SBBX_Hm, 2,15,15,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {EQAX_B, 2,15,15,L0|L1},
+ {EQAX_D, 2,15,15,L0|L1}, {EQAX_H, 2,15,15,L0|L1},
+ {EQAX_Dp, 2,15,15,L0|L1}, {EQAX_Hp, 2,15,15,L0|L1},
+ {EQAX_Dm, 2,15,15,L0|L1}, {EQAX_Hm, 2,15,15,L0|L1}
+};
+
+/* prefix 74 */
+static const struct opcode_s op74_78c06[256] =
+{
+ /* 0x00 - 0x1F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0x20 - 0x3F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0x40 - 0x5F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0x60 - 0x7F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0x80 - 0x9F */
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {ANAW_wa, 3,14,14,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {XRAW_wa, 3,14,14,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {ORAW_wa, 3,14,14,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0xA0 - 0xBF */
+ {ADDNCW_wa, 3,14,14,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {GTAW_wa, 3,14,14,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {SUBNBW_wa, 3,14,14,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {LTAW_wa, 3,14,14,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0xC0 - 0xDF */
+ {ADDW_wa, 3,14,14,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {ONAW_wa, 3,14,14,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {ADCW_wa, 3,14,14,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {OFFAW_wa, 3,14,14,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ /* 0xE0 - 0xFF */
+ {SUBW_wa, 3,14,14,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {NEAW_wa, 3,14,14,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+
+ {SBBW_wa, 3,14,14,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {EQAW_wa, 3,14,14,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1},
+ {illegal2, 2,12,12,L0|L1}, {illegal2, 2,12,12,L0|L1}
+};
+
+static const struct opcode_s opXX_78c06[256] =
+{
+ /* 0x00 - 0x1F */
+ {NOP, 1, 6, 6,L0|L1}, {HALT, 1, 6, 6,L0|L1},
+ {INX_SP, 1, 9, 9,L0|L1}, {DCX_SP, 1, 9, 9,L0|L1},
+ {LXI_S_w, 3,16,16,L0|L1}, {ANIW_wa_xx, 3,22,22,L0|L1},
+ {illegal, 1, 6, 6,L0|L1}, {ANI_A_xx, 2,11,11,L0|L1},
+ {RET, 1,12,12,L0|L1}, {SIO, 1, 6, 6,L0|L1},
+ {MOV_A_B, 1, 6, 6,L0|L1}, {MOV_A_C, 1, 6, 6,L0|L1},
+ {MOV_A_D, 1, 6, 6,L0|L1}, {MOV_A_E, 1, 6, 6,L0|L1},
+ {MOV_A_H, 1, 6, 6,L0|L1}, {MOV_A_L, 1, 6, 6,L0|L1},
+
+ {illegal, 1, 6, 6,L0|L1}, {illegal, 1, 6, 6,L0|L1},
+ {INX_BC, 1, 9, 9,L0|L1}, {DCX_BC, 1, 9, 9,L0|L1},
+ {LXI_B_w, 3,16,16,L0|L1}, {ORIW_wa_xx, 3,22,2,L0|L1},
+ {XRI_A_xx, 2,11,11,L0|L1}, {ORI_A_xx, 2,11,11,L0|L1},
+ {RETS, 1,12,12,L0|L1}, {STM, 1, 6, 6,L0|L1},
+ {MOV_B_A, 1, 6, 6,L0|L1}, {MOV_C_A, 1, 6, 6,L0|L1},
+ {MOV_D_A, 1, 6, 6,L0|L1}, {MOV_E_A, 1, 6, 6,L0|L1},
+ {MOV_H_A, 1, 6, 6,L0|L1}, {MOV_L_A, 1, 6, 6,L0|L1},
+
+ /* 0x20 - 0x3F */
+ {INRW_wa_7801, 2,17,17,L0|L1}, {illegal, 1, 4, 4,L0|L1},
+ {INX_DE, 1, 9, 9,L0|L1}, {DCX_DE, 1, 9, 9,L0|L1},
+ {LXI_D_w, 3,16,16,L0|L1}, {GTIW_wa_xx, 3,19,19,L0|L1},
+ {ADINC_A_xx, 2,11,11,L0|L1}, {GTI_A_xx, 2,11,11,L0|L1},
+ {LDAW_wa, 2,14,14,L0|L1}, {LDAX_B, 1, 9, 9,L0|L1},
+ {LDAX_D, 1, 9, 9,L0|L1}, {LDAX_H, 1, 9, 9,L0|L1},
+ {LDAX_Dp, 1, 9, 9,L0|L1}, {LDAX_Hp, 1, 9, 9,L0|L1},
+ {LDAX_Dm, 1, 9, 9,L0|L1}, {LDAX_Hm, 1, 9, 9,L0|L1},
+
+ {DCRW_wa_7801, 2,17,17,L0|L1}, {illegal, 1, 4, 4,L0|L1},
+ {INX_HL, 1, 9, 9,L0|L1}, {DCX_HL, 1, 9, 9,L0|L1},
+ {LXI_H_w, 3,16,16, L1}, {LTIW_wa_xx, 3,19,19,L0|L1},
+ {SUINB_A_xx, 2,11,11,L0|L1}, {LTI_A_xx, 2,11,11,L0|L1},
+ {STAW_wa, 2,14,14,L0|L1}, {STAX_B, 1, 9, 9,L0|L1},
+ {STAX_D, 1, 9, 9,L0|L1}, {STAX_H, 1, 9, 9,L0|L1},
+ {STAX_Dp, 1, 9, 9,L0|L1}, {STAX_Hp, 1, 9, 9,L0|L1},
+ {STAX_Dm, 1, 9, 9,L0|L1}, {STAX_Hm, 1, 9, 9,L0|L1},
+
+ /* 0x40 - 0x5F */
+ {illegal, 1, 6, 6,L0|L1}, {INR_A_7801, 1, 6, 6,L0|L1},
+ {INR_B_7801, 1, 6, 6,L0|L1}, {INR_C_7801, 1, 6, 6,L0|L1},
+ {CALL_w, 3,22,22,L0|L1}, {ONIW_wa_xx, 3,19,19,L0|L1},
+ {ADI_A_xx, 2,11,11,L0|L1}, {ONI_A_xx, 2,11,11,L0|L1},
+ {PRE_48, 1, 0, 0,L0|L1}, {illegal, 1, 6, 6,L0|L1},
+ {illegal, 1, 6, 6,L0|L1}, {illegal, 1, 6, 6,L0|L1},
+ {PRE_4C, 1, 0, 0,L0|L1}, {PRE_4D, 1, 0, 0,L0|L1},
+ {JRE, 2,17,17,L0|L1}, {JRE, 2,17,17,L0|L1},
+
+ {illegal, 1, 6, 6,L0|L1}, {DCR_A_7801, 1, 6, 6,L0|L1},
+ {DCR_B_7801, 1, 6, 6,L0|L1}, {DCR_C_7801, 1, 6, 6,L0|L1},
+ {JMP_w, 3,16,16,L0|L1}, {OFFIW_wa_xx, 3,19,19,L0|L1},
+ {ACI_A_xx, 2,11,11,L0|L1}, {OFFI_A_xx, 2,11,11,L0|L1},
+ {illegal, 1, 6, 6,L0|L1}, {illegal, 1, 6, 6,L0|L1},
+ {illegal, 1, 6, 6,L0|L1}, {illegal, 1, 6, 6,L0|L1},
+ {illegal, 1, 6, 6,L0|L1}, {illegal, 1, 6, 6,L0|L1},
+ {illegal, 1, 6, 6,L0|L1}, {illegal, 1, 6, 6,L0|L1},
+
+ /* 0x60 - 0x7F */
+ {PRE_60, 1, 0, 0,L0|L1}, {DAA, 1, 6, 6,L0|L1},
+ {RETI, 1,15,15,L0|L1}, {CALB, 2,13,13,L0|L1},
+ {PRE_64, 1, 0, 0,L0|L1}, {NEIW_wa_xx, 3,19,19,L0|L1},
+ {SUI_A_xx, 2,11,11,L0|L1}, {NEI_A_xx, 2,11,11,L0|L1},
+ {illegal, 1, 6, 6,L0|L1}, {MVI_A_xx, 2,11,11,L0 },
+ {MVI_B_xx, 2,11,11,L0|L1}, {MVI_C_xx, 2,11,11,L0|L1},
+ {MVI_D_xx, 2,11,11,L0|L1}, {MVI_E_xx, 2,11,11,L0|L1},
+ {MVI_H_xx, 2,11,11,L0|L1}, {MVI_L_xx, 2,11,11, L1},
+
+ {PRE_70, 1, 0, 0,L0|L1}, {MVIW_wa_xx, 3,13,13,L0|L1},
+ {SOFTI, 1,19,19,L0|L1}, {JB, 1, 6, 6,L0|L1},
+ {PRE_74, 1, 0, 0,L0|L1}, {EQIW_wa_xx, 3,19,19,L0|L1},
+ {SBI_A_xx, 2,11,11,L0|L1}, {EQI_A_xx, 2,11,11,L0|L1},
+ {CALF, 2,17,17,L0|L1}, {CALF, 2,17,17,L0|L1},
+ {CALF, 2,17,17,L0|L1}, {CALF, 2,17,17,L0|L1},
+ {CALF, 2,17,17,L0|L1}, {CALF, 2,17,17,L0|L1},
+ {CALF, 2,17,17,L0|L1}, {CALF, 2,17,17,L0|L1},
+
+ /* 0x80 - 0x9F */
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+
+ /* 0xA0 - 0xBF */
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+ {CALT_7801, 1,19,19,L0|L1}, {CALT_7801, 1,19,19,L0|L1},
+
+ /* 0xC0 - 0xDF */
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+
+ /* 0xE0 - 0xFF */
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1},
+ {JR, 1,12,12,L0|L1}, {JR, 1,12,12,L0|L1}
+};
diff --git a/trunk/src/emu/cpu/upd7810/upd7810.c b/trunk/src/emu/cpu/upd7810/upd7810.c
new file mode 100644
index 00000000000..c67992615c1
--- /dev/null
+++ b/trunk/src/emu/cpu/upd7810/upd7810.c
@@ -0,0 +1,2390 @@
+/*****************************************************************************
+ *
+ * upd7810.h
+ * Portable uPD7810/11, 7810H/11H, 78C10/C11/C14 emulator V0.3
+ *
+ * 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.
+ *
+ *
+ * This work is based on the
+ * "NEC Electronics User's Manual, April 1987"
+ *
+ * NS20030115:
+ * - fixed INRW_wa(cpustate)
+ * - TODO: add 7807, differences are listed below.
+ * I only added support for these opcodes needed by homedata.c (yes, I am
+ * lazy):
+ * 4C CE (MOV A,PT)
+ * 48 AC (EXA)
+ * 48 AD (EXR)
+ * 48 AE (EXH)
+ * 48 AF (EXX)
+ * 50 xx (SKN bit)
+ * 58 xx (SETB)
+ * 5B xx (CLR)
+ * 5D xx (SK bit)
+ *
+ * 2008-02-24 (Wilbert Pol):
+ * - Added preliminary support for uPD7801
+ * For the uPD7801 only the basic instruction set was added. The current timer
+ * and serial i/o implementations are most likely incorrect.
+ * - Added basic support for uPD78C05 and uPD78C06
+ * Documentation of the actual instruction set layout is missing, so we took
+ * the uPD7801 instruction set and only kept the instructions mentioned in
+ * the little documentation available on the uPD78c05A/06A. The serial i/o
+ * implementation has not been tested and is probably incorrect.
+ *
+ *****************************************************************************/
+/* Hau around 23 May 2004
+ gta, gti, dgt fixed
+ working reg opcodes fixed
+ sio input fixed
+--
+ PeT around 19 February 2002
+ type selection/gamemaster support added
+ gamemaster init hack? added
+ ORAX added
+ jre negativ fixed
+ prefixed opcodes skipping fixed
+ interrupts fixed and improved
+ sub(and related)/add/daa flags fixed
+ mvi ports,... fixed
+ rll, rlr, drll, drlr fixed
+ rets fixed
+ l0, l1 skipping fixed
+ calt fixed
+*/
+
+/*
+
+7807 DESCRIPTION
+
+
+
+ PA0 1 64 Vcc
+ PA1 2 63 Vdd
+ PA2 3 62 PD7/AD7
+ PA3 4 61 PD6/AD6
+ PA4 5 60 PD5/AD5
+ PA5 6 59 PD4/AD4
+ PA6 7 58 PD3/AD3
+ PA7 8 57 PD2/AD2
+ PB0 9 56 PD1/AD1
+ PB1 10 55 PD0/AD0
+ PB2 11 54 PF7/AB15
+ PB3 12 53 PF6/AB14
+ PB4 13 52 PF5/AB13
+ PB5 14 51 PF4/AB12
+ PB6 15 50 PF3/AB11
+ PB7 16 49 PF2/AB10
+ PC0 17 48 PF1/AB9
+ PC1 18 47 PF0/AB8
+ PC2 19 46 ALE
+ PC3 20 45 WR*
+ PC4 21 44 RD*
+ PC5 22 43 HLDA
+ PC6 23 42 HOLD
+ PC7 24 41 PT7
+ NMI* 25 40 PT6
+ INT1 26 39 PT5
+ MODE1 27 38 PT4
+RESET* 28 37 PT3
+ MODE0 29 36 PT2
+ X2 30 35 PT1
+ X1 31 34 PT0
+ Vss 32 33 Vth
+
+PA, PB, PC, PD, and PF is bidirectional I/O port
+and PT is comparator input port in uPD7808.
+uPD7807 uses PD port as data I/O and bottom address output,
+and uses PF port as top address output.
+
+NMI* is non maskable interrupt input signal (negative edge trigger).
+
+INT1 is interrupt input (positive edge trigger). It can be used as
+AC zero-cross input or trigger source of 16bit timer counter.
+
+MODE0 and MODE1 is input terminal which decides total amount of
+external memory of uPD7807 (4KByte, 16KBYte, and 64KByte).
+It also decides number of PF ports used as top address output.
+ 4KByte mode: PF0~PF3=address output, PF4~PF7=data I/O port
+16KByte mode: PF0~PF5=address output, PF6~PF7=data I/O port
+64KByte mode: PF0~PF7=address output
+
+RESET* is system rest terminal.
+
+X1 and X2 does clock signal generation (connect OSC and condenser).
+
+Vth is used to determine threshold voltage for PT port.
+PT0~PT7 is connected to + input of each comparator,
+and Vth deterimnes voltage connected to - input of PT0~PT7.
+But the voltage of Vth is not directly connected to comapators.
+It is connected via 16-level programmable voltage separate circuit.
+
+HOLD and HLDA is terminal for DMA. RD*, WR*, and ALE is bus
+interface signal (they are same type of Intel 8085).
+Unlike 8085, I/O address space is not available, so IO /M* signal
+does not exist. Read/write of external memory can be done
+by RD*, WR*, and ALE only.
+
+Vcc and Vss is main power source. Vdd is backup power source
+for internal RWM (32 Byte).
+
+
+PA and PB is I/O port. They have control register MA and MB.
+If control register is set to 1, the port is input.
+If control register is set to 0, the port is output.
+They are set to 1 by reset.
+
+PT is input-only port. It is consisted of input terminal PT0~PT7
+and Vth (set threshold voltage). Each PT input has analog comparator
+and latch, and + input of analog comparator is connected to
+PT terminal. Every - input of analog comparator is connected
+to devided voltage of Vth. Voltage dividing level can be set by
+bottom 4bits of MT (mode T) register. The range is 1/16~16/16 of Vth.
+
+Other internal I/Os are
+8bit timer (x2): Upcounter. If the counter matches to specified value,
+the timer is reset and counts again from 0.
+You can also set it to generate interrupt, or invert output flip-flop
+when the counter matches to specified value.
+Furthermore, you can output that flip-flop output to PC4/TO output,
+connect it to clock input of timer/event counter or watchdog timer.
+Or you can use it as bitrate clock of serial interface.
+Note: There is only 1 output flip-flop for 2 timers.
+If you use it for timer output of 1 timer, another timer cannot be used
+for other than interrupt generator.
+Clock input for timer can be switched between internal clock (2 type)
+or PC3/TI input. You can set 1 timer's match-output as another timer's
+clock input, so that you can use them as 1 16bit timer.
+
+16bit timer/event counter (x1): It can be used as
+- Interval timer
+- External event counter
+- Frequency measurement
+- Pulse width measurement
+- Programmable rectangle wave output
+- One pulse output
+Related terminals are PC5/CI input, PC6/CO0 output, and PC7/CO1.
+You can measure CI input's H duration, or you can output timing signal
+(with phase difference) to CO0 and CO1.
+
+serial I/F (x1): has 3 modes.
+- Asynchronous mode
+- Synchronous mode
+- I/O interface mode
+In all 3 modes, bitrate can be internal fixed clock, or timer output,
+or external clock.
+In asynchronous mode, you can
+- switch 7bit/8bit data
+- set parity ON/OFF and EVEN/ODD
+- set 1/2 stop bit
+
+
+
+
+DIFFERENCES BETWEEN 7810 and 7807
+
+--------------------------
+8bit transfer instructions
+--------------------------
+
+7810
+inst. 1st byte 2nd byte state action
+EXX 00001001 4 Swap BC DE HL
+EXA 00001000 4 Swap VA EA
+EXH 01010000 4 Swap HL
+BLOCK 00110001 13(C+1) (DE)+ <- (HL)+, C <- C - 1, until CY
+
+7807
+inst. 1st byte 2nd byte state action
+EXR 01001000 10101101 8 Swap VA BC DE HL EA
+EXX 01001000 10101111 8 Swap BC DE HL
+EXA 01001000 10101100 8 Swap VA EA
+EXH 01001000 10101110 8 Swap HL
+BLOCK D+ 00010000 13(C+1) (DE)+ <- (HL)+, C <- C - 1, until CY
+BLOCK D- 00010001 13(C+1) (DE)- <- (HL)-, C <- C - 1, until CY
+
+
+---------------------------
+16bit transfer instructions
+---------------------------
+All instructions are same except operand sr4 of DMOV instruction.
+7810
+V0-sr4 -function
+ 0-ECNT-timer/event counter upcounter
+ 1-ECPT-timer/event counter capture
+
+7807
+V1-V0- sr4 -function
+ 0- 0-ECNT -timer/event counter upcounter
+ 0- 1-ECPT0-timer/event counter capture 0
+ 1- 0-ECPT1-timer/event counter capture 1
+
+
+-----------------------------------------
+8bit operation instructions for registers
+-----------------------------------------
+All instructions are same.
+
+
+--------------------------------------
+8bit operation instructions for memory
+--------------------------------------
+All instructions are same.
+
+
+-----------------------------------------
+Operation instructions for immediate data
+-----------------------------------------
+uPD7807 has read-only PT port and special register group sr5 for it.
+ins. 1st byte 2nd byte 3rd 4th state func
+GTI sr5, byte 01100100 s0101sss dd 14 !CY sr5 - byte - 1
+LTI sr5, byte 01100100 s0111sss dd 14 CY sr5 - byte
+NEI sr5, byte 01100100 s1101sss dd 14 !Z sr5 - byte
+EQI sr5, byte 01100100 s1111sss dd 14 Z sr5 - byte
+ONI sr5, byte 01100100 s1001sss dd 14 !Z sr5 & byte
+OFFI sr5, byte 01100100 s1011sss dd 14 Z sr5 & byte
+
+S5-S4-S3-S2-S1-S0-sr -sr1-sr2-sr5-register function
+ 0 0 1 1 1 0 --- PT --- PT comparator input port T data
+ 1 0 0 1 0 0 WDM WDM --- --- watchdog timer mode register
+ 1 0 0 1 0 1 MT --- --- --- port T mode
+
+7807 doesn't have registers below
+ 0 0 1 0 0 0 ANM ANM ANM A/D channel mode
+ 1 0 0 0 0 0 --- CR0 --- A/D conversion result 0
+ 1 0 0 0 0 1 --- CR1 --- A/D conversion result 1
+ 1 0 0 0 1 0 --- CR2 --- A/D conversion result 2
+ 1 0 0 0 1 1 --- CR3 --- A/D conversion result 3
+ 1 0 1 0 0 0 ZCM --- --- zero cross mode
+
+Special register operand (includes registers for I/O ports) has
+6 groups - sr, sr1, sr2, sr3, sr4, and sr5. Among these groups,
+sr, sr1, sr2, and sr5 includes registers described in the table
+below, and expressed as bit pattern S5-S0.
+
+S5S4S3S2S1S0 sr sr1 sr2 sr5 register function
+0 0 0 0 0 0 PA PA PA PA port A
+0 0 0 0 0 1 PB PB PB PB port B
+0 0 0 0 1 0 PC PC PC PC port C
+0 0 0 0 1 1 PD PD PD PD port D
+0 0 0 1 0 1 PF PF PF PF port F
+0 0 0 1 1 0 MKH MKH MKH MKH mask high
+0 0 0 1 1 1 MKL MKL MKL MKL mask low
+0 0 1 0 0 1 SMH SMH SMH SMH serial mode high
+0 0 1 0 1 0 SML --- --- --- serial mode low
+0 0 1 0 1 1 EOM EOM EOM EOM timer/event counter output mode
+0 0 1 1 0 0 ETMM --- --- --- timer/event counter mode
+0 0 1 1 0 1 TMM TMM TMM TMM timer mode
+0 0 1 1 1 0 --- PT --- PT port T
+0 1 0 0 0 0 MM --- --- --- memory mapping
+0 1 0 0 0 1 MCC --- --- --- mode control C
+0 1 0 0 1 0 MA --- --- --- mode A
+0 1 0 0 1 1 MB --- --- --- mode B
+0 1 0 1 0 0 MC --- --- --- mode C
+0 1 0 1 1 1 MF --- --- --- mode F
+0 1 1 0 0 0 TXB --- --- --- Tx buffer
+0 1 1 0 0 1 --- RXB --- --- Rx buffer
+0 1 1 0 1 0 TM0 --- --- --- timer register 0
+0 1 1 0 1 1 TM1 --- --- --- timer register 1
+1 0 0 1 0 0 WDM WDM --- --- watchdog timer mode
+1 0 0 1 0 1 MT --- --- --- mode T
+
+For sr and sr1, all 6bits (S5, S4, S3, S2, S1, and S0) are used.
+For sr2 and sr5, only 4bits (S3, S2, S1, AND S0) are used.
+They are expressed as 'ssssss' and 's sss' in operation code.
+Note that 's sss' (of sr2 and sr5) is located separately.
+S0 is rightmost bit (LSB).
+
+
+--------------------------------------------
+Operation instructions for working registers
+--------------------------------------------
+All instructions are same.
+
+
+--------------------------------------------------------------------------
+16bit operation instructions and divider/multiplier operation instructions
+--------------------------------------------------------------------------
+All instructions are same.
+
+
+------------------------------------------
+Increment/decrement operation instructions
+------------------------------------------
+All instructions are same.
+
+
+----------------------------
+Other operation instructions
+----------------------------
+7807 has CMC instruction (inverts CY flag).
+ins. 1st byte 2nd byte 3rd 4th state func
+CMC 01001000 10101010 8 CY <- !CY
+
+
+---------------------------
+Rotation/shift instructions
+---------------------------
+All instructions are same.
+
+
+-----------------------------
+Jump/call/return instructions
+-----------------------------
+All instructions are same.
+
+
+-----------------
+Skip instructions
+-----------------
+7807 doesn't have this
+ins. 1st byte 2nd byte 3rd 4th state func
+BIT bit, wa 01011bbb wwwwwwww 10* bit skip if (V.wa).bit = 1
+
+Instead, 7807 has these bit manipulation instructions.
+ins. 1st byte 2nd byte 3rd 4th state func
+MOV CY, bit 01011111 bbbbbbbb 10* CY <- (bit)
+MOV bit, CY 01011010 bbbbbbbb 13* (bit) <- CY
+AND CY, bit 00110001 bbbbbbbb 10* CY <- CY & (bit)
+OR CY, bit 01011100 bbbbbbbb 10* CY <- CY | (bit)
+XOR CY, bit 01011110 bbbbbbbb 10* CY <- CY ^ (bit)
+SETB bit 01011000 bbbbbbbb 13* (bit) <- 1
+CLR bit 01011011 bbbbbbbb 13* (bit) <- 0
+NOT bit 01011001 bbbbbbbb 13* (bit) <- !(bit)
+SK bit 01011101 bbbbbbbb 10* (b) skip if (bit) = 1
+SKN bit 01010000 bbbbbbbb 10* !(b) skip if (bit) = 0
+
+
+------------------------
+CPU control instructions
+------------------------
+ins. 1st byte 2nd byte 3rd 4th state func
+HLT 01001000 00111011 11/12 halt
+11 state in uPD7807 and uPD7810, 12 state in uPD78C10.
+
+STOP 01001000 10111011 12 stop
+7807 doesn't have STOP instruction.
+
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "upd7810.h"
+
+typedef struct _upd7810_state upd7810_state;
+struct _upd7810_state
+{
+ PAIR ppc; /* previous program counter */
+ PAIR pc; /* program counter */
+ PAIR sp; /* stack pointer */
+ UINT8 op; /* opcode */
+ UINT8 op2; /* opcode part 2 */
+ UINT8 iff; /* interrupt enable flip flop */
+ UINT8 psw; /* processor status word */
+ PAIR ea; /* extended accumulator */
+ PAIR va; /* accumulator + vector register */
+ PAIR bc; /* 8bit B and C registers / 16bit BC register */
+ PAIR de; /* 8bit D and E registers / 16bit DE register */
+ PAIR hl; /* 8bit H and L registers / 16bit HL register */
+ PAIR ea2; /* alternate register set */
+ PAIR va2;
+ PAIR bc2;
+ PAIR de2;
+ PAIR hl2;
+ PAIR cnt; /* 8 bit timer counter */
+ PAIR tm; /* 8 bit timer 0/1 comparator inputs */
+ PAIR ecnt; /* timer counter register / capture register */
+ PAIR etm; /* timer 0/1 comparator inputs */
+ UINT8 ma; /* port A input or output mask */
+ UINT8 mb; /* port B input or output mask */
+ UINT8 mcc; /* port C control/port select */
+ UINT8 mc; /* port C input or output mask */
+ UINT8 mm; /* memory mapping */
+ UINT8 mf; /* port F input or output mask */
+ UINT8 tmm; /* timer 0 and timer 1 operating parameters */
+ UINT8 etmm; /* 16-bit multifunction timer/event counter */
+ UINT8 eom; /* 16-bit timer/event counter output control */
+ UINT8 sml; /* serial interface parameters low */
+ UINT8 smh; /* -"- high */
+ UINT8 anm; /* analog to digital converter operating parameters */
+ UINT8 mkl; /* interrupt mask low */
+ UINT8 mkh; /* -"- high */
+ UINT8 zcm; /* bias circuitry for ac zero-cross detection */
+ UINT8 pa_in; /* port A,B,C,D,F inputs */
+ UINT8 pb_in;
+ UINT8 pc_in;
+ UINT8 pd_in;
+ UINT8 pf_in;
+ UINT8 pa_out; /* port A,B,C,D,F outputs */
+ UINT8 pb_out;
+ UINT8 pc_out;
+ UINT8 pd_out;
+ UINT8 pf_out;
+ UINT8 cr0; /* analog digital conversion register 0 */
+ UINT8 cr1; /* analog digital conversion register 1 */
+ UINT8 cr2; /* analog digital conversion register 2 */
+ UINT8 cr3; /* analog digital conversion register 3 */
+ UINT8 txb; /* transmitter buffer */
+ UINT8 rxb; /* receiver buffer */
+ UINT8 txd; /* port C control line states */
+ UINT8 rxd;
+ UINT8 sck;
+ UINT8 ti;
+ UINT8 to;
+ UINT8 ci;
+ UINT8 co0;
+ UINT8 co1;
+ UINT16 irr; /* interrupt request register */
+ UINT16 itf; /* interrupt test flag register */
+ int int1; /* keep track of current int1 state. Needed for 7801 irq checking. */
+ int int2; /* keep track to current int2 state. Needed for 7801 irq checking. */
+
+/* internal helper variables */
+ UINT16 txs; /* transmitter shift register */
+ UINT16 rxs; /* receiver shift register */
+ UINT8 txcnt; /* transmitter shift register bit count */
+ UINT8 rxcnt; /* receiver shift register bit count */
+ UINT8 txbuf; /* transmitter buffer was written */
+ INT32 ovc0; /* overflow counter for timer 0 (for clock div 12/384) */
+ INT32 ovc1; /* overflow counter for timer 0 (for clock div 12/384) */
+ INT32 ovce; /* overflow counter for ecnt */
+ INT32 ovcf; /* overflow counter for fixed clock div 3 mode */
+ INT32 ovcs; /* overflow counter for serial I/O */
+ UINT8 edges; /* rising/falling edge flag for serial I/O */
+ const struct opcode_s *opXX; /* opcode table */
+ const struct opcode_s *op48;
+ const struct opcode_s *op4C;
+ const struct opcode_s *op4D;
+ const struct opcode_s *op60;
+ const struct opcode_s *op64;
+ const struct opcode_s *op70;
+ const struct opcode_s *op74;
+ void (*handle_timers)(upd7810_state *cpustate, int cycles);
+ UPD7810_CONFIG config;
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *io;
+ int icount;
+};
+
+INLINE upd7810_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == UPD7810 ||
+ device->type() == UPD7807 ||
+ device->type() == UPD7801 ||
+ device->type() == UPD78C05 ||
+ device->type() == UPD78C06);
+ return (upd7810_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+#define CY 0x01
+#define F1 0x02
+#define L0 0x04
+#define L1 0x08
+#define HC 0x10
+#define SK 0x20
+#define Z 0x40
+#define F7 0x80
+
+/* IRR flags */
+#define INTNMI 0x0001
+#define INTFT0 0x0002
+#define INTFT1 0x0004
+#define INTF1 0x0008
+#define INTF2 0x0010
+#define INTFE0 0x0020
+#define INTFE1 0x0040
+#define INTFEIN 0x0080
+#define INTFAD 0x0100
+#define INTFSR 0x0200
+#define INTFST 0x0400
+#define INTER 0x0800
+#define INTOV 0x1000
+#define INTF0 0x2000
+
+/* ITF flags */
+#define INTAN4 0x0001
+#define INTAN5 0x0002
+#define INTAN6 0x0004
+#define INTAN7 0x0008
+#define INTSB 0x0010
+
+#define PPC cpustate->ppc.w.l
+#define PC cpustate->pc.w.l
+#define PCL cpustate->pc.b.l
+#define PCH cpustate->pc.b.h
+#define PCD cpustate->pc.d
+#define SP cpustate->sp.w.l
+#define SPL cpustate->sp.b.l
+#define SPH cpustate->sp.b.h
+#define SPD cpustate->sp.d
+#define PSW cpustate->psw
+#define OP cpustate->op
+#define OP2 cpustate->op2
+#define IFF cpustate->iff
+#define EA cpustate->ea.w.l
+#define EAL cpustate->ea.b.l
+#define EAH cpustate->ea.b.h
+#define VA cpustate->va.w.l
+#define V cpustate->va.b.h
+#define A cpustate->va.b.l
+#define VAD cpustate->va.d
+#define BC cpustate->bc.w.l
+#define B cpustate->bc.b.h
+#define C cpustate->bc.b.l
+#define DE cpustate->de.w.l
+#define D cpustate->de.b.h
+#define E cpustate->de.b.l
+#define HL cpustate->hl.w.l
+#define H cpustate->hl.b.h
+#define L cpustate->hl.b.l
+#define EA2 cpustate->ea2.w.l
+#define VA2 cpustate->va2.w.l
+#define BC2 cpustate->bc2.w.l
+#define DE2 cpustate->de2.w.l
+#define HL2 cpustate->hl2.w.l
+
+#define OVC0 cpustate->ovc0
+#define OVC1 cpustate->ovc1
+#define OVCE cpustate->ovce
+#define OVCF cpustate->ovcf
+#define OVCS cpustate->ovcs
+#define EDGES cpustate->edges
+
+#define CNT0 cpustate->cnt.b.l
+#define CNT1 cpustate->cnt.b.h
+#define TM0 cpustate->tm.b.l
+#define TM1 cpustate->tm.b.h
+#define ECNT cpustate->ecnt.w.l
+#define ECPT cpustate->ecnt.w.h
+#define ETM0 cpustate->etm.w.l
+#define ETM1 cpustate->etm.w.h
+
+#define MA cpustate->ma
+#define MB cpustate->mb
+#define MCC cpustate->mcc
+#define MC cpustate->mc
+#define MM cpustate->mm
+#define MF cpustate->mf
+#define TMM cpustate->tmm
+#define ETMM cpustate->etmm
+#define EOM cpustate->eom
+#define SML cpustate->sml
+#define SMH cpustate->smh
+#define ANM cpustate->anm
+#define MKL cpustate->mkl
+#define MKH cpustate->mkh
+#define ZCM cpustate->zcm
+
+#define CR0 cpustate->cr0
+#define CR1 cpustate->cr1
+#define CR2 cpustate->cr2
+#define CR3 cpustate->cr3
+#define RXB cpustate->rxb
+#define TXB cpustate->txb
+
+#define RXD cpustate->rxd
+#define TXD cpustate->txd
+#define SCK cpustate->sck
+#define TI cpustate->ti
+#define TO cpustate->to
+#define CI cpustate->ci
+#define CO0 cpustate->co0
+#define CO1 cpustate->co1
+
+#define IRR cpustate->irr
+#define ITF cpustate->itf
+
+struct opcode_s {
+ void (*opfunc)(upd7810_state *cpustate);
+ UINT8 oplen;
+ UINT8 cycles;
+ UINT8 cycles_skip;
+ UINT8 mask_l0_l1;
+};
+
+#define RDOP(O) O = cpustate->direct->read_decrypted_byte(PCD); PC++
+#define RDOPARG(A) A = cpustate->direct->read_raw_byte(PCD); PC++
+#define RM(A) cpustate->program->read_byte(A)
+#define WM(A,V) cpustate->program->write_byte(A,V)
+
+#define ZHC_ADD(after,before,carry) \
+ if (after == 0) PSW |= Z; else PSW &= ~Z; \
+ if (after == before) \
+ PSW = (PSW&~CY) | (carry); \
+ else if (after < before) \
+ PSW |= CY; \
+ else \
+ PSW &= ~CY; \
+ if ((after & 15) < (before & 15)) \
+ PSW |= HC; \
+ else \
+ PSW &= ~HC; \
+
+#define ZHC_SUB(after,before,carry) \
+ if (after == 0) PSW |= Z; else PSW &= ~Z; \
+ if (before == after) \
+ PSW = (PSW & ~CY) | (carry); \
+ else if (after > before) \
+ PSW |= CY; \
+ else \
+ PSW &= ~CY; \
+ if ((after & 15) > (before & 15)) \
+ PSW |= HC; \
+ else \
+ PSW &= ~HC; \
+
+#define SKIP_CY if (CY == (PSW & CY)) PSW |= SK
+#define SKIP_NC if (0 == (PSW & CY)) PSW |= SK
+#define SKIP_Z if (Z == (PSW & Z)) PSW |= SK
+#define SKIP_NZ if (0 == (PSW & Z)) PSW |= SK
+#define SET_Z(n) if (n) PSW &= ~Z; else PSW |= Z
+
+static UINT8 RP(upd7810_state *cpustate, offs_t port)
+{
+ UINT8 data = 0xff;
+ switch (port)
+ {
+ case UPD7810_PORTA:
+ if (cpustate->ma) // NS20031301 no need to read if the port is set as output
+ cpustate->pa_in = cpustate->io->read_byte(port);
+ data = (cpustate->pa_in & cpustate->ma) | (cpustate->pa_out & ~cpustate->ma);
+ break;
+ case UPD7810_PORTB:
+ if (cpustate->mb) // NS20031301 no need to read if the port is set as output
+ cpustate->pb_in = cpustate->io->read_byte(port);
+ data = (cpustate->pb_in & cpustate->mb) | (cpustate->pb_out & ~cpustate->mb);
+ break;
+ case UPD7810_PORTC:
+ if (cpustate->mc) // NS20031301 no need to read if the port is set as output
+ cpustate->pc_in = cpustate->io->read_byte(port);
+ data = (cpustate->pc_in & cpustate->mc) | (cpustate->pc_out & ~cpustate->mc);
+ if (cpustate->mcc & 0x01) /* PC0 = TxD output */
+ data = (data & ~0x01) | (cpustate->txd & 1 ? 0x01 : 0x00);
+ if (cpustate->mcc & 0x02) /* PC1 = RxD input */
+ data = (data & ~0x02) | (cpustate->rxd & 1 ? 0x02 : 0x00);
+ if (cpustate->mcc & 0x04) /* PC2 = SCK input/output */
+ data = (data & ~0x04) | (cpustate->sck & 1 ? 0x04 : 0x00);
+ if (cpustate->mcc & 0x08) /* PC3 = TI input */
+ data = (data & ~0x08) | (cpustate->ti & 1 ? 0x08 : 0x00);
+ if (cpustate->mcc & 0x10) /* PC4 = TO output */
+ data = (data & ~0x10) | (cpustate->to & 1 ? 0x10 : 0x00);
+ if (cpustate->mcc & 0x20) /* PC5 = CI input */
+ data = (data & ~0x20) | (cpustate->ci & 1 ? 0x20 : 0x00);
+ if (cpustate->mcc & 0x40) /* PC6 = CO0 output */
+ data = (data & ~0x40) | (cpustate->co0 & 1 ? 0x40 : 0x00);
+ if (cpustate->mcc & 0x80) /* PC7 = CO1 output */
+ data = (data & ~0x80) | (cpustate->co1 & 1 ? 0x80 : 0x00);
+ break;
+ case UPD7810_PORTD:
+ cpustate->pd_in = cpustate->io->read_byte(port);
+ switch (cpustate->mm & 0x07)
+ {
+ case 0x00: /* PD input mode, PF port mode */
+ data = cpustate->pd_in;
+ break;
+ case 0x01: /* PD output mode, PF port mode */
+ data = cpustate->pd_out;
+ break;
+ default: /* PD extension mode, PF port/extension mode */
+ data = 0xff; /* what do we see on the port here? */
+ break;
+ }
+ break;
+ case UPD7810_PORTF:
+ cpustate->pf_in = cpustate->io->read_byte(port);
+ switch (cpustate->mm & 0x06)
+ {
+ case 0x00: /* PD input/output mode, PF port mode */
+ data = (cpustate->pf_in & cpustate->mf) | (cpustate->pf_out & ~cpustate->mf);
+ break;
+ case 0x02: /* PD extension mode, PF0-3 extension mode, PF4-7 port mode */
+ data = (cpustate->pf_in & cpustate->mf) | (cpustate->pf_out & ~cpustate->mf);
+ data |= 0x0f; /* what would we see on the lower bits here? */
+ break;
+ case 0x04: /* PD extension mode, PF0-5 extension mode, PF6-7 port mode */
+ data = (cpustate->pf_in & cpustate->mf) | (cpustate->pf_out & ~cpustate->mf);
+ data |= 0x3f; /* what would we see on the lower bits here? */
+ break;
+ case 0x06:
+ data = 0xff; /* what would we see on the lower bits here? */
+ break;
+ }
+ break;
+ case UPD7807_PORTT: // NS20031301 partial implementation
+ data = cpustate->io->read_byte(port);
+ break;
+ default:
+ logerror("uPD7810 internal error: RP(cpustate) called with invalid port number\n");
+ }
+ return data;
+}
+
+static void WP(upd7810_state *cpustate, offs_t port, UINT8 data)
+{
+ switch (port)
+ {
+ case UPD7810_PORTA:
+ cpustate->pa_out = data;
+// data = (data & ~cpustate->ma) | (cpustate->pa_in & cpustate->ma);
+ data = (data & ~cpustate->ma) | (cpustate->ma); // NS20031401
+ cpustate->io->write_byte(port, data);
+ break;
+ case UPD7810_PORTB:
+ cpustate->pb_out = data;
+// data = (data & ~cpustate->mb) | (cpustate->pb_in & cpustate->mb);
+ data = (data & ~cpustate->mb) | (cpustate->mb); // NS20031401
+ cpustate->io->write_byte(port, data);
+ break;
+ case UPD7810_PORTC:
+ cpustate->pc_out = data;
+// data = (data & ~cpustate->mc) | (cpustate->pc_in & cpustate->mc);
+ data = (data & ~cpustate->mc) | (cpustate->mc); // NS20031401
+ if (cpustate->mcc & 0x01) /* PC0 = TxD output */
+ data = (data & ~0x01) | (cpustate->txd & 1 ? 0x01 : 0x00);
+ if (cpustate->mcc & 0x02) /* PC1 = RxD input */
+ data = (data & ~0x02) | (cpustate->rxd & 1 ? 0x02 : 0x00);
+ if (cpustate->mcc & 0x04) /* PC2 = SCK input/output */
+ data = (data & ~0x04) | (cpustate->sck & 1 ? 0x04 : 0x00);
+ if (cpustate->mcc & 0x08) /* PC3 = TI input */
+ data = (data & ~0x08) | (cpustate->ti & 1 ? 0x08 : 0x00);
+ if (cpustate->mcc & 0x10) /* PC4 = TO output */
+ data = (data & ~0x10) | (cpustate->to & 1 ? 0x10 : 0x00);
+ if (cpustate->mcc & 0x20) /* PC5 = CI input */
+ data = (data & ~0x20) | (cpustate->ci & 1 ? 0x20 : 0x00);
+ if (cpustate->mcc & 0x40) /* PC6 = CO0 output */
+ data = (data & ~0x40) | (cpustate->co0 & 1 ? 0x40 : 0x00);
+ if (cpustate->mcc & 0x80) /* PC7 = CO1 output */
+ data = (data & ~0x80) | (cpustate->co1 & 1 ? 0x80 : 0x00);
+ cpustate->io->write_byte(port, data);
+ break;
+ case UPD7810_PORTD:
+ cpustate->pd_out = data;
+ switch (cpustate->mm & 0x07)
+ {
+ case 0x00: /* PD input mode, PF port mode */
+ data = cpustate->pd_in;
+ break;
+ case 0x01: /* PD output mode, PF port mode */
+ data = cpustate->pd_out;
+ break;
+ default: /* PD extension mode, PF port/extension mode */
+ return;
+ }
+ cpustate->io->write_byte(port, data);
+ break;
+ case UPD7810_PORTF:
+ cpustate->pf_out = data;
+ data = (data & ~cpustate->mf) | (cpustate->pf_in & cpustate->mf);
+ switch (cpustate->mm & 0x06)
+ {
+ case 0x00: /* PD input/output mode, PF port mode */
+ break;
+ case 0x02: /* PD extension mode, PF0-3 extension mode, PF4-7 port mode */
+ data |= 0x0f; /* what would come out for the lower bits here? */
+ break;
+ case 0x04: /* PD extension mode, PF0-5 extension mode, PF6-7 port mode */
+ data |= 0x3f; /* what would come out for the lower bits here? */
+ break;
+ case 0x06:
+ data |= 0xff; /* what would come out for the lower bits here? */
+ break;
+ }
+ cpustate->io->write_byte(port, data);
+ break;
+ default:
+ logerror("uPD7810 internal error: RP(cpustate) called with invalid port number\n");
+ }
+}
+
+static void upd7810_take_irq(upd7810_state *cpustate)
+{
+ UINT16 vector = 0;
+ int irqline = 0;
+
+ /* global interrupt disable? */
+ if (0 == IFF)
+ return;
+
+ switch ( cpustate->config.type )
+ {
+ case TYPE_7801:
+ /* 1 - SOFTI - vector at 0x0060 */
+ /* 2 - INT0 - Masked by MK0 bit */
+ if ( IRR & INTF0 && 0 == (MKL & 0x01 ) )
+ {
+ irqline = UPD7810_INTF0;
+ vector = 0x0004;
+ IRR &= ~INTF0;
+ }
+ /* 3 - INTT - Masked by MKT bit */
+ if ( IRR & INTFT0 && 0 == ( MKL & 0x02 ) )
+ {
+ vector = 0x0008;
+ IRR &= ~INTFT0;
+ }
+ /* 4 - INT1 - Masked by MK1 bit */
+ if ( IRR & INTF1 && 0 == ( MKL & 0x04 ) )
+ {
+ irqline = UPD7810_INTF1;
+ vector = 0x0010;
+ IRR &= ~INTF1;
+ }
+ /* 5 - INT2 - Masked by MK2 bit */
+ if ( IRR & INTF2 && 0 == ( MKL & 0x08 ) )
+ {
+ irqline = UPD7810_INTF2;
+ vector = 0x0020;
+ IRR &= ~INTF2;
+ }
+ /* 6 - INTS - Masked by MKS bit */
+ if ( IRR & INTFST && 0 == ( MKL & 0x10 ) )
+ {
+ vector = 0x0040;
+ IRR &= ~INTFST;
+ }
+ break;
+
+ default:
+ /* check the interrupts in priority sequence */
+ if ((IRR & INTFT0) && 0 == (MKL & 0x02))
+ {
+ switch (cpustate->config.type)
+ {
+ case TYPE_7810_GAMEMASTER:
+ vector = 0xff2a;
+ break;
+ default:
+ vector = 0x0008;
+ }
+ if (!((IRR & INTFT1) && 0 == (MKL & 0x04)))
+ IRR&=~INTFT0;
+ }
+ else
+ if ((IRR & INTFT1) && 0 == (MKL & 0x04))
+ {
+ switch (cpustate->config.type)
+ {
+ case TYPE_7810_GAMEMASTER:
+ vector = 0xff2a;
+ break;
+ default:
+ vector = 0x0008;
+ }
+ IRR&=~INTFT1;
+ }
+ else
+ if ((IRR & INTF1) && 0 == (MKL & 0x08))
+ {
+ irqline = UPD7810_INTF1;
+ vector = 0x0010;
+ if (!((IRR & INTF2) && 0 == (MKL & 0x10)))
+ IRR&=~INTF1;
+ }
+ else
+ if ((IRR & INTF2) && 0 == (MKL & 0x10))
+ {
+ irqline = UPD7810_INTF2;
+ vector = 0x0010;
+ IRR&=~INTF2;
+ }
+ else
+ if ((IRR & INTFE0) && 0 == (MKL & 0x20))
+ {
+ switch (cpustate->config.type)
+ {
+ case TYPE_7810_GAMEMASTER:
+ vector = 0xff2d;
+ break;
+ default:
+ vector = 0x0018;
+ }
+ if (!((IRR & INTFE1) && 0 == (MKL & 0x40)))
+ IRR&=~INTFE0;
+ }
+ else
+ if ((IRR & INTFE1) && 0 == (MKL & 0x40))
+ {
+ switch (cpustate->config.type)
+ {
+ case TYPE_7810_GAMEMASTER:
+ vector = 0xff2d;
+ break;
+ default:
+ vector = 0x0018;
+ }
+ IRR&=~INTFE1;
+ }
+ else
+ if ((IRR & INTFEIN) && 0 == (MKL & 0x80))
+ {
+ vector = 0x0020;
+ }
+ else
+ if ((IRR & INTFAD) && 0 == (MKH & 0x01))
+ {
+ vector = 0x0020;
+ }
+ else
+ if ((IRR & INTFSR) && 0 == (MKH & 0x02))
+ {
+ vector = 0x0028;
+ IRR&=~INTFSR;
+ }
+ else
+ if ((IRR & INTFST) && 0 == (MKH & 0x04))
+ {
+ vector = 0x0028;
+ IRR&=~INTFST;
+ }
+ break;
+ }
+
+ if (vector)
+ {
+ /* acknowledge external IRQ */
+ if (irqline)
+ (*cpustate->irq_callback)(cpustate->device, irqline);
+ SP--;
+ WM( SP, PSW );
+ SP--;
+ WM( SP, PCH );
+ SP--;
+ WM( SP, PCL );
+ IFF = 0;
+ PSW &= ~(SK|L0|L1);
+ PC = vector;
+ }
+}
+
+static void upd7810_write_EOM(upd7810_state *cpustate)
+{
+ if (EOM & 0x01) /* output LV0 content ? */
+ {
+ switch (EOM & 0x0e)
+ {
+ case 0x02: /* toggle CO0 */
+ CO0 = (CO0 >> 1) | ((CO0 ^ 2) & 2);
+ break;
+ case 0x04: /* reset CO0 */
+ CO0 = 0;
+ break;
+ case 0x08: /* set CO0 */
+ CO0 = 1;
+ break;
+ }
+ }
+ if (EOM & 0x10) /* output LV0 content ? */
+ {
+ switch (EOM & 0xe0)
+ {
+ case 0x20: /* toggle CO1 */
+ CO1 = (CO1 >> 1) | ((CO1 ^ 2) & 2);
+ break;
+ case 0x40: /* reset CO1 */
+ CO1 = 0;
+ break;
+ case 0x80: /* set CO1 */
+ CO1 = 1;
+ break;
+ }
+ }
+}
+
+static void upd7810_write_TXB(upd7810_state *cpustate)
+{
+ cpustate->txbuf = 1;
+}
+
+#define PAR7(n) ((((n)>>6)^((n)>>5)^((n)>>4)^((n)>>3)^((n)>>2)^((n)>>1)^((n)))&1)
+#define PAR8(n) ((((n)>>7)^((n)>>6)^((n)>>5)^((n)>>4)^((n)>>3)^((n)>>2)^((n)>>1)^((n)))&1)
+
+static void upd7810_sio_output(upd7810_state *cpustate)
+{
+ /* shift out more bits? */
+ if (cpustate->txcnt > 0)
+ {
+ TXD = cpustate->txs & 1;
+ if (cpustate->config.io_callback)
+ (*cpustate->config.io_callback)(cpustate->device,UPD7810_TXD,TXD);
+ cpustate->txs >>= 1;
+ cpustate->txcnt--;
+ if (0 == cpustate->txcnt)
+ IRR |= INTFST; /* serial transfer completed */
+ }
+ else
+ if (SMH & 0x04) /* send enable ? */
+ {
+ /* nothing written into the transmitter buffer ? */
+ if (0 == cpustate->txbuf)
+ return;
+ cpustate->txbuf = 0;
+
+ if (SML & 0x03) /* asynchronous mode ? */
+ {
+ switch (SML & 0xfc)
+ {
+ case 0x48: /* 7bits, no parity, 1 stop bit */
+ case 0x68: /* 7bits, no parity, 1 stop bit (parity select = 1 but parity is off) */
+ /* insert start bit in bit0, stop bit int bit8 */
+ cpustate->txs = (TXB << 1) | (1 << 8);
+ cpustate->txcnt = 9;
+ break;
+ case 0x4c: /* 8bits, no parity, 1 stop bit */
+ case 0x6c: /* 8bits, no parity, 1 stop bit (parity select = 1 but parity is off) */
+ /* insert start bit in bit0, stop bit int bit9 */
+ cpustate->txs = (TXB << 1) | (1 << 9);
+ cpustate->txcnt = 10;
+ break;
+ case 0x58: /* 7bits, odd parity, 1 stop bit */
+ /* insert start bit in bit0, parity in bit 8, stop bit in bit9 */
+ cpustate->txs = (TXB << 1) | (PAR7(TXB) << 8) | (1 << 9);
+ cpustate->txcnt = 10;
+ break;
+ case 0x5c: /* 8bits, odd parity, 1 stop bit */
+ /* insert start bit in bit0, parity in bit 9, stop bit int bit10 */
+ cpustate->txs = (TXB << 1) | (PAR8(TXB) << 9) | (1 << 10);
+ cpustate->txcnt = 11;
+ break;
+ case 0x78: /* 7bits, even parity, 1 stop bit */
+ /* insert start bit in bit0, parity in bit 8, stop bit in bit9 */
+ cpustate->txs = (TXB << 1) | ((PAR7(TXB) ^ 1) << 8) | (1 << 9);
+ cpustate->txcnt = 10;
+ break;
+ case 0x7c: /* 8bits, even parity, 1 stop bit */
+ /* insert start bit in bit0, parity in bit 9, stop bit int bit10 */
+ cpustate->txs = (TXB << 1) | ((PAR8(TXB) ^ 1) << 9) | (1 << 10);
+ cpustate->txcnt = 11;
+ break;
+ case 0xc8: /* 7bits, no parity, 2 stop bits */
+ case 0xe8: /* 7bits, no parity, 2 stop bits (parity select = 1 but parity is off) */
+ /* insert start bit in bit0, stop bits int bit8+9 */
+ cpustate->txs = (TXB << 1) | (3 << 8);
+ cpustate->txcnt = 10;
+ break;
+ case 0xcc: /* 8bits, no parity, 2 stop bits */
+ case 0xec: /* 8bits, no parity, 2 stop bits (parity select = 1 but parity is off) */
+ /* insert start bit in bit0, stop bits in bits9+10 */
+ cpustate->txs = (TXB << 1) | (3 << 9);
+ cpustate->txcnt = 11;
+ break;
+ case 0xd8: /* 7bits, odd parity, 2 stop bits */
+ /* insert start bit in bit0, parity in bit 8, stop bits in bits9+10 */
+ cpustate->txs = (TXB << 1) | (PAR7(TXB) << 8) | (3 << 9);
+ cpustate->txcnt = 11;
+ break;
+ case 0xdc: /* 8bits, odd parity, 2 stop bits */
+ /* insert start bit in bit0, parity in bit 9, stop bits int bit10+11 */
+ cpustate->txs = (TXB << 1) | (PAR8(TXB) << 9) | (3 << 10);
+ cpustate->txcnt = 12;
+ break;
+ case 0xf8: /* 7bits, even parity, 2 stop bits */
+ /* insert start bit in bit0, parity in bit 8, stop bits in bit9+10 */
+ cpustate->txs = (TXB << 1) | ((PAR7(TXB) ^ 1) << 8) | (3 << 9);
+ cpustate->txcnt = 11;
+ break;
+ case 0xfc: /* 8bits, even parity, 2 stop bits */
+ /* insert start bit in bit0, parity in bit 9, stop bits int bits10+10 */
+ cpustate->txs = (TXB << 1) | ((PAR8(TXB) ^ 1) << 9) | (1 << 10);
+ cpustate->txcnt = 12;
+ break;
+ }
+ }
+ else
+ {
+ /* synchronous mode */
+ cpustate->txs = TXB;
+ cpustate->txcnt = 8;
+ }
+ }
+}
+
+static void upd7810_sio_input(upd7810_state *cpustate)
+{
+ /* sample next bit? */
+ if (cpustate->rxcnt > 0)
+ {
+ if (cpustate->config.io_callback)
+ RXD = (*cpustate->config.io_callback)(cpustate->device,UPD7810_RXD,RXD);
+ cpustate->rxs = (cpustate->rxs >> 1) | ((UINT16)RXD << 15);
+ cpustate->rxcnt--;
+ if (0 == cpustate->rxcnt)
+ {
+ /* reset the TSK bit */
+ SMH &= ~0x40;
+ /* serial receive completed interrupt */
+ IRR |= INTFSR;
+ /* now extract the data from the shift register */
+ if (SML & 0x03) /* asynchronous mode ? */
+ {
+ switch (SML & 0xfc)
+ {
+ case 0x48: /* 7bits, no parity, 1 stop bit */
+ case 0x68: /* 7bits, no parity, 1 stop bit (parity select = 1 but parity is off) */
+ cpustate->rxs >>= 16 - 9;
+ RXB = (cpustate->rxs >> 1) & 0x7f;
+ if ((1 << 8) != (cpustate->rxs & (1 | (1 << 8))))
+ IRR |= INTER; /* framing error */
+ break;
+ case 0x4c: /* 8bits, no parity, 1 stop bit */
+ case 0x6c: /* 8bits, no parity, 1 stop bit (parity select = 1 but parity is off) */
+ cpustate->rxs >>= 16 - 10;
+ RXB = (cpustate->rxs >> 1) & 0xff;
+ if ((1 << 9) != (cpustate->rxs & (1 | (1 << 9))))
+ IRR |= INTER; /* framing error */
+ break;
+ case 0x58: /* 7bits, odd parity, 1 stop bit */
+ cpustate->rxs >>= 16 - 10;
+ RXB = (cpustate->rxs >> 1) & 0x7f;
+ if ((1 << 9) != (cpustate->rxs & (1 | (1 << 9))))
+ IRR |= INTER; /* framing error */
+ if (PAR7(RXB) != ((cpustate->rxs >> 8) & 1))
+ IRR |= INTER; /* parity error */
+ break;
+ case 0x5c: /* 8bits, odd parity, 1 stop bit */
+ cpustate->rxs >>= 16 - 11;
+ RXB = (cpustate->rxs >> 1) & 0xff;
+ if ((1 << 10) != (cpustate->rxs & (1 | (1 << 10))))
+ IRR |= INTER; /* framing error */
+ if (PAR8(RXB) != ((cpustate->rxs >> 9) & 1))
+ IRR |= INTER; /* parity error */
+ break;
+ case 0x78: /* 7bits, even parity, 1 stop bit */
+ cpustate->rxs >>= 16 - 10;
+ RXB = (cpustate->rxs >> 1) & 0x7f;
+ if ((1 << 9) != (cpustate->rxs & (1 | (1 << 9))))
+ IRR |= INTER; /* framing error */
+ if (PAR7(RXB) != ((cpustate->rxs >> 8) & 1))
+ IRR |= INTER; /* parity error */
+ break;
+ case 0x7c: /* 8bits, even parity, 1 stop bit */
+ cpustate->rxs >>= 16 - 11;
+ RXB = (cpustate->rxs >> 1) & 0xff;
+ if ((1 << 10) != (cpustate->rxs & (1 | (1 << 10))))
+ IRR |= INTER; /* framing error */
+ if (PAR8(RXB) != ((cpustate->rxs >> 9) & 1))
+ IRR |= INTER; /* parity error */
+ break;
+ case 0xc8: /* 7bits, no parity, 2 stop bits */
+ case 0xe8: /* 7bits, no parity, 2 stop bits (parity select = 1 but parity is off) */
+ cpustate->rxs >>= 16 - 10;
+ RXB = (cpustate->rxs >> 1) & 0x7f;
+ if ((3 << 9) != (cpustate->rxs & (1 | (3 << 9))))
+ IRR |= INTER; /* framing error */
+ if (PAR7(RXB) != ((cpustate->rxs >> 8) & 1))
+ IRR |= INTER; /* parity error */
+ break;
+ case 0xcc: /* 8bits, no parity, 2 stop bits */
+ case 0xec: /* 8bits, no parity, 2 stop bits (parity select = 1 but parity is off) */
+ cpustate->rxs >>= 16 - 11;
+ RXB = (cpustate->rxs >> 1) & 0xff;
+ if ((3 << 10) != (cpustate->rxs & (1 | (3 << 10))))
+ IRR |= INTER; /* framing error */
+ if (PAR8(RXB) != ((cpustate->rxs >> 9) & 1))
+ IRR |= INTER; /* parity error */
+ break;
+ case 0xd8: /* 7bits, odd parity, 2 stop bits */
+ cpustate->rxs >>= 16 - 11;
+ RXB = (cpustate->rxs >> 1) & 0x7f;
+ if ((3 << 10) != (cpustate->rxs & (1 | (3 << 10))))
+ IRR |= INTER; /* framing error */
+ if (PAR7(RXB) != ((cpustate->rxs >> 8) & 1))
+ IRR |= INTER; /* parity error */
+ break;
+ case 0xdc: /* 8bits, odd parity, 2 stop bits */
+ cpustate->rxs >>= 16 - 12;
+ RXB = (cpustate->rxs >> 1) & 0xff;
+ if ((3 << 11) != (cpustate->rxs & (1 | (3 << 11))))
+ IRR |= INTER; /* framing error */
+ if (PAR8(RXB) != ((cpustate->rxs >> 9) & 1))
+ IRR |= INTER; /* parity error */
+ break;
+ case 0xf8: /* 7bits, even parity, 2 stop bits */
+ cpustate->rxs >>= 16 - 11;
+ RXB = (cpustate->rxs >> 1) & 0x7f;
+ if ((3 << 10) != (cpustate->rxs & (1 | (3 << 10))))
+ IRR |= INTER; /* framing error */
+ if (PAR7(RXB) != ((cpustate->rxs >> 8) & 1))
+ IRR |= INTER; /* parity error */
+ break;
+ case 0xfc: /* 8bits, even parity, 2 stop bits */
+ cpustate->rxs >>= 16 - 12;
+ RXB = (cpustate->rxs >> 1) & 0xff;
+ if ((3 << 11) != (cpustate->rxs & (1 | (3 << 11))))
+ IRR |= INTER; /* framing error */
+ if (PAR8(RXB) != ((cpustate->rxs >> 9) & 1))
+ IRR |= INTER; /* parity error */
+ break;
+ }
+ }
+ else
+ {
+ cpustate->rxs >>= 16 - 8;
+ RXB = cpustate->rxs;
+// cpustate->rxcnt = 8;
+ }
+ }
+ }
+ else
+ if (SMH & 0x08) /* receive enable ? */
+ {
+ if (SML & 0x03) /* asynchronous mode ? */
+ {
+ switch (SML & 0xfc)
+ {
+ case 0x48: /* 7bits, no parity, 1 stop bit */
+ case 0x68: /* 7bits, no parity, 1 stop bit (parity select = 1 but parity is off) */
+ cpustate->rxcnt = 9;
+ break;
+ case 0x4c: /* 8bits, no parity, 1 stop bit */
+ case 0x6c: /* 8bits, no parity, 1 stop bit (parity select = 1 but parity is off) */
+ cpustate->rxcnt = 10;
+ break;
+ case 0x58: /* 7bits, odd parity, 1 stop bit */
+ cpustate->rxcnt = 10;
+ break;
+ case 0x5c: /* 8bits, odd parity, 1 stop bit */
+ cpustate->rxcnt = 11;
+ break;
+ case 0x78: /* 7bits, even parity, 1 stop bit */
+ cpustate->rxcnt = 10;
+ break;
+ case 0x7c: /* 8bits, even parity, 1 stop bit */
+ cpustate->rxcnt = 11;
+ break;
+ case 0xc8: /* 7bits, no parity, 2 stop bits */
+ case 0xe8: /* 7bits, no parity, 2 stop bits (parity select = 1 but parity is off) */
+ cpustate->rxcnt = 10;
+ break;
+ case 0xcc: /* 8bits, no parity, 2 stop bits */
+ case 0xec: /* 8bits, no parity, 2 stop bits (parity select = 1 but parity is off) */
+ cpustate->rxcnt = 11;
+ break;
+ case 0xd8: /* 7bits, odd parity, 2 stop bits */
+ cpustate->rxcnt = 11;
+ break;
+ case 0xdc: /* 8bits, odd parity, 2 stop bits */
+ cpustate->rxcnt = 12;
+ break;
+ case 0xf8: /* 7bits, even parity, 2 stop bits */
+ cpustate->rxcnt = 11;
+ break;
+ case 0xfc: /* 8bits, even parity, 2 stop bits */
+ cpustate->rxcnt = 12;
+ break;
+ }
+ }
+ else
+ /* TSK bit set ? */
+ if (SMH & 0x40)
+ {
+ cpustate->rxcnt = 8;
+ }
+ }
+}
+
+static void upd7810_timers(upd7810_state *cpustate, int cycles)
+{
+ /**** TIMER 0 ****/
+ if (TMM & 0x10) /* timer 0 upcounter reset ? */
+ CNT0 = 0;
+ else
+ {
+ switch (TMM & 0x0c) /* timer 0 clock source */
+ {
+ case 0x00: /* clock divided by 12 */
+ OVC0 += cycles;
+ while (OVC0 >= 12)
+ {
+ OVC0 -= 12;
+ CNT0++;
+ if (CNT0 == TM0)
+ {
+ CNT0 = 0;
+ IRR |= INTFT0;
+ /* timer F/F source is timer 0 ? */
+ if (0x00 == (TMM & 0x03))
+ {
+ TO ^= 1;
+ if (cpustate->config.io_callback)
+ (*cpustate->config.io_callback)(cpustate->device,UPD7810_TO,TO);
+ }
+ /* timer 1 chained with timer 0 ? */
+ if ((TMM & 0xe0) == 0x60)
+ {
+ CNT1++;
+ if (CNT1 == TM1)
+ {
+ IRR |= INTFT1;
+ CNT1 = 0;
+ /* timer F/F source is timer 1 ? */
+ if (0x01 == (TMM & 0x03))
+ {
+ TO ^= 1;
+ if (cpustate->config.io_callback)
+ (*cpustate->config.io_callback)(cpustate->device,UPD7810_TO,TO);
+ }
+ }
+ }
+ }
+ }
+ break;
+ case 0x04: /* clock divided by 384 */
+ OVC0 += cycles;
+ while (OVC0 >= 384)
+ {
+ OVC0 -= 384;
+ CNT0++;
+ if (CNT0 == TM0)
+ {
+ CNT0 = 0;
+ IRR |= INTFT0;
+ /* timer F/F source is timer 0 ? */
+ if (0x00 == (TMM & 0x03))
+ {
+ TO ^= 1;
+ if (cpustate->config.io_callback)
+ (*cpustate->config.io_callback)(cpustate->device,UPD7810_TO,TO);
+ }
+ /* timer 1 chained with timer 0 ? */
+ if ((TMM & 0xe0) == 0x60)
+ {
+ CNT1++;
+ if (CNT1 == TM1)
+ {
+ CNT1 = 0;
+ IRR |= INTFT1;
+ /* timer F/F source is timer 1 ? */
+ if (0x01 == (TMM & 0x03))
+ {
+ TO ^= 1;
+ if (cpustate->config.io_callback)
+ (*cpustate->config.io_callback)(cpustate->device,UPD7810_TO,TO);
+ }
+ }
+ }
+ }
+ }
+ break;
+ case 0x08: /* external signal at TI */
+ break;
+ case 0x0c: /* disabled */
+ break;
+ }
+ }
+
+ /**** TIMER 1 ****/
+ if (TMM & 0x80) /* timer 1 upcounter reset ? */
+ CNT1 = 0;
+ else
+ {
+ switch (TMM & 0x60) /* timer 1 clock source */
+ {
+ case 0x00: /* clock divided by 12 */
+ OVC1 += cycles;
+ while (OVC1 >= 12)
+ {
+ OVC1 -= 12;
+ CNT1++;
+ if (CNT1 == TM1)
+ {
+ CNT1 = 0;
+ IRR |= INTFT1;
+ /* timer F/F source is timer 1 ? */
+ if (0x01 == (TMM & 0x03))
+ {
+ TO ^= 1;
+ if (cpustate->config.io_callback)
+ (*cpustate->config.io_callback)(cpustate->device,UPD7810_TO,TO);
+ }
+ }
+ }
+ break;
+ case 0x20: /* clock divided by 384 */
+ OVC1 += cycles;
+ while (OVC1 >= 384)
+ {
+ OVC1 -= 384;
+ CNT1++;
+ if (CNT1 == TM1)
+ {
+ CNT1 = 0;
+ IRR |= INTFT1;
+ /* timer F/F source is timer 1 ? */
+ if (0x01 == (TMM & 0x03))
+ {
+ TO ^= 1;
+ if (cpustate->config.io_callback)
+ (*cpustate->config.io_callback)(cpustate->device,UPD7810_TO,TO);
+ }
+ }
+ }
+ break;
+ case 0x40: /* external signal at TI */
+ break;
+ case 0x60: /* clocked with timer 0 */
+ break;
+ }
+ }
+
+ /**** TIMER F/F ****/
+ /* timer F/F source is clock divided by 3 ? */
+ if (0x02 == (TMM & 0x03))
+ {
+ OVCF += cycles;
+ while (OVCF >= 3)
+ {
+ TO ^= 1;
+ if (cpustate->config.io_callback)
+ (*cpustate->config.io_callback)(cpustate->device,UPD7810_TO,TO);
+ OVCF -= 3;
+ }
+ }
+
+ /**** ETIMER ****/
+ /* ECNT clear */
+ if (0x00 == (ETMM & 0x0c))
+ ECNT = 0;
+ else
+ if (0x00 == (ETMM & 0x03) || (0x01 == (ETMM & 0x03) && CI))
+ {
+ OVCE += cycles;
+ /* clock divided by 12 */
+ while (OVCE >= 12)
+ {
+ OVCE -= 12;
+ ECNT++;
+ switch (ETMM & 0x0c)
+ {
+ case 0x00: /* clear ECNT */
+ break;
+ case 0x04: /* free running */
+ if (0 == ECNT)
+ ITF |= INTOV; /* set overflow flag if counter wrapped */
+ break;
+ case 0x08: /* reset at falling edge of CI or TO */
+ break;
+ case 0x0c: /* reset if ECNT == ETM1 */
+ if (ETM1 == ECNT)
+ ECNT = 0;
+ break;
+ }
+ switch (ETMM & 0x30)
+ {
+ case 0x00: /* set CO0 if ECNT == ETM0 */
+ if (ETM0 == ECNT)
+ {
+ switch (EOM & 0x0e)
+ {
+ case 0x02: /* toggle CO0 */
+ CO0 = (CO0 >> 1) | ((CO0 ^ 2) & 2);
+ break;
+ case 0x04: /* reset CO0 */
+ CO0 = 0;
+ break;
+ case 0x08: /* set CO0 */
+ CO0 = 1;
+ break;
+ }
+ }
+ break;
+ case 0x10: /* prohibited */
+ break;
+ case 0x20: /* set CO0 if ECNT == ETM0 or at falling CI input */
+ if (ETM0 == ECNT)
+ {
+ switch (EOM & 0x0e)
+ {
+ case 0x02: /* toggle CO0 */
+ CO0 = (CO0 >> 1) | ((CO0 ^ 2) & 2);
+ break;
+ case 0x04: /* reset CO0 */
+ CO0 = 0;
+ break;
+ case 0x08: /* set CO0 */
+ CO0 = 1;
+ break;
+ }
+ }
+ break;
+ case 0x30: /* latch CO0 if ECNT == ETM0 or ECNT == ETM1 */
+ if (ETM0 == ECNT || ETM1 == ECNT)
+ {
+ switch (EOM & 0x0e)
+ {
+ case 0x02: /* toggle CO0 */
+ CO0 = (CO0 >> 1) | ((CO0 ^ 2) & 2);
+ break;
+ case 0x04: /* reset CO0 */
+ CO0 = 0;
+ break;
+ case 0x08: /* set CO0 */
+ CO0 = 1;
+ break;
+ }
+ }
+ break;
+ }
+ switch (ETMM & 0xc0)
+ {
+ case 0x00: /* lacth CO1 if ECNT == ETM1 */
+ if (ETM1 == ECNT)
+ {
+ switch (EOM & 0xe0)
+ {
+ case 0x20: /* toggle CO1 */
+ CO1 = (CO1 >> 1) | ((CO1 ^ 2) & 2);
+ break;
+ case 0x40: /* reset CO1 */
+ CO1 = 0;
+ break;
+ case 0x80: /* set CO1 */
+ CO1 = 1;
+ break;
+ }
+ }
+ break;
+ case 0x40: /* prohibited */
+ break;
+ case 0x80: /* latch CO1 if ECNT == ETM1 or falling edge of CI input */
+ if (ETM1 == ECNT)
+ {
+ switch (EOM & 0xe0)
+ {
+ case 0x20: /* toggle CO1 */
+ CO1 = (CO1 >> 1) | ((CO1 ^ 2) & 2);
+ break;
+ case 0x40: /* reset CO1 */
+ CO1 = 0;
+ break;
+ case 0x80: /* set CO1 */
+ CO1 = 1;
+ break;
+ }
+ }
+ break;
+ case 0xc0: /* latch CO1 if ECNT == ETM0 or ECNT == ETM1 */
+ if (ETM0 == ECNT || ETM1 == ECNT)
+ {
+ switch (EOM & 0xe0)
+ {
+ case 0x20: /* toggle CO1 */
+ CO1 = (CO1 >> 1) | ((CO1 ^ 2) & 2);
+ break;
+ case 0x40: /* reset CO1 */
+ CO1 = 0;
+ break;
+ case 0x80: /* set CO1 */
+ CO1 = 1;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ /**** SIO ****/
+ switch (SMH & 0x03)
+ {
+ case 0x00: /* interval timer F/F */
+ break;
+ case 0x01: /* internal clock divided by 384 */
+ OVCS += cycles;
+ while (OVCS >= 384)
+ {
+ OVCS -= 384;
+ if (0 == (EDGES ^= 1))
+ upd7810_sio_input(cpustate);
+ else
+ upd7810_sio_output(cpustate);
+ }
+ break;
+ case 0x02: /* internal clock divided by 24 */
+ OVCS += cycles;
+ while (OVCS >= 24)
+ {
+ OVCS -= 24;
+ if (0 == (EDGES ^= 1))
+ upd7810_sio_input(cpustate);
+ else
+ upd7810_sio_output(cpustate);
+ }
+ break;
+ }
+}
+
+static void upd7801_timers(upd7810_state *cpustate, int cycles)
+{
+ if ( cpustate->ovc0 )
+ {
+ cpustate->ovc0 -= cycles;
+
+ /* Check if timer expired */
+ if ( cpustate->ovc0 <= 0 )
+ {
+ IRR |= INTFT0;
+
+ /* Reset the timer flip/fliop */
+ TO = 0;
+ if ( cpustate->config.io_callback)
+ (*cpustate->config.io_callback)(cpustate->device,UPD7810_TO,TO);
+
+ /* Reload the timer */
+ cpustate->ovc0 = 16 * ( TM0 + ( ( TM1 & 0x0f ) << 8 ) );
+ }
+ }
+}
+
+static void upd78c05_timers(upd7810_state *cpustate, int cycles)
+{
+ if ( cpustate->ovc0 ) {
+ cpustate->ovc0 -= cycles;
+
+ if ( cpustate->ovc0 <= 0 ) {
+ IRR |= INTFT0;
+ if (0x00 == (TMM & 0x03)) {
+ TO ^= 1;
+ if (cpustate->config.io_callback)
+ (*cpustate->config.io_callback)(cpustate->device,UPD7810_TO,TO);
+ }
+
+ while ( cpustate->ovc0 <= 0 ) {
+ cpustate->ovc0 += ( ( TMM & 0x04 ) ? 16 * 8 : 8 ) * TM0;
+ }
+ }
+ }
+}
+
+static CPU_INIT( upd7810 )
+{
+ upd7810_state *cpustate = get_safe_token(device);
+
+ cpustate->config = *(const UPD7810_CONFIG*) device->static_config();
+ 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->ppc.w.l));
+ device->save_item(NAME(cpustate->pc.w.l));
+ device->save_item(NAME(cpustate->sp.w.l));
+ device->save_item(NAME(cpustate->psw));
+ device->save_item(NAME(cpustate->op));
+ device->save_item(NAME(cpustate->op2));
+ device->save_item(NAME(cpustate->iff));
+ device->save_item(NAME(cpustate->ea.w.l));
+ device->save_item(NAME(cpustate->va.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->ea2.w.l));
+ device->save_item(NAME(cpustate->va2.w.l));
+ device->save_item(NAME(cpustate->bc2.w.l));
+ device->save_item(NAME(cpustate->de2.w.l));
+ device->save_item(NAME(cpustate->hl2.w.l));
+ device->save_item(NAME(cpustate->cnt.d));
+ device->save_item(NAME(cpustate->tm.d));
+ device->save_item(NAME(cpustate->ecnt.d));
+ device->save_item(NAME(cpustate->etm.d));
+ device->save_item(NAME(cpustate->ma));
+ device->save_item(NAME(cpustate->mb));
+ device->save_item(NAME(cpustate->mcc));
+ device->save_item(NAME(cpustate->mc));
+ device->save_item(NAME(cpustate->mm));
+ device->save_item(NAME(cpustate->mf));
+ device->save_item(NAME(cpustate->tmm));
+ device->save_item(NAME(cpustate->etmm));
+ device->save_item(NAME(cpustate->eom));
+ device->save_item(NAME(cpustate->sml));
+ device->save_item(NAME(cpustate->smh));
+ device->save_item(NAME(cpustate->anm));
+ device->save_item(NAME(cpustate->mkl));
+ device->save_item(NAME(cpustate->mkh));
+ device->save_item(NAME(cpustate->zcm));
+ device->save_item(NAME(cpustate->pa_out));
+ device->save_item(NAME(cpustate->pb_out));
+ device->save_item(NAME(cpustate->pc_out));
+ device->save_item(NAME(cpustate->pd_out));
+ device->save_item(NAME(cpustate->pf_out));
+ device->save_item(NAME(cpustate->cr0));
+ device->save_item(NAME(cpustate->cr1));
+ device->save_item(NAME(cpustate->cr2));
+ device->save_item(NAME(cpustate->cr3));
+ device->save_item(NAME(cpustate->txb));
+ device->save_item(NAME(cpustate->rxb));
+ device->save_item(NAME(cpustate->txd));
+ device->save_item(NAME(cpustate->rxd));
+ device->save_item(NAME(cpustate->sck));
+ device->save_item(NAME(cpustate->ti));
+ device->save_item(NAME(cpustate->to));
+ device->save_item(NAME(cpustate->ci));
+ device->save_item(NAME(cpustate->co0));
+ device->save_item(NAME(cpustate->co1));
+ device->save_item(NAME(cpustate->irr));
+ device->save_item(NAME(cpustate->itf));
+ device->save_item(NAME(cpustate->ovc0));
+ device->save_item(NAME(cpustate->ovc1));
+ device->save_item(NAME(cpustate->ovcf));
+ device->save_item(NAME(cpustate->ovcs));
+ device->save_item(NAME(cpustate->edges));
+ device->save_item(NAME(cpustate->int1));
+ device->save_item(NAME(cpustate->int2));
+}
+
+#include "7810tbl.c"
+#include "7810ops.c"
+
+static CPU_RESET( upd7810 )
+{
+ upd7810_state *cpustate = get_safe_token(device);
+ UPD7810_CONFIG save_config;
+ device_irq_callback save_irqcallback;
+
+ save_config = cpustate->config;
+ save_irqcallback = cpustate->irq_callback;
+ memset(cpustate, 0, sizeof(*cpustate));
+ cpustate->config = save_config;
+ 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->opXX = opXX_7810;
+ cpustate->op48 = op48;
+ cpustate->op4C = op4C;
+ cpustate->op4D = op4D;
+ cpustate->op60 = op60;
+ cpustate->op64 = op64;
+ cpustate->op70 = op70;
+ cpustate->op74 = op74;
+ ETMM = 0xff;
+ TMM = 0xff;
+ MA = 0xff;
+ MB = 0xff;
+ switch (cpustate->config.type)
+ {
+ case TYPE_7810_GAMEMASTER:
+ // needed for lcd screen/ram selection; might be internal in cpu and therefor not needed; 0x10 written in some games
+ MC = 0xff&~0x7;
+ WP( cpustate, UPD7810_PORTC, 1 ); //hyper space
+ PCD=0x8000;
+ break;
+ default:
+ MC = 0xff;
+ }
+ MF = 0xff;
+ // gamemaster falling block "and"s to enable interrupts
+ MKL = 0xff;
+ MKH = 0xff; //?
+ cpustate->handle_timers = upd7810_timers;
+}
+
+static CPU_RESET( upd7807 )
+{
+ upd7810_state *cpustate = get_safe_token(device);
+ CPU_RESET_CALL(upd7810);
+ cpustate->opXX = opXX_7807;
+}
+
+static CPU_RESET( upd7801 )
+{
+ upd7810_state *cpustate = get_safe_token(device);
+ CPU_RESET_CALL(upd7810);
+ cpustate->op48 = op48_7801;
+ cpustate->op4C = op4C_7801;
+ cpustate->op4D = op4D_7801;
+ cpustate->op60 = op60_7801;
+ cpustate->op64 = op64_7801;
+ cpustate->op70 = op70_7801;
+ cpustate->op74 = op74_7801;
+ cpustate->opXX = opXX_7801;
+ cpustate->handle_timers = upd7801_timers;
+ MA = 0; /* Port A is output port on the uPD7801 */
+ cpustate->ovc0 = 0;
+}
+
+static CPU_RESET( upd78c05 )
+{
+ upd7810_state *cpustate = get_safe_token(device);
+ CPU_RESET_CALL(upd7810);
+ cpustate->op48 = op48_78c05;
+ cpustate->op4C = op4C_78c05;
+ cpustate->op4D = op4D_78c05;
+ cpustate->op60 = op60_78c05;
+ cpustate->op64 = op64_78c05;
+ cpustate->op70 = op70_78c05;
+ cpustate->op74 = op74_78c05;
+ cpustate->opXX = opXX_78c05;
+ MA = 0; /* All outputs */
+ MC = 0xFF; /* All inputs */
+ V = 0xFF; /* The vector register is always pointing to FF00 */
+ cpustate->handle_timers = upd78c05_timers;
+ TM0 = 0xFF; /* Timer seems to be running from boot */
+ cpustate->ovc0 = ( ( TMM & 0x04 ) ? 16 * 8 : 8 ) * TM0;
+}
+
+static CPU_RESET( upd78c06 )
+{
+ upd7810_state *cpustate = get_safe_token(device);
+ CPU_RESET_CALL(upd78c05);
+ cpustate->op48 = op48_78c06;
+ cpustate->op4C = op4C_78c06;
+ cpustate->op4D = op4D_78c06;
+ cpustate->op60 = op60_78c06;
+ cpustate->op64 = op64_78c06;
+ cpustate->op70 = op70_78c06;
+ cpustate->op74 = op74_78c06;
+ cpustate->opXX = opXX_78c06;
+}
+
+static CPU_EXIT( upd7810 )
+{
+}
+
+static CPU_EXECUTE( upd7810 )
+{
+ upd7810_state *cpustate = get_safe_token(device);
+
+ do
+ {
+ int cc = 0;
+
+ debugger_instruction_hook(device, PC);
+
+ PPC = PC;
+ RDOP(OP);
+
+ /*
+ * clear L0 and/or L1 flags for all opcodes except
+ * L0 for "MVI L,xx" or "LXI H,xxxx"
+ * L1 for "MVI A,xx"
+ */
+ PSW &= ~cpustate->opXX[OP].mask_l0_l1;
+
+ /* skip flag set and not SOFTI opcode? */
+ if ((PSW & SK) && (OP != 0x72))
+ {
+ if (cpustate->opXX[OP].cycles)
+ {
+ cc = cpustate->opXX[OP].cycles_skip;
+ PC += cpustate->opXX[OP].oplen - 1;
+ }
+ else
+ {
+ RDOP(OP2);
+ switch (OP)
+ {
+ case 0x48:
+ cc = cpustate->op48[OP2].cycles_skip;
+ PC += cpustate->op48[OP2].oplen - 2;
+ break;
+ case 0x4c:
+ cc = cpustate->op4C[OP2].cycles_skip;
+ PC += cpustate->op4C[OP2].oplen - 2;
+ break;
+ case 0x4d:
+ cc = cpustate->op4D[OP2].cycles_skip;
+ PC += cpustate->op4D[OP2].oplen - 2;
+ break;
+ case 0x60:
+ cc = cpustate->op60[OP2].cycles_skip;
+ PC += cpustate->op60[OP2].oplen - 2;
+ break;
+ case 0x64:
+ cc = cpustate->op64[OP2].cycles_skip;
+ PC += cpustate->op64[OP2].oplen - 2;
+ break;
+ case 0x70:
+ cc = cpustate->op70[OP2].cycles_skip;
+ PC += cpustate->op70[OP2].oplen - 2;
+ break;
+ case 0x74:
+ cc = cpustate->op74[OP2].cycles_skip;
+ PC += cpustate->op74[OP2].oplen - 2;
+ break;
+ default:
+ fatalerror("uPD7810 internal error: check cycle counts for main");
+ }
+ }
+ PSW &= ~SK;
+ cpustate->handle_timers( cpustate, cc );
+ }
+ else
+ {
+ cc = cpustate->opXX[OP].cycles;
+ cpustate->handle_timers( cpustate, cc );
+ (*cpustate->opXX[OP].opfunc)(cpustate);
+ }
+ cpustate->icount -= cc;
+ upd7810_take_irq(cpustate);
+
+ } while (cpustate->icount > 0);
+}
+
+static void set_irq_line(upd7810_state *cpustate, int irqline, int state)
+{
+ /* The uPD7801 can check for falling and rising edges changes on the INT2 input */
+ switch ( cpustate->config.type )
+ {
+ case TYPE_7801:
+ switch ( irqline )
+ {
+ case UPD7810_INTF0:
+ /* INT0 is level sensitive */
+ if ( state == ASSERT_LINE )
+ IRR |= INTF0;
+ else
+ IRR &= INTF0;
+ break;
+
+ case UPD7810_INTF1:
+ /* INT1 is rising edge sensitive */
+ if ( cpustate->int1 == CLEAR_LINE && state == ASSERT_LINE )
+ IRR |= INTF1;
+
+ cpustate->int1 = state;
+ break;
+
+ case UPD7810_INTF2:
+ /* INT2 is rising or falling edge sensitive */
+ /* Check if the ES bit is set then check for rising edge, otherwise falling edge */
+ if ( MKL & 0x20 )
+ {
+ if ( cpustate->int2 == CLEAR_LINE && state == ASSERT_LINE )
+ {
+ IRR |= INTF2;
+ }
+ }
+ else
+ {
+ if ( cpustate->int2 == ASSERT_LINE && state == CLEAR_LINE )
+ {
+ IRR |= INTF2;
+ }
+ }
+ cpustate->int2 = state;
+ break;
+ }
+ break;
+
+ default:
+ if (state != CLEAR_LINE)
+ {
+ if (irqline == INPUT_LINE_NMI)
+ {
+ /* no nested NMIs ? */
+// if (0 == (IRR & INTNMI))
+ {
+ IRR |= INTNMI;
+ SP--;
+ WM( SP, PSW );
+ SP--;
+ WM( SP, PCH );
+ SP--;
+ WM( SP, PCL );
+ IFF = 0;
+ PSW &= ~(SK|L0|L1);
+ PC = 0x0004;
+ }
+ }
+ else
+ if (irqline == UPD7810_INTF1)
+ IRR |= INTF1;
+ else
+ if ( irqline == UPD7810_INTF2 && ( MKL & 0x20 ) )
+ IRR |= INTF2;
+ // gamemaster hack
+ else
+ if (irqline == UPD7810_INTFE1)
+ IRR |= INTFE1;
+ else
+ logerror("upd7810_set_irq_line invalid irq line #%d\n", irqline);
+ }
+ /* resetting interrupt requests is done with the SKIT/SKNIT opcodes only! */
+ }
+}
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( upd7810 )
+{
+ upd7810_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_NMI: set_irq_line(cpustate, INPUT_LINE_NMI, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + UPD7810_INTF1: set_irq_line(cpustate, UPD7810_INTF1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + UPD7810_INTF2: set_irq_line(cpustate, UPD7810_INTF2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + UPD7810_INTFE1: set_irq_line(cpustate, UPD7810_INTFE1, info->i); break;
+
+ case CPUINFO_INT_PC: PC = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_PC: PC = info->i; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + UPD7810_SP: SP = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_PSW: PSW = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_A: A = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_V: V = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_EA: EA = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_VA: VA = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_BC: BC = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_DE: DE = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_HL: HL = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_EA2: EA2 = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_VA2: VA2 = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_BC2: BC2 = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_DE2: DE2 = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_HL2: HL2 = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_CNT0: CNT0 = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_CNT1: CNT1 = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_TM0: TM0 = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_TM1: TM1 = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_ECNT: ECNT = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_ECPT: ECPT = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_ETM0: ETM0 = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_ETM1: ETM1 = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_MA: MA = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_MB: MB = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_MCC: MCC = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_MC: MC = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_MM: MM = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_MF: MF = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_TMM: TMM = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_ETMM: ETMM = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_EOM: EOM = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_SML: SML = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_SMH: SMH = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_ANM: ANM = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_MKL: MKL = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_MKH: MKH = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_ZCM: ZCM = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_TXB: TXB = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_RXB: RXB = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_CR0: CR0 = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_CR1: CR1 = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_CR2: CR2 = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_CR3: CR3 = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_TXD: TXD = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_RXD: RXD = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_SCK: SCK = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_TI: TI = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_TO: TO = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_CI: CI = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_CO0: CO0 = info->i; break;
+ case CPUINFO_INT_REGISTER + UPD7810_CO1: CO1 = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( upd7810 )
+{
+ upd7810_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(upd7810_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 = 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 = 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 + INPUT_LINE_NMI: info->i = (IRR & INTNMI) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + UPD7810_INTF1: info->i = (IRR & INTF1) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + UPD7810_INTF2: info->i = (IRR & INTF2) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + UPD7810_INTFE1: info->i = (IRR & INTFE1) ? ASSERT_LINE : CLEAR_LINE; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = PPC; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + UPD7810_PC: info->i = PC; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + UPD7810_SP: info->i = SP; break;
+ case CPUINFO_INT_REGISTER + UPD7810_PSW: info->i = PSW; break;
+ case CPUINFO_INT_REGISTER + UPD7810_EA: info->i = EA; break;
+ case CPUINFO_INT_REGISTER + UPD7810_VA: info->i = VA; break;
+ case CPUINFO_INT_REGISTER + UPD7810_BC: info->i = BC; break;
+ case CPUINFO_INT_REGISTER + UPD7810_DE: info->i = DE; break;
+ case CPUINFO_INT_REGISTER + UPD7810_HL: info->i = HL; break;
+ case CPUINFO_INT_REGISTER + UPD7810_EA2: info->i = EA2; break;
+ case CPUINFO_INT_REGISTER + UPD7810_VA2: info->i = VA2; break;
+ case CPUINFO_INT_REGISTER + UPD7810_BC2: info->i = BC2; break;
+ case CPUINFO_INT_REGISTER + UPD7810_DE2: info->i = DE2; break;
+ case CPUINFO_INT_REGISTER + UPD7810_HL2: info->i = HL2; break;
+ case CPUINFO_INT_REGISTER + UPD7810_CNT0: info->i = CNT0; break;
+ case CPUINFO_INT_REGISTER + UPD7810_CNT1: info->i = CNT1; break;
+ case CPUINFO_INT_REGISTER + UPD7810_TM0: info->i = TM0; break;
+ case CPUINFO_INT_REGISTER + UPD7810_TM1: info->i = TM1; break;
+ case CPUINFO_INT_REGISTER + UPD7810_ECNT: info->i = ECNT; break;
+ case CPUINFO_INT_REGISTER + UPD7810_ECPT: info->i = ECPT; break;
+ case CPUINFO_INT_REGISTER + UPD7810_ETM0: info->i = ETM0; break;
+ case CPUINFO_INT_REGISTER + UPD7810_ETM1: info->i = ETM1; break;
+ case CPUINFO_INT_REGISTER + UPD7810_MA: info->i = MA; break;
+ case CPUINFO_INT_REGISTER + UPD7810_MB: info->i = MB; break;
+ case CPUINFO_INT_REGISTER + UPD7810_MCC: info->i = MCC; break;
+ case CPUINFO_INT_REGISTER + UPD7810_MC: info->i = MC; break;
+ case CPUINFO_INT_REGISTER + UPD7810_MM: info->i = MM; break;
+ case CPUINFO_INT_REGISTER + UPD7810_MF: info->i = MF; break;
+ case CPUINFO_INT_REGISTER + UPD7810_TMM: info->i = TMM; break;
+ case CPUINFO_INT_REGISTER + UPD7810_ETMM: info->i = ETMM; break;
+ case CPUINFO_INT_REGISTER + UPD7810_EOM: info->i = EOM; break;
+ case CPUINFO_INT_REGISTER + UPD7810_SML: info->i = SML; break;
+ case CPUINFO_INT_REGISTER + UPD7810_SMH: info->i = SMH; break;
+ case CPUINFO_INT_REGISTER + UPD7810_ANM: info->i = ANM; break;
+ case CPUINFO_INT_REGISTER + UPD7810_MKL: info->i = MKL; break;
+ case CPUINFO_INT_REGISTER + UPD7810_MKH: info->i = MKH; break;
+ case CPUINFO_INT_REGISTER + UPD7810_ZCM: info->i = ZCM; break;
+ case CPUINFO_INT_REGISTER + UPD7810_TXB: info->i = TXB; break;
+ case CPUINFO_INT_REGISTER + UPD7810_RXB: info->i = RXB; break;
+ case CPUINFO_INT_REGISTER + UPD7810_CR0: info->i = CR0; break;
+ case CPUINFO_INT_REGISTER + UPD7810_CR1: info->i = CR1; break;
+ case CPUINFO_INT_REGISTER + UPD7810_CR2: info->i = CR2; break;
+ case CPUINFO_INT_REGISTER + UPD7810_CR3: info->i = CR3; break;
+ case CPUINFO_INT_REGISTER + UPD7810_TXD: info->i = TXD; break;
+ case CPUINFO_INT_REGISTER + UPD7810_RXD: info->i = RXD; break;
+ case CPUINFO_INT_REGISTER + UPD7810_SCK: info->i = SCK; break;
+ case CPUINFO_INT_REGISTER + UPD7810_TI: info->i = TI; break;
+ case CPUINFO_INT_REGISTER + UPD7810_TO: info->i = TO; break;
+ case CPUINFO_INT_REGISTER + UPD7810_CI: info->i = CI; break;
+ case CPUINFO_INT_REGISTER + UPD7810_CO0: info->i = CO0; break;
+ case CPUINFO_INT_REGISTER + UPD7810_CO1: info->i = CO1; 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(upd7810); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(upd7810); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(upd7810); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(upd7810); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(upd7810); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(upd7810); 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, "uPD7810"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "NEC uPD7810"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "0.3"); 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, "%s:%s:%s:%s:%s:%s",
+ cpustate->psw & 0x40 ? "ZF":"--",
+ cpustate->psw & 0x20 ? "SK":"--",
+ cpustate->psw & 0x10 ? "HC":"--",
+ cpustate->psw & 0x08 ? "L1":"--",
+ cpustate->psw & 0x04 ? "L0":"--",
+ cpustate->psw & 0x01 ? "CY":"--");
+ break;
+
+ case CPUINFO_STR_REGISTER + UPD7810_PC: sprintf(info->s, "PC :%04X", cpustate->pc.w.l); break;
+ case CPUINFO_STR_REGISTER + UPD7810_SP: sprintf(info->s, "SP :%04X", cpustate->sp.w.l); break;
+ case CPUINFO_STR_REGISTER + UPD7810_PSW: sprintf(info->s, "PSW :%02X", cpustate->psw); break;
+ case CPUINFO_STR_REGISTER + UPD7810_A: sprintf(info->s, "A :%02X", cpustate->va.b.l); break;
+ case CPUINFO_STR_REGISTER + UPD7810_V: sprintf(info->s, "V :%02X", cpustate->va.b.h); break;
+ case CPUINFO_STR_REGISTER + UPD7810_EA: sprintf(info->s, "EA :%04X", cpustate->ea.w.l); break;
+ case CPUINFO_STR_REGISTER + UPD7810_BC: sprintf(info->s, "BC :%04X", cpustate->bc.w.l); break;
+ case CPUINFO_STR_REGISTER + UPD7810_DE: sprintf(info->s, "DE :%04X", cpustate->de.w.l); break;
+ case CPUINFO_STR_REGISTER + UPD7810_HL: sprintf(info->s, "HL :%04X", cpustate->hl.w.l); break;
+ case CPUINFO_STR_REGISTER + UPD7810_A2: sprintf(info->s, "A' :%02X", cpustate->va2.b.l); break;
+ case CPUINFO_STR_REGISTER + UPD7810_V2: sprintf(info->s, "V' :%02X", cpustate->va2.b.h); break;
+ case CPUINFO_STR_REGISTER + UPD7810_EA2: sprintf(info->s, "EA' :%04X", cpustate->ea2.w.l); break;
+ case CPUINFO_STR_REGISTER + UPD7810_BC2: sprintf(info->s, "BC' :%04X", cpustate->bc2.w.l); break;
+ case CPUINFO_STR_REGISTER + UPD7810_DE2: sprintf(info->s, "DE' :%04X", cpustate->de2.w.l); break;
+ case CPUINFO_STR_REGISTER + UPD7810_HL2: sprintf(info->s, "HL' :%04X", cpustate->hl2.w.l); break;
+ case CPUINFO_STR_REGISTER + UPD7810_CNT0: sprintf(info->s, "CNT0:%02X", cpustate->cnt.b.l); break;
+ case CPUINFO_STR_REGISTER + UPD7810_CNT1: sprintf(info->s, "CNT1:%02X", cpustate->cnt.b.h); break;
+ case CPUINFO_STR_REGISTER + UPD7810_TM0: sprintf(info->s, "TM0 :%02X", cpustate->tm.b.l); break;
+ case CPUINFO_STR_REGISTER + UPD7810_TM1: sprintf(info->s, "TM1 :%02X", cpustate->tm.b.h); break;
+ case CPUINFO_STR_REGISTER + UPD7810_ECNT: sprintf(info->s, "ECNT:%04X", cpustate->ecnt.w.l); break;
+ case CPUINFO_STR_REGISTER + UPD7810_ECPT: sprintf(info->s, "ECPT:%04X", cpustate->ecnt.w.h); break;
+ case CPUINFO_STR_REGISTER + UPD7810_ETM0: sprintf(info->s, "ETM0:%04X", cpustate->etm.w.l); break;
+ case CPUINFO_STR_REGISTER + UPD7810_ETM1: sprintf(info->s, "ETM1:%04X", cpustate->etm.w.h); break;
+ case CPUINFO_STR_REGISTER + UPD7810_MA: sprintf(info->s, "MA :%02X", cpustate->ma); break;
+ case CPUINFO_STR_REGISTER + UPD7810_MB: sprintf(info->s, "MB :%02X", cpustate->mb); break;
+ case CPUINFO_STR_REGISTER + UPD7810_MCC: sprintf(info->s, "MCC :%02X", cpustate->mcc); break;
+ case CPUINFO_STR_REGISTER + UPD7810_MC: sprintf(info->s, "MC :%02X", cpustate->mc); break;
+ case CPUINFO_STR_REGISTER + UPD7810_MM: sprintf(info->s, "MM :%02X", cpustate->mm); break;
+ case CPUINFO_STR_REGISTER + UPD7810_MF: sprintf(info->s, "MF :%02X", cpustate->mf); break;
+ case CPUINFO_STR_REGISTER + UPD7810_TMM: sprintf(info->s, "TMM :%02X", cpustate->tmm); break;
+ case CPUINFO_STR_REGISTER + UPD7810_ETMM: sprintf(info->s, "ETMM:%02X", cpustate->etmm); break;
+ case CPUINFO_STR_REGISTER + UPD7810_EOM: sprintf(info->s, "EOM :%02X", cpustate->eom); break;
+ case CPUINFO_STR_REGISTER + UPD7810_SML: sprintf(info->s, "SML :%02X", cpustate->sml); break;
+ case CPUINFO_STR_REGISTER + UPD7810_SMH: sprintf(info->s, "SMH :%02X", cpustate->smh); break;
+ case CPUINFO_STR_REGISTER + UPD7810_ANM: sprintf(info->s, "ANM :%02X", cpustate->anm); break;
+ case CPUINFO_STR_REGISTER + UPD7810_MKL: sprintf(info->s, "MKL :%02X", cpustate->mkl); break;
+ case CPUINFO_STR_REGISTER + UPD7810_MKH: sprintf(info->s, "MKH :%02X", cpustate->mkh); break;
+ case CPUINFO_STR_REGISTER + UPD7810_ZCM: sprintf(info->s, "ZCM :%02X", cpustate->zcm); break;
+ case CPUINFO_STR_REGISTER + UPD7810_CR0: sprintf(info->s, "CR0 :%02X", cpustate->cr0); break;
+ case CPUINFO_STR_REGISTER + UPD7810_CR1: sprintf(info->s, "CR1 :%02X", cpustate->cr1); break;
+ case CPUINFO_STR_REGISTER + UPD7810_CR2: sprintf(info->s, "CR2 :%02X", cpustate->cr2); break;
+ case CPUINFO_STR_REGISTER + UPD7810_CR3: sprintf(info->s, "CR3 :%02X", cpustate->cr3); break;
+ case CPUINFO_STR_REGISTER + UPD7810_RXB: sprintf(info->s, "RXB :%02X", cpustate->rxb); break;
+ case CPUINFO_STR_REGISTER + UPD7810_TXB: sprintf(info->s, "TXB :%02X", cpustate->txb); break;
+ case CPUINFO_STR_REGISTER + UPD7810_TXD: sprintf(info->s, "TXD :%d", cpustate->txd); break;
+ case CPUINFO_STR_REGISTER + UPD7810_RXD: sprintf(info->s, "RXD :%d", cpustate->rxd); break;
+ case CPUINFO_STR_REGISTER + UPD7810_SCK: sprintf(info->s, "SCK :%d", cpustate->sck); break;
+ case CPUINFO_STR_REGISTER + UPD7810_TI: sprintf(info->s, "TI :%d", cpustate->ti); break;
+ case CPUINFO_STR_REGISTER + UPD7810_TO: sprintf(info->s, "TO :%d", cpustate->to); break;
+ case CPUINFO_STR_REGISTER + UPD7810_CI: sprintf(info->s, "CI :%d", cpustate->ci); break;
+ case CPUINFO_STR_REGISTER + UPD7810_CO0: sprintf(info->s, "CO0 :%d", cpustate->co0 & 1); break;
+ case CPUINFO_STR_REGISTER + UPD7810_CO1: sprintf(info->s, "CO1 :%d", cpustate->co1 & 1); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+CPU_GET_INFO( upd7807 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(upd7807); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(upd7807); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "uPD7807"); break;
+
+ default: CPU_GET_INFO_CALL(upd7810); break;
+ }
+}
+
+CPU_GET_INFO( upd7801 ) {
+ switch( state ) {
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(upd7801); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(upd7801); break;
+
+ case DEVINFO_STR_NAME: strcpy(info->s, "uPD7801"); break;
+
+ default: CPU_GET_INFO_CALL(upd7810); break;
+ }
+}
+
+CPU_GET_INFO( upd78c05 ) {
+ switch ( state ) {
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 4; break;
+
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(upd78c05); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(upd78c05); break;
+
+ case DEVINFO_STR_NAME: strcpy(info->s, "uPD78C05"); break;
+
+ /* These registers are not present in the uPD78C05 cpu */
+ case CPUINFO_STR_REGISTER + UPD7810_A2:
+ case CPUINFO_STR_REGISTER + UPD7810_V2:
+ case CPUINFO_STR_REGISTER + UPD7810_EA2:
+ case CPUINFO_STR_REGISTER + UPD7810_BC2:
+ case CPUINFO_STR_REGISTER + UPD7810_DE2:
+ case CPUINFO_STR_REGISTER + UPD7810_HL2:
+ case CPUINFO_STR_REGISTER + UPD7810_MA:
+ case CPUINFO_STR_REGISTER + UPD7810_MCC:
+ case CPUINFO_STR_REGISTER + UPD7810_MC:
+ case CPUINFO_STR_REGISTER + UPD7810_MM:
+ case CPUINFO_STR_REGISTER + UPD7810_MF:
+ case CPUINFO_STR_REGISTER + UPD7810_ETMM:
+ case CPUINFO_STR_REGISTER + UPD7810_EOM:
+ case CPUINFO_STR_REGISTER + UPD7810_SML:
+ case CPUINFO_STR_REGISTER + UPD7810_SMH:
+ case CPUINFO_STR_REGISTER + UPD7810_ANM:
+ case CPUINFO_STR_REGISTER + UPD7810_MKH:
+ case CPUINFO_STR_REGISTER + UPD7810_ZCM:
+ case CPUINFO_STR_REGISTER + UPD7810_CR0:
+ case CPUINFO_STR_REGISTER + UPD7810_CR1:
+ case CPUINFO_STR_REGISTER + UPD7810_CR2:
+ case CPUINFO_STR_REGISTER + UPD7810_CR3:
+ case CPUINFO_STR_REGISTER + UPD7810_RXB:
+ case CPUINFO_STR_REGISTER + UPD7810_TXB:
+ case CPUINFO_STR_REGISTER + UPD7810_TXD:
+ case CPUINFO_STR_REGISTER + UPD7810_RXD:
+ case CPUINFO_STR_REGISTER + UPD7810_SCK:
+ case CPUINFO_STR_REGISTER + UPD7810_TI:
+ case CPUINFO_STR_REGISTER + UPD7810_TO:
+ case CPUINFO_STR_REGISTER + UPD7810_CI:
+ case CPUINFO_STR_REGISTER + UPD7810_CO0:
+ case CPUINFO_STR_REGISTER + UPD7810_CO1: break;
+
+ default: CPU_GET_INFO_CALL(upd7801); break;
+ }
+}
+
+CPU_GET_INFO( upd78c06 ) {
+ switch ( state ) {
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(upd78c06); break;
+
+ case DEVINFO_STR_NAME: strcpy(info->s, "uPD78C06"); break;
+
+ default: CPU_GET_INFO_CALL(upd78c05); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(UPD7810, upd7810);
+DEFINE_LEGACY_CPU_DEVICE(UPD7807, upd7807);
+DEFINE_LEGACY_CPU_DEVICE(UPD7801, upd7801);
+DEFINE_LEGACY_CPU_DEVICE(UPD78C05, upd78c05);
+DEFINE_LEGACY_CPU_DEVICE(UPD78C06, upd78c06);
diff --git a/trunk/src/emu/cpu/upd7810/upd7810.h b/trunk/src/emu/cpu/upd7810/upd7810.h
new file mode 100644
index 00000000000..4bb2ba2e062
--- /dev/null
+++ b/trunk/src/emu/cpu/upd7810/upd7810.h
@@ -0,0 +1,85 @@
+#pragma once
+
+#ifndef __UPD7810_H__
+#define __UPD7810_H__
+
+
+/*
+ all types have internal ram at 0xff00-0xffff
+ 7810
+ 7811 (4kbyte),7812(8),7814(16) have internal rom at 0x0000
+*/
+
+// unfortunatly memory configuration differs with internal rom size
+typedef enum
+{
+ TYPE_7801,
+ TYPE_78C05,
+ TYPE_78C06,
+ TYPE_7810,
+ TYPE_7810_GAMEMASTER, // a few modifications until internal rom dumped
+ TYPE_7807
+// TYPE_78C10, // stop instruction added
+// TYPE_78IV,
+// TYPE_78K0,
+// TYPE_78K0S
+// millions of subtypes
+} UPD7810_TYPE;
+
+/* Supply an instance of this function in your driver code:
+ * It will be called whenever an output signal changes or a new
+ * input line state is to be sampled.
+ */
+typedef int (*upd7810_io_callback)(device_t *device, int ioline, int state);
+
+// use it as reset parameter in the Machine struct
+typedef struct {
+ UPD7810_TYPE type;
+ upd7810_io_callback io_callback;
+} UPD7810_CONFIG;
+
+enum
+{
+ UPD7810_PC=1, UPD7810_SP, UPD7810_PSW,
+ UPD7810_EA, UPD7810_V, UPD7810_A, UPD7810_VA,
+ UPD7810_BC, UPD7810_B, UPD7810_C, UPD7810_DE, UPD7810_D, UPD7810_E, UPD7810_HL, UPD7810_H, UPD7810_L,
+ UPD7810_EA2, UPD7810_V2, UPD7810_A2, UPD7810_VA2,
+ UPD7810_BC2, UPD7810_B2, UPD7810_C2, UPD7810_DE2, UPD7810_D2, UPD7810_E2, UPD7810_HL2, UPD7810_H2, UPD7810_L2,
+ UPD7810_CNT0, UPD7810_CNT1, UPD7810_TM0, UPD7810_TM1, UPD7810_ECNT, UPD7810_ECPT, UPD7810_ETM0, UPD7810_ETM1,
+ UPD7810_MA, UPD7810_MB, UPD7810_MCC, UPD7810_MC, UPD7810_MM, UPD7810_MF,
+ UPD7810_TMM, UPD7810_ETMM, UPD7810_EOM, UPD7810_SML, UPD7810_SMH,
+ UPD7810_ANM, UPD7810_MKL, UPD7810_MKH, UPD7810_ZCM,
+ UPD7810_TXB, UPD7810_RXB, UPD7810_CR0, UPD7810_CR1, UPD7810_CR2, UPD7810_CR3,
+ UPD7810_TXD, UPD7810_RXD, UPD7810_SCK, UPD7810_TI, UPD7810_TO, UPD7810_CI, UPD7810_CO0, UPD7810_CO1
+};
+
+/* port numbers for PA,PB,PC,PD and PF */
+enum
+{
+ UPD7810_PORTA, UPD7810_PORTB, UPD7810_PORTC, UPD7810_PORTD, UPD7810_PORTF
+};
+
+enum
+{
+ UPD7807_PORTA, UPD7807_PORTB, UPD7807_PORTC, UPD7807_PORTD, UPD7807_PORTF,
+ UPD7807_PORTT
+};
+
+/* IRQ lines */
+#define UPD7810_INTF1 0
+#define UPD7810_INTF2 1
+#define UPD7810_INTF0 2
+#define UPD7810_INTFE1 4
+
+DECLARE_LEGACY_CPU_DEVICE(UPD7810, upd7810);
+DECLARE_LEGACY_CPU_DEVICE(UPD7807, upd7807);
+DECLARE_LEGACY_CPU_DEVICE(UPD7801, upd7801);
+DECLARE_LEGACY_CPU_DEVICE(UPD78C05, upd78c05);
+DECLARE_LEGACY_CPU_DEVICE(UPD78C06, upd78c06);
+
+CPU_DISASSEMBLE( upd7810 );
+CPU_DISASSEMBLE( upd7807 );
+CPU_DISASSEMBLE( upd7801 );
+CPU_DISASSEMBLE( upd78c05 );
+
+#endif /* __UPD7810_H__ */
diff --git a/trunk/src/emu/cpu/v30mz/nec.h b/trunk/src/emu/cpu/v30mz/nec.h
new file mode 100644
index 00000000000..a3e575b3413
--- /dev/null
+++ b/trunk/src/emu/cpu/v30mz/nec.h
@@ -0,0 +1,23 @@
+/* ASG 971222 -- rewrote this interface */
+#ifndef __NECINTRF_H__
+#define __NECINTRF_H__
+
+
+typedef struct _nec_config nec_config;
+struct _nec_config
+{
+ const UINT8* v25v35_decryptiontable; // internal decryption table
+};
+
+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_VECTOR, NEC_PENDING
+};
+
+/* Public functions */
+DECLARE_LEGACY_CPU_DEVICE(V30MZ, v30mz);
+
+#endif /* __NECINTRF_H__ */
diff --git a/trunk/src/emu/cpu/v30mz/necea.h b/trunk/src/emu/cpu/v30mz/necea.h
new file mode 100644
index 00000000000..d55b5c75b0a
--- /dev/null
+++ b/trunk/src/emu/cpu/v30mz/necea.h
@@ -0,0 +1,56 @@
+
+static unsigned EA_000(v30mz_state *cpustate) { cpustate->eo=cpustate->regs.w[BW]+cpustate->regs.w[IX]; cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_001(v30mz_state *cpustate) { cpustate->eo=cpustate->regs.w[BW]+cpustate->regs.w[IY]; cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_002(v30mz_state *cpustate) { cpustate->eo=cpustate->regs.w[BP]+cpustate->regs.w[IX]; cpustate->ea=DefaultBase(SS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_003(v30mz_state *cpustate) { cpustate->eo=cpustate->regs.w[BP]+cpustate->regs.w[IY]; cpustate->ea=DefaultBase(SS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_004(v30mz_state *cpustate) { cpustate->eo=cpustate->regs.w[IX]; cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_005(v30mz_state *cpustate) { cpustate->eo=cpustate->regs.w[IY]; cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_006(v30mz_state *cpustate) { cpustate->eo=FETCH; cpustate->eo+=FETCH<<8; cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_007(v30mz_state *cpustate) { cpustate->eo=cpustate->regs.w[BW]; cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+
+static unsigned EA_100(v30mz_state *cpustate) { cpustate->eo=(cpustate->regs.w[BW]+cpustate->regs.w[IX]+(INT8)FETCH); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_101(v30mz_state *cpustate) { cpustate->eo=(cpustate->regs.w[BW]+cpustate->regs.w[IY]+(INT8)FETCH); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_102(v30mz_state *cpustate) { cpustate->eo=(cpustate->regs.w[BP]+cpustate->regs.w[IX]+(INT8)FETCH); cpustate->ea=DefaultBase(SS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_103(v30mz_state *cpustate) { cpustate->eo=(cpustate->regs.w[BP]+cpustate->regs.w[IY]+(INT8)FETCH); cpustate->ea=DefaultBase(SS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_104(v30mz_state *cpustate) { cpustate->eo=(cpustate->regs.w[IX]+(INT8)FETCH); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_105(v30mz_state *cpustate) { cpustate->eo=(cpustate->regs.w[IY]+(INT8)FETCH); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_106(v30mz_state *cpustate) { cpustate->eo=(cpustate->regs.w[BP]+(INT8)FETCH); cpustate->ea=DefaultBase(SS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_107(v30mz_state *cpustate) { cpustate->eo=(cpustate->regs.w[BW]+(INT8)FETCH); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+
+static unsigned EA_200(v30mz_state *cpustate) { cpustate->e16=FETCH; cpustate->e16+=FETCH<<8; cpustate->eo=cpustate->regs.w[BW]+cpustate->regs.w[IX]+(INT16)cpustate->e16; cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_201(v30mz_state *cpustate) { cpustate->e16=FETCH; cpustate->e16+=FETCH<<8; cpustate->eo=cpustate->regs.w[BW]+cpustate->regs.w[IY]+(INT16)cpustate->e16; cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_202(v30mz_state *cpustate) { cpustate->e16=FETCH; cpustate->e16+=FETCH<<8; cpustate->eo=cpustate->regs.w[BP]+cpustate->regs.w[IX]+(INT16)cpustate->e16; cpustate->ea=DefaultBase(SS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_203(v30mz_state *cpustate) { cpustate->e16=FETCH; cpustate->e16+=FETCH<<8; cpustate->eo=cpustate->regs.w[BP]+cpustate->regs.w[IY]+(INT16)cpustate->e16; cpustate->ea=DefaultBase(SS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_204(v30mz_state *cpustate) { cpustate->e16=FETCH; cpustate->e16+=FETCH<<8; cpustate->eo=cpustate->regs.w[IX]+(INT16)cpustate->e16; cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_205(v30mz_state *cpustate) { cpustate->e16=FETCH; cpustate->e16+=FETCH<<8; cpustate->eo=cpustate->regs.w[IY]+(INT16)cpustate->e16; cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_206(v30mz_state *cpustate) { cpustate->e16=FETCH; cpustate->e16+=FETCH<<8; cpustate->eo=cpustate->regs.w[BP]+(INT16)cpustate->e16; cpustate->ea=DefaultBase(SS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_207(v30mz_state *cpustate) { cpustate->e16=FETCH; cpustate->e16+=FETCH<<8; cpustate->eo=cpustate->regs.w[BW]+(INT16)cpustate->e16; cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+
+static unsigned (*const GetEA[192])(v30mz_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/v30mz/nechost.h b/trunk/src/emu/cpu/v30mz/nechost.h
new file mode 100644
index 00000000000..042d880c89d
--- /dev/null
+++ b/trunk/src/emu/cpu/v30mz/nechost.h
@@ -0,0 +1,11 @@
+/*****************************************************************************/
+/* host dependent types */
+
+#define BIGCASE
+
+
+typedef char BOOLEAN;
+
+typedef UINT8 BYTE;
+typedef UINT16 WORD;
+typedef UINT32 DWORD;
diff --git a/trunk/src/emu/cpu/v30mz/necinstr.h b/trunk/src/emu/cpu/v30mz/necinstr.h
new file mode 100644
index 00000000000..88708ab14b1
--- /dev/null
+++ b/trunk/src/emu/cpu/v30mz/necinstr.h
@@ -0,0 +1,507 @@
+static void i_add_br8(v30mz_state *cpustate);
+static void i_add_wr16(v30mz_state *cpustate);
+static void i_add_r8b(v30mz_state *cpustate);
+static void i_add_r16w(v30mz_state *cpustate);
+static void i_add_ald8(v30mz_state *cpustate);
+static void i_add_axd16(v30mz_state *cpustate);
+static void i_push_es(v30mz_state *cpustate);
+static void i_pop_es(v30mz_state *cpustate);
+static void i_or_br8(v30mz_state *cpustate);
+static void i_or_r8b(v30mz_state *cpustate);
+static void i_or_wr16(v30mz_state *cpustate);
+static void i_or_r16w(v30mz_state *cpustate);
+static void i_or_ald8(v30mz_state *cpustate);
+static void i_or_axd16(v30mz_state *cpustate);
+static void i_push_cs(v30mz_state *cpustate);
+static void i_pre_nec(v30mz_state *cpustate);
+static void i_adc_br8(v30mz_state *cpustate);
+static void i_adc_wr16(v30mz_state *cpustate);
+static void i_adc_r8b(v30mz_state *cpustate);
+static void i_adc_r16w(v30mz_state *cpustate);
+static void i_adc_ald8(v30mz_state *cpustate);
+static void i_adc_axd16(v30mz_state *cpustate);
+static void i_push_ss(v30mz_state *cpustate);
+static void i_pop_ss(v30mz_state *cpustate);
+static void i_sbb_br8(v30mz_state *cpustate);
+static void i_sbb_wr16(v30mz_state *cpustate);
+static void i_sbb_r8b(v30mz_state *cpustate);
+static void i_sbb_r16w(v30mz_state *cpustate);
+static void i_sbb_ald8(v30mz_state *cpustate);
+static void i_sbb_axd16(v30mz_state *cpustate);
+static void i_push_ds(v30mz_state *cpustate);
+static void i_pop_ds(v30mz_state *cpustate);
+static void i_and_br8(v30mz_state *cpustate);
+static void i_and_r8b(v30mz_state *cpustate);
+static void i_and_wr16(v30mz_state *cpustate);
+static void i_and_r16w(v30mz_state *cpustate);
+static void i_and_ald8(v30mz_state *cpustate);
+static void i_and_axd16(v30mz_state *cpustate);
+static void i_es(v30mz_state *cpustate);
+static void i_daa(v30mz_state *cpustate);
+static void i_sub_br8(v30mz_state *cpustate);
+static void i_sub_wr16(v30mz_state *cpustate);
+static void i_sub_r8b(v30mz_state *cpustate);
+static void i_sub_r16w(v30mz_state *cpustate);
+static void i_sub_ald8(v30mz_state *cpustate);
+static void i_sub_axd16(v30mz_state *cpustate);
+static void i_cs(v30mz_state *cpustate);
+static void i_das(v30mz_state *cpustate);
+static void i_xor_br8(v30mz_state *cpustate);
+static void i_xor_r8b(v30mz_state *cpustate);
+static void i_xor_wr16(v30mz_state *cpustate);
+static void i_xor_r16w(v30mz_state *cpustate);
+static void i_xor_ald8(v30mz_state *cpustate);
+static void i_xor_axd16(v30mz_state *cpustate);
+static void i_ss(v30mz_state *cpustate);
+static void i_aaa(v30mz_state *cpustate);
+static void i_cmp_br8(v30mz_state *cpustate);
+static void i_cmp_wr16(v30mz_state *cpustate);
+static void i_cmp_r8b(v30mz_state *cpustate);
+static void i_cmp_r16w(v30mz_state *cpustate);
+static void i_cmp_ald8(v30mz_state *cpustate);
+static void i_cmp_axd16(v30mz_state *cpustate);
+static void i_ds(v30mz_state *cpustate);
+static void i_aas(v30mz_state *cpustate);
+static void i_inc_ax(v30mz_state *cpustate);
+static void i_inc_cx(v30mz_state *cpustate);
+static void i_inc_dx(v30mz_state *cpustate);
+static void i_inc_bx(v30mz_state *cpustate);
+static void i_inc_sp(v30mz_state *cpustate);
+static void i_inc_bp(v30mz_state *cpustate);
+static void i_inc_si(v30mz_state *cpustate);
+static void i_inc_di(v30mz_state *cpustate);
+static void i_dec_ax(v30mz_state *cpustate);
+static void i_dec_cx(v30mz_state *cpustate);
+static void i_dec_dx(v30mz_state *cpustate);
+static void i_dec_bx(v30mz_state *cpustate);
+static void i_dec_sp(v30mz_state *cpustate);
+static void i_dec_bp(v30mz_state *cpustate);
+static void i_dec_si(v30mz_state *cpustate);
+static void i_dec_di(v30mz_state *cpustate);
+static void i_push_ax(v30mz_state *cpustate);
+static void i_push_cx(v30mz_state *cpustate);
+static void i_push_dx(v30mz_state *cpustate);
+static void i_push_bx(v30mz_state *cpustate);
+static void i_push_sp(v30mz_state *cpustate);
+static void i_push_bp(v30mz_state *cpustate);
+static void i_push_si(v30mz_state *cpustate);
+static void i_push_di(v30mz_state *cpustate);
+static void i_pop_ax(v30mz_state *cpustate);
+static void i_pop_cx(v30mz_state *cpustate);
+static void i_pop_dx(v30mz_state *cpustate);
+static void i_pop_bx(v30mz_state *cpustate);
+static void i_pop_sp(v30mz_state *cpustate);
+static void i_pop_bp(v30mz_state *cpustate);
+static void i_pop_si(v30mz_state *cpustate);
+static void i_pop_di(v30mz_state *cpustate);
+static void i_pusha(v30mz_state *cpustate);
+static void i_popa(v30mz_state *cpustate);
+static void i_chkind(v30mz_state *cpustate);
+static void i_repnc(v30mz_state *cpustate);
+static void i_repc(v30mz_state *cpustate);
+static void i_push_d16(v30mz_state *cpustate);
+static void i_imul_d16(v30mz_state *cpustate);
+static void i_push_d8(v30mz_state *cpustate);
+static void i_imul_d8(v30mz_state *cpustate);
+static void i_insb(v30mz_state *cpustate);
+static void i_insw(v30mz_state *cpustate);
+static void i_outsb(v30mz_state *cpustate);
+static void i_outsw(v30mz_state *cpustate);
+static void i_jo(v30mz_state *cpustate);
+static void i_jno(v30mz_state *cpustate);
+static void i_jc(v30mz_state *cpustate);
+static void i_jnc(v30mz_state *cpustate);
+static void i_jz(v30mz_state *cpustate);
+static void i_jnz(v30mz_state *cpustate);
+static void i_jce(v30mz_state *cpustate);
+static void i_jnce(v30mz_state *cpustate);
+static void i_js(v30mz_state *cpustate);
+static void i_jns(v30mz_state *cpustate);
+static void i_jp(v30mz_state *cpustate);
+static void i_jnp(v30mz_state *cpustate);
+static void i_jl(v30mz_state *cpustate);
+static void i_jnl(v30mz_state *cpustate);
+static void i_jle(v30mz_state *cpustate);
+static void i_jnle(v30mz_state *cpustate);
+static void i_80pre(v30mz_state *cpustate);
+static void i_82pre(v30mz_state *cpustate);
+static void i_81pre(v30mz_state *cpustate);
+static void i_83pre(v30mz_state *cpustate);
+static void i_test_br8(v30mz_state *cpustate);
+static void i_test_wr16(v30mz_state *cpustate);
+static void i_xchg_br8(v30mz_state *cpustate);
+static void i_xchg_wr16(v30mz_state *cpustate);
+static void i_mov_br8(v30mz_state *cpustate);
+static void i_mov_r8b(v30mz_state *cpustate);
+static void i_mov_wr16(v30mz_state *cpustate);
+static void i_mov_r16w(v30mz_state *cpustate);
+static void i_mov_wsreg(v30mz_state *cpustate);
+static void i_lea(v30mz_state *cpustate);
+static void i_mov_sregw(v30mz_state *cpustate);
+static void i_invalid(v30mz_state *cpustate);
+static void i_popw(v30mz_state *cpustate);
+static void i_nop(v30mz_state *cpustate);
+static void i_xchg_axcx(v30mz_state *cpustate);
+static void i_xchg_axdx(v30mz_state *cpustate);
+static void i_xchg_axbx(v30mz_state *cpustate);
+static void i_xchg_axsp(v30mz_state *cpustate);
+static void i_xchg_axbp(v30mz_state *cpustate);
+static void i_xchg_axsi(v30mz_state *cpustate);
+static void i_xchg_axdi(v30mz_state *cpustate);
+static void i_cbw(v30mz_state *cpustate);
+static void i_cwd(v30mz_state *cpustate);
+static void i_call_far(v30mz_state *cpustate);
+static void i_pushf(v30mz_state *cpustate);
+static void i_popf(v30mz_state *cpustate);
+static void i_sahf(v30mz_state *cpustate);
+static void i_lahf(v30mz_state *cpustate);
+static void i_mov_aldisp(v30mz_state *cpustate);
+static void i_mov_axdisp(v30mz_state *cpustate);
+static void i_mov_dispal(v30mz_state *cpustate);
+static void i_mov_dispax(v30mz_state *cpustate);
+static void i_movsb(v30mz_state *cpustate);
+static void i_movsw(v30mz_state *cpustate);
+static void i_cmpsb(v30mz_state *cpustate);
+static void i_cmpsw(v30mz_state *cpustate);
+static void i_test_ald8(v30mz_state *cpustate);
+static void i_test_axd16(v30mz_state *cpustate);
+static void i_stosb(v30mz_state *cpustate);
+static void i_stosw(v30mz_state *cpustate);
+static void i_lodsb(v30mz_state *cpustate);
+static void i_lodsw(v30mz_state *cpustate);
+static void i_scasb(v30mz_state *cpustate);
+static void i_scasw(v30mz_state *cpustate);
+static void i_mov_ald8(v30mz_state *cpustate);
+static void i_mov_cld8(v30mz_state *cpustate);
+static void i_mov_dld8(v30mz_state *cpustate);
+static void i_mov_bld8(v30mz_state *cpustate);
+static void i_mov_ahd8(v30mz_state *cpustate);
+static void i_mov_chd8(v30mz_state *cpustate);
+static void i_mov_dhd8(v30mz_state *cpustate);
+static void i_mov_bhd8(v30mz_state *cpustate);
+static void i_mov_axd16(v30mz_state *cpustate);
+static void i_mov_cxd16(v30mz_state *cpustate);
+static void i_mov_dxd16(v30mz_state *cpustate);
+static void i_mov_bxd16(v30mz_state *cpustate);
+static void i_mov_spd16(v30mz_state *cpustate);
+static void i_mov_bpd16(v30mz_state *cpustate);
+static void i_mov_sid16(v30mz_state *cpustate);
+static void i_mov_did16(v30mz_state *cpustate);
+static void i_rotshft_bd8(v30mz_state *cpustate);
+static void i_rotshft_wd8(v30mz_state *cpustate);
+static void i_ret_d16(v30mz_state *cpustate);
+static void i_ret(v30mz_state *cpustate);
+static void i_les_dw(v30mz_state *cpustate);
+static void i_lds_dw(v30mz_state *cpustate);
+static void i_mov_bd8(v30mz_state *cpustate);
+static void i_mov_wd16(v30mz_state *cpustate);
+static void i_enter(v30mz_state *cpustate);
+static void i_leave(v30mz_state *cpustate);
+static void i_retf_d16(v30mz_state *cpustate);
+static void i_retf(v30mz_state *cpustate);
+static void i_int3(v30mz_state *cpustate);
+static void i_int(v30mz_state *cpustate);
+static void i_into(v30mz_state *cpustate);
+static void i_iret(v30mz_state *cpustate);
+static void i_rotshft_b(v30mz_state *cpustate);
+static void i_rotshft_w(v30mz_state *cpustate);
+static void i_rotshft_bcl(v30mz_state *cpustate);
+static void i_rotshft_wcl(v30mz_state *cpustate);
+static void i_aam(v30mz_state *cpustate);
+static void i_aad(v30mz_state *cpustate);
+static void i_setalc(v30mz_state *cpustate);
+static void i_trans(v30mz_state *cpustate);
+static void i_fpo(v30mz_state *cpustate);
+static void i_loopne(v30mz_state *cpustate);
+static void i_loope(v30mz_state *cpustate);
+static void i_loop(v30mz_state *cpustate);
+static void i_jcxz(v30mz_state *cpustate);
+static void i_inal(v30mz_state *cpustate);
+static void i_inax(v30mz_state *cpustate);
+static void i_outal(v30mz_state *cpustate);
+static void i_outax(v30mz_state *cpustate);
+static void i_call_d16(v30mz_state *cpustate);
+static void i_jmp_d16(v30mz_state *cpustate);
+static void i_jmp_far(v30mz_state *cpustate);
+static void i_jmp_d8(v30mz_state *cpustate);
+static void i_inaldx(v30mz_state *cpustate);
+static void i_inaxdx(v30mz_state *cpustate);
+static void i_outdxal(v30mz_state *cpustate);
+static void i_outdxax(v30mz_state *cpustate);
+static void i_lock(v30mz_state *cpustate);
+static void i_repne(v30mz_state *cpustate);
+static void i_repe(v30mz_state *cpustate);
+static void i_hlt(v30mz_state *cpustate);
+static void i_cmc(v30mz_state *cpustate);
+static void i_f6pre(v30mz_state *cpustate);
+static void i_f7pre(v30mz_state *cpustate);
+static void i_clc(v30mz_state *cpustate);
+static void i_stc(v30mz_state *cpustate);
+static void i_di(v30mz_state *cpustate);
+static void i_ei(v30mz_state *cpustate);
+static void i_cld(v30mz_state *cpustate);
+static void i_std(v30mz_state *cpustate);
+static void i_fepre(v30mz_state *cpustate);
+static void i_ffpre(v30mz_state *cpustate);
+
+static void i_wait(v30mz_state *cpustate);
+
+static void (*const nec_instruction[256])(v30mz_state *cpustate) =
+{
+ 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, /* 0x97 */
+ 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,
+ 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/v30mz/necmodrm.h b/trunk/src/emu/cpu/v30mz/necmodrm.h
new file mode 100644
index 00000000000..23cfedffad7
--- /dev/null
+++ b/trunk/src/emu/cpu/v30mz/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) 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&0xf0000)|((cpustate->ea+2)&0xffff))
+
+#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 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 \
+ 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 = cpustate->regs.b[AL]
+
+#define DEF_axd16 \
+ UINT32 src = FETCH; \
+ UINT32 dst = cpustate->regs.w[AW]; \
+ src += (FETCH << 8)
diff --git a/trunk/src/emu/cpu/v30mz/v30mz.c b/trunk/src/emu/cpu/v30mz/v30mz.c
new file mode 100644
index 00000000000..900a5616376
--- /dev/null
+++ b/trunk/src/emu/cpu/v30mz/v30mz.c
@@ -0,0 +1,1171 @@
+/****************************************************************************
+
+ NEC V20/V30/V33 emulator modified to a v30mz emulator
+
+ (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%.
+ Fix memory interface (should be 16 bit).
+
+****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+
+#define PC(n) (((n)->sregs[CS]<<4)+(n)->ip)
+
+typedef UINT8 BOOLEAN;
+typedef UINT8 BYTE;
+typedef UINT16 WORD;
+typedef UINT32 DWORD;
+
+#include "v30mz.h"
+#include "nec.h"
+
+/* NEC registers */
+typedef union
+{ /* eight general registers */
+ UINT16 w[8]; /* viewed as 16 bits registers */
+ UINT8 b[16]; /* or as 8 bit registers */
+} necbasicregs;
+
+/* default configuration */
+static const nec_config default_config =
+{
+ NULL // no internal decryption table
+};
+
+typedef struct _v30mz_state v30mz_state;
+struct _v30mz_state
+{
+ necbasicregs regs;
+ UINT16 sregs[4];
+
+ UINT16 ip;
+
+ INT32 SignVal;
+ UINT32 AuxVal, OverVal, ZeroVal, CarryVal, ParityVal; /* 0 or non-0 valued flags */
+ UINT8 TF, IF, DF, MF; /* 0 or 1 valued flags */ /* OB[19.07.99] added Mode Flag V30 */
+ UINT32 int_vector;
+ UINT32 pending_irq;
+ UINT32 nmi_state;
+ UINT32 irq_state;
+ UINT8 no_interrupt;
+
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *io;
+ int icount;
+
+ UINT32 prefix_base; /* base address of the latest prefix segment */
+ char seg_prefix; /* prefix segment indicator */
+
+ UINT32 ea;
+ UINT16 eo;
+ UINT16 e16;
+
+ const nec_config *config;
+};
+
+extern int necv_dasm_one(char *buffer, UINT32 eip, const UINT8 *oprom, const nec_config *config);
+
+INLINE v30mz_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == V30MZ);
+ return (v30mz_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/***************************************************************************/
+/* cpu state */
+/***************************************************************************/
+
+
+/* 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 INT_IRQ 0x01
+#define NMI_IRQ 0x02
+
+#include "necinstr.h"
+#include "necea.h"
+#include "necmodrm.h"
+
+static UINT8 parity_table[256];
+
+/***************************************************************************/
+
+static CPU_RESET( nec )
+{
+ v30mz_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 };
+ 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;
+
+ for (i = 0;i < 256; i++)
+ {
+ for (j = i, c = 0; j > 0; j >>= 1)
+ if (j & 1) c++;
+ parity_table[i] = !(c & 1);
+ }
+
+ cpustate->ZeroVal = cpustate->ParityVal = 1;
+ SetMD(1); /* set the mode-flag = native mode */
+
+ 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 CPU_EXIT( nec )
+{
+
+}
+
+static void nec_interrupt(v30mz_state *cpustate,unsigned int_num,BOOLEAN md_flag)
+{
+ UINT32 dest_seg, dest_off;
+
+ i_pushf(cpustate);
+ cpustate->TF = cpustate->IF = 0;
+ if (md_flag) SetMD(0); /* clear Mode-flag = start 8080 emulation mode */
+
+ if (int_num == -1)
+ {
+ int_num = (*cpustate->irq_callback)(cpustate->device, 0);
+
+ cpustate->irq_state = CLEAR_LINE;
+ cpustate->pending_irq &= ~INT_IRQ;
+ }
+
+ dest_off = ReadWord(int_num*4);
+ dest_seg = ReadWord(int_num*4+2);
+
+ PUSH(cpustate->sregs[CS]);
+ PUSH(cpustate->ip);
+ cpustate->ip = (WORD)dest_off;
+ cpustate->sregs[CS] = (WORD)dest_seg;
+}
+
+static void nec_trap(v30mz_state *cpustate)
+{
+ nec_instruction[FETCHOP](cpustate);
+ nec_interrupt(cpustate,1,0);
+}
+
+static void external_int(v30mz_state *cpustate)
+{
+ if( cpustate->pending_irq & NMI_IRQ )
+ {
+ nec_interrupt(cpustate,NEC_NMI_INT_VECTOR,0);
+ cpustate->pending_irq &= ~NMI_IRQ;
+ }
+ else if( cpustate->pending_irq )
+ {
+ /* the actual vector is retrieved after pushing flags */
+ /* and clearing the IF */
+ nec_interrupt(cpustate,(UINT32)-1,0);
+ }
+}
+
+/****************************************************************************/
+/* OPCODES */
+/****************************************************************************/
+
+#define OP(num,func_name) static void func_name(v30mz_state *cpustate)
+
+OP( 0x00, i_add_br8 ) { DEF_br8; ADDB; PutbackRMByte(ModRM,dst); CLKM(1,3); }
+OP( 0x01, i_add_wr16 ) { DEF_wr16; ADDW; PutbackRMWord(ModRM,dst); CLKM(1,3);}
+OP( 0x02, i_add_r8b ) { DEF_r8b; ADDB; RegByte(ModRM)=dst; CLKM(1,2); }
+OP( 0x03, i_add_r16w ) { DEF_r16w; ADDW; RegWord(ModRM)=dst; CLKM(1,2); }
+OP( 0x04, i_add_ald8 ) { DEF_ald8; ADDB; cpustate->regs.b[AL]=dst; CLK(1); }
+OP( 0x05, i_add_axd16) { DEF_axd16; ADDW; cpustate->regs.w[AW]=dst; CLK(1); }
+OP( 0x06, i_push_es ) { PUSH(cpustate->sregs[ES]); CLK(2); }
+OP( 0x07, i_pop_es ) { POP(cpustate->sregs[ES]); CLK(3); }
+
+OP( 0x08, i_or_br8 ) { DEF_br8; ORB; PutbackRMByte(ModRM,dst); CLKM(1,3); }
+OP( 0x09, i_or_wr16 ) { DEF_wr16; ORW; PutbackRMWord(ModRM,dst); CLKM(1,3);}
+OP( 0x0a, i_or_r8b ) { DEF_r8b; ORB; RegByte(ModRM)=dst; CLKM(1,2); }
+OP( 0x0b, i_or_r16w ) { DEF_r16w; ORW; RegWord(ModRM)=dst; CLKM(1,2); }
+OP( 0x0c, i_or_ald8 ) { DEF_ald8; ORB; cpustate->regs.b[AL]=dst; CLK(1); }
+OP( 0x0d, i_or_axd16 ) { DEF_axd16; ORW; cpustate->regs.w[AW]=dst; CLK(1); }
+OP( 0x0e, i_push_cs ) { PUSH(cpustate->sregs[CS]); CLK(2); }
+OP( 0x0f, i_pre_nec ) { UINT32 ModRM, tmp, tmp2;
+ switch (FETCH) {
+ case 0x10 : BITOP_BYTE; tmp2 = cpustate->regs.b[CL] & 0x7; cpustate->ZeroVal = (tmp & (1<<tmp2)) ? 1 : 0; cpustate->CarryVal=cpustate->OverVal=0; break; /* Test */
+ case 0x11 : BITOP_WORD; tmp2 = cpustate->regs.b[CL] & 0xf; cpustate->ZeroVal = (tmp & (1<<tmp2)) ? 1 : 0; cpustate->CarryVal=cpustate->OverVal=0; break; /* Test */
+ case 0x12 : BITOP_BYTE; tmp2 = cpustate->regs.b[CL] & 0x7; tmp &= ~(1<<tmp2); PutbackRMByte(ModRM,tmp); break; /* Clr */
+ case 0x13 : BITOP_WORD; tmp2 = cpustate->regs.b[CL] & 0xf; tmp &= ~(1<<tmp2); PutbackRMWord(ModRM,tmp); break; /* Clr */
+ case 0x14 : BITOP_BYTE; tmp2 = cpustate->regs.b[CL] & 0x7; tmp |= (1<<tmp2); PutbackRMByte(ModRM,tmp); break; /* Set */
+ case 0x15 : BITOP_WORD; tmp2 = cpustate->regs.b[CL] & 0xf; tmp |= (1<<tmp2); PutbackRMWord(ModRM,tmp); break; /* Set */
+ case 0x16 : BITOP_BYTE; tmp2 = cpustate->regs.b[CL] & 0x7; BIT_NOT; PutbackRMByte(ModRM,tmp); break; /* Not */
+ case 0x17 : BITOP_WORD; tmp2 = cpustate->regs.b[CL] & 0xf; BIT_NOT; PutbackRMWord(ModRM,tmp); break; /* Not */
+
+ case 0x18 : BITOP_BYTE; tmp2 = (FETCH) & 0x7; cpustate->ZeroVal = (tmp & (1<<tmp2)) ? 1 : 0; cpustate->CarryVal=cpustate->OverVal=0; break; /* Test */
+ case 0x19 : BITOP_WORD; tmp2 = (FETCH) & 0xf; cpustate->ZeroVal = (tmp & (1<<tmp2)) ? 1 : 0; cpustate->CarryVal=cpustate->OverVal=0; break; /* Test */
+ case 0x1a : BITOP_BYTE; tmp2 = (FETCH) & 0x7; tmp &= ~(1<<tmp2); PutbackRMByte(ModRM,tmp); break; /* Clr */
+ case 0x1b : BITOP_WORD; tmp2 = (FETCH) & 0xf; tmp &= ~(1<<tmp2); PutbackRMWord(ModRM,tmp); break; /* Clr */
+ case 0x1c : BITOP_BYTE; tmp2 = (FETCH) & 0x7; tmp |= (1<<tmp2); PutbackRMByte(ModRM,tmp); break; /* Set */
+ case 0x1d : BITOP_WORD; tmp2 = (FETCH) & 0xf; tmp |= (1<<tmp2); PutbackRMWord(ModRM,tmp); break; /* Set */
+ case 0x1e : BITOP_BYTE; tmp2 = (FETCH) & 0x7; BIT_NOT; PutbackRMByte(ModRM,tmp); break; /* Not */
+ case 0x1f : BITOP_WORD; tmp2 = (FETCH) & 0xf; BIT_NOT; PutbackRMWord(ModRM,tmp); break; /* Not */
+
+ case 0x20 : ADD4S; break;
+ case 0x22 : SUB4S; break;
+ case 0x26 : CMP4S; break;
+ case 0x28 : ModRM = FETCH; tmp = GetRMByte(ModRM); tmp <<= 4; tmp |= cpustate->regs.b[AL] & 0xf; cpustate->regs.b[AL] = (cpustate->regs.b[AL] & 0xf0) | ((tmp>>8)&0xf); tmp &= 0xff; PutbackRMByte(ModRM,tmp); CLKM(9,15); break;
+ case 0x2a : ModRM = FETCH; tmp = GetRMByte(ModRM); tmp2 = (cpustate->regs.b[AL] & 0xf)<<4; cpustate->regs.b[AL] = (cpustate->regs.b[AL] & 0xf0) | (tmp&0xf); tmp = tmp2 | (tmp>>4); PutbackRMByte(ModRM,tmp); CLKM(13,19); break;
+ case 0x31 : ModRM = FETCH; ModRM=0; logerror("%06x: Unimplemented bitfield INS\n",PC(cpustate)); break;
+ case 0x33 : ModRM = FETCH; ModRM=0; logerror("%06x: Unimplemented bitfield EXT\n",PC(cpustate)); break;
+ case 0x92 : CLK(2); break; /* V25/35 FINT */
+ case 0xe0 : ModRM = FETCH; ModRM=0; logerror("%06x: V33 unimplemented BRKXA (break to expansion address)\n",PC(cpustate)); break;
+ case 0xf0 : ModRM = FETCH; ModRM=0; logerror("%06x: V33 unimplemented RETXA (return from expansion address)\n",PC(cpustate)); break;
+ case 0xff : ModRM = FETCH; ModRM=0; logerror("%06x: unimplemented BRKEM (break to 8080 emulation mode)\n",PC(cpustate)); break;
+ default: logerror("%06x: Unknown V20 instruction\n",PC(cpustate)); break;
+ }
+}
+
+OP( 0x10, i_adc_br8 ) { DEF_br8; src+=CF; ADDB; PutbackRMByte(ModRM,dst); CLKM(1,3); }
+OP( 0x11, i_adc_wr16 ) { DEF_wr16; src+=CF; ADDW; PutbackRMWord(ModRM,dst); CLKM(1,3);}
+OP( 0x12, i_adc_r8b ) { DEF_r8b; src+=CF; ADDB; RegByte(ModRM)=dst; CLKM(1,2); }
+OP( 0x13, i_adc_r16w ) { DEF_r16w; src+=CF; ADDW; RegWord(ModRM)=dst; CLKM(1,2); }
+OP( 0x14, i_adc_ald8 ) { DEF_ald8; src+=CF; ADDB; cpustate->regs.b[AL]=dst; CLK(1); }
+OP( 0x15, i_adc_axd16) { DEF_axd16; src+=CF; ADDW; cpustate->regs.w[AW]=dst; CLK(1); }
+OP( 0x16, i_push_ss ) { PUSH(cpustate->sregs[SS]); CLK(2); }
+OP( 0x17, i_pop_ss ) { POP(cpustate->sregs[SS]); CLK(3); cpustate->no_interrupt=1; }
+
+OP( 0x18, i_sbb_br8 ) { DEF_br8; src+=CF; SUBB; PutbackRMByte(ModRM,dst); CLKM(1,3); }
+OP( 0x19, i_sbb_wr16 ) { DEF_wr16; src+=CF; SUBW; PutbackRMWord(ModRM,dst); CLKM(1,3);}
+OP( 0x1a, i_sbb_r8b ) { DEF_r8b; src+=CF; SUBB; RegByte(ModRM)=dst; CLKM(1,2); }
+OP( 0x1b, i_sbb_r16w ) { DEF_r16w; src+=CF; SUBW; RegWord(ModRM)=dst; CLKM(1,2); }
+OP( 0x1c, i_sbb_ald8 ) { DEF_ald8; src+=CF; SUBB; cpustate->regs.b[AL]=dst; CLK(1); }
+OP( 0x1d, i_sbb_axd16) { DEF_axd16; src+=CF; SUBW; cpustate->regs.w[AW]=dst; CLK(1); }
+OP( 0x1e, i_push_ds ) { PUSH(cpustate->sregs[DS]); CLK(2); }
+OP( 0x1f, i_pop_ds ) { POP(cpustate->sregs[DS]); CLK(3); }
+
+OP( 0x20, i_and_br8 ) { DEF_br8; ANDB; PutbackRMByte(ModRM,dst); CLKM(1,3); }
+OP( 0x21, i_and_wr16 ) { DEF_wr16; ANDW; PutbackRMWord(ModRM,dst); CLKM(1,3);}
+OP( 0x22, i_and_r8b ) { DEF_r8b; ANDB; RegByte(ModRM)=dst; CLKM(1,2); }
+OP( 0x23, i_and_r16w ) { DEF_r16w; ANDW; RegWord(ModRM)=dst; CLKM(1,2); }
+OP( 0x24, i_and_ald8 ) { DEF_ald8; ANDB; cpustate->regs.b[AL]=dst; CLK(1); }
+OP( 0x25, i_and_axd16) { DEF_axd16; ANDW; cpustate->regs.w[AW]=dst; CLK(1); }
+OP( 0x26, i_es ) { cpustate->seg_prefix=TRUE; cpustate->prefix_base=cpustate->sregs[ES]<<4; CLK(1); nec_instruction[FETCHOP](cpustate); cpustate->seg_prefix=FALSE; }
+OP( 0x27, i_daa ) { ADJ4(6,0x60); CLK(10); }
+
+OP( 0x28, i_sub_br8 ) { DEF_br8; SUBB; PutbackRMByte(ModRM,dst); CLKM(1,3); }
+OP( 0x29, i_sub_wr16 ) { DEF_wr16; SUBW; PutbackRMWord(ModRM,dst); CLKM(1,3);}
+OP( 0x2a, i_sub_r8b ) { DEF_r8b; SUBB; RegByte(ModRM)=dst; CLKM(1,2); }
+OP( 0x2b, i_sub_r16w ) { DEF_r16w; SUBW; RegWord(ModRM)=dst; CLKM(1,2); }
+OP( 0x2c, i_sub_ald8 ) { DEF_ald8; SUBB; cpustate->regs.b[AL]=dst; CLK(1); }
+OP( 0x2d, i_sub_axd16) { DEF_axd16; SUBW; cpustate->regs.w[AW]=dst; CLK(1); }
+OP( 0x2e, i_cs ) { cpustate->seg_prefix=TRUE; cpustate->prefix_base=cpustate->sregs[CS]<<4; CLK(1); nec_instruction[FETCHOP](cpustate); cpustate->seg_prefix=FALSE; }
+OP( 0x2f, i_das ) { ADJ4(-6,-0x60); CLK(10); }
+
+OP( 0x30, i_xor_br8 ) { DEF_br8; XORB; PutbackRMByte(ModRM,dst); CLKM(1,3); }
+OP( 0x31, i_xor_wr16 ) { DEF_wr16; XORW; PutbackRMWord(ModRM,dst); CLKM(1,3);}
+OP( 0x32, i_xor_r8b ) { DEF_r8b; XORB; RegByte(ModRM)=dst; CLKM(1,2); }
+OP( 0x33, i_xor_r16w ) { DEF_r16w; XORW; RegWord(ModRM)=dst; CLKM(1,2); }
+OP( 0x34, i_xor_ald8 ) { DEF_ald8; XORB; cpustate->regs.b[AL]=dst; CLK(1); }
+OP( 0x35, i_xor_axd16) { DEF_axd16; XORW; cpustate->regs.w[AW]=dst; CLK(1); }
+OP( 0x36, i_ss ) { cpustate->seg_prefix=TRUE; cpustate->prefix_base=cpustate->sregs[SS]<<4; CLK(1); nec_instruction[FETCHOP](cpustate); cpustate->seg_prefix=FALSE; }
+OP( 0x37, i_aaa ) { ADJB(6, (cpustate->regs.b[AL] > 0xf9) ? 2 : 1); CLK(9); }
+
+OP( 0x38, i_cmp_br8 ) { DEF_br8; SUBB; CLKM(1,2); }
+OP( 0x39, i_cmp_wr16 ) { DEF_wr16; SUBW; CLKM(1,2);}
+OP( 0x3a, i_cmp_r8b ) { DEF_r8b; SUBB; CLKM(1,2); }
+OP( 0x3b, i_cmp_r16w ) { DEF_r16w; SUBW; CLKM(1,2); }
+OP( 0x3c, i_cmp_ald8 ) { DEF_ald8; SUBB; CLK(1); }
+OP( 0x3d, i_cmp_axd16) { DEF_axd16; SUBW; CLK(1); }
+OP( 0x3e, i_ds ) { cpustate->seg_prefix=TRUE; cpustate->prefix_base=cpustate->sregs[DS]<<4; CLK(1); nec_instruction[FETCHOP](cpustate); cpustate->seg_prefix=FALSE; }
+OP( 0x3f, i_aas ) { ADJB(-6, (cpustate->regs.b[AL] < 6) ? -2 : -1); CLK(9); }
+
+OP( 0x40, i_inc_ax ) { IncWordReg(AW); CLK(1); }
+OP( 0x41, i_inc_cx ) { IncWordReg(CW); CLK(1); }
+OP( 0x42, i_inc_dx ) { IncWordReg(DW); CLK(1); }
+OP( 0x43, i_inc_bx ) { IncWordReg(BW); CLK(1); }
+OP( 0x44, i_inc_sp ) { IncWordReg(SP); CLK(1); }
+OP( 0x45, i_inc_bp ) { IncWordReg(BP); CLK(1); }
+OP( 0x46, i_inc_si ) { IncWordReg(IX); CLK(1); }
+OP( 0x47, i_inc_di ) { IncWordReg(IY); CLK(1); }
+
+OP( 0x48, i_dec_ax ) { DecWordReg(AW); CLK(1); }
+OP( 0x49, i_dec_cx ) { DecWordReg(CW); CLK(1); }
+OP( 0x4a, i_dec_dx ) { DecWordReg(DW); CLK(1); }
+OP( 0x4b, i_dec_bx ) { DecWordReg(BW); CLK(1); }
+OP( 0x4c, i_dec_sp ) { DecWordReg(SP); CLK(1); }
+OP( 0x4d, i_dec_bp ) { DecWordReg(BP); CLK(1); }
+OP( 0x4e, i_dec_si ) { DecWordReg(IX); CLK(1); }
+OP( 0x4f, i_dec_di ) { DecWordReg(IY); CLK(1); }
+
+OP( 0x50, i_push_ax ) { PUSH(cpustate->regs.w[AW]); CLK(1); }
+OP( 0x51, i_push_cx ) { PUSH(cpustate->regs.w[CW]); CLK(1); }
+OP( 0x52, i_push_dx ) { PUSH(cpustate->regs.w[DW]); CLK(1); }
+OP( 0x53, i_push_bx ) { PUSH(cpustate->regs.w[BW]); CLK(1); }
+OP( 0x54, i_push_sp ) { PUSH(cpustate->regs.w[SP]); CLK(1); }
+OP( 0x55, i_push_bp ) { PUSH(cpustate->regs.w[BP]); CLK(1); }
+OP( 0x56, i_push_si ) { PUSH(cpustate->regs.w[IX]); CLK(1); }
+OP( 0x57, i_push_di ) { PUSH(cpustate->regs.w[IY]); CLK(1); }
+
+OP( 0x58, i_pop_ax ) { POP(cpustate->regs.w[AW]); CLK(1); }
+OP( 0x59, i_pop_cx ) { POP(cpustate->regs.w[CW]); CLK(1); }
+OP( 0x5a, i_pop_dx ) { POP(cpustate->regs.w[DW]); CLK(1); }
+OP( 0x5b, i_pop_bx ) { POP(cpustate->regs.w[BW]); CLK(1); }
+OP( 0x5c, i_pop_sp ) { POP(cpustate->regs.w[SP]); CLK(1); }
+OP( 0x5d, i_pop_bp ) { POP(cpustate->regs.w[BP]); CLK(1); }
+OP( 0x5e, i_pop_si ) { POP(cpustate->regs.w[IX]); CLK(1); }
+OP( 0x5f, i_pop_di ) { POP(cpustate->regs.w[IY]); CLK(1); }
+
+OP( 0x60, i_pusha ) {
+ unsigned tmp=cpustate->regs.w[SP];
+ PUSH(cpustate->regs.w[AW]);
+ PUSH(cpustate->regs.w[CW]);
+ PUSH(cpustate->regs.w[DW]);
+ PUSH(cpustate->regs.w[BW]);
+ PUSH(tmp);
+ PUSH(cpustate->regs.w[BP]);
+ PUSH(cpustate->regs.w[IX]);
+ PUSH(cpustate->regs.w[IY]);
+ CLK(9);
+}
+static unsigned nec_v30mz_popa_tmp;
+OP( 0x61, i_popa ) {
+ POP(cpustate->regs.w[IY]);
+ POP(cpustate->regs.w[IX]);
+ POP(cpustate->regs.w[BP]);
+ POP(nec_v30mz_popa_tmp);
+ POP(cpustate->regs.w[BW]);
+ POP(cpustate->regs.w[DW]);
+ POP(cpustate->regs.w[CW]);
+ POP(cpustate->regs.w[AW]);
+ CLK(8);
+}
+OP( 0x62, i_chkind ) {
+ UINT32 low,high,tmp;
+ GetModRM;
+ low = GetRMWord(ModRM);
+ high= GetnextRMWord;
+ tmp= RegWord(ModRM);
+ if (tmp<low || tmp>high) {
+ nec_interrupt(cpustate,5,0);
+ CLK(20);
+ } else {
+ CLK(13);
+ }
+ logerror("%06x: bound %04x high %04x low %04x tmp\n",PC(cpustate),high,low,tmp);
+}
+OP( 0x64, i_repnc ) { UINT32 next = FETCHOP; UINT16 c = cpustate->regs.w[CW];
+ switch(next) { /* Segments */
+ case 0x26: cpustate->seg_prefix=TRUE; cpustate->prefix_base=cpustate->sregs[ES]<<4; next = FETCHOP; CLK(2); break;
+ case 0x2e: cpustate->seg_prefix=TRUE; cpustate->prefix_base=cpustate->sregs[CS]<<4; next = FETCHOP; CLK(2); break;
+ case 0x36: cpustate->seg_prefix=TRUE; cpustate->prefix_base=cpustate->sregs[SS]<<4; next = FETCHOP; CLK(2); break;
+ case 0x3e: cpustate->seg_prefix=TRUE; cpustate->prefix_base=cpustate->sregs[DS]<<4; next = FETCHOP; CLK(2); break;
+ }
+
+ switch(next) {
+ case 0x6c: CLK(2); if (c) do { i_insb(cpustate); c--; } while (c>0 && !CF); cpustate->regs.w[CW]=c; break;
+ case 0x6d: CLK(2); if (c) do { i_insw(cpustate); c--; } while (c>0 && !CF); cpustate->regs.w[CW]=c; break;
+ case 0x6e: CLK(2); if (c) do { i_outsb(cpustate); c--; } while (c>0 && !CF); cpustate->regs.w[CW]=c; break;
+ case 0x6f: CLK(2); if (c) do { i_outsw(cpustate); c--; } while (c>0 && !CF); cpustate->regs.w[CW]=c; break;
+ case 0xa4: CLK(2); if (c) do { i_movsb(cpustate); c--; } while (c>0 && !CF); cpustate->regs.w[CW]=c; break;
+ case 0xa5: CLK(2); if (c) do { i_movsw(cpustate); c--; } while (c>0 && !CF); cpustate->regs.w[CW]=c; break;
+ case 0xa6: CLK(2); if (c) do { i_cmpsb(cpustate); c--; } while (c>0 && !CF); cpustate->regs.w[CW]=c; break;
+ case 0xa7: CLK(2); if (c) do { i_cmpsw(cpustate); c--; } while (c>0 && !CF); cpustate->regs.w[CW]=c; break;
+ case 0xaa: CLK(2); if (c) do { i_stosb(cpustate); c--; } while (c>0 && !CF); cpustate->regs.w[CW]=c; break;
+ case 0xab: CLK(2); if (c) do { i_stosw(cpustate); c--; } while (c>0 && !CF); cpustate->regs.w[CW]=c; break;
+ case 0xac: CLK(2); if (c) do { i_lodsb(cpustate); c--; } while (c>0 && !CF); cpustate->regs.w[CW]=c; break;
+ case 0xad: CLK(2); if (c) do { i_lodsw(cpustate); c--; } while (c>0 && !CF); cpustate->regs.w[CW]=c; break;
+ case 0xae: CLK(2); if (c) do { i_scasb(cpustate); c--; } while (c>0 && !CF); cpustate->regs.w[CW]=c; break;
+ case 0xaf: CLK(2); if (c) do { i_scasw(cpustate); c--; } while (c>0 && !CF); cpustate->regs.w[CW]=c; break;
+ default: logerror("%06x: REPNC invalid\n",PC(cpustate)); nec_instruction[next](cpustate);
+ }
+ cpustate->seg_prefix=FALSE;
+}
+
+OP( 0x65, i_repc ) { UINT32 next = FETCHOP; UINT16 c = cpustate->regs.w[CW];
+ switch(next) { /* Segments */
+ case 0x26: cpustate->seg_prefix=TRUE; cpustate->prefix_base=cpustate->sregs[ES]<<4; next = FETCHOP; CLK(2); break;
+ case 0x2e: cpustate->seg_prefix=TRUE; cpustate->prefix_base=cpustate->sregs[CS]<<4; next = FETCHOP; CLK(2); break;
+ case 0x36: cpustate->seg_prefix=TRUE; cpustate->prefix_base=cpustate->sregs[SS]<<4; next = FETCHOP; CLK(2); break;
+ case 0x3e: cpustate->seg_prefix=TRUE; cpustate->prefix_base=cpustate->sregs[DS]<<4; next = FETCHOP; CLK(2); break;
+ }
+
+ switch(next) {
+ case 0x6c: CLK(2); if (c) do { i_insb(cpustate); c--; } while (c>0 && CF); cpustate->regs.w[CW]=c; break;
+ case 0x6d: CLK(2); if (c) do { i_insw(cpustate); c--; } while (c>0 && CF); cpustate->regs.w[CW]=c; break;
+ case 0x6e: CLK(2); if (c) do { i_outsb(cpustate); c--; } while (c>0 && CF); cpustate->regs.w[CW]=c; break;
+ case 0x6f: CLK(2); if (c) do { i_outsw(cpustate); c--; } while (c>0 && CF); cpustate->regs.w[CW]=c; break;
+ case 0xa4: CLK(2); if (c) do { i_movsb(cpustate); c--; } while (c>0 && CF); cpustate->regs.w[CW]=c; break;
+ case 0xa5: CLK(2); if (c) do { i_movsw(cpustate); c--; } while (c>0 && CF); cpustate->regs.w[CW]=c; break;
+ case 0xa6: CLK(2); if (c) do { i_cmpsb(cpustate); c--; } while (c>0 && CF); cpustate->regs.w[CW]=c; break;
+ case 0xa7: CLK(2); if (c) do { i_cmpsw(cpustate); c--; } while (c>0 && CF); cpustate->regs.w[CW]=c; break;
+ case 0xaa: CLK(2); if (c) do { i_stosb(cpustate); c--; } while (c>0 && CF); cpustate->regs.w[CW]=c; break;
+ case 0xab: CLK(2); if (c) do { i_stosw(cpustate); c--; } while (c>0 && CF); cpustate->regs.w[CW]=c; break;
+ case 0xac: CLK(2); if (c) do { i_lodsb(cpustate); c--; } while (c>0 && CF); cpustate->regs.w[CW]=c; break;
+ case 0xad: CLK(2); if (c) do { i_lodsw(cpustate); c--; } while (c>0 && CF); cpustate->regs.w[CW]=c; break;
+ case 0xae: CLK(2); if (c) do { i_scasb(cpustate); c--; } while (c>0 && CF); cpustate->regs.w[CW]=c; break;
+ case 0xaf: CLK(2); if (c) do { i_scasw(cpustate); c--; } while (c>0 && CF); cpustate->regs.w[CW]=c; break;
+ default: logerror("%06x: REPC invalid\n",PC(cpustate)); nec_instruction[next](cpustate);
+ }
+ cpustate->seg_prefix=FALSE;
+}
+
+OP( 0x68, i_push_d16 ) { UINT32 tmp; FETCHWORD(tmp); PUSH(tmp); CLK(1); }
+OP( 0x69, i_imul_d16 ) { UINT32 tmp; DEF_r16w; FETCHWORD(tmp); dst = (INT32)((INT16)src)*(INT32)((INT16)tmp); cpustate->CarryVal = cpustate->OverVal = (((INT32)dst) >> 15 != 0) && (((INT32)dst) >> 15 != -1); RegWord(ModRM)=(WORD)dst; if (ModRM >= 0xc0) CLK(3) else CLK(4) }
+OP( 0x6a, i_push_d8 ) { UINT32 tmp = (WORD)((INT16)((INT8)FETCH)); PUSH(tmp); CLK(1); }
+OP( 0x6b, i_imul_d8 ) { UINT32 src2; DEF_r16w; src2= (WORD)((INT16)((INT8)FETCH)); dst = (INT32)((INT16)src)*(INT32)((INT16)src2); cpustate->CarryVal = cpustate->OverVal = (((INT32)dst) >> 15 != 0) && (((INT32)dst) >> 15 != -1); RegWord(ModRM)=(WORD)dst; if (ModRM >= 0xc0) CLK(3) else CLK(4) }
+OP( 0x6c, i_insb ) { PutMemB(ES,cpustate->regs.w[IY],read_port(cpustate->regs.w[DW])); cpustate->regs.w[IY]+= -2 * cpustate->DF + 1; CLK(6); }
+OP( 0x6d, i_insw ) { PutMemB(ES,cpustate->regs.w[IY],read_port(cpustate->regs.w[DW])); PutMemB(ES,(cpustate->regs.w[IY]+1)&0xffff,read_port((cpustate->regs.w[DW]+1)&0xffff)); cpustate->regs.w[IY]+= -4 * cpustate->DF + 2; CLK(6); }
+OP( 0x6e, i_outsb ) { write_port(cpustate->regs.w[DW],GetMemB(DS,cpustate->regs.w[IX])); cpustate->regs.w[IX]+= -2 * cpustate->DF + 1; CLK(7); }
+OP( 0x6f, i_outsw ) { write_port(cpustate->regs.w[DW],GetMemB(DS,cpustate->regs.w[IX])); write_port((cpustate->regs.w[DW]+1)&0xffff,GetMemB(DS,(cpustate->regs.w[IX]+1)&0xffff)); cpustate->regs.w[IX]+= -4 * cpustate->DF + 2; CLK(7); }
+
+OP( 0x70, i_jo ) { JMP( OF); if ( OF) CLK(4) else CLK(1) }
+OP( 0x71, i_jno ) { JMP(!OF); if (!OF) CLK(4) else CLK(1) }
+OP( 0x72, i_jc ) { JMP( CF); if ( CF) CLK(4) else CLK(1) }
+OP( 0x73, i_jnc ) { JMP(!CF); if (!CF) CLK(4) else CLK(1) }
+OP( 0x74, i_jz ) { JMP( ZF); if ( ZF) CLK(4) else CLK(1) }
+OP( 0x75, i_jnz ) { JMP(!ZF); if (!ZF) CLK(4) else CLK(1) }
+OP( 0x76, i_jce ) { JMP(CF || ZF); if (CF || ZF) CLK(4) else CLK(1) }
+OP( 0x77, i_jnce ) { JMP(!(CF || ZF)); if (!(CF || ZF)) CLK(4) else CLK(1) }
+OP( 0x78, i_js ) { JMP( SF); if ( SF) CLK(4) else CLK(1) }
+OP( 0x79, i_jns ) { JMP(!SF); if (!SF) CLK(4) else CLK(1) }
+OP( 0x7a, i_jp ) { JMP( PF); if ( PF) CLK(4) else CLK(1) }
+OP( 0x7b, i_jnp ) { JMP(!PF); if (!PF) CLK(4) else CLK(1) }
+OP( 0x7c, i_jl ) { JMP((SF!=OF)&&(!ZF)); if ((SF!=OF)&&(!ZF)) CLK(4) else CLK(1) }
+OP( 0x7d, i_jnl ) { JMP((ZF)||(SF==OF)); if ((ZF)||(SF==OF)) CLK(4) else CLK(1) }
+OP( 0x7e, i_jle ) { JMP((ZF)||(SF!=OF)); if ((ZF)||(SF!=OF)) CLK(4) else CLK(1) }
+OP( 0x7f, i_jnle ) { JMP((SF==OF)&&(!ZF)); if ((SF==OF)&&(!ZF)) CLK(4) else CLK(1) }
+
+OP( 0x80, i_80pre ) { UINT32 dst, src; GetModRM; dst = GetRMByte(ModRM); src = FETCH;
+ if (ModRM >=0xc0 ) CLK(1) else if ((ModRM & 0x38)==0x38) CLK(2) else CLK(3)
+ 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 ) CLK(1) else if ((ModRM & 0x38)==0x38) CLK(2) else CLK(3)
+ 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 ) CLK(1) else if ((ModRM & 0x38)==0x38) CLK(2) else CLK(3)
+ 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 ) CLK(1) else if ((ModRM & 0x38)==0x38) CLK(2) else CLK(3)
+ 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(1,2); }
+OP( 0x85, i_test_wr16 ) { DEF_wr16; ANDW; CLKM(1,2); }
+OP( 0x86, i_xchg_br8 ) { DEF_br8; RegByte(ModRM)=dst; PutbackRMByte(ModRM,src); CLKM(3,5); }
+OP( 0x87, i_xchg_wr16 ) { DEF_wr16; RegWord(ModRM)=dst; PutbackRMWord(ModRM,src); CLKM(3,5); }
+
+OP( 0x88, i_mov_br8 ) { UINT8 src; GetModRM; src = RegByte(ModRM); PutRMByte(ModRM,src); CLK(1); }
+OP( 0x89, i_mov_wr16 ) { UINT16 src; GetModRM; src = RegWord(ModRM); PutRMWord(ModRM,src); CLK(1); }
+OP( 0x8a, i_mov_r8b ) { UINT8 src; GetModRM; src = GetRMByte(ModRM); RegByte(ModRM)=src; CLK(1); }
+OP( 0x8b, i_mov_r16w ) { UINT16 src; GetModRM; src = GetRMWord(ModRM); RegWord(ModRM)=src; CLK(1); }
+OP( 0x8c, i_mov_wsreg ) { GetModRM; PutRMWord(ModRM,cpustate->sregs[(ModRM & 0x38) >> 3]); CLKM(1,3); }
+OP( 0x8d, i_lea ) { UINT16 ModRM = FETCH; (void)(*GetEA[ModRM])(cpustate); RegWord(ModRM)=cpustate->eo; CLK(1); }
+OP( 0x8e, i_mov_sregw ) { UINT16 src; GetModRM; src = GetRMWord(ModRM); CLKM(2,3);
+ switch (ModRM & 0x38) {
+ case 0x00: cpustate->sregs[ES] = src; break; /* mov es,ew */
+ case 0x08: cpustate->sregs[CS] = src; break; /* mov cs,ew */
+ case 0x10: cpustate->sregs[SS] = src; break; /* mov ss,ew */
+ case 0x18: cpustate->sregs[DS] = src; break; /* mov ds,ew */
+ default: logerror("%06x: Mov Sreg - Invalid register\n",PC(cpustate));
+ }
+ cpustate->no_interrupt=1;
+}
+OP( 0x8f, i_popw ) { UINT16 tmp; GetModRM; POP(tmp); PutRMWord(ModRM,tmp); CLKM(1,3); }
+OP( 0x90, i_nop ) { CLK(1);
+ /* Cycle skip for idle loops (0: NOP 1: JMP 0) */
+ if (cpustate->no_interrupt==0 && cpustate->icount>0 && (cpustate->pending_irq==0) && (PEEKOP((cpustate->sregs[CS]<<4)+cpustate->ip))==0xeb && (PEEK((cpustate->sregs[CS]<<4)+cpustate->ip+1))==0xfd)
+ cpustate->icount%=15;
+}
+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 ) { cpustate->regs.b[AH] = (cpustate->regs.b[AL] & 0x80) ? 0xff : 0; CLK(1); }
+OP( 0x99, i_cwd ) { cpustate->regs.w[DW] = (cpustate->regs.b[AH] & 0x80) ? 0xffff : 0; CLK(1); }
+OP( 0x9a, i_call_far ) { UINT32 tmp, tmp2; FETCHWORD(tmp); FETCHWORD(tmp2); PUSH(cpustate->sregs[CS]); PUSH(cpustate->ip); cpustate->ip = (WORD)tmp; cpustate->sregs[CS] = (WORD)tmp2; CLK(10); }
+OP( 0x9b, i_wait ) { logerror("%06x: Hardware POLL\n",PC(cpustate)); }
+OP( 0x9c, i_pushf ) { PUSH( CompressFlags() ); CLK(2); }
+OP( 0x9d, i_popf ) { UINT32 tmp; POP(tmp); ExpandFlags(tmp); CLK(3); if (cpustate->TF) nec_trap(cpustate); }
+OP( 0x9e, i_sahf ) { UINT32 tmp = (CompressFlags() & 0xff00) | (cpustate->regs.b[AH] & 0xd5); ExpandFlags(tmp); CLK(4); }
+OP( 0x9f, i_lahf ) { cpustate->regs.b[AH] = CompressFlags() & 0xff; CLK(2); }
+
+OP( 0xa0, i_mov_aldisp ) { UINT32 addr; FETCHWORD(addr); cpustate->regs.b[AL] = GetMemB(DS, addr); CLK(1); }
+OP( 0xa1, i_mov_axdisp ) { UINT32 addr; FETCHWORD(addr); cpustate->regs.b[AL] = GetMemB(DS, addr); cpustate->regs.b[AH] = GetMemB(DS, (addr+1)&0xffff); CLK(1); }
+OP( 0xa2, i_mov_dispal ) { UINT32 addr; FETCHWORD(addr); PutMemB(DS, addr, cpustate->regs.b[AL]); CLK(1); }
+OP( 0xa3, i_mov_dispax ) { UINT32 addr; FETCHWORD(addr); PutMemB(DS, addr, cpustate->regs.b[AL]); PutMemB(DS, (addr+1)&0xffff, cpustate->regs.b[AH]); CLK(1); }
+OP( 0xa4, i_movsb ) { UINT32 tmp = GetMemB(DS,cpustate->regs.w[IX]); PutMemB(ES,cpustate->regs.w[IY], tmp); cpustate->regs.w[IY] += -2 * cpustate->DF + 1; cpustate->regs.w[IX] += -2 * cpustate->DF + 1; CLK(5); }
+OP( 0xa5, i_movsw ) { UINT32 tmp = GetMemW(DS,cpustate->regs.w[IX]); PutMemW(ES,cpustate->regs.w[IY], tmp); cpustate->regs.w[IY] += -4 * cpustate->DF + 2; cpustate->regs.w[IX] += -4 * cpustate->DF + 2; CLK(5); }
+OP( 0xa6, i_cmpsb ) { UINT32 src = GetMemB(ES, cpustate->regs.w[IY]); UINT32 dst = GetMemB(DS, cpustate->regs.w[IX]); SUBB; cpustate->regs.w[IY] += -2 * cpustate->DF + 1; cpustate->regs.w[IX] += -2 * cpustate->DF + 1; CLK(6); }
+OP( 0xa7, i_cmpsw ) { UINT32 src = GetMemW(ES, cpustate->regs.w[IY]); UINT32 dst = GetMemW(DS, cpustate->regs.w[IX]); SUBW; cpustate->regs.w[IY] += -4 * cpustate->DF + 2; cpustate->regs.w[IX] += -4 * cpustate->DF + 2; CLK(6); }
+
+OP( 0xa8, i_test_ald8 ) { DEF_ald8; ANDB; CLK(1); }
+OP( 0xa9, i_test_axd16 ) { DEF_axd16; ANDW; CLK(1); }
+OP( 0xaa, i_stosb ) { PutMemB(ES,cpustate->regs.w[IY],cpustate->regs.b[AL]); cpustate->regs.w[IY] += -2 * cpustate->DF + 1; CLK(3); }
+OP( 0xab, i_stosw ) { PutMemW(ES,cpustate->regs.w[IY],cpustate->regs.w[AW]); cpustate->regs.w[IY] += -4 * cpustate->DF + 2; CLK(3); }
+OP( 0xac, i_lodsb ) { cpustate->regs.b[AL] = GetMemB(DS,cpustate->regs.w[IX]); cpustate->regs.w[IX] += -2 * cpustate->DF + 1; CLK(3); }
+OP( 0xad, i_lodsw ) { cpustate->regs.w[AW] = GetMemW(DS,cpustate->regs.w[IX]); cpustate->regs.w[IX] += -4 * cpustate->DF + 2; CLK(3); }
+OP( 0xae, i_scasb ) { UINT32 src = GetMemB(ES, cpustate->regs.w[IY]); UINT32 dst = cpustate->regs.b[AL]; SUBB; cpustate->regs.w[IY] += -2 * cpustate->DF + 1; CLK(4); }
+OP( 0xaf, i_scasw ) { UINT32 src = GetMemW(ES, cpustate->regs.w[IY]); UINT32 dst = cpustate->regs.w[AW]; SUBW; cpustate->regs.w[IY] += -4 * cpustate->DF + 2; CLK(4); }
+
+OP( 0xb0, i_mov_ald8 ) { cpustate->regs.b[AL] = FETCH; CLK(1); }
+OP( 0xb1, i_mov_cld8 ) { cpustate->regs.b[CL] = FETCH; CLK(1); }
+OP( 0xb2, i_mov_dld8 ) { cpustate->regs.b[DL] = FETCH; CLK(1); }
+OP( 0xb3, i_mov_bld8 ) { cpustate->regs.b[BL] = FETCH; CLK(1); }
+OP( 0xb4, i_mov_ahd8 ) { cpustate->regs.b[AH] = FETCH; CLK(1); }
+OP( 0xb5, i_mov_chd8 ) { cpustate->regs.b[CH] = FETCH; CLK(1); }
+OP( 0xb6, i_mov_dhd8 ) { cpustate->regs.b[DH] = FETCH; CLK(1); }
+OP( 0xb7, i_mov_bhd8 ) { cpustate->regs.b[BH] = FETCH; CLK(1); }
+
+OP( 0xb8, i_mov_axd16 ) { cpustate->regs.b[AL] = FETCH; cpustate->regs.b[AH] = FETCH; CLK(1); }
+OP( 0xb9, i_mov_cxd16 ) { cpustate->regs.b[CL] = FETCH; cpustate->regs.b[CH] = FETCH; CLK(1); }
+OP( 0xba, i_mov_dxd16 ) { cpustate->regs.b[DL] = FETCH; cpustate->regs.b[DH] = FETCH; CLK(1); }
+OP( 0xbb, i_mov_bxd16 ) { cpustate->regs.b[BL] = FETCH; cpustate->regs.b[BH] = FETCH; CLK(1); }
+OP( 0xbc, i_mov_spd16 ) { cpustate->regs.b[SPL] = FETCH; cpustate->regs.b[SPH] = FETCH; CLK(1); }
+OP( 0xbd, i_mov_bpd16 ) { cpustate->regs.b[BPL] = FETCH; cpustate->regs.b[BPH] = FETCH; CLK(1); }
+OP( 0xbe, i_mov_sid16 ) { cpustate->regs.b[IXL] = FETCH; cpustate->regs.b[IXH] = FETCH; CLK(1); }
+OP( 0xbf, i_mov_did16 ) { cpustate->regs.b[IYL] = FETCH; cpustate->regs.b[IYH] = FETCH; CLK(1); }
+
+OP( 0xc0, i_rotshft_bd8 ) {
+ UINT32 src, dst; UINT8 c;
+ GetModRM; src = (unsigned)GetRMByte(ModRM); dst=src;
+ c=FETCH;
+ CLKM(3,5);
+ if (c) switch (ModRM & 0x38) {
+ case 0x00: do { ROL_BYTE; c--; } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break;
+ case 0x08: do { ROR_BYTE; c--; } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break;
+ case 0x10: do { ROLC_BYTE; c--; } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break;
+ case 0x18: do { RORC_BYTE; c--; } 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(cpustate)); 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(3,5);
+ if (c) switch (ModRM & 0x38) {
+ case 0x00: do { ROL_WORD; c--; } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break;
+ case 0x08: do { ROR_WORD; c--; } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break;
+ case 0x10: do { ROLC_WORD; c--; } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break;
+ case 0x18: do { RORC_WORD; c--; } 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(cpustate)); break;
+ case 0x38: SHRA_WORD(c); break;
+ }
+}
+
+OP( 0xc2, i_ret_d16 ) { UINT32 count = FETCH; count += FETCH << 8; POP(cpustate->ip); cpustate->regs.w[SP]+=count; CLK(6); }
+OP( 0xc3, i_ret ) { POP(cpustate->ip); CLK(6); }
+OP( 0xc4, i_les_dw ) { GetModRM; WORD tmp = GetRMWord(ModRM); RegWord(ModRM)=tmp; cpustate->sregs[ES] = GetnextRMWord; CLK(6); }
+OP( 0xc5, i_lds_dw ) { GetModRM; WORD tmp = GetRMWord(ModRM); RegWord(ModRM)=tmp; cpustate->sregs[DS] = GetnextRMWord; CLK(6); }
+OP( 0xc6, i_mov_bd8 ) { GetModRM; PutImmRMByte(ModRM); CLK(1); }
+OP( 0xc7, i_mov_wd16 ) { GetModRM; PutImmRMWord(ModRM); CLK(1); }
+
+OP( 0xc8, i_enter ) {
+ UINT32 nb = FETCH;
+ UINT32 i,level;
+
+ CLK(8);
+ nb += FETCH << 8;
+ level = FETCH;
+ PUSH(cpustate->regs.w[BP]);
+ cpustate->regs.w[BP]=cpustate->regs.w[SP];
+ cpustate->regs.w[SP] -= nb;
+ for (i=1;i<level;i++) {
+ PUSH(GetMemW(SS,cpustate->regs.w[BP]-i*2));
+ CLK(4);
+ }
+ if (level) { PUSH(cpustate->regs.w[BP]); if (level==1) CLK(2) else CLK(3) }
+}
+OP( 0xc9, i_leave ) {
+ cpustate->regs.w[SP]=cpustate->regs.w[BP];
+ POP(cpustate->regs.w[BP]);
+ CLK(2);
+}
+OP( 0xca, i_retf_d16 ) { UINT32 count = FETCH; count += FETCH << 8; POP(cpustate->ip); POP(cpustate->sregs[CS]); cpustate->regs.w[SP]+=count; CLK(9); }
+OP( 0xcb, i_retf ) { POP(cpustate->ip); POP(cpustate->sregs[CS]); CLK(8); }
+OP( 0xcc, i_int3 ) { nec_interrupt(cpustate,3,0); CLK(9); }
+OP( 0xcd, i_int ) { nec_interrupt(cpustate,FETCH,0); CLK(10); }
+OP( 0xce, i_into ) { if (OF) { nec_interrupt(cpustate,4,0); CLK(13); } else CLK(6); }
+OP( 0xcf, i_iret ) { POP(cpustate->ip); POP(cpustate->sregs[CS]); i_popf(cpustate); CLK(10); }
+
+OP( 0xd0, i_rotshft_b ) {
+ UINT32 src, dst; GetModRM; src = (UINT32)GetRMByte(ModRM); dst=src;
+ CLKM(1,3);
+ switch (ModRM & 0x38) {
+ case 0x00: ROL_BYTE; PutbackRMByte(ModRM,(BYTE)dst); cpustate->OverVal = (src^dst)&0x80; break;
+ case 0x08: ROR_BYTE; PutbackRMByte(ModRM,(BYTE)dst); cpustate->OverVal = (src^dst)&0x80; break;
+ case 0x10: ROLC_BYTE; PutbackRMByte(ModRM,(BYTE)dst); cpustate->OverVal = (src^dst)&0x80; break;
+ case 0x18: RORC_BYTE; PutbackRMByte(ModRM,(BYTE)dst); cpustate->OverVal = (src^dst)&0x80; break;
+ case 0x20: SHL_BYTE(1); cpustate->OverVal = (src^dst)&0x80; break;
+ case 0x28: SHR_BYTE(1); cpustate->OverVal = (src^dst)&0x80; break;
+ case 0x30: logerror("%06x: Undefined opcode 0xd0 0x30 (SHLA)\n",PC(cpustate)); break;
+ case 0x38: SHRA_BYTE(1); cpustate->OverVal = 0; break;
+ }
+}
+
+OP( 0xd1, i_rotshft_w ) {
+ UINT32 src, dst; GetModRM; src = (UINT32)GetRMWord(ModRM); dst=src;
+ CLKM(1,3);
+ switch (ModRM & 0x38) {
+ case 0x00: ROL_WORD; PutbackRMWord(ModRM,(WORD)dst); cpustate->OverVal = (src^dst)&0x8000; break;
+ case 0x08: ROR_WORD; PutbackRMWord(ModRM,(WORD)dst); cpustate->OverVal = (src^dst)&0x8000; break;
+ case 0x10: ROLC_WORD; PutbackRMWord(ModRM,(WORD)dst); cpustate->OverVal = (src^dst)&0x8000; break;
+ case 0x18: RORC_WORD; PutbackRMWord(ModRM,(WORD)dst); cpustate->OverVal = (src^dst)&0x8000; break;
+ case 0x20: SHL_WORD(1); cpustate->OverVal = (src^dst)&0x8000; break;
+ case 0x28: SHR_WORD(1); cpustate->OverVal = (src^dst)&0x8000; break;
+ case 0x30: logerror("%06x: Undefined opcode 0xd1 0x30 (SHLA)\n",PC(cpustate)); break;
+ case 0x38: SHRA_WORD(1); cpustate->OverVal = 0; break;
+ }
+}
+
+OP( 0xd2, i_rotshft_bcl ) {
+ UINT32 src, dst; UINT8 c; GetModRM; src = (UINT32)GetRMByte(ModRM); dst=src;
+ c=cpustate->regs.b[CL];
+ CLKM(3,5);
+ if (c) switch (ModRM & 0x38) {
+ case 0x00: do { ROL_BYTE; c--; } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break;
+ case 0x08: do { ROR_BYTE; c--; } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break;
+ case 0x10: do { ROLC_BYTE; c--; } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break;
+ case 0x18: do { RORC_BYTE; c--; } 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(cpustate)); 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=cpustate->regs.b[CL];
+ CLKM(3,5);
+ if (c) switch (ModRM & 0x38) {
+ case 0x00: do { ROL_WORD; c--; } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break;
+ case 0x08: do { ROR_WORD; c--; } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break;
+ case 0x10: do { ROLC_WORD; c--; } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break;
+ case 0x18: do { RORC_WORD; c--; } 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(cpustate)); break;
+ case 0x38: SHRA_WORD(c); break;
+ }
+}
+
+OP( 0xd4, i_aam ) { FETCH; cpustate->regs.b[AH] = cpustate->regs.b[AL] / 10; cpustate->regs.b[AL] %= 10; SetSZPF_Word(cpustate->regs.w[AW]); CLK(17); }
+OP( 0xd5, i_aad ) { FETCH; cpustate->regs.b[AL] = cpustate->regs.b[AH] * 10 + cpustate->regs.b[AL]; cpustate->regs.b[AH] = 0; SetSZPF_Byte(cpustate->regs.b[AL]); CLK(5); }
+OP( 0xd6, i_setalc ) { cpustate->regs.b[AL] = (CF)?0xff:0x00; CLK(3); logerror("%06x: Undefined opcode (SETALC)\n",PC(cpustate)); }
+OP( 0xd7, i_trans ) { UINT32 dest = (cpustate->regs.w[BW]+cpustate->regs.b[AL])&0xffff; cpustate->regs.b[AL] = GetMemB(DS, dest); CLK(5); }
+OP( 0xd8, i_fpo ) { GetModRM; CLK(1); logerror("%06x: Unimplemented floating point control %04x\n",PC(cpustate),ModRM); }
+
+OP( 0xe0, i_loopne ) { INT8 disp = (INT8)FETCH; cpustate->regs.w[CW]--; if (!ZF && cpustate->regs.w[CW]) { cpustate->ip = (WORD)(cpustate->ip+disp); CLK(6); } else CLK(3); }
+OP( 0xe1, i_loope ) { INT8 disp = (INT8)FETCH; cpustate->regs.w[CW]--; if ( ZF && cpustate->regs.w[CW]) { cpustate->ip = (WORD)(cpustate->ip+disp); CLK(6); } else CLK(3); }
+OP( 0xe2, i_loop ) { INT8 disp = (INT8)FETCH; cpustate->regs.w[CW]--; if (cpustate->regs.w[CW]) { cpustate->ip = (WORD)(cpustate->ip+disp); CLK(5); } else CLK(2); }
+OP( 0xe3, i_jcxz ) { INT8 disp = (INT8)FETCH; if (cpustate->regs.w[CW] == 0) { cpustate->ip = (WORD)(cpustate->ip+disp); CLK(4); } else CLK(1); }
+OP( 0xe4, i_inal ) { UINT8 port = FETCH; cpustate->regs.b[AL] = read_port(port); CLK(6); }
+OP( 0xe5, i_inax ) { UINT8 port = FETCH; cpustate->regs.b[AL] = read_port(port); cpustate->regs.b[AH] = read_port(port+1); CLK(6); }
+OP( 0xe6, i_outal ) { UINT8 port = FETCH; write_port(port, cpustate->regs.b[AL]); CLK(6); }
+OP( 0xe7, i_outax ) { UINT8 port = FETCH; write_port(port, cpustate->regs.b[AL]); write_port(port+1, cpustate->regs.b[AH]); CLK(6); }
+
+OP( 0xe8, i_call_d16 ) { UINT32 tmp; FETCHWORD(tmp); PUSH(cpustate->ip); cpustate->ip = (WORD)(cpustate->ip+(INT16)tmp); CLK(5); }
+OP( 0xe9, i_jmp_d16 ) { UINT32 tmp; FETCHWORD(tmp); cpustate->ip = (WORD)(cpustate->ip+(INT16)tmp); CLK(4); }
+OP( 0xea, i_jmp_far ) { UINT32 tmp,tmp1; FETCHWORD(tmp); FETCHWORD(tmp1); cpustate->sregs[CS] = (WORD)tmp1; cpustate->ip = (WORD)tmp; CLK(7); }
+OP( 0xeb, i_jmp_d8 ) { int tmp = (int)((INT8)FETCH); CLK(4);
+ if (tmp==-2 && cpustate->no_interrupt==0 && (cpustate->pending_irq==0) && cpustate->icount>0) cpustate->icount%=12; /* cycle skip */
+ cpustate->ip = (WORD)(cpustate->ip+tmp);
+}
+OP( 0xec, i_inaldx ) { cpustate->regs.b[AL] = read_port(cpustate->regs.w[DW]); CLK(6);}
+OP( 0xed, i_inaxdx ) { UINT32 port = cpustate->regs.w[DW]; cpustate->regs.b[AL] = read_port(port); cpustate->regs.b[AH] = read_port(port+1); CLK(6); }
+OP( 0xee, i_outdxal ) { write_port(cpustate->regs.w[DW], cpustate->regs.b[AL]); CLK(6); }
+OP( 0xef, i_outdxax ) { UINT32 port = cpustate->regs.w[DW]; write_port(port, cpustate->regs.b[AL]); write_port(port+1, cpustate->regs.b[AH]); CLK(6); }
+
+OP( 0xf0, i_lock ) { logerror("%06x: Warning - BUSLOCK\n",PC(cpustate)); cpustate->no_interrupt=1; CLK(1); }
+OP( 0xf2, i_repne ) { UINT32 next = FETCHOP; UINT16 c = cpustate->regs.w[CW];
+ switch(next) { /* Segments */
+ case 0x26: cpustate->seg_prefix=TRUE; cpustate->prefix_base=cpustate->sregs[ES]<<4; next = FETCHOP; CLK(2); break;
+ case 0x2e: cpustate->seg_prefix=TRUE; cpustate->prefix_base=cpustate->sregs[CS]<<4; next = FETCHOP; CLK(2); break;
+ case 0x36: cpustate->seg_prefix=TRUE; cpustate->prefix_base=cpustate->sregs[SS]<<4; next = FETCHOP; CLK(2); break;
+ case 0x3e: cpustate->seg_prefix=TRUE; cpustate->prefix_base=cpustate->sregs[DS]<<4; next = FETCHOP; CLK(2); break;
+ }
+
+ switch(next) {
+ case 0x6c: CLK(3); if (c) do { i_insb(cpustate); c--; } while (c>0); cpustate->regs.w[CW]=c; break;
+ case 0x6d: CLK(3); if (c) do { i_insw(cpustate); c--; } while (c>0); cpustate->regs.w[CW]=c; break;
+ case 0x6e: CLK(3); if (c) do { i_outsb(cpustate); c--; } while (c>0); cpustate->regs.w[CW]=c; break;
+ case 0x6f: CLK(3); if (c) do { i_outsw(cpustate); c--; } while (c>0); cpustate->regs.w[CW]=c; break;
+ case 0xa4: CLK(3); if (c) do { i_movsb(cpustate); c--; } while (c>0); cpustate->regs.w[CW]=c; break;
+ case 0xa5: CLK(3); if (c) do { i_movsw(cpustate); c--; } while (c>0); cpustate->regs.w[CW]=c; break;
+ case 0xa6: CLK(3); if (c) do { i_cmpsb(cpustate); c--; } while (c>0 && ZF==0); cpustate->regs.w[CW]=c; break;
+ case 0xa7: CLK(3); if (c) do { i_cmpsw(cpustate); c--; } while (c>0 && ZF==0); cpustate->regs.w[CW]=c; break;
+ case 0xaa: CLK(3); if (c) do { i_stosb(cpustate); c--; } while (c>0); cpustate->regs.w[CW]=c; break;
+ case 0xab: CLK(3); if (c) do { i_stosw(cpustate); c--; } while (c>0); cpustate->regs.w[CW]=c; break;
+ case 0xac: CLK(3); if (c) do { i_lodsb(cpustate); c--; } while (c>0); cpustate->regs.w[CW]=c; break;
+ case 0xad: CLK(3); if (c) do { i_lodsw(cpustate); c--; } while (c>0); cpustate->regs.w[CW]=c; break;
+ case 0xae: CLK(3); if (c) do { i_scasb(cpustate); c--; } while (c>0 && ZF==0); cpustate->regs.w[CW]=c; break;
+ case 0xaf: CLK(3); if (c) do { i_scasw(cpustate); c--; } while (c>0 && ZF==0); cpustate->regs.w[CW]=c; break;
+ default: logerror("%06x: REPNE invalid\n",PC(cpustate)); nec_instruction[next](cpustate);
+ }
+ cpustate->seg_prefix=FALSE;
+}
+OP( 0xf3, i_repe ) { UINT32 next = FETCHOP; UINT16 c = cpustate->regs.w[CW];
+ switch(next) { /* Segments */
+ case 0x26: cpustate->seg_prefix=TRUE; cpustate->prefix_base=cpustate->sregs[ES]<<4; next = FETCHOP; CLK(2); break;
+ case 0x2e: cpustate->seg_prefix=TRUE; cpustate->prefix_base=cpustate->sregs[CS]<<4; next = FETCHOP; CLK(2); break;
+ case 0x36: cpustate->seg_prefix=TRUE; cpustate->prefix_base=cpustate->sregs[SS]<<4; next = FETCHOP; CLK(2); break;
+ case 0x3e: cpustate->seg_prefix=TRUE; cpustate->prefix_base=cpustate->sregs[DS]<<4; next = FETCHOP; CLK(2); break;
+ }
+
+ switch(next) {
+ case 0x6c: CLK(3); if (c) do { i_insb(cpustate); c--; } while (c>0); cpustate->regs.w[CW]=c; break;
+ case 0x6d: CLK(3); if (c) do { i_insw(cpustate); c--; } while (c>0); cpustate->regs.w[CW]=c; break;
+ case 0x6e: CLK(3); if (c) do { i_outsb(cpustate); c--; } while (c>0); cpustate->regs.w[CW]=c; break;
+ case 0x6f: CLK(3); if (c) do { i_outsw(cpustate); c--; } while (c>0); cpustate->regs.w[CW]=c; break;
+ case 0xa4: CLK(3); if (c) do { i_movsb(cpustate); c--; } while (c>0); cpustate->regs.w[CW]=c; break;
+ case 0xa5: CLK(3); if (c) do { i_movsw(cpustate); c--; } while (c>0); cpustate->regs.w[CW]=c; break;
+ case 0xa6: CLK(3); if (c) do { i_cmpsb(cpustate); c--; } while (c>0 && ZF==1); cpustate->regs.w[CW]=c; break;
+ case 0xa7: CLK(3); if (c) do { i_cmpsw(cpustate); c--; } while (c>0 && ZF==1); cpustate->regs.w[CW]=c; break;
+ case 0xaa: CLK(3); if (c) do { i_stosb(cpustate); c--; } while (c>0); cpustate->regs.w[CW]=c; break;
+ case 0xab: CLK(3); if (c) do { i_stosw(cpustate); c--; } while (c>0); cpustate->regs.w[CW]=c; break;
+ case 0xac: CLK(3); if (c) do { i_lodsb(cpustate); c--; } while (c>0); cpustate->regs.w[CW]=c; break;
+ case 0xad: CLK(3); if (c) do { i_lodsw(cpustate); c--; } while (c>0); cpustate->regs.w[CW]=c; break;
+ case 0xae: CLK(3); if (c) do { i_scasb(cpustate); c--; } while (c>0 && ZF==1); cpustate->regs.w[CW]=c; break;
+ case 0xaf: CLK(3); if (c) do { i_scasw(cpustate); c--; } while (c>0 && ZF==1); cpustate->regs.w[CW]=c; break;
+ default: logerror("%06x: REPE invalid\n",PC(cpustate)); nec_instruction[next](cpustate);
+ }
+ cpustate->seg_prefix=FALSE;
+}
+OP( 0xf4, i_hlt ) { logerror("%06x: HALT\n",PC(cpustate)); cpustate->icount=0; }
+OP( 0xf5, i_cmc ) { cpustate->CarryVal = !CF; CLK(4); }
+OP( 0xf6, i_f6pre ) { UINT32 tmp; UINT32 uresult,uresult2; INT32 result,result2;
+ GetModRM; tmp = GetRMByte(ModRM);
+ switch (ModRM & 0x38) {
+ case 0x00: tmp &= FETCH; cpustate->CarryVal = cpustate->OverVal = 0; SetSZPF_Byte(tmp); CLKM(1,2); break; /* TEST */
+ case 0x08: logerror("%06x: Undefined opcode 0xf6 0x08\n",PC(cpustate)); break;
+ case 0x10: PutbackRMByte(ModRM,~tmp); CLKM(1,3); break; /* NOT */
+ case 0x18: cpustate->CarryVal=(tmp!=0); tmp=(~tmp)+1; SetSZPF_Byte(tmp); PutbackRMByte(ModRM,tmp&0xff); CLKM(1,3); break; /* NEG */
+ case 0x20: uresult = cpustate->regs.b[AL]*tmp; cpustate->regs.w[AW]=(WORD)uresult; cpustate->CarryVal=cpustate->OverVal=(cpustate->regs.b[AH]!=0); CLKM(3,4); break; /* MULU */
+ case 0x28: result = (INT16)((INT8)cpustate->regs.b[AL])*(INT16)((INT8)tmp); cpustate->regs.w[AW]=(WORD)result; cpustate->CarryVal=cpustate->OverVal=(cpustate->regs.b[AH]!=0); CLKM(3,4); break; /* MUL */
+ case 0x30: if (tmp) { DIVUB; } else nec_interrupt(cpustate,0,0); CLKM(15,16); break;
+ case 0x38: if (tmp) { DIVB; } else nec_interrupt(cpustate,0,0); CLKM(17,18); break;
+ }
+}
+
+OP( 0xf7, i_f7pre ) { UINT32 tmp,tmp2; UINT32 uresult,uresult2; INT32 result,result2;
+ GetModRM; tmp = GetRMWord(ModRM);
+ switch (ModRM & 0x38) {
+ case 0x00: FETCHWORD(tmp2); tmp &= tmp2; cpustate->CarryVal = cpustate->OverVal = 0; SetSZPF_Word(tmp); CLKM(1,2); break; /* TEST */
+ case 0x08: logerror("%06x: Undefined opcode 0xf7 0x08\n",PC(cpustate)); break;
+ case 0x10: PutbackRMWord(ModRM,~tmp); CLKM(1,3); break; /* NOT */
+ case 0x18: cpustate->CarryVal=(tmp!=0); tmp=(~tmp)+1; SetSZPF_Word(tmp); PutbackRMWord(ModRM,tmp&0xffff); CLKM(1,3); break; /* NEG */
+ case 0x20: uresult = cpustate->regs.w[AW]*tmp; cpustate->regs.w[AW]=uresult&0xffff; cpustate->regs.w[DW]=((UINT32)uresult)>>16; cpustate->CarryVal=cpustate->OverVal=(cpustate->regs.w[DW]!=0); CLKM(3,4); break; /* MULU */
+ case 0x28: result = (INT32)((INT16)cpustate->regs.w[AW])*(INT32)((INT16)tmp); cpustate->regs.w[AW]=result&0xffff; cpustate->regs.w[DW]=result>>16; cpustate->CarryVal=cpustate->OverVal=(cpustate->regs.w[DW]!=0); CLKM(3,4); break; /* MUL */
+ case 0x30: if (tmp) { DIVUW; } else nec_interrupt(cpustate,0,0); CLKM(23,24); break;
+ case 0x38: if (tmp) { DIVW; } else nec_interrupt(cpustate,0,0); CLKM(24,25); break;
+ }
+}
+
+OP( 0xf8, i_clc ) { cpustate->CarryVal = 0; CLK(4); }
+OP( 0xf9, i_stc ) { cpustate->CarryVal = 1; CLK(4); }
+OP( 0xfa, i_di ) { SetIF(0); CLK(4); }
+OP( 0xfb, i_ei ) { SetIF(1); CLK(4); }
+OP( 0xfc, i_cld ) { SetDF(0); CLK(4); }
+OP( 0xfd, i_std ) { SetDF(1); CLK(4); }
+OP( 0xfe, i_fepre ) { UINT32 tmp, tmp1; GetModRM; tmp=GetRMByte(ModRM);
+ switch(ModRM & 0x38) {
+ case 0x00: tmp1 = tmp+1; cpustate->OverVal = (tmp==0x7f); SetAF(tmp1,tmp,1); SetSZPF_Byte(tmp1); PutbackRMByte(ModRM,(BYTE)tmp1); CLKM(1,3); break; /* INC */
+ case 0x08: tmp1 = tmp-1; cpustate->OverVal = (tmp==0x80); SetAF(tmp1,tmp,1); SetSZPF_Byte(tmp1); PutbackRMByte(ModRM,(BYTE)tmp1); CLKM(1,3); break; /* DEC */
+ default: logerror("%06x: FE Pre with unimplemented mod\n",PC(cpustate));
+ }
+}
+OP( 0xff, i_ffpre ) { UINT32 tmp, tmp1; GetModRM; tmp=GetRMWord(ModRM);
+ switch(ModRM & 0x38) {
+ case 0x00: tmp1 = tmp+1; cpustate->OverVal = (tmp==0x7fff); SetAF(tmp1,tmp,1); SetSZPF_Word(tmp1); PutbackRMWord(ModRM,(WORD)tmp1); CLKM(1,3); break; /* INC */
+ case 0x08: tmp1 = tmp-1; cpustate->OverVal = (tmp==0x8000); SetAF(tmp1,tmp,1); SetSZPF_Word(tmp1); PutbackRMWord(ModRM,(WORD)tmp1); CLKM(1,3); break; /* DEC */
+ case 0x10: PUSH(cpustate->ip); cpustate->ip = (WORD)tmp; CLKM(5,6); break; /* CALL */
+ case 0x18: tmp1 = cpustate->sregs[CS]; cpustate->sregs[CS] = GetnextRMWord; PUSH(tmp1); PUSH(cpustate->ip); cpustate->ip = tmp; CLKM(5,12); break; /* CALL FAR */
+ case 0x20: cpustate->ip = tmp; CLKM(4,5); break; /* JMP */
+ case 0x28: cpustate->ip = tmp; cpustate->sregs[CS] = GetnextRMWord; CLK(10); break; /* JMP FAR */
+ case 0x30: PUSH(tmp); CLK(1); break;
+ default: logerror("%06x: FF Pre with unimplemented mod\n",PC(cpustate));
+ }
+}
+
+static void i_invalid(v30mz_state *cpustate)
+{
+ cpustate->icount-=10;
+ logerror("%06x: Invalid Opcode\n",PC(cpustate));
+}
+
+/*****************************************************************************/
+
+static void set_irq_line(v30mz_state *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_irq |= NMI_IRQ;
+ }
+ }
+ else
+ {
+ cpustate->irq_state = state;
+ if (state == CLEAR_LINE)
+ {
+ // if (!cpustate->IF) NS010718 fix interrupt request loss
+ cpustate->pending_irq &= ~INT_IRQ;
+ }
+ else
+ {
+ // if (cpustate->IF) NS010718 fix interrupt request loss
+ cpustate->pending_irq |= INT_IRQ;
+ }
+ }
+}
+
+static CPU_DISASSEMBLE( nec )
+{
+ v30mz_state *cpustate = get_safe_token(device);
+
+ return necv_dasm_one(buffer, pc, oprom, cpustate->config);
+}
+
+static void nec_init(legacy_cpu_device *device, device_irq_callback irqcallback, int type)
+{
+ v30mz_state *cpustate = get_safe_token(device);
+
+ const nec_config *config = &default_config;
+
+ device->save_item(NAME(cpustate->regs.w));
+ device->save_item(NAME(cpustate->sregs));
+
+ device->save_item(NAME(cpustate->ip));
+ device->save_item(NAME(cpustate->TF));
+ device->save_item(NAME(cpustate->IF));
+ device->save_item(NAME(cpustate->DF));
+ device->save_item(NAME(cpustate->MF));
+ device->save_item(NAME(cpustate->SignVal));
+ device->save_item(NAME(cpustate->int_vector));
+ device->save_item(NAME(cpustate->pending_irq));
+ device->save_item(NAME(cpustate->nmi_state));
+ device->save_item(NAME(cpustate->irq_state));
+ device->save_item(NAME(cpustate->AuxVal));
+ device->save_item(NAME(cpustate->OverVal));
+ device->save_item(NAME(cpustate->ZeroVal));
+ device->save_item(NAME(cpustate->CarryVal));
+ device->save_item(NAME(cpustate->ParityVal));
+
+ cpustate->config = config;
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->io = device->space(AS_IO);
+}
+
+static CPU_INIT( v30mz ) { nec_init(device, irqcallback, 3); }
+static CPU_EXECUTE( v30mz )
+{
+ v30mz_state *cpustate = get_safe_token(device);
+
+ while(cpustate->icount>0) {
+ /* Dispatch IRQ */
+ if (cpustate->pending_irq && cpustate->no_interrupt==0)
+ {
+ if (cpustate->pending_irq & NMI_IRQ)
+ external_int(cpustate);
+ else if (cpustate->IF)
+ external_int(cpustate);
+ }
+
+ /* No interrupt allowed between last instruction and this one */
+ if (cpustate->no_interrupt)
+ cpustate->no_interrupt--;
+
+ debugger_instruction_hook(device, (cpustate->sregs[CS]<<4) + cpustate->ip);
+ nec_instruction[FETCHOP](cpustate);
+ }
+}
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( nec )
+{
+ v30mz_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_PC:
+ case CPUINFO_INT_REGISTER + NEC_PC:
+ if( info->i - (cpustate->sregs[CS]<<4) < 0x10000 )
+ {
+ cpustate->ip = info->i - (cpustate->sregs[CS]<<4);
+ }
+ else
+ {
+ cpustate->sregs[CS] = info->i >> 4;
+ cpustate->ip = info->i & 0x0000f;
+ }
+ break;
+ case CPUINFO_INT_REGISTER + NEC_IP: cpustate->ip = info->i; break;
+ case CPUINFO_INT_SP:
+ if( info->i - (cpustate->sregs[SS]<<4) < 0x10000 )
+ {
+ cpustate->regs.w[SP] = info->i - (cpustate->sregs[SS]<<4);
+ }
+ else
+ {
+ cpustate->sregs[SS] = info->i >> 4;
+ cpustate->regs.w[SP] = info->i & 0x0000f;
+ }
+ break;
+ case CPUINFO_INT_REGISTER + NEC_SP: cpustate->regs.w[SP] = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_FLAGS: ExpandFlags(info->i); break;
+ case CPUINFO_INT_REGISTER + NEC_AW: cpustate->regs.w[AW] = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_CW: cpustate->regs.w[CW] = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_DW: cpustate->regs.w[DW] = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_BW: cpustate->regs.w[BW] = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_BP: cpustate->regs.w[BP] = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_IX: cpustate->regs.w[IX] = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_IY: cpustate->regs.w[IY] = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_ES: cpustate->sregs[ES] = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_CS: cpustate->sregs[CS] = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_SS: cpustate->sregs[SS] = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_DS: cpustate->sregs[DS] = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_VECTOR: cpustate->int_vector = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( v30mz )
+{
+ v30mz_state *cpustate = (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(v30mz_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 = 6; 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 = 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 = 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 + 0: info->i = (cpustate->pending_irq & INT_IRQ) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = cpustate->nmi_state; break;
+
+ case CPUINFO_INT_PREVIOUSPC: /* not supported */ break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + NEC_PC: info->i = ((cpustate->sregs[CS]<<4) + cpustate->ip); break;
+ case CPUINFO_INT_REGISTER + NEC_IP: info->i = cpustate->ip; break;
+ case CPUINFO_INT_SP: info->i = (cpustate->sregs[SS]<<4) + cpustate->regs.w[SP]; break;
+ case CPUINFO_INT_REGISTER + NEC_SP: info->i = cpustate->regs.w[SP]; break;
+ case CPUINFO_INT_REGISTER + NEC_FLAGS: info->i = CompressFlags(); break;
+ case CPUINFO_INT_REGISTER + NEC_AW: info->i = cpustate->regs.w[AW]; break;
+ case CPUINFO_INT_REGISTER + NEC_CW: info->i = cpustate->regs.w[CW]; break;
+ case CPUINFO_INT_REGISTER + NEC_DW: info->i = cpustate->regs.w[DW]; break;
+ case CPUINFO_INT_REGISTER + NEC_BW: info->i = cpustate->regs.w[BW]; break;
+ case CPUINFO_INT_REGISTER + NEC_BP: info->i = cpustate->regs.w[BP]; break;
+ case CPUINFO_INT_REGISTER + NEC_IX: info->i = cpustate->regs.w[IX]; break;
+ case CPUINFO_INT_REGISTER + NEC_IY: info->i = cpustate->regs.w[IY]; break;
+ case CPUINFO_INT_REGISTER + NEC_ES: info->i = cpustate->sregs[ES]; break;
+ case CPUINFO_INT_REGISTER + NEC_CS: info->i = cpustate->sregs[CS]; break;
+ case CPUINFO_INT_REGISTER + NEC_SS: info->i = cpustate->sregs[SS]; break;
+ case CPUINFO_INT_REGISTER + NEC_DS: info->i = cpustate->sregs[DS]; break;
+ case CPUINFO_INT_REGISTER + NEC_VECTOR: info->i = cpustate->int_vector; break;
+ case CPUINFO_INT_REGISTER + NEC_PENDING: info->i = cpustate->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_RESET: info->reset = CPU_RESET_NAME(nec); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(nec); 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 = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "NEC V-Series"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.5"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "NEC emulator v1.5 by Bryan McPhail"); 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 ? 'M':'.',
+ 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 ? 'N':'.',
+ flags & 0x0001 ? 'C':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + NEC_PC: sprintf(info->s, "PC:%04X", (cpustate->sregs[CS]<<4) + cpustate->ip); break;
+ case CPUINFO_STR_REGISTER + NEC_IP: sprintf(info->s, "IP:%04X", cpustate->ip); break;
+ case CPUINFO_STR_REGISTER + NEC_SP: sprintf(info->s, "SP:%04X", cpustate->regs.w[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", cpustate->regs.w[AW]); break;
+ case CPUINFO_STR_REGISTER + NEC_CW: sprintf(info->s, "CW:%04X", cpustate->regs.w[CW]); break;
+ case CPUINFO_STR_REGISTER + NEC_DW: sprintf(info->s, "DW:%04X", cpustate->regs.w[DW]); break;
+ case CPUINFO_STR_REGISTER + NEC_BW: sprintf(info->s, "BW:%04X", cpustate->regs.w[BW]); break;
+ case CPUINFO_STR_REGISTER + NEC_BP: sprintf(info->s, "BP:%04X", cpustate->regs.w[BP]); break;
+ case CPUINFO_STR_REGISTER + NEC_IX: sprintf(info->s, "IX:%04X", cpustate->regs.w[IX]); break;
+ case CPUINFO_STR_REGISTER + NEC_IY: sprintf(info->s, "IY:%04X", cpustate->regs.w[IY]); break;
+ case CPUINFO_STR_REGISTER + NEC_ES: sprintf(info->s, "ES:%04X", cpustate->sregs[ES]); break;
+ case CPUINFO_STR_REGISTER + NEC_CS: sprintf(info->s, "CS:%04X", cpustate->sregs[CS]); break;
+ case CPUINFO_STR_REGISTER + NEC_SS: sprintf(info->s, "SS:%04X", cpustate->sregs[SS]); break;
+ case CPUINFO_STR_REGISTER + NEC_DS: sprintf(info->s, "DS:%04X", cpustate->sregs[DS]); break;
+ case CPUINFO_STR_REGISTER + NEC_VECTOR: sprintf(info->s, "V:%02X", cpustate->int_vector); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(v30mz);
+ break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(v30mz);
+ break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "V30MZ");
+ break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(V30MZ, v30mz);
diff --git a/trunk/src/emu/cpu/v30mz/v30mz.h b/trunk/src/emu/cpu/v30mz/v30mz.h
new file mode 100644
index 00000000000..3b0d3d29129
--- /dev/null
+++ b/trunk/src/emu/cpu/v30mz/v30mz.h
@@ -0,0 +1,358 @@
+typedef enum { ES, CS, SS, DS } SREGS;
+typedef enum { AW, CW, DW, BW, SP, BP, IX, IY } WREGS;
+
+#define NEC_NMI_INT_VECTOR 2
+
+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),
+ IXL = NATIVE_ENDIAN_VALUE_LE_BE(0xc, 0xd),
+ IXH = NATIVE_ENDIAN_VALUE_LE_BE(0xd, 0xc),
+ IYL = NATIVE_ENDIAN_VALUE_LE_BE(0xe, 0xf),
+ IYH = 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->DF = (x))
+#define SetMD(x) (cpustate->MF = (x)) /* OB [19.07.99] Mode Flag V30 */
+
+#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->SignVal=cpustate->ZeroVal=cpustate->ParityVal=(INT8)(x))
+#define SetSZPF_Word(x) (cpustate->SignVal=cpustate->ZeroVal=cpustate->ParityVal=(INT16)(x))
+
+#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 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; cpustate->CarryVal=cpustate->OverVal=cpustate->AuxVal=0; SetSZPF_Byte(dst)
+#define ORW dst|=src; cpustate->CarryVal=cpustate->OverVal=cpustate->AuxVal=0; SetSZPF_Word(dst)
+
+#define ANDB dst&=src; cpustate->CarryVal=cpustate->OverVal=cpustate->AuxVal=0; SetSZPF_Byte(dst)
+#define ANDW dst&=src; cpustate->CarryVal=cpustate->OverVal=cpustate->AuxVal=0; SetSZPF_Word(dst)
+
+#define XORB dst^=src; cpustate->CarryVal=cpustate->OverVal=cpustate->AuxVal=0; SetSZPF_Byte(dst)
+#define XORW dst^=src; cpustate->CarryVal=cpustate->OverVal=cpustate->AuxVal=0; SetSZPF_Word(dst)
+
+#define CF (cpustate->CarryVal!=0)
+#define SF (cpustate->SignVal<0)
+#define ZF (cpustate->ZeroVal==0)
+#define PF parity_table[(BYTE)cpustate->ParityVal]
+#define AF (cpustate->AuxVal!=0)
+#define OF (cpustate->OverVal!=0)
+#define MD (cpustate->MF!=0)
+
+/************************************************************************/
+
+#define SegBase(Seg) (cpustate->sregs[Seg] << 4)
+
+#define DefaultBase(Seg) ((cpustate->seg_prefix && (Seg==DS || Seg==SS)) ? cpustate->prefix_base : cpustate->sregs[Seg] << 4)
+
+#define GetMemB(Seg,Off) ((UINT8)cpustate->program->read_byte((DefaultBase(Seg)+(Off))))
+#define GetMemW(Seg,Off) ((UINT16) cpustate->program->read_byte((DefaultBase(Seg)+(Off))) + (cpustate->program->read_byte((DefaultBase(Seg)+((Off)+1)))<<8) )
+
+#define PutMemB(Seg,Off,x) { cpustate->program->write_byte((DefaultBase(Seg)+(Off)),(x)); }
+#define PutMemW(Seg,Off,x) { PutMemB(Seg,Off,(x)&0xff); PutMemB(Seg,(Off)+1,(BYTE)((x)>>8)); }
+
+/* Todo: Remove these later - plus readword could overflow */
+#define ReadByte(ea) ((BYTE)cpustate->program->read_byte((ea)))
+#define ReadWord(ea) (cpustate->program->read_byte((ea))+(cpustate->program->read_byte(((ea)+1))<<8))
+#define WriteByte(ea,val) { cpustate->program->write_byte((ea),val); }
+#define WriteWord(ea,val) { cpustate->program->write_byte((ea),(BYTE)(val)); cpustate->program->write_byte(((ea)+1),(val)>>8); }
+
+#define read_port(port) cpustate->io->read_byte(port)
+#define write_port(port,val) cpustate->io->write_byte(port,val)
+
+#define FETCH (cpustate->direct->read_raw_byte((cpustate->sregs[CS]<<4)+cpustate->ip++))
+#define FETCHOP (cpustate->direct->read_decrypted_byte((cpustate->sregs[CS]<<4)+cpustate->ip++))
+#define FETCHWORD(var) { var=cpustate->direct->read_raw_byte((((cpustate->sregs[CS]<<4)+cpustate->ip)))+(cpustate->direct->read_raw_byte((((cpustate->sregs[CS]<<4)+cpustate->ip+1)))<<8); cpustate->ip+=2; }
+#define PUSH(val) { cpustate->regs.w[SP]-=2; WriteWord((((cpustate->sregs[SS]<<4)+cpustate->regs.w[SP])),val); }
+#define POP(var) { var = ReadWord((((cpustate->sregs[SS]<<4)+cpustate->regs.w[SP]))); cpustate->regs.w[SP]+=2; }
+#define PEEK(addr) ((BYTE)cpustate->direct->read_raw_byte(addr))
+#define PEEKOP(addr) ((BYTE)cpustate->direct->read_decrypted_byte(addr))
+
+#define GetModRM UINT32 ModRM=cpustate->direct->read_raw_byte((cpustate->sregs[CS]<<4)+cpustate->ip++)
+
+/* 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(v30mz) { cpustate->icount-=v30mz; }
+#define CLKM(v30mz,v30mzm) { cpustate->icount-=( ModRM >=0xc0 )?v30mz:v30mzm; }
+
+/************************************************************************/
+#define CompressFlags() (WORD)(CF | (PF << 2) | (AF << 4) | (ZF << 6) \
+ | (SF << 7) | (cpustate->TF << 8) | (cpustate->IF << 9) \
+ | (cpustate->DF << 10) | (OF << 11)| (MD << 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) == 256; \
+ cpustate->IF = ((f) & 512) == 512; \
+ cpustate->DF = ((f) & 1024) == 1024; \
+ cpustate->OverVal = (f) & 2048; \
+ cpustate->MF = ((f) & 0x8000) == 0x8000; \
+}
+
+#define IncWordReg(Reg) \
+ unsigned tmp = (unsigned)cpustate->regs.w[Reg]; \
+ unsigned tmp1 = tmp+1; \
+ cpustate->OverVal = (tmp == 0x7fff); \
+ SetAF(tmp1,tmp,1); \
+ SetSZPF_Word(tmp1); \
+ cpustate->regs.w[Reg]=tmp1
+
+#define DecWordReg(Reg) \
+ unsigned tmp = (unsigned)cpustate->regs.w[Reg]; \
+ unsigned tmp1 = tmp-1; \
+ cpustate->OverVal = (tmp == 0x8000); \
+ SetAF(tmp1,tmp,1); \
+ SetSZPF_Word(tmp1); \
+ cpustate->regs.w[Reg]=tmp1
+
+#define JMP(flag) \
+ int tmp = (int)((INT8)FETCH); \
+ if (flag) \
+ { \
+ cpustate->ip = (WORD)(cpustate->ip+tmp); \
+ cpustate->icount-=10; \
+ return; \
+ }
+
+#define ADJ4(param1,param2) \
+ if (AF || ((cpustate->regs.b[AL] & 0xf) > 9)) \
+ { \
+ UINT16 tmp; \
+ tmp = cpustate->regs.b[AL] + param1; \
+ cpustate->regs.b[AL] = tmp; \
+ cpustate->AuxVal = 1; \
+ cpustate->CarryVal |= tmp & 0x100; \
+ } \
+ if (CF || (cpustate->regs.b[AL]>0x9f)) \
+ { \
+ cpustate->regs.b[AL] += param2; \
+ cpustate->CarryVal = 1; \
+ } \
+ SetSZPF_Byte(cpustate->regs.b[AL])
+
+#define ADJB(param1,param2) \
+ if (AF || ((cpustate->regs.b[AL] & 0xf) > 9)) \
+ { \
+ cpustate->regs.b[AL] += param1; \
+ cpustate->regs.b[AH] += param2; \
+ cpustate->AuxVal = 1; \
+ cpustate->CarryVal = 1; \
+ } \
+ else \
+ { \
+ cpustate->AuxVal = 0; \
+ cpustate->CarryVal = 0; \
+ } \
+ cpustate->regs.b[AL] &= 0x0F
+
+#define BITOP_BYTE \
+ ModRM = FETCH; \
+ if (ModRM >= 0xc0) { \
+ tmp=cpustate->regs.b[Mod_RM.RM.b[ModRM]]; \
+ } \
+ else { \
+ (*GetEA[ModRM])(cpustate); \
+ tmp=ReadByte(cpustate->ea); \
+ }
+
+#define BITOP_WORD \
+ ModRM = FETCH; \
+ if (ModRM >= 0xc0) { \
+ tmp=cpustate->regs.w[Mod_RM.RM.w[ModRM]]; \
+ } \
+ else { \
+ (*GetEA[ModRM])(cpustate); \
+ tmp=ReadWord(cpustate->ea); \
+ }
+
+#define BIT_NOT \
+ if (tmp & (1<<tmp2)) \
+ tmp &= ~(1<<tmp2); \
+ else \
+ tmp |= (1<<tmp2)
+
+#define XchgAWReg(Reg) \
+ WORD tmp; \
+ tmp = cpustate->regs.w[Reg]; \
+ cpustate->regs.w[Reg] = cpustate->regs.w[AW]; \
+ cpustate->regs.w[AW] = tmp
+
+#define ROL_BYTE cpustate->CarryVal = dst & 0x80; dst = (dst << 1)+CF
+#define ROL_WORD cpustate->CarryVal = dst & 0x8000; dst = (dst << 1)+CF
+#define ROR_BYTE cpustate->CarryVal = dst & 0x1; dst = (dst >> 1)+(CF<<7)
+#define ROR_WORD cpustate->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; cpustate->CarryVal = dst & 0x01; dst >>= 1
+#define RORC_WORD dst = (CF<<16)+dst; cpustate->CarryVal = dst & 0x01; dst >>= 1
+#define SHL_BYTE(c) cpustate->icount-=c; dst <<= c; SetCFB(dst); SetSZPF_Byte(dst); PutbackRMByte(ModRM,(BYTE)dst)
+#define SHL_WORD(c) cpustate->icount-=c; dst <<= c; SetCFW(dst); SetSZPF_Word(dst); PutbackRMWord(ModRM,(WORD)dst)
+#define SHR_BYTE(c) cpustate->icount-=c; dst >>= c-1; cpustate->CarryVal = dst & 0x1; dst >>= 1; SetSZPF_Byte(dst); PutbackRMByte(ModRM,(BYTE)dst)
+#define SHR_WORD(c) cpustate->icount-=c; dst >>= c-1; cpustate->CarryVal = dst & 0x1; dst >>= 1; SetSZPF_Word(dst); PutbackRMWord(ModRM,(WORD)dst)
+#define SHRA_BYTE(c) cpustate->icount-=c; dst = ((INT8)dst) >> (c-1); cpustate->CarryVal = dst & 0x1; dst = ((INT8)((BYTE)dst)) >> 1; SetSZPF_Byte(dst); PutbackRMByte(ModRM,(BYTE)dst)
+#define SHRA_WORD(c) cpustate->icount-=c; dst = ((INT16)dst) >> (c-1); cpustate->CarryVal = dst & 0x1; dst = ((INT16)((WORD)dst)) >> 1; SetSZPF_Word(dst); PutbackRMWord(ModRM,(WORD)dst)
+
+#define DIVUB \
+ uresult = cpustate->regs.w[AW]; \
+ uresult2 = uresult % tmp; \
+ if ((uresult /= tmp) > 0xff) { \
+ nec_interrupt(cpustate,0,0); break; \
+ } else { \
+ cpustate->regs.b[AL] = uresult; \
+ cpustate->regs.b[AH] = uresult2; \
+ }
+
+#define DIVB \
+ result = (INT16)cpustate->regs.w[AW]; \
+ result2 = result % (INT16)((INT8)tmp); \
+ if ((result /= (INT16)((INT8)tmp)) > 0xff) { \
+ nec_interrupt(cpustate,0,0); break; \
+ } else { \
+ cpustate->regs.b[AL] = result; \
+ cpustate->regs.b[AH] = result2; \
+ }
+
+#define DIVUW \
+ uresult = (((UINT32)cpustate->regs.w[DW]) << 16) | cpustate->regs.w[AW];\
+ uresult2 = uresult % tmp; \
+ if ((uresult /= tmp) > 0xffff) { \
+ nec_interrupt(cpustate,0,0); break; \
+ } else { \
+ cpustate->regs.w[AW]=uresult; \
+ cpustate->regs.w[DW]=uresult2; \
+ }
+
+#define DIVW \
+ result = ((UINT32)cpustate->regs.w[DW] << 16) + cpustate->regs.w[AW]; \
+ result2 = result % (INT32)((INT16)tmp); \
+ if ((result /= (INT32)((INT16)tmp)) > 0xffff) { \
+ nec_interrupt(cpustate,0,0); break; \
+ } else { \
+ cpustate->regs.w[AW]=result; \
+ cpustate->regs.w[DW]=result2; \
+ }
+
+#define ADD4S { \
+ int i,v1,v2,result; \
+ int count = (cpustate->regs.b[CL]+1)/2; \
+ unsigned di = cpustate->regs.w[IY]; \
+ unsigned si = cpustate->regs.w[IX]; \
+ if (cpustate->seg_prefix) logerror("%06x: Warning: seg_prefix defined for add4s\n",PC(cpustate)); \
+ cpustate->ZeroVal = cpustate->CarryVal = 0; \
+ for (i=0;i<count;i++) { \
+ cpustate->icount-=19; \
+ tmp = GetMemB(DS, si); \
+ tmp2 = GetMemB(ES, di); \
+ v1 = (tmp>>4)*10 + (tmp&0xf); \
+ v2 = (tmp2>>4)*10 + (tmp2&0xf); \
+ result = v1+v2+cpustate->CarryVal; \
+ cpustate->CarryVal = result > 99 ? 1 : 0; \
+ result = result % 100; \
+ v1 = ((result/10)<<4) | (result % 10); \
+ PutMemB(ES, di,v1); \
+ if (v1) cpustate->ZeroVal = 1; \
+ si++; \
+ di++; \
+ } \
+}
+
+#define SUB4S { \
+ int count = (cpustate->regs.b[CL]+1)/2; \
+ int i,v1,v2,result; \
+ unsigned di = cpustate->regs.w[IY]; \
+ unsigned si = cpustate->regs.w[IX]; \
+ if (cpustate->seg_prefix) logerror("%06x: Warning: seg_prefix defined for sub4s\n",PC(cpustate)); \
+ cpustate->ZeroVal = cpustate->CarryVal = 0; \
+ for (i=0;i<count;i++) { \
+ cpustate->icount-=19; \
+ tmp = GetMemB(ES, di); \
+ tmp2 = GetMemB(DS, si); \
+ v1 = (tmp>>4)*10 + (tmp&0xf); \
+ v2 = (tmp2>>4)*10 + (tmp2&0xf); \
+ if (v1 < (v2+cpustate->CarryVal)) { \
+ v1+=100; \
+ result = v1-(v2+cpustate->CarryVal); \
+ cpustate->CarryVal = 1; \
+ } else { \
+ result = v1-(v2+cpustate->CarryVal); \
+ cpustate->CarryVal = 0; \
+ } \
+ v1 = ((result/10)<<4) | (result % 10); \
+ PutMemB(ES, di,v1); \
+ if (v1) cpustate->ZeroVal = 1; \
+ si++; \
+ di++; \
+ } \
+}
+
+#define CMP4S { \
+ int count = (cpustate->regs.b[CL]+1)/2; \
+ int i,v1,v2,result; \
+ unsigned di = cpustate->regs.w[IY]; \
+ unsigned si = cpustate->regs.w[IX]; \
+ if (cpustate->seg_prefix) logerror("%06x: Warning: seg_prefix defined for cmp4s\n",PC(cpustate)); \
+ cpustate->ZeroVal = cpustate->CarryVal = 0; \
+ for (i=0;i<count;i++) { \
+ cpustate->icount-=19; \
+ tmp = GetMemB(ES, di); \
+ tmp2 = GetMemB(DS, si); \
+ v1 = (tmp>>4)*10 + (tmp&0xf); \
+ v2 = (tmp2>>4)*10 + (tmp2&0xf); \
+ if (v1 < (v2+cpustate->CarryVal)) { \
+ v1+=100; \
+ result = v1-(v2+cpustate->CarryVal); \
+ cpustate->CarryVal = 1; \
+ } else { \
+ result = v1-(v2+cpustate->CarryVal); \
+ cpustate->CarryVal = 0; \
+ } \
+ v1 = ((result/10)<<4) | (result % 10); \
+ if (v1) cpustate->ZeroVal = 1; \
+ si++; \
+ di++; \
+ } \
+}
diff --git a/trunk/src/emu/cpu/v60/am.c b/trunk/src/emu/cpu/v60/am.c
new file mode 100644
index 00000000000..3d5c17171eb
--- /dev/null
+++ b/trunk/src/emu/cpu/v60/am.c
@@ -0,0 +1,84 @@
+
+// NOTE for bit string / field addressing
+// ************************************
+// cpustate->moddim must be passed as 10 for bit string instructions,
+// and as 11 for bit field instructions
+
+
+
+
+// Addressing mode functions and tables
+#include "am1.c" // ReadAM
+#include "am2.c" // ReadAMAddress
+#include "am3.c" // WriteAM
+
+/*
+ Input:
+ cpustate->modadd
+ cpustate->moddim
+
+ Output:
+ cpustate->amout
+ amLength
+*/
+
+static UINT32 ReadAM(v60_state *cpustate)
+{
+ cpustate->modm = cpustate->modm?1:0;
+ cpustate->modval = OpRead8(cpustate, cpustate->modadd);
+ return AMTable1[cpustate->modm][cpustate->modval >> 5](cpustate);
+}
+
+static UINT32 BitReadAM(v60_state *cpustate)
+{
+ cpustate->modm = cpustate->modm?1:0;
+ cpustate->modval = OpRead8(cpustate, cpustate->modadd);
+ return BAMTable1[cpustate->modm][cpustate->modval >> 5](cpustate);
+}
+
+
+
+/*
+ Input:
+ cpustate->modadd
+ cpustate->moddim
+
+ Output:
+ cpustate->amout
+ cpustate->amflag
+ amLength
+*/
+
+static UINT32 ReadAMAddress(v60_state *cpustate)
+{
+ cpustate->modm = cpustate->modm?1:0;
+ cpustate->modval = OpRead8(cpustate, cpustate->modadd);
+ return AMTable2[cpustate->modm][cpustate->modval >> 5](cpustate);
+}
+
+static UINT32 BitReadAMAddress(v60_state *cpustate)
+{
+ cpustate->modm = cpustate->modm?1:0;
+ cpustate->modval = OpRead8(cpustate, cpustate->modadd);
+ return BAMTable2[cpustate->modm][cpustate->modval >> 5](cpustate);
+}
+
+/*
+ Input:
+ cpustate->modadd
+ cpustate->moddim
+ cpustate->modwritevalb / H/W
+
+ Output:
+ cpustate->amout
+ amLength
+*/
+
+static UINT32 WriteAM(v60_state *cpustate)
+{
+ cpustate->modm = cpustate->modm?1:0;
+ cpustate->modval = OpRead8(cpustate, cpustate->modadd);
+ return AMTable3[cpustate->modm][cpustate->modval >> 5](cpustate);
+}
+
+
diff --git a/trunk/src/emu/cpu/v60/am1.c b/trunk/src/emu/cpu/v60/am1.c
new file mode 100644
index 00000000000..e25f70d1c5d
--- /dev/null
+++ b/trunk/src/emu/cpu/v60/am1.c
@@ -0,0 +1,1388 @@
+
+// AM1 Functions (for ReadAM)
+// **************************
+
+static UINT32 am1Register(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = (UINT8)cpustate->reg[cpustate->modval & 0x1F];
+ break;
+ case 1:
+ cpustate->amout = (UINT16)cpustate->reg[cpustate->modval & 0x1F];
+ break;
+ case 2:
+ cpustate->amout = cpustate->reg[cpustate->modval & 0x1F];
+ break;
+ }
+
+ return 1;
+}
+
+static UINT32 am1RegisterIndirect(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->reg[cpustate->modval & 0x1F]);
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->reg[cpustate->modval & 0x1F]);
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F]);
+ break;
+ }
+
+ return 1;
+}
+
+static UINT32 bam1RegisterIndirect(v60_state *cpustate)
+{
+ cpustate->bamoffset = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F]);
+ return 1;
+}
+
+static UINT32 am1RegisterIndirectIndexed(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->reg[cpustate->modval2 & 0x1F] + cpustate->reg[cpustate->modval & 0x1F]);
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + cpustate->reg[cpustate->modval & 0x1F] * 2);
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + cpustate->reg[cpustate->modval & 0x1F] * 4);
+ break;
+ }
+
+ return 2;
+}
+
+static UINT32 bam1RegisterIndirectIndexed(v60_state *cpustate)
+{
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 2;
+}
+
+static UINT32 am1Autoincrement(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->reg[cpustate->modval & 0x1F]);
+ cpustate->reg[cpustate->modval & 0x1F]++;
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->reg[cpustate->modval & 0x1F]);
+ cpustate->reg[cpustate->modval & 0x1F] +=2;
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F]);
+ cpustate->reg[cpustate->modval & 0x1F] +=4;
+ break;
+ }
+
+ return 1;
+}
+
+static UINT32 bam1Autoincrement(v60_state *cpustate)
+{
+ cpustate->bamoffset = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F]);
+ switch (cpustate->moddim)
+ {
+ case 10:
+ cpustate->reg[cpustate->modval & 0x1F] +=1;
+ break;
+ case 11:
+ cpustate->reg[cpustate->modval & 0x1F] +=4;
+ break;
+ default:
+ fatalerror("CPU - BAM1 - 7");
+ break;
+ }
+ return 1;
+}
+
+static UINT32 am1Autodecrement(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->reg[cpustate->modval & 0x1F]--;
+ cpustate->amout = cpustate->program->read_byte(cpustate->reg[cpustate->modval & 0x1F]);
+ break;
+ case 1:
+ cpustate->reg[cpustate->modval & 0x1F]-=2;
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->reg[cpustate->modval & 0x1F]);
+ break;
+ case 2:
+ cpustate->reg[cpustate->modval & 0x1F]-=4;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F]);
+ break;
+ }
+
+ return 1;
+}
+
+static UINT32 bam1Autodecrement(v60_state *cpustate)
+{
+ cpustate->bamoffset = 0;
+ switch (cpustate->moddim)
+ {
+ case 10:
+ cpustate->reg[cpustate->modval & 0x1F]-=1;
+ break;
+ case 11:
+ cpustate->reg[cpustate->modval & 0x1F]-=4;
+ break;
+ default:
+ fatalerror("CPU - BAM1 - 7");
+ break;
+ }
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F]);
+ return 1;
+}
+
+static UINT32 am1Displacement8(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1));
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1));
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1));
+ break;
+ }
+
+ return 2;
+}
+
+static UINT32 bam1Displacement8(v60_state *cpustate)
+{
+ cpustate->bamoffset = cpustate->program->read_byte(cpustate->modadd + 1);
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 2;
+}
+
+
+static UINT32 am1Displacement16(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1));
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1));
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1));
+ break;
+ }
+
+ return 3;
+}
+
+static UINT32 bam1Displacement16(v60_state *cpustate)
+{
+ cpustate->bamoffset = OpRead16(cpustate, cpustate->modadd + 1);
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 3;
+}
+
+static UINT32 am1Displacement32(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1));
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1));
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1));
+ break;
+ }
+
+ return 5;
+}
+
+static UINT32 bam1Displacement32(v60_state *cpustate)
+{
+ cpustate->bamoffset = OpRead32(cpustate, cpustate->modadd + 1);
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 5;
+}
+
+static UINT32 am1DisplacementIndexed8(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->reg[cpustate->modval2 & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F]);
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 2);
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 4);
+ break;
+ }
+
+ return 3;
+}
+
+static UINT32 bam1DisplacementIndexed8(v60_state *cpustate)
+{
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 2) + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 3;
+}
+
+static UINT32 am1DisplacementIndexed16(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->reg[cpustate->modval2 & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F]);
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 2);
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 4);
+ break;
+ }
+
+ return 4;
+}
+
+static UINT32 bam1DisplacementIndexed16(v60_state *cpustate)
+{
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 2) + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 4;
+}
+
+static UINT32 am1DisplacementIndexed32(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->reg[cpustate->modval2 & 0x1F] + OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F]);
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 2);
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 4);
+ break;
+ }
+
+ return 6;
+}
+
+static UINT32 bam1DisplacementIndexed32(v60_state *cpustate)
+{
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + OpRead32(cpustate, cpustate->modadd + 2) + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 6;
+}
+
+
+static UINT32 am1PCDisplacement8(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1));
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1));
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1));
+ break;
+ }
+
+ return 2;
+}
+
+static UINT32 bam1PCDisplacement8(v60_state *cpustate)
+{
+ cpustate->bamoffset = OpRead8(cpustate, cpustate->modadd + 1);
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 2;
+}
+
+static UINT32 am1PCDisplacement16(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1));
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1));
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1));
+ break;
+ }
+
+ return 3;
+}
+
+static UINT32 bam1PCDisplacement16(v60_state *cpustate)
+{
+ cpustate->bamoffset = OpRead16(cpustate, cpustate->modadd + 1);
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 3;
+}
+
+static UINT32 am1PCDisplacement32(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1));
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1));
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1));
+ break;
+ }
+
+ return 5;
+}
+
+static UINT32 bam1PCDisplacement32(v60_state *cpustate)
+{
+ cpustate->bamoffset = OpRead32(cpustate, cpustate->modadd + 1);
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 5;
+}
+
+static UINT32 am1PCDisplacementIndexed8(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F]);
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 2);
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 4);
+ break;
+ }
+
+ return 3;
+}
+
+static UINT32 bam1PCDisplacementIndexed8(v60_state *cpustate)
+{
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 2) + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 3;
+}
+
+
+static UINT32 am1PCDisplacementIndexed16(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F]);
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 2);
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 4);
+ break;
+ }
+
+ return 4;
+}
+
+static UINT32 bam1PCDisplacementIndexed16(v60_state *cpustate)
+{
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 2) + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 4;
+}
+
+static UINT32 am1PCDisplacementIndexed32(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F]);
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 2);
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 4);
+ break;
+ }
+
+ return 6;
+}
+
+static UINT32 bam1PCDisplacementIndexed32(v60_state *cpustate)
+{
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 2) + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 6;
+}
+
+static UINT32 am1DisplacementIndirect8(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1)));
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1)));
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1)));
+ break;
+ }
+
+ return 2;
+}
+
+static UINT32 bam1DisplacementIndirect8(v60_state *cpustate)
+{
+ cpustate->bamoffset = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1)));
+ return 2;
+}
+
+static UINT32 am1DisplacementIndirect16(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1)));
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1)));
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1)));
+ break;
+ }
+
+ return 3;
+}
+
+static UINT32 bam1DisplacementIndirect16(v60_state *cpustate)
+{
+ cpustate->bamoffset = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1)));
+ return 3;
+}
+
+static UINT32 am1DisplacementIndirect32(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1)));
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1)));
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1)));
+ break;
+ }
+
+ return 5;
+}
+
+static UINT32 bam1DisplacementIndirect32(v60_state *cpustate)
+{
+ cpustate->bamoffset = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1)));
+ return 5;
+}
+
+static UINT32 am1DisplacementIndirectIndexed8(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F]);
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 2);
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 4);
+ break;
+ }
+
+ return 3;
+}
+
+static UINT32 bam1DisplacementIndirectIndexed8(v60_state *cpustate)
+{
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 2)) + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 3;
+}
+
+static UINT32 am1DisplacementIndirectIndexed16(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F]);
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 2);
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 4);
+ break;
+ }
+
+ return 4;
+}
+
+static UINT32 bam1DisplacementIndirectIndexed16(v60_state *cpustate)
+{
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 2)) + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 4;
+}
+
+static UINT32 am1DisplacementIndirectIndexed32(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F]);
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 2);
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 4);
+ break;
+ }
+
+ return 6;
+}
+
+static UINT32 bam1DisplacementIndirectIndexed32(v60_state *cpustate)
+{
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 6;
+}
+
+static UINT32 am1PCDisplacementIndirect8(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1)));
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1)));
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1)));
+ break;
+ }
+
+ return 2;
+}
+
+static UINT32 bam1PCDisplacementIndirect8(v60_state *cpustate)
+{
+ cpustate->bamoffset = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1)));
+ return 2;
+}
+
+static UINT32 am1PCDisplacementIndirect16(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1)));
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1)));
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1)));
+ break;
+ }
+
+ return 3;
+}
+
+static UINT32 bam1PCDisplacementIndirect16(v60_state *cpustate)
+{
+ cpustate->bamoffset = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1)));
+ return 3;
+}
+
+static UINT32 am1PCDisplacementIndirect32(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1)));
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1)));
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1)));
+ break;
+ }
+
+ return 5;
+}
+
+static UINT32 bam1PCDisplacementIndirect32(v60_state *cpustate)
+{
+ cpustate->bamoffset = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1)));
+ return 5;
+}
+
+static UINT32 am1PCDisplacementIndirectIndexed8(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F]);
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 2);
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 4);
+ break;
+ }
+
+ return 3;
+}
+
+static UINT32 bam1PCDisplacementIndirectIndexed8(v60_state *cpustate)
+{
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 2)) + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 3;
+}
+
+static UINT32 am1PCDisplacementIndirectIndexed16(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F]);
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 2);
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 4);
+ break;
+ }
+
+ return 4;
+}
+
+static UINT32 bam1PCDisplacementIndirectIndexed16(v60_state *cpustate)
+{
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 2)) + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 4;
+}
+
+static UINT32 am1PCDisplacementIndirectIndexed32(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F]);
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 2);
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 4);
+ break;
+ }
+
+ return 6;
+}
+
+static UINT32 bam1PCDisplacementIndirectIndexed32(v60_state *cpustate)
+{
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 6;
+}
+
+static UINT32 am1DoubleDisplacement8(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1)) + (INT8)OpRead8(cpustate, cpustate->modadd + 2));
+ break;
+
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1)) + (INT8)OpRead8(cpustate, cpustate->modadd + 2));
+ break;
+
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1)) + (INT8)OpRead8(cpustate, cpustate->modadd + 2));
+ break;
+ }
+
+ return 3;
+}
+
+static UINT32 bam1DoubleDisplacement8(v60_state *cpustate)
+{
+ cpustate->bamoffset = OpRead8(cpustate, cpustate->modadd + 2);
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1)) + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 3;
+}
+
+static UINT32 am1DoubleDisplacement16(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1)) + (INT16)OpRead16(cpustate, cpustate->modadd + 3));
+ break;
+
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1)) + (INT16)OpRead16(cpustate, cpustate->modadd + 3));
+ break;
+
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1)) + (INT16)OpRead16(cpustate, cpustate->modadd + 3));
+ break;
+ }
+
+ return 5;
+}
+
+static UINT32 bam1DoubleDisplacement16(v60_state *cpustate)
+{
+ cpustate->bamoffset = OpRead16(cpustate, cpustate->modadd + 3);
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1)) + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 5;
+}
+
+static UINT32 am1DoubleDisplacement32(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1)) + OpRead32(cpustate, cpustate->modadd + 5));
+ break;
+
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1)) + OpRead32(cpustate, cpustate->modadd + 5));
+ break;
+
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1)) + OpRead32(cpustate, cpustate->modadd + 5));
+ break;
+ }
+
+ return 9;
+}
+
+static UINT32 bam1DoubleDisplacement32(v60_state *cpustate)
+{
+ cpustate->bamoffset = OpRead32(cpustate, cpustate->modadd + 5);
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1)) + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 9;
+}
+
+static UINT32 am1PCDoubleDisplacement8(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1)) + (INT8)OpRead8(cpustate, cpustate->modadd + 2));
+ break;
+
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1)) + (INT8)OpRead8(cpustate, cpustate->modadd + 2));
+ break;
+
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1)) + (INT8)OpRead8(cpustate, cpustate->modadd + 2));
+ break;
+ }
+
+ return 3;
+}
+
+static UINT32 bam1PCDoubleDisplacement8(v60_state *cpustate)
+{
+ cpustate->bamoffset = OpRead8(cpustate, cpustate->modadd + 2);
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1)) + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 3;
+}
+
+static UINT32 am1PCDoubleDisplacement16(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1)) + (INT16)OpRead16(cpustate, cpustate->modadd + 3));
+ break;
+
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1)) + (INT16)OpRead16(cpustate, cpustate->modadd + 3));
+ break;
+
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1)) + (INT16)OpRead16(cpustate, cpustate->modadd + 3));
+ break;
+ }
+
+ return 5;
+}
+
+static UINT32 bam1PCDoubleDisplacement16(v60_state *cpustate)
+{
+ cpustate->bamoffset = OpRead16(cpustate, cpustate->modadd + 3);
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1)) + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 5;
+}
+
+
+static UINT32 am1PCDoubleDisplacement32(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1)) + OpRead32(cpustate, cpustate->modadd + 5));
+ break;
+
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1)) + OpRead32(cpustate, cpustate->modadd + 5));
+ break;
+
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1)) + OpRead32(cpustate, cpustate->modadd + 5));
+ break;
+ }
+
+ return 9;
+}
+
+static UINT32 bam1PCDoubleDisplacement32(v60_state *cpustate)
+{
+ cpustate->bamoffset = OpRead32(cpustate, cpustate->modadd + 5);
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1)) + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 9;
+}
+
+static UINT32 am1DirectAddress(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(OpRead32(cpustate, cpustate->modadd + 1));
+ break;
+
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(OpRead32(cpustate, cpustate->modadd + 1));
+ break;
+
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 1));
+ break;
+ }
+
+ return 5;
+}
+
+static UINT32 bam1DirectAddress(v60_state *cpustate)
+{
+ cpustate->bamoffset = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 1));
+ return 5;
+}
+
+static UINT32 am1DirectAddressIndexed(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F]);
+ break;
+
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 2);
+ break;
+
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 4);
+ break;
+ }
+
+ return 6;
+}
+
+static UINT32 bam1DirectAddressIndexed(v60_state *cpustate)
+{
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+ cpustate->amout = cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 2) + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 6;
+}
+
+static UINT32 am1DirectAddressDeferred(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 1)));
+ break;
+
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 1)));
+ break;
+
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 1)));
+ break;
+ }
+
+ return 5;
+}
+
+static UINT32 bam1DirectAddressDeferred(v60_state *cpustate)
+{
+ cpustate->bamoffset = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 1)));
+ return 5;
+}
+
+static UINT32 am1DirectAddressDeferredIndexed(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_byte(cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F]);
+ break;
+
+ case 1:
+ cpustate->amout = cpustate->program->read_word_unaligned(cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 2);
+ break;
+
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 4);
+ break;
+ }
+
+ return 6;
+}
+
+static UINT32 bam1DirectAddressDeferredIndexed(v60_state *cpustate)
+{
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->bamoffset / 8);
+ cpustate->bamoffset&=7;
+ return 6;
+}
+
+static UINT32 am1Immediate(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = OpRead8(cpustate, cpustate->modadd + 1);
+ return 2;
+
+ case 1:
+ cpustate->amout = OpRead16(cpustate, cpustate->modadd + 1);
+ return 3;
+
+ case 2:
+ cpustate->amout = OpRead32(cpustate, cpustate->modadd + 1);
+ return 5;
+ }
+
+ // It should not be here! Written to avoid warning
+ assert(0);
+ return 1;
+}
+
+static UINT32 am1ImmediateQuick(v60_state *cpustate)
+{
+ cpustate->amout = cpustate->modval & 0xF;
+ return 1;
+}
+
+
+
+
+// AM1 Tables (for ReadAM)
+// ***********************
+
+static UINT32 am1Error1(v60_state *cpustate)
+{
+ fatalerror("CPU - AM1 - 1 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 bam1Error1(v60_state *cpustate)
+{
+ fatalerror("CPU - BAM1 - 1 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 am1Error2(v60_state *cpustate)
+{
+ fatalerror("CPU - AM1 - 2 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 bam1Error2(v60_state *cpustate)
+{
+ fatalerror("CPU - BAM1 - 2 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+#ifdef UNUSED_FUNCTION
+static UINT32 am1Error3(v60_state *cpustate)
+{
+ fatalerror("CPU - AM1 - 3 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 bam1Error3(v60_state *cpustate)
+{
+ fatalerror("CPU - BAM1 - 3 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+#endif
+
+static UINT32 am1Error4(v60_state *cpustate)
+{
+ fatalerror("CPU - AM1 - 4 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 bam1Error4(v60_state *cpustate)
+{
+ fatalerror("CPU - BAM1 - 4 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 am1Error5(v60_state *cpustate)
+{
+ fatalerror("CPU - AM1 - 5 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 bam1Error5(v60_state *cpustate)
+{
+ fatalerror("CPU - BAM1 - 5 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 bam1Error6(v60_state *cpustate)
+{
+ fatalerror("CPU - BAM1 - 6 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 (*const AMTable1_G7a[16])(v60_state *) =
+{
+ am1PCDisplacementIndexed8,
+ am1PCDisplacementIndexed16,
+ am1PCDisplacementIndexed32,
+ am1DirectAddressIndexed,
+ am1Error5,
+ am1Error5,
+ am1Error5,
+ am1Error5,
+ am1PCDisplacementIndirectIndexed8,
+ am1PCDisplacementIndirectIndexed16,
+ am1PCDisplacementIndirectIndexed32,
+ am1DirectAddressDeferredIndexed,
+ am1Error5,
+ am1Error5,
+ am1Error5,
+ am1Error5
+};
+
+static UINT32 (*const BAMTable1_G7a[16])(v60_state *) =
+{
+ bam1PCDisplacementIndexed8,
+ bam1PCDisplacementIndexed16,
+ bam1PCDisplacementIndexed32,
+ bam1DirectAddressIndexed,
+ bam1Error5,
+ bam1Error5,
+ bam1Error5,
+ bam1Error5,
+ bam1PCDisplacementIndirectIndexed8,
+ bam1PCDisplacementIndirectIndexed16,
+ bam1PCDisplacementIndirectIndexed32,
+ bam1DirectAddressDeferredIndexed,
+ bam1Error5,
+ bam1Error5,
+ bam1Error5,
+ bam1Error5
+};
+
+
+static UINT32 am1Group7a(v60_state *cpustate)
+{
+ if (!(cpustate->modval2 & 0x10))
+ return am1Error4(cpustate);
+
+ return AMTable1_G7a[cpustate->modval2 & 0xF](cpustate);
+}
+
+static UINT32 bam1Group7a(v60_state *cpustate)
+{
+ if (!(cpustate->modval2 & 0x10))
+ return bam1Error4(cpustate);
+
+ return BAMTable1_G7a[cpustate->modval2 & 0xF](cpustate);
+}
+
+static UINT32 (*const AMTable1_G7[32])(v60_state *) =
+{
+ am1ImmediateQuick,
+ am1ImmediateQuick,
+ am1ImmediateQuick,
+ am1ImmediateQuick,
+ am1ImmediateQuick,
+ am1ImmediateQuick,
+ am1ImmediateQuick,
+ am1ImmediateQuick,
+ am1ImmediateQuick,
+ am1ImmediateQuick,
+ am1ImmediateQuick,
+ am1ImmediateQuick,
+ am1ImmediateQuick,
+ am1ImmediateQuick,
+ am1ImmediateQuick,
+ am1ImmediateQuick,
+ am1PCDisplacement8,
+ am1PCDisplacement16,
+ am1PCDisplacement32,
+ am1DirectAddress,
+ am1Immediate,
+ am1Error2,
+ am1Error2,
+ am1Error2,
+ am1PCDisplacementIndirect8,
+ am1PCDisplacementIndirect16,
+ am1PCDisplacementIndirect32,
+ am1DirectAddressDeferred,
+ am1PCDoubleDisplacement8,
+ am1PCDoubleDisplacement16,
+ am1PCDoubleDisplacement32,
+ am1Error2
+};
+
+static UINT32 (*const BAMTable1_G7[32])(v60_state *) =
+{
+ bam1Error6,
+ bam1Error6,
+ bam1Error6,
+ bam1Error6,
+ bam1Error6,
+ bam1Error6,
+ bam1Error6,
+ bam1Error6,
+ bam1Error6,
+ bam1Error6,
+ bam1Error6,
+ bam1Error6,
+ bam1Error6,
+ bam1Error6,
+ bam1Error6,
+ bam1Error6,
+ bam1PCDisplacement8,
+ bam1PCDisplacement16,
+ bam1PCDisplacement32,
+ bam1DirectAddress,
+ bam1Error6,
+ bam1Error2,
+ bam1Error2,
+ bam1Error2,
+ bam1PCDisplacementIndirect8,
+ bam1PCDisplacementIndirect16,
+ bam1PCDisplacementIndirect32,
+ bam1DirectAddressDeferred,
+ bam1PCDoubleDisplacement8,
+ bam1PCDoubleDisplacement16,
+ bam1PCDoubleDisplacement32,
+ bam1Error2
+};
+
+
+
+static UINT32 (*const AMTable1_G6[8])(v60_state *) =
+{
+ am1DisplacementIndexed8,
+ am1DisplacementIndexed16,
+ am1DisplacementIndexed32,
+ am1RegisterIndirectIndexed,
+ am1DisplacementIndirectIndexed8,
+ am1DisplacementIndirectIndexed16,
+ am1DisplacementIndirectIndexed32,
+ am1Group7a
+};
+
+static UINT32 (*const BAMTable1_G6[8])(v60_state *) =
+{
+ bam1DisplacementIndexed8,
+ bam1DisplacementIndexed16,
+ bam1DisplacementIndexed32,
+ bam1RegisterIndirectIndexed,
+ bam1DisplacementIndirectIndexed8,
+ bam1DisplacementIndirectIndexed16,
+ bam1DisplacementIndirectIndexed32,
+ bam1Group7a
+};
+
+
+static UINT32 am1Group6(v60_state *cpustate)
+{
+ cpustate->modval2 = OpRead8(cpustate, cpustate->modadd + 1);
+ return AMTable1_G6[cpustate->modval2 >> 5](cpustate);
+}
+
+static UINT32 bam1Group6(v60_state *cpustate)
+{
+ cpustate->modval2 = OpRead8(cpustate, cpustate->modadd + 1);
+ return BAMTable1_G6[cpustate->modval2 >> 5](cpustate);
+}
+
+
+static UINT32 am1Group7(v60_state *cpustate)
+{
+ return AMTable1_G7[cpustate->modval & 0x1F](cpustate);
+}
+
+static UINT32 bam1Group7(v60_state *cpustate)
+{
+ return BAMTable1_G7[cpustate->modval & 0x1F](cpustate);
+}
+
+static UINT32 (*const AMTable1[2][8])(v60_state *) =
+{
+ {
+ am1Displacement8,
+ am1Displacement16,
+ am1Displacement32,
+ am1RegisterIndirect,
+ am1DisplacementIndirect8,
+ am1DisplacementIndirect16,
+ am1DisplacementIndirect32,
+ am1Group7
+ },
+
+ {
+ am1DoubleDisplacement8,
+ am1DoubleDisplacement16,
+ am1DoubleDisplacement32,
+ am1Register,
+ am1Autoincrement,
+ am1Autodecrement,
+ am1Group6,
+ am1Error1
+ }
+};
+
+
+static UINT32 (*const BAMTable1[2][8])(v60_state *) =
+{
+ {
+ bam1Displacement8,
+ bam1Displacement16,
+ bam1Displacement32,
+ bam1RegisterIndirect,
+ bam1DisplacementIndirect8,
+ bam1DisplacementIndirect16,
+ bam1DisplacementIndirect32,
+ bam1Group7
+ },
+
+ {
+ bam1DoubleDisplacement8,
+ bam1DoubleDisplacement16,
+ bam1DoubleDisplacement32,
+ bam1Error6,
+ bam1Autoincrement,
+ bam1Autodecrement,
+ bam1Group6,
+ bam1Error1
+ }
+};
+
+
+
+
diff --git a/trunk/src/emu/cpu/v60/am2.c b/trunk/src/emu/cpu/v60/am2.c
new file mode 100644
index 00000000000..bf9367d5f75
--- /dev/null
+++ b/trunk/src/emu/cpu/v60/am2.c
@@ -0,0 +1,1256 @@
+
+// AM2 Functions (for ReadAMAddress)
+// *********************************
+
+static UINT32 am2Register(v60_state *cpustate)
+{
+ cpustate->amflag = 1;
+ cpustate->amout = cpustate->modval & 0x1F;
+ return 1;
+}
+
+static UINT32 am2RegisterIndirect(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->reg[cpustate->modval & 0x1F];
+ return 1;
+}
+
+static UINT32 bam2RegisterIndirect(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->reg[cpustate->modval & 0x1F];
+ cpustate->bamoffset = 0;
+ return 1;
+}
+
+static UINT32 am2RegisterIndirectIndexed(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->reg[cpustate->modval2 & 0x1F] + cpustate->reg[cpustate->modval & 0x1F];
+ break;
+ case 1:
+ cpustate->amout = cpustate->reg[cpustate->modval2 & 0x1F] + cpustate->reg[cpustate->modval & 0x1F] * 2;
+ break;
+ case 2:
+ cpustate->amout = cpustate->reg[cpustate->modval2 & 0x1F] + cpustate->reg[cpustate->modval & 0x1F] * 4;
+ break;
+ case 3:
+ cpustate->amout = cpustate->reg[cpustate->modval2 & 0x1F] + cpustate->reg[cpustate->modval & 0x1F] * 8;
+ break;
+ }
+
+ return 2;
+}
+
+static UINT32 bam2RegisterIndirectIndexed(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->reg[cpustate->modval2 & 0x1F];
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+ return 2;
+}
+
+static UINT32 am2Autoincrement(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->reg[cpustate->modval & 0x1F];
+
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->reg[cpustate->modval & 0x1F] += 1;
+ break;
+ case 1:
+ cpustate->reg[cpustate->modval & 0x1F] += 2;
+ break;
+ case 2:
+ cpustate->reg[cpustate->modval & 0x1F] += 4;
+ break;
+ case 3:
+ cpustate->reg[cpustate->modval & 0x1F] += 8;
+ break;
+ }
+
+ return 1;
+}
+
+static UINT32 bam2Autoincrement(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->reg[cpustate->modval & 0x1F];
+ cpustate->bamoffset = 0;
+
+ switch (cpustate->moddim)
+ {
+ case 10:
+ cpustate->reg[cpustate->modval & 0x1F] +=1;
+ break;
+ case 11:
+ cpustate->reg[cpustate->modval & 0x1F] +=4;
+ break;
+ default:
+ fatalerror("CPU - AM2 - 7 (t0 cpustate->PC=%x)", cpustate->PC);
+ break;
+ }
+
+ return 1;
+}
+
+static UINT32 am2Autodecrement(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->reg[cpustate->modval & 0x1F] -= 1;
+ break;
+ case 1:
+ cpustate->reg[cpustate->modval & 0x1F] -= 2;
+ break;
+ case 2:
+ cpustate->reg[cpustate->modval & 0x1F] -= 4;
+ break;
+ case 3:
+ cpustate->reg[cpustate->modval & 0x1F] -= 8;
+ break;
+ }
+
+ cpustate->amout = cpustate->reg[cpustate->modval & 0x1F];
+ return 1;
+}
+
+static UINT32 bam2Autodecrement(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->bamoffset = 0;
+
+ switch (cpustate->moddim)
+ {
+ case 10:
+ cpustate->reg[cpustate->modval & 0x1F]-=1;
+ break;
+ case 11:
+ cpustate->reg[cpustate->modval & 0x1F]-=4;
+ break;
+ default:
+ fatalerror("CPU - BAM2 - 7 (cpustate->PC=%06x)", cpustate->PC);
+ break;
+ }
+
+ cpustate->amout = cpustate->reg[cpustate->modval & 0x1F];
+ return 1;
+}
+
+
+static UINT32 am2Displacement8(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1);
+
+ return 2;
+}
+
+static UINT32 bam2Displacement8(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->reg[cpustate->modval & 0x1F];
+ cpustate->bamoffset = (INT8)OpRead8(cpustate, cpustate->modadd + 1);
+
+ return 2;
+}
+
+static UINT32 am2Displacement16(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1);
+
+ return 3;
+}
+
+static UINT32 bam2Displacement16(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->reg[cpustate->modval & 0x1F];
+ cpustate->bamoffset = (INT16)OpRead16(cpustate, cpustate->modadd + 1);
+
+ return 3;
+}
+
+static UINT32 am2Displacement32(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1);
+
+ return 5;
+}
+
+static UINT32 bam2Displacement32(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->reg[cpustate->modval & 0x1F];
+ cpustate->bamoffset = OpRead32(cpustate, cpustate->modadd + 1);
+
+ return 5;
+}
+
+static UINT32 am2DisplacementIndexed8(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->reg[cpustate->modval2 & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F];
+ break;
+ case 1:
+ cpustate->amout = cpustate->reg[cpustate->modval2 & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 2;
+ break;
+ case 2:
+ cpustate->amout = cpustate->reg[cpustate->modval2 & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 4;
+ break;
+ case 3:
+ cpustate->amout = cpustate->reg[cpustate->modval2 & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 8;
+ break;
+ }
+
+ return 3;
+}
+
+static UINT32 bam2DisplacementIndexed8(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->reg[cpustate->modval2 & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 2);
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+
+ return 3;
+}
+
+static UINT32 am2DisplacementIndexed16(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->reg[cpustate->modval2 & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F];
+ break;
+ case 1:
+ cpustate->amout = cpustate->reg[cpustate->modval2 & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 2;
+ break;
+ case 2:
+ cpustate->amout = cpustate->reg[cpustate->modval2 & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 4;
+ break;
+ case 3:
+ cpustate->amout = cpustate->reg[cpustate->modval2 & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 8;
+ break;
+ }
+
+ return 4;
+}
+
+static UINT32 bam2DisplacementIndexed16(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->reg[cpustate->modval2 & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 2);
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+
+ return 4;
+}
+
+static UINT32 am2DisplacementIndexed32(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->reg[cpustate->modval2 & 0x1F] + OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F];
+ break;
+ case 1:
+ cpustate->amout = cpustate->reg[cpustate->modval2 & 0x1F] + OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 2;
+ break;
+ case 2:
+ cpustate->amout = cpustate->reg[cpustate->modval2 & 0x1F] + OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 4;
+ break;
+ case 3:
+ cpustate->amout = cpustate->reg[cpustate->modval2 & 0x1F] + OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 8;
+ break;
+ }
+
+ return 6;
+}
+
+static UINT32 bam2DisplacementIndexed32(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->reg[cpustate->modval2 & 0x1F] + OpRead32(cpustate, cpustate->modadd + 2);
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+
+ return 6;
+}
+
+static UINT32 am2PCDisplacement8(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1);
+
+ return 2;
+}
+
+static UINT32 bam2PCDisplacement8(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->PC;
+ cpustate->bamoffset = (INT8)OpRead8(cpustate, cpustate->modadd + 1);
+
+ return 2;
+}
+
+static UINT32 am2PCDisplacement16(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1);
+
+ return 3;
+}
+
+static UINT32 bam2PCDisplacement16(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->PC;
+ cpustate->bamoffset = (INT16)OpRead16(cpustate, cpustate->modadd + 1);
+
+ return 3;
+}
+
+static UINT32 am2PCDisplacement32(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1);
+
+ return 5;
+}
+
+static UINT32 bam2PCDisplacement32(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->PC;
+ cpustate->bamoffset = OpRead32(cpustate, cpustate->modadd + 1);
+
+ return 5;
+}
+
+
+static UINT32 am2PCDisplacementIndexed8(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F];
+ break;
+ case 1:
+ cpustate->amout = cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 2;
+ break;
+ case 2:
+ cpustate->amout = cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 4;
+ break;
+ case 3:
+ cpustate->amout = cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 8;
+ break;
+ }
+
+ return 3;
+}
+
+static UINT32 bam2PCDisplacementIndexed8(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 2);
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+
+ return 3;
+}
+
+static UINT32 am2PCDisplacementIndexed16(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F];
+ break;
+ case 1:
+ cpustate->amout = cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 2;
+ break;
+ case 2:
+ cpustate->amout = cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 4;
+ break;
+ case 3:
+ cpustate->amout = cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 8;
+ break;
+ }
+
+ return 4;
+}
+
+static UINT32 bam2PCDisplacementIndexed16(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 2);
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+
+ return 4;
+}
+
+static UINT32 am2PCDisplacementIndexed32(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->PC + OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F];
+ break;
+ case 1:
+ cpustate->amout = cpustate->PC + OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 2;
+ break;
+ case 2:
+ cpustate->amout = cpustate->PC + OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 4;
+ break;
+ case 3:
+ cpustate->amout = cpustate->PC + OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 8;
+ break;
+ }
+
+ return 6;
+}
+
+static UINT32 bam2PCDisplacementIndexed32(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->PC + OpRead32(cpustate, cpustate->modadd + 2);
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+
+ return 6;
+}
+
+static UINT32 am2DisplacementIndirect8(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1));
+
+ return 2;
+}
+
+static UINT32 bam2DisplacementIndirect8(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1));
+ cpustate->bamoffset = 0;
+ return 2;
+}
+
+static UINT32 am2DisplacementIndirect16(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1));
+
+ return 3;
+}
+
+static UINT32 bam2DisplacementIndirect16(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1));
+ cpustate->bamoffset = 0;
+ return 3;
+}
+
+static UINT32 am2DisplacementIndirect32(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1));
+
+ return 5;
+}
+
+static UINT32 bam2DisplacementIndirect32(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1));
+ cpustate->bamoffset = 0;
+
+ return 5;
+}
+
+static UINT32 am2DisplacementIndirectIndexed8(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F];
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 2;
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 4;
+ break;
+ case 3:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 8;
+ break;
+ }
+
+ return 3;
+}
+
+static UINT32 bam2DisplacementIndirectIndexed8(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 2));
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+
+ return 3;
+}
+
+static UINT32 am2DisplacementIndirectIndexed16(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F];
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 2;
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 4;
+ break;
+ case 3:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 8;
+ break;
+ }
+
+ return 4;
+}
+
+static UINT32 bam2DisplacementIndirectIndexed16(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 2));
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+
+ return 4;
+}
+
+static UINT32 am2DisplacementIndirectIndexed32(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F];
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 2;
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 4;
+ break;
+ case 3:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 8;
+ break;
+ }
+
+ return 6;
+}
+
+static UINT32 bam2DisplacementIndirectIndexed32(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + OpRead32(cpustate, cpustate->modadd + 2));
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+
+ return 6;
+}
+
+static UINT32 am2PCDisplacementIndirect8(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1));
+
+ return 2;
+}
+
+static UINT32 bam2PCDisplacementIndirect8(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1));
+ cpustate->bamoffset = 0;
+
+ return 2;
+}
+
+static UINT32 am2PCDisplacementIndirect16(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1));
+
+ return 3;
+}
+
+static UINT32 bam2PCDisplacementIndirect16(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1));
+ cpustate->bamoffset = 0;
+
+ return 3;
+}
+
+static UINT32 am2PCDisplacementIndirect32(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1));
+
+ return 5;
+}
+
+static UINT32 bam2PCDisplacementIndirect32(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1));
+ cpustate->bamoffset = 0;
+
+ return 5;
+}
+
+static UINT32 am2PCDisplacementIndirectIndexed8(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F];
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 2;
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 4;
+ break;
+ case 3:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 8;
+ break;
+ }
+
+ return 3;
+}
+
+static UINT32 bam2PCDisplacementIndirectIndexed8(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 2));
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+
+ return 3;
+}
+
+static UINT32 am2PCDisplacementIndirectIndexed16(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F];
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 2;
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 4;
+ break;
+ case 3:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 8;
+ break;
+ }
+
+ return 4;
+}
+
+
+static UINT32 bam2PCDisplacementIndirectIndexed16(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 2));
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+
+ return 4;
+}
+
+
+static UINT32 am2PCDisplacementIndirectIndexed32(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F];
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 2;
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 4;
+ break;
+ case 3:
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 8;
+ break;
+ }
+
+ return 6;
+}
+
+static UINT32 bam2PCDisplacementIndirectIndexed32(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 2));
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+
+ return 6;
+}
+
+static UINT32 am2DoubleDisplacement8(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1)) + (INT8)OpRead8(cpustate, cpustate->modadd + 2);
+
+ return 3;
+}
+
+static UINT32 bam2DoubleDisplacement8(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1));
+ cpustate->bamoffset = (INT8)OpRead8(cpustate, cpustate->modadd + 2);
+
+ return 3;
+}
+
+static UINT32 am2DoubleDisplacement16(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1)) + (INT16)OpRead16(cpustate, cpustate->modadd + 3);
+
+ return 5;
+}
+
+static UINT32 bam2DoubleDisplacement16(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1));
+ cpustate->bamoffset = (INT8)OpRead8(cpustate, cpustate->modadd + 3);
+
+ return 5;
+}
+
+static UINT32 am2DoubleDisplacement32(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1)) + OpRead32(cpustate, cpustate->modadd + 5);
+
+ return 9;
+}
+
+static UINT32 bam2DoubleDisplacement32(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1));
+ cpustate->bamoffset = OpRead32(cpustate, cpustate->modadd + 5);
+
+ return 9;
+}
+
+
+static UINT32 am2PCDoubleDisplacement8(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1)) + (INT8)OpRead8(cpustate, cpustate->modadd + 2);
+
+ return 3;
+}
+
+static UINT32 bam2PCDoubleDisplacement8(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1));
+ cpustate->bamoffset = (INT8)OpRead8(cpustate, cpustate->modadd + 2);
+
+ return 3;
+}
+
+static UINT32 am2PCDoubleDisplacement16(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1)) + (INT16)OpRead16(cpustate, cpustate->modadd + 3);
+
+ return 5;
+}
+
+static UINT32 bam2PCDoubleDisplacement16(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1));
+ cpustate->bamoffset = (INT8)OpRead8(cpustate, cpustate->modadd + 3);
+
+ return 5;
+}
+
+static UINT32 am2PCDoubleDisplacement32(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1)) + OpRead32(cpustate, cpustate->modadd + 5);
+
+ return 9;
+}
+
+static UINT32 bam2PCDoubleDisplacement32(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1));
+ cpustate->bamoffset = OpRead32(cpustate, cpustate->modadd + 5);
+
+ return 9;
+}
+
+static UINT32 am2DirectAddress(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = OpRead32(cpustate, cpustate->modadd + 1);
+
+ return 5;
+}
+
+static UINT32 bam2DirectAddress(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = OpRead32(cpustate, cpustate->modadd + 1);
+ cpustate->bamoffset = 0;
+
+ return 5;
+}
+
+static UINT32 am2DirectAddressIndexed(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F];
+ break;
+ case 1:
+ cpustate->amout = OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 2;
+ break;
+ case 2:
+ cpustate->amout = OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 4;
+ break;
+ case 3:
+ cpustate->amout = OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 8;
+ break;
+ }
+
+ return 6;
+}
+
+static UINT32 bam2DirectAddressIndexed(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = OpRead32(cpustate, cpustate->modadd + 2);
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+
+ return 6;
+}
+
+static UINT32 am2DirectAddressDeferred(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 1));
+
+ return 5;
+}
+
+static UINT32 bam2DirectAddressDeferred(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 1));
+ cpustate->bamoffset = 0;
+
+ return 5;
+}
+
+static UINT32 am2DirectAddressDeferredIndexed(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->amout = cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F];
+ break;
+ case 1:
+ cpustate->amout = cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 2;
+ break;
+ case 2:
+ cpustate->amout = cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 4;
+ break;
+ case 3:
+ cpustate->amout = cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 8;
+ break;
+ }
+
+ return 6;
+}
+
+static UINT32 bam2DirectAddressDeferredIndexed(v60_state *cpustate)
+{
+ cpustate->amflag = 0;
+ cpustate->amout = cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 2));
+ cpustate->bamoffset = cpustate->reg[cpustate->modval & 0x1F];
+
+ return 6;
+}
+
+static UINT32 am2Immediate(v60_state *cpustate)
+{
+ // ignore LDPR
+ return am1Immediate(cpustate);
+}
+
+static UINT32 am2ImmediateQuick(v60_state *cpustate)
+{
+ // ignore LDPR
+ return am1ImmediateQuick(cpustate);
+}
+
+
+// AM2 Tables (for ReadAMAddress)
+// ******************************
+
+static UINT32 am2Error1(v60_state *cpustate)
+{
+ fatalerror("CPU - AM2 - 1 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 am2Error2(v60_state *cpustate)
+{
+ fatalerror("CPU - AM2 - 2 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+#ifdef UNUSED_FUNCTION
+static UINT32 am2Error3(v60_state *cpustate)
+{
+ fatalerror("CPU - AM2 - 3 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+#endif
+
+static UINT32 am2Error4(v60_state *cpustate)
+{
+ fatalerror("CPU - AM2 - 4 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 am2Error5(v60_state *cpustate)
+{
+ fatalerror("CPU - AM2 - 5 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 bam2Error1(v60_state *cpustate)
+{
+ fatalerror("CPU - BAM2 - 1 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 bam2Error2(v60_state *cpustate)
+{
+ fatalerror("CPU - BAM2 - 2 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+#ifdef UNUSED_FUNCTION
+static UINT32 bam2Error3(v60_state *cpustate)
+{
+ fatalerror("CPU - BAM2 - 3 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+#endif
+
+static UINT32 bam2Error4(v60_state *cpustate)
+{
+ fatalerror("CPU - BAM2 - 4 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 bam2Error5(v60_state *cpustate)
+{
+ fatalerror("CPU - BAM2 - 5 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 bam2Error6(v60_state *cpustate)
+{
+ fatalerror("CPU - BAM2 - 6 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+
+static UINT32 (*const AMTable2_G7a[16])(v60_state *) =
+{
+ am2PCDisplacementIndexed8,
+ am2PCDisplacementIndexed16,
+ am2PCDisplacementIndexed32,
+ am2DirectAddressIndexed,
+ am2Error5,
+ am2Error5,
+ am2Error5,
+ am2Error5,
+ am2PCDisplacementIndirectIndexed8,
+ am2PCDisplacementIndirectIndexed16,
+ am2PCDisplacementIndirectIndexed32,
+ am2DirectAddressDeferredIndexed,
+ am2Error5,
+ am2Error5,
+ am2Error5,
+ am2Error5
+};
+
+static UINT32 (*const BAMTable2_G7a[16])(v60_state *) =
+{
+ bam2PCDisplacementIndexed8,
+ bam2PCDisplacementIndexed16,
+ bam2PCDisplacementIndexed32,
+ bam2DirectAddressIndexed,
+ bam2Error5,
+ bam2Error5,
+ bam2Error5,
+ bam2Error5,
+ bam2PCDisplacementIndirectIndexed8,
+ bam2PCDisplacementIndirectIndexed16,
+ bam2PCDisplacementIndirectIndexed32,
+ bam2DirectAddressDeferredIndexed,
+ bam2Error5,
+ bam2Error5,
+ bam2Error5,
+ bam2Error5
+};
+
+static UINT32 am2Group7a(v60_state *cpustate)
+{
+ if (!(cpustate->modval2 & 0x10))
+ return am2Error4(cpustate);
+
+ return AMTable2_G7a[cpustate->modval2 & 0xF](cpustate);
+}
+
+static UINT32 bam2Group7a(v60_state *cpustate)
+{
+ if (!(cpustate->modval2 & 0x10))
+ return bam2Error4(cpustate);
+
+ return BAMTable2_G7a[cpustate->modval2 & 0xF](cpustate);
+}
+
+static UINT32 (*const AMTable2_G7[32])(v60_state *) =
+{
+ am2ImmediateQuick,
+ am2ImmediateQuick,
+ am2ImmediateQuick,
+ am2ImmediateQuick,
+ am2ImmediateQuick,
+ am2ImmediateQuick,
+ am2ImmediateQuick,
+ am2ImmediateQuick,
+ am2ImmediateQuick,
+ am2ImmediateQuick,
+ am2ImmediateQuick,
+ am2ImmediateQuick,
+ am2ImmediateQuick,
+ am2ImmediateQuick,
+ am2ImmediateQuick,
+ am2ImmediateQuick,
+ am2PCDisplacement8,
+ am2PCDisplacement16,
+ am2PCDisplacement32,
+ am2DirectAddress,
+ am2Immediate,
+ am2Error2,
+ am2Error2,
+ am2Error2,
+ am2PCDisplacementIndirect8,
+ am2PCDisplacementIndirect16,
+ am2PCDisplacementIndirect32,
+ am2DirectAddressDeferred,
+ am2PCDoubleDisplacement8,
+ am2PCDoubleDisplacement16,
+ am2PCDoubleDisplacement32,
+ am2Error2
+};
+
+static UINT32 (*const BAMTable2_G7[32])(v60_state *) =
+{
+ bam2Error6,
+ bam2Error6,
+ bam2Error6,
+ bam2Error6,
+ bam2Error6,
+ bam2Error6,
+ bam2Error6,
+ bam2Error6,
+ bam2Error6,
+ bam2Error6,
+ bam2Error6,
+ bam2Error6,
+ bam2Error6,
+ bam2Error6,
+ bam2Error6,
+ bam2Error6,
+ bam2PCDisplacement8,
+ bam2PCDisplacement16,
+ bam2PCDisplacement32,
+ bam2DirectAddress,
+ bam2Error6,
+ bam2Error2,
+ bam2Error2,
+ bam2Error2,
+ bam2PCDisplacementIndirect8,
+ bam2PCDisplacementIndirect16,
+ bam2PCDisplacementIndirect32,
+ bam2DirectAddressDeferred,
+ bam2PCDoubleDisplacement8,
+ bam2PCDoubleDisplacement16,
+ bam2PCDoubleDisplacement32,
+ bam2Error2
+};
+
+static UINT32 (*const AMTable2_G6[8])(v60_state *) =
+{
+ am2DisplacementIndexed8,
+ am2DisplacementIndexed16,
+ am2DisplacementIndexed32,
+ am2RegisterIndirectIndexed,
+ am2DisplacementIndirectIndexed8,
+ am2DisplacementIndirectIndexed16,
+ am2DisplacementIndirectIndexed32,
+ am2Group7a
+};
+
+static UINT32 (*const BAMTable2_G6[8])(v60_state *) =
+{
+ bam2DisplacementIndexed8,
+ bam2DisplacementIndexed16,
+ bam2DisplacementIndexed32,
+ bam2RegisterIndirectIndexed,
+ bam2DisplacementIndirectIndexed8,
+ bam2DisplacementIndirectIndexed16,
+ bam2DisplacementIndirectIndexed32,
+ bam2Group7a
+};
+
+
+
+
+static UINT32 am2Group6(v60_state *cpustate)
+{
+ cpustate->modval2 = OpRead8(cpustate, cpustate->modadd + 1);
+ return AMTable2_G6[cpustate->modval2 >> 5](cpustate);
+}
+static UINT32 bam2Group6(v60_state *cpustate)
+{
+ cpustate->modval2 = OpRead8(cpustate, cpustate->modadd + 1);
+ return BAMTable2_G6[cpustate->modval2 >> 5](cpustate);
+}
+
+static UINT32 am2Group7(v60_state *cpustate)
+{
+ return AMTable2_G7[cpustate->modval & 0x1F](cpustate);
+}
+static UINT32 bam2Group7(v60_state *cpustate)
+{
+ return BAMTable2_G7[cpustate->modval & 0x1F](cpustate);
+}
+
+
+static UINT32 (*const AMTable2[2][8])(v60_state *) =
+{
+ {
+ am2Displacement8,
+ am2Displacement16,
+ am2Displacement32,
+ am2RegisterIndirect,
+ am2DisplacementIndirect8,
+ am2DisplacementIndirect16,
+ am2DisplacementIndirect32,
+ am2Group7
+ },
+
+ {
+ am2DoubleDisplacement8,
+ am2DoubleDisplacement16,
+ am2DoubleDisplacement32,
+ am2Register,
+ am2Autoincrement,
+ am2Autodecrement,
+ am2Group6,
+ am2Error1
+ }
+};
+
+static UINT32 (*const BAMTable2[2][8])(v60_state *) =
+{
+ {
+ bam2Displacement8,
+ bam2Displacement16,
+ bam2Displacement32,
+ bam2RegisterIndirect,
+ bam2DisplacementIndirect8,
+ bam2DisplacementIndirect16,
+ bam2DisplacementIndirect32,
+ bam2Group7
+ },
+
+ {
+ bam2DoubleDisplacement8,
+ bam2DoubleDisplacement16,
+ bam2DoubleDisplacement32,
+ bam2Error6,
+ bam2Autoincrement,
+ bam2Autodecrement,
+ bam2Group6,
+ bam2Error1
+ }
+};
+
+
+
+
diff --git a/trunk/src/emu/cpu/v60/am3.c b/trunk/src/emu/cpu/v60/am3.c
new file mode 100644
index 00000000000..ca69f092b62
--- /dev/null
+++ b/trunk/src/emu/cpu/v60/am3.c
@@ -0,0 +1,887 @@
+
+// AM3 Functions (for ReadAM)
+// **************************
+
+static UINT32 am3Register(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ SETREG8(cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalb);
+ break;
+ case 1:
+ SETREG16(cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->reg[cpustate->modval & 0x1F] = cpustate->modwritevalw;
+ break;
+ }
+
+ return 1;
+}
+
+static UINT32 am3RegisterIndirect(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalw);
+ break;
+ }
+
+ return 1;
+}
+
+static UINT32 am3RegisterIndirectIndexed(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->reg[cpustate->modval2 & 0x1F] + cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + cpustate->reg[cpustate->modval & 0x1F] * 2, cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + cpustate->reg[cpustate->modval & 0x1F] * 4, cpustate->modwritevalw);
+ break;
+ }
+
+ return 2;
+}
+
+static UINT32 am3Autoincrement(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalb);
+ cpustate->reg[cpustate->modval & 0x1F] += 1;
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalh);
+ cpustate->reg[cpustate->modval & 0x1F] += 2;
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalw);
+ cpustate->reg[cpustate->modval & 0x1F] += 4;
+ break;
+ }
+
+ return 1;
+}
+
+static UINT32 am3Autodecrement(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->reg[cpustate->modval & 0x1F] -= 1;
+ cpustate->program->write_byte(cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->reg[cpustate->modval & 0x1F] -= 2;
+ cpustate->program->write_word_unaligned(cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->reg[cpustate->modval & 0x1F] -= 4;
+ cpustate->program->write_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalw);
+ break;
+ }
+
+ return 1;
+}
+
+static UINT32 am3Displacement8(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1), cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1), cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1), cpustate->modwritevalw);
+ break;
+ }
+
+ return 2;
+}
+
+static UINT32 am3Displacement16(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1), cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1), cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1), cpustate->modwritevalw);
+ break;
+ }
+
+ return 3;
+}
+
+static UINT32 am3Displacement32(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1), cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1), cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1), cpustate->modwritevalw);
+ break;
+ }
+
+ return 5;
+}
+
+
+static UINT32 am3DisplacementIndexed8(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->reg[cpustate->modval2 & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 2, cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 4, cpustate->modwritevalw);
+ break;
+ }
+
+ return 3;
+}
+
+static UINT32 am3DisplacementIndexed16(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->reg[cpustate->modval2 & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 2, cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 4, cpustate->modwritevalw);
+ break;
+ }
+
+ return 4;
+}
+
+static UINT32 am3DisplacementIndexed32(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->reg[cpustate->modval2 & 0x1F] + OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 2, cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 4, cpustate->modwritevalw);
+ break;
+ }
+
+ return 6;
+}
+
+
+static UINT32 am3PCDisplacement8(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1), cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1), cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1), cpustate->modwritevalw);
+ break;
+ }
+
+ return 2;
+}
+
+static UINT32 am3PCDisplacement16(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1), cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1), cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1), cpustate->modwritevalw);
+ break;
+ }
+
+ return 3;
+}
+
+static UINT32 am3PCDisplacement32(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1), cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1), cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1), cpustate->modwritevalw);
+ break;
+ }
+
+ return 5;
+}
+
+static UINT32 am3PCDisplacementIndexed8(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 2, cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 4, cpustate->modwritevalw);
+ break;
+ }
+
+ return 3;
+}
+
+static UINT32 am3PCDisplacementIndexed16(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 2, cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 4, cpustate->modwritevalw);
+ break;
+ }
+
+ return 4;
+}
+
+static UINT32 am3PCDisplacementIndexed32(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 2, cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 4, cpustate->modwritevalw);
+ break;
+ }
+
+ return 6;
+}
+
+static UINT32 am3DisplacementIndirect8(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1)), cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1)), cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1)), cpustate->modwritevalw);
+ break;
+ }
+
+ return 2;
+}
+
+static UINT32 am3DisplacementIndirect16(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1)), cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1)), cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1)), cpustate->modwritevalw);
+ break;
+ }
+
+ return 3;
+}
+
+static UINT32 am3DisplacementIndirect32(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1)), cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1)), cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1)), cpustate->modwritevalw);
+ break;
+ }
+
+ return 5;
+}
+
+
+static UINT32 am3DisplacementIndirectIndexed8(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 2, cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 4, cpustate->modwritevalw);
+ break;
+ }
+
+ return 3;
+}
+
+static UINT32 am3DisplacementIndirectIndexed16(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 2, cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 4, cpustate->modwritevalw);
+ break;
+ }
+
+ return 4;
+}
+
+static UINT32 am3DisplacementIndirectIndexed32(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 2, cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval2 & 0x1F] + OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 4, cpustate->modwritevalw);
+ break;
+ }
+
+ return 6;
+}
+
+static UINT32 am3PCDisplacementIndirect8(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1)), cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1)), cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1)), cpustate->modwritevalw);
+ break;
+ }
+
+ return 2;
+}
+
+static UINT32 am3PCDisplacementIndirect16(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1)), cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1)), cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1)), cpustate->modwritevalw);
+ break;
+ }
+
+ return 3;
+}
+
+static UINT32 am3PCDisplacementIndirect32(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1)), cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1)), cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1)), cpustate->modwritevalw);
+ break;
+ }
+
+ return 5;
+}
+
+
+static UINT32 am3PCDisplacementIndirectIndexed8(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 2, cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 4, cpustate->modwritevalw);
+ break;
+ }
+
+ return 3;
+}
+
+static UINT32 am3PCDisplacementIndirectIndexed16(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 2, cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 4, cpustate->modwritevalw);
+ break;
+ }
+
+ return 4;
+}
+
+static UINT32 am3PCDisplacementIndirectIndexed32(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 2, cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F] * 4, cpustate->modwritevalw);
+ break;
+ }
+
+ return 6;
+}
+
+
+static UINT32 am3DoubleDisplacement8(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1)) + (INT8)OpRead8(cpustate, cpustate->modadd + 2), cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1)) + (INT8)OpRead8(cpustate, cpustate->modadd + 2), cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT8)OpRead8(cpustate, cpustate->modadd + 1)) + (INT8)OpRead8(cpustate, cpustate->modadd + 2), cpustate->modwritevalw);
+ break;
+ }
+
+ return 3;
+}
+
+static UINT32 am3DoubleDisplacement16(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1)) + (INT16)OpRead16(cpustate, cpustate->modadd + 3), cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1)) + (INT16)OpRead16(cpustate, cpustate->modadd + 3), cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + (INT16)OpRead16(cpustate, cpustate->modadd + 1)) + (INT16)OpRead16(cpustate, cpustate->modadd + 3), cpustate->modwritevalw);
+ break;
+ }
+
+ return 5;
+}
+
+static UINT32 am3DoubleDisplacement32(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1)) + OpRead32(cpustate, cpustate->modadd + 5), cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1)) + OpRead32(cpustate, cpustate->modadd + 5), cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->reg[cpustate->modval & 0x1F] + OpRead32(cpustate, cpustate->modadd + 1)) + OpRead32(cpustate, cpustate->modadd + 5), cpustate->modwritevalw);
+ break;
+ }
+
+ return 9;
+}
+
+
+static UINT32 am3PCDoubleDisplacement8(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1)) + (INT8)OpRead8(cpustate, cpustate->modadd + 2), cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1)) + (INT8)OpRead8(cpustate, cpustate->modadd + 2), cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT8)OpRead8(cpustate, cpustate->modadd + 1)) + (INT8)OpRead8(cpustate, cpustate->modadd + 2), cpustate->modwritevalw);
+ break;
+ }
+
+ return 3;
+}
+
+static UINT32 am3PCDoubleDisplacement16(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1)) + (INT16)OpRead16(cpustate, cpustate->modadd + 3), cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1)) + (INT16)OpRead16(cpustate, cpustate->modadd + 3), cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + (INT16)OpRead16(cpustate, cpustate->modadd + 1)) + (INT16)OpRead16(cpustate, cpustate->modadd + 3), cpustate->modwritevalw);
+ break;
+ }
+
+ return 5;
+}
+
+static UINT32 am3PCDoubleDisplacement32(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1)) + OpRead32(cpustate, cpustate->modadd + 5), cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1)) + OpRead32(cpustate, cpustate->modadd + 5), cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->program->read_dword_unaligned(cpustate->PC + OpRead32(cpustate, cpustate->modadd + 1)) + OpRead32(cpustate, cpustate->modadd + 5), cpustate->modwritevalw);
+ break;
+ }
+
+ return 9;
+}
+
+static UINT32 am3DirectAddress(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(OpRead32(cpustate, cpustate->modadd + 1), cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(OpRead32(cpustate, cpustate->modadd + 1), cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 1), cpustate->modwritevalw);
+ break;
+ }
+
+ return 5;
+}
+
+static UINT32 am3DirectAddressIndexed(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 2, cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 2) + cpustate->reg[cpustate->modval & 0x1F] * 4, cpustate->modwritevalw);
+ break;
+ }
+
+ return 6;
+}
+
+static UINT32 am3DirectAddressDeferred(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 1)), cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 1)), cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 1)), cpustate->modwritevalw);
+ break;
+ }
+
+ return 5;
+}
+
+static UINT32 am3DirectAddressDeferredIndexed(v60_state *cpustate)
+{
+ switch (cpustate->moddim)
+ {
+ case 0:
+ cpustate->program->write_byte(cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalb);
+ break;
+ case 1:
+ cpustate->program->write_word_unaligned(cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->program->write_dword_unaligned(cpustate->program->read_dword_unaligned(OpRead32(cpustate, cpustate->modadd + 2)) + cpustate->reg[cpustate->modval & 0x1F], cpustate->modwritevalw);
+ break;
+ }
+
+ return 6;
+}
+
+static UINT32 am3Immediate(v60_state *cpustate)
+{
+ fatalerror("CPU - AM3 - IMM (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 am3ImmediateQuick(v60_state *cpustate)
+{
+ fatalerror("CPU - AM3 - IMMQ (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+
+
+// AM3 Tables (for ReadAMAddress)
+// ******************************
+
+static UINT32 am3Error1(v60_state *cpustate)
+{
+ fatalerror("CPU - AM3 - 1 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 am3Error2(v60_state *cpustate)
+{
+ fatalerror("CPU - AM3 - 2 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+#ifdef UNUSED_FUNCTION
+static UINT32 am3Error3(v60_state *cpustate)
+{
+ fatalerror("CPU - AM3 - 3 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+#endif
+
+static UINT32 am3Error4(v60_state *cpustate)
+{
+ fatalerror("CPU - AM3 - 4 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 am3Error5(v60_state *cpustate)
+{
+ fatalerror("CPU - AM3 - 5 (cpustate->PC=%06x)", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 (*const AMTable3_G7a[16])(v60_state *) =
+{
+ am3PCDisplacementIndexed8,
+ am3PCDisplacementIndexed16,
+ am3PCDisplacementIndexed32,
+ am3DirectAddressIndexed,
+ am3Error5,
+ am3Error5,
+ am3Error5,
+ am3Error5,
+ am3PCDisplacementIndirectIndexed8,
+ am3PCDisplacementIndirectIndexed16,
+ am3PCDisplacementIndirectIndexed32,
+ am3DirectAddressDeferredIndexed,
+ am3Error5,
+ am3Error5,
+ am3Error5,
+ am3Error5
+};
+
+static UINT32 am3Group7a(v60_state *cpustate)
+{
+ if (!(cpustate->modval2 & 0x10))
+ return am3Error4(cpustate);
+
+ return AMTable3_G7a[cpustate->modval2 & 0xF](cpustate);
+}
+
+static UINT32 (*const AMTable3_G7[32])(v60_state *) =
+{
+ am3ImmediateQuick,
+ am3ImmediateQuick,
+ am3ImmediateQuick,
+ am3ImmediateQuick,
+ am3ImmediateQuick,
+ am3ImmediateQuick,
+ am3ImmediateQuick,
+ am3ImmediateQuick,
+ am3ImmediateQuick,
+ am3ImmediateQuick,
+ am3ImmediateQuick,
+ am3ImmediateQuick,
+ am3ImmediateQuick,
+ am3ImmediateQuick,
+ am3ImmediateQuick,
+ am3ImmediateQuick,
+ am3PCDisplacement8,
+ am3PCDisplacement16,
+ am3PCDisplacement32,
+ am3DirectAddress,
+ am3Immediate,
+ am3Error2,
+ am3Error2,
+ am3Error2,
+ am3PCDisplacementIndirect8,
+ am3PCDisplacementIndirect16,
+ am3PCDisplacementIndirect32,
+ am3DirectAddressDeferred,
+ am3PCDoubleDisplacement8,
+ am3PCDoubleDisplacement16,
+ am3PCDoubleDisplacement32,
+ am3Error2
+};
+
+static UINT32 (*const AMTable3_G6[8])(v60_state *) =
+{
+ am3DisplacementIndexed8,
+ am3DisplacementIndexed16,
+ am3DisplacementIndexed32,
+ am3RegisterIndirectIndexed,
+ am3DisplacementIndirectIndexed8,
+ am3DisplacementIndirectIndexed16,
+ am3DisplacementIndirectIndexed32,
+ am3Group7a
+};
+
+
+
+
+static UINT32 am3Group6(v60_state *cpustate)
+{
+ cpustate->modval2 = OpRead8(cpustate, cpustate->modadd + 1);
+ return AMTable3_G6[cpustate->modval2 >> 5](cpustate);
+}
+
+
+static UINT32 am3Group7(v60_state *cpustate)
+{
+ return AMTable3_G7[cpustate->modval & 0x1F](cpustate);
+}
+
+
+
+static UINT32 (*const AMTable3[2][8])(v60_state *) =
+{
+ {
+ am3Displacement8,
+ am3Displacement16,
+ am3Displacement32,
+ am3RegisterIndirect,
+ am3DisplacementIndirect8,
+ am3DisplacementIndirect16,
+ am3DisplacementIndirect32,
+ am3Group7
+ },
+
+ {
+ am3DoubleDisplacement8,
+ am3DoubleDisplacement16,
+ am3DoubleDisplacement32,
+ am3Register,
+ am3Autoincrement,
+ am3Autodecrement,
+ am3Group6,
+ am3Error1
+ }
+};
+
+
+
diff --git a/trunk/src/emu/cpu/v60/op12.c b/trunk/src/emu/cpu/v60/op12.c
new file mode 100644
index 00000000000..b73c3f81f68
--- /dev/null
+++ b/trunk/src/emu/cpu/v60/op12.c
@@ -0,0 +1,2391 @@
+/*
+ * MUL* and MULU* do not set OV correctly
+ * DIVX: the second operand should be treated as dword instead of word
+ * GETATE, GETPTE and GETRA should not be used
+ * UPDPSW: cpustate->_CY and cpustate->_OV must be cleared or unchanged? I suppose
+ * cleared, like TEST being done on the mask operand.
+ * MOVT: I cannot understand exactly what happens to the result
+ * when an overflow occurs
+ *
+ * Unimplemented opcodes:
+ * ROTC, UPDATE, UPDPTE
+ */
+
+
+/*
+ * Macro to access data in operands decoded with ReadAMAddress(cpustate)
+ */
+
+#define F12LOADOPBYTE(cs, num) \
+ if ((cs)->flag##num) \
+ appb = (UINT8)(cs)->reg[(cs)->op##num]; \
+ else \
+ appb = (cs)->program->read_byte((cs)->op##num);
+
+#define F12LOADOPHALF(cs, num) \
+ if ((cs)->flag##num) \
+ apph = (UINT16)(cs)->reg[(cs)->op##num]; \
+ else \
+ apph = (cs)->program->read_word_unaligned((cs)->op##num);
+
+#define F12LOADOPWORD(cs, num) \
+ if ((cs)->flag##num) \
+ appw = (cs)->reg[(cs)->op##num]; \
+ else \
+ appw = (cs)->program->read_dword_unaligned((cs)->op##num);
+
+#define F12STOREOPBYTE(cs, num) \
+ if ((cs)->flag##num) \
+ SETREG8((cs)->reg[(cs)->op##num], appb); \
+ else \
+ (cs)->program->write_byte((cs)->op##num, appb);
+
+#define F12STOREOPHALF(cs, num) \
+ if ((cs)->flag##num) \
+ SETREG16((cs)->reg[(cs)->op##num], apph); \
+ else \
+ (cs)->program->write_word_unaligned((cs)->op##num, apph);
+
+#define F12STOREOPWORD(cs, num) \
+ if ((cs)->flag##num) \
+ (cs)->reg[(cs)->op##num] = appw; \
+ else \
+ (cs)->program->write_dword_unaligned((cs)->op##num, appw);
+
+#define F12LOADOP1BYTE(cs) F12LOADOPBYTE(cs, 1)
+#define F12LOADOP1HALF(cs) F12LOADOPHALF(cs, 1)
+#define F12LOADOP1WORD(cs) F12LOADOPWORD(cs, 1)
+
+#define F12LOADOP2BYTE(cs) F12LOADOPBYTE(cs, 2)
+#define F12LOADOP2HALF(cs) F12LOADOPHALF(cs, 2)
+#define F12LOADOP2WORD(cs) F12LOADOPWORD(cs, 2)
+
+#define F12STOREOP1BYTE(cs) F12STOREOPBYTE(cs, 1)
+#define F12STOREOP1HALF(cs) F12STOREOPHALF(cs, 1)
+#define F12STOREOP1WORD(cs) F12STOREOPWORD(cs, 1)
+
+#define F12STOREOP2BYTE(cs) F12STOREOPBYTE(cs, 2)
+#define F12STOREOP2HALF(cs) F12STOREOPHALF(cs, 2)
+#define F12STOREOP2WORD(cs) F12STOREOPWORD(cs, 2)
+
+#define F12END(cs) \
+ return (cs)->amlength1 + (cs)->amlength2 + 2;
+
+
+// Decode the first operand of the instruction and prepare
+// writing to the second operand.
+static void F12DecodeFirstOperand(v60_state *cpustate, UINT32 (*DecodeOp1)(v60_state *), UINT8 dim1)
+{
+ cpustate->instflags = OpRead8(cpustate, cpustate->PC + 1);
+
+ // Check if F1 or F2
+ if (cpustate->instflags & 0x80)
+ {
+ cpustate->moddim = dim1;
+ cpustate->modm = cpustate->instflags & 0x40;
+ cpustate->modadd = cpustate->PC + 2;
+ cpustate->amlength1 = DecodeOp1(cpustate);
+ cpustate->op1 = cpustate->amout;
+ cpustate->flag1 = cpustate->amflag;
+ }
+ else
+ {
+ // Check D flag
+ if (cpustate->instflags & 0x20)
+ {
+ cpustate->moddim = dim1;
+ cpustate->modm = cpustate->instflags & 0x40;
+ cpustate->modadd = cpustate->PC + 2;
+ cpustate->amlength1 = DecodeOp1(cpustate);
+ cpustate->op1 = cpustate->amout;
+ cpustate->flag1 = cpustate->amflag;
+ }
+ else
+ {
+ if (DecodeOp1 == ReadAM)
+ {
+ switch (dim1)
+ {
+ case 0:
+ cpustate->op1 = (UINT8)cpustate->reg[cpustate->instflags & 0x1F];
+ break;
+ case 1:
+ cpustate->op1 = (UINT16)cpustate->reg[cpustate->instflags & 0x1F];
+ break;
+ case 2:
+ cpustate->op1 = cpustate->reg[cpustate->instflags & 0x1F];
+ break;
+ }
+
+ cpustate->flag1 = 0;
+ }
+ else
+ {
+ cpustate->flag1 = 1;
+ cpustate->op1 = cpustate->instflags & 0x1F;
+ }
+
+ cpustate->amlength1 = 0;
+ }
+ }
+}
+
+static void F12WriteSecondOperand(v60_state *cpustate, UINT8 dim2)
+{
+ cpustate->moddim = dim2;
+
+ // Check if F1 or F2
+ if (cpustate->instflags & 0x80)
+ {
+ cpustate->modm = cpustate->instflags & 0x20;
+ cpustate->modadd = cpustate->PC + 2 + cpustate->amlength1;
+ cpustate->moddim = dim2;
+ cpustate->amlength2 = WriteAM(cpustate);
+ }
+ else
+ {
+ // Check D flag
+ if (cpustate->instflags & 0x20)
+ {
+ switch (dim2)
+ {
+ case 0:
+ SETREG8(cpustate->reg[cpustate->instflags & 0x1F], cpustate->modwritevalb);
+ break;
+ case 1:
+ SETREG16(cpustate->reg[cpustate->instflags & 0x1F], cpustate->modwritevalh);
+ break;
+ case 2:
+ cpustate->reg[cpustate->instflags & 0x1F] = cpustate->modwritevalw;
+ break;
+ }
+
+ cpustate->amlength2 = 0;
+ }
+ else
+ {
+ cpustate->modm = cpustate->instflags & 0x40;
+ cpustate->modadd = cpustate->PC + 2;
+ cpustate->moddim = dim2;
+ cpustate->amlength2 = WriteAM(cpustate);
+ }
+ }
+}
+
+
+
+// Decode both format 1 / 2 operands
+static void F12DecodeOperands(v60_state *cpustate, UINT32 (*DecodeOp1)(v60_state *), UINT8 dim1, UINT32 (*DecodeOp2)(v60_state *), UINT8 dim2)
+{
+ UINT8 _if12 = OpRead8(cpustate, cpustate->PC + 1);
+
+ // Check if F1 or F2
+ if (_if12 & 0x80)
+ {
+ cpustate->moddim = dim1;
+ cpustate->modm = _if12 & 0x40;
+ cpustate->modadd = cpustate->PC + 2;
+ cpustate->amlength1 = DecodeOp1(cpustate);
+ cpustate->op1 = cpustate->amout;
+ cpustate->flag1 = cpustate->amflag;
+
+ cpustate->moddim = dim2;
+ cpustate->modm = _if12 & 0x20;
+ cpustate->modadd = cpustate->PC + 2 + cpustate->amlength1;
+ cpustate->amlength2 = DecodeOp2(cpustate);
+ cpustate->op2 = cpustate->amout;
+ cpustate->flag2 = cpustate->amflag;
+ }
+ else
+ {
+ // Check D flag
+ if (_if12 & 0x20)
+ {
+ if (DecodeOp2 == ReadAMAddress)
+ {
+ cpustate->op2 = _if12 & 0x1F;
+ cpustate->flag2 = 1;
+ }
+ else
+ {
+ switch (dim2)
+ {
+ case 0:
+ cpustate->op2 = (UINT8)cpustate->reg[_if12 & 0x1F];
+ break;
+ case 1:
+ cpustate->op2 = (UINT16)cpustate->reg[_if12 & 0x1F];
+ break;
+ case 2:
+ cpustate->op2 = cpustate->reg[_if12 & 0x1F];
+ break;
+ }
+ }
+
+ cpustate->amlength2 = 0;
+
+ cpustate->moddim = dim1;
+ cpustate->modm = _if12 & 0x40;
+ cpustate->modadd = cpustate->PC + 2;
+ cpustate->amlength1 = DecodeOp1(cpustate);
+ cpustate->op1 = cpustate->amout;
+ cpustate->flag1 = cpustate->amflag;
+ }
+ else
+ {
+ if (DecodeOp1 == ReadAMAddress)
+ {
+ cpustate->op1 = _if12 & 0x1F;
+ cpustate->flag1 = 1;
+ }
+ else
+ {
+ switch (dim1)
+ {
+ case 0:
+ cpustate->op1 = (UINT8)cpustate->reg[_if12 & 0x1F];
+ break;
+ case 1:
+ cpustate->op1 = (UINT16)cpustate->reg[_if12 & 0x1F];
+ break;
+ case 2:
+ cpustate->op1 = cpustate->reg[_if12 & 0x1F];
+ break;
+ }
+ }
+ cpustate->amlength1 = 0;
+
+ cpustate->moddim = dim2;
+ cpustate->modm = _if12 & 0x40;
+ cpustate->modadd = cpustate->PC + 2 + cpustate->amlength1;
+ cpustate->amlength2 = DecodeOp2(cpustate);
+ cpustate->op2 = cpustate->amout;
+ cpustate->flag2 = cpustate->amflag;
+ }
+ }
+}
+
+static UINT32 opADDB(v60_state *cpustate) /* TRUSTED (C too!)*/
+{
+ UINT8 appb;
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 0);
+
+ F12LOADOP2BYTE(cpustate);
+
+ ADDB(appb, (UINT8)cpustate->op1);
+
+ F12STOREOP2BYTE(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opADDH(v60_state *cpustate) /* TRUSTED (C too!)*/
+{
+ UINT16 apph;
+ F12DecodeOperands(cpustate, ReadAM, 1,ReadAMAddress, 1);
+
+ F12LOADOP2HALF(cpustate);
+
+ ADDW(apph, (UINT16)cpustate->op1);
+
+ F12STOREOP2HALF(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opADDW(v60_state *cpustate) /* TRUSTED (C too!) */
+{
+ UINT32 appw;
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAMAddress, 2);
+
+ F12LOADOP2WORD(cpustate);
+
+ ADDL(appw, (UINT32)cpustate->op1);
+
+ F12STOREOP2WORD(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opADDCB(v60_state *cpustate)
+{
+ UINT8 appb, temp;
+
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 0);
+
+ F12LOADOP2BYTE(cpustate);
+
+ temp = ((UINT8)cpustate->op1 + (cpustate->_CY?1:0));
+ ADDB(appb, temp);
+
+ F12STOREOP2BYTE(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opADDCH(v60_state *cpustate)
+{
+ UINT16 apph, temp;
+
+ F12DecodeOperands(cpustate, ReadAM, 1,ReadAMAddress, 1);
+
+ F12LOADOP2HALF(cpustate);
+
+ temp = ((UINT16)cpustate->op1 + (cpustate->_CY?1:0));
+ ADDW(apph, temp);
+
+ F12STOREOP2HALF(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opADDCW(v60_state *cpustate)
+{
+ UINT32 appw, temp;
+
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAMAddress, 2);
+
+ F12LOADOP2WORD(cpustate);
+
+ temp = cpustate->op1 + (cpustate->_CY?1:0);
+ ADDL(appw, temp);
+
+ F12STOREOP2WORD(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opANDB(v60_state *cpustate) /* TRUSTED */
+{
+ UINT8 appb;
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 0);
+
+ F12LOADOP2BYTE(cpustate);
+
+ appb &= cpustate->op1;
+ cpustate->_OV = 0;
+ cpustate->_S = ((appb & 0x80) != 0);
+ cpustate->_Z = (appb == 0);
+
+ F12STOREOP2BYTE(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opANDH(v60_state *cpustate) /* TRUSTED */
+{
+ UINT16 apph;
+ F12DecodeOperands(cpustate, ReadAM, 1,ReadAMAddress, 1);
+
+ F12LOADOP2HALF(cpustate);
+
+ apph &= cpustate->op1;
+ cpustate->_OV = 0;
+ cpustate->_S = ((apph & 0x8000) != 0);
+ cpustate->_Z = (apph == 0);
+
+ F12STOREOP2HALF(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opANDW(v60_state *cpustate) /* TRUSTED */
+{
+ UINT32 appw;
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAMAddress, 2);
+
+ F12LOADOP2WORD(cpustate);
+
+ appw &= cpustate->op1;
+ cpustate->_OV = 0;
+ cpustate->_S = ((appw & 0x80000000) != 0);
+ cpustate->_Z = (appw == 0);
+
+ F12STOREOP2WORD(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opCALL(v60_state *cpustate) /* TRUSTED */
+{
+ F12DecodeOperands(cpustate, ReadAMAddress, 0,ReadAMAddress, 2);
+
+ cpustate->SP -= 4;
+ cpustate->program->write_dword_unaligned(cpustate->SP, cpustate->AP);
+ cpustate->AP = cpustate->op2;
+
+ cpustate->SP -= 4;
+ cpustate->program->write_dword_unaligned(cpustate->SP, cpustate->PC + cpustate->amlength1 + cpustate->amlength2 + 2);
+ cpustate->PC = cpustate->op1;
+
+ return 0;
+}
+
+static UINT32 opCHKAR(v60_state *cpustate)
+{
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAM, 0);
+
+ // No MMU and memory permissions yet @@@
+ cpustate->_Z = 1;
+ cpustate->_CY = 0;
+ cpustate->_S = 0;
+
+ F12END(cpustate);
+}
+
+static UINT32 opCHKAW(v60_state *cpustate)
+{
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAM, 0);
+
+ // No MMU and memory permissions yet @@@
+ cpustate->_Z = 1;
+ cpustate->_CY = 0;
+ cpustate->_S = 0;
+
+ F12END(cpustate);
+}
+
+static UINT32 opCHKAE(v60_state *cpustate)
+{
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAM, 0);
+
+ // No MMU and memory permissions yet @@@
+ cpustate->_Z = 1;
+ cpustate->_CY = 0;
+ cpustate->_S = 0;
+
+ F12END(cpustate);
+}
+
+static UINT32 opCHLVL(v60_state *cpustate)
+{
+ UINT32 oldPSW;
+
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAM, 0);
+
+ if (cpustate->op1 > 3)
+ {
+ fatalerror("Illegal data field on opCHLVL, cpustate->PC=%x", cpustate->PC);
+ }
+
+ oldPSW = v60_update_psw_for_exception(cpustate, 0, cpustate->op1);
+
+ cpustate->SP -= 4;
+ cpustate->program->write_dword_unaligned(cpustate->SP, cpustate->op2);
+
+ cpustate->SP -= 4;
+ cpustate->program->write_dword_unaligned(cpustate->SP, EXCEPTION_CODE_AND_SIZE(0x1800 + cpustate->op1 * 0x100, 8));
+
+ cpustate->SP -= 4;
+ cpustate->program->write_dword_unaligned(cpustate->SP, oldPSW);
+
+ cpustate->SP -= 4;
+ cpustate->program->write_dword_unaligned(cpustate->SP, cpustate->PC + cpustate->amlength1 + cpustate->amlength2 + 2);
+
+ cpustate->PC = GETINTVECT(cpustate, 24 + cpustate->op1);
+
+ return 0;
+}
+
+static UINT32 opCLR1(v60_state *cpustate) /* TRUSTED */
+{
+ UINT32 appw;
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAMAddress, 2);
+
+ F12LOADOP2WORD(cpustate);
+
+ cpustate->_CY = ((appw & (1 << cpustate->op1)) != 0);
+ cpustate->_Z = !(cpustate->_CY);
+
+ appw &= ~(1 << cpustate->op1);
+
+ F12STOREOP2WORD(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opCMPB(v60_state *cpustate) /* TRUSTED (C too!) */
+{
+ UINT8 appb;
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAM, 0);
+
+ appb = (UINT8)cpustate->op2;
+ SUBB(appb, (UINT8)cpustate->op1);
+
+ F12END(cpustate);
+}
+
+static UINT32 opCMPH(v60_state *cpustate) /* TRUSTED (C too!) */
+{
+ UINT16 apph;
+ F12DecodeOperands(cpustate, ReadAM, 1,ReadAM, 1);
+
+ apph = (UINT16)cpustate->op2;
+ SUBW(apph, (UINT16)cpustate->op1);
+
+ F12END(cpustate);
+}
+
+
+static UINT32 opCMPW(v60_state *cpustate) /* TRUSTED (C too!)*/
+{
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAM, 2);
+
+ SUBL(cpustate->op2, (UINT32)cpustate->op1);
+
+ F12END(cpustate);
+}
+
+static UINT32 opDIVB(v60_state *cpustate) /* TRUSTED */
+{
+ UINT8 appb;
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 0);
+
+ F12LOADOP2BYTE(cpustate);
+
+ cpustate->_OV = ((appb == 0x80) && (cpustate->op1 == 0xFF));
+ if (cpustate->op1 && !cpustate->_OV)
+ appb= (INT8)appb / (INT8)cpustate->op1;
+ cpustate->_Z = (appb == 0);
+ cpustate->_S = ((appb & 0x80) != 0);
+
+ F12STOREOP2BYTE(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opDIVH(v60_state *cpustate) /* TRUSTED */
+{
+ UINT16 apph;
+ F12DecodeOperands(cpustate, ReadAM, 1,ReadAMAddress, 1);
+
+ F12LOADOP2HALF(cpustate);
+
+ cpustate->_OV = ((apph == 0x8000) && (cpustate->op1 == 0xFFFF));
+ if (cpustate->op1 && !cpustate->_OV)
+ apph = (INT16)apph / (INT16)cpustate->op1;
+ cpustate->_Z = (apph == 0);
+ cpustate->_S = ((apph & 0x8000) != 0);
+
+ F12STOREOP2HALF(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opDIVW(v60_state *cpustate) /* TRUSTED */
+{
+ UINT32 appw;
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAMAddress, 2);
+
+ F12LOADOP2WORD(cpustate);
+
+ cpustate->_OV = ((appw == 0x80000000) && (cpustate->op1 == 0xFFFFFFFF));
+ if (cpustate->op1 && !cpustate->_OV)
+ appw = (INT32)appw / (INT32)cpustate->op1;
+ cpustate->_Z = (appw == 0);
+ cpustate->_S = ((appw & 0x80000000) != 0);
+
+ F12STOREOP2WORD(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opDIVX(v60_state *cpustate)
+{
+ UINT32 a, b;
+ INT64 dv;
+
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAMAddress, 3);
+
+ if (cpustate->flag2)
+ {
+ a = cpustate->reg[cpustate->op2 & 0x1F];
+ b = cpustate->reg[(cpustate->op2 & 0x1F) + 1];
+ }
+ else
+ {
+ a = cpustate->program->read_dword_unaligned(cpustate->op2);
+ b = cpustate->program->read_dword_unaligned(cpustate->op2 + 4);
+ }
+
+ dv = ((UINT64)b << 32) | ((UINT64)a);
+
+ a = dv / (INT64)((INT32)cpustate->op1);
+ b = dv % (INT64)((INT32)cpustate->op1);
+
+ cpustate->_S = ((a & 0x80000000) != 0);
+ cpustate->_Z = (a == 0);
+
+ if (cpustate->flag2)
+ {
+ cpustate->reg[cpustate->op2 & 0x1F] = a;
+ cpustate->reg[(cpustate->op2 & 0x1F) + 1] = b;
+ }
+ else
+ {
+ cpustate->program->write_dword_unaligned(cpustate->op2, a);
+ cpustate->program->write_dword_unaligned(cpustate->op2 + 4, b);
+ }
+
+ F12END(cpustate);
+}
+
+static UINT32 opDIVUX(v60_state *cpustate)
+{
+ UINT32 a, b;
+ UINT64 dv;
+
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAMAddress, 3);
+
+ if (cpustate->flag2)
+ {
+ a = cpustate->reg[cpustate->op2 & 0x1F];
+ b = cpustate->reg[(cpustate->op2 & 0x1F) + 1];
+ }
+ else
+ {
+ a = cpustate->program->read_dword_unaligned(cpustate->op2);
+ b = cpustate->program->read_dword_unaligned(cpustate->op2 + 4);
+ }
+
+ dv = (UINT64)(((UINT64)b << 32) | (UINT64)a);
+ a = (UINT32)(dv / (UINT64)cpustate->op1);
+ b = (UINT32)(dv % (UINT64)cpustate->op1);
+
+ cpustate->_S = ((a & 0x80000000) != 0);
+ cpustate->_Z = (a == 0);
+
+ if (cpustate->flag2)
+ {
+ cpustate->reg[cpustate->op2 & 0x1F] = a;
+ cpustate->reg[(cpustate->op2 & 0x1F) + 1] = b;
+ }
+ else
+ {
+ cpustate->program->write_dword_unaligned(cpustate->op2, a);
+ cpustate->program->write_dword_unaligned(cpustate->op2 + 4, b);
+ }
+
+ F12END(cpustate);
+}
+
+
+static UINT32 opDIVUB(v60_state *cpustate) /* TRUSTED */
+{
+ UINT8 appb;
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 0);
+
+ F12LOADOP2BYTE(cpustate);
+
+ cpustate->_OV = 0;
+ if (cpustate->op1) appb /= (UINT8)cpustate->op1;
+ cpustate->_Z = (appb == 0);
+ cpustate->_S = ((appb & 0x80) != 0);
+
+ F12STOREOP2BYTE(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opDIVUH(v60_state *cpustate) /* TRUSTED */
+{
+ UINT16 apph;
+ F12DecodeOperands(cpustate, ReadAM, 1,ReadAMAddress, 1);
+
+ F12LOADOP2HALF(cpustate);
+
+ cpustate->_OV = 0;
+ if (cpustate->op1) apph /= (UINT16)cpustate->op1;
+ cpustate->_Z = (apph == 0);
+ cpustate->_S = ((apph & 0x8000) != 0);
+
+ F12STOREOP2HALF(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opDIVUW(v60_state *cpustate) /* TRUSTED */
+{
+ UINT32 appw;
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAMAddress, 2);
+
+ F12LOADOP2WORD(cpustate);
+
+ cpustate->_OV = 0;
+ if (cpustate->op1) appw /= cpustate->op1;
+ cpustate->_Z = (appw == 0);
+ cpustate->_S = ((appw & 0x80000000) != 0);
+
+ F12STOREOP2WORD(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opINB(v60_state *cpustate)
+{
+ F12DecodeFirstOperand(cpustate, ReadAMAddress, 0);
+ cpustate->modwritevalb = cpustate->io->read_byte(cpustate->op1);
+
+ if ( cpustate->stall_io )
+ {
+ cpustate->stall_io = 0;
+ return 0;
+ }
+
+ F12WriteSecondOperand(cpustate, 0);
+ F12END(cpustate);
+}
+
+static UINT32 opINH(v60_state *cpustate)
+{
+ F12DecodeFirstOperand(cpustate, ReadAMAddress, 1);
+ cpustate->modwritevalh = cpustate->io->read_word_unaligned(cpustate->op1);
+
+ if ( cpustate->stall_io )
+ {
+ cpustate->stall_io = 0;
+ return 0;
+ }
+
+ F12WriteSecondOperand(cpustate, 1);
+ F12END(cpustate);
+}
+
+static UINT32 opINW(v60_state *cpustate)
+{
+ F12DecodeFirstOperand(cpustate, ReadAMAddress, 2);
+ cpustate->modwritevalw = cpustate->io->read_dword_unaligned(cpustate->op1);
+
+ if ( cpustate->stall_io )
+ {
+ cpustate->stall_io = 0;
+ return 0;
+ }
+
+ F12WriteSecondOperand(cpustate, 2);
+ F12END(cpustate);
+}
+
+static UINT32 opLDPR(v60_state *cpustate)
+{
+ F12DecodeOperands(cpustate, ReadAMAddress, 2,ReadAM, 2);
+ if (cpustate->op2 >= 0 && cpustate->op2 <= 28)
+ {
+ if (cpustate->flag1 &&(!(OpRead8(cpustate, cpustate->PC + 1)&0x80 && OpRead8(cpustate, cpustate->PC + 2) == 0xf4 ) ))
+ cpustate->reg[cpustate->op2 + 36] = cpustate->reg[cpustate->op1];
+ else
+ cpustate->reg[cpustate->op2 + 36] = cpustate->op1;
+ }
+ else
+ {
+ fatalerror("Invalid operand on LDPR cpustate->PC=%x", cpustate->PC);
+ }
+ F12END(cpustate);
+}
+
+static UINT32 opLDTASK(v60_state *cpustate)
+{
+ int i;
+ F12DecodeOperands(cpustate, ReadAMAddress, 2,ReadAM, 2);
+
+ v60WritePSW(cpustate, v60ReadPSW(cpustate) & 0xefffffff);
+
+ cpustate->TR = cpustate->op2;
+
+ cpustate->TKCW = cpustate->program->read_dword_unaligned(cpustate->op2);
+ cpustate->op2 += 4;
+ if(cpustate->SYCW & 0x100) {
+ cpustate->L0SP = cpustate->program->read_dword_unaligned(cpustate->op2);
+ cpustate->op2 += 4;
+ }
+ if(cpustate->SYCW & 0x200) {
+ cpustate->L1SP = cpustate->program->read_dword_unaligned(cpustate->op2);
+ cpustate->op2 += 4;
+ }
+ if(cpustate->SYCW & 0x400) {
+ cpustate->L2SP = cpustate->program->read_dword_unaligned(cpustate->op2);
+ cpustate->op2 += 4;
+ }
+ if(cpustate->SYCW & 0x800) {
+ cpustate->L3SP = cpustate->program->read_dword_unaligned(cpustate->op2);
+ cpustate->op2 += 4;
+ }
+
+ v60ReloadStack(cpustate);
+
+ // 31 registers supported, _not_ 32
+ for(i = 0; i < 31; i++)
+ if(cpustate->op1 & (1 << i)) {
+ cpustate->reg[i] = cpustate->program->read_dword_unaligned(cpustate->op2);
+ cpustate->op2 += 4;
+ }
+
+ // #### Ignore the virtual addressing crap.
+
+ F12END(cpustate);
+}
+
+static UINT32 opMOVD(v60_state *cpustate) /* TRUSTED */
+{
+ UINT32 a, b;
+
+ F12DecodeOperands(cpustate, ReadAMAddress, 3,ReadAMAddress, 3);
+
+ if (cpustate->flag1)
+ {
+ a = cpustate->reg[cpustate->op1 & 0x1F];
+ b = cpustate->reg[(cpustate->op1 & 0x1F) + 1];
+ }
+ else
+ {
+ a = cpustate->program->read_dword_unaligned(cpustate->op1);
+ b = cpustate->program->read_dword_unaligned(cpustate->op1 + 4);
+ }
+
+ if (cpustate->flag2)
+ {
+ cpustate->reg[cpustate->op2 & 0x1F] = a;
+ cpustate->reg[(cpustate->op2 & 0x1F) + 1] = b;
+ }
+ else
+ {
+ cpustate->program->write_dword_unaligned(cpustate->op2, a);
+ cpustate->program->write_dword_unaligned(cpustate->op2 + 4, b);
+ }
+
+ F12END(cpustate);
+}
+
+static UINT32 opMOVB(v60_state *cpustate) /* TRUSTED */
+{
+ F12DecodeFirstOperand(cpustate, ReadAM, 0);
+ cpustate->modwritevalb = (UINT8)cpustate->op1;
+ F12WriteSecondOperand(cpustate, 0);
+ F12END(cpustate);
+}
+
+static UINT32 opMOVH(v60_state *cpustate) /* TRUSTED */
+{
+ F12DecodeFirstOperand(cpustate, ReadAM, 1);
+ cpustate->modwritevalh = (UINT16)cpustate->op1;
+ F12WriteSecondOperand(cpustate, 1);
+ F12END(cpustate);
+}
+
+static UINT32 opMOVW(v60_state *cpustate) /* TRUSTED */
+{
+ F12DecodeFirstOperand(cpustate, ReadAM, 2);
+ cpustate->modwritevalw = cpustate->op1;
+ F12WriteSecondOperand(cpustate, 2);
+ F12END(cpustate);
+}
+
+static UINT32 opMOVEAB(v60_state *cpustate) /* TRUSTED */
+{
+ F12DecodeFirstOperand(cpustate, ReadAMAddress, 0);
+ cpustate->modwritevalw = cpustate->op1;
+ F12WriteSecondOperand(cpustate, 2);
+ F12END(cpustate);
+}
+
+static UINT32 opMOVEAH(v60_state *cpustate) /* TRUSTED */
+{
+ F12DecodeFirstOperand(cpustate, ReadAMAddress, 1);
+ cpustate->modwritevalw = cpustate->op1;
+ F12WriteSecondOperand(cpustate, 2);
+ F12END(cpustate);
+}
+
+static UINT32 opMOVEAW(v60_state *cpustate) /* TRUSTED */
+{
+ F12DecodeFirstOperand(cpustate, ReadAMAddress, 2);
+ cpustate->modwritevalw = cpustate->op1;
+ F12WriteSecondOperand(cpustate, 2);
+ F12END(cpustate);
+}
+
+static UINT32 opMOVSBH(v60_state *cpustate) /* TRUSTED */
+{
+ F12DecodeFirstOperand(cpustate, ReadAM, 0);
+ cpustate->modwritevalh = (INT8)(cpustate->op1 & 0xFF);
+ F12WriteSecondOperand(cpustate, 1);
+ F12END(cpustate);
+}
+
+static UINT32 opMOVSBW(v60_state *cpustate) /* TRUSTED */
+{
+ F12DecodeFirstOperand(cpustate, ReadAM, 0);
+ cpustate->modwritevalw = (INT8)(cpustate->op1 & 0xFF);
+ F12WriteSecondOperand(cpustate, 2);
+ F12END(cpustate);
+}
+
+static UINT32 opMOVSHW(v60_state *cpustate) /* TRUSTED */
+{
+ F12DecodeFirstOperand(cpustate, ReadAM, 1);
+ cpustate->modwritevalw = (INT16)(cpustate->op1 & 0xFFFF);
+ F12WriteSecondOperand(cpustate, 2);
+ F12END(cpustate);
+}
+
+static UINT32 opMOVTHB(v60_state *cpustate)
+{
+ F12DecodeFirstOperand(cpustate, ReadAM, 1);
+ cpustate->modwritevalb = (UINT8)(cpustate->op1 & 0xFF);
+
+ // Check for overflow: the truncated bits must match the sign
+ // of the result, otherwise overflow
+ if (((cpustate->modwritevalb & 0x80) == 0x80 && ((cpustate->op1 & 0xFF00) == 0xFF00)) ||
+ ((cpustate->modwritevalb & 0x80) == 0 && ((cpustate->op1 & 0xFF00) == 0x0000)))
+ cpustate->_OV = 0;
+ else
+ cpustate->_OV = 1;
+
+ F12WriteSecondOperand(cpustate, 0);
+ F12END(cpustate);
+}
+
+static UINT32 opMOVTWB(v60_state *cpustate)
+{
+ F12DecodeFirstOperand(cpustate, ReadAM, 2);
+ cpustate->modwritevalb = (UINT8)(cpustate->op1 & 0xFF);
+
+ // Check for overflow: the truncated bits must match the sign
+ // of the result, otherwise overflow
+ if (((cpustate->modwritevalb & 0x80) == 0x80 && ((cpustate->op1 & 0xFFFFFF00) == 0xFFFFFF00)) ||
+ ((cpustate->modwritevalb & 0x80) == 0 && ((cpustate->op1 & 0xFFFFFF00) == 0x00000000)))
+ cpustate->_OV = 0;
+ else
+ cpustate->_OV = 1;
+
+ F12WriteSecondOperand(cpustate, 0);
+ F12END(cpustate);
+}
+
+static UINT32 opMOVTWH(v60_state *cpustate)
+{
+ F12DecodeFirstOperand(cpustate, ReadAM, 2);
+ cpustate->modwritevalh = (UINT16)(cpustate->op1 & 0xFFFF);
+
+ // Check for overflow: the truncated bits must match the sign
+ // of the result, otherwise overflow
+ if (((cpustate->modwritevalh & 0x8000) == 0x8000 && ((cpustate->op1 & 0xFFFF0000) == 0xFFFF0000)) ||
+ ((cpustate->modwritevalh & 0x8000) == 0 && ((cpustate->op1 & 0xFFFF0000) == 0x00000000)))
+ cpustate->_OV = 0;
+ else
+ cpustate->_OV = 1;
+
+ F12WriteSecondOperand(cpustate, 1);
+ F12END(cpustate);
+}
+
+
+static UINT32 opMOVZBH(v60_state *cpustate) /* TRUSTED */
+{
+ F12DecodeFirstOperand(cpustate, ReadAM, 0);
+ cpustate->modwritevalh = (UINT16)cpustate->op1;
+ F12WriteSecondOperand(cpustate, 1);
+ F12END(cpustate);
+}
+
+static UINT32 opMOVZBW(v60_state *cpustate) /* TRUSTED */
+{
+ F12DecodeFirstOperand(cpustate, ReadAM, 0);
+ cpustate->modwritevalw = cpustate->op1;
+ F12WriteSecondOperand(cpustate, 2);
+ F12END(cpustate);
+}
+
+static UINT32 opMOVZHW(v60_state *cpustate) /* TRUSTED */
+{
+ F12DecodeFirstOperand(cpustate, ReadAM, 1);
+ cpustate->modwritevalw = cpustate->op1;
+ F12WriteSecondOperand(cpustate, 2);
+ F12END(cpustate);
+}
+
+static UINT32 opMULB(v60_state *cpustate)
+{
+ UINT8 appb;
+ UINT32 tmp;
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 0);
+
+ F12LOADOP2BYTE(cpustate);
+
+ // @@@ OV not set!!
+ tmp = (INT8)appb * (INT32)(INT8)cpustate->op1;
+ appb = tmp;
+ cpustate->_Z = (appb == 0);
+ cpustate->_S = ((appb & 0x80) != 0);
+ cpustate->_OV = ((tmp >> 8) != 0);
+
+ F12STOREOP2BYTE(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opMULH(v60_state *cpustate)
+{
+ UINT16 apph;
+ UINT32 tmp;
+ F12DecodeOperands(cpustate, ReadAM, 1,ReadAMAddress, 1);
+
+ F12LOADOP2HALF(cpustate);
+
+ // @@@ OV not set!!
+ tmp = (INT16)apph * (INT32)(INT16)cpustate->op1;
+ apph = tmp;
+ cpustate->_Z = (apph == 0);
+ cpustate->_S = ((apph & 0x8000) != 0);
+ cpustate->_OV = ((tmp >> 16) != 0);
+
+ F12STOREOP2HALF(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opMULW(v60_state *cpustate)
+{
+ UINT32 appw;
+ UINT64 tmp;
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAMAddress, 2);
+
+ F12LOADOP2WORD(cpustate);
+
+ // @@@ OV not set!!
+ tmp = (INT32)appw * (INT64)(INT32)cpustate->op1;
+ appw = tmp;
+ cpustate->_Z = (appw == 0);
+ cpustate->_S = ((appw & 0x80000000) != 0);
+ cpustate->_OV = ((tmp >> 32) != 0);
+
+ F12STOREOP2WORD(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opMULUB(v60_state *cpustate)
+{
+ UINT8 appb;
+ UINT32 tmp;
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 0);
+
+ F12LOADOP2BYTE(cpustate);
+
+ // @@@ OV not set!!
+ tmp = appb * (UINT8)cpustate->op1;
+ appb = tmp;
+ cpustate->_Z = (appb == 0);
+ cpustate->_S = ((appb & 0x80) != 0);
+ cpustate->_OV = ((tmp >> 8) != 0);
+
+ F12STOREOP2BYTE(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opMULUH(v60_state *cpustate)
+{
+ UINT16 apph;
+ UINT32 tmp;
+ F12DecodeOperands(cpustate, ReadAM, 1,ReadAMAddress, 1);
+
+ F12LOADOP2HALF(cpustate);
+
+ // @@@ OV not set!!
+ tmp = apph * (UINT16)cpustate->op1;
+ apph = tmp;
+ cpustate->_Z = (apph == 0);
+ cpustate->_S = ((apph & 0x8000) != 0);
+ cpustate->_OV = ((tmp >> 16) != 0);
+
+ F12STOREOP2HALF(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opMULUW(v60_state *cpustate)
+{
+ UINT32 appw;
+ UINT64 tmp;
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAMAddress, 2);
+
+ F12LOADOP2WORD(cpustate);
+
+ // @@@ OV not set!!
+ tmp = (UINT64)appw * (UINT64)cpustate->op1;
+ appw = tmp;
+ cpustate->_Z = (appw == 0);
+ cpustate->_S = ((appw & 0x80000000) != 0);
+ cpustate->_OV = ((tmp >> 32) != 0);
+
+ F12STOREOP2WORD(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opNEGB(v60_state *cpustate) /* TRUSTED (C too!)*/
+{
+ F12DecodeFirstOperand(cpustate, ReadAM, 0);
+
+ cpustate->modwritevalb = 0;
+ SUBB(cpustate->modwritevalb, (INT8)cpustate->op1);
+
+ F12WriteSecondOperand(cpustate, 0);
+ F12END(cpustate);
+}
+
+static UINT32 opNEGH(v60_state *cpustate) /* TRUSTED (C too!)*/
+{
+ F12DecodeFirstOperand(cpustate, ReadAM, 1);
+
+ cpustate->modwritevalh = 0;
+ SUBW(cpustate->modwritevalh, (INT16)cpustate->op1);
+
+ F12WriteSecondOperand(cpustate, 1);
+ F12END(cpustate);
+}
+
+static UINT32 opNEGW(v60_state *cpustate) /* TRUSTED (C too!)*/
+{
+ F12DecodeFirstOperand(cpustate, ReadAM, 2);
+
+ cpustate->modwritevalw = 0;
+ SUBL(cpustate->modwritevalw, (INT32)cpustate->op1);
+
+ F12WriteSecondOperand(cpustate, 2);
+ F12END(cpustate);
+}
+
+static UINT32 opNOTB(v60_state *cpustate) /* TRUSTED */
+{
+ F12DecodeFirstOperand(cpustate, ReadAM, 0);
+ cpustate->modwritevalb=~cpustate->op1;
+
+ cpustate->_OV = 0;
+ cpustate->_S = ((cpustate->modwritevalb & 0x80) != 0);
+ cpustate->_Z = (cpustate->modwritevalb == 0);
+
+ F12WriteSecondOperand(cpustate, 0);
+ F12END(cpustate);
+}
+
+static UINT32 opNOTH(v60_state *cpustate) /* TRUSTED */
+{
+ F12DecodeFirstOperand(cpustate, ReadAM, 1);
+ cpustate->modwritevalh=~cpustate->op1;
+
+ cpustate->_OV = 0;
+ cpustate->_S = ((cpustate->modwritevalh & 0x8000) != 0);
+ cpustate->_Z = (cpustate->modwritevalh == 0);
+
+ F12WriteSecondOperand(cpustate, 1);
+ F12END(cpustate);
+}
+
+static UINT32 opNOTW(v60_state *cpustate) /* TRUSTED */
+{
+ F12DecodeFirstOperand(cpustate, ReadAM, 2);
+ cpustate->modwritevalw=~cpustate->op1;
+
+ cpustate->_OV = 0;
+ cpustate->_S = ((cpustate->modwritevalw & 0x80000000) != 0);
+ cpustate->_Z = (cpustate->modwritevalw == 0);
+
+ F12WriteSecondOperand(cpustate, 2);
+ F12END(cpustate);
+}
+
+static UINT32 opNOT1(v60_state *cpustate) /* TRUSTED */
+{
+ UINT32 appw;
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAMAddress, 2);
+
+ F12LOADOP2WORD(cpustate);
+
+ cpustate->_CY = ((appw & (1 << cpustate->op1)) != 0);
+ cpustate->_Z = !(cpustate->_CY);
+
+ if (cpustate->_CY)
+ appw &= ~(1 << cpustate->op1);
+ else
+ appw |= (1 << cpustate->op1);
+
+ F12STOREOP2WORD(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opORB(v60_state *cpustate) /* TRUSTED (C too!)*/
+{
+ UINT8 appb;
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 0);
+
+ F12LOADOP2BYTE(cpustate);
+
+ ORB(appb, (UINT8)cpustate->op1);
+
+ F12STOREOP2BYTE(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opORH(v60_state *cpustate) /* TRUSTED (C too!)*/
+{
+ UINT16 apph;
+ F12DecodeOperands(cpustate, ReadAM, 1,ReadAMAddress, 1);
+
+ F12LOADOP2HALF(cpustate);
+
+ ORW(apph, (UINT16)cpustate->op1);
+
+ F12STOREOP2HALF(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opORW(v60_state *cpustate) /* TRUSTED (C too!) */
+{
+ UINT32 appw;
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAMAddress, 2);
+
+ F12LOADOP2WORD(cpustate);
+
+ ORL(appw, (UINT32)cpustate->op1);
+
+ F12STOREOP2WORD(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opOUTB(v60_state *cpustate)
+{
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 2);
+ cpustate->io->write_byte(cpustate->op2,(UINT8)cpustate->op1);
+ F12END(cpustate);
+}
+
+static UINT32 opOUTH(v60_state *cpustate)
+{
+ F12DecodeOperands(cpustate, ReadAM, 1,ReadAMAddress, 2);
+ cpustate->io->write_word_unaligned(cpustate->op2,(UINT16)cpustate->op1);
+ F12END(cpustate);
+}
+
+static UINT32 opOUTW(v60_state *cpustate)
+{
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAMAddress, 2);
+ cpustate->io->write_dword_unaligned(cpustate->op2, cpustate->op1);
+ F12END(cpustate);
+}
+
+static UINT32 opREMB(v60_state *cpustate)
+{
+ UINT8 appb;
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 0);
+
+ F12LOADOP2BYTE(cpustate);
+
+ cpustate->_OV = 0;
+ if (cpustate->op1)
+ appb= (INT8)appb % (INT8)cpustate->op1;
+ cpustate->_Z = (appb == 0);
+ cpustate->_S = ((appb & 0x80) != 0);
+
+ F12STOREOP2BYTE(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opREMH(v60_state *cpustate)
+{
+ UINT16 apph;
+ F12DecodeOperands(cpustate, ReadAM, 1,ReadAMAddress, 1);
+
+ F12LOADOP2HALF(cpustate);
+
+ cpustate->_OV = 0;
+ if (cpustate->op1)
+ apph = (INT16)apph % (INT16)cpustate->op1;
+ cpustate->_Z = (apph == 0);
+ cpustate->_S = ((apph & 0x8000) != 0);
+
+ F12STOREOP2HALF(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opREMW(v60_state *cpustate)
+{
+ UINT32 appw;
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAMAddress, 2);
+
+ F12LOADOP2WORD(cpustate);
+
+ cpustate->_OV = 0;
+ if (cpustate->op1)
+ appw = (INT32)appw % (INT32)cpustate->op1;
+ cpustate->_Z = (appw == 0);
+ cpustate->_S = ((appw & 0x80000000) != 0);
+
+ F12STOREOP2WORD(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opREMUB(v60_state *cpustate)
+{
+ UINT8 appb;
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 0);
+
+ F12LOADOP2BYTE(cpustate);
+
+ cpustate->_OV = 0;
+ if (cpustate->op1)
+ appb %= (UINT8)cpustate->op1;
+ cpustate->_Z = (appb == 0);
+ cpustate->_S = ((appb & 0x80) != 0);
+
+ F12STOREOP2BYTE(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opREMUH(v60_state *cpustate)
+{
+ UINT16 apph;
+ F12DecodeOperands(cpustate, ReadAM, 1,ReadAMAddress, 1);
+
+ F12LOADOP2HALF(cpustate);
+
+ cpustate->_OV = 0;
+ if (cpustate->op1)
+ apph %= (UINT16)cpustate->op1;
+ cpustate->_Z = (apph == 0);
+ cpustate->_S = ((apph & 0x8000) != 0);
+
+ F12STOREOP2HALF(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opREMUW(v60_state *cpustate)
+{
+ UINT32 appw;
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAMAddress, 2);
+
+ F12LOADOP2WORD(cpustate);
+
+ cpustate->_OV = 0;
+ if (cpustate->op1)
+ appw %= cpustate->op1;
+ cpustate->_Z = (appw == 0);
+ cpustate->_S = ((appw & 0x80000000) != 0);
+
+ F12STOREOP2WORD(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opROTB(v60_state *cpustate) /* TRUSTED */
+{
+ UINT8 appb;
+ INT8 i, count;
+
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 0);
+
+ F12LOADOP2BYTE(cpustate);
+
+ count = (INT8)(cpustate->op1 & 0xFF);
+ if (count > 0)
+ {
+ for (i = 0;i < count;i++)
+ appb = (appb << 1) | ((appb & 0x80) >> 7);
+
+ cpustate->_CY = (appb & 0x1) != 0;
+ }
+ else if (count < 0)
+ {
+ count=-count;
+ for (i = 0;i < count;i++)
+ appb = (appb >> 1) | ((appb & 0x1) << 7);
+
+ cpustate->_CY = (appb & 0x80) != 0;
+ }
+ else
+ cpustate->_CY = 0;
+
+ cpustate->_OV = 0;
+ cpustate->_S = (appb & 0x80) != 0;
+ cpustate->_Z = (appb == 0);
+
+ F12STOREOP2BYTE(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opROTH(v60_state *cpustate) /* TRUSTED */
+{
+ UINT16 apph;
+ INT8 i, count;
+
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 1);
+
+ F12LOADOP2HALF(cpustate);
+
+ count = (INT8)(cpustate->op1 & 0xFF);
+ if (count > 0)
+ {
+ for (i = 0;i < count;i++)
+ apph = (apph << 1) | ((apph & 0x8000) >> 15);
+
+ cpustate->_CY = (apph & 0x1) != 0;
+ }
+ else if (count < 0)
+ {
+ count=-count;
+ for (i = 0;i < count;i++)
+ apph = (apph >> 1) | ((apph & 0x1) << 15);
+
+ cpustate->_CY = (apph & 0x8000) != 0;
+ }
+ else
+ cpustate->_CY = 0;
+
+ cpustate->_OV = 0;
+ cpustate->_S = (apph & 0x8000) != 0;
+ cpustate->_Z = (apph == 0);
+
+ F12STOREOP2HALF(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opROTW(v60_state *cpustate) /* TRUSTED */
+{
+ UINT32 appw;
+ INT8 i, count;
+
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 2);
+
+ F12LOADOP2WORD(cpustate);
+
+ count = (INT8)(cpustate->op1 & 0xFF);
+ if (count > 0)
+ {
+ for (i = 0;i < count;i++)
+ appw = (appw << 1) | ((appw & 0x80000000) >> 31);
+
+ cpustate->_CY = (appw & 0x1) != 0;
+ }
+ else if (count < 0)
+ {
+ count=-count;
+ for (i = 0;i < count;i++)
+ appw = (appw >> 1) | ((appw & 0x1) << 31);
+
+ cpustate->_CY = (appw & 0x80000000) != 0;
+ }
+ else
+ cpustate->_CY = 0;
+
+ cpustate->_OV = 0;
+ cpustate->_S = (appw & 0x80000000) != 0;
+ cpustate->_Z = (appw == 0);
+
+ F12STOREOP2WORD(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opROTCB(v60_state *cpustate) /* TRUSTED */
+{
+ UINT8 appb;
+ INT8 i, cy, count;
+
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 0);
+
+ F12LOADOP2BYTE(cpustate);
+ NORMALIZEFLAGS(cpustate);
+
+ count = (INT8)(cpustate->op1 & 0xFF);
+ if (count > 0)
+ {
+ for (i = 0;i < count;i++)
+ {
+ cy = cpustate->_CY;
+ cpustate->_CY = (UINT8)((appb & 0x80) >> 7);
+ appb = (appb << 1) | cy;
+ }
+ }
+ else if (count < 0)
+ {
+ count=-count;
+ for (i = 0;i < count;i++)
+ {
+ cy = cpustate->_CY;
+ cpustate->_CY = (appb & 1);
+ appb = (appb >> 1) | (cy << 7);
+ }
+ }
+ else
+ cpustate->_CY = 0;
+
+ cpustate->_OV = 0;
+ cpustate->_S = (appb & 0x80) != 0;
+ cpustate->_Z = (appb == 0);
+
+ F12STOREOP2BYTE(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opROTCH(v60_state *cpustate) /* TRUSTED */
+{
+ UINT16 apph;
+ INT8 i, cy, count;
+
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 1);
+
+ F12LOADOP2HALF(cpustate);
+ NORMALIZEFLAGS(cpustate);
+
+ count = (INT8)(cpustate->op1 & 0xFF);
+ if (count > 0)
+ {
+ for (i = 0;i < count;i++)
+ {
+ cy = cpustate->_CY;
+ cpustate->_CY = (UINT8)((apph & 0x8000) >> 15);
+ apph = (apph << 1) | cy;
+ }
+ }
+ else if (count < 0)
+ {
+ count=-count;
+ for (i = 0;i < count;i++)
+ {
+ cy = cpustate->_CY;
+ cpustate->_CY = (UINT8)(apph & 1);
+ apph = (apph >> 1) | ((UINT16)cy << 15);
+ }
+ }
+ else
+ cpustate->_CY = 0;
+
+ cpustate->_OV = 0;
+ cpustate->_S = (apph & 0x8000) != 0;
+ cpustate->_Z = (apph == 0);
+
+ F12STOREOP2HALF(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opROTCW(v60_state *cpustate) /* TRUSTED */
+{
+ UINT32 appw;
+ INT8 i, cy, count;
+
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 2);
+
+ F12LOADOP2WORD(cpustate);
+ NORMALIZEFLAGS(cpustate);
+
+ count = (INT8)(cpustate->op1 & 0xFF);
+ if (count > 0)
+ {
+ for (i = 0;i < count;i++)
+ {
+ cy = cpustate->_CY;
+ cpustate->_CY = (UINT8)((appw & 0x80000000) >> 31);
+ appw = (appw << 1) | cy;
+ }
+ }
+ else if (count < 0)
+ {
+ count=-count;
+ for (i = 0;i < count;i++)
+ {
+ cy = cpustate->_CY;
+ cpustate->_CY = (UINT8)(appw & 1);
+ appw = (appw >> 1) | ((UINT32)cy << 31);
+ }
+ }
+ else
+ cpustate->_CY = 0;
+
+ cpustate->_OV = 0;
+ cpustate->_S = (appw & 0x80000000) != 0;
+ cpustate->_Z = (appw == 0);
+
+ F12STOREOP2WORD(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opRVBIT(v60_state *cpustate)
+{
+ F12DecodeFirstOperand(cpustate, ReadAM, 0);
+
+ cpustate->modwritevalb =(UINT8)
+ (((cpustate->op1 & (1 << 0)) << 7) |
+ ((cpustate->op1 & (1 << 1)) << 5) |
+ ((cpustate->op1 & (1 << 2)) << 3) |
+ ((cpustate->op1 & (1 << 3)) << 1) |
+ ((cpustate->op1 & (1 << 4)) >> 1) |
+ ((cpustate->op1 & (1 << 5)) >> 3) |
+ ((cpustate->op1 & (1 << 6)) >> 5) |
+ ((cpustate->op1 & (1 << 7)) >> 7));
+
+ F12WriteSecondOperand(cpustate, 0);
+ F12END(cpustate);
+}
+
+static UINT32 opRVBYT(v60_state *cpustate) /* TRUSTED */
+{
+ F12DecodeFirstOperand(cpustate, ReadAM, 2);
+
+ cpustate->modwritevalw = ((cpustate->op1 & 0x000000FF) << 24) |
+ ((cpustate->op1 & 0x0000FF00) << 8) |
+ ((cpustate->op1 & 0x00FF0000) >> 8) |
+ ((cpustate->op1 & 0xFF000000) >> 24);
+
+ F12WriteSecondOperand(cpustate, 2);
+ F12END(cpustate);
+}
+
+static UINT32 opSET1(v60_state *cpustate) /* TRUSTED */
+{
+ UINT32 appw;
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAMAddress, 2);
+
+ F12LOADOP2WORD(cpustate);
+
+ cpustate->_CY = ((appw & (1 << cpustate->op1)) != 0);
+ cpustate->_Z = !(cpustate->_CY);
+
+ appw |= (1 << cpustate->op1);
+
+ F12STOREOP2WORD(cpustate);
+ F12END(cpustate);
+}
+
+
+static UINT32 opSETF(v60_state *cpustate)
+{
+ F12DecodeFirstOperand(cpustate, ReadAM, 0);
+
+ // Normalize the flags
+ NORMALIZEFLAGS(cpustate);
+
+ switch (cpustate->op1 & 0xF)
+ {
+ case 0:
+ if (!cpustate->_OV) cpustate->modwritevalb = 0;
+ else cpustate->modwritevalb = 1;
+ break;
+ case 1:
+ if (cpustate->_OV) cpustate->modwritevalb = 0;
+ else cpustate->modwritevalb = 1;
+ break;
+ case 2:
+ if (!cpustate->_CY) cpustate->modwritevalb = 0;
+ else cpustate->modwritevalb = 1;
+ break;
+ case 3:
+ if (cpustate->_CY) cpustate->modwritevalb = 0;
+ else cpustate->modwritevalb = 1;
+ break;
+ case 4:
+ if (!cpustate->_Z) cpustate->modwritevalb = 0;
+ else cpustate->modwritevalb = 1;
+ break;
+ case 5:
+ if (cpustate->_Z) cpustate->modwritevalb = 0;
+ else cpustate->modwritevalb = 1;
+ break;
+ case 6:
+ if (!(cpustate->_CY | cpustate->_Z)) cpustate->modwritevalb = 0;
+ else cpustate->modwritevalb = 1;
+ break;
+ case 7:
+ if ((cpustate->_CY | cpustate->_Z)) cpustate->modwritevalb = 0;
+ else cpustate->modwritevalb = 1;
+ break;
+ case 8:
+ if (!cpustate->_S) cpustate->modwritevalb = 0;
+ else cpustate->modwritevalb = 1;
+ break;
+ case 9:
+ if (cpustate->_S) cpustate->modwritevalb = 0;
+ else cpustate->modwritevalb = 1;
+ break;
+ case 10:
+ cpustate->modwritevalb = 1;
+ break;
+ case 11:
+ cpustate->modwritevalb = 0;
+ break;
+ case 12:
+ if (!(cpustate->_S^cpustate->_OV)) cpustate->modwritevalb = 0;
+ else cpustate->modwritevalb = 1;
+ break;
+ case 13:
+ if ((cpustate->_S^cpustate->_OV)) cpustate->modwritevalb = 0;
+ else cpustate->modwritevalb = 1;
+ break;
+ case 14:
+ if (!((cpustate->_S^cpustate->_OV)|cpustate->_Z)) cpustate->modwritevalb = 0;
+ else cpustate->modwritevalb = 1;
+ break;
+ case 15:
+ if (((cpustate->_S^cpustate->_OV)|cpustate->_Z)) cpustate->modwritevalb = 0;
+ else cpustate->modwritevalb = 1;
+ break;
+ }
+
+ F12WriteSecondOperand(cpustate, 0);
+
+ F12END(cpustate);
+}
+
+/*
+#define SHIFTLEFT_OY(val, count, bitsize) \
+{\
+ UINT32 tmp = ((val) >> (bitsize - 1)) & 1; \
+ tmp <<= count; \
+ tmp -= 1; \
+ tmp <<= (bitsize - (count)); \
+ cpustate->_OV = (((val) & tmp) != tmp); \
+ cpustate->_CY = (((val) & (1 << (count - 1))) != 0); \
+}
+*/
+
+// During the shift, the overflow is set if the sign bit changes at any point during the shift
+#define SHIFTLEFT_OV(val, count, bitsize) \
+{\
+ UINT32 tmp; \
+ if (count == 32) \
+ tmp = 0xFFFFFFFF; \
+ else \
+ tmp = ((1 << (count)) - 1); \
+ tmp <<= (bitsize - (count)); \
+ if (((val) >> (bitsize - 1)) & 1) \
+ cpustate->_OV = (((val) & tmp) != tmp); \
+ else \
+ cpustate->_OV = (((val) & tmp) != 0); \
+}
+
+#define SHIFTLEFT_CY(val, count, bitsize) \
+ cpustate->_CY = (UINT8)(((val) >> (bitsize - count)) & 1);
+
+
+
+#define SHIFTARITHMETICRIGHT_OV(val, count, bitsize) \
+ cpustate->_OV = 0;
+
+#define SHIFTARITHMETICRIGHT_CY(val, count, bitsize) \
+ cpustate->_CY = (UINT8)(((val) >> (count - 1)) & 1);
+
+
+
+static UINT32 opSHAB(v60_state *cpustate)
+{
+ UINT8 appb;
+ INT8 count;
+
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 0);
+
+ F12LOADOP2BYTE(cpustate);
+
+ count = (INT8)(cpustate->op1 & 0xFF);
+
+ // Special case: destination unchanged, flags set
+ if (count == 0)
+ {
+ cpustate->_CY = cpustate->_OV = 0;
+ SetSZPF_Byte(appb);
+ }
+ else if (count > 0)
+ {
+ SHIFTLEFT_OV(appb, count, 8);
+
+ // @@@ Undefined what happens to CY when count >= bitsize
+ SHIFTLEFT_CY(appb, count, 8);
+
+ // do the actual shift...
+ if (count >= 8)
+ appb = 0;
+ else
+ appb <<= count;
+
+ // and set zero and sign
+ SetSZPF_Byte(appb);
+ }
+ else
+ {
+ count = -count;
+
+ SHIFTARITHMETICRIGHT_OV(appb, count, 8);
+ SHIFTARITHMETICRIGHT_CY(appb, count, 8);
+
+ if (count >= 8)
+ appb = (appb & 0x80) ? 0xFF : 0;
+ else
+ appb = ((INT8)appb) >> count;
+
+ SetSZPF_Byte(appb);
+ }
+
+// mame_printf_debug("SHAB: %x cpustate->_CY: %d cpustate->_Z: %d cpustate->_OV: %d cpustate->_S: %d\n", appb, cpustate->_CY, cpustate->_Z, cpustate->_OV, cpustate->_S);
+
+ F12STOREOP2BYTE(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opSHAH(v60_state *cpustate)
+{
+ UINT16 apph;
+ INT8 count;
+
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 1);
+
+ F12LOADOP2HALF(cpustate);
+
+ count = (INT8)(cpustate->op1 & 0xFF);
+
+ // Special case: destination unchanged, flags set
+ if (count == 0)
+ {
+ cpustate->_CY = cpustate->_OV = 0;
+ SetSZPF_Word(apph);
+ }
+ else if (count > 0)
+ {
+ SHIFTLEFT_OV(apph, count, 16);
+
+ // @@@ Undefined what happens to CY when count >= bitsize
+ SHIFTLEFT_CY(apph, count, 16);
+
+ // do the actual shift...
+ if (count >= 16)
+ apph = 0;
+ else
+ apph <<= count;
+
+ // and set zero and sign
+ SetSZPF_Word(apph);
+ }
+ else
+ {
+ count = -count;
+
+ SHIFTARITHMETICRIGHT_OV(apph, count, 16);
+ SHIFTARITHMETICRIGHT_CY(apph, count, 16);
+
+ if (count >= 16)
+ apph = (apph & 0x8000) ? 0xFFFF : 0;
+ else
+ apph = ((INT16)apph) >> count;
+
+ SetSZPF_Word(apph);
+ }
+
+// mame_printf_debug("SHAH: %x >> %d = %x cpustate->_CY: %d cpustate->_Z: %d cpustate->_OV: %d cpustate->_S: %d\n", oldval, count, apph, cpustate->_CY, cpustate->_Z, cpustate->_OV, cpustate->_S);
+
+ F12STOREOP2HALF(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opSHAW(v60_state *cpustate)
+{
+ UINT32 appw;
+ INT8 count;
+
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 2);
+
+ F12LOADOP2WORD(cpustate);
+
+ count = (INT8)(cpustate->op1 & 0xFF);
+
+ // Special case: destination unchanged, flags set
+ if (count == 0)
+ {
+ cpustate->_CY = cpustate->_OV = 0;
+ SetSZPF_Long(appw);
+ }
+ else if (count > 0)
+ {
+ SHIFTLEFT_OV(appw, count, 32);
+
+ // @@@ Undefined what happens to CY when count >= bitsize
+ SHIFTLEFT_CY(appw, count, 32);
+
+ // do the actual shift...
+ if (count >= 32)
+ appw = 0;
+ else
+ appw <<= count;
+
+ // and set zero and sign
+ SetSZPF_Long(appw);
+ }
+ else
+ {
+ count = -count;
+
+ SHIFTARITHMETICRIGHT_OV(appw, count, 32);
+ SHIFTARITHMETICRIGHT_CY(appw, count, 32);
+
+ if (count >= 32)
+ appw = (appw & 0x80000000) ? 0xFFFFFFFF : 0;
+ else
+ appw = ((INT32)appw) >> count;
+
+ SetSZPF_Long(appw);
+ }
+
+// mame_printf_debug("SHAW: %x >> %d = %x cpustate->_CY: %d cpustate->_Z: %d cpustate->_OV: %d cpustate->_S: %d\n", oldval, count, appw, cpustate->_CY, cpustate->_Z, cpustate->_OV, cpustate->_S);
+
+ F12STOREOP2WORD(cpustate);
+ F12END(cpustate);
+}
+
+
+static UINT32 opSHLB(v60_state *cpustate) /* TRUSTED */
+{
+ UINT8 appb;
+ INT8 count;
+ UINT32 tmp;
+
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 0);
+
+ F12LOADOP2BYTE(cpustate);
+
+ count = (INT8)(cpustate->op1 & 0xFF);
+ if (count > 0)
+ {
+ // left shift flags:
+ // carry gets the last bit shifted out,
+ // overflow is always CLEARed
+
+ cpustate->_OV = 0; // default to no overflow
+
+ // now handle carry
+ tmp = appb & 0xff;
+ tmp <<= count;
+ SetCFB(tmp); // set carry properly
+
+ // do the actual shift...
+ appb <<= count;
+
+ // and set zero and sign
+ SetSZPF_Byte(appb);
+ }
+ else
+ {
+ if (count == 0)
+ {
+ // special case: clear carry and overflow, do nothing else
+ cpustate->_CY = cpustate->_OV = 0;
+ SetSZPF_Byte(appb); // doc. is unclear if this is true...
+ }
+ else
+ {
+ // right shift flags:
+ // carry = last bit shifted out
+ // overflow always cleared
+ tmp = appb & 0xff;
+ tmp >>= ((-count) - 1);
+ cpustate->_CY = (UINT8)(tmp & 0x1);
+ cpustate->_OV = 0;
+
+ appb >>= -count;
+ SetSZPF_Byte(appb);
+ }
+ }
+
+// mame_printf_debug("SHLB: %x cpustate->_CY: %d cpustate->_Z: %d cpustate->_OV: %d cpustate->_S: %d\n", appb, cpustate->_CY, cpustate->_Z, cpustate->_OV, cpustate->_S);
+
+ F12STOREOP2BYTE(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opSHLH(v60_state *cpustate) /* TRUSTED */
+{
+ UINT16 apph;
+ INT8 count;
+ UINT32 tmp;
+
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 1);
+
+ F12LOADOP2HALF(cpustate);
+
+ count = (INT8)(cpustate->op1 & 0xFF);
+// mame_printf_debug("apph: %x count: %d ", apph, count);
+ if (count > 0)
+ {
+ // left shift flags:
+ // carry gets the last bit shifted out,
+ // overflow is always CLEARed
+
+ cpustate->_OV = 0;
+
+ // now handle carry
+ tmp = apph & 0xffff;
+ tmp <<= count;
+ SetCFW(tmp); // set carry properly
+
+ // do the actual shift...
+ apph <<= count;
+
+ // and set zero and sign
+ SetSZPF_Word(apph);
+ }
+ else
+ {
+ if (count == 0)
+ {
+ // special case: clear carry and overflow, do nothing else
+ cpustate->_CY = cpustate->_OV = 0;
+ SetSZPF_Word(apph); // doc. is unclear if this is true...
+ }
+ else
+ {
+ // right shift flags:
+ // carry = last bit shifted out
+ // overflow always cleared
+ tmp = apph & 0xffff;
+ tmp >>= ((-count) - 1);
+ cpustate->_CY = (UINT8)(tmp & 0x1);
+ cpustate->_OV = 0;
+
+ apph >>= -count;
+ SetSZPF_Word(apph);
+ }
+ }
+
+// mame_printf_debug("SHLH: %x cpustate->_CY: %d cpustate->_Z: %d cpustate->_OV: %d cpustate->_S: %d\n", apph, cpustate->_CY, cpustate->_Z, cpustate->_OV, cpustate->_S);
+
+ F12STOREOP2HALF(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opSHLW(v60_state *cpustate) /* TRUSTED */
+{
+ UINT32 appw;
+ INT8 count;
+ UINT64 tmp;
+
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 2);
+
+ F12LOADOP2WORD(cpustate);
+
+ count = (INT8)(cpustate->op1 & 0xFF);
+ if (count > 0)
+ {
+ // left shift flags:
+ // carry gets the last bit shifted out,
+ // overflow is always CLEARed
+
+ cpustate->_OV = 0;
+
+ // now handle carry
+ tmp = appw & 0xffffffff;
+ tmp <<= count;
+ SetCFL(tmp); // set carry properly
+
+ // do the actual shift...
+ appw <<= count;
+
+ // and set zero and sign
+ SetSZPF_Long(appw);
+ }
+ else
+ {
+ if (count == 0)
+ {
+ // special case: clear carry and overflow, do nothing else
+ cpustate->_CY = cpustate->_OV = 0;
+ SetSZPF_Long(appw); // doc. is unclear if this is true...
+ }
+ else
+ {
+ // right shift flags:
+ // carry = last bit shifted out
+ // overflow always cleared
+ tmp = (UINT64)(appw & 0xffffffff);
+ tmp >>= ((-count) - 1);
+ cpustate->_CY = (UINT8)(tmp & 0x1);
+ cpustate->_OV = 0;
+
+ appw >>= -count;
+ SetSZPF_Long(appw);
+ }
+ }
+
+// mame_printf_debug("SHLW: %x cpustate->_CY: %d cpustate->_Z: %d cpustate->_OV: %d cpustate->_S: %d\n", appw, cpustate->_CY, cpustate->_Z, cpustate->_OV, cpustate->_S);
+
+ F12STOREOP2WORD(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opSTPR(v60_state *cpustate)
+{
+ F12DecodeFirstOperand(cpustate, ReadAM, 2);
+ if (cpustate->op1 >= 0 && cpustate->op1 <= 28)
+ cpustate->modwritevalw = cpustate->reg[cpustate->op1 + 36];
+ else
+ {
+ fatalerror("Invalid operand on STPR cpustate->PC=%x", cpustate->PC);
+ }
+ F12WriteSecondOperand(cpustate, 2);
+ F12END(cpustate);
+}
+
+
+static UINT32 opSUBB(v60_state *cpustate) /* TRUSTED (C too!) */
+{
+ UINT8 appb;
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 0);
+
+ F12LOADOP2BYTE(cpustate);
+
+ SUBB(appb, (UINT8)cpustate->op1);
+
+ F12STOREOP2BYTE(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opSUBH(v60_state *cpustate) /* TRUSTED (C too!) */
+{
+ UINT16 apph;
+ F12DecodeOperands(cpustate, ReadAM, 1,ReadAMAddress, 1);
+
+ F12LOADOP2HALF(cpustate);
+
+ SUBW(apph, (UINT16)cpustate->op1);
+
+ F12STOREOP2HALF(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opSUBW(v60_state *cpustate) /* TRUSTED (C too!) */
+{
+ UINT32 appw;
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAMAddress, 2);
+
+ F12LOADOP2WORD(cpustate);
+
+ SUBL(appw, (UINT32)cpustate->op1);
+
+ F12STOREOP2WORD(cpustate);
+ F12END(cpustate);
+}
+
+
+static UINT32 opSUBCB(v60_state *cpustate)
+{
+ UINT8 appb;
+ UINT8 src;
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 0);
+
+ F12LOADOP2BYTE(cpustate);
+
+ src = (UINT8)cpustate->op1 + (cpustate->_CY?1:0);
+ SUBB(appb, src);
+
+ F12STOREOP2BYTE(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opSUBCH(v60_state *cpustate)
+{
+ UINT16 apph;
+ UINT16 src;
+
+ F12DecodeOperands(cpustate, ReadAM, 1,ReadAMAddress, 1);
+
+ F12LOADOP2HALF(cpustate);
+
+ src = (UINT16)cpustate->op1 + (cpustate->_CY?1:0);
+ SUBW(apph, src);
+
+ F12STOREOP2HALF(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opSUBCW(v60_state *cpustate)
+{
+ UINT32 appw;
+ UINT32 src;
+
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAMAddress, 2);
+
+ F12LOADOP2WORD(cpustate);
+
+ src = (UINT32)cpustate->op1 + (cpustate->_CY?1:0);
+ SUBL(appw, src);
+
+ F12STOREOP2WORD(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opTEST1(v60_state *cpustate)
+{
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAM, 2);
+
+ cpustate->_CY = ((cpustate->op2 & (1 << cpustate->op1)) != 0);
+ cpustate->_Z = !(cpustate->_CY);
+
+ F12END(cpustate);
+}
+
+static UINT32 opUPDPSWW(v60_state *cpustate)
+{
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAM, 2);
+
+ /* can only modify condition code and control fields */
+ cpustate->op2 &= 0xFFFFFF;
+ cpustate->op1 &= 0xFFFFFF;
+ v60WritePSW(cpustate, (v60ReadPSW(cpustate) & (~cpustate->op2)) | (cpustate->op1 & cpustate->op2));
+
+ F12END(cpustate);
+}
+
+static UINT32 opUPDPSWH(v60_state *cpustate)
+{
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAM, 2);
+
+ /* can only modify condition code fields */
+ cpustate->op2 &= 0xFFFF;
+ cpustate->op1 &= 0xFFFF;
+ v60WritePSW(cpustate, (v60ReadPSW(cpustate) & (~cpustate->op2)) | (cpustate->op1 & cpustate->op2));
+
+ F12END(cpustate);
+}
+
+static UINT32 opXCHB(v60_state *cpustate) /* TRUSTED */
+{
+ UINT8 appb, temp;
+
+ F12DecodeOperands(cpustate, ReadAMAddress, 0,ReadAMAddress, 0);
+
+ F12LOADOP1BYTE(cpustate);
+ temp = appb;
+ F12LOADOP2BYTE(cpustate);
+ F12STOREOP1BYTE(cpustate);
+ appb = temp;
+ F12STOREOP2BYTE(cpustate);
+
+ F12END(cpustate)
+}
+
+static UINT32 opXCHH(v60_state *cpustate) /* TRUSTED */
+{
+ UINT16 apph, temp;
+
+ F12DecodeOperands(cpustate, ReadAMAddress, 1,ReadAMAddress, 1);
+
+ F12LOADOP1HALF(cpustate);
+ temp = apph;
+ F12LOADOP2HALF(cpustate);
+ F12STOREOP1HALF(cpustate);
+ apph = temp;
+ F12STOREOP2HALF(cpustate);
+
+ F12END(cpustate)
+}
+
+static UINT32 opXCHW(v60_state *cpustate) /* TRUSTED */
+{
+ UINT32 appw, temp;
+
+ F12DecodeOperands(cpustate, ReadAMAddress, 2,ReadAMAddress, 2);
+
+ F12LOADOP1WORD(cpustate);
+ temp = appw;
+ F12LOADOP2WORD(cpustate);
+ F12STOREOP1WORD(cpustate);
+ appw = temp;
+ F12STOREOP2WORD(cpustate);
+
+ F12END(cpustate)
+}
+
+static UINT32 opXORB(v60_state *cpustate) /* TRUSTED (C too!) */
+{
+ UINT8 appb;
+ F12DecodeOperands(cpustate, ReadAM, 0,ReadAMAddress, 0);
+
+ F12LOADOP2BYTE(cpustate);
+
+ XORB(appb, (UINT8)cpustate->op1);
+
+ F12STOREOP2BYTE(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opXORH(v60_state *cpustate) /* TRUSTED (C too!) */
+{
+ UINT16 apph;
+ F12DecodeOperands(cpustate, ReadAM, 1,ReadAMAddress, 1);
+
+ F12LOADOP2HALF(cpustate);
+
+ XORW(apph, (UINT16)cpustate->op1);
+
+ F12STOREOP2HALF(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opXORW(v60_state *cpustate) /* TRUSTED (C too!) */
+{
+ UINT32 appw;
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAMAddress, 2);
+
+ F12LOADOP2WORD(cpustate);
+
+ XORL(appw, (UINT32)cpustate->op1);
+
+ F12STOREOP2WORD(cpustate);
+ F12END(cpustate);
+}
+
+static UINT32 opMULX(v60_state *cpustate)
+{
+ INT32 a, b;
+ INT64 res;
+
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAMAddress, 3);
+
+ if (cpustate->flag2)
+ {
+ a = cpustate->reg[cpustate->op2 & 0x1F];
+ }
+ else
+ {
+ a = cpustate->program->read_dword_unaligned(cpustate->op2);
+ }
+
+ res = (INT64)a * (INT64)(INT32)cpustate->op1;
+
+ b = (INT32)((res >> 32)&0xffffffff);
+ a = (INT32)(res & 0xffffffff);
+
+ cpustate->_S = ((b & 0x80000000) != 0);
+ cpustate->_Z = (a == 0 && b == 0);
+
+ if (cpustate->flag2)
+ {
+ cpustate->reg[cpustate->op2 & 0x1F] = a;
+ cpustate->reg[(cpustate->op2 & 0x1F) + 1] = b;
+ }
+ else
+ {
+ cpustate->program->write_dword_unaligned(cpustate->op2, a);
+ cpustate->program->write_dword_unaligned(cpustate->op2 + 4, b);
+ }
+
+ F12END(cpustate);
+}
+
+static UINT32 opMULUX(v60_state *cpustate)
+{
+ INT32 a, b;
+ UINT64 res;
+
+ F12DecodeOperands(cpustate, ReadAM, 2,ReadAMAddress, 3);
+
+ if (cpustate->flag2)
+ {
+ a = cpustate->reg[cpustate->op2 & 0x1F];
+ }
+ else
+ {
+ a = cpustate->program->read_dword_unaligned(cpustate->op2);
+ }
+
+ res = (UINT64)a * (UINT64)cpustate->op1;
+ b = (INT32)((res >> 32)&0xffffffff);
+ a = (INT32)(res & 0xffffffff);
+
+ cpustate->_S = ((b & 0x80000000) != 0);
+ cpustate->_Z = (a == 0 && b == 0);
+
+ if (cpustate->flag2)
+ {
+ cpustate->reg[cpustate->op2 & 0x1F] = a;
+ cpustate->reg[(cpustate->op2 & 0x1F) + 1] = b;
+ }
+ else
+ {
+ cpustate->program->write_dword_unaligned(cpustate->op2, a);
+ cpustate->program->write_dword_unaligned(cpustate->op2 + 4, b);
+ }
+
+ F12END(cpustate);
+}
diff --git a/trunk/src/emu/cpu/v60/op2.c b/trunk/src/emu/cpu/v60/op2.c
new file mode 100644
index 00000000000..d5895775d87
--- /dev/null
+++ b/trunk/src/emu/cpu/v60/op2.c
@@ -0,0 +1,353 @@
+
+
+#define F2END(cs) \
+ return 2 + (cs)->amlength1 + (cs)->amlength2;
+
+#define F2LOADOPFLOAT(cs, num) \
+ if ((cs)->flag##num) \
+ appf = u2f((cs)->reg[(cs)->op##num]); \
+ else \
+ appf = u2f((cs)->program->read_dword_unaligned((cs)->op##num));
+
+#define F2STOREOPFLOAT(cs,num) \
+ if ((cs)->flag##num) \
+ (cs)->reg[(cs)->op##num] = f2u(appf); \
+ else \
+ (cs)->program->write_dword_unaligned((cs)->op##num, f2u(appf));
+
+static void F2DecodeFirstOperand(v60_state *cpustate, UINT32 (*DecodeOp1)(v60_state *), UINT8 dim1)
+{
+ cpustate->moddim = dim1;
+ cpustate->modm = cpustate->instflags & 0x40;
+ cpustate->modadd = cpustate->PC + 2;
+ cpustate->amlength1 = DecodeOp1(cpustate);
+ cpustate->op1 = cpustate->amout;
+ cpustate->flag1 = cpustate->amflag;
+}
+
+static void F2DecodeSecondOperand(v60_state *cpustate, UINT32 (*DecodeOp2)(v60_state *), UINT8 dim2)
+{
+ cpustate->moddim = dim2;
+ cpustate->modm = cpustate->instflags & 0x20;
+ cpustate->modadd = cpustate->PC + 2 + cpustate->amlength1;
+ cpustate->amlength2 = DecodeOp2(cpustate);
+ cpustate->op2 = cpustate->amout;
+ cpustate->flag2 = cpustate->amflag;
+}
+
+static void F2WriteSecondOperand(v60_state *cpustate, UINT8 dim2)
+{
+ cpustate->moddim = dim2;
+ cpustate->modm = cpustate->instflags & 0x20;
+ cpustate->modadd = cpustate->PC + 2 + cpustate->amlength1;
+ cpustate->amlength2 = WriteAM(cpustate);
+}
+
+static UINT32 opCVTWS(v60_state *cpustate)
+{
+ float val;
+
+ F2DecodeFirstOperand(cpustate, ReadAM, 2);
+
+ // Convert to float
+ val = (float)(INT32)cpustate->op1;
+ cpustate->modwritevalw = f2u(val);
+
+ cpustate->_OV = 0;
+ cpustate->_CY = (val < 0.0f);
+ cpustate->_S = ((cpustate->modwritevalw & 0x80000000) != 0);
+ cpustate->_Z = (val == 0.0f);
+
+ F2WriteSecondOperand(cpustate, 2);
+ F2END(cpustate);
+}
+
+static UINT32 opCVTSW(v60_state *cpustate)
+{
+ float val;
+
+ F2DecodeFirstOperand(cpustate, ReadAM, 2);
+
+ // Convert to UINT32
+ val = u2f(cpustate->op1);
+ cpustate->modwritevalw = (UINT32)val;
+
+ cpustate->_OV = 0;
+ cpustate->_CY =(val < 0.0f);
+ cpustate->_S = ((cpustate->modwritevalw & 0x80000000) != 0);
+ cpustate->_Z = (val == 0.0f);
+
+ F2WriteSecondOperand(cpustate, 2);
+ F2END(cpustate);
+}
+
+static UINT32 opMOVFS(v60_state *cpustate)
+{
+ F2DecodeFirstOperand(cpustate, ReadAM, 2);
+ cpustate->modwritevalw = cpustate->op1;
+ F2WriteSecondOperand(cpustate, 2);
+ F2END(cpustate);
+}
+
+static UINT32 opNEGFS(v60_state *cpustate)
+{
+ float appf;
+
+ F2DecodeFirstOperand(cpustate, ReadAM, 2);
+ F2DecodeSecondOperand(cpustate, ReadAMAddress, 2);
+
+ appf = -u2f(cpustate->op1);
+
+ cpustate->_OV = 0;
+ cpustate->_CY = (appf < 0.0f);
+ cpustate->_S = ((f2u(appf) & 0x80000000) != 0);
+ cpustate->_Z = (appf == 0.0f);
+
+ F2STOREOPFLOAT(cpustate, 2);
+ F2END(cpustate)
+}
+
+static UINT32 opABSFS(v60_state *cpustate)
+{
+ float appf;
+
+ F2DecodeFirstOperand(cpustate, ReadAM, 2);
+ F2DecodeSecondOperand(cpustate, ReadAMAddress, 2);
+
+ appf = u2f(cpustate->op1);
+
+ if(appf < 0)
+ appf = -appf;
+
+ cpustate->_OV = 0;
+ cpustate->_CY = 0;
+ cpustate->_S = ((f2u(appf) & 0x80000000) != 0);
+ cpustate->_Z = (appf == 0.0f);
+
+ F2STOREOPFLOAT(cpustate, 2);
+ F2END(cpustate)
+}
+
+static UINT32 opADDFS(v60_state *cpustate)
+{
+ UINT32 appw;
+ float appf;
+
+ F2DecodeFirstOperand(cpustate, ReadAM, 2);
+ F2DecodeSecondOperand(cpustate, ReadAMAddress, 2);
+
+ F2LOADOPFLOAT(cpustate, 2);
+
+ appf += u2f(cpustate->op1);
+
+ appw = f2u(appf);
+ cpustate->_OV = cpustate->_CY = 0;
+ cpustate->_S = ((appw & 0x80000000) != 0);
+ cpustate->_Z = (appw == 0);
+
+ F2STOREOPFLOAT(cpustate, 2);
+ F2END(cpustate)
+}
+
+static UINT32 opSUBFS(v60_state *cpustate)
+{
+ UINT32 appw;
+ float appf;
+
+ F2DecodeFirstOperand(cpustate, ReadAM, 2);
+ F2DecodeSecondOperand(cpustate, ReadAMAddress, 2);
+
+ F2LOADOPFLOAT(cpustate, 2);
+
+ appf -= u2f(cpustate->op1);
+
+ appw = f2u(appf);
+ cpustate->_OV = cpustate->_CY = 0;
+ cpustate->_S = ((appw & 0x80000000) != 0);
+ cpustate->_Z = (appw == 0);
+
+ F2STOREOPFLOAT(cpustate, 2);
+ F2END(cpustate)
+}
+
+static UINT32 opMULFS(v60_state *cpustate)
+{
+ UINT32 appw;
+ float appf;
+
+ F2DecodeFirstOperand(cpustate, ReadAM, 2);
+ F2DecodeSecondOperand(cpustate, ReadAMAddress, 2);
+
+ F2LOADOPFLOAT(cpustate, 2);
+
+ appf *= u2f(cpustate->op1);
+
+ appw = f2u(appf);
+ cpustate->_OV = cpustate->_CY = 0;
+ cpustate->_S = ((appw & 0x80000000) != 0);
+ cpustate->_Z = (appw == 0);
+
+ F2STOREOPFLOAT(cpustate, 2);
+ F2END(cpustate)
+}
+
+static UINT32 opDIVFS(v60_state *cpustate)
+{
+ UINT32 appw;
+ float appf;
+
+ F2DecodeFirstOperand(cpustate, ReadAM, 2);
+ F2DecodeSecondOperand(cpustate, ReadAMAddress, 2);
+
+ F2LOADOPFLOAT(cpustate, 2);
+
+ appf /= u2f(cpustate->op1);
+
+ appw = f2u(appf);
+ cpustate->_OV = cpustate->_CY = 0;
+ cpustate->_S = ((appw & 0x80000000) != 0);
+ cpustate->_Z = (appw == 0);
+
+ F2STOREOPFLOAT(cpustate, 2);
+ F2END(cpustate)
+}
+
+static UINT32 opSCLFS(v60_state *cpustate)
+{
+ UINT32 appw;
+ float appf;
+
+ F2DecodeFirstOperand(cpustate, ReadAM, 1);
+ F2DecodeSecondOperand(cpustate, ReadAMAddress, 2);
+
+ F2LOADOPFLOAT(cpustate, 2);
+
+ if ((INT16)cpustate->op1 < 0)
+ appf /= 1 << -(INT16)cpustate->op1;
+ else
+ appf *= 1 << cpustate->op1;
+
+ appw = f2u(appf);
+ cpustate->_OV = cpustate->_CY = 0;
+ cpustate->_S = ((appw & 0x80000000) != 0);
+ cpustate->_Z = (appw == 0);
+
+ F2STOREOPFLOAT(cpustate, 2);
+ F2END(cpustate)
+}
+
+static UINT32 opCMPF(v60_state *cpustate)
+{
+ float appf;
+
+ F2DecodeFirstOperand(cpustate, ReadAM, 2);
+ F2DecodeSecondOperand(cpustate, ReadAM, 2);
+
+ appf = u2f(cpustate->op2) - u2f(cpustate->op1);
+
+ cpustate->_Z = (appf == 0);
+ cpustate->_S = (appf < 0);
+ cpustate->_OV = 0;
+ cpustate->_CY = 0;
+
+ F2END(cpustate);
+}
+
+static UINT32 op5FUNHANDLED(v60_state *cpustate)
+{
+ fatalerror("Unhandled 5F opcode at %08x", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 op5CUNHANDLED(v60_state *cpustate)
+{
+ fatalerror("Unhandled 5C opcode at %08x", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 (*const Op5FTable[32])(v60_state *) =
+{
+ opCVTWS,
+ opCVTSW,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED,
+ op5FUNHANDLED
+};
+
+static UINT32 (*const Op5CTable[32])(v60_state *) =
+{
+ opCMPF,
+ op5CUNHANDLED,
+ op5CUNHANDLED,
+ op5CUNHANDLED,
+ op5CUNHANDLED,
+ op5CUNHANDLED,
+ op5CUNHANDLED,
+ op5CUNHANDLED,
+ opMOVFS,
+ opNEGFS,
+ opABSFS,
+ op5CUNHANDLED,
+ op5CUNHANDLED,
+ op5CUNHANDLED,
+ op5CUNHANDLED,
+ op5CUNHANDLED,
+
+ opSCLFS,
+ op5CUNHANDLED,
+ op5CUNHANDLED,
+ op5CUNHANDLED,
+ op5CUNHANDLED,
+ op5CUNHANDLED,
+ op5CUNHANDLED,
+ op5CUNHANDLED,
+ opADDFS,
+ opSUBFS,
+ opMULFS,
+ opDIVFS,
+ op5CUNHANDLED,
+ op5CUNHANDLED,
+ op5CUNHANDLED,
+ op5CUNHANDLED
+};
+
+
+static UINT32 op5F(v60_state *cpustate)
+{
+ cpustate->instflags = OpRead8(cpustate, cpustate->PC + 1);
+ return Op5FTable[cpustate->instflags & 0x1F](cpustate);
+}
+
+
+static UINT32 op5C(v60_state *cpustate)
+{
+ cpustate->instflags = OpRead8(cpustate, cpustate->PC + 1);
+ return Op5CTable[cpustate->instflags & 0x1F](cpustate);
+}
diff --git a/trunk/src/emu/cpu/v60/op3.c b/trunk/src/emu/cpu/v60/op3.c
new file mode 100644
index 00000000000..f7e5f674237
--- /dev/null
+++ b/trunk/src/emu/cpu/v60/op3.c
@@ -0,0 +1,639 @@
+static UINT32 opINCB(v60_state *cpustate) /* TRUSTED */
+{
+ UINT8 appb;
+ cpustate->modadd = cpustate->PC + 1;
+ cpustate->moddim = 0;
+
+ cpustate->amlength1 = ReadAMAddress(cpustate);
+
+ if (cpustate->amflag)
+ appb = (UINT8)cpustate->reg[cpustate->amout];
+ else
+ appb = cpustate->program->read_byte(cpustate->amout);
+
+ ADDB(appb, 1);
+
+ if (cpustate->amflag)
+ SETREG8(cpustate->reg[cpustate->amout], appb);
+ else
+ cpustate->program->write_byte(cpustate->amout, appb);
+
+ return cpustate->amlength1 + 1;
+}
+
+static UINT32 opINCH(v60_state *cpustate) /* TRUSTED */
+{
+ UINT16 apph;
+ cpustate->modadd = cpustate->PC + 1;
+ cpustate->moddim = 1;
+
+ cpustate->amlength1 = ReadAMAddress(cpustate);
+
+ if (cpustate->amflag)
+ apph = (UINT16)cpustate->reg[cpustate->amout];
+ else
+ apph = cpustate->program->read_word_unaligned(cpustate->amout);
+
+ ADDW(apph, 1);
+
+ if (cpustate->amflag)
+ SETREG16(cpustate->reg[cpustate->amout], apph);
+ else
+ cpustate->program->write_word_unaligned(cpustate->amout, apph);
+
+ return cpustate->amlength1 + 1;
+}
+
+static UINT32 opINCW(v60_state *cpustate) /* TRUSTED */
+{
+ UINT32 appw;
+ cpustate->modadd = cpustate->PC + 1;
+ cpustate->moddim = 2;
+
+ cpustate->amlength1 = ReadAMAddress(cpustate);
+
+ if (cpustate->amflag)
+ appw = cpustate->reg[cpustate->amout];
+ else
+ appw = cpustate->program->read_dword_unaligned(cpustate->amout);
+
+ ADDL(appw, 1);
+
+ if (cpustate->amflag)
+ cpustate->reg[cpustate->amout] = appw;
+ else
+ cpustate->program->write_dword_unaligned(cpustate->amout, appw);
+
+ return cpustate->amlength1 + 1;
+}
+
+static UINT32 opDECB(v60_state *cpustate) /* TRUSTED */
+{
+ UINT8 appb;
+ cpustate->modadd = cpustate->PC + 1;
+ cpustate->moddim = 0;
+
+ cpustate->amlength1 = ReadAMAddress(cpustate);
+
+ if (cpustate->amflag)
+ appb = (UINT8)cpustate->reg[cpustate->amout];
+ else
+ appb = cpustate->program->read_byte(cpustate->amout);
+
+ SUBB(appb, 1);
+
+ if (cpustate->amflag)
+ SETREG8(cpustate->reg[cpustate->amout], appb);
+ else
+ cpustate->program->write_byte(cpustate->amout, appb);
+
+ return cpustate->amlength1 + 1;
+}
+
+static UINT32 opDECH(v60_state *cpustate) /* TRUSTED */
+{
+ UINT16 apph;
+ cpustate->modadd = cpustate->PC + 1;
+ cpustate->moddim = 1;
+
+ cpustate->amlength1 = ReadAMAddress(cpustate);
+
+ if (cpustate->amflag)
+ apph = (UINT16)cpustate->reg[cpustate->amout];
+ else
+ apph = cpustate->program->read_word_unaligned(cpustate->amout);
+
+ SUBW(apph, 1);
+
+ if (cpustate->amflag)
+ SETREG16(cpustate->reg[cpustate->amout], apph);
+ else
+ cpustate->program->write_word_unaligned(cpustate->amout, apph);
+
+ return cpustate->amlength1 + 1;
+}
+
+static UINT32 opDECW(v60_state *cpustate) /* TRUSTED */
+{
+ UINT32 appw;
+ cpustate->modadd = cpustate->PC + 1;
+ cpustate->moddim = 2;
+
+ cpustate->amlength1 = ReadAMAddress(cpustate);
+
+ if (cpustate->amflag)
+ appw = cpustate->reg[cpustate->amout];
+ else
+ appw = cpustate->program->read_dword_unaligned(cpustate->amout);
+
+ SUBL(appw, 1);
+
+ if (cpustate->amflag)
+ cpustate->reg[cpustate->amout] = appw;
+ else
+ cpustate->program->write_dword_unaligned(cpustate->amout, appw);
+
+ return cpustate->amlength1 + 1;
+}
+
+static UINT32 opJMP(v60_state *cpustate) /* TRUSTED */
+{
+ cpustate->modadd = cpustate->PC + 1;
+ cpustate->moddim = 0;
+
+ // Read the address of the operand
+ ReadAMAddress(cpustate);
+
+ // It cannot be a register!!
+ assert(cpustate->amflag == 0);
+
+ // Jump there
+ cpustate->PC = cpustate->amout;
+
+ return 0;
+}
+
+static UINT32 opJSR(v60_state *cpustate) /* TRUSTED */
+{
+ cpustate->modadd = cpustate->PC + 1;
+ cpustate->moddim = 0;
+
+ // Read the address of the operand
+ cpustate->amlength1 = ReadAMAddress(cpustate);
+
+ // It cannot be a register!!
+ assert(cpustate->amflag == 0);
+
+ // Save NextPC into the stack
+ cpustate->SP -= 4;
+ cpustate->program->write_dword_unaligned(cpustate->SP, cpustate->PC + cpustate->amlength1 + 1);
+
+ // Jump there
+ cpustate->PC = cpustate->amout;
+
+ return 0;
+}
+
+static UINT32 opPREPARE(v60_state *cpustate) /* somewhat TRUSTED */
+{
+ cpustate->modadd = cpustate->PC + 1;
+ cpustate->moddim = 2;
+
+ // Read the operand
+ cpustate->amlength1 = ReadAM(cpustate);
+
+ // step 1: save frame pointer on the stack
+ cpustate->SP -= 4;
+ cpustate->program->write_dword_unaligned(cpustate->SP, cpustate->FP);
+
+ // step 2: cpustate->FP = new cpustate->SP
+ cpustate->FP = cpustate->SP;
+
+ // step 3: cpustate->SP -= operand
+ cpustate->SP -= cpustate->amout;
+
+ return cpustate->amlength1 + 1;
+}
+
+static UINT32 opRET(v60_state *cpustate) /* TRUSTED */
+{
+ cpustate->modadd = cpustate->PC + 1;
+ cpustate->moddim = 2;
+
+ // Read the operand
+ ReadAM(cpustate);
+
+ // Read return address from stack
+ cpustate->PC = cpustate->program->read_dword_unaligned(cpustate->SP);
+ cpustate->SP +=4;
+
+ // Restore cpustate->AP from stack
+ cpustate->AP = cpustate->program->read_dword_unaligned(cpustate->SP);
+ cpustate->SP +=4;
+
+ // Skip stack frame
+ cpustate->SP += cpustate->amout;
+
+ return 0;
+}
+
+static UINT32 opTRAP(v60_state *cpustate)
+{
+ UINT32 oldPSW;
+
+ cpustate->modadd = cpustate->PC + 1;
+ cpustate->moddim = 0;
+
+ // Read the operand
+ cpustate->amlength1 = ReadAM(cpustate);
+
+ // Normalize the flags
+ NORMALIZEFLAGS(cpustate);
+
+ switch ((cpustate->amout >> 4) & 0xF)
+ {
+ case 0:
+ if (!cpustate->_OV) return cpustate->amlength1 + 1;
+ else break;
+ case 1:
+ if (cpustate->_OV) return cpustate->amlength1 + 1;
+ else break;
+ case 2:
+ if (!cpustate->_CY) return cpustate->amlength1 + 1;
+ else break;
+ case 3:
+ if (cpustate->_CY) return cpustate->amlength1 + 1;
+ else break;
+ case 4:
+ if (!cpustate->_Z) return cpustate->amlength1 + 1;
+ else break;
+ case 5:
+ if (cpustate->_Z) return cpustate->amlength1 + 1;
+ else break;
+ case 6:
+ if (!(cpustate->_CY | cpustate->_Z)) return cpustate->amlength1 + 1;
+ else break;
+ case 7:
+ if ((cpustate->_CY | cpustate->_Z)) return cpustate->amlength1 + 1;
+ else break;
+ case 8:
+ if (!cpustate->_S) return cpustate->amlength1 + 1;
+ else break;
+ case 9:
+ if (cpustate->_S) return cpustate->amlength1 + 1;
+ else break;
+ case 10:
+ break;
+ case 11:
+ return cpustate->amlength1 + 1;
+ case 12:
+ if (!(cpustate->_S^cpustate->_OV)) return cpustate->amlength1 + 1;
+ else break;
+ case 13:
+ if ((cpustate->_S^cpustate->_OV)) return cpustate->amlength1 + 1;
+ else break;
+ case 14:
+ if (!((cpustate->_S^cpustate->_OV)|cpustate->_Z)) return cpustate->amlength1 + 1;
+ else break;
+ case 15:
+ if (((cpustate->_S^cpustate->_OV)|cpustate->_Z)) return cpustate->amlength1 + 1;
+ else break;
+ }
+
+ oldPSW = v60_update_psw_for_exception(cpustate, 0, 0);
+
+ // Issue the software trap with interrupts
+ cpustate->SP -= 4;
+ cpustate->program->write_dword_unaligned(cpustate->SP, EXCEPTION_CODE_AND_SIZE(0x3000 + 0x100 * (cpustate->amout & 0xF), 4));
+
+ cpustate->SP -= 4;
+ cpustate->program->write_dword_unaligned(cpustate->SP, oldPSW);
+
+ cpustate->SP -= 4;
+ cpustate->program->write_dword_unaligned(cpustate->SP, cpustate->PC + cpustate->amlength1 + 1);
+
+ cpustate->PC = GETINTVECT(cpustate, 48 + (cpustate->amout & 0xF));
+
+ return 0;
+}
+
+static UINT32 opRETIU(v60_state *cpustate) /* TRUSTED */
+{
+ UINT32 newPSW;
+ cpustate->modadd = cpustate->PC + 1;
+ cpustate->moddim = 1;
+
+ // Read the operand
+ ReadAM(cpustate);
+
+ // Restore cpustate->PC and cpustate->PSW from stack
+ cpustate->PC = cpustate->program->read_dword_unaligned(cpustate->SP);
+ cpustate->SP += 4;
+
+ newPSW = cpustate->program->read_dword_unaligned(cpustate->SP);
+ cpustate->SP += 4;
+
+ // Destroy stack frame
+ cpustate->SP += cpustate->amout;
+
+ v60WritePSW(cpustate, newPSW);
+
+ return 0;
+}
+
+static UINT32 opRETIS(v60_state *cpustate)
+{
+ UINT32 newPSW;
+
+ cpustate->modadd = cpustate->PC + 1;
+ cpustate->moddim = 1;
+
+ // Read the operand
+ ReadAM(cpustate);
+
+ // Restore cpustate->PC and cpustate->PSW from stack
+ cpustate->PC = cpustate->program->read_dword_unaligned(cpustate->SP);
+ cpustate->SP += 4;
+
+ newPSW = cpustate->program->read_dword_unaligned(cpustate->SP);
+ cpustate->SP += 4;
+
+ // Destroy stack frame
+ cpustate->SP += cpustate->amout;
+
+ v60WritePSW(cpustate, newPSW);
+
+ return 0;
+}
+
+static UINT32 opSTTASK(v60_state *cpustate)
+{
+ int i;
+ UINT32 adr;
+
+ cpustate->modadd = cpustate->PC + 1;
+ cpustate->moddim = 2;
+
+ cpustate->amlength1 = ReadAM(cpustate);
+
+ adr = cpustate->TR;
+
+ v60WritePSW(cpustate, v60ReadPSW(cpustate) | 0x10000000);
+ v60SaveStack(cpustate);
+
+ cpustate->program->write_dword_unaligned(adr, cpustate->TKCW);
+ adr += 4;
+ if(cpustate->SYCW & 0x100) {
+ cpustate->program->write_dword_unaligned(adr, cpustate->L0SP);
+ adr += 4;
+ }
+ if(cpustate->SYCW & 0x200) {
+ cpustate->program->write_dword_unaligned(adr, cpustate->L1SP);
+ adr += 4;
+ }
+ if(cpustate->SYCW & 0x400) {
+ cpustate->program->write_dword_unaligned(adr, cpustate->L2SP);
+ adr += 4;
+ }
+ if(cpustate->SYCW & 0x800) {
+ cpustate->program->write_dword_unaligned(adr, cpustate->L3SP);
+ adr += 4;
+ }
+
+ // 31 registers supported, _not_ 32
+ for(i = 0; i < 31; i++)
+ if(cpustate->amout & (1 << i)) {
+ cpustate->program->write_dword_unaligned(adr, cpustate->reg[i]);
+ adr += 4;
+ }
+
+ // #### Ignore the virtual addressing crap.
+
+ return cpustate->amlength1 + 1;
+}
+
+static UINT32 opGETPSW(v60_state *cpustate)
+{
+ cpustate->modadd = cpustate->PC + 1;
+ cpustate->moddim = 2;
+ cpustate->modwritevalw = v60ReadPSW(cpustate);
+
+ // Write cpustate->PSW to the operand
+ cpustate->amlength1 = WriteAM(cpustate);
+
+ return cpustate->amlength1 + 1;
+}
+
+static UINT32 opTASI(v60_state *cpustate)
+{
+ UINT8 appb;
+ cpustate->modadd = cpustate->PC + 1;
+ cpustate->moddim = 0;
+
+ // Load the address of the operand
+ cpustate->amlength1 = ReadAMAddress(cpustate);
+
+ // Load UINT8 from the address
+ if (cpustate->amflag)
+ appb = (UINT8)cpustate->reg[cpustate->amout & 0x1F];
+ else
+ appb = cpustate->program->read_byte(cpustate->amout);
+
+ // Set the flags for SUB appb, FF
+ SUBB(appb, 0xff);
+
+ // Write FF in the operand
+ if (cpustate->amflag)
+ SETREG8(cpustate->reg[cpustate->amout & 0x1F], 0xFF);
+ else
+ cpustate->program->write_byte(cpustate->amout, 0xFF);
+
+ return cpustate->amlength1 + 1;
+}
+
+static UINT32 opCLRTLB(v60_state *cpustate)
+{
+ cpustate->modadd = cpustate->PC + 1;
+ cpustate->moddim = 2;
+
+ // Read the operand
+ cpustate->amlength1 = ReadAM(cpustate);
+
+ // @@@ TLB not yet emulated
+
+ return cpustate->amlength1 + 1;
+}
+
+static UINT32 opPOPM(v60_state *cpustate)
+{
+ int i;
+
+ cpustate->modadd = cpustate->PC + 1;
+ cpustate->moddim = 2;
+
+ // Read the bit register list
+ cpustate->amlength1 = ReadAM(cpustate);
+
+ for (i = 0;i < 31;i++)
+ if (cpustate->amout & (1 << i))
+ {
+ cpustate->reg[i] = cpustate->program->read_dword_unaligned(cpustate->SP);
+ cpustate->SP += 4;
+ }
+
+ if (cpustate->amout & (1 << 31))
+ {
+ v60WritePSW(cpustate, (v60ReadPSW(cpustate) & 0xffff0000) | cpustate->program->read_word_unaligned(cpustate->SP));
+ cpustate->SP += 4;
+ }
+
+ return cpustate->amlength1 + 1;
+}
+
+static UINT32 opPUSHM(v60_state *cpustate)
+{
+ int i;
+
+ cpustate->modadd = cpustate->PC + 1;
+ cpustate->moddim = 2;
+
+ // Read the bit register list
+ cpustate->amlength1 = ReadAM(cpustate);
+
+ if (cpustate->amout & (1 << 31))
+ {
+ cpustate->SP -= 4;
+ cpustate->program->write_dword_unaligned(cpustate->SP, v60ReadPSW(cpustate));
+ }
+
+ for (i = 0;i < 31;i++)
+ if (cpustate->amout & (1 << (30 - i)))
+ {
+ cpustate->SP -= 4;
+ cpustate->program->write_dword_unaligned(cpustate->SP, cpustate->reg[(30 - i)]);
+ }
+
+
+ return cpustate->amlength1 + 1;
+}
+
+static UINT32 opTESTB(v60_state *cpustate) /* TRUSTED */
+{
+ cpustate->modadd = cpustate->PC + 1;
+ cpustate->moddim = 0;
+
+ // Read the operand
+ cpustate->amlength1 = ReadAM(cpustate);
+
+ cpustate->_Z = (cpustate->amout == 0);
+ cpustate->_S = ((cpustate->amout & 0x80) != 0);
+ cpustate->_CY = 0;
+ cpustate->_OV = 0;
+
+ return cpustate->amlength1 + 1;
+}
+
+static UINT32 opTESTH(v60_state *cpustate) /* TRUSTED */
+{
+ cpustate->modadd = cpustate->PC + 1;
+ cpustate->moddim = 1;
+
+ // Read the operand
+ cpustate->amlength1 = ReadAM(cpustate);
+
+ cpustate->_Z = (cpustate->amout == 0);
+ cpustate->_S = ((cpustate->amout & 0x8000) != 0);
+ cpustate->_CY = 0;
+ cpustate->_OV = 0;
+
+ return cpustate->amlength1 + 1;
+}
+
+static UINT32 opTESTW(v60_state *cpustate) /* TRUSTED */
+{
+ cpustate->modadd = cpustate->PC + 1;
+ cpustate->moddim = 2;
+
+ // Read the operand
+ cpustate->amlength1 = ReadAM(cpustate);
+
+ cpustate->_Z = (cpustate->amout == 0);
+ cpustate->_S = ((cpustate->amout & 0x80000000) != 0);
+ cpustate->_CY = 0;
+ cpustate->_OV = 0;
+
+ return cpustate->amlength1 + 1;
+}
+
+static UINT32 opPUSH(v60_state *cpustate)
+{
+ cpustate->modadd = cpustate->PC + 1;
+ cpustate->moddim = 2;
+
+ cpustate->amlength1 = ReadAM(cpustate);
+
+ cpustate->SP-=4;
+ cpustate->program->write_dword_unaligned(cpustate->SP, cpustate->amout);
+
+ return cpustate->amlength1 + 1;
+}
+
+static UINT32 opPOP(v60_state *cpustate)
+{
+ cpustate->modadd = cpustate->PC + 1;
+ cpustate->moddim = 2;
+ cpustate->modwritevalw = cpustate->program->read_dword_unaligned(cpustate->SP);
+ cpustate->SP +=4;
+ cpustate->amlength1 = WriteAM(cpustate);
+
+ return cpustate->amlength1 + 1;
+}
+
+
+static UINT32 opINCB_0(v60_state *cpustate) { cpustate->modm = 0; return opINCB(cpustate); }
+static UINT32 opINCB_1(v60_state *cpustate) { cpustate->modm = 1; return opINCB(cpustate); }
+static UINT32 opINCH_0(v60_state *cpustate) { cpustate->modm = 0; return opINCH(cpustate); }
+static UINT32 opINCH_1(v60_state *cpustate) { cpustate->modm = 1; return opINCH(cpustate); }
+static UINT32 opINCW_0(v60_state *cpustate) { cpustate->modm = 0; return opINCW(cpustate); }
+static UINT32 opINCW_1(v60_state *cpustate) { cpustate->modm = 1; return opINCW(cpustate); }
+
+static UINT32 opDECB_0(v60_state *cpustate) { cpustate->modm = 0; return opDECB(cpustate); }
+static UINT32 opDECB_1(v60_state *cpustate) { cpustate->modm = 1; return opDECB(cpustate); }
+static UINT32 opDECH_0(v60_state *cpustate) { cpustate->modm = 0; return opDECH(cpustate); }
+static UINT32 opDECH_1(v60_state *cpustate) { cpustate->modm = 1; return opDECH(cpustate); }
+static UINT32 opDECW_0(v60_state *cpustate) { cpustate->modm = 0; return opDECW(cpustate); }
+static UINT32 opDECW_1(v60_state *cpustate) { cpustate->modm = 1; return opDECW(cpustate); }
+
+static UINT32 opJMP_0(v60_state *cpustate) { cpustate->modm = 0; return opJMP(cpustate); }
+static UINT32 opJMP_1(v60_state *cpustate) { cpustate->modm = 1; return opJMP(cpustate); }
+
+static UINT32 opJSR_0(v60_state *cpustate) { cpustate->modm = 0; return opJSR(cpustate); }
+static UINT32 opJSR_1(v60_state *cpustate) { cpustate->modm = 1; return opJSR(cpustate); }
+
+static UINT32 opPREPARE_0(v60_state *cpustate) { cpustate->modm = 0; return opPREPARE(cpustate); }
+static UINT32 opPREPARE_1(v60_state *cpustate) { cpustate->modm = 1; return opPREPARE(cpustate); }
+
+static UINT32 opRET_0(v60_state *cpustate) { cpustate->modm = 0; return opRET(cpustate); }
+static UINT32 opRET_1(v60_state *cpustate) { cpustate->modm = 1; return opRET(cpustate); }
+
+static UINT32 opTRAP_0(v60_state *cpustate) { cpustate->modm = 0; return opTRAP(cpustate); }
+static UINT32 opTRAP_1(v60_state *cpustate) { cpustate->modm = 1; return opTRAP(cpustate); }
+
+static UINT32 opRETIU_0(v60_state *cpustate) { cpustate->modm = 0; return opRETIU(cpustate); }
+static UINT32 opRETIU_1(v60_state *cpustate) { cpustate->modm = 1; return opRETIU(cpustate); }
+
+static UINT32 opRETIS_0(v60_state *cpustate) { cpustate->modm = 0; return opRETIS(cpustate); }
+static UINT32 opRETIS_1(v60_state *cpustate) { cpustate->modm = 1; return opRETIS(cpustate); }
+
+static UINT32 opGETPSW_0(v60_state *cpustate) { cpustate->modm = 0; return opGETPSW(cpustate); }
+static UINT32 opGETPSW_1(v60_state *cpustate) { cpustate->modm = 1; return opGETPSW(cpustate); }
+
+static UINT32 opTASI_0(v60_state *cpustate) { cpustate->modm = 0; return opTASI(cpustate); }
+static UINT32 opTASI_1(v60_state *cpustate) { cpustate->modm = 1; return opTASI(cpustate); }
+
+static UINT32 opCLRTLB_0(v60_state *cpustate) { cpustate->modm = 0; return opCLRTLB(cpustate); }
+static UINT32 opCLRTLB_1(v60_state *cpustate) { cpustate->modm = 1; return opCLRTLB(cpustate); }
+
+static UINT32 opPOPM_0(v60_state *cpustate) { cpustate->modm = 0; return opPOPM(cpustate); }
+static UINT32 opPOPM_1(v60_state *cpustate) { cpustate->modm = 1; return opPOPM(cpustate); }
+
+static UINT32 opPUSHM_0(v60_state *cpustate) { cpustate->modm = 0; return opPUSHM(cpustate); }
+static UINT32 opPUSHM_1(v60_state *cpustate) { cpustate->modm = 1; return opPUSHM(cpustate); }
+
+static UINT32 opTESTB_0(v60_state *cpustate) { cpustate->modm = 0; return opTESTB(cpustate); }
+static UINT32 opTESTB_1(v60_state *cpustate) { cpustate->modm = 1; return opTESTB(cpustate); }
+
+static UINT32 opTESTH_0(v60_state *cpustate) { cpustate->modm = 0; return opTESTH(cpustate); }
+static UINT32 opTESTH_1(v60_state *cpustate) { cpustate->modm = 1; return opTESTH(cpustate); }
+
+static UINT32 opTESTW_0(v60_state *cpustate) { cpustate->modm = 0; return opTESTW(cpustate); }
+static UINT32 opTESTW_1(v60_state *cpustate) { cpustate->modm = 1; return opTESTW(cpustate); }
+
+static UINT32 opPUSH_0(v60_state *cpustate) { cpustate->modm = 0; return opPUSH(cpustate); }
+static UINT32 opPUSH_1(v60_state *cpustate) { cpustate->modm = 1; return opPUSH(cpustate); }
+
+static UINT32 opPOP_0(v60_state *cpustate) { cpustate->modm = 0; return opPOP(cpustate); }
+static UINT32 opPOP_1(v60_state *cpustate) { cpustate->modm = 1; return opPOP(cpustate); }
+
+static UINT32 opSTTASK_0(v60_state *cpustate) { cpustate->modm = 0; return opSTTASK(cpustate); }
+static UINT32 opSTTASK_1(v60_state *cpustate) { cpustate->modm = 1; return opSTTASK(cpustate); }
diff --git a/trunk/src/emu/cpu/v60/op4.c b/trunk/src/emu/cpu/v60/op4.c
new file mode 100644
index 00000000000..dd83915c1c9
--- /dev/null
+++ b/trunk/src/emu/cpu/v60/op4.c
@@ -0,0 +1,354 @@
+
+/*
+ FULLY TRUSTED
+*/
+
+static UINT32 opBGT8(v60_state *cpustate) /* TRUSTED */
+{
+ NORMALIZEFLAGS(cpustate);
+
+ if (!((cpustate->_S ^ cpustate->_OV) | cpustate->_Z))
+ {
+ cpustate->PC += (INT8)OpRead8(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 2;
+}
+
+static UINT32 opBGT16(v60_state *cpustate) /* TRUSTED */
+{
+ NORMALIZEFLAGS(cpustate);
+
+ if (!((cpustate->_S ^ cpustate->_OV) | cpustate->_Z))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 3;
+}
+
+
+static UINT32 opBGE8(v60_state *cpustate) /* TRUSTED */
+{
+ NORMALIZEFLAGS(cpustate);
+
+ if (!(cpustate->_S ^ cpustate->_OV))
+ {
+ cpustate->PC += (INT8)OpRead8(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 2;
+}
+
+static UINT32 opBGE16(v60_state *cpustate) /* TRUSTED */
+{
+ NORMALIZEFLAGS(cpustate);
+
+ if (!(cpustate->_S ^ cpustate->_OV))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 3;
+}
+
+static UINT32 opBLT8(v60_state *cpustate) /* TRUSTED */
+{
+ NORMALIZEFLAGS(cpustate);
+
+ if ((cpustate->_S ^ cpustate->_OV))
+ {
+ cpustate->PC += (INT8)OpRead8(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 2;
+}
+
+static UINT32 opBLT16(v60_state *cpustate) /* TRUSTED */
+{
+ NORMALIZEFLAGS(cpustate);
+
+ if ((cpustate->_S ^ cpustate->_OV))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 3;
+}
+
+
+static UINT32 opBLE8(v60_state *cpustate) /* TRUSTED */
+{
+ NORMALIZEFLAGS(cpustate);
+
+ if (((cpustate->_S ^ cpustate->_OV) | cpustate->_Z))
+ {
+ cpustate->PC += (INT8)OpRead8(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 2;
+}
+
+static UINT32 opBLE16(v60_state *cpustate) /* TRUSTED */
+{
+ NORMALIZEFLAGS(cpustate);
+
+ if (((cpustate->_S ^ cpustate->_OV) | cpustate->_Z))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 3;
+}
+
+static UINT32 opBH8(v60_state *cpustate) /* TRUSTED */
+{
+ if (!(cpustate->_CY | cpustate->_Z))
+ {
+ cpustate->PC += (INT8)OpRead8(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 2;
+}
+
+static UINT32 opBH16(v60_state *cpustate) /* TRUSTED */
+{
+ if (!(cpustate->_CY | cpustate->_Z))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 3;
+}
+
+static UINT32 opBNH8(v60_state *cpustate) /* TRUSTED */
+{
+ if ((cpustate->_CY | cpustate->_Z))
+ {
+ cpustate->PC += (INT8)OpRead8(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 2;
+}
+
+static UINT32 opBNH16(v60_state *cpustate) /* TRUSTED */
+{
+ if ((cpustate->_CY | cpustate->_Z))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 3;
+}
+
+static UINT32 opBNL8(v60_state *cpustate) /* TRUSTED */
+{
+ if (!(cpustate->_CY))
+ {
+ cpustate->PC += (INT8)OpRead8(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 2;
+}
+
+static UINT32 opBNL16(v60_state *cpustate) /* TRUSTED */
+{
+ if (!(cpustate->_CY))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 3;
+}
+
+static UINT32 opBL8(v60_state *cpustate) /* TRUSTED */
+{
+ if ((cpustate->_CY))
+ {
+ cpustate->PC += (INT8)OpRead8(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 2;
+}
+
+static UINT32 opBL16(v60_state *cpustate) /* TRUSTED */
+{
+ if ((cpustate->_CY))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 3;
+}
+
+static UINT32 opBNE8(v60_state *cpustate) /* TRUSTED */
+{
+ if (!(cpustate->_Z))
+ {
+ cpustate->PC += (INT8)OpRead8(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 2;
+}
+
+static UINT32 opBNE16(v60_state *cpustate) /* TRUSTED */
+{
+ if (!(cpustate->_Z))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 3;
+}
+
+static UINT32 opBE8(v60_state *cpustate) /* TRUSTED */
+{
+ if ((cpustate->_Z))
+ {
+ cpustate->PC += (INT8)OpRead8(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 2;
+}
+
+static UINT32 opBE16(v60_state *cpustate) /* TRUSTED */
+{
+ if ((cpustate->_Z))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 3;
+}
+
+static UINT32 opBNV8(v60_state *cpustate) /* TRUSTED */
+{
+ if (!(cpustate->_OV))
+ {
+ cpustate->PC += (INT8)OpRead8(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 2;
+}
+
+static UINT32 opBNV16(v60_state *cpustate) /* TRUSTED */
+{
+ if (!(cpustate->_OV))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 3;
+}
+
+static UINT32 opBV8(v60_state *cpustate) /* TRUSTED */
+{
+ if ((cpustate->_OV))
+ {
+ cpustate->PC += (INT8)OpRead8(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 2;
+}
+
+static UINT32 opBV16(v60_state *cpustate) /* TRUSTED */
+{
+ if ((cpustate->_OV))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 3;
+}
+
+static UINT32 opBP8(v60_state *cpustate) /* TRUSTED */
+{
+ if (!(cpustate->_S))
+ {
+ cpustate->PC += (INT8)OpRead8(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 2;
+}
+
+static UINT32 opBP16(v60_state *cpustate) /* TRUSTED */
+{
+ if (!(cpustate->_S))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 3;
+}
+
+static UINT32 opBN8(v60_state *cpustate) /* TRUSTED */
+{
+ if ((cpustate->_S))
+ {
+ cpustate->PC += (INT8)OpRead8(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 2;
+}
+
+static UINT32 opBN16(v60_state *cpustate) /* TRUSTED */
+{
+ if ((cpustate->_S))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 1);
+ return 0;
+ }
+
+ return 3;
+}
+
+static UINT32 opBR8(v60_state *cpustate) /* TRUSTED */
+{
+ cpustate->PC += (INT8)OpRead8(cpustate, cpustate->PC + 1);
+ return 0;
+}
+
+static UINT32 opBR16(v60_state *cpustate) /* TRUSTED */
+{
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 1);
+ return 0;
+}
+
+static UINT32 opBSR(v60_state *cpustate) /* TRUSTED */
+{
+ // Save Next cpustate->PC onto the stack
+ cpustate->SP -= 4;
+ cpustate->program->write_dword_unaligned(cpustate->SP, cpustate->PC + 3);
+
+ // Jump to subroutine
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 1);
+ return 0;
+}
+
diff --git a/trunk/src/emu/cpu/v60/op5.c b/trunk/src/emu/cpu/v60/op5.c
new file mode 100644
index 00000000000..63663ed4c29
--- /dev/null
+++ b/trunk/src/emu/cpu/v60/op5.c
@@ -0,0 +1,93 @@
+
+/*
+ * HALT: must add log
+ */
+
+static UINT32 opBRK(v60_state *cpustate)
+{
+/*
+ UINT32 oldPSW = v60_update_psw_for_exception(cpustate, 0, 0);
+
+ cpustate->SP -=4;
+ cpustate->program->write_dword_unaligned(cpustate->SP, EXCEPTION_CODE_AND_SIZE(0x0d00, 4));
+ cpustate->SP -=4;
+ cpustate->program->write_dword_unaligned(cpustate->SP, oldPSW);
+ cpustate->SP -=4;
+ cpustate->program->write_dword_unaligned(cpustate->SP, cpustate->PC + 1);
+ cpustate->PC = GETINTVECT(cpustate, 13);
+*/
+ logerror("Skipping BRK opcode! cpustate->PC=%x", cpustate->PC);
+
+ return 1;
+}
+
+static UINT32 opBRKV(v60_state *cpustate)
+{
+ UINT32 oldPSW = v60_update_psw_for_exception(cpustate, 0, 0);
+
+ cpustate->SP -=4;
+ cpustate->program->write_dword_unaligned(cpustate->SP, cpustate->PC);
+ cpustate->SP -=4;
+ cpustate->program->write_dword_unaligned(cpustate->SP, EXCEPTION_CODE_AND_SIZE(0x1501, 4));
+ cpustate->SP -=4;
+ cpustate->program->write_dword_unaligned(cpustate->SP, oldPSW);
+ cpustate->SP -=4;
+ cpustate->program->write_dword_unaligned(cpustate->SP, cpustate->PC + 1);
+ cpustate->PC = GETINTVECT(cpustate, 21);
+
+ return 0;
+}
+
+static UINT32 opCLRTLBA(v60_state *cpustate)
+{
+ // @@@ TLB not yet supported
+ logerror("Skipping CLRTLBA opcode! cpustate->PC=%x\n", cpustate->PC);
+ return 1;
+}
+
+static UINT32 opDISPOSE(v60_state *cpustate)
+{
+ cpustate->SP = cpustate->FP;
+ cpustate->FP = cpustate->program->read_dword_unaligned(cpustate->SP);
+ cpustate->SP +=4;
+
+ return 1;
+}
+
+static UINT32 opHALT(v60_state *cpustate)
+{
+ // @@@ It should wait for an interrupt to occur
+ //logerror("HALT found: skipping");
+ return 1;
+}
+
+static UINT32 opNOP(v60_state *cpustate) /* TRUSTED */
+{
+ return 1;
+}
+
+static UINT32 opRSR(v60_state *cpustate)
+{
+ cpustate->PC = cpustate->program->read_dword_unaligned(cpustate->SP);
+ cpustate->SP +=4;
+
+ return 0;
+}
+
+static UINT32 opTRAPFL(v60_state *cpustate)
+{
+ if ((cpustate->TKCW & 0x1F0) & ((v60ReadPSW(cpustate) & 0x1F00) >> 4))
+ {
+ // @@@ FPU exception
+ fatalerror("Hit TRAPFL! cpustate->PC=%x", cpustate->PC);
+ }
+
+ return 1;
+}
+
+
+
+
+
+
+
diff --git a/trunk/src/emu/cpu/v60/op6.c b/trunk/src/emu/cpu/v60/op6.c
new file mode 100644
index 00000000000..0441c83bb87
--- /dev/null
+++ b/trunk/src/emu/cpu/v60/op6.c
@@ -0,0 +1,254 @@
+
+/*
+ FULLY TRUSTED
+*/
+
+static UINT32 opTB(v60_state *cpustate, int reg) /* TRUSTED */
+{
+ if (cpustate->reg[reg] == 0)
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 2);
+ return 0;
+ }
+
+ return 4;
+}
+
+static UINT32 opDBGT(v60_state *cpustate, int reg) /* TRUSTED */
+{
+ cpustate->reg[reg]--;
+
+ NORMALIZEFLAGS(cpustate);
+ if ((cpustate->reg[reg] != 0) && !((cpustate->_S ^ cpustate->_OV) | cpustate->_Z))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 2);
+ return 0;
+ }
+
+ return 4;
+}
+
+static UINT32 opDBLE(v60_state *cpustate, int reg) /* TRUSTED */
+{
+ cpustate->reg[reg]--;
+
+ NORMALIZEFLAGS(cpustate);
+ if ((cpustate->reg[reg] != 0) && ((cpustate->_S ^ cpustate->_OV) | cpustate->_Z))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 2);
+ return 0;
+ }
+
+ return 4;
+}
+
+
+static UINT32 opDBGE(v60_state *cpustate, int reg) /* TRUSTED */
+{
+ cpustate->reg[reg]--;
+
+ NORMALIZEFLAGS(cpustate);
+ if ((cpustate->reg[reg] != 0) && !(cpustate->_S ^ cpustate->_OV))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 2);
+ return 0;
+ }
+
+ return 4;
+}
+
+static UINT32 opDBLT(v60_state *cpustate, int reg) /* TRUSTED */
+{
+ cpustate->reg[reg]--;
+
+ NORMALIZEFLAGS(cpustate);
+ if ((cpustate->reg[reg] != 0) && (cpustate->_S ^ cpustate->_OV))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 2);
+ return 0;
+ }
+
+ return 4;
+}
+
+static UINT32 opDBH(v60_state *cpustate, int reg) /* TRUSTED */
+{
+ cpustate->reg[reg]--;
+
+ if ((cpustate->reg[reg] != 0) && !(cpustate->_CY | cpustate->_Z))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 2);
+ return 0;
+ }
+
+ return 4;
+}
+
+static UINT32 opDBNH(v60_state *cpustate, int reg) /* TRUSTED */
+{
+ cpustate->reg[reg]--;
+
+ if ((cpustate->reg[reg] != 0) && (cpustate->_CY | cpustate->_Z))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 2);
+ return 0;
+ }
+
+ return 4;
+}
+
+
+static UINT32 opDBL(v60_state *cpustate, int reg) /* TRUSTED */
+{
+ cpustate->reg[reg]--;
+
+ if ((cpustate->reg[reg] != 0) && (cpustate->_CY))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 2);
+ return 0;
+ }
+
+ return 4;
+}
+
+static UINT32 opDBNL(v60_state *cpustate, int reg) /* TRUSTED */
+{
+ cpustate->reg[reg]--;
+
+ if ((cpustate->reg[reg] != 0) && !(cpustate->_CY))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 2);
+ return 0;
+ }
+
+ return 4;
+}
+
+static UINT32 opDBE(v60_state *cpustate, int reg) /* TRUSTED */
+{
+ cpustate->reg[reg]--;
+
+ if ((cpustate->reg[reg] != 0) && (cpustate->_Z))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 2);
+ return 0;
+ }
+
+ return 4;
+}
+
+static UINT32 opDBNE(v60_state *cpustate, int reg) /* TRUSTED */
+{
+ cpustate->reg[reg]--;
+
+ if ((cpustate->reg[reg] != 0) && !(cpustate->_Z))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 2);
+ return 0;
+ }
+
+ return 4;
+}
+
+static UINT32 opDBV(v60_state *cpustate, int reg) /* TRUSTED */
+{
+ cpustate->reg[reg]--;
+
+ if ((cpustate->reg[reg] != 0) && (cpustate->_OV))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 2);
+ return 0;
+ }
+
+ return 4;
+}
+
+static UINT32 opDBNV(v60_state *cpustate, int reg) /* TRUSTED */
+{
+ cpustate->reg[reg]--;
+
+ if ((cpustate->reg[reg] != 0) && !(cpustate->_OV))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 2);
+ return 0;
+ }
+
+ return 4;
+}
+
+static UINT32 opDBN(v60_state *cpustate, int reg) /* TRUSTED */
+{
+ cpustate->reg[reg]--;
+
+ if ((cpustate->reg[reg] != 0) && (cpustate->_S))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 2);
+ return 0;
+ }
+
+ return 4;
+}
+
+static UINT32 opDBP(v60_state *cpustate, int reg) /* TRUSTED */
+{
+ cpustate->reg[reg]--;
+
+ if ((cpustate->reg[reg] != 0) && !(cpustate->_S))
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 2);
+ return 0;
+ }
+
+ return 4;
+}
+
+static UINT32 opDBR(v60_state *cpustate, int reg) /* TRUSTED */
+{
+ cpustate->reg[reg]--;
+
+ if (cpustate->reg[reg] != 0)
+ {
+ cpustate->PC += (INT16)OpRead16(cpustate, cpustate->PC + 2);
+ return 0;
+ }
+
+ return 4;
+}
+
+static UINT32 (*const OpC6Table[8])(v60_state *, int reg) = /* TRUSTED */
+{
+ opDBV,
+ opDBL,
+ opDBE,
+ opDBNH,
+ opDBN,
+ opDBR,
+ opDBLT,
+ opDBLE
+};
+
+static UINT32 (*const OpC7Table[8])(v60_state *, int reg) = /* TRUSTED */
+{
+ opDBNV,
+ opDBNL,
+ opDBNE,
+ opDBH,
+ opDBP,
+ opTB,
+ opDBGE,
+ opDBGT
+};
+
+
+static UINT32 opC6(v60_state *cpustate) /* TRUSTED */
+{
+ UINT8 appb = OpRead8(cpustate, cpustate->PC + 1);
+ return OpC6Table[appb >> 5](cpustate, appb & 0x1f);
+}
+
+static UINT32 opC7(v60_state *cpustate) /* TRUSTED */
+{
+ UINT8 appb = OpRead8(cpustate, cpustate->PC + 1);
+ return OpC7Table[appb >> 5](cpustate, appb & 0x1f);
+}
+
diff --git a/trunk/src/emu/cpu/v60/op7a.c b/trunk/src/emu/cpu/v60/op7a.c
new file mode 100644
index 00000000000..e2d062fa14a
--- /dev/null
+++ b/trunk/src/emu/cpu/v60/op7a.c
@@ -0,0 +1,1211 @@
+
+/*
+ * CMPC: What happens to cpustate->_S flag if the strings are identical?
+ * I suppose that it will be cleared. And is it set or cleared
+ * when the first one is a substring of the second? I suppose
+ * cleared (since cpustate->_S should be (src > dst))
+ * MOVC: Why MOVCS does not exist in downward version?
+ * SHCHDB / SHCHDH: cpustate->R27 is filled with the offset from the start or from the end?
+ *
+ * Strange stuff:
+ * SCHC opcodes does *not* modify cpustate->_Z flag as stated in V60 manual:
+ * they do the opposite (set if not found, reset if found)
+ */
+
+#define F7AEND(cs) \
+ return (cs)->amlength1 + (cs)->amlength2 + 4;
+
+#define F7BEND(cs) \
+ return (cs)->amlength1 + (cs)->amlength2 + 3;
+
+#define F7CEND(cs) \
+ return (cs)->amlength1 + (cs)->amlength2 + 3;
+
+#define F7BCREATEBITMASK(x) \
+ x = ((1 << (x)) - 1)
+
+#define F7CCREATEBITMASK(x) \
+ x = ((1 << (x)) - 1)
+
+static void F7aDecodeOperands(v60_state *cpustate, UINT32 (*DecodeOp1)(v60_state *), UINT8 dim1, UINT32 (*DecodeOp2)(v60_state *), UINT8 dim2)
+{
+ UINT8 appb;
+ // Decode first operand
+ cpustate->moddim = dim1;
+ cpustate->modm = cpustate->subop & 0x40;
+ cpustate->modadd = cpustate->PC + 2;
+ cpustate->amlength1 = DecodeOp1(cpustate);
+ cpustate->flag1 = cpustate->amflag;
+ cpustate->op1 = cpustate->amout;
+
+ // Decode length
+ appb = OpRead8(cpustate, cpustate->PC + 2 + cpustate->amlength1);
+ if (appb & 0x80)
+ cpustate->lenop1 = cpustate->reg[appb & 0x1F];
+ else
+ cpustate->lenop1 = appb;
+
+ // Decode second operand
+ cpustate->moddim = dim2;
+ cpustate->modm = cpustate->subop & 0x20;
+ cpustate->modadd = cpustate->PC + 3 + cpustate->amlength1;
+ cpustate->amlength2 = DecodeOp2(cpustate);
+ cpustate->flag2 = cpustate->amflag;
+ cpustate->op2 = cpustate->amout;
+
+ // Decode length
+ appb = OpRead8(cpustate, cpustate->PC + 3 + cpustate->amlength1 + cpustate->amlength2);
+ if (appb & 0x80)
+ cpustate->lenop2 = cpustate->reg[appb & 0x1F];
+ else
+ cpustate->lenop2 = appb;
+}
+
+static void F7bDecodeFirstOperand(v60_state *cpustate, UINT32 (*DecodeOp1)(v60_state *), UINT8 dim1)
+{
+ UINT8 appb;
+ // Decode first operand
+ cpustate->moddim = dim1;
+ cpustate->modm = cpustate->subop & 0x40;
+ cpustate->modadd = cpustate->PC + 2;
+ cpustate->amlength1 = DecodeOp1(cpustate);
+ cpustate->flag1 = cpustate->amflag;
+ cpustate->op1 = cpustate->amout;
+
+ // Decode ext
+ appb = OpRead8(cpustate, cpustate->PC + 2 + cpustate->amlength1);
+ if (appb & 0x80)
+ cpustate->lenop1 = cpustate->reg[appb & 0x1F];
+ else
+ cpustate->lenop1 = appb;
+}
+
+
+static void F7bWriteSecondOperand(v60_state *cpustate, UINT8 dim2)
+{
+ cpustate->moddim = dim2;
+ cpustate->modm = cpustate->subop & 0x20;
+ cpustate->modadd = cpustate->PC + 3 + cpustate->amlength1;
+ cpustate->amlength2 = WriteAM(cpustate);
+}
+
+
+static void F7bDecodeOperands(v60_state *cpustate, UINT32 (*DecodeOp1)(v60_state *), UINT8 dim1, UINT32 (*DecodeOp2)(v60_state *), UINT8 dim2)
+{
+ // Decode first operand
+ F7bDecodeFirstOperand(cpustate, DecodeOp1, dim1);
+ cpustate->bamoffset1 = cpustate->bamoffset;
+
+ // Decode second operand
+ cpustate->moddim = dim2;
+ cpustate->modm = cpustate->subop & 0x20;
+ cpustate->modadd = cpustate->PC + 3 + cpustate->amlength1;
+ cpustate->amlength2 = DecodeOp2(cpustate);
+ cpustate->flag2 = cpustate->amflag;
+ cpustate->op2 = cpustate->amout;
+ cpustate->bamoffset2 = cpustate->bamoffset;
+}
+
+static void F7cDecodeOperands(v60_state *cpustate, UINT32 (*DecodeOp1)(v60_state *), UINT8 dim1, UINT32 (*DecodeOp2)(v60_state *), UINT8 dim2)
+{
+ UINT8 appb;
+ // Decode first operand
+ cpustate->moddim = dim1;
+ cpustate->modm = cpustate->subop & 0x40;
+ cpustate->modadd = cpustate->PC + 2;
+ cpustate->amlength1 = DecodeOp1(cpustate);
+ cpustate->flag1 = cpustate->amflag;
+ cpustate->op1 = cpustate->amout;
+
+ // Decode second operand
+ cpustate->moddim = dim2;
+ cpustate->modm = cpustate->subop & 0x20;
+ cpustate->modadd = cpustate->PC + 2 + cpustate->amlength1;
+ cpustate->amlength2 = DecodeOp2(cpustate);
+ cpustate->flag2 = cpustate->amflag;
+ cpustate->op2 = cpustate->amout;
+
+ // Decode ext
+ appb = OpRead8(cpustate, cpustate->PC + 2 + cpustate->amlength1 + cpustate->amlength2);
+ if (appb & 0x80)
+ cpustate->lenop1 = cpustate->reg[appb & 0x1F];
+ else
+ cpustate->lenop1 = appb;
+}
+
+#define F7CLOADOP1BYTE(cs,appb) \
+ if ((cs)->flag1) \
+ appb = (UINT8)((cs)->reg[(cs)->op1]&0xFF); \
+ else \
+ appb = (cs)->program->read_byte((cs)->op1);
+
+#define F7CLOADOP2BYTE(cs,appb) \
+ if ((cs)->flag2) \
+ appb = (UINT8)((cs)->reg[(cs)->op2]&0xFF); \
+ else \
+ appb = (cs)->program->read_byte((cs)->op2);
+
+
+#define F7CSTOREOP2BYTE(cs) \
+ if ((cs)->flag2) \
+ SETREG8((cs)->reg[(cs)->op2], appb); \
+ else \
+ (cs)->program->write_byte((cs)->op2, appb);
+
+#define F7CSTOREOP2HALF(cs) \
+ if ((cs)->flag2) \
+ SETREG16((cs)->reg[(cs)->op2], apph); \
+ else \
+ (cs)->program->write_word_unaligned((cs)->op2, apph);
+
+static UINT32 opCMPSTRB(v60_state *cpustate, UINT8 bFill, UINT8 bStop)
+{
+ UINT32 i, dest;
+ UINT8 c1, c2;
+
+ F7aDecodeOperands(cpustate, ReadAMAddress, 0,ReadAMAddress, 0);
+
+ // Filling
+ if (bFill)
+ {
+ if (cpustate->lenop1 < cpustate->lenop2)
+ {
+ for (i = cpustate->lenop1; i < cpustate->lenop2; i++)
+ cpustate->program->write_byte(cpustate->op1 + i,(UINT8)cpustate->R26);
+ }
+ else if (cpustate->lenop2 < cpustate->lenop1)
+ {
+ for (i = cpustate->lenop2; i < cpustate->lenop1; i++)
+ cpustate->program->write_byte(cpustate->op2 + i,(UINT8)cpustate->R26);
+ }
+ }
+
+ dest = (cpustate->lenop1 < cpustate->lenop2 ? cpustate->lenop1 : cpustate->lenop2);
+
+ cpustate->_Z = 0;
+ cpustate->_S = 0;
+ if (bStop) cpustate->_CY = 1;
+
+ for (i = 0; i < dest; i++)
+ {
+ c1 = cpustate->program->read_byte(cpustate->op1 + i);
+ c2 = cpustate->program->read_byte(cpustate->op2 + i);
+
+ if (c1 > c2)
+ {
+ cpustate->_S = 1; break;
+ }
+ else if (c2 > c1)
+ {
+ cpustate->_S = 0; break;
+ }
+
+ if (bStop)
+ if (c1 == (UINT8)cpustate->R26 || c2 == (UINT8)cpustate->R26)
+ {
+ cpustate->_CY = 0;
+ break;
+ }
+ }
+
+ cpustate->R28 = cpustate->lenop1 + i;
+ cpustate->R27 = cpustate->lenop2 + i;
+
+ if (i == dest)
+ {
+ if (cpustate->lenop1 > cpustate->lenop2)
+ cpustate->_S = 1;
+ else if (cpustate->lenop2 > cpustate->lenop1)
+ cpustate->_S = 0;
+ else
+ cpustate->_Z = 1;
+ }
+
+ F7AEND(cpustate);
+}
+
+static UINT32 opCMPSTRH(v60_state *cpustate, UINT8 bFill, UINT8 bStop)
+{
+ UINT32 i, dest;
+ UINT16 c1, c2;
+
+ F7aDecodeOperands(cpustate, ReadAMAddress, 0,ReadAMAddress, 0);
+
+ // Filling
+ if (bFill)
+ {
+ if (cpustate->lenop1 < cpustate->lenop2)
+ {
+ for (i = cpustate->lenop1; i < cpustate->lenop2; i++)
+ cpustate->program->write_word_unaligned(cpustate->op1 + i * 2,(UINT16)cpustate->R26);
+ }
+ else if (cpustate->lenop2 < cpustate->lenop1)
+ {
+ for (i = cpustate->lenop2; i < cpustate->lenop1; i++)
+ cpustate->program->write_word_unaligned(cpustate->op2 + i * 2,(UINT16)cpustate->R26);
+ }
+ }
+
+ dest = (cpustate->lenop1 < cpustate->lenop2 ? cpustate->lenop1 : cpustate->lenop2);
+
+ cpustate->_Z = 0;
+ cpustate->_S = 0;
+ if (bStop) cpustate->_CY = 1;
+
+ for (i = 0; i < dest; i++)
+ {
+ c1 = cpustate->program->read_word_unaligned(cpustate->op1 + i * 2);
+ c2 = cpustate->program->read_word_unaligned(cpustate->op2 + i * 2);
+
+ if (c1 > c2)
+ {
+ cpustate->_S = 1; break;
+ }
+ else if (c2 > c1)
+ {
+ cpustate->_S = 0; break;
+ }
+
+ if (bStop)
+ if (c1 == (UINT16)cpustate->R26 || c2 == (UINT16)cpustate->R26)
+ {
+ cpustate->_CY = 0;
+ break;
+ }
+ }
+
+ cpustate->R28 = cpustate->lenop1 + i * 2;
+ cpustate->R27 = cpustate->lenop2 + i * 2;
+
+ if (i == dest)
+ {
+ if (cpustate->lenop1 > cpustate->lenop2)
+ cpustate->_S = 1;
+ else if (cpustate->lenop2 > cpustate->lenop1)
+ cpustate->_S = 0;
+ else
+ cpustate->_Z = 1;
+ }
+
+ F7AEND(cpustate);
+}
+
+
+
+static UINT32 opMOVSTRUB(v60_state *cpustate, UINT8 bFill, UINT8 bStop) /* TRUSTED (0, 0) (1, 0) */
+{
+ UINT32 i, dest;
+ UINT8 c1;
+
+// if (bStop)
+// {
+// int a = 1;
+// }
+
+ F7aDecodeOperands(cpustate, ReadAMAddress, 0,ReadAMAddress, 0);
+
+ dest = (cpustate->lenop1 < cpustate->lenop2 ? cpustate->lenop1 : cpustate->lenop2);
+
+ for (i = 0; i < dest; i++)
+ {
+ cpustate->program->write_byte(cpustate->op2 + i,(c1 = cpustate->program->read_byte(cpustate->op1 + i)));
+
+ if (bStop && c1 == (UINT8)cpustate->R26)
+ break;
+ }
+
+ cpustate->R28 = cpustate->op1 + i;
+ cpustate->R27 = cpustate->op2 + i;
+
+ if (bFill && cpustate->lenop1 < cpustate->lenop2)
+ {
+ for (;i < cpustate->lenop2; i++)
+ cpustate->program->write_byte(cpustate->op2 + i,(UINT8)cpustate->R26);
+
+ cpustate->R27 = cpustate->op2 + i;
+ }
+
+
+ F7AEND(cpustate);
+}
+
+static UINT32 opMOVSTRDB(v60_state *cpustate, UINT8 bFill, UINT8 bStop)
+{
+ UINT32 i, dest;
+ UINT8 c1;
+
+ F7aDecodeOperands(cpustate, ReadAMAddress, 0,ReadAMAddress, 0);
+
+ dest = (cpustate->lenop1 < cpustate->lenop2 ? cpustate->lenop1 : cpustate->lenop2);
+
+ for (i = 0; i < dest; i++)
+ {
+ cpustate->program->write_byte(cpustate->op2 + (dest - i - 1),(c1 = cpustate->program->read_byte(cpustate->op1 + (dest - i - 1))));
+
+ if (bStop && c1 == (UINT8)cpustate->R26)
+ break;
+ }
+
+ cpustate->R28 = cpustate->op1 + (cpustate->lenop1 - i - 1);
+ cpustate->R27 = cpustate->op2 + (cpustate->lenop2 - i - 1);
+
+ if (bFill && cpustate->lenop1 < cpustate->lenop2)
+ {
+ for (;i < cpustate->lenop2; i++)
+ cpustate->program->write_byte(cpustate->op2 + dest + (cpustate->lenop2 - i - 1),(UINT8)cpustate->R26);
+
+ cpustate->R27 = cpustate->op2 + (cpustate->lenop2 - i - 1);
+ }
+
+
+ F7AEND(cpustate);
+}
+
+
+static UINT32 opMOVSTRUH(v60_state *cpustate, UINT8 bFill, UINT8 bStop) /* TRUSTED (0, 0) (1, 0) */
+{
+ UINT32 i, dest;
+ UINT16 c1;
+
+// if (bStop)
+// { int a = 1; }
+
+ F7aDecodeOperands(cpustate, ReadAMAddress, 1,ReadAMAddress, 1);
+
+ dest = (cpustate->lenop1 < cpustate->lenop2 ? cpustate->lenop1 : cpustate->lenop2);
+
+ for (i = 0; i < dest; i++)
+ {
+ cpustate->program->write_word_unaligned(cpustate->op2 + i * 2,(c1 = cpustate->program->read_word_unaligned(cpustate->op1 + i * 2)));
+
+ if (bStop && c1 == (UINT16)cpustate->R26)
+ break;
+ }
+
+ cpustate->R28 = cpustate->op1 + i * 2;
+ cpustate->R27 = cpustate->op2 + i * 2;
+
+ if (bFill && cpustate->lenop1 < cpustate->lenop2)
+ {
+ for (;i < cpustate->lenop2; i++)
+ cpustate->program->write_word_unaligned(cpustate->op2 + i * 2,(UINT16)cpustate->R26);
+
+ cpustate->R27 = cpustate->op2 + i * 2;
+ }
+
+ F7AEND(cpustate);
+}
+
+static UINT32 opMOVSTRDH(v60_state *cpustate, UINT8 bFill, UINT8 bStop)
+{
+ UINT32 i, dest;
+ UINT16 c1;
+
+// if (bFill | bStop)
+// { int a = 1; }
+
+ F7aDecodeOperands(cpustate, ReadAMAddress, 1,ReadAMAddress, 1);
+
+// if (cpustate->lenop1 != cpustate->lenop2)
+// { int a = 1; }
+
+ dest = (cpustate->lenop1 < cpustate->lenop2 ? cpustate->lenop1 : cpustate->lenop2);
+
+ for (i = 0; i < dest; i++)
+ {
+ cpustate->program->write_word_unaligned(cpustate->op2 + (dest - i - 1) * 2,(c1 = cpustate->program->read_word_unaligned(cpustate->op1 + (dest - i - 1) * 2)));
+
+ if (bStop && c1 == (UINT16)cpustate->R26)
+ break;
+ }
+
+ cpustate->R28 = cpustate->op1 + (cpustate->lenop1 - i - 1) * 2;
+ cpustate->R27 = cpustate->op2 + (cpustate->lenop2 - i - 1) * 2;
+
+ if (bFill && cpustate->lenop1 < cpustate->lenop2)
+ {
+ for (;i < cpustate->lenop2; i++)
+ cpustate->program->write_word_unaligned(cpustate->op2 + (cpustate->lenop2 - i - 1) * 2,(UINT16)cpustate->R26);
+
+ cpustate->R27 = cpustate->op2 + (cpustate->lenop2 - i - 1) * 2;
+ }
+
+ F7AEND(cpustate);
+}
+
+static UINT32 opSEARCHUB(v60_state *cpustate, UINT8 bSearch)
+{
+ UINT8 appb;
+ UINT32 i;
+
+ F7bDecodeOperands(cpustate, ReadAMAddress, 0,ReadAM, 0);
+
+ for (i = 0; i < cpustate->lenop1; i++)
+ {
+ appb = (cpustate->program->read_byte(cpustate->op1 + i) == (UINT8)cpustate->op2);
+ if ((bSearch && appb) || (!bSearch && !appb))
+ break;
+ }
+
+ cpustate->R28 = cpustate->op1 + i;
+ cpustate->R27 = i;
+
+ // This is the opposite as stated in V60 manual...
+ if (i != cpustate->lenop1)
+ cpustate->_Z = 0;
+ else
+ cpustate->_Z = 1;
+
+ F7BEND(cpustate);
+}
+
+static UINT32 opSEARCHUH(v60_state *cpustate, UINT8 bSearch)
+{
+ UINT8 appb;
+ UINT32 i;
+
+ F7bDecodeOperands(cpustate, ReadAMAddress, 1,ReadAM, 1);
+
+ for (i = 0; i < cpustate->lenop1; i++)
+ {
+ appb = (cpustate->program->read_word_unaligned(cpustate->op1 + i * 2) == (UINT16)cpustate->op2);
+ if ((bSearch && appb) || (!bSearch && !appb))
+ break;
+ }
+
+ cpustate->R28 = cpustate->op1 + i * 2;
+ cpustate->R27 = i;
+
+ if (i != cpustate->lenop1)
+ cpustate->_Z = 0;
+ else
+ cpustate->_Z = 1;
+
+ F7BEND(cpustate);
+}
+
+static UINT32 opSEARCHDB(v60_state *cpustate, UINT8 bSearch)
+{
+ UINT8 appb;
+ INT32 i;
+
+ F7bDecodeOperands(cpustate, ReadAMAddress, 0,ReadAM, 0);
+
+ for (i = cpustate->lenop1; i >= 0; i--)
+ {
+ appb = (cpustate->program->read_byte(cpustate->op1 + i) == (UINT8)cpustate->op2);
+ if ((bSearch && appb) || (!bSearch && !appb))
+ break;
+ }
+
+ cpustate->R28 = cpustate->op1 + i;
+ cpustate->R27 = i;
+
+ // This is the opposite as stated in V60 manual...
+ if ((UINT32)i != cpustate->lenop1)
+ cpustate->_Z = 0;
+ else
+ cpustate->_Z = 1;
+
+ F7BEND(cpustate);
+}
+
+static UINT32 opSEARCHDH(v60_state *cpustate, UINT8 bSearch)
+{
+ UINT8 appb;
+ INT32 i;
+
+ F7bDecodeOperands(cpustate, ReadAMAddress, 1,ReadAM, 1);
+
+ for (i = cpustate->lenop1 - 1; i >= 0; i--)
+ {
+ appb = (cpustate->program->read_word_unaligned(cpustate->op1 + i * 2) == (UINT16)cpustate->op2);
+ if ((bSearch && appb) || (!bSearch && !appb))
+ break;
+ }
+
+ cpustate->R28 = cpustate->op1 + i * 2;
+ cpustate->R27 = i;
+
+ if ((UINT32)i != cpustate->lenop1)
+ cpustate->_Z = 0;
+ else
+ cpustate->_Z = 1;
+
+ F7BEND(cpustate);
+}
+
+
+static UINT32 opSCHCUB(v60_state *cpustate) { return opSEARCHUB(cpustate, 1); }
+static UINT32 opSCHCUH(v60_state *cpustate) { return opSEARCHUH(cpustate, 1); }
+static UINT32 opSCHCDB(v60_state *cpustate) { return opSEARCHDB(cpustate, 1); }
+static UINT32 opSCHCDH(v60_state *cpustate) { return opSEARCHDH(cpustate, 1); }
+static UINT32 opSKPCUB(v60_state *cpustate) { return opSEARCHUB(cpustate, 0); }
+static UINT32 opSKPCUH(v60_state *cpustate) { return opSEARCHUH(cpustate, 0); }
+static UINT32 opSKPCDB(v60_state *cpustate) { return opSEARCHDB(cpustate, 0); }
+static UINT32 opSKPCDH(v60_state *cpustate) { return opSEARCHDH(cpustate, 0); }
+
+static UINT32 opCMPCB(v60_state *cpustate) { return opCMPSTRB(cpustate, 0, 0); }
+static UINT32 opCMPCH(v60_state *cpustate) { return opCMPSTRH(cpustate, 0, 0); }
+static UINT32 opCMPCFB(v60_state *cpustate) { return opCMPSTRB(cpustate, 1, 0); }
+static UINT32 opCMPCFH(v60_state *cpustate) { return opCMPSTRH(cpustate, 1, 0); }
+static UINT32 opCMPCSB(v60_state *cpustate) { return opCMPSTRB(cpustate, 0, 1); }
+static UINT32 opCMPCSH(v60_state *cpustate) { return opCMPSTRH(cpustate, 0, 1); }
+
+static UINT32 opMOVCUB(v60_state *cpustate) { return opMOVSTRUB(cpustate, 0, 0); }
+static UINT32 opMOVCUH(v60_state *cpustate) { return opMOVSTRUH(cpustate, 0, 0); }
+static UINT32 opMOVCFUB(v60_state *cpustate) { return opMOVSTRUB(cpustate, 1, 0); }
+static UINT32 opMOVCFUH(v60_state *cpustate) { return opMOVSTRUH(cpustate, 1, 0); }
+static UINT32 opMOVCSUB(v60_state *cpustate) { return opMOVSTRUB(cpustate, 0, 1); }
+static UINT32 opMOVCSUH(v60_state *cpustate) { return opMOVSTRUH(cpustate, 0, 1); }
+
+static UINT32 opMOVCDB(v60_state *cpustate) { return opMOVSTRDB(cpustate, 0, 0); }
+static UINT32 opMOVCDH(v60_state *cpustate) { return opMOVSTRDH(cpustate, 0, 0); }
+static UINT32 opMOVCFDB(v60_state *cpustate) { return opMOVSTRDB(cpustate, 1, 0); }
+static UINT32 opMOVCFDH(v60_state *cpustate) { return opMOVSTRDH(cpustate, 1, 0); }
+
+static UINT32 opEXTBFZ(v60_state *cpustate) /* TRUSTED */
+{
+ F7bDecodeFirstOperand(cpustate, BitReadAM, 11);
+
+ F7BCREATEBITMASK(cpustate->lenop1);
+
+ cpustate->modwritevalw = (cpustate->op1 >> cpustate->bamoffset) & cpustate->lenop1;
+
+ F7bWriteSecondOperand(cpustate, 2);
+
+ F7BEND(cpustate);
+}
+
+static UINT32 opEXTBFS(v60_state *cpustate) /* TRUSTED */
+{
+ F7bDecodeFirstOperand(cpustate, BitReadAM, 11);
+
+ F7BCREATEBITMASK(cpustate->lenop1);
+
+ cpustate->modwritevalw = (cpustate->op1 >> cpustate->bamoffset) & cpustate->lenop1;
+ if (cpustate->modwritevalw & ((cpustate->lenop1 + 1) >> 1))
+ cpustate->modwritevalw |= ~cpustate->lenop1;
+
+ F7bWriteSecondOperand(cpustate, 2);
+
+ F7BEND(cpustate);
+}
+
+static UINT32 opEXTBFL(v60_state *cpustate)
+{
+ UINT32 appw;
+
+ F7bDecodeFirstOperand(cpustate, BitReadAM, 11);
+
+ appw = cpustate->lenop1;
+ F7BCREATEBITMASK(cpustate->lenop1);
+
+ cpustate->modwritevalw = (cpustate->op1 >> cpustate->bamoffset) & cpustate->lenop1;
+ cpustate->modwritevalw <<= 32 - appw;
+
+ F7bWriteSecondOperand(cpustate, 2);
+
+ F7BEND(cpustate);
+}
+
+static UINT32 opSCHBS(v60_state *cpustate, UINT32 bSearch1)
+{
+ UINT32 i, data;
+ UINT32 offset;
+
+ F7bDecodeFirstOperand(cpustate, BitReadAMAddress, 10);
+
+ // Read first UINT8
+ cpustate->op1 += cpustate->bamoffset / 8;
+ data = cpustate->program->read_byte(cpustate->op1);
+ offset = cpustate->bamoffset & 7;
+
+ // Scan bitstring
+ for (i = 0; i < cpustate->lenop1; i++)
+ {
+ // Update the work register
+ cpustate->R28 = cpustate->op1;
+
+ // There is a 0 / 1 at current offset?
+ if ((bSearch1 && (data&(1 << offset))) ||
+ (!bSearch1 && !(data&(1 << offset))))
+ break;
+
+ // Next bit please
+ offset++;
+ if (offset == 8)
+ {
+ // Next UINT8 please
+ offset = 0;
+ cpustate->op1++;
+ data = cpustate->program->read_byte(cpustate->op1);
+ }
+ }
+
+ // Set zero if bit not found
+ cpustate->_Z = (i == cpustate->lenop1);
+
+ // Write to destination the final offset
+ cpustate->modwritevalw = i;
+ F7bWriteSecondOperand(cpustate, 2);
+
+ F7BEND(cpustate);
+}
+
+static UINT32 opSCH0BSU(v60_state *cpustate) { return opSCHBS(cpustate, 0); }
+static UINT32 opSCH1BSU(v60_state *cpustate) { return opSCHBS(cpustate, 1); }
+
+static UINT32 opINSBFR(v60_state *cpustate)
+{
+ UINT32 appw;
+ F7cDecodeOperands(cpustate, ReadAM, 2,BitReadAMAddress, 11);
+
+ F7CCREATEBITMASK(cpustate->lenop1);
+
+ cpustate->op2 += cpustate->bamoffset / 8;
+ appw = cpustate->program->read_dword_unaligned(cpustate->op2);
+ cpustate->bamoffset &= 7;
+
+ appw &= ~(cpustate->lenop1 << cpustate->bamoffset);
+ appw |= (cpustate->lenop1 & cpustate->op1) << cpustate->bamoffset;
+
+ cpustate->program->write_dword_unaligned(cpustate->op2, appw);
+
+ F7CEND(cpustate);
+}
+
+static UINT32 opINSBFL(v60_state *cpustate)
+{
+ UINT32 appw;
+ F7cDecodeOperands(cpustate, ReadAM, 2,BitReadAMAddress, 11);
+
+ cpustate->op1 >>= (32 - cpustate->lenop1);
+
+ F7CCREATEBITMASK(cpustate->lenop1);
+
+ cpustate->op2 += cpustate->bamoffset / 8;
+ appw = cpustate->program->read_dword_unaligned(cpustate->op2);
+ cpustate->bamoffset &= 7;
+
+ appw &= ~(cpustate->lenop1 << cpustate->bamoffset);
+ appw |= (cpustate->lenop1 & cpustate->op1) << cpustate->bamoffset;
+
+ cpustate->program->write_dword_unaligned(cpustate->op2, appw);
+
+ F7CEND(cpustate);
+}
+
+static UINT32 opMOVBSD(v60_state *cpustate)
+{
+ UINT32 i;
+ UINT8 srcdata, dstdata;
+
+ F7bDecodeOperands(cpustate, BitReadAMAddress, 10, BitReadAMAddress, 10);
+
+// if (cpustate->lenop1 != 1)
+// { int a = 1; }
+
+ cpustate->bamoffset1 += cpustate->lenop1 - 1;
+ cpustate->bamoffset2 += cpustate->lenop1 - 1;
+
+ cpustate->op1 += cpustate->bamoffset1 / 8;
+ cpustate->op2 += cpustate->bamoffset2 / 8;
+
+ cpustate->bamoffset1 &= 7;
+ cpustate->bamoffset2 &= 7;
+
+ srcdata = cpustate->program->read_byte(cpustate->op1);
+ dstdata = cpustate->program->read_byte(cpustate->op2);
+
+ for (i = 0; i < cpustate->lenop1; i++)
+ {
+ // Update work registers
+ cpustate->R28 = cpustate->op1;
+ cpustate->R27 = cpustate->op2;
+
+ dstdata &= ~(1 << cpustate->bamoffset2);
+ dstdata |= ((srcdata >> cpustate->bamoffset1) & 1) << cpustate->bamoffset2;
+
+ if (cpustate->bamoffset1 == 0)
+ {
+ cpustate->bamoffset1 = 8;
+ cpustate->op1--;
+ srcdata = cpustate->program->read_byte(cpustate->op1);
+ }
+ if (cpustate->bamoffset2 == 0)
+ {
+ cpustate->program->write_byte(cpustate->op2, dstdata);
+ cpustate->bamoffset2 = 8;
+ cpustate->op2--;
+ dstdata = cpustate->program->read_byte(cpustate->op2);
+ }
+
+ cpustate->bamoffset1--;
+ cpustate->bamoffset2--;
+ }
+
+ // Flush of the final data
+ if (cpustate->bamoffset2 != 7)
+ cpustate->program->write_byte(cpustate->op2, dstdata);
+
+ F7BEND(cpustate);
+}
+
+static UINT32 opMOVBSU(v60_state *cpustate)
+{
+ UINT32 i;
+ UINT8 srcdata, dstdata;
+
+ F7bDecodeOperands(cpustate, BitReadAMAddress, 10, BitReadAMAddress, 10);
+
+ cpustate->op1 += cpustate->bamoffset1 / 8;
+ cpustate->op2 += cpustate->bamoffset2 / 8;
+
+ cpustate->bamoffset1 &= 7;
+ cpustate->bamoffset2 &= 7;
+
+ srcdata = cpustate->program->read_byte(cpustate->op1);
+ dstdata = cpustate->program->read_byte(cpustate->op2);
+
+ for (i = 0; i < cpustate->lenop1; i++)
+ {
+ // Update work registers
+ cpustate->R28 = cpustate->op1;
+ cpustate->R27 = cpustate->op2;
+
+ dstdata &= ~(1 << cpustate->bamoffset2);
+ dstdata |= ((srcdata >> cpustate->bamoffset1) & 1) << cpustate->bamoffset2;
+
+ cpustate->bamoffset1++;
+ cpustate->bamoffset2++;
+ if (cpustate->bamoffset1 == 8)
+ {
+ cpustate->bamoffset1 = 0;
+ cpustate->op1++;
+ srcdata = cpustate->program->read_byte(cpustate->op1);
+ }
+ if (cpustate->bamoffset2 == 8)
+ {
+ cpustate->program->write_byte(cpustate->op2, dstdata);
+ cpustate->bamoffset2 = 0;
+ cpustate->op2++;
+ dstdata = cpustate->program->read_byte(cpustate->op2);
+ }
+ }
+
+ // Flush of the final data
+ if (cpustate->bamoffset2 != 0)
+ cpustate->program->write_byte(cpustate->op2, dstdata);
+
+ F7BEND(cpustate);
+}
+
+// RADM 0x20f4b8 holds the time left
+
+static UINT32 opADDDC(v60_state *cpustate)
+{
+ UINT8 appb;
+ UINT8 src, dst;
+
+ F7cDecodeOperands(cpustate, ReadAM, 0, ReadAMAddress, 0);
+
+ if (cpustate->lenop1 != 0)
+ {
+ logerror("ADDDC %x (pat: %x)\n", cpustate->op1, cpustate->lenop1);
+ }
+
+ F7CLOADOP2BYTE(cpustate, appb);
+
+ src = (UINT8)(cpustate->op1 >> 4) * 10 + (UINT8)(cpustate->op1 & 0xF);
+ dst = (appb >> 4) * 10 + (appb & 0xF);
+
+ appb = src + dst + (cpustate->_CY?1:0);
+
+ if (appb >= 100)
+ {
+ appb -= 100;
+ cpustate->_CY = 1;
+ }
+ else
+ cpustate->_CY = 0;
+
+ // compute z flag:
+ // cleared if result non-zero or carry generated
+ // unchanged otherwise
+ if (appb != 0 || cpustate->_CY)
+ cpustate->_Z = 0;
+
+ appb = ((appb / 10) << 4) | (appb % 10);
+
+ F7CSTOREOP2BYTE(cpustate);
+ F7CEND(cpustate);
+}
+
+static UINT32 opSUBDC(v60_state *cpustate)
+{
+ INT8 appb;
+ UINT32 src, dst;
+
+ F7cDecodeOperands(cpustate, ReadAM, 0, ReadAMAddress, 0);
+
+ if (cpustate->lenop1 != 0)
+ {
+ logerror("SUBDC %x (pat: %x)\n", cpustate->op1, cpustate->lenop1);
+ }
+
+ F7CLOADOP2BYTE(cpustate, appb);
+
+ src = (UINT32)(cpustate->op1 >> 4) * 10 + (UINT32)(cpustate->op1 & 0xF);
+ dst = ((appb & 0xF0) >> 4) * 10 + (appb & 0xF);
+
+ // Note that this APPB must be SIGNED!
+ appb = (INT32)dst - (INT32)src - (cpustate->_CY?1:0);
+
+ if (appb < 0)
+ {
+ appb += 100;
+ cpustate->_CY = 1;
+ }
+ else
+ cpustate->_CY = 0;
+
+ // compute z flag:
+ // cleared if result non-zero or carry generated
+ // unchanged otherwise
+ if (appb != 0 || cpustate->_CY)
+ cpustate->_Z = 0;
+
+ appb = ((appb / 10) << 4) | (appb % 10);
+
+ F7CSTOREOP2BYTE(cpustate);
+ F7CEND(cpustate);
+}
+
+static UINT32 opSUBRDC(v60_state *cpustate)
+{
+ INT8 appb;
+ UINT32 src, dst;
+
+ F7cDecodeOperands(cpustate, ReadAM, 0, ReadAMAddress, 0);
+
+ if (cpustate->lenop1 != 0)
+ {
+ logerror("SUBRDC %x (pat: %x)\n", cpustate->op1, cpustate->lenop1);
+ }
+
+ F7CLOADOP2BYTE(cpustate, appb);
+
+ src = (UINT32)(cpustate->op1 >> 4) * 10 + (UINT32)(cpustate->op1 & 0xF);
+ dst = ((appb & 0xF0) >> 4) * 10 + (appb & 0xF);
+
+ // Note that this APPB must be SIGNED!
+ appb = (INT32)src - (INT32)dst - (cpustate->_CY?1:0);
+
+ if (appb < 0)
+ {
+ appb += 100;
+ cpustate->_CY = 1;
+ }
+ else
+ cpustate->_CY = 0;
+
+ // compute z flag:
+ // cleared if result non-zero or carry generated
+ // unchanged otherwise
+ if (appb != 0 || cpustate->_CY)
+ cpustate->_Z = 0;
+
+ appb = ((appb / 10) << 4) | (appb % 10);
+
+ F7CSTOREOP2BYTE(cpustate);
+ F7CEND(cpustate);
+}
+
+static UINT32 opCVTDPZ(v60_state *cpustate)
+{
+ UINT16 apph;
+
+ F7cDecodeOperands(cpustate, ReadAM, 0, ReadAMAddress, 1);
+
+ apph = (UINT16)(((cpustate->op1 >> 4) & 0xF) | ((cpustate->op1 & 0xF) << 8));
+ apph |= (cpustate->lenop1);
+ apph |= (cpustate->lenop1 << 8);
+
+ // Z flag is unchanged if src is zero, cleared otherwise
+ if (cpustate->op1 != 0) cpustate->_Z = 0;
+
+ F7CSTOREOP2HALF(cpustate);
+ F7CEND(cpustate);
+}
+
+static UINT32 opCVTDZP(v60_state *cpustate)
+{
+ UINT8 appb;
+ F7cDecodeOperands(cpustate, ReadAM, 1, ReadAMAddress, 0);
+
+ if ((cpustate->op1 & 0xF0) != (cpustate->lenop1 & 0xF0) || ((cpustate->op1 >> 8) & 0xF0) != (cpustate->lenop1 & 0xF0))
+ {
+ // Decimal exception
+ logerror("CVTD.ZP Decimal exception #1!\n");
+ }
+
+ if ((cpustate->op1 & 0xF) > 9 || ((cpustate->op1 >> 8) & 0xF) > 9)
+ {
+ // Decimal exception
+ logerror("CVTD.ZP Decimal exception #2!\n");
+ }
+
+ appb = (UINT8)(((cpustate->op1 >> 8) & 0xF) | ((cpustate->op1 & 0xF) << 4));
+ if (appb != 0) cpustate->_Z = 0;
+
+ F7CSTOREOP2BYTE(cpustate);
+ F7CEND(cpustate);
+}
+
+static UINT32 op58UNHANDLED(v60_state *cpustate)
+{
+ fatalerror("Unhandled 58 opcode at cpustate->PC: /%06x", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 op5AUNHANDLED(v60_state *cpustate)
+{
+ fatalerror("Unhandled 5A opcode at cpustate->PC: /%06x", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 op5BUNHANDLED(v60_state *cpustate)
+{
+ fatalerror("Unhandled 5B opcode at cpustate->PC: /%06x", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 op5DUNHANDLED(v60_state *cpustate)
+{
+ fatalerror("Unhandled 5D opcode at cpustate->PC: /%06x", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 op59UNHANDLED(v60_state *cpustate)
+{
+ fatalerror("Unhandled 59 opcode at cpustate->PC: /%06x", cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+static UINT32 (*const Op59Table[32])(v60_state *) =
+{
+ opADDDC,
+ opSUBDC,
+ opSUBRDC,
+ op59UNHANDLED,
+ op59UNHANDLED,
+ op59UNHANDLED,
+ op59UNHANDLED,
+ op59UNHANDLED,
+ op59UNHANDLED,
+ op59UNHANDLED,
+ op59UNHANDLED,
+ op59UNHANDLED,
+ op59UNHANDLED,
+ op59UNHANDLED,
+ op59UNHANDLED,
+ op59UNHANDLED,
+ opCVTDPZ,
+ op59UNHANDLED,
+ op59UNHANDLED,
+ op59UNHANDLED,
+ op59UNHANDLED,
+ op59UNHANDLED,
+ op59UNHANDLED,
+ op59UNHANDLED,
+ opCVTDZP,
+ op59UNHANDLED,
+ op59UNHANDLED,
+ op59UNHANDLED,
+ op59UNHANDLED,
+ op59UNHANDLED,
+ op59UNHANDLED,
+ op59UNHANDLED
+};
+
+
+static UINT32 (*const Op5BTable[32])(v60_state *) =
+{
+ opSCH0BSU,
+ op5BUNHANDLED,
+ opSCH1BSU,
+ op5BUNHANDLED,
+ op5BUNHANDLED,
+ op5BUNHANDLED,
+ op5BUNHANDLED,
+ op5BUNHANDLED,
+ opMOVBSU,
+ opMOVBSD,
+ op5BUNHANDLED,
+ op5BUNHANDLED,
+ op5BUNHANDLED,
+ op5BUNHANDLED,
+ op5BUNHANDLED,
+ op5BUNHANDLED,
+ op5BUNHANDLED,
+ op5BUNHANDLED,
+ op5BUNHANDLED,
+ op5BUNHANDLED,
+ op5BUNHANDLED,
+ op5BUNHANDLED,
+ op5BUNHANDLED,
+ op5BUNHANDLED,
+ op5BUNHANDLED,
+ op5BUNHANDLED,
+ op5BUNHANDLED,
+ op5BUNHANDLED,
+ op5BUNHANDLED,
+ op5BUNHANDLED,
+ op5BUNHANDLED,
+ op5BUNHANDLED
+};
+
+
+static UINT32 (*const Op5DTable[32])(v60_state *) =
+{
+ op5DUNHANDLED,
+ op5DUNHANDLED,
+ op5DUNHANDLED,
+ op5DUNHANDLED,
+ op5DUNHANDLED,
+ op5DUNHANDLED,
+ op5DUNHANDLED,
+ op5DUNHANDLED,
+ opEXTBFS,
+ opEXTBFZ,
+ opEXTBFL,
+ op5DUNHANDLED,
+ op5DUNHANDLED,
+ op5DUNHANDLED,
+ op5DUNHANDLED,
+ op5DUNHANDLED,
+ op5DUNHANDLED,
+ op5DUNHANDLED,
+ op5DUNHANDLED,
+ op5DUNHANDLED,
+ op5DUNHANDLED,
+ op5DUNHANDLED,
+ op5DUNHANDLED,
+ op5DUNHANDLED,
+ opINSBFR,
+ opINSBFL,
+ op5DUNHANDLED,
+ op5DUNHANDLED,
+ op5DUNHANDLED,
+ op5DUNHANDLED,
+ op5DUNHANDLED,
+ op5DUNHANDLED
+};
+
+static UINT32 (*const Op58Table[32])(v60_state *) =
+{
+ opCMPCB,
+ opCMPCFB,
+ opCMPCSB,
+ op58UNHANDLED,
+ op58UNHANDLED,
+ op58UNHANDLED,
+ op58UNHANDLED,
+ op58UNHANDLED,
+ opMOVCUB,
+ opMOVCDB,
+ opMOVCFUB,
+ opMOVCFDB,
+ opMOVCSUB,
+ op58UNHANDLED,
+ op58UNHANDLED,
+ op58UNHANDLED,
+ op58UNHANDLED,
+ op58UNHANDLED,
+ op58UNHANDLED,
+ op58UNHANDLED,
+ op58UNHANDLED,
+ op58UNHANDLED,
+ op58UNHANDLED,
+ op58UNHANDLED,
+ opSCHCUB,
+ opSCHCDB,
+ opSKPCUB,
+ opSKPCDB,
+ op58UNHANDLED,
+ op58UNHANDLED,
+ op58UNHANDLED,
+ op58UNHANDLED
+};
+
+static UINT32 (*const Op5ATable[32])(v60_state *) =
+{
+ opCMPCH,
+ opCMPCFH,
+ opCMPCSH,
+ op5AUNHANDLED,
+ op5AUNHANDLED,
+ op5AUNHANDLED,
+ op5AUNHANDLED,
+ op5AUNHANDLED,
+ opMOVCUH,
+ opMOVCDH,
+ opMOVCFUH,
+ opMOVCFDH,
+ opMOVCSUH,
+ op5AUNHANDLED,
+ op5AUNHANDLED,
+ op5AUNHANDLED,
+ op5AUNHANDLED,
+ op5AUNHANDLED,
+ op5AUNHANDLED,
+ op5AUNHANDLED,
+ op5AUNHANDLED,
+ op5AUNHANDLED,
+ op5AUNHANDLED,
+ op5AUNHANDLED,
+ opSCHCUH,
+ opSCHCDH,
+ opSKPCUH,
+ opSKPCDH,
+ op5AUNHANDLED,
+ op5AUNHANDLED,
+ op5AUNHANDLED,
+ op5AUNHANDLED
+};
+
+static UINT32 op58(v60_state *cpustate)
+{
+ cpustate->subop = OpRead8(cpustate, cpustate->PC + 1);
+
+ return Op58Table[cpustate->subop & 0x1F](cpustate);
+}
+
+static UINT32 op5A(v60_state *cpustate)
+{
+ cpustate->subop = OpRead8(cpustate, cpustate->PC + 1);
+
+ return Op5ATable[cpustate->subop & 0x1F](cpustate);
+}
+
+static UINT32 op5B(v60_state *cpustate)
+{
+ cpustate->subop = OpRead8(cpustate, cpustate->PC + 1);
+
+ return Op5BTable[cpustate->subop & 0x1F](cpustate);
+}
+
+static UINT32 op5D(v60_state *cpustate)
+{
+ cpustate->subop = OpRead8(cpustate, cpustate->PC + 1);
+
+ return Op5DTable[cpustate->subop & 0x1F](cpustate);
+}
+
+static UINT32 op59(v60_state *cpustate)
+{
+ cpustate->subop = OpRead8(cpustate, cpustate->PC + 1);
+
+ return Op59Table[cpustate->subop & 0x1F](cpustate);
+}
diff --git a/trunk/src/emu/cpu/v60/optable.c b/trunk/src/emu/cpu/v60/optable.c
new file mode 100644
index 00000000000..91f4bb06fc8
--- /dev/null
+++ b/trunk/src/emu/cpu/v60/optable.c
@@ -0,0 +1,259 @@
+static UINT32 (*const OpCodeTable[256])(v60_state *cpustate) =
+{
+ /* 0x00 */ opHALT,
+ /* 0x01 */ opLDTASK,
+ /* 0x02 */ opSTPR,
+ /* 0x03 */ opUNHANDLED,
+ /* 0x04 */ opUNHANDLED,
+ /* 0x05 */ opUNHANDLED,
+ /* 0x06 */ opUNHANDLED,
+ /* 0x07 */ opUNHANDLED,
+ /* 0x08 */ opRVBIT,
+ /* 0x09 */ opMOVB,
+ /* 0x0a */ opMOVSBH,
+ /* 0x0b */ opMOVZBH,
+ /* 0x0c */ opMOVSBW,
+ /* 0x0d */ opMOVZBW,
+ /* 0x0e */ opUNHANDLED,
+ /* 0x0f */ opUNHANDLED,
+ /* 0x10 */ opCLRTLBA,
+ /* 0x11 */ opUNHANDLED,
+ /* 0x12 */ opLDPR,
+ /* 0x13 */ opUPDPSWW,
+ /* 0x14 */ opUNHANDLED,
+ /* 0x15 */ opUNHANDLED,
+ /* 0x16 */ opUNHANDLED,
+ /* 0x17 */ opUNHANDLED,
+ /* 0x18 */ opUNHANDLED,
+ /* 0x19 */ opMOVTHB,
+ /* 0x1a */ opUNHANDLED,
+ /* 0x1b */ opMOVH,
+ /* 0x1c */ opMOVSHW,
+ /* 0x1d */ opMOVZHW,
+ /* 0x1e */ opUNHANDLED,
+ /* 0x1f */ opUNHANDLED,
+ /* 0x20 */ opINB,
+ /* 0x21 */ opOUTB,
+ /* 0x22 */ opINH,
+ /* 0x23 */ opOUTH,
+ /* 0x24 */ opINW,
+ /* 0x25 */ opOUTW,
+ /* 0x26 */ opUNHANDLED,
+ /* 0x27 */ opUNHANDLED,
+ /* 0x28 */ opUNHANDLED,
+ /* 0x29 */ opMOVTWB,
+ /* 0x2a */ opUNHANDLED,
+ /* 0x2b */ opMOVTWH,
+ /* 0x2c */ opRVBYT,
+ /* 0x2d */ opMOVW,
+ /* 0x2e */ opUNHANDLED,
+ /* 0x2f */ opUNHANDLED,
+ /* 0x30 */ opUNHANDLED,
+ /* 0x31 */ opUNHANDLED,
+ /* 0x32 */ opUNHANDLED,
+ /* 0x33 */ opUNHANDLED,
+ /* 0x34 */ opUNHANDLED,
+ /* 0x35 */ opUNHANDLED,
+ /* 0x36 */ opUNHANDLED,
+ /* 0x37 */ opUNHANDLED,
+ /* 0x38 */ opNOTB,
+ /* 0x39 */ opNEGB,
+ /* 0x3a */ opNOTH,
+ /* 0x3b */ opNEGH,
+ /* 0x3c */ opNOTW,
+ /* 0x3d */ opNEGW,
+ /* 0x3e */ opUNHANDLED,
+ /* 0x3f */ opMOVD,
+ /* 0x40 */ opMOVEAB,
+ /* 0x41 */ opXCHB,
+ /* 0x42 */ opMOVEAH,
+ /* 0x43 */ opXCHH,
+ /* 0x44 */ opMOVEAW,
+ /* 0x45 */ opXCHW,
+ /* 0x46 */ opUNHANDLED,
+ /* 0x47 */ opSETF,
+ /* 0x48 */ opBSR,
+ /* 0x49 */ opCALL,
+ /* 0x4a */ opUPDPSWH,
+ /* 0x4b */ opCHLVL,
+ /* 0x4c */ opUNHANDLED,
+ /* 0x4d */ opCHKAR,
+ /* 0x4e */ opCHKAW,
+ /* 0x4f */ opCHKAE,
+ /* 0x50 */ opREMB,
+ /* 0x51 */ opREMUB,
+ /* 0x52 */ opREMH,
+ /* 0x53 */ opREMUH,
+ /* 0x54 */ opREMW,
+ /* 0x55 */ opREMUW,
+ /* 0x56 */ opUNHANDLED,
+ /* 0x57 */ opUNHANDLED,
+ /* 0x58 */ op58,
+ /* 0x59 */ op59,
+ /* 0x5a */ op5A,
+ /* 0x5b */ op5B,
+ /* 0x5c */ op5C,
+ /* 0x5d */ op5D,
+ /* 0x5e */ opUNHANDLED,
+ /* 0x5f */ op5F,
+ /* 0x60 */ opBV8,
+ /* 0x61 */ opBNV8,
+ /* 0x62 */ opBL8,
+ /* 0x63 */ opBNL8,
+ /* 0x64 */ opBE8,
+ /* 0x65 */ opBNE8,
+ /* 0x66 */ opBNH8,
+ /* 0x67 */ opBH8,
+ /* 0x68 */ opBN8,
+ /* 0x69 */ opBP8,
+ /* 0x6a */ opBR8,
+ /* 0x6b */ opUNHANDLED,
+ /* 0x6C */ opBLT8,
+ /* 0x6c */ opBGE8,
+ /* 0x6e */ opBLE8,
+ /* 0x6f */ opBGT8,
+ /* 0x70 */ opBV16,
+ /* 0x71 */ opBNV16,
+ /* 0x72 */ opBL16,
+ /* 0x73 */ opBNL16,
+ /* 0x74 */ opBE16,
+ /* 0x75 */ opBNE16,
+ /* 0x76 */ opBNH16,
+ /* 0x77 */ opBH16,
+ /* 0x78 */ opBN16,
+ /* 0x79 */ opBP16,
+ /* 0x7a */ opBR16,
+ /* 0x7b */ opUNHANDLED,
+ /* 0x7c */ opBLT16,
+ /* 0x7d */ opBGE16,
+ /* 0x7e */ opBLE16,
+ /* 0x7f */ opBGT16,
+ /* 0x80 */ opADDB,
+ /* 0x81 */ opMULB,
+ /* 0x82 */ opADDH,
+ /* 0x83 */ opMULH,
+ /* 0x84 */ opADDW,
+ /* 0x85 */ opMULW,
+ /* 0x86 */ opMULX,
+ /* 0x87 */ opTEST1,
+ /* 0x88 */ opORB,
+ /* 0x89 */ opROTB,
+ /* 0x8a */ opORH,
+ /* 0x8b */ opROTH,
+ /* 0x8c */ opORW,
+ /* 0x8d */ opROTW,
+ /* 0x8e */ opUNHANDLED,
+ /* 0x8f */ opUNHANDLED,
+ /* 0x90 */ opADDCB,
+ /* 0x91 */ opMULUB,
+ /* 0x92 */ opADDCH,
+ /* 0x93 */ opMULUH,
+ /* 0x94 */ opADDCW,
+ /* 0x95 */ opMULUW,
+ /* 0x96 */ opMULUX,
+ /* 0x97 */ opSET1,
+ /* 0x98 */ opSUBCB,
+ /* 0x99 */ opROTCB,
+ /* 0x9a */ opSUBCH,
+ /* 0x9b */ opROTCH,
+ /* 0x9c */ opSUBCW,
+ /* 0x9d */ opROTCW,
+ /* 0x9e */ opUNHANDLED,
+ /* 0x9f */ opUNHANDLED,
+ /* 0xa0 */ opANDB,
+ /* 0xa1 */ opDIVB,
+ /* 0xa2 */ opANDH,
+ /* 0xa3 */ opDIVH,
+ /* 0xa4 */ opANDW,
+ /* 0xa5 */ opDIVW,
+ /* 0xa6 */ opDIVX,
+ /* 0xa7 */ opCLR1,
+ /* 0xa8 */ opSUBB,
+ /* 0xa9 */ opSHLB,
+ /* 0xaa */ opSUBH,
+ /* 0xab */ opSHLH,
+ /* 0xac */ opSUBW,
+ /* 0xad */ opSHLW,
+ /* 0xae */ opUNHANDLED,
+ /* 0xaf */ opUNHANDLED,
+ /* 0xb0 */ opXORB,
+ /* 0xb1 */ opDIVUB,
+ /* 0xb2 */ opXORH,
+ /* 0xb3 */ opDIVUH,
+ /* 0xb4 */ opXORW,
+ /* 0xb5 */ opDIVUW,
+ /* 0xb6 */ opDIVUX,
+ /* 0xb7 */ opNOT1,
+ /* 0xb8 */ opCMPB,
+ /* 0xb9 */ opSHAB,
+ /* 0xba */ opCMPH,
+ /* 0xbb */ opSHAH,
+ /* 0xbc */ opCMPW,
+ /* 0xbd */ opSHAW,
+ /* 0xbe */ opUNHANDLED,
+ /* 0xbf */ opUNHANDLED,
+ /* 0xc0 */ opUNHANDLED,
+ /* 0xc1 */ opUNHANDLED,
+ /* 0xc2 */ opUNHANDLED,
+ /* 0xc3 */ opUNHANDLED,
+ /* 0xc4 */ opUNHANDLED,
+ /* 0xc5 */ opUNHANDLED,
+ /* 0xc6 */ opC6,
+ /* 0xc7 */ opC7,
+ /* 0xc8 */ opBRK,
+ /* 0xc9 */ opBRKV,
+ /* 0xca */ opRSR,
+ /* 0xcb */ opTRAPFL,
+ /* 0xcc */ opDISPOSE,
+ /* 0xcd */ opNOP,
+ /* 0xce */ opUNHANDLED,
+ /* 0xcf */ opUNHANDLED,
+ /* 0xd0 */ opDECB_0,
+ /* 0xd1 */ opDECB_1,
+ /* 0xd2 */ opDECH_0,
+ /* 0xd3 */ opDECH_1,
+ /* 0xd4 */ opDECW_0,
+ /* 0xd5 */ opDECW_1,
+ /* 0xd6 */ opJMP_0,
+ /* 0xd7 */ opJMP_1,
+ /* 0xd8 */ opINCB_0,
+ /* 0xd9 */ opINCB_1,
+ /* 0xda */ opINCH_0,
+ /* 0xdb */ opINCH_1,
+ /* 0xdc */ opINCW_0,
+ /* 0xdd */ opINCW_1,
+ /* 0xde */ opPREPARE_0,
+ /* 0xdf */ opPREPARE_1,
+ /* 0xe0 */ opTASI_0,
+ /* 0xe1 */ opTASI_1,
+ /* 0xe2 */ opRET_0,
+ /* 0xe3 */ opRET_1,
+ /* 0xe4 */ opPOPM_0,
+ /* 0xe5 */ opPOPM_1,
+ /* 0xe6 */ opPOP_0,
+ /* 0xe7 */ opPOP_1,
+ /* 0xe8 */ opJSR_0,
+ /* 0xe9 */ opJSR_1,
+ /* 0xea */ opRETIU_0,
+ /* 0xeb */ opRETIU_1,
+ /* 0xec */ opPUSHM_0,
+ /* 0xed */ opPUSHM_1,
+ /* 0xee */ opPUSH_0,
+ /* 0xef */ opPUSH_1,
+ /* 0xf0 */ opTESTB_0,
+ /* 0xf1 */ opTESTB_1,
+ /* 0xf2 */ opTESTH_0,
+ /* 0xf3 */ opTESTH_1,
+ /* 0xf4 */ opTESTW_0,
+ /* 0xf5 */ opTESTW_1,
+ /* 0xf6 */ opGETPSW_0,
+ /* 0xf7 */ opGETPSW_1,
+ /* 0xf8 */ opTRAP_0,
+ /* 0xf9 */ opTRAP_1,
+ /* 0xfa */ opRETIS_0,
+ /* 0xfb */ opRETIS_1,
+ /* 0xfc */ opSTTASK_0,
+ /* 0xfd */ opSTTASK_1,
+ /* 0xfe */ opCLRTLB_0,
+ /* 0xff */ opCLRTLB_1,
+};
diff --git a/trunk/src/emu/cpu/v60/v60.c b/trunk/src/emu/cpu/v60/v60.c
new file mode 100644
index 00000000000..bf2e2faface
--- /dev/null
+++ b/trunk/src/emu/cpu/v60/v60.c
@@ -0,0 +1,766 @@
+// V60.C
+// Undiscover the beast!
+// Main hacking and coding by Farfetch'd
+// Portability fixes by Richter Belmont
+
+#include "emu.h"
+#include "debugger.h"
+#include "v60.h"
+
+// memory accessors
+#if defined(LSB_FIRST) && !defined(ALIGN_INTS)
+#define OpRead8(s, a) ((s)->direct->read_decrypted_byte(a))
+#define OpRead16(s, a) ((s)->direct->read_decrypted_word(a))
+#define OpRead32(s, a) ((s)->direct->read_decrypted_dword(a))
+#else
+#define OpRead8(s, a) ((s)->direct->read_decrypted_byte((a), (s)->fetch_xor))
+#define OpRead16(s, a) (((s)->direct->read_decrypted_byte(((a)+0), (s)->fetch_xor) << 0) | \
+ ((s)->direct->read_decrypted_byte(((a)+1), (s)->fetch_xor) << 8))
+#define OpRead32(s, a) (((s)->direct->read_decrypted_byte(((a)+0), (s)->fetch_xor) << 0) | \
+ ((s)->direct->read_decrypted_byte(((a)+1), (s)->fetch_xor) << 8) | \
+ ((s)->direct->read_decrypted_byte(((a)+2), (s)->fetch_xor) << 16) | \
+ ((s)->direct->read_decrypted_byte(((a)+3), (s)->fetch_xor) << 24))
+#endif
+
+
+// macros stolen from MAME for flags calc
+// note that these types are in x86 naming:
+// byte = 8 bit, word = 16 bit, long = 32 bit
+
+// parameter x = result, y = source 1, z = source 2
+
+#define SetOFL_Add(x, y,z) (cpustate->_OV = (((x) ^ (y)) & ((x) ^ (z)) & 0x80000000) ? 1: 0)
+#define SetOFW_Add(x, y,z) (cpustate->_OV = (((x) ^ (y)) & ((x) ^ (z)) & 0x8000) ? 1 : 0)
+#define SetOFB_Add(x, y,z) (cpustate->_OV = (((x) ^ (y)) & ((x) ^ (z)) & 0x80) ? 1 : 0)
+
+#define SetOFL_Sub(x, y,z) (cpustate->_OV = (((z) ^ (y)) & ((z) ^ (x)) & 0x80000000) ? 1 : 0)
+#define SetOFW_Sub(x, y,z) (cpustate->_OV = (((z) ^ (y)) & ((z) ^ (x)) & 0x8000) ? 1 : 0)
+#define SetOFB_Sub(x, y,z) (cpustate->_OV = (((z) ^ (y)) & ((z) ^ (x)) & 0x80) ? 1 : 0)
+
+#define SetCFB(x) {cpustate->_CY = ((x) & 0x100) ? 1 : 0; }
+#define SetCFW(x) {cpustate->_CY = ((x) & 0x10000) ? 1 : 0; }
+#define SetCFL(x) {cpustate->_CY = ((x) & (((UINT64)1) << 32)) ? 1 : 0; }
+
+#define SetSF(x) (cpustate->_S = (x))
+#define SetZF(x) (cpustate->_Z = (x))
+
+#define SetSZPF_Byte(x) {cpustate->_Z = ((UINT8)(x) == 0); cpustate->_S = ((x)&0x80) ? 1 : 0; }
+#define SetSZPF_Word(x) {cpustate->_Z = ((UINT16)(x) == 0); cpustate->_S = ((x)&0x8000) ? 1 : 0; }
+#define SetSZPF_Long(x) {cpustate->_Z = ((UINT32)(x) == 0); cpustate->_S = ((x)&0x80000000) ? 1 : 0; }
+
+#define ORB(dst, src) { (dst) |= (src); cpustate->_CY = cpustate->_OV = 0; SetSZPF_Byte(dst); }
+#define ORW(dst, src) { (dst) |= (src); cpustate->_CY = cpustate->_OV = 0; SetSZPF_Word(dst); }
+#define ORL(dst, src) { (dst) |= (src); cpustate->_CY = cpustate->_OV = 0; SetSZPF_Long(dst); }
+
+#define ANDB(dst, src) { (dst) &= (src); cpustate->_CY = cpustate->_OV = 0; SetSZPF_Byte(dst); }
+#define ANDW(dst, src) { (dst) &= (src); cpustate->_CY = cpustate->_OV = 0; SetSZPF_Word(dst); }
+#define ANDL(dst, src) { (dst) &= (src); cpustate->_CY = cpustate->_OV = 0; SetSZPF_Long(dst); }
+
+#define XORB(dst, src) { (dst) ^= (src); cpustate->_CY = cpustate->_OV = 0; SetSZPF_Byte(dst); }
+#define XORW(dst, src) { (dst) ^= (src); cpustate->_CY = cpustate->_OV = 0; SetSZPF_Word(dst); }
+#define XORL(dst, src) { (dst) ^= (src); cpustate->_CY = cpustate->_OV = 0; SetSZPF_Long(dst); }
+
+#define SUBB(dst, src) { unsigned res = (dst) - (src); SetCFB(res); SetOFB_Sub(res, src, dst); SetSZPF_Byte(res); dst = (UINT8)res; }
+#define SUBW(dst, src) { unsigned res = (dst) - (src); SetCFW(res); SetOFW_Sub(res, src, dst); SetSZPF_Word(res); dst = (UINT16)res; }
+#define SUBL(dst, src) { UINT64 res = (UINT64)(dst) - (INT64)(src); SetCFL(res); SetOFL_Sub(res, src, dst); SetSZPF_Long(res); dst = (UINT32)res; }
+
+#define ADDB(dst, src) { unsigned res = (dst) + (src); SetCFB(res); SetOFB_Add(res, src, dst); SetSZPF_Byte(res); dst = (UINT8)res; }
+#define ADDW(dst, src) { unsigned res = (dst) + (src); SetCFW(res); SetOFW_Add(res, src, dst); SetSZPF_Word(res); dst = (UINT16)res; }
+#define ADDL(dst, src) { UINT64 res = (UINT64)(dst) + (UINT64)(src); SetCFL(res); SetOFL_Add(res, src, dst); SetSZPF_Long(res); dst = (UINT32)res; }
+
+#define SETREG8(a, b) (a) = ((a) & ~0xff) | ((b) & 0xff)
+#define SETREG16(a, b) (a) = ((a) & ~0xffff) | ((b) & 0xffff)
+
+typedef struct _v60_flags v60_flags;
+struct _v60_flags
+{
+ UINT8 CY;
+ UINT8 OV;
+ UINT8 S;
+ UINT8 Z;
+};
+
+// v60 Register Inside (Hm... It's not a pentium inside :-))) )
+typedef struct _v60_state v60_state;
+struct _v60_state
+{
+ offs_t fetch_xor;
+ offs_t start_pc;
+ UINT32 reg[68];
+ v60_flags flags;
+ UINT8 irq_line;
+ UINT8 nmi_line;
+ device_irq_callback irq_cb;
+ legacy_cpu_device * device;
+ address_space *program;
+ direct_read_data * direct;
+ address_space *io;
+ UINT32 PPC;
+ int icount;
+ int stall_io;
+
+ UINT32 op1, op2;
+ UINT8 flag1, flag2;
+ UINT8 instflags;
+ UINT32 lenop1, lenop2;
+ UINT8 subop;
+ UINT32 bamoffset1, bamoffset2;
+
+ // Output variables for ReadAMAddress(cpustate)
+ UINT8 amflag;
+ UINT32 amout;
+ UINT32 bamoffset;
+
+ // Appo temp var
+ UINT32 amlength1, amlength2;
+
+ // Global vars used by AM functions
+ UINT32 modadd;
+ UINT8 modm;
+ UINT8 modval;
+ UINT8 modval2;
+ UINT8 modwritevalb;
+ UINT16 modwritevalh;
+ UINT32 modwritevalw;
+ UINT8 moddim;
+};
+
+INLINE v60_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == V60 ||
+ device->type() == V70);
+ return (v60_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/*
+ * Prevent warnings on NetBSD. All identifiers beginning with an underscore
+ * followed by an uppercase letter are reserved by the C standard (ISO / IEC
+ * 9899:1999, 7.1.3) to be used by the implementation. It'd be best to rename
+ * all such instances, but this is less intrusive and error-prone.
+ */
+#undef _S
+
+#define _CY flags.CY
+#define _OV flags.OV
+#define _S flags.S
+#define _Z flags.Z
+
+
+// Defines of all v60 register...
+#define R0 reg[0]
+#define R1 reg[1]
+#define R2 reg[2]
+#define R3 reg[3]
+#define R4 reg[4]
+#define R5 reg[5]
+#define R6 reg[6]
+#define R7 reg[7]
+#define R8 reg[8]
+#define R9 reg[9]
+#define R10 reg[10]
+#define R11 reg[11]
+#define R12 reg[12]
+#define R13 reg[13]
+#define R14 reg[14]
+#define R15 reg[15]
+#define R16 reg[16]
+#define R17 reg[17]
+#define R18 reg[18]
+#define R19 reg[19]
+#define R20 reg[20]
+#define R21 reg[21]
+#define R22 reg[22]
+#define R23 reg[23]
+#define R24 reg[24]
+#define R25 reg[25]
+#define R26 reg[26]
+#define R27 reg[27]
+#define R28 reg[28]
+#define AP reg[29]
+#define FP reg[30]
+#define SP reg[31]
+
+#define PC reg[32]
+#define PSW reg[33]
+
+// Privileged registers
+#define ISP reg[36]
+#define L0SP reg[37]
+#define L1SP reg[38]
+#define L2SP reg[39]
+#define L3SP reg[40]
+#define SBR reg[41]
+#define TR reg[42]
+#define SYCW reg[43]
+#define TKCW reg[44]
+#define PIR reg[45]
+//10-14 reserved
+#define PSW2 reg[51]
+#define ATBR0 reg[52]
+#define ATLR0 reg[53]
+#define ATBR1 reg[54]
+#define ATLR1 reg[55]
+#define ATBR2 reg[56]
+#define ATLR2 reg[57]
+#define ATBR3 reg[58]
+#define ATLR3 reg[59]
+#define TRMODE reg[60]
+#define ADTR0 reg[61]
+#define ADTR1 reg[62]
+#define ADTMR0 reg[63]
+#define ADTMR1 reg[64]
+//29-31 reserved
+
+// Defines...
+#define NORMALIZEFLAGS(cs) \
+{ \
+ (cs)->_S = (cs)->_S ? 1 : 0; \
+ (cs)->_OV = (cs)->_OV ? 1 : 0; \
+ (cs)->_Z = (cs)->_Z ? 1 : 0; \
+ (cs)->_CY = (cs)->_CY ? 1 : 0; \
+}
+
+static void v60_try_irq(v60_state *cpustate);
+
+
+INLINE void v60SaveStack(v60_state *cpustate)
+{
+ if (cpustate->PSW & 0x10000000)
+ cpustate->ISP = cpustate->SP;
+ else
+ cpustate->reg[37 + ((cpustate->PSW >> 24) & 3)] = cpustate->SP;
+}
+
+INLINE void v60ReloadStack(v60_state *cpustate)
+{
+ if (cpustate->PSW & 0x10000000)
+ cpustate->SP = cpustate->ISP;
+ else
+ cpustate->SP = cpustate->reg[37 + ((cpustate->PSW >> 24) & 3)];
+}
+
+INLINE UINT32 v60ReadPSW(v60_state *cpustate)
+{
+ cpustate->PSW &= 0xfffffff0;
+ cpustate->PSW |= (cpustate->_Z?1:0) | (cpustate->_S?2:0) | (cpustate->_OV?4:0) | (cpustate->_CY?8:0);
+ return cpustate->PSW;
+}
+
+INLINE void v60WritePSW(v60_state *cpustate, UINT32 newval)
+{
+ /* determine if we need to save / restore the stacks */
+ int updateStack = 0;
+
+ /* if the interrupt state is changing, we definitely need to update */
+ if ((newval ^ cpustate->PSW) & 0x10000000)
+ updateStack = 1;
+
+ /* if we are not in interrupt mode and the level is changing, we also must update */
+ else if (!(cpustate->PSW & 0x10000000) && ((newval ^ cpustate->PSW) & 0x03000000))
+ updateStack = 1;
+
+ /* save the previous stack value */
+ if (updateStack)
+ v60SaveStack(cpustate);
+
+ /* set the new value and update the flags */
+ cpustate->PSW = newval;
+ cpustate->_Z = (UINT8)(cpustate->PSW & 1);
+ cpustate->_S = (UINT8)(cpustate->PSW & 2);
+ cpustate->_OV = (UINT8)(cpustate->PSW & 4);
+ cpustate->_CY = (UINT8)(cpustate->PSW & 8);
+
+ /* fetch the new stack value */
+ if (updateStack)
+ v60ReloadStack(cpustate);
+}
+
+
+INLINE UINT32 v60_update_psw_for_exception(v60_state *cpustate, int is_interrupt, int target_level)
+{
+ UINT32 oldPSW = v60ReadPSW(cpustate);
+ UINT32 newPSW = oldPSW;
+
+ // Change to interrupt context
+ newPSW &= ~(3 << 24); // cpustate->PSW.EL = 0
+ newPSW |= target_level << 24; // set target level
+ newPSW &= ~(1 << 18); // cpustate->PSW.IE = 0
+ newPSW &= ~(1 << 16); // cpustate->PSW.TE = 0
+ newPSW &= ~(1 << 27); // cpustate->PSW.TP = 0
+ newPSW &= ~(1 << 17); // cpustate->PSW.AE = 0
+ newPSW &= ~(1 << 29); // cpustate->PSW.EM = 0
+ if (is_interrupt)
+ newPSW |= (1 << 28);// cpustate->PSW.IS = 1
+ newPSW |= (1 << 31); // cpustate->PSW.ASA = 1
+ v60WritePSW(cpustate, newPSW);
+
+ return oldPSW;
+}
+
+
+#define GETINTVECT(cs, nint) (cs)->program->read_dword(((cs)->SBR & ~0xfff) + (nint) * 4)
+#define EXCEPTION_CODE_AND_SIZE(code, size) (((code) << 16) | (size))
+
+
+// Addressing mode decoding functions
+#include "am.c"
+
+// Opcode functions
+#include "op12.c"
+#include "op2.c"
+#include "op3.c"
+#include "op4.c"
+#include "op5.c"
+#include "op6.c"
+#include "op7a.c"
+
+static UINT32 opUNHANDLED(v60_state *cpustate)
+{
+ fatalerror("Unhandled OpCode found : %02x at %08x", OpRead16(cpustate, cpustate->PC), cpustate->PC);
+ return 0; /* never reached, fatalerror won't return */
+}
+
+// Opcode jump table
+#include "optable.c"
+
+static void base_init(legacy_cpu_device *device, device_irq_callback irqcallback)
+{
+ v60_state *cpustate = get_safe_token(device);
+
+ cpustate->stall_io = 0;
+ cpustate->irq_cb = irqcallback;
+ cpustate->device = device;
+ cpustate->irq_line = CLEAR_LINE;
+ cpustate->nmi_line = CLEAR_LINE;
+
+ device->save_item(NAME(cpustate->reg));
+ device->save_item(NAME(cpustate->irq_line));
+ device->save_item(NAME(cpustate->nmi_line));
+ device->save_item(NAME(cpustate->PPC));
+ device->save_item(NAME(cpustate->_CY));
+ device->save_item(NAME(cpustate->_OV));
+ device->save_item(NAME(cpustate->_S));
+ device->save_item(NAME(cpustate->_Z));
+}
+
+static CPU_INIT( v60 )
+{
+ v60_state *cpustate = get_safe_token(device);
+
+ base_init(device, irqcallback);
+ // Set cpustate->PIR (Processor ID) for NEC cpustate-> LSB is reserved to NEC,
+ // so I don't know what it contains.
+ cpustate->PIR = 0x00006000;
+ cpustate->fetch_xor = BYTE_XOR_LE(0);
+ cpustate->start_pc = 0xfffff0;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->io = device->space(AS_IO);
+}
+
+static CPU_INIT( v70 )
+{
+ v60_state *cpustate = get_safe_token(device);
+
+ base_init(device, irqcallback);
+ // Set cpustate->PIR (Processor ID) for NEC v70. LSB is reserved to NEC,
+ // so I don't know what it contains.
+ cpustate->PIR = 0x00007000;
+ cpustate->fetch_xor = BYTE4_XOR_LE(0);
+ cpustate->start_pc = 0xfffffff0;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->io = device->space(AS_IO);
+}
+
+static CPU_RESET( v60 )
+{
+ v60_state *cpustate = get_safe_token(device);
+
+ cpustate->PSW = 0x10000000;
+ cpustate->PC = cpustate->start_pc;
+ cpustate->SBR = 0x00000000;
+ cpustate->SYCW = 0x00000070;
+ cpustate->TKCW = 0x0000e000;
+ cpustate->PSW2 = 0x0000f002;
+
+ cpustate->_CY = 0;
+ cpustate->_OV = 0;
+ cpustate->_S = 0;
+ cpustate->_Z = 0;
+}
+
+static CPU_EXIT( v60 )
+{
+}
+
+void v60_stall(device_t *device)
+{
+ v60_state *cpustate = get_safe_token(device);
+ cpustate->stall_io = 1;
+}
+
+static void v60_do_irq(v60_state *cpustate, int vector)
+{
+ UINT32 oldPSW = v60_update_psw_for_exception(cpustate, 1, 0);
+
+ // Push cpustate->PC and cpustate->PSW onto the stack
+ cpustate->SP-=4;
+ cpustate->program->write_dword_unaligned(cpustate->SP, oldPSW);
+ cpustate->SP-=4;
+ cpustate->program->write_dword_unaligned(cpustate->SP, cpustate->PC);
+
+ // Jump to vector for user interrupt
+ cpustate->PC = GETINTVECT(cpustate, vector);
+}
+
+static void v60_try_irq(v60_state *cpustate)
+{
+ if(cpustate->irq_line == CLEAR_LINE)
+ return;
+ if((cpustate->PSW & (1 << 18)) != 0) {
+ int vector;
+ if(cpustate->irq_line != ASSERT_LINE)
+ cpustate->irq_line = CLEAR_LINE;
+
+ vector = cpustate->irq_cb(cpustate->device, 0);
+
+ v60_do_irq(cpustate, vector + 0x40);
+ }
+}
+
+static void set_irq_line(v60_state *cpustate, int irqline, int state)
+{
+ if(irqline == INPUT_LINE_NMI) {
+ switch(state) {
+ case ASSERT_LINE:
+ if(cpustate->nmi_line == CLEAR_LINE) {
+ cpustate->nmi_line = ASSERT_LINE;
+ v60_do_irq(cpustate, 2);
+ }
+ break;
+ case CLEAR_LINE:
+ cpustate->nmi_line = CLEAR_LINE;
+ break;
+ }
+ } else {
+ cpustate->irq_line = state;
+ v60_try_irq(cpustate);
+ }
+}
+
+// Actual cycles / instruction is unknown
+
+static CPU_EXECUTE( v60 )
+{
+ v60_state *cpustate = get_safe_token(device);
+
+ if (cpustate->irq_line != CLEAR_LINE)
+ v60_try_irq(cpustate);
+
+ while (cpustate->icount > 0)
+ {
+ UINT32 inc;
+ cpustate->PPC = cpustate->PC;
+ debugger_instruction_hook(device, cpustate->PC);
+ cpustate->icount -= 8; /* fix me -- this is just an average */
+ inc = OpCodeTable[OpRead8(cpustate, cpustate->PC)](cpustate);
+ cpustate->PC += inc;
+ if (cpustate->irq_line != CLEAR_LINE)
+ v60_try_irq(cpustate);
+ }
+}
+
+
+CPU_DISASSEMBLE( v60 );
+CPU_DISASSEMBLE( v70 );
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( v60 )
+{
+ v60_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_PC: cpustate->PC = info->i; break;
+ case CPUINFO_INT_SP: cpustate->SP = info->i; break;
+
+ case CPUINFO_INT_REGISTER + V60_R0: cpustate->R0 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R1: cpustate->R1 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R2: cpustate->R2 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R3: cpustate->R3 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R4: cpustate->R4 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R5: cpustate->R5 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R6: cpustate->R6 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R7: cpustate->R7 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R8: cpustate->R8 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R9: cpustate->R9 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R10: cpustate->R10 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R11: cpustate->R11 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R12: cpustate->R12 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R13: cpustate->R13 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R14: cpustate->R14 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R15: cpustate->R15 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R16: cpustate->R16 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R17: cpustate->R17 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R18: cpustate->R18 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R19: cpustate->R19 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R20: cpustate->R20 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R21: cpustate->R21 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R22: cpustate->R22 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R23: cpustate->R23 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R24: cpustate->R24 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R25: cpustate->R25 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R26: cpustate->R26 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R27: cpustate->R27 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_R28: cpustate->R28 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_AP: cpustate->AP = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_FP: cpustate->FP = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_SP: cpustate->SP = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_PC: cpustate->PC = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_PSW: v60WritePSW(cpustate, info->i); break;
+ case CPUINFO_INT_REGISTER + V60_ISP: cpustate->ISP = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_L0SP: cpustate->L0SP = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_L1SP: cpustate->L1SP = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_L2SP: cpustate->L2SP = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_L3SP: cpustate->L3SP = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_SBR: cpustate->SBR = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_TR: cpustate->TR = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_SYCW: cpustate->SYCW = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_TKCW: cpustate->TKCW = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_PIR: cpustate->PIR = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_PSW2: cpustate->PSW2 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_ATBR0: cpustate->ATBR0 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_ATLR0: cpustate->ATLR0 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_ATBR1: cpustate->ATBR1 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_ATLR1: cpustate->ATLR1 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_ATBR2: cpustate->ATBR2 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_ATLR2: cpustate->ATLR2 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_ATBR3: cpustate->ATBR3 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_ATLR3: cpustate->ATLR3 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_TRMODE: cpustate->TRMODE = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_ADTR0: cpustate->ADTR0 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_ADTR1: cpustate->ADTR1 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_ADTMR0: cpustate->ADTMR0 = info->i; break;
+ case CPUINFO_INT_REGISTER + V60_ADTMR1: cpustate->ADTMR1 = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( v60 )
+{
+ v60_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(v60_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 = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 22; 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 = 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 = 24; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + 0: info->i = cpustate->irq_line; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = cpustate->nmi_line; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->PPC; break;
+
+ case CPUINFO_INT_REGISTER + V60_R0: info->i = cpustate->R0; break;
+ case CPUINFO_INT_REGISTER + V60_R1: info->i = cpustate->R1; break;
+ case CPUINFO_INT_REGISTER + V60_R2: info->i = cpustate->R2; break;
+ case CPUINFO_INT_REGISTER + V60_R3: info->i = cpustate->R3; break;
+ case CPUINFO_INT_REGISTER + V60_R4: info->i = cpustate->R4; break;
+ case CPUINFO_INT_REGISTER + V60_R5: info->i = cpustate->R5; break;
+ case CPUINFO_INT_REGISTER + V60_R6: info->i = cpustate->R6; break;
+ case CPUINFO_INT_REGISTER + V60_R7: info->i = cpustate->R7; break;
+ case CPUINFO_INT_REGISTER + V60_R8: info->i = cpustate->R8; break;
+ case CPUINFO_INT_REGISTER + V60_R9: info->i = cpustate->R9; break;
+ case CPUINFO_INT_REGISTER + V60_R10: info->i = cpustate->R10; break;
+ case CPUINFO_INT_REGISTER + V60_R11: info->i = cpustate->R11; break;
+ case CPUINFO_INT_REGISTER + V60_R12: info->i = cpustate->R12; break;
+ case CPUINFO_INT_REGISTER + V60_R13: info->i = cpustate->R13; break;
+ case CPUINFO_INT_REGISTER + V60_R14: info->i = cpustate->R14; break;
+ case CPUINFO_INT_REGISTER + V60_R15: info->i = cpustate->R15; break;
+ case CPUINFO_INT_REGISTER + V60_R16: info->i = cpustate->R16; break;
+ case CPUINFO_INT_REGISTER + V60_R17: info->i = cpustate->R17; break;
+ case CPUINFO_INT_REGISTER + V60_R18: info->i = cpustate->R18; break;
+ case CPUINFO_INT_REGISTER + V60_R19: info->i = cpustate->R19; break;
+ case CPUINFO_INT_REGISTER + V60_R20: info->i = cpustate->R20; break;
+ case CPUINFO_INT_REGISTER + V60_R21: info->i = cpustate->R21; break;
+ case CPUINFO_INT_REGISTER + V60_R22: info->i = cpustate->R22; break;
+ case CPUINFO_INT_REGISTER + V60_R23: info->i = cpustate->R23; break;
+ case CPUINFO_INT_REGISTER + V60_R24: info->i = cpustate->R24; break;
+ case CPUINFO_INT_REGISTER + V60_R25: info->i = cpustate->R25; break;
+ case CPUINFO_INT_REGISTER + V60_R26: info->i = cpustate->R26; break;
+ case CPUINFO_INT_REGISTER + V60_R27: info->i = cpustate->R27; break;
+ case CPUINFO_INT_REGISTER + V60_R28: info->i = cpustate->R28; break;
+ case CPUINFO_INT_REGISTER + V60_AP: info->i = cpustate->AP; break;
+ case CPUINFO_INT_REGISTER + V60_FP: info->i = cpustate->FP; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + V60_SP: info->i = cpustate->SP; break;
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + V60_PC: info->i = cpustate->PC; break;
+ case CPUINFO_INT_REGISTER + V60_PSW: info->i = v60ReadPSW(cpustate); break;
+ case CPUINFO_INT_REGISTER + V60_ISP: info->i = cpustate->ISP; break;
+ case CPUINFO_INT_REGISTER + V60_L0SP: info->i = cpustate->L0SP; break;
+ case CPUINFO_INT_REGISTER + V60_L1SP: info->i = cpustate->L1SP; break;
+ case CPUINFO_INT_REGISTER + V60_L2SP: info->i = cpustate->L2SP; break;
+ case CPUINFO_INT_REGISTER + V60_L3SP: info->i = cpustate->L3SP; break;
+ case CPUINFO_INT_REGISTER + V60_SBR: info->i = cpustate->SBR; break;
+ case CPUINFO_INT_REGISTER + V60_TR: info->i = cpustate->TR; break;
+ case CPUINFO_INT_REGISTER + V60_SYCW: info->i = cpustate->SYCW; break;
+ case CPUINFO_INT_REGISTER + V60_TKCW: info->i = cpustate->TKCW; break;
+ case CPUINFO_INT_REGISTER + V60_PIR: info->i = cpustate->PIR; break;
+ case CPUINFO_INT_REGISTER + V60_PSW2: info->i = cpustate->PSW2; break;
+ case CPUINFO_INT_REGISTER + V60_ATBR0: info->i = cpustate->ATBR0; break;
+ case CPUINFO_INT_REGISTER + V60_ATLR0: info->i = cpustate->ATLR0; break;
+ case CPUINFO_INT_REGISTER + V60_ATBR1: info->i = cpustate->ATBR1; break;
+ case CPUINFO_INT_REGISTER + V60_ATLR1: info->i = cpustate->ATLR1; break;
+ case CPUINFO_INT_REGISTER + V60_ATBR2: info->i = cpustate->ATBR2; break;
+ case CPUINFO_INT_REGISTER + V60_ATLR2: info->i = cpustate->ATLR2; break;
+ case CPUINFO_INT_REGISTER + V60_ATBR3: info->i = cpustate->ATBR3; break;
+ case CPUINFO_INT_REGISTER + V60_ATLR3: info->i = cpustate->ATLR3; break;
+ case CPUINFO_INT_REGISTER + V60_TRMODE: info->i = cpustate->TRMODE; break;
+ case CPUINFO_INT_REGISTER + V60_ADTR0: info->i = cpustate->ADTR0; break;
+ case CPUINFO_INT_REGISTER + V60_ADTR1: info->i = cpustate->ADTR1; break;
+ case CPUINFO_INT_REGISTER + V60_ADTMR0: info->i = cpustate->ADTMR0; break;
+ case CPUINFO_INT_REGISTER + V60_ADTMR1: info->i = cpustate->ADTMR1; 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(v60); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(v60); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(v60); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(v60); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(v60); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(v60); 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, "V60"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "NEC V60"); 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, "Farfetch'd and R.Belmont"); break;
+
+ case CPUINFO_STR_FLAGS: strcpy(info->s, " "); break;
+
+ case CPUINFO_STR_REGISTER + V60_R0: sprintf(info->s, "R0:%08X", cpustate->R0); break;
+ case CPUINFO_STR_REGISTER + V60_R1: sprintf(info->s, "R1:%08X", cpustate->R1); break;
+ case CPUINFO_STR_REGISTER + V60_R2: sprintf(info->s, "R2:%08X", cpustate->R2); break;
+ case CPUINFO_STR_REGISTER + V60_R3: sprintf(info->s, "R3:%08X", cpustate->R3); break;
+ case CPUINFO_STR_REGISTER + V60_R4: sprintf(info->s, "R4:%08X", cpustate->R4); break;
+ case CPUINFO_STR_REGISTER + V60_R5: sprintf(info->s, "R5:%08X", cpustate->R5); break;
+ case CPUINFO_STR_REGISTER + V60_R6: sprintf(info->s, "R6:%08X", cpustate->R6); break;
+ case CPUINFO_STR_REGISTER + V60_R7: sprintf(info->s, "R7:%08X", cpustate->R7); break;
+ case CPUINFO_STR_REGISTER + V60_R8: sprintf(info->s, "R8:%08X", cpustate->R8); break;
+ case CPUINFO_STR_REGISTER + V60_R9: sprintf(info->s, "R9:%08X", cpustate->R9); break;
+ case CPUINFO_STR_REGISTER + V60_R10: sprintf(info->s, "R10:%08X", cpustate->R10); break;
+ case CPUINFO_STR_REGISTER + V60_R11: sprintf(info->s, "R11:%08X", cpustate->R11); break;
+ case CPUINFO_STR_REGISTER + V60_R12: sprintf(info->s, "R12:%08X", cpustate->R12); break;
+ case CPUINFO_STR_REGISTER + V60_R13: sprintf(info->s, "R13:%08X", cpustate->R13); break;
+ case CPUINFO_STR_REGISTER + V60_R14: sprintf(info->s, "R14:%08X", cpustate->R14); break;
+ case CPUINFO_STR_REGISTER + V60_R15: sprintf(info->s, "R15:%08X", cpustate->R15); break;
+ case CPUINFO_STR_REGISTER + V60_R16: sprintf(info->s, "R16:%08X", cpustate->R16); break;
+ case CPUINFO_STR_REGISTER + V60_R17: sprintf(info->s, "R17:%08X", cpustate->R17); break;
+ case CPUINFO_STR_REGISTER + V60_R18: sprintf(info->s, "R18:%08X", cpustate->R18); break;
+ case CPUINFO_STR_REGISTER + V60_R19: sprintf(info->s, "R19:%08X", cpustate->R19); break;
+ case CPUINFO_STR_REGISTER + V60_R20: sprintf(info->s, "R20:%08X", cpustate->R20); break;
+ case CPUINFO_STR_REGISTER + V60_R21: sprintf(info->s, "R21:%08X", cpustate->R21); break;
+ case CPUINFO_STR_REGISTER + V60_R22: sprintf(info->s, "R22:%08X", cpustate->R22); break;
+ case CPUINFO_STR_REGISTER + V60_R23: sprintf(info->s, "R23:%08X", cpustate->R23); break;
+ case CPUINFO_STR_REGISTER + V60_R24: sprintf(info->s, "R24:%08X", cpustate->R24); break;
+ case CPUINFO_STR_REGISTER + V60_R25: sprintf(info->s, "R25:%08X", cpustate->R25); break;
+ case CPUINFO_STR_REGISTER + V60_R26: sprintf(info->s, "R26:%08X", cpustate->R26); break;
+ case CPUINFO_STR_REGISTER + V60_R27: sprintf(info->s, "R27:%08X", cpustate->R27); break;
+ case CPUINFO_STR_REGISTER + V60_R28: sprintf(info->s, "R28:%08X", cpustate->R28); break;
+ case CPUINFO_STR_REGISTER + V60_AP: sprintf(info->s, "AP:%08X", cpustate->AP); break;
+ case CPUINFO_STR_REGISTER + V60_FP: sprintf(info->s, "FP:%08X", cpustate->FP); break;
+ case CPUINFO_STR_REGISTER + V60_SP: sprintf(info->s, "SP:%08X", cpustate->SP); break;
+ case CPUINFO_STR_REGISTER + V60_PC: sprintf(info->s, "PC:%08X", cpustate->PC); break;
+ case CPUINFO_STR_REGISTER + V60_PSW: sprintf(info->s, "PSW:%08X", v60ReadPSW(cpustate)); break;
+ case CPUINFO_STR_REGISTER + V60_ISP: sprintf(info->s, "ISP:%08X", cpustate->ISP); break;
+ case CPUINFO_STR_REGISTER + V60_L0SP: sprintf(info->s, "L0SP:%08X", cpustate->L0SP); break;
+ case CPUINFO_STR_REGISTER + V60_L1SP: sprintf(info->s, "L1SP:%08X", cpustate->L1SP); break;
+ case CPUINFO_STR_REGISTER + V60_L2SP: sprintf(info->s, "L2SP:%08X", cpustate->L2SP); break;
+ case CPUINFO_STR_REGISTER + V60_L3SP: sprintf(info->s, "L3SP:%08X", cpustate->L3SP); break;
+ case CPUINFO_STR_REGISTER + V60_SBR: sprintf(info->s, "SBR:%08X", cpustate->SBR); break;
+ case CPUINFO_STR_REGISTER + V60_TR: sprintf(info->s, "TR:%08X", cpustate->TR); break;
+ case CPUINFO_STR_REGISTER + V60_SYCW: sprintf(info->s, "SYCW:%08X", cpustate->SYCW); break;
+ case CPUINFO_STR_REGISTER + V60_TKCW: sprintf(info->s, "TKCW:%08X", cpustate->TKCW); break;
+ case CPUINFO_STR_REGISTER + V60_PIR: sprintf(info->s, "PIR:%08X", cpustate->PIR); break;
+ case CPUINFO_STR_REGISTER + V60_PSW2: sprintf(info->s, "PSW2:%08X", cpustate->PSW2); break;
+ case CPUINFO_STR_REGISTER + V60_ATBR0: sprintf(info->s, "ATBR0:%08X", cpustate->ATBR0); break;
+ case CPUINFO_STR_REGISTER + V60_ATLR0: sprintf(info->s, "ATLR0:%08X", cpustate->ATLR0); break;
+ case CPUINFO_STR_REGISTER + V60_ATBR1: sprintf(info->s, "ATBR1:%08X", cpustate->ATBR1); break;
+ case CPUINFO_STR_REGISTER + V60_ATLR1: sprintf(info->s, "ATLR1:%08X", cpustate->ATLR1); break;
+ case CPUINFO_STR_REGISTER + V60_ATBR2: sprintf(info->s, "ATBR2:%08X", cpustate->ATBR2); break;
+ case CPUINFO_STR_REGISTER + V60_ATLR2: sprintf(info->s, "ATLR2:%08X", cpustate->ATLR2); break;
+ case CPUINFO_STR_REGISTER + V60_ATBR3: sprintf(info->s, "ATBR3:%08X", cpustate->ATBR3); break;
+ case CPUINFO_STR_REGISTER + V60_ATLR3: sprintf(info->s, "ATLR3:%08X", cpustate->ATLR3); break;
+ case CPUINFO_STR_REGISTER + V60_TRMODE: sprintf(info->s, "TRMODE:%08X", cpustate->TRMODE); break;
+ case CPUINFO_STR_REGISTER + V60_ADTR0: sprintf(info->s, "ADTR0:%08X", cpustate->ADTR0); break;
+ case CPUINFO_STR_REGISTER + V60_ADTR1: sprintf(info->s, "ADTR1:%08X", cpustate->ADTR1); break;
+ case CPUINFO_STR_REGISTER + V60_ADTMR0: sprintf(info->s, "ADTMR0:%08X", cpustate->ADTMR0); break;
+ case CPUINFO_STR_REGISTER + V60_ADTMR1: sprintf(info->s, "ADTMR1:%08X", cpustate->ADTMR1); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+CPU_GET_INFO( v70 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ 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;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(v70); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(v70); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "V70"); break;
+
+ default: CPU_GET_INFO_CALL(v60); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(V60, v60);
+DEFINE_LEGACY_CPU_DEVICE(V70, v70);
diff --git a/trunk/src/emu/cpu/v60/v60.h b/trunk/src/emu/cpu/v60/v60.h
new file mode 100644
index 00000000000..35b653aed26
--- /dev/null
+++ b/trunk/src/emu/cpu/v60/v60.h
@@ -0,0 +1,85 @@
+#pragma once
+
+#ifndef __V60_H__
+#define __V60_H__
+
+
+enum
+{
+ V60_R0 = 1,
+ V60_R1,
+ V60_R2,
+ V60_R3,
+ V60_R4,
+ V60_R5,
+ V60_R6,
+ V60_R7,
+ V60_R8,
+ V60_R9,
+ V60_R10,
+ V60_R11,
+ V60_R12,
+ V60_R13,
+ V60_R14,
+ V60_R15,
+ V60_R16,
+ V60_R17,
+ V60_R18,
+ V60_R19,
+ V60_R20,
+ V60_R21,
+ V60_R22,
+ V60_R23,
+ V60_R24,
+ V60_R25,
+ V60_R26,
+ V60_R27,
+ V60_R28,
+ V60_AP,
+ V60_FP,
+ V60_SP,
+ V60_PC,
+ V60_PSW,
+ V60_U1,
+ V60_U2,
+ V60_ISP,
+ V60_L0SP,
+ V60_L1SP,
+ V60_L2SP,
+ V60_L3SP,
+ V60_SBR,
+ V60_TR,
+ V60_SYCW,
+ V60_TKCW,
+ V60_PIR,
+ V60_Res1,
+ V60_Res2,
+ V60_Res3,
+ V60_Res4,
+ V60_Res5,
+ V60_PSW2,
+ V60_ATBR0,
+ V60_ATLR0,
+ V60_ATBR1,
+ V60_ATLR1,
+ V60_ATBR2,
+ V60_ATLR2,
+ V60_ATBR3,
+ V60_ATLR3,
+ V60_TRMODE,
+ V60_ADTR0,
+ V60_ADTR1,
+ V60_ADTMR0,
+ V60_ADTMR1,
+ V60_Res6,
+ V60_Res7,
+ V60_Res8,
+ V60_REGMAX
+};
+
+void v60_stall(device_t *device);
+
+DECLARE_LEGACY_CPU_DEVICE(V60, v60);
+DECLARE_LEGACY_CPU_DEVICE(V70, v70);
+
+#endif /* __V60_H__ */
diff --git a/trunk/src/emu/cpu/v60/v60d.c b/trunk/src/emu/cpu/v60/v60d.c
new file mode 100644
index 00000000000..1a181b448b2
--- /dev/null
+++ b/trunk/src/emu/cpu/v60/v60d.c
@@ -0,0 +1,1497 @@
+
+#include "emu.h"
+#include "debugger.h"
+#include "v60.h"
+
+// Register names
+static const char *const v60_reg_names[69] = {
+ "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", "AP", "FP", "SP",
+ "PC", "PSW","Unk","Unk",
+ "ISP", "L0SP", "L1SP", "L2SP",
+ "L3SP", "SBR","TR","SYCW",
+ "TKCW", "PIR", "Reserved","Reserved",
+ "Reserved","Reserved","Reserved","PSW2",
+ "ATBR0", "ATLR0", "ATBR1", "ATLR1",
+ "ATBR2", "ATLR2", "ATBR3", "ATLR3",
+ "TRMODE", "ADTR0", "ADTR1","ADTMR0",
+ "ADTMR1","Reserved","Reserved","Reserved"
+};
+
+static const UINT8 *rombase;
+static offs_t pcbase;
+
+#define readop(a) rombase[(a) - pcbase]
+
+static signed char read8(unsigned pc)
+{
+ return readop(pc);
+}
+
+static signed short read16(unsigned pc)
+{
+ return readop(pc) | (readop(pc+1) << 8);
+}
+
+static signed int read32(unsigned pc)
+{
+ return readop(pc) | (readop(pc+1) << 8)| (readop(pc+2) << 16)| (readop(pc+3) << 24);
+}
+
+static void out_AM_Register(int reg, char *out)
+{
+ strcat(out, v60_reg_names[reg]);
+}
+
+static void out_AM_RegisterIndirect(int reg, int opsize, char *out)
+{
+ if(opsize & 0x80)
+ *out++ = '@';
+ sprintf(out, "[%s]", v60_reg_names[reg]);
+}
+
+static void out_AM_RegisterIndirectIndexed(int rn, int rx, int opsize, char *out)
+{
+ if(opsize & 0x80)
+ sprintf(out, "%s@[%s]", v60_reg_names[rx], v60_reg_names[rn]);
+ else
+ sprintf(out, "[%s](%s)", v60_reg_names[rn], v60_reg_names[rx]);
+
+}
+
+static void out_AM_Autoincrement(int reg, int opsize, char *out)
+{
+ if(opsize & 0x80)
+ *out++ = '@';
+ sprintf(out, "[%s+]", v60_reg_names[reg]);
+}
+
+static void out_AM_Autodecrement(int reg, int opsize, char *out)
+{
+ if(opsize & 0x80)
+ *out++ = '@';
+ sprintf(out, "[-%s]", v60_reg_names[reg]);
+}
+
+static void out_AM_Displacement(int reg, int disp, int opsize, char *out)
+{
+ sprintf(out, "%s%X%s[%s]",
+ disp >= 0 ? "" : "-", disp >= 0 ? disp : -disp,
+ opsize & 0x80 ? "@" : "",
+ v60_reg_names[reg]);
+}
+
+static void out_AM_DisplacementIndexed(int rn, int rx, int disp, int opsize, char *out)
+{
+ if(opsize & 0x80)
+ sprintf(out, "%s@%s%X[%s]", v60_reg_names[rx], disp >= 0 ? "" : "-", disp >= 0 ? disp : -disp,v60_reg_names[rn]);
+ else
+ sprintf(out, "%s%X[%s](%s)", disp >= 0 ? "" : "-", disp >= 0 ? disp : -disp,v60_reg_names[rn], v60_reg_names[rx]);
+}
+
+static void out_AM_PCDisplacement(unsigned pc, int disp, int opsize, char *out)
+{
+ sprintf(out, "%X%s[PC]", pc+disp, opsize & 0x80 ? "@" : "");
+}
+
+static void out_AM_PCDisplacementIndexed(unsigned pc, int disp, int rx, int opsize, char *out)
+{
+ if(opsize & 0x80)
+ sprintf(out, "%s@%X[PC]", v60_reg_names[rx], pc+disp);
+ else
+ sprintf(out, "%X[PC](%s)", pc+disp, v60_reg_names[rx]);
+}
+
+static void out_AM_DisplacementIndirect(int reg, int disp, int opsize, char *out)
+{
+ sprintf(out, "%s[%s%X[%s]]",
+ opsize & 0x80 ? "@" : "",
+ disp >= 0 ? "" : "-", disp >= 0 ? disp : -disp,
+ v60_reg_names[reg]);
+}
+
+static void out_AM_DisplacementIndirectIndexed(int rn, int rx, int disp, int opsize, char *out)
+{
+ if(opsize & 0x80)
+ sprintf(out, "%s@[%s%X[%s]]", v60_reg_names[rx], disp >= 0 ? "" : "-", disp >= 0 ? disp : -disp,v60_reg_names[rn]);
+ else
+ sprintf(out, "[%s%X[%s]](%s)", disp >= 0 ? "" : "-", disp >= 0 ? disp : -disp,v60_reg_names[rn], v60_reg_names[rx]);
+}
+
+static void out_AM_PCDisplacementIndirect(unsigned pc, int disp, int opsize, char *out)
+{
+ sprintf(out, "%s[%X[PC]]", opsize & 0x80 ? "@" : "", pc+disp);
+}
+
+static void out_AM_PCDisplacementIndirectIndexed(unsigned pc, int disp, int rx, int opsize, char *out)
+{
+ if(opsize & 0x80)
+ sprintf(out, "%s@[%X[PC]]", v60_reg_names[rx], pc+disp);
+ else
+ sprintf(out, "[%X[PC]](%s)", pc+disp, v60_reg_names[rx]);
+}
+
+static void out_AM_DoubleDisplacement(int reg, int disp2, int disp1, int opsize, char *out)
+{
+ sprintf(out, "%s%X%s[%s%X[%s]]",
+ disp1 >= 0 ? "" : "-", disp1 >= 0 ? disp1 : -disp1,
+ opsize & 0x80 ? "@" : "",
+ disp2 >= 0 ? "" : "-", disp2 >= 0 ? disp2 : -disp2,
+ v60_reg_names[reg]);
+}
+
+static void out_AM_PCDoubleDisplacement(unsigned pc, int disp2, int disp1, int opsize, char *out)
+{
+ sprintf(out, "%s%X%s[%X[PC]]",
+ disp1 >= 0 ? "" : "-", disp1 >= 0 ? disp1 : -disp1,
+ opsize & 0x80 ? "@" : "",
+ disp2 + pc);
+}
+
+static void out_AM_DirectAddress(unsigned addr, int opsize, char *out)
+{
+ if(opsize & 0x80)
+ *out++ = '@';
+ sprintf(out, "%X", addr);
+}
+
+static void out_AM_DirectAddressIndexed(unsigned addr, int rx, int opsize, char *out)
+{
+ if(opsize & 0x80)
+ sprintf(out, "%s@%X", v60_reg_names[rx], addr);
+ else
+ sprintf(out, "%X(%s)", addr, v60_reg_names[rx]);
+}
+
+static void out_AM_DirectAddressDeferred(unsigned addr, int opsize, char *out)
+{
+ if(opsize & 0x80)
+ *out++ = '@';
+ sprintf(out, "[%X]", addr);
+}
+
+static void out_AM_DirectAddressDeferredIndexed(unsigned addr, int rx, int opsize, char *out)
+{
+ if(opsize & 0x80)
+ sprintf(out, "%s@[%X]", v60_reg_names[rx], addr);
+ else
+ sprintf(out, "[%X](%s)", addr, v60_reg_names[rx]);
+}
+
+static void out_AM_Immediate(unsigned value, int opsize, char *out)
+{
+ if(opsize == 0)
+ value &= 0xff;
+ else if(opsize == 1)
+ value &= 0xffff;
+
+ sprintf(out, "#%X", value);
+}
+
+static int decode_AM(unsigned ipc, unsigned pc, int m, int opsize, char *out)
+{
+ unsigned char mod = readop(pc);
+ if(m) {
+ switch(mod>>5) {
+ case 0: // Double displacement (8 bit)
+ out_AM_DoubleDisplacement(mod&0x1F, read8(pc+1), read8(pc+2), opsize, out);
+ return 3;
+
+ case 1: // Double displacement (16 bit)
+ out_AM_DoubleDisplacement(mod&0x1F, read16(pc+1), read16(pc+3), opsize, out);
+ return 5;
+
+ case 2: // Double displacement (32 bit)
+ out_AM_DoubleDisplacement(mod&0x1F, read32(pc+1), read32(pc+5), opsize, out);
+ return 9;
+
+ case 3: // Register
+ out_AM_Register(mod&0x1F, out);
+ return 1;
+
+ case 4: // Autoincrement
+ out_AM_Autoincrement(mod&0x1F, opsize, out);
+ return 1;
+
+ case 5: // Autodecrement
+ out_AM_Autodecrement(mod&0x1F, opsize, out);
+ return 1;
+
+ case 6:
+ switch (readop(pc+1)>>5)
+ {
+ case 0: // Displacement indexed (8 bit)
+ out_AM_DisplacementIndexed(readop(pc+1)&0x1F, mod&0x1F, read8(pc+2), opsize, out);
+ return 3;
+
+ case 1: // Displacement indexed (16 bit)
+ out_AM_DisplacementIndexed(readop(pc+1)&0x1F, mod&0x1F, read16(pc+2), opsize, out);
+ return 4;
+
+ case 2: // Displacement indexed (32 bit)
+ out_AM_DisplacementIndexed(readop(pc+1)&0x1F, mod&0x1F, read32(pc+2), opsize, out);
+ return 6;
+
+ case 3: // Register indirect indexed
+ out_AM_RegisterIndirectIndexed(readop(pc+1)&0x1F, mod&0x1F, opsize, out);
+ return 2;
+
+ case 4: // Displacement indirect indexed (8 bit)
+ out_AM_DisplacementIndirectIndexed(readop(pc+1)&0x1F, mod&0x1F, read8(pc+2), opsize, out);
+ return 3;
+
+ case 5: // Displacement indirect indexed (16 bit)
+ out_AM_DisplacementIndirectIndexed(readop(pc+1)&0x1F, mod&0x1F, read16(pc+2), opsize, out);
+ return 4;
+
+ case 6: // Displacement indirect indexed (32 bit)
+ out_AM_DisplacementIndirectIndexed(readop(pc+1)&0x1F, mod&0x1F, read32(pc+2), opsize, out);
+ return 6;
+
+ case 7:
+ switch (readop(pc+1)&0x1F)
+ {
+ case 16: // PC Displacement Indexed (8 bit)
+ out_AM_PCDisplacementIndexed(ipc, read8(pc+2), mod&0x1F, opsize, out);
+ return 3;
+
+ case 17: // PC Displacement Indexed (16 bit)
+ out_AM_PCDisplacementIndexed(ipc, read16(pc+2), mod&0x1F, opsize, out);
+ return 4;
+
+ case 18: // PC Displacement Indexed (32 bit)
+ out_AM_PCDisplacementIndexed(ipc, read32(pc+2), mod&0x1F, opsize, out);
+ return 6;
+
+ case 19: // Direct Address Indexed
+ out_AM_DirectAddressIndexed(read32(pc+2), mod&0x1F, opsize, out);
+ return 6;
+
+ case 24: // PC Displacement Indirect Indexed(8 bit)
+ out_AM_PCDisplacementIndirectIndexed(ipc, read8(pc+2), mod&0x1F, opsize, out);
+ return 3;
+
+ case 25: // PC Displacement Indirect Indexed (16 bit)
+ out_AM_PCDisplacementIndirectIndexed(ipc, read16(pc+2), mod&0x1F, opsize, out);
+ return 4;
+
+ case 26: // PC Displacement Indirect Indexed (32 bit)
+ out_AM_PCDisplacementIndirectIndexed(ipc, read32(pc+2), mod&0x1F, opsize, out);
+ return 6;
+
+ case 27: // Direct Address Deferred Indexed
+ out_AM_DirectAddressDeferredIndexed(read32(pc+2), mod&0x1F, opsize, out);
+ return 6;
+
+ default:
+ strcat(out, "!ERRAM3");
+ return 1;
+ }
+
+ default:
+ strcat(out, "!ERRAM2");
+ return 1;
+ }
+
+ default:
+ strcat(out, "!ERRAM1");
+ return 1;
+ }
+ } else {
+ switch(mod>>5) {
+ case 0: // Displacement (8 bit)
+ out_AM_Displacement(mod&0x1F, read8(pc+1), opsize, out);
+ return 2;
+
+ case 1: // Displacement (16 bit)
+ out_AM_Displacement(mod&0x1F, read16(pc+1), opsize, out);
+ return 3;
+
+ case 2: // Displacement (32 bit)
+ out_AM_Displacement(mod&0x1F, read32(pc+1), opsize, out);
+ return 5;
+
+ case 3: // Register indirect
+ out_AM_RegisterIndirect(mod&0x1F, opsize, out);
+ return 1;
+
+ case 4: // Displacement indirect (8 bit)
+ out_AM_DisplacementIndirect(mod&0x1F, read8(pc+1), opsize, out);
+ return 2;
+
+ case 5: // Displacement indirect (16 bit)
+ out_AM_DisplacementIndirect(mod&0x1F, read16(pc+1), opsize, out);
+ return 3;
+
+ case 6: // Displacement indirect (32 bit)
+ out_AM_DisplacementIndirect(mod&0x1F, read32(pc+1), opsize, out);
+ return 5;
+
+ case 7:
+ switch(mod&0x1F) {
+ 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:
+ out_AM_Immediate(mod&0x1F, opsize, out);
+ return 1;
+
+ case 16: // PC Displacement (8 bit)
+ out_AM_PCDisplacement(ipc, read8(pc+1), opsize, out);
+ return 2;
+
+ case 17: // PC Displacement (16 bit)
+ out_AM_PCDisplacement(ipc, read16(pc+1), opsize, out);
+ return 3;
+
+ case 18: // PC Displacement (32 bit)
+ out_AM_PCDisplacement(ipc, read32(pc+1), opsize, out);
+ return 5;
+
+ case 19: // Direct Address
+ out_AM_DirectAddress(read32(pc+1), opsize, out);
+ return 5;
+
+
+ case 20:
+ switch(opsize&0x7F) {
+ case 0: // Immediate (8 bit)
+ out_AM_Immediate(read8(pc+1), opsize, out);
+ return 2;
+
+ case 1: // Immediate (16 bit)
+ out_AM_Immediate(read16(pc+1), opsize, out);
+ return 3;
+
+ case 2: // Immediate (32 bit)
+ out_AM_Immediate(read32(pc+1), opsize, out);
+ return 5;
+
+ default:
+ strcat(out, "!ERRAM6");
+ return 1;
+ }
+
+ case 24: // PC Displacement Indirect (8 bit)
+ out_AM_PCDisplacementIndirect(ipc, read8(pc+1), opsize, out);
+ return 2;
+
+ case 25: // PC Displacement Indirect (16 bit)
+ out_AM_PCDisplacementIndirect(ipc, read16(pc+1), opsize, out);
+ return 3;
+
+ case 26: // PC Displacement Indirect (32 bit)
+ out_AM_PCDisplacementIndirect(ipc, read32(pc+1), opsize, out);
+ return 5;
+
+ case 27: // Direct Address Deferred
+ out_AM_DirectAddressDeferred(read32(pc+1), opsize, out);
+ return 5;
+
+ case 28: // PC Double Displacement (8 bit)
+ out_AM_PCDoubleDisplacement(ipc, read8(pc+1), read8(pc+2), opsize, out);
+ return 3;
+
+ case 29: // PC Double Displacement (16 bit)
+ out_AM_PCDoubleDisplacement(ipc, read16(pc+1), read16(pc+3), opsize, out);
+ return 5;
+
+ case 30: // PC Double Displacement (32 bit)
+ out_AM_PCDoubleDisplacement(ipc, read32(pc+1), read32(pc+5), opsize, out);
+ return 9;
+
+ default:
+ strcat(out, "!ERRAM5");
+ return 1;
+ }
+
+ default:
+ strcat(out, "!ERRAM4");
+ return 1;
+ }
+ }
+}
+
+
+static int decode_F1(const char *opnm, int opsize1, int opsize2, unsigned ipc, unsigned pc, char *out)
+{
+ unsigned char code = readop(pc);
+ sprintf(out, "%-8s", opnm);
+ if(code & 0x20) {
+ int ret = decode_AM(ipc, pc+1, code & 0x40, opsize1, out + strlen(out)) + 2;
+ strcat(out, ", ");
+ out_AM_Register(code & 0x1f, out + strlen(out));
+ return ret;
+ } else {
+ out_AM_Register(code & 0x1f, out + strlen(out));
+ strcat(out, ", ");
+ return decode_AM(ipc, pc+1, code & 0x40, opsize1, out + strlen(out)) + 2;
+ }
+}
+
+static int decode_F2(const char *opnm, int opsize1, int opsize2, unsigned ipc, unsigned pc, char *out)
+{
+ int ret;
+ unsigned char code = readop(pc);
+ sprintf(out, "%-8s", opnm);
+ ret = decode_AM(ipc, pc+1, code & 0x40, opsize1, out + strlen(out));
+ strcat(out, ", ");
+ ret += decode_AM(ipc, pc+1+ret, code & 0x20, opsize2, out + strlen(out));
+ return ret+2;
+}
+
+static int decode_F1F2(const char *opnm, int opsize1, int opsize2, unsigned ipc, unsigned pc, char *out)
+{
+ if(readop(pc) & 0x80)
+ return decode_F2(opnm, opsize1, opsize2, ipc, pc, out);
+ else
+ return decode_F1(opnm, opsize1, opsize2, ipc, pc, out);
+}
+
+static int decode_F3(const char *opnm, int opsize1, int opsize2, unsigned ipc, unsigned pc, char *out)
+{
+ sprintf(out, "%-8s", opnm);
+ return decode_AM(ipc, pc, readop(pc-1) & 1, opsize1, out + strlen(out)) + 1;
+}
+
+static int decode_F4a(const char *opnm, int opsize1, int opsize2, unsigned ipc, unsigned pc, char *out)
+{
+ sprintf(out, "%-8s%X", opnm, ipc+read8(pc));
+ return 2;
+}
+
+static int decode_F4b(const char *opnm, int opsize1, int opsize2, unsigned ipc, unsigned pc, char *out)
+{
+ sprintf(out, "%-8s%X", opnm, ipc+read16(pc));
+ return 3;
+}
+
+static int decode_F5(const char *opnm, int opsize1, int opsize2, unsigned ipc, unsigned pc, char *out)
+{
+ strcpy(out, opnm);
+ return 1;
+}
+
+static int decode_F6(const char *opnm, int opsize1, int opsize2, unsigned ipc, unsigned pc, char *out)
+{
+ sprintf(out, "%-8s%s, %X[PC]", opnm, v60_reg_names[readop(pc) & 0x1f], ipc+read16(pc+1));
+ return 4;
+}
+
+static int decode_F7a(const char *opnm, int opsize1, int opsize2, unsigned ipc, unsigned pc, char *out)
+{
+ int ret;
+ unsigned char code = readop(pc);
+ unsigned char code2;
+
+ sprintf(out, "%-8s", opnm);
+ ret = decode_AM(ipc, pc+1, code & 0x40, opsize1, out + strlen(out));
+ strcat(out, ", ");
+
+ code2 = readop(pc+1+ret);
+ if(code2 & 0x80)
+ out_AM_Register(code2 & 0x1f, out + strlen(out));
+ else
+ out_AM_Immediate(code2, 1, out + strlen(out));
+ strcat(out, ", ");
+
+ ret += decode_AM(ipc, pc+2+ret, code & 0x20, opsize2, out + strlen(out));
+ strcat(out, ", ");
+
+ code2 = readop(pc+2+ret);
+ if(code2 & 0x80)
+ out_AM_Register(code2 & 0x1f, out + strlen(out));
+ else
+ out_AM_Immediate(code2, 1, out + strlen(out));
+
+ return ret+4;
+}
+
+static int decode_F7b(const char *opnm, int opsize1, int opsize2, unsigned ipc, unsigned pc, char *out)
+{
+ int ret;
+ unsigned char code = readop(pc);
+ unsigned char code2;
+
+ sprintf(out, "%-8s", opnm);
+ ret = decode_AM(ipc, pc+1, code & 0x40, opsize1, out + strlen(out));
+ strcat(out, ", ");
+
+ code2 = readop(pc+1+ret);
+ if(code2 & 0x80)
+ out_AM_Register(code2 & 0x1f, out + strlen(out));
+ else
+ out_AM_Immediate(code2, 1, out + strlen(out));
+ strcat(out, ", ");
+
+ ret += decode_AM(ipc, pc+2+ret, code & 0x20, opsize2, out + strlen(out));
+
+ return ret+3;
+}
+
+static int decode_F7c(const char *opnm, int opsize1, int opsize2, unsigned ipc, unsigned pc, char *out)
+{
+ int ret;
+ unsigned char code = readop(pc);
+ unsigned char code2;
+
+ sprintf(out, "%-8s", opnm);
+ ret = decode_AM(ipc, pc+1, code & 0x40, opsize1, out + strlen(out));
+ strcat(out, ", ");
+
+ ret += decode_AM(ipc, pc+1+ret, code & 0x20, opsize2, out + strlen(out));
+ strcat(out, ", ");
+
+ code2 = readop(pc+1+ret);
+ if(code2 & 0x80)
+ out_AM_Register(code2 & 0x1f, out + strlen(out));
+ else
+ out_AM_Immediate(code2, 1, out + strlen(out));
+
+ return ret+3;
+}
+
+static int dopUNHANDLED(unsigned ipc, unsigned pc, char *out)
+{
+ sprintf(out, "$%02X", readop(pc));
+ return 1;
+}
+
+static int dop58UNHANDLED(unsigned ipc, unsigned pc, char *out)
+{
+ sprintf(out, "$58");
+ return 1;
+}
+
+static int dop59UNHANDLED(unsigned ipc, unsigned pc, char *out)
+{
+ sprintf(out, "$59");
+ return 1;
+}
+
+static int dop5AUNHANDLED(unsigned ipc, unsigned pc, char *out)
+{
+ sprintf(out, "$5A");
+ return 1;
+}
+
+static int dop5BUNHANDLED(unsigned ipc, unsigned pc, char *out)
+{
+ sprintf(out, "$5B");
+ return 1;
+}
+
+static int dop5CUNHANDLED(unsigned ipc, unsigned pc, char *out)
+{
+ sprintf(out, "$5C");
+ return 1;
+}
+
+static int dop5DUNHANDLED(unsigned ipc, unsigned pc, char *out)
+{
+ sprintf(out, "$5D");
+ return 1;
+}
+
+static int dop5EUNHANDLED(unsigned ipc, unsigned pc, char *out)
+{
+ sprintf(out, "$5E");
+ return 1;
+}
+
+static int dop5FUNHANDLED(unsigned ipc, unsigned pc, char *out)
+{
+ sprintf(out, "$5F");
+ return 1;
+}
+
+#define DEFINE_EASY_OPCODE(name, opnm, ftype, opsize1, opsize2) \
+ static int dop ## name(unsigned ipc, unsigned pc, char *out) \
+ { \
+ return decode_ ## ftype(opnm, opsize1, opsize2, ipc, pc, out); \
+ }
+
+#define DEFINE_EASY_OPCODE_EX(name, opnm, ftype, opsize1, opsize2, flags) \
+ static int dop ## name(unsigned ipc, unsigned pc, char *out) \
+ { \
+ return decode_ ## ftype(opnm, opsize1, opsize2, ipc, pc, out) | (flags); \
+ }
+
+#define DEFINE_TRIPLE_OPCODE(name, string, ftype) \
+ DEFINE_EASY_OPCODE(name##B,string ".b", ftype, 0, 0) \
+ DEFINE_EASY_OPCODE(name##H,string ".h", ftype, 1, 1) \
+ DEFINE_EASY_OPCODE(name##W,string ".w", ftype, 2, 2)
+
+#define DEFINE_DOUBLE_OPCODE(name, string, ftype) \
+ DEFINE_EASY_OPCODE(name##B,string ".b", ftype, 0, 0) \
+ DEFINE_EASY_OPCODE(name##H,string ".h", ftype, 1, 1)
+
+#define DEFINE_FPU_OPCODE(name,string,ftype) \
+ DEFINE_EASY_OPCODE(name##S,string ".s", ftype, 2, 2) \
+ DEFINE_EASY_OPCODE(name##L,string ".l", ftype, 2, 2)
+
+
+DEFINE_FPU_OPCODE(ABSF, "absf", F2)
+DEFINE_TRIPLE_OPCODE(ADD, "add", F1F2)
+DEFINE_TRIPLE_OPCODE(ADDC, "addc", F1F2)
+DEFINE_EASY_OPCODE(ADDDC, "adddc", F7c, 0, 0)
+DEFINE_FPU_OPCODE(ADDF, "addf", F2)
+DEFINE_TRIPLE_OPCODE(AND, "and", F1F2)
+DEFINE_EASY_OPCODE(ANDBSU, "andbsu", F7b, 0x80, 0x80)
+DEFINE_EASY_OPCODE(ANDBSD, "andbsd", F7b, 0x80, 0x80)
+DEFINE_EASY_OPCODE(ANDNBSU, "andnbsu", F7b, 0x80, 0x80)
+DEFINE_EASY_OPCODE(ANDNBSD, "andnbsd", F7b, 0x80, 0x80)
+DEFINE_EASY_OPCODE(BGT8, "bgt", F4a, 0, 0)
+DEFINE_EASY_OPCODE(BGT16, "bgt", F4b, 0, 0)
+DEFINE_EASY_OPCODE(BGE8, "bge", F4a, 0, 0)
+DEFINE_EASY_OPCODE(BGE16, "bge", F4b, 0, 0)
+DEFINE_EASY_OPCODE(BLT8, "blt", F4a, 0, 0)
+DEFINE_EASY_OPCODE(BLT16, "blt", F4b, 0, 0)
+DEFINE_EASY_OPCODE(BLE8, "ble", F4a, 0, 0)
+DEFINE_EASY_OPCODE(BLE16, "ble", F4b, 0, 0)
+DEFINE_EASY_OPCODE(BH8, "bh", F4a, 0, 0)
+DEFINE_EASY_OPCODE(BH16, "bh", F4b, 0, 0)
+DEFINE_EASY_OPCODE(BNL8, "bnl", F4a, 0, 0)
+DEFINE_EASY_OPCODE(BNL16, "bnl", F4b, 0, 0)
+DEFINE_EASY_OPCODE(BL8, "bl", F4a, 0, 0)
+DEFINE_EASY_OPCODE(BL16, "bl", F4b, 0, 0)
+DEFINE_EASY_OPCODE(BNH8, "bnh", F4a, 0, 0)
+DEFINE_EASY_OPCODE(BNH16, "bnh", F4b, 0, 0)
+DEFINE_EASY_OPCODE(BE8, "be", F4a, 0, 0)
+DEFINE_EASY_OPCODE(BE16, "be", F4b, 0, 0)
+DEFINE_EASY_OPCODE(BNE8, "bne", F4a, 0, 0)
+DEFINE_EASY_OPCODE(BNE16, "bne", F4b, 0, 0)
+DEFINE_EASY_OPCODE(BV8, "bv", F4a, 0, 0)
+DEFINE_EASY_OPCODE(BV16, "bv", F4b, 0, 0)
+DEFINE_EASY_OPCODE(BNV8, "bnv", F4a, 0, 0)
+DEFINE_EASY_OPCODE(BNV16, "bnv", F4b, 0, 0)
+DEFINE_EASY_OPCODE(BN8, "bn", F4a, 0, 0)
+DEFINE_EASY_OPCODE(BN16, "bn", F4b, 0, 0)
+DEFINE_EASY_OPCODE(BP8, "bp", F4a, 0, 0)
+DEFINE_EASY_OPCODE(BP16, "bp", F4b, 0, 0)
+DEFINE_EASY_OPCODE(BR8, "br", F4a, 0, 0)
+DEFINE_EASY_OPCODE(BR16, "br", F4b, 0, 0)
+DEFINE_EASY_OPCODE(BRK, "brk", F5, 0, 0)
+DEFINE_EASY_OPCODE(BRKV, "brkv", F5, 0, 0)
+DEFINE_EASY_OPCODE_EX(BSR, "bsr", F4b, 0, 0, DASMFLAG_STEP_OVER)
+DEFINE_EASY_OPCODE_EX(CALL, "call", F1F2, 0, 2, DASMFLAG_STEP_OVER)
+DEFINE_EASY_OPCODE(CAXI, "caxi", F1, 2, 2)
+DEFINE_EASY_OPCODE(CHKAR, "chkar", F1F2, 0, 0) // ?
+DEFINE_EASY_OPCODE(CHKAW, "chkaw", F1F2, 0, 0) // ?
+DEFINE_EASY_OPCODE(CHKAE, "chkae", F1F2, 0, 0)
+DEFINE_EASY_OPCODE(CHLVL, "chlvl", F1F2, 0, 0)
+DEFINE_EASY_OPCODE(CLR1, "clr1", F1F2, 2, 2)
+DEFINE_EASY_OPCODE(CLRTLB, "clrtlb", F3, 0, 0) // ?
+DEFINE_EASY_OPCODE(CLRTLBA, "clrtlba", F5, 0, 0)
+DEFINE_TRIPLE_OPCODE(CMP, "cmp", F1F2)
+DEFINE_EASY_OPCODE(CMPBFS, "cmpbfs", F7b, 0x82, 2)
+DEFINE_EASY_OPCODE(CMPBFZ, "cmpbfz", F7b, 0x82, 2)
+DEFINE_EASY_OPCODE(CMPBFL, "cmpbfl", F7b, 0x82, 2)
+DEFINE_DOUBLE_OPCODE(CMPC, "cmpc", F7a)
+DEFINE_DOUBLE_OPCODE(CMPCF, "cmpcf", F7a)
+DEFINE_DOUBLE_OPCODE(CMPCS, "cmpcs", F7a)
+DEFINE_FPU_OPCODE(CMPF, "cmpf", F2)
+DEFINE_EASY_OPCODE(CVTSL, "cvt.sl", F2, 0, 1)
+DEFINE_EASY_OPCODE(CVTLS, "cvt.ls", F2, 1, 0)
+DEFINE_EASY_OPCODE(CVTWS, "cvt.ws", F2, 2, 0)
+DEFINE_EASY_OPCODE(CVTWL, "cvt.wl", F2, 2, 1)
+DEFINE_EASY_OPCODE(CVTSW, "cvt.sw", F2, 0, 2)
+DEFINE_EASY_OPCODE(CVTLW, "cvt.lw", F2, 1, 2)
+DEFINE_EASY_OPCODE(CVTDPZ, "cvtd.pz", F7c, 0, 1)
+DEFINE_EASY_OPCODE(CVTDZP, "cvtd.zp", F7c, 1, 0)
+DEFINE_EASY_OPCODE_EX(DBGT, "dbgt", F6, 0, 0, DASMFLAG_STEP_OVER)
+DEFINE_EASY_OPCODE_EX(DBGE, "dbge", F6, 0, 0, DASMFLAG_STEP_OVER)
+DEFINE_EASY_OPCODE_EX(DBLT, "dbgt", F6, 0, 0, DASMFLAG_STEP_OVER)
+DEFINE_EASY_OPCODE_EX(DBLE, "dbge", F6, 0, 0, DASMFLAG_STEP_OVER)
+DEFINE_EASY_OPCODE_EX(DBH, "dbh", F6, 0, 0, DASMFLAG_STEP_OVER)
+DEFINE_EASY_OPCODE_EX(DBNL, "dbnl", F6, 0, 0, DASMFLAG_STEP_OVER)
+DEFINE_EASY_OPCODE_EX(DBL, "dbl", F6, 0, 0, DASMFLAG_STEP_OVER)
+DEFINE_EASY_OPCODE_EX(DBNH, "dbnh", F6, 0, 0, DASMFLAG_STEP_OVER)
+DEFINE_EASY_OPCODE_EX(DBE, "dbe", F6, 0, 0, DASMFLAG_STEP_OVER)
+DEFINE_EASY_OPCODE_EX(DBNE, "dbne", F6, 0, 0, DASMFLAG_STEP_OVER)
+DEFINE_EASY_OPCODE_EX(DBV, "dbe", F6, 0, 0, DASMFLAG_STEP_OVER)
+DEFINE_EASY_OPCODE_EX(DBNV, "dbne", F6, 0, 0, DASMFLAG_STEP_OVER)
+DEFINE_EASY_OPCODE_EX(DBN, "dbn", F6, 0, 0, DASMFLAG_STEP_OVER)
+DEFINE_EASY_OPCODE_EX(DBP, "dbp", F6, 0, 0, DASMFLAG_STEP_OVER)
+DEFINE_EASY_OPCODE_EX(DBR, "dbr", F6, 0, 0, DASMFLAG_STEP_OVER)
+DEFINE_TRIPLE_OPCODE(DEC, "dec", F3)
+DEFINE_EASY_OPCODE(DISPOSE, "dispose", F5, 0, 0)
+DEFINE_TRIPLE_OPCODE(DIV, "div", F1F2)
+DEFINE_FPU_OPCODE(DIVF, "divf", F2)
+DEFINE_TRIPLE_OPCODE(DIVU, "divu", F1F2)
+DEFINE_EASY_OPCODE(DIVX, "divx", F1F2, 2, 3)
+DEFINE_EASY_OPCODE(DIVUX, "divux", F1F2, 2, 3)
+DEFINE_EASY_OPCODE(EXTBFS, "extbfs", F7b, 0x82, 2)
+DEFINE_EASY_OPCODE(EXTBFZ, "extbfz", F7b, 0x82, 2)
+DEFINE_EASY_OPCODE(EXTBFL, "extbfl", F7b, 0x82, 2)
+DEFINE_EASY_OPCODE(GETATE, "getate", F1F2, 0, 3) // ?
+DEFINE_EASY_OPCODE(GETPSW, "getpsw", F3, 2, 0)
+DEFINE_EASY_OPCODE(GETPTE, "getpte", F1F2, 0, 2) // ?
+DEFINE_EASY_OPCODE(GETRA, "getra", F1F2, 0, 2) // ?
+DEFINE_EASY_OPCODE(HALT, "halt", F5, 0, 0)
+DEFINE_TRIPLE_OPCODE(IN, "in", F1F2)
+DEFINE_TRIPLE_OPCODE(INC, "inc", F3)
+DEFINE_EASY_OPCODE(INSBFL, "insbfl", F7c, 2, 0x82)
+DEFINE_EASY_OPCODE(INSBFR, "insbfr", F7c, 2, 0x82)
+DEFINE_EASY_OPCODE(JMP, "jmp", F3, 0, 0)
+DEFINE_EASY_OPCODE_EX(JSR, "jsr", F3, 0, 0, DASMFLAG_STEP_OVER)
+DEFINE_EASY_OPCODE(LDPR, "ldpr", F1F2, 2, 2)
+DEFINE_EASY_OPCODE(LDTASK, "ldtask", F1F2, 2, 2)
+DEFINE_TRIPLE_OPCODE(MOV, "mov", F1F2)
+DEFINE_EASY_OPCODE(MOVBSU, "movbsu", F7b, 0x80, 0x80)
+DEFINE_EASY_OPCODE(MOVBSD, "movbsd", F7b, 0x80, 0x80)
+DEFINE_DOUBLE_OPCODE(MOVCU, "movcu", F7a)
+DEFINE_DOUBLE_OPCODE(MOVCD, "movcd", F7a)
+DEFINE_DOUBLE_OPCODE(MOVCFU, "movcfu", F7a)
+DEFINE_DOUBLE_OPCODE(MOVCFD, "movcfd", F7a)
+DEFINE_DOUBLE_OPCODE(MOVCS, "movcs", F7a)
+DEFINE_EASY_OPCODE(MOVD, "mov.d", F1F2, 3, 3)
+DEFINE_EASY_OPCODE(MOVEAB, "movea.b", F1F2, 0, 2)
+DEFINE_EASY_OPCODE(MOVEAH, "movea.h", F1F2, 1, 2)
+DEFINE_EASY_OPCODE(MOVEAW, "movea.w", F1F2, 2, 2)
+DEFINE_FPU_OPCODE(MOVF, "movf", F2)
+DEFINE_EASY_OPCODE(MOVSBH, "movs.bh", F1F2, 0, 1)
+DEFINE_EASY_OPCODE(MOVSBW, "movs.bw", F1F2, 0, 2)
+DEFINE_EASY_OPCODE(MOVSHW, "movs.hw", F1F2, 1, 2)
+DEFINE_EASY_OPCODE(MOVTHB, "movt.hb", F1F2, 1, 0)
+DEFINE_EASY_OPCODE(MOVTWB, "movt.wb", F1F2, 2, 0)
+DEFINE_EASY_OPCODE(MOVTWH, "movt.wh", F1F2, 2, 1)
+DEFINE_EASY_OPCODE(MOVZBH, "movz.bh", F1F2, 0, 1)
+DEFINE_EASY_OPCODE(MOVZBW, "movz.bw", F1F2, 0, 2)
+DEFINE_EASY_OPCODE(MOVZHW, "movz.hw", F1F2, 1, 2)
+DEFINE_TRIPLE_OPCODE(MUL, "mul", F1F2)
+DEFINE_FPU_OPCODE(MULF, "mulf", F2)
+DEFINE_TRIPLE_OPCODE(MULU, "mulu", F1F2)
+DEFINE_EASY_OPCODE(MULX, "mulx", F1F2, 2, 3)
+DEFINE_EASY_OPCODE(MULUX, "mulux", F1F2, 2, 3)
+DEFINE_TRIPLE_OPCODE(NEG, "neg", F1F2)
+DEFINE_FPU_OPCODE(NEGF, "negf", F2)
+DEFINE_EASY_OPCODE(NOP, "nop", F5, 0, 0)
+DEFINE_TRIPLE_OPCODE(NOT, "not", F1F2)
+DEFINE_EASY_OPCODE(NOT1, "not1", F1F2, 2, 2)
+DEFINE_EASY_OPCODE(NOTBSU, "notbsu", F7b, 0x80, 0x80)
+DEFINE_EASY_OPCODE(NOTBSD, "notbsd", F7b, 0x80, 0x80)
+DEFINE_TRIPLE_OPCODE(OR, "or", F1F2)
+DEFINE_EASY_OPCODE(ORBSU, "orbsu", F7b, 0x80, 0x80)
+DEFINE_EASY_OPCODE(ORBSD, "orbsd", F7b, 0x80, 0x80)
+DEFINE_EASY_OPCODE(ORNBSU, "ornbsu", F7b, 0x80, 0x80)
+DEFINE_EASY_OPCODE(ORNBSD, "ornbsd", F7b, 0x80, 0x80)
+DEFINE_TRIPLE_OPCODE(OUT, "out", F1F2)
+DEFINE_EASY_OPCODE(POP, "pop", F3, 2, 0)
+DEFINE_EASY_OPCODE(POPM, "popm", F3, 2, 0)
+DEFINE_EASY_OPCODE(PREPARE, "prepare", F3, 2, 0)
+DEFINE_EASY_OPCODE(PUSH, "push", F3, 2, 0)
+DEFINE_EASY_OPCODE(PUSHM, "pushm", F3, 2, 0)
+DEFINE_TRIPLE_OPCODE(REM, "rem", F1F2)
+DEFINE_TRIPLE_OPCODE(REMU, "remu", F1F2)
+DEFINE_EASY_OPCODE_EX(RET, "ret", F3, 2, 0, DASMFLAG_STEP_OUT)
+DEFINE_EASY_OPCODE_EX(RETIU, "retiu", F3, 1, 0, DASMFLAG_STEP_OUT)
+DEFINE_EASY_OPCODE_EX(RETIS, "retis", F3, 1, 0, DASMFLAG_STEP_OUT)
+DEFINE_EASY_OPCODE(ROTB, "rot.b", F1F2, 0, 0)
+DEFINE_EASY_OPCODE(ROTH, "rot.h", F1F2, 0, 1)
+DEFINE_EASY_OPCODE(ROTW, "rot.w", F1F2, 0, 2)
+DEFINE_EASY_OPCODE(ROTCB, "rotc.b", F1F2, 0, 0)
+DEFINE_EASY_OPCODE(ROTCH, "rotc.h", F1F2, 0, 1)
+DEFINE_EASY_OPCODE(ROTCW, "rotc.w", F1F2, 0, 2)
+DEFINE_EASY_OPCODE_EX(RSR, "rsr", F5, 0, 0, DASMFLAG_STEP_OUT)
+DEFINE_EASY_OPCODE(RVBIT, "rvbit", F1F2, 0, 0)
+DEFINE_EASY_OPCODE(RVBYT, "rvbyt", F1F2, 2, 2)
+DEFINE_EASY_OPCODE(SCH0BSU, "sch0bsu", F7b, 0x80, 2)
+DEFINE_EASY_OPCODE(SCH0BSD, "sch0bsd", F7b, 0x80, 2)
+DEFINE_EASY_OPCODE(SCH1BSU, "sch1bsu", F7b, 0x80, 2)
+DEFINE_EASY_OPCODE(SCH1BSD, "sch1bsd", F7b, 0x80, 2)
+DEFINE_EASY_OPCODE(SCHCUB, "schcu.b", F7b, 0, 0)
+DEFINE_EASY_OPCODE(SCHCDB, "schcd.b", F7b, 0, 0)
+DEFINE_EASY_OPCODE(SCHCUH, "schcu.h", F7b, 1, 1)
+DEFINE_EASY_OPCODE(SCHCDH, "schcd.h", F7b, 1, 1)
+DEFINE_EASY_OPCODE(SCLFS, "sclf.s", F2, 1, 2)
+DEFINE_EASY_OPCODE(SCLFL, "sclf.l", F2, 1, 2)
+DEFINE_EASY_OPCODE(SET1, "set1", F1F2, 2, 2)
+DEFINE_EASY_OPCODE(SETF, "setf", F1F2, 0, 0)
+DEFINE_EASY_OPCODE(SHAB, "sha.b", F1F2, 0, 0)
+DEFINE_EASY_OPCODE(SHAH, "sha.h", F1F2, 0, 1)
+DEFINE_EASY_OPCODE(SHAW, "sha.w", F1F2, 0, 2)
+DEFINE_EASY_OPCODE(SHLB, "shl.b", F1F2, 0, 0)
+DEFINE_EASY_OPCODE(SHLH, "shl.h", F1F2, 0, 1)
+DEFINE_EASY_OPCODE(SHLW, "shl.w", F1F2, 0, 2)
+DEFINE_EASY_OPCODE(SKPCUB, "skpcu.b", F7b, 0, 0)
+DEFINE_EASY_OPCODE(SKPCDB, "skpcd.b", F7b, 0, 0)
+DEFINE_EASY_OPCODE(SKPCUH, "skpcu.h", F7b, 1, 1)
+DEFINE_EASY_OPCODE(SKPCDH, "skpcd.h", F7b, 1, 1)
+DEFINE_EASY_OPCODE(STPR, "stpr", F1F2, 2, 2)
+DEFINE_EASY_OPCODE(STTASK, "sttask", F3, 2, 0)
+DEFINE_TRIPLE_OPCODE(SUB, "sub", F1F2)
+DEFINE_TRIPLE_OPCODE(SUBC, "subc", F1F2)
+DEFINE_EASY_OPCODE(SUBDC, "subdc", F7c, 0, 0)
+DEFINE_EASY_OPCODE(SUBRDC, "subrdc", F7c, 0, 0)
+DEFINE_FPU_OPCODE(SUBF, "subf", F2)
+DEFINE_EASY_OPCODE(TASI, "tasi", F3, 0, 0)
+DEFINE_EASY_OPCODE(TB, "tb", F6, 0, 0)
+DEFINE_TRIPLE_OPCODE(TEST, "test", F3)
+DEFINE_EASY_OPCODE(TEST1, "test1", F1F2, 2, 2)
+DEFINE_EASY_OPCODE_EX(TRAP, "trap", F3, 0, 0, DASMFLAG_STEP_OVER)
+DEFINE_EASY_OPCODE(TRAPFL, "trapfl", F5, 0, 0)
+DEFINE_EASY_OPCODE(UPDATE, "update", F1F2, 0, 3) // ?
+DEFINE_EASY_OPCODE(UPDPSWH, "updpsw.h", F1F2, 2, 2)
+DEFINE_EASY_OPCODE(UPDPSWW, "updpsw.w", F1F2, 2, 2)
+DEFINE_EASY_OPCODE(UPDPTE, "updpte", F1F2, 0, 2) // ?
+DEFINE_TRIPLE_OPCODE(XCH, "xch", F1)
+DEFINE_TRIPLE_OPCODE(XOR, "xor", F1F2)
+DEFINE_EASY_OPCODE(XORBSU, "xorbsu", F7b, 0x80, 0x80)
+DEFINE_EASY_OPCODE(XORBSD, "xorbsd", F7b, 0x80, 0x80)
+DEFINE_EASY_OPCODE(XORNBSU, "xornbsu", F7b, 0x80, 0x80)
+DEFINE_EASY_OPCODE(XORNBSD, "xornbsd", F7b, 0x80, 0x80)
+
+static int (*const dasm_optable_58[32])(unsigned ipc, unsigned pc, char *out) =
+{
+ /* 0x00 */ dopCMPCB,
+ /* 0x01 */ dopCMPCFB,
+ /* 0x02 */ dopCMPCSB,
+ /* 0x03 */ dop58UNHANDLED,
+ /* 0x04 */ dop58UNHANDLED,
+ /* 0x05 */ dop58UNHANDLED,
+ /* 0x06 */ dop58UNHANDLED,
+ /* 0x07 */ dop58UNHANDLED,
+ /* 0x08 */ dopMOVCUB,
+ /* 0x09 */ dopMOVCDB,
+ /* 0x0A */ dopMOVCFUB,
+ /* 0x0B */ dopMOVCFDB,
+ /* 0x0C */ dopMOVCSB,
+ /* 0x0D */ dop58UNHANDLED,
+ /* 0x0E */ dop58UNHANDLED,
+ /* 0x0F */ dop58UNHANDLED,
+ /* 0x10 */ dop58UNHANDLED,
+ /* 0x11 */ dop58UNHANDLED,
+ /* 0x12 */ dop58UNHANDLED,
+ /* 0x13 */ dop58UNHANDLED,
+ /* 0x14 */ dop58UNHANDLED,
+ /* 0x15 */ dop58UNHANDLED,
+ /* 0x16 */ dop58UNHANDLED,
+ /* 0x17 */ dop58UNHANDLED,
+ /* 0x18 */ dopSCHCUB,
+ /* 0x19 */ dopSCHCDB,
+ /* 0x1A */ dopSKPCUB,
+ /* 0x1B */ dopSKPCDB,
+ /* 0x1C */ dop58UNHANDLED,
+ /* 0x1D */ dop58UNHANDLED,
+ /* 0x1E */ dop58UNHANDLED,
+ /* 0x1F */ dop58UNHANDLED
+};
+
+static int (*const dasm_optable_59[32])(unsigned ipc, unsigned pc, char *out) =
+{
+ /* 0x00 */ dopADDDC,
+ /* 0x01 */ dopSUBDC,
+ /* 0x02 */ dopSUBRDC,
+ /* 0x03 */ dop59UNHANDLED,
+ /* 0x04 */ dop59UNHANDLED,
+ /* 0x05 */ dop59UNHANDLED,
+ /* 0x06 */ dop59UNHANDLED,
+ /* 0x07 */ dop59UNHANDLED,
+ /* 0x08 */ dop59UNHANDLED,
+ /* 0x09 */ dop59UNHANDLED,
+ /* 0x0A */ dop59UNHANDLED,
+ /* 0x0B */ dop59UNHANDLED,
+ /* 0x0C */ dop59UNHANDLED,
+ /* 0x0D */ dop59UNHANDLED,
+ /* 0x0E */ dop59UNHANDLED,
+ /* 0x0F */ dop59UNHANDLED,
+ /* 0x10 */ dopCVTDPZ,
+ /* 0x11 */ dop59UNHANDLED,
+ /* 0x12 */ dop59UNHANDLED,
+ /* 0x13 */ dop59UNHANDLED,
+ /* 0x14 */ dop59UNHANDLED,
+ /* 0x15 */ dop59UNHANDLED,
+ /* 0x16 */ dop59UNHANDLED,
+ /* 0x17 */ dop59UNHANDLED,
+ /* 0x18 */ dopCVTDZP,
+ /* 0x19 */ dop59UNHANDLED,
+ /* 0x1A */ dop59UNHANDLED,
+ /* 0x1B */ dop59UNHANDLED,
+ /* 0x1C */ dop59UNHANDLED,
+ /* 0x1D */ dop59UNHANDLED,
+ /* 0x1E */ dop59UNHANDLED,
+ /* 0x1F */ dop59UNHANDLED
+};
+
+static int (*const dasm_optable_5A[32])(unsigned ipc, unsigned pc, char *out) =
+{
+ /* 0x00 */ dopCMPCH,
+ /* 0x01 */ dopCMPCFH,
+ /* 0x02 */ dopCMPCSH,
+ /* 0x03 */ dop5AUNHANDLED,
+ /* 0x04 */ dop5AUNHANDLED,
+ /* 0x05 */ dop5AUNHANDLED,
+ /* 0x06 */ dop5AUNHANDLED,
+ /* 0x07 */ dop5AUNHANDLED,
+ /* 0x08 */ dopMOVCUH,
+ /* 0x09 */ dopMOVCDH,
+ /* 0x0A */ dopMOVCFUH,
+ /* 0x0B */ dopMOVCFDH,
+ /* 0x0C */ dopMOVCSH,
+ /* 0x0D */ dop5AUNHANDLED,
+ /* 0x0E */ dop5AUNHANDLED,
+ /* 0x0F */ dop5AUNHANDLED,
+ /* 0x10 */ dop5AUNHANDLED,
+ /* 0x11 */ dop5AUNHANDLED,
+ /* 0x12 */ dop5AUNHANDLED,
+ /* 0x13 */ dop5AUNHANDLED,
+ /* 0x14 */ dop5AUNHANDLED,
+ /* 0x15 */ dop5AUNHANDLED,
+ /* 0x16 */ dop5AUNHANDLED,
+ /* 0x17 */ dop5AUNHANDLED,
+ /* 0x18 */ dopSCHCUH,
+ /* 0x19 */ dopSCHCDH,
+ /* 0x1A */ dopSKPCUH,
+ /* 0x1B */ dopSKPCDH,
+ /* 0x1C */ dop5AUNHANDLED,
+ /* 0x1D */ dop5AUNHANDLED,
+ /* 0x1E */ dop5AUNHANDLED,
+ /* 0x1F */ dop5AUNHANDLED
+};
+
+static int (*const dasm_optable_5B[32])(unsigned ipc, unsigned pc, char *out) =
+{
+ /* 0x00 */ dopSCH0BSU,
+ /* 0x01 */ dopSCH0BSD,
+ /* 0x02 */ dopSCH1BSU,
+ /* 0x03 */ dopSCH1BSD,
+ /* 0x04 */ dop5BUNHANDLED,
+ /* 0x05 */ dop5BUNHANDLED,
+ /* 0x06 */ dop5BUNHANDLED,
+ /* 0x07 */ dop5BUNHANDLED,
+ /* 0x08 */ dopMOVBSU,
+ /* 0x09 */ dopMOVBSD,
+ /* 0x0A */ dopNOTBSU,
+ /* 0x0B */ dopNOTBSD,
+ /* 0x0C */ dop5BUNHANDLED,
+ /* 0x0D */ dop5BUNHANDLED,
+ /* 0x0E */ dop5BUNHANDLED,
+ /* 0x0F */ dop5BUNHANDLED,
+ /* 0x10 */ dopANDBSU,
+ /* 0x11 */ dopANDBSD,
+ /* 0x12 */ dopANDNBSU,
+ /* 0x13 */ dopANDNBSD,
+ /* 0x14 */ dopORBSU,
+ /* 0x15 */ dopORBSD,
+ /* 0x16 */ dopORNBSU,
+ /* 0x17 */ dopORNBSD,
+ /* 0x18 */ dopXORBSU,
+ /* 0x19 */ dopXORBSD,
+ /* 0x1A */ dopXORNBSU,
+ /* 0x1B */ dopXORNBSD,
+ /* 0x1C */ dop5BUNHANDLED,
+ /* 0x1D */ dop5BUNHANDLED,
+ /* 0x1E */ dop5BUNHANDLED,
+ /* 0x1F */ dop5BUNHANDLED
+};
+
+static int (*const dasm_optable_5C[32])(unsigned ipc, unsigned pc, char *out) =
+{
+ /* 0x00 */ dopCMPFS,
+ /* 0x01 */ dop5CUNHANDLED,
+ /* 0x02 */ dop5CUNHANDLED,
+ /* 0x03 */ dop5CUNHANDLED,
+ /* 0x04 */ dop5CUNHANDLED,
+ /* 0x05 */ dop5CUNHANDLED,
+ /* 0x06 */ dop5CUNHANDLED,
+ /* 0x07 */ dop5CUNHANDLED,
+ /* 0x08 */ dopMOVFS,
+ /* 0x09 */ dopNEGFS,
+ /* 0x0A */ dopABSFS,
+ /* 0x0B */ dop5CUNHANDLED,
+ /* 0x0C */ dop5CUNHANDLED,
+ /* 0x0D */ dop5CUNHANDLED,
+ /* 0x0E */ dop5CUNHANDLED,
+ /* 0x0F */ dop5CUNHANDLED,
+ /* 0x10 */ dopSCLFS,
+ /* 0x11 */ dop5CUNHANDLED,
+ /* 0x12 */ dop5CUNHANDLED,
+ /* 0x13 */ dop5CUNHANDLED,
+ /* 0x14 */ dop5CUNHANDLED,
+ /* 0x15 */ dop5CUNHANDLED,
+ /* 0x16 */ dop5CUNHANDLED,
+ /* 0x17 */ dop5CUNHANDLED,
+ /* 0x18 */ dopADDFS,
+ /* 0x19 */ dopSUBFS,
+ /* 0x1A */ dopMULFS,
+ /* 0x1B */ dopDIVFS,
+ /* 0x1C */ dop5CUNHANDLED,
+ /* 0x1D */ dop5CUNHANDLED,
+ /* 0x1E */ dop5CUNHANDLED,
+ /* 0x1F */ dop5CUNHANDLED
+};
+
+static int (*const dasm_optable_5D[32])(unsigned ipc, unsigned pc, char *out) =
+{
+ /* 0x00 */ dopCMPBFS,
+ /* 0x01 */ dopCMPBFZ,
+ /* 0x02 */ dopCMPBFL,
+ /* 0x03 */ dop5DUNHANDLED,
+ /* 0x04 */ dop5DUNHANDLED,
+ /* 0x05 */ dop5DUNHANDLED,
+ /* 0x06 */ dop5DUNHANDLED,
+ /* 0x07 */ dop5DUNHANDLED,
+ /* 0x08 */ dopEXTBFS,
+ /* 0x09 */ dopEXTBFZ,
+ /* 0x0A */ dopEXTBFL,
+ /* 0x0B */ dop5DUNHANDLED,
+ /* 0x0C */ dop5DUNHANDLED,
+ /* 0x0D */ dop5DUNHANDLED,
+ /* 0x0E */ dop5DUNHANDLED,
+ /* 0x0F */ dop5DUNHANDLED,
+ /* 0x10 */ dop5DUNHANDLED,
+ /* 0x11 */ dop5DUNHANDLED,
+ /* 0x12 */ dop5DUNHANDLED,
+ /* 0x13 */ dop5DUNHANDLED,
+ /* 0x14 */ dop5DUNHANDLED,
+ /* 0x15 */ dop5DUNHANDLED,
+ /* 0x16 */ dop5DUNHANDLED,
+ /* 0x17 */ dop5DUNHANDLED,
+ /* 0x18 */ dopINSBFR,
+ /* 0x19 */ dopINSBFL,
+ /* 0x1A */ dop5DUNHANDLED,
+ /* 0x1B */ dop5DUNHANDLED,
+ /* 0x1C */ dop5DUNHANDLED,
+ /* 0x1D */ dop5DUNHANDLED,
+ /* 0x1E */ dop5DUNHANDLED,
+ /* 0x1F */ dop5DUNHANDLED
+};
+
+static int (*const dasm_optable_5E[32])(unsigned ipc, unsigned pc, char *out) =
+{
+ /* 0x00 */ dopCMPFL,
+ /* 0x01 */ dop5EUNHANDLED,
+ /* 0x02 */ dop5EUNHANDLED,
+ /* 0x03 */ dop5EUNHANDLED,
+ /* 0x04 */ dop5EUNHANDLED,
+ /* 0x05 */ dop5EUNHANDLED,
+ /* 0x06 */ dop5EUNHANDLED,
+ /* 0x07 */ dop5EUNHANDLED,
+ /* 0x08 */ dopMOVFL,
+ /* 0x09 */ dopNEGFL,
+ /* 0x0A */ dopABSFL,
+ /* 0x0B */ dop5EUNHANDLED,
+ /* 0x0C */ dop5EUNHANDLED,
+ /* 0x0D */ dop5EUNHANDLED,
+ /* 0x0E */ dop5EUNHANDLED,
+ /* 0x0F */ dop5EUNHANDLED,
+ /* 0x10 */ dopSCLFL,
+ /* 0x11 */ dop5EUNHANDLED,
+ /* 0x12 */ dop5EUNHANDLED,
+ /* 0x13 */ dop5EUNHANDLED,
+ /* 0x14 */ dop5EUNHANDLED,
+ /* 0x15 */ dop5EUNHANDLED,
+ /* 0x16 */ dop5EUNHANDLED,
+ /* 0x17 */ dop5EUNHANDLED,
+ /* 0x18 */ dopADDFL,
+ /* 0x19 */ dopSUBFL,
+ /* 0x1A */ dopMULFL,
+ /* 0x1B */ dopDIVFL,
+ /* 0x1C */ dop5EUNHANDLED,
+ /* 0x1D */ dop5EUNHANDLED,
+ /* 0x1E */ dop5EUNHANDLED,
+ /* 0x1F */ dop5EUNHANDLED
+};
+
+static int (*const dasm_optable_5F[32])(unsigned ipc, unsigned pc, char *out) =
+{
+ /* 0x00 */ dopCVTWS,
+ /* 0x01 */ dopCVTSW,
+ /* 0x02 */ dop5FUNHANDLED,
+ /* 0x03 */ dop5FUNHANDLED,
+ /* 0x04 */ dop5FUNHANDLED,
+ /* 0x05 */ dop5FUNHANDLED,
+ /* 0x06 */ dop5FUNHANDLED,
+ /* 0x07 */ dop5FUNHANDLED,
+ /* 0x08 */ dopCVTLS,
+ /* 0x09 */ dopCVTLW,
+ /* 0x0A */ dop5FUNHANDLED,
+ /* 0x0B */ dop5FUNHANDLED,
+ /* 0x0C */ dop5FUNHANDLED,
+ /* 0x0D */ dop5FUNHANDLED,
+ /* 0x0E */ dop5FUNHANDLED,
+ /* 0x0F */ dop5FUNHANDLED,
+ /* 0x10 */ dopCVTSL,
+ /* 0x11 */ dopCVTWL,
+ /* 0x12 */ dop5FUNHANDLED,
+ /* 0x13 */ dop5FUNHANDLED,
+ /* 0x14 */ dop5FUNHANDLED,
+ /* 0x15 */ dop5FUNHANDLED,
+ /* 0x16 */ dop5FUNHANDLED,
+ /* 0x17 */ dop5FUNHANDLED,
+ /* 0x18 */ dop5FUNHANDLED,
+ /* 0x19 */ dop5FUNHANDLED,
+ /* 0x1A */ dop5FUNHANDLED,
+ /* 0x1B */ dop5FUNHANDLED,
+ /* 0x1C */ dop5FUNHANDLED,
+ /* 0x1D */ dop5FUNHANDLED,
+ /* 0x1E */ dop5FUNHANDLED,
+ /* 0x1F */ dop5FUNHANDLED
+};
+
+static int (*const dasm_optable_C6[8])(unsigned ipc, unsigned pc, char *out) =
+{
+ /* 0x0 */ dopDBV,
+ /* 0x1 */ dopDBL,
+ /* 0x2 */ dopDBE,
+ /* 0x3 */ dopDBNH,
+ /* 0x4 */ dopDBN,
+ /* 0x5 */ dopDBR,
+ /* 0x6 */ dopDBLT,
+ /* 0x7 */ dopDBLE
+};
+
+static int (*const dasm_optable_C7[8])(unsigned ipc, unsigned pc, char *out) =
+{
+ /* 0x0 */ dopDBNV,
+ /* 0x1 */ dopDBNL,
+ /* 0x2 */ dopDBNE,
+ /* 0x3 */ dopDBH,
+ /* 0x4 */ dopDBP,
+ /* 0x5 */ dopTB,
+ /* 0x6 */ dopDBGE,
+ /* 0x7 */ dopDBGT
+};
+
+static int dop58(unsigned ipc, unsigned pc, char *out)
+{
+ return dasm_optable_58[readop(pc) & 0x1f](ipc, pc, out);
+}
+
+static int dop59(unsigned ipc, unsigned pc, char *out)
+{
+ return dasm_optable_59[readop(pc) & 0x1f](ipc, pc, out);
+}
+
+static int dop5A(unsigned ipc, unsigned pc, char *out)
+{
+ return dasm_optable_5A[readop(pc) & 0x1f](ipc, pc, out);
+}
+
+static int dop5B(unsigned ipc, unsigned pc, char *out)
+{
+ return dasm_optable_5B[readop(pc) & 0x1f](ipc, pc, out);
+}
+
+static int dop5C(unsigned ipc, unsigned pc, char *out)
+{
+ return dasm_optable_5C[readop(pc) & 0x1f](ipc, pc, out);
+}
+
+static int dop5D(unsigned ipc, unsigned pc, char *out)
+{
+ return dasm_optable_5D[readop(pc) & 0x1f](ipc, pc, out);
+}
+
+static int dop5E(unsigned ipc, unsigned pc, char *out)
+{
+ return dasm_optable_5E[readop(pc) & 0x1f](ipc, pc, out);
+}
+
+static int dop5F(unsigned ipc, unsigned pc, char *out)
+{
+ return dasm_optable_5F[readop(pc) & 0x1f](ipc, pc, out);
+}
+
+static int dopC6(unsigned ipc, unsigned pc, char *out)
+{
+ return dasm_optable_C6[readop(pc) >> 5](ipc, pc, out);
+}
+
+static int dopC7(unsigned ipc, unsigned pc, char *out)
+{
+ return dasm_optable_C7[readop(pc) >> 5](ipc, pc, out);
+}
+
+static int (*const dasm_optable[256])(unsigned ipc, unsigned pc, char *out) =
+{
+ /* 0x00 */ dopHALT,
+ /* 0x01 */ dopLDTASK,
+ /* 0x02 */ dopSTPR,
+ /* 0x03 */ dopGETRA,
+ /* 0x04 */ dopGETPTE,
+ /* 0x05 */ dopGETATE,
+ /* 0x06 */ dopUNHANDLED,
+ /* 0x07 */ dopUNHANDLED,
+ /* 0x08 */ dopRVBIT,
+ /* 0x09 */ dopMOVB,
+ /* 0x0A */ dopMOVSBH,
+ /* 0x0B */ dopMOVZBH,
+ /* 0x0C */ dopMOVSBW,
+ /* 0x0D */ dopMOVZBW,
+ /* 0x0E */ dopUNHANDLED,
+ /* 0x0F */ dopUNHANDLED,
+ /* 0x10 */ dopCLRTLBA,
+ /* 0x11 */ dopUNHANDLED,
+ /* 0x12 */ dopLDPR,
+ /* 0x13 */ dopUPDPSWW,
+ /* 0x14 */ dopUPDPTE,
+ /* 0x15 */ dopUPDATE,
+ /* 0x16 */ dopUNHANDLED,
+ /* 0x17 */ dopUNHANDLED,
+ /* 0x18 */ dopUNHANDLED,
+ /* 0x19 */ dopMOVTHB,
+ /* 0x1A */ dopUNHANDLED,
+ /* 0x1B */ dopMOVH,
+ /* 0x1C */ dopMOVSHW,
+ /* 0x1D */ dopMOVZHW,
+ /* 0x1E */ dopUNHANDLED,
+ /* 0x1F */ dopUNHANDLED,
+ /* 0x20 */ dopINB,
+ /* 0x21 */ dopOUTB,
+ /* 0x22 */ dopINH,
+ /* 0x23 */ dopOUTH,
+ /* 0x24 */ dopINW,
+ /* 0x25 */ dopOUTW,
+ /* 0x26 */ dopUNHANDLED,
+ /* 0x27 */ dopUNHANDLED,
+ /* 0x28 */ dopUNHANDLED,
+ /* 0x29 */ dopMOVTWB,
+ /* 0x2A */ dopUNHANDLED,
+ /* 0x2B */ dopMOVTWH,
+ /* 0x2C */ dopRVBYT,
+ /* 0x2D */ dopMOVW,
+ /* 0x2E */ dopUNHANDLED,
+ /* 0x2F */ dopUNHANDLED,
+ /* 0x30 */ dopUNHANDLED,
+ /* 0x31 */ dopUNHANDLED,
+ /* 0x32 */ dopUNHANDLED,
+ /* 0x33 */ dopUNHANDLED,
+ /* 0x34 */ dopUNHANDLED,
+ /* 0x35 */ dopUNHANDLED,
+ /* 0x36 */ dopUNHANDLED,
+ /* 0x37 */ dopUNHANDLED,
+ /* 0x38 */ dopNOTB,
+ /* 0x39 */ dopNEGB,
+ /* 0x3A */ dopNOTH,
+ /* 0x3B */ dopNEGH,
+ /* 0x3C */ dopNOTW,
+ /* 0x3D */ dopNEGW,
+ /* 0x3E */ dopUNHANDLED,
+ /* 0x3F */ dopMOVD,
+ /* 0x40 */ dopMOVEAB,
+ /* 0x41 */ dopXCHB,
+ /* 0x42 */ dopMOVEAH,
+ /* 0x43 */ dopXCHH,
+ /* 0x44 */ dopMOVEAW,
+ /* 0x45 */ dopXCHW,
+ /* 0x46 */ dopUNHANDLED,
+ /* 0x47 */ dopSETF,
+ /* 0x48 */ dopBSR,
+ /* 0x49 */ dopCALL,
+ /* 0x4A */ dopUPDPSWH,
+ /* 0x4B */ dopCHLVL,
+ /* 0x4C */ dopCAXI,
+ /* 0x4D */ dopCHKAR,
+ /* 0x4E */ dopCHKAW,
+ /* 0x4F */ dopCHKAE,
+ /* 0x50 */ dopREMB,
+ /* 0x51 */ dopREMUB,
+ /* 0x52 */ dopREMH,
+ /* 0x53 */ dopREMUH,
+ /* 0x54 */ dopREMW,
+ /* 0x55 */ dopREMUW,
+ /* 0x56 */ dopUNHANDLED,
+ /* 0x57 */ dopUNHANDLED,
+ /* 0x58 */ dop58,
+ /* 0x59 */ dop59,
+ /* 0x5A */ dop5A,
+ /* 0x5B */ dop5B,
+ /* 0x5C */ dop5C,
+ /* 0x5D */ dop5D,
+ /* 0x5E */ dop5E,
+ /* 0x5F */ dop5F,
+ /* 0x60 */ dopBV8,
+ /* 0x61 */ dopBNV8,
+ /* 0x62 */ dopBL8,
+ /* 0x63 */ dopBNL8,
+ /* 0x64 */ dopBE8,
+ /* 0x65 */ dopBNE8,
+ /* 0x66 */ dopBNH8,
+ /* 0x67 */ dopBH8,
+ /* 0x68 */ dopBN8,
+ /* 0x69 */ dopBP8,
+ /* 0x6A */ dopBR8,
+ /* 0x6B */ dopUNHANDLED,
+ /* 0x6C */ dopBLT8,
+ /* 0x6D */ dopBGE8,
+ /* 0x6E */ dopBLE8,
+ /* 0x6F */ dopBGT8,
+ /* 0x70 */ dopBV16,
+ /* 0x71 */ dopBNV16,
+ /* 0x72 */ dopBL16,
+ /* 0x73 */ dopBNL16,
+ /* 0x74 */ dopBE16,
+ /* 0x75 */ dopBNE16,
+ /* 0x76 */ dopBNH16,
+ /* 0x77 */ dopBH16,
+ /* 0x78 */ dopBN16,
+ /* 0x79 */ dopBP16,
+ /* 0x7A */ dopBR16,
+ /* 0x7B */ dopUNHANDLED,
+ /* 0x7C */ dopBLT16,
+ /* 0x7D */ dopBGE16,
+ /* 0x7E */ dopBLE16,
+ /* 0x7F */ dopBGT16,
+ /* 0x80 */ dopADDB,
+ /* 0x81 */ dopMULB,
+ /* 0x82 */ dopADDH,
+ /* 0x83 */ dopMULH,
+ /* 0x84 */ dopADDW,
+ /* 0x85 */ dopMULW,
+ /* 0x86 */ dopMULX,
+ /* 0x87 */ dopTEST1,
+ /* 0x88 */ dopORB,
+ /* 0x89 */ dopROTB,
+ /* 0x8A */ dopORH,
+ /* 0x8B */ dopROTH,
+ /* 0x8C */ dopORW,
+ /* 0x8D */ dopROTW,
+ /* 0x8E */ dopUNHANDLED,
+ /* 0x8F */ dopUNHANDLED,
+ /* 0x90 */ dopADDCB,
+ /* 0x91 */ dopMULUB,
+ /* 0x92 */ dopADDCH,
+ /* 0x93 */ dopMULUH,
+ /* 0x94 */ dopADDCW,
+ /* 0x95 */ dopMULUW,
+ /* 0x96 */ dopMULUX,
+ /* 0x97 */ dopSET1,
+ /* 0x98 */ dopSUBCB,
+ /* 0x99 */ dopROTCB,
+ /* 0x9A */ dopSUBCH,
+ /* 0x9B */ dopROTCH,
+ /* 0x9C */ dopSUBCW,
+ /* 0x9D */ dopROTCW,
+ /* 0x9E */ dopUNHANDLED,
+ /* 0x9F */ dopUNHANDLED,
+ /* 0xA0 */ dopANDB,
+ /* 0xA1 */ dopDIVB,
+ /* 0xA2 */ dopANDH,
+ /* 0xA3 */ dopDIVH,
+ /* 0xA4 */ dopANDW,
+ /* 0xA5 */ dopDIVW,
+ /* 0xA6 */ dopDIVX,
+ /* 0xA7 */ dopCLR1,
+ /* 0xA8 */ dopSUBB,
+ /* 0xA9 */ dopSHLB,
+ /* 0xAA */ dopSUBH,
+ /* 0xAB */ dopSHLH,
+ /* 0xAC */ dopSUBW,
+ /* 0xAD */ dopSHLW,
+ /* 0xAE */ dopUNHANDLED,
+ /* 0xAF */ dopUNHANDLED,
+ /* 0xB0 */ dopXORB,
+ /* 0xB1 */ dopDIVUB,
+ /* 0xB2 */ dopXORH,
+ /* 0xB3 */ dopDIVUH,
+ /* 0xB4 */ dopXORW,
+ /* 0xB5 */ dopDIVUW,
+ /* 0xB6 */ dopDIVUX,
+ /* 0xB7 */ dopNOT1,
+ /* 0xB8 */ dopCMPB,
+ /* 0xB9 */ dopSHAB,
+ /* 0xBA */ dopCMPH,
+ /* 0xBB */ dopSHAH,
+ /* 0xBC */ dopCMPW,
+ /* 0xBD */ dopSHAW,
+ /* 0xBE */ dopUNHANDLED,
+ /* 0xBF */ dopUNHANDLED,
+ /* 0xC0 */ dopUNHANDLED,
+ /* 0xC1 */ dopUNHANDLED,
+ /* 0xC2 */ dopUNHANDLED,
+ /* 0xC3 */ dopUNHANDLED,
+ /* 0xC4 */ dopUNHANDLED,
+ /* 0xC5 */ dopUNHANDLED,
+ /* 0xC6 */ dopC6,
+ /* 0xC7 */ dopC7,
+ /* 0xC8 */ dopBRK,
+ /* 0xC9 */ dopBRKV,
+ /* 0xCA */ dopRSR,
+ /* 0xCB */ dopTRAPFL,
+ /* 0xCC */ dopDISPOSE,
+ /* 0xCD */ dopNOP,
+ /* 0xCE */ dopUNHANDLED,
+ /* 0xCF */ dopUNHANDLED,
+ /* 0xD0 */ dopDECB,
+ /* 0xD1 */ dopDECB,
+ /* 0xD2 */ dopDECH,
+ /* 0xD3 */ dopDECH,
+ /* 0xD4 */ dopDECW,
+ /* 0xD5 */ dopDECW,
+ /* 0xD6 */ dopJMP,
+ /* 0xD7 */ dopJMP,
+ /* 0xD8 */ dopINCB,
+ /* 0xD9 */ dopINCB,
+ /* 0xDA */ dopINCH,
+ /* 0xDB */ dopINCH,
+ /* 0xDC */ dopINCW,
+ /* 0xDD */ dopINCW,
+ /* 0xDE */ dopPREPARE,
+ /* 0xDF */ dopPREPARE,
+ /* 0xE0 */ dopTASI,
+ /* 0xE1 */ dopTASI,
+ /* 0xE2 */ dopRET,
+ /* 0xE3 */ dopRET,
+ /* 0xE4 */ dopPOPM,
+ /* 0xE5 */ dopPOPM,
+ /* 0xE6 */ dopPOP,
+ /* 0xE7 */ dopPOP,
+ /* 0xE8 */ dopJSR,
+ /* 0xE9 */ dopJSR,
+ /* 0xEA */ dopRETIU,
+ /* 0xEB */ dopRETIU,
+ /* 0xEC */ dopPUSHM,
+ /* 0xED */ dopPUSHM,
+ /* 0xEE */ dopPUSH,
+ /* 0xEF */ dopPUSH,
+ /* 0xF0 */ dopTESTB,
+ /* 0xF1 */ dopTESTB,
+ /* 0xF2 */ dopTESTH,
+ /* 0xF3 */ dopTESTH,
+ /* 0xF4 */ dopTESTW,
+ /* 0xF5 */ dopTESTW,
+ /* 0xF6 */ dopGETPSW,
+ /* 0xF7 */ dopGETPSW,
+ /* 0xF8 */ dopTRAP,
+ /* 0xF9 */ dopTRAP,
+ /* 0xFA */ dopRETIS,
+ /* 0xFB */ dopRETIS,
+ /* 0xFC */ dopSTTASK,
+ /* 0xFD */ dopSTTASK,
+ /* 0xFE */ dopCLRTLB,
+ /* 0xFF */ dopCLRTLB
+};
+
+CPU_DISASSEMBLE( v60 )
+{
+ rombase = oprom;
+ pcbase = pc;
+ return dasm_optable[oprom[0]](pc, pc+1, buffer) | DASMFLAG_SUPPORTED;
+}
+
+CPU_DISASSEMBLE( v70 )
+{
+ rombase = oprom;
+ pcbase = pc;
+ return dasm_optable[oprom[0]](pc, pc+1, buffer) | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/v810/v810.c b/trunk/src/emu/cpu/v810/v810.c
new file mode 100644
index 00000000000..06ad6c4b7b6
--- /dev/null
+++ b/trunk/src/emu/cpu/v810/v810.c
@@ -0,0 +1,1354 @@
+/********************************************
+ NEC V810 (upd70732) core
+ Tomasz Slanina - analog[at]op.pl
+
+ Change Log
+ - 20/07/2004 - first public release
+
+
+ TODO:
+ - CY flag in few floating point opcodes
+ (all floating point opcodes are NOT tested!)
+ - traps/interrupts/exceptions
+ - bitstring opcodes
+ - timing
+ - missing opcodes : reti , trap
+
+********************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "v810.h"
+
+#define clkIF 3
+#define clkMEM 3
+
+typedef struct _v810_state v810_state;
+struct _v810_state
+{
+ UINT32 reg[65];
+ UINT8 irq_line;
+ UINT8 irq_state;
+ UINT8 nmi_line;
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *io;
+ UINT32 PPC;
+ int icount;
+};
+
+INLINE v810_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == V810);
+ return (v810_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+#define R0 reg[0]
+#define R1 reg[1]
+#define R2 reg[2]
+#define SP reg[3]
+#define R4 reg[4]
+#define R5 reg[5]
+#define R6 reg[6]
+#define R7 reg[7]
+#define R8 reg[8]
+#define R9 reg[9]
+#define R10 reg[10]
+#define R11 reg[11]
+#define R12 reg[12]
+#define R13 reg[13]
+#define R14 reg[14]
+#define R15 reg[15]
+#define R16 reg[16]
+#define R17 reg[17]
+#define R18 reg[18]
+#define R19 reg[19]
+#define R20 reg[20]
+#define R21 reg[21]
+#define R22 reg[22]
+#define R23 reg[23]
+#define R24 reg[24]
+#define R25 reg[25]
+#define R26 reg[26]
+#define R27 reg[27]
+#define R28 reg[28]
+#define R29 reg[29]
+#define R30 reg[30]
+#define R31 reg[31]
+
+#define EIPC reg[32]
+#define EIPSW reg[33]
+#define FEPC reg[34]
+#define FEPSW reg[35]
+#define ECR reg[36]
+#define PSW reg[37]
+#define PIR reg[38]
+#define TKCW reg[39]
+#define CHCW reg[56]
+#define ADTRE reg[57]
+
+#define PC reg[64]
+
+/* Flags */
+#define GET_Z ( cpustate->PSW & 0x00000001)
+#define GET_S ((cpustate->PSW & 0x00000002)>>1)
+#define GET_OV ((cpustate->PSW & 0x00000004)>>2)
+#define GET_CY ((cpustate->PSW & 0x00000008)>>3)
+#define GET_ID ((cpustate->PSW & 0x00001000)>>12)
+#define GET_AE ((cpustate->PSW & 0x00002000)>>13)
+#define GET_EP ((cpustate->PSW & 0x00004000)>>14)
+#define GET_NP ((cpustate->PSW & 0x00008000)>>15)
+
+#define SET_Z(val) (cpustate->PSW = (cpustate->PSW & ~0x00000001) | (val))
+#define SET_S(val) (cpustate->PSW = (cpustate->PSW & ~0x00000002) | ((val) << 1))
+#define SET_OV(val) (cpustate->PSW = (cpustate->PSW & ~0x00000004) | ((val) << 2))
+#define SET_CY(val) (cpustate->PSW = (cpustate->PSW & ~0x00000008) | ((val) << 3))
+#define SET_ID(val) (cpustate->PSW = (cpustate->PSW & ~0x00001000) | ((val) << 12))
+#define SET_AE(val) (cpustate->PSW = (cpustate->PSW & ~0x00002000) | ((val) << 13))
+#define SET_EP(val) (cpustate->PSW = (cpustate->PSW & ~0x00004000) | ((val) << 14))
+#define SET_NP(val) (cpustate->PSW = (cpustate->PSW & ~0x00008000) | ((val) << 15))
+
+#define R_B(cs, addr) ((cs)->program->read_byte(addr))
+#define R_H(cs, addr) ((cs)->program->read_word(addr))
+#define R_W(cs, addr) ((cs)->program->read_dword(addr))
+
+
+#define W_B(cs, addr, val) ((cs)->program->write_byte(addr,val))
+#define W_H(cs, addr, val) ((cs)->program->write_word(addr,val))
+#define W_W(cs, addr, val) ((cs)->program->write_dword(addr,val))
+
+
+#define RIO_B(cs, addr) ((cs)->io->read_byte(addr))
+#define RIO_H(cs, addr) ((cs)->io->read_word(addr))
+#define RIO_W(cs, addr) ((cs)->io->read_dword(addr))
+
+
+#define WIO_B(cs, addr, val) ((cs)->io->write_byte(addr,val))
+#define WIO_H(cs, addr, val) ((cs)->io->write_word(addr,val))
+#define WIO_W(cs, addr, val) ((cs)->io->write_dword(addr,val))
+
+#define R_OP(cs, addr) ((cs)->direct->read_decrypted_word(addr))
+
+#define GET1 (op&0x1f)
+#define GET2 ((op>>5)&0x1f)
+#define I5(x) (((x)&0x1f)|(((x)&0x10)?0xffffffe0:0))
+#define UI5(x) ((x)&0x1f)
+#define I16(x) (((x)&0xffff)|(((x)&0x8000)?0xffff0000:0))
+#define UI16(x) ((x)&0xffff)
+#define D16(x) (((x)&0xffff)|(((x)&0x8000)?0xffff0000:0))
+#define D26(x,y) ((y)|((x&0x3ff)<<16 )|((x&0x200)?0xfc000000:0))
+#define D9(x) ((x&0x1ff)|((x&0x100)?0xfffffe00:0))
+#define SO(opcode) (((opcode)&0xfc00)>>10)
+
+#define CHECK_CY(x) cpustate->PSW=(cpustate->PSW & ~8)|(((x) & (((UINT64)1) << 32)) ? 8 : 0)
+#define CHECK_OVADD(x,y,z) cpustate->PSW=(cpustate->PSW & ~0x00000004) |(( ((x) ^ (z)) & ((y) ^ (z)) & 0x80000000) ? 4: 0)
+#define CHECK_OVSUB(x,y,z) cpustate->PSW=(cpustate->PSW & ~0x00000004) |(( ((y) ^ (z)) & ((x) ^ (y)) & 0x80000000) ? 4: 0)
+#define CHECK_ZS(x) cpustate->PSW=(cpustate->PSW & ~3)|((UINT32)(x)==0)|(((x)&0x80000000) ? 2: 0)
+
+
+#define ADD(dst, src) { UINT64 res=(UINT64)(dst)+(UINT64)(src); SetCF(res); SetOF_Add(res,src,dst); SetSZPF(res); dst=(UINT32)res; }
+#define SUB(dst, src) { UINT64 res=(UINT64)(dst)-(INT64)(src); SetCF(res); SetOF_Sub(res,src,dst); SetSZPF(res); dst=(UINT32)res; }
+
+
+
+
+static void SETREG(v810_state *cpustate,UINT32 reg,UINT32 val)
+{
+ if(reg)
+ cpustate->reg[reg]=val;
+}
+
+static UINT32 GETREG(v810_state *cpustate,UINT32 reg)
+{
+ if(reg)
+ return cpustate->reg[reg];
+ else
+ return 0;
+}
+
+static UINT32 opUNDEF(v810_state *cpustate,UINT32 op)
+{
+ logerror("V810: Unknown opcode %x @ %x",op,cpustate->PC-2);
+ return clkIF;
+}
+
+static UINT32 opMOVr(v810_state *cpustate,UINT32 op) // mov reg1, reg2
+{
+ SETREG(cpustate,GET2,GETREG(cpustate,GET1));
+ return clkIF;
+}
+
+static UINT32 opMOVEA(v810_state *cpustate,UINT32 op) // movea imm16, reg1, reg2
+{
+ UINT32 op1=GETREG(cpustate,GET1);
+ UINT32 op2=R_OP(cpustate,cpustate->PC);
+ cpustate->PC+=2;
+ op2=I16(op2);
+ SETREG(cpustate,GET2,op1+op2);
+ return clkIF;
+}
+
+static UINT32 opMOVHI(v810_state *cpustate,UINT32 op) // movhi imm16, reg1 ,reg2
+{
+ UINT32 op2=R_OP(cpustate,cpustate->PC);
+ cpustate->PC+=2;
+ op2=UI16(op2);
+ op2<<=16;
+ SETREG(cpustate,GET2,GETREG(cpustate,GET1)+op2);
+ return clkIF;
+}
+
+static UINT32 opMOVi(v810_state *cpustate,UINT32 op) // mov imm5,r2
+{
+ SETREG(cpustate,GET2,I5(op));
+ return clkIF;
+}
+
+static UINT32 opADDr(v810_state *cpustate,UINT32 op) // add r1,r2
+{
+ UINT32 op1=GETREG(cpustate,GET1);
+ UINT32 op2=GETREG(cpustate,GET2);
+ UINT64 res=(UINT64)op2+(UINT64)op1;
+ CHECK_CY(res);
+ CHECK_OVADD(op1,op2,res);
+ CHECK_ZS(res);
+ SETREG(cpustate,GET2,res);
+ return clkIF;
+}
+
+static UINT32 opADDi(v810_state *cpustate,UINT32 op) // add imm5,r2
+{
+ UINT32 op1=I5(op);
+ UINT32 op2=GETREG(cpustate,GET2);
+ UINT64 res=(UINT64)op2+(UINT64)op1;
+ CHECK_CY(res);
+ CHECK_OVADD(op1,op2,res);
+ CHECK_ZS(res);
+ SETREG(cpustate,GET2,res);
+ return clkIF;
+}
+
+
+static UINT32 opADDI(v810_state *cpustate,UINT32 op) // addi imm16, reg1, reg2
+{
+ UINT32 op1=GETREG(cpustate,GET1);
+ UINT32 op2=R_OP(cpustate,cpustate->PC);
+ UINT64 res;
+ cpustate->PC+=2;
+ op2=I16(op2);
+ res=(UINT64)op2+(UINT64)op1;
+ CHECK_CY(res);
+ CHECK_OVADD(op1,op2,res);
+ CHECK_ZS(res);
+ SETREG(cpustate,GET2,res);
+ return clkIF;
+}
+
+static UINT32 opSUBr(v810_state *cpustate,UINT32 op) // sub r1,r2
+{
+ UINT32 op1=GETREG(cpustate,GET1);
+ UINT32 op2=GETREG(cpustate,GET2);
+ UINT64 res=(UINT64)op2-(UINT64)op1;
+ CHECK_CY(res);
+ CHECK_OVSUB(op1,op2,res);
+ CHECK_ZS(res);
+ SETREG(cpustate,GET2,res);
+ return clkIF;
+}
+
+
+static UINT32 opCMPr(v810_state *cpustate,UINT32 op) // cmp r1,r2
+{
+ UINT32 op1=GETREG(cpustate,GET1);
+ UINT32 op2=GETREG(cpustate,GET2);
+ UINT64 res=(UINT64)op2-(UINT64)op1;
+ CHECK_CY(res);
+ CHECK_OVSUB(op1,op2,res);
+ CHECK_ZS(res);
+ return clkIF;
+}
+
+static UINT32 opCMPi(v810_state *cpustate,UINT32 op) // cmpi imm5,r2
+{
+ UINT32 op1=I5(op);
+ UINT32 op2=GETREG(cpustate,GET2);
+ UINT64 res=(UINT64)op2-(UINT64)op1;
+ CHECK_CY(res);
+ CHECK_OVSUB(op1,op2,res);
+ CHECK_ZS(res);
+ return clkIF;
+}
+
+static UINT32 opSETFi(v810_state *cpustate,UINT32 op) // setf imm5,r2
+{
+ UINT32 op1=I5(op);
+ UINT32 op2=cpustate->PSW&0xf;
+ op1&=0xf;
+ SETREG(cpustate,GET2,(op1==op2)?1:0);
+ return clkIF;
+}
+
+
+static UINT32 opANDr(v810_state *cpustate,UINT32 op) // and r1,r2
+{
+ UINT32 op1=GETREG(cpustate,GET1);
+ UINT32 op2=GETREG(cpustate,GET2);
+ op2&=op1;
+ CHECK_ZS(op2);
+ SET_OV(0);
+ SETREG(cpustate,GET2,op2);
+ return clkIF;
+}
+
+static UINT32 opANDI(v810_state *cpustate,UINT32 op) // andi imm16,r1,r2
+{
+ UINT32 op1=GETREG(cpustate,GET1);
+ UINT32 op2=R_OP(cpustate,cpustate->PC);
+ cpustate->PC+=2;
+ op2=UI16(op2);
+ op2&=op1;
+ CHECK_ZS(op2);
+ SET_OV(0);
+ SET_S(0);
+ SETREG(cpustate,GET2,op2);
+ return clkIF;
+}
+
+static UINT32 opORr(v810_state *cpustate,UINT32 op) // or r1,r2
+{
+ UINT32 op1=GETREG(cpustate,GET1);
+ UINT32 op2=GETREG(cpustate,GET2);
+ op2|=op1;
+ CHECK_ZS(op2);
+ SET_OV(0);
+ SETREG(cpustate,GET2,op2);
+ return clkIF;
+}
+
+static UINT32 opORI(v810_state *cpustate,UINT32 op) // ori imm16,r1,r2
+{
+ UINT32 op1=GETREG(cpustate,GET1);
+ UINT32 op2=R_OP(cpustate,cpustate->PC);
+ cpustate->PC+=2;
+ op2=UI16(op2);
+ op2|=op1;
+ CHECK_ZS(op2);
+ SET_OV(0);
+ SET_S(0);
+ SETREG(cpustate,GET2,op2);
+ return clkIF;
+}
+
+static UINT32 opXORr(v810_state *cpustate,UINT32 op) // xor r1,r2
+{
+ UINT32 op1=GETREG(cpustate,GET1);
+ UINT32 op2=GETREG(cpustate,GET2);
+ op2^=op1;
+ CHECK_ZS(op2);
+ SET_OV(0);
+ SETREG(cpustate,GET2,op2);
+ return clkIF;
+}
+
+
+static UINT32 opLDSR(v810_state *cpustate,UINT32 op) // ldsr reg2,regID
+{
+ UINT32 op1=UI5(op);
+ SETREG(cpustate,32+op1,GETREG(cpustate,GET2));
+ return clkIF;
+}
+
+static UINT32 opSTSR(v810_state *cpustate,UINT32 op) // ldsr regID,reg2
+{
+ UINT32 op1=UI5(op);
+ SETREG(cpustate,GET2,GETREG(cpustate,32+op1));
+ return clkIF;
+}
+
+
+static UINT32 opXORI(v810_state *cpustate,UINT32 op) // xori imm16,r1,r2
+{
+ UINT32 op1=GETREG(cpustate,GET1);
+ UINT32 op2=R_OP(cpustate,cpustate->PC);
+ cpustate->PC+=2;
+ op2=UI16(op2);
+ op2^=op1;
+ CHECK_ZS(op2);
+ SET_OV(0);
+ SET_S(0);
+ SETREG(cpustate,GET2,op2);
+ return clkIF;
+}
+
+static UINT32 opNOTr(v810_state *cpustate,UINT32 op) // not r1,r2
+{
+ UINT32 op1=GETREG(cpustate,GET1);
+ UINT32 op2=~op1;
+ CHECK_ZS(op2);
+ SET_OV(0);
+ SETREG(cpustate,GET2,op2);
+ return clkIF;
+}
+
+static UINT32 opSHLr(v810_state *cpustate,UINT32 op) // shl r1,r2
+{
+ UINT64 tmp;
+ UINT32 count=GETREG(cpustate,GET1);
+ count&=0x1f;
+
+ SET_OV(0);
+ SET_CY(0);
+
+ if(count)
+ {
+ tmp=GETREG(cpustate,GET2);
+ tmp<<=count;
+ CHECK_CY(tmp);
+ SETREG(cpustate,GET2,tmp&0xffffffff);
+ CHECK_ZS(GETREG(cpustate,GET2));
+ }
+ return clkIF;
+}
+
+static UINT32 opSHLi(v810_state *cpustate,UINT32 op) // shl imm5,r2
+{
+ UINT64 tmp;
+ UINT32 count=UI5(op);
+
+ SET_OV(0);
+ SET_CY(0);
+
+ if(count)
+ {
+ tmp=GETREG(cpustate,GET2);
+ tmp<<=count;
+ CHECK_CY(tmp);
+ SETREG(cpustate,GET2,tmp&0xffffffff);
+ }
+ CHECK_ZS(GETREG(cpustate,GET2));
+ return clkIF;
+}
+
+static UINT32 opSHRr(v810_state *cpustate,UINT32 op) // shr r1,r2
+{
+ UINT64 tmp;
+ UINT32 count=GETREG(cpustate,GET1);
+ count&=0x1f;
+ SET_OV(0);
+ SET_CY(0);
+ if(count)
+ {
+ tmp=GETREG(cpustate,GET2);
+ tmp>>=count-1;
+ SET_CY(tmp&1);
+ SETREG(cpustate,GET2,(tmp>>1)&0xffffffff);
+ }
+ CHECK_ZS(GETREG(cpustate,GET2));
+ return clkIF;
+}
+
+static UINT32 opSHRi(v810_state *cpustate,UINT32 op) // shr imm5,r2
+{
+ UINT64 tmp;
+ UINT32 count=UI5(op);
+ SET_OV(0);
+ SET_CY(0);
+ if(count)
+ {
+ tmp=GETREG(cpustate,GET2);
+ tmp>>=count-1;
+ SET_CY(tmp&1);
+ tmp>>=1;
+ SETREG(cpustate,GET2,tmp&0xffffffff);
+ }
+ CHECK_ZS(GETREG(cpustate,GET2));
+ return clkIF;
+}
+
+static UINT32 opSARr(v810_state *cpustate,UINT32 op) // sar r1,r2
+{
+ INT32 tmp;
+ UINT32 count=GETREG(cpustate,GET1);
+ count&=0x1f;
+ SET_OV(0);
+ SET_CY(0);
+ if(count)
+ {
+ tmp=GETREG(cpustate,GET2);
+ tmp>>=count-1;
+ SET_CY(tmp&1);
+ tmp>>=1;
+ SETREG(cpustate,GET2,tmp);
+ }
+ CHECK_ZS(GETREG(cpustate,GET2));
+ return clkIF;
+}
+
+static UINT32 opSARi(v810_state *cpustate,UINT32 op) // sar imm5,r2
+{
+ INT32 tmp;
+ UINT32 count=UI5(op);
+ SET_OV(0);
+ SET_CY(0);
+ if(count)
+ {
+ tmp=GETREG(cpustate,GET2);
+ tmp>>=count-1;
+ SET_CY(tmp&1);
+ tmp>>=1;
+ SETREG(cpustate,GET2,tmp);
+ }
+ CHECK_ZS(GETREG(cpustate,GET2));
+ return clkIF;
+}
+
+static UINT32 opJMPr(v810_state *cpustate,UINT32 op)
+{
+ cpustate->PC=GETREG(cpustate,GET1)&~1;
+ return clkIF+2;
+}
+
+
+static UINT32 opJR(v810_state *cpustate,UINT32 op)
+{
+ UINT32 tmp=R_OP(cpustate,cpustate->PC);
+ cpustate->PC=cpustate->PC-2+(D26(op,tmp)&~1);
+ return clkIF+2;
+}
+
+static UINT32 opJAL(v810_state *cpustate,UINT32 op)
+{
+ UINT32 tmp=R_OP(cpustate,cpustate->PC);
+ cpustate->PC+=2;
+ cpustate->R31=cpustate->PC;
+ cpustate->PC+=D26(op,tmp);
+ cpustate->PC-=4;
+ cpustate->PC&=~1;
+ return clkIF+2;
+}
+
+
+static UINT32 opEI(v810_state *cpustate,UINT32 op)
+{
+ SET_ID(0);
+ return clkIF;
+}
+
+static UINT32 opDI(v810_state *cpustate,UINT32 op)
+{
+ SET_ID(1);
+ return clkIF;
+}
+
+static UINT32 opTRAP(v810_state *cpustate,UINT32 op)
+{
+ logerror("V810: TRAP @ %X\n",cpustate->PC-2);
+ return clkIF;
+}
+
+static UINT32 opRETI(v810_state *cpustate,UINT32 op)
+{
+ if(GET_NP) {
+ cpustate->PC = cpustate->FEPC;
+ cpustate->PSW = cpustate->FEPSW;
+ } else {
+ cpustate->PC = cpustate->EIPC;
+ cpustate->PSW = cpustate->EIPSW;
+ }
+ return clkIF;
+}
+
+static UINT32 opHALT(v810_state *cpustate,UINT32 op)
+{
+ logerror("V810: HALT @ %X",cpustate->PC-2);
+ return clkIF;
+}
+
+static UINT32 opB(v810_state *cpustate,UINT32 op)
+{
+ int doBranch=0;
+ switch((op>>9)&0xf)
+ {
+ case 0: //bv
+ doBranch=GET_OV;
+ break;
+
+ case 1: //bl
+ doBranch=GET_CY;
+ break;
+
+ case 2: //be
+ doBranch=GET_Z;
+ break;
+
+ case 3: //bnh
+ doBranch=GET_Z||GET_CY;
+ break;
+
+ case 4: //bn
+ doBranch=GET_S;
+ break;
+
+ case 5: //br
+ doBranch=1;
+ break;
+
+ case 6: //blt
+ doBranch=GET_S^GET_OV;
+ break;
+
+ case 7: //ble
+ doBranch=GET_Z||(GET_S^GET_OV);
+ break;
+
+ case 8: //bnv
+ doBranch=!GET_OV;
+ break;
+
+ case 9: //bnl
+ doBranch=!GET_CY;
+ break;
+
+ case 10: //bne
+ doBranch=!GET_Z;
+ break;
+
+ case 11: //bh
+ doBranch=!(GET_Z||GET_CY);
+ break;
+
+ case 12: //bp
+ doBranch=!GET_S;
+ break;
+
+ case 13: //nop
+
+ break;
+
+ case 14: //bge
+ doBranch=!(GET_OV^GET_S);
+ break;
+
+ case 15: //bgt
+ doBranch=!(GET_Z||(GET_OV^GET_S));
+ break;
+ }
+ if(doBranch)
+ {
+ cpustate->PC=cpustate->PC-2+(D9(op)&~1);
+ }
+ return clkIF;
+}
+
+static UINT32 opLDB(v810_state *cpustate,UINT32 op) // ld.b disp16[reg1],reg2
+{
+ UINT32 tmp=R_OP(cpustate,cpustate->PC);
+ cpustate->PC+=2;
+ tmp=D16(tmp);
+ tmp+=GETREG(cpustate,GET1);
+ tmp=R_B(cpustate,tmp);
+ tmp|=(tmp&0x80)?0xffffff00:0;
+ SETREG(cpustate,GET2,tmp);
+ return clkIF+clkMEM;
+}
+
+static UINT32 opLDH(v810_state *cpustate,UINT32 op) // ld.h disp16[reg1],reg2
+{
+ UINT32 tmp=R_OP(cpustate,cpustate->PC);
+ cpustate->PC+=2;
+ tmp=D16(tmp);
+ tmp+=GETREG(cpustate,GET1);
+ tmp=R_H(cpustate,tmp&~1);
+ tmp|=(tmp&0x8000)?0xffff0000:0;
+ SETREG(cpustate,GET2,tmp);
+ return clkIF+clkMEM;
+}
+
+static UINT32 opLDW(v810_state *cpustate,UINT32 op) // ld.w disp16[reg1],reg2
+{
+ UINT32 tmp=R_OP(cpustate,cpustate->PC);
+ cpustate->PC+=2;
+ tmp=D16(tmp);
+ tmp+=GETREG(cpustate,GET1);
+ tmp=R_W(cpustate,tmp&~3);
+ SETREG(cpustate,GET2,tmp);
+ return clkIF+clkMEM;
+}
+
+static UINT32 opINB(v810_state *cpustate,UINT32 op) // in.b disp16[reg1],reg2
+{
+ UINT32 tmp=R_OP(cpustate,cpustate->PC);
+ cpustate->PC+=2;
+ tmp=D16(tmp);
+ tmp+=GETREG(cpustate,GET1);
+ tmp=RIO_B(cpustate,tmp);
+ SETREG(cpustate,GET2,tmp);
+ return clkIF+clkMEM;
+}
+
+static UINT32 opCAXI(v810_state *cpustate,UINT32 op) // caxi disp16[reg1],reg2
+{
+ cpustate->PC+=2;
+ return clkIF;
+}
+
+static UINT32 opINH(v810_state *cpustate,UINT32 op) // in.h disp16[reg1],reg2
+{
+ UINT32 tmp=R_OP(cpustate,cpustate->PC);
+ cpustate->PC+=2;
+ tmp=D16(tmp);
+ tmp+=GETREG(cpustate,GET1);
+ tmp=RIO_H(cpustate,tmp&~1);
+ SETREG(cpustate,GET2,tmp);
+ return clkIF+clkMEM;
+}
+
+static UINT32 opINW(v810_state *cpustate,UINT32 op) // in.w disp16[reg1],reg2
+{
+ UINT32 tmp=R_OP(cpustate,cpustate->PC);
+ cpustate->PC+=2;
+ tmp=D16(tmp);
+ tmp+=GETREG(cpustate,GET1);
+ tmp=RIO_W(cpustate,tmp&~3);
+ SETREG(cpustate,GET2,tmp);
+ return clkIF+clkMEM;
+}
+
+static UINT32 opSTB(v810_state *cpustate,UINT32 op) // st.b reg2, disp16[reg1]
+{
+ UINT32 tmp=R_OP(cpustate,cpustate->PC);
+ cpustate->PC+=2;
+ tmp=D16(tmp);
+ tmp+=GETREG(cpustate,GET1);
+ W_B(cpustate,tmp,GETREG(cpustate,GET2)&0xff);
+ return clkIF+clkMEM;
+}
+
+static UINT32 opSTH(v810_state *cpustate,UINT32 op) // st.h reg2, disp16[reg1]
+{
+ UINT32 tmp=R_OP(cpustate,cpustate->PC);
+ cpustate->PC+=2;
+ tmp=D16(tmp);
+ tmp+=GETREG(cpustate,GET1);
+ W_H(cpustate,tmp&~1,GETREG(cpustate,GET2)&0xffff);
+ return clkIF+clkMEM;
+}
+
+static UINT32 opSTW(v810_state *cpustate,UINT32 op) // st.w reg2, disp16[reg1]
+{
+ UINT32 tmp=R_OP(cpustate,cpustate->PC);
+ cpustate->PC+=2;
+ tmp=D16(tmp);
+ tmp+=GETREG(cpustate,GET1);
+ W_W(cpustate,tmp&~3,GETREG(cpustate,GET2));
+ return clkIF+clkMEM;
+}
+
+static UINT32 opOUTB(v810_state *cpustate,UINT32 op) // out.b reg2, disp16[reg1]
+{
+ UINT32 tmp=R_OP(cpustate,cpustate->PC);
+ cpustate->PC+=2;
+ tmp=D16(tmp);
+ tmp+=GETREG(cpustate,GET1);
+ WIO_B(cpustate,tmp,GETREG(cpustate,GET2)&0xff);
+ return clkIF+clkMEM;
+}
+
+static UINT32 opOUTH(v810_state *cpustate,UINT32 op) // out.h reg2, disp16[reg1]
+{
+ UINT32 tmp=R_OP(cpustate,cpustate->PC);
+ cpustate->PC+=2;
+ tmp=D16(tmp);
+ tmp+=GETREG(cpustate,GET1);
+ WIO_H(cpustate,tmp&~1,GETREG(cpustate,GET2)&0xffff);
+ return clkIF+clkMEM;
+}
+
+static UINT32 opOUTW(v810_state *cpustate,UINT32 op) // out.w reg2, disp16[reg1]
+{
+ UINT32 tmp=R_OP(cpustate,cpustate->PC);
+ cpustate->PC+=2;
+ tmp=D16(tmp);
+ tmp+=GETREG(cpustate,GET1);
+ WIO_W(cpustate,tmp&~3,GETREG(cpustate,GET2));
+ return clkIF+clkMEM;
+}
+
+static UINT32 opMULr(v810_state *cpustate,UINT32 op) // mul r1,r2
+{
+ UINT32 op1=GETREG(cpustate,GET1);
+ UINT32 op2=GETREG(cpustate,GET2);
+ UINT64 tmp;
+ tmp=(INT64)(INT32)op1*(INT64)(INT32)op2;
+ op2=tmp&0xffffffff;
+ tmp>>=32;
+ CHECK_ZS(tmp);//z = bad!
+ SET_Z( (tmp|op2)==0 );
+ SET_OV((tmp!=0));
+ SET_CY((tmp!=0));
+ SETREG(cpustate,GET2,op2);
+ SETREG(cpustate,30,tmp);
+ return clkIF;
+}
+
+static UINT32 opMULUr(v810_state *cpustate,UINT32 op) // mulu r1,r2
+{
+ UINT32 op1=GETREG(cpustate,GET1);
+ UINT32 op2=GETREG(cpustate,GET2);
+ UINT64 tmp;
+ tmp=(UINT64)op1*(UINT64)op2;
+ op2=tmp&0xffffffff;
+ tmp>>=32;
+ CHECK_ZS(tmp);//z = bad!
+ SET_Z( (tmp|op2)==0 );
+ SET_OV((tmp!=0));
+ SET_CY((tmp!=0));
+ SETREG(cpustate,GET2,op2);
+ SETREG(cpustate,30,tmp);
+ return clkIF;
+}
+
+static UINT32 opDIVr(v810_state *cpustate,UINT32 op) // div r1,r2
+{
+ UINT32 op1=GETREG(cpustate,GET1);
+ UINT32 op2=GETREG(cpustate,GET2);
+ if(op1)
+ {
+ SETREG(cpustate,30,(INT32)((INT32)op2%(INT32)op1));
+ SETREG(cpustate,GET2,(INT32)((INT32)op2/(INT32)op1));
+ SET_OV((op1^op2^GETREG(cpustate,GET2)) == 0x80000000);
+ CHECK_ZS(GETREG(cpustate,GET2));
+ }
+ return clkIF;
+}
+
+static UINT32 opDIVUr(v810_state *cpustate,UINT32 op) // divu r1,r2
+{
+ UINT32 op1=GETREG(cpustate,GET1);
+ UINT32 op2=GETREG(cpustate,GET2);
+ if(op1)
+ {
+ SETREG(cpustate,30,(INT32)(op2%op1));
+ SETREG(cpustate,GET2,(INT32)(op2/op1));
+ SET_OV((op1^op2^GETREG(cpustate,GET2)) == 0x80000000);
+ CHECK_ZS(GETREG(cpustate,GET2));
+ }
+ return clkIF;
+}
+
+static void opADDF(v810_state *cpustate,UINT32 op)
+{
+ //TODO: CY
+ float val1=u2f(GETREG(cpustate,GET1));
+ float val2=u2f(GETREG(cpustate,GET2));
+ SET_OV(0);
+ val2+=val1;
+ SET_Z((val2==0.0)?1:0);
+ SET_S((val2<0.0)?1:0);
+ SETREG(cpustate,GET2,f2u(val2));
+}
+
+static void opSUBF(v810_state *cpustate,UINT32 op)
+{
+ float val1=u2f(GETREG(cpustate,GET1));
+ float val2=u2f(GETREG(cpustate,GET2));
+ SET_OV(0);
+ SET_CY((val2<val1)?1:0);
+ val2-=val1;
+ SET_Z((val2==0.0)?1:0);
+ SET_S((val2<0.0)?1:0);
+ SETREG(cpustate,GET2,f2u(val2));
+}
+
+static void opMULF(v810_state *cpustate,UINT32 op)
+{
+ //TODO: CY
+ float val1=u2f(GETREG(cpustate,GET1));
+ float val2=u2f(GETREG(cpustate,GET2));
+ SET_OV(0);
+ val2*=val1;
+ SET_Z((val2==0.0)?1:0);
+ SET_S((val2<0.0)?1:0);
+ SETREG(cpustate,GET2,f2u(val2));
+}
+
+static void opDIVF(v810_state *cpustate,UINT32 op)
+{
+ //TODO: CY
+ float val1=u2f(GETREG(cpustate,GET1));
+ float val2=u2f(GETREG(cpustate,GET2));
+ SET_OV(0);
+ if(val1!=0)
+ val2/=val1;
+ SET_Z((val2==0.0)?1:0);
+ SET_S((val2<0.0)?1:0);
+ SETREG(cpustate,GET2,f2u(val2));
+}
+
+static void opTRNC(v810_state *cpustate,UINT32 op)
+{
+ float val1=u2f(GETREG(cpustate,GET1));
+ SET_OV(0);
+ SET_Z((val1==0.0)?1:0);
+ SET_S((val1<0.0)?1:0);
+ SETREG(cpustate,GET2,(INT32)val1);
+}
+
+static void opCMPF(v810_state *cpustate,UINT32 op)
+{
+ float val1=u2f(GETREG(cpustate,GET1));
+ float val2=u2f(GETREG(cpustate,GET2));
+ SET_OV(0);
+ SET_CY((val2<val1)?1:0);
+ val2-=val1;
+ SET_Z((val2==0.0)?1:0);
+ SET_S((val2<0.0)?1:0);
+}
+
+static void opCVTS(v810_state *cpustate,UINT32 op)
+{
+ float val1=u2f(GETREG(cpustate,GET1));
+ SET_OV(0);
+ SET_Z((val1==0.0)?1:0);
+ SET_S((val1<0.0)?1:0);
+ SETREG(cpustate,GET2,(INT32)val1);
+}
+
+static void opCVTW(v810_state *cpustate,UINT32 op)
+{
+ //TODO: CY
+ float val1=GETREG(cpustate,GET1);
+ SET_OV(0);
+ SET_Z((val1==0.0)?1:0);
+ SET_S((val1<0.0)?1:0);
+ SETREG(cpustate,GET2,f2u(val1));
+}
+
+static UINT32 opFpoint(v810_state *cpustate,UINT32 op)
+{
+ UINT32 tmp=R_OP(cpustate,cpustate->PC);
+ cpustate->PC+=2;
+ switch((tmp&0xfc00)>>10)
+ {
+ case 0x0: opCMPF(cpustate,op);break;
+ case 0x2: opCVTW(cpustate,op);break;
+ case 0x3: opCVTS(cpustate,op);break;
+ case 0x4: opADDF(cpustate,op);break;
+ case 0x5: opSUBF(cpustate,op);break;
+ case 0x6: opMULF(cpustate,op);break;
+ case 0x7: opDIVF(cpustate,op);break;
+ case 0xb: opTRNC(cpustate,op);break;
+ }
+ return clkIF+1;
+}
+
+static UINT32 (*const OpCodeTable[64])(v810_state *cpustate,UINT32 op) =
+{
+ /* 0x00 */ opMOVr, // mov r1,r2 1
+ /* 0x01 */ opADDr, // add r1,r2 1
+ /* 0x02 */ opSUBr, // sub r1,r2 1
+ /* 0x03 */ opCMPr, // cmp2 r1,r2 1
+ /* 0x04 */ opSHLr, // shl r1,r2 1
+ /* 0x05 */ opSHRr, // shr r1,r2 1
+ /* 0x06 */ opJMPr, // jmp [r1] 1
+ /* 0x07 */ opSARr, // sar r1,r2 1
+ /* 0x08 */ opMULr, // mul r1,r2 1
+ /* 0x09 */ opDIVr, // div r1,r2 1
+ /* 0x0a */ opMULUr, // mulu r1,r2 1
+ /* 0x0b */ opDIVUr, // divu r1,r2 1
+ /* 0x0c */ opORr, // or r1,r2 1
+ /* 0x0d */ opANDr, // and r1,r2 1
+ /* 0x0e */ opXORr, // xor r1,r2 1
+ /* 0x0f */ opNOTr, // not r1,r2 1
+ /* 0x10 */ opMOVi, // mov imm5,r2 2
+ /* 0x11 */ opADDi, // add imm5,r2 2
+ /* 0x12 */ opSETFi, // setf imm5,r2 2
+ /* 0x13 */ opCMPi, // cmp imm5,r2 2
+ /* 0x14 */ opSHLi, // shl imm5,r2 2
+ /* 0x15 */ opSHRi, // shr imm5,r2 2
+ /* 0x16 */ opEI, // ei 2
+ /* 0x17 */ opSARi, // sar imm5,r2 2
+ /* 0x18 */ opTRAP,
+ /* 0x19 */ opRETI,
+ /* 0x1a */ opHALT, // halt 2
+ /* 0x1b */ opUNDEF,
+ /* 0x1c */ opLDSR, // ldsr reg2,regID 2
+ /* 0x1d */ opSTSR, // stsr regID,reg2 2
+ /* 0x1e */ opDI, // DI 2
+ /* 0x1f */ opUNDEF,
+ /* 0x20 */ opB, // Branch (7 bit opcode)
+ /* 0x21 */ opB, // Branch (7 bit opcode)
+ /* 0x22 */ opB, // Branch (7 bit opcode)
+ /* 0x23 */ opB, // Branch (7 bit opcode)
+ /* 0x24 */ opB, // Branch (7 bit opcode)
+ /* 0x25 */ opB, // Branch (7 bit opcode)
+ /* 0x26 */ opB, // Branch (7 bit opcode)
+ /* 0x27 */ opB, // Branch (7 bit opcode)
+ /* 0x28 */ opMOVEA, // movea imm16, reg1, reg2 5
+ /* 0x29 */ opADDI, // addi imm16, reg1, reg2 5
+ /* 0x2a */ opJR, // jr disp26 4
+ /* 0x2b */ opJAL, // jal disp26 4
+ /* 0x2c */ opORI, // ori imm16, reg1, reg2 5
+ /* 0x2d */ opANDI, // andi imm16, reg1, reg2 5
+ /* 0x2e */ opXORI, // xori imm16, reg1, reg2 5
+ /* 0x2f */ opMOVHI, // movhi imm16, reg1 ,reg2 5
+ /* 0x30 */ opLDB, // ld.b disp16[reg1],reg2 6a
+ /* 0x31 */ opLDH, // ld.h disp16[reg1],reg2 6a
+ /* 0x32 */ opUNDEF,
+ /* 0x33 */ opLDW, // ld.w disp16[reg1],reg2 6a
+ /* 0x34 */ opSTB, // st.b reg2, disp16[reg1] 6b
+ /* 0x35 */ opSTH, // st.h reg2, disp16[reg1] 6b
+ /* 0x36 */ opUNDEF,
+ /* 0x37 */ opSTW, // st.w reg2, disp16[reg1] 6b
+ /* 0x38 */ opINB, // in.b disp16[reg1], reg2 6a
+ /* 0x39 */ opINH, // in.h disp16[reg1], reg2 6a
+ /* 0x3a */ opCAXI, // caxi disp16[reg1],reg2 6a
+ /* 0x3b */ opINW, // in.w disp16[reg1], reg2 6a
+ /* 0x3c */ opOUTB, // out.b reg2, disp16[reg1] 6b
+ /* 0x3d */ opOUTH, // out.h reg2, disp16[reg1] 6b
+ /* 0x3e */ opFpoint, //floating point opcodes
+ /* 0x3f */ opOUTW // out.w reg2, disp16[reg1] 6b
+};
+
+static CPU_INIT( v810 )
+{
+ v810_state *cpustate = get_safe_token(device);
+
+ cpustate->irq_state = CLEAR_LINE;
+ cpustate->irq_line = 0;
+ cpustate->nmi_line = CLEAR_LINE;
+ 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));
+ device->save_item(NAME(cpustate->irq_line));
+ device->save_item(NAME(cpustate->irq_state));
+ device->save_item(NAME(cpustate->nmi_line));
+ device->save_item(NAME(cpustate->PPC));
+
+}
+
+static CPU_RESET( v810 )
+{
+ v810_state *cpustate = get_safe_token(device);
+ int i;
+ for(i=0;i<64;i++) cpustate->reg[i]=0;
+ cpustate->PC = 0xfffffff0;
+ cpustate->PSW = 0x1000;
+ cpustate->ECR = 0x0000fff0;
+}
+
+static void take_interrupt(v810_state *cpustate)
+{
+ cpustate->EIPC = cpustate->PC;
+ cpustate->EIPSW = cpustate->PSW;
+
+ cpustate->PC = 0xfffffe00 | (cpustate->irq_line << 4);
+ cpustate->ECR = 0xfe00 | (cpustate->irq_line << 4);
+
+ UINT8 num = cpustate->irq_line + 1;
+ if (num==0x10) num=0x0f;
+
+ cpustate->PSW &= 0xfff0ffff; // clear interrupt level
+ SET_EP(1);
+ SET_ID(1);
+ cpustate->PSW |= num << 16;
+
+ cpustate->icount-= clkIF;
+}
+
+static CPU_EXECUTE( v810 )
+{
+ v810_state *cpustate = get_safe_token(device);
+
+ if (cpustate->irq_state != CLEAR_LINE) {
+ if (!(GET_NP | GET_EP | GET_ID)) {
+ if (cpustate->irq_line >=((cpustate->PSW & 0xF0000) >> 16)) {
+ take_interrupt(cpustate);
+ }
+ }
+ }
+ while(cpustate->icount>0)
+ {
+ UINT32 op;
+
+ cpustate->PPC=cpustate->PC;
+ debugger_instruction_hook(device, cpustate->PC);
+ op=R_OP(cpustate,cpustate->PC);
+ cpustate->PC+=2;
+ cpustate->icount-= OpCodeTable[op>>10](cpustate,op);
+ }
+}
+
+
+static void set_irq_line(v810_state *cpustate, int irqline, int state)
+{
+ cpustate->irq_state = state;
+ cpustate->irq_line = irqline;
+}
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( v810 )
+{
+ v810_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 + 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;
+ case CPUINFO_INT_INPUT_STATE + 8: set_irq_line(cpustate, 8, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + 9: set_irq_line(cpustate, 9, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + 10: set_irq_line(cpustate, 10, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + 11: set_irq_line(cpustate, 11, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + 12: set_irq_line(cpustate, 12, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + 13: set_irq_line(cpustate, 13, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + 14: set_irq_line(cpustate, 14, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + 15: set_irq_line(cpustate, 15, info->i); break;
+
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line(cpustate, INPUT_LINE_NMI, info->i); break;
+
+ case CPUINFO_INT_PREVIOUSPC: cpustate->PPC = info->i; break;
+
+ case CPUINFO_INT_REGISTER + V810_PC:
+ case CPUINFO_INT_PC: cpustate->PC = info->i; break;
+
+ case CPUINFO_INT_REGISTER + V810_R0: cpustate->R0 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R1: cpustate->R1 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R2: cpustate->R2 = info->i; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + V810_SP: cpustate->SP = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R4: cpustate->R4 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R5: cpustate->R5 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R6: cpustate->R6 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R7: cpustate->R7 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R8: cpustate->R8 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R9: cpustate->R9 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R10: cpustate->R10 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R11: cpustate->R11 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R12: cpustate->R12 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R13: cpustate->R13 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R14: cpustate->R14 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R15: cpustate->R15 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R16: cpustate->R16 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R17: cpustate->R17 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R18: cpustate->R18 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R19: cpustate->R19 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R20: cpustate->R20 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R21: cpustate->R21 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R22: cpustate->R22 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R23: cpustate->R23 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R24: cpustate->R24 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R25: cpustate->R25 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R26: cpustate->R26 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R27: cpustate->R27 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R28: cpustate->R28 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R29: cpustate->R29 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R30: cpustate->R30 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_R31: cpustate->R31 = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_PSW: cpustate->PSW = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_EIPC: cpustate->EIPC = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_EIPSW: cpustate->EIPSW = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_FEPC: cpustate->FEPC = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_FEPSW: cpustate->FEPSW = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_ECR: cpustate->ECR = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_PIR: cpustate->PIR = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_TKCW: cpustate->TKCW = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_CHCW: cpustate->CHCW = info->i; break;
+ case CPUINFO_INT_REGISTER + V810_ADTRE: cpustate->ADTRE = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( v810 )
+{
+ v810_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_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c",
+ GET_AE ? 'A':'.',
+ GET_NP ? 'N':'.',
+ GET_EP ? 'E':'.',
+ GET_ID ? 'I':'.',
+ GET_CY ? 'C':'.',
+ GET_OV ? 'V':'.',
+ GET_S ? 'S':'.',
+ GET_Z ? 'Z':'.');
+ break;
+
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(v810_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_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 = 6; 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 = 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 + 0: info->i = (cpustate->irq_line == 0) ? cpustate->irq_state : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + 1: info->i = (cpustate->irq_line == 1) ? cpustate->irq_state : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + 2: info->i = (cpustate->irq_line == 2) ? cpustate->irq_state : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + 3: info->i = (cpustate->irq_line == 3) ? cpustate->irq_state : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + 4: info->i = (cpustate->irq_line == 4) ? cpustate->irq_state : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + 5: info->i = (cpustate->irq_line == 5) ? cpustate->irq_state : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + 6: info->i = (cpustate->irq_line == 6) ? cpustate->irq_state : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + 7: info->i = (cpustate->irq_line == 7) ? cpustate->irq_state : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + 8: info->i = (cpustate->irq_line == 8) ? cpustate->irq_state : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + 9: info->i = (cpustate->irq_line == 9) ? cpustate->irq_state : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + 10: info->i = (cpustate->irq_line == 10) ? cpustate->irq_state : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + 11: info->i = (cpustate->irq_line == 11) ? cpustate->irq_state : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + 12: info->i = (cpustate->irq_line == 12) ? cpustate->irq_state : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + 13: info->i = (cpustate->irq_line == 13) ? cpustate->irq_state : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + 14: info->i = (cpustate->irq_line == 14) ? cpustate->irq_state : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + 15: info->i = (cpustate->irq_line == 15) ? cpustate->irq_state : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = cpustate->nmi_line; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->PPC; break;
+
+ case CPUINFO_INT_REGISTER + V810_PC:
+ case CPUINFO_INT_PC: info->i = cpustate->PC; break;
+
+ case CPUINFO_INT_REGISTER + V810_R0: info->i = cpustate->R0; break;
+ case CPUINFO_INT_REGISTER + V810_R1: info->i = cpustate->R1; break;
+ case CPUINFO_INT_REGISTER + V810_R2: info->i = cpustate->R2; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + V810_SP: info->i = cpustate->SP; break;
+ case CPUINFO_INT_REGISTER + V810_R4: info->i = cpustate->R4; break;
+ case CPUINFO_INT_REGISTER + V810_R5: info->i = cpustate->R5; break;
+ case CPUINFO_INT_REGISTER + V810_R6: info->i = cpustate->R6; break;
+ case CPUINFO_INT_REGISTER + V810_R7: info->i = cpustate->R7; break;
+ case CPUINFO_INT_REGISTER + V810_R8: info->i = cpustate->R8; break;
+ case CPUINFO_INT_REGISTER + V810_R9: info->i = cpustate->R9; break;
+ case CPUINFO_INT_REGISTER + V810_R10: info->i = cpustate->R10; break;
+ case CPUINFO_INT_REGISTER + V810_R11: info->i = cpustate->R11; break;
+ case CPUINFO_INT_REGISTER + V810_R12: info->i = cpustate->R12; break;
+ case CPUINFO_INT_REGISTER + V810_R13: info->i = cpustate->R13; break;
+ case CPUINFO_INT_REGISTER + V810_R14: info->i = cpustate->R14; break;
+ case CPUINFO_INT_REGISTER + V810_R15: info->i = cpustate->R15; break;
+ case CPUINFO_INT_REGISTER + V810_R16: info->i = cpustate->R16; break;
+ case CPUINFO_INT_REGISTER + V810_R17: info->i = cpustate->R17; break;
+ case CPUINFO_INT_REGISTER + V810_R18: info->i = cpustate->R18; break;
+ case CPUINFO_INT_REGISTER + V810_R19: info->i = cpustate->R19; break;
+ case CPUINFO_INT_REGISTER + V810_R20: info->i = cpustate->R20; break;
+ case CPUINFO_INT_REGISTER + V810_R21: info->i = cpustate->R21; break;
+ case CPUINFO_INT_REGISTER + V810_R22: info->i = cpustate->R22; break;
+ case CPUINFO_INT_REGISTER + V810_R23: info->i = cpustate->R23; break;
+ case CPUINFO_INT_REGISTER + V810_R24: info->i = cpustate->R24; break;
+ case CPUINFO_INT_REGISTER + V810_R25: info->i = cpustate->R25; break;
+ case CPUINFO_INT_REGISTER + V810_R26: info->i = cpustate->R26; break;
+ case CPUINFO_INT_REGISTER + V810_R27: info->i = cpustate->R27; break;
+ case CPUINFO_INT_REGISTER + V810_R28: info->i = cpustate->R28; break;
+ case CPUINFO_INT_REGISTER + V810_R29: info->i = cpustate->R29; break;
+ case CPUINFO_INT_REGISTER + V810_R30: info->i = cpustate->R30; break;
+ case CPUINFO_INT_REGISTER + V810_R31: info->i = cpustate->R31; break;
+ case CPUINFO_INT_REGISTER + V810_PSW: info->i = cpustate->PSW; break;
+ case CPUINFO_INT_REGISTER + V810_EIPC: info->i = cpustate->EIPC; break;
+ case CPUINFO_INT_REGISTER + V810_EIPSW: info->i = cpustate->EIPSW; break;
+ case CPUINFO_INT_REGISTER + V810_FEPC: info->i = cpustate->FEPC; break;
+ case CPUINFO_INT_REGISTER + V810_FEPSW: info->i = cpustate->FEPSW; break;
+ case CPUINFO_INT_REGISTER + V810_ECR: info->i = cpustate->ECR; break;
+ case CPUINFO_INT_REGISTER + V810_PIR: info->i = cpustate->PIR; break;
+ case CPUINFO_INT_REGISTER + V810_TKCW: info->i = cpustate->TKCW; break;
+ case CPUINFO_INT_REGISTER + V810_CHCW: info->i = cpustate->CHCW; break;
+ case CPUINFO_INT_REGISTER + V810_ADTRE: info->i = cpustate->ADTRE; 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(v810); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(v810); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(v810); break;
+ case CPUINFO_FCT_EXIT: info->exit = NULL; break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(v810); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(v810); 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, "V810"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "NEC V810"); 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, "Tomasz Slanina"); break;
+
+ case CPUINFO_STR_REGISTER + V810_PC: sprintf(info->s, "PC:%08X", cpustate->PC); break;
+ case CPUINFO_STR_REGISTER + V810_R0: sprintf(info->s, "R0 :%08X", cpustate->R0); break;
+ case CPUINFO_STR_REGISTER + V810_R1: sprintf(info->s, "R1 :%08X", cpustate->R1); break;
+ case CPUINFO_STR_REGISTER + V810_R2: sprintf(info->s, "R2 :%08X", cpustate->R2); break;
+ case CPUINFO_STR_REGISTER + V810_SP: sprintf(info->s, "SP :%08X", cpustate->SP); break;
+ case CPUINFO_STR_REGISTER + V810_R4: sprintf(info->s, "R4 :%08X", cpustate->R4); break;
+ case CPUINFO_STR_REGISTER + V810_R5: sprintf(info->s, "R5 :%08X", cpustate->R5); break;
+ case CPUINFO_STR_REGISTER + V810_R6: sprintf(info->s, "R6 :%08X", cpustate->R6); break;
+ case CPUINFO_STR_REGISTER + V810_R7: sprintf(info->s, "R7 :%08X", cpustate->R7); break;
+ case CPUINFO_STR_REGISTER + V810_R8: sprintf(info->s, "R8 :%08X", cpustate->R8); break;
+ case CPUINFO_STR_REGISTER + V810_R9: sprintf(info->s, "R9 :%08X", cpustate->R9); break;
+ case CPUINFO_STR_REGISTER + V810_R10: sprintf(info->s, "R10:%08X", cpustate->R10); break;
+ case CPUINFO_STR_REGISTER + V810_R11: sprintf(info->s, "R11:%08X", cpustate->R11); break;
+ case CPUINFO_STR_REGISTER + V810_R12: sprintf(info->s, "R12:%08X", cpustate->R12); break;
+ case CPUINFO_STR_REGISTER + V810_R13: sprintf(info->s, "R13:%08X", cpustate->R13); break;
+ case CPUINFO_STR_REGISTER + V810_R14: sprintf(info->s, "R14:%08X", cpustate->R14); break;
+ case CPUINFO_STR_REGISTER + V810_R15: sprintf(info->s, "R15:%08X", cpustate->R15); break;
+ case CPUINFO_STR_REGISTER + V810_R16: sprintf(info->s, "R16:%08X", cpustate->R16); break;
+ case CPUINFO_STR_REGISTER + V810_R17: sprintf(info->s, "R17:%08X", cpustate->R17); break;
+ case CPUINFO_STR_REGISTER + V810_R18: sprintf(info->s, "R18:%08X", cpustate->R18); break;
+ case CPUINFO_STR_REGISTER + V810_R19: sprintf(info->s, "R19:%08X", cpustate->R19); break;
+ case CPUINFO_STR_REGISTER + V810_R20: sprintf(info->s, "R20:%08X", cpustate->R20); break;
+ case CPUINFO_STR_REGISTER + V810_R21: sprintf(info->s, "R21:%08X", cpustate->R21); break;
+ case CPUINFO_STR_REGISTER + V810_R22: sprintf(info->s, "R22:%08X", cpustate->R22); break;
+ case CPUINFO_STR_REGISTER + V810_R23: sprintf(info->s, "R23:%08X", cpustate->R23); break;
+ case CPUINFO_STR_REGISTER + V810_R24: sprintf(info->s, "R24:%08X", cpustate->R24); break;
+ case CPUINFO_STR_REGISTER + V810_R25: sprintf(info->s, "R25:%08X", cpustate->R25); break;
+ case CPUINFO_STR_REGISTER + V810_R26: sprintf(info->s, "R26:%08X", cpustate->R26); break;
+ case CPUINFO_STR_REGISTER + V810_R27: sprintf(info->s, "R27:%08X", cpustate->R27); break;
+ case CPUINFO_STR_REGISTER + V810_R28: sprintf(info->s, "R28:%08X", cpustate->R28); break;
+ case CPUINFO_STR_REGISTER + V810_R29: sprintf(info->s, "R29:%08X", cpustate->R29); break;
+ case CPUINFO_STR_REGISTER + V810_R30: sprintf(info->s, "R30:%08X", cpustate->R30); break;
+ case CPUINFO_STR_REGISTER + V810_R31: sprintf(info->s, "R31:%08X", cpustate->R31); break;
+ case CPUINFO_STR_REGISTER + V810_EIPC: sprintf(info->s, "EIPC :%08X", cpustate->EIPC); break;
+ case CPUINFO_STR_REGISTER + V810_PSW: sprintf(info->s, "PSW :%08X", cpustate->PSW); break;
+ case CPUINFO_STR_REGISTER + V810_EIPSW: sprintf(info->s, "EIPSW:%08X", cpustate->EIPSW); break;
+ case CPUINFO_STR_REGISTER + V810_FEPC: sprintf(info->s, "FEPC :%08X", cpustate->FEPC); break;
+ case CPUINFO_STR_REGISTER + V810_FEPSW: sprintf(info->s, "FEPSW:%08X", cpustate->FEPSW); break;
+ case CPUINFO_STR_REGISTER + V810_ECR: sprintf(info->s, "ECR :%08X", cpustate->ECR); break;
+ case CPUINFO_STR_REGISTER + V810_PIR: sprintf(info->s, "PIR :%08X", cpustate->PIR); break;
+ case CPUINFO_STR_REGISTER + V810_TKCW: sprintf(info->s, "TKCW :%08X", cpustate->TKCW); break;
+ case CPUINFO_STR_REGISTER + V810_CHCW: sprintf(info->s, "CHCW :%08X", cpustate->CHCW); break;
+ case CPUINFO_STR_REGISTER + V810_ADTRE: sprintf(info->s, "ADTRE:%08X", cpustate->ADTRE); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(V810, v810);
diff --git a/trunk/src/emu/cpu/v810/v810.h b/trunk/src/emu/cpu/v810/v810.h
new file mode 100644
index 00000000000..bbca2c59424
--- /dev/null
+++ b/trunk/src/emu/cpu/v810/v810.h
@@ -0,0 +1,83 @@
+#pragma once
+
+#ifndef __V810_H__
+#define __V810_H__
+
+
+DECLARE_LEGACY_CPU_DEVICE(V810, v810);
+
+CPU_DISASSEMBLE( v810 );
+
+enum
+{
+ V810_R0=1,
+ V810_R1,
+ V810_R2, /* R2 - handler stack pointer */
+ V810_SP, /* R3 - stack pointer */
+ V810_R4, /* R4 - global pointer */
+ V810_R5, /* R5 - text pointer */
+ V810_R6,
+ V810_R7,
+ V810_R8,
+ V810_R9,
+ V810_R10,
+ V810_R11,
+ V810_R12,
+ V810_R13,
+ V810_R14,
+ V810_R15,
+ V810_R16,
+ V810_R17,
+ V810_R18,
+ V810_R19,
+ V810_R20,
+ V810_R21,
+ V810_R22,
+ V810_R23,
+ V810_R24,
+ V810_R25,
+ V810_R26,
+ V810_R27,
+ V810_R28,
+ V810_R29,
+ V810_R30,
+ V810_R31, /* R31 - link pointer */
+
+ /* System Registers */
+ V810_EIPC, /* Exception/interrupt saving - PC */
+ V810_EIPSW,/* Exception/interrupt saving - PSW */
+ V810_FEPC, /* Duplexed exception/NMI saving - PC */
+ V810_FEPSW,/* Duplexed exception/NMI saving - PSW */
+ V810_ECR, /* Exception cause register */
+ V810_PSW, /* Program status word */
+ V810_PIR, /* Processor ID register */
+ V810_TKCW, /* Task control word */
+ V810_res08,
+ V810_res09,
+ V810_res10,
+ V810_res11,
+ V810_res12,
+ V810_res13,
+ V810_res14,
+ V810_res15,
+ V810_res16,
+ V810_res17,
+ V810_res18,
+ V810_res19,
+ V810_res20,
+ V810_res21,
+ V810_res22,
+ V810_res23,
+ V810_CHCW, /* Cache control word */
+ V810_ADTRE, /* Address trap register */
+ V810_res26,
+ V810_res27,
+ V810_res28,
+ V810_res29,
+ V810_res30,
+ V810_res31,
+
+ V810_PC
+};
+
+#endif /* __V810_H__ */
diff --git a/trunk/src/emu/cpu/v810/v810dasm.c b/trunk/src/emu/cpu/v810/v810dasm.c
new file mode 100644
index 00000000000..3503ae09a83
--- /dev/null
+++ b/trunk/src/emu/cpu/v810/v810dasm.c
@@ -0,0 +1,176 @@
+/********************************************
+ NEC V810 (upd70732) disassembler
+ Tomasz Slanina - analog[at]op.pl
+*******************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "v810.h"
+
+#define I5(x) (((x)&0x1f)|(((x)&0x10)?0xffffffe0:0))
+#define UI5(x) ((x)&0x1f)
+#define I16(x) (((x)&0xffff)|(((x)&0x8000)?0xffff0000:0))
+#define UI16(x) ((x)&0xffff)
+#define D16(x) (((x)&0xffff)|(((x)&0x8000)?0xffff0000:0))
+#define D26(x,y) ((y)|((x&0x3ff)<<16 )|((x&0x200)?0xfc000000:0))
+#define D9(x) ((x&0x1ff)|((x&0x100)?0xfffffe00:0))
+
+static const char *const dRegs[]=
+{
+"R0","R1","R2","SP","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",
+"EIPC","EIPSW","FEPC","FEPSW","ECR",
+"PSW","PIR","TKCW","<Unk>","<Unk>",
+"<Unk>","<Unk>","<Unk>","<Unk>","<Unk>",
+"<Unk>","<Unk>","<Unk>","<Unk>","<Unk>",
+"<Unk>","<Unk>","<Unk>","<Unk>","CHCW","ADTRE",
+"<Unk>","<Unk>","<Unk>","<Unk>","<Unk>","<Unk>"
+};
+
+#define GET1s(opcode) dRegs[(opcode)&0x1f]
+#define GET2s(opcode) dRegs[((opcode)>>5)&0x1f]
+#define GETRs(opcode) dRegs[32+((opcode)&0x1f)]
+
+CPU_DISASSEMBLE( v810 )
+{
+ UINT32 flags = 0;
+ UINT32 opc,opc2;
+ unsigned size;
+ opc = oprom[0] | (oprom[1] << 8);
+ opc2 = oprom[2] | (oprom[3] << 8);
+
+ switch(opc>>10)
+ {
+ case 0x00: sprintf(buffer,"MOV %s,%s",GET1s(opc),GET2s(opc)); size=2; break;
+ case 0x01: sprintf(buffer,"ADD %s,%s",GET1s(opc),GET2s(opc)); size=2; break;
+ case 0x02: sprintf(buffer,"SUB %s,%s",GET1s(opc),GET2s(opc)); size=2; break;
+ case 0x03: sprintf(buffer,"CMP %s,%s",GET1s(opc),GET2s(opc)); size=2; break;
+ case 0x04: sprintf(buffer,"SHL %s,%s",GET1s(opc),GET2s(opc)); size=2; break;
+ case 0x05: sprintf(buffer,"SHR %s,%s",GET1s(opc),GET2s(opc)); size=2; break;
+ case 0x06: sprintf(buffer,"JMP [%s]",GET1s(opc)); size=2; if ((opc&0x1f) == 31) flags = DASMFLAG_STEP_OUT; break;
+ case 0x07: sprintf(buffer,"SAR %s,%s",GET1s(opc),GET2s(opc)); size=2; break;
+ case 0x08: sprintf(buffer,"MUL %s,%s",GET1s(opc),GET2s(opc)); size=2; break;
+ case 0x09: sprintf(buffer,"DIV %s,%s",GET1s(opc),GET2s(opc)); size=2; break;
+ case 0x0a: sprintf(buffer,"MULU %s,%s",GET1s(opc),GET2s(opc)); size=2; break;
+ case 0x0b: sprintf(buffer,"DIVU %s,%s",GET1s(opc),GET2s(opc)); size=2; break;
+ case 0x0c: sprintf(buffer,"OR %s,%s",GET1s(opc),GET2s(opc)); size=2; break;
+ case 0x0d: sprintf(buffer,"AND %s,%s",GET1s(opc),GET2s(opc)); size=2; break;
+ case 0x0e: sprintf(buffer,"XOR %s,%s",GET1s(opc),GET2s(opc)); size=2; break;
+ case 0x0f: sprintf(buffer,"NOT %s,%s",GET1s(opc),GET2s(opc)); size=2; break;
+ case 0x10: sprintf(buffer,"MOV %X,%s",I5(opc),GET2s(opc)); size=2; break;
+ case 0x11: sprintf(buffer,"ADD %X,%s",I5(opc),GET2s(opc)); size=2; break;
+ case 0x12: sprintf(buffer,"SETF %X,%s",I5(opc),GET2s(opc)); size=2; break;
+ case 0x13: sprintf(buffer,"CMP %X,%s",I5(opc),GET2s(opc)); size=2; break;
+ case 0x14: sprintf(buffer,"SHL %X,%s",UI5(opc),GET2s(opc)); size=2; break;
+ case 0x15: sprintf(buffer,"SHR %X,%s",UI5(opc),GET2s(opc)); size=2; break;
+ case 0x16: sprintf(buffer,"EI"); size=2; break;
+ case 0x17: sprintf(buffer,"SAR %X,%s",UI5(opc),GET2s(opc)); size=2; break;
+ case 0x18: sprintf(buffer,"TRAP %X",I5(opc)); size=2; break;
+ case 0x19: sprintf(buffer,"RETI"); size=2; flags = DASMFLAG_STEP_OUT; break;
+ case 0x1a: sprintf(buffer,"HALT"); size=2; break;
+ case 0x1b: sprintf(buffer,"Unk 0x1B"); size=2; break;
+ case 0x1c: sprintf(buffer,"LDSR %s,%s",GET2s(opc),GETRs(opc));size=2; break;
+ case 0x1d: sprintf(buffer,"STSR %s,%s",GETRs(opc),GET2s(opc));size=2; break;
+ case 0x1e: sprintf(buffer,"DI"); size=2; break;
+ case 0x1f:
+ switch(opc&0x1f)
+ {
+ case 0x00: sprintf(buffer,"SCH0BSU"); break;
+ case 0x01: sprintf(buffer,"SCH0BSD"); break;
+ case 0x02: sprintf(buffer,"SCH1BSU"); break;
+ case 0x03: sprintf(buffer,"SCH1BSD"); break;
+ case 0x04: sprintf(buffer,"UnkS 4"); break;
+ case 0x05: sprintf(buffer,"UnkS 5"); break;
+ case 0x06: sprintf(buffer,"UnkS 6"); break;
+ case 0x08: sprintf(buffer,"ORBSU"); break;
+ case 0x09: sprintf(buffer,"ANDBSU"); break;
+ case 0x0a: sprintf(buffer,"XORBSU"); break;
+ case 0x0b: sprintf(buffer,"MOVBSU"); break;
+ case 0x0c: sprintf(buffer,"ORNBSU"); break;
+ case 0x0d: sprintf(buffer,"ANDNBSU"); break;
+ case 0x0e: sprintf(buffer,"XORNBSU"); break;
+ case 0x0f: sprintf(buffer,"NOTBSU"); break;
+ default: sprintf(buffer,"UnkBS 0x%X",opc&0x1f); break;
+ }
+ size=2;
+ break;
+ case 0x20:
+ case 0x21:
+ case 0x22:
+ case 0x23:
+ case 0x24:
+ case 0x25:
+ case 0x26:
+ case 0x27: switch( (opc>>9) &0xf)
+ {
+ case 0x0: sprintf(buffer,"BV %X",pc+D9(opc)); break;
+ case 0x1: sprintf(buffer,"BL %X",pc+D9(opc)); break;
+ case 0x2: sprintf(buffer,"BE %X",pc+D9(opc)); break;
+ case 0x3: sprintf(buffer,"BNH %X",pc+D9(opc)); break;
+ case 0x4: sprintf(buffer,"BN %X",pc+D9(opc)); break;
+ case 0x5: sprintf(buffer,"BR %X",pc+D9(opc)); break;
+ case 0x6: sprintf(buffer,"BLT %X",pc+D9(opc)); break;
+ case 0x7: sprintf(buffer,"BLE %X",pc+D9(opc)); break;
+ case 0x8: sprintf(buffer,"BNV %X",pc+D9(opc)); break;
+ case 0x9: sprintf(buffer,"BNL %X",pc+D9(opc)); break;
+ case 0xa: sprintf(buffer,"BNE %X",pc+D9(opc)); break;
+ case 0xb: sprintf(buffer,"BH %X",pc+D9(opc)); break;
+ case 0xc: sprintf(buffer,"BP %X",pc+D9(opc)); break;
+ case 0xd: sprintf(buffer,"NOP"); break;
+ case 0xe: sprintf(buffer,"BGE %X",pc+D9(opc)); break;
+ case 0xf: sprintf(buffer,"BGT %X",pc+D9(opc)); break;
+ }
+ size=2;
+ break;
+
+ case 0x28: sprintf(buffer,"MOVEA %X, %s, %s",I16(opc2),GET1s(opc),GET2s(opc));size=4; break;
+ case 0x29: sprintf(buffer,"ADDI %X, %s, %s",I16(opc2),GET1s(opc),GET2s(opc));size=4; break;
+ case 0x2a: sprintf(buffer,"JR %X",pc+D26(opc,opc2));size=4; break;
+ case 0x2b: sprintf(buffer,"JAL %X",pc+D26(opc,opc2));size=4; flags = DASMFLAG_STEP_OVER; break;
+ case 0x2c: sprintf(buffer,"ORI %X, %s, %s",UI16(opc2),GET1s(opc),GET2s(opc));size=4; break;
+ case 0x2d: sprintf(buffer,"ANDI %X, %s, %s",UI16(opc2),GET1s(opc),GET2s(opc));size=4; break;
+ case 0x2e: sprintf(buffer,"XORI %X, %s, %s",UI16(opc2),GET1s(opc),GET2s(opc));size=4; break;
+ case 0x2f: sprintf(buffer,"MOVHI %X, %s, %s",UI16(opc2),GET1s(opc),GET2s(opc));size=4; break;
+ case 0x30: sprintf(buffer,"LDB %X[%s], %s",D16(opc2),GET1s(opc),GET2s(opc));size=4; break;
+ case 0x31: sprintf(buffer,"LDH %X[%s], %s",D16(opc2),GET1s(opc),GET2s(opc));size=4; break;
+ case 0x32: sprintf(buffer,"Unk 0x32"); size=2; break;
+ case 0x33: sprintf(buffer,"LDW %X[%s], %s",D16(opc2),GET1s(opc),GET2s(opc));size=4; break;
+ case 0x34: sprintf(buffer,"STB %s, %X[%s]",GET2s(opc),D16(opc2),GET1s(opc));size=4; break;
+ case 0x35: sprintf(buffer,"STH %s, %X[%s]",GET2s(opc),D16(opc2),GET1s(opc));size=4; break;
+ case 0x36: sprintf(buffer,"Unk 0x36"); size=2; break;
+ case 0x37: sprintf(buffer,"STW %s, %X[%s]",GET2s(opc),D16(opc2),GET1s(opc));size=4; break;
+ case 0x38: sprintf(buffer,"INB %X[%s], %s",D16(opc2),GET1s(opc),GET2s(opc));size=4; break;
+ case 0x39: sprintf(buffer,"INH %X[%s], %s",D16(opc2),GET1s(opc),GET2s(opc));size=4; break;
+ case 0x3a: sprintf(buffer,"CAXI %X[%s], %s",D16(opc2),GET1s(opc),GET2s(opc));size=4; break;
+ case 0x3b: sprintf(buffer,"INW %X[%s], %s",D16(opc2),GET1s(opc),GET2s(opc));size=4; break;
+
+ case 0x3c: sprintf(buffer,"OUTB %s, %X[%s]",GET2s(opc),D16(opc2),GET1s(opc));size=4; break;
+ case 0x3d: sprintf(buffer,"OUTH %s, %X[%s]",GET2s(opc),D16(opc2),GET1s(opc));size=4; break;
+ case 0x3e:
+ switch((opc2&0xfc00)>>10)
+ {
+ case 0x0: sprintf(buffer,"CMPF.S %s, %s",GET1s(opc),GET2s(opc)); break;
+ case 0x2: sprintf(buffer,"CVT.WS %s, %s",GET1s(opc),GET2s(opc)); break;
+ case 0x3: sprintf(buffer,"CVT.SW %s, %s",GET1s(opc),GET2s(opc)); break;
+ case 0x4: sprintf(buffer,"ADDF.S %s, %s",GET1s(opc),GET2s(opc)); break;
+ case 0x5: sprintf(buffer,"SUBF.S %s, %s",GET1s(opc),GET2s(opc)); break;
+ case 0x6: sprintf(buffer,"MULF.S %s, %s",GET1s(opc),GET2s(opc)); break;
+ case 0x7: sprintf(buffer,"DIVF.S %s, %s",GET1s(opc),GET2s(opc)); break;
+ case 0xb: sprintf(buffer,"TRNC.SW %s, %s",GET1s(opc),GET2s(opc)); break;
+ default : sprintf(buffer,"Unkf 0x%X",(opc2&0xfc00)>>10); break;
+ }
+ size=4;
+ break;
+ case 0x3f: sprintf(buffer,"OUTW %s, %X[%s]",GET2s(opc),D16(opc2),GET1s(opc));size=4; break;
+
+ default : size=2;
+ }
+ return size | flags | DASMFLAG_SUPPORTED;
+}
+
diff --git a/trunk/src/emu/cpu/vtlb.c b/trunk/src/emu/cpu/vtlb.c
new file mode 100644
index 00000000000..4e364f59011
--- /dev/null
+++ b/trunk/src/emu/cpu/vtlb.c
@@ -0,0 +1,287 @@
+/***************************************************************************
+
+ vtlb.c
+
+ Generic virtual TLB implementation.
+
+ Copyright Aaron Giles
+ Released for general non-commercial use under the MAME license
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "vtlb.h"
+
+
+
+/***************************************************************************
+ DEBUGGING
+***************************************************************************/
+
+#define PRINTF_TLB (0)
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/* VTLB state */
+struct _vtlb_state
+{
+ cpu_device * cpudevice; /* CPU device */
+ address_spacenum space; /* address space */
+ int dynamic; /* number of dynamic entries */
+ int fixed; /* number of fixed entries */
+ int dynindex; /* index of next dynamic entry */
+ int pageshift; /* bits to shift to get page index */
+ int addrwidth; /* logical address bus width */
+ offs_t * live; /* array of live entries by table index */
+ int * fixedpages; /* number of pages each fixed entry covers */
+ vtlb_entry * table; /* table of entries by address */
+ vtlb_entry * save; /* cache of live table entries for saving */
+};
+
+
+
+/***************************************************************************
+ INITIALIZATION/TEARDOWN
+***************************************************************************/
+
+/*-------------------------------------------------
+ vtlb_alloc - allocate a new VTLB for the
+ given CPU
+-------------------------------------------------*/
+
+vtlb_state *vtlb_alloc(device_t *cpu, address_spacenum space, int fixed_entries, int dynamic_entries)
+{
+ vtlb_state *vtlb;
+
+ /* allocate memory for the core structure */
+ vtlb = auto_alloc_clear(cpu->machine(), vtlb_state);
+
+ /* fill in CPU information */
+ vtlb->cpudevice = downcast<cpu_device *>(cpu);
+ vtlb->space = space;
+ vtlb->dynamic = dynamic_entries;
+ vtlb->fixed = fixed_entries;
+ const address_space_config *spaceconfig = device_get_space_config(*cpu, space);
+ assert(spaceconfig != NULL);
+ vtlb->pageshift = spaceconfig->m_page_shift;
+ vtlb->addrwidth = spaceconfig->m_logaddr_width;
+
+ /* validate CPU information */
+ assert((1 << vtlb->pageshift) > VTLB_FLAGS_MASK);
+ assert(vtlb->addrwidth > vtlb->pageshift);
+
+ /* allocate the entry array */
+ vtlb->live = auto_alloc_array_clear(cpu->machine(), offs_t, fixed_entries + dynamic_entries);
+ cpu->save_pointer(NAME(vtlb->live), fixed_entries + dynamic_entries, space);
+
+ /* allocate the lookup table */
+ vtlb->table = auto_alloc_array_clear(cpu->machine(), vtlb_entry, (size_t) 1 << (vtlb->addrwidth - vtlb->pageshift));
+ cpu->save_pointer(NAME(vtlb->table), 1 << (vtlb->addrwidth - vtlb->pageshift), space);
+
+ /* allocate the fixed page count array */
+ if (fixed_entries > 0)
+ {
+ vtlb->fixedpages = auto_alloc_array_clear(cpu->machine(), int, fixed_entries);
+ cpu->save_pointer(NAME(vtlb->fixedpages), fixed_entries, space);
+ }
+ return vtlb;
+}
+
+
+/*-------------------------------------------------
+ vtlb_free - free an allocated VTLB
+-------------------------------------------------*/
+
+void vtlb_free(vtlb_state *vtlb)
+{
+ /* free the fixed pages if allocated */
+ if (vtlb->fixedpages != NULL)
+ auto_free(vtlb->cpudevice->machine(), vtlb->fixedpages);
+
+ /* free the table and array if they exist */
+ if (vtlb->live != NULL)
+ auto_free(vtlb->cpudevice->machine(), vtlb->live);
+ if (vtlb->table != NULL)
+ auto_free(vtlb->cpudevice->machine(), vtlb->table);
+
+ /* and then the VTLB object itself */
+ auto_free(vtlb->cpudevice->machine(), vtlb);
+}
+
+
+
+/***************************************************************************
+ FILLING
+***************************************************************************/
+
+/*-------------------------------------------------
+ vtlb_fill - rcalled by the CPU core in
+ response to an unmapped access
+-------------------------------------------------*/
+
+int vtlb_fill(vtlb_state *vtlb, offs_t address, int intention)
+{
+ offs_t tableindex = address >> vtlb->pageshift;
+ vtlb_entry entry = vtlb->table[tableindex];
+ offs_t taddress;
+
+ if (PRINTF_TLB)
+ printf("vtlb_fill: %08X(%X) ... ", address, intention);
+
+ /* should not be called here if the entry is in the table already */
+// assert((entry & (1 << intention)) == 0);
+
+ /* if we have no dynamic entries, we always fail */
+ if (vtlb->dynamic == 0)
+ {
+ if (PRINTF_TLB)
+ printf("failed: no dynamic entries\n");
+ return FALSE;
+ }
+
+ /* ask the CPU core to translate for us */
+ taddress = address;
+ if (!vtlb->cpudevice->translate(vtlb->space, intention, taddress))
+ {
+ if (PRINTF_TLB)
+ printf("failed: no translation\n");
+ return FALSE;
+ }
+
+ /* if this is the first successful translation for this address, allocate a new entry */
+ if ((entry & VTLB_FLAGS_MASK) == 0)
+ {
+ int liveindex = vtlb->dynindex++ % vtlb->dynamic;
+
+ /* if an entry already exists at this index, free it */
+ if (vtlb->live[liveindex] != 0)
+ vtlb->table[vtlb->live[liveindex] - 1] = 0;
+
+ /* claim this new entry */
+ vtlb->live[liveindex] = tableindex + 1;
+
+ /* form a new blank entry */
+ entry = (taddress >> vtlb->pageshift) << vtlb->pageshift;
+ entry |= VTLB_FLAG_VALID;
+
+ if (PRINTF_TLB)
+ printf("success (%08X), new entry\n", taddress);
+ }
+
+ /* otherwise, ensure that different intentions do not produce different addresses */
+ else
+ {
+ assert((entry >> vtlb->pageshift) == (taddress >> vtlb->pageshift));
+ assert(entry & VTLB_FLAG_VALID);
+
+ if (PRINTF_TLB)
+ printf("success (%08X), existing entry\n", taddress);
+ }
+
+ /* add the intention to the list of valid intentions and store */
+ entry |= 1 << (intention & (TRANSLATE_TYPE_MASK | TRANSLATE_USER_MASK));
+ vtlb->table[tableindex] = entry;
+ return TRUE;
+}
+
+
+/*-------------------------------------------------
+ vtlb_load - load a fixed VTLB entry
+-------------------------------------------------*/
+
+void vtlb_load(vtlb_state *vtlb, int entrynum, int numpages, offs_t address, vtlb_entry value)
+{
+ offs_t tableindex = address >> vtlb->pageshift;
+ int liveindex = vtlb->dynamic + entrynum;
+ int pagenum;
+
+ /* must be in range */
+ assert(entrynum >= 0 && entrynum < vtlb->fixed);
+
+ if (PRINTF_TLB)
+ printf("vtlb_load %d for %d pages at %08X == %08X\n", entrynum, numpages, address, value);
+
+ /* if an entry already exists at this index, free it */
+ if (vtlb->live[liveindex] != 0)
+ {
+ int pagecount = vtlb->fixedpages[entrynum];
+ int oldtableindex = vtlb->live[liveindex] - 1;
+ for (pagenum = 0; pagenum < pagecount; pagenum++)
+ vtlb->table[oldtableindex + pagenum] = 0;
+ }
+
+ /* claim this new entry */
+ vtlb->live[liveindex] = tableindex + 1;
+
+ /* store the raw value, making sure the "fixed" flag is set */
+ value |= VTLB_FLAG_FIXED;
+ vtlb->fixedpages[entrynum] = numpages;
+ for (pagenum = 0; pagenum < numpages; pagenum++)
+ vtlb->table[tableindex + pagenum] = value + (pagenum << vtlb->pageshift);
+}
+
+
+
+/***************************************************************************
+ FLUSHING
+***************************************************************************/
+
+/*-------------------------------------------------
+ vtlb_flush_dynamic - flush all knowledge
+ from the dynamic part of the VTLB
+-------------------------------------------------*/
+
+void vtlb_flush_dynamic(vtlb_state *vtlb)
+{
+ int liveindex;
+
+ if (PRINTF_TLB)
+ printf("vtlb_flush_dynamic\n");
+
+ /* loop over live entries and release them from the table */
+ for (liveindex = 0; liveindex < vtlb->dynamic; liveindex++)
+ if (vtlb->live[liveindex] != 0)
+ {
+ offs_t tableindex = vtlb->live[liveindex] - 1;
+ vtlb->table[tableindex] = 0;
+ vtlb->live[liveindex] = 0;
+ }
+}
+
+
+/*-------------------------------------------------
+ vtlb_flush_address - flush knowledge of a
+ particular address from the VTLB
+-------------------------------------------------*/
+
+void vtlb_flush_address(vtlb_state *vtlb, offs_t address)
+{
+ offs_t tableindex = address >> vtlb->pageshift;
+
+ if (PRINTF_TLB)
+ printf("vtlb_flush_address %08X\n", address);
+
+ /* free the entry in the table; for speed, we leave the entry in the live array */
+ vtlb->table[tableindex] = 0;
+}
+
+
+
+/***************************************************************************
+ ACCESSORS
+***************************************************************************/
+
+/*-------------------------------------------------
+ vtlb_table - return a pointer to the base of
+ the linear VTLB lookup table
+-------------------------------------------------*/
+
+const vtlb_entry *vtlb_table(vtlb_state *vtlb)
+{
+ return vtlb->table;
+}
diff --git a/trunk/src/emu/cpu/vtlb.h b/trunk/src/emu/cpu/vtlb.h
new file mode 100644
index 00000000000..3777668fa99
--- /dev/null
+++ b/trunk/src/emu/cpu/vtlb.h
@@ -0,0 +1,88 @@
+/***************************************************************************
+
+ vtlb.h
+
+ Generic virtual TLB implementation.
+
+ 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 __VTLB_H__
+#define __VTLB_H__
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define VTLB_FLAGS_MASK 0xff
+
+#define VTLB_READ_ALLOWED 0x01 /* (1 << TRANSLATE_READ) */
+#define VTLB_WRITE_ALLOWED 0x02 /* (1 << TRANSLATE_WRITE) */
+#define VTLB_FETCH_ALLOWED 0x04 /* (1 << TRANSLATE_FETCH) */
+#define VTLB_FLAG_VALID 0x08
+#define VTLB_USER_READ_ALLOWED 0x10 /* (1 << TRANSLATE_READ_USER) */
+#define VTLB_USER_WRITE_ALLOWED 0x20 /* (1 << TRANSLATE_WRITE_USER) */
+#define VTLB_USER_FETCH_ALLOWED 0x40 /* (1 << TRANSLATE_FETCH_USER) */
+#define VTLB_FLAG_FIXED 0x80
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/* represents an entry in the VTLB */
+typedef UINT32 vtlb_entry;
+
+
+/* opaque structure describing VTLB state */
+typedef struct _vtlb_state vtlb_state;
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+
+/* ----- initialization/teardown ----- */
+
+/* allocate a new VTLB for the given CPU */
+vtlb_state *vtlb_alloc(device_t *cpu, address_spacenum space, int fixed_entries, int dynamic_entries);
+
+/* free an allocated VTLB */
+void vtlb_free(vtlb_state *vtlb);
+
+
+/* ----- filling ----- */
+
+/* called by the CPU core in response to an unmapped access */
+int vtlb_fill(vtlb_state *vtlb, offs_t address, int intention);
+
+/* load a fixed VTLB entry */
+void vtlb_load(vtlb_state *vtlb, int entrynum, int numpages, offs_t address, vtlb_entry value);
+
+
+/* ----- flushing ----- */
+
+/* flush all knowledge from the dynamic part of the VTLB */
+void vtlb_flush_dynamic(vtlb_state *vtlb);
+
+/* flush knowledge of a particular address from the VTLB */
+void vtlb_flush_address(vtlb_state *vtlb, offs_t address);
+
+
+/* ----- accessors ----- */
+
+/* return a pointer to the base of the linear VTLB lookup table */
+const vtlb_entry *vtlb_table(vtlb_state *vtlb);
+
+
+#endif /* __VTLB_H__ */
diff --git a/trunk/src/emu/cpu/x86emit.h b/trunk/src/emu/cpu/x86emit.h
new file mode 100644
index 00000000000..7d4129d0def
--- /dev/null
+++ b/trunk/src/emu/cpu/x86emit.h
@@ -0,0 +1,3218 @@
+/***************************************************************************
+
+ x86emit.h
+
+ Generic x86/x64 code emitters.
+
+****************************************************************************
+
+ 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:
+
+ It is assumed in 64-bit mode that all byte register accesses are
+ intended to be to the low 8 bits (SPL,BPL,SIL,DIL) and not to the
+ upper half (AH,CH,DH,BH).
+
+***************************************************************************/
+
+
+//**************************************************************************
+// SHARED DEFINITIONS
+//**************************************************************************
+
+#ifndef __X86EMIT_H__
+#define __X86EMIT_H__
+
+// use x86code * to reference generated code
+typedef UINT8 x86code;
+
+// this structure tracks information about a link
+struct emit_link
+{
+ x86code * target;
+ UINT8 size;
+};
+
+// structure for describing memory references
+class x86_memref
+{
+public:
+ x86_memref(UINT8 basereg, UINT8 indreg, UINT8 scale, INT32 disp)
+ : m_base(basereg),
+ m_index(indreg),
+ m_scale(scale),
+ m_disp(disp) { }
+
+ x86_memref operator+(INT32 offset) { return x86_memref(m_base, m_index, m_scale, m_disp + offset); }
+
+ UINT8 m_base;
+ UINT8 m_index;
+ UINT8 m_scale;
+ INT32 m_disp;
+};
+
+#endif
+
+
+
+//**************************************************************************
+// 32-BIT and 64-BIT SPECIFIC DEFINITIONS
+//**************************************************************************
+
+#ifdef X86EMIT_SIZE
+
+#if (X86EMIT_SIZE != 32 && X86EMIT_SIZE != 64)
+#error Must specify X86EMIT_SIZE as either 32 or 64!
+#endif
+
+// put emitters into their own namespace so they don't clash
+#if (X86EMIT_SIZE == 32)
+namespace x86emit
+#else
+namespace x64emit
+#endif
+{
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// opcode size flag; low 4 bits must match REX low 4 bits, hence the odd numbers here
+const UINT8 OP_16BIT = 0x10;
+const UINT8 OP_32BIT = 0x00;
+const UINT8 OP_64BIT = 0x08;
+
+// 16 registers on x64, only 8 on x86
+#if (X86EMIT_SIZE == 64)
+const int REG_MAX = 16;
+#else
+const int REG_MAX = 8;
+#endif
+
+// invalid register index for "none"
+const UINT8 REG_NONE = REG_MAX;
+
+// 8-bit registers -- note that we assume a flat model for 64-bit
+const UINT8 REG_AL = 0;
+const UINT8 REG_CL = 1;
+const UINT8 REG_DL = 2;
+const UINT8 REG_BL = 3;
+#if (X86EMIT_SIZE == 32)
+const UINT8 REG_AH = 4;
+const UINT8 REG_CH = 5;
+const UINT8 REG_DH = 6;
+const UINT8 REG_BH = 7;
+#else
+const UINT8 REG_SPL = 4;
+const UINT8 REG_BPL = 5;
+const UINT8 REG_SIL = 6;
+const UINT8 REG_DIL = 7;
+const UINT8 REG_R8L = 8;
+const UINT8 REG_R9L = 9;
+const UINT8 REG_R10L = 10;
+const UINT8 REG_R11L = 11;
+const UINT8 REG_R12L = 12;
+const UINT8 REG_R13L = 13;
+const UINT8 REG_R14L = 14;
+const UINT8 REG_R15L = 15;
+#endif
+
+// 16-bit registers
+const UINT8 REG_AX = 0;
+const UINT8 REG_CX = 1;
+const UINT8 REG_DX = 2;
+const UINT8 REG_BX = 3;
+const UINT8 REG_SP = 4;
+const UINT8 REG_BP = 5;
+const UINT8 REG_SI = 6;
+const UINT8 REG_DI = 7;
+#if (X86EMIT_SIZE == 64)
+const UINT8 REG_R8W = 8;
+const UINT8 REG_R9W = 9;
+const UINT8 REG_R10W = 10;
+const UINT8 REG_R11W = 11;
+const UINT8 REG_R12W = 12;
+const UINT8 REG_R13W = 13;
+const UINT8 REG_R14W = 14;
+const UINT8 REG_R15W = 15;
+#endif
+
+// 32-bit registers
+const UINT8 REG_EAX = 0;
+const UINT8 REG_ECX = 1;
+const UINT8 REG_EDX = 2;
+const UINT8 REG_EBX = 3;
+const UINT8 REG_ESP = 4;
+const UINT8 REG_EBP = 5;
+const UINT8 REG_ESI = 6;
+const UINT8 REG_EDI = 7;
+#if (X86EMIT_SIZE == 64)
+const UINT8 REG_R8D = 8;
+const UINT8 REG_R9D = 9;
+const UINT8 REG_R10D = 10;
+const UINT8 REG_R11D = 11;
+const UINT8 REG_R12D = 12;
+const UINT8 REG_R13D = 13;
+const UINT8 REG_R14D = 14;
+const UINT8 REG_R15D = 15;
+#endif
+
+// 64-bit registers
+#if (X86EMIT_SIZE == 64)
+const UINT8 REG_RAX = 0;
+const UINT8 REG_RCX = 1;
+const UINT8 REG_RDX = 2;
+const UINT8 REG_RBX = 3;
+const UINT8 REG_RSP = 4;
+const UINT8 REG_RBP = 5;
+const UINT8 REG_RSI = 6;
+const UINT8 REG_RDI = 7;
+const UINT8 REG_R8 = 8;
+const UINT8 REG_R9 = 9;
+const UINT8 REG_R10 = 10;
+const UINT8 REG_R11 = 11;
+const UINT8 REG_R12 = 12;
+const UINT8 REG_R13 = 13;
+const UINT8 REG_R14 = 14;
+const UINT8 REG_R15 = 15;
+#endif
+
+// 64-bit MMX registers
+const UINT8 REG_MM0 = 0;
+const UINT8 REG_MM1 = 1;
+const UINT8 REG_MM2 = 2;
+const UINT8 REG_MM3 = 3;
+const UINT8 REG_MM4 = 4;
+const UINT8 REG_MM5 = 5;
+const UINT8 REG_MM6 = 6;
+const UINT8 REG_MM7 = 7;
+#if (X86EMIT_SIZE == 64)
+const UINT8 REG_MM8 = 8;
+const UINT8 REG_MM9 = 9;
+const UINT8 REG_MM10 = 10;
+const UINT8 REG_MM11 = 11;
+const UINT8 REG_MM12 = 12;
+const UINT8 REG_MM13 = 13;
+const UINT8 REG_MM14 = 14;
+const UINT8 REG_MM15 = 15;
+#endif
+
+// 128-bit XMM registers
+const UINT8 REG_XMM0 = 0;
+const UINT8 REG_XMM1 = 1;
+const UINT8 REG_XMM2 = 2;
+const UINT8 REG_XMM3 = 3;
+const UINT8 REG_XMM4 = 4;
+const UINT8 REG_XMM5 = 5;
+const UINT8 REG_XMM6 = 6;
+const UINT8 REG_XMM7 = 7;
+#if (X86EMIT_SIZE == 64)
+const UINT8 REG_XMM8 = 8;
+const UINT8 REG_XMM9 = 9;
+const UINT8 REG_XMM10 = 10;
+const UINT8 REG_XMM11 = 11;
+const UINT8 REG_XMM12 = 12;
+const UINT8 REG_XMM13 = 13;
+const UINT8 REG_XMM14 = 14;
+const UINT8 REG_XMM15 = 15;
+#endif
+
+// conditions
+const UINT8 COND_A = 7;
+const UINT8 COND_AE = 3;
+const UINT8 COND_B = 2;
+const UINT8 COND_BE = 6;
+const UINT8 COND_C = 2;
+const UINT8 COND_E = 4;
+const UINT8 COND_Z = 4;
+const UINT8 COND_G = 15;
+const UINT8 COND_GE = 13;
+const UINT8 COND_L = 12;
+const UINT8 COND_LE = 14;
+const UINT8 COND_NA = 6;
+const UINT8 COND_NAE = 2;
+const UINT8 COND_NB = 3;
+const UINT8 COND_NBE = 7;
+const UINT8 COND_NC = 3;
+const UINT8 COND_NE = 5;
+const UINT8 COND_NG = 14;
+const UINT8 COND_NGE = 12;
+const UINT8 COND_NL = 13;
+const UINT8 COND_NLE = 15;
+const UINT8 COND_NO = 1;
+const UINT8 COND_NP = 11;
+const UINT8 COND_NS = 9;
+const UINT8 COND_NZ = 5;
+const UINT8 COND_O = 0;
+const UINT8 COND_P = 10;
+const UINT8 COND_PE = 10;
+const UINT8 COND_PO = 11;
+const UINT8 COND_S = 8;
+
+// floating point rounding modes
+const UINT8 FPRND_NEAR = 0;
+const UINT8 FPRND_DOWN = 1;
+const UINT8 FPRND_UP = 2;
+const UINT8 FPRND_CHOP = 3;
+
+
+
+//**************************************************************************
+// OPCODE DEFINITIONS
+//**************************************************************************
+
+// opcode flags (in upper 8 bits of opcode)
+const UINT32 OPFLAG_8BITREG = (1 << 24);
+const UINT32 OPFLAG_8BITRM = (1 << 25);
+
+// single byte opcodes
+const UINT32 OP_ADD_Eb_Gb = (0x00 | OPFLAG_8BITRM | OPFLAG_8BITREG);
+const UINT32 OP_ADD_Ev_Gv = 0x01;
+const UINT32 OP_ADD_Gb_Eb = (0x02 | OPFLAG_8BITRM | OPFLAG_8BITREG);
+const UINT32 OP_ADD_Gv_Ev = 0x03;
+const UINT32 OP_ADD_AL_Ib = 0x04;
+const UINT32 OP_ADD_rAX_Iz = 0x05;
+const UINT32 OP_PUSH_ES = 0x06;
+const UINT32 OP_POP_ES = 0x07;
+const UINT32 OP_OR_Eb_Gb = (0x08 | OPFLAG_8BITRM | OPFLAG_8BITREG);
+const UINT32 OP_OR_Ev_Gv = 0x09;
+const UINT32 OP_OR_Gb_Eb = (0x0a | OPFLAG_8BITRM | OPFLAG_8BITREG);
+const UINT32 OP_OR_Gv_Ev = 0x0b;
+const UINT32 OP_OR_AL_Ib = 0x0c;
+const UINT32 OP_OR_eAX_Iv = 0x0d;
+const UINT32 OP_PUSH_CS = 0x0e;
+const UINT32 OP_EXTENDED = 0x0f;
+
+const UINT32 OP_ADC_Eb_Gb = (0x10 | OPFLAG_8BITRM | OPFLAG_8BITREG);
+const UINT32 OP_ADC_Ev_Gv = 0x11;
+const UINT32 OP_ADC_Gb_Eb = (0x12 | OPFLAG_8BITRM | OPFLAG_8BITREG);
+const UINT32 OP_ADC_Gv_Ev = 0x13;
+const UINT32 OP_ADC_AL_Ib = 0x14;
+const UINT32 OP_ADC_rAX_Iz = 0x15;
+const UINT32 OP_PUSH_SS = 0x16;
+const UINT32 OP_POP_SS = 0x17;
+const UINT32 OP_SBB_Eb_Gb = (0x18 | OPFLAG_8BITRM | OPFLAG_8BITREG);
+const UINT32 OP_SBB_Ev_Gv = 0x19;
+const UINT32 OP_SBB_Gb_Eb = (0x1a | OPFLAG_8BITRM | OPFLAG_8BITREG);
+const UINT32 OP_SBB_Gv_Ev = 0x1b;
+const UINT32 OP_SBB_AL_Ib = 0x1c;
+const UINT32 OP_SBB_eAX_Iv = 0x1d;
+const UINT32 OP_PUSH_DS = 0x1e;
+const UINT32 OP_POP_DS = 0x1f;
+
+const UINT32 OP_AND_Eb_Gb = (0x20 | OPFLAG_8BITRM | OPFLAG_8BITREG);
+const UINT32 OP_AND_Ev_Gv = 0x21;
+const UINT32 OP_AND_Gb_Eb = (0x22 | OPFLAG_8BITRM | OPFLAG_8BITREG);
+const UINT32 OP_AND_Gv_Ev = 0x23;
+const UINT32 OP_AND_AL_Ib = 0x24;
+const UINT32 OP_AND_rAX_Iz = 0x25;
+const UINT32 PREFIX_ES = 0x26;
+const UINT32 OP_DAA = 0x27;
+const UINT32 OP_SUB_Eb_Gb = (0x28 | OPFLAG_8BITRM | OPFLAG_8BITREG);
+const UINT32 OP_SUB_Ev_Gv = 0x29;
+const UINT32 OP_SUB_Gb_Eb = (0x2a | OPFLAG_8BITRM | OPFLAG_8BITREG);
+const UINT32 OP_SUB_Gv_Ev = 0x2b;
+const UINT32 OP_SUB_AL_Ib = 0x2c;
+const UINT32 OP_SUB_eAX_Iv = 0x2d;
+const UINT32 PREFIX_CS = 0x2e;
+const UINT32 OP_DAS = 0x2f;
+
+const UINT32 OP_XOR_Eb_Gb = (0x30 | OPFLAG_8BITRM | OPFLAG_8BITREG);
+const UINT32 OP_XOR_Ev_Gv = 0x31;
+const UINT32 OP_XOR_Gb_Eb = (0x32 | OPFLAG_8BITRM | OPFLAG_8BITREG);
+const UINT32 OP_XOR_Gv_Ev = 0x33;
+const UINT32 OP_XOR_AL_Ib = 0x34;
+const UINT32 OP_XOR_rAX_Iz = 0x35;
+const UINT32 PREFIX_SS = 0x36;
+const UINT32 OP_AAA = 0x37;
+const UINT32 OP_CMP_Eb_Gb = (0x38 | OPFLAG_8BITRM | OPFLAG_8BITREG);
+const UINT32 OP_CMP_Ev_Gv = 0x39;
+const UINT32 OP_CMP_Gb_Eb = (0x3a | OPFLAG_8BITRM | OPFLAG_8BITREG);
+const UINT32 OP_CMP_Gv_Ev = 0x3b;
+const UINT32 OP_CMP_AL_Ib = 0x3c;
+const UINT32 OP_CMP_eAX_Iv = 0x3d;
+const UINT32 PREFIX_DS = 0x3e;
+const UINT32 OP_AAS = 0x3f;
+
+const UINT32 OP_REX = 0x40;
+const UINT32 OP_REX_B = 0x41;
+const UINT32 OP_REX_X = 0x42;
+const UINT32 OP_REX_XB = 0x43;
+const UINT32 OP_REX_R = 0x44;
+const UINT32 OP_REX_RB = 0x45;
+const UINT32 OP_REX_RX = 0x46;
+const UINT32 OP_REX_RXB = 0x47;
+const UINT32 OP_REX_W = 0x48;
+const UINT32 OP_REX_WB = 0x49;
+const UINT32 OP_REX_WX = 0x4a;
+const UINT32 OP_REX_WXB = 0x4b;
+const UINT32 OP_REX_WR = 0x4c;
+const UINT32 OP_REX_WRB = 0x4d;
+const UINT32 OP_REX_WRX = 0x4e;
+const UINT32 OP_REX_WRXB = 0x4f;
+
+const UINT32 OP_PUSH_rAX = 0x50;
+const UINT32 OP_PUSH_rCX = 0x51;
+const UINT32 OP_PUSH_rDX = 0x52;
+const UINT32 OP_PUSH_rBX = 0x53;
+const UINT32 OP_PUSH_rSP = 0x54;
+const UINT32 OP_PUSH_rBP = 0x55;
+const UINT32 OP_PUSH_rSI = 0x56;
+const UINT32 OP_PUSH_rDI = 0x57;
+const UINT32 OP_POP_rAX = 0x58;
+const UINT32 OP_POP_rCX = 0x59;
+const UINT32 OP_POP_rDX = 0x5a;
+const UINT32 OP_POP_rBX = 0x5b;
+const UINT32 OP_POP_rSP = 0x5c;
+const UINT32 OP_POP_rBP = 0x5d;
+const UINT32 OP_POP_rSI = 0x5e;
+const UINT32 OP_POP_rDI = 0x5f;
+
+const UINT32 OP_PUSHA = 0x60;
+const UINT32 OP_POPA = 0x61;
+const UINT32 OP_BOUND_Gv_Ma = 0x62;
+const UINT32 OP_ARPL_Ew_Gw = 0x63;
+const UINT32 OP_MOVSXD_Gv_Ev = 0x63;
+const UINT32 PREFIX_FS = 0x64;
+const UINT32 PREFIX_GS = 0x65;
+const UINT32 PREFIX_OPSIZE = 0x66;
+const UINT32 PREFIX_ADSIZE = 0x67;
+const UINT32 OP_PUSH_Iz = 0x68;
+const UINT32 OP_IMUL_Gv_Ev_Iz = 0x69;
+const UINT32 OP_PUSH_Ib = 0x6a;
+const UINT32 OP_IMUL_Gv_Ev_Ib = 0x6b;
+const UINT32 OP_INS_Yb_DX = 0x6c;
+const UINT32 OP_INS_Yz_DX = 0x6d;
+const UINT32 OP_OUTS_DX_Xb = 0x6e;
+const UINT32 OP_OUTS_DX_Xz = 0x6f;
+
+const UINT32 OP_JCC_O_Jb = 0x70;
+const UINT32 OP_JCC_NO_Jb = 0x71;
+const UINT32 OP_JCC_B_Jb = 0x72;
+const UINT32 OP_JCC_C_Jb = 0x72;
+const UINT32 OP_JCC_NAE_Jb = 0x72;
+const UINT32 OP_JCC_AE_Jb = 0x73;
+const UINT32 OP_JCC_NB_Jb = 0x73;
+const UINT32 OP_JCC_NC_Jb = 0x73;
+const UINT32 OP_JCC_E_Jb = 0x74;
+const UINT32 OP_JCC_Z_Jb = 0x74;
+const UINT32 OP_JCC_NE_Jb = 0x75;
+const UINT32 OP_JCC_NZ_Jb = 0x75;
+const UINT32 OP_JCC_BE_Jb = 0x76;
+const UINT32 OP_JCC_NA_Jb = 0x76;
+const UINT32 OP_JCC_A_Jb = 0x77;
+const UINT32 OP_JCC_NBE_Jb = 0x77;
+const UINT32 OP_JCC_S_Jb = 0x78;
+const UINT32 OP_JCC_NS_Jb = 0x79;
+const UINT32 OP_JCC_P_Jb = 0x7a;
+const UINT32 OP_JCC_PE_Jb = 0x7a;
+const UINT32 OP_JCC_NP_Jb = 0x7b;
+const UINT32 OP_JCC_PO_Jb = 0x7b;
+const UINT32 OP_JCC_L_Jb = 0x7c;
+const UINT32 OP_JCC_NGE_Jb = 0x7c;
+const UINT32 OP_JCC_NL_Jb = 0x7d;
+const UINT32 OP_JCC_GE_Jb = 0x7d;
+const UINT32 OP_JCC_LE_Jb = 0x7e;
+const UINT32 OP_JCC_NG_Jb = 0x7e;
+const UINT32 OP_JCC_NLE_Jb = 0x7f;
+const UINT32 OP_JCC_G_Jb = 0x7f;
+
+const UINT32 OP_G1_Eb_Ib = (0x80 | OPFLAG_8BITRM);
+const UINT32 OP_G1_Ev_Iz = 0x81;
+const UINT32 OP_G1_Eb_Ibx = (0x82 | OPFLAG_8BITRM);
+const UINT32 OP_G1_Ev_Ib = 0x83;
+const UINT32 OP_TEST_Eb_Gb = (0x84 | OPFLAG_8BITRM | OPFLAG_8BITREG);
+const UINT32 OP_TEST_Ev_Gv = 0x85;
+const UINT32 OP_XCHG_Eb_Gb = (0x86 | OPFLAG_8BITRM | OPFLAG_8BITREG);
+const UINT32 OP_XCHG_Ev_Gv = 0x87;
+const UINT32 OP_MOV_Eb_Gb = (0x88 | OPFLAG_8BITRM | OPFLAG_8BITREG);
+const UINT32 OP_MOV_Ev_Gv = 0x89;
+const UINT32 OP_MOV_Gb_Eb = (0x8a | OPFLAG_8BITRM | OPFLAG_8BITREG);
+const UINT32 OP_MOV_Gv_Ev = 0x8b;
+const UINT32 OP_MOV_Ev_Sw = 0x8c;
+const UINT32 OP_LEA_Gv_M = 0x8d;
+const UINT32 OP_MOV_Sw_Ew = 0x8e;
+const UINT32 OP_G1A_Ev = 0x8f;
+
+const UINT32 OP_NOP = 0x90;
+const UINT32 OP_PAUSE = 0x90;
+const UINT32 OP_XCHG_rCX = 0x91;
+const UINT32 OP_XCHG_rDX = 0x92;
+const UINT32 OP_XCHG_rBX = 0x93;
+const UINT32 OP_XCHG_rSP = 0x94;
+const UINT32 OP_XCHG_rBP = 0x95;
+const UINT32 OP_XCHG_rSI = 0x96;
+const UINT32 OP_XCHG_rDI = 0x97;
+const UINT32 OP_CBW = 0x98;
+const UINT32 OP_CWDE = 0x98;
+const UINT32 OP_CDQE = 0x98;
+const UINT32 OP_CWD = 0x99;
+const UINT32 OP_CDQ = 0x99;
+const UINT32 OP_CQO = 0x99;
+const UINT32 OP_CALLF_Ap = 0x9a;
+const UINT32 OP_FWAIT = 0x9b;
+const UINT32 OP_PUSHF_Fv = 0x9c;
+const UINT32 OP_POPF_Fv = 0x9d;
+const UINT32 OP_SAHF = 0x9e;
+const UINT32 OP_LAHF = 0x9f;
+
+const UINT32 OP_MOV_AL_Ob = 0xa0;
+const UINT32 OP_MOV_rAX_Ov = 0xa1;
+const UINT32 OP_MOV_Ob_AL = 0xa2;
+const UINT32 OP_MOV_Ov_rAX = 0xa3;
+const UINT32 OP_MOVS_Xb_Yb = 0xa4;
+const UINT32 OP_MOVS_Xv_Yv = 0xa5;
+const UINT32 OP_CMPS_Xb_Yb = 0xa6;
+const UINT32 OP_CMPS_Xv_Yv = 0xa7;
+const UINT32 OP_TEST_AL_Ib = 0xa8;
+const UINT32 OP_TEST_rAX_Iz = 0xa9;
+const UINT32 OP_STOS_Yb_AL = 0xaa;
+const UINT32 OP_STOS_Yv_rAX = 0xab;
+const UINT32 OP_LODS_AL_Xb = 0xac;
+const UINT32 OP_LODS_rAX_Xv = 0xad;
+const UINT32 OP_SCAS_AL_Yb = 0xae;
+const UINT32 OP_SCAC_rAX_Yv = 0xaf;
+
+const UINT32 OP_MOV_AL_Ib = 0xb0;
+const UINT32 OP_MOV_CL_Ib = 0xb1;
+const UINT32 OP_MOV_DL_Ib = 0xb2;
+const UINT32 OP_MOV_BL_Ib = 0xb3;
+const UINT32 OP_MOV_AH_Ib = 0xb4;
+const UINT32 OP_MOV_CH_Ib = 0xb5;
+const UINT32 OP_MOV_DH_Ib = 0xb6;
+const UINT32 OP_MOV_BH_Ib = 0xb7;
+const UINT32 OP_MOV_rAX_Iv = 0xb8;
+const UINT32 OP_MOV_rCX_Iv = 0xb9;
+const UINT32 OP_MOV_rDX_Iv = 0xba;
+const UINT32 OP_MOV_rBX_Iv = 0xbb;
+const UINT32 OP_MOV_rSP_Iv = 0xbc;
+const UINT32 OP_MOV_rBP_Iv = 0xbd;
+const UINT32 OP_MOV_rSI_Iv = 0xbe;
+const UINT32 OP_MOV_rDI_Iv = 0xbf;
+
+const UINT32 OP_G2_Eb_Ib = (0xc0 | OPFLAG_8BITRM);
+const UINT32 OP_G2_Ev_Ib = 0xc1;
+const UINT32 OP_RETN_Iw = 0xc2;
+const UINT32 OP_RETN = 0xc3;
+const UINT32 OP_LES_Gz_Mp = 0xc4;
+const UINT32 OP_LDS_Gz_Mp = 0xc5;
+const UINT32 OP_G11_Eb_Ib = (0xc6 | OPFLAG_8BITRM);
+const UINT32 OP_G11_Ev_Iz = 0xc7;
+const UINT32 OP_ENTER_Iw_Ib = 0xc8;
+const UINT32 OP_LEAVE = 0xc9;
+const UINT32 OP_RETF_Iw = 0xca;
+const UINT32 OP_RETF = 0xcb;
+const UINT32 OP_INT_3 = 0xcc;
+const UINT32 OP_INT_Ib = 0xcd;
+const UINT32 OP_INTO = 0xce;
+const UINT32 OP_IRET = 0xcf;
+
+const UINT32 OP_G2_Eb_1 = (0xd0 | OPFLAG_8BITRM);
+const UINT32 OP_G2_Ev_1 = 0xd1;
+const UINT32 OP_G2_Eb_CL = (0xd2 | OPFLAG_8BITRM);
+const UINT32 OP_G2_Ev_CL = 0xd3;
+const UINT32 OP_AAM = 0xd4;
+const UINT32 OP_AAD = 0xd5;
+const UINT32 OP_XLAT = 0xd7;
+const UINT32 OP_ESC_D8 = 0xd8;
+const UINT32 OP_ESC_D9 = 0xd9;
+const UINT32 OP_ESC_DA = 0xda;
+const UINT32 OP_ESC_DB = 0xdb;
+const UINT32 OP_ESC_DC = 0xdc;
+const UINT32 OP_ESC_DD = 0xdd;
+const UINT32 OP_ESC_DE = 0xde;
+const UINT32 OP_ESC_DF = 0xdf;
+
+const UINT32 OP_LOOPNE_Jb = 0xe0;
+const UINT32 OP_LOOPE_Jb = 0xe1;
+const UINT32 OP_LOOP_Jb = 0xe2;
+const UINT32 OP_JrCXZ_Jb = 0xe3;
+const UINT32 OP_IN_AL_Ib = 0xe4;
+const UINT32 OP_IN_eAX_Ib = 0xe5;
+const UINT32 OP_OUT_Ib_AL = 0xe6;
+const UINT32 OP_OUT_Ib_eAX = 0xe7;
+const UINT32 OP_CALL_Jz = 0xe8;
+const UINT32 OP_JMP_Jz = 0xe9;
+const UINT32 OP_JMPF_AP = 0xea;
+const UINT32 OP_JMP_Jb = 0xeb;
+const UINT32 OP_IN_AL_DX = 0xec;
+const UINT32 OP_IN_eAX_D = 0xed;
+const UINT32 OP_OUT_DX_AL = 0xee;
+const UINT32 OP_OUT_DX_eAX = 0xef;
+
+const UINT32 PREFIX_LOCK = 0xf0;
+const UINT32 PREFIX_REPNE = 0xf2;
+const UINT32 PREFIX_REPE = 0xf3;
+const UINT32 OP_HLT = 0xf4;
+const UINT32 OP_CMC = 0xf5;
+const UINT32 OP_G3_Eb = (0xf6 | OPFLAG_8BITRM);
+const UINT32 OP_G3_Ev = 0xf7;
+const UINT32 OP_CLC = 0xf8;
+const UINT32 OP_STC = 0xf9;
+const UINT32 OP_CLI = 0xfa;
+const UINT32 OP_STI = 0xfb;
+const UINT32 OP_CLD = 0xfc;
+const UINT32 OP_STD = 0xfd;
+const UINT32 OP_G4 = 0xfe;
+const UINT32 OP_G5 = 0xff;
+
+
+// double byte opcodes
+const UINT32 OP_G6 = 0x0f00;
+const UINT32 OP_G7 = 0x0f01;
+const UINT32 OP_LAR_Gv_Ew = 0x0f02;
+const UINT32 OP_LSL_Gv_Ew = 0x0f03;
+const UINT32 OP_SYSCALL = 0x0f05;
+const UINT32 OP_CLTS = 0x0f06;
+const UINT32 OP_SYSRET = 0x0f07;
+const UINT32 OP_INVD = 0x0f08;
+const UINT32 OP_WBINVD = 0x0f09;
+const UINT32 OP_UD2 = 0x0f0b;
+const UINT32 OP_NOP0d_Ev = 0x0f0d;
+
+const UINT32 OP_MOVUPS_Vps_Wps = 0x0f10;
+const UINT32 OP_MOVSS_Vss_Wss = 0xf30f10;
+const UINT32 OP_MOVUPD_Vpd_Wpd = 0x660f10;
+const UINT32 OP_MOVSD_Vsd_Wsd = 0xf20f10;
+const UINT32 OP_MOVUPS_Wps_Vps = 0x0f11;
+const UINT32 OP_MOVSS_Wss_Vss = 0xf30f11;
+const UINT32 OP_MOVUPD_Wpd_Vpd = 0x660f11;
+const UINT32 OP_MOVSD_Wsd_Vsd = 0xf20f11;
+const UINT32 OP_MOVLPS_Vq_Mq = 0x0f12;
+const UINT32 OP_MOVLPD_Vq_Mq = 0x660f12;
+const UINT32 OP_MOVHLPS_Vq_Uq = 0x0f12;
+const UINT32 OP_MOVDDUP_Vq_Wq = 0xf20f12;
+const UINT32 OP_MOVSLDUP_Vq_Wq = 0xf30f12;
+const UINT32 OP_MOVLPS_Mq_Vq = 0x0f13;
+const UINT32 OP_MOVLPD_Mq_Vq = 0x660f13;
+const UINT32 OP_UNPCKLPS_Vps_Wq = 0x0f14;
+const UINT32 OP_UNPCKLPD_Vpd_Wq = 0x660f14;
+const UINT32 OP_UNPCKHPS_Vps_Wq = 0x0f15;
+const UINT32 OP_UNPCKHPD_Vpd_Wq = 0x660f15;
+const UINT32 OP_MOVHPS_Vq_Mq = 0x0f16;
+const UINT32 OP_MOVHPD_Vq_Mq = 0x660f16;
+const UINT32 OP_MOVLHPS_Vq_Uq = 0x0f16;
+const UINT32 OP_MOVSHDUP_Vq_Wq = 0xf30f16;
+const UINT32 OP_MOVHPS_Mq_Vq = 0x0f17;
+const UINT32 OP_MOVHPD_Mq_Vq = 0x660f17;
+const UINT32 OP_PREFETCH_G16 = 0x0f18;
+const UINT32 OP_NOP1f_Ev = 0x0f1f;
+
+const UINT32 OP_MOV_Rd_Cd = 0x0f20;
+const UINT32 OP_MOV_Rd_Dd = 0x0f21;
+const UINT32 OP_MOV_Cd_Rd = 0x0f22;
+const UINT32 OP_MOV_Dd_Rd = 0x0f23;
+const UINT32 OP_MOVAPS_Vps_Wps = 0x0f28;
+const UINT32 OP_MOVAPD_Vpd_Wpd = 0x660f28;
+const UINT32 OP_MOVAPS_Wps_Vps = 0x0f29;
+const UINT32 OP_MOVAPD_Wpd_Vpd = 0x660f29;
+const UINT32 OP_CVTPI2PS_Vps_Qq = 0x0f2a;
+const UINT32 OP_CVTSI2SS_Vss_Ed = 0xf30f2a;
+const UINT32 OP_CVTPI2PD_Vpd_Qq = 0x660f2a;
+const UINT32 OP_CVTSI2SD_Vsd_Ed = 0xf20f2a;
+const UINT32 OP_MOVNTPS_Mps_Vps = 0x0f2b;
+const UINT32 OP_MOVNTPD_Mpd_Vpd = 0x660f2b;
+const UINT32 OP_CVTTPS2PI_Pq_Wq = 0x0f2c;
+const UINT32 OP_CVTTSS2SI_Gd_Wss = 0xf30f2c;
+const UINT32 OP_CVTTPD2PI_Pq_Wpd = 0x660f2c;
+const UINT32 OP_CVTTSD2SI_Gd_Wsd = 0xf20f2c;
+const UINT32 OP_CVTPS2PI_Pq_Wq = 0x0f2d;
+const UINT32 OP_CVTSS2SI_Gd_Wss = 0xf30f2d;
+const UINT32 OP_CVTPD2PI_Pq_Wpd = 0x660f2d;
+const UINT32 OP_CVTSD2SI_Gd_Wsd = 0xf20f2d;
+const UINT32 OP_UCOMISS_Vss_Wss = 0x0f2e;
+const UINT32 OP_UCOMISD_Vsd_Wsd = 0x660f2e;
+const UINT32 OP_COMISS_Vss_Wss = 0x0f2f;
+const UINT32 OP_COMISD_Vsd_Wsd = 0x660f2f;
+
+const UINT32 OP_WRMSR = 0x0f30;
+const UINT32 OP_RDTSC = 0x0f31;
+const UINT32 OP_RDMSR = 0x0f32;
+const UINT32 OP_RDPMC = 0x0f33;
+const UINT32 OP_SYSENTER = 0x0f34;
+const UINT32 OP_SYSEXIT = 0x0f35;
+const UINT32 OP_GETSEC = 0x0f37;
+
+const UINT32 OP_CMOV_O_Gv_Ev = 0x0f40;
+const UINT32 OP_CMOV_NO_Gv_Ev = 0x0f41;
+const UINT32 OP_CMOV_B_Gv_Ev = 0x0f42;
+const UINT32 OP_CMOV_C_Gv_Ev = 0x0f42;
+const UINT32 OP_CMOV_AE_Gv_Ev = 0x0f43;
+const UINT32 OP_CMOV_NC_Gv_Ev = 0x0f43;
+const UINT32 OP_CMOV_E_Gv_Ev = 0x0f44;
+const UINT32 OP_CMOV_Z_Gv_Ev = 0x0f44;
+const UINT32 OP_CMOV_NE_Gv_Ev = 0x0f45;
+const UINT32 OP_CMOV_NZ_Gv_Ev = 0x0f45;
+const UINT32 OP_CMOV_BE_Gv_Ev = 0x0f46;
+const UINT32 OP_CMOV_A_Gv_Ev = 0x0f47;
+const UINT32 OP_CMOV_S_Gv_Ev = 0x0f48;
+const UINT32 OP_CMOV_NS_Gv_Ev = 0x0f49;
+const UINT32 OP_CMOV_P_Gv_Ev = 0x0f4a;
+const UINT32 OP_CMOV_PE_Gv_Ev = 0x0f4a;
+const UINT32 OP_CMOV_NP_Gv_Ev = 0x0f4b;
+const UINT32 OP_CMOV_PO_Gv_Ev = 0x0f4b;
+const UINT32 OP_CMOV_L_Gv_Ev = 0x0f4c;
+const UINT32 OP_CMOV_NGE_Gv_Ev = 0x0f4c;
+const UINT32 OP_CMOV_NL_Gv_Ev = 0x0f4d;
+const UINT32 OP_CMOV_GE_Gv_Ev = 0x0f4d;
+const UINT32 OP_CMOV_LE_Gv_Ev = 0x0f4e;
+const UINT32 OP_CMOV_NG_Gv_Ev = 0x0f4e;
+const UINT32 OP_CMOV_NLE_Gv_Ev = 0x0f4f;
+const UINT32 OP_CMOV_G_Gv_Ev = 0x0f4f;
+
+const UINT32 OP_MOVMSKPS_Gd_Ups = 0x0f50;
+const UINT32 OP_MOVMSKPD_Gd_Upd = 0x660f50;
+const UINT32 OP_SQRTPS_Vps_Wps = 0x0f51;
+const UINT32 OP_SQRTSS_Vss_Wss = 0xf30f51;
+const UINT32 OP_SQRTPD_Vpd_Wpd = 0x660f51;
+const UINT32 OP_SQRTSD_Vsd_Wsd = 0xf20f51;
+const UINT32 OP_RSQRTPS_Vps_Wps = 0x0f52;
+const UINT32 OP_RSQRTSS_Vss_Wss = 0xf30f52;
+const UINT32 OP_RCPPS_Vps_Wps = 0x0f53;
+const UINT32 OP_RCPSS_Vss_Wss = 0xf30f53;
+const UINT32 OP_ANDPS_Vps_Wps = 0x0f54;
+const UINT32 OP_ANDPD_Vpd_Wpd = 0x660f54;
+const UINT32 OP_ANDNPS_Vps_Wps = 0x0f55;
+const UINT32 OP_ANDNPD_Vpd_Wpd = 0x660f55;
+const UINT32 OP_ORPS_Vps_Wps = 0x0f56;
+const UINT32 OP_ORPD_Vpd_Wpd = 0x660f56;
+const UINT32 OP_XORPS_Vps_Wps = 0x0f57;
+const UINT32 OP_XORPD_Vpd_Wpd = 0x660f57;
+const UINT32 OP_ADDPS_Vps_Wps = 0x0f58;
+const UINT32 OP_ADDSS_Vss_Wss = 0xf30f58;
+const UINT32 OP_ADDPD_Vpd_Wpd = 0x660f58;
+const UINT32 OP_ADDSD_Vsd_Wsd = 0xf20f58;
+const UINT32 OP_MULPS_Vps_Wps = 0x0f59;
+const UINT32 OP_MULSS_Vss_Wss = 0xf30f59;
+const UINT32 OP_MULPD_Vpd_Wpd = 0x660f59;
+const UINT32 OP_MULSD_Vsd_Wsd = 0xf20f59;
+const UINT32 OP_CVTPS2PD_Vpd_Wq = 0x0f5a;
+const UINT32 OP_CVTSS2SD_Vsd_Wss = 0xf30f5a;
+const UINT32 OP_CVTPD2PS_Vps_Wpd = 0x660f5a;
+const UINT32 OP_CVTSD2SS_Vss_Wsd = 0xf20f5a;
+const UINT32 OP_CVTDQ2PS_Vps_Wdq = 0x0f5b;
+const UINT32 OP_CVTPS2DQ_Vdq_Wps = 0x660f5b;
+const UINT32 OP_CVTTPS2DQ_Vdq_Wps = 0xf30f5b;
+const UINT32 OP_SUBPS_Vps_Wps = 0x0f5c;
+const UINT32 OP_SUBSS_Vss_Wss = 0xf30f5c;
+const UINT32 OP_SUBPD_Vpd_Wpd = 0x660f5c;
+const UINT32 OP_SUBSD_Vsd_Wsd = 0xf20f5c;
+const UINT32 OP_MINPS_Vps_Wps = 0x0f5d;
+const UINT32 OP_MINSS_Vss_Wss = 0xf30f5d;
+const UINT32 OP_MINPD_Vpd_Wpd = 0x660f5d;
+const UINT32 OP_MINSD_Vsd_Wsd = 0xf20f5d;
+const UINT32 OP_DIVPS_Vps_Wps = 0x0f5e;
+const UINT32 OP_DIVSS_Vss_Wss = 0xf30f5e;
+const UINT32 OP_DIVPD_Vpd_Wpd = 0x660f5e;
+const UINT32 OP_DIVSD_Vsd_Wsd = 0xf20f5e;
+const UINT32 OP_MAXPS_Vps_Wps = 0x0f5f;
+const UINT32 OP_MAXSS_Vss_Wss = 0xf30f5f;
+const UINT32 OP_MAXPD_Vpd_Wpd = 0x660f5f;
+const UINT32 OP_MAXSD_Vsd_Wsd = 0xf20f5f;
+
+const UINT32 OP_PUNPCKLBW_Pq_Qd = 0x0f60;
+const UINT32 OP_PUNPCKLBW_Vdq_Wdq = 0x660f60;
+const UINT32 OP_PUNPCKLWD_Pq_Qd = 0x0f61;
+const UINT32 OP_PUNPCKLWD_Vdq_Wdq = 0x660f61;
+const UINT32 OP_PUNPCKLDQ_Pq_Qd = 0x0f62;
+const UINT32 OP_PUNPCKLDQ_Vdq_Wdq = 0x660f62;
+const UINT32 OP_PACKSSWB_Pq_Qq = 0x0f63;
+const UINT32 OP_PACKSSWB_Vdq_Wdq = 0x660f63;
+const UINT32 OP_PCMPGTB_Pq_Qq = 0x0f64;
+const UINT32 OP_PCMPGTB_Vdq_Wdq = 0x660f64;
+const UINT32 OP_PCMPGTW_Pq_Qq = 0x0f65;
+const UINT32 OP_PCMPGTW_Vdq_Wdq = 0x660f65;
+const UINT32 OP_PCMPGTD_Pq_Qq = 0x0f66;
+const UINT32 OP_PCMPGTD_Vdq_Wdq = 0x660f66;
+const UINT32 OP_PACKUSWB_Pq_Qq = 0x0f67;
+const UINT32 OP_PACKUSWB_Vdq_Wdq = 0x660f67;
+const UINT32 OP_PUNPCKHBW_Pq_Qq = 0x0f68;
+const UINT32 OP_PUNPCKHBW_Vdq_Qdq = 0x660f68;
+const UINT32 OP_PUNPCKHWD_Pq_Qq = 0x0f69;
+const UINT32 OP_PUNPCKHWD_Vdq_Qdq = 0x660f69;
+const UINT32 OP_PUNPCKHDQ_Pq_Qq = 0x0f6a;
+const UINT32 OP_PUNPCKHDQ_Vdq_Qdq = 0x660f6a;
+const UINT32 OP_PACKSSDW_Pq_Qq = 0x0f6b;
+const UINT32 OP_PACKSSDW_Vdq_Qdq = 0x660f6b;
+const UINT32 OP_PUNPCKLQDQ_Vdq_Wdq = 0x660f6c;
+const UINT32 OP_PUNPCKHQDQ_Vdq_Wdq = 0x660f6d;
+const UINT32 OP_MOVD_Pd_Ed = 0x0f6e;
+const UINT32 OP_MOVD_Vd_Ed = 0x660f6e;
+const UINT32 OP_MOVQ_Pq_Qq = 0x0f6f;
+const UINT32 OP_MOVDQA_Vdq_Wdq = 0x660f6f;
+const UINT32 OP_MOVDQU_Vdq_Wdq = 0xf30f6f;
+
+const UINT32 OP_PSHUFW_Pq_Qq_Ib = 0x0f70;
+const UINT32 OP_PSHUFD_Vdq_Wdq_Ib = 0x660f70;
+const UINT32 OP_PSHUFHW_Vdq_Wdq_Ib = 0xf30f70;
+const UINT32 OP_PSHUFLW_Vdq_Wdq_Ib = 0xf20f70;
+const UINT32 OP_G12 = 0x0f71;
+const UINT32 OP_G13 = 0x0f72;
+const UINT32 OP_G14 = 0x0f73;
+const UINT32 OP_PCMPEQB_Pq_Qq = 0x0f74;
+const UINT32 OP_PCMPEQB_Vdq_Wdq = 0x660f74;
+const UINT32 OP_PCMPEQW_Pq_Qq = 0x0f75;
+const UINT32 OP_PCMPEQW_Vdq_Wdq = 0x660f75;
+const UINT32 OP_PCMPEQD_Pq_Qq = 0x0f76;
+const UINT32 OP_PCMPEQD_Vdq_Wdq = 0x660f76;
+const UINT32 OP_EMMS = 0x0f77;
+const UINT32 OP_VMREAD_Ed_Gd = 0x0f78;
+const UINT32 OP_VMWRITE_Gd_Ed = 0x0f79;
+const UINT32 OP_HADDPD_Vpd_Wpd = 0x660f7c;
+const UINT32 OP_HADDPS_Vps_Wps = 0xf20f7c;
+const UINT32 OP_HSUBPD_Vpd_Wpd = 0x660f7d;
+const UINT32 OP_HSUBPS_Vps_Wps = 0xf20f7d;
+const UINT32 OP_MOVD_Ed_Pd = 0x0f7e;
+const UINT32 OP_MOVD_Ed_Vd = 0x660f7e;
+const UINT32 OP_MOVQ_Vq_Wq = 0xf30f7e;
+const UINT32 OP_MOVQ_Qq_Pq = 0x0f7f;
+const UINT32 OP_MOVDQA_Wdq_Vdq = 0x660f7f;
+const UINT32 OP_MOVDQU_Wdq_Vdq = 0xf30f7f;
+
+const UINT32 OP_JCC_O_Jv = 0x0f80;
+const UINT32 OP_JCC_NO_Jv = 0x0f81;
+const UINT32 OP_JCC_B_Jv = 0x0f82;
+const UINT32 OP_JCC_C_Jv = 0x0f82;
+const UINT32 OP_JCC_NAE_Jv = 0x0f82;
+const UINT32 OP_JCC_AE_Jv = 0x0f83;
+const UINT32 OP_JCC_NB_Jv = 0x0f83;
+const UINT32 OP_JCC_NC_Jv = 0x0f83;
+const UINT32 OP_JCC_E_Jv = 0x0f84;
+const UINT32 OP_JCC_Z_Jv = 0x0f84;
+const UINT32 OP_JCC_NE_Jv = 0x0f85;
+const UINT32 OP_JCC_NZ_Jv = 0x0f85;
+const UINT32 OP_JCC_BE_Jv = 0x0f86;
+const UINT32 OP_JCC_NA_Jv = 0x0f86;
+const UINT32 OP_JCC_A_Jv = 0x0f87;
+const UINT32 OP_JCC_NBE_Jv = 0x0f87;
+const UINT32 OP_JCC_S_Jv = 0x0f88;
+const UINT32 OP_JCC_NS_Jv = 0x0f89;
+const UINT32 OP_JCC_P_Jv = 0x0f8a;
+const UINT32 OP_JCC_PE_Jv = 0x0f8a;
+const UINT32 OP_JCC_NP_Jv = 0x0f8b;
+const UINT32 OP_JCC_PO_Jv = 0x0f8b;
+const UINT32 OP_JCC_L_Jv = 0x0f8c;
+const UINT32 OP_JCC_NGE_Jv = 0x0f8c;
+const UINT32 OP_JCC_NL_Jv = 0x0f8d;
+const UINT32 OP_JCC_GE_Jv = 0x0f8d;
+const UINT32 OP_JCC_LE_Jv = 0x0f8e;
+const UINT32 OP_JCC_NG_Jv = 0x0f8e;
+const UINT32 OP_JCC_NLE_Jv = 0x0f8f;
+const UINT32 OP_JCC_G_Jv = 0x0f8f;
+
+const UINT32 OP_SETCC_O_Eb = (0x0f90 | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_NO_Eb = (0x0f91 | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_B_Eb = (0x0f92 | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_C_Eb = (0x0f92 | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_NAE_Eb = (0x0f92 | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_AE_Eb = (0x0f93 | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_NB_Eb = (0x0f93 | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_NC_Eb = (0x0f93 | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_E_Eb = (0x0f94 | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_Z_Eb = (0x0f94 | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_NE_Eb = (0x0f95 | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_NZ_Eb = (0x0f95 | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_BE_Eb = (0x0f96 | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_NA_Eb = (0x0f96 | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_A_Eb = (0x0f97 | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_NBE_Eb = (0x0f97 | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_S_Eb = (0x0f98 | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_NS_Eb = (0x0f99 | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_P_Eb = (0x0f9a | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_PE_Eb = (0x0f9a | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_NP_Eb = (0x0f9b | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_PO_Eb = (0x0f9b | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_L_Eb = (0x0f9c | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_NGE_Eb = (0x0f9c | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_NL_Eb = (0x0f9d | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_GE_Eb = (0x0f9d | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_LE_Eb = (0x0f9e | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_NG_Eb = (0x0f9e | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_NLE_Eb = (0x0f9f | OPFLAG_8BITRM);
+const UINT32 OP_SETCC_G_Eb = (0x0f9f | OPFLAG_8BITRM);
+
+const UINT32 OP_PUSH_FS = 0x0fa0;
+const UINT32 OP_POP_FS = 0x0fa1;
+const UINT32 OP_CPUID = 0x0fa2;
+const UINT32 OP_BT_Ev_Gv = 0x0fa3;
+const UINT32 OP_SHLD_Ev_Gv_Ib = 0x0fa4;
+const UINT32 OP_SHLD_Ev_Gv_CL = 0x0fa5;
+const UINT32 OP_PUSH_GS = 0x0fa8;
+const UINT32 OP_POP_GS = 0x0fa9;
+const UINT32 OP_RSM = 0x0faa;
+const UINT32 OP_BTS_Ev_Gv = 0x0fab;
+const UINT32 OP_SHRD_Ev_Gv_Ib = 0x0fac;
+const UINT32 OP_SHRD_Ev_Gv_CL = 0x0fad;
+const UINT32 OP_G16 = 0x0fae;
+const UINT32 OP_IMUL_Gv_Ev = 0x0faf;
+
+const UINT32 OP_CMPXCHG_Eb_Gb = (0x0fb0 | OPFLAG_8BITRM | OPFLAG_8BITREG);
+const UINT32 OP_CMPXCHG_Ev_Gv = 0x0fb1;
+const UINT32 OP_LSS_Mp = 0x0fb2;
+const UINT32 OP_BTR_Ev_Gv = 0x0fb3;
+const UINT32 OP_LFS_Mp = 0x0fb4;
+const UINT32 OP_LGS_Mp = 0x0fb5;
+const UINT32 OP_MOVZX_Gv_Eb = (0x0fb6 | OPFLAG_8BITRM);
+const UINT32 OP_MOVZX_Gv_Ew = 0x0fb7;
+const UINT32 OP_JMPE = 0x0fb8;
+const UINT32 OP_POPCNT_Gv_Ev = 0xf30fb8;
+const UINT32 OP_G10_INVALID = 0x0fb9;
+const UINT32 OP_G8_Ev_Ib = 0x0fba;
+const UINT32 OP_BTC_Ev_Gv = 0x0fbb;
+const UINT32 OP_BSF_Gv_Ev = 0x0fbc;
+const UINT32 OP_BSR_Gv_Ev = 0x0fbd;
+const UINT32 OP_MOVSX_Gv_Eb = (0x0fbe | OPFLAG_8BITRM);
+const UINT32 OP_MOVSX_Gv_Ew = 0x0fbf;
+
+const UINT32 OP_XADD_Eb_Gb = (0x0fc0 | OPFLAG_8BITRM | OPFLAG_8BITREG);
+const UINT32 OP_XADD_Ev_Gv = 0x0fc1;
+const UINT32 OP_CMPPS_Vps_Wps_Ib = 0x0fc2;
+const UINT32 OP_CMPSS_Vss_Wss_Ib = 0xf30fc2;
+const UINT32 OP_CMPPD_Vpd_Wpd_Ib = 0x660fc2;
+const UINT32 OP_CMPSD_Vsd_Wsd_Ib = 0xf20fc2;
+const UINT32 OP_MOVNTI_Md_Gd = 0x0fc3;
+const UINT32 OP_PINSRW_Pw_Ew_Ib = 0x0fc4;
+const UINT32 OP_PINSRW_Vw_Ew_Ib = 0x660fc4;
+const UINT32 OP_PEXTRW_Gw_Pw_Ib = 0x0fc5;
+const UINT32 OP_PEXTRW_Gw_Vw_Ib = 0x660fc5;
+const UINT32 OP_SHUFPS_Vps_Wps_Ib = 0x0fc6;
+const UINT32 OP_SHUFPD_Vpd_Wpd_Ib = 0x660fc6;
+const UINT32 OP_G9 = 0x0fc7;
+const UINT32 OP_BSWAP_EAX = 0x0fc8;
+const UINT32 OP_BSWAP_ECX = 0x0fc9;
+const UINT32 OP_BSWAP_EDX = 0x0fca;
+const UINT32 OP_BSWAP_EBX = 0x0fcb;
+const UINT32 OP_BSWAP_ESP = 0x0fcc;
+const UINT32 OP_BSWAP_EBP = 0x0fcd;
+const UINT32 OP_BSWAP_ESI = 0x0fce;
+const UINT32 OP_BSWAP_EDI = 0x0fcf;
+
+const UINT32 OP_ADDSUBPD_Vpd_Wpd = 0x0fd0;
+const UINT32 OP_ADDSUBPS_Vps_Wps = 0xf20fd0;
+const UINT32 OP_PSRLW_Pq_Qq = 0x0fd1;
+const UINT32 OP_PSRLW_Vdq_Wdq = 0x660fd1;
+const UINT32 OP_PSRLD_Pq_Qq = 0x0fd2;
+const UINT32 OP_PSRLD_Vdq_Wdq = 0x660fd2;
+const UINT32 OP_PSRLQ_Pq_Qq = 0x0fd3;
+const UINT32 OP_PSRLQ_Vdq_Wdq = 0x660fd3;
+const UINT32 OP_PADDQ_Pq_Qq = 0x0fd4;
+const UINT32 OP_PADDQ_Vdq_Wdq = 0x660fd4;
+const UINT32 OP_PMULLW_Pq_Qq = 0x0fd5;
+const UINT32 OP_PMULLW_Vdq_Wdq = 0x660fd5;
+const UINT32 OP_MOVQ_Wq_Vq = 0x0fd6;
+const UINT32 OP_MOVQ2DQ_Vdq_Qq = 0xf30fd6;
+const UINT32 OP_MOVDQ2Q_Pq_Vq = 0xf20fd6;
+const UINT32 OP_PMOVMSKB_Gd_Pq = 0x0fd7;
+const UINT32 OP_PMOVMSKB_Gd_Vdq = 0x660fd7;
+const UINT32 OP_PSUBUSB_Pq_Qq = 0x0fd8;
+const UINT32 OP_PSUBUSB_Vdq_Wdq = 0x660fd8;
+const UINT32 OP_PSUBUSW_Pq_Qq = 0x0fd9;
+const UINT32 OP_PSUBUSW_Vdq_Wdq = 0x660fd9;
+const UINT32 OP_PMINUB_Pq_Qq = 0x0fda;
+const UINT32 OP_PMINUB_Vdq_Wdq = 0x660fda;
+const UINT32 OP_PAND_Pq_Qq = 0x0fdb;
+const UINT32 OP_PAND_Vdq_Wdq = 0x660fdb;
+const UINT32 OP_PADDUSB_Pq_Qq = 0x0fdc;
+const UINT32 OP_PADDUSB_Vdq_Wdq = 0x660fdc;
+const UINT32 OP_PADDUSW_Pq_Qq = 0x0fdd;
+const UINT32 OP_PADDUSW_Vdq_Wdq = 0x660fdd;
+const UINT32 OP_PMAXUB_Pq_Qq = 0x0fde;
+const UINT32 OP_PMAXUB_Vdq_Wdq = 0x660fde;
+const UINT32 OP_PANDN_Pq_Qq = 0x0fdf;
+const UINT32 OP_PANDN_Vdq_Wdq = 0x660fdf;
+
+const UINT32 OP_PAVGB_Pq_Qq = 0x0fe0;
+const UINT32 OP_PAVGB_Vdq_Wdq = 0x660fe0;
+const UINT32 OP_PSRAW_Pq_Qq = 0x0fe1;
+const UINT32 OP_PSRAW_Vdq_Wdq = 0x660fe1;
+const UINT32 OP_PSRAD_Pq_Qq = 0x0fe2;
+const UINT32 OP_PSRAD_Vdq_Wdq = 0x660fe2;
+const UINT32 OP_PAVGW_Pq_Qq = 0x0fe3;
+const UINT32 OP_PAVGW_Vdq_Wdq = 0x660fe3;
+const UINT32 OP_PMULHUW_Pq_Qq = 0x0fe4;
+const UINT32 OP_PMULHUW_Vdq_Wdq = 0x660fe4;
+const UINT32 OP_PMULHW_Pq_Qq = 0x0fe5;
+const UINT32 OP_PMULHW_Vdq_Wdq = 0x660fe5;
+const UINT32 OP_CVTPD2DQ_Vdq_Wpd = 0xf20fe6;
+const UINT32 OP_CVTTPD2DQ_Vdq_Wpd = 0x660fe6;
+const UINT32 OP_CVTDQ2PD_Vpd_Wq = 0xf30fe6;
+const UINT32 OP_MOVNTQ_Mq_Vq = 0x0fe7;
+const UINT32 OP_MOVNTDQ_Mdq_Vdq = 0x660fe7;
+const UINT32 OP_PSUBSB_Pq_Qq = 0x0fe8;
+const UINT32 OP_PSUBSB_Vdq_Wdq = 0x660fe8;
+const UINT32 OP_PSUBSW_Pq_Qq = 0x0fe9;
+const UINT32 OP_PSUBSW_Vdq_Wdq = 0x660fe9;
+const UINT32 OP_PMINSW_Pq_Qq = 0x0fea;
+const UINT32 OP_PMINSW_Vdq_Wdq = 0x660fea;
+const UINT32 OP_POR_Pq_Qq = 0x0feb;
+const UINT32 OP_POR_Vdq_Wdq = 0x660feb;
+const UINT32 OP_PADDSB_Pq_Qq = 0x0fec;
+const UINT32 OP_PADDSB_Vdq_Wdq = 0x660fec;
+const UINT32 OP_PADDSW_Pq_Qq = 0x0fed;
+const UINT32 OP_PADDSW_Vdq_Wdq = 0x660fed;
+const UINT32 OP_PMAXSW_Pq_Qq = 0x0fee;
+const UINT32 OP_PMAXSW_Vdq_Wdq = 0x660fee;
+const UINT32 OP_PXOR_Pq_Qq = 0x0fef;
+const UINT32 OP_PXOR_Vdq_Wdq = 0x660fef;
+
+const UINT32 OP_LDDQU_Vdq_Mdq = 0xf20ff0;
+const UINT32 OP_PSLLW_Pq_Qq = 0x0ff1;
+const UINT32 OP_PSLLW_Vdq_Wdq = 0x660ff1;
+const UINT32 OP_PSLLD_Pq_Qq = 0x0ff2;
+const UINT32 OP_PSLLD_Vdq_Wdq = 0x660ff2;
+const UINT32 OP_PSLLQ_Pq_Qq = 0x0ff3;
+const UINT32 OP_PSLLQ_Vdq_Wdq = 0x660ff3;
+const UINT32 OP_PMULUDQ_Pq_Qq = 0x0ff4;
+const UINT32 OP_PMULUDQ_Vdq_Wdq = 0x660ff4;
+const UINT32 OP_PMADDWD_Pq_Qq = 0x0ff5;
+const UINT32 OP_PMADDWD_Vdq_Wdq = 0x660ff5;
+const UINT32 OP_PSADBW_Pq_Qq = 0x0ff6;
+const UINT32 OP_PSADBW_Vdq_Wdq = 0x660ff6;
+const UINT32 OP_MASKMOVQ_Pq_Qq = 0x0ff7;
+const UINT32 OP_MASKMOVDQU_Vdq_Wdq = 0x660ff7;
+const UINT32 OP_PSUBB_Pq_Qq = 0x0ff8;
+const UINT32 OP_PSUBB_Vdq_Wdq = 0x660ff8;
+const UINT32 OP_PSUBW_Pq_Qq = 0x0ff9;
+const UINT32 OP_PSUBW_Vdq_Wdq = 0x660ff9;
+const UINT32 OP_PSUBD_Pq_Qq = 0x0ffa;
+const UINT32 OP_PSUBD_Vdq_Wdq = 0x660ffa;
+const UINT32 OP_PSUBQ_Pq_Qq = 0x0ffb;
+const UINT32 OP_PSUBQ_Vdq_Wdq = 0x660ffb;
+const UINT32 OP_PADDB_Pq_Qq = 0x0ffc;
+const UINT32 OP_PADDB_Vdq_Wdq = 0x660ffc;
+const UINT32 OP_PADDW_Pq_Qq = 0x0ffd;
+const UINT32 OP_PADDW_Vdq_Wdq = 0x660ffd;
+const UINT32 OP_PADDD_Pq_Qq = 0x0ffe;
+const UINT32 OP_PADDD_Vdq_Wdq = 0x660ffe;
+
+
+// triple byte opcodes (0f 38)
+const UINT32 OP_PSHUFB_Pq_Qq = 0x0f3800;
+const UINT32 OP_PSHUFB_Vdq_Wdq = 0x660f3800;
+const UINT32 OP_PHADDW_Pq_Qq = 0x0f3801;
+const UINT32 OP_PHADDW_Vdq_Wdq = 0x660f3801;
+const UINT32 OP_PHADDD_Pq_Qq = 0x0f3802;
+const UINT32 OP_PHADDD_Vdq_Wdq = 0x660f3802;
+const UINT32 OP_PHADDSW_Pq_Qq = 0x0f3803;
+const UINT32 OP_PHADDSW_Vdq_Wdq = 0x660f3803;
+const UINT32 OP_PMADDUBSW_Pq_Qq = 0x0f3804;
+const UINT32 OP_PMADDUBSW_Vdq_Wdq = 0x660f3804;
+const UINT32 OP_PHSUBW_Pq_Qq = 0x0f3805;
+const UINT32 OP_PHSUBW_Vdq_Wdq = 0x660f3805;
+const UINT32 OP_PHSUBD_Pq_Qq = 0x0f3806;
+const UINT32 OP_PHSUBD_Vdq_Wdq = 0x660f3806;
+const UINT32 OP_PHSUBSW_Pq_Qq = 0x0f3807;
+const UINT32 OP_PHSUBSW_Vdq_Wdq = 0x660f3807;
+const UINT32 OP_PSIGNB_Pq_Qq = 0x0f3808;
+const UINT32 OP_PSIGNB_Vdq_Wdq = 0x660f3808;
+const UINT32 OP_PSIGNW_Pq_Qq = 0x0f3809;
+const UINT32 OP_PSIGNW_Vdq_Wdq = 0x660f3809;
+const UINT32 OP_PSIGND_Pq_Qq = 0x0f380a;
+const UINT32 OP_PSIGND_Vdq_Wdq = 0x660f380a;
+const UINT32 OP_PMULHRSW_Pq_Qq = 0x0f380b;
+const UINT32 OP_PMULHRSW_Vdq_Wdq = 0x660f380b;
+
+const UINT32 OP_PBLENDVB_Vdq_Wdq = 0x660f3810;
+const UINT32 OP_PBLENDVPS_Vdq_Wdq = 0x660f3814;
+const UINT32 OP_PBLENDVPD_Vdq_Wdq = 0x660f3815;
+const UINT32 OP_PTEST_Vdq_Wdq = 0x660f3817;
+const UINT32 OP_PABSB_Pq_Qq = 0x0f381c;
+const UINT32 OP_PABSB_Vdq_Wdq = 0x660f381c;
+const UINT32 OP_PABSW_Pq_Qq = 0x0f381d;
+const UINT32 OP_PABSW_Vdq_Wdq = 0x660f381d;
+const UINT32 OP_PABSD_Pq_Qq = 0x0f381e;
+const UINT32 OP_PABSD_Vdq_Wdq = 0x660f381e;
+
+const UINT32 OP_PMOVSXBW_Vdq_Udq = 0x660f3820;
+const UINT32 OP_PMOVSXBD_Vdq_Udq = 0x660f3821;
+const UINT32 OP_PMOVSXBQ_Vdq_Udq = 0x660f3822;
+const UINT32 OP_PMOVSXWD_Vdq_Udq = 0x660f3823;
+const UINT32 OP_PMOVSXWQ_Vdq_Udq = 0x660f3824;
+const UINT32 OP_PMOVSXDQ_Vdq_Udq = 0x660f3825;
+const UINT32 OP_PMULDQ_Vdq_Udq = 0x660f3828;
+const UINT32 OP_PCMPEQQ_Vdq_Udq = 0x660f3829;
+const UINT32 OP_MOVNTDQA_Vdq_Udq = 0x660f382a;
+const UINT32 OP_PACKUSDW_Vdq_Udq = 0x660f382b;
+
+const UINT32 OP_PMOVZXBW_Vdq_Udq = 0x660f3830;
+const UINT32 OP_PMOVZXBD_Vdq_Udq = 0x660f3831;
+const UINT32 OP_PMOVZXBQ_Vdq_Udq = 0x660f3832;
+const UINT32 OP_PMOVZXWD_Vdq_Udq = 0x660f3833;
+const UINT32 OP_PMOVZXWQ_Vdq_Udq = 0x660f3834;
+const UINT32 OP_PMOVZXDQ_Vdq_Udq = 0x660f3835;
+const UINT32 OP_PMINSB_Vdq_Udq = 0x660f3838;
+const UINT32 OP_PMINSD_Vdq_Udq = 0x660f3839;
+const UINT32 OP_PMINUW_Vdq_Udq = 0x660f383a;
+const UINT32 OP_PMINUD_Vdq_Udq = 0x660f383b;
+const UINT32 OP_PMAXSB_Vdq_Udq = 0x660f383c;
+const UINT32 OP_PMAXSD_Vdq_Udq = 0x660f383d;
+const UINT32 OP_PMAXUW_Vdq_Udq = 0x660f383e;
+const UINT32 OP_PMAXUD_Vdq_Udq = 0x660f383f;
+
+const UINT32 OP_MULLD_Vdq_Wdq = 0x660f3840;
+const UINT32 OP_PHMINPOSUW_Vdq_Wdq = 0x660f3841;
+
+const UINT32 OP_NVEPT_Gd_Mdq = 0x660f3880;
+const UINT32 OP_NVVPID_Gd_Mdq = 0x660f3881;
+
+const UINT32 OP_MOVBE_Gv_Mv = 0x0f38f0;
+const UINT32 OP_CRC32_Gd_Eb = 0xf20f38f0;
+const UINT32 OP_MOVBE_Mv_Gv = 0x0f38f1;
+const UINT32 OP_CRC32_Gd_Ev = 0xf20f38f1;
+
+
+// triple byte opcodes (0f 3a)
+const UINT32 OP_ROUNDPS_Vdq_Wdq_Ib = 0x660f3a08;
+const UINT32 OP_ROUNDPD_Vdq_Wdq_Ib = 0x660f3a09;
+const UINT32 OP_ROUNDSS_Vss_Wss_Ib = 0x660f3a0a;
+const UINT32 OP_ROUNDSD_Vsd_Wsd_Ib = 0x660f3a0b;
+const UINT32 OP_BLENDPS_Vdq_Wdq_Ib = 0x660f3a0c;
+const UINT32 OP_BLENDPD_Vdq_Wdq_Ib = 0x660f3a0d;
+const UINT32 OP_PBLENDW_Vdq_Wdq_Ib = 0x660f3a0e;
+const UINT32 OP_PALIGNR_Pq_Qq_Ib = 0x0f3a0f;
+const UINT32 OP_PALIGNR_Vdq_Wdq_Ib = 0x660f3a0f;
+
+const UINT32 OP_EXTRB_Rd_Vdq_Ib = 0x660f3a14;
+const UINT32 OP_EXTRW_Rd_Vdq_Ib = 0x660f3a15;
+const UINT32 OP_EXTRD_Rd_Vdq_Ib = 0x660f3a16;
+const UINT32 OP_EXTRACTPS_Ed_Vdq_Ib = 0x660f3a17;
+
+const UINT32 OP_PINSRB_Vdq_Rd_Ib = 0x660f3a20;
+const UINT32 OP_INSERTPS_Vdq_Udq_Ib = 0x660f3a21;
+const UINT32 OP_PINSRD_Vdq_Ed_Ib = 0x660f3a22;
+
+const UINT32 OP_DPPS_Vdq_Wdq_Ib = 0x660f3a40;
+const UINT32 OP_DPPD_Vdq_Wdq_Ib = 0x660f3a41;
+const UINT32 OP_MPSADBW_Vdq_Wdq_Ib = 0x660f3a42;
+
+const UINT32 OP_PCMPESTRM_Vdq_Wdq_Ib = 0x660f3a60;
+const UINT32 OP_PCMPESTRI_Vdq_Wdq_Ib = 0x660f3a61;
+const UINT32 OP_PCMPISTRM_Vdq_Wdq_Ib = 0x660f3a62;
+const UINT32 OP_PCMPISTRI_Vdq_Wdq_Ib = 0x660f3a63;
+
+
+// floating point opcodes
+const UINT32 OP_FADD_ST0_STn = 0xd8c0;
+const UINT32 OP_FMUL_ST0_STn = 0xd8c8;
+const UINT32 OP_FCOM_ST0_STn = 0xd8d0;
+const UINT32 OP_FCOMP_ST0_STn = 0xd8d8;
+const UINT32 OP_FSUB_ST0_STn = 0xd8e0;
+const UINT32 OP_FSUBR_ST0_STn = 0xd8e8;
+const UINT32 OP_FDIV_ST0_STn = 0xd8f0;
+const UINT32 OP_FDIVR_ST0_STn = 0xd8f8;
+const UINT32 OP_FLD_ST0_STn = 0xd9c0;
+const UINT32 OP_FXCH_ST0_STn = 0xd9c8;
+const UINT32 OP_FNOP = 0xd9d0;
+const UINT32 OP_FCHS = 0xd9e0;
+const UINT32 OP_FABS = 0xd9e1;
+const UINT32 OP_FTST = 0xd9e4;
+const UINT32 OP_FXAM = 0xd9e5;
+const UINT32 OP_FLD1 = 0xd9e8;
+const UINT32 OP_FLDL2T = 0xd9e9;
+const UINT32 OP_FLDL2E = 0xd9ea;
+const UINT32 OP_FLDPI = 0xd9eb;
+const UINT32 OP_FLDLG2 = 0xd9ec;
+const UINT32 OP_FLDLN2 = 0xd9ed;
+const UINT32 OP_FLDZ = 0xd9ee;
+const UINT32 OP_F2XM1 = 0xd9f0;
+const UINT32 OP_FYL2X = 0xd9f1;
+const UINT32 OP_FPTAN = 0xd9f2;
+const UINT32 OP_FPATAN = 0xd9f3;
+const UINT32 OP_FXTRACT = 0xd9f4;
+const UINT32 OP_FPREM1 = 0xd9f5;
+const UINT32 OP_FDECSTP = 0xd9f6;
+const UINT32 OP_FINCSTP = 0xd9f7;
+const UINT32 OP_FPREM = 0xd9f8;
+const UINT32 OP_FYL2XP1 = 0xd9f9;
+const UINT32 OP_FSQRT = 0xd9fa;
+const UINT32 OP_FSINCOS = 0xd9fb;
+const UINT32 OP_FRNDINT = 0xd9fc;
+const UINT32 OP_FSCALE = 0xd9fd;
+const UINT32 OP_FSIN = 0xd9fe;
+const UINT32 OP_FCOS = 0xd9ff;
+const UINT32 OP_FCMOVB_ST0_STn = 0xdac0;
+const UINT32 OP_FCMOVE_ST0_STn = 0xdac8;
+const UINT32 OP_FCMOVBE_ST0_STn = 0xdad0;
+const UINT32 OP_FCMOVU_ST0_STn = 0xdad8;
+const UINT32 OP_FUCOMPP = 0xdae9;
+const UINT32 OP_FCMOVNB_ST0_STn = 0xdbc0;
+const UINT32 OP_FCMOVNE_ST0_STn = 0xdbc8;
+const UINT32 OP_FCMOVNBE_ST0_STn = 0xdbd0;
+const UINT32 OP_FCMOVNU_ST0_STn = 0xdbd8;
+const UINT32 OP_FCLEX = 0xdbe2;
+const UINT32 OP_FINIT = 0xdbe3;
+const UINT32 OP_FUCOMI_ST0_STn = 0xdbe8;
+const UINT32 OP_FCOMI_ST0_STn = 0xdbf0;
+const UINT32 OP_FADD_STn_ST0 = 0xdcc0;
+const UINT32 OP_FMUL_STn_ST0 = 0xdcc8;
+const UINT32 OP_FSUBR_STn_ST0 = 0xdce0;
+const UINT32 OP_FSUB_STn_ST0 = 0xdce8;
+const UINT32 OP_FDIVR_STn_ST0 = 0xdcf0;
+const UINT32 OP_FDIV_STn_ST0 = 0xdcf8;
+const UINT32 OP_FFREE_STn = 0xddc0;
+const UINT32 OP_FST_STn = 0xddd0;
+const UINT32 OP_FSTP_STn = 0xddd8;
+const UINT32 OP_FUCOM_STn_ST0 = 0xdde0;
+const UINT32 OP_FUCOMP_STn = 0xdde8;
+const UINT32 OP_FADDP_STn_ST0 = 0xdec0;
+const UINT32 OP_FMULP_STn_ST0 = 0xdec8;
+const UINT32 OP_FCOMPP = 0xded9;
+const UINT32 OP_FSUBRP_STn_ST0 = 0xdee0;
+const UINT32 OP_FSUBP_STn_ST0 = 0xdee8;
+const UINT32 OP_FDIVRP_STn_ST0 = 0xdef0;
+const UINT32 OP_FDIVP_STn_ST0 = 0xdef8;
+const UINT32 OP_FSTSW_AX = 0xdfe0;
+const UINT32 OP_FCOMIP_ST0_STn = 0xdff0;
+
+
+
+//**************************************************************************
+// MEMORY REFERENCES
+//**************************************************************************
+
+inline x86_memref MBD(UINT8 base, INT32 disp) { return x86_memref(base, REG_NONE, 1, disp); }
+inline x86_memref MBISD(UINT8 base, UINT8 ind, UINT8 scale, INT32 disp) { return x86_memref(base, ind, scale, disp); }
+
+#if (X86EMIT_SIZE == 32)
+inline x86_memref MABS(const void *mem) { return x86_memref(REG_NONE, REG_NONE, 1, reinterpret_cast<FPTR>(const_cast<void *>(mem))); }
+inline x86_memref MABSI(const void *mem, UINT8 index) { return x86_memref(index, REG_NONE, 1, reinterpret_cast<FPTR>(const_cast<void *>(mem))); }
+inline x86_memref MABSI(const void *mem, UINT8 index, UINT8 scale) { return x86_memref(REG_NONE, index, scale, reinterpret_cast<FPTR>(const_cast<void *>(mem))); }
+#endif
+
+
+
+//**************************************************************************
+// CORE FUNCTIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// make_modrm - assemble a modrm byte from the
+// three components
+//-------------------------------------------------
+
+inline UINT8 make_modrm(UINT8 mode, UINT8 reg, UINT8 rm)
+{
+ assert(mode < 4);
+ assert(reg < REG_MAX);
+ assert(rm < REG_MAX);
+ return (mode << 6) | ((reg & 7) << 3) | (rm & 7);
+}
+
+
+//-------------------------------------------------
+// make_sib - assemble an sib byte from the
+// three components
+//-------------------------------------------------
+
+inline UINT8 make_sib(UINT8 scale, UINT8 index, UINT8 base)
+{
+ static const UINT8 scale_lookup[9] = { 0<<6, 0<<6, 1<<6, 0<<6, 2<<6, 0<<6, 0<<6, 0<<6, 3<<6 };
+ assert(scale == 1 || scale == 2 || scale == 4 || scale == 8);
+ assert(index < REG_MAX);
+ assert(base < REG_MAX);
+ return scale_lookup[scale] | ((index & 7) << 3) | (base & 7);
+}
+
+
+//-------------------------------------------------
+// emit_byte - emit a byte
+//-------------------------------------------------
+
+inline void emit_byte(x86code *&emitptr, UINT8 byte)
+{
+ *((UINT8 *)emitptr) = byte;
+ emitptr += 1;
+}
+
+
+//-------------------------------------------------
+// emit_word - emit a word
+//-------------------------------------------------
+
+inline void emit_word(x86code *&emitptr, UINT16 word)
+{
+ *((UINT16 *)emitptr) = word;
+ emitptr += 2;
+}
+
+
+//-------------------------------------------------
+// emit_dword - emit a dword
+//-------------------------------------------------
+
+inline void emit_dword(x86code *&emitptr, UINT32 dword)
+{
+ *((UINT32 *)emitptr) = dword;
+ emitptr += 4;
+}
+
+
+//-------------------------------------------------
+// emit_qword - emit a dword
+//-------------------------------------------------
+
+inline void emit_qword(x86code *&emitptr, UINT64 qword)
+{
+ *((UINT64 *)emitptr) = qword;
+ emitptr += 8;
+}
+
+
+
+//**************************************************************************
+// GENERIC OPCODE EMITTERS
+//**************************************************************************
+
+//-------------------------------------------------
+// emit_op - emit a 1, 2, or 3-byte opcode,
+// along with any necessary REX prefixes for x64
+//-------------------------------------------------
+
+inline void emit_op(x86code *&emitptr, UINT32 op, UINT8 opsize, UINT8 reg, UINT8 sib, UINT8 rm)
+{
+ if (opsize == OP_16BIT)
+ emit_byte(emitptr, PREFIX_OPSIZE);
+
+#if (X86EMIT_SIZE == 64)
+{
+ UINT8 rex;
+
+ assert(opsize == OP_16BIT || opsize == OP_32BIT || opsize == OP_64BIT);
+
+ rex = (opsize & 8) | ((reg & 8) >> 1) | ((sib & 8) >> 2) | ((rm & 8) >> 3);
+ if (rex != 0 || ((op & OPFLAG_8BITREG) && reg >= 4) || ((op & OPFLAG_8BITRM) && rm >= 4))
+ emit_byte(emitptr, OP_REX + rex);
+}
+#else
+ assert(opsize != OP_64BIT);
+#endif
+
+ if ((op & 0xff0000) != 0)
+ emit_byte(emitptr, op >> 16);
+ if ((op & 0xff00) != 0)
+ emit_byte(emitptr, op >> 8);
+ emit_byte(emitptr, op);
+}
+
+
+//-------------------------------------------------
+// emit_op_simple - emit a simple opcode
+//-------------------------------------------------
+
+inline void emit_op_simple(x86code *&emitptr, UINT32 op, UINT8 opsize)
+{
+ emit_op(emitptr, op, opsize, 0, 0, 0);
+}
+
+
+//-------------------------------------------------
+// emit_op_reg - emit a simple opcode that has
+// a register parameter
+//-------------------------------------------------
+
+inline void emit_op_reg(x86code *&emitptr, UINT32 op, UINT8 opsize, UINT8 reg)
+{
+ emit_op(emitptr, op, opsize, 0, 0, reg);
+}
+
+
+//-------------------------------------------------
+// emit_op_modrm_reg - emit an opcode with a
+// register modrm byte
+//-------------------------------------------------
+
+inline void emit_op_modrm_reg(x86code *&emitptr, UINT32 op, UINT8 opsize, UINT8 reg, UINT8 rm)
+{
+ assert(reg < REG_MAX);
+ assert(rm < REG_MAX);
+
+ emit_op(emitptr, op, opsize, reg, 0, rm);
+ emit_byte(emitptr, make_modrm(3, reg, rm));
+}
+
+
+//-------------------------------------------------
+// emit_op_modrm_mem - emit an opcode with a
+// memory modrm byte
+//-------------------------------------------------
+
+inline void emit_op_modrm_mem(x86code *&emitptr, UINT32 op, UINT8 opsize, UINT8 reg, x86_memref memref)
+{
+ assert(reg < REG_MAX);
+ assert(memref.m_base < REG_MAX || memref.m_base == REG_NONE);
+ assert(memref.m_index < REG_MAX || memref.m_index == REG_NONE);
+
+ // turn off the OPFLAG_8BITRM flag since it only applies to register operands
+ op &= ~OPFLAG_8BITRM;
+
+ // displacement only case
+ if (memref.m_base == REG_NONE && memref.m_index == REG_NONE)
+ {
+#if (X86EMIT_SIZE == 32)
+ emit_op(emitptr, op, opsize, reg, 0, 5);
+ emit_byte(emitptr, make_modrm(0, reg, 5));
+ emit_dword(emitptr, memref.m_disp);
+#else
+ fatalerror("Invalid absolute mode in 64-bits!\n");
+#endif
+ }
+
+ // base only case
+ else if (memref.m_index == REG_NONE && (memref.m_base & 7) != REG_ESP)
+ {
+ emit_op(emitptr, op, opsize, reg, 0, memref.m_base);
+
+ // mode 0 for no offset
+ if (memref.m_disp == 0 && (memref.m_base & 7) != REG_EBP)
+ emit_byte(emitptr, make_modrm(0, reg, memref.m_base));
+
+ // mode 1 for 1-byte offset
+ else if ((INT8)memref.m_disp == memref.m_disp)
+ {
+ emit_byte(emitptr, make_modrm(1, reg, memref.m_base));
+ emit_byte(emitptr, (INT8)memref.m_disp);
+ }
+
+ // mode 2 for 4-byte offset
+ else
+ {
+ emit_byte(emitptr, make_modrm(2, reg, memref.m_base));
+ emit_dword(emitptr, memref.m_disp);
+ }
+ }
+
+ // full BISD case
+ else
+ {
+ assert(memref.m_index != REG_ESP);
+ emit_op(emitptr, op, opsize, reg, memref.m_index, memref.m_base);
+
+ // a "none" index == REG_ESP
+ if (memref.m_index == REG_NONE)
+ memref.m_index = REG_ESP;
+
+ // no base is a special case
+ if (memref.m_base == REG_NONE)
+ {
+ emit_byte(emitptr, make_modrm(0, reg, 4));
+ emit_byte(emitptr, make_sib(memref.m_scale, memref.m_index, REG_EBP));
+ emit_dword(emitptr, memref.m_disp);
+ }
+
+ // mode 0 for no offset
+ else if (memref.m_disp == 0 && (memref.m_base & 7) != REG_EBP)
+ {
+ emit_byte(emitptr, make_modrm(0, reg, 4));
+ emit_byte(emitptr, make_sib(memref.m_scale, memref.m_index, memref.m_base));
+ }
+
+ // mode 1 for 1-byte offset
+ else if ((INT8)memref.m_disp == memref.m_disp)
+ {
+ emit_byte(emitptr, make_modrm(1, reg, 4));
+ emit_byte(emitptr, make_sib(memref.m_scale, memref.m_index, memref.m_base));
+ emit_byte(emitptr, (INT8)memref.m_disp);
+ }
+
+ // mode 2 for 4-byte offset
+ else
+ {
+ emit_byte(emitptr, make_modrm(2, reg, 4));
+ emit_byte(emitptr, make_sib(memref.m_scale, memref.m_index, memref.m_base));
+ emit_dword(emitptr, memref.m_disp);
+ }
+ }
+}
+
+
+
+//**************************************************************************
+// GENERIC OPCODE + IMMEDIATE EMITTERS
+//**************************************************************************
+
+//-------------------------------------------------
+// emit_op_modrm_reg_imm8 - emit an opcode with a
+// register modrm byte and an 8-bit immediate
+//-------------------------------------------------
+
+inline void emit_op_modrm_reg_imm8(x86code *&emitptr, UINT32 op, UINT8 opsize, UINT8 reg, UINT8 rm, UINT8 imm)
+{
+ emit_op_modrm_reg(emitptr, op, opsize, reg, rm);
+ emit_byte(emitptr, imm);
+}
+
+
+//-------------------------------------------------
+// emit_op_modrm_mem_imm8 - emit an opcode with a
+// memory modrm byte and an 8-bit immediate
+//-------------------------------------------------
+
+inline void emit_op_modrm_mem_imm8(x86code *&emitptr, UINT32 op, UINT8 opsize, UINT8 reg, x86_memref memref, UINT8 imm)
+{
+ emit_op_modrm_mem(emitptr, op, opsize, reg, memref);
+ emit_byte(emitptr, imm);
+}
+
+
+//-------------------------------------------------
+// emit_op_modrm_reg_imm16 - emit an opcode with a
+// register modrm byte and a 16-bit immediate
+//-------------------------------------------------
+
+inline void emit_op_modrm_reg_imm16(x86code *&emitptr, UINT32 op, UINT8 opsize, UINT8 reg, UINT8 rm, UINT16 imm)
+{
+ emit_op_modrm_reg(emitptr, op, opsize, reg, rm);
+ emit_word(emitptr, imm);
+}
+
+
+//-------------------------------------------------
+// emit_op_modrm_mem_imm16 - emit an opcode with a
+// memory modrm byte and a 16-bit immediate
+//-------------------------------------------------
+
+inline void emit_op_modrm_mem_imm16(x86code *&emitptr, UINT32 op, UINT8 opsize, UINT8 reg, x86_memref memref, UINT16 imm)
+{
+ emit_op_modrm_mem(emitptr, op, opsize, reg, memref);
+ emit_word(emitptr, imm);
+}
+
+
+//-------------------------------------------------
+// emit_op_modrm_reg_imm816 - emit an opcode with
+// a register modrm byte and an 8-bit or 16-bit
+// immediate
+//-------------------------------------------------
+
+inline void emit_op_modrm_reg_imm816(x86code *&emitptr, UINT32 op8, UINT32 op16, UINT8 opsize, UINT8 reg, UINT8 rm, UINT16 imm)
+{
+ if ((INT8)imm == (INT16)imm)
+ {
+ emit_op_modrm_reg(emitptr, op8, opsize, reg, rm);
+ emit_byte(emitptr, imm);
+ }
+ else
+ {
+ emit_op_modrm_reg(emitptr, op16, opsize, reg, rm);
+ emit_word(emitptr, imm);
+ }
+}
+
+
+//-------------------------------------------------
+// emit_op_modrm_mem_imm816 - emit an opcode with
+// a memory modrm byte and an 8-bit or 16-bit
+// immediate
+//-------------------------------------------------
+
+inline void emit_op_modrm_mem_imm816(x86code *&emitptr, UINT32 op8, UINT32 op16, UINT8 opsize, UINT8 reg, x86_memref memref, UINT16 imm)
+{
+ if ((INT8)imm == (INT16)imm)
+ {
+ emit_op_modrm_mem(emitptr, op8, opsize, reg, memref);
+ emit_byte(emitptr, imm);
+ }
+ else
+ {
+ emit_op_modrm_mem(emitptr, op16, opsize, reg, memref);
+ emit_word(emitptr, imm);
+ }
+}
+
+
+//-------------------------------------------------
+// emit_op_modrm_reg_imm32 - emit an opcode with a
+// register modrm byte and a 32-bit immediate
+//-------------------------------------------------
+
+inline void emit_op_modrm_reg_imm32(x86code *&emitptr, UINT32 op, UINT8 opsize, UINT8 reg, UINT8 rm, UINT32 imm)
+{
+ emit_op_modrm_reg(emitptr, op, opsize, reg, rm);
+ emit_dword(emitptr, imm);
+}
+
+
+//-------------------------------------------------
+// emit_op_modrm_mem_imm32 - emit an opcode with a
+// memory modrm byte and a 32-bit immediate
+//-------------------------------------------------
+
+inline void emit_op_modrm_mem_imm32(x86code *&emitptr, UINT32 op, UINT8 opsize, UINT8 reg, x86_memref memref, UINT32 imm)
+{
+ emit_op_modrm_mem(emitptr, op, opsize, reg, memref);
+ emit_dword(emitptr, imm);
+}
+
+
+//-------------------------------------------------
+// emit_op_modrm_reg_imm832 - emit an opcode with
+// a register modrm byte and an 8-bit or 32-bit
+// immediate
+//-------------------------------------------------
+
+inline void emit_op_modrm_reg_imm832(x86code *&emitptr, UINT32 op8, UINT32 op32, UINT8 opsize, UINT8 reg, UINT8 rm, UINT32 imm)
+{
+ if ((INT8)imm == (INT32)imm)
+ {
+ emit_op_modrm_reg(emitptr, op8, opsize, reg, rm);
+ emit_byte(emitptr, imm);
+ }
+ else
+ {
+ emit_op_modrm_reg(emitptr, op32, opsize, reg, rm);
+ emit_dword(emitptr, imm);
+ }
+}
+
+
+//-------------------------------------------------
+// emit_op_modrm_mem_imm832 - emit an opcode with
+// a memory modrm byte and an 8-bit or 32-bit
+// immediate
+//-------------------------------------------------
+
+inline void emit_op_modrm_mem_imm832(x86code *&emitptr, UINT32 op8, UINT32 op32, UINT8 opsize, UINT8 reg, x86_memref memref, UINT32 imm)
+{
+ if ((INT8)imm == (INT32)imm)
+ {
+ emit_op_modrm_mem(emitptr, op8, opsize, reg, memref);
+ emit_byte(emitptr, imm);
+ }
+ else
+ {
+ emit_op_modrm_mem(emitptr, op32, opsize, reg, memref);
+ emit_dword(emitptr, imm);
+ }
+}
+
+
+
+//**************************************************************************
+// SIMPLE OPCODE EMITTERS
+//**************************************************************************
+
+inline void emit_nop(x86code *&emitptr) { emit_op_simple(emitptr, OP_NOP, OP_32BIT); }
+inline void emit_int_3(x86code *&emitptr) { emit_op_simple(emitptr, OP_INT_3, OP_32BIT); }
+inline void emit_ret(x86code *&emitptr) { emit_op_simple(emitptr, OP_RETN, OP_32BIT); }
+inline void emit_cdq(x86code *&emitptr) { emit_op_simple(emitptr, OP_CDQ, OP_32BIT); }
+inline void emit_clc(x86code *&emitptr) { emit_op_simple(emitptr, OP_CLC, OP_32BIT); }
+inline void emit_stc(x86code *&emitptr) { emit_op_simple(emitptr, OP_STC, OP_32BIT); }
+inline void emit_cmc(x86code *&emitptr) { emit_op_simple(emitptr, OP_CMC, OP_32BIT); }
+inline void emit_pushf(x86code *&emitptr) { emit_op_simple(emitptr, OP_PUSHF_Fv, OP_32BIT); }
+inline void emit_popf(x86code *&emitptr) { emit_op_simple(emitptr, OP_POPF_Fv, OP_32BIT); }
+inline void emit_cpuid(x86code *&emitptr) { emit_op_simple(emitptr, OP_CPUID, OP_32BIT); }
+
+#if (X86EMIT_SIZE == 32)
+inline void emit_pushad(x86code *&emitptr) { emit_op_simple(emitptr, OP_PUSHA, OP_32BIT); }
+inline void emit_popad(x86code *&emitptr) { emit_op_simple(emitptr, OP_POPA, OP_32BIT); }
+inline void emit_lahf(x86code *&emitptr) { emit_op_simple(emitptr, OP_LAHF, OP_32BIT); }
+inline void emit_sahf(x86code *&emitptr) { emit_op_simple(emitptr, OP_SAHF, OP_32BIT); }
+#endif
+
+#if (X86EMIT_SIZE == 64)
+inline void emit_cqo(x86code *&emitptr) { emit_op_simple(emitptr, OP_CQO, OP_64BIT); }
+#endif
+
+
+
+//**************************************************************************
+// CALL/JUMP EMITTERS
+//**************************************************************************
+
+//-------------------------------------------------
+// resolve_link - resolve a link in a jump
+// instruction
+//-------------------------------------------------
+
+inline void resolve_link(x86code *&destptr, const emit_link &linkinfo)
+{
+ INT64 delta = destptr - linkinfo.target;
+ if (linkinfo.size == 1)
+ {
+ assert((INT8)delta == delta);
+ ((INT8 *)linkinfo.target)[-1] = (INT8)delta;
+ }
+ else if (linkinfo.size == 2)
+ {
+ assert((INT16)delta == delta);
+ ((INT16 *)linkinfo.target)[-1] = (INT16)delta;
+ }
+ else
+ {
+ assert((INT32)delta == delta);
+ ((INT32 *)linkinfo.target)[-1] = (INT32)delta;
+ }
+}
+
+
+//-------------------------------------------------
+// emit_call_*
+//-------------------------------------------------
+
+inline void emit_call_link(x86code *&emitptr, emit_link &linkinfo)
+{
+ emit_op_simple(emitptr, OP_CALL_Jz, OP_32BIT);
+ emit_dword(emitptr, 0);
+ linkinfo.target = emitptr;
+ linkinfo.size = 4;
+}
+
+inline void emit_call(x86code *&emitptr, x86code *target)
+{
+ emit_link link;
+ emit_call_link(emitptr, link);
+ resolve_link(target, link);
+}
+
+
+//-------------------------------------------------
+// emit_jmp_*
+//-------------------------------------------------
+
+inline void emit_jmp_short_link(x86code *&emitptr, emit_link &linkinfo)
+{
+ emit_op_simple(emitptr, OP_JMP_Jb, OP_32BIT);
+ emit_byte(emitptr, 0);
+ linkinfo.target = emitptr;
+ linkinfo.size = 1;
+}
+
+inline void emit_jmp_near_link(x86code *&emitptr, emit_link &linkinfo)
+{
+ emit_op_simple(emitptr, OP_JMP_Jz, OP_32BIT);
+ emit_dword(emitptr, 0);
+ linkinfo.target = emitptr;
+ linkinfo.size = 4;
+}
+
+inline void emit_jmp(x86code *&emitptr, x86code *target)
+{
+ INT32 delta = target - (emitptr + 2);
+ emit_link link;
+
+ if ((INT8)delta == delta)
+ emit_jmp_short_link(emitptr, link);
+ else
+ emit_jmp_near_link(emitptr, link);
+ resolve_link(target, link);
+}
+
+
+//-------------------------------------------------
+// emit_jcc_*
+//-------------------------------------------------
+
+inline void emit_jcc_short_link(x86code *&emitptr, UINT8 cond, emit_link &linkinfo)
+{
+ emit_op_simple(emitptr, OP_JCC_O_Jb + cond, OP_32BIT);
+ emit_byte(emitptr, 0);
+ linkinfo.target = emitptr;
+ linkinfo.size = 1;
+}
+
+inline void emit_jcc_near_link(x86code *&emitptr, UINT8 cond, emit_link &linkinfo)
+{
+ emit_op_simple(emitptr, OP_JCC_O_Jv + cond, OP_32BIT);
+ emit_dword(emitptr, 0);
+ linkinfo.target = emitptr;
+ linkinfo.size = 4;
+}
+
+inline void emit_jcc(x86code *&emitptr, UINT8 cond, x86code *target)
+{
+ INT32 delta = emitptr + 2 - target;
+ emit_link link;
+
+ if ((INT8)delta == delta)
+ emit_jcc_short_link(emitptr, cond, link);
+ else
+ emit_jcc_near_link(emitptr, cond, link);
+ resolve_link(target, link);
+}
+
+
+//-------------------------------------------------
+// emit_jecxz_*
+//-------------------------------------------------
+
+inline void emit_jecxz_link(x86code *&emitptr, emit_link &linkinfo)
+{
+ emit_op_simple(emitptr, OP_JrCXZ_Jb, OP_32BIT);
+ emit_byte(emitptr, 0);
+ linkinfo.target = emitptr;
+ linkinfo.size = 1;
+}
+
+inline void emit_jecxz(x86code *&emitptr, x86code *target)
+{
+ emit_link link;
+ emit_jecxz_link(emitptr, link);
+ resolve_link(target, link);
+}
+
+#if (X86EMIT_SIZE == 64)
+
+inline void emit_jrcxz_link(x86code *&emitptr, emit_link &linkinfo)
+{
+ emit_op_simple(emitptr, OP_JrCXZ_Jb, OP_64BIT);
+ emit_byte(emitptr, 0);
+ linkinfo.target = emitptr;
+ linkinfo.size = 1;
+}
+
+inline void emit_jrcxz(x86code *&emitptr, x86code *target)
+{
+ emit_link link;
+ emit_jrcxz_link(emitptr, link);
+ resolve_link(target, link);
+}
+
+#endif
+
+
+//-------------------------------------------------
+// emit_call/jmp_*
+//-------------------------------------------------
+
+#if (X86EMIT_SIZE == 32)
+inline void emit_call_r32(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G5, OP_32BIT, 2, dreg); }
+inline void emit_call_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G5, OP_32BIT, 2, memref); }
+inline void emit_jmp_r32(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G5, OP_32BIT, 4, dreg); }
+inline void emit_jmp_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G5, OP_32BIT, 4, memref); }
+#else
+inline void emit_call_r64(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G5, OP_32BIT, 2, dreg); }
+inline void emit_call_m64(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G5, OP_32BIT, 2, memref); }
+inline void emit_jmp_r64(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G5, OP_32BIT, 4, dreg); }
+inline void emit_jmp_m64(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G5, OP_32BIT, 4, memref); }
+#endif
+
+
+//-------------------------------------------------
+// emit_ret_*
+//-------------------------------------------------
+
+inline void emit_ret_imm(x86code *&emitptr, UINT16 imm)
+{
+ emit_op_simple(emitptr, OP_RETN_Iw, OP_32BIT);
+ emit_word(emitptr, imm);
+}
+
+
+
+//**************************************************************************
+// PUSH/POP EMITTERS
+//**************************************************************************
+
+inline void emit_push_imm(x86code *&emitptr, INT32 imm)
+{
+ if ((INT8)imm == imm)
+ {
+ emit_op_simple(emitptr, OP_PUSH_Ib, OP_32BIT);
+ emit_byte(emitptr, (INT8)imm);
+ }
+ else
+ {
+ emit_op_simple(emitptr, OP_PUSH_Iz, OP_32BIT);
+ emit_dword(emitptr, imm);
+ }
+}
+
+#if (X86EMIT_SIZE == 32)
+
+inline void emit_push_r32(x86code *&emitptr, UINT8 reg) { emit_op_reg(emitptr, OP_PUSH_rAX + (reg & 7), OP_32BIT, reg); }
+inline void emit_push_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G5, OP_32BIT, 6, memref); }
+inline void emit_pop_r32(x86code *&emitptr, UINT8 reg) { emit_op_reg(emitptr, OP_POP_rAX + (reg & 7), OP_32BIT, reg); }
+inline void emit_pop_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G1A_Ev, OP_32BIT, 0, memref); }
+
+#else
+
+inline void emit_push_r64(x86code *&emitptr, UINT8 reg) { emit_op_reg(emitptr, OP_PUSH_rAX + (reg & 7), OP_32BIT, reg); }
+inline void emit_push_m64(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G5, OP_32BIT, 6, memref); }
+inline void emit_pop_r64(x86code *&emitptr, UINT8 reg) { emit_op_reg(emitptr, OP_POP_rAX + (reg & 7), OP_32BIT, reg); }
+inline void emit_pop_m64(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G1A_Ev, OP_32BIT, 0, memref); }
+
+#endif
+
+
+
+//**************************************************************************
+// MOVE EMITTERS
+//**************************************************************************
+
+//-------------------------------------------------
+// emit_mov_r8_*
+//-------------------------------------------------
+
+inline void emit_mov_r8_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm)
+{
+ emit_op_reg(emitptr, OP_MOV_AL_Ib | (dreg & 7), OP_32BIT, dreg);
+ emit_byte(emitptr, imm);
+}
+
+inline void emit_mov_r8_r8(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOV_Gb_Eb, OP_32BIT, dreg, sreg); }
+inline void emit_mov_r8_m8(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MOV_Gb_Eb, OP_32BIT, dreg, memref); }
+inline void emit_mov_m8_r8(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_MOV_Eb_Gb, OP_32BIT, sreg, memref); }
+inline void emit_mov_m8_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_G11_Eb_Ib, OP_32BIT, 0, memref, imm); }
+
+
+//-------------------------------------------------
+// emit_xchg_r8_*
+//-------------------------------------------------
+
+inline void emit_xchg_r8_r8(x86code *&emitptr, UINT8 dreg, UINT8 sreg)
+{
+ if (dreg == REG_EAX)
+ emit_op_reg(emitptr, OP_NOP | (sreg & 7), OP_32BIT, sreg);
+ else if (sreg == REG_EAX)
+ emit_op_reg(emitptr, OP_NOP | (dreg & 7), OP_32BIT, dreg);
+ else
+ emit_op_modrm_reg(emitptr, OP_XCHG_Eb_Gb, OP_32BIT, dreg, sreg);
+}
+
+
+//-------------------------------------------------
+// emit_mov_r16_*
+//-------------------------------------------------
+
+inline void emit_mov_r16_imm(x86code *&emitptr, UINT8 dreg, UINT16 imm)
+{
+ emit_op_reg(emitptr, OP_MOV_rAX_Iv | (dreg & 7), OP_16BIT, dreg);
+ emit_word(emitptr, imm);
+}
+
+inline void emit_mov_r16_r16(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOV_Gv_Ev, OP_16BIT, dreg, sreg); }
+inline void emit_mov_r16_m16(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MOV_Gv_Ev, OP_16BIT, dreg, memref); }
+inline void emit_mov_m16_imm(x86code *&emitptr, x86_memref memref, UINT16 imm) { emit_op_modrm_mem_imm16(emitptr, OP_G11_Ev_Iz, OP_16BIT, 0, memref, imm); }
+inline void emit_mov_m16_r16(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_MOV_Ev_Gv, OP_16BIT, sreg, memref); }
+inline void emit_movsx_r16_r8(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOVSX_Gv_Eb, OP_16BIT, dreg, sreg); }
+inline void emit_movsx_r16_m8(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MOVSX_Gv_Eb, OP_16BIT, dreg, memref); }
+inline void emit_movzx_r16_r8(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOVZX_Gv_Eb, OP_16BIT, dreg, sreg); }
+inline void emit_movzx_r16_m8(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MOVZX_Gv_Eb, OP_16BIT, dreg, memref); }
+inline void emit_cmovcc_r16_r16(x86code *&emitptr, UINT8 cond, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CMOV_O_Gv_Ev + cond, OP_16BIT, dreg, sreg); }
+inline void emit_cmovcc_r16_m16(x86code *&emitptr, UINT8 cond, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CMOV_O_Gv_Ev + cond, OP_16BIT, dreg, memref); }
+
+
+//-------------------------------------------------
+// emit_xchg_r16_*
+//-------------------------------------------------
+
+inline void emit_xchg_r16_r16(x86code *&emitptr, UINT8 dreg, UINT8 sreg)
+{
+ if (dreg == REG_EAX)
+ emit_op_reg(emitptr, OP_NOP | (sreg & 7), OP_16BIT, sreg);
+ else if (sreg == REG_EAX)
+ emit_op_reg(emitptr, OP_NOP | (dreg & 7), OP_16BIT, dreg);
+ else
+ emit_op_modrm_reg(emitptr, OP_XCHG_Ev_Gv, OP_16BIT, dreg, sreg);
+}
+
+
+//-------------------------------------------------
+// emit_mov_r32_*
+//-------------------------------------------------
+
+inline void emit_mov_r32_imm(x86code *&emitptr, UINT8 dreg, UINT32 imm)
+{
+ emit_op_reg(emitptr, OP_MOV_rAX_Iv | (dreg & 7), OP_32BIT, dreg);
+ emit_dword(emitptr, imm);
+}
+
+inline void emit_mov_r32_r32(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOV_Gv_Ev, OP_32BIT, dreg, sreg); }
+inline void emit_mov_r32_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MOV_Gv_Ev, OP_32BIT, dreg, memref); }
+inline void emit_mov_m32_imm(x86code *&emitptr, x86_memref memref, UINT32 imm) { emit_op_modrm_mem_imm32(emitptr, OP_G11_Ev_Iz, OP_32BIT, 0, memref, imm); }
+inline void emit_mov_m32_r32(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_MOV_Ev_Gv, OP_32BIT, sreg, memref); }
+inline void emit_movsx_r32_r8(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOVSX_Gv_Eb, OP_32BIT, dreg, sreg); }
+inline void emit_movsx_r32_m8(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MOVSX_Gv_Eb, OP_32BIT, dreg, memref); }
+inline void emit_movsx_r32_r16(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOVSX_Gv_Ew, OP_32BIT, dreg, sreg); }
+inline void emit_movsx_r32_m16(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MOVSX_Gv_Ew, OP_32BIT, dreg, memref); }
+inline void emit_movzx_r32_r8(x86code *&emitptr, UINT8 dreg, UINT8 sreg)
+{
+#if (X86EMIT_SIZE == 32)
+ if (sreg >= 4)
+ {
+ emit_op_modrm_reg(emitptr, OP_MOV_Gv_Ev, OP_32BIT, dreg, sreg); // mov dreg,sreg
+ emit_op_modrm_reg_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_32BIT, 4, dreg, 0xff); // and dreg,0xff
+ }
+ else
+#endif
+ emit_op_modrm_reg(emitptr, OP_MOVZX_Gv_Eb, OP_32BIT, dreg, sreg);
+}
+inline void emit_movzx_r32_m8(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MOVZX_Gv_Eb, OP_32BIT, dreg, memref); }
+inline void emit_movzx_r32_r16(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOVZX_Gv_Ew, OP_32BIT, dreg, sreg); }
+inline void emit_movzx_r32_m16(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MOVZX_Gv_Ew, OP_32BIT, dreg, memref); }
+inline void emit_cmovcc_r32_r32(x86code *&emitptr, UINT8 cond, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CMOV_O_Gv_Ev + cond, OP_32BIT, dreg, sreg); }
+inline void emit_cmovcc_r32_m32(x86code *&emitptr, UINT8 cond, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CMOV_O_Gv_Ev + cond, OP_32BIT, dreg, memref); }
+
+
+//-------------------------------------------------
+// emit_xchg_r32_*
+//-------------------------------------------------
+
+inline void emit_xchg_r32_r32(x86code *&emitptr, UINT8 dreg, UINT8 sreg)
+{
+ if (dreg == REG_EAX)
+ emit_op_reg(emitptr, OP_NOP | (sreg & 7), OP_32BIT, sreg);
+ else if (sreg == REG_EAX)
+ emit_op_reg(emitptr, OP_NOP | (dreg & 7), OP_32BIT, dreg);
+ else
+ emit_op_modrm_reg(emitptr, OP_XCHG_Ev_Gv, OP_32BIT, dreg, sreg);
+}
+
+
+//-------------------------------------------------
+// emit_mov_r64_*
+//-------------------------------------------------
+
+#if (X86EMIT_SIZE == 64)
+
+inline void emit_mov_r64_imm(x86code *&emitptr, UINT8 dreg, UINT64 imm)
+{
+ if ((UINT32)imm == imm)
+ {
+ emit_op_reg(emitptr, OP_MOV_rAX_Iv | (dreg & 7), OP_32BIT, dreg);
+ emit_dword(emitptr, imm);
+ }
+ else if ((INT32)imm == imm)
+ emit_op_modrm_reg_imm32(emitptr, OP_G11_Ev_Iz, OP_64BIT, 0, dreg, imm);
+ else
+ {
+ emit_op_reg(emitptr, OP_MOV_rAX_Iv | (dreg & 7), OP_64BIT, dreg);
+ emit_qword(emitptr, imm);
+ }
+}
+
+inline void emit_mov_r64_r64(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOV_Gv_Ev, OP_64BIT, dreg, sreg); }
+inline void emit_mov_r64_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MOV_Gv_Ev, OP_64BIT, dreg, memref); }
+inline void emit_mov_m64_imm(x86code *&emitptr, x86_memref memref, UINT32 imm) { emit_op_modrm_mem_imm32(emitptr, OP_G11_Ev_Iz, OP_64BIT, 0, memref, imm); }
+inline void emit_mov_m64_r64(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_MOV_Ev_Gv, OP_64BIT, sreg, memref); }
+inline void emit_movsx_r64_r8(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOVSX_Gv_Eb, OP_64BIT, dreg, sreg); }
+inline void emit_movsx_r64_m8(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MOVSX_Gv_Eb, OP_64BIT, dreg, memref); }
+inline void emit_movsx_r64_r16(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOVSX_Gv_Ew, OP_64BIT, dreg, sreg); }
+inline void emit_movsx_r64_m16(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MOVSX_Gv_Ew, OP_64BIT, dreg, memref); }
+inline void emit_movsxd_r64_r32(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOVSXD_Gv_Ev, OP_64BIT, dreg, sreg); }
+inline void emit_movsxd_r64_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MOVSXD_Gv_Ev, OP_64BIT, dreg, memref); }
+inline void emit_movzx_r64_r8(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOVZX_Gv_Eb, OP_64BIT, dreg, sreg); }
+inline void emit_movzx_r64_m8(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MOVZX_Gv_Eb, OP_64BIT, dreg, memref); }
+inline void emit_movzx_r64_r16(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOVZX_Gv_Ew, OP_64BIT, dreg, sreg); }
+inline void emit_movzx_r64_m16(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MOVZX_Gv_Ew, OP_64BIT, dreg, memref); }
+inline void emit_cmovcc_r64_r64(x86code *&emitptr, UINT8 cond, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CMOV_O_Gv_Ev + cond, OP_64BIT, dreg, sreg); }
+inline void emit_cmovcc_r64_m64(x86code *&emitptr, UINT8 cond, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CMOV_O_Gv_Ev + cond, OP_64BIT, dreg, memref); }
+
+
+//-------------------------------------------------
+// emit_xchg_r64_*
+//-------------------------------------------------
+
+inline void emit_xchg_r64_r64(x86code *&emitptr, UINT8 dreg, UINT8 sreg)
+{
+ if (dreg == REG_EAX)
+ emit_op_reg(emitptr, OP_NOP | (sreg & 7), OP_64BIT, sreg);
+ else if (sreg == REG_EAX)
+ emit_op_reg(emitptr, OP_NOP | (dreg & 7), OP_64BIT, dreg);
+ else
+ emit_op_modrm_reg(emitptr, OP_XCHG_Ev_Gv, OP_64BIT, dreg, sreg);
+}
+
+#endif
+
+
+//**************************************************************************
+// ARITHMETIC EMITTERS
+//**************************************************************************
+
+//-------------------------------------------------
+// emit_arith_r8_*
+//-------------------------------------------------
+
+inline void emit_add_r8_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_G1_Eb_Ib, OP_32BIT, 0, dreg, imm); }
+inline void emit_add_m8_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_G1_Eb_Ib, OP_32BIT, 0, memref, imm); }
+inline void emit_add_r8_r8(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_ADD_Gb_Eb, OP_32BIT, dreg, sreg); }
+inline void emit_add_r8_m8(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ADD_Gb_Eb, OP_32BIT, dreg, memref); }
+inline void emit_add_m8_r8(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_ADD_Eb_Gb, OP_32BIT, sreg, memref); }
+
+inline void emit_or_r8_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_G1_Eb_Ib, OP_32BIT, 1, dreg, imm); }
+inline void emit_or_m8_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_G1_Eb_Ib, OP_32BIT, 1, memref, imm); }
+inline void emit_or_r8_r8(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_OR_Gb_Eb, OP_32BIT, dreg, sreg); }
+inline void emit_or_r8_m8(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_OR_Gb_Eb, OP_32BIT, dreg, memref); }
+inline void emit_or_m8_r8(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_OR_Eb_Gb, OP_32BIT, sreg, memref); }
+
+inline void emit_adc_r8_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_G1_Eb_Ib, OP_32BIT, 2, dreg, imm); }
+inline void emit_adc_m8_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_G1_Eb_Ib, OP_32BIT, 2, memref, imm); }
+inline void emit_adc_r8_r8(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_ADC_Gb_Eb, OP_32BIT, dreg, sreg); }
+inline void emit_adc_r8_m8(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ADC_Gb_Eb, OP_32BIT, dreg, memref); }
+inline void emit_adc_m8_r8(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_ADC_Eb_Gb, OP_32BIT, sreg, memref); }
+
+inline void emit_sbb_r8_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_G1_Eb_Ib, OP_32BIT, 3, dreg, imm); }
+inline void emit_sbb_m8_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_G1_Eb_Ib, OP_32BIT, 3, memref, imm); }
+inline void emit_sbb_r8_r8(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_SBB_Gb_Eb, OP_32BIT, dreg, sreg); }
+inline void emit_sbb_r8_m8(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_SBB_Gb_Eb, OP_32BIT, dreg, memref); }
+inline void emit_sbb_m8_r8(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_SBB_Eb_Gb, OP_32BIT, sreg, memref); }
+
+inline void emit_and_r8_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_G1_Eb_Ib, OP_32BIT, 4, dreg, imm); }
+inline void emit_and_m8_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_G1_Eb_Ib, OP_32BIT, 4, memref, imm); }
+inline void emit_and_r8_r8(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_AND_Gb_Eb, OP_32BIT, dreg, sreg); }
+inline void emit_and_r8_m8(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_AND_Gb_Eb, OP_32BIT, dreg, memref); }
+inline void emit_and_m8_r8(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_AND_Eb_Gb, OP_32BIT, sreg, memref); }
+
+inline void emit_sub_r8_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_G1_Eb_Ib, OP_32BIT, 5, dreg, imm); }
+inline void emit_sub_m8_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_G1_Eb_Ib, OP_32BIT, 5, memref, imm); }
+inline void emit_sub_r8_r8(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_SUB_Gb_Eb, OP_32BIT, dreg, sreg); }
+inline void emit_sub_r8_m8(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_SUB_Gb_Eb, OP_32BIT, dreg, memref); }
+inline void emit_sub_m8_r8(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_SUB_Eb_Gb, OP_32BIT, sreg, memref); }
+
+inline void emit_xor_r8_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_G1_Eb_Ib, OP_32BIT, 6, dreg, imm); }
+inline void emit_xor_m8_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_G1_Eb_Ib, OP_32BIT, 6, memref, imm); }
+inline void emit_xor_r8_r8(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_XOR_Gb_Eb, OP_32BIT, dreg, sreg); }
+inline void emit_xor_r8_m8(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_XOR_Gb_Eb, OP_32BIT, dreg, memref); }
+inline void emit_xor_m8_r8(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_XOR_Eb_Gb, OP_32BIT, sreg, memref); }
+
+inline void emit_cmp_r8_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_G1_Eb_Ib, OP_32BIT, 7, dreg, imm); }
+inline void emit_cmp_m8_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_G1_Eb_Ib, OP_32BIT, 7, memref, imm); }
+inline void emit_cmp_r8_r8(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CMP_Gb_Eb, OP_32BIT, dreg, sreg); }
+inline void emit_cmp_r8_m8(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CMP_Gb_Eb, OP_32BIT, dreg, memref); }
+inline void emit_cmp_m8_r8(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_CMP_Eb_Gb, OP_32BIT, sreg, memref); }
+
+inline void emit_test_r8_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_G3_Eb, OP_32BIT, 0, dreg, imm); }
+inline void emit_test_m8_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_G3_Eb, OP_32BIT, 0, memref, imm); }
+inline void emit_test_r8_r8(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_TEST_Eb_Gb, OP_32BIT, sreg, dreg); }
+inline void emit_test_m8_r8(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_TEST_Eb_Gb, OP_32BIT, sreg, memref); }
+
+
+//-------------------------------------------------
+// emit_arith_r16_*
+//-------------------------------------------------
+
+inline void emit_add_r16_imm(x86code *&emitptr, UINT8 dreg, UINT16 imm) { emit_op_modrm_reg_imm816(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_16BIT, 0, dreg, imm); }
+inline void emit_add_m16_imm(x86code *&emitptr, x86_memref memref, UINT16 imm) { emit_op_modrm_mem_imm816(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_16BIT, 0, memref, imm); }
+inline void emit_add_r16_r16(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_ADD_Gv_Ev, OP_16BIT, dreg, sreg); }
+inline void emit_add_r16_m16(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ADD_Gv_Ev, OP_16BIT, dreg, memref); }
+inline void emit_add_m16_r16(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_ADD_Ev_Gv, OP_16BIT, sreg, memref); }
+
+inline void emit_or_r16_imm(x86code *&emitptr, UINT8 dreg, UINT16 imm) { emit_op_modrm_reg_imm816(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_16BIT, 1, dreg, imm); }
+inline void emit_or_m16_imm(x86code *&emitptr, x86_memref memref, UINT16 imm) { emit_op_modrm_mem_imm816(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_16BIT, 1, memref, imm); }
+inline void emit_or_r16_r16(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_OR_Gv_Ev, OP_16BIT, dreg, sreg); }
+inline void emit_or_r16_m16(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_OR_Gv_Ev, OP_16BIT, dreg, memref); }
+inline void emit_or_m16_r16(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_OR_Ev_Gv, OP_16BIT, sreg, memref); }
+
+inline void emit_adc_r16_imm(x86code *&emitptr, UINT8 dreg, UINT16 imm) { emit_op_modrm_reg_imm816(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_16BIT, 2, dreg, imm); }
+inline void emit_adc_m16_imm(x86code *&emitptr, x86_memref memref, UINT16 imm) { emit_op_modrm_mem_imm816(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_16BIT, 2, memref, imm); }
+inline void emit_adc_r16_r16(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_ADC_Gv_Ev, OP_16BIT, dreg, sreg); }
+inline void emit_adc_r16_m16(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ADC_Gv_Ev, OP_16BIT, dreg, memref); }
+inline void emit_adc_m16_r16(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_ADC_Ev_Gv, OP_16BIT, sreg, memref); }
+
+inline void emit_sbb_r16_imm(x86code *&emitptr, UINT8 dreg, UINT16 imm) { emit_op_modrm_reg_imm816(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_16BIT, 3, dreg, imm); }
+inline void emit_sbb_m16_imm(x86code *&emitptr, x86_memref memref, UINT16 imm) { emit_op_modrm_mem_imm816(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_16BIT, 3, memref, imm); }
+inline void emit_sbb_r16_r16(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_SBB_Gv_Ev, OP_16BIT, dreg, sreg); }
+inline void emit_sbb_r16_m16(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_SBB_Gv_Ev, OP_16BIT, dreg, memref); }
+inline void emit_sbb_m16_r16(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_SBB_Ev_Gv, OP_16BIT, sreg, memref); }
+
+inline void emit_and_r16_imm(x86code *&emitptr, UINT8 dreg, UINT16 imm) { emit_op_modrm_reg_imm816(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_16BIT, 4, dreg, imm); }
+inline void emit_and_m16_imm(x86code *&emitptr, x86_memref memref, UINT16 imm) { emit_op_modrm_mem_imm816(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_16BIT, 4, memref, imm); }
+inline void emit_and_r16_r16(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_AND_Gv_Ev, OP_16BIT, dreg, sreg); }
+inline void emit_and_r16_m16(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_AND_Gv_Ev, OP_16BIT, dreg, memref); }
+inline void emit_and_m16_r16(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_AND_Ev_Gv, OP_16BIT, sreg, memref); }
+
+inline void emit_sub_r16_imm(x86code *&emitptr, UINT8 dreg, UINT16 imm) { emit_op_modrm_reg_imm816(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_16BIT, 5, dreg, imm); }
+inline void emit_sub_m16_imm(x86code *&emitptr, x86_memref memref, UINT16 imm) { emit_op_modrm_mem_imm816(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_16BIT, 5, memref, imm); }
+inline void emit_sub_r16_r16(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_SUB_Gv_Ev, OP_16BIT, dreg, sreg); }
+inline void emit_sub_r16_m16(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_SUB_Gv_Ev, OP_16BIT, dreg, memref); }
+inline void emit_sub_m16_r16(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_SUB_Ev_Gv, OP_16BIT, sreg, memref); }
+
+inline void emit_xor_r16_imm(x86code *&emitptr, UINT8 dreg, UINT16 imm) { emit_op_modrm_reg_imm816(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_16BIT, 6, dreg, imm); }
+inline void emit_xor_m16_imm(x86code *&emitptr, x86_memref memref, UINT16 imm) { emit_op_modrm_mem_imm816(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_16BIT, 6, memref, imm); }
+inline void emit_xor_r16_r16(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_XOR_Gv_Ev, OP_16BIT, dreg, sreg); }
+inline void emit_xor_r16_m16(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_XOR_Gv_Ev, OP_16BIT, dreg, memref); }
+inline void emit_xor_m16_r16(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_XOR_Ev_Gv, OP_16BIT, sreg, memref); }
+
+inline void emit_cmp_r16_imm(x86code *&emitptr, UINT8 dreg, UINT16 imm) { emit_op_modrm_reg_imm816(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_16BIT, 7, dreg, imm); }
+inline void emit_cmp_m16_imm(x86code *&emitptr, x86_memref memref, UINT16 imm) { emit_op_modrm_mem_imm816(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_16BIT, 7, memref, imm); }
+inline void emit_cmp_r16_r16(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CMP_Gv_Ev, OP_16BIT, dreg, sreg); }
+inline void emit_cmp_r16_m16(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CMP_Gv_Ev, OP_16BIT, dreg, memref); }
+inline void emit_cmp_m16_r16(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_CMP_Ev_Gv, OP_16BIT, sreg, memref); }
+
+inline void emit_test_r16_imm(x86code *&emitptr, UINT8 dreg, UINT16 imm) { emit_op_modrm_reg_imm16(emitptr, OP_G3_Ev, OP_16BIT, 0, dreg, imm); }
+inline void emit_test_m16_imm(x86code *&emitptr, x86_memref memref, UINT16 imm) { emit_op_modrm_mem_imm16(emitptr, OP_G3_Ev, OP_16BIT, 0, memref, imm); }
+inline void emit_test_r16_r16(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_TEST_Ev_Gv, OP_16BIT, sreg, dreg); }
+inline void emit_test_m16_r16(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_TEST_Ev_Gv, OP_16BIT, sreg, memref); }
+
+
+//-------------------------------------------------
+// emit_arith_r32_*
+//-------------------------------------------------
+
+inline void emit_add_r32_imm(x86code *&emitptr, UINT8 dreg, UINT32 imm) { emit_op_modrm_reg_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_32BIT, 0, dreg, imm); }
+inline void emit_add_m32_imm(x86code *&emitptr, x86_memref memref, UINT32 imm) { emit_op_modrm_mem_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_32BIT, 0, memref, imm); }
+inline void emit_add_r32_r32(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_ADD_Gv_Ev, OP_32BIT, dreg, sreg); }
+inline void emit_add_r32_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ADD_Gv_Ev, OP_32BIT, dreg, memref); }
+inline void emit_add_m32_r32(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_ADD_Ev_Gv, OP_32BIT, sreg, memref); }
+
+inline void emit_or_r32_imm(x86code *&emitptr, UINT8 dreg, UINT32 imm) { emit_op_modrm_reg_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_32BIT, 1, dreg, imm); }
+inline void emit_or_m32_imm(x86code *&emitptr, x86_memref memref, UINT32 imm) { emit_op_modrm_mem_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_32BIT, 1, memref, imm); }
+inline void emit_or_r32_r32(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_OR_Gv_Ev, OP_32BIT, dreg, sreg); }
+inline void emit_or_r32_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_OR_Gv_Ev, OP_32BIT, dreg, memref); }
+inline void emit_or_m32_r32(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_OR_Ev_Gv, OP_32BIT, sreg, memref); }
+
+inline void emit_adc_r32_imm(x86code *&emitptr, UINT8 dreg, UINT32 imm) { emit_op_modrm_reg_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_32BIT, 2, dreg, imm); }
+inline void emit_adc_m32_imm(x86code *&emitptr, x86_memref memref, UINT32 imm) { emit_op_modrm_mem_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_32BIT, 2, memref, imm); }
+inline void emit_adc_r32_r32(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_ADC_Gv_Ev, OP_32BIT, dreg, sreg); }
+inline void emit_adc_r32_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ADC_Gv_Ev, OP_32BIT, dreg, memref); }
+inline void emit_adc_m32_r32(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_ADC_Ev_Gv, OP_32BIT, sreg, memref); }
+
+inline void emit_sbb_r32_imm(x86code *&emitptr, UINT8 dreg, UINT32 imm) { emit_op_modrm_reg_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_32BIT, 3, dreg, imm); }
+inline void emit_sbb_m32_imm(x86code *&emitptr, x86_memref memref, UINT32 imm) { emit_op_modrm_mem_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_32BIT, 3, memref, imm); }
+inline void emit_sbb_r32_r32(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_SBB_Gv_Ev, OP_32BIT, dreg, sreg); }
+inline void emit_sbb_r32_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_SBB_Gv_Ev, OP_32BIT, dreg, memref); }
+inline void emit_sbb_m32_r32(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_SBB_Ev_Gv, OP_32BIT, sreg, memref); }
+
+inline void emit_and_r32_imm(x86code *&emitptr, UINT8 dreg, UINT32 imm) { emit_op_modrm_reg_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_32BIT, 4, dreg, imm); }
+inline void emit_and_m32_imm(x86code *&emitptr, x86_memref memref, UINT32 imm) { emit_op_modrm_mem_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_32BIT, 4, memref, imm); }
+inline void emit_and_r32_r32(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_AND_Gv_Ev, OP_32BIT, dreg, sreg); }
+inline void emit_and_r32_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_AND_Gv_Ev, OP_32BIT, dreg, memref); }
+inline void emit_and_m32_r32(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_AND_Ev_Gv, OP_32BIT, sreg, memref); }
+
+inline void emit_sub_r32_imm(x86code *&emitptr, UINT8 dreg, UINT32 imm) { emit_op_modrm_reg_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_32BIT, 5, dreg, imm); }
+inline void emit_sub_m32_imm(x86code *&emitptr, x86_memref memref, UINT32 imm) { emit_op_modrm_mem_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_32BIT, 5, memref, imm); }
+inline void emit_sub_r32_r32(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_SUB_Gv_Ev, OP_32BIT, dreg, sreg); }
+inline void emit_sub_r32_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_SUB_Gv_Ev, OP_32BIT, dreg, memref); }
+inline void emit_sub_m32_r32(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_SUB_Ev_Gv, OP_32BIT, sreg, memref); }
+
+inline void emit_xor_r32_imm(x86code *&emitptr, UINT8 dreg, UINT32 imm) { emit_op_modrm_reg_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_32BIT, 6, dreg, imm); }
+inline void emit_xor_m32_imm(x86code *&emitptr, x86_memref memref, UINT32 imm) { emit_op_modrm_mem_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_32BIT, 6, memref, imm); }
+inline void emit_xor_r32_r32(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_XOR_Gv_Ev, OP_32BIT, dreg, sreg); }
+inline void emit_xor_r32_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_XOR_Gv_Ev, OP_32BIT, dreg, memref); }
+inline void emit_xor_m32_r32(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_XOR_Ev_Gv, OP_32BIT, sreg, memref); }
+
+inline void emit_cmp_r32_imm(x86code *&emitptr, UINT8 dreg, UINT32 imm) { emit_op_modrm_reg_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_32BIT, 7, dreg, imm); }
+inline void emit_cmp_m32_imm(x86code *&emitptr, x86_memref memref, UINT32 imm) { emit_op_modrm_mem_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_32BIT, 7, memref, imm); }
+inline void emit_cmp_r32_r32(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CMP_Gv_Ev, OP_32BIT, dreg, sreg); }
+inline void emit_cmp_r32_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CMP_Gv_Ev, OP_32BIT, dreg, memref); }
+inline void emit_cmp_m32_r32(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_CMP_Ev_Gv, OP_32BIT, sreg, memref); }
+
+inline void emit_test_r32_imm(x86code *&emitptr, UINT8 dreg, UINT32 imm) { emit_op_modrm_reg_imm32(emitptr, OP_G3_Ev, OP_32BIT, 0, dreg, imm); }
+inline void emit_test_m32_imm(x86code *&emitptr, x86_memref memref, UINT32 imm) { emit_op_modrm_mem_imm32(emitptr, OP_G3_Ev, OP_32BIT, 0, memref, imm); }
+inline void emit_test_r32_r32(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_TEST_Ev_Gv, OP_32BIT, sreg, dreg); }
+inline void emit_test_m32_r32(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_TEST_Ev_Gv, OP_32BIT, sreg, memref); }
+
+
+//-------------------------------------------------
+// emit_arith_r64_*
+//-------------------------------------------------
+
+#if (X86EMIT_SIZE == 64)
+
+inline void emit_add_r64_imm(x86code *&emitptr, UINT8 dreg, UINT32 imm) { emit_op_modrm_reg_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_64BIT, 0, dreg, imm); }
+inline void emit_add_m64_imm(x86code *&emitptr, x86_memref memref, UINT32 imm) { emit_op_modrm_mem_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_64BIT, 0, memref, imm); }
+inline void emit_add_r64_r64(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_ADD_Gv_Ev, OP_64BIT, dreg, sreg); }
+inline void emit_add_r64_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ADD_Gv_Ev, OP_64BIT, dreg, memref); }
+inline void emit_add_m64_r64(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_ADD_Ev_Gv, OP_64BIT, sreg, memref); }
+
+inline void emit_or_r64_imm(x86code *&emitptr, UINT8 dreg, UINT32 imm) { emit_op_modrm_reg_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_64BIT, 1, dreg, imm); }
+inline void emit_or_m64_imm(x86code *&emitptr, x86_memref memref, UINT32 imm) { emit_op_modrm_mem_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_64BIT, 1, memref, imm); }
+inline void emit_or_r64_r64(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_OR_Gv_Ev, OP_64BIT, dreg, sreg); }
+inline void emit_or_r64_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_OR_Gv_Ev, OP_64BIT, dreg, memref); }
+inline void emit_or_m64_r64(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_OR_Ev_Gv, OP_64BIT, sreg, memref); }
+
+inline void emit_adc_r64_imm(x86code *&emitptr, UINT8 dreg, UINT32 imm) { emit_op_modrm_reg_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_64BIT, 2, dreg, imm); }
+inline void emit_adc_m64_imm(x86code *&emitptr, x86_memref memref, UINT32 imm) { emit_op_modrm_mem_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_64BIT, 2, memref, imm); }
+inline void emit_adc_r64_r64(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_ADC_Gv_Ev, OP_64BIT, dreg, sreg); }
+inline void emit_adc_r64_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ADC_Gv_Ev, OP_64BIT, dreg, memref); }
+inline void emit_adc_m64_r64(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_ADC_Ev_Gv, OP_64BIT, sreg, memref); }
+
+inline void emit_sbb_r64_imm(x86code *&emitptr, UINT8 dreg, UINT32 imm) { emit_op_modrm_reg_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_64BIT, 3, dreg, imm); }
+inline void emit_sbb_m64_imm(x86code *&emitptr, x86_memref memref, UINT32 imm) { emit_op_modrm_mem_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_64BIT, 3, memref, imm); }
+inline void emit_sbb_r64_r64(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_SBB_Gv_Ev, OP_64BIT, dreg, sreg); }
+inline void emit_sbb_r64_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_SBB_Gv_Ev, OP_64BIT, dreg, memref); }
+inline void emit_sbb_m64_r64(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_SBB_Ev_Gv, OP_64BIT, sreg, memref); }
+
+inline void emit_and_r64_imm(x86code *&emitptr, UINT8 dreg, UINT32 imm) { emit_op_modrm_reg_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_64BIT, 4, dreg, imm); }
+inline void emit_and_m64_imm(x86code *&emitptr, x86_memref memref, UINT32 imm) { emit_op_modrm_mem_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_64BIT, 4, memref, imm); }
+inline void emit_and_r64_r64(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_AND_Gv_Ev, OP_64BIT, dreg, sreg); }
+inline void emit_and_r64_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_AND_Gv_Ev, OP_64BIT, dreg, memref); }
+inline void emit_and_m64_r64(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_AND_Ev_Gv, OP_64BIT, sreg, memref); }
+
+inline void emit_sub_r64_imm(x86code *&emitptr, UINT8 dreg, UINT32 imm) { emit_op_modrm_reg_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_64BIT, 5, dreg, imm); }
+inline void emit_sub_m64_imm(x86code *&emitptr, x86_memref memref, UINT32 imm) { emit_op_modrm_mem_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_64BIT, 5, memref, imm); }
+inline void emit_sub_r64_r64(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_SUB_Gv_Ev, OP_64BIT, dreg, sreg); }
+inline void emit_sub_r64_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_SUB_Gv_Ev, OP_64BIT, dreg, memref); }
+inline void emit_sub_m64_r64(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_SUB_Ev_Gv, OP_64BIT, sreg, memref); }
+
+inline void emit_xor_r64_imm(x86code *&emitptr, UINT8 dreg, UINT32 imm) { emit_op_modrm_reg_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_64BIT, 6, dreg, imm); }
+inline void emit_xor_m64_imm(x86code *&emitptr, x86_memref memref, UINT32 imm) { emit_op_modrm_mem_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_64BIT, 6, memref, imm); }
+inline void emit_xor_r64_r64(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_XOR_Gv_Ev, OP_64BIT, dreg, sreg); }
+inline void emit_xor_r64_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_XOR_Gv_Ev, OP_64BIT, dreg, memref); }
+inline void emit_xor_m64_r64(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_XOR_Ev_Gv, OP_64BIT, sreg, memref); }
+
+inline void emit_cmp_r64_imm(x86code *&emitptr, UINT8 dreg, UINT32 imm) { emit_op_modrm_reg_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_64BIT, 7, dreg, imm); }
+inline void emit_cmp_m64_imm(x86code *&emitptr, x86_memref memref, UINT32 imm) { emit_op_modrm_mem_imm832(emitptr, OP_G1_Ev_Ib, OP_G1_Ev_Iz, OP_64BIT, 7, memref, imm); }
+inline void emit_cmp_r64_r64(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CMP_Gv_Ev, OP_64BIT, dreg, sreg); }
+inline void emit_cmp_r64_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CMP_Gv_Ev, OP_64BIT, dreg, memref); }
+inline void emit_cmp_m64_r64(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_CMP_Ev_Gv, OP_64BIT, sreg, memref); }
+
+inline void emit_test_r64_imm(x86code *&emitptr, UINT8 dreg, UINT32 imm) { emit_op_modrm_reg_imm32(emitptr, OP_G3_Ev, OP_64BIT, 0, dreg, imm); }
+inline void emit_test_m64_imm(x86code *&emitptr, x86_memref memref, UINT32 imm) { emit_op_modrm_mem_imm32(emitptr, OP_G3_Ev, OP_64BIT, 0, memref, imm); }
+inline void emit_test_r64_r64(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_TEST_Ev_Gv, OP_64BIT, sreg, dreg); }
+inline void emit_test_m64_r64(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_TEST_Ev_Gv, OP_64BIT, sreg, memref); }
+
+#endif
+
+
+
+//**************************************************************************
+// SHIFT EMITTERS
+//**************************************************************************
+
+//-------------------------------------------------
+// emit_shift_reg_imm
+//-------------------------------------------------
+
+inline void emit_shift_reg_imm(x86code *&emitptr, UINT32 op1, UINT32 opn, UINT8 opsize, UINT8 opindex, UINT8 dreg, UINT8 imm)
+{
+ if (imm == 1)
+ emit_op_modrm_reg(emitptr, op1, opsize, opindex, dreg);
+ else
+ emit_op_modrm_reg_imm8(emitptr, opn, opsize, opindex, dreg, imm);
+}
+
+inline void emit_shift_mem_imm(x86code *&emitptr, UINT32 op1, UINT32 opn, UINT8 opsize, UINT8 opindex, x86_memref memref, UINT8 imm)
+{
+ if (imm == 1)
+ emit_op_modrm_mem(emitptr, op1, opsize, opindex, memref);
+ else
+ emit_op_modrm_mem_imm8(emitptr, opn, opsize, opindex, memref, imm);
+}
+
+
+//-------------------------------------------------
+// emit_shift_r8_*
+//-------------------------------------------------
+
+inline void emit_rol_r8_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Eb_1, OP_G2_Eb_Ib, OP_32BIT, 0, dreg, imm); }
+inline void emit_rol_m8_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Eb_1, OP_G2_Eb_Ib, OP_32BIT, 0, memref, imm); }
+inline void emit_rol_r8_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Eb_CL, OP_32BIT, 0, dreg); }
+inline void emit_rol_m8_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Eb_CL, OP_32BIT, 0, memref); }
+
+inline void emit_ror_r8_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Eb_1, OP_G2_Eb_Ib, OP_32BIT, 1, dreg, imm); }
+inline void emit_ror_m8_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Eb_1, OP_G2_Eb_Ib, OP_32BIT, 1, memref, imm); }
+inline void emit_ror_r8_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Eb_CL, OP_32BIT, 1, dreg); }
+inline void emit_ror_m8_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Eb_CL, OP_32BIT, 1, memref); }
+
+inline void emit_rcl_r8_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Eb_1, OP_G2_Eb_Ib, OP_32BIT, 2, dreg, imm); }
+inline void emit_rcl_m8_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Eb_1, OP_G2_Eb_Ib, OP_32BIT, 2, memref, imm); }
+inline void emit_rcl_r8_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Eb_CL, OP_32BIT, 2, dreg); }
+inline void emit_rcl_m8_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Eb_CL, OP_32BIT, 2, memref); }
+
+inline void emit_rcr_r8_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Eb_1, OP_G2_Eb_Ib, OP_32BIT, 3, dreg, imm); }
+inline void emit_rcr_m8_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Eb_1, OP_G2_Eb_Ib, OP_32BIT, 3, memref, imm); }
+inline void emit_rcr_r8_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Eb_CL, OP_32BIT, 3, dreg); }
+inline void emit_rcr_m8_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Eb_CL, OP_32BIT, 3, memref); }
+
+inline void emit_shl_r8_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Eb_1, OP_G2_Eb_Ib, OP_32BIT, 4, dreg, imm); }
+inline void emit_shl_m8_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Eb_1, OP_G2_Eb_Ib, OP_32BIT, 4, memref, imm); }
+inline void emit_shl_r8_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Eb_CL, OP_32BIT, 4, dreg); }
+inline void emit_shl_m8_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Eb_CL, OP_32BIT, 4, memref); }
+
+inline void emit_shr_r8_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Eb_1, OP_G2_Eb_Ib, OP_32BIT, 5, dreg, imm); }
+inline void emit_shr_m8_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Eb_1, OP_G2_Eb_Ib, OP_32BIT, 5, memref, imm); }
+inline void emit_shr_r8_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Eb_CL, OP_32BIT, 5, dreg); }
+inline void emit_shr_m8_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Eb_CL, OP_32BIT, 5, memref); }
+
+inline void emit_sar_r8_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Eb_1, OP_G2_Eb_Ib, OP_32BIT, 7, dreg, imm); }
+inline void emit_sar_m8_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Eb_1, OP_G2_Eb_Ib, OP_32BIT, 7, memref, imm); }
+inline void emit_sar_r8_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Eb_CL, OP_32BIT, 7, dreg); }
+inline void emit_sar_m8_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Eb_CL, OP_32BIT, 7, memref); }
+
+
+//-------------------------------------------------
+// emit_shift_r16_*
+//-------------------------------------------------
+
+inline void emit_rol_r16_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_16BIT, 0, dreg, imm); }
+inline void emit_rol_m16_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_16BIT, 0, memref, imm); }
+inline void emit_rol_r16_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Ev_CL, OP_16BIT, 0, dreg); }
+inline void emit_rol_m16_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Ev_CL, OP_16BIT, 0, memref); }
+
+inline void emit_ror_r16_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_16BIT, 1, dreg, imm); }
+inline void emit_ror_m16_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_16BIT, 1, memref, imm); }
+inline void emit_ror_r16_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Ev_CL, OP_16BIT, 1, dreg); }
+inline void emit_ror_m16_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Ev_CL, OP_16BIT, 1, memref); }
+
+inline void emit_rcl_r16_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_16BIT, 2, dreg, imm); }
+inline void emit_rcl_m16_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_16BIT, 2, memref, imm); }
+inline void emit_rcl_r16_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Ev_CL, OP_16BIT, 2, dreg); }
+inline void emit_rcl_m16_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Ev_CL, OP_16BIT, 2, memref); }
+
+inline void emit_rcr_r16_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_16BIT, 3, dreg, imm); }
+inline void emit_rcr_m16_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_16BIT, 3, memref, imm); }
+inline void emit_rcr_r16_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Ev_CL, OP_16BIT, 3, dreg); }
+inline void emit_rcr_m16_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Ev_CL, OP_16BIT, 3, memref); }
+
+inline void emit_shl_r16_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_16BIT, 4, dreg, imm); }
+inline void emit_shl_m16_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_16BIT, 4, memref, imm); }
+inline void emit_shl_r16_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Ev_CL, OP_16BIT, 4, dreg); }
+inline void emit_shl_m16_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Ev_CL, OP_16BIT, 4, memref); }
+
+inline void emit_shr_r16_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_16BIT, 5, dreg, imm); }
+inline void emit_shr_m16_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_16BIT, 5, memref, imm); }
+inline void emit_shr_r16_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Ev_CL, OP_16BIT, 5, dreg); }
+inline void emit_shr_m16_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Ev_CL, OP_16BIT, 5, memref); }
+
+inline void emit_sar_r16_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_16BIT, 7, dreg, imm); }
+inline void emit_sar_m16_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_16BIT, 7, memref, imm); }
+inline void emit_sar_r16_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Ev_CL, OP_16BIT, 7, dreg); }
+inline void emit_sar_m16_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Ev_CL, OP_16BIT, 7, memref); }
+
+
+//-------------------------------------------------
+// emit_shift_r32_*
+//-------------------------------------------------
+
+inline void emit_rol_r32_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_32BIT, 0, dreg, imm); }
+inline void emit_rol_m32_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_32BIT, 0, memref, imm); }
+inline void emit_rol_r32_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Ev_CL, OP_32BIT, 0, dreg); }
+inline void emit_rol_m32_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Ev_CL, OP_32BIT, 0, memref); }
+
+inline void emit_ror_r32_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_32BIT, 1, dreg, imm); }
+inline void emit_ror_m32_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_32BIT, 1, memref, imm); }
+inline void emit_ror_r32_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Ev_CL, OP_32BIT, 1, dreg); }
+inline void emit_ror_m32_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Ev_CL, OP_32BIT, 1, memref); }
+
+inline void emit_rcl_r32_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_32BIT, 2, dreg, imm); }
+inline void emit_rcl_m32_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_32BIT, 2, memref, imm); }
+inline void emit_rcl_r32_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Ev_CL, OP_32BIT, 2, dreg); }
+inline void emit_rcl_m32_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Ev_CL, OP_32BIT, 2, memref); }
+
+inline void emit_rcr_r32_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_32BIT, 3, dreg, imm); }
+inline void emit_rcr_m32_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_32BIT, 3, memref, imm); }
+inline void emit_rcr_r32_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Ev_CL, OP_32BIT, 3, dreg); }
+inline void emit_rcr_m32_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Ev_CL, OP_32BIT, 3, memref); }
+
+inline void emit_shl_r32_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_32BIT, 4, dreg, imm); }
+inline void emit_shl_m32_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_32BIT, 4, memref, imm); }
+inline void emit_shl_r32_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Ev_CL, OP_32BIT, 4, dreg); }
+inline void emit_shl_m32_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Ev_CL, OP_32BIT, 4, memref); }
+
+inline void emit_shr_r32_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_32BIT, 5, dreg, imm); }
+inline void emit_shr_m32_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_32BIT, 5, memref, imm); }
+inline void emit_shr_r32_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Ev_CL, OP_32BIT, 5, dreg); }
+inline void emit_shr_m32_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Ev_CL, OP_32BIT, 5, memref); }
+
+inline void emit_sar_r32_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_32BIT, 7, dreg, imm); }
+inline void emit_sar_m32_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_32BIT, 7, memref, imm); }
+inline void emit_sar_r32_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Ev_CL, OP_32BIT, 7, dreg); }
+inline void emit_sar_m32_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Ev_CL, OP_32BIT, 7, memref); }
+
+inline void emit_shld_r32_r32_imm(x86code *&emitptr, UINT8 dreg, UINT8 sreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_SHLD_Ev_Gv_Ib, OP_32BIT, sreg, dreg, imm); }
+inline void emit_shld_m32_r32_imm(x86code *&emitptr, x86_memref memref, UINT8 sreg, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_SHLD_Ev_Gv_Ib, OP_32BIT, sreg, memref, imm); }
+inline void emit_shld_r32_r32_cl(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_SHLD_Ev_Gv_CL, OP_32BIT, sreg, dreg); }
+inline void emit_shld_m32_r32_cl(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_SHLD_Ev_Gv_CL, OP_32BIT, sreg, memref); }
+
+inline void emit_shrd_r32_r32_imm(x86code *&emitptr, UINT8 dreg, UINT8 sreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_SHRD_Ev_Gv_Ib, OP_32BIT, sreg, dreg, imm); }
+inline void emit_shrd_m32_r32_imm(x86code *&emitptr, x86_memref memref, UINT8 sreg, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_SHRD_Ev_Gv_Ib, OP_32BIT, sreg, memref, imm); }
+inline void emit_shrd_r32_r32_cl(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_SHRD_Ev_Gv_CL, OP_32BIT, sreg, dreg); }
+inline void emit_shrd_m32_r32_cl(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_SHRD_Ev_Gv_CL, OP_32BIT, sreg, memref); }
+
+
+//-------------------------------------------------
+// emit_shift_r64_*
+//-------------------------------------------------
+
+#if (X86EMIT_SIZE == 64)
+
+inline void emit_rol_r64_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_64BIT, 0, dreg, imm); }
+inline void emit_rol_m64_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_64BIT, 0, memref, imm); }
+inline void emit_rol_r64_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Ev_CL, OP_64BIT, 0, dreg); }
+inline void emit_rol_m64_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Ev_CL, OP_64BIT, 0, memref); }
+
+inline void emit_ror_r64_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_64BIT, 1, dreg, imm); }
+inline void emit_ror_m64_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_64BIT, 1, memref, imm); }
+inline void emit_ror_r64_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Ev_CL, OP_64BIT, 1, dreg); }
+inline void emit_ror_m64_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Ev_CL, OP_64BIT, 1, memref); }
+
+inline void emit_rcl_r64_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_64BIT, 2, dreg, imm); }
+inline void emit_rcl_m64_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_64BIT, 2, memref, imm); }
+inline void emit_rcl_r64_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Ev_CL, OP_64BIT, 2, dreg); }
+inline void emit_rcl_m64_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Ev_CL, OP_64BIT, 2, memref); }
+
+inline void emit_rcr_r64_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_64BIT, 3, dreg, imm); }
+inline void emit_rcr_m64_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_64BIT, 3, memref, imm); }
+inline void emit_rcr_r64_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Ev_CL, OP_64BIT, 3, dreg); }
+inline void emit_rcr_m64_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Ev_CL, OP_64BIT, 3, memref); }
+
+inline void emit_shl_r64_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_64BIT, 4, dreg, imm); }
+inline void emit_shl_m64_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_64BIT, 4, memref, imm); }
+inline void emit_shl_r64_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Ev_CL, OP_64BIT, 4, dreg); }
+inline void emit_shl_m64_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Ev_CL, OP_64BIT, 4, memref); }
+
+inline void emit_shr_r64_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_64BIT, 5, dreg, imm); }
+inline void emit_shr_m64_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_64BIT, 5, memref, imm); }
+inline void emit_shr_r64_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Ev_CL, OP_64BIT, 5, dreg); }
+inline void emit_shr_m64_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Ev_CL, OP_64BIT, 5, memref); }
+
+inline void emit_sar_r64_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_shift_reg_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_64BIT, 7, dreg, imm); }
+inline void emit_sar_m64_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_shift_mem_imm(emitptr, OP_G2_Ev_1, OP_G2_Ev_Ib, OP_64BIT, 7, memref, imm); }
+inline void emit_sar_r64_cl(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G2_Ev_CL, OP_64BIT, 7, dreg); }
+inline void emit_sar_m64_cl(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G2_Ev_CL, OP_64BIT, 7, memref); }
+
+inline void emit_shld_r64_r64_imm(x86code *&emitptr, UINT8 dreg, UINT8 sreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_SHLD_Ev_Gv_Ib, OP_64BIT, sreg, dreg, imm); }
+inline void emit_shld_m64_r64_imm(x86code *&emitptr, x86_memref memref, UINT8 sreg, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_SHLD_Ev_Gv_Ib, OP_64BIT, sreg, memref, imm); }
+inline void emit_shld_r64_r64_cl(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_SHLD_Ev_Gv_CL, OP_64BIT, sreg, dreg); }
+inline void emit_shld_m64_r64_cl(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_SHLD_Ev_Gv_CL, OP_64BIT, sreg, memref); }
+
+inline void emit_shrd_r64_r64_imm(x86code *&emitptr, UINT8 dreg, UINT8 sreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_SHRD_Ev_Gv_Ib, OP_64BIT, sreg, dreg, imm); }
+inline void emit_shrd_m64_r64_imm(x86code *&emitptr, x86_memref memref, UINT8 sreg, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_SHRD_Ev_Gv_Ib, OP_64BIT, sreg, memref, imm); }
+inline void emit_shrd_r64_r64_cl(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_SHRD_Ev_Gv_CL, OP_64BIT, sreg, dreg); }
+inline void emit_shrd_m64_r64_cl(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_SHRD_Ev_Gv_CL, OP_64BIT, sreg, memref); }
+
+#endif
+
+
+
+//**************************************************************************
+// GROUP3 EMITTERS
+//**************************************************************************
+
+//-------------------------------------------------
+// emit_group3_r8_*
+//-------------------------------------------------
+
+inline void emit_not_r8(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G3_Ev, OP_32BIT, 2, dreg); }
+inline void emit_not_m8(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G3_Ev, OP_32BIT, 2, memref); }
+
+inline void emit_neg_r8(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G3_Ev, OP_32BIT, 3, dreg); }
+inline void emit_neg_m8(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G3_Ev, OP_32BIT, 3, memref); }
+
+inline void emit_mul_r8(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G3_Ev, OP_32BIT, 4, dreg); }
+inline void emit_mul_m8(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G3_Ev, OP_32BIT, 4, memref); }
+
+inline void emit_imul_r8(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G3_Ev, OP_32BIT, 5, dreg); }
+inline void emit_imul_m8(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G3_Ev, OP_32BIT, 5, memref); }
+
+inline void emit_div_r8(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G3_Ev, OP_32BIT, 6, dreg); }
+inline void emit_div_m8(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G3_Ev, OP_32BIT, 6, memref); }
+
+inline void emit_idiv_r8(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G3_Ev, OP_32BIT, 7, dreg); }
+inline void emit_idiv_m8(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G3_Ev, OP_32BIT, 7, memref); }
+
+
+//-------------------------------------------------
+// emit_group3_r16_*
+//-------------------------------------------------
+
+inline void emit_not_r16(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G3_Ev, OP_16BIT, 2, dreg); }
+inline void emit_not_m16(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G3_Ev, OP_16BIT, 2, memref); }
+
+inline void emit_neg_r16(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G3_Ev, OP_16BIT, 3, dreg); }
+inline void emit_neg_m16(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G3_Ev, OP_16BIT, 3, memref); }
+
+inline void emit_mul_r16(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G3_Ev, OP_16BIT, 4, dreg); }
+inline void emit_mul_m16(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G3_Ev, OP_16BIT, 4, memref); }
+
+inline void emit_imul_r16(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G3_Ev, OP_16BIT, 5, dreg); }
+inline void emit_imul_m16(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G3_Ev, OP_16BIT, 5, memref); }
+
+inline void emit_div_r16(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G3_Ev, OP_16BIT, 6, dreg); }
+inline void emit_div_m16(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G3_Ev, OP_16BIT, 6, memref); }
+
+inline void emit_idiv_r16(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G3_Ev, OP_16BIT, 7, dreg); }
+inline void emit_idiv_m16(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G3_Ev, OP_16BIT, 7, memref); }
+
+
+//-------------------------------------------------
+// emit_group3_r32_*
+//-------------------------------------------------
+
+inline void emit_not_r32(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G3_Ev, OP_32BIT, 2, dreg); }
+inline void emit_not_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G3_Ev, OP_32BIT, 2, memref); }
+
+inline void emit_neg_r32(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G3_Ev, OP_32BIT, 3, dreg); }
+inline void emit_neg_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G3_Ev, OP_32BIT, 3, memref); }
+
+inline void emit_mul_r32(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G3_Ev, OP_32BIT, 4, dreg); }
+inline void emit_mul_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G3_Ev, OP_32BIT, 4, memref); }
+
+inline void emit_imul_r32(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G3_Ev, OP_32BIT, 5, dreg); }
+inline void emit_imul_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G3_Ev, OP_32BIT, 5, memref); }
+
+inline void emit_div_r32(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G3_Ev, OP_32BIT, 6, dreg); }
+inline void emit_div_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G3_Ev, OP_32BIT, 6, memref); }
+
+inline void emit_idiv_r32(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G3_Ev, OP_32BIT, 7, dreg); }
+inline void emit_idiv_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G3_Ev, OP_32BIT, 7, memref); }
+
+
+//-------------------------------------------------
+// emit_group3_r64_*
+//-------------------------------------------------
+
+#if (X86EMIT_SIZE == 64)
+
+inline void emit_not_r64(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G3_Ev, OP_64BIT, 2, dreg); }
+inline void emit_not_m64(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G3_Ev, OP_64BIT, 2, memref); }
+
+inline void emit_neg_r64(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G3_Ev, OP_64BIT, 3, dreg); }
+inline void emit_neg_m64(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G3_Ev, OP_64BIT, 3, memref); }
+
+inline void emit_mul_r64(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G3_Ev, OP_64BIT, 4, dreg); }
+inline void emit_mul_m64(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G3_Ev, OP_64BIT, 4, memref); }
+
+inline void emit_imul_r64(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G3_Ev, OP_64BIT, 5, dreg); }
+inline void emit_imul_m64(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G3_Ev, OP_64BIT, 5, memref); }
+
+inline void emit_div_r64(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G3_Ev, OP_64BIT, 6, dreg); }
+inline void emit_div_m64(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G3_Ev, OP_64BIT, 6, memref); }
+
+inline void emit_idiv_r64(x86code *&emitptr, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_G3_Ev, OP_64BIT, 7, dreg); }
+inline void emit_idiv_m64(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G3_Ev, OP_64BIT, 7, memref); }
+
+#endif
+
+
+
+//**************************************************************************
+// IMUL EMITTERS
+//**************************************************************************
+
+//-------------------------------------------------
+// emit_imul_r16_*
+//-------------------------------------------------
+
+inline void emit_imul_r16_r16(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_IMUL_Gv_Ev, OP_16BIT, dreg, sreg); }
+inline void emit_imul_r16_m16(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_IMUL_Gv_Ev, OP_16BIT, dreg, memref); }
+inline void emit_imul_r16_r16_imm(x86code *&emitptr, UINT8 dreg, UINT8 sreg, INT16 imm) { emit_op_modrm_reg_imm816(emitptr, OP_IMUL_Gv_Ev_Ib, OP_IMUL_Gv_Ev_Iz, OP_16BIT, dreg, sreg, imm); }
+inline void emit_imul_r16_m16_imm(x86code *&emitptr, UINT8 dreg, x86_memref memref, INT16 imm) { emit_op_modrm_mem_imm816(emitptr, OP_IMUL_Gv_Ev_Ib, OP_IMUL_Gv_Ev_Iz, OP_16BIT, dreg, memref, imm); }
+
+inline void emit_imul_r32_r32(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_IMUL_Gv_Ev, OP_32BIT, dreg, sreg); }
+inline void emit_imul_r32_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_IMUL_Gv_Ev, OP_32BIT, dreg, memref); }
+inline void emit_imul_r32_r32_imm(x86code *&emitptr, UINT8 dreg, UINT8 sreg, INT32 imm) { emit_op_modrm_reg_imm832(emitptr, OP_IMUL_Gv_Ev_Ib, OP_IMUL_Gv_Ev_Iz, OP_32BIT, dreg, sreg, imm); }
+inline void emit_imul_r32_m32_imm(x86code *&emitptr, UINT8 dreg, x86_memref memref, INT32 imm) { emit_op_modrm_mem_imm832(emitptr, OP_IMUL_Gv_Ev_Ib, OP_IMUL_Gv_Ev_Iz, OP_32BIT, dreg, memref, imm); }
+
+#if (X86EMIT_SIZE == 64)
+
+inline void emit_imul_r64_r64(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_IMUL_Gv_Ev, OP_64BIT, dreg, sreg); }
+inline void emit_imul_r64_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_IMUL_Gv_Ev, OP_64BIT, dreg, memref); }
+inline void emit_imul_r64_r64_imm(x86code *&emitptr, UINT8 dreg, UINT8 sreg, INT32 imm) { emit_op_modrm_reg_imm832(emitptr, OP_IMUL_Gv_Ev_Ib, OP_IMUL_Gv_Ev_Iz, OP_64BIT, dreg, sreg, imm); }
+inline void emit_imul_r64_m64_imm(x86code *&emitptr, UINT8 dreg, x86_memref memref, INT32 imm) { emit_op_modrm_mem_imm832(emitptr, OP_IMUL_Gv_Ev_Ib, OP_IMUL_Gv_Ev_Iz, OP_64BIT, dreg, memref, imm); }
+
+#endif
+
+
+
+//**************************************************************************
+// BIT OPERATION EMITTERS
+//**************************************************************************
+
+//-------------------------------------------------
+// emit_bswap_*
+//-------------------------------------------------
+
+inline void emit_bswap_r32(x86code *&emitptr, UINT8 dreg) { emit_op_reg(emitptr, OP_BSWAP_EAX + (dreg & 7), OP_32BIT, dreg); }
+inline void emit_bswap_r64(x86code *&emitptr, UINT8 dreg) { emit_op_reg(emitptr, OP_BSWAP_EAX + (dreg & 7), OP_64BIT, dreg); }
+
+
+//-------------------------------------------------
+// emit_bsr/bsf_r16_*
+//-------------------------------------------------
+
+inline void emit_bsf_r16_r16(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_BSF_Gv_Ev, OP_16BIT, dreg, sreg); }
+inline void emit_bsf_r16_m16(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_BSF_Gv_Ev, OP_16BIT, dreg, memref); }
+inline void emit_bsr_r16_r16(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_BSR_Gv_Ev, OP_16BIT, dreg, sreg); }
+inline void emit_bsr_r16_m16(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_BSR_Gv_Ev, OP_16BIT, dreg, memref); }
+
+inline void emit_bsf_r32_r32(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_BSF_Gv_Ev, OP_32BIT, dreg, sreg); }
+inline void emit_bsf_r32_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_BSF_Gv_Ev, OP_32BIT, dreg, memref); }
+inline void emit_bsr_r32_r32(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_BSR_Gv_Ev, OP_32BIT, dreg, sreg); }
+inline void emit_bsr_r32_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_BSR_Gv_Ev, OP_32BIT, dreg, memref); }
+
+#if (X86EMIT_SIZE == 64)
+inline void emit_bsf_r64_r64(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_BSF_Gv_Ev, OP_64BIT, dreg, sreg); }
+inline void emit_bsf_r64_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_BSF_Gv_Ev, OP_64BIT, dreg, memref); }
+inline void emit_bsr_r64_r64(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_BSR_Gv_Ev, OP_64BIT, dreg, sreg); }
+inline void emit_bsr_r64_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_BSR_Gv_Ev, OP_64BIT, dreg, memref); }
+#endif
+
+
+//-------------------------------------------------
+// emit_bit_r16_*
+//-------------------------------------------------
+
+inline void emit_bt_r16_r16(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_BT_Ev_Gv, OP_16BIT, sreg, dreg); }
+inline void emit_bt_m16_r16(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_BT_Ev_Gv, OP_16BIT, sreg, memref); }
+inline void emit_bt_r16_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_G8_Ev_Ib, OP_16BIT, 4, dreg, imm); }
+inline void emit_bt_m16_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_G8_Ev_Ib, OP_16BIT, 4, memref, imm); }
+
+inline void emit_bts_r16_r16(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_BTS_Ev_Gv, OP_16BIT, sreg, dreg); }
+inline void emit_bts_m16_r16(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_BTS_Ev_Gv, OP_16BIT, sreg, memref); }
+inline void emit_bts_r16_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_G8_Ev_Ib, OP_16BIT, 5, dreg, imm); }
+inline void emit_bts_m16_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_G8_Ev_Ib, OP_16BIT, 5, memref, imm); }
+
+inline void emit_btr_r16_r16(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_BTR_Ev_Gv, OP_16BIT, sreg, dreg); }
+inline void emit_btr_m16_r16(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_BTR_Ev_Gv, OP_16BIT, sreg, memref); }
+inline void emit_btr_r16_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_G8_Ev_Ib, OP_16BIT, 6, dreg, imm); }
+inline void emit_btr_m16_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_G8_Ev_Ib, OP_16BIT, 6, memref, imm); }
+
+inline void emit_btc_r16_r16(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_BTC_Ev_Gv, OP_16BIT, sreg, dreg); }
+inline void emit_btc_m16_r16(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_BTC_Ev_Gv, OP_16BIT, sreg, memref); }
+inline void emit_btc_r16_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_G8_Ev_Ib, OP_16BIT, 7, dreg, imm); }
+inline void emit_btc_m16_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_G8_Ev_Ib, OP_16BIT, 7, memref, imm); }
+
+
+//-------------------------------------------------
+// emit_bit_r32_*
+//-------------------------------------------------
+
+inline void emit_bt_r32_r32(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_BT_Ev_Gv, OP_32BIT, sreg, dreg); }
+inline void emit_bt_m32_r32(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_BT_Ev_Gv, OP_32BIT, sreg, memref); }
+inline void emit_bt_r32_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_G8_Ev_Ib, OP_32BIT, 4, dreg, imm); }
+inline void emit_bt_m32_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_G8_Ev_Ib, OP_32BIT, 4, memref, imm); }
+
+inline void emit_bts_r32_r32(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_BTS_Ev_Gv, OP_32BIT, sreg, dreg); }
+inline void emit_bts_m32_r32(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_BTS_Ev_Gv, OP_32BIT, sreg, memref); }
+inline void emit_bts_r32_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_G8_Ev_Ib, OP_32BIT, 5, dreg, imm); }
+inline void emit_bts_m32_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_G8_Ev_Ib, OP_32BIT, 5, memref, imm); }
+
+inline void emit_btr_r32_r32(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_BTR_Ev_Gv, OP_32BIT, sreg, dreg); }
+inline void emit_btr_m32_r32(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_BTR_Ev_Gv, OP_32BIT, sreg, memref); }
+inline void emit_btr_r32_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_G8_Ev_Ib, OP_32BIT, 6, dreg, imm); }
+inline void emit_btr_m32_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_G8_Ev_Ib, OP_32BIT, 6, memref, imm); }
+
+inline void emit_btc_r32_r32(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_BTC_Ev_Gv, OP_32BIT, sreg, dreg); }
+inline void emit_btc_m32_r32(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_BTC_Ev_Gv, OP_32BIT, sreg, memref); }
+inline void emit_btc_r32_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_G8_Ev_Ib, OP_32BIT, 7, dreg, imm); }
+inline void emit_btc_m32_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_G8_Ev_Ib, OP_32BIT, 7, memref, imm); }
+
+
+//-------------------------------------------------
+// emit_bit_r64_*
+//-------------------------------------------------
+
+#if (X86EMIT_SIZE == 64)
+
+inline void emit_bt_r64_r64(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_BT_Ev_Gv, OP_64BIT, sreg, dreg); }
+inline void emit_bt_m64_r64(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_BT_Ev_Gv, OP_64BIT, sreg, memref); }
+inline void emit_bt_r64_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_G8_Ev_Ib, OP_64BIT, 4, dreg, imm); }
+inline void emit_bt_m64_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_G8_Ev_Ib, OP_64BIT, 4, memref, imm); }
+
+inline void emit_bts_r64_r64(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_BTS_Ev_Gv, OP_64BIT, sreg, dreg); }
+inline void emit_bts_m64_r64(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_BTS_Ev_Gv, OP_64BIT, sreg, memref); }
+inline void emit_bts_r64_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_G8_Ev_Ib, OP_64BIT, 5, dreg, imm); }
+inline void emit_bts_m64_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_G8_Ev_Ib, OP_64BIT, 5, memref, imm); }
+
+inline void emit_btr_r64_r64(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_BTR_Ev_Gv, OP_64BIT, sreg, dreg); }
+inline void emit_btr_m64_r64(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_BTR_Ev_Gv, OP_64BIT, sreg, memref); }
+inline void emit_btr_r64_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_G8_Ev_Ib, OP_64BIT, 6, dreg, imm); }
+inline void emit_btr_m64_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_G8_Ev_Ib, OP_64BIT, 6, memref, imm); }
+
+inline void emit_btc_r64_r64(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_BTC_Ev_Gv, OP_64BIT, sreg, dreg); }
+inline void emit_btc_m64_r64(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_BTC_Ev_Gv, OP_64BIT, sreg, memref); }
+inline void emit_btc_r64_imm(x86code *&emitptr, UINT8 dreg, UINT8 imm) { emit_op_modrm_reg_imm8(emitptr, OP_G8_Ev_Ib, OP_64BIT, 7, dreg, imm); }
+inline void emit_btc_m64_imm(x86code *&emitptr, x86_memref memref, UINT8 imm) { emit_op_modrm_mem_imm8(emitptr, OP_G8_Ev_Ib, OP_64BIT, 7, memref, imm); }
+
+#endif
+
+
+
+//**************************************************************************
+// LEA EMITTERS
+//**************************************************************************
+
+inline void emit_lea_r32_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_LEA_Gv_M, OP_32BIT, dreg, memref); }
+
+#if (X86EMIT_SIZE == 64)
+inline void emit_lea_r64_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_LEA_Gv_M, OP_64BIT, dreg, memref); }
+#endif
+
+
+
+//**************************************************************************
+// SET EMITTERS
+//**************************************************************************
+
+//-------------------------------------------------
+// emit_setcc_*
+//-------------------------------------------------
+
+inline void emit_setcc_r8(x86code *&emitptr, UINT8 cond, UINT8 dreg) { emit_op_modrm_reg(emitptr, OP_SETCC_O_Eb + cond, OP_32BIT, 0, dreg); }
+inline void emit_setcc_m8(x86code *&emitptr, UINT8 cond, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_SETCC_O_Eb + cond, OP_32BIT, 0, memref); }
+
+
+
+//**************************************************************************
+// SIMPLE FPU EMITTERS
+//**************************************************************************
+
+#if (X86EMIT_SIZE == 32)
+
+inline void emit_fnop(x86code *&emitptr) { emit_op_simple(emitptr, OP_FNOP, OP_32BIT); }
+inline void emit_fchs(x86code *&emitptr) { emit_op_simple(emitptr, OP_FCHS, OP_32BIT); }
+inline void emit_fabs(x86code *&emitptr) { emit_op_simple(emitptr, OP_FABS, OP_32BIT); }
+inline void emit_ftst(x86code *&emitptr) { emit_op_simple(emitptr, OP_FTST, OP_32BIT); }
+inline void emit_fxam(x86code *&emitptr) { emit_op_simple(emitptr, OP_FXAM, OP_32BIT); }
+inline void emit_fld1(x86code *&emitptr) { emit_op_simple(emitptr, OP_FLD1, OP_32BIT); }
+inline void emit_fldl2t(x86code *&emitptr) { emit_op_simple(emitptr, OP_FLDL2T, OP_32BIT); }
+inline void emit_fldl2e(x86code *&emitptr) { emit_op_simple(emitptr, OP_FLDL2E, OP_32BIT); }
+inline void emit_fldpi(x86code *&emitptr) { emit_op_simple(emitptr, OP_FLDPI, OP_32BIT); }
+inline void emit_fldlg2(x86code *&emitptr) { emit_op_simple(emitptr, OP_FLDLG2, OP_32BIT); }
+inline void emit_fldln2(x86code *&emitptr) { emit_op_simple(emitptr, OP_FLDLN2, OP_32BIT); }
+inline void emit_fldz(x86code *&emitptr) { emit_op_simple(emitptr, OP_FLDZ, OP_32BIT); }
+inline void emit_f2xm1(x86code *&emitptr) { emit_op_simple(emitptr, OP_F2XM1, OP_32BIT); }
+inline void emit_fyl2x(x86code *&emitptr) { emit_op_simple(emitptr, OP_FYL2X, OP_32BIT); }
+inline void emit_fptan(x86code *&emitptr) { emit_op_simple(emitptr, OP_FPTAN, OP_32BIT); }
+inline void emit_fpatan(x86code *&emitptr) { emit_op_simple(emitptr, OP_FPATAN, OP_32BIT); }
+inline void emit_fxtract(x86code *&emitptr) { emit_op_simple(emitptr, OP_FXTRACT, OP_32BIT); }
+inline void emit_fprem1(x86code *&emitptr) { emit_op_simple(emitptr, OP_FPREM1, OP_32BIT); }
+inline void emit_fdecstp(x86code *&emitptr) { emit_op_simple(emitptr, OP_FDECSTP, OP_32BIT); }
+inline void emit_fincstp(x86code *&emitptr) { emit_op_simple(emitptr, OP_FINCSTP, OP_32BIT); }
+inline void emit_fprem(x86code *&emitptr) { emit_op_simple(emitptr, OP_FPREM, OP_32BIT); }
+inline void emit_fyl2xp1(x86code *&emitptr) { emit_op_simple(emitptr, OP_FYL2XP1, OP_32BIT); }
+inline void emit_fsqrt(x86code *&emitptr) { emit_op_simple(emitptr, OP_FSQRT, OP_32BIT); }
+inline void emit_fsincos(x86code *&emitptr) { emit_op_simple(emitptr, OP_FSINCOS, OP_32BIT); }
+inline void emit_frndint(x86code *&emitptr) { emit_op_simple(emitptr, OP_FRNDINT, OP_32BIT); }
+inline void emit_fscale(x86code *&emitptr) { emit_op_simple(emitptr, OP_FSCALE, OP_32BIT); }
+inline void emit_fsin(x86code *&emitptr) { emit_op_simple(emitptr, OP_FSIN, OP_32BIT); }
+inline void emit_fcos(x86code *&emitptr) { emit_op_simple(emitptr, OP_FCOS, OP_32BIT); }
+inline void emit_fucompp(x86code *&emitptr) { emit_op_simple(emitptr, OP_FUCOMPP, OP_32BIT); }
+inline void emit_fclex(x86code *&emitptr) { emit_op_simple(emitptr, OP_FCLEX, OP_32BIT); }
+inline void emit_finit(x86code *&emitptr) { emit_op_simple(emitptr, OP_FINIT, OP_32BIT); }
+inline void emit_fcompp(x86code *&emitptr) { emit_op_simple(emitptr, OP_FCOMPP, OP_32BIT); }
+inline void emit_fstsw_ax(x86code *&emitptr) { emit_op_simple(emitptr, OP_FSTSW_AX, OP_32BIT); }
+
+#endif
+
+
+
+//**************************************************************************
+// REGISTER-BASED FPU EMITTERS
+//**************************************************************************
+
+#if (X86EMIT_SIZE == 32)
+
+inline void emit_ffree_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FFREE_STn + reg, OP_32BIT); }
+inline void emit_fst_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FST_STn + reg, OP_32BIT); }
+inline void emit_fstp_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FSTP_STn + reg, OP_32BIT); }
+inline void emit_fucomp_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FUCOMP_STn + reg, OP_32BIT); }
+
+inline void emit_fadd_st0_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FADD_ST0_STn + reg, OP_32BIT); }
+inline void emit_fmul_st0_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FMUL_ST0_STn + reg, OP_32BIT); }
+inline void emit_fcom_st0_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FCOM_ST0_STn + reg, OP_32BIT); }
+inline void emit_fcomp_st0_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FCOMP_ST0_STn + reg, OP_32BIT); }
+inline void emit_fsub_st0_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FSUB_ST0_STn + reg, OP_32BIT); }
+inline void emit_fsubr_st0_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FSUBR_ST0_STn + reg, OP_32BIT); }
+inline void emit_fdiv_st0_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FDIV_ST0_STn + reg, OP_32BIT); }
+inline void emit_fdivr_st0_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FDIVR_ST0_STn + reg, OP_32BIT); }
+inline void emit_fld_st0_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FLD_ST0_STn + reg, OP_32BIT); }
+inline void emit_fxch_st0_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FXCH_ST0_STn + reg, OP_32BIT); }
+inline void emit_fcmovb_st0_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FCMOVB_ST0_STn + reg, OP_32BIT); }
+inline void emit_fcmove_st0_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FCMOVE_ST0_STn + reg, OP_32BIT); }
+inline void emit_fcmovbe_st0_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FCMOVBE_ST0_STn + reg, OP_32BIT); }
+inline void emit_fcmovu_st0_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FCMOVU_ST0_STn + reg, OP_32BIT); }
+inline void emit_fcmovnb_st0_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FCMOVNB_ST0_STn + reg, OP_32BIT); }
+inline void emit_fcmovne_st0_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FCMOVNE_ST0_STn + reg, OP_32BIT); }
+inline void emit_fcmovnbe_st0_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FCMOVNBE_ST0_STn + reg, OP_32BIT); }
+inline void emit_fcmovnu_st0_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FCMOVNU_ST0_STn + reg, OP_32BIT); }
+inline void emit_fucomi_st0_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FUCOMI_ST0_STn + reg, OP_32BIT); }
+inline void emit_fcomi_st0_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FCOMI_ST0_STn + reg, OP_32BIT); }
+inline void emit_fcomip_st0_stn(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FCOMIP_ST0_STn + reg, OP_32BIT); }
+
+inline void emit_fadd_stn_st0(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FADD_STn_ST0 + reg, OP_32BIT); }
+inline void emit_fmul_stn_st0(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FMUL_STn_ST0 + reg, OP_32BIT); }
+inline void emit_fsubr_stn_st0(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FSUBR_STn_ST0 + reg, OP_32BIT); }
+inline void emit_fsub_stn_st0(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FSUB_STn_ST0 + reg, OP_32BIT); }
+inline void emit_fdivr_stn_st0(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FDIVR_STn_ST0 + reg, OP_32BIT); }
+inline void emit_fdiv_stn_st0(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FDIV_STn_ST0 + reg, OP_32BIT); }
+inline void emit_fucom_stn_st0(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FUCOM_STn_ST0 + reg, OP_32BIT); }
+inline void emit_faddp_stn_st0(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FADDP_STn_ST0 + reg, OP_32BIT); }
+inline void emit_fmulp_stn_st0(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FMULP_STn_ST0 + reg, OP_32BIT); }
+inline void emit_fsubrp_stn_st0(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FSUBRP_STn_ST0 + reg, OP_32BIT); }
+inline void emit_fsubp_stn_st0(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FSUBP_STn_ST0 + reg, OP_32BIT); }
+inline void emit_fdivrp_stn_st0(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FDIVRP_STn_ST0 + reg, OP_32BIT); }
+inline void emit_fdivp_stn_st0(x86code *&emitptr, UINT8 reg) { emit_op_simple(emitptr, OP_FDIVP_STn_ST0 + reg, OP_32BIT); }
+
+inline void emit_faddp(x86code *&emitptr) { emit_faddp_stn_st0(emitptr, 1); }
+inline void emit_fmulp(x86code *&emitptr) { emit_fmulp_stn_st0(emitptr, 1); }
+inline void emit_fsubrp(x86code *&emitptr) { emit_fsubrp_stn_st0(emitptr, 1); }
+inline void emit_fsubp(x86code *&emitptr) { emit_fsubp_stn_st0(emitptr, 1); }
+inline void emit_fdivrp(x86code *&emitptr) { emit_fdivrp_stn_st0(emitptr, 1); }
+inline void emit_fdivp(x86code *&emitptr) { emit_fdivp_stn_st0(emitptr, 1); }
+
+#endif
+
+
+
+//**************************************************************************
+// MEMORY FPU EMITTERS
+//**************************************************************************
+
+#if (X86EMIT_SIZE == 32)
+
+inline void emit_fadd_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_D8, OP_32BIT, 0, memref); }
+inline void emit_fmul_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_D8, OP_32BIT, 1, memref); }
+inline void emit_fcom_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_D8, OP_32BIT, 2, memref); }
+inline void emit_fcomp_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_D8, OP_32BIT, 3, memref); }
+inline void emit_fsub_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_D8, OP_32BIT, 4, memref); }
+inline void emit_fsubr_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_D8, OP_32BIT, 5, memref); }
+inline void emit_fdiv_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_D8, OP_32BIT, 6, memref); }
+inline void emit_fdivr_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_D8, OP_32BIT, 7, memref); }
+
+inline void emit_fld_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_D9, OP_32BIT, 0, memref); }
+inline void emit_fst_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_D9, OP_32BIT, 2, memref); }
+inline void emit_fstp_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_D9, OP_32BIT, 3, memref); }
+inline void emit_fldenv_m(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_D9, OP_32BIT, 4, memref); }
+inline void emit_fldcw_m16(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_D9, OP_32BIT, 5, memref); }
+inline void emit_fstenv_m(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_D9, OP_32BIT, 6, memref); }
+inline void emit_fstcw_m16(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_D9, OP_32BIT, 7, memref); }
+
+inline void emit_fiadd_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DA, OP_32BIT, 0, memref); }
+inline void emit_fimul_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DA, OP_32BIT, 1, memref); }
+inline void emit_ficom_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DA, OP_32BIT, 2, memref); }
+inline void emit_ficomp_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DA, OP_32BIT, 3, memref); }
+inline void emit_fisub_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DA, OP_32BIT, 4, memref); }
+inline void emit_fisubr_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DA, OP_32BIT, 5, memref); }
+inline void emit_fidiv_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DA, OP_32BIT, 6, memref); }
+inline void emit_fidivr_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DA, OP_32BIT, 7, memref); }
+
+inline void emit_fild_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DB, OP_32BIT, 0, memref); }
+inline void emit_fisttp_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DB, OP_32BIT, 1, memref); }
+inline void emit_fist_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DB, OP_32BIT, 2, memref); }
+inline void emit_fistp_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DB, OP_32BIT, 3, memref); }
+inline void emit_fld_m80(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DB, OP_32BIT, 5, memref); }
+inline void emit_fstp_m80(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DB, OP_32BIT, 7, memref); }
+
+inline void emit_fadd_m64(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DC, OP_32BIT, 0, memref); }
+inline void emit_fmul_m64(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DC, OP_32BIT, 1, memref); }
+inline void emit_fcom_m64(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DC, OP_32BIT, 2, memref); }
+inline void emit_fcomp_m64(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DC, OP_32BIT, 3, memref); }
+inline void emit_fsub_m64(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DC, OP_32BIT, 4, memref); }
+inline void emit_fsubr_m64(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DC, OP_32BIT, 5, memref); }
+inline void emit_fdiv_m64(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DC, OP_32BIT, 6, memref); }
+inline void emit_fdivr_m64(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DC, OP_32BIT, 7, memref); }
+
+inline void emit_fld_m64(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DD, OP_32BIT, 0, memref); }
+inline void emit_fisttp_m64(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DD, OP_32BIT, 1, memref); }
+inline void emit_fst_m64(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DD, OP_32BIT, 2, memref); }
+inline void emit_fstp_m64(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DD, OP_32BIT, 3, memref); }
+inline void emit_frstor_m(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DD, OP_32BIT, 4, memref); }
+inline void emit_fsave_m(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DD, OP_32BIT, 6, memref); }
+inline void emit_fstsw_m16(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DD, OP_32BIT, 7, memref); }
+
+inline void emit_fiadd_m16(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DE, OP_32BIT, 0, memref); }
+inline void emit_fimul_m16(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DE, OP_32BIT, 1, memref); }
+inline void emit_ficom_m16(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DE, OP_32BIT, 2, memref); }
+inline void emit_ficomp_m16(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DE, OP_32BIT, 3, memref); }
+inline void emit_fisub_m16(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DE, OP_32BIT, 4, memref); }
+inline void emit_fisubr_m16(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DE, OP_32BIT, 5, memref); }
+inline void emit_fidiv_m16(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DE, OP_32BIT, 6, memref); }
+inline void emit_fidivr_m16(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DE, OP_32BIT, 7, memref); }
+
+inline void emit_fild_m16(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DF, OP_32BIT, 0, memref); }
+inline void emit_fisttp_m16(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DF, OP_32BIT, 1, memref); }
+inline void emit_fist_m16(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DF, OP_32BIT, 2, memref); }
+inline void emit_fistp_m16(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DF, OP_32BIT, 3, memref); }
+inline void emit_fbld_m80(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DF, OP_32BIT, 4, memref); }
+inline void emit_fild_m64(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DF, OP_32BIT, 5, memref); }
+inline void emit_fbstp_m80(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DF, OP_32BIT, 6, memref); }
+inline void emit_fistp_m64(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ESC_DF, OP_32BIT, 7, memref); }
+
+#endif
+
+
+
+//**************************************************************************
+// GROUP16 EMITTERS
+//**************************************************************************
+
+inline void emit_ldmxcsr_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G16, OP_32BIT, 2, memref); }
+inline void emit_stmxcsr_m32(x86code *&emitptr, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_G16, OP_32BIT, 3, memref); }
+
+
+
+//**************************************************************************
+// MISC SSE EMITTERS
+//**************************************************************************
+
+inline void emit_movd_r128_r32(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOVD_Vd_Ed, OP_32BIT, dreg, sreg); }
+inline void emit_movd_r128_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MOVD_Vd_Ed, OP_32BIT, dreg, memref); }
+inline void emit_movd_r32_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOVD_Ed_Vd, OP_32BIT, sreg, dreg); }
+inline void emit_movd_m32_r128(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_MOVD_Ed_Vd, OP_32BIT, sreg, memref); }
+
+#if (X86EMIT_SIZE == 64)
+
+inline void emit_movq_r128_r64(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOVD_Vd_Ed, OP_64BIT, dreg, sreg); }
+inline void emit_movq_r128_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MOVD_Vd_Ed, OP_64BIT, dreg, memref); }
+inline void emit_movq_r64_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOVD_Ed_Vd, OP_64BIT, sreg, dreg); }
+inline void emit_movq_m64_r128(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_MOVD_Ed_Vd, OP_64BIT, sreg, memref); }
+
+#endif
+
+
+
+//**************************************************************************
+// SSE SCALAR SINGLE EMITTERS
+//**************************************************************************
+
+inline void emit_movss_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOVSS_Vss_Wss, OP_32BIT, dreg, sreg); }
+inline void emit_movss_r128_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MOVSS_Vss_Wss, OP_32BIT, dreg, memref); }
+inline void emit_movss_m32_r128(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_MOVSS_Wss_Vss, OP_32BIT, sreg, memref); }
+
+inline void emit_addss_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_ADDSS_Vss_Wss, OP_32BIT, dreg, sreg); }
+inline void emit_addss_r128_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ADDSS_Vss_Wss, OP_32BIT, dreg, memref); }
+
+inline void emit_subss_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_SUBSS_Vss_Wss, OP_32BIT, dreg, sreg); }
+inline void emit_subss_r128_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_SUBSS_Vss_Wss, OP_32BIT, dreg, memref); }
+
+inline void emit_mulss_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MULSS_Vss_Wss, OP_32BIT, dreg, sreg); }
+inline void emit_mulss_r128_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MULSS_Vss_Wss, OP_32BIT, dreg, memref); }
+
+inline void emit_divss_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_DIVSS_Vss_Wss, OP_32BIT, dreg, sreg); }
+inline void emit_divss_r128_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_DIVSS_Vss_Wss, OP_32BIT, dreg, memref); }
+
+inline void emit_rcpss_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_RCPSS_Vss_Wss, OP_32BIT, dreg, sreg); }
+inline void emit_rcpss_r128_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_RCPSS_Vss_Wss, OP_32BIT, dreg, memref); }
+
+inline void emit_sqrtss_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_SQRTSS_Vss_Wss, OP_32BIT, dreg, sreg); }
+inline void emit_sqrtss_r128_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_SQRTSS_Vss_Wss, OP_32BIT, dreg, memref); }
+
+inline void emit_rsqrtss_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_RSQRTSS_Vss_Wss, OP_32BIT, dreg, sreg); }
+inline void emit_rsqrtss_r128_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_RSQRTSS_Vss_Wss, OP_32BIT, dreg, memref); }
+
+inline void emit_comiss_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_COMISS_Vss_Wss, OP_32BIT, dreg, sreg); }
+inline void emit_comiss_r128_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_COMISS_Vss_Wss, OP_32BIT, dreg, memref); }
+
+inline void emit_ucomiss_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_UCOMISS_Vss_Wss, OP_32BIT, dreg, sreg); }
+inline void emit_ucomiss_r128_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_UCOMISS_Vss_Wss, OP_32BIT, dreg, memref); }
+
+inline void emit_cvtsi2ss_r128_r32(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CVTSI2SS_Vss_Ed, OP_32BIT, dreg, sreg); }
+inline void emit_cvtsi2ss_r128_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CVTSI2SS_Vss_Ed, OP_32BIT, dreg, memref); }
+
+#if (X86EMIT_SIZE == 64)
+inline void emit_cvtsi2ss_r128_r64(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CVTSI2SS_Vss_Ed, OP_64BIT, dreg, sreg); }
+inline void emit_cvtsi2ss_r128_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CVTSI2SS_Vss_Ed, OP_64BIT, dreg, memref); }
+#endif
+
+inline void emit_cvtsd2ss_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CVTSD2SS_Vss_Wsd, OP_32BIT, dreg, sreg); }
+inline void emit_cvtsd2ss_r128_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CVTSD2SS_Vss_Wsd, OP_32BIT, dreg, memref); }
+
+inline void emit_cvtss2si_r32_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CVTSS2SI_Gd_Wss, OP_32BIT, dreg, sreg); }
+inline void emit_cvtss2si_r32_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CVTSS2SI_Gd_Wss, OP_32BIT, dreg, memref); }
+
+#if (X86EMIT_SIZE == 64)
+inline void emit_cvtss2si_r64_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CVTSS2SI_Gd_Wss, OP_64BIT, dreg, sreg); }
+inline void emit_cvtss2si_r64_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CVTSS2SI_Gd_Wss, OP_64BIT, dreg, memref); }
+#endif
+
+inline void emit_cvttss2si_r32_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CVTTSS2SI_Gd_Wss, OP_32BIT, dreg, sreg); }
+inline void emit_cvttss2si_r32_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CVTTSS2SI_Gd_Wss, OP_32BIT, dreg, memref); }
+
+#if (X86EMIT_SIZE == 64)
+inline void emit_cvttss2si_r64_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CVTTSS2SI_Gd_Wss, OP_64BIT, dreg, sreg); }
+inline void emit_cvttss2si_r64_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CVTTSS2SI_Gd_Wss, OP_64BIT, dreg, memref); }
+#endif
+
+inline void emit_roundss_r128_r128_imm(x86code *&emitptr, UINT8 dreg, UINT8 sreg, UINT8 imm) { emit_op_modrm_reg(emitptr, OP_ROUNDSS_Vss_Wss_Ib, OP_32BIT, dreg, sreg); emit_byte(emitptr, imm); }
+inline void emit_roundss_r128_m32_imm(x86code *&emitptr, UINT8 dreg, x86_memref memref, UINT8 imm) { emit_op_modrm_mem(emitptr, OP_ROUNDSS_Vss_Wss_Ib, OP_32BIT, dreg, memref); emit_byte(emitptr, imm); }
+
+
+
+//**************************************************************************
+// SSE PACKED SINGLE EMITTERS
+//**************************************************************************
+
+inline void emit_movps_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOVAPS_Vps_Wps, OP_32BIT, dreg, sreg); }
+inline void emit_movps_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MOVAPS_Vps_Wps, OP_32BIT, dreg, memref); }
+inline void emit_movps_m128_r128(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_MOVAPS_Wps_Vps, OP_32BIT, sreg, memref); }
+
+inline void emit_addps_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_ADDPS_Vps_Wps, OP_32BIT, dreg, sreg); }
+inline void emit_addps_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ADDPS_Vps_Wps, OP_32BIT, dreg, memref); }
+
+inline void emit_subps_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_SUBPS_Vps_Wps, OP_32BIT, dreg, sreg); }
+inline void emit_subps_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_SUBPS_Vps_Wps, OP_32BIT, dreg, memref); }
+
+inline void emit_mulps_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MULPS_Vps_Wps, OP_32BIT, dreg, sreg); }
+inline void emit_mulps_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MULPS_Vps_Wps, OP_32BIT, dreg, memref); }
+
+inline void emit_divps_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_DIVPS_Vps_Wps, OP_32BIT, dreg, sreg); }
+inline void emit_divps_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_DIVPS_Vps_Wps, OP_32BIT, dreg, memref); }
+
+inline void emit_rcpps_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_RCPPS_Vps_Wps, OP_32BIT, dreg, sreg); }
+inline void emit_rcpps_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_RCPPS_Vps_Wps, OP_32BIT, dreg, memref); }
+
+inline void emit_sqrtps_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_SQRTPS_Vps_Wps, OP_32BIT, dreg, sreg); }
+inline void emit_sqrtps_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_SQRTPS_Vps_Wps, OP_32BIT, dreg, memref); }
+
+inline void emit_rsqrtps_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_RSQRTPS_Vps_Wps, OP_32BIT, dreg, sreg); }
+inline void emit_rsqrtps_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_RSQRTPS_Vps_Wps, OP_32BIT, dreg, memref); }
+
+inline void emit_andps_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_ANDPS_Vps_Wps, OP_32BIT, dreg, sreg); }
+inline void emit_andps_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ANDPS_Vps_Wps, OP_32BIT, dreg, memref); }
+
+inline void emit_andnps_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_ANDNPS_Vps_Wps, OP_32BIT, dreg, sreg); }
+inline void emit_andnps_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ANDNPS_Vps_Wps, OP_32BIT, dreg, memref); }
+
+inline void emit_orps_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_ORPS_Vps_Wps, OP_32BIT, dreg, sreg); }
+inline void emit_orps_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ORPS_Vps_Wps, OP_32BIT, dreg, memref); }
+
+inline void emit_xorps_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_XORPS_Vps_Wps, OP_32BIT, dreg, sreg); }
+inline void emit_xorps_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_XORPS_Vps_Wps, OP_32BIT, dreg, memref); }
+
+inline void emit_cvtdq2ps_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CVTDQ2PS_Vps_Wdq, OP_32BIT, dreg, sreg); }
+inline void emit_cvtdq2ps_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CVTDQ2PS_Vps_Wdq, OP_32BIT, dreg, memref); }
+
+inline void emit_cvtpd2ps_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CVTPD2PS_Vps_Wpd, OP_32BIT, dreg, sreg); }
+inline void emit_cvtpd2ps_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CVTPD2PS_Vps_Wpd, OP_32BIT, dreg, memref); }
+
+inline void emit_cvtps2dq_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CVTPS2DQ_Vdq_Wps, OP_32BIT, dreg, sreg); }
+inline void emit_cvtps2dq_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CVTPS2DQ_Vdq_Wps, OP_32BIT, dreg, memref); }
+
+inline void emit_cvttps2dq_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CVTTPS2DQ_Vdq_Wps, OP_32BIT, dreg, sreg); }
+inline void emit_cvttps2dq_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CVTTPS2DQ_Vdq_Wps, OP_32BIT, dreg, memref); }
+
+inline void emit_roundps_r128_r128_imm(x86code *&emitptr, UINT8 dreg, UINT8 sreg, UINT8 imm) { emit_op_modrm_reg(emitptr, OP_ROUNDPS_Vdq_Wdq_Ib, OP_32BIT, dreg, sreg); emit_byte(emitptr, imm); }
+inline void emit_roundps_r128_m128_imm(x86code *&emitptr, UINT8 dreg, x86_memref memref, UINT8 imm) { emit_op_modrm_mem(emitptr, OP_ROUNDPS_Vdq_Wdq_Ib, OP_32BIT, dreg, memref); emit_byte(emitptr, imm); }
+
+
+
+//**************************************************************************
+// SSE SCALAR DOUBLE EMITTERS
+//**************************************************************************
+
+inline void emit_movsd_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOVSD_Vsd_Wsd, OP_32BIT, dreg, sreg); }
+inline void emit_movsd_r128_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MOVSD_Vsd_Wsd, OP_32BIT, dreg, memref); }
+inline void emit_movsd_m64_r128(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_MOVSD_Wsd_Vsd, OP_32BIT, sreg, memref); }
+
+inline void emit_addsd_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_ADDSD_Vsd_Wsd, OP_32BIT, dreg, sreg); }
+inline void emit_addsd_r128_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ADDSD_Vsd_Wsd, OP_32BIT, dreg, memref); }
+
+inline void emit_subsd_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_SUBSD_Vsd_Wsd, OP_32BIT, dreg, sreg); }
+inline void emit_subsd_r128_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_SUBSD_Vsd_Wsd, OP_32BIT, dreg, memref); }
+
+inline void emit_mulsd_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MULSD_Vsd_Wsd, OP_32BIT, dreg, sreg); }
+inline void emit_mulsd_r128_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MULSD_Vsd_Wsd, OP_32BIT, dreg, memref); }
+
+inline void emit_divsd_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_DIVSD_Vsd_Wsd, OP_32BIT, dreg, sreg); }
+inline void emit_divsd_r128_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_DIVSD_Vsd_Wsd, OP_32BIT, dreg, memref); }
+
+inline void emit_sqrtsd_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_SQRTSD_Vsd_Wsd, OP_32BIT, dreg, sreg); }
+inline void emit_sqrtsd_r128_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_SQRTSD_Vsd_Wsd, OP_32BIT, dreg, memref); }
+
+inline void emit_comisd_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_COMISD_Vsd_Wsd, OP_32BIT, dreg, sreg); }
+inline void emit_comisd_r128_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_COMISD_Vsd_Wsd, OP_32BIT, dreg, memref); }
+
+inline void emit_ucomisd_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_UCOMISD_Vsd_Wsd, OP_32BIT, dreg, sreg); }
+inline void emit_ucomisd_r128_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_UCOMISD_Vsd_Wsd, OP_32BIT, dreg, memref); }
+
+inline void emit_cvtsi2sd_r128_r32(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CVTSI2SD_Vsd_Ed, OP_32BIT, dreg, sreg); }
+inline void emit_cvtsi2sd_r128_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CVTSI2SD_Vsd_Ed, OP_32BIT, dreg, memref); }
+
+#if (X86EMIT_SIZE == 64)
+inline void emit_cvtsi2sd_r128_r64(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CVTSI2SD_Vsd_Ed, OP_64BIT, dreg, sreg); }
+inline void emit_cvtsi2sd_r128_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CVTSI2SD_Vsd_Ed, OP_64BIT, dreg, memref); }
+#endif
+
+inline void emit_cvtss2sd_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CVTSS2SD_Vsd_Wss, OP_32BIT, dreg, sreg); }
+inline void emit_cvtss2sd_r128_m32(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CVTSS2SD_Vsd_Wss, OP_32BIT, dreg, memref); }
+
+inline void emit_cvtsd2si_r32_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CVTSD2SI_Gd_Wsd, OP_32BIT, dreg, sreg); }
+inline void emit_cvtsd2si_r32_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CVTSD2SI_Gd_Wsd, OP_32BIT, dreg, memref); }
+
+#if (X86EMIT_SIZE == 64)
+inline void emit_cvtsd2si_r64_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CVTSD2SI_Gd_Wsd, OP_64BIT, dreg, sreg); }
+inline void emit_cvtsd2si_r64_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CVTSD2SI_Gd_Wsd, OP_64BIT, dreg, memref); }
+#endif
+
+inline void emit_cvttsd2si_r32_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CVTTSD2SI_Gd_Wsd, OP_32BIT, dreg, sreg); }
+inline void emit_cvttsd2si_r32_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CVTTSD2SI_Gd_Wsd, OP_32BIT, dreg, memref); }
+
+#if (X86EMIT_SIZE == 64)
+inline void emit_cvttsd2si_r64_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CVTTSD2SI_Gd_Wsd, OP_64BIT, dreg, sreg); }
+inline void emit_cvttsd2si_r64_m64(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CVTTSD2SI_Gd_Wsd, OP_64BIT, dreg, memref); }
+#endif
+
+inline void emit_roundsd_r128_r128_imm(x86code *&emitptr, UINT8 dreg, UINT8 sreg, UINT8 imm) { emit_op_modrm_reg(emitptr, OP_ROUNDSD_Vsd_Wsd_Ib, OP_32BIT, dreg, sreg); emit_byte(emitptr, imm); }
+inline void emit_roundsd_r128_m64_imm(x86code *&emitptr, UINT8 dreg, x86_memref memref, UINT8 imm) { emit_op_modrm_mem(emitptr, OP_ROUNDSD_Vsd_Wsd_Ib, OP_32BIT, dreg, memref); emit_byte(emitptr, imm); }
+
+
+
+//**************************************************************************
+// SSE PACKED DOUBLE EMITTERS
+//**************************************************************************
+
+inline void emit_movpd_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MOVAPD_Vpd_Wpd, OP_32BIT, dreg, sreg); }
+inline void emit_movpd_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MOVAPD_Vpd_Wpd, OP_32BIT, dreg, memref); }
+inline void emit_movpd_m128_r128(x86code *&emitptr, x86_memref memref, UINT8 sreg) { emit_op_modrm_mem(emitptr, OP_MOVAPD_Wpd_Vpd, OP_32BIT, sreg, memref); }
+
+inline void emit_addpd_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_ADDPD_Vpd_Wpd, OP_32BIT, dreg, sreg); }
+inline void emit_addpd_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ADDPD_Vpd_Wpd, OP_32BIT, dreg, memref); }
+
+inline void emit_subpd_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_SUBPD_Vpd_Wpd, OP_32BIT, dreg, sreg); }
+inline void emit_subpd_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_SUBPD_Vpd_Wpd, OP_32BIT, dreg, memref); }
+
+inline void emit_mulpd_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_MULPD_Vpd_Wpd, OP_32BIT, dreg, sreg); }
+inline void emit_mulpd_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_MULPD_Vpd_Wpd, OP_32BIT, dreg, memref); }
+
+inline void emit_divpd_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_DIVPD_Vpd_Wpd, OP_32BIT, dreg, sreg); }
+inline void emit_divpd_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_DIVPD_Vpd_Wpd, OP_32BIT, dreg, memref); }
+
+inline void emit_sqrtpd_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_SQRTPD_Vpd_Wpd, OP_32BIT, dreg, sreg); }
+inline void emit_sqrtpd_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_SQRTPD_Vpd_Wpd, OP_32BIT, dreg, memref); }
+
+inline void emit_andpd_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_ANDPD_Vpd_Wpd, OP_32BIT, dreg, sreg); }
+inline void emit_andpd_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ANDPD_Vpd_Wpd, OP_32BIT, dreg, memref); }
+
+inline void emit_andnpd_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_ANDNPD_Vpd_Wpd, OP_32BIT, dreg, sreg); }
+inline void emit_andnpd_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ANDNPD_Vpd_Wpd, OP_32BIT, dreg, memref); }
+
+inline void emit_orpd_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_ORPD_Vpd_Wpd, OP_32BIT, dreg, sreg); }
+inline void emit_orpd_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_ORPD_Vpd_Wpd, OP_32BIT, dreg, memref); }
+
+inline void emit_xorpd_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_XORPD_Vpd_Wpd, OP_32BIT, dreg, sreg); }
+inline void emit_xorpd_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_XORPD_Vpd_Wpd, OP_32BIT, dreg, memref); }
+
+inline void emit_cvtdq2pd_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CVTDQ2PD_Vpd_Wq, OP_32BIT, dreg, sreg); }
+inline void emit_cvtdq2pd_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CVTDQ2PD_Vpd_Wq, OP_32BIT, dreg, memref); }
+
+inline void emit_cvtps2pd_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CVTPS2PD_Vpd_Wq, OP_32BIT, dreg, sreg); }
+inline void emit_cvtps2pd_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CVTPS2PD_Vpd_Wq, OP_32BIT, dreg, memref); }
+
+inline void emit_cvtpd2dq_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CVTPD2DQ_Vdq_Wpd, OP_32BIT, dreg, sreg); }
+inline void emit_cvtpd2dq_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CVTPD2DQ_Vdq_Wpd, OP_32BIT, dreg, memref); }
+
+inline void emit_cvttpd2dq_r128_r128(x86code *&emitptr, UINT8 dreg, UINT8 sreg) { emit_op_modrm_reg(emitptr, OP_CVTTPD2DQ_Vdq_Wpd, OP_32BIT, dreg, sreg); }
+inline void emit_cvttpd2dq_r128_m128(x86code *&emitptr, UINT8 dreg, x86_memref memref) { emit_op_modrm_mem(emitptr, OP_CVTTPD2DQ_Vdq_Wpd, OP_32BIT, dreg, memref); }
+
+inline void emit_roundpd_r128_r128_imm(x86code *&emitptr, UINT8 dreg, UINT8 sreg, UINT8 imm) { emit_op_modrm_reg(emitptr, OP_ROUNDPD_Vdq_Wdq_Ib, OP_32BIT, dreg, sreg); emit_byte(emitptr, imm); }
+inline void emit_roundpd_r128_m128_imm(x86code *&emitptr, UINT8 dreg, x86_memref memref, UINT8 imm) { emit_op_modrm_mem(emitptr, OP_ROUNDPD_Vdq_Wdq_Ib, OP_32BIT, dreg, memref); emit_byte(emitptr, imm); }
+
+};
+
+#undef X86EMIT_SIZE
+
+#endif
diff --git a/trunk/src/emu/cpu/x86log.c b/trunk/src/emu/cpu/x86log.c
new file mode 100644
index 00000000000..1a824d64c0d
--- /dev/null
+++ b/trunk/src/emu/cpu/x86log.c
@@ -0,0 +1,304 @@
+/***************************************************************************
+
+ x86log.c
+
+ x86/x64 code logging helpers.
+
+ Copyright Aaron Giles
+ Released for general use under the MAME license
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "x86log.h"
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* comment parameters */
+#define MAX_COMMENTS 4000
+#define MAX_DATA_RANGES 1000
+#define COMMENT_POOL_SIZE (MAX_COMMENTS * 40)
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/* code logging info */
+typedef struct _log_comment log_comment;
+struct _log_comment
+{
+ x86code * base;
+ const char * string;
+};
+
+
+/* data ranges */
+typedef struct _data_range_t data_range_t;
+struct _data_range_t
+{
+ x86code * base;
+ x86code * end;
+ int size;
+};
+
+
+/* the code logging context */
+struct _x86log_context
+{
+ astring filename; /* name of the file */
+ FILE * file; /* file we are logging to */
+
+ data_range_t data_range[MAX_DATA_RANGES]; /* list of data ranges */
+ int data_range_count; /* number of data ranges */
+
+ log_comment comment_list[MAX_COMMENTS]; /* list of comments */
+ int comment_count; /* number of live comments */
+
+ char comment_pool[COMMENT_POOL_SIZE];/* string pool to hold comments */
+ char * comment_pool_next; /* pointer to next string pool location */
+};
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void reset_log(x86log_context *log);
+extern int i386_dasm_one_ex(char *buffer, UINT64 eip, const UINT8 *oprom, int mode);
+
+
+
+/***************************************************************************
+ EXTERNAL INTERFACES
+***************************************************************************/
+
+/*-------------------------------------------------
+ x86log_create_context - create a new context
+-------------------------------------------------*/
+
+x86log_context *x86log_create_context(const char *filename)
+{
+ x86log_context *log;
+
+ /* allocate the log */
+ log = global_alloc_clear(x86log_context);
+
+ /* allocate the filename */
+ log->filename.cpy(filename);
+
+ /* reset things */
+ reset_log(log);
+ return log;
+}
+
+
+/*-------------------------------------------------
+ x86log_free_context - release a context
+-------------------------------------------------*/
+
+void x86log_free_context(x86log_context *log)
+{
+ /* close any open files */
+ if (log->file != NULL)
+ fclose(log->file);
+
+ /* free the structure */
+ global_free(log);
+}
+
+
+/*-------------------------------------------------
+ x86log_add_comment - add a comment associated
+ with a given code pointer
+-------------------------------------------------*/
+
+void x86log_add_comment(x86log_context *log, x86code *base, const char *format, ...)
+{
+ char *string = log->comment_pool_next;
+ log_comment *comment;
+ va_list va;
+
+ assert(log->comment_count < MAX_COMMENTS);
+ assert(log->comment_pool_next + strlen(format) + 256 < log->comment_pool + COMMENT_POOL_SIZE);
+
+ /* we assume comments are registered in order; enforce this */
+ assert(log->comment_count == 0 || base >= log->comment_list[log->comment_count - 1].base);
+
+ /* if we exceed the maxima, skip it */
+ if (log->comment_count >= MAX_COMMENTS)
+ return;
+ if (log->comment_pool_next + strlen(format) + 256 >= log->comment_pool + COMMENT_POOL_SIZE)
+ return;
+
+ /* do the printf to the string pool */
+ va_start(va, format);
+ log->comment_pool_next += vsprintf(log->comment_pool_next, format, va) + 1;
+ va_end(va);
+
+ /* fill in the new comment */
+ comment = &log->comment_list[log->comment_count++];
+ comment->base = base;
+ comment->string = string;
+}
+
+
+/*-------------------------------------------------
+ x86log_mark_as_data - mark a given range as
+ data for logging purposes
+-------------------------------------------------*/
+
+void x86log_mark_as_data(x86log_context *log, x86code *base, x86code *end, int size)
+{
+ data_range_t *data;
+
+ assert(log->data_range_count < MAX_DATA_RANGES);
+ assert(end >= base);
+ assert(size == 1 || size == 2 || size == 4 || size == 8);
+
+ /* we assume data ranges are registered in order; enforce this */
+ assert(log->data_range_count == 0 || base > log->data_range[log->data_range_count - 1].end);
+
+ /* if we exceed the maxima, skip it */
+ if (log->data_range_count >= MAX_DATA_RANGES)
+ return;
+
+ /* fill in the new range */
+ data = &log->data_range[log->data_range_count++];
+ data->base = base;
+ data->end = end;
+ data->size = size;
+}
+
+
+/*-------------------------------------------------
+ x86log_disasm_code_range - disassemble a range
+ of code and reset accumulated information
+-------------------------------------------------*/
+
+void x86log_disasm_code_range(x86log_context *log, const char *label, x86code *start, x86code *stop)
+{
+ const log_comment *lastcomment = &log->comment_list[log->comment_count];
+ const log_comment *curcomment = &log->comment_list[0];
+ const data_range_t *lastdata = &log->data_range[log->data_range_count];
+ const data_range_t *curdata = &log->data_range[0];
+ x86code *cur = start;
+
+ /* print the optional label */
+ if (label != NULL)
+ x86log_printf(log, "\n%s\n", label);
+
+ /* loop from the start until the cache top */
+ while (cur < stop)
+ {
+ char buffer[100];
+ int bytes;
+
+ /* skip past any past data ranges */
+ while (curdata < lastdata && cur > curdata->end)
+ curdata++;
+
+ /* skip past any past comments */
+ while (curcomment < lastcomment && cur > curcomment->base)
+ curcomment++;
+
+ /* if we're in a data range, output the next chunk and continue */
+ if (cur >= curdata->base && cur <= curdata->end)
+ {
+ bytes = curdata->size;
+ switch (curdata->size)
+ {
+ default:
+ case 1: sprintf(buffer, "db %02X", *cur); break;
+ case 2: sprintf(buffer, "dw %04X", *(UINT16 *)cur); break;
+ case 4: sprintf(buffer, "dd %08X", *(UINT32 *)cur); break;
+ case 8: sprintf(buffer, "dq %08X%08X", ((UINT32 *)cur)[1], ((UINT32 *)cur)[0]); break;
+ }
+ }
+
+ /* if we're not in the data range, skip filler opcodes */
+ else if (*cur == 0xcc)
+ {
+ cur++;
+ continue;
+ }
+
+ /* otherwise, do a disassembly of the current instruction */
+ else
+ {
+#ifdef PTR64
+ bytes = i386_dasm_one_ex(buffer, (FPTR)cur, cur, 64) & DASMFLAG_LENGTHMASK;
+#else
+ bytes = i386_dasm_one_ex(buffer, (FPTR)cur, cur, 32) & DASMFLAG_LENGTHMASK;
+#endif
+ }
+
+ /* if we have a matching comment, output it */
+ if (curcomment < lastcomment && cur == curcomment->base)
+ {
+ /* if we have additional matching comments at the same address, output them first */
+ for ( ; curcomment + 1 < lastcomment && cur == curcomment[1].base; curcomment++)
+ x86log_printf(log, "%p: %-50s; %s\n", cur, "", curcomment->string);
+ x86log_printf(log, "%p: %-50s; %s\n", cur, buffer, curcomment->string);
+ }
+
+ /* if we don't, just print the disassembly and move on */
+ else
+ x86log_printf(log, "%p: %s\n", cur, buffer);
+
+ /* advance past this instruction */
+ cur += bytes;
+ }
+
+ /* reset our state */
+ reset_log(log);
+}
+
+
+/*-------------------------------------------------
+ x86log_printf - manually printf information to
+ the log file
+-------------------------------------------------*/
+
+void x86log_printf(x86log_context *log, const char *format, ...)
+{
+ va_list va;
+
+ /* open the file, creating it if necessary */
+ if (log->file == NULL)
+ log->file = fopen(log->filename, "w");
+ if (log->file == NULL)
+ return;
+
+ /* do the printf */
+ va_start(va, format);
+ vfprintf(log->file, format, va);
+ va_end(va);
+
+ /* flush the file */
+ fflush(log->file);
+}
+
+
+
+/***************************************************************************
+ LOCAL FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ reset_log - reset the state of the log
+-------------------------------------------------*/
+
+static void reset_log(x86log_context *log)
+{
+ log->data_range_count = 0;
+ log->comment_count = 0;
+ log->comment_pool_next = log->comment_pool;
+}
diff --git a/trunk/src/emu/cpu/x86log.h b/trunk/src/emu/cpu/x86log.h
new file mode 100644
index 00000000000..ddaebfe43c6
--- /dev/null
+++ b/trunk/src/emu/cpu/x86log.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+
+ x86log.h
+
+ x86/x64 code logging helpers.
+
+ Copyright Aaron Giles
+ Released for general use under the MAME license
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __X86LOG_H__
+#define __X86LOG_H__
+
+#include "x86emit.h"
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _x86log_context x86log_context;
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+/* create a new context */
+x86log_context *x86log_create_context(const char *filename);
+
+/* release a context */
+void x86log_free_context(x86log_context *log);
+
+/* add a comment associated with a given code pointer */
+void x86log_add_comment(x86log_context *log, x86code *base, const char *format, ...) ATTR_PRINTF(3, 4);
+
+/* mark a given range as data for logging purposes */
+void x86log_mark_as_data(x86log_context *log, x86code *base, x86code *end, int size);
+
+/* disassemble a range of code and reset accumulated information */
+void x86log_disasm_code_range(x86log_context *log, const char *label, x86code *start, x86code *stop);
+
+/* manually printf information to the log file */
+void x86log_printf(x86log_context *log, const char *format, ...) ATTR_PRINTF(2, 3);
+
+
+#endif /* __X86LOG_H__ */
diff --git a/trunk/src/emu/cpu/z180/z180.c b/trunk/src/emu/cpu/z180/z180.c
new file mode 100644
index 00000000000..ceef0e23568
--- /dev/null
+++ b/trunk/src/emu/cpu/z180/z180.c
@@ -0,0 +1,2738 @@
+/*****************************************************************************
+ *
+ * z180.c
+ * Portable Z180 emulator V0.3
+ *
+ * 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.
+ *
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ TODO:
+ - HALT processing is not yet perfect. The manual states that
+ during HALT, all dma and internal i/o incl. timers continue to
+ work. Currently, only timers are implemented. Ideally, the
+ burn_cycles routine would go away and halt processing be
+ implemented in cpu_execute.
+ *****************************************************************************/
+
+/*****************************************************************************
+
+Z180 Info:
+
+Known clock speeds (from ZiLOG): 6, 8, 10, 20 & 33MHz
+
+ZiLOG Z180 codes:
+
+ Speed: 10 = 10MHZ
+ 20 = 20MHz
+ 33 = 33MHz
+Package: P = 60-Pin Plastic DIP
+ V = 68-Pin PLCC
+ F = 80-Pin QFP
+ Temp: S = 0C to +70C
+ E = -40C to +85C
+
+Environmanetal Flow: C = Plastic Standard
+
+
+Example from Ms.Pac-Man/Galaga - 20 year Reunion hardare (see src/mame/drivers/20pacgal.c):
+
+ CPU is Z8S18020VSC = Z180, 20MHz, 68-Pin PLCC, 0C to +70C, Plastic Standard
+
+
+Other CPUs that use a compatible Z180 core:
+
+Hitachi HD647180 series:
+ Available in QFP80, PLCC84 & DIP90 packages (the QFP80 is not pinout compatible)
+ The HD647180 also has an internal ROM
+
+ *****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "z180.h"
+#include "cpu/z80/z80daisy.h"
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+/* interrupt priorities */
+#define Z180_INT_TRAP 0 /* Undefined opcode */
+#define Z180_INT_NMI 1 /* NMI */
+#define Z180_INT_IRQ0 2 /* Execute IRQ1 */
+#define Z180_INT_IRQ1 3 /* Execute IRQ1 */
+#define Z180_INT_IRQ2 4 /* Execute IRQ2 */
+#define Z180_INT_PRT0 5 /* Internal PRT channel 0 */
+#define Z180_INT_PRT1 6 /* Internal PRT channel 1 */
+#define Z180_INT_DMA0 7 /* Internal DMA channel 0 */
+#define Z180_INT_DMA1 8 /* Internal DMA channel 1 */
+#define Z180_INT_CSIO 9 /* Internal CSI/O */
+#define Z180_INT_ASCI0 10 /* Internal ASCI channel 0 */
+#define Z180_INT_ASCI1 11 /* Internal ASCI channel 1 */
+#define Z180_INT_MAX Z180_INT_ASCI1
+
+/****************************************************************************/
+/* The Z180 registers. HALT is set to 1 when the CPU is halted, the refresh */
+/* register is calculated as follows: refresh=(Regs.R&127)|(Regs.R2&128) */
+/****************************************************************************/
+typedef struct _z180_state z180_state;
+struct _z180_state
+{
+ PAIR PREPC,PC,SP,AF,BC,DE,HL,IX,IY;
+ PAIR AF2,BC2,DE2,HL2;
+ UINT8 R,R2,IFF1,IFF2,HALT,IM,I;
+ UINT8 tmdr_latch; /* flag latched TMDR0H, TMDR1H values */
+ UINT8 read_tcr_tmdr[2]; /* flag to indicate that TCR or TMDR was read */
+ UINT32 iol; /* I/O line status bits */
+ UINT8 io[64]; /* 64 internal 8 bit registers */
+ offs_t mmu[16]; /* MMU address translation */
+ UINT8 tmdrh[2]; /* latched TMDR0H and TMDR1H values */
+ UINT16 tmdr_value[2]; /* TMDR values used byt PRT0 and PRT1 as down counter */
+ UINT8 tif[2]; /* TIF0 and TIF1 values */
+ UINT8 nmi_state; /* nmi line state */
+ UINT8 nmi_pending; /* nmi pending */
+ UINT8 irq_state[3]; /* irq line states (INT0,INT1,INT2) */
+ UINT8 int_pending[Z180_INT_MAX + 1]; /* interrupt pending */
+ UINT8 after_EI; /* are we in the EI shadow? */
+ UINT32 ea;
+ UINT8 timer_cnt; /* timer counter / divide by 20 */
+ UINT8 dma0_cnt; /* dma0 counter / divide by 20 */
+ UINT8 dma1_cnt; /* dma1 counter / divide by 20 */
+ z80_daisy_chain daisy;
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *iospace;
+ UINT8 rtemp;
+ UINT32 ioltemp;
+ int icount;
+ int extra_cycles; /* extra cpu cycles */
+ UINT8 *cc[6];
+};
+
+INLINE z180_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == Z180);
+ return (z180_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+static void set_irq_line(z180_state *cpustate, int irqline, int state);
+
+#define CF 0x01
+#define NF 0x02
+#define PF 0x04
+#define VF PF
+#define XF 0x08
+#define HF 0x10
+#define YF 0x20
+#define ZF 0x40
+#define SF 0x80
+
+/* I/O line status flags */
+#define Z180_CKA0 0x00000001 /* I/O asynchronous clock 0 (active high) or DREQ0 (mux) */
+#define Z180_CKA1 0x00000002 /* I/O asynchronous clock 1 (active high) or TEND1 (mux) */
+#define Z180_CKS 0x00000004 /* I/O serial clock (active high) */
+#define Z180_CTS0 0x00000100 /* I clear to send 0 (active low) */
+#define Z180_CTS1 0x00000200 /* I clear to send 1 (active low) or RXS (mux) */
+#define Z180_DCD0 0x00000400 /* I data carrier detect (active low) */
+#define Z180_DREQ0 0x00000800 /* I data request DMA ch 0 (active low) or CKA0 (mux) */
+#define Z180_DREQ1 0x00001000 /* I data request DMA ch 1 (active low) */
+#define Z180_RXA0 0x00002000 /* I asynchronous receive data 0 (active high) */
+#define Z180_RXA1 0x00004000 /* I asynchronous receive data 1 (active high) */
+#define Z180_RXS 0x00008000 /* I clocked serial receive data (active high) or CTS1 (mux) */
+#define Z180_RTS0 0x00010000 /* O request to send (active low) */
+#define Z180_TEND0 0x00020000 /* O transfer end 0 (active low) or CKA1 (mux) */
+#define Z180_TEND1 0x00040000 /* O transfer end 1 (active low) */
+#define Z180_A18_TOUT 0x00080000 /* O transfer out (PRT channel, active low) or A18 (mux) */
+#define Z180_TXA0 0x00100000 /* O asynchronous transmit data 0 (active high) */
+#define Z180_TXA1 0x00200000 /* O asynchronous transmit data 1 (active high) */
+#define Z180_TXS 0x00400000 /* O clocked serial transmit data (active high) */
+
+/*
+ * Prevent warnings on NetBSD. All identifiers beginning with an underscore
+ * followed by an uppercase letter are reserved by the C standard (ISO/IEC
+ * 9899:1999, 7.1.3) to be used by the implementation. It'd be best to rename
+ * all such instances, but this is less intrusive and error-prone.
+ */
+#undef _B
+#undef _C
+#undef _L
+
+#define _PPC PREPC.d /* previous program counter */
+
+#define _PCD PC.d
+#define _PC PC.w.l
+
+#define _SPD SP.d
+#define _SP SP.w.l
+
+#define _AFD AF.d
+#define _AF AF.w.l
+#define _A AF.b.h
+#define _F AF.b.l
+
+#define _BCD BC.d
+#define _BC BC.w.l
+#define _B BC.b.h
+#define _C BC.b.l
+
+#define _DED DE.d
+#define _DE DE.w.l
+#define _D DE.b.h
+#define _E DE.b.l
+
+#define _HLD HL.d
+#define _HL HL.w.l
+#define _H HL.b.h
+#define _L HL.b.l
+
+#define _IXD IX.d
+#define _IX IX.w.l
+#define _HX IX.b.h
+#define _LX IX.b.l
+
+#define _IYD IY.d
+#define _IY IY.w.l
+#define _HY IY.b.h
+#define _LY IY.b.l
+
+#define IO(n) io[(n)-Z180_CNTLA0]
+#define IO_CNTLA0 IO(Z180_CNTLA0)
+#define IO_CNTLA1 IO(Z180_CNTLA1)
+#define IO_CNTLB0 IO(Z180_CNTLB0)
+#define IO_CNTLB1 IO(Z180_CNTLB1)
+#define IO_STAT0 IO(Z180_STAT0)
+#define IO_STAT1 IO(Z180_STAT1)
+#define IO_TDR0 IO(Z180_TDR0)
+#define IO_TDR1 IO(Z180_TDR1)
+#define IO_RDR0 IO(Z180_RDR0)
+#define IO_RDR1 IO(Z180_RDR1)
+#define IO_CNTR IO(Z180_CNTR)
+#define IO_TRDR IO(Z180_TRDR)
+#define IO_TMDR0L IO(Z180_TMDR0L)
+#define IO_TMDR0H IO(Z180_TMDR0H)
+#define IO_RLDR0L IO(Z180_RLDR0L)
+#define IO_RLDR0H IO(Z180_RLDR0H)
+#define IO_TCR IO(Z180_TCR)
+#define IO_IO11 IO(Z180_IO11)
+#define IO_ASEXT0 IO(Z180_ASEXT0)
+#define IO_ASEXT1 IO(Z180_ASEXT1)
+#define IO_TMDR1L IO(Z180_TMDR1L)
+#define IO_TMDR1H IO(Z180_TMDR1H)
+#define IO_RLDR1L IO(Z180_RLDR1L)
+#define IO_RLDR1H IO(Z180_RLDR1H)
+#define IO_FRC IO(Z180_FRC)
+#define IO_IO19 IO(Z180_IO19)
+#define IO_ASTC0L IO(Z180_ASTC0L)
+#define IO_ASTC0H IO(Z180_ASTC0H)
+#define IO_ASTC1L IO(Z180_ASTC1L)
+#define IO_ASTC1H IO(Z180_ASTC1H)
+#define IO_CMR IO(Z180_CMR)
+#define IO_CCR IO(Z180_CCR)
+#define IO_SAR0L IO(Z180_SAR0L)
+#define IO_SAR0H IO(Z180_SAR0H)
+#define IO_SAR0B IO(Z180_SAR0B)
+#define IO_DAR0L IO(Z180_DAR0L)
+#define IO_DAR0H IO(Z180_DAR0H)
+#define IO_DAR0B IO(Z180_DAR0B)
+#define IO_BCR0L IO(Z180_BCR0L)
+#define IO_BCR0H IO(Z180_BCR0H)
+#define IO_MAR1L IO(Z180_MAR1L)
+#define IO_MAR1H IO(Z180_MAR1H)
+#define IO_MAR1B IO(Z180_MAR1B)
+#define IO_IAR1L IO(Z180_IAR1L)
+#define IO_IAR1H IO(Z180_IAR1H)
+#define IO_IAR1B IO(Z180_IAR1B)
+#define IO_BCR1L IO(Z180_BCR1L)
+#define IO_BCR1H IO(Z180_BCR1H)
+#define IO_DSTAT IO(Z180_DSTAT)
+#define IO_DMODE IO(Z180_DMODE)
+#define IO_DCNTL IO(Z180_DCNTL)
+#define IO_IL IO(Z180_IL)
+#define IO_ITC IO(Z180_ITC)
+#define IO_IO35 IO(Z180_IO35)
+#define IO_RCR IO(Z180_RCR)
+#define IO_IO37 IO(Z180_IO37)
+#define IO_CBR IO(Z180_CBR)
+#define IO_BBR IO(Z180_BBR)
+#define IO_CBAR IO(Z180_CBAR)
+#define IO_IO3B IO(Z180_IO3B)
+#define IO_IO3C IO(Z180_IO3C)
+#define IO_IO3D IO(Z180_IO3D)
+#define IO_OMCR IO(Z180_OMCR)
+#define IO_IOCR IO(Z180_IOCR)
+
+/* 00 ASCI control register A ch 0 */
+#define Z180_CNTLA0_MPE 0x80
+#define Z180_CNTLA0_RE 0x40
+#define Z180_CNTLA0_TE 0x20
+#define Z180_CNTLA0_RTS0 0x10
+#define Z180_CNTLA0_MPBR_EFR 0x08
+#define Z180_CNTLA0_MODE_DATA 0x04
+#define Z180_CNTLA0_MODE_PARITY 0x02
+#define Z180_CNTLA0_MODE_STOPB 0x01
+
+#define Z180_CNTLA0_RESET 0x10
+#define Z180_CNTLA0_RMASK 0xff
+#define Z180_CNTLA0_WMASK 0xff
+
+/* 01 ASCI control register A ch 1 */
+#define Z180_CNTLA1_MPE 0x80
+#define Z180_CNTLA1_RE 0x40
+#define Z180_CNTLA1_TE 0x20
+#define Z180_CNTLA1_CKA1D 0x10
+#define Z180_CNTLA1_MPBR_EFR 0x08
+#define Z180_CNTLA1_MODE 0x07
+
+#define Z180_CNTLA1_RESET 0x10
+#define Z180_CNTLA1_RMASK 0xff
+#define Z180_CNTLA1_WMASK 0xff
+
+/* 02 ASCI control register B ch 0 */
+#define Z180_CNTLB0_MPBT 0x80
+#define Z180_CNTLB0_MP 0x40
+#define Z180_CNTLB0_CTS_PS 0x20
+#define Z180_CNTLB0_PEO 0x10
+#define Z180_CNTLB0_DR 0x08
+#define Z180_CNTLB0_SS 0x07
+
+#define Z180_CNTLB0_RESET 0x07
+#define Z180_CNTLB0_RMASK 0xff
+#define Z180_CNTLB0_WMASK 0xff
+
+/* 03 ASCI control register B ch 1 */
+#define Z180_CNTLB1_MPBT 0x80
+#define Z180_CNTLB1_MP 0x40
+#define Z180_CNTLB1_CTS_PS 0x20
+#define Z180_CNTLB1_PEO 0x10
+#define Z180_CNTLB1_DR 0x08
+#define Z180_CNTLB1_SS 0x07
+
+#define Z180_CNTLB1_RESET 0x07
+#define Z180_CNTLB1_RMASK 0xff
+#define Z180_CNTLB1_WMASK 0xff
+
+/* 04 ASCI status register 0 */
+#define Z180_STAT0_RDRF 0x80
+#define Z180_STAT0_OVRN 0x40
+#define Z180_STAT0_PE 0x20
+#define Z180_STAT0_FE 0x10
+#define Z180_STAT0_RIE 0x08
+#define Z180_STAT0_DCD0 0x04
+#define Z180_STAT0_TDRE 0x02
+#define Z180_STAT0_TIE 0x01
+
+#define Z180_STAT0_RESET 0x00
+#define Z180_STAT0_RMASK 0xff
+#define Z180_STAT0_WMASK 0x09
+
+/* 05 ASCI status register 1 */
+#define Z180_STAT1_RDRF 0x80
+#define Z180_STAT1_OVRN 0x40
+#define Z180_STAT1_PE 0x20
+#define Z180_STAT1_FE 0x10
+#define Z180_STAT1_RIE 0x08
+#define Z180_STAT1_CTS1E 0x04
+#define Z180_STAT1_TDRE 0x02
+#define Z180_STAT1_TIE 0x01
+
+#define Z180_STAT1_RESET 0x00
+#define Z180_STAT1_RMASK 0xff
+#define Z180_STAT1_WMASK 0x0d
+
+/* 06 ASCI transmit data register 0 */
+#define Z180_TDR0_TDR 0xff
+
+#define Z180_TDR0_RESET 0x00
+#define Z180_TDR0_RMASK 0xff
+#define Z180_TDR0_WMASK 0xff
+
+/* 07 ASCI transmit data register 1 */
+#define Z180_TDR1_TDR 0xff
+
+#define Z180_TDR1_RESET 0x00
+#define Z180_TDR1_RMASK 0xff
+#define Z180_TDR1_WMASK 0xff
+
+/* 08 ASCI receive register 0 */
+#define Z180_RDR0_RDR 0xff
+
+#define Z180_RDR0_RESET 0x00
+#define Z180_RDR0_RMASK 0xff
+#define Z180_RDR0_WMASK 0xff
+
+/* 09 ASCI receive register 1 */
+#define Z180_RDR1_RDR 0xff
+
+#define Z180_RDR1_RESET 0x00
+#define Z180_RDR1_RMASK 0xff
+#define Z180_RDR1_WMASK 0xff
+
+/* 0a CSI/O control/status register */
+#define Z180_CNTR_EF 0x80
+#define Z180_CNTR_EIE 0x40
+#define Z180_CNTR_RE 0x20
+#define Z180_CNTR_TE 0x10
+#define Z180_CNTR_SS 0x07
+
+#define Z180_CNTR_RESET 0x07
+#define Z180_CNTR_RMASK 0xff
+#define Z180_CNTR_WMASK 0x7f
+
+/* 0b CSI/O transmit/receive register */
+#define Z180_TRDR_RESET 0x00
+#define Z180_TRDR_RMASK 0xff
+#define Z180_TRDR_WMASK 0xff
+
+/* 0c TIMER data register ch 0 L */
+#define Z180_TMDR0L_RESET 0x00
+#define Z180_TMDR0L_RMASK 0xff
+#define Z180_TMDR0L_WMASK 0xff
+
+/* 0d TIMER data register ch 0 H */
+#define Z180_TMDR0H_RESET 0x00
+#define Z180_TMDR0H_RMASK 0xff
+#define Z180_TMDR0H_WMASK 0xff
+
+/* 0e TIMER reload register ch 0 L */
+#define Z180_RLDR0L_RESET 0xff
+#define Z180_RLDR0L_RMASK 0xff
+#define Z180_RLDR0L_WMASK 0xff
+
+/* 0f TIMER reload register ch 0 H */
+#define Z180_RLDR0H_RESET 0xff
+#define Z180_RLDR0H_RMASK 0xff
+#define Z180_RLDR0H_WMASK 0xff
+
+/* 10 TIMER control register */
+#define Z180_TCR_TIF1 0x80
+#define Z180_TCR_TIF0 0x40
+#define Z180_TCR_TIE1 0x20
+#define Z180_TCR_TIE0 0x10
+#define Z180_TCR_TOC1 0x08
+#define Z180_TCR_TOC0 0x04
+#define Z180_TCR_TDE1 0x02
+#define Z180_TCR_TDE0 0x01
+
+#define Z180_TCR_RESET 0x00
+#define Z180_TCR_RMASK 0xff
+#define Z180_TCR_WMASK 0x3f
+
+/* 11 reserved */
+#define Z180_IO11_RESET 0x00
+#define Z180_IO11_RMASK 0xff
+#define Z180_IO11_WMASK 0xff
+
+/* 12 (Z8S180/Z8L180) ASCI extension control register 0 */
+#define Z180_ASEXT0_RDRF 0x80
+#define Z180_ASEXT0_DCD0 0x40
+#define Z180_ASEXT0_CTS0 0x20
+#define Z180_ASEXT0_X1_BIT_CLK0 0x10
+#define Z180_ASEXT0_BRG0_MODE 0x08
+#define Z180_ASEXT0_BRK_EN 0x04
+#define Z180_ASEXT0_BRK_DET 0x02
+#define Z180_ASEXT0_BRK_SEND 0x01
+
+#define Z180_ASEXT0_RESET 0x00
+#define Z180_ASEXT0_RMASK 0xff
+#define Z180_ASEXT0_WMASK 0xfd
+
+/* 13 (Z8S180/Z8L180) ASCI extension control register 0 */
+#define Z180_ASEXT1_RDRF 0x80
+#define Z180_ASEXT1_X1_BIT_CLK1 0x10
+#define Z180_ASEXT1_BRG1_MODE 0x08
+#define Z180_ASEXT1_BRK_EN 0x04
+#define Z180_ASEXT1_BRK_DET 0x02
+#define Z180_ASEXT1_BRK_SEND 0x01
+
+#define Z180_ASEXT1_RESET 0x00
+#define Z180_ASEXT1_RMASK 0xff
+#define Z180_ASEXT1_WMASK 0xfd
+
+
+/* 14 TIMER data register ch 1 L */
+#define Z180_TMDR1L_RESET 0x00
+#define Z180_TMDR1L_RMASK 0xff
+#define Z180_TMDR1L_WMASK 0xff
+
+/* 15 TIMER data register ch 1 H */
+#define Z180_TMDR1H_RESET 0x00
+#define Z180_TMDR1H_RMASK 0xff
+#define Z180_TMDR1H_WMASK 0xff
+
+/* 16 TIMER reload register ch 1 L */
+#define Z180_RLDR1L_RESET 0x00
+#define Z180_RLDR1L_RMASK 0xff
+#define Z180_RLDR1L_WMASK 0xff
+
+/* 17 TIMER reload register ch 1 H */
+#define Z180_RLDR1H_RESET 0x00
+#define Z180_RLDR1H_RMASK 0xff
+#define Z180_RLDR1H_WMASK 0xff
+
+/* 18 free running counter */
+#define Z180_FRC_RESET 0x00
+#define Z180_FRC_RMASK 0xff
+#define Z180_FRC_WMASK 0xff
+
+/* 19 reserved */
+#define Z180_IO19_RESET 0x00
+#define Z180_IO19_RMASK 0xff
+#define Z180_IO19_WMASK 0xff
+
+/* 1a ASCI time constant ch 0 L */
+#define Z180_ASTC0L_RESET 0x00
+#define Z180_ASTC0L_RMASK 0xff
+#define Z180_ASTC0L_WMASK 0xff
+
+/* 1b ASCI time constant ch 0 H */
+#define Z180_ASTC0H_RESET 0x00
+#define Z180_ASTC0H_RMASK 0xff
+#define Z180_ASTC0H_WMASK 0xff
+
+/* 1c ASCI time constant ch 1 L */
+#define Z180_ASTC1L_RESET 0x00
+#define Z180_ASTC1L_RMASK 0xff
+#define Z180_ASTC1L_WMASK 0xff
+
+/* 1d ASCI time constant ch 1 H */
+#define Z180_ASTC1H_RESET 0x00
+#define Z180_ASTC1H_RMASK 0xff
+#define Z180_ASTC1H_WMASK 0xff
+
+/* 1e clock multiplier */
+#define Z180_CMR_X2 0x80
+
+#define Z180_CMR_RESET 0x7f
+#define Z180_CMR_RMASK 0x80
+#define Z180_CMR_WMASK 0x80
+
+/* 1f chip control register */
+#define Z180_CCR_CLOCK_DIVIDE 0x80
+#define Z180_CCR_STDBY_IDLE1 0x40
+#define Z180_CCR_BREXT 0x20
+#define Z180_CCR_LNPHI 0x10
+#define Z180_CCR_STDBY_IDLE0 0x08
+#define Z180_CCR_LNIO 0x04
+#define Z180_CCR_LNCPU_CTL 0x02
+#define Z180_CCR_LNAD_DATA 0x01
+
+#define Z180_CCR_RESET 0x00
+#define Z180_CCR_RMASK 0xff
+#define Z180_CCR_WMASK 0xff
+
+/* 20 DMA source address register ch 0 L */
+#define Z180_SAR0L_SAR 0xff
+
+#define Z180_SAR0L_RESET 0x00
+#define Z180_SAR0L_RMASK 0xff
+#define Z180_SAR0L_WMASK 0xff
+
+/* 21 DMA source address register ch 0 H */
+#define Z180_SAR0H_SAR 0xff
+
+#define Z180_SAR0H_RESET 0x00
+#define Z180_SAR0H_RMASK 0xff
+#define Z180_SAR0H_WMASK 0xff
+
+/* 22 DMA source address register ch 0 B */
+#define Z180_SAR0B_SAR 0x0f
+
+#define Z180_SAR0B_RESET 0x00
+#define Z180_SAR0B_RMASK 0x0f
+#define Z180_SAR0B_WMASK 0x0f
+
+/* 23 DMA destination address register ch 0 L */
+#define Z180_DAR0L_DAR 0xff
+
+#define Z180_DAR0L_RESET 0x00
+#define Z180_DAR0L_RMASK 0xff
+#define Z180_DAR0L_WMASK 0xff
+
+/* 24 DMA destination address register ch 0 H */
+#define Z180_DAR0H_DAR 0xff
+
+#define Z180_DAR0H_RESET 0x00
+#define Z180_DAR0H_RMASK 0xff
+#define Z180_DAR0H_WMASK 0xff
+
+/* 25 DMA destination address register ch 0 B */
+#define Z180_DAR0B_DAR 0x00
+
+#define Z180_DAR0B_RESET 0x00
+#define Z180_DAR0B_RMASK 0x0f
+#define Z180_DAR0B_WMASK 0x0f
+
+/* 26 DMA byte count register ch 0 L */
+#define Z180_BCR0L_BCR 0xff
+
+#define Z180_BCR0L_RESET 0x00
+#define Z180_BCR0L_RMASK 0xff
+#define Z180_BCR0L_WMASK 0xff
+
+/* 27 DMA byte count register ch 0 H */
+#define Z180_BCR0H_BCR 0xff
+
+#define Z180_BCR0H_RESET 0x00
+#define Z180_BCR0H_RMASK 0xff
+#define Z180_BCR0H_WMASK 0xff
+
+/* 28 DMA memory address register ch 1 L */
+#define Z180_MAR1L_MAR 0xff
+
+#define Z180_MAR1L_RESET 0x00
+#define Z180_MAR1L_RMASK 0xff
+#define Z180_MAR1L_WMASK 0xff
+
+/* 29 DMA memory address register ch 1 H */
+#define Z180_MAR1H_MAR 0xff
+
+#define Z180_MAR1H_RESET 0x00
+#define Z180_MAR1H_RMASK 0xff
+#define Z180_MAR1H_WMASK 0xff
+
+/* 2a DMA memory address register ch 1 B */
+#define Z180_MAR1B_MAR 0x0f
+
+#define Z180_MAR1B_RESET 0x00
+#define Z180_MAR1B_RMASK 0x0f
+#define Z180_MAR1B_WMASK 0x0f
+
+/* 2b DMA I/O address register ch 1 L */
+#define Z180_IAR1L_IAR 0xff
+
+#define Z180_IAR1L_RESET 0x00
+#define Z180_IAR1L_RMASK 0xff
+#define Z180_IAR1L_WMASK 0xff
+
+/* 2c DMA I/O address register ch 1 H */
+#define Z180_IAR1H_IAR 0xff
+
+#define Z180_IAR1H_RESET 0x00
+#define Z180_IAR1H_RMASK 0xff
+#define Z180_IAR1H_WMASK 0xff
+
+/* 2d (Z8S180/Z8L180) DMA I/O address register ch 1 B */
+#define Z180_IAR1B_IAR 0x0f
+
+#define Z180_IAR1B_RESET 0x00
+#define Z180_IAR1B_RMASK 0x0f
+#define Z180_IAR1B_WMASK 0x0f
+
+/* 2e DMA byte count register ch 1 L */
+#define Z180_BCR1L_BCR 0xff
+
+#define Z180_BCR1L_RESET 0x00
+#define Z180_BCR1L_RMASK 0xff
+#define Z180_BCR1L_WMASK 0xff
+
+/* 2f DMA byte count register ch 1 H */
+#define Z180_BCR1H_BCR 0xff
+
+#define Z180_BCR1H_RESET 0x00
+#define Z180_BCR1H_RMASK 0xff
+#define Z180_BCR1H_WMASK 0xff
+
+/* 30 DMA status register */
+#define Z180_DSTAT_DE1 0x80 /* DMA enable ch 1 */
+#define Z180_DSTAT_DE0 0x40 /* DMA enable ch 0 */
+#define Z180_DSTAT_DWE1 0x20 /* DMA write enable ch 0 (active low) */
+#define Z180_DSTAT_DWE0 0x10 /* DMA write enable ch 1 (active low) */
+#define Z180_DSTAT_DIE1 0x08 /* DMA IRQ enable ch 1 */
+#define Z180_DSTAT_DIE0 0x04 /* DMA IRQ enable ch 0 */
+#define Z180_DSTAT_DME 0x01 /* DMA enable (read only) */
+
+#define Z180_DSTAT_RESET 0x30
+#define Z180_DSTAT_RMASK 0xfd
+#define Z180_DSTAT_WMASK 0xcc
+
+/* 31 DMA mode register */
+#define Z180_DMODE_DM 0x30
+#define Z180_DMODE_SM 0x0c
+#define Z180_DMODE_MMOD 0x04
+
+#define Z180_DMODE_RESET 0x00
+#define Z180_DMODE_RMASK 0x3e
+#define Z180_DMODE_WMASK 0x3e
+
+/* 32 DMA/WAIT control register */
+#define Z180_DCNTL_MWI1 0x80
+#define Z180_DCNTL_MWI0 0x40
+#define Z180_DCNTL_IWI1 0x20
+#define Z180_DCNTL_IWI0 0x10
+#define Z180_DCNTL_DMS1 0x08
+#define Z180_DCNTL_DMS0 0x04
+#define Z180_DCNTL_DIM1 0x02
+#define Z180_DCNTL_DIM0 0x01
+
+#define Z180_DCNTL_RESET 0x00
+#define Z180_DCNTL_RMASK 0xff
+#define Z180_DCNTL_WMASK 0xff
+
+/* 33 INT vector low register */
+#define Z180_IL_IL 0xe0
+
+#define Z180_IL_RESET 0x00
+#define Z180_IL_RMASK 0xe0
+#define Z180_IL_WMASK 0xe0
+
+/* 34 INT/TRAP control register */
+#define Z180_ITC_TRAP 0x80
+#define Z180_ITC_UFO 0x40
+#define Z180_ITC_ITE2 0x04
+#define Z180_ITC_ITE1 0x02
+#define Z180_ITC_ITE0 0x01
+
+#define Z180_ITC_RESET 0x01
+#define Z180_ITC_RMASK 0xc7
+#define Z180_ITC_WMASK 0x87
+
+/* 35 reserved */
+#define Z180_IO35_RESET 0x00
+#define Z180_IO35_RMASK 0xff
+#define Z180_IO35_WMASK 0xff
+
+/* 36 refresh control register */
+#define Z180_RCR_REFE 0x80
+#define Z180_RCR_REFW 0x80
+#define Z180_RCR_CYC 0x03
+
+#define Z180_RCR_RESET 0xc0
+#define Z180_RCR_RMASK 0xc3
+#define Z180_RCR_WMASK 0xc3
+
+/* 37 reserved */
+#define Z180_IO37_RESET 0x00
+#define Z180_IO37_RMASK 0xff
+#define Z180_IO37_WMASK 0xff
+
+/* 38 MMU common base register */
+#define Z180_CBR_CB 0xff
+
+#define Z180_CBR_RESET 0x00
+#define Z180_CBR_RMASK 0xff
+#define Z180_CBR_WMASK 0xff
+
+/* 39 MMU bank base register */
+#define Z180_BBR_BB 0xff
+
+#define Z180_BBR_RESET 0x00
+#define Z180_BBR_RMASK 0xff
+#define Z180_BBR_WMASK 0xff
+
+/* 3a MMU common/bank area register */
+#define Z180_CBAR_CA 0xf0
+#define Z180_CBAR_BA 0x0f
+
+#define Z180_CBAR_RESET 0xf0
+#define Z180_CBAR_RMASK 0xff
+#define Z180_CBAR_WMASK 0xff
+
+/* 3b reserved */
+#define Z180_IO3B_RESET 0x00
+#define Z180_IO3B_RMASK 0xff
+#define Z180_IO3B_WMASK 0xff
+
+/* 3c reserved */
+#define Z180_IO3C_RESET 0x00
+#define Z180_IO3C_RMASK 0xff
+#define Z180_IO3C_WMASK 0xff
+
+/* 3d reserved */
+#define Z180_IO3D_RESET 0x00
+#define Z180_IO3D_RMASK 0xff
+#define Z180_IO3D_WMASK 0xff
+
+/* 3e operation mode control register */
+#define Z180_OMCR_RESET 0x00
+#define Z180_OMCR_RMASK 0xff
+#define Z180_OMCR_WMASK 0xff
+
+/* 3f I/O control register */
+#define Z180_IOCR_RESET 0x00
+#define Z180_IOCR_RMASK 0xff
+#define Z180_IOCR_WMASK 0xff
+
+/***************************************************************************
+ CPU PREFIXES
+
+ order is important here - see z180tbl.h
+***************************************************************************/
+
+#define Z180_PREFIX_op 0
+#define Z180_PREFIX_cb 1
+#define Z180_PREFIX_dd 2
+#define Z180_PREFIX_ed 3
+#define Z180_PREFIX_fd 4
+#define Z180_PREFIX_xycb 5
+
+#define Z180_PREFIX_COUNT (Z180_PREFIX_xycb + 1)
+
+
+
+static UINT8 SZ[256]; /* zero and sign flags */
+static UINT8 SZ_BIT[256]; /* zero, sign and parity/overflow (=zero) flags for BIT opcode */
+static UINT8 SZP[256]; /* zero, sign and parity flags */
+static UINT8 SZHV_inc[256]; /* zero, sign, half carry and overflow flags INC r8 */
+static UINT8 SZHV_dec[256]; /* zero, sign, half carry and overflow flags DEC r8 */
+
+static UINT8 *SZHVC_add;
+static UINT8 *SZHVC_sub;
+
+static UINT8 z180_readcontrol(z180_state *cpustate, offs_t port);
+static void z180_writecontrol(z180_state *cpustate, offs_t port, UINT8 data);
+static int z180_dma0(z180_state *cpustate, int max_cycles);
+static int z180_dma1(z180_state *cpustate);
+static CPU_BURN( z180 );
+static CPU_SET_INFO( z180 );
+
+#include "z180ops.h"
+#include "z180tbl.h"
+
+#include "z180cb.c"
+#include "z180xy.c"
+#include "z180dd.c"
+#include "z180fd.c"
+#include "z180ed.c"
+#include "z180op.c"
+
+static UINT8 z180_readcontrol(z180_state *cpustate, offs_t port)
+{
+ /* normal external readport */
+ UINT8 data = cpustate->iospace->read_byte(port);
+
+ /* remap internal I/O registers */
+ if((port & (cpustate->IO_IOCR & 0xc0)) == (cpustate->IO_IOCR & 0xc0))
+ port = port - (cpustate->IO_IOCR & 0xc0);
+
+ /* but ignore the data and read the internal register */
+ switch (port + Z180_CNTLA0)
+ {
+ case Z180_CNTLA0:
+ data = cpustate->IO_CNTLA0 & Z180_CNTLA0_RMASK;
+ LOG(("Z180 '%s' CNTLA0 rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_CNTLA1:
+ data = cpustate->IO_CNTLA1 & Z180_CNTLA1_RMASK;
+ LOG(("Z180 '%s' CNTLA1 rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_CNTLB0:
+ data = cpustate->IO_CNTLB0 & Z180_CNTLB0_RMASK;
+ LOG(("Z180 '%s' CNTLB0 rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_CNTLB1:
+ data = cpustate->IO_CNTLB1 & Z180_CNTLB1_RMASK;
+ LOG(("Z180 '%s' CNTLB1 rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_STAT0:
+ data = cpustate->IO_STAT0 & Z180_STAT0_RMASK;
+data |= 0x02; // kludge for 20pacgal
+ LOG(("Z180 '%s' STAT0 rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_STAT1:
+ data = cpustate->IO_STAT1 & Z180_STAT1_RMASK;
+ LOG(("Z180 '%s' STAT1 rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_TDR0:
+ data = cpustate->IO_TDR0 & Z180_TDR0_RMASK;
+ LOG(("Z180 '%s' TDR0 rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_TDR1:
+ data = cpustate->IO_TDR1 & Z180_TDR1_RMASK;
+ LOG(("Z180 '%s' TDR1 rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_RDR0:
+ data = cpustate->IO_RDR0 & Z180_RDR0_RMASK;
+ LOG(("Z180 '%s' RDR0 rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_RDR1:
+ data = cpustate->IO_RDR1 & Z180_RDR1_RMASK;
+ LOG(("Z180 '%s' RDR1 rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_CNTR:
+ data = cpustate->IO_CNTR & Z180_CNTR_RMASK;
+ LOG(("Z180 '%s' CNTR rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_TRDR:
+ data = cpustate->IO_TRDR & Z180_TRDR_RMASK;
+ LOG(("Z180 '%s' TRDR rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_TMDR0L:
+ data = cpustate->tmdr_value[0] & Z180_TMDR0L_RMASK;
+ LOG(("Z180 '%s' TMDR0L rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ /* if timer is counting, latch the MSB and set the latch flag */
+ if ((cpustate->IO_TCR & Z180_TCR_TDE0) == 0)
+ {
+ cpustate->tmdr_latch |= 1;
+ cpustate->tmdrh[0] = (cpustate->tmdr_value[0] & 0xff00) >> 8;
+ }
+
+ if(cpustate->read_tcr_tmdr[0])
+ {
+ cpustate->tif[0] = 0; // reset TIF0
+ cpustate->read_tcr_tmdr[0] = 0;
+ }
+ else
+ {
+ cpustate->read_tcr_tmdr[0] = 1;
+ }
+ break;
+
+ case Z180_TMDR0H:
+ /* read latched value? */
+ if (cpustate->tmdr_latch & 1)
+ {
+ cpustate->tmdr_latch &= ~1;
+ data = cpustate->tmdrh[0];
+ }
+ else
+ {
+ data = (cpustate->tmdr_value[0] & 0xff00) >> 8;
+ }
+
+ if(cpustate->read_tcr_tmdr[0])
+ {
+ cpustate->tif[0] = 0; // reset TIF0
+ cpustate->read_tcr_tmdr[0] = 0;
+ }
+ else
+ {
+ cpustate->read_tcr_tmdr[0] = 1;
+ }
+ LOG(("Z180 '%s' TMDR0H rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_RLDR0L:
+ data = cpustate->IO_RLDR0L & Z180_RLDR0L_RMASK;
+ LOG(("Z180 '%s' RLDR0L rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_RLDR0H:
+ data = cpustate->IO_RLDR0H & Z180_RLDR0H_RMASK;
+ LOG(("Z180 '%s' RLDR0H rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_TCR:
+ data = (cpustate->IO_TCR & Z180_TCR_RMASK) | (cpustate->tif[0] << 6) | (cpustate->tif[1] << 7);
+
+ if(cpustate->read_tcr_tmdr[0])
+ {
+ cpustate->tif[0] = 0; // reset TIF0
+ cpustate->read_tcr_tmdr[0] = 0;
+ }
+ else
+ {
+ cpustate->read_tcr_tmdr[0] = 1;
+ }
+
+ if(cpustate->read_tcr_tmdr[1])
+ {
+ cpustate->tif[1] = 0; // reset TIF1
+ cpustate->read_tcr_tmdr[1] = 0;
+ }
+ else
+ {
+ cpustate->read_tcr_tmdr[1] = 1;
+ }
+
+ LOG(("Z180 '%s' TCR rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_IO11:
+ data = cpustate->IO_IO11 & Z180_IO11_RMASK;
+ LOG(("Z180 '%s' IO11 rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_ASEXT0:
+ data = cpustate->IO_ASEXT0 & Z180_ASEXT0_RMASK;
+ LOG(("Z180 '%s' ASEXT0 rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_ASEXT1:
+ data = cpustate->IO_ASEXT1 & Z180_ASEXT1_RMASK;
+ LOG(("Z180 '%s' ASEXT1 rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_TMDR1L:
+ data = cpustate->tmdr_value[1] & Z180_TMDR1L_RMASK;
+ LOG(("Z180 '%s' TMDR1L rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ /* if timer is counting, latch the MSB and set the latch flag */
+ if ((cpustate->IO_TCR & Z180_TCR_TDE1) == 0)
+ {
+ cpustate->tmdr_latch |= 2;
+ cpustate->tmdrh[1] = (cpustate->tmdr_value[1] & 0xff00) >> 8;
+ }
+
+ if(cpustate->read_tcr_tmdr[1])
+ {
+ cpustate->tif[1] = 0; // reset TIF1
+ cpustate->read_tcr_tmdr[1] = 0;
+ }
+ else
+ {
+ cpustate->read_tcr_tmdr[1] = 1;
+ }
+ break;
+
+ case Z180_TMDR1H:
+ /* read latched value? */
+ if (cpustate->tmdr_latch & 2)
+ {
+ cpustate->tmdr_latch &= ~2;
+ data = cpustate->tmdrh[1];
+ }
+ else
+ {
+ data = (cpustate->tmdr_value[1] & 0xff00) >> 8;
+ }
+
+ if(cpustate->read_tcr_tmdr[1])
+ {
+ cpustate->tif[1] = 0; // reset TIF1
+ cpustate->read_tcr_tmdr[1] = 0;
+ }
+ else
+ {
+ cpustate->read_tcr_tmdr[1] = 1;
+ }
+ LOG(("Z180 '%s' TMDR1H rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_RLDR1L:
+ data = cpustate->IO_RLDR1L & Z180_RLDR1L_RMASK;
+ LOG(("Z180 '%s' RLDR1L rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_RLDR1H:
+ data = cpustate->IO_RLDR1H & Z180_RLDR1H_RMASK;
+ LOG(("Z180 '%s' RLDR1H rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_FRC:
+ data = cpustate->IO_FRC & Z180_FRC_RMASK;
+ LOG(("Z180 '%s' FRC rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_IO19:
+ data = cpustate->IO_IO19 & Z180_IO19_RMASK;
+ LOG(("Z180 '%s' IO19 rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_ASTC0L:
+ data = cpustate->IO_ASTC0L & Z180_ASTC0L_RMASK;
+ LOG(("Z180 '%s' ASTC0L rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_ASTC0H:
+ data = cpustate->IO_ASTC0H & Z180_ASTC0H_RMASK;
+ LOG(("Z180 '%s' ASTC0H rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_ASTC1L:
+ data = cpustate->IO_ASTC1L & Z180_ASTC1L_RMASK;
+ LOG(("Z180 '%s' ASTC1L rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_ASTC1H:
+ data = cpustate->IO_ASTC1H & Z180_ASTC1H_RMASK;
+ LOG(("Z180 '%s' ASTC1H rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_CMR:
+ data = cpustate->IO_CMR & Z180_CMR_RMASK;
+ LOG(("Z180 '%s' CMR rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_CCR:
+ data = cpustate->IO_CCR & Z180_CCR_RMASK;
+ LOG(("Z180 '%s' CCR rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_SAR0L:
+ data = cpustate->IO_SAR0L & Z180_SAR0L_RMASK;
+ LOG(("Z180 '%s' SAR0L rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_SAR0H:
+ data = cpustate->IO_SAR0H & Z180_SAR0H_RMASK;
+ LOG(("Z180 '%s' SAR0H rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_SAR0B:
+ data = cpustate->IO_SAR0B & Z180_SAR0B_RMASK;
+ LOG(("Z180 '%s' SAR0B rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_DAR0L:
+ data = cpustate->IO_DAR0L & Z180_DAR0L_RMASK;
+ LOG(("Z180 '%s' DAR0L rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_DAR0H:
+ data = cpustate->IO_DAR0H & Z180_DAR0H_RMASK;
+ LOG(("Z180 '%s' DAR0H rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_DAR0B:
+ data = cpustate->IO_DAR0B & Z180_DAR0B_RMASK;
+ LOG(("Z180 '%s' DAR0B rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_BCR0L:
+ data = cpustate->IO_BCR0L & Z180_BCR0L_RMASK;
+ LOG(("Z180 '%s' BCR0L rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_BCR0H:
+ data = cpustate->IO_BCR0H & Z180_BCR0H_RMASK;
+ LOG(("Z180 '%s' BCR0H rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_MAR1L:
+ data = cpustate->IO_MAR1L & Z180_MAR1L_RMASK;
+ LOG(("Z180 '%s' MAR1L rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_MAR1H:
+ data = cpustate->IO_MAR1H & Z180_MAR1H_RMASK;
+ LOG(("Z180 '%s' MAR1H rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_MAR1B:
+ data = cpustate->IO_MAR1B & Z180_MAR1B_RMASK;
+ LOG(("Z180 '%s' MAR1B rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_IAR1L:
+ data = cpustate->IO_IAR1L & Z180_IAR1L_RMASK;
+ LOG(("Z180 '%s' IAR1L rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_IAR1H:
+ data = cpustate->IO_IAR1H & Z180_IAR1H_RMASK;
+ LOG(("Z180 '%s' IAR1H rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_IAR1B:
+ data = cpustate->IO_IAR1B & Z180_IAR1B_RMASK;
+ LOG(("Z180 '%s' IAR1B rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_BCR1L:
+ data = cpustate->IO_BCR1L & Z180_BCR1L_RMASK;
+ LOG(("Z180 '%s' BCR1L rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_BCR1H:
+ data = cpustate->IO_BCR1H & Z180_BCR1H_RMASK;
+ LOG(("Z180 '%s' BCR1H rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_DSTAT:
+ data = cpustate->IO_DSTAT & Z180_DSTAT_RMASK;
+ LOG(("Z180 '%s' DSTAT rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_DMODE:
+ data = cpustate->IO_DMODE & Z180_DMODE_RMASK;
+ LOG(("Z180 '%s' DMODE rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_DCNTL:
+ data = cpustate->IO_DCNTL & Z180_DCNTL_RMASK;
+ LOG(("Z180 '%s' DCNTL rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_IL:
+ data = cpustate->IO_IL & Z180_IL_RMASK;
+ LOG(("Z180 '%s' IL rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_ITC:
+ data = cpustate->IO_ITC & Z180_ITC_RMASK;
+ LOG(("Z180 '%s' ITC rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_IO35:
+ data = cpustate->IO_IO35 & Z180_IO35_RMASK;
+ LOG(("Z180 '%s' IO35 rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_RCR:
+ data = cpustate->IO_RCR & Z180_RCR_RMASK;
+ LOG(("Z180 '%s' RCR rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_IO37:
+ data = cpustate->IO_IO37 & Z180_IO37_RMASK;
+ LOG(("Z180 '%s' IO37 rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_CBR:
+ data = cpustate->IO_CBR & Z180_CBR_RMASK;
+ LOG(("Z180 '%s' CBR rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_BBR:
+ data = cpustate->IO_BBR & Z180_BBR_RMASK;
+ LOG(("Z180 '%s' BBR rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_CBAR:
+ data = cpustate->IO_CBAR & Z180_CBAR_RMASK;
+ LOG(("Z180 '%s' CBAR rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_IO3B:
+ data = cpustate->IO_IO3B & Z180_IO3B_RMASK;
+ LOG(("Z180 '%s' IO3B rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_IO3C:
+ data = cpustate->IO_IO3C & Z180_IO3C_RMASK;
+ LOG(("Z180 '%s' IO3C rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_IO3D:
+ data = cpustate->IO_IO3D & Z180_IO3D_RMASK;
+ LOG(("Z180 '%s' IO3D rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_OMCR:
+ data = cpustate->IO_OMCR & Z180_OMCR_RMASK;
+ LOG(("Z180 '%s' OMCR rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+
+ case Z180_IOCR:
+ data = cpustate->IO_IOCR & Z180_IOCR_RMASK;
+ LOG(("Z180 '%s' IOCR rd $%02x ($%02x)\n", cpustate->device->tag(), data, cpustate->io[port & 0x3f]));
+ break;
+ }
+
+ return data;
+}
+
+static void z180_writecontrol(z180_state *cpustate, offs_t port, UINT8 data)
+{
+ /* normal external write port */
+ cpustate->iospace->write_byte(port, data);
+
+ /* remap internal I/O registers */
+ if((port & (cpustate->IO_IOCR & 0xc0)) == (cpustate->IO_IOCR & 0xc0))
+ port = port - (cpustate->IO_IOCR & 0xc0);
+
+ /* store the data in the internal register */
+ switch (port + Z180_CNTLA0)
+ {
+ case Z180_CNTLA0:
+ LOG(("Z180 '%s' CNTLA0 wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_CNTLA0_WMASK));
+ cpustate->IO_CNTLA0 = (cpustate->IO_CNTLA0 & ~Z180_CNTLA0_WMASK) | (data & Z180_CNTLA0_WMASK);
+ break;
+
+ case Z180_CNTLA1:
+ LOG(("Z180 '%s' CNTLA1 wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_CNTLA1_WMASK));
+ cpustate->IO_CNTLA1 = (cpustate->IO_CNTLA1 & ~Z180_CNTLA1_WMASK) | (data & Z180_CNTLA1_WMASK);
+ break;
+
+ case Z180_CNTLB0:
+ LOG(("Z180 '%s' CNTLB0 wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_CNTLB0_WMASK));
+ cpustate->IO_CNTLB0 = (cpustate->IO_CNTLB0 & ~Z180_CNTLB0_WMASK) | (data & Z180_CNTLB0_WMASK);
+ break;
+
+ case Z180_CNTLB1:
+ LOG(("Z180 '%s' CNTLB1 wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_CNTLB1_WMASK));
+ cpustate->IO_CNTLB1 = (cpustate->IO_CNTLB1 & ~Z180_CNTLB1_WMASK) | (data & Z180_CNTLB1_WMASK);
+ break;
+
+ case Z180_STAT0:
+ LOG(("Z180 '%s' STAT0 wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_STAT0_WMASK));
+ cpustate->IO_STAT0 = (cpustate->IO_STAT0 & ~Z180_STAT0_WMASK) | (data & Z180_STAT0_WMASK);
+ break;
+
+ case Z180_STAT1:
+ LOG(("Z180 '%s' STAT1 wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_STAT1_WMASK));
+ cpustate->IO_STAT1 = (cpustate->IO_STAT1 & ~Z180_STAT1_WMASK) | (data & Z180_STAT1_WMASK);
+ break;
+
+ case Z180_TDR0:
+ LOG(("Z180 '%s' TDR0 wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_TDR0_WMASK));
+ cpustate->IO_TDR0 = (cpustate->IO_TDR0 & ~Z180_TDR0_WMASK) | (data & Z180_TDR0_WMASK);
+ break;
+
+ case Z180_TDR1:
+ LOG(("Z180 '%s' TDR1 wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_TDR1_WMASK));
+ cpustate->IO_TDR1 = (cpustate->IO_TDR1 & ~Z180_TDR1_WMASK) | (data & Z180_TDR1_WMASK);
+ break;
+
+ case Z180_RDR0:
+ LOG(("Z180 '%s' RDR0 wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_RDR0_WMASK));
+ cpustate->IO_RDR0 = (cpustate->IO_RDR0 & ~Z180_RDR0_WMASK) | (data & Z180_RDR0_WMASK);
+ break;
+
+ case Z180_RDR1:
+ LOG(("Z180 '%s' RDR1 wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_RDR1_WMASK));
+ cpustate->IO_RDR1 = (cpustate->IO_RDR1 & ~Z180_RDR1_WMASK) | (data & Z180_RDR1_WMASK);
+ break;
+
+ case Z180_CNTR:
+ LOG(("Z180 '%s' CNTR wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_CNTR_WMASK));
+ cpustate->IO_CNTR = (cpustate->IO_CNTR & ~Z180_CNTR_WMASK) | (data & Z180_CNTR_WMASK);
+ break;
+
+ case Z180_TRDR:
+ LOG(("Z180 '%s' TRDR wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_TRDR_WMASK));
+ cpustate->IO_TRDR = (cpustate->IO_TRDR & ~Z180_TRDR_WMASK) | (data & Z180_TRDR_WMASK);
+ break;
+
+ case Z180_TMDR0L:
+ LOG(("Z180 '%s' TMDR0L wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_TMDR0L_WMASK));
+ cpustate->IO_TMDR0L = data & Z180_TMDR0L_WMASK;
+ cpustate->tmdr_value[0] = (cpustate->tmdr_value[0] & 0xff00) | cpustate->IO_TMDR0L;
+ break;
+
+ case Z180_TMDR0H:
+ LOG(("Z180 '%s' TMDR0H wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_TMDR0H_WMASK));
+ cpustate->IO_TMDR0H = data & Z180_TMDR0H_WMASK;
+ cpustate->tmdr_value[0] = (cpustate->tmdr_value[0] & 0x00ff) | (cpustate->IO_TMDR0H << 8);
+ break;
+
+ case Z180_RLDR0L:
+ LOG(("Z180 '%s' RLDR0L wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_RLDR0L_WMASK));
+ cpustate->IO_RLDR0L = (cpustate->IO_RLDR0L & ~Z180_RLDR0L_WMASK) | (data & Z180_RLDR0L_WMASK);
+ break;
+
+ case Z180_RLDR0H:
+ LOG(("Z180 '%s' RLDR0H wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_RLDR0H_WMASK));
+ cpustate->IO_RLDR0H = (cpustate->IO_RLDR0H & ~Z180_RLDR0H_WMASK) | (data & Z180_RLDR0H_WMASK);
+ break;
+
+ case Z180_TCR:
+ LOG(("Z180 '%s' TCR wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_TCR_WMASK));
+ {
+ UINT16 old = cpustate->IO_TCR;
+ /* Force reload on state change */
+ cpustate->IO_TCR = (cpustate->IO_TCR & ~Z180_TCR_WMASK) | (data & Z180_TCR_WMASK);
+ if (!(old & Z180_TCR_TDE0) && (cpustate->IO_TCR & Z180_TCR_TDE0))
+ cpustate->tmdr_value[0] = 0; //cpustate->IO_RLDR0L | (cpustate->IO_RLDR0H << 8);
+ if (!(old & Z180_TCR_TDE1) && (cpustate->IO_TCR & Z180_TCR_TDE1))
+ cpustate->tmdr_value[1] = 0; //cpustate->IO_RLDR1L | (cpustate->IO_RLDR1H << 8);
+ }
+
+ break;
+
+ case Z180_IO11:
+ LOG(("Z180 '%s' IO11 wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_IO11_WMASK));
+ cpustate->IO_IO11 = (cpustate->IO_IO11 & ~Z180_IO11_WMASK) | (data & Z180_IO11_WMASK);
+ break;
+
+ case Z180_ASEXT0:
+ LOG(("Z180 '%s' ASEXT0 wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_ASEXT0_WMASK));
+ cpustate->IO_ASEXT0 = (cpustate->IO_ASEXT0 & ~Z180_ASEXT0_WMASK) | (data & Z180_ASEXT0_WMASK);
+ break;
+
+ case Z180_ASEXT1:
+ LOG(("Z180 '%s' ASEXT1 wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_ASEXT1_WMASK));
+ cpustate->IO_ASEXT1 = (cpustate->IO_ASEXT1 & ~Z180_ASEXT1_WMASK) | (data & Z180_ASEXT1_WMASK);
+ break;
+
+ case Z180_TMDR1L:
+ LOG(("Z180 '%s' TMDR1L wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_TMDR1L_WMASK));
+ cpustate->IO_TMDR1L = data & Z180_TMDR1L_WMASK;
+ cpustate->tmdr_value[1] = (cpustate->tmdr_value[1] & 0xff00) | cpustate->IO_TMDR1L;
+ break;
+
+ case Z180_TMDR1H:
+ LOG(("Z180 '%s' TMDR1H wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_TMDR1H_WMASK));
+ cpustate->IO_TMDR1H = data & Z180_TMDR1H_WMASK;
+ cpustate->tmdr_value[1] = (cpustate->tmdr_value[1] & 0x00ff) | cpustate->IO_TMDR1H;
+ break;
+
+ case Z180_RLDR1L:
+ LOG(("Z180 '%s' RLDR1L wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_RLDR1L_WMASK));
+ cpustate->IO_RLDR1L = (cpustate->IO_RLDR1L & ~Z180_RLDR1L_WMASK) | (data & Z180_RLDR1L_WMASK);
+ break;
+
+ case Z180_RLDR1H:
+ LOG(("Z180 '%s' RLDR1H wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_RLDR1H_WMASK));
+ cpustate->IO_RLDR1H = (cpustate->IO_RLDR1H & ~Z180_RLDR1H_WMASK) | (data & Z180_RLDR1H_WMASK);
+ break;
+
+ case Z180_FRC:
+ LOG(("Z180 '%s' FRC wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_FRC_WMASK));
+ cpustate->IO_FRC = (cpustate->IO_FRC & ~Z180_FRC_WMASK) | (data & Z180_FRC_WMASK);
+ break;
+
+ case Z180_IO19:
+ LOG(("Z180 '%s' IO19 wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_IO19_WMASK));
+ cpustate->IO_IO19 = (cpustate->IO_IO19 & ~Z180_IO19_WMASK) | (data & Z180_IO19_WMASK);
+ break;
+
+ case Z180_ASTC0L:
+ LOG(("Z180 '%s' ASTC0L wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_ASTC0L_WMASK));
+ cpustate->IO_ASTC0L = (cpustate->IO_ASTC0L & ~Z180_ASTC0L_WMASK) | (data & Z180_ASTC0L_WMASK);
+ break;
+
+ case Z180_ASTC0H:
+ LOG(("Z180 '%s' ASTC0H wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_ASTC0H_WMASK));
+ cpustate->IO_ASTC0H = (cpustate->IO_ASTC0H & ~Z180_ASTC0H_WMASK) | (data & Z180_ASTC0H_WMASK);
+ break;
+
+ case Z180_ASTC1L:
+ LOG(("Z180 '%s' ASTC1L wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_ASTC1L_WMASK));
+ cpustate->IO_ASTC1L = (cpustate->IO_ASTC1L & ~Z180_ASTC1L_WMASK) | (data & Z180_ASTC1L_WMASK);
+ break;
+
+ case Z180_ASTC1H:
+ LOG(("Z180 '%s' ASTC1H wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_ASTC1H_WMASK));
+ cpustate->IO_ASTC1H = (cpustate->IO_ASTC1H & ~Z180_ASTC1H_WMASK) | (data & Z180_ASTC1H_WMASK);
+ break;
+
+ case Z180_CMR:
+ LOG(("Z180 '%s' CMR wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_CMR_WMASK));
+ cpustate->IO_CMR = (cpustate->IO_CMR & ~Z180_CMR_WMASK) | (data & Z180_CMR_WMASK);
+ break;
+
+ case Z180_CCR:
+ LOG(("Z180 '%s' CCR wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_CCR_WMASK));
+ cpustate->IO_CCR = (cpustate->IO_CCR & ~Z180_CCR_WMASK) | (data & Z180_CCR_WMASK);
+ break;
+
+ case Z180_SAR0L:
+ LOG(("Z180 '%s' SAR0L wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_SAR0L_WMASK));
+ cpustate->IO_SAR0L = (cpustate->IO_SAR0L & ~Z180_SAR0L_WMASK) | (data & Z180_SAR0L_WMASK);
+ break;
+
+ case Z180_SAR0H:
+ LOG(("Z180 '%s' SAR0H wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_SAR0H_WMASK));
+ cpustate->IO_SAR0H = (cpustate->IO_SAR0H & ~Z180_SAR0H_WMASK) | (data & Z180_SAR0H_WMASK);
+ break;
+
+ case Z180_SAR0B:
+ LOG(("Z180 '%s' SAR0B wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_SAR0B_WMASK));
+ cpustate->IO_SAR0B = (cpustate->IO_SAR0B & ~Z180_SAR0B_WMASK) | (data & Z180_SAR0B_WMASK);
+ break;
+
+ case Z180_DAR0L:
+ LOG(("Z180 '%s' DAR0L wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_DAR0L_WMASK));
+ cpustate->IO_DAR0L = (cpustate->IO_DAR0L & ~Z180_DAR0L_WMASK) | (data & Z180_DAR0L_WMASK);
+ break;
+
+ case Z180_DAR0H:
+ LOG(("Z180 '%s' DAR0H wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_DAR0H_WMASK));
+ cpustate->IO_DAR0H = (cpustate->IO_DAR0H & ~Z180_DAR0H_WMASK) | (data & Z180_DAR0H_WMASK);
+ break;
+
+ case Z180_DAR0B:
+ LOG(("Z180 '%s' DAR0B wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_DAR0B_WMASK));
+ cpustate->IO_DAR0B = (cpustate->IO_DAR0B & ~Z180_DAR0B_WMASK) | (data & Z180_DAR0B_WMASK);
+ break;
+
+ case Z180_BCR0L:
+ LOG(("Z180 '%s' BCR0L wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_BCR0L_WMASK));
+ cpustate->IO_BCR0L = (cpustate->IO_BCR0L & ~Z180_BCR0L_WMASK) | (data & Z180_BCR0L_WMASK);
+ break;
+
+ case Z180_BCR0H:
+ LOG(("Z180 '%s' BCR0H wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_BCR0H_WMASK));
+ cpustate->IO_BCR0H = (cpustate->IO_BCR0H & ~Z180_BCR0H_WMASK) | (data & Z180_BCR0H_WMASK);
+ break;
+
+ case Z180_MAR1L:
+ LOG(("Z180 '%s' MAR1L wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_MAR1L_WMASK));
+ cpustate->IO_MAR1L = (cpustate->IO_MAR1L & ~Z180_MAR1L_WMASK) | (data & Z180_MAR1L_WMASK);
+ break;
+
+ case Z180_MAR1H:
+ LOG(("Z180 '%s' MAR1H wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_MAR1H_WMASK));
+ cpustate->IO_MAR1H = (cpustate->IO_MAR1H & ~Z180_MAR1H_WMASK) | (data & Z180_MAR1H_WMASK);
+ break;
+
+ case Z180_MAR1B:
+ LOG(("Z180 '%s' MAR1B wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_MAR1B_WMASK));
+ cpustate->IO_MAR1B = (cpustate->IO_MAR1B & ~Z180_MAR1B_WMASK) | (data & Z180_MAR1B_WMASK);
+ break;
+
+ case Z180_IAR1L:
+ LOG(("Z180 '%s' IAR1L wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_IAR1L_WMASK));
+ cpustate->IO_IAR1L = (cpustate->IO_IAR1L & ~Z180_IAR1L_WMASK) | (data & Z180_IAR1L_WMASK);
+ break;
+
+ case Z180_IAR1H:
+ LOG(("Z180 '%s' IAR1H wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_IAR1H_WMASK));
+ cpustate->IO_IAR1H = (cpustate->IO_IAR1H & ~Z180_IAR1H_WMASK) | (data & Z180_IAR1H_WMASK);
+ break;
+
+ case Z180_IAR1B:
+ LOG(("Z180 '%s' IAR1B wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_IAR1B_WMASK));
+ cpustate->IO_IAR1B = (cpustate->IO_IAR1B & ~Z180_IAR1B_WMASK) | (data & Z180_IAR1B_WMASK);
+ break;
+
+ case Z180_BCR1L:
+ LOG(("Z180 '%s' BCR1L wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_BCR1L_WMASK));
+ cpustate->IO_BCR1L = (cpustate->IO_BCR1L & ~Z180_BCR1L_WMASK) | (data & Z180_BCR1L_WMASK);
+ break;
+
+ case Z180_BCR1H:
+ LOG(("Z180 '%s' BCR1H wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_BCR1H_WMASK));
+ cpustate->IO_BCR1H = (cpustate->IO_BCR1H & ~Z180_BCR1H_WMASK) | (data & Z180_BCR1H_WMASK);
+ break;
+
+ case Z180_DSTAT:
+ LOG(("Z180 '%s' DSTAT wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_DSTAT_WMASK));
+ cpustate->IO_DSTAT = (cpustate->IO_DSTAT & ~Z180_DSTAT_WMASK) | (data & Z180_DSTAT_WMASK);
+ if ((data & (Z180_DSTAT_DE1 | Z180_DSTAT_DWE1)) == Z180_DSTAT_DE1)
+ cpustate->IO_DSTAT |= Z180_DSTAT_DME; /* DMA enable */
+ if ((data & (Z180_DSTAT_DE0 | Z180_DSTAT_DWE0)) == Z180_DSTAT_DE0)
+ cpustate->IO_DSTAT |= Z180_DSTAT_DME; /* DMA enable */
+ break;
+
+ case Z180_DMODE:
+ LOG(("Z180 '%s' DMODE wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_DMODE_WMASK));
+ cpustate->IO_DMODE = (cpustate->IO_DMODE & ~Z180_DMODE_WMASK) | (data & Z180_DMODE_WMASK);
+ break;
+
+ case Z180_DCNTL:
+ LOG(("Z180 '%s' DCNTL wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_DCNTL_WMASK));
+ cpustate->IO_DCNTL = (cpustate->IO_DCNTL & ~Z180_DCNTL_WMASK) | (data & Z180_DCNTL_WMASK);
+ break;
+
+ case Z180_IL:
+ LOG(("Z180 '%s' IL wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_IL_WMASK));
+ cpustate->IO_IL = (cpustate->IO_IL & ~Z180_IL_WMASK) | (data & Z180_IL_WMASK);
+ break;
+
+ case Z180_ITC:
+ LOG(("Z180 '%s' ITC wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_ITC_WMASK));
+ cpustate->IO_ITC = (cpustate->IO_ITC & ~Z180_ITC_WMASK) | (data & Z180_ITC_WMASK);
+ break;
+
+ case Z180_IO35:
+ LOG(("Z180 '%s' IO35 wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_IO35_WMASK));
+ cpustate->IO_IO35 = (cpustate->IO_IO35 & ~Z180_IO35_WMASK) | (data & Z180_IO35_WMASK);
+ break;
+
+ case Z180_RCR:
+ LOG(("Z180 '%s' RCR wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_RCR_WMASK));
+ cpustate->IO_RCR = (cpustate->IO_RCR & ~Z180_RCR_WMASK) | (data & Z180_RCR_WMASK);
+ break;
+
+ case Z180_IO37:
+ LOG(("Z180 '%s' IO37 wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_IO37_WMASK));
+ cpustate->IO_IO37 = (cpustate->IO_IO37 & ~Z180_IO37_WMASK) | (data & Z180_IO37_WMASK);
+ break;
+
+ case Z180_CBR:
+ LOG(("Z180 '%s' CBR wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_CBR_WMASK));
+ cpustate->IO_CBR = (cpustate->IO_CBR & ~Z180_CBR_WMASK) | (data & Z180_CBR_WMASK);
+ z180_mmu(cpustate);
+ break;
+
+ case Z180_BBR:
+ LOG(("Z180 '%s' BBR wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_BBR_WMASK));
+ cpustate->IO_BBR = (cpustate->IO_BBR & ~Z180_BBR_WMASK) | (data & Z180_BBR_WMASK);
+ z180_mmu(cpustate);
+ break;
+
+ case Z180_CBAR:
+ LOG(("Z180 '%s' CBAR wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_CBAR_WMASK));
+ cpustate->IO_CBAR = (cpustate->IO_CBAR & ~Z180_CBAR_WMASK) | (data & Z180_CBAR_WMASK);
+ z180_mmu(cpustate);
+ break;
+
+ case Z180_IO3B:
+ LOG(("Z180 '%s' IO3B wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_IO3B_WMASK));
+ cpustate->IO_IO3B = (cpustate->IO_IO3B & ~Z180_IO3B_WMASK) | (data & Z180_IO3B_WMASK);
+ break;
+
+ case Z180_IO3C:
+ LOG(("Z180 '%s' IO3C wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_IO3C_WMASK));
+ cpustate->IO_IO3C = (cpustate->IO_IO3C & ~Z180_IO3C_WMASK) | (data & Z180_IO3C_WMASK);
+ break;
+
+ case Z180_IO3D:
+ LOG(("Z180 '%s' IO3D wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_IO3D_WMASK));
+ cpustate->IO_IO3D = (cpustate->IO_IO3D & ~Z180_IO3D_WMASK) | (data & Z180_IO3D_WMASK);
+ break;
+
+ case Z180_OMCR:
+ LOG(("Z180 '%s' OMCR wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_OMCR_WMASK));
+ cpustate->IO_OMCR = (cpustate->IO_OMCR & ~Z180_OMCR_WMASK) | (data & Z180_OMCR_WMASK);
+ break;
+
+ case Z180_IOCR:
+ LOG(("Z180 '%s' IOCR wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_IOCR_WMASK));
+ cpustate->IO_IOCR = (cpustate->IO_IOCR & ~Z180_IOCR_WMASK) | (data & Z180_IOCR_WMASK);
+ break;
+ }
+}
+
+static int z180_dma0(z180_state *cpustate, int max_cycles)
+{
+ offs_t sar0 = 65536 * cpustate->IO_SAR0B + 256 * cpustate->IO_SAR0H + cpustate->IO_SAR0L;
+ offs_t dar0 = 65536 * cpustate->IO_DAR0B + 256 * cpustate->IO_DAR0H + cpustate->IO_DAR0L;
+ int bcr0 = 256 * cpustate->IO_BCR0H + cpustate->IO_BCR0L;
+ int count = (cpustate->IO_DMODE & Z180_DMODE_MMOD) ? bcr0 : 1;
+ int cycles = 0;
+
+ if (bcr0 == 0)
+ {
+ cpustate->IO_DSTAT &= ~Z180_DSTAT_DE0;
+ return 0;
+ }
+
+ while (count-- > 0)
+ {
+ /* last transfer happening now? */
+ if (bcr0 == 1)
+ {
+ cpustate->iol |= Z180_TEND0;
+ }
+ switch( cpustate->IO_DMODE & (Z180_DMODE_SM | Z180_DMODE_DM) )
+ {
+ case 0x00: /* memory SAR0+1 to memory DAR0+1 */
+ cpustate->program->write_byte(dar0++, cpustate->program->read_byte(sar0++));
+ break;
+ case 0x04: /* memory SAR0-1 to memory DAR0+1 */
+ cpustate->program->write_byte(dar0++, cpustate->program->read_byte(sar0--));
+ break;
+ case 0x08: /* memory SAR0 fixed to memory DAR0+1 */
+ cpustate->program->write_byte(dar0++, cpustate->program->read_byte(sar0));
+ break;
+ case 0x0c: /* I/O SAR0 fixed to memory DAR0+1 */
+ if (cpustate->iol & Z180_DREQ0)
+ {
+ cpustate->program->write_byte(dar0++, IN(cpustate, sar0));
+ /* edge sensitive DREQ0 ? */
+ if (cpustate->IO_DCNTL & Z180_DCNTL_DIM0)
+ {
+ cpustate->iol &= ~Z180_DREQ0;
+ count = 0;
+ }
+ }
+ break;
+ case 0x10: /* memory SAR0+1 to memory DAR0-1 */
+ cpustate->program->write_byte(dar0--, cpustate->program->read_byte(sar0++));
+ break;
+ case 0x14: /* memory SAR0-1 to memory DAR0-1 */
+ cpustate->program->write_byte(dar0--, cpustate->program->read_byte(sar0--));
+ break;
+ case 0x18: /* memory SAR0 fixed to memory DAR0-1 */
+ cpustate->program->write_byte(dar0--, cpustate->program->read_byte(sar0));
+ break;
+ case 0x1c: /* I/O SAR0 fixed to memory DAR0-1 */
+ if (cpustate->iol & Z180_DREQ0)
+ {
+ cpustate->program->write_byte(dar0--, IN(cpustate, sar0));
+ /* edge sensitive DREQ0 ? */
+ if (cpustate->IO_DCNTL & Z180_DCNTL_DIM0)
+ {
+ cpustate->iol &= ~Z180_DREQ0;
+ count = 0;
+ }
+ }
+ break;
+ case 0x20: /* memory SAR0+1 to memory DAR0 fixed */
+ cpustate->program->write_byte(dar0, cpustate->program->read_byte(sar0++));
+ break;
+ case 0x24: /* memory SAR0-1 to memory DAR0 fixed */
+ cpustate->program->write_byte(dar0, cpustate->program->read_byte(sar0--));
+ break;
+ case 0x28: /* reserved */
+ break;
+ case 0x2c: /* reserved */
+ break;
+ case 0x30: /* memory SAR0+1 to I/O DAR0 fixed */
+ if (cpustate->iol & Z180_DREQ0)
+ {
+ OUT(cpustate, dar0, cpustate->program->read_byte(sar0++));
+ /* edge sensitive DREQ0 ? */
+ if (cpustate->IO_DCNTL & Z180_DCNTL_DIM0)
+ {
+ cpustate->iol &= ~Z180_DREQ0;
+ count = 0;
+ }
+ }
+ break;
+ case 0x34: /* memory SAR0-1 to I/O DAR0 fixed */
+ if (cpustate->iol & Z180_DREQ0)
+ {
+ OUT(cpustate, dar0, cpustate->program->read_byte(sar0--));
+ /* edge sensitive DREQ0 ? */
+ if (cpustate->IO_DCNTL & Z180_DCNTL_DIM0)
+ {
+ cpustate->iol &= ~Z180_DREQ0;
+ count = 0;
+ }
+ }
+ break;
+ case 0x38: /* reserved */
+ break;
+ case 0x3c: /* reserved */
+ break;
+ }
+ bcr0--;
+ count--;
+ cycles += 6;
+ if (cycles > max_cycles)
+ break;
+ }
+
+ cpustate->IO_SAR0L = sar0;
+ cpustate->IO_SAR0H = sar0 >> 8;
+ cpustate->IO_SAR0B = sar0 >> 16;
+ cpustate->IO_DAR0L = dar0;
+ cpustate->IO_DAR0H = dar0 >> 8;
+ cpustate->IO_DAR0B = dar0 >> 16;
+ cpustate->IO_BCR0L = bcr0;
+ cpustate->IO_BCR0H = bcr0 >> 8;
+
+ /* DMA terminal count? */
+ if (bcr0 == 0)
+ {
+ cpustate->iol &= ~Z180_TEND0;
+ cpustate->IO_DSTAT &= ~Z180_DSTAT_DE0;
+ /* terminal count interrupt enabled? */
+ if (cpustate->IO_DSTAT & Z180_DSTAT_DIE0 && cpustate->IFF1)
+ cpustate->int_pending[Z180_INT_DMA0] = 1;
+ }
+ return cycles;
+}
+
+static int z180_dma1(z180_state *cpustate)
+{
+ offs_t mar1 = 65536 * cpustate->IO_MAR1B + 256 * cpustate->IO_MAR1H + cpustate->IO_MAR1L;
+ offs_t iar1 = 256 * cpustate->IO_IAR1H + cpustate->IO_IAR1L;
+ int bcr1 = 256 * cpustate->IO_BCR1H + cpustate->IO_BCR1L;
+ int cycles = 0;
+
+ if ((cpustate->iol & Z180_DREQ1) == 0)
+ return 0;
+
+ /* counter is zero? */
+ if (bcr1 == 0)
+ {
+ cpustate->IO_DSTAT &= ~Z180_DSTAT_DE1;
+ return 0;
+ }
+
+ /* last transfer happening now? */
+ if (bcr1 == 1)
+ {
+ cpustate->iol |= Z180_TEND1;
+ }
+
+ switch (cpustate->IO_DCNTL & (Z180_DCNTL_DIM1 | Z180_DCNTL_DIM0))
+ {
+ case 0x00: /* memory MAR1+1 to I/O IAR1 fixed */
+ cpustate->iospace->write_byte(iar1, cpustate->program->read_byte(mar1++));
+ break;
+ case 0x01: /* memory MAR1-1 to I/O IAR1 fixed */
+ cpustate->iospace->write_byte(iar1, cpustate->program->read_byte(mar1--));
+ break;
+ case 0x02: /* I/O IAR1 fixed to memory MAR1+1 */
+ cpustate->program->write_byte(mar1++, cpustate->iospace->read_byte(iar1));
+ break;
+ case 0x03: /* I/O IAR1 fixed to memory MAR1-1 */
+ cpustate->program->write_byte(mar1--, cpustate->iospace->read_byte(iar1));
+ break;
+ }
+
+ /* edge sensitive DREQ1 ? */
+ if (cpustate->IO_DCNTL & Z180_DCNTL_DIM1)
+ cpustate->iol &= ~Z180_DREQ1;
+
+ cpustate->IO_MAR1L = mar1;
+ cpustate->IO_MAR1H = mar1 >> 8;
+ cpustate->IO_MAR1B = mar1 >> 16;
+ cpustate->IO_BCR1L = bcr1;
+ cpustate->IO_BCR1H = bcr1 >> 8;
+
+ /* DMA terminal count? */
+ if (bcr1 == 0)
+ {
+ cpustate->iol &= ~Z180_TEND1;
+ cpustate->IO_DSTAT &= ~Z180_DSTAT_DE1;
+ if (cpustate->IO_DSTAT & Z180_DSTAT_DIE1 && cpustate->IFF1)
+ cpustate->int_pending[Z180_INT_DMA1] = 1;
+ }
+
+ /* six cycles per transfer (minimum) */
+ return 6 + cycles;
+}
+
+static void z180_write_iolines(z180_state *cpustate, UINT32 data)
+{
+ UINT32 changes = cpustate->iol ^ data;
+
+ /* I/O asynchronous clock 0 (active high) or DREQ0 (mux) */
+ if (changes & Z180_CKA0)
+ {
+ LOG(("Z180 '%s' CKA0 %d\n", cpustate->device->tag(), data & Z180_CKA0 ? 1 : 0));
+ cpustate->iol = (cpustate->iol & ~Z180_CKA0) | (data & Z180_CKA0);
+ }
+
+ /* I/O asynchronous clock 1 (active high) or TEND1 (mux) */
+ if (changes & Z180_CKA1)
+ {
+ LOG(("Z180 '%s' CKA1 %d\n", cpustate->device->tag(), data & Z180_CKA1 ? 1 : 0));
+ cpustate->iol = (cpustate->iol & ~Z180_CKA1) | (data & Z180_CKA1);
+ }
+
+ /* I/O serial clock (active high) */
+ if (changes & Z180_CKS)
+ {
+ LOG(("Z180 '%s' CKS %d\n", cpustate->device->tag(), data & Z180_CKS ? 1 : 0));
+ cpustate->iol = (cpustate->iol & ~Z180_CKS) | (data & Z180_CKS);
+ }
+
+ /* I clear to send 0 (active low) */
+ if (changes & Z180_CTS0)
+ {
+ LOG(("Z180 '%s' CTS0 %d\n", cpustate->device->tag(), data & Z180_CTS0 ? 1 : 0));
+ cpustate->iol = (cpustate->iol & ~Z180_CTS0) | (data & Z180_CTS0);
+ }
+
+ /* I clear to send 1 (active low) or RXS (mux) */
+ if (changes & Z180_CTS1)
+ {
+ LOG(("Z180 '%s' CTS1 %d\n", cpustate->device->tag(), data & Z180_CTS1 ? 1 : 0));
+ cpustate->iol = (cpustate->iol & ~Z180_CTS1) | (data & Z180_CTS1);
+ }
+
+ /* I data carrier detect (active low) */
+ if (changes & Z180_DCD0)
+ {
+ LOG(("Z180 '%s' DCD0 %d\n", cpustate->device->tag(), data & Z180_DCD0 ? 1 : 0));
+ cpustate->iol = (cpustate->iol & ~Z180_DCD0) | (data & Z180_DCD0);
+ }
+
+ /* I data request DMA ch 0 (active low) or CKA0 (mux) */
+ if (changes & Z180_DREQ0)
+ {
+ LOG(("Z180 '%s' DREQ0 %d\n", cpustate->device->tag(), data & Z180_DREQ0 ? 1 : 0));
+ cpustate->iol = (cpustate->iol & ~Z180_DREQ0) | (data & Z180_DREQ0);
+ }
+
+ /* I data request DMA ch 1 (active low) */
+ if (changes & Z180_DREQ1)
+ {
+ LOG(("Z180 '%s' DREQ1 %d\n", cpustate->device->tag(), data & Z180_DREQ1 ? 1 : 0));
+ cpustate->iol = (cpustate->iol & ~Z180_DREQ1) | (data & Z180_DREQ1);
+ }
+
+ /* I asynchronous receive data 0 (active high) */
+ if (changes & Z180_RXA0)
+ {
+ LOG(("Z180 '%s' RXA0 %d\n", cpustate->device->tag(), data & Z180_RXA0 ? 1 : 0));
+ cpustate->iol = (cpustate->iol & ~Z180_RXA0) | (data & Z180_RXA0);
+ }
+
+ /* I asynchronous receive data 1 (active high) */
+ if (changes & Z180_RXA1)
+ {
+ LOG(("Z180 '%s' RXA1 %d\n", cpustate->device->tag(), data & Z180_RXA1 ? 1 : 0));
+ cpustate->iol = (cpustate->iol & ~Z180_RXA1) | (data & Z180_RXA1);
+ }
+
+ /* I clocked serial receive data (active high) or CTS1 (mux) */
+ if (changes & Z180_RXS)
+ {
+ LOG(("Z180 '%s' RXS %d\n", cpustate->device->tag(), data & Z180_RXS ? 1 : 0));
+ cpustate->iol = (cpustate->iol & ~Z180_RXS) | (data & Z180_RXS);
+ }
+
+ /* O request to send (active low) */
+ if (changes & Z180_RTS0)
+ {
+ LOG(("Z180 '%s' RTS0 won't change output\n", cpustate->device->tag()));
+ }
+
+ /* O transfer end 0 (active low) or CKA1 (mux) */
+ if (changes & Z180_TEND0)
+ {
+ LOG(("Z180 '%s' TEND0 won't change output\n", cpustate->device->tag()));
+ }
+
+ /* O transfer end 1 (active low) */
+ if (changes & Z180_TEND1)
+ {
+ LOG(("Z180 '%s' TEND1 won't change output\n", cpustate->device->tag()));
+ }
+
+ /* O transfer out (PRT channel, active low) or A18 (mux) */
+ if (changes & Z180_A18_TOUT)
+ {
+ LOG(("Z180 '%s' TOUT won't change output\n", cpustate->device->tag()));
+ }
+
+ /* O asynchronous transmit data 0 (active high) */
+ if (changes & Z180_TXA0)
+ {
+ LOG(("Z180 '%s' TXA0 won't change output\n", cpustate->device->tag()));
+ }
+
+ /* O asynchronous transmit data 1 (active high) */
+ if (changes & Z180_TXA1)
+ {
+ LOG(("Z180 '%s' TXA1 won't change output\n", cpustate->device->tag()));
+ }
+
+ /* O clocked serial transmit data (active high) */
+ if (changes & Z180_TXS)
+ {
+ LOG(("Z180 '%s' TXS won't change output\n", cpustate->device->tag()));
+ }
+}
+
+
+static CPU_INIT( z180 )
+{
+ z180_state *cpustate = get_safe_token(device);
+ if (device->static_config() != NULL)
+ cpustate->daisy.init(device, (const z80_daisy_config *)device->static_config());
+ cpustate->irq_callback = irqcallback;
+
+ SZHVC_add = auto_alloc_array(device->machine(), UINT8, 2*256*256);
+ SZHVC_sub = auto_alloc_array(device->machine(), UINT8, 2*256*256);
+
+ /* set up the state table */
+ {
+ device_state_interface *state;
+ device->interface(state);
+ state->state_add(Z180_PC, "PC", cpustate->PC.w.l);
+ state->state_add(STATE_GENPC, "GENPC", cpustate->_PCD).noshow();
+ state->state_add(STATE_GENPCBASE, "GENPCBASE", cpustate->PREPC.w.l).noshow();
+ state->state_add(Z180_SP, "SP", cpustate->_SPD);
+ 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(Z180_A, "A", cpustate->_A).noshow();
+ state->state_add(Z180_B, "B", cpustate->_B).noshow();
+ state->state_add(Z180_C, "C", cpustate->_C).noshow();
+ state->state_add(Z180_D, "D", cpustate->_D).noshow();
+ state->state_add(Z180_E, "E", cpustate->_E).noshow();
+ state->state_add(Z180_H, "H", cpustate->_H).noshow();
+ state->state_add(Z180_L, "L", cpustate->_L).noshow();
+ state->state_add(Z180_AF, "AF", cpustate->AF.w.l);
+ state->state_add(Z180_BC, "BC", cpustate->BC.w.l);
+ state->state_add(Z180_DE, "DE", cpustate->DE.w.l);
+ state->state_add(Z180_HL, "HL", cpustate->HL.w.l);
+ state->state_add(Z180_IX, "IX", cpustate->IX.w.l);
+ state->state_add(Z180_IY, "IY", cpustate->IY.w.l);
+ state->state_add(Z180_AF2, "AF2", cpustate->AF2.w.l);
+ state->state_add(Z180_BC2, "BC2", cpustate->BC2.w.l);
+ state->state_add(Z180_DE2, "DE2", cpustate->DE2.w.l);
+ state->state_add(Z180_HL2, "HL2", cpustate->HL2.w.l);
+ state->state_add(Z180_R, "R", cpustate->rtemp).callimport().callexport();
+ state->state_add(Z180_I, "I", cpustate->I);
+ state->state_add(Z180_IM, "IM", cpustate->IM).mask(0x3);
+ state->state_add(Z180_IFF1, "IFF1", cpustate->IFF1).mask(0x1);
+ state->state_add(Z180_IFF2, "IFF2", cpustate->IFF2).mask(0x1);
+ state->state_add(Z180_HALT, "HALT", cpustate->HALT).mask(0x1);
+
+ state->state_add(Z180_IOLINES, "IOLINES", cpustate->ioltemp).mask(0xffffff).callimport();
+
+ state->state_add(Z180_CNTLA0, "CNTLA0", cpustate->IO_CNTLA0);
+ state->state_add(Z180_CNTLA1, "CNTLA1", cpustate->IO_CNTLA1);
+ state->state_add(Z180_CNTLB0, "CNTLB0", cpustate->IO_CNTLB0);
+ state->state_add(Z180_CNTLB1, "CNTLB1", cpustate->IO_CNTLB1);
+ state->state_add(Z180_STAT0, "STAT0", cpustate->IO_STAT0);
+ state->state_add(Z180_STAT1, "STAT1", cpustate->IO_STAT1);
+ state->state_add(Z180_TDR0, "TDR0", cpustate->IO_TDR0);
+ state->state_add(Z180_TDR1, "TDR1", cpustate->IO_TDR1);
+ state->state_add(Z180_RDR0, "RDR0", cpustate->IO_RDR0);
+ state->state_add(Z180_RDR1, "RDR1", cpustate->IO_RDR1);
+ state->state_add(Z180_CNTR, "CNTR", cpustate->IO_CNTR);
+ state->state_add(Z180_TRDR, "TRDR", cpustate->IO_TRDR);
+ state->state_add(Z180_TMDR0L, "TMDR0L", cpustate->IO_TMDR0L);
+ state->state_add(Z180_TMDR0H, "TMDR0H", cpustate->IO_TMDR0H);
+ state->state_add(Z180_RLDR0L, "RLDR0L", cpustate->IO_RLDR0L);
+ state->state_add(Z180_RLDR0H, "RLDR0H", cpustate->IO_RLDR0H);
+ state->state_add(Z180_TCR, "TCR", cpustate->IO_TCR);
+ state->state_add(Z180_IO11, "IO11", cpustate->IO_IO11);
+ state->state_add(Z180_ASEXT0, "ASEXT0", cpustate->IO_ASEXT0);
+ state->state_add(Z180_ASEXT1, "ASEXT1", cpustate->IO_ASEXT1);
+ state->state_add(Z180_TMDR1L, "TMDR1L", cpustate->IO_TMDR1L);
+ state->state_add(Z180_TMDR1H, "TMDR1H", cpustate->IO_TMDR1H);
+ state->state_add(Z180_RLDR1L, "RLDR1L", cpustate->IO_RLDR1L);
+ state->state_add(Z180_RLDR1H, "RLDR1H", cpustate->IO_RLDR1H);
+ state->state_add(Z180_FRC, "FRC", cpustate->IO_FRC);
+ state->state_add(Z180_IO19, "IO19", cpustate->IO_IO19);
+ state->state_add(Z180_ASTC0L, "ASTC0L", cpustate->IO_ASTC0L);
+ state->state_add(Z180_ASTC0H, "ASTC0H", cpustate->IO_ASTC0H);
+ state->state_add(Z180_ASTC1L, "ASTC1L", cpustate->IO_ASTC1L);
+ state->state_add(Z180_ASTC1H, "ASTC1H", cpustate->IO_ASTC1H);
+ state->state_add(Z180_CMR, "CMR", cpustate->IO_CMR);
+ state->state_add(Z180_CCR, "CCR", cpustate->IO_CCR);
+ state->state_add(Z180_SAR0L, "SAR0L", cpustate->IO_SAR0L);
+ state->state_add(Z180_SAR0H, "SAR0H", cpustate->IO_SAR0H);
+ state->state_add(Z180_SAR0B, "SAR0B", cpustate->IO_SAR0B);
+ state->state_add(Z180_DAR0L, "DAR0L", cpustate->IO_DAR0L);
+ state->state_add(Z180_DAR0H, "DAR0H", cpustate->IO_DAR0H);
+ state->state_add(Z180_DAR0B, "DAR0B", cpustate->IO_DAR0B);
+ state->state_add(Z180_BCR0L, "BCR0L", cpustate->IO_BCR0L);
+ state->state_add(Z180_BCR0H, "BCR0H", cpustate->IO_BCR0H);
+ state->state_add(Z180_MAR1L, "MAR1L", cpustate->IO_MAR1L);
+ state->state_add(Z180_MAR1H, "MAR1H", cpustate->IO_MAR1H);
+ state->state_add(Z180_MAR1B, "MAR1B", cpustate->IO_MAR1B);
+ state->state_add(Z180_IAR1L, "IAR1L", cpustate->IO_IAR1L);
+ state->state_add(Z180_IAR1H, "IAR1H", cpustate->IO_IAR1H);
+ state->state_add(Z180_IAR1B, "IAR1B", cpustate->IO_IAR1B);
+ state->state_add(Z180_BCR1L, "BCR1L", cpustate->IO_BCR1L);
+ state->state_add(Z180_BCR1H, "BCR1H", cpustate->IO_BCR1H);
+ state->state_add(Z180_DSTAT, "DSTAT", cpustate->IO_DSTAT);
+ state->state_add(Z180_DMODE, "DMODE", cpustate->IO_DMODE);
+ state->state_add(Z180_DCNTL, "DCNTL", cpustate->IO_DCNTL);
+ state->state_add(Z180_IL, "IL", cpustate->IO_IL);
+ state->state_add(Z180_ITC, "ITC", cpustate->IO_ITC);
+ state->state_add(Z180_IO35, "IO35", cpustate->IO_IO35);
+ state->state_add(Z180_RCR, "RCR", cpustate->IO_RCR);
+ state->state_add(Z180_IO37, "IO37", cpustate->IO_IO37);
+ state->state_add(Z180_CBR, "CBR", cpustate->IO_CBR).callimport();
+ state->state_add(Z180_BBR, "BBR", cpustate->IO_BBR).callimport();
+ state->state_add(Z180_CBAR, "CBAR", cpustate->IO_CBAR).callimport();
+ state->state_add(Z180_IO3B, "IO3B", cpustate->IO_IO3B);
+ state->state_add(Z180_IO3C, "IO3C", cpustate->IO_IO3C);
+ state->state_add(Z180_IO3D, "IO3D", cpustate->IO_IO3D);
+ state->state_add(Z180_OMCR, "OMCR", cpustate->IO_OMCR);
+ state->state_add(Z180_IOCR, "IOCR", cpustate->IO_IOCR);
+ }
+
+ 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->IX.w.l));
+ device->save_item(NAME(cpustate->IY.w.l));
+ device->save_item(NAME(cpustate->PC.w.l));
+ device->save_item(NAME(cpustate->SP.w.l));
+ device->save_item(NAME(cpustate->AF2.w.l));
+ device->save_item(NAME(cpustate->BC2.w.l));
+ device->save_item(NAME(cpustate->DE2.w.l));
+ device->save_item(NAME(cpustate->HL2.w.l));
+ device->save_item(NAME(cpustate->R));
+ device->save_item(NAME(cpustate->R2));
+ device->save_item(NAME(cpustate->IFF1));
+ device->save_item(NAME(cpustate->IFF2));
+ device->save_item(NAME(cpustate->HALT));
+ device->save_item(NAME(cpustate->IM));
+ device->save_item(NAME(cpustate->I));
+ device->save_item(NAME(cpustate->nmi_state));
+ device->save_item(NAME(cpustate->nmi_pending));
+ device->save_item(NAME(cpustate->irq_state));
+ device->save_item(NAME(cpustate->int_pending));
+ device->save_item(NAME(cpustate->timer_cnt));
+ device->save_item(NAME(cpustate->dma0_cnt));
+ device->save_item(NAME(cpustate->dma1_cnt));
+ device->save_item(NAME(cpustate->after_EI));
+
+ device->save_item(NAME(cpustate->tif));
+
+ device->save_item(NAME(cpustate->read_tcr_tmdr));
+ device->save_item(NAME(cpustate->tmdr_value));
+ device->save_item(NAME(cpustate->tmdrh));
+ device->save_item(NAME(cpustate->tmdr_latch));
+
+ device->save_item(NAME(cpustate->io));
+ device->save_item(NAME(cpustate->iol));
+ device->save_item(NAME(cpustate->ioltemp));
+
+ device->save_item(NAME(cpustate->mmu));
+
+}
+
+/****************************************************************************
+ * Reset registers to their initial values
+ ****************************************************************************/
+static CPU_RESET( z180 )
+{
+ z180_state *cpustate = get_safe_token(device);
+ int i, p;
+ int oldval, newval, val;
+ UINT8 *padd, *padc, *psub, *psbc;
+ /* allocate big flag arrays once */
+ padd = &SZHVC_add[ 0*256];
+ padc = &SZHVC_add[256*256];
+ psub = &SZHVC_sub[ 0*256];
+ psbc = &SZHVC_sub[256*256];
+ for (oldval = 0; oldval < 256; oldval++)
+ {
+ for (newval = 0; newval < 256; newval++)
+ {
+ /* add or adc w/o carry set */
+ val = newval - oldval;
+ *padd = (newval) ? ((newval & 0x80) ? SF : 0) : ZF;
+ *padd |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */
+
+ if( (newval & 0x0f) < (oldval & 0x0f) ) *padd |= HF;
+ if( newval < oldval ) *padd |= CF;
+ if( (val^oldval^0x80) & (val^newval) & 0x80 ) *padd |= VF;
+ padd++;
+
+ /* adc with carry set */
+ val = newval - oldval - 1;
+ *padc = (newval) ? ((newval & 0x80) ? SF : 0) : ZF;
+ *padc |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */
+ if( (newval & 0x0f) <= (oldval & 0x0f) ) *padc |= HF;
+ if( newval <= oldval ) *padc |= CF;
+ if( (val^oldval^0x80) & (val^newval) & 0x80 ) *padc |= VF;
+ padc++;
+
+ /* cp, sub or sbc w/o carry set */
+ val = oldval - newval;
+ *psub = NF | ((newval) ? ((newval & 0x80) ? SF : 0) : ZF);
+ *psub |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */
+ if( (newval & 0x0f) > (oldval & 0x0f) ) *psub |= HF;
+ if( newval > oldval ) *psub |= CF;
+ if( (val^oldval) & (oldval^newval) & 0x80 ) *psub |= VF;
+ psub++;
+
+ /* sbc with carry set */
+ val = oldval - newval - 1;
+ *psbc = NF | ((newval) ? ((newval & 0x80) ? SF : 0) : ZF);
+ *psbc |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */
+ if( (newval & 0x0f) >= (oldval & 0x0f) ) *psbc |= HF;
+ if( newval >= oldval ) *psbc |= CF;
+ if( (val^oldval) & (oldval^newval) & 0x80 ) *psbc |= VF;
+ psbc++;
+ }
+ }
+ for (i = 0; i < 256; i++)
+ {
+ p = 0;
+ if( i&0x01 ) ++p;
+ if( i&0x02 ) ++p;
+ if( i&0x04 ) ++p;
+ if( i&0x08 ) ++p;
+ if( i&0x10 ) ++p;
+ if( i&0x20 ) ++p;
+ if( i&0x40 ) ++p;
+ if( i&0x80 ) ++p;
+ SZ[i] = i ? i & SF : ZF;
+ SZ[i] |= (i & (YF | XF)); /* undocumented flag bits 5+3 */
+ SZ_BIT[i] = i ? i & SF : ZF | PF;
+ SZ_BIT[i] |= (i & (YF | XF)); /* undocumented flag bits 5+3 */
+ SZP[i] = SZ[i] | ((p & 1) ? 0 : PF);
+ SZHV_inc[i] = SZ[i];
+ if( i == 0x80 ) SZHV_inc[i] |= VF;
+ if( (i & 0x0f) == 0x00 ) SZHV_inc[i] |= HF;
+ SZHV_dec[i] = SZ[i] | NF;
+ if( i == 0x7f ) SZHV_dec[i] |= VF;
+ if( (i & 0x0f) == 0x0f ) SZHV_dec[i] |= HF;
+ }
+
+ cpustate->_PPC = 0;
+ cpustate->_PCD = 0;
+ cpustate->_SPD = 0;
+ cpustate->_AFD = 0;
+ cpustate->_BCD = 0;
+ cpustate->_DED = 0;
+ cpustate->_HLD = 0;
+ cpustate->_IXD = 0;
+ cpustate->_IYD = 0;
+ cpustate->AF2.d = 0;
+ cpustate->BC2.d = 0;
+ cpustate->DE2.d = 0;
+ cpustate->HL2.d = 0;
+ cpustate->R = 0;
+ cpustate->R2 = 0;
+ cpustate->IFF1 = 0;
+ cpustate->IFF2 = 0;
+ cpustate->HALT = 0;
+ cpustate->IM = 0;
+ cpustate->I = 0;
+ cpustate->tmdr_latch = 0;
+ cpustate->read_tcr_tmdr[0] = 0;
+ cpustate->read_tcr_tmdr[1] = 0;
+ cpustate->iol = 0;
+ memset(cpustate->io, 0, sizeof(cpustate->io));
+ memset(cpustate->mmu, 0, sizeof(cpustate->mmu));
+ cpustate->tmdrh[0] = 0;
+ cpustate->tmdrh[1] = 0;
+ cpustate->tmdr_value[0] = 0xffff;
+ cpustate->tmdr_value[1] = 0xffff;
+ cpustate->tif[0] = 0;
+ cpustate->tif[1] = 0;
+ cpustate->nmi_state = CLEAR_LINE;
+ cpustate->nmi_pending = 0;
+ cpustate->irq_state[0] = CLEAR_LINE;
+ cpustate->irq_state[1] = CLEAR_LINE;
+ cpustate->irq_state[2] = CLEAR_LINE;
+ cpustate->after_EI = 0;
+ cpustate->ea = 0;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->iospace = device->space(AS_IO);
+ cpustate->device = device;
+
+ memcpy(cpustate->cc, (UINT8 *)cc_default, sizeof(cpustate->cc));
+ cpustate->_IX = cpustate->_IY = 0xffff; /* IX and IY are FFFF after a reset! */
+ cpustate->_F = ZF; /* Zero flag is set */
+
+ for (i=0; i <= Z180_INT_MAX; i++)
+ cpustate->int_pending[i] = 0;
+
+ cpustate->timer_cnt = 0;
+ cpustate->dma0_cnt = 0;
+ cpustate->dma1_cnt = 0;
+
+ /* reset io registers */
+ cpustate->IO_CNTLA0 = Z180_CNTLA0_RESET;
+ cpustate->IO_CNTLA1 = Z180_CNTLA1_RESET;
+ cpustate->IO_CNTLB0 = Z180_CNTLB0_RESET;
+ cpustate->IO_CNTLB1 = Z180_CNTLB1_RESET;
+ cpustate->IO_STAT0 = Z180_STAT0_RESET;
+ cpustate->IO_STAT1 = Z180_STAT1_RESET;
+ cpustate->IO_TDR0 = Z180_TDR0_RESET;
+ cpustate->IO_TDR1 = Z180_TDR1_RESET;
+ cpustate->IO_RDR0 = Z180_RDR0_RESET;
+ cpustate->IO_RDR1 = Z180_RDR1_RESET;
+ cpustate->IO_CNTR = Z180_CNTR_RESET;
+ cpustate->IO_TRDR = Z180_TRDR_RESET;
+ cpustate->IO_TMDR0L = Z180_TMDR0L_RESET;
+ cpustate->IO_TMDR0H = Z180_TMDR0H_RESET;
+ cpustate->IO_RLDR0L = Z180_RLDR0L_RESET;
+ cpustate->IO_RLDR0H = Z180_RLDR0H_RESET;
+ cpustate->IO_TCR = Z180_TCR_RESET;
+ cpustate->IO_IO11 = Z180_IO11_RESET;
+ cpustate->IO_ASEXT0 = Z180_ASEXT0_RESET;
+ cpustate->IO_ASEXT1 = Z180_ASEXT1_RESET;
+ cpustate->IO_TMDR1L = Z180_TMDR1L_RESET;
+ cpustate->IO_TMDR1H = Z180_TMDR1H_RESET;
+ cpustate->IO_RLDR1L = Z180_RLDR1L_RESET;
+ cpustate->IO_RLDR1H = Z180_RLDR1H_RESET;
+ cpustate->IO_FRC = Z180_FRC_RESET;
+ cpustate->IO_IO19 = Z180_IO19_RESET;
+ cpustate->IO_ASTC0L = Z180_ASTC0L_RESET;
+ cpustate->IO_ASTC0H = Z180_ASTC0H_RESET;
+ cpustate->IO_ASTC1L = Z180_ASTC1L_RESET;
+ cpustate->IO_ASTC1H = Z180_ASTC1H_RESET;
+ cpustate->IO_CMR = Z180_CMR_RESET;
+ cpustate->IO_CCR = Z180_CCR_RESET;
+ cpustate->IO_SAR0L = Z180_SAR0L_RESET;
+ cpustate->IO_SAR0H = Z180_SAR0H_RESET;
+ cpustate->IO_SAR0B = Z180_SAR0B_RESET;
+ cpustate->IO_DAR0L = Z180_DAR0L_RESET;
+ cpustate->IO_DAR0H = Z180_DAR0H_RESET;
+ cpustate->IO_DAR0B = Z180_DAR0B_RESET;
+ cpustate->IO_BCR0L = Z180_BCR0L_RESET;
+ cpustate->IO_BCR0H = Z180_BCR0H_RESET;
+ cpustate->IO_MAR1L = Z180_MAR1L_RESET;
+ cpustate->IO_MAR1H = Z180_MAR1H_RESET;
+ cpustate->IO_MAR1B = Z180_MAR1B_RESET;
+ cpustate->IO_IAR1L = Z180_IAR1L_RESET;
+ cpustate->IO_IAR1H = Z180_IAR1H_RESET;
+ cpustate->IO_IAR1B = Z180_IAR1B_RESET;
+ cpustate->IO_BCR1L = Z180_BCR1L_RESET;
+ cpustate->IO_BCR1H = Z180_BCR1H_RESET;
+ cpustate->IO_DSTAT = Z180_DSTAT_RESET;
+ cpustate->IO_DMODE = Z180_DMODE_RESET;
+ cpustate->IO_DCNTL = Z180_DCNTL_RESET;
+ cpustate->IO_IL = Z180_IL_RESET;
+ cpustate->IO_ITC = Z180_ITC_RESET;
+ cpustate->IO_IO35 = Z180_IO35_RESET;
+ cpustate->IO_RCR = Z180_RCR_RESET;
+ cpustate->IO_IO37 = Z180_IO37_RESET;
+ cpustate->IO_CBR = Z180_CBR_RESET;
+ cpustate->IO_BBR = Z180_BBR_RESET;
+ cpustate->IO_CBAR = Z180_CBAR_RESET;
+ cpustate->IO_IO3B = Z180_IO3B_RESET;
+ cpustate->IO_IO3C = Z180_IO3C_RESET;
+ cpustate->IO_IO3D = Z180_IO3D_RESET;
+ cpustate->IO_OMCR = Z180_OMCR_RESET;
+ cpustate->IO_IOCR = Z180_IOCR_RESET;
+
+ cpustate->daisy.reset();
+ z180_mmu(cpustate);
+}
+
+/* Handle PRT timers, decreasing them after 20 clocks and returning the new icount base that needs to be used for the next check */
+static void clock_timers(z180_state *cpustate)
+{
+ cpustate->timer_cnt++;
+ if (cpustate->timer_cnt >= 20)
+ {
+ cpustate->timer_cnt = 0;
+ /* Programmable Reload Timer 0 */
+ if(cpustate->IO_TCR & Z180_TCR_TDE0)
+ {
+ if(cpustate->tmdr_value[0] == 0)
+ {
+ cpustate->tmdr_value[0] = cpustate->IO_RLDR0L | (cpustate->IO_RLDR0H << 8);
+ cpustate->tif[0] = 1;
+ }
+ else
+ cpustate->tmdr_value[0]--;
+ }
+
+ /* Programmable Reload Timer 1 */
+ if(cpustate->IO_TCR & Z180_TCR_TDE1)
+ {
+ if(cpustate->tmdr_value[1] == 0)
+ {
+ cpustate->tmdr_value[1] = cpustate->IO_RLDR1L | (cpustate->IO_RLDR1H << 8);
+ cpustate->tif[1] = 1;
+ }
+ else
+ cpustate->tmdr_value[1]--;
+ }
+
+ if((cpustate->IO_TCR & Z180_TCR_TIE0) && cpustate->tif[0])
+ {
+ // check if we can take the interrupt
+ if(cpustate->IFF1 && !cpustate->after_EI)
+ {
+ cpustate->int_pending[Z180_INT_PRT0] = 1;
+ }
+ }
+
+ if((cpustate->IO_TCR & Z180_TCR_TIE1) && cpustate->tif[1])
+ {
+ // check if we can take the interrupt
+ if(cpustate->IFF1 && !cpustate->after_EI)
+ {
+ cpustate->int_pending[Z180_INT_PRT1] = 1;
+ }
+ }
+
+ }
+}
+
+static int check_interrupts(z180_state *cpustate)
+{
+ int i;
+ int cycles = 0;
+
+ /* check for IRQs before each instruction */
+ if (cpustate->IFF1 && !cpustate->after_EI)
+ {
+ if (cpustate->irq_state[0] != CLEAR_LINE && (cpustate->IO_ITC & Z180_ITC_ITE0) == Z180_ITC_ITE0)
+ cpustate->int_pending[Z180_INT_IRQ0] = 1;
+
+ if (cpustate->irq_state[1] != CLEAR_LINE && (cpustate->IO_ITC & Z180_ITC_ITE1) == Z180_ITC_ITE1)
+ cpustate->int_pending[Z180_INT_IRQ1] = 1;
+
+ if (cpustate->irq_state[2] != CLEAR_LINE && (cpustate->IO_ITC & Z180_ITC_ITE2) == Z180_ITC_ITE2)
+ cpustate->int_pending[Z180_INT_IRQ2] = 1;
+ }
+
+ for (i = 0; i <= Z180_INT_MAX; i++)
+ if (cpustate->int_pending[i])
+ {
+ cycles += take_interrupt(cpustate, i);
+ cpustate->int_pending[i] = 0;
+ break;
+ }
+
+ return cycles;
+}
+
+/****************************************************************************
+ * Handle I/O and timers
+ ****************************************************************************/
+
+static void handle_io_timers(z180_state *cpustate, int cycles)
+{
+ while (cycles-- > 0)
+ {
+ clock_timers(cpustate);
+ }
+}
+
+/****************************************************************************
+ * Execute 'cycles' T-states. Return number of T-states really executed
+ ****************************************************************************/
+static CPU_EXECUTE( z180 )
+{
+ z180_state *cpustate = get_safe_token(device);
+ int curcycles;
+
+ /* check for NMIs on the way in; they can only be set externally */
+ /* via timers, and can't be dynamically enabled, so it is safe */
+ /* to just check here */
+ if (cpustate->nmi_pending)
+ {
+ LOG(("Z180 '%s' take NMI\n", cpustate->device->tag()));
+ cpustate->_PPC = -1; /* there isn't a valid previous program counter */
+ LEAVE_HALT(cpustate); /* Check if processor was halted */
+
+ /* disable DMA transfers!! */
+ cpustate->IO_DSTAT &= ~Z180_DSTAT_DME;
+
+ cpustate->IFF2 = cpustate->IFF1;
+ cpustate->IFF1 = 0;
+ PUSH(cpustate, PC );
+ cpustate->_PCD = 0x0066;
+ cpustate->icount -= 11;
+ cpustate->nmi_pending = 0;
+ handle_io_timers(cpustate, 11);
+ }
+
+again:
+ /* check if any DMA transfer is running */
+ if ((cpustate->IO_DSTAT & Z180_DSTAT_DME) == Z180_DSTAT_DME)
+ {
+ /* check if DMA channel 0 is running and also is in burst mode */
+ if ((cpustate->IO_DSTAT & Z180_DSTAT_DE0) == Z180_DSTAT_DE0 &&
+ (cpustate->IO_DMODE & Z180_DMODE_MMOD) == Z180_DMODE_MMOD)
+ {
+ debugger_instruction_hook(device, cpustate->_PCD);
+
+ /* FIXME z180_dma0 should be handled in handle_io_timers */
+ curcycles = z180_dma0(cpustate, cpustate->icount);
+ cpustate->icount -= curcycles;
+ handle_io_timers(cpustate, curcycles);
+ }
+ else
+ {
+ do
+ {
+ curcycles = check_interrupts(cpustate);
+ cpustate->icount -= curcycles;
+ handle_io_timers(cpustate, curcycles);
+ cpustate->after_EI = 0;
+
+ cpustate->_PPC = cpustate->_PCD;
+ debugger_instruction_hook(device, cpustate->_PCD);
+
+ if (!cpustate->HALT)
+ {
+ cpustate->R++;
+ cpustate->extra_cycles = 0;
+ curcycles = exec_op(cpustate,ROP(cpustate));
+ curcycles += cpustate->extra_cycles;
+ }
+ else
+ curcycles = 3;
+
+ cpustate->icount -= curcycles;
+
+ handle_io_timers(cpustate, curcycles);
+
+ /* FIXME:
+ * For simultaneous DREQ0 and DREQ1 requests, channel 0 has priority
+ * over channel 1. When channel 0 is performing a memory to/from memory
+ * transfer, channel 1 cannot operate until the channel 0 operation has
+ * terminated. If channel 1 is operating, channel 0 cannot operate until
+ * channel 1 releases control of the bus.
+ *
+ */
+ curcycles = z180_dma0(cpustate, 6);
+ cpustate->icount -= curcycles;
+ handle_io_timers(cpustate, curcycles);
+
+ curcycles = z180_dma1(cpustate);
+ cpustate->icount -= curcycles;
+ handle_io_timers(cpustate, curcycles);
+
+ /* If DMA is done break out to the faster loop */
+ if ((cpustate->IO_DSTAT & Z180_DSTAT_DME) != Z180_DSTAT_DME)
+ break;
+ } while( cpustate->icount > 0 );
+ }
+ }
+
+ if (cpustate->icount > 0)
+ {
+ do
+ {
+ curcycles = check_interrupts(cpustate);
+ cpustate->icount -= curcycles;
+ handle_io_timers(cpustate, curcycles);
+ cpustate->after_EI = 0;
+
+ cpustate->_PPC = cpustate->_PCD;
+ debugger_instruction_hook(device, cpustate->_PCD);
+
+ if (!cpustate->HALT)
+ {
+ cpustate->R++;
+ cpustate->extra_cycles = 0;
+ curcycles = exec_op(cpustate,ROP(cpustate));
+ curcycles += cpustate->extra_cycles;
+ }
+ else
+ curcycles = 3;
+
+ cpustate->icount -= curcycles;
+ handle_io_timers(cpustate, curcycles);
+
+ /* If DMA is started go to check the mode */
+ if ((cpustate->IO_DSTAT & Z180_DSTAT_DME) == Z180_DSTAT_DME)
+ goto again;
+ } while( cpustate->icount > 0 );
+ }
+
+ //cpustate->old_icount -= cpustate->icount;
+}
+
+/****************************************************************************
+ * Burn 'cycles' T-states. Adjust R register for the lost time
+ ****************************************************************************/
+static CPU_BURN( z180 )
+{
+ /* FIXME: This is not appropriate for dma */
+ z180_state *cpustate = get_safe_token(device);
+ while ( (cycles > 0) )
+ {
+ handle_io_timers(cpustate, 3);
+ /* NOP takes 3 cycles per instruction */
+ cpustate->R += 1;
+ cpustate->icount -= 3;
+ cycles -= 3;
+ }
+}
+
+/****************************************************************************
+ * Set IRQ line state
+ ****************************************************************************/
+static void set_irq_line(z180_state *cpustate, int irqline, int state)
+{
+ if (irqline == INPUT_LINE_NMI)
+ {
+ /* mark an NMI pending on the rising edge */
+ if (cpustate->nmi_state == CLEAR_LINE && state != CLEAR_LINE)
+ cpustate->nmi_pending = 1;
+ cpustate->nmi_state = state;
+ }
+ else
+ {
+ LOG(("Z180 '%s' set_irq_line %d = %d\n",cpustate->device->tag() , irqline,state));
+
+ /* update the IRQ state */
+ cpustate->irq_state[irqline] = state;
+ if (cpustate->daisy.present())
+ cpustate->irq_state[0] = cpustate->daisy.update_irq_state();
+
+ /* the main execute loop will take the interrupt */
+ }
+}
+
+/* logical to physical address translation */
+static CPU_TRANSLATE( z180 )
+{
+ if (space == AS_PROGRAM)
+ {
+ z180_state *cpustate = get_safe_token(device);
+ *address = MMU_REMAP_ADDR(cpustate, *address);
+ }
+ return TRUE;
+}
+
+
+/**************************************************************************
+ * STATE IMPORT/EXPORT
+ **************************************************************************/
+
+static CPU_IMPORT_STATE( z180 )
+{
+ z180_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case Z180_R:
+ cpustate->R = cpustate->rtemp & 0x7f;
+ cpustate->R2 = cpustate->rtemp & 0x80;
+ break;
+
+ case Z180_CBR:
+ case Z180_BBR:
+ case Z180_CBAR:
+ z180_mmu(cpustate);
+ break;
+
+ case Z180_IOLINES:
+ z180_write_iolines(cpustate, cpustate->ioltemp);
+ break;
+
+ default:
+ fatalerror("CPU_IMPORT_STATE(z80) called for unexpected value\n");
+ break;
+ }
+}
+
+
+static CPU_EXPORT_STATE( z180 )
+{
+ z180_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case Z180_R:
+ cpustate->rtemp = (cpustate->R & 0x7f) | (cpustate->R2 & 0x80);
+ break;
+
+ case Z180_IOLINES:
+ cpustate->ioltemp = cpustate->iol;
+ break;
+
+ default:
+ fatalerror("CPU_EXPORT_STATE(z80) called for unexpected value\n");
+ break;
+ }
+}
+
+static CPU_EXPORT_STRING( z180 )
+{
+ z180_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 ? '5':'.',
+ cpustate->AF.b.l & 0x10 ? 'H':'.',
+ cpustate->AF.b.l & 0x08 ? '3':'.',
+ cpustate->AF.b.l & 0x04 ? 'P':'.',
+ cpustate->AF.b.l & 0x02 ? 'N':'.',
+ cpustate->AF.b.l & 0x01 ? 'C':'.');
+ break;
+ }
+}
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( z180 )
+{
+ z180_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_NMI: set_irq_line(cpustate, INPUT_LINE_NMI, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + Z180_IRQ0: set_irq_line(cpustate, Z180_IRQ0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + Z180_IRQ1: set_irq_line(cpustate, Z180_IRQ1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + Z180_IRQ2: set_irq_line(cpustate, Z180_IRQ2, info->i); break;
+
+ /* --- the following bits of info are set as pointers to data or functions --- */
+ case CPUINFO_PTR_Z180_CYCLE_TABLE + Z180_TABLE_op: cpustate->cc[Z180_TABLE_op] = (UINT8 *)info->p; break;
+ case CPUINFO_PTR_Z180_CYCLE_TABLE + Z180_TABLE_cb: cpustate->cc[Z180_TABLE_cb] = (UINT8 *)info->p; break;
+ case CPUINFO_PTR_Z180_CYCLE_TABLE + Z180_TABLE_ed: cpustate->cc[Z180_TABLE_ed] = (UINT8 *)info->p; break;
+ case CPUINFO_PTR_Z180_CYCLE_TABLE + Z180_TABLE_xy: cpustate->cc[Z180_TABLE_xy] = (UINT8 *)info->p; break;
+ case CPUINFO_PTR_Z180_CYCLE_TABLE + Z180_TABLE_xycb: cpustate->cc[Z180_TABLE_xycb] = (UINT8 *)info->p; break;
+ case CPUINFO_PTR_Z180_CYCLE_TABLE + Z180_TABLE_ex: cpustate->cc[Z180_TABLE_ex] = (UINT8 *)info->p; break;
+ }
+}
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( z180 )
+{
+ z180_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(z180_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 3; 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; 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 = 20; 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 = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = cpustate->nmi_state; break;
+ case CPUINFO_INT_INPUT_STATE + Z180_IRQ0: info->i = cpustate->irq_state[0]; break;
+ case CPUINFO_INT_INPUT_STATE + Z180_IRQ1: info->i = cpustate->irq_state[1]; break;
+ case CPUINFO_INT_INPUT_STATE + Z180_IRQ2: info->i = cpustate->irq_state[2]; break;
+
+ /* --- the following bits of info are returned as pointers --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(z180); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(z180); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(z180); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(z180); break;
+ case CPUINFO_FCT_BURN: info->burn = CPU_BURN_NAME(z180); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(z180); break;
+ case CPUINFO_FCT_TRANSLATE: info->translate = CPU_TRANSLATE_NAME(z180); break;
+ case CPUINFO_FCT_IMPORT_STATE: info->import_state = CPU_IMPORT_STATE_NAME(z180); break;
+ case CPUINFO_FCT_EXPORT_STATE: info->export_state = CPU_EXPORT_STATE_NAME(z180); break;
+ case CPUINFO_FCT_EXPORT_STRING: info->export_string = CPU_EXPORT_STRING_NAME(z180); break;
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ case CPUINFO_PTR_Z180_CYCLE_TABLE + Z180_TABLE_op: info->p = (void *)cpustate->cc[Z180_TABLE_op]; break;
+ case CPUINFO_PTR_Z180_CYCLE_TABLE + Z180_TABLE_cb: info->p = (void *)cpustate->cc[Z180_TABLE_cb]; break;
+ case CPUINFO_PTR_Z180_CYCLE_TABLE + Z180_TABLE_ed: info->p = (void *)cpustate->cc[Z180_TABLE_ed]; break;
+ case CPUINFO_PTR_Z180_CYCLE_TABLE + Z180_TABLE_xy: info->p = (void *)cpustate->cc[Z180_TABLE_xy]; break;
+ case CPUINFO_PTR_Z180_CYCLE_TABLE + Z180_TABLE_xycb: info->p = (void *)cpustate->cc[Z180_TABLE_xycb]; break;
+ case CPUINFO_PTR_Z180_CYCLE_TABLE + Z180_TABLE_ex: info->p = (void *)cpustate->cc[Z180_TABLE_ex]; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Z180"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Zilog Z8x180"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "0.4"); 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;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(Z180, z180);
diff --git a/trunk/src/emu/cpu/z180/z180.h b/trunk/src/emu/cpu/z180/z180.h
new file mode 100644
index 00000000000..7cb62db363d
--- /dev/null
+++ b/trunk/src/emu/cpu/z180/z180.h
@@ -0,0 +1,141 @@
+#pragma once
+
+#ifndef __Z180_H__
+#define __Z180_H__
+
+
+enum
+{
+ Z180_PC,
+ Z180_SP,
+ Z180_AF,
+ Z180_BC,
+ Z180_DE,
+ Z180_HL,
+ Z180_IX,
+ Z180_IY,
+ Z180_A,
+ Z180_B,
+ Z180_C,
+ Z180_D,
+ Z180_E,
+ Z180_H,
+ Z180_L,
+ Z180_AF2,
+ Z180_BC2,
+ Z180_DE2,
+ Z180_HL2,
+ Z180_R,
+ Z180_I,
+ Z180_IM,
+ Z180_IFF1,
+ Z180_IFF2,
+ Z180_HALT,
+ Z180_DC0,
+ Z180_DC1,
+ Z180_DC2,
+ Z180_DC3,
+ Z180_CNTLA0, /* 00 ASCI control register A ch 0 */
+ Z180_CNTLA1, /* 01 ASCI control register A ch 1 */
+ Z180_CNTLB0, /* 02 ASCI control register B ch 0 */
+ Z180_CNTLB1, /* 03 ASCI control register B ch 1 */
+ Z180_STAT0, /* 04 ASCI status register 0 */
+ Z180_STAT1, /* 05 ASCI status register 1 */
+ Z180_TDR0, /* 06 ASCI transmit data register 0 */
+ Z180_TDR1, /* 07 ASCI transmit data register 1 */
+ Z180_RDR0, /* 08 ASCI receive data register 0 */
+ Z180_RDR1, /* 09 ASCI receive data register 1 */
+ Z180_CNTR, /* 0a CSI/O control/status register */
+ Z180_TRDR, /* 0b CSI/O transmit/receive register */
+ Z180_TMDR0L, /* 0c TIMER data register ch 0 L */
+ Z180_TMDR0H, /* 0d TIMER data register ch 0 H */
+ Z180_RLDR0L, /* 0e TIMER reload register ch 0 L */
+ Z180_RLDR0H, /* 0f TIMER reload register ch 0 H */
+ Z180_TCR, /* 10 TIMER control register */
+ Z180_IO11, /* 11 reserved */
+ Z180_ASEXT0, /* 12 (Z8S180/Z8L180) ASCI extension control register 0 */
+ Z180_ASEXT1, /* 13 (Z8S180/Z8L180) ASCI extension control register 0 */
+ Z180_TMDR1L, /* 14 TIMER data register ch 1 L */
+ Z180_TMDR1H, /* 15 TIMER data register ch 1 H */
+ Z180_RLDR1L, /* 16 TIMER reload register ch 1 L */
+ Z180_RLDR1H, /* 17 TIMER reload register ch 1 H */
+ Z180_FRC, /* 18 free running counter */
+ Z180_IO19, /* 19 reserved */
+ Z180_ASTC0L, /* 1a ASCI time constant ch 0 L */
+ Z180_ASTC0H, /* 1b ASCI time constant ch 0 H */
+ Z180_ASTC1L, /* 1c ASCI time constant ch 1 L */
+ Z180_ASTC1H, /* 1d ASCI time constant ch 1 H */
+ Z180_CMR, /* 1e clock multiplier */
+ Z180_CCR, /* 1f chip control register */
+ Z180_SAR0L, /* 20 DMA source address register ch 0 L */
+ Z180_SAR0H, /* 21 DMA source address register ch 0 H */
+ Z180_SAR0B, /* 22 DMA source address register ch 0 B */
+ Z180_DAR0L, /* 23 DMA destination address register ch 0 L */
+ Z180_DAR0H, /* 24 DMA destination address register ch 0 H */
+ Z180_DAR0B, /* 25 DMA destination address register ch 0 B */
+ Z180_BCR0L, /* 26 DMA byte count register ch 0 L */
+ Z180_BCR0H, /* 27 DMA byte count register ch 0 H */
+ Z180_MAR1L, /* 28 DMA memory address register ch 1 L */
+ Z180_MAR1H, /* 29 DMA memory address register ch 1 H */
+ Z180_MAR1B, /* 2a DMA memory address register ch 1 B */
+ Z180_IAR1L, /* 2b DMA I/O address register ch 1 L */
+ Z180_IAR1H, /* 2c DMA I/O address register ch 1 H */
+ Z180_IAR1B, /* 2d (Z8S180/Z8L180) DMA I/O address register ch 1 B */
+ Z180_BCR1L, /* 2e DMA byte count register ch 1 L */
+ Z180_BCR1H, /* 2f DMA byte count register ch 1 H */
+ Z180_DSTAT, /* 30 DMA status register */
+ Z180_DMODE, /* 31 DMA mode register */
+ Z180_DCNTL, /* 32 DMA/WAIT control register */
+ Z180_IL, /* 33 INT vector low register */
+ Z180_ITC, /* 34 INT/TRAP control register */
+ Z180_IO35, /* 35 reserved */
+ Z180_RCR, /* 36 refresh control register */
+ Z180_IO37, /* 37 reserved */
+ Z180_CBR, /* 38 MMU common base register */
+ Z180_BBR, /* 39 MMU bank base register */
+ Z180_CBAR, /* 3a MMU common/bank area register */
+ Z180_IO3B, /* 3b reserved */
+ Z180_IO3C, /* 3c reserved */
+ Z180_IO3D, /* 3d reserved */
+ Z180_OMCR, /* 3e operation mode control register */
+ Z180_IOCR, /* 3f I/O control register */
+ Z180_IOLINES, /* read/write I/O lines */
+
+ Z180_GENPC = STATE_GENPC,
+ Z180_GENSP = STATE_GENSP,
+ Z180_GENPCBASE = STATE_GENPCBASE
+};
+
+enum
+{
+ Z180_TABLE_op,
+ Z180_TABLE_cb,
+ Z180_TABLE_ed,
+ Z180_TABLE_xy,
+ Z180_TABLE_xycb,
+ Z180_TABLE_ex /* cycles counts for taken jr/jp/call and interrupt latency (rst opcodes) */
+};
+
+enum
+{
+ CPUINFO_PTR_Z180_CYCLE_TABLE = CPUINFO_PTR_CPU_SPECIFIC,
+ CPUINFO_PTR_Z180_CYCLE_TABLE_LAST = CPUINFO_PTR_Z180_CYCLE_TABLE + Z180_TABLE_ex
+};
+
+
+#define Z180_IRQ0 0 /* Execute IRQ1 */
+#define Z180_IRQ1 1 /* Execute IRQ1 */
+#define Z180_IRQ2 2 /* Execute IRQ2 */
+
+
+#ifdef UNUSED_DEFINITION
+/* MMU mapped memory lookup */
+extern UINT8 z180_readmem(device_t *device, offs_t offset);
+extern void z180_writemem(device_t *device, offs_t offset, UINT8 data);
+#endif
+
+DECLARE_LEGACY_CPU_DEVICE(Z180, z180);
+
+CPU_DISASSEMBLE( z180 );
+
+#endif /* __Z180_H__ */
diff --git a/trunk/src/emu/cpu/z180/z180cb.c b/trunk/src/emu/cpu/z180/z180cb.c
new file mode 100644
index 00000000000..6c24c6971e5
--- /dev/null
+++ b/trunk/src/emu/cpu/z180/z180cb.c
@@ -0,0 +1,293 @@
+/**********************************************************
+ * opcodes with CB prefix
+ * rotate, shift and bit operations
+ **********************************************************/
+OP(cb,00) { cpustate->_B = RLC(cpustate, cpustate->_B); } /* RLC B */
+OP(cb,01) { cpustate->_C = RLC(cpustate, cpustate->_C); } /* RLC C */
+OP(cb,02) { cpustate->_D = RLC(cpustate, cpustate->_D); } /* RLC D */
+OP(cb,03) { cpustate->_E = RLC(cpustate, cpustate->_E); } /* RLC E */
+OP(cb,04) { cpustate->_H = RLC(cpustate, cpustate->_H); } /* RLC H */
+OP(cb,05) { cpustate->_L = RLC(cpustate, cpustate->_L); } /* RLC L */
+OP(cb,06) { WM(cpustate, cpustate->_HL, RLC(cpustate, RM(cpustate, cpustate->_HL)) ); } /* RLC (HL) */
+OP(cb,07) { cpustate->_A = RLC(cpustate, cpustate->_A); } /* RLC A */
+
+OP(cb,08) { cpustate->_B = RRC(cpustate, cpustate->_B); } /* RRC B */
+OP(cb,09) { cpustate->_C = RRC(cpustate, cpustate->_C); } /* RRC C */
+OP(cb,0a) { cpustate->_D = RRC(cpustate, cpustate->_D); } /* RRC D */
+OP(cb,0b) { cpustate->_E = RRC(cpustate, cpustate->_E); } /* RRC E */
+OP(cb,0c) { cpustate->_H = RRC(cpustate, cpustate->_H); } /* RRC H */
+OP(cb,0d) { cpustate->_L = RRC(cpustate, cpustate->_L); } /* RRC L */
+OP(cb,0e) { WM(cpustate, cpustate->_HL, RRC(cpustate, RM(cpustate, cpustate->_HL)) ); } /* RRC (HL) */
+OP(cb,0f) { cpustate->_A = RRC(cpustate, cpustate->_A); } /* RRC A */
+
+OP(cb,10) { cpustate->_B = RL(cpustate, cpustate->_B); } /* RL B */
+OP(cb,11) { cpustate->_C = RL(cpustate, cpustate->_C); } /* RL C */
+OP(cb,12) { cpustate->_D = RL(cpustate, cpustate->_D); } /* RL D */
+OP(cb,13) { cpustate->_E = RL(cpustate, cpustate->_E); } /* RL E */
+OP(cb,14) { cpustate->_H = RL(cpustate, cpustate->_H); } /* RL H */
+OP(cb,15) { cpustate->_L = RL(cpustate, cpustate->_L); } /* RL L */
+OP(cb,16) { WM(cpustate, cpustate->_HL, RL(cpustate, RM(cpustate, cpustate->_HL)) ); } /* RL (HL) */
+OP(cb,17) { cpustate->_A = RL(cpustate, cpustate->_A); } /* RL A */
+
+OP(cb,18) { cpustate->_B = RR(cpustate, cpustate->_B); } /* RR B */
+OP(cb,19) { cpustate->_C = RR(cpustate, cpustate->_C); } /* RR C */
+OP(cb,1a) { cpustate->_D = RR(cpustate, cpustate->_D); } /* RR D */
+OP(cb,1b) { cpustate->_E = RR(cpustate, cpustate->_E); } /* RR E */
+OP(cb,1c) { cpustate->_H = RR(cpustate, cpustate->_H); } /* RR H */
+OP(cb,1d) { cpustate->_L = RR(cpustate, cpustate->_L); } /* RR L */
+OP(cb,1e) { WM(cpustate, cpustate->_HL, RR(cpustate, RM(cpustate, cpustate->_HL)) ); } /* RR (HL) */
+OP(cb,1f) { cpustate->_A = RR(cpustate, cpustate->_A); } /* RR A */
+
+OP(cb,20) { cpustate->_B = SLA(cpustate, cpustate->_B); } /* SLA B */
+OP(cb,21) { cpustate->_C = SLA(cpustate, cpustate->_C); } /* SLA C */
+OP(cb,22) { cpustate->_D = SLA(cpustate, cpustate->_D); } /* SLA D */
+OP(cb,23) { cpustate->_E = SLA(cpustate, cpustate->_E); } /* SLA E */
+OP(cb,24) { cpustate->_H = SLA(cpustate, cpustate->_H); } /* SLA H */
+OP(cb,25) { cpustate->_L = SLA(cpustate, cpustate->_L); } /* SLA L */
+OP(cb,26) { WM(cpustate, cpustate->_HL, SLA(cpustate, RM(cpustate, cpustate->_HL)) ); } /* SLA (HL) */
+OP(cb,27) { cpustate->_A = SLA(cpustate, cpustate->_A); } /* SLA A */
+
+OP(cb,28) { cpustate->_B = SRA(cpustate, cpustate->_B); } /* SRA B */
+OP(cb,29) { cpustate->_C = SRA(cpustate, cpustate->_C); } /* SRA C */
+OP(cb,2a) { cpustate->_D = SRA(cpustate, cpustate->_D); } /* SRA D */
+OP(cb,2b) { cpustate->_E = SRA(cpustate, cpustate->_E); } /* SRA E */
+OP(cb,2c) { cpustate->_H = SRA(cpustate, cpustate->_H); } /* SRA H */
+OP(cb,2d) { cpustate->_L = SRA(cpustate, cpustate->_L); } /* SRA L */
+OP(cb,2e) { WM(cpustate, cpustate->_HL, SRA(cpustate, RM(cpustate, cpustate->_HL)) ); } /* SRA (HL) */
+OP(cb,2f) { cpustate->_A = SRA(cpustate, cpustate->_A); } /* SRA A */
+
+OP(cb,30) { cpustate->_B = SLL(cpustate, cpustate->_B); } /* SLL B */
+OP(cb,31) { cpustate->_C = SLL(cpustate, cpustate->_C); } /* SLL C */
+OP(cb,32) { cpustate->_D = SLL(cpustate, cpustate->_D); } /* SLL D */
+OP(cb,33) { cpustate->_E = SLL(cpustate, cpustate->_E); } /* SLL E */
+OP(cb,34) { cpustate->_H = SLL(cpustate, cpustate->_H); } /* SLL H */
+OP(cb,35) { cpustate->_L = SLL(cpustate, cpustate->_L); } /* SLL L */
+OP(cb,36) { WM(cpustate, cpustate->_HL, SLL(cpustate, RM(cpustate, cpustate->_HL)) ); } /* SLL (HL) */
+OP(cb,37) { cpustate->_A = SLL(cpustate, cpustate->_A); } /* SLL A */
+
+OP(cb,38) { cpustate->_B = SRL(cpustate, cpustate->_B); } /* SRL B */
+OP(cb,39) { cpustate->_C = SRL(cpustate, cpustate->_C); } /* SRL C */
+OP(cb,3a) { cpustate->_D = SRL(cpustate, cpustate->_D); } /* SRL D */
+OP(cb,3b) { cpustate->_E = SRL(cpustate, cpustate->_E); } /* SRL E */
+OP(cb,3c) { cpustate->_H = SRL(cpustate, cpustate->_H); } /* SRL H */
+OP(cb,3d) { cpustate->_L = SRL(cpustate, cpustate->_L); } /* SRL L */
+OP(cb,3e) { WM(cpustate, cpustate->_HL, SRL(cpustate, RM(cpustate, cpustate->_HL)) ); } /* SRL (HL) */
+OP(cb,3f) { cpustate->_A = SRL(cpustate, cpustate->_A); } /* SRL A */
+
+OP(cb,40) { BIT(0,cpustate->_B); } /* BIT 0,B */
+OP(cb,41) { BIT(0,cpustate->_C); } /* BIT 0,C */
+OP(cb,42) { BIT(0,cpustate->_D); } /* BIT 0,D */
+OP(cb,43) { BIT(0,cpustate->_E); } /* BIT 0,E */
+OP(cb,44) { BIT(0,cpustate->_H); } /* BIT 0,H */
+OP(cb,45) { BIT(0,cpustate->_L); } /* BIT 0,L */
+OP(cb,46) { BIT(0,RM(cpustate, cpustate->_HL)); } /* BIT 0,(HL) */
+OP(cb,47) { BIT(0,cpustate->_A); } /* BIT 0,A */
+
+OP(cb,48) { BIT(1,cpustate->_B); } /* BIT 1,B */
+OP(cb,49) { BIT(1,cpustate->_C); } /* BIT 1,C */
+OP(cb,4a) { BIT(1,cpustate->_D); } /* BIT 1,D */
+OP(cb,4b) { BIT(1,cpustate->_E); } /* BIT 1,E */
+OP(cb,4c) { BIT(1,cpustate->_H); } /* BIT 1,H */
+OP(cb,4d) { BIT(1,cpustate->_L); } /* BIT 1,L */
+OP(cb,4e) { BIT(1,RM(cpustate, cpustate->_HL)); } /* BIT 1,(HL) */
+OP(cb,4f) { BIT(1,cpustate->_A); } /* BIT 1,A */
+
+OP(cb,50) { BIT(2,cpustate->_B); } /* BIT 2,B */
+OP(cb,51) { BIT(2,cpustate->_C); } /* BIT 2,C */
+OP(cb,52) { BIT(2,cpustate->_D); } /* BIT 2,D */
+OP(cb,53) { BIT(2,cpustate->_E); } /* BIT 2,E */
+OP(cb,54) { BIT(2,cpustate->_H); } /* BIT 2,H */
+OP(cb,55) { BIT(2,cpustate->_L); } /* BIT 2,L */
+OP(cb,56) { BIT(2,RM(cpustate, cpustate->_HL)); } /* BIT 2,(HL) */
+OP(cb,57) { BIT(2,cpustate->_A); } /* BIT 2,A */
+
+OP(cb,58) { BIT(3,cpustate->_B); } /* BIT 3,B */
+OP(cb,59) { BIT(3,cpustate->_C); } /* BIT 3,C */
+OP(cb,5a) { BIT(3,cpustate->_D); } /* BIT 3,D */
+OP(cb,5b) { BIT(3,cpustate->_E); } /* BIT 3,E */
+OP(cb,5c) { BIT(3,cpustate->_H); } /* BIT 3,H */
+OP(cb,5d) { BIT(3,cpustate->_L); } /* BIT 3,L */
+OP(cb,5e) { BIT(3,RM(cpustate, cpustate->_HL)); } /* BIT 3,(HL) */
+OP(cb,5f) { BIT(3,cpustate->_A); } /* BIT 3,A */
+
+OP(cb,60) { BIT(4,cpustate->_B); } /* BIT 4,B */
+OP(cb,61) { BIT(4,cpustate->_C); } /* BIT 4,C */
+OP(cb,62) { BIT(4,cpustate->_D); } /* BIT 4,D */
+OP(cb,63) { BIT(4,cpustate->_E); } /* BIT 4,E */
+OP(cb,64) { BIT(4,cpustate->_H); } /* BIT 4,H */
+OP(cb,65) { BIT(4,cpustate->_L); } /* BIT 4,L */
+OP(cb,66) { BIT(4,RM(cpustate, cpustate->_HL)); } /* BIT 4,(HL) */
+OP(cb,67) { BIT(4,cpustate->_A); } /* BIT 4,A */
+
+OP(cb,68) { BIT(5,cpustate->_B); } /* BIT 5,B */
+OP(cb,69) { BIT(5,cpustate->_C); } /* BIT 5,C */
+OP(cb,6a) { BIT(5,cpustate->_D); } /* BIT 5,D */
+OP(cb,6b) { BIT(5,cpustate->_E); } /* BIT 5,E */
+OP(cb,6c) { BIT(5,cpustate->_H); } /* BIT 5,H */
+OP(cb,6d) { BIT(5,cpustate->_L); } /* BIT 5,L */
+OP(cb,6e) { BIT(5,RM(cpustate, cpustate->_HL)); } /* BIT 5,(HL) */
+OP(cb,6f) { BIT(5,cpustate->_A); } /* BIT 5,A */
+
+OP(cb,70) { BIT(6,cpustate->_B); } /* BIT 6,B */
+OP(cb,71) { BIT(6,cpustate->_C); } /* BIT 6,C */
+OP(cb,72) { BIT(6,cpustate->_D); } /* BIT 6,D */
+OP(cb,73) { BIT(6,cpustate->_E); } /* BIT 6,E */
+OP(cb,74) { BIT(6,cpustate->_H); } /* BIT 6,H */
+OP(cb,75) { BIT(6,cpustate->_L); } /* BIT 6,L */
+OP(cb,76) { BIT(6,RM(cpustate, cpustate->_HL)); } /* BIT 6,(HL) */
+OP(cb,77) { BIT(6,cpustate->_A); } /* BIT 6,A */
+
+OP(cb,78) { BIT(7,cpustate->_B); } /* BIT 7,B */
+OP(cb,79) { BIT(7,cpustate->_C); } /* BIT 7,C */
+OP(cb,7a) { BIT(7,cpustate->_D); } /* BIT 7,D */
+OP(cb,7b) { BIT(7,cpustate->_E); } /* BIT 7,E */
+OP(cb,7c) { BIT(7,cpustate->_H); } /* BIT 7,H */
+OP(cb,7d) { BIT(7,cpustate->_L); } /* BIT 7,L */
+OP(cb,7e) { BIT(7,RM(cpustate, cpustate->_HL)); } /* BIT 7,(HL) */
+OP(cb,7f) { BIT(7,cpustate->_A); } /* BIT 7,A */
+
+OP(cb,80) { cpustate->_B = RES(0,cpustate->_B); } /* RES 0,B */
+OP(cb,81) { cpustate->_C = RES(0,cpustate->_C); } /* RES 0,C */
+OP(cb,82) { cpustate->_D = RES(0,cpustate->_D); } /* RES 0,D */
+OP(cb,83) { cpustate->_E = RES(0,cpustate->_E); } /* RES 0,E */
+OP(cb,84) { cpustate->_H = RES(0,cpustate->_H); } /* RES 0,H */
+OP(cb,85) { cpustate->_L = RES(0,cpustate->_L); } /* RES 0,L */
+OP(cb,86) { WM(cpustate, cpustate->_HL, RES(0,RM(cpustate, cpustate->_HL)) ); } /* RES 0,(HL) */
+OP(cb,87) { cpustate->_A = RES(0,cpustate->_A); } /* RES 0,A */
+
+OP(cb,88) { cpustate->_B = RES(1,cpustate->_B); } /* RES 1,B */
+OP(cb,89) { cpustate->_C = RES(1,cpustate->_C); } /* RES 1,C */
+OP(cb,8a) { cpustate->_D = RES(1,cpustate->_D); } /* RES 1,D */
+OP(cb,8b) { cpustate->_E = RES(1,cpustate->_E); } /* RES 1,E */
+OP(cb,8c) { cpustate->_H = RES(1,cpustate->_H); } /* RES 1,H */
+OP(cb,8d) { cpustate->_L = RES(1,cpustate->_L); } /* RES 1,L */
+OP(cb,8e) { WM(cpustate, cpustate->_HL, RES(1,RM(cpustate, cpustate->_HL)) ); } /* RES 1,(HL) */
+OP(cb,8f) { cpustate->_A = RES(1,cpustate->_A); } /* RES 1,A */
+
+OP(cb,90) { cpustate->_B = RES(2,cpustate->_B); } /* RES 2,B */
+OP(cb,91) { cpustate->_C = RES(2,cpustate->_C); } /* RES 2,C */
+OP(cb,92) { cpustate->_D = RES(2,cpustate->_D); } /* RES 2,D */
+OP(cb,93) { cpustate->_E = RES(2,cpustate->_E); } /* RES 2,E */
+OP(cb,94) { cpustate->_H = RES(2,cpustate->_H); } /* RES 2,H */
+OP(cb,95) { cpustate->_L = RES(2,cpustate->_L); } /* RES 2,L */
+OP(cb,96) { WM(cpustate, cpustate->_HL, RES(2,RM(cpustate, cpustate->_HL)) ); } /* RES 2,(HL) */
+OP(cb,97) { cpustate->_A = RES(2,cpustate->_A); } /* RES 2,A */
+
+OP(cb,98) { cpustate->_B = RES(3,cpustate->_B); } /* RES 3,B */
+OP(cb,99) { cpustate->_C = RES(3,cpustate->_C); } /* RES 3,C */
+OP(cb,9a) { cpustate->_D = RES(3,cpustate->_D); } /* RES 3,D */
+OP(cb,9b) { cpustate->_E = RES(3,cpustate->_E); } /* RES 3,E */
+OP(cb,9c) { cpustate->_H = RES(3,cpustate->_H); } /* RES 3,H */
+OP(cb,9d) { cpustate->_L = RES(3,cpustate->_L); } /* RES 3,L */
+OP(cb,9e) { WM(cpustate, cpustate->_HL, RES(3,RM(cpustate, cpustate->_HL)) ); } /* RES 3,(HL) */
+OP(cb,9f) { cpustate->_A = RES(3,cpustate->_A); } /* RES 3,A */
+
+OP(cb,a0) { cpustate->_B = RES(4,cpustate->_B); } /* RES 4,B */
+OP(cb,a1) { cpustate->_C = RES(4,cpustate->_C); } /* RES 4,C */
+OP(cb,a2) { cpustate->_D = RES(4,cpustate->_D); } /* RES 4,D */
+OP(cb,a3) { cpustate->_E = RES(4,cpustate->_E); } /* RES 4,E */
+OP(cb,a4) { cpustate->_H = RES(4,cpustate->_H); } /* RES 4,H */
+OP(cb,a5) { cpustate->_L = RES(4,cpustate->_L); } /* RES 4,L */
+OP(cb,a6) { WM(cpustate, cpustate->_HL, RES(4,RM(cpustate, cpustate->_HL)) ); } /* RES 4,(HL) */
+OP(cb,a7) { cpustate->_A = RES(4,cpustate->_A); } /* RES 4,A */
+
+OP(cb,a8) { cpustate->_B = RES(5,cpustate->_B); } /* RES 5,B */
+OP(cb,a9) { cpustate->_C = RES(5,cpustate->_C); } /* RES 5,C */
+OP(cb,aa) { cpustate->_D = RES(5,cpustate->_D); } /* RES 5,D */
+OP(cb,ab) { cpustate->_E = RES(5,cpustate->_E); } /* RES 5,E */
+OP(cb,ac) { cpustate->_H = RES(5,cpustate->_H); } /* RES 5,H */
+OP(cb,ad) { cpustate->_L = RES(5,cpustate->_L); } /* RES 5,L */
+OP(cb,ae) { WM(cpustate, cpustate->_HL, RES(5,RM(cpustate, cpustate->_HL)) ); } /* RES 5,(HL) */
+OP(cb,af) { cpustate->_A = RES(5,cpustate->_A); } /* RES 5,A */
+
+OP(cb,b0) { cpustate->_B = RES(6,cpustate->_B); } /* RES 6,B */
+OP(cb,b1) { cpustate->_C = RES(6,cpustate->_C); } /* RES 6,C */
+OP(cb,b2) { cpustate->_D = RES(6,cpustate->_D); } /* RES 6,D */
+OP(cb,b3) { cpustate->_E = RES(6,cpustate->_E); } /* RES 6,E */
+OP(cb,b4) { cpustate->_H = RES(6,cpustate->_H); } /* RES 6,H */
+OP(cb,b5) { cpustate->_L = RES(6,cpustate->_L); } /* RES 6,L */
+OP(cb,b6) { WM(cpustate, cpustate->_HL, RES(6,RM(cpustate, cpustate->_HL)) ); } /* RES 6,(HL) */
+OP(cb,b7) { cpustate->_A = RES(6,cpustate->_A); } /* RES 6,A */
+
+OP(cb,b8) { cpustate->_B = RES(7,cpustate->_B); } /* RES 7,B */
+OP(cb,b9) { cpustate->_C = RES(7,cpustate->_C); } /* RES 7,C */
+OP(cb,ba) { cpustate->_D = RES(7,cpustate->_D); } /* RES 7,D */
+OP(cb,bb) { cpustate->_E = RES(7,cpustate->_E); } /* RES 7,E */
+OP(cb,bc) { cpustate->_H = RES(7,cpustate->_H); } /* RES 7,H */
+OP(cb,bd) { cpustate->_L = RES(7,cpustate->_L); } /* RES 7,L */
+OP(cb,be) { WM(cpustate, cpustate->_HL, RES(7,RM(cpustate, cpustate->_HL)) ); } /* RES 7,(HL) */
+OP(cb,bf) { cpustate->_A = RES(7,cpustate->_A); } /* RES 7,A */
+
+OP(cb,c0) { cpustate->_B = SET(0,cpustate->_B); } /* SET 0,B */
+OP(cb,c1) { cpustate->_C = SET(0,cpustate->_C); } /* SET 0,C */
+OP(cb,c2) { cpustate->_D = SET(0,cpustate->_D); } /* SET 0,D */
+OP(cb,c3) { cpustate->_E = SET(0,cpustate->_E); } /* SET 0,E */
+OP(cb,c4) { cpustate->_H = SET(0,cpustate->_H); } /* SET 0,H */
+OP(cb,c5) { cpustate->_L = SET(0,cpustate->_L); } /* SET 0,L */
+OP(cb,c6) { WM(cpustate, cpustate->_HL, SET(0,RM(cpustate, cpustate->_HL)) ); } /* SET 0,(HL) */
+OP(cb,c7) { cpustate->_A = SET(0,cpustate->_A); } /* SET 0,A */
+
+OP(cb,c8) { cpustate->_B = SET(1,cpustate->_B); } /* SET 1,B */
+OP(cb,c9) { cpustate->_C = SET(1,cpustate->_C); } /* SET 1,C */
+OP(cb,ca) { cpustate->_D = SET(1,cpustate->_D); } /* SET 1,D */
+OP(cb,cb) { cpustate->_E = SET(1,cpustate->_E); } /* SET 1,E */
+OP(cb,cc) { cpustate->_H = SET(1,cpustate->_H); } /* SET 1,H */
+OP(cb,cd) { cpustate->_L = SET(1,cpustate->_L); } /* SET 1,L */
+OP(cb,ce) { WM(cpustate, cpustate->_HL, SET(1,RM(cpustate, cpustate->_HL)) ); } /* SET 1,(HL) */
+OP(cb,cf) { cpustate->_A = SET(1,cpustate->_A); } /* SET 1,A */
+
+OP(cb,d0) { cpustate->_B = SET(2,cpustate->_B); } /* SET 2,B */
+OP(cb,d1) { cpustate->_C = SET(2,cpustate->_C); } /* SET 2,C */
+OP(cb,d2) { cpustate->_D = SET(2,cpustate->_D); } /* SET 2,D */
+OP(cb,d3) { cpustate->_E = SET(2,cpustate->_E); } /* SET 2,E */
+OP(cb,d4) { cpustate->_H = SET(2,cpustate->_H); } /* SET 2,H */
+OP(cb,d5) { cpustate->_L = SET(2,cpustate->_L); } /* SET 2,L */
+OP(cb,d6) { WM(cpustate, cpustate->_HL, SET(2,RM(cpustate, cpustate->_HL)) ); }/* SET 2,(HL) */
+OP(cb,d7) { cpustate->_A = SET(2,cpustate->_A); } /* SET 2,A */
+
+OP(cb,d8) { cpustate->_B = SET(3,cpustate->_B); } /* SET 3,B */
+OP(cb,d9) { cpustate->_C = SET(3,cpustate->_C); } /* SET 3,C */
+OP(cb,da) { cpustate->_D = SET(3,cpustate->_D); } /* SET 3,D */
+OP(cb,db) { cpustate->_E = SET(3,cpustate->_E); } /* SET 3,E */
+OP(cb,dc) { cpustate->_H = SET(3,cpustate->_H); } /* SET 3,H */
+OP(cb,dd) { cpustate->_L = SET(3,cpustate->_L); } /* SET 3,L */
+OP(cb,de) { WM(cpustate, cpustate->_HL, SET(3,RM(cpustate, cpustate->_HL)) ); } /* SET 3,(HL) */
+OP(cb,df) { cpustate->_A = SET(3,cpustate->_A); } /* SET 3,A */
+
+OP(cb,e0) { cpustate->_B = SET(4,cpustate->_B); } /* SET 4,B */
+OP(cb,e1) { cpustate->_C = SET(4,cpustate->_C); } /* SET 4,C */
+OP(cb,e2) { cpustate->_D = SET(4,cpustate->_D); } /* SET 4,D */
+OP(cb,e3) { cpustate->_E = SET(4,cpustate->_E); } /* SET 4,E */
+OP(cb,e4) { cpustate->_H = SET(4,cpustate->_H); } /* SET 4,H */
+OP(cb,e5) { cpustate->_L = SET(4,cpustate->_L); } /* SET 4,L */
+OP(cb,e6) { WM(cpustate, cpustate->_HL, SET(4,RM(cpustate, cpustate->_HL)) ); } /* SET 4,(HL) */
+OP(cb,e7) { cpustate->_A = SET(4,cpustate->_A); } /* SET 4,A */
+
+OP(cb,e8) { cpustate->_B = SET(5,cpustate->_B); } /* SET 5,B */
+OP(cb,e9) { cpustate->_C = SET(5,cpustate->_C); } /* SET 5,C */
+OP(cb,ea) { cpustate->_D = SET(5,cpustate->_D); } /* SET 5,D */
+OP(cb,eb) { cpustate->_E = SET(5,cpustate->_E); } /* SET 5,E */
+OP(cb,ec) { cpustate->_H = SET(5,cpustate->_H); } /* SET 5,H */
+OP(cb,ed) { cpustate->_L = SET(5,cpustate->_L); } /* SET 5,L */
+OP(cb,ee) { WM(cpustate, cpustate->_HL, SET(5,RM(cpustate, cpustate->_HL)) ); } /* SET 5,(HL) */
+OP(cb,ef) { cpustate->_A = SET(5,cpustate->_A); } /* SET 5,A */
+
+OP(cb,f0) { cpustate->_B = SET(6,cpustate->_B); } /* SET 6,B */
+OP(cb,f1) { cpustate->_C = SET(6,cpustate->_C); } /* SET 6,C */
+OP(cb,f2) { cpustate->_D = SET(6,cpustate->_D); } /* SET 6,D */
+OP(cb,f3) { cpustate->_E = SET(6,cpustate->_E); } /* SET 6,E */
+OP(cb,f4) { cpustate->_H = SET(6,cpustate->_H); } /* SET 6,H */
+OP(cb,f5) { cpustate->_L = SET(6,cpustate->_L); } /* SET 6,L */
+OP(cb,f6) { WM(cpustate, cpustate->_HL, SET(6,RM(cpustate, cpustate->_HL)) ); } /* SET 6,(HL) */
+OP(cb,f7) { cpustate->_A = SET(6,cpustate->_A); } /* SET 6,A */
+
+OP(cb,f8) { cpustate->_B = SET(7,cpustate->_B); } /* SET 7,B */
+OP(cb,f9) { cpustate->_C = SET(7,cpustate->_C); } /* SET 7,C */
+OP(cb,fa) { cpustate->_D = SET(7,cpustate->_D); } /* SET 7,D */
+OP(cb,fb) { cpustate->_E = SET(7,cpustate->_E); } /* SET 7,E */
+OP(cb,fc) { cpustate->_H = SET(7,cpustate->_H); } /* SET 7,H */
+OP(cb,fd) { cpustate->_L = SET(7,cpustate->_L); } /* SET 7,L */
+OP(cb,fe) { WM(cpustate, cpustate->_HL, SET(7,RM(cpustate, cpustate->_HL)) ); } /* SET 7,(HL) */
+OP(cb,ff) { cpustate->_A = SET(7,cpustate->_A); } /* SET 7,A */
+
+
diff --git a/trunk/src/emu/cpu/z180/z180dasm.c b/trunk/src/emu/cpu/z180/z180dasm.c
new file mode 100644
index 00000000000..a772bb0e2cf
--- /dev/null
+++ b/trunk/src/emu/cpu/z180/z180dasm.c
@@ -0,0 +1,554 @@
+/*****************************************************************************
+ *
+ * z180dasm.c
+ * Portable Z8x180 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"
+#include "debugger.h"
+#include "z180.h"
+
+enum e_mnemonics {
+ zADC ,zADD ,zAND ,zBIT ,zCALL ,zCCF ,zCP ,zCPD ,
+ zCPDR ,zCPI ,zCPIR ,zCPL ,zDAA ,zDB ,zDEC ,zDI ,
+ zDJNZ ,zEI ,zEX ,zEXX ,zHLT ,zIM ,zIN ,zIN0 ,
+ zINC ,zIND ,zINDR ,zINI ,zINIR ,zJP ,zJR ,zLD ,
+ zLDD ,zLDDR ,zLDI ,zLDIR ,zMLT ,zNEG ,zNOP ,zOR ,
+ zOTDM ,zOTDMR ,zOTDR ,zOTIM ,zOTIMR ,zOTIR ,zOUT ,zOUT0 ,
+ zOUTD ,zOUTI ,zPOP ,zPUSH ,zRES ,zRET ,zRETI ,zRETN ,
+ zRL ,zRLA ,zRLC ,zRLCA ,zRLD ,zRR ,zRRA ,zRRC ,
+ zRRCA ,zRRD ,zRST ,zSBC ,zSCF ,zSET ,zSLA ,zSLL ,
+ zSLP ,zSRA ,zSRL ,zSUB ,zTST ,zTSTIO ,zXOR
+};
+
+static const char *const s_mnemonic[] = {
+ "adc" ,"add" ,"and" ,"bit" ,"call" ,"ccf" ,"cp" ,"cpd" ,
+ "cpdr" ,"cpi" ,"cpir" ,"cpl" ,"daa" ,"db" ,"dec" ,"di" ,
+ "djnz" ,"ei" ,"ex" ,"exx" ,"halt" ,"im" ,"in" ,"in0" ,
+ "inc" ,"ind" ,"indr" ,"ini" ,"inir" ,"jp" ,"jr" ,"ld" ,
+ "ldd" ,"lddr" ,"ldi" ,"ldir" ,"mlt" ,"neg" ,"nop" ,"or" ,
+ "otdm" ,"otdmr","otdr" ,"otim" ,"otimr","otir" ,"out" ,"out0" ,
+ "outd" ,"outi" ,"pop" ,"push" ,"res" ,"ret" ,"reti" ,"retn" ,
+ "rl" ,"rla" ,"rlc" ,"rlca" ,"rld" ,"rr" ,"rra" ,"rrc" ,
+ "rrca" ,"rrd" ,"rst" ,"sbc" ,"scf" ,"set" ,"sla" ,"sll" ,
+ "slp" ,"sra" ,"srl" ,"sub" ,"tst" ,"tstio","xor "
+};
+
+typedef struct {
+ UINT8 mnemonic;
+ const char *arguments;
+} z80dasm;
+
+static const z80dasm mnemonic_xx_cb[256]= {
+ {zRLC,"b=Y"}, {zRLC,"c=Y"}, {zRLC,"d=Y"}, {zRLC,"e=Y"},
+ {zRLC,"h=Y"}, {zRLC,"l=Y"}, {zRLC,"Y"}, {zRLC,"a=Y"},
+ {zRRC,"b=Y"}, {zRRC,"c=Y"}, {zRRC,"d=Y"}, {zRRC,"e=Y"},
+ {zRRC,"h=Y"}, {zRRC,"l=Y"}, {zRRC,"Y"}, {zRRC,"a=Y"},
+ {zRL,"b=Y"}, {zRL,"c=Y"}, {zRL,"d=Y"}, {zRL,"e=Y"},
+ {zRL,"h=Y"}, {zRL,"l=Y"}, {zRL,"Y"}, {zRL,"a=Y"},
+ {zRR,"b=Y"}, {zRR,"c=Y"}, {zRR,"d=Y"}, {zRR,"e=Y"},
+ {zRR,"h=Y"}, {zRR,"l=Y"}, {zRR,"Y"}, {zRR,"a=Y"},
+ {zSLA,"b=Y"}, {zSLA,"c=Y"}, {zSLA,"d=Y"}, {zSLA,"e=Y"},
+ {zSLA,"h=Y"}, {zSLA,"l=Y"}, {zSLA,"Y"}, {zSLA,"a=Y"},
+ {zSRA,"b=Y"}, {zSRA,"c=Y"}, {zSRA,"d=Y"}, {zSRA,"e=Y"},
+ {zSRA,"h=Y"}, {zSRA,"l=Y"}, {zSRA,"Y"}, {zSRA,"a=Y"},
+ {zSLL,"b=Y"}, {zSLL,"c=Y"}, {zSLL,"d=Y"}, {zSLL,"e=Y"},
+ {zSLL,"h=Y"}, {zSLL,"l=Y"}, {zSLL,"Y"}, {zSLL,"a=Y"},
+ {zSRL,"b=Y"}, {zSRL,"c=Y"}, {zSRL,"d=Y"}, {zSRL,"e=Y"},
+ {zSRL,"h=Y"}, {zSRL,"l=Y"}, {zSRL,"Y"}, {zSRL,"a=Y"},
+ {zBIT,"b=0,Y"}, {zBIT,"c=0,Y"}, {zBIT,"d=0,Y"}, {zBIT,"e=0,Y"},
+ {zBIT,"h=0,Y"}, {zBIT,"l=0,Y"}, {zBIT,"0,Y"}, {zBIT,"a=0,Y"},
+ {zBIT,"b=1,Y"}, {zBIT,"c=1,Y"}, {zBIT,"d=1,Y"}, {zBIT,"e=1,Y"},
+ {zBIT,"h=1,Y"}, {zBIT,"l=1,Y"}, {zBIT,"1,Y"}, {zBIT,"a=1,Y"},
+ {zBIT,"b=2,Y"}, {zBIT,"c=2,Y"}, {zBIT,"d=2,Y"}, {zBIT,"e=2,Y"},
+ {zBIT,"h=2,Y"}, {zBIT,"l=2,Y"}, {zBIT,"2,Y"}, {zBIT,"a=2,Y"},
+ {zBIT,"b=3,Y"}, {zBIT,"c=3,Y"}, {zBIT,"d=3,Y"}, {zBIT,"e=3,Y"},
+ {zBIT,"h=3,Y"}, {zBIT,"l=3,Y"}, {zBIT,"3,Y"}, {zBIT,"a=3,Y"},
+ {zBIT,"b=4,Y"}, {zBIT,"c=4,Y"}, {zBIT,"d=4,Y"}, {zBIT,"e=4,Y"},
+ {zBIT,"h=4,Y"}, {zBIT,"l=4,Y"}, {zBIT,"4,Y"}, {zBIT,"a=4,Y"},
+ {zBIT,"b=5,Y"}, {zBIT,"c=5,Y"}, {zBIT,"d=5,Y"}, {zBIT,"e=5,Y"},
+ {zBIT,"h=5,Y"}, {zBIT,"l=5,Y"}, {zBIT,"5,Y"}, {zBIT,"a=5,Y"},
+ {zBIT,"b=6,Y"}, {zBIT,"c=6,Y"}, {zBIT,"d=6,Y"}, {zBIT,"e=6,Y"},
+ {zBIT,"h=6,Y"}, {zBIT,"l=6,Y"}, {zBIT,"6,Y"}, {zBIT,"a=6,Y"},
+ {zBIT,"b=7,Y"}, {zBIT,"c=7,Y"}, {zBIT,"d=7,Y"}, {zBIT,"e=7,Y"},
+ {zBIT,"h=7,Y"}, {zBIT,"l=7,Y"}, {zBIT,"7,Y"}, {zBIT,"a=7,Y"},
+ {zRES,"b=0,Y"}, {zRES,"c=0,Y"}, {zRES,"d=0,Y"}, {zRES,"e=0,Y"},
+ {zRES,"h=0,Y"}, {zRES,"l=0,Y"}, {zRES,"0,Y"}, {zRES,"a=0,Y"},
+ {zRES,"b=1,Y"}, {zRES,"c=1,Y"}, {zRES,"d=1,Y"}, {zRES,"e=1,Y"},
+ {zRES,"h=1,Y"}, {zRES,"l=1,Y"}, {zRES,"1,Y"}, {zRES,"a=1,Y"},
+ {zRES,"b=2,Y"}, {zRES,"c=2,Y"}, {zRES,"d=2,Y"}, {zRES,"e=2,Y"},
+ {zRES,"h=2,Y"}, {zRES,"l=2,Y"}, {zRES,"2,Y"}, {zRES,"a=2,Y"},
+ {zRES,"b=3,Y"}, {zRES,"c=3,Y"}, {zRES,"d=3,Y"}, {zRES,"e=3,Y"},
+ {zRES,"h=3,Y"}, {zRES,"l=3,Y"}, {zRES,"3,Y"}, {zRES,"a=3,Y"},
+ {zRES,"b=4,Y"}, {zRES,"c=4,Y"}, {zRES,"d=4,Y"}, {zRES,"e=4,Y"},
+ {zRES,"h=4,Y"}, {zRES,"l=4,Y"}, {zRES,"4,Y"}, {zRES,"a=4,Y"},
+ {zRES,"b=5,Y"}, {zRES,"c=5,Y"}, {zRES,"d=5,Y"}, {zRES,"e=5,Y"},
+ {zRES,"h=5,Y"}, {zRES,"l=5,Y"}, {zRES,"5,Y"}, {zRES,"a=5,Y"},
+ {zRES,"b=6,Y"}, {zRES,"c=6,Y"}, {zRES,"d=6,Y"}, {zRES,"e=6,Y"},
+ {zRES,"h=6,Y"}, {zRES,"l=6,Y"}, {zRES,"6,Y"}, {zRES,"a=6,Y"},
+ {zRES,"b=7,Y"}, {zRES,"c=7,Y"}, {zRES,"d=7,Y"}, {zRES,"e=7,Y"},
+ {zRES,"h=7,Y"}, {zRES,"l=7,Y"}, {zRES,"7,Y"}, {zRES,"a=7,Y"},
+ {zSET,"b=0,Y"}, {zSET,"c=0,Y"}, {zSET,"d=0,Y"}, {zSET,"e=0,Y"},
+ {zSET,"h=0,Y"}, {zSET,"l=0,Y"}, {zSET,"0,Y"}, {zSET,"a=0,Y"},
+ {zSET,"b=1,Y"}, {zSET,"c=1,Y"}, {zSET,"d=1,Y"}, {zSET,"e=1,Y"},
+ {zSET,"h=1,Y"}, {zSET,"l=1,Y"}, {zSET,"1,Y"}, {zSET,"a=1,Y"},
+ {zSET,"b=2,Y"}, {zSET,"c=2,Y"}, {zSET,"d=2,Y"}, {zSET,"e=2,Y"},
+ {zSET,"h=2,Y"}, {zSET,"l=2,Y"}, {zSET,"2,Y"}, {zSET,"a=2,Y"},
+ {zSET,"b=3,Y"}, {zSET,"c=3,Y"}, {zSET,"d=3,Y"}, {zSET,"e=3,Y"},
+ {zSET,"h=3,Y"}, {zSET,"l=3,Y"}, {zSET,"3,Y"}, {zSET,"a=3,Y"},
+ {zSET,"b=4,Y"}, {zSET,"c=4,Y"}, {zSET,"d=4,Y"}, {zSET,"e=4,Y"},
+ {zSET,"h=4,Y"}, {zSET,"l=4,Y"}, {zSET,"4,Y"}, {zSET,"a=4,Y"},
+ {zSET,"b=5,Y"}, {zSET,"c=5,Y"}, {zSET,"d=5,Y"}, {zSET,"e=5,Y"},
+ {zSET,"h=5,Y"}, {zSET,"l=5,Y"}, {zSET,"5,Y"}, {zSET,"a=5,Y"},
+ {zSET,"b=6,Y"}, {zSET,"c=6,Y"}, {zSET,"d=6,Y"}, {zSET,"e=6,Y"},
+ {zSET,"h=6,Y"}, {zSET,"l=6,Y"}, {zSET,"6,Y"}, {zSET,"a=6,Y"},
+ {zSET,"b=7,Y"}, {zSET,"c=7,Y"}, {zSET,"d=7,Y"}, {zSET,"e=7,Y"},
+ {zSET,"h=7,Y"}, {zSET,"l=7,Y"}, {zSET,"7,Y"}, {zSET,"a=7,Y"}
+};
+
+static const z80dasm 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"},
+ {zSLL,"b"}, {zSLL,"c"}, {zSLL,"d"}, {zSLL,"e"},
+ {zSLL,"h"}, {zSLL,"l"}, {zSLL,"(hl)"}, {zSLL,"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 z80dasm mnemonic_ed[256]= {
+ {zIN0,"b,(B)"}, {zOUT0,"(B),b"},{zDB,"?"}, {zDB,"?"},
+ {zTST,"b"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zIN0,"c,(B)"}, {zOUT0,"(B),c"},{zDB,"?"}, {zDB,"?"},
+ {zTST,"c"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zIN0,"d,(B)"}, {zOUT0,"(B),d"},{zDB,"?"}, {zDB,"?"},
+ {zTST,"d"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zIN0,"e,(B)"}, {zOUT0,"(B),e"},{zDB,"?"}, {zDB,"?"},
+ {zTST,"e"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zIN0,"h,(B)"}, {zOUT0,"(B),h"},{zDB,"?"}, {zDB,"?"},
+ {zTST,"h"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zIN0,"l,(B)"}, {zOUT0,"(B),l"},{zDB,"?"}, {zDB,"?"},
+ {zTST,"l"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zIN0,"f,(B)"}, {zOUT0,"(B),0"},{zDB,"?"}, {zDB,"?"},
+ {zTST,"(hl)"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zIN0,"a,(B)"}, {zOUT0,"(B),a"},{zDB,"?"}, {zDB,"?"},
+ {zTST,"a"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zIN,"b,(c)"}, {zOUT,"(c),b"}, {zSBC,"hl,bc"}, {zLD,"(W),bc"},
+ {zNEG,0}, {zRETN,0}, {zIM,"0"}, {zLD,"i,a"},
+ {zIN,"c,(c)"}, {zOUT,"(c),c"}, {zADC,"hl,bc"}, {zLD,"bc,(W)"},
+ {zMLT,"bc"}, {zRETI,0}, {zIM,"0"}, {zLD,"r,a"},
+ {zIN,"d,(c)"}, {zOUT,"(c),d"}, {zSBC,"hl,de"}, {zLD,"(W),de"},
+ {zNEG,"*"}, {zRETN,0}, {zIM,"1"}, {zLD,"a,i"},
+ {zIN,"e,(c)"}, {zOUT,"(c),e"}, {zADC,"hl,de"}, {zLD,"de,(W)"},
+ {zMLT,"de"}, {zRETI,0}, {zIM,"2"}, {zLD,"a,r"},
+ {zIN,"h,(c)"}, {zOUT,"(c),h"}, {zSBC,"hl,hl"}, {zLD,"(W),hl"},
+ {zTST,"B"}, {zRETN,0}, {zIM,"0"}, {zRRD,"(hl)"},
+ {zIN,"l,(c)"}, {zOUT,"(c),l"}, {zADC,"hl,hl"}, {zLD,"hl,(W)"},
+ {zMLT,"hl"}, {zRETI,0}, {zIM,"0"}, {zRLD,"(hl)"},
+ {zIN,"0,(c)"}, {zOUT,"(c),0"}, {zSBC,"hl,sp"}, {zLD,"(W),sp"},
+ {zTSTIO,"B"}, {zRETN,0}, {zSLP,0}, {zDB,"?"},
+ {zIN,"a,(c)"}, {zOUT,"(c),a"}, {zADC,"hl,sp"}, {zLD,"sp,(W)"},
+ {zMLT,"sp"}, {zRETI,0}, {zIM,"2"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zOTIM,0},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zOTDM,0},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zOTIMR,0},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zOTDMR,0},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zLDI,0}, {zCPI,0}, {zINI,0}, {zOUTI,0},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zLDD,0}, {zCPD,0}, {zIND,0}, {zOUTD,0},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zLDIR,0}, {zCPIR,0}, {zINIR,0}, {zOTIR,0},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zLDDR,0}, {zCPDR,0}, {zINDR,0}, {zOTDR,0},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"}
+};
+
+static const z80dasm mnemonic_xx[256]= {
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zADD,"I,bc"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zADD,"I,de"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zLD,"I,N"}, {zLD,"(W),I"}, {zINC,"I"},
+ {zINC,"Ih"}, {zDEC,"Ih"}, {zLD,"Ih,B"}, {zDB,"?"},
+ {zDB,"?"}, {zADD,"I,I"}, {zLD,"I,(W)"}, {zDEC,"I"},
+ {zINC,"Il"}, {zDEC,"Il"}, {zLD,"Il,B"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zINC,"X"}, {zDEC,"X"}, {zLD,"X,B"}, {zDB,"?"},
+ {zDB,"?"}, {zADD,"I,sp"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zLD,"b,Ih"}, {zLD,"b,Il"}, {zLD,"b,X"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zLD,"c,Ih"}, {zLD,"c,Il"}, {zLD,"c,X"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zLD,"d,Ih"}, {zLD,"d,Il"}, {zLD,"d,X"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zLD,"e,Ih"}, {zLD,"e,Il"}, {zLD,"e,X"}, {zDB,"?"},
+ {zLD,"Ih,b"}, {zLD,"Ih,c"}, {zLD,"Ih,d"}, {zLD,"Ih,e"},
+ {zLD,"Ih,Ih"}, {zLD,"Ih,Il"}, {zLD,"h,X"}, {zLD,"Ih,a"},
+ {zLD,"Il,b"}, {zLD,"Il,c"}, {zLD,"Il,d"}, {zLD,"Il,e"},
+ {zLD,"Il,Ih"}, {zLD,"Il,Il"}, {zLD,"l,X"}, {zLD,"Il,a"},
+ {zLD,"X,b"}, {zLD,"X,c"}, {zLD,"X,d"}, {zLD,"X,e"},
+ {zLD,"X,h"}, {zLD,"X,l"}, {zDB,"?"}, {zLD,"X,a"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zLD,"a,Ih"}, {zLD,"a,Il"}, {zLD,"a,X"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zADD,"a,Ih"}, {zADD,"a,Il"}, {zADD,"a,X"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zADC,"a,Ih"}, {zADC,"a,Il"}, {zADC,"a,X"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zSUB,"Ih"}, {zSUB,"Il"}, {zSUB,"X"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zSBC,"a,Ih"}, {zSBC,"a,Il"}, {zSBC,"a,X"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zAND,"Ih"}, {zAND,"Il"}, {zAND,"X"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zXOR,"Ih"}, {zXOR,"Il"}, {zXOR,"X"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zOR,"Ih"}, {zOR,"Il"}, {zOR,"X"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zCP,"Ih"}, {zCP,"Il"}, {zCP,"X"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"cb"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zPOP,"I"}, {zDB,"?"}, {zEX,"(sp),I"},
+ {zDB,"?"}, {zPUSH,"I"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zJP,"(I)"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zLD,"sp,I"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"}
+};
+
+static const z80dasm mnemonic_main[256]= {
+ {zNOP,0}, {zLD,"bc,N"}, {zLD,"(bc),a"}, {zINC,"bc"},
+ {zINC,"b"}, {zDEC,"b"}, {zLD,"b,B"}, {zRLCA,0},
+ {zEX,"af,af'"}, {zADD,"hl,bc"}, {zLD,"a,(bc)"}, {zDEC,"bc"},
+ {zINC,"c"}, {zDEC,"c"}, {zLD,"c,B"}, {zRRCA,0},
+ {zDJNZ,"O"}, {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,"(W),hl"}, {zINC,"hl"},
+ {zINC,"h"}, {zDEC,"h"}, {zLD,"h,B"}, {zDAA,0},
+ {zJR,"z,O"}, {zADD,"hl,hl"}, {zLD,"hl,(W)"}, {zDEC,"hl"},
+ {zINC,"l"}, {zDEC,"l"}, {zLD,"l,B"}, {zCPL,0},
+ {zJR,"nc,O"}, {zLD,"sp,N"}, {zLD,"(W),a"}, {zINC,"sp"},
+ {zINC,"(hl)"}, {zDEC,"(hl)"}, {zLD,"(hl),B"}, {zSCF,0},
+ {zJR,"c,O"}, {zADD,"hl,sp"}, {zLD,"a,(W)"}, {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"}, {zOUT,"(P),a"},
+ {zCALL,"nc,A"}, {zPUSH,"de"}, {zSUB,"B"}, {zRST,"V"},
+ {zRET,"c"}, {zEXX,0}, {zJP,"c,A"}, {zIN,"a,(P)"},
+ {zCALL,"c,A"}, {zDB,"dd"}, {zSBC,"a,B"}, {zRST,"V"},
+ {zRET,"po"}, {zPOP,"hl"}, {zJP,"po,A"}, {zEX,"(sp),hl"},
+ {zCALL,"po,A"}, {zPUSH,"hl"}, {zAND,"B"}, {zRST,"V"},
+ {zRET,"pe"}, {zJP,"(hl)"}, {zJP,"pe,A"}, {zEX,"de,hl"},
+ {zCALL,"pe,A"}, {zDB,"ed"}, {zXOR,"B"}, {zRST,"V"},
+ {zRET,"p"}, {zPOP,"af"}, {zJP,"p,A"}, {zDI,0},
+ {zCALL,"p,A"}, {zPUSH,"af"}, {zOR,"B"}, {zRST,"V"},
+ {zRET,"m"}, {zLD,"sp,hl"}, {zJP,"m,A"}, {zEI,0},
+ {zCALL,"m,A"}, {zDB,"fd"}, {zCP,"B"}, {zRST,"V"}
+};
+
+static char sign(INT8 offset)
+{
+ return (offset < 0)? '-':'+';
+}
+
+static int offs(INT8 offset)
+{
+ if (offset < 0) return -offset;
+ return offset;
+}
+
+/****************************************************************************
+ * Disassemble opcode at PC and return number of bytes it takes
+ ****************************************************************************/
+CPU_DISASSEMBLE( z180 )
+{
+ const z80dasm *d;
+ const char *src, *ixy;
+ char *dst;
+ unsigned PC = pc;
+ INT8 offset = 0;
+ UINT8 op, op1 = 0;
+ UINT16 ea = 0;
+ int pos = 0;
+ UINT32 flags = 0;
+
+ ixy = "oops!!";
+ dst = buffer;
+
+ op = oprom[pos++];
+
+ switch (op)
+ {
+ case 0xcb:
+ op = oprom[pos++];
+ d = &mnemonic_cb[op];
+ break;
+ case 0xed:
+ op1 = oprom[pos++];
+ d = &mnemonic_ed[op1];
+ break;
+ case 0xdd:
+ ixy = "ix";
+ op1 = oprom[pos++];
+ if( op1 == 0xcb )
+ {
+ offset = (INT8) opram[pos++];
+ op1 = opram[pos++]; /* fourth byte from opbase.ram! */
+ d = &mnemonic_xx_cb[op1];
+ }
+ else d = &mnemonic_xx[op1];
+ break;
+ case 0xfd:
+ ixy = "iy";
+ op1 = oprom[pos++];
+ if( op1 == 0xcb )
+ {
+ offset = (INT8) opram[pos++];
+ op1 = opram[pos++]; /* fourth byte from opbase.ram! */
+ d = &mnemonic_xx_cb[op1];
+ }
+ else d = &mnemonic_xx[op1];
+ break;
+ default:
+ d = &mnemonic_main[op];
+ break;
+ }
+
+ if( d->arguments )
+ {
+ dst += sprintf(dst, "%-5s ", 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 '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, "$%05X", PC + offset + 2 );
+ break;
+ case 'P': /* Port number */
+ ea = opram[pos++];
+ dst += sprintf( dst, "$%02X", ea );
+ 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, "$%05X", ea );
+ break;
+ case 'X':
+ offset = (INT8) opram[pos++];
+ case 'Y':
+ dst += sprintf( dst,"(%s%c$%02x)", ixy, sign(offset), offs(offset) );
+ break;
+ case 'I':
+ dst += sprintf( dst, "%s", ixy);
+ break;
+ default:
+ *dst++ = *src;
+ }
+ src++;
+ }
+ *dst = '\0';
+ }
+ else
+ {
+ dst += sprintf(dst, "%s", s_mnemonic[d->mnemonic]);
+ }
+
+ if (d->mnemonic == zCALL || d->mnemonic == zCPDR || d->mnemonic == zCPIR || d->mnemonic == zDJNZ ||
+ d->mnemonic == zHLT || d->mnemonic == zINDR || d->mnemonic == zINIR || d->mnemonic == zLDDR ||
+ d->mnemonic == zLDIR || d->mnemonic == zOTDR || d->mnemonic == zOTIR || d->mnemonic == zRST)
+ flags = DASMFLAG_STEP_OVER;
+ else if (d->mnemonic == zRETN || d->mnemonic == zRET || d->mnemonic == zRETI)
+ flags = DASMFLAG_STEP_OUT;
+
+ return pos | flags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/z180/z180dd.c b/trunk/src/emu/cpu/z180/z180dd.c
new file mode 100644
index 00000000000..dd7a4c0a7ec
--- /dev/null
+++ b/trunk/src/emu/cpu/z180/z180dd.c
@@ -0,0 +1,296 @@
+OP(illegal,1) {
+ logerror("Z180 '%s' ill. opcode $%02x $%02x\n",
+ cpustate->device->tag(), cpustate->direct->read_decrypted_byte((cpustate->_PCD-1)&0xffff), cpustate->direct->read_decrypted_byte(cpustate->_PCD));
+}
+
+/**********************************************************
+ * IX register related opcodes (DD prefix)
+ **********************************************************/
+OP(dd,00) { illegal_1(cpustate); op_00(cpustate); } /* DB DD */
+OP(dd,01) { illegal_1(cpustate); op_01(cpustate); } /* DB DD */
+OP(dd,02) { illegal_1(cpustate); op_02(cpustate); } /* DB DD */
+OP(dd,03) { illegal_1(cpustate); op_03(cpustate); } /* DB DD */
+OP(dd,04) { illegal_1(cpustate); op_04(cpustate); } /* DB DD */
+OP(dd,05) { illegal_1(cpustate); op_05(cpustate); } /* DB DD */
+OP(dd,06) { illegal_1(cpustate); op_06(cpustate); } /* DB DD */
+OP(dd,07) { illegal_1(cpustate); op_07(cpustate); } /* DB DD */
+
+OP(dd,08) { illegal_1(cpustate); op_08(cpustate); } /* DB DD */
+OP(dd,09) { cpustate->R++; ADD16(IX,BC); } /* ADD IX,BC */
+OP(dd,0a) { illegal_1(cpustate); op_0a(cpustate); } /* DB DD */
+OP(dd,0b) { illegal_1(cpustate); op_0b(cpustate); } /* DB DD */
+OP(dd,0c) { illegal_1(cpustate); op_0c(cpustate); } /* DB DD */
+OP(dd,0d) { illegal_1(cpustate); op_0d(cpustate); } /* DB DD */
+OP(dd,0e) { illegal_1(cpustate); op_0e(cpustate); } /* DB DD */
+OP(dd,0f) { illegal_1(cpustate); op_0f(cpustate); } /* DB DD */
+
+OP(dd,10) { illegal_1(cpustate); op_10(cpustate); } /* DB DD */
+OP(dd,11) { illegal_1(cpustate); op_11(cpustate); } /* DB DD */
+OP(dd,12) { illegal_1(cpustate); op_12(cpustate); } /* DB DD */
+OP(dd,13) { illegal_1(cpustate); op_13(cpustate); } /* DB DD */
+OP(dd,14) { illegal_1(cpustate); op_14(cpustate); } /* DB DD */
+OP(dd,15) { illegal_1(cpustate); op_15(cpustate); } /* DB DD */
+OP(dd,16) { illegal_1(cpustate); op_16(cpustate); } /* DB DD */
+OP(dd,17) { illegal_1(cpustate); op_17(cpustate); } /* DB DD */
+
+OP(dd,18) { illegal_1(cpustate); op_18(cpustate); } /* DB DD */
+OP(dd,19) { cpustate->R++; ADD16(IX,DE); } /* ADD IX,DE */
+OP(dd,1a) { illegal_1(cpustate); op_1a(cpustate); } /* DB DD */
+OP(dd,1b) { illegal_1(cpustate); op_1b(cpustate); } /* DB DD */
+OP(dd,1c) { illegal_1(cpustate); op_1c(cpustate); } /* DB DD */
+OP(dd,1d) { illegal_1(cpustate); op_1d(cpustate); } /* DB DD */
+OP(dd,1e) { illegal_1(cpustate); op_1e(cpustate); } /* DB DD */
+OP(dd,1f) { illegal_1(cpustate); op_1f(cpustate); } /* DB DD */
+
+OP(dd,20) { illegal_1(cpustate); op_20(cpustate); } /* DB DD */
+OP(dd,21) { cpustate->R++; cpustate->_IX = ARG16(cpustate); } /* LD IX,w */
+OP(dd,22) { cpustate->R++; cpustate->ea = ARG16(cpustate); WM16(cpustate, cpustate->ea, &cpustate->IX ); } /* LD (w),IX */
+OP(dd,23) { cpustate->R++; cpustate->_IX++; } /* INC IX */
+OP(dd,24) { cpustate->R++; cpustate->_HX = INC(cpustate, cpustate->_HX); } /* INC HX */
+OP(dd,25) { cpustate->R++; cpustate->_HX = DEC(cpustate, cpustate->_HX); } /* DEC HX */
+OP(dd,26) { cpustate->R++; cpustate->_HX = ARG(cpustate); } /* LD HX,n */
+OP(dd,27) { illegal_1(cpustate); op_27(cpustate); } /* DB DD */
+
+OP(dd,28) { illegal_1(cpustate); op_28(cpustate); } /* DB DD */
+OP(dd,29) { cpustate->R++; ADD16(IX,IX); } /* ADD IX,IX */
+OP(dd,2a) { cpustate->R++; cpustate->ea = ARG16(cpustate); RM16(cpustate, cpustate->ea, &cpustate->IX ); } /* LD IX,(w) */
+OP(dd,2b) { cpustate->R++; cpustate->_IX--; } /* DEC IX */
+OP(dd,2c) { cpustate->R++; cpustate->_LX = INC(cpustate, cpustate->_LX); } /* INC LX */
+OP(dd,2d) { cpustate->R++; cpustate->_LX = DEC(cpustate, cpustate->_LX); } /* DEC LX */
+OP(dd,2e) { cpustate->R++; cpustate->_LX = ARG(cpustate); } /* LD LX,n */
+OP(dd,2f) { illegal_1(cpustate); op_2f(cpustate); } /* DB DD */
+
+OP(dd,30) { illegal_1(cpustate); op_30(cpustate); } /* DB DD */
+OP(dd,31) { illegal_1(cpustate); op_31(cpustate); } /* DB DD */
+OP(dd,32) { illegal_1(cpustate); op_32(cpustate); } /* DB DD */
+OP(dd,33) { illegal_1(cpustate); op_33(cpustate); } /* DB DD */
+OP(dd,34) { cpustate->R++; EAX(cpustate); WM(cpustate, cpustate->ea, INC(cpustate, RM(cpustate, cpustate->ea)) ); } /* INC (IX+o) */
+OP(dd,35) { cpustate->R++; EAX(cpustate); WM(cpustate, cpustate->ea, DEC(cpustate, RM(cpustate, cpustate->ea)) ); } /* DEC (IX+o) */
+OP(dd,36) { cpustate->R++; EAX(cpustate); WM(cpustate, cpustate->ea, ARG(cpustate) ); } /* LD (IX+o),n */
+OP(dd,37) { illegal_1(cpustate); op_37(cpustate); } /* DB DD */
+
+OP(dd,38) { illegal_1(cpustate); op_38(cpustate); } /* DB DD */
+OP(dd,39) { cpustate->R++; ADD16(IX,SP); } /* ADD IX,SP */
+OP(dd,3a) { illegal_1(cpustate); op_3a(cpustate); } /* DB DD */
+OP(dd,3b) { illegal_1(cpustate); op_3b(cpustate); } /* DB DD */
+OP(dd,3c) { illegal_1(cpustate); op_3c(cpustate); } /* DB DD */
+OP(dd,3d) { illegal_1(cpustate); op_3d(cpustate); } /* DB DD */
+OP(dd,3e) { illegal_1(cpustate); op_3e(cpustate); } /* DB DD */
+OP(dd,3f) { illegal_1(cpustate); op_3f(cpustate); } /* DB DD */
+
+OP(dd,40) { illegal_1(cpustate); op_40(cpustate); } /* DB DD */
+OP(dd,41) { illegal_1(cpustate); op_41(cpustate); } /* DB DD */
+OP(dd,42) { illegal_1(cpustate); op_42(cpustate); } /* DB DD */
+OP(dd,43) { illegal_1(cpustate); op_43(cpustate); } /* DB DD */
+OP(dd,44) { cpustate->R++; cpustate->_B = cpustate->_HX; } /* LD B,HX */
+OP(dd,45) { cpustate->R++; cpustate->_B = cpustate->_LX; } /* LD B,LX */
+OP(dd,46) { cpustate->R++; EAX(cpustate); cpustate->_B = RM(cpustate, cpustate->ea); } /* LD B,(IX+o) */
+OP(dd,47) { illegal_1(cpustate); op_47(cpustate); } /* DB DD */
+
+OP(dd,48) { illegal_1(cpustate); op_48(cpustate); } /* DB DD */
+OP(dd,49) { illegal_1(cpustate); op_49(cpustate); } /* DB DD */
+OP(dd,4a) { illegal_1(cpustate); op_4a(cpustate); } /* DB DD */
+OP(dd,4b) { illegal_1(cpustate); op_4b(cpustate); } /* DB DD */
+OP(dd,4c) { cpustate->R++; cpustate->_C = cpustate->_HX; } /* LD C,HX */
+OP(dd,4d) { cpustate->R++; cpustate->_C = cpustate->_LX; } /* LD C,LX */
+OP(dd,4e) { cpustate->R++; EAX(cpustate); cpustate->_C = RM(cpustate, cpustate->ea); } /* LD C,(IX+o) */
+OP(dd,4f) { illegal_1(cpustate); op_4f(cpustate); } /* DB DD */
+
+OP(dd,50) { illegal_1(cpustate); op_50(cpustate); } /* DB DD */
+OP(dd,51) { illegal_1(cpustate); op_51(cpustate); } /* DB DD */
+OP(dd,52) { illegal_1(cpustate); op_52(cpustate); } /* DB DD */
+OP(dd,53) { illegal_1(cpustate); op_53(cpustate); } /* DB DD */
+OP(dd,54) { cpustate->R++; cpustate->_D = cpustate->_HX; } /* LD D,HX */
+OP(dd,55) { cpustate->R++; cpustate->_D = cpustate->_LX; } /* LD D,LX */
+OP(dd,56) { cpustate->R++; EAX(cpustate); cpustate->_D = RM(cpustate, cpustate->ea); } /* LD D,(IX+o) */
+OP(dd,57) { illegal_1(cpustate); op_57(cpustate); } /* DB DD */
+
+OP(dd,58) { illegal_1(cpustate); op_58(cpustate); } /* DB DD */
+OP(dd,59) { illegal_1(cpustate); op_59(cpustate); } /* DB DD */
+OP(dd,5a) { illegal_1(cpustate); op_5a(cpustate); } /* DB DD */
+OP(dd,5b) { illegal_1(cpustate); op_5b(cpustate); } /* DB DD */
+OP(dd,5c) { cpustate->R++; cpustate->_E = cpustate->_HX; } /* LD E,HX */
+OP(dd,5d) { cpustate->R++; cpustate->_E = cpustate->_LX; } /* LD E,LX */
+OP(dd,5e) { cpustate->R++; EAX(cpustate); cpustate->_E = RM(cpustate, cpustate->ea); } /* LD E,(IX+o) */
+OP(dd,5f) { illegal_1(cpustate); op_5f(cpustate); } /* DB DD */
+
+OP(dd,60) { cpustate->R++; cpustate->_HX = cpustate->_B; } /* LD HX,B */
+OP(dd,61) { cpustate->R++; cpustate->_HX = cpustate->_C; } /* LD HX,C */
+OP(dd,62) { cpustate->R++; cpustate->_HX = cpustate->_D; } /* LD HX,D */
+OP(dd,63) { cpustate->R++; cpustate->_HX = cpustate->_E; } /* LD HX,E */
+OP(dd,64) { } /* LD HX,HX */
+OP(dd,65) { cpustate->R++; cpustate->_HX = cpustate->_LX; } /* LD HX,LX */
+OP(dd,66) { cpustate->R++; EAX(cpustate); cpustate->_H = RM(cpustate, cpustate->ea); } /* LD H,(IX+o) */
+OP(dd,67) { cpustate->R++; cpustate->_HX = cpustate->_A; } /* LD HX,A */
+
+OP(dd,68) { cpustate->R++; cpustate->_LX = cpustate->_B; } /* LD LX,B */
+OP(dd,69) { cpustate->R++; cpustate->_LX = cpustate->_C; } /* LD LX,C */
+OP(dd,6a) { cpustate->R++; cpustate->_LX = cpustate->_D; } /* LD LX,D */
+OP(dd,6b) { cpustate->R++; cpustate->_LX = cpustate->_E; } /* LD LX,E */
+OP(dd,6c) { cpustate->R++; cpustate->_LX = cpustate->_HX; } /* LD LX,HX */
+OP(dd,6d) { } /* LD LX,LX */
+OP(dd,6e) { cpustate->R++; EAX(cpustate); cpustate->_L = RM(cpustate, cpustate->ea); } /* LD L,(IX+o) */
+OP(dd,6f) { cpustate->R++; cpustate->_LX = cpustate->_A; } /* LD LX,A */
+
+OP(dd,70) { cpustate->R++; EAX(cpustate); WM(cpustate, cpustate->ea, cpustate->_B ); } /* LD (IX+o),B */
+OP(dd,71) { cpustate->R++; EAX(cpustate); WM(cpustate, cpustate->ea, cpustate->_C ); } /* LD (IX+o),C */
+OP(dd,72) { cpustate->R++; EAX(cpustate); WM(cpustate, cpustate->ea, cpustate->_D ); } /* LD (IX+o),D */
+OP(dd,73) { cpustate->R++; EAX(cpustate); WM(cpustate, cpustate->ea, cpustate->_E ); } /* LD (IX+o),E */
+OP(dd,74) { cpustate->R++; EAX(cpustate); WM(cpustate, cpustate->ea, cpustate->_H ); } /* LD (IX+o),H */
+OP(dd,75) { cpustate->R++; EAX(cpustate); WM(cpustate, cpustate->ea, cpustate->_L ); } /* LD (IX+o),L */
+OP(dd,76) { illegal_1(cpustate); op_76(cpustate); } /* DB DD */
+OP(dd,77) { cpustate->R++; EAX(cpustate); WM(cpustate, cpustate->ea, cpustate->_A ); } /* LD (IX+o),A */
+
+OP(dd,78) { illegal_1(cpustate); op_78(cpustate); } /* DB DD */
+OP(dd,79) { illegal_1(cpustate); op_79(cpustate); } /* DB DD */
+OP(dd,7a) { illegal_1(cpustate); op_7a(cpustate); } /* DB DD */
+OP(dd,7b) { illegal_1(cpustate); op_7b(cpustate); } /* DB DD */
+OP(dd,7c) { cpustate->R++; cpustate->_A = cpustate->_HX; } /* LD A,HX */
+OP(dd,7d) { cpustate->R++; cpustate->_A = cpustate->_LX; } /* LD A,LX */
+OP(dd,7e) { cpustate->R++; EAX(cpustate); cpustate->_A = RM(cpustate, cpustate->ea); } /* LD A,(IX+o) */
+OP(dd,7f) { illegal_1(cpustate); op_7f(cpustate); } /* DB DD */
+
+OP(dd,80) { illegal_1(cpustate); op_80(cpustate); } /* DB DD */
+OP(dd,81) { illegal_1(cpustate); op_81(cpustate); } /* DB DD */
+OP(dd,82) { illegal_1(cpustate); op_82(cpustate); } /* DB DD */
+OP(dd,83) { illegal_1(cpustate); op_83(cpustate); } /* DB DD */
+OP(dd,84) { cpustate->R++; ADD(cpustate->_HX); } /* ADD A,HX */
+OP(dd,85) { cpustate->R++; ADD(cpustate->_LX); } /* ADD A,LX */
+OP(dd,86) { cpustate->R++; EAX(cpustate); ADD(RM(cpustate, cpustate->ea)); } /* ADD A,(IX+o) */
+OP(dd,87) { illegal_1(cpustate); op_87(cpustate); } /* DB DD */
+
+OP(dd,88) { illegal_1(cpustate); op_88(cpustate); } /* DB DD */
+OP(dd,89) { illegal_1(cpustate); op_89(cpustate); } /* DB DD */
+OP(dd,8a) { illegal_1(cpustate); op_8a(cpustate); } /* DB DD */
+OP(dd,8b) { illegal_1(cpustate); op_8b(cpustate); } /* DB DD */
+OP(dd,8c) { cpustate->R++; ADC(cpustate->_HX); } /* ADC A,HX */
+OP(dd,8d) { cpustate->R++; ADC(cpustate->_LX); } /* ADC A,LX */
+OP(dd,8e) { cpustate->R++; EAX(cpustate); ADC(RM(cpustate, cpustate->ea)); } /* ADC A,(IX+o) */
+OP(dd,8f) { illegal_1(cpustate); op_8f(cpustate); } /* DB DD */
+
+OP(dd,90) { illegal_1(cpustate); op_90(cpustate); } /* DB DD */
+OP(dd,91) { illegal_1(cpustate); op_91(cpustate); } /* DB DD */
+OP(dd,92) { illegal_1(cpustate); op_92(cpustate); } /* DB DD */
+OP(dd,93) { illegal_1(cpustate); op_93(cpustate); } /* DB DD */
+OP(dd,94) { cpustate->R++; SUB(cpustate->_HX); } /* SUB HX */
+OP(dd,95) { cpustate->R++; SUB(cpustate->_LX); } /* SUB LX */
+OP(dd,96) { cpustate->R++; EAX(cpustate); SUB(RM(cpustate, cpustate->ea)); } /* SUB (IX+o) */
+OP(dd,97) { illegal_1(cpustate); op_97(cpustate); } /* DB DD */
+
+OP(dd,98) { illegal_1(cpustate); op_98(cpustate); } /* DB DD */
+OP(dd,99) { illegal_1(cpustate); op_99(cpustate); } /* DB DD */
+OP(dd,9a) { illegal_1(cpustate); op_9a(cpustate); } /* DB DD */
+OP(dd,9b) { illegal_1(cpustate); op_9b(cpustate); } /* DB DD */
+OP(dd,9c) { cpustate->R++; SBC(cpustate->_HX); } /* SBC A,HX */
+OP(dd,9d) { cpustate->R++; SBC(cpustate->_LX); } /* SBC A,LX */
+OP(dd,9e) { cpustate->R++; EAX(cpustate); SBC(RM(cpustate, cpustate->ea)); } /* SBC A,(IX+o) */
+OP(dd,9f) { illegal_1(cpustate); op_9f(cpustate); } /* DB DD */
+
+OP(dd,a0) { illegal_1(cpustate); op_a0(cpustate); } /* DB DD */
+OP(dd,a1) { illegal_1(cpustate); op_a1(cpustate); } /* DB DD */
+OP(dd,a2) { illegal_1(cpustate); op_a2(cpustate); } /* DB DD */
+OP(dd,a3) { illegal_1(cpustate); op_a3(cpustate); } /* DB DD */
+OP(dd,a4) { cpustate->R++; AND(cpustate->_HX); } /* AND HX */
+OP(dd,a5) { cpustate->R++; AND(cpustate->_LX); } /* AND LX */
+OP(dd,a6) { cpustate->R++; EAX(cpustate); AND(RM(cpustate, cpustate->ea)); } /* AND (IX+o) */
+OP(dd,a7) { illegal_1(cpustate); op_a7(cpustate); } /* DB DD */
+
+OP(dd,a8) { illegal_1(cpustate); op_a8(cpustate); } /* DB DD */
+OP(dd,a9) { illegal_1(cpustate); op_a9(cpustate); } /* DB DD */
+OP(dd,aa) { illegal_1(cpustate); op_aa(cpustate); } /* DB DD */
+OP(dd,ab) { illegal_1(cpustate); op_ab(cpustate); } /* DB DD */
+OP(dd,ac) { cpustate->R++; XOR(cpustate->_HX); } /* XOR HX */
+OP(dd,ad) { cpustate->R++; XOR(cpustate->_LX); } /* XOR LX */
+OP(dd,ae) { cpustate->R++; EAX(cpustate); XOR(RM(cpustate, cpustate->ea)); } /* XOR (IX+o) */
+OP(dd,af) { illegal_1(cpustate); op_af(cpustate); } /* DB DD */
+
+OP(dd,b0) { illegal_1(cpustate); op_b0(cpustate); } /* DB DD */
+OP(dd,b1) { illegal_1(cpustate); op_b1(cpustate); } /* DB DD */
+OP(dd,b2) { illegal_1(cpustate); op_b2(cpustate); } /* DB DD */
+OP(dd,b3) { illegal_1(cpustate); op_b3(cpustate); } /* DB DD */
+OP(dd,b4) { cpustate->R++; OR(cpustate->_HX); } /* OR HX */
+OP(dd,b5) { cpustate->R++; OR(cpustate->_LX); } /* OR LX */
+OP(dd,b6) { cpustate->R++; EAX(cpustate); OR(RM(cpustate, cpustate->ea)); } /* OR (IX+o) */
+OP(dd,b7) { illegal_1(cpustate); op_b7(cpustate); } /* DB DD */
+
+OP(dd,b8) { illegal_1(cpustate); op_b8(cpustate); } /* DB DD */
+OP(dd,b9) { illegal_1(cpustate); op_b9(cpustate); } /* DB DD */
+OP(dd,ba) { illegal_1(cpustate); op_ba(cpustate); } /* DB DD */
+OP(dd,bb) { illegal_1(cpustate); op_bb(cpustate); } /* DB DD */
+OP(dd,bc) { cpustate->R++; CP(cpustate->_HX); } /* CP HX */
+OP(dd,bd) { cpustate->R++; CP(cpustate->_LX); } /* CP LX */
+OP(dd,be) { cpustate->R++; EAX(cpustate); CP(RM(cpustate, cpustate->ea)); } /* CP (IX+o) */
+OP(dd,bf) { illegal_1(cpustate); op_bf(cpustate); } /* DB DD */
+
+OP(dd,c0) { illegal_1(cpustate); op_c0(cpustate); } /* DB DD */
+OP(dd,c1) { illegal_1(cpustate); op_c1(cpustate); } /* DB DD */
+OP(dd,c2) { illegal_1(cpustate); op_c2(cpustate); } /* DB DD */
+OP(dd,c3) { illegal_1(cpustate); op_c3(cpustate); } /* DB DD */
+OP(dd,c4) { illegal_1(cpustate); op_c4(cpustate); } /* DB DD */
+OP(dd,c5) { illegal_1(cpustate); op_c5(cpustate); } /* DB DD */
+OP(dd,c6) { illegal_1(cpustate); op_c6(cpustate); } /* DB DD */
+OP(dd,c7) { illegal_1(cpustate); op_c7(cpustate); } /* DB DD */
+
+OP(dd,c8) { illegal_1(cpustate); op_c8(cpustate); } /* DB DD */
+OP(dd,c9) { illegal_1(cpustate); op_c9(cpustate); } /* DB DD */
+OP(dd,ca) { illegal_1(cpustate); op_ca(cpustate); } /* DB DD */
+OP(dd,cb) { cpustate->R++; EAX(cpustate); cpustate->extra_cycles += exec_xycb(cpustate,ARG(cpustate)); } /* ** DD CB xx */
+OP(dd,cc) { illegal_1(cpustate); op_cc(cpustate); } /* DB DD */
+OP(dd,cd) { illegal_1(cpustate); op_cd(cpustate); } /* DB DD */
+OP(dd,ce) { illegal_1(cpustate); op_ce(cpustate); } /* DB DD */
+OP(dd,cf) { illegal_1(cpustate); op_cf(cpustate); } /* DB DD */
+
+OP(dd,d0) { illegal_1(cpustate); op_d0(cpustate); } /* DB DD */
+OP(dd,d1) { illegal_1(cpustate); op_d1(cpustate); } /* DB DD */
+OP(dd,d2) { illegal_1(cpustate); op_d2(cpustate); } /* DB DD */
+OP(dd,d3) { illegal_1(cpustate); op_d3(cpustate); } /* DB DD */
+OP(dd,d4) { illegal_1(cpustate); op_d4(cpustate); } /* DB DD */
+OP(dd,d5) { illegal_1(cpustate); op_d5(cpustate); } /* DB DD */
+OP(dd,d6) { illegal_1(cpustate); op_d6(cpustate); } /* DB DD */
+OP(dd,d7) { illegal_1(cpustate); op_d7(cpustate); } /* DB DD */
+
+OP(dd,d8) { illegal_1(cpustate); op_d8(cpustate); } /* DB DD */
+OP(dd,d9) { illegal_1(cpustate); op_d9(cpustate); } /* DB DD */
+OP(dd,da) { illegal_1(cpustate); op_da(cpustate); } /* DB DD */
+OP(dd,db) { illegal_1(cpustate); op_db(cpustate); } /* DB DD */
+OP(dd,dc) { illegal_1(cpustate); op_dc(cpustate); } /* DB DD */
+OP(dd,dd) { illegal_1(cpustate); op_dd(cpustate); } /* DB DD */
+OP(dd,de) { illegal_1(cpustate); op_de(cpustate); } /* DB DD */
+OP(dd,df) { illegal_1(cpustate); op_df(cpustate); } /* DB DD */
+
+OP(dd,e0) { illegal_1(cpustate); op_e0(cpustate); } /* DB DD */
+OP(dd,e1) { cpustate->R++; POP(cpustate, IX); } /* POP IX */
+OP(dd,e2) { illegal_1(cpustate); op_e2(cpustate); } /* DB DD */
+OP(dd,e3) { cpustate->R++; EXSP(IX); } /* EX (SP),IX */
+OP(dd,e4) { illegal_1(cpustate); op_e4(cpustate); } /* DB DD */
+OP(dd,e5) { cpustate->R++; PUSH(cpustate, IX ); } /* PUSH IX */
+OP(dd,e6) { illegal_1(cpustate); op_e6(cpustate); } /* DB DD */
+OP(dd,e7) { illegal_1(cpustate); op_e7(cpustate); } /* DB DD */
+
+OP(dd,e8) { illegal_1(cpustate); op_e8(cpustate); } /* DB DD */
+OP(dd,e9) { cpustate->R++; cpustate->_PC = cpustate->_IX; } /* JP (IX) */
+OP(dd,ea) { illegal_1(cpustate); op_ea(cpustate); } /* DB DD */
+OP(dd,eb) { illegal_1(cpustate); op_eb(cpustate); } /* DB DD */
+OP(dd,ec) { illegal_1(cpustate); op_ec(cpustate); } /* DB DD */
+OP(dd,ed) { illegal_1(cpustate); op_ed(cpustate); } /* DB DD */
+OP(dd,ee) { illegal_1(cpustate); op_ee(cpustate); } /* DB DD */
+OP(dd,ef) { illegal_1(cpustate); op_ef(cpustate); } /* DB DD */
+
+OP(dd,f0) { illegal_1(cpustate); op_f0(cpustate); } /* DB DD */
+OP(dd,f1) { illegal_1(cpustate); op_f1(cpustate); } /* DB DD */
+OP(dd,f2) { illegal_1(cpustate); op_f2(cpustate); } /* DB DD */
+OP(dd,f3) { illegal_1(cpustate); op_f3(cpustate); } /* DB DD */
+OP(dd,f4) { illegal_1(cpustate); op_f4(cpustate); } /* DB DD */
+OP(dd,f5) { illegal_1(cpustate); op_f5(cpustate); } /* DB DD */
+OP(dd,f6) { illegal_1(cpustate); op_f6(cpustate); } /* DB DD */
+OP(dd,f7) { illegal_1(cpustate); op_f7(cpustate); } /* DB DD */
+
+OP(dd,f8) { illegal_1(cpustate); op_f8(cpustate); } /* DB DD */
+OP(dd,f9) { cpustate->R++; cpustate->_SP = cpustate->_IX; } /* LD SP,IX */
+OP(dd,fa) { illegal_1(cpustate); op_fa(cpustate); } /* DB DD */
+OP(dd,fb) { illegal_1(cpustate); op_fb(cpustate); } /* DB DD */
+OP(dd,fc) { illegal_1(cpustate); op_fc(cpustate); } /* DB DD */
+OP(dd,fd) { illegal_1(cpustate); op_fd(cpustate); } /* DB DD */
+OP(dd,fe) { illegal_1(cpustate); op_fe(cpustate); } /* DB DD */
+OP(dd,ff) { illegal_1(cpustate); op_ff(cpustate); } /* DB DD */
+
diff --git a/trunk/src/emu/cpu/z180/z180ed.c b/trunk/src/emu/cpu/z180/z180ed.c
new file mode 100644
index 00000000000..1777e7592c3
--- /dev/null
+++ b/trunk/src/emu/cpu/z180/z180ed.c
@@ -0,0 +1,297 @@
+OP(illegal,2)
+{
+ logerror("Z180 '%s' ill. opcode $ed $%02x\n",
+ cpustate->device->tag(), cpustate->direct->read_decrypted_byte((cpustate->_PCD-1)&0xffff));
+}
+
+/**********************************************************
+ * special opcodes (ED prefix)
+ **********************************************************/
+OP(ed,00) { unsigned n = ARG(cpustate); cpustate->_B = IN(cpustate, n ); } /* IN0 B,(n) */
+OP(ed,01) { unsigned n = ARG(cpustate); OUT(cpustate, n, cpustate->_B ); } /* OUT0 (n),B */
+OP(ed,02) { illegal_2(cpustate); } /* DB ED */
+OP(ed,03) { illegal_2(cpustate); } /* DB ED */
+OP(ed,04) { TST( cpustate->_B ); } /* TST B */
+OP(ed,05) { illegal_2(cpustate); } /* DB ED */
+OP(ed,06) { illegal_2(cpustate); } /* DB ED */
+OP(ed,07) { illegal_2(cpustate); } /* DB ED */
+
+OP(ed,08) { unsigned n = ARG(cpustate); cpustate->_C = IN(cpustate, n ); } /* IN0 C,(n) */
+OP(ed,09) { unsigned n = ARG(cpustate); OUT(cpustate, n, cpustate->_C ); } /* OUT0 (n),C */
+OP(ed,0a) { illegal_2(cpustate); } /* DB ED */
+OP(ed,0b) { illegal_2(cpustate); } /* DB ED */
+OP(ed,0c) { TST( cpustate->_C ); } /* TST C */
+OP(ed,0d) { illegal_2(cpustate); } /* DB ED */
+OP(ed,0e) { illegal_2(cpustate); } /* DB ED */
+OP(ed,0f) { illegal_2(cpustate); } /* DB ED */
+
+OP(ed,10) { unsigned n = ARG(cpustate); cpustate->_D = IN(cpustate, n ); } /* IN0 D,(n) */
+OP(ed,11) { unsigned n = ARG(cpustate); OUT(cpustate, n, cpustate->_D ); } /* OUT0 (n),D */
+OP(ed,12) { illegal_2(cpustate); } /* DB ED */
+OP(ed,13) { illegal_2(cpustate); } /* DB ED */
+OP(ed,14) { TST( cpustate->_D ); } /* TST D */
+OP(ed,15) { illegal_2(cpustate); } /* DB ED */
+OP(ed,16) { illegal_2(cpustate); } /* DB ED */
+OP(ed,17) { illegal_2(cpustate); } /* DB ED */
+
+OP(ed,18) { unsigned n = ARG(cpustate); cpustate->_E = IN(cpustate, n ); } /* IN0 E,(n) */
+OP(ed,19) { unsigned n = ARG(cpustate); OUT(cpustate, n, cpustate->_E ); } /* OUT0 (n),E */
+OP(ed,1a) { illegal_2(cpustate); } /* DB ED */
+OP(ed,1b) { illegal_2(cpustate); } /* DB ED */
+OP(ed,1c) { TST( cpustate->_E ); } /* TST E */
+OP(ed,1d) { illegal_2(cpustate); } /* DB ED */
+OP(ed,1e) { illegal_2(cpustate); } /* DB ED */
+OP(ed,1f) { illegal_2(cpustate); } /* DB ED */
+
+OP(ed,20) { unsigned n = ARG(cpustate); cpustate->_H = IN(cpustate, n ); } /* IN0 H,(n) */
+OP(ed,21) { unsigned n = ARG(cpustate); OUT(cpustate, n, cpustate->_H ); } /* OUT0 (n),H */
+OP(ed,22) { illegal_2(cpustate); } /* DB ED */
+OP(ed,23) { illegal_2(cpustate); } /* DB ED */
+OP(ed,24) { TST( cpustate->_H ); } /* TST H */
+OP(ed,25) { illegal_2(cpustate); } /* DB ED */
+OP(ed,26) { illegal_2(cpustate); } /* DB ED */
+OP(ed,27) { illegal_2(cpustate); } /* DB ED */
+
+OP(ed,28) { unsigned n = ARG(cpustate); cpustate->_L = IN(cpustate, n ); } /* IN0 L,(n) */
+OP(ed,29) { unsigned n = ARG(cpustate); OUT(cpustate, n, cpustate->_L ); } /* OUT0 (n),L */
+OP(ed,2a) { illegal_2(cpustate); } /* DB ED */
+OP(ed,2b) { illegal_2(cpustate); } /* DB ED */
+OP(ed,2c) { TST( cpustate->_L ); } /* TST L */
+OP(ed,2d) { illegal_2(cpustate); } /* DB ED */
+OP(ed,2e) { illegal_2(cpustate); } /* DB ED */
+OP(ed,2f) { illegal_2(cpustate); } /* DB ED */
+
+OP(ed,30) { unsigned n = ARG(cpustate); IN(cpustate, n ); } /* IN0 (n) */
+OP(ed,31) { unsigned n = ARG(cpustate); OUT(cpustate, n, 0 ); } /* OUT0 (n) */
+OP(ed,32) { illegal_2(cpustate); } /* DB ED */
+OP(ed,33) { illegal_2(cpustate); } /* DB ED */
+OP(ed,34) { TST( RM(cpustate, cpustate->_HL) ); } /* TST (HL) */
+OP(ed,35) { illegal_2(cpustate); } /* DB ED */
+OP(ed,36) { illegal_2(cpustate); } /* DB ED */
+OP(ed,37) { illegal_2(cpustate); } /* DB ED */
+
+OP(ed,38) { unsigned n = ARG(cpustate); cpustate->_A = IN(cpustate, n ); } /* IN0 A,(n) */
+OP(ed,39) { unsigned n = ARG(cpustate); OUT(cpustate, n, cpustate->_A ); } /* OUT0 (n),A */
+OP(ed,3a) { illegal_2(cpustate); } /* DB ED */
+OP(ed,3b) { illegal_2(cpustate); } /* DB ED */
+OP(ed,3c) { TST( cpustate->_A ); } /* TST A */
+OP(ed,3d) { illegal_2(cpustate); } /* DB ED */
+OP(ed,3e) { illegal_2(cpustate); } /* DB ED */
+OP(ed,3f) { illegal_2(cpustate); } /* DB ED */
+
+OP(ed,40) { cpustate->_B = IN(cpustate, cpustate->_BC); cpustate->_F = (cpustate->_F & CF) | SZP[cpustate->_B]; } /* IN B,(C) */
+OP(ed,41) { OUT(cpustate, cpustate->_BC,cpustate->_B); } /* OUT (C),B */
+OP(ed,42) { SBC16( BC ); } /* SBC HL,BC */
+OP(ed,43) { cpustate->ea = ARG16(cpustate); WM16(cpustate, cpustate->ea, &cpustate->BC ); } /* LD (w),BC */
+OP(ed,44) { NEG; } /* NEG */
+OP(ed,45) { RETN; } /* RETN; */
+OP(ed,46) { cpustate->IM = 0; } /* IM 0 */
+OP(ed,47) { LD_I_A; } /* LD I,A */
+
+OP(ed,48) { cpustate->_C = IN(cpustate, cpustate->_BC); cpustate->_F = (cpustate->_F & CF) | SZP[cpustate->_C]; } /* IN C,(C) */
+OP(ed,49) { OUT(cpustate, cpustate->_BC,cpustate->_C); } /* OUT (C),C */
+OP(ed,4a) { ADC16( BC ); } /* ADC HL,BC */
+OP(ed,4b) { cpustate->ea = ARG16(cpustate); RM16(cpustate, cpustate->ea, &cpustate->BC ); } /* LD BC,(w) */
+OP(ed,4c) { MLT( BC ); } /* MLT BC */
+OP(ed,4d) { RETI; } /* RETI */
+OP(ed,4e) { cpustate->IM = 0; } /* IM 0 */
+OP(ed,4f) { LD_R_A; } /* LD R,A */
+
+OP(ed,50) { cpustate->_D = IN(cpustate, cpustate->_BC); cpustate->_F = (cpustate->_F & CF) | SZP[cpustate->_D]; } /* IN D,(C) */
+OP(ed,51) { OUT(cpustate, cpustate->_BC,cpustate->_D); } /* OUT (C),D */
+OP(ed,52) { SBC16( DE ); } /* SBC HL,DE */
+OP(ed,53) { cpustate->ea = ARG16(cpustate); WM16(cpustate, cpustate->ea, &cpustate->DE ); } /* LD (w),DE */
+OP(ed,54) { NEG; } /* NEG */
+OP(ed,55) { RETN; } /* RETN; */
+OP(ed,56) { cpustate->IM = 1; } /* IM 1 */
+OP(ed,57) { LD_A_I; } /* LD A,I */
+
+OP(ed,58) { cpustate->_E = IN(cpustate, cpustate->_BC); cpustate->_F = (cpustate->_F & CF) | SZP[cpustate->_E]; } /* IN E,(C) */
+OP(ed,59) { OUT(cpustate, cpustate->_BC,cpustate->_E); } /* OUT (C),E */
+OP(ed,5a) { ADC16( DE ); } /* ADC HL,DE */
+OP(ed,5b) { cpustate->ea = ARG16(cpustate); RM16(cpustate, cpustate->ea, &cpustate->DE ); } /* LD DE,(w) */
+OP(ed,5c) { MLT( DE ); } /* MLT DE */
+OP(ed,5d) { RETI; } /* RETI */
+OP(ed,5e) { cpustate->IM = 2; } /* IM 2 */
+OP(ed,5f) { LD_A_R; } /* LD A,R */
+
+OP(ed,60) { cpustate->_H = IN(cpustate, cpustate->_BC); cpustate->_F = (cpustate->_F & CF) | SZP[cpustate->_H]; } /* IN H,(C) */
+OP(ed,61) { OUT(cpustate, cpustate->_BC,cpustate->_H); } /* OUT (C),H */
+OP(ed,62) { SBC16( HL ); } /* SBC HL,HL */
+OP(ed,63) { cpustate->ea = ARG16(cpustate); WM16(cpustate, cpustate->ea, &cpustate->HL ); } /* LD (w),HL */
+OP(ed,64) { unsigned m = ARG(cpustate); TST( m ); } /* TST m */
+OP(ed,65) { RETN; } /* RETN; */
+OP(ed,66) { cpustate->IM = 0; } /* IM 0 */
+OP(ed,67) { RRD; } /* RRD (HL) */
+
+OP(ed,68) { cpustate->_L = IN(cpustate, cpustate->_BC); cpustate->_F = (cpustate->_F & CF) | SZP[cpustate->_L]; } /* IN L,(C) */
+OP(ed,69) { OUT(cpustate, cpustate->_BC,cpustate->_L); } /* OUT (C),L */
+OP(ed,6a) { ADC16( HL ); } /* ADC HL,HL */
+OP(ed,6b) { cpustate->ea = ARG16(cpustate); RM16(cpustate, cpustate->ea, &cpustate->HL ); } /* LD HL,(w) */
+OP(ed,6c) { MLT( HL ); } /* MLT HL */
+OP(ed,6d) { RETI; } /* RETI */
+OP(ed,6e) { cpustate->IM = 0; } /* IM 0 */
+OP(ed,6f) { RLD; } /* RLD (HL) */
+
+OP(ed,70) { UINT8 res = IN(cpustate, cpustate->_BC); cpustate->_F = (cpustate->_F & CF) | SZP[res]; } /* IN 0,(C) */
+OP(ed,71) { OUT(cpustate, cpustate->_BC,0); } /* OUT (C),0 */
+OP(ed,72) { SBC16( SP ); } /* SBC HL,SP */
+OP(ed,73) { cpustate->ea = ARG16(cpustate); WM16(cpustate, cpustate->ea, &cpustate->SP ); } /* LD (w),SP */
+OP(ed,74) { unsigned m = ARG(cpustate); cpustate->_F = (cpustate->_F & CF) | SZP[IN(cpustate, cpustate->_C) & m]; } /* TSTIO m */
+OP(ed,75) { RETN; } /* RETN; */
+OP(ed,76) { SLP; } /* SLP */
+OP(ed,77) { illegal_2(cpustate); } /* DB ED,77 */
+
+OP(ed,78) { cpustate->_A = IN(cpustate, cpustate->_BC); cpustate->_F = (cpustate->_F & CF) | SZP[cpustate->_A]; } /* IN E,(C) */
+OP(ed,79) { OUT(cpustate, cpustate->_BC,cpustate->_A); } /* OUT (C),E */
+OP(ed,7a) { ADC16( SP ); } /* ADC HL,SP */
+OP(ed,7b) { cpustate->ea = ARG16(cpustate); RM16(cpustate, cpustate->ea, &cpustate->SP ); } /* LD SP,(w) */
+OP(ed,7c) { MLT( SP ); } /* MLT SP */
+OP(ed,7d) { RETI; } /* RETI */
+OP(ed,7e) { cpustate->IM = 2; } /* IM 2 */
+OP(ed,7f) { illegal_2(cpustate); } /* DB ED,7F */
+
+OP(ed,80) { illegal_2(cpustate); } /* DB ED */
+OP(ed,81) { illegal_2(cpustate); } /* DB ED */
+OP(ed,82) { illegal_2(cpustate); } /* DB ED */
+OP(ed,83) { OTIM; } /* OTIM */
+OP(ed,84) { illegal_2(cpustate); } /* DB ED */
+OP(ed,85) { illegal_2(cpustate); } /* DB ED */
+OP(ed,86) { illegal_2(cpustate); } /* DB ED */
+OP(ed,87) { illegal_2(cpustate); } /* DB ED */
+
+OP(ed,88) { illegal_2(cpustate); } /* DB ED */
+OP(ed,89) { illegal_2(cpustate); } /* DB ED */
+OP(ed,8a) { illegal_2(cpustate); } /* DB ED */
+OP(ed,8b) { OTDM; } /* OTDM */
+OP(ed,8c) { illegal_2(cpustate); } /* DB ED */
+OP(ed,8d) { illegal_2(cpustate); } /* DB ED */
+OP(ed,8e) { illegal_2(cpustate); } /* DB ED */
+OP(ed,8f) { illegal_2(cpustate); } /* DB ED */
+
+OP(ed,90) { illegal_2(cpustate); } /* DB ED */
+OP(ed,91) { illegal_2(cpustate); } /* DB ED */
+OP(ed,92) { illegal_2(cpustate); } /* DB ED */
+OP(ed,93) { OTIMR; } /* OTIMR */
+OP(ed,94) { illegal_2(cpustate); } /* DB ED */
+OP(ed,95) { illegal_2(cpustate); } /* DB ED */
+OP(ed,96) { illegal_2(cpustate); } /* DB ED */
+OP(ed,97) { illegal_2(cpustate); } /* DB ED */
+
+OP(ed,98) { illegal_2(cpustate); } /* DB ED */
+OP(ed,99) { illegal_2(cpustate); } /* DB ED */
+OP(ed,9a) { illegal_2(cpustate); } /* DB ED */
+OP(ed,9b) { OTDMR; } /* OTDMR */
+OP(ed,9c) { illegal_2(cpustate); } /* DB ED */
+OP(ed,9d) { illegal_2(cpustate); } /* DB ED */
+OP(ed,9e) { illegal_2(cpustate); } /* DB ED */
+OP(ed,9f) { illegal_2(cpustate); } /* DB ED */
+
+OP(ed,a0) { LDI; } /* LDI */
+OP(ed,a1) { CPI; } /* CPI */
+OP(ed,a2) { INI; } /* INI */
+OP(ed,a3) { OUTI; } /* OUTI */
+OP(ed,a4) { illegal_2(cpustate); } /* DB ED */
+OP(ed,a5) { illegal_2(cpustate); } /* DB ED */
+OP(ed,a6) { illegal_2(cpustate); } /* DB ED */
+OP(ed,a7) { illegal_2(cpustate); } /* DB ED */
+
+OP(ed,a8) { LDD; } /* LDD */
+OP(ed,a9) { CPD; } /* CPD */
+OP(ed,aa) { IND; } /* IND */
+OP(ed,ab) { OUTD; } /* OUTD */
+OP(ed,ac) { illegal_2(cpustate); } /* DB ED */
+OP(ed,ad) { illegal_2(cpustate); } /* DB ED */
+OP(ed,ae) { illegal_2(cpustate); } /* DB ED */
+OP(ed,af) { illegal_2(cpustate); } /* DB ED */
+
+OP(ed,b0) { LDIR; } /* LDIR */
+OP(ed,b1) { CPIR; } /* CPIR */
+OP(ed,b2) { INIR; } /* INIR */
+OP(ed,b3) { OTIR; } /* OTIR */
+OP(ed,b4) { illegal_2(cpustate); } /* DB ED */
+OP(ed,b5) { illegal_2(cpustate); } /* DB ED */
+OP(ed,b6) { illegal_2(cpustate); } /* DB ED */
+OP(ed,b7) { illegal_2(cpustate); } /* DB ED */
+
+OP(ed,b8) { LDDR; } /* LDDR */
+OP(ed,b9) { CPDR; } /* CPDR */
+OP(ed,ba) { INDR; } /* INDR */
+OP(ed,bb) { OTDR; } /* OTDR */
+OP(ed,bc) { illegal_2(cpustate); } /* DB ED */
+OP(ed,bd) { illegal_2(cpustate); } /* DB ED */
+OP(ed,be) { illegal_2(cpustate); } /* DB ED */
+OP(ed,bf) { illegal_2(cpustate); } /* DB ED */
+
+OP(ed,c0) { illegal_2(cpustate); } /* DB ED */
+OP(ed,c1) { illegal_2(cpustate); } /* DB ED */
+OP(ed,c2) { illegal_2(cpustate); } /* DB ED */
+OP(ed,c3) { illegal_2(cpustate); } /* DB ED */
+OP(ed,c4) { illegal_2(cpustate); } /* DB ED */
+OP(ed,c5) { illegal_2(cpustate); } /* DB ED */
+OP(ed,c6) { illegal_2(cpustate); } /* DB ED */
+OP(ed,c7) { illegal_2(cpustate); } /* DB ED */
+
+OP(ed,c8) { illegal_2(cpustate); } /* DB ED */
+OP(ed,c9) { illegal_2(cpustate); } /* DB ED */
+OP(ed,ca) { illegal_2(cpustate); } /* DB ED */
+OP(ed,cb) { illegal_2(cpustate); } /* DB ED */
+OP(ed,cc) { illegal_2(cpustate); } /* DB ED */
+OP(ed,cd) { illegal_2(cpustate); } /* DB ED */
+OP(ed,ce) { illegal_2(cpustate); } /* DB ED */
+OP(ed,cf) { illegal_2(cpustate); } /* DB ED */
+
+OP(ed,d0) { illegal_2(cpustate); } /* DB ED */
+OP(ed,d1) { illegal_2(cpustate); } /* DB ED */
+OP(ed,d2) { illegal_2(cpustate); } /* DB ED */
+OP(ed,d3) { illegal_2(cpustate); } /* DB ED */
+OP(ed,d4) { illegal_2(cpustate); } /* DB ED */
+OP(ed,d5) { illegal_2(cpustate); } /* DB ED */
+OP(ed,d6) { illegal_2(cpustate); } /* DB ED */
+OP(ed,d7) { illegal_2(cpustate); } /* DB ED */
+
+OP(ed,d8) { illegal_2(cpustate); } /* DB ED */
+OP(ed,d9) { illegal_2(cpustate); } /* DB ED */
+OP(ed,da) { illegal_2(cpustate); } /* DB ED */
+OP(ed,db) { illegal_2(cpustate); } /* DB ED */
+OP(ed,dc) { illegal_2(cpustate); } /* DB ED */
+OP(ed,dd) { illegal_2(cpustate); } /* DB ED */
+OP(ed,de) { illegal_2(cpustate); } /* DB ED */
+OP(ed,df) { illegal_2(cpustate); } /* DB ED */
+
+OP(ed,e0) { illegal_2(cpustate); } /* DB ED */
+OP(ed,e1) { illegal_2(cpustate); } /* DB ED */
+OP(ed,e2) { illegal_2(cpustate); } /* DB ED */
+OP(ed,e3) { illegal_2(cpustate); } /* DB ED */
+OP(ed,e4) { illegal_2(cpustate); } /* DB ED */
+OP(ed,e5) { illegal_2(cpustate); } /* DB ED */
+OP(ed,e6) { illegal_2(cpustate); } /* DB ED */
+OP(ed,e7) { illegal_2(cpustate); } /* DB ED */
+
+OP(ed,e8) { illegal_2(cpustate); } /* DB ED */
+OP(ed,e9) { illegal_2(cpustate); } /* DB ED */
+OP(ed,ea) { illegal_2(cpustate); } /* DB ED */
+OP(ed,eb) { illegal_2(cpustate); } /* DB ED */
+OP(ed,ec) { illegal_2(cpustate); } /* DB ED */
+OP(ed,ed) { illegal_2(cpustate); } /* DB ED */
+OP(ed,ee) { illegal_2(cpustate); } /* DB ED */
+OP(ed,ef) { illegal_2(cpustate); } /* DB ED */
+
+OP(ed,f0) { illegal_2(cpustate); } /* DB ED */
+OP(ed,f1) { illegal_2(cpustate); } /* DB ED */
+OP(ed,f2) { illegal_2(cpustate); } /* DB ED */
+OP(ed,f3) { illegal_2(cpustate); } /* DB ED */
+OP(ed,f4) { illegal_2(cpustate); } /* DB ED */
+OP(ed,f5) { illegal_2(cpustate); } /* DB ED */
+OP(ed,f6) { illegal_2(cpustate); } /* DB ED */
+OP(ed,f7) { illegal_2(cpustate); } /* DB ED */
+
+OP(ed,f8) { illegal_2(cpustate); } /* DB ED */
+OP(ed,f9) { illegal_2(cpustate); } /* DB ED */
+OP(ed,fa) { illegal_2(cpustate); } /* DB ED */
+OP(ed,fb) { illegal_2(cpustate); } /* DB ED */
+OP(ed,fc) { illegal_2(cpustate); } /* DB ED */
+OP(ed,fd) { illegal_2(cpustate); } /* DB ED */
+OP(ed,fe) { illegal_2(cpustate); } /* DB ED */
+OP(ed,ff) { illegal_2(cpustate); } /* DB ED */
+
diff --git a/trunk/src/emu/cpu/z180/z180fd.c b/trunk/src/emu/cpu/z180/z180fd.c
new file mode 100644
index 00000000000..1cd28612796
--- /dev/null
+++ b/trunk/src/emu/cpu/z180/z180fd.c
@@ -0,0 +1,291 @@
+/**********************************************************
+ * IY register related opcodes (FD prefix)
+ **********************************************************/
+OP(fd,00) { illegal_1(cpustate); op_00(cpustate); } /* DB FD */
+OP(fd,01) { illegal_1(cpustate); op_01(cpustate); } /* DB FD */
+OP(fd,02) { illegal_1(cpustate); op_02(cpustate); } /* DB FD */
+OP(fd,03) { illegal_1(cpustate); op_03(cpustate); } /* DB FD */
+OP(fd,04) { illegal_1(cpustate); op_04(cpustate); } /* DB FD */
+OP(fd,05) { illegal_1(cpustate); op_05(cpustate); } /* DB FD */
+OP(fd,06) { illegal_1(cpustate); op_06(cpustate); } /* DB FD */
+OP(fd,07) { illegal_1(cpustate); op_07(cpustate); } /* DB FD */
+
+OP(fd,08) { illegal_1(cpustate); op_08(cpustate); } /* DB FD */
+OP(fd,09) { cpustate->R++; ADD16(IY,BC); } /* ADD IY,BC */
+OP(fd,0a) { illegal_1(cpustate); op_0a(cpustate); } /* DB FD */
+OP(fd,0b) { illegal_1(cpustate); op_0b(cpustate); } /* DB FD */
+OP(fd,0c) { illegal_1(cpustate); op_0c(cpustate); } /* DB FD */
+OP(fd,0d) { illegal_1(cpustate); op_0d(cpustate); } /* DB FD */
+OP(fd,0e) { illegal_1(cpustate); op_0e(cpustate); } /* DB FD */
+OP(fd,0f) { illegal_1(cpustate); op_0f(cpustate); } /* DB FD */
+
+OP(fd,10) { illegal_1(cpustate); op_10(cpustate); } /* DB FD */
+OP(fd,11) { illegal_1(cpustate); op_11(cpustate); } /* DB FD */
+OP(fd,12) { illegal_1(cpustate); op_12(cpustate); } /* DB FD */
+OP(fd,13) { illegal_1(cpustate); op_13(cpustate); } /* DB FD */
+OP(fd,14) { illegal_1(cpustate); op_14(cpustate); } /* DB FD */
+OP(fd,15) { illegal_1(cpustate); op_15(cpustate); } /* DB FD */
+OP(fd,16) { illegal_1(cpustate); op_16(cpustate); } /* DB FD */
+OP(fd,17) { illegal_1(cpustate); op_17(cpustate); } /* DB FD */
+
+OP(fd,18) { illegal_1(cpustate); op_18(cpustate); } /* DB FD */
+OP(fd,19) { cpustate->R++; ADD16(IY,DE); } /* ADD IY,DE */
+OP(fd,1a) { illegal_1(cpustate); op_1a(cpustate); } /* DB FD */
+OP(fd,1b) { illegal_1(cpustate); op_1b(cpustate); } /* DB FD */
+OP(fd,1c) { illegal_1(cpustate); op_1c(cpustate); } /* DB FD */
+OP(fd,1d) { illegal_1(cpustate); op_1d(cpustate); } /* DB FD */
+OP(fd,1e) { illegal_1(cpustate); op_1e(cpustate); } /* DB FD */
+OP(fd,1f) { illegal_1(cpustate); op_1f(cpustate); } /* DB FD */
+
+OP(fd,20) { illegal_1(cpustate); op_20(cpustate); } /* DB FD */
+OP(fd,21) { cpustate->R++; cpustate->_IY = ARG16(cpustate); } /* LD IY,w */
+OP(fd,22) { cpustate->R++; cpustate->ea = ARG16(cpustate); WM16(cpustate, cpustate->ea, &cpustate->IY ); } /* LD (w),IY */
+OP(fd,23) { cpustate->R++; cpustate->_IY++; } /* INC IY */
+OP(fd,24) { cpustate->R++; cpustate->_HY = INC(cpustate, cpustate->_HY); } /* INC HY */
+OP(fd,25) { cpustate->R++; cpustate->_HY = DEC(cpustate, cpustate->_HY); } /* DEC HY */
+OP(fd,26) { cpustate->R++; cpustate->_HY = ARG(cpustate); } /* LD HY,n */
+OP(fd,27) { illegal_1(cpustate); op_27(cpustate); } /* DB FD */
+
+OP(fd,28) { illegal_1(cpustate); op_28(cpustate); } /* DB FD */
+OP(fd,29) { cpustate->R++; ADD16(IY,IY); } /* ADD IY,IY */
+OP(fd,2a) { cpustate->R++; cpustate->ea = ARG16(cpustate); RM16(cpustate, cpustate->ea, &cpustate->IY ); } /* LD IY,(w) */
+OP(fd,2b) { cpustate->R++; cpustate->_IY--; } /* DEC IY */
+OP(fd,2c) { cpustate->R++; cpustate->_LY = INC(cpustate, cpustate->_LY); } /* INC LY */
+OP(fd,2d) { cpustate->R++; cpustate->_LY = DEC(cpustate, cpustate->_LY); } /* DEC LY */
+OP(fd,2e) { cpustate->R++; cpustate->_LY = ARG(cpustate); } /* LD LY,n */
+OP(fd,2f) { illegal_1(cpustate); op_2f(cpustate); } /* DB FD */
+
+OP(fd,30) { illegal_1(cpustate); op_30(cpustate); } /* DB FD */
+OP(fd,31) { illegal_1(cpustate); op_31(cpustate); } /* DB FD */
+OP(fd,32) { illegal_1(cpustate); op_32(cpustate); } /* DB FD */
+OP(fd,33) { illegal_1(cpustate); op_33(cpustate); } /* DB FD */
+OP(fd,34) { cpustate->R++; EAY(cpustate); WM(cpustate, cpustate->ea, INC(cpustate, RM(cpustate, cpustate->ea)) ); } /* INC (IY+o) */
+OP(fd,35) { cpustate->R++; EAY(cpustate); WM(cpustate, cpustate->ea, DEC(cpustate, RM(cpustate, cpustate->ea)) ); } /* DEC (IY+o) */
+OP(fd,36) { cpustate->R++; EAY(cpustate); WM(cpustate, cpustate->ea, ARG(cpustate) ); } /* LD (IY+o),n */
+OP(fd,37) { illegal_1(cpustate); op_37(cpustate); } /* DB FD */
+
+OP(fd,38) { illegal_1(cpustate); op_38(cpustate); } /* DB FD */
+OP(fd,39) { cpustate->R++; ADD16(IY,SP); } /* ADD IY,SP */
+OP(fd,3a) { illegal_1(cpustate); op_3a(cpustate); } /* DB FD */
+OP(fd,3b) { illegal_1(cpustate); op_3b(cpustate); } /* DB FD */
+OP(fd,3c) { illegal_1(cpustate); op_3c(cpustate); } /* DB FD */
+OP(fd,3d) { illegal_1(cpustate); op_3d(cpustate); } /* DB FD */
+OP(fd,3e) { illegal_1(cpustate); op_3e(cpustate); } /* DB FD */
+OP(fd,3f) { illegal_1(cpustate); op_3f(cpustate); } /* DB FD */
+
+OP(fd,40) { illegal_1(cpustate); op_40(cpustate); } /* DB FD */
+OP(fd,41) { illegal_1(cpustate); op_41(cpustate); } /* DB FD */
+OP(fd,42) { illegal_1(cpustate); op_42(cpustate); } /* DB FD */
+OP(fd,43) { illegal_1(cpustate); op_43(cpustate); } /* DB FD */
+OP(fd,44) { cpustate->R++; cpustate->_B = cpustate->_HY; } /* LD B,HY */
+OP(fd,45) { cpustate->R++; cpustate->_B = cpustate->_LY; } /* LD B,LY */
+OP(fd,46) { cpustate->R++; EAY(cpustate); cpustate->_B = RM(cpustate, cpustate->ea); } /* LD B,(IY+o) */
+OP(fd,47) { illegal_1(cpustate); op_47(cpustate); } /* DB FD */
+
+OP(fd,48) { illegal_1(cpustate); op_48(cpustate); } /* DB FD */
+OP(fd,49) { illegal_1(cpustate); op_49(cpustate); } /* DB FD */
+OP(fd,4a) { illegal_1(cpustate); op_4a(cpustate); } /* DB FD */
+OP(fd,4b) { illegal_1(cpustate); op_4b(cpustate); } /* DB FD */
+OP(fd,4c) { cpustate->R++; cpustate->_C = cpustate->_HY; } /* LD C,HY */
+OP(fd,4d) { cpustate->R++; cpustate->_C = cpustate->_LY; } /* LD C,LY */
+OP(fd,4e) { cpustate->R++; EAY(cpustate); cpustate->_C = RM(cpustate, cpustate->ea); } /* LD C,(IY+o) */
+OP(fd,4f) { illegal_1(cpustate); op_4f(cpustate); } /* DB FD */
+
+OP(fd,50) { illegal_1(cpustate); op_50(cpustate); } /* DB FD */
+OP(fd,51) { illegal_1(cpustate); op_51(cpustate); } /* DB FD */
+OP(fd,52) { illegal_1(cpustate); op_52(cpustate); } /* DB FD */
+OP(fd,53) { illegal_1(cpustate); op_53(cpustate); } /* DB FD */
+OP(fd,54) { cpustate->R++; cpustate->_D = cpustate->_HY; } /* LD D,HY */
+OP(fd,55) { cpustate->R++; cpustate->_D = cpustate->_LY; } /* LD D,LY */
+OP(fd,56) { cpustate->R++; EAY(cpustate); cpustate->_D = RM(cpustate, cpustate->ea); } /* LD D,(IY+o) */
+OP(fd,57) { illegal_1(cpustate); op_57(cpustate); } /* DB FD */
+
+OP(fd,58) { illegal_1(cpustate); op_58(cpustate); } /* DB FD */
+OP(fd,59) { illegal_1(cpustate); op_59(cpustate); } /* DB FD */
+OP(fd,5a) { illegal_1(cpustate); op_5a(cpustate); } /* DB FD */
+OP(fd,5b) { illegal_1(cpustate); op_5b(cpustate); } /* DB FD */
+OP(fd,5c) { cpustate->R++; cpustate->_E = cpustate->_HY; } /* LD E,HY */
+OP(fd,5d) { cpustate->R++; cpustate->_E = cpustate->_LY; } /* LD E,LY */
+OP(fd,5e) { cpustate->R++; EAY(cpustate); cpustate->_E = RM(cpustate, cpustate->ea); } /* LD E,(IY+o) */
+OP(fd,5f) { illegal_1(cpustate); op_5f(cpustate); } /* DB FD */
+
+OP(fd,60) { cpustate->R++; cpustate->_HY = cpustate->_B; } /* LD HY,B */
+OP(fd,61) { cpustate->R++; cpustate->_HY = cpustate->_C; } /* LD HY,C */
+OP(fd,62) { cpustate->R++; cpustate->_HY = cpustate->_D; } /* LD HY,D */
+OP(fd,63) { cpustate->R++; cpustate->_HY = cpustate->_E; } /* LD HY,E */
+OP(fd,64) { cpustate->R++; } /* LD HY,HY */
+OP(fd,65) { cpustate->R++; cpustate->_HY = cpustate->_LY; } /* LD HY,LY */
+OP(fd,66) { cpustate->R++; EAY(cpustate); cpustate->_H = RM(cpustate, cpustate->ea); } /* LD H,(IY+o) */
+OP(fd,67) { cpustate->R++; cpustate->_HY = cpustate->_A; } /* LD HY,A */
+
+OP(fd,68) { cpustate->R++; cpustate->_LY = cpustate->_B; } /* LD LY,B */
+OP(fd,69) { cpustate->R++; cpustate->_LY = cpustate->_C; } /* LD LY,C */
+OP(fd,6a) { cpustate->R++; cpustate->_LY = cpustate->_D; } /* LD LY,D */
+OP(fd,6b) { cpustate->R++; cpustate->_LY = cpustate->_E; } /* LD LY,E */
+OP(fd,6c) { cpustate->R++; cpustate->_LY = cpustate->_HY; } /* LD LY,HY */
+OP(fd,6d) { cpustate->R++; } /* LD LY,LY */
+OP(fd,6e) { cpustate->R++; EAY(cpustate); cpustate->_L = RM(cpustate, cpustate->ea); } /* LD L,(IY+o) */
+OP(fd,6f) { cpustate->R++; cpustate->_LY = cpustate->_A; } /* LD LY,A */
+
+OP(fd,70) { cpustate->R++; EAY(cpustate); WM(cpustate, cpustate->ea, cpustate->_B ); } /* LD (IY+o),B */
+OP(fd,71) { cpustate->R++; EAY(cpustate); WM(cpustate, cpustate->ea, cpustate->_C ); } /* LD (IY+o),C */
+OP(fd,72) { cpustate->R++; EAY(cpustate); WM(cpustate, cpustate->ea, cpustate->_D ); } /* LD (IY+o),D */
+OP(fd,73) { cpustate->R++; EAY(cpustate); WM(cpustate, cpustate->ea, cpustate->_E ); } /* LD (IY+o),E */
+OP(fd,74) { cpustate->R++; EAY(cpustate); WM(cpustate, cpustate->ea, cpustate->_H ); } /* LD (IY+o),H */
+OP(fd,75) { cpustate->R++; EAY(cpustate); WM(cpustate, cpustate->ea, cpustate->_L ); } /* LD (IY+o),L */
+OP(fd,76) { illegal_1(cpustate); op_76(cpustate); } /* DB FD */
+OP(fd,77) { cpustate->R++; EAY(cpustate); WM(cpustate, cpustate->ea, cpustate->_A ); } /* LD (IY+o),A */
+
+OP(fd,78) { illegal_1(cpustate); op_78(cpustate); } /* DB FD */
+OP(fd,79) { illegal_1(cpustate); op_79(cpustate); } /* DB FD */
+OP(fd,7a) { illegal_1(cpustate); op_7a(cpustate); } /* DB FD */
+OP(fd,7b) { illegal_1(cpustate); op_7b(cpustate); } /* DB FD */
+OP(fd,7c) { cpustate->R++; cpustate->_A = cpustate->_HY; } /* LD A,HY */
+OP(fd,7d) { cpustate->R++; cpustate->_A = cpustate->_LY; } /* LD A,LY */
+OP(fd,7e) { cpustate->R++; EAY(cpustate); cpustate->_A = RM(cpustate, cpustate->ea); } /* LD A,(IY+o) */
+OP(fd,7f) { illegal_1(cpustate); op_7f(cpustate); } /* DB FD */
+
+OP(fd,80) { illegal_1(cpustate); op_80(cpustate); } /* DB FD */
+OP(fd,81) { illegal_1(cpustate); op_81(cpustate); } /* DB FD */
+OP(fd,82) { illegal_1(cpustate); op_82(cpustate); } /* DB FD */
+OP(fd,83) { illegal_1(cpustate); op_83(cpustate); } /* DB FD */
+OP(fd,84) { cpustate->R++; ADD(cpustate->_HY); } /* ADD A,HY */
+OP(fd,85) { cpustate->R++; ADD(cpustate->_LY); } /* ADD A,LY */
+OP(fd,86) { cpustate->R++; EAY(cpustate); ADD(RM(cpustate, cpustate->ea)); } /* ADD A,(IY+o) */
+OP(fd,87) { illegal_1(cpustate); op_87(cpustate); } /* DB FD */
+
+OP(fd,88) { illegal_1(cpustate); op_88(cpustate); } /* DB FD */
+OP(fd,89) { illegal_1(cpustate); op_89(cpustate); } /* DB FD */
+OP(fd,8a) { illegal_1(cpustate); op_8a(cpustate); } /* DB FD */
+OP(fd,8b) { illegal_1(cpustate); op_8b(cpustate); } /* DB FD */
+OP(fd,8c) { cpustate->R++; ADC(cpustate->_HY); } /* ADC A,HY */
+OP(fd,8d) { cpustate->R++; ADC(cpustate->_LY); } /* ADC A,LY */
+OP(fd,8e) { cpustate->R++; EAY(cpustate); ADC(RM(cpustate, cpustate->ea)); } /* ADC A,(IY+o) */
+OP(fd,8f) { illegal_1(cpustate); op_8f(cpustate); } /* DB FD */
+
+OP(fd,90) { illegal_1(cpustate); op_90(cpustate); } /* DB FD */
+OP(fd,91) { illegal_1(cpustate); op_91(cpustate); } /* DB FD */
+OP(fd,92) { illegal_1(cpustate); op_92(cpustate); } /* DB FD */
+OP(fd,93) { illegal_1(cpustate); op_93(cpustate); } /* DB FD */
+OP(fd,94) { cpustate->R++; SUB(cpustate->_HY); } /* SUB HY */
+OP(fd,95) { cpustate->R++; SUB(cpustate->_LY); } /* SUB LY */
+OP(fd,96) { cpustate->R++; EAY(cpustate); SUB(RM(cpustate, cpustate->ea)); } /* SUB (IY+o) */
+OP(fd,97) { illegal_1(cpustate); op_97(cpustate); } /* DB FD */
+
+OP(fd,98) { illegal_1(cpustate); op_98(cpustate); } /* DB FD */
+OP(fd,99) { illegal_1(cpustate); op_99(cpustate); } /* DB FD */
+OP(fd,9a) { illegal_1(cpustate); op_9a(cpustate); } /* DB FD */
+OP(fd,9b) { illegal_1(cpustate); op_9b(cpustate); } /* DB FD */
+OP(fd,9c) { cpustate->R++; SBC(cpustate->_HY); } /* SBC A,HY */
+OP(fd,9d) { cpustate->R++; SBC(cpustate->_LY); } /* SBC A,LY */
+OP(fd,9e) { cpustate->R++; EAY(cpustate); SBC(RM(cpustate, cpustate->ea)); } /* SBC A,(IY+o) */
+OP(fd,9f) { illegal_1(cpustate); op_9f(cpustate); } /* DB FD */
+
+OP(fd,a0) { illegal_1(cpustate); op_a0(cpustate); } /* DB FD */
+OP(fd,a1) { illegal_1(cpustate); op_a1(cpustate); } /* DB FD */
+OP(fd,a2) { illegal_1(cpustate); op_a2(cpustate); } /* DB FD */
+OP(fd,a3) { illegal_1(cpustate); op_a3(cpustate); } /* DB FD */
+OP(fd,a4) { cpustate->R++; AND(cpustate->_HY); } /* AND HY */
+OP(fd,a5) { cpustate->R++; AND(cpustate->_LY); } /* AND LY */
+OP(fd,a6) { cpustate->R++; EAY(cpustate); AND(RM(cpustate, cpustate->ea)); } /* AND (IY+o) */
+OP(fd,a7) { illegal_1(cpustate); op_a7(cpustate); } /* DB FD */
+
+OP(fd,a8) { illegal_1(cpustate); op_a8(cpustate); } /* DB FD */
+OP(fd,a9) { illegal_1(cpustate); op_a9(cpustate); } /* DB FD */
+OP(fd,aa) { illegal_1(cpustate); op_aa(cpustate); } /* DB FD */
+OP(fd,ab) { illegal_1(cpustate); op_ab(cpustate); } /* DB FD */
+OP(fd,ac) { cpustate->R++; XOR(cpustate->_HY); } /* XOR HY */
+OP(fd,ad) { cpustate->R++; XOR(cpustate->_LY); } /* XOR LY */
+OP(fd,ae) { cpustate->R++; EAY(cpustate); XOR(RM(cpustate, cpustate->ea)); } /* XOR (IY+o) */
+OP(fd,af) { illegal_1(cpustate); op_af(cpustate); } /* DB FD */
+
+OP(fd,b0) { illegal_1(cpustate); op_b0(cpustate); } /* DB FD */
+OP(fd,b1) { illegal_1(cpustate); op_b1(cpustate); } /* DB FD */
+OP(fd,b2) { illegal_1(cpustate); op_b2(cpustate); } /* DB FD */
+OP(fd,b3) { illegal_1(cpustate); op_b3(cpustate); } /* DB FD */
+OP(fd,b4) { cpustate->R++; OR(cpustate->_HY); } /* OR HY */
+OP(fd,b5) { cpustate->R++; OR(cpustate->_LY); } /* OR LY */
+OP(fd,b6) { cpustate->R++; EAY(cpustate); OR(RM(cpustate, cpustate->ea)); } /* OR (IY+o) */
+OP(fd,b7) { illegal_1(cpustate); op_b7(cpustate); } /* DB FD */
+
+OP(fd,b8) { illegal_1(cpustate); op_b8(cpustate); } /* DB FD */
+OP(fd,b9) { illegal_1(cpustate); op_b9(cpustate); } /* DB FD */
+OP(fd,ba) { illegal_1(cpustate); op_ba(cpustate); } /* DB FD */
+OP(fd,bb) { illegal_1(cpustate); op_bb(cpustate); } /* DB FD */
+OP(fd,bc) { cpustate->R++; CP(cpustate->_HY); } /* CP HY */
+OP(fd,bd) { cpustate->R++; CP(cpustate->_LY); } /* CP LY */
+OP(fd,be) { cpustate->R++; EAY(cpustate); CP(RM(cpustate, cpustate->ea)); } /* CP (IY+o) */
+OP(fd,bf) { illegal_1(cpustate); op_bf(cpustate); } /* DB FD */
+
+OP(fd,c0) { illegal_1(cpustate); op_c0(cpustate); } /* DB FD */
+OP(fd,c1) { illegal_1(cpustate); op_c1(cpustate); } /* DB FD */
+OP(fd,c2) { illegal_1(cpustate); op_c2(cpustate); } /* DB FD */
+OP(fd,c3) { illegal_1(cpustate); op_c3(cpustate); } /* DB FD */
+OP(fd,c4) { illegal_1(cpustate); op_c4(cpustate); } /* DB FD */
+OP(fd,c5) { illegal_1(cpustate); op_c5(cpustate); } /* DB FD */
+OP(fd,c6) { illegal_1(cpustate); op_c6(cpustate); } /* DB FD */
+OP(fd,c7) { illegal_1(cpustate); op_c7(cpustate); } /* DB FD */
+
+OP(fd,c8) { illegal_1(cpustate); op_c8(cpustate); } /* DB FD */
+OP(fd,c9) { illegal_1(cpustate); op_c9(cpustate); } /* DB FD */
+OP(fd,ca) { illegal_1(cpustate); op_ca(cpustate); } /* DB FD */
+OP(fd,cb) { cpustate->R++; EAY(cpustate); cpustate->extra_cycles += exec_xycb(cpustate,ARG(cpustate)); } /* ** FD CB xx */
+OP(fd,cc) { illegal_1(cpustate); op_cc(cpustate); } /* DB FD */
+OP(fd,cd) { illegal_1(cpustate); op_cd(cpustate); } /* DB FD */
+OP(fd,ce) { illegal_1(cpustate); op_ce(cpustate); } /* DB FD */
+OP(fd,cf) { illegal_1(cpustate); op_cf(cpustate); } /* DB FD */
+
+OP(fd,d0) { illegal_1(cpustate); op_d0(cpustate); } /* DB FD */
+OP(fd,d1) { illegal_1(cpustate); op_d1(cpustate); } /* DB FD */
+OP(fd,d2) { illegal_1(cpustate); op_d2(cpustate); } /* DB FD */
+OP(fd,d3) { illegal_1(cpustate); op_d3(cpustate); } /* DB FD */
+OP(fd,d4) { illegal_1(cpustate); op_d4(cpustate); } /* DB FD */
+OP(fd,d5) { illegal_1(cpustate); op_d5(cpustate); } /* DB FD */
+OP(fd,d6) { illegal_1(cpustate); op_d6(cpustate); } /* DB FD */
+OP(fd,d7) { illegal_1(cpustate); op_d7(cpustate); } /* DB FD */
+
+OP(fd,d8) { illegal_1(cpustate); op_d8(cpustate); } /* DB FD */
+OP(fd,d9) { illegal_1(cpustate); op_d9(cpustate); } /* DB FD */
+OP(fd,da) { illegal_1(cpustate); op_da(cpustate); } /* DB FD */
+OP(fd,db) { illegal_1(cpustate); op_db(cpustate); } /* DB FD */
+OP(fd,dc) { illegal_1(cpustate); op_dc(cpustate); } /* DB FD */
+OP(fd,dd) { illegal_1(cpustate); op_dd(cpustate); } /* DB FD */
+OP(fd,de) { illegal_1(cpustate); op_de(cpustate); } /* DB FD */
+OP(fd,df) { illegal_1(cpustate); op_df(cpustate); } /* DB FD */
+
+OP(fd,e0) { illegal_1(cpustate); op_e0(cpustate); } /* DB FD */
+OP(fd,e1) { cpustate->R++; POP(cpustate, IY); } /* POP IY */
+OP(fd,e2) { illegal_1(cpustate); op_e2(cpustate); } /* DB FD */
+OP(fd,e3) { cpustate->R++; EXSP(IY); } /* EX (SP),IY */
+OP(fd,e4) { illegal_1(cpustate); op_e4(cpustate); } /* DB FD */
+OP(fd,e5) { cpustate->R++; PUSH(cpustate, IY ); } /* PUSH IY */
+OP(fd,e6) { illegal_1(cpustate); op_e6(cpustate); } /* DB FD */
+OP(fd,e7) { illegal_1(cpustate); op_e7(cpustate); } /* DB FD */
+
+OP(fd,e8) { illegal_1(cpustate); op_e8(cpustate); } /* DB FD */
+OP(fd,e9) { cpustate->R++; cpustate->_PC = cpustate->_IY; } /* JP (IY) */
+OP(fd,ea) { illegal_1(cpustate); op_ea(cpustate); } /* DB FD */
+OP(fd,eb) { illegal_1(cpustate); op_eb(cpustate); } /* DB FD */
+OP(fd,ec) { illegal_1(cpustate); op_ec(cpustate); } /* DB FD */
+OP(fd,ed) { illegal_1(cpustate); op_ed(cpustate); } /* DB FD */
+OP(fd,ee) { illegal_1(cpustate); op_ee(cpustate); } /* DB FD */
+OP(fd,ef) { illegal_1(cpustate); op_ef(cpustate); } /* DB FD */
+
+OP(fd,f0) { illegal_1(cpustate); op_f0(cpustate); } /* DB FD */
+OP(fd,f1) { illegal_1(cpustate); op_f1(cpustate); } /* DB FD */
+OP(fd,f2) { illegal_1(cpustate); op_f2(cpustate); } /* DB FD */
+OP(fd,f3) { illegal_1(cpustate); op_f3(cpustate); } /* DB FD */
+OP(fd,f4) { illegal_1(cpustate); op_f4(cpustate); } /* DB FD */
+OP(fd,f5) { illegal_1(cpustate); op_f5(cpustate); } /* DB FD */
+OP(fd,f6) { illegal_1(cpustate); op_f6(cpustate); } /* DB FD */
+OP(fd,f7) { illegal_1(cpustate); op_f7(cpustate); } /* DB FD */
+
+OP(fd,f8) { illegal_1(cpustate); op_f8(cpustate); } /* DB FD */
+OP(fd,f9) { cpustate->R++; cpustate->_SP = cpustate->_IY; } /* LD SP,IY */
+OP(fd,fa) { illegal_1(cpustate); op_fa(cpustate); } /* DB FD */
+OP(fd,fb) { illegal_1(cpustate); op_fb(cpustate); } /* DB FD */
+OP(fd,fc) { illegal_1(cpustate); op_fc(cpustate); } /* DB FD */
+OP(fd,fd) { illegal_1(cpustate); op_fd(cpustate); } /* DB FD */
+OP(fd,fe) { illegal_1(cpustate); op_fe(cpustate); } /* DB FD */
+OP(fd,ff) { illegal_1(cpustate); op_ff(cpustate); } /* DB FD */
+
diff --git a/trunk/src/emu/cpu/z180/z180op.c b/trunk/src/emu/cpu/z180/z180op.c
new file mode 100644
index 00000000000..1dd7018663b
--- /dev/null
+++ b/trunk/src/emu/cpu/z180/z180op.c
@@ -0,0 +1,382 @@
+
+/**********************************************************
+ * main opcodes
+ **********************************************************/
+OP(op,00) { } /* NOP */
+OP(op,01) { cpustate->_BC = ARG16(cpustate); } /* LD BC,w */
+OP(op,02) { WM(cpustate, cpustate->_BC, cpustate->_A ); } /* LD (BC),A */
+OP(op,03) { cpustate->_BC++; } /* INC BC */
+OP(op,04) { cpustate->_B = INC(cpustate, cpustate->_B); } /* INC B */
+OP(op,05) { cpustate->_B = DEC(cpustate, cpustate->_B); } /* DEC B */
+OP(op,06) { cpustate->_B = ARG(cpustate); } /* LD B,n */
+OP(op,07) { RLCA; } /* RLCA */
+
+OP(op,08) { EX_AF; } /* EX AF,AF' */
+OP(op,09) { ADD16(HL,BC); } /* ADD HL,BC */
+OP(op,0a) { cpustate->_A = RM(cpustate, cpustate->_BC); } /* LD A,(BC) */
+OP(op,0b) { cpustate->_BC--; } /* DEC BC */
+OP(op,0c) { cpustate->_C = INC(cpustate, cpustate->_C); } /* INC C */
+OP(op,0d) { cpustate->_C = DEC(cpustate, cpustate->_C); } /* DEC C */
+OP(op,0e) { cpustate->_C = ARG(cpustate); } /* LD C,n */
+OP(op,0f) { RRCA; } /* RRCA */
+
+OP(op,10) { cpustate->_B--; JR_COND( cpustate->_B, 0x10 ); } /* DJNZ o */
+OP(op,11) { cpustate->_DE = ARG16(cpustate); } /* LD DE,w */
+OP(op,12) { WM(cpustate, cpustate->_DE, cpustate->_A ); } /* LD (DE),A */
+OP(op,13) { cpustate->_DE++; } /* INC DE */
+OP(op,14) { cpustate->_D = INC(cpustate, cpustate->_D); } /* INC D */
+OP(op,15) { cpustate->_D = DEC(cpustate, cpustate->_D); } /* DEC D */
+OP(op,16) { cpustate->_D = ARG(cpustate); } /* LD D,n */
+OP(op,17) { RLA; } /* RLA */
+
+OP(op,18) { JR(); } /* JR o */
+OP(op,19) { ADD16(HL,DE); } /* ADD HL,DE */
+OP(op,1a) { cpustate->_A = RM(cpustate, cpustate->_DE); } /* LD A,(DE) */
+OP(op,1b) { cpustate->_DE--; ; } /* DEC DE */
+OP(op,1c) { cpustate->_E = INC(cpustate, cpustate->_E); } /* INC E */
+OP(op,1d) { cpustate->_E = DEC(cpustate, cpustate->_E); } /* DEC E */
+OP(op,1e) { cpustate->_E = ARG(cpustate); } /* LD E,n */
+OP(op,1f) { RRA; } /* RRA */
+
+OP(op,20) { JR_COND( !(cpustate->_F & ZF), 0x20 ); } /* JR NZ,o */
+OP(op,21) { cpustate->_HL = ARG16(cpustate); } /* LD HL,w */
+OP(op,22) { cpustate->ea = ARG16(cpustate); WM16(cpustate, cpustate->ea, &cpustate->HL ); } /* LD (w),HL */
+OP(op,23) { cpustate->_HL++; } /* INC HL */
+OP(op,24) { cpustate->_H = INC(cpustate, cpustate->_H); } /* INC H */
+OP(op,25) { cpustate->_H = DEC(cpustate, cpustate->_H); } /* DEC H */
+OP(op,26) { cpustate->_H = ARG(cpustate); } /* LD H,n */
+OP(op,27) { DAA; } /* DAA */
+
+OP(op,28) { JR_COND( cpustate->_F & ZF, 0x28 ); } /* JR Z,o */
+OP(op,29) { ADD16(HL,HL); } /* ADD HL,HL */
+OP(op,2a) { cpustate->ea = ARG16(cpustate); RM16(cpustate, cpustate->ea, &cpustate->HL ); } /* LD HL,(w) */
+OP(op,2b) { cpustate->_HL--; } /* DEC HL */
+OP(op,2c) { cpustate->_L = INC(cpustate, cpustate->_L); } /* INC L */
+OP(op,2d) { cpustate->_L = DEC(cpustate, cpustate->_L); } /* DEC L */
+OP(op,2e) { cpustate->_L = ARG(cpustate); } /* LD L,n */
+OP(op,2f) { cpustate->_A ^= 0xff; cpustate->_F = (cpustate->_F&(SF|ZF|PF|CF))|HF|NF|(cpustate->_A&(YF|XF)); } /* CPL */
+
+OP(op,30) { JR_COND( !(cpustate->_F & CF), 0x30 ); } /* JR NC,o */
+OP(op,31) { cpustate->_SP = ARG16(cpustate); } /* LD SP,w */
+OP(op,32) { cpustate->ea = ARG16(cpustate); WM(cpustate, cpustate->ea, cpustate->_A ); } /* LD (w),A */
+OP(op,33) { cpustate->_SP++; } /* INC SP */
+OP(op,34) { WM(cpustate, cpustate->_HL, INC(cpustate, RM(cpustate, cpustate->_HL)) ); } /* INC (HL) */
+OP(op,35) { WM(cpustate, cpustate->_HL, DEC(cpustate, RM(cpustate, cpustate->_HL)) ); } /* DEC (HL) */
+OP(op,36) { WM(cpustate, cpustate->_HL, ARG(cpustate) ); } /* LD (HL),n */
+OP(op,37) { cpustate->_F = (cpustate->_F & (SF|ZF|PF)) | CF | (cpustate->_A & (YF|XF)); } /* SCF */
+
+OP(op,38) { JR_COND( cpustate->_F & CF, 0x38 ); } /* JR C,o */
+OP(op,39) { ADD16(HL,SP); } /* ADD HL,SP */
+OP(op,3a) { cpustate->ea = ARG16(cpustate); cpustate->_A = RM(cpustate, cpustate->ea ); } /* LD A,(w) */
+OP(op,3b) { cpustate->_SP--; } /* DEC SP */
+OP(op,3c) { cpustate->_A = INC(cpustate, cpustate->_A); } /* INC A */
+OP(op,3d) { cpustate->_A = DEC(cpustate, cpustate->_A); } /* DEC A */
+OP(op,3e) { cpustate->_A = ARG(cpustate); } /* LD A,n */
+OP(op,3f) { cpustate->_F = ((cpustate->_F&(SF|ZF|PF|CF))|((cpustate->_F&CF)<<4)|(cpustate->_A&(YF|XF)))^CF; } /* CCF */
+//OP(op,3f) { cpustate->_F = ((cpustate->_F & ~(HF|NF)) | ((cpustate->_F & CF)<<4)) ^ CF; } /* CCF */
+
+OP(op,40) { } /* LD B,B */
+OP(op,41) { cpustate->_B = cpustate->_C; } /* LD B,C */
+OP(op,42) { cpustate->_B = cpustate->_D; } /* LD B,D */
+OP(op,43) { cpustate->_B = cpustate->_E; } /* LD B,E */
+OP(op,44) { cpustate->_B = cpustate->_H; } /* LD B,H */
+OP(op,45) { cpustate->_B = cpustate->_L; } /* LD B,L */
+OP(op,46) { cpustate->_B = RM(cpustate, cpustate->_HL); } /* LD B,(HL) */
+OP(op,47) { cpustate->_B = cpustate->_A; } /* LD B,A */
+
+OP(op,48) { cpustate->_C = cpustate->_B; } /* LD C,B */
+OP(op,49) { } /* LD C,C */
+OP(op,4a) { cpustate->_C = cpustate->_D; } /* LD C,D */
+OP(op,4b) { cpustate->_C = cpustate->_E; } /* LD C,E */
+OP(op,4c) { cpustate->_C = cpustate->_H; } /* LD C,H */
+OP(op,4d) { cpustate->_C = cpustate->_L; } /* LD C,L */
+OP(op,4e) { cpustate->_C = RM(cpustate, cpustate->_HL); } /* LD C,(HL) */
+OP(op,4f) { cpustate->_C = cpustate->_A; } /* LD C,A */
+
+OP(op,50) { cpustate->_D = cpustate->_B; } /* LD D,B */
+OP(op,51) { cpustate->_D = cpustate->_C; } /* LD D,C */
+OP(op,52) { } /* LD D,D */
+OP(op,53) { cpustate->_D = cpustate->_E; } /* LD D,E */
+OP(op,54) { cpustate->_D = cpustate->_H; } /* LD D,H */
+OP(op,55) { cpustate->_D = cpustate->_L; } /* LD D,L */
+OP(op,56) { cpustate->_D = RM(cpustate, cpustate->_HL); } /* LD D,(HL) */
+OP(op,57) { cpustate->_D = cpustate->_A; } /* LD D,A */
+
+OP(op,58) { cpustate->_E = cpustate->_B; } /* LD E,B */
+OP(op,59) { cpustate->_E = cpustate->_C; } /* LD E,C */
+OP(op,5a) { cpustate->_E = cpustate->_D; } /* LD E,D */
+OP(op,5b) { } /* LD E,E */
+OP(op,5c) { cpustate->_E = cpustate->_H; } /* LD E,H */
+OP(op,5d) { cpustate->_E = cpustate->_L; } /* LD E,L */
+OP(op,5e) { cpustate->_E = RM(cpustate, cpustate->_HL); } /* LD E,(HL) */
+OP(op,5f) { cpustate->_E = cpustate->_A; } /* LD E,A */
+
+OP(op,60) { cpustate->_H = cpustate->_B; } /* LD H,B */
+OP(op,61) { cpustate->_H = cpustate->_C; } /* LD H,C */
+OP(op,62) { cpustate->_H = cpustate->_D; } /* LD H,D */
+OP(op,63) { cpustate->_H = cpustate->_E; } /* LD H,E */
+OP(op,64) { } /* LD H,H */
+OP(op,65) { cpustate->_H = cpustate->_L; } /* LD H,L */
+OP(op,66) { cpustate->_H = RM(cpustate, cpustate->_HL); } /* LD H,(HL) */
+OP(op,67) { cpustate->_H = cpustate->_A; } /* LD H,A */
+
+OP(op,68) { cpustate->_L = cpustate->_B; } /* LD L,B */
+OP(op,69) { cpustate->_L = cpustate->_C; } /* LD L,C */
+OP(op,6a) { cpustate->_L = cpustate->_D; } /* LD L,D */
+OP(op,6b) { cpustate->_L = cpustate->_E; } /* LD L,E */
+OP(op,6c) { cpustate->_L = cpustate->_H; } /* LD L,H */
+OP(op,6d) { } /* LD L,L */
+OP(op,6e) { cpustate->_L = RM(cpustate, cpustate->_HL); } /* LD L,(HL) */
+OP(op,6f) { cpustate->_L = cpustate->_A; } /* LD L,A */
+
+OP(op,70) { WM(cpustate, cpustate->_HL, cpustate->_B ); } /* LD (HL),B */
+OP(op,71) { WM(cpustate, cpustate->_HL, cpustate->_C ); } /* LD (HL),C */
+OP(op,72) { WM(cpustate, cpustate->_HL, cpustate->_D ); } /* LD (HL),D */
+OP(op,73) { WM(cpustate, cpustate->_HL, cpustate->_E ); } /* LD (HL),E */
+OP(op,74) { WM(cpustate, cpustate->_HL, cpustate->_H ); } /* LD (HL),H */
+OP(op,75) { WM(cpustate, cpustate->_HL, cpustate->_L ); } /* LD (HL),L */
+OP(op,76) { ENTER_HALT(cpustate); } /* HALT */
+OP(op,77) { WM(cpustate, cpustate->_HL, cpustate->_A ); } /* LD (HL),A */
+
+OP(op,78) { cpustate->_A = cpustate->_B; } /* LD A,B */
+OP(op,79) { cpustate->_A = cpustate->_C; } /* LD A,C */
+OP(op,7a) { cpustate->_A = cpustate->_D; } /* LD A,D */
+OP(op,7b) { cpustate->_A = cpustate->_E; } /* LD A,E */
+OP(op,7c) { cpustate->_A = cpustate->_H; } /* LD A,H */
+OP(op,7d) { cpustate->_A = cpustate->_L; } /* LD A,L */
+OP(op,7e) { cpustate->_A = RM(cpustate, cpustate->_HL); } /* LD A,(HL) */
+OP(op,7f) { } /* LD A,A */
+
+OP(op,80) { ADD(cpustate->_B); } /* ADD A,B */
+OP(op,81) { ADD(cpustate->_C); } /* ADD A,C */
+OP(op,82) { ADD(cpustate->_D); } /* ADD A,D */
+OP(op,83) { ADD(cpustate->_E); } /* ADD A,E */
+OP(op,84) { ADD(cpustate->_H); } /* ADD A,H */
+OP(op,85) { ADD(cpustate->_L); } /* ADD A,L */
+OP(op,86) { ADD(RM(cpustate, cpustate->_HL)); } /* ADD A,(HL) */
+OP(op,87) { ADD(cpustate->_A); } /* ADD A,A */
+
+OP(op,88) { ADC(cpustate->_B); } /* ADC A,B */
+OP(op,89) { ADC(cpustate->_C); } /* ADC A,C */
+OP(op,8a) { ADC(cpustate->_D); } /* ADC A,D */
+OP(op,8b) { ADC(cpustate->_E); } /* ADC A,E */
+OP(op,8c) { ADC(cpustate->_H); } /* ADC A,H */
+OP(op,8d) { ADC(cpustate->_L); } /* ADC A,L */
+OP(op,8e) { ADC(RM(cpustate, cpustate->_HL)); } /* ADC A,(HL) */
+OP(op,8f) { ADC(cpustate->_A); } /* ADC A,A */
+
+OP(op,90) { SUB(cpustate->_B); } /* SUB B */
+OP(op,91) { SUB(cpustate->_C); } /* SUB C */
+OP(op,92) { SUB(cpustate->_D); } /* SUB D */
+OP(op,93) { SUB(cpustate->_E); } /* SUB E */
+OP(op,94) { SUB(cpustate->_H); } /* SUB H */
+OP(op,95) { SUB(cpustate->_L); } /* SUB L */
+OP(op,96) { SUB(RM(cpustate, cpustate->_HL)); } /* SUB (HL) */
+OP(op,97) { SUB(cpustate->_A); } /* SUB A */
+
+OP(op,98) { SBC(cpustate->_B); } /* SBC A,B */
+OP(op,99) { SBC(cpustate->_C); } /* SBC A,C */
+OP(op,9a) { SBC(cpustate->_D); } /* SBC A,D */
+OP(op,9b) { SBC(cpustate->_E); } /* SBC A,E */
+OP(op,9c) { SBC(cpustate->_H); } /* SBC A,H */
+OP(op,9d) { SBC(cpustate->_L); } /* SBC A,L */
+OP(op,9e) { SBC(RM(cpustate, cpustate->_HL)); } /* SBC A,(HL) */
+OP(op,9f) { SBC(cpustate->_A); } /* SBC A,A */
+
+OP(op,a0) { AND(cpustate->_B); } /* AND B */
+OP(op,a1) { AND(cpustate->_C); } /* AND C */
+OP(op,a2) { AND(cpustate->_D); } /* AND D */
+OP(op,a3) { AND(cpustate->_E); } /* AND E */
+OP(op,a4) { AND(cpustate->_H); } /* AND H */
+OP(op,a5) { AND(cpustate->_L); } /* AND L */
+OP(op,a6) { AND(RM(cpustate, cpustate->_HL)); } /* AND (HL) */
+OP(op,a7) { AND(cpustate->_A); } /* AND A */
+
+OP(op,a8) { XOR(cpustate->_B); } /* XOR B */
+OP(op,a9) { XOR(cpustate->_C); } /* XOR C */
+OP(op,aa) { XOR(cpustate->_D); } /* XOR D */
+OP(op,ab) { XOR(cpustate->_E); } /* XOR E */
+OP(op,ac) { XOR(cpustate->_H); } /* XOR H */
+OP(op,ad) { XOR(cpustate->_L); } /* XOR L */
+OP(op,ae) { XOR(RM(cpustate, cpustate->_HL)); } /* XOR (HL) */
+OP(op,af) { XOR(cpustate->_A); } /* XOR A */
+
+OP(op,b0) { OR(cpustate->_B); } /* OR B */
+OP(op,b1) { OR(cpustate->_C); } /* OR C */
+OP(op,b2) { OR(cpustate->_D); } /* OR D */
+OP(op,b3) { OR(cpustate->_E); } /* OR E */
+OP(op,b4) { OR(cpustate->_H); } /* OR H */
+OP(op,b5) { OR(cpustate->_L); } /* OR L */
+OP(op,b6) { OR(RM(cpustate, cpustate->_HL)); } /* OR (HL) */
+OP(op,b7) { OR(cpustate->_A); } /* OR A */
+
+OP(op,b8) { CP(cpustate->_B); } /* CP B */
+OP(op,b9) { CP(cpustate->_C); } /* CP C */
+OP(op,ba) { CP(cpustate->_D); } /* CP D */
+OP(op,bb) { CP(cpustate->_E); } /* CP E */
+OP(op,bc) { CP(cpustate->_H); } /* CP H */
+OP(op,bd) { CP(cpustate->_L); } /* CP L */
+OP(op,be) { CP(RM(cpustate, cpustate->_HL)); } /* CP (HL) */
+OP(op,bf) { CP(cpustate->_A); } /* CP A */
+
+OP(op,c0) { RET_COND( !(cpustate->_F & ZF), 0xc0 ); } /* RET NZ */
+OP(op,c1) { POP(cpustate, BC); } /* POP BC */
+OP(op,c2) { JP_COND( !(cpustate->_F & ZF) ); } /* JP NZ,a */
+OP(op,c3) { JP; } /* JP a */
+OP(op,c4) { CALL_COND( !(cpustate->_F & ZF), 0xc4 ); } /* CALL NZ,a */
+OP(op,c5) { PUSH(cpustate, BC ); } /* PUSH BC */
+OP(op,c6) { ADD(ARG(cpustate)); } /* ADD A,n */
+OP(op,c7) { RST(0x00); } /* RST 0 */
+
+OP(op,c8) { RET_COND( cpustate->_F & ZF, 0xc8 ); } /* RET Z */
+OP(op,c9) { POP(cpustate, PC); } /* RET */
+OP(op,ca) { JP_COND( cpustate->_F & ZF ); } /* JP Z,a */
+OP(op,cb) { cpustate->R++; cpustate->extra_cycles += exec_cb(cpustate,ROP(cpustate)); } /* **** CB xx */
+OP(op,cc) { CALL_COND( cpustate->_F & ZF, 0xcc ); } /* CALL Z,a */
+OP(op,cd) { CALL(); } /* CALL a */
+OP(op,ce) { ADC(ARG(cpustate)); } /* ADC A,n */
+OP(op,cf) { RST(0x08); } /* RST 1 */
+
+OP(op,d0) { RET_COND( !(cpustate->_F & CF), 0xd0 ); } /* RET NC */
+OP(op,d1) { POP(cpustate, DE); } /* POP DE */
+OP(op,d2) { JP_COND( !(cpustate->_F & CF) ); } /* JP NC,a */
+OP(op,d3) { unsigned n = ARG(cpustate) | (cpustate->_A << 8); OUT( cpustate, n, cpustate->_A ); } /* OUT (n),A */
+OP(op,d4) { CALL_COND( !(cpustate->_F & CF), 0xd4 ); } /* CALL NC,a */
+OP(op,d5) { PUSH(cpustate, DE ); } /* PUSH DE */
+OP(op,d6) { SUB(ARG(cpustate)); } /* SUB n */
+OP(op,d7) { RST(0x10); } /* RST 2 */
+
+OP(op,d8) { RET_COND( cpustate->_F & CF, 0xd8 ); } /* RET C */
+OP(op,d9) { EXX; } /* EXX */
+OP(op,da) { JP_COND( cpustate->_F & CF ); } /* JP C,a */
+OP(op,db) { unsigned n = ARG(cpustate) | (cpustate->_A << 8); cpustate->_A = IN( cpustate, n ); } /* IN A,(n) */
+OP(op,dc) { CALL_COND( cpustate->_F & CF, 0xdc ); } /* CALL C,a */
+OP(op,dd) { cpustate->R++; cpustate->extra_cycles += exec_dd(cpustate,ROP(cpustate)); } /* **** DD xx */
+OP(op,de) { SBC(ARG(cpustate)); } /* SBC A,n */
+OP(op,df) { RST(0x18); } /* RST 3 */
+
+OP(op,e0) { RET_COND( !(cpustate->_F & PF), 0xe0 ); } /* RET PO */
+OP(op,e1) { POP(cpustate, HL); } /* POP HL */
+OP(op,e2) { JP_COND( !(cpustate->_F & PF) ); } /* JP PO,a */
+OP(op,e3) { EXSP(HL); } /* EX HL,(SP) */
+OP(op,e4) { CALL_COND( !(cpustate->_F & PF), 0xe4 ); } /* CALL PO,a */
+OP(op,e5) { PUSH(cpustate, HL ); } /* PUSH HL */
+OP(op,e6) { AND(ARG(cpustate)); } /* AND n */
+OP(op,e7) { RST(0x20); } /* RST 4 */
+
+OP(op,e8) { RET_COND( cpustate->_F & PF, 0xe8 ); } /* RET PE */
+OP(op,e9) { cpustate->_PC = cpustate->_HL; } /* JP (HL) */
+OP(op,ea) { JP_COND( cpustate->_F & PF ); } /* JP PE,a */
+OP(op,eb) { EX_DE_HL; } /* EX DE,HL */
+OP(op,ec) { CALL_COND( cpustate->_F & PF, 0xec ); } /* CALL PE,a */
+OP(op,ed) { cpustate->R++; cpustate->extra_cycles += exec_ed(cpustate,ROP(cpustate)); } /* **** ED xx */
+OP(op,ee) { XOR(ARG(cpustate)); } /* XOR n */
+OP(op,ef) { RST(0x28); } /* RST 5 */
+
+OP(op,f0) { RET_COND( !(cpustate->_F & SF), 0xf0 ); } /* RET P */
+OP(op,f1) { POP(cpustate, AF); } /* POP AF */
+OP(op,f2) { JP_COND( !(cpustate->_F & SF) ); } /* JP P,a */
+OP(op,f3) { cpustate->IFF1 = cpustate->IFF2 = 0; } /* DI */
+OP(op,f4) { CALL_COND( !(cpustate->_F & SF), 0xf4 ); } /* CALL P,a */
+OP(op,f5) { PUSH(cpustate, AF ); } /* PUSH AF */
+OP(op,f6) { OR(ARG(cpustate)); } /* OR n */
+OP(op,f7) { RST(0x30); } /* RST 6 */
+
+OP(op,f8) { RET_COND( cpustate->_F & SF, 0xf8 ); } /* RET M */
+OP(op,f9) { cpustate->_SP = cpustate->_HL; } /* LD SP,HL */
+OP(op,fa) { JP_COND(cpustate->_F & SF); } /* JP M,a */
+OP(op,fb) { EI; } /* EI */
+OP(op,fc) { CALL_COND( cpustate->_F & SF, 0xfc ); } /* CALL M,a */
+OP(op,fd) { cpustate->R++; cpustate->extra_cycles += exec_fd(cpustate,ROP(cpustate)); } /* **** FD xx */
+OP(op,fe) { CP(ARG(cpustate)); } /* CP n */
+OP(op,ff) { RST(0x38); } /* RST 7 */
+
+
+static int take_interrupt(z180_state *cpustate, int irq)
+{
+ int irq_vector;
+ int cycles = 0;
+
+ /* there isn't a valid previous program counter */
+ cpustate->_PPC = -1;
+
+ /* Check if processor was halted */
+ LEAVE_HALT(cpustate);
+
+ /* Clear both interrupt flip flops */
+ cpustate->IFF1 = cpustate->IFF2 = 0;
+
+ if( irq == Z180_INT_IRQ0 )
+ {
+ /* Daisy chain mode? If so, call the requesting device */
+ if (cpustate->daisy.present())
+ irq_vector = cpustate->daisy.call_ack_device();
+
+ /* else call back the cpu interface to retrieve the vector */
+ else
+ irq_vector = (*cpustate->irq_callback)(cpustate->device, 0);
+
+ LOG(("Z180 '%s' single int. irq_vector $%02x\n", cpustate->device->tag(), irq_vector));
+
+ /* Interrupt mode 2. Call [cpustate->I:databyte] */
+ if( cpustate->IM == 2 )
+ {
+ irq_vector = (irq_vector & 0xff) + (cpustate->I << 8);
+ PUSH(cpustate, PC );
+ RM16( cpustate, irq_vector, &cpustate->PC );
+ LOG(("Z180 '%s' IM2 [$%04x] = $%04x\n",cpustate->device->tag() , irq_vector, cpustate->_PCD));
+ /* CALL opcode timing */
+ cycles += cpustate->cc[Z180_TABLE_op][0xcd];
+ }
+ else
+ /* Interrupt mode 1. RST 38h */
+ if( cpustate->IM == 1 )
+ {
+ LOG(("Z180 '%s' IM1 $0038\n",cpustate->device->tag() ));
+ PUSH(cpustate, PC );
+ cpustate->_PCD = 0x0038;
+ /* RST $38 + 'interrupt latency' cycles */
+ cycles += cpustate->cc[Z180_TABLE_op][0xff] - cpustate->cc[Z180_TABLE_ex][0xff];
+ }
+ else
+ {
+ /* Interrupt mode 0. We check for CALL and JP instructions, */
+ /* if neither of these were found we assume a 1 byte opcode */
+ /* was placed on the databus */
+ LOG(("Z180 '%s' IM0 $%04x\n",cpustate->device->tag() , irq_vector));
+ switch (irq_vector & 0xff0000)
+ {
+ case 0xcd0000: /* call */
+ PUSH(cpustate, PC );
+ cpustate->_PCD = irq_vector & 0xffff;
+ /* CALL $xxxx + 'interrupt latency' cycles */
+ cycles += cpustate->cc[Z180_TABLE_op][0xcd] - cpustate->cc[Z180_TABLE_ex][0xff];
+ break;
+ case 0xc30000: /* jump */
+ cpustate->_PCD = irq_vector & 0xffff;
+ /* JP $xxxx + 2 cycles */
+ cycles += cpustate->cc[Z180_TABLE_op][0xc3] - cpustate->cc[Z180_TABLE_ex][0xff];
+ break;
+ default: /* rst (or other opcodes?) */
+ PUSH(cpustate, PC );
+ cpustate->_PCD = irq_vector & 0x0038;
+ /* RST $xx + 2 cycles */
+ cycles += cpustate->cc[Z180_TABLE_op][cpustate->_PCD] - cpustate->cc[Z180_TABLE_ex][cpustate->_PCD];
+ break;
+ }
+ }
+ }
+ else
+ {
+ irq_vector = (cpustate->IO(Z180_IL) & Z180_IL_IL) + (irq - Z180_INT_IRQ1) * 2;
+ irq_vector = (cpustate->I << 8) + (irq_vector & 0xff);
+ PUSH(cpustate, PC );
+ RM16( cpustate, irq_vector, &cpustate->PC );
+ LOG(("Z180 '%s' INT%d [$%04x] = $%04x\n", cpustate->device->tag(), irq, irq_vector, cpustate->_PCD));
+ /* CALL opcode timing */
+ cycles += cpustate->cc[Z180_TABLE_op][0xcd];
+ }
+
+ return cycles;
+}
+
diff --git a/trunk/src/emu/cpu/z180/z180ops.h b/trunk/src/emu/cpu/z180/z180ops.h
new file mode 100644
index 00000000000..b2efef210cb
--- /dev/null
+++ b/trunk/src/emu/cpu/z180/z180ops.h
@@ -0,0 +1,954 @@
+/***************************************************************
+ * Enter HALT state; write 1 to fake port on first execution
+ ***************************************************************/
+#define ENTER_HALT(cs) { \
+ (cs)->_PC--; \
+ (cs)->HALT = 1; \
+}
+
+/***************************************************************
+ * Leave HALT state; write 0 to fake port
+ ***************************************************************/
+#define LEAVE_HALT(cs) { \
+ if( (cs)->HALT ) \
+ { \
+ (cs)->HALT = 0; \
+ (cs)->_PC++; \
+ } \
+}
+
+/***************************************************************
+ * Input a byte from given I/O port
+ ***************************************************************/
+#define IN(cs,port) \
+ (((port ^ (cs)->IO_IOCR) & 0xffc0) == 0) ? \
+ z180_readcontrol(cs, port) : (cs)->iospace->read_byte(port)
+
+/***************************************************************
+ * Output a byte to given I/O port
+ ***************************************************************/
+#define OUT(cs,port,value) \
+ if (((port ^ (cs)->IO_IOCR) & 0xffc0) == 0) \
+ z180_writecontrol(cs,port,value); \
+ else (cs)->iospace->write_byte(port,value)
+
+/***************************************************************
+ * MMU calculate the memory managemant lookup table
+ * bb and cb specify a 4K page
+ * If the 4 most significant bits of an 16 bit address are
+ * greater or equal to the bank base, the bank base register
+ * specifies the 4K offset into the 20 bit address space.
+ * If the 4 bits are also greater or equal to the common base,
+ * the common base register is used to specify the offset.
+ ***************************************************************/
+INLINE void z180_mmu(z180_state *cpustate)
+{
+ offs_t addr, page, bb, cb;
+ bb = cpustate->IO_CBAR & 15;
+ cb = cpustate->IO_CBAR >> 4;
+ for( page = 0; page < 16; page++ )
+ {
+ addr = page << 12;
+ if (page >= bb)
+ {
+ if (page >= cb)
+ addr += (cpustate->IO_CBR << 12);
+ else
+ addr += (cpustate->IO_BBR << 12);
+ }
+ cpustate->mmu[page] = (addr & 0xfffff);
+ }
+}
+
+
+#define MMU_REMAP_ADDR(cs,addr) ((cs)->mmu[((addr)>>12)&15]|((addr)&4095))
+
+/***************************************************************
+ * Read a byte from given memory location
+ ***************************************************************/
+#define RM(cs,addr) (cs)->program->read_byte(MMU_REMAP_ADDR(cs,addr))
+#ifdef UNUSED_FUNCTION
+UINT8 z180_readmem(device_t *device, offs_t offset)
+{
+ z180_state *cpustate = get_safe_token(device);
+ return RM(cpustate, offset);
+}
+#endif
+
+/***************************************************************
+ * Write a byte to given memory location
+ ***************************************************************/
+#define WM(cs,addr,value) (cs)->program->write_byte(MMU_REMAP_ADDR(cs,addr),value)
+#ifdef UNUSED_FUNCTION
+void z180_writemem(device_t *device, offs_t offset, UINT8 data)
+{
+ z180_state *cpustate = get_safe_token(device);
+ WM(cpustate, offset, data);
+}
+#endif
+
+/***************************************************************
+ * Read a word from given memory location
+ ***************************************************************/
+INLINE void RM16( z180_state *cpustate, offs_t addr, PAIR *r )
+{
+ r->b.l = RM(cpustate, addr);
+ r->b.h = RM(cpustate, addr+1);
+}
+
+/***************************************************************
+ * Write a word to given memory location
+ ***************************************************************/
+INLINE void WM16( z180_state *cpustate, offs_t addr, PAIR *r )
+{
+ WM(cpustate, addr, r->b.l);
+ WM(cpustate, addr+1, r->b.h);
+}
+
+/***************************************************************
+ * ROP(cpustate) is identical to RM() except it is used for
+ * reading opcodes. In case of system with memory mapped I/O,
+ * this function can be used to greatly speed up emulation
+ ***************************************************************/
+INLINE UINT8 ROP(z180_state *cpustate)
+{
+ offs_t addr = cpustate->_PCD;
+ cpustate->_PC++;
+ return cpustate->direct->read_decrypted_byte(MMU_REMAP_ADDR(cpustate, addr));
+}
+
+/****************************************************************
+ * ARG(cpustate) is identical to ROP(cpustate) except it is used
+ * for reading opcode arguments. This difference can be used to
+ * support systems that use different encoding mechanisms for
+ * opcodes and opcode arguments
+ ***************************************************************/
+INLINE UINT8 ARG(z180_state *cpustate)
+{
+ offs_t addr = cpustate->_PCD;
+ cpustate->_PC++;
+ return cpustate->direct->read_raw_byte(MMU_REMAP_ADDR(cpustate, addr));
+}
+
+INLINE UINT32 ARG16(z180_state *cpustate)
+{
+ offs_t addr = cpustate->_PCD;
+ cpustate->_PC += 2;
+ return cpustate->direct->read_raw_byte(MMU_REMAP_ADDR(cpustate, addr)) | (cpustate->direct->read_raw_byte(MMU_REMAP_ADDR(cpustate, addr+1)) << 8);
+}
+
+/***************************************************************
+ * Calculate the effective addess cpustate->ea of an opcode using
+ * IX+offset resp. IY+offset addressing.
+ ***************************************************************/
+#define EAX(cs) (cs)->ea = (UINT32)(UINT16)((cs)->_IX + (INT8)ARG(cs))
+#define EAY(cs) (cs)->ea = (UINT32)(UINT16)((cs)->_IY + (INT8)ARG(cs))
+
+/***************************************************************
+ * POP
+ ***************************************************************/
+#define POP(cs,DR) { RM16(cs, (cs)->_SPD, &(cs)->DR ); (cs)->_SP += 2; }
+
+/***************************************************************
+ * PUSH
+ ***************************************************************/
+#define PUSH(cs,SR) { (cs)->_SP -= 2; WM16(cs, (cs)->_SPD, &(cs)->SR); }
+
+/***************************************************************
+ * JP
+ ***************************************************************/
+#define JP { \
+ cpustate->_PCD = ARG16(cpustate); \
+}
+
+/***************************************************************
+ * JP_COND
+ ***************************************************************/
+
+#define JP_COND(cond) \
+ if( cond ) \
+ { \
+ cpustate->_PCD = ARG16(cpustate); \
+ } \
+ else \
+ { \
+ cpustate->_PC += 2; \
+ }
+
+/***************************************************************
+ * JR
+ ***************************************************************/
+#define JR() \
+{ \
+ INT8 arg = (INT8)ARG(cpustate); /* ARG(cpustate) also increments cpustate->_PC */ \
+ cpustate->_PC += arg; /* so don't do cpustate->_PC += ARG(cpustate) */ \
+}
+
+/***************************************************************
+ * JR_COND
+ ***************************************************************/
+#define JR_COND(cond,opcode) \
+ if( cond ) \
+ { \
+ INT8 arg = (INT8)ARG(cpustate); /* ARG(cpustate) also increments cpustate->_PC */ \
+ cpustate->_PC += arg; /* so don't do cpustate->_PC += ARG(cpustate) */ \
+ CC(ex,opcode); \
+ } \
+ else cpustate->_PC++; \
+
+/***************************************************************
+ * CALL
+ ***************************************************************/
+#define CALL() \
+ cpustate->ea = ARG16(cpustate); \
+ PUSH(cpustate, PC ); \
+ cpustate->_PCD = cpustate->ea;
+
+/***************************************************************
+ * CALL_COND
+ ***************************************************************/
+#define CALL_COND(cond,opcode) \
+ if( cond ) \
+ { \
+ cpustate->ea = ARG16(cpustate); \
+ PUSH(cpustate, PC ); \
+ cpustate->_PCD = cpustate->ea; \
+ CC(ex,opcode); \
+ } \
+ else \
+ { \
+ cpustate->_PC+=2; \
+ }
+
+/***************************************************************
+ * RET_COND
+ ***************************************************************/
+#define RET_COND(cond,opcode) \
+ if( cond ) \
+ { \
+ POP(cpustate, PC); \
+ CC(ex,opcode); \
+ }
+
+/***************************************************************
+ * RETN
+ ***************************************************************/
+#define RETN { \
+ LOG(("Z180 '%s' RETN IFF1:%d IFF2:%d\n", cpustate->device->tag(), cpustate->IFF1, cpustate->IFF2)); \
+ POP(cpustate, PC); \
+ cpustate->IFF1 = cpustate->IFF2; \
+}
+
+/***************************************************************
+ * RETI
+ ***************************************************************/
+#define RETI { \
+ POP(cpustate, PC); \
+/* according to http://www.msxnet.org/tech/Z80/z80undoc.txt */ \
+/* cpustate->IFF1 = cpustate->IFF2; */ \
+ cpustate->daisy.call_reti_device(); \
+}
+
+/***************************************************************
+ * LD R,A
+ ***************************************************************/
+#define LD_R_A { \
+ cpustate->R = cpustate->_A; \
+ cpustate->R2 = cpustate->_A & 0x80; /* keep bit 7 of R */ \
+}
+
+/***************************************************************
+ * LD A,R
+ ***************************************************************/
+#define LD_A_R { \
+ cpustate->_A = (cpustate->R & 0x7f) | cpustate->R2; \
+ cpustate->_F = (cpustate->_F & CF) | SZ[cpustate->_A] | ( cpustate->IFF2 << 2 ); \
+}
+
+/***************************************************************
+ * LD I,A
+ ***************************************************************/
+#define LD_I_A { \
+ cpustate->I = cpustate->_A; \
+}
+
+/***************************************************************
+ * LD A,I
+ ***************************************************************/
+#define LD_A_I { \
+ cpustate->_A = cpustate->I; \
+ cpustate->_F = (cpustate->_F & CF) | SZ[cpustate->_A] | ( cpustate->IFF2 << 2 ); \
+}
+
+/***************************************************************
+ * RST
+ ***************************************************************/
+#define RST(addr) \
+ PUSH(cpustate, PC ); \
+ cpustate->_PCD = addr;
+
+/***************************************************************
+ * INC r8
+ ***************************************************************/
+INLINE UINT8 INC(z180_state *cpustate, UINT8 value)
+{
+ UINT8 res = value + 1;
+ cpustate->_F = (cpustate->_F & CF) | SZHV_inc[res];
+ return (UINT8)res;
+}
+
+/***************************************************************
+ * DEC r8
+ ***************************************************************/
+INLINE UINT8 DEC(z180_state *cpustate, UINT8 value)
+{
+ UINT8 res = value - 1;
+ cpustate->_F = (cpustate->_F & CF) | SZHV_dec[res];
+ return res;
+}
+
+/***************************************************************
+ * RLCA
+ ***************************************************************/
+#define RLCA \
+ cpustate->_A = (cpustate->_A << 1) | (cpustate->_A >> 7); \
+ cpustate->_F = (cpustate->_F & (SF | ZF | PF)) | (cpustate->_A & (YF | XF | CF))
+
+/***************************************************************
+ * RRCA
+ ***************************************************************/
+#define RRCA \
+ cpustate->_F = (cpustate->_F & (SF | ZF | PF)) | (cpustate->_A & (YF | XF | CF)); \
+ cpustate->_A = (cpustate->_A >> 1) | (cpustate->_A << 7)
+
+/***************************************************************
+ * RLA
+ ***************************************************************/
+#define RLA { \
+ UINT8 res = (cpustate->_A << 1) | (cpustate->_F & CF); \
+ UINT8 c = (cpustate->_A & 0x80) ? CF : 0; \
+ cpustate->_F = (cpustate->_F & (SF | ZF | PF)) | c | (res & (YF | XF)); \
+ cpustate->_A = res; \
+}
+
+/***************************************************************
+ * RRA
+ ***************************************************************/
+#define RRA { \
+ UINT8 res = (cpustate->_A >> 1) | (cpustate->_F << 7); \
+ UINT8 c = (cpustate->_A & 0x01) ? CF : 0; \
+ cpustate->_F = (cpustate->_F & (SF | ZF | PF)) | c | (res & (YF | XF)); \
+ cpustate->_A = res; \
+}
+
+/***************************************************************
+ * RRD
+ ***************************************************************/
+#define RRD { \
+ UINT8 n = RM(cpustate, cpustate->_HL); \
+ WM(cpustate, cpustate->_HL, (n >> 4) | (cpustate->_A << 4) ); \
+ cpustate->_A = (cpustate->_A & 0xf0) | (n & 0x0f); \
+ cpustate->_F = (cpustate->_F & CF) | SZP[cpustate->_A]; \
+}
+
+/***************************************************************
+ * RLD
+ ***************************************************************/
+#define RLD { \
+ UINT8 n = RM(cpustate, cpustate->_HL); \
+ WM(cpustate, cpustate->_HL, (n << 4) | (cpustate->_A & 0x0f) ); \
+ cpustate->_A = (cpustate->_A & 0xf0) | (n >> 4); \
+ cpustate->_F = (cpustate->_F & CF) | SZP[cpustate->_A]; \
+}
+
+/***************************************************************
+ * ADD A,n
+ ***************************************************************/
+#define ADD(value) \
+{ \
+ UINT32 ah = cpustate->_AFD & 0xff00; \
+ UINT32 res = (UINT8)((ah >> 8) + value); \
+ cpustate->_F = SZHVC_add[ah | res]; \
+ cpustate->_A = res; \
+}
+
+/***************************************************************
+ * ADC A,n
+ ***************************************************************/
+#define ADC(value) \
+{ \
+ UINT32 ah = cpustate->_AFD & 0xff00, c = cpustate->_AFD & 1; \
+ UINT32 res = (UINT8)((ah >> 8) + value + c); \
+ cpustate->_F = SZHVC_add[(c << 16) | ah | res]; \
+ cpustate->_A = res; \
+}
+
+/***************************************************************
+ * SUB n
+ ***************************************************************/
+#define SUB(value) \
+{ \
+ UINT32 ah = cpustate->_AFD & 0xff00; \
+ UINT32 res = (UINT8)((ah >> 8) - value); \
+ cpustate->_F = SZHVC_sub[ah | res]; \
+ cpustate->_A = res; \
+}
+
+/***************************************************************
+ * SBC A,n
+ ***************************************************************/
+#define SBC(value) \
+{ \
+ UINT32 ah = cpustate->_AFD & 0xff00, c = cpustate->_AFD & 1; \
+ UINT32 res = (UINT8)((ah >> 8) - value - c); \
+ cpustate->_F = SZHVC_sub[(c<<16) | ah | res]; \
+ cpustate->_A = res; \
+}
+
+/***************************************************************
+ * NEG
+ ***************************************************************/
+#define NEG { \
+ UINT8 value = cpustate->_A; \
+ cpustate->_A = 0; \
+ SUB(value); \
+}
+
+/***************************************************************
+ * DAA
+ ***************************************************************/
+#define DAA { \
+ UINT8 r = cpustate->_A; \
+ if (cpustate->_F&NF) { \
+ if ((cpustate->_F&HF)|((cpustate->_A&0xf)>9)) r-=6; \
+ if ((cpustate->_F&CF)|(cpustate->_A>0x99)) r-=0x60; \
+ } \
+ else { \
+ if ((cpustate->_F&HF)|((cpustate->_A&0xf)>9)) r+=6; \
+ if ((cpustate->_F&CF)|(cpustate->_A>0x99)) r+=0x60; \
+ } \
+ cpustate->_F=(cpustate->_F&3)|(cpustate->_A>0x99)|((cpustate->_A^r)&HF)|SZP[r]; \
+ cpustate->_A=r; \
+}
+
+/***************************************************************
+ * AND n
+ ***************************************************************/
+#define AND(value) \
+ cpustate->_A &= value; \
+ cpustate->_F = SZP[cpustate->_A] | HF
+
+/***************************************************************
+ * OR n
+ ***************************************************************/
+#define OR(value) \
+ cpustate->_A |= value; \
+ cpustate->_F = SZP[cpustate->_A]
+
+/***************************************************************
+ * XOR n
+ ***************************************************************/
+#define XOR(value) \
+ cpustate->_A ^= value; \
+ cpustate->_F = SZP[cpustate->_A]
+
+/***************************************************************
+ * CP n
+ ***************************************************************/
+#define CP(value) \
+{ \
+ UINT32 ah = cpustate->_AFD & 0xff00; \
+ UINT32 res = (UINT8)((ah >> 8) - value); \
+ cpustate->_F = SZHVC_sub[ah | res]; \
+}
+
+/***************************************************************
+ * EX AF,AF'
+ ***************************************************************/
+#define EX_AF { \
+ PAIR tmp; \
+ tmp = cpustate->AF; cpustate->AF = cpustate->AF2; cpustate->AF2 = tmp; \
+}
+
+/***************************************************************
+ * EX DE,HL
+ ***************************************************************/
+#define EX_DE_HL { \
+ PAIR tmp; \
+ tmp = cpustate->DE; cpustate->DE = cpustate->HL; cpustate->HL = tmp; \
+}
+
+/***************************************************************
+ * EXX
+ ***************************************************************/
+#define EXX { \
+ PAIR tmp; \
+ tmp = cpustate->BC; cpustate->BC = cpustate->BC2; cpustate->BC2 = tmp; \
+ tmp = cpustate->DE; cpustate->DE = cpustate->DE2; cpustate->DE2 = tmp; \
+ tmp = cpustate->HL; cpustate->HL = cpustate->HL2; cpustate->HL2 = tmp; \
+}
+
+/***************************************************************
+ * EX (SP),r16
+ ***************************************************************/
+#define EXSP(DR) \
+{ \
+ PAIR tmp = { { 0, 0, 0, 0 } }; \
+ RM16(cpustate, cpustate->_SPD, &tmp ); \
+ WM16(cpustate, cpustate->_SPD, &cpustate->DR ); \
+ cpustate->DR = tmp; \
+}
+
+
+/***************************************************************
+ * ADD16
+ ***************************************************************/
+#define ADD16(DR,SR) \
+{ \
+ UINT32 res = cpustate->DR.d + cpustate->SR.d; \
+ cpustate->_F = (cpustate->_F & (SF | ZF | VF)) | \
+ (((cpustate->DR.d ^ res ^ cpustate->SR.d) >> 8) & HF) | \
+ ((res >> 16) & CF); \
+ cpustate->DR.w.l = (UINT16)res; \
+}
+
+/***************************************************************
+ * ADC r16,r16
+ ***************************************************************/
+#define ADC16(DR) \
+{ \
+ UINT32 res = cpustate->_HLD + cpustate->DR.d + (cpustate->_F & CF); \
+ cpustate->_F = (((cpustate->_HLD ^ res ^ cpustate->DR.d) >> 8) & HF) | \
+ ((res >> 16) & CF) | \
+ ((res >> 8) & SF) | \
+ ((res & 0xffff) ? 0 : ZF) | \
+ (((cpustate->DR.d ^ cpustate->_HLD ^ 0x8000) & (cpustate->DR.d ^ res) & 0x8000) >> 13); \
+ cpustate->_HL = (UINT16)res; \
+}
+
+/***************************************************************
+ * SBC r16,r16
+ ***************************************************************/
+#define SBC16(DR) \
+{ \
+ UINT32 res = cpustate->_HLD - cpustate->DR.d - (cpustate->_F & CF); \
+ cpustate->_F = (((cpustate->_HLD ^ res ^ cpustate->DR.d) >> 8) & HF) | NF | \
+ ((res >> 16) & CF) | \
+ ((res >> 8) & SF) | \
+ ((res & 0xffff) ? 0 : ZF) | \
+ (((cpustate->DR.d ^ cpustate->_HLD) & (cpustate->_HLD ^ res) &0x8000) >> 13); \
+ cpustate->_HL = (UINT16)res; \
+}
+
+/***************************************************************
+ * RLC r8
+ ***************************************************************/
+INLINE UINT8 RLC(z180_state *cpustate, UINT8 value)
+{
+ unsigned res = value;
+ unsigned c = (res & 0x80) ? CF : 0;
+ res = ((res << 1) | (res >> 7)) & 0xff;
+ cpustate->_F = SZP[res] | c;
+ return res;
+}
+
+/***************************************************************
+ * RRC r8
+ ***************************************************************/
+INLINE UINT8 RRC(z180_state *cpustate, UINT8 value)
+{
+ unsigned res = value;
+ unsigned c = (res & 0x01) ? CF : 0;
+ res = ((res >> 1) | (res << 7)) & 0xff;
+ cpustate->_F = SZP[res] | c;
+ return res;
+}
+
+/***************************************************************
+ * RL r8
+ ***************************************************************/
+INLINE UINT8 RL(z180_state *cpustate, UINT8 value)
+{
+ unsigned res = value;
+ unsigned c = (res & 0x80) ? CF : 0;
+ res = ((res << 1) | (cpustate->_F & CF)) & 0xff;
+ cpustate->_F = SZP[res] | c;
+ return res;
+}
+
+/***************************************************************
+ * RR r8
+ ***************************************************************/
+INLINE UINT8 RR(z180_state *cpustate, UINT8 value)
+{
+ unsigned res = value;
+ unsigned c = (res & 0x01) ? CF : 0;
+ res = ((res >> 1) | (cpustate->_F << 7)) & 0xff;
+ cpustate->_F = SZP[res] | c;
+ return res;
+}
+
+/***************************************************************
+ * SLA r8
+ ***************************************************************/
+INLINE UINT8 SLA(z180_state *cpustate, UINT8 value)
+{
+ unsigned res = value;
+ unsigned c = (res & 0x80) ? CF : 0;
+ res = (res << 1) & 0xff;
+ cpustate->_F = SZP[res] | c;
+ return res;
+}
+
+/***************************************************************
+ * SRA r8
+ ***************************************************************/
+INLINE UINT8 SRA(z180_state *cpustate, UINT8 value)
+{
+ unsigned res = value;
+ unsigned c = (res & 0x01) ? CF : 0;
+ res = ((res >> 1) | (res & 0x80)) & 0xff;
+ cpustate->_F = SZP[res] | c;
+ return res;
+}
+
+/***************************************************************
+ * SLL r8
+ ***************************************************************/
+INLINE UINT8 SLL(z180_state *cpustate, UINT8 value)
+{
+ unsigned res = value;
+ unsigned c = (res & 0x80) ? CF : 0;
+ res = ((res << 1) | 0x01) & 0xff;
+ cpustate->_F = SZP[res] | c;
+ return res;
+}
+
+/***************************************************************
+ * SRL r8
+ ***************************************************************/
+INLINE UINT8 SRL(z180_state *cpustate, UINT8 value)
+{
+ unsigned res = value;
+ unsigned c = (res & 0x01) ? CF : 0;
+ res = (res >> 1) & 0xff;
+ cpustate->_F = SZP[res] | c;
+ return res;
+}
+
+/***************************************************************
+ * BIT bit,r8
+ ***************************************************************/
+#undef BIT
+#define BIT(bit,reg) \
+ cpustate->_F = (cpustate->_F & CF) | HF | SZ_BIT[reg & (1<<bit)]
+
+/***************************************************************
+ * BIT bit,(IX/Y+o)
+ ***************************************************************/
+#define BIT_XY(bit,reg) \
+ cpustate->_F = (cpustate->_F & CF) | HF | (SZ_BIT[reg & (1<<bit)] & ~(YF|XF)) | ((cpustate->ea>>8) & (YF|XF))
+
+/***************************************************************
+ * RES bit,r8
+ ***************************************************************/
+INLINE UINT8 RES(UINT8 bit, UINT8 value)
+{
+ return value & ~(1<<bit);
+}
+
+/***************************************************************
+ * SET bit,r8
+ ***************************************************************/
+INLINE UINT8 SET(UINT8 bit, UINT8 value)
+{
+ return value | (1<<bit);
+}
+
+/***************************************************************
+ * LDI
+ ***************************************************************/
+#define LDI { \
+ UINT8 io = RM(cpustate, cpustate->_HL); \
+ WM(cpustate, cpustate->_DE, io ); \
+ cpustate->_F &= SF | ZF | CF; \
+ if( (cpustate->_A + io) & 0x02 ) cpustate->_F |= YF; /* bit 1 -> flag 5 */ \
+ if( (cpustate->_A + io) & 0x08 ) cpustate->_F |= XF; /* bit 3 -> flag 3 */ \
+ cpustate->_HL++; cpustate->_DE++; cpustate->_BC--; \
+ if( cpustate->_BC ) cpustate->_F |= VF; \
+}
+
+/***************************************************************
+ * CPI
+ ***************************************************************/
+#define CPI { \
+ UINT8 val = RM(cpustate, cpustate->_HL); \
+ UINT8 res = cpustate->_A - val; \
+ cpustate->_HL++; cpustate->_BC--; \
+ cpustate->_F = (cpustate->_F & CF) | (SZ[res] & ~(YF|XF)) | ((cpustate->_A ^ val ^ res) & HF) | NF; \
+ if( cpustate->_F & HF ) res -= 1; \
+ if( res & 0x02 ) cpustate->_F |= YF; /* bit 1 -> flag 5 */ \
+ if( res & 0x08 ) cpustate->_F |= XF; /* bit 3 -> flag 3 */ \
+ if( cpustate->_BC ) cpustate->_F |= VF; \
+}
+
+/***************************************************************
+ * INI
+ ***************************************************************/
+#define INI { \
+ UINT8 io = IN(cpustate, cpustate->_BC); \
+ cpustate->_B--; \
+ WM(cpustate, cpustate->_HL, io ); \
+ cpustate->_HL++; \
+ cpustate->_F = SZ[cpustate->_B]; \
+ if( io & SF ) cpustate->_F |= NF; \
+ if( (cpustate->_C + io + 1) & 0x100 ) cpustate->_F |= HF | CF; \
+ if( (irep_tmp1[cpustate->_C & 3][io & 3] ^ \
+ breg_tmp2[cpustate->_B] ^ \
+ (cpustate->_C >> 2) ^ \
+ (io >> 2)) & 1 ) \
+ cpustate->_F |= PF; \
+}
+
+/***************************************************************
+ * OUTI
+ ***************************************************************/
+#define OUTI { \
+ UINT8 io = RM(cpustate, cpustate->_HL); \
+ cpustate->_B--; \
+ OUT(cpustate, cpustate->_BC, io ); \
+ cpustate->_HL++; \
+ cpustate->_F = SZ[cpustate->_B]; \
+ if( io & SF ) cpustate->_F |= NF; \
+ if( (cpustate->_C + io + 1) & 0x100 ) cpustate->_F |= HF | CF; \
+ if( (irep_tmp1[cpustate->_C & 3][io & 3] ^ \
+ breg_tmp2[cpustate->_B] ^ \
+ (cpustate->_C >> 2) ^ \
+ (io >> 2)) & 1 ) \
+ cpustate->_F |= PF; \
+}
+
+/***************************************************************
+ * LDD
+ ***************************************************************/
+#define LDD { \
+ UINT8 io = RM(cpustate, cpustate->_HL); \
+ WM(cpustate, cpustate->_DE, io ); \
+ cpustate->_F &= SF | ZF | CF; \
+ if( (cpustate->_A + io) & 0x02 ) cpustate->_F |= YF; /* bit 1 -> flag 5 */ \
+ if( (cpustate->_A + io) & 0x08 ) cpustate->_F |= XF; /* bit 3 -> flag 3 */ \
+ cpustate->_HL--; cpustate->_DE--; cpustate->_BC--; \
+ if( cpustate->_BC ) cpustate->_F |= VF; \
+}
+
+/***************************************************************
+ * CPD
+ ***************************************************************/
+#define CPD { \
+ UINT8 val = RM(cpustate, cpustate->_HL); \
+ UINT8 res = cpustate->_A - val; \
+ cpustate->_HL--; cpustate->_BC--; \
+ cpustate->_F = (cpustate->_F & CF) | (SZ[res] & ~(YF|XF)) | ((cpustate->_A ^ val ^ res) & HF) | NF; \
+ if( cpustate->_F & HF ) res -= 1; \
+ if( res & 0x02 ) cpustate->_F |= YF; /* bit 1 -> flag 5 */ \
+ if( res & 0x08 ) cpustate->_F |= XF; /* bit 3 -> flag 3 */ \
+ if( cpustate->_BC ) cpustate->_F |= VF; \
+}
+
+/***************************************************************
+ * IND
+ ***************************************************************/
+#define IND { \
+ UINT8 io = IN(cpustate, cpustate->_BC); \
+ cpustate->_B--; \
+ WM(cpustate, cpustate->_HL, io ); \
+ cpustate->_HL--; \
+ cpustate->_F = SZ[cpustate->_B]; \
+ if( io & SF ) cpustate->_F |= NF; \
+ if( (cpustate->_C + io - 1) & 0x100 ) cpustate->_F |= HF | CF; \
+ if( (drep_tmp1[cpustate->_C & 3][io & 3] ^ \
+ breg_tmp2[cpustate->_B] ^ \
+ (cpustate->_C >> 2) ^ \
+ (io >> 2)) & 1 ) \
+ cpustate->_F |= PF; \
+}
+
+/***************************************************************
+ * OUTD
+ ***************************************************************/
+#define OUTD { \
+ UINT8 io = RM(cpustate, cpustate->_HL); \
+ cpustate->_B--; \
+ OUT(cpustate, cpustate->_BC, io ); \
+ cpustate->_HL--; \
+ cpustate->_F = SZ[cpustate->_B]; \
+ if( io & SF ) cpustate->_F |= NF; \
+ if( (cpustate->_C + io - 1) & 0x100 ) cpustate->_F |= HF | CF; \
+ if( (drep_tmp1[cpustate->_C & 3][io & 3] ^ \
+ breg_tmp2[cpustate->_B] ^ \
+ (cpustate->_C >> 2) ^ \
+ (io >> 2)) & 1 ) \
+ cpustate->_F |= PF; \
+}
+
+/***************************************************************
+ * LDIR
+ ***************************************************************/
+#define LDIR \
+ LDI; \
+ if( cpustate->_BC ) \
+ { \
+ cpustate->_PC -= 2; \
+ CC(ex,0xb0); \
+ }
+
+/***************************************************************
+ * CPIR
+ ***************************************************************/
+#define CPIR \
+ CPI; \
+ if( cpustate->_BC && !(cpustate->_F & ZF) ) \
+ { \
+ cpustate->_PC -= 2; \
+ CC(ex,0xb1); \
+ }
+
+/***************************************************************
+ * INIR
+ ***************************************************************/
+#define INIR \
+ INI; \
+ if( cpustate->_B ) \
+ { \
+ cpustate->_PC -= 2; \
+ CC(ex,0xb2); \
+ }
+
+/***************************************************************
+ * OTIR
+ ***************************************************************/
+#define OTIR \
+ OUTI; \
+ if( cpustate->_B ) \
+ { \
+ cpustate->_PC -= 2; \
+ CC(ex,0xb3); \
+ }
+
+/***************************************************************
+ * LDDR
+ ***************************************************************/
+#define LDDR \
+ LDD; \
+ if( cpustate->_BC ) \
+ { \
+ cpustate->_PC -= 2; \
+ CC(ex,0xb8); \
+ }
+
+/***************************************************************
+ * CPDR
+ ***************************************************************/
+#define CPDR \
+ CPD; \
+ if( cpustate->_BC && !(cpustate->_F & ZF) ) \
+ { \
+ cpustate->_PC -= 2; \
+ CC(ex,0xb9); \
+ }
+
+/***************************************************************
+ * INDR
+ ***************************************************************/
+#define INDR \
+ IND; \
+ if( cpustate->_B ) \
+ { \
+ cpustate->_PC -= 2; \
+ CC(ex,0xba); \
+ }
+
+/***************************************************************
+ * OTDR
+ ***************************************************************/
+#define OTDR \
+ OUTD; \
+ if( cpustate->_B ) \
+ { \
+ cpustate->_PC -= 2; \
+ CC(ex,0xbb); \
+ }
+
+/***************************************************************
+ * EI
+ ***************************************************************/
+#define EI { \
+ cpustate->IFF1 = cpustate->IFF2 = 1; \
+ cpustate->after_EI = 1; \
+}
+
+/***************************************************************
+ * TST n
+ ***************************************************************/
+#define TST(value) \
+ cpustate->_F = SZP[cpustate->_A & value] | HF
+
+/***************************************************************
+ * MLT rr
+ ***************************************************************/
+#define MLT(DR) { \
+ cpustate->DR.w.l = cpustate->DR.b.l * cpustate->DR.b.h; \
+}
+
+/***************************************************************
+ * OTIM
+ ***************************************************************/
+#define OTIM { \
+ cpustate->_B--; \
+ OUT(cpustate, cpustate->_C, RM(cpustate, cpustate->_HL) ); \
+ cpustate->_HL++; \
+ cpustate->_C++; \
+ cpustate->_F = (cpustate->_B) ? NF : NF | ZF; \
+}
+
+/***************************************************************
+ * OTDM
+ ***************************************************************/
+#define OTDM { \
+ cpustate->_B--; \
+ OUT(cpustate, cpustate->_C, RM(cpustate, cpustate->_HL) ); \
+ cpustate->_HL--; \
+ cpustate->_C--; \
+ cpustate->_F = (cpustate->_B) ? NF : NF | ZF; \
+}
+
+/***************************************************************
+ * OTIMR
+ ***************************************************************/
+#define OTIMR \
+ OTIM; \
+ if( cpustate->_B ) \
+ { \
+ cpustate->_PC -= 2; \
+ CC(ex,0xb3); \
+ }
+
+/***************************************************************
+ * OTDMR
+ ***************************************************************/
+#define OTDMR \
+ OTDM; \
+ if( cpustate->_B ) \
+ { \
+ cpustate->_PC -= 2; \
+ CC(ex,0xb3); \
+ }
+
+/***************************************************************
+ * OTDMR
+ ***************************************************************/
+#define SLP { \
+ cpustate->icount = 0; \
+ cpustate->HALT = 2; \
+}
+
diff --git a/trunk/src/emu/cpu/z180/z180tbl.h b/trunk/src/emu/cpu/z180/z180tbl.h
new file mode 100644
index 00000000000..01864a68d36
--- /dev/null
+++ b/trunk/src/emu/cpu/z180/z180tbl.h
@@ -0,0 +1,304 @@
+/* tmp1 value for ini/inir/outi/otir for [C.1-0][io.1-0] */
+static const UINT8 irep_tmp1[4][4] = {
+ {0,0,1,0},{0,1,0,1},{1,0,1,1},{0,1,1,0}
+};
+
+/* tmp1 value for ind/indr/outd/otdr for [C.1-0][io.1-0] */
+static const UINT8 drep_tmp1[4][4] = {
+ {0,1,0,0},{1,0,0,1},{0,0,1,0},{0,1,0,1}
+};
+
+/* tmp2 value for all in/out repeated opcodes for B.7-0 */
+static const UINT8 breg_tmp2[256] = {
+ 0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,
+ 0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,
+ 1,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,
+ 1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,
+ 0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,
+ 1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,
+ 0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,
+ 0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,
+ 1,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,
+ 1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,
+ 0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,
+ 0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,
+ 1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,
+ 0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,
+ 1,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,
+ 1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1
+};
+
+static const UINT8 cc_op[0x100] = {
+/*-0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -a -b -c -d -e -f */
+ 3, 9, 7, 4, 4, 4, 6, 3, 4, 7, 6, 4, 4, 4, 6, 3,
+ 7, 9, 7, 4, 4, 4, 6, 3, 8, 7, 6, 4, 4, 4, 6, 3,
+ 6, 9,16, 4, 4, 4, 6, 4, 6, 7,15, 4, 4, 4, 6, 3,
+ 6, 9,13, 4,10,10, 9, 3, 6, 7,12, 4, 4, 4, 6, 3,
+ 4, 4, 4, 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 6, 4,
+ 4, 4, 4, 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 6, 4,
+ 4, 4, 4, 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 6, 4,
+ 7, 7, 7, 7, 7, 7, 3, 7, 4, 4, 4, 4, 4, 4, 6, 4,
+ 4, 4, 4, 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 6, 4,
+ 4, 4, 4, 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 6, 4,
+ 4, 4, 4, 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 6, 4,
+ 4, 4, 4, 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 6, 4,
+ 5, 9, 6, 9, 6,11, 6,11, 5, 9, 6, 0, 6,16, 6,11,
+ 5, 9, 6,10, 6,11, 6,11, 5, 3, 6, 9, 6, 0, 6,11,
+ 5, 9, 6,16, 6,11, 6,11, 5, 3, 6, 3, 6, 0, 6,11,
+ 5, 9, 6, 3, 6,11, 6,11, 5, 4, 6, 3, 6, 0, 6,11
+};
+
+static const UINT8 cc_cb[0x100] = {
+/*-0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -a -b -c -d -e -f */
+ 7, 7, 7, 7, 7, 7,13, 7, 7, 7, 7, 7, 7, 7,13, 7,
+ 7, 7, 7, 7, 7, 7,13, 7, 7, 7, 7, 7, 7, 7,13, 7,
+ 7, 7, 7, 7, 7, 7,13, 7, 7, 7, 7, 7, 7, 7,13, 7,
+ 7, 7, 7, 7, 7, 7,13, 7, 7, 7, 7, 7, 7, 7,13, 7,
+ 6, 6, 6, 6, 6, 6, 9, 6, 6, 6, 6, 6, 6, 6, 9, 6,
+ 6, 6, 6, 6, 6, 6, 9, 6, 6, 6, 6, 6, 6, 6, 9, 6,
+ 6, 6, 6, 6, 6, 6, 9, 6, 6, 6, 6, 6, 6, 6, 9, 6,
+ 6, 6, 6, 6, 6, 6, 9, 6, 6, 6, 6, 6, 6, 6, 9, 6,
+ 7, 7, 7, 7, 7, 7,13, 7, 7, 7, 7, 7, 7, 7,13, 7,
+ 7, 7, 7, 7, 7, 7,13, 7, 7, 7, 7, 7, 7, 7,13, 7,
+ 7, 7, 7, 7, 7, 7,13, 7, 7, 7, 7, 7, 7, 7,13, 7,
+ 7, 7, 7, 7, 7, 7,13, 7, 7, 7, 7, 7, 7, 7,13, 7,
+ 7, 7, 7, 7, 7, 7,13, 7, 7, 7, 7, 7, 7, 7,13, 7,
+ 7, 7, 7, 7, 7, 7,13, 7, 7, 7, 7, 7, 7, 7,13, 7,
+ 7, 7, 7, 7, 7, 7,13, 7, 7, 7, 7, 7, 7, 7,13, 7,
+ 7, 7, 7, 7, 7, 7,13, 7, 7, 7, 7, 7, 7, 7,13, 7
+};
+
+static const UINT8 cc_ed[0x100] = {
+/*-0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -a -b -c -d -e -f */
+ 12,13, 6, 6, 9, 6, 6, 6,12,13, 6, 6, 9, 6, 6, 6,
+ 12,13, 6, 6, 9, 6, 6, 6,12,13, 6, 6, 9, 6, 6, 6,
+ 12,13, 6, 6, 9, 6, 6, 6,12,13, 6, 6,10, 6, 6, 6,
+ 12,13, 6, 6, 9, 6, 6, 6,12,13, 6, 6, 9, 6, 6, 6,
+ 9,10,10,19, 6,12, 6, 6, 9,10,10,18,17,12, 6, 6,
+ 9,10,10,19, 6,12, 6, 6, 9,10,10,18,17,12, 6, 6,
+ 9,10,10,19, 6,12, 6,16, 9,10,10,18,17,12, 6,16,
+ 9,10,10,19,12,12, 8, 6, 9,10,10,18,17,12, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 12,12,12,12, 6, 6, 6, 6,12,12,12,12, 6, 6, 6, 6,
+ 12,12,12,12, 6, 6, 6, 6,12,12,12,12, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
+};
+
+static const UINT8 cc_xy[0x100] = {
+/*-0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -a -b -c -d -e -f */
+ 4, 4, 4, 4, 4, 4, 4, 4, 4,10, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4,10, 4, 4, 4, 4, 4, 4,
+ 4,12,19, 7, 9, 9,15, 4, 4,10,18, 7, 9, 9, 9, 4,
+ 4, 4, 4, 4,18,18,15, 4, 4,10, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 9, 9,14, 4, 4, 4, 4, 4, 9, 9,14, 4,
+ 4, 4, 4, 4, 9, 9,14, 4, 4, 4, 4, 4, 9, 9,14, 4,
+ 9, 9, 9, 9, 9, 9,14, 9, 9, 9, 9, 9, 9, 9,14, 9,
+ 15,15,15,15,15,15, 4,15, 4, 4, 4, 4, 9, 9,14, 4,
+ 4, 4, 4, 4, 9, 9,14, 4, 4, 4, 4, 4, 9, 9,14, 4,
+ 4, 4, 4, 4, 9, 9,14, 4, 4, 4, 4, 4, 9, 9,14, 4,
+ 4, 4, 4, 4, 9, 9,14, 4, 4, 4, 4, 4, 9, 9,14, 4,
+ 4, 4, 4, 4, 9, 9,14, 4, 4, 4, 4, 4, 9, 9,14, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4,12, 4,19, 4,14, 4, 4, 4, 6, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4
+};
+
+static const UINT8 cc_xycb[0x100] = {
+/*-0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -a -b -c -d -e -f */
+ 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+ 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+ 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+ 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+ 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+ 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+ 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+ 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+ 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+ 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+ 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+ 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+ 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+ 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+ 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+ 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19
+};
+
+/* extra cycles if jr/jp/call taken and 'interrupt latency' on rst 0-7 */
+static const UINT8 cc_ex[0x100] = {
+/*-0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -a -b -c -d -e -f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* DJNZ */
+ 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, /* JR NZ/JR Z */
+ 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, /* JR NC/JR C */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,10, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,10, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,10, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,10, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 4, 4, 4, 0, 0, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, /* LDIR/CPIR/INIR/OTIR LDDR/CPDR/INDR/OTDR */
+ 5, 0, 3, 0,10, 0, 0, 2, 5, 0, 3, 0,10, 0, 0, 2,
+ 5, 0, 3, 0,10, 0, 0, 2, 5, 0, 3, 0,10, 0, 0, 2,
+ 5, 0, 3, 0,10, 0, 0, 2, 5, 0, 3, 0,10, 0, 0, 2,
+ 5, 0, 3, 0,10, 0, 0, 2, 5, 0, 3, 0,10, 0, 0, 2
+};
+
+static const UINT8 *const cc_default[6] = { cc_op, cc_cb, cc_ed, cc_xy, cc_xycb, cc_ex };
+
+#define Z180_TABLE_dd Z180_TABLE_xy
+#define Z180_TABLE_fd Z180_TABLE_xy
+
+static int take_interrupt(z180_state *cpustate, int irq);
+
+#define PROTOTYPES(tablename,prefix) \
+ INLINE void prefix##_00(z180_state *cpustate); INLINE void prefix##_01(z180_state *cpustate); INLINE void prefix##_02(z180_state *cpustate); INLINE void prefix##_03(z180_state *cpustate); \
+ INLINE void prefix##_04(z180_state *cpustate); INLINE void prefix##_05(z180_state *cpustate); INLINE void prefix##_06(z180_state *cpustate); INLINE void prefix##_07(z180_state *cpustate); \
+ INLINE void prefix##_08(z180_state *cpustate); INLINE void prefix##_09(z180_state *cpustate); INLINE void prefix##_0a(z180_state *cpustate); INLINE void prefix##_0b(z180_state *cpustate); \
+ INLINE void prefix##_0c(z180_state *cpustate); INLINE void prefix##_0d(z180_state *cpustate); INLINE void prefix##_0e(z180_state *cpustate); INLINE void prefix##_0f(z180_state *cpustate); \
+ INLINE void prefix##_10(z180_state *cpustate); INLINE void prefix##_11(z180_state *cpustate); INLINE void prefix##_12(z180_state *cpustate); INLINE void prefix##_13(z180_state *cpustate); \
+ INLINE void prefix##_14(z180_state *cpustate); INLINE void prefix##_15(z180_state *cpustate); INLINE void prefix##_16(z180_state *cpustate); INLINE void prefix##_17(z180_state *cpustate); \
+ INLINE void prefix##_18(z180_state *cpustate); INLINE void prefix##_19(z180_state *cpustate); INLINE void prefix##_1a(z180_state *cpustate); INLINE void prefix##_1b(z180_state *cpustate); \
+ INLINE void prefix##_1c(z180_state *cpustate); INLINE void prefix##_1d(z180_state *cpustate); INLINE void prefix##_1e(z180_state *cpustate); INLINE void prefix##_1f(z180_state *cpustate); \
+ INLINE void prefix##_20(z180_state *cpustate); INLINE void prefix##_21(z180_state *cpustate); INLINE void prefix##_22(z180_state *cpustate); INLINE void prefix##_23(z180_state *cpustate); \
+ INLINE void prefix##_24(z180_state *cpustate); INLINE void prefix##_25(z180_state *cpustate); INLINE void prefix##_26(z180_state *cpustate); INLINE void prefix##_27(z180_state *cpustate); \
+ INLINE void prefix##_28(z180_state *cpustate); INLINE void prefix##_29(z180_state *cpustate); INLINE void prefix##_2a(z180_state *cpustate); INLINE void prefix##_2b(z180_state *cpustate); \
+ INLINE void prefix##_2c(z180_state *cpustate); INLINE void prefix##_2d(z180_state *cpustate); INLINE void prefix##_2e(z180_state *cpustate); INLINE void prefix##_2f(z180_state *cpustate); \
+ INLINE void prefix##_30(z180_state *cpustate); INLINE void prefix##_31(z180_state *cpustate); INLINE void prefix##_32(z180_state *cpustate); INLINE void prefix##_33(z180_state *cpustate); \
+ INLINE void prefix##_34(z180_state *cpustate); INLINE void prefix##_35(z180_state *cpustate); INLINE void prefix##_36(z180_state *cpustate); INLINE void prefix##_37(z180_state *cpustate); \
+ INLINE void prefix##_38(z180_state *cpustate); INLINE void prefix##_39(z180_state *cpustate); INLINE void prefix##_3a(z180_state *cpustate); INLINE void prefix##_3b(z180_state *cpustate); \
+ INLINE void prefix##_3c(z180_state *cpustate); INLINE void prefix##_3d(z180_state *cpustate); INLINE void prefix##_3e(z180_state *cpustate); INLINE void prefix##_3f(z180_state *cpustate); \
+ INLINE void prefix##_40(z180_state *cpustate); INLINE void prefix##_41(z180_state *cpustate); INLINE void prefix##_42(z180_state *cpustate); INLINE void prefix##_43(z180_state *cpustate); \
+ INLINE void prefix##_44(z180_state *cpustate); INLINE void prefix##_45(z180_state *cpustate); INLINE void prefix##_46(z180_state *cpustate); INLINE void prefix##_47(z180_state *cpustate); \
+ INLINE void prefix##_48(z180_state *cpustate); INLINE void prefix##_49(z180_state *cpustate); INLINE void prefix##_4a(z180_state *cpustate); INLINE void prefix##_4b(z180_state *cpustate); \
+ INLINE void prefix##_4c(z180_state *cpustate); INLINE void prefix##_4d(z180_state *cpustate); INLINE void prefix##_4e(z180_state *cpustate); INLINE void prefix##_4f(z180_state *cpustate); \
+ INLINE void prefix##_50(z180_state *cpustate); INLINE void prefix##_51(z180_state *cpustate); INLINE void prefix##_52(z180_state *cpustate); INLINE void prefix##_53(z180_state *cpustate); \
+ INLINE void prefix##_54(z180_state *cpustate); INLINE void prefix##_55(z180_state *cpustate); INLINE void prefix##_56(z180_state *cpustate); INLINE void prefix##_57(z180_state *cpustate); \
+ INLINE void prefix##_58(z180_state *cpustate); INLINE void prefix##_59(z180_state *cpustate); INLINE void prefix##_5a(z180_state *cpustate); INLINE void prefix##_5b(z180_state *cpustate); \
+ INLINE void prefix##_5c(z180_state *cpustate); INLINE void prefix##_5d(z180_state *cpustate); INLINE void prefix##_5e(z180_state *cpustate); INLINE void prefix##_5f(z180_state *cpustate); \
+ INLINE void prefix##_60(z180_state *cpustate); INLINE void prefix##_61(z180_state *cpustate); INLINE void prefix##_62(z180_state *cpustate); INLINE void prefix##_63(z180_state *cpustate); \
+ INLINE void prefix##_64(z180_state *cpustate); INLINE void prefix##_65(z180_state *cpustate); INLINE void prefix##_66(z180_state *cpustate); INLINE void prefix##_67(z180_state *cpustate); \
+ INLINE void prefix##_68(z180_state *cpustate); INLINE void prefix##_69(z180_state *cpustate); INLINE void prefix##_6a(z180_state *cpustate); INLINE void prefix##_6b(z180_state *cpustate); \
+ INLINE void prefix##_6c(z180_state *cpustate); INLINE void prefix##_6d(z180_state *cpustate); INLINE void prefix##_6e(z180_state *cpustate); INLINE void prefix##_6f(z180_state *cpustate); \
+ INLINE void prefix##_70(z180_state *cpustate); INLINE void prefix##_71(z180_state *cpustate); INLINE void prefix##_72(z180_state *cpustate); INLINE void prefix##_73(z180_state *cpustate); \
+ INLINE void prefix##_74(z180_state *cpustate); INLINE void prefix##_75(z180_state *cpustate); INLINE void prefix##_76(z180_state *cpustate); INLINE void prefix##_77(z180_state *cpustate); \
+ INLINE void prefix##_78(z180_state *cpustate); INLINE void prefix##_79(z180_state *cpustate); INLINE void prefix##_7a(z180_state *cpustate); INLINE void prefix##_7b(z180_state *cpustate); \
+ INLINE void prefix##_7c(z180_state *cpustate); INLINE void prefix##_7d(z180_state *cpustate); INLINE void prefix##_7e(z180_state *cpustate); INLINE void prefix##_7f(z180_state *cpustate); \
+ INLINE void prefix##_80(z180_state *cpustate); INLINE void prefix##_81(z180_state *cpustate); INLINE void prefix##_82(z180_state *cpustate); INLINE void prefix##_83(z180_state *cpustate); \
+ INLINE void prefix##_84(z180_state *cpustate); INLINE void prefix##_85(z180_state *cpustate); INLINE void prefix##_86(z180_state *cpustate); INLINE void prefix##_87(z180_state *cpustate); \
+ INLINE void prefix##_88(z180_state *cpustate); INLINE void prefix##_89(z180_state *cpustate); INLINE void prefix##_8a(z180_state *cpustate); INLINE void prefix##_8b(z180_state *cpustate); \
+ INLINE void prefix##_8c(z180_state *cpustate); INLINE void prefix##_8d(z180_state *cpustate); INLINE void prefix##_8e(z180_state *cpustate); INLINE void prefix##_8f(z180_state *cpustate); \
+ INLINE void prefix##_90(z180_state *cpustate); INLINE void prefix##_91(z180_state *cpustate); INLINE void prefix##_92(z180_state *cpustate); INLINE void prefix##_93(z180_state *cpustate); \
+ INLINE void prefix##_94(z180_state *cpustate); INLINE void prefix##_95(z180_state *cpustate); INLINE void prefix##_96(z180_state *cpustate); INLINE void prefix##_97(z180_state *cpustate); \
+ INLINE void prefix##_98(z180_state *cpustate); INLINE void prefix##_99(z180_state *cpustate); INLINE void prefix##_9a(z180_state *cpustate); INLINE void prefix##_9b(z180_state *cpustate); \
+ INLINE void prefix##_9c(z180_state *cpustate); INLINE void prefix##_9d(z180_state *cpustate); INLINE void prefix##_9e(z180_state *cpustate); INLINE void prefix##_9f(z180_state *cpustate); \
+ INLINE void prefix##_a0(z180_state *cpustate); INLINE void prefix##_a1(z180_state *cpustate); INLINE void prefix##_a2(z180_state *cpustate); INLINE void prefix##_a3(z180_state *cpustate); \
+ INLINE void prefix##_a4(z180_state *cpustate); INLINE void prefix##_a5(z180_state *cpustate); INLINE void prefix##_a6(z180_state *cpustate); INLINE void prefix##_a7(z180_state *cpustate); \
+ INLINE void prefix##_a8(z180_state *cpustate); INLINE void prefix##_a9(z180_state *cpustate); INLINE void prefix##_aa(z180_state *cpustate); INLINE void prefix##_ab(z180_state *cpustate); \
+ INLINE void prefix##_ac(z180_state *cpustate); INLINE void prefix##_ad(z180_state *cpustate); INLINE void prefix##_ae(z180_state *cpustate); INLINE void prefix##_af(z180_state *cpustate); \
+ INLINE void prefix##_b0(z180_state *cpustate); INLINE void prefix##_b1(z180_state *cpustate); INLINE void prefix##_b2(z180_state *cpustate); INLINE void prefix##_b3(z180_state *cpustate); \
+ INLINE void prefix##_b4(z180_state *cpustate); INLINE void prefix##_b5(z180_state *cpustate); INLINE void prefix##_b6(z180_state *cpustate); INLINE void prefix##_b7(z180_state *cpustate); \
+ INLINE void prefix##_b8(z180_state *cpustate); INLINE void prefix##_b9(z180_state *cpustate); INLINE void prefix##_ba(z180_state *cpustate); INLINE void prefix##_bb(z180_state *cpustate); \
+ INLINE void prefix##_bc(z180_state *cpustate); INLINE void prefix##_bd(z180_state *cpustate); INLINE void prefix##_be(z180_state *cpustate); INLINE void prefix##_bf(z180_state *cpustate); \
+ INLINE void prefix##_c0(z180_state *cpustate); INLINE void prefix##_c1(z180_state *cpustate); INLINE void prefix##_c2(z180_state *cpustate); INLINE void prefix##_c3(z180_state *cpustate); \
+ INLINE void prefix##_c4(z180_state *cpustate); INLINE void prefix##_c5(z180_state *cpustate); INLINE void prefix##_c6(z180_state *cpustate); INLINE void prefix##_c7(z180_state *cpustate); \
+ INLINE void prefix##_c8(z180_state *cpustate); INLINE void prefix##_c9(z180_state *cpustate); INLINE void prefix##_ca(z180_state *cpustate); INLINE void prefix##_cb(z180_state *cpustate); \
+ INLINE void prefix##_cc(z180_state *cpustate); INLINE void prefix##_cd(z180_state *cpustate); INLINE void prefix##_ce(z180_state *cpustate); INLINE void prefix##_cf(z180_state *cpustate); \
+ INLINE void prefix##_d0(z180_state *cpustate); INLINE void prefix##_d1(z180_state *cpustate); INLINE void prefix##_d2(z180_state *cpustate); INLINE void prefix##_d3(z180_state *cpustate); \
+ INLINE void prefix##_d4(z180_state *cpustate); INLINE void prefix##_d5(z180_state *cpustate); INLINE void prefix##_d6(z180_state *cpustate); INLINE void prefix##_d7(z180_state *cpustate); \
+ INLINE void prefix##_d8(z180_state *cpustate); INLINE void prefix##_d9(z180_state *cpustate); INLINE void prefix##_da(z180_state *cpustate); INLINE void prefix##_db(z180_state *cpustate); \
+ INLINE void prefix##_dc(z180_state *cpustate); INLINE void prefix##_dd(z180_state *cpustate); INLINE void prefix##_de(z180_state *cpustate); INLINE void prefix##_df(z180_state *cpustate); \
+ INLINE void prefix##_e0(z180_state *cpustate); INLINE void prefix##_e1(z180_state *cpustate); INLINE void prefix##_e2(z180_state *cpustate); INLINE void prefix##_e3(z180_state *cpustate); \
+ INLINE void prefix##_e4(z180_state *cpustate); INLINE void prefix##_e5(z180_state *cpustate); INLINE void prefix##_e6(z180_state *cpustate); INLINE void prefix##_e7(z180_state *cpustate); \
+ INLINE void prefix##_e8(z180_state *cpustate); INLINE void prefix##_e9(z180_state *cpustate); INLINE void prefix##_ea(z180_state *cpustate); INLINE void prefix##_eb(z180_state *cpustate); \
+ INLINE void prefix##_ec(z180_state *cpustate); INLINE void prefix##_ed(z180_state *cpustate); INLINE void prefix##_ee(z180_state *cpustate); INLINE void prefix##_ef(z180_state *cpustate); \
+ INLINE void prefix##_f0(z180_state *cpustate); INLINE void prefix##_f1(z180_state *cpustate); INLINE void prefix##_f2(z180_state *cpustate); INLINE void prefix##_f3(z180_state *cpustate); \
+ INLINE void prefix##_f4(z180_state *cpustate); INLINE void prefix##_f5(z180_state *cpustate); INLINE void prefix##_f6(z180_state *cpustate); INLINE void prefix##_f7(z180_state *cpustate); \
+ INLINE void prefix##_f8(z180_state *cpustate); INLINE void prefix##_f9(z180_state *cpustate); INLINE void prefix##_fa(z180_state *cpustate); INLINE void prefix##_fb(z180_state *cpustate); \
+ INLINE void prefix##_fc(z180_state *cpustate); INLINE void prefix##_fd(z180_state *cpustate); INLINE void prefix##_fe(z180_state *cpustate); INLINE void prefix##_ff(z180_state *cpustate);
+
+#define TABLE(prefix) {\
+ prefix##_00,prefix##_01,prefix##_02,prefix##_03,prefix##_04,prefix##_05,prefix##_06,prefix##_07, \
+ prefix##_08,prefix##_09,prefix##_0a,prefix##_0b,prefix##_0c,prefix##_0d,prefix##_0e,prefix##_0f, \
+ prefix##_10,prefix##_11,prefix##_12,prefix##_13,prefix##_14,prefix##_15,prefix##_16,prefix##_17, \
+ prefix##_18,prefix##_19,prefix##_1a,prefix##_1b,prefix##_1c,prefix##_1d,prefix##_1e,prefix##_1f, \
+ prefix##_20,prefix##_21,prefix##_22,prefix##_23,prefix##_24,prefix##_25,prefix##_26,prefix##_27, \
+ prefix##_28,prefix##_29,prefix##_2a,prefix##_2b,prefix##_2c,prefix##_2d,prefix##_2e,prefix##_2f, \
+ prefix##_30,prefix##_31,prefix##_32,prefix##_33,prefix##_34,prefix##_35,prefix##_36,prefix##_37, \
+ prefix##_38,prefix##_39,prefix##_3a,prefix##_3b,prefix##_3c,prefix##_3d,prefix##_3e,prefix##_3f, \
+ prefix##_40,prefix##_41,prefix##_42,prefix##_43,prefix##_44,prefix##_45,prefix##_46,prefix##_47, \
+ prefix##_48,prefix##_49,prefix##_4a,prefix##_4b,prefix##_4c,prefix##_4d,prefix##_4e,prefix##_4f, \
+ prefix##_50,prefix##_51,prefix##_52,prefix##_53,prefix##_54,prefix##_55,prefix##_56,prefix##_57, \
+ prefix##_58,prefix##_59,prefix##_5a,prefix##_5b,prefix##_5c,prefix##_5d,prefix##_5e,prefix##_5f, \
+ prefix##_60,prefix##_61,prefix##_62,prefix##_63,prefix##_64,prefix##_65,prefix##_66,prefix##_67, \
+ prefix##_68,prefix##_69,prefix##_6a,prefix##_6b,prefix##_6c,prefix##_6d,prefix##_6e,prefix##_6f, \
+ prefix##_70,prefix##_71,prefix##_72,prefix##_73,prefix##_74,prefix##_75,prefix##_76,prefix##_77, \
+ prefix##_78,prefix##_79,prefix##_7a,prefix##_7b,prefix##_7c,prefix##_7d,prefix##_7e,prefix##_7f, \
+ prefix##_80,prefix##_81,prefix##_82,prefix##_83,prefix##_84,prefix##_85,prefix##_86,prefix##_87, \
+ prefix##_88,prefix##_89,prefix##_8a,prefix##_8b,prefix##_8c,prefix##_8d,prefix##_8e,prefix##_8f, \
+ prefix##_90,prefix##_91,prefix##_92,prefix##_93,prefix##_94,prefix##_95,prefix##_96,prefix##_97, \
+ prefix##_98,prefix##_99,prefix##_9a,prefix##_9b,prefix##_9c,prefix##_9d,prefix##_9e,prefix##_9f, \
+ prefix##_a0,prefix##_a1,prefix##_a2,prefix##_a3,prefix##_a4,prefix##_a5,prefix##_a6,prefix##_a7, \
+ prefix##_a8,prefix##_a9,prefix##_aa,prefix##_ab,prefix##_ac,prefix##_ad,prefix##_ae,prefix##_af, \
+ prefix##_b0,prefix##_b1,prefix##_b2,prefix##_b3,prefix##_b4,prefix##_b5,prefix##_b6,prefix##_b7, \
+ prefix##_b8,prefix##_b9,prefix##_ba,prefix##_bb,prefix##_bc,prefix##_bd,prefix##_be,prefix##_bf, \
+ prefix##_c0,prefix##_c1,prefix##_c2,prefix##_c3,prefix##_c4,prefix##_c5,prefix##_c6,prefix##_c7, \
+ prefix##_c8,prefix##_c9,prefix##_ca,prefix##_cb,prefix##_cc,prefix##_cd,prefix##_ce,prefix##_cf, \
+ prefix##_d0,prefix##_d1,prefix##_d2,prefix##_d3,prefix##_d4,prefix##_d5,prefix##_d6,prefix##_d7, \
+ prefix##_d8,prefix##_d9,prefix##_da,prefix##_db,prefix##_dc,prefix##_dd,prefix##_de,prefix##_df, \
+ prefix##_e0,prefix##_e1,prefix##_e2,prefix##_e3,prefix##_e4,prefix##_e5,prefix##_e6,prefix##_e7, \
+ prefix##_e8,prefix##_e9,prefix##_ea,prefix##_eb,prefix##_ec,prefix##_ed,prefix##_ee,prefix##_ef, \
+ prefix##_f0,prefix##_f1,prefix##_f2,prefix##_f3,prefix##_f4,prefix##_f5,prefix##_f6,prefix##_f7, \
+ prefix##_f8,prefix##_f9,prefix##_fa,prefix##_fb,prefix##_fc,prefix##_fd,prefix##_fe,prefix##_ff \
+}
+
+PROTOTYPES(Z180op,op);
+PROTOTYPES(Z180cb,cb);
+PROTOTYPES(Z180dd,dd);
+PROTOTYPES(Z180ed,ed);
+PROTOTYPES(Z180fd,fd);
+PROTOTYPES(Z180xycb,xycb);
+
+static void (*const Z180ops[Z180_PREFIX_COUNT][0x100])(z180_state *cpustate) =
+{
+ TABLE(op),
+ TABLE(cb),
+ TABLE(dd),
+ TABLE(ed),
+ TABLE(fd),
+ TABLE(xycb)
+};
+
+/***************************************************************
+ * define an opcode function
+ ***************************************************************/
+#define OP(prefix,opcode) INLINE void prefix##_##opcode(z180_state *cpustate)
+
+/***************************************************************
+ * adjust cycle count by n T-states
+ ***************************************************************/
+#define CC(prefix,opcode) cpustate->extra_cycles += cpustate->cc[Z180_TABLE_##prefix][opcode]
+
+/***************************************************************
+ * execute an opcode
+ ***************************************************************/
+
+#define EXEC_PROTOTYPE(prefix) \
+INLINE int exec##_##prefix(z180_state *cpustate, const UINT8 opcode) \
+{ \
+ (*Z180ops[Z180_PREFIX_##prefix][opcode])(cpustate); \
+ return cpustate->cc[Z180_TABLE_##prefix][opcode]; \
+}
+
+EXEC_PROTOTYPE(op)
+EXEC_PROTOTYPE(cb)
+EXEC_PROTOTYPE(dd)
+EXEC_PROTOTYPE(ed)
+EXEC_PROTOTYPE(fd)
+EXEC_PROTOTYPE(xycb)
+
diff --git a/trunk/src/emu/cpu/z180/z180xy.c b/trunk/src/emu/cpu/z180/z180xy.c
new file mode 100644
index 00000000000..5cc0b5fcff6
--- /dev/null
+++ b/trunk/src/emu/cpu/z180/z180xy.c
@@ -0,0 +1,292 @@
+/**********************************************************
+* opcodes with DD/FD CB prefix
+* rotate, shift and bit operations with (IX+o)
+**********************************************************/
+OP(xycb,00) { cpustate->_B = RLC( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_B ); } /* RLC B=(XY+o) */
+OP(xycb,01) { cpustate->_C = RLC( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_C ); } /* RLC C=(XY+o) */
+OP(xycb,02) { cpustate->_D = RLC( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_D ); } /* RLC D=(XY+o) */
+OP(xycb,03) { cpustate->_E = RLC( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_E ); } /* RLC E=(XY+o) */
+OP(xycb,04) { cpustate->_H = RLC( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_H ); } /* RLC H=(XY+o) */
+OP(xycb,05) { cpustate->_L = RLC( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_L ); } /* RLC L=(XY+o) */
+OP(xycb,06) { WM(cpustate, cpustate->ea, RLC( cpustate, RM(cpustate, cpustate->ea) ) ); } /* RLC (XY+o) */
+OP(xycb,07) { cpustate->_A = RLC( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_A ); } /* RLC A=(XY+o) */
+
+OP(xycb,08) { cpustate->_B = RRC( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_B ); } /* RRC B=(XY+o) */
+OP(xycb,09) { cpustate->_C = RRC( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_C ); } /* RRC C=(XY+o) */
+OP(xycb,0a) { cpustate->_D = RRC( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_D ); } /* RRC D=(XY+o) */
+OP(xycb,0b) { cpustate->_E = RRC( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_E ); } /* RRC E=(XY+o) */
+OP(xycb,0c) { cpustate->_H = RRC( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_H ); } /* RRC H=(XY+o) */
+OP(xycb,0d) { cpustate->_L = RRC( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_L ); } /* RRC L=(XY+o) */
+OP(xycb,0e) { WM(cpustate, cpustate->ea,RRC( cpustate, RM(cpustate, cpustate->ea) ) ); } /* RRC (XY+o) */
+OP(xycb,0f) { cpustate->_A = RRC( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_A ); } /* RRC A=(XY+o) */
+
+OP(xycb,10) { cpustate->_B = RL( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_B ); } /* RL B=(XY+o) */
+OP(xycb,11) { cpustate->_C = RL( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_C ); } /* RL C=(XY+o) */
+OP(xycb,12) { cpustate->_D = RL( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_D ); } /* RL D=(XY+o) */
+OP(xycb,13) { cpustate->_E = RL( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_E ); } /* RL E=(XY+o) */
+OP(xycb,14) { cpustate->_H = RL( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_H ); } /* RL H=(XY+o) */
+OP(xycb,15) { cpustate->_L = RL( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_L ); } /* RL L=(XY+o) */
+OP(xycb,16) { WM(cpustate, cpustate->ea,RL( cpustate, RM(cpustate, cpustate->ea) ) ); } /* RL (XY+o) */
+OP(xycb,17) { cpustate->_A = RL( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_A ); } /* RL A=(XY+o) */
+
+OP(xycb,18) { cpustate->_B = RR( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_B ); } /* RR B=(XY+o) */
+OP(xycb,19) { cpustate->_C = RR( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_C ); } /* RR C=(XY+o) */
+OP(xycb,1a) { cpustate->_D = RR( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_D ); } /* RR D=(XY+o) */
+OP(xycb,1b) { cpustate->_E = RR( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_E ); } /* RR E=(XY+o) */
+OP(xycb,1c) { cpustate->_H = RR( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_H ); } /* RR H=(XY+o) */
+OP(xycb,1d) { cpustate->_L = RR( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_L ); } /* RR L=(XY+o) */
+OP(xycb,1e) { WM(cpustate, cpustate->ea,RR( cpustate, RM(cpustate, cpustate->ea) ) ); } /* RR (XY+o) */
+OP(xycb,1f) { cpustate->_A = RR( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_A ); } /* RR A=(XY+o) */
+
+OP(xycb,20) { cpustate->_B = SLA( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_B ); } /* SLA B=(XY+o) */
+OP(xycb,21) { cpustate->_C = SLA( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_C ); } /* SLA C=(XY+o) */
+OP(xycb,22) { cpustate->_D = SLA( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_D ); } /* SLA D=(XY+o) */
+OP(xycb,23) { cpustate->_E = SLA( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_E ); } /* SLA E=(XY+o) */
+OP(xycb,24) { cpustate->_H = SLA( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_H ); } /* SLA H=(XY+o) */
+OP(xycb,25) { cpustate->_L = SLA( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_L ); } /* SLA L=(XY+o) */
+OP(xycb,26) { WM(cpustate, cpustate->ea,SLA( cpustate, RM(cpustate, cpustate->ea) ) ); } /* SLA (XY+o) */
+OP(xycb,27) { cpustate->_A = SLA( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_A ); } /* SLA A=(XY+o) */
+
+OP(xycb,28) { cpustate->_B = SRA( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_B ); } /* SRA B=(XY+o) */
+OP(xycb,29) { cpustate->_C = SRA( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_C ); } /* SRA C=(XY+o) */
+OP(xycb,2a) { cpustate->_D = SRA( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_D ); } /* SRA D=(XY+o) */
+OP(xycb,2b) { cpustate->_E = SRA( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_E ); } /* SRA E=(XY+o) */
+OP(xycb,2c) { cpustate->_H = SRA( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_H ); } /* SRA H=(XY+o) */
+OP(xycb,2d) { cpustate->_L = SRA( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_L ); } /* SRA L=(XY+o) */
+OP(xycb,2e) { WM(cpustate, cpustate->ea,SRA( cpustate, RM(cpustate, cpustate->ea) ) ); } /* SRA (XY+o) */
+OP(xycb,2f) { cpustate->_A = SRA( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_A ); } /* SRA A=(XY+o) */
+
+OP(xycb,30) { cpustate->_B = SLL( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_B ); } /* SLL B=(XY+o) */
+OP(xycb,31) { cpustate->_C = SLL( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_C ); } /* SLL C=(XY+o) */
+OP(xycb,32) { cpustate->_D = SLL( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_D ); } /* SLL D=(XY+o) */
+OP(xycb,33) { cpustate->_E = SLL( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_E ); } /* SLL E=(XY+o) */
+OP(xycb,34) { cpustate->_H = SLL( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_H ); } /* SLL H=(XY+o) */
+OP(xycb,35) { cpustate->_L = SLL( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_L ); } /* SLL L=(XY+o) */
+OP(xycb,36) { WM(cpustate, cpustate->ea,SLL( cpustate, RM(cpustate, cpustate->ea) ) ); } /* SLL (XY+o) */
+OP(xycb,37) { cpustate->_A = SLL( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_A ); } /* SLL A=(XY+o) */
+
+OP(xycb,38) { cpustate->_B = SRL( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_B ); } /* SRL B=(XY+o) */
+OP(xycb,39) { cpustate->_C = SRL( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_C ); } /* SRL C=(XY+o) */
+OP(xycb,3a) { cpustate->_D = SRL( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_D ); } /* SRL D=(XY+o) */
+OP(xycb,3b) { cpustate->_E = SRL( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_E ); } /* SRL E=(XY+o) */
+OP(xycb,3c) { cpustate->_H = SRL( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_H ); } /* SRL H=(XY+o) */
+OP(xycb,3d) { cpustate->_L = SRL( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_L ); } /* SRL L=(XY+o) */
+OP(xycb,3e) { WM(cpustate, cpustate->ea,SRL( cpustate, RM(cpustate, cpustate->ea) ) ); } /* SRL (XY+o) */
+OP(xycb,3f) { cpustate->_A = SRL( cpustate, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_A ); } /* SRL A=(XY+o) */
+
+OP(xycb,40) { xycb_46(cpustate); } /* BIT 0,B=(XY+o) */
+OP(xycb,41) { xycb_46(cpustate); } /* BIT 0,C=(XY+o) */
+OP(xycb,42) { xycb_46(cpustate); } /* BIT 0,D=(XY+o) */
+OP(xycb,43) { xycb_46(cpustate); } /* BIT 0,E=(XY+o) */
+OP(xycb,44) { xycb_46(cpustate); } /* BIT 0,H=(XY+o) */
+OP(xycb,45) { xycb_46(cpustate); } /* BIT 0,L=(XY+o) */
+OP(xycb,46) { BIT_XY(0,RM(cpustate, cpustate->ea)); } /* BIT 0,(XY+o) */
+OP(xycb,47) { xycb_46(cpustate); } /* BIT 0,A=(XY+o) */
+
+OP(xycb,48) { xycb_4e(cpustate); } /* BIT 1,B=(XY+o) */
+OP(xycb,49) { xycb_4e(cpustate); } /* BIT 1,C=(XY+o) */
+OP(xycb,4a) { xycb_4e(cpustate); } /* BIT 1,D=(XY+o) */
+OP(xycb,4b) { xycb_4e(cpustate); } /* BIT 1,E=(XY+o) */
+OP(xycb,4c) { xycb_4e(cpustate); } /* BIT 1,H=(XY+o) */
+OP(xycb,4d) { xycb_4e(cpustate); } /* BIT 1,L=(XY+o) */
+OP(xycb,4e) { BIT_XY(1,RM(cpustate, cpustate->ea)); } /* BIT 1,(XY+o) */
+OP(xycb,4f) { xycb_4e(cpustate); } /* BIT 1,A=(XY+o) */
+
+OP(xycb,50) { xycb_56(cpustate); } /* BIT 2,B=(XY+o) */
+OP(xycb,51) { xycb_56(cpustate); } /* BIT 2,C=(XY+o) */
+OP(xycb,52) { xycb_56(cpustate); } /* BIT 2,D=(XY+o) */
+OP(xycb,53) { xycb_56(cpustate); } /* BIT 2,E=(XY+o) */
+OP(xycb,54) { xycb_56(cpustate); } /* BIT 2,H=(XY+o) */
+OP(xycb,55) { xycb_56(cpustate); } /* BIT 2,L=(XY+o) */
+OP(xycb,56) { BIT_XY(2,RM(cpustate, cpustate->ea)); } /* BIT 2,(XY+o) */
+OP(xycb,57) { xycb_56(cpustate); } /* BIT 2,A=(XY+o) */
+
+OP(xycb,58) { xycb_5e(cpustate); } /* BIT 3,B=(XY+o) */
+OP(xycb,59) { xycb_5e(cpustate); } /* BIT 3,C=(XY+o) */
+OP(xycb,5a) { xycb_5e(cpustate); } /* BIT 3,D=(XY+o) */
+OP(xycb,5b) { xycb_5e(cpustate); } /* BIT 3,E=(XY+o) */
+OP(xycb,5c) { xycb_5e(cpustate); } /* BIT 3,H=(XY+o) */
+OP(xycb,5d) { xycb_5e(cpustate); } /* BIT 3,L=(XY+o) */
+OP(xycb,5e) { BIT_XY(3,RM(cpustate, cpustate->ea)); } /* BIT 3,(XY+o) */
+OP(xycb,5f) { xycb_5e(cpustate); } /* BIT 3,A=(XY+o) */
+
+OP(xycb,60) { xycb_66(cpustate); } /* BIT 4,B=(XY+o) */
+OP(xycb,61) { xycb_66(cpustate); } /* BIT 4,C=(XY+o) */
+OP(xycb,62) { xycb_66(cpustate); } /* BIT 4,D=(XY+o) */
+OP(xycb,63) { xycb_66(cpustate); } /* BIT 4,E=(XY+o) */
+OP(xycb,64) { xycb_66(cpustate); } /* BIT 4,H=(XY+o) */
+OP(xycb,65) { xycb_66(cpustate); } /* BIT 4,L=(XY+o) */
+OP(xycb,66) { BIT_XY(4,RM(cpustate, cpustate->ea)); } /* BIT 4,(XY+o) */
+OP(xycb,67) { xycb_66(cpustate); } /* BIT 4,A=(XY+o) */
+
+OP(xycb,68) { xycb_6e(cpustate); } /* BIT 5,B=(XY+o) */
+OP(xycb,69) { xycb_6e(cpustate); } /* BIT 5,C=(XY+o) */
+OP(xycb,6a) { xycb_6e(cpustate); } /* BIT 5,D=(XY+o) */
+OP(xycb,6b) { xycb_6e(cpustate); } /* BIT 5,E=(XY+o) */
+OP(xycb,6c) { xycb_6e(cpustate); } /* BIT 5,H=(XY+o) */
+OP(xycb,6d) { xycb_6e(cpustate); } /* BIT 5,L=(XY+o) */
+OP(xycb,6e) { BIT_XY(5,RM(cpustate, cpustate->ea)); } /* BIT 5,(XY+o) */
+OP(xycb,6f) { xycb_6e(cpustate); } /* BIT 5,A=(XY+o) */
+
+OP(xycb,70) { xycb_76(cpustate); } /* BIT 6,B=(XY+o) */
+OP(xycb,71) { xycb_76(cpustate); } /* BIT 6,C=(XY+o) */
+OP(xycb,72) { xycb_76(cpustate); } /* BIT 6,D=(XY+o) */
+OP(xycb,73) { xycb_76(cpustate); } /* BIT 6,E=(XY+o) */
+OP(xycb,74) { xycb_76(cpustate); } /* BIT 6,H=(XY+o) */
+OP(xycb,75) { xycb_76(cpustate); } /* BIT 6,L=(XY+o) */
+OP(xycb,76) { BIT_XY(6,RM(cpustate, cpustate->ea)); } /* BIT 6,(XY+o) */
+OP(xycb,77) { xycb_76(cpustate); } /* BIT 6,A=(XY+o) */
+
+OP(xycb,78) { xycb_7e(cpustate); } /* BIT 7,B=(XY+o) */
+OP(xycb,79) { xycb_7e(cpustate); } /* BIT 7,C=(XY+o) */
+OP(xycb,7a) { xycb_7e(cpustate); } /* BIT 7,D=(XY+o) */
+OP(xycb,7b) { xycb_7e(cpustate); } /* BIT 7,E=(XY+o) */
+OP(xycb,7c) { xycb_7e(cpustate); } /* BIT 7,H=(XY+o) */
+OP(xycb,7d) { xycb_7e(cpustate); } /* BIT 7,L=(XY+o) */
+OP(xycb,7e) { BIT_XY(7,RM(cpustate, cpustate->ea)); } /* BIT 7,(XY+o) */
+OP(xycb,7f) { xycb_7e(cpustate); } /* BIT 7,A=(XY+o) */
+
+OP(xycb,80) { cpustate->_B = RES(0, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_B ); } /* RES 0,B=(XY+o) */
+OP(xycb,81) { cpustate->_C = RES(0, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_C ); } /* RES 0,C=(XY+o) */
+OP(xycb,82) { cpustate->_D = RES(0, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_D ); } /* RES 0,D=(XY+o) */
+OP(xycb,83) { cpustate->_E = RES(0, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_E ); } /* RES 0,E=(XY+o) */
+OP(xycb,84) { cpustate->_H = RES(0, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_H ); } /* RES 0,H=(XY+o) */
+OP(xycb,85) { cpustate->_L = RES(0, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_L ); } /* RES 0,L=(XY+o) */
+OP(xycb,86) { WM(cpustate, cpustate->ea, RES(0,RM(cpustate, cpustate->ea)) ); } /* RES 0,(XY+o) */
+OP(xycb,87) { cpustate->_A = RES(0, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_A ); } /* RES 0,A=(XY+o) */
+
+OP(xycb,88) { cpustate->_B = RES(1, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_B ); } /* RES 1,B=(XY+o) */
+OP(xycb,89) { cpustate->_C = RES(1, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_C ); } /* RES 1,C=(XY+o) */
+OP(xycb,8a) { cpustate->_D = RES(1, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_D ); } /* RES 1,D=(XY+o) */
+OP(xycb,8b) { cpustate->_E = RES(1, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_E ); } /* RES 1,E=(XY+o) */
+OP(xycb,8c) { cpustate->_H = RES(1, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_H ); } /* RES 1,H=(XY+o) */
+OP(xycb,8d) { cpustate->_L = RES(1, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_L ); } /* RES 1,L=(XY+o) */
+OP(xycb,8e) { WM(cpustate, cpustate->ea, RES(1,RM(cpustate, cpustate->ea)) ); } /* RES 1,(XY+o) */
+OP(xycb,8f) { cpustate->_A = RES(1, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_A ); } /* RES 1,A=(XY+o) */
+
+OP(xycb,90) { cpustate->_B = RES(2, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_B ); } /* RES 2,B=(XY+o) */
+OP(xycb,91) { cpustate->_C = RES(2, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_C ); } /* RES 2,C=(XY+o) */
+OP(xycb,92) { cpustate->_D = RES(2, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_D ); } /* RES 2,D=(XY+o) */
+OP(xycb,93) { cpustate->_E = RES(2, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_E ); } /* RES 2,E=(XY+o) */
+OP(xycb,94) { cpustate->_H = RES(2, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_H ); } /* RES 2,H=(XY+o) */
+OP(xycb,95) { cpustate->_L = RES(2, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_L ); } /* RES 2,L=(XY+o) */
+OP(xycb,96) { WM(cpustate, cpustate->ea, RES(2,RM(cpustate, cpustate->ea)) ); } /* RES 2,(XY+o) */
+OP(xycb,97) { cpustate->_A = RES(2, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_A ); } /* RES 2,A=(XY+o) */
+
+OP(xycb,98) { cpustate->_B = RES(3, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_B ); } /* RES 3,B=(XY+o) */
+OP(xycb,99) { cpustate->_C = RES(3, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_C ); } /* RES 3,C=(XY+o) */
+OP(xycb,9a) { cpustate->_D = RES(3, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_D ); } /* RES 3,D=(XY+o) */
+OP(xycb,9b) { cpustate->_E = RES(3, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_E ); } /* RES 3,E=(XY+o) */
+OP(xycb,9c) { cpustate->_H = RES(3, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_H ); } /* RES 3,H=(XY+o) */
+OP(xycb,9d) { cpustate->_L = RES(3, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_L ); } /* RES 3,L=(XY+o) */
+OP(xycb,9e) { WM(cpustate, cpustate->ea, RES(3,RM(cpustate, cpustate->ea)) ); } /* RES 3,(XY+o) */
+OP(xycb,9f) { cpustate->_A = RES(3, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_A ); } /* RES 3,A=(XY+o) */
+
+OP(xycb,a0) { cpustate->_B = RES(4, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_B ); } /* RES 4,B=(XY+o) */
+OP(xycb,a1) { cpustate->_C = RES(4, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_C ); } /* RES 4,C=(XY+o) */
+OP(xycb,a2) { cpustate->_D = RES(4, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_D ); } /* RES 4,D=(XY+o) */
+OP(xycb,a3) { cpustate->_E = RES(4, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_E ); } /* RES 4,E=(XY+o) */
+OP(xycb,a4) { cpustate->_H = RES(4, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_H ); } /* RES 4,H=(XY+o) */
+OP(xycb,a5) { cpustate->_L = RES(4, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_L ); } /* RES 4,L=(XY+o) */
+OP(xycb,a6) { WM(cpustate, cpustate->ea, RES(4,RM(cpustate, cpustate->ea)) ); } /* RES 4,(XY+o) */
+OP(xycb,a7) { cpustate->_A = RES(4, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_A ); } /* RES 4,A=(XY+o) */
+
+OP(xycb,a8) { cpustate->_B = RES(5, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_B ); } /* RES 5,B=(XY+o) */
+OP(xycb,a9) { cpustate->_C = RES(5, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_C ); } /* RES 5,C=(XY+o) */
+OP(xycb,aa) { cpustate->_D = RES(5, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_D ); } /* RES 5,D=(XY+o) */
+OP(xycb,ab) { cpustate->_E = RES(5, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_E ); } /* RES 5,E=(XY+o) */
+OP(xycb,ac) { cpustate->_H = RES(5, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_H ); } /* RES 5,H=(XY+o) */
+OP(xycb,ad) { cpustate->_L = RES(5, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_L ); } /* RES 5,L=(XY+o) */
+OP(xycb,ae) { WM(cpustate, cpustate->ea, RES(5,RM(cpustate, cpustate->ea)) ); } /* RES 5,(XY+o) */
+OP(xycb,af) { cpustate->_A = RES(5, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_A ); } /* RES 5,A=(XY+o) */
+
+OP(xycb,b0) { cpustate->_B = RES(6, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_B ); } /* RES 6,B=(XY+o) */
+OP(xycb,b1) { cpustate->_C = RES(6, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_C ); } /* RES 6,C=(XY+o) */
+OP(xycb,b2) { cpustate->_D = RES(6, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_D ); } /* RES 6,D=(XY+o) */
+OP(xycb,b3) { cpustate->_E = RES(6, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_E ); } /* RES 6,E=(XY+o) */
+OP(xycb,b4) { cpustate->_H = RES(6, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_H ); } /* RES 6,H=(XY+o) */
+OP(xycb,b5) { cpustate->_L = RES(6, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_L ); } /* RES 6,L=(XY+o) */
+OP(xycb,b6) { WM(cpustate, cpustate->ea, RES(6,RM(cpustate, cpustate->ea)) ); } /* RES 6,(XY+o) */
+OP(xycb,b7) { cpustate->_A = RES(6, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_A ); } /* RES 6,A=(XY+o) */
+
+OP(xycb,b8) { cpustate->_B = RES(7, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_B ); } /* RES 7,B=(XY+o) */
+OP(xycb,b9) { cpustate->_C = RES(7, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_C ); } /* RES 7,C=(XY+o) */
+OP(xycb,ba) { cpustate->_D = RES(7, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_D ); } /* RES 7,D=(XY+o) */
+OP(xycb,bb) { cpustate->_E = RES(7, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_E ); } /* RES 7,E=(XY+o) */
+OP(xycb,bc) { cpustate->_H = RES(7, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_H ); } /* RES 7,H=(XY+o) */
+OP(xycb,bd) { cpustate->_L = RES(7, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_L ); } /* RES 7,L=(XY+o) */
+OP(xycb,be) { WM(cpustate, cpustate->ea, RES(7,RM(cpustate, cpustate->ea)) ); } /* RES 7,(XY+o) */
+OP(xycb,bf) { cpustate->_A = RES(7, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_A ); } /* RES 7,A=(XY+o) */
+
+OP(xycb,c0) { cpustate->_B = SET(0, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_B ); } /* SET 0,B=(XY+o) */
+OP(xycb,c1) { cpustate->_C = SET(0, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_C ); } /* SET 0,C=(XY+o) */
+OP(xycb,c2) { cpustate->_D = SET(0, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_D ); } /* SET 0,D=(XY+o) */
+OP(xycb,c3) { cpustate->_E = SET(0, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_E ); } /* SET 0,E=(XY+o) */
+OP(xycb,c4) { cpustate->_H = SET(0, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_H ); } /* SET 0,H=(XY+o) */
+OP(xycb,c5) { cpustate->_L = SET(0, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_L ); } /* SET 0,L=(XY+o) */
+OP(xycb,c6) { WM(cpustate, cpustate->ea, SET(0,RM(cpustate, cpustate->ea)) ); } /* SET 0,(XY+o) */
+OP(xycb,c7) { cpustate->_A = SET(0, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_A ); } /* SET 0,A=(XY+o) */
+
+OP(xycb,c8) { cpustate->_B = SET(1, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_B ); } /* SET 1,B=(XY+o) */
+OP(xycb,c9) { cpustate->_C = SET(1, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_C ); } /* SET 1,C=(XY+o) */
+OP(xycb,ca) { cpustate->_D = SET(1, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_D ); } /* SET 1,D=(XY+o) */
+OP(xycb,cb) { cpustate->_E = SET(1, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_E ); } /* SET 1,E=(XY+o) */
+OP(xycb,cc) { cpustate->_H = SET(1, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_H ); } /* SET 1,H=(XY+o) */
+OP(xycb,cd) { cpustate->_L = SET(1, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_L ); } /* SET 1,L=(XY+o) */
+OP(xycb,ce) { WM(cpustate, cpustate->ea, SET(1,RM(cpustate, cpustate->ea)) ); } /* SET 1,(XY+o) */
+OP(xycb,cf) { cpustate->_A = SET(1, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_A ); } /* SET 1,A=(XY+o) */
+
+OP(xycb,d0) { cpustate->_B = SET(2, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_B ); } /* SET 2,B=(XY+o) */
+OP(xycb,d1) { cpustate->_C = SET(2, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_C ); } /* SET 2,C=(XY+o) */
+OP(xycb,d2) { cpustate->_D = SET(2, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_D ); } /* SET 2,D=(XY+o) */
+OP(xycb,d3) { cpustate->_E = SET(2, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_E ); } /* SET 2,E=(XY+o) */
+OP(xycb,d4) { cpustate->_H = SET(2, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_H ); } /* SET 2,H=(XY+o) */
+OP(xycb,d5) { cpustate->_L = SET(2, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_L ); } /* SET 2,L=(XY+o) */
+OP(xycb,d6) { WM(cpustate, cpustate->ea, SET(2,RM(cpustate, cpustate->ea)) ); } /* SET 2,(XY+o) */
+OP(xycb,d7) { cpustate->_A = SET(2, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_A ); } /* SET 2,A=(XY+o) */
+
+OP(xycb,d8) { cpustate->_B = SET(3, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_B ); } /* SET 3,B=(XY+o) */
+OP(xycb,d9) { cpustate->_C = SET(3, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_C ); } /* SET 3,C=(XY+o) */
+OP(xycb,da) { cpustate->_D = SET(3, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_D ); } /* SET 3,D=(XY+o) */
+OP(xycb,db) { cpustate->_E = SET(3, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_E ); } /* SET 3,E=(XY+o) */
+OP(xycb,dc) { cpustate->_H = SET(3, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_H ); } /* SET 3,H=(XY+o) */
+OP(xycb,dd) { cpustate->_L = SET(3, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_L ); } /* SET 3,L=(XY+o) */
+OP(xycb,de) { WM(cpustate, cpustate->ea, SET(3,RM(cpustate, cpustate->ea)) ); } /* SET 3,(XY+o) */
+OP(xycb,df) { cpustate->_A = SET(3, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_A ); } /* SET 3,A=(XY+o) */
+
+OP(xycb,e0) { cpustate->_B = SET(4, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_B ); } /* SET 4,B=(XY+o) */
+OP(xycb,e1) { cpustate->_C = SET(4, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_C ); } /* SET 4,C=(XY+o) */
+OP(xycb,e2) { cpustate->_D = SET(4, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_D ); } /* SET 4,D=(XY+o) */
+OP(xycb,e3) { cpustate->_E = SET(4, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_E ); } /* SET 4,E=(XY+o) */
+OP(xycb,e4) { cpustate->_H = SET(4, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_H ); } /* SET 4,H=(XY+o) */
+OP(xycb,e5) { cpustate->_L = SET(4, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_L ); } /* SET 4,L=(XY+o) */
+OP(xycb,e6) { WM(cpustate, cpustate->ea, SET(4,RM(cpustate, cpustate->ea)) ); } /* SET 4,(XY+o) */
+OP(xycb,e7) { cpustate->_A = SET(4, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_A ); } /* SET 4,A=(XY+o) */
+
+OP(xycb,e8) { cpustate->_B = SET(5, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_B ); } /* SET 5,B=(XY+o) */
+OP(xycb,e9) { cpustate->_C = SET(5, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_C ); } /* SET 5,C=(XY+o) */
+OP(xycb,ea) { cpustate->_D = SET(5, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_D ); } /* SET 5,D=(XY+o) */
+OP(xycb,eb) { cpustate->_E = SET(5, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_E ); } /* SET 5,E=(XY+o) */
+OP(xycb,ec) { cpustate->_H = SET(5, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_H ); } /* SET 5,H=(XY+o) */
+OP(xycb,ed) { cpustate->_L = SET(5, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_L ); } /* SET 5,L=(XY+o) */
+OP(xycb,ee) { WM(cpustate, cpustate->ea, SET(5,RM(cpustate, cpustate->ea)) ); } /* SET 5,(XY+o) */
+OP(xycb,ef) { cpustate->_A = SET(5, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_A ); } /* SET 5,A=(XY+o) */
+
+OP(xycb,f0) { cpustate->_B = SET(6, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_B ); } /* SET 6,B=(XY+o) */
+OP(xycb,f1) { cpustate->_C = SET(6, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_C ); } /* SET 6,C=(XY+o) */
+OP(xycb,f2) { cpustate->_D = SET(6, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_D ); } /* SET 6,D=(XY+o) */
+OP(xycb,f3) { cpustate->_E = SET(6, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_E ); } /* SET 6,E=(XY+o) */
+OP(xycb,f4) { cpustate->_H = SET(6, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_H ); } /* SET 6,H=(XY+o) */
+OP(xycb,f5) { cpustate->_L = SET(6, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_L ); } /* SET 6,L=(XY+o) */
+OP(xycb,f6) { WM(cpustate, cpustate->ea, SET(6,RM(cpustate, cpustate->ea)) ); } /* SET 6,(XY+o) */
+OP(xycb,f7) { cpustate->_A = SET(6, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_A ); } /* SET 6,A=(XY+o) */
+
+OP(xycb,f8) { cpustate->_B = SET(7, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_B ); } /* SET 7,B=(XY+o) */
+OP(xycb,f9) { cpustate->_C = SET(7, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_C ); } /* SET 7,C=(XY+o) */
+OP(xycb,fa) { cpustate->_D = SET(7, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_D ); } /* SET 7,D=(XY+o) */
+OP(xycb,fb) { cpustate->_E = SET(7, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_E ); } /* SET 7,E=(XY+o) */
+OP(xycb,fc) { cpustate->_H = SET(7, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_H ); } /* SET 7,H=(XY+o) */
+OP(xycb,fd) { cpustate->_L = SET(7, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_L ); } /* SET 7,L=(XY+o) */
+OP(xycb,fe) { WM(cpustate, cpustate->ea, SET(7,RM(cpustate, cpustate->ea)) ); } /* SET 7,(XY+o) */
+OP(xycb,ff) { cpustate->_A = SET(7, RM(cpustate, cpustate->ea) ); WM(cpustate, cpustate->ea,cpustate->_A ); } /* SET 7,A=(XY+o) */
+
diff --git a/trunk/src/emu/cpu/z8/z8.c b/trunk/src/emu/cpu/z8/z8.c
new file mode 100644
index 00000000000..444f36b4af2
--- /dev/null
+++ b/trunk/src/emu/cpu/z8/z8.c
@@ -0,0 +1,923 @@
+/**********************************************************************
+
+ Zilog Z8 Single-Chip MCU emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+/*
+
+ TODO:
+
+ - strobed I/O
+ - interrupts
+ - expose register file to disassembler
+ - decimal adjust instruction
+ - timer Tin/Tout modes
+ - serial
+ - instruction pipeline
+
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "z8.h"
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+enum
+{
+ Z8_REGISTER_P0 = 0,
+ Z8_REGISTER_P1,
+ Z8_REGISTER_P2,
+ Z8_REGISTER_P3,
+ Z8_REGISTER_SIO = 0xf0,
+ Z8_REGISTER_TMR,
+ Z8_REGISTER_T1,
+ Z8_REGISTER_PRE1,
+ Z8_REGISTER_T0,
+ Z8_REGISTER_PRE0,
+ Z8_REGISTER_P2M,
+ Z8_REGISTER_P3M,
+ Z8_REGISTER_P01M,
+ Z8_REGISTER_IPR,
+ Z8_REGISTER_IRQ,
+ Z8_REGISTER_IMR,
+ Z8_REGISTER_FLAGS,
+ Z8_REGISTER_RP,
+ Z8_REGISTER_SPH,
+ Z8_REGISTER_SPL
+};
+
+#define Z8_P3_DAV0 0x04 /* not supported */
+#define Z8_P3_DAV1 0x08 /* not supported */
+#define Z8_P3_DAV2 0x02 /* not supported */
+#define Z8_P3_RDY0 0x20 /* not supported */
+#define Z8_P3_RDY1 0x10 /* not supported */
+#define Z8_P3_RDY2 0x40 /* not supported */
+#define Z8_P3_IRQ0 0x04 /* not supported */
+#define Z8_P3_IRQ1 0x08 /* not supported */
+#define Z8_P3_IRQ2 0x02 /* not supported */
+#define Z8_P3_IRQ3 0x01 /* not supported */
+#define Z8_P3_DI 0x01 /* not supported */
+#define Z8_P3_DO 0x80 /* not supported */
+#define Z8_P3_TIN 0x02 /* not supported */
+#define Z8_P3_TOUT 0x40 /* not supported */
+#define Z8_P3_DM 0x10 /* not supported */
+
+#define Z8_PRE0_COUNT_MODULO_N 0x01
+
+#define Z8_PRE1_COUNT_MODULO_N 0x01
+#define Z8_PRE1_INTERNAL_CLOCK 0x02
+
+#define Z8_TMR_LOAD_T0 0x01
+#define Z8_TMR_ENABLE_T0 0x02
+#define Z8_TMR_LOAD_T1 0x04
+#define Z8_TMR_ENABLE_T1 0x08
+#define Z8_TMR_TIN_MASK 0x30 /* not supported */
+#define Z8_TMR_TIN_EXTERNAL_CLK 0x00 /* not supported */
+#define Z8_TMR_TIN_GATE 0x10 /* not supported */
+#define Z8_TMR_TIN_TRIGGER 0x20 /* not supported */
+#define Z8_TMR_TIN_RETRIGGER 0x30 /* not supported */
+#define Z8_TMR_TOUT_MASK 0xc0 /* not supported */
+#define Z8_TMR_TOUT_OFF 0x00 /* not supported */
+#define Z8_TMR_TOUT_T0 0x40 /* not supported */
+#define Z8_TMR_TOUT_T1 0x80 /* not supported */
+#define Z8_TMR_TOUT_INTERNAL_CLK 0xc0 /* not supported */
+
+#define Z8_P01M_P0L_MODE_MASK 0x03
+#define Z8_P01M_P0L_MODE_OUTPUT 0x00
+#define Z8_P01M_P0L_MODE_INPUT 0x01
+#define Z8_P01M_P0L_MODE_A8_A11 0x02 /* not supported */
+#define Z8_P01M_INTERNAL_STACK 0x04
+#define Z8_P01M_P1_MODE_MASK 0x18
+#define Z8_P01M_P1_MODE_OUTPUT 0x00
+#define Z8_P01M_P1_MODE_INPUT 0x08
+#define Z8_P01M_P1_MODE_AD0_AD7 0x10 /* not supported */
+#define Z8_P01M_P1_MODE_HI_Z 0x18 /* not supported */
+#define Z8_P01M_EXTENDED_TIMING 0x20 /* not supported */
+#define Z8_P01M_P0H_MODE_MASK 0xc0
+#define Z8_P01M_P0H_MODE_OUTPUT 0x00
+#define Z8_P01M_P0H_MODE_INPUT 0x40
+#define Z8_P01M_P0H_MODE_A12_A15 0x80 /* not supported */
+
+#define Z8_P3M_P2_ACTIVE_PULLUPS 0x01 /* not supported */
+#define Z8_P3M_P0_STROBED 0x04 /* not supported */
+#define Z8_P3M_P33_P34_MASK 0x18
+#define Z8_P3M_P33_P34_INPUT_OUTPUT 0x00
+#define Z8_P3M_P33_P34_INPUT_DM 0x08 /* not supported */
+#define Z8_P3M_P33_P34_INPUT_DM_2 0x10 /* not supported */
+#define Z8_P3M_P33_P34_DAV1_RDY1 0x18 /* not supported */
+#define Z8_P3M_P2_STROBED 0x20 /* not supported */
+#define Z8_P3M_P3_SERIAL 0x40 /* not supported */
+#define Z8_P3M_PARITY 0x80 /* not supported */
+
+#define Z8_IMR_ENABLE 0x80 /* not supported */
+#define Z8_IMR_RAM_PROTECT 0x40 /* not supported */
+#define Z8_IMR_ENABLE_IRQ5 0x20 /* not supported */
+#define Z8_IMR_ENABLE_IRQ4 0x10 /* not supported */
+#define Z8_IMR_ENABLE_IRQ3 0x08 /* not supported */
+#define Z8_IMR_ENABLE_IRQ2 0x04 /* not supported */
+#define Z8_IMR_ENABLE_IRQ1 0x02 /* not supported */
+#define Z8_IMR_ENABLE_IRQ0 0x01 /* not supported */
+
+#define Z8_FLAGS_F1 0x01
+#define Z8_FLAGS_F2 0x02
+#define Z8_FLAGS_H 0x04
+#define Z8_FLAGS_D 0x08
+#define Z8_FLAGS_V 0x10
+#define Z8_FLAGS_S 0x20
+#define Z8_FLAGS_Z 0x40
+#define Z8_FLAGS_C 0x80
+
+enum
+{
+ CC_F = 0, CC_LT, CC_LE, CC_ULE, CC_OV, CC_MI, CC_Z, CC_C,
+ CC_T, CC_GE, CC_GT, CC_UGT, CC_NOV, CC_PL, CC_NZ, CC_NC
+};
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define P01M cpustate->r[Z8_REGISTER_P01M]
+#define P2M cpustate->r[Z8_REGISTER_P2M]
+#define P3M cpustate->r[Z8_REGISTER_P3M]
+#define T0 cpustate->r[Z8_REGISTER_T0]
+#define T1 cpustate->r[Z8_REGISTER_T1]
+#define PRE0 cpustate->r[Z8_REGISTER_PRE0]
+#define PRE1 cpustate->r[Z8_REGISTER_PRE1]
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _z8_state z8_state;
+struct _z8_state
+{
+ address_space *program;
+ direct_read_data *direct;
+ address_space *data;
+ address_space *io;
+
+ /* registers */
+ UINT16 pc; /* program counter */
+ UINT8 r[256]; /* register file */
+ UINT8 input[4]; /* port input latches */
+ UINT8 output[4]; /* port output latches */
+ UINT8 t0; /* timer 0 current count */
+ UINT8 t1; /* timer 1 current count */
+
+ /* fake registers */
+ UINT16 fake_sp; /* fake stack pointer */
+ UINT8 fake_r[16]; /* fake working registers */
+
+ /* interrupts */
+ int irq[6]; /* interrupts */
+
+ /* execution logic */
+ int clock; /* clock */
+ int icount; /* instruction counter */
+
+ /* timers */
+ emu_timer *t0_timer;
+ emu_timer *t1_timer;
+};
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE z8_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert((device->type() == Z8601) ||
+ (device->type() == UB8830D) ||
+ (device->type() == Z8611));
+ return (z8_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+INLINE UINT8 fetch(z8_state *cpustate)
+{
+ UINT8 data = cpustate->direct->read_decrypted_byte(cpustate->pc);
+
+ cpustate->pc++;
+
+ return data;
+}
+
+INLINE UINT8 register_read(z8_state *cpustate, UINT8 offset)
+{
+ UINT8 data = 0xff;
+ UINT8 mask = 0;
+
+ switch (offset)
+ {
+ case Z8_REGISTER_P0:
+ switch (P01M & Z8_P01M_P0L_MODE_MASK)
+ {
+ case Z8_P01M_P0L_MODE_OUTPUT: data = cpustate->output[offset] & 0x0f; break;
+ case Z8_P01M_P0L_MODE_INPUT: mask = 0x0f; break;
+ default: /* A8...A11 */ data = 0x0f; break;
+ }
+
+ switch (P01M & Z8_P01M_P0H_MODE_MASK)
+ {
+ case Z8_P01M_P0H_MODE_OUTPUT: data |= cpustate->output[offset] & 0xf0; break;
+ case Z8_P01M_P0H_MODE_INPUT: mask |= 0xf0; break;
+ default: /* A12...A15 */ data |= 0xf0; break;
+ }
+
+ if (!(P3M & Z8_P3M_P0_STROBED))
+ {
+ if (mask) cpustate->input[offset] = cpustate->io->read_byte(offset);
+ }
+
+ data |= cpustate->input[offset] & mask;
+ break;
+
+ case Z8_REGISTER_P1:
+ switch (P01M & Z8_P01M_P1_MODE_MASK)
+ {
+ case Z8_P01M_P1_MODE_OUTPUT: data = cpustate->output[offset]; break;
+ case Z8_P01M_P1_MODE_INPUT: mask = 0xff; break;
+ default: /* AD0..AD7 */ data = 0xff; break;
+ }
+
+ if ((P3M & Z8_P3M_P33_P34_MASK) != Z8_P3M_P33_P34_DAV1_RDY1)
+ {
+ if (mask) cpustate->input[offset] = cpustate->io->read_byte(offset);
+ }
+
+ data |= cpustate->input[offset] & mask;
+ break;
+
+ case Z8_REGISTER_P2:
+ mask = cpustate->r[Z8_REGISTER_P2M];
+
+ if (!(P3M & Z8_P3M_P2_STROBED))
+ {
+ if (mask) cpustate->input[offset] = cpustate->io->read_byte(offset);
+ }
+
+ data = (cpustate->input[offset] & mask) | (cpustate->output[offset] & ~mask);
+ break;
+
+ case Z8_REGISTER_P3:
+ // TODO: special port 3 modes
+ if (!(P3M & 0x7c))
+ {
+ mask = 0x0f;
+ }
+
+ if (mask) cpustate->input[offset] = cpustate->io->read_byte(offset);
+
+ data = (cpustate->input[offset] & mask) | (cpustate->output[offset] & ~mask);
+ break;
+
+ case Z8_REGISTER_T0:
+ data = cpustate->t0;
+ break;
+
+ case Z8_REGISTER_T1:
+ data = cpustate->t1;
+ break;
+
+ case Z8_REGISTER_PRE1:
+ case Z8_REGISTER_PRE0:
+ case Z8_REGISTER_P2M:
+ case Z8_REGISTER_P3M:
+ case Z8_REGISTER_P01M:
+ case Z8_REGISTER_IPR:
+ /* write only */
+ break;
+
+ default:
+ data = cpustate->r[offset];
+ break;
+ }
+
+ return data;
+}
+
+INLINE UINT16 register_pair_read(z8_state *cpustate, UINT8 offset)
+{
+ return (register_read(cpustate, offset) << 8) | register_read(cpustate, offset + 1);
+}
+
+INLINE void register_write(z8_state *cpustate, UINT8 offset, UINT8 data)
+{
+ UINT8 mask = 0;
+
+ switch (offset)
+ {
+ case Z8_REGISTER_P0:
+ cpustate->output[offset] = data;
+ if ((P01M & Z8_P01M_P0L_MODE_MASK) == Z8_P01M_P0L_MODE_OUTPUT) mask |= 0x0f;
+ if ((P01M & Z8_P01M_P0H_MODE_MASK) == Z8_P01M_P0H_MODE_OUTPUT) mask |= 0xf0;
+ if (mask) cpustate->io->write_byte(offset, data & mask);
+ break;
+
+ case Z8_REGISTER_P1:
+ cpustate->output[offset] = data;
+ if ((P01M & Z8_P01M_P1_MODE_MASK) == Z8_P01M_P1_MODE_OUTPUT) mask = 0xff;
+ if (mask) cpustate->io->write_byte(offset, data & mask);
+ break;
+
+ case Z8_REGISTER_P2:
+ cpustate->output[offset] = data;
+ mask = cpustate->r[Z8_REGISTER_P2M] ^ 0xff;
+ if (mask) cpustate->io->write_byte(offset, data & mask);
+ break;
+
+ case Z8_REGISTER_P3:
+ cpustate->output[offset] = data;
+
+ // TODO: special port 3 modes
+ if (!(P3M & 0x7c))
+ {
+ mask = 0xf0;
+ }
+
+ if (mask) cpustate->io->write_byte(offset, data & mask);
+ break;
+
+ case Z8_REGISTER_SIO:
+ break;
+
+ case Z8_REGISTER_TMR:
+ if (data & Z8_TMR_LOAD_T0)
+ {
+ cpustate->t0 = T0;
+ cpustate->t0_timer->adjust(attotime::zero, 0, attotime::from_hz(cpustate->clock / 2 / 4 / ((PRE0 >> 2) + 1)));
+ }
+
+ cpustate->t0_timer->enable(data & Z8_TMR_ENABLE_T0);
+
+ if (data & Z8_TMR_LOAD_T1)
+ {
+ cpustate->t1 = T1;
+ cpustate->t1_timer->adjust(attotime::zero, 0, attotime::from_hz(cpustate->clock / 2 / 4 / ((PRE1 >> 2) + 1)));
+ }
+
+ cpustate->t1_timer->enable(data & Z8_TMR_ENABLE_T1);
+ break;
+
+ case Z8_REGISTER_P2M:
+ break;
+ case Z8_REGISTER_P3M:
+ break;
+ case Z8_REGISTER_P01M:
+ break;
+ case Z8_REGISTER_IPR:
+ break;
+ case Z8_REGISTER_IRQ:
+ break;
+ case Z8_REGISTER_IMR:
+ break;
+ case Z8_REGISTER_FLAGS:
+ break;
+ case Z8_REGISTER_RP:
+ break;
+ case Z8_REGISTER_SPH:
+ break;
+ case Z8_REGISTER_SPL:
+ break;
+ default:
+ // TODO ignore missing registers
+ break;
+ }
+
+ cpustate->r[offset] = data;
+}
+
+INLINE void register_pair_write(z8_state *cpustate, UINT8 offset, UINT16 data)
+{
+ register_write(cpustate, offset, data >> 8);
+ register_write(cpustate, offset + 1, data & 0xff);
+}
+
+INLINE UINT8 get_working_register(z8_state *cpustate, int offset)
+{
+ return (cpustate->r[Z8_REGISTER_RP] & 0xf0) | (offset & 0x0f);
+}
+
+INLINE UINT8 get_register(z8_state *cpustate, UINT8 offset)
+{
+ if ((offset & 0xf0) == 0xe0)
+ return get_working_register(cpustate, offset & 0x0f);
+ else
+ return offset;
+}
+
+INLINE UINT8 get_intermediate_register(z8_state *cpustate, int offset)
+{
+ return register_read(cpustate, get_register(cpustate, offset));
+}
+
+INLINE void stack_push_byte(z8_state *cpustate, UINT8 src)
+{
+ if (register_read(cpustate, Z8_REGISTER_P01M) & Z8_P01M_INTERNAL_STACK)
+ {
+ /* SP <- SP - 1 */
+ UINT8 sp = register_read(cpustate, Z8_REGISTER_SPL) - 1;
+ register_write(cpustate, Z8_REGISTER_SPL, sp);
+
+ /* @SP <- src */
+ register_write(cpustate, sp, src);
+ }
+ else
+ {
+ /* SP <- SP - 1 */
+ UINT16 sp = register_pair_read(cpustate, Z8_REGISTER_SPH) - 1;
+ register_pair_write(cpustate, Z8_REGISTER_SPH, sp);
+
+ /* @SP <- src */
+ cpustate->data->write_byte(sp, src);
+ }
+}
+
+INLINE void stack_push_word(z8_state *cpustate, UINT16 src)
+{
+ if (register_read(cpustate, Z8_REGISTER_P01M) & Z8_P01M_INTERNAL_STACK)
+ {
+ /* SP <- SP - 2 */
+ UINT8 sp = register_read(cpustate, Z8_REGISTER_SPL) - 2;
+ register_write(cpustate, Z8_REGISTER_SPL, sp);
+
+ /* @SP <- src */
+ register_pair_write(cpustate, sp, src);
+ }
+ else
+ {
+ /* SP <- SP - 2 */
+ UINT16 sp = register_pair_read(cpustate, Z8_REGISTER_SPH) - 2;
+ register_pair_write(cpustate, Z8_REGISTER_SPH, sp);
+
+ /* @SP <- src */
+ cpustate->data->write_word(sp, src);
+ }
+}
+
+INLINE UINT8 stack_pop_byte(z8_state *cpustate)
+{
+ if (register_read(cpustate, Z8_REGISTER_P01M) & Z8_P01M_INTERNAL_STACK)
+ {
+ /* SP <- SP + 1 */
+ UINT8 sp = register_read(cpustate, Z8_REGISTER_SPL) + 1;
+ register_write(cpustate, Z8_REGISTER_SPL, sp);
+
+ /* @SP <- src */
+ return register_read(cpustate, sp);
+ }
+ else
+ {
+ /* SP <- SP + 1 */
+ UINT16 sp = register_pair_read(cpustate, Z8_REGISTER_SPH) + 1;
+ register_pair_write(cpustate, Z8_REGISTER_SPH, sp);
+
+ /* @SP <- src */
+ return cpustate->data->read_byte(sp);
+ }
+}
+
+INLINE UINT16 stack_pop_word(z8_state *cpustate)
+{
+ if (register_read(cpustate, Z8_REGISTER_P01M) & Z8_P01M_INTERNAL_STACK)
+ {
+ /* SP <- SP + 2 */
+ UINT8 sp = register_read(cpustate, Z8_REGISTER_SPL) + 2;
+ register_write(cpustate, Z8_REGISTER_SPL, sp);
+
+ /* @SP <- src */
+ return register_read(cpustate, sp);
+ }
+ else
+ {
+ /* SP <- SP + 2 */
+ UINT16 sp = register_pair_read(cpustate, Z8_REGISTER_SPH) + 2;
+ register_pair_write(cpustate, Z8_REGISTER_SPH, sp);
+
+ /* @SP <- src */
+ return cpustate->data->read_word(sp);
+ }
+}
+
+INLINE void set_flag(z8_state *cpustate, UINT8 flag, int state)
+{
+ if (state)
+ cpustate->r[Z8_REGISTER_FLAGS] |= flag;
+ else
+ cpustate->r[Z8_REGISTER_FLAGS] &= ~flag;
+}
+
+#define set_flag_h(state) set_flag(cpustate, Z8_FLAGS_H, state);
+#define set_flag_d(state) set_flag(cpustate, Z8_FLAGS_D, state);
+#define set_flag_v(state) set_flag(cpustate, Z8_FLAGS_V, state);
+#define set_flag_s(state) set_flag(cpustate, Z8_FLAGS_S, state);
+#define set_flag_z(state) set_flag(cpustate, Z8_FLAGS_Z, state);
+#define set_flag_c(state) set_flag(cpustate, Z8_FLAGS_C, state);
+
+/***************************************************************************
+ OPCODE HANDLERS
+***************************************************************************/
+
+#define INSTRUCTION(mnemonic) INLINE void (mnemonic)(z8_state *cpustate, UINT8 opcode, int *cycles)
+
+INSTRUCTION( illegal )
+{
+ logerror("Z8: PC = %04x, Illegal opcode = %02x\n", cpustate->pc - 1, opcode);
+}
+
+#include "z8ops.c"
+
+/***************************************************************************
+ OPCODE TABLES
+***************************************************************************/
+
+typedef void (*z8_opcode_func) (z8_state *cpustate, UINT8 opcode, int *cycles);
+
+typedef struct _z8_opcode_map z8_opcode_map;
+struct _z8_opcode_map
+{
+ z8_opcode_func function;
+ int execution_cycles;
+ int pipeline_cycles;
+};
+
+static const z8_opcode_map Z8601_OPCODE_MAP[] =
+{
+ { dec_R1, 6, 5 }, { dec_IR1, 6, 5 }, { add_r1_r2, 10, 5 }, { add_r1_Ir2, 10, 5 }, { add_R2_R1, 10, 5 }, { add_IR2_R1, 10, 5 }, { add_R1_IM, 10, 5 }, { add_IR1_IM, 10, 5 },
+ { ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { illegal, 0, 0 },
+
+ { rlc_R1, 6, 5 }, { rlc_IR1, 6, 5 }, { adc_r1_r2, 6, 5 }, { adc_r1_Ir2, 6, 5 }, { adc_R2_R1, 10, 5 }, { adc_IR2_R1, 10, 5 }, { adc_R1_IM, 10, 5 }, { adc_IR1_IM, 10, 5 },
+ { ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { illegal, 0, 0 },
+
+ { inc_R1, 6, 5 }, { inc_IR1, 6, 5 }, { sub_r1_r2, 6, 5 }, { sub_r1_Ir2, 6, 5 }, { sub_R2_R1, 10, 5 }, { sub_IR2_R1, 10, 5 }, { sub_R1_IM, 10, 5 }, { sub_IR1_IM, 10, 5 },
+ { ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { illegal, 0, 0 },
+
+ { jp_IRR1, 8, 0 }, { srp_IM, 6, 1 }, { sbc_r1_r2, 6, 5 }, { sbc_r1_Ir2, 6, 5 }, { sbc_R2_R1, 10, 5 }, { sbc_IR2_R1, 10, 5 }, { sbc_R1_IM, 10, 5 }, { sbc_IR1_IM, 10, 5 },
+ { ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { illegal, 0, 0 },
+
+ { da_R1, 8, 5 }, { da_IR1, 8, 5 }, { or_r1_r2, 6, 5 }, { or_r1_Ir2, 6, 5 }, { or_R2_R1, 10, 5 }, { or_IR2_R1, 10, 5 }, { or_R1_IM, 10, 5 }, { or_IR1_IM, 10, 5 },
+ { ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { illegal, 0, 0 },
+
+ { pop_R1, 10, 5 }, { pop_IR1, 10, 5 }, { and_r1_r2, 6, 5 }, { and_r1_Ir2, 6, 5 }, { and_R2_R1, 10, 5 }, { and_IR2_R1, 10, 5 }, { and_R1_IM, 10, 5 }, { and_IR1_IM, 10, 5 },
+ { ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { illegal, 0, 0 },
+
+ { com_R1, 6, 5 }, { com_IR1, 6, 5 }, { tcm_r1_r2, 6, 5 }, { tcm_r1_Ir2, 6, 5 }, { tcm_R2_R1, 10, 5 }, { tcm_IR2_R1, 10, 5 }, { tcm_R1_IM, 10, 5 }, { tcm_IR1_IM, 10, 5 },
+ { ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { illegal, 0, 0 },
+
+ { push_R2, 10, 1 }, { push_IR2, 12, 1 },{ tm_r1_r2, 6, 5 }, { tm_r1_Ir2, 6, 5 }, { tm_R2_R1, 10, 5 }, { tm_IR2_R1, 10, 5 }, { tm_R1_IM, 10, 5 }, { tm_IR1_IM, 10, 5 },
+ { ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { illegal, 0, 0 },
+
+ { decw_RR1, 10, 5 },{ decw_IR1, 10, 5 },{ lde_r1_Irr2, 12, 0 }, { ldei_Ir1_Irr2, 18, 0 },{ illegal, 0, 0 }, { illegal, 0, 0 }, { illegal, 0, 0 }, { illegal, 0, 0 },
+ { ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { di, 6, 1 },
+
+ { rl_R1, 6, 5 }, { rl_IR1, 6, 5 }, { lde_r2_Irr1, 12, 0 }, { ldei_Ir2_Irr1, 18, 0 },{ illegal, 0, 0 }, { illegal, 0, 0 }, { illegal, 0, 0 }, { illegal, 0, 0 },
+ { ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { ei, 6, 1 },
+
+ { incw_RR1, 10, 5 },{ incw_IR1, 10, 5 },{ cp_r1_r2, 6, 5 }, { cp_r1_Ir2, 6, 5 }, { cp_R2_R1, 10, 5 }, { cp_IR2_R1, 10, 5 }, { cp_R1_IM, 10, 5 }, { cp_IR1_IM, 10, 5 },
+ { ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { ret, 14, 0 },
+
+ { clr_R1, 6, 5 }, { clr_IR1, 6, 5 }, { xor_r1_r2, 6, 5 }, { xor_r1_Ir2, 6, 5 }, { xor_R2_R1, 10, 5 }, { xor_IR2_R1, 10, 5 }, { xor_R1_IM, 10, 5 }, { xor_IR1_IM, 10, 5 },
+ { ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { iret, 16, 0 },
+
+ { rrc_R1, 6, 5 }, { rrc_IR1, 6, 5 }, { ldc_r1_Irr2, 12, 0 }, { ldci_Ir1_Irr2, 18, 0 },{ illegal, 0, 0 }, { illegal, 0, 0 }, { illegal, 0, 0 }, { ld_r1_x_R2, 10, 5 },
+ { ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { rcf, 6, 5 },
+
+ { sra_R1, 6, 5 }, { sra_IR1, 6, 5 }, { ldc_r2_Irr1, 12, 0 }, { ldci_Ir2_Irr1, 18, 0 },{ call_IRR1, 20, 0 }, { illegal, 0, 0 }, { call_DA, 20, 0 }, { ld_r2_x_R1, 10, 5 },
+ { ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { scf, 6, 5 },
+
+ { rr_R1, 6, 5 }, { rr_IR1, 6, 5 }, { illegal, 0, 0 }, { ld_r1_Ir2, 6, 5 }, { ld_R2_R1, 10, 5 }, { ld_IR2_R1, 10, 5 }, { ld_R1_IM, 10, 5 }, { ld_IR1_IM, 10, 5 },
+ { ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { ccf, 6, 5 },
+
+ { swap_R1, 8, 5 }, { swap_IR1, 8, 5 }, { illegal, 0, 0 }, { ld_Ir1_r2, 6, 5 }, { illegal, 0, 0 }, { ld_R2_IR1, 10, 5 }, { illegal, 0, 0 }, { illegal, 0, 0 },
+ { ld_r1_R2, 6, 5 }, { ld_r2_R1, 6, 5 }, { djnz_r1_RA, 10, 5 }, { jr_cc_RA, 10, 0 }, { ld_r1_IM, 6, 5 }, { jp_cc_DA, 10, 0 }, { inc_r1, 6, 5 }, { nop, 6, 0 },
+};
+
+/***************************************************************************
+ TIMER CALLBACKS
+***************************************************************************/
+
+static TIMER_CALLBACK( t0_tick )
+{
+ z8_state *cpustate = (z8_state *)ptr;
+
+ cpustate->t0--;
+
+ if (cpustate->t0 == 0)
+ {
+ cpustate->t0 = T0;
+ cpustate->t0_timer->adjust(attotime::zero, 0, attotime::from_hz(cpustate->clock / 2 / 4 / ((PRE0 >> 2) + 1)));
+ cpustate->t0_timer->enable(PRE0 & Z8_PRE0_COUNT_MODULO_N);
+ cpustate->irq[4] = ASSERT_LINE;
+ }
+}
+
+static TIMER_CALLBACK( t1_tick )
+{
+ z8_state *cpustate = (z8_state *)ptr;
+
+ cpustate->t1--;
+
+ if (cpustate->t1 == 0)
+ {
+ cpustate->t1 = T1;
+ cpustate->t1_timer->adjust(attotime::zero, 0, attotime::from_hz(cpustate->clock / 2 / 4 / ((PRE1 >> 2) + 1)));
+ cpustate->t1_timer->enable(PRE1 & Z8_PRE0_COUNT_MODULO_N);
+ cpustate->irq[5] = ASSERT_LINE;
+ }
+}
+
+/***************************************************************************
+ INITIALIZATION
+***************************************************************************/
+
+static CPU_INIT( z8 )
+{
+ z8_state *cpustate = get_safe_token(device);
+
+ /* set up the state table */
+ {
+ device_state_interface *state;
+ device->interface(state);
+ state->state_add(Z8_PC, "PC", cpustate->pc);
+ state->state_add(STATE_GENPC, "GENPC", cpustate->pc).noshow();
+ state->state_add(Z8_SP, "SP", cpustate->fake_sp).callimport().callexport();
+ state->state_add(STATE_GENSP, "GENSP", cpustate->fake_sp).callimport().callexport().noshow();
+ state->state_add(Z8_RP, "RP", cpustate->r[Z8_REGISTER_RP]);
+ state->state_add(Z8_T0, "T0", cpustate->t0);
+ state->state_add(Z8_T1, "T1", cpustate->t1);
+ state->state_add(STATE_GENFLAGS, "GENFLAGS", cpustate->r[Z8_REGISTER_FLAGS]).noshow().formatstr("%6s");
+
+ astring tempstr;
+ for (int regnum = 0; regnum < 16; regnum++)
+ state->state_add(Z8_R0 + regnum, tempstr.format("R%d", regnum), cpustate->fake_r[regnum]).callimport().callexport();
+ }
+
+ cpustate->clock = device->clock();
+
+ /* 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);
+
+ /* allocate timers */
+ cpustate->t0_timer = device->machine().scheduler().timer_alloc(FUNC(t0_tick), cpustate);
+ cpustate->t1_timer = device->machine().scheduler().timer_alloc(FUNC(t1_tick), cpustate);
+
+ /* register for state saving */
+ device->save_item(NAME(cpustate->pc));
+ device->save_item(NAME(cpustate->r));
+ device->save_item(NAME(cpustate->input));
+ device->save_item(NAME(cpustate->output));
+ device->save_item(NAME(cpustate->irq));
+}
+
+/***************************************************************************
+ EXECUTION
+***************************************************************************/
+
+static CPU_EXECUTE( z8 )
+{
+ z8_state *cpustate = get_safe_token(device);
+
+ do
+ {
+ UINT8 opcode;
+ int cycles;
+
+ debugger_instruction_hook(device, cpustate->pc);
+
+ /* TODO: sample interrupts */
+ cpustate->input[3] = cpustate->io->read_byte(3);
+
+ /* fetch opcode */
+ opcode = fetch(cpustate);
+ cycles = Z8601_OPCODE_MAP[opcode].execution_cycles;
+
+ /* execute instruction */
+ (*(Z8601_OPCODE_MAP[opcode].function))(cpustate, opcode, &cycles);
+
+ cpustate->icount -= cycles;
+ }
+ while (cpustate->icount > 0);
+}
+
+/***************************************************************************
+ RESET
+***************************************************************************/
+
+static CPU_RESET( z8 )
+{
+ z8_state *cpustate = get_safe_token(device);
+
+ cpustate->pc = 0x000c;
+
+ register_write(cpustate, Z8_REGISTER_TMR, 0x00);
+ register_write(cpustate, Z8_REGISTER_PRE1, register_read(cpustate, Z8_REGISTER_PRE1) & 0xfc);
+ register_write(cpustate, Z8_REGISTER_PRE0, register_read(cpustate, Z8_REGISTER_PRE0) & 0xfe);
+ register_write(cpustate, Z8_REGISTER_P2M, 0xff);
+ register_write(cpustate, Z8_REGISTER_P3M, 0x00);
+ register_write(cpustate, Z8_REGISTER_P01M, 0x4d);
+ register_write(cpustate, Z8_REGISTER_IRQ, 0x00);
+ register_write(cpustate, Z8_REGISTER_RP, 0x00);
+}
+
+/***************************************************************************
+ ADDRESS MAPS
+***************************************************************************/
+
+static ADDRESS_MAP_START( program_2kb, AS_PROGRAM, 8 )
+ AM_RANGE(0x0000, 0x07ff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( program_4kb, AS_PROGRAM, 8 )
+ AM_RANGE(0x0000, 0x0fff) AM_ROM
+ADDRESS_MAP_END
+
+/**************************************************************************
+ * STATE IMPORT/EXPORT
+ **************************************************************************/
+
+static CPU_IMPORT_STATE( z8 )
+{
+ z8_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case Z8_SP:
+ case Z8_GENSP:
+ cpustate->r[Z8_REGISTER_SPH] = cpustate->fake_sp >> 8;
+ cpustate->r[Z8_REGISTER_SPL] = cpustate->fake_sp & 0xff;
+ break;
+
+ case Z8_R0: case Z8_R1: case Z8_R2: case Z8_R3: case Z8_R4: case Z8_R5: case Z8_R6: case Z8_R7: case Z8_R8: case Z8_R9: case Z8_R10: case Z8_R11: case Z8_R12: case Z8_R13: case Z8_R14: case Z8_R15:
+ cpustate->r[cpustate->r[Z8_REGISTER_RP] + (entry.index() - Z8_R0)] = cpustate->fake_r[entry.index() - Z8_R0];
+ break;
+
+ default:
+ fatalerror("CPU_IMPORT_STATE(z8) called for unexpected value\n");
+ break;
+ }
+}
+
+static CPU_EXPORT_STATE( z8 )
+{
+ z8_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case Z8_SP:
+ case Z8_GENSP:
+ cpustate->fake_sp = (cpustate->r[Z8_REGISTER_SPH] << 8) | cpustate->r[Z8_REGISTER_SPL];
+ break;
+
+ case Z8_R0: case Z8_R1: case Z8_R2: case Z8_R3: case Z8_R4: case Z8_R5: case Z8_R6: case Z8_R7: case Z8_R8: case Z8_R9: case Z8_R10: case Z8_R11: case Z8_R12: case Z8_R13: case Z8_R14: case Z8_R15:
+ cpustate->fake_r[entry.index() - Z8_R0] = cpustate->r[cpustate->r[Z8_REGISTER_RP] + (entry.index() - Z8_R0)];
+ break;
+
+ default:
+ fatalerror("CPU_EXPORT_STATE(z8) called for unexpected value\n");
+ break;
+ }
+}
+
+static CPU_EXPORT_STRING( z8 )
+{
+ z8_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS: string.printf("%c%c%c%c%c%c",
+ cpustate->r[Z8_REGISTER_FLAGS] & Z8_FLAGS_C ? 'C' : '.',
+ cpustate->r[Z8_REGISTER_FLAGS] & Z8_FLAGS_Z ? 'Z' : '.',
+ cpustate->r[Z8_REGISTER_FLAGS] & Z8_FLAGS_S ? 'S' : '.',
+ cpustate->r[Z8_REGISTER_FLAGS] & Z8_FLAGS_V ? 'V' : '.',
+ cpustate->r[Z8_REGISTER_FLAGS] & Z8_FLAGS_D ? 'D' : '.',
+ cpustate->r[Z8_REGISTER_FLAGS] & Z8_FLAGS_H ? 'H' : '.'); break;
+ }
+}
+
+/***************************************************************************
+ GENERAL CONTEXT ACCESS
+***************************************************************************/
+
+static CPU_SET_INFO( z8 )
+{
+ z8_state *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ0: cpustate->irq[0] = info->i; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ1: cpustate->irq[1] = info->i; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ2: cpustate->irq[2] = info->i; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ3: cpustate->irq[3] = info->i; break;
+ }
+}
+
+static CPU_GET_INFO( z8 )
+{
+ z8_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(z8_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 4; 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 = 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 = 6; 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 = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 16; 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;
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(z8); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(z8); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(z8); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(z8); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(z8); break;
+ case CPUINFO_FCT_IMPORT_STATE: info->import_state = CPU_IMPORT_STATE_NAME(z8); break;
+ case CPUINFO_FCT_EXPORT_STATE: info->export_state = CPU_EXPORT_STATE_NAME(z8); break;
+ case CPUINFO_FCT_EXPORT_STRING: info->export_string = CPU_EXPORT_STRING_NAME(z8); 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, "Z8"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Zilog Z8"); 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 MESS Team"); break;
+ }
+}
+
+/***************************************************************************
+ CPU-SPECIFIC CONTEXT ACCESS
+***************************************************************************/
+
+CPU_GET_INFO( z8601 )
+{
+ switch (state)
+ {
+ /* --- 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;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Z8601"); break;
+
+ default: CPU_GET_INFO_CALL(z8); break;
+ }
+}
+
+CPU_GET_INFO( ub8830d )
+{
+ switch (state)
+ {
+ /* --- 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;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "UB8830D"); break;
+
+ default: CPU_GET_INFO_CALL(z8); break;
+ }
+}
+
+CPU_GET_INFO( z8611 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers --- */
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(program_4kb); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Z8611"); break;
+
+ default: CPU_GET_INFO_CALL(z8); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(Z8601, z8601);
+DEFINE_LEGACY_CPU_DEVICE(UB8830D, ub8830d);
+DEFINE_LEGACY_CPU_DEVICE(Z8611, z8611);
diff --git a/trunk/src/emu/cpu/z8/z8.h b/trunk/src/emu/cpu/z8/z8.h
new file mode 100644
index 00000000000..61735952450
--- /dev/null
+++ b/trunk/src/emu/cpu/z8/z8.h
@@ -0,0 +1,37 @@
+/**********************************************************************
+
+ Zilog Z8 Single-Chip MCU emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __Z8_H__
+#define __Z8_H__
+
+
+enum
+{
+ Z8_PC, Z8_SP, Z8_RP, Z8_T0, Z8_T1,
+
+ Z8_R0, Z8_R1, Z8_R2, Z8_R3, Z8_R4, Z8_R5, Z8_R6, Z8_R7, Z8_R8, Z8_R9, Z8_R10, Z8_R11, Z8_R12, Z8_R13, Z8_R14, Z8_R15,
+
+ Z8_GENPC = STATE_GENPC,
+ Z8_GENSP = STATE_GENSP
+};
+
+/* Zilog Z8601 */
+DECLARE_LEGACY_CPU_DEVICE(Z8601, z8601);
+
+/* VEB Mikroelektronik Erfurt UB8830D MME */
+DECLARE_LEGACY_CPU_DEVICE(UB8830D, ub8830d);
+
+/* Zilog Z8611 */
+DECLARE_LEGACY_CPU_DEVICE(Z8611, z8611);
+
+CPU_DISASSEMBLE( z8 );
+
+#endif
diff --git a/trunk/src/emu/cpu/z8/z8dasm.c b/trunk/src/emu/cpu/z8/z8dasm.c
new file mode 100644
index 00000000000..1e8eba79c4d
--- /dev/null
+++ b/trunk/src/emu/cpu/z8/z8dasm.c
@@ -0,0 +1,378 @@
+#include "emu.h"
+#include "debugger.h"
+#include "z8.h"
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+static const char *const REGISTER_NAME[256] =
+{
+ "P0", "P1", "P2", "P3", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "SIO", "TMR", "T1", "PRE1", "T0", "PRE0", "P2M", "P3M", "P01M", "IPR", "IRQ", "IMR", "FLAGS", "RP", "SPH", "SPL"
+};
+
+static const char *const CONDITION_CODE[16] =
+{
+ "F", "LT", "LE", "ULE", "OV", "MI", "Z", "C",
+ "", "GE", "GT", "UGT", "NOV", "PL", "NZ", "NC"
+};
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define r "R%u"
+#define Ir "@R%u"
+#define R "%02Xh"
+#define RR "%02Xh"
+#define IR "@%02Xh"
+#define Irr "@RR%u"
+#define IRR "@%02Xh"
+#define IM "#%02Xh"
+#define X "%02Xh(R%u)"
+#define DA "%04Xh"
+#define RA "%04Xh"
+
+#define B0 oprom[0]
+#define B1 oprom[1]
+#define B0H (B0 >> 4)
+#define B0L (B0 & 0x0f)
+#define OPH (opcode >> 4)
+
+#define ARG(_formatting, _value) { if (argc) dst += sprintf(dst, ", "); dst += sprintf(dst, _formatting, _value); argc++; }
+
+#define arg_name(_value) ARG("%s", REGISTER_NAME[_value])
+#define arg_cc ARG("%s", CONDITION_CODE[OPH])
+#define arg_r(_value) ARG(r, _value)
+#define arg_Ir(_value) ARG(Ir, _value)
+#define arg_Irr(_value) ARG(Irr, _value & 0x0f)
+#define arg_R(_value) if ((_value & 0xf0) == 0xe0) ARG(r, _value & 0x0f) else if ((_value < 4) || (_value >= 0xf0)) arg_name(_value) else ARG(R, _value)
+#define arg_RR(_value) if ((_value & 0xf0) == 0xe0) ARG(r, _value & 0x0f) else ARG(R, _value)
+#define arg_IR(_value) if ((_value & 0xf0) == 0xe0) ARG(Ir, _value & 0x0f) else ARG(IR, _value)
+#define arg_IRR(_value) if ((_value & 0xf0) == 0xe0) ARG(Irr, _value & 0x0f) else ARG(IRR, _value)
+#define arg_IM(_value) ARG(IM, _value)
+#define arg_RA ARG(RA, pc + (INT8)B0 + 2)
+#define arg_DA ARG(DA, B0 << 8 | B1)
+#define arg_X(_value1, _value2) { if (argc) dst += sprintf(dst, ", "); dst += sprintf(dst, X, _value1, _value2); argc++; }
+
+#define illegal dst += sprintf(dst, "Illegal")
+#define mnemonic(_mnemonic) dst += sprintf(dst, "%-5s", _mnemonic)
+#define bytes(_count) oprom += (_count - 1)
+#define step_over flags = DASMFLAG_STEP_OVER
+#define step_out flags = DASMFLAG_STEP_OUT
+
+/***************************************************************************
+ DISASSEMBLER
+***************************************************************************/
+
+CPU_DISASSEMBLE( z8 )
+{
+ const UINT8 *startrom = oprom;
+ UINT32 flags = 0;
+ UINT8 opcode = *oprom++;
+ char *dst = buffer;
+ int argc = 0;
+
+ switch (pc)
+ {
+ case 0x0000:
+ case 0x0002:
+ case 0x0004:
+ case 0x0006:
+ case 0x0008:
+ case 0x000a:
+ sprintf(buffer, "IRQ%u Vector %04Xh", pc / 2, opcode << 8 | *oprom++); break;
+ default:
+ switch (opcode)
+ {
+ case 0x00: mnemonic("DEC"); arg_R(B0); bytes(2); break;
+ case 0x01: mnemonic("DEC"); arg_IR(B0); bytes(2); break;
+ case 0x02: mnemonic("ADD"); arg_r(B0H); arg_r(B0L); bytes(2); break;
+ case 0x03: mnemonic("ADD"); arg_r(B0H); arg_Ir(B0L); bytes(2); break;
+ case 0x04: mnemonic("ADD"); arg_R(B1); arg_R(B0); bytes(3); break;
+ case 0x05: mnemonic("ADD"); arg_R(B1); arg_IR(B0); bytes(3); break;
+ case 0x06: mnemonic("ADD"); arg_R(B0); arg_IM(B1); bytes(3); break;
+ case 0x07: mnemonic("ADD"); arg_IR(B0); arg_IM(B1); bytes(3); break;
+ case 0x08: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
+ case 0x09: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
+ case 0x0a: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
+ case 0x0b: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
+ case 0x0c: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
+ case 0x0d: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
+ case 0x0e: mnemonic("INC"); arg_r(OPH); break;
+ case 0x0f: illegal; break;
+
+ case 0x10: mnemonic("RLC"); arg_R(B0); bytes(2); break;
+ case 0x11: mnemonic("RLC"); arg_IR(B0); bytes(2); break;
+ case 0x12: mnemonic("ADC"); arg_r(B0H); arg_r(B0L); bytes(2); break;
+ case 0x13: mnemonic("ADC"); arg_r(B0H); arg_Ir(B0L); bytes(2); break;
+ case 0x14: mnemonic("ADC"); arg_R(B1); arg_R(B0); bytes(3); break;
+ case 0x15: mnemonic("ADC"); arg_R(B1); arg_IR(B0); bytes(3); break;
+ case 0x16: mnemonic("ADC"); arg_R(B0); arg_IM(B1); bytes(3); break;
+ case 0x17: mnemonic("ADC"); arg_IR(B0); arg_IM(B1); bytes(3); break;
+ case 0x18: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
+ case 0x19: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
+ case 0x1a: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
+ case 0x1b: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
+ case 0x1c: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
+ case 0x1d: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
+ case 0x1e: mnemonic("INC"); arg_r(OPH); break;
+ case 0x1f: illegal; break;
+
+ case 0x20: mnemonic("INC"); arg_R(B0); bytes(2); break;
+ case 0x21: mnemonic("INC"); arg_IR(B0); bytes(2); break;
+ case 0x22: mnemonic("SUB"); arg_r(B0H); arg_r(B0L); bytes(2); break;
+ case 0x23: mnemonic("SUB"); arg_r(B0H); arg_Ir(B0L); bytes(2); break;
+ case 0x24: mnemonic("SUB"); arg_R(B1); arg_R(B0); bytes(3); break;
+ case 0x25: mnemonic("SUB"); arg_R(B1); arg_IR(B0); bytes(3); break;
+ case 0x26: mnemonic("SUB"); arg_R(B0); arg_IM(B1); bytes(3); break;
+ case 0x27: mnemonic("SUB"); arg_IR(B0); arg_IM(B1); bytes(3); break;
+ case 0x28: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
+ case 0x29: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
+ case 0x2a: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
+ case 0x2b: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
+ case 0x2c: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
+ case 0x2d: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
+ case 0x2e: mnemonic("INC"); arg_r(OPH); break;
+ case 0x2f: illegal; break;
+
+ case 0x30: mnemonic("JP"); arg_IRR(B0); bytes(2); break;
+ case 0x31: mnemonic("SRP"); arg_IM(*oprom++); break;
+ case 0x32: mnemonic("SBC"); arg_r(B0H); arg_r(B0L); bytes(2); break;
+ case 0x33: mnemonic("SBC"); arg_r(B0H); arg_Ir(B0L); bytes(2); break;
+ case 0x34: mnemonic("SBC"); arg_R(B1); arg_R(B0); bytes(3); break;
+ case 0x35: mnemonic("SBC"); arg_R(B1); arg_IR(B0); bytes(3); break;
+ case 0x36: mnemonic("SBC"); arg_R(B0); arg_IM(B1); bytes(3); break;
+ case 0x37: mnemonic("SBC"); arg_IR(B0); arg_IM(B1); bytes(3); break;
+ case 0x38: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
+ case 0x39: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
+ case 0x3a: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
+ case 0x3b: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
+ case 0x3c: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
+ case 0x3d: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
+ case 0x3e: mnemonic("INC"); arg_r(OPH); break;
+ case 0x3f: illegal; break;
+
+ case 0x40: mnemonic("DA"); arg_R(B0); bytes(2); break;
+ case 0x41: mnemonic("DA"); arg_IR(B0); bytes(2); break;
+ case 0x42: mnemonic("OR"); arg_r(B0H); arg_r(B0L); bytes(2); break;
+ case 0x43: mnemonic("OR"); arg_r(B0H); arg_Ir(B0L); bytes(2); break;
+ case 0x44: mnemonic("OR"); arg_R(B1); arg_R(B0); bytes(3); break;
+ case 0x45: mnemonic("OR"); arg_R(B1); arg_IR(B0); bytes(3); break;
+ case 0x46: mnemonic("OR"); arg_R(B0); arg_IM(B1); bytes(3); break;
+ case 0x47: mnemonic("OR"); arg_IR(B0); arg_IM(B1); bytes(3); break;
+ case 0x48: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
+ case 0x49: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
+ case 0x4a: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
+ case 0x4b: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
+ case 0x4c: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
+ case 0x4d: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
+ case 0x4e: mnemonic("INC"); arg_r(OPH); break;
+ case 0x4f: illegal; /* mnemonic("WDH"); */ break;
+
+ case 0x50: mnemonic("POP"); arg_R(B0); bytes(2); break;
+ case 0x51: mnemonic("POP"); arg_IR(B0); bytes(2); break;
+ case 0x52: mnemonic("AND"); arg_r(B0H); arg_r(B0L); bytes(2); break;
+ case 0x53: mnemonic("AND"); arg_r(B0H); arg_Ir(B0L); bytes(2); break;
+ case 0x54: mnemonic("AND"); arg_R(B1); arg_R(B0); bytes(3); break;
+ case 0x55: mnemonic("AND"); arg_R(B1); arg_IR(B0); bytes(3); break;
+ case 0x56: mnemonic("AND"); arg_R(B0); arg_IM(B1); bytes(3); break;
+ case 0x57: mnemonic("AND"); arg_IR(B0); arg_IM(B1); bytes(3); break;
+ case 0x58: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
+ case 0x59: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
+ case 0x5a: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
+ case 0x5b: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
+ case 0x5c: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
+ case 0x5d: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
+ case 0x5e: mnemonic("INC"); arg_r(OPH); break;
+ case 0x5f: illegal; /* mnemonic("WDT"); */ break;
+
+ case 0x60: mnemonic("COM"); arg_R(B0); bytes(2); break;
+ case 0x61: mnemonic("COM"); arg_IR(B0); bytes(2); break;
+ case 0x62: mnemonic("TCM"); arg_r(B0H); arg_r(B0L); bytes(2); break;
+ case 0x63: mnemonic("TCM"); arg_r(B0H); arg_Ir(B0L); bytes(2); break;
+ case 0x64: mnemonic("TCM"); arg_R(B1); arg_R(B0); bytes(3); break;
+ case 0x65: mnemonic("TCM"); arg_R(B1); arg_IR(B0); bytes(3); break;
+ case 0x66: mnemonic("TCM"); arg_R(B0); arg_IM(B1); bytes(3); break;
+ case 0x67: mnemonic("TCM"); arg_IR(B0); arg_IM(B1); bytes(3); break;
+ case 0x68: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
+ case 0x69: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
+ case 0x6a: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
+ case 0x6b: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
+ case 0x6c: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
+ case 0x6d: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
+ case 0x6e: mnemonic("INC"); arg_r(OPH); break;
+ case 0x6f: illegal; /* mnemonic("STOP"); */ break;
+
+ case 0x70: mnemonic("PUSH"); arg_R(B0); bytes(2); break;
+ case 0x71: mnemonic("PUSH"); arg_IR(B0); bytes(2); break;
+ case 0x72: mnemonic("TM"); arg_r(B0H); arg_r(B0L); bytes(2); break;
+ case 0x73: mnemonic("TM"); arg_r(B0H); arg_Ir(B0L); bytes(2); break;
+ case 0x74: mnemonic("TM"); arg_R(B1); arg_R(B0); bytes(3); break;
+ case 0x75: mnemonic("TM"); arg_R(B1); arg_IR(B0); bytes(3); break;
+ case 0x76: mnemonic("TM"); arg_R(B0); arg_IM(B1); bytes(3); break;
+ case 0x77: mnemonic("TM"); arg_IR(B0); arg_IM(B1); bytes(3); break;
+ case 0x78: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
+ case 0x79: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
+ case 0x7a: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
+ case 0x7b: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
+ case 0x7c: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
+ case 0x7d: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
+ case 0x7e: mnemonic("INC"); arg_r(OPH); break;
+ case 0x7f: illegal; /* mnemonic("HALT"); */ break;
+
+ case 0x80: mnemonic("DECW"); arg_RR(*oprom++); break;
+ case 0x81: mnemonic("DECW"); arg_IR(B0); bytes(2); break;
+ case 0x82: mnemonic("LDE"); arg_r(B0H); arg_Irr(B0L); bytes(2); break;
+ case 0x83: mnemonic("LDEI"); arg_Ir(B0H); arg_Irr(B0L); bytes(2); break;
+ case 0x84: illegal; break;
+ case 0x85: illegal; break;
+ case 0x86: illegal; break;
+ case 0x87: illegal; break;
+ case 0x88: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
+ case 0x89: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
+ case 0x8a: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
+ case 0x8b: mnemonic("JR"); arg_RA; bytes(2); break;
+ case 0x8c: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
+ case 0x8d: mnemonic("JP"); arg_DA; bytes(3); break;
+ case 0x8e: mnemonic("INC"); arg_r(OPH); break;
+ case 0x8f: mnemonic("DI"); break;
+
+ case 0x90: mnemonic("RL"); arg_R(B0); bytes(2); break;
+ case 0x91: mnemonic("RL"); arg_IR(B0); bytes(2); break;
+ case 0x92: mnemonic("LDE"); arg_r(B0L); arg_Irr(B0H); bytes(2); break;
+ case 0x93: mnemonic("LDEI"); arg_Ir(B0L); arg_Irr(B0H); bytes(2); break;
+ case 0x94: illegal; break;
+ case 0x95: illegal; break;
+ case 0x96: illegal; break;
+ case 0x97: illegal; break;
+ case 0x98: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
+ case 0x99: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
+ case 0x9a: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
+ case 0x9b: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
+ case 0x9c: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
+ case 0x9d: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
+ case 0x9e: mnemonic("INC"); arg_r(OPH); break;
+ case 0x9f: mnemonic("EI"); break;
+
+ case 0xa0: mnemonic("INCW"); arg_RR(B0); bytes(2); break;
+ case 0xa1: mnemonic("INCW"); arg_IR(B0); bytes(2); break;
+ case 0xa2: mnemonic("CP"); arg_r(B0H); arg_r(B0L); bytes(2); break;
+ case 0xa3: mnemonic("CP"); arg_r(B0H); arg_Ir(B0L); bytes(2); break;
+ case 0xa4: mnemonic("CP"); arg_R(B1); arg_R(B0); bytes(3); break;
+ case 0xa5: mnemonic("CP"); arg_R(B1); arg_IR(B0); bytes(3); break;
+ case 0xa6: mnemonic("CP"); arg_R(B0); arg_IM(B1); bytes(3); break;
+ case 0xa7: mnemonic("CP"); arg_IR(B0); arg_IM(B1); bytes(3); break;
+ case 0xa8: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
+ case 0xa9: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
+ case 0xaa: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
+ case 0xab: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
+ case 0xac: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
+ case 0xad: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
+ case 0xae: mnemonic("INC"); arg_r(OPH); break;
+ case 0xaf: mnemonic("RET"); step_out; break;
+
+ case 0xb0: mnemonic("CLR"); arg_R(B0); bytes(2); break;
+ case 0xb1: mnemonic("CLR"); arg_IR(B0); bytes(2); break;
+ case 0xb2: mnemonic("XOR"); arg_r(B0H); arg_r(B0L); bytes(2); break;
+ case 0xb3: mnemonic("XOR"); arg_r(B0H); arg_Ir(B0L); bytes(2); break;
+ case 0xb4: mnemonic("XOR"); arg_R(B1); arg_R(B0); bytes(3); break;
+ case 0xb5: mnemonic("XOR"); arg_R(B1); arg_IR(B0); bytes(3); break;
+ case 0xb6: mnemonic("XOR"); arg_R(B0); arg_IM(B1); bytes(3); break;
+ case 0xb7: mnemonic("XOR"); arg_IR(B0); arg_IM(B1); bytes(3); break;
+ case 0xb8: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
+ case 0xb9: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
+ case 0xba: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
+ case 0xbb: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
+ case 0xbc: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
+ case 0xbd: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
+ case 0xbe: mnemonic("INC"); arg_r(OPH); break;
+ case 0xbf: mnemonic("IRET"); step_out; break;
+
+ case 0xc0: mnemonic("RRC"); arg_R(B0); bytes(2); break;
+ case 0xc1: mnemonic("RRC"); arg_IR(B0); bytes(2); break;
+ case 0xc2: mnemonic("LDC"); arg_r(B0H); arg_Irr(B0L); bytes(2); break;
+ case 0xc3: mnemonic("LDCI"); arg_Ir(B0H); arg_Irr(B0L); bytes(2); break;
+ case 0xc4: illegal; break;
+ case 0xc5: illegal; break;
+ case 0xc6: illegal; break;
+ case 0xc7: mnemonic("LD"); arg_r(B0H); arg_X(B1, B0L); bytes(3); break;
+ case 0xc8: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
+ case 0xc9: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
+ case 0xca: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
+ case 0xcb: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
+ case 0xcc: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
+ case 0xcd: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
+ case 0xce: mnemonic("INC"); arg_r(OPH); break;
+ case 0xcf: mnemonic("RCF"); break;
+
+ case 0xd0: mnemonic("SRA"); arg_R(B0); bytes(2); break;
+ case 0xd1: mnemonic("SRA"); arg_IR(B0); bytes(2); break;
+ case 0xd2: mnemonic("LDC"); arg_Irr(B0L); arg_r(B0H); bytes(2); break;
+ case 0xd3: mnemonic("LDCI"); arg_Irr(B0L); arg_Ir(B0H); bytes(2); break;
+ case 0xd4: mnemonic("CALL"); arg_IRR(B0); bytes(2); step_over; break;
+ case 0xd5: illegal; break;
+ case 0xd6: mnemonic("CALL"); arg_DA; bytes(3); step_over; break;
+ case 0xd7: mnemonic("LD"); arg_r(B0L); arg_X(B1, B0H); bytes(3); break;
+ case 0xd8: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
+ case 0xd9: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
+ case 0xda: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
+ case 0xdb: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
+ case 0xdc: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
+ case 0xdd: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
+ case 0xde: mnemonic("INC"); arg_r(OPH); break;
+ case 0xdf: mnemonic("SCF"); break;
+
+ case 0xe0: mnemonic("RR"); arg_R(B0); bytes(2); break;
+ case 0xe1: mnemonic("RR"); arg_IR(B0); bytes(2); break;
+ case 0xe2: illegal; break;
+ case 0xe3: mnemonic("LD"); arg_r(B0H); arg_Ir(B0L); bytes(2); break;
+ case 0xe4: mnemonic("LD"); arg_R(B1); arg_R(B0); bytes(3); break;
+ case 0xe5: mnemonic("LD"); arg_R(B1); arg_IR(B0); bytes(3); break;
+ case 0xe6: mnemonic("LD"); arg_R(B0); arg_IM(B1); bytes(3); break;
+ case 0xe7: mnemonic("LD"); arg_IR(B0); arg_IM(B1); bytes(3); break;
+ case 0xe8: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
+ case 0xe9: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
+ case 0xea: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
+ case 0xeb: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
+ case 0xec: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
+ case 0xed: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
+ case 0xee: mnemonic("INC"); arg_r(OPH); break;
+ case 0xef: mnemonic("CCF"); break;
+
+ case 0xf0: mnemonic("SWAP"); arg_R(B0); bytes(2); break;
+ case 0xf1: mnemonic("SWAP"); arg_IR(B0); bytes(2); break;
+ case 0xf2: illegal; break;
+ case 0xf3: mnemonic("LD"); arg_Ir(B0H); arg_r(B0L); bytes(2); break;
+ case 0xf4: illegal; break;
+ case 0xf5: mnemonic("LD"); arg_IR(B0); arg_R(B1); bytes(3); break;
+ case 0xf6: illegal; break;
+ case 0xf7: illegal; break;
+ case 0xf8: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
+ case 0xf9: mnemonic("LD"); arg_R(B0); arg_r(OPH); bytes(2); break;
+ case 0xfa: mnemonic("DJNZ"); arg_r(OPH); arg_RA; bytes(2); break;
+ case 0xfb: mnemonic("JR"); arg_cc; arg_RA; bytes(2); break;
+ case 0xfc: mnemonic("LD"); arg_r(OPH); arg_IM(B0); bytes(2); break;
+ case 0xfd: mnemonic("JP"); arg_cc; arg_DA; bytes(3); break;
+ case 0xfe: mnemonic("INC"); arg_r(OPH); break;
+ case 0xff: mnemonic("NOP"); break;
+ }
+ }
+
+ return (oprom - startrom) | flags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/z8/z8ops.c b/trunk/src/emu/cpu/z8/z8ops.c
new file mode 100644
index 00000000000..43ef894235e
--- /dev/null
+++ b/trunk/src/emu/cpu/z8/z8ops.c
@@ -0,0 +1,746 @@
+/**********************************************************************
+
+ Zilog Z8 Single-Chip MCU emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define read(_reg) register_read(cpustate, _reg)
+#define r(_data) get_working_register(cpustate, _data)
+#define Ir(_data) get_intermediate_register(cpustate, get_working_register(cpustate, _data))
+#define R get_register(cpustate, fetch(cpustate))
+#define IR get_intermediate_register(cpustate, get_register(cpustate, fetch(cpustate)))
+#define RR get_intermediate_register(cpustate, get_register(cpustate, fetch(cpustate)))
+#define IM fetch(cpustate)
+#define flag(_flag) ((cpustate->r[Z8_REGISTER_FLAGS] & Z8_FLAGS##_##_flag) ? 1 : 0)
+
+#define mode_r1_r2(_func) \
+ UINT8 dst_src = fetch(cpustate);\
+ UINT8 dst = r(dst_src >> 4);\
+ UINT8 src = read(r(dst_src & 0x0f));\
+ _func(cpustate, dst, src);
+
+#define mode_r1_Ir2(_func) \
+ UINT8 dst_src = fetch(cpustate);\
+ UINT8 dst = r(dst_src >> 4);\
+ UINT8 src = read(Ir(dst_src & 0x0f));\
+ _func(cpustate, dst, src);
+
+#define mode_R2_R1(_func) \
+ UINT8 src = read(R);\
+ UINT8 dst = R;\
+ _func(cpustate, dst, src);
+
+#define mode_IR2_R1(_func) \
+ UINT8 src = read(R);\
+ UINT8 dst = IR;\
+ _func(cpustate, dst, src);
+
+#define mode_R1_IM(_func) \
+ UINT8 dst = R;\
+ UINT8 src = IM;\
+ _func(cpustate, dst, src);
+
+#define mode_IR1_IM(_func) \
+ UINT8 dst = IR;\
+ UINT8 src = IM;\
+ _func(cpustate, dst, src);
+
+#define mode_r1(_func) \
+ UINT8 dst = r(opcode >> 4);\
+ _func(cpustate, dst);
+
+#define mode_R1(_func) \
+ UINT8 dst = R;\
+ _func(cpustate, dst);
+
+#define mode_RR1(_func) \
+ UINT8 dst = R;\
+ _func(cpustate, dst);
+
+#define mode_IR1(_func) \
+ UINT8 dst = IR;\
+ _func(cpustate, dst);
+
+#define mode_r1_IM(_func) \
+ UINT8 dst = r(opcode >> 4);\
+ UINT8 src = IM;\
+ _func(cpustate, dst, src);
+
+#define mode_r1_R2(_func) \
+ UINT8 dst = r(opcode >> 4);\
+ UINT8 src = read(R);\
+ _func(cpustate, dst, src);
+
+#define mode_r2_R1(_func) \
+ UINT8 src = read(r(opcode >> 4));\
+ UINT8 dst = R;\
+ _func(cpustate, dst, src);
+
+#define mode_Ir1_r2(_func) \
+ UINT8 dst_src = fetch(cpustate);\
+ UINT8 dst = Ir(dst_src >> 4);\
+ UINT8 src = read(r(dst_src & 0x0f));\
+ _func(cpustate, dst, src);
+
+#define mode_R2_IR1(_func) \
+ UINT8 src = read(R);\
+ UINT8 dst = IR;\
+ _func(cpustate, dst, src);
+
+#define mode_r1_x_R2(_func) \
+ UINT8 dst_src = fetch(cpustate);\
+ UINT8 dst = r(dst_src >> 4);\
+ UINT8 src = read(read(r(dst_src & 0x0f)) + R);\
+ _func(cpustate, dst, src);
+
+#define mode_r2_x_R1(_func) \
+ UINT8 dst_src = fetch(cpustate);\
+ UINT8 dst = R + read(r(dst_src & 0x0f));\
+ UINT8 src = read(r(dst_src >> 4));\
+ _func(cpustate, dst, src);
+
+/***************************************************************************
+ LOAD INSTRUCTIONS
+***************************************************************************/
+
+static void clear(z8_state *cpustate, UINT8 dst)
+{
+ /* dst <- 0 */
+ register_write(cpustate, dst, 0);
+}
+
+INSTRUCTION( clr_R1 ) { mode_R1(clear) }
+INSTRUCTION( clr_IR1 ) { mode_IR1(clear) }
+
+static void load(z8_state *cpustate, UINT8 dst, UINT8 src)
+{
+ /* dst <- src */
+ register_write(cpustate, dst, src);
+}
+
+INSTRUCTION( ld_r1_IM ) { mode_r1_IM(load) }
+INSTRUCTION( ld_r1_R2 ) { mode_r1_R2(load) }
+INSTRUCTION( ld_r2_R1 ) { mode_r2_R1(load) }
+INSTRUCTION( ld_Ir1_r2 ) { mode_Ir1_r2(load) }
+INSTRUCTION( ld_R2_IR1 ) { mode_R2_IR1(load) }
+INSTRUCTION( ld_r1_x_R2 ) { mode_r1_x_R2(load) }
+INSTRUCTION( ld_r2_x_R1 ) { mode_r2_x_R1(load) }
+
+INSTRUCTION( ld_r1_r2 ) { mode_r1_r2(load) }
+INSTRUCTION( ld_r1_Ir2 ) { mode_r1_Ir2(load) }
+INSTRUCTION( ld_R2_R1 ) { mode_R2_R1(load) }
+INSTRUCTION( ld_IR2_R1 ) { mode_IR2_R1(load) }
+INSTRUCTION( ld_R1_IM ) { mode_R1_IM(load) }
+INSTRUCTION( ld_IR1_IM ) { mode_IR1_IM(load) }
+
+static void load_from_memory(z8_state *cpustate, address_space *space)
+{
+ UINT8 operands = fetch(cpustate);
+ UINT8 dst = get_working_register(cpustate, operands >> 4);
+ UINT8 src = get_working_register(cpustate, operands & 0x0f);
+
+ UINT16 address = register_pair_read(cpustate, src);
+ UINT8 data = cpustate->direct->read_decrypted_byte(address);
+
+ register_write(cpustate, dst, data);
+}
+
+static void load_to_memory(z8_state *cpustate, address_space *space)
+{
+ UINT8 operands = fetch(cpustate);
+ UINT8 src = get_working_register(cpustate, operands >> 4);
+ UINT8 dst = get_working_register(cpustate, operands & 0x0f);
+
+ UINT16 address = register_pair_read(cpustate, dst);
+ UINT8 data = register_read(cpustate, src);
+
+ cpustate->program->write_byte(address, data);
+}
+
+static void load_from_memory_autoinc(z8_state *cpustate, address_space *space)
+{
+ UINT8 operands = fetch(cpustate);
+ UINT8 dst = get_working_register(cpustate, operands >> 4);
+ UINT8 real_dst = get_intermediate_register(cpustate, dst);
+ UINT8 src = get_working_register(cpustate, operands & 0x0f);
+
+ UINT16 address = register_pair_read(cpustate, src);
+ UINT8 data = cpustate->direct->read_decrypted_byte(address);
+
+ register_write(cpustate, real_dst, data);
+
+ register_write(cpustate, dst, real_dst + 1);
+ register_pair_write(cpustate, src, address + 1);
+}
+
+static void load_to_memory_autoinc(z8_state *cpustate, address_space *space)
+{
+ UINT8 operands = fetch(cpustate);
+ UINT8 src = get_working_register(cpustate, operands >> 4);
+ UINT8 dst = get_working_register(cpustate, operands & 0x0f);
+ UINT8 real_src = get_intermediate_register(cpustate, src);
+
+ UINT16 address = register_pair_read(cpustate, dst);
+ UINT8 data = register_read(cpustate, real_src);
+
+ cpustate->program->write_byte(address, data);
+
+ register_pair_write(cpustate, dst, address + 1);
+ register_write(cpustate, src, real_src + 1);
+}
+
+INSTRUCTION( ldc_r1_Irr2 ) { load_from_memory(cpustate, cpustate->program); }
+INSTRUCTION( ldc_r2_Irr1 ) { load_to_memory(cpustate, cpustate->program); }
+INSTRUCTION( ldci_Ir1_Irr2 ) { load_from_memory_autoinc(cpustate, cpustate->program); }
+INSTRUCTION( ldci_Ir2_Irr1 ) { load_to_memory_autoinc(cpustate, cpustate->program); }
+INSTRUCTION( lde_r1_Irr2 ) { load_from_memory(cpustate, cpustate->data); }
+INSTRUCTION( lde_r2_Irr1 ) { load_to_memory(cpustate, cpustate->data); }
+INSTRUCTION( ldei_Ir1_Irr2 ) { load_from_memory_autoinc(cpustate, cpustate->data); }
+INSTRUCTION( ldei_Ir2_Irr1 ) { load_to_memory_autoinc(cpustate, cpustate->data); }
+
+static void pop(z8_state *cpustate, UINT8 dst)
+{
+ /* dst <- @SP
+ SP <- SP + 1 */
+ register_write(cpustate, dst, stack_pop_byte(cpustate));
+}
+
+INSTRUCTION( pop_R1 ) { mode_R1(pop) }
+INSTRUCTION( pop_IR1 ) { mode_IR1(pop) }
+
+static void push(z8_state *cpustate, UINT8 src)
+{
+ /* SP <- SP - 1
+ @SP <- src */
+ stack_push_byte(cpustate, read(src));
+}
+
+INSTRUCTION( push_R2 ) { mode_R1(push) }
+INSTRUCTION( push_IR2 ) { mode_IR1(push) }
+
+/***************************************************************************
+ ARITHMETIC INSTRUCTIONS
+***************************************************************************/
+
+static void add_carry(z8_state *cpustate, UINT8 dst, INT8 src)
+{
+ /* dst <- dst + src + C */
+ UINT8 data = register_read(cpustate, dst);
+ UINT16 new_data = data + src + flag(C);
+
+ set_flag_c(new_data & 0x100);
+ set_flag_z(new_data == 0);
+ set_flag_s(new_data & 0x80);
+ set_flag_v(((data & 0x80) == (src & 0x80)) && ((new_data & 0x80) != (src & 0x80)));
+ set_flag_d(0);
+ set_flag_h(((data & 0x1f) == 0x0f) && ((new_data & 0x1f) == 0x10));
+
+ register_write(cpustate, dst, new_data & 0xff);
+}
+
+INSTRUCTION( adc_r1_r2 ) { mode_r1_r2(add_carry) }
+INSTRUCTION( adc_r1_Ir2 ) { mode_r1_Ir2(add_carry) }
+INSTRUCTION( adc_R2_R1 ) { mode_R2_R1(add_carry) }
+INSTRUCTION( adc_IR2_R1 ) { mode_IR2_R1(add_carry) }
+INSTRUCTION( adc_R1_IM ) { mode_R1_IM(add_carry) }
+INSTRUCTION( adc_IR1_IM ) { mode_IR1_IM(add_carry) }
+
+static void add(z8_state *cpustate, UINT8 dst, INT8 src)
+{
+ /* dst <- dst + src */
+ UINT8 data = register_read(cpustate, dst);
+ UINT16 new_data = data + src;
+
+ set_flag_c(new_data & 0x100);
+ set_flag_z(new_data == 0);
+ set_flag_s(new_data & 0x80);
+ set_flag_v(((data & 0x80) == (src & 0x80)) && ((new_data & 0x80) != (src & 0x80)));
+ set_flag_d(0);
+ set_flag_h(((data & 0x1f) == 0x0f) && ((new_data & 0x1f) == 0x10));
+
+ register_write(cpustate, dst, new_data & 0xff);
+}
+
+INSTRUCTION( add_r1_r2 ) { mode_r1_r2(add) }
+INSTRUCTION( add_r1_Ir2 ) { mode_r1_Ir2(add) }
+INSTRUCTION( add_R2_R1 ) { mode_R2_R1(add) }
+INSTRUCTION( add_IR2_R1 ) { mode_IR2_R1(add) }
+INSTRUCTION( add_R1_IM ) { mode_R1_IM(add) }
+INSTRUCTION( add_IR1_IM ) { mode_IR1_IM(add) }
+
+static void compare(z8_state *cpustate, UINT8 dst, UINT8 src)
+{
+ /* dst - src */
+ UINT8 data = register_read(cpustate, dst);
+ UINT16 new_data = data - src;
+
+ set_flag_c(!(new_data & 0x100));
+ set_flag_z(new_data == 0);
+ set_flag_s(new_data & 0x80);
+ set_flag_v(((data & 0x80) != (src & 0x80)) && ((new_data & 0x80) == (src & 0x80)));
+}
+
+INSTRUCTION( cp_r1_r2 ) { mode_r1_r2(compare) }
+INSTRUCTION( cp_r1_Ir2 ) { mode_r1_Ir2(compare) }
+INSTRUCTION( cp_R2_R1 ) { mode_R2_R1(compare) }
+INSTRUCTION( cp_IR2_R1 ) { mode_IR2_R1(compare) }
+INSTRUCTION( cp_R1_IM ) { mode_R1_IM(compare) }
+INSTRUCTION( cp_IR1_IM ) { mode_IR1_IM(compare) }
+
+static void decimal_adjust(z8_state *cpustate, UINT8 dst)
+{
+}
+
+INSTRUCTION( da_R1 ) { mode_R1(decimal_adjust) }
+INSTRUCTION( da_IR1 ) { mode_IR1(decimal_adjust) }
+
+static void decrement(z8_state *cpustate, UINT8 dst)
+{
+ /* dst <- dst - 1 */
+ UINT8 data = register_read(cpustate, dst) - 1;
+
+ set_flag_z(data == 0);
+ set_flag_s(data & 0x80);
+ set_flag_v(data == 0x7f);
+
+ register_write(cpustate, dst, data);
+}
+
+INSTRUCTION( dec_R1 ) { mode_R1(decrement) }
+INSTRUCTION( dec_IR1 ) { mode_IR1(decrement) }
+
+static void decrement_word(z8_state *cpustate, UINT8 dst)
+{
+ /* dst <- dst - 1 */
+ UINT16 data = register_pair_read(cpustate, dst) - 1;
+
+ set_flag_z(data == 0);
+ set_flag_s(data & 0x8000);
+ set_flag_v(data == 0x7fff);
+
+ register_pair_write(cpustate, dst, data);
+}
+
+INSTRUCTION( decw_RR1 ) { mode_RR1(decrement_word) }
+INSTRUCTION( decw_IR1 ) { mode_IR1(decrement_word) }
+
+static void increment(z8_state *cpustate, UINT8 dst)
+{
+ /* dst <- dst + 1 */
+ UINT8 data = register_read(cpustate, dst) + 1;
+
+ set_flag_z(data == 0);
+ set_flag_s(data & 0x80);
+ set_flag_v(data == 0x80);
+
+ register_write(cpustate, dst, data);
+}
+
+INSTRUCTION( inc_r1 ) { mode_r1(increment) }
+INSTRUCTION( inc_R1 ) { mode_R1(increment) }
+INSTRUCTION( inc_IR1 ) { mode_IR1(increment) }
+
+static void increment_word(z8_state *cpustate, UINT8 dst)
+{
+ /* dst <- dst + 1 */
+ UINT16 data = register_pair_read(cpustate, dst) + 1;
+
+ set_flag_z(data == 0);
+ set_flag_s(data & 0x8000);
+ set_flag_v(data == 0x8000);
+
+ register_pair_write(cpustate, dst, data);
+}
+
+INSTRUCTION( incw_RR1 ) { mode_RR1(increment_word) }
+INSTRUCTION( incw_IR1 ) { mode_IR1(increment_word) }
+
+static void subtract_carry(z8_state *cpustate, UINT8 dst, UINT8 src)
+{
+ /* dst <- dst - src - C */
+ UINT8 data = register_read(cpustate, dst);
+ UINT16 new_data = data - src;
+
+ set_flag_c(!(new_data & 0x100));
+ set_flag_z(new_data == 0);
+ set_flag_s(new_data & 0x80);
+ set_flag_v(((data & 0x80) != (src & 0x80)) && ((new_data & 0x80) == (src & 0x80)));
+ set_flag_d(1);
+ set_flag_h(!(((data & 0x1f) == 0x0f) && ((new_data & 0x1f) == 0x10)));
+
+ register_write(cpustate, dst, new_data & 0xff);
+}
+
+INSTRUCTION( sbc_r1_r2 ) { mode_r1_r2(subtract_carry) }
+INSTRUCTION( sbc_r1_Ir2 ) { mode_r1_Ir2(subtract_carry) }
+INSTRUCTION( sbc_R2_R1 ) { mode_R2_R1(subtract_carry) }
+INSTRUCTION( sbc_IR2_R1 ) { mode_IR2_R1(subtract_carry) }
+INSTRUCTION( sbc_R1_IM ) { mode_R1_IM(subtract_carry) }
+INSTRUCTION( sbc_IR1_IM ) { mode_IR1_IM(subtract_carry) }
+
+static void subtract(z8_state *cpustate, UINT8 dst, UINT8 src)
+{
+ /* dst <- dst - src */
+ UINT8 data = register_read(cpustate, dst);
+ UINT16 new_data = data - src;
+
+ set_flag_c(!(new_data & 0x100));
+ set_flag_z(new_data == 0);
+ set_flag_s(new_data & 0x80);
+ set_flag_v(((data & 0x80) != (src & 0x80)) && ((new_data & 0x80) == (src & 0x80)));
+ set_flag_d(1);
+ set_flag_h(!(((data & 0x1f) == 0x0f) && ((new_data & 0x1f) == 0x10)));
+
+ register_write(cpustate, dst, new_data & 0xff);
+}
+
+INSTRUCTION( sub_r1_r2 ) { mode_r1_r2(subtract) }
+INSTRUCTION( sub_r1_Ir2 ) { mode_r1_Ir2(subtract) }
+INSTRUCTION( sub_R2_R1 ) { mode_R2_R1(subtract) }
+INSTRUCTION( sub_IR2_R1 ) { mode_IR2_R1(subtract) }
+INSTRUCTION( sub_R1_IM ) { mode_R1_IM(subtract) }
+INSTRUCTION( sub_IR1_IM ) { mode_IR1_IM(subtract) }
+
+/***************************************************************************
+ LOGICAL INSTRUCTIONS
+***************************************************************************/
+
+static void _and(z8_state *cpustate, UINT8 dst, UINT8 src)
+{
+ /* dst <- dst AND src */
+ UINT8 data = register_read(cpustate, dst) & src;
+ register_write(cpustate, dst, data);
+
+ set_flag_z(data == 0);
+ set_flag_s(data & 0x80);
+ set_flag_v(0);
+}
+
+INSTRUCTION( and_r1_r2 ) { mode_r1_r2(_and) }
+INSTRUCTION( and_r1_Ir2 ) { mode_r1_Ir2(_and) }
+INSTRUCTION( and_R2_R1 ) { mode_R2_R1(_and) }
+INSTRUCTION( and_IR2_R1 ) { mode_IR2_R1(_and) }
+INSTRUCTION( and_R1_IM ) { mode_R1_IM(_and) }
+INSTRUCTION( and_IR1_IM ) { mode_IR1_IM(_and) }
+
+static void complement(z8_state *cpustate, UINT8 dst)
+{
+ /* dst <- NOT dst */
+ UINT8 data = register_read(cpustate, dst) ^ 0xff;
+ register_write(cpustate, dst, data);
+
+ set_flag_z(data == 0);
+ set_flag_s(data & 0x80);
+ set_flag_v(0);
+}
+
+INSTRUCTION( com_R1 ) { mode_R1(complement) }
+INSTRUCTION( com_IR1 ) { mode_IR1(complement) }
+
+static void _or(z8_state *cpustate, UINT8 dst, UINT8 src)
+{
+ /* dst <- dst OR src */
+ UINT8 data = register_read(cpustate, dst) | src;
+ register_write(cpustate, dst, data);
+
+ set_flag_z(data == 0);
+ set_flag_s(data & 0x80);
+ set_flag_v(0);
+}
+
+INSTRUCTION( or_r1_r2 ) { mode_r1_r2(_or) }
+INSTRUCTION( or_r1_Ir2 ) { mode_r1_Ir2(_or) }
+INSTRUCTION( or_R2_R1 ) { mode_R2_R1(_or) }
+INSTRUCTION( or_IR2_R1 ) { mode_IR2_R1(_or) }
+INSTRUCTION( or_R1_IM ) { mode_R1_IM(_or) }
+INSTRUCTION( or_IR1_IM ) { mode_IR1_IM(_or) }
+
+static void _xor(z8_state *cpustate, UINT8 dst, UINT8 src)
+{
+ /* dst <- dst XOR src */
+ UINT8 data = register_read(cpustate, dst) ^ src;
+ register_write(cpustate, dst, data);
+
+ set_flag_z(data == 0);
+ set_flag_s(data & 0x80);
+ set_flag_v(0);
+}
+
+INSTRUCTION( xor_r1_r2 ) { mode_r1_r2(_xor) }
+INSTRUCTION( xor_r1_Ir2 ) { mode_r1_Ir2(_xor) }
+INSTRUCTION( xor_R2_R1 ) { mode_R2_R1(_xor) }
+INSTRUCTION( xor_IR2_R1 ) { mode_IR2_R1(_xor) }
+INSTRUCTION( xor_R1_IM ) { mode_R1_IM(_xor) }
+INSTRUCTION( xor_IR1_IM ) { mode_IR1_IM(_xor) }
+
+/***************************************************************************
+ PROGRAM CONTROL INSTRUCTIONS
+***************************************************************************/
+
+static void call(z8_state *cpustate, UINT16 dst)
+{
+ stack_push_word(cpustate, cpustate->pc);
+ cpustate->pc = dst;
+}
+
+INSTRUCTION( call_IRR1 ) { UINT16 dst = register_pair_read(cpustate, get_intermediate_register(cpustate, get_register(cpustate, fetch(cpustate)))); call(cpustate, dst); }
+INSTRUCTION( call_DA ) { UINT16 dst = (fetch(cpustate) << 8) | fetch(cpustate); call(cpustate, dst); }
+
+INSTRUCTION( djnz_r1_RA )
+{
+ INT8 ra = (INT8)fetch(cpustate);
+
+ /* r <- r - 1 */
+ int r = get_working_register(cpustate, opcode >> 4);
+ UINT8 data = register_read(cpustate, r) - 1;
+ register_write(cpustate, r, data);
+
+ /* if r<>0, PC <- PC + dst */
+ if (data != 0)
+ {
+ cpustate->pc += ra;
+ *cycles += 2;
+ }
+}
+
+INSTRUCTION( iret )
+{
+ /* FLAGS <- @SP
+ SP <- SP + 1 */
+ register_write(cpustate, Z8_REGISTER_FLAGS, stack_pop_byte(cpustate));
+
+ /* PC <- @SP
+ SP <- SP + 2 */
+ cpustate->pc = stack_pop_word(cpustate);
+
+ /* IMR (7) <- 1 */
+ cpustate->r[Z8_REGISTER_IMR] |= Z8_IMR_ENABLE;
+}
+
+INSTRUCTION( ret )
+{
+ /* PC <- @SP
+ SP <- SP + 2 */
+ cpustate->pc = stack_pop_word(cpustate);
+}
+
+static void jump(z8_state *cpustate, UINT16 dst)
+{
+ /* PC <- dst */
+ cpustate->pc = dst;
+}
+
+INSTRUCTION( jp_IRR1 ) { jump(cpustate, register_pair_read(cpustate, IR)); }
+
+static int check_condition_code(z8_state *cpustate, int cc)
+{
+ int truth = 0;
+
+ switch (cc)
+ {
+ case CC_F: truth = 0; break;
+ case CC_LT: truth = flag(S) ^ flag(V); break;
+ case CC_LE: truth = (flag(Z) | (flag(S) ^ flag(V))); break;
+ case CC_ULE: truth = flag(C) | flag(Z); break;
+ case CC_OV: truth = flag(V); break;
+ case CC_MI: truth = flag(S); break;
+ case CC_Z: truth = flag(Z); break;
+ case CC_C: truth = flag(C); break;
+ case CC_T: truth = 1; break;
+ case CC_GE: truth = !(flag(S) ^ flag(V)); break;
+ case CC_GT: truth = !(flag(Z) | (flag(S) ^ flag(V))); break;
+ case CC_UGT: truth = ((!flag(C)) & (!flag(Z))); break;
+ case CC_NOV: truth = !flag(V); break;
+ case CC_PL: truth = !flag(S); break;
+ case CC_NZ: truth = !flag(Z); break;
+ case CC_NC: truth = !flag(C); break;
+ }
+
+ return truth;
+}
+
+INSTRUCTION( jp_cc_DA )
+{
+ UINT16 dst = (fetch(cpustate) << 8) | fetch(cpustate);
+
+ /* if cc is true, then PC <- dst */
+ if (check_condition_code(cpustate, opcode >> 4))
+ {
+ jump(cpustate, dst);
+ *cycles += 2;
+ }
+}
+
+INSTRUCTION( jr_cc_RA )
+{
+ INT8 ra = (INT8)fetch(cpustate);
+ UINT16 dst = cpustate->pc + ra;
+
+ /* if cc is true, then PC <- dst */
+ if (check_condition_code(cpustate, opcode >> 4))
+ {
+ jump(cpustate, dst);
+ *cycles += 2;
+ }
+}
+
+/***************************************************************************
+ BIT MANIPULATION INSTRUCTIONS
+***************************************************************************/
+
+static void test_complement_under_mask(z8_state *cpustate, UINT8 dst, UINT8 src)
+{
+ /* NOT(dst) AND src */
+ UINT8 data = (register_read(cpustate, dst) ^ 0xff) & src;
+
+ set_flag_z(data == 0);
+ set_flag_s(data & 0x80);
+ set_flag_v(0);
+}
+
+INSTRUCTION( tcm_r1_r2 ) { mode_r1_r2(test_complement_under_mask) }
+INSTRUCTION( tcm_r1_Ir2 ) { mode_r1_Ir2(test_complement_under_mask) }
+INSTRUCTION( tcm_R2_R1 ) { mode_R2_R1(test_complement_under_mask) }
+INSTRUCTION( tcm_IR2_R1 ) { mode_IR2_R1(test_complement_under_mask) }
+INSTRUCTION( tcm_R1_IM ) { mode_R1_IM(test_complement_under_mask) }
+INSTRUCTION( tcm_IR1_IM ) { mode_IR1_IM(test_complement_under_mask) }
+
+static void test_under_mask(z8_state *cpustate, UINT8 dst, UINT8 src)
+{
+ /* dst AND src */
+ UINT8 data = register_read(cpustate, dst) & src;
+
+ set_flag_z(data == 0);
+ set_flag_s(data & 0x80);
+ set_flag_v(0);
+}
+
+INSTRUCTION( tm_r1_r2 ) { mode_r1_r2(test_under_mask) }
+INSTRUCTION( tm_r1_Ir2 ) { mode_r1_Ir2(test_under_mask) }
+INSTRUCTION( tm_R2_R1 ) { mode_R2_R1(test_under_mask) }
+INSTRUCTION( tm_IR2_R1 ) { mode_IR2_R1(test_under_mask) }
+INSTRUCTION( tm_R1_IM ) { mode_R1_IM(test_under_mask) }
+INSTRUCTION( tm_IR1_IM ) { mode_IR1_IM(test_under_mask) }
+
+/***************************************************************************
+ ROTATE AND SHIFT INSTRUCTIONS
+***************************************************************************/
+
+static void rotate_left(z8_state *cpustate, UINT8 dst)
+{
+ /* << */
+ UINT8 data = register_read(cpustate, dst);
+ UINT8 new_data = (data << 1) | BIT(data, 7);
+
+ set_flag_c(data & 0x80);
+ set_flag_z(data == 0);
+ set_flag_s(new_data & 0x80);
+ set_flag_v((data & 0x80) != (new_data & 0x80));
+
+ register_write(cpustate, dst, new_data);
+}
+
+INSTRUCTION( rl_R1 ) { mode_R1(rotate_left) }
+INSTRUCTION( rl_IR1 ) { mode_IR1(rotate_left) }
+
+static void rotate_left_carry(z8_state *cpustate, UINT8 dst)
+{
+ /* << C */
+ UINT8 data = register_read(cpustate, dst);
+ UINT8 new_data = (data << 1) | flag(C);
+
+ set_flag_c(data & 0x80);
+ set_flag_z(data == 0);
+ set_flag_s(new_data & 0x80);
+ set_flag_v((data & 0x80) != (new_data & 0x80));
+
+ register_write(cpustate, dst, new_data);
+}
+
+INSTRUCTION( rlc_R1 ) { mode_R1(rotate_left_carry) }
+INSTRUCTION( rlc_IR1 ) { mode_IR1(rotate_left_carry) }
+
+static void rotate_right(z8_state *cpustate, UINT8 dst)
+{
+ /* >> */
+ UINT8 data = register_read(cpustate, dst);
+ UINT8 new_data = ((data & 0x01) << 7) | (data >> 1);
+
+ set_flag_c(data & 0x01);
+ set_flag_z(data == 0);
+ set_flag_s(new_data & 0x80);
+ set_flag_v((data & 0x80) != (new_data & 0x80));
+
+ register_write(cpustate, dst, new_data);
+}
+
+INSTRUCTION( rr_R1 ) { mode_R1(rotate_right) }
+INSTRUCTION( rr_IR1 ) { mode_IR1(rotate_right) }
+
+static void rotate_right_carry(z8_state *cpustate, UINT8 dst)
+{
+ /* >> C */
+ UINT8 data = register_read(cpustate, dst);
+ UINT8 new_data = (flag(C) << 7) | (data >> 1);
+
+ set_flag_c(data & 0x01);
+ set_flag_z(data == 0);
+ set_flag_s(new_data & 0x80);
+ set_flag_v((data & 0x80) != (new_data & 0x80));
+
+ register_write(cpustate, dst, new_data);
+}
+
+INSTRUCTION( rrc_R1 ) { mode_R1(rotate_right_carry) }
+INSTRUCTION( rrc_IR1 ) { mode_IR1(rotate_right_carry) }
+
+static void shift_right_arithmetic(z8_state *cpustate, UINT8 dst)
+{
+ /* */
+ UINT8 data = register_read(cpustate, dst);
+ UINT8 new_data = (data & 0x80) | ((data >> 1) & 0x7f);
+
+ set_flag_c(data & 0x01);
+ set_flag_z(data == 0);
+ set_flag_s(new_data & 0x80);
+ set_flag_v(0);
+
+ register_write(cpustate, dst, new_data);
+}
+
+INSTRUCTION( sra_R1 ) { mode_R1(shift_right_arithmetic) }
+INSTRUCTION( sra_IR1 ) { mode_IR1(shift_right_arithmetic) }
+
+static void swap(z8_state *cpustate, UINT8 dst)
+{
+ /* dst(7-4) <-> dst(3-0) */
+ UINT8 data = register_read(cpustate, dst);
+ data = (data << 4) | (data >> 4);
+ register_write(cpustate, dst, data);
+
+ set_flag_z(data == 0);
+ set_flag_s(data & 0x80);
+// set_flag_v(0); undefined
+}
+
+INSTRUCTION( swap_R1 ) { mode_R1(swap) }
+INSTRUCTION( swap_IR1 ) { mode_IR1(swap) }
+
+/***************************************************************************
+ CPU CONTROL INSTRUCTIONS
+***************************************************************************/
+
+INSTRUCTION( ccf ) { cpustate->r[Z8_REGISTER_FLAGS] ^= Z8_FLAGS_C; }
+INSTRUCTION( di ) { cpustate->r[Z8_REGISTER_IMR] &= ~Z8_IMR_ENABLE; }
+INSTRUCTION( ei ) { cpustate->r[Z8_REGISTER_IMR] |= Z8_IMR_ENABLE; }
+INSTRUCTION( nop ) { /* no operation */ }
+INSTRUCTION( rcf ) { set_flag_c(0); }
+INSTRUCTION( scf ) { set_flag_c(1); }
+INSTRUCTION( srp_IM ) { cpustate->r[Z8_REGISTER_RP] = fetch(cpustate); }
diff --git a/trunk/src/emu/cpu/z80/z80.c b/trunk/src/emu/cpu/z80/z80.c
new file mode 100644
index 00000000000..176194ef6a2
--- /dev/null
+++ b/trunk/src/emu/cpu/z80/z80.c
@@ -0,0 +1,3959 @@
+/*****************************************************************************
+ *
+ * z80.c
+ * Portable Z80 emulator V3.9
+ *
+ * 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.
+ *
+ * TODO:
+ * - Interrupt mode 0 should be able to execute arbitrary opcodes
+ * - If LD A,I or LD A,R is interrupted, P/V flag gets reset, even if IFF2
+ * was set before this instruction (implemented, but not enabled: we need
+ * document Z80 types first, see below)
+ * - Ideally, the tiny differences between Z80 types should be supported,
+ * currently known differences:
+ * - LD A,I/R P/V flag reset glitch is fixed on CMOS Z80
+ * - OUT (C),0 outputs 0 on NMOS Z80, $FF on CMOS Z80
+ * - SCF/CCF X/Y flags is ((flags | A) & 0x28) on SGS/SHARP/ZiLOG NMOS Z80,
+ * (flags & A & 0x28) on NEC NMOS Z80, other models unknown.
+ * However, people from the Speccy scene mention that SCF/CCF X/Y results
+ * are inconsistant and may be influenced by I and R registers.
+ * This Z80 emulator assumes a ZiLOG NMOS model.
+ *
+ * Changes in 3.9:
+ * - Fixed cycle counts for LD IYL/IXL/IYH/IXH,n [Marshmellow]
+ * - Fixed X/Y flags in CCF/SCF/BIT, ZEXALL is happy now [hap]
+ * - Simplified DAA, renamed MEMPTR (3.8) to WZ, added TODO [hap]
+ * - Fixed IM2 interrupt cycles [eke]
+ * Changes in 3.8 [Miodrag Milanovic]:
+ * - Added MEMPTR register (according to informations provided
+ * by Vladimir Kladov
+ * - BIT n,(HL) now return valid values due to use of MEMPTR
+ * - Fixed BIT 6,(XY+o) undocumented instructions
+ * Changes in 3.7 [Aaron Giles]:
+ * - Changed NMI handling. NMIs are now latched in set_irq_state
+ * but are not taken there. Instead they are taken at the start of the
+ * execute loop.
+ * - Changed IRQ handling. IRQ state is set in set_irq_state but not taken
+ * except during the inner execute loop.
+ * - Removed x86 assembly hacks and obsolete timing loop catchers.
+ * Changes in 3.6:
+ * - Got rid of the code that would inexactly emulate a Z80, i.e. removed
+ * all the #if Z80_EXACT #else branches.
+ * - Removed leading underscores from local register name shortcuts as
+ * this violates the C99 standard.
+ * - Renamed the registers inside the Z80 context to lower case to avoid
+ * ambiguities (shortcuts would have had the same names as the fields
+ * of the structure).
+ * Changes in 3.5:
+ * - Implemented OTIR, INIR, etc. without look-up table for PF flag.
+ * [Ramsoft, Sean Young]
+ * Changes in 3.4:
+ * - Removed Z80-MSX specific code as it's not needed any more.
+ * - Implemented DAA without look-up table [Ramsoft, Sean Young]
+ * Changes in 3.3:
+ * - Fixed undocumented flags XF & YF in the non-asm versions of CP,
+ * and all the 16 bit arithmetic instructions. [Sean Young]
+ * Changes in 3.2:
+ * - Fixed undocumented flags XF & YF of RRCA, and CF and HF of
+ * INI/IND/OUTI/OUTD/INIR/INDR/OTIR/OTDR [Sean Young]
+ * Changes in 3.1:
+ * - removed the REPEAT_AT_ONCE execution of LDIR/CPIR etc. opcodes
+ * for readabilities sake and because the implementation was buggy
+ * (and i was not able to find the difference)
+ * Changes in 3.0:
+ * - 'finished' switch to dynamically overrideable cycle count tables
+ * Changes in 2.9:
+ * - added methods to access and override the cycle count tables
+ * - fixed handling and timing of multiple DD/FD prefixed opcodes
+ * Changes in 2.8:
+ * - OUTI/OUTD/OTIR/OTDR also pre-decrement the B register now.
+ * This was wrong because of a bug fix on the wrong side
+ * (astrocade sound driver).
+ * Changes in 2.7:
+ * - removed z80_vm specific code, it's not needed (and never was).
+ * Changes in 2.6:
+ * - BUSY_LOOP_HACKS needed to call change_pc() earlier, before
+ * checking the opcodes at the new address, because otherwise they
+ * might access the old (wrong or even NULL) banked memory region.
+ * Thanks to Sean Young for finding this nasty bug.
+ * Changes in 2.5:
+ * - Burning cycles always adjusts the ICount by a multiple of 4.
+ * - In REPEAT_AT_ONCE cases the r register wasn't incremented twice
+ * per repetition as it should have been. Those repeated opcodes
+ * could also underflow the ICount.
+ * - Simplified TIME_LOOP_HACKS for BC and added two more for DE + HL
+ * timing loops. i think those hacks weren't endian safe before too.
+ * Changes in 2.4:
+ * - z80_reset zaps the entire context, sets IX and IY to 0xffff(!) and
+ * sets the Z flag. With these changes the Tehkan World Cup driver
+ * _seems_ to work again.
+ * Changes in 2.3:
+ * - External termination of the execution loop calls z80_burn() and
+ * z80_vm_burn() to burn an amount of cycles (r adjustment)
+ * - Shortcuts which burn CPU cycles (BUSY_LOOP_HACKS and TIME_LOOP_HACKS)
+ * now also adjust the r register depending on the skipped opcodes.
+ * Changes in 2.2:
+ * - Fixed bugs in CPL, SCF and CCF instructions flag handling.
+ * - Changed variable ea and ARG16() function to UINT32; this
+ * produces slightly more efficient code.
+ * - The DD/FD XY CB opcodes where XY is 40-7F and Y is not 6/E
+ * are changed to calls to the X6/XE opcodes to reduce object size.
+ * They're hardly ever used so this should not yield a speed penalty.
+ * New in 2.0:
+ * - Optional more exact Z80 emulation (#define Z80_EXACT 1) according
+ * to a detailed description by Sean Young which can be found at:
+ * http://www.msxnet.org/tech/z80-documented.pdf
+ *****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "z80.h"
+#include "z80daisy.h"
+
+#define VERBOSE 0
+
+/* On an NMOS Z80, if LD A,I or LD A,R is interrupted, P/V flag gets reset,
+ even if IFF2 was set before this instruction. This issue was fixed on
+ the CMOS Z80, so until knowing (most) Z80 types on hardware, it's disabled */
+#define HAS_LDAIR_QUIRK 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+/* execute main opcodes inside a big switch statement */
+#ifndef BIG_SWITCH
+#define BIG_SWITCH 1
+#endif
+
+
+/****************************************************************************/
+/* The Z80 registers. halt is set to 1 when the CPU is halted, the refresh */
+/* register is calculated as follows: refresh=(r&127)|(r2&128) */
+/****************************************************************************/
+typedef struct _z80_state z80_state;
+struct _z80_state
+{
+ PAIR prvpc,pc,sp,af,bc,de,hl,ix,iy,wz;
+ PAIR af2,bc2,de2,hl2;
+ UINT8 r,r2,iff1,iff2,halt,im,i;
+ UINT8 nmi_state; /* nmi line state */
+ UINT8 nmi_pending; /* nmi pending */
+ UINT8 irq_state; /* irq line state */
+ UINT8 nsc800_irq_state[4];/* state of NSC800 restart interrupts A, B, C */
+ int wait_state; // wait line state
+ int busrq_state; // bus request line state
+ UINT8 after_ei; /* are we in the EI shadow? */
+ UINT8 after_ldair; /* same, but for LD A,I or LD A,R */
+ UINT32 ea;
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *io;
+ int icount;
+ z80_daisy_chain daisy;
+ UINT8 rtemp;
+ const UINT8 * cc_op;
+ const UINT8 * cc_cb;
+ const UINT8 * cc_ed;
+ const UINT8 * cc_xy;
+ const UINT8 * cc_xycb;
+ const UINT8 * cc_ex;
+};
+
+INLINE z80_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == Z80 || device->type() == NSC800);
+ return (z80_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+#define CF 0x01
+#define NF 0x02
+#define PF 0x04
+#define VF PF
+#define XF 0x08
+#define HF 0x10
+#define YF 0x20
+#define ZF 0x40
+#define SF 0x80
+
+#define INT_IRQ 0x01
+#define NMI_IRQ 0x02
+
+#define PRVPC prvpc.d /* previous program counter */
+
+#define PCD pc.d
+#define PC pc.w.l
+
+#define SPD sp.d
+#define SP sp.w.l
+
+#define AFD af.d
+#define AF af.w.l
+#define A af.b.h
+#define F af.b.l
+
+#define BCD bc.d
+#define BC bc.w.l
+#define B bc.b.h
+#define C bc.b.l
+
+#define DED de.d
+#define DE de.w.l
+#define D de.b.h
+#define E de.b.l
+
+#define HLD hl.d
+#define HL hl.w.l
+#define H hl.b.h
+#define L hl.b.l
+
+#define IXD ix.d
+#define IX ix.w.l
+#define HX ix.b.h
+#define LX ix.b.l
+
+#define IYD iy.d
+#define IY iy.w.l
+#define HY iy.b.h
+#define LY iy.b.l
+
+#define WZ wz.w.l
+#define WZ_H wz.b.h
+#define WZ_L wz.b.l
+
+
+static UINT8 SZ[256]; /* zero and sign flags */
+static UINT8 SZ_BIT[256]; /* zero, sign and parity/overflow (=zero) flags for BIT opcode */
+static UINT8 SZP[256]; /* zero, sign and parity flags */
+static UINT8 SZHV_inc[256]; /* zero, sign, half carry and overflow flags INC r8 */
+static UINT8 SZHV_dec[256]; /* zero, sign, half carry and overflow flags DEC r8 */
+
+static UINT8 *SZHVC_add = 0;
+static UINT8 *SZHVC_sub = 0;
+
+static const UINT8 cc_op[0x100] = {
+ 4,10, 7, 6, 4, 4, 7, 4, 4,11, 7, 6, 4, 4, 7, 4,
+ 8,10, 7, 6, 4, 4, 7, 4,12,11, 7, 6, 4, 4, 7, 4,
+ 7,10,16, 6, 4, 4, 7, 4, 7,11,16, 6, 4, 4, 7, 4,
+ 7,10,13, 6,11,11,10, 4, 7,11,13, 6, 4, 4, 7, 4,
+ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+ 7, 7, 7, 7, 7, 7, 4, 7, 4, 4, 4, 4, 4, 4, 7, 4,
+ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+ 5,10,10,10,10,11, 7,11, 5,10,10, 0,10,17, 7,11,
+ 5,10,10,11,10,11, 7,11, 5, 4,10,11,10, 0, 7,11,
+ 5,10,10,19,10,11, 7,11, 5, 4,10, 4,10, 0, 7,11,
+ 5,10,10, 4,10,11, 7,11, 5, 6,10, 4,10, 0, 7,11};
+
+static const UINT8 cc_cb[0x100] = {
+ 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
+ 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
+ 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
+ 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
+ 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
+ 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
+ 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
+ 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
+ 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
+ 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
+ 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
+ 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
+ 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
+ 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
+ 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
+ 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8};
+
+static const UINT8 cc_ed[0x100] = {
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+12,12,15,20, 8,14, 8, 9,12,12,15,20, 8,14, 8, 9,
+12,12,15,20, 8,14, 8, 9,12,12,15,20, 8,14, 8, 9,
+12,12,15,20, 8,14, 8,18,12,12,15,20, 8,14, 8,18,
+12,12,15,20, 8,14, 8, 8,12,12,15,20, 8,14, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+16,16,16,16, 8, 8, 8, 8,16,16,16,16, 8, 8, 8, 8,
+16,16,16,16, 8, 8, 8, 8,16,16,16,16, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8};
+
+static const UINT8 cc_xy[0x100] = {
+ 4, 4, 4, 4, 4, 4, 4, 4, 4,15, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4,15, 4, 4, 4, 4, 4, 4,
+ 4,14,20,10, 9, 9,11, 4, 4,15,20,10, 9, 9,11, 4,
+ 4, 4, 4, 4,23,23,19, 4, 4,15, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 9, 9,19, 4, 4, 4, 4, 4, 9, 9,19, 4,
+ 4, 4, 4, 4, 9, 9,19, 4, 4, 4, 4, 4, 9, 9,19, 4,
+ 9, 9, 9, 9, 9, 9,19, 9, 9, 9, 9, 9, 9, 9,19, 9,
+19,19,19,19,19,19, 4,19, 4, 4, 4, 4, 9, 9,19, 4,
+ 4, 4, 4, 4, 9, 9,19, 4, 4, 4, 4, 4, 9, 9,19, 4,
+ 4, 4, 4, 4, 9, 9,19, 4, 4, 4, 4, 4, 9, 9,19, 4,
+ 4, 4, 4, 4, 9, 9,19, 4, 4, 4, 4, 4, 9, 9,19, 4,
+ 4, 4, 4, 4, 9, 9,19, 4, 4, 4, 4, 4, 9, 9,19, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4,14, 4,23, 4,15, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4,10, 4, 4, 4, 4, 4, 4};
+
+static const UINT8 cc_xycb[0x100] = {
+23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
+23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
+23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
+23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
+20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
+20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
+20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
+20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
+23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
+23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
+23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
+23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
+23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
+23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
+23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
+23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23};
+
+/* extra cycles if jr/jp/call taken and 'interrupt latency' on rst 0-7 */
+static const UINT8 cc_ex[0x100] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* DJNZ */
+ 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, /* JR NZ/JR Z */
+ 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, /* JR NC/JR C */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 5, 5, 5, 5, 0, 0, 0, 0, 5, 5, 5, 5, 0, 0, 0, 0, /* LDIR/CPIR/INIR/OTIR LDDR/CPDR/INDR/OTDR */
+ 6, 0, 0, 0, 7, 0, 0, 2, 6, 0, 0, 0, 7, 0, 0, 2,
+ 6, 0, 0, 0, 7, 0, 0, 2, 6, 0, 0, 0, 7, 0, 0, 2,
+ 6, 0, 0, 0, 7, 0, 0, 2, 6, 0, 0, 0, 7, 0, 0, 2,
+ 6, 0, 0, 0, 7, 0, 0, 2, 6, 0, 0, 0, 7, 0, 0, 2};
+
+#define cc_dd cc_xy
+#define cc_fd cc_xy
+
+static void take_interrupt(z80_state *z80);
+static void take_interrupt_nsc800(z80_state *z80);
+static CPU_BURN( z80 );
+
+typedef void (*funcptr)(z80_state *z80);
+
+#define PROTOTYPES(tablename,prefix) \
+ INLINE void prefix##_00(z80_state *z80); INLINE void prefix##_01(z80_state *z80); INLINE void prefix##_02(z80_state *z80); INLINE void prefix##_03(z80_state *z80); \
+ INLINE void prefix##_04(z80_state *z80); INLINE void prefix##_05(z80_state *z80); INLINE void prefix##_06(z80_state *z80); INLINE void prefix##_07(z80_state *z80); \
+ INLINE void prefix##_08(z80_state *z80); INLINE void prefix##_09(z80_state *z80); INLINE void prefix##_0a(z80_state *z80); INLINE void prefix##_0b(z80_state *z80); \
+ INLINE void prefix##_0c(z80_state *z80); INLINE void prefix##_0d(z80_state *z80); INLINE void prefix##_0e(z80_state *z80); INLINE void prefix##_0f(z80_state *z80); \
+ INLINE void prefix##_10(z80_state *z80); INLINE void prefix##_11(z80_state *z80); INLINE void prefix##_12(z80_state *z80); INLINE void prefix##_13(z80_state *z80); \
+ INLINE void prefix##_14(z80_state *z80); INLINE void prefix##_15(z80_state *z80); INLINE void prefix##_16(z80_state *z80); INLINE void prefix##_17(z80_state *z80); \
+ INLINE void prefix##_18(z80_state *z80); INLINE void prefix##_19(z80_state *z80); INLINE void prefix##_1a(z80_state *z80); INLINE void prefix##_1b(z80_state *z80); \
+ INLINE void prefix##_1c(z80_state *z80); INLINE void prefix##_1d(z80_state *z80); INLINE void prefix##_1e(z80_state *z80); INLINE void prefix##_1f(z80_state *z80); \
+ INLINE void prefix##_20(z80_state *z80); INLINE void prefix##_21(z80_state *z80); INLINE void prefix##_22(z80_state *z80); INLINE void prefix##_23(z80_state *z80); \
+ INLINE void prefix##_24(z80_state *z80); INLINE void prefix##_25(z80_state *z80); INLINE void prefix##_26(z80_state *z80); INLINE void prefix##_27(z80_state *z80); \
+ INLINE void prefix##_28(z80_state *z80); INLINE void prefix##_29(z80_state *z80); INLINE void prefix##_2a(z80_state *z80); INLINE void prefix##_2b(z80_state *z80); \
+ INLINE void prefix##_2c(z80_state *z80); INLINE void prefix##_2d(z80_state *z80); INLINE void prefix##_2e(z80_state *z80); INLINE void prefix##_2f(z80_state *z80); \
+ INLINE void prefix##_30(z80_state *z80); INLINE void prefix##_31(z80_state *z80); INLINE void prefix##_32(z80_state *z80); INLINE void prefix##_33(z80_state *z80); \
+ INLINE void prefix##_34(z80_state *z80); INLINE void prefix##_35(z80_state *z80); INLINE void prefix##_36(z80_state *z80); INLINE void prefix##_37(z80_state *z80); \
+ INLINE void prefix##_38(z80_state *z80); INLINE void prefix##_39(z80_state *z80); INLINE void prefix##_3a(z80_state *z80); INLINE void prefix##_3b(z80_state *z80); \
+ INLINE void prefix##_3c(z80_state *z80); INLINE void prefix##_3d(z80_state *z80); INLINE void prefix##_3e(z80_state *z80); INLINE void prefix##_3f(z80_state *z80); \
+ INLINE void prefix##_40(z80_state *z80); INLINE void prefix##_41(z80_state *z80); INLINE void prefix##_42(z80_state *z80); INLINE void prefix##_43(z80_state *z80); \
+ INLINE void prefix##_44(z80_state *z80); INLINE void prefix##_45(z80_state *z80); INLINE void prefix##_46(z80_state *z80); INLINE void prefix##_47(z80_state *z80); \
+ INLINE void prefix##_48(z80_state *z80); INLINE void prefix##_49(z80_state *z80); INLINE void prefix##_4a(z80_state *z80); INLINE void prefix##_4b(z80_state *z80); \
+ INLINE void prefix##_4c(z80_state *z80); INLINE void prefix##_4d(z80_state *z80); INLINE void prefix##_4e(z80_state *z80); INLINE void prefix##_4f(z80_state *z80); \
+ INLINE void prefix##_50(z80_state *z80); INLINE void prefix##_51(z80_state *z80); INLINE void prefix##_52(z80_state *z80); INLINE void prefix##_53(z80_state *z80); \
+ INLINE void prefix##_54(z80_state *z80); INLINE void prefix##_55(z80_state *z80); INLINE void prefix##_56(z80_state *z80); INLINE void prefix##_57(z80_state *z80); \
+ INLINE void prefix##_58(z80_state *z80); INLINE void prefix##_59(z80_state *z80); INLINE void prefix##_5a(z80_state *z80); INLINE void prefix##_5b(z80_state *z80); \
+ INLINE void prefix##_5c(z80_state *z80); INLINE void prefix##_5d(z80_state *z80); INLINE void prefix##_5e(z80_state *z80); INLINE void prefix##_5f(z80_state *z80); \
+ INLINE void prefix##_60(z80_state *z80); INLINE void prefix##_61(z80_state *z80); INLINE void prefix##_62(z80_state *z80); INLINE void prefix##_63(z80_state *z80); \
+ INLINE void prefix##_64(z80_state *z80); INLINE void prefix##_65(z80_state *z80); INLINE void prefix##_66(z80_state *z80); INLINE void prefix##_67(z80_state *z80); \
+ INLINE void prefix##_68(z80_state *z80); INLINE void prefix##_69(z80_state *z80); INLINE void prefix##_6a(z80_state *z80); INLINE void prefix##_6b(z80_state *z80); \
+ INLINE void prefix##_6c(z80_state *z80); INLINE void prefix##_6d(z80_state *z80); INLINE void prefix##_6e(z80_state *z80); INLINE void prefix##_6f(z80_state *z80); \
+ INLINE void prefix##_70(z80_state *z80); INLINE void prefix##_71(z80_state *z80); INLINE void prefix##_72(z80_state *z80); INLINE void prefix##_73(z80_state *z80); \
+ INLINE void prefix##_74(z80_state *z80); INLINE void prefix##_75(z80_state *z80); INLINE void prefix##_76(z80_state *z80); INLINE void prefix##_77(z80_state *z80); \
+ INLINE void prefix##_78(z80_state *z80); INLINE void prefix##_79(z80_state *z80); INLINE void prefix##_7a(z80_state *z80); INLINE void prefix##_7b(z80_state *z80); \
+ INLINE void prefix##_7c(z80_state *z80); INLINE void prefix##_7d(z80_state *z80); INLINE void prefix##_7e(z80_state *z80); INLINE void prefix##_7f(z80_state *z80); \
+ INLINE void prefix##_80(z80_state *z80); INLINE void prefix##_81(z80_state *z80); INLINE void prefix##_82(z80_state *z80); INLINE void prefix##_83(z80_state *z80); \
+ INLINE void prefix##_84(z80_state *z80); INLINE void prefix##_85(z80_state *z80); INLINE void prefix##_86(z80_state *z80); INLINE void prefix##_87(z80_state *z80); \
+ INLINE void prefix##_88(z80_state *z80); INLINE void prefix##_89(z80_state *z80); INLINE void prefix##_8a(z80_state *z80); INLINE void prefix##_8b(z80_state *z80); \
+ INLINE void prefix##_8c(z80_state *z80); INLINE void prefix##_8d(z80_state *z80); INLINE void prefix##_8e(z80_state *z80); INLINE void prefix##_8f(z80_state *z80); \
+ INLINE void prefix##_90(z80_state *z80); INLINE void prefix##_91(z80_state *z80); INLINE void prefix##_92(z80_state *z80); INLINE void prefix##_93(z80_state *z80); \
+ INLINE void prefix##_94(z80_state *z80); INLINE void prefix##_95(z80_state *z80); INLINE void prefix##_96(z80_state *z80); INLINE void prefix##_97(z80_state *z80); \
+ INLINE void prefix##_98(z80_state *z80); INLINE void prefix##_99(z80_state *z80); INLINE void prefix##_9a(z80_state *z80); INLINE void prefix##_9b(z80_state *z80); \
+ INLINE void prefix##_9c(z80_state *z80); INLINE void prefix##_9d(z80_state *z80); INLINE void prefix##_9e(z80_state *z80); INLINE void prefix##_9f(z80_state *z80); \
+ INLINE void prefix##_a0(z80_state *z80); INLINE void prefix##_a1(z80_state *z80); INLINE void prefix##_a2(z80_state *z80); INLINE void prefix##_a3(z80_state *z80); \
+ INLINE void prefix##_a4(z80_state *z80); INLINE void prefix##_a5(z80_state *z80); INLINE void prefix##_a6(z80_state *z80); INLINE void prefix##_a7(z80_state *z80); \
+ INLINE void prefix##_a8(z80_state *z80); INLINE void prefix##_a9(z80_state *z80); INLINE void prefix##_aa(z80_state *z80); INLINE void prefix##_ab(z80_state *z80); \
+ INLINE void prefix##_ac(z80_state *z80); INLINE void prefix##_ad(z80_state *z80); INLINE void prefix##_ae(z80_state *z80); INLINE void prefix##_af(z80_state *z80); \
+ INLINE void prefix##_b0(z80_state *z80); INLINE void prefix##_b1(z80_state *z80); INLINE void prefix##_b2(z80_state *z80); INLINE void prefix##_b3(z80_state *z80); \
+ INLINE void prefix##_b4(z80_state *z80); INLINE void prefix##_b5(z80_state *z80); INLINE void prefix##_b6(z80_state *z80); INLINE void prefix##_b7(z80_state *z80); \
+ INLINE void prefix##_b8(z80_state *z80); INLINE void prefix##_b9(z80_state *z80); INLINE void prefix##_ba(z80_state *z80); INLINE void prefix##_bb(z80_state *z80); \
+ INLINE void prefix##_bc(z80_state *z80); INLINE void prefix##_bd(z80_state *z80); INLINE void prefix##_be(z80_state *z80); INLINE void prefix##_bf(z80_state *z80); \
+ INLINE void prefix##_c0(z80_state *z80); INLINE void prefix##_c1(z80_state *z80); INLINE void prefix##_c2(z80_state *z80); INLINE void prefix##_c3(z80_state *z80); \
+ INLINE void prefix##_c4(z80_state *z80); INLINE void prefix##_c5(z80_state *z80); INLINE void prefix##_c6(z80_state *z80); INLINE void prefix##_c7(z80_state *z80); \
+ INLINE void prefix##_c8(z80_state *z80); INLINE void prefix##_c9(z80_state *z80); INLINE void prefix##_ca(z80_state *z80); INLINE void prefix##_cb(z80_state *z80); \
+ INLINE void prefix##_cc(z80_state *z80); INLINE void prefix##_cd(z80_state *z80); INLINE void prefix##_ce(z80_state *z80); INLINE void prefix##_cf(z80_state *z80); \
+ INLINE void prefix##_d0(z80_state *z80); INLINE void prefix##_d1(z80_state *z80); INLINE void prefix##_d2(z80_state *z80); INLINE void prefix##_d3(z80_state *z80); \
+ INLINE void prefix##_d4(z80_state *z80); INLINE void prefix##_d5(z80_state *z80); INLINE void prefix##_d6(z80_state *z80); INLINE void prefix##_d7(z80_state *z80); \
+ INLINE void prefix##_d8(z80_state *z80); INLINE void prefix##_d9(z80_state *z80); INLINE void prefix##_da(z80_state *z80); INLINE void prefix##_db(z80_state *z80); \
+ INLINE void prefix##_dc(z80_state *z80); INLINE void prefix##_dd(z80_state *z80); INLINE void prefix##_de(z80_state *z80); INLINE void prefix##_df(z80_state *z80); \
+ INLINE void prefix##_e0(z80_state *z80); INLINE void prefix##_e1(z80_state *z80); INLINE void prefix##_e2(z80_state *z80); INLINE void prefix##_e3(z80_state *z80); \
+ INLINE void prefix##_e4(z80_state *z80); INLINE void prefix##_e5(z80_state *z80); INLINE void prefix##_e6(z80_state *z80); INLINE void prefix##_e7(z80_state *z80); \
+ INLINE void prefix##_e8(z80_state *z80); INLINE void prefix##_e9(z80_state *z80); INLINE void prefix##_ea(z80_state *z80); INLINE void prefix##_eb(z80_state *z80); \
+ INLINE void prefix##_ec(z80_state *z80); INLINE void prefix##_ed(z80_state *z80); INLINE void prefix##_ee(z80_state *z80); INLINE void prefix##_ef(z80_state *z80); \
+ INLINE void prefix##_f0(z80_state *z80); INLINE void prefix##_f1(z80_state *z80); INLINE void prefix##_f2(z80_state *z80); INLINE void prefix##_f3(z80_state *z80); \
+ INLINE void prefix##_f4(z80_state *z80); INLINE void prefix##_f5(z80_state *z80); INLINE void prefix##_f6(z80_state *z80); INLINE void prefix##_f7(z80_state *z80); \
+ INLINE void prefix##_f8(z80_state *z80); INLINE void prefix##_f9(z80_state *z80); INLINE void prefix##_fa(z80_state *z80); INLINE void prefix##_fb(z80_state *z80); \
+ INLINE void prefix##_fc(z80_state *z80); INLINE void prefix##_fd(z80_state *z80); INLINE void prefix##_fe(z80_state *z80); INLINE void prefix##_ff(z80_state *z80); \
+static const funcptr tablename[0x100] = { \
+ prefix##_00,prefix##_01,prefix##_02,prefix##_03,prefix##_04,prefix##_05,prefix##_06,prefix##_07, \
+ prefix##_08,prefix##_09,prefix##_0a,prefix##_0b,prefix##_0c,prefix##_0d,prefix##_0e,prefix##_0f, \
+ prefix##_10,prefix##_11,prefix##_12,prefix##_13,prefix##_14,prefix##_15,prefix##_16,prefix##_17, \
+ prefix##_18,prefix##_19,prefix##_1a,prefix##_1b,prefix##_1c,prefix##_1d,prefix##_1e,prefix##_1f, \
+ prefix##_20,prefix##_21,prefix##_22,prefix##_23,prefix##_24,prefix##_25,prefix##_26,prefix##_27, \
+ prefix##_28,prefix##_29,prefix##_2a,prefix##_2b,prefix##_2c,prefix##_2d,prefix##_2e,prefix##_2f, \
+ prefix##_30,prefix##_31,prefix##_32,prefix##_33,prefix##_34,prefix##_35,prefix##_36,prefix##_37, \
+ prefix##_38,prefix##_39,prefix##_3a,prefix##_3b,prefix##_3c,prefix##_3d,prefix##_3e,prefix##_3f, \
+ prefix##_40,prefix##_41,prefix##_42,prefix##_43,prefix##_44,prefix##_45,prefix##_46,prefix##_47, \
+ prefix##_48,prefix##_49,prefix##_4a,prefix##_4b,prefix##_4c,prefix##_4d,prefix##_4e,prefix##_4f, \
+ prefix##_50,prefix##_51,prefix##_52,prefix##_53,prefix##_54,prefix##_55,prefix##_56,prefix##_57, \
+ prefix##_58,prefix##_59,prefix##_5a,prefix##_5b,prefix##_5c,prefix##_5d,prefix##_5e,prefix##_5f, \
+ prefix##_60,prefix##_61,prefix##_62,prefix##_63,prefix##_64,prefix##_65,prefix##_66,prefix##_67, \
+ prefix##_68,prefix##_69,prefix##_6a,prefix##_6b,prefix##_6c,prefix##_6d,prefix##_6e,prefix##_6f, \
+ prefix##_70,prefix##_71,prefix##_72,prefix##_73,prefix##_74,prefix##_75,prefix##_76,prefix##_77, \
+ prefix##_78,prefix##_79,prefix##_7a,prefix##_7b,prefix##_7c,prefix##_7d,prefix##_7e,prefix##_7f, \
+ prefix##_80,prefix##_81,prefix##_82,prefix##_83,prefix##_84,prefix##_85,prefix##_86,prefix##_87, \
+ prefix##_88,prefix##_89,prefix##_8a,prefix##_8b,prefix##_8c,prefix##_8d,prefix##_8e,prefix##_8f, \
+ prefix##_90,prefix##_91,prefix##_92,prefix##_93,prefix##_94,prefix##_95,prefix##_96,prefix##_97, \
+ prefix##_98,prefix##_99,prefix##_9a,prefix##_9b,prefix##_9c,prefix##_9d,prefix##_9e,prefix##_9f, \
+ prefix##_a0,prefix##_a1,prefix##_a2,prefix##_a3,prefix##_a4,prefix##_a5,prefix##_a6,prefix##_a7, \
+ prefix##_a8,prefix##_a9,prefix##_aa,prefix##_ab,prefix##_ac,prefix##_ad,prefix##_ae,prefix##_af, \
+ prefix##_b0,prefix##_b1,prefix##_b2,prefix##_b3,prefix##_b4,prefix##_b5,prefix##_b6,prefix##_b7, \
+ prefix##_b8,prefix##_b9,prefix##_ba,prefix##_bb,prefix##_bc,prefix##_bd,prefix##_be,prefix##_bf, \
+ prefix##_c0,prefix##_c1,prefix##_c2,prefix##_c3,prefix##_c4,prefix##_c5,prefix##_c6,prefix##_c7, \
+ prefix##_c8,prefix##_c9,prefix##_ca,prefix##_cb,prefix##_cc,prefix##_cd,prefix##_ce,prefix##_cf, \
+ prefix##_d0,prefix##_d1,prefix##_d2,prefix##_d3,prefix##_d4,prefix##_d5,prefix##_d6,prefix##_d7, \
+ prefix##_d8,prefix##_d9,prefix##_da,prefix##_db,prefix##_dc,prefix##_dd,prefix##_de,prefix##_df, \
+ prefix##_e0,prefix##_e1,prefix##_e2,prefix##_e3,prefix##_e4,prefix##_e5,prefix##_e6,prefix##_e7, \
+ prefix##_e8,prefix##_e9,prefix##_ea,prefix##_eb,prefix##_ec,prefix##_ed,prefix##_ee,prefix##_ef, \
+ prefix##_f0,prefix##_f1,prefix##_f2,prefix##_f3,prefix##_f4,prefix##_f5,prefix##_f6,prefix##_f7, \
+ prefix##_f8,prefix##_f9,prefix##_fa,prefix##_fb,prefix##_fc,prefix##_fd,prefix##_fe,prefix##_ff \
+}
+
+PROTOTYPES(Z80op,op);
+PROTOTYPES(Z80cb,cb);
+PROTOTYPES(Z80dd,dd);
+PROTOTYPES(Z80ed,ed);
+PROTOTYPES(Z80fd,fd);
+PROTOTYPES(Z80xycb,xycb);
+
+/****************************************************************************/
+/* Burn an odd amount of cycles, that is instructions taking something */
+/* different from 4 T-states per opcode (and r increment) */
+/****************************************************************************/
+INLINE void BURNODD(z80_state *z80, int cycles, int opcodes, int cyclesum)
+{
+ if( cycles > 0 )
+ {
+ z80->r += (cycles / cyclesum) * opcodes;
+ z80->icount -= (cycles / cyclesum) * cyclesum;
+ }
+}
+
+/***************************************************************
+ * define an opcode function
+ ***************************************************************/
+#define OP(prefix,opcode) INLINE void prefix##_##opcode(z80_state *z80)
+
+/***************************************************************
+ * adjust cycle count by n T-states
+ ***************************************************************/
+#define CC(Z,prefix,opcode) do { (Z)->icount -= z80->cc_##prefix[opcode]; } while (0)
+
+/***************************************************************
+ * execute an opcode
+ ***************************************************************/
+#define EXEC(Z,prefix,opcode) \
+{ \
+ unsigned op = opcode; \
+ CC(Z,prefix,op); \
+ (*Z80##prefix[op])(Z); \
+}
+
+#if BIG_SWITCH
+#define EXEC_INLINE(Z,prefix,opcode) \
+{ \
+ unsigned op = opcode; \
+ CC(Z,prefix,op); \
+ switch(op) \
+ { \
+ case 0x00:prefix##_##00(Z);break; case 0x01:prefix##_##01(Z);break; case 0x02:prefix##_##02(Z);break; case 0x03:prefix##_##03(Z);break; \
+ case 0x04:prefix##_##04(Z);break; case 0x05:prefix##_##05(Z);break; case 0x06:prefix##_##06(Z);break; case 0x07:prefix##_##07(Z);break; \
+ case 0x08:prefix##_##08(Z);break; case 0x09:prefix##_##09(Z);break; case 0x0a:prefix##_##0a(Z);break; case 0x0b:prefix##_##0b(Z);break; \
+ case 0x0c:prefix##_##0c(Z);break; case 0x0d:prefix##_##0d(Z);break; case 0x0e:prefix##_##0e(Z);break; case 0x0f:prefix##_##0f(Z);break; \
+ case 0x10:prefix##_##10(Z);break; case 0x11:prefix##_##11(Z);break; case 0x12:prefix##_##12(Z);break; case 0x13:prefix##_##13(Z);break; \
+ case 0x14:prefix##_##14(Z);break; case 0x15:prefix##_##15(Z);break; case 0x16:prefix##_##16(Z);break; case 0x17:prefix##_##17(Z);break; \
+ case 0x18:prefix##_##18(Z);break; case 0x19:prefix##_##19(Z);break; case 0x1a:prefix##_##1a(Z);break; case 0x1b:prefix##_##1b(Z);break; \
+ case 0x1c:prefix##_##1c(Z);break; case 0x1d:prefix##_##1d(Z);break; case 0x1e:prefix##_##1e(Z);break; case 0x1f:prefix##_##1f(Z);break; \
+ case 0x20:prefix##_##20(Z);break; case 0x21:prefix##_##21(Z);break; case 0x22:prefix##_##22(Z);break; case 0x23:prefix##_##23(Z);break; \
+ case 0x24:prefix##_##24(Z);break; case 0x25:prefix##_##25(Z);break; case 0x26:prefix##_##26(Z);break; case 0x27:prefix##_##27(Z);break; \
+ case 0x28:prefix##_##28(Z);break; case 0x29:prefix##_##29(Z);break; case 0x2a:prefix##_##2a(Z);break; case 0x2b:prefix##_##2b(Z);break; \
+ case 0x2c:prefix##_##2c(Z);break; case 0x2d:prefix##_##2d(Z);break; case 0x2e:prefix##_##2e(Z);break; case 0x2f:prefix##_##2f(Z);break; \
+ case 0x30:prefix##_##30(Z);break; case 0x31:prefix##_##31(Z);break; case 0x32:prefix##_##32(Z);break; case 0x33:prefix##_##33(Z);break; \
+ case 0x34:prefix##_##34(Z);break; case 0x35:prefix##_##35(Z);break; case 0x36:prefix##_##36(Z);break; case 0x37:prefix##_##37(Z);break; \
+ case 0x38:prefix##_##38(Z);break; case 0x39:prefix##_##39(Z);break; case 0x3a:prefix##_##3a(Z);break; case 0x3b:prefix##_##3b(Z);break; \
+ case 0x3c:prefix##_##3c(Z);break; case 0x3d:prefix##_##3d(Z);break; case 0x3e:prefix##_##3e(Z);break; case 0x3f:prefix##_##3f(Z);break; \
+ case 0x40:prefix##_##40(Z);break; case 0x41:prefix##_##41(Z);break; case 0x42:prefix##_##42(Z);break; case 0x43:prefix##_##43(Z);break; \
+ case 0x44:prefix##_##44(Z);break; case 0x45:prefix##_##45(Z);break; case 0x46:prefix##_##46(Z);break; case 0x47:prefix##_##47(Z);break; \
+ case 0x48:prefix##_##48(Z);break; case 0x49:prefix##_##49(Z);break; case 0x4a:prefix##_##4a(Z);break; case 0x4b:prefix##_##4b(Z);break; \
+ case 0x4c:prefix##_##4c(Z);break; case 0x4d:prefix##_##4d(Z);break; case 0x4e:prefix##_##4e(Z);break; case 0x4f:prefix##_##4f(Z);break; \
+ case 0x50:prefix##_##50(Z);break; case 0x51:prefix##_##51(Z);break; case 0x52:prefix##_##52(Z);break; case 0x53:prefix##_##53(Z);break; \
+ case 0x54:prefix##_##54(Z);break; case 0x55:prefix##_##55(Z);break; case 0x56:prefix##_##56(Z);break; case 0x57:prefix##_##57(Z);break; \
+ case 0x58:prefix##_##58(Z);break; case 0x59:prefix##_##59(Z);break; case 0x5a:prefix##_##5a(Z);break; case 0x5b:prefix##_##5b(Z);break; \
+ case 0x5c:prefix##_##5c(Z);break; case 0x5d:prefix##_##5d(Z);break; case 0x5e:prefix##_##5e(Z);break; case 0x5f:prefix##_##5f(Z);break; \
+ case 0x60:prefix##_##60(Z);break; case 0x61:prefix##_##61(Z);break; case 0x62:prefix##_##62(Z);break; case 0x63:prefix##_##63(Z);break; \
+ case 0x64:prefix##_##64(Z);break; case 0x65:prefix##_##65(Z);break; case 0x66:prefix##_##66(Z);break; case 0x67:prefix##_##67(Z);break; \
+ case 0x68:prefix##_##68(Z);break; case 0x69:prefix##_##69(Z);break; case 0x6a:prefix##_##6a(Z);break; case 0x6b:prefix##_##6b(Z);break; \
+ case 0x6c:prefix##_##6c(Z);break; case 0x6d:prefix##_##6d(Z);break; case 0x6e:prefix##_##6e(Z);break; case 0x6f:prefix##_##6f(Z);break; \
+ case 0x70:prefix##_##70(Z);break; case 0x71:prefix##_##71(Z);break; case 0x72:prefix##_##72(Z);break; case 0x73:prefix##_##73(Z);break; \
+ case 0x74:prefix##_##74(Z);break; case 0x75:prefix##_##75(Z);break; case 0x76:prefix##_##76(Z);break; case 0x77:prefix##_##77(Z);break; \
+ case 0x78:prefix##_##78(Z);break; case 0x79:prefix##_##79(Z);break; case 0x7a:prefix##_##7a(Z);break; case 0x7b:prefix##_##7b(Z);break; \
+ case 0x7c:prefix##_##7c(Z);break; case 0x7d:prefix##_##7d(Z);break; case 0x7e:prefix##_##7e(Z);break; case 0x7f:prefix##_##7f(Z);break; \
+ case 0x80:prefix##_##80(Z);break; case 0x81:prefix##_##81(Z);break; case 0x82:prefix##_##82(Z);break; case 0x83:prefix##_##83(Z);break; \
+ case 0x84:prefix##_##84(Z);break; case 0x85:prefix##_##85(Z);break; case 0x86:prefix##_##86(Z);break; case 0x87:prefix##_##87(Z);break; \
+ case 0x88:prefix##_##88(Z);break; case 0x89:prefix##_##89(Z);break; case 0x8a:prefix##_##8a(Z);break; case 0x8b:prefix##_##8b(Z);break; \
+ case 0x8c:prefix##_##8c(Z);break; case 0x8d:prefix##_##8d(Z);break; case 0x8e:prefix##_##8e(Z);break; case 0x8f:prefix##_##8f(Z);break; \
+ case 0x90:prefix##_##90(Z);break; case 0x91:prefix##_##91(Z);break; case 0x92:prefix##_##92(Z);break; case 0x93:prefix##_##93(Z);break; \
+ case 0x94:prefix##_##94(Z);break; case 0x95:prefix##_##95(Z);break; case 0x96:prefix##_##96(Z);break; case 0x97:prefix##_##97(Z);break; \
+ case 0x98:prefix##_##98(Z);break; case 0x99:prefix##_##99(Z);break; case 0x9a:prefix##_##9a(Z);break; case 0x9b:prefix##_##9b(Z);break; \
+ case 0x9c:prefix##_##9c(Z);break; case 0x9d:prefix##_##9d(Z);break; case 0x9e:prefix##_##9e(Z);break; case 0x9f:prefix##_##9f(Z);break; \
+ case 0xa0:prefix##_##a0(Z);break; case 0xa1:prefix##_##a1(Z);break; case 0xa2:prefix##_##a2(Z);break; case 0xa3:prefix##_##a3(Z);break; \
+ case 0xa4:prefix##_##a4(Z);break; case 0xa5:prefix##_##a5(Z);break; case 0xa6:prefix##_##a6(Z);break; case 0xa7:prefix##_##a7(Z);break; \
+ case 0xa8:prefix##_##a8(Z);break; case 0xa9:prefix##_##a9(Z);break; case 0xaa:prefix##_##aa(Z);break; case 0xab:prefix##_##ab(Z);break; \
+ case 0xac:prefix##_##ac(Z);break; case 0xad:prefix##_##ad(Z);break; case 0xae:prefix##_##ae(Z);break; case 0xaf:prefix##_##af(Z);break; \
+ case 0xb0:prefix##_##b0(Z);break; case 0xb1:prefix##_##b1(Z);break; case 0xb2:prefix##_##b2(Z);break; case 0xb3:prefix##_##b3(Z);break; \
+ case 0xb4:prefix##_##b4(Z);break; case 0xb5:prefix##_##b5(Z);break; case 0xb6:prefix##_##b6(Z);break; case 0xb7:prefix##_##b7(Z);break; \
+ case 0xb8:prefix##_##b8(Z);break; case 0xb9:prefix##_##b9(Z);break; case 0xba:prefix##_##ba(Z);break; case 0xbb:prefix##_##bb(Z);break; \
+ case 0xbc:prefix##_##bc(Z);break; case 0xbd:prefix##_##bd(Z);break; case 0xbe:prefix##_##be(Z);break; case 0xbf:prefix##_##bf(Z);break; \
+ case 0xc0:prefix##_##c0(Z);break; case 0xc1:prefix##_##c1(Z);break; case 0xc2:prefix##_##c2(Z);break; case 0xc3:prefix##_##c3(Z);break; \
+ case 0xc4:prefix##_##c4(Z);break; case 0xc5:prefix##_##c5(Z);break; case 0xc6:prefix##_##c6(Z);break; case 0xc7:prefix##_##c7(Z);break; \
+ case 0xc8:prefix##_##c8(Z);break; case 0xc9:prefix##_##c9(Z);break; case 0xca:prefix##_##ca(Z);break; case 0xcb:prefix##_##cb(Z);break; \
+ case 0xcc:prefix##_##cc(Z);break; case 0xcd:prefix##_##cd(Z);break; case 0xce:prefix##_##ce(Z);break; case 0xcf:prefix##_##cf(Z);break; \
+ case 0xd0:prefix##_##d0(Z);break; case 0xd1:prefix##_##d1(Z);break; case 0xd2:prefix##_##d2(Z);break; case 0xd3:prefix##_##d3(Z);break; \
+ case 0xd4:prefix##_##d4(Z);break; case 0xd5:prefix##_##d5(Z);break; case 0xd6:prefix##_##d6(Z);break; case 0xd7:prefix##_##d7(Z);break; \
+ case 0xd8:prefix##_##d8(Z);break; case 0xd9:prefix##_##d9(Z);break; case 0xda:prefix##_##da(Z);break; case 0xdb:prefix##_##db(Z);break; \
+ case 0xdc:prefix##_##dc(Z);break; case 0xdd:prefix##_##dd(Z);break; case 0xde:prefix##_##de(Z);break; case 0xdf:prefix##_##df(Z);break; \
+ case 0xe0:prefix##_##e0(Z);break; case 0xe1:prefix##_##e1(Z);break; case 0xe2:prefix##_##e2(Z);break; case 0xe3:prefix##_##e3(Z);break; \
+ case 0xe4:prefix##_##e4(Z);break; case 0xe5:prefix##_##e5(Z);break; case 0xe6:prefix##_##e6(Z);break; case 0xe7:prefix##_##e7(Z);break; \
+ case 0xe8:prefix##_##e8(Z);break; case 0xe9:prefix##_##e9(Z);break; case 0xea:prefix##_##ea(Z);break; case 0xeb:prefix##_##eb(Z);break; \
+ case 0xec:prefix##_##ec(Z);break; case 0xed:prefix##_##ed(Z);break; case 0xee:prefix##_##ee(Z);break; case 0xef:prefix##_##ef(Z);break; \
+ case 0xf0:prefix##_##f0(Z);break; case 0xf1:prefix##_##f1(Z);break; case 0xf2:prefix##_##f2(Z);break; case 0xf3:prefix##_##f3(Z);break; \
+ case 0xf4:prefix##_##f4(Z);break; case 0xf5:prefix##_##f5(Z);break; case 0xf6:prefix##_##f6(Z);break; case 0xf7:prefix##_##f7(Z);break; \
+ case 0xf8:prefix##_##f8(Z);break; case 0xf9:prefix##_##f9(Z);break; case 0xfa:prefix##_##fa(Z);break; case 0xfb:prefix##_##fb(Z);break; \
+ case 0xfc:prefix##_##fc(Z);break; case 0xfd:prefix##_##fd(Z);break; case 0xfe:prefix##_##fe(Z);break; case 0xff:prefix##_##ff(Z);break; \
+ } \
+}
+#else
+#define EXEC_INLINE EXEC
+#endif
+
+
+/***************************************************************
+ * Enter halt state; write 1 to fake port on first execution
+ ***************************************************************/
+#define ENTER_HALT(Z) do { \
+ (Z)->PC--; \
+ (Z)->halt = 1; \
+ if( (Z)->irq_state == CLEAR_LINE ) \
+ CPU_BURN_NAME(z80)( (Z)->device, (Z)->icount); \
+} while (0)
+
+/***************************************************************
+ * Leave halt state; write 0 to fake port
+ ***************************************************************/
+#define LEAVE_HALT(Z) do { \
+ if( (Z)->halt ) \
+ { \
+ (Z)->halt = 0; \
+ (Z)->PC++; \
+ } \
+} while (0)
+
+/***************************************************************
+ * Input a byte from given I/O port
+ ***************************************************************/
+#define IN(Z,port) (Z)->io->read_byte(port)
+
+/***************************************************************
+ * Output a byte to given I/O port
+ ***************************************************************/
+#define OUT(Z,port,value) (Z)->io->write_byte(port, value)
+
+/***************************************************************
+ * Read a byte from given memory location
+ ***************************************************************/
+#define RM(Z,addr) (Z)->program->read_byte(addr)
+
+/***************************************************************
+ * Read a word from given memory location
+ ***************************************************************/
+INLINE void RM16(z80_state *z80, UINT32 addr, PAIR *r)
+{
+ r->b.l = RM(z80, addr);
+ r->b.h = RM(z80, (addr+1)&0xffff);
+}
+
+/***************************************************************
+ * Write a byte to given memory location
+ ***************************************************************/
+#define WM(Z,addr,value) (Z)->program->write_byte(addr, value)
+
+/***************************************************************
+ * Write a word to given memory location
+ ***************************************************************/
+INLINE void WM16(z80_state *z80, UINT32 addr, PAIR *r)
+{
+ WM(z80, addr, r->b.l);
+ WM(z80, (addr+1)&0xffff, r->b.h);
+}
+
+/***************************************************************
+ * ROP() is identical to RM() except it is used for
+ * reading opcodes. In case of system with memory mapped I/O,
+ * this function can be used to greatly speed up emulation
+ ***************************************************************/
+INLINE UINT8 ROP(z80_state *z80)
+{
+ unsigned pc = z80->PCD;
+ z80->PC++;
+ return z80->direct->read_decrypted_byte(pc);
+}
+
+/****************************************************************
+ * ARG(z80) is identical to ROP() except it is used
+ * for reading opcode arguments. This difference can be used to
+ * support systems that use different encoding mechanisms for
+ * opcodes and opcode arguments
+ ***************************************************************/
+INLINE UINT8 ARG(z80_state *z80)
+{
+ unsigned pc = z80->PCD;
+ z80->PC++;
+ return z80->direct->read_raw_byte(pc);
+}
+
+INLINE UINT32 ARG16(z80_state *z80)
+{
+ unsigned pc = z80->PCD;
+ z80->PC += 2;
+ return z80->direct->read_raw_byte(pc) | (z80->direct->read_raw_byte((pc+1)&0xffff) << 8);
+}
+
+/***************************************************************
+ * Calculate the effective address EA of an opcode using
+ * IX+offset resp. IY+offset addressing.
+ ***************************************************************/
+#define EAX(Z) do { (Z)->ea = (UINT32)(UINT16)((Z)->IX + (INT8)ARG(Z)); (Z)->WZ = (Z)->ea; } while (0)
+#define EAY(Z) do { (Z)->ea = (UINT32)(UINT16)((Z)->IY + (INT8)ARG(Z)); (Z)->WZ = (Z)->ea; } while (0)
+
+/***************************************************************
+ * POP
+ ***************************************************************/
+#define POP(Z,DR) do { RM16((Z), (Z)->SPD, &(Z)->DR); (Z)->SP += 2; } while (0)
+
+/***************************************************************
+ * PUSH
+ ***************************************************************/
+#define PUSH(Z,SR) do { (Z)->SP -= 2; WM16((Z), (Z)->SPD, &(Z)->SR); } while (0)
+
+/***************************************************************
+ * JP
+ ***************************************************************/
+#define JP(Z) do { \
+ (Z)->PCD = ARG16(Z); \
+ (Z)->WZ = (Z)->PCD; \
+} while (0)
+
+/***************************************************************
+ * JP_COND
+ ***************************************************************/
+#define JP_COND(Z, cond) do { \
+ if (cond) \
+ { \
+ (Z)->PCD = ARG16(Z); \
+ (Z)->WZ = (Z)->PCD; \
+ } \
+ else \
+ { \
+ (Z)->WZ = ARG16(Z); /* implicit do PC += 2 */ \
+ } \
+} while (0)
+
+/***************************************************************
+ * JR
+ ***************************************************************/
+#define JR(Z) do { \
+ INT8 arg = (INT8)ARG(Z); /* ARG() also increments PC */ \
+ (Z)->PC += arg; /* so don't do PC += ARG() */ \
+ (Z)->WZ = (Z)->PC; \
+} while (0)
+
+/***************************************************************
+ * JR_COND
+ ***************************************************************/
+#define JR_COND(Z, cond, opcode) do { \
+ if (cond) \
+ { \
+ JR(Z); \
+ CC(Z, ex, opcode); \
+ } \
+ else (Z)->PC++; \
+} while (0)
+
+/***************************************************************
+ * CALL
+ ***************************************************************/
+#define CALL(Z) do { \
+ (Z)->ea = ARG16(Z); \
+ (Z)->WZ = (Z)->ea; \
+ PUSH((Z), pc); \
+ (Z)->PCD = (Z)->ea; \
+} while (0)
+
+/***************************************************************
+ * CALL_COND
+ ***************************************************************/
+#define CALL_COND(Z, cond, opcode) do { \
+ if (cond) \
+ { \
+ (Z)->ea = ARG16(Z); \
+ (Z)->WZ = (Z)->ea; \
+ PUSH((Z), pc); \
+ (Z)->PCD = (Z)->ea; \
+ CC(Z, ex, opcode); \
+ } \
+ else \
+ { \
+ z80->WZ = ARG16(z80); /* implicit call PC+=2; */ \
+ } \
+} while (0)
+
+/***************************************************************
+ * RET_COND
+ ***************************************************************/
+#define RET_COND(Z, cond, opcode) do { \
+ if (cond) \
+ { \
+ POP((Z), pc); \
+ (Z)->WZ = (Z)->PC; \
+ CC(Z, ex, opcode); \
+ } \
+} while (0)
+
+/***************************************************************
+ * RETN
+ ***************************************************************/
+#define RETN(Z) do { \
+ LOG(("Z80 '%s' RETN z80->iff1:%d z80->iff2:%d\n", \
+ (Z)->device->tag(), (Z)->iff1, (Z)->iff2)); \
+ POP((Z), pc); \
+ (Z)->WZ = (Z)->PC; \
+ (Z)->iff1 = (Z)->iff2; \
+} while (0)
+
+/***************************************************************
+ * RETI
+ ***************************************************************/
+#define RETI(Z) do { \
+ POP((Z), pc); \
+ (Z)->WZ = (Z)->PC; \
+/* according to http://www.msxnet.org/tech/z80-documented.pdf */\
+ (Z)->iff1 = (Z)->iff2; \
+ (Z)->daisy.call_reti_device(); \
+} while (0)
+
+/***************************************************************
+ * LD R,A
+ ***************************************************************/
+#define LD_R_A(Z) do { \
+ (Z)->r = (Z)->A; \
+ (Z)->r2 = (Z)->A & 0x80; /* keep bit 7 of r */ \
+} while (0)
+
+/***************************************************************
+ * LD A,R
+ ***************************************************************/
+#define LD_A_R(Z) do { \
+ (Z)->A = ((Z)->r & 0x7f) | (Z)->r2; \
+ (Z)->F = ((Z)->F & CF) | SZ[(Z)->A] | ((Z)->iff2 << 2); \
+ (Z)->after_ldair = TRUE; \
+} while (0)
+
+/***************************************************************
+ * LD I,A
+ ***************************************************************/
+#define LD_I_A(Z) do { \
+ (Z)->i = (Z)->A; \
+} while (0)
+
+/***************************************************************
+ * LD A,I
+ ***************************************************************/
+#define LD_A_I(Z) do { \
+ (Z)->A = (Z)->i; \
+ (Z)->F = ((Z)->F & CF) | SZ[(Z)->A] | ((Z)->iff2 << 2); \
+ (Z)->after_ldair = TRUE; \
+} while (0)
+
+/***************************************************************
+ * RST
+ ***************************************************************/
+#define RST(Z, addr) do { \
+ PUSH((Z), pc); \
+ (Z)->PCD = addr; \
+ (Z)->WZ = (Z)->PC; \
+} while (0)
+
+/***************************************************************
+ * INC r8
+ ***************************************************************/
+INLINE UINT8 INC(z80_state *z80, UINT8 value)
+{
+ UINT8 res = value + 1;
+ z80->F = (z80->F & CF) | SZHV_inc[res];
+ return (UINT8)res;
+}
+
+/***************************************************************
+ * DEC r8
+ ***************************************************************/
+INLINE UINT8 DEC(z80_state *z80, UINT8 value)
+{
+ UINT8 res = value - 1;
+ z80->F = (z80->F & CF) | SZHV_dec[res];
+ return res;
+}
+
+/***************************************************************
+ * RLCA
+ ***************************************************************/
+#define RLCA(Z) do { \
+ (Z)->A = ((Z)->A << 1) | ((Z)->A >> 7); \
+ (Z)->F = ((Z)->F & (SF | ZF | PF)) | ((Z)->A & (YF | XF | CF)); \
+} while (0)
+
+/***************************************************************
+ * RRCA
+ ***************************************************************/
+#define RRCA(Z) do { \
+ (Z)->F = ((Z)->F & (SF | ZF | PF)) | ((Z)->A & CF); \
+ (Z)->A = ((Z)->A >> 1) | ((Z)->A << 7); \
+ (Z)->F |= ((Z)->A & (YF | XF)); \
+} while (0)
+
+/***************************************************************
+ * RLA
+ ***************************************************************/
+#define RLA(Z) do { \
+ UINT8 res = ((Z)->A << 1) | ((Z)->F & CF); \
+ UINT8 c = ((Z)->A & 0x80) ? CF : 0; \
+ (Z)->F = ((Z)->F & (SF | ZF | PF)) | c | (res & (YF | XF)); \
+ (Z)->A = res; \
+} while (0)
+
+/***************************************************************
+ * RRA
+ ***************************************************************/
+#define RRA(Z) do { \
+ UINT8 res = ((Z)->A >> 1) | ((Z)->F << 7); \
+ UINT8 c = ((Z)->A & 0x01) ? CF : 0; \
+ (Z)->F = ((Z)->F & (SF | ZF | PF)) | c | (res & (YF | XF)); \
+ (Z)->A = res; \
+} while (0)
+
+/***************************************************************
+ * RRD
+ ***************************************************************/
+#define RRD(Z) do { \
+ UINT8 n = RM((Z), (Z)->HL); \
+ (Z)->WZ = (Z)->HL+1; \
+ WM((Z), (Z)->HL, (n >> 4) | ((Z)->A << 4)); \
+ (Z)->A = ((Z)->A & 0xf0) | (n & 0x0f); \
+ (Z)->F = ((Z)->F & CF) | SZP[(Z)->A]; \
+} while (0)
+
+/***************************************************************
+ * RLD
+ ***************************************************************/
+#define RLD(Z) do { \
+ UINT8 n = RM((Z), (Z)->HL); \
+ (Z)->WZ = (Z)->HL+1; \
+ WM((Z), (Z)->HL, (n << 4) | ((Z)->A & 0x0f)); \
+ (Z)->A = ((Z)->A & 0xf0) | (n >> 4); \
+ (Z)->F = ((Z)->F & CF) | SZP[(Z)->A]; \
+} while (0)
+
+/***************************************************************
+ * ADD A,n
+ ***************************************************************/
+#define ADD(Z, value) do { \
+ UINT32 ah = (Z)->AFD & 0xff00; \
+ UINT32 res = (UINT8)((ah >> 8) + value); \
+ (Z)->F = SZHVC_add[ah | res]; \
+ (Z)->A = res; \
+} while (0)
+
+/***************************************************************
+ * ADC A,n
+ ***************************************************************/
+#define ADC(Z, value) do { \
+ UINT32 ah = (Z)->AFD & 0xff00, c = (Z)->AFD & 1; \
+ UINT32 res = (UINT8)((ah >> 8) + value + c); \
+ (Z)->F = SZHVC_add[(c << 16) | ah | res]; \
+ (Z)->A = res; \
+} while (0)
+
+/***************************************************************
+ * SUB n
+ ***************************************************************/
+#define SUB(Z, value) do { \
+ UINT32 ah = (Z)->AFD & 0xff00; \
+ UINT32 res = (UINT8)((ah >> 8) - value); \
+ (Z)->F = SZHVC_sub[ah | res]; \
+ (Z)->A = res; \
+} while (0)
+
+/***************************************************************
+ * SBC A,n
+ ***************************************************************/
+#define SBC(Z, value) do { \
+ UINT32 ah = (Z)->AFD & 0xff00, c = (Z)->AFD & 1; \
+ UINT32 res = (UINT8)((ah >> 8) - value - c); \
+ (Z)->F = SZHVC_sub[(c<<16) | ah | res]; \
+ (Z)->A = res; \
+} while (0)
+
+/***************************************************************
+ * NEG
+ ***************************************************************/
+#define NEG(Z) do { \
+ UINT8 value = (Z)->A; \
+ (Z)->A = 0; \
+ SUB(Z, value); \
+} while (0)
+
+/***************************************************************
+ * DAA
+ ***************************************************************/
+#define DAA(Z) do { \
+ UINT8 a = (Z)->A; \
+ if ((Z)->F & NF) { \
+ if (((Z)->F&HF) | (((Z)->A&0xf)>9)) a-=6; \
+ if (((Z)->F&CF) | ((Z)->A>0x99)) a-=0x60; \
+ } \
+ else { \
+ if (((Z)->F&HF) | (((Z)->A&0xf)>9)) a+=6; \
+ if (((Z)->F&CF) | ((Z)->A>0x99)) a+=0x60; \
+ } \
+ \
+ (Z)->F = ((Z)->F&(CF|NF)) | ((Z)->A>0x99) | (((Z)->A^a)&HF) | SZP[a]; \
+ (Z)->A = a; \
+} while (0)
+
+/***************************************************************
+ * AND n
+ ***************************************************************/
+#define AND(Z, value) do { \
+ (Z)->A &= value; \
+ (Z)->F = SZP[(Z)->A] | HF; \
+} while (0)
+
+/***************************************************************
+ * OR n
+ ***************************************************************/
+#define OR(Z, value) do { \
+ (Z)->A |= value; \
+ (Z)->F = SZP[(Z)->A]; \
+} while (0)
+
+/***************************************************************
+ * XOR n
+ ***************************************************************/
+#define XOR(Z, value) do { \
+ (Z)->A ^= value; \
+ (Z)->F = SZP[(Z)->A]; \
+} while (0)
+
+/***************************************************************
+ * CP n
+ ***************************************************************/
+#define CP(Z, value) do { \
+ unsigned val = value; \
+ UINT32 ah = (Z)->AFD & 0xff00; \
+ UINT32 res = (UINT8)((ah >> 8) - val); \
+ (Z)->F = (SZHVC_sub[ah | res] & ~(YF | XF)) | \
+ (val & (YF | XF)); \
+} while (0)
+
+/***************************************************************
+ * EX AF,AF'
+ ***************************************************************/
+#define EX_AF(Z) do { \
+ PAIR tmp; \
+ tmp = (Z)->af; (Z)->af = (Z)->af2; (Z)->af2 = tmp; \
+} while (0)
+
+/***************************************************************
+ * EX DE,HL
+ ***************************************************************/
+#define EX_DE_HL(Z) do { \
+ PAIR tmp; \
+ tmp = (Z)->de; (Z)->de = (Z)->hl; (Z)->hl = tmp; \
+} while (0)
+
+/***************************************************************
+ * EXX
+ ***************************************************************/
+#define EXX(Z) do { \
+ PAIR tmp; \
+ tmp = (Z)->bc; (Z)->bc = (Z)->bc2; (Z)->bc2 = tmp; \
+ tmp = (Z)->de; (Z)->de = (Z)->de2; (Z)->de2 = tmp; \
+ tmp = (Z)->hl; (Z)->hl = (Z)->hl2; (Z)->hl2 = tmp; \
+} while (0)
+
+/***************************************************************
+ * EX (SP),r16
+ ***************************************************************/
+#define EXSP(Z, DR) do { \
+ PAIR tmp = { { 0, 0, 0, 0 } }; \
+ RM16((Z), (Z)->SPD, &tmp); \
+ WM16((Z), (Z)->SPD, &(Z)->DR); \
+ (Z)->DR = tmp; \
+ (Z)->WZ = (Z)->DR.d; \
+} while (0)
+
+/***************************************************************
+ * ADD16
+ ***************************************************************/
+#define ADD16(Z, DR, SR) do { \
+ UINT32 res = (Z)->DR.d + (Z)->SR.d; \
+ (Z)->WZ = (Z)->DR.d + 1; \
+ (Z)->F = ((Z)->F & (SF | ZF | VF)) | \
+ ((((Z)->DR.d ^ res ^ (Z)->SR.d) >> 8) & HF) | \
+ ((res >> 16) & CF) | ((res >> 8) & (YF | XF)); \
+ (Z)->DR.w.l = (UINT16)res; \
+} while (0)
+
+/***************************************************************
+ * ADC r16,r16
+ ***************************************************************/
+#define ADC16(Z, Reg) do { \
+ UINT32 res = (Z)->HLD + (Z)->Reg.d + ((Z)->F & CF); \
+ (Z)->WZ = (Z)->HL + 1; \
+ (Z)->F = ((((Z)->HLD ^ res ^ (Z)->Reg.d) >> 8) & HF) | \
+ ((res >> 16) & CF) | \
+ ((res >> 8) & (SF | YF | XF)) | \
+ ((res & 0xffff) ? 0 : ZF) | \
+ ((((Z)->Reg.d ^ (Z)->HLD ^ 0x8000) & ((Z)->Reg.d ^ res) & 0x8000) >> 13); \
+ (Z)->HL = (UINT16)res; \
+} while (0)
+
+/***************************************************************
+ * SBC r16,r16
+ ***************************************************************/
+#define SBC16(Z, Reg) do { \
+ UINT32 res = (Z)->HLD - (Z)->Reg.d - ((Z)->F & CF); \
+ (Z)->WZ = (Z)->HL + 1; \
+ (Z)->F = ((((Z)->HLD ^ res ^ (Z)->Reg.d) >> 8) & HF) | NF | \
+ ((res >> 16) & CF) | \
+ ((res >> 8) & (SF | YF | XF)) | \
+ ((res & 0xffff) ? 0 : ZF) | \
+ ((((Z)->Reg.d ^ (Z)->HLD) & ((Z)->HLD ^ res) &0x8000) >> 13); \
+ (Z)->HL = (UINT16)res; \
+} while (0)
+
+/***************************************************************
+ * RLC r8
+ ***************************************************************/
+INLINE UINT8 RLC(z80_state *z80, UINT8 value)
+{
+ unsigned res = value;
+ unsigned c = (res & 0x80) ? CF : 0;
+ res = ((res << 1) | (res >> 7)) & 0xff;
+ z80->F = SZP[res] | c;
+ return res;
+}
+
+/***************************************************************
+ * RRC r8
+ ***************************************************************/
+INLINE UINT8 RRC(z80_state *z80, UINT8 value)
+{
+ unsigned res = value;
+ unsigned c = (res & 0x01) ? CF : 0;
+ res = ((res >> 1) | (res << 7)) & 0xff;
+ z80->F = SZP[res] | c;
+ return res;
+}
+
+/***************************************************************
+ * RL r8
+ ***************************************************************/
+INLINE UINT8 RL(z80_state *z80, UINT8 value)
+{
+ unsigned res = value;
+ unsigned c = (res & 0x80) ? CF : 0;
+ res = ((res << 1) | (z80->F & CF)) & 0xff;
+ z80->F = SZP[res] | c;
+ return res;
+}
+
+/***************************************************************
+ * RR r8
+ ***************************************************************/
+INLINE UINT8 RR(z80_state *z80, UINT8 value)
+{
+ unsigned res = value;
+ unsigned c = (res & 0x01) ? CF : 0;
+ res = ((res >> 1) | (z80->F << 7)) & 0xff;
+ z80->F = SZP[res] | c;
+ return res;
+}
+
+/***************************************************************
+ * SLA r8
+ ***************************************************************/
+INLINE UINT8 SLA(z80_state *z80, UINT8 value)
+{
+ unsigned res = value;
+ unsigned c = (res & 0x80) ? CF : 0;
+ res = (res << 1) & 0xff;
+ z80->F = SZP[res] | c;
+ return res;
+}
+
+/***************************************************************
+ * SRA r8
+ ***************************************************************/
+INLINE UINT8 SRA(z80_state *z80, UINT8 value)
+{
+ unsigned res = value;
+ unsigned c = (res & 0x01) ? CF : 0;
+ res = ((res >> 1) | (res & 0x80)) & 0xff;
+ z80->F = SZP[res] | c;
+ return res;
+}
+
+/***************************************************************
+ * SLL r8
+ ***************************************************************/
+INLINE UINT8 SLL(z80_state *z80, UINT8 value)
+{
+ unsigned res = value;
+ unsigned c = (res & 0x80) ? CF : 0;
+ res = ((res << 1) | 0x01) & 0xff;
+ z80->F = SZP[res] | c;
+ return res;
+}
+
+/***************************************************************
+ * SRL r8
+ ***************************************************************/
+INLINE UINT8 SRL(z80_state *z80, UINT8 value)
+{
+ unsigned res = value;
+ unsigned c = (res & 0x01) ? CF : 0;
+ res = (res >> 1) & 0xff;
+ z80->F = SZP[res] | c;
+ return res;
+}
+
+/***************************************************************
+ * BIT bit,r8
+ ***************************************************************/
+#undef BIT
+#define BIT(Z, bit, reg) do { \
+ (Z)->F = ((Z)->F & CF) | HF | (SZ_BIT[reg & (1<<bit)] & ~(YF|XF)) | (reg & (YF|XF)); \
+} while (0)
+
+/***************************************************************
+ * BIT bit,(HL)
+ ***************************************************************/
+#define BIT_HL(Z, bit, reg) do { \
+ (Z)->F = ((Z)->F & CF) | HF | (SZ_BIT[reg & (1<<bit)] & ~(YF|XF)) | ((Z)->WZ_H & (YF|XF)); \
+} while (0)
+
+/***************************************************************
+ * BIT bit,(IX/Y+o)
+ ***************************************************************/
+#define BIT_XY(Z, bit, reg) do { \
+ (Z)->F = ((Z)->F & CF) | HF | (SZ_BIT[reg & (1<<bit)] & ~(YF|XF)) | (((Z)->ea>>8) & (YF|XF)); \
+} while (0)
+
+/***************************************************************
+ * RES bit,r8
+ ***************************************************************/
+INLINE UINT8 RES(UINT8 bit, UINT8 value)
+{
+ return value & ~(1<<bit);
+}
+
+/***************************************************************
+ * SET bit,r8
+ ***************************************************************/
+INLINE UINT8 SET(UINT8 bit, UINT8 value)
+{
+ return value | (1<<bit);
+}
+
+/***************************************************************
+ * LDI
+ ***************************************************************/
+#define LDI(Z) do { \
+ UINT8 io = RM((Z), (Z)->HL); \
+ WM((Z), (Z)->DE, io); \
+ (Z)->F &= SF | ZF | CF; \
+ if (((Z)->A + io) & 0x02) (Z)->F |= YF; /* bit 1 -> flag 5 */ \
+ if (((Z)->A + io) & 0x08) (Z)->F |= XF; /* bit 3 -> flag 3 */ \
+ (Z)->HL++; (Z)->DE++; (Z)->BC--; \
+ if((Z)->BC) (Z)->F |= VF; \
+} while (0)
+
+/***************************************************************
+ * CPI
+ ***************************************************************/
+#define CPI(Z) do { \
+ UINT8 val = RM((Z), (Z)->HL); \
+ UINT8 res = (Z)->A - val; \
+ (Z)->WZ++; \
+ (Z)->HL++; (Z)->BC--; \
+ (Z)->F = ((Z)->F & CF) | (SZ[res]&~(YF|XF)) | (((Z)->A^val^res)&HF) | NF; \
+ if ((Z)->F & HF) res -= 1; \
+ if (res & 0x02) (Z)->F |= YF; /* bit 1 -> flag 5 */ \
+ if (res & 0x08) (Z)->F |= XF; /* bit 3 -> flag 3 */ \
+ if ((Z)->BC) (Z)->F |= VF; \
+} while (0)
+
+/***************************************************************
+ * INI
+ ***************************************************************/
+#define INI(Z) do { \
+ unsigned t; \
+ UINT8 io = IN((Z), (Z)->BC); \
+ (Z)->WZ = (Z)->BC + 1; \
+ (Z)->B--; \
+ WM((Z), (Z)->HL, io); \
+ (Z)->HL++; \
+ (Z)->F = SZ[(Z)->B]; \
+ t = (unsigned)(((Z)->C + 1) & 0xff) + (unsigned)io; \
+ if (io & SF) (Z)->F |= NF; \
+ if (t & 0x100) (Z)->F |= HF | CF; \
+ (Z)->F |= SZP[(UINT8)(t & 0x07) ^ (Z)->B] & PF; \
+} while (0)
+
+/***************************************************************
+ * OUTI
+ ***************************************************************/
+#define OUTI(Z) do { \
+ unsigned t; \
+ UINT8 io = RM((Z), (Z)->HL); \
+ (Z)->B--; \
+ (Z)->WZ = (Z)->BC + 1; \
+ OUT((Z), (Z)->BC, io); \
+ (Z)->HL++; \
+ (Z)->F = SZ[(Z)->B]; \
+ t = (unsigned)(Z)->L + (unsigned)io; \
+ if (io & SF) (Z)->F |= NF; \
+ if (t & 0x100) (Z)->F |= HF | CF; \
+ (Z)->F |= SZP[(UINT8)(t & 0x07) ^ (Z)->B] & PF; \
+} while (0)
+
+/***************************************************************
+ * LDD
+ ***************************************************************/
+#define LDD(Z) do { \
+ UINT8 io = RM((Z), (Z)->HL); \
+ WM((Z), (Z)->DE, io); \
+ (Z)->F &= SF | ZF | CF; \
+ if (((Z)->A + io) & 0x02) (Z)->F |= YF; /* bit 1 -> flag 5 */ \
+ if (((Z)->A + io) & 0x08) (Z)->F |= XF; /* bit 3 -> flag 3 */ \
+ (Z)->HL--; (Z)->DE--; (Z)->BC--; \
+ if ((Z)->BC) (Z)->F |= VF; \
+} while (0)
+
+/***************************************************************
+ * CPD
+ ***************************************************************/
+#define CPD(Z) do { \
+ UINT8 val = RM((Z), (Z)->HL); \
+ UINT8 res = (Z)->A - val; \
+ (Z)->WZ--; \
+ (Z)->HL--; (Z)->BC--; \
+ (Z)->F = ((Z)->F & CF) | (SZ[res]&~(YF|XF)) | (((Z)->A^val^res)&HF) | NF; \
+ if ((Z)->F & HF) res -= 1; \
+ if (res & 0x02) (Z)->F |= YF; /* bit 1 -> flag 5 */ \
+ if (res & 0x08) (Z)->F |= XF; /* bit 3 -> flag 3 */ \
+ if ((Z)->BC) (Z)->F |= VF; \
+} while (0)
+
+/***************************************************************
+ * IND
+ ***************************************************************/
+#define IND(Z) do { \
+ unsigned t; \
+ UINT8 io = IN((Z), (Z)->BC); \
+ (Z)->WZ = (Z)->BC - 1; \
+ (Z)->B--; \
+ WM((Z), (Z)->HL, io); \
+ (Z)->HL--; \
+ (Z)->F = SZ[(Z)->B]; \
+ t = ((unsigned)((Z)->C - 1) & 0xff) + (unsigned)io; \
+ if (io & SF) (Z)->F |= NF; \
+ if (t & 0x100) (Z)->F |= HF | CF; \
+ (Z)->F |= SZP[(UINT8)(t & 0x07) ^ (Z)->B] & PF; \
+} while (0)
+
+/***************************************************************
+ * OUTD
+ ***************************************************************/
+#define OUTD(Z) do { \
+ unsigned t; \
+ UINT8 io = RM((Z), (Z)->HL); \
+ (Z)->B--; \
+ (Z)->WZ = (Z)->BC - 1; \
+ OUT((Z), (Z)->BC, io); \
+ (Z)->HL--; \
+ (Z)->F = SZ[(Z)->B]; \
+ t = (unsigned)(Z)->L + (unsigned)io; \
+ if (io & SF) (Z)->F |= NF; \
+ if (t & 0x100) (Z)->F |= HF | CF; \
+ (Z)->F |= SZP[(UINT8)(t & 0x07) ^ (Z)->B] & PF; \
+} while (0)
+
+/***************************************************************
+ * LDIR
+ ***************************************************************/
+#define LDIR(Z) do { \
+ LDI(Z); \
+ if ((Z)->BC != 0) \
+ { \
+ (Z)->PC -= 2; \
+ (Z)->WZ = (Z)->PC + 1; \
+ CC(Z, ex, 0xb0); \
+ } \
+} while (0)
+
+/***************************************************************
+ * CPIR
+ ***************************************************************/
+#define CPIR(Z) do { \
+ CPI(Z); \
+ if ((Z)->BC != 0 && !((Z)->F & ZF)) \
+ { \
+ (Z)->PC -= 2; \
+ (Z)->WZ = (Z)->PC + 1; \
+ CC(Z, ex, 0xb1); \
+ } \
+} while (0)
+
+/***************************************************************
+ * INIR
+ ***************************************************************/
+#define INIR(Z) do { \
+ INI(Z); \
+ if ((Z)->B != 0) \
+ { \
+ (Z)->PC -= 2; \
+ CC(Z, ex, 0xb2); \
+ } \
+} while (0)
+
+/***************************************************************
+ * OTIR
+ ***************************************************************/
+#define OTIR(Z) do { \
+ OUTI(Z); \
+ if ((Z)->B != 0) \
+ { \
+ (Z)->PC -= 2; \
+ CC(Z, ex, 0xb3); \
+ } \
+} while (0)
+
+/***************************************************************
+ * LDDR
+ ***************************************************************/
+#define LDDR(Z) do { \
+ LDD(Z); \
+ if ((Z)->BC != 0) \
+ { \
+ (Z)->PC -= 2; \
+ (Z)->WZ = (Z)->PC + 1; \
+ CC(Z, ex, 0xb8); \
+ } \
+} while (0)
+
+/***************************************************************
+ * CPDR
+ ***************************************************************/
+#define CPDR(Z) do { \
+ CPD(Z); \
+ if ((Z)->BC != 0 && !((Z)->F & ZF)) \
+ { \
+ (Z)->PC -= 2; \
+ (Z)->WZ = (Z)->PC + 1; \
+ CC(Z, ex, 0xb9); \
+ } \
+} while (0)
+
+/***************************************************************
+ * INDR
+ ***************************************************************/
+#define INDR(Z) do { \
+ IND(Z); \
+ if ((Z)->B != 0) \
+ { \
+ (Z)->PC -= 2; \
+ CC(Z, ex, 0xba); \
+ } \
+} while (0)
+
+/***************************************************************
+ * OTDR
+ ***************************************************************/
+#define OTDR(Z) do { \
+ OUTD(Z); \
+ if ((Z)->B != 0) \
+ { \
+ (Z)->PC -= 2; \
+ CC(Z, ex, 0xbb); \
+ } \
+} while (0)
+
+/***************************************************************
+ * EI
+ ***************************************************************/
+#define EI(Z) do { \
+ (Z)->iff1 = (Z)->iff2 = 1; \
+ (Z)->after_ei = TRUE; \
+} while (0)
+
+/**********************************************************
+ * opcodes with CB prefix
+ * rotate, shift and bit operations
+ **********************************************************/
+OP(cb,00) { z80->B = RLC(z80, z80->B); } /* RLC B */
+OP(cb,01) { z80->C = RLC(z80, z80->C); } /* RLC C */
+OP(cb,02) { z80->D = RLC(z80, z80->D); } /* RLC D */
+OP(cb,03) { z80->E = RLC(z80, z80->E); } /* RLC E */
+OP(cb,04) { z80->H = RLC(z80, z80->H); } /* RLC H */
+OP(cb,05) { z80->L = RLC(z80, z80->L); } /* RLC L */
+OP(cb,06) { WM(z80, z80->HL, RLC(z80, RM(z80, z80->HL))); } /* RLC (HL) */
+OP(cb,07) { z80->A = RLC(z80, z80->A); } /* RLC A */
+
+OP(cb,08) { z80->B = RRC(z80, z80->B); } /* RRC B */
+OP(cb,09) { z80->C = RRC(z80, z80->C); } /* RRC C */
+OP(cb,0a) { z80->D = RRC(z80, z80->D); } /* RRC D */
+OP(cb,0b) { z80->E = RRC(z80, z80->E); } /* RRC E */
+OP(cb,0c) { z80->H = RRC(z80, z80->H); } /* RRC H */
+OP(cb,0d) { z80->L = RRC(z80, z80->L); } /* RRC L */
+OP(cb,0e) { WM(z80, z80->HL, RRC(z80, RM(z80, z80->HL))); } /* RRC (HL) */
+OP(cb,0f) { z80->A = RRC(z80, z80->A); } /* RRC A */
+
+OP(cb,10) { z80->B = RL(z80, z80->B); } /* RL B */
+OP(cb,11) { z80->C = RL(z80, z80->C); } /* RL C */
+OP(cb,12) { z80->D = RL(z80, z80->D); } /* RL D */
+OP(cb,13) { z80->E = RL(z80, z80->E); } /* RL E */
+OP(cb,14) { z80->H = RL(z80, z80->H); } /* RL H */
+OP(cb,15) { z80->L = RL(z80, z80->L); } /* RL L */
+OP(cb,16) { WM(z80, z80->HL, RL(z80, RM(z80, z80->HL))); } /* RL (HL) */
+OP(cb,17) { z80->A = RL(z80, z80->A); } /* RL A */
+
+OP(cb,18) { z80->B = RR(z80, z80->B); } /* RR B */
+OP(cb,19) { z80->C = RR(z80, z80->C); } /* RR C */
+OP(cb,1a) { z80->D = RR(z80, z80->D); } /* RR D */
+OP(cb,1b) { z80->E = RR(z80, z80->E); } /* RR E */
+OP(cb,1c) { z80->H = RR(z80, z80->H); } /* RR H */
+OP(cb,1d) { z80->L = RR(z80, z80->L); } /* RR L */
+OP(cb,1e) { WM(z80, z80->HL, RR(z80, RM(z80, z80->HL))); } /* RR (HL) */
+OP(cb,1f) { z80->A = RR(z80, z80->A); } /* RR A */
+
+OP(cb,20) { z80->B = SLA(z80, z80->B); } /* SLA B */
+OP(cb,21) { z80->C = SLA(z80, z80->C); } /* SLA C */
+OP(cb,22) { z80->D = SLA(z80, z80->D); } /* SLA D */
+OP(cb,23) { z80->E = SLA(z80, z80->E); } /* SLA E */
+OP(cb,24) { z80->H = SLA(z80, z80->H); } /* SLA H */
+OP(cb,25) { z80->L = SLA(z80, z80->L); } /* SLA L */
+OP(cb,26) { WM(z80, z80->HL, SLA(z80, RM(z80, z80->HL))); } /* SLA (HL) */
+OP(cb,27) { z80->A = SLA(z80, z80->A); } /* SLA A */
+
+OP(cb,28) { z80->B = SRA(z80, z80->B); } /* SRA B */
+OP(cb,29) { z80->C = SRA(z80, z80->C); } /* SRA C */
+OP(cb,2a) { z80->D = SRA(z80, z80->D); } /* SRA D */
+OP(cb,2b) { z80->E = SRA(z80, z80->E); } /* SRA E */
+OP(cb,2c) { z80->H = SRA(z80, z80->H); } /* SRA H */
+OP(cb,2d) { z80->L = SRA(z80, z80->L); } /* SRA L */
+OP(cb,2e) { WM(z80, z80->HL, SRA(z80, RM(z80, z80->HL))); } /* SRA (HL) */
+OP(cb,2f) { z80->A = SRA(z80, z80->A); } /* SRA A */
+
+OP(cb,30) { z80->B = SLL(z80, z80->B); } /* SLL B */
+OP(cb,31) { z80->C = SLL(z80, z80->C); } /* SLL C */
+OP(cb,32) { z80->D = SLL(z80, z80->D); } /* SLL D */
+OP(cb,33) { z80->E = SLL(z80, z80->E); } /* SLL E */
+OP(cb,34) { z80->H = SLL(z80, z80->H); } /* SLL H */
+OP(cb,35) { z80->L = SLL(z80, z80->L); } /* SLL L */
+OP(cb,36) { WM(z80, z80->HL, SLL(z80, RM(z80, z80->HL))); } /* SLL (HL) */
+OP(cb,37) { z80->A = SLL(z80, z80->A); } /* SLL A */
+
+OP(cb,38) { z80->B = SRL(z80, z80->B); } /* SRL B */
+OP(cb,39) { z80->C = SRL(z80, z80->C); } /* SRL C */
+OP(cb,3a) { z80->D = SRL(z80, z80->D); } /* SRL D */
+OP(cb,3b) { z80->E = SRL(z80, z80->E); } /* SRL E */
+OP(cb,3c) { z80->H = SRL(z80, z80->H); } /* SRL H */
+OP(cb,3d) { z80->L = SRL(z80, z80->L); } /* SRL L */
+OP(cb,3e) { WM(z80, z80->HL, SRL(z80, RM(z80, z80->HL))); } /* SRL (HL) */
+OP(cb,3f) { z80->A = SRL(z80, z80->A); } /* SRL A */
+
+OP(cb,40) { BIT(z80, 0, z80->B); } /* BIT 0,B */
+OP(cb,41) { BIT(z80, 0, z80->C); } /* BIT 0,C */
+OP(cb,42) { BIT(z80, 0, z80->D); } /* BIT 0,D */
+OP(cb,43) { BIT(z80, 0, z80->E); } /* BIT 0,E */
+OP(cb,44) { BIT(z80, 0, z80->H); } /* BIT 0,H */
+OP(cb,45) { BIT(z80, 0, z80->L); } /* BIT 0,L */
+OP(cb,46) { BIT_HL(z80, 0, RM(z80, z80->HL)); } /* BIT 0,(HL) */
+OP(cb,47) { BIT(z80, 0, z80->A); } /* BIT 0,A */
+
+OP(cb,48) { BIT(z80, 1, z80->B); } /* BIT 1,B */
+OP(cb,49) { BIT(z80, 1, z80->C); } /* BIT 1,C */
+OP(cb,4a) { BIT(z80, 1, z80->D); } /* BIT 1,D */
+OP(cb,4b) { BIT(z80, 1, z80->E); } /* BIT 1,E */
+OP(cb,4c) { BIT(z80, 1, z80->H); } /* BIT 1,H */
+OP(cb,4d) { BIT(z80, 1, z80->L); } /* BIT 1,L */
+OP(cb,4e) { BIT_HL(z80, 1, RM(z80, z80->HL)); } /* BIT 1,(HL) */
+OP(cb,4f) { BIT(z80, 1, z80->A); } /* BIT 1,A */
+
+OP(cb,50) { BIT(z80, 2, z80->B); } /* BIT 2,B */
+OP(cb,51) { BIT(z80, 2, z80->C); } /* BIT 2,C */
+OP(cb,52) { BIT(z80, 2, z80->D); } /* BIT 2,D */
+OP(cb,53) { BIT(z80, 2, z80->E); } /* BIT 2,E */
+OP(cb,54) { BIT(z80, 2, z80->H); } /* BIT 2,H */
+OP(cb,55) { BIT(z80, 2, z80->L); } /* BIT 2,L */
+OP(cb,56) { BIT_HL(z80, 2, RM(z80, z80->HL)); } /* BIT 2,(HL) */
+OP(cb,57) { BIT(z80, 2, z80->A); } /* BIT 2,A */
+
+OP(cb,58) { BIT(z80, 3, z80->B); } /* BIT 3,B */
+OP(cb,59) { BIT(z80, 3, z80->C); } /* BIT 3,C */
+OP(cb,5a) { BIT(z80, 3, z80->D); } /* BIT 3,D */
+OP(cb,5b) { BIT(z80, 3, z80->E); } /* BIT 3,E */
+OP(cb,5c) { BIT(z80, 3, z80->H); } /* BIT 3,H */
+OP(cb,5d) { BIT(z80, 3, z80->L); } /* BIT 3,L */
+OP(cb,5e) { BIT_HL(z80, 3, RM(z80, z80->HL)); } /* BIT 3,(HL) */
+OP(cb,5f) { BIT(z80, 3, z80->A); } /* BIT 3,A */
+
+OP(cb,60) { BIT(z80, 4, z80->B); } /* BIT 4,B */
+OP(cb,61) { BIT(z80, 4, z80->C); } /* BIT 4,C */
+OP(cb,62) { BIT(z80, 4, z80->D); } /* BIT 4,D */
+OP(cb,63) { BIT(z80, 4, z80->E); } /* BIT 4,E */
+OP(cb,64) { BIT(z80, 4, z80->H); } /* BIT 4,H */
+OP(cb,65) { BIT(z80, 4, z80->L); } /* BIT 4,L */
+OP(cb,66) { BIT_HL(z80, 4, RM(z80, z80->HL)); } /* BIT 4,(HL) */
+OP(cb,67) { BIT(z80, 4, z80->A); } /* BIT 4,A */
+
+OP(cb,68) { BIT(z80, 5, z80->B); } /* BIT 5,B */
+OP(cb,69) { BIT(z80, 5, z80->C); } /* BIT 5,C */
+OP(cb,6a) { BIT(z80, 5, z80->D); } /* BIT 5,D */
+OP(cb,6b) { BIT(z80, 5, z80->E); } /* BIT 5,E */
+OP(cb,6c) { BIT(z80, 5, z80->H); } /* BIT 5,H */
+OP(cb,6d) { BIT(z80, 5, z80->L); } /* BIT 5,L */
+OP(cb,6e) { BIT_HL(z80, 5, RM(z80, z80->HL)); } /* BIT 5,(HL) */
+OP(cb,6f) { BIT(z80, 5, z80->A); } /* BIT 5,A */
+
+OP(cb,70) { BIT(z80, 6, z80->B); } /* BIT 6,B */
+OP(cb,71) { BIT(z80, 6, z80->C); } /* BIT 6,C */
+OP(cb,72) { BIT(z80, 6, z80->D); } /* BIT 6,D */
+OP(cb,73) { BIT(z80, 6, z80->E); } /* BIT 6,E */
+OP(cb,74) { BIT(z80, 6, z80->H); } /* BIT 6,H */
+OP(cb,75) { BIT(z80, 6, z80->L); } /* BIT 6,L */
+OP(cb,76) { BIT_HL(z80, 6, RM(z80, z80->HL)); } /* BIT 6,(HL) */
+OP(cb,77) { BIT(z80, 6, z80->A); } /* BIT 6,A */
+
+OP(cb,78) { BIT(z80, 7, z80->B); } /* BIT 7,B */
+OP(cb,79) { BIT(z80, 7, z80->C); } /* BIT 7,C */
+OP(cb,7a) { BIT(z80, 7, z80->D); } /* BIT 7,D */
+OP(cb,7b) { BIT(z80, 7, z80->E); } /* BIT 7,E */
+OP(cb,7c) { BIT(z80, 7, z80->H); } /* BIT 7,H */
+OP(cb,7d) { BIT(z80, 7, z80->L); } /* BIT 7,L */
+OP(cb,7e) { BIT_HL(z80, 7, RM(z80, z80->HL)); } /* BIT 7,(HL) */
+OP(cb,7f) { BIT(z80, 7, z80->A); } /* BIT 7,A */
+
+OP(cb,80) { z80->B = RES(0, z80->B); } /* RES 0,B */
+OP(cb,81) { z80->C = RES(0, z80->C); } /* RES 0,C */
+OP(cb,82) { z80->D = RES(0, z80->D); } /* RES 0,D */
+OP(cb,83) { z80->E = RES(0, z80->E); } /* RES 0,E */
+OP(cb,84) { z80->H = RES(0, z80->H); } /* RES 0,H */
+OP(cb,85) { z80->L = RES(0, z80->L); } /* RES 0,L */
+OP(cb,86) { WM(z80, z80->HL, RES(0, RM(z80, z80->HL))); } /* RES 0,(HL) */
+OP(cb,87) { z80->A = RES(0, z80->A); } /* RES 0,A */
+
+OP(cb,88) { z80->B = RES(1, z80->B); } /* RES 1,B */
+OP(cb,89) { z80->C = RES(1, z80->C); } /* RES 1,C */
+OP(cb,8a) { z80->D = RES(1, z80->D); } /* RES 1,D */
+OP(cb,8b) { z80->E = RES(1, z80->E); } /* RES 1,E */
+OP(cb,8c) { z80->H = RES(1, z80->H); } /* RES 1,H */
+OP(cb,8d) { z80->L = RES(1, z80->L); } /* RES 1,L */
+OP(cb,8e) { WM(z80, z80->HL, RES(1, RM(z80, z80->HL))); } /* RES 1,(HL) */
+OP(cb,8f) { z80->A = RES(1, z80->A); } /* RES 1,A */
+
+OP(cb,90) { z80->B = RES(2, z80->B); } /* RES 2,B */
+OP(cb,91) { z80->C = RES(2, z80->C); } /* RES 2,C */
+OP(cb,92) { z80->D = RES(2, z80->D); } /* RES 2,D */
+OP(cb,93) { z80->E = RES(2, z80->E); } /* RES 2,E */
+OP(cb,94) { z80->H = RES(2, z80->H); } /* RES 2,H */
+OP(cb,95) { z80->L = RES(2, z80->L); } /* RES 2,L */
+OP(cb,96) { WM(z80, z80->HL, RES(2, RM(z80, z80->HL))); } /* RES 2,(HL) */
+OP(cb,97) { z80->A = RES(2, z80->A); } /* RES 2,A */
+
+OP(cb,98) { z80->B = RES(3, z80->B); } /* RES 3,B */
+OP(cb,99) { z80->C = RES(3, z80->C); } /* RES 3,C */
+OP(cb,9a) { z80->D = RES(3, z80->D); } /* RES 3,D */
+OP(cb,9b) { z80->E = RES(3, z80->E); } /* RES 3,E */
+OP(cb,9c) { z80->H = RES(3, z80->H); } /* RES 3,H */
+OP(cb,9d) { z80->L = RES(3, z80->L); } /* RES 3,L */
+OP(cb,9e) { WM(z80, z80->HL, RES(3, RM(z80, z80->HL))); } /* RES 3,(HL) */
+OP(cb,9f) { z80->A = RES(3, z80->A); } /* RES 3,A */
+
+OP(cb,a0) { z80->B = RES(4, z80->B); } /* RES 4,B */
+OP(cb,a1) { z80->C = RES(4, z80->C); } /* RES 4,C */
+OP(cb,a2) { z80->D = RES(4, z80->D); } /* RES 4,D */
+OP(cb,a3) { z80->E = RES(4, z80->E); } /* RES 4,E */
+OP(cb,a4) { z80->H = RES(4, z80->H); } /* RES 4,H */
+OP(cb,a5) { z80->L = RES(4, z80->L); } /* RES 4,L */
+OP(cb,a6) { WM(z80, z80->HL, RES(4, RM(z80, z80->HL))); } /* RES 4,(HL) */
+OP(cb,a7) { z80->A = RES(4, z80->A); } /* RES 4,A */
+
+OP(cb,a8) { z80->B = RES(5, z80->B); } /* RES 5,B */
+OP(cb,a9) { z80->C = RES(5, z80->C); } /* RES 5,C */
+OP(cb,aa) { z80->D = RES(5, z80->D); } /* RES 5,D */
+OP(cb,ab) { z80->E = RES(5, z80->E); } /* RES 5,E */
+OP(cb,ac) { z80->H = RES(5, z80->H); } /* RES 5,H */
+OP(cb,ad) { z80->L = RES(5, z80->L); } /* RES 5,L */
+OP(cb,ae) { WM(z80, z80->HL, RES(5, RM(z80, z80->HL))); } /* RES 5,(HL) */
+OP(cb,af) { z80->A = RES(5, z80->A); } /* RES 5,A */
+
+OP(cb,b0) { z80->B = RES(6, z80->B); } /* RES 6,B */
+OP(cb,b1) { z80->C = RES(6, z80->C); } /* RES 6,C */
+OP(cb,b2) { z80->D = RES(6, z80->D); } /* RES 6,D */
+OP(cb,b3) { z80->E = RES(6, z80->E); } /* RES 6,E */
+OP(cb,b4) { z80->H = RES(6, z80->H); } /* RES 6,H */
+OP(cb,b5) { z80->L = RES(6, z80->L); } /* RES 6,L */
+OP(cb,b6) { WM(z80, z80->HL, RES(6, RM(z80, z80->HL))); } /* RES 6,(HL) */
+OP(cb,b7) { z80->A = RES(6, z80->A); } /* RES 6,A */
+
+OP(cb,b8) { z80->B = RES(7, z80->B); } /* RES 7,B */
+OP(cb,b9) { z80->C = RES(7, z80->C); } /* RES 7,C */
+OP(cb,ba) { z80->D = RES(7, z80->D); } /* RES 7,D */
+OP(cb,bb) { z80->E = RES(7, z80->E); } /* RES 7,E */
+OP(cb,bc) { z80->H = RES(7, z80->H); } /* RES 7,H */
+OP(cb,bd) { z80->L = RES(7, z80->L); } /* RES 7,L */
+OP(cb,be) { WM(z80, z80->HL, RES(7, RM(z80, z80->HL))); } /* RES 7,(HL) */
+OP(cb,bf) { z80->A = RES(7, z80->A); } /* RES 7,A */
+
+OP(cb,c0) { z80->B = SET(0, z80->B); } /* SET 0,B */
+OP(cb,c1) { z80->C = SET(0, z80->C); } /* SET 0,C */
+OP(cb,c2) { z80->D = SET(0, z80->D); } /* SET 0,D */
+OP(cb,c3) { z80->E = SET(0, z80->E); } /* SET 0,E */
+OP(cb,c4) { z80->H = SET(0, z80->H); } /* SET 0,H */
+OP(cb,c5) { z80->L = SET(0, z80->L); } /* SET 0,L */
+OP(cb,c6) { WM(z80, z80->HL, SET(0, RM(z80, z80->HL))); } /* SET 0,(HL) */
+OP(cb,c7) { z80->A = SET(0, z80->A); } /* SET 0,A */
+
+OP(cb,c8) { z80->B = SET(1, z80->B); } /* SET 1,B */
+OP(cb,c9) { z80->C = SET(1, z80->C); } /* SET 1,C */
+OP(cb,ca) { z80->D = SET(1, z80->D); } /* SET 1,D */
+OP(cb,cb) { z80->E = SET(1, z80->E); } /* SET 1,E */
+OP(cb,cc) { z80->H = SET(1, z80->H); } /* SET 1,H */
+OP(cb,cd) { z80->L = SET(1, z80->L); } /* SET 1,L */
+OP(cb,ce) { WM(z80, z80->HL, SET(1, RM(z80, z80->HL))); } /* SET 1,(HL) */
+OP(cb,cf) { z80->A = SET(1, z80->A); } /* SET 1,A */
+
+OP(cb,d0) { z80->B = SET(2, z80->B); } /* SET 2,B */
+OP(cb,d1) { z80->C = SET(2, z80->C); } /* SET 2,C */
+OP(cb,d2) { z80->D = SET(2, z80->D); } /* SET 2,D */
+OP(cb,d3) { z80->E = SET(2, z80->E); } /* SET 2,E */
+OP(cb,d4) { z80->H = SET(2, z80->H); } /* SET 2,H */
+OP(cb,d5) { z80->L = SET(2, z80->L); } /* SET 2,L */
+OP(cb,d6) { WM(z80, z80->HL, SET(2, RM(z80, z80->HL))); } /* SET 2,(HL) */
+OP(cb,d7) { z80->A = SET(2, z80->A); } /* SET 2,A */
+
+OP(cb,d8) { z80->B = SET(3, z80->B); } /* SET 3,B */
+OP(cb,d9) { z80->C = SET(3, z80->C); } /* SET 3,C */
+OP(cb,da) { z80->D = SET(3, z80->D); } /* SET 3,D */
+OP(cb,db) { z80->E = SET(3, z80->E); } /* SET 3,E */
+OP(cb,dc) { z80->H = SET(3, z80->H); } /* SET 3,H */
+OP(cb,dd) { z80->L = SET(3, z80->L); } /* SET 3,L */
+OP(cb,de) { WM(z80, z80->HL, SET(3, RM(z80, z80->HL))); } /* SET 3,(HL) */
+OP(cb,df) { z80->A = SET(3, z80->A); } /* SET 3,A */
+
+OP(cb,e0) { z80->B = SET(4, z80->B); } /* SET 4,B */
+OP(cb,e1) { z80->C = SET(4, z80->C); } /* SET 4,C */
+OP(cb,e2) { z80->D = SET(4, z80->D); } /* SET 4,D */
+OP(cb,e3) { z80->E = SET(4, z80->E); } /* SET 4,E */
+OP(cb,e4) { z80->H = SET(4, z80->H); } /* SET 4,H */
+OP(cb,e5) { z80->L = SET(4, z80->L); } /* SET 4,L */
+OP(cb,e6) { WM(z80, z80->HL, SET(4, RM(z80, z80->HL))); } /* SET 4,(HL) */
+OP(cb,e7) { z80->A = SET(4, z80->A); } /* SET 4,A */
+
+OP(cb,e8) { z80->B = SET(5, z80->B); } /* SET 5,B */
+OP(cb,e9) { z80->C = SET(5, z80->C); } /* SET 5,C */
+OP(cb,ea) { z80->D = SET(5, z80->D); } /* SET 5,D */
+OP(cb,eb) { z80->E = SET(5, z80->E); } /* SET 5,E */
+OP(cb,ec) { z80->H = SET(5, z80->H); } /* SET 5,H */
+OP(cb,ed) { z80->L = SET(5, z80->L); } /* SET 5,L */
+OP(cb,ee) { WM(z80, z80->HL, SET(5, RM(z80, z80->HL))); } /* SET 5,(HL) */
+OP(cb,ef) { z80->A = SET(5, z80->A); } /* SET 5,A */
+
+OP(cb,f0) { z80->B = SET(6, z80->B); } /* SET 6,B */
+OP(cb,f1) { z80->C = SET(6, z80->C); } /* SET 6,C */
+OP(cb,f2) { z80->D = SET(6, z80->D); } /* SET 6,D */
+OP(cb,f3) { z80->E = SET(6, z80->E); } /* SET 6,E */
+OP(cb,f4) { z80->H = SET(6, z80->H); } /* SET 6,H */
+OP(cb,f5) { z80->L = SET(6, z80->L); } /* SET 6,L */
+OP(cb,f6) { WM(z80, z80->HL, SET(6, RM(z80, z80->HL))); } /* SET 6,(HL) */
+OP(cb,f7) { z80->A = SET(6, z80->A); } /* SET 6,A */
+
+OP(cb,f8) { z80->B = SET(7, z80->B); } /* SET 7,B */
+OP(cb,f9) { z80->C = SET(7, z80->C); } /* SET 7,C */
+OP(cb,fa) { z80->D = SET(7, z80->D); } /* SET 7,D */
+OP(cb,fb) { z80->E = SET(7, z80->E); } /* SET 7,E */
+OP(cb,fc) { z80->H = SET(7, z80->H); } /* SET 7,H */
+OP(cb,fd) { z80->L = SET(7, z80->L); } /* SET 7,L */
+OP(cb,fe) { WM(z80, z80->HL, SET(7, RM(z80, z80->HL))); } /* SET 7,(HL) */
+OP(cb,ff) { z80->A = SET(7, z80->A); } /* SET 7,A */
+
+
+/**********************************************************
+* opcodes with DD/FD CB prefix
+* rotate, shift and bit operations with (IX+o)
+**********************************************************/
+OP(xycb,00) { z80->B = RLC(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->B); } /* RLC B=(XY+o) */
+OP(xycb,01) { z80->C = RLC(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->C); } /* RLC C=(XY+o) */
+OP(xycb,02) { z80->D = RLC(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->D); } /* RLC D=(XY+o) */
+OP(xycb,03) { z80->E = RLC(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->E); } /* RLC E=(XY+o) */
+OP(xycb,04) { z80->H = RLC(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->H); } /* RLC H=(XY+o) */
+OP(xycb,05) { z80->L = RLC(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->L); } /* RLC L=(XY+o) */
+OP(xycb,06) { WM(z80, z80->ea, RLC(z80, RM(z80, z80->ea))); } /* RLC (XY+o) */
+OP(xycb,07) { z80->A = RLC(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->A); } /* RLC A=(XY+o) */
+
+OP(xycb,08) { z80->B = RRC(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->B); } /* RRC B=(XY+o) */
+OP(xycb,09) { z80->C = RRC(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->C); } /* RRC C=(XY+o) */
+OP(xycb,0a) { z80->D = RRC(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->D); } /* RRC D=(XY+o) */
+OP(xycb,0b) { z80->E = RRC(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->E); } /* RRC E=(XY+o) */
+OP(xycb,0c) { z80->H = RRC(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->H); } /* RRC H=(XY+o) */
+OP(xycb,0d) { z80->L = RRC(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->L); } /* RRC L=(XY+o) */
+OP(xycb,0e) { WM(z80, z80->ea,RRC(z80, RM(z80, z80->ea))); } /* RRC (XY+o) */
+OP(xycb,0f) { z80->A = RRC(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->A); } /* RRC A=(XY+o) */
+
+OP(xycb,10) { z80->B = RL(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->B); } /* RL B=(XY+o) */
+OP(xycb,11) { z80->C = RL(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->C); } /* RL C=(XY+o) */
+OP(xycb,12) { z80->D = RL(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->D); } /* RL D=(XY+o) */
+OP(xycb,13) { z80->E = RL(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->E); } /* RL E=(XY+o) */
+OP(xycb,14) { z80->H = RL(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->H); } /* RL H=(XY+o) */
+OP(xycb,15) { z80->L = RL(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->L); } /* RL L=(XY+o) */
+OP(xycb,16) { WM(z80, z80->ea,RL(z80, RM(z80, z80->ea))); } /* RL (XY+o) */
+OP(xycb,17) { z80->A = RL(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->A); } /* RL A=(XY+o) */
+
+OP(xycb,18) { z80->B = RR(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->B); } /* RR B=(XY+o) */
+OP(xycb,19) { z80->C = RR(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->C); } /* RR C=(XY+o) */
+OP(xycb,1a) { z80->D = RR(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->D); } /* RR D=(XY+o) */
+OP(xycb,1b) { z80->E = RR(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->E); } /* RR E=(XY+o) */
+OP(xycb,1c) { z80->H = RR(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->H); } /* RR H=(XY+o) */
+OP(xycb,1d) { z80->L = RR(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->L); } /* RR L=(XY+o) */
+OP(xycb,1e) { WM(z80, z80->ea,RR(z80, RM(z80, z80->ea))); } /* RR (XY+o) */
+OP(xycb,1f) { z80->A = RR(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->A); } /* RR A=(XY+o) */
+
+OP(xycb,20) { z80->B = SLA(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->B); } /* SLA B=(XY+o) */
+OP(xycb,21) { z80->C = SLA(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->C); } /* SLA C=(XY+o) */
+OP(xycb,22) { z80->D = SLA(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->D); } /* SLA D=(XY+o) */
+OP(xycb,23) { z80->E = SLA(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->E); } /* SLA E=(XY+o) */
+OP(xycb,24) { z80->H = SLA(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->H); } /* SLA H=(XY+o) */
+OP(xycb,25) { z80->L = SLA(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->L); } /* SLA L=(XY+o) */
+OP(xycb,26) { WM(z80, z80->ea,SLA(z80, RM(z80, z80->ea))); } /* SLA (XY+o) */
+OP(xycb,27) { z80->A = SLA(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->A); } /* SLA A=(XY+o) */
+
+OP(xycb,28) { z80->B = SRA(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->B); } /* SRA B=(XY+o) */
+OP(xycb,29) { z80->C = SRA(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->C); } /* SRA C=(XY+o) */
+OP(xycb,2a) { z80->D = SRA(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->D); } /* SRA D=(XY+o) */
+OP(xycb,2b) { z80->E = SRA(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->E); } /* SRA E=(XY+o) */
+OP(xycb,2c) { z80->H = SRA(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->H); } /* SRA H=(XY+o) */
+OP(xycb,2d) { z80->L = SRA(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->L); } /* SRA L=(XY+o) */
+OP(xycb,2e) { WM(z80, z80->ea,SRA(z80, RM(z80, z80->ea))); } /* SRA (XY+o) */
+OP(xycb,2f) { z80->A = SRA(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->A); } /* SRA A=(XY+o) */
+
+OP(xycb,30) { z80->B = SLL(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->B); } /* SLL B=(XY+o) */
+OP(xycb,31) { z80->C = SLL(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->C); } /* SLL C=(XY+o) */
+OP(xycb,32) { z80->D = SLL(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->D); } /* SLL D=(XY+o) */
+OP(xycb,33) { z80->E = SLL(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->E); } /* SLL E=(XY+o) */
+OP(xycb,34) { z80->H = SLL(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->H); } /* SLL H=(XY+o) */
+OP(xycb,35) { z80->L = SLL(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->L); } /* SLL L=(XY+o) */
+OP(xycb,36) { WM(z80, z80->ea,SLL(z80, RM(z80, z80->ea))); } /* SLL (XY+o) */
+OP(xycb,37) { z80->A = SLL(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->A); } /* SLL A=(XY+o) */
+
+OP(xycb,38) { z80->B = SRL(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->B); } /* SRL B=(XY+o) */
+OP(xycb,39) { z80->C = SRL(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->C); } /* SRL C=(XY+o) */
+OP(xycb,3a) { z80->D = SRL(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->D); } /* SRL D=(XY+o) */
+OP(xycb,3b) { z80->E = SRL(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->E); } /* SRL E=(XY+o) */
+OP(xycb,3c) { z80->H = SRL(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->H); } /* SRL H=(XY+o) */
+OP(xycb,3d) { z80->L = SRL(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->L); } /* SRL L=(XY+o) */
+OP(xycb,3e) { WM(z80, z80->ea,SRL(z80, RM(z80, z80->ea))); } /* SRL (XY+o) */
+OP(xycb,3f) { z80->A = SRL(z80, RM(z80, z80->ea)); WM(z80, z80->ea,z80->A); } /* SRL A=(XY+o) */
+
+OP(xycb,40) { xycb_46(z80); } /* BIT 0,(XY+o) */
+OP(xycb,41) { xycb_46(z80); } /* BIT 0,(XY+o) */
+OP(xycb,42) { xycb_46(z80); } /* BIT 0,(XY+o) */
+OP(xycb,43) { xycb_46(z80); } /* BIT 0,(XY+o) */
+OP(xycb,44) { xycb_46(z80); } /* BIT 0,(XY+o) */
+OP(xycb,45) { xycb_46(z80); } /* BIT 0,(XY+o) */
+OP(xycb,46) { BIT_XY(z80, 0, RM(z80, z80->ea)); } /* BIT 0,(XY+o) */
+OP(xycb,47) { xycb_46(z80); } /* BIT 0,(XY+o) */
+
+OP(xycb,48) { xycb_4e(z80); } /* BIT 1,(XY+o) */
+OP(xycb,49) { xycb_4e(z80); } /* BIT 1,(XY+o) */
+OP(xycb,4a) { xycb_4e(z80); } /* BIT 1,(XY+o) */
+OP(xycb,4b) { xycb_4e(z80); } /* BIT 1,(XY+o) */
+OP(xycb,4c) { xycb_4e(z80); } /* BIT 1,(XY+o) */
+OP(xycb,4d) { xycb_4e(z80); } /* BIT 1,(XY+o) */
+OP(xycb,4e) { BIT_XY(z80, 1, RM(z80, z80->ea)); } /* BIT 1,(XY+o) */
+OP(xycb,4f) { xycb_4e(z80); } /* BIT 1,(XY+o) */
+
+OP(xycb,50) { xycb_56(z80); } /* BIT 2,(XY+o) */
+OP(xycb,51) { xycb_56(z80); } /* BIT 2,(XY+o) */
+OP(xycb,52) { xycb_56(z80); } /* BIT 2,(XY+o) */
+OP(xycb,53) { xycb_56(z80); } /* BIT 2,(XY+o) */
+OP(xycb,54) { xycb_56(z80); } /* BIT 2,(XY+o) */
+OP(xycb,55) { xycb_56(z80); } /* BIT 2,(XY+o) */
+OP(xycb,56) { BIT_XY(z80, 2, RM(z80, z80->ea)); } /* BIT 2,(XY+o) */
+OP(xycb,57) { xycb_56(z80); } /* BIT 2,(XY+o) */
+
+OP(xycb,58) { xycb_5e(z80); } /* BIT 3,(XY+o) */
+OP(xycb,59) { xycb_5e(z80); } /* BIT 3,(XY+o) */
+OP(xycb,5a) { xycb_5e(z80); } /* BIT 3,(XY+o) */
+OP(xycb,5b) { xycb_5e(z80); } /* BIT 3,(XY+o) */
+OP(xycb,5c) { xycb_5e(z80); } /* BIT 3,(XY+o) */
+OP(xycb,5d) { xycb_5e(z80); } /* BIT 3,(XY+o) */
+OP(xycb,5e) { BIT_XY(z80, 3, RM(z80, z80->ea)); } /* BIT 3,(XY+o) */
+OP(xycb,5f) { xycb_5e(z80); } /* BIT 3,(XY+o) */
+
+OP(xycb,60) { xycb_66(z80); } /* BIT 4,(XY+o) */
+OP(xycb,61) { xycb_66(z80); } /* BIT 4,(XY+o) */
+OP(xycb,62) { xycb_66(z80); } /* BIT 4,(XY+o) */
+OP(xycb,63) { xycb_66(z80); } /* BIT 4,(XY+o) */
+OP(xycb,64) { xycb_66(z80); } /* BIT 4,(XY+o) */
+OP(xycb,65) { xycb_66(z80); } /* BIT 4,(XY+o) */
+OP(xycb,66) { BIT_XY(z80, 4, RM(z80, z80->ea)); } /* BIT 4,(XY+o) */
+OP(xycb,67) { xycb_66(z80); } /* BIT 4,(XY+o) */
+
+OP(xycb,68) { xycb_6e(z80); } /* BIT 5,(XY+o) */
+OP(xycb,69) { xycb_6e(z80); } /* BIT 5,(XY+o) */
+OP(xycb,6a) { xycb_6e(z80); } /* BIT 5,(XY+o) */
+OP(xycb,6b) { xycb_6e(z80); } /* BIT 5,(XY+o) */
+OP(xycb,6c) { xycb_6e(z80); } /* BIT 5,(XY+o) */
+OP(xycb,6d) { xycb_6e(z80); } /* BIT 5,(XY+o) */
+OP(xycb,6e) { BIT_XY(z80, 5, RM(z80, z80->ea)); } /* BIT 5,(XY+o) */
+OP(xycb,6f) { xycb_6e(z80); } /* BIT 5,(XY+o) */
+
+OP(xycb,70) { xycb_76(z80); } /* BIT 6,(XY+o) */
+OP(xycb,71) { xycb_76(z80); } /* BIT 6,(XY+o) */
+OP(xycb,72) { xycb_76(z80); } /* BIT 6,(XY+o) */
+OP(xycb,73) { xycb_76(z80); } /* BIT 6,(XY+o) */
+OP(xycb,74) { xycb_76(z80); } /* BIT 6,(XY+o) */
+OP(xycb,75) { xycb_76(z80); } /* BIT 6,(XY+o) */
+OP(xycb,76) { BIT_XY(z80, 6, RM(z80, z80->ea)); } /* BIT 6,(XY+o) */
+OP(xycb,77) { xycb_76(z80); } /* BIT 6,(XY+o) */
+
+OP(xycb,78) { xycb_7e(z80); } /* BIT 7,(XY+o) */
+OP(xycb,79) { xycb_7e(z80); } /* BIT 7,(XY+o) */
+OP(xycb,7a) { xycb_7e(z80); } /* BIT 7,(XY+o) */
+OP(xycb,7b) { xycb_7e(z80); } /* BIT 7,(XY+o) */
+OP(xycb,7c) { xycb_7e(z80); } /* BIT 7,(XY+o) */
+OP(xycb,7d) { xycb_7e(z80); } /* BIT 7,(XY+o) */
+OP(xycb,7e) { BIT_XY(z80, 7, RM(z80, z80->ea)); } /* BIT 7,(XY+o) */
+OP(xycb,7f) { xycb_7e(z80); } /* BIT 7,(XY+o) */
+
+OP(xycb,80) { z80->B = RES(0, RM(z80, z80->ea)); WM(z80, z80->ea,z80->B); } /* RES 0,B=(XY+o) */
+OP(xycb,81) { z80->C = RES(0, RM(z80, z80->ea)); WM(z80, z80->ea,z80->C); } /* RES 0,C=(XY+o) */
+OP(xycb,82) { z80->D = RES(0, RM(z80, z80->ea)); WM(z80, z80->ea,z80->D); } /* RES 0,D=(XY+o) */
+OP(xycb,83) { z80->E = RES(0, RM(z80, z80->ea)); WM(z80, z80->ea,z80->E); } /* RES 0,E=(XY+o) */
+OP(xycb,84) { z80->H = RES(0, RM(z80, z80->ea)); WM(z80, z80->ea,z80->H); } /* RES 0,H=(XY+o) */
+OP(xycb,85) { z80->L = RES(0, RM(z80, z80->ea)); WM(z80, z80->ea,z80->L); } /* RES 0,L=(XY+o) */
+OP(xycb,86) { WM(z80, z80->ea, RES(0, RM(z80, z80->ea))); } /* RES 0,(XY+o) */
+OP(xycb,87) { z80->A = RES(0, RM(z80, z80->ea)); WM(z80, z80->ea,z80->A); } /* RES 0,A=(XY+o) */
+
+OP(xycb,88) { z80->B = RES(1, RM(z80, z80->ea)); WM(z80, z80->ea,z80->B); } /* RES 1,B=(XY+o) */
+OP(xycb,89) { z80->C = RES(1, RM(z80, z80->ea)); WM(z80, z80->ea,z80->C); } /* RES 1,C=(XY+o) */
+OP(xycb,8a) { z80->D = RES(1, RM(z80, z80->ea)); WM(z80, z80->ea,z80->D); } /* RES 1,D=(XY+o) */
+OP(xycb,8b) { z80->E = RES(1, RM(z80, z80->ea)); WM(z80, z80->ea,z80->E); } /* RES 1,E=(XY+o) */
+OP(xycb,8c) { z80->H = RES(1, RM(z80, z80->ea)); WM(z80, z80->ea,z80->H); } /* RES 1,H=(XY+o) */
+OP(xycb,8d) { z80->L = RES(1, RM(z80, z80->ea)); WM(z80, z80->ea,z80->L); } /* RES 1,L=(XY+o) */
+OP(xycb,8e) { WM(z80, z80->ea, RES(1, RM(z80, z80->ea))); } /* RES 1,(XY+o) */
+OP(xycb,8f) { z80->A = RES(1, RM(z80, z80->ea)); WM(z80, z80->ea,z80->A); } /* RES 1,A=(XY+o) */
+
+OP(xycb,90) { z80->B = RES(2, RM(z80, z80->ea)); WM(z80, z80->ea,z80->B); } /* RES 2,B=(XY+o) */
+OP(xycb,91) { z80->C = RES(2, RM(z80, z80->ea)); WM(z80, z80->ea,z80->C); } /* RES 2,C=(XY+o) */
+OP(xycb,92) { z80->D = RES(2, RM(z80, z80->ea)); WM(z80, z80->ea,z80->D); } /* RES 2,D=(XY+o) */
+OP(xycb,93) { z80->E = RES(2, RM(z80, z80->ea)); WM(z80, z80->ea,z80->E); } /* RES 2,E=(XY+o) */
+OP(xycb,94) { z80->H = RES(2, RM(z80, z80->ea)); WM(z80, z80->ea,z80->H); } /* RES 2,H=(XY+o) */
+OP(xycb,95) { z80->L = RES(2, RM(z80, z80->ea)); WM(z80, z80->ea,z80->L); } /* RES 2,L=(XY+o) */
+OP(xycb,96) { WM(z80, z80->ea, RES(2, RM(z80, z80->ea))); } /* RES 2,(XY+o) */
+OP(xycb,97) { z80->A = RES(2, RM(z80, z80->ea)); WM(z80, z80->ea,z80->A); } /* RES 2,A=(XY+o) */
+
+OP(xycb,98) { z80->B = RES(3, RM(z80, z80->ea)); WM(z80, z80->ea,z80->B); } /* RES 3,B=(XY+o) */
+OP(xycb,99) { z80->C = RES(3, RM(z80, z80->ea)); WM(z80, z80->ea,z80->C); } /* RES 3,C=(XY+o) */
+OP(xycb,9a) { z80->D = RES(3, RM(z80, z80->ea)); WM(z80, z80->ea,z80->D); } /* RES 3,D=(XY+o) */
+OP(xycb,9b) { z80->E = RES(3, RM(z80, z80->ea)); WM(z80, z80->ea,z80->E); } /* RES 3,E=(XY+o) */
+OP(xycb,9c) { z80->H = RES(3, RM(z80, z80->ea)); WM(z80, z80->ea,z80->H); } /* RES 3,H=(XY+o) */
+OP(xycb,9d) { z80->L = RES(3, RM(z80, z80->ea)); WM(z80, z80->ea,z80->L); } /* RES 3,L=(XY+o) */
+OP(xycb,9e) { WM(z80, z80->ea, RES(3, RM(z80, z80->ea))); } /* RES 3,(XY+o) */
+OP(xycb,9f) { z80->A = RES(3, RM(z80, z80->ea)); WM(z80, z80->ea,z80->A); } /* RES 3,A=(XY+o) */
+
+OP(xycb,a0) { z80->B = RES(4, RM(z80, z80->ea)); WM(z80, z80->ea,z80->B); } /* RES 4,B=(XY+o) */
+OP(xycb,a1) { z80->C = RES(4, RM(z80, z80->ea)); WM(z80, z80->ea,z80->C); } /* RES 4,C=(XY+o) */
+OP(xycb,a2) { z80->D = RES(4, RM(z80, z80->ea)); WM(z80, z80->ea,z80->D); } /* RES 4,D=(XY+o) */
+OP(xycb,a3) { z80->E = RES(4, RM(z80, z80->ea)); WM(z80, z80->ea,z80->E); } /* RES 4,E=(XY+o) */
+OP(xycb,a4) { z80->H = RES(4, RM(z80, z80->ea)); WM(z80, z80->ea,z80->H); } /* RES 4,H=(XY+o) */
+OP(xycb,a5) { z80->L = RES(4, RM(z80, z80->ea)); WM(z80, z80->ea,z80->L); } /* RES 4,L=(XY+o) */
+OP(xycb,a6) { WM(z80, z80->ea, RES(4, RM(z80, z80->ea))); } /* RES 4,(XY+o) */
+OP(xycb,a7) { z80->A = RES(4, RM(z80, z80->ea)); WM(z80, z80->ea,z80->A); } /* RES 4,A=(XY+o) */
+
+OP(xycb,a8) { z80->B = RES(5, RM(z80, z80->ea)); WM(z80, z80->ea,z80->B); } /* RES 5,B=(XY+o) */
+OP(xycb,a9) { z80->C = RES(5, RM(z80, z80->ea)); WM(z80, z80->ea,z80->C); } /* RES 5,C=(XY+o) */
+OP(xycb,aa) { z80->D = RES(5, RM(z80, z80->ea)); WM(z80, z80->ea,z80->D); } /* RES 5,D=(XY+o) */
+OP(xycb,ab) { z80->E = RES(5, RM(z80, z80->ea)); WM(z80, z80->ea,z80->E); } /* RES 5,E=(XY+o) */
+OP(xycb,ac) { z80->H = RES(5, RM(z80, z80->ea)); WM(z80, z80->ea,z80->H); } /* RES 5,H=(XY+o) */
+OP(xycb,ad) { z80->L = RES(5, RM(z80, z80->ea)); WM(z80, z80->ea,z80->L); } /* RES 5,L=(XY+o) */
+OP(xycb,ae) { WM(z80, z80->ea, RES(5, RM(z80, z80->ea))); } /* RES 5,(XY+o) */
+OP(xycb,af) { z80->A = RES(5, RM(z80, z80->ea)); WM(z80, z80->ea,z80->A); } /* RES 5,A=(XY+o) */
+
+OP(xycb,b0) { z80->B = RES(6, RM(z80, z80->ea)); WM(z80, z80->ea,z80->B); } /* RES 6,B=(XY+o) */
+OP(xycb,b1) { z80->C = RES(6, RM(z80, z80->ea)); WM(z80, z80->ea,z80->C); } /* RES 6,C=(XY+o) */
+OP(xycb,b2) { z80->D = RES(6, RM(z80, z80->ea)); WM(z80, z80->ea,z80->D); } /* RES 6,D=(XY+o) */
+OP(xycb,b3) { z80->E = RES(6, RM(z80, z80->ea)); WM(z80, z80->ea,z80->E); } /* RES 6,E=(XY+o) */
+OP(xycb,b4) { z80->H = RES(6, RM(z80, z80->ea)); WM(z80, z80->ea,z80->H); } /* RES 6,H=(XY+o) */
+OP(xycb,b5) { z80->L = RES(6, RM(z80, z80->ea)); WM(z80, z80->ea,z80->L); } /* RES 6,L=(XY+o) */
+OP(xycb,b6) { WM(z80, z80->ea, RES(6, RM(z80, z80->ea))); } /* RES 6,(XY+o) */
+OP(xycb,b7) { z80->A = RES(6, RM(z80, z80->ea)); WM(z80, z80->ea,z80->A); } /* RES 6,A=(XY+o) */
+
+OP(xycb,b8) { z80->B = RES(7, RM(z80, z80->ea)); WM(z80, z80->ea,z80->B); } /* RES 7,B=(XY+o) */
+OP(xycb,b9) { z80->C = RES(7, RM(z80, z80->ea)); WM(z80, z80->ea,z80->C); } /* RES 7,C=(XY+o) */
+OP(xycb,ba) { z80->D = RES(7, RM(z80, z80->ea)); WM(z80, z80->ea,z80->D); } /* RES 7,D=(XY+o) */
+OP(xycb,bb) { z80->E = RES(7, RM(z80, z80->ea)); WM(z80, z80->ea,z80->E); } /* RES 7,E=(XY+o) */
+OP(xycb,bc) { z80->H = RES(7, RM(z80, z80->ea)); WM(z80, z80->ea,z80->H); } /* RES 7,H=(XY+o) */
+OP(xycb,bd) { z80->L = RES(7, RM(z80, z80->ea)); WM(z80, z80->ea,z80->L); } /* RES 7,L=(XY+o) */
+OP(xycb,be) { WM(z80, z80->ea, RES(7, RM(z80, z80->ea))); } /* RES 7,(XY+o) */
+OP(xycb,bf) { z80->A = RES(7, RM(z80, z80->ea)); WM(z80, z80->ea,z80->A); } /* RES 7,A=(XY+o) */
+
+OP(xycb,c0) { z80->B = SET(0, RM(z80, z80->ea)); WM(z80, z80->ea,z80->B); } /* SET 0,B=(XY+o) */
+OP(xycb,c1) { z80->C = SET(0, RM(z80, z80->ea)); WM(z80, z80->ea,z80->C); } /* SET 0,C=(XY+o) */
+OP(xycb,c2) { z80->D = SET(0, RM(z80, z80->ea)); WM(z80, z80->ea,z80->D); } /* SET 0,D=(XY+o) */
+OP(xycb,c3) { z80->E = SET(0, RM(z80, z80->ea)); WM(z80, z80->ea,z80->E); } /* SET 0,E=(XY+o) */
+OP(xycb,c4) { z80->H = SET(0, RM(z80, z80->ea)); WM(z80, z80->ea,z80->H); } /* SET 0,H=(XY+o) */
+OP(xycb,c5) { z80->L = SET(0, RM(z80, z80->ea)); WM(z80, z80->ea,z80->L); } /* SET 0,L=(XY+o) */
+OP(xycb,c6) { WM(z80, z80->ea, SET(0, RM(z80, z80->ea))); } /* SET 0,(XY+o) */
+OP(xycb,c7) { z80->A = SET(0, RM(z80, z80->ea)); WM(z80, z80->ea,z80->A); } /* SET 0,A=(XY+o) */
+
+OP(xycb,c8) { z80->B = SET(1, RM(z80, z80->ea)); WM(z80, z80->ea,z80->B); } /* SET 1,B=(XY+o) */
+OP(xycb,c9) { z80->C = SET(1, RM(z80, z80->ea)); WM(z80, z80->ea,z80->C); } /* SET 1,C=(XY+o) */
+OP(xycb,ca) { z80->D = SET(1, RM(z80, z80->ea)); WM(z80, z80->ea,z80->D); } /* SET 1,D=(XY+o) */
+OP(xycb,cb) { z80->E = SET(1, RM(z80, z80->ea)); WM(z80, z80->ea,z80->E); } /* SET 1,E=(XY+o) */
+OP(xycb,cc) { z80->H = SET(1, RM(z80, z80->ea)); WM(z80, z80->ea,z80->H); } /* SET 1,H=(XY+o) */
+OP(xycb,cd) { z80->L = SET(1, RM(z80, z80->ea)); WM(z80, z80->ea,z80->L); } /* SET 1,L=(XY+o) */
+OP(xycb,ce) { WM(z80, z80->ea, SET(1, RM(z80, z80->ea))); } /* SET 1,(XY+o) */
+OP(xycb,cf) { z80->A = SET(1, RM(z80, z80->ea)); WM(z80, z80->ea,z80->A); } /* SET 1,A=(XY+o) */
+
+OP(xycb,d0) { z80->B = SET(2, RM(z80, z80->ea)); WM(z80, z80->ea,z80->B); } /* SET 2,B=(XY+o) */
+OP(xycb,d1) { z80->C = SET(2, RM(z80, z80->ea)); WM(z80, z80->ea,z80->C); } /* SET 2,C=(XY+o) */
+OP(xycb,d2) { z80->D = SET(2, RM(z80, z80->ea)); WM(z80, z80->ea,z80->D); } /* SET 2,D=(XY+o) */
+OP(xycb,d3) { z80->E = SET(2, RM(z80, z80->ea)); WM(z80, z80->ea,z80->E); } /* SET 2,E=(XY+o) */
+OP(xycb,d4) { z80->H = SET(2, RM(z80, z80->ea)); WM(z80, z80->ea,z80->H); } /* SET 2,H=(XY+o) */
+OP(xycb,d5) { z80->L = SET(2, RM(z80, z80->ea)); WM(z80, z80->ea,z80->L); } /* SET 2,L=(XY+o) */
+OP(xycb,d6) { WM(z80, z80->ea, SET(2, RM(z80, z80->ea))); } /* SET 2,(XY+o) */
+OP(xycb,d7) { z80->A = SET(2, RM(z80, z80->ea)); WM(z80, z80->ea,z80->A); } /* SET 2,A=(XY+o) */
+
+OP(xycb,d8) { z80->B = SET(3, RM(z80, z80->ea)); WM(z80, z80->ea,z80->B); } /* SET 3,B=(XY+o) */
+OP(xycb,d9) { z80->C = SET(3, RM(z80, z80->ea)); WM(z80, z80->ea,z80->C); } /* SET 3,C=(XY+o) */
+OP(xycb,da) { z80->D = SET(3, RM(z80, z80->ea)); WM(z80, z80->ea,z80->D); } /* SET 3,D=(XY+o) */
+OP(xycb,db) { z80->E = SET(3, RM(z80, z80->ea)); WM(z80, z80->ea,z80->E); } /* SET 3,E=(XY+o) */
+OP(xycb,dc) { z80->H = SET(3, RM(z80, z80->ea)); WM(z80, z80->ea,z80->H); } /* SET 3,H=(XY+o) */
+OP(xycb,dd) { z80->L = SET(3, RM(z80, z80->ea)); WM(z80, z80->ea,z80->L); } /* SET 3,L=(XY+o) */
+OP(xycb,de) { WM(z80, z80->ea, SET(3, RM(z80, z80->ea))); } /* SET 3,(XY+o) */
+OP(xycb,df) { z80->A = SET(3, RM(z80, z80->ea)); WM(z80, z80->ea,z80->A); } /* SET 3,A=(XY+o) */
+
+OP(xycb,e0) { z80->B = SET(4, RM(z80, z80->ea)); WM(z80, z80->ea,z80->B); } /* SET 4,B=(XY+o) */
+OP(xycb,e1) { z80->C = SET(4, RM(z80, z80->ea)); WM(z80, z80->ea,z80->C); } /* SET 4,C=(XY+o) */
+OP(xycb,e2) { z80->D = SET(4, RM(z80, z80->ea)); WM(z80, z80->ea,z80->D); } /* SET 4,D=(XY+o) */
+OP(xycb,e3) { z80->E = SET(4, RM(z80, z80->ea)); WM(z80, z80->ea,z80->E); } /* SET 4,E=(XY+o) */
+OP(xycb,e4) { z80->H = SET(4, RM(z80, z80->ea)); WM(z80, z80->ea,z80->H); } /* SET 4,H=(XY+o) */
+OP(xycb,e5) { z80->L = SET(4, RM(z80, z80->ea)); WM(z80, z80->ea,z80->L); } /* SET 4,L=(XY+o) */
+OP(xycb,e6) { WM(z80, z80->ea, SET(4, RM(z80, z80->ea))); } /* SET 4,(XY+o) */
+OP(xycb,e7) { z80->A = SET(4, RM(z80, z80->ea)); WM(z80, z80->ea,z80->A); } /* SET 4,A=(XY+o) */
+
+OP(xycb,e8) { z80->B = SET(5, RM(z80, z80->ea)); WM(z80, z80->ea,z80->B); } /* SET 5,B=(XY+o) */
+OP(xycb,e9) { z80->C = SET(5, RM(z80, z80->ea)); WM(z80, z80->ea,z80->C); } /* SET 5,C=(XY+o) */
+OP(xycb,ea) { z80->D = SET(5, RM(z80, z80->ea)); WM(z80, z80->ea,z80->D); } /* SET 5,D=(XY+o) */
+OP(xycb,eb) { z80->E = SET(5, RM(z80, z80->ea)); WM(z80, z80->ea,z80->E); } /* SET 5,E=(XY+o) */
+OP(xycb,ec) { z80->H = SET(5, RM(z80, z80->ea)); WM(z80, z80->ea,z80->H); } /* SET 5,H=(XY+o) */
+OP(xycb,ed) { z80->L = SET(5, RM(z80, z80->ea)); WM(z80, z80->ea,z80->L); } /* SET 5,L=(XY+o) */
+OP(xycb,ee) { WM(z80, z80->ea, SET(5, RM(z80, z80->ea))); } /* SET 5,(XY+o) */
+OP(xycb,ef) { z80->A = SET(5, RM(z80, z80->ea)); WM(z80, z80->ea,z80->A); } /* SET 5,A=(XY+o) */
+
+OP(xycb,f0) { z80->B = SET(6, RM(z80, z80->ea)); WM(z80, z80->ea,z80->B); } /* SET 6,B=(XY+o) */
+OP(xycb,f1) { z80->C = SET(6, RM(z80, z80->ea)); WM(z80, z80->ea,z80->C); } /* SET 6,C=(XY+o) */
+OP(xycb,f2) { z80->D = SET(6, RM(z80, z80->ea)); WM(z80, z80->ea,z80->D); } /* SET 6,D=(XY+o) */
+OP(xycb,f3) { z80->E = SET(6, RM(z80, z80->ea)); WM(z80, z80->ea,z80->E); } /* SET 6,E=(XY+o) */
+OP(xycb,f4) { z80->H = SET(6, RM(z80, z80->ea)); WM(z80, z80->ea,z80->H); } /* SET 6,H=(XY+o) */
+OP(xycb,f5) { z80->L = SET(6, RM(z80, z80->ea)); WM(z80, z80->ea,z80->L); } /* SET 6,L=(XY+o) */
+OP(xycb,f6) { WM(z80, z80->ea, SET(6, RM(z80, z80->ea))); } /* SET 6,(XY+o) */
+OP(xycb,f7) { z80->A = SET(6, RM(z80, z80->ea)); WM(z80, z80->ea,z80->A); } /* SET 6,A=(XY+o) */
+
+OP(xycb,f8) { z80->B = SET(7, RM(z80, z80->ea)); WM(z80, z80->ea,z80->B); } /* SET 7,B=(XY+o) */
+OP(xycb,f9) { z80->C = SET(7, RM(z80, z80->ea)); WM(z80, z80->ea,z80->C); } /* SET 7,C=(XY+o) */
+OP(xycb,fa) { z80->D = SET(7, RM(z80, z80->ea)); WM(z80, z80->ea,z80->D); } /* SET 7,D=(XY+o) */
+OP(xycb,fb) { z80->E = SET(7, RM(z80, z80->ea)); WM(z80, z80->ea,z80->E); } /* SET 7,E=(XY+o) */
+OP(xycb,fc) { z80->H = SET(7, RM(z80, z80->ea)); WM(z80, z80->ea,z80->H); } /* SET 7,H=(XY+o) */
+OP(xycb,fd) { z80->L = SET(7, RM(z80, z80->ea)); WM(z80, z80->ea,z80->L); } /* SET 7,L=(XY+o) */
+OP(xycb,fe) { WM(z80, z80->ea, SET(7, RM(z80, z80->ea))); } /* SET 7,(XY+o) */
+OP(xycb,ff) { z80->A = SET(7, RM(z80, z80->ea)); WM(z80, z80->ea,z80->A); } /* SET 7,A=(XY+o) */
+
+OP(illegal,1) {
+ logerror("Z80 '%s' ill. opcode $%02x $%02x\n",
+ z80->device->tag(), z80->direct->read_decrypted_byte((z80->PCD-1)&0xffff), z80->direct->read_decrypted_byte(z80->PCD));
+}
+
+/**********************************************************
+ * IX register related opcodes (DD prefix)
+ **********************************************************/
+OP(dd,00) { illegal_1(z80); op_00(z80); } /* DB DD */
+OP(dd,01) { illegal_1(z80); op_01(z80); } /* DB DD */
+OP(dd,02) { illegal_1(z80); op_02(z80); } /* DB DD */
+OP(dd,03) { illegal_1(z80); op_03(z80); } /* DB DD */
+OP(dd,04) { illegal_1(z80); op_04(z80); } /* DB DD */
+OP(dd,05) { illegal_1(z80); op_05(z80); } /* DB DD */
+OP(dd,06) { illegal_1(z80); op_06(z80); } /* DB DD */
+OP(dd,07) { illegal_1(z80); op_07(z80); } /* DB DD */
+
+OP(dd,08) { illegal_1(z80); op_08(z80); } /* DB DD */
+OP(dd,09) { ADD16(z80, ix, bc); } /* ADD IX,BC */
+OP(dd,0a) { illegal_1(z80); op_0a(z80); } /* DB DD */
+OP(dd,0b) { illegal_1(z80); op_0b(z80); } /* DB DD */
+OP(dd,0c) { illegal_1(z80); op_0c(z80); } /* DB DD */
+OP(dd,0d) { illegal_1(z80); op_0d(z80); } /* DB DD */
+OP(dd,0e) { illegal_1(z80); op_0e(z80); } /* DB DD */
+OP(dd,0f) { illegal_1(z80); op_0f(z80); } /* DB DD */
+
+OP(dd,10) { illegal_1(z80); op_10(z80); } /* DB DD */
+OP(dd,11) { illegal_1(z80); op_11(z80); } /* DB DD */
+OP(dd,12) { illegal_1(z80); op_12(z80); } /* DB DD */
+OP(dd,13) { illegal_1(z80); op_13(z80); } /* DB DD */
+OP(dd,14) { illegal_1(z80); op_14(z80); } /* DB DD */
+OP(dd,15) { illegal_1(z80); op_15(z80); } /* DB DD */
+OP(dd,16) { illegal_1(z80); op_16(z80); } /* DB DD */
+OP(dd,17) { illegal_1(z80); op_17(z80); } /* DB DD */
+
+OP(dd,18) { illegal_1(z80); op_18(z80); } /* DB DD */
+OP(dd,19) { ADD16(z80, ix, de); } /* ADD IX,DE */
+OP(dd,1a) { illegal_1(z80); op_1a(z80); } /* DB DD */
+OP(dd,1b) { illegal_1(z80); op_1b(z80); } /* DB DD */
+OP(dd,1c) { illegal_1(z80); op_1c(z80); } /* DB DD */
+OP(dd,1d) { illegal_1(z80); op_1d(z80); } /* DB DD */
+OP(dd,1e) { illegal_1(z80); op_1e(z80); } /* DB DD */
+OP(dd,1f) { illegal_1(z80); op_1f(z80); } /* DB DD */
+
+OP(dd,20) { illegal_1(z80); op_20(z80); } /* DB DD */
+OP(dd,21) { z80->IX = ARG16(z80); } /* LD IX,w */
+OP(dd,22) { z80->ea = ARG16(z80); WM16(z80, z80->ea, &z80->ix); z80->WZ = z80->ea+1;} /* LD (w),IX */
+OP(dd,23) { z80->IX++; } /* INC IX */
+OP(dd,24) { z80->HX = INC(z80, z80->HX); } /* INC HX */
+OP(dd,25) { z80->HX = DEC(z80, z80->HX); } /* DEC HX */
+OP(dd,26) { z80->HX = ARG(z80); } /* LD HX,n */
+OP(dd,27) { illegal_1(z80); op_27(z80); } /* DB DD */
+
+OP(dd,28) { illegal_1(z80); op_28(z80); } /* DB DD */
+OP(dd,29) { ADD16(z80, ix, ix); } /* ADD IX,IX */
+OP(dd,2a) { z80->ea = ARG16(z80); RM16(z80, z80->ea, &z80->ix); z80->WZ = z80->ea+1;} /* LD IX,(w) */
+OP(dd,2b) { z80->IX--; } /* DEC IX */
+OP(dd,2c) { z80->LX = INC(z80, z80->LX); } /* INC LX */
+OP(dd,2d) { z80->LX = DEC(z80, z80->LX); } /* DEC LX */
+OP(dd,2e) { z80->LX = ARG(z80); } /* LD LX,n */
+OP(dd,2f) { illegal_1(z80); op_2f(z80); } /* DB DD */
+
+OP(dd,30) { illegal_1(z80); op_30(z80); } /* DB DD */
+OP(dd,31) { illegal_1(z80); op_31(z80); } /* DB DD */
+OP(dd,32) { illegal_1(z80); op_32(z80); } /* DB DD */
+OP(dd,33) { illegal_1(z80); op_33(z80); } /* DB DD */
+OP(dd,34) { EAX(z80); WM(z80, z80->ea, INC(z80, RM(z80, z80->ea))); } /* INC (IX+o) */
+OP(dd,35) { EAX(z80); WM(z80, z80->ea, DEC(z80, RM(z80, z80->ea))); } /* DEC (IX+o) */
+OP(dd,36) { EAX(z80); WM(z80, z80->ea, ARG(z80)); } /* LD (IX+o),n */
+OP(dd,37) { illegal_1(z80); op_37(z80); } /* DB DD */
+
+OP(dd,38) { illegal_1(z80); op_38(z80); } /* DB DD */
+OP(dd,39) { ADD16(z80, ix, sp); } /* ADD IX,SP */
+OP(dd,3a) { illegal_1(z80); op_3a(z80); } /* DB DD */
+OP(dd,3b) { illegal_1(z80); op_3b(z80); } /* DB DD */
+OP(dd,3c) { illegal_1(z80); op_3c(z80); } /* DB DD */
+OP(dd,3d) { illegal_1(z80); op_3d(z80); } /* DB DD */
+OP(dd,3e) { illegal_1(z80); op_3e(z80); } /* DB DD */
+OP(dd,3f) { illegal_1(z80); op_3f(z80); } /* DB DD */
+
+OP(dd,40) { illegal_1(z80); op_40(z80); } /* DB DD */
+OP(dd,41) { illegal_1(z80); op_41(z80); } /* DB DD */
+OP(dd,42) { illegal_1(z80); op_42(z80); } /* DB DD */
+OP(dd,43) { illegal_1(z80); op_43(z80); } /* DB DD */
+OP(dd,44) { z80->B = z80->HX; } /* LD B,HX */
+OP(dd,45) { z80->B = z80->LX; } /* LD B,LX */
+OP(dd,46) { EAX(z80); z80->B = RM(z80, z80->ea); } /* LD B,(IX+o) */
+OP(dd,47) { illegal_1(z80); op_47(z80); } /* DB DD */
+
+OP(dd,48) { illegal_1(z80); op_48(z80); } /* DB DD */
+OP(dd,49) { illegal_1(z80); op_49(z80); } /* DB DD */
+OP(dd,4a) { illegal_1(z80); op_4a(z80); } /* DB DD */
+OP(dd,4b) { illegal_1(z80); op_4b(z80); } /* DB DD */
+OP(dd,4c) { z80->C = z80->HX; } /* LD C,HX */
+OP(dd,4d) { z80->C = z80->LX; } /* LD C,LX */
+OP(dd,4e) { EAX(z80); z80->C = RM(z80, z80->ea); } /* LD C,(IX+o) */
+OP(dd,4f) { illegal_1(z80); op_4f(z80); } /* DB DD */
+
+OP(dd,50) { illegal_1(z80); op_50(z80); } /* DB DD */
+OP(dd,51) { illegal_1(z80); op_51(z80); } /* DB DD */
+OP(dd,52) { illegal_1(z80); op_52(z80); } /* DB DD */
+OP(dd,53) { illegal_1(z80); op_53(z80); } /* DB DD */
+OP(dd,54) { z80->D = z80->HX; } /* LD D,HX */
+OP(dd,55) { z80->D = z80->LX; } /* LD D,LX */
+OP(dd,56) { EAX(z80); z80->D = RM(z80, z80->ea); } /* LD D,(IX+o) */
+OP(dd,57) { illegal_1(z80); op_57(z80); } /* DB DD */
+
+OP(dd,58) { illegal_1(z80); op_58(z80); } /* DB DD */
+OP(dd,59) { illegal_1(z80); op_59(z80); } /* DB DD */
+OP(dd,5a) { illegal_1(z80); op_5a(z80); } /* DB DD */
+OP(dd,5b) { illegal_1(z80); op_5b(z80); } /* DB DD */
+OP(dd,5c) { z80->E = z80->HX; } /* LD E,HX */
+OP(dd,5d) { z80->E = z80->LX; } /* LD E,LX */
+OP(dd,5e) { EAX(z80); z80->E = RM(z80, z80->ea); } /* LD E,(IX+o) */
+OP(dd,5f) { illegal_1(z80); op_5f(z80); } /* DB DD */
+
+OP(dd,60) { z80->HX = z80->B; } /* LD HX,B */
+OP(dd,61) { z80->HX = z80->C; } /* LD HX,C */
+OP(dd,62) { z80->HX = z80->D; } /* LD HX,D */
+OP(dd,63) { z80->HX = z80->E; } /* LD HX,E */
+OP(dd,64) { } /* LD HX,HX */
+OP(dd,65) { z80->HX = z80->LX; } /* LD HX,LX */
+OP(dd,66) { EAX(z80); z80->H = RM(z80, z80->ea); } /* LD H,(IX+o) */
+OP(dd,67) { z80->HX = z80->A; } /* LD HX,A */
+
+OP(dd,68) { z80->LX = z80->B; } /* LD LX,B */
+OP(dd,69) { z80->LX = z80->C; } /* LD LX,C */
+OP(dd,6a) { z80->LX = z80->D; } /* LD LX,D */
+OP(dd,6b) { z80->LX = z80->E; } /* LD LX,E */
+OP(dd,6c) { z80->LX = z80->HX; } /* LD LX,HX */
+OP(dd,6d) { } /* LD LX,LX */
+OP(dd,6e) { EAX(z80); z80->L = RM(z80, z80->ea); } /* LD L,(IX+o) */
+OP(dd,6f) { z80->LX = z80->A; } /* LD LX,A */
+
+OP(dd,70) { EAX(z80); WM(z80, z80->ea, z80->B); } /* LD (IX+o),B */
+OP(dd,71) { EAX(z80); WM(z80, z80->ea, z80->C); } /* LD (IX+o),C */
+OP(dd,72) { EAX(z80); WM(z80, z80->ea, z80->D); } /* LD (IX+o),D */
+OP(dd,73) { EAX(z80); WM(z80, z80->ea, z80->E); } /* LD (IX+o),E */
+OP(dd,74) { EAX(z80); WM(z80, z80->ea, z80->H); } /* LD (IX+o),H */
+OP(dd,75) { EAX(z80); WM(z80, z80->ea, z80->L); } /* LD (IX+o),L */
+OP(dd,76) { illegal_1(z80); op_76(z80); } /* DB DD */
+OP(dd,77) { EAX(z80); WM(z80, z80->ea, z80->A); } /* LD (IX+o),A */
+
+OP(dd,78) { illegal_1(z80); op_78(z80); } /* DB DD */
+OP(dd,79) { illegal_1(z80); op_79(z80); } /* DB DD */
+OP(dd,7a) { illegal_1(z80); op_7a(z80); } /* DB DD */
+OP(dd,7b) { illegal_1(z80); op_7b(z80); } /* DB DD */
+OP(dd,7c) { z80->A = z80->HX; } /* LD A,HX */
+OP(dd,7d) { z80->A = z80->LX; } /* LD A,LX */
+OP(dd,7e) { EAX(z80); z80->A = RM(z80, z80->ea); } /* LD A,(IX+o) */
+OP(dd,7f) { illegal_1(z80); op_7f(z80); } /* DB DD */
+
+OP(dd,80) { illegal_1(z80); op_80(z80); } /* DB DD */
+OP(dd,81) { illegal_1(z80); op_81(z80); } /* DB DD */
+OP(dd,82) { illegal_1(z80); op_82(z80); } /* DB DD */
+OP(dd,83) { illegal_1(z80); op_83(z80); } /* DB DD */
+OP(dd,84) { ADD(z80, z80->HX); } /* ADD A,HX */
+OP(dd,85) { ADD(z80, z80->LX); } /* ADD A,LX */
+OP(dd,86) { EAX(z80); ADD(z80, RM(z80, z80->ea)); } /* ADD A,(IX+o) */
+OP(dd,87) { illegal_1(z80); op_87(z80); } /* DB DD */
+
+OP(dd,88) { illegal_1(z80); op_88(z80); } /* DB DD */
+OP(dd,89) { illegal_1(z80); op_89(z80); } /* DB DD */
+OP(dd,8a) { illegal_1(z80); op_8a(z80); } /* DB DD */
+OP(dd,8b) { illegal_1(z80); op_8b(z80); } /* DB DD */
+OP(dd,8c) { ADC(z80, z80->HX); } /* ADC A,HX */
+OP(dd,8d) { ADC(z80, z80->LX); } /* ADC A,LX */
+OP(dd,8e) { EAX(z80); ADC(z80, RM(z80, z80->ea)); } /* ADC A,(IX+o) */
+OP(dd,8f) { illegal_1(z80); op_8f(z80); } /* DB DD */
+
+OP(dd,90) { illegal_1(z80); op_90(z80); } /* DB DD */
+OP(dd,91) { illegal_1(z80); op_91(z80); } /* DB DD */
+OP(dd,92) { illegal_1(z80); op_92(z80); } /* DB DD */
+OP(dd,93) { illegal_1(z80); op_93(z80); } /* DB DD */
+OP(dd,94) { SUB(z80, z80->HX); } /* SUB HX */
+OP(dd,95) { SUB(z80, z80->LX); } /* SUB LX */
+OP(dd,96) { EAX(z80); SUB(z80, RM(z80, z80->ea)); } /* SUB (IX+o) */
+OP(dd,97) { illegal_1(z80); op_97(z80); } /* DB DD */
+
+OP(dd,98) { illegal_1(z80); op_98(z80); } /* DB DD */
+OP(dd,99) { illegal_1(z80); op_99(z80); } /* DB DD */
+OP(dd,9a) { illegal_1(z80); op_9a(z80); } /* DB DD */
+OP(dd,9b) { illegal_1(z80); op_9b(z80); } /* DB DD */
+OP(dd,9c) { SBC(z80, z80->HX); } /* SBC A,HX */
+OP(dd,9d) { SBC(z80, z80->LX); } /* SBC A,LX */
+OP(dd,9e) { EAX(z80); SBC(z80, RM(z80, z80->ea)); } /* SBC A,(IX+o) */
+OP(dd,9f) { illegal_1(z80); op_9f(z80); } /* DB DD */
+
+OP(dd,a0) { illegal_1(z80); op_a0(z80); } /* DB DD */
+OP(dd,a1) { illegal_1(z80); op_a1(z80); } /* DB DD */
+OP(dd,a2) { illegal_1(z80); op_a2(z80); } /* DB DD */
+OP(dd,a3) { illegal_1(z80); op_a3(z80); } /* DB DD */
+OP(dd,a4) { AND(z80, z80->HX); } /* AND HX */
+OP(dd,a5) { AND(z80, z80->LX); } /* AND LX */
+OP(dd,a6) { EAX(z80); AND(z80, RM(z80, z80->ea)); } /* AND (IX+o) */
+OP(dd,a7) { illegal_1(z80); op_a7(z80); } /* DB DD */
+
+OP(dd,a8) { illegal_1(z80); op_a8(z80); } /* DB DD */
+OP(dd,a9) { illegal_1(z80); op_a9(z80); } /* DB DD */
+OP(dd,aa) { illegal_1(z80); op_aa(z80); } /* DB DD */
+OP(dd,ab) { illegal_1(z80); op_ab(z80); } /* DB DD */
+OP(dd,ac) { XOR(z80, z80->HX); } /* XOR HX */
+OP(dd,ad) { XOR(z80, z80->LX); } /* XOR LX */
+OP(dd,ae) { EAX(z80); XOR(z80, RM(z80, z80->ea)); } /* XOR (IX+o) */
+OP(dd,af) { illegal_1(z80); op_af(z80); } /* DB DD */
+
+OP(dd,b0) { illegal_1(z80); op_b0(z80); } /* DB DD */
+OP(dd,b1) { illegal_1(z80); op_b1(z80); } /* DB DD */
+OP(dd,b2) { illegal_1(z80); op_b2(z80); } /* DB DD */
+OP(dd,b3) { illegal_1(z80); op_b3(z80); } /* DB DD */
+OP(dd,b4) { OR(z80, z80->HX); } /* OR HX */
+OP(dd,b5) { OR(z80, z80->LX); } /* OR LX */
+OP(dd,b6) { EAX(z80); OR(z80, RM(z80, z80->ea)); } /* OR (IX+o) */
+OP(dd,b7) { illegal_1(z80); op_b7(z80); } /* DB DD */
+
+OP(dd,b8) { illegal_1(z80); op_b8(z80); } /* DB DD */
+OP(dd,b9) { illegal_1(z80); op_b9(z80); } /* DB DD */
+OP(dd,ba) { illegal_1(z80); op_ba(z80); } /* DB DD */
+OP(dd,bb) { illegal_1(z80); op_bb(z80); } /* DB DD */
+OP(dd,bc) { CP(z80, z80->HX); } /* CP HX */
+OP(dd,bd) { CP(z80, z80->LX); } /* CP LX */
+OP(dd,be) { EAX(z80); CP(z80, RM(z80, z80->ea)); } /* CP (IX+o) */
+OP(dd,bf) { illegal_1(z80); op_bf(z80); } /* DB DD */
+
+OP(dd,c0) { illegal_1(z80); op_c0(z80); } /* DB DD */
+OP(dd,c1) { illegal_1(z80); op_c1(z80); } /* DB DD */
+OP(dd,c2) { illegal_1(z80); op_c2(z80); } /* DB DD */
+OP(dd,c3) { illegal_1(z80); op_c3(z80); } /* DB DD */
+OP(dd,c4) { illegal_1(z80); op_c4(z80); } /* DB DD */
+OP(dd,c5) { illegal_1(z80); op_c5(z80); } /* DB DD */
+OP(dd,c6) { illegal_1(z80); op_c6(z80); } /* DB DD */
+OP(dd,c7) { illegal_1(z80); op_c7(z80); } /* DB DD */
+
+OP(dd,c8) { illegal_1(z80); op_c8(z80); } /* DB DD */
+OP(dd,c9) { illegal_1(z80); op_c9(z80); } /* DB DD */
+OP(dd,ca) { illegal_1(z80); op_ca(z80); } /* DB DD */
+OP(dd,cb) { EAX(z80); EXEC(z80,xycb,ARG(z80)); } /* ** DD CB xx */
+OP(dd,cc) { illegal_1(z80); op_cc(z80); } /* DB DD */
+OP(dd,cd) { illegal_1(z80); op_cd(z80); } /* DB DD */
+OP(dd,ce) { illegal_1(z80); op_ce(z80); } /* DB DD */
+OP(dd,cf) { illegal_1(z80); op_cf(z80); } /* DB DD */
+
+OP(dd,d0) { illegal_1(z80); op_d0(z80); } /* DB DD */
+OP(dd,d1) { illegal_1(z80); op_d1(z80); } /* DB DD */
+OP(dd,d2) { illegal_1(z80); op_d2(z80); } /* DB DD */
+OP(dd,d3) { illegal_1(z80); op_d3(z80); } /* DB DD */
+OP(dd,d4) { illegal_1(z80); op_d4(z80); } /* DB DD */
+OP(dd,d5) { illegal_1(z80); op_d5(z80); } /* DB DD */
+OP(dd,d6) { illegal_1(z80); op_d6(z80); } /* DB DD */
+OP(dd,d7) { illegal_1(z80); op_d7(z80); } /* DB DD */
+
+OP(dd,d8) { illegal_1(z80); op_d8(z80); } /* DB DD */
+OP(dd,d9) { illegal_1(z80); op_d9(z80); } /* DB DD */
+OP(dd,da) { illegal_1(z80); op_da(z80); } /* DB DD */
+OP(dd,db) { illegal_1(z80); op_db(z80); } /* DB DD */
+OP(dd,dc) { illegal_1(z80); op_dc(z80); } /* DB DD */
+OP(dd,dd) { illegal_1(z80); op_dd(z80); } /* DB DD */
+OP(dd,de) { illegal_1(z80); op_de(z80); } /* DB DD */
+OP(dd,df) { illegal_1(z80); op_df(z80); } /* DB DD */
+
+OP(dd,e0) { illegal_1(z80); op_e0(z80); } /* DB DD */
+OP(dd,e1) { POP(z80, ix); } /* POP IX */
+OP(dd,e2) { illegal_1(z80); op_e2(z80); } /* DB DD */
+OP(dd,e3) { EXSP(z80, ix); } /* EX (SP),IX */
+OP(dd,e4) { illegal_1(z80); op_e4(z80); } /* DB DD */
+OP(dd,e5) { PUSH(z80, ix); } /* PUSH IX */
+OP(dd,e6) { illegal_1(z80); op_e6(z80); } /* DB DD */
+OP(dd,e7) { illegal_1(z80); op_e7(z80); } /* DB DD */
+
+OP(dd,e8) { illegal_1(z80); op_e8(z80); } /* DB DD */
+OP(dd,e9) { z80->PC = z80->IX; } /* JP (IX) */
+OP(dd,ea) { illegal_1(z80); op_ea(z80); } /* DB DD */
+OP(dd,eb) { illegal_1(z80); op_eb(z80); } /* DB DD */
+OP(dd,ec) { illegal_1(z80); op_ec(z80); } /* DB DD */
+OP(dd,ed) { illegal_1(z80); op_ed(z80); } /* DB DD */
+OP(dd,ee) { illegal_1(z80); op_ee(z80); } /* DB DD */
+OP(dd,ef) { illegal_1(z80); op_ef(z80); } /* DB DD */
+
+OP(dd,f0) { illegal_1(z80); op_f0(z80); } /* DB DD */
+OP(dd,f1) { illegal_1(z80); op_f1(z80); } /* DB DD */
+OP(dd,f2) { illegal_1(z80); op_f2(z80); } /* DB DD */
+OP(dd,f3) { illegal_1(z80); op_f3(z80); } /* DB DD */
+OP(dd,f4) { illegal_1(z80); op_f4(z80); } /* DB DD */
+OP(dd,f5) { illegal_1(z80); op_f5(z80); } /* DB DD */
+OP(dd,f6) { illegal_1(z80); op_f6(z80); } /* DB DD */
+OP(dd,f7) { illegal_1(z80); op_f7(z80); } /* DB DD */
+
+OP(dd,f8) { illegal_1(z80); op_f8(z80); } /* DB DD */
+OP(dd,f9) { z80->SP = z80->IX; } /* LD SP,IX */
+OP(dd,fa) { illegal_1(z80); op_fa(z80); } /* DB DD */
+OP(dd,fb) { illegal_1(z80); op_fb(z80); } /* DB DD */
+OP(dd,fc) { illegal_1(z80); op_fc(z80); } /* DB DD */
+OP(dd,fd) { illegal_1(z80); op_fd(z80); } /* DB DD */
+OP(dd,fe) { illegal_1(z80); op_fe(z80); } /* DB DD */
+OP(dd,ff) { illegal_1(z80); op_ff(z80); } /* DB DD */
+
+/**********************************************************
+ * IY register related opcodes (FD prefix)
+ **********************************************************/
+OP(fd,00) { illegal_1(z80); op_00(z80); } /* DB FD */
+OP(fd,01) { illegal_1(z80); op_01(z80); } /* DB FD */
+OP(fd,02) { illegal_1(z80); op_02(z80); } /* DB FD */
+OP(fd,03) { illegal_1(z80); op_03(z80); } /* DB FD */
+OP(fd,04) { illegal_1(z80); op_04(z80); } /* DB FD */
+OP(fd,05) { illegal_1(z80); op_05(z80); } /* DB FD */
+OP(fd,06) { illegal_1(z80); op_06(z80); } /* DB FD */
+OP(fd,07) { illegal_1(z80); op_07(z80); } /* DB FD */
+
+OP(fd,08) { illegal_1(z80); op_08(z80); } /* DB FD */
+OP(fd,09) { ADD16(z80, iy, bc); } /* ADD IY,BC */
+OP(fd,0a) { illegal_1(z80); op_0a(z80); } /* DB FD */
+OP(fd,0b) { illegal_1(z80); op_0b(z80); } /* DB FD */
+OP(fd,0c) { illegal_1(z80); op_0c(z80); } /* DB FD */
+OP(fd,0d) { illegal_1(z80); op_0d(z80); } /* DB FD */
+OP(fd,0e) { illegal_1(z80); op_0e(z80); } /* DB FD */
+OP(fd,0f) { illegal_1(z80); op_0f(z80); } /* DB FD */
+
+OP(fd,10) { illegal_1(z80); op_10(z80); } /* DB FD */
+OP(fd,11) { illegal_1(z80); op_11(z80); } /* DB FD */
+OP(fd,12) { illegal_1(z80); op_12(z80); } /* DB FD */
+OP(fd,13) { illegal_1(z80); op_13(z80); } /* DB FD */
+OP(fd,14) { illegal_1(z80); op_14(z80); } /* DB FD */
+OP(fd,15) { illegal_1(z80); op_15(z80); } /* DB FD */
+OP(fd,16) { illegal_1(z80); op_16(z80); } /* DB FD */
+OP(fd,17) { illegal_1(z80); op_17(z80); } /* DB FD */
+
+OP(fd,18) { illegal_1(z80); op_18(z80); } /* DB FD */
+OP(fd,19) { ADD16(z80, iy, de); } /* ADD IY,DE */
+OP(fd,1a) { illegal_1(z80); op_1a(z80); } /* DB FD */
+OP(fd,1b) { illegal_1(z80); op_1b(z80); } /* DB FD */
+OP(fd,1c) { illegal_1(z80); op_1c(z80); } /* DB FD */
+OP(fd,1d) { illegal_1(z80); op_1d(z80); } /* DB FD */
+OP(fd,1e) { illegal_1(z80); op_1e(z80); } /* DB FD */
+OP(fd,1f) { illegal_1(z80); op_1f(z80); } /* DB FD */
+
+OP(fd,20) { illegal_1(z80); op_20(z80); } /* DB FD */
+OP(fd,21) { z80->IY = ARG16(z80); } /* LD IY,w */
+OP(fd,22) { z80->ea = ARG16(z80); WM16(z80, z80->ea, &z80->iy); z80->WZ = z80->ea+1;} /* LD (w),IY */
+OP(fd,23) { z80->IY++; } /* INC IY */
+OP(fd,24) { z80->HY = INC(z80, z80->HY); } /* INC HY */
+OP(fd,25) { z80->HY = DEC(z80, z80->HY); } /* DEC HY */
+OP(fd,26) { z80->HY = ARG(z80); } /* LD HY,n */
+OP(fd,27) { illegal_1(z80); op_27(z80); } /* DB FD */
+
+OP(fd,28) { illegal_1(z80); op_28(z80); } /* DB FD */
+OP(fd,29) { ADD16(z80, iy, iy); } /* ADD IY,IY */
+OP(fd,2a) { z80->ea = ARG16(z80); RM16(z80, z80->ea, &z80->iy); z80->WZ = z80->ea+1;} /* LD IY,(w) */
+OP(fd,2b) { z80->IY--; } /* DEC IY */
+OP(fd,2c) { z80->LY = INC(z80, z80->LY); } /* INC LY */
+OP(fd,2d) { z80->LY = DEC(z80, z80->LY); } /* DEC LY */
+OP(fd,2e) { z80->LY = ARG(z80); } /* LD LY,n */
+OP(fd,2f) { illegal_1(z80); op_2f(z80); } /* DB FD */
+
+OP(fd,30) { illegal_1(z80); op_30(z80); } /* DB FD */
+OP(fd,31) { illegal_1(z80); op_31(z80); } /* DB FD */
+OP(fd,32) { illegal_1(z80); op_32(z80); } /* DB FD */
+OP(fd,33) { illegal_1(z80); op_33(z80); } /* DB FD */
+OP(fd,34) { EAY(z80); WM(z80, z80->ea, INC(z80, RM(z80, z80->ea))); } /* INC (IY+o) */
+OP(fd,35) { EAY(z80); WM(z80, z80->ea, DEC(z80, RM(z80, z80->ea))); } /* DEC (IY+o) */
+OP(fd,36) { EAY(z80); WM(z80, z80->ea, ARG(z80)); } /* LD (IY+o),n */
+OP(fd,37) { illegal_1(z80); op_37(z80); } /* DB FD */
+
+OP(fd,38) { illegal_1(z80); op_38(z80); } /* DB FD */
+OP(fd,39) { ADD16(z80, iy, sp); } /* ADD IY,SP */
+OP(fd,3a) { illegal_1(z80); op_3a(z80); } /* DB FD */
+OP(fd,3b) { illegal_1(z80); op_3b(z80); } /* DB FD */
+OP(fd,3c) { illegal_1(z80); op_3c(z80); } /* DB FD */
+OP(fd,3d) { illegal_1(z80); op_3d(z80); } /* DB FD */
+OP(fd,3e) { illegal_1(z80); op_3e(z80); } /* DB FD */
+OP(fd,3f) { illegal_1(z80); op_3f(z80); } /* DB FD */
+
+OP(fd,40) { illegal_1(z80); op_40(z80); } /* DB FD */
+OP(fd,41) { illegal_1(z80); op_41(z80); } /* DB FD */
+OP(fd,42) { illegal_1(z80); op_42(z80); } /* DB FD */
+OP(fd,43) { illegal_1(z80); op_43(z80); } /* DB FD */
+OP(fd,44) { z80->B = z80->HY; } /* LD B,HY */
+OP(fd,45) { z80->B = z80->LY; } /* LD B,LY */
+OP(fd,46) { EAY(z80); z80->B = RM(z80, z80->ea); } /* LD B,(IY+o) */
+OP(fd,47) { illegal_1(z80); op_47(z80); } /* DB FD */
+
+OP(fd,48) { illegal_1(z80); op_48(z80); } /* DB FD */
+OP(fd,49) { illegal_1(z80); op_49(z80); } /* DB FD */
+OP(fd,4a) { illegal_1(z80); op_4a(z80); } /* DB FD */
+OP(fd,4b) { illegal_1(z80); op_4b(z80); } /* DB FD */
+OP(fd,4c) { z80->C = z80->HY; } /* LD C,HY */
+OP(fd,4d) { z80->C = z80->LY; } /* LD C,LY */
+OP(fd,4e) { EAY(z80); z80->C = RM(z80, z80->ea); } /* LD C,(IY+o) */
+OP(fd,4f) { illegal_1(z80); op_4f(z80); } /* DB FD */
+
+OP(fd,50) { illegal_1(z80); op_50(z80); } /* DB FD */
+OP(fd,51) { illegal_1(z80); op_51(z80); } /* DB FD */
+OP(fd,52) { illegal_1(z80); op_52(z80); } /* DB FD */
+OP(fd,53) { illegal_1(z80); op_53(z80); } /* DB FD */
+OP(fd,54) { z80->D = z80->HY; } /* LD D,HY */
+OP(fd,55) { z80->D = z80->LY; } /* LD D,LY */
+OP(fd,56) { EAY(z80); z80->D = RM(z80, z80->ea); } /* LD D,(IY+o) */
+OP(fd,57) { illegal_1(z80); op_57(z80); } /* DB FD */
+
+OP(fd,58) { illegal_1(z80); op_58(z80); } /* DB FD */
+OP(fd,59) { illegal_1(z80); op_59(z80); } /* DB FD */
+OP(fd,5a) { illegal_1(z80); op_5a(z80); } /* DB FD */
+OP(fd,5b) { illegal_1(z80); op_5b(z80); } /* DB FD */
+OP(fd,5c) { z80->E = z80->HY; } /* LD E,HY */
+OP(fd,5d) { z80->E = z80->LY; } /* LD E,LY */
+OP(fd,5e) { EAY(z80); z80->E = RM(z80, z80->ea); } /* LD E,(IY+o) */
+OP(fd,5f) { illegal_1(z80); op_5f(z80); } /* DB FD */
+
+OP(fd,60) { z80->HY = z80->B; } /* LD HY,B */
+OP(fd,61) { z80->HY = z80->C; } /* LD HY,C */
+OP(fd,62) { z80->HY = z80->D; } /* LD HY,D */
+OP(fd,63) { z80->HY = z80->E; } /* LD HY,E */
+OP(fd,64) { } /* LD HY,HY */
+OP(fd,65) { z80->HY = z80->LY; } /* LD HY,LY */
+OP(fd,66) { EAY(z80); z80->H = RM(z80, z80->ea); } /* LD H,(IY+o) */
+OP(fd,67) { z80->HY = z80->A; } /* LD HY,A */
+
+OP(fd,68) { z80->LY = z80->B; } /* LD LY,B */
+OP(fd,69) { z80->LY = z80->C; } /* LD LY,C */
+OP(fd,6a) { z80->LY = z80->D; } /* LD LY,D */
+OP(fd,6b) { z80->LY = z80->E; } /* LD LY,E */
+OP(fd,6c) { z80->LY = z80->HY; } /* LD LY,HY */
+OP(fd,6d) { } /* LD LY,LY */
+OP(fd,6e) { EAY(z80); z80->L = RM(z80, z80->ea); } /* LD L,(IY+o) */
+OP(fd,6f) { z80->LY = z80->A; } /* LD LY,A */
+
+OP(fd,70) { EAY(z80); WM(z80, z80->ea, z80->B); } /* LD (IY+o),B */
+OP(fd,71) { EAY(z80); WM(z80, z80->ea, z80->C); } /* LD (IY+o),C */
+OP(fd,72) { EAY(z80); WM(z80, z80->ea, z80->D); } /* LD (IY+o),D */
+OP(fd,73) { EAY(z80); WM(z80, z80->ea, z80->E); } /* LD (IY+o),E */
+OP(fd,74) { EAY(z80); WM(z80, z80->ea, z80->H); } /* LD (IY+o),H */
+OP(fd,75) { EAY(z80); WM(z80, z80->ea, z80->L); } /* LD (IY+o),L */
+OP(fd,76) { illegal_1(z80); op_76(z80); } /* DB FD */
+OP(fd,77) { EAY(z80); WM(z80, z80->ea, z80->A); } /* LD (IY+o),A */
+
+OP(fd,78) { illegal_1(z80); op_78(z80); } /* DB FD */
+OP(fd,79) { illegal_1(z80); op_79(z80); } /* DB FD */
+OP(fd,7a) { illegal_1(z80); op_7a(z80); } /* DB FD */
+OP(fd,7b) { illegal_1(z80); op_7b(z80); } /* DB FD */
+OP(fd,7c) { z80->A = z80->HY; } /* LD A,HY */
+OP(fd,7d) { z80->A = z80->LY; } /* LD A,LY */
+OP(fd,7e) { EAY(z80); z80->A = RM(z80, z80->ea); } /* LD A,(IY+o) */
+OP(fd,7f) { illegal_1(z80); op_7f(z80); } /* DB FD */
+
+OP(fd,80) { illegal_1(z80); op_80(z80); } /* DB FD */
+OP(fd,81) { illegal_1(z80); op_81(z80); } /* DB FD */
+OP(fd,82) { illegal_1(z80); op_82(z80); } /* DB FD */
+OP(fd,83) { illegal_1(z80); op_83(z80); } /* DB FD */
+OP(fd,84) { ADD(z80, z80->HY); } /* ADD A,HY */
+OP(fd,85) { ADD(z80, z80->LY); } /* ADD A,LY */
+OP(fd,86) { EAY(z80); ADD(z80, RM(z80, z80->ea)); } /* ADD A,(IY+o) */
+OP(fd,87) { illegal_1(z80); op_87(z80); } /* DB FD */
+
+OP(fd,88) { illegal_1(z80); op_88(z80); } /* DB FD */
+OP(fd,89) { illegal_1(z80); op_89(z80); } /* DB FD */
+OP(fd,8a) { illegal_1(z80); op_8a(z80); } /* DB FD */
+OP(fd,8b) { illegal_1(z80); op_8b(z80); } /* DB FD */
+OP(fd,8c) { ADC(z80, z80->HY); } /* ADC A,HY */
+OP(fd,8d) { ADC(z80, z80->LY); } /* ADC A,LY */
+OP(fd,8e) { EAY(z80); ADC(z80, RM(z80, z80->ea)); } /* ADC A,(IY+o) */
+OP(fd,8f) { illegal_1(z80); op_8f(z80); } /* DB FD */
+
+OP(fd,90) { illegal_1(z80); op_90(z80); } /* DB FD */
+OP(fd,91) { illegal_1(z80); op_91(z80); } /* DB FD */
+OP(fd,92) { illegal_1(z80); op_92(z80); } /* DB FD */
+OP(fd,93) { illegal_1(z80); op_93(z80); } /* DB FD */
+OP(fd,94) { SUB(z80, z80->HY); } /* SUB HY */
+OP(fd,95) { SUB(z80, z80->LY); } /* SUB LY */
+OP(fd,96) { EAY(z80); SUB(z80, RM(z80, z80->ea)); } /* SUB (IY+o) */
+OP(fd,97) { illegal_1(z80); op_97(z80); } /* DB FD */
+
+OP(fd,98) { illegal_1(z80); op_98(z80); } /* DB FD */
+OP(fd,99) { illegal_1(z80); op_99(z80); } /* DB FD */
+OP(fd,9a) { illegal_1(z80); op_9a(z80); } /* DB FD */
+OP(fd,9b) { illegal_1(z80); op_9b(z80); } /* DB FD */
+OP(fd,9c) { SBC(z80, z80->HY); } /* SBC A,HY */
+OP(fd,9d) { SBC(z80, z80->LY); } /* SBC A,LY */
+OP(fd,9e) { EAY(z80); SBC(z80, RM(z80, z80->ea)); } /* SBC A,(IY+o) */
+OP(fd,9f) { illegal_1(z80); op_9f(z80); } /* DB FD */
+
+OP(fd,a0) { illegal_1(z80); op_a0(z80); } /* DB FD */
+OP(fd,a1) { illegal_1(z80); op_a1(z80); } /* DB FD */
+OP(fd,a2) { illegal_1(z80); op_a2(z80); } /* DB FD */
+OP(fd,a3) { illegal_1(z80); op_a3(z80); } /* DB FD */
+OP(fd,a4) { AND(z80, z80->HY); } /* AND HY */
+OP(fd,a5) { AND(z80, z80->LY); } /* AND LY */
+OP(fd,a6) { EAY(z80); AND(z80, RM(z80, z80->ea)); } /* AND (IY+o) */
+OP(fd,a7) { illegal_1(z80); op_a7(z80); } /* DB FD */
+
+OP(fd,a8) { illegal_1(z80); op_a8(z80); } /* DB FD */
+OP(fd,a9) { illegal_1(z80); op_a9(z80); } /* DB FD */
+OP(fd,aa) { illegal_1(z80); op_aa(z80); } /* DB FD */
+OP(fd,ab) { illegal_1(z80); op_ab(z80); } /* DB FD */
+OP(fd,ac) { XOR(z80, z80->HY); } /* XOR HY */
+OP(fd,ad) { XOR(z80, z80->LY); } /* XOR LY */
+OP(fd,ae) { EAY(z80); XOR(z80, RM(z80, z80->ea)); } /* XOR (IY+o) */
+OP(fd,af) { illegal_1(z80); op_af(z80); } /* DB FD */
+
+OP(fd,b0) { illegal_1(z80); op_b0(z80); } /* DB FD */
+OP(fd,b1) { illegal_1(z80); op_b1(z80); } /* DB FD */
+OP(fd,b2) { illegal_1(z80); op_b2(z80); } /* DB FD */
+OP(fd,b3) { illegal_1(z80); op_b3(z80); } /* DB FD */
+OP(fd,b4) { OR(z80, z80->HY); } /* OR HY */
+OP(fd,b5) { OR(z80, z80->LY); } /* OR LY */
+OP(fd,b6) { EAY(z80); OR(z80, RM(z80, z80->ea)); } /* OR (IY+o) */
+OP(fd,b7) { illegal_1(z80); op_b7(z80); } /* DB FD */
+
+OP(fd,b8) { illegal_1(z80); op_b8(z80); } /* DB FD */
+OP(fd,b9) { illegal_1(z80); op_b9(z80); } /* DB FD */
+OP(fd,ba) { illegal_1(z80); op_ba(z80); } /* DB FD */
+OP(fd,bb) { illegal_1(z80); op_bb(z80); } /* DB FD */
+OP(fd,bc) { CP(z80, z80->HY); } /* CP HY */
+OP(fd,bd) { CP(z80, z80->LY); } /* CP LY */
+OP(fd,be) { EAY(z80); CP(z80, RM(z80, z80->ea)); } /* CP (IY+o) */
+OP(fd,bf) { illegal_1(z80); op_bf(z80); } /* DB FD */
+
+OP(fd,c0) { illegal_1(z80); op_c0(z80); } /* DB FD */
+OP(fd,c1) { illegal_1(z80); op_c1(z80); } /* DB FD */
+OP(fd,c2) { illegal_1(z80); op_c2(z80); } /* DB FD */
+OP(fd,c3) { illegal_1(z80); op_c3(z80); } /* DB FD */
+OP(fd,c4) { illegal_1(z80); op_c4(z80); } /* DB FD */
+OP(fd,c5) { illegal_1(z80); op_c5(z80); } /* DB FD */
+OP(fd,c6) { illegal_1(z80); op_c6(z80); } /* DB FD */
+OP(fd,c7) { illegal_1(z80); op_c7(z80); } /* DB FD */
+
+OP(fd,c8) { illegal_1(z80); op_c8(z80); } /* DB FD */
+OP(fd,c9) { illegal_1(z80); op_c9(z80); } /* DB FD */
+OP(fd,ca) { illegal_1(z80); op_ca(z80); } /* DB FD */
+OP(fd,cb) { EAY(z80); EXEC(z80,xycb,ARG(z80)); } /* ** FD CB xx */
+OP(fd,cc) { illegal_1(z80); op_cc(z80); } /* DB FD */
+OP(fd,cd) { illegal_1(z80); op_cd(z80); } /* DB FD */
+OP(fd,ce) { illegal_1(z80); op_ce(z80); } /* DB FD */
+OP(fd,cf) { illegal_1(z80); op_cf(z80); } /* DB FD */
+
+OP(fd,d0) { illegal_1(z80); op_d0(z80); } /* DB FD */
+OP(fd,d1) { illegal_1(z80); op_d1(z80); } /* DB FD */
+OP(fd,d2) { illegal_1(z80); op_d2(z80); } /* DB FD */
+OP(fd,d3) { illegal_1(z80); op_d3(z80); } /* DB FD */
+OP(fd,d4) { illegal_1(z80); op_d4(z80); } /* DB FD */
+OP(fd,d5) { illegal_1(z80); op_d5(z80); } /* DB FD */
+OP(fd,d6) { illegal_1(z80); op_d6(z80); } /* DB FD */
+OP(fd,d7) { illegal_1(z80); op_d7(z80); } /* DB FD */
+
+OP(fd,d8) { illegal_1(z80); op_d8(z80); } /* DB FD */
+OP(fd,d9) { illegal_1(z80); op_d9(z80); } /* DB FD */
+OP(fd,da) { illegal_1(z80); op_da(z80); } /* DB FD */
+OP(fd,db) { illegal_1(z80); op_db(z80); } /* DB FD */
+OP(fd,dc) { illegal_1(z80); op_dc(z80); } /* DB FD */
+OP(fd,dd) { illegal_1(z80); op_dd(z80); } /* DB FD */
+OP(fd,de) { illegal_1(z80); op_de(z80); } /* DB FD */
+OP(fd,df) { illegal_1(z80); op_df(z80); } /* DB FD */
+
+OP(fd,e0) { illegal_1(z80); op_e0(z80); } /* DB FD */
+OP(fd,e1) { POP(z80, iy); } /* POP IY */
+OP(fd,e2) { illegal_1(z80); op_e2(z80); } /* DB FD */
+OP(fd,e3) { EXSP(z80, iy); } /* EX (SP),IY */
+OP(fd,e4) { illegal_1(z80); op_e4(z80); } /* DB FD */
+OP(fd,e5) { PUSH(z80, iy); } /* PUSH IY */
+OP(fd,e6) { illegal_1(z80); op_e6(z80); } /* DB FD */
+OP(fd,e7) { illegal_1(z80); op_e7(z80); } /* DB FD */
+
+OP(fd,e8) { illegal_1(z80); op_e8(z80); } /* DB FD */
+OP(fd,e9) { z80->PC = z80->IY; } /* JP (IY) */
+OP(fd,ea) { illegal_1(z80); op_ea(z80); } /* DB FD */
+OP(fd,eb) { illegal_1(z80); op_eb(z80); } /* DB FD */
+OP(fd,ec) { illegal_1(z80); op_ec(z80); } /* DB FD */
+OP(fd,ed) { illegal_1(z80); op_ed(z80); } /* DB FD */
+OP(fd,ee) { illegal_1(z80); op_ee(z80); } /* DB FD */
+OP(fd,ef) { illegal_1(z80); op_ef(z80); } /* DB FD */
+
+OP(fd,f0) { illegal_1(z80); op_f0(z80); } /* DB FD */
+OP(fd,f1) { illegal_1(z80); op_f1(z80); } /* DB FD */
+OP(fd,f2) { illegal_1(z80); op_f2(z80); } /* DB FD */
+OP(fd,f3) { illegal_1(z80); op_f3(z80); } /* DB FD */
+OP(fd,f4) { illegal_1(z80); op_f4(z80); } /* DB FD */
+OP(fd,f5) { illegal_1(z80); op_f5(z80); } /* DB FD */
+OP(fd,f6) { illegal_1(z80); op_f6(z80); } /* DB FD */
+OP(fd,f7) { illegal_1(z80); op_f7(z80); } /* DB FD */
+
+OP(fd,f8) { illegal_1(z80); op_f8(z80); } /* DB FD */
+OP(fd,f9) { z80->SP = z80->IY; } /* LD SP,IY */
+OP(fd,fa) { illegal_1(z80); op_fa(z80); } /* DB FD */
+OP(fd,fb) { illegal_1(z80); op_fb(z80); } /* DB FD */
+OP(fd,fc) { illegal_1(z80); op_fc(z80); } /* DB FD */
+OP(fd,fd) { illegal_1(z80); op_fd(z80); } /* DB FD */
+OP(fd,fe) { illegal_1(z80); op_fe(z80); } /* DB FD */
+OP(fd,ff) { illegal_1(z80); op_ff(z80); } /* DB FD */
+
+OP(illegal,2)
+{
+ logerror("Z80 '%s' ill. opcode $ed $%02x\n",
+ z80->device->tag(), z80->direct->read_decrypted_byte((z80->PCD-1)&0xffff));
+}
+
+/**********************************************************
+ * special opcodes (ED prefix)
+ **********************************************************/
+OP(ed,00) { illegal_2(z80); } /* DB ED */
+OP(ed,01) { illegal_2(z80); } /* DB ED */
+OP(ed,02) { illegal_2(z80); } /* DB ED */
+OP(ed,03) { illegal_2(z80); } /* DB ED */
+OP(ed,04) { illegal_2(z80); } /* DB ED */
+OP(ed,05) { illegal_2(z80); } /* DB ED */
+OP(ed,06) { illegal_2(z80); } /* DB ED */
+OP(ed,07) { illegal_2(z80); } /* DB ED */
+
+OP(ed,08) { illegal_2(z80); } /* DB ED */
+OP(ed,09) { illegal_2(z80); } /* DB ED */
+OP(ed,0a) { illegal_2(z80); } /* DB ED */
+OP(ed,0b) { illegal_2(z80); } /* DB ED */
+OP(ed,0c) { illegal_2(z80); } /* DB ED */
+OP(ed,0d) { illegal_2(z80); } /* DB ED */
+OP(ed,0e) { illegal_2(z80); } /* DB ED */
+OP(ed,0f) { illegal_2(z80); } /* DB ED */
+
+OP(ed,10) { illegal_2(z80); } /* DB ED */
+OP(ed,11) { illegal_2(z80); } /* DB ED */
+OP(ed,12) { illegal_2(z80); } /* DB ED */
+OP(ed,13) { illegal_2(z80); } /* DB ED */
+OP(ed,14) { illegal_2(z80); } /* DB ED */
+OP(ed,15) { illegal_2(z80); } /* DB ED */
+OP(ed,16) { illegal_2(z80); } /* DB ED */
+OP(ed,17) { illegal_2(z80); } /* DB ED */
+
+OP(ed,18) { illegal_2(z80); } /* DB ED */
+OP(ed,19) { illegal_2(z80); } /* DB ED */
+OP(ed,1a) { illegal_2(z80); } /* DB ED */
+OP(ed,1b) { illegal_2(z80); } /* DB ED */
+OP(ed,1c) { illegal_2(z80); } /* DB ED */
+OP(ed,1d) { illegal_2(z80); } /* DB ED */
+OP(ed,1e) { illegal_2(z80); } /* DB ED */
+OP(ed,1f) { illegal_2(z80); } /* DB ED */
+
+OP(ed,20) { illegal_2(z80); } /* DB ED */
+OP(ed,21) { illegal_2(z80); } /* DB ED */
+OP(ed,22) { illegal_2(z80); } /* DB ED */
+OP(ed,23) { illegal_2(z80); } /* DB ED */
+OP(ed,24) { illegal_2(z80); } /* DB ED */
+OP(ed,25) { illegal_2(z80); } /* DB ED */
+OP(ed,26) { illegal_2(z80); } /* DB ED */
+OP(ed,27) { illegal_2(z80); } /* DB ED */
+
+OP(ed,28) { illegal_2(z80); } /* DB ED */
+OP(ed,29) { illegal_2(z80); } /* DB ED */
+OP(ed,2a) { illegal_2(z80); } /* DB ED */
+OP(ed,2b) { illegal_2(z80); } /* DB ED */
+OP(ed,2c) { illegal_2(z80); } /* DB ED */
+OP(ed,2d) { illegal_2(z80); } /* DB ED */
+OP(ed,2e) { illegal_2(z80); } /* DB ED */
+OP(ed,2f) { illegal_2(z80); } /* DB ED */
+
+OP(ed,30) { illegal_2(z80); } /* DB ED */
+OP(ed,31) { illegal_2(z80); } /* DB ED */
+OP(ed,32) { illegal_2(z80); } /* DB ED */
+OP(ed,33) { illegal_2(z80); } /* DB ED */
+OP(ed,34) { illegal_2(z80); } /* DB ED */
+OP(ed,35) { illegal_2(z80); } /* DB ED */
+OP(ed,36) { illegal_2(z80); } /* DB ED */
+OP(ed,37) { illegal_2(z80); } /* DB ED */
+
+OP(ed,38) { illegal_2(z80); } /* DB ED */
+OP(ed,39) { illegal_2(z80); } /* DB ED */
+OP(ed,3a) { illegal_2(z80); } /* DB ED */
+OP(ed,3b) { illegal_2(z80); } /* DB ED */
+OP(ed,3c) { illegal_2(z80); } /* DB ED */
+OP(ed,3d) { illegal_2(z80); } /* DB ED */
+OP(ed,3e) { illegal_2(z80); } /* DB ED */
+OP(ed,3f) { illegal_2(z80); } /* DB ED */
+
+OP(ed,40) { z80->B = IN(z80, z80->BC); z80->F = (z80->F & CF) | SZP[z80->B]; } /* IN B,(C) */
+OP(ed,41) { OUT(z80, z80->BC, z80->B); } /* OUT (C),B */
+OP(ed,42) { SBC16(z80, bc); } /* SBC HL,BC */
+OP(ed,43) { z80->ea = ARG16(z80); WM16(z80, z80->ea, &z80->bc); z80->WZ = z80->ea+1;} /* LD (w),BC */
+OP(ed,44) { NEG(z80); } /* NEG */
+OP(ed,45) { RETN(z80); } /* RETN */
+OP(ed,46) { z80->im = 0; } /* im 0 */
+OP(ed,47) { LD_I_A(z80); } /* LD i,A */
+
+OP(ed,48) { z80->C = IN(z80, z80->BC); z80->F = (z80->F & CF) | SZP[z80->C]; } /* IN C,(C) */
+OP(ed,49) { OUT(z80, z80->BC, z80->C); } /* OUT (C),C */
+OP(ed,4a) { ADC16(z80, bc); } /* ADC HL,BC */
+OP(ed,4b) { z80->ea = ARG16(z80); RM16(z80, z80->ea, &z80->bc); z80->WZ = z80->ea+1;} /* LD BC,(w) */
+OP(ed,4c) { NEG(z80); } /* NEG */
+OP(ed,4d) { RETI(z80); } /* RETI */
+OP(ed,4e) { z80->im = 0; } /* im 0 */
+OP(ed,4f) { LD_R_A(z80); } /* LD r,A */
+
+OP(ed,50) { z80->D = IN(z80, z80->BC); z80->F = (z80->F & CF) | SZP[z80->D]; } /* IN D,(C) */
+OP(ed,51) { OUT(z80, z80->BC, z80->D); } /* OUT (C),D */
+OP(ed,52) { SBC16(z80, de); } /* SBC HL,DE */
+OP(ed,53) { z80->ea = ARG16(z80); WM16(z80, z80->ea, &z80->de); z80->WZ = z80->ea+1;} /* LD (w),DE */
+OP(ed,54) { NEG(z80); } /* NEG */
+OP(ed,55) { RETN(z80); } /* RETN */
+OP(ed,56) { z80->im = 1; } /* im 1 */
+OP(ed,57) { LD_A_I(z80); } /* LD A,i */
+
+OP(ed,58) { z80->E = IN(z80, z80->BC); z80->F = (z80->F & CF) | SZP[z80->E]; } /* IN E,(C) */
+OP(ed,59) { OUT(z80, z80->BC, z80->E); } /* OUT (C),E */
+OP(ed,5a) { ADC16(z80, de); } /* ADC HL,DE */
+OP(ed,5b) { z80->ea = ARG16(z80); RM16(z80, z80->ea, &z80->de); z80->WZ = z80->ea+1;} /* LD DE,(w) */
+OP(ed,5c) { NEG(z80); } /* NEG */
+OP(ed,5d) { RETI(z80); } /* RETI */
+OP(ed,5e) { z80->im = 2; } /* im 2 */
+OP(ed,5f) { LD_A_R(z80); } /* LD A,r */
+
+OP(ed,60) { z80->H = IN(z80, z80->BC); z80->F = (z80->F & CF) | SZP[z80->H]; } /* IN H,(C) */
+OP(ed,61) { OUT(z80, z80->BC, z80->H); } /* OUT (C),H */
+OP(ed,62) { SBC16(z80, hl); } /* SBC HL,HL */
+OP(ed,63) { z80->ea = ARG16(z80); WM16(z80, z80->ea, &z80->hl); z80->WZ = z80->ea+1;} /* LD (w),HL */
+OP(ed,64) { NEG(z80); } /* NEG */
+OP(ed,65) { RETN(z80); } /* RETN */
+OP(ed,66) { z80->im = 0; } /* im 0 */
+OP(ed,67) { RRD(z80); } /* RRD (HL) */
+
+OP(ed,68) { z80->L = IN(z80, z80->BC); z80->F = (z80->F & CF) | SZP[z80->L]; } /* IN L,(C) */
+OP(ed,69) { OUT(z80, z80->BC, z80->L); } /* OUT (C),L */
+OP(ed,6a) { ADC16(z80, hl); } /* ADC HL,HL */
+OP(ed,6b) { z80->ea = ARG16(z80); RM16(z80, z80->ea, &z80->hl); z80->WZ = z80->ea+1;} /* LD HL,(w) */
+OP(ed,6c) { NEG(z80); } /* NEG */
+OP(ed,6d) { RETI(z80); } /* RETI */
+OP(ed,6e) { z80->im = 0; } /* im 0 */
+OP(ed,6f) { RLD(z80); } /* RLD (HL) */
+
+OP(ed,70) { UINT8 res = IN(z80, z80->BC); z80->F = (z80->F & CF) | SZP[res]; } /* IN 0,(C) */
+OP(ed,71) { OUT(z80, z80->BC, 0); } /* OUT (C),0 */
+OP(ed,72) { SBC16(z80, sp); } /* SBC HL,SP */
+OP(ed,73) { z80->ea = ARG16(z80); WM16(z80, z80->ea, &z80->sp); z80->WZ = z80->ea+1;} /* LD (w),SP */
+OP(ed,74) { NEG(z80); } /* NEG */
+OP(ed,75) { RETN(z80); } /* RETN */
+OP(ed,76) { z80->im = 1; } /* im 1 */
+OP(ed,77) { illegal_2(z80); } /* DB ED,77 */
+
+OP(ed,78) { z80->A = IN(z80, z80->BC); z80->F = (z80->F & CF) | SZP[z80->A]; z80->WZ = z80->BC + 1; } /* IN A,(C) */
+OP(ed,79) { OUT(z80, z80->BC, z80->A); z80->WZ = z80->BC + 1; } /* OUT (C),A */
+OP(ed,7a) { ADC16(z80, sp); } /* ADC HL,SP */
+OP(ed,7b) { z80->ea = ARG16(z80); RM16(z80, z80->ea, &z80->sp); z80->WZ = z80->ea+1;} /* LD SP,(w) */
+OP(ed,7c) { NEG(z80); } /* NEG */
+OP(ed,7d) { RETI(z80); } /* RETI */
+OP(ed,7e) { z80->im = 2; } /* im 2 */
+OP(ed,7f) { illegal_2(z80); } /* DB ED,7F */
+
+OP(ed,80) { illegal_2(z80); } /* DB ED */
+OP(ed,81) { illegal_2(z80); } /* DB ED */
+OP(ed,82) { illegal_2(z80); } /* DB ED */
+OP(ed,83) { illegal_2(z80); } /* DB ED */
+OP(ed,84) { illegal_2(z80); } /* DB ED */
+OP(ed,85) { illegal_2(z80); } /* DB ED */
+OP(ed,86) { illegal_2(z80); } /* DB ED */
+OP(ed,87) { illegal_2(z80); } /* DB ED */
+
+OP(ed,88) { illegal_2(z80); } /* DB ED */
+OP(ed,89) { illegal_2(z80); } /* DB ED */
+OP(ed,8a) { illegal_2(z80); } /* DB ED */
+OP(ed,8b) { illegal_2(z80); } /* DB ED */
+OP(ed,8c) { illegal_2(z80); } /* DB ED */
+OP(ed,8d) { illegal_2(z80); } /* DB ED */
+OP(ed,8e) { illegal_2(z80); } /* DB ED */
+OP(ed,8f) { illegal_2(z80); } /* DB ED */
+
+OP(ed,90) { illegal_2(z80); } /* DB ED */
+OP(ed,91) { illegal_2(z80); } /* DB ED */
+OP(ed,92) { illegal_2(z80); } /* DB ED */
+OP(ed,93) { illegal_2(z80); } /* DB ED */
+OP(ed,94) { illegal_2(z80); } /* DB ED */
+OP(ed,95) { illegal_2(z80); } /* DB ED */
+OP(ed,96) { illegal_2(z80); } /* DB ED */
+OP(ed,97) { illegal_2(z80); } /* DB ED */
+
+OP(ed,98) { illegal_2(z80); } /* DB ED */
+OP(ed,99) { illegal_2(z80); } /* DB ED */
+OP(ed,9a) { illegal_2(z80); } /* DB ED */
+OP(ed,9b) { illegal_2(z80); } /* DB ED */
+OP(ed,9c) { illegal_2(z80); } /* DB ED */
+OP(ed,9d) { illegal_2(z80); } /* DB ED */
+OP(ed,9e) { illegal_2(z80); } /* DB ED */
+OP(ed,9f) { illegal_2(z80); } /* DB ED */
+
+OP(ed,a0) { LDI(z80); } /* LDI */
+OP(ed,a1) { CPI(z80); } /* CPI */
+OP(ed,a2) { INI(z80); } /* INI */
+OP(ed,a3) { OUTI(z80); } /* OUTI */
+OP(ed,a4) { illegal_2(z80); } /* DB ED */
+OP(ed,a5) { illegal_2(z80); } /* DB ED */
+OP(ed,a6) { illegal_2(z80); } /* DB ED */
+OP(ed,a7) { illegal_2(z80); } /* DB ED */
+
+OP(ed,a8) { LDD(z80); } /* LDD */
+OP(ed,a9) { CPD(z80); } /* CPD */
+OP(ed,aa) { IND(z80); } /* IND */
+OP(ed,ab) { OUTD(z80); } /* OUTD */
+OP(ed,ac) { illegal_2(z80); } /* DB ED */
+OP(ed,ad) { illegal_2(z80); } /* DB ED */
+OP(ed,ae) { illegal_2(z80); } /* DB ED */
+OP(ed,af) { illegal_2(z80); } /* DB ED */
+
+OP(ed,b0) { LDIR(z80); } /* LDIR */
+OP(ed,b1) { CPIR(z80); } /* CPIR */
+OP(ed,b2) { INIR(z80); } /* INIR */
+OP(ed,b3) { OTIR(z80); } /* OTIR */
+OP(ed,b4) { illegal_2(z80); } /* DB ED */
+OP(ed,b5) { illegal_2(z80); } /* DB ED */
+OP(ed,b6) { illegal_2(z80); } /* DB ED */
+OP(ed,b7) { illegal_2(z80); } /* DB ED */
+
+OP(ed,b8) { LDDR(z80); } /* LDDR */
+OP(ed,b9) { CPDR(z80); } /* CPDR */
+OP(ed,ba) { INDR(z80); } /* INDR */
+OP(ed,bb) { OTDR(z80); } /* OTDR */
+OP(ed,bc) { illegal_2(z80); } /* DB ED */
+OP(ed,bd) { illegal_2(z80); } /* DB ED */
+OP(ed,be) { illegal_2(z80); } /* DB ED */
+OP(ed,bf) { illegal_2(z80); } /* DB ED */
+
+OP(ed,c0) { illegal_2(z80); } /* DB ED */
+OP(ed,c1) { illegal_2(z80); } /* DB ED */
+OP(ed,c2) { illegal_2(z80); } /* DB ED */
+OP(ed,c3) { illegal_2(z80); } /* DB ED */
+OP(ed,c4) { illegal_2(z80); } /* DB ED */
+OP(ed,c5) { illegal_2(z80); } /* DB ED */
+OP(ed,c6) { illegal_2(z80); } /* DB ED */
+OP(ed,c7) { illegal_2(z80); } /* DB ED */
+
+OP(ed,c8) { illegal_2(z80); } /* DB ED */
+OP(ed,c9) { illegal_2(z80); } /* DB ED */
+OP(ed,ca) { illegal_2(z80); } /* DB ED */
+OP(ed,cb) { illegal_2(z80); } /* DB ED */
+OP(ed,cc) { illegal_2(z80); } /* DB ED */
+OP(ed,cd) { illegal_2(z80); } /* DB ED */
+OP(ed,ce) { illegal_2(z80); } /* DB ED */
+OP(ed,cf) { illegal_2(z80); } /* DB ED */
+
+OP(ed,d0) { illegal_2(z80); } /* DB ED */
+OP(ed,d1) { illegal_2(z80); } /* DB ED */
+OP(ed,d2) { illegal_2(z80); } /* DB ED */
+OP(ed,d3) { illegal_2(z80); } /* DB ED */
+OP(ed,d4) { illegal_2(z80); } /* DB ED */
+OP(ed,d5) { illegal_2(z80); } /* DB ED */
+OP(ed,d6) { illegal_2(z80); } /* DB ED */
+OP(ed,d7) { illegal_2(z80); } /* DB ED */
+
+OP(ed,d8) { illegal_2(z80); } /* DB ED */
+OP(ed,d9) { illegal_2(z80); } /* DB ED */
+OP(ed,da) { illegal_2(z80); } /* DB ED */
+OP(ed,db) { illegal_2(z80); } /* DB ED */
+OP(ed,dc) { illegal_2(z80); } /* DB ED */
+OP(ed,dd) { illegal_2(z80); } /* DB ED */
+OP(ed,de) { illegal_2(z80); } /* DB ED */
+OP(ed,df) { illegal_2(z80); } /* DB ED */
+
+OP(ed,e0) { illegal_2(z80); } /* DB ED */
+OP(ed,e1) { illegal_2(z80); } /* DB ED */
+OP(ed,e2) { illegal_2(z80); } /* DB ED */
+OP(ed,e3) { illegal_2(z80); } /* DB ED */
+OP(ed,e4) { illegal_2(z80); } /* DB ED */
+OP(ed,e5) { illegal_2(z80); } /* DB ED */
+OP(ed,e6) { illegal_2(z80); } /* DB ED */
+OP(ed,e7) { illegal_2(z80); } /* DB ED */
+
+OP(ed,e8) { illegal_2(z80); } /* DB ED */
+OP(ed,e9) { illegal_2(z80); } /* DB ED */
+OP(ed,ea) { illegal_2(z80); } /* DB ED */
+OP(ed,eb) { illegal_2(z80); } /* DB ED */
+OP(ed,ec) { illegal_2(z80); } /* DB ED */
+OP(ed,ed) { illegal_2(z80); } /* DB ED */
+OP(ed,ee) { illegal_2(z80); } /* DB ED */
+OP(ed,ef) { illegal_2(z80); } /* DB ED */
+
+OP(ed,f0) { illegal_2(z80); } /* DB ED */
+OP(ed,f1) { illegal_2(z80); } /* DB ED */
+OP(ed,f2) { illegal_2(z80); } /* DB ED */
+OP(ed,f3) { illegal_2(z80); } /* DB ED */
+OP(ed,f4) { illegal_2(z80); } /* DB ED */
+OP(ed,f5) { illegal_2(z80); } /* DB ED */
+OP(ed,f6) { illegal_2(z80); } /* DB ED */
+OP(ed,f7) { illegal_2(z80); } /* DB ED */
+
+OP(ed,f8) { illegal_2(z80); } /* DB ED */
+OP(ed,f9) { illegal_2(z80); } /* DB ED */
+OP(ed,fa) { illegal_2(z80); } /* DB ED */
+OP(ed,fb) { illegal_2(z80); } /* DB ED */
+OP(ed,fc) { illegal_2(z80); } /* DB ED */
+OP(ed,fd) { illegal_2(z80); } /* DB ED */
+OP(ed,fe) { illegal_2(z80); } /* DB ED */
+OP(ed,ff) { illegal_2(z80); } /* DB ED */
+
+
+/**********************************************************
+ * main opcodes
+ **********************************************************/
+OP(op,00) { } /* NOP */
+OP(op,01) { z80->BC = ARG16(z80); } /* LD BC,w */
+OP(op,02) { WM(z80,z80->BC,z80->A); z80->WZ_L = (z80->BC + 1) & 0xFF; z80->WZ_H = z80->A; } /* LD (BC),A */
+OP(op,03) { z80->BC++; } /* INC BC */
+OP(op,04) { z80->B = INC(z80, z80->B); } /* INC B */
+OP(op,05) { z80->B = DEC(z80, z80->B); } /* DEC B */
+OP(op,06) { z80->B = ARG(z80); } /* LD B,n */
+OP(op,07) { RLCA(z80); } /* RLCA */
+
+OP(op,08) { EX_AF(z80); } /* EX AF,AF' */
+OP(op,09) { ADD16(z80, hl, bc); } /* ADD HL,BC */
+OP(op,0a) { z80->A = RM(z80, z80->BC); z80->WZ=z80->BC+1; } /* LD A,(BC) */
+OP(op,0b) { z80->BC--; } /* DEC BC */
+OP(op,0c) { z80->C = INC(z80, z80->C); } /* INC C */
+OP(op,0d) { z80->C = DEC(z80, z80->C); } /* DEC C */
+OP(op,0e) { z80->C = ARG(z80); } /* LD C,n */
+OP(op,0f) { RRCA(z80); } /* RRCA */
+
+OP(op,10) { z80->B--; JR_COND(z80, z80->B, 0x10); } /* DJNZ o */
+OP(op,11) { z80->DE = ARG16(z80); } /* LD DE,w */
+OP(op,12) { WM(z80,z80->DE,z80->A); z80->WZ_L = (z80->DE + 1) & 0xFF; z80->WZ_H = z80->A; } /* LD (DE),A */
+OP(op,13) { z80->DE++; } /* INC DE */
+OP(op,14) { z80->D = INC(z80, z80->D); } /* INC D */
+OP(op,15) { z80->D = DEC(z80, z80->D); } /* DEC D */
+OP(op,16) { z80->D = ARG(z80); } /* LD D,n */
+OP(op,17) { RLA(z80); } /* RLA */
+
+OP(op,18) { JR(z80); } /* JR o */
+OP(op,19) { ADD16(z80, hl, de); } /* ADD HL,DE */
+OP(op,1a) { z80->A = RM(z80, z80->DE); z80->WZ=z80->DE+1; } /* LD A,(DE) */
+OP(op,1b) { z80->DE--; } /* DEC DE */
+OP(op,1c) { z80->E = INC(z80, z80->E); } /* INC E */
+OP(op,1d) { z80->E = DEC(z80, z80->E); } /* DEC E */
+OP(op,1e) { z80->E = ARG(z80); } /* LD E,n */
+OP(op,1f) { RRA(z80); } /* RRA */
+
+OP(op,20) { JR_COND(z80, !(z80->F & ZF), 0x20); } /* JR NZ,o */
+OP(op,21) { z80->HL = ARG16(z80); } /* LD HL,w */
+OP(op,22) { z80->ea = ARG16(z80); WM16(z80, z80->ea, &z80->hl); z80->WZ = z80->ea+1;} /* LD (w),HL */
+OP(op,23) { z80->HL++; } /* INC HL */
+OP(op,24) { z80->H = INC(z80, z80->H); } /* INC H */
+OP(op,25) { z80->H = DEC(z80, z80->H); } /* DEC H */
+OP(op,26) { z80->H = ARG(z80); } /* LD H,n */
+OP(op,27) { DAA(z80); } /* DAA */
+
+OP(op,28) { JR_COND(z80, z80->F & ZF, 0x28); } /* JR Z,o */
+OP(op,29) { ADD16(z80, hl, hl); } /* ADD HL,HL */
+OP(op,2a) { z80->ea = ARG16(z80); RM16(z80, z80->ea, &z80->hl); z80->WZ = z80->ea+1;} /* LD HL,(w) */
+OP(op,2b) { z80->HL--; } /* DEC HL */
+OP(op,2c) { z80->L = INC(z80, z80->L); } /* INC L */
+OP(op,2d) { z80->L = DEC(z80, z80->L); } /* DEC L */
+OP(op,2e) { z80->L = ARG(z80); } /* LD L,n */
+OP(op,2f) { z80->A ^= 0xff; z80->F = (z80->F&(SF|ZF|PF|CF))|HF|NF|(z80->A&(YF|XF)); } /* CPL */
+
+OP(op,30) { JR_COND(z80, !(z80->F & CF), 0x30); } /* JR NC,o */
+OP(op,31) { z80->SP = ARG16(z80); } /* LD SP,w */
+OP(op,32) { z80->ea=ARG16(z80);WM(z80,z80->ea,z80->A);z80->WZ_L=(z80->ea+1)&0xFF;z80->WZ_H=z80->A; } /* LD (w),A */
+OP(op,33) { z80->SP++; } /* INC SP */
+OP(op,34) { WM(z80, z80->HL, INC(z80, RM(z80, z80->HL))); } /* INC (HL) */
+OP(op,35) { WM(z80, z80->HL, DEC(z80, RM(z80, z80->HL))); } /* DEC (HL) */
+OP(op,36) { WM(z80, z80->HL, ARG(z80)); } /* LD (HL),n */
+OP(op,37) { z80->F = (z80->F & (SF|ZF|YF|XF|PF)) | CF | (z80->A & (YF|XF)); } /* SCF */
+
+OP(op,38) { JR_COND(z80, z80->F & CF, 0x38); } /* JR C,o */
+OP(op,39) { ADD16(z80, hl, sp); } /* ADD HL,SP */
+OP(op,3a) { z80->ea = ARG16(z80); z80->A = RM(z80, z80->ea); z80->WZ=z80->ea+1; } /* LD A,(w) */
+OP(op,3b) { z80->SP--; } /* DEC SP */
+OP(op,3c) { z80->A = INC(z80, z80->A); } /* INC A */
+OP(op,3d) { z80->A = DEC(z80, z80->A); } /* DEC A */
+OP(op,3e) { z80->A = ARG(z80); } /* LD A,n */
+OP(op,3f) { z80->F = ((z80->F&(SF|ZF|YF|XF|PF|CF))|((z80->F&CF)<<4)|(z80->A&(YF|XF)))^CF; } /* CCF */
+
+OP(op,40) { } /* LD B,B */
+OP(op,41) { z80->B = z80->C; } /* LD B,C */
+OP(op,42) { z80->B = z80->D; } /* LD B,D */
+OP(op,43) { z80->B = z80->E; } /* LD B,E */
+OP(op,44) { z80->B = z80->H; } /* LD B,H */
+OP(op,45) { z80->B = z80->L; } /* LD B,L */
+OP(op,46) { z80->B = RM(z80, z80->HL); } /* LD B,(HL) */
+OP(op,47) { z80->B = z80->A; } /* LD B,A */
+
+OP(op,48) { z80->C = z80->B; } /* LD C,B */
+OP(op,49) { } /* LD C,C */
+OP(op,4a) { z80->C = z80->D; } /* LD C,D */
+OP(op,4b) { z80->C = z80->E; } /* LD C,E */
+OP(op,4c) { z80->C = z80->H; } /* LD C,H */
+OP(op,4d) { z80->C = z80->L; } /* LD C,L */
+OP(op,4e) { z80->C = RM(z80, z80->HL); } /* LD C,(HL) */
+OP(op,4f) { z80->C = z80->A; } /* LD C,A */
+
+OP(op,50) { z80->D = z80->B; } /* LD D,B */
+OP(op,51) { z80->D = z80->C; } /* LD D,C */
+OP(op,52) { } /* LD D,D */
+OP(op,53) { z80->D = z80->E; } /* LD D,E */
+OP(op,54) { z80->D = z80->H; } /* LD D,H */
+OP(op,55) { z80->D = z80->L; } /* LD D,L */
+OP(op,56) { z80->D = RM(z80, z80->HL); } /* LD D,(HL) */
+OP(op,57) { z80->D = z80->A; } /* LD D,A */
+
+OP(op,58) { z80->E = z80->B; } /* LD E,B */
+OP(op,59) { z80->E = z80->C; } /* LD E,C */
+OP(op,5a) { z80->E = z80->D; } /* LD E,D */
+OP(op,5b) { } /* LD E,E */
+OP(op,5c) { z80->E = z80->H; } /* LD E,H */
+OP(op,5d) { z80->E = z80->L; } /* LD E,L */
+OP(op,5e) { z80->E = RM(z80, z80->HL); } /* LD E,(HL) */
+OP(op,5f) { z80->E = z80->A; } /* LD E,A */
+
+OP(op,60) { z80->H = z80->B; } /* LD H,B */
+OP(op,61) { z80->H = z80->C; } /* LD H,C */
+OP(op,62) { z80->H = z80->D; } /* LD H,D */
+OP(op,63) { z80->H = z80->E; } /* LD H,E */
+OP(op,64) { } /* LD H,H */
+OP(op,65) { z80->H = z80->L; } /* LD H,L */
+OP(op,66) { z80->H = RM(z80, z80->HL); } /* LD H,(HL) */
+OP(op,67) { z80->H = z80->A; } /* LD H,A */
+
+OP(op,68) { z80->L = z80->B; } /* LD L,B */
+OP(op,69) { z80->L = z80->C; } /* LD L,C */
+OP(op,6a) { z80->L = z80->D; } /* LD L,D */
+OP(op,6b) { z80->L = z80->E; } /* LD L,E */
+OP(op,6c) { z80->L = z80->H; } /* LD L,H */
+OP(op,6d) { } /* LD L,L */
+OP(op,6e) { z80->L = RM(z80, z80->HL); } /* LD L,(HL) */
+OP(op,6f) { z80->L = z80->A; } /* LD L,A */
+
+OP(op,70) { WM(z80, z80->HL, z80->B); } /* LD (HL),B */
+OP(op,71) { WM(z80, z80->HL, z80->C); } /* LD (HL),C */
+OP(op,72) { WM(z80, z80->HL, z80->D); } /* LD (HL),D */
+OP(op,73) { WM(z80, z80->HL, z80->E); } /* LD (HL),E */
+OP(op,74) { WM(z80, z80->HL, z80->H); } /* LD (HL),H */
+OP(op,75) { WM(z80, z80->HL, z80->L); } /* LD (HL),L */
+OP(op,76) { ENTER_HALT(z80); } /* halt */
+OP(op,77) { WM(z80, z80->HL, z80->A); } /* LD (HL),A */
+
+OP(op,78) { z80->A = z80->B; } /* LD A,B */
+OP(op,79) { z80->A = z80->C; } /* LD A,C */
+OP(op,7a) { z80->A = z80->D; } /* LD A,D */
+OP(op,7b) { z80->A = z80->E; } /* LD A,E */
+OP(op,7c) { z80->A = z80->H; } /* LD A,H */
+OP(op,7d) { z80->A = z80->L; } /* LD A,L */
+OP(op,7e) { z80->A = RM(z80, z80->HL); } /* LD A,(HL) */
+OP(op,7f) { } /* LD A,A */
+
+OP(op,80) { ADD(z80, z80->B); } /* ADD A,B */
+OP(op,81) { ADD(z80, z80->C); } /* ADD A,C */
+OP(op,82) { ADD(z80, z80->D); } /* ADD A,D */
+OP(op,83) { ADD(z80, z80->E); } /* ADD A,E */
+OP(op,84) { ADD(z80, z80->H); } /* ADD A,H */
+OP(op,85) { ADD(z80, z80->L); } /* ADD A,L */
+OP(op,86) { ADD(z80, RM(z80, z80->HL)); } /* ADD A,(HL) */
+OP(op,87) { ADD(z80, z80->A); } /* ADD A,A */
+
+OP(op,88) { ADC(z80, z80->B); } /* ADC A,B */
+OP(op,89) { ADC(z80, z80->C); } /* ADC A,C */
+OP(op,8a) { ADC(z80, z80->D); } /* ADC A,D */
+OP(op,8b) { ADC(z80, z80->E); } /* ADC A,E */
+OP(op,8c) { ADC(z80, z80->H); } /* ADC A,H */
+OP(op,8d) { ADC(z80, z80->L); } /* ADC A,L */
+OP(op,8e) { ADC(z80, RM(z80, z80->HL)); } /* ADC A,(HL) */
+OP(op,8f) { ADC(z80, z80->A); } /* ADC A,A */
+
+OP(op,90) { SUB(z80, z80->B); } /* SUB B */
+OP(op,91) { SUB(z80, z80->C); } /* SUB C */
+OP(op,92) { SUB(z80, z80->D); } /* SUB D */
+OP(op,93) { SUB(z80, z80->E); } /* SUB E */
+OP(op,94) { SUB(z80, z80->H); } /* SUB H */
+OP(op,95) { SUB(z80, z80->L); } /* SUB L */
+OP(op,96) { SUB(z80, RM(z80, z80->HL)); } /* SUB (HL) */
+OP(op,97) { SUB(z80, z80->A); } /* SUB A */
+
+OP(op,98) { SBC(z80, z80->B); } /* SBC A,B */
+OP(op,99) { SBC(z80, z80->C); } /* SBC A,C */
+OP(op,9a) { SBC(z80, z80->D); } /* SBC A,D */
+OP(op,9b) { SBC(z80, z80->E); } /* SBC A,E */
+OP(op,9c) { SBC(z80, z80->H); } /* SBC A,H */
+OP(op,9d) { SBC(z80, z80->L); } /* SBC A,L */
+OP(op,9e) { SBC(z80, RM(z80, z80->HL)); } /* SBC A,(HL) */
+OP(op,9f) { SBC(z80, z80->A); } /* SBC A,A */
+
+OP(op,a0) { AND(z80, z80->B); } /* AND B */
+OP(op,a1) { AND(z80, z80->C); } /* AND C */
+OP(op,a2) { AND(z80, z80->D); } /* AND D */
+OP(op,a3) { AND(z80, z80->E); } /* AND E */
+OP(op,a4) { AND(z80, z80->H); } /* AND H */
+OP(op,a5) { AND(z80, z80->L); } /* AND L */
+OP(op,a6) { AND(z80, RM(z80, z80->HL)); } /* AND (HL) */
+OP(op,a7) { AND(z80, z80->A); } /* AND A */
+
+OP(op,a8) { XOR(z80, z80->B); } /* XOR B */
+OP(op,a9) { XOR(z80, z80->C); } /* XOR C */
+OP(op,aa) { XOR(z80, z80->D); } /* XOR D */
+OP(op,ab) { XOR(z80, z80->E); } /* XOR E */
+OP(op,ac) { XOR(z80, z80->H); } /* XOR H */
+OP(op,ad) { XOR(z80, z80->L); } /* XOR L */
+OP(op,ae) { XOR(z80, RM(z80, z80->HL)); } /* XOR (HL) */
+OP(op,af) { XOR(z80, z80->A); } /* XOR A */
+
+OP(op,b0) { OR(z80, z80->B); } /* OR B */
+OP(op,b1) { OR(z80, z80->C); } /* OR C */
+OP(op,b2) { OR(z80, z80->D); } /* OR D */
+OP(op,b3) { OR(z80, z80->E); } /* OR E */
+OP(op,b4) { OR(z80, z80->H); } /* OR H */
+OP(op,b5) { OR(z80, z80->L); } /* OR L */
+OP(op,b6) { OR(z80, RM(z80, z80->HL)); } /* OR (HL) */
+OP(op,b7) { OR(z80, z80->A); } /* OR A */
+
+OP(op,b8) { CP(z80, z80->B); } /* CP B */
+OP(op,b9) { CP(z80, z80->C); } /* CP C */
+OP(op,ba) { CP(z80, z80->D); } /* CP D */
+OP(op,bb) { CP(z80, z80->E); } /* CP E */
+OP(op,bc) { CP(z80, z80->H); } /* CP H */
+OP(op,bd) { CP(z80, z80->L); } /* CP L */
+OP(op,be) { CP(z80, RM(z80, z80->HL)); } /* CP (HL) */
+OP(op,bf) { CP(z80, z80->A); } /* CP A */
+
+OP(op,c0) { RET_COND(z80, !(z80->F & ZF), 0xc0); } /* RET NZ */
+OP(op,c1) { POP(z80, bc); } /* POP BC */
+OP(op,c2) { JP_COND(z80, !(z80->F & ZF)); } /* JP NZ,a */
+OP(op,c3) { JP(z80); } /* JP a */
+OP(op,c4) { CALL_COND(z80, !(z80->F & ZF), 0xc4); } /* CALL NZ,a */
+OP(op,c5) { PUSH(z80, bc); } /* PUSH BC */
+OP(op,c6) { ADD(z80, ARG(z80)); } /* ADD A,n */
+OP(op,c7) { RST(z80, 0x00); } /* RST 0 */
+
+OP(op,c8) { RET_COND(z80, z80->F & ZF, 0xc8); } /* RET Z */
+OP(op,c9) { POP(z80, pc); z80->WZ=z80->PCD; } /* RET */
+OP(op,ca) { JP_COND(z80, z80->F & ZF); } /* JP Z,a */
+OP(op,cb) { z80->r++; EXEC(z80,cb,ROP(z80)); } /* **** CB xx */
+OP(op,cc) { CALL_COND(z80, z80->F & ZF, 0xcc); } /* CALL Z,a */
+OP(op,cd) { CALL(z80); } /* CALL a */
+OP(op,ce) { ADC(z80, ARG(z80)); } /* ADC A,n */
+OP(op,cf) { RST(z80, 0x08); } /* RST 1 */
+
+OP(op,d0) { RET_COND(z80, !(z80->F & CF), 0xd0); } /* RET NC */
+OP(op,d1) { POP(z80, de); } /* POP DE */
+OP(op,d2) { JP_COND(z80, !(z80->F & CF)); } /* JP NC,a */
+OP(op,d3) { unsigned n = ARG(z80) | (z80->A << 8); OUT(z80, n, z80->A); z80->WZ_L = ((n & 0xff) + 1) & 0xff; z80->WZ_H = z80->A; } /* OUT (n),A */
+OP(op,d4) { CALL_COND(z80, !(z80->F & CF), 0xd4); } /* CALL NC,a */
+OP(op,d5) { PUSH(z80, de); } /* PUSH DE */
+OP(op,d6) { SUB(z80, ARG(z80)); } /* SUB n */
+OP(op,d7) { RST(z80, 0x10); } /* RST 2 */
+
+OP(op,d8) { RET_COND(z80, z80->F & CF, 0xd8); } /* RET C */
+OP(op,d9) { EXX(z80); } /* EXX */
+OP(op,da) { JP_COND(z80, z80->F & CF); } /* JP C,a */
+OP(op,db) { unsigned n = ARG(z80) | (z80->A << 8); z80->A = IN(z80, n); z80->WZ = n + 1; } /* IN A,(n) */
+OP(op,dc) { CALL_COND(z80, z80->F & CF, 0xdc); } /* CALL C,a */
+OP(op,dd) { z80->r++; EXEC(z80,dd,ROP(z80)); } /* **** DD xx */
+OP(op,de) { SBC(z80, ARG(z80)); } /* SBC A,n */
+OP(op,df) { RST(z80, 0x18); } /* RST 3 */
+
+OP(op,e0) { RET_COND(z80, !(z80->F & PF), 0xe0); } /* RET PO */
+OP(op,e1) { POP(z80, hl); } /* POP HL */
+OP(op,e2) { JP_COND(z80, !(z80->F & PF)); } /* JP PO,a */
+OP(op,e3) { EXSP(z80, hl); } /* EX HL,(SP) */
+OP(op,e4) { CALL_COND(z80, !(z80->F & PF), 0xe4); } /* CALL PO,a */
+OP(op,e5) { PUSH(z80, hl); } /* PUSH HL */
+OP(op,e6) { AND(z80, ARG(z80)); } /* AND n */
+OP(op,e7) { RST(z80, 0x20); } /* RST 4 */
+
+OP(op,e8) { RET_COND(z80, z80->F & PF, 0xe8); } /* RET PE */
+OP(op,e9) { z80->PC = z80->HL; } /* JP (HL) */
+OP(op,ea) { JP_COND(z80, z80->F & PF); } /* JP PE,a */
+OP(op,eb) { EX_DE_HL(z80); } /* EX DE,HL */
+OP(op,ec) { CALL_COND(z80, z80->F & PF, 0xec); } /* CALL PE,a */
+OP(op,ed) { z80->r++; EXEC(z80,ed,ROP(z80)); } /* **** ED xx */
+OP(op,ee) { XOR(z80, ARG(z80)); } /* XOR n */
+OP(op,ef) { RST(z80, 0x28); } /* RST 5 */
+
+OP(op,f0) { RET_COND(z80, !(z80->F & SF), 0xf0); } /* RET P */
+OP(op,f1) { POP(z80, af); } /* POP AF */
+OP(op,f2) { JP_COND(z80, !(z80->F & SF)); } /* JP P,a */
+OP(op,f3) { z80->iff1 = z80->iff2 = 0; } /* DI */
+OP(op,f4) { CALL_COND(z80, !(z80->F & SF), 0xf4); } /* CALL P,a */
+OP(op,f5) { PUSH(z80, af); } /* PUSH AF */
+OP(op,f6) { OR(z80, ARG(z80)); } /* OR n */
+OP(op,f7) { RST(z80, 0x30); } /* RST 6 */
+
+OP(op,f8) { RET_COND(z80, z80->F & SF, 0xf8); } /* RET M */
+OP(op,f9) { z80->SP = z80->HL; } /* LD SP,HL */
+OP(op,fa) { JP_COND(z80, z80->F & SF); } /* JP M,a */
+OP(op,fb) { EI(z80); } /* EI */
+OP(op,fc) { CALL_COND(z80, z80->F & SF, 0xfc); } /* CALL M,a */
+OP(op,fd) { z80->r++; EXEC(z80,fd,ROP(z80)); } /* **** FD xx */
+OP(op,fe) { CP(z80, ARG(z80)); } /* CP n */
+OP(op,ff) { RST(z80, 0x38); } /* RST 7 */
+
+
+static void take_interrupt(z80_state *z80)
+{
+ int irq_vector;
+
+ /* there isn't a valid previous program counter */
+ z80->PRVPC = -1;
+
+ /* Check if processor was halted */
+ LEAVE_HALT(z80);
+
+ /* Clear both interrupt flip flops */
+ z80->iff1 = z80->iff2 = 0;
+
+ /* Daisy chain mode? If so, call the requesting device */
+ if (z80->daisy.present())
+ irq_vector = z80->daisy.call_ack_device();
+
+ /* else call back the cpu interface to retrieve the vector */
+ else
+ irq_vector = (*z80->irq_callback)(z80->device, 0);
+
+ LOG(("Z80 '%s' single int. irq_vector $%02x\n", z80->device->tag(), irq_vector));
+
+ /* Interrupt mode 2. Call [i:databyte] */
+ if( z80->im == 2 )
+ {
+ irq_vector = (irq_vector & 0xff) | (z80->i << 8);
+ PUSH(z80, pc);
+ RM16(z80, irq_vector, &z80->pc);
+ LOG(("Z80 '%s' IM2 [$%04x] = $%04x\n", z80->device->tag(), irq_vector, z80->PCD));
+ /* CALL opcode timing + 'interrupt latency' cycles */
+ z80->icount -= z80->cc_op[0xcd] + z80->cc_ex[0xff];
+ }
+ else
+ /* Interrupt mode 1. RST 38h */
+ if( z80->im == 1 )
+ {
+ LOG(("Z80 '%s' IM1 $0038\n", z80->device->tag()));
+ PUSH(z80, pc);
+ z80->PCD = 0x0038;
+ /* RST $38 + 'interrupt latency' cycles */
+ z80->icount -= z80->cc_op[0xff] + cc_ex[0xff];
+ }
+ else
+ {
+ /* Interrupt mode 0. We check for CALL and JP instructions, */
+ /* if neither of these were found we assume a 1 byte opcode */
+ /* was placed on the databus */
+ LOG(("Z80 '%s' IM0 $%04x\n", z80->device->tag(), irq_vector));
+
+ /* check for nop */
+ if (irq_vector != 0x00)
+ {
+ switch (irq_vector & 0xff0000)
+ {
+ case 0xcd0000: /* call */
+ PUSH(z80, pc);
+ z80->PCD = irq_vector & 0xffff;
+ /* CALL $xxxx cycles */
+ z80->icount -= z80->cc_op[0xcd];
+ break;
+ case 0xc30000: /* jump */
+ z80->PCD = irq_vector & 0xffff;
+ /* JP $xxxx cycles */
+ z80->icount -= z80->cc_op[0xc3];
+ break;
+ default: /* rst (or other opcodes?) */
+ PUSH(z80, pc);
+ z80->PCD = irq_vector & 0x0038;
+ /* RST $xx cycles */
+ z80->icount -= z80->cc_op[0xff];
+ break;
+ }
+ }
+
+ /* 'interrupt latency' cycles */
+ z80->icount -= z80->cc_ex[0xff];
+ }
+ z80->WZ=z80->PCD;
+}
+
+static void take_interrupt_nsc800(z80_state *z80)
+{
+ /* there isn't a valid previous program counter */
+ z80->PRVPC = -1;
+
+ /* Check if processor was halted */
+ LEAVE_HALT(z80);
+
+ /* Clear both interrupt flip flops */
+ z80->iff1 = z80->iff2 = 0;
+
+ if (z80->nsc800_irq_state[NSC800_RSTA])
+ {
+ PUSH(z80, pc);
+ z80->PCD = 0x003c;
+ }
+ else if (z80->nsc800_irq_state[NSC800_RSTB])
+ {
+ PUSH(z80, pc);
+ z80->PCD = 0x0034;
+ }
+ else if (z80->nsc800_irq_state[NSC800_RSTC])
+ {
+ PUSH(z80, pc);
+ z80->PCD = 0x002c;
+ }
+
+ /* 'interrupt latency' cycles */
+ z80->icount -= z80->cc_op[0xff] + cc_ex[0xff];
+
+ z80->WZ=z80->PCD;
+}
+
+/****************************************************************************
+ * Processor initialization
+ ****************************************************************************/
+static CPU_INIT( z80 )
+{
+ z80_state *z80 = get_safe_token(device);
+ int i, p;
+
+ if( !SZHVC_add || !SZHVC_sub )
+ {
+ int oldval, newval, val;
+ UINT8 *padd, *padc, *psub, *psbc;
+ /* allocate big flag arrays once */
+ SZHVC_add = global_alloc_array(UINT8, 2*256*256);
+ SZHVC_sub = global_alloc_array(UINT8, 2*256*256);
+ padd = &SZHVC_add[ 0*256];
+ padc = &SZHVC_add[256*256];
+ psub = &SZHVC_sub[ 0*256];
+ psbc = &SZHVC_sub[256*256];
+ for (oldval = 0; oldval < 256; oldval++)
+ {
+ for (newval = 0; newval < 256; newval++)
+ {
+ /* add or adc w/o carry set */
+ val = newval - oldval;
+ *padd = (newval) ? ((newval & 0x80) ? SF : 0) : ZF;
+ *padd |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */
+ if( (newval & 0x0f) < (oldval & 0x0f) ) *padd |= HF;
+ if( newval < oldval ) *padd |= CF;
+ if( (val^oldval^0x80) & (val^newval) & 0x80 ) *padd |= VF;
+ padd++;
+
+ /* adc with carry set */
+ val = newval - oldval - 1;
+ *padc = (newval) ? ((newval & 0x80) ? SF : 0) : ZF;
+ *padc |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */
+ if( (newval & 0x0f) <= (oldval & 0x0f) ) *padc |= HF;
+ if( newval <= oldval ) *padc |= CF;
+ if( (val^oldval^0x80) & (val^newval) & 0x80 ) *padc |= VF;
+ padc++;
+
+ /* cp, sub or sbc w/o carry set */
+ val = oldval - newval;
+ *psub = NF | ((newval) ? ((newval & 0x80) ? SF : 0) : ZF);
+ *psub |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */
+ if( (newval & 0x0f) > (oldval & 0x0f) ) *psub |= HF;
+ if( newval > oldval ) *psub |= CF;
+ if( (val^oldval) & (oldval^newval) & 0x80 ) *psub |= VF;
+ psub++;
+
+ /* sbc with carry set */
+ val = oldval - newval - 1;
+ *psbc = NF | ((newval) ? ((newval & 0x80) ? SF : 0) : ZF);
+ *psbc |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */
+ if( (newval & 0x0f) >= (oldval & 0x0f) ) *psbc |= HF;
+ if( newval >= oldval ) *psbc |= CF;
+ if( (val^oldval) & (oldval^newval) & 0x80 ) *psbc |= VF;
+ psbc++;
+ }
+ }
+ }
+
+ for (i = 0; i < 256; i++)
+ {
+ p = 0;
+ if( i&0x01 ) ++p;
+ if( i&0x02 ) ++p;
+ if( i&0x04 ) ++p;
+ if( i&0x08 ) ++p;
+ if( i&0x10 ) ++p;
+ if( i&0x20 ) ++p;
+ if( i&0x40 ) ++p;
+ if( i&0x80 ) ++p;
+ SZ[i] = i ? i & SF : ZF;
+ SZ[i] |= (i & (YF | XF)); /* undocumented flag bits 5+3 */
+ SZ_BIT[i] = i ? i & SF : ZF | PF;
+ SZ_BIT[i] |= (i & (YF | XF)); /* undocumented flag bits 5+3 */
+ SZP[i] = SZ[i] | ((p & 1) ? 0 : PF);
+ SZHV_inc[i] = SZ[i];
+ if( i == 0x80 ) SZHV_inc[i] |= VF;
+ if( (i & 0x0f) == 0x00 ) SZHV_inc[i] |= HF;
+ SZHV_dec[i] = SZ[i] | NF;
+ if( i == 0x7f ) SZHV_dec[i] |= VF;
+ if( (i & 0x0f) == 0x0f ) SZHV_dec[i] |= HF;
+ }
+
+ device->save_item(NAME(z80->prvpc.w.l));
+ device->save_item(NAME(z80->PC));
+ device->save_item(NAME(z80->SP));
+ device->save_item(NAME(z80->AF));
+ device->save_item(NAME(z80->BC));
+ device->save_item(NAME(z80->DE));
+ device->save_item(NAME(z80->HL));
+ device->save_item(NAME(z80->IX));
+ device->save_item(NAME(z80->IY));
+ device->save_item(NAME(z80->WZ));
+ device->save_item(NAME(z80->af2.w.l));
+ device->save_item(NAME(z80->bc2.w.l));
+ device->save_item(NAME(z80->de2.w.l));
+ device->save_item(NAME(z80->hl2.w.l));
+ device->save_item(NAME(z80->r));
+ device->save_item(NAME(z80->r2));
+ device->save_item(NAME(z80->iff1));
+ device->save_item(NAME(z80->iff2));
+ device->save_item(NAME(z80->halt));
+ device->save_item(NAME(z80->im));
+ device->save_item(NAME(z80->i));
+ device->save_item(NAME(z80->nmi_state));
+ device->save_item(NAME(z80->nmi_pending));
+ device->save_item(NAME(z80->irq_state));
+ device->save_item(NAME(z80->wait_state));
+ device->save_item(NAME(z80->busrq_state));
+ device->save_item(NAME(z80->after_ei));
+ device->save_item(NAME(z80->after_ldair));
+
+ /* Reset registers to their initial values */
+ z80->PRVPC = 0;
+ z80->PCD = 0;
+ z80->SPD = 0;
+ z80->AFD = 0;
+ z80->BCD = 0;
+ z80->DED = 0;
+ z80->HLD = 0;
+ z80->IXD = 0;
+ z80->IYD = 0;
+ z80->WZ = 0;
+ z80->af2.d = 0;
+ z80->bc2.d = 0;
+ z80->de2.d = 0;
+ z80->hl2.d = 0;
+ z80->r = 0;
+ z80->r2 = 0;
+ z80->iff1 = 0;
+ z80->iff2 = 0;
+ z80->halt = 0;
+ z80->im = 0;
+ z80->i = 0;
+ z80->nmi_state = 0;
+ z80->nmi_pending = 0;
+ z80->irq_state = 0;
+ z80->wait_state = 0;
+ z80->busrq_state = 0;
+ z80->after_ei = 0;
+ z80->after_ldair = 0;
+ z80->ea = 0;
+
+ if (device->static_config() != NULL)
+ z80->daisy.init(device, (const z80_daisy_config *)device->static_config());
+ z80->irq_callback = irqcallback;
+ z80->device = device;
+ z80->program = device->space(AS_PROGRAM);
+ z80->direct = &z80->program->direct();
+ z80->io = device->space(AS_IO);
+ z80->IX = z80->IY = 0xffff; /* IX and IY are FFFF after a reset! */
+ z80->F = ZF; /* Zero flag is set */
+
+ /* set up the state table */
+ {
+ device_state_interface *state;
+ device->interface(state);
+ state->state_add(Z80_PC, "PC", z80->pc.w.l);
+ state->state_add(STATE_GENPC, "GENPC", z80->pc.w.l).noshow();
+ state->state_add(STATE_GENPCBASE, "GENPCBASE", z80->prvpc.w.l).noshow();
+ state->state_add(Z80_SP, "SP", z80->SP);
+ state->state_add(STATE_GENSP, "GENSP", z80->SP).noshow();
+ state->state_add(STATE_GENFLAGS, "GENFLAGS", z80->F).noshow().formatstr("%8s");
+ state->state_add(Z80_A, "A", z80->A).noshow();
+ state->state_add(Z80_B, "B", z80->B).noshow();
+ state->state_add(Z80_C, "C", z80->C).noshow();
+ state->state_add(Z80_D, "D", z80->D).noshow();
+ state->state_add(Z80_E, "E", z80->E).noshow();
+ state->state_add(Z80_H, "H", z80->H).noshow();
+ state->state_add(Z80_L, "L", z80->L).noshow();
+ state->state_add(Z80_AF, "AF", z80->AF);
+ state->state_add(Z80_BC, "BC", z80->BC);
+ state->state_add(Z80_DE, "DE", z80->DE);
+ state->state_add(Z80_HL, "HL", z80->HL);
+ state->state_add(Z80_IX, "IX", z80->IX);
+ state->state_add(Z80_IY, "IY", z80->IY);
+ state->state_add(Z80_AF2, "AF2", z80->af2.w.l);
+ state->state_add(Z80_BC2, "BC2", z80->bc2.w.l);
+ state->state_add(Z80_DE2, "DE2", z80->de2.w.l);
+ state->state_add(Z80_HL2, "HL2", z80->hl2.w.l);
+ state->state_add(Z80_WZ, "WZ", z80->WZ);
+ state->state_add(Z80_R, "R", z80->rtemp).callimport().callexport();
+ state->state_add(Z80_I, "I", z80->i);
+ state->state_add(Z80_IM, "IM", z80->im).mask(0x3);
+ state->state_add(Z80_IFF1, "IFF1", z80->iff1).mask(0x1);
+ state->state_add(Z80_IFF2, "IFF2", z80->iff2).mask(0x1);
+ state->state_add(Z80_HALT, "HALT", z80->halt).mask(0x1);
+ }
+
+ /* setup cycle tables */
+ z80->cc_op = cc_op;
+ z80->cc_cb = cc_cb;
+ z80->cc_ed = cc_ed;
+ z80->cc_xy = cc_xy;
+ z80->cc_xycb = cc_xycb;
+ z80->cc_ex = cc_ex;
+}
+
+static CPU_INIT( nsc800 )
+{
+ z80_state *z80 = get_safe_token(device);
+ device->save_item(NAME(z80->nsc800_irq_state));
+ CPU_INIT_CALL (z80);
+}
+
+/****************************************************************************
+ * Do a reset
+ ****************************************************************************/
+static CPU_RESET( z80 )
+{
+ z80_state *z80 = get_safe_token(device);
+
+ z80->PC = 0x0000;
+ z80->i = 0;
+ z80->r = 0;
+ z80->r2 = 0;
+ z80->nmi_state = CLEAR_LINE;
+ z80->nmi_pending = FALSE;
+ z80->irq_state = CLEAR_LINE;
+ z80->wait_state = CLEAR_LINE;
+ z80->busrq_state = CLEAR_LINE;
+ z80->after_ei = FALSE;
+ z80->after_ldair = FALSE;
+ z80->iff1 = 0;
+ z80->iff2 = 0;
+
+ z80->daisy.reset();
+
+ z80->WZ=z80->PCD;
+}
+
+ static CPU_RESET( nsc800 )
+{
+ z80_state *z80 = get_safe_token(device);
+ memset(z80->nsc800_irq_state, 0, sizeof(z80->nsc800_irq_state));
+ CPU_RESET_CALL(z80);
+}
+
+static CPU_EXIT( z80 )
+{
+ global_free(SZHVC_add);
+ SZHVC_add = NULL;
+ global_free(SZHVC_sub);
+ SZHVC_sub = NULL;
+}
+
+/****************************************************************************
+ * Execute 'cycles' T-states. Return number of T-states really executed
+ ****************************************************************************/
+static CPU_EXECUTE( z80 )
+{
+ z80_state *z80 = get_safe_token(device);
+
+ /* check for NMIs on the way in; they can only be set externally */
+ /* via timers, and can't be dynamically enabled, so it is safe */
+ /* to just check here */
+ if (z80->nmi_pending)
+ {
+ LOG(("Z80 '%s' take NMI\n", z80->device->tag()));
+ z80->PRVPC = -1; /* there isn't a valid previous program counter */
+ LEAVE_HALT(z80); /* Check if processor was halted */
+
+#if HAS_LDAIR_QUIRK
+ /* reset parity flag after LD A,I or LD A,R */
+ if (z80->after_ldair) z80->F &= ~PF;
+#endif
+ z80->after_ldair = FALSE;
+
+ z80->iff1 = 0;
+ PUSH(z80, pc);
+ z80->PCD = 0x0066;
+ z80->WZ=z80->PCD;
+ z80->icount -= 11;
+ z80->nmi_pending = FALSE;
+ }
+
+ do
+ {
+ /* check for IRQs before each instruction */
+ if (z80->irq_state != CLEAR_LINE && z80->iff1 && !z80->after_ei)
+ {
+#if HAS_LDAIR_QUIRK
+ /* reset parity flag after LD A,I or LD A,R */
+ if (z80->after_ldair) z80->F &= ~PF;
+#endif
+ take_interrupt(z80);
+ }
+ z80->after_ei = FALSE;
+ z80->after_ldair = FALSE;
+
+ z80->PRVPC = z80->PCD;
+ debugger_instruction_hook(device, z80->PCD);
+ z80->r++;
+ EXEC_INLINE(z80,op,ROP(z80));
+ } while (z80->icount > 0);
+}
+
+ static CPU_EXECUTE( nsc800 )
+{
+ z80_state *z80 = get_safe_token(device);
+
+ /* check for NMIs on the way in; they can only be set externally */
+ /* via timers, and can't be dynamically enabled, so it is safe */
+ /* to just check here */
+ if (z80->nmi_pending)
+ {
+ LOG(("Z80 '%s' take NMI\n", z80->device->tag()));
+ z80->PRVPC = -1; /* there isn't a valid previous program counter */
+ LEAVE_HALT(z80); /* Check if processor was halted */
+
+ z80->iff1 = 0;
+ PUSH(z80, pc);
+ z80->PCD = 0x0066;
+ z80->WZ=z80->PCD;
+ z80->icount -= 11;
+ z80->nmi_pending = FALSE;
+ }
+
+ do
+ {
+ /* check for NSC800 IRQs line RSTA, RSTB, RSTC */
+ if ((z80->nsc800_irq_state[NSC800_RSTA] != CLEAR_LINE ||
+ z80->nsc800_irq_state[NSC800_RSTB] != CLEAR_LINE ||
+ z80->nsc800_irq_state[NSC800_RSTC] != CLEAR_LINE) && z80->iff1 && !z80->after_ei)
+ take_interrupt_nsc800(z80);
+
+ /* check for IRQs before each instruction */
+ if (z80->irq_state != CLEAR_LINE && z80->iff1 && !z80->after_ei)
+ take_interrupt(z80);
+
+ z80->after_ei = FALSE;
+
+ z80->PRVPC = z80->PCD;
+ debugger_instruction_hook(device, z80->PCD);
+ z80->r++;
+ EXEC_INLINE(z80,op,ROP(z80));
+ } while (z80->icount > 0);
+}
+
+/****************************************************************************
+ * Burn 'cycles' T-states. Adjust z80->r register for the lost time
+ ****************************************************************************/
+static CPU_BURN( z80 )
+{
+ z80_state *z80 = get_safe_token(device);
+
+ if( cycles > 0 )
+ {
+ /* NOP takes 4 cycles per instruction */
+ int n = (cycles + 3) / 4;
+ z80->r += n;
+ z80->icount -= 4 * n;
+ }
+}
+
+/****************************************************************************
+ * Set IRQ line state
+ ****************************************************************************/
+static void set_irq_line(z80_state *z80, int irqline, int state)
+{
+ switch (irqline)
+ {
+ case Z80_INPUT_LINE_BUSRQ:
+ z80->busrq_state = state;
+ break;
+
+ case INPUT_LINE_NMI:
+ /* mark an NMI pending on the rising edge */
+ if (z80->nmi_state == CLEAR_LINE && state != CLEAR_LINE)
+ z80->nmi_pending = TRUE;
+ z80->nmi_state = state;
+ break;
+
+ case INPUT_LINE_IRQ0:
+ /* update the IRQ state via the daisy chain */
+ z80->irq_state = state;
+ if (z80->daisy.present())
+ z80->irq_state = ( z80->daisy.update_irq_state() == ASSERT_LINE ) ? ASSERT_LINE : z80->irq_state;
+
+ /* the main execute loop will take the interrupt */
+ break;
+
+ case Z80_INPUT_LINE_WAIT:
+ z80->wait_state = state;
+ break;
+ }
+}
+
+
+static void set_irq_line_nsc800(z80_state *z80, int irqline, int state)
+{
+ switch (irqline)
+ {
+ case Z80_INPUT_LINE_BUSRQ:
+ z80->busrq_state = state;
+ break;
+
+ case INPUT_LINE_NMI:
+ /* mark an NMI pending on the rising edge */
+ if (z80->nmi_state == CLEAR_LINE && state != CLEAR_LINE)
+ z80->nmi_pending = TRUE;
+ z80->nmi_state = state;
+ break;
+
+ case NSC800_RSTA:
+ z80->nsc800_irq_state[NSC800_RSTA] = state;
+ break;
+
+ case NSC800_RSTB:
+ z80->nsc800_irq_state[NSC800_RSTB] = state;
+ break;
+
+ case NSC800_RSTC:
+ z80->nsc800_irq_state[NSC800_RSTC] = state;
+ break;
+
+ case INPUT_LINE_IRQ0:
+ /* update the IRQ state via the daisy chain */
+ z80->irq_state = state;
+ if (z80->daisy.present())
+ z80->irq_state = z80->daisy.update_irq_state();
+
+ /* the main execute loop will take the interrupt */
+ break;
+
+ case Z80_INPUT_LINE_WAIT:
+ z80->wait_state = state;
+ break;
+ }
+}
+
+
+/**************************************************************************
+ * STATE IMPORT/EXPORT
+ **************************************************************************/
+
+static CPU_IMPORT_STATE( z80 )
+{
+ z80_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case Z80_R:
+ cpustate->r = cpustate->rtemp & 0x7f;
+ cpustate->r2 = cpustate->rtemp & 0x80;
+ break;
+
+ default:
+ fatalerror("CPU_IMPORT_STATE(z80) called for unexpected value\n");
+ break;
+ }
+}
+
+
+static CPU_EXPORT_STATE( z80 )
+{
+ z80_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case Z80_R:
+ cpustate->rtemp = (cpustate->r & 0x7f) | (cpustate->r2 & 0x80);
+ break;
+
+ default:
+ fatalerror("CPU_EXPORT_STATE(z80) called for unexpected value\n");
+ break;
+ }
+}
+
+static CPU_EXPORT_STRING( z80 )
+{
+ z80_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ string.printf("%c%c%c%c%c%c%c%c",
+ cpustate->F & 0x80 ? 'S':'.',
+ cpustate->F & 0x40 ? 'Z':'.',
+ cpustate->F & 0x20 ? 'Y':'.',
+ cpustate->F & 0x10 ? 'H':'.',
+ cpustate->F & 0x08 ? 'X':'.',
+ cpustate->F & 0x04 ? 'P':'.',
+ cpustate->F & 0x02 ? 'N':'.',
+ cpustate->F & 0x01 ? 'C':'.');
+ break;
+ }
+}
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( z80 )
+{
+ z80_state *z80 = get_safe_token(device);
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + Z80_INPUT_LINE_BUSRQ: set_irq_line(z80, Z80_INPUT_LINE_BUSRQ, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line(z80, INPUT_LINE_NMI, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ0: set_irq_line(z80, INPUT_LINE_IRQ0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + Z80_INPUT_LINE_WAIT: set_irq_line(z80, Z80_INPUT_LINE_WAIT, info->i); break;
+ }
+}
+
+static CPU_SET_INFO( nsc800 )
+{
+ z80_state *z80 = get_safe_token(device);
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + Z80_INPUT_LINE_BUSRQ: set_irq_line(z80, Z80_INPUT_LINE_BUSRQ, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line_nsc800(z80, INPUT_LINE_NMI, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + NSC800_RSTA: set_irq_line_nsc800(z80, NSC800_RSTA, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + NSC800_RSTB: set_irq_line_nsc800(z80, NSC800_RSTB, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + NSC800_RSTC: set_irq_line_nsc800(z80, NSC800_RSTC, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ0: set_irq_line_nsc800(z80, INPUT_LINE_IRQ0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + Z80_INPUT_LINE_WAIT: set_irq_line(z80, Z80_INPUT_LINE_WAIT, info->i); break;
+ }
+}
+
+void z80_set_cycle_tables(device_t *device, const UINT8 *op, const UINT8 *cb, const UINT8 *ed, const UINT8 *xy, const UINT8 *xycb, const UINT8 *ex)
+{
+ z80_state *z80 = get_safe_token(device);
+
+ z80->cc_op = (op != NULL) ? op : cc_op;
+ z80->cc_cb = (cb != NULL) ? cb : cc_cb;
+ z80->cc_ed = (ed != NULL) ? ed : cc_ed;
+ z80->cc_xy = (xy != NULL) ? xy : cc_xy;
+ z80->cc_xycb = (xycb != NULL) ? xycb : cc_xycb;
+ z80->cc_ex = (ex != NULL) ? ex : cc_ex;
+}
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( z80 )
+{
+ z80_state *z80 = (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(z80_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 = 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 = 2; 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 = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + Z80_INPUT_LINE_BUSRQ: info->i = z80->busrq_state; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = z80->nmi_state; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ0: info->i = z80->irq_state; break;
+ case CPUINFO_INT_INPUT_STATE + Z80_INPUT_LINE_WAIT: info->i = z80->wait_state; break;
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(z80); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(z80); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(z80); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(z80); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(z80); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(z80); break;
+ case CPUINFO_FCT_IMPORT_STATE: info->import_state = CPU_IMPORT_STATE_NAME(z80); break;
+ case CPUINFO_FCT_EXPORT_STATE: info->export_state = CPU_EXPORT_STATE_NAME(z80); break;
+ case CPUINFO_FCT_EXPORT_STRING: info->export_string = CPU_EXPORT_STRING_NAME(z80); break;
+
+ /* --- the following bits of info are returned as pointers --- */
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &z80->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Z80"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Zilog Z80"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "3.9"); 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;
+ }
+}
+
+CPU_GET_INFO( nsc800 )
+{
+ z80_state *z80 = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+ switch (state)
+ {
+ case CPUINFO_INT_INPUT_LINES: info->i = 7; break;
+
+ case CPUINFO_INT_INPUT_STATE + NSC800_RSTA: info->i = z80->nsc800_irq_state[NSC800_RSTA]; break;
+ case CPUINFO_INT_INPUT_STATE + NSC800_RSTB: info->i = z80->nsc800_irq_state[NSC800_RSTB]; break;
+ case CPUINFO_INT_INPUT_STATE + NSC800_RSTC: info->i = z80->nsc800_irq_state[NSC800_RSTC]; break;
+
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(nsc800); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(nsc800); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(nsc800); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(nsc800); break;
+
+ case DEVINFO_STR_NAME: strcpy(info->s, "NSC800"); break;
+
+ default: CPU_GET_INFO_CALL(z80); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(Z80, z80);
+DEFINE_LEGACY_CPU_DEVICE(NSC800, nsc800);
diff --git a/trunk/src/emu/cpu/z80/z80.h b/trunk/src/emu/cpu/z80/z80.h
new file mode 100644
index 00000000000..b92c7174071
--- /dev/null
+++ b/trunk/src/emu/cpu/z80/z80.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#ifndef __Z80_H__
+#define __Z80_H__
+
+enum
+{
+ NSC800_RSTA = INPUT_LINE_IRQ0 + 1,
+ NSC800_RSTB,
+ NSC800_RSTC,
+ Z80_INPUT_LINE_WAIT,
+ Z80_INPUT_LINE_BUSRQ
+};
+
+enum
+{
+ Z80_PC, Z80_SP,
+ Z80_A, Z80_B, Z80_C, Z80_D, Z80_E, Z80_H, Z80_L,
+ Z80_AF, Z80_BC, Z80_DE, Z80_HL,
+ Z80_IX, Z80_IY, Z80_AF2, Z80_BC2, Z80_DE2, Z80_HL2,
+ Z80_R, Z80_I, Z80_IM, Z80_IFF1, Z80_IFF2, Z80_HALT,
+ Z80_DC0, Z80_DC1, Z80_DC2, Z80_DC3, Z80_WZ,
+
+ Z80_GENPC = STATE_GENPC,
+ Z80_GENSP = STATE_GENSP,
+ Z80_GENPCBASE = STATE_GENPCBASE
+};
+
+DECLARE_LEGACY_CPU_DEVICE(Z80, z80);
+DECLARE_LEGACY_CPU_DEVICE(NSC800, nsc800);
+
+CPU_DISASSEMBLE( z80 );
+
+void z80_set_cycle_tables(device_t *device, const UINT8 *op, const UINT8 *cb, const UINT8 *ed, const UINT8 *xy, const UINT8 *xycb, const UINT8 *ex);
+
+#endif /* __Z80_H__ */
diff --git a/trunk/src/emu/cpu/z80/z80daisy.c b/trunk/src/emu/cpu/z80/z80daisy.c
new file mode 100644
index 00000000000..e7d5b20d2cf
--- /dev/null
+++ b/trunk/src/emu/cpu/z80/z80daisy.c
@@ -0,0 +1,170 @@
+/***************************************************************************
+
+ z80daisy.c
+
+ Z80/180 daisy chaining support functions.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "z80daisy.h"
+
+
+//**************************************************************************
+// DEVICE Z80 DAISY INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_z80daisy_interface - constructor
+//-------------------------------------------------
+
+device_z80daisy_interface::device_z80daisy_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device)
+{
+}
+
+
+//-------------------------------------------------
+// ~device_z80daisy_interface - destructor
+//-------------------------------------------------
+
+device_z80daisy_interface::~device_z80daisy_interface()
+{
+}
+
+
+
+//**************************************************************************
+// Z80 DAISY CHAIN
+//**************************************************************************
+
+//-------------------------------------------------
+// z80_daisy_chain - constructor
+//-------------------------------------------------
+
+z80_daisy_chain::z80_daisy_chain()
+ : m_daisy_list(NULL)
+{
+}
+
+
+//-------------------------------------------------
+// init - allocate the daisy chain based on the
+// provided configuration
+//-------------------------------------------------
+
+void z80_daisy_chain::init(device_t *cpudevice, const z80_daisy_config *daisy)
+{
+ // create a linked list of devices
+ daisy_entry **tailptr = &m_daisy_list;
+ for ( ; daisy->devname != NULL; daisy++)
+ {
+ // find the device
+ device_t *target = cpudevice->siblingdevice(daisy->devname);
+ if (target == NULL)
+ fatalerror("Unable to locate device '%s'", daisy->devname);
+
+ // make sure it has an interface
+ device_z80daisy_interface *intf;
+ if (!target->interface(intf))
+ fatalerror("Device '%s' does not implement the z80daisy interface!", daisy->devname);
+
+ // append to the end
+ *tailptr = auto_alloc(cpudevice->machine(), daisy_entry(target));
+ tailptr = &(*tailptr)->m_next;
+ }
+}
+
+
+//-------------------------------------------------
+// reset - send a reset signal to all chained
+// devices
+//-------------------------------------------------
+
+void z80_daisy_chain::reset()
+{
+ // loop over all devices and call their reset function
+ for (daisy_entry *daisy = m_daisy_list; daisy != NULL; daisy = daisy->m_next)
+ daisy->m_device->reset();
+}
+
+
+//-------------------------------------------------
+// update_irq_state - update the IRQ state and
+// return assert/clear based on the state
+//-------------------------------------------------
+
+int z80_daisy_chain::update_irq_state()
+{
+ // loop over all devices; dev[0] is highest priority
+ for (daisy_entry *daisy = m_daisy_list; daisy != NULL; daisy = daisy->m_next)
+ {
+ // if this device is asserting the INT line, that's the one we want
+ int state = daisy->m_interface->z80daisy_irq_state();
+ if (state & Z80_DAISY_INT)
+ return ASSERT_LINE;
+
+ // if this device is asserting the IEO line, it blocks everyone else
+ if (state & Z80_DAISY_IEO)
+ return CLEAR_LINE;
+ }
+ return CLEAR_LINE;
+}
+
+
+//-------------------------------------------------
+// call_ack_device - acknowledge an interrupt
+// from a chained device and return the vector
+//-------------------------------------------------
+
+int z80_daisy_chain::call_ack_device()
+{
+ int vector = 0;
+
+ // loop over all devices; dev[0] is the highest priority
+ for (daisy_entry *daisy = m_daisy_list; daisy != NULL; daisy = daisy->m_next)
+ {
+ // if this device is asserting the INT line, that's the one we want
+ int state = daisy->m_interface->z80daisy_irq_state();
+ vector = daisy->m_interface->z80daisy_irq_ack();
+ if (state & Z80_DAISY_INT)
+ return vector;
+ }
+ logerror("z80daisy_call_ack_device: failed to find an device to ack!\n");
+ return vector;
+}
+
+
+//-------------------------------------------------
+// call_reti_device - signal a RETI operator to
+// the chain
+//-------------------------------------------------
+
+void z80_daisy_chain::call_reti_device()
+{
+ // loop over all devices; dev[0] is the highest priority
+ for (daisy_entry *daisy = m_daisy_list; daisy != NULL; daisy = daisy->m_next)
+ {
+ // if this device is asserting the IEO line, that's the one we want
+ int state = daisy->m_interface->z80daisy_irq_state();
+ if (state & Z80_DAISY_IEO)
+ {
+ daisy->m_interface->z80daisy_irq_reti();
+ return;
+ }
+ }
+ //logerror("z80daisy_call_reti_device: failed to find an device to reti!\n");
+}
+
+
+//-------------------------------------------------
+// daisy_entry - constructor
+//-------------------------------------------------
+
+z80_daisy_chain::daisy_entry::daisy_entry(device_t *device)
+ : m_next(NULL),
+ m_device(device),
+ m_interface(NULL)
+{
+ device->interface(m_interface);
+}
diff --git a/trunk/src/emu/cpu/z80/z80daisy.h b/trunk/src/emu/cpu/z80/z80daisy.h
new file mode 100644
index 00000000000..5dbfd66294b
--- /dev/null
+++ b/trunk/src/emu/cpu/z80/z80daisy.h
@@ -0,0 +1,87 @@
+/***************************************************************************
+
+ z80daisy.h
+
+ Z80/180 daisy chaining support functions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __Z80DAISY_H__
+#define __Z80DAISY_H__
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// these constants are returned from the irq_state function
+const UINT8 Z80_DAISY_INT = 0x01; // interrupt request mask
+const UINT8 Z80_DAISY_IEO = 0x02; // interrupt disable mask (IEO)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> z80_daisy_config
+
+struct z80_daisy_config
+{
+ const char * devname; // name of the device
+};
+
+
+
+// ======================> device_z80daisy_interface
+
+class device_z80daisy_interface : public device_interface
+{
+public:
+ // construction/destruction
+ device_z80daisy_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_z80daisy_interface();
+
+ // required operation overrides
+ virtual int z80daisy_irq_state() = 0;
+ virtual int z80daisy_irq_ack() = 0;
+ virtual void z80daisy_irq_reti() = 0;
+};
+
+
+
+// ======================> z80_daisy_chain
+
+class z80_daisy_chain
+{
+public:
+ z80_daisy_chain();
+ void init(device_t *cpudevice, const z80_daisy_config *daisy);
+
+ bool present() const { return (m_daisy_list != NULL); }
+
+ void reset();
+ int update_irq_state();
+ int call_ack_device();
+ void call_reti_device();
+
+protected:
+ class daisy_entry
+ {
+ public:
+ daisy_entry(device_t *device);
+
+ daisy_entry * m_next; // next device
+ device_t * m_device; // associated device
+ device_z80daisy_interface * m_interface; // associated device's daisy interface
+ };
+
+ daisy_entry * m_daisy_list; // head of the daisy chain
+};
+
+
+#endif
diff --git a/trunk/src/emu/cpu/z80/z80dasm.c b/trunk/src/emu/cpu/z80/z80dasm.c
new file mode 100644
index 00000000000..f0b494e67d0
--- /dev/null
+++ b/trunk/src/emu/cpu/z80/z80dasm.c
@@ -0,0 +1,544 @@
+/*****************************************************************************
+ *
+ * z80dasm.c
+ * Portable Z80 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.
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "z80.h"
+
+enum e_mnemonics
+{
+ zADC ,zADD ,zAND ,zBIT ,zCALL ,zCCF ,zCP ,zCPD ,
+ zCPDR ,zCPI ,zCPIR ,zCPL ,zDAA ,zDB ,zDEC ,zDI ,
+ zDJNZ ,zEI ,zEX ,zEXX ,zHLT ,zIM ,zIN ,zINC ,
+ zIND ,zINDR ,zINI ,zINIR ,zJP ,zJR ,zLD ,zLDD ,
+ zLDDR ,zLDI ,zLDIR ,zNEG ,zNOP ,zOR ,zOTDR ,zOTIR ,
+ zOUT ,zOUTD ,zOUTI ,zPOP ,zPUSH ,zRES ,zRET ,zRETI ,
+ zRETN ,zRL ,zRLA ,zRLC ,zRLCA ,zRLD ,zRR ,zRRA ,
+ zRRC ,zRRCA ,zRRD ,zRST ,zSBC ,zSCF ,zSET ,zSLA ,
+ zSLL ,zSRA ,zSRL ,zSUB ,zXOR
+};
+
+static const char *const s_mnemonic[] =
+{
+ "adc" ,"add" ,"and" ,"bit" ,"call","ccf" ,"cp" ,"cpd" ,
+ "cpdr","cpi" ,"cpir","cpl" ,"daa" ,"db" ,"dec" ,"di" ,
+ "djnz","ei" ,"ex" ,"exx" ,"halt","im" ,"in" ,"inc" ,
+ "ind" ,"indr","ini" ,"inir","jp" ,"jr" ,"ld" ,"ldd" ,
+ "lddr","ldi" ,"ldir","neg" ,"nop" ,"or" ,"otdr","otir",
+ "out" ,"outd","outi","pop" ,"push","res" ,"ret" ,"reti",
+ "retn","rl" ,"rla" ,"rlc" ,"rlca","rld" ,"rr" ,"rra" ,
+ "rrc" ,"rrca","rrd" ,"rst" ,"sbc" ,"scf" ,"set" ,"sla" ,
+ "sll" ,"sra" ,"srl" ,"sub" ,"xor "
+};
+
+#define _OVER DASMFLAG_STEP_OVER
+#define _OUT DASMFLAG_STEP_OUT
+
+static const UINT32 s_flags[] =
+{
+ 0 ,0 ,0 ,0 ,_OVER,0 ,0 ,0 ,
+ _OVER,0 ,_OVER,0 ,0 ,0 ,0 ,0 ,
+ _OVER,0 ,0 ,0 ,_OVER,0 ,0 ,0 ,
+ 0 ,_OVER,0 ,_OVER,0 ,0 ,0 ,0 ,
+ _OVER,0 ,_OVER,0 ,0 ,0 ,_OVER,_OVER,
+ 0 ,0 ,0 ,0 ,0 ,0 ,_OUT ,_OUT ,
+ _OUT ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,_OVER,0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 ,0
+};
+
+typedef struct
+{
+ UINT8 mnemonic;
+ const char *arguments;
+} z80dasm;
+
+static const z80dasm mnemonic_xx_cb[256] =
+{
+ {zRLC,"b=Y"}, {zRLC,"c=Y"}, {zRLC,"d=Y"}, {zRLC,"e=Y"},
+ {zRLC,"h=Y"}, {zRLC,"l=Y"}, {zRLC,"Y"}, {zRLC,"a=Y"},
+ {zRRC,"b=Y"}, {zRRC,"c=Y"}, {zRRC,"d=Y"}, {zRRC,"e=Y"},
+ {zRRC,"h=Y"}, {zRRC,"l=Y"}, {zRRC,"Y"}, {zRRC,"a=Y"},
+ {zRL,"b=Y"}, {zRL,"c=Y"}, {zRL,"d=Y"}, {zRL,"e=Y"},
+ {zRL,"h=Y"}, {zRL,"l=Y"}, {zRL,"Y"}, {zRL,"a=Y"},
+ {zRR,"b=Y"}, {zRR,"c=Y"}, {zRR,"d=Y"}, {zRR,"e=Y"},
+ {zRR,"h=Y"}, {zRR,"l=Y"}, {zRR,"Y"}, {zRR,"a=Y"},
+ {zSLA,"b=Y"}, {zSLA,"c=Y"}, {zSLA,"d=Y"}, {zSLA,"e=Y"},
+ {zSLA,"h=Y"}, {zSLA,"l=Y"}, {zSLA,"Y"}, {zSLA,"a=Y"},
+ {zSRA,"b=Y"}, {zSRA,"c=Y"}, {zSRA,"d=Y"}, {zSRA,"e=Y"},
+ {zSRA,"h=Y"}, {zSRA,"l=Y"}, {zSRA,"Y"}, {zSRA,"a=Y"},
+ {zSLL,"b=Y"}, {zSLL,"c=Y"}, {zSLL,"d=Y"}, {zSLL,"e=Y"},
+ {zSLL,"h=Y"}, {zSLL,"l=Y"}, {zSLL,"Y"}, {zSLL,"a=Y"},
+ {zSRL,"b=Y"}, {zSRL,"c=Y"}, {zSRL,"d=Y"}, {zSRL,"e=Y"},
+ {zSRL,"h=Y"}, {zSRL,"l=Y"}, {zSRL,"Y"}, {zSRL,"a=Y"},
+ {zBIT,"b=0,Y"}, {zBIT,"c=0,Y"}, {zBIT,"d=0,Y"}, {zBIT,"e=0,Y"},
+ {zBIT,"h=0,Y"}, {zBIT,"l=0,Y"}, {zBIT,"0,Y"}, {zBIT,"a=0,Y"},
+ {zBIT,"b=1,Y"}, {zBIT,"c=1,Y"}, {zBIT,"d=1,Y"}, {zBIT,"e=1,Y"},
+ {zBIT,"h=1,Y"}, {zBIT,"l=1,Y"}, {zBIT,"1,Y"}, {zBIT,"a=1,Y"},
+ {zBIT,"b=2,Y"}, {zBIT,"c=2,Y"}, {zBIT,"d=2,Y"}, {zBIT,"e=2,Y"},
+ {zBIT,"h=2,Y"}, {zBIT,"l=2,Y"}, {zBIT,"2,Y"}, {zBIT,"a=2,Y"},
+ {zBIT,"b=3,Y"}, {zBIT,"c=3,Y"}, {zBIT,"d=3,Y"}, {zBIT,"e=3,Y"},
+ {zBIT,"h=3,Y"}, {zBIT,"l=3,Y"}, {zBIT,"3,Y"}, {zBIT,"a=3,Y"},
+ {zBIT,"b=4,Y"}, {zBIT,"c=4,Y"}, {zBIT,"d=4,Y"}, {zBIT,"e=4,Y"},
+ {zBIT,"h=4,Y"}, {zBIT,"l=4,Y"}, {zBIT,"4,Y"}, {zBIT,"a=4,Y"},
+ {zBIT,"b=5,Y"}, {zBIT,"c=5,Y"}, {zBIT,"d=5,Y"}, {zBIT,"e=5,Y"},
+ {zBIT,"h=5,Y"}, {zBIT,"l=5,Y"}, {zBIT,"5,Y"}, {zBIT,"a=5,Y"},
+ {zBIT,"b=6,Y"}, {zBIT,"c=6,Y"}, {zBIT,"d=6,Y"}, {zBIT,"e=6,Y"},
+ {zBIT,"h=6,Y"}, {zBIT,"l=6,Y"}, {zBIT,"6,Y"}, {zBIT,"a=6,Y"},
+ {zBIT,"b=7,Y"}, {zBIT,"c=7,Y"}, {zBIT,"d=7,Y"}, {zBIT,"e=7,Y"},
+ {zBIT,"h=7,Y"}, {zBIT,"l=7,Y"}, {zBIT,"7,Y"}, {zBIT,"a=7,Y"},
+ {zRES,"b=0,Y"}, {zRES,"c=0,Y"}, {zRES,"d=0,Y"}, {zRES,"e=0,Y"},
+ {zRES,"h=0,Y"}, {zRES,"l=0,Y"}, {zRES,"0,Y"}, {zRES,"a=0,Y"},
+ {zRES,"b=1,Y"}, {zRES,"c=1,Y"}, {zRES,"d=1,Y"}, {zRES,"e=1,Y"},
+ {zRES,"h=1,Y"}, {zRES,"l=1,Y"}, {zRES,"1,Y"}, {zRES,"a=1,Y"},
+ {zRES,"b=2,Y"}, {zRES,"c=2,Y"}, {zRES,"d=2,Y"}, {zRES,"e=2,Y"},
+ {zRES,"h=2,Y"}, {zRES,"l=2,Y"}, {zRES,"2,Y"}, {zRES,"a=2,Y"},
+ {zRES,"b=3,Y"}, {zRES,"c=3,Y"}, {zRES,"d=3,Y"}, {zRES,"e=3,Y"},
+ {zRES,"h=3,Y"}, {zRES,"l=3,Y"}, {zRES,"3,Y"}, {zRES,"a=3,Y"},
+ {zRES,"b=4,Y"}, {zRES,"c=4,Y"}, {zRES,"d=4,Y"}, {zRES,"e=4,Y"},
+ {zRES,"h=4,Y"}, {zRES,"l=4,Y"}, {zRES,"4,Y"}, {zRES,"a=4,Y"},
+ {zRES,"b=5,Y"}, {zRES,"c=5,Y"}, {zRES,"d=5,Y"}, {zRES,"e=5,Y"},
+ {zRES,"h=5,Y"}, {zRES,"l=5,Y"}, {zRES,"5,Y"}, {zRES,"a=5,Y"},
+ {zRES,"b=6,Y"}, {zRES,"c=6,Y"}, {zRES,"d=6,Y"}, {zRES,"e=6,Y"},
+ {zRES,"h=6,Y"}, {zRES,"l=6,Y"}, {zRES,"6,Y"}, {zRES,"a=6,Y"},
+ {zRES,"b=7,Y"}, {zRES,"c=7,Y"}, {zRES,"d=7,Y"}, {zRES,"e=7,Y"},
+ {zRES,"h=7,Y"}, {zRES,"l=7,Y"}, {zRES,"7,Y"}, {zRES,"a=7,Y"},
+ {zSET,"b=0,Y"}, {zSET,"c=0,Y"}, {zSET,"d=0,Y"}, {zSET,"e=0,Y"},
+ {zSET,"h=0,Y"}, {zSET,"l=0,Y"}, {zSET,"0,Y"}, {zSET,"a=0,Y"},
+ {zSET,"b=1,Y"}, {zSET,"c=1,Y"}, {zSET,"d=1,Y"}, {zSET,"e=1,Y"},
+ {zSET,"h=1,Y"}, {zSET,"l=1,Y"}, {zSET,"1,Y"}, {zSET,"a=1,Y"},
+ {zSET,"b=2,Y"}, {zSET,"c=2,Y"}, {zSET,"d=2,Y"}, {zSET,"e=2,Y"},
+ {zSET,"h=2,Y"}, {zSET,"l=2,Y"}, {zSET,"2,Y"}, {zSET,"a=2,Y"},
+ {zSET,"b=3,Y"}, {zSET,"c=3,Y"}, {zSET,"d=3,Y"}, {zSET,"e=3,Y"},
+ {zSET,"h=3,Y"}, {zSET,"l=3,Y"}, {zSET,"3,Y"}, {zSET,"a=3,Y"},
+ {zSET,"b=4,Y"}, {zSET,"c=4,Y"}, {zSET,"d=4,Y"}, {zSET,"e=4,Y"},
+ {zSET,"h=4,Y"}, {zSET,"l=4,Y"}, {zSET,"4,Y"}, {zSET,"a=4,Y"},
+ {zSET,"b=5,Y"}, {zSET,"c=5,Y"}, {zSET,"d=5,Y"}, {zSET,"e=5,Y"},
+ {zSET,"h=5,Y"}, {zSET,"l=5,Y"}, {zSET,"5,Y"}, {zSET,"a=5,Y"},
+ {zSET,"b=6,Y"}, {zSET,"c=6,Y"}, {zSET,"d=6,Y"}, {zSET,"e=6,Y"},
+ {zSET,"h=6,Y"}, {zSET,"l=6,Y"}, {zSET,"6,Y"}, {zSET,"a=6,Y"},
+ {zSET,"b=7,Y"}, {zSET,"c=7,Y"}, {zSET,"d=7,Y"}, {zSET,"e=7,Y"},
+ {zSET,"h=7,Y"}, {zSET,"l=7,Y"}, {zSET,"7,Y"}, {zSET,"a=7,Y"}
+};
+
+static const z80dasm 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"},
+ {zSLL,"b"}, {zSLL,"c"}, {zSLL,"d"}, {zSLL,"e"},
+ {zSLL,"h"}, {zSLL,"l"}, {zSLL,"(hl)"}, {zSLL,"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 z80dasm mnemonic_ed[256] =
+{
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zIN,"b,(c)"}, {zOUT,"(c),b"}, {zSBC,"hl,bc"}, {zLD,"(W),bc"},
+ {zNEG,0}, {zRETN,0}, {zIM,"0"}, {zLD,"i,a"},
+ {zIN,"c,(c)"}, {zOUT,"(c),c"}, {zADC,"hl,bc"}, {zLD,"bc,(W)"},
+ {zNEG,"*"}, {zRETI,0}, {zIM,"0"}, {zLD,"r,a"},
+ {zIN,"d,(c)"}, {zOUT,"(c),d"}, {zSBC,"hl,de"}, {zLD,"(W),de"},
+ {zNEG,"*"}, {zRETN,0}, {zIM,"1"}, {zLD,"a,i"},
+ {zIN,"e,(c)"}, {zOUT,"(c),e"}, {zADC,"hl,de"}, {zLD,"de,(W)"},
+ {zNEG,"*"}, {zRETI,0}, {zIM,"2"}, {zLD,"a,r"},
+ {zIN,"h,(c)"}, {zOUT,"(c),h"}, {zSBC,"hl,hl"}, {zLD,"(W),hl"},
+ {zNEG,"*"}, {zRETN,0}, {zIM,"0"}, {zRRD,"(hl)"},
+ {zIN,"l,(c)"}, {zOUT,"(c),l"}, {zADC,"hl,hl"}, {zLD,"hl,(W)"},
+ {zNEG,"*"}, {zRETI,0}, {zIM,"0"}, {zRLD,"(hl)"},
+ {zIN,"0,(c)"}, {zOUT,"(c),0"}, {zSBC,"hl,sp"}, {zLD,"(W),sp"},
+ {zNEG,"*"}, {zRETN,0}, {zIM,"1"}, {zDB,"?"},
+ {zIN,"a,(c)"}, {zOUT,"(c),a"}, {zADC,"hl,sp"}, {zLD,"sp,(W)"},
+ {zNEG,"*"}, {zRETI,0}, {zIM,"2"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zLDI,0}, {zCPI,0}, {zINI,0}, {zOUTI,0},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zLDD,0}, {zCPD,0}, {zIND,0}, {zOUTD,0},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zLDIR,0}, {zCPIR,0}, {zINIR,0}, {zOTIR,0},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zLDDR,0}, {zCPDR,0}, {zINDR,0}, {zOTDR,0},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"}
+};
+
+static const z80dasm mnemonic_xx[256] =
+{
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zADD,"I,bc"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zADD,"I,de"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zLD,"I,N"}, {zLD,"(W),I"}, {zINC,"I"},
+ {zINC,"Ih"}, {zDEC,"Ih"}, {zLD,"Ih,B"}, {zDB,"?"},
+ {zDB,"?"}, {zADD,"I,I"}, {zLD,"I,(W)"}, {zDEC,"I"},
+ {zINC,"Il"}, {zDEC,"Il"}, {zLD,"Il,B"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zINC,"X"}, {zDEC,"X"}, {zLD,"X,B"}, {zDB,"?"},
+ {zDB,"?"}, {zADD,"I,sp"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zLD,"b,Ih"}, {zLD,"b,Il"}, {zLD,"b,X"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zLD,"c,Ih"}, {zLD,"c,Il"}, {zLD,"c,X"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zLD,"d,Ih"}, {zLD,"d,Il"}, {zLD,"d,X"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zLD,"e,Ih"}, {zLD,"e,Il"}, {zLD,"e,X"}, {zDB,"?"},
+ {zLD,"Ih,b"}, {zLD,"Ih,c"}, {zLD,"Ih,d"}, {zLD,"Ih,e"},
+ {zLD,"Ih,Ih"}, {zLD,"Ih,Il"}, {zLD,"h,X"}, {zLD,"Ih,a"},
+ {zLD,"Il,b"}, {zLD,"Il,c"}, {zLD,"Il,d"}, {zLD,"Il,e"},
+ {zLD,"Il,Ih"}, {zLD,"Il,Il"}, {zLD,"l,X"}, {zLD,"Il,a"},
+ {zLD,"X,b"}, {zLD,"X,c"}, {zLD,"X,d"}, {zLD,"X,e"},
+ {zLD,"X,h"}, {zLD,"X,l"}, {zDB,"?"}, {zLD,"X,a"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zLD,"a,Ih"}, {zLD,"a,Il"}, {zLD,"a,X"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zADD,"a,Ih"}, {zADD,"a,Il"}, {zADD,"a,X"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zADC,"a,Ih"}, {zADC,"a,Il"}, {zADC,"a,X"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zSUB,"Ih"}, {zSUB,"Il"}, {zSUB,"X"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zSBC,"a,Ih"}, {zSBC,"a,Il"}, {zSBC,"a,X"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zAND,"Ih"}, {zAND,"Il"}, {zAND,"X"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zXOR,"Ih"}, {zXOR,"Il"}, {zXOR,"X"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zOR,"Ih"}, {zOR,"Il"}, {zOR,"X"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zCP,"Ih"}, {zCP,"Il"}, {zCP,"X"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"cb"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zPOP,"I"}, {zDB,"?"}, {zEX,"(sp),I"},
+ {zDB,"?"}, {zPUSH,"I"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zJP,"(I)"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zLD,"sp,I"}, {zDB,"?"}, {zDB,"?"},
+ {zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"}
+};
+
+static const z80dasm mnemonic_main[256] =
+{
+ {zNOP,0}, {zLD,"bc,N"}, {zLD,"(bc),a"}, {zINC,"bc"},
+ {zINC,"b"}, {zDEC,"b"}, {zLD,"b,B"}, {zRLCA,0},
+ {zEX,"af,af'"}, {zADD,"hl,bc"}, {zLD,"a,(bc)"}, {zDEC,"bc"},
+ {zINC,"c"}, {zDEC,"c"}, {zLD,"c,B"}, {zRRCA,0},
+ {zDJNZ,"O"}, {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,"(W),hl"}, {zINC,"hl"},
+ {zINC,"h"}, {zDEC,"h"}, {zLD,"h,B"}, {zDAA,0},
+ {zJR,"z,O"}, {zADD,"hl,hl"}, {zLD,"hl,(W)"}, {zDEC,"hl"},
+ {zINC,"l"}, {zDEC,"l"}, {zLD,"l,B"}, {zCPL,0},
+ {zJR,"nc,O"}, {zLD,"sp,N"}, {zLD,"(W),a"}, {zINC,"sp"},
+ {zINC,"(hl)"}, {zDEC,"(hl)"}, {zLD,"(hl),B"}, {zSCF,0},
+ {zJR,"c,O"}, {zADD,"hl,sp"}, {zLD,"a,(W)"}, {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"}, {zOUT,"(P),a"},
+ {zCALL,"nc,A"}, {zPUSH,"de"}, {zSUB,"B"}, {zRST,"V"},
+ {zRET,"c"}, {zEXX,0}, {zJP,"c,A"}, {zIN,"a,(P)"},
+ {zCALL,"c,A"}, {zDB,"dd"}, {zSBC,"a,B"}, {zRST,"V"},
+ {zRET,"po"}, {zPOP,"hl"}, {zJP,"po,A"}, {zEX,"(sp),hl"},
+ {zCALL,"po,A"}, {zPUSH,"hl"}, {zAND,"B"}, {zRST,"V"},
+ {zRET,"pe"}, {zJP,"(hl)"}, {zJP,"pe,A"}, {zEX,"de,hl"},
+ {zCALL,"pe,A"}, {zDB,"ed"}, {zXOR,"B"}, {zRST,"V"},
+ {zRET,"p"}, {zPOP,"af"}, {zJP,"p,A"}, {zDI,0},
+ {zCALL,"p,A"}, {zPUSH,"af"}, {zOR,"B"}, {zRST,"V"},
+ {zRET,"m"}, {zLD,"sp,hl"}, {zJP,"m,A"}, {zEI,0},
+ {zCALL,"m,A"}, {zDB,"fd"}, {zCP,"B"}, {zRST,"V"}
+};
+
+static char sign(INT8 offset)
+{
+ return (offset < 0)? '-':'+';
+}
+
+static int offs(INT8 offset)
+{
+ if (offset < 0) return -offset;
+ return offset;
+}
+
+/****************************************************************************
+ * Disassemble opcode at PC and return number of bytes it takes
+ ****************************************************************************/
+CPU_DISASSEMBLE( z80 )
+{
+ const z80dasm *d;
+ const char *src, *ixy;
+ char *dst;
+ INT8 offset = 0;
+ UINT8 op, op1 = 0;
+ UINT16 ea = 0;
+ int pos = 0;
+
+ ixy = "oops!!";
+ dst = buffer;
+
+ op = oprom[pos++];
+
+ switch (op)
+ {
+ case 0xcb:
+ op = oprom[pos++];
+ d = &mnemonic_cb[op];
+ break;
+ case 0xed:
+ op1 = oprom[pos++];
+ d = &mnemonic_ed[op1];
+ break;
+ case 0xdd:
+ ixy = "ix";
+ op1 = oprom[pos++];
+ if( op1 == 0xcb )
+ {
+ offset = (INT8) opram[pos++];
+ op1 = opram[pos++]; /* fourth byte from opbase.ram! */
+ d = &mnemonic_xx_cb[op1];
+ }
+ else d = &mnemonic_xx[op1];
+ break;
+ case 0xfd:
+ ixy = "iy";
+ op1 = oprom[pos++];
+ if( op1 == 0xcb )
+ {
+ offset = (INT8) opram[pos++];
+ op1 = opram[pos++]; /* fourth byte from opbase.ram! */
+ d = &mnemonic_xx_cb[op1];
+ }
+ else d = &mnemonic_xx[op1];
+ break;
+ default:
+ d = &mnemonic_main[op];
+ break;
+ }
+
+ if( d->arguments )
+ {
+ dst += sprintf(dst, "%-4s ", s_mnemonic[d->mnemonic]);
+ src = d->arguments;
+ while( *src )
+ {
+ switch( *src )
+ {
+ case '?': /* illegal opcode */
+ dst += sprintf( dst, "$%02x,$%02x", op, op1 );
+ break;
+ case 'A':
+ ea = opram[pos+0] + ( 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 'N': /* Immediate 16 bit */
+ ea = opram[pos+0] + ( 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) & 0xffff );
+ break;
+ case 'P': /* Port number */
+ ea = opram[pos++];
+ dst += sprintf( dst, "$%02X", ea );
+ break;
+ case 'V': /* Restart vector */
+ ea = op & 0x38;
+ dst += sprintf( dst, "$%02X", ea );
+ break;
+ case 'W': /* Memory address word */
+ ea = opram[pos+0] + ( opram[pos+1] << 8 );
+ pos += 2;
+ dst += sprintf( dst, "$%04X", ea );
+ break;
+ case 'X':
+ offset = (INT8) opram[pos++];
+ /* fall through */
+ case 'Y':
+ dst += sprintf( dst,"(%s%c$%02x)", ixy, sign(offset), offs(offset) );
+ break;
+ case 'I':
+ dst += sprintf( dst, "%s", ixy);
+ break;
+ default:
+ *dst++ = *src;
+ }
+ src++;
+ }
+ *dst = '\0';
+ }
+ else
+ {
+ dst += sprintf(dst, "%s", s_mnemonic[d->mnemonic]);
+ }
+
+ return pos | s_flags[d->mnemonic] | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/z8000/8000dasm.c b/trunk/src/emu/cpu/z8000/8000dasm.c
new file mode 100644
index 00000000000..85b0a16f635
--- /dev/null
+++ b/trunk/src/emu/cpu/z8000/8000dasm.c
@@ -0,0 +1,322 @@
+/*****************************************************************************
+ *
+ * 8000dasm.c
+ * Portable Z8000(2) emulator
+ * Z8000 disassembler; requires the z8000_exec table to be initialized
+ *
+ * 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"
+#include "z8000.h"
+#include "z8000cpu.h"
+
+static int n[12]; /* opcode nibbles */
+static int b[6]; /* opcode bytes */
+static int w[3]; /* opcode words */
+
+static void GET_OP(const UINT8 *oprom, int i, unsigned offset)
+{
+ UINT16 opcode = (oprom[offset] << 8) | oprom[offset + 1];
+ w[i] = opcode;
+ b[i*2+0] = opcode >> 8;
+ b[i*2+1] = opcode & 0xff;
+ n[i*4+0] = (opcode >> 12) & 0x0f;
+ n[i*4+1] = (opcode >> 8) & 0x0f;
+ n[i*4+2] = (opcode >> 4) & 0x0f;
+ n[i*4+3] = opcode & 0x0f;
+}
+
+static const char *const cc[16] = {
+ "n", "lt", "le", "ule", "pe/ov", "mi", "eq/z", "c/ult",
+ "a", "ge", "gt", "ugt", "po/nov", "pl", "ne/nz", "nc/uge"
+};
+
+static const char *const flg[16] = {
+ "", "p/v", "s", "p/v,s", "z", "p/v,z", "s,z", "p/v,s,z",
+ "c", "p/v,c","s,c", "p/v,s,c", "z,c", "p/v,z,c","s,z,c","p/v,s,z,c"
+};
+
+static const char *const ints[4] = {
+ "", "vi", "nvi", "vi,nvi"
+};
+
+CPU_DISASSEMBLE( z8000 )
+{
+ int new_pc = pc, i, tmp;
+ char *dst = buffer;
+ const char *src;
+ Z8000_exec *o;
+ UINT32 flags = 0;
+
+ /* already initialized? */
+ if(z8000_exec == NULL)
+ z8002_init_tables();
+
+ GET_OP(oprom, 0, new_pc - pc);
+ new_pc += 2;
+ switch (pc)
+ {
+ case 0x0000:
+ dst += sprintf(dst, ".word #$%04x ;RST", w[0]);
+ break;
+ case 0x0002:
+ dst += sprintf(dst, ".word #$%04x ;RST FCW", w[0]);
+ break;
+ case 0x0004:
+ dst += sprintf(dst, ".word #$%04x ;RST PC", w[0]);
+ break;
+ default:
+ o = &z8000_exec[w[0]];
+ if (o->size > 1) { GET_OP(oprom, 1, new_pc - pc); new_pc += 2; }
+ if (o->size > 2) { GET_OP(oprom, 2, new_pc - pc); new_pc += 2; }
+ src = o->dasm;
+ flags = o->dasmflags;
+
+ while (*src)
+ {
+ if (*src == '%')
+ {
+ src++;
+ switch (*src) {
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ /* nibble number */
+ i = *src++ - '0';
+ dst += sprintf(dst, "%d", n[i]);
+ break;
+ case '#':
+ /* immediate */
+ src++;
+ switch (*src++) {
+ case 'b': /* imm8 (byte) */
+ i = *src++ - '0';
+ dst += sprintf(dst, "#$%02x", b[i]);
+ break;
+ case 'w': /* imm16 (word) */
+ i = *src++ - '0';
+ dst += sprintf(dst, "#$%04x", w[i]);
+ break;
+ case 'l': /* imm32 (long) */
+ i = *src++ - '0';
+ dst += sprintf(dst, "#$%04x%04x", w[i], w[i+1]);
+ break;
+ }
+ break;
+ case '$':
+ /* absolute immediate 8bit (rl/rr) */
+ src++;
+ i = *src++ - '0';
+ dst += sprintf(dst, "#%d", ((INT8)b[i]<0) ? -(INT8)b[i] : b[i]);
+ break;
+ case '+':
+ /* imm4m1 (inc/dec value) */
+ src++;
+ i = *src++ - '0';
+ dst += sprintf(dst, "%i", n[i] + 1);
+ break;
+ case '*':
+ /* left/right (rotate/shift) */
+ src++;
+ dst += sprintf(dst, "%c", b[2] ? 'r' : 'l');
+ break;
+ case '?':
+ /* imm1or2 (shift/rotate once or twice) */
+ src++;
+ i = *src++ - '0';
+ dst += sprintf(dst, "%c", (n[i] & 2) ? '2' : '1');
+ break;
+ case 'R':
+ src++;
+ tmp = ((n[1] & 0x01) << 16) + (n[3] << 8) + (n[7] & 0x08);
+ switch (tmp)
+ {
+ case 0x000: dst += sprintf(dst, "inirb "); flags = DASMFLAG_STEP_OVER; break;
+ case 0x008: dst += sprintf(dst, "inib "); break;
+ case 0x010: dst += sprintf(dst, "sinirb"); flags = DASMFLAG_STEP_OVER; break;
+ case 0x018: dst += sprintf(dst, "sinib "); break;
+ case 0x020: dst += sprintf(dst, "otirb "); flags = DASMFLAG_STEP_OVER; break;
+ case 0x028: dst += sprintf(dst, "outib "); break;
+ case 0x030: dst += sprintf(dst, "soutib"); break;
+ case 0x038: dst += sprintf(dst, "sotirb"); flags = DASMFLAG_STEP_OVER; break;
+ case 0x040: dst += sprintf(dst, "inb "); break;
+ case 0x048: dst += sprintf(dst, "inb "); break;
+ case 0x050: dst += sprintf(dst, "sinb "); break;
+ case 0x058: dst += sprintf(dst, "sinb "); break;
+ case 0x060: dst += sprintf(dst, "outb "); break;
+ case 0x068: dst += sprintf(dst, "outb "); break;
+ case 0x070: dst += sprintf(dst, "soutb "); break;
+ case 0x078: dst += sprintf(dst, "soutb "); break;
+ case 0x080: dst += sprintf(dst, "indrb "); flags = DASMFLAG_STEP_OVER; break;
+ case 0x088: dst += sprintf(dst, "indb "); break;
+ case 0x090: dst += sprintf(dst, "sindrb"); flags = DASMFLAG_STEP_OVER; break;
+ case 0x098: dst += sprintf(dst, "sindb "); break;
+ case 0x0a0: dst += sprintf(dst, "otdrb "); flags = DASMFLAG_STEP_OVER; break;
+ case 0x0a8: dst += sprintf(dst, "outdb "); break;
+ case 0x0b0: dst += sprintf(dst, "soutdb"); break;
+ case 0x0b8: dst += sprintf(dst, "sotdrb"); flags = DASMFLAG_STEP_OVER; break;
+ case 0x100: dst += sprintf(dst, "inir "); flags = DASMFLAG_STEP_OVER; break;
+ case 0x108: dst += sprintf(dst, "ini "); break;
+ case 0x110: dst += sprintf(dst, "sinir "); flags = DASMFLAG_STEP_OVER; break;
+ case 0x118: dst += sprintf(dst, "sini "); break;
+ case 0x120: dst += sprintf(dst, "otir "); flags = DASMFLAG_STEP_OVER; break;
+ case 0x128: dst += sprintf(dst, "outi "); break;
+ case 0x130: dst += sprintf(dst, "souti "); break;
+ case 0x138: dst += sprintf(dst, "sotir "); flags = DASMFLAG_STEP_OVER; break;
+ case 0x140: dst += sprintf(dst, "in "); break;
+ case 0x148: dst += sprintf(dst, "in "); break;
+ case 0x150: dst += sprintf(dst, "sin "); break;
+ case 0x158: dst += sprintf(dst, "sin "); break;
+ case 0x160: dst += sprintf(dst, "out "); break;
+ case 0x168: dst += sprintf(dst, "out "); break;
+ case 0x170: dst += sprintf(dst, "sout "); break;
+ case 0x178: dst += sprintf(dst, "sout "); break;
+ case 0x180: dst += sprintf(dst, "indr "); flags = DASMFLAG_STEP_OVER; break;
+ case 0x188: dst += sprintf(dst, "ind "); break;
+ case 0x190: dst += sprintf(dst, "sindr "); flags = DASMFLAG_STEP_OVER; break;
+ case 0x198: dst += sprintf(dst, "sind "); break;
+ case 0x1a0: dst += sprintf(dst, "otdr "); flags = DASMFLAG_STEP_OVER; break;
+ case 0x1a8: dst += sprintf(dst, "outd "); break;
+ case 0x1b0: dst += sprintf(dst, "soutd "); break;
+ case 0x1b8: dst += sprintf(dst, "sotdr "); flags = DASMFLAG_STEP_OVER; break;
+ default:
+ dst += sprintf(dst, "??????");
+ }
+ break;
+ case 'a':
+ /* address */
+ src++;
+ i = *src++ - '0';
+ dst += sprintf(dst, "$%04x", w[i]);
+ break;
+ case 'c':
+ /* condition code */
+ src++;
+ i = *src++ - '0';
+ if (n[i] == 8) { /* always? */
+ /* skip following comma */
+ if (*src == ',')
+ src++;
+ }
+ else dst += sprintf(dst, "%s", cc[n[i]]);
+ break;
+ case 'd':
+ /* displacement */
+ src++;
+ i = *src++ - '0';
+ switch (i) {
+ case 0: /* disp7 */
+ tmp = new_pc - 2 * (w[0] & 0x7f);
+ dst += sprintf(dst, "#$%04x", tmp);
+ break;
+ case 1: /* disp8 */
+ tmp = new_pc + 2 * (INT8)(w[0] & 0xff);
+ dst += sprintf(dst, "#$%04x", tmp);
+ break;
+ case 2: /* disp12 */
+ tmp = w[0] & 0x7ff;
+ if (w[0] & 0x800)
+ tmp = new_pc + 0x1000 -2 * tmp;
+ else
+ tmp = new_pc + -2 * tmp;
+ dst += sprintf(dst, "#$%04x", tmp);
+ break;
+ }
+ break;
+ case 'f':
+ /* flag (setflg/resflg/comflg) */
+ src++;
+ i = *src++ - '0';
+ dst += sprintf(dst, "%s", flg[n[i]]);
+ break;
+ case 'i':
+ /* interrupts */
+ src++;
+ i = *src++ - '0';
+ dst += sprintf(dst, "%s", ints[n[i] & 3]);
+ break;
+ case 'p':
+ /* disp16 (pc relative) */
+ src++;
+ i = *src++ - '0';
+ dst += sprintf(dst, "$%04x", new_pc + w[i]);
+ break;
+ case 'r':
+ /* register */
+ src++;
+ switch (*src++) {
+ case 'b':
+ /* byte */
+ i = *src++ - '0';
+ if (n[i] & 8)
+ dst += sprintf(dst, "rl%d", n[i] & 7);
+ else
+ dst += sprintf(dst, "rh%d", n[i]);
+ break;
+ case 'w':
+ /* word */
+ i = *src++ - '0';
+ dst += sprintf(dst, "r%d", n[i]);
+ break;
+ case 'l':
+ /* long */
+ i = *src++ - '0';
+ dst += sprintf(dst, "rr%d", n[i]);
+ break;
+ case 'q':
+ /* quad word (long long) */
+ i = *src++ - '0';
+ dst += sprintf(dst, "rq%d", n[i]);
+ break;
+ }
+ break;
+ default:
+ *dst++ = '%';
+ *dst++ = *src++;
+ break;
+ }
+ } else *dst++ = *src++;
+ }
+ *dst = '\0';
+ break;
+ }
+ return (new_pc - pc) | flags | DASMFLAG_SUPPORTED;
+}
+
diff --git a/trunk/src/emu/cpu/z8000/makedab.c b/trunk/src/emu/cpu/z8000/makedab.c
new file mode 100644
index 00000000000..e9ec0fe91c6
--- /dev/null
+++ b/trunk/src/emu/cpu/z8000/makedab.c
@@ -0,0 +1,87 @@
+#include <stdio.h>
+
+#define CF 0x100
+#define HF 0x200
+#define DF 0x400
+
+int dab[0x800];
+
+int main(int ac, char **av)
+{
+ int i;
+
+ for (i = 0; i < DF; i++) {
+ if (i & CF) {
+ if (i & 0x0f < 0x0a)
+ dab[i] = CF | ((i + 0x60) & 0xff);
+ else
+ dab[i] = CF | ((i + 0x66) & 0xff);
+ } else {
+ if (i & HF) {
+ if (i & 0xf0 < 0xa0)
+ dab[i] = ((i + 0x06) & 0xff);
+ else
+ dab[i] = CF | ((i + 0x66) & 0xff);
+ } else {
+ if ((i & 0xf0) < 0xa0 && (i & 0x0f) < 0x0a)
+ dab[i] = i & 0xff;
+ else if ((i & 0xf0) < 0x90 && (i & 0x0f) >= 0x0a)
+ dab[i] = ((i + 0x06) & 0xff);
+ else if ((i & 0xf0) >= 0xa0 && (i & 0x0f) < 0x0a)
+ dab[i] = CF | ((i + 0x60) & 0xff);
+ else if ((i & 0xf0) >= 0x90 && (i & 0x0f) >= 0x0a)
+ dab[i] = CF | ((i + 0x66) & 0xff);
+ else {
+ fprintf(stderr, "unhandled $%04x\n", i);
+ return 1;
+ }
+
+ }
+ }
+
+ if (i & CF) {
+ if (i & HF) {
+ dab[DF+i] = CF | ((i + 0x9a) & 0xff);
+ } else {
+ dab[DF+i] = CF | ((i + 0xa0) & 0xff);
+ }
+ } else {
+ if (i & HF) {
+ dab[DF+i] = CF | ((i + 0xfa) & 0xff);
+ } else {
+ dab[DF+i] = (i & 0xff);
+ }
+ }
+ }
+
+ printf("/************************************************ \n");
+ printf(" * Result table for Z8000 DAB instruction \n");
+ printf(" * \n");
+ printf(" * bits description \n");
+ printf(" * ---------------------------------------------- \n");
+ printf(" * 0..7 destination value \n");
+ printf(" * 8 carry flag before \n");
+ printf(" * 9 half carry flag before \n");
+ printf(" * 10 D flag (0 add/adc, 1 sub/sbc) \n");
+ printf(" * \n");
+ printf(" * result description \n");
+ printf(" * ---------------------------------------------- \n");
+ printf(" * 0..7 result value \n");
+ printf(" * 8 carry flag after \n");
+ printf(" ************************************************/\n");
+ printf("static const UINT16 Z8000_dab[0x800] = {\n");
+ for (i = 0; i < 0x800; i++) {
+ if ((i & 0x3ff) == 0) {
+ if (i & 0x400)
+ printf("\t/* sub/sbc results */\n");
+ else
+ printf("\t/* add/adc results */\n");
+ }
+ if ((i & 7) == 0) printf("\t");
+ printf("0x%03x,",dab[i]);
+ if ((i & 7) == 7) printf("\n");
+ }
+ printf("};\n");
+
+ return 0;
+}
diff --git a/trunk/src/emu/cpu/z8000/z8000.c b/trunk/src/emu/cpu/z8000/z8000.c
new file mode 100644
index 00000000000..09f69555c83
--- /dev/null
+++ b/trunk/src/emu/cpu/z8000/z8000.c
@@ -0,0 +1,719 @@
+/*****************************************************************************
+ *
+ * z8000.c
+ * Portable Z8000(2) emulator
+ * Z8000 MAME interface
+ *
+ * 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.
+ *
+ * TODO:
+ * - make the z8001 opcodes to be dynamic (i.e. to take segmented mode flag into account and use the non-segmented mode)
+ * - dissassembler doesn't work at all with the z8001
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "z8000.h"
+
+#define VERBOSE 0
+
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+typedef union _z8000_reg_file z8000_reg_file;
+union _z8000_reg_file
+{
+ UINT8 B[16]; /* RL0,RH0,RL1,RH1...RL7,RH7 */
+ UINT16 W[16]; /* R0,R1,R2...R15 */
+ UINT32 L[8]; /* RR0,RR2,RR4..RR14 */
+ UINT64 Q[4]; /* RQ0,RQ4,..RQ12 */
+};
+
+/* In z8000cpu.h: typedef struct _z8000_state z8000_state; */
+struct _z8000_state
+{
+ UINT16 op[4]; /* opcodes/data of current instruction */
+ UINT32 ppc; /* previous program counter */
+ UINT32 pc; /* program counter */
+ UINT16 psap; /* program status pointer */
+ UINT16 fcw; /* flags and control word */
+ UINT16 refresh; /* refresh timer/counter */
+ UINT16 nsp; /* system stack pointer */
+ UINT16 irq_req; /* CPU is halted, interrupt or trap request */
+ UINT16 irq_srv; /* serviced interrupt request */
+ UINT16 irq_vec; /* interrupt vector */
+ z8000_reg_file regs;/* registers */
+ int nmi_state; /* NMI line state */
+ int irq_state[2]; /* IRQ line states (NVI, VI) */
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *io;
+ int icount;
+};
+
+#include "z8000cpu.h"
+
+INLINE z8000_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == Z8001 || device->type() == Z8002);
+ return (z8000_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/* opcode execution table */
+Z8000_exec *z8000_exec = NULL;
+
+/* zero, sign and parity flags for logical byte operations */
+static UINT8 z8000_zsp[256];
+
+/* conversion table for Z8000 DAB opcode */
+#include "z8000dab.h"
+
+INLINE UINT16 RDOP(z8000_state *cpustate)
+{
+ UINT16 res = cpustate->direct->read_decrypted_word(cpustate->pc);
+ cpustate->pc += 2;
+ return res;
+}
+
+INLINE UINT8 RDMEM_B(z8000_state *cpustate, UINT32 addr)
+{
+ return cpustate->program->read_byte(addr);
+}
+
+INLINE UINT16 RDMEM_W(z8000_state *cpustate, UINT32 addr)
+{
+ addr &= ~1;
+ return cpustate->program->read_word(addr);
+}
+
+INLINE UINT32 RDMEM_L(z8000_state *cpustate, UINT32 addr)
+{
+ UINT32 result;
+ addr &= ~1;
+ result = cpustate->program->read_word(addr) << 16;
+ return result + cpustate->program->read_word(addr + 2);
+}
+
+INLINE void WRMEM_B(z8000_state *cpustate, UINT32 addr, UINT8 value)
+{
+ cpustate->program->write_byte(addr, value);
+}
+
+INLINE void WRMEM_W(z8000_state *cpustate, UINT32 addr, UINT16 value)
+{
+ addr &= ~1;
+ cpustate->program->write_word(addr, value);
+}
+
+INLINE void WRMEM_L(z8000_state *cpustate, UINT32 addr, UINT32 value)
+{
+ addr &= ~1;
+ cpustate->program->write_word(addr, value >> 16);
+ cpustate->program->write_word((UINT16)(addr + 2), value & 0xffff);
+}
+
+INLINE UINT8 RDPORT_B(z8000_state *cpustate, int mode, UINT16 addr)
+{
+ if(mode == 0)
+ {
+ return cpustate->io->read_byte(addr);
+ }
+ else
+ {
+ /* how to handle MMU reads? */
+ return 0x00;
+ }
+}
+
+INLINE UINT16 RDPORT_W(z8000_state *cpustate, int mode, UINT16 addr)
+{
+ if(mode == 0)
+ {
+ return cpustate->io->read_byte((UINT16)(addr)) +
+ (cpustate->io->read_byte((UINT16)(addr+1)) << 8);
+ }
+ else
+ {
+ /* how to handle MMU reads? */
+ return 0x0000;
+ }
+}
+
+INLINE void WRPORT_B(z8000_state *cpustate, int mode, UINT16 addr, UINT8 value)
+{
+ if(mode == 0)
+ {
+ cpustate->io->write_byte(addr,value);
+ }
+ else
+ {
+ /* how to handle MMU writes? */
+ }
+}
+
+INLINE void WRPORT_W(z8000_state *cpustate, int mode, UINT16 addr, UINT16 value)
+{
+ if(mode == 0)
+ {
+ cpustate->io->write_byte((UINT16)(addr),value & 0xff);
+ cpustate->io->write_byte((UINT16)(addr+1),(value >> 8) & 0xff);
+ }
+ else
+ {
+ /* how to handle MMU writes? */
+ }
+}
+
+INLINE UINT16 fetch(z8000_state *cpustate)
+{
+ UINT16 data = cpustate->direct->read_decrypted_word(cpustate->pc);
+
+ cpustate->pc+=2;
+
+ return data;
+}
+
+INLINE void cycles(z8000_state *cpustate, int cycles)
+{
+ cpustate->icount -= cycles;
+}
+
+#include "z8000ops.c"
+#include "z8000tbl.c"
+
+INLINE void set_irq(z8000_state *cpustate, int type)
+{
+ switch ((type >> 8) & 255)
+ {
+ case Z8000_TRAP >> 8:
+ if (cpustate->irq_srv >= Z8000_TRAP)
+ return; /* double TRAP.. very bad :( */
+ cpustate->irq_req = type;
+ break;
+ case Z8000_NMI >> 8:
+ if (cpustate->irq_srv >= Z8000_NMI)
+ return; /* no NMIs inside trap */
+ cpustate->irq_req = type;
+ break;
+ case Z8000_SEGTRAP >> 8:
+ if (cpustate->irq_srv >= Z8000_SEGTRAP)
+ return; /* no SEGTRAPs inside NMI/TRAP */
+ cpustate->irq_req = type;
+ break;
+ case Z8000_NVI >> 8:
+ if (cpustate->irq_srv >= Z8000_NVI)
+ return; /* no NVIs inside SEGTRAP/NMI/TRAP */
+ cpustate->irq_req = type;
+ break;
+ case Z8000_VI >> 8:
+ if (cpustate->irq_srv >= Z8000_VI)
+ return; /* no VIs inside NVI/SEGTRAP/NMI/TRAP */
+ cpustate->irq_req = type;
+ break;
+ case Z8000_SYSCALL >> 8:
+ LOG(("Z8K '%s' SYSCALL $%02x\n", cpustate->device->tag(), type & 0xff));
+ cpustate->irq_req = type;
+ break;
+ default:
+ logerror("Z8000 invalid Cause_Interrupt %04x\n", type);
+ return;
+ }
+ /* set interrupt request flag, reset HALT flag */
+ cpustate->irq_req = type & ~Z8000_HALT;
+}
+
+
+INLINE void Interrupt(z8000_state *cpustate)
+{
+ UINT16 fcw = cpustate->fcw;
+
+ if (cpustate->irq_req & Z8000_NVI)
+ {
+ int type = (*cpustate->irq_callback)(cpustate->device, 0);
+ set_irq(cpustate, type);
+ }
+
+ if (cpustate->irq_req & Z8000_VI)
+ {
+ int type = (*cpustate->irq_callback)(cpustate->device, 1);
+ set_irq(cpustate, type);
+ }
+
+ /* trap ? */
+ if (cpustate->irq_req & Z8000_TRAP)
+ {
+ CHANGE_FCW(cpustate, fcw | F_S_N);/* swap to system stack */
+ PUSHW(cpustate, SP, cpustate->pc); /* save current cpustate->pc */
+ PUSHW(cpustate, SP, fcw); /* save current cpustate->fcw */
+ PUSHW(cpustate, SP, cpustate->irq_req); /* save interrupt/trap type tag */
+ cpustate->irq_srv = cpustate->irq_req;
+ cpustate->irq_req &= ~Z8000_TRAP;
+ cpustate->pc = TRAP;
+ LOG(("Z8K '%s' trap $%04x\n", cpustate->device->tag(), cpustate->pc));
+ }
+ else
+ if (cpustate->irq_req & Z8000_SYSCALL)
+ {
+ CHANGE_FCW(cpustate, fcw | F_S_N);/* swap to system stack */
+ PUSHW(cpustate, SP, cpustate->pc); /* save current cpustate->pc */
+ PUSHW(cpustate, SP, fcw); /* save current cpustate->fcw */
+ PUSHW(cpustate, SP, cpustate->irq_req); /* save interrupt/trap type tag */
+ cpustate->irq_srv = cpustate->irq_req;
+ cpustate->irq_req &= ~Z8000_SYSCALL;
+ cpustate->pc = SYSCALL;
+ LOG(("Z8K '%s' syscall $%04x\n", cpustate->device->tag(), cpustate->pc));
+ }
+ else
+ if (cpustate->irq_req & Z8000_SEGTRAP)
+ {
+ CHANGE_FCW(cpustate, fcw | F_S_N);/* swap to system stack */
+ PUSHW(cpustate, SP, cpustate->pc); /* save current cpustate->pc */
+ PUSHW(cpustate, SP, fcw); /* save current cpustate->fcw */
+ PUSHW(cpustate, SP, cpustate->irq_req); /* save interrupt/trap type tag */
+ cpustate->irq_srv = cpustate->irq_req;
+ cpustate->irq_req &= ~Z8000_SEGTRAP;
+ cpustate->pc = SEGTRAP;
+ LOG(("Z8K '%s' segtrap $%04x\n", cpustate->device->tag(), cpustate->pc));
+ }
+ else
+ if (cpustate->irq_req & Z8000_NMI)
+ {
+ CHANGE_FCW(cpustate, fcw | F_S_N);/* swap to system stack */
+ PUSHW(cpustate, SP, cpustate->pc); /* save current cpustate->pc */
+ PUSHW(cpustate, SP, fcw); /* save current cpustate->fcw */
+ PUSHW(cpustate, SP, cpustate->irq_req); /* save interrupt/trap type tag */
+ cpustate->irq_srv = cpustate->irq_req;
+ fcw = RDMEM_W(cpustate, NMI);
+ cpustate->pc = RDMEM_W(cpustate, NMI + 2);
+ cpustate->irq_req &= ~Z8000_NMI;
+ CHANGE_FCW(cpustate, fcw);
+ cpustate->pc = NMI;
+ LOG(("Z8K '%s' NMI $%04x\n", cpustate->device->tag(), cpustate->pc));
+ }
+ else
+ if ((cpustate->irq_req & Z8000_NVI) && (cpustate->fcw & F_NVIE))
+ {
+ CHANGE_FCW(cpustate, fcw | F_S_N);/* swap to system stack */
+ PUSHW(cpustate, SP, cpustate->pc); /* save current cpustate->pc */
+ PUSHW(cpustate, SP, fcw); /* save current cpustate->fcw */
+ PUSHW(cpustate, SP, cpustate->irq_req); /* save interrupt/trap type tag */
+ cpustate->irq_srv = cpustate->irq_req;
+ fcw = RDMEM_W(cpustate, NVI);
+ cpustate->pc = RDMEM_W(cpustate, NVI + 2);
+ cpustate->irq_req &= ~Z8000_NVI;
+ CHANGE_FCW(cpustate, fcw);
+ LOG(("Z8K '%s' NVI $%04x\n", cpustate->device->tag(), cpustate->pc));
+ }
+ else
+ if ((cpustate->irq_req & Z8000_VI) && (cpustate->fcw & F_VIE))
+ {
+ CHANGE_FCW(cpustate, fcw | F_S_N);/* swap to system stack */
+ PUSHW(cpustate, SP, cpustate->pc); /* save current cpustate->pc */
+ PUSHW(cpustate, SP, fcw); /* save current cpustate->fcw */
+ PUSHW(cpustate, SP, cpustate->irq_req); /* save interrupt/trap type tag */
+ cpustate->irq_srv = cpustate->irq_req;
+ fcw = RDMEM_W(cpustate, cpustate->irq_vec);
+ cpustate->pc = RDMEM_W(cpustate, VEC00 + 2 * (cpustate->irq_req & 0xff));
+ cpustate->irq_req &= ~Z8000_VI;
+ CHANGE_FCW(cpustate, fcw);
+ LOG(("Z8K '%s' VI [$%04x/$%04x] fcw $%04x, pc $%04x\n", cpustate->device->tag(), cpustate->irq_vec, VEC00 + VEC00 + 2 * (cpustate->irq_req & 0xff), cpustate->fcw, cpustate->pc));
+ }
+}
+
+static CPU_INIT( z8001 )
+{
+ z8000_state *cpustate = get_safe_token(device);
+
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->io = device->space(AS_IO);
+
+ /* already initialized? */
+ if(z8000_exec == NULL)
+ z8001_init_tables();
+}
+
+static CPU_INIT( z8002 )
+{
+ z8000_state *cpustate = get_safe_token(device);
+
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->io = device->space(AS_IO);
+
+ /* already initialized? */
+ if(z8000_exec == NULL)
+ z8002_init_tables();
+}
+
+static CPU_RESET( z8001 )
+{
+ z8000_state *cpustate = get_safe_token(device);
+
+ device_irq_callback 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->fcw = RDMEM_W(cpustate, 2); /* get reset cpustate->fcw */
+ if(cpustate->fcw & F_SEG)
+ {
+ cpustate->pc = ((RDMEM_W(cpustate, 4) & 0x0700) << 8) | (RDMEM_W(cpustate, 6) & 0xffff); /* get reset cpustate->pc */
+ }
+ else
+ {
+ cpustate->pc = RDMEM_W(cpustate, 4); /* get reset cpustate->pc */
+ }
+}
+
+static CPU_RESET( z8002 )
+{
+ z8000_state *cpustate = get_safe_token(device);
+
+ device_irq_callback 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->fcw = RDMEM_W(cpustate, 2); /* get reset cpustate->fcw */
+ cpustate->pc = RDMEM_W(cpustate, 4); /* get reset cpustate->pc */
+}
+
+static CPU_EXIT( z8000 )
+{
+ z8000_deinit_tables();
+}
+
+static CPU_EXECUTE( z8000 )
+{
+ z8000_state *cpustate = get_safe_token(device);
+
+ do
+ {
+ /* any interrupt request pending? */
+ if (cpustate->irq_req)
+ Interrupt(cpustate);
+
+ debugger_instruction_hook(device, cpustate->pc);
+
+ if (cpustate->irq_req & Z8000_HALT)
+ {
+ cpustate->icount = 0;
+ }
+ else
+ {
+ Z8000_exec *exec;
+ cpustate->op[0] = RDOP(cpustate);
+ exec = &z8000_exec[cpustate->op[0]];
+
+ if (exec->size > 1)
+ cpustate->op[1] = RDOP(cpustate);
+ if (exec->size > 2)
+ cpustate->op[2] = RDOP(cpustate);
+
+ cpustate->icount -= exec->cycles;
+ (*exec->opcode)(cpustate);
+ }
+ } while (cpustate->icount > 0);
+
+}
+
+static void set_irq_line(z8000_state *cpustate, int irqline, int state)
+{
+ if (irqline == INPUT_LINE_NMI)
+ {
+ if (cpustate->nmi_state == state)
+ return;
+
+ cpustate->nmi_state = state;
+
+ if (state != CLEAR_LINE)
+ {
+ if (cpustate->irq_srv >= Z8000_NMI) /* no NMIs inside trap */
+ return;
+ cpustate->irq_req = Z8000_NMI;
+ cpustate->irq_vec = NMI;
+ }
+ }
+ else if (irqline < 2)
+ {
+ cpustate->irq_state[irqline] = state;
+ if (irqline == 0)
+ {
+ if (state == CLEAR_LINE)
+ {
+ if (!(cpustate->fcw & F_NVIE))
+ cpustate->irq_req &= ~Z8000_NVI;
+ }
+ else
+ {
+ if (cpustate->fcw & F_NVIE)
+ cpustate->irq_req |= Z8000_NVI;
+ }
+ }
+ else
+ {
+ if (state == CLEAR_LINE)
+ {
+ if (!(cpustate->fcw & F_VIE))
+ cpustate->irq_req &= ~Z8000_VI;
+ }
+ else
+ {
+ if (cpustate->fcw & F_VIE)
+ cpustate->irq_req |= Z8000_VI;
+ }
+ }
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( z8002 )
+{
+ z8000_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_NMI: set_irq_line(cpustate, INPUT_LINE_NMI, 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_PC: cpustate->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + Z8000_PC: cpustate->pc = info->i; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + Z8000_NSP: cpustate->nsp = info->i; break;
+ case CPUINFO_INT_REGISTER + Z8000_FCW: cpustate->fcw = info->i; break;
+ case CPUINFO_INT_REGISTER + Z8000_PSAP: cpustate->psap = info->i; break;
+ case CPUINFO_INT_REGISTER + Z8000_REFRESH: cpustate->refresh = info->i; break;
+ case CPUINFO_INT_REGISTER + Z8000_IRQ_REQ: cpustate->irq_req = info->i; break;
+ case CPUINFO_INT_REGISTER + Z8000_IRQ_SRV: cpustate->irq_srv = info->i; break;
+ case CPUINFO_INT_REGISTER + Z8000_IRQ_VEC: cpustate->irq_vec = info->i; break;
+ case CPUINFO_INT_REGISTER + Z8000_R0: cpustate->RW( 0) = info->i; break;
+ case CPUINFO_INT_REGISTER + Z8000_R1: cpustate->RW( 1) = info->i; break;
+ case CPUINFO_INT_REGISTER + Z8000_R2: cpustate->RW( 2) = info->i; break;
+ case CPUINFO_INT_REGISTER + Z8000_R3: cpustate->RW( 3) = info->i; break;
+ case CPUINFO_INT_REGISTER + Z8000_R4: cpustate->RW( 4) = info->i; break;
+ case CPUINFO_INT_REGISTER + Z8000_R5: cpustate->RW( 5) = info->i; break;
+ case CPUINFO_INT_REGISTER + Z8000_R6: cpustate->RW( 6) = info->i; break;
+ case CPUINFO_INT_REGISTER + Z8000_R7: cpustate->RW( 7) = info->i; break;
+ case CPUINFO_INT_REGISTER + Z8000_R8: cpustate->RW( 8) = info->i; break;
+ case CPUINFO_INT_REGISTER + Z8000_R9: cpustate->RW( 9) = info->i; break;
+ case CPUINFO_INT_REGISTER + Z8000_R10: cpustate->RW(10) = info->i; break;
+ case CPUINFO_INT_REGISTER + Z8000_R11: cpustate->RW(11) = info->i; break;
+ case CPUINFO_INT_REGISTER + Z8000_R12: cpustate->RW(12) = info->i; break;
+ case CPUINFO_INT_REGISTER + Z8000_R13: cpustate->RW(13) = info->i; break;
+ case CPUINFO_INT_REGISTER + Z8000_R14: cpustate->RW(14) = info->i; break;
+ case CPUINFO_INT_REGISTER + Z8000_R15: cpustate->RW(15) = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( z8002 )
+{
+ z8000_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(z8000_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 = 2; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 6; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 2; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 744; 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 = 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 + INPUT_LINE_NMI: info->i = cpustate->nmi_state; 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_PREVIOUSPC: info->i = cpustate->ppc; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + Z8000_PC: info->i = cpustate->pc; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + Z8000_NSP: info->i = cpustate->nsp; break;
+ case CPUINFO_INT_REGISTER + Z8000_FCW: info->i = cpustate->fcw; break;
+ case CPUINFO_INT_REGISTER + Z8000_PSAP: info->i = cpustate->psap; break;
+ case CPUINFO_INT_REGISTER + Z8000_REFRESH: info->i = cpustate->refresh; break;
+ case CPUINFO_INT_REGISTER + Z8000_IRQ_REQ: info->i = cpustate->irq_req; break;
+ case CPUINFO_INT_REGISTER + Z8000_IRQ_SRV: info->i = cpustate->irq_srv; break;
+ case CPUINFO_INT_REGISTER + Z8000_IRQ_VEC: info->i = cpustate->irq_vec; break;
+ case CPUINFO_INT_REGISTER + Z8000_R0: info->i = cpustate->RW( 0); break;
+ case CPUINFO_INT_REGISTER + Z8000_R1: info->i = cpustate->RW( 1); break;
+ case CPUINFO_INT_REGISTER + Z8000_R2: info->i = cpustate->RW( 2); break;
+ case CPUINFO_INT_REGISTER + Z8000_R3: info->i = cpustate->RW( 3); break;
+ case CPUINFO_INT_REGISTER + Z8000_R4: info->i = cpustate->RW( 4); break;
+ case CPUINFO_INT_REGISTER + Z8000_R5: info->i = cpustate->RW( 5); break;
+ case CPUINFO_INT_REGISTER + Z8000_R6: info->i = cpustate->RW( 6); break;
+ case CPUINFO_INT_REGISTER + Z8000_R7: info->i = cpustate->RW( 7); break;
+ case CPUINFO_INT_REGISTER + Z8000_R8: info->i = cpustate->RW( 8); break;
+ case CPUINFO_INT_REGISTER + Z8000_R9: info->i = cpustate->RW( 9); break;
+ case CPUINFO_INT_REGISTER + Z8000_R10: info->i = cpustate->RW(10); break;
+ case CPUINFO_INT_REGISTER + Z8000_R11: info->i = cpustate->RW(11); break;
+ case CPUINFO_INT_REGISTER + Z8000_R12: info->i = cpustate->RW(12); break;
+ case CPUINFO_INT_REGISTER + Z8000_R13: info->i = cpustate->RW(13); break;
+ case CPUINFO_INT_REGISTER + Z8000_R14: info->i = cpustate->RW(14); break;
+ case CPUINFO_INT_REGISTER + Z8000_R15: info->i = cpustate->RW(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(z8002); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(z8002); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(z8002); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(z8000); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(z8000); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(z8000);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, "Z8002"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Zilog Z8000"); 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;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
+ cpustate->fcw & 0x8000 ? 's':'.',
+ cpustate->fcw & 0x4000 ? 'n':'.',
+ cpustate->fcw & 0x2000 ? 'e':'.',
+ cpustate->fcw & 0x1000 ? '2':'.',
+ cpustate->fcw & 0x0800 ? '1':'.',
+ cpustate->fcw & 0x0400 ? '?':'.',
+ cpustate->fcw & 0x0200 ? '?':'.',
+ cpustate->fcw & 0x0100 ? '?':'.',
+ cpustate->fcw & 0x0080 ? 'C':'.',
+ cpustate->fcw & 0x0040 ? 'Z':'.',
+ cpustate->fcw & 0x0020 ? 'S':'.',
+ cpustate->fcw & 0x0010 ? 'V':'.',
+ cpustate->fcw & 0x0008 ? 'D':'.',
+ cpustate->fcw & 0x0004 ? 'H':'.',
+ cpustate->fcw & 0x0002 ? '?':'.',
+ cpustate->fcw & 0x0001 ? '?':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + Z8000_PC: sprintf(info->s, "pc :%08X", cpustate->pc); break;
+ case CPUINFO_STR_REGISTER + Z8000_NSP: sprintf(info->s, "SP :%04X", cpustate->nsp); break;
+ case CPUINFO_STR_REGISTER + Z8000_FCW: sprintf(info->s, "fcw:%04X", cpustate->fcw); break;
+ case CPUINFO_STR_REGISTER + Z8000_PSAP: sprintf(info->s, "nsp:%04X", cpustate->psap); break;
+ case CPUINFO_STR_REGISTER + Z8000_REFRESH: sprintf(info->s, "REFR:%04X", cpustate->refresh); break;
+ case CPUINFO_STR_REGISTER + Z8000_IRQ_REQ: sprintf(info->s, "IRQR:%04X", cpustate->irq_req); break;
+ case CPUINFO_STR_REGISTER + Z8000_IRQ_SRV: sprintf(info->s, "IRQS:%04X", cpustate->irq_srv); break;
+ case CPUINFO_STR_REGISTER + Z8000_IRQ_VEC: sprintf(info->s, "IRQV:%04X", cpustate->irq_vec); break;
+ case CPUINFO_STR_REGISTER + Z8000_R0: sprintf(info->s, "R0 :%04X", cpustate->RW(0)); break;
+ case CPUINFO_STR_REGISTER + Z8000_R1: sprintf(info->s, "R1 :%04X", cpustate->RW(1)); break;
+ case CPUINFO_STR_REGISTER + Z8000_R2: sprintf(info->s, "R2 :%04X", cpustate->RW(2)); break;
+ case CPUINFO_STR_REGISTER + Z8000_R3: sprintf(info->s, "R3 :%04X", cpustate->RW(3)); break;
+ case CPUINFO_STR_REGISTER + Z8000_R4: sprintf(info->s, "R4 :%04X", cpustate->RW(4)); break;
+ case CPUINFO_STR_REGISTER + Z8000_R5: sprintf(info->s, "R5 :%04X", cpustate->RW(5)); break;
+ case CPUINFO_STR_REGISTER + Z8000_R6: sprintf(info->s, "R6 :%04X", cpustate->RW(6)); break;
+ case CPUINFO_STR_REGISTER + Z8000_R7: sprintf(info->s, "R7 :%04X", cpustate->RW(7)); break;
+ case CPUINFO_STR_REGISTER + Z8000_R8: sprintf(info->s, "R8 :%04X", cpustate->RW(8)); break;
+ case CPUINFO_STR_REGISTER + Z8000_R9: sprintf(info->s, "R9 :%04X", cpustate->RW(9)); break;
+ case CPUINFO_STR_REGISTER + Z8000_R10: sprintf(info->s, "R10:%04X", cpustate->RW(10)); break;
+ case CPUINFO_STR_REGISTER + Z8000_R11: sprintf(info->s, "R11:%04X", cpustate->RW(11)); break;
+ case CPUINFO_STR_REGISTER + Z8000_R12: sprintf(info->s, "R12:%04X", cpustate->RW(12)); break;
+ case CPUINFO_STR_REGISTER + Z8000_R13: sprintf(info->s, "R13:%04X", cpustate->RW(13)); break;
+ case CPUINFO_STR_REGISTER + Z8000_R14: sprintf(info->s, "R14:%04X", cpustate->RW(14)); break;
+ case CPUINFO_STR_REGISTER + Z8000_R15: sprintf(info->s, "R15:%04X", cpustate->RW(15)); break;
+ }
+}
+
+/*
+handling for the z8001
+*/
+
+CPU_GET_INFO( z8001 )
+{
+ switch (state)
+ {
+ 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_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_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(z8001); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(z8001); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Zilog Z8001"); break;
+
+ default: CPU_GET_INFO_CALL(z8002); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(Z8001, z8001);
+DEFINE_LEGACY_CPU_DEVICE(Z8002, z8002);
diff --git a/trunk/src/emu/cpu/z8000/z8000.h b/trunk/src/emu/cpu/z8000/z8000.h
new file mode 100644
index 00000000000..06baa037fec
--- /dev/null
+++ b/trunk/src/emu/cpu/z8000/z8000.h
@@ -0,0 +1,32 @@
+#pragma once
+
+#ifndef __Z8000_H__
+#define __Z8000_H__
+
+
+enum
+{
+ Z8000_PC=1, Z8000_NSP, Z8000_FCW, Z8000_PSAP, Z8000_REFRESH,
+ Z8000_IRQ_REQ, Z8000_IRQ_SRV, Z8000_IRQ_VEC,
+ Z8000_R0, Z8000_R1, Z8000_R2, Z8000_R3,
+ Z8000_R4, Z8000_R5, Z8000_R6, Z8000_R7,
+ Z8000_R8, Z8000_R9, Z8000_R10, Z8000_R11,
+ Z8000_R12, Z8000_R13, Z8000_R14, Z8000_R15
+};
+
+/* Interrupt Types that can be generated by outside sources */
+#define Z8000_TRAP 0x4000 /* internal trap */
+#define Z8000_NMI 0x2000 /* non maskable interrupt */
+#define Z8000_SEGTRAP 0x1000 /* segment trap (Z8001) */
+#define Z8000_NVI 0x0800 /* non vectored interrupt */
+#define Z8000_VI 0x0400 /* vectored interrupt (LSB is vector) */
+#define Z8000_SYSCALL 0x0200 /* system call (lsb is vector) */
+#define Z8000_HALT 0x0100 /* halted flag */
+
+/* PUBLIC FUNCTIONS */
+DECLARE_LEGACY_CPU_DEVICE(Z8001, z8001);
+DECLARE_LEGACY_CPU_DEVICE(Z8002, z8002);
+
+CPU_DISASSEMBLE( z8000 );
+
+#endif /* __Z8000_H__ */
diff --git a/trunk/src/emu/cpu/z8000/z8000cpu.h b/trunk/src/emu/cpu/z8000/z8000cpu.h
new file mode 100644
index 00000000000..36f81371e3f
--- /dev/null
+++ b/trunk/src/emu/cpu/z8000/z8000cpu.h
@@ -0,0 +1,215 @@
+/*****************************************************************************
+ *
+ * z8000cpu.h
+ * Portable Z8000(2) emulator
+ * Macros and types used in z8000.c / z8000ops.c / z8000tbl.c
+ *
+ * Copyright Juergen Buchmueller, all rights reserved.
+ * Bug fixes and MSB_FIRST compliance Ernesto Corvi.
+ *
+ * - 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 is the register file layout:
+ *
+ * BYTE WORD LONG QUAD
+ * msb lsb bits bits bits
+ * RH0 - RL0 R 0 15- 0 RR 0 31-16 RQ 0 63-48
+ * RH1 - RL1 R 1 15- 0 15- 0 47-32
+ * RH2 - RL2 R 2 15- 0 RR 2 31-16 31-16
+ * RH3 - RL3 R 3 15- 0 15- 0 15- 0
+ * RH4 - RL4 R 4 15- 0 RR 4 31-16 RQ 4 63-48
+ * RH5 - RL5 R 5 15- 0 15- 0 47-32
+ * RH6 - RL6 R 6 15- 0 RR 6 31-16 31-16
+ * RH7 - RL7 R 7 15- 0 15- 0 15- 0
+ * R 8 15- 0 RR 8 31-16 RQ 8 63-48
+ * R 9 15- 0 15- 0 47-32
+ * R10 15- 0 RR10 31-16 31-16
+ * R11 15- 0 15- 0 15- 0
+ * R12 15- 0 RR12 31-16 RQ12 63-48
+ * R13 15- 0 15- 0 47-32
+ * R14 15- 0 RR14 31-16 31-16
+ * R15 15- 0 15- 0 15- 0
+ *
+ * Note that for LSB_FIRST machines we have the case that the RR registers
+ * use the lower numbered R registers in the higher bit positions.
+ * And also the RQ registers use the lower numbered RR registers in the
+ * higher bit positions.
+ * That's the reason for the ordering in the following pointer table.
+ **************************************************************************/
+#define RB(n) regs.B[BYTE8_XOR_BE((((n) & 7) << 1) | (((n) & 8) >> 3))]
+#define RW(n) regs.W[BYTE4_XOR_BE(n)]
+#define RL(n) regs.L[BYTE_XOR_BE((n) >> 1)]
+#define RQ(n) regs.Q[(n) >> 2]
+
+/* the register used as stack pointer */
+#define SP 15
+
+/* these vectors are based on cpustate->psap */
+#define RST (cpustate->psap + 0x0000) /* start up cpustate->fcw and cpustate->pc */
+#define EPU (cpustate->psap + 0x0004) /* extension processor unit? trap */
+#define TRAP (cpustate->psap + 0x0008) /* privilege violation trap */
+#define SYSCALL (cpustate->psap + 0x000c) /* system call SC */
+#define SEGTRAP (cpustate->psap + 0x0010) /* segment trap */
+#define NMI (cpustate->psap + 0x0014) /* non maskable interrupt */
+#define NVI (cpustate->psap + 0x0018) /* non vectored interrupt */
+#define VI (cpustate->psap + 0x001c) /* vectored interrupt */
+#define VEC00 (cpustate->psap + 0x001e) /* vector n cpustate->pc value */
+
+/* bits of the cpustate->fcw */
+#define F_SEG 0x8000 /* segmented mode (Z8001 only) */
+#define F_S_N 0x4000 /* system / normal mode */
+#define F_EPU 0x2000 /* extension processor unit? */
+#define F_NVIE 0x1000 /* non vectored interrupt enable */
+#define F_VIE 0x0800 /* vectored interrupt enable */
+#define F_10 0x0400 /* unused */
+#define F_9 0x0200 /* unused */
+#define F_8 0x0100 /* unused */
+#define F_C 0x0080 /* carry flag */
+#define F_Z 0x0040 /* zero flag */
+#define F_S 0x0020 /* sign flag */
+#define F_PV 0x0010 /* parity/overflow flag */
+#define F_DA 0x0008 /* decimal adjust flag (0 add/adc, 1 sub/sbc) */
+#define F_H 0x0004 /* half carry flag (byte arithmetic only) */
+#define F_1 0x0002 /* unused */
+#define F_0 0x0001 /* unused */
+
+/* opcode word numbers in cpustate->op[] array */
+#define OP0 0
+#define OP1 1
+#define OP2 2
+
+/* nibble shift factors for an opcode word */
+/* left to right: 0x1340 -> NIB0=1, NIB1=3, NIB2=4, NIB3=0 */
+#define NIB0 12
+#define NIB1 8
+#define NIB2 4
+#define NIB3 0
+
+/* sign bit masks for byte, word and long */
+#define S08 0x80
+#define S16 0x8000
+#define S32 0x80000000
+
+/* get a single flag bit 0/1 */
+#define GET_C ((cpustate->fcw >> 7) & 1)
+#define GET_Z ((cpustate->fcw >> 6) & 1)
+#define GET_S ((cpustate->fcw >> 5) & 1)
+#define GET_PV ((cpustate->fcw >> 4) & 1)
+#define GET_DA ((cpustate->fcw >> 3) & 1)
+#define GET_H ((cpustate->fcw >> 2) & 1)
+
+/* clear a single flag bit */
+#define CLR_C cpustate->fcw &= ~F_C
+#define CLR_Z cpustate->fcw &= ~F_Z
+#define CLR_S cpustate->fcw &= ~F_S
+#define CLR_P cpustate->fcw &= ~F_PV
+#define CLR_V cpustate->fcw &= ~F_PV
+#define CLR_DA cpustate->fcw &= ~F_DA
+#define CLR_H cpustate->fcw &= ~F_H
+
+/* clear a flag bit combination */
+#define CLR_CZS cpustate->fcw &= ~(F_C|F_Z|F_S)
+#define CLR_CZSP cpustate->fcw &= ~(F_C|F_Z|F_S|F_PV)
+#define CLR_CZSV cpustate->fcw &= ~(F_C|F_Z|F_S|F_PV)
+#define CLR_CZSVH cpustate->fcw &= ~(F_C|F_Z|F_S|F_PV|F_H)
+#define CLR_ZS cpustate->fcw &= ~(F_Z|F_S)
+#define CLR_ZSV cpustate->fcw &= ~(F_Z|F_S|F_PV)
+#define CLR_ZSP cpustate->fcw &= ~(F_Z|F_S|F_PV)
+
+/* set a single flag bit */
+#define SET_C cpustate->fcw |= F_C
+#define SET_Z cpustate->fcw |= F_Z
+#define SET_S cpustate->fcw |= F_S
+#define SET_P cpustate->fcw |= F_PV
+#define SET_V cpustate->fcw |= F_PV
+#define SET_DA cpustate->fcw |= F_DA
+#define SET_H cpustate->fcw |= F_H
+
+/* set a flag bit combination */
+#define SET_SC cpustate->fcw |= F_C | F_S
+
+/* check condition codes */
+#define CC0 (0) /* always false */
+#define CC1 (GET_PV^GET_S) /* less than */
+#define CC2 (GET_Z|(GET_PV^GET_S)) /* less than or equal */
+#define CC3 (GET_Z|GET_C) /* unsigned less than or equal */
+#define CC4 GET_PV /* parity even / overflow */
+#define CC5 GET_S /* minus (signed) */
+#define CC6 GET_Z /* zero / equal */
+#define CC7 GET_C /* carry / unsigned less than */
+
+#define CC8 (1) /* always true */
+#define CC9 !(GET_PV^GET_S) /* greater than or equal */
+#define CCA !(GET_Z|(GET_PV^GET_S)) /* greater than */
+#define CCB !(GET_Z|GET_C) /* unsigned greater than */
+#define CCC !GET_PV /* parity odd / no overflow */
+#define CCD !GET_S /* plus (not signed) */
+#define CCE !GET_Z /* not zero / not equal */
+#define CCF !GET_C /* not carry / unsigned greater than */
+
+/* get data from the opcode words */
+/* o is the opcode word offset */
+/* s is a nibble shift factor */
+#define GET_BIT(o) UINT16 bit = 1 << (cpustate->op[o] & 15)
+#define GET_CCC(o,s) UINT8 cc = (cpustate->op[o] >> (s)) & 15
+
+#define GET_DST(o,s) UINT8 dst = (cpustate->op[o] >> (s)) & 15
+#define GET_SRC(o,s) UINT8 src = (cpustate->op[o] >> (s)) & 15
+#define GET_IDX(o,s) UINT8 idx = (cpustate->op[o] >> (s)) & 15
+#define GET_CNT(o,s) INT8 cnt = (cpustate->op[o] >> (s)) & 15
+#define GET_IMM4(o,s) UINT8 imm4 = (cpustate->op[o] >> (s)) & 15
+
+#define GET_I4M1(o,s) UINT8 i4p1 = ((cpustate->op[o] >> (s)) & 15) + 1
+#define GET_IMM1(o,s) UINT8 imm1 = (cpustate->op[o] >> (s)) & 2
+#define GET_IMM2(o,s) UINT8 imm2 = (cpustate->op[o] >> (s)) & 3
+#define GET_IMM3(o,s) UINT8 imm3 = (cpustate->op[o] >> (s)) & 7
+
+#define GET_IMM8(o) UINT8 imm8 = (UINT8)cpustate->op[o]
+
+#define GET_IMM16(o) UINT16 imm16 = cpustate->op[o]
+#define GET_IMM32 UINT32 imm32 = cpustate->op[2] + (cpustate->op[1] << 16)
+#define GET_DSP7 UINT8 dsp7 = cpustate->op[0] & 127
+#define GET_DSP8 INT8 dsp8 = (INT8)cpustate->op[0]
+#define GET_DSP16 UINT16 dsp16 = cpustate->pc + (INT16)cpustate->op[1]
+#define GET_ADDR(o) UINT16 addr = (UINT16)cpustate->op[o]
+
+typedef struct _z8000_state z8000_state;
+
+/* structure for the opcode definition table */
+typedef struct {
+ int beg, end, step;
+ int size, cycles;
+ void (*opcode)(z8000_state *cpustate);
+ const char *dasm;
+ UINT32 dasmflags;
+} Z8000_init;
+
+/* structure for the opcode execution table / disassembler */
+typedef struct {
+ void (*opcode)(z8000_state *cpustate);
+ int cycles;
+ int size;
+ const char *dasm;
+ UINT32 dasmflags;
+} Z8000_exec;
+
+/* opcode execution table */
+extern Z8000_exec *z8000_exec;
+
+extern void z8001_init_tables(void);
+extern void z8002_init_tables(void);
+extern void z8000_deinit_tables(void);
+
diff --git a/trunk/src/emu/cpu/z8000/z8000dab.h b/trunk/src/emu/cpu/z8000/z8000dab.h
new file mode 100644
index 00000000000..bee36eedaee
--- /dev/null
+++ b/trunk/src/emu/cpu/z8000/z8000dab.h
@@ -0,0 +1,275 @@
+/************************************************
+ * Result table for Z8000 DAB instruction
+ *
+ * bits description
+ * ----------------------------------------------
+ * 0..7 destination value
+ * 8 carry flag before
+ * 9 half carry flag before
+ * 10 D flag (0 add/adc, 1 sub/sbc)
+ *
+ * result description
+ * ----------------------------------------------
+ * 0..7 result value
+ * 8 carry flag after
+ ************************************************/
+static const UINT16 Z8000_dab[0x800] = {
+ /* add/adc results */
+ 0x000,0x001,0x002,0x003,0x004,0x005,0x006,0x007,
+ 0x008,0x009,0x010,0x011,0x012,0x013,0x014,0x015,
+ 0x010,0x011,0x012,0x013,0x014,0x015,0x016,0x017,
+ 0x018,0x019,0x020,0x021,0x022,0x023,0x024,0x025,
+ 0x020,0x021,0x022,0x023,0x024,0x025,0x026,0x027,
+ 0x028,0x029,0x030,0x031,0x032,0x033,0x034,0x035,
+ 0x030,0x031,0x032,0x033,0x034,0x035,0x036,0x037,
+ 0x038,0x039,0x040,0x041,0x042,0x043,0x044,0x045,
+ 0x040,0x041,0x042,0x043,0x044,0x045,0x046,0x047,
+ 0x048,0x049,0x050,0x051,0x052,0x053,0x054,0x055,
+ 0x050,0x051,0x052,0x053,0x054,0x055,0x056,0x057,
+ 0x058,0x059,0x060,0x061,0x062,0x063,0x064,0x065,
+ 0x060,0x061,0x062,0x063,0x064,0x065,0x066,0x067,
+ 0x068,0x069,0x070,0x071,0x072,0x073,0x074,0x075,
+ 0x070,0x071,0x072,0x073,0x074,0x075,0x076,0x077,
+ 0x078,0x079,0x080,0x081,0x082,0x083,0x084,0x085,
+ 0x080,0x081,0x082,0x083,0x084,0x085,0x086,0x087,
+ 0x088,0x089,0x090,0x091,0x092,0x093,0x094,0x095,
+ 0x090,0x091,0x092,0x093,0x094,0x095,0x096,0x097,
+ 0x098,0x099,0x100,0x101,0x102,0x103,0x104,0x105,
+ 0x100,0x101,0x102,0x103,0x104,0x105,0x106,0x107,
+ 0x108,0x109,0x110,0x111,0x112,0x113,0x114,0x115,
+ 0x110,0x111,0x112,0x113,0x114,0x115,0x116,0x117,
+ 0x118,0x119,0x120,0x121,0x122,0x123,0x124,0x125,
+ 0x120,0x121,0x122,0x123,0x124,0x125,0x126,0x127,
+ 0x128,0x129,0x130,0x131,0x132,0x133,0x134,0x135,
+ 0x130,0x131,0x132,0x133,0x134,0x135,0x136,0x137,
+ 0x138,0x139,0x140,0x141,0x142,0x143,0x144,0x145,
+ 0x140,0x141,0x142,0x143,0x144,0x145,0x146,0x147,
+ 0x148,0x149,0x150,0x151,0x152,0x153,0x154,0x155,
+ 0x150,0x151,0x152,0x153,0x154,0x155,0x156,0x157,
+ 0x158,0x159,0x160,0x161,0x162,0x163,0x164,0x165,
+ 0x166,0x167,0x168,0x169,0x16a,0x16b,0x16c,0x16d,
+ 0x16e,0x16f,0x170,0x171,0x172,0x173,0x174,0x175,
+ 0x176,0x177,0x178,0x179,0x17a,0x17b,0x17c,0x17d,
+ 0x17e,0x17f,0x180,0x181,0x182,0x183,0x184,0x185,
+ 0x186,0x187,0x188,0x189,0x18a,0x18b,0x18c,0x18d,
+ 0x18e,0x18f,0x190,0x191,0x192,0x193,0x194,0x195,
+ 0x196,0x197,0x198,0x199,0x19a,0x19b,0x19c,0x19d,
+ 0x19e,0x19f,0x1a0,0x1a1,0x1a2,0x1a3,0x1a4,0x1a5,
+ 0x1a6,0x1a7,0x1a8,0x1a9,0x1aa,0x1ab,0x1ac,0x1ad,
+ 0x1ae,0x1af,0x1b0,0x1b1,0x1b2,0x1b3,0x1b4,0x1b5,
+ 0x1b6,0x1b7,0x1b8,0x1b9,0x1ba,0x1bb,0x1bc,0x1bd,
+ 0x1be,0x1bf,0x1c0,0x1c1,0x1c2,0x1c3,0x1c4,0x1c5,
+ 0x1c6,0x1c7,0x1c8,0x1c9,0x1ca,0x1cb,0x1cc,0x1cd,
+ 0x1ce,0x1cf,0x1d0,0x1d1,0x1d2,0x1d3,0x1d4,0x1d5,
+ 0x1d6,0x1d7,0x1d8,0x1d9,0x1da,0x1db,0x1dc,0x1dd,
+ 0x1de,0x1df,0x1e0,0x1e1,0x1e2,0x1e3,0x1e4,0x1e5,
+ 0x1e6,0x1e7,0x1e8,0x1e9,0x1ea,0x1eb,0x1ec,0x1ed,
+ 0x1ee,0x1ef,0x1f0,0x1f1,0x1f2,0x1f3,0x1f4,0x1f5,
+ 0x1f6,0x1f7,0x1f8,0x1f9,0x1fa,0x1fb,0x1fc,0x1fd,
+ 0x1fe,0x1ff,0x100,0x101,0x102,0x103,0x104,0x105,
+ 0x106,0x107,0x108,0x109,0x10a,0x10b,0x10c,0x10d,
+ 0x10e,0x10f,0x110,0x111,0x112,0x113,0x114,0x115,
+ 0x116,0x117,0x118,0x119,0x11a,0x11b,0x11c,0x11d,
+ 0x11e,0x11f,0x120,0x121,0x122,0x123,0x124,0x125,
+ 0x126,0x127,0x128,0x129,0x12a,0x12b,0x12c,0x12d,
+ 0x12e,0x12f,0x130,0x131,0x132,0x133,0x134,0x135,
+ 0x136,0x137,0x138,0x139,0x13a,0x13b,0x13c,0x13d,
+ 0x13e,0x13f,0x140,0x141,0x142,0x143,0x144,0x145,
+ 0x146,0x147,0x148,0x149,0x14a,0x14b,0x14c,0x14d,
+ 0x14e,0x14f,0x150,0x151,0x152,0x153,0x154,0x155,
+ 0x156,0x157,0x158,0x159,0x15a,0x15b,0x15c,0x15d,
+ 0x15e,0x15f,0x160,0x161,0x162,0x163,0x164,0x165,
+ 0x166,0x167,0x168,0x169,0x16a,0x16b,0x16c,0x16d,
+ 0x16e,0x16f,0x170,0x171,0x172,0x173,0x174,0x175,
+ 0x176,0x177,0x178,0x179,0x17a,0x17b,0x17c,0x17d,
+ 0x17e,0x17f,0x180,0x181,0x182,0x183,0x184,0x185,
+ 0x186,0x187,0x188,0x189,0x18a,0x18b,0x18c,0x18d,
+ 0x18e,0x18f,0x190,0x191,0x192,0x193,0x194,0x195,
+ 0x196,0x197,0x198,0x199,0x19a,0x19b,0x19c,0x19d,
+ 0x19e,0x19f,0x1a0,0x1a1,0x1a2,0x1a3,0x1a4,0x1a5,
+ 0x1a6,0x1a7,0x1a8,0x1a9,0x1aa,0x1ab,0x1ac,0x1ad,
+ 0x1ae,0x1af,0x1b0,0x1b1,0x1b2,0x1b3,0x1b4,0x1b5,
+ 0x1b6,0x1b7,0x1b8,0x1b9,0x1ba,0x1bb,0x1bc,0x1bd,
+ 0x1be,0x1bf,0x1c0,0x1c1,0x1c2,0x1c3,0x1c4,0x1c5,
+ 0x1c6,0x1c7,0x1c8,0x1c9,0x1ca,0x1cb,0x1cc,0x1cd,
+ 0x1ce,0x1cf,0x1d0,0x1d1,0x1d2,0x1d3,0x1d4,0x1d5,
+ 0x1d6,0x1d7,0x1d8,0x1d9,0x1da,0x1db,0x1dc,0x1dd,
+ 0x1de,0x1df,0x1e0,0x1e1,0x1e2,0x1e3,0x1e4,0x1e5,
+ 0x1e6,0x1e7,0x1e8,0x1e9,0x1ea,0x1eb,0x1ec,0x1ed,
+ 0x1ee,0x1ef,0x1f0,0x1f1,0x1f2,0x1f3,0x1f4,0x1f5,
+ 0x1f6,0x1f7,0x1f8,0x1f9,0x1fa,0x1fb,0x1fc,0x1fd,
+ 0x1fe,0x1ff,0x100,0x101,0x102,0x103,0x104,0x105,
+ 0x106,0x107,0x108,0x109,0x10a,0x10b,0x10c,0x10d,
+ 0x10e,0x10f,0x110,0x111,0x112,0x113,0x114,0x115,
+ 0x116,0x117,0x118,0x119,0x11a,0x11b,0x11c,0x11d,
+ 0x11e,0x11f,0x120,0x121,0x122,0x123,0x124,0x125,
+ 0x126,0x127,0x128,0x129,0x12a,0x12b,0x12c,0x12d,
+ 0x12e,0x12f,0x130,0x131,0x132,0x133,0x134,0x135,
+ 0x136,0x137,0x138,0x139,0x13a,0x13b,0x13c,0x13d,
+ 0x13e,0x13f,0x140,0x141,0x142,0x143,0x144,0x145,
+ 0x146,0x147,0x148,0x149,0x14a,0x14b,0x14c,0x14d,
+ 0x14e,0x14f,0x150,0x151,0x152,0x153,0x154,0x155,
+ 0x156,0x157,0x158,0x159,0x15a,0x15b,0x15c,0x15d,
+ 0x15e,0x15f,0x160,0x161,0x162,0x163,0x164,0x165,
+ 0x166,0x167,0x168,0x169,0x16a,0x16b,0x16c,0x16d,
+ 0x16e,0x16f,0x170,0x171,0x172,0x173,0x174,0x175,
+ 0x176,0x177,0x178,0x179,0x17a,0x17b,0x17c,0x17d,
+ 0x17e,0x17f,0x180,0x181,0x182,0x183,0x184,0x185,
+ 0x186,0x187,0x188,0x189,0x18a,0x18b,0x18c,0x18d,
+ 0x18e,0x18f,0x190,0x191,0x192,0x193,0x194,0x195,
+ 0x196,0x197,0x198,0x199,0x19a,0x19b,0x19c,0x19d,
+ 0x19e,0x19f,0x1a0,0x1a1,0x1a2,0x1a3,0x1a4,0x1a5,
+ 0x1a6,0x1a7,0x1a8,0x1a9,0x1aa,0x1ab,0x1ac,0x1ad,
+ 0x1ae,0x1af,0x1b0,0x1b1,0x1b2,0x1b3,0x1b4,0x1b5,
+ 0x1b6,0x1b7,0x1b8,0x1b9,0x1ba,0x1bb,0x1bc,0x1bd,
+ 0x1be,0x1bf,0x1c0,0x1c1,0x1c2,0x1c3,0x1c4,0x1c5,
+ 0x1c6,0x1c7,0x1c8,0x1c9,0x1ca,0x1cb,0x1cc,0x1cd,
+ 0x1ce,0x1cf,0x1d0,0x1d1,0x1d2,0x1d3,0x1d4,0x1d5,
+ 0x1d6,0x1d7,0x1d8,0x1d9,0x1da,0x1db,0x1dc,0x1dd,
+ 0x1de,0x1df,0x1e0,0x1e1,0x1e2,0x1e3,0x1e4,0x1e5,
+ 0x1e6,0x1e7,0x1e8,0x1e9,0x1ea,0x1eb,0x1ec,0x1ed,
+ 0x1ee,0x1ef,0x1f0,0x1f1,0x1f2,0x1f3,0x1f4,0x1f5,
+ 0x1f6,0x1f7,0x1f8,0x1f9,0x1fa,0x1fb,0x1fc,0x1fd,
+ 0x1fe,0x1ff,0x100,0x101,0x102,0x103,0x104,0x105,
+ 0x106,0x107,0x108,0x109,0x10a,0x10b,0x10c,0x10d,
+ 0x10e,0x10f,0x110,0x111,0x112,0x113,0x114,0x115,
+ 0x116,0x117,0x118,0x119,0x11a,0x11b,0x11c,0x11d,
+ 0x11e,0x11f,0x120,0x121,0x122,0x123,0x124,0x125,
+ 0x126,0x127,0x128,0x129,0x12a,0x12b,0x12c,0x12d,
+ 0x12e,0x12f,0x130,0x131,0x132,0x133,0x134,0x135,
+ 0x136,0x137,0x138,0x139,0x13a,0x13b,0x13c,0x13d,
+ 0x13e,0x13f,0x140,0x141,0x142,0x143,0x144,0x145,
+ 0x146,0x147,0x148,0x149,0x14a,0x14b,0x14c,0x14d,
+ 0x14e,0x14f,0x150,0x151,0x152,0x153,0x154,0x155,
+ 0x156,0x157,0x158,0x159,0x15a,0x15b,0x15c,0x15d,
+ 0x15e,0x15f,0x160,0x161,0x162,0x163,0x164,0x165,
+ /* sub/sbc results */
+ 0x000,0x001,0x002,0x003,0x004,0x005,0x006,0x007,
+ 0x008,0x009,0x00a,0x00b,0x00c,0x00d,0x00e,0x00f,
+ 0x010,0x011,0x012,0x013,0x014,0x015,0x016,0x017,
+ 0x018,0x019,0x01a,0x01b,0x01c,0x01d,0x01e,0x01f,
+ 0x020,0x021,0x022,0x023,0x024,0x025,0x026,0x027,
+ 0x028,0x029,0x02a,0x02b,0x02c,0x02d,0x02e,0x02f,
+ 0x030,0x031,0x032,0x033,0x034,0x035,0x036,0x037,
+ 0x038,0x039,0x03a,0x03b,0x03c,0x03d,0x03e,0x03f,
+ 0x040,0x041,0x042,0x043,0x044,0x045,0x046,0x047,
+ 0x048,0x049,0x04a,0x04b,0x04c,0x04d,0x04e,0x04f,
+ 0x050,0x051,0x052,0x053,0x054,0x055,0x056,0x057,
+ 0x058,0x059,0x05a,0x05b,0x05c,0x05d,0x05e,0x05f,
+ 0x060,0x061,0x062,0x063,0x064,0x065,0x066,0x067,
+ 0x068,0x069,0x06a,0x06b,0x06c,0x06d,0x06e,0x06f,
+ 0x070,0x071,0x072,0x073,0x074,0x075,0x076,0x077,
+ 0x078,0x079,0x07a,0x07b,0x07c,0x07d,0x07e,0x07f,
+ 0x080,0x081,0x082,0x083,0x084,0x085,0x086,0x087,
+ 0x088,0x089,0x08a,0x08b,0x08c,0x08d,0x08e,0x08f,
+ 0x090,0x091,0x092,0x093,0x094,0x095,0x096,0x097,
+ 0x098,0x099,0x09a,0x09b,0x09c,0x09d,0x09e,0x09f,
+ 0x0a0,0x0a1,0x0a2,0x0a3,0x0a4,0x0a5,0x0a6,0x0a7,
+ 0x0a8,0x0a9,0x0aa,0x0ab,0x0ac,0x0ad,0x0ae,0x0af,
+ 0x0b0,0x0b1,0x0b2,0x0b3,0x0b4,0x0b5,0x0b6,0x0b7,
+ 0x0b8,0x0b9,0x0ba,0x0bb,0x0bc,0x0bd,0x0be,0x0bf,
+ 0x0c0,0x0c1,0x0c2,0x0c3,0x0c4,0x0c5,0x0c6,0x0c7,
+ 0x0c8,0x0c9,0x0ca,0x0cb,0x0cc,0x0cd,0x0ce,0x0cf,
+ 0x0d0,0x0d1,0x0d2,0x0d3,0x0d4,0x0d5,0x0d6,0x0d7,
+ 0x0d8,0x0d9,0x0da,0x0db,0x0dc,0x0dd,0x0de,0x0df,
+ 0x0e0,0x0e1,0x0e2,0x0e3,0x0e4,0x0e5,0x0e6,0x0e7,
+ 0x0e8,0x0e9,0x0ea,0x0eb,0x0ec,0x0ed,0x0ee,0x0ef,
+ 0x0f0,0x0f1,0x0f2,0x0f3,0x0f4,0x0f5,0x0f6,0x0f7,
+ 0x0f8,0x0f9,0x0fa,0x0fb,0x0fc,0x0fd,0x0fe,0x0ff,
+ 0x1a0,0x1a1,0x1a2,0x1a3,0x1a4,0x1a5,0x1a6,0x1a7,
+ 0x1a8,0x1a9,0x1aa,0x1ab,0x1ac,0x1ad,0x1ae,0x1af,
+ 0x1b0,0x1b1,0x1b2,0x1b3,0x1b4,0x1b5,0x1b6,0x1b7,
+ 0x1b8,0x1b9,0x1ba,0x1bb,0x1bc,0x1bd,0x1be,0x1bf,
+ 0x1c0,0x1c1,0x1c2,0x1c3,0x1c4,0x1c5,0x1c6,0x1c7,
+ 0x1c8,0x1c9,0x1ca,0x1cb,0x1cc,0x1cd,0x1ce,0x1cf,
+ 0x1d0,0x1d1,0x1d2,0x1d3,0x1d4,0x1d5,0x1d6,0x1d7,
+ 0x1d8,0x1d9,0x1da,0x1db,0x1dc,0x1dd,0x1de,0x1df,
+ 0x1e0,0x1e1,0x1e2,0x1e3,0x1e4,0x1e5,0x1e6,0x1e7,
+ 0x1e8,0x1e9,0x1ea,0x1eb,0x1ec,0x1ed,0x1ee,0x1ef,
+ 0x1f0,0x1f1,0x1f2,0x1f3,0x1f4,0x1f5,0x1f6,0x1f7,
+ 0x1f8,0x1f9,0x1fa,0x1fb,0x1fc,0x1fd,0x1fe,0x1ff,
+ 0x100,0x101,0x102,0x103,0x104,0x105,0x106,0x107,
+ 0x108,0x109,0x10a,0x10b,0x10c,0x10d,0x10e,0x10f,
+ 0x110,0x111,0x112,0x113,0x114,0x115,0x116,0x117,
+ 0x118,0x119,0x11a,0x11b,0x11c,0x11d,0x11e,0x11f,
+ 0x120,0x121,0x122,0x123,0x124,0x125,0x126,0x127,
+ 0x128,0x129,0x12a,0x12b,0x12c,0x12d,0x12e,0x12f,
+ 0x130,0x131,0x132,0x133,0x134,0x135,0x136,0x137,
+ 0x138,0x139,0x13a,0x13b,0x13c,0x13d,0x13e,0x13f,
+ 0x140,0x141,0x142,0x143,0x144,0x145,0x146,0x147,
+ 0x148,0x149,0x14a,0x14b,0x14c,0x14d,0x14e,0x14f,
+ 0x150,0x151,0x152,0x153,0x154,0x155,0x156,0x157,
+ 0x158,0x159,0x15a,0x15b,0x15c,0x15d,0x15e,0x15f,
+ 0x160,0x161,0x162,0x163,0x164,0x165,0x166,0x167,
+ 0x168,0x169,0x16a,0x16b,0x16c,0x16d,0x16e,0x16f,
+ 0x170,0x171,0x172,0x173,0x174,0x175,0x176,0x177,
+ 0x178,0x179,0x17a,0x17b,0x17c,0x17d,0x17e,0x17f,
+ 0x180,0x181,0x182,0x183,0x184,0x185,0x186,0x187,
+ 0x188,0x189,0x18a,0x18b,0x18c,0x18d,0x18e,0x18f,
+ 0x190,0x191,0x192,0x193,0x194,0x195,0x196,0x197,
+ 0x198,0x199,0x19a,0x19b,0x19c,0x19d,0x19e,0x19f,
+ 0x1fa,0x1fb,0x1fc,0x1fd,0x1fe,0x1ff,0x100,0x101,
+ 0x102,0x103,0x104,0x105,0x106,0x107,0x108,0x109,
+ 0x10a,0x10b,0x10c,0x10d,0x10e,0x10f,0x110,0x111,
+ 0x112,0x113,0x114,0x115,0x116,0x117,0x118,0x119,
+ 0x11a,0x11b,0x11c,0x11d,0x11e,0x11f,0x120,0x121,
+ 0x122,0x123,0x124,0x125,0x126,0x127,0x128,0x129,
+ 0x12a,0x12b,0x12c,0x12d,0x12e,0x12f,0x130,0x131,
+ 0x132,0x133,0x134,0x135,0x136,0x137,0x138,0x139,
+ 0x13a,0x13b,0x13c,0x13d,0x13e,0x13f,0x140,0x141,
+ 0x142,0x143,0x144,0x145,0x146,0x147,0x148,0x149,
+ 0x14a,0x14b,0x14c,0x14d,0x14e,0x14f,0x150,0x151,
+ 0x152,0x153,0x154,0x155,0x156,0x157,0x158,0x159,
+ 0x15a,0x15b,0x15c,0x15d,0x15e,0x15f,0x160,0x161,
+ 0x162,0x163,0x164,0x165,0x166,0x167,0x168,0x169,
+ 0x16a,0x16b,0x16c,0x16d,0x16e,0x16f,0x170,0x171,
+ 0x172,0x173,0x174,0x175,0x176,0x177,0x178,0x179,
+ 0x17a,0x17b,0x17c,0x17d,0x17e,0x17f,0x180,0x181,
+ 0x182,0x183,0x184,0x185,0x186,0x187,0x188,0x189,
+ 0x18a,0x18b,0x18c,0x18d,0x18e,0x18f,0x190,0x191,
+ 0x192,0x193,0x194,0x195,0x196,0x197,0x198,0x199,
+ 0x19a,0x19b,0x19c,0x19d,0x19e,0x19f,0x1a0,0x1a1,
+ 0x1a2,0x1a3,0x1a4,0x1a5,0x1a6,0x1a7,0x1a8,0x1a9,
+ 0x1aa,0x1ab,0x1ac,0x1ad,0x1ae,0x1af,0x1b0,0x1b1,
+ 0x1b2,0x1b3,0x1b4,0x1b5,0x1b6,0x1b7,0x1b8,0x1b9,
+ 0x1ba,0x1bb,0x1bc,0x1bd,0x1be,0x1bf,0x1c0,0x1c1,
+ 0x1c2,0x1c3,0x1c4,0x1c5,0x1c6,0x1c7,0x1c8,0x1c9,
+ 0x1ca,0x1cb,0x1cc,0x1cd,0x1ce,0x1cf,0x1d0,0x1d1,
+ 0x1d2,0x1d3,0x1d4,0x1d5,0x1d6,0x1d7,0x1d8,0x1d9,
+ 0x1da,0x1db,0x1dc,0x1dd,0x1de,0x1df,0x1e0,0x1e1,
+ 0x1e2,0x1e3,0x1e4,0x1e5,0x1e6,0x1e7,0x1e8,0x1e9,
+ 0x1ea,0x1eb,0x1ec,0x1ed,0x1ee,0x1ef,0x1f0,0x1f1,
+ 0x1f2,0x1f3,0x1f4,0x1f5,0x1f6,0x1f7,0x1f8,0x1f9,
+ 0x19a,0x19b,0x19c,0x19d,0x19e,0x19f,0x1a0,0x1a1,
+ 0x1a2,0x1a3,0x1a4,0x1a5,0x1a6,0x1a7,0x1a8,0x1a9,
+ 0x1aa,0x1ab,0x1ac,0x1ad,0x1ae,0x1af,0x1b0,0x1b1,
+ 0x1b2,0x1b3,0x1b4,0x1b5,0x1b6,0x1b7,0x1b8,0x1b9,
+ 0x1ba,0x1bb,0x1bc,0x1bd,0x1be,0x1bf,0x1c0,0x1c1,
+ 0x1c2,0x1c3,0x1c4,0x1c5,0x1c6,0x1c7,0x1c8,0x1c9,
+ 0x1ca,0x1cb,0x1cc,0x1cd,0x1ce,0x1cf,0x1d0,0x1d1,
+ 0x1d2,0x1d3,0x1d4,0x1d5,0x1d6,0x1d7,0x1d8,0x1d9,
+ 0x1da,0x1db,0x1dc,0x1dd,0x1de,0x1df,0x1e0,0x1e1,
+ 0x1e2,0x1e3,0x1e4,0x1e5,0x1e6,0x1e7,0x1e8,0x1e9,
+ 0x1ea,0x1eb,0x1ec,0x1ed,0x1ee,0x1ef,0x1f0,0x1f1,
+ 0x1f2,0x1f3,0x1f4,0x1f5,0x1f6,0x1f7,0x1f8,0x1f9,
+ 0x1fa,0x1fb,0x1fc,0x1fd,0x1fe,0x1ff,0x100,0x101,
+ 0x102,0x103,0x104,0x105,0x106,0x107,0x108,0x109,
+ 0x10a,0x10b,0x10c,0x10d,0x10e,0x10f,0x110,0x111,
+ 0x112,0x113,0x114,0x115,0x116,0x117,0x118,0x119,
+ 0x11a,0x11b,0x11c,0x11d,0x11e,0x11f,0x120,0x121,
+ 0x122,0x123,0x124,0x125,0x126,0x127,0x128,0x129,
+ 0x12a,0x12b,0x12c,0x12d,0x12e,0x12f,0x130,0x131,
+ 0x132,0x133,0x134,0x135,0x136,0x137,0x138,0x139,
+ 0x13a,0x13b,0x13c,0x13d,0x13e,0x13f,0x140,0x141,
+ 0x142,0x143,0x144,0x145,0x146,0x147,0x148,0x149,
+ 0x14a,0x14b,0x14c,0x14d,0x14e,0x14f,0x150,0x151,
+ 0x152,0x153,0x154,0x155,0x156,0x157,0x158,0x159,
+ 0x15a,0x15b,0x15c,0x15d,0x15e,0x15f,0x160,0x161,
+ 0x162,0x163,0x164,0x165,0x166,0x167,0x168,0x169,
+ 0x16a,0x16b,0x16c,0x16d,0x16e,0x16f,0x170,0x171,
+ 0x172,0x173,0x174,0x175,0x176,0x177,0x178,0x179,
+ 0x17a,0x17b,0x17c,0x17d,0x17e,0x17f,0x180,0x181,
+ 0x182,0x183,0x184,0x185,0x186,0x187,0x188,0x189,
+ 0x18a,0x18b,0x18c,0x18d,0x18e,0x18f,0x190,0x191,
+ 0x192,0x193,0x194,0x195,0x196,0x197,0x198,0x199,
+};
diff --git a/trunk/src/emu/cpu/z8000/z8000ops.c b/trunk/src/emu/cpu/z8000/z8000ops.c
new file mode 100644
index 00000000000..bdbc673e4a1
--- /dev/null
+++ b/trunk/src/emu/cpu/z8000/z8000ops.c
@@ -0,0 +1,6607 @@
+/*****************************************************************************
+ *
+ * z8000ops.c
+ * Portable Z8000(2) emulator
+ * Opcode functions
+ *
+ * Copyright Juergen Buchmueller, all rights reserved.
+ * Bug fixes and MSB_FIRST compliance Ernesto Corvi.
+ *
+ * - 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.
+ *
+ *****************************************************************************/
+
+/******************************************
+ helper functions
+ ******************************************/
+
+/******************************************
+ check new fcw for switch to system mode
+ and swap stack pointer if needed
+ ******************************************/
+INLINE void CHANGE_FCW(z8000_state *cpustate, UINT16 fcw)
+{
+ if (fcw & F_S_N) { /* system mode now? */
+ if (!(cpustate->fcw & F_S_N)) { /* and not before? */
+ UINT16 tmp = cpustate->RW(SP);
+ cpustate->RW(SP) = cpustate->nsp;
+ cpustate->nsp = tmp;
+ }
+ } else { /* user mode now */
+ if (cpustate->fcw & F_S_N) { /* and not before? */
+ UINT16 tmp = cpustate->RW(SP);
+ cpustate->RW(SP) = cpustate->nsp;
+ cpustate->nsp = tmp;
+ }
+ }
+ if (!(cpustate->fcw & F_NVIE) && (fcw & F_NVIE) && (cpustate->irq_state[0] != CLEAR_LINE))
+ cpustate->irq_req |= Z8000_NVI;
+ if (!(cpustate->fcw & F_VIE) && (fcw & F_VIE) && (cpustate->irq_state[1] != CLEAR_LINE))
+ cpustate->irq_req |= Z8000_VI;
+ cpustate->fcw = fcw; /* set new cpustate->fcw */
+}
+
+INLINE void PUSHW(z8000_state *cpustate, UINT8 dst, UINT16 value)
+{
+ cpustate->RW(dst) -= 2;
+ WRMEM_W(cpustate, cpustate->RW(dst), value);
+}
+
+INLINE UINT16 POPW(z8000_state *cpustate, UINT8 src)
+{
+ UINT16 result = RDMEM_W(cpustate, cpustate->RW(src));
+ cpustate->RW(src) += 2;
+ return result;
+}
+
+INLINE void PUSHL(z8000_state *cpustate, UINT8 dst, UINT32 value)
+{
+ cpustate->RW(dst) -= 4;
+ WRMEM_L(cpustate, cpustate->RW(dst), value);
+}
+
+INLINE UINT32 POPL(z8000_state *cpustate, UINT8 src)
+{
+ UINT32 result = RDMEM_L(cpustate, cpustate->RW(src));
+ cpustate->RW(src) += 4;
+ return result;
+}
+
+/* check zero and sign flag for byte, word and long results */
+#define CHK_XXXB_ZS if (!result) SET_Z; else if ((INT8) result < 0) SET_S
+#define CHK_XXXW_ZS if (!result) SET_Z; else if ((INT16)result < 0) SET_S
+#define CHK_XXXL_ZS if (!result) SET_Z; else if ((INT32)result < 0) SET_S
+#define CHK_XXXQ_ZS if (!result) SET_Z; else if ((INT64)result < 0) SET_S
+
+#define CHK_XXXB_ZSP cpustate->fcw |= z8000_zsp[result]
+
+/* check carry for addition and subtraction */
+#define CHK_ADDX_C if (result < dest) SET_C
+#define CHK_ADCX_C if (result < dest || (result == dest && value)) SET_C
+
+#define CHK_SUBX_C if (result > dest) SET_C
+#define CHK_SBCX_C if (result > dest || (result == dest && value)) SET_C
+
+/* check half carry for A addition and S subtraction */
+#define CHK_ADDB_H if ((result & 15) < (dest & 15)) SET_H
+#define CHK_ADCB_H if ((result & 15) < (dest & 15) || ((result & 15) == (dest & 15) && (value & 15))) SET_H
+
+#define CHK_SUBB_H if ((result & 15) > (dest & 15)) SET_H
+#define CHK_SBCB_H if ((result & 15) > (dest & 15) || ((result & 15) == (dest & 15) && (value & 15))) SET_H
+
+/* check overflow for addition for byte, word and long */
+#define CHK_ADDB_V if (((value & dest & ~result) | (~value & ~dest & result)) & S08) SET_V
+#define CHK_ADDW_V if (((value & dest & ~result) | (~value & ~dest & result)) & S16) SET_V
+#define CHK_ADDL_V if (((value & dest & ~result) | (~value & ~dest & result)) & S32) SET_V
+
+/* check overflow for subtraction for byte, word and long */
+#define CHK_SUBB_V if (((~value & dest & ~result) | (value & ~dest & result)) & S08) SET_V
+#define CHK_SUBW_V if (((~value & dest & ~result) | (value & ~dest & result)) & S16) SET_V
+#define CHK_SUBL_V if (((~value & dest & ~result) | (value & ~dest & result)) & S32) SET_V
+
+
+/******************************************
+ add byte
+ flags: CZSVDH
+ ******************************************/
+INLINE UINT8 ADDB(z8000_state *cpustate, UINT8 dest, UINT8 value)
+{
+ UINT8 result = dest + value;
+ CLR_CZSVH; /* first clear C, Z, S, P/V and H flags */
+ CLR_DA; /* clear DA (decimal adjust) flag for addb */
+ CHK_XXXB_ZS; /* set Z and S flags for result byte */
+ CHK_ADDX_C; /* set C if result overflowed */
+ CHK_ADDB_V; /* set V if result has incorrect sign */
+ CHK_ADDB_H; /* set H if lower nibble overflowed */
+ return result;
+}
+
+/******************************************
+ add word
+ flags: CZSV--
+ ******************************************/
+INLINE UINT16 ADDW(z8000_state *cpustate, UINT16 dest, UINT16 value)
+{
+ UINT16 result = dest + value;
+ CLR_CZSV; /* first clear C, Z, S, P/V flags */
+ CHK_XXXW_ZS; /* set Z and S flags for result word */
+ CHK_ADDX_C; /* set C if result overflowed */
+ CHK_ADDW_V; /* set V if result has incorrect sign */
+ return result;
+}
+
+/******************************************
+ add long
+ flags: CZSV--
+ ******************************************/
+INLINE UINT32 ADDL(z8000_state *cpustate, UINT32 dest, UINT32 value)
+{
+ UINT32 result = dest + value;
+ CLR_CZSV; /* first clear C, Z, S, P/V flags */
+ CHK_XXXL_ZS; /* set Z and S flags for result long */
+ CHK_ADDX_C; /* set C if result overflowed */
+ CHK_ADDL_V; /* set V if result has incorrect sign */
+ return result;
+}
+
+/******************************************
+ add with carry byte
+ flags: CZSVDH
+ ******************************************/
+INLINE UINT8 ADCB(z8000_state *cpustate, UINT8 dest, UINT8 value)
+{
+ UINT8 result = dest + value + GET_C;
+ CLR_CZSVH; /* first clear C, Z, S, P/V and H flags */
+ CLR_DA; /* clear DA (decimal adjust) flag for adcb */
+ CHK_XXXB_ZS; /* set Z and S flags for result byte */
+ CHK_ADCX_C; /* set C if result overflowed */
+ CHK_ADDB_V; /* set V if result has incorrect sign */
+ CHK_ADCB_H; /* set H if lower nibble overflowed */
+ return result;
+}
+
+/******************************************
+ add with carry word
+ flags: CZSV--
+ ******************************************/
+INLINE UINT16 ADCW(z8000_state *cpustate, UINT16 dest, UINT16 value)
+{
+ UINT16 result = dest + value + GET_C;
+ CLR_CZSV; /* first clear C, Z, S, P/V flags */
+ CHK_XXXW_ZS; /* set Z and S flags for result word */
+ CHK_ADCX_C; /* set C if result overflowed */
+ CHK_ADDW_V; /* set V if result has incorrect sign */
+ return result;
+}
+
+/******************************************
+ subtract byte
+ flags: CZSVDH
+ ******************************************/
+INLINE UINT8 SUBB(z8000_state *cpustate, UINT8 dest, UINT8 value)
+{
+ UINT8 result = dest - value;
+ CLR_CZSVH; /* first clear C, Z, S, P/V and H flags */
+ SET_DA; /* set DA (decimal adjust) flag for subb */
+ CHK_XXXB_ZS; /* set Z and S flags for result byte */
+ CHK_SUBX_C; /* set C if result underflowed */
+ CHK_SUBB_V; /* set V if result has incorrect sign */
+ CHK_SUBB_H; /* set H if lower nibble underflowed */
+ return result;
+}
+
+/******************************************
+ subtract word
+ flags: CZSV--
+ ******************************************/
+INLINE UINT16 SUBW(z8000_state *cpustate, UINT16 dest, UINT16 value)
+{
+ UINT16 result = dest - value;
+ CLR_CZSV; /* first clear C, Z, S, P/V flags */
+ CHK_XXXW_ZS; /* set Z and S flags for result word */
+ CHK_SUBX_C; /* set C if result underflowed */
+ CHK_SUBW_V; /* set V if result has incorrect sign */
+ return result;
+}
+
+/******************************************
+ subtract long
+ flags: CZSV--
+ ******************************************/
+INLINE UINT32 SUBL(z8000_state *cpustate, UINT32 dest, UINT32 value)
+{
+ UINT32 result = dest - value;
+ CLR_CZSV; /* first clear C, Z, S, P/V flags */
+ CHK_XXXL_ZS; /* set Z and S flags for result long */
+ CHK_SUBX_C; /* set C if result underflowed */
+ CHK_SUBL_V; /* set V if result has incorrect sign */
+ return result;
+}
+
+/******************************************
+ subtract with carry byte
+ flags: CZSVDH
+ ******************************************/
+INLINE UINT8 SBCB(z8000_state *cpustate, UINT8 dest, UINT8 value)
+{
+ UINT8 result = dest - value - GET_C;
+ CLR_CZSVH; /* first clear C, Z, S, P/V and H flags */
+ SET_DA; /* set DA (decimal adjust) flag for sbcb */
+ CHK_XXXB_ZS; /* set Z and S flags for result byte */
+ CHK_SBCX_C; /* set C if result underflowed */
+ CHK_SUBB_V; /* set V if result has incorrect sign */
+ CHK_SBCB_H; /* set H if lower nibble underflowed */
+ return result;
+}
+
+/******************************************
+ subtract with carry word
+ flags: CZSV--
+ ******************************************/
+INLINE UINT16 SBCW(z8000_state *cpustate, UINT16 dest, UINT16 value)
+{
+ UINT16 result = dest - value - GET_C;
+ CLR_CZSV; /* first clear C, Z, S, P/V flags */
+ CHK_XXXW_ZS; /* set Z and S flags for result word */
+ CHK_SBCX_C; /* set C if result underflowed */
+ CHK_SUBW_V; /* set V if result has incorrect sign */
+ return result;
+}
+
+/******************************************
+ logical or byte
+ flags: -ZSP--
+ ******************************************/
+INLINE UINT8 ORB(z8000_state *cpustate, UINT8 dest, UINT8 value)
+{
+ UINT8 result = dest | value;
+ CLR_ZSP; /* first clear Z, S, P/V flags */
+ CHK_XXXB_ZSP; /* set Z, S and P flags for result byte */
+ return result;
+}
+
+/******************************************
+ logical or word
+ flags: -ZS---
+ ******************************************/
+INLINE UINT16 ORW(z8000_state *cpustate, UINT16 dest, UINT16 value)
+{
+ UINT16 result = dest | value;
+ CLR_ZS; /* first clear Z, and S flags */
+ CHK_XXXW_ZS; /* set Z and S flags for result word */
+ return result;
+}
+
+/******************************************
+ logical and byte
+ flags: -ZSP--
+ ******************************************/
+INLINE UINT8 ANDB(z8000_state *cpustate, UINT8 dest, UINT8 value)
+{
+ UINT8 result = dest & value;
+ CLR_ZSP; /* first clear Z,S and P/V flags */
+ CHK_XXXB_ZSP; /* set Z, S and P flags for result byte */
+ return result;
+}
+
+/******************************************
+ logical and word
+ flags: -ZS---
+ ******************************************/
+INLINE UINT16 ANDW(z8000_state *cpustate, UINT16 dest, UINT16 value)
+{
+ UINT16 result = dest & value;
+ CLR_ZS; /* first clear Z and S flags */
+ CHK_XXXW_ZS; /* set Z and S flags for result word */
+ return result;
+}
+
+/******************************************
+ logical exclusive or byte
+ flags: -ZSP--
+ ******************************************/
+INLINE UINT8 XORB(z8000_state *cpustate, UINT8 dest, UINT8 value)
+{
+ UINT8 result = dest ^ value;
+ CLR_ZSP; /* first clear Z, S and P/V flags */
+ CHK_XXXB_ZSP; /* set Z, S and P flags for result byte */
+ return result;
+}
+
+/******************************************
+ logical exclusive or word
+ flags: -ZS---
+ ******************************************/
+INLINE UINT16 XORW(z8000_state *cpustate, UINT16 dest, UINT16 value)
+{
+ UINT16 result = dest ^ value;
+ CLR_ZS; /* first clear Z and S flags */
+ CHK_XXXW_ZS; /* set Z and S flags for result word */
+ return result;
+}
+
+
+/******************************************
+ compare byte
+ flags: CZSV--
+ ******************************************/
+INLINE void CPB(z8000_state *cpustate, UINT8 dest, UINT8 value)
+{
+ UINT8 result = dest - value;
+ CLR_CZSV; /* first clear C, Z, S and P/V flags */
+ CHK_XXXB_ZS; /* set Z and S flags for result byte */
+ CHK_SUBX_C; /* set C if result underflowed */
+ CHK_SUBB_V;
+}
+
+/******************************************
+ compare word
+ flags: CZSV--
+ ******************************************/
+INLINE void CPW(z8000_state *cpustate, UINT16 dest, UINT16 value)
+{
+ UINT16 result = dest - value;
+ CLR_CZSV;
+ CHK_XXXW_ZS; /* set Z and S flags for result word */
+ CHK_SUBX_C; /* set C if result underflowed */
+ CHK_SUBW_V;
+}
+
+/******************************************
+ compare long
+ flags: CZSV--
+ ******************************************/
+INLINE void CPL(z8000_state *cpustate, UINT32 dest, UINT32 value)
+{
+ UINT32 result = dest - value;
+ CLR_CZSV;
+ CHK_XXXL_ZS; /* set Z and S flags for result long */
+ CHK_SUBX_C; /* set C if result underflowed */
+ CHK_SUBL_V;
+}
+
+/******************************************
+ complement byte
+ flags: -ZSP--
+ ******************************************/
+INLINE UINT8 COMB(z8000_state *cpustate, UINT8 dest)
+{
+ UINT8 result = ~dest;
+ CLR_ZSP;
+ CHK_XXXB_ZSP; /* set Z, S and P flags for result byte */
+ return result;
+}
+
+/******************************************
+ complement word
+ flags: -ZS---
+ ******************************************/
+INLINE UINT16 COMW(z8000_state *cpustate, UINT16 dest)
+{
+ UINT16 result = ~dest;
+ CLR_ZS;
+ CHK_XXXW_ZS; /* set Z and S flags for result word */
+ return result;
+}
+
+/******************************************
+ negate byte
+ flags: CZSV--
+ ******************************************/
+INLINE UINT8 NEGB(z8000_state *cpustate, UINT8 dest)
+{
+ UINT8 result = (UINT8) -dest;
+ CLR_CZSV;
+ CHK_XXXB_ZS; /* set Z and S flags for result byte */
+ if (result > 0) SET_C;
+ if (result == S08) SET_V;
+ return result;
+}
+
+/******************************************
+ negate word
+ flags: CZSV--
+ ******************************************/
+INLINE UINT16 NEGW(z8000_state *cpustate, UINT16 dest)
+{
+ UINT16 result = (UINT16) -dest;
+ CLR_CZSV;
+ CHK_XXXW_ZS; /* set Z and S flags for result word */
+ if (result > 0) SET_C;
+ if (result == S16) SET_V;
+ return result;
+}
+
+/******************************************
+ test byte
+ flags: -ZSP--
+ ******************************************/
+INLINE void TESTB(z8000_state *cpustate, UINT8 result)
+{
+ CLR_ZSP;
+ CHK_XXXB_ZSP; /* set Z and S flags for result byte */
+}
+
+/******************************************
+ test word
+ flags: -ZS---
+ ******************************************/
+INLINE void TESTW(z8000_state *cpustate, UINT16 dest)
+{
+ CLR_ZS;
+ if (!dest) SET_Z; else if (dest & S16) SET_S;
+}
+
+/******************************************
+ test long
+ flags: -ZS---
+ ******************************************/
+INLINE void TESTL(z8000_state *cpustate, UINT32 dest)
+{
+ CLR_ZS;
+ if (!dest) SET_Z; else if (dest & S32) SET_S;
+}
+
+/******************************************
+ increment byte
+ flags: -ZSV--
+ ******************************************/
+INLINE UINT8 INCB(z8000_state *cpustate, UINT8 dest, UINT8 value)
+{
+ UINT8 result = dest + value;
+ CLR_ZSV;
+ CHK_XXXB_ZS; /* set Z and S flags for result byte */
+ CHK_ADDB_V; /* set V if result overflowed */
+ return result;
+}
+
+/******************************************
+ increment word
+ flags: -ZSV--
+ ******************************************/
+INLINE UINT16 INCW(z8000_state *cpustate, UINT16 dest, UINT16 value)
+{
+ UINT16 result = dest + value;
+ CLR_ZSV;
+ CHK_XXXW_ZS; /* set Z and S flags for result byte */
+ CHK_ADDW_V; /* set V if result overflowed */
+ return result;
+}
+
+/******************************************
+ decrement byte
+ flags: -ZSV--
+ ******************************************/
+INLINE UINT8 DECB(z8000_state *cpustate, UINT8 dest, UINT8 value)
+{
+ UINT8 result = dest - value;
+ CLR_ZSV;
+ CHK_XXXB_ZS; /* set Z and S flags for result byte */
+ CHK_SUBB_V; /* set V if result overflowed */
+ return result;
+}
+
+/******************************************
+ decrement word
+ flags: -ZSV--
+ ******************************************/
+INLINE UINT16 DECW(z8000_state *cpustate, UINT16 dest, UINT16 value)
+{
+ UINT16 result = dest - value;
+ CLR_ZSV;
+ CHK_XXXW_ZS; /* set Z and S flags for result word */
+ CHK_SUBW_V; /* set V if result overflowed */
+ return result;
+}
+
+/******************************************
+ multiply words
+ flags: CZSV--
+ ******************************************/
+INLINE UINT32 MULTW(z8000_state *cpustate, UINT16 dest, UINT16 value)
+{
+ UINT32 result = (INT32)(INT16)dest * (INT16)value;
+ CLR_CZSV;
+ CHK_XXXL_ZS;
+ if(!value)
+ {
+ /* multiplication with zero is faster */
+ cpustate->icount += (70-18);
+ }
+ if((INT32)result < -0x7fff || (INT32)result >= 0x7fff) SET_C;
+ return result;
+}
+
+/******************************************
+ multiply longs
+ flags: CZSV--
+ ******************************************/
+INLINE UINT64 MULTL(z8000_state *cpustate, UINT32 dest, UINT32 value)
+{
+ UINT64 result = (INT64)(INT32)dest * (INT32)value;
+ if(!value)
+ {
+ /* multiplication with zero is faster */
+ cpustate->icount += (282 - 30);
+ }
+ else
+ {
+ int n;
+ for(n = 0; n < 32; n++)
+ if(dest & (1L << n)) cpustate->icount -= 7;
+ }
+ CLR_CZSV;
+ CHK_XXXQ_ZS;
+ if((INT64)result < -0x7fffffffL || (INT64)result >= 0x7fffffffL) SET_C;
+ return result;
+}
+
+/******************************************
+ divide long by word
+ flags: CZSV--
+ ******************************************/
+INLINE UINT32 DIVW(z8000_state *cpustate, UINT32 dest, UINT16 value)
+{
+ UINT32 result = dest;
+ UINT16 remainder = 0;
+ CLR_CZSV;
+ if (value)
+ {
+ UINT16 qsign = ((dest >> 16) ^ value) & S16;
+ UINT16 rsign = (dest >> 16) & S16;
+ if ((INT32)dest < 0) dest = -dest;
+ if ((INT16)value < 0) value = -value;
+ result = dest / value;
+ remainder = dest % value;
+ if (qsign) result = -result;
+ if (rsign) remainder = -remainder;
+ if ((INT32)result < -0x8000 || (INT32)result > 0x7fff)
+ {
+ INT32 temp = (INT32)result >> 1;
+ SET_V;
+ if (temp >= -0x8000 && temp <= 0x7fff)
+ {
+ result = (temp < 0) ? -1 : 0;
+ CHK_XXXW_ZS;
+ SET_C;
+ }
+ }
+ else
+ {
+ CHK_XXXW_ZS;
+ }
+ result = ((UINT32)remainder << 16) | (result & 0xffff);
+ }
+ else
+ {
+ SET_Z;
+ SET_V;
+ }
+ return result;
+}
+
+/******************************************
+ divide quad word by long
+ flags: CZSV--
+ ******************************************/
+INLINE UINT64 DIVL(z8000_state *cpustate, UINT64 dest, UINT32 value)
+{
+ UINT64 result = dest;
+ UINT32 remainder = 0;
+ CLR_CZSV;
+ if (value)
+ {
+ UINT32 qsign = ((dest >> 32) ^ value) & S32;
+ UINT32 rsign = (dest >> 32) & S32;
+ if ((INT64)dest < 0) dest = -dest;
+ if ((INT32)value < 0) value = -value;
+ result = dest / value;
+ remainder = dest % value;
+ if (qsign) result = -result;
+ if (rsign) remainder = -remainder;
+ if ((INT64)result < -0x80000000 || (INT64)result > 0x7fffffff)
+ {
+ INT64 temp = (INT64)result >> 1;
+ SET_V;
+ if (temp >= -0x80000000 && temp <= 0x7fffffff)
+ {
+ result = (temp < 0) ? -1 : 0;
+ CHK_XXXL_ZS;
+ SET_C;
+ }
+ }
+ else
+ {
+ CHK_XXXL_ZS;
+ }
+ result = ((UINT64)remainder << 32) | (result & 0xffffffff);
+ }
+ else
+ {
+ SET_Z;
+ SET_V;
+ }
+ return result;
+}
+
+/******************************************
+ rotate left byte
+ flags: CZSV--
+ ******************************************/
+INLINE UINT8 RLB(z8000_state *cpustate, UINT8 dest, UINT8 twice)
+{
+ UINT8 result = (dest << 1) | (dest >> 7);
+ CLR_CZSV;
+ if (twice) result = (result << 1) | (result >> 7);
+ CHK_XXXB_ZS; /* set Z and S flags for result byte */
+ if (result & 0x01) SET_C;
+ if ((result ^ dest) & S08) SET_V;
+ return result;
+}
+
+/******************************************
+ rotate left word
+ flags: CZSV--
+ ******************************************/
+INLINE UINT16 RLW(z8000_state *cpustate, UINT16 dest, UINT8 twice)
+{
+ UINT16 result = (dest << 1) | (dest >> 15);
+ CLR_CZSV;
+ if (twice) result = (result << 1) | (result >> 15);
+ CHK_XXXW_ZS; /* set Z and S flags for result word */
+ if (result & 0x0001) SET_C;
+ if ((result ^ dest) & S16) SET_V;
+ return result;
+}
+
+/******************************************
+ rotate left through carry byte
+ flags: CZSV--
+ ******************************************/
+INLINE UINT8 RLCB(z8000_state *cpustate, UINT8 dest, UINT8 twice)
+{
+ UINT8 c = dest & S08;
+ UINT8 result = (dest << 1) | GET_C;
+ CLR_CZSV;
+ if (twice) {
+ UINT8 c1 = c >> 7;
+ c = result & S08;
+ result = (result << 1) | c1;
+ }
+ CHK_XXXB_ZS; /* set Z and S flags for result byte */
+ if (c) SET_C;
+ if ((result ^ dest) & S08) SET_V;
+ return result;
+}
+
+/******************************************
+ rotate left through carry word
+ flags: CZSV--
+ ******************************************/
+INLINE UINT16 RLCW(z8000_state *cpustate, UINT16 dest, UINT8 twice)
+{
+ UINT16 c = dest & S16;
+ UINT16 result = (dest << 1) | GET_C;
+ CLR_CZSV;
+ if (twice) {
+ UINT16 c1 = c >> 15;
+ c = result & S16;
+ result = (result << 1) | c1;
+ }
+ CHK_XXXW_ZS; /* set Z and S flags for result word */
+ if (c) SET_C;
+ if ((result ^ dest) & S16) SET_V;
+ return result;
+}
+
+/******************************************
+ rotate right byte
+ flags: CZSV--
+ ******************************************/
+INLINE UINT8 RRB(z8000_state *cpustate, UINT8 dest, UINT8 twice)
+{
+ UINT8 result = (dest >> 1) | (dest << 7);
+ CLR_CZSV;
+ if (twice) result = (result >> 1) | (result << 7);
+ if (!result) SET_Z; else if (result & S08) SET_SC;
+ if ((result ^ dest) & S08) SET_V;
+ return result;
+}
+
+/******************************************
+ rotate right word
+ flags: CZSV--
+ ******************************************/
+INLINE UINT16 RRW(z8000_state *cpustate, UINT16 dest, UINT8 twice)
+{
+ UINT16 result = (dest >> 1) | (dest << 15);
+ CLR_CZSV;
+ if (twice) result = (result >> 1) | (result << 15);
+ if (!result) SET_Z; else if (result & S16) SET_SC;
+ if ((result ^ dest) & S16) SET_V;
+ return result;
+}
+
+/******************************************
+ rotate right through carry byte
+ flags: CZSV--
+ ******************************************/
+INLINE UINT8 RRCB(z8000_state *cpustate, UINT8 dest, UINT8 twice)
+{
+ UINT8 c = dest & 1;
+ UINT8 result = (dest >> 1) | (GET_C << 7);
+ CLR_CZSV;
+ if (twice) {
+ UINT8 c1 = c << 7;
+ c = result & 1;
+ result = (result >> 1) | c1;
+ }
+ CHK_XXXB_ZS; /* set Z and S flags for result byte */
+ if (c) SET_C;
+ if ((result ^ dest) & S08) SET_V;
+ return result;
+}
+
+/******************************************
+ rotate right through carry word
+ flags: CZSV--
+ ******************************************/
+INLINE UINT16 RRCW(z8000_state *cpustate, UINT16 dest, UINT8 twice)
+{
+ UINT16 c = dest & 1;
+ UINT16 result = (dest >> 1) | (GET_C << 15);
+ CLR_CZSV;
+ if (twice) {
+ UINT16 c1 = c << 15;
+ c = result & 1;
+ result = (result >> 1) | c1;
+ }
+ CHK_XXXW_ZS; /* set Z and S flags for result word */
+ if (c) SET_C;
+ if ((result ^ dest) & S16) SET_V;
+ return result;
+}
+
+/******************************************
+ shift dynamic arithmetic byte
+ flags: CZSV--
+ ******************************************/
+INLINE UINT8 SDAB(z8000_state *cpustate, UINT8 dest, INT8 count)
+{
+ INT8 result = (INT8) dest;
+ UINT8 c = 0;
+ CLR_CZSV;
+ while (count > 0) {
+ c = result & S08;
+ result <<= 1;
+ count--;
+ }
+ while (count < 0) {
+ c = result & 0x01;
+ result >>= 1;
+ count++;
+ }
+ CHK_XXXB_ZS; /* set Z and S flags for result byte */
+ if (c) SET_C;
+ if ((result ^ dest) & S08) SET_V;
+ return (UINT8)result;
+}
+
+/******************************************
+ shift dynamic arithmetic word
+ flags: CZSV--
+ ******************************************/
+INLINE UINT16 SDAW(z8000_state *cpustate, UINT16 dest, INT8 count)
+{
+ INT16 result = (INT16) dest;
+ UINT16 c = 0;
+ CLR_CZSV;
+ while (count > 0) {
+ c = result & S16;
+ result <<= 1;
+ count--;
+ }
+ while (count < 0) {
+ c = result & 0x0001;
+ result >>= 1;
+ count++;
+ }
+ CHK_XXXW_ZS; /* set Z and S flags for result word */
+ if (c) SET_C;
+ if ((result ^ dest) & S16) SET_V;
+ return (UINT16)result;
+}
+
+/******************************************
+ shift dynamic arithmetic long
+ flags: CZSV--
+ ******************************************/
+INLINE UINT32 SDAL(z8000_state *cpustate, UINT32 dest, INT8 count)
+{
+ INT32 result = (INT32) dest;
+ UINT32 c = 0;
+ CLR_CZSV;
+ while (count > 0) {
+ c = result & S32;
+ result <<= 1;
+ count--;
+ }
+ while (count < 0) {
+ c = result & 0x00000001;
+ result >>= 1;
+ count++;
+ }
+ CHK_XXXL_ZS; /* set Z and S flags for result long */
+ if (c) SET_C;
+ if ((result ^ dest) & S32) SET_V;
+ return (UINT32) result;
+}
+
+/******************************************
+ shift dynamic logic byte
+ flags: CZSV--
+ ******************************************/
+INLINE UINT8 SDLB(z8000_state *cpustate, UINT8 dest, INT8 count)
+{
+ UINT8 result = dest;
+ UINT8 c = 0;
+ CLR_CZSV;
+ while (count > 0) {
+ c = result & S08;
+ result <<= 1;
+ count--;
+ }
+ while (count < 0) {
+ c = result & 0x01;
+ result >>= 1;
+ count++;
+ }
+ CHK_XXXB_ZS; /* set Z and S flags for result byte */
+ if (c) SET_C;
+ if ((result ^ dest) & S08) SET_V;
+ return result;
+}
+
+/******************************************
+ shift dynamic logic word
+ flags: CZSV--
+ ******************************************/
+INLINE UINT16 SDLW(z8000_state *cpustate, UINT16 dest, INT8 count)
+{
+ UINT16 result = dest;
+ UINT16 c = 0;
+ CLR_CZSV;
+ while (count > 0) {
+ c = result & S16;
+ result <<= 1;
+ count--;
+ }
+ while (count < 0) {
+ c = result & 0x0001;
+ result >>= 1;
+ count++;
+ }
+ CHK_XXXW_ZS; /* set Z and S flags for result word */
+ if (c) SET_C;
+ if ((result ^ dest) & S16) SET_V;
+ return result;
+}
+
+/******************************************
+ shift dynamic logic long
+ flags: CZSV--
+ ******************************************/
+INLINE UINT32 SDLL(z8000_state *cpustate, UINT32 dest, INT8 count)
+{
+ UINT32 result = dest;
+ UINT32 c = 0;
+ CLR_CZSV;
+ while (count > 0) {
+ c = result & S32;
+ result <<= 1;
+ count--;
+ }
+ while (count < 0) {
+ c = result & 0x00000001;
+ result >>= 1;
+ count++;
+ }
+ CHK_XXXL_ZS; /* set Z and S flags for result long */
+ if (c) SET_C;
+ if ((result ^ dest) & S32) SET_V;
+ return result;
+}
+
+/******************************************
+ shift left arithmetic byte
+ flags: CZSV--
+ ******************************************/
+INLINE UINT8 SLAB(z8000_state *cpustate, UINT8 dest, UINT8 count)
+{
+ UINT8 c = (count) ? (dest << (count - 1)) & S08 : 0;
+ UINT8 result = (UINT8)((INT8)dest << count);
+ CLR_CZSV;
+ CHK_XXXB_ZS; /* set Z and S flags for result byte */
+ if (c) SET_C;
+ if ((result ^ dest) & S08) SET_V;
+ return result;
+}
+
+/******************************************
+ shift left arithmetic word
+ flags: CZSV--
+ ******************************************/
+INLINE UINT16 SLAW(z8000_state *cpustate, UINT16 dest, UINT8 count)
+{
+ UINT16 c = (count) ? (dest << (count - 1)) & S16 : 0;
+ UINT16 result = (UINT16)((INT16)dest << count);
+ CLR_CZSV;
+ CHK_XXXW_ZS; /* set Z and S flags for result word */
+ if (c) SET_C;
+ if ((result ^ dest) & S16) SET_V;
+ return result;
+}
+
+/******************************************
+ shift left arithmetic long
+ flags: CZSV--
+ ******************************************/
+INLINE UINT32 SLAL(z8000_state *cpustate, UINT32 dest, UINT8 count)
+{
+ UINT32 c = (count) ? (dest << (count - 1)) & S32 : 0;
+ UINT32 result = (UINT32)((INT32)dest << count);
+ CLR_CZSV;
+ CHK_XXXL_ZS; /* set Z and S flags for result long */
+ if (c) SET_C;
+ if ((result ^ dest) & S32) SET_V;
+ return result;
+}
+
+/******************************************
+ shift left logic byte
+ flags: CZS---
+ ******************************************/
+INLINE UINT8 SLLB(z8000_state *cpustate, UINT8 dest, UINT8 count)
+{
+ UINT8 c = (count) ? (dest << (count - 1)) & S08 : 0;
+ UINT8 result = dest << count;
+ CLR_CZS;
+ CHK_XXXB_ZS; /* set Z and S flags for result byte */
+ if (c) SET_C;
+ return result;
+}
+
+/******************************************
+ shift left logic word
+ flags: CZS---
+ ******************************************/
+INLINE UINT16 SLLW(z8000_state *cpustate, UINT16 dest, UINT8 count)
+{
+ UINT16 c = (count) ? (dest << (count - 1)) & S16 : 0;
+ UINT16 result = dest << count;
+ CLR_CZS;
+ CHK_XXXW_ZS; /* set Z and S flags for result word */
+ if (c) SET_C;
+ return result;
+}
+
+/******************************************
+ shift left logic long
+ flags: CZS---
+ ******************************************/
+INLINE UINT32 SLLL(z8000_state *cpustate, UINT32 dest, UINT8 count)
+{
+ UINT32 c = (count) ? (dest << (count - 1)) & S32 : 0;
+ UINT32 result = dest << count;
+ CLR_CZS;
+ CHK_XXXL_ZS; /* set Z and S flags for result long */
+ if (c) SET_C;
+ return result;
+}
+
+/******************************************
+ shift right arithmetic byte
+ flags: CZSV--
+ ******************************************/
+INLINE UINT8 SRAB(z8000_state *cpustate, UINT8 dest, UINT8 count)
+{
+ UINT8 c = (count) ? ((INT8)dest >> (count - 1)) & 1 : 0;
+ UINT8 result = (UINT8)((INT8)dest >> count);
+ CLR_CZSV;
+ CHK_XXXB_ZS; /* set Z and S flags for result byte */
+ if (c) SET_C;
+ return result;
+}
+
+/******************************************
+ shift right arithmetic word
+ flags: CZSV--
+ ******************************************/
+INLINE UINT16 SRAW(z8000_state *cpustate, UINT16 dest, UINT8 count)
+{
+ UINT8 c = (count) ? ((INT16)dest >> (count - 1)) & 1 : 0;
+ UINT16 result = (UINT16)((INT16)dest >> count);
+ CLR_CZSV;
+ CHK_XXXW_ZS; /* set Z and S flags for result word */
+ if (c) SET_C;
+ return result;
+}
+
+/******************************************
+ shift right arithmetic long
+ flags: CZSV--
+ ******************************************/
+INLINE UINT32 SRAL(z8000_state *cpustate, UINT32 dest, UINT8 count)
+{
+ UINT8 c = (count) ? ((INT32)dest >> (count - 1)) & 1 : 0;
+ UINT32 result = (UINT32)((INT32)dest >> count);
+ CLR_CZSV;
+ CHK_XXXL_ZS; /* set Z and S flags for result long */
+ if (c) SET_C;
+ return result;
+}
+
+/******************************************
+ shift right logic byte
+ flags: CZSV--
+ ******************************************/
+INLINE UINT8 SRLB(z8000_state *cpustate, UINT8 dest, UINT8 count)
+{
+ UINT8 c = (count) ? (dest >> (count - 1)) & 1 : 0;
+ UINT8 result = dest >> count;
+ CLR_CZS;
+ CHK_XXXB_ZS; /* set Z and S flags for result byte */
+ if (c) SET_C;
+ return result;
+}
+
+/******************************************
+ shift right logic word
+ flags: CZSV--
+ ******************************************/
+INLINE UINT16 SRLW(z8000_state *cpustate, UINT16 dest, UINT8 count)
+{
+ UINT8 c = (count) ? (dest >> (count - 1)) & 1 : 0;
+ UINT16 result = dest >> count;
+ CLR_CZS;
+ CHK_XXXW_ZS; /* set Z and S flags for result word */
+ if (c) SET_C;
+ return result;
+}
+
+/******************************************
+ shift right logic long
+ flags: CZSV--
+ ******************************************/
+INLINE UINT32 SRLL(z8000_state *cpustate, UINT32 dest, UINT8 count)
+{
+ UINT8 c = (count) ? (dest >> (count - 1)) & 1 : 0;
+ UINT32 result = dest >> count;
+ CLR_CZS;
+ CHK_XXXL_ZS; /* set Z and S flags for result long */
+ if (c) SET_C;
+ return result;
+}
+
+/******************************************
+ invalid
+ flags: ------
+ ******************************************/
+static void zinvalid(z8000_state *cpustate)
+{
+ logerror("Z8000 invalid opcode %04x: %04x\n", cpustate->pc, cpustate->op[0]);
+}
+
+/******************************************
+ addb rbd,imm8
+ flags: CZSVDH
+ ******************************************/
+static void Z00_0000_dddd_imm8(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_IMM8(OP1);
+ cpustate->RB(dst) = ADDB(cpustate, cpustate->RB(dst), imm8);
+}
+
+/******************************************
+ addb rbd,@rs
+ flags: CZSVDH
+ ******************************************/
+static void Z00_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RB(dst) = ADDB(cpustate, cpustate->RB(dst), RDMEM_B(cpustate, cpustate->RW(src)));
+}
+
+/******************************************
+ add rd,imm16
+ flags: CZSV--
+ ******************************************/
+static void Z01_0000_dddd_imm16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_IMM16(OP1);
+ cpustate->RW(dst) = ADDW(cpustate, cpustate->RW(dst), imm16);
+}
+
+/******************************************
+ add rd,@rs
+ flags: CZSV--
+ ******************************************/
+static void Z01_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RW(dst) = ADDW(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, cpustate->RW(src)));
+}
+
+/******************************************
+ subb rbd,imm8
+ flags: CZSVDH
+ ******************************************/
+static void Z02_0000_dddd_imm8(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_IMM8(OP1);
+ cpustate->RB(dst) = SUBB(cpustate, cpustate->RB(dst), imm8);
+}
+
+/******************************************
+ subb rbd,@rs
+ flags: CZSVDH
+ ******************************************/
+static void Z02_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RB(dst) = SUBB(cpustate, cpustate->RB(dst), RDMEM_B(cpustate, cpustate->RW(src))); /* EHC */
+}
+
+/******************************************
+ sub rd,imm16
+ flags: CZSV--
+ ******************************************/
+static void Z03_0000_dddd_imm16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_IMM16(OP1);
+ cpustate->RW(dst) = SUBW(cpustate, cpustate->RW(dst), imm16);
+}
+
+/******************************************
+ sub rd,@rs
+ flags: CZSV--
+ ******************************************/
+static void Z03_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RW(dst) = SUBW(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, cpustate->RW(src)));
+}
+
+/******************************************
+ orb rbd,imm8
+ flags: CZSP--
+ ******************************************/
+static void Z04_0000_dddd_imm8(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_IMM8(OP1);
+ cpustate->RB(dst) = ORB(cpustate, cpustate->RB(dst), imm8);
+}
+
+/******************************************
+ orb rbd,@rs
+ flags: CZSP--
+ ******************************************/
+static void Z04_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RB(dst) = ORB(cpustate, cpustate->RB(dst), RDMEM_B(cpustate, cpustate->RW(src)));
+}
+
+/******************************************
+ or rd,imm16
+ flags: CZS---
+ ******************************************/
+static void Z05_0000_dddd_imm16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_IMM16(OP1);
+ cpustate->RW(dst) = ORW(cpustate, cpustate->RW(dst), imm16);
+}
+
+/******************************************
+ or rd,@rs
+ flags: CZS---
+ ******************************************/
+static void Z05_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RW(dst) = ORW(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, cpustate->RW(src)));
+}
+
+/******************************************
+ andb rbd,imm8
+ flags: -ZSP--
+ ******************************************/
+static void Z06_0000_dddd_imm8(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_IMM8(OP1);
+ cpustate->RB(dst) = ANDB(cpustate, cpustate->RB(dst), imm8);
+}
+
+/******************************************
+ andb rbd,@rs
+ flags: -ZSP--
+ ******************************************/
+static void Z06_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RB(dst) = ANDB(cpustate, cpustate->RB(dst), RDMEM_B(cpustate, cpustate->RW(src)));
+}
+
+/******************************************
+ and rd,imm16
+ flags: -ZS---
+ ******************************************/
+static void Z07_0000_dddd_imm16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_IMM16(OP1);
+ cpustate->RW(dst) = ANDW(cpustate, cpustate->RW(dst), imm16);
+}
+
+/******************************************
+ and rd,@rs
+ flags: -ZS---
+ ******************************************/
+static void Z07_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RW(dst) = ANDW(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, cpustate->RW(src)));
+}
+
+/******************************************
+ xorb rbd,imm8
+ flags: -ZSP--
+ ******************************************/
+static void Z08_0000_dddd_imm8(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_IMM8(OP1);
+ cpustate->RB(dst) = XORB(cpustate, cpustate->RB(dst), imm8);
+}
+
+/******************************************
+ xorb rbd,@rs
+ flags: -ZSP--
+ ******************************************/
+static void Z08_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RB(dst) = XORB(cpustate, cpustate->RB(dst), RDMEM_B(cpustate, cpustate->RW(src)));
+}
+
+/******************************************
+ xor rd,imm16
+ flags: -ZS---
+ ******************************************/
+static void Z09_0000_dddd_imm16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_IMM16(OP1);
+ cpustate->RW(dst) = XORW(cpustate, cpustate->RW(dst), imm16);
+}
+
+/******************************************
+ xor rd,@rs
+ flags: -ZS---
+ ******************************************/
+static void Z09_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RW(dst) = XORW(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, cpustate->RW(src)));
+}
+
+/******************************************
+ cpb rbd,imm8
+ flags: CZSV--
+ ******************************************/
+static void Z0A_0000_dddd_imm8(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_IMM8(OP1);
+ CPB(cpustate, cpustate->RB(dst), imm8);
+}
+
+/******************************************
+ cpb rbd,@rs
+ flags: CZSV--
+ ******************************************/
+static void Z0A_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ CPB(cpustate, cpustate->RB(dst), RDMEM_B(cpustate, cpustate->RW(src)));
+}
+
+/******************************************
+ cp rd,imm16
+ flags: CZSV--
+ ******************************************/
+static void Z0B_0000_dddd_imm16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_IMM16(OP1);
+ CPW(cpustate, cpustate->RW(dst), imm16);
+}
+
+/******************************************
+ cp rd,@rs
+ flags: CZSV--
+ ******************************************/
+static void Z0B_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ CPW(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, cpustate->RW(src)));
+}
+
+/******************************************
+ comb @rd
+ flags: -ZSP--
+ ******************************************/
+static void Z0C_ddN0_0000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ WRMEM_B(cpustate, cpustate->RW(dst), COMB(cpustate, RDMEM_B(cpustate, cpustate->RW(dst))));
+}
+
+/******************************************
+ cpb @rd,imm8
+ flags: CZSV--
+ ******************************************/
+static void Z0C_ddN0_0001_imm8(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_IMM8(OP1);
+ CPB(cpustate, cpustate->RB(dst), imm8);
+}
+
+/******************************************
+ negb @rd
+ flags: CZSV--
+ ******************************************/
+static void Z0C_ddN0_0010(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ WRMEM_B(cpustate, cpustate->RW(dst), NEGB(cpustate, RDMEM_B(cpustate, cpustate->RW(dst))));
+}
+
+/******************************************
+ testb @rd
+ flags: -ZSP--
+ ******************************************/
+static void Z0C_ddN0_0100(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ TESTB(cpustate, RDMEM_B(cpustate, cpustate->RW(dst)));
+}
+
+/******************************************
+ ldb @rd,imm8
+ flags: ------
+ ******************************************/
+static void Z0C_ddN0_0101_imm8(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_IMM8(OP1);
+ WRMEM_B(cpustate, cpustate->RW(dst), imm8);
+}
+
+/******************************************
+ tsetb @rd
+ flags: --S---
+ ******************************************/
+static void Z0C_ddN0_0110(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ if (RDMEM_B(cpustate, cpustate->RW(dst)) & S08) SET_S; else CLR_S;
+ WRMEM_B(cpustate, cpustate->RW(dst), 0xff);
+}
+
+/******************************************
+ clrb @rd
+ flags: ------
+ ******************************************/
+static void Z0C_ddN0_1000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ WRMEM_B(cpustate, cpustate->RW(dst), 0);
+}
+
+/******************************************
+ com @rd
+ flags: -ZS---
+ ******************************************/
+static void Z0D_ddN0_0000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ WRMEM_W(cpustate, cpustate->RW(dst), COMW(cpustate, RDMEM_W(cpustate, cpustate->RW(dst))));
+}
+
+/******************************************
+ cp @rd,imm16
+ flags: CZSV--
+ ******************************************/
+static void Z0D_ddN0_0001_imm16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_IMM16(OP1);
+ CPW(cpustate, RDMEM_W(cpustate, cpustate->RW(dst)), imm16);
+}
+
+/******************************************
+ neg @rd
+ flags: CZSV--
+ ******************************************/
+static void Z0D_ddN0_0010(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ WRMEM_W(cpustate, cpustate->RW(dst), NEGW(cpustate, RDMEM_W(cpustate, cpustate->RW(dst))));
+}
+
+/******************************************
+ test @rd
+ flags: -ZS---
+ ******************************************/
+static void Z0D_ddN0_0100(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ TESTW(cpustate, RDMEM_W(cpustate, cpustate->RW(dst)));
+}
+
+/******************************************
+ ld @rd,imm16
+ flags: ------
+ ******************************************/
+static void Z0D_ddN0_0101_imm16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_IMM16(OP1);
+ WRMEM_W(cpustate, cpustate->RW(dst), imm16);
+}
+
+/******************************************
+ tset @rd
+ flags: --S---
+ ******************************************/
+static void Z0D_ddN0_0110(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ if (RDMEM_W(cpustate, cpustate->RW(dst)) & S16) SET_S; else CLR_S;
+ WRMEM_W(cpustate, cpustate->RW(dst), 0xffff);
+}
+
+/******************************************
+ clr @rd
+ flags: ------
+ ******************************************/
+static void Z0D_ddN0_1000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ WRMEM_W(cpustate, RDMEM_W(cpustate, cpustate->RW(dst)), 0);
+}
+
+/******************************************
+ push @rd,imm16
+ flags: ------
+ ******************************************/
+static void Z0D_ddN0_1001_imm16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_IMM16(OP1);
+ PUSHW(cpustate, dst, imm16);
+}
+
+/******************************************
+ ext0e imm8
+ flags: ------
+ ******************************************/
+static void Z0E_imm8(z8000_state *cpustate)
+{
+ GET_IMM8(0);
+ LOG(("Z8K '%s' %04x: ext0e $%02x\n", cpustate->device->tag(), cpustate->pc, imm8));
+ if (cpustate->fcw & F_EPU) {
+ /* Z8001 EPU code goes here */
+ (void)imm8;
+ }
+}
+
+/******************************************
+ ext0f imm8
+ flags: ------
+ ******************************************/
+static void Z0F_imm8(z8000_state *cpustate)
+{
+ GET_IMM8(0);
+ LOG(("Z8K '%s' %04x: ext0f $%02x\n", cpustate->device->tag(), cpustate->pc, imm8));
+ if (cpustate->fcw & F_EPU) {
+ /* Z8001 EPU code goes here */
+ (void)imm8;
+ }
+}
+
+/******************************************
+ cpl rrd,imm32
+ flags: CZSV--
+ ******************************************/
+static void Z10_0000_dddd_imm32(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_IMM32;
+ CPL(cpustate, cpustate->RL(dst), imm32);
+}
+
+/******************************************
+ cpl rrd,@rs
+ flags: CZSV--
+ ******************************************/
+static void Z10_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ CPL(cpustate, cpustate->RL(dst), RDMEM_L(cpustate, cpustate->RW(src)));
+}
+
+/******************************************
+ pushl @rd,@rs
+ flags: ------
+ ******************************************/
+static void Z11_ddN0_ssN0(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ PUSHL(cpustate, dst, RDMEM_L(cpustate, cpustate->RW(src)));
+}
+
+/******************************************
+ subl rrd,imm32
+ flags: CZSV--
+ ******************************************/
+static void Z12_0000_dddd_imm32(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_IMM32;
+ cpustate->RL(dst) = SUBL(cpustate, cpustate->RL(dst), imm32);
+}
+
+/******************************************
+ subl rrd,@rs
+ flags: CZSV--
+ ******************************************/
+static void Z12_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RL(dst) = SUBL(cpustate, cpustate->RL(dst), RDMEM_L(cpustate, cpustate->RW(src)));
+}
+
+/******************************************
+ push @rd,@rs
+ flags: ------
+ ******************************************/
+static void Z13_ddN0_ssN0(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ PUSHW(cpustate, dst, RDMEM_W(cpustate, cpustate->RW(src)));
+}
+
+/******************************************
+ ldl rrd,imm32
+ flags: ------
+ ******************************************/
+static void Z14_0000_dddd_imm32(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_IMM32;
+ cpustate->RL(dst) = imm32;
+}
+
+/******************************************
+ ldl rrd,@rs
+ flags: ------
+ ******************************************/
+static void Z14_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RL(dst) = RDMEM_L(cpustate, cpustate->RW(src));
+}
+
+/******************************************
+ popl @rd,@rs
+ flags: ------
+ ******************************************/
+static void Z15_ssN0_ddN0(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RL(dst) = POPL(cpustate, src);
+}
+
+/******************************************
+ addl rrd,imm32
+ flags: CZSV--
+ ******************************************/
+static void Z16_0000_dddd_imm32(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_IMM32;
+ cpustate->RL(dst) = ADDL(cpustate, cpustate->RL(dst), imm32);
+}
+
+/******************************************
+ addl rrd,@rs
+ flags: CZSV--
+ ******************************************/
+static void Z16_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RL(dst) = ADDL(cpustate, cpustate->RL(dst), RDMEM_L(cpustate, cpustate->RW(src)));
+}
+
+/******************************************
+ pop @rd,@rs
+ flags: ------
+ ******************************************/
+static void Z17_ssN0_ddN0(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RW(dst) = POPW(cpustate, src);
+}
+
+/******************************************
+ multl rqd,@rs
+ flags: CZSV--
+ ******************************************/
+static void Z18_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RQ(dst) = MULTL(cpustate, cpustate->RQ(dst), cpustate->RL(src));
+}
+
+/******************************************
+ mult rrd,imm16
+ flags: CZSV--
+ ******************************************/
+static void Z19_0000_dddd_imm16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_IMM16(OP1);
+ cpustate->RL(dst) = MULTW(cpustate, cpustate->RL(dst), imm16);
+}
+
+/******************************************
+ mult rrd,@rs
+ flags: CZSV--
+ ******************************************/
+static void Z19_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RL(dst) = MULTW(cpustate, cpustate->RL(dst), RDMEM_W(cpustate, cpustate->RW(src)));
+}
+
+/******************************************
+ divl rqd,imm32
+ flags: CZSV--
+ ******************************************/
+static void Z1A_0000_dddd_imm32(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_IMM32;
+ cpustate->RQ(dst) = DIVL(cpustate, cpustate->RQ(dst), imm32);
+}
+
+/******************************************
+ divl rqd,@rs
+ flags: CZSV--
+ ******************************************/
+static void Z1A_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RQ(dst) = DIVL(cpustate, cpustate->RQ(dst), RDMEM_L(cpustate, cpustate->RW(src)));
+}
+
+/******************************************
+ div rrd,imm16
+ flags: CZSV--
+ ******************************************/
+static void Z1B_0000_dddd_imm16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_IMM16(OP1);
+ cpustate->RL(dst) = DIVW(cpustate, cpustate->RL(dst), imm16);
+}
+
+/******************************************
+ div rrd,@rs
+ flags: CZSV--
+ ******************************************/
+static void Z1B_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RL(dst) = DIVW(cpustate, cpustate->RL(dst), RDMEM_W(cpustate, cpustate->RW(src)));
+}
+
+/******************************************
+ testl @rd
+ flags: -ZS---
+ ******************************************/
+static void Z1C_ddN0_1000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ TESTL(cpustate, RDMEM_L(cpustate, cpustate->RW(dst)));
+}
+
+/******************************************
+ ldm @rd,rs,n
+ flags: ------
+ ******************************************/
+static void Z1C_ddN0_1001_0000_ssss_0000_nmin1(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_CNT(OP1,NIB3);
+ GET_SRC(OP1,NIB1);
+ UINT16 idx = cpustate->RW(dst);
+ while (cnt-- >= 0) {
+ WRMEM_W(cpustate, idx, cpustate->RW(src));
+ idx = (idx + 2) & 0xffff;
+ src = (src+1) & 15;
+ }
+}
+
+/******************************************
+ ldm rd,@rs,n
+ flags: ------
+ ******************************************/
+static void Z1C_ssN0_0001_0000_dddd_0000_nmin1(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CNT(OP1,NIB3);
+ GET_DST(OP1,NIB1);
+ UINT16 idx = cpustate->RW(src);
+ while (cnt-- >= 0) {
+ cpustate->RW(dst) = RDMEM_W(cpustate, idx);
+ idx = (idx + 2) & 0xffff;
+ dst = (dst+1) & 15;
+ }
+}
+
+/******************************************
+ ldl @rd,rrs
+ flags: ------
+ ******************************************/
+static void Z1D_ddN0_ssss(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ WRMEM_L(cpustate, cpustate->RW(dst), cpustate->RL(src));
+}
+
+/******************************************
+ jp cc,rd
+ flags: ------
+ ******************************************/
+static void Z1E_ddN0_cccc(z8000_state *cpustate)
+{
+ GET_CCC(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ switch (cc) {
+ case 0: if (CC0) cpustate->pc = cpustate->RW(dst); break;
+ case 1: if (CC1) cpustate->pc = cpustate->RW(dst); break;
+ case 2: if (CC2) cpustate->pc = cpustate->RW(dst); break;
+ case 3: if (CC3) cpustate->pc = cpustate->RW(dst); break;
+ case 4: if (CC4) cpustate->pc = cpustate->RW(dst); break;
+ case 5: if (CC5) cpustate->pc = cpustate->RW(dst); break;
+ case 6: if (CC6) cpustate->pc = cpustate->RW(dst); break;
+ case 7: if (CC7) cpustate->pc = cpustate->RW(dst); break;
+ case 8: if (CC8) cpustate->pc = cpustate->RW(dst); break;
+ case 9: if (CC9) cpustate->pc = cpustate->RW(dst); break;
+ case 10: if (CCA) cpustate->pc = cpustate->RW(dst); break;
+ case 11: if (CCB) cpustate->pc = cpustate->RW(dst); break;
+ case 12: if (CCC) cpustate->pc = cpustate->RW(dst); break;
+ case 13: if (CCD) cpustate->pc = cpustate->RW(dst); break;
+ case 14: if (CCE) cpustate->pc = cpustate->RW(dst); break;
+ case 15: if (CCF) cpustate->pc = cpustate->RW(dst); break;
+ }
+}
+
+/******************************************
+ call @rd
+ flags: ------
+ ******************************************/
+static void Z1F_ddN0_0000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ PUSHW(cpustate, SP, cpustate->pc);
+ cpustate->pc = cpustate->RW(dst);
+}
+
+/******************************************
+ ldb rbd,@rs
+ flags: ------
+ ******************************************/
+static void Z20_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RB(dst) = RDMEM_B(cpustate, cpustate->RW(src));
+}
+
+static void Z20_ssN0_dddd_seg(z8000_state *cpustate)
+{
+ UINT32 addr;
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ addr = (cpustate->RW(src) & 0x0007) << 16;
+ addr|= cpustate->RW(src+1) & 0xffff;
+ cpustate->RB(dst) = RDMEM_B(cpustate, addr);
+ //cycles?
+}
+
+/******************************************
+ ld rd,imm16
+ flags: ------
+ ******************************************/
+static void Z21_0000_dddd_imm16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_IMM16(OP1);
+ cpustate->RW(dst) = imm16;
+}
+
+/******************************************
+ ld rd,@rs
+ flags: ------
+ ******************************************/
+static void Z21_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RW(dst) = RDMEM_W(cpustate, cpustate->RW(src));
+}
+
+/******************************************
+ resb rbd,rs
+ flags: ------
+ ******************************************/
+static void Z22_0000_ssss_0000_dddd_0000_0000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DST(OP1,NIB1);
+ cpustate->RB(dst) = cpustate->RB(dst) & ~(1 << (cpustate->RW(src) & 7));
+}
+
+/******************************************
+ resb @rd,imm4
+ flags: ------
+ ******************************************/
+static void Z22_ddN0_imm4(z8000_state *cpustate)
+{
+ GET_BIT(OP0);
+ GET_DST(OP0,NIB2);
+ WRMEM_B(cpustate, cpustate->RW(dst), RDMEM_B(cpustate, cpustate->RW(dst)) & ~bit);
+}
+
+/******************************************
+ result rd,rs
+ flags: ------
+ ******************************************/
+static void Z23_0000_ssss_0000_dddd_0000_0000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DST(OP1,NIB1);
+ cpustate->RW(dst) = cpustate->RW(dst) & ~(1 << (cpustate->RW(src) & 15));
+}
+
+/******************************************
+ res @rd,imm4
+ flags: ------
+ ******************************************/
+static void Z23_ddN0_imm4(z8000_state *cpustate)
+{
+ GET_BIT(OP0);
+ GET_DST(OP0,NIB2);
+ WRMEM_W(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, cpustate->RW(dst)) & ~bit);
+}
+
+/******************************************
+ setb rbd,rs
+ flags: ------
+ ******************************************/
+static void Z24_0000_ssss_0000_dddd_0000_0000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DST(OP1,NIB1);
+ cpustate->RB(dst) = cpustate->RB(dst) | (1 << (cpustate->RW(src) & 7));
+}
+
+/******************************************
+ setb @rd,imm4
+ flags: ------
+ ******************************************/
+static void Z24_ddN0_imm4(z8000_state *cpustate)
+{
+ GET_BIT(OP0);
+ GET_DST(OP0,NIB2);
+ WRMEM_B(cpustate, cpustate->RW(dst), RDMEM_B(cpustate, cpustate->RW(dst)) | bit);
+}
+
+/******************************************
+ set rd,rs
+ flags: ------
+ ******************************************/
+static void Z25_0000_ssss_0000_dddd_0000_0000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DST(OP1,NIB1);
+ cpustate->RW(dst) = cpustate->RW(dst) | (1 << (cpustate->RW(src) & 15));
+}
+
+/******************************************
+ set @rd,imm4
+ flags: ------
+ ******************************************/
+static void Z25_ddN0_imm4(z8000_state *cpustate)
+{
+ GET_BIT(OP0);
+ GET_DST(OP0,NIB2);
+ WRMEM_W(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, cpustate->RW(dst)) | bit);
+}
+
+/******************************************
+ bitb rbd,rs
+ flags: -Z----
+ ******************************************/
+static void Z26_0000_ssss_0000_dddd_0000_0000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DST(OP1,NIB1);
+ if (cpustate->RB(dst) & (1 << (cpustate->RW(src) & 7))) CLR_Z; else SET_Z;
+}
+
+/******************************************
+ bitb @rd,imm4
+ flags: -Z----
+ ******************************************/
+static void Z26_ddN0_imm4(z8000_state *cpustate)
+{
+ GET_BIT(OP0);
+ GET_DST(OP0,NIB2);
+ if (RDMEM_B(cpustate, cpustate->RW(dst)) & bit) CLR_Z; else SET_Z;
+}
+
+/******************************************
+ bit rd,rs
+ flags: -Z----
+ ******************************************/
+static void Z27_0000_ssss_0000_dddd_0000_0000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DST(OP1,NIB1);
+ if (cpustate->RW(dst) & (1 << (cpustate->RW(src) & 15))) CLR_Z; else SET_Z;
+}
+
+/******************************************
+ bit @rd,imm4
+ flags: -Z----
+ ******************************************/
+static void Z27_ddN0_imm4(z8000_state *cpustate)
+{
+ GET_BIT(OP0);
+ GET_DST(OP0,NIB2);
+ if (RDMEM_W(cpustate, cpustate->RW(dst)) & bit) CLR_Z; else SET_Z;
+}
+
+/******************************************
+ incb @rd,imm4m1
+ flags: -ZSV--
+ ******************************************/
+static void Z28_ddN0_imm4m1(z8000_state *cpustate)
+{
+ GET_I4M1(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ WRMEM_B(cpustate, cpustate->RW(dst), INCB(cpustate, RDMEM_B(cpustate, cpustate->RW(dst)), i4p1));
+}
+
+/******************************************
+ inc @rd,imm4m1
+ flags: -ZSV--
+ ******************************************/
+static void Z29_ddN0_imm4m1(z8000_state *cpustate)
+{
+ GET_I4M1(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ WRMEM_W(cpustate, cpustate->RW(dst), INCW(cpustate, RDMEM_W(cpustate, cpustate->RW(dst)), i4p1));
+}
+
+/******************************************
+ decb @rd,imm4m1
+ flags: -ZSV--
+ ******************************************/
+static void Z2A_ddN0_imm4m1(z8000_state *cpustate)
+{
+ GET_I4M1(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ WRMEM_B(cpustate, cpustate->RW(dst), DECB(cpustate, RDMEM_B(cpustate, cpustate->RW(dst)), i4p1));
+}
+
+/******************************************
+ dec @rd,imm4m1
+ flags: -ZSV--
+ ******************************************/
+static void Z2B_ddN0_imm4m1(z8000_state *cpustate)
+{
+ GET_I4M1(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ WRMEM_W(cpustate, cpustate->RW(dst), DECW(cpustate, RDMEM_W(cpustate, cpustate->RW(dst)), i4p1));
+}
+
+/******************************************
+ exb rbd,@rs
+ flags: ------
+ ******************************************/
+static void Z2C_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ UINT8 tmp = RDMEM_B(cpustate, cpustate->RW(src));
+ WRMEM_B(cpustate, cpustate->RW(src), cpustate->RB(dst));
+ cpustate->RB(dst) = tmp;
+}
+
+/******************************************
+ ex rd,@rs
+ flags: ------
+ ******************************************/
+static void Z2D_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ UINT16 tmp = RDMEM_W(cpustate, cpustate->RW(src));
+ WRMEM_W(cpustate, cpustate->RW(src), cpustate->RW(dst));
+ cpustate->RW(dst) = tmp;
+}
+
+/******************************************
+ ldb @rd,rbs
+ flags: ------
+ ******************************************/
+static void Z2E_ddN0_ssss(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ WRMEM_B(cpustate, cpustate->RW(dst), cpustate->RB(src));
+}
+
+/******************************************
+ ld @rd,rs
+ flags: ------
+ ******************************************/
+static void Z2F_ddN0_ssss(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ WRMEM_W(cpustate, cpustate->RW(dst), cpustate->RW(src));
+}
+
+/******************************************
+ ldrb rbd,dsp16
+ flags: ------
+ ******************************************/
+static void Z30_0000_dddd_dsp16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_DSP16;
+ cpustate->RB(dst) = RDMEM_B(cpustate, dsp16);
+}
+
+/******************************************
+ ldb rbd,rs(imm16)
+ flags: ------
+ ******************************************/
+static void Z30_ssN0_dddd_imm16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_IMM16(OP1);
+ imm16 += cpustate->RW(src);
+ cpustate->RB(dst) = RDMEM_B(cpustate, imm16);
+}
+
+/******************************************
+ ldr rd,dsp16
+ flags: ------
+ ******************************************/
+static void Z31_0000_dddd_dsp16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_DSP16;
+ cpustate->RW(dst) = RDMEM_W(cpustate, dsp16);
+}
+
+/******************************************
+ ld rd,rs(imm16)
+ flags: ------
+ ******************************************/
+static void Z31_ssN0_dddd_imm16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_IMM16(OP1);
+ imm16 += cpustate->RW(src);
+ cpustate->RW(dst) = RDMEM_W(cpustate, imm16);
+}
+
+/******************************************
+ ldrb dsp16,rbs
+ flags: ------
+ ******************************************/
+static void Z32_0000_ssss_dsp16(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DSP16;
+ WRMEM_B(cpustate, dsp16, cpustate->RB(src));
+}
+
+/******************************************
+ ldb rd(imm16),rbs
+ flags: ------
+ ******************************************/
+static void Z32_ddN0_ssss_imm16(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ GET_IMM16(OP1);
+ imm16 += cpustate->RW(dst);
+ WRMEM_B(cpustate, imm16, cpustate->RB(src));
+}
+
+/******************************************
+ ldr dsp16,rs
+ flags: ------
+ ******************************************/
+static void Z33_0000_ssss_dsp16(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DSP16;
+ WRMEM_W(cpustate, dsp16, cpustate->RW(src));
+}
+
+/******************************************
+ ld rd(imm16),rs
+ flags: ------
+ ******************************************/
+static void Z33_ddN0_ssss_imm16(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ GET_IMM16(OP1);
+ imm16 += cpustate->RW(dst);
+ WRMEM_W(cpustate, imm16, cpustate->RW(src));
+}
+
+/******************************************
+ ldar prd,dsp16
+ flags: ------
+ ******************************************/
+static void Z34_0000_dddd_dsp16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_DSP16;
+ cpustate->RW(dst) = dsp16;
+}
+
+/******************************************
+ lda prd,rs(imm16)
+ flags: ------
+ ******************************************/
+static void Z34_ssN0_dddd_imm16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_IMM16(OP1);
+ imm16 += cpustate->RW(src);
+ cpustate->RW(dst) = imm16;
+}
+
+/******************************************
+ ldrl rrd,dsp16
+ flags: ------
+ ******************************************/
+static void Z35_0000_dddd_dsp16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_DSP16;
+ cpustate->RL(dst) = RDMEM_L(cpustate, dsp16);
+}
+
+/******************************************
+ ldl rrd,rs(imm16)
+ flags: ------
+ ******************************************/
+static void Z35_ssN0_dddd_imm16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_IMM16(OP1);
+ imm16 += cpustate->RW(src);
+ cpustate->RL(dst) = RDMEM_L(cpustate, imm16);
+}
+
+/******************************************
+ bpt
+ flags: ------
+ ******************************************/
+static void Z36_0000_0000(z8000_state *cpustate)
+{
+ /* execute break point trap cpustate->irq_req */
+ cpustate->irq_req = Z8000_TRAP;
+}
+
+/******************************************
+ rsvd36
+ flags: ------
+ ******************************************/
+static void Z36_imm8(z8000_state *cpustate)
+{
+ GET_IMM8(0);
+ LOG(("Z8K '%s' %04x: rsvd36 $%02x\n", cpustate->device->tag(), cpustate->pc, imm8));
+ if (cpustate->fcw & F_EPU) {
+ /* Z8001 EPU code goes here */
+ (void)imm8;
+ }
+}
+
+/******************************************
+ ldrl dsp16,rrs
+ flags: ------
+ ******************************************/
+static void Z37_0000_ssss_dsp16(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DSP16;
+ WRMEM_L(cpustate, dsp16, cpustate->RL(src));
+}
+
+/******************************************
+ ldl rd(imm16),rrs
+ flags: ------
+ ******************************************/
+static void Z37_ddN0_ssss_imm16(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ GET_IMM16(OP1);
+ imm16 += cpustate->RW(dst);
+ WRMEM_L(cpustate, imm16, cpustate->RL(src));
+}
+
+/******************************************
+ rsvd38
+ flags: ------
+ ******************************************/
+static void Z38_imm8(z8000_state *cpustate)
+{
+ GET_IMM8(0);
+ LOG(("Z8K '%s' %04x: rsvd38 $%02x\n", cpustate->device->tag(), cpustate->pc, imm8));
+ if (cpustate->fcw & F_EPU) {
+ /* Z8001 EPU code goes here */
+ (void)imm8;
+ }
+}
+
+/******************************************
+ ldps @rs
+ flags: CZSVDH
+ ******************************************/
+static void Z39_ssN0_0000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ UINT16 fcw;
+ fcw = RDMEM_W(cpustate, cpustate->RW(src));
+ cpustate->pc = RDMEM_W(cpustate, (UINT16)(cpustate->RW(src) + 2));
+ CHANGE_FCW(cpustate, fcw); /* check for user/system mode change */
+}
+
+/******************************************
+ inib(r) @rd,@rs,ra
+ flags: ---V--
+ ******************************************/
+static void Z3A_ssss_0000_0000_aaaa_dddd_x000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CNT(OP1,NIB1);
+ GET_DST(OP1,NIB2);
+ GET_CCC(OP1,NIB3);
+ WRMEM_B(cpustate, cpustate->RW(dst), RDPORT_B(cpustate, 0, cpustate->RW(src)));
+ cpustate->RW(dst)++;
+ cpustate->RW(src)++;
+ if (--cpustate->RW(cnt)) { CLR_V; if (cc == 0) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ sinib @rd,@rs,ra
+ sinibr @rd,@rs,ra
+ flags: ------
+ ******************************************/
+static void Z3A_ssss_0001_0000_aaaa_dddd_x000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CNT(OP1,NIB1);
+ GET_DST(OP1,NIB2);
+ GET_CCC(OP1,NIB3);
+ WRMEM_B(cpustate, cpustate->RW(dst), RDPORT_B(cpustate, 1, cpustate->RW(src)));
+ cpustate->RW(dst)++;
+ cpustate->RW(src)++;
+ if (--cpustate->RW(cnt)) { CLR_V; if (cc == 0) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ outib @rd,@rs,ra
+ outibr @rd,@rs,ra
+ flags: ---V--
+ ******************************************/
+static void Z3A_ssss_0010_0000_aaaa_dddd_x000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CNT(OP1,NIB1);
+ GET_DST(OP1,NIB2);
+ GET_CCC(OP1,NIB3);
+ WRPORT_B(cpustate, 0, cpustate->RW(dst), RDMEM_B(cpustate, cpustate->RW(src)));
+ cpustate->RW(dst)++;
+ cpustate->RW(src)++;
+ if (--cpustate->RW(cnt)) { CLR_V; if (cc == 0) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ soutib @rd,@rs,ra
+ soutibr @rd,@rs,ra
+ flags: ------
+ ******************************************/
+static void Z3A_ssss_0011_0000_aaaa_dddd_x000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CNT(OP1,NIB1);
+ GET_DST(OP1,NIB2);
+ GET_CCC(OP1,NIB3);
+ WRPORT_B(cpustate, 1, cpustate->RW(dst), RDMEM_B(cpustate, cpustate->RW(src)));
+ cpustate->RW(dst)++;
+ cpustate->RW(src)++;
+ if (--cpustate->RW(cnt)) { CLR_V; if (cc == 0) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ inb rbd,imm16
+ flags: ------
+ ******************************************/
+static void Z3A_dddd_0100_imm16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_IMM16(OP1);
+ cpustate->RB(dst) = RDPORT_B(cpustate, 0, imm16);
+}
+
+/******************************************
+ sinb rbd,imm16
+ flags: ------
+ ******************************************/
+static void Z3A_dddd_0101_imm16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_IMM16(OP1);
+ cpustate->RB(dst) = RDPORT_B(cpustate, 1, imm16);
+}
+
+/******************************************
+ outb imm16,rbs
+ flags: ---V--
+ ******************************************/
+static void Z3A_ssss_0110_imm16(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_IMM16(OP1);
+ WRPORT_B(cpustate, 0, imm16, cpustate->RB(src));
+}
+
+/******************************************
+ soutb imm16,rbs
+ flags: ------
+ ******************************************/
+static void Z3A_ssss_0111_imm16(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_IMM16(OP1);
+ WRPORT_B(cpustate, 1, imm16, cpustate->RB(src));
+}
+
+/******************************************
+ indb @rd,@rs,rba
+ indbr @rd,@rs,rba
+ flags: ---V--
+ ******************************************/
+static void Z3A_ssss_1000_0000_aaaa_dddd_x000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CNT(OP1,NIB1);
+ GET_DST(OP1,NIB2);
+ GET_CCC(OP1,NIB3);
+ WRMEM_B(cpustate, cpustate->RW(dst), RDPORT_B(cpustate, 0, cpustate->RW(src)));
+ cpustate->RW(dst)--;
+ cpustate->RW(src)--;
+ if (--cpustate->RW(cnt)) { CLR_V; if (cc == 0) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ sindb @rd,@rs,rba
+ sindbr @rd,@rs,rba
+ flags: ------
+ ******************************************/
+static void Z3A_ssss_1001_0000_aaaa_dddd_x000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CNT(OP1,NIB1);
+ GET_DST(OP1,NIB2);
+ GET_CCC(OP1,NIB3);
+ WRMEM_B(cpustate, cpustate->RW(dst), RDPORT_B(cpustate, 1, cpustate->RW(src)));
+ cpustate->RW(dst)--;
+ cpustate->RW(src)--;
+ if (--cpustate->RW(cnt)) { CLR_V; if (cc == 0) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ outdb @rd,@rs,rba
+ outdbr @rd,@rs,rba
+ flags: ---V--
+ ******************************************/
+static void Z3A_ssss_1010_0000_aaaa_dddd_x000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CNT(OP1,NIB1);
+ GET_DST(OP1,NIB2);
+ GET_CCC(OP1,NIB3);
+ WRPORT_B(cpustate, 0, cpustate->RW(dst), RDMEM_B(cpustate, cpustate->RW(src)));
+ cpustate->RW(dst)--;
+ cpustate->RW(src)--;
+ if (--cpustate->RW(cnt)) { CLR_V; if (cc == 0) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ soutdb @rd,@rs,rba
+ soutdbr @rd,@rs,rba
+ flags: ------
+ ******************************************/
+static void Z3A_ssss_1011_0000_aaaa_dddd_x000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CNT(OP1,NIB1);
+ GET_DST(OP1,NIB2);
+ GET_CCC(OP1,NIB3);
+ WRPORT_B(cpustate, 1, cpustate->RW(dst), RDMEM_B(cpustate, cpustate->RW(src)));
+ cpustate->RW(dst)--;
+ cpustate->RW(src)--;
+ if (--cpustate->RW(cnt)) { CLR_V; if (cc == 0) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ ini @rd,@rs,ra
+ inir @rd,@rs,ra
+ flags: ---V--
+ ******************************************/
+static void Z3B_ssss_0000_0000_aaaa_dddd_x000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CNT(OP1,NIB1);
+ GET_DST(OP1,NIB2);
+ GET_CCC(OP1,NIB3);
+ WRMEM_W(cpustate, cpustate->RW(dst), RDPORT_W(cpustate, 0, cpustate->RW(src)));
+ cpustate->RW(dst) += 2;
+ cpustate->RW(src) += 2;
+ if (--cpustate->RW(cnt)) { CLR_V; if (cc == 0) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ sini @rd,@rs,ra
+ sinir @rd,@rs,ra
+ flags: ------
+ ******************************************/
+static void Z3B_ssss_0001_0000_aaaa_dddd_x000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CNT(OP1,NIB1);
+ GET_DST(OP1,NIB2);
+ GET_CCC(OP1,NIB3);
+ WRMEM_W(cpustate, cpustate->RW(dst), RDPORT_W(cpustate, 1, cpustate->RW(src)));
+ cpustate->RW(dst) += 2;
+ cpustate->RW(src) += 2;
+ if (--cpustate->RW(cnt)) { CLR_V; if (cc == 0) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ outi @rd,@rs,ra
+ outir @rd,@rs,ra
+ flags: ---V--
+ ******************************************/
+static void Z3B_ssss_0010_0000_aaaa_dddd_x000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CNT(OP1,NIB1);
+ GET_DST(OP1,NIB2);
+ GET_CCC(OP1,NIB3);
+ WRPORT_W(cpustate, 0, cpustate->RW(dst), RDMEM_W(cpustate, cpustate->RW(src)));
+ cpustate->RW(dst) += 2;
+ cpustate->RW(src) += 2;
+ if (--cpustate->RW(cnt)) { CLR_V; if (cc == 0) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ souti @rd,@rs,ra
+ soutir @rd,@rs,ra
+ flags: ------
+ ******************************************/
+static void Z3B_ssss_0011_0000_aaaa_dddd_x000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CNT(OP1,NIB1);
+ GET_DST(OP1,NIB2);
+ GET_CCC(OP1,NIB3);
+ WRPORT_W(cpustate, 1, cpustate->RW(dst), RDMEM_W(cpustate, cpustate->RW(src)));
+ cpustate->RW(dst) += 2;
+ cpustate->RW(src) += 2;
+ if (--cpustate->RW(cnt)) { CLR_V; if (cc == 0) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ in rd,imm16
+ flags: ------
+ ******************************************/
+static void Z3B_dddd_0100_imm16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_IMM16(OP1);
+ cpustate->RW(dst) = RDPORT_W(cpustate, 0, imm16);
+}
+
+/******************************************
+ sin rd,imm16
+ flags: ------
+ ******************************************/
+static void Z3B_dddd_0101_imm16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_IMM16(OP1);
+ cpustate->RW(dst) = RDPORT_W(cpustate, 1, imm16);
+}
+
+/******************************************
+ out imm16,rs
+ flags: ---V--
+ ******************************************/
+static void Z3B_ssss_0110_imm16(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_IMM16(OP1);
+ WRPORT_W(cpustate, 0, imm16, cpustate->RW(src));
+}
+
+/******************************************
+ sout imm16,rbs
+ flags: ------
+ ******************************************/
+static void Z3B_ssss_0111_imm16(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_IMM16(OP1);
+ WRPORT_W(cpustate, 1, imm16, cpustate->RW(src));
+}
+
+/******************************************
+ ind @rd,@rs,ra
+ indr @rd,@rs,ra
+ flags: ---V--
+ ******************************************/
+static void Z3B_ssss_1000_0000_aaaa_dddd_x000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CNT(OP1,NIB1);
+ GET_DST(OP1,NIB2);
+ GET_CCC(OP1,NIB3);
+ WRMEM_W(cpustate, cpustate->RW(dst), RDPORT_W(cpustate, 0, cpustate->RW(src)));
+ cpustate->RW(dst) -= 2;
+ cpustate->RW(src) -= 2;
+ if (--cpustate->RW(cnt)) { CLR_V; if (cc == 0) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ sind @rd,@rs,ra
+ sindr @rd,@rs,ra
+ flags: ------
+ ******************************************/
+static void Z3B_ssss_1001_0000_aaaa_dddd_x000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CNT(OP1,NIB1);
+ GET_DST(OP1,NIB2);
+ GET_CCC(OP1,NIB3);
+ WRMEM_W(cpustate, cpustate->RW(dst), RDPORT_W(cpustate, 1, cpustate->RW(src)));
+ cpustate->RW(dst) -= 2;
+ cpustate->RW(src) -= 2;
+ if (--cpustate->RW(cnt)) { CLR_V; if (cc == 0) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ outd @rd,@rs,ra
+ outdr @rd,@rs,ra
+ flags: ---V--
+ ******************************************/
+static void Z3B_ssss_1010_0000_aaaa_dddd_x000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CNT(OP1,NIB1);
+ GET_DST(OP1,NIB2);
+ GET_CCC(OP1,NIB3);
+ WRPORT_W(cpustate, 0, cpustate->RW(dst), RDMEM_W(cpustate, cpustate->RW(src)));
+ cpustate->RW(dst) -= 2;
+ cpustate->RW(src) -= 2;
+ if (--cpustate->RW(cnt)) { CLR_V; if (cc == 0) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ soutd @rd,@rs,ra
+ soutdr @rd,@rs,ra
+ flags: ------
+ ******************************************/
+static void Z3B_ssss_1011_0000_aaaa_dddd_x000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CNT(OP1,NIB1);
+ GET_DST(OP1,NIB2);
+ GET_CCC(OP1,NIB3);
+ WRPORT_W(cpustate, 1, cpustate->RW(dst), RDMEM_W(cpustate, cpustate->RW(src)));
+ cpustate->RW(dst) -= 2;
+ cpustate->RW(src) -= 2;
+ if (--cpustate->RW(cnt)) { CLR_V; if (cc == 0) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ inb rbd,@rs
+ flags: ------
+ ******************************************/
+static void Z3C_ssss_dddd(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_DST(OP0,NIB3);
+ cpustate->RB(dst) = RDPORT_B(cpustate, 0, RDMEM_W(cpustate, cpustate->RW(src)));
+}
+
+/******************************************
+ in rd,@rs
+ flags: ------
+ ******************************************/
+static void Z3D_ssss_dddd(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_DST(OP0,NIB3);
+ cpustate->RW(dst) = RDPORT_W(cpustate, 0, RDMEM_W(cpustate, cpustate->RW(src)));
+}
+
+/******************************************
+ outb @rd,rbs
+ flags: ---V--
+ ******************************************/
+static void Z3E_dddd_ssss(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_SRC(OP0,NIB3);
+ WRPORT_B(cpustate, 0, RDMEM_W(cpustate, cpustate->RW(dst)), cpustate->RB(src));
+}
+
+/* FIXME: aforementioned opcode looks bugged. */
+static void Z3E_dddd_ssss_seg(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_SRC(OP0,NIB3);
+ WRPORT_B(cpustate, 0, cpustate->RW(dst), cpustate->RB(src));
+}
+
+/******************************************
+ out @rd,rs
+ flags: ---V--
+ ******************************************/
+static void Z3F_dddd_ssss(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_SRC(OP0,NIB3);
+ WRPORT_W(cpustate, 0, RDMEM_W(cpustate, cpustate->RW(dst)), cpustate->RW(src));
+}
+
+/******************************************
+ addb rbd,addr
+ flags: CZSVDH
+ ******************************************/
+static void Z40_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ cpustate->RB(dst) = ADDB(cpustate, cpustate->RB(dst), RDMEM_B(cpustate, addr));
+}
+
+/******************************************
+ addb rbd,addr(rs)
+ flags: CZSVDH
+ ******************************************/
+static void Z40_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ cpustate->RB(dst) = ADDB(cpustate, cpustate->RB(dst), RDMEM_B(cpustate, addr));
+}
+
+/******************************************
+ add rd,addr
+ flags: CZSV--
+ ******************************************/
+static void Z41_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ cpustate->RW(dst) = ADDW(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, addr)); /* EHC */
+}
+
+/******************************************
+ add rd,addr(rs)
+ flags: CZSV--
+ ******************************************/
+static void Z41_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ cpustate->RW(dst) = ADDW(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, addr)); /* ASG */
+}
+
+/******************************************
+ subb rbd,addr
+ flags: CZSVDH
+ ******************************************/
+static void Z42_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ cpustate->RB(dst) = SUBB(cpustate, cpustate->RB(dst), RDMEM_B(cpustate, addr)); /* EHC */
+}
+
+/******************************************
+ subb rbd,addr(rs)
+ flags: CZSVDH
+ ******************************************/
+static void Z42_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ cpustate->RB(dst) = SUBB(cpustate, cpustate->RB(dst), RDMEM_B(cpustate, addr));
+}
+
+/******************************************
+ sub rd,addr
+ flags: CZSV--
+ ******************************************/
+static void Z43_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ cpustate->RW(dst) = SUBW(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, addr));
+}
+
+/******************************************
+ sub rd,addr(rs)
+ flags: CZSV--
+ ******************************************/
+static void Z43_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ cpustate->RW(dst) = SUBW(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, addr));
+}
+
+/******************************************
+ orb rbd,addr
+ flags: CZSP--
+ ******************************************/
+static void Z44_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ cpustate->RB(dst) = ORB(cpustate, cpustate->RB(dst), RDMEM_B(cpustate, addr));
+}
+
+/******************************************
+ orb rbd,addr(rs)
+ flags: CZSP--
+ ******************************************/
+static void Z44_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ cpustate->RB(dst) = ORB(cpustate, cpustate->RB(dst), RDMEM_B(cpustate, addr));
+}
+
+/******************************************
+ or rd,addr
+ flags: CZS---
+ ******************************************/
+static void Z45_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ cpustate->RW(dst) = ORW(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, addr));
+}
+
+/******************************************
+ or rd,addr(rs)
+ flags: CZS---
+ ******************************************/
+static void Z45_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ cpustate->RW(dst) = ORW(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, addr));
+}
+
+/******************************************
+ andb rbd,addr
+ flags: -ZSP--
+ ******************************************/
+static void Z46_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ cpustate->RB(dst) = ANDB(cpustate, cpustate->RB(dst), RDMEM_B(cpustate, addr));
+}
+
+/******************************************
+ andb rbd,addr(rs)
+ flags: -ZSP--
+ ******************************************/
+static void Z46_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ cpustate->RB(dst) = ANDB(cpustate, cpustate->RB(dst), RDMEM_B(cpustate, addr));
+}
+
+/******************************************
+ and rd,addr
+ flags: -ZS---
+ ******************************************/
+static void Z47_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ cpustate->RW(dst) = ANDW(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, addr));
+}
+
+/******************************************
+ and rd,addr(rs)
+ flags: -ZS---
+ ******************************************/
+static void Z47_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ cpustate->RW(dst) = ANDW(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, addr));
+}
+
+/******************************************
+ xorb rbd,addr
+ flags: -ZSP--
+ ******************************************/
+static void Z48_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ cpustate->RB(dst) = XORB(cpustate, cpustate->RB(dst), RDMEM_B(cpustate, addr));
+}
+
+/******************************************
+ xorb rbd,addr(rs)
+ flags: -ZSP--
+ ******************************************/
+static void Z48_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ cpustate->RB(dst) = XORB(cpustate, cpustate->RB(dst), RDMEM_B(cpustate, addr));
+}
+
+/******************************************
+ xor rd,addr
+ flags: -ZS---
+ ******************************************/
+static void Z49_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ cpustate->RW(dst) = XORW(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, addr));
+}
+
+/******************************************
+ xor rd,addr(rs)
+ flags: -ZS---
+ ******************************************/
+static void Z49_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ cpustate->RW(dst) = XORW(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, addr));
+}
+
+/******************************************
+ cpb rbd,addr
+ flags: CZSV--
+ ******************************************/
+static void Z4A_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ CPB(cpustate, cpustate->RB(dst), RDMEM_B(cpustate, addr));
+}
+
+/******************************************
+ cpb rbd,addr(rs)
+ flags: CZSV--
+ ******************************************/
+static void Z4A_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ CPB(cpustate, cpustate->RB(dst), RDMEM_B(cpustate, addr));
+}
+
+/******************************************
+ cp rd,addr
+ flags: CZSV--
+ ******************************************/
+static void Z4B_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ CPW(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, addr));
+}
+
+/******************************************
+ cp rd,addr(rs)
+ flags: CZSV--
+ ******************************************/
+static void Z4B_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ CPW(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, addr));
+}
+
+/******************************************
+ comb addr
+ flags: -ZSP--
+ ******************************************/
+static void Z4C_0000_0000_addr(z8000_state *cpustate)
+{
+ GET_ADDR(OP1);
+ WRMEM_B(cpustate, addr, COMB(cpustate, RDMEM_W(cpustate, addr)));
+}
+
+/******************************************
+ cpb addr,imm8
+ flags: CZSV--
+ ******************************************/
+static void Z4C_0000_0001_addr_imm8(z8000_state *cpustate)
+{
+ GET_ADDR(OP1);
+ GET_IMM8(OP2);
+ CPB(cpustate, RDMEM_B(cpustate, addr), imm8);
+}
+
+/******************************************
+ negb addr
+ flags: CZSV--
+ ******************************************/
+static void Z4C_0000_0010_addr(z8000_state *cpustate)
+{
+ GET_ADDR(OP1);
+ WRMEM_B(cpustate, addr, NEGB(cpustate, RDMEM_B(cpustate, addr)));
+}
+
+/******************************************
+ testb addr
+ flags: -ZSP--
+ ******************************************/
+static void Z4C_0000_0100_addr(z8000_state *cpustate)
+{
+ GET_ADDR(OP1);
+ TESTB(cpustate, RDMEM_B(cpustate, addr));
+}
+
+/******************************************
+ ldb addr,imm8
+ flags: ------
+ ******************************************/
+static void Z4C_0000_0101_addr_imm8(z8000_state *cpustate)
+{
+ GET_ADDR(OP1);
+ GET_IMM8(OP2);
+ WRMEM_B(cpustate, addr, imm8);
+}
+
+/******************************************
+ tsetb addr
+ flags: --S---
+ ******************************************/
+static void Z4C_0000_0110_addr(z8000_state *cpustate)
+{
+ GET_ADDR(OP1);
+ if (RDMEM_B(cpustate, addr) & S08) SET_S; else CLR_S;
+ WRMEM_B(cpustate, addr, 0xff);
+}
+
+/******************************************
+ clrb addr
+ flags: ------
+ ******************************************/
+static void Z4C_0000_1000_addr(z8000_state *cpustate)
+{
+ GET_ADDR(OP1);
+ WRMEM_B(cpustate, addr, 0);
+}
+
+static void Z4C_0000_1000_addr_seg(z8000_state *cpustate)
+{
+ static UINT32 offset;
+ UINT16 operand1 = fetch(cpustate);
+
+ if(operand1 & 0x8000)
+ {
+ UINT16 operand2 = fetch(cpustate);
+
+ offset = (operand1 & 0x0700) << 8;
+ offset|= (operand2 & 0xffff);
+ WRMEM_B(cpustate, offset, 0);
+ cycles(cpustate, 14);
+ }
+ else
+ {
+ offset = (operand1 & 0x0700) << 8;
+ offset|= (operand1 & 0x00ff);
+ WRMEM_B(cpustate, offset, 0);
+ cycles(cpustate, 12);
+ }
+}
+
+/******************************************
+ comb addr(rd)
+ flags: -ZSP--
+ ******************************************/
+static void Z4C_ddN0_0000_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ WRMEM_B(cpustate, addr, COMB(cpustate, RDMEM_B(cpustate, addr)));
+}
+
+/******************************************
+ cpb addr(rd),imm8
+ flags: CZSV--
+ ******************************************/
+static void Z4C_ddN0_0001_addr_imm8(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ GET_IMM8(OP2);
+ addr += cpustate->RW(dst);
+ CPB(cpustate, RDMEM_B(cpustate, addr), imm8);
+}
+
+/******************************************
+ negb addr(rd)
+ flags: CZSV--
+ ******************************************/
+static void Z4C_ddN0_0010_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ WRMEM_B(cpustate, addr, NEGB(cpustate, RDMEM_B(cpustate, addr)));
+}
+
+/******************************************
+ testb addr(rd)
+ flags: -ZSP--
+ ******************************************/
+static void Z4C_ddN0_0100_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ TESTB(cpustate, RDMEM_B(cpustate, addr));
+}
+
+/******************************************
+ ldb addr(rd),imm8
+ flags: ------
+ ******************************************/
+static void Z4C_ddN0_0101_addr_imm8(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ GET_IMM8(OP2);
+ addr += cpustate->RW(dst);
+ WRMEM_B(cpustate, addr, imm8);
+}
+
+/******************************************
+ tsetb addr(rd)
+ flags: --S---
+ ******************************************/
+static void Z4C_ddN0_0110_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ if (RDMEM_B(cpustate, addr) & S08) SET_S; else CLR_S;
+ WRMEM_B(cpustate, addr, 0xff);
+}
+
+/******************************************
+ clrb addr(rd)
+ flags: ------
+ ******************************************/
+static void Z4C_ddN0_1000_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ WRMEM_B(cpustate, addr, 0);
+}
+
+/******************************************
+ com addr
+ flags: -ZS---
+ ******************************************/
+static void Z4D_0000_0000_addr(z8000_state *cpustate)
+{
+ GET_ADDR(OP1);
+ WRMEM_W(cpustate, addr, COMW(cpustate, RDMEM_W(cpustate, addr)));
+}
+
+/******************************************
+ cp addr,imm16
+ flags: CZSV--
+ ******************************************/
+static void Z4D_0000_0001_addr_imm16(z8000_state *cpustate)
+{
+ GET_ADDR(OP1);
+ GET_IMM16(OP2);
+ CPW(cpustate, RDMEM_W(cpustate, addr), imm16);
+}
+
+/******************************************
+ neg addr
+ flags: CZSV--
+ ******************************************/
+static void Z4D_0000_0010_addr(z8000_state *cpustate)
+{
+ GET_ADDR(OP1);
+ WRMEM_W(cpustate, addr, NEGW(cpustate, RDMEM_W(cpustate, addr)));
+}
+
+/******************************************
+ test addr
+ flags: ------
+ ******************************************/
+static void Z4D_0000_0100_addr(z8000_state *cpustate)
+{
+ GET_ADDR(OP1);
+ TESTW(cpustate, RDMEM_W(cpustate, addr));
+}
+
+/******************************************
+ ld addr,imm16
+ flags: ------
+ ******************************************/
+static void Z4D_0000_0101_addr_imm16(z8000_state *cpustate)
+{
+ GET_ADDR(OP1);
+ GET_IMM16(OP2);
+ WRMEM_W(cpustate, addr, imm16);
+}
+
+static void Z4D_0000_0101_addr_imm16_seg(z8000_state *cpustate)
+{
+ static UINT32 offset;
+ UINT16 operand1 = fetch(cpustate);
+
+ if(operand1 & 0x8000)
+ {
+ UINT16 operand2 = fetch(cpustate);
+ UINT16 imm16 = fetch(cpustate);
+
+ offset = (operand1 & 0x0700) << 8;
+ offset|= (operand2 & 0xffff);
+ WRMEM_W(cpustate, offset, imm16);
+ cycles(cpustate, 17);
+ }
+ else
+ {
+ UINT16 imm16 = fetch(cpustate);
+
+ offset = (operand1 & 0x0700) << 8;
+ offset|= (operand1 & 0x00ff);
+ WRMEM_W(cpustate, offset, imm16);
+ cycles(cpustate, 15);
+ }
+}
+
+/******************************************
+ tset addr
+ flags: --S---
+ ******************************************/
+static void Z4D_0000_0110_addr(z8000_state *cpustate)
+{
+ GET_ADDR(OP1);
+ if (RDMEM_W(cpustate, addr) & S16) SET_S; else CLR_S;
+ WRMEM_W(cpustate, addr, 0xffff);
+}
+
+/******************************************
+ clr addr
+ flags: ------
+ ******************************************/
+static void Z4D_0000_1000_addr(z8000_state *cpustate)
+{
+ GET_ADDR(OP1);
+ WRMEM_W(cpustate, addr, 0);
+}
+
+static void Z4D_0000_1000_addr_seg(z8000_state *cpustate)
+{
+ static UINT32 offset;
+ UINT16 operand1 = fetch(cpustate);
+
+ if(operand1 & 0x8000)
+ {
+ UINT16 operand2 = fetch(cpustate);
+
+ offset = (operand1 & 0x0700) << 8;
+ offset|= (operand2 & 0xffff);
+ WRMEM_W(cpustate, offset, 0);
+ cycles(cpustate, 15);
+ }
+ else
+ {
+ offset = (operand1 & 0x0700) << 8;
+ offset|= (operand1 & 0x00ff);
+ WRMEM_W(cpustate, offset, 0);
+ cycles(cpustate, 12);
+ }
+}
+
+/******************************************
+ com addr(rd)
+ flags: -ZS---
+ ******************************************/
+static void Z4D_ddN0_0000_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ WRMEM_W(cpustate, addr, COMW(cpustate, RDMEM_W(cpustate, addr)));
+}
+
+/******************************************
+ cp addr(rd),imm16
+ flags: CZSV--
+ ******************************************/
+static void Z4D_ddN0_0001_addr_imm16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ GET_IMM16(OP2);
+ addr += cpustate->RW(dst);
+ CPW(cpustate, RDMEM_W(cpustate, addr), imm16);
+}
+
+/******************************************
+ neg addr(rd)
+ flags: CZSV--
+ ******************************************/
+static void Z4D_ddN0_0010_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ WRMEM_W(cpustate, addr, NEGW(cpustate, RDMEM_W(cpustate, addr)));
+}
+
+/******************************************
+ test addr(rd)
+ flags: ------
+ ******************************************/
+static void Z4D_ddN0_0100_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ TESTW(cpustate, RDMEM_W(cpustate, addr));
+}
+
+/******************************************
+ ld addr(rd),imm16
+ flags: ------
+ ******************************************/
+static void Z4D_ddN0_0101_addr_imm16(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ GET_IMM16(OP2);
+ addr += cpustate->RW(dst);
+ WRMEM_W(cpustate, addr, imm16);
+}
+
+/******************************************
+ tset addr(rd)
+ flags: --S---
+ ******************************************/
+static void Z4D_ddN0_0110_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ if (RDMEM_W(cpustate, addr) & S16) SET_S; else CLR_S;
+ WRMEM_W(cpustate, addr, 0xffff);
+}
+
+/******************************************
+ clr addr(rd)
+ flags: ------
+ ******************************************/
+static void Z4D_ddN0_1000_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ WRMEM_W(cpustate, addr, 0);
+}
+
+/******************************************
+ ldb addr(rd),rbs
+ flags: ------
+ ******************************************/
+static void Z4E_ddN0_ssN0_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_SRC(OP0,NIB3);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ WRMEM_B(cpustate, addr, cpustate->RB(src));
+}
+
+/******************************************
+ cpl rrd,addr
+ flags: CZSV--
+ ******************************************/
+static void Z50_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ CPL(cpustate, cpustate->RL(dst), RDMEM_L(cpustate, addr));
+}
+
+/******************************************
+ cpl rrd,addr(rs)
+ flags: CZSV--
+ ******************************************/
+static void Z50_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ CPL(cpustate, cpustate->RL(dst), RDMEM_L(cpustate, addr));
+}
+
+/******************************************
+ pushl @rd,addr
+ flags: ------
+ ******************************************/
+static void Z51_ddN0_0000_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ PUSHL(cpustate, dst, RDMEM_L(cpustate, addr));
+}
+
+/******************************************
+ pushl @rd,addr(rs)
+ flags: ------
+ ******************************************/
+static void Z51_ddN0_ssN0_addr(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ PUSHL(cpustate, dst, RDMEM_L(cpustate, addr));
+}
+
+/******************************************
+ subl rrd,addr
+ flags: CZSV--
+ ******************************************/
+static void Z52_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ cpustate->RL(dst) = SUBL(cpustate, cpustate->RL(dst), RDMEM_L(cpustate, addr));
+}
+
+/******************************************
+ subl rrd,addr(rs)
+ flags: CZSV--
+ ******************************************/
+static void Z52_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ cpustate->RL(dst) = SUBL(cpustate, cpustate->RL(dst), RDMEM_L(cpustate, addr));
+}
+
+/******************************************
+ push @rd,addr
+ flags: ------
+ ******************************************/
+static void Z53_ddN0_0000_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ PUSHW(cpustate, dst, RDMEM_W(cpustate, addr));
+}
+
+/******************************************
+ push @rd,addr(rs)
+ flags: ------
+ ******************************************/
+static void Z53_ddN0_ssN0_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_SRC(OP0,NIB3);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ PUSHW(cpustate, dst, RDMEM_W(cpustate, addr));
+}
+
+/******************************************
+ ldl rrd,addr
+ flags: ------
+ ******************************************/
+static void Z54_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ cpustate->RL(dst) = RDMEM_L(cpustate, addr);
+}
+
+/******************************************
+ ldl rrd,addr(rs)
+ flags: ------
+ ******************************************/
+static void Z54_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ cpustate->RL(dst) = RDMEM_L(cpustate, addr);
+}
+
+/******************************************
+ popl addr,@rs
+ flags: ------
+ ******************************************/
+static void Z55_ssN0_0000_addr(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ WRMEM_L(cpustate, addr, POPL(cpustate, src));
+}
+
+/******************************************
+ popl addr(rd),@rs
+ flags: ------
+ ******************************************/
+static void Z55_ssN0_ddN0_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ WRMEM_L(cpustate, addr, POPL(cpustate, src));
+}
+
+/******************************************
+ addl rrd,addr
+ flags: CZSV--
+ ******************************************/
+static void Z56_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ cpustate->RL(dst) = ADDL(cpustate, cpustate->RL(dst), RDMEM_L(cpustate, addr));
+}
+
+/******************************************
+ addl rrd,addr(rs)
+ flags: CZSV--
+ ******************************************/
+static void Z56_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ cpustate->RL(dst) = ADDL(cpustate, cpustate->RL(dst), RDMEM_L(cpustate, addr));
+}
+
+/******************************************
+ pop addr,@rs
+ flags: ------
+ ******************************************/
+static void Z57_ssN0_0000_addr(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ WRMEM_W(cpustate, addr, POPW(cpustate, src));
+}
+
+/******************************************
+ pop addr(rd),@rs
+ flags: ------
+ ******************************************/
+static void Z57_ssN0_ddN0_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ WRMEM_W(cpustate, addr, POPW(cpustate, src));
+}
+
+/******************************************
+ multl rqd,addr
+ flags: CZSV--
+ ******************************************/
+static void Z58_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ cpustate->RQ(dst) = MULTL(cpustate, cpustate->RQ(dst), RDMEM_L(cpustate, addr));
+}
+
+/******************************************
+ multl rqd,addr(rs)
+ flags: CZSV--
+ ******************************************/
+static void Z58_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ cpustate->RQ(dst) = MULTL(cpustate, cpustate->RQ(dst), RDMEM_L(cpustate, addr));
+}
+
+/******************************************
+ mult rrd,addr
+ flags: CZSV--
+ ******************************************/
+static void Z59_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ cpustate->RL(dst) = MULTW(cpustate, cpustate->RL(dst), RDMEM_W(cpustate, addr));
+}
+
+/******************************************
+ mult rrd,addr(rs)
+ flags: CZSV--
+ ******************************************/
+static void Z59_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ cpustate->RL(dst) = MULTW(cpustate, cpustate->RL(dst), RDMEM_W(cpustate, addr));
+}
+
+/******************************************
+ divl rqd,addr
+ flags: CZSV--
+ ******************************************/
+static void Z5A_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ cpustate->RQ(dst) = DIVL(cpustate, cpustate->RQ(dst), RDMEM_L(cpustate, addr));
+}
+
+/******************************************
+ divl rqd,addr(rs)
+ flags: CZSV--
+ ******************************************/
+static void Z5A_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ cpustate->RQ(dst) = DIVL(cpustate, cpustate->RQ(dst), RDMEM_L(cpustate, addr));
+}
+
+/******************************************
+ div rrd,addr
+ flags: CZSV--
+ ******************************************/
+static void Z5B_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ cpustate->RL(dst) = DIVW(cpustate, cpustate->RL(dst), RDMEM_W(cpustate, addr));
+}
+
+/******************************************
+ div rrd,addr(rs)
+ flags: CZSV--
+ ******************************************/
+static void Z5B_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ cpustate->RL(dst) = DIVW(cpustate, cpustate->RL(dst), RDMEM_W(cpustate, addr));
+}
+
+/******************************************
+ ldm rd,addr,n
+ flags: ------
+ ******************************************/
+static void Z5C_0000_0001_0000_dddd_0000_nmin1_addr(z8000_state *cpustate)
+{
+ GET_DST(OP1,NIB1);
+ GET_CNT(OP1,NIB3);
+ GET_ADDR(OP2);
+ while (cnt-- >= 0) {
+ cpustate->RW(dst) = RDMEM_W(cpustate, addr);
+ dst = (dst+1) & 15;
+ addr = (addr + 2) & 0xffff;
+ }
+}
+
+/******************************************
+ testl addr
+ flags: -ZS---
+ ******************************************/
+static void Z5C_0000_1000_addr(z8000_state *cpustate)
+{
+ GET_ADDR(OP1);
+ TESTL(cpustate, RDMEM_L(cpustate, addr));
+}
+
+/******************************************
+ ldm addr,rs,n
+ flags: ------
+ ******************************************/
+static void Z5C_0000_1001_0000_ssss_0000_nmin1_addr(z8000_state *cpustate)
+{
+ GET_SRC(OP1,NIB1);
+ GET_CNT(OP1,NIB3);
+ GET_ADDR(OP2);
+ while (cnt-- >= 0) {
+ WRMEM_W(cpustate, addr, cpustate->RW(src));
+ src = (src+1) & 15;
+ addr = (addr + 2) & 0xffff;
+ }
+}
+
+/******************************************
+ testl addr(rd)
+ flags: -ZS---
+ ******************************************/
+static void Z5C_ddN0_1000_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ TESTL(cpustate, RDMEM_L(cpustate, addr));
+}
+
+/******************************************
+ ldm addr(rd),rs,n
+ flags: ------
+ ******************************************/
+static void Z5C_ddN0_1001_0000_ssN0_0000_nmin1_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_SRC(OP1,NIB1);
+ GET_CNT(OP1,NIB3);
+ GET_ADDR(OP2);
+ addr += cpustate->RW(dst);
+ while (cnt-- >= 0) {
+ WRMEM_W(cpustate, addr, cpustate->RW(src));
+ src = (src+1) & 15;
+ addr = (addr + 2) & 0xffff;
+ }
+}
+
+/******************************************
+ ldm rd,addr(rs),n
+ flags: ------
+ ******************************************/
+static void Z5C_ssN0_0001_0000_dddd_0000_nmin1_addr(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_DST(OP1,NIB1);
+ GET_CNT(OP1,NIB3);
+ GET_ADDR(OP2);
+ addr += cpustate->RW(src);
+ while (cnt-- >= 0) {
+ cpustate->RW(dst) = RDMEM_W(cpustate, addr);
+ dst = (dst+1) & 15;
+ addr = (addr + 2) & 0xffff;
+ }
+}
+
+/******************************************
+ ldl addr,rrs
+ flags: ------
+ ******************************************/
+static void Z5D_0000_ssss_addr(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_ADDR(OP1);
+ WRMEM_L(cpustate, addr, cpustate->RL(src));
+}
+
+/******************************************
+ ldl addr(rd),rrs
+ flags: ------
+ ******************************************/
+static void Z5D_ddN0_ssss_addr(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ WRMEM_L(cpustate, addr, cpustate->RL(src));
+}
+
+/******************************************
+ jp cc,addr
+ flags: ------
+ ******************************************/
+static void Z5E_0000_cccc_addr(z8000_state *cpustate)
+{
+ GET_CCC(OP0,NIB3);
+ GET_ADDR(OP1);
+ switch (cc) {
+ case 0: if (CC0) cpustate->pc = addr; break;
+ case 1: if (CC1) cpustate->pc = addr; break;
+ case 2: if (CC2) cpustate->pc = addr; break;
+ case 3: if (CC3) cpustate->pc = addr; break;
+ case 4: if (CC4) cpustate->pc = addr; break;
+ case 5: if (CC5) cpustate->pc = addr; break;
+ case 6: if (CC6) cpustate->pc = addr; break;
+ case 7: if (CC7) cpustate->pc = addr; break;
+ case 8: if (CC8) cpustate->pc = addr; break;
+ case 9: if (CC9) cpustate->pc = addr; break;
+ case 10: if (CCA) cpustate->pc = addr; break;
+ case 11: if (CCB) cpustate->pc = addr; break;
+ case 12: if (CCC) cpustate->pc = addr; break;
+ case 13: if (CCD) cpustate->pc = addr; break;
+ case 14: if (CCE) cpustate->pc = addr; break;
+ case 15: if (CCF) cpustate->pc = addr; break;
+ }
+}
+
+/******************************************
+ jp cc,addr(rd)
+ flags: ------
+ ******************************************/
+static void Z5E_ddN0_cccc_addr(z8000_state *cpustate)
+{
+ GET_CCC(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ switch (cc) {
+ case 0: if (CC0) cpustate->pc = addr; break;
+ case 1: if (CC1) cpustate->pc = addr; break;
+ case 2: if (CC2) cpustate->pc = addr; break;
+ case 3: if (CC3) cpustate->pc = addr; break;
+ case 4: if (CC4) cpustate->pc = addr; break;
+ case 5: if (CC5) cpustate->pc = addr; break;
+ case 6: if (CC6) cpustate->pc = addr; break;
+ case 7: if (CC7) cpustate->pc = addr; break;
+ case 8: if (CC8) cpustate->pc = addr; break;
+ case 9: if (CC9) cpustate->pc = addr; break;
+ case 10: if (CCA) cpustate->pc = addr; break;
+ case 11: if (CCB) cpustate->pc = addr; break;
+ case 12: if (CCC) cpustate->pc = addr; break;
+ case 13: if (CCD) cpustate->pc = addr; break;
+ case 14: if (CCE) cpustate->pc = addr; break;
+ case 15: if (CCF) cpustate->pc = addr; break;
+ }
+}
+
+/******************************************
+ call addr
+ flags: ------
+ ******************************************/
+static void Z5F_0000_0000_addr(z8000_state *cpustate)
+{
+ GET_ADDR(OP1);
+ PUSHW(cpustate, SP, cpustate->pc);
+ cpustate->pc = addr;
+}
+
+/******************************************
+ call addr(rd)
+ flags: ------
+ ******************************************/
+static void Z5F_ddN0_0000_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ PUSHW(cpustate, SP, cpustate->pc);
+ addr += cpustate->RW(dst);
+ cpustate->pc = addr;
+}
+
+/******************************************
+ ldb rbd,addr
+ flags: ------
+ ******************************************/
+static void Z60_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ cpustate->RB(dst) = RDMEM_B(cpustate, addr);
+}
+
+/******************************************
+ ldb rbd,addr(rs)
+ flags: ------
+ ******************************************/
+static void Z60_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ cpustate->RB(dst) = RDMEM_B(cpustate, addr);
+}
+
+/******************************************
+ ld rd,addr
+ flags: ------
+ ******************************************/
+static void Z61_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ cpustate->RW(dst) = RDMEM_W(cpustate, addr);
+}
+
+/******************************************
+ ld rd,addr(rs)
+ flags: ------
+ ******************************************/
+static void Z61_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ cpustate->RW(dst) = RDMEM_W(cpustate, addr);
+}
+
+/******************************************
+ resb addr,imm4
+ flags: ------
+ ******************************************/
+static void Z62_0000_imm4_addr(z8000_state *cpustate)
+{
+ GET_BIT(OP0);
+ GET_ADDR(OP1);
+ WRMEM_B(cpustate, addr, RDMEM_B(cpustate, addr) & ~bit);
+}
+
+/******************************************
+ resb addr(rd),imm4
+ flags: ------
+ ******************************************/
+static void Z62_ddN0_imm4_addr(z8000_state *cpustate)
+{
+ GET_BIT(OP0);
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ WRMEM_B(cpustate, addr, RDMEM_B(cpustate, addr) & ~bit);
+}
+
+/******************************************
+ res addr,imm4
+ flags: ------
+ ******************************************/
+static void Z63_0000_imm4_addr(z8000_state *cpustate)
+{
+ GET_BIT(OP0);
+ GET_ADDR(OP1);
+ WRMEM_W(cpustate, addr, RDMEM_W(cpustate, addr) & ~bit);
+}
+
+/******************************************
+ res addr(rd),imm4
+ flags: ------
+ ******************************************/
+static void Z63_ddN0_imm4_addr(z8000_state *cpustate)
+{
+ GET_BIT(OP0);
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ WRMEM_W(cpustate, addr, RDMEM_W(cpustate, addr) & ~bit);
+}
+
+/******************************************
+ setb addr,imm4
+ flags: ------
+ ******************************************/
+static void Z64_0000_imm4_addr(z8000_state *cpustate)
+{
+ GET_BIT(OP0);
+ GET_ADDR(OP1);
+ WRMEM_B(cpustate, addr, RDMEM_B(cpustate, addr) | bit);
+}
+
+/******************************************
+ setb addr(rd),imm4
+ flags: ------
+ ******************************************/
+static void Z64_ddN0_imm4_addr(z8000_state *cpustate)
+{
+ GET_BIT(OP0);
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ WRMEM_B(cpustate, addr, RDMEM_B(cpustate, addr) | bit);
+}
+
+/******************************************
+ set addr,imm4
+ flags: ------
+ ******************************************/
+static void Z65_0000_imm4_addr(z8000_state *cpustate)
+{
+ GET_BIT(OP0);
+ GET_ADDR(OP1);
+ WRMEM_W(cpustate, addr, RDMEM_W(cpustate, addr) | bit);
+}
+
+/******************************************
+ set addr(rd),imm4
+ flags: ------
+ ******************************************/
+static void Z65_ddN0_imm4_addr(z8000_state *cpustate)
+{
+ GET_BIT(OP0);
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ WRMEM_W(cpustate, addr, RDMEM_W(cpustate, addr) | bit);
+}
+
+/******************************************
+ bitb addr,imm4
+ flags: -Z----
+ ******************************************/
+static void Z66_0000_imm4_addr(z8000_state *cpustate)
+{
+ GET_BIT(OP0);
+ GET_ADDR(OP1);
+ if (RDMEM_B(cpustate, addr) & bit) CLR_Z; else SET_Z;
+}
+
+/******************************************
+ bitb addr(rd),imm4
+ flags: -Z----
+ ******************************************/
+static void Z66_ddN0_imm4_addr(z8000_state *cpustate)
+{
+ GET_BIT(OP0);
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ if (RDMEM_B(cpustate, addr) & bit) CLR_Z; else SET_Z;
+}
+
+/******************************************
+ bit addr,imm4
+ flags: -Z----
+ ******************************************/
+static void Z67_0000_imm4_addr(z8000_state *cpustate)
+{
+ GET_BIT(OP0);
+ GET_ADDR(OP1);
+ if (RDMEM_W(cpustate, addr) & bit) CLR_Z; else SET_Z;
+}
+
+/******************************************
+ bit addr(rd),imm4
+ flags: -Z----
+ ******************************************/
+static void Z67_ddN0_imm4_addr(z8000_state *cpustate)
+{
+ GET_BIT(OP0);
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ if (RDMEM_W(cpustate, addr) & bit) CLR_Z; else SET_Z;
+}
+
+/******************************************
+ incb addr,imm4m1
+ flags: -ZSV--
+ ******************************************/
+static void Z68_0000_imm4m1_addr(z8000_state *cpustate)
+{
+ GET_I4M1(OP0,NIB3);
+ GET_ADDR(OP1);
+ WRMEM_B(cpustate, addr, INCB(cpustate, RDMEM_B(cpustate, addr), i4p1));
+}
+
+/******************************************
+ incb addr(rd),imm4m1
+ flags: -ZSV--
+ ******************************************/
+static void Z68_ddN0_imm4m1_addr(z8000_state *cpustate)
+{
+ GET_I4M1(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ WRMEM_B(cpustate, addr, INCB(cpustate, RDMEM_B(cpustate, addr), i4p1));
+}
+
+/******************************************
+ inc addr,imm4m1
+ flags: -ZSV--
+ ******************************************/
+static void Z69_0000_imm4m1_addr(z8000_state *cpustate)
+{
+ GET_I4M1(OP0,NIB3);
+ GET_ADDR(OP1);
+ WRMEM_W(cpustate, addr, INCW(cpustate, RDMEM_W(cpustate, addr), i4p1));
+}
+
+/******************************************
+ inc addr(rd),imm4m1
+ flags: -ZSV--
+ ******************************************/
+static void Z69_ddN0_imm4m1_addr(z8000_state *cpustate)
+{
+ GET_I4M1(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ WRMEM_W(cpustate, addr, INCW(cpustate, RDMEM_W(cpustate, addr), i4p1));
+}
+
+/******************************************
+ decb addr,imm4m1
+ flags: -ZSV--
+ ******************************************/
+static void Z6A_0000_imm4m1_addr(z8000_state *cpustate)
+{
+ GET_I4M1(OP0,NIB3);
+ GET_ADDR(OP1);
+ WRMEM_B(cpustate, addr, DECB(cpustate, RDMEM_B(cpustate, addr), i4p1));
+}
+
+/******************************************
+ decb addr(rd),imm4m1
+ flags: -ZSV--
+ ******************************************/
+static void Z6A_ddN0_imm4m1_addr(z8000_state *cpustate)
+{
+ GET_I4M1(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ WRMEM_B(cpustate, addr, DECB(cpustate, RDMEM_B(cpustate, addr), i4p1));
+}
+
+/******************************************
+ dec addr,imm4m1
+ flags: -ZSV--
+ ******************************************/
+static void Z6B_0000_imm4m1_addr(z8000_state *cpustate)
+{
+ GET_I4M1(OP0,NIB3);
+ GET_ADDR(OP1);
+ WRMEM_W(cpustate, addr, DECW(cpustate, RDMEM_W(cpustate, addr), i4p1));
+}
+
+/******************************************
+ dec addr(rd),imm4m1
+ flags: -ZSV--
+ ******************************************/
+static void Z6B_ddN0_imm4m1_addr(z8000_state *cpustate)
+{
+ GET_I4M1(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ WRMEM_W(cpustate, addr, DECW(cpustate, RDMEM_W(cpustate, addr), i4p1));
+}
+
+/******************************************
+ exb rbd,addr
+ flags: ------
+ ******************************************/
+static void Z6C_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ UINT8 tmp = RDMEM_B(cpustate, addr);
+ WRMEM_B(cpustate, addr, cpustate->RB(dst));
+ cpustate->RB(dst) = tmp;
+}
+
+/******************************************
+ exb rbd,addr(rs)
+ flags: ------
+ ******************************************/
+static void Z6C_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ UINT8 tmp;
+ addr += cpustate->RW(src);
+ tmp = RDMEM_B(cpustate, addr);
+ WRMEM_B(cpustate, addr, cpustate->RB(dst));
+ cpustate->RB(dst) = tmp;
+}
+
+/******************************************
+ ex rd,addr
+ flags: ------
+ ******************************************/
+static void Z6D_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ UINT16 tmp = RDMEM_W(cpustate, addr);
+ WRMEM_W(cpustate, addr, cpustate->RW(dst));
+ cpustate->RW(dst) = tmp;
+}
+
+/******************************************
+ ex rd,addr(rs)
+ flags: ------
+ ******************************************/
+static void Z6D_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ UINT16 tmp;
+ addr += cpustate->RW(src);
+ tmp = RDMEM_W(cpustate, addr);
+ WRMEM_W(cpustate, addr, cpustate->RW(dst));
+ cpustate->RW(dst) = tmp;
+}
+
+/******************************************
+ ldb addr,rbs
+ flags: ------
+ ******************************************/
+static void Z6E_0000_ssss_addr(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_ADDR(OP1);
+ WRMEM_B(cpustate, addr, cpustate->RB(src));
+}
+
+/******************************************
+ ldb addr(rd),rbs
+ flags: ------
+ ******************************************/
+static void Z6E_ddN0_ssss_addr(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ WRMEM_B(cpustate, addr, cpustate->RB(src));
+}
+
+/******************************************
+ ld addr,rs
+ flags: ------
+ ******************************************/
+static void Z6F_0000_ssss_addr(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_ADDR(OP1);
+ WRMEM_W(cpustate, addr, cpustate->RW(src));
+}
+
+/******************************************
+ ld addr(rd),rs
+ flags: ------
+ ******************************************/
+static void Z6F_ddN0_ssss_addr(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(dst);
+ WRMEM_W(cpustate, addr, cpustate->RW(src));
+}
+
+/******************************************
+ ldb rbd,rs(rx)
+ flags: ------
+ ******************************************/
+static void Z70_ssN0_dddd_0000_xxxx_0000_0000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_IDX(OP1,NIB1);
+ cpustate->RB(dst) = RDMEM_B(cpustate, (UINT16)(cpustate->RW(src) + cpustate->RW(idx)));
+}
+
+/******************************************
+ ld rd,rs(rx)
+ flags: ------
+ ******************************************/
+static void Z71_ssN0_dddd_0000_xxxx_0000_0000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_IDX(OP1,NIB1);
+ cpustate->RW(dst) = RDMEM_W(cpustate, (UINT16)(cpustate->RW(src) + cpustate->RW(idx)));
+}
+
+/******************************************
+ ldb rd(rx),rbs
+ flags: ------
+ ******************************************/
+static void Z72_ddN0_ssss_0000_xxxx_0000_0000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ GET_IDX(OP1,NIB1);
+ WRMEM_B(cpustate, (UINT16)(cpustate->RW(dst) + cpustate->RW(idx)), cpustate->RB(src));
+}
+
+/******************************************
+ ld rd(rx),rs
+ flags: ------
+ ******************************************/
+static void Z73_ddN0_ssss_0000_xxxx_0000_0000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ GET_IDX(OP1,NIB1);
+ WRMEM_W(cpustate, (UINT16)(cpustate->RW(dst) + cpustate->RW(idx)), cpustate->RW(src));
+}
+
+/******************************************
+ lda prd,rs(rx)
+ flags: ------
+ ******************************************/
+static void Z74_ssN0_dddd_0000_xxxx_0000_0000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_IDX(OP1,NIB1);
+ cpustate->RW(dst) = (UINT16)(cpustate->RW(src) + cpustate->RW(idx));
+}
+
+/******************************************
+ ldl rrd,rs(rx)
+ flags: ------
+ ******************************************/
+static void Z75_ssN0_dddd_0000_xxxx_0000_0000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_IDX(OP1,NIB1);
+ cpustate->RL(dst) = RDMEM_L(cpustate, (UINT16)(cpustate->RW(src) + cpustate->RW(idx)));
+}
+
+/******************************************
+ lda prd,addr
+ flags: ------
+ ******************************************/
+static void Z76_0000_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_ADDR(OP1);
+ cpustate->RW(dst) = addr;
+}
+
+static void Z76_0000_dddd_addr_seg(z8000_state *cpustate)
+{
+ static UINT32 offset;
+ UINT16 operand1;
+
+ GET_DST(OP0,NIB3);
+ operand1 = fetch(cpustate);
+
+ if(operand1 & 0x8000)
+ {
+ UINT16 operand2 = fetch(cpustate);
+
+ offset = (operand1 & 0x0700) << 8;
+ offset|= (operand2 & 0xffff);
+ cpustate->RW(dst) = (offset & 0x70000) >> 16;
+ cpustate->RW(dst+1) = offset & 0xffff;
+ cycles(cpustate, 15);
+ }
+ else
+ {
+ offset = (operand1 & 0x0700) << 8;
+ offset|= (operand1 & 0x00ff);
+ cpustate->RW(dst) = (offset & 0x70000) >> 16;
+ cpustate->RW(dst+1) = offset & 0x00ff;
+ cycles(cpustate, 13);
+ }
+}
+
+/******************************************
+ lda prd,addr(rs)
+ flags: ------
+ ******************************************/
+static void Z76_ssN0_dddd_addr(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ addr += cpustate->RW(src);
+ cpustate->RW(dst) = addr;
+}
+
+/******************************************
+ ldl rd(rx),rrs
+ flags: ------
+ ******************************************/
+static void Z77_ddN0_ssss_0000_xxxx_0000_0000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ GET_IDX(OP1,NIB1);
+ WRMEM_L(cpustate, (UINT16)(cpustate->RW(dst) + cpustate->RW(idx)), cpustate->RL(src));
+}
+
+/******************************************
+ rsvd78
+ flags: ------
+ ******************************************/
+static void Z78_imm8(z8000_state *cpustate)
+{
+ GET_IMM8(0);
+ LOG(("Z8K '%s' %04x: rsvd78 $%02x\n", cpustate->device->tag(), cpustate->pc, imm8));
+ if (cpustate->fcw & F_EPU) {
+ /* Z8001 EPU code goes here */
+ (void)imm8;
+ }
+}
+
+/******************************************
+ ldps addr
+ flags: CZSVDH
+ ******************************************/
+static void Z79_0000_0000_addr(z8000_state *cpustate)
+{
+ GET_ADDR(OP1);
+ UINT16 fcw;
+ fcw = RDMEM_W(cpustate, addr);
+ cpustate->pc = RDMEM_W(cpustate, (UINT16)(addr + 2));
+ CHANGE_FCW(cpustate, fcw); /* check for user/system mode change */
+}
+
+/******************************************
+ ldps addr(rs)
+ flags: CZSVDH
+ ******************************************/
+static void Z79_ssN0_0000_addr(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_ADDR(OP1);
+ UINT16 fcw;
+ addr += cpustate->RW(src);
+ fcw = RDMEM_W(cpustate, addr);
+ cpustate->pc = RDMEM_W(cpustate, (UINT16)(addr + 2));
+ CHANGE_FCW(cpustate, fcw); /* check for user/system mode change */
+}
+
+/******************************************
+ halt
+ flags: ------
+ ******************************************/
+static void Z7A_0000_0000(z8000_state *cpustate)
+{
+ cpustate->irq_req |= Z8000_HALT;
+ if (cpustate->icount > 0) cpustate->icount = 0;
+}
+
+/******************************************
+ iret
+ flags: CZSVDH
+ ******************************************/
+static void Z7B_0000_0000(z8000_state *cpustate)
+{
+ UINT16 tag, fcw;
+ tag = POPW(cpustate, SP); /* get type tag */
+ fcw = POPW(cpustate, SP); /* get cpustate->fcw */
+ cpustate->pc = POPW(cpustate, SP); /* get cpustate->pc */
+ cpustate->irq_srv &= ~tag; /* remove IRQ serviced flag */
+ CHANGE_FCW(cpustate, fcw); /* check for user/system mode change */
+ LOG(("Z8K '%s' IRET tag $%04x, fcw $%04x, pc $%04x\n", cpustate->device->tag(), tag, fcw, cpustate->pc));
+}
+
+/******************************************
+ mset
+ flags: ------
+ ******************************************/
+static void Z7B_0000_1000(z8000_state *cpustate)
+{
+ /* set mu-0 line */
+}
+
+/******************************************
+ mres
+ flags: ------
+ ******************************************/
+static void Z7B_0000_1001(z8000_state *cpustate)
+{
+ /* reset mu-0 line */
+}
+
+/******************************************
+ mbit
+ flags: CZS---
+ ******************************************/
+static void Z7B_0000_1010(z8000_state *cpustate)
+{
+ /* test mu-I line */
+}
+
+/******************************************
+ mreq rd
+ flags: -ZS---
+ ******************************************/
+static void Z7B_dddd_1101(z8000_state *cpustate)
+{
+ /* test mu-I line, invert cascade to mu-0 */
+}
+
+/******************************************
+ di i2
+ flags: ------
+ ******************************************/
+static void Z7C_0000_00ii(z8000_state *cpustate)
+{
+ GET_IMM2(OP0,NIB3);
+ UINT16 fcw = cpustate->fcw;
+ fcw &= ~(imm2 << 11);
+ CHANGE_FCW(cpustate, fcw);
+}
+
+/******************************************
+ ei i2
+ flags: ------
+ ******************************************/
+static void Z7C_0000_01ii(z8000_state *cpustate)
+{
+ GET_IMM2(OP0,NIB3);
+ UINT16 fcw = cpustate->fcw;
+ fcw |= imm2 << 11;
+ CHANGE_FCW(cpustate, fcw);
+}
+
+/******************************************
+ ldctl rd,ctrl
+ flags: ------
+ ******************************************/
+static void Z7D_dddd_0ccc(z8000_state *cpustate)
+{
+ GET_IMM3(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ switch (imm3) {
+ case 0:
+ cpustate->RW(dst) = cpustate->fcw;
+ break;
+ case 3:
+ cpustate->RW(dst) = cpustate->refresh;
+ break;
+ case 5:
+ cpustate->RW(dst) = cpustate->psap;
+ break;
+ case 7:
+ cpustate->RW(dst) = cpustate->nsp;
+ break;
+ default:
+ LOG(("Z8K '%s' LDCTL R%d,%d\n", cpustate->device->tag(), dst, imm3));
+ }
+}
+
+/******************************************
+ ldctl ctrl,rs
+ flags: ------
+ ******************************************/
+static void Z7D_ssss_1ccc(z8000_state *cpustate)
+{
+ GET_IMM3(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ switch (imm3) {
+ case 0:
+ {
+ UINT16 fcw;
+ fcw = cpustate->RW(src);
+ CHANGE_FCW(cpustate, fcw); /* check for user/system mode change */
+ }
+ break;
+ case 3:
+ cpustate->refresh = cpustate->RW(src);
+ break;
+ case 5:
+ cpustate->psap = cpustate->RW(src);
+ break;
+ case 7:
+ cpustate->nsp = cpustate->RW(src);
+ break;
+ default:
+ LOG(("Z8K '%s' LDCTL %d,R%d\n", cpustate->device->tag(), imm3, src));
+ }
+}
+
+/******************************************
+ rsvd7e
+ flags: ------
+ ******************************************/
+static void Z7E_imm8(z8000_state *cpustate)
+{
+ GET_IMM8(0);
+ LOG(("Z8K '%s' %04x: rsvd7e $%02x\n", cpustate->device->tag(), cpustate->pc, imm8));
+ if (cpustate->fcw & F_EPU) {
+ /* Z8001 EPU code goes here */
+ (void)imm8;
+ }
+}
+
+/******************************************
+ sc imm8
+ flags: CZSVDH
+ ******************************************/
+static void Z7F_imm8(z8000_state *cpustate)
+{
+ GET_IMM8(0);
+ /* execute system call via IRQ */
+ cpustate->irq_req = Z8000_SYSCALL | imm8;
+
+}
+
+/******************************************
+ addb rbd,rbs
+ flags: CZSVDH
+ ******************************************/
+static void Z80_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RB(dst) = ADDB(cpustate, cpustate->RB(dst), cpustate->RB(src));
+}
+
+/******************************************
+ add rd,rs
+ flags: CZSV--
+ ******************************************/
+static void Z81_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RW(dst) = ADDW(cpustate, cpustate->RW(dst), cpustate->RW(src));
+}
+
+/******************************************
+ subb rbd,rbs
+ flags: CZSVDH
+ ******************************************/
+static void Z82_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RB(dst) = SUBB(cpustate, cpustate->RB(dst), cpustate->RB(src));
+}
+
+/******************************************
+ sub rd,rs
+ flags: CZSV--
+ ******************************************/
+static void Z83_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RW(dst) = SUBW(cpustate, cpustate->RW(dst), cpustate->RW(src));
+}
+
+/******************************************
+ orb rbd,rbs
+ flags: CZSP--
+ ******************************************/
+static void Z84_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RB(dst) = ORB(cpustate, cpustate->RB(dst), cpustate->RB(src));
+}
+
+/******************************************
+ or rd,rs
+ flags: CZS---
+ ******************************************/
+static void Z85_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RW(dst) = ORW(cpustate, cpustate->RW(dst), cpustate->RW(src));
+}
+
+/******************************************
+ andb rbd,rbs
+ flags: -ZSP--
+ ******************************************/
+static void Z86_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RB(dst) = ANDB(cpustate, cpustate->RB(dst), cpustate->RB(src));
+}
+
+/******************************************
+ and rd,rs
+ flags: -ZS---
+ ******************************************/
+static void Z87_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RW(dst) = ANDW(cpustate, cpustate->RW(dst), cpustate->RW(src));
+}
+
+/******************************************
+ xorb rbd,rbs
+ flags: -ZSP--
+ ******************************************/
+static void Z88_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RB(dst) = XORB(cpustate, cpustate->RB(dst), cpustate->RB(src));
+}
+
+/******************************************
+ xor rd,rs
+ flags: -ZS---
+ ******************************************/
+static void Z89_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RW(dst) = XORW(cpustate, cpustate->RW(dst), cpustate->RW(src));
+}
+
+/******************************************
+ cpb rbd,rbs
+ flags: CZSV--
+ ******************************************/
+static void Z8A_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ CPB(cpustate, cpustate->RB(dst), cpustate->RB(src));
+}
+
+/******************************************
+ cp rd,rs
+ flags: CZSV--
+ ******************************************/
+static void Z8B_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ CPW(cpustate, cpustate->RW(dst), cpustate->RW(src));
+}
+
+/******************************************
+ comb rbd
+ flags: -ZSP--
+ ******************************************/
+static void Z8C_dddd_0000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ cpustate->RB(dst) = COMB(cpustate, cpustate->RB(dst));
+}
+
+/******************************************
+ negb rbd
+ flags: CZSV--
+ ******************************************/
+static void Z8C_dddd_0010(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ cpustate->RB(dst) = NEGB(cpustate, cpustate->RB(dst));
+}
+
+/******************************************
+ testb rbd
+ flags: -ZSP--
+ ******************************************/
+static void Z8C_dddd_0100(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ TESTB(cpustate, cpustate->RB(dst));
+}
+
+/******************************************
+ tsetb rbd
+ flags: --S---
+ ******************************************/
+static void Z8C_dddd_0110(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ if (cpustate->RB(dst) & S08) SET_S; else CLR_S;
+ cpustate->RB(dst) = 0xff;
+}
+
+/******************************************
+ clrb rbd
+ flags: ------
+ ******************************************/
+static void Z8C_dddd_1000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ cpustate->RB(dst) = 0;
+}
+
+/******************************************
+ nop
+ flags: ------
+ ******************************************/
+static void Z8D_0000_0111(z8000_state *cpustate)
+{
+ /* nothing */
+}
+
+/******************************************
+ com rd
+ flags: -ZS---
+ ******************************************/
+static void Z8D_dddd_0000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ cpustate->RW(dst) = COMW(cpustate, cpustate->RW(dst));
+}
+
+/******************************************
+ neg rd
+ flags: CZSV--
+ ******************************************/
+static void Z8D_dddd_0010(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ cpustate->RW(dst) = NEGW(cpustate, cpustate->RW(dst));
+}
+
+/******************************************
+ test rd
+ flags: ------
+ ******************************************/
+static void Z8D_dddd_0100(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ TESTW(cpustate, cpustate->RW(dst));
+}
+
+/******************************************
+ tset rd
+ flags: --S---
+ ******************************************/
+static void Z8D_dddd_0110(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ if (cpustate->RW(dst) & S16) SET_S; else CLR_S;
+ cpustate->RW(dst) = 0xffff;
+}
+
+/******************************************
+ clr rd
+ flags: ------
+ ******************************************/
+static void Z8D_dddd_1000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ cpustate->RW(dst) = 0;
+}
+
+/******************************************
+ setflg imm4
+ flags: CZSV--
+ ******************************************/
+static void Z8D_imm4_0001(z8000_state *cpustate)
+{
+ cpustate->fcw |= cpustate->op[0] & 0x00f0;
+}
+
+/******************************************
+ resflg imm4
+ flags: CZSV--
+ ******************************************/
+static void Z8D_imm4_0011(z8000_state *cpustate)
+{
+ cpustate->fcw &= ~(cpustate->op[0] & 0x00f0);
+}
+
+/******************************************
+ comflg flags
+ flags: CZSP--
+ ******************************************/
+static void Z8D_imm4_0101(z8000_state *cpustate)
+{
+ cpustate->fcw ^= (cpustate->op[0] & 0x00f0);
+}
+
+/******************************************
+ ext8e imm8
+ flags: ------
+ ******************************************/
+static void Z8E_imm8(z8000_state *cpustate)
+{
+ GET_IMM8(0);
+ LOG(("Z8K '%s' %04x: ext8e $%02x\n", cpustate->device->tag(), cpustate->pc, imm8));
+ if (cpustate->fcw & F_EPU) {
+ /* Z8001 EPU code goes here */
+ (void)imm8;
+ }
+}
+
+/******************************************
+ ext8f imm8
+ flags: ------
+ ******************************************/
+static void Z8F_imm8(z8000_state *cpustate)
+{
+ GET_IMM8(0);
+ LOG(("Z8K '%s' %04x: ext8f $%02x\n", cpustate->device->tag(), cpustate->pc, imm8));
+ if (cpustate->fcw & F_EPU) {
+ /* Z8001 EPU code goes here */
+ (void)imm8;
+ }
+}
+
+/******************************************
+ cpl rrd,rrs
+ flags: CZSV--
+ ******************************************/
+static void Z90_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ CPL(cpustate, cpustate->RL(dst), cpustate->RL(src));
+}
+
+/******************************************
+ pushl @rd,rrs
+ flags: ------
+ ******************************************/
+static void Z91_ddN0_ssss(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ PUSHL(cpustate, dst, cpustate->RL(src));
+}
+
+/******************************************
+ subl rrd,rrs
+ flags: CZSV--
+ ******************************************/
+static void Z92_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RL(dst) = SUBL(cpustate, cpustate->RL(dst), cpustate->RL(src));
+}
+
+/******************************************
+ push @rd,rs
+ flags: ------
+ ******************************************/
+static void Z93_ddN0_ssss(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ PUSHW(cpustate, dst, cpustate->RW(src));
+}
+
+/******************************************
+ ldl rrd,rrs
+ flags: ------
+ ******************************************/
+static void Z94_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RL(dst) = cpustate->RL(src);
+}
+
+/******************************************
+ popl rrd,@rs
+ flags: ------
+ ******************************************/
+static void Z95_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RL(dst) = POPL(cpustate, src);
+}
+
+/******************************************
+ addl rrd,rrs
+ flags: CZSV--
+ ******************************************/
+static void Z96_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RL(dst) = ADDL(cpustate, cpustate->RL(dst), cpustate->RL(src));
+}
+
+/******************************************
+ pop rd,@rs
+ flags: ------
+ ******************************************/
+static void Z97_ssN0_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RW(dst) = POPW(cpustate, src);
+}
+
+/******************************************
+ multl rqd,rrs
+ flags: CZSV--
+ ******************************************/
+static void Z98_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RQ(dst) = MULTL(cpustate, cpustate->RQ(dst), cpustate->RL(src));
+}
+
+/******************************************
+ mult rrd,rs
+ flags: CZSV--
+ ******************************************/
+static void Z99_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RL(dst) = MULTW(cpustate, cpustate->RL(dst), cpustate->RW(src));
+}
+
+/******************************************
+ divl rqd,rrs
+ flags: CZSV--
+ ******************************************/
+static void Z9A_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RQ(dst) = DIVL(cpustate, cpustate->RQ(dst), cpustate->RL(src));
+}
+
+/******************************************
+ div rrd,rs
+ flags: CZSV--
+ ******************************************/
+static void Z9B_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RL(dst) = DIVW(cpustate, cpustate->RL(dst), cpustate->RW(src));
+}
+
+/******************************************
+ testl rrd
+ flags: -ZS---
+ ******************************************/
+static void Z9C_dddd_1000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ CLR_ZS;
+ if (!cpustate->RL(dst)) SET_Z;
+ else if (cpustate->RL(dst) & S32) SET_S;
+}
+
+/******************************************
+ rsvd9d
+ flags: ------
+ ******************************************/
+static void Z9D_imm8(z8000_state *cpustate)
+{
+ GET_IMM8(0);
+ LOG(("Z8K '%s' %04x: rsvd9d $%02x\n", cpustate->device->tag(), cpustate->pc, imm8));
+ if (cpustate->fcw & F_EPU) {
+ /* Z8001 EPU code goes here */
+ (void)imm8;
+ }
+}
+
+/******************************************
+ ret cc
+ flags: ------
+ ******************************************/
+static void Z9E_0000_cccc(z8000_state *cpustate)
+{
+ GET_CCC(OP0,NIB3);
+ switch (cc) {
+ case 0: if (CC0) cpustate->pc = POPW(cpustate, SP); break;
+ case 1: if (CC1) cpustate->pc = POPW(cpustate, SP); break;
+ case 2: if (CC2) cpustate->pc = POPW(cpustate, SP); break;
+ case 3: if (CC3) cpustate->pc = POPW(cpustate, SP); break;
+ case 4: if (CC4) cpustate->pc = POPW(cpustate, SP); break;
+ case 5: if (CC5) cpustate->pc = POPW(cpustate, SP); break;
+ case 6: if (CC6) cpustate->pc = POPW(cpustate, SP); break;
+ case 7: if (CC7) cpustate->pc = POPW(cpustate, SP); break;
+ case 8: if (CC8) cpustate->pc = POPW(cpustate, SP); break;
+ case 9: if (CC9) cpustate->pc = POPW(cpustate, SP); break;
+ case 10: if (CCA) cpustate->pc = POPW(cpustate, SP); break;
+ case 11: if (CCB) cpustate->pc = POPW(cpustate, SP); break;
+ case 12: if (CCC) cpustate->pc = POPW(cpustate, SP); break;
+ case 13: if (CCD) cpustate->pc = POPW(cpustate, SP); break;
+ case 14: if (CCE) cpustate->pc = POPW(cpustate, SP); break;
+ case 15: if (CCF) cpustate->pc = POPW(cpustate, SP); break;
+ }
+}
+
+/******************************************
+ rsvd9f
+ flags: ------
+ ******************************************/
+static void Z9F_imm8(z8000_state *cpustate)
+{
+ GET_IMM8(0);
+ LOG(("Z8K '%s' %04x: rsvd9f $%02x\n", cpustate->device->tag(), cpustate->pc, imm8));
+ if (cpustate->fcw & F_EPU) {
+ /* Z8001 EPU code goes here */
+ (void)imm8;
+ }
+}
+
+/******************************************
+ ldb rbd,rbs
+ flags: ------
+ ******************************************/
+static void ZA0_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RB(dst) = cpustate->RB(src);
+}
+
+/******************************************
+ ld rd,rs
+ flags: ------
+ ******************************************/
+static void ZA1_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RW(dst) = cpustate->RW(src);
+}
+
+/******************************************
+ resb rbd,imm4
+ flags: ------
+ ******************************************/
+static void ZA2_dddd_imm4(z8000_state *cpustate)
+{
+ GET_BIT(OP0);
+ GET_DST(OP0,NIB2);
+ cpustate->RB(dst) &= ~bit;
+}
+
+/******************************************
+ res rd,imm4
+ flags: ------
+ ******************************************/
+static void ZA3_dddd_imm4(z8000_state *cpustate)
+{
+ GET_BIT(OP0);
+ GET_DST(OP0,NIB2);
+ cpustate->RW(dst) &= ~bit;
+}
+
+/******************************************
+ setb rbd,imm4
+ flags: ------
+ ******************************************/
+static void ZA4_dddd_imm4(z8000_state *cpustate)
+{
+ GET_BIT(OP0);
+ GET_DST(OP0,NIB2);
+ cpustate->RB(dst) |= bit;
+}
+
+/******************************************
+ set rd,imm4
+ flags: ------
+ ******************************************/
+static void ZA5_dddd_imm4(z8000_state *cpustate)
+{
+ GET_BIT(OP0);
+ GET_DST(OP0,NIB2);
+ cpustate->RW(dst) |= bit;
+}
+
+/******************************************
+ bitb rbd,imm4
+ flags: -Z----
+ ******************************************/
+static void ZA6_dddd_imm4(z8000_state *cpustate)
+{
+ GET_BIT(OP0);
+ GET_DST(OP0,NIB2);
+ if (cpustate->RB(dst) & bit) CLR_Z; else SET_Z;
+}
+
+/******************************************
+ bit rd,imm4
+ flags: -Z----
+ ******************************************/
+static void ZA7_dddd_imm4(z8000_state *cpustate)
+{
+ GET_BIT(OP0);
+ GET_DST(OP0,NIB2);
+ if (cpustate->RW(dst) & bit) CLR_Z; else SET_Z;
+}
+
+/******************************************
+ incb rbd,imm4m1
+ flags: -ZSV--
+ ******************************************/
+static void ZA8_dddd_imm4m1(z8000_state *cpustate)
+{
+ GET_I4M1(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ cpustate->RB(dst) = INCB(cpustate, cpustate->RB(dst), i4p1);
+}
+
+/******************************************
+ inc rd,imm4m1
+ flags: -ZSV--
+ ******************************************/
+static void ZA9_dddd_imm4m1(z8000_state *cpustate)
+{
+ GET_I4M1(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ cpustate->RW(dst) = INCW(cpustate, cpustate->RW(dst), i4p1);
+}
+
+/******************************************
+ decb rbd,imm4m1
+ flags: -ZSV--
+ ******************************************/
+static void ZAA_dddd_imm4m1(z8000_state *cpustate)
+{
+ GET_I4M1(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ cpustate->RB(dst) = DECB(cpustate, cpustate->RB(dst), i4p1);
+}
+
+/******************************************
+ dec rd,imm4m1
+ flags: -ZSV--
+ ******************************************/
+static void ZAB_dddd_imm4m1(z8000_state *cpustate)
+{
+ GET_I4M1(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ cpustate->RW(dst) = DECW(cpustate, cpustate->RW(dst), i4p1);
+}
+
+/******************************************
+ exb rbd,rbs
+ flags: ------
+ ******************************************/
+static void ZAC_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ UINT8 tmp = cpustate->RB(src);
+ cpustate->RB(src) = cpustate->RB(dst);
+ cpustate->RB(dst) = tmp;
+}
+
+/******************************************
+ ex rd,rs
+ flags: ------
+ ******************************************/
+static void ZAD_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ UINT16 tmp = cpustate->RW(src);
+ cpustate->RW(src) = cpustate->RW(dst);
+ cpustate->RW(dst) = tmp;
+}
+
+/******************************************
+ tccb cc,rbd
+ flags: ------
+ ******************************************/
+static void ZAE_dddd_cccc(z8000_state *cpustate)
+{
+ GET_CCC(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ UINT8 tmp = cpustate->RB(dst) & ~1;
+ switch (cc) {
+ case 0: if (CC0) tmp |= 1; break;
+ case 1: if (CC1) tmp |= 1; break;
+ case 2: if (CC2) tmp |= 1; break;
+ case 3: if (CC3) tmp |= 1; break;
+ case 4: if (CC4) tmp |= 1; break;
+ case 5: if (CC5) tmp |= 1; break;
+ case 6: if (CC6) tmp |= 1; break;
+ case 7: if (CC7) tmp |= 1; break;
+ case 8: if (CC8) tmp |= 1; break;
+ case 9: if (CC9) tmp |= 1; break;
+ case 10: if (CCA) tmp |= 1; break;
+ case 11: if (CCB) tmp |= 1; break;
+ case 12: if (CCC) tmp |= 1; break;
+ case 13: if (CCD) tmp |= 1; break;
+ case 14: if (CCE) tmp |= 1; break;
+ case 15: if (CCF) tmp |= 1; break;
+ }
+ cpustate->RB(dst) = tmp;
+}
+
+/******************************************
+ tcc cc,rd
+ flags: ------
+ ******************************************/
+static void ZAF_dddd_cccc(z8000_state *cpustate)
+{
+ GET_CCC(OP0,NIB3);
+ GET_DST(OP0,NIB2);
+ UINT16 tmp = cpustate->RW(dst) & ~1;
+ switch (cc) {
+ case 0: if (CC0) tmp |= 1; break;
+ case 1: if (CC1) tmp |= 1; break;
+ case 2: if (CC2) tmp |= 1; break;
+ case 3: if (CC3) tmp |= 1; break;
+ case 4: if (CC4) tmp |= 1; break;
+ case 5: if (CC5) tmp |= 1; break;
+ case 6: if (CC6) tmp |= 1; break;
+ case 7: if (CC7) tmp |= 1; break;
+ case 8: if (CC8) tmp |= 1; break;
+ case 9: if (CC9) tmp |= 1; break;
+ case 10: if (CCA) tmp |= 1; break;
+ case 11: if (CCB) tmp |= 1; break;
+ case 12: if (CCC) tmp |= 1; break;
+ case 13: if (CCD) tmp |= 1; break;
+ case 14: if (CCE) tmp |= 1; break;
+ case 15: if (CCF) tmp |= 1; break;
+ }
+ cpustate->RW(dst) = tmp;
+}
+
+/******************************************
+ dab rbd
+ flags: CZS---
+ ******************************************/
+static void ZB0_dddd_0000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ UINT8 result;
+ UINT16 idx = cpustate->RB(dst);
+ if (cpustate->fcw & F_C) idx |= 0x100;
+ if (cpustate->fcw & F_H) idx |= 0x200;
+ if (cpustate->fcw & F_DA) idx |= 0x400;
+ result = Z8000_dab[idx];
+ CLR_CZS;
+ CHK_XXXB_ZS;
+ if (Z8000_dab[idx] & 0x100) SET_C;
+ cpustate->RB(dst) = result;
+}
+
+/******************************************
+ extsb rd
+ flags: ------
+ ******************************************/
+static void ZB1_dddd_0000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ cpustate->RW(dst) = (cpustate->RW(dst) & 0xff) | ((cpustate->RW(dst) & S08) ? 0xff00 : 0x0000);
+}
+
+/******************************************
+ extsl rqd
+ flags: ------
+ ******************************************/
+static void ZB1_dddd_0111(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ cpustate->RQ(dst) = CONCAT_64((cpustate->RQ(dst) & S32) ?
+ 0xfffffffful : 0, EXTRACT_64LO(cpustate->RQ(dst)));
+}
+
+/******************************************
+ exts rrd
+ flags: ------
+ ******************************************/
+static void ZB1_dddd_1010(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ cpustate->RL(dst) = (cpustate->RL(dst) & 0xffff) | ((cpustate->RL(dst) & S16) ?
+ 0xffff0000ul : 0x00000000ul);
+}
+
+/******************************************
+ sllb rbd,imm8
+ flags: CZS---
+ srlb rbd,imm8
+ flags: CZSV--
+ ******************************************/
+static void ZB2_dddd_0001_imm8(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_IMM16(OP1);
+ if (imm16 & S16)
+ cpustate->RB(dst) = SRLB(cpustate, cpustate->RB(dst), -(INT16)imm16);
+ else
+ cpustate->RB(dst) = SLLB(cpustate, cpustate->RB(dst), imm16);
+}
+
+/******************************************
+ sdlb rbd,rs
+ flags: CZS---
+ ******************************************/
+static void ZB2_dddd_0011_0000_ssss_0000_0000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_SRC(OP1,NIB1);
+ cpustate->RB(dst) = SRLB(cpustate, cpustate->RB(dst), (INT8)cpustate->RW(src));
+}
+
+/******************************************
+ rlb rbd,imm1or2
+ flags: CZSV--
+ ******************************************/
+static void ZB2_dddd_00I0(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_IMM1(OP0,NIB3);
+ cpustate->RB(dst) = RLB(cpustate, cpustate->RB(dst), imm1);
+}
+
+/******************************************
+ rrb rbd,imm1or2
+ flags: CZSV--
+ ******************************************/
+static void ZB2_dddd_01I0(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_IMM1(OP0,NIB3);
+ cpustate->RB(dst) = RRB(cpustate, cpustate->RB(dst), imm1);
+}
+
+/******************************************
+ slab rbd,imm8
+ flags: CZSV--
+ srab rbd,imm8
+ flags: CZSV--
+ ******************************************/
+static void ZB2_dddd_1001_imm8(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_IMM16(OP1);
+ if (imm16 & S16)
+ cpustate->RB(dst) = SRAB(cpustate, cpustate->RB(dst), -(INT16)imm16);
+ else
+ cpustate->RB(dst) = SLAB(cpustate, cpustate->RB(dst), imm16);
+}
+
+/******************************************
+ sdab rbd,rs
+ flags: CZSV--
+ ******************************************/
+static void ZB2_dddd_1011_0000_ssss_0000_0000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_SRC(OP1,NIB1);
+ cpustate->RB(dst) = SDAB(cpustate, cpustate->RB(dst), (INT8) cpustate->RW(src));
+}
+
+/******************************************
+ rlcb rbd,imm1or2
+ flags: -Z----
+ ******************************************/
+static void ZB2_dddd_10I0(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_IMM1(OP0,NIB3);
+ cpustate->RB(dst) = RLCB(cpustate, cpustate->RB(dst), imm1);
+}
+
+/******************************************
+ rrcb rbd,imm1or2
+ flags: -Z----
+ ******************************************/
+static void ZB2_dddd_11I0(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_IMM1(OP0,NIB3);
+ cpustate->RB(dst) = RRCB(cpustate, cpustate->RB(dst), imm1);
+}
+
+/******************************************
+ sll rd,imm8
+ flags: CZS---
+ srl rd,imm8
+ flags: CZSV--
+ ******************************************/
+static void ZB3_dddd_0001_imm8(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_IMM16(OP1);
+ if (imm16 & S16)
+ cpustate->RW(dst) = SRLW(cpustate, cpustate->RW(dst), -(INT16)imm16);
+ else
+ cpustate->RW(dst) = SLLW(cpustate, cpustate->RW(dst), imm16);
+}
+
+/******************************************
+ sdl rd,rs
+ flags: CZS---
+ ******************************************/
+static void ZB3_dddd_0011_0000_ssss_0000_0000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_SRC(OP1,NIB1);
+ cpustate->RW(dst) = SDLW(cpustate, cpustate->RW(dst), (INT8)cpustate->RW(src));
+}
+
+/******************************************
+ rl rd,imm1or2
+ flags: CZSV--
+ ******************************************/
+static void ZB3_dddd_00I0(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_IMM1(OP0,NIB3);
+ cpustate->RW(dst) = RLW(cpustate, cpustate->RW(dst), imm1);
+}
+
+/******************************************
+ slll rrd,imm8
+ flags: CZS---
+ srll rrd,imm8
+ flags: CZSV--
+ ******************************************/
+static void ZB3_dddd_0101_imm8(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_IMM16(OP1);
+ if (imm16 & S16)
+ cpustate->RL(dst) = SRLL(cpustate, cpustate->RL(dst), -(INT16)imm16);
+ else
+ cpustate->RL(dst) = SLLL(cpustate, cpustate->RL(dst), imm16);
+}
+
+/******************************************
+ sdll rrd,rs
+ flags: CZS---
+ ******************************************/
+static void ZB3_dddd_0111_0000_ssss_0000_0000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_SRC(OP1,NIB1);
+ cpustate->RL(dst) = SDLL(cpustate, cpustate->RL(dst), cpustate->RW(src) & 0xff);
+}
+
+/******************************************
+ rr rd,imm1or2
+ flags: CZSV--
+ ******************************************/
+static void ZB3_dddd_01I0(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_IMM1(OP0,NIB3);
+ cpustate->RW(dst) = RRW(cpustate, cpustate->RW(dst), imm1);
+}
+
+/******************************************
+ sla rd,imm8
+ flags: CZSV--
+ sra rd,imm8
+ flags: CZSV--
+ ******************************************/
+static void ZB3_dddd_1001_imm8(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_IMM16(OP1);
+ if (imm16 & S16)
+ cpustate->RW(dst) = SRAW(cpustate, cpustate->RW(dst), -(INT16)imm16);
+ else
+ cpustate->RW(dst) = SLAW(cpustate, cpustate->RW(dst), imm16);
+}
+
+/******************************************
+ sda rd,rs
+ flags: CZSV--
+ ******************************************/
+static void ZB3_dddd_1011_0000_ssss_0000_0000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_SRC(OP1,NIB1);
+ cpustate->RW(dst) = SDAW(cpustate, cpustate->RW(dst), (INT8)cpustate->RW(src));
+}
+
+/******************************************
+ rlc rd,imm1or2
+ flags: CZSV--
+ ******************************************/
+static void ZB3_dddd_10I0(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_IMM1(OP0,NIB3);
+ cpustate->RW(dst) = RLCW(cpustate, cpustate->RW(dst), imm1);
+}
+
+/******************************************
+ slal rrd,imm8
+ flags: CZSV--
+ sral rrd,imm8
+ flags: CZSV--
+ ******************************************/
+static void ZB3_dddd_1101_imm8(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_IMM16(OP1);
+ if (imm16 & S16)
+ cpustate->RL(dst) = SRAL(cpustate, cpustate->RL(dst), -(INT16)imm16);
+ else
+ cpustate->RL(dst) = SLAL(cpustate, cpustate->RL(dst), imm16);
+}
+
+/******************************************
+ sdal rrd,rs
+ flags: CZSV--
+ ******************************************/
+static void ZB3_dddd_1111_0000_ssss_0000_0000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_SRC(OP1,NIB1);
+ cpustate->RL(dst) = SDAL(cpustate, cpustate->RL(dst), cpustate->RW(src) & 0xff);
+}
+
+/******************************************
+ rrc rd,imm1or2
+ flags: CZSV--
+ ******************************************/
+static void ZB3_dddd_11I0(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_IMM1(OP0,NIB3);
+ cpustate->RW(dst) = RRCW(cpustate, cpustate->RW(dst), imm1);
+}
+
+/******************************************
+ adcb rbd,rbs
+ flags: CZSVDH
+ ******************************************/
+static void ZB4_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RB(dst) = ADCB(cpustate, cpustate->RB(dst), cpustate->RB(src));
+}
+
+/******************************************
+ adc rd,rs
+ flags: CZSV--
+ ******************************************/
+static void ZB5_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RW(dst) = ADCW(cpustate, cpustate->RW(dst), cpustate->RW(src));
+}
+
+/******************************************
+ sbcb rbd,rbs
+ flags: CZSVDH
+ ******************************************/
+static void ZB6_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RB(dst) = SBCB(cpustate, cpustate->RB(dst), cpustate->RB(src));
+}
+
+/******************************************
+ sbc rd,rs
+ flags: CZSV--
+ ******************************************/
+static void ZB7_ssss_dddd(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB3);
+ GET_SRC(OP0,NIB2);
+ cpustate->RW(dst) = SBCW(cpustate, cpustate->RW(dst), cpustate->RW(src));
+}
+
+/******************************************
+ trtib @rd,@rs,rr
+ flags: -ZSV--
+ ******************************************/
+static void ZB8_ddN0_0010_0000_rrrr_ssN0_0000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_SRC(OP1,NIB2);
+ GET_CNT(OP1,NIB1);
+ UINT8 xlt = RDMEM_B(cpustate, (UINT16)(cpustate->RW(src) + RDMEM_B(cpustate, cpustate->RW(dst))));
+ cpustate->RB(2) = xlt;
+ if (xlt) CLR_Z; else SET_Z;
+ cpustate->RW(dst)++;
+ if (--cpustate->RW(cnt)) CLR_V; else SET_V;
+}
+
+/******************************************
+ trtirb @rd,@rs,rbr
+ flags: -ZSV--
+ ******************************************/
+static void ZB8_ddN0_0110_0000_rrrr_ssN0_1110(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_SRC(OP1,NIB2);
+ GET_CNT(OP1,NIB1);
+ UINT8 xlt = RDMEM_B(cpustate, (UINT16)(cpustate->RW(src) + RDMEM_B(cpustate, cpustate->RW(dst))));
+ cpustate->RB(2) = xlt;
+ if (xlt) CLR_Z; else SET_Z;
+ cpustate->RW(dst)++;
+ if (--cpustate->RW(cnt)) { CLR_V; cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ trtdb @rd,@rs,rbr
+ flags: -ZSV--
+ ******************************************/
+static void ZB8_ddN0_1010_0000_rrrr_ssN0_0000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_SRC(OP1,NIB2);
+ GET_CNT(OP1,NIB1);
+ UINT8 xlt = RDMEM_B(cpustate, (UINT16)(cpustate->RW(src) + RDMEM_B(cpustate, cpustate->RW(dst))));
+ cpustate->RB(2) = xlt;
+ if (xlt) CLR_Z; else SET_Z;
+ cpustate->RW(dst)--;
+ if (--cpustate->RW(cnt)) CLR_V; else SET_V;
+}
+
+/******************************************
+ trtdrb @rd,@rs,rbr
+ flags: -ZSV--
+ ******************************************/
+static void ZB8_ddN0_1110_0000_rrrr_ssN0_1110(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_SRC(OP1,NIB2);
+ GET_CNT(OP1,NIB1);
+ UINT8 xlt = RDMEM_B(cpustate, (UINT16)(cpustate->RW(src) + RDMEM_B(cpustate, cpustate->RW(dst))));
+ cpustate->RB(2) = xlt;
+ if (xlt) CLR_Z; else SET_Z;
+ cpustate->RW(dst)--;
+ if (--cpustate->RW(cnt)) { CLR_V; cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ trib @rd,@rs,rbr
+ flags: -ZSV--
+ ******************************************/
+static void ZB8_ddN0_0000_0000_rrrr_ssN0_0000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_SRC(OP1,NIB2);
+ GET_CNT(OP1,NIB1);
+ UINT8 xlt = RDMEM_B(cpustate, (UINT16)(cpustate->RW(src) + RDMEM_B(cpustate, cpustate->RW(dst))));
+ WRMEM_B(cpustate, cpustate->RW(dst), xlt);
+ cpustate->RW(dst)++;
+ if (--cpustate->RW(cnt)) CLR_V; else SET_V;
+}
+
+/******************************************
+ trirb @rd,@rs,rbr
+ flags: -ZSV--
+ ******************************************/
+static void ZB8_ddN0_0100_0000_rrrr_ssN0_0000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_SRC(OP1,NIB2);
+ GET_CNT(OP1,NIB1);
+ UINT8 xlt = RDMEM_B(cpustate, (UINT16)(cpustate->RW(src) + RDMEM_B(cpustate, cpustate->RW(dst))));
+ WRMEM_B(cpustate, cpustate->RW(dst), xlt);
+ cpustate->RW(dst)++;
+ if (--cpustate->RW(cnt)) { CLR_V; cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ trdb @rd,@rs,rbr
+ flags: -ZSV--
+ ******************************************/
+static void ZB8_ddN0_1000_0000_rrrr_ssN0_0000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_SRC(OP1,NIB2);
+ GET_CNT(OP1,NIB1);
+ UINT8 xlt = RDMEM_B(cpustate, (UINT16)(cpustate->RW(src) + RDMEM_B(cpustate, cpustate->RW(dst))));
+ WRMEM_B(cpustate, cpustate->RW(dst), xlt);
+ cpustate->RW(dst)--;
+ if (--cpustate->RW(cnt)) CLR_V; else SET_V;
+}
+
+/******************************************
+ trdrb @rd,@rs,rbr
+ flags: -ZSV--
+ ******************************************/
+static void ZB8_ddN0_1100_0000_rrrr_ssN0_0000(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_SRC(OP1,NIB2);
+ GET_CNT(OP1,NIB1);
+ UINT8 xlt = RDMEM_B(cpustate, (UINT16)(cpustate->RW(src) + RDMEM_B(cpustate, cpustate->RW(dst))));
+ WRMEM_B(cpustate, cpustate->RW(dst), xlt);
+ cpustate->RW(dst)--;
+ if (--cpustate->RW(cnt)) { CLR_V; cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ rsvdb9
+ flags: ------
+ ******************************************/
+static void ZB9_imm8(z8000_state *cpustate)
+{
+ GET_IMM8(0);
+ LOG(("Z8K '%s' %04x: rsvdb9 $%02x\n", cpustate->device->tag(), cpustate->pc, imm8));
+ if (cpustate->fcw & F_EPU) {
+ /* Z8001 EPU code goes here */
+ (void)imm8;
+ }
+ (void)imm8;
+}
+
+/******************************************
+ cpib rbd,@rs,rr,cc
+ flags: CZSV--
+ ******************************************/
+static void ZBA_ssN0_0000_0000_rrrr_dddd_cccc(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CCC(OP1,NIB3);
+ GET_DST(OP1,NIB2);
+ GET_CNT(OP1,NIB1);
+ CPB(cpustate, cpustate->RB(dst), RDMEM_B(cpustate, cpustate->RW(src)));
+ switch (cc) {
+ case 0: if (CC0) SET_Z; else CLR_Z; break;
+ case 1: if (CC1) SET_Z; else CLR_Z; break;
+ case 2: if (CC2) SET_Z; else CLR_Z; break;
+ case 3: if (CC3) SET_Z; else CLR_Z; break;
+ case 4: if (CC4) SET_Z; else CLR_Z; break;
+ case 5: if (CC5) SET_Z; else CLR_Z; break;
+ case 6: if (CC6) SET_Z; else CLR_Z; break;
+ case 7: if (CC7) SET_Z; else CLR_Z; break;
+ case 8: if (CC8) SET_Z; else CLR_Z; break;
+ case 9: if (CC9) SET_Z; else CLR_Z; break;
+ case 10: if (CCA) SET_Z; else CLR_Z; break;
+ case 11: if (CCB) SET_Z; else CLR_Z; break;
+ case 12: if (CCC) SET_Z; else CLR_Z; break;
+ case 13: if (CCD) SET_Z; else CLR_Z; break;
+ case 14: if (CCE) SET_Z; else CLR_Z; break;
+ case 15: if (CCF) SET_Z; else CLR_Z; break;
+ }
+ cpustate->RW(src)++;
+ if (--cpustate->RW(cnt)) CLR_V; else SET_V;
+}
+
+/******************************************
+ ldib @rd,@rs,rr
+ ldibr @rd,@rs,rr
+ flags: ---V--
+ ******************************************/
+static void ZBA_ssN0_0001_0000_rrrr_ddN0_x000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CNT(OP1,NIB1);
+ GET_DST(OP1,NIB2);
+ GET_CCC(OP1,NIB3); /* repeat? */
+ WRMEM_B(cpustate, cpustate->RW(dst), RDMEM_B(cpustate, cpustate->RW(src)));
+ cpustate->RW(dst)++;
+ cpustate->RW(src)++;
+ if (--cpustate->RW(cnt)) { CLR_V; if (cc == 0) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ cpsib @rd,@rs,rr,cc
+ flags: CZSV--
+ ******************************************/
+static void ZBA_ssN0_0010_0000_rrrr_ddN0_cccc(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CCC(OP1,NIB3);
+ GET_DST(OP1,NIB2);
+ GET_CNT(OP1,NIB1);
+ CPB(cpustate, RDMEM_B(cpustate, cpustate->RW(dst)), RDMEM_B(cpustate, cpustate->RW(src)));
+ switch (cc) {
+ case 0: if (CC0) SET_Z; else CLR_Z; break;
+ case 1: if (CC1) SET_Z; else CLR_Z; break;
+ case 2: if (CC2) SET_Z; else CLR_Z; break;
+ case 3: if (CC3) SET_Z; else CLR_Z; break;
+ case 4: if (CC4) SET_Z; else CLR_Z; break;
+ case 5: if (CC5) SET_Z; else CLR_Z; break;
+ case 6: if (CC6) SET_Z; else CLR_Z; break;
+ case 7: if (CC7) SET_Z; else CLR_Z; break;
+ case 8: if (CC8) SET_Z; else CLR_Z; break;
+ case 9: if (CC9) SET_Z; else CLR_Z; break;
+ case 10: if (CCA) SET_Z; else CLR_Z; break;
+ case 11: if (CCB) SET_Z; else CLR_Z; break;
+ case 12: if (CCC) SET_Z; else CLR_Z; break;
+ case 13: if (CCD) SET_Z; else CLR_Z; break;
+ case 14: if (CCE) SET_Z; else CLR_Z; break;
+ case 15: if (CCF) SET_Z; else CLR_Z; break;
+ }
+ cpustate->RW(dst)++;
+ cpustate->RW(src)++;
+ if (--cpustate->RW(cnt)) { CLR_V; if (!(cpustate->fcw & F_Z)) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ cpirb rbd,@rs,rr,cc
+ flags: CZSV--
+ ******************************************/
+static void ZBA_ssN0_0100_0000_rrrr_dddd_cccc(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CCC(OP1,NIB3);
+ GET_DST(OP1,NIB2);
+ GET_CNT(OP1,NIB1);
+ CPB(cpustate, cpustate->RB(dst), RDMEM_B(cpustate, cpustate->RW(src)));
+ switch (cc) {
+ case 0: if (CC0) SET_Z; else CLR_Z; break;
+ case 1: if (CC1) SET_Z; else CLR_Z; break;
+ case 2: if (CC2) SET_Z; else CLR_Z; break;
+ case 3: if (CC3) SET_Z; else CLR_Z; break;
+ case 4: if (CC4) SET_Z; else CLR_Z; break;
+ case 5: if (CC5) SET_Z; else CLR_Z; break;
+ case 6: if (CC6) SET_Z; else CLR_Z; break;
+ case 7: if (CC7) SET_Z; else CLR_Z; break;
+ case 8: if (CC8) SET_Z; else CLR_Z; break;
+ case 9: if (CC9) SET_Z; else CLR_Z; break;
+ case 10: if (CCA) SET_Z; else CLR_Z; break;
+ case 11: if (CCB) SET_Z; else CLR_Z; break;
+ case 12: if (CCC) SET_Z; else CLR_Z; break;
+ case 13: if (CCD) SET_Z; else CLR_Z; break;
+ case 14: if (CCE) SET_Z; else CLR_Z; break;
+ case 15: if (CCF) SET_Z; else CLR_Z; break;
+ }
+ cpustate->RW(src)++;
+ if (--cpustate->RW(cnt)) { CLR_V; if (!(cpustate->fcw & F_Z)) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ cpsirb @rd,@rs,rr,cc
+ flags: CZSV--
+ ******************************************/
+static void ZBA_ssN0_0110_0000_rrrr_ddN0_cccc(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CCC(OP1,NIB3);
+ GET_DST(OP1,NIB2);
+ GET_CNT(OP1,NIB1);
+ CPB(cpustate, RDMEM_B(cpustate, cpustate->RW(dst)), RDMEM_B(cpustate, cpustate->RW(src)));
+ switch (cc) {
+ case 0: if (CC0) SET_Z; else CLR_Z; break;
+ case 1: if (CC1) SET_Z; else CLR_Z; break;
+ case 2: if (CC2) SET_Z; else CLR_Z; break;
+ case 3: if (CC3) SET_Z; else CLR_Z; break;
+ case 4: if (CC4) SET_Z; else CLR_Z; break;
+ case 5: if (CC5) SET_Z; else CLR_Z; break;
+ case 6: if (CC6) SET_Z; else CLR_Z; break;
+ case 7: if (CC7) SET_Z; else CLR_Z; break;
+ case 8: if (CC8) SET_Z; else CLR_Z; break;
+ case 9: if (CC9) SET_Z; else CLR_Z; break;
+ case 10: if (CCA) SET_Z; else CLR_Z; break;
+ case 11: if (CCB) SET_Z; else CLR_Z; break;
+ case 12: if (CCC) SET_Z; else CLR_Z; break;
+ case 13: if (CCD) SET_Z; else CLR_Z; break;
+ case 14: if (CCE) SET_Z; else CLR_Z; break;
+ case 15: if (CCF) SET_Z; else CLR_Z; break;
+ }
+ cpustate->RW(dst)++;
+ cpustate->RW(src)++;
+ if (--cpustate->RW(cnt)) { CLR_V; if (!(cpustate->fcw & F_Z)) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ cpdb rbd,@rs,rr,cc
+ flags: CZSV--
+ ******************************************/
+static void ZBA_ssN0_1000_0000_rrrr_dddd_cccc(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CCC(OP1,NIB3);
+ GET_DST(OP1,NIB2);
+ GET_CNT(OP1,NIB1);
+ CPB(cpustate, cpustate->RB(dst), RDMEM_B(cpustate, cpustate->RW(src)));
+ switch (cc) {
+ case 0: if (CC0) SET_Z; else CLR_Z; break;
+ case 1: if (CC1) SET_Z; else CLR_Z; break;
+ case 2: if (CC2) SET_Z; else CLR_Z; break;
+ case 3: if (CC3) SET_Z; else CLR_Z; break;
+ case 4: if (CC4) SET_Z; else CLR_Z; break;
+ case 5: if (CC5) SET_Z; else CLR_Z; break;
+ case 6: if (CC6) SET_Z; else CLR_Z; break;
+ case 7: if (CC7) SET_Z; else CLR_Z; break;
+ case 8: if (CC8) SET_Z; else CLR_Z; break;
+ case 9: if (CC9) SET_Z; else CLR_Z; break;
+ case 10: if (CCA) SET_Z; else CLR_Z; break;
+ case 11: if (CCB) SET_Z; else CLR_Z; break;
+ case 12: if (CCC) SET_Z; else CLR_Z; break;
+ case 13: if (CCD) SET_Z; else CLR_Z; break;
+ case 14: if (CCE) SET_Z; else CLR_Z; break;
+ case 15: if (CCF) SET_Z; else CLR_Z; break;
+ }
+ cpustate->RW(src)--;
+ if (--cpustate->RW(cnt)) CLR_V; else SET_V;
+}
+
+/******************************************
+ lddb @rs,@rd,rr
+ lddbr @rs,@rd,rr
+ flags: ---V--
+ ******************************************/
+static void ZBA_ssN0_1001_0000_rrrr_ddN0_x000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CNT(OP1,NIB1);
+ GET_DST(OP1,NIB2);
+ GET_CCC(OP1,NIB3);
+ WRMEM_B(cpustate, cpustate->RW(dst), RDMEM_B(cpustate, cpustate->RW(src)));
+ cpustate->RW(dst)--;
+ cpustate->RW(src)--;
+ if (--cpustate->RW(cnt)) { CLR_V; if (cc == 0) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ cpsdb @rd,@rs,rr,cc
+ flags: CZSV--
+ ******************************************/
+static void ZBA_ssN0_1010_0000_rrrr_ddN0_cccc(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CCC(OP1,NIB3);
+ GET_DST(OP1,NIB2);
+ GET_CNT(OP1,NIB1);
+ CPB(cpustate, RDMEM_B(cpustate, cpustate->RW(dst)), RDMEM_B(cpustate, cpustate->RW(src)));
+ switch (cc) {
+ case 0: if (CC0) SET_Z; else CLR_Z; break;
+ case 1: if (CC1) SET_Z; else CLR_Z; break;
+ case 2: if (CC2) SET_Z; else CLR_Z; break;
+ case 3: if (CC3) SET_Z; else CLR_Z; break;
+ case 4: if (CC4) SET_Z; else CLR_Z; break;
+ case 5: if (CC5) SET_Z; else CLR_Z; break;
+ case 6: if (CC6) SET_Z; else CLR_Z; break;
+ case 7: if (CC7) SET_Z; else CLR_Z; break;
+ case 8: if (CC8) SET_Z; else CLR_Z; break;
+ case 9: if (CC9) SET_Z; else CLR_Z; break;
+ case 10: if (CCA) SET_Z; else CLR_Z; break;
+ case 11: if (CCB) SET_Z; else CLR_Z; break;
+ case 12: if (CCC) SET_Z; else CLR_Z; break;
+ case 13: if (CCD) SET_Z; else CLR_Z; break;
+ case 14: if (CCE) SET_Z; else CLR_Z; break;
+ case 15: if (CCF) SET_Z; else CLR_Z; break;
+ }
+ cpustate->RW(dst)--;
+ cpustate->RW(src)--;
+ if (--cpustate->RW(cnt)) CLR_V; else SET_V;
+}
+
+/******************************************
+ cpdrb rbd,@rs,rr,cc
+ flags: CZSV--
+ ******************************************/
+static void ZBA_ssN0_1100_0000_rrrr_dddd_cccc(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CCC(OP1,NIB3);
+ GET_DST(OP1,NIB2);
+ GET_CNT(OP1,NIB1);
+ CPB(cpustate, cpustate->RB(dst), RDMEM_B(cpustate, cpustate->RW(src)));
+ switch (cc) {
+ case 0: if (CC0) SET_Z; else CLR_Z; break;
+ case 1: if (CC1) SET_Z; else CLR_Z; break;
+ case 2: if (CC2) SET_Z; else CLR_Z; break;
+ case 3: if (CC3) SET_Z; else CLR_Z; break;
+ case 4: if (CC4) SET_Z; else CLR_Z; break;
+ case 5: if (CC5) SET_Z; else CLR_Z; break;
+ case 6: if (CC6) SET_Z; else CLR_Z; break;
+ case 7: if (CC7) SET_Z; else CLR_Z; break;
+ case 8: if (CC8) SET_Z; else CLR_Z; break;
+ case 9: if (CC9) SET_Z; else CLR_Z; break;
+ case 10: if (CCA) SET_Z; else CLR_Z; break;
+ case 11: if (CCB) SET_Z; else CLR_Z; break;
+ case 12: if (CCC) SET_Z; else CLR_Z; break;
+ case 13: if (CCD) SET_Z; else CLR_Z; break;
+ case 14: if (CCE) SET_Z; else CLR_Z; break;
+ case 15: if (CCF) SET_Z; else CLR_Z; break;
+ }
+ cpustate->RW(src)--;
+ if (--cpustate->RW(cnt)) { CLR_V; if (!(cpustate->fcw & F_Z)) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ cpsdrb @rd,@rs,rr,cc
+ flags: CZSV--
+ ******************************************/
+static void ZBA_ssN0_1110_0000_rrrr_ddN0_cccc(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CCC(OP1,NIB3);
+ GET_DST(OP1,NIB2);
+ GET_CNT(OP1,NIB1);
+ CPB(cpustate, RDMEM_B(cpustate, cpustate->RW(dst)), RDMEM_B(cpustate, cpustate->RW(src)));
+ switch (cc) {
+ case 0: if (CC0) SET_Z; else CLR_Z; break;
+ case 1: if (CC1) SET_Z; else CLR_Z; break;
+ case 2: if (CC2) SET_Z; else CLR_Z; break;
+ case 3: if (CC3) SET_Z; else CLR_Z; break;
+ case 4: if (CC4) SET_Z; else CLR_Z; break;
+ case 5: if (CC5) SET_Z; else CLR_Z; break;
+ case 6: if (CC6) SET_Z; else CLR_Z; break;
+ case 7: if (CC7) SET_Z; else CLR_Z; break;
+ case 8: if (CC8) SET_Z; else CLR_Z; break;
+ case 9: if (CC9) SET_Z; else CLR_Z; break;
+ case 10: if (CCA) SET_Z; else CLR_Z; break;
+ case 11: if (CCB) SET_Z; else CLR_Z; break;
+ case 12: if (CCC) SET_Z; else CLR_Z; break;
+ case 13: if (CCD) SET_Z; else CLR_Z; break;
+ case 14: if (CCE) SET_Z; else CLR_Z; break;
+ case 15: if (CCF) SET_Z; else CLR_Z; break;
+ }
+ cpustate->RW(dst)--;
+ cpustate->RW(src)--;
+ if (--cpustate->RW(cnt)) { CLR_V; if (!(cpustate->fcw & F_Z)) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ cpi rd,@rs,rr,cc
+ flags: CZSV--
+ ******************************************/
+static void ZBB_ssN0_0000_0000_rrrr_dddd_cccc(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CCC(OP1,NIB3);
+ GET_DST(OP1,NIB2);
+ GET_CNT(OP1,NIB1);
+ CPW(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, cpustate->RW(src)));
+ switch (cc) {
+ case 0: if (CC0) SET_Z; else CLR_Z; break;
+ case 1: if (CC1) SET_Z; else CLR_Z; break;
+ case 2: if (CC2) SET_Z; else CLR_Z; break;
+ case 3: if (CC3) SET_Z; else CLR_Z; break;
+ case 4: if (CC4) SET_Z; else CLR_Z; break;
+ case 5: if (CC5) SET_Z; else CLR_Z; break;
+ case 6: if (CC6) SET_Z; else CLR_Z; break;
+ case 7: if (CC7) SET_Z; else CLR_Z; break;
+ case 8: if (CC8) SET_Z; else CLR_Z; break;
+ case 9: if (CC9) SET_Z; else CLR_Z; break;
+ case 10: if (CCA) SET_Z; else CLR_Z; break;
+ case 11: if (CCB) SET_Z; else CLR_Z; break;
+ case 12: if (CCC) SET_Z; else CLR_Z; break;
+ case 13: if (CCD) SET_Z; else CLR_Z; break;
+ case 14: if (CCE) SET_Z; else CLR_Z; break;
+ case 15: if (CCF) SET_Z; else CLR_Z; break;
+ }
+ cpustate->RW(src) += 2;
+ if (--cpustate->RW(cnt)) CLR_V; else SET_V;
+}
+
+/******************************************
+ ldi @rd,@rs,rr
+ ldir @rd,@rs,rr
+ flags: ---V--
+ ******************************************/
+static void ZBB_ssN0_0001_0000_rrrr_ddN0_x000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CNT(OP1,NIB1);
+ GET_DST(OP1,NIB2);
+ GET_CCC(OP1,NIB3);
+ WRMEM_W(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, cpustate->RW(src)));
+ cpustate->RW(dst) += 2;
+ cpustate->RW(src) += 2;
+ if (--cpustate->RW(cnt)) { CLR_V; if (cc == 0) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ cpsi @rd,@rs,rr,cc
+ flags: CZSV--
+ ******************************************/
+static void ZBB_ssN0_0010_0000_rrrr_ddN0_cccc(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CCC(OP1,NIB3);
+ GET_DST(OP1,NIB2);
+ GET_CNT(OP1,NIB1);
+ CPW(cpustate, RDMEM_W(cpustate, cpustate->RW(dst)), RDMEM_W(cpustate, cpustate->RW(src)));
+ switch (cc) {
+ case 0: if (CC0) SET_Z; else CLR_Z; break;
+ case 1: if (CC1) SET_Z; else CLR_Z; break;
+ case 2: if (CC2) SET_Z; else CLR_Z; break;
+ case 3: if (CC3) SET_Z; else CLR_Z; break;
+ case 4: if (CC4) SET_Z; else CLR_Z; break;
+ case 5: if (CC5) SET_Z; else CLR_Z; break;
+ case 6: if (CC6) SET_Z; else CLR_Z; break;
+ case 7: if (CC7) SET_Z; else CLR_Z; break;
+ case 8: if (CC8) SET_Z; else CLR_Z; break;
+ case 9: if (CC9) SET_Z; else CLR_Z; break;
+ case 10: if (CCA) SET_Z; else CLR_Z; break;
+ case 11: if (CCB) SET_Z; else CLR_Z; break;
+ case 12: if (CCC) SET_Z; else CLR_Z; break;
+ case 13: if (CCD) SET_Z; else CLR_Z; break;
+ case 14: if (CCE) SET_Z; else CLR_Z; break;
+ case 15: if (CCF) SET_Z; else CLR_Z; break;
+ }
+ cpustate->RW(dst) += 2;
+ cpustate->RW(src) += 2;
+ if (--cpustate->RW(cnt)) CLR_V; else SET_V;
+}
+
+/******************************************
+ cpir rd,@rs,rr,cc
+ flags: CZSV--
+ ******************************************/
+static void ZBB_ssN0_0100_0000_rrrr_dddd_cccc(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CCC(OP1,NIB3);
+ GET_DST(OP1,NIB2);
+ GET_CNT(OP1,NIB1);
+ CPW(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, cpustate->RW(src)));
+ switch (cc) {
+ case 0: if (CC0) SET_Z; else CLR_Z; break;
+ case 1: if (CC1) SET_Z; else CLR_Z; break;
+ case 2: if (CC2) SET_Z; else CLR_Z; break;
+ case 3: if (CC3) SET_Z; else CLR_Z; break;
+ case 4: if (CC4) SET_Z; else CLR_Z; break;
+ case 5: if (CC5) SET_Z; else CLR_Z; break;
+ case 6: if (CC6) SET_Z; else CLR_Z; break;
+ case 7: if (CC7) SET_Z; else CLR_Z; break;
+ case 8: if (CC8) SET_Z; else CLR_Z; break;
+ case 9: if (CC9) SET_Z; else CLR_Z; break;
+ case 10: if (CCA) SET_Z; else CLR_Z; break;
+ case 11: if (CCB) SET_Z; else CLR_Z; break;
+ case 12: if (CCC) SET_Z; else CLR_Z; break;
+ case 13: if (CCD) SET_Z; else CLR_Z; break;
+ case 14: if (CCE) SET_Z; else CLR_Z; break;
+ case 15: if (CCF) SET_Z; else CLR_Z; break;
+ }
+ cpustate->RW(src) += 2;
+ if (--cpustate->RW(cnt)) { CLR_V; if (!(cpustate->fcw & F_Z)) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ cpsir @rd,@rs,rr,cc
+ flags: CZSV--
+ ******************************************/
+static void ZBB_ssN0_0110_0000_rrrr_ddN0_cccc(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CCC(OP1,NIB3);
+ GET_DST(OP1,NIB2);
+ GET_CNT(OP1,NIB1);
+ CPW(cpustate, RDMEM_W(cpustate, cpustate->RW(dst)), RDMEM_W(cpustate, cpustate->RW(src)));
+ switch (cc) {
+ case 0: if (CC0) SET_Z; else CLR_Z; break;
+ case 1: if (CC1) SET_Z; else CLR_Z; break;
+ case 2: if (CC2) SET_Z; else CLR_Z; break;
+ case 3: if (CC3) SET_Z; else CLR_Z; break;
+ case 4: if (CC4) SET_Z; else CLR_Z; break;
+ case 5: if (CC5) SET_Z; else CLR_Z; break;
+ case 6: if (CC6) SET_Z; else CLR_Z; break;
+ case 7: if (CC7) SET_Z; else CLR_Z; break;
+ case 8: if (CC8) SET_Z; else CLR_Z; break;
+ case 9: if (CC9) SET_Z; else CLR_Z; break;
+ case 10: if (CCA) SET_Z; else CLR_Z; break;
+ case 11: if (CCB) SET_Z; else CLR_Z; break;
+ case 12: if (CCC) SET_Z; else CLR_Z; break;
+ case 13: if (CCD) SET_Z; else CLR_Z; break;
+ case 14: if (CCE) SET_Z; else CLR_Z; break;
+ case 15: if (CCF) SET_Z; else CLR_Z; break;
+ }
+ cpustate->RW(dst) += 2;
+ cpustate->RW(src) += 2;
+ if (--cpustate->RW(cnt)) { CLR_V; if (!(cpustate->fcw & F_Z)) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ cpd rd,@rs,rr,cc
+ flags: CZSV--
+ ******************************************/
+static void ZBB_ssN0_1000_0000_rrrr_dddd_cccc(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CCC(OP1,NIB3);
+ GET_DST(OP1,NIB2);
+ GET_CNT(OP1,NIB1);
+ CPW(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, cpustate->RW(src)));
+ switch (cc) {
+ case 0: if (CC0) SET_Z; else CLR_Z; break;
+ case 1: if (CC1) SET_Z; else CLR_Z; break;
+ case 2: if (CC2) SET_Z; else CLR_Z; break;
+ case 3: if (CC3) SET_Z; else CLR_Z; break;
+ case 4: if (CC4) SET_Z; else CLR_Z; break;
+ case 5: if (CC5) SET_Z; else CLR_Z; break;
+ case 6: if (CC6) SET_Z; else CLR_Z; break;
+ case 7: if (CC7) SET_Z; else CLR_Z; break;
+ case 8: if (CC8) SET_Z; else CLR_Z; break;
+ case 9: if (CC9) SET_Z; else CLR_Z; break;
+ case 10: if (CCA) SET_Z; else CLR_Z; break;
+ case 11: if (CCB) SET_Z; else CLR_Z; break;
+ case 12: if (CCC) SET_Z; else CLR_Z; break;
+ case 13: if (CCD) SET_Z; else CLR_Z; break;
+ case 14: if (CCE) SET_Z; else CLR_Z; break;
+ case 15: if (CCF) SET_Z; else CLR_Z; break;
+ }
+ cpustate->RW(src) -= 2;
+ if (--cpustate->RW(cnt)) CLR_V; else SET_V;
+}
+
+/******************************************
+ ldd @rs,@rd,rr
+ lddr @rs,@rd,rr
+ flags: ---V--
+ ******************************************/
+static void ZBB_ssN0_1001_0000_rrrr_ddN0_x000(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CNT(OP1,NIB1);
+ GET_DST(OP1,NIB2);
+ GET_CCC(OP1,NIB3);
+ WRMEM_W(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, cpustate->RW(src)));
+ cpustate->RW(dst) -= 2;
+ cpustate->RW(src) -= 2;
+ if (--cpustate->RW(cnt)) { CLR_V; if (cc == 0) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ cpsd @rd,@rs,rr,cc
+ flags: CZSV--
+ ******************************************/
+static void ZBB_ssN0_1010_0000_rrrr_ddN0_cccc(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CCC(OP1,NIB3);
+ GET_DST(OP1,NIB2);
+ GET_CNT(OP1,NIB1);
+ CPW(cpustate, RDMEM_W(cpustate, cpustate->RW(dst)), RDMEM_W(cpustate, cpustate->RW(src)));
+ switch (cc) {
+ case 0: if (CC0) SET_Z; else CLR_Z; break;
+ case 1: if (CC1) SET_Z; else CLR_Z; break;
+ case 2: if (CC2) SET_Z; else CLR_Z; break;
+ case 3: if (CC3) SET_Z; else CLR_Z; break;
+ case 4: if (CC4) SET_Z; else CLR_Z; break;
+ case 5: if (CC5) SET_Z; else CLR_Z; break;
+ case 6: if (CC6) SET_Z; else CLR_Z; break;
+ case 7: if (CC7) SET_Z; else CLR_Z; break;
+ case 8: if (CC8) SET_Z; else CLR_Z; break;
+ case 9: if (CC9) SET_Z; else CLR_Z; break;
+ case 10: if (CCA) SET_Z; else CLR_Z; break;
+ case 11: if (CCB) SET_Z; else CLR_Z; break;
+ case 12: if (CCC) SET_Z; else CLR_Z; break;
+ case 13: if (CCD) SET_Z; else CLR_Z; break;
+ case 14: if (CCE) SET_Z; else CLR_Z; break;
+ case 15: if (CCF) SET_Z; else CLR_Z; break;
+ }
+ cpustate->RW(dst) -= 2;
+ cpustate->RW(src) -= 2;
+ if (--cpustate->RW(cnt)) CLR_V; else SET_V;
+}
+
+/******************************************
+ cpdr rd,@rs,rr,cc
+ flags: CZSV--
+ ******************************************/
+static void ZBB_ssN0_1100_0000_rrrr_dddd_cccc(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CCC(OP1,NIB3);
+ GET_DST(OP1,NIB2);
+ GET_CNT(OP1,NIB1);
+ CPW(cpustate, cpustate->RW(dst), RDMEM_W(cpustate, cpustate->RW(src)));
+ switch (cc) {
+ case 0: if (CC0) SET_Z; else CLR_Z; break;
+ case 1: if (CC1) SET_Z; else CLR_Z; break;
+ case 2: if (CC2) SET_Z; else CLR_Z; break;
+ case 3: if (CC3) SET_Z; else CLR_Z; break;
+ case 4: if (CC4) SET_Z; else CLR_Z; break;
+ case 5: if (CC5) SET_Z; else CLR_Z; break;
+ case 6: if (CC6) SET_Z; else CLR_Z; break;
+ case 7: if (CC7) SET_Z; else CLR_Z; break;
+ case 8: if (CC8) SET_Z; else CLR_Z; break;
+ case 9: if (CC9) SET_Z; else CLR_Z; break;
+ case 10: if (CCA) SET_Z; else CLR_Z; break;
+ case 11: if (CCB) SET_Z; else CLR_Z; break;
+ case 12: if (CCC) SET_Z; else CLR_Z; break;
+ case 13: if (CCD) SET_Z; else CLR_Z; break;
+ case 14: if (CCE) SET_Z; else CLR_Z; break;
+ case 15: if (CCF) SET_Z; else CLR_Z; break;
+ }
+ cpustate->RW(src) -= 2;
+ if (--cpustate->RW(cnt)) { CLR_V; if (!(cpustate->fcw & F_Z)) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ cpsdr @rd,@rs,rr,cc
+ flags: CZSV--
+ ******************************************/
+static void ZBB_ssN0_1110_0000_rrrr_ddN0_cccc(z8000_state *cpustate)
+{
+ GET_SRC(OP0,NIB2);
+ GET_CCC(OP1,NIB3);
+ GET_DST(OP1,NIB2);
+ GET_CNT(OP1,NIB1);
+ CPW(cpustate, RDMEM_W(cpustate, cpustate->RW(dst)), RDMEM_W(cpustate, cpustate->RW(src)));
+ switch (cc) {
+ case 0: if (CC0) SET_Z; else CLR_Z; break;
+ case 1: if (CC1) SET_Z; else CLR_Z; break;
+ case 2: if (CC2) SET_Z; else CLR_Z; break;
+ case 3: if (CC3) SET_Z; else CLR_Z; break;
+ case 4: if (CC4) SET_Z; else CLR_Z; break;
+ case 5: if (CC5) SET_Z; else CLR_Z; break;
+ case 6: if (CC6) SET_Z; else CLR_Z; break;
+ case 7: if (CC7) SET_Z; else CLR_Z; break;
+ case 8: if (CC8) SET_Z; else CLR_Z; break;
+ case 9: if (CC9) SET_Z; else CLR_Z; break;
+ case 10: if (CCA) SET_Z; else CLR_Z; break;
+ case 11: if (CCB) SET_Z; else CLR_Z; break;
+ case 12: if (CCC) SET_Z; else CLR_Z; break;
+ case 13: if (CCD) SET_Z; else CLR_Z; break;
+ case 14: if (CCE) SET_Z; else CLR_Z; break;
+ case 15: if (CCF) SET_Z; else CLR_Z; break;
+ }
+ cpustate->RW(dst) -= 2;
+ cpustate->RW(src) -= 2;
+ if (--cpustate->RW(cnt)) { CLR_V; if (!(cpustate->fcw & F_Z)) cpustate->pc -= 4; } else SET_V;
+}
+
+/******************************************
+ rrdb rbb,rba
+ flags: -Z----
+ ******************************************/
+static void ZBC_aaaa_bbbb(z8000_state *cpustate)
+{
+ UINT8 b = cpustate->op[0] & 15;
+ UINT8 a = (cpustate->op[0] >> 4) & 15;
+ UINT8 tmp = cpustate->RB(b);
+ cpustate->RB(a) = (cpustate->RB(a) >> 4) | (cpustate->RB(b) << 4);
+ cpustate->RB(b) = (cpustate->RB(b) & 0xf0) | (tmp & 0x0f);
+ if (cpustate->RB(b)) CLR_Z; else SET_Z;
+}
+
+/******************************************
+ ldk rd,imm4
+ flags: ------
+ ******************************************/
+static void ZBD_dddd_imm4(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB2);
+ GET_IMM4(OP0,NIB3);
+ cpustate->RW(dst) = imm4;
+}
+
+/******************************************
+ rldb rbb,rba
+ flags: -Z----
+ ******************************************/
+static void ZBE_aaaa_bbbb(z8000_state *cpustate)
+{
+ UINT8 b = cpustate->op[0] & 15;
+ UINT8 a = (cpustate->op[0] >> 4) & 15;
+ UINT8 tmp = cpustate->RB(a);
+ cpustate->RB(a) = (cpustate->RB(a) << 4) | (cpustate->RB(b) & 0x0f);
+ cpustate->RB(b) = (cpustate->RB(b) & 0xf0) | (tmp >> 4);
+ if (cpustate->RB(b)) CLR_Z; else SET_Z;
+}
+
+/******************************************
+ rsvdbf
+ flags: ------
+ ******************************************/
+static void ZBF_imm8(z8000_state *cpustate)
+{
+ GET_IMM8(0);
+ LOG(("Z8K '%s' %04x: rsvdbf $%02x\n", cpustate->device->tag(), cpustate->pc, imm8));
+ if (cpustate->fcw & F_EPU) {
+ /* Z8001 EPU code goes here */
+ (void)imm8;
+ }
+ (void)imm8;
+}
+
+/******************************************
+ ldb rbd,imm8
+ flags: ------
+ ******************************************/
+static void ZC_dddd_imm8(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB1);
+ GET_IMM8(0);
+ cpustate->RB(dst) = imm8;
+}
+
+/******************************************
+ calr dsp12
+ flags: ------
+ ******************************************/
+static void ZD_dsp12(z8000_state *cpustate)
+{
+ INT16 dsp12 = cpustate->op[0] & 0xfff;
+ PUSHW(cpustate, SP, cpustate->pc);
+ dsp12 = (dsp12 & 2048) ? 4096 -2 * (dsp12 & 2047) : -2 * (dsp12 & 2047);
+ cpustate->pc += dsp12;
+}
+
+/******************************************
+ jr cc,dsp8
+ flags: ------
+ ******************************************/
+static void ZE_cccc_dsp8(z8000_state *cpustate)
+{
+ GET_DSP8;
+ GET_CCC(OP0,NIB1);
+ switch (cc) {
+ case 0: if (CC0) cpustate->pc += dsp8 * 2; break;
+ case 1: if (CC1) cpustate->pc += dsp8 * 2; break;
+ case 2: if (CC2) cpustate->pc += dsp8 * 2; break;
+ case 3: if (CC3) cpustate->pc += dsp8 * 2; break;
+ case 4: if (CC4) cpustate->pc += dsp8 * 2; break;
+ case 5: if (CC5) cpustate->pc += dsp8 * 2; break;
+ case 6: if (CC6) cpustate->pc += dsp8 * 2; break;
+ case 7: if (CC7) cpustate->pc += dsp8 * 2; break;
+ case 8: if (CC8) cpustate->pc += dsp8 * 2; break;
+ case 9: if (CC9) cpustate->pc += dsp8 * 2; break;
+ case 10: if (CCA) cpustate->pc += dsp8 * 2; break;
+ case 11: if (CCB) cpustate->pc += dsp8 * 2; break;
+ case 12: if (CCC) cpustate->pc += dsp8 * 2; break;
+ case 13: if (CCD) cpustate->pc += dsp8 * 2; break;
+ case 14: if (CCE) cpustate->pc += dsp8 * 2; break;
+ case 15: if (CCF) cpustate->pc += dsp8 * 2; break;
+ }
+}
+
+/******************************************
+ dbjnz rbd,dsp7
+ flags: ------
+ ******************************************/
+static void ZF_dddd_0dsp7(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB1);
+ GET_DSP7;
+ cpustate->RB(dst) -= 1;
+ if (cpustate->RB(dst)) {
+ cpustate->pc = cpustate->pc - 2 * dsp7;
+ }
+}
+
+/******************************************
+ djnz rd,dsp7
+ flags: ------
+ ******************************************/
+static void ZF_dddd_1dsp7(z8000_state *cpustate)
+{
+ GET_DST(OP0,NIB1);
+ GET_DSP7;
+ cpustate->RW(dst) -= 1;
+ if (cpustate->RW(dst)) {
+ cpustate->pc = cpustate->pc - 2 * dsp7;
+ }
+}
+
+
diff --git a/trunk/src/emu/cpu/z8000/z8000tbl.c b/trunk/src/emu/cpu/z8000/z8000tbl.c
new file mode 100644
index 00000000000..2f8f611f7a8
--- /dev/null
+++ b/trunk/src/emu/cpu/z8000/z8000tbl.c
@@ -0,0 +1,1152 @@
+/*****************************************************************************
+ *
+ * z8000tbl.c
+ * Portable Z8000(2) emulator
+ * Opcode table (including mnemonics) and initialization
+ *
+ * Copyright Juergen Buchmueller, all rights reserved.
+ * Bug fixes and MSB_FIRST compliance Ernesto Corvi.
+ *
+ * - 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.
+ *
+ *****************************************************************************/
+
+static const Z8000_init table[] = {
+{0x0000,0x000f, 1,2, 7,Z00_0000_dddd_imm8, "addb %rb3,%#b3", 0},
+{0x0010,0x00ff, 1,1, 7,Z00_ssN0_dddd, "addb %rb3,@%rw2", 0},
+{0x0100,0x010f, 1,2, 7,Z01_0000_dddd_imm16, "add %rw3,%#w1", 0},
+{0x0110,0x01ff, 1,1, 7,Z01_ssN0_dddd, "add %rw3,@%rw2", 0},
+{0x0200,0x020f, 1,2, 7,Z02_0000_dddd_imm8, "subb %rb3,%#b3", 0},
+{0x0210,0x02ff, 1,1, 7,Z02_ssN0_dddd, "subb %rb3,@%rw2", 0},
+{0x0300,0x030f, 1,2, 7,Z03_0000_dddd_imm16, "sub %rw3,%#w1", 0},
+{0x0310,0x03ff, 1,1, 7,Z03_ssN0_dddd, "sub %rw3,@%rw2", 0},
+{0x0400,0x040f, 1,2, 7,Z04_0000_dddd_imm8, "orb %rb3,%#b3", 0},
+{0x0410,0x04ff, 1,1, 7,Z04_ssN0_dddd, "orb %rb3,@%rw2", 0},
+{0x0500,0x050f, 1,2, 7,Z05_0000_dddd_imm16, "or %rw3,%#w1", 0},
+{0x0510,0x05ff, 1,1, 7,Z05_ssN0_dddd, "or %rw3,@%rw2", 0},
+{0x0600,0x060f, 1,2, 7,Z06_0000_dddd_imm8, "andb %rb3,%#b3", 0},
+{0x0610,0x06ff, 1,1, 7,Z06_ssN0_dddd, "andb %rb3,@%rw2", 0},
+{0x0700,0x070f, 1,2, 7,Z07_0000_dddd_imm16, "and %rw3,%#w1", 0},
+{0x0710,0x07ff, 1,1, 7,Z07_ssN0_dddd, "and %rw3,@%rw2", 0},
+{0x0800,0x080f, 1,2, 7,Z08_0000_dddd_imm8, "xorb %rb3,%#b3", 0},
+{0x0810,0x08ff, 1,1, 7,Z08_ssN0_dddd, "xorb %rb3,@%rw2", 0},
+{0x0900,0x090f, 1,2, 7,Z09_0000_dddd_imm16, "xor %rw3,%#w1", 0},
+{0x0910,0x09ff, 1,1, 7,Z09_ssN0_dddd, "xor %rw3,@%rw2", 0},
+{0x0a00,0x0a0f, 1,2, 7,Z0A_0000_dddd_imm8, "cpb %rb3,%#b3", 0},
+{0x0a10,0x0aff, 1,1, 7,Z0A_ssN0_dddd, "cpb %rb3,@%rw2", 0},
+{0x0b00,0x0b0f, 1,2, 7,Z0B_0000_dddd_imm16, "cp %rw3,%#w1", 0},
+{0x0b10,0x0bff, 1,1, 7,Z0B_ssN0_dddd, "cp %rw3,@%rw2", 0},
+{0x0c10,0x0cf0,16,1, 12,Z0C_ddN0_0000, "comb @%rw2", 0},
+{0x0c11,0x0cf1,16,2, 11,Z0C_ddN0_0001_imm8, "cpb @%rw2,%#b3", 0},
+{0x0c12,0x0cf2,16,1, 12,Z0C_ddN0_0010, "negb @%rw2", 0},
+{0x0c14,0x0cf4,16,1, 8,Z0C_ddN0_0100, "testb @%rw2", 0},
+{0x0c15,0x0cf5,16,2, 7,Z0C_ddN0_0101_imm8, "ldb @%rw2,%#b3", 0},
+{0x0c16,0x0cf6,16,1, 11,Z0C_ddN0_0110, "tsetb @%rw2", 0},
+{0x0c18,0x0cf8,16,1, 8,Z0C_ddN0_1000, "clrb @%rw2", 0},
+{0x0d10,0x0df0,16,1, 12,Z0D_ddN0_0000, "com @%rw2", 0},
+{0x0d11,0x0df1,16,2, 11,Z0D_ddN0_0001_imm16, "cp @%rw2,%#w1", 0},
+{0x0d12,0x0df2,16,1, 12,Z0D_ddN0_0010, "neg @%rw2", 0},
+{0x0d14,0x0df4,16,1, 8,Z0D_ddN0_0100, "test @%rw2", 0},
+{0x0d15,0x0df5,16,2, 11,Z0D_ddN0_0101_imm16, "ld @%rw2,%#w1", 0}, /* fix cycles ld IR,IM */
+{0x0d16,0x0df6,16,1, 11,Z0D_ddN0_0110, "tset @%rw2", 0},
+{0x0d18,0x0df8,16,1, 8,Z0D_ddN0_1000, "clr @%rw2", 0},
+{0x0d19,0x0df9,16,2, 12,Z0D_ddN0_1001_imm16, "push @%rw2,%#w1", 0},
+{0x0e00,0x0eff, 1,1, 10,Z0E_imm8, "ext0e %#b1", 0},
+{0x0f00,0x0fff, 1,1, 10,Z0F_imm8, "ext0f %#b1", 0},
+{0x1000,0x100f, 1,3, 14,Z10_0000_dddd_imm32, "cpl %rl3,%#l1", 0},
+{0x1010,0x10ff, 1,1, 14,Z10_ssN0_dddd, "cpl %rl3,@%rw2", 0},
+{0x1111,0x11ff, 1,1, 20,Z11_ddN0_ssN0, "pushl @%rw2,@%rw3", 0},
+{0x1200,0x120f, 1,3, 14,Z12_0000_dddd_imm32, "subl %rl3,%#l1", 0},
+{0x1210,0x12ff, 1,1, 14,Z12_ssN0_dddd, "subl %rl3,@%rw2", 0},
+{0x1311,0x13ff, 1,1, 13,Z13_ddN0_ssN0, "push @%rw2,@%rw3", 0},
+{0x1400,0x140f, 1,3, 11,Z14_0000_dddd_imm32, "ldl %rl3,%#l1", 0},
+{0x1410,0x14ff, 1,1, 11,Z14_ssN0_dddd, "ldl %rl3,@%rw2", 0},
+{0x1511,0x15ff, 1,1, 19,Z15_ssN0_ddN0, "popl @%rw3,@%rw2", 0},
+{0x1600,0x160f, 1,3, 14,Z16_0000_dddd_imm32, "addl %rl3,%#l1", 0},
+{0x1610,0x16ff, 1,1, 14,Z16_ssN0_dddd, "addl %rl3,@%rw2", 0},
+{0x1711,0x17ff, 1,1, 12,Z17_ssN0_ddN0, "pop @%rw3,@%rw2", 0},
+{0x1810,0x18ff, 1,1,282,Z18_ssN0_dddd, "multl %rq3,@%rw2", 0},
+{0x1900,0x190f, 1,2, 70,Z19_0000_dddd_imm16, "mult %rl3,%#w1", 0},
+{0x1910,0x19ff, 1,1, 70,Z19_ssN0_dddd, "mult %rl3,@%rw2", 0},
+{0x1a00,0x1a0f, 1,3,744,Z1A_0000_dddd_imm32, "divl %rq3,%#l1", 0},
+{0x1a10,0x1aff, 1,1,744,Z1A_ssN0_dddd, "divl %rq3,@%rw2", 0},
+{0x1b00,0x1b0f, 1,2,107,Z1B_0000_dddd_imm16, "div %rl3,%#w1", 0},
+{0x1b10,0x1bff, 1,1,107,Z1B_ssN0_dddd, "div %rl3,@%rw2", 0},
+{0x1c11,0x1cf1,16,2, 11,Z1C_ssN0_0001_0000_dddd_0000_nmin1, "ldm %rw5,@%rw2,#%n", 0},
+{0x1c18,0x1cf8,16,1, 13,Z1C_ddN0_1000, "testl @%rw2", 0},
+{0x1c19,0x1cf9,16,2, 11,Z1C_ddN0_1001_0000_ssss_0000_nmin1, "ldm @%rw2,%rw5,#%n", 0},
+{0x1d10,0x1dff, 1,1, 11,Z1D_ddN0_ssss, "ldl @%rw2,%rl3", 0},
+{0x1e10,0x1eff, 1,1, 10,Z1E_ddN0_cccc, "jp %c3,@%rl2", 0},
+{0x1f10,0x1ff0,16,1, 10,Z1F_ddN0_0000, "call %rw2", DASMFLAG_STEP_OVER},
+{0x2010,0x20ff, 1,1, 7,Z20_ssN0_dddd, "ldb %rb3,@%rw2", 0},
+{0x2100,0x210f, 1,2, 7,Z21_0000_dddd_imm16, "ld %rw3,%#w1", 0},
+{0x2110,0x21ff, 1,1, 7,Z21_ssN0_dddd, "ld %rw3,@%rw2", 0},
+{0x2200,0x220f, 1,2, 10,Z22_0000_ssss_0000_dddd_0000_0000, "resb %rb5,%rw3", 0},
+{0x2210,0x22ff, 1,1, 11,Z22_ddN0_imm4, "resb @%rw3,%3", 0},
+{0x2300,0x230f, 1,2, 10,Z23_0000_ssss_0000_dddd_0000_0000, "res %rw5,%rw3", 0},
+{0x2310,0x23ff, 1,1, 11,Z23_ddN0_imm4, "res @%rw3,%3", 0},
+{0x2400,0x240f, 1,2, 10,Z24_0000_ssss_0000_dddd_0000_0000, "setb %rb5,%rw3", 0},
+{0x2410,0x24ff, 1,1, 11,Z24_ddN0_imm4, "setb @%rw3,%3", 0},
+{0x2500,0x250f, 1,2, 10,Z25_0000_ssss_0000_dddd_0000_0000, "set %rw5,%rw3", 0},
+{0x2510,0x25ff, 1,1, 11,Z25_ddN0_imm4, "set @%rw3,%3", 0},
+{0x2600,0x260f, 1,2, 10,Z26_0000_ssss_0000_dddd_0000_0000, "bitb %rb5,%rw3", 0},
+{0x2610,0x26ff, 1,1, 8,Z26_ddN0_imm4, "bitb @%rw3,%3", 0},
+{0x2700,0x270f, 1,2, 10,Z27_0000_ssss_0000_dddd_0000_0000, "bit %rw5,%rw3", 0},
+{0x2710,0x27ff, 1,1, 8,Z27_ddN0_imm4, "bit @%rw2,%3", 0},
+{0x2810,0x28ff, 1,1, 11,Z28_ddN0_imm4m1, "incb @%rw2,%+3", 0},
+{0x2910,0x29ff, 1,1, 11,Z29_ddN0_imm4m1, "inc @%rw2,%+3", 0},
+{0x2a10,0x2aff, 1,1, 11,Z2A_ddN0_imm4m1, "decb @%rw2,%+3", 0},
+{0x2b10,0x2bff, 1,1, 11,Z2B_ddN0_imm4m1, "dec @%rw2,%+3", 0},
+{0x2c10,0x2cff, 1,1, 12,Z2C_ssN0_dddd, "exb %rb3,@%rw2", 0},
+{0x2d10,0x2dff, 1,1, 12,Z2D_ssN0_dddd, "ex %rw3,@%rw2", 0},
+{0x2e10,0x2eff, 1,1, 8,Z2E_ddN0_ssss, "ldb @%rw2,%rb3", 0},
+{0x2f10,0x2fff, 1,1, 8,Z2F_ddN0_ssss, "ld @%rw2,%rw3", 0},
+{0x3000,0x300f, 1,2, 14,Z30_0000_dddd_dsp16, "ldrb %rb3,%p1", 0},
+{0x3010,0x30ff, 1,2, 14,Z30_ssN0_dddd_imm16, "ldb %rb3,%rw2(%#w1)", 0},
+{0x3100,0x310f, 1,2, 14,Z31_0000_dddd_dsp16, "ldr %rw3,%p1", 0},
+{0x3110,0x31ff, 1,2, 14,Z31_ssN0_dddd_imm16, "ld %rw3,%rw2(%#w1)", 0},
+{0x3200,0x320f, 1,2, 14,Z32_0000_ssss_dsp16, "ldrb %p1,%rb3", 0},
+{0x3210,0x32ff, 1,2, 14,Z32_ddN0_ssss_imm16, "ldb %rw2(%#w1),%rb3", 0},
+{0x3300,0x330f, 1,2, 14,Z33_0000_ssss_dsp16, "ldr %p1,%rw3", 0},
+{0x3310,0x33ff, 1,2, 14,Z33_ddN0_ssss_imm16, "ld %rw2(%#w1),%rw3", 0},
+{0x3400,0x340f, 1,2, 15,Z34_0000_dddd_dsp16, "ldar p%rw3,%p1", 0},
+{0x3410,0x34ff, 1,2, 15,Z34_ssN0_dddd_imm16, "lda p%rw3,%rw2(%#w1)", 0},
+{0x3500,0x350f, 1,2, 17,Z35_0000_dddd_dsp16, "ldrl %rl3,%p1", 0},
+{0x3510,0x35ff, 1,2, 17,Z35_ssN0_dddd_imm16, "ldl %rl3,%rw2(%#w1)", 0},
+{0x3600,0x3600, 1,1, 2,Z36_0000_0000, "bpt", 0},
+{0x3601,0x36ff, 1,1, 10,Z36_imm8, "rsvd36", 0},
+{0x3700,0x370f, 1,2, 17,Z37_0000_ssss_dsp16, "ldrl %p1,%rl3", 0},
+{0x3710,0x37ff, 1,2, 17,Z37_ddN0_ssss_imm16, "ldl %rw2(%#w1),%rl3", 0},
+{0x3800,0x38ff, 1,1, 10,Z38_imm8, "rsvd38", 0},
+{0x3910,0x39f0,16,1, 12,Z39_ssN0_0000, "ldps @%rw2", 0},
+{0x3a00,0x3af0,16,2, 21,Z3A_ssss_0000_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3a01,0x3af1,16,2, 21,Z3A_ssss_0001_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3a02,0x3af2,16,2, 21,Z3A_ssss_0010_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3a03,0x3af3,16,2, 21,Z3A_ssss_0011_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3a04,0x3af4,16,2, 10,Z3A_dddd_0100_imm16, "%R %rb2,%#w1", 0},
+{0x3a05,0x3af5,16,2, 10,Z3A_dddd_0101_imm16, "%R %rb2,%#w1", 0},
+{0x3a06,0x3af6,16,2, 12,Z3A_ssss_0110_imm16, "%R %#w1,%rb2", 0},
+{0x3a07,0x3af7,16,2, 12,Z3A_ssss_0111_imm16, "%R %#w1,%rb2", 0},
+{0x3a08,0x3af8,16,2, 21,Z3A_ssss_1000_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3a09,0x3af9,16,2, 21,Z3A_ssss_1001_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3a0a,0x3afa,16,2, 21,Z3A_ssss_1010_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3a0b,0x3afb,16,2, 21,Z3A_ssss_1011_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3b00,0x3bf0,16,2, 21,Z3B_ssss_0000_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3b01,0x3bf1,16,2, 21,Z3B_ssss_0001_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3b02,0x3bf2,16,2, 21,Z3B_ssss_0010_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3b03,0x3bf3,16,2, 21,Z3B_ssss_0011_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3b04,0x3bf4,16,2, 12,Z3B_dddd_0100_imm16, "%R %rw2,%#w1", 0},
+{0x3b05,0x3bf5,16,2, 12,Z3B_dddd_0101_imm16, "%R %rw2,%#w1", 0},
+{0x3b06,0x3bf6,16,2, 12,Z3B_ssss_0110_imm16, "%R %#w1,%rw2", 0},
+{0x3b07,0x3bf7,16,2, 12,Z3B_ssss_0111_imm16, "%R %#w1,%rw2", 0},
+{0x3b08,0x3bf8,16,2, 21,Z3B_ssss_1000_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3b09,0x3bf9,16,2, 21,Z3B_ssss_1001_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3b0a,0x3bfa,16,2, 21,Z3B_ssss_1010_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rb5", 0},
+{0x3b0b,0x3bfb,16,2, 21,Z3B_ssss_1011_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rb5", 0},
+{0x3c00,0x3cff, 1,1, 10,Z3C_ssss_dddd, "inb %rb3,@%rw2", 0},
+{0x3d00,0x3dff, 1,1, 10,Z3D_ssss_dddd, "in %rw3,@%rw2", 0},
+{0x3e00,0x3eff, 1,1, 12,Z3E_dddd_ssss, "outb @%rw2,%rb3", 0},
+{0x3f00,0x3fff, 1,1, 12,Z3F_dddd_ssss, "out @%rw2,%rw3", 0},
+{0x4000,0x400f, 1,2, 9,Z40_0000_dddd_addr, "addb %rb3,%a1", 0},
+{0x4010,0x40ff, 1,2, 10,Z40_ssN0_dddd_addr, "addb %rb3,%a1(%rw2)", 0},
+{0x4100,0x410f, 1,2, 9,Z41_0000_dddd_addr, "add %rw3,%a1", 0},
+{0x4110,0x41ff, 1,2, 10,Z41_ssN0_dddd_addr, "add %rw3,%a1(%rw2)", 0},
+{0x4200,0x420f, 1,2, 9,Z42_0000_dddd_addr, "subb %rb3,%a1", 0},
+{0x4210,0x42ff, 1,2, 10,Z42_ssN0_dddd_addr, "subb %rb3,%a1(%rw2)", 0},
+{0x4300,0x430f, 1,2, 9,Z43_0000_dddd_addr, "sub %rw3,%a1", 0},
+{0x4310,0x43ff, 1,2, 10,Z43_ssN0_dddd_addr, "sub %rw3,%a1(%rw2)", 0},
+{0x4400,0x440f, 1,2, 9,Z44_0000_dddd_addr, "orb %rb3,%a1", 0},
+{0x4410,0x44ff, 1,2, 10,Z44_ssN0_dddd_addr, "orb %rb3,%a1(%rw2)", 0},
+{0x4500,0x450f, 1,2, 9,Z45_0000_dddd_addr, "or %rw3,%a1", 0},
+{0x4510,0x45ff, 1,2, 10,Z45_ssN0_dddd_addr, "or %rw3,%a1(%rw2)", 0},
+{0x4600,0x460f, 1,2, 9,Z46_0000_dddd_addr, "andb %rb3,%a1", 0},
+{0x4610,0x46ff, 1,2, 10,Z46_ssN0_dddd_addr, "andb %rb3,%a1(%rw2)", 0},
+{0x4700,0x470f, 1,2, 9,Z47_0000_dddd_addr, "and %rw3,%a1", 0},
+{0x4710,0x47ff, 1,2, 10,Z47_ssN0_dddd_addr, "and %rw3,%a1(%rw2)", 0},
+{0x4800,0x480f, 1,2, 9,Z48_0000_dddd_addr, "xorb %rb3,%a1", 0},
+{0x4810,0x48ff, 1,2, 10,Z48_ssN0_dddd_addr, "xorb %rb3,%a1(%rw2)", 0},
+{0x4900,0x490f, 1,2, 9,Z49_0000_dddd_addr, "xor %rw3,%a1", 0},
+{0x4910,0x49ff, 1,2, 10,Z49_ssN0_dddd_addr, "xor %rw3,%a1(%rw2)", 0},
+{0x4a00,0x4a0f, 1,2, 9,Z4A_0000_dddd_addr, "cpb %rb3,%a1", 0},
+{0x4a10,0x4aff, 1,2, 10,Z4A_ssN0_dddd_addr, "cpb %rb3,%a1(%rw2)", 0},
+{0x4b00,0x4b0f, 1,2, 9,Z4B_0000_dddd_addr, "cp %rw3,%a1", 0},
+{0x4b10,0x4bff, 1,2, 10,Z4B_ssN0_dddd_addr, "cp %rw3,%a1(%rw2)", 0},
+{0x4c00,0x4c00, 1,2, 15,Z4C_0000_0000_addr, "comb %a1", 0},
+{0x4c01,0x4c01, 1,3, 14,Z4C_0000_0001_addr_imm8, "cpb %a1,%#b3", 0},
+{0x4c02,0x4c02, 1,2, 15,Z4C_0000_0010_addr, "negb %a1", 0},
+{0x4c04,0x4c04, 1,2, 11,Z4C_0000_0100_addr, "testb %a1", 0},
+{0x4c05,0x4c05, 1,3, 14,Z4C_0000_0101_addr_imm8, "ldb %a1,%#b3", 0},
+{0x4c06,0x4c06, 1,2, 14,Z4C_0000_0110_addr, "tsetb %a1", 0},
+{0x4c08,0x4c08, 1,2, 11,Z4C_0000_1000_addr, "clrb %a1", 0},
+{0x4c10,0x4cf0,16,2, 16,Z4C_ddN0_0000_addr, "comb %a1(%rw2)", 0},
+{0x4c11,0x4cf1,16,3, 15,Z4C_ddN0_0001_addr_imm8, "cpb %a1(%rw2),%#b3", 0},
+{0x4c12,0x4cf2,16,2, 16,Z4C_ddN0_0010_addr, "negb %a1(%rw2)", 0},
+{0x4c14,0x4cf4,16,2, 12,Z4C_ddN0_0100_addr, "testb %a1(%rw2)", 0},
+{0x4c15,0x4cf5,16,3, 15,Z4C_ddN0_0101_addr_imm8, "ldb %a1(%rw2),%#b3", 0},
+{0x4c16,0x4cf6,16,2, 15,Z4C_ddN0_0110_addr, "tsetb %a1(%rw2)", 0},
+{0x4c18,0x4cf8,16,2, 12,Z4C_ddN0_1000_addr, "clrb %a1(%rw2)", 0},
+{0x4d00,0x4d00, 1,2, 15,Z4D_0000_0000_addr, "com %a1", 0},
+{0x4d01,0x4d01, 1,3, 14,Z4D_0000_0001_addr_imm16, "cp %a1,%#w2", 0},
+{0x4d02,0x4d02, 1,2, 15,Z4D_0000_0010_addr, "neg %a1", 0},
+{0x4d04,0x4d04, 1,2, 11,Z4D_0000_0100_addr, "test %a1", 0},
+{0x4d05,0x4d05, 1,3, 14,Z4D_0000_0101_addr_imm16, "ld %a1,%#w2", 0},
+{0x4d06,0x4d06, 1,2, 14,Z4D_0000_0110_addr, "tset %a1", 0},
+{0x4d08,0x4d08, 1,2, 11,Z4D_0000_1000_addr, "clr %a1", 0},
+{0x4d10,0x4df0,16,2, 16,Z4D_ddN0_0000_addr, "com %a1(%rw2)", 0},
+{0x4d11,0x4df1,16,3, 15,Z4D_ddN0_0001_addr_imm16, "cp %a1(%rw2),%#w2", 0},
+{0x4d12,0x4df2,16,2, 16,Z4D_ddN0_0010_addr, "neg %a1(%rw2)", 0},
+{0x4d14,0x4df4,16,2, 12,Z4D_ddN0_0100_addr, "test %a1(%rw2)", 0},
+{0x4d15,0x4df5,16,3, 15,Z4D_ddN0_0101_addr_imm16, "ld %a1(%rw2),%#w2", 0},
+{0x4d16,0x4df6,16,2, 15,Z4D_ddN0_0110_addr, "tset %a1(%rw2)", 0},
+{0x4d18,0x4df8,16,2, 12,Z4D_ddN0_1000_addr, "clr %a1(%rw2)", 0},
+{0x4e11,0x4ef0,16,2, 12,Z4E_ddN0_ssN0_addr, "ldb %a1(%rw2),%rb3", 0},
+{0x5000,0x500f, 1,2, 15,Z50_0000_dddd_addr, "cpl %rl3,%a1", 0},
+{0x5010,0x50ff, 1,2, 16,Z50_ssN0_dddd_addr, "cpl %rl3,%a1(%rw2)", 0},
+{0x5110,0x51f0,16,2, 21,Z51_ddN0_0000_addr, "pushl @%rw2,%a1", 0},
+{0x5111,0x51f1,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x5112,0x51f2,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x5113,0x51f3,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x5114,0x51f4,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x5115,0x51f5,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x5116,0x51f6,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x5117,0x51f7,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x5118,0x51f8,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x5119,0x51f9,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x511a,0x51fa,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x511b,0x51fb,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x511c,0x51fc,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x511d,0x51fd,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x511e,0x51fe,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x511f,0x51ff,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x5200,0x520f, 1,2, 15,Z52_0000_dddd_addr, "subl %rl3,%a1", 0},
+{0x5210,0x52ff, 1,2, 16,Z52_ssN0_dddd_addr, "subl %rl3,%a1(%rw2)", 0},
+{0x5310,0x53f0,16,2, 14,Z53_ddN0_0000_addr, "push @%rw2,%a1", 0},
+{0x5311,0x53f1,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x5312,0x53f2,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x5313,0x53f3,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x5314,0x53f4,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x5315,0x53f5,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x5316,0x53f6,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x5317,0x53f7,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x5318,0x53f8,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x5319,0x53f9,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x531a,0x53fa,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x531b,0x53fb,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x531c,0x53fc,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x531d,0x53fd,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x531e,0x53fe,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x531f,0x53ff,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x5400,0x540f, 1,2, 12,Z54_0000_dddd_addr, "ldl %rl3,%a1", 0},
+{0x5410,0x54ff, 1,2, 13,Z54_ssN0_dddd_addr, "ldl %rl3,%a1(%rw2)", 0},
+{0x5510,0x55f0,16,2, 23,Z55_ssN0_0000_addr, "popl %a1,@%rw2", 0},
+{0x5511,0x55f1,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x5512,0x55f2,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x5513,0x55f3,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x5514,0x55f4,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x5515,0x55f5,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x5516,0x55f6,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x5517,0x55f7,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x5518,0x55f8,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x5519,0x55f9,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x551a,0x55fa,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x551b,0x55fb,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x551c,0x55fc,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x551d,0x55fd,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x551e,0x55fe,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x551f,0x55ff,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x5600,0x560f, 1,2, 15,Z56_0000_dddd_addr, "addl %rl3,%a1", 0},
+{0x5610,0x56ff, 1,2, 16,Z56_ssN0_dddd_addr, "addl %rl3,%a1(%rw2)", 0},
+{0x5710,0x57f0,16,2, 16,Z57_ssN0_0000_addr, "pop %a1,@%rw2", 0},
+{0x5711,0x57f1,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x5712,0x57f2,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x5713,0x57f3,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x5714,0x57f4,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x5715,0x57f5,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x5716,0x57f6,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x5717,0x57f7,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x5718,0x57f8,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x5719,0x57f9,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x571a,0x57fa,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x571b,0x57fb,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x571c,0x57fc,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x571d,0x57fd,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x571e,0x57fe,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x571f,0x57ff,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x5800,0x580f, 1,2,283,Z58_0000_dddd_addr, "multl %rq3,%a1", 0},
+{0x5810,0x58ff, 1,2,284,Z58_ssN0_dddd_addr, "multl %rq3,%a1(%rw2)", 0},
+{0x5900,0x590f, 1,2, 71,Z59_0000_dddd_addr, "mult %rl3,%a1", 0},
+{0x5910,0x59ff, 1,2, 72,Z59_ssN0_dddd_addr, "mult %rl3,%a1(%rw2)", 0},
+{0x5a00,0x5a0f, 1,2,745,Z5A_0000_dddd_addr, "divl %rq3,%a1", 0},
+{0x5a10,0x5aff, 1,2,746,Z5A_ssN0_dddd_addr, "divl %rq3,%a1(%rw2)", 0},
+{0x5b00,0x5b0f, 1,2,108,Z5B_0000_dddd_addr, "div %rl3,%a1", 0},
+{0x5b10,0x5bff, 1,2,109,Z5B_ssN0_dddd_addr, "div %rl3,%a1(%rw2)", 0},
+{0x5c01,0x5c01, 1,3, 14,Z5C_0000_0001_0000_dddd_0000_nmin1_addr, "ldm %rw5,%a2,#%n", 0},
+{0x5c08,0x5c08, 1,2, 16,Z5C_0000_1000_addr, "testl %a1", 0},
+{0x5c09,0x5c09, 1,3, 14,Z5C_0000_1001_0000_ssss_0000_nmin1_addr, "ldm %a2,%rw5,#%n", 0},
+{0x5c11,0x5cf1,16,3, 15,Z5C_ssN0_0001_0000_dddd_0000_nmin1_addr, "ldm %rw5,%a2(%rw2),#%n", 0},
+{0x5c18,0x5cf8,16,2, 17,Z5C_ddN0_1000_addr, "testl %a1(%rw2)", 0},
+{0x5c19,0x5cf9,16,3, 15,Z5C_ddN0_1001_0000_ssN0_0000_nmin1_addr, "ldm %a2(%rw2),%rw5,#%n", 0},
+{0x5d00,0x5d0f, 1,2, 15,Z5D_0000_ssss_addr, "ldl %a1,%rl3", 0},
+{0x5d10,0x5dff, 1,2, 14,Z5D_ddN0_ssss_addr, "ldl %a1(%rw2),%rl3", 0},
+{0x5e00,0x5e0f, 1,2, 7,Z5E_0000_cccc_addr, "jp %c3,%a1", 0},
+{0x5e10,0x5eff, 1,2, 8,Z5E_ddN0_cccc_addr, "jp %c3,%a1(%rw2)", 0},
+{0x5f00,0x5f00, 1,2, 12,Z5F_0000_0000_addr, "call %a1", DASMFLAG_STEP_OVER},
+{0x5f10,0x5ff0,16,2, 13,Z5F_ddN0_0000_addr, "call %a1(%rw2)", DASMFLAG_STEP_OVER},
+{0x6000,0x600f, 1,2, 9,Z60_0000_dddd_addr, "ldb %rb3,%a1", 0},
+{0x6010,0x60ff, 1,2, 10,Z60_ssN0_dddd_addr, "ldb %rb3,%a1(%rw2)", 0},
+{0x6100,0x610f, 1,2, 9,Z61_0000_dddd_addr, "ld %rw3,%a1", 0},
+{0x6110,0x61ff, 1,2, 10,Z61_ssN0_dddd_addr, "ld %rw3,%a1(%rw2)", 0},
+{0x6200,0x620f, 1,2, 13,Z62_0000_imm4_addr, "resb %a1,%3", 0},
+{0x6210,0x62ff, 1,2, 14,Z62_ddN0_imm4_addr, "resb %a1(%rw2),%3", 0},
+{0x6300,0x630f, 1,2, 13,Z63_0000_imm4_addr, "res %a1,%3", 0},
+{0x6310,0x63ff, 1,2, 14,Z63_ddN0_imm4_addr, "res %a1(%rw2),%3", 0},
+{0x6400,0x640f, 1,2, 13,Z64_0000_imm4_addr, "setb %a1,%3", 0},
+{0x6410,0x64ff, 1,2, 14,Z64_ddN0_imm4_addr, "setb %a1(%rw2),%3", 0},
+{0x6500,0x650f, 1,2, 13,Z65_0000_imm4_addr, "set %a1,%3", 0},
+{0x6510,0x65ff, 1,2, 14,Z65_ddN0_imm4_addr, "set %a1(%rw2),%3", 0},
+{0x6600,0x660f, 1,2, 10,Z66_0000_imm4_addr, "bitb %a1,%3", 0},
+{0x6610,0x66ff, 1,2, 11,Z66_ddN0_imm4_addr, "bitb %a1(%rw2),%3", 0},
+{0x6700,0x670f, 1,2, 10,Z67_0000_imm4_addr, "bit %a1,%3", 0},
+{0x6710,0x67ff, 1,2, 11,Z67_ddN0_imm4_addr, "bit %a1(%rw2),%3", 0},
+{0x6800,0x680f, 1,2, 13,Z68_0000_imm4m1_addr, "incb %a1,%+3", 0},
+{0x6810,0x68ff, 1,2, 14,Z68_ddN0_imm4m1_addr, "incb %a1(%rw2),%+3", 0},
+{0x6900,0x690f, 1,2, 13,Z69_0000_imm4m1_addr, "inc %a1,%+3", 0},
+{0x6910,0x69ff, 1,2, 14,Z69_ddN0_imm4m1_addr, "inc %a1(%rw2),%+3", 0},
+{0x6a00,0x6a0f, 1,2, 13,Z6A_0000_imm4m1_addr, "decb %a1,%+3", 0},
+{0x6a10,0x6aff, 1,2, 14,Z6A_ddN0_imm4m1_addr, "decb %a1(%rw2),%+3", 0},
+{0x6b00,0x6b0f, 1,2, 13,Z6B_0000_imm4m1_addr, "dec %a1,%+3", 0},
+{0x6b10,0x6bff, 1,2, 14,Z6B_ddN0_imm4m1_addr, "dec %a1(%rw2),%+3", 0},
+{0x6c00,0x6c0f, 1,2, 15,Z6C_0000_dddd_addr, "exb %rb3,%a1", 0},
+{0x6c10,0x6cff, 1,2, 16,Z6C_ssN0_dddd_addr, "exb %rb3,%a1(%rw2)", 0},
+{0x6d00,0x6d0f, 1,2, 15,Z6D_0000_dddd_addr, "ex %rw3,%a1", 0},
+{0x6d10,0x6dff, 1,2, 16,Z6D_ssN0_dddd_addr, "ex %rw3,%a1(%rw2)", 0},
+{0x6e00,0x6e0f, 1,2, 11,Z6E_0000_ssss_addr, "ldb %a1,%rb3", 0},
+{0x6e10,0x6eff, 1,2, 11,Z6E_ddN0_ssss_addr, "ldb %a1(%rw2),%rb3", 0},
+{0x6f00,0x6f0f, 1,2, 11,Z6F_0000_ssss_addr, "ld %a1,%rw3", 0},
+{0x6f10,0x6fff, 1,2, 12,Z6F_ddN0_ssss_addr, "ld %a1(%rw2),%rw3", 0},
+{0x7010,0x70ff, 1,2, 14,Z70_ssN0_dddd_0000_xxxx_0000_0000, "ldb %rb3,%rw2(%rw5)", 0},
+{0x7110,0x71ff, 1,2, 14,Z71_ssN0_dddd_0000_xxxx_0000_0000, "ld %rw3,%rw2(%rw5)", 0},
+{0x7210,0x72ff, 1,2, 14,Z72_ddN0_ssss_0000_xxxx_0000_0000, "ldb %rw2(%rw5),%rb3", 0},
+{0x7310,0x73ff, 1,2, 14,Z73_ddN0_ssss_0000_xxxx_0000_0000, "ld %rw2(%rw5),%rw3", 0},
+{0x7410,0x74ff, 1,2, 15,Z74_ssN0_dddd_0000_xxxx_0000_0000, "lda p%rw3,%rw2(%rw5)", 0},
+{0x7510,0x75ff, 1,2, 17,Z75_ssN0_dddd_0000_xxxx_0000_0000, "ldl %rl3,%rw2(%rw5)", 0},
+{0x7600,0x760f, 1,2, 12,Z76_0000_dddd_addr, "lda p%rw3,%a1", 0},
+{0x7610,0x76ff, 1,2, 13,Z76_ssN0_dddd_addr, "lda p%rw3,%a1(%rw2)", 0},
+{0x7710,0x77ff, 1,2, 17,Z77_ddN0_ssss_0000_xxxx_0000_0000, "ldl %rw2(%rw5),%rl3", 0},
+{0x7800,0x78ff, 1,1, 10,Z78_imm8, "rsvd78", 0},
+{0x7900,0x7900, 1,2, 16,Z79_0000_0000_addr, "ldps %a1", 0},
+{0x7910,0x79f0,16,2, 17,Z79_ssN0_0000_addr, "ldps %a1(%rw2)", 0},
+{0x7a00,0x7a00, 1,1, 8,Z7A_0000_0000, "halt", DASMFLAG_STEP_OVER},
+{0x7b00,0x7b00, 1,1, 13,Z7B_0000_0000, "iret", DASMFLAG_STEP_OUT},
+{0x7b08,0x7b08, 1,1, 5,Z7B_0000_1000, "mset", 0},
+{0x7b09,0x7b09, 1,1, 5,Z7B_0000_1001, "mres", 0},
+{0x7b0a,0x7b0a, 1,1, 7,Z7B_0000_1010, "mbit", 0},
+{0x7b0d,0x7bfd,16,1, 12,Z7B_dddd_1101, "mreq %rw2", 0},
+{0x7c00,0x7c03, 1,1, 7,Z7C_0000_00ii, "di %i3", 0},
+{0x7c04,0x7c07, 1,1, 7,Z7C_0000_01ii, "ei %i3", 0},
+{0x7d00,0x7df0,16,1, 7,Z7D_dddd_0ccc, "ldctl %rw2,ctrl0", 0},
+{0x7d01,0x7df1,16,1, 7,Z7D_dddd_0ccc, "ldctl %rw2,ctrl1", 0},
+{0x7d02,0x7df2,16,1, 7,Z7D_dddd_0ccc, "ldctl %rw2,fcw", 0},
+{0x7d03,0x7df3,16,1, 7,Z7D_dddd_0ccc, "ldctl %rw2,refresh", 0},
+{0x7d04,0x7df4,16,1, 7,Z7D_dddd_0ccc, "ldctl %rw2,ctrl4", 0},
+{0x7d05,0x7df5,16,1, 7,Z7D_dddd_0ccc, "ldctl %rw2,psap", 0},
+{0x7d06,0x7df6,16,1, 7,Z7D_dddd_0ccc, "ldctl %rw2,ctrl6", 0},
+{0x7d07,0x7df7,16,1, 7,Z7D_dddd_0ccc, "ldctl %rw2,nsp", 0},
+{0x7d08,0x7df8,16,1, 7,Z7D_ssss_1ccc, "ldctl ctrl0,%rw2", 0},
+{0x7d09,0x7df9,16,1, 7,Z7D_ssss_1ccc, "ldctl ctrl1,%rw2", 0},
+{0x7d0a,0x7dfa,16,1, 7,Z7D_ssss_1ccc, "ldctl fcw,%rw2", 0},
+{0x7d0b,0x7dfb,16,1, 7,Z7D_ssss_1ccc, "ldctl refresh,%rw2", 0},
+{0x7d0c,0x7dfc,16,1, 7,Z7D_ssss_1ccc, "ldctl ctrl4,%rw2", 0},
+{0x7d0d,0x7dfd,16,1, 7,Z7D_ssss_1ccc, "ldctl psap,%rw2", 0},
+{0x7d0e,0x7dfe,16,1, 7,Z7D_ssss_1ccc, "ldctl ctrl6,%rw2", 0},
+{0x7d0f,0x7dff,16,1, 7,Z7D_ssss_1ccc, "ldctl nsp,%rw2", 0},
+{0x7e00,0x7eff, 1,1, 10,Z7E_imm8, "rsvd7e %#b1", 0},
+{0x7f00,0x7fff, 1,1, 33,Z7F_imm8, "sc %#b1", 0},
+{0x8000,0x80ff, 1,1, 4,Z80_ssss_dddd, "addb %rb3,%rb2", 0},
+{0x8100,0x81ff, 1,1, 4,Z81_ssss_dddd, "add %rw3,%rw2", 0},
+{0x8200,0x82ff, 1,1, 4,Z82_ssss_dddd, "subb %rb3,%rb2", 0},
+{0x8300,0x83ff, 1,1, 4,Z83_ssss_dddd, "sub %rw3,%rw2", 0},
+{0x8400,0x84ff, 1,1, 4,Z84_ssss_dddd, "orb %rb3,%rb2", 0},
+{0x8500,0x85ff, 1,1, 4,Z85_ssss_dddd, "or %rw3,%rw2", 0},
+{0x8600,0x86ff, 1,1, 4,Z86_ssss_dddd, "andb %rb3,%rb2", 0},
+{0x8700,0x87ff, 1,1, 4,Z87_ssss_dddd, "and %rw3,%rw2", 0},
+{0x8800,0x88ff, 1,1, 4,Z88_ssss_dddd, "xorb %rb3,%rb2", 0},
+{0x8900,0x89ff, 1,1, 4,Z89_ssss_dddd, "xor %rw3,%rw2", 0},
+{0x8a00,0x8aff, 1,1, 4,Z8A_ssss_dddd, "cpb %rb3,%rb2", 0},
+{0x8b00,0x8bff, 1,1, 4,Z8B_ssss_dddd, "cp %rw3,%rw2", 0},
+{0x8c00,0x8cf0,16,1, 7,Z8C_dddd_0000, "comb %rb2", 0},
+{0x8c02,0x8cf2,16,1, 7,Z8C_dddd_0010, "negb %rb2", 0},
+{0x8c04,0x8cf4,16,1, 7,Z8C_dddd_0100, "testb %rb2", 0},
+{0x8c06,0x8cf6,16,1, 7,Z8C_dddd_0110, "tsetb %rb2", 0},
+{0x8c08,0x8cf8,16,1, 7,Z8C_dddd_1000, "clrb %rb2", 0},
+{0x8d00,0x8df0,16,1, 7,Z8D_dddd_0000, "com %rw2", 0},
+{0x8d01,0x8df1,16,1, 7,Z8D_imm4_0001, "setflg %f2", 0},
+{0x8d02,0x8df2,16,1, 7,Z8D_dddd_0010, "neg %rw2", 0},
+{0x8d03,0x8df3,16,1, 7,Z8D_imm4_0011, "resflg %f2", 0},
+{0x8d04,0x8df4,16,1, 7,Z8D_dddd_0100, "test %rw2", 0},
+{0x8d05,0x8df5,16,1, 7,Z8D_imm4_0101, "comflg %f2", 0},
+{0x8d06,0x8df6,16,1, 7,Z8D_dddd_0110, "tset %rw2", 0},
+{0x8d07,0x8d07, 1,1, 7,Z8D_0000_0111, "nop", 0},
+{0x8d08,0x8df8,16,1, 7,Z8D_dddd_1000, "clr %rw2", 0},
+{0x8e00,0x8eff, 1,1, 10,Z8E_imm8, "ext8e %#b1", 0},
+{0x8f00,0x8fff, 1,1, 10,Z8F_imm8, "ext8f %#b1", 0},
+{0x9000,0x90ff, 1,1, 8,Z90_ssss_dddd, "cpl %rl3,%rl2", 0},
+{0x9110,0x91ff, 1,1, 12,Z91_ddN0_ssss, "pushl @%rw2,%rl3", 0},
+{0x9200,0x92ff, 1,1, 8,Z92_ssss_dddd, "subl %rl3,%rl2", 0},
+{0x9310,0x93ff, 1,1, 9,Z93_ddN0_ssss, "push @%rw2,%rw3", 0},
+{0x9400,0x94ff, 1,1, 5,Z94_ssss_dddd, "ldl %rl3,%rl2", 0},
+{0x9510,0x95ff, 1,1, 12,Z95_ssN0_dddd, "popl %rl3,@%rw2", 0},
+{0x9600,0x96ff, 1,1, 8,Z96_ssss_dddd, "addl %rl3,%rl2", 0},
+{0x9710,0x97ff, 1,1, 8,Z97_ssN0_dddd, "pop %rw3,@%rw2", 0},
+{0x9800,0x98ff, 1,1,282,Z98_ssss_dddd, "multl %rq3,%rl2", 0},
+{0x9900,0x99ff, 1,1, 70,Z99_ssss_dddd, "mult %rl3,%rw2", 0},
+{0x9a00,0x9aff, 1,1,744,Z9A_ssss_dddd, "divl %rq3,%rl2", 0},
+{0x9b00,0x9bff, 1,1,107,Z9B_ssss_dddd, "div %rl3,%rw2", 0},
+{0x9c08,0x9cf8,16,1, 13,Z9C_dddd_1000, "testl %rl2", 0},
+{0x9d00,0x9dff, 1,1, 10,Z9D_imm8, "rsvd9d", 0},
+{0x9e00,0x9e0f, 1,1, 10,Z9E_0000_cccc, "ret %c3", DASMFLAG_STEP_OUT},
+{0x9f00,0x9fff, 1,1, 10,Z9F_imm8, "rsvd9f", 0},
+{0xa000,0xa0ff, 1,1, 3,ZA0_ssss_dddd, "ldb %rb3,%rb2", 0},
+{0xa100,0xa1ff, 1,1, 3,ZA1_ssss_dddd, "ld %rw3,%rw2", 0},
+{0xa200,0xa2ff, 1,1, 4,ZA2_dddd_imm4, "resb %rb2,%3", 0},
+{0xa300,0xa3ff, 1,1, 4,ZA3_dddd_imm4, "res %rw2,%3", 0},
+{0xa400,0xa4ff, 1,1, 4,ZA4_dddd_imm4, "setb %rb2,%3", 0},
+{0xa500,0xa5ff, 1,1, 4,ZA5_dddd_imm4, "set %rw2,%3", 0},
+{0xa600,0xa6ff, 1,1, 4,ZA6_dddd_imm4, "bitb %rb2,%3", 0},
+{0xa700,0xa7ff, 1,1, 4,ZA7_dddd_imm4, "bit %rw2,%3", 0},
+{0xa800,0xa8ff, 1,1, 4,ZA8_dddd_imm4m1, "incb %rb2,%+3", 0},
+{0xa900,0xa9ff, 1,1, 4,ZA9_dddd_imm4m1, "inc %rw2,%+3", 0},
+{0xaa00,0xaaff, 1,1, 4,ZAA_dddd_imm4m1, "decb %rb2,%+3", 0},
+{0xab00,0xabff, 1,1, 4,ZAB_dddd_imm4m1, "dec %rw2,%+3", 0},
+{0xac00,0xacff, 1,1, 6,ZAC_ssss_dddd, "exb %rb3,%rb2", 0},
+{0xad00,0xadff, 1,1, 6,ZAD_ssss_dddd, "ex %rw3,%rw2", 0},
+{0xae00,0xaeff, 1,1, 5,ZAE_dddd_cccc, "tccb %c3,%rb2", 0},
+{0xaf00,0xafff, 1,1, 5,ZAF_dddd_cccc, "tcc %c3,%rw2", 0},
+{0xb000,0xb0f0,16,1, 5,ZB0_dddd_0000, "dab %rb2", 0},
+{0xb100,0xb1f0,16,1, 11,ZB1_dddd_0000, "extsb %rw2", 0},
+{0xb107,0xb1f7,16,1, 11,ZB1_dddd_0111, "extsl %rq2", 0},
+{0xb10a,0xb1fa,16,1, 11,ZB1_dddd_1010, "exts %rl2", 0},
+{0xb200,0xb2f0,16,1, 6,ZB2_dddd_00I0, "rlb %rb2,%?3", 0},
+{0xb201,0xb2f1,16,2, 13,ZB2_dddd_0001_imm8, "s%*lb %rb2,%$3", 0},
+{0xb202,0xb2f2,16,1, 6,ZB2_dddd_00I0, "rlb %rb2,%?3", 0},
+{0xb203,0xb2f3,16,2, 15,ZB2_dddd_0011_0000_ssss_0000_0000, "sdlb %rb2,%rw5", 0},
+{0xb204,0xb2f4,16,1, 6,ZB2_dddd_01I0, "rrb %rb2,%?3", 0},
+{0xb206,0xb2f6,16,1, 6,ZB2_dddd_01I0, "rrb %rb2,%?3", 0},
+{0xb208,0xb2f8,16,1, 9,ZB2_dddd_10I0, "rlcb %rb2,%?3", 0},
+{0xb209,0xb2f9,16,2, 13,ZB2_dddd_1001_imm8, "s%*ab %rb2,%$3", 0},
+{0xb20a,0xb2fa,16,1, 9,ZB2_dddd_10I0, "rlcb %rb2,%?3", 0},
+{0xb20b,0xb2fb,16,2, 15,ZB2_dddd_1011_0000_ssss_0000_0000, "sdab %rb2,%rw5", 0},
+{0xb20c,0xb2fc,16,1, 9,ZB2_dddd_11I0, "rrcb %rb2,%?3", 0},
+{0xb20e,0xb2fe,16,1, 9,ZB2_dddd_11I0, "rrcb %rb2,%?3", 0},
+{0xb300,0xb3f0,16,1, 6,ZB3_dddd_00I0, "rl %rw2,%?3", 0},
+{0xb301,0xb3f1,16,2, 13,ZB3_dddd_0001_imm8, "s%*l %rw2,%$3", 0},
+{0xb302,0xb3f2,16,1, 6,ZB3_dddd_00I0, "rl %rw2,%?3", 0},
+{0xb303,0xb3f3,16,2, 15,ZB3_dddd_0011_0000_ssss_0000_0000, "sdl %rw2,%rw5", 0},
+{0xb304,0xb3f4,16,1, 6,ZB3_dddd_01I0, "rr %rw2,%?3", 0},
+{0xb305,0xb3f5,16,2, 13,ZB3_dddd_0101_imm8, "s%*ll %rl2,%$3", 0},
+{0xb306,0xb3f6,16,1, 6,ZB3_dddd_01I0, "rr %rw2,%?3", 0},
+{0xb307,0xb3f7,16,2, 15,ZB3_dddd_0111_0000_ssss_0000_0000, "sdll %rl2,%rw5", 0},
+{0xb308,0xb3f8,16,1, 6,ZB3_dddd_10I0, "rlc %rw2,%?3", 0},
+{0xb309,0xb3f9,16,2, 13,ZB3_dddd_1001_imm8, "s%*a %rw2,%$3", 0},
+{0xb30a,0xb3fa,16,1, 6,ZB3_dddd_10I0, "rlc %rw2,%?3", 0},
+{0xb30b,0xb3fb,16,2, 15,ZB3_dddd_1011_0000_ssss_0000_0000, "sda %rw2,%rw5", 0},
+{0xb30c,0xb3fc,16,1, 6,ZB3_dddd_11I0, "rrc %rw2,%?3", 0},
+{0xb30d,0xb3fd,16,2, 13,ZB3_dddd_1101_imm8, "s%*al %rl2,%$3", 0},
+{0xb30e,0xb3fe,16,1, 6,ZB3_dddd_11I0, "rrc %rw2,%?3", 0},
+{0xb30f,0xb3ff,16,2, 15,ZB3_dddd_1111_0000_ssss_0000_0000, "sdal %rl2,%rw5", 0},
+{0xb400,0xb4ff, 1,1, 5,ZB4_ssss_dddd, "adcb %rb3,%rb2", 0},
+{0xb500,0xb5ff, 1,1, 5,ZB5_ssss_dddd, "adc %rw3,%rw2", 0},
+{0xb600,0xb6ff, 1,1, 5,ZB6_ssss_dddd, "sbcb %rb3,%rb2", 0},
+{0xb700,0xb7ff, 1,1, 5,ZB7_ssss_dddd, "sbc %rw3,%rw2", 0},
+{0xb810,0xb8f0,16,2, 25,ZB8_ddN0_0000_0000_rrrr_ssN0_0000, "trib @%rw2,@%rw6,%rb5", 0},
+{0xb812,0xb8f2,16,2, 25,ZB8_ddN0_0010_0000_rrrr_ssN0_0000, "trtib @%rw2,@%rw6,%rb5", 0},
+{0xb814,0xb8f4,16,2, 25,ZB8_ddN0_0100_0000_rrrr_ssN0_0000, "trirb @%rw2,@%rw6,%rb5", 0},
+{0xb816,0xb8f6,16,2, 25,ZB8_ddN0_0110_0000_rrrr_ssN0_1110, "trtirb @%rw2,@%rw6,%rb5", 0},
+{0xb818,0xb8f8,16,2, 25,ZB8_ddN0_1000_0000_rrrr_ssN0_0000, "trdb @%rw2,@%rw6,%rb5", 0},
+{0xb81a,0xb8fa,16,2, 25,ZB8_ddN0_1010_0000_rrrr_ssN0_0000, "trtrb @%rw2,@%rw6,%rb5", 0},
+{0xb81c,0xb8fc,16,2, 25,ZB8_ddN0_1100_0000_rrrr_ssN0_0000, "trdrb @%rw2,@%rw6,%rb5", 0},
+{0xb81e,0xb8fe,16,2, 25,ZB8_ddN0_1110_0000_rrrr_ssN0_1110, "trtdrb @%rw2,@%rw6,%rb5", 0},
+{0xb900,0xb9ff,16,1, 10,ZB9_imm8, "rsvdb9", 0},
+{0xba10,0xbaf0,16,2, 11,ZBA_ssN0_0000_0000_rrrr_dddd_cccc, "cpib %rb6,@%rw2,%rw5,%c7", 0},
+{0xba11,0xbaf1,16,2, 11,ZBA_ssN0_0001_0000_rrrr_ddN0_x000, "ldirb @%rw6,@%rw2,%rw5", DASMFLAG_STEP_OVER},
+{0xba12,0xbaf2,16,2, 11,ZBA_ssN0_0010_0000_rrrr_ddN0_cccc, "cpsib @%rw6,@%rw2,%rw5,%c7", 0},
+{0xba14,0xbaf4,16,2, 11,ZBA_ssN0_0100_0000_rrrr_dddd_cccc, "cpirb %rb6,@%rw2,%rw5,%c7", DASMFLAG_STEP_OVER},
+{0xba16,0xbaf6,16,2, 11,ZBA_ssN0_0110_0000_rrrr_ddN0_cccc, "cpsirb @%rw6,@%rw2,%rw5,%c7", DASMFLAG_STEP_OVER},
+{0xba18,0xbaf8,16,2, 11,ZBA_ssN0_1000_0000_rrrr_dddd_cccc, "cpdb %rb6,@%rw2,%rw5,%c7", 0},
+{0xba19,0xbaf9,16,2, 11,ZBA_ssN0_1001_0000_rrrr_ddN0_x000, "lddrb @%rw2,@%rw6,%rw5", DASMFLAG_STEP_OVER},
+{0xba1a,0xbafa,16,2, 11,ZBA_ssN0_1010_0000_rrrr_ddN0_cccc, "cpsdb @%rw6,@%rw2,%rw5,%c7", 0},
+{0xba1c,0xbafc,16,2, 11,ZBA_ssN0_1100_0000_rrrr_dddd_cccc, "cpdrb %rb6,@%rw2,%rw5,%c7", DASMFLAG_STEP_OVER},
+{0xba1e,0xbafe,16,2, 11,ZBA_ssN0_1110_0000_rrrr_ddN0_cccc, "cpsdrb @%rw6,@%rw2,%rw5,%c7", DASMFLAG_STEP_OVER},
+{0xbb10,0xbbf0,16,2, 11,ZBB_ssN0_0000_0000_rrrr_dddd_cccc, "cpi %rw6,@%rw2,%rw5,%c7", 0},
+{0xbb11,0xbbf1,16,2, 11,ZBB_ssN0_0001_0000_rrrr_ddN0_x000, "ldir @%rw6,@%rw2,%rw5", DASMFLAG_STEP_OVER},
+{0xbb12,0xbbf2,16,2, 11,ZBB_ssN0_0010_0000_rrrr_ddN0_cccc, "cpsi @%rw6,@%rw2,%rw5,%c7", 0},
+{0xbb14,0xbbf4,16,2, 11,ZBB_ssN0_0100_0000_rrrr_dddd_cccc, "cpir %rw6,@%rw2,%rw5,%c7", DASMFLAG_STEP_OVER},
+{0xbb16,0xbbf6,16,2, 11,ZBB_ssN0_0110_0000_rrrr_ddN0_cccc, "cpsir @%rw6,@%rw2,%rw5,%c7", DASMFLAG_STEP_OVER},
+{0xbb18,0xbbf8,16,2, 11,ZBB_ssN0_1000_0000_rrrr_dddd_cccc, "cpd %rw6,@%rw2,%rw5,%c7", 0},
+{0xbb19,0xbbf9,16,2, 11,ZBB_ssN0_1001_0000_rrrr_ddN0_x000, "lddr @%rw2,@%rw6,%rw5", DASMFLAG_STEP_OVER},
+{0xbb1a,0xbbfa,16,2, 11,ZBB_ssN0_1010_0000_rrrr_ddN0_cccc, "cpsd @%rw6,@%rw2,%rw5,%c7", 0},
+{0xbb1c,0xbbfc,16,2, 11,ZBB_ssN0_1100_0000_rrrr_dddd_cccc, "cpdr %rw6,@%rw2,%rw5,%c7", DASMFLAG_STEP_OVER},
+{0xbb1e,0xbbfe,16,2, 11,ZBB_ssN0_1110_0000_rrrr_ddN0_cccc, "cpsdr @%rw6,@%rw2,%rw5,%c7", DASMFLAG_STEP_OVER},
+{0xbc00,0xbcff, 1,1, 9,ZBC_aaaa_bbbb, "rrdb %rb3,%rb2", 0},
+{0xbd00,0xbdff, 1,1, 5,ZBD_dddd_imm4, "ldk %rw2,%3", 0},
+{0xbe00,0xbeff, 1,1, 9,ZBE_aaaa_bbbb, "rldb %rb3,%rb2", 0},
+{0xbf00,0xbfff, 1,1, 10,ZBF_imm8, "rsvdbf", 0},
+{0xc000,0xcfff, 1,1, 5,ZC_dddd_imm8, "ldb %rb1,%#b1", 0},
+{0xd000,0xdfff, 1,1, 10,ZD_dsp12, "calr %d2", DASMFLAG_STEP_OVER},
+{0xe000,0xefff, 1,1, 6,ZE_cccc_dsp8, "jr %c1,%d1", 0},
+{0xf000,0xf07f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xf100,0xf17f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xf200,0xf27f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xf300,0xf37f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xf400,0xf47f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xf500,0xf57f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xf600,0xf67f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xf700,0xf77f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xf800,0xf87f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xf900,0xf97f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xfa00,0xfa7f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xfb00,0xfb7f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xfc00,0xfc7f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xfd00,0xfd7f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xfe00,0xfe7f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xff00,0xff7f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xf080,0xf0ff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xf180,0xf1ff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xf280,0xf2ff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xf380,0xf3ff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xf480,0xf4ff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xf580,0xf5ff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xf680,0xf6ff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xf780,0xf7ff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xf880,0xf8ff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xf980,0xf9ff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xfa80,0xfaff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xfb80,0xfbff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xfc80,0xfcff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xfd80,0xfdff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xfe80,0xfeff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xff80,0xffff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0, 0, 0,0, 0,NULL, NULL, 0}
+};
+
+/*
+opcodes in segmented mode
+*/
+
+static const Z8000_init seg_table[] = {
+{0x0000,0x000f, 1,2, 7,Z00_0000_dddd_imm8, "addb %rb3,%#b3", 0},
+{0x0010,0x00ff, 1,1, 7,Z00_ssN0_dddd, "addb %rb3,@%rw2", 0},
+{0x0100,0x010f, 1,2, 7,Z01_0000_dddd_imm16, "add %rw3,%#w1", 0},
+{0x0110,0x01ff, 1,1, 7,Z01_ssN0_dddd, "add %rw3,@%rw2", 0},
+{0x0200,0x020f, 1,2, 7,Z02_0000_dddd_imm8, "subb %rb3,%#b3", 0},
+{0x0210,0x02ff, 1,1, 7,Z02_ssN0_dddd, "subb %rb3,@%rw2", 0},
+{0x0300,0x030f, 1,2, 7,Z03_0000_dddd_imm16, "sub %rw3,%#w1", 0},
+{0x0310,0x03ff, 1,1, 7,Z03_ssN0_dddd, "sub %rw3,@%rw2", 0},
+{0x0400,0x040f, 1,2, 7,Z04_0000_dddd_imm8, "orb %rb3,%#b3", 0},
+{0x0410,0x04ff, 1,1, 7,Z04_ssN0_dddd, "orb %rb3,@%rw2", 0},
+{0x0500,0x050f, 1,2, 7,Z05_0000_dddd_imm16, "or %rw3,%#w1", 0},
+{0x0510,0x05ff, 1,1, 7,Z05_ssN0_dddd, "or %rw3,@%rw2", 0},
+{0x0600,0x060f, 1,2, 7,Z06_0000_dddd_imm8, "andb %rb3,%#b3", 0},
+{0x0610,0x06ff, 1,1, 7,Z06_ssN0_dddd, "andb %rb3,@%rw2", 0},
+{0x0700,0x070f, 1,2, 7,Z07_0000_dddd_imm16, "and %rw3,%#w1", 0},
+{0x0710,0x07ff, 1,1, 7,Z07_ssN0_dddd, "and %rw3,@%rw2", 0},
+{0x0800,0x080f, 1,2, 7,Z08_0000_dddd_imm8, "xorb %rb3,%#b3", 0},
+{0x0810,0x08ff, 1,1, 7,Z08_ssN0_dddd, "xorb %rb3,@%rw2", 0},
+{0x0900,0x090f, 1,2, 7,Z09_0000_dddd_imm16, "xor %rw3,%#w1", 0},
+{0x0910,0x09ff, 1,1, 7,Z09_ssN0_dddd, "xor %rw3,@%rw2", 0},
+{0x0a00,0x0a0f, 1,2, 7,Z0A_0000_dddd_imm8, "cpb %rb3,%#b3", 0},
+{0x0a10,0x0aff, 1,1, 7,Z0A_ssN0_dddd, "cpb %rb3,@%rw2", 0},
+{0x0b00,0x0b0f, 1,2, 7,Z0B_0000_dddd_imm16, "cp %rw3,%#w1", 0},
+{0x0b10,0x0bff, 1,1, 7,Z0B_ssN0_dddd, "cp %rw3,@%rw2", 0},
+{0x0c10,0x0cf0,16,1, 12,Z0C_ddN0_0000, "comb @%rw2", 0},
+{0x0c11,0x0cf1,16,2, 11,Z0C_ddN0_0001_imm8, "cpb @%rw2,%#b3", 0},
+{0x0c12,0x0cf2,16,1, 12,Z0C_ddN0_0010, "negb @%rw2", 0},
+{0x0c14,0x0cf4,16,1, 8,Z0C_ddN0_0100, "testb @%rw2", 0},
+{0x0c15,0x0cf5,16,2, 7,Z0C_ddN0_0101_imm8, "ldb @%rw2,%#b3", 0},
+{0x0c16,0x0cf6,16,1, 11,Z0C_ddN0_0110, "tsetb @%rw2", 0},
+{0x0c18,0x0cf8,16,1, 8,Z0C_ddN0_1000, "clrb @%rw2", 0},
+{0x0d10,0x0df0,16,1, 12,Z0D_ddN0_0000, "com @%rw2", 0},
+{0x0d11,0x0df1,16,2, 11,Z0D_ddN0_0001_imm16, "cp @%rw2,%#w1", 0},
+{0x0d12,0x0df2,16,1, 12,Z0D_ddN0_0010, "neg @%rw2", 0},
+{0x0d14,0x0df4,16,1, 8,Z0D_ddN0_0100, "test @%rw2", 0},
+{0x0d15,0x0df5,16,2, 11,Z0D_ddN0_0101_imm16, "ld @%rw2,%#w1", 0}, /* fix cycles ld IR,IM */
+{0x0d16,0x0df6,16,1, 11,Z0D_ddN0_0110, "tset @%rw2", 0},
+{0x0d18,0x0df8,16,1, 8,Z0D_ddN0_1000, "clr @%rw2", 0},
+{0x0d19,0x0df9,16,2, 12,Z0D_ddN0_1001_imm16, "push @%rw2,%#w1", 0},
+{0x0e00,0x0eff, 1,1, 10,Z0E_imm8, "ext0e %#b1", 0},
+{0x0f00,0x0fff, 1,1, 10,Z0F_imm8, "ext0f %#b1", 0},
+{0x1000,0x100f, 1,3, 14,Z10_0000_dddd_imm32, "cpl %rl3,%#l1", 0},
+{0x1010,0x10ff, 1,1, 14,Z10_ssN0_dddd, "cpl %rl3,@%rw2", 0},
+{0x1111,0x11ff, 1,1, 20,Z11_ddN0_ssN0, "pushl @%rw2,@%rw3", 0},
+{0x1200,0x120f, 1,3, 14,Z12_0000_dddd_imm32, "subl %rl3,%#l1", 0},
+{0x1210,0x12ff, 1,1, 14,Z12_ssN0_dddd, "subl %rl3,@%rw2", 0},
+{0x1311,0x13ff, 1,1, 13,Z13_ddN0_ssN0, "push @%rw2,@%rw3", 0},
+{0x1400,0x140f, 1,3, 11,Z14_0000_dddd_imm32, "ldl %rl3,%#l1", 0},
+{0x1410,0x14ff, 1,1, 11,Z14_ssN0_dddd, "ldl %rl3,@%rw2", 0},
+{0x1511,0x15ff, 1,1, 19,Z15_ssN0_ddN0, "popl @%rw3,@%rw2", 0},
+{0x1600,0x160f, 1,3, 14,Z16_0000_dddd_imm32, "addl %rl3,%#l1", 0},
+{0x1610,0x16ff, 1,1, 14,Z16_ssN0_dddd, "addl %rl3,@%rw2", 0},
+{0x1711,0x17ff, 1,1, 12,Z17_ssN0_ddN0, "pop @%rw3,@%rw2", 0},
+{0x1810,0x18ff, 1,1,282,Z18_ssN0_dddd, "multl %rq3,@%rw2", 0},
+{0x1900,0x190f, 1,2, 70,Z19_0000_dddd_imm16, "mult %rl3,%#w1", 0},
+{0x1910,0x19ff, 1,1, 70,Z19_ssN0_dddd, "mult %rl3,@%rw2", 0},
+{0x1a00,0x1a0f, 1,3,744,Z1A_0000_dddd_imm32, "divl %rq3,%#l1", 0},
+{0x1a10,0x1aff, 1,1,744,Z1A_ssN0_dddd, "divl %rq3,@%rw2", 0},
+{0x1b00,0x1b0f, 1,2,107,Z1B_0000_dddd_imm16, "div %rl3,%#w1", 0},
+{0x1b10,0x1bff, 1,1,107,Z1B_ssN0_dddd, "div %rl3,@%rw2", 0},
+{0x1c11,0x1cf1,16,2, 11,Z1C_ssN0_0001_0000_dddd_0000_nmin1, "ldm %rw5,@%rw2,#%n", 0},
+{0x1c18,0x1cf8,16,1, 13,Z1C_ddN0_1000, "testl @%rw2", 0},
+{0x1c19,0x1cf9,16,2, 11,Z1C_ddN0_1001_0000_ssss_0000_nmin1, "ldm @%rw2,%rw5,#%n", 0},
+{0x1d10,0x1dff, 1,1, 11,Z1D_ddN0_ssss, "ldl @%rw2,%rl3", 0},
+{0x1e10,0x1eff, 1,1, 10,Z1E_ddN0_cccc, "jp %c3,@%rl2", 0},
+{0x1f10,0x1ff0,16,1, 10,Z1F_ddN0_0000, "call %rw2", DASMFLAG_STEP_OVER},
+{0x2010,0x20ff, 1,1, 7,Z20_ssN0_dddd_seg, "ldb %rb3,@%rw2", 0},
+{0x2100,0x210f, 1,2, 7,Z21_0000_dddd_imm16, "ld %rw3,%#w1", 0},
+{0x2110,0x21ff, 1,1, 7,Z21_ssN0_dddd, "ld %rw3,@%rw2", 0},
+{0x2200,0x220f, 1,2, 10,Z22_0000_ssss_0000_dddd_0000_0000, "resb %rb5,%rw3", 0},
+{0x2210,0x22ff, 1,1, 11,Z22_ddN0_imm4, "resb @%rw3,%3", 0},
+{0x2300,0x230f, 1,2, 10,Z23_0000_ssss_0000_dddd_0000_0000, "res %rw5,%rw3", 0},
+{0x2310,0x23ff, 1,1, 11,Z23_ddN0_imm4, "res @%rw3,%3", 0},
+{0x2400,0x240f, 1,2, 10,Z24_0000_ssss_0000_dddd_0000_0000, "setb %rb5,%rw3", 0},
+{0x2410,0x24ff, 1,1, 11,Z24_ddN0_imm4, "setb @%rw3,%3", 0},
+{0x2500,0x250f, 1,2, 10,Z25_0000_ssss_0000_dddd_0000_0000, "set %rw5,%rw3", 0},
+{0x2510,0x25ff, 1,1, 11,Z25_ddN0_imm4, "set @%rw3,%3", 0},
+{0x2600,0x260f, 1,2, 10,Z26_0000_ssss_0000_dddd_0000_0000, "bitb %rb5,%rw3", 0},
+{0x2610,0x26ff, 1,1, 8,Z26_ddN0_imm4, "bitb @%rw3,%3", 0},
+{0x2700,0x270f, 1,2, 10,Z27_0000_ssss_0000_dddd_0000_0000, "bit %rw5,%rw3", 0},
+{0x2710,0x27ff, 1,1, 8,Z27_ddN0_imm4, "bit @%rw2,%3", 0},
+{0x2810,0x28ff, 1,1, 11,Z28_ddN0_imm4m1, "incb @%rw2,%+3", 0},
+{0x2910,0x29ff, 1,1, 11,Z29_ddN0_imm4m1, "inc @%rw2,%+3", 0},
+{0x2a10,0x2aff, 1,1, 11,Z2A_ddN0_imm4m1, "decb @%rw2,%+3", 0},
+{0x2b10,0x2bff, 1,1, 11,Z2B_ddN0_imm4m1, "dec @%rw2,%+3", 0},
+{0x2c10,0x2cff, 1,1, 12,Z2C_ssN0_dddd, "exb %rb3,@%rw2", 0},
+{0x2d10,0x2dff, 1,1, 12,Z2D_ssN0_dddd, "ex %rw3,@%rw2", 0},
+{0x2e10,0x2eff, 1,1, 8,Z2E_ddN0_ssss, "ldb @%rw2,%rb3", 0},
+{0x2f10,0x2fff, 1,1, 8,Z2F_ddN0_ssss, "ld @%rw2,%rw3", 0},
+{0x3000,0x300f, 1,2, 14,Z30_0000_dddd_dsp16, "ldrb %rb3,%p1", 0},
+{0x3010,0x30ff, 1,2, 14,Z30_ssN0_dddd_imm16, "ldb %rb3,%rw2(%#w1)", 0},
+{0x3100,0x310f, 1,2, 14,Z31_0000_dddd_dsp16, "ldr %rw3,%p1", 0},
+{0x3110,0x31ff, 1,2, 14,Z31_ssN0_dddd_imm16, "ld %rw3,%rw2(%#w1)", 0},
+{0x3200,0x320f, 1,2, 14,Z32_0000_ssss_dsp16, "ldrb %p1,%rb3", 0},
+{0x3210,0x32ff, 1,2, 14,Z32_ddN0_ssss_imm16, "ldb %rw2(%#w1),%rb3", 0},
+{0x3300,0x330f, 1,2, 14,Z33_0000_ssss_dsp16, "ldr %p1,%rw3", 0},
+{0x3310,0x33ff, 1,2, 14,Z33_ddN0_ssss_imm16, "ld %rw2(%#w1),%rw3", 0},
+{0x3400,0x340f, 1,2, 15,Z34_0000_dddd_dsp16, "ldar p%rw3,%p1", 0},
+{0x3410,0x34ff, 1,2, 15,Z34_ssN0_dddd_imm16, "lda p%rw3,%rw2(%#w1)", 0},
+{0x3500,0x350f, 1,2, 17,Z35_0000_dddd_dsp16, "ldrl %rl3,%p1", 0},
+{0x3510,0x35ff, 1,2, 17,Z35_ssN0_dddd_imm16, "ldl %rl3,%rw2(%#w1)", 0},
+{0x3600,0x3600, 1,1, 2,Z36_0000_0000, "bpt", 0},
+{0x3601,0x36ff, 1,1, 10,Z36_imm8, "rsvd36", 0},
+{0x3700,0x370f, 1,2, 17,Z37_0000_ssss_dsp16, "ldrl %p1,%rl3", 0},
+{0x3710,0x37ff, 1,2, 17,Z37_ddN0_ssss_imm16, "ldl %rw2(%#w1),%rl3", 0},
+{0x3800,0x38ff, 1,1, 10,Z38_imm8, "rsvd38", 0},
+{0x3910,0x39f0,16,1, 12,Z39_ssN0_0000, "ldps @%rw2", 0},
+{0x3a00,0x3af0,16,2, 21,Z3A_ssss_0000_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3a01,0x3af1,16,2, 21,Z3A_ssss_0001_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3a02,0x3af2,16,2, 21,Z3A_ssss_0010_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3a03,0x3af3,16,2, 21,Z3A_ssss_0011_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3a04,0x3af4,16,2, 10,Z3A_dddd_0100_imm16, "%R %rb2,%#w1", 0},
+{0x3a05,0x3af5,16,2, 10,Z3A_dddd_0101_imm16, "%R %rb2,%#w1", 0},
+{0x3a06,0x3af6,16,2, 12,Z3A_ssss_0110_imm16, "%R %#w1,%rb2", 0},
+{0x3a07,0x3af7,16,2, 12,Z3A_ssss_0111_imm16, "%R %#w1,%rb2", 0},
+{0x3a08,0x3af8,16,2, 21,Z3A_ssss_1000_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3a09,0x3af9,16,2, 21,Z3A_ssss_1001_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3a0a,0x3afa,16,2, 21,Z3A_ssss_1010_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3a0b,0x3afb,16,2, 21,Z3A_ssss_1011_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3b00,0x3bf0,16,2, 21,Z3B_ssss_0000_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3b01,0x3bf1,16,2, 21,Z3B_ssss_0001_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3b02,0x3bf2,16,2, 21,Z3B_ssss_0010_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3b03,0x3bf3,16,2, 21,Z3B_ssss_0011_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3b04,0x3bf4,16,2, 12,Z3B_dddd_0100_imm16, "%R %rw2,%#w1", 0},
+{0x3b05,0x3bf5,16,2, 12,Z3B_dddd_0101_imm16, "%R %rw2,%#w1", 0},
+{0x3b06,0x3bf6,16,2, 12,Z3B_ssss_0110_imm16, "%R %#w1,%rw2", 0},
+{0x3b07,0x3bf7,16,2, 12,Z3B_ssss_0111_imm16, "%R %#w1,%rw2", 0},
+{0x3b08,0x3bf8,16,2, 21,Z3B_ssss_1000_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3b09,0x3bf9,16,2, 21,Z3B_ssss_1001_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rw5", 0},
+{0x3b0a,0x3bfa,16,2, 21,Z3B_ssss_1010_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rb5", 0},
+{0x3b0b,0x3bfb,16,2, 21,Z3B_ssss_1011_0000_aaaa_dddd_x000, "%R @%rw6,@%rw2,%rb5", 0},
+{0x3c00,0x3cff, 1,1, 10,Z3C_ssss_dddd, "inb %rb3,@%rw2", 0},
+{0x3d00,0x3dff, 1,1, 10,Z3D_ssss_dddd, "in %rw3,@%rw2", 0},
+{0x3e00,0x3eff, 1,1, 12,Z3E_dddd_ssss_seg, "outb @%rw2,%rb3", 0},
+{0x3f00,0x3fff, 1,1, 12,Z3F_dddd_ssss, "out @%rw2,%rw3", 0},
+{0x4000,0x400f, 1,2, 9,Z40_0000_dddd_addr, "addb %rb3,%a1", 0},
+{0x4010,0x40ff, 1,2, 10,Z40_ssN0_dddd_addr, "addb %rb3,%a1(%rw2)", 0},
+{0x4100,0x410f, 1,2, 9,Z41_0000_dddd_addr, "add %rw3,%a1", 0},
+{0x4110,0x41ff, 1,2, 10,Z41_ssN0_dddd_addr, "add %rw3,%a1(%rw2)", 0},
+{0x4200,0x420f, 1,2, 9,Z42_0000_dddd_addr, "subb %rb3,%a1", 0},
+{0x4210,0x42ff, 1,2, 10,Z42_ssN0_dddd_addr, "subb %rb3,%a1(%rw2)", 0},
+{0x4300,0x430f, 1,2, 9,Z43_0000_dddd_addr, "sub %rw3,%a1", 0},
+{0x4310,0x43ff, 1,2, 10,Z43_ssN0_dddd_addr, "sub %rw3,%a1(%rw2)", 0},
+{0x4400,0x440f, 1,2, 9,Z44_0000_dddd_addr, "orb %rb3,%a1", 0},
+{0x4410,0x44ff, 1,2, 10,Z44_ssN0_dddd_addr, "orb %rb3,%a1(%rw2)", 0},
+{0x4500,0x450f, 1,2, 9,Z45_0000_dddd_addr, "or %rw3,%a1", 0},
+{0x4510,0x45ff, 1,2, 10,Z45_ssN0_dddd_addr, "or %rw3,%a1(%rw2)", 0},
+{0x4600,0x460f, 1,2, 9,Z46_0000_dddd_addr, "andb %rb3,%a1", 0},
+{0x4610,0x46ff, 1,2, 10,Z46_ssN0_dddd_addr, "andb %rb3,%a1(%rw2)", 0},
+{0x4700,0x470f, 1,2, 9,Z47_0000_dddd_addr, "and %rw3,%a1", 0},
+{0x4710,0x47ff, 1,2, 10,Z47_ssN0_dddd_addr, "and %rw3,%a1(%rw2)", 0},
+{0x4800,0x480f, 1,2, 9,Z48_0000_dddd_addr, "xorb %rb3,%a1", 0},
+{0x4810,0x48ff, 1,2, 10,Z48_ssN0_dddd_addr, "xorb %rb3,%a1(%rw2)", 0},
+{0x4900,0x490f, 1,2, 9,Z49_0000_dddd_addr, "xor %rw3,%a1", 0},
+{0x4910,0x49ff, 1,2, 10,Z49_ssN0_dddd_addr, "xor %rw3,%a1(%rw2)", 0},
+{0x4a00,0x4a0f, 1,2, 9,Z4A_0000_dddd_addr, "cpb %rb3,%a1", 0},
+{0x4a10,0x4aff, 1,2, 10,Z4A_ssN0_dddd_addr, "cpb %rb3,%a1(%rw2)", 0},
+{0x4b00,0x4b0f, 1,2, 9,Z4B_0000_dddd_addr, "cp %rw3,%a1", 0},
+{0x4b10,0x4bff, 1,2, 10,Z4B_ssN0_dddd_addr, "cp %rw3,%a1(%rw2)", 0},
+{0x4c00,0x4c00, 1,2, 15,Z4C_0000_0000_addr, "comb %a1", 0},
+{0x4c01,0x4c01, 1,3, 14,Z4C_0000_0001_addr_imm8, "cpb %a1,%#b3", 0},
+{0x4c02,0x4c02, 1,2, 15,Z4C_0000_0010_addr, "negb %a1", 0},
+{0x4c04,0x4c04, 1,2, 11,Z4C_0000_0100_addr, "testb %a1", 0},
+{0x4c05,0x4c05, 1,3, 14,Z4C_0000_0101_addr_imm8, "ldb %a1,%#b3", 0},
+{0x4c06,0x4c06, 1,2, 14,Z4C_0000_0110_addr, "tsetb %a1", 0},
+{0x4c08,0x4c08, 1,1, 0, Z4C_0000_1000_addr_seg, "clrb %a1", 0},
+{0x4c10,0x4cf0,16,2, 16,Z4C_ddN0_0000_addr, "comb %a1(%rw2)", 0},
+{0x4c11,0x4cf1,16,3, 15,Z4C_ddN0_0001_addr_imm8, "cpb %a1(%rw2),%#b3", 0},
+{0x4c12,0x4cf2,16,2, 16,Z4C_ddN0_0010_addr, "negb %a1(%rw2)", 0},
+{0x4c14,0x4cf4,16,2, 12,Z4C_ddN0_0100_addr, "testb %a1(%rw2)", 0},
+{0x4c15,0x4cf5,16,3, 15,Z4C_ddN0_0101_addr_imm8, "ldb %a1(%rw2),%#b3", 0},
+{0x4c16,0x4cf6,16,2, 15,Z4C_ddN0_0110_addr, "tsetb %a1(%rw2)", 0},
+{0x4c18,0x4cf8,16,2, 12,Z4C_ddN0_1000_addr, "clrb %a1(%rw2)", 0},
+{0x4d00,0x4d00, 1,2, 15,Z4D_0000_0000_addr, "com %a1", 0},
+{0x4d01,0x4d01, 1,3, 14,Z4D_0000_0001_addr_imm16, "cp %a1,%#w2", 0},
+{0x4d02,0x4d02, 1,2, 15,Z4D_0000_0010_addr, "neg %a1", 0},
+{0x4d04,0x4d04, 1,2, 11,Z4D_0000_0100_addr, "test %a1", 0},
+{0x4d05,0x4d05, 1,1, 0, Z4D_0000_0101_addr_imm16_seg, "ld %a1,%#w2", 0},
+{0x4d06,0x4d06, 1,2, 14,Z4D_0000_0110_addr, "tset %a1", 0},
+{0x4d08,0x4d08, 1,1, 0, Z4D_0000_1000_addr_seg, "clr %a1", 0},
+{0x4d10,0x4df0,16,2, 16,Z4D_ddN0_0000_addr, "com %a1(%rw2)", 0},
+{0x4d11,0x4df1,16,3, 15,Z4D_ddN0_0001_addr_imm16, "cp %a1(%rw2),%#w2", 0},
+{0x4d12,0x4df2,16,2, 16,Z4D_ddN0_0010_addr, "neg %a1(%rw2)", 0},
+{0x4d14,0x4df4,16,2, 12,Z4D_ddN0_0100_addr, "test %a1(%rw2)", 0},
+{0x4d15,0x4df5,16,3, 15,Z4D_ddN0_0101_addr_imm16, "ld %a1(%rw2),%#w2", 0},
+{0x4d16,0x4df6,16,2, 15,Z4D_ddN0_0110_addr, "tset %a1(%rw2)", 0},
+{0x4d18,0x4df8,16,2, 12,Z4D_ddN0_1000_addr, "clr %a1(%rw2)", 0},
+{0x4e11,0x4ef0,16,2, 12,Z4E_ddN0_ssN0_addr, "ldb %a1(%rw2),%rb3", 0},
+{0x5000,0x500f, 1,2, 15,Z50_0000_dddd_addr, "cpl %rl3,%a1", 0},
+{0x5010,0x50ff, 1,2, 16,Z50_ssN0_dddd_addr, "cpl %rl3,%a1(%rw2)", 0},
+{0x5110,0x51f0,16,2, 21,Z51_ddN0_0000_addr, "pushl @%rw2,%a1", 0},
+{0x5111,0x51f1,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x5112,0x51f2,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x5113,0x51f3,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x5114,0x51f4,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x5115,0x51f5,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x5116,0x51f6,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x5117,0x51f7,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x5118,0x51f8,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x5119,0x51f9,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x511a,0x51fa,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x511b,0x51fb,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x511c,0x51fc,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x511d,0x51fd,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x511e,0x51fe,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x511f,0x51ff,16,2, 21,Z51_ddN0_ssN0_addr, "pushl @%rw2,%a1(%rw3)", 0},
+{0x5200,0x520f, 1,2, 15,Z52_0000_dddd_addr, "subl %rl3,%a1", 0},
+{0x5210,0x52ff, 1,2, 16,Z52_ssN0_dddd_addr, "subl %rl3,%a1(%rw2)", 0},
+{0x5310,0x53f0,16,2, 14,Z53_ddN0_0000_addr, "push @%rw2,%a1", 0},
+{0x5311,0x53f1,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x5312,0x53f2,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x5313,0x53f3,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x5314,0x53f4,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x5315,0x53f5,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x5316,0x53f6,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x5317,0x53f7,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x5318,0x53f8,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x5319,0x53f9,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x531a,0x53fa,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x531b,0x53fb,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x531c,0x53fc,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x531d,0x53fd,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x531e,0x53fe,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x531f,0x53ff,16,2, 14,Z53_ddN0_ssN0_addr, "push @%rw2,%a1(%rw3)", 0},
+{0x5400,0x540f, 1,2, 12,Z54_0000_dddd_addr, "ldl %rl3,%a1", 0},
+{0x5410,0x54ff, 1,2, 13,Z54_ssN0_dddd_addr, "ldl %rl3,%a1(%rw2)", 0},
+{0x5510,0x55f0,16,2, 23,Z55_ssN0_0000_addr, "popl %a1,@%rw2", 0},
+{0x5511,0x55f1,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x5512,0x55f2,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x5513,0x55f3,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x5514,0x55f4,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x5515,0x55f5,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x5516,0x55f6,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x5517,0x55f7,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x5518,0x55f8,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x5519,0x55f9,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x551a,0x55fa,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x551b,0x55fb,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x551c,0x55fc,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x551d,0x55fd,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x551e,0x55fe,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x551f,0x55ff,16,2, 23,Z55_ssN0_ddN0_addr, "popl %a1(%rw3),@%rw2", 0},
+{0x5600,0x560f, 1,2, 15,Z56_0000_dddd_addr, "addl %rl3,%a1", 0},
+{0x5610,0x56ff, 1,2, 16,Z56_ssN0_dddd_addr, "addl %rl3,%a1(%rw2)", 0},
+{0x5710,0x57f0,16,2, 16,Z57_ssN0_0000_addr, "pop %a1,@%rw2", 0},
+{0x5711,0x57f1,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x5712,0x57f2,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x5713,0x57f3,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x5714,0x57f4,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x5715,0x57f5,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x5716,0x57f6,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x5717,0x57f7,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x5718,0x57f8,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x5719,0x57f9,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x571a,0x57fa,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x571b,0x57fb,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x571c,0x57fc,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x571d,0x57fd,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x571e,0x57fe,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x571f,0x57ff,16,2, 16,Z57_ssN0_ddN0_addr, "pop %a1(%rw3),@%rw2", 0},
+{0x5800,0x580f, 1,2,283,Z58_0000_dddd_addr, "multl %rq3,%a1", 0},
+{0x5810,0x58ff, 1,2,284,Z58_ssN0_dddd_addr, "multl %rq3,%a1(%rw2)", 0},
+{0x5900,0x590f, 1,2, 71,Z59_0000_dddd_addr, "mult %rl3,%a1", 0},
+{0x5910,0x59ff, 1,2, 72,Z59_ssN0_dddd_addr, "mult %rl3,%a1(%rw2)", 0},
+{0x5a00,0x5a0f, 1,2,745,Z5A_0000_dddd_addr, "divl %rq3,%a1", 0},
+{0x5a10,0x5aff, 1,2,746,Z5A_ssN0_dddd_addr, "divl %rq3,%a1(%rw2)", 0},
+{0x5b00,0x5b0f, 1,2,108,Z5B_0000_dddd_addr, "div %rl3,%a1", 0},
+{0x5b10,0x5bff, 1,2,109,Z5B_ssN0_dddd_addr, "div %rl3,%a1(%rw2)", 0},
+{0x5c01,0x5c01, 1,3, 14,Z5C_0000_0001_0000_dddd_0000_nmin1_addr, "ldm %rw5,%a2,#%n", 0},
+{0x5c08,0x5c08, 1,2, 16,Z5C_0000_1000_addr, "testl %a1", 0},
+{0x5c09,0x5c09, 1,3, 14,Z5C_0000_1001_0000_ssss_0000_nmin1_addr, "ldm %a2,%rw5,#%n", 0},
+{0x5c11,0x5cf1,16,3, 15,Z5C_ssN0_0001_0000_dddd_0000_nmin1_addr, "ldm %rw5,%a2(%rw2),#%n", 0},
+{0x5c18,0x5cf8,16,2, 17,Z5C_ddN0_1000_addr, "testl %a1(%rw2)", 0},
+{0x5c19,0x5cf9,16,3, 15,Z5C_ddN0_1001_0000_ssN0_0000_nmin1_addr, "ldm %a2(%rw2),%rw5,#%n", 0},
+{0x5d00,0x5d0f, 1,2, 15,Z5D_0000_ssss_addr, "ldl %a1,%rl3", 0},
+{0x5d10,0x5dff, 1,2, 14,Z5D_ddN0_ssss_addr, "ldl %a1(%rw2),%rl3", 0},
+{0x5e00,0x5e0f, 1,2, 7,Z5E_0000_cccc_addr, "jp %c3,%a1", 0},
+{0x5e10,0x5eff, 1,2, 8,Z5E_ddN0_cccc_addr, "jp %c3,%a1(%rw2)", 0},
+{0x5f00,0x5f00, 1,2, 12,Z5F_0000_0000_addr, "call %a1", DASMFLAG_STEP_OVER},
+{0x5f10,0x5ff0,16,2, 13,Z5F_ddN0_0000_addr, "call %a1(%rw2)", DASMFLAG_STEP_OVER},
+{0x6000,0x600f, 1,2, 9,Z60_0000_dddd_addr, "ldb %rb3,%a1", 0},
+{0x6010,0x60ff, 1,2, 10,Z60_ssN0_dddd_addr, "ldb %rb3,%a1(%rw2)", 0},
+{0x6100,0x610f, 1,2, 9,Z61_0000_dddd_addr, "ld %rw3,%a1", 0},
+{0x6110,0x61ff, 1,2, 10,Z61_ssN0_dddd_addr, "ld %rw3,%a1(%rw2)", 0},
+{0x6200,0x620f, 1,2, 13,Z62_0000_imm4_addr, "resb %a1,%3", 0},
+{0x6210,0x62ff, 1,2, 14,Z62_ddN0_imm4_addr, "resb %a1(%rw2),%3", 0},
+{0x6300,0x630f, 1,2, 13,Z63_0000_imm4_addr, "res %a1,%3", 0},
+{0x6310,0x63ff, 1,2, 14,Z63_ddN0_imm4_addr, "res %a1(%rw2),%3", 0},
+{0x6400,0x640f, 1,2, 13,Z64_0000_imm4_addr, "setb %a1,%3", 0},
+{0x6410,0x64ff, 1,2, 14,Z64_ddN0_imm4_addr, "setb %a1(%rw2),%3", 0},
+{0x6500,0x650f, 1,2, 13,Z65_0000_imm4_addr, "set %a1,%3", 0},
+{0x6510,0x65ff, 1,2, 14,Z65_ddN0_imm4_addr, "set %a1(%rw2),%3", 0},
+{0x6600,0x660f, 1,2, 10,Z66_0000_imm4_addr, "bitb %a1,%3", 0},
+{0x6610,0x66ff, 1,2, 11,Z66_ddN0_imm4_addr, "bitb %a1(%rw2),%3", 0},
+{0x6700,0x670f, 1,2, 10,Z67_0000_imm4_addr, "bit %a1,%3", 0},
+{0x6710,0x67ff, 1,2, 11,Z67_ddN0_imm4_addr, "bit %a1(%rw2),%3", 0},
+{0x6800,0x680f, 1,2, 13,Z68_0000_imm4m1_addr, "incb %a1,%+3", 0},
+{0x6810,0x68ff, 1,2, 14,Z68_ddN0_imm4m1_addr, "incb %a1(%rw2),%+3", 0},
+{0x6900,0x690f, 1,2, 13,Z69_0000_imm4m1_addr, "inc %a1,%+3", 0},
+{0x6910,0x69ff, 1,2, 14,Z69_ddN0_imm4m1_addr, "inc %a1(%rw2),%+3", 0},
+{0x6a00,0x6a0f, 1,2, 13,Z6A_0000_imm4m1_addr, "decb %a1,%+3", 0},
+{0x6a10,0x6aff, 1,2, 14,Z6A_ddN0_imm4m1_addr, "decb %a1(%rw2),%+3", 0},
+{0x6b00,0x6b0f, 1,2, 13,Z6B_0000_imm4m1_addr, "dec %a1,%+3", 0},
+{0x6b10,0x6bff, 1,2, 14,Z6B_ddN0_imm4m1_addr, "dec %a1(%rw2),%+3", 0},
+{0x6c00,0x6c0f, 1,2, 15,Z6C_0000_dddd_addr, "exb %rb3,%a1", 0},
+{0x6c10,0x6cff, 1,2, 16,Z6C_ssN0_dddd_addr, "exb %rb3,%a1(%rw2)", 0},
+{0x6d00,0x6d0f, 1,2, 15,Z6D_0000_dddd_addr, "ex %rw3,%a1", 0},
+{0x6d10,0x6dff, 1,2, 16,Z6D_ssN0_dddd_addr, "ex %rw3,%a1(%rw2)", 0},
+{0x6e00,0x6e0f, 1,2, 11,Z6E_0000_ssss_addr, "ldb %a1,%rb3", 0},
+{0x6e10,0x6eff, 1,2, 11,Z6E_ddN0_ssss_addr, "ldb %a1(%rw2),%rb3", 0},
+{0x6f00,0x6f0f, 1,2, 11,Z6F_0000_ssss_addr, "ld %a1,%rw3", 0},
+{0x6f10,0x6fff, 1,2, 12,Z6F_ddN0_ssss_addr, "ld %a1(%rw2),%rw3", 0},
+{0x7010,0x70ff, 1,2, 14,Z70_ssN0_dddd_0000_xxxx_0000_0000, "ldb %rb3,%rw2(%rw5)", 0},
+{0x7110,0x71ff, 1,2, 14,Z71_ssN0_dddd_0000_xxxx_0000_0000, "ld %rw3,%rw2(%rw5)", 0},
+{0x7210,0x72ff, 1,2, 14,Z72_ddN0_ssss_0000_xxxx_0000_0000, "ldb %rw2(%rw5),%rb3", 0},
+{0x7310,0x73ff, 1,2, 14,Z73_ddN0_ssss_0000_xxxx_0000_0000, "ld %rw2(%rw5),%rw3", 0},
+{0x7410,0x74ff, 1,2, 15,Z74_ssN0_dddd_0000_xxxx_0000_0000, "lda p%rw3,%rw2(%rw5)", 0},
+{0x7510,0x75ff, 1,2, 17,Z75_ssN0_dddd_0000_xxxx_0000_0000, "ldl %rl3,%rw2(%rw5)", 0},
+{0x7600,0x760f, 1,1, 0, Z76_0000_dddd_addr_seg, "lda p%rw3,%a1", 0},
+{0x7610,0x76ff, 1,2, 13,Z76_ssN0_dddd_addr, "lda p%rw3,%a1(%rw2)", 0},
+{0x7710,0x77ff, 1,2, 17,Z77_ddN0_ssss_0000_xxxx_0000_0000, "ldl %rw2(%rw5),%rl3", 0},
+{0x7800,0x78ff, 1,1, 10,Z78_imm8, "rsvd78", 0},
+{0x7900,0x7900, 1,2, 16,Z79_0000_0000_addr, "ldps %a1", 0},
+{0x7910,0x79f0,16,2, 17,Z79_ssN0_0000_addr, "ldps %a1(%rw2)", 0},
+{0x7a00,0x7a00, 1,1, 8,Z7A_0000_0000, "halt", DASMFLAG_STEP_OVER},
+{0x7b00,0x7b00, 1,1, 13,Z7B_0000_0000, "iret", DASMFLAG_STEP_OUT},
+{0x7b08,0x7b08, 1,1, 5,Z7B_0000_1000, "mset", 0},
+{0x7b09,0x7b09, 1,1, 5,Z7B_0000_1001, "mres", 0},
+{0x7b0a,0x7b0a, 1,1, 7,Z7B_0000_1010, "mbit", 0},
+{0x7b0d,0x7bfd,16,1, 12,Z7B_dddd_1101, "mreq %rw2", 0},
+{0x7c00,0x7c03, 1,1, 7,Z7C_0000_00ii, "di %i3", 0},
+{0x7c04,0x7c07, 1,1, 7,Z7C_0000_01ii, "ei %i3", 0},
+{0x7d00,0x7df0,16,1, 7,Z7D_dddd_0ccc, "ldctl %rw2,ctrl0", 0},
+{0x7d01,0x7df1,16,1, 7,Z7D_dddd_0ccc, "ldctl %rw2,ctrl1", 0},
+{0x7d02,0x7df2,16,1, 7,Z7D_dddd_0ccc, "ldctl %rw2,fcw", 0},
+{0x7d03,0x7df3,16,1, 7,Z7D_dddd_0ccc, "ldctl %rw2,refresh", 0},
+{0x7d04,0x7df4,16,1, 7,Z7D_dddd_0ccc, "ldctl %rw2,ctrl4", 0},
+{0x7d05,0x7df5,16,1, 7,Z7D_dddd_0ccc, "ldctl %rw2,psap", 0},
+{0x7d06,0x7df6,16,1, 7,Z7D_dddd_0ccc, "ldctl %rw2,ctrl6", 0},
+{0x7d07,0x7df7,16,1, 7,Z7D_dddd_0ccc, "ldctl %rw2,nsp", 0},
+{0x7d08,0x7df8,16,1, 7,Z7D_ssss_1ccc, "ldctl ctrl0,%rw2", 0},
+{0x7d09,0x7df9,16,1, 7,Z7D_ssss_1ccc, "ldctl ctrl1,%rw2", 0},
+{0x7d0a,0x7dfa,16,1, 7,Z7D_ssss_1ccc, "ldctl fcw,%rw2", 0},
+{0x7d0b,0x7dfb,16,1, 7,Z7D_ssss_1ccc, "ldctl refresh,%rw2", 0},
+{0x7d0c,0x7dfc,16,1, 7,Z7D_ssss_1ccc, "ldctl ctrl4,%rw2", 0},
+{0x7d0d,0x7dfd,16,1, 7,Z7D_ssss_1ccc, "ldctl psap,%rw2", 0},
+{0x7d0e,0x7dfe,16,1, 7,Z7D_ssss_1ccc, "ldctl ctrl6,%rw2", 0},
+{0x7d0f,0x7dff,16,1, 7,Z7D_ssss_1ccc, "ldctl nsp,%rw2", 0},
+{0x7e00,0x7eff, 1,1, 10,Z7E_imm8, "rsvd7e %#b1", 0},
+{0x7f00,0x7fff, 1,1, 33,Z7F_imm8, "sc %#b1", 0},
+{0x8000,0x80ff, 1,1, 4,Z80_ssss_dddd, "addb %rb3,%rb2", 0},
+{0x8100,0x81ff, 1,1, 4,Z81_ssss_dddd, "add %rw3,%rw2", 0},
+{0x8200,0x82ff, 1,1, 4,Z82_ssss_dddd, "subb %rb3,%rb2", 0},
+{0x8300,0x83ff, 1,1, 4,Z83_ssss_dddd, "sub %rw3,%rw2", 0},
+{0x8400,0x84ff, 1,1, 4,Z84_ssss_dddd, "orb %rb3,%rb2", 0},
+{0x8500,0x85ff, 1,1, 4,Z85_ssss_dddd, "or %rw3,%rw2", 0},
+{0x8600,0x86ff, 1,1, 4,Z86_ssss_dddd, "andb %rb3,%rb2", 0},
+{0x8700,0x87ff, 1,1, 4,Z87_ssss_dddd, "and %rw3,%rw2", 0},
+{0x8800,0x88ff, 1,1, 4,Z88_ssss_dddd, "xorb %rb3,%rb2", 0},
+{0x8900,0x89ff, 1,1, 4,Z89_ssss_dddd, "xor %rw3,%rw2", 0},
+{0x8a00,0x8aff, 1,1, 4,Z8A_ssss_dddd, "cpb %rb3,%rb2", 0},
+{0x8b00,0x8bff, 1,1, 4,Z8B_ssss_dddd, "cp %rw3,%rw2", 0},
+{0x8c00,0x8cf0,16,1, 7,Z8C_dddd_0000, "comb %rb2", 0},
+{0x8c02,0x8cf2,16,1, 7,Z8C_dddd_0010, "negb %rb2", 0},
+{0x8c04,0x8cf4,16,1, 7,Z8C_dddd_0100, "testb %rb2", 0},
+{0x8c06,0x8cf6,16,1, 7,Z8C_dddd_0110, "tsetb %rb2", 0},
+{0x8c08,0x8cf8,16,1, 7,Z8C_dddd_1000, "clrb %rb2", 0},
+{0x8d00,0x8df0,16,1, 7,Z8D_dddd_0000, "com %rw2", 0},
+{0x8d01,0x8df1,16,1, 7,Z8D_imm4_0001, "setflg %f2", 0},
+{0x8d02,0x8df2,16,1, 7,Z8D_dddd_0010, "neg %rw2", 0},
+{0x8d03,0x8df3,16,1, 7,Z8D_imm4_0011, "resflg %f2", 0},
+{0x8d04,0x8df4,16,1, 7,Z8D_dddd_0100, "test %rw2", 0},
+{0x8d05,0x8df5,16,1, 7,Z8D_imm4_0101, "comflg %f2", 0},
+{0x8d06,0x8df6,16,1, 7,Z8D_dddd_0110, "tset %rw2", 0},
+{0x8d07,0x8d07, 1,1, 7,Z8D_0000_0111, "nop", 0},
+{0x8d08,0x8df8,16,1, 7,Z8D_dddd_1000, "clr %rw2", 0},
+{0x8e00,0x8eff, 1,1, 10,Z8E_imm8, "ext8e %#b1", 0},
+{0x8f00,0x8fff, 1,1, 10,Z8F_imm8, "ext8f %#b1", 0},
+{0x9000,0x90ff, 1,1, 8,Z90_ssss_dddd, "cpl %rl3,%rl2", 0},
+{0x9110,0x91ff, 1,1, 12,Z91_ddN0_ssss, "pushl @%rw2,%rl3", 0},
+{0x9200,0x92ff, 1,1, 8,Z92_ssss_dddd, "subl %rl3,%rl2", 0},
+{0x9310,0x93ff, 1,1, 9,Z93_ddN0_ssss, "push @%rw2,%rw3", 0},
+{0x9400,0x94ff, 1,1, 5,Z94_ssss_dddd, "ldl %rl3,%rl2", 0},
+{0x9510,0x95ff, 1,1, 12,Z95_ssN0_dddd, "popl %rl3,@%rw2", 0},
+{0x9600,0x96ff, 1,1, 8,Z96_ssss_dddd, "addl %rl3,%rl2", 0},
+{0x9710,0x97ff, 1,1, 8,Z97_ssN0_dddd, "pop %rw3,@%rw2", 0},
+{0x9800,0x98ff, 1,1,282,Z98_ssss_dddd, "multl %rq3,%rl2", 0},
+{0x9900,0x99ff, 1,1, 70,Z99_ssss_dddd, "mult %rl3,%rw2", 0},
+{0x9a00,0x9aff, 1,1,744,Z9A_ssss_dddd, "divl %rq3,%rl2", 0},
+{0x9b00,0x9bff, 1,1,107,Z9B_ssss_dddd, "div %rl3,%rw2", 0},
+{0x9c08,0x9cf8,16,1, 13,Z9C_dddd_1000, "testl %rl2", 0},
+{0x9d00,0x9dff, 1,1, 10,Z9D_imm8, "rsvd9d", 0},
+{0x9e00,0x9e0f, 1,1, 10,Z9E_0000_cccc, "ret %c3", DASMFLAG_STEP_OUT},
+{0x9f00,0x9fff, 1,1, 10,Z9F_imm8, "rsvd9f", 0},
+{0xa000,0xa0ff, 1,1, 3,ZA0_ssss_dddd, "ldb %rb3,%rb2", 0},
+{0xa100,0xa1ff, 1,1, 3,ZA1_ssss_dddd, "ld %rw3,%rw2", 0},
+{0xa200,0xa2ff, 1,1, 4,ZA2_dddd_imm4, "resb %rb2,%3", 0},
+{0xa300,0xa3ff, 1,1, 4,ZA3_dddd_imm4, "res %rw2,%3", 0},
+{0xa400,0xa4ff, 1,1, 4,ZA4_dddd_imm4, "setb %rb2,%3", 0},
+{0xa500,0xa5ff, 1,1, 4,ZA5_dddd_imm4, "set %rw2,%3", 0},
+{0xa600,0xa6ff, 1,1, 4,ZA6_dddd_imm4, "bitb %rb2,%3", 0},
+{0xa700,0xa7ff, 1,1, 4,ZA7_dddd_imm4, "bit %rw2,%3", 0},
+{0xa800,0xa8ff, 1,1, 4,ZA8_dddd_imm4m1, "incb %rb2,%+3", 0},
+{0xa900,0xa9ff, 1,1, 4,ZA9_dddd_imm4m1, "inc %rw2,%+3", 0},
+{0xaa00,0xaaff, 1,1, 4,ZAA_dddd_imm4m1, "decb %rb2,%+3", 0},
+{0xab00,0xabff, 1,1, 4,ZAB_dddd_imm4m1, "dec %rw2,%+3", 0},
+{0xac00,0xacff, 1,1, 6,ZAC_ssss_dddd, "exb %rb3,%rb2", 0},
+{0xad00,0xadff, 1,1, 6,ZAD_ssss_dddd, "ex %rw3,%rw2", 0},
+{0xae00,0xaeff, 1,1, 5,ZAE_dddd_cccc, "tccb %c3,%rb2", 0},
+{0xaf00,0xafff, 1,1, 5,ZAF_dddd_cccc, "tcc %c3,%rw2", 0},
+{0xb000,0xb0f0,16,1, 5,ZB0_dddd_0000, "dab %rb2", 0},
+{0xb100,0xb1f0,16,1, 11,ZB1_dddd_0000, "extsb %rw2", 0},
+{0xb107,0xb1f7,16,1, 11,ZB1_dddd_0111, "extsl %rq2", 0},
+{0xb10a,0xb1fa,16,1, 11,ZB1_dddd_1010, "exts %rl2", 0},
+{0xb200,0xb2f0,16,1, 6,ZB2_dddd_00I0, "rlb %rb2,%?3", 0},
+{0xb201,0xb2f1,16,2, 13,ZB2_dddd_0001_imm8, "s%*lb %rb2,%$3", 0},
+{0xb202,0xb2f2,16,1, 6,ZB2_dddd_00I0, "rlb %rb2,%?3", 0},
+{0xb203,0xb2f3,16,2, 15,ZB2_dddd_0011_0000_ssss_0000_0000, "sdlb %rb2,%rw5", 0},
+{0xb204,0xb2f4,16,1, 6,ZB2_dddd_01I0, "rrb %rb2,%?3", 0},
+{0xb206,0xb2f6,16,1, 6,ZB2_dddd_01I0, "rrb %rb2,%?3", 0},
+{0xb208,0xb2f8,16,1, 9,ZB2_dddd_10I0, "rlcb %rb2,%?3", 0},
+{0xb209,0xb2f9,16,2, 13,ZB2_dddd_1001_imm8, "s%*ab %rb2,%$3", 0},
+{0xb20a,0xb2fa,16,1, 9,ZB2_dddd_10I0, "rlcb %rb2,%?3", 0},
+{0xb20b,0xb2fb,16,2, 15,ZB2_dddd_1011_0000_ssss_0000_0000, "sdab %rb2,%rw5", 0},
+{0xb20c,0xb2fc,16,1, 9,ZB2_dddd_11I0, "rrcb %rb2,%?3", 0},
+{0xb20e,0xb2fe,16,1, 9,ZB2_dddd_11I0, "rrcb %rb2,%?3", 0},
+{0xb300,0xb3f0,16,1, 6,ZB3_dddd_00I0, "rl %rw2,%?3", 0},
+{0xb301,0xb3f1,16,2, 13,ZB3_dddd_0001_imm8, "s%*l %rw2,%$3", 0},
+{0xb302,0xb3f2,16,1, 6,ZB3_dddd_00I0, "rl %rw2,%?3", 0},
+{0xb303,0xb3f3,16,2, 15,ZB3_dddd_0011_0000_ssss_0000_0000, "sdl %rw2,%rw5", 0},
+{0xb304,0xb3f4,16,1, 6,ZB3_dddd_01I0, "rr %rw2,%?3", 0},
+{0xb305,0xb3f5,16,2, 13,ZB3_dddd_0101_imm8, "s%*ll %rl2,%$3", 0},
+{0xb306,0xb3f6,16,1, 6,ZB3_dddd_01I0, "rr %rw2,%?3", 0},
+{0xb307,0xb3f7,16,2, 15,ZB3_dddd_0111_0000_ssss_0000_0000, "sdll %rl2,%rw5", 0},
+{0xb308,0xb3f8,16,1, 6,ZB3_dddd_10I0, "rlc %rw2,%?3", 0},
+{0xb309,0xb3f9,16,2, 13,ZB3_dddd_1001_imm8, "s%*a %rw2,%$3", 0},
+{0xb30a,0xb3fa,16,1, 6,ZB3_dddd_10I0, "rlc %rw2,%?3", 0},
+{0xb30b,0xb3fb,16,2, 15,ZB3_dddd_1011_0000_ssss_0000_0000, "sda %rw2,%rw5", 0},
+{0xb30c,0xb3fc,16,1, 6,ZB3_dddd_11I0, "rrc %rw2,%?3", 0},
+{0xb30d,0xb3fd,16,2, 13,ZB3_dddd_1101_imm8, "s%*al %rl2,%$3", 0},
+{0xb30e,0xb3fe,16,1, 6,ZB3_dddd_11I0, "rrc %rw2,%?3", 0},
+{0xb30f,0xb3ff,16,2, 15,ZB3_dddd_1111_0000_ssss_0000_0000, "sdal %rl2,%rw5", 0},
+{0xb400,0xb4ff, 1,1, 5,ZB4_ssss_dddd, "adcb %rb3,%rb2", 0},
+{0xb500,0xb5ff, 1,1, 5,ZB5_ssss_dddd, "adc %rw3,%rw2", 0},
+{0xb600,0xb6ff, 1,1, 5,ZB6_ssss_dddd, "sbcb %rb3,%rb2", 0},
+{0xb700,0xb7ff, 1,1, 5,ZB7_ssss_dddd, "sbc %rw3,%rw2", 0},
+{0xb810,0xb8f0,16,2, 25,ZB8_ddN0_0000_0000_rrrr_ssN0_0000, "trib @%rw2,@%rw6,%rb5", 0},
+{0xb812,0xb8f2,16,2, 25,ZB8_ddN0_0010_0000_rrrr_ssN0_0000, "trtib @%rw2,@%rw6,%rb5", 0},
+{0xb814,0xb8f4,16,2, 25,ZB8_ddN0_0100_0000_rrrr_ssN0_0000, "trirb @%rw2,@%rw6,%rb5", 0},
+{0xb816,0xb8f6,16,2, 25,ZB8_ddN0_0110_0000_rrrr_ssN0_1110, "trtirb @%rw2,@%rw6,%rb5", 0},
+{0xb818,0xb8f8,16,2, 25,ZB8_ddN0_1000_0000_rrrr_ssN0_0000, "trdb @%rw2,@%rw6,%rb5", 0},
+{0xb81a,0xb8fa,16,2, 25,ZB8_ddN0_1010_0000_rrrr_ssN0_0000, "trtrb @%rw2,@%rw6,%rb5", 0},
+{0xb81c,0xb8fc,16,2, 25,ZB8_ddN0_1100_0000_rrrr_ssN0_0000, "trdrb @%rw2,@%rw6,%rb5", 0},
+{0xb81e,0xb8fe,16,2, 25,ZB8_ddN0_1110_0000_rrrr_ssN0_1110, "trtdrb @%rw2,@%rw6,%rb5", 0},
+{0xb900,0xb9ff,16,1, 10,ZB9_imm8, "rsvdb9", 0},
+{0xba10,0xbaf0,16,2, 11,ZBA_ssN0_0000_0000_rrrr_dddd_cccc, "cpib %rb6,@%rw2,%rw5,%c7", 0},
+{0xba11,0xbaf1,16,2, 11,ZBA_ssN0_0001_0000_rrrr_ddN0_x000, "ldirb @%rw6,@%rw2,%rw5", DASMFLAG_STEP_OVER},
+{0xba12,0xbaf2,16,2, 11,ZBA_ssN0_0010_0000_rrrr_ddN0_cccc, "cpsib @%rw6,@%rw2,%rw5,%c7", 0},
+{0xba14,0xbaf4,16,2, 11,ZBA_ssN0_0100_0000_rrrr_dddd_cccc, "cpirb %rb6,@%rw2,%rw5,%c7", DASMFLAG_STEP_OVER},
+{0xba16,0xbaf6,16,2, 11,ZBA_ssN0_0110_0000_rrrr_ddN0_cccc, "cpsirb @%rw6,@%rw2,%rw5,%c7", DASMFLAG_STEP_OVER},
+{0xba18,0xbaf8,16,2, 11,ZBA_ssN0_1000_0000_rrrr_dddd_cccc, "cpdb %rb6,@%rw2,%rw5,%c7", 0},
+{0xba19,0xbaf9,16,2, 11,ZBA_ssN0_1001_0000_rrrr_ddN0_x000, "lddrb @%rw2,@%rw6,%rw5", DASMFLAG_STEP_OVER},
+{0xba1a,0xbafa,16,2, 11,ZBA_ssN0_1010_0000_rrrr_ddN0_cccc, "cpsdb @%rw6,@%rw2,%rw5,%c7", 0},
+{0xba1c,0xbafc,16,2, 11,ZBA_ssN0_1100_0000_rrrr_dddd_cccc, "cpdrb %rb6,@%rw2,%rw5,%c7", DASMFLAG_STEP_OVER},
+{0xba1e,0xbafe,16,2, 11,ZBA_ssN0_1110_0000_rrrr_ddN0_cccc, "cpsdrb @%rw6,@%rw2,%rw5,%c7", DASMFLAG_STEP_OVER},
+{0xbb10,0xbbf0,16,2, 11,ZBB_ssN0_0000_0000_rrrr_dddd_cccc, "cpi %rw6,@%rw2,%rw5,%c7", 0},
+{0xbb11,0xbbf1,16,2, 11,ZBB_ssN0_0001_0000_rrrr_ddN0_x000, "ldir @%rw6,@%rw2,%rw5", DASMFLAG_STEP_OVER},
+{0xbb12,0xbbf2,16,2, 11,ZBB_ssN0_0010_0000_rrrr_ddN0_cccc, "cpsi @%rw6,@%rw2,%rw5,%c7", 0},
+{0xbb14,0xbbf4,16,2, 11,ZBB_ssN0_0100_0000_rrrr_dddd_cccc, "cpir %rw6,@%rw2,%rw5,%c7", DASMFLAG_STEP_OVER},
+{0xbb16,0xbbf6,16,2, 11,ZBB_ssN0_0110_0000_rrrr_ddN0_cccc, "cpsir @%rw6,@%rw2,%rw5,%c7", DASMFLAG_STEP_OVER},
+{0xbb18,0xbbf8,16,2, 11,ZBB_ssN0_1000_0000_rrrr_dddd_cccc, "cpd %rw6,@%rw2,%rw5,%c7", 0},
+{0xbb19,0xbbf9,16,2, 11,ZBB_ssN0_1001_0000_rrrr_ddN0_x000, "lddr @%rw2,@%rw6,%rw5", DASMFLAG_STEP_OVER},
+{0xbb1a,0xbbfa,16,2, 11,ZBB_ssN0_1010_0000_rrrr_ddN0_cccc, "cpsd @%rw6,@%rw2,%rw5,%c7", 0},
+{0xbb1c,0xbbfc,16,2, 11,ZBB_ssN0_1100_0000_rrrr_dddd_cccc, "cpdr %rw6,@%rw2,%rw5,%c7", DASMFLAG_STEP_OVER},
+{0xbb1e,0xbbfe,16,2, 11,ZBB_ssN0_1110_0000_rrrr_ddN0_cccc, "cpsdr @%rw6,@%rw2,%rw5,%c7", DASMFLAG_STEP_OVER},
+{0xbc00,0xbcff, 1,1, 9,ZBC_aaaa_bbbb, "rrdb %rb3,%rb2", 0},
+{0xbd00,0xbdff, 1,1, 5,ZBD_dddd_imm4, "ldk %rw2,%3", 0},
+{0xbe00,0xbeff, 1,1, 9,ZBE_aaaa_bbbb, "rldb %rb3,%rb2", 0},
+{0xbf00,0xbfff, 1,1, 10,ZBF_imm8, "rsvdbf", 0},
+{0xc000,0xcfff, 1,1, 5,ZC_dddd_imm8, "ldb %rb1,%#b1", 0},
+{0xd000,0xdfff, 1,1, 10,ZD_dsp12, "calr %d2", DASMFLAG_STEP_OVER},
+{0xe000,0xefff, 1,1, 6,ZE_cccc_dsp8, "jr %c1,%d1", 0},
+{0xf000,0xf07f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xf100,0xf17f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xf200,0xf27f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xf300,0xf37f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xf400,0xf47f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xf500,0xf57f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xf600,0xf67f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xf700,0xf77f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xf800,0xf87f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xf900,0xf97f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xfa00,0xfa7f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xfb00,0xfb7f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xfc00,0xfc7f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xfd00,0xfd7f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xfe00,0xfe7f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xff00,0xff7f, 1,1, 11,ZF_dddd_0dsp7, "dbjnz %rb1,%d0", DASMFLAG_STEP_OVER},
+{0xf080,0xf0ff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xf180,0xf1ff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xf280,0xf2ff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xf380,0xf3ff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xf480,0xf4ff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xf580,0xf5ff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xf680,0xf6ff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xf780,0xf7ff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xf880,0xf8ff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xf980,0xf9ff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xfa80,0xfaff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xfb80,0xfbff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xfc80,0xfcff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xfd80,0xfdff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xfe80,0xfeff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0xff80,0xffff, 1,1, 11,ZF_dddd_1dsp7, "djnz %rw1,%d0", DASMFLAG_STEP_OVER},
+{0, 0, 0,0, 0,NULL, NULL, 0}
+};
+
+
+void z8001_init_tables(void)
+{
+ const Z8000_init *init;
+ int i;
+
+ /* allocate the opcode execution and disassembler array */
+ z8000_exec = global_alloc_array(Z8000_exec, 0x10000);
+
+ /* set up the zero, sign, parity lookup table */
+ for (i = 0; i < 256; i++)
+ z8000_zsp[i] = ((i == 0) ? F_Z : 0) |
+ ((i & 128) ? F_S : 0) |
+ ((((i>>7)^(i>>6)^(i>>5)^(i>>4)^(i>>3)^(i>>2)^(i>>1)^i) & 1) ? F_PV : 0);
+
+ /* first set all 64K opcodes to invalid */
+ for (i = 0; i < 0x10000; i++)
+ {
+ z8000_exec[i].opcode = zinvalid;
+ z8000_exec[i].cycles = 4;
+ z8000_exec[i].size = 1;
+ z8000_exec[i].dasm = ".word %#w0";
+ z8000_exec[i].dasmflags = 0;
+ }
+
+ /* now decompose the initialization table */
+ for (init = seg_table; init->size; init++)
+ {
+ for (i = init->beg; i <= init->end; i += init->step)
+ {
+ if (z8000_exec[i].opcode != zinvalid)
+ logerror("Z8000 opcode %04x clash '%s'\n", i, z8000_exec[i].dasm);
+
+ z8000_exec[i].opcode = init->opcode;
+ z8000_exec[i].cycles = init->cycles;
+ z8000_exec[i].size = init->size;
+ z8000_exec[i].dasm = init->dasm;
+ z8000_exec[i].dasmflags = init->dasmflags;
+ }
+ }
+}
+
+void z8002_init_tables(void)
+{
+ const Z8000_init *init;
+ int i;
+
+ /* allocate the opcode execution and disassembler array */
+ z8000_exec = global_alloc_array(Z8000_exec, 0x10000);
+
+ /* set up the zero, sign, parity lookup table */
+ for (i = 0; i < 256; i++)
+ z8000_zsp[i] = ((i == 0) ? F_Z : 0) |
+ ((i & 128) ? F_S : 0) |
+ ((((i>>7)^(i>>6)^(i>>5)^(i>>4)^(i>>3)^(i>>2)^(i>>1)^i) & 1) ? F_PV : 0);
+
+ /* first set all 64K opcodes to invalid */
+ for (i = 0; i < 0x10000; i++)
+ {
+ z8000_exec[i].opcode = zinvalid;
+ z8000_exec[i].cycles = 4;
+ z8000_exec[i].size = 1;
+ z8000_exec[i].dasm = ".word %#w0";
+ z8000_exec[i].dasmflags = 0;
+ }
+
+ /* now decompose the initialization table */
+ for (init = table; init->size; init++)
+ {
+ for (i = init->beg; i <= init->end; i += init->step)
+ {
+ if (z8000_exec[i].opcode != zinvalid)
+ logerror("Z8000 opcode %04x clash '%s'\n", i, z8000_exec[i].dasm);
+
+ z8000_exec[i].opcode = init->opcode;
+ z8000_exec[i].cycles = init->cycles;
+ z8000_exec[i].size = init->size;
+ z8000_exec[i].dasm = init->dasm;
+ z8000_exec[i].dasmflags = init->dasmflags;
+ }
+ }
+}
+
+void z8000_deinit_tables(void)
+{
+ global_free( z8000_exec );
+ z8000_exec = 0;
+}
+
diff --git a/trunk/src/emu/crsshair.c b/trunk/src/emu/crsshair.c
new file mode 100644
index 00000000000..40bd09a6445
--- /dev/null
+++ b/trunk/src/emu/crsshair.c
@@ -0,0 +1,532 @@
+/***************************************************************************
+
+ crsshair.c
+
+ Crosshair handling.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "emuopts.h"
+#include "rendutil.h"
+#include "config.h"
+#include "xmlfile.h"
+#include "crsshair.h"
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define CROSSHAIR_RAW_SIZE 100
+#define CROSSHAIR_RAW_ROWBYTES ((CROSSHAIR_RAW_SIZE + 7) / 8)
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _crosshair_global crosshair_global;
+struct _crosshair_global
+{
+ UINT8 usage; /* true if any crosshairs are used */
+ UINT8 used[MAX_PLAYERS]; /* usage per player */
+ UINT8 mode[MAX_PLAYERS]; /* visibility mode per player */
+ UINT8 visible[MAX_PLAYERS]; /* visibility per player */
+ bitmap_t * bitmap[MAX_PLAYERS]; /* bitmap per player */
+ render_texture * texture[MAX_PLAYERS]; /* texture per player */
+ device_t *screen[MAX_PLAYERS]; /* the screen on which this player's crosshair is drawn */
+ float x[MAX_PLAYERS]; /* current X position */
+ float y[MAX_PLAYERS]; /* current Y position */
+ float last_x[MAX_PLAYERS]; /* last X position */
+ float last_y[MAX_PLAYERS]; /* last Y position */
+ UINT8 fade; /* color fading factor */
+ UINT8 animation_counter; /* animation frame index */
+ UINT16 auto_time; /* time in seconds to turn invisible */
+ UINT16 time[MAX_PLAYERS]; /* time since last movement */
+ char name[MAX_PLAYERS][CROSSHAIR_PIC_NAME_LENGTH + 1]; /* name of crosshair png file */
+};
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+/* global state */
+static crosshair_global global;
+
+/* raw bitmap */
+static const UINT8 crosshair_raw_top[] =
+{
+ 0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,
+ 0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,
+ 0x00,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xf0,0x00,
+ 0x01,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xf8,0x00,
+ 0x03,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xfc,0x00,
+ 0x07,0xfe,0x00,0x00,0x00,0x0f,0xfe,0x00,0x00,0x00,0x07,0xfe,0x00,
+ 0x0f,0xff,0x00,0x00,0x01,0xff,0xff,0xf0,0x00,0x00,0x0f,0xff,0x00,
+ 0x1f,0xff,0x80,0x00,0x1f,0xff,0xff,0xff,0x00,0x00,0x1f,0xff,0x80,
+ 0x3f,0xff,0x80,0x00,0xff,0xff,0xff,0xff,0xe0,0x00,0x1f,0xff,0xc0,
+ 0x7f,0xff,0xc0,0x03,0xff,0xff,0xff,0xff,0xf8,0x00,0x3f,0xff,0xe0,
+ 0xff,0xff,0xe0,0x07,0xff,0xff,0xff,0xff,0xfc,0x00,0x7f,0xff,0xf0,
+ 0x7f,0xff,0xf0,0x1f,0xff,0xff,0xff,0xff,0xff,0x00,0xff,0xff,0xe0,
+ 0x3f,0xff,0xf8,0x7f,0xff,0xff,0xff,0xff,0xff,0xc1,0xff,0xff,0xc0,
+ 0x0f,0xff,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xe1,0xff,0xff,0x00,
+ 0x07,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfb,0xff,0xfe,0x00,
+ 0x03,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x00,
+ 0x01,0xff,0xff,0xff,0xff,0xf0,0x01,0xff,0xff,0xff,0xff,0xf8,0x00,
+ 0x00,0x7f,0xff,0xff,0xff,0x00,0x00,0x1f,0xff,0xff,0xff,0xe0,0x00,
+ 0x00,0x3f,0xff,0xff,0xf8,0x00,0x00,0x03,0xff,0xff,0xff,0xc0,0x00,
+ 0x00,0x1f,0xff,0xff,0xe0,0x00,0x00,0x00,0xff,0xff,0xff,0x80,0x00,
+ 0x00,0x0f,0xff,0xff,0x80,0x00,0x00,0x00,0x3f,0xff,0xff,0x00,0x00,
+ 0x00,0x03,0xff,0xfe,0x00,0x00,0x00,0x00,0x0f,0xff,0xfc,0x00,0x00,
+ 0x00,0x01,0xff,0xfc,0x00,0x00,0x00,0x00,0x07,0xff,0xf8,0x00,0x00,
+ 0x00,0x03,0xff,0xf8,0x00,0x00,0x00,0x00,0x01,0xff,0xf8,0x00,0x00,
+ 0x00,0x07,0xff,0xfc,0x00,0x00,0x00,0x00,0x03,0xff,0xfc,0x00,0x00,
+ 0x00,0x0f,0xff,0xfe,0x00,0x00,0x00,0x00,0x07,0xff,0xfe,0x00,0x00,
+ 0x00,0x0f,0xff,0xff,0x00,0x00,0x00,0x00,0x0f,0xff,0xfe,0x00,0x00,
+ 0x00,0x1f,0xff,0xff,0x80,0x00,0x00,0x00,0x1f,0xff,0xff,0x00,0x00,
+ 0x00,0x1f,0xff,0xff,0x80,0x00,0x00,0x00,0x1f,0xff,0xff,0x00,0x00,
+ 0x00,0x3f,0xfe,0xff,0xc0,0x00,0x00,0x00,0x3f,0xff,0xff,0x80,0x00,
+ 0x00,0x7f,0xfc,0x7f,0xe0,0x00,0x00,0x00,0x7f,0xe7,0xff,0xc0,0x00,
+ 0x00,0x7f,0xf8,0x3f,0xf0,0x00,0x00,0x00,0xff,0xc3,0xff,0xc0,0x00,
+ 0x00,0xff,0xf8,0x1f,0xf8,0x00,0x00,0x01,0xff,0x83,0xff,0xe0,0x00,
+ 0x00,0xff,0xf0,0x07,0xf8,0x00,0x00,0x01,0xfe,0x01,0xff,0xe0,0x00,
+ 0x00,0xff,0xf0,0x03,0xfc,0x00,0x00,0x03,0xfc,0x01,0xff,0xe0,0x00,
+ 0x01,0xff,0xe0,0x01,0xfe,0x00,0x00,0x07,0xf8,0x00,0xff,0xf0,0x00,
+ 0x01,0xff,0xe0,0x00,0xff,0x00,0x00,0x0f,0xf0,0x00,0xff,0xf0,0x00,
+ 0x01,0xff,0xc0,0x00,0x3f,0x80,0x00,0x1f,0xc0,0x00,0x7f,0xf0,0x00,
+ 0x01,0xff,0xc0,0x00,0x1f,0x80,0x00,0x1f,0x80,0x00,0x7f,0xf0,0x00,
+ 0x03,0xff,0xc0,0x00,0x0f,0xc0,0x00,0x3f,0x00,0x00,0x7f,0xf8,0x00,
+ 0x03,0xff,0x80,0x00,0x07,0xe0,0x00,0x7e,0x00,0x00,0x3f,0xf8,0x00,
+ 0x03,0xff,0x80,0x00,0x01,0xf0,0x00,0xf8,0x00,0x00,0x3f,0xf8,0x00,
+ 0x03,0xff,0x80,0x00,0x00,0xf8,0x01,0xf0,0x00,0x00,0x3f,0xf8,0x00,
+ 0x03,0xff,0x80,0x00,0x00,0x78,0x01,0xe0,0x00,0x00,0x3f,0xf8,0x00,
+ 0x07,0xff,0x00,0x00,0x00,0x3c,0x03,0xc0,0x00,0x00,0x3f,0xfc,0x00,
+ 0x07,0xff,0x00,0x00,0x00,0x0e,0x07,0x00,0x00,0x00,0x1f,0xfc,0x00,
+ 0x07,0xff,0x00,0x00,0x00,0x07,0x0e,0x00,0x00,0x00,0x1f,0xfc,0x00,
+ 0x07,0xff,0x00,0x00,0x00,0x03,0x9c,0x00,0x00,0x00,0x1f,0xfc,0x00,
+ 0x07,0xff,0x00,0x00,0x00,0x01,0x98,0x00,0x00,0x00,0x1f,0xfc,0x00,
+ 0x07,0xff,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x1f,0xfc,0x00
+};
+
+/* per-player colors */
+static const rgb_t crosshair_colors[] =
+{
+ MAKE_RGB(0x40,0x40,0xff),
+ MAKE_RGB(0xff,0x40,0x40),
+ MAKE_RGB(0x40,0xff,0x40),
+ MAKE_RGB(0xff,0xff,0x40),
+ MAKE_RGB(0xff,0x40,0xff),
+ MAKE_RGB(0x40,0xff,0xff),
+ MAKE_RGB(0xff,0xff,0xff)
+};
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void crosshair_exit(running_machine &machine);
+static void crosshair_load(running_machine &machine, int config_type, xml_data_node *parentnode);
+static void crosshair_save(running_machine &machine, int config_type, xml_data_node *parentnode);
+
+static void animate(running_machine &machine, screen_device &device, bool vblank_state);
+
+
+/***************************************************************************
+ CORE IMPLEMENTATION
+***************************************************************************/
+
+
+/*-------------------------------------------------
+ create_bitmap - create the rendering
+ structures for the given player
+-------------------------------------------------*/
+
+static void create_bitmap(running_machine &machine, int player)
+{
+ int x, y;
+ char filename[20];
+ rgb_t color = crosshair_colors[player];
+
+ /* if we have a bitmap and texture for this player, kill it */
+ global_free(global.bitmap[player]);
+ machine.render().texture_free(global.texture[player]);
+
+ emu_file crossfile(machine.options().crosshair_path(), OPEN_FLAG_READ);
+ if (global.name[player][0] != 0)
+ {
+ /* look for user specified file */
+ sprintf(filename, "%s.png", global.name[player]);
+ global.bitmap[player] = render_load_png(crossfile, NULL, filename, NULL, NULL);
+ }
+ else
+ {
+ /* look for default cross?.png in crsshair\game dir */
+ sprintf(filename, "cross%d.png", player + 1);
+ global.bitmap[player] = render_load_png(crossfile, machine.system().name, filename, NULL, NULL);
+
+ /* look for default cross?.png in crsshair dir */
+ if (global.bitmap[player] == NULL)
+ global.bitmap[player] = render_load_png(crossfile, NULL, filename, NULL, NULL);
+ }
+
+ /* if that didn't work, use the built-in one */
+ if (global.bitmap[player] == NULL)
+ {
+ /* allocate a blank bitmap to start with */
+ global.bitmap[player] = global_alloc(bitmap_t(CROSSHAIR_RAW_SIZE, CROSSHAIR_RAW_SIZE, BITMAP_FORMAT_ARGB32));
+ bitmap_fill(global.bitmap[player], NULL, MAKE_ARGB(0x00,0xff,0xff,0xff));
+
+ /* extract the raw source data to it */
+ for (y = 0; y < CROSSHAIR_RAW_SIZE / 2; y++)
+ {
+ /* assume it is mirrored vertically */
+ UINT32 *dest0 = BITMAP_ADDR32(global.bitmap[player], y, 0);
+ UINT32 *dest1 = BITMAP_ADDR32(global.bitmap[player], CROSSHAIR_RAW_SIZE - 1 - y, 0);
+
+ /* extract to two rows simultaneously */
+ for (x = 0; x < CROSSHAIR_RAW_SIZE; x++)
+ if ((crosshair_raw_top[y * CROSSHAIR_RAW_ROWBYTES + x / 8] << (x % 8)) & 0x80)
+ dest0[x] = dest1[x] = MAKE_ARGB(0xff,0x00,0x00,0x00) | color;
+ }
+ }
+
+ /* create a texture to reference the bitmap */
+ global.texture[player] = machine.render().texture_alloc(render_texture::hq_scale);
+ global.texture[player]->set_bitmap(global.bitmap[player], NULL, TEXFORMAT_ARGB32);
+}
+
+
+/*-------------------------------------------------
+ crosshair_init - initialize the crosshair
+ bitmaps and such
+-------------------------------------------------*/
+
+void crosshair_init(running_machine &machine)
+{
+ /* request a callback upon exiting */
+ machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(crosshair_exit), &machine));
+
+ /* clear all the globals */
+ memset(&global, 0, sizeof(global));
+
+ /* setup the default auto visibility time */
+ global.auto_time = CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT;
+
+ /* determine who needs crosshairs */
+ for (input_port_config *port = machine.m_portlist.first(); port != NULL; port = port->next())
+ for (input_field_config *field = port->fieldlist().first(); field != NULL; field = field->next())
+ if (field->crossaxis != CROSSHAIR_AXIS_NONE)
+ {
+ int player = field->player;
+
+ assert(player < MAX_PLAYERS);
+
+ /* mark as used and set the default visibility and mode */
+ global.usage = TRUE;
+ global.used[player] = TRUE;
+ global.mode[player] = CROSSHAIR_VISIBILITY_DEFAULT;
+ global.visible[player] = (CROSSHAIR_VISIBILITY_DEFAULT == CROSSHAIR_VISIBILITY_OFF) ? FALSE : TRUE;
+
+ /* for now, use the main screen */
+ global.screen[player] = machine.primary_screen;
+
+ create_bitmap(machine, player);
+ }
+
+ /* register callbacks for when we load/save configurations */
+ if (global.usage)
+ config_register(machine, "crosshairs", config_saveload_delegate(FUNC(crosshair_load), &machine), config_saveload_delegate(FUNC(crosshair_save), &machine));
+
+ /* register the animation callback */
+ if (machine.primary_screen != NULL)
+ machine.primary_screen->register_vblank_callback(vblank_state_delegate(FUNC(animate), &machine));
+}
+
+
+/*-------------------------------------------------
+ crosshair_exit - free memory allocated for
+ the crosshairs
+-------------------------------------------------*/
+
+static void crosshair_exit(running_machine &machine)
+{
+ /* free bitmaps and textures for each player */
+ for (int player = 0; player < MAX_PLAYERS; player++)
+ {
+ machine.render().texture_free(global.texture[player]);
+ global.texture[player] = NULL;
+
+ global_free(global.bitmap[player]);
+ global.bitmap[player] = NULL;
+ }
+}
+
+
+/*-------------------------------------------------
+ crosshair_get_usage - return TRUE
+ if any crosshairs are used
+-------------------------------------------------*/
+
+int crosshair_get_usage(running_machine &machine)
+{
+ return global.usage;
+}
+
+
+/*-------------------------------------------------
+ crosshair_get_user_settings - return the
+ current crosshair settings for a player
+ Note: auto_time is common for all players
+-------------------------------------------------*/
+
+void crosshair_get_user_settings(running_machine &machine, UINT8 player, crosshair_user_settings *settings)
+{
+ settings->auto_time = global.auto_time;
+ settings->used = global.used[player];
+ settings->mode = global.mode[player];
+ strcpy(settings->name, global.name[player]);
+}
+
+
+/*-------------------------------------------------
+ crosshair_set_user_settings - modify the
+ current crosshair settings for a player
+ Note: auto_time is common for all players
+-------------------------------------------------*/
+
+void crosshair_set_user_settings(running_machine &machine, UINT8 player, crosshair_user_settings *settings)
+{
+ int changed = FALSE;
+
+ global.auto_time = settings->auto_time;
+ global.used[player] = settings->used;
+ global.mode[player] = settings->mode;
+
+ /* set visibility as specified by mode */
+ /* auto mode starts with visibility off */
+ global.visible[player] = (settings->mode == CROSSHAIR_VISIBILITY_ON) ? TRUE : FALSE;
+
+ /* update bitmap if name has changed */
+ changed = strcmp(settings->name, global.name[player]);
+ strcpy(global.name[player], settings->name);
+ if (changed)
+ create_bitmap(machine, player);
+}
+
+
+/*-------------------------------------------------
+ animate - animates the crosshair once a frame
+-------------------------------------------------*/
+
+static void animate(running_machine &machine, screen_device &device, bool vblank_state)
+{
+ int player;
+
+ /* only animate once per frame, when vblank_state is 1 */
+ if (!vblank_state)
+ return;
+
+ /* increment animation counter */
+ global.animation_counter += 0x08;
+
+ /* compute a fade factor from the current animation value */
+ if (global.animation_counter < 0x80)
+ global.fade = 0xa0 + (0x60 * ( global.animation_counter & 0x7f) / 0x80);
+ else
+ global.fade = 0xa0 + (0x60 * (~global.animation_counter & 0x7f) / 0x80);
+
+ for (player = 0; player < MAX_PLAYERS; player++)
+ {
+ /* read all the lightgun values */
+ if (global.used[player])
+ input_port_get_crosshair_position(device.machine(), player, &global.x[player], &global.y[player]);
+
+ /* auto visibility */
+ if (global.mode[player] == CROSSHAIR_VISIBILITY_AUTO)
+ {
+ if ((global.x[player] != global.last_x[player]) || (global.y[player] != global.last_y[player]))
+ {
+ /* crosshair has moved, keep crosshair visible */
+ global.visible[player] = TRUE;
+ global.last_x[player] = global.x[player];
+ global.last_y[player] = global.y[player];
+ global.time[player] = 0;
+ }
+ else
+ {
+ /* see if the player has been motionless for time specified */
+ /* slightly confusing formula, but the effect is: */
+ /* auto_time = 0 makes the crosshair barely visible while moved */
+ /* every increment in auto_time is about .2s at 60Hz */
+ if (global.time[player] > global.auto_time * 12 + 2)
+ /* time exceeded so turn crosshair invisible */
+ global.visible[player] = FALSE;
+
+ /* increment player visibility time */
+ global.time[player]++;
+ }
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ crosshair_render - render the crosshairs
+ for the given screen
+-------------------------------------------------*/
+
+void crosshair_render(screen_device &screen)
+{
+ int player;
+
+ for (player = 0; player < MAX_PLAYERS; player++)
+ /* draw if visible and the right screen */
+ if (global.visible[player] &&
+ ((global.screen[player] == &screen) || (global.screen[player] == CROSSHAIR_SCREEN_ALL)))
+ {
+ /* add a quad assuming a 4:3 screen (this is not perfect) */
+ screen.container().add_quad(global.x[player] - 0.03f, global.y[player] - 0.04f,
+ global.x[player] + 0.03f, global.y[player] + 0.04f,
+ MAKE_ARGB(0xc0, global.fade, global.fade, global.fade),
+ global.texture[player], PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ }
+}
+
+
+/*-------------------------------------------------
+ crosshair_set_screen - sets the screen(s) for a
+ given player's crosshair
+-------------------------------------------------*/
+
+void crosshair_set_screen(running_machine &machine, int player, device_t *screen)
+{
+ global.screen[player] = screen;
+}
+
+
+/*-------------------------------------------------
+ crosshair_load - read and apply data from the
+ configuration file
+-------------------------------------------------*/
+
+static void crosshair_load(running_machine &machine, int config_type, xml_data_node *parentnode)
+{
+ /* Note: crosshair_load() is only registered if croshairs are used */
+
+ xml_data_node *crosshairnode;
+ int auto_time;
+
+ /* we only care about game files */
+ if (config_type != CONFIG_TYPE_GAME)
+ return;
+
+ /* might not have any data */
+ if (parentnode == NULL)
+ return;
+
+ /* loop and get player crosshair info */
+ for (crosshairnode = xml_get_sibling(parentnode->child, "crosshair"); crosshairnode; crosshairnode = xml_get_sibling(crosshairnode->next, "crosshair"))
+ {
+ int player, mode;
+
+ player = xml_get_attribute_int(crosshairnode, "player", -1);
+
+ /* check to make sure we have a valid player */
+ /* also check if the player really uses a crosshair */
+ if (player >=0 && player < MAX_PLAYERS && global.used[player])
+ {
+ /* get, check, and store visibility mode */
+ mode = xml_get_attribute_int(crosshairnode, "mode", CROSSHAIR_VISIBILITY_DEFAULT);
+ if (mode >= CROSSHAIR_VISIBILITY_OFF && mode <= CROSSHAIR_VISIBILITY_AUTO)
+ {
+ global.mode[player] = (UINT8)mode;
+ /* set visibility as specified by mode */
+ /* auto mode starts with visibility off */
+ global.visible[player] = (mode == CROSSHAIR_VISIBILITY_ON) ? TRUE : FALSE;
+ }
+
+ /* get and store crosshair pic name, truncate name to max length */
+ strncpy(global.name[player], xml_get_attribute_string(crosshairnode, "pic", ""), CROSSHAIR_PIC_NAME_LENGTH);
+ /* update bitmap */
+ create_bitmap(machine, player);
+ }
+ }
+
+ /* get, check, and store auto visibility time */
+ crosshairnode = xml_get_sibling(parentnode->child, "autotime");
+ if (crosshairnode != NULL)
+ {
+ auto_time = xml_get_attribute_int(crosshairnode, "val", CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT);
+ if ((auto_time >= CROSSHAIR_VISIBILITY_AUTOTIME_MIN) && (auto_time <= CROSSHAIR_VISIBILITY_AUTOTIME_MAX))
+ global.auto_time = (UINT8)auto_time;
+ }
+}
+
+
+/*-------------------------------------------------
+ crosshair_save - save data to the
+ configuration file
+-------------------------------------------------*/
+
+static void crosshair_save(running_machine &machine, int config_type, xml_data_node *parentnode)
+{
+ /* Note: crosshair_save() is only registered if crosshairs are used */
+
+ xml_data_node *crosshairnode;
+ int player;
+
+ /* we only care about game files */
+ if (config_type != CONFIG_TYPE_GAME)
+ return;
+
+ for (player = 0; player < MAX_PLAYERS; player++)
+ {
+ if (global.used[player])
+ {
+ /* create a node */
+ crosshairnode = xml_add_child(parentnode, "crosshair", NULL);
+
+ if (crosshairnode != NULL)
+ {
+ int changed = FALSE;
+
+ xml_set_attribute_int(crosshairnode, "player", player);
+
+ if (global.visible[player] != CROSSHAIR_VISIBILITY_DEFAULT)
+ {
+ xml_set_attribute_int(crosshairnode, "mode", global.mode[player]);
+ changed = TRUE;
+ }
+
+ /* the default graphic name is "", so only save if not */
+ if (strlen(global.name[player]) > 0)
+ {
+ xml_set_attribute(crosshairnode, "pic", global.name[player]);
+ changed = TRUE;
+ }
+
+ /* if nothing changed, kill the node */
+ if (!changed)
+ xml_delete_node(crosshairnode);
+ }
+ }
+ }
+
+ /* always store autotime so that it stays at the user value if it is needed */
+ if (global.auto_time != CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT)
+ {
+ /* create a node */
+ crosshairnode = xml_add_child(parentnode, "autotime", NULL);
+
+ if (crosshairnode != NULL)
+ xml_set_attribute_int(crosshairnode, "val", global.auto_time);
+ }
+
+}
diff --git a/trunk/src/emu/crsshair.h b/trunk/src/emu/crsshair.h
new file mode 100644
index 00000000000..244f05593db
--- /dev/null
+++ b/trunk/src/emu/crsshair.h
@@ -0,0 +1,80 @@
+/***************************************************************************
+
+ crsshair.h
+
+ Crosshair handling.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __CRSSHAIR_H__
+#define __CRSSHAIR_H__
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define CROSSHAIR_SCREEN_NONE ((device_t *) 0)
+#define CROSSHAIR_SCREEN_ALL ((device_t *) ~0)
+
+/* user settings for visibility mode */
+#define CROSSHAIR_VISIBILITY_OFF 0
+#define CROSSHAIR_VISIBILITY_ON 1
+#define CROSSHAIR_VISIBILITY_AUTO 2
+#define CROSSHAIR_VISIBILITY_DEFAULT CROSSHAIR_VISIBILITY_AUTO
+
+/* range allowed for auto visibility */
+#define CROSSHAIR_VISIBILITY_AUTOTIME_MIN 0
+#define CROSSHAIR_VISIBILITY_AUTOTIME_MAX 50
+#define CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT 15
+
+/* maximum crosshair pic filename size */
+#define CROSSHAIR_PIC_NAME_LENGTH 12
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/* user-controllable settings for a player */
+typedef struct _crosshair_user_settings crosshair_user_settings;
+struct _crosshair_user_settings
+{
+ UINT8 used; /* is used */
+ UINT8 mode; /* visibility mode */
+ UINT8 auto_time; /* time in seconds to blank crosshair if no movement */
+ char name[CROSSHAIR_PIC_NAME_LENGTH + 1]; /* bitmap name */
+};
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+/* initializes the crosshair system */
+void crosshair_init(running_machine &machine);
+
+/* draws crosshair(s) in a given screen, if necessary */
+void crosshair_render(screen_device &screen);
+
+/* sets the screen(s) for a given player's crosshair */
+void crosshair_set_screen(running_machine &machine, int player, device_t *screen);
+
+/* return TRUE if any crosshairs are used */
+int crosshair_get_usage(running_machine &machine);
+
+/* return the current crosshair settings for the given player */
+void crosshair_get_user_settings(running_machine &machine, UINT8 player, crosshair_user_settings *settings);
+
+/* modify the current crosshair settings for the given player */
+void crosshair_set_user_settings(running_machine &machine, UINT8 player, crosshair_user_settings *settings);
+
+
+#endif /* __CRSSHAIR_H__ */
diff --git a/trunk/src/emu/debug/debugcmd.c b/trunk/src/emu/debug/debugcmd.c
new file mode 100644
index 00000000000..5f5606f1968
--- /dev/null
+++ b/trunk/src/emu/debug/debugcmd.c
@@ -0,0 +1,2738 @@
+/*********************************************************************
+
+ debugcmd.c
+
+ Debugger command interface engine.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "emuopts.h"
+#include "debugcmd.h"
+#include "debugcon.h"
+#include "debugcpu.h"
+#include "express.h"
+#include "debughlp.h"
+#include "debugvw.h"
+#include "render.h"
+#include <ctype.h>
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define MAX_GLOBALS 1000
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _global_entry global_entry;
+struct _global_entry
+{
+ void * base;
+ UINT32 size;
+};
+
+
+typedef struct _cheat_map cheat_map;
+struct _cheat_map
+{
+ UINT64 offset;
+ UINT64 first_value;
+ UINT64 previous_value;
+ UINT8 state:1;
+ UINT8 undo:7;
+};
+
+
+typedef struct _cheat_system cheat_system;
+struct _cheat_system
+{
+ char cpu;
+ UINT64 length;
+ UINT8 width;
+ cheat_map * cheatmap;
+ UINT8 undo;
+ UINT8 signed_cheat;
+ UINT8 swapped_cheat;
+};
+
+
+typedef struct _cheat_region_map cheat_region_map;
+struct _cheat_region_map
+{
+ UINT64 offset;
+ UINT64 endoffset;
+ const char *share;
+ UINT8 disabled;
+};
+
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+static global_entry global_array[MAX_GLOBALS];
+static cheat_system cheat;
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void debug_command_exit(running_machine &machine);
+
+static UINT64 execute_min(symbol_table &table, void *ref, int params, const UINT64 *param);
+static UINT64 execute_max(symbol_table &table, void *ref, int params, const UINT64 *param);
+static UINT64 execute_if(symbol_table &table, void *ref, int params, const UINT64 *param);
+
+static UINT64 global_get(symbol_table &table, void *ref);
+static void global_set(symbol_table &table, void *ref, UINT64 value);
+
+static void execute_help(running_machine &machine, int ref, int params, const char **param);
+static void execute_print(running_machine &machine, int ref, int params, const char **param);
+static void execute_printf(running_machine &machine, int ref, int params, const char **param);
+static void execute_logerror(running_machine &machine, int ref, int params, const char **param);
+static void execute_tracelog(running_machine &machine, int ref, int params, const char **param);
+static void execute_quit(running_machine &machine, int ref, int params, const char **param);
+static void execute_do(running_machine &machine, int ref, int params, const char **param);
+static void execute_step(running_machine &machine, int ref, int params, const char **param);
+static void execute_over(running_machine &machine, int ref, int params, const char **param);
+static void execute_out(running_machine &machine, int ref, int params, const char **param);
+static void execute_go(running_machine &machine, int ref, int params, const char **param);
+static void execute_go_vblank(running_machine &machine, int ref, int params, const char **param);
+static void execute_go_interrupt(running_machine &machine, int ref, int params, const char **param);
+static void execute_go_time(running_machine &machine, int ref, int params, const char *param[]);
+static void execute_focus(running_machine &machine, int ref, int params, const char **param);
+static void execute_ignore(running_machine &machine, int ref, int params, const char **param);
+static void execute_observe(running_machine &machine, int ref, int params, const char **param);
+static void execute_next(running_machine &machine, int ref, int params, const char **param);
+static void execute_comment(running_machine &machine, int ref, int params, const char **param);
+static void execute_comment_del(running_machine &machine, int ref, int params, const char **param);
+static void execute_comment_save(running_machine &machine, int ref, int params, const char **param);
+static void execute_bpset(running_machine &machine, int ref, int params, const char **param);
+static void execute_bpclear(running_machine &machine, int ref, int params, const char **param);
+static void execute_bpdisenable(running_machine &machine, int ref, int params, const char **param);
+static void execute_bplist(running_machine &machine, int ref, int params, const char **param);
+static void execute_wpset(running_machine &machine, int ref, int params, const char **param);
+static void execute_wpclear(running_machine &machine, int ref, int params, const char **param);
+static void execute_wpdisenable(running_machine &machine, int ref, int params, const char **param);
+static void execute_wplist(running_machine &machine, int ref, int params, const char **param);
+static void execute_hotspot(running_machine &machine, int ref, int params, const char **param);
+static void execute_save(running_machine &machine, int ref, int params, const char **param);
+static void execute_load(running_machine &machine, int ref, int params, const char **param);
+static void execute_dump(running_machine &machine, int ref, int params, const char **param);
+static void execute_cheatinit(running_machine &machine, int ref, int params, const char **param);
+static void execute_cheatnext(running_machine &machine, int ref, int params, const char **param);
+static void execute_cheatlist(running_machine &machine, int ref, int params, const char **param);
+static void execute_cheatundo(running_machine &machine, int ref, int params, const char **param);
+static void execute_dasm(running_machine &machine, int ref, int params, const char **param);
+static void execute_find(running_machine &machine, int ref, int params, const char **param);
+static void execute_trace(running_machine &machine, int ref, int params, const char **param);
+static void execute_traceover(running_machine &machine, int ref, int params, const char **param);
+static void execute_traceflush(running_machine &machine, int ref, int params, const char **param);
+static void execute_history(running_machine &machine, int ref, int params, const char **param);
+static void execute_snap(running_machine &machine, int ref, int params, const char **param);
+static void execute_source(running_machine &machine, int ref, int params, const char **param);
+static void execute_map(running_machine &machine, int ref, int params, const char **param);
+static void execute_memdump(running_machine &machine, int ref, int params, const char **param);
+static void execute_symlist(running_machine &machine, int ref, int params, const char **param);
+static void execute_softreset(running_machine &machine, int ref, int params, const char **param);
+static void execute_hardreset(running_machine &machine, int ref, int params, const char **param);
+static void execute_images(running_machine &machine, int ref, int params, const char **param);
+static void execute_mount(running_machine &machine, int ref, int params, const char **param);
+static void execute_unmount(running_machine &machine, int ref, int params, const char **param);
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ cheat_address_is_valid - return TRUE if the
+ given address is valid for cheating
+-------------------------------------------------*/
+
+INLINE int cheat_address_is_valid(address_space *space, offs_t address)
+{
+ return debug_cpu_translate(space, TRANSLATE_READ, &address) && (space->get_write_ptr(address) != NULL);
+}
+
+
+/*-------------------------------------------------
+ cheat_sign_extend - sign-extend a value to
+ the current cheat width, if signed
+-------------------------------------------------*/
+
+INLINE UINT64 cheat_sign_extend(const cheat_system *cheatsys, UINT64 value)
+{
+ if (cheatsys->signed_cheat)
+ {
+ switch (cheatsys->width)
+ {
+ case 1: value = (INT8)value; break;
+ case 2: value = (INT16)value; break;
+ case 4: value = (INT32)value; break;
+ }
+ }
+ return value;
+}
+/*-------------------------------------------------
+ cheat_byte_swap - swap a value
+-------------------------------------------------*/
+
+INLINE UINT64 cheat_byte_swap(const cheat_system *cheatsys, UINT64 value)
+{
+ if (cheatsys->swapped_cheat)
+ {
+ switch (cheatsys->width)
+ {
+ case 2: value = ((value >> 8) & 0x00ff) | ((value << 8) & 0xff00); break;
+ case 4: value = ((value >> 24) & 0x000000ff) | ((value >> 8) & 0x0000ff00) | ((value << 8) & 0x00ff0000) | ((value << 24) & 0xff000000); break;
+ case 8: value = ((value >> 56) & U64(0x00000000000000ff)) | ((value >> 40) & U64(0x000000000000ff00)) | ((value >> 24) & U64(0x0000000000ff0000)) | ((value >> 8) & U64(0x00000000ff000000)) |
+ ((value << 8) & U64(0x000000ff00000000)) | ((value << 24) & U64(0x0000ff0000000000)) | ((value << 40) & U64(0x00ff000000000000)) | ((value << 56) & U64(0xff00000000000000)); break;
+ }
+ }
+ return value;
+}
+
+/*-------------------------------------------------
+ cheat_read_extended - read a value from memory
+ in the given address space, sign-extending
+ and swapping if necessary
+-------------------------------------------------*/
+
+INLINE UINT64 cheat_read_extended(const cheat_system *cheatsys, address_space *space, offs_t address)
+{
+ return cheat_sign_extend(cheatsys, cheat_byte_swap(cheatsys, debug_read_memory(space, address, cheatsys->width, TRUE)));
+}
+
+
+
+/***************************************************************************
+ INITIALIZATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ debug_command_init - initializes the command
+ system
+-------------------------------------------------*/
+
+void debug_command_init(running_machine &machine)
+{
+ symbol_table *symtable = debug_cpu_get_global_symtable(machine);
+ const char *name;
+ int itemnum;
+
+ /* add a few simple global functions */
+ symtable->add("min", NULL, 2, 2, execute_min);
+ symtable->add("max", NULL, 2, 2, execute_max);
+ symtable->add("if", NULL, 3, 3, execute_if);
+
+ /* add all single-entry save state globals */
+ for (itemnum = 0; itemnum < MAX_GLOBALS; itemnum++)
+ {
+ UINT32 valsize, valcount;
+ void *base;
+
+ /* stop when we run out of items */
+ name = machine.save().indexed_item(itemnum, base, valsize, valcount);
+ if (name == NULL)
+ break;
+
+ /* if this is a single-entry global, add it */
+ if (valcount == 1 && strstr(name, "/globals/"))
+ {
+ char symname[100];
+ sprintf(symname, ".%s", strrchr(name, '/') + 1);
+ global_array[itemnum].base = base;
+ global_array[itemnum].size = valsize;
+ symtable->add(symname, &global_array, global_get, global_set);
+ }
+ }
+
+ /* add all the commands */
+ debug_console_register_command(machine, "help", CMDFLAG_NONE, 0, 0, 1, execute_help);
+ debug_console_register_command(machine, "print", CMDFLAG_NONE, 0, 1, MAX_COMMAND_PARAMS, execute_print);
+ debug_console_register_command(machine, "printf", CMDFLAG_NONE, 0, 1, MAX_COMMAND_PARAMS, execute_printf);
+ debug_console_register_command(machine, "logerror", CMDFLAG_NONE, 0, 1, MAX_COMMAND_PARAMS, execute_logerror);
+ debug_console_register_command(machine, "tracelog", CMDFLAG_NONE, 0, 1, MAX_COMMAND_PARAMS, execute_tracelog);
+ debug_console_register_command(machine, "quit", CMDFLAG_NONE, 0, 0, 0, execute_quit);
+ debug_console_register_command(machine, "do", CMDFLAG_NONE, 0, 1, 1, execute_do);
+ debug_console_register_command(machine, "step", CMDFLAG_NONE, 0, 0, 1, execute_step);
+ debug_console_register_command(machine, "s", CMDFLAG_NONE, 0, 0, 1, execute_step);
+ debug_console_register_command(machine, "over", CMDFLAG_NONE, 0, 0, 1, execute_over);
+ debug_console_register_command(machine, "o", CMDFLAG_NONE, 0, 0, 1, execute_over);
+ debug_console_register_command(machine, "out" , CMDFLAG_NONE, 0, 0, 0, execute_out);
+ debug_console_register_command(machine, "go", CMDFLAG_NONE, 0, 0, 1, execute_go);
+ debug_console_register_command(machine, "g", CMDFLAG_NONE, 0, 0, 1, execute_go);
+ debug_console_register_command(machine, "gvblank", CMDFLAG_NONE, 0, 0, 0, execute_go_vblank);
+ debug_console_register_command(machine, "gv", CMDFLAG_NONE, 0, 0, 0, execute_go_vblank);
+ debug_console_register_command(machine, "gint", CMDFLAG_NONE, 0, 0, 1, execute_go_interrupt);
+ debug_console_register_command(machine, "gi", CMDFLAG_NONE, 0, 0, 1, execute_go_interrupt);
+ debug_console_register_command(machine, "gtime", CMDFLAG_NONE, 0, 0, 1, execute_go_time);
+ debug_console_register_command(machine, "gt", CMDFLAG_NONE, 0, 0, 1, execute_go_time);
+ debug_console_register_command(machine, "next", CMDFLAG_NONE, 0, 0, 0, execute_next);
+ debug_console_register_command(machine, "n", CMDFLAG_NONE, 0, 0, 0, execute_next);
+ debug_console_register_command(machine, "focus", CMDFLAG_NONE, 0, 1, 1, execute_focus);
+ debug_console_register_command(machine, "ignore", CMDFLAG_NONE, 0, 0, MAX_COMMAND_PARAMS, execute_ignore);
+ debug_console_register_command(machine, "observe", CMDFLAG_NONE, 0, 0, MAX_COMMAND_PARAMS, execute_observe);
+
+ debug_console_register_command(machine, "comadd", CMDFLAG_NONE, 0, 1, 2, execute_comment);
+ debug_console_register_command(machine, "//", CMDFLAG_NONE, 0, 1, 2, execute_comment);
+ debug_console_register_command(machine, "comdelete", CMDFLAG_NONE, 0, 1, 1, execute_comment_del);
+ debug_console_register_command(machine, "comsave", CMDFLAG_NONE, 0, 0, 0, execute_comment_save);
+
+ debug_console_register_command(machine, "bpset", CMDFLAG_NONE, 0, 1, 3, execute_bpset);
+ debug_console_register_command(machine, "bp", CMDFLAG_NONE, 0, 1, 3, execute_bpset);
+ debug_console_register_command(machine, "bpclear", CMDFLAG_NONE, 0, 0, 1, execute_bpclear);
+ debug_console_register_command(machine, "bpdisable", CMDFLAG_NONE, 0, 0, 1, execute_bpdisenable);
+ debug_console_register_command(machine, "bpenable", CMDFLAG_NONE, 1, 0, 1, execute_bpdisenable);
+ debug_console_register_command(machine, "bplist", CMDFLAG_NONE, 0, 0, 0, execute_bplist);
+
+ debug_console_register_command(machine, "wpset", CMDFLAG_NONE, AS_PROGRAM, 3, 5, execute_wpset);
+ debug_console_register_command(machine, "wp", CMDFLAG_NONE, AS_PROGRAM, 3, 5, execute_wpset);
+ debug_console_register_command(machine, "wpdset", CMDFLAG_NONE, AS_DATA, 3, 5, execute_wpset);
+ debug_console_register_command(machine, "wpd", CMDFLAG_NONE, AS_DATA, 3, 5, execute_wpset);
+ debug_console_register_command(machine, "wpiset", CMDFLAG_NONE, AS_IO, 3, 5, execute_wpset);
+ debug_console_register_command(machine, "wpi", CMDFLAG_NONE, AS_IO, 3, 5, execute_wpset);
+ debug_console_register_command(machine, "wpclear", CMDFLAG_NONE, 0, 0, 1, execute_wpclear);
+ debug_console_register_command(machine, "wpdisable", CMDFLAG_NONE, 0, 0, 1, execute_wpdisenable);
+ debug_console_register_command(machine, "wpenable", CMDFLAG_NONE, 1, 0, 1, execute_wpdisenable);
+ debug_console_register_command(machine, "wplist", CMDFLAG_NONE, 0, 0, 0, execute_wplist);
+
+ debug_console_register_command(machine, "hotspot", CMDFLAG_NONE, 0, 0, 3, execute_hotspot);
+
+ debug_console_register_command(machine, "save", CMDFLAG_NONE, AS_PROGRAM, 3, 4, execute_save);
+ debug_console_register_command(machine, "saved", CMDFLAG_NONE, AS_DATA, 3, 4, execute_save);
+ debug_console_register_command(machine, "savei", CMDFLAG_NONE, AS_IO, 3, 4, execute_save);
+
+ debug_console_register_command(machine, "load", CMDFLAG_NONE, AS_PROGRAM, 3, 4, execute_load);
+ debug_console_register_command(machine, "loadd", CMDFLAG_NONE, AS_DATA, 3, 4, execute_load);
+ debug_console_register_command(machine, "loadi", CMDFLAG_NONE, AS_IO, 3, 4, execute_load);
+
+ debug_console_register_command(machine, "dump", CMDFLAG_NONE, AS_PROGRAM, 3, 6, execute_dump);
+ debug_console_register_command(machine, "dumpd", CMDFLAG_NONE, AS_DATA, 3, 6, execute_dump);
+ debug_console_register_command(machine, "dumpi", CMDFLAG_NONE, AS_IO, 3, 6, execute_dump);
+
+ debug_console_register_command(machine, "cheatinit", CMDFLAG_NONE, 0, 0, 4, execute_cheatinit);
+ debug_console_register_command(machine, "ci", CMDFLAG_NONE, 0, 0, 4, execute_cheatinit);
+
+ debug_console_register_command(machine, "cheatrange",CMDFLAG_NONE, 1, 2, 2, execute_cheatinit);
+ debug_console_register_command(machine, "cr", CMDFLAG_NONE, 1, 2, 2, execute_cheatinit);
+
+ debug_console_register_command(machine, "cheatnext", CMDFLAG_NONE, 0, 1, 2, execute_cheatnext);
+ debug_console_register_command(machine, "cn", CMDFLAG_NONE, 0, 1, 2, execute_cheatnext);
+ debug_console_register_command(machine, "cheatnextf",CMDFLAG_NONE, 1, 1, 2, execute_cheatnext);
+ debug_console_register_command(machine, "cnf", CMDFLAG_NONE, 1, 1, 2, execute_cheatnext);
+
+ debug_console_register_command(machine, "cheatlist", CMDFLAG_NONE, 0, 0, 1, execute_cheatlist);
+ debug_console_register_command(machine, "cl", CMDFLAG_NONE, 0, 0, 1, execute_cheatlist);
+
+ debug_console_register_command(machine, "cheatundo", CMDFLAG_NONE, 0, 0, 0, execute_cheatundo);
+ debug_console_register_command(machine, "cu", CMDFLAG_NONE, 0, 0, 0, execute_cheatundo);
+
+ debug_console_register_command(machine, "f", CMDFLAG_KEEP_QUOTES, AS_PROGRAM, 3, MAX_COMMAND_PARAMS, execute_find);
+ debug_console_register_command(machine, "find", CMDFLAG_KEEP_QUOTES, AS_PROGRAM, 3, MAX_COMMAND_PARAMS, execute_find);
+ debug_console_register_command(machine, "fd", CMDFLAG_KEEP_QUOTES, AS_DATA, 3, MAX_COMMAND_PARAMS, execute_find);
+ debug_console_register_command(machine, "findd", CMDFLAG_KEEP_QUOTES, AS_DATA, 3, MAX_COMMAND_PARAMS, execute_find);
+ debug_console_register_command(machine, "fi", CMDFLAG_KEEP_QUOTES, AS_IO, 3, MAX_COMMAND_PARAMS, execute_find);
+ debug_console_register_command(machine, "findi", CMDFLAG_KEEP_QUOTES, AS_IO, 3, MAX_COMMAND_PARAMS, execute_find);
+
+ debug_console_register_command(machine, "dasm", CMDFLAG_NONE, 0, 3, 5, execute_dasm);
+
+ debug_console_register_command(machine, "trace", CMDFLAG_NONE, 0, 1, 3, execute_trace);
+ debug_console_register_command(machine, "traceover", CMDFLAG_NONE, 0, 1, 3, execute_traceover);
+ debug_console_register_command(machine, "traceflush",CMDFLAG_NONE, 0, 0, 0, execute_traceflush);
+
+ debug_console_register_command(machine, "history", CMDFLAG_NONE, 0, 0, 2, execute_history);
+
+ debug_console_register_command(machine, "snap", CMDFLAG_NONE, 0, 0, 1, execute_snap);
+
+ debug_console_register_command(machine, "source", CMDFLAG_NONE, 0, 1, 1, execute_source);
+
+ debug_console_register_command(machine, "map", CMDFLAG_NONE, AS_PROGRAM, 1, 1, execute_map);
+ debug_console_register_command(machine, "mapd", CMDFLAG_NONE, AS_DATA, 1, 1, execute_map);
+ debug_console_register_command(machine, "mapi", CMDFLAG_NONE, AS_IO, 1, 1, execute_map);
+ debug_console_register_command(machine, "memdump", CMDFLAG_NONE, 0, 0, 1, execute_memdump);
+
+ debug_console_register_command(machine, "symlist", CMDFLAG_NONE, 0, 0, 1, execute_symlist);
+
+ debug_console_register_command(machine, "softreset", CMDFLAG_NONE, 0, 0, 1, execute_softreset);
+ debug_console_register_command(machine, "hardreset", CMDFLAG_NONE, 0, 0, 1, execute_hardreset);
+
+ debug_console_register_command(machine, "images", CMDFLAG_NONE, 0, 0, 0, execute_images);
+ debug_console_register_command(machine, "mount", CMDFLAG_NONE, 0, 2, 2, execute_mount);
+ debug_console_register_command(machine, "unmount", CMDFLAG_NONE, 0, 1, 1, execute_unmount);
+
+ machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(debug_command_exit), &machine));
+
+ /* set up the initial debugscript if specified */
+ name = machine.options().debug_script();
+ if (name[0] != 0)
+ debug_cpu_source_script(machine, name);
+}
+
+
+/*-------------------------------------------------
+ debug_command_exit - exit-time cleanup
+-------------------------------------------------*/
+
+static void debug_command_exit(running_machine &machine)
+{
+ /* turn off all traces */
+ for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next())
+ device->debug()->trace(NULL, 0, NULL);
+
+ if (cheat.length)
+ auto_free(machine, cheat.cheatmap);
+}
+
+
+
+/***************************************************************************
+ GLOBAL FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ execute_min - return the minimum of two values
+-------------------------------------------------*/
+
+static UINT64 execute_min(symbol_table &table, void *ref, int params, const UINT64 *param)
+{
+ return (param[0] < param[1]) ? param[0] : param[1];
+}
+
+
+/*-------------------------------------------------
+ execute_max - return the maximum of two values
+-------------------------------------------------*/
+
+static UINT64 execute_max(symbol_table &table, void *ref, int params, const UINT64 *param)
+{
+ return (param[0] > param[1]) ? param[0] : param[1];
+}
+
+
+/*-------------------------------------------------
+ execute_if - if (a) return b; else return c;
+-------------------------------------------------*/
+
+static UINT64 execute_if(symbol_table &table, void *ref, int params, const UINT64 *param)
+{
+ return param[0] ? param[1] : param[2];
+}
+
+
+
+/***************************************************************************
+ GLOBAL ACCESSORS
+***************************************************************************/
+
+/*-------------------------------------------------
+ global_get - symbol table getter for globals
+-------------------------------------------------*/
+
+static UINT64 global_get(symbol_table &table, void *ref)
+{
+ global_entry *global = (global_entry *)ref;
+ switch (global->size)
+ {
+ case 1: return *(UINT8 *)global->base;
+ case 2: return *(UINT16 *)global->base;
+ case 4: return *(UINT32 *)global->base;
+ case 8: return *(UINT64 *)global->base;
+ }
+ return ~0;
+}
+
+
+/*-------------------------------------------------
+ global_set - symbol table setter for globals
+-------------------------------------------------*/
+
+static void global_set(symbol_table &table, void *ref, UINT64 value)
+{
+ global_entry *global = (global_entry *)ref;
+ switch (global->size)
+ {
+ case 1: *(UINT8 *)global->base = value; break;
+ case 2: *(UINT16 *)global->base = value; break;
+ case 4: *(UINT32 *)global->base = value; break;
+ case 8: *(UINT64 *)global->base = value; break;
+ }
+}
+
+
+
+/***************************************************************************
+ PARAMETER VALIDATION HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ debug_command_parameter_number - validates a
+ number parameter
+-------------------------------------------------*/
+
+int debug_command_parameter_number(running_machine &machine, const char *param, UINT64 *result)
+{
+ /* NULL parameter does nothing and returns no error */
+ if (param == NULL)
+ return TRUE;
+
+ /* evaluate the expression; success if no error */
+ try
+ {
+ parsed_expression expression(debug_cpu_get_visible_symtable(machine), param, result);
+ return TRUE;
+ }
+ catch (expression_error &error)
+ {
+ /* print an error pointing to the character that caused it */
+ debug_console_printf(machine, "Error in expression: %s\n", param);
+ debug_console_printf(machine, " %*s^", error.offset(), "");
+ debug_console_printf(machine, "%s\n", error.code_string());
+ return FALSE;
+ }
+}
+
+
+/*-------------------------------------------------
+ debug_command_parameter_cpu - validates a
+ parameter as a cpu
+-------------------------------------------------*/
+
+int debug_command_parameter_cpu(running_machine &machine, const char *param, device_t **result)
+{
+ UINT64 cpunum;
+
+ /* if no parameter, use the visible CPU */
+ if (param == NULL)
+ {
+ *result = debug_cpu_get_visible_cpu(machine);
+ if (*result == NULL)
+ {
+ debug_console_printf(machine, "No valid CPU is currently selected\n");
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+ /* first look for a tag match */
+ *result = machine.device(param);
+ if (*result != NULL)
+ return TRUE;
+
+ /* then evaluate as an expression; on an error assume it was a tag */
+ try
+ {
+ parsed_expression expression(debug_cpu_get_visible_symtable(machine), param, &cpunum);
+ }
+ catch (expression_error &)
+ {
+ debug_console_printf(machine, "Unable to find CPU '%s'\n", param);
+ return FALSE;
+ }
+
+ /* if we got a valid one, return */
+ device_execute_interface *exec = NULL;
+ for (bool gotone = machine.devicelist().first(exec); gotone; gotone = exec->next(exec))
+ if (cpunum-- == 0)
+ {
+ *result = &exec->device();
+ return TRUE;
+ }
+
+ /* if out of range, complain */
+ debug_console_printf(machine, "Invalid CPU index %d\n", (UINT32)cpunum);
+ return FALSE;
+}
+
+
+/*-------------------------------------------------
+ debug_command_parameter_cpu_space - validates
+ a parameter as a cpu and retrieves the given
+ address space
+-------------------------------------------------*/
+
+int debug_command_parameter_cpu_space(running_machine &machine, const char *param, int spacenum, address_space **result)
+{
+ device_t *cpu;
+
+ /* first do the standard CPU thing */
+ if (!debug_command_parameter_cpu(machine, param, &cpu))
+ return FALSE;
+
+ /* fetch the space pointer */
+ *result = cpu->memory().space(spacenum);
+ if (*result == NULL)
+ {
+ debug_console_printf(machine, "No matching memory space found for CPU '%s'\n", cpu->tag());
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/*-------------------------------------------------
+ debug_command_parameter_expression - validates
+ an expression parameter
+-------------------------------------------------*/
+
+static int debug_command_parameter_expression(running_machine &machine, const char *param, parsed_expression &result)
+{
+ /* NULL parameter does nothing and returns no error */
+ if (param == NULL)
+ return TRUE;
+
+ /* parse the expression; success if no error */
+ try
+ {
+ result.parse(param);
+ return TRUE;
+ }
+ catch (expression_error &err)
+ {
+ /* output an error */
+ debug_console_printf(machine, "Error in expression: %s\n", param);
+ debug_console_printf(machine, " %*s^", err.offset(), "");
+ debug_console_printf(machine, "%s\n", err.code_string());
+ return FALSE;
+ }
+}
+
+
+/*-------------------------------------------------
+ debug_command_parameter_command - validates a
+ command parameter
+-------------------------------------------------*/
+
+static int debug_command_parameter_command(running_machine &machine, const char *param)
+{
+ CMDERR err;
+
+ /* NULL parameter does nothing and returns no error */
+ if (param == NULL)
+ return TRUE;
+
+ /* validate the comment; success if no error */
+ err = debug_console_validate_command(machine, param);
+ if (err == CMDERR_NONE)
+ return TRUE;
+
+ /* output an error */
+ debug_console_printf(machine, "Error in command: %s\n", param);
+ debug_console_printf(machine, " %*s^", CMDERR_ERROR_OFFSET(err), "");
+ debug_console_printf(machine, "%s\n", debug_cmderr_to_string(err));
+ return 0;
+}
+
+
+
+/***************************************************************************
+ COMMAND HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ execute_help - execute the help command
+-------------------------------------------------*/
+
+static void execute_help(running_machine &machine, int ref, int params, const char *param[])
+{
+ if (params == 0)
+ debug_console_printf_wrap(machine, 80, "%s\n", debug_get_help(""));
+ else
+ debug_console_printf_wrap(machine, 80, "%s\n", debug_get_help(param[0]));
+}
+
+
+/*-------------------------------------------------
+ execute_print - execute the print command
+-------------------------------------------------*/
+
+static void execute_print(running_machine &machine, int ref, int params, const char *param[])
+{
+ UINT64 values[MAX_COMMAND_PARAMS];
+ int i;
+
+ /* validate the other parameters */
+ for (i = 0; i < params; i++)
+ if (!debug_command_parameter_number(machine, param[i], &values[i]))
+ return;
+
+ /* then print each one */
+ for (i = 0; i < params; i++)
+ debug_console_printf(machine, "%s", core_i64_hex_format(values[i], 0));
+ debug_console_printf(machine, "\n");
+}
+
+
+/*-------------------------------------------------
+ mini_printf - safe printf to a buffer
+-------------------------------------------------*/
+
+static int mini_printf(running_machine &machine, char *buffer, const char *format, int params, UINT64 *param)
+{
+ const char *f = format;
+ char *p = buffer;
+
+ /* parse the string looking for % signs */
+ for (;;)
+ {
+ char c = *f++;
+ if (!c) break;
+
+ /* escape sequences */
+ if (c == '\\')
+ {
+ c = *f++;
+ if (!c) break;
+ switch (c)
+ {
+ case '\\': *p++ = c; break;
+ case 'n': *p++ = '\n'; break;
+ default: break;
+ }
+ continue;
+ }
+
+ /* formatting */
+ else if (c == '%')
+ {
+ int width = 0;
+ int zerofill = 0;
+
+ /* parse out the width */
+ for (;;)
+ {
+ c = *f++;
+ if (!c || c < '0' || c > '9') break;
+ if (c == '0' && width == 0)
+ zerofill = 1;
+ width = width * 10 + (c - '0');
+ }
+ if (!c) break;
+
+ /* get the format */
+ switch (c)
+ {
+ case '%':
+ *p++ = c;
+ break;
+
+ case 'X':
+ case 'x':
+ if (params == 0)
+ {
+ debug_console_printf(machine, "Not enough parameters for format!\n");
+ return 0;
+ }
+ if ((UINT32)(*param >> 32) != 0)
+ p += sprintf(p, zerofill ? "%0*X" : "%*X", (width <= 8) ? 1 : width - 8, (UINT32)(*param >> 32));
+ else if (width > 8)
+ p += sprintf(p, zerofill ? "%0*X" : "%*X", width - 8, 0);
+ p += sprintf(p, zerofill ? "%0*X" : "%*X", (width < 8) ? width : 8, (UINT32)*param);
+ param++;
+ params--;
+ break;
+
+ case 'D':
+ case 'd':
+ if (params == 0)
+ {
+ debug_console_printf(machine, "Not enough parameters for format!\n");
+ return 0;
+ }
+ p += sprintf(p, zerofill ? "%0*d" : "%*d", width, (UINT32)*param);
+ param++;
+ params--;
+ break;
+ }
+ }
+
+ /* normal stuff */
+ else
+ *p++ = c;
+ }
+
+ /* NULL-terminate and exit */
+ *p = 0;
+ return 1;
+}
+
+
+/*-------------------------------------------------
+ execute_printf - execute the printf command
+-------------------------------------------------*/
+
+static void execute_printf(running_machine &machine, int ref, int params, const char *param[])
+{
+ UINT64 values[MAX_COMMAND_PARAMS];
+ char buffer[1024];
+ int i;
+
+ /* validate the other parameters */
+ for (i = 1; i < params; i++)
+ if (!debug_command_parameter_number(machine, param[i], &values[i]))
+ return;
+
+ /* then do a printf */
+ if (mini_printf(machine, buffer, param[0], params - 1, &values[1]))
+ debug_console_printf(machine, "%s\n", buffer);
+}
+
+
+/*-------------------------------------------------
+ execute_logerror - execute the logerror command
+-------------------------------------------------*/
+
+static void execute_logerror(running_machine &machine, int ref, int params, const char *param[])
+{
+ UINT64 values[MAX_COMMAND_PARAMS];
+ char buffer[1024];
+ int i;
+
+ /* validate the other parameters */
+ for (i = 1; i < params; i++)
+ if (!debug_command_parameter_number(machine, param[i], &values[i]))
+ return;
+
+ /* then do a printf */
+ if (mini_printf(machine, buffer, param[0], params - 1, &values[1]))
+ logerror("%s", buffer);
+}
+
+
+/*-------------------------------------------------
+ execute_tracelog - execute the tracelog command
+-------------------------------------------------*/
+
+static void execute_tracelog(running_machine &machine, int ref, int params, const char *param[])
+{
+ UINT64 values[MAX_COMMAND_PARAMS];
+ char buffer[1024];
+ int i;
+
+ /* validate the other parameters */
+ for (i = 1; i < params; i++)
+ if (!debug_command_parameter_number(machine, param[i], &values[i]))
+ return;
+
+ /* then do a printf */
+ if (mini_printf(machine, buffer, param[0], params - 1, &values[1]))
+ debug_cpu_get_visible_cpu(machine)->debug()->trace_printf("%s", buffer);
+}
+
+
+/*-------------------------------------------------
+ execute_quit - execute the quit command
+-------------------------------------------------*/
+
+static void execute_quit(running_machine &machine, int ref, int params, const char *param[])
+{
+ mame_printf_error("Exited via the debugger\n");
+ machine.schedule_exit();
+}
+
+
+/*-------------------------------------------------
+ execute_do - execute the do command
+-------------------------------------------------*/
+
+static void execute_do(running_machine &machine, int ref, int params, const char *param[])
+{
+ UINT64 dummy;
+ debug_command_parameter_number(machine, param[0], &dummy);
+}
+
+
+/*-------------------------------------------------
+ execute_step - execute the step command
+-------------------------------------------------*/
+
+static void execute_step(running_machine &machine, int ref, int params, const char *param[])
+{
+ UINT64 steps = 1;
+
+ /* if we have a parameter, use it instead */
+ if (!debug_command_parameter_number(machine, param[0], &steps))
+ return;
+
+ debug_cpu_get_visible_cpu(machine)->debug()->single_step(steps);
+}
+
+
+/*-------------------------------------------------
+ execute_over - execute the over command
+-------------------------------------------------*/
+
+static void execute_over(running_machine &machine, int ref, int params, const char *param[])
+{
+ UINT64 steps = 1;
+
+ /* if we have a parameter, use it instead */
+ if (!debug_command_parameter_number(machine, param[0], &steps))
+ return;
+
+ debug_cpu_get_visible_cpu(machine)->debug()->single_step_over(steps);
+}
+
+
+/*-------------------------------------------------
+ execute_out - execute the out command
+-------------------------------------------------*/
+
+static void execute_out(running_machine &machine, int ref, int params, const char *param[])
+{
+ debug_cpu_get_visible_cpu(machine)->debug()->single_step_out();
+}
+
+
+/*-------------------------------------------------
+ execute_go - execute the go command
+-------------------------------------------------*/
+
+static void execute_go(running_machine &machine, int ref, int params, const char *param[])
+{
+ UINT64 addr = ~0;
+
+ /* if we have a parameter, use it instead */
+ if (!debug_command_parameter_number(machine, param[0], &addr))
+ return;
+
+ debug_cpu_get_visible_cpu(machine)->debug()->go(addr);
+}
+
+
+/*-------------------------------------------------
+ execute_go_vblank - execute the govblank
+ command
+-------------------------------------------------*/
+
+static void execute_go_vblank(running_machine &machine, int ref, int params, const char *param[])
+{
+ debug_cpu_get_visible_cpu(machine)->debug()->go_vblank();
+}
+
+
+/*-------------------------------------------------
+ execute_go_interrupt - execute the goint command
+-------------------------------------------------*/
+
+static void execute_go_interrupt(running_machine &machine, int ref, int params, const char *param[])
+{
+ UINT64 irqline = -1;
+
+ /* if we have a parameter, use it instead */
+ if (!debug_command_parameter_number(machine, param[0], &irqline))
+ return;
+
+ debug_cpu_get_visible_cpu(machine)->debug()->go_interrupt(irqline);
+}
+
+
+/*-------------------------------------------------
+ execute_go_time - execute the gtime command
+-------------------------------------------------*/
+
+static void execute_go_time(running_machine &machine, int ref, int params, const char *param[])
+{
+ UINT64 milliseconds = -1;
+
+ /* if we have a parameter, use it instead */
+ if (!debug_command_parameter_number(machine, param[0], &milliseconds))
+ return;
+
+ debug_cpu_get_visible_cpu(machine)->debug()->go_milliseconds(milliseconds);
+}
+
+
+/*-------------------------------------------------
+ execute_next - execute the next command
+-------------------------------------------------*/
+
+static void execute_next(running_machine &machine, int ref, int params, const char *param[])
+{
+ debug_cpu_get_visible_cpu(machine)->debug()->go_next_device();
+}
+
+
+/*-------------------------------------------------
+ execute_focus - execute the focus command
+-------------------------------------------------*/
+
+static void execute_focus(running_machine &machine, int ref, int params, const char *param[])
+{
+ /* validate params */
+ device_t *cpu;
+ if (!debug_command_parameter_cpu(machine, param[0], &cpu))
+ return;
+
+ /* first clear the ignore flag on the focused CPU */
+ cpu->debug()->ignore(false);
+
+ /* then loop over CPUs and set the ignore flags on all other CPUs */
+ device_execute_interface *exec = NULL;
+ for (bool gotone = machine.devicelist().first(exec); gotone; gotone = exec->next(exec))
+ if (&exec->device() != cpu)
+ exec->device().debug()->ignore(true);
+ debug_console_printf(machine, "Now focused on CPU '%s'\n", cpu->tag());
+}
+
+
+/*-------------------------------------------------
+ execute_ignore - execute the ignore command
+-------------------------------------------------*/
+
+static void execute_ignore(running_machine &machine, int ref, int params, const char *param[])
+{
+ /* if there are no parameters, dump the ignore list */
+ if (params == 0)
+ {
+ astring buffer;
+
+ /* loop over all executable devices */
+ device_execute_interface *exec = NULL;
+ for (bool gotone = machine.devicelist().first(exec); gotone; gotone = exec->next(exec))
+
+ /* build up a comma-separated list */
+ if (!exec->device().debug()->observing())
+ {
+ if (!buffer)
+ buffer.printf("Currently ignoring device '%s'", exec->device().tag());
+ else
+ buffer.catprintf(", '%s'", exec->device().tag());
+ }
+
+ /* special message for none */
+ if (!buffer)
+ buffer.printf("Not currently ignoring any devices");
+ debug_console_printf(machine, "%s\n", buffer.cstr());
+ }
+
+ /* otherwise clear the ignore flag on all requested CPUs */
+ else
+ {
+ device_t *devicelist[MAX_COMMAND_PARAMS];
+
+ /* validate parameters */
+ for (int paramnum = 0; paramnum < params; paramnum++)
+ if (!debug_command_parameter_cpu(machine, param[paramnum], &devicelist[paramnum]))
+ return;
+
+ /* set the ignore flags */
+ for (int paramnum = 0; paramnum < params; paramnum++)
+ {
+ /* make sure this isn't the last live CPU */
+ device_execute_interface *exec = NULL;
+ bool gotone;
+ for (gotone = machine.devicelist().first(exec); gotone; gotone = exec->next(exec))
+ if (&exec->device() != devicelist[paramnum] && exec->device().debug()->observing())
+ break;
+ if (!gotone)
+ {
+ debug_console_printf(machine, "Can't ignore all devices!\n");
+ return;
+ }
+
+ devicelist[paramnum]->debug()->ignore(true);
+ debug_console_printf(machine, "Now ignoring device '%s'\n", devicelist[paramnum]->tag());
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ execute_observe - execute the observe command
+-------------------------------------------------*/
+
+static void execute_observe(running_machine &machine, int ref, int params, const char *param[])
+{
+ /* if there are no parameters, dump the ignore list */
+ if (params == 0)
+ {
+ astring buffer;
+
+ /* loop over all executable devices */
+ device_execute_interface *exec = NULL;
+ for (bool gotone = machine.devicelist().first(exec); gotone; gotone = exec->next(exec))
+
+ /* build up a comma-separated list */
+ if (exec->device().debug()->observing())
+ {
+ if (!buffer)
+ buffer.printf("Currently observing CPU '%s'", exec->device().tag());
+ else
+ buffer.catprintf(", '%s'", exec->device().tag());
+ }
+
+ /* special message for none */
+ if (!buffer)
+ buffer.printf("Not currently observing any devices");
+ debug_console_printf(machine, "%s\n", buffer.cstr());
+ }
+
+ /* otherwise set the ignore flag on all requested CPUs */
+ else
+ {
+ device_t *devicelist[MAX_COMMAND_PARAMS];
+
+ /* validate parameters */
+ for (int paramnum = 0; paramnum < params; paramnum++)
+ if (!debug_command_parameter_cpu(machine, param[paramnum], &devicelist[paramnum]))
+ return;
+
+ /* clear the ignore flags */
+ for (int paramnum = 0; paramnum < params; paramnum++)
+ {
+ devicelist[paramnum]->debug()->ignore(false);
+ debug_console_printf(machine, "Now observing device '%s'\n", devicelist[paramnum]->tag());
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ execute_comment - add a comment to a line
+-------------------------------------------------*/
+
+static void execute_comment(running_machine &machine, int ref, int params, const char *param[])
+{
+ device_t *cpu;
+ UINT64 address;
+
+ /* param 1 is the address for the comment */
+ if (!debug_command_parameter_number(machine, param[0], &address))
+ return;
+
+ /* CPU parameter is implicit */
+ if (!debug_command_parameter_cpu(machine, NULL, &cpu))
+ return;
+
+ /* make sure param 2 exists */
+ if (strlen(param[1]) == 0)
+ {
+ debug_console_printf(machine, "Error : comment text empty\n");
+ return;
+ }
+
+ /* Now try adding the comment */
+ cpu->debug()->comment_add(address, param[1], 0x00ff0000);
+ cpu->machine().debug_view().update_all(DVT_DISASSEMBLY);
+}
+
+
+/*------------------------------------------------------
+ execute_comment_del - remove a comment from an addr
+--------------------------------------------------------*/
+
+static void execute_comment_del(running_machine &machine, int ref, int params, const char *param[])
+{
+ device_t *cpu;
+ UINT64 address;
+
+ /* param 1 can either be a command or the address for the comment */
+ if (!debug_command_parameter_number(machine, param[0], &address))
+ return;
+
+ /* CPU parameter is implicit */
+ if (!debug_command_parameter_cpu(machine, NULL, &cpu))
+ return;
+
+ /* If it's a number, it must be an address */
+ /* The bankoff and cbn will be pulled from what's currently active */
+ cpu->debug()->comment_remove(address);
+ cpu->machine().debug_view().update_all(DVT_DISASSEMBLY);
+}
+
+
+/*-------------------------------------------------
+ execute_comment - add a comment to a line
+-------------------------------------------------*/
+
+static void execute_comment_save(running_machine &machine, int ref, int params, const char *param[])
+{
+ if (debug_comment_save(machine))
+ debug_console_printf(machine, "Comments successfully saved\n");
+}
+
+
+/*-------------------------------------------------
+ execute_bpset - execute the breakpoint set
+ command
+-------------------------------------------------*/
+
+static void execute_bpset(running_machine &machine, int ref, int params, const char *param[])
+{
+ device_t *cpu;
+ const char *action = NULL;
+ UINT64 address;
+ int bpnum;
+
+ /* CPU is implicit */
+ if (!debug_command_parameter_cpu(machine, NULL, &cpu))
+ return;
+
+ /* param 1 is the address */
+ if (!debug_command_parameter_number(machine, param[0], &address))
+ return;
+
+ /* param 2 is the condition */
+ parsed_expression condition(&cpu->debug()->symtable());
+ if (!debug_command_parameter_expression(machine, param[1], condition))
+ return;
+
+ /* param 3 is the action */
+ if (!debug_command_parameter_command(machine, action = param[2]))
+ return;
+
+ /* set the breakpoint */
+ bpnum = cpu->debug()->breakpoint_set(address, (condition.is_empty()) ? NULL : condition.original_string(), action);
+ debug_console_printf(machine, "Breakpoint %X set\n", bpnum);
+}
+
+
+/*-------------------------------------------------
+ execute_bpclear - execute the breakpoint
+ clear command
+-------------------------------------------------*/
+
+static void execute_bpclear(running_machine &machine, int ref, int params, const char *param[])
+{
+ UINT64 bpindex;
+
+ /* if 0 parameters, clear all */
+ if (params == 0)
+ {
+ for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next())
+ device->debug()->breakpoint_clear_all();
+ debug_console_printf(machine, "Cleared all breakpoints\n");
+ }
+
+ /* otherwise, clear the specific one */
+ else if (!debug_command_parameter_number(machine, param[0], &bpindex))
+ return;
+ else
+ {
+ bool found = false;
+ for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next())
+ if (device->debug()->breakpoint_clear(bpindex))
+ found = true;
+ if (found)
+ debug_console_printf(machine, "Breakpoint %X cleared\n", (UINT32)bpindex);
+ else
+ debug_console_printf(machine, "Invalid breakpoint number %X\n", (UINT32)bpindex);
+ }
+}
+
+
+/*-------------------------------------------------
+ execute_bpdisenable - execute the breakpoint
+ disable/enable commands
+-------------------------------------------------*/
+
+static void execute_bpdisenable(running_machine &machine, int ref, int params, const char *param[])
+{
+ UINT64 bpindex;
+
+ /* if 0 parameters, clear all */
+ if (params == 0)
+ {
+ for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next())
+ device->debug()->breakpoint_enable_all(ref);
+ if (ref == 0)
+ debug_console_printf(machine, "Disabled all breakpoints\n");
+ else
+ debug_console_printf(machine, "Enabled all breakpoints\n");
+ }
+
+ /* otherwise, clear the specific one */
+ else if (!debug_command_parameter_number(machine, param[0], &bpindex))
+ return;
+ else
+ {
+ bool found = false;
+ for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next())
+ if (device->debug()->breakpoint_enable(bpindex, ref))
+ found = true;
+ if (found)
+ debug_console_printf(machine, "Breakpoint %X %s\n", (UINT32)bpindex, ref ? "enabled" : "disabled");
+ else
+ debug_console_printf(machine, "Invalid breakpoint number %X\n", (UINT32)bpindex);
+ }
+}
+
+
+/*-------------------------------------------------
+ execute_bplist - execute the breakpoint list
+ command
+-------------------------------------------------*/
+
+static void execute_bplist(running_machine &machine, int ref, int params, const char *param[])
+{
+ int printed = 0;
+ astring buffer;
+
+ /* loop over all CPUs */
+ for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next())
+ if (device->debug()->breakpoint_first() != NULL)
+ {
+ debug_console_printf(machine, "Device '%s' breakpoints:\n", device->tag());
+
+ /* loop over the breakpoints */
+ for (device_debug::breakpoint *bp = device->debug()->breakpoint_first(); bp != NULL; bp = bp->next())
+ {
+ buffer.printf("%c%4X @ %s", bp->enabled() ? ' ' : 'D', bp->index(), core_i64_hex_format(bp->address(), device->debug()->logaddrchars()));
+ if (bp->condition() != NULL)
+ buffer.catprintf(" if %s", bp->condition());
+ if (bp->action() != NULL)
+ buffer.catprintf(" do %s", bp->action());
+ debug_console_printf(machine, "%s\n", buffer.cstr());
+ printed++;
+ }
+ }
+
+ if (printed == 0)
+ debug_console_printf(machine, "No breakpoints currently installed\n");
+}
+
+
+/*-------------------------------------------------
+ execute_wpset - execute the watchpoint set
+ command
+-------------------------------------------------*/
+
+static void execute_wpset(running_machine &machine, int ref, int params, const char *param[])
+{
+ address_space *space;
+ const char *action = NULL;
+ UINT64 address, length;
+ int type = 0;
+ int wpnum;
+
+ /* CPU is implicit */
+ if (!debug_command_parameter_cpu_space(machine, NULL, ref, &space))
+ return;
+
+ /* param 1 is the address */
+ if (!debug_command_parameter_number(machine, param[0], &address))
+ return;
+
+ /* param 2 is the length */
+ if (!debug_command_parameter_number(machine, param[1], &length))
+ return;
+
+ /* param 3 is the type */
+ if (!strcmp(param[2], "r"))
+ type = WATCHPOINT_READ;
+ else if (!strcmp(param[2], "w"))
+ type = WATCHPOINT_WRITE;
+ else if (!strcmp(param[2], "rw") || !strcmp(param[2], "wr"))
+ type = WATCHPOINT_READWRITE;
+ else
+ {
+ debug_console_printf(machine, "Invalid watchpoint type: expected r, w, or rw\n");
+ return;
+ }
+
+ /* param 4 is the condition */
+ parsed_expression condition(&space->device().debug()->symtable());
+ if (!debug_command_parameter_expression(machine, param[3], condition))
+ return;
+
+ /* param 5 is the action */
+ if (!debug_command_parameter_command(machine, action = param[4]))
+ return;
+
+ /* set the watchpoint */
+ wpnum = space->device().debug()->watchpoint_set(*space, type, address, length, (condition.is_empty()) ? NULL : condition.original_string(), action);
+ debug_console_printf(machine, "Watchpoint %X set\n", wpnum);
+}
+
+
+/*-------------------------------------------------
+ execute_wpclear - execute the watchpoint
+ clear command
+-------------------------------------------------*/
+
+static void execute_wpclear(running_machine &machine, int ref, int params, const char *param[])
+{
+ UINT64 wpindex;
+
+ /* if 0 parameters, clear all */
+ if (params == 0)
+ {
+ for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next())
+ device->debug()->watchpoint_clear_all();
+ debug_console_printf(machine, "Cleared all watchpoints\n");
+ }
+
+ /* otherwise, clear the specific one */
+ else if (!debug_command_parameter_number(machine, param[0], &wpindex))
+ return;
+ else
+ {
+ bool found = false;
+ for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next())
+ if (device->debug()->watchpoint_clear(wpindex))
+ found = true;
+ if (found)
+ debug_console_printf(machine, "Watchpoint %X cleared\n", (UINT32)wpindex);
+ else
+ debug_console_printf(machine, "Invalid watchpoint number %X\n", (UINT32)wpindex);
+ }
+}
+
+
+/*-------------------------------------------------
+ execute_wpdisenable - execute the watchpoint
+ disable/enable commands
+-------------------------------------------------*/
+
+static void execute_wpdisenable(running_machine &machine, int ref, int params, const char *param[])
+{
+ UINT64 wpindex;
+
+ /* if 0 parameters, clear all */
+ if (params == 0)
+ {
+ for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next())
+ device->debug()->watchpoint_enable_all(ref);
+ if (ref == 0)
+ debug_console_printf(machine, "Disabled all watchpoints\n");
+ else
+ debug_console_printf(machine, "Enabled all watchpoints\n");
+ }
+
+ /* otherwise, clear the specific one */
+ else if (!debug_command_parameter_number(machine, param[0], &wpindex))
+ return;
+ else
+ {
+ bool found = false;
+ for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next())
+ if (device->debug()->watchpoint_enable(wpindex, ref))
+ found = true;
+ if (found)
+ debug_console_printf(machine, "Watchpoint %X %s\n", (UINT32)wpindex, ref ? "enabled" : "disabled");
+ else
+ debug_console_printf(machine, "Invalid watchpoint number %X\n", (UINT32)wpindex);
+ }
+}
+
+
+/*-------------------------------------------------
+ execute_wplist - execute the watchpoint list
+ command
+-------------------------------------------------*/
+
+static void execute_wplist(running_machine &machine, int ref, int params, const char *param[])
+{
+ int printed = 0;
+ astring buffer;
+
+ /* loop over all CPUs */
+ for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next())
+ for (address_spacenum spacenum = AS_0; spacenum < ADDRESS_SPACES; spacenum++)
+ if (device->debug()->watchpoint_first(spacenum) != NULL)
+ {
+ static const char *const types[] = { "unkn ", "read ", "write", "r/w " };
+
+ debug_console_printf(machine, "Device '%s' %s space watchpoints:\n", device->tag(), device->debug()->watchpoint_first(spacenum)->space().name());
+
+ /* loop over the watchpoints */
+ for (device_debug::watchpoint *wp = device->debug()->watchpoint_first(spacenum); wp != NULL; wp = wp->next())
+ {
+ buffer.printf("%c%4X @ %s-%s %s", wp->enabled() ? ' ' : 'D', wp->index(),
+ core_i64_hex_format(wp->space().byte_to_address(wp->address()), wp->space().addrchars()),
+ core_i64_hex_format(wp->space().byte_to_address_end(wp->address() + wp->length()) - 1, wp->space().addrchars()),
+ types[wp->type() & 3]);
+ if (wp->condition() != NULL)
+ buffer.catprintf(" if %s", wp->condition());
+ if (wp->action() != NULL)
+ buffer.catprintf(" do %s", wp->action());
+ debug_console_printf(machine, "%s\n", buffer.cstr());
+ printed++;
+ }
+ }
+
+ if (printed == 0)
+ debug_console_printf(machine, "No watchpoints currently installed\n");
+}
+
+
+/*-------------------------------------------------
+ execute_hotspot - execute the hotspot
+ command
+-------------------------------------------------*/
+
+static void execute_hotspot(running_machine &machine, int ref, int params, const char *param[])
+{
+ /* if no params, and there are live hotspots, clear them */
+ if (params == 0)
+ {
+ bool cleared = false;
+
+ /* loop over CPUs and find live spots */
+ for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next())
+ if (device->debug()->hotspot_tracking_enabled())
+ {
+ device->debug()->hotspot_track(0, 0);
+ debug_console_printf(machine, "Cleared hotspot tracking on CPU '%s'\n", device->tag());
+ cleared = true;
+ }
+
+ /* if we cleared, we're done */
+ if (cleared)
+ return;
+ }
+
+ /* extract parameters */
+ device_t *device = NULL;
+ if (!debug_command_parameter_cpu(machine, (params > 0) ? param[0] : NULL, &device))
+ return;
+ UINT64 count = 64;
+ if (!debug_command_parameter_number(machine, param[1], &count))
+ return;
+ UINT64 threshhold = 250;
+ if (!debug_command_parameter_number(machine, param[2], &threshhold))
+ return;
+
+ /* attempt to install */
+ device->debug()->hotspot_track(count, threshhold);
+ debug_console_printf(machine, "Now tracking hotspots on CPU '%s' using %d slots with a threshhold of %d\n", device->tag(), (int)count, (int)threshhold);
+}
+
+
+/*-------------------------------------------------
+ execute_save - execute the save command
+-------------------------------------------------*/
+
+static void execute_save(running_machine &machine, int ref, int params, const char *param[])
+{
+ UINT64 offset, endoffset, length;
+ address_space *space;
+ FILE *f;
+ UINT64 i;
+
+ /* validate parameters */
+ if (!debug_command_parameter_number(machine, param[1], &offset))
+ return;
+ if (!debug_command_parameter_number(machine, param[2], &length))
+ return;
+ if (!debug_command_parameter_cpu_space(machine, (params > 3) ? param[3] : NULL, ref, &space))
+ return;
+
+ /* determine the addresses to write */
+ endoffset = space->address_to_byte(offset + length - 1) & space->bytemask();
+ offset = space->address_to_byte(offset) & space->bytemask();
+
+ /* open the file */
+ f = fopen(param[0], "wb");
+ if (!f)
+ {
+ debug_console_printf(machine, "Error opening file '%s'\n", param[0]);
+ return;
+ }
+
+ /* now write the data out */
+ for (i = offset; i <= endoffset; i++)
+ {
+ UINT8 byte = debug_read_byte(space, i, TRUE);
+ fwrite(&byte, 1, 1, f);
+ }
+
+ /* close the file */
+ fclose(f);
+ debug_console_printf(machine, "Data saved successfully\n");
+}
+
+
+/*-------------------------------------------------
+ execute_load - execute the load command
+-------------------------------------------------*/
+
+static void execute_load(running_machine &machine, int ref, int params, const char *param[])
+{
+ UINT64 offset, endoffset, length;
+ address_space *space;
+ FILE *f;
+ UINT64 i;
+
+ /* validate parameters */
+ if (!debug_command_parameter_number(machine, param[1], &offset))
+ return;
+ if (!debug_command_parameter_number(machine, param[2], &length))
+ return;
+ if (!debug_command_parameter_cpu_space(machine, (params > 3) ? param[3] : NULL, ref, &space))
+ return;
+
+ /* determine the addresses to read */
+ endoffset = space->address_to_byte(offset + length - 1) & space->bytemask();
+ offset = space->address_to_byte(offset) & space->bytemask();
+
+ /* open the file */
+ f = fopen(param[0], "rb");
+ if (!f)
+ {
+ debug_console_printf(machine, "Error opening file '%s'\n", param[0]);
+ return;
+ }
+
+ /* now read the data in, ignore endoffset and load entire file if length has been set to zero (offset-1) */
+ UINT8 byte;
+ for (i = offset; i <= endoffset || endoffset == offset - 1 ; i++)
+ {
+ fread(&byte, 1, 1, f);
+ /* check if end of file has been reached and stop loading if it has */
+ if (feof(f))
+ break;
+ debug_write_byte(space, i, byte, TRUE);
+ }
+ /* close the file */
+ fclose(f);
+ if ( i == offset)
+ debug_console_printf(machine, "Length specified too large, load failed\n");
+ else
+ debug_console_printf(machine, "Data loaded successfully to memory : 0x%s to 0x%s\n", core_i64_hex_format(offset,0), core_i64_hex_format(i-1,0));
+}
+
+
+/*-------------------------------------------------
+ execute_dump - execute the dump command
+-------------------------------------------------*/
+
+static void execute_dump(running_machine &machine, int ref, int params, const char *param[])
+{
+ UINT64 offset, endoffset, length, width = 0, ascii = 1;
+ address_space *space;
+ FILE *f = NULL;
+ UINT64 i, j;
+
+ /* validate parameters */
+ if (!debug_command_parameter_number(machine, param[1], &offset))
+ return;
+ if (!debug_command_parameter_number(machine, param[2], &length))
+ return;
+ if (!debug_command_parameter_number(machine, param[3], &width))
+ return;
+ if (!debug_command_parameter_number(machine, param[4], &ascii))
+ return;
+ if (!debug_command_parameter_cpu_space(machine, (params > 5) ? param[5] : NULL, ref, &space))
+ return;
+
+ /* further validation */
+ if (width == 0)
+ width = space->data_width() / 8;
+ if (width < space->address_to_byte(1))
+ width = space->address_to_byte(1);
+ if (width != 1 && width != 2 && width != 4 && width != 8)
+ {
+ debug_console_printf(machine, "Invalid width! (must be 1,2,4 or 8)\n");
+ return;
+ }
+ endoffset = space->address_to_byte(offset + length - 1) & space->bytemask();
+ offset = space->address_to_byte(offset) & space->bytemask();
+
+ /* open the file */
+ f = fopen(param[0], "w");
+ if (!f)
+ {
+ debug_console_printf(machine, "Error opening file '%s'\n", param[0]);
+ return;
+ }
+
+ /* now write the data out */
+ for (i = offset; i <= endoffset; i += 16)
+ {
+ char output[200];
+ int outdex = 0;
+
+ /* print the address */
+ outdex += sprintf(&output[outdex], "%s: ", core_i64_hex_format((UINT32)space->byte_to_address(i), space->logaddrchars()));
+
+ /* print the bytes */
+ for (j = 0; j < 16; j += width)
+ {
+ if (i + j <= endoffset)
+ {
+ offs_t curaddr = i + j;
+ if (debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &curaddr))
+ {
+ UINT64 value = debug_read_memory(space, i + j, width, TRUE);
+ outdex += sprintf(&output[outdex], " %s", core_i64_hex_format(value, width * 2));
+ }
+ else
+ outdex += sprintf(&output[outdex], " %.*s", (int)width * 2, "****************");
+ }
+ else
+ outdex += sprintf(&output[outdex], " %*s", (int)width * 2, "");
+ }
+
+ /* print the ASCII */
+ if (ascii)
+ {
+ outdex += sprintf(&output[outdex], " ");
+ for (j = 0; j < 16 && (i + j) <= endoffset; j++)
+ {
+ offs_t curaddr = i + j;
+ if (debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &curaddr))
+ {
+ UINT8 byte = debug_read_byte(space, i + j, TRUE);
+ outdex += sprintf(&output[outdex], "%c", (byte >= 32 && byte < 127) ? byte : '.');
+ }
+ else
+ outdex += sprintf(&output[outdex], " ");
+ }
+ }
+
+ /* output the result */
+ fprintf(f, "%s\n", output);
+ }
+
+ /* close the file */
+ fclose(f);
+ debug_console_printf(machine, "Data dumped successfully\n");
+}
+
+
+/*-------------------------------------------------
+ execute_cheatinit - initialize the cheat system
+-------------------------------------------------*/
+
+static void execute_cheatinit(running_machine &machine, int ref, int params, const char *param[])
+{
+ UINT64 offset, length = 0, real_length = 0;
+ address_space *space;
+ UINT32 active_cheat = 0;
+ UINT64 curaddr;
+ UINT8 i, region_count = 0;
+
+ address_map_entry *entry;
+ cheat_region_map cheat_region[100];
+
+ memset(cheat_region, 0, sizeof(cheat_region));
+
+ /* validate parameters */
+ if (!debug_command_parameter_cpu_space(machine, (params > 3) ? param[3] : NULL, AS_PROGRAM, &space))
+ return;
+
+ if (ref == 0)
+ {
+ cheat.width = 1;
+ cheat.signed_cheat = FALSE;
+ cheat.swapped_cheat = FALSE;
+ if (params > 0)
+ {
+ char *srtpnt = (char*)param[0];
+
+ if (*srtpnt == 's')
+ cheat.signed_cheat = TRUE;
+ else if (*srtpnt == 'u')
+ cheat.signed_cheat = FALSE;
+ else
+ {
+ debug_console_printf(machine, "Invalid sign: expected s or u\n");
+ return;
+ }
+
+ if (*(++srtpnt) == 'b')
+ cheat.width = 1;
+ else if (*srtpnt == 'w')
+ cheat.width = 2;
+ else if (*srtpnt == 'd')
+ cheat.width = 4;
+ else if (*srtpnt == 'q')
+ cheat.width = 8;
+ else
+ {
+ debug_console_printf(machine, "Invalid width: expected b, w, d or q\n");
+ return;
+ }
+
+ if (*(++srtpnt) == 's')
+ cheat.swapped_cheat = TRUE;
+ else
+ cheat.swapped_cheat = FALSE;
+ }
+ }
+
+ /* initialize entire memory by default */
+ if (params <= 1)
+ {
+ offset = 0;
+ length = space->bytemask() + 1;
+ for (entry = space->map()->m_entrylist.first(); entry != NULL; entry = entry->next())
+ {
+ cheat_region[region_count].offset = space->address_to_byte(entry->m_addrstart) & space->bytemask();
+ cheat_region[region_count].endoffset = space->address_to_byte(entry->m_addrend) & space->bytemask();
+ cheat_region[region_count].share = entry->m_share;
+ cheat_region[region_count].disabled = (entry->m_write.m_type == AMH_RAM) ? FALSE : TRUE;
+
+ /* disable double share regions */
+ if (entry->m_share != NULL)
+ for (i = 0; i < region_count; i++)
+ if (cheat_region[i].share != NULL)
+ if (strcmp(cheat_region[i].share, entry->m_share) == 0)
+ cheat_region[region_count].disabled = TRUE;
+
+ region_count++;
+ }
+ }
+ else
+ {
+ /* validate parameters */
+ if (!debug_command_parameter_number(machine, param[(ref == 0) ? 1 : 0], &offset))
+ return;
+ if (!debug_command_parameter_number(machine, param[(ref == 0) ? 2 : 1], &length))
+ return;
+
+ /* force region to the specified range */
+ cheat_region[region_count].offset = space->address_to_byte(offset) & space->bytemask();
+ cheat_region[region_count].endoffset = space->address_to_byte(offset + length - 1) & space->bytemask();
+ cheat_region[region_count].share = NULL;
+ cheat_region[region_count].disabled = FALSE;
+ region_count++;
+ }
+
+ /* determine the writable extent of each region in total */
+ for (i = 0; i <= region_count; i++)
+ if (!cheat_region[i].disabled)
+ for (curaddr = cheat_region[i].offset; curaddr <= cheat_region[i].endoffset; curaddr += cheat.width)
+ if (cheat_address_is_valid(space, curaddr))
+ real_length++;
+
+ if (real_length == 0)
+ {
+ debug_console_printf(machine, "No writable bytes found in this area\n");
+ return;
+ }
+
+ if (ref == 0)
+ {
+ /* initialize new cheat system */
+ if (cheat.cheatmap != NULL)
+ auto_free(machine, cheat.cheatmap);
+ cheat.cheatmap = auto_alloc_array(machine, cheat_map, real_length);
+
+ cheat.length = real_length;
+ cheat.undo = 0;
+ cheat.cpu = (params > 3) ? *param[3] : '0';
+ }
+ else
+ {
+ /* add range to cheat system */
+ if (cheat.cpu == 0)
+ {
+ debug_console_printf(machine, "Use cheatinit before cheatrange\n");
+ return;
+ }
+
+ if (!debug_command_parameter_cpu_space(machine, &cheat.cpu, AS_PROGRAM, &space))
+ return;
+
+ cheat_map *newmap = auto_alloc_array(machine, cheat_map, cheat.length + real_length);
+ for (int item = 0; item < cheat.length; item++)
+ newmap[item] = cheat.cheatmap[item];
+ auto_free(machine, cheat.cheatmap);
+ cheat.cheatmap = newmap;
+
+ active_cheat = cheat.length;
+ cheat.length += real_length;
+ }
+
+ /* initialize cheatmap in the selected space */
+ for (i = 0; i < region_count; i++)
+ if (!cheat_region[i].disabled)
+ for (curaddr = cheat_region[i].offset; curaddr <= cheat_region[i].endoffset; curaddr += cheat.width)
+ if (cheat_address_is_valid(space, curaddr))
+ {
+ cheat.cheatmap[active_cheat].previous_value = cheat_read_extended(&cheat, space, curaddr);
+ cheat.cheatmap[active_cheat].first_value = cheat.cheatmap[active_cheat].previous_value;
+ cheat.cheatmap[active_cheat].offset = curaddr;
+ cheat.cheatmap[active_cheat].state = 1;
+ cheat.cheatmap[active_cheat].undo = 0;
+ active_cheat++;
+ }
+
+ debug_console_printf(machine, "%u cheat initialized\n", active_cheat);
+}
+
+
+/*-------------------------------------------------
+ execute_cheatnext - execute the search
+-------------------------------------------------*/
+
+static void execute_cheatnext(running_machine &machine, int ref, int params, const char *param[])
+{
+ address_space *space;
+ UINT64 cheatindex;
+ UINT32 active_cheat = 0;
+ UINT8 condition;
+ UINT64 comp_value = 0;
+
+ enum
+ {
+ CHEAT_ALL = 0,
+ CHEAT_EQUAL,
+ CHEAT_NOTEQUAL,
+ CHEAT_EQUALTO,
+ CHEAT_NOTEQUALTO,
+ CHEAT_DECREASE,
+ CHEAT_INCREASE,
+ CHEAT_DECREASE_OR_EQUAL,
+ CHEAT_INCREASE_OR_EQUAL,
+ CHEAT_DECREASEOF,
+ CHEAT_INCREASEOF,
+ CHEAT_SMALLEROF,
+ CHEAT_GREATEROF,
+ CHEAT_CHANGEDBY
+ };
+
+ if (cheat.cpu == 0)
+ {
+ debug_console_printf(machine, "Use cheatinit before cheatnext\n");
+ return;
+ }
+
+ if (!debug_command_parameter_cpu_space(machine, &cheat.cpu, AS_PROGRAM, &space))
+ return;
+
+ if (params > 1 && !debug_command_parameter_number(machine, param[1], &comp_value))
+ return;
+ comp_value = cheat_sign_extend(&cheat, comp_value);
+
+ /* decode contidion */
+ if (!strcmp(param[0], "all"))
+ condition = CHEAT_ALL;
+ else if (!strcmp(param[0], "equal") || !strcmp(param[0], "eq"))
+ condition = (params > 1) ? CHEAT_EQUALTO : CHEAT_EQUAL;
+ else if (!strcmp(param[0], "notequal") || !strcmp(param[0], "ne"))
+ condition = (params > 1) ? CHEAT_NOTEQUALTO : CHEAT_NOTEQUAL;
+ else if (!strcmp(param[0], "decrease") || !strcmp(param[0], "de") || !strcmp(param[0], "-"))
+ condition = (params > 1) ? CHEAT_DECREASEOF : CHEAT_DECREASE;
+ else if (!strcmp(param[0], "increase") || !strcmp(param[0], "in") || !strcmp(param[0], "+"))
+ condition = (params > 1) ? CHEAT_INCREASEOF : CHEAT_INCREASE;
+ else if (!strcmp(param[0], "decreaseorequal") || !strcmp(param[0], "deeq"))
+ condition = CHEAT_DECREASE_OR_EQUAL;
+ else if (!strcmp(param[0], "increaseorequal") || !strcmp(param[0], "ineq"))
+ condition = CHEAT_INCREASE_OR_EQUAL;
+ else if (!strcmp(param[0], "smallerof") || !strcmp(param[0], "lt") || !strcmp(param[0], "<"))
+ condition = CHEAT_SMALLEROF;
+ else if (!strcmp(param[0], "greaterof") || !strcmp(param[0], "gt") || !strcmp(param[0], ">"))
+ condition = CHEAT_GREATEROF;
+ else if (!strcmp(param[0], "changedby") || !strcmp(param[0], "ch") || !strcmp(param[0], "~"))
+ condition = CHEAT_CHANGEDBY;
+ else
+ {
+ debug_console_printf(machine, "Invalid condition type\n");
+ return;
+ }
+
+ cheat.undo++;
+
+ /* execute the search */
+ for (cheatindex = 0; cheatindex < cheat.length; cheatindex += 1)
+ if (cheat.cheatmap[cheatindex].state == 1)
+ {
+ UINT64 cheat_value = cheat_read_extended(&cheat, space, cheat.cheatmap[cheatindex].offset);
+ UINT64 comp_byte = (ref == 0) ? cheat.cheatmap[cheatindex].previous_value : cheat.cheatmap[cheatindex].first_value;
+ UINT8 disable_byte = FALSE;
+
+ switch (condition)
+ {
+ case CHEAT_ALL:
+ break;
+
+ case CHEAT_EQUAL:
+ disable_byte = (cheat_value != comp_byte);
+ break;
+
+ case CHEAT_NOTEQUAL:
+ disable_byte = (cheat_value == comp_byte);
+ break;
+
+ case CHEAT_EQUALTO:
+ disable_byte = (cheat_value != comp_value);
+ break;
+
+ case CHEAT_NOTEQUALTO:
+ disable_byte = (cheat_value == comp_value);
+ break;
+
+ case CHEAT_DECREASE:
+ if (cheat.signed_cheat)
+ disable_byte = ((INT64)cheat_value >= (INT64)comp_byte);
+ else
+ disable_byte = ((UINT64)cheat_value >= (UINT64)comp_byte);
+ break;
+
+ case CHEAT_INCREASE:
+ if (cheat.signed_cheat)
+ disable_byte = ((INT64)cheat_value <= (INT64)comp_byte);
+ else
+ disable_byte = ((UINT64)cheat_value <= (UINT64)comp_byte);
+ break;
+
+ case CHEAT_DECREASE_OR_EQUAL:
+ if (cheat.signed_cheat)
+ disable_byte = ((INT64)cheat_value > (INT64)comp_byte);
+ else
+ disable_byte = ((UINT64)cheat_value > (UINT64)comp_byte);
+ break;
+
+ case CHEAT_INCREASE_OR_EQUAL:
+ if (cheat.signed_cheat)
+ disable_byte = ((INT64)cheat_value < (INT64)comp_byte);
+ else
+ disable_byte = ((UINT64)cheat_value < (UINT64)comp_byte);
+ break;
+
+ case CHEAT_DECREASEOF:
+ disable_byte = (cheat_value != comp_byte - comp_value);
+ break;
+
+ case CHEAT_INCREASEOF:
+ disable_byte = (cheat_value != comp_byte + comp_value);
+ break;
+
+ case CHEAT_SMALLEROF:
+ if (cheat.signed_cheat)
+ disable_byte = ((INT64)cheat_value >= (INT64)comp_value);
+ else
+ disable_byte = ((UINT64)cheat_value >= (UINT64)comp_value);
+ break;
+
+ case CHEAT_GREATEROF:
+ if (cheat.signed_cheat)
+ disable_byte = ((INT64)cheat_value <= (INT64)comp_value);
+ else
+ disable_byte = ((UINT64)cheat_value <= (UINT64)comp_value);
+ break;
+ case CHEAT_CHANGEDBY:
+ if (cheat_value > comp_byte)
+ disable_byte = (cheat_value != comp_byte + comp_value);
+ else
+ disable_byte = (cheat_value != comp_byte - comp_value);
+ break;
+ }
+
+ if (disable_byte)
+ {
+ cheat.cheatmap[cheatindex].state = 0;
+ cheat.cheatmap[cheatindex].undo = cheat.undo;
+ }
+ else
+ active_cheat++;
+
+ /* update previous value */
+ cheat.cheatmap[cheatindex].previous_value = cheat_value;
+ }
+
+ if (active_cheat <= 5)
+ execute_cheatlist(machine, 0, 0, NULL);
+
+ debug_console_printf(machine, "%u cheats found\n", active_cheat);
+}
+
+
+/*-------------------------------------------------
+ execute_cheatlist - show a list of active cheat
+-------------------------------------------------*/
+
+static void execute_cheatlist(running_machine &machine, int ref, int params, const char *param[])
+{
+ char spaceletter, sizeletter;
+ address_space *space;
+ device_t *cpu;
+ UINT32 active_cheat = 0;
+ UINT64 cheatindex;
+ UINT64 sizemask;
+ FILE *f = NULL;
+
+ if (!debug_command_parameter_cpu_space(machine, &cheat.cpu, AS_PROGRAM, &space))
+ return;
+
+ if (!debug_command_parameter_cpu(machine, &cheat.cpu, &cpu))
+ return;
+
+ if (params > 0)
+ f = fopen(param[0], "w");
+
+ switch (space->spacenum())
+ {
+ default:
+ case AS_PROGRAM: spaceletter = 'p'; break;
+ case AS_DATA: spaceletter = 'd'; break;
+ case AS_IO: spaceletter = 'i'; break;
+ }
+
+ switch (cheat.width)
+ {
+ default:
+ case 1: sizeletter = 'b'; sizemask = 0xff; break;
+ case 2: sizeletter = 'w'; sizemask = 0xffff; break;
+ case 4: sizeletter = 'd'; sizemask = 0xffffffff; break;
+ case 8: sizeletter = 'q'; sizemask = U64(0xffffffffffffffff); break;
+ }
+
+ /* write the cheat list */
+ for (cheatindex = 0; cheatindex < cheat.length; cheatindex += 1)
+ {
+ if (cheat.cheatmap[cheatindex].state == 1)
+ {
+ UINT64 value = cheat_byte_swap(&cheat, cheat_read_extended(&cheat, space, cheat.cheatmap[cheatindex].offset)) & sizemask;
+ offs_t address = space->byte_to_address(cheat.cheatmap[cheatindex].offset);
+
+ if (params > 0)
+ {
+ active_cheat++;
+ fprintf(f, " <cheat desc=\"Possibility %d : %s (%s)\">\n", active_cheat, core_i64_hex_format(address, space->logaddrchars()), core_i64_hex_format(value, cheat.width * 2));
+ fprintf(f, " <script state=\"run\">\n");
+ fprintf(f, " <action>%s.p%c%c@%s=%s</action>\n", cpu->tag(), spaceletter, sizeletter, core_i64_hex_format(address, space->logaddrchars()), core_i64_hex_format(cheat_byte_swap(&cheat, cheat.cheatmap[cheatindex].first_value) & sizemask, cheat.width * 2));
+ fprintf(f, " </script>\n");
+ fprintf(f, " </cheat>\n\n");
+ }
+ else
+ debug_console_printf(machine, "Address=%s Start=%s Current=%s\n", core_i64_hex_format(address, space->logaddrchars()), core_i64_hex_format(cheat_byte_swap(&cheat, cheat.cheatmap[cheatindex].first_value) & sizemask, cheat.width * 2), core_i64_hex_format(value, cheat.width * 2));
+ }
+ }
+ if (params > 0)
+ fclose(f);
+}
+
+
+/*-------------------------------------------------
+ execute_cheatundo - undo the last search
+-------------------------------------------------*/
+
+static void execute_cheatundo(running_machine &machine, int ref, int params, const char *param[])
+{
+ UINT64 cheatindex;
+ UINT32 undo_count = 0;
+
+ if (cheat.undo > 0)
+ {
+ for (cheatindex = 0; cheatindex < cheat.length; cheatindex += 1)
+ {
+ if (cheat.cheatmap[cheatindex].undo == cheat.undo)
+ {
+ cheat.cheatmap[cheatindex].state = 1;
+ cheat.cheatmap[cheatindex].undo = 0;
+ undo_count++;
+ }
+ }
+
+ cheat.undo--;
+ debug_console_printf(machine, "%u cheat reactivated\n", undo_count);
+ }
+ else
+ debug_console_printf(machine, "Maximum undo reached\n");
+}
+
+
+/*-------------------------------------------------
+ execute_find - execute the find command
+-------------------------------------------------*/
+
+static void execute_find(running_machine &machine, int ref, int params, const char *param[])
+{
+ UINT64 offset, endoffset, length;
+ address_space *space;
+ UINT64 data_to_find[256];
+ UINT8 data_size[256];
+ int cur_data_size;
+ int data_count = 0;
+ int found = 0;
+ UINT64 i, j;
+
+ /* validate parameters */
+ if (!debug_command_parameter_number(machine, param[0], &offset))
+ return;
+ if (!debug_command_parameter_number(machine, param[1], &length))
+ return;
+ if (!debug_command_parameter_cpu_space(machine, NULL, ref, &space))
+ return;
+
+ /* further validation */
+ endoffset = space->address_to_byte(offset + length - 1) & space->bytemask();
+ offset = space->address_to_byte(offset) & space->bytemask();
+ cur_data_size = space->address_to_byte(1);
+ if (cur_data_size == 0)
+ cur_data_size = 1;
+
+ /* parse the data parameters */
+ for (i = 2; i < params; i++)
+ {
+ const char *pdata = param[i];
+
+ /* check for a string */
+ if (pdata[0] == '"' && pdata[strlen(pdata) - 1] == '"')
+ {
+ for (j = 1; j < strlen(pdata) - 1; j++)
+ {
+ data_to_find[data_count] = pdata[j];
+ data_size[data_count++] = 1;
+ }
+ }
+
+ /* otherwise, validate as a number */
+ else
+ {
+ /* check for a 'b','w','d',or 'q' prefix */
+ data_size[data_count] = cur_data_size;
+ if (tolower((UINT8)pdata[0]) == 'b' && pdata[1] == '.') { data_size[data_count] = cur_data_size = 1; pdata += 2; }
+ if (tolower((UINT8)pdata[0]) == 'w' && pdata[1] == '.') { data_size[data_count] = cur_data_size = 2; pdata += 2; }
+ if (tolower((UINT8)pdata[0]) == 'd' && pdata[1] == '.') { data_size[data_count] = cur_data_size = 4; pdata += 2; }
+ if (tolower((UINT8)pdata[0]) == 'q' && pdata[1] == '.') { data_size[data_count] = cur_data_size = 8; pdata += 2; }
+
+ /* look for a wildcard */
+ if (!strcmp(pdata, "?"))
+ data_size[data_count++] |= 0x10;
+
+ /* otherwise, validate as a number */
+ else if (!debug_command_parameter_number(machine, pdata, &data_to_find[data_count++]))
+ return;
+ }
+ }
+
+ /* now search */
+ for (i = offset; i <= endoffset; i += data_size[0])
+ {
+ int suboffset = 0;
+ int match = 1;
+
+ /* find the entire string */
+ for (j = 0; j < data_count && match; j++)
+ {
+ switch (data_size[j])
+ {
+ case 1: match = ((UINT8)debug_read_byte(space, i + suboffset, TRUE) == (UINT8)data_to_find[j]); break;
+ case 2: match = ((UINT16)debug_read_word(space, i + suboffset, TRUE) == (UINT16)data_to_find[j]); break;
+ case 4: match = ((UINT32)debug_read_dword(space, i + suboffset, TRUE) == (UINT32)data_to_find[j]); break;
+ case 8: match = ((UINT64)debug_read_qword(space, i + suboffset, TRUE) == (UINT64)data_to_find[j]); break;
+ default: /* all other cases are wildcards */ break;
+ }
+ suboffset += data_size[j] & 0x0f;
+ }
+
+ /* did we find it? */
+ if (match)
+ {
+ found++;
+ debug_console_printf(machine, "Found at %s\n", core_i64_hex_format((UINT32)space->byte_to_address(i), space->addrchars()));
+ }
+ }
+
+ /* print something if not found */
+ if (found == 0)
+ debug_console_printf(machine, "Not found\n");
+}
+
+
+/*-------------------------------------------------
+ execute_dasm - execute the dasm command
+-------------------------------------------------*/
+
+static void execute_dasm(running_machine &machine, int ref, int params, const char *param[])
+{
+ UINT64 offset, length, bytes = 1;
+ int minbytes, maxbytes, byteswidth;
+ address_space *space;
+ FILE *f = NULL;
+ int i, j;
+
+ /* validate parameters */
+ if (!debug_command_parameter_number(machine, param[1], &offset))
+ return;
+ if (!debug_command_parameter_number(machine, param[2], &length))
+ return;
+ if (!debug_command_parameter_number(machine, param[3], &bytes))
+ return;
+ if (!debug_command_parameter_cpu_space(machine, (params > 4) ? param[4] : NULL, AS_PROGRAM, &space))
+ return;
+
+ /* determine the width of the bytes */
+ cpu_device *cpudevice = downcast<cpu_device *>(&space->device());
+ minbytes = cpudevice->min_opcode_bytes();
+ maxbytes = cpudevice->max_opcode_bytes();
+ byteswidth = 0;
+ if (bytes)
+ {
+ byteswidth = (maxbytes + (minbytes - 1)) / minbytes;
+ byteswidth *= (2 * minbytes) + 1;
+ }
+
+ /* open the file */
+ f = fopen(param[0], "w");
+ if (!f)
+ {
+ debug_console_printf(machine, "Error opening file '%s'\n", param[0]);
+ return;
+ }
+
+ /* now write the data out */
+ for (i = 0; i < length; )
+ {
+ int pcbyte = space->address_to_byte(offset + i) & space->bytemask();
+ char output[512], disasm[200];
+ const char *comment;
+ offs_t tempaddr;
+ int outdex = 0;
+ int numbytes = 0;
+
+ /* print the address */
+ outdex += sprintf(&output[outdex], "%s: ", core_i64_hex_format((UINT32)space->byte_to_address(pcbyte), space->logaddrchars()));
+
+ /* make sure we can translate the address */
+ tempaddr = pcbyte;
+ if (debug_cpu_translate(space, TRANSLATE_FETCH_DEBUG, &tempaddr))
+ {
+ UINT8 opbuf[64], argbuf[64];
+
+ /* fetch the bytes up to the maximum */
+ for (numbytes = 0; numbytes < maxbytes; numbytes++)
+ {
+ opbuf[numbytes] = debug_read_opcode(space, pcbyte + numbytes, 1, FALSE);
+ argbuf[numbytes] = debug_read_opcode(space, pcbyte + numbytes, 1, TRUE);
+ }
+
+ /* disassemble the result */
+ i += numbytes = space->device().debug()->disassemble(disasm, offset + i, opbuf, argbuf) & DASMFLAG_LENGTHMASK;
+ }
+
+ /* print the bytes */
+ if (bytes)
+ {
+ int startdex = outdex;
+ numbytes = space->address_to_byte(numbytes);
+ for (j = 0; j < numbytes; j += minbytes)
+ outdex += sprintf(&output[outdex], "%s ", core_i64_hex_format(debug_read_opcode(space, pcbyte + j, minbytes, FALSE), minbytes * 2));
+ if (outdex - startdex < byteswidth)
+ outdex += sprintf(&output[outdex], "%*s", byteswidth - (outdex - startdex), "");
+ outdex += sprintf(&output[outdex], " ");
+ }
+
+ /* add the disassembly */
+ sprintf(&output[outdex], "%s", disasm);
+
+ /* attempt to add the comment */
+ comment = space->device().debug()->comment_text(tempaddr);
+ if (comment != NULL)
+ {
+ /* somewhat arbitrary guess as to how long most disassembly lines will be [column 60] */
+ if (strlen(output) < 60)
+ {
+ /* pad the comment space out to 60 characters and null-terminate */
+ for (outdex = (int)strlen(output); outdex < 60; outdex++)
+ output[outdex] = ' ' ;
+ output[outdex] = 0 ;
+
+ sprintf(&output[strlen(output)], "// %s", comment) ;
+ }
+ else
+ sprintf(&output[strlen(output)], "\t// %s", comment) ;
+ }
+
+ /* output the result */
+ fprintf(f, "%s\n", output);
+ }
+
+ /* close the file */
+ fclose(f);
+ debug_console_printf(machine, "Data dumped successfully\n");
+}
+
+
+/*-------------------------------------------------
+ execute_trace_internal - functionality for
+ trace over and trace info
+-------------------------------------------------*/
+
+static void execute_trace_internal(running_machine &machine, int ref, int params, const char *param[], int trace_over)
+{
+ const char *action = NULL, *filename = param[0];
+ device_t *cpu;
+ FILE *f = NULL;
+ const char *mode;
+
+ /* validate parameters */
+ if (!debug_command_parameter_cpu(machine, (params > 1) ? param[1] : NULL, &cpu))
+ return;
+ if (!debug_command_parameter_command(machine, action = param[2]))
+ return;
+
+ /* further validation */
+ if (mame_stricmp(filename, "off") == 0)
+ filename = NULL;
+
+ /* open the file */
+ if (filename)
+ {
+ mode = "w";
+
+ /* opening for append? */
+ if ((filename[0] == '>') && (filename[1] == '>'))
+ {
+ mode = "a";
+ filename += 2;
+ }
+
+ f = fopen(filename, mode);
+ if (!f)
+ {
+ debug_console_printf(machine, "Error opening file '%s'\n", param[0]);
+ return;
+ }
+ }
+
+ /* do it */
+ cpu->debug()->trace(f, trace_over, action);
+ if (f)
+ debug_console_printf(machine, "Tracing CPU '%s' to file %s\n", cpu->tag(), filename);
+ else
+ debug_console_printf(machine, "Stopped tracing on CPU '%s'\n", cpu->tag());
+}
+
+
+/*-------------------------------------------------
+ execute_trace - execute the trace command
+-------------------------------------------------*/
+
+static void execute_trace(running_machine &machine, int ref, int params, const char *param[])
+{
+ execute_trace_internal(machine, ref, params, param, 0);
+}
+
+
+/*-------------------------------------------------
+ execute_traceover - execute the trace over command
+-------------------------------------------------*/
+
+static void execute_traceover(running_machine &machine, int ref, int params, const char *param[])
+{
+ execute_trace_internal(machine, ref, params, param, 1);
+}
+
+
+/*-------------------------------------------------
+ execute_traceflush - execute the trace flush command
+-------------------------------------------------*/
+
+static void execute_traceflush(running_machine &machine, int ref, int params, const char *param[])
+{
+ debug_cpu_flush_traces(machine);
+}
+
+
+/*-------------------------------------------------
+ execute_history - execute the history command
+-------------------------------------------------*/
+
+static void execute_history(running_machine &machine, int ref, int params, const char *param[])
+{
+ /* validate parameters */
+ address_space *space;
+ if (!debug_command_parameter_cpu_space(machine, (params > 0) ? param[0] : NULL, AS_PROGRAM, &space))
+ return;
+
+ UINT64 count = device_debug::HISTORY_SIZE;
+ if (!debug_command_parameter_number(machine, param[1], &count))
+ return;
+
+ /* further validation */
+ if (count > device_debug::HISTORY_SIZE)
+ count = device_debug::HISTORY_SIZE;
+
+ device_debug *debug = space->device().debug();
+
+ /* loop over lines */
+ int maxbytes = debug->max_opcode_bytes();
+ for (int index = 0; index < count; index++)
+ {
+ offs_t pc = debug->history_pc(-index);
+
+ /* fetch the bytes up to the maximum */
+ offs_t pcbyte = space->address_to_byte(pc) & space->bytemask();
+ UINT8 opbuf[64], argbuf[64];
+ for (int numbytes = 0; numbytes < maxbytes; numbytes++)
+ {
+ opbuf[numbytes] = debug_read_opcode(space, pcbyte + numbytes, 1, false);
+ argbuf[numbytes] = debug_read_opcode(space, pcbyte + numbytes, 1, true);
+ }
+
+ char buffer[200];
+ debug->disassemble(buffer, pc, opbuf, argbuf);
+
+ debug_console_printf(machine, "%s: %s\n", core_i64_hex_format(pc, space->logaddrchars()), buffer);
+ }
+}
+
+
+/*-------------------------------------------------
+ execute_snap - execute the snapshot command
+-------------------------------------------------*/
+
+static void execute_snap(running_machine &machine, int ref, int params, const char *param[])
+{
+ /* if no params, use the default behavior */
+ if (params == 0)
+ {
+ machine.video().save_active_screen_snapshots();
+ debug_console_printf(machine, "Saved snapshot\n");
+ }
+
+ /* otherwise, we have to open the file ourselves */
+ else
+ {
+ const char *filename = param[0];
+ int scrnum = (params > 1) ? atoi(param[1]) : 0;
+
+ screen_device *screen = downcast<screen_device *>(machine.devicelist().find(SCREEN, scrnum));
+
+ if ((screen == NULL) || !machine.render().is_live(*screen))
+ {
+ debug_console_printf(machine, "Invalid screen number '%d'\n", scrnum);
+ return;
+ }
+
+ astring fname(filename);
+ if (fname.find(0, ".png") == -1)
+ fname.cat(".png");
+ emu_file file(machine.options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ file_error filerr = file.open(fname);
+
+ if (filerr != FILERR_NONE)
+ {
+ debug_console_printf(machine, "Error creating file '%s'\n", filename);
+ return;
+ }
+
+ screen->machine().video().save_snapshot(screen, file);
+ debug_console_printf(machine, "Saved screen #%d snapshot as '%s'\n", scrnum, filename);
+ }
+}
+
+
+/*-------------------------------------------------
+ execute_source - execute the source command
+-------------------------------------------------*/
+
+static void execute_source(running_machine &machine, int ref, int params, const char *param[])
+{
+ debug_cpu_source_script(machine, param[0]);
+}
+
+
+/*-------------------------------------------------
+ execute_map - execute the map command
+-------------------------------------------------*/
+
+static void execute_map(running_machine &machine, int ref, int params, const char *param[])
+{
+ address_space *space;
+ offs_t taddress;
+ UINT64 address;
+ int intention;
+
+ /* validate parameters */
+ if (!debug_command_parameter_number(machine, param[0], &address))
+ return;
+
+ /* CPU is implicit */
+ if (!debug_command_parameter_cpu_space(machine, NULL, ref, &space))
+ return;
+
+ /* do the translation first */
+ for (intention = TRANSLATE_READ_DEBUG; intention <= TRANSLATE_FETCH_DEBUG; intention++)
+ {
+ static const char *const intnames[] = { "Read", "Write", "Fetch" };
+ taddress = space->address_to_byte(address) & space->bytemask();
+ if (debug_cpu_translate(space, intention, &taddress))
+ {
+ const char *mapname = const_cast<address_space *>(space)->get_handler_string((intention == TRANSLATE_WRITE_DEBUG) ? ROW_WRITE : ROW_READ, taddress);
+ debug_console_printf(machine, "%7s: %s logical == %s physical -> %s\n", intnames[intention & 3], core_i64_hex_format(address, space->logaddrchars()), core_i64_hex_format(space->byte_to_address(taddress), space->addrchars()), mapname);
+ }
+ else
+ debug_console_printf(machine, "%7s: %s logical is unmapped\n", intnames[intention & 3], core_i64_hex_format(address, space->logaddrchars()));
+ }
+}
+
+
+/*-------------------------------------------------
+ execute_memdump - execute the memdump command
+-------------------------------------------------*/
+
+static void execute_memdump(running_machine &machine, int ref, int params, const char **param)
+{
+ FILE *file;
+ const char *filename;
+
+ filename = (params == 0) ? "memdump.log" : param[0];
+
+ debug_console_printf(machine, "Dumping memory to %s\n", filename);
+
+ file = fopen(filename, "w");
+ if (file)
+ {
+ memory_dump(machine, file);
+ fclose(file);
+ }
+}
+
+
+/*-------------------------------------------------
+ execute_symlist - execute the symlist command
+-------------------------------------------------*/
+
+static int CLIB_DECL symbol_sort_compare(const void *item1, const void *item2)
+{
+ const char *str1 = *(const char **)item1;
+ const char *str2 = *(const char **)item2;
+ return strcmp(str1, str2);
+}
+
+static void execute_symlist(running_machine &machine, int ref, int params, const char **param)
+{
+ device_t *cpu = NULL;
+ const char *namelist[1000];
+ symbol_table *symtable;
+ int symnum, count = 0;
+
+
+ if (param[0] != NULL)
+ {
+ /* validate parameters */
+ if (!debug_command_parameter_cpu(machine, param[0], &cpu))
+ return;
+ symtable = &cpu->debug()->symtable();
+ debug_console_printf(machine, "CPU '%s' symbols:\n", cpu->tag());
+ }
+ else
+ {
+ symtable = debug_cpu_get_global_symtable(machine);
+ debug_console_printf(machine, "Global symbols:\n");
+ }
+
+ /* gather names for all symbols */
+ for (symbol_entry *entry = symtable->first(); entry != NULL; entry = entry->next())
+ {
+ /* only display "register" type symbols */
+ if (!entry->is_function())
+ {
+ namelist[count++] = entry->name();
+ if (count >= ARRAY_LENGTH(namelist))
+ break;
+ }
+ }
+
+ /* sort the symbols */
+ if (count > 1)
+ qsort((void *)namelist, count, sizeof(namelist[0]), symbol_sort_compare);
+
+ /* iterate over symbols and print out relevant ones */
+ for (symnum = 0; symnum < count; symnum++)
+ {
+ const symbol_entry *entry = symtable->find(namelist[symnum]);
+ assert(entry != NULL);
+ UINT64 value = entry->value();
+
+ /* only display "register" type symbols */
+ debug_console_printf(machine, "%s = %s", namelist[symnum], core_i64_hex_format(value, 0));
+ if (!entry->is_lval())
+ debug_console_printf(machine, " (read-only)");
+ debug_console_printf(machine, "\n");
+ }
+}
+
+
+/*-------------------------------------------------
+ execute_softreset - execute the softreset command
+-------------------------------------------------*/
+
+static void execute_softreset(running_machine &machine, int ref, int params, const char **param)
+{
+ machine.schedule_soft_reset();
+}
+
+
+/*-------------------------------------------------
+ execute_hardreset - execute the hardreset command
+-------------------------------------------------*/
+
+static void execute_hardreset(running_machine &machine, int ref, int params, const char **param)
+{
+ machine.schedule_hard_reset();
+}
+
+/*-------------------------------------------------
+ execute_images - lists all image devices with
+ mounted files
+-------------------------------------------------*/
+
+static void execute_images(running_machine &machine, int ref, int params, const char **param)
+{
+ device_image_interface *img = NULL;
+ for (bool gotone = machine.devicelist().first(img); gotone; gotone = img->next(img))
+ {
+ debug_console_printf(machine, "%s: %s\n",img->brief_instance_name(),img->exists() ? img->filename() : "[empty slot]");
+ }
+ if (!machine.devicelist().first(img)) {
+ debug_console_printf(machine, "No image devices in this driver\n");
+ }
+}
+
+/*-------------------------------------------------
+ execute_mount - execute the image mount command
+-------------------------------------------------*/
+
+static void execute_mount(running_machine &machine, int ref, int params, const char **param)
+{
+ device_image_interface *img = NULL;
+ bool done = false;
+ for (bool gotone = machine.devicelist().first(img); gotone; gotone = img->next(img))
+ {
+ if (strcmp(img->brief_instance_name(),param[0])==0) {
+ if (img->load(param[1])==IMAGE_INIT_FAIL) {
+ debug_console_printf(machine, "Unable to mount file %s on %s\n",param[1],param[0]);
+ } else {
+ debug_console_printf(machine, "File %s mounted on %s\n",param[1],param[0]);
+ }
+ done = true;
+ break;
+ }
+ }
+ if (!done)
+ debug_console_printf(machine, "There is no image device :%s\n",param[0]);
+}
+
+/*-------------------------------------------------
+ execute_unmount - execute the image unmount command
+-------------------------------------------------*/
+
+static void execute_unmount(running_machine &machine, int ref, int params, const char **param)
+{
+ device_image_interface *img = NULL;
+ bool done = false;
+ for (bool gotone = machine.devicelist().first(img); gotone; gotone = img->next(img))
+ {
+ if (strcmp(img->brief_instance_name(),param[0])==0) {
+ img->unload();
+ debug_console_printf(machine, "Unmounted file from : %s\n",param[0]);
+ done = true;
+ break;
+ }
+ }
+ if (!done)
+ debug_console_printf(machine, "There is no image device :%s\n",param[0]);
+}
diff --git a/trunk/src/emu/debug/debugcmd.h b/trunk/src/emu/debug/debugcmd.h
new file mode 100644
index 00000000000..0944df45f89
--- /dev/null
+++ b/trunk/src/emu/debug/debugcmd.h
@@ -0,0 +1,38 @@
+/*********************************************************************
+
+ debugcmd.h
+
+ Debugger command interface engine.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+#ifndef __DEBUGCMD_H__
+#define __DEBUGCMD_H__
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+/* ----- initialization ----- */
+
+/* initializes the command system */
+void debug_command_init(running_machine &machine);
+
+
+
+/* ----- parameter validation ----- */
+
+/* validates a number parameter */
+int debug_command_parameter_number(running_machine &machine, const char *param, UINT64 *result);
+
+/* validates a parameter as a cpu */
+int debug_command_parameter_cpu(running_machine &machine, const char *param, device_t **result);
+
+/* validates a parameter as a cpu and retrieves the given address space */
+int debug_command_parameter_cpu_space(running_machine &machine, const char *param, int spacenum, address_space **result);
+
+#endif
diff --git a/trunk/src/emu/debug/debugcon.c b/trunk/src/emu/debug/debugcon.c
new file mode 100644
index 00000000000..6cb821ad810
--- /dev/null
+++ b/trunk/src/emu/debug/debugcon.c
@@ -0,0 +1,568 @@
+/*********************************************************************
+
+ debugcon.c
+
+ Debugger console engine.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "debugcon.h"
+#include "debugcpu.h"
+#include "debughlp.h"
+#include "debugvw.h"
+#include "textbuf.h"
+#include "debugger.h"
+#include <ctype.h>
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define CONSOLE_BUF_SIZE (1024 * 1024)
+#define CONSOLE_MAX_LINES (CONSOLE_BUF_SIZE / 20)
+
+#define ERRORLOG_BUF_SIZE (1024 * 1024)
+#define ERRORLOG_MAX_LINES (ERRORLOG_BUF_SIZE / 20)
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _debug_command debug_command;
+struct _debug_command
+{
+ debug_command * next;
+ char command[32];
+ const char * params;
+ const char * help;
+ void (*handler)(running_machine &machine, int ref, int params, const char **param);
+ void (*handler_ex)(int ref);
+ UINT32 flags;
+ int ref;
+ int minparams;
+ int maxparams;
+};
+
+
+
+/***************************************************************************
+ LOCAL VARIABLES
+***************************************************************************/
+
+static text_buffer *console_textbuf;
+static text_buffer *errorlog_textbuf;
+
+static debug_command *commandlist;
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void debug_console_exit(running_machine &machine);
+
+
+
+/***************************************************************************
+
+ Initialization and tear down
+
+***************************************************************************/
+
+/*-------------------------------------------------
+ debug_console_init - initializes the console
+ system
+-------------------------------------------------*/
+
+void debug_console_init(running_machine &machine)
+{
+ /* allocate text buffers */
+ console_textbuf = text_buffer_alloc(CONSOLE_BUF_SIZE, CONSOLE_MAX_LINES);
+ if (!console_textbuf)
+ return;
+
+ errorlog_textbuf = text_buffer_alloc(ERRORLOG_BUF_SIZE, ERRORLOG_MAX_LINES);
+ if (!errorlog_textbuf)
+ return;
+
+ /* print the opening lines */
+ debug_console_printf(machine, "MAME new debugger version %s\n", build_version);
+ debug_console_printf(machine, "Currently targeting %s (%s)\n", machine.system().name, machine.system().description);
+
+ /* request callback upon exiting */
+ machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(debug_console_exit), &machine));
+}
+
+
+/*-------------------------------------------------
+ debug_console_exit - frees the console
+ system
+-------------------------------------------------*/
+
+static void debug_console_exit(running_machine &machine)
+{
+ /* free allocated memory */
+ if (console_textbuf)
+ text_buffer_free(console_textbuf);
+ console_textbuf = NULL;
+
+ if (errorlog_textbuf)
+ text_buffer_free(errorlog_textbuf);
+ errorlog_textbuf = NULL;
+
+ /* free the command list */
+ commandlist = NULL;
+}
+
+
+
+/***************************************************************************
+
+ Command Handling
+
+***************************************************************************/
+
+/*-------------------------------------------------
+ trim_parameter - executes a
+ command
+-------------------------------------------------*/
+
+static void trim_parameter(char **paramptr, int keep_quotes)
+{
+ char *param = *paramptr;
+ size_t len = strlen(param);
+ int repeat;
+
+ /* loop until all adornments are gone */
+ do
+ {
+ repeat = 0;
+
+ /* check for begin/end quotes */
+ if (len >= 2 && param[0] == '"' && param[len - 1] == '"')
+ {
+ if (!keep_quotes)
+ {
+ param[len - 1] = 0;
+ param++;
+ len -= 2;
+ }
+ }
+
+ /* check for start/end braces */
+ else if (len >= 2 && param[0] == '{' && param[len - 1] == '}')
+ {
+ param[len - 1] = 0;
+ param++;
+ len -= 2;
+ repeat = 1;
+ }
+
+ /* check for leading spaces */
+ else if (len >= 1 && param[0] == ' ')
+ {
+ param++;
+ len--;
+ repeat = 1;
+ }
+
+ /* check for trailing spaces */
+ else if (len >= 1 && param[len - 1] == ' ')
+ {
+ param[len - 1] = 0;
+ len--;
+ repeat = 1;
+ }
+ } while (repeat);
+
+ *paramptr = param;
+}
+
+
+/*-------------------------------------------------
+ internal_execute_command - executes a
+ command
+-------------------------------------------------*/
+
+static CMDERR internal_execute_command(running_machine &machine, int execute, int params, char **param)
+{
+ debug_command *cmd, *found = NULL;
+ int i, foundcount = 0;
+ char *p, *command;
+ size_t len;
+
+ /* no params is an error */
+ if (params == 0)
+ return CMDERR_NONE;
+
+ /* the first parameter has the command and the real first parameter; separate them */
+ for (p = param[0]; *p && isspace((UINT8)*p); p++) { }
+ for (command = p; *p && !isspace((UINT8)*p); p++) { }
+ if (*p != 0)
+ {
+ *p++ = 0;
+ for ( ; *p && isspace((UINT8)*p); p++) { }
+ if (*p != 0)
+ param[0] = p;
+ else
+ params = 0;
+ }
+ else
+ {
+ params = 0;
+ param[0] = NULL;
+ }
+
+ /* search the command list */
+ len = strlen(command);
+ for (cmd = commandlist; cmd != NULL; cmd = cmd->next)
+ if (!strncmp(command, cmd->command, len))
+ {
+ foundcount++;
+ found = cmd;
+ if (strlen(cmd->command) == len)
+ {
+ foundcount = 1;
+ break;
+ }
+ }
+
+ /* error if not found */
+ if (!found)
+ return MAKE_CMDERR_UNKNOWN_COMMAND(0);
+ if (foundcount > 1)
+ return MAKE_CMDERR_AMBIGUOUS_COMMAND(0);
+
+ /* NULL-terminate and trim space around all the parameters */
+ for (i = 1; i < params; i++)
+ *param[i]++ = 0;
+
+ /* now go back and trim quotes and braces and any spaces they reveal*/
+ for (i = 0; i < params; i++)
+ trim_parameter(&param[i], found->flags & CMDFLAG_KEEP_QUOTES);
+
+ /* see if we have the right number of parameters */
+ if (params < found->minparams)
+ return MAKE_CMDERR_NOT_ENOUGH_PARAMS(0);
+ if (params > found->maxparams)
+ return MAKE_CMDERR_TOO_MANY_PARAMS(0);
+
+ /* execute the handler */
+ if (execute)
+ (*found->handler)(machine, found->ref, params, (const char **)param);
+ return CMDERR_NONE;
+}
+
+
+/*-------------------------------------------------
+ internal_parse_command - parses a command
+ and either executes or just validates it
+-------------------------------------------------*/
+
+static CMDERR internal_parse_command(running_machine &machine, const char *original_command, int execute)
+{
+ char command[MAX_COMMAND_LENGTH], parens[MAX_COMMAND_LENGTH];
+ char *params[MAX_COMMAND_PARAMS] = { 0 };
+ CMDERR result = CMDERR_NONE;
+ char *command_start;
+ char *p, c = 0;
+
+ /* make a copy of the command */
+ strcpy(command, original_command);
+
+ /* loop over all semicolon-separated stuff */
+ for (p = command; *p != 0; )
+ {
+ int paramcount = 0, foundend = FALSE, instring = FALSE, isexpr = FALSE, parendex = 0;
+
+ /* find a semicolon or the end */
+ for (params[paramcount++] = p; !foundend; p++)
+ {
+ c = *p;
+ if (instring)
+ {
+ if (c == '"' && p[-1] != '\\')
+ instring = FALSE;
+ }
+ else
+ {
+ switch (c)
+ {
+ case '"': instring = TRUE; break;
+ case '(':
+ case '[':
+ case '{': parens[parendex++] = c; break;
+ case ')': if (parendex == 0 || parens[--parendex] != '(') return MAKE_CMDERR_UNBALANCED_PARENS(p - command); break;
+ case ']': if (parendex == 0 || parens[--parendex] != '[') return MAKE_CMDERR_UNBALANCED_PARENS(p - command); break;
+ case '}': if (parendex == 0 || parens[--parendex] != '{') return MAKE_CMDERR_UNBALANCED_PARENS(p - command); break;
+ case ',': if (parendex == 0) params[paramcount++] = p; break;
+ case ';': if (parendex == 0) foundend = TRUE; break;
+ case '-': if (parendex == 0 && paramcount == 1 && p[1] == '-') isexpr = TRUE; *p = c; break;
+ case '+': if (parendex == 0 && paramcount == 1 && p[1] == '+') isexpr = TRUE; *p = c; break;
+ case '=': if (parendex == 0 && paramcount == 1) isexpr = TRUE; *p = c; break;
+ case 0: foundend = TRUE; break;
+ default: *p = tolower((UINT8)c); break;
+ }
+ }
+ }
+
+ /* check for unbalanced parentheses or quotes */
+ if (instring)
+ return MAKE_CMDERR_UNBALANCED_QUOTES(p - command);
+ if (parendex != 0)
+ return MAKE_CMDERR_UNBALANCED_PARENS(p - command);
+
+ /* NULL-terminate if we ended in a semicolon */
+ p--;
+ if (c == ';') *p++ = 0;
+
+ /* process the command */
+ command_start = params[0];
+
+ /* allow for "do" commands */
+ if (tolower((UINT8)command_start[0] == 'd') && tolower((UINT8)command_start[1] == 'o') && isspace((UINT8)command_start[2]))
+ {
+ isexpr = TRUE;
+ command_start += 3;
+ }
+
+ /* if it smells like an assignment expression, treat it as such */
+ if (isexpr && paramcount == 1)
+ {
+ try
+ {
+ UINT64 expresult;
+ parsed_expression expression(debug_cpu_get_visible_symtable(machine), command_start, &expresult);
+ }
+ catch (expression_error &err)
+ {
+ return MAKE_CMDERR_EXPRESSION_ERROR(err);
+ }
+ }
+ else
+ {
+ result = internal_execute_command(machine, execute, paramcount, &params[0]);
+ if (result != CMDERR_NONE)
+ return MAKE_CMDERR(CMDERR_ERROR_CLASS(result), command_start - command);
+ }
+ }
+ return CMDERR_NONE;
+}
+
+
+/*-------------------------------------------------
+ debug_console_execute_command - execute a
+ command string
+-------------------------------------------------*/
+
+CMDERR debug_console_execute_command(running_machine &machine, const char *command, int echo)
+{
+ CMDERR result;
+
+ /* echo if requested */
+ if (echo)
+ debug_console_printf(machine, ">%s\n", command);
+
+ /* parse and execute */
+ result = internal_parse_command(machine, command, TRUE);
+
+ /* display errors */
+ if (result != CMDERR_NONE)
+ {
+ if (!echo)
+ debug_console_printf(machine, ">%s\n", command);
+ debug_console_printf(machine, " %*s^\n", CMDERR_ERROR_OFFSET(result), "");
+ debug_console_printf(machine, "%s\n", debug_cmderr_to_string(result));
+ }
+
+ /* update all views */
+ if (echo)
+ {
+ machine.debug_view().update_all();
+ debugger_refresh_display(machine);
+ }
+ return result;
+}
+
+
+/*-------------------------------------------------
+ debug_console_validate_command - validate a
+ command string
+-------------------------------------------------*/
+
+CMDERR debug_console_validate_command(running_machine &machine, const char *command)
+{
+ return internal_parse_command(machine, command, FALSE);
+}
+
+
+/*-------------------------------------------------
+ debug_console_register_command - register a
+ command handler
+-------------------------------------------------*/
+
+void debug_console_register_command(running_machine &machine, const char *command, UINT32 flags, int ref, int minparams, int maxparams, void (*handler)(running_machine &machine, int ref, int params, const char **param))
+{
+ debug_command *cmd;
+
+ assert_always(machine.phase() == MACHINE_PHASE_INIT, "Can only call debug_console_register_command() at init time!");
+ assert_always((machine.debug_flags & DEBUG_FLAG_ENABLED) != 0, "Cannot call debug_console_register_command() when debugger is not running");
+
+ cmd = auto_alloc_clear(machine, debug_command);
+
+ /* fill in the command */
+ strcpy(cmd->command, command);
+ cmd->flags = flags;
+ cmd->ref = ref;
+ cmd->minparams = minparams;
+ cmd->maxparams = maxparams;
+ cmd->handler = handler;
+
+ /* link it */
+ cmd->next = commandlist;
+ commandlist = cmd;
+}
+
+
+
+/***************************************************************************
+
+ Error Handling
+
+***************************************************************************/
+
+/*-------------------------------------------------
+ debug_cmderr_to_string - return a friendly
+ string for a given command error
+-------------------------------------------------*/
+
+const char *debug_cmderr_to_string(CMDERR error)
+{
+ switch (CMDERR_ERROR_CLASS(error))
+ {
+ case CMDERR_UNKNOWN_COMMAND: return "unknown command";
+ case CMDERR_AMBIGUOUS_COMMAND: return "ambiguous command";
+ case CMDERR_UNBALANCED_PARENS: return "unbalanced parentheses";
+ case CMDERR_UNBALANCED_QUOTES: return "unbalanced quotes";
+ case CMDERR_NOT_ENOUGH_PARAMS: return "not enough parameters for command";
+ case CMDERR_TOO_MANY_PARAMS: return "too many parameters for command";
+ case CMDERR_EXPRESSION_ERROR: return "error in assignment expression";
+ default: return "unknown error";
+ }
+}
+
+
+
+/***************************************************************************
+
+ Console Management
+
+***************************************************************************/
+
+/*-------------------------------------------------
+ debug_console_printf - printfs the given
+ arguments using the format to the debug
+ console
+-------------------------------------------------*/
+
+void CLIB_DECL debug_console_printf(running_machine &machine, const char *format, ...)
+{
+ astring buffer;
+ va_list arg;
+
+ va_start(arg, format);
+ buffer.vprintf(format, arg);
+ va_end(arg);
+
+ text_buffer_print(console_textbuf, buffer);
+
+ /* force an update of any console views */
+ machine.debug_view().update_all(DVT_CONSOLE);
+}
+
+
+/*-------------------------------------------------
+ debug_console_vprintf - printfs the given
+ arguments using the format to the debug
+ console
+-------------------------------------------------*/
+
+void CLIB_DECL debug_console_vprintf(running_machine &machine, const char *format, va_list args)
+{
+ astring buffer;
+
+ buffer.vprintf(format, args);
+ text_buffer_print(console_textbuf, buffer);
+
+ /* force an update of any console views */
+ machine.debug_view().update_all(DVT_CONSOLE);
+}
+
+
+/*-------------------------------------------------
+ debug_console_printf_wrap - printfs the given
+ arguments using the format to the debug
+ console
+-------------------------------------------------*/
+
+void CLIB_DECL debug_console_printf_wrap(running_machine &machine, int wrapcol, const char *format, ...)
+{
+ astring buffer;
+ va_list arg;
+
+ va_start(arg, format);
+ buffer.vprintf(format, arg);
+ va_end(arg);
+
+ text_buffer_print_wrap(console_textbuf, buffer, wrapcol);
+
+ /* force an update of any console views */
+ machine.debug_view().update_all(DVT_CONSOLE);
+}
+
+
+/*-------------------------------------------------
+ debug_console_get_textbuf - return a pointer
+ to the console text buffer
+-------------------------------------------------*/
+
+text_buffer *debug_console_get_textbuf(void)
+{
+ return console_textbuf;
+}
+
+
+/*-------------------------------------------------
+ debug_errorlog_write_line - writes a line to
+ the errorlog ring buffer
+-------------------------------------------------*/
+
+void debug_errorlog_write_line(running_machine &machine, const char *line)
+{
+ if (errorlog_textbuf)
+ text_buffer_print(errorlog_textbuf, line);
+
+ /* force an update of any log views */
+ machine.debug_view().update_all(DVT_LOG);
+}
+
+
+/*-------------------------------------------------
+ debug_errorlog_get_textbuf - return a pointer
+ to the errorlog text buffer
+-------------------------------------------------*/
+
+text_buffer *debug_errorlog_get_textbuf(void)
+{
+ return errorlog_textbuf;
+}
+
diff --git a/trunk/src/emu/debug/debugcon.h b/trunk/src/emu/debug/debugcon.h
new file mode 100644
index 00000000000..9977a19b578
--- /dev/null
+++ b/trunk/src/emu/debug/debugcon.h
@@ -0,0 +1,96 @@
+/*********************************************************************
+
+ debugcon.h
+
+ Debugger console engine.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+#ifndef __DEBUGCON_H__
+#define __DEBUGCON_H__
+
+#include "textbuf.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define MAX_COMMAND_LENGTH 512
+#define MAX_COMMAND_PARAMS 16
+
+/* flags for command parsing */
+#define CMDFLAG_NONE (0x0000)
+#define CMDFLAG_KEEP_QUOTES (0x0001)
+
+/* values for the error code in a command error */
+#define CMDERR_NONE (0)
+#define CMDERR_UNKNOWN_COMMAND (1)
+#define CMDERR_AMBIGUOUS_COMMAND (2)
+#define CMDERR_UNBALANCED_PARENS (3)
+#define CMDERR_UNBALANCED_QUOTES (4)
+#define CMDERR_NOT_ENOUGH_PARAMS (5)
+#define CMDERR_TOO_MANY_PARAMS (6)
+#define CMDERR_EXPRESSION_ERROR (7)
+
+/* parameter separator macros */
+#define CMDPARAM_SEPARATOR "\0"
+#define CMDPARAM_TERMINATOR "\0\0"
+
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+/* command error assembly/disassembly macros */
+#define CMDERR_ERROR_CLASS(x) ((x) >> 16)
+#define CMDERR_ERROR_OFFSET(x) ((x) & 0xffff)
+#define MAKE_CMDERR(a,b) (((a) << 16) | ((b) & 0xffff))
+
+/* macros to assemble specific error conditions */
+#define MAKE_CMDERR_UNKNOWN_COMMAND(x) MAKE_CMDERR(CMDERR_UNKNOWN_COMMAND, (x))
+#define MAKE_CMDERR_AMBIGUOUS_COMMAND(x) MAKE_CMDERR(CMDERR_AMBIGUOUS_COMMAND, (x))
+#define MAKE_CMDERR_UNBALANCED_PARENS(x) MAKE_CMDERR(CMDERR_UNBALANCED_PARENS, (x))
+#define MAKE_CMDERR_UNBALANCED_QUOTES(x) MAKE_CMDERR(CMDERR_UNBALANCED_QUOTES, (x))
+#define MAKE_CMDERR_NOT_ENOUGH_PARAMS(x) MAKE_CMDERR(CMDERR_NOT_ENOUGH_PARAMS, (x))
+#define MAKE_CMDERR_TOO_MANY_PARAMS(x) MAKE_CMDERR(CMDERR_TOO_MANY_PARAMS, (x))
+#define MAKE_CMDERR_EXPRESSION_ERROR(x) MAKE_CMDERR(CMDERR_EXPRESSION_ERROR, (x))
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/* CMDERR is an error code for command evaluation */
+typedef UINT32 CMDERR;
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+/* initialization */
+void debug_console_init(running_machine &machine);
+
+/* command handling */
+CMDERR debug_console_execute_command(running_machine &machine, const char *command, int echo);
+CMDERR debug_console_validate_command(running_machine &machine, const char *command);
+void debug_console_register_command(running_machine &machine, const char *command, UINT32 flags, int ref, int minparams, int maxparams, void (*handler)(running_machine &machine, int ref, int params, const char **param));
+const char * debug_cmderr_to_string(CMDERR error);
+
+/* console management */
+void CLIB_DECL debug_console_printf(running_machine &machine, const char *format, ...) ATTR_PRINTF(2,3);
+void CLIB_DECL debug_console_vprintf(running_machine &machine, const char *format, va_list args);
+void CLIB_DECL debug_console_printf_wrap(running_machine &machine, int wrapcol, const char *format, ...) ATTR_PRINTF(3,4);
+text_buffer * debug_console_get_textbuf(void);
+
+/* errorlog management */
+void debug_errorlog_write_line(running_machine &machine, const char *line);
+text_buffer * debug_errorlog_get_textbuf(void);
+
+#endif
diff --git a/trunk/src/emu/debug/debugcpu.c b/trunk/src/emu/debug/debugcpu.c
new file mode 100644
index 00000000000..ad260552815
--- /dev/null
+++ b/trunk/src/emu/debug/debugcpu.c
@@ -0,0 +1,3376 @@
+/*********************************************************************
+
+ debugcpu.c
+
+ Debugger CPU/memory interface engine.
+
+****************************************************************************
+
+ 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 "osdepend.h"
+#include "debugcpu.h"
+#include "debugcmd.h"
+#include "debugcon.h"
+#include "express.h"
+#include "debugvw.h"
+#include "debugger.h"
+#include "debugint/debugint.h"
+#include "uiinput.h"
+#include "xmlfile.h"
+#include <ctype.h>
+#include <zlib.h>
+#if defined(SDLMAME_FREEBSD) || defined(SDLMAME_NETBSD) || defined(SDLMAME_OS2)
+# undef tolower
+#endif
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define NUM_TEMP_VARIABLES 10
+
+enum
+{
+ EXECUTION_STATE_STOPPED,
+ EXECUTION_STATE_RUNNING
+};
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/* in mame.h: typedef struct _debugcpu_private debugcpu_private; */
+struct _debugcpu_private
+{
+ device_t *livecpu;
+ device_t *visiblecpu;
+ device_t *breakcpu;
+
+ FILE * source_file; /* script source file */
+
+ symbol_table * symtable; /* global symbol table */
+
+ bool within_instruction_hook;
+ bool vblank_occurred;
+ bool memory_modified;
+ bool debugger_access;
+
+ int execution_state;
+ device_t * m_stop_when_not_device; // stop execution when the device ceases to be this
+
+ UINT32 bpindex;
+ UINT32 wpindex;
+
+ UINT64 wpdata;
+ UINT64 wpaddr;
+ UINT64 tempvar[NUM_TEMP_VARIABLES];
+
+ osd_ticks_t last_periodic_update_time;
+
+ bool comments_loaded;
+};
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+/* internal helpers */
+static void debug_cpu_exit(running_machine &machine);
+static void on_vblank(running_machine &machine, screen_device &device, bool vblank_state);
+static void reset_transient_flags(running_machine &machine);
+static void process_source_file(running_machine &machine);
+
+/* expression handlers */
+static UINT64 expression_read_memory(void *param, const char *name, expression_space space, UINT32 address, int size);
+static UINT64 expression_read_program_direct(address_space *space, int opcode, offs_t address, int size);
+static UINT64 expression_read_memory_region(running_machine &machine, const char *rgntag, offs_t address, int size);
+static void expression_write_memory(void *param, const char *name, expression_space space, UINT32 address, int size, UINT64 data);
+static void expression_write_program_direct(address_space *space, int opcode, offs_t address, int size, UINT64 data);
+static void expression_write_memory_region(running_machine &machine, const char *rgntag, offs_t address, int size, UINT64 data);
+static expression_error::error_code expression_validate(void *param, const char *name, expression_space space);
+
+/* variable getters/setters */
+static UINT64 get_cpunum(symbol_table &table, void *ref);
+static UINT64 get_beamx(symbol_table &table, void *ref);
+static UINT64 get_beamy(symbol_table &table, void *ref);
+static UINT64 get_frame(symbol_table &table, void *ref);
+
+
+
+/***************************************************************************
+ INITIALIZATION AND CLEANUP
+***************************************************************************/
+
+/*-------------------------------------------------
+ debug_cpu_init - initialize the CPU
+ information for debugging
+-------------------------------------------------*/
+
+void debug_cpu_init(running_machine &machine)
+{
+ screen_device *first_screen = machine.first_screen();
+ debugcpu_private *global;
+ int regnum;
+
+ /* allocate and reset globals */
+ machine.debugcpu_data = global = auto_alloc_clear(machine, debugcpu_private);
+ global->execution_state = EXECUTION_STATE_STOPPED;
+ global->bpindex = 1;
+ global->wpindex = 1;
+
+ /* create a global symbol table */
+ global->symtable = global_alloc(symbol_table(&machine));
+
+ // configure our base memory accessors
+ debug_cpu_configure_memory(machine, *global->symtable);
+
+ /* add "wpaddr", "wpdata", "cycles", "cpunum", "logunmap" to the global symbol table */
+ global->symtable->add("wpaddr", symbol_table::READ_ONLY, &global->wpaddr);
+ global->symtable->add("wpdata", symbol_table::READ_ONLY, &global->wpdata);
+ global->symtable->add("cpunum", NULL, get_cpunum);
+ global->symtable->add("beamx", (void *)first_screen, get_beamx);
+ global->symtable->add("beamy", (void *)first_screen, get_beamy);
+ global->symtable->add("frame", (void *)first_screen, get_frame);
+
+ /* add the temporary variables to the global symbol table */
+ for (regnum = 0; regnum < NUM_TEMP_VARIABLES; regnum++)
+ {
+ char symname[10];
+ sprintf(symname, "temp%d", regnum);
+ global->symtable->add(symname, symbol_table::READ_WRITE, &global->tempvar[regnum]);
+ }
+
+ /* first CPU is visible by default */
+ global->visiblecpu = machine.firstcpu;
+
+ /* add callback for breaking on VBLANK */
+ if (machine.primary_screen != NULL)
+ machine.primary_screen->register_vblank_callback(vblank_state_delegate(FUNC(on_vblank), &machine));
+
+ machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(debug_cpu_exit), &machine));
+}
+
+
+void debug_cpu_configure_memory(running_machine &machine, symbol_table &table)
+{
+ table.configure_memory(&machine, expression_validate, expression_read_memory, expression_write_memory);
+}
+
+
+/*-------------------------------------------------
+ debug_cpu_flush_traces - flushes all traces;
+ this is useful if a trace is going on when we
+ fatalerror
+-------------------------------------------------*/
+
+void debug_cpu_flush_traces(running_machine &machine)
+{
+ /* this can be called on exit even when no debugging is enabled, so
+ make sure the devdebug is valid before proceeding */
+ for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next())
+ if (device->debug() != NULL)
+ device->debug()->trace_flush();
+}
+
+
+
+/***************************************************************************
+ DEBUGGING STATUS AND INFORMATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ cpu_get_visible_cpu - return the visible CPU
+ device (the one that commands should apply to)
+-------------------------------------------------*/
+
+device_t *debug_cpu_get_visible_cpu(running_machine &machine)
+{
+ return machine.debugcpu_data->visiblecpu;
+}
+
+
+/*-------------------------------------------------
+ debug_cpu_within_instruction_hook - true if
+ the debugger is currently live
+-------------------------------------------------*/
+
+int debug_cpu_within_instruction_hook(running_machine &machine)
+{
+ return machine.debugcpu_data->within_instruction_hook;
+}
+
+
+/*-------------------------------------------------
+ debug_cpu_is_stopped - return true if the
+ current execution state is stopped
+-------------------------------------------------*/
+
+int debug_cpu_is_stopped(running_machine &machine)
+{
+ debugcpu_private *global = machine.debugcpu_data;
+ return (global != NULL) ? (global->execution_state == EXECUTION_STATE_STOPPED) : false;
+}
+
+
+
+/***************************************************************************
+ SYMBOL TABLE INTERFACES
+***************************************************************************/
+
+/*-------------------------------------------------
+ debug_cpu_get_global_symtable - return the
+ global symbol table
+-------------------------------------------------*/
+
+symbol_table *debug_cpu_get_global_symtable(running_machine &machine)
+{
+ return machine.debugcpu_data->symtable;
+}
+
+
+/*-------------------------------------------------
+ debug_cpu_get_visible_symtable - return the
+ locally-visible symbol table
+-------------------------------------------------*/
+
+symbol_table *debug_cpu_get_visible_symtable(running_machine &machine)
+{
+ return &machine.debugcpu_data->visiblecpu->debug()->symtable();
+}
+
+
+/*-------------------------------------------------
+ debug_cpu_source_script - specifies a debug
+ command script to execute
+-------------------------------------------------*/
+
+void debug_cpu_source_script(running_machine &machine, const char *file)
+{
+ debugcpu_private *global = machine.debugcpu_data;
+
+ /* close any existing source file */
+ if (global->source_file != NULL)
+ {
+ fclose(global->source_file);
+ global->source_file = NULL;
+ }
+
+ /* open a new one if requested */
+ if (file != NULL)
+ {
+ global->source_file = fopen(file, "r");
+ if (!global->source_file)
+ {
+ if (machine.phase() == MACHINE_PHASE_RUNNING)
+ debug_console_printf(machine, "Cannot open command file '%s'\n", file);
+ else
+ fatalerror("Cannot open command file '%s'", file);
+ }
+ }
+}
+
+
+
+//**************************************************************************
+// MEMORY AND DISASSEMBLY HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// debug_comment_save - save all comments for
+// the given machine
+//-------------------------------------------------
+
+bool debug_comment_save(running_machine &machine)
+{
+ // if we don't have a root, bail
+ xml_data_node *root = xml_file_create();
+ if (root == NULL)
+ return false;
+
+ // wrap in a try/catch to handle errors
+ try
+ {
+ // create a comment node
+ xml_data_node *commentnode = xml_add_child(root, "mamecommentfile", NULL);
+ if (commentnode == NULL)
+ throw emu_exception();
+ xml_set_attribute_int(commentnode, "version", COMMENT_VERSION);
+
+ // create a system node
+ xml_data_node *systemnode = xml_add_child(commentnode, "system", NULL);
+ if (systemnode == NULL)
+ throw emu_exception();
+ xml_set_attribute(systemnode, "name", machine.system().name);
+
+ // for each device
+ bool found_comments = false;
+ for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next())
+ if (device->debug()->comment_count() > 0)
+ {
+ // create a node for this device
+ xml_data_node *curnode = xml_add_child(systemnode, "cpu", NULL);
+ if (curnode == NULL)
+ throw emu_exception();
+ xml_set_attribute(curnode, "tag", device->tag());
+
+ // export the comments
+ if (!device->debug()->comment_export(*curnode))
+ throw emu_exception();
+ found_comments = true;
+ }
+
+ // flush the file
+ if (found_comments)
+ {
+ emu_file file(machine.options().comment_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ file_error filerr = file.open(machine.basename(), ".cmt");
+ if (filerr == FILERR_NONE)
+ xml_file_write(root, file);
+ }
+ }
+ catch (emu_exception &)
+ {
+ xml_file_free(root);
+ return false;
+ }
+
+ // free and get out of here
+ xml_file_free(root);
+ return true;
+}
+
+
+//-------------------------------------------------
+// debug_comment_load - load all comments for
+// the given machine
+//-------------------------------------------------
+
+bool debug_comment_load(running_machine &machine)
+{
+ // open the file
+ emu_file file(machine.options().comment_directory(), OPEN_FLAG_READ);
+ file_error filerr = file.open(machine.basename(), ".cmt");
+
+ // if an error, just return false
+ if (filerr != FILERR_NONE)
+ return false;
+
+ // wrap in a try/catch to handle errors
+ xml_data_node *root = xml_file_read(file, NULL);
+ try
+ {
+ // read the file
+ if (root == NULL)
+ throw emu_exception();
+
+ // find the config node
+ xml_data_node *commentnode = xml_get_sibling(root->child, "mamecommentfile");
+ if (commentnode == NULL)
+ throw emu_exception();
+
+ // validate the config data version
+ int version = xml_get_attribute_int(commentnode, "version", 0);
+ if (version != COMMENT_VERSION)
+ throw emu_exception();
+
+ // check to make sure the file is applicable
+ xml_data_node *systemnode = xml_get_sibling(commentnode->child, "system");
+ const char *name = xml_get_attribute_string(systemnode, "name", "");
+ if (strcmp(name, machine.system().name) != 0)
+ throw emu_exception();
+
+ // iterate over devices
+ for (xml_data_node *cpunode = xml_get_sibling(systemnode->child, "cpu"); cpunode; cpunode = xml_get_sibling(cpunode->next, "cpu"))
+ {
+ device_t *device = machine.device(xml_get_attribute_string(cpunode, "tag", ""));
+ if (device != NULL)
+ if (!device->debug()->comment_import(*cpunode))
+ throw emu_exception();
+ }
+ }
+ catch (emu_exception &)
+ {
+ // clean up in case of error
+ if (root != NULL)
+ xml_file_free(root);
+ return false;
+ }
+
+ // free the parser
+ xml_file_free(root);
+ return true;
+}
+
+
+
+/***************************************************************************
+ MEMORY AND DISASSEMBLY HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ debug_cpu_translate - return the physical
+ address corresponding to the given logical
+ address
+-------------------------------------------------*/
+
+int debug_cpu_translate(address_space *space, int intention, offs_t *address)
+{
+ device_memory_interface *memory;
+ if (space->device().interface(memory))
+ return memory->translate(space->spacenum(), intention, *address);
+ return true;
+}
+
+
+/***************************************************************************
+ DEBUGGER MEMORY ACCESSORS
+***************************************************************************/
+
+/*-------------------------------------------------
+ debug_read_byte - return a byte from the
+ the specified memory space
+-------------------------------------------------*/
+
+UINT8 debug_read_byte(address_space *_space, offs_t address, int apply_translation)
+{
+ address_space *space = const_cast<address_space *>(_space);
+ debugcpu_private *global = space->machine().debugcpu_data;
+ UINT64 custom;
+ UINT8 result;
+
+ /* mask against the logical byte mask */
+ address &= space->logbytemask();
+
+ /* all accesses from this point on are for the debugger */
+ space->set_debugger_access(global->debugger_access = true);
+
+ /* translate if necessary; if not mapped, return 0xff */
+ if (apply_translation && !debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address))
+ result = 0xff;
+
+ /* if there is a custom read handler, and it returns true, use that value */
+ else if (space->device().memory().read(space->spacenum(), address, 1, custom))
+ result = custom;
+
+ /* otherwise, call the byte reading function for the translated address */
+ else
+ result = space->read_byte(address);
+
+ /* no longer accessing via the debugger */
+ space->set_debugger_access(global->debugger_access = false);
+ return result;
+}
+
+
+/*-------------------------------------------------
+ debug_read_word - return a word from the
+ specified memory space
+-------------------------------------------------*/
+
+UINT16 debug_read_word(address_space *_space, offs_t address, int apply_translation)
+{
+ address_space *space = const_cast<address_space *>(_space);
+ debugcpu_private *global = space->machine().debugcpu_data;
+ UINT16 result;
+
+ /* mask against the logical byte mask */
+ address &= space->logbytemask();
+
+ /* if this is misaligned read, or if there are no word readers, just read two bytes */
+ if ((address & 1) != 0)
+ {
+ UINT8 byte0 = debug_read_byte(space, address + 0, apply_translation);
+ UINT8 byte1 = debug_read_byte(space, address + 1, apply_translation);
+
+ /* based on the endianness, the result is assembled differently */
+ if (space->endianness() == ENDIANNESS_LITTLE)
+ result = byte0 | (byte1 << 8);
+ else
+ result = byte1 | (byte0 << 8);
+ }
+
+ /* otherwise, this proceeds like the byte case */
+ else
+ {
+ UINT64 custom;
+
+ /* all accesses from this point on are for the debugger */
+ space->set_debugger_access(global->debugger_access = true);
+
+ /* translate if necessary; if not mapped, return 0xffff */
+ if (apply_translation && !debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address))
+ result = 0xffff;
+
+ /* if there is a custom read handler, and it returns true, use that value */
+ else if (space->device().memory().read(space->spacenum(), address, 2, custom))
+ result = custom;
+
+ /* otherwise, call the byte reading function for the translated address */
+ else
+ result = space->read_word(address);
+
+ /* no longer accessing via the debugger */
+ space->set_debugger_access(global->debugger_access = false);
+ }
+
+ return result;
+}
+
+
+/*-------------------------------------------------
+ debug_read_dword - return a dword from the
+ specified memory space
+-------------------------------------------------*/
+
+UINT32 debug_read_dword(address_space *_space, offs_t address, int apply_translation)
+{
+ address_space *space = const_cast<address_space *>(_space);
+ debugcpu_private *global = space->machine().debugcpu_data;
+ UINT32 result;
+
+ /* mask against the logical byte mask */
+ address &= space->logbytemask();
+
+ /* if this is misaligned read, or if there are no dword readers, just read two words */
+ if ((address & 3) != 0)
+ {
+ UINT16 word0 = debug_read_word(space, address + 0, apply_translation);
+ UINT16 word1 = debug_read_word(space, address + 2, apply_translation);
+
+ /* based on the endianness, the result is assembled differently */
+ if (space->endianness() == ENDIANNESS_LITTLE)
+ result = word0 | (word1 << 16);
+ else
+ result = word1 | (word0 << 16);
+ }
+
+ /* otherwise, this proceeds like the byte case */
+ else
+ {
+ UINT64 custom;
+
+ /* all accesses from this point on are for the debugger */
+ space->set_debugger_access(global->debugger_access = true);
+
+ /* translate if necessary; if not mapped, return 0xffffffff */
+ if (apply_translation && !debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address))
+ result = 0xffffffff;
+
+ /* if there is a custom read handler, and it returns true, use that value */
+ else if (space->device().memory().read(space->spacenum(), address, 4, custom))
+ result = custom;
+
+ /* otherwise, call the byte reading function for the translated address */
+ else
+ result = space->read_dword(address);
+
+ /* no longer accessing via the debugger */
+ space->set_debugger_access(global->debugger_access = false);
+ }
+
+ return result;
+}
+
+
+/*-------------------------------------------------
+ debug_read_qword - return a qword from the
+ specified memory space
+-------------------------------------------------*/
+
+UINT64 debug_read_qword(address_space *_space, offs_t address, int apply_translation)
+{
+ address_space *space = const_cast<address_space *>(_space);
+ debugcpu_private *global = space->machine().debugcpu_data;
+ UINT64 result;
+
+ /* mask against the logical byte mask */
+ address &= space->logbytemask();
+
+ /* if this is misaligned read, or if there are no qword readers, just read two dwords */
+ if ((address & 7) != 0)
+ {
+ UINT32 dword0 = debug_read_dword(space, address + 0, apply_translation);
+ UINT32 dword1 = debug_read_dword(space, address + 4, apply_translation);
+
+ /* based on the endianness, the result is assembled differently */
+ if (space->endianness() == ENDIANNESS_LITTLE)
+ result = dword0 | ((UINT64)dword1 << 32);
+ else
+ result = dword1 | ((UINT64)dword0 << 32);
+ }
+
+ /* otherwise, this proceeds like the byte case */
+ else
+ {
+ UINT64 custom;
+
+ /* all accesses from this point on are for the debugger */
+ space->set_debugger_access(global->debugger_access = true);
+
+ /* translate if necessary; if not mapped, return 0xffffffffffffffff */
+ if (apply_translation && !debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address))
+ result = ~(UINT64)0;
+
+ /* if there is a custom read handler, and it returns true, use that value */
+ else if (space->device().memory().read(space->spacenum(), address, 8, custom))
+ result = custom;
+
+ /* otherwise, call the byte reading function for the translated address */
+ else
+ result = space->read_qword(address);
+
+ /* no longer accessing via the debugger */
+ space->set_debugger_access(global->debugger_access = false);
+ }
+
+ return result;
+}
+
+
+/*-------------------------------------------------
+ debug_read_memory - return 1,2,4 or 8 bytes
+ from the specified memory space
+-------------------------------------------------*/
+
+UINT64 debug_read_memory(address_space *space, offs_t address, int size, int apply_translation)
+{
+ UINT64 result = ~(UINT64)0 >> (64 - 8*size);
+ switch (size)
+ {
+ case 1: result = debug_read_byte(space, address, apply_translation); break;
+ case 2: result = debug_read_word(space, address, apply_translation); break;
+ case 4: result = debug_read_dword(space, address, apply_translation); break;
+ case 8: result = debug_read_qword(space, address, apply_translation); break;
+ }
+ return result;
+}
+
+
+/*-------------------------------------------------
+ debug_write_byte - write a byte to the
+ specified memory space
+-------------------------------------------------*/
+
+void debug_write_byte(address_space *_space, offs_t address, UINT8 data, int apply_translation)
+{
+ address_space *space = const_cast<address_space *>(_space);
+ debugcpu_private *global = space->machine().debugcpu_data;
+
+ /* mask against the logical byte mask */
+ address &= space->logbytemask();
+
+ /* all accesses from this point on are for the debugger */
+ space->set_debugger_access(global->debugger_access = true);
+
+ /* translate if necessary; if not mapped, we're done */
+ if (apply_translation && !debug_cpu_translate(space, TRANSLATE_WRITE_DEBUG, &address))
+ ;
+
+ /* if there is a custom write handler, and it returns true, use that */
+ else if (space->device().memory().write(space->spacenum(), address, 1, data))
+ ;
+
+ /* otherwise, call the byte reading function for the translated address */
+ else
+ space->write_byte(address, data);
+
+ /* no longer accessing via the debugger */
+ space->set_debugger_access(global->debugger_access = false);
+ global->memory_modified = true;
+}
+
+
+/*-------------------------------------------------
+ debug_write_word - write a word to the
+ specified memory space
+-------------------------------------------------*/
+
+void debug_write_word(address_space *_space, offs_t address, UINT16 data, int apply_translation)
+{
+ address_space *space = const_cast<address_space *>(_space);
+ debugcpu_private *global = space->machine().debugcpu_data;
+
+ /* mask against the logical byte mask */
+ address &= space->logbytemask();
+
+ /* if this is a misaligned write, or if there are no word writers, just read two bytes */
+ if ((address & 1) != 0)
+ {
+ if (space->endianness() == ENDIANNESS_LITTLE)
+ {
+ debug_write_byte(space, address + 0, data >> 0, apply_translation);
+ debug_write_byte(space, address + 1, data >> 8, apply_translation);
+ }
+ else
+ {
+ debug_write_byte(space, address + 0, data >> 8, apply_translation);
+ debug_write_byte(space, address + 1, data >> 0, apply_translation);
+ }
+ }
+
+ /* otherwise, this proceeds like the byte case */
+ else
+ {
+ /* all accesses from this point on are for the debugger */
+ space->set_debugger_access(global->debugger_access = true);
+
+ /* translate if necessary; if not mapped, we're done */
+ if (apply_translation && !debug_cpu_translate(space, TRANSLATE_WRITE_DEBUG, &address))
+ ;
+
+ /* if there is a custom write handler, and it returns true, use that */
+ else if (space->device().memory().write(space->spacenum(), address, 2, data))
+ ;
+
+ /* otherwise, call the byte reading function for the translated address */
+ else
+ space->write_word(address, data);
+
+ /* no longer accessing via the debugger */
+ space->set_debugger_access(global->debugger_access = false);
+ global->memory_modified = true;
+ }
+}
+
+
+/*-------------------------------------------------
+ debug_write_dword - write a dword to the
+ specified memory space
+-------------------------------------------------*/
+
+void debug_write_dword(address_space *_space, offs_t address, UINT32 data, int apply_translation)
+{
+ address_space *space = const_cast<address_space *>(_space);
+ debugcpu_private *global = space->machine().debugcpu_data;
+
+ /* mask against the logical byte mask */
+ address &= space->logbytemask();
+
+ /* if this is a misaligned write, or if there are no dword writers, just read two words */
+ if ((address & 3) != 0)
+ {
+ if (space->endianness() == ENDIANNESS_LITTLE)
+ {
+ debug_write_word(space, address + 0, data >> 0, apply_translation);
+ debug_write_word(space, address + 2, data >> 16, apply_translation);
+ }
+ else
+ {
+ debug_write_word(space, address + 0, data >> 16, apply_translation);
+ debug_write_word(space, address + 2, data >> 0, apply_translation);
+ }
+ }
+
+ /* otherwise, this proceeds like the byte case */
+ else
+ {
+ /* all accesses from this point on are for the debugger */
+ space->set_debugger_access(global->debugger_access = true);
+
+ /* translate if necessary; if not mapped, we're done */
+ if (apply_translation && !debug_cpu_translate(space, TRANSLATE_WRITE_DEBUG, &address))
+ ;
+
+ /* if there is a custom write handler, and it returns true, use that */
+ else if (space->device().memory().write(space->spacenum(), address, 4, data))
+ ;
+
+ /* otherwise, call the byte reading function for the translated address */
+ else
+ space->write_dword(address, data);
+
+ /* no longer accessing via the debugger */
+ space->set_debugger_access(global->debugger_access = false);
+ global->memory_modified = true;
+ }
+}
+
+
+/*-------------------------------------------------
+ debug_write_qword - write a qword to the
+ specified memory space
+-------------------------------------------------*/
+
+void debug_write_qword(address_space *_space, offs_t address, UINT64 data, int apply_translation)
+{
+ address_space *space = const_cast<address_space *>(_space);
+ debugcpu_private *global = space->machine().debugcpu_data;
+
+ /* mask against the logical byte mask */
+ address &= space->logbytemask();
+
+ /* if this is a misaligned write, or if there are no qword writers, just read two dwords */
+ if ((address & 7) != 0)
+ {
+ if (space->endianness() == ENDIANNESS_LITTLE)
+ {
+ debug_write_dword(space, address + 0, data >> 0, apply_translation);
+ debug_write_dword(space, address + 4, data >> 32, apply_translation);
+ }
+ else
+ {
+ debug_write_dword(space, address + 0, data >> 32, apply_translation);
+ debug_write_dword(space, address + 4, data >> 0, apply_translation);
+ }
+ }
+
+ /* otherwise, this proceeds like the byte case */
+ else
+ {
+ /* all accesses from this point on are for the debugger */
+ space->set_debugger_access(global->debugger_access = true);
+
+ /* translate if necessary; if not mapped, we're done */
+ if (apply_translation && !debug_cpu_translate(space, TRANSLATE_WRITE_DEBUG, &address))
+ ;
+
+ /* if there is a custom write handler, and it returns true, use that */
+ else if (space->device().memory().write(space->spacenum(), address, 8, data))
+ ;
+
+ /* otherwise, call the byte reading function for the translated address */
+ else
+ space->write_qword(address, data);
+
+ /* no longer accessing via the debugger */
+ space->set_debugger_access(global->debugger_access = false);
+ global->memory_modified = true;
+ }
+}
+
+
+/*-------------------------------------------------
+ debug_write_memory - write 1,2,4 or 8 bytes
+ to the specified memory space
+-------------------------------------------------*/
+
+void debug_write_memory(address_space *space, offs_t address, UINT64 data, int size, int apply_translation)
+{
+ switch (size)
+ {
+ case 1: debug_write_byte(space, address, data, apply_translation); break;
+ case 2: debug_write_word(space, address, data, apply_translation); break;
+ case 4: debug_write_dword(space, address, data, apply_translation); break;
+ case 8: debug_write_qword(space, address, data, apply_translation); break;
+ }
+}
+
+
+/*-------------------------------------------------
+ debug_read_opcode - read 1,2,4 or 8 bytes at
+ the given offset from opcode space
+-------------------------------------------------*/
+
+UINT64 debug_read_opcode(address_space *_space, offs_t address, int size, int arg)
+{
+ address_space *space = const_cast<address_space *>(_space);
+ UINT64 result = ~(UINT64)0 & (~(UINT64)0 >> (64 - 8*size)), result2;
+ debugcpu_private *global = space->machine().debugcpu_data;
+
+ /* keep in logical range */
+ address &= space->logbytemask();
+
+ /* return early if we got the result directly */
+ space->set_debugger_access(global->debugger_access = true);
+ device_memory_interface *memory;
+ if (space->device().interface(memory) && memory->readop(address, size, result2))
+ {
+ space->set_debugger_access(global->debugger_access = false);
+ return result2;
+ }
+
+ /* if we're bigger than the address bus, break into smaller pieces */
+ if (size > space->data_width() / 8)
+ {
+ int halfsize = size / 2;
+ UINT64 r0 = debug_read_opcode(space, address + 0, halfsize, arg);
+ UINT64 r1 = debug_read_opcode(space, address + halfsize, halfsize, arg);
+
+ if (space->endianness() == ENDIANNESS_LITTLE)
+ return r0 | (r1 << (8 * halfsize));
+ else
+ return r1 | (r0 << (8 * halfsize));
+ }
+
+ /* translate to physical first */
+ if (!debug_cpu_translate(space, TRANSLATE_FETCH_DEBUG, &address))
+ return result;
+
+ /* keep in physical range */
+ address &= space->bytemask();
+ offs_t addrxor = 0;
+ switch (space->data_width() / 8 * 10 + size)
+ {
+ /* dump opcodes in bytes from a byte-sized bus */
+ case 11:
+ break;
+
+ /* dump opcodes in bytes from a word-sized bus */
+ case 21:
+ addrxor = (space->endianness() == ENDIANNESS_LITTLE) ? BYTE_XOR_LE(0) : BYTE_XOR_BE(0);
+ break;
+
+ /* dump opcodes in words from a word-sized bus */
+ case 22:
+ break;
+
+ /* dump opcodes in bytes from a dword-sized bus */
+ case 41:
+ addrxor = (space->endianness() == ENDIANNESS_LITTLE) ? BYTE4_XOR_LE(0) : BYTE4_XOR_BE(0);
+ break;
+
+ /* dump opcodes in words from a dword-sized bus */
+ case 42:
+ addrxor = (space->endianness() == ENDIANNESS_LITTLE) ? WORD_XOR_LE(0) : WORD_XOR_BE(0);
+ break;
+
+ /* dump opcodes in dwords from a dword-sized bus */
+ case 44:
+ break;
+
+ /* dump opcodes in bytes from a qword-sized bus */
+ case 81:
+ addrxor = (space->endianness() == ENDIANNESS_LITTLE) ? BYTE8_XOR_LE(0) : BYTE8_XOR_BE(0);
+ break;
+
+ /* dump opcodes in words from a qword-sized bus */
+ case 82:
+ addrxor = (space->endianness() == ENDIANNESS_LITTLE) ? WORD2_XOR_LE(0) : WORD2_XOR_BE(0);
+ break;
+
+ /* dump opcodes in dwords from a qword-sized bus */
+ case 84:
+ addrxor = (space->endianness() == ENDIANNESS_LITTLE) ? DWORD_XOR_LE(0) : DWORD_XOR_BE(0);
+ break;
+
+ /* dump opcodes in qwords from a qword-sized bus */
+ case 88:
+ break;
+
+ default:
+ fatalerror("debug_read_opcode: unknown type = %d", space->data_width() / 8 * 10 + size);
+ break;
+ }
+
+ /* turn on debugger access */
+ if (!global->debugger_access)
+ space->set_debugger_access(global->debugger_access = true);
+
+ /* switch off the size and handle unaligned accesses */
+ switch (size)
+ {
+ case 1:
+ result = (arg) ? space->direct().read_raw_byte(address, addrxor) : space->direct().read_decrypted_byte(address, addrxor);
+ break;
+
+ case 2:
+ result = (arg) ? space->direct().read_raw_word(address & ~1, addrxor) : space->direct().read_decrypted_word(address & ~1, addrxor);
+ if ((address & 1) != 0)
+ {
+ result2 = (arg) ? space->direct().read_raw_word((address & ~1) + 2, addrxor) : space->direct().read_decrypted_word((address & ~1) + 2, addrxor);
+ if (space->endianness() == ENDIANNESS_LITTLE)
+ result = (result >> (8 * (address & 1))) | (result2 << (16 - 8 * (address & 1)));
+ else
+ result = (result << (8 * (address & 1))) | (result2 >> (16 - 8 * (address & 1)));
+ result &= 0xffff;
+ }
+ break;
+
+ case 4:
+ result = (arg) ? space->direct().read_raw_dword(address & ~3, addrxor) : space->direct().read_decrypted_dword(address & ~3, addrxor);
+ if ((address & 3) != 0)
+ {
+ result2 = (arg) ? space->direct().read_raw_dword((address & ~3) + 4, addrxor) : space->direct().read_decrypted_dword((address & ~3) + 4, addrxor);
+ if (space->endianness() == ENDIANNESS_LITTLE)
+ result = (result >> (8 * (address & 3))) | (result2 << (32 - 8 * (address & 3)));
+ else
+ result = (result << (8 * (address & 3))) | (result2 >> (32 - 8 * (address & 3)));
+ result &= 0xffffffff;
+ }
+ break;
+
+ case 8:
+ result = (arg) ? space->direct().read_raw_qword(address & ~7, addrxor) : space->direct().read_decrypted_qword(address & ~7, addrxor);
+ if ((address & 7) != 0)
+ {
+ result2 = (arg) ? space->direct().read_raw_qword((address & ~7) + 8, addrxor) : space->direct().read_decrypted_qword((address & ~7) + 8, addrxor);
+ if (space->endianness() == ENDIANNESS_LITTLE)
+ result = (result >> (8 * (address & 7))) | (result2 << (64 - 8 * (address & 7)));
+ else
+ result = (result << (8 * (address & 7))) | (result2 >> (64 - 8 * (address & 7)));
+ }
+ break;
+ }
+
+ /* no longer accessing via the debugger */
+ space->set_debugger_access(global->debugger_access = false);
+ return result;
+}
+
+
+
+/***************************************************************************
+ INTERNAL HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ debug_cpu_exit - free all memory
+-------------------------------------------------*/
+
+static void debug_cpu_exit(running_machine &machine)
+{
+ debugcpu_private *global = machine.debugcpu_data;
+
+ /* free the global symbol table */
+ if (global != NULL)
+ global_free(global->symtable);
+}
+
+
+/*-------------------------------------------------
+ on_vblank - called when a VBLANK hits
+-------------------------------------------------*/
+
+static void on_vblank(running_machine &machine, screen_device &device, bool vblank_state)
+{
+ /* just set a global flag to be consumed later */
+ if (vblank_state)
+ device.machine().debugcpu_data->vblank_occurred = true;
+}
+
+
+/*-------------------------------------------------
+ reset_transient_flags - reset the transient
+ flags on all CPUs
+-------------------------------------------------*/
+
+static void reset_transient_flags(running_machine &machine)
+{
+ /* loop over CPUs and reset the transient flags */
+ for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next())
+ device->debug()->reset_transient_flag();
+ machine.debugcpu_data->m_stop_when_not_device = NULL;
+}
+
+
+/*-------------------------------------------------
+ process_source_file - executes commands from
+ a source file
+-------------------------------------------------*/
+
+static void process_source_file(running_machine &machine)
+{
+ debugcpu_private *global = machine.debugcpu_data;
+
+ /* loop until the file is exhausted or until we are executing again */
+ while (global->source_file != NULL && global->execution_state == EXECUTION_STATE_STOPPED)
+ {
+ char buf[512];
+ int i;
+ char *s;
+
+ /* stop at the end of file */
+ if (feof(global->source_file))
+ {
+ fclose(global->source_file);
+ global->source_file = NULL;
+ return;
+ }
+
+ /* fetch the next line */
+ memset(buf, 0, sizeof(buf));
+ fgets(buf, sizeof(buf), global->source_file);
+
+ /* strip out comments (text after '//') */
+ s = strstr(buf, "//");
+ if (s)
+ *s = '\0';
+
+ /* strip whitespace */
+ i = (int)strlen(buf);
+ while((i > 0) && (isspace((UINT8)buf[i-1])))
+ buf[--i] = '\0';
+
+ /* execute the command */
+ if (buf[0])
+ debug_console_execute_command(machine, buf, 1);
+ }
+}
+
+
+
+/***************************************************************************
+ EXPRESSION HANDLERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ expression_get_device - return a device
+ based on a case insensitive tag search
+-------------------------------------------------*/
+
+static device_t *expression_get_device(running_machine &machine, const char *tag)
+{
+ device_t *device;
+
+ for (device = machine.devicelist().first(); device != NULL; device = device->next())
+ if (mame_stricmp(device->tag(), tag) == 0)
+ return device;
+
+ return NULL;
+}
+
+
+/*-------------------------------------------------
+ expression_read_memory - read 1,2,4 or 8 bytes
+ at the given offset in the given address
+ space
+-------------------------------------------------*/
+
+static UINT64 expression_read_memory(void *param, const char *name, expression_space spacenum, UINT32 address, int size)
+{
+ running_machine &machine = *(running_machine *)param;
+ UINT64 result = ~(UINT64)0 >> (64 - 8*size);
+ device_t *device = NULL;
+ address_space *space;
+
+ switch (spacenum)
+ {
+ case EXPSPACE_PROGRAM_LOGICAL:
+ case EXPSPACE_DATA_LOGICAL:
+ case EXPSPACE_IO_LOGICAL:
+ case EXPSPACE_SPACE3_LOGICAL:
+ if (name != NULL)
+ device = expression_get_device(machine, name);
+ if (device == NULL)
+ device = debug_cpu_get_visible_cpu(machine);
+ space = device->memory().space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_LOGICAL));
+ if (space != NULL)
+ result = debug_read_memory(space, space->address_to_byte(address), size, true);
+ break;
+
+ case EXPSPACE_PROGRAM_PHYSICAL:
+ case EXPSPACE_DATA_PHYSICAL:
+ case EXPSPACE_IO_PHYSICAL:
+ case EXPSPACE_SPACE3_PHYSICAL:
+ if (name != NULL)
+ device = expression_get_device(machine, name);
+ if (device == NULL)
+ device = debug_cpu_get_visible_cpu(machine);
+ space = device->memory().space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_PHYSICAL));
+ if (space != NULL)
+ result = debug_read_memory(space, space->address_to_byte(address), size, false);
+ break;
+
+ case EXPSPACE_OPCODE:
+ case EXPSPACE_RAMWRITE:
+ if (name != NULL)
+ device = expression_get_device(machine, name);
+ if (device == NULL)
+ device = debug_cpu_get_visible_cpu(machine);
+ result = expression_read_program_direct(device->memory().space(AS_PROGRAM), (spacenum == EXPSPACE_OPCODE), address, size);
+ break;
+
+ case EXPSPACE_REGION:
+ if (name == NULL)
+ break;
+ result = expression_read_memory_region(machine, name, address, size);
+ break;
+
+ default:
+ break;
+ }
+ return result;
+}
+
+
+/*-------------------------------------------------
+ expression_read_program_direct - read memory
+ directly from an opcode or RAM pointer
+-------------------------------------------------*/
+
+static UINT64 expression_read_program_direct(address_space *_space, int opcode, offs_t address, int size)
+{
+ address_space *space = const_cast<address_space *>(_space);
+ UINT64 result = ~(UINT64)0 >> (64 - 8*size);
+
+ if (space != NULL)
+ {
+ UINT8 *base;
+
+ /* adjust the address into a byte address, but not if being called recursively */
+ if ((opcode & 2) == 0)
+ address = space->address_to_byte(address);
+
+ /* call ourself recursively until we are byte-sized */
+ if (size > 1)
+ {
+ int halfsize = size / 2;
+ UINT64 r0, r1;
+
+ /* read each half, from lower address to upper address */
+ r0 = expression_read_program_direct(space, opcode | 2, address + 0, halfsize);
+ r1 = expression_read_program_direct(space, opcode | 2, address + halfsize, halfsize);
+
+ /* assemble based on the target endianness */
+ if (space->endianness() == ENDIANNESS_LITTLE)
+ result = r0 | (r1 << (8 * halfsize));
+ else
+ result = r1 | (r0 << (8 * halfsize));
+ }
+
+ /* handle the byte-sized final requests */
+ else
+ {
+ /* lowmask specified which address bits are within the databus width */
+ offs_t lowmask = space->data_width() / 8 - 1;
+
+ /* get the base of memory, aligned to the address minus the lowbits */
+ if (opcode & 1)
+ base = (UINT8 *)space->direct().read_decrypted_ptr(address & ~lowmask);
+ else
+ base = (UINT8 *)space->get_read_ptr(address & ~lowmask);
+
+ /* if we have a valid base, return the appropriate byte */
+ if (base != NULL)
+ {
+ if (space->endianness() == ENDIANNESS_LITTLE)
+ result = base[BYTE8_XOR_LE(address) & lowmask];
+ else
+ result = base[BYTE8_XOR_BE(address) & lowmask];
+ }
+ }
+ }
+ return result;
+}
+
+
+/*-------------------------------------------------
+ expression_read_memory_region - read memory
+ from a memory region
+-------------------------------------------------*/
+
+static UINT64 expression_read_memory_region(running_machine &machine, const char *rgntag, offs_t address, int size)
+{
+ const memory_region *region = machine.region(rgntag);
+ UINT64 result = ~(UINT64)0 >> (64 - 8*size);
+
+ /* make sure we get a valid base before proceeding */
+ if (region != NULL)
+ {
+ /* call ourself recursively until we are byte-sized */
+ if (size > 1)
+ {
+ int halfsize = size / 2;
+ UINT64 r0, r1;
+
+ /* read each half, from lower address to upper address */
+ r0 = expression_read_memory_region(machine, rgntag, address + 0, halfsize);
+ r1 = expression_read_memory_region(machine, rgntag, address + halfsize, halfsize);
+
+ /* assemble based on the target endianness */
+ if (region->endianness() == ENDIANNESS_LITTLE)
+ result = r0 | (r1 << (8 * halfsize));
+ else
+ result = r1 | (r0 << (8 * halfsize));
+ }
+
+ /* only process if we're within range */
+ else if (address < region->bytes())
+ {
+ /* lowmask specified which address bits are within the databus width */
+ UINT32 lowmask = region->width() - 1;
+ UINT8 *base = region->base() + (address & ~lowmask);
+
+ /* if we have a valid base, return the appropriate byte */
+ if (region->endianness() == ENDIANNESS_LITTLE)
+ result = base[BYTE8_XOR_LE(address) & lowmask];
+ else
+ result = base[BYTE8_XOR_BE(address) & lowmask];
+ }
+ }
+ return result;
+}
+
+
+/*-------------------------------------------------
+ expression_write_memory - write 1,2,4 or 8
+ bytes at the given offset in the given address
+ space
+-------------------------------------------------*/
+
+static void expression_write_memory(void *param, const char *name, expression_space spacenum, UINT32 address, int size, UINT64 data)
+{
+ running_machine &machine = *(running_machine *)param;
+ device_t *device = NULL;
+ address_space *space;
+
+ switch (spacenum)
+ {
+ case EXPSPACE_PROGRAM_LOGICAL:
+ case EXPSPACE_DATA_LOGICAL:
+ case EXPSPACE_IO_LOGICAL:
+ case EXPSPACE_SPACE3_LOGICAL:
+ if (name != NULL)
+ device = expression_get_device(machine, name);
+ if (device == NULL)
+ device = debug_cpu_get_visible_cpu(machine);
+ space = device->memory().space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_LOGICAL));
+ if (space != NULL)
+ debug_write_memory(space, space->address_to_byte(address), data, size, true);
+ break;
+
+ case EXPSPACE_PROGRAM_PHYSICAL:
+ case EXPSPACE_DATA_PHYSICAL:
+ case EXPSPACE_IO_PHYSICAL:
+ case EXPSPACE_SPACE3_PHYSICAL:
+ if (name != NULL)
+ device = expression_get_device(machine, name);
+ if (device == NULL)
+ device = debug_cpu_get_visible_cpu(machine);
+ space = device->memory().space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_PHYSICAL));
+ if (space != NULL)
+ debug_write_memory(space, space->address_to_byte(address), data, size, false);
+ break;
+
+ case EXPSPACE_OPCODE:
+ case EXPSPACE_RAMWRITE:
+ if (name != NULL)
+ device = expression_get_device(machine, name);
+ if (device == NULL)
+ device = debug_cpu_get_visible_cpu(machine);
+ expression_write_program_direct(device->memory().space(AS_PROGRAM), (spacenum == EXPSPACE_OPCODE), address, size, data);
+ break;
+
+ case EXPSPACE_REGION:
+ if (name == NULL)
+ break;
+ expression_write_memory_region(machine, name, address, size, data);
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+/*-------------------------------------------------
+ expression_write_program_direct - write memory
+ directly to an opcode or RAM pointer
+-------------------------------------------------*/
+
+static void expression_write_program_direct(address_space *_space, int opcode, offs_t address, int size, UINT64 data)
+{
+ address_space *space = const_cast<address_space *>(_space);
+ if (space != NULL)
+ {
+ debugcpu_private *global = space->machine().debugcpu_data;
+ UINT8 *base;
+
+ /* adjust the address into a byte address, but not if being called recursively */
+ if ((opcode & 2) == 0)
+ address = space->address_to_byte(address);
+
+ /* call ourself recursively until we are byte-sized */
+ if (size > 1)
+ {
+ int halfsize = size / 2;
+ UINT64 r0, r1, halfmask;
+
+ /* break apart based on the target endianness */
+ halfmask = ~(UINT64)0 >> (64 - 8 * halfsize);
+ if (space->endianness() == ENDIANNESS_LITTLE)
+ {
+ r0 = data & halfmask;
+ r1 = (data >> (8 * halfsize)) & halfmask;
+ }
+ else
+ {
+ r0 = (data >> (8 * halfsize)) & halfmask;
+ r1 = data & halfmask;
+ }
+
+ /* write each half, from lower address to upper address */
+ expression_write_program_direct(space, opcode | 2, address + 0, halfsize, r0);
+ expression_write_program_direct(space, opcode | 2, address + halfsize, halfsize, r1);
+ }
+
+ /* handle the byte-sized final case */
+ else
+ {
+ /* lowmask specified which address bits are within the databus width */
+ offs_t lowmask = space->data_width() / 8 - 1;
+
+ /* get the base of memory, aligned to the address minus the lowbits */
+ if (opcode & 1)
+ base = (UINT8 *)space->direct().read_decrypted_ptr(address & ~lowmask);
+ else
+ base = (UINT8 *)space->get_read_ptr(address & ~lowmask);
+
+ /* if we have a valid base, write the appropriate byte */
+ if (base != NULL)
+ {
+ if (space->endianness() == ENDIANNESS_LITTLE)
+ base[BYTE8_XOR_LE(address) & lowmask] = data;
+ else
+ base[BYTE8_XOR_BE(address) & lowmask] = data;
+ global->memory_modified = true;
+ }
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ expression_write_memory_region - write memory
+ from a memory region
+-------------------------------------------------*/
+
+static void expression_write_memory_region(running_machine &machine, const char *rgntag, offs_t address, int size, UINT64 data)
+{
+ debugcpu_private *global = machine.debugcpu_data;
+ const memory_region *region = machine.region(rgntag);
+
+ /* make sure we get a valid base before proceeding */
+ if (region != NULL)
+ {
+ /* call ourself recursively until we are byte-sized */
+ if (size > 1)
+ {
+ int halfsize = size / 2;
+ UINT64 r0, r1, halfmask;
+
+ /* break apart based on the target endianness */
+ halfmask = ~(UINT64)0 >> (64 - 8 * halfsize);
+ if (region->endianness() == ENDIANNESS_LITTLE)
+ {
+ r0 = data & halfmask;
+ r1 = (data >> (8 * halfsize)) & halfmask;
+ }
+ else
+ {
+ r0 = (data >> (8 * halfsize)) & halfmask;
+ r1 = data & halfmask;
+ }
+
+ /* write each half, from lower address to upper address */
+ expression_write_memory_region(machine, rgntag, address + 0, halfsize, r0);
+ expression_write_memory_region(machine, rgntag, address + halfsize, halfsize, r1);
+ }
+
+ /* only process if we're within range */
+ else if (address < region->bytes())
+ {
+ /* lowmask specified which address bits are within the databus width */
+ UINT32 lowmask = region->width() - 1;
+ UINT8 *base = region->base() + (address & ~lowmask);
+
+ /* if we have a valid base, set the appropriate byte */
+ if (region->endianness() == ENDIANNESS_LITTLE)
+ base[BYTE8_XOR_LE(address) & lowmask] = data;
+ else
+ base[BYTE8_XOR_BE(address) & lowmask] = data;
+ global->memory_modified = true;
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ expression_validate - validate that the
+ provided expression references an
+ appropriate name
+-------------------------------------------------*/
+
+static expression_error::error_code expression_validate(void *param, const char *name, expression_space space)
+{
+ running_machine &machine = *(running_machine *)param;
+ device_t *device = NULL;
+
+ switch (space)
+ {
+ case EXPSPACE_PROGRAM_LOGICAL:
+ case EXPSPACE_DATA_LOGICAL:
+ case EXPSPACE_IO_LOGICAL:
+ case EXPSPACE_SPACE3_LOGICAL:
+ if (name != NULL)
+ {
+ device = expression_get_device(machine, name);
+ if (device == NULL)
+ return expression_error::INVALID_MEMORY_NAME;
+ }
+ if (device == NULL)
+ device = debug_cpu_get_visible_cpu(machine);
+ if (device->memory().space(AS_PROGRAM + (space - EXPSPACE_PROGRAM_LOGICAL)) == NULL)
+ return expression_error::NO_SUCH_MEMORY_SPACE;
+ break;
+
+ case EXPSPACE_PROGRAM_PHYSICAL:
+ case EXPSPACE_DATA_PHYSICAL:
+ case EXPSPACE_IO_PHYSICAL:
+ case EXPSPACE_SPACE3_PHYSICAL:
+ if (name != NULL)
+ {
+ device = expression_get_device(machine, name);
+ if (device == NULL)
+ return expression_error::INVALID_MEMORY_NAME;
+ }
+ if (device == NULL)
+ device = debug_cpu_get_visible_cpu(machine);
+ if (device->memory().space(AS_PROGRAM + (space - EXPSPACE_PROGRAM_PHYSICAL)) == NULL)
+ return expression_error::NO_SUCH_MEMORY_SPACE;
+ break;
+
+ case EXPSPACE_OPCODE:
+ case EXPSPACE_RAMWRITE:
+ if (name != NULL)
+ {
+ device = expression_get_device(machine, name);
+ if (device == NULL)
+ return expression_error::INVALID_MEMORY_NAME;
+ }
+ if (device == NULL)
+ device = debug_cpu_get_visible_cpu(machine);
+ if (device->memory().space(AS_PROGRAM) == NULL)
+ return expression_error::NO_SUCH_MEMORY_SPACE;
+ break;
+
+ case EXPSPACE_REGION:
+ if (name == NULL)
+ return expression_error::MISSING_MEMORY_NAME;
+ if (machine.region(name)->base() == NULL)
+ return expression_error::INVALID_MEMORY_NAME;
+ break;
+
+ default:
+ return expression_error::NO_SUCH_MEMORY_SPACE;
+ }
+ return expression_error::NONE;
+}
+
+
+
+/***************************************************************************
+ VARIABLE GETTERS/SETTERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ get_beamx - get beam horizontal position
+-------------------------------------------------*/
+
+static UINT64 get_beamx(symbol_table &table, void *ref)
+{
+ screen_device *screen = reinterpret_cast<screen_device *>(ref);
+ return (screen != NULL) ? screen->hpos() : 0;
+}
+
+
+/*-------------------------------------------------
+ get_beamy - get beam vertical position
+-------------------------------------------------*/
+
+static UINT64 get_beamy(symbol_table &table, void *ref)
+{
+ screen_device *screen = reinterpret_cast<screen_device *>(ref);
+ return (screen != NULL) ? screen->vpos() : 0;
+}
+
+
+/*-------------------------------------------------
+ get_frame - get current frame number
+-------------------------------------------------*/
+
+static UINT64 get_frame(symbol_table &table, void *ref)
+{
+ screen_device *screen = reinterpret_cast<screen_device *>(ref);
+ return (screen != NULL) ? screen->frame_number() : 0;
+}
+
+
+/*-------------------------------------------------
+ get_cpunum - getter callback for the
+ 'cpunum' symbol
+-------------------------------------------------*/
+
+static UINT64 get_cpunum(symbol_table &table, void *ref)
+{
+ running_machine &machine = *reinterpret_cast<running_machine *>(table.globalref());
+ device_t *target = machine.debugcpu_data->visiblecpu;
+
+ device_execute_interface *exec = NULL;
+ int index = 0;
+ for (bool gotone = machine.devicelist().first(exec); gotone; gotone = exec->next(exec))
+ {
+ if (&exec->device() == target)
+ return index;
+ index++;
+ }
+ return 0;
+}
+
+
+
+//**************************************************************************
+// DEVICE DEBUG
+//**************************************************************************
+
+//-------------------------------------------------
+// device_debug - constructor
+//-------------------------------------------------
+
+device_debug::device_debug(device_t &device)
+ : m_device(device),
+ m_exec(NULL),
+ m_memory(NULL),
+ m_state(NULL),
+ m_disasm(NULL),
+ m_flags(0),
+ m_symtable(&device, debug_cpu_get_global_symtable(device.machine())),
+ m_instrhook(NULL),
+ m_dasm_override(NULL),
+ m_opwidth(0),
+ m_stepaddr(0),
+ m_stepsleft(0),
+ m_stopaddr(0),
+ m_stoptime(attotime::zero),
+ m_stopirq(0),
+ m_stopexception(0),
+ m_endexectime(attotime::zero),
+ m_pc_history_index(0),
+ m_bplist(NULL),
+ m_trace(NULL),
+ m_hotspots(NULL),
+ m_hotspot_count(0),
+ m_hotspot_threshhold(0)
+{
+ memset(m_pc_history, 0, sizeof(m_pc_history));
+ memset(m_wplist, 0, sizeof(m_wplist));
+
+ // find out which interfaces we have to work with
+ device.interface(m_exec);
+ device.interface(m_memory);
+ device.interface(m_state);
+ device.interface(m_disasm);
+
+ // set up state-related stuff
+ if (m_state != NULL)
+ {
+ // add a global symbol for the current instruction pointer
+ if (m_exec != NULL)
+ m_symtable.add("cycles", NULL, get_cycles);
+
+ // add entries to enable/disable unmap reporting for each space
+ if (m_memory != NULL)
+ {
+ if (m_memory->space(AS_PROGRAM) != NULL)
+ m_symtable.add("logunmap", (void *)m_memory->space(AS_PROGRAM), get_logunmap, set_logunmap);
+ if (m_memory->space(AS_DATA) != NULL)
+ m_symtable.add("logunmapd", (void *)m_memory->space(AS_DATA), get_logunmap, set_logunmap);
+ if (m_memory->space(AS_IO) != NULL)
+ m_symtable.add("logunmapi", (void *)m_memory->space(AS_IO), get_logunmap, set_logunmap);
+ }
+
+ // add all registers into it
+ astring tempstr;
+ for (const device_state_entry *entry = m_state->state_first(); entry != NULL; entry = entry->next())
+ m_symtable.add(tempstr.cpy(entry->symbol()).tolower(), (void *)(FPTR)entry->index(), get_state, set_state);
+ }
+
+ // set up execution-related stuff
+ if (m_exec != NULL)
+ {
+ m_flags = DEBUG_FLAG_OBSERVING | DEBUG_FLAG_HISTORY;
+ m_opwidth = min_opcode_bytes();
+
+ // if no curpc, add one
+ if (m_state != NULL && m_symtable.find("curpc") == NULL)
+ m_symtable.add("curpc", NULL, get_current_pc);
+ }
+}
+
+
+//-------------------------------------------------
+// ~device_debug - constructor
+//-------------------------------------------------
+
+device_debug::~device_debug()
+{
+ // free breakpoints and watchpoints
+ breakpoint_clear_all();
+ watchpoint_clear_all();
+}
+
+
+//-------------------------------------------------
+// start_hook - the scheduler calls this hook
+// before beginning execution for the given device
+//-------------------------------------------------
+
+void device_debug::start_hook(attotime endtime)
+{
+ debugcpu_private *global = m_device.machine().debugcpu_data;
+
+ assert((m_device.machine().debug_flags & DEBUG_FLAG_ENABLED) != 0);
+
+ // stash a pointer to the current live CPU
+ assert(global->livecpu == NULL);
+ global->livecpu = &m_device;
+
+ // if we're a new device, stop now
+ if (global->m_stop_when_not_device != NULL && global->m_stop_when_not_device != &m_device)
+ {
+ global->m_stop_when_not_device = NULL;
+ global->execution_state = EXECUTION_STATE_STOPPED;
+ reset_transient_flags(m_device.machine());
+ }
+
+ // update the target execution end time
+ m_endexectime = endtime;
+
+ // if we're running, do some periodic updating
+ if (global->execution_state != EXECUTION_STATE_STOPPED)
+ {
+ // check for periodic updates
+ if (&m_device == global->visiblecpu && osd_ticks() > global->last_periodic_update_time + osd_ticks_per_second()/4)
+ {
+ m_device.machine().debug_view().update_all();
+ m_device.machine().debug_view().flush_osd_updates();
+ global->last_periodic_update_time = osd_ticks();
+ }
+
+ // check for pending breaks
+ else if (&m_device == global->breakcpu)
+ {
+ global->execution_state = EXECUTION_STATE_STOPPED;
+ global->breakcpu = NULL;
+ }
+
+ // if a VBLANK occurred, check on things
+ if (global->vblank_occurred)
+ {
+ global->vblank_occurred = false;
+
+ // if we were waiting for a VBLANK, signal it now
+ if ((m_flags & DEBUG_FLAG_STOP_VBLANK) != 0)
+ {
+ global->execution_state = EXECUTION_STATE_STOPPED;
+ debug_console_printf(m_device.machine(), "Stopped at VBLANK\n");
+ }
+ }
+ // check for debug keypresses
+ if (ui_input_pressed(m_device.machine(), IPT_UI_DEBUG_BREAK))
+ global->visiblecpu->debug()->halt_on_next_instruction("User-initiated break\n");
+ }
+
+ // recompute the debugging mode
+ compute_debug_flags();
+}
+
+
+//-------------------------------------------------
+// stop_hook - the scheduler calls this hook when
+// ending execution for the given device
+//-------------------------------------------------
+
+void device_debug::stop_hook()
+{
+ debugcpu_private *global = m_device.machine().debugcpu_data;
+
+ assert(global->livecpu == &m_device);
+
+ // clear the live CPU
+ global->livecpu = NULL;
+}
+
+
+//-------------------------------------------------
+// interrupt_hook - called when an interrupt is
+// acknowledged
+//-------------------------------------------------
+
+void device_debug::interrupt_hook(int irqline)
+{
+ debugcpu_private *global = m_device.machine().debugcpu_data;
+
+ // see if this matches a pending interrupt request
+ if ((m_flags & DEBUG_FLAG_STOP_INTERRUPT) != 0 && (m_stopirq == -1 || m_stopirq == irqline))
+ {
+ global->execution_state = EXECUTION_STATE_STOPPED;
+ debug_console_printf(m_device.machine(), "Stopped on interrupt (CPU '%s', IRQ %d)\n", m_device.tag(), irqline);
+ compute_debug_flags();
+ }
+}
+
+
+//-------------------------------------------------
+// exception_hook - called when an exception is
+// generated
+//-------------------------------------------------
+
+void device_debug::exception_hook(int exception)
+{
+ debugcpu_private *global = m_device.machine().debugcpu_data;
+
+ // see if this matches a pending interrupt request
+ if ((m_flags & DEBUG_FLAG_STOP_EXCEPTION) != 0 && (m_stopexception == -1 || m_stopexception == exception))
+ {
+ global->execution_state = EXECUTION_STATE_STOPPED;
+ debug_console_printf(m_device.machine(), "Stopped on exception (CPU '%s', exception %d)\n", m_device.tag(), exception);
+ compute_debug_flags();
+ }
+}
+
+
+//-------------------------------------------------
+// instruction_hook - called by the CPU cores
+// before executing each instruction
+//-------------------------------------------------
+
+void device_debug::instruction_hook(offs_t curpc)
+{
+ running_machine &machine = m_device.machine();
+ debugcpu_private *global = machine.debugcpu_data;
+
+ // note that we are in the debugger code
+ global->within_instruction_hook = true;
+
+ // update the history
+ m_pc_history[m_pc_history_index++ % HISTORY_SIZE] = curpc;
+
+ // are we tracing?
+ if (m_trace != NULL)
+ m_trace->update(curpc);
+
+ // per-instruction hook?
+ if (global->execution_state != EXECUTION_STATE_STOPPED && (m_flags & DEBUG_FLAG_HOOKED) != 0 && (*m_instrhook)(m_device, curpc))
+ global->execution_state = EXECUTION_STATE_STOPPED;
+
+ // handle single stepping
+ if (global->execution_state != EXECUTION_STATE_STOPPED && (m_flags & DEBUG_FLAG_STEPPING_ANY) != 0)
+ {
+ // is this an actual step?
+ if (m_stepaddr == ~0 || curpc == m_stepaddr)
+ {
+ // decrement the count and reset the breakpoint
+ m_stepsleft--;
+ m_stepaddr = ~0;
+
+ // if we hit 0, stop
+ if (m_stepsleft == 0)
+ global->execution_state = EXECUTION_STATE_STOPPED;
+
+ // update every 100 steps until we are within 200 of the end
+ else if ((m_flags & DEBUG_FLAG_STEPPING_OUT) == 0 && (m_stepsleft < 200 || m_stepsleft % 100 == 0))
+ {
+ machine.debug_view().update_all();
+ machine.debug_view().flush_osd_updates();
+ debugger_refresh_display(machine);
+ }
+ }
+ }
+
+ // handle breakpoints
+ if (global->execution_state != EXECUTION_STATE_STOPPED && (m_flags & (DEBUG_FLAG_STOP_TIME | DEBUG_FLAG_STOP_PC | DEBUG_FLAG_LIVE_BP)) != 0)
+ {
+ // see if we hit a target time
+ if ((m_flags & DEBUG_FLAG_STOP_TIME) != 0 && machine.time() >= m_stoptime)
+ {
+ debug_console_printf(machine, "Stopped at time interval %.1g\n", machine.time().as_double());
+ global->execution_state = EXECUTION_STATE_STOPPED;
+ }
+
+ // check the temp running breakpoint and break if we hit it
+ else if ((m_flags & DEBUG_FLAG_STOP_PC) != 0 && m_stopaddr == curpc)
+ {
+ debug_console_printf(machine, "Stopped at temporary breakpoint %X on CPU '%s'\n", m_stopaddr, m_device.tag());
+ global->execution_state = EXECUTION_STATE_STOPPED;
+ }
+
+ // check for execution breakpoints
+ else if ((m_flags & DEBUG_FLAG_LIVE_BP) != 0)
+ breakpoint_check(curpc);
+ }
+
+ // if we are supposed to halt, do it now
+ if (global->execution_state == EXECUTION_STATE_STOPPED)
+ {
+ bool firststop = true;
+
+ // load comments if we haven't yet
+ if (!global->comments_loaded)
+ {
+ debug_comment_load(m_device.machine());
+ global->comments_loaded = true;
+ }
+
+ // reset any transient state
+ reset_transient_flags(m_device.machine());
+ global->breakcpu = NULL;
+
+ // remember the last visible CPU in the debugger
+ global->visiblecpu = &m_device;
+
+ // update all views
+ machine.debug_view().update_all();
+ debugger_refresh_display(m_device.machine());
+
+ // wait for the debugger; during this time, disable sound output
+ m_device.machine().sound().debugger_mute(true);
+ while (global->execution_state == EXECUTION_STATE_STOPPED)
+ {
+ // flush any pending updates before waiting again
+ machine.debug_view().flush_osd_updates();
+
+ // clear the memory modified flag and wait
+ global->memory_modified = false;
+ if (machine.debug_flags & DEBUG_FLAG_OSD_ENABLED)
+ machine.osd().wait_for_debugger(m_device, firststop);
+ else if (machine.debug_flags & DEBUG_FLAG_ENABLED)
+ debugint_wait_for_debugger(m_device, firststop);
+ firststop = false;
+
+ // if something modified memory, update the screen
+ if (global->memory_modified)
+ {
+ machine.debug_view().update_all(DVT_DISASSEMBLY);
+ debugger_refresh_display(m_device.machine());
+ }
+
+ // check for commands in the source file
+ process_source_file(m_device.machine());
+
+ // if an event got scheduled, resume
+ if (machine.scheduled_event_pending())
+ global->execution_state = EXECUTION_STATE_RUNNING;
+ }
+ m_device.machine().sound().debugger_mute(false);
+
+ // remember the last visible CPU in the debugger
+ global->visiblecpu = &m_device;
+ }
+
+ // handle step out/over on the instruction we are about to execute
+ if ((m_flags & (DEBUG_FLAG_STEPPING_OVER | DEBUG_FLAG_STEPPING_OUT)) != 0 && m_stepaddr == ~0)
+ prepare_for_step_overout(pc());
+
+ // no longer in debugger code
+ global->within_instruction_hook = false;
+}
+
+
+//-------------------------------------------------
+// memory_read_hook - the memory system calls
+// this hook when watchpoints are enabled and a
+// memory read happens
+//-------------------------------------------------
+
+void device_debug::memory_read_hook(address_space &space, offs_t address, UINT64 mem_mask)
+{
+ // check watchpoints
+ watchpoint_check(space, WATCHPOINT_READ, address, 0, mem_mask);
+
+ // check hotspots
+ if (m_hotspots != NULL)
+ hotspot_check(space, address);
+}
+
+
+//-------------------------------------------------
+// memory_write_hook - the memory system calls
+// this hook when watchpoints are enabled and a
+// memory write happens
+//-------------------------------------------------
+
+void device_debug::memory_write_hook(address_space &space, offs_t address, UINT64 data, UINT64 mem_mask)
+{
+ watchpoint_check(space, WATCHPOINT_WRITE, address, data, mem_mask);
+}
+
+
+//-------------------------------------------------
+// set_instruction_hook - set a hook to be
+// called on each instruction for a given device
+//-------------------------------------------------
+
+void device_debug::set_instruction_hook(debug_instruction_hook_func hook)
+{
+ // set the hook and also the CPU's flag for fast knowledge of the hook
+ m_instrhook = hook;
+ if (hook != NULL)
+ m_flags |= DEBUG_FLAG_HOOKED;
+ else
+ m_flags &= ~DEBUG_FLAG_HOOKED;
+}
+
+
+//-------------------------------------------------
+// disassemble - disassemble a line at a given
+// PC on a given device
+//-------------------------------------------------
+
+offs_t device_debug::disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram) const
+{
+ offs_t result = 0;
+
+ // check for disassembler override
+ if (m_dasm_override != NULL)
+ result = (*m_dasm_override)(m_device, buffer, pc, oprom, opram, 0);
+
+ // if we have a disassembler, run it
+ if (result == 0 && m_disasm != NULL)
+ result = m_disasm->disassemble(buffer, pc, oprom, opram, 0);
+
+ // make sure we get good results
+ assert((result & DASMFLAG_LENGTHMASK) != 0);
+#ifdef MAME_DEBUG
+if (m_memory != NULL && m_disasm != NULL)
+{
+ address_space *space = m_memory->space(AS_PROGRAM);
+ int bytes = space->address_to_byte(result & DASMFLAG_LENGTHMASK);
+ assert(bytes >= m_disasm->min_opcode_bytes());
+ assert(bytes <= m_disasm->max_opcode_bytes());
+ (void) bytes; // appease compiler
+}
+#endif
+
+ return result;
+}
+
+
+//-------------------------------------------------
+// ignore - ignore/observe a given device
+//-------------------------------------------------
+
+void device_debug::ignore(bool ignore)
+{
+ debugcpu_private *global = m_device.machine().debugcpu_data;
+
+ assert(m_exec != NULL);
+
+ if (ignore)
+ m_flags &= ~DEBUG_FLAG_OBSERVING;
+ else
+ m_flags |= DEBUG_FLAG_OBSERVING;
+
+ if (&m_device == global->livecpu && ignore)
+ go_next_device();
+}
+
+
+//-------------------------------------------------
+// single_step - single step the device past the
+// requested number of instructions
+//-------------------------------------------------
+
+void device_debug::single_step(int numsteps)
+{
+ debugcpu_private *global = m_device.machine().debugcpu_data;
+
+ assert(m_exec != NULL);
+
+ m_stepsleft = numsteps;
+ m_stepaddr = ~0;
+ m_flags |= DEBUG_FLAG_STEPPING;
+ global->execution_state = EXECUTION_STATE_RUNNING;
+}
+
+
+//-------------------------------------------------
+// single_step_over - single step the device over
+// the requested number of instructions
+//-------------------------------------------------
+
+void device_debug::single_step_over(int numsteps)
+{
+ debugcpu_private *global = m_device.machine().debugcpu_data;
+
+ assert(m_exec != NULL);
+
+ m_stepsleft = numsteps;
+ m_stepaddr = ~0;
+ m_flags |= DEBUG_FLAG_STEPPING_OVER;
+ global->execution_state = EXECUTION_STATE_RUNNING;
+}
+
+
+//-------------------------------------------------
+// single_step_out - single step the device
+// out of the current function
+//-------------------------------------------------
+
+void device_debug::single_step_out()
+{
+ debugcpu_private *global = m_device.machine().debugcpu_data;
+
+ assert(m_exec != NULL);
+
+ m_stepsleft = 100;
+ m_stepaddr = ~0;
+ m_flags |= DEBUG_FLAG_STEPPING_OUT;
+ global->execution_state = EXECUTION_STATE_RUNNING;
+}
+
+
+//-------------------------------------------------
+// go - execute the device until it hits the given
+// address
+//-------------------------------------------------
+
+void device_debug::go(offs_t targetpc)
+{
+ debugcpu_private *global = m_device.machine().debugcpu_data;
+
+ assert(m_exec != NULL);
+
+ m_stopaddr = targetpc;
+ m_flags |= DEBUG_FLAG_STOP_PC;
+ global->execution_state = EXECUTION_STATE_RUNNING;
+}
+
+
+//-------------------------------------------------
+// go_vblank - execute until the next VBLANK
+//-------------------------------------------------
+
+void device_debug::go_vblank()
+{
+ debugcpu_private *global = m_device.machine().debugcpu_data;
+
+ assert(m_exec != NULL);
+
+ global->vblank_occurred = false;
+ m_flags |= DEBUG_FLAG_STOP_VBLANK;
+ global->execution_state = EXECUTION_STATE_RUNNING;
+}
+
+
+//-------------------------------------------------
+// go_interrupt - execute until the specified
+// interrupt fires on the device
+//-------------------------------------------------
+
+void device_debug::go_interrupt(int irqline)
+{
+ debugcpu_private *global = m_device.machine().debugcpu_data;
+
+ assert(m_exec != NULL);
+
+ m_stopirq = irqline;
+ m_flags |= DEBUG_FLAG_STOP_INTERRUPT;
+ global->execution_state = EXECUTION_STATE_RUNNING;
+}
+
+
+//-------------------------------------------------
+// go_exception - execute until the specified
+// exception fires on the visible CPU
+//-------------------------------------------------
+
+void device_debug::go_exception(int exception)
+{
+ debugcpu_private *global = m_device.machine().debugcpu_data;
+
+ assert(m_exec != NULL);
+
+ m_stopexception = exception;
+ m_flags |= DEBUG_FLAG_STOP_EXCEPTION;
+ global->execution_state = EXECUTION_STATE_RUNNING;
+}
+
+
+//-------------------------------------------------
+// go_milliseconds - execute until the specified
+// delay elapses
+//-------------------------------------------------
+
+void device_debug::go_milliseconds(UINT64 milliseconds)
+{
+ debugcpu_private *global = m_device.machine().debugcpu_data;
+
+ assert(m_exec != NULL);
+
+ m_stoptime = m_device.machine().time() + attotime::from_msec(milliseconds);
+ m_flags |= DEBUG_FLAG_STOP_TIME;
+ global->execution_state = EXECUTION_STATE_RUNNING;
+}
+
+
+//-------------------------------------------------
+// go_next_device - execute until we hit the next
+// device
+//-------------------------------------------------
+
+void device_debug::go_next_device()
+{
+ debugcpu_private *global = m_device.machine().debugcpu_data;
+
+ assert(m_exec != NULL);
+
+ global->m_stop_when_not_device = &m_device;
+ global->execution_state = EXECUTION_STATE_RUNNING;
+}
+
+
+//-------------------------------------------------
+// halt_on_next_instruction - halt in the
+// debugger on the next instruction
+//-------------------------------------------------
+
+void device_debug::halt_on_next_instruction(const char *fmt, ...)
+{
+ debugcpu_private *global = m_device.machine().debugcpu_data;
+ va_list arg;
+
+ assert(m_exec != NULL);
+
+ // if something is pending on this CPU already, ignore this request
+ if (&m_device == global->breakcpu)
+ return;
+
+ // output the message to the console
+ va_start(arg, fmt);
+ debug_console_vprintf(m_device.machine(), fmt, arg);
+ va_end(arg);
+
+ // if we are live, stop now, otherwise note that we want to break there
+ if (&m_device == global->livecpu)
+ {
+ global->execution_state = EXECUTION_STATE_STOPPED;
+ if (global->livecpu != NULL)
+ global->livecpu->debug()->compute_debug_flags();
+ }
+ else
+ global->breakcpu = &m_device;
+}
+
+
+//-------------------------------------------------
+// breakpoint_set - set a new breakpoint,
+// returning its index
+//-------------------------------------------------
+
+int device_debug::breakpoint_set(offs_t address, const char *condition, const char *action)
+{
+ // allocate a new one
+ breakpoint *bp = auto_alloc(m_device.machine(), breakpoint(m_symtable, m_device.machine().debugcpu_data->bpindex++, address, condition, action));
+
+ // hook it into our list
+ bp->m_next = m_bplist;
+ m_bplist = bp;
+
+ // update the flags and return the index
+ breakpoint_update_flags();
+ return bp->m_index;
+}
+
+
+//-------------------------------------------------
+// breakpoint_clear - clear a breakpoint by index,
+// returning true if we found it
+//-------------------------------------------------
+
+bool device_debug::breakpoint_clear(int index)
+{
+ // scan the list to see if we own this breakpoint
+ for (breakpoint **bp = &m_bplist; *bp != NULL; bp = &(*bp)->m_next)
+ if ((*bp)->m_index == index)
+ {
+ breakpoint *deleteme = *bp;
+ *bp = deleteme->m_next;
+ auto_free(m_device.machine(), deleteme);
+ breakpoint_update_flags();
+ return true;
+ }
+
+ // we don't own it, return false
+ return false;
+}
+
+
+//-------------------------------------------------
+// breakpoint_clear_all - clear all breakpoints
+//-------------------------------------------------
+
+void device_debug::breakpoint_clear_all()
+{
+ // clear the head until we run out
+ while (m_bplist != NULL)
+ breakpoint_clear(m_bplist->index());
+}
+
+
+//-------------------------------------------------
+// breakpoint_enable - enable/disable a breakpoint
+// by index, returning true if we found it
+//-------------------------------------------------
+
+bool device_debug::breakpoint_enable(int index, bool enable)
+{
+ // scan the list to see if we own this breakpoint
+ for (breakpoint *bp = m_bplist; bp != NULL; bp = bp->next())
+ if (bp->m_index == index)
+ {
+ bp->m_enabled = enable;
+ breakpoint_update_flags();
+ return true;
+ }
+
+ // we don't own it, return false
+ return false;
+}
+
+
+//-------------------------------------------------
+// breakpoint_enable_all - enable/disable all
+// breakpoints
+//-------------------------------------------------
+
+void device_debug::breakpoint_enable_all(bool enable)
+{
+ // apply the enable to all breakpoints we own
+ for (breakpoint *bp = m_bplist; bp != NULL; bp = bp->next())
+ breakpoint_enable(bp->index(), enable);
+}
+
+
+//-------------------------------------------------
+// watchpoint_set - set a new watchpoint,
+// returning its index
+//-------------------------------------------------
+
+int device_debug::watchpoint_set(address_space &space, int type, offs_t address, offs_t length, const char *condition, const char *action)
+{
+ assert(space.spacenum() < ARRAY_LENGTH(m_wplist));
+
+ // allocate a new one
+ watchpoint *wp = auto_alloc(m_device.machine(), watchpoint(m_symtable, m_device.machine().debugcpu_data->bpindex++, space, type, address, length, condition, action));
+
+ // hook it into our list
+ wp->m_next = m_wplist[space.spacenum()];
+ m_wplist[space.spacenum()] = wp;
+
+ // update the flags and return the index
+ watchpoint_update_flags(wp->m_space);
+ return wp->m_index;
+}
+
+
+//-------------------------------------------------
+// watchpoint_clear - clear a watchpoint by index,
+// returning true if we found it
+//-------------------------------------------------
+
+bool device_debug::watchpoint_clear(int index)
+{
+ // scan the list to see if we own this breakpoint
+ for (address_spacenum spacenum = AS_0; spacenum < ARRAY_LENGTH(m_wplist); spacenum++)
+ for (watchpoint **wp = &m_wplist[spacenum]; *wp != NULL; wp = &(*wp)->m_next)
+ if ((*wp)->m_index == index)
+ {
+ watchpoint *deleteme = *wp;
+ address_space &space = deleteme->m_space;
+ *wp = deleteme->m_next;
+ auto_free(m_device.machine(), deleteme);
+ watchpoint_update_flags(space);
+ return true;
+ }
+
+ // we don't own it, return false
+ return false;
+}
+
+
+//-------------------------------------------------
+// watchpoint_clear_all - clear all watchpoints
+//-------------------------------------------------
+
+void device_debug::watchpoint_clear_all()
+{
+ // clear the head until we run out
+ for (address_spacenum spacenum = AS_0; spacenum < ARRAY_LENGTH(m_wplist); spacenum++)
+ while (m_wplist[spacenum] != NULL)
+ watchpoint_clear(m_wplist[spacenum]->index());
+}
+
+
+//-------------------------------------------------
+// watchpoint_enable - enable/disable a watchpoint
+// by index, returning true if we found it
+//-------------------------------------------------
+
+bool device_debug::watchpoint_enable(int index, bool enable)
+{
+ // scan the list to see if we own this watchpoint
+ for (address_spacenum spacenum = AS_0; spacenum < ARRAY_LENGTH(m_wplist); spacenum++)
+ for (watchpoint *wp = m_wplist[spacenum]; wp != NULL; wp = wp->next())
+ if (wp->m_index == index)
+ {
+ wp->m_enabled = enable;
+ watchpoint_update_flags(wp->m_space);
+ return true;
+ }
+
+ // we don't own it, return false
+ return false;
+}
+
+
+//-------------------------------------------------
+// watchpoint_enable_all - enable/disable all
+// watchpoints
+//-------------------------------------------------
+
+void device_debug::watchpoint_enable_all(bool enable)
+{
+ // apply the enable to all watchpoints we own
+ for (address_spacenum spacenum = AS_0; spacenum < ARRAY_LENGTH(m_wplist); spacenum++)
+ for (watchpoint *wp = m_wplist[spacenum]; wp != NULL; wp = wp->next())
+ watchpoint_enable(wp->index(), enable);
+}
+
+
+//-------------------------------------------------
+// hotspot_track - enable/disable tracking of
+// hotspots
+//-------------------------------------------------
+
+void device_debug::hotspot_track(int numspots, int threshhold)
+{
+ // if we already have tracking enabled, kill it
+ auto_free(m_device.machine(), m_hotspots);
+ m_hotspots = NULL;
+
+ // only start tracking if we have a non-zero count
+ if (numspots > 0)
+ {
+ // allocate memory for hotspots
+ m_hotspots = auto_alloc_array(m_device.machine(), hotspot_entry, numspots);
+ memset(m_hotspots, 0xff, sizeof(*m_hotspots) * numspots);
+
+ // fill in the info
+ m_hotspot_count = numspots;
+ m_hotspot_threshhold = threshhold;
+ }
+
+ // update the watchpoint flags to include us
+ if (m_memory != NULL && m_memory->space(AS_PROGRAM) != NULL)
+ watchpoint_update_flags(*m_memory->space(AS_PROGRAM));
+}
+
+
+//-------------------------------------------------
+// history_pc - return an entry from the PC
+// history
+//-------------------------------------------------
+
+offs_t device_debug::history_pc(int index) const
+{
+ if (index > 0)
+ index = 0;
+ if (index <= -HISTORY_SIZE)
+ index = -HISTORY_SIZE + 1;
+ return m_pc_history[(m_pc_history_index + ARRAY_LENGTH(m_pc_history) - 1 + index) % ARRAY_LENGTH(m_pc_history)];
+}
+
+
+//-------------------------------------------------
+// comment_add - adds a comment to the list at
+// the given address
+//-------------------------------------------------
+
+void device_debug::comment_add(offs_t addr, const char *comment, rgb_t color)
+{
+ // create a new item for the list
+ UINT32 crc = compute_opcode_crc32(addr);
+ dasm_comment *newcomment = auto_alloc(m_device.machine(), dasm_comment(comment, addr, color, crc));
+
+ // figure out where to insert it
+ dasm_comment *prev = NULL;
+ dasm_comment *curr;
+ for (curr = m_comment_list.first(); curr != NULL; prev = curr, curr = curr->next())
+ if (curr->m_address >= addr)
+ break;
+
+ // we could be the new head
+ if (prev == NULL)
+ m_comment_list.prepend(*newcomment);
+
+ // or else we just insert ourselves here
+ else
+ {
+ newcomment->m_next = prev->m_next;
+ prev->m_next = newcomment;
+ }
+
+ // scan forward from here to delete any exact matches
+ for ( ; curr != NULL && curr->m_address == addr; curr = curr->next())
+ if (curr->m_crc == crc)
+ {
+ m_comment_list.remove(*curr);
+ break;
+ }
+
+ // force an update
+ m_comment_change++;
+}
+
+
+//-------------------------------------------------
+// comment_remove - removes a comment at the
+// given address with a matching CRC
+//-------------------------------------------------
+
+bool device_debug::comment_remove(offs_t addr)
+{
+ // scan the list for a match
+ UINT32 crc = compute_opcode_crc32(addr);
+ for (dasm_comment *curr = m_comment_list.first(); curr != NULL; curr = curr->next())
+ {
+ // if we're past the address, we failed
+ if (curr->m_address > addr)
+ break;
+
+ // find an exact match
+ if (curr->m_address == addr && curr->m_crc == crc)
+ {
+ // remove it and force an update
+ m_comment_list.remove(*curr);
+ m_comment_change++;
+ return true;
+ }
+ }
+
+ // failure is an option
+ return false;
+}
+
+
+//-------------------------------------------------
+// comment_text - return the text of a comment
+//-------------------------------------------------
+
+const char *device_debug::comment_text(offs_t addr) const
+{
+ // scan the list for a match
+ UINT32 crc = compute_opcode_crc32(addr);
+ for (dasm_comment *curr = m_comment_list.first(); curr != NULL; curr = curr->next())
+ {
+ // if we're past the address, we failed
+ if (curr->m_address > addr)
+ break;
+
+ // find an exact match
+ if (curr->m_address == addr && curr->m_crc == crc)
+ return curr->m_text;
+ }
+
+ // failure is an option
+ return NULL;
+}
+
+
+//-------------------------------------------------
+// comment_export - export the comments to the
+// given XML data node
+//-------------------------------------------------
+
+bool device_debug::comment_export(xml_data_node &curnode)
+{
+ // iterate through the comments
+ astring crc_buf;
+ for (dasm_comment *curr = m_comment_list.first(); curr != NULL; curr = curr->next())
+ {
+ xml_data_node *datanode = xml_add_child(&curnode, "comment", xml_normalize_string(curr->m_text));
+ if (datanode == NULL)
+ return false;
+ xml_set_attribute_int(datanode, "address", curr->m_address);
+ xml_set_attribute_int(datanode, "color", curr->m_color);
+ crc_buf.printf("%08X", curr->m_crc);
+ xml_set_attribute(datanode, "crc", crc_buf);
+ }
+ return true;
+}
+
+
+//-------------------------------------------------
+// comment_import - import the comments from the
+// given XML data node
+//-------------------------------------------------
+
+bool device_debug::comment_import(xml_data_node &cpunode)
+{
+ // iterate through nodes
+ for (xml_data_node *datanode = xml_get_sibling(cpunode.child, "comment"); datanode; datanode = xml_get_sibling(datanode->next, "comment"))
+ {
+ // extract attributes
+ offs_t address = xml_get_attribute_int(datanode, "address", 0);
+ rgb_t color = xml_get_attribute_int(datanode, "color", 0);
+ UINT32 crc;
+ sscanf(xml_get_attribute_string(datanode, "crc", 0), "%08X", &crc);
+
+ // add the new comment; we assume they were saved ordered
+ m_comment_list.append(*auto_alloc(m_device.machine(), dasm_comment(datanode->value, address, color, crc)));
+ }
+ return true;
+}
+
+
+//-------------------------------------------------
+// comment_dump - logs comments to the error.log
+// at a given address
+//-------------------------------------------------
+
+void device_debug::comment_dump(offs_t addr)
+{
+ // determine the CRC at the given address (if valid)
+ UINT32 crc = (addr == ~0) ? 0 : compute_opcode_crc32(addr);
+
+ // dump everything that matches
+ bool found = false;
+ for (dasm_comment *curr = m_comment_list.first(); curr != NULL; curr = curr->next())
+ if (addr == ~0 || (curr->m_address == addr && curr->m_crc == crc))
+ {
+ found = true;
+ logerror("%08X %08X - %s\n", curr->m_address, curr->m_crc, curr->m_text.cstr());
+ }
+
+ // if nothing found, indicate as much
+ if (!found)
+ logerror("No comment exists for address : 0x%x\n", addr);
+}
+
+
+//-------------------------------------------------
+// compute_opcode_crc32 - determine the CRC of
+// the opcode bytes at the given address
+//-------------------------------------------------
+
+UINT32 device_debug::compute_opcode_crc32(offs_t address) const
+{
+ // no memory interface, just fail
+ if (m_memory == NULL)
+ return 0;
+
+ // no program interface, just fail
+ address_space *space = m_memory->space(AS_PROGRAM);
+ if (space == NULL)
+ return 0;
+
+ // zero out the buffers
+ UINT8 opbuf[64], argbuf[64];
+ memset(opbuf, 0x00, sizeof(opbuf));
+ memset(argbuf, 0x00, sizeof(argbuf));
+
+ // fetch the bytes up to the maximum
+ int maxbytes = m_disasm->max_opcode_bytes();
+ for (int index = 0; index < maxbytes; index++)
+ {
+ opbuf[index] = debug_read_opcode(space, address + index, 1, false);
+ argbuf[index] = debug_read_opcode(space, address + index, 1, true);
+ }
+
+ // disassemble and then convert to bytes
+ char buff[256];
+ int numbytes = disassemble(buff, address & space->logaddrmask(), opbuf, argbuf) & DASMFLAG_LENGTHMASK;
+ numbytes = space->address_to_byte(numbytes);
+
+ // return a CRC of the resulting bytes
+ return crc32(0, argbuf, numbytes);
+}
+
+
+//-------------------------------------------------
+// trace - trace execution of a given device
+//-------------------------------------------------
+
+void device_debug::trace(FILE *file, bool trace_over, const char *action)
+{
+ // delete any existing tracers
+ auto_free(m_device.machine(), m_trace);
+ m_trace = NULL;
+
+ // if we have a new file, make a new tracer
+ if (file != NULL)
+ m_trace = auto_alloc(m_device.machine(), tracer(*this, *file, trace_over, action));
+}
+
+
+//-------------------------------------------------
+// trace_printf - output data into the given
+// device's tracefile, if tracing
+//-------------------------------------------------
+
+void device_debug::trace_printf(const char *fmt, ...)
+{
+ if (m_trace != NULL)
+ {
+ va_list va;
+ va_start(va, fmt);
+ m_trace->vprintf(fmt, va);
+ va_end(va);
+ }
+}
+
+
+//-------------------------------------------------
+// compute_debug_flags - compute the global
+// debug flags for optimal efficiency
+//-------------------------------------------------
+
+void device_debug::compute_debug_flags()
+{
+ running_machine &machine = m_device.machine();
+ debugcpu_private *global = machine.debugcpu_data;
+
+ // clear out global flags by default, keep DEBUG_FLAG_OSD_ENABLED
+ machine.debug_flags &= DEBUG_FLAG_OSD_ENABLED;
+ machine.debug_flags |= DEBUG_FLAG_ENABLED;
+
+ // if we are ignoring this CPU, or if events are pending, we're done
+ if ((m_flags & DEBUG_FLAG_OBSERVING) == 0 || machine.scheduled_event_pending() || machine.save_or_load_pending())
+ return;
+
+ // if we're stopped, keep calling the hook
+ if (global->execution_state == EXECUTION_STATE_STOPPED)
+ machine.debug_flags |= DEBUG_FLAG_CALL_HOOK;
+
+ // if we're tracking history, or we're hooked, or stepping, or stopping at a breakpoint
+ // make sure we call the hook
+ if ((m_flags & (DEBUG_FLAG_HISTORY | DEBUG_FLAG_HOOKED | DEBUG_FLAG_STEPPING_ANY | DEBUG_FLAG_STOP_PC | DEBUG_FLAG_LIVE_BP)) != 0)
+ machine.debug_flags |= DEBUG_FLAG_CALL_HOOK;
+
+ // also call if we are tracing
+ if (m_trace != NULL)
+ machine.debug_flags |= DEBUG_FLAG_CALL_HOOK;
+
+ // if we are stopping at a particular time and that time is within the current timeslice, we need to be called
+ if ((m_flags & DEBUG_FLAG_STOP_TIME) && m_endexectime <= m_stoptime)
+ machine.debug_flags |= DEBUG_FLAG_CALL_HOOK;
+}
+
+
+//-------------------------------------------------
+// prepare_for_step_overout - prepare things for
+// stepping over an instruction
+//-------------------------------------------------
+
+void device_debug::prepare_for_step_overout(offs_t pc)
+{
+ // disassemble the current instruction and get the flags
+ astring dasmbuffer;
+ offs_t dasmresult = dasm_wrapped(dasmbuffer, pc);
+
+ // if flags are supported and it's a call-style opcode, set a temp breakpoint after that instruction
+ if ((dasmresult & DASMFLAG_SUPPORTED) != 0 && (dasmresult & DASMFLAG_STEP_OVER) != 0)
+ {
+ int extraskip = (dasmresult & DASMFLAG_OVERINSTMASK) >> DASMFLAG_OVERINSTSHIFT;
+ pc += dasmresult & DASMFLAG_LENGTHMASK;
+
+ // if we need to skip additional instructions, advance as requested
+ while (extraskip-- > 0)
+ pc += dasm_wrapped(dasmbuffer, pc) & DASMFLAG_LENGTHMASK;
+ m_stepaddr = pc;
+ }
+
+ // if we're stepping out and this isn't a step out instruction, reset the steps until stop to a high number
+ if ((m_flags & DEBUG_FLAG_STEPPING_OUT) != 0)
+ {
+ if ((dasmresult & DASMFLAG_SUPPORTED) != 0 && (dasmresult & DASMFLAG_STEP_OUT) == 0)
+ m_stepsleft = 100;
+ else
+ m_stepsleft = 1;
+ }
+}
+
+
+//-------------------------------------------------
+// breakpoint_update_flags - update the device's
+// breakpoint flags
+//-------------------------------------------------
+
+void device_debug::breakpoint_update_flags()
+{
+ // see if there are any enabled breakpoints
+ m_flags &= ~DEBUG_FLAG_LIVE_BP;
+ for (breakpoint *bp = m_bplist; bp != NULL; bp = bp->m_next)
+ if (bp->m_enabled)
+ {
+ m_flags |= DEBUG_FLAG_LIVE_BP;
+ break;
+ }
+
+ // push the flags out globally
+ debugcpu_private *global = m_device.machine().debugcpu_data;
+ if (global->livecpu != NULL)
+ global->livecpu->debug()->compute_debug_flags();
+}
+
+
+//-------------------------------------------------
+// breakpoint_check - check the breakpoints for
+// a given device
+//-------------------------------------------------
+
+void device_debug::breakpoint_check(offs_t pc)
+{
+ // see if we match
+ for (breakpoint *bp = m_bplist; bp != NULL; bp = bp->m_next)
+ if (bp->hit(pc))
+ {
+ // halt in the debugger by default
+ debugcpu_private *global = m_device.machine().debugcpu_data;
+ global->execution_state = EXECUTION_STATE_STOPPED;
+
+ // if we hit, evaluate the action
+ if (bp->m_action)
+ debug_console_execute_command(m_device.machine(), bp->m_action, 0);
+
+ // print a notification, unless the action made us go again
+ if (global->execution_state == EXECUTION_STATE_STOPPED)
+ debug_console_printf(m_device.machine(), "Stopped at breakpoint %X\n", bp->m_index);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// watchpoint_update_flags - update the device's
+// watchpoint flags
+//-------------------------------------------------
+
+void device_debug::watchpoint_update_flags(address_space &space)
+{
+ // if hotspots are enabled, turn on all reads
+ bool enableread = false;
+ if (m_hotspots != NULL)
+ enableread = true;
+
+ // see if there are any enabled breakpoints
+ bool enablewrite = false;
+ for (watchpoint *wp = m_wplist[space.spacenum()]; wp != NULL; wp = wp->m_next)
+ if (wp->m_enabled)
+ {
+ if (wp->m_type & WATCHPOINT_READ)
+ enableread = true;
+ if (wp->m_type & WATCHPOINT_WRITE)
+ enablewrite = true;
+ }
+
+ // push the flags out globally
+ space.enable_read_watchpoints(enableread);
+ space.enable_write_watchpoints(enablewrite);
+}
+
+
+//-------------------------------------------------
+// watchpoint_check - check the watchpoints
+// for a given CPU and address space
+//-------------------------------------------------
+
+void device_debug::watchpoint_check(address_space &space, int type, offs_t address, UINT64 value_to_write, UINT64 mem_mask)
+{
+ debugcpu_private *global = space.machine().debugcpu_data;
+
+ // if we're within debugger code, don't stop
+ if (global->within_instruction_hook || global->debugger_access)
+ return;
+ global->within_instruction_hook = true;
+
+ // adjust address, size & value_to_write based on mem_mask.
+ offs_t size = 0;
+ if (mem_mask != 0)
+ {
+ int bus_size = space.data_width() / 8;
+ int address_offset = 0;
+
+ while (address_offset < bus_size && (mem_mask & 0xff) == 0)
+ {
+ address_offset++;
+ value_to_write >>= 8;
+ mem_mask >>= 8;
+ }
+
+ while (mem_mask != 0)
+ {
+ size++;
+ mem_mask >>= 8;
+ }
+
+ if (space.endianness() == ENDIANNESS_LITTLE)
+ address += address_offset;
+ else
+ address += bus_size - size - address_offset;
+ }
+
+ // if we are a write watchpoint, stash the value that will be written
+ global->wpaddr = address;
+ if (type & WATCHPOINT_WRITE)
+ global->wpdata = value_to_write;
+
+ // see if we match
+ for (watchpoint *wp = m_wplist[space.spacenum()]; wp != NULL; wp = wp->m_next)
+ if (wp->hit(type, address, size))
+ {
+ // halt in the debugger by default
+ global->execution_state = EXECUTION_STATE_STOPPED;
+
+ // if we hit, evaluate the action
+ if (wp->m_action)
+ debug_console_execute_command(space.machine(), wp->m_action, 0);
+
+ // print a notification, unless the action made us go again
+ if (global->execution_state == EXECUTION_STATE_STOPPED)
+ {
+ static const char *const sizes[] =
+ {
+ "0bytes", "byte", "word", "3bytes", "dword", "5bytes", "6bytes", "7bytes", "qword"
+ };
+ offs_t pc = (space.device().debug()->m_state != NULL) ? space.device().debug()->m_state->pc() : 0;
+ astring buffer;
+
+ if (type & WATCHPOINT_WRITE)
+ {
+ buffer.printf("Stopped at watchpoint %X writing %s to %08X (PC=%X)", wp->m_index, sizes[size], space.byte_to_address(address), pc);
+ if (value_to_write >> 32)
+ buffer.catprintf(" (data=%X%08X)", (UINT32)(value_to_write >> 32), (UINT32)value_to_write);
+ else
+ buffer.catprintf(" (data=%X)", (UINT32)value_to_write);
+ }
+ else
+ buffer.printf("Stopped at watchpoint %X reading %s from %08X (PC=%X)", wp->m_index, sizes[size], space.byte_to_address(address), pc);
+ debug_console_printf(space.machine(), "%s\n", buffer.cstr());
+ space.device().debug()->compute_debug_flags();
+ }
+ break;
+ }
+
+ global->within_instruction_hook = false;
+}
+
+
+//-------------------------------------------------
+// hotspot_check - check for hotspots on a
+// memory read access
+//-------------------------------------------------
+
+void device_debug::hotspot_check(address_space &space, offs_t address)
+{
+ offs_t curpc = pc();
+
+ // see if we have a match in our list
+ int hotindex;
+ for (hotindex = 0; hotindex < m_hotspot_count; hotindex++)
+ if (m_hotspots[hotindex].m_access == address && m_hotspots[hotindex].m_pc == curpc && m_hotspots[hotindex].m_space == &space)
+ break;
+
+ // if we didn't find any, make a new entry
+ if (hotindex == m_hotspot_count)
+ {
+ // if the bottom of the list is over the threshhold, print it
+ hotspot_entry &spot = m_hotspots[m_hotspot_count - 1];
+ if (spot.m_count > m_hotspot_threshhold)
+ debug_console_printf(space.machine(), "Hotspot @ %s %08X (PC=%08X) hit %d times (fell off bottom)\n", space.name(), spot.m_access, spot.m_pc, spot.m_count);
+
+ // move everything else down and insert this one at the top
+ memmove(&m_hotspots[1], &m_hotspots[0], sizeof(m_hotspots[0]) * (m_hotspot_count - 1));
+ m_hotspots[0].m_access = address;
+ m_hotspots[0].m_pc = curpc;
+ m_hotspots[0].m_space = &space;
+ m_hotspots[0].m_count = 1;
+ }
+
+ // if we did find one, increase the count and move it to the top
+ else
+ {
+ m_hotspots[hotindex].m_count++;
+ if (hotindex != 0)
+ {
+ hotspot_entry temp = m_hotspots[hotindex];
+ memmove(&m_hotspots[1], &m_hotspots[0], sizeof(m_hotspots[0]) * hotindex);
+ m_hotspots[0] = temp;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// dasm_wrapped - wraps calls to the disassembler
+// by fetching the opcode bytes to a temporary
+// buffer and then disassembling them
+//-------------------------------------------------
+
+UINT32 device_debug::dasm_wrapped(astring &buffer, offs_t pc)
+{
+ assert(m_memory != NULL && m_disasm != NULL);
+
+ // determine the adjusted PC
+ address_space *space = m_memory->space(AS_PROGRAM);
+ offs_t pcbyte = space->address_to_byte(pc) & space->bytemask();
+
+ // fetch the bytes up to the maximum
+ UINT8 opbuf[64], argbuf[64];
+ int maxbytes = max_opcode_bytes();
+ for (int numbytes = 0; numbytes < maxbytes; numbytes++)
+ {
+ opbuf[numbytes] = debug_read_opcode(space, pcbyte + numbytes, 1, false);
+ argbuf[numbytes] = debug_read_opcode(space, pcbyte + numbytes, 1, true);
+ }
+
+ // disassemble to our buffer
+ buffer.expand(200);
+ return disassemble(buffer.text, pc, opbuf, argbuf);
+}
+
+
+//-------------------------------------------------
+// get_current_pc - getter callback for a device's
+// current instruction pointer
+//-------------------------------------------------
+
+UINT64 device_debug::get_current_pc(symbol_table &table, void *ref)
+{
+ device_t *device = reinterpret_cast<device_t *>(table.globalref());
+ return device->debug()->pc();
+}
+
+
+//-------------------------------------------------
+// get_cycles - getter callback for the
+// 'cycles' symbol
+//-------------------------------------------------
+
+UINT64 device_debug::get_cycles(symbol_table &table, void *ref)
+{
+ device_t *device = reinterpret_cast<device_t *>(table.globalref());
+ return device->debug()->m_exec->cycles_remaining();
+}
+
+
+//-------------------------------------------------
+// get_logunmap - getter callback for the logumap
+// symbols
+//-------------------------------------------------
+
+UINT64 device_debug::get_logunmap(symbol_table &table, void *ref)
+{
+ address_space *space = reinterpret_cast<address_space *>(table.globalref());
+ return space->log_unmap();
+}
+
+
+//-------------------------------------------------
+// set_logunmap - setter callback for the logumap
+// symbols
+//-------------------------------------------------
+
+void device_debug::set_logunmap(symbol_table &table, void *ref, UINT64 value)
+{
+ address_space *space = reinterpret_cast<address_space *>(table.globalref());
+ space->set_log_unmap(value ? true : false);
+}
+
+
+//-------------------------------------------------
+// get_state - getter callback for a device's
+// state symbols
+//-------------------------------------------------
+
+UINT64 device_debug::get_state(symbol_table &table, void *ref)
+{
+ device_t *device = reinterpret_cast<device_t *>(table.globalref());
+ return device->debug()->m_state->state(reinterpret_cast<FPTR>(ref));
+}
+
+
+//-------------------------------------------------
+// set_state - setter callback for a device's
+// state symbols
+//-------------------------------------------------
+
+void device_debug::set_state(symbol_table &table, void *ref, UINT64 value)
+{
+ device_t *device = reinterpret_cast<device_t *>(table.globalref());
+ device->debug()->m_state->set_state(reinterpret_cast<FPTR>(ref), value);
+}
+
+
+
+//**************************************************************************
+// DEBUG BREAKPOINT
+//**************************************************************************
+
+//-------------------------------------------------
+// breakpoint - constructor
+//-------------------------------------------------
+
+device_debug::breakpoint::breakpoint(symbol_table &symbols, int index, offs_t address, const char *condition, const char *action)
+ : m_next(NULL),
+ m_index(index),
+ m_enabled(true),
+ m_address(address),
+ m_condition(&symbols, (condition != NULL) ? condition : "1"),
+ m_action((action != NULL) ? action : "")
+{
+}
+
+
+//-------------------------------------------------
+// hit - detect a hit
+//-------------------------------------------------
+
+bool device_debug::breakpoint::hit(offs_t pc)
+{
+ // don't hit if disabled
+ if (!m_enabled)
+ return false;
+
+ // must match our address
+ if (m_address != pc)
+ return false;
+
+ // must satisfy the condition
+ if (!m_condition.is_empty())
+ {
+ try
+ {
+ return (m_condition.execute() != 0);
+ }
+ catch (expression_error &)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+
+//**************************************************************************
+// DEBUG WATCHPOINT
+//**************************************************************************
+
+//-------------------------------------------------
+// watchpoint - constructor
+//-------------------------------------------------
+
+device_debug::watchpoint::watchpoint(symbol_table &symbols, int index, address_space &space, int type, offs_t address, offs_t length, const char *condition, const char *action)
+ : m_next(NULL),
+ m_space(space),
+ m_index(index),
+ m_enabled(true),
+ m_type(type),
+ m_address(space.address_to_byte(address) & space.bytemask()),
+ m_length(space.address_to_byte(length)),
+ m_condition(&symbols, (condition != NULL) ? condition : "1"),
+ m_action((action != NULL) ? action : "")
+{
+}
+
+
+//-------------------------------------------------
+// hit - detect a hit
+//-------------------------------------------------
+
+bool device_debug::watchpoint::hit(int type, offs_t address, int size)
+{
+ // don't hit if disabled
+ if (!m_enabled)
+ return false;
+
+ // must match the type
+ if ((m_type & type) == 0)
+ return false;
+
+ // must match our address
+ if (address + size <= m_address || address >= m_address + m_length)
+ return false;
+
+ // must satisfy the condition
+ if (!m_condition.is_empty())
+ {
+ try
+ {
+ return (m_condition.execute() != 0);
+ }
+ catch (expression_error &)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+
+//**************************************************************************
+// TRACER
+//**************************************************************************
+
+//-------------------------------------------------
+// tracer - constructor
+//-------------------------------------------------
+
+device_debug::tracer::tracer(device_debug &debug, FILE &file, bool trace_over, const char *action)
+ : m_debug(debug),
+ m_file(file),
+ m_action((action != NULL) ? action : ""),
+ m_loops(0),
+ m_nextdex(0),
+ m_trace_over(trace_over),
+ m_trace_over_target(~0)
+{
+ memset(m_history, 0, sizeof(m_history));
+}
+
+
+//-------------------------------------------------
+// ~tracer - destructor
+//-------------------------------------------------
+
+device_debug::tracer::~tracer()
+{
+ // make sure we close the file if we can
+ fclose(&m_file);
+}
+
+
+//-------------------------------------------------
+// update - log to the tracefile the data for a
+// given instruction
+//-------------------------------------------------
+
+void device_debug::tracer::update(offs_t pc)
+{
+ // are we in trace over mode and in a subroutine?
+ if (m_trace_over && m_trace_over_target != ~0)
+ {
+ if (m_trace_over_target != pc)
+ return;
+ m_trace_over_target = ~0;
+ }
+
+ // check for a loop condition
+ int count = 0;
+ for (int index = 0; index < ARRAY_LENGTH(m_history); index++)
+ if (m_history[index] == pc)
+ count++;
+
+ // if more than 1 hit, just up the loop count and get out
+ if (count > 1)
+ {
+ m_loops++;
+ return;
+ }
+
+ // if we just finished looping, indicate as much
+ if (m_loops != 0)
+ fprintf(&m_file, "\n (loops for %d instructions)\n\n", m_loops);
+ m_loops = 0;
+
+ // execute any trace actions first
+ if (m_action)
+ debug_console_execute_command(m_debug.m_device.machine(), m_action, 0);
+
+ // print the address
+ astring buffer;
+ int logaddrchars = m_debug.logaddrchars();
+ buffer.printf("%0*X: ", logaddrchars, pc);
+
+ // print the disassembly
+ astring dasm;
+ offs_t dasmresult = m_debug.dasm_wrapped(dasm, pc);
+ buffer.cat(dasm);
+
+ // output the result
+ fprintf(&m_file, "%s\n", buffer.cstr());
+
+ // do we need to step the trace over this instruction?
+ if (m_trace_over && (dasmresult & DASMFLAG_SUPPORTED) != 0 && (dasmresult & DASMFLAG_STEP_OVER) != 0)
+ {
+ int extraskip = (dasmresult & DASMFLAG_OVERINSTMASK) >> DASMFLAG_OVERINSTSHIFT;
+ offs_t trace_over_target = pc + (dasmresult & DASMFLAG_LENGTHMASK);
+
+ // if we need to skip additional instructions, advance as requested
+ while (extraskip-- > 0)
+ trace_over_target += m_debug.dasm_wrapped(dasm, trace_over_target) & DASMFLAG_LENGTHMASK;
+
+ m_trace_over_target = trace_over_target;
+ }
+
+ // log this PC
+ m_nextdex = (m_nextdex + 1) % TRACE_LOOPS;
+ m_history[m_nextdex] = pc;
+}
+
+
+//-------------------------------------------------
+// vprintf - generic print to the trace file
+//-------------------------------------------------
+
+void device_debug::tracer::vprintf(const char *format, va_list va)
+{
+ // pass through to the file
+ vfprintf(&m_file, format, va);
+}
+
+
+//-------------------------------------------------
+// flush - flush any pending changes to the trace
+// file
+//-------------------------------------------------
+
+void device_debug::tracer::flush()
+{
+ fflush(&m_file);
+}
+
+
+//-------------------------------------------------
+// dasm_comment - constructor
+//-------------------------------------------------
+
+device_debug::dasm_comment::dasm_comment(const char *text, offs_t address, rgb_t color, UINT32 crc)
+ : m_next(NULL),
+ m_address(address),
+ m_color(color),
+ m_crc(crc),
+ m_text(text)
+{
+}
diff --git a/trunk/src/emu/debug/debugcpu.h b/trunk/src/emu/debug/debugcpu.h
new file mode 100644
index 00000000000..2c414b88fc8
--- /dev/null
+++ b/trunk/src/emu/debug/debugcpu.h
@@ -0,0 +1,460 @@
+/*********************************************************************
+
+ debugcpu.h
+
+ Debugger CPU/memory interface engine.
+
+****************************************************************************
+
+ 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 __DEBUGCPU_H__
+#define __DEBUGCPU_H__
+
+#include "express.h"
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+const UINT8 WATCHPOINT_READ = 1;
+const UINT8 WATCHPOINT_WRITE = 2;
+const UINT8 WATCHPOINT_READWRITE = WATCHPOINT_READ | WATCHPOINT_WRITE;
+
+const int COMMENT_VERSION = 1;
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+typedef int (*debug_instruction_hook_func)(device_t &device, offs_t curpc);
+
+
+typedef struct _xml_data_node xml_data_node;
+
+
+class device_debug
+{
+ typedef offs_t (*dasm_override_func)(device_t &device, char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, int options);
+
+public:
+ // breakpoint class
+ class breakpoint
+ {
+ friend class device_debug;
+
+ public:
+ // construction/destruction
+ breakpoint(symbol_table &symbols, int index, offs_t address, const char *condition = NULL, const char *action = NULL);
+
+ // getters
+ breakpoint *next() const { return m_next; }
+ int index() const { return m_index; }
+ bool enabled() const { return m_enabled; }
+ offs_t address() const { return m_address; }
+ const char *condition() const { return m_condition.original_string(); }
+ const char *action() const { return m_action; }
+
+ private:
+ // internals
+ bool hit(offs_t pc);
+
+ breakpoint * m_next; // next in the list
+ int m_index; // user reported index
+ UINT8 m_enabled; // enabled?
+ offs_t m_address; // execution address
+ parsed_expression m_condition; // condition
+ astring m_action; // action
+ };
+
+ // watchpoint class
+ class watchpoint
+ {
+ friend class device_debug;
+
+ public:
+ // construction/destruction
+ watchpoint(symbol_table &symbols, int index, address_space &space, int type, offs_t address, offs_t length, const char *condition = NULL, const char *action = NULL);
+
+ // getters
+ watchpoint *next() const { return m_next; }
+ address_space &space() const { return m_space; }
+ int index() const { return m_index; }
+ int type() const { return m_type; }
+ bool enabled() const { return m_enabled; }
+ offs_t address() const { return m_address; }
+ offs_t length() const { return m_length; }
+ const char *condition() const { return m_condition.original_string(); }
+ const char *action() const { return m_action; }
+
+ private:
+ // internals
+ bool hit(int type, offs_t address, int size);
+
+ watchpoint * m_next; // next in the list
+ address_space & m_space; // address space
+ int m_index; // user reported index
+ bool m_enabled; // enabled?
+ UINT8 m_type; // type (read/write)
+ offs_t m_address; // start address
+ offs_t m_length; // length of watch area
+ parsed_expression m_condition; // condition
+ astring m_action; // action
+ };
+
+public:
+ // construction/destruction
+ device_debug(device_t &device);
+ ~device_debug();
+
+ // getters
+ symbol_table &symtable() { return m_symtable; }
+
+ // commonly-used pass-throughs
+ offs_t pc() const { return (m_state != NULL) ? m_state->pc() : 0; }
+ int logaddrchars(address_spacenum spacenum = AS_0) const { return (m_memory != NULL && m_memory->space(spacenum) != NULL) ? m_memory->space(spacenum)->logaddrchars() : 8; }
+ int min_opcode_bytes() const { return (m_disasm != NULL) ? m_disasm->max_opcode_bytes() : 1; }
+ int max_opcode_bytes() const { return (m_disasm != NULL) ? m_disasm->max_opcode_bytes() : 1; }
+
+ // hooks used by the rest of the system
+ void start_hook(attotime endtime);
+ void stop_hook();
+ void interrupt_hook(int irqline);
+ void exception_hook(int exception);
+ void instruction_hook(offs_t curpc);
+ void memory_read_hook(address_space &space, offs_t address, UINT64 mem_mask);
+ void memory_write_hook(address_space &space, offs_t address, UINT64 data, UINT64 mem_mask);
+
+ // hooks into our operations
+ void set_instruction_hook(debug_instruction_hook_func hook);
+ void set_dasm_override(dasm_override_func dasm_override) { m_dasm_override = dasm_override; }
+
+ // disassembly
+ offs_t disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram) const;
+
+ // debugger focus
+ void ignore(bool ignore = true);
+ bool observing() const { return ((m_flags & DEBUG_FLAG_OBSERVING) != 0); }
+
+ // single stepping
+ void single_step(int numsteps = 1);
+ void single_step_over(int numsteps = 1);
+ void single_step_out();
+
+ // execution
+ void go(offs_t targetpc = ~0);
+ void go_vblank();
+ void go_interrupt(int irqline = -1);
+ void go_exception(int exception);
+ void go_milliseconds(UINT64 milliseconds);
+ void go_next_device();
+ void halt_on_next_instruction(const char *fmt, ...);
+
+ // breakpoints
+ breakpoint *breakpoint_first() const { return m_bplist; }
+ int breakpoint_set(offs_t address, const char *condition = NULL, const char *action = NULL);
+ bool breakpoint_clear(int index);
+ void breakpoint_clear_all();
+ bool breakpoint_enable(int index, bool enable = true);
+ void breakpoint_enable_all(bool enable = true);
+
+ // watchpoints
+ watchpoint *watchpoint_first(address_spacenum spacenum) const { return m_wplist[spacenum]; }
+ int watchpoint_set(address_space &space, int type, offs_t address, offs_t length, const char *condition, const char *action);
+ bool watchpoint_clear(int wpnum);
+ void watchpoint_clear_all();
+ bool watchpoint_enable(int index, bool enable = true);
+ void watchpoint_enable_all(bool enable = true);
+
+ // hotspots
+ bool hotspot_tracking_enabled() const { return (m_hotspots != NULL); }
+ void hotspot_track(int numspots, int threshhold);
+
+ // comments
+ void comment_add(offs_t address, const char *comment, rgb_t color);
+ bool comment_remove(offs_t addr);
+ const char *comment_text(offs_t addr) const;
+ UINT32 comment_count() const { return m_comment_list.count(); }
+ UINT32 comment_change_count() const { return m_comment_change; }
+ bool comment_export(xml_data_node &node);
+ bool comment_import(xml_data_node &node);
+ void comment_dump(offs_t addr = ~0);
+ UINT32 compute_opcode_crc32(offs_t address) const;
+
+ // history
+ offs_t history_pc(int index) const;
+
+ // tracing
+ void trace(FILE *file, bool trace_over, const char *action);
+ void trace_printf(const char *fmt, ...);
+ void trace_flush() { if (m_trace != NULL) m_trace->flush(); }
+
+ void reset_transient_flag() { m_flags &= ~DEBUG_FLAG_TRANSIENT; }
+
+ static const int HISTORY_SIZE = 256;
+
+private:
+ // internal helpers
+ void compute_debug_flags();
+ void prepare_for_step_overout(offs_t pc);
+ UINT32 dasm_wrapped(astring &buffer, offs_t pc);
+
+ // breakpoint and watchpoint helpers
+ void breakpoint_update_flags();
+ void breakpoint_check(offs_t pc);
+ void watchpoint_update_flags(address_space &space);
+ void watchpoint_check(address_space &space, int type, offs_t address, UINT64 value_to_write, UINT64 mem_mask);
+ void hotspot_check(address_space &space, offs_t address);
+
+ // symbol get/set callbacks
+ static UINT64 get_current_pc(symbol_table &table, void *ref);
+ static UINT64 get_cycles(symbol_table &table, void *ref);
+ static UINT64 get_logunmap(symbol_table &table, void *ref);
+ static void set_logunmap(symbol_table &table, void *ref, UINT64 value);
+ static UINT64 get_state(symbol_table &table, void *ref);
+ static void set_state(symbol_table &table, void *ref, UINT64 value);
+
+ // basic device information
+ device_t & m_device; // device we are attached to
+ device_execute_interface *m_exec; // execute interface, if present
+ device_memory_interface *m_memory; // memory interface, if present
+ device_state_interface *m_state; // state interface, if present
+ device_disasm_interface *m_disasm; // disasm interface, if present
+
+ // global state
+ UINT32 m_flags; // debugging flags for this CPU
+ symbol_table m_symtable; // symbol table for expression evaluation
+ debug_instruction_hook_func m_instrhook; // per-instruction callback hook
+
+ // disassembly
+ dasm_override_func m_dasm_override; // pointer to provided override function
+ UINT8 m_opwidth; // width of an opcode
+
+ // stepping information
+ offs_t m_stepaddr; // step target address for DEBUG_FLAG_STEPPING_OVER
+ int m_stepsleft; // number of steps left until done
+
+ // execution information
+ offs_t m_stopaddr; // stop address for DEBUG_FLAG_STOP_PC
+ attotime m_stoptime; // stop time for DEBUG_FLAG_STOP_TIME
+ int m_stopirq; // stop IRQ number for DEBUG_FLAG_STOP_INTERRUPT
+ int m_stopexception; // stop exception number for DEBUG_FLAG_STOP_EXCEPTION
+ attotime m_endexectime; // ending time of the current execution
+
+ // history
+ offs_t m_pc_history[HISTORY_SIZE]; // history of recent PCs
+ UINT32 m_pc_history_index; // current history index
+
+ // breakpoints and watchpoints
+ breakpoint * m_bplist; // list of breakpoints
+ watchpoint * m_wplist[ADDRESS_SPACES]; // watchpoint lists for each address space
+
+ // tracing
+ class tracer
+ {
+ public:
+ tracer(device_debug &debug, FILE &file, bool trace_over, const char *action);
+ ~tracer();
+
+ void update(offs_t pc);
+ void vprintf(const char *format, va_list va);
+ void flush();
+
+ private:
+ static const int TRACE_LOOPS = 64;
+
+ device_debug & m_debug; // reference to our owner
+ FILE & m_file; // tracing file for this CPU
+ astring m_action; // action to perform during a trace
+ offs_t m_history[TRACE_LOOPS]; // history of recent PCs
+ int m_loops; // number of instructions in a loop
+ int m_nextdex; // next index
+ bool m_trace_over; // true if we're tracing over
+ offs_t m_trace_over_target; // target for tracing over
+ // (0 = not tracing over,
+ // ~0 = not currently tracing over)
+ };
+ tracer * m_trace; // tracer state
+
+ // hotspots
+ struct hotspot_entry
+ {
+ offs_t m_access; // access address
+ offs_t m_pc; // PC of the access
+ address_space * m_space; // space where the access occurred
+ UINT32 m_count; // number of hits
+ };
+ hotspot_entry * m_hotspots; // hotspot list
+ int m_hotspot_count; // number of hotspots
+ int m_hotspot_threshhold; // threshhold for the number of hits to print
+
+ // comments
+ class dasm_comment
+ {
+ public:
+ dasm_comment(const char *text, offs_t address, rgb_t color, UINT32 crc);
+
+ dasm_comment *next() const { return m_next; }
+
+ dasm_comment * m_next; // next comment in the list
+ offs_t m_address; // address in question
+ rgb_t m_color; // color to use
+ UINT32 m_crc; // CRC of code
+ astring m_text; // text
+ };
+ simple_list<dasm_comment> m_comment_list; // list of comments
+ UINT32 m_comment_change; // change counter for comments
+
+ // internal flag values
+ static const UINT32 DEBUG_FLAG_OBSERVING = 0x00000001; // observing this CPU
+ static const UINT32 DEBUG_FLAG_HISTORY = 0x00000002; // tracking this CPU's history
+ static const UINT32 DEBUG_FLAG_TRACING = 0x00000004; // tracing this CPU
+ static const UINT32 DEBUG_FLAG_TRACING_OVER = 0x00000008; // tracing this CPU with step over behavior
+ static const UINT32 DEBUG_FLAG_HOOKED = 0x00000010; // per-instruction callback hook
+ static const UINT32 DEBUG_FLAG_STEPPING = 0x00000020; // CPU is single stepping
+ static const UINT32 DEBUG_FLAG_STEPPING_OVER = 0x00000040; // CPU is stepping over a function
+ static const UINT32 DEBUG_FLAG_STEPPING_OUT = 0x00000080; // CPU is stepping out of a function
+ static const UINT32 DEBUG_FLAG_STOP_PC = 0x00000100; // there is a pending stop at cpu->breakpc
+ static const UINT32 DEBUG_FLAG_STOP_INTERRUPT = 0x00000400; // there is a pending stop on the next interrupt
+ static const UINT32 DEBUG_FLAG_STOP_EXCEPTION = 0x00000800; // there is a pending stop on the next exception
+ static const UINT32 DEBUG_FLAG_STOP_VBLANK = 0x00001000; // there is a pending stop on the next VBLANK
+ static const UINT32 DEBUG_FLAG_STOP_TIME = 0x00002000; // there is a pending stop at cpu->stoptime
+ static const UINT32 DEBUG_FLAG_LIVE_BP = 0x00010000; // there are live breakpoints for this CPU
+
+ static const UINT32 DEBUG_FLAG_STEPPING_ANY = DEBUG_FLAG_STEPPING | DEBUG_FLAG_STEPPING_OVER | DEBUG_FLAG_STEPPING_OUT;
+ static const UINT32 DEBUG_FLAG_TRACING_ANY = DEBUG_FLAG_TRACING | DEBUG_FLAG_TRACING_OVER;
+ static const UINT32 DEBUG_FLAG_TRANSIENT = DEBUG_FLAG_STEPPING_ANY | DEBUG_FLAG_STOP_PC |
+ DEBUG_FLAG_STOP_INTERRUPT | DEBUG_FLAG_STOP_EXCEPTION | DEBUG_FLAG_STOP_VBLANK | DEBUG_FLAG_STOP_TIME;
+};
+
+
+
+//**************************************************************************
+// FUNCTION PROTOTYPES
+//**************************************************************************
+
+/* ----- initialization and cleanup ----- */
+
+/* initialize the CPU tracking for the debugger */
+void debug_cpu_init(running_machine &machine);
+void debug_cpu_configure_memory(running_machine &machine, symbol_table &table);
+
+/* flushes all traces; this is useful if a trace is going on when we fatalerror */
+void debug_cpu_flush_traces(running_machine &machine);
+
+
+
+/* ----- debugging status & information ----- */
+
+/* return the visible CPU device (the one that commands should apply to) */
+device_t *debug_cpu_get_visible_cpu(running_machine &machine);
+
+/* TRUE if the debugger is currently stopped within an instruction hook callback */
+int debug_cpu_within_instruction_hook(running_machine &machine);
+
+/* return TRUE if the current execution state is stopped */
+int debug_cpu_is_stopped(running_machine &machine);
+
+
+
+/* ----- symbol table interfaces ----- */
+
+/* return the global symbol table */
+symbol_table *debug_cpu_get_global_symtable(running_machine &machine);
+
+/* return the locally-visible symbol table */
+symbol_table *debug_cpu_get_visible_symtable(running_machine &machine);
+
+
+
+/* ----- misc debugger functions ----- */
+
+/* specifies a debug command script to execute */
+void debug_cpu_source_script(running_machine &machine, const char *file);
+
+
+
+/* ----- debugger comment helpers ----- */
+
+// save all comments for a given machine
+bool debug_comment_save(running_machine &machine);
+
+// load all comments for a given machine
+bool debug_comment_load(running_machine &machine);
+
+
+
+/* ----- debugger memory accessors ----- */
+
+/* return the physical address corresponding to the given logical address */
+int debug_cpu_translate(address_space *space, int intention, offs_t *address);
+
+/* return a byte from the the specified memory space */
+UINT8 debug_read_byte(address_space *space, offs_t address, int apply_translation);
+
+/* return a word from the the specified memory space */
+UINT16 debug_read_word(address_space *space, offs_t address, int apply_translation);
+
+/* return a dword from the the specified memory space */
+UINT32 debug_read_dword(address_space *space, offs_t address, int apply_translation);
+
+/* return a qword from the the specified memory space */
+UINT64 debug_read_qword(address_space *space, offs_t address, int apply_translation);
+
+/* return 1,2,4 or 8 bytes from the specified memory space */
+UINT64 debug_read_memory(address_space *space, offs_t address, int size, int apply_translation);
+
+/* write a byte to the specified memory space */
+void debug_write_byte(address_space *space, offs_t address, UINT8 data, int apply_translation);
+
+/* write a word to the specified memory space */
+void debug_write_word(address_space *space, offs_t address, UINT16 data, int apply_translation);
+
+/* write a dword to the specified memory space */
+void debug_write_dword(address_space *space, offs_t address, UINT32 data, int apply_translation);
+
+/* write a qword to the specified memory space */
+void debug_write_qword(address_space *space, offs_t address, UINT64 data, int apply_translation);
+
+/* write 1,2,4 or 8 bytes to the specified memory space */
+void debug_write_memory(address_space *space, offs_t address, UINT64 data, int size, int apply_translation);
+
+/* read 1,2,4 or 8 bytes at the given offset from opcode space */
+UINT64 debug_read_opcode(address_space *space, offs_t offset, int size, int arg);
+
+
+#endif
diff --git a/trunk/src/emu/debug/debughlp.c b/trunk/src/emu/debug/debughlp.c
new file mode 100644
index 00000000000..2ca5c4c2b3a
--- /dev/null
+++ b/trunk/src/emu/debug/debughlp.c
@@ -0,0 +1,1323 @@
+/*********************************************************************
+
+ debughlp.c
+
+ Debugger help engine.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "debughlp.h"
+#include <ctype.h>
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define CONSOLE_HISTORY (10000)
+#define CONSOLE_LINE_CHARS (100)
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _help_item help_item;
+struct _help_item
+{
+ const char * tag;
+ const char * help;
+};
+
+
+
+/***************************************************************************
+ LOCAL VARIABLES
+***************************************************************************/
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+
+
+/***************************************************************************
+ TABLE OF HELP
+***************************************************************************/
+
+static const help_item static_help_list[] =
+{
+ {
+ "",
+ "\n"
+ "MAME Debugger Help\n"
+ " help [<topic>] -- get help on a particular topic\n"
+ "\n"
+ "Topics:\n"
+ " General\n"
+ " Memory\n"
+ " Execution\n"
+ " Breakpoints\n"
+ " Watchpoints\n"
+ " Expressions\n"
+ " Comments\n"
+ " Cheats\n"
+ " Image\n"
+ },
+ {
+ "general",
+ "\n"
+ "General Debugger Help\n"
+ "Type help <command> for further details on each command\n"
+ "\n"
+ " help [<topic>] -- get help on a particular topic\n"
+ " do <expression> -- evaluates the given expression\n"
+ " symlist [<cpu>] -- lists registered symbols\n"
+ " softreset -- executes a soft reset\n"
+ " hardreset -- executes a hard reset\n"
+ " print <item>[,...] -- prints one or more <item>s to the console\n"
+ " printf <format>[,<item>[,...]] -- prints one or more <item>s to the console using <format>\n"
+ " logerror <format>[,<item>[,...]] -- outputs one or more <item>s to the error.log\n"
+ " tracelog <format>[,<item>[,...]] -- outputs one or more <item>s to the trace file using <format>\n"
+ " snap [<filename>] -- save a screen snapshot\n"
+ " source <filename> -- reads commands from <filename> and executes them one by one\n"
+ " quit -- exits MAME and the debugger\n"
+ },
+ {
+ "memory",
+ "\n"
+ "Memory Commands\n"
+ "Type help <command> for further details on each command\n"
+ "\n"
+ " dasm <filename>,<address>,<length>[,<opcodes>[,<cpu>]] -- disassemble to the given file\n"
+ " f[ind] <address>,<length>[,<data>[,...]] -- search program memory for data\n"
+ " f[ind]d <address>,<length>[,<data>[,...]] -- search data memory for data\n"
+ " f[ind]i <address>,<length>[,<data>[,...]] -- search I/O memory for data\n"
+ " dump <filename>,<address>,<length>[,<size>[,<ascii>[,<cpu>]]] -- dump program memory as text\n"
+ " dumpd <filename>,<address>,<length>[,<size>[,<ascii>[,<cpu>]]] -- dump data memory as text\n"
+ " dumpi <filename>,<address>,<length>[,<size>[,<ascii>[,<cpu>]]] -- dump I/O memory as text\n"
+ " save <filename>,<address>,<length>[,<cpu>] -- save binary program memory to the given file\n"
+ " saved <filename>,<address>,<length>[,<cpu>] -- save binary data memory to the given file\n"
+ " savei <filename>,<address>,<length>[,<cpu>] -- save binary I/O memory to the given file\n"
+ " load <filename>,<address>,<length>[,<cpu>] -- load binary program memory from the given file\n"
+ " loadd <filename>,<address>,<length>[,<cpu>] -- load binary data memory from the given file\n"
+ " loadi <filename>,<address>,<length>[,<cpu>] -- load binary I/O memory from the given file\n"
+ " map <address> -- map logical program address to physical address and bank\n"
+ " mapd <address> -- map logical data address to physical address and bank\n"
+ " mapi <address> -- map logical I/O address to physical address and bank\n"
+ " memdump [<filename>] -- dump the current memory map to <filename>\n"
+ },
+ {
+ "execution",
+ "\n"
+ "Execution Commands\n"
+ "Type help <command> for further details on each command\n"
+ "\n"
+ " s[tep] [<count>=1] -- single steps for <count> instructions (F11)\n"
+ " o[ver] [<count>=1] -- single steps over <count> instructions (F10)\n"
+ " out -- single steps until the current subroutine/exception handler is exited (Shift-F11)\n"
+ " g[o] [<address>] -- resumes execution, sets temp breakpoint at <address> (F5)\n"
+ " gi[nt] [<irqline>] -- resumes execution, setting temp breakpoint if <irqline> is taken (F7)\n"
+ " gt[ime] <milliseconds> -- resumes execution until the given delay has elapsed\n"
+ " gv[blank] -- resumes execution, setting temp breakpoint on the next VBLANK (F8)\n"
+ " n[ext] -- executes until the next CPU switch (F6)\n"
+ " focus <cpu> -- focuses debugger only on <cpu>\n"
+ " ignore [<cpu>[,<cpu>[,...]]] -- stops debugging on <cpu>\n"
+ " observe [<cpu>[,<cpu>[,...]]] -- resumes debugging on <cpu>\n"
+ " trace {<filename>|OFF}[,<cpu>[,<action>]] -- trace the given CPU to a file (defaults to active CPU)\n"
+ " traceover {<filename>|OFF}[,<cpu>[,<action>]] -- trace the given CPU to a file, but skip subroutines (defaults to active CPU)\n"
+ " traceflush -- flushes all open trace files\n"
+ },
+ {
+ "breakpoints",
+ "\n"
+ "Breakpoint Commands\n"
+ "Type help <command> for further details on each command\n"
+ "\n"
+ " bp[set] <address>[,<condition>[,<action>]] -- sets breakpoint at <address>\n"
+ " bpclear [<bpnum>] -- clears a given breakpoint or all if no <bpnum> specified\n"
+ " bpdisable [<bpnum>] -- disables a given breakpoint or all if no <bpnum> specified\n"
+ " bpenable [<bpnum>] -- enables a given breakpoint or all if no <bpnum> specified\n"
+ " bplist -- lists all the breakpoints\n"
+ },
+ {
+ "watchpoints",
+ "\n"
+ "Watchpoint Commands\n"
+ "Type help <command> for further details on each command\n"
+ "\n"
+ " wp[set] <address>,<length>,<type>[,<condition>[,<action>]] -- sets program space watchpoint\n"
+ " wpd[set] <address>,<length>,<type>[,<condition>[,<action>]] -- sets data space watchpoint\n"
+ " wpi[set] <address>,<length>,<type>[,<condition>[,<action>]] -- sets I/O space watchpoint\n"
+ " wpclear [<wpnum>] -- clears a given watchpoint or all if no <wpnum> specified\n"
+ " wpdisable [<wpnum>] -- disables a given watchpoint or all if no <wpnum> specified\n"
+ " wpenable [<wpnum>] -- enables a given watchpoint or all if no <wpnum> specified\n"
+ " wplist -- lists all the watchpoints\n"
+ " hotspot [<cpu>,[<depth>[,<hits>]]] -- attempt to find hotspots\n"
+ },
+ {
+ "expressions",
+ "\n"
+ "Expressions can be used anywhere a numeric parameter is expected. The syntax for expressions is "
+ "very close to standard C-style syntax with full operator ordering and parentheses. There are a "
+ "few operators missing (notably the trinary ? : operator), and a few new ones (memory accessors). "
+ "The table below lists all the operators in their order, highest precedence operators first.\n"
+ "\n"
+ " ( ) : standard parentheses\n"
+ " ++ -- : postfix increment/decrement\n"
+ " ++ -- ~ ! - + b@ w@ d@ q@ : prefix inc/dec, binary NOT, logical NOT, unary +/-, memory access\n"
+ " * / % : multiply, divide, modulus\n"
+ " + - : add, subtract\n"
+ " << >> : shift left/right\n"
+ " < <= > >= : less than, less than or equal, greater than, greater than or equal\n"
+ " == != : equal, not equal\n"
+ " & : binary AND\n"
+ " ^ : binary XOR\n"
+ " | : binary OR\n"
+ " && : logical AND\n"
+ " || : logical OR\n"
+ " = *= /= %= += -= <<= >>= &= |= ^= : assignment\n"
+ " , : separate terms, function parameters\n"
+ "\n"
+ "These are the differences from C behaviors. First, All math is performed on full 64-bit unsigned "
+ "values, so things like a < 0 won't work as expected. Second, the logical operators && and || do "
+ "not have short-circuit properties -- both halves are always evaluated. Finally, the new memory "
+ "operators work like this: b@<addr> refers to the byte read from <addr>. Similarly, w@ refers to "
+ "a word in memory, d@ refers to a dword in memory, and q@ refers to a qword in memory. The memory "
+ "operators can be used as both lvalues and rvalues, so you can write b@100 = ff to store a byte "
+ "in memory. By default these operators read from the program memory space, but you can override "
+ "that by prefixing them with a 'd' or an 'i'. So dw@300 refers to data memory word at address "
+ "300 and id@400 refers to an I/O memory dword at address 400.\n"
+ },
+ {
+ "comments",
+ "\n"
+ "Code annotation commands\n"
+ "Type help <command> for further details on each command\n"
+ "\n"
+ " comadd[//] <address>,<comment> -- adds a comment to the disassembled code at given address\n"
+ " comdelete <address> -- removes a comment from the given address\n"
+ " comsave -- save the current comments to a file\n"
+ "\n"
+ },
+ {
+ "cheats",
+ "\n"
+ "Cheat Commands\n"
+ "Type help <command> for further details on each command\n"
+ "\n"
+ " cheatinit [<address>,<length>[,<cpu>]] -- initialize the cheat search to the selected memory area\n"
+ " cheatrange <address>,<length> -- add to the cheat search the selected memory area\n"
+ " cheatnext <condition>[,<comparisonvalue>] -- continue cheat search comparing with the the last value\n"
+ " cheatnextf <condition>[,<comparisonvalue>] -- continue cheat search comparing with the the first value\n"
+ " cheatlist [<filename>] -- show the list of cheat search matches or save them to <filename>\n"
+ " cheatundo -- undo the last cheat search (state only)\n"
+ },
+ {
+ "image",
+ "\n"
+ "Image Commands\n"
+ "Type help <command> for further details on each command\n"
+ "\n"
+ " images -- lists all image devices and mounted files\n"
+ " mount <device>,<filename> -- mounts file to named device\n"
+ " unmount <device> -- unmounts file from named device\n"
+ },
+ {
+ "do",
+ "\n"
+ " do <expression>\n"
+ "\n"
+ "The do command simply evaluates the given <expression>. This is typically used to set or modify "
+ "variables.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "do pc = 0\n"
+ " Sets the register 'pc' to 0.\n"
+ },
+ {
+ "symlist",
+ "\n"
+ " symlist [<cpu>]\n"
+ "\n"
+ "Lists registered symbols. If <cpu> is not specified, then symbols in the global symbol table are "
+ "displayed; otherwise, the symbols for <cpu>'s specific CPU are displayed. Symbols are listed "
+ "alphabetically. Read-only symbols are flagged with an asterisk.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "symlist\n"
+ " Displays the global symbol table.\n"
+ "\n"
+ "symlist 2\n"
+ " Displays the symbols specific to CPU #2.\n"
+ },
+ {
+ "softreset",
+ "\n"
+ " softreset\n"
+ "\n"
+ "Executes a soft reset.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "softreset\n"
+ " Executes a soft reset.\n"
+ },
+ {
+ "hardreset",
+ "\n"
+ " hardreset\n"
+ "\n"
+ "Executes a hard reset.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "hardreset\n"
+ " Executes a hard reset.\n"
+ },
+ {
+ "print",
+ "\n"
+ " print <item>[,...]\n"
+ "\n"
+ "The print command prints the results of one or more expressions to the debugger console as hexadecimal "
+ "values.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "print pc\n"
+ " Prints the value of 'pc' to the console as a hex number.\n"
+ "\n"
+ "print a,b,a+b\n"
+ " Prints a, b, and the value of a+b to the console as hex numbers.\n"
+ },
+ {
+ "printf",
+ "\n"
+ " printf <format>[,<item>[,...]]\n"
+ "\n"
+ "The printf command performs a C-style printf to the debugger console. Only a very limited set of "
+ "formatting options are available:\n"
+ "\n"
+ " %[0][<n>]d -- prints <item> as a decimal value with optional digit count and zero-fill\n"
+ " %[0][<n>]x -- prints <item> as a hexadecimal value with optional digit count and zero-fill\n"
+ "\n"
+ "All remaining formatting options are ignored. Use %% together to output a % character. Multiple "
+ "lines can be printed by embedding a \\n in the text.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "printf \"PC=%04X\",pc\n"
+ " Prints PC=<pcval> where <pcval> is displayed in hexadecimal with 4 digits with zero-fill.\n"
+ "\n"
+ "printf \"A=%d, B=%d\\nC=%d\",a,b,a+b\n"
+ " Prints A=<aval>, B=<bval> on one line, and C=<a+bval> on a second line.\n"
+ },
+ {
+ "logerror",
+ "\n"
+ " logerror <format>[,<item>[,...]]\n"
+ "\n"
+ "The logerror command performs a C-style printf to the error log. Only a very limited set of "
+ "formatting options are available:\n"
+ "\n"
+ " %[0][<n>]d -- logs <item> as a decimal value with optional digit count and zero-fill\n"
+ " %[0][<n>]x -- logs <item> as a hexadecimal value with optional digit count and zero-fill\n"
+ "\n"
+ "All remaining formatting options are ignored. Use %% together to output a % character. Multiple "
+ "lines can be printed by embedding a \\n in the text.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "logerror \"PC=%04X\",pc\n"
+ " Logs PC=<pcval> where <pcval> is displayed in hexadecimal with 4 digits with zero-fill.\n"
+ "\n"
+ "logerror \"A=%d, B=%d\\nC=%d\",a,b,a+b\n"
+ " Logs A=<aval>, B=<bval> on one line, and C=<a+bval> on a second line.\n"
+ },
+ {
+ "tracelog",
+ "\n"
+ " tracelog <format>[,<item>[,...]]\n"
+ "\n"
+ "The tracelog command performs a C-style printf and routes the output to the currently open trace "
+ "file (see the 'trace' command for details). If no file is currently open, tracelog does nothing. "
+ "Only a very limited set of formatting options are available. See the 'printf' help for details.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "tracelog \"PC=%04X\",pc\n"
+ " Outputs PC=<pcval> where <pcval> is displayed in hexadecimal with 4 digits with zero-fill.\n"
+ "\n"
+ "printf \"A=%d, B=%d\\nC=%d\",a,b,a+b\n"
+ " Outputs A=<aval>, B=<bval> on one line, and C=<a+bval> on a second line.\n"
+ },
+ {
+ "snap",
+ "\n"
+ " snap [[<filename>], <scrnum>]\n"
+ "\n"
+ "The snap command takes a snapshot of the current video display and saves it to the configured "
+ "snapshot directory. If <filename> is specified explicitly, a single screenshot for <scrnum> is "
+ "saved under the requested filename. If <filename> is omitted, all screens are saved using the "
+ "same default rules as the \"save snapshot\" key in MAME proper.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "snap\n"
+ " Takes a snapshot of the current video screen and saves to the next non-conflicting filename "
+ " in the configured snapshot directory.\n"
+ "\n"
+ "snap shinobi\n"
+ " Takes a snapshot of the current video screen and saves it as 'shinobi.png' in the configured "
+ " snapshot directory.\n"
+ },
+ {
+ "source",
+ "\n"
+ " source <filename>\n"
+ "\n"
+ "The source command reads in a set of debugger commands from a file and executes them one by "
+ "one, similar to a batch file.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "source break_and_trace.cmd\n"
+ " Reads in debugger commands from break_and_trace.cmd and executes them.\n"
+ },
+ {
+ "quit",
+ "\n"
+ " quit\n"
+ "\n"
+ "The quit command exits MAME immediately.\n"
+ },
+ {
+ "dasm",
+ "\n"
+ " dasm <filename>,<address>,<length>[,<opcodes>[,<cpu>]]\n"
+ "\n"
+ "The dasm command disassembles program memory to the file specified in the <filename> parameter. "
+ "<address> indicates the address of the start of disassembly, and <length> indicates how much "
+ "memory to disassemble. The range <address> through <address>+<length>-1 inclusive will be "
+ "output to the file. By default, the raw opcode data is output with each line. The optional "
+ "<opcodes> parameter can be used to enable (1) or disable(0) this feature. Finally, you can "
+ "disassemble code from another CPU by specifying the <cpu> parameter.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "dasm venture.asm,0,10000\n"
+ " Disassembles addresses 0-ffff in the current CPU, including raw opcode data, to the "
+ "file 'venture.asm'.\n"
+ "\n"
+ "dasm harddriv.asm,3000,1000,0,2\n"
+ " Disassembles addresses 3000-3fff from CPU #2, with no raw opcode data, to the file "
+ "'harddriv.asm'.\n"
+ },
+ {
+ "find",
+ "\n"
+ " f[ind][{d|i}] <address>,<length>[,<data>[,...]]\n"
+ "\n"
+ "The find/findd/findi commands search through memory for the specified sequence of data. "
+ "'find' will search program space memory, while 'findd' will search data space memory "
+ "and 'findi' will search I/O space memory. <address> indicates the address to begin searching, "
+ "and <length> indicates how much memory to search. <data> can either be a quoted string "
+ "or a numeric value or expression or the wildcard character '?'. Strings by default imply a "
+ "byte-sized search; non-string data is searched by default in the native word size of the CPU. "
+ "To override the search size for non-strings, you can prefix the value with b. to force byte- "
+ "sized search, w. for word-sized search, d. for dword-sized, and q. for qword-sized. Overrides "
+ "are remembered, so if you want to search for a series of words, you need only to prefix the "
+ "first value with a w. Note also that you can intermix sizes in order to perform more complex "
+ "searches. The entire range <address> through <address>+<length>-1 inclusive will be searched "
+ "for the sequence, and all occurrences will be displayed.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "find 0,10000,\"HIGH SCORE\",0\n"
+ " Searches the address range 0-ffff in the current CPU for the string \"HIGH SCORE\" followed "
+ "by a 0 byte.\n"
+ "\n"
+ "findd 3000,1000,w.abcd,4567\n"
+ " Searches the data memory address range 3000-3fff for the word-sized value abcd followed by "
+ "the word-sized value 4567.\n"
+ "\n"
+ "find 0,8000,\"AAR\",d.0,\"BEN\",w.0\n"
+ " Searches the address range 0000-7fff for the string \"AAR\" followed by a dword-sized 0 "
+ "followed by the string \"BEN\", followed by a word-sized 0.\n"
+ },
+ {
+ "dump",
+ "\n"
+ " dump[{d|i}] <filename>,<address>,<length>[,<size>[,<ascii>[,<cpu>]]]\n"
+ "\n"
+ "The dump/dumpd/dumpi commands dump memory to the text file specified in the <filename> "
+ "parameter. 'dump' will dump program space memory, while 'dumpd' will dump data space memory "
+ "and 'dumpi' will dump I/O space memory. <address> indicates the address of the start of dumping, "
+ "and <length> indicates how much memory to dump. The range <address> through <address>+<length>-1 "
+ "inclusive will be output to the file. By default, the data will be output in byte format, unless "
+ "the underlying address space is word/dword/qword-only. You can override this by specifying the "
+ "<size> parameter, which can be used to group the data in 1, 2, 4 or 8-byte chunks. The optional "
+ "<ascii> parameter can be used to enable (1) or disable (0) the output of ASCII characters to the "
+ "right of each line; by default, this is enabled. Finally, you can dump memory from another CPU "
+ "by specifying the <cpu> parameter.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "dump venture.dmp,0,10000\n"
+ " Dumps addresses 0-ffff in the current CPU in 1-byte chunks, including ASCII data, to "
+ "the file 'venture.dmp'.\n"
+ "\n"
+ "dumpd harddriv.dmp,3000,1000,4,0,3\n"
+ " Dumps data memory addresses 3000-3fff from CPU #3 in 4-byte chunks, with no ASCII data, "
+ "to the file 'harddriv.dmp'.\n"
+ },
+ {
+ "save",
+ "\n"
+ " save[{d|i}] <filename>,<address>,<length>[,<cpu>]\n"
+ "\n"
+ "The save/saved/savei commands save raw memory to the binary file specified in the <filename> "
+ "parameter. 'save' will save program space memory, while 'saved' will save data space memory "
+ "and 'savei' will save I/O space memory. <address> indicates the address of the start of saving, "
+ "and <length> indicates how much memory to save. The range <address> through <address>+<length>-1 "
+ "inclusive will be output to the file. You can also save memory from another CPU by specifying the "
+ "<cpu> parameter.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "save venture.bin,0,10000\n"
+ " Saves addresses 0-ffff in the current CPU to the binary file 'venture.bin'.\n"
+ "\n"
+ "saved harddriv.bin,3000,1000,3\n"
+ " Saves data memory addresses 3000-3fff from CPU #3 to the binary file 'harddriv.bin'.\n"
+ },
+ {
+ "load",
+ "\n"
+ " load[{d|i}] <filename>,<address>,<length>[,<cpu>]\n"
+ "\n"
+ "The load/loadd/loadi commands load raw memory from the binary file specified in the <filename> "
+ "parameter. 'load' will load program space memory, while 'loadd' will load data space memory "
+ "and 'loadi' will load I/O space memory. <address> indicates the address of the start of saving, "
+ "and <length> indicates how much memory to load. The range <address> through <address>+<length>-1 "
+ "inclusive will be read in from the file. If you specify <length> = 0 or a length greater than the "
+ "total length of the file it will load the entire contents of the file and no more. You can also load "
+ "memory from another CPU by specifying the <cpu> parameter.\n"
+ "NOTE: This will only actually write memory that is possible to overwrite in the Memory Window\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "load venture.bin,0,10000\n"
+ " Loads addresses 0-ffff in the current CPU from the binary file 'venture.bin'.\n"
+ "\n"
+ "loadd harddriv.bin,3000,1000,3\n"
+ " Loads data memory addresses 3000-3fff from CPU #3 from the binary file 'harddriv.bin'.\n"
+ },
+ {
+ "step",
+ "\n"
+ " s[tep] [<count>=1]\n"
+ "\n"
+ "The step command single steps one or more instructions in the currently executing CPU. By "
+ "default, step executes one instruction each time it is issued. You can also tell step to step "
+ "multiple instructions by including the optional <count> parameter.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "s\n"
+ " Steps forward one instruction on the current CPU.\n"
+ "\n"
+ "step 4\n"
+ " Steps forward four instructions on the current CPU.\n"
+ },
+ {
+ "over",
+ "\n"
+ " o[ver] [<count>=1]\n"
+ "\n"
+ "The over command single steps \"over\" one or more instructions in the currently executing CPU, "
+ "stepping over subroutine calls and exception handler traps and counting them as a single "
+ "instruction. Note that when stepping over a subroutine call, code may execute on other CPUs "
+ "before the subroutine call completes. By default, over executes one instruction each time it is "
+ "issued. You can also tell step to step multiple instructions by including the optional <count> "
+ "parameter.\n"
+ "\n"
+ "Note that the step over functionality may not be implemented on all CPU types. If it is not "
+ "implemented, then 'over' will behave exactly like 'step'.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "o\n"
+ " Steps forward over one instruction on the current CPU.\n"
+ "\n"
+ "over 4\n"
+ " Steps forward over four instructions on the current CPU.\n"
+ },
+ {
+ "out",
+ "\n"
+ " out\n"
+ "\n"
+ "The out command single steps until it encounters a return from subroutine or return from "
+ "exception instruction. Note that because it detects return from exception conditions, if you "
+ "attempt to step out of a subroutine and an interrupt/exception occurs before you hit the end, "
+ "then you may stop prematurely at the end of the exception handler.\n"
+ "\n"
+ "Note that the step out functionality may not be implemented on all CPU types. If it is not "
+ "implemented, then 'out' will behave exactly like 'step'.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "out\n"
+ " Steps until the current subroutine or exception handler returns.\n"
+ },
+ {
+ "go",
+ "\n"
+ " g[o] [<address>]\n"
+ "\n"
+ "The go command resumes execution of the current code. Control will not be returned to the "
+ "debugger until a breakpoint or watchpoint is hit, or until you manually break in using the "
+ "assigned key. The go command takes an optional <address> parameter which is a temporary "
+ "unconditional breakpoint that is set before executing, and automatically removed when hit. "
+ "\n"
+ "Examples:\n"
+ "\n"
+ "g\n"
+ " Resume execution until the next break/watchpoint or until a manual break.\n"
+ "\n"
+ "g 1234\n"
+ " Resume execution, stopping at address 1234 unless something else stops us first.\n"
+ },
+ {
+ "gvblank",
+ "\n"
+ " gv[blank]\n"
+ "\n"
+ "The gvblank command resumes execution of the current code. Control will not be returned to "
+ "the debugger until a breakpoint or watchpoint is hit, or until the next VBLANK occurs in the "
+ "emulator.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "gv\n"
+ " Resume execution until the next break/watchpoint or until the next VBLANK.\n"
+ },
+ {
+ "gint",
+ "\n"
+ " gi[nt] [<irqline>]\n"
+ "\n"
+ "The gint command resumes execution of the current code. Control will not be returned to the "
+ "debugger until a breakpoint or watchpoint is hit, or until an IRQ is asserted and acknowledged "
+ "on the current CPU. You can specify <irqline> if you wish to stop execution only on a particular "
+ "IRQ line being asserted and acknowledged. If <irqline> is omitted, then any IRQ line will stop "
+ "execution.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "gi\n"
+ " Resume execution until the next break/watchpoint or until any IRQ is asserted and acknowledged "
+ "on the current CPU.\n"
+ "\n"
+ "gint 4\n"
+ " Resume execution until the next break/watchpoint or until IRQ line 4 is asserted and "
+ "acknowledged on the current CPU.\n"
+ },
+ {
+ "gtime",
+ "\n"
+ " gt[ime] <milliseconds>\n"
+ "\n"
+ "The gtime command resumes execution of the current code. Control will not be returned to the "
+ "debugger until a specified delay has elapsed. The delay is in milliseconds.\n"
+ "\n"
+ "Example:\n"
+ "\n"
+ "gtime #10000\n"
+ " Resume execution for ten seconds\n"
+ },
+ {
+ "next",
+ "\n"
+ " n[ext]\n"
+ "\n"
+ "The next command resumes execution and continues executing until the next time a different "
+ "CPU is scheduled. Note that if you have used 'ignore' to ignore certain CPUs, you will not "
+ "stop until a non-'ignore'd CPU is scheduled.\n"
+ },
+ {
+ "focus",
+ "\n"
+ " focus <cpu>\n"
+ "\n"
+ "Sets the debugger focus exclusively to the given <cpu>. This is equivalent to specifying "
+ "'ignore' on all other CPUs.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "focus 1\n"
+ " Focus exclusively CPU #1 while ignoring all other CPUs when using the debugger.\n"
+ },
+ {
+ "ignore",
+ "\n"
+ " ignore [<cpu>[,<cpu>[,...]]]\n"
+ "\n"
+ "Ignores the specified <cpu> in the debugger. This means that you won't ever see execution "
+ "on that CPU, nor will you be able to set breakpoints on that CPU. To undo this change use "
+ "the 'observe' command. You can specify multiple <cpu>s in a single command. Note also that "
+ "you are not permitted to ignore all CPUs; at least one must be active at all times.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "ignore 1\n"
+ " Ignore CPU #1 when using the debugger.\n"
+ "\n"
+ "ignore 2,3,4\n"
+ " Ignore CPU #2, #3 and #4 when using the debugger.\n"
+ "\n"
+ "ignore\n"
+ " List the CPUs that are currently ignored.\n"
+ },
+ {
+ "observe",
+ "\n"
+ " observe [<cpu>[,<cpu>[,...]]]\n"
+ "\n"
+ "Re-enables interaction with the specified <cpu> in the debugger. This command undoes the "
+ "effects of the 'ignore' command. You can specify multiple <cpu>s in a single command.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "observe 1\n"
+ " Stop ignoring CPU #1 when using the debugger.\n"
+ "\n"
+ "observe 2,3,4\n"
+ " Stop ignoring CPU #2, #3 and #4 when using the debugger.\n"
+ "\n"
+ "observe\n"
+ " List the CPUs that are currently observed.\n"
+ },
+ {
+ "trace",
+ "\n"
+ " trace {<filename>|OFF}[,<cpu>[,<action>]]\n"
+ "\n"
+ "Starts or stops tracing of the execution of the specified <cpu>. If <cpu> is omitted, "
+ "the currently active CPU is specified. When enabling tracing, specify the filename in the "
+ "<filename> parameter. To disable tracing, substitute the keyword 'off' for <filename>. If you "
+ "wish to log additional information on each trace, you can append an <action> parameter which "
+ "is a command that is executed before each trace is logged. Generally, this is used to include "
+ "a 'tracelog' command. Note that you may need to embed the action within braces { } in order "
+ "to prevent commas and semicolons from being interpreted as applying to the trace command "
+ "itself.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "trace dribling.tr,0\n"
+ " Begin tracing the execution of CPU #0, logging output to dribling.tr.\n"
+ "\n"
+ "trace joust.tr\n"
+ " Begin tracing the currently active CPU, logging output to joust.tr.\n"
+ "\n"
+ "trace >>pigskin.tr\n"
+ " Begin tracing the currently active CPU, appending log output to pigskin.tr.\n"
+ "\n"
+ "trace off,0\n"
+ " Turn off tracing on CPU #0.\n"
+ "\n"
+ "trace asteroid.tr,0,{tracelog \"A=%02X \",a}\n"
+ " Begin tracing the execution of CPU #0, logging output to asteroid.tr. Before each line, "
+ "output A=<aval> to the tracelog.\n"
+ },
+ {
+ "traceover",
+ "\n"
+ " traceover {<filename>|OFF}[,<cpu>[,<action>]]\n"
+ "\n"
+ "Starts or stops tracing of the execution of the specified <cpu>. When tracing reaches "
+ "a subroutine or call, tracing will skip over the subroutine. The same algorithm is used as is "
+ "used in the step over command. This means that traceover will not work properly when calls "
+ "are recusive or the return address is not immediately following the call instruction. If "
+ "<cpu> is omitted, the currently active CPU is specified. When enabling tracing, specify the "
+ "filename in the <filename> parameter. To disable tracing, substitute the keyword 'off' for "
+ "<filename>. If you wish to log additional information on each trace, you can append an <action> "
+ "parameter which is a command that is executed before each trace is logged. Generally, this is "
+ "used to include a 'tracelog' command. Note that you may need to embed the action within braces "
+ "{ } in order to prevent commas and semicolons from being interpreted as applying to the trace "
+ "command itself.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "traceover dribling.tr,0\n"
+ " Begin tracing the execution of CPU #0, logging output to dribling.tr.\n"
+ "\n"
+ "traceover joust.tr\n"
+ " Begin tracing the currently active CPU, logging output to joust.tr.\n"
+ "\n"
+ "traceover off,0\n"
+ " Turn off tracing on CPU #0.\n"
+ "\n"
+ "traceover asteroid.tr,0,{tracelog \"A=%02X \",a}\n"
+ " Begin tracing the execution of CPU #0, logging output to asteroid.tr. Before each line, "
+ "output A=<aval> to the tracelog.\n"
+ },
+ {
+ "traceflush",
+ "\n"
+ " traceflush\n"
+ "\n"
+ "Flushes all open trace files.\n"
+ },
+ {
+ "bpset",
+ "\n"
+ " bp[set] <address>[,<condition>[,<action>]]\n"
+ "\n"
+ "Sets a new execution breakpoint at the specified <address>. The optional <condition> "
+ "parameter lets you specify an expression that will be evaluated each time the breakpoint is "
+ "hit. If the result of the expression is true (non-zero), the breakpoint will actually halt "
+ "execution; otherwise, execution will continue with no notification. The optional <action> "
+ "parameter provides a command that is executed whenever the breakpoint is hit and the "
+ "<condition> is true. Note that you may need to embed the action within braces { } in order "
+ "to prevent commas and semicolons from being interpreted as applying to the bpset command "
+ "itself. Each breakpoint that is set is assigned an index which can be used in other "
+ "breakpoint commands to reference this breakpoint.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "bp 1234\n"
+ " Set a breakpoint that will halt execution whenever the PC is equal to 1234.\n"
+ "\n"
+ "bp 23456,a0 == 0 && a1 == 0\n"
+ " Set a breakpoint that will halt execution whenever the PC is equal to 23456 AND the "
+ "expression (a0 == 0 && a1 == 0) is true.\n"
+ "\n"
+ "bp 3456,1,{printf \"A0=%08X\\n\",a0; g}\n"
+ " Set a breakpoint that will halt execution whenever the PC is equal to 3456. When "
+ "this happens, print A0=<a0val> and continue executing.\n"
+ "\n"
+ "bp 45678,a0==100,{a0 = ff; g}\n"
+ " Set a breakpoint that will halt execution whenever the PC is equal to 45678 AND the "
+ "expression (a0 == 100) is true. When that happens, set a0 to ff and resume execution.\n"
+ "\n"
+ "temp0 = 0; bp 567890,++temp0 >= 10\n"
+ " Set a breakpoint that will halt execution whenever the PC is equal to 567890 AND the "
+ "expression (++temp0 >= 10) is true. This effectively breaks only after the breakpoint "
+ "has been hit 16 times.\n"
+ },
+ {
+ "bpclear",
+ "\n"
+ " bpclear [<bpnum>]\n"
+ "\n"
+ "The bpclear command clears a breakpoint. If <bpnum> is specified, only the requested "
+ "breakpoint is cleared, otherwise all breakpoints are cleared.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "bpclear 3\n"
+ " Clear breakpoint index 3.\n"
+ "\n"
+ "bpclear\n"
+ " Clear all breakpoints.\n"
+ },
+ {
+ "bpdisable",
+ "\n"
+ " bpdisable [<bpnum>]\n"
+ "\n"
+ "The bpdisable command disables a breakpoint. If <bpnum> is specified, only the requested "
+ "breakpoint is disabled, otherwise all breakpoints are disabled. Note that disabling a "
+ "breakpoint does not delete it, it just temporarily marks the breakpoint as inactive.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "bpdisable 3\n"
+ " Disable breakpoint index 3.\n"
+ "\n"
+ "bpdisable\n"
+ " Disable all breakpoints.\n"
+ },
+ {
+ "bpenable",
+ "\n"
+ " bpenable [<bpnum>]\n"
+ "\n"
+ "The bpenable command enables a breakpoint. If <bpnum> is specified, only the requested "
+ "breakpoint is enabled, otherwise all breakpoints are enabled.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "bpenable 3\n"
+ " Enable breakpoint index 3.\n"
+ "\n"
+ "bpenable\n"
+ " Enable all breakpoints.\n"
+ },
+ {
+ "bplist",
+ "\n"
+ " bplist\n"
+ "\n"
+ "The bplist command lists all the current breakpoints, along with their index and any "
+ "conditions or actions attached to them.\n"
+ },
+ {
+ "wpset",
+ "\n"
+ " wp[{d|i}][set] <address>,<length>,<type>[,<condition>[,<action>]]\n"
+ "\n"
+ "Sets a new watchpoint starting at the specified <address> and extending for <length>. The "
+ "inclusive range of the watchpoint is <address> through <address> + <length> - 1. The 'wpset' "
+ "command sets a watchpoint on program memory; the 'wpdset' command sets a watchpoint on data "
+ "memory; and the 'wpiset' sets a watchpoint on I/O memory. The <type> parameter specifies "
+ "which sort of accesses to trap on. It can be one of three values: 'r' for a read watchpoint "
+ "'w' for a write watchpoint, and 'rw' for a read/write watchpoint.\n"
+ "\n"
+ "The optional <condition> parameter lets you specify an expression that will be evaluated each "
+ "time the watchpoint is hit. If the result of the expression is true (non-zero), the watchpoint "
+ "will actually halt execution; otherwise, execution will continue with no notification. The "
+ "optional <action> parameter provides a command that is executed whenever the watchpoint is hit "
+ "and the <condition> is true. Note that you may need to embed the action within braces { } in "
+ "order to prevent commas and semicolons from being interpreted as applying to the wpset command "
+ "itself. Each watchpoint that is set is assigned an index which can be used in other "
+ "watchpoint commands to reference this watchpoint.\n"
+ "\n"
+ "In order to help <condition> expressions, two variables are available. For all watchpoints, "
+ "the variable 'wpaddr' is set to the address that actually triggered the watchpoint. For write "
+ "watchpoints, the variable 'wpdata' is set to the data that is being written.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "wp 1234,6,rw\n"
+ " Set a watchpoint that will halt execution whenever a read or write occurs in the address "
+ "range 1234-1239 inclusive.\n"
+ "\n"
+ "wp 23456,a,w,wpdata == 1\n"
+ " Set a watchpoint that will halt execution whenever a write occurs in the address range "
+ "23456-2345f AND the data written is equal to 1.\n"
+ "\n"
+ "wp 3456,20,r,1,{printf \"Read @ %08X\\n\",wpaddr; g}\n"
+ " Set a watchpoint that will halt execution whenever a read occurs in the address range "
+ "3456-3475. When this happens, print Read @ <wpaddr> and continue executing.\n"
+ "\n"
+ "temp0 = 0; wp 45678,1,w,wpdata==f0,{temp0++; g}\n"
+ " Set a watchpoint that will halt execution whenever a write occurs to the address 45678 AND "
+ "the value being written is equal to f0. When that happens, increment the variable temp0 and "
+ "resume execution.\n"
+ },
+ {
+ "wpclear",
+ "\n"
+ " wpclear [<wpnum>]\n"
+ "\n"
+ "The wpclear command clears a watchpoint. If <wpnum> is specified, only the requested "
+ "watchpoint is cleared, otherwise all watchpoints are cleared.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "wpclear 3\n"
+ " Clear watchpoint index 3.\n"
+ "\n"
+ "wpclear\n"
+ " Clear all watchpoints.\n"
+ },
+ {
+ "wpdisable",
+ "\n"
+ " wpdisable [<wpnum>]\n"
+ "\n"
+ "The wpdisable command disables a watchpoint. If <wpnum> is specified, only the requested "
+ "watchpoint is disabled, otherwise all watchpoints are disabled. Note that disabling a "
+ "watchpoint does not delete it, it just temporarily marks the watchpoint as inactive.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "wpdisable 3\n"
+ " Disable watchpoint index 3.\n"
+ "\n"
+ "wpdisable\n"
+ " Disable all watchpoints.\n"
+ },
+ {
+ "wpenable",
+ "\n"
+ " wpenable [<wpnum>]\n"
+ "\n"
+ "The wpenable command enables a watchpoint. If <wpnum> is specified, only the requested "
+ "watchpoint is enabled, otherwise all watchpoints are enabled.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "wpenable 3\n"
+ " Enable watchpoint index 3.\n"
+ "\n"
+ "wpenable\n"
+ " Enable all watchpoints.\n"
+ },
+ {
+ "wplist",
+ "\n"
+ " wplist\n"
+ "\n"
+ "The wplist command lists all the current watchpoints, along with their index and any "
+ "conditions or actions attached to them.\n"
+ },
+ {
+ "hotspot",
+ "\n"
+ " hotspot [<cpu>,[<depth>[,<hits>]]]\n"
+ "\n"
+ "The hotspot command attempts to help locate hotspots in the code where speedup opportunities "
+ "might be present. <cpu>, which defaults to the currently active CPU, specified which "
+ "processor's memory to track. <depth>, which defaults to 64, controls the depth of the search "
+ "buffer. The search buffer tracks the last <depth> memory reads from unique PCs. The <hits> "
+ "parameter, which defaults to 250, specifies the minimum number of hits to report.\n"
+ "\n"
+ "The basic theory of operation is like this: each memory read is trapped by the debugger and "
+ "logged in the search buffer according to the address which was read and the PC that executed "
+ "the opcode. If the search buffer already contains a matching entry, that entry's count is "
+ "incremented and the entry is moved to the top of the list. If the search buffer does not "
+ "contain a matching entry, the entry from the bottom of the list is removed, and a new entry "
+ "is created at the top with an initial count of 1. Entries which fall off the bottom are "
+ "examined and if their count is larger than <hits>, they are reported to the debugger "
+ "console.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "hotspot 0,10\n"
+ " Looks for hotspots on CPU 0 using a search buffer of 16 entries, reporting any entries which "
+ "end up with 250 or more hits.\n"
+ "\n"
+ "hotspot 1,40,#1000\n"
+ " Looks for hotspots on CPU 1 using a search buffer of 64 entries, reporting any entries which "
+ "end up with 1000 or more hits.\n"
+ },
+ {
+ "map",
+ "\n"
+ " map[{d|i}] <address>\n"
+ "\n"
+ "The map/mapd/mapi commands map a logical address in memory to the correct physical address, as "
+ "well as specifying the bank. 'map' will map program space memory, while 'mapd' will map data space "
+ "memory and 'mapi' will map I/O space memory.\n"
+ "\n"
+ "Example:\n"
+ "\n"
+ "map 152d0\n"
+ " Gives physical address and bank for logical address 152d0 in program memory\n"
+ },
+ {
+ "memdump",
+ "\n"
+ " memdump [<filename>]\n"
+ "\n"
+ "Dumps the current memory map to <filename>. If <filename> is omitted, then dumps\n"
+ "to memdump.log"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "memdump mylog.log\n"
+ " Dumps memory to mylog.log.\n"
+ "\n"
+ "memdump\n"
+ " Dumps memory to memdump.log.\n"
+ },
+ {
+ "comadd",
+ "\n"
+ " comadd[//] <address>,<comment>\n"
+ "\n"
+ "Adds a string <comment> to the disassembled code at <address>. The shortcut for this command is simply "
+ "'//'\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "comadd 0, hello world.\n"
+ " Adds the comment 'hello world.' to the code at address 0x0\n"
+ "\n"
+ "// 10, undocumented opcode!\n"
+ " Adds the comment 'undocumented opcode!' to the code at address 0x10\n"
+ "\n"
+ },
+ {
+ "comsave",
+ "\n"
+ " comsave\n"
+ "\n"
+ "Saves the working comments to the driver's XML comment file.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "comsave\n"
+ " Saves the comments to the driver's comment file\n"
+ "\n"
+ },
+ {
+ "comdelete",
+ "\n"
+ " comdelete\n"
+ "\n"
+ "Deletes the comment at the specified memory offset. "
+ "The comment which is deleted is in the currently active memory bank.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "comdelete 10\n"
+ " Deletes the comment at code address 0x10 (using the current memory bank settings)\n"
+ "\n"
+ },
+ {
+ "cheatinit",
+ "\n"
+ " cheatinit [<sign><width><swap>,[<address>,<length>[,<cpu>]]]\n"
+ "\n"
+ "The cheatinit command initializes the cheat search to the selected memory area.\n"
+ "If no parameter is specified the cheat search is initialized to all changeable memory of the main cpu.\n"
+ "<sign> can be s(signed) or u(unsigned)\n"
+ "<width> can be b(8 bit), w(16 bit), d(32 bit) or q(64 bit)\n"
+ "<swap> append s for swapped search\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "cheatinit ub,0x1000,0x10\n"
+ " Initialize the cheat search from 0x1000 to 0x1010 of the first CPU.\n"
+ "\n"
+ "cheatinit sw,0x2000,0x1000,1\n"
+ " Initialize the cheat search with width of 2 byte in signed mode from 0x2000 to 0x3000 of the second CPU.\n"
+ "\n"
+ "cheatinit uds,0x0000,0x1000\n"
+ " Initialize the cheat search with width of 4 byte swapped from 0x0000 to 0x1000.\n"
+ },
+ {
+ "cheatrange",
+ "\n"
+ " cheatrange <address>,<length>\n"
+ "\n"
+ "The cheatrange command adds the selected memory area to the cheat search.\n"
+ "Before using cheatrange it is necessary to initialize the cheat search with cheatinit.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "cheatrange 0x1000,0x10\n"
+ " Add the bytes from 0x1000 to 0x1010 to the cheat search.\n"
+ },
+ {
+ "cheatnext",
+ "\n"
+ " cheatnext <condition>[,<comparisonvalue>]\n"
+ "\n"
+ "The cheatnext command will make comparisons with the last search matches.\n"
+ "Possible <condition>:\n"
+ " all\n"
+ " no <comparisonvalue> needed.\n"
+ " use to update the last value without changing the current matches.\n"
+ " equal [eq]\n"
+ " without <comparisonvalue> search for all bytes that are equal to the last search.\n"
+ " with <comparisonvalue> search for all bytes that are equal to the <comparisonvalue>.\n"
+ " notequal [ne]\n"
+ " without <comparisonvalue> search for all bytes that are not equal to the last search.\n"
+ " with <comparisonvalue> search for all bytes that are not equal to the <comparisonvalue>.\n"
+ " decrease [de, +]\n"
+ " without <comparisonvalue> search for all bytes that have decreased since the last search.\n"
+ " with <comparisonvalue> search for all bytes that have decreased by the <comparisonvalue> since the last search.\n"
+ " increase [in, -]\n"
+ " without <comparisonvalue> search for all bytes that have increased since the last search.\n"
+ " with <comparisonvalue> search for all bytes that have increased by the <comparisonvalue> since the last search.\n"
+ " decreaseorequal [deeq]\n"
+ " no <comparisonvalue> needed.\n"
+ " search for all bytes that have decreased or have same value since the last search.\n"
+ " increaseorequal [ineq]\n"
+ " no <comparisonvalue> needed.\n"
+ " search for all bytes that have decreased or have same value since the last search.\n"
+ " smallerof [lt]\n"
+ " without <comparisonvalue> this condition is invalid\n"
+ " with <comparisonvalue> search for all bytes that are smaller than the <comparisonvalue>.\n"
+ " greaterof [gt]\n"
+ " without <comparisonvalue> this condition is invalid\n"
+ " with <comparisonvalue> search for all bytes that are larger than the <comparisonvalue>.\n"
+ " changedby [ch, ~]\n"
+ " without <comparisonvalue> this condition is invalid\n"
+ " with <comparisonvalue> search for all bytes that have changed by the <comparisonvalue> since the last search.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "cheatnext increase\n"
+ " search for all bytes that have increased since the last search.\n"
+ "\n"
+ "cheatnext decrease, 1\n"
+ " search for all bytes that have decreased by 1 since the last search.\n"
+ },
+ {
+ "cheatnextf",
+ "\n"
+ " cheatnextf <condition>[,<comparisonvalue>]\n"
+ "\n"
+ "The cheatnextf command will make comparisons with the initial search.\n"
+ "Possible <condition>:\n"
+ " all\n"
+ " no <comparisonvalue> needed.\n"
+ " use to update the last value without changing the current matches.\n"
+ " equal [eq]\n"
+ " without <comparisonvalue> search for all bytes that are equal to the initial search.\n"
+ " with <comparisonvalue> search for all bytes that are equal to the <comparisonvalue>.\n"
+ " notequal [ne]\n"
+ " without <comparisonvalue> search for all bytes that are not equal to the initial search.\n"
+ " with <comparisonvalue> search for all bytes that are not equal to the <comparisonvalue>.\n"
+ " decrease [de, +]\n"
+ " without <comparisonvalue> search for all bytes that have decreased since the initial search.\n"
+ " with <comparisonvalue> search for all bytes that have decreased by the <comparisonvalue> since the initial search.\n"
+ " increase [in, -]\n"
+ " without <comparisonvalue> search for all bytes that have increased since the initial search.\n"
+ " with <comparisonvalue> search for all bytes that have increased by the <comparisonvalue> since the initial search.\n"
+ " decreaseorequal [deeq]\n"
+ " no <comparisonvalue> needed.\n"
+ " search for all bytes that have decreased or have same value since the initial search.\n"
+ " increaseorequal [ineq]\n"
+ " no <comparisonvalue> needed.\n"
+ " search for all bytes that have decreased or have same value since the initial search.\n"
+ " smallerof [lt]\n"
+ " without <comparisonvalue> this condition is invalid.\n"
+ " with <comparisonvalue> search for all bytes that are smaller than the <comparisonvalue>.\n"
+ " greaterof [gt]\n"
+ " without <comparisonvalue> this condition is invalid.\n"
+ " with <comparisonvalue> search for all bytes that are larger than the <comparisonvalue>.\n"
+ " changedby [ch, ~]\n"
+ " without <comparisonvalue> this condition is invalid\n"
+ " with <comparisonvalue> search for all bytes that have changed by the <comparisonvalue> since the initial search.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "cheatnextf increase\n"
+ " search for all bytes that have increased since the initial search.\n"
+ "\n"
+ "cheatnextf decrease, 1\n"
+ " search for all bytes that have decreased by 1 since the initial search.\n"
+ },
+ {
+ "cheatlist",
+ "\n"
+ " cheatlist [<filename>]\n"
+ "\n"
+ "Without <filename> show the list of matches in the debug console.\n"
+ "With <filename> save the list of matches in basic xml format to <filename>.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "cheatlist\n"
+ " Show the current matches in the debug console.\n"
+ "cheatlist cheat.txt\n"
+ " Save the current matches to cheat.txt.\n"
+ },
+ {
+ "cheatundo",
+ "\n"
+ " cheatundo\n"
+ "\n"
+ "Undo the results of the last search.\n"
+ "The undo command has no effect on the last value.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "cheatundo\n"
+ " Undo the last search (state only).\n"
+ },
+ {
+ "images",
+ "\n"
+ " images\n"
+ "\n"
+ "Used to display list of available image devices.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "images\n"
+ " Show list of devices and mounted files for current driver.\n"
+ },
+ {
+ "mount",
+ "\n"
+ " mount <device>,<filename>\n"
+ "\n"
+ "Mount <filename> to image <device>.\n"
+ "<filename> can be softlist item or full path to file.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "mount cart,aladdin\n"
+ " Mounts softlist item alladin on cart device.\n"
+ },
+ {
+ "unmount",
+ "\n"
+ " unmount <device>\n"
+ "\n"
+ "Unmounts file from image <device>.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ "unmount cart\n"
+ " Unmounts any file mounted on device named cart.\n"
+ }
+};
+
+
+
+/***************************************************************************
+ CODE
+***************************************************************************/
+
+const char *debug_get_help(const char *tag)
+{
+ static char ambig_message[1024];
+ const help_item *found = NULL;
+ int i, msglen, foundcount = 0;
+ int taglen = (int)strlen(tag);
+ char tagcopy[256];
+
+ /* make a lowercase copy of the tag */
+ for (i = 0; i <= taglen; i++)
+ tagcopy[i] = tolower((UINT8)tag[i]);
+
+ /* find a match */
+ for (i = 0; i < sizeof(static_help_list) / sizeof(static_help_list[0]); i++)
+ if (!strncmp(static_help_list[i].tag, tagcopy, taglen))
+ {
+ foundcount++;
+ found = &static_help_list[i];
+ if (strlen(found->tag) == taglen)
+ {
+ foundcount = 1;
+ break;
+ }
+ }
+
+ /* only a single match makes sense */
+ if (foundcount == 1)
+ return found->help;
+
+ /* if not found, return the first entry */
+ if (foundcount == 0)
+ return static_help_list[0].help;
+
+ /* otherwise, indicate ambiguous help */
+ msglen = sprintf(ambig_message, "Ambiguous help request, did you mean:\n");
+ for (i = 0; i < sizeof(static_help_list) / sizeof(static_help_list[0]); i++)
+ if (!strncmp(static_help_list[i].tag, tagcopy, taglen))
+ msglen += sprintf(&ambig_message[msglen], " help %s?\n", static_help_list[i].tag);
+ return ambig_message;
+}
+
diff --git a/trunk/src/emu/debug/debughlp.h b/trunk/src/emu/debug/debughlp.h
new file mode 100644
index 00000000000..d7ce2806320
--- /dev/null
+++ b/trunk/src/emu/debug/debughlp.h
@@ -0,0 +1,23 @@
+/*********************************************************************
+
+ debughlp.h
+
+ Debugger help engine.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+#ifndef __DEBUGHLP_H__
+#define __DEBUGHLP_H__
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+/* help management */
+const char * debug_get_help(const char *tag);
+
+#endif
diff --git a/trunk/src/emu/debug/debugvw.c b/trunk/src/emu/debug/debugvw.c
new file mode 100644
index 00000000000..a0eb13452d2
--- /dev/null
+++ b/trunk/src/emu/debug/debugvw.c
@@ -0,0 +1,633 @@
+/*********************************************************************
+
+ debugvw.c
+
+ Debugger view engine.
+
+****************************************************************************
+
+ 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 "express.h"
+#include "debugvw.h"
+#include "dvtext.h"
+#include "dvstate.h"
+#include "dvdisasm.h"
+#include "dvmemory.h"
+#include "debugcmd.h"
+#include "debugcpu.h"
+#include "debugcon.h"
+#include <ctype.h>
+
+
+
+//**************************************************************************
+// DEBUG VIEW SOURCE
+//**************************************************************************
+
+//-------------------------------------------------
+// debug_view_source - constructor
+//-------------------------------------------------
+
+debug_view_source::debug_view_source(const char *name, device_t *device)
+ : m_next(NULL),
+ m_name(name),
+ m_device(device)
+{
+}
+
+
+//-------------------------------------------------
+// ~debug_view_source - destructor
+//-------------------------------------------------
+
+debug_view_source::~debug_view_source()
+{
+}
+
+
+
+//**************************************************************************
+// DEBUG VIEW SOURCE LIST
+//**************************************************************************
+
+//-------------------------------------------------
+// debug_view_source_list - constructor
+//-------------------------------------------------
+
+debug_view_source_list::debug_view_source_list(running_machine &machine)
+ : m_machine(machine),
+ m_head(NULL),
+ m_tail(NULL),
+ m_count(0)
+{
+}
+
+
+//-------------------------------------------------
+// ~debug_view_source_list - destructor
+//-------------------------------------------------
+
+debug_view_source_list::~debug_view_source_list()
+{
+ reset();
+}
+
+
+//-------------------------------------------------
+// index - return the index of a source
+//-------------------------------------------------
+
+int debug_view_source_list::index(const debug_view_source &source) const
+{
+ int result = 0;
+ for (debug_view_source *cursource = m_head; cursource != NULL; cursource = cursource->m_next)
+ {
+ if (cursource == &source)
+ break;
+ result++;
+ }
+ return result;
+}
+
+
+//-------------------------------------------------
+// by_index - return a source given an index
+//-------------------------------------------------
+
+const debug_view_source *debug_view_source_list::by_index(int index) const
+{
+ if (m_head == NULL)
+ return NULL;
+ const debug_view_source *result;
+ for (result = m_head; index > 0 && result->m_next != NULL; result = result->m_next)
+ index--;
+ return result;
+}
+
+
+//-------------------------------------------------
+// reset - free all the view_sources
+//-------------------------------------------------
+
+void debug_view_source_list::reset()
+{
+ // free from the head
+ while (m_head != NULL)
+ {
+ debug_view_source *source = m_head;
+ m_head = source->m_next;
+ auto_free(machine(), source);
+ }
+
+ // reset the tail pointer and index
+ m_tail = NULL;
+ m_count = 0;
+}
+
+
+//-------------------------------------------------
+// append - add a view_source to the end of the
+// list
+//-------------------------------------------------
+
+void debug_view_source_list::append(debug_view_source &source)
+{
+ // set the next and index values
+ source.m_next = NULL;
+
+ // append to the end
+ if (m_tail == NULL)
+ m_head = m_tail = &source;
+ else
+ m_tail->m_next = &source;
+ m_tail = &source;
+ m_count++;
+}
+
+
+//-------------------------------------------------
+// match_device - find the first view that
+// matches the given device
+//-------------------------------------------------
+
+const debug_view_source *debug_view_source_list::match_device(device_t *device) const
+{
+ for (debug_view_source *source = m_head; source != NULL; source = source->m_next)
+ if (device == source->m_device)
+ return source;
+ return m_head;
+}
+
+
+
+//**************************************************************************
+// DEBUG VIEW
+//**************************************************************************
+
+//-------------------------------------------------
+// debug_view - constructor
+//-------------------------------------------------
+
+debug_view::debug_view(running_machine &machine, debug_view_type type, debug_view_osd_update_func osdupdate, void *osdprivate)
+ : m_next(NULL),
+ m_type(type),
+ m_source(NULL),
+ m_source_list(machine),
+ m_osdupdate(osdupdate),
+ m_osdprivate(osdprivate),
+ m_visible(10,10),
+ m_total(10,10),
+ m_topleft(0,0),
+ m_cursor(0,0),
+ m_supports_cursor(false),
+ m_cursor_visible(false),
+ m_recompute(true),
+ m_update_level(0),
+ m_update_pending(true),
+ m_osd_update_pending(true),
+ m_viewdata(NULL),
+ m_viewdata_size(0),
+ m_machine(machine)
+{
+ // allocate memory for the buffer
+ m_viewdata_size = m_visible.y * m_visible.x;
+ m_viewdata = auto_alloc_array(machine, debug_view_char, m_viewdata_size);
+}
+
+
+//-------------------------------------------------
+// ~debug_view - destructor
+//-------------------------------------------------
+
+debug_view::~debug_view()
+{
+}
+
+
+//-------------------------------------------------
+// end_update - bracket a sequence of changes so
+// that only one update occurs
+//-------------------------------------------------
+
+void debug_view::end_update()
+{
+ /* if we hit zero, call the update function */
+ if (m_update_level == 1)
+ {
+ while (m_update_pending)
+ {
+ // no longer pending, but flag for the OSD
+ m_update_pending = false;
+ m_osd_update_pending = true;
+
+ // resize the viewdata if needed
+ int size = m_visible.x * m_visible.y;
+ if (size > m_viewdata_size)
+ {
+ m_viewdata_size = size;
+ auto_free(machine(), m_viewdata);
+ m_viewdata = auto_alloc_array(machine(), debug_view_char, m_viewdata_size);
+ }
+
+ // update the view
+ view_update();
+ }
+ }
+
+ // decrement the level
+ m_update_level--;
+}
+
+
+//-------------------------------------------------
+// flush_osd_updates - notify the OSD of any
+// pending updates
+//-------------------------------------------------
+
+void debug_view::flush_osd_updates()
+{
+ if (m_osd_update_pending && m_osdupdate != NULL)
+ (*m_osdupdate)(*this, m_osdprivate);
+ m_osd_update_pending = false;
+}
+
+
+//-------------------------------------------------
+// set_visible_size - set the visible size in
+// rows and columns
+//-------------------------------------------------*/
+
+void debug_view::set_visible_size(debug_view_xy size)
+{
+ if (size.x != m_visible.x || size.y != m_visible.y)
+ {
+ begin_update();
+ m_visible = size;
+ m_update_pending = true;
+ view_notify(VIEW_NOTIFY_VISIBLE_CHANGED);
+ end_update();
+ }
+}
+
+
+//-------------------------------------------------
+// set_visible_position - set the top left
+// position of the visible area in rows and
+// columns
+//-------------------------------------------------
+
+void debug_view::set_visible_position(debug_view_xy pos)
+{
+ if (pos.x != m_topleft.x || pos.y != m_topleft.y)
+ {
+ begin_update();
+ m_topleft = pos;
+ m_update_pending = true;
+ view_notify(VIEW_NOTIFY_VISIBLE_CHANGED);
+ end_update();
+ }
+}
+
+
+//-------------------------------------------------
+// set_cursor_position - set the current cursor
+// position as a row and column
+//-------------------------------------------------
+
+void debug_view::set_cursor_position(debug_view_xy pos)
+{
+ if (pos.x != m_cursor.x || pos.y != m_cursor.y)
+ {
+ begin_update();
+ m_cursor = pos;
+ m_update_pending = true;
+ view_notify(VIEW_NOTIFY_CURSOR_CHANGED);
+ end_update();
+ }
+}
+
+
+//-------------------------------------------------
+// set_cursor_visible - set the visible state of
+// the cursor
+//-------------------------------------------------
+
+void debug_view::set_cursor_visible(bool visible)
+{
+ if (visible != m_cursor_visible)
+ {
+ begin_update();
+ m_cursor_visible = visible;
+ m_update_pending = true;
+ view_notify(VIEW_NOTIFY_CURSOR_CHANGED);
+ end_update();
+ }
+}
+
+
+//-------------------------------------------------
+// set_subview - set the current subview
+//-------------------------------------------------
+
+void debug_view::set_source(const debug_view_source &source)
+{
+ if (&source != m_source)
+ {
+ begin_update();
+ m_source = &source;
+ m_update_pending = true;
+ view_notify(VIEW_NOTIFY_SOURCE_CHANGED);
+ end_update();
+ }
+}
+
+
+//-------------------------------------------------
+// adjust_visible_x_for_cursor - adjust a view's
+// visible X position to ensure the cursor is
+// visible
+//-------------------------------------------------
+
+void debug_view::adjust_visible_x_for_cursor()
+{
+ if (m_cursor.x < m_topleft.x)
+ m_topleft.x = m_cursor.x;
+ else if (m_cursor.x >= m_topleft.x + m_visible.x - 1)
+ m_topleft.x = m_cursor.x - m_visible.x + 2;
+}
+
+
+//-------------------------------------------------
+// adjust_visible_y_for_cursor - adjust a view's
+// visible Y position to ensure the cursor is
+// visible
+//-------------------------------------------------
+
+void debug_view::adjust_visible_y_for_cursor()
+{
+ if (m_cursor.y < m_topleft.y)
+ m_topleft.y = m_cursor.y;
+ else if (m_cursor.y >= m_topleft.y + m_visible.y - 1)
+ m_topleft.y = m_cursor.y - m_visible.y + 2;
+}
+
+
+//-------------------------------------------------
+// view_notify - handle notification of updates
+//-------------------------------------------------
+
+void debug_view::view_notify(debug_view_notification type)
+{
+ // default does nothing
+}
+
+
+//-------------------------------------------------
+// view_char - handle a character typed within
+// the current view
+//-------------------------------------------------
+
+void debug_view::view_char(int chval)
+{
+ // default does nothing
+}
+
+
+
+//**************************************************************************
+// DEBUG VIEW MANAGER
+//**************************************************************************
+
+//-------------------------------------------------
+// debug_view_manager - constructor
+//-------------------------------------------------
+
+debug_view_manager::debug_view_manager(running_machine &machine)
+ : m_machine(machine),
+ m_viewlist(NULL)
+{
+}
+
+
+//-------------------------------------------------
+// ~debug_view_manager - destructor
+//-------------------------------------------------
+
+debug_view_manager::~debug_view_manager()
+{
+ while (m_viewlist != NULL)
+ {
+ debug_view *oldhead = m_viewlist;
+ m_viewlist = oldhead->m_next;
+ auto_free(machine(), oldhead);
+ }
+}
+
+
+//-------------------------------------------------
+// alloc_view - create a new view
+//-------------------------------------------------
+
+debug_view *debug_view_manager::alloc_view(debug_view_type type, debug_view_osd_update_func osdupdate, void *osdprivate)
+{
+ switch (type)
+ {
+ case DVT_CONSOLE:
+ return append(auto_alloc(machine(), debug_view_console(machine(), osdupdate, osdprivate)));
+
+ case DVT_STATE:
+ return append(auto_alloc(machine(), debug_view_state(machine(), osdupdate, osdprivate)));
+
+ case DVT_DISASSEMBLY:
+ return append(auto_alloc(machine(), debug_view_disasm(machine(), osdupdate, osdprivate)));
+
+ case DVT_MEMORY:
+ return append(auto_alloc(machine(), debug_view_memory(machine(), osdupdate, osdprivate)));
+
+ case DVT_LOG:
+ return append(auto_alloc(machine(), debug_view_log(machine(), osdupdate, osdprivate)));
+
+ case DVT_TIMERS:
+// return append(auto_alloc(machine(), debug_view_timers(machine(), osdupdate, osdprivate)));
+
+ case DVT_ALLOCS:
+// return append(auto_alloc(machine(), debug_view_allocs(machine(), osdupdate, osdprivate)));
+
+ default:
+ fatalerror("Attempt to create invalid debug view type %d\n", type);
+ }
+ return NULL;
+}
+
+
+//-------------------------------------------------
+// free_view - free a view
+//-------------------------------------------------
+
+void debug_view_manager::free_view(debug_view &view)
+{
+ // free us but only if we're in the list
+ for (debug_view **viewptr = &m_viewlist; *viewptr != NULL; viewptr = &(*viewptr)->m_next)
+ if (*viewptr == &view)
+ {
+ *viewptr = view.m_next;
+ auto_free(machine(), &view);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// update_all - force all views to refresh
+//-------------------------------------------------
+
+void debug_view_manager::update_all(debug_view_type type)
+{
+ // loop over each view and force an update
+ for (debug_view *view = m_viewlist; view != NULL; view = view->next())
+ if (type == DVT_NONE || type == view->type())
+ view->force_update();
+}
+
+
+//-------------------------------------------------
+// flush_osd_updates - flush all pending OSD
+// updates
+//-------------------------------------------------
+
+void debug_view_manager::flush_osd_updates()
+{
+ for (debug_view *view = m_viewlist; view != NULL; view = view->m_next)
+ view->flush_osd_updates();
+}
+
+
+//-------------------------------------------------
+// append - append a view to the end of our list
+//-------------------------------------------------
+
+debug_view *debug_view_manager::append(debug_view *view)
+{
+ debug_view **viewptr;
+ for (viewptr = &m_viewlist; *viewptr != NULL; viewptr = &(*viewptr)->m_next) ;
+ *viewptr = view;
+ return view;
+}
+
+
+
+//**************************************************************************
+// DEBUG VIEW EXPRESSION
+//**************************************************************************
+
+//-------------------------------------------------
+// debug_view_expression - constructor
+//-------------------------------------------------
+
+debug_view_expression::debug_view_expression(running_machine &machine)
+ : m_machine(machine),
+ m_dirty(true),
+ m_result(0),
+ m_parsed(debug_cpu_get_global_symtable(machine)),
+ m_string("0")
+{
+}
+
+
+//-------------------------------------------------
+// ~debug_view_expression - destructor
+//-------------------------------------------------
+
+debug_view_expression::~debug_view_expression()
+{
+}
+
+
+//-------------------------------------------------
+// set_context - set the context for the
+// expression
+//-------------------------------------------------
+
+void debug_view_expression::set_context(symbol_table *context)
+{
+ m_parsed.set_symbols((context != NULL) ? context : debug_cpu_get_global_symtable(machine()));
+ m_dirty = true;
+}
+
+
+//-------------------------------------------------
+// recompute - recompute the value of an
+// expression
+//-------------------------------------------------
+
+bool debug_view_expression::recompute()
+{
+ bool changed = m_dirty;
+
+ // if dirty, re-evaluate
+ if (m_dirty)
+ {
+ astring oldstring(m_parsed.original_string());
+ try
+ {
+ m_parsed.parse(m_string);
+ }
+ catch (expression_error &)
+ {
+ m_parsed.parse(oldstring);
+ }
+ }
+
+ // if we have a parsed expression, evalute it
+ if (!m_parsed.is_empty())
+ {
+ // recompute the value of the expression
+ try
+ {
+ UINT64 newresult = m_parsed.execute();
+ if (newresult != m_result)
+ {
+ m_result = newresult;
+ changed = true;
+ }
+ }
+ catch (expression_error &)
+ {
+ }
+ }
+
+ // expression no longer dirty by definition
+ m_dirty = false;
+ return changed;
+}
diff --git a/trunk/src/emu/debug/debugvw.h b/trunk/src/emu/debug/debugvw.h
new file mode 100644
index 00000000000..2d2bde6c4c5
--- /dev/null
+++ b/trunk/src/emu/debug/debugvw.h
@@ -0,0 +1,335 @@
+/*********************************************************************
+
+ debugvw.h
+
+ Debugger view engine.
+
+****************************************************************************
+
+ 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.
+
+***************************************************************************/
+
+#ifndef __DEBUGVIEW_H__
+#define __DEBUGVIEW_H__
+
+#include "express.h"
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// types passed to debug_view_manager::alloc_view()
+enum debug_view_type
+{
+ DVT_NONE,
+ DVT_CONSOLE,
+ DVT_STATE,
+ DVT_DISASSEMBLY,
+ DVT_MEMORY,
+ DVT_LOG,
+ DVT_TIMERS,
+ DVT_ALLOCS
+};
+
+
+// notifications passed to view_notify()
+enum debug_view_notification
+{
+ VIEW_NOTIFY_NONE,
+ VIEW_NOTIFY_VISIBLE_CHANGED,
+ VIEW_NOTIFY_CURSOR_CHANGED,
+ VIEW_NOTIFY_SOURCE_CHANGED
+};
+
+
+// attribute bits for debug_view_char.attrib
+const UINT8 DCA_NORMAL = 0x00; // in Windows: black on white
+const UINT8 DCA_CHANGED = 0x01; // in Windows: red foreground
+const UINT8 DCA_SELECTED = 0x02; // in Windows: light red background
+const UINT8 DCA_INVALID = 0x04; // in Windows: dark blue foreground
+const UINT8 DCA_DISABLED = 0x08; // in Windows: darker foreground
+const UINT8 DCA_ANCILLARY = 0x10; // in Windows: grey background
+const UINT8 DCA_CURRENT = 0x20; // in Windows: yellow background
+const UINT8 DCA_COMMENT = 0x40; // in Windows: green foreground
+
+
+// special characters that can be passed to process_char()
+const int DCH_UP = 1; // up arrow
+const int DCH_DOWN = 2; // down arrow
+const int DCH_LEFT = 3; // left arrow
+const int DCH_RIGHT = 4; // right arrow
+const int DCH_PUP = 5; // page up
+const int DCH_PDOWN = 6; // page down
+const int DCH_HOME = 7; // home
+const int DCH_CTRLHOME = 8; // ctrl+home
+const int DCH_END = 9; // end
+const int DCH_CTRLEND = 10; // ctrl+end
+const int DCH_CTRLRIGHT = 11; // ctrl+right
+const int DCH_CTRLLEFT = 12; // ctrl+left
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// forward references
+class debug_view;
+
+
+// OSD callback function for a view
+typedef void (*debug_view_osd_update_func)(debug_view &view, void *osdprivate);
+
+
+// a single "character" in the debug view has an ASCII value and an attribute byte
+struct debug_view_char
+{
+ UINT8 byte;
+ UINT8 attrib;
+};
+
+
+// pair of X,Y coordinates for sizing
+class debug_view_xy
+{
+public:
+ debug_view_xy(int _x = 0, int _y = 0) : x(_x), y(_y) { }
+
+ INT32 x;
+ INT32 y;
+};
+
+
+// debug_view_sources select from multiple sources available within a view
+class debug_view_source
+{
+ DISABLE_COPYING(debug_view_source);
+
+ friend class debug_view_source_list;
+
+public:
+ // construction/destruction
+ debug_view_source(const char *name, device_t *device = NULL);
+ virtual ~debug_view_source();
+
+ // getters
+ const char *name() const { return m_name; }
+ debug_view_source *next() const { return m_next; }
+ device_t *device() const { return m_device; }
+
+private:
+ // internal state
+ debug_view_source * m_next; // link to next item
+ astring m_name; // name of the source item
+ device_t * m_device; // associated device (if applicable)
+};
+
+
+// a debug_view_source_list contains a list of debug_view_sources
+class debug_view_source_list
+{
+ DISABLE_COPYING(debug_view_source_list);
+
+public:
+ // construction/destruction
+ debug_view_source_list(running_machine &machine);
+ ~debug_view_source_list();
+
+ // getters
+ running_machine &machine() const { return m_machine; }
+ const debug_view_source *head() const { return m_head; }
+ int count() const { return m_count; }
+ int index(const debug_view_source &source) const;
+ const debug_view_source *by_index(int index) const;
+
+ // operations
+ void reset();
+ void append(debug_view_source &view_source);
+ const debug_view_source *match_device(device_t *device) const;
+ int match_device_index(device_t *device) const { return index(*match_device(device)); }
+
+private:
+ // internal state
+ running_machine & m_machine; // reference to our machine
+ debug_view_source * m_head; // head of the list
+ debug_view_source * m_tail; // end of the tail
+ UINT32 m_count; // number of items in the list
+};
+
+
+// debug_view describes a single text-based view
+class debug_view
+{
+ friend class debug_view_manager;
+
+protected:
+ // construction/destruction
+ debug_view(running_machine &machine, debug_view_type type, debug_view_osd_update_func osdupdate, void *osdprivate);
+ virtual ~debug_view();
+
+public:
+ // getters
+ running_machine &machine() const { return m_machine; }
+ debug_view *next() const { return m_next; }
+ debug_view_type type() const { return m_type; }
+ const debug_view_char *viewdata() const { return m_viewdata; }
+ debug_view_xy total_size() { flush_updates(); return m_total; }
+ debug_view_xy visible_size() { flush_updates(); return m_visible; }
+ debug_view_xy visible_position() { flush_updates(); return m_topleft; }
+ debug_view_xy cursor_position() { flush_updates(); return m_cursor; }
+ bool cursor_supported() { flush_updates(); return m_supports_cursor; }
+ bool cursor_visible() { flush_updates(); return m_cursor_visible; }
+ const debug_view_source *source() const { return m_source; }
+ const debug_view_source_list &source_list() const { return m_source_list; }
+
+ // setters
+ void set_size(int width, int height);
+ void set_visible_size(debug_view_xy size);
+ void set_visible_position(debug_view_xy pos);
+ void set_cursor_position(debug_view_xy pos);
+ void set_cursor_visible(bool visible = true);
+ void set_source(const debug_view_source &source);
+ void process_char(int character) { view_char(character); }
+
+protected:
+ // internal updating helpers
+ void begin_update() { m_update_level++; }
+ void end_update();
+ void force_update() { begin_update(); m_update_pending = true; end_update(); }
+ void flush_updates() { begin_update(); end_update(); }
+ void flush_osd_updates();
+
+ // cursor management helpers
+ void adjust_visible_x_for_cursor();
+ void adjust_visible_y_for_cursor();
+
+ // overridables
+ virtual void view_update() = 0;
+ virtual void view_notify(debug_view_notification type);
+ virtual void view_char(int chval);
+
+protected:
+ // core view data
+ debug_view * m_next; // link to the next view
+ debug_view_type m_type; // type of view
+ const debug_view_source *m_source; // currently selected data source
+ debug_view_source_list m_source_list; // list of available data sources
+
+ // OSD data
+ debug_view_osd_update_func m_osdupdate; // callback for the update
+ void * m_osdprivate; // OSD-managed private data
+
+ // visibility info
+ debug_view_xy m_visible; // visible size (in rows and columns)
+ debug_view_xy m_total; // total size (in rows and columns)
+ debug_view_xy m_topleft; // top-left visible position (in rows and columns)
+ debug_view_xy m_cursor; // cursor position
+ bool m_supports_cursor; // does this view support a cursor?
+ bool m_cursor_visible; // is the cursor visible?
+
+ // update info
+ bool m_recompute; // does this view require a recomputation?
+ UINT8 m_update_level; // update level; updates when this hits 0
+ bool m_update_pending; // true if there is a pending update
+ bool m_osd_update_pending; // true if there is a pending update
+ debug_view_char * m_viewdata; // current array of view data
+ int m_viewdata_size; // number of elements of the viewdata array
+
+private:
+ running_machine & m_machine; // machine associated with this view
+};
+
+
+// debug_view_manager manages all the views
+class debug_view_manager
+{
+public:
+ // construction/destruction
+ debug_view_manager(running_machine &machine);
+ ~debug_view_manager();
+
+ // getters
+ running_machine &machine() const { return m_machine; }
+
+ // view allocation
+ debug_view *alloc_view(debug_view_type type, debug_view_osd_update_func osdupdate, void *osdprivate);
+ void free_view(debug_view &view);
+
+ // update helpers
+ void update_all(debug_view_type type = DVT_NONE);
+ void flush_osd_updates();
+
+private:
+ // private helpers
+ debug_view *append(debug_view *view);
+
+ // internal state
+ running_machine & m_machine; // reference to our machine
+ debug_view * m_viewlist; // list of views
+};
+
+
+// debug_view_expression is a helper for handling embedded expressions
+class debug_view_expression
+{
+public:
+ // construction/destruction
+ debug_view_expression(running_machine &machine);
+ ~debug_view_expression();
+
+ // getters
+ running_machine &machine() const { return m_machine; }
+ bool dirty() const { return m_dirty; }
+ UINT64 last_value() const { return m_result; }
+ UINT64 value() { recompute(); return m_result; }
+ const char *string() const { return m_string; }
+ symbol_table *context() const { return m_parsed.symbols(); }
+
+ // setters
+ void mark_dirty() { m_dirty = true; }
+ void set_string(const char *string) { m_string.cpy(string); m_dirty = true; }
+ void set_context(symbol_table *context);
+
+private:
+ // internal helpers
+ bool recompute();
+
+ // internal state
+ running_machine & m_machine; // reference to the machine
+ bool m_dirty; // true if the expression needs to be re-evaluated
+ UINT64 m_result; // last result from the expression
+ parsed_expression m_parsed; // parsed expression data
+ astring m_string; // copy of the expression string
+};
+
+
+#endif
diff --git a/trunk/src/emu/debug/dvdisasm.c b/trunk/src/emu/debug/dvdisasm.c
new file mode 100644
index 00000000000..ccd1616f1e2
--- /dev/null
+++ b/trunk/src/emu/debug/dvdisasm.c
@@ -0,0 +1,705 @@
+/*********************************************************************
+
+ dvdisasm.c
+
+ Disassembly debugger view.
+
+****************************************************************************
+
+ 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 "debugvw.h"
+#include "dvdisasm.h"
+#include "debugcpu.h"
+
+
+
+//**************************************************************************
+// DEBUG VIEW DISASM SOURCE
+//**************************************************************************
+
+//-------------------------------------------------
+// debug_view_disasm_source - constructor
+//-------------------------------------------------
+
+debug_view_disasm_source::debug_view_disasm_source(const char *name, device_t &device)
+ : debug_view_source(name, &device),
+ m_device(device),
+ m_disasmintf(dynamic_cast<device_disasm_interface *>(&device)),
+ m_space(dynamic_cast<device_memory_interface *>(&device)->space(AS_PROGRAM))
+{
+}
+
+
+
+//**************************************************************************
+// DEBUG VIEW DISASM
+//**************************************************************************
+
+//-------------------------------------------------
+// debug_view_disasm - constructor
+//-------------------------------------------------
+
+debug_view_disasm::debug_view_disasm(running_machine &machine, debug_view_osd_update_func osdupdate, void *osdprivate)
+ : debug_view(machine, DVT_DISASSEMBLY, osdupdate, osdprivate),
+ m_right_column(DASM_RIGHTCOL_RAW),
+ m_backwards_steps(3),
+ m_dasm_width(DEFAULT_DASM_WIDTH),
+ m_last_direct_raw(NULL),
+ m_last_direct_decrypted(NULL),
+ m_last_change_count(0),
+ m_last_pcbyte(0),
+ m_divider1(0),
+ m_divider2(0),
+ m_divider3(0),
+ m_expression(machine),
+ m_allocated(0,0),
+ m_byteaddress(NULL),
+ m_dasm(NULL)
+{
+ // fail if no available sources
+ enumerate_sources();
+ if (m_source_list.count() == 0)
+ throw std::bad_alloc();
+
+ // count the number of comments
+ int total_comments = 0;
+ for (const debug_view_source *source = m_source_list.head(); source != NULL; source = source->next())
+ {
+ const debug_view_disasm_source &dasmsource = downcast<const debug_view_disasm_source &>(*source);
+ total_comments += dasmsource.m_device.debug()->comment_count();
+ }
+
+ // initialize
+ if (total_comments > 0)
+ m_right_column = DASM_RIGHTCOL_COMMENTS;
+
+ // configure the view
+ m_total.y = DEFAULT_DASM_LINES;
+ m_supports_cursor = true;
+}
+
+
+//-------------------------------------------------
+// ~debug_view_disasm - destructor
+//-------------------------------------------------
+
+debug_view_disasm::~debug_view_disasm()
+{
+ auto_free(machine(), m_byteaddress);
+ auto_free(machine(), m_dasm);
+}
+
+
+//-------------------------------------------------
+// enumerate_sources - enumerate all possible
+// sources for a disassembly view
+//-------------------------------------------------
+
+void debug_view_disasm::enumerate_sources()
+{
+ // start with an empty list
+ m_source_list.reset();
+
+ // iterate over devices with disassembly interfaces
+ device_disasm_interface *dasm = NULL;
+ astring name;
+ for (bool gotone = machine().devicelist().first(dasm); gotone; gotone = dasm->next(dasm))
+ {
+ name.printf("%s '%s'", dasm->device().name(), dasm->device().tag());
+ m_source_list.append(*auto_alloc(machine(), debug_view_disasm_source(name, dasm->device())));
+ }
+
+ // reset the source to a known good entry
+ set_source(*m_source_list.head());
+}
+
+
+//-------------------------------------------------
+// view_notify - handle notification of updates
+// to cursor changes
+//-------------------------------------------------
+
+void debug_view_disasm::view_notify(debug_view_notification type)
+{
+ if (type == VIEW_NOTIFY_CURSOR_CHANGED)
+ adjust_visible_y_for_cursor();
+
+ else if (type == VIEW_NOTIFY_SOURCE_CHANGED)
+ m_expression.set_context(&downcast<const debug_view_disasm_source *>(m_source)->device().debug()->symtable());
+}
+
+
+//-------------------------------------------------
+// view_char - handle a character typed within
+// the current view
+//-------------------------------------------------
+
+void debug_view_disasm::view_char(int chval)
+{
+ debug_view_xy origcursor = m_cursor;
+ UINT8 end_buffer = 3;
+ INT32 temp;
+
+ switch (chval)
+ {
+ case DCH_UP:
+ if (m_cursor.y > 0)
+ m_cursor.y--;
+ break;
+
+ case DCH_DOWN:
+ if (m_cursor.y < m_total.y - 1)
+ m_cursor.y++;
+ break;
+
+ case DCH_PUP:
+ temp = m_cursor.y - (m_visible.y - end_buffer);
+ if (temp < 0)
+ m_cursor.y = 0;
+ else
+ m_cursor.y = temp;
+ break;
+
+ case DCH_PDOWN:
+ temp = m_cursor.y + (m_visible.y - end_buffer);
+ if (temp > m_total.y - 1)
+ m_cursor.y = m_total.y - 1;
+ else
+ m_cursor.y = temp;
+ break;
+
+ case DCH_HOME: // set the active column to the PC
+ {
+ const debug_view_disasm_source &source = downcast<const debug_view_disasm_source &>(*m_source);
+ offs_t pc = source.m_space->address_to_byte(cpu_get_pc(&source.m_device)) & source.m_space->logbytemask();
+
+ // figure out which row the pc is on
+ for (int curline = 0; curline < m_allocated.y; curline++)
+ if (m_byteaddress[curline] == pc)
+ m_cursor.y = curline;
+ break;
+ }
+
+ case DCH_CTRLHOME:
+ m_cursor.y = 0;
+ break;
+
+ case DCH_CTRLEND:
+ m_cursor.y = m_total.y - 1;
+ break;
+ }
+
+ /* send a cursor changed notification */
+ if (m_cursor.y != origcursor.y)
+ {
+ begin_update();
+ view_notify(VIEW_NOTIFY_CURSOR_CHANGED);
+ m_update_pending = true;
+ end_update();
+ }
+}
+
+
+//-------------------------------------------------
+// find_pc_backwards - back up the specified
+// number of instructions from the given PC
+//-------------------------------------------------
+
+offs_t debug_view_disasm::find_pc_backwards(offs_t targetpc, int numinstrs)
+{
+ const debug_view_disasm_source &source = downcast<const debug_view_disasm_source &>(*m_source);
+
+ // compute the increment
+ int minlen = source.m_space->byte_to_address(source.m_disasmintf->min_opcode_bytes());
+ if (minlen == 0) minlen = 1;
+ int maxlen = source.m_space->byte_to_address(source.m_disasmintf->max_opcode_bytes());
+ if (maxlen == 0) maxlen = 1;
+
+ // start off numinstrs back
+ offs_t curpc = targetpc - minlen * numinstrs;
+ if (curpc > targetpc)
+ curpc = 0;
+
+ /* loop until we find what we are looking for */
+ offs_t targetpcbyte = source.m_space->address_to_byte(targetpc) & source.m_space->logbytemask();
+ offs_t fillpcbyte = targetpcbyte;
+ offs_t lastgoodpc = targetpc;
+ while (1)
+ {
+ // fill the buffer up to the target
+ offs_t curpcbyte = source.m_space->address_to_byte(curpc) & source.m_space->logbytemask();
+ UINT8 opbuf[1024], argbuf[1024];
+ while (curpcbyte < fillpcbyte)
+ {
+ fillpcbyte--;
+ opbuf[1000 + fillpcbyte - targetpcbyte] = debug_read_opcode(source.m_space, fillpcbyte, 1, FALSE);
+ argbuf[1000 + fillpcbyte - targetpcbyte] = debug_read_opcode(source.m_space, fillpcbyte, 1, TRUE);
+ }
+
+ // loop until we get past the target instruction
+ int instcount = 0;
+ int instlen;
+ offs_t scanpc;
+ for (scanpc = curpc; scanpc < targetpc; scanpc += instlen)
+ {
+ offs_t scanpcbyte = source.m_space->address_to_byte(scanpc) & source.m_space->logbytemask();
+ offs_t physpcbyte = scanpcbyte;
+
+ // get the disassembly, but only if mapped
+ instlen = 1;
+ if (debug_cpu_translate(source.m_space, TRANSLATE_FETCH, &physpcbyte))
+ {
+ char dasmbuffer[100];
+ instlen = source.m_device.debug()->disassemble(dasmbuffer, scanpc, &opbuf[1000 + scanpcbyte - targetpcbyte], &argbuf[1000 + scanpcbyte - targetpcbyte]) & DASMFLAG_LENGTHMASK;
+ }
+
+ // count this one
+ instcount++;
+ }
+
+ // if we ended up right on targetpc, this is a good candidate
+ if (scanpc == targetpc && instcount <= numinstrs)
+ lastgoodpc = curpc;
+
+ // we're also done if we go back too far
+ if (targetpc - curpc >= numinstrs * maxlen)
+ break;
+
+ // and if we hit 0, we're done
+ if (curpc == 0)
+ break;
+
+ // back up one more and try again
+ curpc -= minlen;
+ if (curpc > targetpc)
+ curpc = 0;
+ }
+
+ return lastgoodpc;
+}
+
+
+//-------------------------------------------------
+// generate_bytes - generate the opcode byte
+// values
+//-------------------------------------------------
+
+void debug_view_disasm::generate_bytes(offs_t pcbyte, int numbytes, int minbytes, char *string, int maxchars, bool encrypted)
+{
+ const debug_view_disasm_source &source = downcast<const debug_view_disasm_source &>(*m_source);
+
+ // output the first value
+ int offset = 0;
+ if (maxchars >= 2 * minbytes)
+ offset = sprintf(string, "%s", core_i64_hex_format(debug_read_opcode(source.m_space, pcbyte, minbytes, FALSE), minbytes * 2));
+
+ // output subsequent values
+ int byte;
+ for (byte = minbytes; byte < numbytes && offset + 1 + 2 * minbytes < maxchars; byte += minbytes)
+ offset += sprintf(&string[offset], " %s", core_i64_hex_format(debug_read_opcode(source.m_space, pcbyte + byte, minbytes, encrypted), minbytes * 2));
+
+ // if we ran out of room, indicate more
+ string[maxchars - 1] = 0;
+ if (byte < numbytes && maxchars > 3)
+ string[maxchars - 2] = string[maxchars - 3] = string[maxchars - 4] = '.';
+}
+
+
+//-------------------------------------------------
+// recompute - recompute selected info for the
+// disassembly view
+//-------------------------------------------------
+
+bool debug_view_disasm::recompute(offs_t pc, int startline, int lines)
+{
+ bool changed = false;
+ const debug_view_disasm_source &source = downcast<const debug_view_disasm_source &>(*m_source);
+
+ // determine how many characters we need for an address and set the divider
+ m_divider1 = 1 + source.m_space->logaddrchars() + 1;
+
+ // assume a fixed number of characters for the disassembly
+ m_divider2 = m_divider1 + 1 + m_dasm_width + 1;
+
+ // determine how many bytes we might need to display
+ int minbytes = source.m_disasmintf->min_opcode_bytes();
+ int maxbytes = source.m_disasmintf->max_opcode_bytes();
+
+ // ensure that the PC is aligned to the minimum opcode size
+ pc &= ~source.m_space->byte_to_address_end(minbytes - 1);
+
+ // set the width of the third column according to display mode
+ if (m_right_column == DASM_RIGHTCOL_RAW || m_right_column == DASM_RIGHTCOL_ENCRYPTED)
+ {
+ int maxbytes_clamped = MIN(maxbytes, DASM_MAX_BYTES);
+ m_total.x = m_divider2 + 1 + 2 * maxbytes_clamped + (maxbytes_clamped / minbytes - 1) + 1;
+ }
+ else if (m_right_column == DASM_RIGHTCOL_COMMENTS)
+ m_total.x = m_divider2 + 1 + 50; // DEBUG_COMMENT_MAX_LINE_LENGTH
+ else
+ m_total.x = m_divider2 + 1;
+
+ // reallocate memory if we don't have enough
+ if (m_allocated.x < m_total.x || m_allocated.y < m_total.y)
+ {
+ // update our values
+ m_allocated = m_total;
+
+ // allocate address array
+ auto_free(machine(), m_byteaddress);
+ m_byteaddress = auto_alloc_array(machine(), offs_t, m_allocated.y);
+
+ // allocate disassembly buffer
+ auto_free(machine(), m_dasm);
+ m_dasm = auto_alloc_array(machine(), char, m_allocated.x * m_allocated.y);
+ }
+
+ // iterate over lines
+ for (int line = 0; line < lines; line++)
+ {
+ // convert PC to a byte offset
+ offs_t pcbyte = source.m_space->address_to_byte(pc) & source.m_space->logbytemask();
+
+ // save a copy of the previous line as a backup if we're only doing one line
+ int instr = startline + line;
+ char *destbuf = &m_dasm[instr * m_allocated.x];
+ char oldbuf[100];
+ if (lines == 1)
+ strncpy(oldbuf, destbuf, MIN(sizeof(oldbuf), m_allocated.x));
+
+ // convert back and set the address of this instruction
+ m_byteaddress[instr] = pcbyte;
+ sprintf(&destbuf[0], " %s ", core_i64_hex_format(source.m_space->byte_to_address(pcbyte), source.m_space->logaddrchars()));
+
+ // make sure we can translate the address, and then disassemble the result
+ char buffer[100];
+ int numbytes = 0;
+ offs_t physpcbyte = pcbyte;
+ if (debug_cpu_translate(source.m_space, TRANSLATE_FETCH_DEBUG, &physpcbyte))
+ {
+ UINT8 opbuf[64], argbuf[64];
+
+ // fetch the bytes up to the maximum
+ for (numbytes = 0; numbytes < maxbytes; numbytes++)
+ {
+ opbuf[numbytes] = debug_read_opcode(source.m_space, pcbyte + numbytes, 1, FALSE);
+ argbuf[numbytes] = debug_read_opcode(source.m_space, pcbyte + numbytes, 1, TRUE);
+ }
+
+ // disassemble the result
+ pc += numbytes = source.m_device.debug()->disassemble(buffer, pc & source.m_space->logaddrmask(), opbuf, argbuf) & DASMFLAG_LENGTHMASK;
+ }
+ else
+ strcpy(buffer, "<unmapped>");
+
+ // append the disassembly to the buffer
+ sprintf(&destbuf[m_divider1 + 1], "%-*s ", m_dasm_width, buffer);
+
+ // output the right column
+ if (m_right_column == DASM_RIGHTCOL_RAW || m_right_column == DASM_RIGHTCOL_ENCRYPTED)
+ {
+ // get the bytes
+ numbytes = source.m_space->address_to_byte(numbytes) & source.m_space->logbytemask();
+ generate_bytes(pcbyte, numbytes, minbytes, &destbuf[m_divider2], m_allocated.x - m_divider2, m_right_column == DASM_RIGHTCOL_ENCRYPTED);
+ }
+ else if (m_right_column == DASM_RIGHTCOL_COMMENTS)
+ {
+ // get and add the comment, if present
+ offs_t comment_address = source.m_space->byte_to_address(m_byteaddress[instr]);
+ const char *text = source.m_device.debug()->comment_text(comment_address);
+ if (text != NULL)
+ sprintf(&destbuf[m_divider2], "// %.*s", m_allocated.x - m_divider2 - 1, text);
+ }
+
+ // see if the line changed at all
+ if (lines == 1 && strncmp(oldbuf, destbuf, MIN(sizeof(oldbuf), m_allocated.x)) != 0)
+ changed = true;
+ }
+
+ // update opcode base information
+ m_last_direct_decrypted = source.m_space->direct().decrypted();
+ m_last_direct_raw = source.m_space->direct().raw();
+ m_last_change_count = source.m_device.debug()->comment_change_count();
+
+ // now longer need to recompute
+ m_recompute = false;
+ return changed;
+}
+
+
+//-------------------------------------------------
+// view_update - update the contents of the
+// disassembly view
+//-------------------------------------------------
+
+void debug_view_disasm::view_update()
+{
+ const debug_view_disasm_source &source = downcast<const debug_view_disasm_source &>(*m_source);
+
+ offs_t pc = cpu_get_pc(&source.m_device);
+ offs_t pcbyte = source.m_space->address_to_byte(pc) & source.m_space->logbytemask();
+
+ // update our context; if the expression is dirty, recompute
+ if (m_expression.dirty())
+ m_recompute = true;
+
+ // if we're tracking a value, make sure it is visible
+ UINT64 previous = m_expression.last_value();
+ UINT64 result = m_expression.value();
+ if (result != previous)
+ {
+ offs_t resultbyte = source.m_space->address_to_byte(result) & source.m_space->logbytemask();
+
+ // see if the new result is an address we already have
+ UINT32 row;
+ for (row = 0; row < m_allocated.y; row++)
+ if (m_byteaddress[row] == resultbyte)
+ break;
+
+ // if we didn't find it, or if it's really close to the bottom, recompute
+ if (row == m_allocated.y || row >= m_total.y - m_visible.y)
+ m_recompute = true;
+
+ // otherwise, if it's not visible, adjust the view so it is
+ else if (row < m_topleft.y || row >= m_topleft.y + m_visible.y - 2)
+ m_topleft.y = (row > 3) ? row - 3 : 0;
+ }
+
+ // if the opcode base has changed, rework things
+ if (source.m_space->direct().decrypted() != m_last_direct_decrypted || source.m_space->direct().raw() != m_last_direct_raw)
+ m_recompute = true;
+
+ // if the comments have changed, redo it
+ if (m_last_change_count != source.m_device.debug()->comment_change_count())
+ m_recompute = true;
+
+ // if we need to recompute, do it
+ bool recomputed_this_time = false;
+recompute:
+ if (m_recompute)
+ {
+ // recompute the view
+ if (m_byteaddress != NULL && m_last_change_count != source.m_device.debug()->comment_change_count())
+ {
+ // smoosh us against the left column, but not the top row
+ m_topleft.x = 0;
+
+ // recompute from where we last recomputed!
+ recompute(source.m_space->byte_to_address(m_byteaddress[0]), 0, m_total.y);
+ }
+ else
+ {
+ // determine the addresses of what we will display
+ offs_t backpc = find_pc_backwards((UINT32)m_expression.value(), m_backwards_steps);
+
+ // put ourselves back in the top left
+ m_topleft.y = 0;
+ m_topleft.x = 0;
+
+ recompute(backpc, 0, m_total.y);
+ }
+ recomputed_this_time = true;
+ }
+
+ // figure out the row where the PC is and recompute the disassembly
+ if (pcbyte != m_last_pcbyte)
+ {
+ // find the row with the PC on it
+ for (UINT32 row = 0; row < m_visible.y; row++)
+ {
+ UINT32 effrow = m_topleft.y + row;
+ if (effrow >= m_allocated.y)
+ break;
+ if (pcbyte == m_byteaddress[effrow])
+ {
+ // see if we changed
+ bool changed = recompute(pc, effrow, 1);
+ if (changed && !recomputed_this_time)
+ {
+ m_recompute = true;
+ goto recompute;
+ }
+
+ // set the effective row and PC
+ m_cursor.y = effrow;
+ view_notify(VIEW_NOTIFY_CURSOR_CHANGED);
+ }
+ }
+ m_last_pcbyte = pcbyte;
+ }
+
+ // loop over visible rows
+ debug_view_char *dest = m_viewdata;
+ for (UINT32 row = 0; row < m_visible.y; row++)
+ {
+ UINT32 effrow = m_topleft.y + row;
+ UINT32 col = 0;
+
+ // if this visible row is valid, add it to the buffer
+ UINT8 attrib = DCA_NORMAL;
+ if (effrow < m_allocated.y)
+ {
+ // if we're on the line with the PC, recompute and hilight it
+ if (pcbyte == m_byteaddress[effrow])
+ attrib = DCA_CURRENT;
+
+ // if we're on a line with a breakpoint, tag it changed
+ else
+ {
+ for (device_debug::breakpoint *bp = source.m_device.debug()->breakpoint_first(); bp != NULL; bp = bp->next())
+ if (m_byteaddress[effrow] == (source.m_space->address_to_byte(bp->address()) & source.m_space->logbytemask()))
+ attrib = DCA_CHANGED;
+ }
+
+ // if we're on the active column and everything is couth, highlight it
+ if (m_cursor_visible && effrow == m_cursor.y)
+ attrib |= DCA_SELECTED;
+
+ // get the effective string
+ const char *data = &m_dasm[effrow * m_allocated.x];
+ UINT32 len = (UINT32)strlen(data);
+
+ // copy data
+ UINT32 effcol = m_topleft.x;
+ while (col < m_visible.x && effcol < len)
+ {
+ dest->byte = data[effcol++];
+ dest->attrib = (effcol <= m_divider1 || effcol >= m_divider2) ? (attrib | DCA_ANCILLARY) : attrib;
+
+ // comments are just green for now - maybe they shouldn't even be this?
+ if (effcol >= m_divider2 && m_right_column == DASM_RIGHTCOL_COMMENTS)
+ attrib |= DCA_COMMENT;
+
+ dest++;
+ col++;
+ }
+ }
+
+ // fill the rest with blanks
+ while (col < m_visible.x)
+ {
+ dest->byte = ' ';
+ dest->attrib = (effrow < m_total.y) ? (attrib | DCA_ANCILLARY) : attrib;
+ dest++;
+ col++;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// selected_address - return the PC of the
+// currently selected address in the view
+//-------------------------------------------------
+
+offs_t debug_view_disasm::selected_address()
+{
+ flush_updates();
+ return downcast<const debug_view_disasm_source &>(*m_source).m_space->byte_to_address(m_byteaddress[m_cursor.y]);
+}
+
+
+//-------------------------------------------------
+// set_sexpression - set the expression string
+// describing the home address
+//-------------------------------------------------
+
+void debug_view_disasm::set_expression(const char *expression)
+{
+ begin_update();
+ m_expression.set_string(expression);
+ m_recompute = m_update_pending = true;
+ end_update();
+}
+
+
+//-------------------------------------------------
+// set_right_column - set the contents of the
+// right column
+//-------------------------------------------------
+
+void debug_view_disasm::set_right_column(disasm_right_column contents)
+{
+ begin_update();
+ m_right_column = contents;
+ m_recompute = m_update_pending = true;
+ end_update();
+}
+
+
+//-------------------------------------------------
+// set_backward_steps - set the number of
+// instructions displayed before the home address
+//-------------------------------------------------
+
+void debug_view_disasm::set_backward_steps(UINT32 steps)
+{
+ begin_update();
+ m_backwards_steps = steps;
+ m_recompute = m_update_pending = true;
+ end_update();
+}
+
+
+//-------------------------------------------------
+// set_disasm_width - set the width in characters
+// of the main disassembly section
+//-------------------------------------------------
+
+void debug_view_disasm::set_disasm_width(UINT32 width)
+{
+ begin_update();
+ m_dasm_width = width;
+ m_recompute = m_update_pending = true;
+ end_update();
+}
+
+
+//-------------------------------------------------
+// set_selected_address - set the PC of the
+// currently selected address in the view
+//-------------------------------------------------
+
+void debug_view_disasm::set_selected_address(offs_t address)
+{
+ const debug_view_disasm_source &source = downcast<const debug_view_disasm_source &>(*m_source);
+ offs_t byteaddress = source.m_space->address_to_byte(address) & source.m_space->logbytemask();
+ for (int line = 0; line < m_total.y; line++)
+ if (m_byteaddress[line] == byteaddress)
+ {
+ m_cursor.y = line;
+ set_cursor_position(m_cursor);
+ break;
+ }
+}
diff --git a/trunk/src/emu/debug/dvdisasm.h b/trunk/src/emu/debug/dvdisasm.h
new file mode 100644
index 00000000000..a1cd81b008b
--- /dev/null
+++ b/trunk/src/emu/debug/dvdisasm.h
@@ -0,0 +1,146 @@
+/*********************************************************************
+
+ dvdisasm.h
+
+ Disassembly debugger view.
+
+****************************************************************************
+
+ 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.
+
+***************************************************************************/
+
+#ifndef __DVDISASM_H__
+#define __DVDISASM_H__
+
+#include "debugvw.h"
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// selections for what goes into the right-hand column
+enum disasm_right_column
+{
+ DASM_RIGHTCOL_NONE,
+ DASM_RIGHTCOL_RAW,
+ DASM_RIGHTCOL_ENCRYPTED,
+ DASM_RIGHTCOL_COMMENTS
+};
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// a disassembly view_source
+class debug_view_disasm_source : public debug_view_source
+{
+ friend class debug_view_disasm;
+
+ // construction/destruction
+ debug_view_disasm_source(const char *name, device_t &device);
+
+public:
+ // getters
+ device_t &device() const { return m_device; }
+ address_space *space() const { return m_space; }
+
+private:
+ // internal state
+ device_t & m_device; // underlying device
+ device_disasm_interface *m_disasmintf; // disassembly interface
+ address_space * m_space; // address space to display
+};
+
+
+// debug view for disassembly
+class debug_view_disasm : public debug_view
+{
+ friend resource_pool_object<debug_view_disasm>::~resource_pool_object();
+ friend class debug_view_manager;
+
+ // construction/destruction
+ debug_view_disasm(running_machine &machine, debug_view_osd_update_func osdupdate, void *osdprivate);
+ virtual ~debug_view_disasm();
+
+public:
+ // getters
+ const char *expression() const { return m_expression.string(); }
+ disasm_right_column right_column() const { return m_right_column; }
+ UINT32 backward_steps() const { return m_backwards_steps; }
+ UINT32 disasm_width() const { return m_dasm_width; }
+ offs_t selected_address();
+
+ // setters
+ void set_expression(const char *expression);
+ void set_right_column(disasm_right_column contents);
+ void set_backward_steps(UINT32 steps);
+ void set_disasm_width(UINT32 width);
+ void set_selected_address(offs_t address);
+
+protected:
+ // view overrides
+ virtual void view_update();
+ virtual void view_notify(debug_view_notification type);
+ virtual void view_char(int chval);
+
+private:
+ // internal helpers
+ void enumerate_sources();
+ offs_t find_pc_backwards(offs_t targetpc, int numinstrs);
+ void generate_bytes(offs_t pcbyte, int numbytes, int minbytes, char *string, int maxchars, bool encrypted);
+ bool recompute(offs_t pc, int startline, int lines);
+
+ // internal state
+ disasm_right_column m_right_column; // right column contents
+ UINT32 m_backwards_steps; // number of backwards steps
+ UINT32 m_dasm_width; // width of the disassembly area
+ UINT8 * m_last_direct_raw; // last direct raw value
+ UINT8 * m_last_direct_decrypted;// last direct decrypted value
+ UINT32 m_last_change_count; // last comment change count
+ offs_t m_last_pcbyte; // last PC byte value
+ int m_divider1, m_divider2; // left and right divider columns
+ int m_divider3; // comment divider column
+ debug_view_expression m_expression; // expression-related information
+ debug_view_xy m_allocated; // allocated rows/columns
+ offs_t * m_byteaddress; // addresses of the instructions
+ char * m_dasm; // disassembled instructions
+
+ // constants
+ static const int DEFAULT_DASM_LINES = 1000;
+ static const int DEFAULT_DASM_WIDTH = 50;
+ static const int DASM_MAX_BYTES = 16;
+};
+
+
+#endif
diff --git a/trunk/src/emu/debug/dvmemory.c b/trunk/src/emu/debug/dvmemory.c
new file mode 100644
index 00000000000..a1d4d88f9f8
--- /dev/null
+++ b/trunk/src/emu/debug/dvmemory.c
@@ -0,0 +1,815 @@
+/*********************************************************************
+
+ dvmemory.c
+
+ Memory debugger view.
+
+****************************************************************************
+
+ 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 "debugvw.h"
+#include "dvmemory.h"
+#include "debugcpu.h"
+#include <ctype.h>
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const debug_view_memory::memory_view_pos debug_view_memory::s_memory_pos_table[9] =
+{
+ /* 0 bytes per chunk: */ { 0, { 0 } },
+ /* 1 byte per chunk: 00 11 22 33 44 55 66 77 */ { 3, { 0x04, 0x00, 0x80 } },
+ /* 2 bytes per chunk: 0011 2233 4455 6677 */ { 6, { 0x8c, 0x0c, 0x08, 0x04, 0x00, 0x80 } },
+ /* 3 bytes per chunk: */ { 0, { 0 } },
+ /* 4 bytes per chunk: 00112233 44556677 */ { 12, { 0x9c, 0x9c, 0x1c, 0x18, 0x14, 0x10, 0x0c, 0x08, 0x04, 0x00, 0x80, 0x80 } },
+ /* 5 bytes per chunk: */ { 0, { 0 } },
+ /* 6 bytes per chunk: */ { 0, { 0 } },
+ /* 7 bytes per chunk: */ { 0, { 0 } },
+ /* 8 bytes per chunk: 0011223344556677 */ { 24, { 0xbc, 0xbc, 0xbc, 0xbc, 0x3c, 0x38, 0x34, 0x30, 0x2c, 0x28, 0x24, 0x20, 0x1c, 0x18, 0x14, 0x10, 0x0c, 0x08, 0x04, 0x00, 0x80, 0x80, 0x80, 0x80 } }
+};
+
+
+
+//**************************************************************************
+// DEBUG VIEW MEMORY SOURCE
+//**************************************************************************
+
+//-------------------------------------------------
+// debug_view_memory_source - constructors
+//-------------------------------------------------
+
+debug_view_memory_source::debug_view_memory_source(const char *name, address_space &space)
+ : debug_view_source(name, &space.device()),
+ m_space(&space),
+ m_memintf(dynamic_cast<device_memory_interface *>(&space.device())),
+ m_base(NULL),
+ m_length(0),
+ m_offsetxor(0),
+ m_endianness(space.endianness()),
+ m_prefsize(space.data_width() / 8)
+{
+}
+
+debug_view_memory_source::debug_view_memory_source(const char *name, const memory_region &region)
+ : debug_view_source(name),
+ m_space(NULL),
+ m_memintf(NULL),
+ m_base(region),
+ m_length(region.bytes()),
+ m_offsetxor(NATIVE_ENDIAN_VALUE_LE_BE(region.width() - 1, 0)),
+ m_endianness(region.endianness()),
+ m_prefsize(MIN(region.width(), 8))
+{
+}
+
+debug_view_memory_source::debug_view_memory_source(const char *name, void *base, int element_size, int num_elements)
+ : debug_view_source(name),
+ m_space(NULL),
+ m_memintf(NULL),
+ m_base(base),
+ m_length(element_size * num_elements),
+ m_offsetxor(0),
+ m_endianness(ENDIANNESS_NATIVE),
+ m_prefsize(MIN(element_size, 8))
+{
+}
+
+
+
+//**************************************************************************
+// DEBUG VIEW MEMORY
+//**************************************************************************
+
+//-------------------------------------------------
+// debug_view_memory - constructor
+//-------------------------------------------------
+
+debug_view_memory::debug_view_memory(running_machine &machine, debug_view_osd_update_func osdupdate, void *osdprivate)
+ : debug_view(machine, DVT_MEMORY, osdupdate, osdprivate),
+ m_expression(machine),
+ m_chunks_per_row(16),
+ m_bytes_per_chunk(1),
+ m_reverse_view(false),
+ m_ascii_view(true),
+ m_no_translation(false),
+ m_maxaddr(0),
+ m_bytes_per_row(16),
+ m_byte_offset(0)
+{
+ // fail if no available sources
+ enumerate_sources();
+ if (m_source_list.count() == 0)
+ throw std::bad_alloc();
+
+ // configure the view
+ m_supports_cursor = true;
+}
+
+
+//-------------------------------------------------
+// enumerate_sources - enumerate all possible
+// sources for a memory view
+//-------------------------------------------------
+
+void debug_view_memory::enumerate_sources()
+{
+ // start with an empty list
+ m_source_list.reset();
+ astring name;
+
+ // first add all the devices' address spaces
+ device_memory_interface *memintf = NULL;
+ for (bool gotone = machine().devicelist().first(memintf); gotone; gotone = memintf->next(memintf))
+ for (address_spacenum spacenum = AS_0; spacenum < ADDRESS_SPACES; spacenum++)
+ {
+ address_space *space = memintf->space(spacenum);
+ if (space != NULL)
+ {
+ name.printf("%s '%s' %s space memory", memintf->device().name(), memintf->device().tag(), space->name());
+ m_source_list.append(*auto_alloc(machine(), debug_view_memory_source(name, *space)));
+ }
+ }
+
+ // then add all the memory regions
+ for (const memory_region *region = machine().first_region(); region != NULL; region = region->next())
+ {
+ name.printf("Region '%s'", region->name());
+ m_source_list.append(*auto_alloc(machine(), debug_view_memory_source(name, *region)));
+ }
+
+ // finally add all global array symbols
+ for (int itemnum = 0; itemnum < 10000; itemnum++)
+ {
+ // stop when we run out of items
+ UINT32 valsize, valcount;
+ void *base;
+ const char *itemname = machine().save().indexed_item(itemnum, base, valsize, valcount);
+ if (itemname == NULL)
+ break;
+
+ // if this is a single-entry global, add it
+ if (valcount > 1 && strstr(itemname, "globals/"))
+ {
+ name.cpy(strrchr(itemname, '/') + 1);
+ m_source_list.append(*auto_alloc(machine(), debug_view_memory_source(name, base, valsize, valcount)));
+ }
+ }
+
+ // reset the source to a known good entry
+ set_source(*m_source_list.head());
+}
+
+
+//-------------------------------------------------
+// view_notify - handle notification of updates
+// to cursor changes
+//-------------------------------------------------
+
+void debug_view_memory::view_notify(debug_view_notification type)
+{
+ if (type == VIEW_NOTIFY_CURSOR_CHANGED)
+ {
+ // normalize the cursor
+ set_cursor_pos(get_cursor_pos());
+ }
+ else if (type == VIEW_NOTIFY_SOURCE_CHANGED)
+ {
+ // update for the new source
+ const debug_view_memory_source &source = downcast<const debug_view_memory_source &>(*m_source);
+ m_chunks_per_row = m_bytes_per_chunk * m_chunks_per_row / source.m_prefsize;
+ m_bytes_per_chunk = source.m_prefsize;
+ if (source.m_space != NULL)
+ m_expression.set_context(&source.m_space->device().debug()->symtable());
+ else
+ m_expression.set_context(NULL);
+ }
+}
+
+
+//-------------------------------------------------
+// view_update - update the contents of the
+// memory view
+//-------------------------------------------------
+
+void debug_view_memory::view_update()
+{
+ const debug_view_memory_source &source = downcast<const debug_view_memory_source &>(*m_source);
+
+ // if we need to recompute, do it now
+ if (needs_recompute())
+ recompute();
+
+ // get positional data
+ const memory_view_pos &posdata = s_memory_pos_table[m_bytes_per_chunk];
+
+ // loop over visible rows
+ for (UINT32 row = 0; row < m_visible.y; row++)
+ {
+ debug_view_char *destmin = m_viewdata + row * m_visible.x;
+ debug_view_char *destmax = destmin + m_visible.x;
+ debug_view_char *destrow = destmin - m_topleft.x;
+ UINT32 effrow = m_topleft.y + row;
+
+ // reset the line of data; section 1 is normal, others are ancillary, cursor is selected
+ debug_view_char *dest = destmin;
+ for (int ch = 0; ch < m_visible.x; ch++, dest++)
+ {
+ UINT32 effcol = m_topleft.x + ch;
+ dest->byte = ' ';
+ dest->attrib = DCA_ANCILLARY;
+ if (m_section[1].contains(effcol))
+ {
+ dest->attrib = DCA_NORMAL;
+ if (m_cursor_visible && effrow == m_cursor.y && effcol == m_cursor.x)
+ dest->attrib |= DCA_SELECTED;
+ }
+ }
+
+ // if this visible row is valid, add it to the buffer
+ if (effrow < m_total.y)
+ {
+ offs_t addrbyte = m_byte_offset + effrow * m_bytes_per_row;
+ offs_t address = (source.m_space != NULL) ? source.m_space->byte_to_address(addrbyte) : addrbyte;
+ char addrtext[20];
+
+ // generate the address
+ sprintf(addrtext, m_addrformat, address);
+ dest = destrow + m_section[0].m_pos + 1;
+ for (int ch = 0; addrtext[ch] != 0 && ch < m_section[0].m_width - 1; ch++, dest++)
+ if (dest >= destmin && dest < destmax)
+ dest->byte = addrtext[ch];
+
+ // generate the data
+ for (int chunknum = 0; chunknum < m_chunks_per_row; chunknum++)
+ {
+ int chunkindex = m_reverse_view ? (m_chunks_per_row - 1 - chunknum) : chunknum;
+
+ UINT64 chunkdata;
+ bool ismapped = read(m_bytes_per_chunk, addrbyte + chunknum * m_bytes_per_chunk, chunkdata);
+ dest = destrow + m_section[1].m_pos + 1 + chunkindex * posdata.m_spacing;
+ for (int ch = 0; ch < posdata.m_spacing; ch++, dest++)
+ if (dest >= destmin && dest < destmax)
+ {
+ UINT8 shift = posdata.m_shift[ch];
+ if (shift < 64)
+ dest->byte = ismapped ? "0123456789ABCDEF"[(chunkdata >> shift) & 0x0f] : '*';
+ }
+ }
+
+ // generate the ASCII data
+ if (m_section[2].m_width > 0)
+ {
+ dest = destrow + m_section[2].m_pos + 1;
+ for (int ch = 0; ch < m_bytes_per_row; ch++, dest++)
+ if (dest >= destmin && dest < destmax)
+ {
+ UINT64 chval;
+ bool ismapped = read(1, addrbyte + ch, chval);
+ dest->byte = (ismapped && isprint(chval)) ? chval : '.';
+ }
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// view_char - handle a character typed within
+// the current view
+//-------------------------------------------------
+
+void debug_view_memory::view_char(int chval)
+{
+ // get the position
+ cursor_pos pos = get_cursor_pos();
+
+ // handle the incoming key
+ switch (chval)
+ {
+ case DCH_UP:
+ if (pos.m_address >= m_byte_offset + m_bytes_per_row)
+ pos.m_address -= m_bytes_per_row;
+ break;
+
+ case DCH_DOWN:
+ if (pos.m_address <= m_maxaddr - m_bytes_per_row)
+ pos.m_address += m_bytes_per_row;
+ break;
+
+ case DCH_PUP:
+ for (UINT32 delta = (m_visible.y - 2) * m_bytes_per_row; delta > 0; delta -= m_bytes_per_row)
+ if (pos.m_address >= m_byte_offset + delta)
+ {
+ pos.m_address -= delta;
+ break;
+ }
+ break;
+
+ case DCH_PDOWN:
+ for (UINT32 delta = (m_visible.y - 2) * m_bytes_per_row; delta > 0; delta -= m_bytes_per_row)
+ if (pos.m_address <= m_maxaddr - delta)
+ {
+ pos.m_address += delta;
+ break;
+ }
+ break;
+
+ case DCH_HOME:
+ pos.m_address -= pos.m_address % m_bytes_per_row;
+ pos.m_shift = (m_bytes_per_chunk * 8) - 4;
+ break;
+
+ case DCH_CTRLHOME:
+ pos.m_address = m_byte_offset;
+ pos.m_shift = (m_bytes_per_chunk * 8) - 4;
+ break;
+
+ case DCH_END:
+ pos.m_address += (m_bytes_per_row - (pos.m_address % m_bytes_per_row) - 1);
+ pos.m_shift = 0;
+ break;
+
+ case DCH_CTRLEND:
+ pos.m_address = m_maxaddr;
+ pos.m_shift = 0;
+ break;
+
+ case DCH_CTRLLEFT:
+ if (pos.m_address >= m_byte_offset + m_bytes_per_chunk)
+ pos.m_address -= m_bytes_per_chunk;
+ break;
+
+ case DCH_CTRLRIGHT:
+ if (pos.m_address <= m_maxaddr - m_bytes_per_chunk)
+ pos.m_address += m_bytes_per_chunk;
+ break;
+
+ default:
+ {
+ static const char hexvals[] = "0123456789abcdef";
+ char *hexchar = (char *)strchr(hexvals, tolower(chval));
+ if (hexchar == NULL)
+ break;
+
+ UINT64 data;
+ bool ismapped = read(m_bytes_per_chunk, pos.m_address, data);
+ if (!ismapped)
+ break;
+
+ data &= ~((UINT64)0x0f << pos.m_shift);
+ data |= (UINT64)(hexchar - hexvals) << pos.m_shift;
+ write(m_bytes_per_chunk, pos.m_address, data);
+ // fall through...
+ }
+
+ case DCH_RIGHT:
+ if (pos.m_shift == 0 && pos.m_address != m_maxaddr)
+ {
+ pos.m_shift = m_bytes_per_chunk * 8 - 4;
+ pos.m_address += m_bytes_per_chunk;
+ }
+ else
+ pos.m_shift -= 4;
+ break;
+
+ case DCH_LEFT:
+ if (pos.m_shift == m_bytes_per_chunk * 8 - 4 && pos.m_address != m_byte_offset)
+ {
+ pos.m_shift = 0;
+ pos.m_address -= m_bytes_per_chunk;
+ }
+ else
+ pos.m_shift += 4;
+ break;
+ }
+
+ // set a new position
+ begin_update();
+ set_cursor_pos(pos);
+ m_update_pending = true;
+ end_update();
+}
+
+
+//-------------------------------------------------
+// recompute - recompute the internal data and
+// structure of the memory view
+//-------------------------------------------------
+
+void debug_view_memory::recompute()
+{
+ const debug_view_memory_source &source = downcast<const debug_view_memory_source &>(*m_source);
+
+ // get the current cursor position
+ cursor_pos pos = get_cursor_pos();
+
+ // determine the maximum address and address format string from the raw information
+ int addrchars;
+ if (source.m_space != NULL)
+ {
+ m_maxaddr = m_no_translation ? source.m_space->bytemask() : source.m_space->logbytemask();
+ addrchars = m_no_translation ? source.m_space->addrchars() : source.m_space->logaddrchars();
+ }
+ else
+ {
+ m_maxaddr = source.m_length - 1;
+ addrchars = m_addrformat.printf("%X", m_maxaddr);
+ }
+
+ // generate an 8-byte aligned format for the address
+ if (!m_reverse_view)
+ m_addrformat.printf("%*s%%0%dX", 8 - addrchars, "", addrchars);
+ else
+ m_addrformat.printf("%%0%dX%*s", addrchars, 8 - addrchars, "");
+
+ // if we are viewing a space with a minimum chunk size, clamp the bytes per chunk
+ if (source.m_space != NULL && source.m_space->byte_to_address(1) > 1)
+ {
+ UINT32 min_bytes_per_chunk = source.m_space->byte_to_address(1);
+ while (m_bytes_per_chunk < min_bytes_per_chunk)
+ {
+ m_bytes_per_chunk *= 2;
+ m_chunks_per_row /= 2;
+ }
+ m_chunks_per_row = MAX(1, m_chunks_per_row);
+ }
+
+ // recompute the byte offset based on the most recent expression result
+ m_bytes_per_row = m_bytes_per_chunk * m_chunks_per_row;
+ m_byte_offset = m_expression.value() % m_bytes_per_row;
+
+ // compute the section widths
+ m_section[0].m_width = 1 + 8 + 1;
+ m_section[1].m_width = 1 + 3 * m_bytes_per_row + 1;
+ m_section[2].m_width = m_ascii_view ? (1 + m_bytes_per_row + 1) : 0;
+
+ // compute the section positions
+ if (!m_reverse_view)
+ {
+ m_section[0].m_pos = 0;
+ m_section[1].m_pos = m_section[0].m_pos + m_section[0].m_width;
+ m_section[2].m_pos = m_section[1].m_pos + m_section[1].m_width;
+ m_total.x = m_section[2].m_pos + m_section[2].m_width;
+ }
+ else
+ {
+ m_section[2].m_pos = 0;
+ m_section[1].m_pos = m_section[2].m_pos + m_section[2].m_width;
+ m_section[0].m_pos = m_section[1].m_pos + m_section[1].m_width;
+ m_total.x = m_section[0].m_pos + m_section[0].m_width;
+ }
+
+ // derive total sizes from that
+ m_total.y = ((UINT64)m_maxaddr - (UINT64)m_byte_offset + (UINT64)m_bytes_per_row - 1) / m_bytes_per_row;
+
+ // reset the current cursor position
+ set_cursor_pos(pos);
+}
+
+
+//-------------------------------------------------
+// needs_recompute - determine if anything has
+// changed that requires a recomputation
+//-------------------------------------------------
+
+bool debug_view_memory::needs_recompute()
+{
+ bool recompute = m_recompute;
+
+ // handle expression changes
+ if (m_expression.dirty())
+ {
+ recompute = true;
+ m_topleft.y = (m_expression.value() - m_byte_offset) / m_bytes_per_row;
+ m_topleft.y = MAX(m_topleft.y, 0);
+ m_topleft.y = MIN(m_topleft.y, m_total.y - 1);
+
+ const debug_view_memory_source &source = downcast<const debug_view_memory_source &>(*m_source);
+ offs_t resultbyte;
+ if (source.m_space != NULL)
+ resultbyte = source.m_space->address_to_byte(m_expression.value()) & source.m_space->logbytemask();
+ else
+ resultbyte = m_expression.value();
+
+ set_cursor_pos(cursor_pos(resultbyte, m_bytes_per_chunk * 8 - 4));
+ }
+
+ // expression is clean at this point, and future recomputation is not necessary
+ m_recompute = false;
+ return recompute;
+}
+
+
+//-------------------------------------------------
+// get_cursor_pos - return the cursor position as
+// an address and a shift value
+//-------------------------------------------------
+
+debug_view_memory::cursor_pos debug_view_memory::get_cursor_pos()
+{
+ // start with the base address for this row
+ cursor_pos pos;
+ pos.m_address = m_byte_offset + m_cursor.y * m_bytes_per_chunk * m_chunks_per_row;
+
+ // determine the X position within the middle section, clamping as necessary
+ const memory_view_pos &posdata = s_memory_pos_table[m_bytes_per_chunk];
+ int xposition = m_cursor.x - m_section[1].m_pos - 1;
+ if (xposition < 0)
+ xposition = 0;
+ else if (xposition >= posdata.m_spacing * m_chunks_per_row)
+ xposition = posdata.m_spacing * m_chunks_per_row - 1;
+
+ // compute chunk number and offset within that chunk
+ int chunknum = xposition / posdata.m_spacing;
+ int chunkoffs = xposition % posdata.m_spacing;
+
+ // reverse the chunknum if we're reversed
+ if (m_reverse_view)
+ chunknum = m_chunks_per_row - 1 - chunknum;
+
+ // compute the address and shift
+ pos.m_address += chunknum * m_bytes_per_chunk;
+ pos.m_shift = posdata.m_shift[chunkoffs] & 0x7f;
+ return pos;
+}
+
+
+//-------------------------------------------------
+// set_cursor_pos - set the cursor position as a
+// function of an address and a shift value
+//-------------------------------------------------
+
+void debug_view_memory::set_cursor_pos(cursor_pos pos)
+{
+ const memory_view_pos &posdata = s_memory_pos_table[m_bytes_per_chunk];
+
+ // offset the address by the byte offset
+ if (pos.m_address < m_byte_offset)
+ pos.m_address = m_byte_offset;
+ pos.m_address -= m_byte_offset;
+
+ // compute the Y coordinate and chunk index
+ m_cursor.y = pos.m_address / m_bytes_per_row;
+ int chunknum = (pos.m_address % m_bytes_per_row) / m_bytes_per_chunk;
+
+ // reverse the chunknum if we're reversed
+ if (m_reverse_view)
+ chunknum = m_chunks_per_row - 1 - chunknum;
+
+ // scan within the chunk to find the shift
+ for (m_cursor.x = 0; m_cursor.x < posdata.m_spacing; m_cursor.x++)
+ if (posdata.m_shift[m_cursor.x] == pos.m_shift)
+ break;
+
+ // add in the chunk offset and shift to the right of divider1
+ m_cursor.x += m_section[1].m_pos + 1 + posdata.m_spacing * chunknum;
+
+ // clamp to the window bounds
+ m_cursor.x = MIN(m_cursor.x, m_total.x);
+ m_cursor.y = MIN(m_cursor.y, m_total.y);
+
+ // scroll if out of range
+ adjust_visible_x_for_cursor();
+ adjust_visible_y_for_cursor();
+}
+
+
+//-------------------------------------------------
+// read - generic memory view data reader
+//-------------------------------------------------
+
+bool debug_view_memory::read(UINT8 size, offs_t offs, UINT64 &data)
+{
+ const debug_view_memory_source &source = downcast<const debug_view_memory_source &>(*m_source);
+
+ // if no raw data, just use the standard debug routines
+ if (source.m_space != NULL)
+ {
+ offs_t dummyaddr = offs;
+
+ bool ismapped = m_no_translation ? true : source.m_memintf->translate(source.m_space->spacenum(), TRANSLATE_READ_DEBUG, dummyaddr);
+ data = ~(UINT64)0;
+ if (ismapped)
+ {
+ switch (size)
+ {
+ case 1: data = debug_read_byte(source.m_space, offs, !m_no_translation); break;
+ case 2: data = debug_read_word(source.m_space, offs, !m_no_translation); break;
+ case 4: data = debug_read_dword(source.m_space, offs, !m_no_translation); break;
+ case 8: data = debug_read_qword(source.m_space, offs, !m_no_translation); break;
+ }
+ }
+ return ismapped;
+ }
+
+ // if larger than a byte, reduce by half and recurse
+ if (size > 1)
+ {
+ size /= 2;
+
+ UINT64 data0, data1;
+ bool ismapped = read(size, offs + 0 * size, data0);
+ ismapped |= read(size, offs + 1 * size, data1);
+
+ if (source.m_endianness == ENDIANNESS_LITTLE)
+ data = data0 | (data1 << (size * 8));
+ else
+ data = data1 | (data0 << (size * 8));
+ return ismapped;
+ }
+
+ // all 0xff if out of bounds
+ offs ^= source.m_offsetxor;
+ if (offs >= source.m_length)
+ return false;
+ data = *((UINT8 *)source.m_base + offs);
+ return true;
+}
+
+
+//-------------------------------------------------
+// write - generic memory view data writer
+//-------------------------------------------------
+
+void debug_view_memory::write(UINT8 size, offs_t offs, UINT64 data)
+{
+ const debug_view_memory_source &source = downcast<const debug_view_memory_source &>(*m_source);
+
+ // if no raw data, just use the standard debug routines
+ if (source.m_space != NULL)
+ {
+ switch (size)
+ {
+ case 1: debug_write_byte(source.m_space, offs, data, !m_no_translation); break;
+ case 2: debug_write_word(source.m_space, offs, data, !m_no_translation); break;
+ case 4: debug_write_dword(source.m_space, offs, data, !m_no_translation); break;
+ case 8: debug_write_qword(source.m_space, offs, data, !m_no_translation); break;
+ }
+ return;
+ }
+
+ // if larger than a byte, reduce by half and recurse
+ if (size > 1)
+ {
+ size /= 2;
+ if (source.m_endianness == ENDIANNESS_LITTLE)
+ {
+ write(size, offs + 0 * size, data);
+ write(size, offs + 1 * size, data >> (8 * size));
+ }
+ else
+ {
+ write(size, offs + 1 * size, data);
+ write(size, offs + 0 * size, data >> (8 * size));
+ }
+ return;
+ }
+
+ // ignore if out of bounds
+ offs ^= source.m_offsetxor;
+ if (offs >= source.m_length)
+ return;
+ *((UINT8 *)source.m_base + offs) = data;
+
+// hack for FD1094 editing
+#ifdef FD1094_HACK
+ if (source.m_base == machine().region("user2"))
+ {
+ extern void fd1094_regenerate_key(running_machine &machine);
+ fd1094_regenerate_key(machine());
+ }
+#endif
+}
+
+
+//-------------------------------------------------
+// set_expression - set the expression string
+// describing the home address
+//-------------------------------------------------
+
+void debug_view_memory::set_expression(const char *expression)
+{
+ begin_update();
+ m_expression.set_string(expression);
+ m_recompute = m_update_pending = true;
+ end_update();
+}
+
+
+//-------------------------------------------------
+// set_bytes_per_chunk - specify the number of
+// bytes displayed per chunk
+//-------------------------------------------------
+
+void debug_view_memory::set_bytes_per_chunk(UINT8 chunkbytes)
+{
+ const debug_view_memory_source &source = downcast<const debug_view_memory_source &>(*m_source);
+
+ cursor_pos pos = begin_update_and_get_cursor_pos();
+ pos.m_address += (pos.m_shift / 8) ^ ((source.m_endianness == ENDIANNESS_LITTLE) ? 0 : (m_bytes_per_chunk - 1));
+ pos.m_shift %= 8;
+
+ m_bytes_per_chunk = chunkbytes;
+ m_chunks_per_row = m_bytes_per_row / chunkbytes;
+ m_recompute = m_update_pending = true;
+
+ pos.m_shift += 8 * ((pos.m_address % m_bytes_per_chunk) ^ ((source.m_endianness == ENDIANNESS_LITTLE) ? 0 : (m_bytes_per_chunk - 1)));
+ pos.m_address -= pos.m_address % m_bytes_per_chunk;
+
+ m_recompute = m_update_pending = true;
+ end_update_and_set_cursor_pos(pos);
+}
+
+
+//-------------------------------------------------
+// set_chunks_per_row - specify the number of
+// chunks displayed across a row
+//-------------------------------------------------
+
+void debug_view_memory::set_chunks_per_row(UINT32 rowchunks)
+{
+ if (rowchunks < 1)
+ return;
+
+ cursor_pos pos = begin_update_and_get_cursor_pos();
+ m_chunks_per_row = rowchunks;
+ m_recompute = m_update_pending = true;
+ end_update_and_set_cursor_pos(pos);
+}
+
+
+//-------------------------------------------------
+// set_reverse - specify true if the memory view
+// is displayed reverse
+//-------------------------------------------------
+
+void debug_view_memory::set_reverse(bool reverse)
+{
+ cursor_pos pos = begin_update_and_get_cursor_pos();
+ m_reverse_view = reverse;
+ m_recompute = m_update_pending = true;
+ end_update_and_set_cursor_pos(pos);
+}
+
+
+//-------------------------------------------------
+// set_ascii - specify TRUE if the memory view
+// should display an ASCII representation
+//-------------------------------------------------
+
+void debug_view_memory::set_ascii(bool ascii)
+{
+ cursor_pos pos = begin_update_and_get_cursor_pos();
+ m_ascii_view = ascii;
+ m_recompute = m_update_pending = true;
+ end_update_and_set_cursor_pos(pos);
+}
+
+
+//-------------------------------------------------
+// set_physical - specify true if the memory view
+// should display physical addresses versus
+// logical addresses
+//-------------------------------------------------
+
+void debug_view_memory::set_physical(bool physical)
+{
+ cursor_pos pos = begin_update_and_get_cursor_pos();
+ m_no_translation = physical;
+ m_recompute = m_update_pending = true;
+ end_update_and_set_cursor_pos(pos);
+}
diff --git a/trunk/src/emu/debug/dvmemory.h b/trunk/src/emu/debug/dvmemory.h
new file mode 100644
index 00000000000..147b63a0fa7
--- /dev/null
+++ b/trunk/src/emu/debug/dvmemory.h
@@ -0,0 +1,160 @@
+/*********************************************************************
+
+ dvmemory.h
+
+ Memory debugger view.
+
+****************************************************************************
+
+ 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.
+
+***************************************************************************/
+
+#ifndef __DVMEMORY_H__
+#define __DVMEMORY_H__
+
+#include "dvstate.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// a memory view_source
+class debug_view_memory_source : public debug_view_source
+{
+ friend class debug_view_memory;
+
+ debug_view_memory_source(const char *name, address_space &space);
+ debug_view_memory_source(const char *name, const memory_region &region);
+ debug_view_memory_source(const char *name, void *base, int element_size, int num_elements);
+
+public:
+ address_space *space() const { return m_space; }
+
+private:
+ address_space *m_space; // address space we reference (if any)
+ device_memory_interface *m_memintf; // pointer to the memory interface of the device
+ void * m_base; // pointer to memory base
+ offs_t m_length; // length of memory
+ offs_t m_offsetxor; // XOR to apply to offsets
+ endianness_t m_endianness; // endianness of memory
+ UINT8 m_prefsize; // preferred bytes per chunk
+};
+
+
+// debug view for memory
+class debug_view_memory : public debug_view
+{
+ friend resource_pool_object<debug_view_memory>::~resource_pool_object();
+ friend class debug_view_manager;
+
+ // construction/destruction
+ debug_view_memory(running_machine &machine, debug_view_osd_update_func osdupdate, void *osdprivate);
+
+public:
+ // getters
+ const char *expression() { return m_expression.string(); }
+ UINT8 bytes_per_chunk() { flush_updates(); return m_bytes_per_chunk; }
+ UINT8 chunks_per_row() { flush_updates(); return m_chunks_per_row; }
+ bool reverse() const { return m_reverse_view; }
+ bool ascii() const { return m_ascii_view; }
+ bool physical() const { return m_no_translation; }
+
+ // setters
+ void set_expression(const char *expression);
+ void set_bytes_per_chunk(UINT8 chunkbytes);
+ void set_chunks_per_row(UINT32 rowchunks);
+ void set_reverse(bool reverse);
+ void set_ascii(bool reverse);
+ void set_physical(bool physical);
+
+protected:
+ // view overrides
+ virtual void view_notify(debug_view_notification type);
+ virtual void view_update();
+ virtual void view_char(int chval);
+
+private:
+ struct cursor_pos
+ {
+ cursor_pos(offs_t address = 0, UINT8 shift = 0) : m_address(address), m_shift(shift) { }
+ offs_t m_address;
+ UINT8 m_shift;
+ };
+
+ // internal helpers
+ void enumerate_sources();
+ void recompute();
+ bool needs_recompute();
+
+ // cursor position management
+ cursor_pos get_cursor_pos();
+ void set_cursor_pos(cursor_pos pos);
+ cursor_pos begin_update_and_get_cursor_pos() { begin_update(); return get_cursor_pos(); }
+ void end_update_and_set_cursor_pos(cursor_pos pos) { set_cursor_pos(pos); end_update(); }
+
+ // memory access
+ bool read(UINT8 size, offs_t offs, UINT64 &data);
+ void write(UINT8 size, offs_t offs, UINT64 data);
+
+ // internal state
+ debug_view_expression m_expression; // expression describing the start address
+ UINT32 m_chunks_per_row; // number of chunks displayed per line
+ UINT8 m_bytes_per_chunk; // bytes per chunk
+ bool m_reverse_view; // reverse-endian view?
+ bool m_ascii_view; // display ASCII characters?
+ bool m_no_translation; // don't run addresses through the cpu translation hook
+ offs_t m_maxaddr; // (derived) maximum address to display
+ UINT32 m_bytes_per_row; // (derived) number of bytes displayed per line
+ UINT32 m_byte_offset; // (derived) offset of starting visible byte
+ astring m_addrformat; // (derived) format string to use to print addresses
+
+ struct section
+ {
+ bool contains(int x) const { return x >= m_pos && x < m_pos + m_width; }
+ INT32 m_pos; /* starting position */
+ INT32 m_width; /* width of this section */
+ };
+ section m_section[3]; // (derived) 3 sections to manage
+
+ struct memory_view_pos
+ {
+ UINT8 m_spacing; /* spacing between each entry */
+ UINT8 m_shift[24]; /* shift for each character */
+ };
+ static const memory_view_pos s_memory_pos_table[9]; // table for rendering at different chunk sizes
+
+ // constants
+ static const int MEM_MAX_LINE_WIDTH = 1024;
+};
+
+
+#endif
diff --git a/trunk/src/emu/debug/dvstate.c b/trunk/src/emu/debug/dvstate.c
new file mode 100644
index 00000000000..9d14f1c83d8
--- /dev/null
+++ b/trunk/src/emu/debug/dvstate.c
@@ -0,0 +1,370 @@
+/*********************************************************************
+
+ dvstate.c
+
+ State debugger view.
+
+****************************************************************************
+
+ 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 "debugvw.h"
+#include "dvstate.h"
+
+
+
+//**************************************************************************
+// DEBUG VIEW STATE SOURCE
+//**************************************************************************
+
+//-------------------------------------------------
+// debug_view_state_source - constructor
+//-------------------------------------------------
+
+debug_view_state_source::debug_view_state_source(const char *name, device_t &device)
+ : debug_view_source(name, &device),
+ m_device(device),
+ m_stateintf(dynamic_cast<device_state_interface *>(&device)),
+ m_execintf(dynamic_cast<device_execute_interface *>(&device))
+{
+}
+
+
+
+//**************************************************************************
+// DEBUG VIEW STATE
+//**************************************************************************
+
+//-------------------------------------------------
+// debug_view_state - constructor
+//-------------------------------------------------
+
+debug_view_state::debug_view_state(running_machine &machine, debug_view_osd_update_func osdupdate, void *osdprivate)
+ : debug_view(machine, DVT_STATE, osdupdate, osdprivate),
+ m_divider(0),
+ m_last_update(0),
+ m_state_list(NULL)
+{
+ // fail if no available sources
+ enumerate_sources();
+ if (m_source_list.count() == 0)
+ throw std::bad_alloc();
+}
+
+
+//-------------------------------------------------
+// ~debug_view_state - destructor
+//-------------------------------------------------
+
+debug_view_state::~debug_view_state()
+{
+ reset();
+}
+
+
+//-------------------------------------------------
+// enumerate_sources - enumerate all possible
+// sources for a registers view
+//-------------------------------------------------
+
+void debug_view_state::enumerate_sources()
+{
+ // start with an empty list
+ m_source_list.reset();
+
+ // iterate over devices that have state interfaces
+ device_state_interface *state = NULL;
+ astring name;
+ for (bool gotone = machine().devicelist().first(state); gotone; gotone = state->next(state))
+ {
+ name.printf("%s '%s'", state->device().name(), state->device().tag());
+ m_source_list.append(*auto_alloc(machine(), debug_view_state_source(name, state->device())));
+ }
+
+ // reset the source to a known good entry
+ set_source(*m_source_list.head());
+}
+
+
+//-------------------------------------------------
+// reset - delete all of our state items
+//-------------------------------------------------
+
+void debug_view_state::reset()
+{
+ // free all items in the state list
+ while (m_state_list != NULL)
+ {
+ state_item *oldhead = m_state_list;
+ m_state_list = oldhead->m_next;
+ auto_free(machine(), oldhead);
+ }
+}
+
+
+//-------------------------------------------------
+// recompute - recompute all info for the
+// registers view
+//-------------------------------------------------
+
+void debug_view_state::recompute()
+{
+ const debug_view_state_source &source = downcast<const debug_view_state_source &>(*m_source);
+
+ // start with a blank list
+ reset();
+
+ // add a cycles entry: cycles:99999999
+ state_item **tailptr = &m_state_list;
+ *tailptr = auto_alloc(machine(), state_item(REG_CYCLES, "cycles", 8));
+ tailptr = &(*tailptr)->m_next;
+
+ // add a beam entry: beamx:1234
+ *tailptr = auto_alloc(machine(), state_item(REG_BEAMX, "beamx", 4));
+ tailptr = &(*tailptr)->m_next;
+
+ // add a beam entry: beamy:5678
+ *tailptr = auto_alloc(machine(), state_item(REG_BEAMY, "beamy", 4));
+ tailptr = &(*tailptr)->m_next;
+
+ // add a beam entry: frame:123456
+ *tailptr = auto_alloc(machine(), state_item(REG_FRAME, "frame", 6));
+ tailptr = &(*tailptr)->m_next;
+
+ // add a flags entry: flags:xxxxxxxx
+ *tailptr = auto_alloc(machine(), state_item(STATE_GENFLAGS, "flags", source.m_stateintf->state_string_max_length(STATE_GENFLAGS)));
+ tailptr = &(*tailptr)->m_next;
+
+ // add a divider entry
+ *tailptr = auto_alloc(machine(), state_item(REG_DIVIDER, "", 0));
+ tailptr = &(*tailptr)->m_next;
+
+ // add all registers into it
+ for (const device_state_entry *entry = source.m_stateintf->state_first(); entry != NULL; entry = entry->next())
+ if (entry->visible())
+ {
+ *tailptr = auto_alloc(machine(), state_item(entry->index(), entry->symbol(), source.m_stateintf->state_string_max_length(entry->index())));
+ tailptr = &(*tailptr)->m_next;
+ }
+
+ // count the entries and determine the maximum tag and value sizes
+ int count = 0;
+ int maxtaglen = 0;
+ int maxvallen = 0;
+ for (state_item *item = m_state_list; item != NULL; item = item->m_next)
+ {
+ count++;
+ maxtaglen = MAX(maxtaglen, item->m_symbol.len());
+ maxvallen = MAX(maxvallen, item->m_vallen);
+ }
+
+ // set the current divider and total cols
+ m_divider = 1 + maxtaglen + 1;
+ m_total.x = 1 + maxtaglen + 2 + maxvallen + 1;
+ m_total.y = count;
+ m_topleft.x = 0;
+ m_topleft.y = 0;
+
+ // no longer need to recompute
+ m_recompute = false;
+}
+
+
+//-------------------------------------------------
+// view_notify - handle notification of updates
+// to cursor changes
+//-------------------------------------------------
+
+void debug_view_state::view_notify(debug_view_notification type)
+{
+ if (type == VIEW_NOTIFY_SOURCE_CHANGED)
+ m_recompute = true;
+}
+
+
+//-------------------------------------------------
+// view_update - update the contents of the
+// register view
+//-------------------------------------------------
+
+void debug_view_state::view_update()
+{
+ // if our assumptions changed, revisit them
+ if (m_recompute)
+ recompute();
+
+ // get cycle count if we have an execute interface
+ const debug_view_state_source &source = downcast<const debug_view_state_source &>(*m_source);
+ UINT64 total_cycles = 0;
+ if (source.m_execintf != NULL)
+ total_cycles = source.m_execintf->total_cycles();
+
+ // find the first entry
+ state_item *curitem = m_state_list;
+ for (int index = 0; curitem != NULL && index < m_topleft.y; index++)
+ curitem = curitem->m_next;
+
+ // loop over visible rows
+ screen_device *screen = machine().primary_screen;
+ debug_view_char *dest = m_viewdata;
+ for (UINT32 row = 0; row < m_visible.y; row++)
+ {
+ UINT32 col = 0;
+
+ // if this visible row is valid, add it to the buffer
+ if (curitem != NULL)
+ {
+ UINT32 effcol = m_topleft.x;
+ UINT8 attrib = DCA_NORMAL;
+ UINT32 len = 0;
+ astring valstr;
+
+ // get the effective string
+ if (curitem->m_index >= REG_FRAME && curitem->m_index <= REG_DIVIDER)
+ {
+ curitem->m_lastval = curitem->m_currval;
+ switch (curitem->m_index)
+ {
+ case REG_DIVIDER:
+ curitem->m_vallen = 0;
+ curitem->m_symbol.reset();
+ for (int i = 0; i < m_total.x; i++)
+ curitem->m_symbol.cat("-");
+ break;
+
+ case REG_CYCLES:
+ if (source.m_execintf != NULL)
+ {
+ curitem->m_currval = source.m_execintf->cycles_remaining();
+ valstr.printf("%-8d", (UINT32)curitem->m_currval);
+ }
+ break;
+
+ case REG_BEAMX:
+ if (screen != NULL)
+ {
+ curitem->m_currval = screen->hpos();
+ valstr.printf("%4d", (UINT32)curitem->m_currval);
+ }
+ break;
+
+ case REG_BEAMY:
+ if (screen != NULL)
+ {
+ curitem->m_currval = screen->vpos();
+ valstr.printf("%4d", (UINT32)curitem->m_currval);
+ }
+ break;
+
+ case REG_FRAME:
+ if (screen != NULL)
+ {
+ curitem->m_currval = screen->frame_number();
+ valstr.printf("%6d", (UINT32)curitem->m_currval);
+ }
+ break;
+ }
+ }
+ else
+ {
+ if (m_last_update != total_cycles)
+ curitem->m_lastval = curitem->m_currval;
+ curitem->m_currval = source.m_stateintf->state(curitem->m_index);
+ source.m_stateintf->state_string(curitem->m_index, valstr);
+ }
+
+ // see if we changed
+ if (curitem->m_lastval != curitem->m_currval)
+ attrib = DCA_CHANGED;
+
+ // build up a string
+ char temp[256];
+ if (curitem->m_symbol.len() < m_divider - 1)
+ {
+ memset(&temp[len], ' ', m_divider - 1 - curitem->m_symbol.len());
+ len += m_divider - 1 - curitem->m_symbol.len();
+ }
+
+ memcpy(&temp[len], curitem->m_symbol.cstr(), curitem->m_symbol.len());
+ len += curitem->m_symbol.len();
+
+ temp[len++] = ' ';
+ temp[len++] = ' ';
+
+ memcpy(&temp[len], valstr.cstr(), curitem->m_vallen);
+ len += curitem->m_vallen;
+
+ temp[len++] = ' ';
+ temp[len] = 0;
+
+ // copy data
+ while (col < m_visible.x && effcol < len)
+ {
+ dest->byte = temp[effcol++];
+ dest->attrib = attrib | ((effcol <= m_divider) ? DCA_ANCILLARY : DCA_NORMAL);
+ dest++;
+ col++;
+ }
+
+ // advance to the next item
+ curitem = curitem->m_next;
+ }
+
+ // fill the rest with blanks
+ while (col < m_visible.x)
+ {
+ dest->byte = ' ';
+ dest->attrib = DCA_NORMAL;
+ dest++;
+ col++;
+ }
+ }
+
+ // remember the last update
+ m_last_update = total_cycles;
+}
+
+
+//-------------------------------------------------
+// state_item - constructor
+//-------------------------------------------------
+
+debug_view_state::state_item::state_item(int index, const char *name, UINT8 valuechars)
+ : m_next(NULL),
+ m_lastval(0),
+ m_currval(0),
+ m_index(index),
+ m_vallen(valuechars),
+ m_symbol(name)
+{
+}
diff --git a/trunk/src/emu/debug/dvstate.h b/trunk/src/emu/debug/dvstate.h
new file mode 100644
index 00000000000..406ce2c35c6
--- /dev/null
+++ b/trunk/src/emu/debug/dvstate.h
@@ -0,0 +1,117 @@
+/*********************************************************************
+
+ dvstate.h
+
+ State debugger view.
+
+****************************************************************************
+
+ 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.
+
+***************************************************************************/
+
+#ifndef __DVSTATE_H__
+#define __DVSTATE_H__
+
+#include "debugvw.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// data sources for state views
+class debug_view_state_source : public debug_view_source
+{
+ friend class debug_view_state;
+
+ // construction/destruction
+ debug_view_state_source(const char *name, device_t &device);
+
+public:
+ // getters
+ device_t &device() const { return m_device; }
+
+private:
+ // internal state
+ device_t & m_device; // underlying device
+ device_state_interface *m_stateintf; // state interface
+ device_execute_interface *m_execintf; // execution interface
+};
+
+
+// debug view for state
+class debug_view_state : public debug_view
+{
+ friend resource_pool_object<debug_view_state>::~resource_pool_object();
+ friend class debug_view_manager;
+
+ // construction/destruction
+ debug_view_state(running_machine &machine, debug_view_osd_update_func osdupdate, void *osdprivate);
+ virtual ~debug_view_state();
+
+protected:
+ // view overrides
+ virtual void view_update();
+ virtual void view_notify(debug_view_notification type);
+
+private:
+ struct state_item
+ {
+ state_item(int index, const char *name, UINT8 valuechars);
+
+ state_item * m_next; // next item
+ UINT64 m_lastval; // last value
+ UINT64 m_currval; // current value
+ int m_index; // index
+ UINT8 m_vallen; // number of value chars
+ astring m_symbol; // symbol
+ };
+
+ // internal helpers
+ void enumerate_sources();
+ void reset();
+ void recompute();
+
+ // internal state
+ int m_divider; // dividing column
+ UINT64 m_last_update; // execution counter at last update
+ state_item * m_state_list; // state data
+
+ // constants
+ static const int REG_DIVIDER = -10;
+ static const int REG_CYCLES = -11;
+ static const int REG_BEAMX = -12;
+ static const int REG_BEAMY = -13;
+ static const int REG_FRAME = -14;
+};
+
+
+#endif
diff --git a/trunk/src/emu/debug/dvtext.c b/trunk/src/emu/debug/dvtext.c
new file mode 100644
index 00000000000..8e42b182f86
--- /dev/null
+++ b/trunk/src/emu/debug/dvtext.c
@@ -0,0 +1,184 @@
+/*********************************************************************
+
+ dvtext.c
+
+ Debugger simple text-based views.
+
+****************************************************************************
+
+ 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 "debugvw.h"
+#include "dvtext.h"
+#include "debugcon.h"
+
+
+
+//**************************************************************************
+// DEBUG VIEW TEXTBUF
+//**************************************************************************
+
+//-------------------------------------------------
+// debug_view_textbuf - constructor
+//-------------------------------------------------
+
+debug_view_textbuf::debug_view_textbuf(running_machine &machine, debug_view_type type, debug_view_osd_update_func osdupdate, void *osdprivate, text_buffer &textbuf)
+ : debug_view(machine, type, osdupdate, osdprivate),
+ m_textbuf(textbuf),
+ m_at_bottom(true),
+ m_topseq(0)
+{
+}
+
+
+//-------------------------------------------------
+// ~debug_view_textbuf - destructor
+//-------------------------------------------------
+
+debug_view_textbuf::~debug_view_textbuf()
+{
+}
+
+
+//-------------------------------------------------
+// view_update - update a text buffer-based view
+//-------------------------------------------------
+
+void debug_view_textbuf::view_update()
+{
+ // update the console info
+ m_total.x = text_buffer_max_width(&m_textbuf);
+ m_total.y = text_buffer_num_lines(&m_textbuf);
+ if (m_total.x < 80)
+ m_total.x = 80;
+
+ // determine the starting sequence number
+ UINT32 curseq = 0;
+ if (!m_at_bottom)
+ {
+ curseq = m_topseq;
+ if (!text_buffer_get_seqnum_line(&m_textbuf, curseq))
+ m_at_bottom = true;
+ }
+ if (m_at_bottom)
+ {
+ curseq = text_buffer_line_index_to_seqnum(&m_textbuf, m_total.y - 1);
+ if (m_total.y < m_visible.y)
+ curseq -= m_total.y - 1;
+ else
+ curseq -= m_visible.y - 1;
+ }
+ m_topleft.y = curseq - text_buffer_line_index_to_seqnum(&m_textbuf, 0);
+
+ // loop over visible rows
+ debug_view_char *dest = m_viewdata;
+ for (UINT32 row = 0; row < m_visible.y; row++)
+ {
+ const char *line = text_buffer_get_seqnum_line(&m_textbuf, curseq++);
+ UINT32 col = 0;
+
+ // if this visible row is valid, add it to the buffer
+ if (line != NULL)
+ {
+ size_t len = strlen(line);
+ UINT32 effcol = m_topleft.x;
+
+ // copy data
+ while (col < m_visible.x && effcol < len)
+ {
+ dest->byte = line[effcol++];
+ dest->attrib = DCA_NORMAL;
+ dest++;
+ col++;
+ }
+ }
+
+ // fill the rest with blanks
+ while (col < m_visible.x)
+ {
+ dest->byte = ' ';
+ dest->attrib = DCA_NORMAL;
+ dest++;
+ col++;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// view_notify - handle notification of updates
+// to visible area
+//-------------------------------------------------
+
+void debug_view_textbuf::view_notify(debug_view_notification type)
+{
+ if (type == VIEW_NOTIFY_VISIBLE_CHANGED)
+ {
+ // if the bottom line is visible, just track the bottom
+ m_at_bottom = (m_total.y >= m_topleft.y && m_total.y <= m_topleft.y + m_visible.y);
+
+ /* otherwise, track the seqence number of the top line */
+ if (!m_at_bottom)
+ m_topseq = text_buffer_line_index_to_seqnum(&m_textbuf, m_topleft.y);
+ }
+}
+
+
+
+//**************************************************************************
+// DEBUG VIEW CONSOLE
+//**************************************************************************
+
+//-------------------------------------------------
+// debug_view_console - constructor
+//-------------------------------------------------
+
+debug_view_console::debug_view_console(running_machine &machine, debug_view_osd_update_func osdupdate, void *osdprivate)
+ : debug_view_textbuf(machine, DVT_CONSOLE, osdupdate, osdprivate, *debug_console_get_textbuf())
+{
+}
+
+
+
+//**************************************************************************
+// DEBUG VIEW LOG
+//**************************************************************************
+
+//-------------------------------------------------
+// debug_view_log - constructor
+//-------------------------------------------------
+
+debug_view_log::debug_view_log(running_machine &machine, debug_view_osd_update_func osdupdate, void *osdprivate)
+ : debug_view_textbuf(machine, DVT_LOG, osdupdate, osdprivate, *debug_errorlog_get_textbuf())
+{
+}
diff --git a/trunk/src/emu/debug/dvtext.h b/trunk/src/emu/debug/dvtext.h
new file mode 100644
index 00000000000..dcaa02eaa74
--- /dev/null
+++ b/trunk/src/emu/debug/dvtext.h
@@ -0,0 +1,90 @@
+/*********************************************************************
+
+ dvtext.h
+
+ Debugger simple text-based views.
+
+****************************************************************************
+
+ 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.
+
+***************************************************************************/
+
+#ifndef __DVTEXT_H__
+#define __DVTEXT_H__
+
+#include "debugvw.h"
+#include "textbuf.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// debug_view_textbuf contains data specific to a textbuffer view
+class debug_view_textbuf : public debug_view
+{
+ friend class debug_view_manager;
+
+protected:
+ // construction/destruction
+ debug_view_textbuf(running_machine &machine, debug_view_type type, debug_view_osd_update_func osdupdate, void *osdprivate, text_buffer &textbuf);
+ virtual ~debug_view_textbuf();
+
+protected:
+ // view overrides
+ virtual void view_update();
+ virtual void view_notify(debug_view_notification type);
+
+private:
+ // internal state
+ text_buffer & m_textbuf; /* pointer to the text buffer */
+ bool m_at_bottom; /* are we tracking new stuff being added? */
+ UINT32 m_topseq; /* sequence number of the top line */
+};
+
+
+// debug_view_console describes a console view
+class debug_view_console : public debug_view_textbuf
+{
+ friend class debug_view_manager;
+ debug_view_console(running_machine &machine, debug_view_osd_update_func osdupdate, void *osdprivate);
+};
+
+
+// debug_view_textbuf describes an error log view
+class debug_view_log : public debug_view_textbuf
+{
+ friend class debug_view_manager;
+ debug_view_log(running_machine &machine, debug_view_osd_update_func osdupdate, void *osdprivate);
+};
+
+
+#endif
diff --git a/trunk/src/emu/debug/express.c b/trunk/src/emu/debug/express.c
new file mode 100644
index 00000000000..cf9fc8699e9
--- /dev/null
+++ b/trunk/src/emu/debug/express.c
@@ -0,0 +1,1781 @@
+/***************************************************************************
+
+ express.c
+
+ Generic expressions engine.
+
+****************************************************************************
+
+ 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.
+
+****************************************************************************
+
+ Operator precedence
+ ===================
+ 0x0000 ( )
+ 0x0001 ++ (postfix), -- (postfix)
+ 0x0002 ++ (prefix), -- (prefix), ~, !, - (unary), + (unary), b@, w@, d@, q@
+ 0x0003 *, /, %
+ 0x0004 + -
+ 0x0005 << >>
+ 0x0006 < <= > >=
+ 0x0007 == !=
+ 0x0008 &
+ 0x0009 ^
+ 0x000a |
+ 0x000b &&
+ 0x000c ||
+ 0x000d = *= /= %= += -= <<= >>= &= |= ^=
+ 0x000e ,
+ 0x000f func()
+
+***************************************************************************/
+
+#include "emu.h"
+#include "express.h"
+#include <ctype.h>
+
+
+
+/***************************************************************************
+ DEBUGGING
+***************************************************************************/
+
+#define DEBUG_TOKENS 0
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#ifndef DEFAULT_BASE
+#define DEFAULT_BASE 16 // hex unless otherwise specified
+#endif
+
+
+// token.value values if token.is_operator()
+enum
+{
+ TVL_LPAREN,
+ TVL_RPAREN,
+ TVL_PLUSPLUS,
+ TVL_MINUSMINUS,
+ TVL_PREINCREMENT,
+ TVL_PREDECREMENT,
+ TVL_POSTINCREMENT,
+ TVL_POSTDECREMENT,
+ TVL_COMPLEMENT,
+ TVL_NOT,
+ TVL_UPLUS,
+ TVL_UMINUS,
+ TVL_MULTIPLY,
+ TVL_DIVIDE,
+ TVL_MODULO,
+ TVL_ADD,
+ TVL_SUBTRACT,
+ TVL_LSHIFT,
+ TVL_RSHIFT,
+ TVL_LESS,
+ TVL_LESSOREQUAL,
+ TVL_GREATER,
+ TVL_GREATEROREQUAL,
+ TVL_EQUAL,
+ TVL_NOTEQUAL,
+ TVL_BAND,
+ TVL_BXOR,
+ TVL_BOR,
+ TVL_LAND,
+ TVL_LOR,
+ TVL_ASSIGN,
+ TVL_ASSIGNMULTIPLY,
+ TVL_ASSIGNDIVIDE,
+ TVL_ASSIGNMODULO,
+ TVL_ASSIGNADD,
+ TVL_ASSIGNSUBTRACT,
+ TVL_ASSIGNLSHIFT,
+ TVL_ASSIGNRSHIFT,
+ TVL_ASSIGNBAND,
+ TVL_ASSIGNBXOR,
+ TVL_ASSIGNBOR,
+ TVL_COMMA,
+ TVL_MEMORYAT,
+ TVL_EXECUTEFUNC
+};
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// a symbol entry representing a register, with read/write callbacks
+class integer_symbol_entry : public symbol_entry
+{
+public:
+ // construction/destruction
+ integer_symbol_entry(symbol_table &table, const char *name, symbol_table::read_write rw, UINT64 *ptr = NULL);
+ integer_symbol_entry(symbol_table &table, const char *name, UINT64 constval);
+ integer_symbol_entry(symbol_table &table, const char *name, void *ref, symbol_table::getter_func getter, symbol_table::setter_func setter);
+
+ // symbol access
+ virtual bool is_lval() const;
+ virtual UINT64 value() const;
+ virtual void set_value(UINT64 newvalue);
+
+private:
+ // internal helpers
+ static UINT64 internal_getter(symbol_table &table, void *symref);
+ static void internal_setter(symbol_table &table, void *symref, UINT64 value);
+
+ // internal state
+ symbol_table::getter_func m_getter;
+ symbol_table::setter_func m_setter;
+ UINT64 m_value;
+};
+
+
+// a symbol entry representing a function
+class function_symbol_entry : public symbol_entry
+{
+public:
+ // construction/destruction
+ function_symbol_entry(symbol_table &table, const char *name, void *ref, int minparams, int maxparams, symbol_table::execute_func execute);
+
+ // symbol access
+ virtual bool is_lval() const;
+ virtual UINT64 value() const;
+ virtual void set_value(UINT64 newvalue);
+
+ // execution helper
+ virtual UINT64 execute(int numparams, const UINT64 *paramlist);
+
+private:
+ // internal state
+ UINT16 m_minparams;
+ UINT16 m_maxparams;
+ symbol_table::execute_func m_execute;
+};
+
+
+
+//**************************************************************************
+// EXPRESSION ERROR
+//**************************************************************************
+
+//-------------------------------------------------
+// code_string - return a friendly string for a
+// given expression error
+//-------------------------------------------------
+
+const char *expression_error::code_string() const
+{
+ switch (m_code)
+ {
+ case NOT_LVAL: return "not an lvalue";
+ case NOT_RVAL: return "not an rvalue";
+ case SYNTAX: return "syntax error";
+ case UNKNOWN_SYMBOL: return "unknown symbol";
+ case INVALID_NUMBER: return "invalid number";
+ case INVALID_TOKEN: return "invalid token";
+ case STACK_OVERFLOW: return "stack overflow";
+ case STACK_UNDERFLOW: return "stack underflow";
+ case UNBALANCED_PARENS: return "unbalanced parentheses";
+ case DIVIDE_BY_ZERO: return "divide by zero";
+ case OUT_OF_MEMORY: return "out of memory";
+ case INVALID_PARAM_COUNT: return "invalid number of parameters";
+ case UNBALANCED_QUOTES: return "unbalanced quotes";
+ case TOO_MANY_STRINGS: return "too many strings";
+ case INVALID_MEMORY_SIZE: return "invalid memory size (b/w/d/q expected)";
+ case NO_SUCH_MEMORY_SPACE: return "non-existent memory space";
+ case INVALID_MEMORY_SPACE: return "invalid memory space (p/d/i/o/r/m expected)";
+ case INVALID_MEMORY_NAME: return "invalid memory name";
+ case MISSING_MEMORY_NAME: return "missing memory name";
+ default: return "unknown error";
+ }
+}
+
+
+
+//**************************************************************************
+// SYMBOL ENTRY
+//**************************************************************************
+
+//-------------------------------------------------
+// symbol_entry - constructor
+//-------------------------------------------------
+
+symbol_entry::symbol_entry(symbol_table &table, symbol_type type, const char *name, void *ref)
+ : m_next(NULL),
+ m_table(table),
+ m_type(type),
+ m_name(name),
+ m_ref(ref)
+{
+}
+
+
+//-------------------------------------------------
+// ~symbol_entry - destructor
+//-------------------------------------------------
+
+symbol_entry::~symbol_entry()
+{
+}
+
+
+
+//**************************************************************************
+// REGISTER SYMBOL ENTRY
+//**************************************************************************
+
+//-------------------------------------------------
+// integer_symbol_entry - constructor
+//-------------------------------------------------
+
+integer_symbol_entry::integer_symbol_entry(symbol_table &table, const char *name, symbol_table::read_write rw, UINT64 *ptr)
+ : symbol_entry(table, SMT_INTEGER, name, (ptr == NULL) ? &m_value : ptr),
+ m_getter(internal_getter),
+ m_setter((rw == symbol_table::READ_ONLY) ? NULL : internal_setter),
+ m_value(0)
+{
+}
+
+
+integer_symbol_entry::integer_symbol_entry(symbol_table &table, const char *name, UINT64 constval)
+ : symbol_entry(table, SMT_INTEGER, name, &m_value),
+ m_getter(internal_getter),
+ m_setter(NULL),
+ m_value(constval)
+{
+}
+
+
+integer_symbol_entry::integer_symbol_entry(symbol_table &table, const char *name, void *ref, symbol_table::getter_func getter, symbol_table::setter_func setter)
+ : symbol_entry(table, SMT_INTEGER, name, ref),
+ m_getter(getter),
+ m_setter(setter),
+ m_value(0)
+{
+}
+
+
+//-------------------------------------------------
+// is_lval - is this symbol allowable as an lval?
+//-------------------------------------------------
+
+bool integer_symbol_entry::is_lval() const
+{
+ return (m_setter != NULL);
+}
+
+
+//-------------------------------------------------
+// value - return the value of this symbol
+//-------------------------------------------------
+
+UINT64 integer_symbol_entry::value() const
+{
+ return (*m_getter)(m_table, m_ref);
+}
+
+
+//-------------------------------------------------
+// set_value - set the value of this symbol
+//-------------------------------------------------
+
+void integer_symbol_entry::set_value(UINT64 newvalue)
+{
+ if (m_setter != NULL)
+ (*m_setter)(m_table, m_ref, newvalue);
+ else
+ throw emu_fatalerror("Symbol '%s' is read-only", m_name.cstr());
+}
+
+
+//-------------------------------------------------
+// internal_getter - internal helper for
+// returning the value of a variable
+//-------------------------------------------------
+
+UINT64 integer_symbol_entry::internal_getter(symbol_table &table, void *symref)
+{
+ return *(UINT64 *)symref;
+}
+
+
+//-------------------------------------------------
+// internal_setter - internal helper for setting
+// the value of a variable
+//-------------------------------------------------
+
+void integer_symbol_entry::internal_setter(symbol_table &table, void *symref, UINT64 value)
+{
+ *(UINT64 *)symref = value;
+}
+
+
+
+//**************************************************************************
+// FUNCTION SYMBOL ENTRY
+//**************************************************************************
+
+//-------------------------------------------------
+// function_symbol_entry - constructor
+//-------------------------------------------------
+
+function_symbol_entry::function_symbol_entry(symbol_table &table, const char *name, void *ref, int minparams, int maxparams, symbol_table::execute_func execute)
+ : symbol_entry(table, SMT_FUNCTION, name, ref),
+ m_minparams(minparams),
+ m_maxparams(maxparams),
+ m_execute(execute)
+{
+}
+
+
+//-------------------------------------------------
+// is_lval - is this symbol allowable as an lval?
+//-------------------------------------------------
+
+bool function_symbol_entry::is_lval() const
+{
+ return false;
+}
+
+
+//-------------------------------------------------
+// value - return the value of this symbol
+//-------------------------------------------------
+
+UINT64 function_symbol_entry::value() const
+{
+ throw emu_fatalerror("Symbol '%s' is a function and cannot be used in this context", m_name.cstr());
+}
+
+
+//-------------------------------------------------
+// set_value - set the value of this symbol
+//-------------------------------------------------
+
+void function_symbol_entry::set_value(UINT64 newvalue)
+{
+ throw emu_fatalerror("Symbol '%s' is a function and cannot be written", m_name.cstr());
+}
+
+
+//-------------------------------------------------
+// execute - execute the function
+//-------------------------------------------------
+
+UINT64 function_symbol_entry::execute(int numparams, const UINT64 *paramlist)
+{
+ if (numparams < m_minparams)
+ throw emu_fatalerror("Function '%s' requires at least %d parameters", m_name.cstr(), m_minparams);
+ if (numparams > m_maxparams)
+ throw emu_fatalerror("Function '%s' accepts no more than %d parameters", m_name.cstr(), m_maxparams);
+ return (*m_execute)(m_table, m_ref, numparams, paramlist);
+}
+
+
+
+//**************************************************************************
+// SYMBOL TABLE
+//**************************************************************************
+
+//-------------------------------------------------
+// symbol_table - constructor
+//-------------------------------------------------
+
+symbol_table::symbol_table(void *globalref, symbol_table *parent)
+ : m_parent(parent),
+ m_globalref(globalref),
+ m_memory_param(NULL),
+ m_memory_valid(NULL),
+ m_memory_read(NULL),
+ m_memory_write(NULL)
+{
+}
+
+
+//-------------------------------------------------
+// add - add a new UINT64 pointer symbol
+//-------------------------------------------------
+
+void symbol_table::configure_memory(void *param, valid_func valid, read_func read, write_func write)
+{
+ m_memory_param = param;
+ m_memory_valid = valid;
+ m_memory_read = read;
+ m_memory_write = write;
+}
+
+
+//-------------------------------------------------
+// add - add a new UINT64 pointer symbol
+//-------------------------------------------------
+
+void symbol_table::add(const char *name, read_write rw, UINT64 *ptr)
+{
+ m_symlist.remove(name);
+ m_symlist.append(name, *global_alloc(integer_symbol_entry(*this, name, rw, ptr)));
+}
+
+
+//-------------------------------------------------
+// add - add a new value symbol
+//-------------------------------------------------
+
+void symbol_table::add(const char *name, UINT64 value)
+{
+ m_symlist.remove(name);
+ m_symlist.append(name, *global_alloc(integer_symbol_entry(*this, name, value)));
+}
+
+
+//-------------------------------------------------
+// add - add a new register symbol
+//-------------------------------------------------
+
+void symbol_table::add(const char *name, void *ref, getter_func getter, setter_func setter)
+{
+ m_symlist.remove(name);
+ m_symlist.append(name, *global_alloc(integer_symbol_entry(*this, name, ref, getter, setter)));
+}
+
+
+//-------------------------------------------------
+// add - add a new function symbol
+//-------------------------------------------------
+
+void symbol_table::add(const char *name, void *ref, int minparams, int maxparams, execute_func execute)
+{
+ m_symlist.remove(name);
+ m_symlist.append(name, *global_alloc(function_symbol_entry(*this, name, ref, minparams, maxparams, execute)));
+}
+
+
+//-------------------------------------------------
+// find_deep - do a deep search for a symbol,
+// looking in the parent if needed
+//-------------------------------------------------
+
+symbol_entry *symbol_table::find_deep(const char *symbol)
+{
+ // walk up the table hierarchy to find the owner
+ for (symbol_table *symtable = this; symtable != NULL; symtable = symtable->m_parent)
+ {
+ symbol_entry *entry = symtable->find(symbol);
+ if (entry != NULL)
+ return entry;
+ }
+ return NULL;
+}
+
+
+//-------------------------------------------------
+// value - return the value of a symbol
+//-------------------------------------------------
+
+UINT64 symbol_table::value(const char *symbol)
+{
+ symbol_entry *entry = find_deep(symbol);
+ return (entry != NULL) ? entry->value() : 0;
+}
+
+
+//-------------------------------------------------
+// set_value - set the value of a symbol
+//-------------------------------------------------
+
+void symbol_table::set_value(const char *symbol, UINT64 value)
+{
+ symbol_entry *entry = find_deep(symbol);
+ if (entry != NULL)
+ entry->set_value(value);
+}
+
+
+//-------------------------------------------------
+// memory_valid - return true if the given
+// memory name/space/offset combination is valid
+//-------------------------------------------------
+
+expression_error::error_code symbol_table::memory_valid(const char *name, expression_space space)
+{
+ // walk up the table hierarchy to find the owner
+ for (symbol_table *symtable = this; symtable != NULL; symtable = symtable->m_parent)
+ if (symtable->m_memory_valid != NULL)
+ {
+ expression_error::error_code err = (*symtable->m_memory_valid)(symtable->m_memory_param, name, space);
+ if (err != expression_error::NO_SUCH_MEMORY_SPACE)
+ return err;
+ }
+ return expression_error::NO_SUCH_MEMORY_SPACE;
+}
+
+
+//-------------------------------------------------
+// memory_value - return a value read from memory
+//-------------------------------------------------
+
+UINT64 symbol_table::memory_value(const char *name, expression_space space, UINT32 offset, int size)
+{
+ // walk up the table hierarchy to find the owner
+ for (symbol_table *symtable = this; symtable != NULL; symtable = symtable->m_parent)
+ if (symtable->m_memory_valid != NULL)
+ {
+ expression_error::error_code err = (*symtable->m_memory_valid)(symtable->m_memory_param, name, space);
+ if (err != expression_error::NO_SUCH_MEMORY_SPACE && symtable->m_memory_read != NULL)
+ return (*symtable->m_memory_read)(symtable->m_memory_param, name, space, offset, size);
+ return 0;
+ }
+ return 0;
+}
+
+
+//-------------------------------------------------
+// set_memory_value - write a value to memory
+//-------------------------------------------------
+
+void symbol_table::set_memory_value(const char *name, expression_space space, UINT32 offset, int size, UINT64 value)
+{
+ // walk up the table hierarchy to find the owner
+ for (symbol_table *symtable = this; symtable != NULL; symtable = symtable->m_parent)
+ if (symtable->m_memory_valid != NULL)
+ {
+ expression_error::error_code err = (*symtable->m_memory_valid)(symtable->m_memory_param, name, space);
+ if (err != expression_error::NO_SUCH_MEMORY_SPACE && symtable->m_memory_write != NULL)
+ (*symtable->m_memory_write)(symtable->m_memory_param, name, space, offset, size, value);
+ return;
+ }
+}
+
+
+
+//**************************************************************************
+// PARSED EXPRESSION
+//**************************************************************************
+
+//-------------------------------------------------
+// parsed_expression - constructor
+//-------------------------------------------------
+
+parsed_expression::parsed_expression(symbol_table *symtable, const char *expression, UINT64 *result)
+ : m_symtable(symtable)
+{
+ // if we got an expression parse it
+ if (expression != NULL)
+ parse(expression);
+
+ // if we get a result pointer, execute it
+ if (result != NULL)
+ *result = execute();
+}
+
+
+//-------------------------------------------------
+// parse - parse an expression into tokens
+//-------------------------------------------------
+
+void parsed_expression::parse(const char *expression)
+{
+ // copy the string and reset our parsing state
+ m_original_string.cpy(expression);
+ m_tokenlist.reset();
+ m_stringlist.reset();
+
+ // first parse the tokens into the token array in order
+ parse_string_into_tokens();
+
+ // convert the infix order to postfix order
+ infix_to_postfix();
+}
+
+
+//-------------------------------------------------
+// copy - copy an expression from another source
+//-------------------------------------------------
+
+void parsed_expression::copy(const parsed_expression &src)
+{
+ m_symtable = src.m_symtable;
+ m_original_string.cpy(src.m_original_string);
+ if (m_original_string)
+ parse_string_into_tokens();
+}
+
+
+//-------------------------------------------------
+// print_tokens - debugging took to print a
+// human readable token representation
+//-------------------------------------------------
+
+void parsed_expression::print_tokens(FILE *out)
+{
+#if DEBUG_TOKENS
+ mame_printf_debug("----\n");
+ for (parse_token *token = m_tokens.first(); token != NULL; token = token->next())
+ {
+ switch (token->type)
+ {
+ default:
+ case parse_token::INVALID:
+ fprintf(out, "INVALID\n");
+ break;
+
+ case parse_token::END:
+ fprintf(out, "END\n");
+ break;
+
+ case parse_token::NUMBER:
+ fprintf(out, "NUMBER: %08X%08X\n", (UINT32)(token->value.i >> 32), (UINT32)token->value.i);
+ break;
+
+ case parse_token::STRING:
+ fprintf(out, "STRING: ""%s""\n", token->string);
+ break;
+
+ case parse_token::SYMBOL:
+ fprintf(out, "SYMBOL: %08X%08X\n", (UINT32)(token->value.i >> 32), (UINT32)token->value.i);
+ break;
+
+ case parse_token::OPERATOR:
+ switch (token->value.i)
+ {
+ case TVL_LPAREN: fprintf(out, "(\n"); break;
+ case TVL_RPAREN: fprintf(out, ")\n"); break;
+ case TVL_PLUSPLUS: fprintf(out, "++ (unspecified)\n"); break;
+ case TVL_MINUSMINUS: fprintf(out, "-- (unspecified)\n"); break;
+ case TVL_PREINCREMENT: fprintf(out, "++ (prefix)\n"); break;
+ case TVL_PREDECREMENT: fprintf(out, "-- (prefix)\n"); break;
+ case TVL_POSTINCREMENT: fprintf(out, "++ (postfix)\n"); break;
+ case TVL_POSTDECREMENT: fprintf(out, "-- (postfix)\n"); break;
+ case TVL_COMPLEMENT: fprintf(out, "!\n"); break;
+ case TVL_NOT: fprintf(out, "~\n"); break;
+ case TVL_UPLUS: fprintf(out, "+ (unary)\n"); break;
+ case TVL_UMINUS: fprintf(out, "- (unary)\n"); break;
+ case TVL_MULTIPLY: fprintf(out, "*\n"); break;
+ case TVL_DIVIDE: fprintf(out, "/\n"); break;
+ case TVL_MODULO: fprintf(out, "%%\n"); break;
+ case TVL_ADD: fprintf(out, "+\n"); break;
+ case TVL_SUBTRACT: fprintf(out, "-\n"); break;
+ case TVL_LSHIFT: fprintf(out, "<<\n"); break;
+ case TVL_RSHIFT: fprintf(out, ">>\n"); break;
+ case TVL_LESS: fprintf(out, "<\n"); break;
+ case TVL_LESSOREQUAL: fprintf(out, "<=\n"); break;
+ case TVL_GREATER: fprintf(out, ">\n"); break;
+ case TVL_GREATEROREQUAL:fprintf(out, ">=\n"); break;
+ case TVL_EQUAL: fprintf(out, "==\n"); break;
+ case TVL_NOTEQUAL: fprintf(out, "!=\n"); break;
+ case TVL_BAND: fprintf(out, "&\n"); break;
+ case TVL_BXOR: fprintf(out, "^\n"); break;
+ case TVL_BOR: fprintf(out, "|\n"); break;
+ case TVL_LAND: fprintf(out, "&&\n"); break;
+ case TVL_LOR: fprintf(out, "||\n"); break;
+ case TVL_ASSIGN: fprintf(out, "=\n"); break;
+ case TVL_ASSIGNMULTIPLY:fprintf(out, "*=\n"); break;
+ case TVL_ASSIGNDIVIDE: fprintf(out, "/=\n"); break;
+ case TVL_ASSIGNMODULO: fprintf(out, "%%=\n"); break;
+ case TVL_ASSIGNADD: fprintf(out, "+=\n"); break;
+ case TVL_ASSIGNSUBTRACT:fprintf(out, "-=\n"); break;
+ case TVL_ASSIGNLSHIFT: fprintf(out, "<<=\n"); break;
+ case TVL_ASSIGNRSHIFT: fprintf(out, ">>=\n"); break;
+ case TVL_ASSIGNBAND: fprintf(out, "&=\n"); break;
+ case TVL_ASSIGNBXOR: fprintf(out, "^=\n"); break;
+ case TVL_ASSIGNBOR: fprintf(out, "|=\n"); break;
+ case TVL_COMMA: fprintf(out, ",\n"); break;
+ case TVL_MEMORYAT: fprintf(out, "mem@\n"); break;
+ case TVL_EXECUTEFUNC: fprintf(out, "execute\n"); break;
+ default: fprintf(out, "INVALID OPERATOR\n"); break;
+ }
+ break;
+ }
+ }
+ mame_printf_debug("----\n");
+#endif
+}
+
+
+//-------------------------------------------------
+// parse_string_into_tokens - take an expression
+// string and break it into a sequence of tokens
+//-------------------------------------------------
+
+void parsed_expression::parse_string_into_tokens()
+{
+ // loop until done
+ const char *stringstart = m_original_string;
+ const char *string = stringstart;
+ while (string[0] != 0)
+ {
+ // ignore any whitespace
+ while (string[0] != 0 && isspace((UINT8)string[0]))
+ string++;
+ if (string[0] == 0)
+ break;
+
+ // initialize the current token object
+ parse_token &token = m_tokenlist.append(*global_alloc(parse_token(string - stringstart)));
+
+ // switch off the first character
+ switch (tolower((UINT8)string[0]))
+ {
+ case '(':
+ string += 1, token.configure_operator(TVL_LPAREN, 0);
+ break;
+
+ case ')':
+ string += 1, token.configure_operator(TVL_RPAREN, 0);
+ break;
+
+ case '~':
+ string += 1, token.configure_operator(TVL_NOT, 2);
+ break;
+
+ case ',':
+ string += 1, token.configure_operator(TVL_COMMA, 14);
+ break;
+
+ case '+':
+ if (string[1] == '+')
+ string += 2, token.configure_operator(TVL_PLUSPLUS, 1);
+ else if (string[1] == '=')
+ string += 2, token.configure_operator(TVL_ASSIGNADD, 13).set_right_to_left();
+ else
+ string += 1, token.configure_operator(TVL_ADD, 4);
+ break;
+
+ case '-':
+ if (string[1] == '-')
+ string += 2, token.configure_operator(TVL_MINUSMINUS, 1);
+ else if (string[1] == '=')
+ string += 2, token.configure_operator(TVL_ASSIGNSUBTRACT, 13).set_right_to_left();
+ else
+ string += 1, token.configure_operator(TVL_SUBTRACT, 4);
+ break;
+
+ case '*':
+ if (string[1] == '=')
+ string += 2, token.configure_operator(TVL_ASSIGNMULTIPLY, 13).set_right_to_left();
+ else
+ string += 1, token.configure_operator(TVL_MULTIPLY, 3);
+ break;
+
+ case '/':
+ if (string[1] == '=')
+ string += 2, token.configure_operator(TVL_ASSIGNDIVIDE, 13).set_right_to_left();
+ else
+ string += 1, token.configure_operator(TVL_DIVIDE, 3);
+ break;
+
+ case '%':
+ if (string[1] == '=')
+ string += 2, token.configure_operator(TVL_ASSIGNMODULO, 13).set_right_to_left();
+ else
+ string += 1, token.configure_operator(TVL_MODULO, 3);
+ break;
+
+ case '<':
+ if (string[1] == '<' && string[2] == '=')
+ string += 3, token.configure_operator(TVL_ASSIGNLSHIFT, 13).set_right_to_left();
+ else if (string[1] == '<')
+ string += 2, token.configure_operator(TVL_LSHIFT, 5);
+ else if (string[1] == '=')
+ string += 2, token.configure_operator(TVL_LESSOREQUAL, 6);
+ else
+ string += 1, token.configure_operator(TVL_LESS, 6);
+ break;
+
+ case '>':
+ if (string[1] == '>' && string[2] == '=')
+ string += 3, token.configure_operator(TVL_ASSIGNRSHIFT, 13).set_right_to_left();
+ else if (string[1] == '>')
+ string += 2, token.configure_operator(TVL_RSHIFT, 5);
+ else if (string[1] == '=')
+ string += 2, token.configure_operator(TVL_GREATEROREQUAL, 6);
+ else
+ string += 1, token.configure_operator(TVL_GREATER, 6);
+ break;
+
+ case '=':
+ if (string[1] == '=')
+ string += 2, token.configure_operator(TVL_EQUAL, 7);
+ else
+ string += 1, token.configure_operator(TVL_ASSIGN, 13).set_right_to_left();
+ break;
+
+ case '!':
+ if (string[1] == '=')
+ string += 2, token.configure_operator(TVL_NOTEQUAL, 7);
+ else
+ string += 2, token.configure_operator(TVL_COMPLEMENT, 2);
+ break;
+
+ case '&':
+ if (string[1] == '&')
+ string += 2, token.configure_operator(TVL_LAND, 11);
+ else if (string[1] == '=')
+ string += 2, token.configure_operator(TVL_ASSIGNBAND, 13).set_right_to_left();
+ else
+ string += 1, token.configure_operator(TVL_BAND, 8);
+ break;
+
+ case '|':
+ if (string[1] == '|')
+ string += 2, token.configure_operator(TVL_LOR, 12);
+ else if (string[1] == '=')
+ string += 2, token.configure_operator(TVL_ASSIGNBOR, 13).set_right_to_left();
+ else
+ string += 1, token.configure_operator(TVL_BOR, 10);
+ break;
+
+ case '^':
+ if (string[1] == '=')
+ string += 2, token.configure_operator(TVL_ASSIGNBXOR, 13).set_right_to_left();
+ else
+ string += 1, token.configure_operator(TVL_BXOR, 9);
+ break;
+
+ case '"':
+ parse_quoted_string(token, string);
+ break;
+
+ case '\'':
+ parse_quoted_char(token, string);
+ break;
+
+ default:
+ parse_symbol_or_number(token, string);
+ break;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// parse_symbol_or_number - parse a substring
+// into either a symbol or a number or an
+// expanded operator
+//-------------------------------------------------
+
+void parsed_expression::parse_symbol_or_number(parse_token &token, const char *&string)
+{
+ // accumulate a lower-case version of the symbol
+ const char *stringstart = string;
+ astring buffer;
+ while (1)
+ {
+ static const char valid[] = "abcdefghijklmnopqrstuvwxyz0123456789_$#.:";
+ char val = tolower((UINT8)string[0]);
+ if (val == 0 || strchr(valid, val) == NULL)
+ break;
+ buffer.cat(&val, 1);
+ string++;
+ }
+
+ // check for memory @ operators
+ if (string[0] == '@')
+ {
+ string += 1;
+ return parse_memory_operator(token, buffer);
+ }
+
+ // empty string is automatically invalid
+ if (!buffer)
+ throw expression_error(expression_error::INVALID_TOKEN, token.offset());
+
+ // check for wordy variants on standard operators
+ if (buffer == "bnot")
+ { token.configure_operator(TVL_NOT, 2); return; }
+ if (buffer == "plus")
+ { token.configure_operator(TVL_ADD, 4); return; }
+ if (buffer == "minus")
+ { token.configure_operator(TVL_SUBTRACT, 4); return; }
+ if (buffer == "times" || buffer == "mul")
+ { token.configure_operator(TVL_MULTIPLY, 3); return; }
+ if (buffer == "div")
+ { token.configure_operator(TVL_DIVIDE, 3); return; }
+ if (buffer == "mod")
+ { token.configure_operator(TVL_MODULO, 3); return; }
+ if (buffer == "lt")
+ { token.configure_operator(TVL_LESS, 6); return; }
+ if (buffer == "le")
+ { token.configure_operator(TVL_LESSOREQUAL, 6); return; }
+ if (buffer == "gt")
+ { token.configure_operator(TVL_GREATER, 6); return; }
+ if (buffer == "ge")
+ { token.configure_operator(TVL_GREATEROREQUAL, 6); return; }
+ if (buffer == "eq")
+ { token.configure_operator(TVL_EQUAL, 7); return; }
+ if (buffer == "ne")
+ { token.configure_operator(TVL_NOTEQUAL, 7); return; }
+ if (buffer == "not")
+ { token.configure_operator(TVL_COMPLEMENT, 2); return; }
+ if (buffer == "and")
+ { token.configure_operator(TVL_LAND, 8); return; }
+ if (buffer == "band")
+ { token.configure_operator(TVL_BAND, 8); return; }
+ if (buffer == "or")
+ { token.configure_operator(TVL_LOR, 12); return; }
+ if (buffer == "bor")
+ { token.configure_operator(TVL_BOR, 10); return; }
+ if (buffer == "bxor")
+ { token.configure_operator(TVL_BXOR, 9); return; }
+ if (buffer == "lshift")
+ { token.configure_operator(TVL_LSHIFT, 5); return; }
+ if (buffer == "rshift")
+ { token.configure_operator(TVL_RSHIFT, 5); return; }
+
+ // if we have an 0x prefix, we must be a hex value
+ if (buffer[0] == '0' && buffer[1] == 'x')
+ return parse_number(token, &buffer[2], 16, expression_error::INVALID_NUMBER);
+
+ // if we have a # prefix, we must be a decimal value
+ if (buffer[0] == '#')
+ return parse_number(token, &buffer[1], 10, expression_error::INVALID_NUMBER);
+
+ // if we have a $ prefix, we are a hex value
+ if (buffer[0] == '$')
+ return parse_number(token, &buffer[1], 16, expression_error::INVALID_NUMBER);
+
+ // check for a symbol match
+ symbol_entry *symbol = m_symtable->find_deep(buffer);
+ if (symbol != NULL)
+ {
+ token.configure_symbol(*symbol);
+
+ // if this is a function symbol, synthesize an execute function operator
+ if (symbol->is_function())
+ {
+ token = m_tokenlist.append(*global_alloc(parse_token(string - stringstart)));
+ token.configure_operator(TVL_EXECUTEFUNC, 0);
+ }
+ return;
+ }
+
+ // attempt to parse as a number in the default base
+ parse_number(token, buffer, DEFAULT_BASE, expression_error::UNKNOWN_SYMBOL);
+}
+
+
+//-------------------------------------------------
+// parse_number - parse a number using the
+// given base
+//-------------------------------------------------
+
+void parsed_expression::parse_number(parse_token &token, const char *string, int base, expression_error::error_code errcode)
+{
+ // parse the actual value
+ UINT64 value = 0;
+ while (*string != 0)
+ {
+ // look up the number's value, stopping if not valid
+ static const char numbers[] = "0123456789abcdef";
+ const char *ptr = strchr(numbers, tolower((UINT8)*string));
+ if (ptr == NULL)
+ break;
+
+ // if outside of the base, we also stop
+ int digit = ptr - numbers;
+ if (digit >= base)
+ break;
+
+ // shift previous digits up and add in new digit
+ value = (value * (UINT64)base) + digit;
+ string++;
+ }
+
+ // if we succeeded as a number, make it so
+ if (*string == 0)
+ token.configure_number(value);
+ else
+ throw expression_error(errcode, token.offset());
+}
+
+
+//-------------------------------------------------
+// parse_quoted_char - parse a single-quoted
+// character constant
+//-------------------------------------------------
+
+void parsed_expression::parse_quoted_char(parse_token &token, const char *&string)
+{
+ // accumulate the value of the character token
+ string++;
+ UINT64 value = 0;
+ while (string[0] != 0)
+ {
+ // allow '' to mean a nested single quote
+ if (string[0] == '\'')
+ {
+ if (string[1] != '\'')
+ break;
+ string++;
+ }
+ value = (value << 8) | (UINT8)*string++;
+ }
+
+ // if we didn't find the ending quote, report an error
+ if (string[0] != '\'')
+ throw expression_error(expression_error::UNBALANCED_QUOTES, token.offset());
+ string++;
+
+ // make it a number token
+ token.configure_number(value);
+}
+
+
+//-------------------------------------------------
+// parse_quoted_string - parse a double-quoted
+// string constant
+//-------------------------------------------------
+
+void parsed_expression::parse_quoted_string(parse_token &token, const char *&string)
+{
+ // accumulate a copy of the quoted string
+ string++;
+ astring buffer;
+ while (string[0] != 0)
+ {
+ // allow "" to mean a nested double-quote
+ if (string[0] == '"')
+ {
+ if (string[1] != '"')
+ break;
+ string++;
+ }
+ buffer.cat(string++, 1);
+ }
+
+ // if we didn't find the ending quote, report an error
+ if (string[0] != '"')
+ throw expression_error(expression_error::UNBALANCED_QUOTES, token.offset());
+ string++;
+
+ // make the token
+ token.configure_string(m_stringlist.append(*global_alloc(expression_string(buffer))));
+}
+
+
+//-------------------------------------------------
+// parse_memory_operator - parse the several
+// forms of memory operators
+//-------------------------------------------------
+
+void parsed_expression::parse_memory_operator(parse_token &token, const char *string)
+{
+ // if there is a '.', it means we have a name
+ const char *startstring = string;
+ const char *namestring = NULL;
+ const char *dot = strrchr(string, '.');
+ if (dot != NULL)
+ {
+ namestring = m_stringlist.append(*global_alloc(expression_string(string, dot - string)));
+ string = dot + 1;
+ }
+
+ // length 3 means logical/physical, then space, then size
+ int length = (int)strlen(string);
+ bool physical = false;
+ int space = 'p';
+ int size;
+ if (length == 3)
+ {
+ if (string[0] != 'l' && string[0] != 'p')
+ throw expression_error(expression_error::INVALID_MEMORY_SPACE, token.offset() + (string - startstring));
+ if (string[1] != 'p' && string[1] != 'd' && string[1] != 'i' && string[1] != '3')
+ throw expression_error(expression_error::INVALID_MEMORY_SPACE, token.offset() + (string - startstring));
+ physical = (string[0] == 'p');
+ space = string[1];
+ size = string[2];
+ }
+
+ // length 2 means space then size
+ else if (length == 2)
+ {
+ space = string[0];
+ size = string[1];
+ }
+
+ // length 1 means size
+ else if (length == 1)
+ size = string[0];
+
+ // anything else is invalid
+ else
+ throw expression_error(expression_error::INVALID_TOKEN, token.offset());
+
+ // convert the space to flags
+ expression_space memspace = EXPSPACE_INVALID;
+ switch (space)
+ {
+ case 'p': memspace = physical ? EXPSPACE_PROGRAM_PHYSICAL : EXPSPACE_PROGRAM_LOGICAL; break;
+ case 'd': memspace = physical ? EXPSPACE_DATA_PHYSICAL : EXPSPACE_DATA_LOGICAL; break;
+ case 'i': memspace = physical ? EXPSPACE_IO_PHYSICAL : EXPSPACE_IO_LOGICAL; break;
+ case '3': memspace = physical ? EXPSPACE_SPACE3_PHYSICAL : EXPSPACE_SPACE3_LOGICAL; break;
+ case 'o': memspace = EXPSPACE_OPCODE; break;
+ case 'r': memspace = EXPSPACE_RAMWRITE; break;
+ case 'm': memspace = EXPSPACE_REGION; break;
+ default: throw expression_error(expression_error::INVALID_MEMORY_SPACE, token.offset() + (string - startstring));
+ }
+
+ // convert the size to flags
+ int memsize;
+ switch (size)
+ {
+ case 'b': memsize = 0; break;
+ case 'w': memsize = 1; break;
+ case 'd': memsize = 2; break;
+ case 'q': memsize = 3; break;
+ default: throw expression_error(expression_error::INVALID_MEMORY_SIZE, token.offset() + (string - startstring) + length - 1);
+ }
+
+ // validate the name
+ if (m_symtable != NULL)
+ {
+ expression_error::error_code err = m_symtable->memory_valid(namestring, memspace);
+ if (err != expression_error::NONE)
+ throw expression_error(err, token.offset() + (string - startstring));
+ }
+
+ // configure the token
+ token.configure_operator(TVL_MEMORYAT, 2).set_memory_size(memsize).set_memory_space(memspace).set_memory_source(namestring);
+}
+
+
+//-------------------------------------------------
+// normalize_operator - resolve operator
+// ambiguities based on neighboring tokens
+//-------------------------------------------------
+
+void parsed_expression::normalize_operator(parse_token *prevtoken, parse_token &thistoken)
+{
+ parse_token *nexttoken = thistoken.next();
+ switch (thistoken.optype())
+ {
+ // Determine if an open paren is part of a function or not
+ case TVL_LPAREN:
+ if (prevtoken != NULL && prevtoken->is_operator(TVL_EXECUTEFUNC))
+ thistoken.set_function_separator();
+ break;
+
+ // Determine if ++ is a pre or post increment
+ case TVL_PLUSPLUS:
+ if (nexttoken != NULL && (nexttoken->is_symbol() || (nexttoken->is_operator(TVL_MEMORYAT))))
+ thistoken.configure_operator(TVL_PREINCREMENT, 2);
+ else if (prevtoken != NULL && (prevtoken->is_symbol() || (prevtoken->is_operator(TVL_MEMORYAT))))
+ thistoken.configure_operator(TVL_POSTINCREMENT, 1);
+ else
+ throw expression_error(expression_error::SYNTAX, thistoken.offset());
+ break;
+
+ // Determine if -- is a pre or post decrement
+ case TVL_MINUSMINUS:
+ if (nexttoken != NULL && (nexttoken->is_symbol() || (nexttoken->is_operator(TVL_MEMORYAT))))
+ thistoken.configure_operator(TVL_PREDECREMENT, 2);
+ else if (prevtoken != NULL && (prevtoken->is_symbol() || (prevtoken->is_operator(TVL_MEMORYAT))))
+ thistoken.configure_operator(TVL_POSTDECREMENT, 1);
+ else
+ throw expression_error(expression_error::SYNTAX, thistoken.offset());
+ break;
+
+ // Determine if +/- is a unary or binary
+ case TVL_ADD:
+ case TVL_SUBTRACT:
+ // Assume we're unary if we are the first token, or if the previous token is not
+ // a symbol, a number, or a right parenthesis
+ if (prevtoken == NULL || (!prevtoken->is_symbol() && !prevtoken->is_number() && !prevtoken->is_operator(TVL_RPAREN)))
+ thistoken.configure_operator(thistoken.is_operator(TVL_ADD) ? TVL_UPLUS : TVL_UMINUS, 2);
+ break;
+
+ // Determine if , refers to a function parameter
+ case TVL_COMMA:
+ for (int lookback = 0; lookback < MAX_STACK_DEPTH; lookback++)
+ {
+ parse_token *peek = peek_token(lookback);
+ if (peek == NULL)
+ break;
+
+ // if we hit an execute function operator, or else a left parenthesis that is
+ // already tagged, then tag us as well
+ if (peek->is_operator(TVL_EXECUTEFUNC) || (peek->is_operator(TVL_LPAREN) && peek->is_function_separator()))
+ {
+ thistoken.set_function_separator();
+ break;
+ }
+ }
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// infix_to_postfix - convert an infix sequence
+// of tokens to a postfix sequence for processing
+//-------------------------------------------------
+
+void parsed_expression::infix_to_postfix()
+{
+ simple_list<parse_token> stack;
+
+ // loop over all the original tokens
+ parse_token *prev = NULL;
+ parse_token *next = NULL;
+ for (parse_token *token = m_tokenlist.detach_all(); token != NULL; prev = token, token = next)
+ {
+ // pre-determine our next token
+ next = token->next();
+
+ // if the character is an operand, append it to the result string
+ if (token->is_number() || token->is_symbol() || token->is_string())
+ m_tokenlist.append(*token);
+
+ // if this is an operator, process it
+ else if (token->is_operator())
+ {
+ // normalize the operator based on neighbors
+ normalize_operator(prev, *token);
+
+ // if the token is an opening parenthesis, push it onto the stack.
+ if (token->is_operator(TVL_LPAREN))
+ stack.prepend(*token);
+
+ // if the token is a closing parenthesis, pop all operators until we
+ // reach an opening parenthesis and append them to the result string,
+ // discaring the open parenthesis
+ else if (token->is_operator(TVL_RPAREN))
+ {
+ // loop until we find our matching opener
+ parse_token *popped;
+ while ((popped = stack.detach_head()) != NULL)
+ {
+ if (popped->is_operator(TVL_LPAREN))
+ break;
+ m_tokenlist.append(*popped);
+ }
+
+ // if we didn't find an open paren, it's an error
+ if (popped == NULL)
+ throw expression_error(expression_error::UNBALANCED_PARENS, token->offset());
+
+ // free ourself and our matching opening parenthesis
+ global_free(token);
+ global_free(popped);
+ }
+
+ // if the token is an operator, pop operators until we reach an opening parenthesis,
+ // an operator of lower precedence, or a right associative symbol of equal precedence.
+ // Push the operator onto the stack.
+ else
+ {
+ int our_precedence = token->precedence();
+
+ // loop until we can't peek at the stack anymore
+ parse_token *peek;
+ while ((peek = stack.first()) != NULL)
+ {
+ // break if any of the above conditions are true
+ if (peek->is_operator(TVL_LPAREN))
+ break;
+ int stack_precedence = peek->precedence();
+ if (stack_precedence > our_precedence || (stack_precedence == our_precedence && peek->right_to_left()))
+ break;
+
+ // pop this token
+ m_tokenlist.append(*stack.detach_head());
+ }
+
+ // push the new operator
+ stack.prepend(*token);
+ }
+ }
+ }
+
+ // finish popping the stack
+ parse_token *popped;
+ while ((popped = stack.detach_head()) != NULL)
+ {
+ // it is an error to have a left parenthesis still on the stack
+ if (popped->is_operator(TVL_LPAREN))
+ throw expression_error(expression_error::UNBALANCED_PARENS, popped->offset());
+
+ // pop this token
+ m_tokenlist.append(*popped);
+ }
+}
+
+
+//-------------------------------------------------
+// push_token - push a token onto the stack
+//-------------------------------------------------
+
+inline void parsed_expression::push_token(parse_token &token)
+{
+ // check for overflow
+ if (m_token_stack_ptr >= MAX_STACK_DEPTH)
+ throw expression_error(expression_error::STACK_OVERFLOW, token.offset());
+
+ // push
+ m_token_stack[m_token_stack_ptr++] = token;
+}
+
+
+//-------------------------------------------------
+// pop_token - pop a token off the stack
+//-------------------------------------------------
+
+inline void parsed_expression::pop_token(parse_token &token)
+{
+ // check for underflow
+ if (m_token_stack_ptr == 0)
+ throw expression_error(expression_error::STACK_UNDERFLOW, token.offset());
+
+ // pop
+ token = m_token_stack[--m_token_stack_ptr];
+}
+
+
+//-------------------------------------------------
+// peek_token - look at a token some number of
+// entries up the stack
+//-------------------------------------------------
+
+inline parsed_expression::parse_token *parsed_expression::peek_token(int count)
+{
+ if (m_token_stack_ptr <= count)
+ return NULL;
+ return &m_token_stack[m_token_stack_ptr - count - 1];
+}
+
+
+//-------------------------------------------------
+// pop_token_lval - pop a token off the stack
+// and ensure that it is a proper lval
+//-------------------------------------------------
+
+inline void parsed_expression::pop_token_lval(parse_token &token)
+{
+ // start with normal pop
+ pop_token(token);
+
+ // if we're not an lval, throw an error
+ if (!token.is_lval())
+ throw expression_error(expression_error::NOT_LVAL, token.offset());
+}
+
+
+//-------------------------------------------------
+// pop_token_rval - pop a token off the stack
+// and ensure that it is a proper rval
+//-------------------------------------------------
+
+inline void parsed_expression::pop_token_rval(parse_token &token)
+{
+ // start with normal pop
+ pop_token(token);
+
+ // symbol and memory tokens get resolved down to number tokens
+ if (token.is_symbol() || token.is_memory())
+ token.configure_number(token.get_lval_value(m_symtable));
+
+ // to be an rval, the final token must be a number
+ if (!token.is_number())
+ throw expression_error(expression_error::NOT_RVAL, token.offset());
+}
+
+
+//-------------------------------------------------
+// execute_tokens - execute a postfix sequence
+// of tokens
+//-------------------------------------------------
+
+UINT64 parsed_expression::execute_tokens()
+{
+ // reset the token stack
+ m_token_stack_ptr = 0;
+
+ // loop over the entire sequence
+ parse_token t1, t2, result;
+ for (parse_token *token = m_tokenlist.first(); token != NULL; token = token->next())
+ {
+ // symbols/numbers/strings just get pushed
+ if (!token->is_operator())
+ {
+ push_token(*token);
+ continue;
+ }
+
+ // otherwise, switch off the operator
+ switch (token->optype())
+ {
+ case TVL_PREINCREMENT:
+ pop_token_lval(t1);
+ push_token(result.configure_number(t1.get_lval_value(m_symtable) + 1).set_offset(t1));
+ t1.set_lval_value(m_symtable, result.value());
+ break;
+
+ case TVL_PREDECREMENT:
+ pop_token_lval(t1);
+ push_token(result.configure_number(t1.get_lval_value(m_symtable) - 1).set_offset(t1));
+ t1.set_lval_value(m_symtable, result.value());
+ break;
+
+ case TVL_POSTINCREMENT:
+ pop_token_lval(t1);
+ push_token(result.configure_number(t1.get_lval_value(m_symtable)).set_offset(t1));
+ t1.set_lval_value(m_symtable, result.value() + 1);
+ break;
+
+ case TVL_POSTDECREMENT:
+ pop_token_lval(t1);
+ push_token(result.configure_number(t1.get_lval_value(m_symtable)).set_offset(t1));
+ t1.set_lval_value(m_symtable, result.value() - 1);
+ break;
+
+ case TVL_COMPLEMENT:
+ pop_token_rval(t1);
+ push_token(result.configure_number(!t1.value()).set_offset(t1));
+ break;
+
+ case TVL_NOT:
+ pop_token_rval(t1);
+ push_token(result.configure_number(~t1.value()).set_offset(t1));
+ break;
+
+ case TVL_UPLUS:
+ pop_token_rval(t1);
+ push_token(result.configure_number(t1.value()).set_offset(t1));
+ break;
+
+ case TVL_UMINUS:
+ pop_token_rval(t1);
+ push_token(result.configure_number(-t1.value()).set_offset(t1));
+ break;
+
+ case TVL_MULTIPLY:
+ pop_token_rval(t2); pop_token_rval(t1);
+ push_token(result.configure_number(t1.value() * t2.value()).set_offset(t1, t2));
+ break;
+
+ case TVL_DIVIDE:
+ pop_token_rval(t2); pop_token_rval(t1);
+ if (t2.value() == 0)
+ throw expression_error(expression_error::DIVIDE_BY_ZERO, t2.offset());
+ push_token(result.configure_number(t1.value() / t2.value()).set_offset(t1, t2));
+ break;
+
+ case TVL_MODULO:
+ pop_token_rval(t2); pop_token_rval(t1);
+ if (t2.value() == 0)
+ throw expression_error(expression_error::DIVIDE_BY_ZERO, t2.offset());
+ push_token(result.configure_number(t1.value() % t2.value()).set_offset(t1, t2));
+ break;
+
+ case TVL_ADD:
+ pop_token_rval(t2); pop_token_rval(t1);
+ push_token(result.configure_number(t1.value() + t2.value()).set_offset(t1, t2));
+ break;
+
+ case TVL_SUBTRACT:
+ pop_token_rval(t2); pop_token_rval(t1);
+ push_token(result.configure_number(t1.value() - t2.value()).set_offset(t1, t2));
+ break;
+
+ case TVL_LSHIFT:
+ pop_token_rval(t2); pop_token_rval(t1);
+ push_token(result.configure_number(t1.value() << t2.value()).set_offset(t1, t2));
+ break;
+
+ case TVL_RSHIFT:
+ pop_token_rval(t2); pop_token_rval(t1);
+ push_token(result.configure_number(t1.value() >> t2.value()).set_offset(t1, t2));
+ break;
+
+ case TVL_LESS:
+ pop_token_rval(t2); pop_token_rval(t1);
+ push_token(result.configure_number(t1.value() < t2.value()).set_offset(t1, t2));
+ break;
+
+ case TVL_LESSOREQUAL:
+ pop_token_rval(t2); pop_token_rval(t1);
+ push_token(result.configure_number(t1.value() <= t2.value()).set_offset(t1, t2));
+ break;
+
+ case TVL_GREATER:
+ pop_token_rval(t2); pop_token_rval(t1);
+ push_token(result.configure_number(t1.value() > t2.value()).set_offset(t1, t2));
+ break;
+
+ case TVL_GREATEROREQUAL:
+ pop_token_rval(t2); pop_token_rval(t1);
+ push_token(result.configure_number(t1.value() >= t2.value()).set_offset(t1, t2));
+ break;
+
+ case TVL_EQUAL:
+ pop_token_rval(t2); pop_token_rval(t1);
+ push_token(result.configure_number(t1.value() == t2.value()).set_offset(t1, t2));
+ break;
+
+ case TVL_NOTEQUAL:
+ pop_token_rval(t2); pop_token_rval(t1);
+ push_token(result.configure_number(t1.value() != t2.value()).set_offset(t1, t2));
+ break;
+
+ case TVL_BAND:
+ pop_token_rval(t2); pop_token_rval(t1);
+ push_token(result.configure_number(t1.value() & t2.value()).set_offset(t1, t2));
+ break;
+
+ case TVL_BXOR:
+ pop_token_rval(t2); pop_token_rval(t1);
+ push_token(result.configure_number(t1.value() ^ t2.value()).set_offset(t1, t2));
+ break;
+
+ case TVL_BOR:
+ pop_token_rval(t2); pop_token_rval(t1);
+ push_token(result.configure_number(t1.value() | t2.value()).set_offset(t1, t2));
+ break;
+
+ case TVL_LAND:
+ pop_token_rval(t2); pop_token_rval(t1);
+ push_token(result.configure_number(t1.value() && t2.value()).set_offset(t1, t2));
+ break;
+
+ case TVL_LOR:
+ pop_token_rval(t2); pop_token_rval(t1);
+ push_token(result.configure_number(t1.value() || t2.value()).set_offset(t1, t2));
+ break;
+
+ case TVL_ASSIGN:
+ pop_token_rval(t2); pop_token_lval(t1);
+ push_token(result.configure_number(t2.value()).set_offset(t2));
+ t1.set_lval_value(m_symtable, t2.value());
+ break;
+
+ case TVL_ASSIGNMULTIPLY:
+ pop_token_rval(t2); pop_token_lval(t1);
+ push_token(result.configure_number(t1.get_lval_value(m_symtable) * t2.value()).set_offset(t1, t2));
+ t1.set_lval_value(m_symtable, result.value());
+ break;
+
+ case TVL_ASSIGNDIVIDE:
+ pop_token_rval(t2); pop_token_lval(t1);
+ if (t2.value() == 0)
+ throw expression_error(expression_error::DIVIDE_BY_ZERO, t2.offset());
+ push_token(result.configure_number(t1.get_lval_value(m_symtable) / t2.value()).set_offset(t1, t2));
+ t1.set_lval_value(m_symtable, result.value());
+ break;
+
+ case TVL_ASSIGNMODULO:
+ pop_token_rval(t2); pop_token_lval(t1);
+ if (t2.value() == 0)
+ throw expression_error(expression_error::DIVIDE_BY_ZERO, t2.offset());
+ push_token(result.configure_number(t1.get_lval_value(m_symtable) % t2.value()).set_offset(t1, t2));
+ t1.set_lval_value(m_symtable, result.value());
+ break;
+
+ case TVL_ASSIGNADD:
+ pop_token_rval(t2); pop_token_lval(t1);
+ push_token(result.configure_number(t1.get_lval_value(m_symtable) + t2.value()).set_offset(t1, t2));
+ t1.set_lval_value(m_symtable, result.value());
+ break;
+
+ case TVL_ASSIGNSUBTRACT:
+ pop_token_rval(t2); pop_token_lval(t1);
+ push_token(result.configure_number(t1.get_lval_value(m_symtable) - t2.value()).set_offset(t1, t2));
+ t1.set_lval_value(m_symtable, result.value());
+ break;
+
+ case TVL_ASSIGNLSHIFT:
+ pop_token_rval(t2); pop_token_lval(t1);
+ push_token(result.configure_number(t1.get_lval_value(m_symtable) << t2.value()).set_offset(t1, t2));
+ t1.set_lval_value(m_symtable, result.value());
+ break;
+
+ case TVL_ASSIGNRSHIFT:
+ pop_token_rval(t2); pop_token_lval(t1);
+ push_token(result.configure_number(t1.get_lval_value(m_symtable) >> t2.value()).set_offset(t1, t2));
+ t1.set_lval_value(m_symtable, result.value());
+ break;
+
+ case TVL_ASSIGNBAND:
+ pop_token_rval(t2); pop_token_lval(t1);
+ push_token(result.configure_number(t1.get_lval_value(m_symtable) & t2.value()).set_offset(t1, t2));
+ t1.set_lval_value(m_symtable, result.value());
+ break;
+
+ case TVL_ASSIGNBXOR:
+ pop_token_rval(t2); pop_token_lval(t1);
+ push_token(result.configure_number(t1.get_lval_value(m_symtable) ^ t2.value()).set_offset(t1, t2));
+ t1.set_lval_value(m_symtable, result.value());
+ break;
+
+ case TVL_ASSIGNBOR:
+ pop_token_rval(t2); pop_token_lval(t1);
+ push_token(result.configure_number(t1.get_lval_value(m_symtable) | t2.value()).set_offset(t1, t2));
+ t1.set_lval_value(m_symtable, result.value());
+ break;
+
+ case TVL_COMMA:
+ if (!token->is_function_separator())
+ {
+ pop_token_rval(t2); pop_token_rval(t1);
+ push_token(t2);
+ }
+ break;
+
+ case TVL_MEMORYAT:
+ pop_token_rval(t1);
+ push_token(result.configure_memory(t1.value(), *token));
+ break;
+
+ case TVL_EXECUTEFUNC:
+ execute_function(*token);
+ break;
+
+ default:
+ throw expression_error(expression_error::SYNTAX, token->offset());
+ }
+ }
+
+ // pop the final result
+ pop_token_rval(result);
+
+ // error if our stack isn't empty
+ if (peek_token(0) != NULL)
+ throw expression_error(expression_error::SYNTAX, 0);
+
+ return result.value();
+}
+
+
+
+//**************************************************************************
+// PARSE TOKEN
+//**************************************************************************
+
+//-------------------------------------------------
+// parse_token - constructor
+//-------------------------------------------------
+
+parsed_expression::parse_token::parse_token(int offset)
+ : m_next(NULL),
+ m_type(INVALID),
+ m_offset(offset),
+ m_value(0),
+ m_flags(0),
+ m_string(NULL),
+ m_symbol(NULL)
+{
+}
+
+
+//-------------------------------------------------
+// get_lval_value - call the getter function
+// for a SYMBOL token
+//-------------------------------------------------
+
+UINT64 parsed_expression::parse_token::get_lval_value(symbol_table *table)
+{
+ // get the value of a symbol
+ if (is_symbol())
+ return m_symbol->value();
+
+ // or get the value from the memory callbacks
+ else if (is_memory() && table != NULL)
+ return table->memory_value(m_string, memory_space(), address(), 1 << memory_size());
+
+ return 0;
+}
+
+
+//-------------------------------------------------
+// set_lval_value - call the setter function
+// for a SYMBOL token
+//-------------------------------------------------
+
+inline void parsed_expression::parse_token::set_lval_value(symbol_table *table, UINT64 value)
+{
+ // set the value of a symbol
+ if (is_symbol())
+ m_symbol->set_value(value);
+
+ // or set the value via the memory callbacks
+ else if (is_memory() && table != NULL)
+ table->set_memory_value(m_string, memory_space(), address(), 1 << memory_size(), value);
+}
+
+
+//-------------------------------------------------
+// execute_function - handle an execute function
+// operator
+//-------------------------------------------------
+
+void parsed_expression::execute_function(parse_token &token)
+{
+ // pop off all pushed parameters
+ UINT64 funcparams[MAX_FUNCTION_PARAMS];
+ symbol_entry *symbol = NULL;
+ int paramcount = 0;
+ while (paramcount < MAX_FUNCTION_PARAMS)
+ {
+ // peek at the next token on the stack
+ parse_token *peek = peek_token(0);
+ if (peek == NULL)
+ throw expression_error(expression_error::INVALID_PARAM_COUNT, token.offset());
+
+ // if it is a function symbol, break out of the loop
+ if (peek->is_symbol())
+ {
+ symbol = peek->symbol();
+ if (symbol->is_function())
+ {
+ parse_token t1;
+ pop_token(t1);
+ break;
+ }
+ }
+
+ // otherwise, pop as a standard rval
+ parse_token t1;
+ pop_token_rval(t1);
+ funcparams[MAX_FUNCTION_PARAMS - (++paramcount)] = t1.value();
+ }
+
+ // if we didn't find the symbol, fail
+ if (paramcount == MAX_FUNCTION_PARAMS)
+ throw expression_error(expression_error::INVALID_PARAM_COUNT, token.offset());
+
+ // execute the function and push the result
+ function_symbol_entry *function = downcast<function_symbol_entry *>(symbol);
+ parse_token result(token.offset());
+ result.configure_number(function->execute(paramcount, &funcparams[MAX_FUNCTION_PARAMS - paramcount]));
+ push_token(result);
+}
diff --git a/trunk/src/emu/debug/express.h b/trunk/src/emu/debug/express.h
new file mode 100644
index 00000000000..8b348c67ef0
--- /dev/null
+++ b/trunk/src/emu/debug/express.h
@@ -0,0 +1,413 @@
+/***************************************************************************
+
+ express.h
+
+ Generic expressions engine.
+
+****************************************************************************
+
+ 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 __EXPRESS_H__
+#define __EXPRESS_H__
+
+#include "emu.h"
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// values for the address space passed to external_read/write_memory
+enum expression_space
+{
+ EXPSPACE_INVALID,
+ EXPSPACE_PROGRAM_LOGICAL,
+ EXPSPACE_DATA_LOGICAL,
+ EXPSPACE_IO_LOGICAL,
+ EXPSPACE_SPACE3_LOGICAL,
+ EXPSPACE_PROGRAM_PHYSICAL,
+ EXPSPACE_DATA_PHYSICAL,
+ EXPSPACE_IO_PHYSICAL,
+ EXPSPACE_SPACE3_PHYSICAL,
+ EXPSPACE_OPCODE,
+ EXPSPACE_RAMWRITE,
+ EXPSPACE_REGION
+};
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// forward references
+class symbol_table;
+
+
+// ======================> expression_error
+
+// an expression_error holds an error code and a string offset
+class expression_error
+{
+public:
+ // codes
+ enum error_code
+ {
+ NONE,
+ NOT_LVAL,
+ NOT_RVAL,
+ SYNTAX,
+ UNKNOWN_SYMBOL,
+ INVALID_NUMBER,
+ INVALID_TOKEN,
+ STACK_OVERFLOW,
+ STACK_UNDERFLOW,
+ UNBALANCED_PARENS,
+ DIVIDE_BY_ZERO,
+ OUT_OF_MEMORY,
+ INVALID_PARAM_COUNT,
+ UNBALANCED_QUOTES,
+ TOO_MANY_STRINGS,
+ INVALID_MEMORY_SIZE,
+ INVALID_MEMORY_SPACE,
+ NO_SUCH_MEMORY_SPACE,
+ INVALID_MEMORY_NAME,
+ MISSING_MEMORY_NAME
+ };
+
+ // construction/destruction
+ expression_error(error_code code, int offset = 0)
+ : m_code(code),
+ m_offset(offset) { }
+
+ // operators
+ operator error_code() const { return m_code; }
+
+ // getters
+ error_code code() const { return m_code; }
+ int offset() const { return m_offset; }
+ const char *code_string() const;
+
+private:
+ // internal state
+ error_code m_code;
+ int m_offset;
+};
+
+
+// ======================> symbol_entry
+
+// symbol_entry describes a symbol in a symbol table
+class symbol_entry
+{
+ friend class simple_list<symbol_entry>;
+
+protected:
+ // symbol types
+ enum symbol_type
+ {
+ SMT_INTEGER,
+ SMT_FUNCTION
+ };
+
+ // construction/destruction
+ symbol_entry(symbol_table &table, symbol_type type, const char *name, void *ref);
+ virtual ~symbol_entry();
+
+public:
+ // getters
+ symbol_entry *next() const { return m_next; }
+ const char *name() const { return m_name; }
+
+ // type checking
+ bool is_function() const { return (m_type == SMT_FUNCTION); }
+
+ // symbol access
+ virtual bool is_lval() const = 0;
+ virtual UINT64 value() const = 0;
+ virtual void set_value(UINT64 newvalue) = 0;
+
+protected:
+ // internal state
+ symbol_entry * m_next; // link to next entry
+ symbol_table & m_table; // pointer back to the owning table
+ symbol_type m_type; // type of symbol
+ astring m_name; // name of the symbol
+ void * m_ref; // internal reference
+};
+
+
+// ======================> symbol_table
+
+// a symbol_table holds symbols of various types which the expression engine
+// queries to look up symbols
+class symbol_table
+{
+public:
+ // callback functions for getting/setting a symbol value
+ typedef UINT64 (*getter_func)(symbol_table &table, void *symref);
+ typedef void (*setter_func)(symbol_table &table, void *symref, UINT64 value);
+
+ // callback functions for function execution
+ typedef UINT64 (*execute_func)(symbol_table &table, void *symref, int numparams, const UINT64 *paramlist);
+
+ // callback functions for memory reads/writes
+ typedef expression_error::error_code (*valid_func)(void *cbparam, const char *name, expression_space space);
+ typedef UINT64 (*read_func)(void *cbparam, const char *name, expression_space space, UINT32 offset, int size);
+ typedef void (*write_func)(void *cbparam, const char *name, expression_space space, UINT32 offset, int size, UINT64 value);
+
+ enum read_write
+ {
+ READ_ONLY = 0,
+ READ_WRITE
+ };
+
+ // construction/destruction
+ symbol_table(void *globalref, symbol_table *parent = NULL);
+
+ // getters
+ symbol_entry *first() const { return m_symlist.first(); }
+ symbol_table *parent() const { return m_parent; }
+ void *globalref() const { return m_globalref; }
+
+ // setters
+ void configure_memory(void *param, valid_func valid, read_func read, write_func write);
+
+ // symbol access
+ void add(const char *name, read_write rw, UINT64 *ptr = NULL);
+ void add(const char *name, UINT64 constvalue);
+ void add(const char *name, void *ref, getter_func getter, setter_func setter = NULL);
+ void add(const char *name, void *ref, int minparams, int maxparams, execute_func execute);
+ symbol_entry *find(const char *name) { return m_symlist.find(name); }
+ symbol_entry *find_deep(const char *name);
+
+ // value getter/setter
+ UINT64 value(const char *symbol);
+ void set_value(const char *symbol, UINT64 value);
+
+ // memory accessors
+ expression_error::error_code memory_valid(const char *name, expression_space space);
+ UINT64 memory_value(const char *name, expression_space space, UINT32 offset, int size);
+ void set_memory_value(const char *name, expression_space space, UINT32 offset, int size, UINT64 value);
+
+private:
+ // internal state
+ symbol_table * m_parent; // pointer to the parent symbol table
+ void * m_globalref; // global reference parameter
+ tagged_list<symbol_entry> m_symlist; // list of symbols
+ void * m_memory_param; // callback parameter for memory
+ valid_func m_memory_valid; // validation callback
+ read_func m_memory_read; // read callback
+ write_func m_memory_write; // write callback
+};
+
+
+// ======================> parsed_expression
+
+// a parsed_expression holds a pre-parsed expression that can be
+// efficiently executed at a later time
+class parsed_expression
+{
+public:
+ // construction/destruction
+ parsed_expression(const parsed_expression &src) { copy(src); }
+ parsed_expression(symbol_table *symtable = NULL, const char *expression = NULL, UINT64 *result = NULL);
+
+ // operators
+ parsed_expression &operator=(const parsed_expression &src) { copy(src); return *this; }
+
+ // getters
+ bool is_empty() const { return (m_tokenlist.count() == 0); }
+ const char *original_string() const { return m_original_string; }
+ symbol_table *symbols() const { return m_symtable; }
+
+ // setters
+ void set_symbols(symbol_table *symtable) { m_symtable = symtable; }
+
+ // execution
+ void parse(const char *string);
+ UINT64 execute() { return execute_tokens(); }
+
+private:
+ // a single token
+ class parse_token
+ {
+ friend class simple_list<parse_token>;
+
+ // operator flags
+ enum
+ {
+ TIN_OPTYPE_SHIFT = 0, // 8 bits (0-7)
+ TIN_OPTYPE_MASK = 0xff << TIN_OPTYPE_SHIFT,
+ TIN_RIGHT_TO_LEFT_SHIFT = 16, // 1 bit (16)
+ TIN_RIGHT_TO_LEFT_MASK = 1 << TIN_RIGHT_TO_LEFT_SHIFT,
+ TIN_FUNCTION_SHIFT = 17, // 1 bit (17)
+ TIN_FUNCTION_MASK = 1 << TIN_FUNCTION_SHIFT,
+ TIN_MEMORY_SIZE_SHIFT = 18, // 2 bits (18-19)
+ TIN_MEMORY_SIZE_MASK = 3 << TIN_MEMORY_SIZE_SHIFT,
+ TIN_MEMORY_SPACE_SHIFT = 20, // 4 bits (20-23)
+ TIN_MEMORY_SPACE_MASK = 0xf << TIN_MEMORY_SPACE_SHIFT,
+ TIN_PRECEDENCE_SHIFT = 24, // 8 bits (24-31)
+ TIN_PRECEDENCE_MASK = 0xff << TIN_PRECEDENCE_SHIFT
+ };
+
+ // types of tokens
+ enum token_type
+ {
+ INVALID = 0,
+ NUMBER,
+ STRING,
+ MEMORY,
+ SYMBOL,
+ OPERATOR
+ };
+
+ public:
+ // construction/destruction
+ parse_token(int offset = 0);
+
+ // getters
+ parse_token *next() const { return m_next; }
+ int offset() const { return m_offset; }
+ bool is_number() const { return (m_type == NUMBER); }
+ bool is_string() const { return (m_type == STRING); }
+ bool is_memory() const { return (m_type == MEMORY); }
+ bool is_symbol() const { return (m_type == SYMBOL); }
+ bool is_operator() const { return (m_type == OPERATOR); }
+ bool is_operator(UINT8 type) const { return (m_type == OPERATOR && optype() == type); }
+ bool is_lval() const { return ((m_type == SYMBOL && m_symbol->is_lval()) || m_type == MEMORY); }
+
+ UINT64 value() const { assert(m_type == NUMBER); return m_value; }
+ UINT32 address() const { assert(m_type == MEMORY); return m_value; }
+ symbol_entry *symbol() const { assert(m_type == SYMBOL); return m_symbol; }
+
+ UINT8 optype() const { assert(m_type == OPERATOR); return (m_flags & TIN_OPTYPE_MASK) >> TIN_OPTYPE_SHIFT; }
+ UINT8 precedence() const { assert(m_type == OPERATOR); return (m_flags & TIN_PRECEDENCE_MASK) >> TIN_PRECEDENCE_SHIFT; }
+ bool is_function_separator() const { assert(m_type == OPERATOR); return ((m_flags & TIN_FUNCTION_MASK) != 0); }
+ bool right_to_left() const { assert(m_type == OPERATOR); return ((m_flags & TIN_RIGHT_TO_LEFT_MASK) != 0); }
+ expression_space memory_space() const { assert(m_type == OPERATOR || m_type == MEMORY); return expression_space((m_flags & TIN_MEMORY_SPACE_MASK) >> TIN_MEMORY_SPACE_SHIFT); }
+ int memory_size() const { assert(m_type == OPERATOR || m_type == MEMORY); return (m_flags & TIN_MEMORY_SIZE_MASK) >> TIN_MEMORY_SIZE_SHIFT; }
+
+ // setters
+ parse_token &set_offset(int offset) { m_offset = offset; return *this; }
+ parse_token &set_offset(const parse_token &src) { m_offset = src.m_offset; return *this; }
+ parse_token &set_offset(const parse_token &src1, const parse_token &src2) { m_offset = MIN(src1.m_offset, src2.m_offset); return *this; }
+ parse_token &configure_number(UINT64 value) { m_type = NUMBER; m_value = value; return *this; }
+ parse_token &configure_string(const char *string) { m_type = STRING; m_string = string; return *this; }
+ parse_token &configure_memory(UINT32 address, parse_token &memoryat) { m_type = MEMORY; m_value = address; m_flags = memoryat.m_flags; m_string = memoryat.m_string; return *this; }
+ parse_token &configure_symbol(symbol_entry &symbol) { m_type = SYMBOL; m_symbol = &symbol; return *this; }
+ parse_token &configure_operator(UINT8 optype, UINT8 precedence)
+ { m_type = OPERATOR; m_flags = ((optype << TIN_OPTYPE_SHIFT) & TIN_OPTYPE_MASK) | ((precedence << TIN_PRECEDENCE_SHIFT) & TIN_PRECEDENCE_MASK); return *this; }
+
+ parse_token &set_function_separator() { assert(m_type == OPERATOR); m_flags |= TIN_FUNCTION_MASK; return *this; }
+ parse_token &set_right_to_left() { assert(m_type == OPERATOR); m_flags |= TIN_RIGHT_TO_LEFT_MASK; return *this; }
+ parse_token &set_memory_space(expression_space space) { assert(m_type == OPERATOR || m_type == MEMORY); m_flags = (m_flags & ~TIN_MEMORY_SPACE_MASK) | ((space << TIN_MEMORY_SPACE_SHIFT) & TIN_MEMORY_SPACE_MASK); return *this; }
+ parse_token &set_memory_size(int log2ofbits) { assert(m_type == OPERATOR || m_type == MEMORY); m_flags = (m_flags & ~TIN_MEMORY_SIZE_MASK) | ((log2ofbits << TIN_MEMORY_SIZE_SHIFT) & TIN_MEMORY_SIZE_MASK); return *this; }
+ parse_token &set_memory_source(const char *string) { assert(m_type == OPERATOR || m_type == MEMORY); m_string = string; return *this; }
+
+ // access
+ UINT64 get_lval_value(symbol_table *symtable);
+ void set_lval_value(symbol_table *symtable, UINT64 value);
+
+ private:
+ // internal state
+ parse_token * m_next; // next token in list
+ token_type m_type; // type of token
+ int m_offset; // offset within the string
+ UINT64 m_value; // integral value
+ UINT32 m_flags; // additional flags/info
+ const char * m_string; // associated string
+ symbol_entry * m_symbol; // symbol pointer
+ };
+
+ // an expression_string holds an indexed string parsed from the expression
+ class expression_string
+ {
+ friend class simple_list<expression_string>;
+
+ public:
+ // construction/destruction
+ expression_string(const char *string, int length = 0)
+ : m_next(NULL),
+ m_string(string, (length == 0) ? strlen(string) : length) { }
+
+ // operators
+ operator const char *() { return m_string; }
+ operator const char *() const { return m_string; }
+
+ private:
+ // internal state
+ expression_string * m_next; // next string in list
+ astring m_string; // copy of the string
+ };
+
+ // internal helpers
+ void copy(const parsed_expression &src);
+ void print_tokens(FILE *out);
+
+ // parsing helpers
+ void parse_string_into_tokens();
+ void parse_symbol_or_number(parse_token &token, const char *&string);
+ void parse_number(parse_token &token, const char *string, int base, expression_error::error_code errcode);
+ void parse_quoted_char(parse_token &token, const char *&string);
+ void parse_quoted_string(parse_token &token, const char *&string);
+ void parse_memory_operator(parse_token &token, const char *string);
+ void normalize_operator(parse_token *prevtoken, parse_token &thistoken);
+ void infix_to_postfix();
+
+ // execution helpers
+ void push_token(parse_token &token);
+ void pop_token(parse_token &token);
+ parse_token *peek_token(int count);
+ void pop_token_lval(parse_token &token);
+ void pop_token_rval(parse_token &token);
+ UINT64 execute_tokens();
+ void execute_function(parse_token &token);
+
+ // constants
+ static const int MAX_FUNCTION_PARAMS = 16;
+ static const int MAX_STACK_DEPTH = 16;
+
+ // internal state
+ symbol_table * m_symtable; // symbol table
+ astring m_original_string; // original string (prior to parsing)
+ simple_list<parse_token> m_tokenlist; // token list
+ simple_list<expression_string> m_stringlist; // string list
+ int m_token_stack_ptr; // stack pointer (used during execution)
+ parse_token m_token_stack[MAX_STACK_DEPTH]; // token stack (used during execution)
+};
+
+
+#endif
diff --git a/trunk/src/emu/debug/textbuf.c b/trunk/src/emu/debug/textbuf.c
new file mode 100644
index 00000000000..08b8fb2214e
--- /dev/null
+++ b/trunk/src/emu/debug/textbuf.c
@@ -0,0 +1,326 @@
+/***************************************************************************
+
+ textbuf.c
+
+ Debugger text buffering engine.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "osdcore.h"
+#include "textbuf.h"
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define MAX_LINE_LENGTH 250
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/* typedef struct _text_buffer text_buffer; -- declared in textbuf.h */
+struct _text_buffer
+{
+ char * buffer;
+ INT32 * lineoffs;
+ INT32 bufsize;
+ INT32 bufstart;
+ INT32 bufend;
+ INT32 linesize;
+ INT32 linestart;
+ INT32 lineend;
+ UINT32 linestartseq;
+ INT32 maxwidth;
+};
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ buffer_used - return the number of bytes
+ currently held in the buffer
+-------------------------------------------------*/
+
+INLINE INT32 buffer_used(text_buffer *text)
+{
+ INT32 used = text->bufend - text->bufstart;
+ if (used < 0)
+ used += text->bufsize;
+ return used;
+}
+
+
+/*-------------------------------------------------
+ buffer_space - return the number of bytes
+ available in the buffer
+-------------------------------------------------*/
+
+INLINE INT32 buffer_space(text_buffer *text)
+{
+ return text->bufsize - buffer_used(text);
+}
+
+
+
+/***************************************************************************
+
+ Buffer object management
+
+***************************************************************************/
+
+/*-------------------------------------------------
+ text_buffer_alloc - allocate a new text buffer
+-------------------------------------------------*/
+
+text_buffer *text_buffer_alloc(UINT32 bytes, UINT32 lines)
+{
+ text_buffer *text;
+
+ /* allocate memory for the text buffer object */
+ text = (text_buffer *)osd_malloc(sizeof(*text));
+ if (!text)
+ return NULL;
+
+ /* allocate memory for the buffer itself */
+ text->buffer = (char *)osd_malloc_array(bytes);
+ if (!text->buffer)
+ {
+ osd_free(text);
+ return NULL;
+ }
+
+ /* allocate memory for the lines array */
+ text->lineoffs = (INT32 *)osd_malloc_array(lines * sizeof(text->lineoffs[0]));
+ if (!text->lineoffs)
+ {
+ osd_free(text->buffer);
+ osd_free(text);
+ return NULL;
+ }
+
+ /* initialize the buffer description */
+ text->bufsize = bytes;
+ text->linesize = lines;
+ text_buffer_clear(text);
+
+ return text;
+}
+
+
+/*-------------------------------------------------
+ text_buffer_free - free a previously allocated
+ text buffer
+-------------------------------------------------*/
+
+void text_buffer_free(text_buffer *text)
+{
+ if (text->lineoffs)
+ osd_free(text->lineoffs);
+ if (text->buffer)
+ osd_free(text->buffer);
+ osd_free(text);
+}
+
+
+/*-------------------------------------------------
+ text_buffer_clear - clear a text buffer
+-------------------------------------------------*/
+
+void text_buffer_clear(text_buffer *text)
+{
+ /* reset all the buffer pointers and other bits */
+ text->bufstart = 0;
+ text->bufend = 0;
+
+ text->linestart = 0;
+ text->lineend = 0;
+ text->linestartseq = 0;
+
+ text->maxwidth = 0;
+
+ /* create the initial line */
+ text->lineoffs[0] = 0;
+ text->buffer[text->lineoffs[0]] = 0;
+}
+
+
+
+/***************************************************************************
+
+ Adding data to the buffer
+
+***************************************************************************/
+
+/*-------------------------------------------------
+ text_buffer_print - print data to the text
+ buffer
+-------------------------------------------------*/
+
+void text_buffer_print(text_buffer *text, const char *data)
+{
+ text_buffer_print_wrap(text, data, 10000);
+}
+
+
+/*-------------------------------------------------
+ text_buffer_print_wrap - print data to the
+ text buffer with word wrapping to a given
+ column
+-------------------------------------------------*/
+
+void text_buffer_print_wrap(text_buffer *text, const char *data, int wrapcol)
+{
+ INT32 stopcol = (wrapcol < MAX_LINE_LENGTH) ? wrapcol : MAX_LINE_LENGTH;
+ INT32 needed_space;
+
+ /* we need to ensure there is enough space for this string plus enough for the max line length */
+ needed_space = (INT32)strlen(data) + MAX_LINE_LENGTH;
+
+ /* make space in the buffer if we need to */
+ while (buffer_space(text) < needed_space && text->linestart != text->lineend)
+ {
+ text->linestartseq++;
+ if (++text->linestart >= text->linesize)
+ text->linestart = 0;
+ text->bufstart = text->lineoffs[text->linestart];
+ }
+
+ /* now add the data */
+ for ( ; *data; data++)
+ {
+ int ch = *data;
+ int linelen;
+
+ /* a CR resets our position */
+ if (ch == '\r')
+ text->bufend = text->lineoffs[text->lineend];
+
+ /* non-CR data is just characters */
+ else if (ch != '\n')
+ text->buffer[text->bufend++] = ch;
+
+ /* an explicit newline or line-too-long condition inserts a newline */
+ linelen = text->bufend - text->lineoffs[text->lineend];
+ if (ch == '\n' || linelen >= stopcol)
+ {
+ int overflow = 0;
+
+ /* if we're wrapping, back off until we hit a space */
+ if (linelen >= wrapcol)
+ {
+ /* scan backwards, removing characters along the way */
+ overflow = 1;
+ while (overflow < linelen && text->buffer[text->bufend - overflow] != ' ')
+ overflow++;
+
+ /* if we found a space, take it; otherwise, reset and pretend we didn't try */
+ if (overflow < linelen)
+ linelen -= overflow;
+ else
+ overflow = 0;
+ }
+
+ /* did we beat the max width */
+ if (linelen > text->maxwidth)
+ text->maxwidth = linelen;
+
+ /* append a terminator */
+ if (overflow == 0)
+ text->buffer[text->bufend++] = 0;
+ else
+ text->buffer[text->bufend - overflow] = 0;
+
+ /* determine what the next line will be */
+ if (++text->lineend >= text->linesize)
+ text->lineend = 0;
+
+ /* if we're out of lines, consume the next one */
+ if (text->lineend == text->linestart)
+ {
+ text->linestartseq++;
+ if (++text->linestart >= text->linesize)
+ text->linestart = 0;
+ text->bufstart = text->lineoffs[text->linestart];
+ }
+
+ /* if we don't have enough room in the buffer for a max line, wrap to the start */
+ if (text->bufend + MAX_LINE_LENGTH + 1 >= text->bufsize)
+ text->bufend = 0;
+
+ /* create a new empty line */
+ text->lineoffs[text->lineend] = text->bufend - (overflow ? (overflow - 1) : 0);
+ }
+ }
+
+ /* NULL terminate what we have on this line */
+ text->buffer[text->bufend] = 0;
+}
+
+
+
+/***************************************************************************
+
+ Reading data from the buffer
+
+***************************************************************************/
+
+/*-------------------------------------------------
+ text_buffer_max_width - return the maximum
+ width of all lines seen so far
+-------------------------------------------------*/
+
+UINT32 text_buffer_max_width(text_buffer *text)
+{
+ return text->maxwidth;
+}
+
+
+/*-------------------------------------------------
+ text_buffer_num_lines - return the number of
+ lines in the text buffer
+-------------------------------------------------*/
+
+UINT32 text_buffer_num_lines(text_buffer *text)
+{
+ INT32 lines = text->lineend + 1 - text->linestart;
+ if (lines <= 0)
+ lines += text->linesize;
+ return lines;
+}
+
+
+/*-------------------------------------------------
+ text_buffer_line_index_to_seqnum - convert a
+ line index into a sequence number
+-------------------------------------------------*/
+
+UINT32 text_buffer_line_index_to_seqnum(text_buffer *text, UINT32 index)
+{
+ return text->linestartseq + index;
+}
+
+
+/*-------------------------------------------------
+ text_buffer_get_seqnum_line - get a pointer to
+ an indexed line in the buffer
+-------------------------------------------------*/
+
+const char *text_buffer_get_seqnum_line(text_buffer *text, UINT32 seqnum)
+{
+ UINT32 numlines = text_buffer_num_lines(text);
+ UINT32 index = seqnum - text->linestartseq;
+ if (index >= numlines)
+ return NULL;
+ return &text->buffer[text->lineoffs[(text->linestart + index) % text->linesize]];
+}
diff --git a/trunk/src/emu/debug/textbuf.h b/trunk/src/emu/debug/textbuf.h
new file mode 100644
index 00000000000..64347dab179
--- /dev/null
+++ b/trunk/src/emu/debug/textbuf.h
@@ -0,0 +1,56 @@
+/***************************************************************************
+
+ textbuf.h
+
+ Debugger text buffering engine.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#ifndef __TEXTBUF_H__
+#define __TEXTBUF_H__
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _text_buffer text_buffer;
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+/* allocate a new text buffer */
+text_buffer *text_buffer_alloc(UINT32 bytes, UINT32 lines);
+
+/* free a text buffer */
+void text_buffer_free(text_buffer *text);
+
+/* clear a text buffer */
+void text_buffer_clear(text_buffer *text);
+
+/* "print" data to a text buffer */
+void text_buffer_print(text_buffer *text, const char *data);
+
+/* "print" data to a text buffer with word wrapping to a given column */
+void text_buffer_print_wrap(text_buffer *text, const char *data, int wrapcol);
+
+/* get the maximum width of lines seen so far */
+UINT32 text_buffer_max_width(text_buffer *text);
+
+/* get the current number of lines in the buffer */
+UINT32 text_buffer_num_lines(text_buffer *text);
+
+/* get an absolute sequence number for a given line */
+UINT32 text_buffer_line_index_to_seqnum(text_buffer *text, UINT32 index);
+
+/* get a sequenced line from the text buffer */
+const char *text_buffer_get_seqnum_line(text_buffer *text, UINT32 seqnum);
+
+
+#endif /* __TEXTBUF_H__ */
diff --git a/trunk/src/emu/debugger.c b/trunk/src/emu/debugger.c
new file mode 100644
index 00000000000..dc960d34322
--- /dev/null
+++ b/trunk/src/emu/debugger.c
@@ -0,0 +1,148 @@
+/*********************************************************************
+
+ debugger.c
+
+ Front-end debugger interfaces.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "osdepend.h"
+#include "debug/debugcpu.h"
+#include "debug/debugcmd.h"
+#include "debug/debugcon.h"
+#include "debug/express.h"
+#include "debug/debugvw.h"
+#include "debugint/debugint.h"
+#include <ctype.h>
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _machine_entry machine_entry;
+struct _machine_entry
+{
+ machine_entry * next;
+ running_machine * machine;
+};
+
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+static machine_entry *machine_list;
+static int atexit_registered;
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void debugger_exit(running_machine &machine);
+
+
+
+/***************************************************************************
+ CENTRAL INITIALIZATION POINT
+***************************************************************************/
+
+/*-------------------------------------------------
+ debugger_init - start up all subsections
+-------------------------------------------------*/
+
+void debugger_init(running_machine &machine)
+{
+ /* only if debugging is enabled */
+ if (machine.debug_flags & DEBUG_FLAG_ENABLED)
+ {
+ machine_entry *entry;
+
+ /* initialize the submodules */
+ machine.m_debug_view = auto_alloc(machine, debug_view_manager(machine));
+ debug_cpu_init(machine);
+ debug_command_init(machine);
+ debug_console_init(machine);
+
+ /* always initialize the internal render debugger */
+ debugint_init(machine);
+
+ /* allocate a new entry for our global list */
+ machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(debugger_exit), &machine));
+ entry = global_alloc(machine_entry);
+ entry->next = machine_list;
+ entry->machine = &machine;
+ machine_list = entry;
+
+ /* register an atexit handler if we haven't yet */
+ if (!atexit_registered)
+ atexit(debugger_flush_all_traces_on_abnormal_exit);
+ atexit_registered = TRUE;
+
+ /* listen in on the errorlog */
+ machine.add_logerror_callback(debug_errorlog_write_line);
+
+ /* initialize osd debugger features */
+ machine.osd().init_debugger();
+ }
+}
+
+
+/*-------------------------------------------------
+ debugger_refresh_display - redraw the current
+ video display
+-------------------------------------------------*/
+
+void debugger_refresh_display(running_machine &machine)
+{
+ machine.video().frame_update(true);
+}
+
+
+/*-------------------------------------------------
+ debugger_exit - remove ourself from the
+ global list of active machines for cleanup
+-------------------------------------------------*/
+
+static void debugger_exit(running_machine &machine)
+{
+ machine_entry **entryptr;
+
+ /* remove this machine from the list; it came down cleanly */
+ for (entryptr = &machine_list; *entryptr != NULL; entryptr = &(*entryptr)->next)
+ if ((*entryptr)->machine == &machine)
+ {
+ machine_entry *deleteme = *entryptr;
+ *entryptr = deleteme->next;
+ global_free(deleteme);
+ break;
+ }
+}
+
+
+/*-------------------------------------------------
+ debugger_flush_all_traces_on_abnormal_exit -
+ flush any traces in the event of an aborted
+ execution
+-------------------------------------------------*/
+
+void debugger_flush_all_traces_on_abnormal_exit(void)
+{
+ /* clear out the machine list and flush traces on each one */
+ while (machine_list != NULL)
+ {
+ machine_entry *deleteme = machine_list;
+ debug_cpu_flush_traces(*deleteme->machine);
+ machine_list = deleteme->next;
+ global_free(deleteme);
+ }
+}
diff --git a/trunk/src/emu/debugger.h b/trunk/src/emu/debugger.h
new file mode 100644
index 00000000000..6b2978974eb
--- /dev/null
+++ b/trunk/src/emu/debugger.h
@@ -0,0 +1,140 @@
+/****************************************************************************
+
+ debugger.h
+
+ General debugging interfaces
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+****************************************************************************/
+
+#pragma once
+
+#ifndef __DEBUGGER_H__
+#define __DEBUGGER_H__
+
+#include "debug/debugcpu.h"
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+/* ----- core debugger functions ----- */
+
+/* initialize the debugger */
+void debugger_init(running_machine &machine);
+
+/* redraw the current video display */
+void debugger_refresh_display(running_machine &machine);
+
+/* OSD can call this to safely flush all traces in the event of a crash */
+void debugger_flush_all_traces_on_abnormal_exit(void);
+
+
+
+/***************************************************************************
+ CPU CORE INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ debugger_instruction_hook - CPU cores call
+ this once per instruction from CPU cores
+-------------------------------------------------*/
+
+INLINE void debugger_instruction_hook(device_t *device, offs_t curpc)
+{
+ if ((device->machine().debug_flags & DEBUG_FLAG_CALL_HOOK) != 0)
+ device->debug()->instruction_hook(curpc);
+}
+
+
+/*-------------------------------------------------
+ debugger_exception_hook - CPU cores call this
+ anytime an exception is generated
+-------------------------------------------------*/
+
+INLINE void debugger_exception_hook(device_t *device, int exception)
+{
+ if ((device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ device->debug()->exception_hook(exception);
+}
+
+
+
+/***************************************************************************
+ CPU EXECUTION SYSTEM INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ debugger_start_cpu_hook - the CPU execution
+ system calls this hook before beginning
+ execution for the given CPU
+-------------------------------------------------*/
+
+INLINE void debugger_start_cpu_hook(device_t *device, attotime endtime)
+{
+ if ((device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ device->debug()->start_hook(endtime);
+}
+
+
+/*-------------------------------------------------
+ debugger_stop_cpu_hook - the CPU execution
+ system calls this hook when ending execution
+ for the given CPU
+-------------------------------------------------*/
+
+INLINE void debugger_stop_cpu_hook(device_t *device)
+{
+ if ((device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ device->debug()->stop_hook();
+}
+
+
+/*-------------------------------------------------
+ debugger_interrupt_hook - the CPU execution
+ system calls this hook when an interrupt is
+ acknowledged
+-------------------------------------------------*/
+
+INLINE void debugger_interrupt_hook(device_t *device, int irqline)
+{
+ if ((device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ device->debug()->interrupt_hook(irqline);
+}
+
+
+
+/***************************************************************************
+ GENERAL INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ debugger_break - stop in the debugger at the
+ next opportunity
+-------------------------------------------------*/
+
+INLINE void debugger_break(running_machine &machine)
+{
+ if ((machine.debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ debug_cpu_get_visible_cpu(machine)->debug()->halt_on_next_instruction("Internal breakpoint\n");
+}
+
+
+/*-------------------------------------------------
+ debugger_within_instruction_hook - call this
+ to determine if the debugger is currently
+ halted within the instruction hook
+-------------------------------------------------*/
+
+INLINE int debugger_within_instruction_hook(running_machine &machine)
+{
+ if ((machine.debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ return debug_cpu_within_instruction_hook(machine);
+ return FALSE;
+}
+
+
+#endif /* __DEBUGGER_H__ */
diff --git a/trunk/src/emu/debugint/debugint.c b/trunk/src/emu/debugint/debugint.c
new file mode 100644
index 00000000000..f02ef141acb
--- /dev/null
+++ b/trunk/src/emu/debugint/debugint.c
@@ -0,0 +1,1484 @@
+/*********************************************************************
+
+ debugint.c
+
+ Internal debugger frontend using render interface.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "ui.h"
+#include "rendfont.h"
+#include "uimenu.h"
+#include "uiinput.h"
+#include "video.h"
+#include "osdepend.h"
+
+#include "debug/debugvw.h"
+#include "debug/dvdisasm.h"
+#include "debug/dvmemory.h"
+#include "debug/dvstate.h"
+#include "debug/debugcon.h"
+#include "debug/debugcpu.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define BORDER_YTHICKNESS 1
+#define BORDER_XTHICKNESS 1
+#define HSB_HEIGHT 20
+#define VSB_WIDTH 20
+#define TITLE_HEIGHT 20
+
+enum
+{
+ RECT_DVIEW,
+ RECT_DVIEW_CLIENT,
+ RECT_DVIEW_TITLE,
+ RECT_DVIEW_HSB,
+ RECT_DVIEW_VSB,
+ RECT_DVIEW_SIZE,
+};
+
+enum
+{
+ VIEW_STATE_BUTTON = 0x01,
+ VIEW_STATE_MOVING = 0x02,
+ VIEW_STATE_SIZING = 0x04,
+ VIEW_STATE_NEEDS_UPDATE = 0x08,
+ VIEW_STATE_FOLLOW_CPU = 0x10,
+};
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+//#define NX(_dv, _x) ((float) (_x)/(float)rect_get_width(&(_dv)->bounds))
+//#define NY(_dv, _y) ((float) (_y)/(float)rect_get_height(&(_dv)->bounds))
+#define NX(_dv, _x) ((float) (_x)/(float) (dv)->rt_width)
+#define NY(_dv, _y) ((float) (_y)/(float) (dv)->rt_height)
+
+
+#define LIST_ADD_FRONT(_list, _elem, _type) \
+ do { \
+ (_elem)->next = _list; \
+ _list = _elem; \
+ } while (0)
+
+#define LIST_GET_PREVIOUS(_list, _elem, _prev) \
+ do { \
+ _prev = NULL; \
+ if (_list != _elem) \
+ for (_prev = _list; _prev != NULL; _prev = _prev->next) \
+ if ((_prev)->next == _elem) \
+ break; \
+ } while (0)
+
+#define LIST_GET_LAST(_list, _last) \
+ do { \
+ for (_last = _list; _last != NULL; _last = _last->next) \
+ if ((_last)->next == NULL) \
+ break; \
+ } while (0)
+
+#define LIST_REMOVE(_list, _elem, _type) \
+ do { \
+ _type *_hlp; \
+ LIST_GET_PREVIOUS(_list, _elem, _hlp); \
+ if (_hlp != NULL) \
+ (_hlp)->next = (_elem)->next; \
+ else \
+ _list = (_elem)->next; \
+ } while (0)
+
+#define LIST_ADD_BACK(_list, _elem, _type) \
+ do { \
+ _type *_hlp; \
+ LIST_GET_LAST(_list, _hlp); \
+ if (_hlp != NULL) \
+ (_hlp)->next = _elem; \
+ else \
+ _list = _elem; \
+ } while (0)
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _adjustment adjustment;
+struct _adjustment
+{
+ int visible;
+ int lower;
+ int upper;
+ int value;
+ int step_increment;
+ int page_increment;
+ int page_size;
+};
+
+class DView;
+
+class DView_edit
+{
+ DISABLE_COPYING(DView_edit);
+
+public:
+ DView_edit()
+ { }
+ ~DView_edit()
+ { }
+ int active;
+ render_container * container;
+ astring str;
+};
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void dview_update(debug_view &dw, void *osdprivate);
+static int map_point(DView *dv, INT32 target_x, INT32 target_y, INT32 *mapped_x, INT32 *mapped_y);
+
+class DView
+{
+ DISABLE_COPYING(DView);
+
+public:
+ DView(render_target *target, running_machine &machine, debug_view_type type, int flags)
+ : next(NULL),
+ type(0),
+ state(0),
+ ofs_x(0),
+ ofs_y(0)
+ {
+ this->target = target;
+ //dv->container = render_target_get_component_container(target, name, &pos);
+ this->container = target->debug_alloc();
+ this->view = machine.debug_view().alloc_view(type, dview_update, this);
+ this->type = type;
+ this->m_machine = &machine;
+ this->state = flags | VIEW_STATE_NEEDS_UPDATE;
+
+ // initial size
+ this->bounds.min_x = 0;
+ this->bounds.min_y = 0;
+ this->bounds.max_x = 300;
+ this->bounds.max_y = 300;
+
+ /* specials */
+ switch (type)
+ {
+ case DVT_DISASSEMBLY:
+ /* set up disasm view */
+ downcast<debug_view_disasm *>(this->view)->set_expression("curpc");
+ //debug_view_ property_UINT32(dv->view, DVP_DASM_TRACK_LIVE, 1);
+ break;
+ default:
+ break;
+ }
+ }
+ ~DView()
+ {
+ this->target->debug_free(*this->container);
+ machine().debug_view().free_view(*this->view);
+ }
+
+ running_machine &machine() const { assert(m_machine != NULL); return *m_machine; }
+
+ DView * next;
+
+ int type;
+ debug_view * view;
+ render_container * container;
+ render_target * target;
+ running_machine * m_machine;
+ int state;
+ // drawing
+ rectangle bounds;
+ int ofs_x;
+ int ofs_y;
+ astring title;
+ int last_x;
+ int last_y;
+ // Scrollbars
+ adjustment hsb;
+ adjustment vsb;
+ // render target tracking
+ INT32 rt_width;
+ INT32 rt_height;
+ //optional
+ DView_edit editor;
+};
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE int rect_get_width(rectangle *r)
+{
+ return r->max_x - r->min_x + 1;
+}
+
+INLINE int rect_get_height(rectangle *r)
+{
+ return r->max_y - r->min_y + 1;
+}
+
+INLINE void rect_set_width(rectangle *r, int width)
+{
+ r->max_x = r->min_x + width - 1;
+}
+
+INLINE void rect_set_height(rectangle *r, int height)
+{
+ r->max_y = r->min_y + height - 1;
+}
+
+INLINE void rect_move(rectangle *r, int x, int y)
+{
+ int dx = x - r->min_x;
+ int dy = y - r->min_y;
+
+ r->min_x += dx;
+ r->max_x += dx;
+ r->min_y += dy;
+ r->max_y += dy;
+}
+
+INLINE int dview_is_state(DView *dv, int state)
+{
+ return ((dv->state & state) ? TRUE : FALSE);
+}
+
+INLINE int dview_is_state_all(DView *dv, int state)
+{
+ return ((dv->state & state) == state ? TRUE : FALSE);
+}
+
+INLINE void dview_set_state(DView *dv, int state, int onoff)
+{
+ if (onoff)
+ dv->state |= state;
+ else
+ dv->state &= ~state;
+}
+
+/***************************************************************************
+ LOCAL VARIABLES
+***************************************************************************/
+
+static render_font * debug_font;
+static int debug_font_width;
+static int debug_font_height;
+static float debug_font_aspect;
+static DView * list;
+static DView * focus_view;
+
+static ui_menu * menu;
+static DView_edit * cur_editor;
+
+static void set_focus_view(DView *dv)
+{
+ if (focus_view != NULL)
+ dview_set_state(focus_view, VIEW_STATE_NEEDS_UPDATE, TRUE);
+
+ if (dv != NULL)
+ dview_set_state(dv, VIEW_STATE_NEEDS_UPDATE, TRUE);
+
+ if (focus_view != dv)
+ {
+ focus_view = dv;
+ LIST_REMOVE(list, dv, DView);
+ LIST_ADD_FRONT(list, dv, DView);
+ dv->target->debug_top(*dv->container);
+ }
+}
+
+static DView *dview_alloc(render_target *target, running_machine &machine, debug_view_type type, int flags)
+{
+ DView *dv;
+
+ dv = auto_alloc(machine, DView(target, machine, type, flags));
+
+ /* add to list */
+
+ LIST_ADD_BACK(list, dv, DView);
+
+ return dv;
+}
+
+static void dview_free(DView *dv)
+{
+ //astring_free(dv->title);
+ LIST_REMOVE(list, dv, DView);
+ auto_free(dv->machine(), dv);
+}
+
+static void dview_get_rect(DView *dv, int type, rectangle *rect)
+{
+ *rect = dv->bounds;
+ switch (type)
+ {
+ case RECT_DVIEW:
+ break;
+ case RECT_DVIEW_CLIENT:
+ rect->min_x += BORDER_XTHICKNESS;
+ rect->max_x -= (BORDER_XTHICKNESS + dv->vsb.visible * VSB_WIDTH);
+ rect->min_y += 2 * BORDER_YTHICKNESS + TITLE_HEIGHT;
+ rect->max_y -= (BORDER_YTHICKNESS + dv->hsb.visible * HSB_HEIGHT);
+ break;
+ case RECT_DVIEW_HSB:
+ rect->min_x += 0;
+ rect->max_x -= /* dv->vsb.visible * */ VSB_WIDTH;
+ rect->min_y = dv->bounds.max_y - HSB_HEIGHT;
+ rect->max_y -= 0;
+ break;
+ case RECT_DVIEW_VSB:
+ rect->min_x = dv->bounds.max_x - VSB_WIDTH;
+ rect->max_x -= 0;
+ rect->min_y += TITLE_HEIGHT;
+ rect->max_y -= /* dv->hsb.visible * */ HSB_HEIGHT;
+ break;
+ case RECT_DVIEW_SIZE:
+ rect->min_x = dv->bounds.max_x - VSB_WIDTH;
+ rect->max_x -= 0;
+ rect->min_y = dv->bounds.max_y - HSB_HEIGHT;
+ rect->max_y -= 0;
+ break;
+ case RECT_DVIEW_TITLE:
+ rect->min_x += 0;
+ rect->max_x -= 0;
+ rect->min_y += 0;
+ rect->max_y = rect->min_y + TITLE_HEIGHT - 1;
+ break;
+ default:
+ assert_always(FALSE, "unknown rectangle type");
+ }
+}
+
+
+static void dview_clear(DView *dv)
+{
+ dv->container->empty();
+}
+
+static void dview_draw_outlined_box(DView *dv, int rtype, int x, int y, int w, int h, rgb_t bg)
+{
+ rectangle r;
+
+ dview_get_rect(dv, rtype, &r);
+ ui_draw_outlined_box(dv->container, NX(dv, x + r.min_x), NY(dv, y + r.min_y),
+ NX(dv, x + r.min_x + w), NY(dv, y + r.min_y + h), bg);
+}
+
+static void dview_draw_box(DView *dv, int rtype, int x, int y, int w, int h, rgb_t col)
+{
+ rectangle r;
+
+ dview_get_rect(dv, rtype, &r);
+ dv->container->add_rect(NX(dv, x + r.min_x), NY(dv, y + r.min_y),
+ NX(dv, x + r.min_x + w), NY(dv, y + r.min_y + h), col,
+ PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+}
+
+static void dview_draw_char(DView *dv, int rtype, int x, int y, int h, rgb_t col, UINT16 ch)
+{
+ rectangle r;
+
+ dview_get_rect(dv, rtype, &r);
+ dv->container->add_char(
+ NX(dv, x + r.min_x),
+ NY(dv, y + r.min_y),
+ NY(dv, h),
+ debug_font_aspect,
+ //(float) rect_get_height(&dv->bounds) / (float) rect_get_width(&dv->bounds), //render_get_ui_aspect(),
+ col,
+ *debug_font,
+ ch);
+}
+
+static int dview_xy_in_rect(DView *dv, int type, int x, int y)
+{
+ rectangle r;
+
+ dview_get_rect(dv, type, &r);
+ if (x >= r.min_x && x <= r.max_x && y >= r.min_y && y <= r.max_y)
+ return TRUE;
+ return FALSE;
+}
+
+static void dview_draw_hsb(DView *dv)
+{
+ int vt;
+ int ts;
+ //int sz = SLIDER_SIZE;
+ int sz;
+ rectangle r;
+ adjustment *sb = &dv->hsb;
+
+ dview_get_rect(dv, RECT_DVIEW_HSB, &r);
+
+ dview_draw_outlined_box(dv, RECT_DVIEW_HSB, 0, 0, VSB_WIDTH,HSB_HEIGHT, MAKE_ARGB(0xff, 0xff, 0x00, 0x00));
+ dview_draw_outlined_box(dv, RECT_DVIEW_HSB, rect_get_width(&r) - VSB_WIDTH, 0, VSB_WIDTH, HSB_HEIGHT, MAKE_ARGB(0xff, 0xff, 0x00, 0x00));
+
+ ts = (r.max_x - r.min_x + 1) - 2 * VSB_WIDTH;
+
+ sz = (ts * (sb->page_size)) / (sb->upper - sb->lower);
+ ts = ts - sz;
+
+ vt = (ts * (sb->value - sb->lower)) / (sb->upper - sb->lower - sb->page_size) + sz / 2 + r.min_x + VSB_WIDTH;
+
+ dview_draw_outlined_box(dv, RECT_DVIEW_HSB, vt - sz / 2, 0, sz, HSB_HEIGHT, MAKE_ARGB(0xff, 0xff, 0x00, 0x00));
+}
+
+static void dview_draw_vsb(DView *dv)
+{
+ int vt;
+ int ts;
+ //int sz = SLIDER_SIZE;
+ int sz;
+ rectangle r;
+ adjustment *sb = &dv->vsb;
+
+ dview_get_rect(dv, RECT_DVIEW_VSB, &r);
+
+ dview_draw_outlined_box(dv, RECT_DVIEW_VSB, 0, rect_get_height(&r) - HSB_HEIGHT, VSB_WIDTH, HSB_HEIGHT, MAKE_ARGB(0xff, 0xff, 0x00, 0x00));
+ dview_draw_outlined_box(dv, RECT_DVIEW_VSB, 0, 0, VSB_WIDTH, HSB_HEIGHT, MAKE_ARGB(0xff, 0xff, 0x00, 0x00));
+
+ ts = (r.max_y - r.min_y + 1) - 2 * HSB_HEIGHT;
+
+ sz = (ts * (sb->page_size)) / (sb->upper - sb->lower);
+ ts = ts - sz;
+
+ vt = (ts * (sb->value - sb->lower)) / (sb->upper - sb->lower - sb->page_size) + sz / 2 + HSB_HEIGHT;
+
+ dview_draw_outlined_box(dv, RECT_DVIEW_VSB, 0, vt - sz / 2, VSB_WIDTH, sz, MAKE_ARGB(0xff, 0xff, 0x00, 0x00));
+}
+
+static void dview_draw_size(DView *dv)
+{
+ rectangle r;
+
+ dview_get_rect(dv, RECT_DVIEW_SIZE, &r);
+
+ dview_draw_outlined_box(dv, RECT_DVIEW_SIZE, 0, 0,
+ rect_get_width(&r),rect_get_height(&r), MAKE_ARGB(0xff, 0xff, 0xff, 0x00));
+}
+
+static void dview_set_title(DView *dv, astring title)
+{
+ if (dv->title.cmp(title) != 0)
+ {
+ dv->title = title;
+ dview_set_state(dv, VIEW_STATE_NEEDS_UPDATE, TRUE);
+ }
+}
+
+static void dview_draw_title(DView *dv)
+{
+ int i;
+ rgb_t col = MAKE_ARGB(0xff,0x00,0x00,0xff);
+ rectangle r;
+
+ dview_get_rect(dv, RECT_DVIEW_TITLE, &r);
+
+ if (dv == focus_view)
+ col = MAKE_ARGB(0xff,0x00,0x7f,0x00);
+
+ dview_draw_outlined_box(dv, RECT_DVIEW_TITLE, 0, 0, rect_get_width(&dv->bounds), TITLE_HEIGHT, col);
+
+ if (!dv->title)
+ return;
+
+ for (i=0; i<strlen(dv->title); i++)
+ {
+ dview_draw_char(dv, RECT_DVIEW_TITLE, i * debug_font_width + BORDER_XTHICKNESS,
+ BORDER_YTHICKNESS, debug_font_height, //r.max_y - 2 * BORDER_YTHICKNESS,
+ MAKE_ARGB(0xff,0xff,0xff,0xff), (UINT16) dv->title[i] );
+ }
+}
+
+static int dview_on_mouse(DView *dv, int mx, int my, int button)
+{
+ int clicked = (button && !dview_is_state(dv, VIEW_STATE_BUTTON));
+ int handled = TRUE;
+ int x,y;
+
+ if (button && dview_is_state_all(dv, VIEW_STATE_BUTTON | VIEW_STATE_MOVING))
+ {
+ int dx = mx - dv->last_x;
+ int dy = my - dv->last_y;
+
+ dv->ofs_x += dx;
+ dv->ofs_y += dy;
+ dv->last_x = mx;
+ dv->last_y = my;
+ dview_set_state(dv, VIEW_STATE_NEEDS_UPDATE, TRUE);
+ return TRUE;
+ }
+ else if (button && dview_is_state_all(dv, VIEW_STATE_BUTTON | VIEW_STATE_SIZING))
+ {
+ int dx = mx - dv->last_x;
+ int dy = my - dv->last_y;
+
+ dv->bounds.max_x += dx;
+ dv->bounds.max_y += dy;
+ dv->last_x = mx;
+ dv->last_y = my;
+ dview_set_state(dv, VIEW_STATE_NEEDS_UPDATE, TRUE);
+ return TRUE;
+ }
+ else
+ dview_set_state(dv, VIEW_STATE_MOVING | VIEW_STATE_SIZING, FALSE);
+
+ if (!map_point(dv, mx, my, &x, &y))
+ return FALSE;
+
+ if (dview_xy_in_rect(dv, RECT_DVIEW_TITLE, x, y))
+ {
+ /* on title, do nothing */
+ if (clicked) {
+ dv->last_x = mx;
+ dv->last_y = my;
+ set_focus_view(dv);
+ dview_set_state(dv, VIEW_STATE_MOVING, TRUE);
+ }
+ }
+ else if (dview_xy_in_rect(dv, RECT_DVIEW_HSB, x, y))
+ {
+ /* on horizontal scrollbar */
+ debug_view_xy pos;
+ adjustment *sb = &dv->hsb;
+
+ if (clicked)
+ {
+ rectangle r;
+ int xt;
+
+ dview_get_rect(dv, RECT_DVIEW_HSB, &r);
+ x -= r.min_x;
+
+ xt = (x - VSB_WIDTH) * (sb->upper - sb->lower) / (rect_get_width(&r) - 2 * dv->vsb.visible * VSB_WIDTH) + sb->lower;
+ if (x < VSB_WIDTH)
+ sb->value -= sb->step_increment;
+ else if (x > rect_get_width(&r) - VSB_WIDTH)
+ sb->value += sb->step_increment;
+ else if (xt < sb->value)
+ sb->value -= sb->page_increment;
+ else if (xt > sb->value)
+ sb->value += sb->page_increment;
+
+ if (sb->value < sb->lower)
+ sb->value = sb->lower;
+ if (sb->value > sb->upper)
+ sb->value = sb->upper;
+ }
+
+ pos = dv->view->visible_position();
+
+ if (sb->value != pos.x)
+ {
+ pos.x = sb->value;
+ dv->view->set_visible_position(pos);
+ dview_set_state(dv, VIEW_STATE_NEEDS_UPDATE, TRUE);
+ }
+ }
+ else if (dview_xy_in_rect(dv, RECT_DVIEW_VSB, x, y) )
+ {
+ /* on vertical scrollbar */
+ debug_view_xy pos;
+ adjustment *sb = &dv->vsb;
+
+ if (clicked)
+ {
+ rectangle r;
+ int yt;
+
+ dview_get_rect(dv, RECT_DVIEW_VSB, &r);
+ y -= r.min_y;
+ yt = (y - HSB_HEIGHT) * (sb->upper - sb->lower) / (rect_get_height(&r) - 2 * HSB_HEIGHT) + sb->lower;
+
+ if (y < HSB_HEIGHT)
+ sb->value -= sb->step_increment;
+ else if (y > rect_get_height(&r) - HSB_HEIGHT)
+ sb->value += sb->step_increment;
+ else if (yt < sb->value)
+ sb->value -= sb->page_increment;
+ else if (yt > sb->value)
+ sb->value += sb->page_increment;
+
+ if (sb->value < sb->lower)
+ sb->value = sb->lower;
+ if (sb->value > sb->upper)
+ sb->value = sb->upper;
+ }
+
+ pos = dv->view->visible_position();
+
+ if (sb->value != pos.y)
+ {
+ pos.y = sb->value;
+ dv->view->set_visible_position(pos);
+ dview_set_state(dv, VIEW_STATE_NEEDS_UPDATE, TRUE);
+ }
+ }
+ else if (dview_xy_in_rect(dv, RECT_DVIEW_SIZE, x, y))
+ {
+ /* on sizing area */
+ if (clicked)
+ {
+ dv->last_x = mx;
+ dv->last_y = my;
+ set_focus_view(dv);
+ dview_set_state(dv, VIEW_STATE_SIZING, TRUE);
+ }
+ }
+ else if (dview_xy_in_rect(dv, RECT_DVIEW_CLIENT, x, y))
+ {
+ y -= TITLE_HEIGHT;
+ if (dv->view->cursor_supported() && clicked && y >= 0)
+ {
+ debug_view_xy topleft = dv->view->visible_position();
+ debug_view_xy newpos;
+ newpos.x = topleft.x + x / debug_font_width;
+ newpos.y = topleft.y + y / debug_font_height;
+ dv->view->set_cursor_position(newpos);
+ dv->view->set_cursor_visible(true);
+ }
+ if (clicked)
+ set_focus_view(dv);
+ }
+ else
+ {
+ handled = FALSE;
+ }
+ dview_set_state(dv, VIEW_STATE_BUTTON, button);
+ return handled;
+
+}
+
+INLINE void map_attr_to_fg_bg(unsigned char attr, rgb_t *fg, rgb_t *bg)
+{
+
+ *bg = MAKE_ARGB(0xff,0xff,0xff,0xff);
+ *fg = MAKE_ARGB(0xff,0x00,0x00,0x00);
+
+ if(attr & DCA_ANCILLARY)
+ *bg = MAKE_ARGB(0xff,0xe0,0xe0,0xe0);
+ if(attr & DCA_SELECTED) {
+ *bg = MAKE_ARGB(0xff,0xff,0x80,0x80);
+ }
+ if(attr & DCA_CURRENT) {
+ *bg = MAKE_ARGB(0xff,0xff,0xff,0x00);
+ }
+ if(attr & DCA_CHANGED) {
+ *fg = MAKE_ARGB(0xff,0xff,0x00,0x00);
+ }
+ if(attr & DCA_INVALID) {
+ *fg = MAKE_ARGB(0xff,0x00,0x00,0xff);
+ }
+ if(attr & DCA_DISABLED) {
+ *fg = MAKE_ARGB(RGB_ALPHA(*fg),
+ (RGB_RED(*fg)+RGB_RED(*bg)) >> 1,
+ (RGB_GREEN(*fg)+RGB_GREEN(*bg)) >> 1,
+ (RGB_BLUE(*fg)+RGB_BLUE(*bg)) >> 1);
+ }
+ if(attr & DCA_COMMENT) {
+ *fg = MAKE_ARGB(0xff,0x00,0x80,0x00);
+ }
+}
+
+static void dview_draw(DView *dv)
+{
+ const debug_view_char *viewdata;
+ debug_view_xy vsize;
+ UINT32 i, j, xx, yy;
+ rgb_t bg_base, bg, fg;
+ rectangle r;
+
+ vsize = dv->view->visible_size();
+
+ bg_base = MAKE_ARGB(0xff,0xff,0xff,0xff);
+
+ /* always start clean */
+ dview_clear(dv);
+
+ dview_draw_title(dv);
+
+ dview_get_rect(dv, RECT_DVIEW_CLIENT, &r);
+
+ dview_draw_outlined_box(dv, RECT_DVIEW_CLIENT, 0, 0,
+ rect_get_width(&r) /*- (dv->vs ? VSB_WIDTH : 0)*/,
+ rect_get_height(&r) /*- (dv->hsb.visible ? HSB_HEIGHT : 0)*/, bg_base);
+
+ /* background first */
+ viewdata = dv->view->viewdata();
+
+ yy = BORDER_YTHICKNESS;
+ for(j=0; j<vsize.y; j++)
+ {
+ xx = BORDER_XTHICKNESS;
+ for(i=0; i<vsize.x; i++)
+ {
+ map_attr_to_fg_bg(viewdata->attrib, &fg, &bg);
+
+ if (bg != bg_base)
+ dview_draw_box(dv, RECT_DVIEW_CLIENT, xx, yy,
+ debug_font_width, debug_font_height, bg);
+ xx += debug_font_width;
+ viewdata++;
+ }
+ yy += debug_font_height;
+ }
+
+ /* now the text */
+ viewdata = dv->view->viewdata();
+
+ yy = BORDER_YTHICKNESS;
+ for(j=0; j<vsize.y; j++)
+ {
+ xx = BORDER_XTHICKNESS;
+ for(i=0; i<vsize.x; i++)
+ {
+ UINT16 s;
+ unsigned char v = viewdata->byte;
+
+ if (v != ' ')
+ {
+ if(v < 128) {
+ s = v;
+ } else {
+ s = 0xc0 | (v>>6);
+ s |= (0x80 | (v & 0x3f));
+ }
+ map_attr_to_fg_bg(viewdata->attrib, &fg, &bg);
+
+ dview_draw_char(dv, RECT_DVIEW_CLIENT, xx, yy, debug_font_height, fg, s);
+ }
+ xx += debug_font_width;
+ viewdata++;
+ }
+ yy += debug_font_height;
+ }
+
+ if(dv->hsb.visible)
+ dview_draw_hsb(dv);
+ if(dv->vsb.visible)
+ dview_draw_vsb(dv);
+ dview_draw_size(dv);
+}
+
+
+static void dview_size_allocate(DView *dv)
+{
+ debug_view_xy size, pos, col, vsize;
+ render_container::user_settings rcus;
+ rectangle r;
+
+ dv->container->get_user_settings(rcus);
+ rcus.m_xoffset = (float) dv->ofs_x / (float) dv->rt_width;
+ rcus.m_yoffset = (float) dv->ofs_y / (float) dv->rt_height;
+ rcus.m_xscale = 1.0; //(float) rect_get_width(&dv->bounds) / (float) dv->rt_width;
+ rcus.m_yscale = 1.0; //(float) rect_get_height(&dv->bounds) / (float) dv->rt_height;
+ dv->container->set_user_settings(rcus);
+ //printf("%d %d %d %d\n", wpos.min_x, wpos.max_x, wpos.min_y, wpos.max_y);
+
+ pos = dv->view->visible_position();
+ size = dv->view->total_size();
+
+ dv->hsb.visible = 0;
+ dv->vsb.visible = 0;
+ dview_get_rect(dv, RECT_DVIEW_CLIENT, &r);
+
+ dv->hsb.visible = (size.x * debug_font_width > rect_get_width(&r) ? 1 : 0);
+ dv->vsb.visible = (size.y * debug_font_height > rect_get_height(&r) ? 1 : 0);
+ dview_get_rect(dv, RECT_DVIEW_CLIENT, &r);
+
+ dv->hsb.visible = (size.x * debug_font_width > rect_get_width(&r) ? 1 : 0);
+ dv->vsb.visible = (size.y * debug_font_height > rect_get_height(&r) ? 1 : 0);
+ dview_get_rect(dv, RECT_DVIEW_CLIENT, &r);
+
+ col.y = (rect_get_height(&r) - 2 * BORDER_YTHICKNESS /*+ debug_font_height - 1*/) / debug_font_height;
+ col.x = (rect_get_width(&r) - 2 * BORDER_XTHICKNESS /*+ debug_font_width - 1*/) / debug_font_width;
+
+ vsize.y = size.y - pos.y;
+ vsize.x = size.x - pos.x;
+ if(vsize.y > col.y)
+ vsize.y = col.y;
+ else if(vsize.y < col.y) {
+ pos.y = size.y-col.y;
+ if(pos.y < 0)
+ pos.y = 0;
+ vsize.y = size.y-pos.y;
+ }
+ if(vsize.x > col.x)
+ vsize.x = col.x;
+ else if(vsize.x < col.x) {
+ pos.x = size.x-col.x;
+ if(pos.x < 0)
+ pos.x = 0;
+ vsize.x = size.x-pos.x;
+ }
+
+ dv->view->set_visible_position(pos);
+ dv->view->set_visible_size(vsize);
+
+ if(dv->hsb.visible) {
+ int span = (rect_get_width(&r) - 2 * BORDER_XTHICKNESS) / debug_font_width;
+
+ if(pos.x + span > size.x)
+ pos.x = size.x - span;
+ if(pos.x < 0)
+ pos.x = 0;
+ dv->hsb.lower = 0;
+ dv->hsb.upper = size.x;
+ dv->hsb.value = pos.x;
+ dv->hsb.step_increment = 1;
+ dv->hsb.page_increment = span;
+ dv->hsb.page_size = span;
+
+ dv->view->set_visible_position(pos);
+ }
+
+ if(dv->vsb.visible) {
+ int span = (rect_get_height(&r) - 2 * BORDER_YTHICKNESS) / debug_font_height;
+
+ if(pos.y + span > size.y)
+ pos.y = size.y - span;
+ if(pos.y < 0)
+ pos.y = 0;
+ dv->vsb.lower = 0;
+ dv->vsb.upper = size.y;
+ dv->vsb.value = pos.y;
+ dv->vsb.step_increment = 1;
+ dv->vsb.page_increment = span;
+ dv->vsb.page_size = span;
+
+ dv->view->set_visible_position(pos);
+ }
+}
+
+static void dview_update(debug_view &dw, void *osdprivate)
+{
+ DView *dv = (DView *) osdprivate;
+
+ dview_set_state(dv, VIEW_STATE_NEEDS_UPDATE, TRUE);
+
+#if 0
+ debug_view_xy size = dw.total_size();
+
+ if((dv->tr != size.y) || (dv->tc != size.x))
+ gtk_widget_queue_resize(GTK_WIDGET(dv));
+ else
+ gtk_widget_queue_draw(GTK_WIDGET(dv));
+#endif
+}
+
+static void debugint_exit(running_machine &machine)
+{
+ for (DView *ndv = list; ndv != NULL; )
+ {
+ DView *temp = ndv;
+ ndv = ndv->next;
+ dview_free(temp);
+ }
+ if (debug_font != NULL)
+ {
+ machine.render().font_free(debug_font);
+ debug_font = NULL;
+ }
+
+}
+
+void debugint_init(running_machine &machine)
+{
+ unicode_char ch;
+ int chw;
+ debug_font = machine.render().font_alloc("ui.bdf"); //ui_get_font(machine);
+ debug_font_width = 0;
+ debug_font_height = 15;
+
+ menu = NULL;
+ cur_editor = NULL;
+ list = NULL;
+ focus_view = NULL;
+
+ debug_font_aspect = machine.render().ui_aspect();
+
+ for (ch=0;ch<=127;ch++)
+ {
+ chw = debug_font->char_width(debug_font_height, debug_font_aspect, ch);
+ if (chw>debug_font_width)
+ debug_font_width = chw;
+ }
+ debug_font_width++;
+ /* FIXME: above does not really work */
+ debug_font_width = 10;
+ machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(debugint_exit), &machine));
+}
+
+#if 0
+static void set_view_by_name(render_target *target, const char *name)
+{
+ int i = 0;
+ const char *s;
+
+ for (i = 0; ; i++ )
+ {
+ s = target->view_name(i);
+ if (s == NULL)
+ return;
+ //printf("%d %s\n", i, s);
+ if (strcmp(name, s) == 0)
+ {
+ target->set_view(i);
+ //printf("%d\n", target->view() );
+ return;
+ }
+ }
+}
+#endif
+
+/*-------------------------------------------------
+ Menu Callbacks
+ -------------------------------------------------*/
+
+static void process_string(DView *dv, const char *str)
+{
+ switch (dv->type)
+ {
+ case DVT_DISASSEMBLY:
+ downcast<debug_view_disasm *>(dv->view)->set_expression(str);
+ break;
+ case DVT_CONSOLE:
+ if(!dv->editor.str[(long)0])
+ debug_cpu_get_visible_cpu(dv->machine())->debug()->single_step();
+ else
+ debug_console_execute_command(dv->machine(), str, 1);
+ break;
+ case DVT_MEMORY:
+ downcast<debug_view_memory *>(dv->view)->set_expression(str);
+ break;
+ }
+}
+
+static void on_memory_window_activate(DView *dv, const ui_menu_event *event)
+{
+}
+
+static void on_disassembly_window_activate(DView *dv, const ui_menu_event *event)
+{
+ DView *ndv;
+ render_target *target;
+ const debug_view_source *source;
+
+ target = &dv->machine().render().ui_target();
+
+ ndv = dview_alloc(target, dv->machine(), DVT_DISASSEMBLY, 0);
+ ndv->editor.active = TRUE;
+ ndv->editor.container = &dv->machine().render().ui_container();
+ source = ndv->view->source();
+ dview_set_title(ndv, source->name());
+ set_focus_view(ndv);
+
+}
+
+static void on_disasm_cpu_activate(DView *dv, const ui_menu_event *event)
+{
+ const debug_view_source *current = dv->view->source();
+
+ if (event->iptkey == IPT_UI_RIGHT)
+ {
+ current = current->next();
+ if (current == NULL)
+ {
+ current = dv->view->source_list().head();
+ }
+ dv->view->set_source(*current);
+ dview_set_state(dv, VIEW_STATE_NEEDS_UPDATE, TRUE);
+ dview_set_title(dv, current->name());
+ }
+}
+
+static void on_log_window_activate(DView *dv, const ui_menu_event *event)
+{
+ DView *ndv;
+ render_target *target;
+
+ target = &dv->machine().render().ui_target();
+ ndv = dview_alloc(target, dv->machine(), DVT_LOG, 0);
+ dview_set_title(ndv, "Log");
+ set_focus_view(ndv);
+}
+
+static void on_close_activate(DView *dv, const ui_menu_event *event)
+{
+ if (focus_view == dv)
+ set_focus_view(dv->next);
+ dview_free(dv);
+}
+
+static void on_run_activate(DView *dv, const ui_menu_event *event)
+{
+ debug_cpu_get_visible_cpu(dv->machine())->debug()->go();
+}
+
+#if 0
+void on_run_h_activate(DView *dv, const ui_menu_event *event)
+{
+ debugwin_show(0);
+ debug_cpu_get_visible_cpu(dv->machine())->debug()->go();
+}
+#endif
+
+static void on_run_cpu_activate(DView *dv, const ui_menu_event *event)
+{
+ debug_cpu_get_visible_cpu(dv->machine())->debug()->go_next_device();
+}
+
+static void on_run_irq_activate(DView *dv, const ui_menu_event *event)
+{
+ debug_cpu_get_visible_cpu(dv->machine())->debug()->go_interrupt();
+}
+
+static void on_run_vbl_activate(DView *dv, const ui_menu_event *event)
+{
+ debug_cpu_get_visible_cpu(dv->machine())->debug()->go_vblank();
+}
+
+static void on_step_into_activate(DView *dv, const ui_menu_event *event)
+{
+ debug_cpu_get_visible_cpu(dv->machine())->debug()->single_step();
+}
+
+static void on_step_over_activate(DView *dv, const ui_menu_event *event)
+{
+ debug_cpu_get_visible_cpu(dv->machine())->debug()->single_step_over();
+}
+
+#ifdef UNUSED_CODE
+static void on_step_out_activate(DView *dv, const ui_menu_event *event)
+{
+ debug_cpu_get_visible_cpu(dv->machine())->debug()->single_step_out();
+}
+#endif
+
+static void on_hard_reset_activate(DView *dv, const ui_menu_event *event)
+{
+ dv->machine().schedule_hard_reset();
+}
+
+static void on_soft_reset_activate(DView *dv, const ui_menu_event *event)
+{
+ dv->machine().schedule_soft_reset();
+ debug_cpu_get_visible_cpu(dv->machine())->debug()->go();
+}
+
+static void on_exit_activate(DView *dv, const ui_menu_event *event)
+{
+ dv->machine().schedule_exit();
+}
+
+static void on_view_opcodes_activate(DView *dv, const ui_menu_event *event)
+{
+ debug_view_disasm *dasmview = downcast<debug_view_disasm *>(focus_view->view);
+ disasm_right_column rc = dasmview->right_column();
+ disasm_right_column new_rc = DASM_RIGHTCOL_NONE;
+
+ if (event->iptkey == IPT_UI_RIGHT)
+ {
+ switch (rc)
+ {
+ case DASM_RIGHTCOL_RAW: new_rc = DASM_RIGHTCOL_ENCRYPTED; break;
+ case DASM_RIGHTCOL_ENCRYPTED: new_rc = DASM_RIGHTCOL_COMMENTS; break;
+ case DASM_RIGHTCOL_COMMENTS: new_rc = DASM_RIGHTCOL_RAW; break;
+ default: break;
+ }
+ dasmview->set_right_column(new_rc);
+ dview_set_state(dv, VIEW_STATE_NEEDS_UPDATE, TRUE);
+ }
+}
+
+static void on_run_to_cursor_activate(DView *dv, const ui_menu_event *event)
+{
+ char command[64];
+
+ if (dv->view->cursor_visible() && debug_cpu_get_visible_cpu(dv->machine()) == dv->view->source()->device())
+ {
+ offs_t address = downcast<debug_view_disasm *>(dv->view)->selected_address();
+ sprintf(command, "go %X", address);
+ debug_console_execute_command(dv->machine(), command, 1);
+ }
+}
+
+/*-------------------------------------------------
+ editor
+ -------------------------------------------------*/
+
+static void render_editor(DView_edit *editor)
+{
+ float width, maxwidth;
+ float x1, y1, x2, y2;
+
+ editor->container->empty();
+ /* get the size of the text */
+ ui_draw_text_full(editor->container, editor->str, 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, NULL);
+ width += 2 * UI_BOX_LR_BORDER;
+ maxwidth = MAX(width, 0.5);
+
+ /* compute our bounds */
+ x1 = 0.5f - 0.5f * maxwidth;
+ x2 = x1 + maxwidth;
+ y1 = 0.25f;
+ y2 = 0.45f - UI_BOX_TB_BORDER;
+
+ /* draw a box */
+ ui_draw_outlined_box(editor->container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+
+ /* take off the borders */
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+ y2 -= UI_BOX_TB_BORDER;
+
+ /* draw the text within it */
+ ui_draw_text_full(editor->container, editor->str, x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, NULL, NULL);
+
+}
+
+/*-------------------------------------------------
+ menu_main_populate - populate the main menu
+ -------------------------------------------------*/
+
+static void CreateMainMenu(running_machine &machine)
+{
+ const char *subtext = "";
+ int rc;
+ astring title;
+
+ if (menu != NULL)
+ ui_menu_free(menu);
+ menu = ui_menu_alloc(machine, &machine.render().ui_container(),NULL,NULL);
+
+ switch (focus_view->type)
+ {
+ case DVT_DISASSEMBLY:
+ title = "Disassembly:";
+ break;
+ case DVT_CONSOLE:
+ title = "Console:";
+ break;
+ case DVT_LOG:
+ title = "Log:";
+ break;
+ case DVT_MEMORY:
+ title = "Memory:";
+ break;
+ case DVT_STATE:
+ title = "State:";
+ break;
+ }
+
+ ui_menu_item_append(menu, title.cat(focus_view->title), NULL, MENU_FLAG_DISABLE, NULL);
+ ui_menu_item_append(menu, MENU_SEPARATOR_ITEM, NULL, 0, NULL);
+
+ switch (focus_view->type)
+ {
+ case DVT_DISASSEMBLY:
+ {
+ rc = downcast<debug_view_disasm *>(focus_view->view)->right_column();
+ switch(rc)
+ {
+ case DASM_RIGHTCOL_RAW: subtext = "Raw Opcodes"; break;
+ case DASM_RIGHTCOL_ENCRYPTED: subtext = "Enc Opcodes"; break;
+ case DASM_RIGHTCOL_COMMENTS: subtext = "Comments"; break;
+ }
+ ui_menu_item_append(menu, "View", subtext, MENU_FLAG_RIGHT_ARROW, (void *)on_view_opcodes_activate);
+ ui_menu_item_append(menu, "Run to cursor", NULL, 0, (void *)on_run_to_cursor_activate);
+
+ if (!dview_is_state(focus_view, VIEW_STATE_FOLLOW_CPU))
+ {
+ ui_menu_item_append(menu, "CPU", focus_view->view->source()->name(), MENU_FLAG_RIGHT_ARROW, (void *)on_disasm_cpu_activate);
+ }
+ ui_menu_item_append(menu, MENU_SEPARATOR_ITEM, NULL, 0, NULL);
+ break;
+ }
+ }
+
+ /* add input menu items */
+
+ ui_menu_item_append(menu, "New Memory Window", NULL, 0, (void *)on_memory_window_activate);
+ ui_menu_item_append(menu, "New Disassembly Window", NULL, 0, (void *)on_disassembly_window_activate);
+ ui_menu_item_append(menu, "New Error Log Window", NULL, 0, (void *)on_log_window_activate);
+ ui_menu_item_append(menu, MENU_SEPARATOR_ITEM, NULL, 0, NULL);
+ ui_menu_item_append(menu, "Run", NULL, 0, (void *)on_run_activate);
+ ui_menu_item_append(menu, "Run to Next CPU", NULL, 0, (void *)on_run_cpu_activate);
+ ui_menu_item_append(menu, "Run until Next Interrupt on This CPU", NULL, 0, (void *)on_run_irq_activate);
+ ui_menu_item_append(menu, "Run until Next VBLANK", NULL, 0, (void *)on_run_vbl_activate);
+ ui_menu_item_append(menu, MENU_SEPARATOR_ITEM, NULL, 0, NULL);
+ ui_menu_item_append(menu, "Step Into", NULL, 0, (void *)on_step_into_activate);
+ ui_menu_item_append(menu, "Step Over", NULL, 0, (void *)on_step_over_activate);
+ ui_menu_item_append(menu, MENU_SEPARATOR_ITEM, NULL, 0, NULL);
+ ui_menu_item_append(menu, "Soft Reset", NULL, 0, (void *)on_soft_reset_activate);
+ ui_menu_item_append(menu, "Hard Reset", NULL, 0, (void *)on_hard_reset_activate);
+ ui_menu_item_append(menu, MENU_SEPARATOR_ITEM, NULL, 0, NULL);
+ if (!dview_is_state(focus_view, VIEW_STATE_FOLLOW_CPU))
+ ui_menu_item_append(menu, "Close Window", NULL, 0, (void *)on_close_activate);
+ ui_menu_item_append(menu, "Exit", NULL, 0, (void *)on_exit_activate);
+}
+
+static int map_point(DView *dv, INT32 target_x, INT32 target_y, INT32 *mapped_x, INT32 *mapped_y)
+{
+ rectangle pos;
+
+ /* default to point not mapped */
+ *mapped_x = -1;
+ *mapped_y = -1;
+
+ pos = dv->bounds;
+ pos.min_x += dv->ofs_x;
+ pos.max_x += dv->ofs_x;
+ pos.min_y += dv->ofs_y;
+ pos.max_y += dv->ofs_y;
+ //render_target_get_component_container(target, name, &pos);
+
+ if (target_x >= pos.min_x && target_x <= pos.max_x && target_y >= pos.min_y && target_y <= pos.max_y)
+ {
+ *mapped_x = target_x - pos.min_x;
+ *mapped_y = target_y - pos.min_y;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void handle_mouse(running_machine &machine)
+{
+ render_target * mouse_target;
+ INT32 x,y;
+ int button;
+
+ if (menu != NULL)
+ return;
+
+ mouse_target = ui_input_find_mouse(machine, &x, &y, &button);
+
+ if (mouse_target == NULL)
+ return;
+ //printf("mouse %d %d %d\n", x, y, button);
+
+ for (DView *dv = list; dv != NULL; dv = dv->next)
+ {
+ if (mouse_target == dv->target)
+ {
+ if (dview_on_mouse(dv, x, y, button))
+ break;
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ handle_editor - handle the editor
+-------------------------------------------------*/
+
+static void handle_editor(running_machine &machine)
+{
+ if (focus_view->editor.active)
+ {
+ ui_event event;
+
+ /* loop while we have interesting events */
+ while (ui_input_pop_event(machine, &event))
+ {
+ switch (event.event_type)
+ {
+ case UI_EVENT_CHAR:
+ /* if it's a backspace and we can handle it, do so */
+ if ((event.ch == 8 || event.ch == 0x7f) && focus_view->editor.str.len() > 0)
+ {
+ /* autoschow */
+ cur_editor = &focus_view->editor;
+ cur_editor->str = cur_editor->str.substr(0, cur_editor->str.len()-1);
+ }
+ /* if it's any other key and we're not maxed out, update */
+ else if (event.ch >= ' ' && event.ch < 0x7f)
+ {
+ char buf[10];
+ int ret;
+ /* autoschow */
+ cur_editor = &focus_view->editor;
+ ret = utf8_from_uchar(buf, 10, event.ch);
+ buf[ret] = 0;
+ cur_editor->str = cur_editor->str.cat(buf);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (cur_editor != NULL)
+ {
+ render_editor(cur_editor);
+ if (ui_input_pressed(machine, IPT_UI_SELECT))
+ {
+ process_string(focus_view, focus_view->editor.str);
+ focus_view->editor.str = "";
+ cur_editor = NULL;
+ }
+ if (ui_input_pressed(machine, IPT_UI_CANCEL))
+ cur_editor = NULL;
+ }
+ }
+
+}
+
+
+/*-------------------------------------------------
+ menu_main - handle the main menu
+-------------------------------------------------*/
+
+static void handle_menus(running_machine &machine)
+{
+ const ui_menu_event *event;
+
+ machine.render().ui_container().empty();
+ ui_input_frame_update(machine);
+ if (menu != NULL)
+ {
+ /* process the menu */
+ event = ui_menu_process(machine, menu, 0);
+ if (event != NULL && (event->iptkey == IPT_UI_SELECT || (event->iptkey == IPT_UI_RIGHT)))
+ {
+ //ui_menu_free(menu);
+ //menu = NULL;
+ ((void (*)(DView *, const ui_menu_event *)) event->itemref)(focus_view, event);
+ //ui_menu_stack_push(ui_menu_alloc(machine, menu->container, (ui_menu_handler_func)event->itemref, NULL));
+ CreateMainMenu(machine);
+ }
+ else if (ui_input_pressed(machine, IPT_UI_CONFIGURE))
+ {
+ ui_menu_free(menu);
+ menu = NULL;
+ }
+ }
+ else
+ {
+ /* turn on menus if requested */
+ if (ui_input_pressed(machine, IPT_UI_CONFIGURE))
+ CreateMainMenu(machine);
+ /* turn on editor if requested */
+ //if (ui_input_pressed(machine, IPT_UI_UP) && focus_view->editor.active)
+ // cur_editor = &focus_view->editor;
+ handle_editor(machine);
+ }
+}
+
+//============================================================
+// followers_set_cpu
+//============================================================
+
+static void followers_set_cpu(device_t *device)
+{
+ astring title;
+
+ for (DView *dv = list; dv != NULL; dv = dv->next)
+ {
+ if (dview_is_state(dv, VIEW_STATE_FOLLOW_CPU))
+ {
+ const debug_view_source *source = dv->view->source_list().match_device(device);
+ switch (dv->type)
+ {
+ case DVT_DISASSEMBLY:
+ case DVT_STATE:
+ dv->view->set_source(*source);
+ title.printf("%s", source->name());
+ dview_set_title(dv, title);
+ break;
+ }
+ }
+ }
+ // and recompute the children
+ //console_recompute_children(main_console);
+}
+
+
+static void dview_update_view(DView *dv)
+{
+ INT32 old_rt_width = dv->rt_width;
+ INT32 old_rt_height = dv->rt_height;
+
+ dv->rt_width = dv->target->width();
+ dv->rt_height = dv->target->height();
+ if (dview_is_state(dv, VIEW_STATE_NEEDS_UPDATE) || dv->rt_width != old_rt_width || dv->rt_height != old_rt_height)
+ {
+ dview_size_allocate(dv);
+ dview_draw(dv);
+ dview_set_state(dv, VIEW_STATE_NEEDS_UPDATE, FALSE);
+ }
+}
+
+
+static void update_views(void)
+{
+ DView *dv, *prev;
+
+ LIST_GET_LAST(list, dv);
+ while (dv != NULL)
+ {
+ dview_update_view(dv);
+ LIST_GET_PREVIOUS(list, dv, prev);
+ dv = prev;
+ }
+}
+
+
+void debugint_wait_for_debugger(device_t &device, bool firststop)
+{
+
+ if (firststop && list == NULL)
+ {
+ DView *dv;
+ render_target *target;
+
+ target = &device.machine().render().ui_target();
+
+ //set_view_by_name(target, "Debug");
+
+ dv = dview_alloc(target, device.machine(), DVT_DISASSEMBLY, VIEW_STATE_FOLLOW_CPU);
+ dv->editor.active = TRUE;
+ dv->editor.container = &device.machine().render().ui_container();
+ dv = dview_alloc(target, device.machine(), DVT_STATE, VIEW_STATE_FOLLOW_CPU);
+ dv = dview_alloc(target, device.machine(), DVT_CONSOLE, VIEW_STATE_FOLLOW_CPU);
+ dview_set_title(dv, "Console");
+ dv->editor.active = TRUE;
+ dv->editor.container = &device.machine().render().ui_container();
+ set_focus_view(dv);
+ }
+
+ followers_set_cpu(&device);
+
+ //ui_update_and_render(device.machine(), device.machine().render().ui_container()());
+ update_views();
+ device.machine().osd().update(false);
+ handle_menus(device.machine());
+ handle_mouse(device.machine());
+ //osd_sleep(osd_ticks_per_second()/60);
+
+}
+
+void debugint_update_during_game(running_machine &machine)
+{
+ if (!debug_cpu_is_stopped(machine) && machine.phase() == MACHINE_PHASE_RUNNING)
+ {
+ update_views();
+ }
+}
diff --git a/trunk/src/emu/debugint/debugint.h b/trunk/src/emu/debugint/debugint.h
new file mode 100644
index 00000000000..850be46a547
--- /dev/null
+++ b/trunk/src/emu/debugint/debugint.h
@@ -0,0 +1,47 @@
+/*********************************************************************
+
+ debugint.c
+
+ Internal debugger frontend using render interface.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+#pragma once
+
+#ifndef __DEBUGINT_H__
+#define __DEBUGINT_H__
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+/* initialize the internal debugger */
+void debugint_init(running_machine &machine);
+
+/* process events for internal debugger */
+void debugint_wait_for_debugger(device_t &device, bool firststop);
+
+/* update the internal debugger during a game */
+void debugint_update_during_game(running_machine &machine);
+
+#endif
diff --git a/trunk/src/emu/delegate.c b/trunk/src/emu/delegate.c
new file mode 100644
index 00000000000..0aaee215d61
--- /dev/null
+++ b/trunk/src/emu/delegate.c
@@ -0,0 +1,70 @@
+/***************************************************************************
+
+ delegate.c
+
+ Templates and classes to enable delegates for callbacks.
+
+****************************************************************************
+
+ 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 "delegate.h"
+
+
+//**************************************************************************
+// INTERNAL DELEGATE HELPERS
+//**************************************************************************
+
+#if (USE_DELEGATE_TYPE == DELEGATE_TYPE_INTERNAL)
+
+//-------------------------------------------------
+// delegate_convert_raw - given an object and
+// an raw function, adjust the object base and
+// return the actual final code pointer
+//-------------------------------------------------
+
+delegate_generic_function delegate_internal_mfp::convert_to_generic(delegate_generic_class *&object) const
+{
+ // apply the "this" delta to the object first
+ object = reinterpret_cast<delegate_generic_class *>(reinterpret_cast<UINT8 *>(object) + m_this_delta);
+
+ // if the low bit of the vtable index is clear, then it is just a raw function pointer
+ if (!(m_function & 1))
+ return reinterpret_cast<delegate_generic_function>(m_function);
+
+ // otherwise, it is the byte index into the vtable where the actual function lives
+ UINT8 *vtable_base = *reinterpret_cast<UINT8 **>(object);
+ return *reinterpret_cast<delegate_generic_function *>(vtable_base + m_function - 1);
+}
+
+#endif
diff --git a/trunk/src/emu/delegate.h b/trunk/src/emu/delegate.h
new file mode 100644
index 00000000000..9826ad522e5
--- /dev/null
+++ b/trunk/src/emu/delegate.h
@@ -0,0 +1,700 @@
+/***************************************************************************
+
+ delegate.h
+
+ Templates and classes to enable delegates for callbacks.
+
+****************************************************************************
+
+ 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.
+
+****************************************************************************
+
+ There are many implementations of delegate-like functionality for
+ C++ code, but none of them is a perfect drop-in fit for use in MAME.
+ In order to be useful in MAME, we need the following properties:
+
+ * No significant overhead; we want to use these for memory
+ accessors, and memory accessor overhead is already the dominant
+ performance aspect for most drivers.
+
+ * Existing static functions need to be bound with an additional
+ pointer parameter as the first argument. All existing
+ implementations that allow static function binding assume the
+ same signature as the member functions.
+
+ * We must be able to bind the function separately from the
+ object. This is to allow configurations to bind functions
+ before the objects are created.
+
+ Thus, the implementations below are based on existing works but are
+ really a new implementation that is specific to MAME.
+
+ --------------------------------------------------------------------
+
+ The "compatible" version of delegates is based on an implementation
+ from Sergey Ryazanov, found here:
+
+ http://www.codeproject.com/KB/cpp/ImpossiblyFastCppDelegate.aspx
+
+ These delegates essentially generate a templated static stub function
+ for each target function. The static function takes the first
+ parameter, uses it as the object pointer, and calls through the
+ member function. For static functions, the stub is compatible with
+ the signature of a static function, so we just set the stub directly.
+
+ Pros:
+ * should work with any modern compiler
+ * static bindings are just as fast as direct calls
+
+ Cons:
+ * lots of little stub functions generated
+ * double-hops on member function calls means more overhead
+ * calling through stub functions repackages parameters
+
+ --------------------------------------------------------------------
+
+ The "internal" version of delegates makes use of the internal
+ structure of member function pointers in order to convert them at
+ binding time into simple static function pointers. This only works
+ on platforms where object->func(p1, p2) is equivalent in calling
+ convention to func(object, p1, p2).
+
+ Most of the information on how this works comes from Don Clugston
+ in this article:
+
+ http://www.codeproject.com/KB/cpp/FastDelegate.aspx
+
+ Pros:
+ * as fast as a standard function call in static and member cases
+ * no stub functions or double-hops needed
+
+ Cons:
+ * requires internal knowledge of the member function pointer
+ * only works for GCC (for now; MSVC info is also readily available)
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __DELEGATE_H__
+#define __DELEGATE_H__
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+// types of delegates supported
+#define DELEGATE_TYPE_COMPATIBLE 0
+#define DELEGATE_TYPE_INTERNAL 1
+
+// select which one we will be using
+#if defined(__GNUC__)
+#define USE_DELEGATE_TYPE DELEGATE_TYPE_INTERNAL
+#else
+#define USE_DELEGATE_TYPE DELEGATE_TYPE_COMPATIBLE
+#endif
+
+
+
+//**************************************************************************
+// HELPER CLASSES
+//**************************************************************************
+
+// ======================> generic_class
+
+// define a dummy generic class that is just straight single-inheritance
+#ifdef _MSC_VER
+class __single_inheritance generic_class;
+class delegate_generic_class { };
+#else
+class delegate_generic_class;
+#endif
+
+
+// ======================> delegate_late_bind
+
+// simple polymorphic class that must be mixed into any object that is late-bound
+class delegate_late_bind
+{
+public:
+ delegate_late_bind() { }
+ virtual ~delegate_late_bind() { }
+};
+
+
+// ======================> delegate_traits
+
+// delegate_traits is a meta-template that is used to provide a static function pointer
+// and member function pointer of the appropriate type and number of parameters; we use
+// partial template specialization to support fewer parameters by defaulting the later
+// parameters to the special type _noparam
+template<typename _ClassType, typename _ReturnType, typename _P1Type, typename _P2Type, typename _P3Type, typename _P4Type>
+struct delegate_traits
+{
+ typedef _ReturnType (*static_func_type)(_ClassType *, _P1Type, _P2Type, _P3Type, _P4Type);
+ typedef _ReturnType (*static_ref_func_type)(_ClassType &, _P1Type, _P2Type, _P3Type, _P4Type);
+ typedef _ReturnType (_ClassType::*member_func_type)(_P1Type, _P2Type, _P3Type, _P4Type);
+};
+
+// dummy class used to indicate a non-existant parameter
+class _noparam { };
+
+// specialization for 3 parameters
+template<typename _ClassType, typename _ReturnType, typename _P1Type, typename _P2Type, typename _P3Type>
+struct delegate_traits<_ClassType, _ReturnType, _P1Type, _P2Type, _P3Type, _noparam>
+{
+ typedef _ReturnType (*static_func_type)(_ClassType *, _P1Type, _P2Type, _P3Type);
+ typedef _ReturnType (*static_ref_func_type)(_ClassType &, _P1Type, _P2Type, _P3Type);
+ typedef _ReturnType (_ClassType::*member_func_type)(_P1Type, _P2Type, _P3Type);
+};
+
+// specialization for 2 parameters
+template<typename _ClassType, typename _ReturnType, typename _P1Type, typename _P2Type>
+struct delegate_traits<_ClassType, _ReturnType, _P1Type, _P2Type, _noparam, _noparam>
+{
+ typedef _ReturnType (*static_func_type)(_ClassType *, _P1Type, _P2Type);
+ typedef _ReturnType (*static_ref_func_type)(_ClassType &, _P1Type, _P2Type);
+ typedef _ReturnType (_ClassType::*member_func_type)(_P1Type, _P2Type);
+};
+
+// specialization for 1 parameter
+template<typename _ClassType, typename _ReturnType, typename _P1Type>
+struct delegate_traits<_ClassType, _ReturnType, _P1Type, _noparam, _noparam, _noparam>
+{
+ typedef _ReturnType (*static_func_type)(_ClassType *, _P1Type);
+ typedef _ReturnType (*static_ref_func_type)(_ClassType &, _P1Type);
+ typedef _ReturnType (_ClassType::*member_func_type)(_P1Type);
+};
+
+// specialization for no parameters
+template<typename _ClassType, typename _ReturnType>
+struct delegate_traits<_ClassType, _ReturnType, _noparam, _noparam, _noparam, _noparam>
+{
+ typedef _ReturnType (*static_func_type)(_ClassType *);
+ typedef _ReturnType (*static_ref_func_type)(_ClassType &);
+ typedef _ReturnType (_ClassType::*member_func_type)();
+};
+
+
+
+//**************************************************************************
+// COMPATIBLE DELEGATES
+//**************************************************************************
+
+#if (USE_DELEGATE_TYPE == DELEGATE_TYPE_COMPATIBLE)
+
+// ======================> delegate_raw_mfp
+
+// delegate_raw_mfp is a class that wraps a generic member function pointer
+// in a static buffer, and can effectively recast itself back for later use;
+// it hides some of the gross details involved in copying artibtrary member
+// function pointers around
+struct delegate_raw_mfp
+{
+ // for MSVC maximum size is one pointer, plus 3 ints
+ static const int MAX_MFP_SIZE = sizeof(void *) + 3 * sizeof(int);
+
+ // default and copy constructors
+ delegate_raw_mfp() { memset(&m_rawdata, 0, sizeof(m_rawdata)); }
+ delegate_raw_mfp(const delegate_raw_mfp &src) : m_rawdata(src.m_rawdata) { }
+
+ // construct from any member function pointer
+ template<typename _FunctionType>
+ delegate_raw_mfp(_FunctionType mfp)
+ {
+ assert(sizeof(mfp) <= sizeof(m_rawdata));
+ memset(&m_rawdata, 0, sizeof(m_rawdata));
+ *reinterpret_cast<_FunctionType *>(&m_rawdata) = mfp;
+ }
+
+ // assignment operator
+ delegate_raw_mfp &operator=(const delegate_raw_mfp &src)
+ {
+ if (this != &src)
+ m_rawdata = src.m_rawdata;
+ return *this;
+ }
+
+ // comparison operator
+ bool operator==(const delegate_raw_mfp &rhs) const
+ {
+ return (memcmp(&m_rawdata, &rhs.m_rawdata, sizeof(m_rawdata)) == 0);
+ }
+
+ // convert back to a member function pointer
+ template<class _FunctionType>
+ _FunctionType &mfp() const { return *reinterpret_cast<_FunctionType *>(&m_rawdata); }
+
+ // raw buffer to hold the copy of the function pointer
+ mutable struct { UINT8 bytes[MAX_MFP_SIZE]; } m_rawdata;
+};
+
+
+// ======================> delegate
+
+// general delegate class template supporting up to 4 parameters
+template<typename _ReturnType, typename _P1Type = _noparam, typename _P2Type = _noparam, typename _P3Type = _noparam, typename _P4Type = _noparam>
+class delegate_base
+{
+ typedef delegate_generic_class *(*late_bind_func)(delegate_late_bind &object);
+ typedef typename delegate_traits<delegate_generic_class, _ReturnType, _P1Type, _P2Type, _P3Type, _P4Type>::static_func_type generic_static_func;
+
+public:
+ // generic constructor
+ delegate_base()
+ : m_name(NULL),
+ m_object(NULL),
+ m_callobject(NULL),
+ m_function(NULL),
+ m_latebinder(NULL) { }
+
+ // copy constructor
+ delegate_base(const delegate_base &src)
+ : m_name(src.m_name),
+ m_object(src.m_object),
+ m_callobject(src.is_mfp() ? reinterpret_cast<delegate_generic_class *>(this) : src.m_object),
+ m_function(src.m_function),
+ m_rawfunction(src.m_rawfunction),
+ m_latebinder(src.m_latebinder) { }
+
+ // copy constructor with late bind
+ delegate_base(const delegate_base &src, delegate_late_bind &object)
+ : m_name(src.m_name),
+ m_object(src.m_object),
+ m_callobject(src.is_mfp() ? reinterpret_cast<delegate_generic_class *>(this) : src.m_object),
+ m_function(src.m_function),
+ m_rawfunction(src.m_rawfunction),
+ m_latebinder(src.m_latebinder) { late_bind(object); }
+
+ // construct from member function with object pointer
+ template<class _FunctionClass>
+ delegate_base(typename delegate_traits<_FunctionClass, _ReturnType, _P1Type, _P2Type, _P3Type, _P4Type>::member_func_type funcptr, const char *name, _FunctionClass *object)
+ : m_name(name),
+ m_object(NULL),
+ m_callobject(reinterpret_cast<delegate_generic_class *>(this)),
+ m_function(&delegate_base::method_stub<_FunctionClass>),
+ m_rawfunction(funcptr),
+ m_latebinder(&late_bind_helper<_FunctionClass>) { bind(reinterpret_cast<delegate_generic_class *>(object)); }
+
+ // construct from static function with object pointer
+ template<class _FunctionClass>
+ delegate_base(typename delegate_traits<_FunctionClass, _ReturnType, _P1Type, _P2Type, _P3Type, _P4Type>::static_func_type funcptr, const char *name, _FunctionClass *object)
+ : m_name(name),
+ m_object(NULL),
+ m_callobject(NULL),
+ m_function(reinterpret_cast<generic_static_func>(funcptr)),
+ m_latebinder(&late_bind_helper<_FunctionClass>) { bind(reinterpret_cast<delegate_generic_class *>(object)); }
+
+ // construct from static reference function with object pointer
+ template<class _FunctionClass>
+ delegate_base(typename delegate_traits<_FunctionClass, _ReturnType, _P1Type, _P2Type, _P3Type, _P4Type>::static_ref_func_type funcptr, const char *name, _FunctionClass *object)
+ : m_name(name),
+ m_object(NULL),
+ m_callobject(NULL),
+ m_function(reinterpret_cast<generic_static_func>(funcptr)),
+ m_latebinder(&late_bind_helper<_FunctionClass>) { bind(reinterpret_cast<delegate_generic_class *>(object)); }
+
+ // copy operator
+ delegate_base &operator=(const delegate_base &src)
+ {
+ if (this != &src)
+ {
+ m_name = src.m_name;
+ m_object = src.m_object;
+ m_callobject = src.is_mfp() ? reinterpret_cast<delegate_generic_class *>(this) : src.m_object;
+ m_function = src.m_function;
+ m_rawfunction = src.m_rawfunction;
+ m_latebinder = src.m_latebinder;
+ }
+ return *this;
+ }
+
+ // comparison operator
+ bool operator==(const delegate_base &rhs) const
+ {
+ return (m_object == rhs.m_object && m_function == rhs.m_function && m_rawfunction == rhs.m_rawfunction);
+ }
+
+ // getters
+ bool isnull() const { return (m_function == NULL); }
+ bool has_object() const { return (m_object != NULL); }
+ const char *name() const { return m_name; }
+
+ // call the function
+ _ReturnType operator()() const { return (*m_function)(m_callobject); }
+ _ReturnType operator()(_P1Type p1) const { return (*m_function)(m_callobject, p1); }
+ _ReturnType operator()(_P1Type p1, _P2Type p2) const { return (*m_function)(m_callobject, p1, p2); }
+ _ReturnType operator()(_P1Type p1, _P2Type p2, _P3Type p3) const { return (*m_function)(m_callobject, p1, p2, p3); }
+ _ReturnType operator()(_P1Type p1, _P2Type p2, _P3Type p3, _P4Type p4) const { return (*m_function)(m_callobject, p1, p2, p3, p4); }
+
+ // late binding
+ void late_bind(delegate_late_bind &object) { bind((*m_latebinder)(object)); }
+
+protected:
+ // bind the actual object
+ void bind(delegate_generic_class *object)
+ {
+ m_object = object;
+ if (!is_mfp()) m_callobject = m_object;
+ }
+
+ // internal helpers
+ bool is_mfp() const { return m_callobject == reinterpret_cast<const delegate_generic_class *>(this); }
+
+ // helper stub that calls the member function; we need one for each parameter count
+ template<class _FunctionClass>
+ static _ReturnType method_stub(delegate_generic_class *object)
+ {
+ typedef _ReturnType (_FunctionClass::*mfptype)();
+ delegate_base *_this = reinterpret_cast<delegate_base *>(object);
+ mfptype &mfp = _this->m_rawfunction.mfp<mfptype>();
+ return (reinterpret_cast<_FunctionClass *>(_this->m_object)->*mfp)();
+ }
+
+ template<class _FunctionClass>
+ static _ReturnType method_stub(delegate_generic_class *object, _P1Type p1)
+ {
+ typedef _ReturnType (_FunctionClass::*mfptype)(_P1Type p1);
+ delegate_base *_this = reinterpret_cast<delegate_base *>(object);
+ mfptype &mfp = _this->m_rawfunction.mfp<mfptype>();
+ return (reinterpret_cast<_FunctionClass *>(_this->m_object)->*mfp)(p1);
+ }
+
+ template<class _FunctionClass>
+ static _ReturnType method_stub(delegate_generic_class *object, _P1Type p1, _P2Type p2)
+ {
+ typedef _ReturnType (_FunctionClass::*mfptype)(_P1Type p1, _P2Type p2);
+ delegate_base *_this = reinterpret_cast<delegate_base *>(object);
+ mfptype &mfp = _this->m_rawfunction.mfp<mfptype>();
+ return (reinterpret_cast<_FunctionClass *>(_this->m_object)->*mfp)(p1, p2);
+ }
+
+ template<class _FunctionClass>
+ static _ReturnType method_stub(delegate_generic_class *object, _P1Type p1, _P2Type p2, _P3Type p3)
+ {
+ typedef _ReturnType (_FunctionClass::*mfptype)(_P1Type p1, _P2Type p2, _P3Type p3);
+ delegate_base *_this = reinterpret_cast<delegate_base *>(object);
+ mfptype &mfp = _this->m_rawfunction.mfp<mfptype>();
+ return (reinterpret_cast<_FunctionClass *>(_this->m_object)->*mfp)(p1, p2, p3);
+ }
+
+ template<class _FunctionClass>
+ static _ReturnType method_stub(delegate_generic_class *object, _P1Type p1, _P2Type p2, _P3Type p3, _P4Type p4)
+ {
+ typedef _ReturnType (_FunctionClass::*mfptype)(_P1Type p1, _P2Type p2, _P3Type p3, _P4Type p4);
+ delegate_base *_this = reinterpret_cast<delegate_base *>(object);
+ mfptype &mfp = _this->m_rawfunction.mfp<mfptype>();
+ return (reinterpret_cast<_FunctionClass *>(_this->m_object)->*mfp)(p1, p2, p3, p4);
+ }
+
+ // late binding helper
+ template<class _FunctionClass>
+ static delegate_generic_class *late_bind_helper(delegate_late_bind &object)
+ {
+ return reinterpret_cast<delegate_generic_class *>(dynamic_cast<_FunctionClass *>(&object));
+ }
+
+ // internal state
+ const char * m_name; // name string
+ delegate_generic_class * m_object; // pointer to the post-cast object
+ delegate_generic_class * m_callobject; // pointer to the object used for calling
+ generic_static_func m_function; // generic static function pointer
+ delegate_raw_mfp m_rawfunction; // copy of raw MFP
+ late_bind_func m_latebinder; // late binding helper
+};
+
+#endif
+
+
+//**************************************************************************
+// GCC DELEGATES
+//**************************************************************************
+
+#if (USE_DELEGATE_TYPE == DELEGATE_TYPE_INTERNAL)
+
+// a generic function pointer type and a generic member function pointer type
+typedef void (*delegate_generic_function)();
+
+// struct describing the contents of a member function pointer
+struct delegate_internal_mfp
+{
+ // default constructor
+ delegate_internal_mfp()
+ : m_function(0),
+ m_this_delta(0) { }
+
+ // copy constructor
+ delegate_internal_mfp(const delegate_internal_mfp &src)
+ : m_function(src.m_function),
+ m_this_delta(src.m_this_delta) { }
+
+ // construct from any member function pointer
+ template<typename _FunctionPtr>
+ delegate_internal_mfp(_FunctionPtr funcptr)
+ {
+ assert(sizeof(funcptr) == sizeof(*this));
+ *reinterpret_cast<_FunctionPtr *>(this) = funcptr;
+ }
+
+ // assignment operator
+ delegate_internal_mfp &operator=(const delegate_internal_mfp &src)
+ {
+ if (this != &src)
+ {
+ m_function = src.m_function;
+ m_this_delta = src.m_this_delta;
+ }
+ return *this;
+ }
+
+ // comparison operator
+ bool operator==(const delegate_internal_mfp &rhs) const
+ {
+ return (m_function == rhs.m_function && m_this_delta == rhs.m_this_delta);
+ }
+
+ // extract the generic function and adjust the object pointer
+ delegate_generic_function convert_to_generic(delegate_generic_class *&object) const;
+
+ // actual state
+ FPTR m_function; // first item can be one of two things:
+ // if even, it's a pointer to the function
+ // if odd, it's the byte offset into the vtable
+ int m_this_delta; // delta to apply to the 'this' pointer
+};
+
+
+// ======================> delegate
+
+template<typename _ReturnType, typename _P1Type = _noparam, typename _P2Type = _noparam, typename _P3Type = _noparam, typename _P4Type = _noparam>
+class delegate_base
+{
+ typedef delegate_generic_class *(*late_bind_func)(delegate_late_bind &object);
+ typedef typename delegate_traits<delegate_generic_class, _ReturnType, _P1Type, _P2Type, _P3Type, _P4Type>::static_func_type generic_static_func;
+
+public:
+ // generic constructor
+ delegate_base()
+ : m_name(NULL),
+ m_object(NULL),
+ m_function(NULL),
+ m_latebinder(NULL) { }
+
+ // copy constructor
+ delegate_base(const delegate_base &src)
+ : m_name(src.m_name),
+ m_object(src.m_object),
+ m_function(src.m_function),
+ m_rawfunction(src.m_rawfunction),
+ m_latebinder(src.m_latebinder) { }
+
+ // copy constructor with late bind
+ delegate_base(const delegate_base &src, delegate_late_bind &object)
+ : m_name(src.m_name),
+ m_object(src.m_object),
+ m_function(src.m_function),
+ m_rawfunction(src.m_rawfunction),
+ m_latebinder(src.m_latebinder) { late_bind(object); }
+
+ // construct from member function with object pointer
+ template<class _FunctionClass>
+ delegate_base(typename delegate_traits<_FunctionClass, _ReturnType, _P1Type, _P2Type, _P3Type, _P4Type>::member_func_type funcptr, const char *name, _FunctionClass *object)
+ : m_name(name),
+ m_object(NULL),
+ m_function(NULL),
+ m_rawfunction(funcptr),
+ m_latebinder(&late_bind_helper<_FunctionClass>) { bind(reinterpret_cast<delegate_generic_class *>(object)); }
+
+ // construct from static function with object pointer
+ template<class _FunctionClass>
+ delegate_base(typename delegate_traits<_FunctionClass, _ReturnType, _P1Type, _P2Type, _P3Type, _P4Type>::static_func_type funcptr, const char *name, _FunctionClass *object)
+ : m_name(name),
+ m_object(NULL),
+ m_function(reinterpret_cast<generic_static_func>(funcptr)),
+ m_latebinder(&late_bind_helper<_FunctionClass>) { bind(reinterpret_cast<delegate_generic_class *>(object)); }
+
+ // construct from static reference function with object pointer
+ template<class _FunctionClass>
+ delegate_base(typename delegate_traits<_FunctionClass, _ReturnType, _P1Type, _P2Type, _P3Type, _P4Type>::static_ref_func_type funcptr, const char *name, _FunctionClass *object)
+ : m_name(name),
+ m_object(NULL),
+ m_function(reinterpret_cast<generic_static_func>(funcptr)),
+ m_latebinder(&late_bind_helper<_FunctionClass>) { bind(reinterpret_cast<delegate_generic_class *>(object)); }
+
+ // copy operator
+ delegate_base &operator=(const delegate_base &src)
+ {
+ if (this != &src)
+ {
+ m_name = src.m_name;
+ m_object = src.m_object;
+ m_function = src.m_function;
+ m_rawfunction = src.m_rawfunction;
+ m_latebinder = src.m_latebinder;
+ }
+ return *this;
+ }
+
+ // comparison operator
+ bool operator==(const delegate_base &rhs) const
+ {
+ return (m_object == rhs.m_object && m_function == rhs.m_function && m_rawfunction == rhs.m_rawfunction);
+ }
+
+ // getters
+ bool isnull() const { return (m_function == NULL && m_rawfunction.m_function == 0); }
+ bool has_object() const { return (m_object != NULL); }
+ const char *name() const { return m_name; }
+
+ // call the function
+ _ReturnType operator()() const { return (*m_function)(m_object); }
+ _ReturnType operator()(_P1Type p1) const { return (*m_function)(m_object, p1); }
+ _ReturnType operator()(_P1Type p1, _P2Type p2) const { return (*m_function)(m_object, p1, p2); }
+ _ReturnType operator()(_P1Type p1, _P2Type p2, _P3Type p3) const { return (*m_function)(m_object, p1, p2, p3); }
+ _ReturnType operator()(_P1Type p1, _P2Type p2, _P3Type p3, _P4Type p4) const { return (*m_function)(m_object, p1, p2, p3, p4); }
+
+ // late binding
+ void late_bind(delegate_late_bind &object) { bind((*m_latebinder)(object)); }
+
+protected:
+ // bind the actual object
+ void bind(delegate_generic_class *object)
+ {
+ m_object = object;
+ if (m_object != NULL && m_rawfunction.m_function != 0)
+ m_function = reinterpret_cast<generic_static_func>(m_rawfunction.convert_to_generic(m_object));
+ }
+
+ // late binding helper
+ template<class _FunctionClass>
+ static delegate_generic_class *late_bind_helper(delegate_late_bind &object)
+ {
+ return reinterpret_cast<delegate_generic_class *>(dynamic_cast<_FunctionClass *>(&object));
+ }
+
+ // internal state
+ const char * m_name; // name string
+ delegate_generic_class * m_object; // pointer to the post-cast object
+ generic_static_func m_function; // generic static function pointer
+ delegate_internal_mfp m_rawfunction; // raw member function definition
+ late_bind_func m_latebinder; // late binding helper
+};
+
+#endif
+
+
+//**************************************************************************
+// NATURAL SYNTAX
+//**************************************************************************
+
+// declare the base template
+template <typename Signature>
+class delegate;
+
+// specialize for 0 parameters; we derive from the base class and provide equivalent
+// pass-through constructors for each type, as well as an assignment operator
+template<typename _ReturnType>
+class delegate<_ReturnType ()> : public delegate_base<_ReturnType>
+{
+ typedef delegate_base<_ReturnType> basetype;
+public:
+ delegate() : basetype() { }
+ delegate(const basetype &src) : basetype(src) { }
+ delegate(const basetype &src, delegate_late_bind &object) : basetype(src, object) { }
+ template<class _FunctionClass> delegate(typename delegate_traits<_FunctionClass, _ReturnType, _noparam, _noparam, _noparam, _noparam>::member_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object) { }
+ template<class _FunctionClass> delegate(typename delegate_traits<_FunctionClass, _ReturnType, _noparam, _noparam, _noparam, _noparam>::static_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object) { }
+ template<class _FunctionClass> delegate(typename delegate_traits<_FunctionClass, _ReturnType, _noparam, _noparam, _noparam, _noparam>::static_ref_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object) { }
+ delegate &operator=(const basetype &src) { *static_cast<basetype *>(this) = src; return *this; }
+};
+
+// specialize for 1 parameter
+template<typename _ReturnType, typename _P1Type>
+class delegate<_ReturnType (_P1Type)> : public delegate_base<_ReturnType, _P1Type>
+{
+ typedef delegate_base<_ReturnType, _P1Type> basetype;
+public:
+ delegate() : basetype() { }
+ delegate(const basetype &src) : basetype(src) { }
+ delegate(const basetype &src, delegate_late_bind &object) : basetype(src, object) { }
+ template<class _FunctionClass> delegate(typename delegate_traits<_FunctionClass, _ReturnType, _P1Type, _noparam, _noparam, _noparam>::member_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object) { }
+ template<class _FunctionClass> delegate(typename delegate_traits<_FunctionClass, _ReturnType, _P1Type, _noparam, _noparam, _noparam>::static_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object) { }
+ template<class _FunctionClass> delegate(typename delegate_traits<_FunctionClass, _ReturnType, _P1Type, _noparam, _noparam, _noparam>::static_ref_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object) { }
+ delegate &operator=(const basetype &src) { *static_cast<basetype *>(this) = src; return *this; }
+};
+
+// specialize for 2 parameters
+template<typename _ReturnType, typename _P1Type, typename _P2Type>
+class delegate<_ReturnType (_P1Type, _P2Type)> : public delegate_base<_ReturnType, _P1Type, _P2Type>
+{
+ typedef delegate_base<_ReturnType, _P1Type, _P2Type> basetype;
+public:
+ delegate() : basetype() { }
+ delegate(const basetype &src) : basetype(src) { }
+ delegate(const basetype &src, delegate_late_bind &object) : basetype(src, object) { }
+ template<class _FunctionClass> delegate(typename delegate_traits<_FunctionClass, _ReturnType, _P1Type, _P2Type, _noparam, _noparam>::member_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object) { }
+ template<class _FunctionClass> delegate(typename delegate_traits<_FunctionClass, _ReturnType, _P1Type, _P2Type, _noparam, _noparam>::static_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object) { }
+ template<class _FunctionClass> delegate(typename delegate_traits<_FunctionClass, _ReturnType, _P1Type, _P2Type, _noparam, _noparam>::static_ref_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object) { }
+ delegate &operator=(const basetype &src) { *static_cast<basetype *>(this) = src; return *this; }
+};
+
+// specialize for 3 parameters
+template<typename _ReturnType, typename _P1Type, typename _P2Type, typename _P3Type>
+class delegate<_ReturnType (_P1Type, _P2Type, _P3Type)> : public delegate_base<_ReturnType, _P1Type, _P2Type, _P3Type>
+{
+ typedef delegate_base<_ReturnType, _P1Type, _P2Type, _P3Type> basetype;
+public:
+ delegate() : basetype() { }
+ delegate(const basetype &src) : basetype(src) { }
+ delegate(const basetype &src, delegate_late_bind &object) : basetype(src, object) { }
+ template<class _FunctionClass> delegate(typename delegate_traits<_FunctionClass, _ReturnType, _P1Type, _P2Type, _P3Type, _noparam>::member_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object) { }
+ template<class _FunctionClass> delegate(typename delegate_traits<_FunctionClass, _ReturnType, _P1Type, _P2Type, _P3Type, _noparam>::static_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object) { }
+ template<class _FunctionClass> delegate(typename delegate_traits<_FunctionClass, _ReturnType, _P1Type, _P2Type, _P3Type, _noparam>::static_ref_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object) { }
+ delegate &operator=(const basetype &src) { *static_cast<basetype *>(this) = src; return *this; }
+};
+
+// specialize for 4 parameters
+template<typename _ReturnType, typename _P1Type, typename _P2Type, typename _P3Type, typename _P4Type>
+class delegate<_ReturnType (_P1Type, _P2Type, _P3Type, _P4Type)> : public delegate_base<_ReturnType, _P1Type, _P2Type, _P3Type, _P4Type>
+{
+ typedef delegate_base<_ReturnType, _P1Type, _P2Type, _P3Type, _P4Type> basetype;
+public:
+ delegate() : basetype() { }
+ delegate(const basetype &src) : basetype(src) { }
+ delegate(const basetype &src, delegate_late_bind &object) : basetype(src, object) { }
+ template<class _FunctionClass> delegate(typename delegate_traits<_FunctionClass, _ReturnType, _P1Type, _P2Type, _P3Type, _P4Type>::member_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object) { }
+ template<class _FunctionClass> delegate(typename delegate_traits<_FunctionClass, _ReturnType, _P1Type, _P2Type, _P3Type, _P4Type>::static_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object) { }
+ template<class _FunctionClass> delegate(typename delegate_traits<_FunctionClass, _ReturnType, _P1Type, _P2Type, _P3Type, _P4Type>::static_ref_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object) { }
+ delegate &operator=(const basetype &src) { *static_cast<basetype *>(this) = src; return *this; }
+};
+
+
+#endif /* __DELEGATE_H__ */
diff --git a/trunk/src/emu/deprecat.h b/trunk/src/emu/deprecat.h
new file mode 100644
index 00000000000..924f1c98631
--- /dev/null
+++ b/trunk/src/emu/deprecat.h
@@ -0,0 +1,53 @@
+/***************************************************************************
+
+ deprecat.h
+
+ Definition of derprecated and obsolte constructs that should not
+ be used by new code, if at all possible.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __DEPRECAT_H__
+#define __DEPRECAT_H__
+
+
+/*************************************
+ *
+ * Old way of allowing "VBLANK"
+ * interrupts to fire more than once
+ * a frame.
+ *
+ * These should be replaced with
+ * scanline based interrupts as
+ * it makes no sense to have more
+ * than one VBLANK interrupt
+ * per frame.
+ *
+ *************************************/
+
+#define MCFG_CPU_VBLANK_INT_HACK(_func, _rate) \
+ device_execute_interface::static_set_vblank_int(*device, _func, NULL, _rate); \
+
+
+
+/*************************************
+ *
+ * Core timing
+ *
+ *************************************/
+
+/* Returns the number of times the interrupt handler will be called before
+ the end of the current video frame. This is can be useful to interrupt
+ handlers to synchronize their operation. If you call this from outside
+ an interrupt handler, add 1 to the result, i.e. if it returns 0, it means
+ that the interrupt handler will be called once. */
+#define cpu_getiloops(dev) device_execute(dev)->iloops()
+
+
+
+#endif /* __DEPRECAT_H__ */
diff --git a/trunk/src/emu/devcb.c b/trunk/src/emu/devcb.c
new file mode 100644
index 00000000000..03c18f75c52
--- /dev/null
+++ b/trunk/src/emu/devcb.c
@@ -0,0 +1,754 @@
+/***************************************************************************
+
+ devcb.c
+
+ Device callback interface helpers.
+
+****************************************************************************
+
+ 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"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// special identifiers used to discover NULL functions
+UINT8 devcb_resolved_read_line::s_null;
+UINT8 devcb_resolved_write_line::s_null;
+UINT8 devcb_resolved_read8::s_null;
+UINT8 devcb_resolved_write8::s_null;
+UINT8 devcb_resolved_read16::s_null;
+UINT8 devcb_resolved_write16::s_null;
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> devcb_resolver
+
+class devcb_resolver
+{
+public:
+ static const input_port_config *resolve_port(const char *tag, device_t &current);
+ static device_t *resolve_device(int index, const char *tag, device_t &current);
+ static device_execute_interface *resolve_execute_interface(const char *tag, device_t &current);
+ static address_space *resolve_space(int index, const char *tag, device_t &current);
+};
+
+
+
+//**************************************************************************
+// DEVCB RESOLVER
+//**************************************************************************
+
+//-------------------------------------------------
+// resolve_port - resolve to an input port object
+// based on the provided tag
+//-------------------------------------------------
+
+const input_port_config *devcb_resolver::resolve_port(const char *tag, device_t &current)
+{
+ const input_port_config *result = current.machine().port(tag);
+ if (result == NULL)
+ throw emu_fatalerror("Unable to find input port '%s' (requested by %s '%s')", tag, current.name(), current.tag());
+ return result;
+}
+
+
+//-------------------------------------------------
+// resolve_device - resolve to a device given
+// a tag and special index type
+//-------------------------------------------------
+
+device_t *devcb_resolver::resolve_device(int index, const char *tag, device_t &current)
+{
+ device_t *result = NULL;
+
+ if (index == DEVCB_DEVICE_SELF)
+ result = &current;
+ else if (index == DEVCB_DEVICE_DRIVER)
+ result = current.machine().driver_data();
+ else if (strcmp(tag, DEVICE_SELF_OWNER) == 0)
+ result = current.owner();
+ else
+ result = current.siblingdevice(tag);
+
+ if (result == NULL)
+ throw emu_fatalerror("Unable to resolve device '%s' (requested by callback to %s '%s')", tag, current.name(), current.tag());
+ return result;
+}
+
+
+//-------------------------------------------------
+// resolve_execute_interface - resolve to an
+// execute interface on a device given a device
+// tag
+//-------------------------------------------------
+
+device_execute_interface *devcb_resolver::resolve_execute_interface(const char *tag, device_t &current)
+{
+ // find our target device
+ device_t *targetdev = current.siblingdevice(tag);
+ if (targetdev == NULL)
+ throw emu_fatalerror("Unable to resolve device '%s' (requested by %s '%s')", tag, current.name(), current.tag());
+
+ // make sure the target device has an execute interface
+ device_execute_interface *exec;
+ if (!targetdev->interface(exec))
+ throw emu_fatalerror("Device '%s' (requested by %s '%s') has no execute interface", tag, current.name(), current.tag());
+
+ return exec;
+}
+
+
+//-------------------------------------------------
+// resolve_space - resolve to an address space
+// given a device tag and a space index
+//-------------------------------------------------
+
+address_space *devcb_resolver::resolve_space(int index, const char *tag, device_t &current)
+{
+ // find our target device
+ device_t *targetdev = current.siblingdevice(tag);
+ if (targetdev == NULL)
+ throw emu_fatalerror("Unable to resolve device '%s' (requested by %s '%s')", tag, current.name(), current.tag());
+
+ // make sure the target device has a memory interface
+ device_memory_interface *memory;
+ if (!targetdev->interface(memory))
+ throw emu_fatalerror("Device '%s' (requested by %s '%s') has no memory interface", tag, current.name(), current.tag());
+
+ // set the real target and function, then prime a delegate
+ address_space *result = memory->space(index);
+ if (result == NULL)
+ throw emu_fatalerror("Unable to find device '%s' space %d (requested by %s '%s')", tag, index, current.name(), current.tag());
+
+ return result;
+}
+
+
+
+//**************************************************************************
+// DEVCB RESOLVED READ LINE
+//**************************************************************************
+
+//-------------------------------------------------
+// devcb_resolved_read_line - empty constructor
+//-------------------------------------------------
+
+devcb_resolved_read_line::devcb_resolved_read_line()
+{
+ m_object.port = NULL;
+ m_helper.read_line = NULL;
+}
+
+
+//-------------------------------------------------
+// resolve - resolve to a delegate from a static
+// structure definition
+//-------------------------------------------------
+
+void devcb_resolved_read_line::resolve(const devcb_read_line &desc, device_t &device)
+{
+ switch (desc.type)
+ {
+ default:
+ case DEVCB_TYPE_NULL:
+ m_object.constant = 0;
+ m_helper.null_indicator = &s_null;
+ *static_cast<devcb_read_line_delegate *>(this) = devcb_read_line_delegate(&devcb_resolved_read_line::from_constant, "(null)", this);
+ break;
+
+ case DEVCB_TYPE_IOPORT:
+ m_object.port = devcb_resolver::resolve_port(desc.tag, device);
+ *static_cast<devcb_read_line_delegate *>(this) = devcb_read_line_delegate(&devcb_resolved_read_line::from_port, desc.tag, this);
+ break;
+
+ case DEVCB_TYPE_DEVICE:
+ m_object.device = devcb_resolver::resolve_device(desc.index, desc.tag, device);
+ if (desc.readline != NULL)
+ *static_cast<devcb_read_line_delegate *>(this) = devcb_read_line_delegate(desc.readline, desc.name, m_object.device);
+ else
+ {
+ m_helper.read8_device = desc.readdevice;
+ *static_cast<devcb_read_line_delegate *>(this) = devcb_read_line_delegate(&devcb_resolved_read_line::from_read8, desc.name, this);
+ }
+ break;
+
+ case DEVCB_TYPE_LEGACY_SPACE:
+ m_object.space = devcb_resolver::resolve_space(desc.index, desc.tag, device);
+ m_helper.read8_space = desc.readspace;
+ *static_cast<devcb_read_line_delegate *>(this) = devcb_read_line_delegate(&devcb_resolved_read_line::from_read8, desc.name, this);
+ break;
+
+ case DEVCB_TYPE_CONSTANT:
+ m_object.constant = desc.index;
+ *static_cast<devcb_read_line_delegate *>(this) = devcb_read_line_delegate(&devcb_resolved_read_line::from_constant, "constant", this);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// from_port - helper to convert from an I/O port
+// value to a line value
+//-------------------------------------------------
+
+int devcb_resolved_read_line::from_port()
+{
+ return (input_port_read_direct(m_object.port) & 1) ? ASSERT_LINE : CLEAR_LINE;
+}
+
+
+//-------------------------------------------------
+// from_read8 - helper to convert from an 8-bit
+// memory read value to a line value
+//-------------------------------------------------
+
+int devcb_resolved_read_line::from_read8()
+{
+ return ((*m_helper.read8_device)(m_object.device, 0) & 1) ? ASSERT_LINE : CLEAR_LINE;
+}
+
+
+//-------------------------------------------------
+// from_constant - helper to convert from a
+// constant value to a line value
+//-------------------------------------------------
+
+int devcb_resolved_read_line::from_constant()
+{
+ return (m_object.constant & 1) ? ASSERT_LINE : CLEAR_LINE;
+}
+
+
+
+//**************************************************************************
+// DEVCB RESOLVED WRITE LINE
+//**************************************************************************
+
+//-------------------------------------------------
+// devcb_resolved_write_line - empty constructor
+//-------------------------------------------------
+
+devcb_resolved_write_line::devcb_resolved_write_line()
+{
+ m_object.port = NULL;
+ m_helper.write_line = NULL;
+}
+
+
+//-------------------------------------------------
+// resolve - resolve to a delegate from a static
+// structure definition
+//-------------------------------------------------
+
+void devcb_resolved_write_line::resolve(const devcb_write_line &desc, device_t &device)
+{
+ switch (desc.type)
+ {
+ default:
+ case DEVCB_TYPE_NULL:
+ m_helper.null_indicator = &s_null;
+ *static_cast<devcb_write_line_delegate *>(this) = devcb_write_line_delegate(&devcb_resolved_write_line::to_null, "(null)", this);
+ break;
+
+ case DEVCB_TYPE_IOPORT:
+ m_object.port = devcb_resolver::resolve_port(desc.tag, device);
+ *static_cast<devcb_write_line_delegate *>(this) = devcb_write_line_delegate(&devcb_resolved_write_line::to_port, desc.tag, this);
+ break;
+
+ case DEVCB_TYPE_DEVICE:
+ m_object.device = devcb_resolver::resolve_device(desc.index, desc.tag, device);
+ if (desc.writeline != NULL)
+ *static_cast<devcb_write_line_delegate *>(this) = devcb_write_line_delegate(desc.writeline, desc.name, m_object.device);
+ else
+ {
+ m_helper.write8_device = desc.writedevice;
+ *static_cast<devcb_write_line_delegate *>(this) = devcb_write_line_delegate(&devcb_resolved_write_line::to_write8, desc.name, this);
+ }
+ break;
+
+ case DEVCB_TYPE_LEGACY_SPACE:
+ m_object.space = devcb_resolver::resolve_space(desc.index, desc.tag, device);
+ m_helper.write8_space = desc.writespace;
+ *static_cast<devcb_write_line_delegate *>(this) = devcb_write_line_delegate(&devcb_resolved_write_line::to_write8, desc.name, this);
+ break;
+
+ case DEVCB_TYPE_INPUT_LINE:
+ m_object.execute = devcb_resolver::resolve_execute_interface(desc.tag, device);
+ m_helper.input_line = desc.index;
+ *static_cast<devcb_write_line_delegate *>(this) = devcb_write_line_delegate(&devcb_resolved_write_line::to_input, desc.tag, this);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// to_null - helper to handle a NULL write
+//-------------------------------------------------
+
+void devcb_resolved_write_line::to_null(int state)
+{
+}
+
+
+//-------------------------------------------------
+// to_port - helper to convert to an I/O port
+// value from a line value
+//-------------------------------------------------
+
+void devcb_resolved_write_line::to_port(int state)
+{
+ input_port_write_direct(m_object.port, state, 0xffffffff);
+}
+
+
+//-------------------------------------------------
+// to_write8 - helper to convert to an 8-bit
+// memory read value from a line value
+//-------------------------------------------------
+
+void devcb_resolved_write_line::to_write8(int state)
+{
+ (*m_helper.write8_device)(m_object.device, 0, state);
+}
+
+
+//-------------------------------------------------
+// to_input - helper to convert to a device input
+// value from a line value
+//-------------------------------------------------
+
+void devcb_resolved_write_line::to_input(int state)
+{
+ m_object.execute->set_input_line(m_helper.input_line, state);
+}
+
+
+
+//**************************************************************************
+// DEVCB RESOLVED READ8
+//**************************************************************************
+
+//-------------------------------------------------
+// devcb_resolved_read8 - empty constructor
+//-------------------------------------------------
+
+devcb_resolved_read8::devcb_resolved_read8()
+{
+ m_object.port = NULL;
+ m_helper.read_line = NULL;
+}
+
+
+//-------------------------------------------------
+// resolve - resolve to a delegate from a static
+// structure definition
+//-------------------------------------------------
+
+void devcb_resolved_read8::resolve(const devcb_read8 &desc, device_t &device)
+{
+ switch (desc.type)
+ {
+ default:
+ case DEVCB_TYPE_NULL:
+ m_object.constant = 0;
+ m_helper.null_indicator = &s_null;
+ *static_cast<devcb_read8_delegate *>(this) = devcb_read8_delegate(&devcb_resolved_read8::from_constant, "(null)", this);
+ break;
+
+ case DEVCB_TYPE_IOPORT:
+ m_object.port = devcb_resolver::resolve_port(desc.tag, device);
+ *static_cast<devcb_read8_delegate *>(this) = devcb_read8_delegate(&devcb_resolved_read8::from_port, desc.tag, this);
+ break;
+
+ case DEVCB_TYPE_DEVICE:
+ m_object.device = devcb_resolver::resolve_device(desc.index, desc.tag, device);
+ if (desc.readdevice != NULL)
+ *static_cast<devcb_read8_delegate *>(this) = devcb_read8_delegate(desc.readdevice, desc.name, m_object.device);
+ else
+ {
+ m_helper.read_line = desc.readline;
+ *static_cast<devcb_read8_delegate *>(this) = devcb_read8_delegate(&devcb_resolved_read8::from_readline, desc.name, this);
+ }
+ break;
+
+ case DEVCB_TYPE_LEGACY_SPACE:
+ m_object.space = devcb_resolver::resolve_space(desc.index, desc.tag, device);
+ *static_cast<devcb_read8_delegate *>(this) = devcb_read8_delegate(desc.readspace, desc.name, m_object.space);
+ break;
+
+ case DEVCB_TYPE_CONSTANT:
+ m_object.constant = desc.index;
+ *static_cast<devcb_read8_delegate *>(this) = devcb_read8_delegate(&devcb_resolved_read8::from_constant, "constant", this);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// from_port - helper to convert from an I/O port
+// value to an 8-bit value
+//-------------------------------------------------
+
+UINT8 devcb_resolved_read8::from_port(offs_t offset)
+{
+ return input_port_read_direct(m_object.port);
+}
+
+
+//-------------------------------------------------
+// from_read8 - helper to convert from a device
+// line read value to an 8-bit value
+//-------------------------------------------------
+
+UINT8 devcb_resolved_read8::from_readline(offs_t offset)
+{
+ return (*m_helper.read_line)(m_object.device);
+}
+
+
+//-------------------------------------------------
+// from_constant - helper to convert from a
+// constant value to an 8-bit value
+//-------------------------------------------------
+
+UINT8 devcb_resolved_read8::from_constant(offs_t offset)
+{
+ return m_object.constant;
+}
+
+
+
+//**************************************************************************
+// DEVCB RESOLVED WRITE8
+//**************************************************************************
+
+//-------------------------------------------------
+// devcb_resolved_write8 - empty constructor
+//-------------------------------------------------
+
+devcb_resolved_write8::devcb_resolved_write8()
+{
+ m_object.port = NULL;
+ m_helper.write_line = NULL;
+}
+
+
+//-------------------------------------------------
+// resolve - resolve to a delegate from a static
+// structure definition
+//-------------------------------------------------
+
+void devcb_resolved_write8::resolve(const devcb_write8 &desc, device_t &device)
+{
+ switch (desc.type)
+ {
+ default:
+ case DEVCB_TYPE_NULL:
+ m_helper.null_indicator = &s_null;
+ *static_cast<devcb_write8_delegate *>(this) = devcb_write8_delegate(&devcb_resolved_write8::to_null, "(null)", this);
+ break;
+
+ case DEVCB_TYPE_IOPORT:
+ m_object.port = devcb_resolver::resolve_port(desc.tag, device);
+ *static_cast<devcb_write8_delegate *>(this) = devcb_write8_delegate(&devcb_resolved_write8::to_port, desc.tag, this);
+ break;
+
+ case DEVCB_TYPE_DEVICE:
+ m_object.device = devcb_resolver::resolve_device(desc.index, desc.tag, device);
+ if (desc.writedevice != NULL)
+ *static_cast<devcb_write8_delegate *>(this) = devcb_write8_delegate(desc.writedevice, desc.name, m_object.device);
+ else
+ {
+ m_helper.write_line = desc.writeline;
+ *static_cast<devcb_write8_delegate *>(this) = devcb_write8_delegate(&devcb_resolved_write8::to_writeline, desc.name, this);
+ }
+ break;
+
+ case DEVCB_TYPE_LEGACY_SPACE:
+ m_object.space = devcb_resolver::resolve_space(desc.index, desc.tag, device);
+ *static_cast<devcb_write8_delegate *>(this) = devcb_write8_delegate(desc.writespace, desc.name, m_object.space);
+ break;
+
+ case DEVCB_TYPE_INPUT_LINE:
+ m_object.execute = devcb_resolver::resolve_execute_interface(desc.tag, device);
+ m_helper.input_line = desc.index;
+ *static_cast<devcb_write8_delegate *>(this) = devcb_write8_delegate(&devcb_resolved_write8::to_input, desc.tag, this);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// to_null - helper to handle a NULL write
+//-------------------------------------------------
+
+void devcb_resolved_write8::to_null(offs_t offset, UINT8 data)
+{
+}
+
+
+//-------------------------------------------------
+// to_port - helper to convert to an I/O port
+// value from a line value
+//-------------------------------------------------
+
+void devcb_resolved_write8::to_port(offs_t offset, UINT8 data)
+{
+ input_port_write_direct(m_object.port, data, 0xff);
+}
+
+
+//-------------------------------------------------
+// to_write8 - helper to convert to an 8-bit
+// memory read value from a line value
+//-------------------------------------------------
+
+void devcb_resolved_write8::to_writeline(offs_t offset, UINT8 data)
+{
+ (*m_helper.write_line)(m_object.device, (data & 1) ? ASSERT_LINE : CLEAR_LINE);
+}
+
+
+//-------------------------------------------------
+// to_input - helper to convert to a device input
+// value from a line value
+//-------------------------------------------------
+
+void devcb_resolved_write8::to_input(offs_t offset, UINT8 data)
+{
+ m_object.execute->set_input_line(m_helper.input_line, (data & 1) ? ASSERT_LINE : CLEAR_LINE);
+}
+
+
+
+//**************************************************************************
+// DEVCB RESOLVED READ16
+//**************************************************************************
+
+//-------------------------------------------------
+// devcb_resolved_read16 - empty constructor
+//-------------------------------------------------
+
+devcb_resolved_read16::devcb_resolved_read16()
+{
+ m_object.port = NULL;
+ m_helper.read_line = NULL;
+}
+
+
+//-------------------------------------------------
+// resolve - resolve to a delegate from a static
+// structure definition
+//-------------------------------------------------
+
+void devcb_resolved_read16::resolve(const devcb_read16 &desc, device_t &device)
+{
+ switch (desc.type)
+ {
+ default:
+ case DEVCB_TYPE_NULL:
+ m_object.constant = 0;
+ m_helper.null_indicator = &s_null;
+ *static_cast<devcb_read16_delegate *>(this) = devcb_read16_delegate(&devcb_resolved_read16::from_constant, "(null)", this);
+ break;
+
+ case DEVCB_TYPE_IOPORT:
+ m_object.port = devcb_resolver::resolve_port(desc.tag, device);
+ *static_cast<devcb_read16_delegate *>(this) = devcb_read16_delegate(&devcb_resolved_read16::from_port, desc.tag, this);
+ break;
+
+ case DEVCB_TYPE_DEVICE:
+ m_object.device = devcb_resolver::resolve_device(desc.index, desc.tag, device);
+ if (desc.readdevice != NULL)
+ *static_cast<devcb_read16_delegate *>(this) = devcb_read16_delegate(desc.readdevice, desc.name, m_object.device);
+ else
+ {
+ m_helper.read_line = desc.readline;
+ *static_cast<devcb_read16_delegate *>(this) = devcb_read16_delegate(&devcb_resolved_read16::from_readline, desc.name, this);
+ }
+ break;
+
+ case DEVCB_TYPE_LEGACY_SPACE:
+ m_object.space = devcb_resolver::resolve_space(desc.index, desc.tag, device);
+ *static_cast<devcb_read16_delegate *>(this) = devcb_read16_delegate(desc.readspace, desc.name, m_object.space);
+ break;
+
+ case DEVCB_TYPE_CONSTANT:
+ m_object.constant = desc.index;
+ *static_cast<devcb_read16_delegate *>(this) = devcb_read16_delegate(&devcb_resolved_read16::from_constant, "constant", this);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// from_port - helper to convert from an I/O port
+// value to a 16-bit value
+//-------------------------------------------------
+
+UINT16 devcb_resolved_read16::from_port(offs_t offset, UINT16 mask)
+{
+ return input_port_read_direct(m_object.port);
+}
+
+
+//-------------------------------------------------
+// from_read16 - helper to convert from a device
+// line read value to a 16-bit value
+//-------------------------------------------------
+
+UINT16 devcb_resolved_read16::from_readline(offs_t offset, UINT16 mask)
+{
+ return (*m_helper.read_line)(m_object.device);
+}
+
+
+//-------------------------------------------------
+// from_constant - helper to convert from a
+// constant value to a 16-bit value
+//-------------------------------------------------
+
+UINT16 devcb_resolved_read16::from_constant(offs_t offset, UINT16 mask)
+{
+ return m_object.constant;
+}
+
+
+
+//**************************************************************************
+// DEVCB RESOLVED WRITE16
+//**************************************************************************
+
+//-------------------------------------------------
+// devcb_resolved_write16 - empty constructor
+//-------------------------------------------------
+
+devcb_resolved_write16::devcb_resolved_write16()
+{
+ m_object.port = NULL;
+ m_helper.write_line = NULL;
+}
+
+
+//-------------------------------------------------
+// resolve - resolve to a delegate from a static
+// structure definition
+//-------------------------------------------------
+
+void devcb_resolved_write16::resolve(const devcb_write16 &desc, device_t &device)
+{
+ switch (desc.type)
+ {
+ default:
+ case DEVCB_TYPE_NULL:
+ m_helper.null_indicator = &s_null;
+ *static_cast<devcb_write16_delegate *>(this) = devcb_write16_delegate(&devcb_resolved_write16::to_null, "(null)", this);
+ break;
+
+ case DEVCB_TYPE_IOPORT:
+ m_object.port = devcb_resolver::resolve_port(desc.tag, device);
+ *static_cast<devcb_write16_delegate *>(this) = devcb_write16_delegate(&devcb_resolved_write16::to_port, desc.tag, this);
+ break;
+
+ case DEVCB_TYPE_DEVICE:
+ m_object.device = devcb_resolver::resolve_device(desc.index, desc.tag, device);
+ if (desc.writedevice != NULL)
+ *static_cast<devcb_write16_delegate *>(this) = devcb_write16_delegate(desc.writedevice, desc.name, m_object.device);
+ else
+ {
+ m_helper.write_line = desc.writeline;
+ *static_cast<devcb_write16_delegate *>(this) = devcb_write16_delegate(&devcb_resolved_write16::to_writeline, desc.name, this);
+ }
+ break;
+
+ case DEVCB_TYPE_LEGACY_SPACE:
+ m_object.space = devcb_resolver::resolve_space(desc.index, desc.tag, device);
+ *static_cast<devcb_write16_delegate *>(this) = devcb_write16_delegate(desc.writespace, desc.name, m_object.space);
+ break;
+
+ case DEVCB_TYPE_INPUT_LINE:
+ m_object.execute = devcb_resolver::resolve_execute_interface(desc.tag, device);
+ m_helper.input_line = desc.index;
+ *static_cast<devcb_write16_delegate *>(this) = devcb_write16_delegate(&devcb_resolved_write16::to_input, desc.tag, this);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// to_null - helper to handle a NULL write
+//-------------------------------------------------
+
+void devcb_resolved_write16::to_null(offs_t offset, UINT16 data, UINT16 mask)
+{
+}
+
+
+//-------------------------------------------------
+// to_port - helper to convert to an I/O port
+// value from a line value
+//-------------------------------------------------
+
+void devcb_resolved_write16::to_port(offs_t offset, UINT16 data, UINT16 mask)
+{
+ input_port_write_direct(m_object.port, data, mask);
+}
+
+
+//-------------------------------------------------
+// to_write16 - helper to convert to a 16-bit
+// memory read value from a line value
+//-------------------------------------------------
+
+void devcb_resolved_write16::to_writeline(offs_t offset, UINT16 data, UINT16 mask)
+{
+ (*m_helper.write_line)(m_object.device, (data & 1) ? ASSERT_LINE : CLEAR_LINE);
+}
+
+
+//-------------------------------------------------
+// to_input - helper to convert to a device input
+// value from a line value
+//-------------------------------------------------
+
+void devcb_resolved_write16::to_input(offs_t offset, UINT16 data, UINT16 mask)
+{
+ m_object.execute->set_input_line(m_helper.input_line, (data & 1) ? ASSERT_LINE : CLEAR_LINE);
+}
diff --git a/trunk/src/emu/devcb.h b/trunk/src/emu/devcb.h
new file mode 100644
index 00000000000..6ce7c70ca3f
--- /dev/null
+++ b/trunk/src/emu/devcb.h
@@ -0,0 +1,541 @@
+/***************************************************************************
+
+ devcb.h
+
+ Device callback interface helpers.
+
+****************************************************************************
+
+ 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.
+
+****************************************************************************
+
+ These functions are used to adapt multiple read/write handler types
+ to be used with device I/O. In general, a device is expected to
+ declare its desired callback type, and these functions allow other
+ callback types to be adapted appropriately.
+
+ The desired callback types currently supported include:
+
+ read_line_device_func: (device)
+ write_line_device_func: (device, data)
+ read8_device_func: (device, offset)
+ write8_device_func: (device, offset, data)
+ read16_device_func: (device, offset)
+ write16_device_func: (device, offset, data)
+
+ The adapted callback types supported are:
+
+ input port (port)
+ cpu input line (cpu input line)
+ read_line_device_func: (device)
+ write_line_device_func: (device, data)
+ read8_device_func: (device, offset)
+ write8_device_func: (device, offset, data)
+ read8_space_func: (space, offset)
+ write8_space_func: (space, offset, data)
+ read16_device_func: (device, offset)
+ write16_device_func: (device, offset, data)
+ read16_space_func: (space, offset)
+ write16_space_func: (space, offset, data)
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __EMU_H__
+#error Dont include this file directly; include emu.h instead.
+#endif
+
+#ifndef __DEVCB_H__
+#define __DEVCB_H__
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// callback types
+enum
+{
+ DEVCB_TYPE_NULL = 0, // NULL callback
+ DEVCB_TYPE_IOPORT, // I/O port read/write
+ DEVCB_TYPE_DEVICE, // device read/write
+ DEVCB_TYPE_LEGACY_SPACE, // legacy address space read/write
+ DEVCB_TYPE_INPUT_LINE, // device input line write
+ DEVCB_TYPE_CONSTANT // constant value read
+};
+
+// for DEVCB_TYPE_DEVICE, some further differentiation
+enum
+{
+ DEVCB_DEVICE_SELF, // ignore 'tag', refers to the device itself
+ DEVCB_DEVICE_DRIVER, // ignore 'tag', refers to the driver device
+ DEVCB_DEVICE_OTHER // device specified by 'tag'
+};
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+// static template for a read_line stub function that calls through a given READ_LINE_MEMBER
+template<class _Class, int (_Class::*_Function)()>
+int devcb_line_stub(device_t *device)
+{
+ _Class *target = downcast<_Class *>(device);
+ return (target->*_Function)();
+}
+
+// static template for a read8 stub function that calls through a given READ8_MEMBER
+template<class _Class, UINT8 (_Class::*_Function)(address_space &, offs_t, UINT8)>
+UINT8 devcb_stub(device_t *device, offs_t offset)
+{
+ _Class *target = downcast<_Class *>(device);
+ return (target->*_Function)(*memory_nonspecific_space(device->machine()), offset, 0xff);
+}
+
+// static template for a read16 stub function that calls through a given READ16_MEMBER
+template<class _Class, UINT16 (_Class::*_Function)(address_space &, offs_t, UINT16)>
+UINT16 devcb_stub16(device_t *device, offs_t offset)
+{
+ _Class *target = downcast<_Class *>(device);
+ return (target->*_Function)(*memory_nonspecific_space(device->machine()), offset, 0xffff);
+}
+
+// static template for a write_line stub function that calls through a given WRITE_LINE_MEMBER
+template<class _Class, void (_Class::*_Function)(int state)>
+void devcb_line_stub(device_t *device, int state)
+{
+ _Class *target = downcast<_Class *>(device);
+ (target->*_Function)(state);
+}
+
+// static template for a write8 stub function that calls through a given WRITE8_MEMBER
+template<class _Class, void (_Class::*_Function)(address_space &, offs_t, UINT8, UINT8)>
+void devcb_stub(device_t *device, offs_t offset, UINT8 data)
+{
+ _Class *target = downcast<_Class *>(device);
+ (target->*_Function)(*memory_nonspecific_space(device->machine()), offset, data, 0xff);
+}
+
+// static template for a write16 stub function that calls through a given WRITE16_MEMBER
+template<class _Class, void (_Class::*_Function)(address_space &, offs_t, UINT16, UINT16)>
+void devcb_stub16(device_t *device, offs_t offset, UINT16 data)
+{
+ _Class *target = downcast<_Class *>(device);
+ (target->*_Function)(*memory_nonspecific_space(device->machine()), offset, data, 0xffff);
+}
+
+#define DEVCB_NULL { DEVCB_TYPE_NULL }
+
+// standard line or read/write handlers with the calling device passed
+#define DEVCB_LINE(func) { DEVCB_TYPE_DEVICE, DEVCB_DEVICE_SELF, NULL, #func, func, NULL, NULL }
+#define DEVCB_LINE_MEMBER(cls,memb) { DEVCB_TYPE_DEVICE, DEVCB_DEVICE_SELF, NULL, #cls "::" #memb, &devcb_line_stub<cls, &cls::memb>, NULL, NULL }
+#define DEVCB_HANDLER(func) { DEVCB_TYPE_DEVICE, DEVCB_DEVICE_SELF, NULL, #func, NULL, func, NULL }
+#define DEVCB_MEMBER(cls,memb) { DEVCB_TYPE_DEVICE, DEVCB_DEVICE_SELF, NULL, #cls "::" #memb, NULL, &devcb_stub<cls, &cls::memb>, NULL }
+
+// line or read/write handlers for the driver device
+#define DEVCB_DRIVER_LINE_MEMBER(cls,memb) { DEVCB_TYPE_DEVICE, DEVCB_DEVICE_DRIVER, NULL, #cls "::" #memb, &devcb_line_stub<cls, &cls::memb>, NULL, NULL }
+#define DEVCB_DRIVER_MEMBER(cls,memb) { DEVCB_TYPE_DEVICE, DEVCB_DEVICE_DRIVER, NULL, #cls "::" #memb, NULL, &devcb_stub<cls, &cls::memb>, NULL }
+
+// line or read/write handlers for another device
+#define DEVCB_DEVICE_LINE(tag,func) { DEVCB_TYPE_DEVICE, DEVCB_DEVICE_OTHER, tag, #func, func, NULL, NULL }
+#define DEVCB_DEVICE_LINE_MEMBER(tag,cls,memb) { DEVCB_TYPE_DEVICE, DEVCB_DEVICE_OTHER, tag, #cls "::" #memb, &devcb_line_stub<cls, &cls::memb>, NULL, NULL }
+#define DEVCB_DEVICE_HANDLER(tag,func) { DEVCB_TYPE_DEVICE, DEVCB_DEVICE_OTHER, tag, #func, NULL, func, NULL }
+#define DEVCB_DEVICE_MEMBER(tag,cls,memb) { DEVCB_TYPE_DEVICE, DEVCB_DEVICE_OTHER, tag, #cls "::" #memb, NULL, &devcb_stub<cls, &cls::memb>, NULL }
+
+// constant values
+#define DEVCB_CONSTANT(value) { DEVCB_TYPE_CONSTANT, value, NULL, NULL, NULL, NULL }
+#define DEVCB_LINE_GND DEVCB_CONSTANT(0)
+#define DEVCB_LINE_VCC DEVCB_CONSTANT(1)
+
+// read/write handlers for a given CPU's address space
+#define DEVCB_MEMORY_HANDLER(cpu,space,func) { DEVCB_TYPE_LEGACY_SPACE, AS_##space, (cpu), #func, NULL, NULL, func }
+
+// read handlers for an I/O port by tag
+#define DEVCB_INPUT_PORT(tag) { DEVCB_TYPE_IOPORT, 0, (tag), NULL, NULL, NULL, NULL }
+
+// write handlers for a CPU input line
+#define DEVCB_CPU_INPUT_LINE(tag,line) { DEVCB_TYPE_INPUT_LINE, (line), (tag), NULL, NULL, NULL, NULL }
+
+
+// macros for defining read_line/write_line functions
+#define READ_LINE_DEVICE_HANDLER(name) int name(ATTR_UNUSED device_t *device)
+#define WRITE_LINE_DEVICE_HANDLER(name) void name(ATTR_UNUSED device_t *device, ATTR_UNUSED int state)
+
+#define DECLARE_READ_LINE_MEMBER(name) int name()
+#define READ_LINE_MEMBER(name) int name()
+#define DECLARE_WRITE_LINE_MEMBER(name) void name(ATTR_UNUSED int state)
+#define WRITE_LINE_MEMBER(name) void name(ATTR_UNUSED int state)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> devcb_resolved_objects
+
+// resolving a devcb may produce one of the following object types
+union devcb_resolved_objects
+{
+ const input_port_config * port;
+ address_space * space;
+ device_t * device;
+ device_execute_interface * execute;
+ UINT32 constant;
+};
+
+
+// ======================> devcb_resolved_helpers
+
+// resolving a devcb may produce one of the following helper functions/additional info
+union devcb_resolved_read_helpers
+{
+ UINT8 * null_indicator;
+ read_line_device_func read_line;
+ read8_device_func read8_device;
+ read8_space_func read8_space;
+ read16_device_func read16_device;
+ read16_space_func read16_space;
+};
+
+union devcb_resolved_write_helpers
+{
+ UINT8 * null_indicator;
+ write_line_device_func write_line;
+ write8_device_func write8_device;
+ write8_space_func write8_space;
+ write16_device_func write16_device;
+ write16_space_func write16_space;
+ int input_line;
+};
+
+
+// ======================> devcb_read_line
+
+// static structure used for device configuration when the desired callback type is a read_line_device_func
+struct devcb_read_line
+{
+ UINT16 type; // one of the special DEVCB_TYPE values
+ UINT16 index; // index related to the above types
+ const char * tag; // tag of target, where appropriate
+ const char * name; // name of the target function
+ read_line_device_func readline; // read line function
+ read8_device_func readdevice; // read device function
+ read8_space_func readspace; // read space function
+};
+
+
+// ======================> devcb_resolved_read_line
+
+// base delegate type for a read_line
+typedef delegate<int ()> devcb_read_line_delegate;
+
+// class which wraps resolving a devcb_read_line into a delegate
+class devcb_resolved_read_line : public devcb_read_line_delegate
+{
+ DISABLE_COPYING(devcb_resolved_read_line);
+
+public:
+ // construction/destruction
+ devcb_resolved_read_line();
+ devcb_resolved_read_line(const devcb_read_line &desc, device_t &device) { resolve(desc, device); }
+
+ // resolution
+ void resolve(const devcb_read_line &desc, device_t &device);
+
+ // override parent class' notion of NULL
+ bool isnull() const { return m_helper.null_indicator == &s_null; }
+
+private:
+ // internal helpers
+ int from_port();
+ int from_read8();
+ int from_constant();
+
+ // internal state
+ devcb_resolved_objects m_object;
+ devcb_resolved_read_helpers m_helper;
+ static UINT8 s_null;
+};
+
+
+// ======================> devcb_write_line
+
+// static structure used for device configuration when the desired callback type is a write_line_device_func
+struct devcb_write_line
+{
+ UINT16 type; // one of the special DEVCB_TYPE values
+ UINT16 index; // index related to the above types
+ const char * tag; // tag of target, where appropriate
+ const char * name; // name of the target function
+ write_line_device_func writeline; // write line function
+ write8_device_func writedevice; // write device function
+ write8_space_func writespace; // write space function
+};
+
+
+// ======================> devcb_resolved_write_line
+
+// base delegate type for a write_line
+typedef delegate<void (int)> devcb_write_line_delegate;
+
+// class which wraps resolving a devcb_write_line into a delegate
+class devcb_resolved_write_line : public devcb_write_line_delegate
+{
+ DISABLE_COPYING(devcb_resolved_write_line);
+
+public:
+ // construction/destruction
+ devcb_resolved_write_line();
+ devcb_resolved_write_line(const devcb_write_line &desc, device_t &device) { resolve(desc, device); }
+
+ // resolution
+ void resolve(const devcb_write_line &desc, device_t &device);
+
+ // override parent class' notion of NULL
+ bool isnull() const { return m_helper.null_indicator == &s_null; }
+
+private:
+ // internal helpers
+ void to_null(int state);
+ void to_port(int state);
+ void to_write8(int state);
+ void to_input(int state);
+
+ // internal state
+ devcb_resolved_objects m_object;
+ devcb_resolved_write_helpers m_helper;
+ static UINT8 s_null;
+};
+
+
+// ======================> devcb_read8
+
+// static structure used for device configuration when the desired callback type is a read8_device_func
+struct devcb_read8
+{
+ UINT16 type; // one of the special DEVCB_TYPE values
+ UINT16 index; // index related to the above types
+ const char * tag; // tag of target, where appropriate
+ const char * name; // name of the target function
+ read_line_device_func readline; // read line function
+ read8_device_func readdevice; // read device function
+ read8_space_func readspace; // read space function
+};
+
+
+// ======================> devcb_resolved_read8
+
+// base delegate type for a read8
+typedef delegate<UINT8 (offs_t)> devcb_read8_delegate;
+
+// class which wraps resolving a devcb_read8 into a delegate
+class devcb_resolved_read8 : public devcb_read8_delegate
+{
+ DISABLE_COPYING(devcb_resolved_read8);
+
+public:
+ // construction/destruction
+ devcb_resolved_read8();
+ devcb_resolved_read8(const devcb_read8 &desc, device_t &device) { resolve(desc, device); }
+
+ // resolution
+ void resolve(const devcb_read8 &desc, device_t &device);
+
+ // override parent class' notion of NULL
+ bool isnull() const { return m_helper.null_indicator == &s_null; }
+
+private:
+ // internal helpers
+ UINT8 from_port(offs_t offset);
+ UINT8 from_readline(offs_t offset);
+ UINT8 from_constant(offs_t offset);
+
+ // internal state
+ devcb_resolved_objects m_object;
+ devcb_resolved_read_helpers m_helper;
+ static UINT8 s_null;
+};
+
+
+// ======================> devcb_write8
+
+// static structure used for device configuration when the desired callback type is a write8_device_func
+struct devcb_write8
+{
+ UINT16 type; // one of the special DEVCB_TYPE values
+ UINT16 index; // index related to the above types
+ const char * tag; // tag of target, where appropriate
+ const char * name; // name of the target function
+ write_line_device_func writeline; // write line function
+ write8_device_func writedevice; // write device function
+ write8_space_func writespace; // write space function
+};
+
+
+// ======================> devcb_resolved_write8
+
+// base delegate type for a write8
+typedef delegate<void (offs_t, UINT8)> devcb_write8_delegate;
+
+// class which wraps resolving a devcb_write8 into a delegate
+class devcb_resolved_write8 : public devcb_write8_delegate
+{
+ DISABLE_COPYING(devcb_resolved_write8);
+
+public:
+ // construction/destruction
+ devcb_resolved_write8();
+ devcb_resolved_write8(const devcb_write8 &desc, device_t &device) { resolve(desc, device); }
+
+ // resolution
+ void resolve(const devcb_write8 &desc, device_t &device);
+
+ // override parent class' notion of NULL
+ bool isnull() const { return m_helper.null_indicator == &s_null; }
+
+private:
+ // internal helpers
+ void to_null(offs_t offset, UINT8 data);
+ void to_port(offs_t offset, UINT8 data);
+ void to_writeline(offs_t offset, UINT8 data);
+ void to_input(offs_t offset, UINT8 data);
+
+ // internal state
+ devcb_resolved_objects m_object;
+ devcb_resolved_write_helpers m_helper;
+ static UINT8 s_null;
+};
+
+
+// ======================> devcb_read16
+
+// static structure used for device configuration when the desired callback type is a read16_device_func
+struct devcb_read16
+{
+ UINT16 type; // one of the special DEVCB_TYPE values
+ UINT16 index; // index related to the above types
+ const char * tag; // tag of target, where appropriate
+ const char * name; // name of the target function
+ read_line_device_func readline; // read line function
+ read16_device_func readdevice; // read device function
+ read16_space_func readspace; // read space function
+};
+
+
+// ======================> devcb_resolved_read16
+
+// base delegate type for a write8
+typedef delegate<UINT16 (offs_t, UINT16)> devcb_read16_delegate;
+
+// class which wraps resolving a devcb_read16 into a delegate
+class devcb_resolved_read16 : public devcb_read16_delegate
+{
+ DISABLE_COPYING(devcb_resolved_read16);
+
+public:
+ // construction/destruction
+ devcb_resolved_read16();
+ devcb_resolved_read16(const devcb_read16 &desc, device_t &device) { resolve(desc, device); }
+
+ // resolution
+ void resolve(const devcb_read16 &desc, device_t &device);
+
+ // override parent class' notion of NULL
+ bool isnull() const { return m_helper.null_indicator == &s_null; }
+
+private:
+ // internal helpers
+ UINT16 from_port(offs_t offset, UINT16 mask);
+ UINT16 from_readline(offs_t offset, UINT16 mask);
+ UINT16 from_constant(offs_t offset, UINT16 mask);
+
+ // internal state
+ devcb_resolved_objects m_object;
+ devcb_resolved_read_helpers m_helper;
+ static UINT8 s_null;
+};
+
+
+// ======================> devcb_write16
+
+// static structure used for device configuration when the desired callback type is a write16_device_func
+struct devcb_write16
+{
+ UINT16 type; // one of the special DEVCB_TYPE values
+ UINT16 index; // index related to the above types
+ const char * tag; // tag of target, where appropriate
+ const char * name; // name of the target function
+ write_line_device_func writeline; // write line function
+ write16_device_func writedevice; // write device function
+ write16_space_func writespace; // write space function
+};
+
+
+// ======================> devcb_resolved_write16
+
+// base delegate type for a write8
+typedef delegate<void (offs_t, UINT16, UINT16)> devcb_write16_delegate;
+
+// class which wraps resolving a devcb_write16 into a delegate
+class devcb_resolved_write16 : public devcb_write16_delegate
+{
+ DISABLE_COPYING(devcb_resolved_write16);
+
+public:
+ // construction/destruction
+ devcb_resolved_write16();
+ devcb_resolved_write16(const devcb_write16 &desc, device_t &device) { resolve(desc, device); }
+
+ // resolution
+ void resolve(const devcb_write16 &desc, device_t &device);
+
+ // override parent class' notion of NULL
+ bool isnull() const { return m_helper.null_indicator == &s_null; }
+
+private:
+ // internal helpers
+ void to_null(offs_t offset, UINT16 data, UINT16 mask);
+ void to_port(offs_t offset, UINT16 data, UINT16 mask);
+ void to_writeline(offs_t offset, UINT16 data, UINT16 mask);
+ void to_input(offs_t offset, UINT16 data, UINT16 mask);
+
+ // internal state
+ devcb_resolved_objects m_object;
+ devcb_resolved_write_helpers m_helper;
+ static UINT8 s_null;
+};
+
+
+#endif // __DEVCB_H__
diff --git a/trunk/src/emu/devconv.h b/trunk/src/emu/devconv.h
new file mode 100644
index 00000000000..a7b81a27827
--- /dev/null
+++ b/trunk/src/emu/devconv.h
@@ -0,0 +1,1020 @@
+/***************************************************************************
+
+ devconv.h
+
+ Functions which help convert between different device handlers.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+****************************************************************************
+
+ ***** VERY IMPORTANT NOTICE *****
+
+ These functions and macros are provided to facilitate the mapping
+ of devices on cpus with different data bus widths.
+ Devices should be implemented using their native data bus width,
+ since that ensures that read/write operations are kept atomic.
+ If we discover you have abused the functionality presented in this
+ file, you *will* be publicly humiliated and your code submission
+ will probably not be accepted. Seriously, please do not abuse these
+ functions/macros.
+
+****************************************************************************
+
+ Conversions supported:
+
+ CW = CPU Data Bus Width in bits
+ CBO = CPU Byte Order
+ DW = Device Data Bus Width in bits
+ DBO = Device Byte Order
+
+ CW | CBO | DW | DBO | Functions to use
+ ---+--------+----+--------+-----------------------------------------------------------
+ 16 | Big | 8 | N/A | read16be_with_read8_device_handler,write16be_with_write8_device_handler
+ 16 | Little | 8 | N/A | read16le_with_read8_device_handler,write16le_with_write8_device_handler
+ ---+--------+----+--------+-----------------------------------------------------------
+ 32 | Big | 8 | N/A | read32be_with_read8_device_handler,write32be_with_write8_device_handler
+ 32 | Little | 8 | N/A | read32le_with_read8_device_handler,write32le_with_write8_device_handler
+ 32 | Big | 16 | Big | read32be_with_16be_device_handler,write32be_with_16be_device_handler
+ 32 | Little | 16 | Little | read32le_with_16le_device_handler,write32le_with_16le_device_handler
+ 32 | Big | 16 | Little | read32be_with_16le_device_handler,write32be_with_16le_device_handler
+ 32 | Little | 16 | Big | read32le_with_16be_device_handler,write32le_with_16be_device_handler
+ ---+--------+----+--------+-----------------------------------------------------------
+ 64 | Big | 8 | N/A | read64be_with_read8_device_handler,write64be_with_write8_device_handler
+ 64 | Little | 8 | N/A | read64le_with_read8_device_handler,write64le_with_write8_device_handler
+ 64 | Big | 16 | Big | read64be_with_16be_device_handler,write64be_with_16be_device_handler
+ 64 | Little | 16 | Little | read64le_with_16le_device_handler,write64le_with_16le_device_handler
+ 64 | Big | 16 | Little | read64be_with_16le_device_handler,write64be_with_16le_device_handler
+ 64 | Little | 16 | Big | read64le_with_16be_device_handler,write64le_with_16be_device_handler
+ 64 | Big | 32 | Big | read64be_with_32be_device_handler,write64be_with_32be_device_handler
+ 64 | Little | 32 | Little | read64le_with_32le_device_handler,write64le_with_32le_device_handler
+ 64 | Big | 32 | Little | read64be_with_32le_device_handler,write64be_with_32le_device_handler
+ 64 | Little | 32 | Big | read64le_with_32be_device_handler,write64le_with_32be_device_handler
+
+ You can also find at the bottom of this file a few convernient
+ macros that will create the stub read and/or write handlers for
+ the most common mappings, that will use the functions above.
+ Here's an example on how to use them: Say you have a 8 bit device
+ whose handlers are device8_r and device8_w, and you want to connect
+ it to a 16 bit, big endian cpu. We'll say the device is mapped on
+ the least significant byte of the data bus (LSB).
+
+ In your driver, you would add:
+
+ DEV_READWRITE8TO16BE_LSB( device16, device8_r, device8_w )
+
+ which will create two 16 bit memory handlers, one for read, called
+ device16_r, and one for write, called device16_w, with the proper
+ mapping.
+
+ then in the MEMORY_MAP you would specify:
+
+ AM_RANGE(0x000000, 0x0000ff) AM_DEVREADWRITE( DEVICE, "device", device16_r, device16_w )
+
+ And that is all. Your device should be mapped properly.
+ If you need to do custom mappings, or a mapping that is not currently
+ supported in this file, you can always write the stub yourself, and
+ call the above functions to invoke the base handlers.
+
+***************************************************************************/
+
+/*************************************
+ *
+ * 16-bit BE using 8-bit handlers
+ *
+ *************************************/
+
+INLINE UINT16 read16be_with_read8_device_handler(read8_device_func handler, device_t *device, offs_t offset, UINT16 mem_mask)
+{
+ UINT16 result = 0;
+ if (ACCESSING_BITS_8_15)
+ result |= ((UINT16)(*handler)(device, offset * 2 + 0)) << 8;
+ if (ACCESSING_BITS_0_7)
+ result |= ((UINT16)(*handler)(device, offset * 2 + 1)) << 0;
+ return result;
+}
+
+
+INLINE void write16be_with_write8_device_handler(write8_device_func handler, device_t *device, offs_t offset, UINT16 data, UINT16 mem_mask)
+{
+ if (ACCESSING_BITS_8_15)
+ (*handler)(device, offset * 2 + 0, data >> 8);
+ if (ACCESSING_BITS_0_7)
+ (*handler)(device, offset * 2 + 1, data >> 0);
+}
+
+
+/*************************************
+ *
+ * 16-bit LE using 8-bit handlers
+ *
+ *************************************/
+
+INLINE UINT16 read16le_with_read8_device_handler(read8_device_func handler, device_t *device, offs_t offset, UINT16 mem_mask)
+{
+ UINT16 result = 0;
+ if (ACCESSING_BITS_0_7)
+ result |= ((UINT16) (*handler)(device, offset * 2 + 0)) << 0;
+ if (ACCESSING_BITS_8_15)
+ result |= ((UINT16) (*handler)(device, offset * 2 + 1)) << 8;
+ return result;
+}
+
+
+INLINE void write16le_with_write8_device_handler(write8_device_func handler, device_t *device, offs_t offset, UINT16 data, UINT16 mem_mask)
+{
+ if (ACCESSING_BITS_0_7)
+ (*handler)(device, offset * 2 + 0, data >> 0);
+ if (ACCESSING_BITS_8_15)
+ (*handler)(device, offset * 2 + 1, data >> 8);
+}
+
+
+/*************************************
+ *
+ * 32-bit BE using 8-bit handlers
+ *
+ *************************************/
+
+INLINE UINT32 read32be_with_read8_device_handler(read8_device_func handler, device_t *device, offs_t offset, UINT32 mem_mask)
+{
+ UINT32 result = 0;
+ if (ACCESSING_BITS_16_31)
+ result |= read16be_with_read8_device_handler(handler, device, offset * 2 + 0, mem_mask >> 16) << 16;
+ if (ACCESSING_BITS_0_15)
+ result |= read16be_with_read8_device_handler(handler, device, offset * 2 + 1, mem_mask) << 0;
+ return result;
+}
+
+
+INLINE void write32be_with_write8_device_handler(write8_device_func handler, device_t *device, offs_t offset, UINT32 data, UINT32 mem_mask)
+{
+ if (ACCESSING_BITS_16_31)
+ write16be_with_write8_device_handler(handler, device, offset * 2 + 0, data >> 16, mem_mask >> 16);
+ if (ACCESSING_BITS_0_15)
+ write16be_with_write8_device_handler(handler, device, offset * 2 + 1, data, mem_mask);
+}
+
+
+/*************************************
+ *
+ * 32-bit LE using 8-bit handlers
+ *
+ *************************************/
+
+INLINE UINT32 read32le_with_read8_device_handler(read8_device_func handler, device_t *device, offs_t offset, UINT32 mem_mask)
+{
+ UINT32 result = 0;
+ if (ACCESSING_BITS_0_15)
+ result |= read16le_with_read8_device_handler(handler, device, offset * 2 + 0, mem_mask) << 0;
+ if (ACCESSING_BITS_16_31)
+ result |= read16le_with_read8_device_handler(handler, device, offset * 2 + 1, mem_mask >> 16) << 16;
+ return result;
+}
+
+
+INLINE void write32le_with_write8_device_handler(write8_device_func handler, device_t *device, offs_t offset, UINT32 data, UINT32 mem_mask)
+{
+ if (ACCESSING_BITS_0_15)
+ write16le_with_write8_device_handler(handler, device, offset * 2 + 0, data, mem_mask);
+ if (ACCESSING_BITS_16_31)
+ write16le_with_write8_device_handler(handler, device, offset * 2 + 1, data >> 16, mem_mask >> 16);
+}
+
+
+/*************************************
+ *
+ * 32-bit BE using 16-bit BE handlers
+ *
+ *************************************/
+
+INLINE UINT32 read32be_with_16be_device_handler(read16_device_func handler, device_t *device, offs_t offset, UINT32 mem_mask)
+{
+ UINT32 result = 0;
+ if (ACCESSING_BITS_16_31)
+ result |= (*handler)(device, offset * 2 + 0, mem_mask >> 16) << 16;
+ if (ACCESSING_BITS_0_15)
+ result |= (*handler)(device, offset * 2 + 1, mem_mask) << 0;
+ return result;
+}
+
+
+INLINE void write32be_with_16be_device_handler(write16_device_func handler, device_t *device, offs_t offset, UINT32 data, UINT32 mem_mask)
+{
+ if (ACCESSING_BITS_16_31)
+ (*handler)(device, offset * 2 + 0, data >> 16, mem_mask >> 16);
+ if (ACCESSING_BITS_0_15)
+ (*handler)(device, offset * 2 + 1, data, mem_mask);
+}
+
+
+/*************************************
+ *
+ * 32-bit LE using 16-bit LE handlers
+ *
+ *************************************/
+
+INLINE UINT32 read32le_with_16le_device_handler(read16_device_func handler, device_t *device, offs_t offset, UINT32 mem_mask)
+{
+ UINT32 result = 0;
+ if (ACCESSING_BITS_0_15)
+ result |= (*handler)(device, offset * 2 + 0, mem_mask) << 0;
+ if (ACCESSING_BITS_16_31)
+ result |= (*handler)(device, offset * 2 + 1, mem_mask >> 16) << 16;
+ return result;
+}
+
+
+INLINE void write32le_with_16le_device_handler(write16_device_func handler, device_t *device, offs_t offset, UINT32 data, UINT32 mem_mask)
+{
+ if (ACCESSING_BITS_0_15)
+ (*handler)(device, offset * 2 + 0, data, mem_mask);
+ if (ACCESSING_BITS_16_31)
+ (*handler)(device, offset * 2 + 1, data >> 16, mem_mask >> 16);
+}
+
+
+/*************************************
+ *
+ * 32-bit BE using 16-bit LE handlers
+ *
+ *************************************/
+
+INLINE UINT32 read32be_with_16le_device_handler(read16_device_func handler, device_t *device, offs_t offset, UINT32 mem_mask)
+{
+ UINT32 result = 0;
+ mem_mask = FLIPENDIAN_INT32(mem_mask);
+ result = read32le_with_16le_device_handler(handler, device, offset, mem_mask);
+ return FLIPENDIAN_INT32(result);
+}
+
+
+INLINE void write32be_with_16le_device_handler(write16_device_func handler, device_t *device, offs_t offset, UINT32 data, UINT32 mem_mask)
+{
+ data = FLIPENDIAN_INT32(data);
+ mem_mask = FLIPENDIAN_INT32(mem_mask);
+ write32le_with_16le_device_handler(handler, device, offset, data, mem_mask);
+}
+
+
+/*************************************
+ *
+ * 32-bit LE using 16-bit BE handlers
+ *
+ *************************************/
+
+INLINE UINT32 read32le_with_16be_device_handler(read16_device_func handler, device_t *device, offs_t offset, UINT32 mem_mask)
+{
+ UINT32 result = 0;
+ mem_mask = FLIPENDIAN_INT32(mem_mask);
+ result = read32be_with_16be_device_handler(handler, device, offset, mem_mask);
+ return FLIPENDIAN_INT32(result);
+}
+
+
+INLINE void write32le_with_16be_device_handler(write16_device_func handler, device_t *device, offs_t offset, UINT32 data, UINT32 mem_mask)
+{
+ data = FLIPENDIAN_INT32(data);
+ mem_mask = FLIPENDIAN_INT32(mem_mask);
+ write32be_with_16be_device_handler(handler, device, offset, data, mem_mask);
+}
+
+
+/*************************************
+ *
+ * 64-bit BE using 8-bit handlers
+ *
+ *************************************/
+
+INLINE UINT64 read64be_with_read8_device_handler(read8_device_func handler, device_t *device, offs_t offset, UINT64 mem_mask)
+{
+ UINT64 result = 0;
+ if (ACCESSING_BITS_32_63)
+ result |= (UINT64)read32be_with_read8_device_handler(handler, device, offset * 2 + 0, mem_mask >> 32) << 32;
+ if (ACCESSING_BITS_0_31)
+ result |= (UINT64)read32be_with_read8_device_handler(handler, device, offset * 2 + 1, mem_mask) << 0;
+ return result;
+}
+
+
+INLINE void write64be_with_write8_device_handler(write8_device_func handler, device_t *device, offs_t offset, UINT64 data, UINT64 mem_mask)
+{
+ if (ACCESSING_BITS_32_63)
+ write32be_with_write8_device_handler(handler, device, offset * 2 + 0, data >> 32, mem_mask >> 32);
+ if (ACCESSING_BITS_0_31)
+ write32be_with_write8_device_handler(handler, device, offset * 2 + 1, data, mem_mask);
+}
+
+
+/*************************************
+ *
+ * 64-bit LE using 8-bit handlers
+ *
+ *************************************/
+
+INLINE UINT64 read64le_with_read8_device_handler(read8_device_func handler, device_t *device, offs_t offset, UINT64 mem_mask)
+{
+ UINT64 result = 0;
+ if (ACCESSING_BITS_0_31)
+ result |= (UINT64)read32le_with_read8_device_handler(handler, device, offset * 2 + 0, mem_mask >> 0) << 0;
+ if (ACCESSING_BITS_32_63)
+ result |= (UINT64)read32le_with_read8_device_handler(handler, device, offset * 2 + 1, mem_mask >> 32) << 32;
+ return result;
+}
+
+
+INLINE void write64le_with_write8_device_handler(write8_device_func handler, device_t *device, offs_t offset, UINT64 data, UINT64 mem_mask)
+{
+ if (ACCESSING_BITS_0_31)
+ write32le_with_write8_device_handler(handler, device, offset * 2 + 0, data >> 0, mem_mask >> 0);
+ if (ACCESSING_BITS_32_63)
+ write32le_with_write8_device_handler(handler, device, offset * 2 + 1, data >> 32, mem_mask >> 32);
+}
+
+
+/*************************************
+ *
+ * 64-bit BE using 16-bit BE handlers
+ *
+ *************************************/
+
+INLINE UINT32 read64be_with_16be_device_handler(read16_device_func handler, device_t *device, offs_t offset, UINT64 mem_mask)
+{
+ UINT64 result = 0;
+ if (ACCESSING_BITS_32_63)
+ result |= (UINT64)read32be_with_16be_device_handler(handler, device, offset * 2 + 0, mem_mask >> 32) << 32;
+ if (ACCESSING_BITS_0_31)
+ result |= (UINT64)read32be_with_16be_device_handler(handler, device, offset * 2 + 1, mem_mask >> 0) << 0;
+ return result;
+}
+
+
+INLINE void write64be_with_16be_device_handler(write16_device_func handler, device_t *device, offs_t offset, UINT64 data, UINT64 mem_mask)
+{
+ if (ACCESSING_BITS_32_63)
+ write32be_with_16be_device_handler(handler, device, offset * 2 + 0, data >> 32, mem_mask >> 32);
+ if (ACCESSING_BITS_0_31)
+ write32be_with_16be_device_handler(handler, device, offset * 2 + 1, data >> 0, mem_mask >> 0);
+}
+
+
+/*************************************
+ *
+ * 64-bit LE using 16-bit LE handlers
+ *
+ *************************************/
+
+INLINE UINT32 read64le_with_16le_device_handler(read16_device_func handler, device_t *device, offs_t offset, UINT64 mem_mask)
+{
+ UINT64 result = 0;
+ if (ACCESSING_BITS_0_31)
+ result |= (UINT64)read32le_with_16le_device_handler(handler, device, offset * 2 + 0, mem_mask >> 0) << 0;
+ if (ACCESSING_BITS_32_63)
+ result |= (UINT64)read32le_with_16le_device_handler(handler, device, offset * 2 + 1, mem_mask >> 32) << 32;
+ return result;
+}
+
+
+INLINE void write64le_with_16le_device_handler(write16_device_func handler, device_t *device, offs_t offset, UINT64 data, UINT64 mem_mask)
+{
+ if (ACCESSING_BITS_0_31)
+ write32le_with_16le_device_handler(handler, device, offset * 2 + 0, data >> 0, mem_mask >> 0);
+ if (ACCESSING_BITS_32_63)
+ write32le_with_16le_device_handler(handler, device, offset * 2 + 1, data >> 32, mem_mask >> 32);
+}
+
+
+/*************************************
+ *
+ * 64-bit BE using 16-bit LE handlers
+ *
+ *************************************/
+
+INLINE UINT32 read64be_with_16le_device_handler(read16_device_func handler, device_t *device, offs_t offset, UINT64 mem_mask)
+{
+ UINT64 result = 0;
+ if (ACCESSING_BITS_32_63)
+ result |= (UINT64)read32be_with_16le_device_handler(handler, device, offset * 2 + 0, mem_mask >> 32) << 32;
+ if (ACCESSING_BITS_0_31)
+ result |= (UINT64)read32be_with_16le_device_handler(handler, device, offset * 2 + 1, mem_mask >> 0) << 0;
+ return result;
+}
+
+
+INLINE void write64be_with_16le_device_handler(write16_device_func handler, device_t *device, offs_t offset, UINT64 data, UINT64 mem_mask)
+{
+ if (ACCESSING_BITS_32_63)
+ write32be_with_16le_device_handler(handler, device, offset * 2 + 0, data >> 32, mem_mask >> 32);
+ if (ACCESSING_BITS_0_31)
+ write32be_with_16le_device_handler(handler, device, offset * 2 + 1, data >> 0, mem_mask >> 0);
+}
+
+
+/*************************************
+ *
+ * 64-bit LE using 16-bit BE handlers
+ *
+ *************************************/
+
+INLINE UINT32 read64le_with_16be_device_handler(read16_device_func handler, device_t *device, offs_t offset, UINT64 mem_mask)
+{
+ UINT64 result = 0;
+ if (ACCESSING_BITS_0_31)
+ result |= (UINT64)read32le_with_16be_device_handler(handler, device, offset * 2 + 0, mem_mask >> 0) << 0;
+ if (ACCESSING_BITS_32_63)
+ result |= (UINT64)read32le_with_16be_device_handler(handler, device, offset * 2 + 1, mem_mask >> 32) << 32;
+ return result;
+}
+
+
+INLINE void write64le_with_16be_device_handler(write16_device_func handler, device_t *device, offs_t offset, UINT64 data, UINT64 mem_mask)
+{
+ if (ACCESSING_BITS_0_31)
+ write32le_with_16be_device_handler(handler, device, offset * 2 + 0, data >> 0, mem_mask >> 0);
+ if (ACCESSING_BITS_32_63)
+ write32le_with_16be_device_handler(handler, device, offset * 2 + 1, data >> 32, mem_mask >> 32);
+}
+
+
+/*************************************
+ *
+ * 64-bit BE using 32-bit BE handlers
+ *
+ *************************************/
+
+INLINE UINT64 read64be_with_32be_device_handler(read32_device_func handler, device_t *device, offs_t offset, UINT64 mem_mask)
+{
+ UINT64 result = 0;
+ if (ACCESSING_BITS_32_63)
+ result |= (UINT64)(*handler)(device, offset * 2 + 0, mem_mask >> 32) << 32;
+ if (ACCESSING_BITS_0_31)
+ result |= (UINT64)(*handler)(device, offset * 2 + 1, mem_mask >> 0) << 0;
+ return result;
+}
+
+
+INLINE void write64be_with_32be_device_handler(write32_device_func handler, device_t *device, offs_t offset, UINT64 data, UINT64 mem_mask)
+{
+ if (ACCESSING_BITS_32_63)
+ (*handler)(device, offset * 2 + 0, data >> 32, mem_mask >> 32);
+ if (ACCESSING_BITS_0_31)
+ (*handler)(device, offset * 2 + 1, data >> 0, mem_mask >> 0);
+}
+
+
+/*************************************
+ *
+ * 64-bit LE using 32-bit LE handlers
+ *
+ *************************************/
+
+INLINE UINT64 read64le_with_32le_device_handler(read32_device_func handler, device_t *device, offs_t offset, UINT64 mem_mask)
+{
+ UINT64 result = 0;
+ if (ACCESSING_BITS_0_31)
+ result |= (UINT64)(*handler)(device, offset * 2 + 0, mem_mask >> 0) << 0;
+ if (ACCESSING_BITS_32_63)
+ result |= (UINT64)(*handler)(device, offset * 2 + 1, mem_mask >> 32) << 32;
+ return result;
+}
+
+
+INLINE void write64le_with_32le_device_handler(write32_device_func handler, device_t *device, offs_t offset, UINT64 data, UINT64 mem_mask)
+{
+ if (ACCESSING_BITS_0_31)
+ (*handler)(device, offset * 2 + 0, data >> 0, mem_mask >> 0);
+ if (ACCESSING_BITS_32_63)
+ (*handler)(device, offset * 2 + 1, data >> 32, mem_mask >> 32);
+}
+
+
+/*************************************
+ *
+ * 64-bit BE using 32-bit LE handlers
+ *
+ *************************************/
+
+INLINE UINT64 read64be_with_32le_device_handler(read32_device_func handler, device_t *device, offs_t offset, UINT64 mem_mask)
+{
+ UINT64 result;
+ mem_mask = FLIPENDIAN_INT64(mem_mask);
+ result = read64le_with_32le_device_handler(handler, device, offset, mem_mask);
+ return FLIPENDIAN_INT64(result);
+}
+
+
+INLINE void write64be_with_32le_device_handler(write32_device_func handler, device_t *device, offs_t offset, UINT64 data, UINT64 mem_mask)
+{
+ data = FLIPENDIAN_INT64(data);
+ mem_mask = FLIPENDIAN_INT64(mem_mask);
+ write64le_with_32le_device_handler(handler, device, offset, data, mem_mask);
+}
+
+
+/*************************************
+ *
+ * 64-bit LE using 32-bit BE handlers
+ *
+ *************************************/
+
+INLINE UINT64 read64le_with_32be_device_handler(read32_device_func handler, device_t *device, offs_t offset, UINT64 mem_mask)
+{
+ UINT64 result;
+ mem_mask = FLIPENDIAN_INT64(mem_mask);
+ result = read64be_with_32be_device_handler(handler, device, offset, mem_mask);
+ return FLIPENDIAN_INT64(result);
+}
+
+
+INLINE void write64le_with_32be_device_handler(write32_device_func handler, device_t *device, offs_t offset, UINT64 data, UINT64 mem_mask)
+{
+ data = FLIPENDIAN_INT64(data);
+ mem_mask = FLIPENDIAN_INT64(mem_mask);
+ write64be_with_32be_device_handler(handler, device, offset, data, mem_mask);
+}
+
+
+
+/**************************************************************************
+
+ Utility macros
+
+**************************************************************************/
+
+#define DEV_READ_TEMPLATE(bits, name, handler, func) \
+READ##bits##_DEVICE_HANDLER( name##_r ) \
+{ \
+ return func(handler, device, offset, mem_mask); \
+}
+
+#define DEV_READ_TEMPLATE_COND(bits, name, handler, func, cond) \
+READ##bits##_DEVICE_HANDLER( name##_r ) \
+{ \
+ if (cond) \
+ return func(handler, device, offset, mem_mask); \
+ return 0; \
+}
+
+#define DEV_WRITE_TEMPLATE(bits, name, handler, func) \
+WRITE##bits##_DEVICE_HANDLER( name##_w ) \
+{ \
+ func(handler, device, offset, data, mem_mask); \
+}
+
+#define DEV_WRITE_TEMPLATE_COND(bits, name, handler, func, cond) \
+WRITE##bits##_DEVICE_HANDLER( name##_w ) \
+{ \
+ if (cond) \
+ func(handler, device, offset, data, mem_mask); \
+}
+
+
+
+/**************************************************************************
+
+ Generic conversions macros
+
+**************************************************************************/
+
+
+/*************************************
+ * 8->16be, 1:1 mapping
+ ************************************/
+
+#define DEV_READ8TO16BE( name, read8 ) \
+DEV_READ_TEMPLATE( 16, name, read8, read16be_with_read8_device_handler )
+
+
+#define DEV_WRITE8TO16BE( name, write8 ) \
+DEV_WRITE_TEMPLATE( 16, name, write8, write16be_with_write8_device_handler )
+
+
+#define DEV_READWRITE8TO16BE( name, read8, write8 ) \
+DEV_READ8TO16BE(name,read8) \
+DEV_WRITE8TO16BE(name,write8)
+
+
+/*************************************
+ * 8->16le, 1:1 mapping
+ ************************************/
+
+#define DEV_READ8TO16LE( name, read8 ) \
+DEV_READ_TEMPLATE( 16, name, read8, read16le_with_read8_device_handler )
+
+
+#define DEV_WRITE8TO16LE( name, write8 ) \
+DEV_WRITE_TEMPLATE( 16, name, write8, write16le_with_write8_device_handler )
+
+
+#define DEV_READWRITE8TO16LE( name, read8, write8 ) \
+DEV_READ8TO16LE(name,read8) \
+DEV_WRITE8TO16LE(name,write8)
+
+
+/*************************************
+ * 8->16be, MSB mapping
+ ************************************/
+
+#define DEV_READ8TO16BE_MSB( name, read8 ) \
+DEV_READ_TEMPLATE_COND( 16, name, read8, read16be_with_read8_device_handler, ACCESSING_BITS_8_15 )
+
+
+#define DEV_WRITE8TO16BE_MSB( name, write8 ) \
+DEV_WRITE_TEMPLATE_COND( 16, name, write8, write16be_with_write8_device_handler, ACCESSING_BITS_8_15 )
+
+
+#define DEV_READWRITE8TO16BE_MSB( name, read8, write8 ) \
+DEV_READ8TO16BE_MSB(name,read8) \
+DEV_WRITE8TO16BE_MSB(name,write8)
+
+
+/*************************************
+ * 8->16le, MSB mapping
+ ************************************/
+
+#define DEV_READ8TO16LE_MSB( name, read8 ) \
+DEV_READ_TEMPLATE_COND( 16, name, read8, read16le_with_read8_device_handler, ACCESSING_BITS_8_15 )
+
+
+#define DEV_WRITE8TO16LE_MSB( name, write8 ) \
+DEV_WRITE_TEMPLATE_COND( 16, name, write8, write16le_with_write8_device_handler, ACCESSING_BITS_8_15 )
+
+
+#define DEV_READWRITE8TO16LE_MSB( name, read8, write8 ) \
+DEV_READ8TO16LE_MSB(name,read8) \
+DEV_WRITE8TO16LE_MSB(name,write8)
+
+
+/*************************************
+ * 8->16be, LSB mapping
+ ************************************/
+
+#define DEV_READ8TO16BE_LSB( name, read8 ) \
+DEV_READ_TEMPLATE_COND( 16, name, read8, read16be_with_read8_device_handler, ACCESSING_BITS_0_7 )
+
+
+#define DEV_WRITE8TO16BE_LSB( name, write8 ) \
+DEV_WRITE_TEMPLATE_COND( 16, name, write8, write16be_with_write8_device_handler, ACCESSING_BITS_0_7 )
+
+
+#define DEV_READWRITE8TO16BE_LSB( name, read8, write8 ) \
+DEV_READ8TO16BE_LSB(name,read8) \
+DEV_WRITE8TO16BE_LSB(name,write8)
+
+
+/*************************************
+ * 8->16le, LSB mapping
+ ************************************/
+
+#define DEV_READ8TO16LE_LSB( name, read8 ) \
+DEV_READ_TEMPLATE_COND( 16, name, read8, read16le_with_read8_device_handler, ACCESSING_BITS_0_7 )
+
+
+#define DEV_WRITE8TO16LE_LSB( name, write8 ) \
+DEV_WRITE_TEMPLATE_COND( 16, name, write8, write16le_with_write8_device_handler, ACCESSING_BITS_0_7 )
+
+
+#define DEV_READWRITE8TO16LE_LSB( name, read8, write8 ) \
+DEV_READ8TO16LE_LSB(name,read8) \
+DEV_WRITE8TO16LE_LSB(name,write8)
+
+
+/*************************************
+ * 8->32be, 1:1 mapping
+ ************************************/
+
+#define DEV_READ8TO32BE( name, read8 ) \
+DEV_READ_TEMPLATE( 32, name, read8, read32be_with_read8_device_handler )
+
+
+#define DEV_WRITE8TO32BE( name, write8 ) \
+DEV_WRITE_TEMPLATE( 32, name, write8, write32be_with_write8_device_handler )
+
+
+#define DEV_READWRITE8TO32BE( name, read8, write8 ) \
+DEV_READ8TO32BE(name,read8) \
+DEV_WRITE8TO32BE(name,write8)
+
+
+/*************************************
+ * 8->32le, 1:1 mapping
+ ************************************/
+
+#define DEV_READ8TO32LE( name, read8 ) \
+DEV_READ_TEMPLATE( 32, name, read8, read32le_with_read8_device_handler )
+
+
+#define DEV_WRITE8TO32LE( name, write8 ) \
+DEV_WRITE_TEMPLATE( 32, name, write8, write32le_with_write8_device_handler )
+
+
+#define DEV_READWRITE8TO32LE( name, read8, write8 ) \
+DEV_READ8TO32LE(name,read8) \
+DEV_WRITE8TO32LE(name,write8)
+
+
+/*************************************
+ * 8->32be, MSB mapping
+ ************************************/
+
+#define DEV_READ8TO32BE_MSB( name, read8 ) \
+DEV_READ_TEMPLATE_COND( 32, name, read8, read32be_with_read8_device_handler, ACCESSING_BITS_24_31 )
+
+
+#define DEV_WRITE8TO32BE_MSB( name, write8 ) \
+DEV_WRITE_TEMPLATE_COND( 32, name, write8, write32be_with_write8_device_handler, ACCESSING_BITS_24_31 )
+
+
+#define DEV_READWRITE8TO32BE_MSB( name, read8, write8 ) \
+DEV_READ8TO32BE_MSB(name,read8) \
+DEV_WRITE8TO32BE_MSB(name,write8)
+
+
+/*************************************
+ * 8->32le, MSB mapping
+ ************************************/
+
+#define DEV_READ8TO32LE_MSB( name, read8 ) \
+DEV_READ_TEMPLATE_COND( 32, name, read8, read32le_with_read8_device_handler, ACCESSING_BITS_24_31 )
+
+
+#define DEV_WRITE8TO32LE_MSB( name, write8 ) \
+DEV_WRITE_TEMPLATE_COND( 32, name, write8, write32le_with_write8_device_handler, ACCESSING_BITS_24_31 )
+
+
+#define DEV_READWRITE8TO32LE_MSB( name, read8, write8 ) \
+DEV_READ8TO32LE_MSB(name,read8) \
+DEV_WRITE8TO32LE_MSB(name,write8)
+
+
+/*************************************
+ * 8->32be, LSB mapping
+ ************************************/
+
+#define DEV_READ8TO32BE_LSB( name, read8 ) \
+DEV_READ_TEMPLATE_COND( 32, name, read8, read32be_with_read8_device_handler, ACCESSING_BITS_0_7 )
+
+
+#define DEV_WRITE8TO32BE_LSB( name, write8 ) \
+DEV_WRITE_TEMPLATE_COND( 32, name, write8, write32be_with_write8_device_handler, ACCESSING_BITS_0_7 )
+
+
+#define DEV_READWRITE8TO32BE_LSB( name, read8, write8 ) \
+DEV_READ8TO32BE_LSB(name,read8) \
+DEV_WRITE8TO32BE_LSB(name,write8)
+
+
+/*************************************
+ * 8->32le, LSB mapping
+ ************************************/
+
+#define DEV_READ8TO32LE_LSB( name, read8 ) \
+DEV_READ_TEMPLATE_COND( 32, name, read8, read32le_with_read8_device_handler, ACCESSING_BITS_0_7 )
+
+
+#define DEV_WRITE8TO32LE_LSB( name, write8 ) \
+DEV_WRITE_TEMPLATE_COND( 32, name, write8, write32le_with_write8_device_handler, ACCESSING_BITS_0_7 )
+
+
+#define DEV_READWRITE8TO32LE_LSB( name, read8, write8 ) \
+DEV_READ8TO32LE_LSB(name,read8) \
+DEV_WRITE8TO32LE_LSB(name,write8)
+
+
+/*************************************
+ * 8->64be, 1:1 mapping
+ ************************************/
+
+#define DEV_READ8TO64BE( name, read8 ) \
+DEV_READ_TEMPLATE( 64, name, read8, read64be_with_read8_device_handler )
+
+
+#define DEV_WRITE8TO64BE( name, write8 ) \
+DEV_WRITE_TEMPLATE( 64, name, write8, write64be_with_write8_device_handler )
+
+
+#define DEV_READWRITE8TO64BE( name, read8, write8 ) \
+DEV_READ8TO64BE(name,read8) \
+DEV_WRITE8TO64BE(name,write8)
+
+
+/*************************************
+ * 8->64le, 1:1 mapping
+ ************************************/
+
+#define DEV_READ8TO64LE( name, read8 ) \
+DEV_READ_TEMPLATE( 64, name, read8, read64le_with_read8_device_handler )
+
+
+#define DEV_WRITE8TO64LE( name, write8 ) \
+DEV_WRITE_TEMPLATE( 64, name, write8, write64le_with_write8_device_handler )
+
+
+#define DEV_READWRITE8TO64LE( name, read8, write8 ) \
+DEV_READ8TO64LE(name,read8) \
+DEV_WRITE8TO64LE(name,write8)
+
+
+/*************************************
+ * 16be->32be, 1:1 mapping
+ *************************************/
+
+#define DEV_READ16BETO32BE( name, read16 ) \
+DEV_READ_TEMPLATE( 32, name, read16, read32be_with_16be_device_handler )
+
+
+#define DEV_WRITE16BETO32BE( name, write16 ) \
+DEV_WRITE_TEMPLATE( 32, name, write16, write32be_with_16be_device_handler )
+
+
+#define DEV_READWRITE16BETO32BE( name, read16, write16 ) \
+DEV_READ16BETO32BE(name,read16) \
+DEV_WRITE16BETO32BE(name,write16)
+
+
+/*************************************
+ * 16le->32be, 1:1 mapping
+ *************************************/
+
+#define DEV_READ16LETO32BE( name, read16 ) \
+DEV_READ_TEMPLATE( 32, name, read16, read32be_with_16le_device_handler )
+
+
+#define DEV_WRITE16LETO32BE( name, write16 ) \
+DEV_WRITE_TEMPLATE( 32, name, write16, write32be_with_16le_device_handler )
+
+
+#define DEV_READWRITE16LETO32BE( name, read16, write16 ) \
+DEV_READ16LETO32BE(name,read16) \
+DEV_WRITE16LETO32BE(name,write16)
+
+
+/*************************************
+ * 16be->32le, 1:1 mapping
+ *************************************/
+
+#define DEV_READ16BETO32LE( name, read16 ) \
+DEV_READ_TEMPLATE( 32, name, read16, read32le_with_16be_device_handler )
+
+
+#define DEV_WRITE16BETO32LE( name, write16 ) \
+DEV_WRITE_TEMPLATE( 32, name, write16, write32le_with_16be_device_handler )
+
+
+#define DEV_READWRITE16BETO32LE( name, read16, write16 ) \
+DEV_READ16BETO32LE(name,read16) \
+DEV_WRITE16BETO32LE(name,write16)
+
+
+/*************************************
+ * 16le->32le, 1:1 mapping
+ *************************************/
+
+#define DEV_READ16LETO32LE( name, read16 ) \
+DEV_READ_TEMPLATE( 32, name, read16, read32le_with_16le_device_handler )
+
+
+#define DEV_WRITE16LETO32LE( name, write16 ) \
+DEV_WRITE_TEMPLATE( 32, name, write16, write32le_with_16le_device_handler )
+
+
+#define DEV_READWRITE16LETO32LE( name, read16, write16 ) \
+DEV_READ16LETO32LE(name,read16) \
+DEV_WRITE16LETO32LE(name,write16)
+
+
+/*************************************
+ * 16be->32be, MSW mapping
+ *************************************/
+
+#define DEV_READ16BETO32BE_MSW( name, read16 ) \
+DEV_READ_TEMPLATE_COND( 32, name, read16, read32be_with_16be_device_handler, ACCESSING_BITS_16_31 )
+
+
+#define DEV_WRITE16BETO32BE_MSW( name, write16 ) \
+DEV_WRITE_TEMPLATE_COND( 32, name, write16, write32be_with_16be_device_handler, ACCESSING_BITS_16_31 )
+
+
+#define DEV_READWRITE16BETO32BE_MSW( name, read16, write16 ) \
+DEV_READ16BETO32BE_MSW(name,read16) \
+DEV_WRITE16BETO32BE_MSW(name,write16)
+
+
+/*************************************
+ * 16le->32be, MSW mapping
+ *************************************/
+
+#define DEV_READ16LETO32BE_MSW( name, read16 ) \
+DEV_READ_TEMPLATE_COND( 32, name, read16, read32be_with_16le_device_handler, ACCESSING_BITS_16_31 )
+
+
+#define DEV_WRITE16LETO32BE_MSW( name, write16 ) \
+DEV_WRITE_TEMPLATE_COND( 32, name, write16, write32be_with_16le_device_handler, ACCESSING_BITS_16_31 )
+
+
+#define DEV_READWRITE16LETO32BE_MSW( name, read16, write16 ) \
+DEV_READ16LETO32BE_MSW(name,read16) \
+DEV_WRITE16LETO32BE_MSW(name,write16)
+
+
+/*************************************
+ * 16be->32le, MSW mapping
+ *************************************/
+
+#define DEV_READ16BETO32LE_MSW( name, read16 ) \
+DEV_READ_TEMPLATE_COND( 32, name, read16, read32le_with_16be_device_handler, ACCESSING_BITS_16_31 )
+
+
+#define DEV_WRITE16BETO32LE_MSW( name, write16 ) \
+DEV_WRITE_TEMPLATE_COND( 32, name, write16, write32le_with_16be_device_handler, ACCESSING_BITS_16_31 )
+
+
+#define DEV_READWRITE16BETO32LE_MSW( name, read16, write16 ) \
+DEV_READ16BETO32LE_MSW(name,read16) \
+DEV_WRITE16BETO32LE_MSW(name,write16)
+
+
+/*************************************
+ * 16le->32le, MSW mapping
+ *************************************/
+
+#define DEV_READ16LETO32LE_MSW( name, read16 ) \
+DEV_READ_TEMPLATE_COND( 32, name, read16, read32le_with_16le_device_handler, ACCESSING_BITS_16_31 )
+
+
+#define DEV_WRITE16LETO32LE_MSW( name, write16 ) \
+DEV_WRITE_TEMPLATE_COND( 32, name, write16, write32le_with_16le_device_handler, ACCESSING_BITS_16_31 )
+
+
+#define DEV_READWRITE16LETO32LE_MSW( name, read16, write16 ) \
+DEV_READ16LETO32LE_MSW(name,read16) \
+DEV_WRITE16LETO32LE_MSW(name,write16)
+
+/*************************************
+ * 16be->32be, LSW mapping
+ *************************************/
+
+#define DEV_READ16BETO32BE_LSW( name, read16 ) \
+DEV_READ_TEMPLATE_COND( 32, name, read16, read32be_with_16be_device_handler, ACCESSING_BITS_0_15 )
+
+
+#define DEV_WRITE16BETO32BE_LSW( name, write16 ) \
+DEV_WRITE_TEMPLATE_COND( 32, name, write16, write32be_with_16be_device_handler, ACCESSING_BITS_0_15 )
+
+
+#define DEV_READWRITE16BETO32BE_LSW( name, read16, write16 ) \
+DEV_READ16BETO32BE_LSW(name,read16) \
+DEV_WRITE16BETO32BE_LSW(name,write16)
+
+
+/*************************************
+ * 16le->32be, LSW mapping
+ *************************************/
+
+#define DEV_READ16LETO32BE_LSW( name, read16 ) \
+DEV_READ_TEMPLATE_COND( 32, name, read16, read32be_with_16le_device_handler, ACCESSING_BITS_0_15 )
+
+
+#define DEV_WRITE16LETO32BE_LSW( name, write16 ) \
+DEV_WRITE_TEMPLATE_COND( 32, name, write16, write32be_with_16le_device_handler, ACCESSING_BITS_0_15 )
+
+
+#define DEV_READWRITE16LETO32BE_LSW( name, read16, write16 ) \
+DEV_READ16LETO32BE_LSW(name,read16) \
+DEV_WRITE16LETO32BE_LSW(name,write16)
+
+
+/*************************************
+ * 16be->32le, LSW mapping
+ *************************************/
+
+#define DEV_READ16BETO32LE_LSW( name, read16 ) \
+DEV_READ_TEMPLATE_COND( 32, name, read16, read32le_with_16be_device_handler, ACCESSING_BITS_0_15 )
+
+
+#define DEV_WRITE16BETO32LE_LSW( name, write16 ) \
+DEV_WRITE_TEMPLATE_COND( 32, name, write16, write32le_with_16be_device_handler, ACCESSING_BITS_0_15 )
+
+
+#define DEV_READWRITE16BETO32LE_LSW( name, read16, write16 ) \
+DEV_READ16BETO32LE_LSW(name,read16) \
+DEV_WRITE16BETO32LE_LSW(name,write16)
+
+
+/*************************************
+ * 16le->32le, LSW mapping
+ *************************************/
+
+#define DEV_READ16LETO32LE_LSW( name, read16 ) \
+DEV_READ_TEMPLATE_COND( 32, name, read16, read32le_with_16le_device_handler, ACCESSING_BITS_0_15 )
+
+
+#define DEV_WRITE16LETO32LE_LSW( name, write16 ) \
+DEV_WRITE_TEMPLATE_COND( 32, name, write16, write32le_with_16le_device_handler, ACCESSING_BITS_0_15 )
+
+
+#define DEV_READWRITE16LETO32LE_LSW( name, read16, write16 ) \
+DEV_READ16LETO32LE_LSW(name,read16) \
+DEV_WRITE16LETO32LE_LSW(name,write16)
+
diff --git a/trunk/src/emu/devcpu.c b/trunk/src/emu/devcpu.c
new file mode 100644
index 00000000000..0442b4746f5
--- /dev/null
+++ b/trunk/src/emu/devcpu.c
@@ -0,0 +1,484 @@
+/***************************************************************************
+
+ devcpu.c
+
+ CPU device 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"
+#include "debugger.h"
+#include <ctype.h>
+
+
+//**************************************************************************
+// CPU RUNNING DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// cpu_device - constructor
+//-------------------------------------------------
+
+cpu_device::cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, type, name, tag, owner, clock),
+ device_execute_interface(mconfig, *this),
+ device_memory_interface(mconfig, *this),
+ device_state_interface(mconfig, *this),
+ device_disasm_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// cpu_device - destructor
+//-------------------------------------------------
+
+cpu_device::~cpu_device()
+{
+}
+
+
+//-------------------------------------------------
+// legacy_cpu_device - constructor
+//-------------------------------------------------
+
+legacy_cpu_device::legacy_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, cpu_get_info_func get_info)
+ : cpu_device(mconfig, type, "CPU", tag, owner, clock),
+ m_get_info(get_info),
+ m_token(NULL),
+ m_set_info(reinterpret_cast<cpu_set_info_func>(get_legacy_fct(CPUINFO_FCT_SET_INFO))),
+ m_execute(reinterpret_cast<cpu_execute_func>(get_legacy_fct(CPUINFO_FCT_EXECUTE))),
+ m_burn(reinterpret_cast<cpu_burn_func>(get_legacy_fct(CPUINFO_FCT_BURN))),
+ m_translate(reinterpret_cast<cpu_translate_func>(get_legacy_fct(CPUINFO_FCT_TRANSLATE))),
+ m_read(reinterpret_cast<cpu_read_func>(get_legacy_fct(CPUINFO_FCT_READ))),
+ m_write(reinterpret_cast<cpu_write_func>(get_legacy_fct(CPUINFO_FCT_WRITE))),
+ m_readop(reinterpret_cast<cpu_readop_func>(get_legacy_fct(CPUINFO_FCT_READOP))),
+ m_disassemble(reinterpret_cast<cpu_disassemble_func>(get_legacy_fct(CPUINFO_FCT_DISASSEMBLE))),
+ m_state_import(reinterpret_cast<cpu_state_io_func>(get_legacy_fct(CPUINFO_FCT_IMPORT_STATE))),
+ m_state_export(reinterpret_cast<cpu_state_io_func>(get_legacy_fct(CPUINFO_FCT_EXPORT_STATE))),
+ m_string_export(reinterpret_cast<cpu_string_io_func>(get_legacy_fct(CPUINFO_FCT_EXPORT_STRING))),
+ m_exit(reinterpret_cast<cpu_exit_func>(get_legacy_fct(CPUINFO_FCT_EXIT))),
+ m_using_legacy_state(false),
+ m_inited(false)
+{
+ // build up our address spaces; legacy devices don't have logical spaces
+ memset(m_space_config, 0, sizeof(m_space_config));
+ for (address_spacenum spacenum = AS_0; spacenum < ARRAY_LENGTH(m_space_config); spacenum++)
+ {
+ m_space_config[spacenum].m_name = (spacenum == 1) ? "data" : (spacenum == 2) ? "i/o" : "program";
+ m_space_config[spacenum].m_endianness = static_cast<endianness_t>(get_legacy_int(DEVINFO_INT_ENDIANNESS));
+ m_space_config[spacenum].m_databus_width = get_legacy_int(DEVINFO_INT_DATABUS_WIDTH + spacenum);
+ m_space_config[spacenum].m_addrbus_width = get_legacy_int(DEVINFO_INT_ADDRBUS_WIDTH + spacenum);
+ m_space_config[spacenum].m_addrbus_shift = get_legacy_int(DEVINFO_INT_ADDRBUS_SHIFT + spacenum);
+ m_space_config[spacenum].m_logaddr_width = get_legacy_int(CPUINFO_INT_LOGADDR_WIDTH + spacenum);
+ if (m_space_config[spacenum].m_logaddr_width == 0)
+ m_space_config[spacenum].m_logaddr_width = m_space_config[spacenum].m_addrbus_width;
+ m_space_config[spacenum].m_page_shift = get_legacy_int(CPUINFO_INT_PAGE_SHIFT + spacenum);
+ m_space_config[spacenum].m_internal_map = reinterpret_cast<address_map_constructor>(get_legacy_fct(DEVINFO_PTR_INTERNAL_MEMORY_MAP + spacenum));
+ m_space_config[spacenum].m_default_map = reinterpret_cast<address_map_constructor>(get_legacy_fct(DEVINFO_PTR_DEFAULT_MEMORY_MAP + spacenum));
+ }
+
+ // set the real name
+ m_name = get_legacy_string(DEVINFO_STR_NAME);
+ m_shortname = get_legacy_string(DEVINFO_STR_SHORTNAME);
+ m_searchpath = m_shortname;
+
+ memset(&m_partial_frame_period, 0, sizeof(m_partial_frame_period));
+
+ int tokenbytes = get_legacy_int(CPUINFO_INT_CONTEXT_SIZE);
+ if (tokenbytes == 0)
+ throw emu_fatalerror("Device %s specifies a 0 context size!\n", tag);
+
+ // allocate memory for the token
+ m_token = global_alloc_array_clear(UINT8, tokenbytes);
+}
+
+
+//-------------------------------------------------
+// legacy_cpu_device - destructor
+//-------------------------------------------------
+
+legacy_cpu_device::~legacy_cpu_device()
+{
+ global_free(m_token);
+}
+
+
+//-------------------------------------------------
+// device_start - start up the device
+//-------------------------------------------------
+
+void legacy_cpu_device::device_start()
+{
+ // standard init
+ cpu_init_func init = reinterpret_cast<cpu_init_func>(get_legacy_fct(CPUINFO_FCT_INIT));
+ (*init)(this, static_standard_irq_callback);
+ m_inited = true;
+
+ // fetch information about the CPU states
+ if (m_state_list.count() == 0)
+ {
+ m_using_legacy_state = true;
+ for (int index = 0; index < MAX_REGS; index++)
+ {
+ const char *string = get_legacy_string(CPUINFO_STR_REGISTER + index);
+ if (strchr(string, ':') != NULL)
+ {
+ astring tempstr(string);
+ bool noshow = (tempstr.chr(0, '~') == 0);
+ if (noshow)
+ tempstr.substr(1, -1);
+
+ int colon = tempstr.chr(0, ':');
+ int length = tempstr.len() - colon - 1;
+
+ tempstr.substr(0, colon).trimspace();
+
+ astring formatstr;
+ formatstr.printf("%%%ds", length);
+ device_state_entry &entry = state_add(index, tempstr, m_state_io).callimport().callexport().formatstr(formatstr);
+ if (noshow)
+ entry.noshow();
+ }
+ }
+ state_add(STATE_GENPC, "curpc", m_state_io).callimport().callexport().formatstr("%8s").noshow();
+ state_add(STATE_GENPCBASE, "curpcbase", m_state_io).callimport().callexport().formatstr("%8s").noshow();
+
+ const char *string = get_legacy_string(CPUINFO_STR_FLAGS);
+ if (string != NULL && string[0] != 0)
+ {
+ astring flagstr;
+ flagstr.printf("%%%ds", strlen(string));
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_state_io).callimport().callexport().formatstr(flagstr).noshow();
+ }
+ }
+
+ // get our icount pointer
+ m_icountptr = reinterpret_cast<int *>(get_legacy_ptr(CPUINFO_PTR_INSTRUCTION_COUNTER));
+ assert(m_icountptr != 0);
+ *m_icountptr = 0;
+}
+
+
+//-------------------------------------------------
+// device_reset - reset up the device
+//-------------------------------------------------
+
+void legacy_cpu_device::device_reset()
+{
+ cpu_reset_func reset = reinterpret_cast<cpu_reset_func>(get_legacy_fct(CPUINFO_FCT_RESET));
+ if (reset != NULL)
+ (*reset)(this);
+}
+
+
+//-------------------------------------------------
+// device_stop - clean up before the machine goes
+// away
+//-------------------------------------------------
+
+void legacy_cpu_device::device_stop()
+{
+ // call the CPU's exit function if present
+ if (m_inited && m_exit != NULL)
+ (*m_exit)(this);
+}
+
+
+//-------------------------------------------------
+// execute_clocks_to_cycles - convert the raw
+// clock into cycles per second
+//-------------------------------------------------
+
+UINT64 legacy_cpu_device::execute_clocks_to_cycles(UINT64 clocks) const
+{
+ UINT32 multiplier = get_legacy_int(CPUINFO_INT_CLOCK_MULTIPLIER);
+ UINT32 divider = get_legacy_int(CPUINFO_INT_CLOCK_DIVIDER);
+
+ if (multiplier == 0) multiplier = 1;
+ if (divider == 0) divider = 1;
+
+ return (clocks * multiplier + divider - 1) / divider;
+}
+
+
+//-------------------------------------------------
+// execute_cycles_to_clocks - convert a cycle
+// count back to raw clocks
+//-------------------------------------------------
+
+UINT64 legacy_cpu_device::execute_cycles_to_clocks(UINT64 cycles) const
+{
+ UINT32 multiplier = get_legacy_int(CPUINFO_INT_CLOCK_MULTIPLIER);
+ UINT32 divider = get_legacy_int(CPUINFO_INT_CLOCK_DIVIDER);
+
+ if (multiplier == 0) multiplier = 1;
+ if (divider == 0) divider = 1;
+
+ return (cycles * divider + multiplier - 1) / multiplier;
+}
+
+
+//-------------------------------------------------
+// execute_run - execute for the provided number
+// of cycles
+//-------------------------------------------------
+
+void legacy_cpu_device::execute_run()
+{
+ (*m_execute)(this);
+}
+
+
+//-------------------------------------------------
+// execute_burn - burn the requested number of cycles
+//-------------------------------------------------
+
+void legacy_cpu_device::execute_burn(INT32 cycles)
+{
+ if (m_burn != NULL)
+ (*m_burn)(this, cycles);
+}
+
+
+//-------------------------------------------------
+// memory_translate - perform address translation
+// on the provided address
+//-------------------------------------------------
+
+bool legacy_cpu_device::memory_translate(address_spacenum spacenum, int intention, offs_t &address)
+{
+ if (m_translate != NULL)
+ return (*m_translate)(this, spacenum, intention, &address) ? true : false;
+ return true;
+}
+
+
+//-------------------------------------------------
+// memory_read - read device memory, allowing for
+// device specific overrides
+//-------------------------------------------------
+
+bool legacy_cpu_device::memory_read(address_spacenum spacenum, offs_t offset, int size, UINT64 &value)
+{
+ if (m_read != NULL)
+ return (*m_read)(this, spacenum, offset, size, &value) ? true : false;
+ return false;
+}
+
+
+//-------------------------------------------------
+// memory_write - write device memory, allowing
+// for device specific overrides
+//-------------------------------------------------
+
+bool legacy_cpu_device::memory_write(address_spacenum spacenum, offs_t offset, int size, UINT64 value)
+{
+ if (m_write != NULL)
+ return (*m_write)(this, spacenum, offset, size, value) ? true : false;
+ return false;
+}
+
+
+//-------------------------------------------------
+// memory_read - read device opcode memory,
+// allowing for device specific overrides
+//-------------------------------------------------
+
+bool legacy_cpu_device::memory_readop(offs_t offset, int size, UINT64 &value)
+{
+ if (m_readop != NULL)
+ return (*m_readop)(this, offset, size, &value) ? true : false;
+ return false;
+}
+
+
+//-------------------------------------------------
+// debug_setup - set up any device-specific
+// debugging commands or state
+//-------------------------------------------------
+
+void legacy_cpu_device::device_debug_setup()
+{
+ cpu_debug_init_func init = reinterpret_cast<cpu_debug_init_func>(get_legacy_fct(CPUINFO_FCT_DEBUG_INIT));
+ if (init != NULL)
+ (*init)(this);
+}
+
+
+//-------------------------------------------------
+// disassemble - disassemble the provided opcode
+// data to a buffer
+//-------------------------------------------------
+
+offs_t legacy_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+{
+ // if we have a callback, just use that
+ if (m_disassemble != NULL)
+ return (*m_disassemble)(this, buffer, pc, oprom, opram, options);
+
+ // if not, just output vanilla bytes
+ int width = min_opcode_bytes();
+ switch (width)
+ {
+ case 1:
+ default:
+ sprintf(buffer, "$%02X", *(UINT8 *)oprom);
+ break;
+
+ case 2:
+ sprintf(buffer, "$%04X", *(UINT16 *)oprom);
+ break;
+
+ case 4:
+ sprintf(buffer, "$%08X", *(UINT32 *)oprom);
+ break;
+
+ case 8:
+ sprintf(buffer, "$%08X%08X", (UINT32)(*(UINT64 *)oprom >> 32), (UINT32)(*(UINT64 *)oprom >> 0));
+ break;
+ }
+ return width;
+}
+
+
+//-------------------------------------------------
+// get_legacy_int - return a legacy integer value
+//-------------------------------------------------
+
+INT64 legacy_cpu_device::get_legacy_int(UINT32 state) const
+{
+ cpuinfo info = { 0 };
+ (*m_get_info)(const_cast<legacy_cpu_device *>(this), state, &info);
+ return info.i;
+}
+
+
+//-------------------------------------------------
+// get_legacy_ptr - return a legacy pointer value
+//-------------------------------------------------
+
+void *legacy_cpu_device::get_legacy_ptr(UINT32 state) const
+{
+ cpuinfo info = { 0 };
+ (*m_get_info)(const_cast<legacy_cpu_device *>(this), state, &info);
+ return info.p;
+}
+
+
+//-------------------------------------------------
+// get_legacy_fct - return a legacy function value
+//-------------------------------------------------
+
+genf *legacy_cpu_device::get_legacy_fct(UINT32 state) const
+{
+ cpuinfo info = { 0 };
+ (*m_get_info)(const_cast<legacy_cpu_device *>(this), state, &info);
+ return info.f;
+}
+
+
+//-------------------------------------------------
+// get_legacy_string - return a legacy
+// string value
+//-------------------------------------------------
+
+const char *legacy_cpu_device::get_legacy_string(UINT32 state) const
+{
+ cpuinfo info;
+ info.s = get_temp_string_buffer();
+ (*m_get_info)(const_cast<legacy_cpu_device *>(this), state, &info);
+ return info.s;
+}
+
+
+//-------------------------------------------------
+// set_legacy_int - call the get info function
+// to set an integer value
+//-------------------------------------------------
+
+void legacy_cpu_device::set_legacy_int(UINT32 state, INT64 value)
+{
+ cpuinfo info = { 0 };
+ info.i = value;
+ (*m_set_info)(this, state, &info);
+}
+
+
+
+void legacy_cpu_device::state_import(const device_state_entry &entry)
+{
+ if (m_using_legacy_state)
+ {
+ if (entry.index() == STATE_GENFLAGS)
+ ; // do nothing
+ else
+ set_legacy_int(CPUINFO_INT_REGISTER + entry.index(), m_state_io);
+ }
+ else if (m_state_import != NULL)
+ (*m_state_import)(this, entry);
+}
+
+
+void legacy_cpu_device::state_export(const device_state_entry &entry)
+{
+ if (m_using_legacy_state)
+ {
+ if (entry.index() == STATE_GENFLAGS)
+ {
+ const char *temp = get_legacy_string(CPUINFO_STR_FLAGS);
+ m_state_io = 0;
+ while (*temp != 0)
+ m_state_io = ((m_state_io << 5) | (m_state_io >> (64-5))) ^ *temp++;
+ }
+ else
+ m_state_io = get_legacy_int(CPUINFO_INT_REGISTER + entry.index());
+ }
+ else if (m_state_export != NULL)
+ (*m_state_export)(this, entry);
+}
+
+
+void legacy_cpu_device::state_string_export(const device_state_entry &entry, astring &string)
+{
+ if (m_using_legacy_state)
+ {
+ if (entry.index() == STATE_GENFLAGS)
+ string.cpy(get_legacy_string(CPUINFO_STR_FLAGS));
+ else
+ string.cpy(strchr(get_legacy_string(CPUINFO_STR_REGISTER + entry.index()), ':') + 1);
+ }
+ else if (m_string_export != NULL)
+ (*m_string_export)(this, entry, string);
+}
diff --git a/trunk/src/emu/devcpu.h b/trunk/src/emu/devcpu.h
new file mode 100644
index 00000000000..f77ce912609
--- /dev/null
+++ b/trunk/src/emu/devcpu.h
@@ -0,0 +1,437 @@
+/***************************************************************************
+
+ devcpu.h
+
+ CPU device 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 __DEVCPU_H__
+#define __DEVCPU_H__
+
+#include "devlegcy.h"
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// CPU information constants
+const int MAX_REGS = 256;
+enum
+{
+ // --- the following bits of info are returned as 64-bit signed integers ---
+ CPUINFO_INT_FIRST = DEVINFO_INT_FIRST,
+
+ // CPU-specific additionsg
+ CPUINFO_INT_CONTEXT_SIZE = DEVINFO_INT_CLASS_SPECIFIC, // R/O: size of CPU context in bytes
+ CPUINFO_INT_INPUT_LINES, // R/O: number of input lines
+ CPUINFO_INT_DEFAULT_IRQ_VECTOR, // R/O: default IRQ vector
+ CPUINFO_INT_CLOCK_MULTIPLIER, // R/O: internal clock multiplier
+ CPUINFO_INT_CLOCK_DIVIDER, // R/O: internal clock divider
+ CPUINFO_INT_MIN_INSTRUCTION_BYTES, // R/O: minimum bytes per instruction
+ CPUINFO_INT_MAX_INSTRUCTION_BYTES, // R/O: maximum bytes per instruction
+ CPUINFO_INT_MIN_CYCLES, // R/O: minimum cycles for a single instruction
+ CPUINFO_INT_MAX_CYCLES, // R/O: maximum cycles for a single instruction
+
+ CPUINFO_INT_LOGADDR_WIDTH, // R/O: address bus size for logical accesses in each space (0=same as physical)
+ CPUINFO_INT_LOGADDR_WIDTH_PROGRAM = CPUINFO_INT_LOGADDR_WIDTH + AS_PROGRAM,
+ CPUINFO_INT_LOGADDR_WIDTH_DATA = CPUINFO_INT_LOGADDR_WIDTH + AS_DATA,
+ CPUINFO_INT_LOGADDR_WIDTH_IO = CPUINFO_INT_LOGADDR_WIDTH + AS_IO,
+ CPUINFO_INT_LOGADDR_WIDTH_LAST = CPUINFO_INT_LOGADDR_WIDTH + ADDRESS_SPACES - 1,
+ CPUINFO_INT_PAGE_SHIFT, // R/O: size of a page log 2 (i.e., 12=4096), or 0 if paging not supported
+ CPUINFO_INT_PAGE_SHIFT_PROGRAM = CPUINFO_INT_PAGE_SHIFT + AS_PROGRAM,
+ CPUINFO_INT_PAGE_SHIFT_DATA = CPUINFO_INT_PAGE_SHIFT + AS_DATA,
+ CPUINFO_INT_PAGE_SHIFT_IO = CPUINFO_INT_PAGE_SHIFT + AS_IO,
+ CPUINFO_INT_PAGE_SHIFT_LAST = CPUINFO_INT_PAGE_SHIFT + ADDRESS_SPACES - 1,
+
+ CPUINFO_INT_INPUT_STATE, // R/W: states for each input line
+ CPUINFO_INT_INPUT_STATE_LAST = CPUINFO_INT_INPUT_STATE + MAX_INPUT_LINES - 1,
+ CPUINFO_INT_REGISTER = CPUINFO_INT_INPUT_STATE_LAST + 10, // R/W: values of up to MAX_REGs registers
+ CPUINFO_INT_SP = CPUINFO_INT_REGISTER + STATE_GENSP, // R/W: the current stack pointer value
+ CPUINFO_INT_PC = CPUINFO_INT_REGISTER + STATE_GENPC, // R/W: the current PC value
+ CPUINFO_INT_PREVIOUSPC = CPUINFO_INT_REGISTER + STATE_GENPCBASE, // R/W: the previous PC value
+ CPUINFO_INT_REGISTER_LAST = CPUINFO_INT_REGISTER + MAX_REGS - 1,
+
+ CPUINFO_INT_CPU_SPECIFIC = 0x08000, // R/W: CPU-specific values start here
+
+ // --- the following bits of info are returned as pointers to data or functions ---
+ CPUINFO_PTR_FIRST = DEVINFO_PTR_FIRST,
+
+ // CPU-specific additions
+ CPUINFO_PTR_INSTRUCTION_COUNTER = DEVINFO_PTR_CLASS_SPECIFIC,
+ // R/O: int *icount
+
+ CPUINFO_PTR_CPU_SPECIFIC = DEVINFO_PTR_DEVICE_SPECIFIC, // R/W: CPU-specific values start here
+
+ // --- the following bits of info are returned as pointers to functions ---
+ CPUINFO_FCT_FIRST = DEVINFO_FCT_FIRST,
+
+ // CPU-specific additions
+ CPUINFO_FCT_SET_INFO = DEVINFO_FCT_CLASS_SPECIFIC, // R/O: void (*set_info)(legacy_cpu_device *device, UINT32 state, INT64 data, void *ptr)
+ CPUINFO_FCT_INIT, // R/O: void (*init)(legacy_cpu_device *device, int index, int clock, int (*irqcallback)(legacy_cpu_device *device, int))
+ CPUINFO_FCT_RESET, // R/O: void (*reset)(legacy_cpu_device *device)
+ CPUINFO_FCT_EXIT, // R/O: void (*exit)(legacy_cpu_device *device)
+ CPUINFO_FCT_EXECUTE, // R/O: int (*execute)(legacy_cpu_device *device, int cycles)
+ CPUINFO_FCT_BURN, // R/O: void (*burn)(legacy_cpu_device *device, int cycles)
+ CPUINFO_FCT_DISASSEMBLE, // R/O: offs_t (*disassemble)(legacy_cpu_device *device, char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, int options)
+ CPUINFO_FCT_TRANSLATE, // R/O: int (*translate)(legacy_cpu_device *device, address_spacenum space, int intention, offs_t *address)
+ CPUINFO_FCT_READ, // R/O: int (*read)(legacy_cpu_device *device, address_spacenum space, UINT32 offset, int size, UINT64 *value)
+ CPUINFO_FCT_WRITE, // R/O: int (*write)(legacy_cpu_device *device, address_spacenum space, UINT32 offset, int size, UINT64 value)
+ CPUINFO_FCT_READOP, // R/O: int (*readop)(legacy_cpu_device *device, UINT32 offset, int size, UINT64 *value)
+ CPUINFO_FCT_DEBUG_INIT, // R/O: void (*debug_init)(legacy_cpu_device *device)
+ CPUINFO_FCT_IMPORT_STATE, // R/O: void (*import_state)(legacy_cpu_device *device, const device_state_entry &entry)
+ CPUINFO_FCT_EXPORT_STATE, // R/O: void (*export_state)(legacy_cpu_device *device, const device_state_entry &entry)
+ CPUINFO_FCT_IMPORT_STRING, // R/O: void (*import_string)(legacy_cpu_device *device, const device_state_entry &entry, astring &string)
+ CPUINFO_FCT_EXPORT_STRING, // R/O: void (*export_string)(legacy_cpu_device *device, const device_state_entry &entry, astring &string)
+
+ CPUINFO_FCT_CPU_SPECIFIC = DEVINFO_FCT_DEVICE_SPECIFIC, // R/W: CPU-specific values start here
+
+ // --- the following bits of info are returned as NULL-terminated strings ---
+ CPUINFO_STR_FIRST = DEVINFO_STR_FIRST,
+
+ // CPU-specific additions
+ CPUINFO_STR_REGISTER = DEVINFO_STR_CLASS_SPECIFIC + 10, // R/O: string representation of up to MAX_REGs registers
+ CPUINFO_STR_FLAGS = CPUINFO_STR_REGISTER + STATE_GENFLAGS, // R/O: string representation of the main flags value
+ CPUINFO_STR_REGISTER_LAST = CPUINFO_STR_REGISTER + MAX_REGS - 1,
+
+ CPUINFO_STR_CPU_SPECIFIC = DEVINFO_STR_DEVICE_SPECIFIC // R/W: CPU-specific values start here
+};
+
+
+
+//**************************************************************************
+// CPU DEVICE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_CPU_ADD MCFG_DEVICE_ADD
+#define MCFG_CPU_MODIFY MCFG_DEVICE_MODIFY
+#define MCFG_CPU_REPLACE MCFG_DEVICE_REPLACE
+
+#define MCFG_CPU_CLOCK MCFG_DEVICE_CLOCK
+#define MCFG_CPU_CONFIG MCFG_DEVICE_CONFIG
+
+#define MCFG_CPU_PROGRAM_MAP MCFG_DEVICE_PROGRAM_MAP
+#define MCFG_CPU_DATA_MAP MCFG_DEVICE_DATA_MAP
+#define MCFG_CPU_IO_MAP MCFG_DEVICE_IO_MAP
+
+#define MCFG_CPU_VBLANK_INT MCFG_DEVICE_VBLANK_INT
+#define MCFG_CPU_PERIODIC_INT MCFG_DEVICE_PERIODIC_INT
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+// macro for declaring the configuration and device classes of a legacy CPU device
+#define DECLARE_LEGACY_CPU_DEVICE(name, basename) \
+ \
+CPU_GET_INFO( basename ); \
+ \
+class basename##_device : public legacy_cpu_device \
+{ \
+public: \
+ basename##_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock); \
+}; \
+ \
+extern const device_type name;
+
+// macro for defining the implementation needed for configuration and device classes
+#define DEFINE_LEGACY_CPU_DEVICE(name, basename) \
+ \
+basename##_device::basename##_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock) \
+ : legacy_cpu_device(mconfig, type, tag, owner, clock, CPU_GET_INFO_NAME(basename)) \
+{ \
+} \
+ \
+const device_type name = &legacy_device_creator<basename##_device>
+
+
+
+// CPU interface functions
+#define CPU_GET_INFO_NAME(name) cpu_get_info_##name
+#define CPU_GET_INFO(name) void CPU_GET_INFO_NAME(name)(legacy_cpu_device *device, UINT32 state, cpuinfo *info)
+#define CPU_GET_INFO_CALL(name) CPU_GET_INFO_NAME(name)(device, state, info)
+
+#define CPU_SET_INFO_NAME(name) cpu_set_info_##name
+#define CPU_SET_INFO(name) void CPU_SET_INFO_NAME(name)(legacy_cpu_device *device, UINT32 state, cpuinfo *info)
+#define CPU_SET_INFO_CALL(name) CPU_SET_INFO_NAME(name)(device, state, info)
+
+#define CPU_INIT_NAME(name) cpu_init_##name
+#define CPU_INIT(name) void CPU_INIT_NAME(name)(legacy_cpu_device *device, device_irq_callback irqcallback)
+#define CPU_INIT_CALL(name) CPU_INIT_NAME(name)(device, irqcallback)
+
+#define CPU_RESET_NAME(name) cpu_reset_##name
+#define CPU_RESET(name) void CPU_RESET_NAME(name)(legacy_cpu_device *device)
+#define CPU_RESET_CALL(name) CPU_RESET_NAME(name)(device)
+
+#define CPU_EXIT_NAME(name) cpu_exit_##name
+#define CPU_EXIT(name) void CPU_EXIT_NAME(name)(legacy_cpu_device *device)
+#define CPU_EXIT_CALL(name) CPU_EXIT_NAME(name)(device)
+
+#define CPU_EXECUTE_NAME(name) cpu_execute_##name
+#define CPU_EXECUTE(name) void CPU_EXECUTE_NAME(name)(legacy_cpu_device *device)
+#define CPU_EXECUTE_CALL(name) CPU_EXECUTE_NAME(name)(device, cycles)
+
+#define CPU_BURN_NAME(name) cpu_burn_##name
+#define CPU_BURN(name) void CPU_BURN_NAME(name)(legacy_cpu_device *device, int cycles)
+#define CPU_BURN_CALL(name) CPU_BURN_NAME(name)(device, cycles)
+
+#define CPU_TRANSLATE_NAME(name) cpu_translate_##name
+#define CPU_TRANSLATE(name) int CPU_TRANSLATE_NAME(name)(legacy_cpu_device *device, address_spacenum space, int intention, offs_t *address)
+#define CPU_TRANSLATE_CALL(name) CPU_TRANSLATE_NAME(name)(device, space, intention, address)
+
+#define CPU_READ_NAME(name) cpu_read_##name
+#define CPU_READ(name) int CPU_READ_NAME(name)(legacy_cpu_device *device, address_spacenum space, UINT32 offset, int size, UINT64 *value)
+#define CPU_READ_CALL(name) CPU_READ_NAME(name)(device, space, offset, size, value)
+
+#define CPU_WRITE_NAME(name) cpu_write_##name
+#define CPU_WRITE(name) int CPU_WRITE_NAME(name)(legacy_cpu_device *device, address_spacenum space, UINT32 offset, int size, UINT64 value)
+#define CPU_WRITE_CALL(name) CPU_WRITE_NAME(name)(device, space, offset, size, value)
+
+#define CPU_READOP_NAME(name) cpu_readop_##name
+#define CPU_READOP(name) int CPU_READOP_NAME(name)(legacy_cpu_device *device, UINT32 offset, int size, UINT64 *value)
+#define CPU_READOP_CALL(name) CPU_READOP_NAME(name)(device, offset, size, value)
+
+#define CPU_DEBUG_INIT_NAME(name) cpu_debug_init_##name
+#define CPU_DEBUG_INIT(name) void CPU_DEBUG_INIT_NAME(name)(legacy_cpu_device *device)
+#define CPU_DEBUG_INIT_CALL(name) CPU_DEBUG_INIT_NAME(name)(device)
+
+#define CPU_DISASSEMBLE_NAME(name) cpu_disassemble_##name
+#define CPU_DISASSEMBLE(name) offs_t CPU_DISASSEMBLE_NAME(name)(legacy_cpu_device *device, char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, int options)
+#define CPU_DISASSEMBLE_CALL(name) CPU_DISASSEMBLE_NAME(name)(device, buffer, pc, oprom, opram, options)
+
+#define CPU_IMPORT_STATE_NAME(name) cpu_state_import_##name
+#define CPU_IMPORT_STATE(name) void CPU_IMPORT_STATE_NAME(name)(legacy_cpu_device *device, const device_state_entry &entry)
+#define CPU_IMPORT_STATE_CALL(name) CPU_IMPORT_STATE_NAME(name)(device, entry)
+
+#define CPU_EXPORT_STATE_NAME(name) cpu_state_export_##name
+#define CPU_EXPORT_STATE(name) void CPU_EXPORT_STATE_NAME(name)(legacy_cpu_device *device, const device_state_entry &entry)
+#define CPU_EXPORT_STATE_CALL(name) CPU_EXPORT_STATE_NAME(name)(device, entry)
+
+#define CPU_EXPORT_STRING_NAME(name) cpu_string_export_##name
+#define CPU_EXPORT_STRING(name) void CPU_EXPORT_STRING_NAME(name)(legacy_cpu_device *device, const device_state_entry &entry, astring &string)
+#define CPU_EXPORT_STRING_CALL(name) CPU_EXPORT_STRING_NAME(name)(device, entry, string)
+
+
+// CPU timing
+#define cpu_get_reg(cpu, _reg) device_state(cpu)->state(_reg)
+#define cpu_get_previouspc(cpu) ((offs_t)device_state(cpu)->state(STATE_GENPCBASE))
+#define cpu_get_pc(cpu) ((offs_t)device_state(cpu)->state(STATE_GENPC))
+
+#define cpu_set_reg(cpu, _reg, val) device_state(cpu)->set_state(_reg, val)
+
+#define INTERRUPT_GEN(func) void func(device_t *device)
+
+// helpers for using machine/cputag instead of cpu objects
+#define cputag_set_input_line(mach, tag, line, state) device_execute((mach).device(tag))->set_input_line(line, state)
+#define cputag_set_input_line_and_vector(mach, tag, line, state, vec) device_execute((mach).device(tag))->set_input_line_and_vector(line, state, vec)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// forward declaration of types
+union cpuinfo;
+class cpu_device;
+class legacy_cpu_device;
+
+
+// CPU interface functions
+typedef void (*cpu_get_info_func)(legacy_cpu_device *device, UINT32 state, cpuinfo *info);
+typedef void (*cpu_set_info_func)(legacy_cpu_device *device, UINT32 state, cpuinfo *info);
+typedef void (*cpu_init_func)(legacy_cpu_device *device, device_irq_callback irqcallback);
+typedef void (*cpu_reset_func)(legacy_cpu_device *device);
+typedef void (*cpu_exit_func)(legacy_cpu_device *device);
+typedef void (*cpu_execute_func)(legacy_cpu_device *device);
+typedef void (*cpu_burn_func)(legacy_cpu_device *device, int cycles);
+typedef int (*cpu_translate_func)(legacy_cpu_device *device, address_spacenum space, int intention, offs_t *address);
+typedef int (*cpu_read_func)(legacy_cpu_device *device, address_spacenum space, UINT32 offset, int size, UINT64 *value);
+typedef int (*cpu_write_func)(legacy_cpu_device *device, address_spacenum space, UINT32 offset, int size, UINT64 value);
+typedef int (*cpu_readop_func)(legacy_cpu_device *device, UINT32 offset, int size, UINT64 *value);
+typedef void (*cpu_debug_init_func)(legacy_cpu_device *device);
+typedef offs_t (*cpu_disassemble_func)(legacy_cpu_device *device, char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, int options);
+typedef void (*cpu_state_io_func)(legacy_cpu_device *device, const device_state_entry &entry);
+typedef void (*cpu_string_io_func)(legacy_cpu_device *device, const device_state_entry &entry, astring &string);
+
+
+// cpuinfo union used to pass data to/from the get_info/set_info functions
+union cpuinfo
+{
+ INT64 i; // generic integers
+ void * p; // generic pointers
+ genf * f; // generic function pointers
+ char * s; // generic strings
+
+ cpu_set_info_func setinfo; // CPUINFO_FCT_SET_INFO
+ cpu_init_func init; // CPUINFO_FCT_INIT
+ cpu_reset_func reset; // CPUINFO_FCT_RESET
+ cpu_exit_func exit; // CPUINFO_FCT_EXIT
+ cpu_execute_func execute; // CPUINFO_FCT_EXECUTE
+ cpu_burn_func burn; // CPUINFO_FCT_BURN
+ cpu_translate_func translate; // CPUINFO_FCT_TRANSLATE
+ cpu_read_func read; // CPUINFO_FCT_READ
+ cpu_write_func write; // CPUINFO_FCT_WRITE
+ cpu_readop_func readop; // CPUINFO_FCT_READOP
+ cpu_debug_init_func debug_init; // CPUINFO_FCT_DEBUG_INIT
+ cpu_disassemble_func disassemble; // CPUINFO_FCT_DISASSEMBLE
+ cpu_state_io_func import_state; // CPUINFO_FCT_IMPORT_STATE
+ cpu_state_io_func export_state; // CPUINFO_FCT_EXPORT_STATE
+ cpu_string_io_func import_string; // CPUINFO_FCT_IMPORT_STRING
+ cpu_string_io_func export_string; // CPUINFO_FCT_EXPORT_STRING
+ int * icount; // CPUINFO_PTR_INSTRUCTION_COUNTER
+ address_map_constructor internal_map8; // DEVINFO_PTR_INTERNAL_MEMORY_MAP
+ address_map_constructor internal_map16; // DEVINFO_PTR_INTERNAL_MEMORY_MAP
+ address_map_constructor internal_map32; // DEVINFO_PTR_INTERNAL_MEMORY_MAP
+ address_map_constructor internal_map64; // DEVINFO_PTR_INTERNAL_MEMORY_MAP
+ address_map_constructor default_map8; // DEVINFO_PTR_DEFAULT_MEMORY_MAP
+ address_map_constructor default_map16; // DEVINFO_PTR_DEFAULT_MEMORY_MAP
+ address_map_constructor default_map32; // DEVINFO_PTR_DEFAULT_MEMORY_MAP
+ address_map_constructor default_map64; // DEVINFO_PTR_DEFAULT_MEMORY_MAP
+};
+
+
+
+// ======================> cpu_device
+
+class cpu_device : public device_t,
+ public device_execute_interface,
+ public device_memory_interface,
+ public device_state_interface,
+ public device_disasm_interface
+{
+ friend resource_pool_object<cpu_device>::~resource_pool_object();
+
+protected:
+ // construction/destruction
+ cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
+ virtual ~cpu_device();
+};
+
+
+
+// ======================> legacy_cpu_device
+
+class legacy_cpu_device : public cpu_device
+{
+ friend resource_pool_object<legacy_cpu_device>::~resource_pool_object();
+
+protected:
+ // construction/destruction
+ legacy_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, cpu_get_info_func info);
+ virtual ~legacy_cpu_device();
+
+public:
+ void *token() const { return m_token; }
+
+protected:
+ // device-level overrides
+ virtual const rom_entry *device_rom_region() const { return reinterpret_cast<const rom_entry *>(get_legacy_ptr(DEVINFO_PTR_ROM_REGION)); }
+ virtual machine_config_constructor device_mconfig_additions() const { return reinterpret_cast<machine_config_constructor>(get_legacy_ptr(DEVINFO_PTR_MACHINE_CONFIG)); }
+ virtual ioport_constructor device_input_ports() const { return reinterpret_cast<ioport_constructor>(get_legacy_ptr(DEVINFO_PTR_INPUT_PORTS)); }
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_stop();
+ virtual void device_debug_setup();
+
+ // device_execute_interface overrides
+ virtual UINT64 execute_clocks_to_cycles(UINT64 clocks) const;
+ virtual UINT64 execute_cycles_to_clocks(UINT64 cycles) const;
+ virtual UINT32 execute_min_cycles() const { return get_legacy_int(CPUINFO_INT_MIN_CYCLES); }
+ virtual UINT32 execute_max_cycles() const { return get_legacy_int(CPUINFO_INT_MAX_CYCLES); }
+ virtual UINT32 execute_input_lines() const { return get_legacy_int(CPUINFO_INT_INPUT_LINES); }
+ virtual UINT32 execute_default_irq_vector() const { return get_legacy_int(CPUINFO_INT_DEFAULT_IRQ_VECTOR); }
+ virtual void execute_run();
+ virtual void execute_burn(INT32 cycles);
+ virtual void execute_set_input(int inputnum, int state) { set_legacy_int(CPUINFO_INT_INPUT_STATE + inputnum, state); }
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return (spacenum < ARRAY_LENGTH(m_space_config) && m_space_config[spacenum].m_addrbus_width != 0) ? &m_space_config[spacenum] : NULL; }
+ virtual bool memory_translate(address_spacenum spacenum, int intention, offs_t &address);
+ virtual bool memory_read(address_spacenum spacenum, offs_t offset, int size, UINT64 &value);
+ virtual bool memory_write(address_spacenum spacenum, offs_t offset, int size, UINT64 value);
+ virtual bool memory_readop(offs_t offset, int size, UINT64 &value);
+
+ // 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 { return get_legacy_int(CPUINFO_INT_MIN_INSTRUCTION_BYTES); }
+ virtual UINT32 disasm_max_opcode_bytes() const { return get_legacy_int(CPUINFO_INT_MAX_INSTRUCTION_BYTES); }
+ virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
+
+ // helpers to access data via the legacy get_info functions
+ INT64 get_legacy_int(UINT32 state) const;
+ void *get_legacy_ptr(UINT32 state) const;
+ genf *get_legacy_fct(UINT32 state) const;
+ const char *get_legacy_string(UINT32 state) const;
+ void set_legacy_int(UINT32 state, INT64 value);
+
+protected:
+ // internal state
+ cpu_get_info_func m_get_info;
+ address_space_config m_space_config[3]; // array of address space configs
+ void * m_token; // pointer to our state
+
+ cpu_set_info_func m_set_info; // extracted legacy function pointers
+ cpu_execute_func m_execute; //
+ cpu_burn_func m_burn; //
+ cpu_translate_func m_translate; //
+ cpu_read_func m_read; //
+ cpu_write_func m_write; //
+ cpu_readop_func m_readop; //
+ cpu_disassemble_func m_disassemble; //
+ cpu_state_io_func m_state_import; //
+ cpu_state_io_func m_state_export; //
+ cpu_string_io_func m_string_export; //
+ cpu_exit_func m_exit; //
+
+ UINT64 m_state_io; // temporary buffer for state I/O
+ bool m_using_legacy_state; // true if we are using the old-style state access
+ bool m_inited;
+};
+
+
+#endif /* __CPUINTRF_H__ */
diff --git a/trunk/src/emu/device.c b/trunk/src/emu/device.c
new file mode 100644
index 00000000000..cf974663892
--- /dev/null
+++ b/trunk/src/emu/device.c
@@ -0,0 +1,1143 @@
+/***************************************************************************
+
+ device.c
+
+ Device interface 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 "debug/debugcpu.h"
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+#define TEMP_STRING_POOL_ENTRIES 16
+#define MAX_STRING_LENGTH 256
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+static char temp_string_pool[TEMP_STRING_POOL_ENTRIES][MAX_STRING_LENGTH];
+static int temp_string_pool_index;
+
+
+
+//**************************************************************************
+// INLINE FUNCTIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// get_temp_string_buffer - return a pointer to
+// a temporary string buffer
+//-------------------------------------------------
+
+char *get_temp_string_buffer(void)
+{
+ char *string = &temp_string_pool[temp_string_pool_index++ % TEMP_STRING_POOL_ENTRIES][0];
+ string[0] = 0;
+ return string;
+}
+
+
+resource_pool &machine_get_pool(running_machine &machine)
+{
+ // temporary to get around include dependencies, until CPUs
+ // get a proper device class
+ return machine.respool();
+}
+
+
+
+//**************************************************************************
+// DEVICE LIST MANAGEMENT
+//**************************************************************************
+
+//-------------------------------------------------
+// device_list - device list constructor
+//-------------------------------------------------
+
+device_list::device_list(resource_pool &pool)
+ : tagged_list<device_t>(pool)
+{
+}
+
+
+//-------------------------------------------------
+// set_machine_all - once the machine is created,
+// tell every device about it
+//-------------------------------------------------
+
+void device_list::set_machine_all(running_machine &machine)
+{
+ // add exit and reset callbacks
+ m_machine = &machine;
+
+ // iterate over devices and set their machines as well
+ for (device_t *device = first(); device != NULL; device = device->next())
+ device->set_machine(machine);
+}
+
+
+//-------------------------------------------------
+// start_all - start all the devices in the
+// list
+//-------------------------------------------------
+
+void device_list::start_all()
+{
+ // add exit and reset callbacks
+ machine().add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(FUNC(device_list::reset_all), this));
+ machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(device_list::exit), this));
+
+ // add pre-save and post-load callbacks
+ machine().save().register_presave(save_prepost_delegate(FUNC(device_list::presave_all), this));
+ machine().save().register_postload(save_prepost_delegate(FUNC(device_list::postload_all), this));
+
+ // start_new_devices does all the necessary work
+ start_new_devices();
+}
+
+
+//-------------------------------------------------
+// start_new_devices - start any unstarted devices
+//-------------------------------------------------
+
+void device_list::start_new_devices()
+{
+ assert(m_machine != NULL);
+
+ // iterate through the devices
+ device_t *nextdevice;
+ for (device_t *device = first(); device != NULL; device = nextdevice)
+ {
+ // see if this device is what we want
+ nextdevice = device->next();
+ if (!device->started())
+ {
+ // attempt to start the device, catching any expected exceptions
+ try
+ {
+ // if the device doesn't have a machine yet, set it first
+ if (device->m_machine == NULL)
+ device->set_machine(machine());
+
+ // now start the device
+ mame_printf_verbose("Starting %s '%s'\n", device->name(), device->tag());
+ device->start();
+ }
+
+ // handle missing dependencies by moving the device to the end
+ catch (device_missing_dependencies &)
+ {
+ // if we're the end, fail
+ mame_printf_verbose(" (missing dependencies; rescheduling)\n");
+ if (nextdevice == NULL)
+ throw emu_fatalerror("Circular dependency in device startup; unable to start %s '%s'\n", device->name(), device->tag());
+ detach(*device);
+ append(device->tag(), *device);
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// reset_all - reset all devices in the list
+//-------------------------------------------------
+
+void device_list::reset_all()
+{
+ // iterate over devices and reset them
+ for (device_t *device = first(); device != NULL; device = device->next())
+ device->reset();
+}
+
+
+//-------------------------------------------------
+// stop_all - stop all the devices in the
+// list
+//-------------------------------------------------
+
+void device_list::stop_all()
+{
+ // iterate over devices and stop them
+ for (device_t *device = first(); device != NULL; device = device->next())
+ device->stop();
+
+ // leave with no machine
+ m_machine = NULL;
+}
+
+
+//-------------------------------------------------
+// first - return the first device of the given
+// type
+//-------------------------------------------------
+
+device_t *device_list::first(device_type type) const
+{
+ device_t *cur;
+ for (cur = super::first(); cur != NULL && cur->type() != type; cur = cur->next()) ;
+ return cur;
+}
+
+
+//-------------------------------------------------
+// count - count the number of devices of the
+// given type
+//-------------------------------------------------
+
+int device_list::count(device_type type) const
+{
+ int num = 0;
+ for (const device_t *curdev = first(type); curdev != NULL; curdev = curdev->typenext()) num++;
+ return num;
+}
+
+
+//-------------------------------------------------
+// indexof - return the index of the given device
+// among its kind
+//-------------------------------------------------
+
+int device_list::indexof(device_type type, device_t &object) const
+{
+ int num = 0;
+ for (device_t *cur = first(type); cur != NULL; cur = cur->typenext(), num++)
+ if (cur == &object) return num;
+ return -1;
+}
+
+
+//-------------------------------------------------
+// indexof - return the index of the given device
+// among its kind
+//-------------------------------------------------
+
+int device_list::indexof(device_type type, const char *tag) const
+{
+ device_t *object = find(tag);
+ return (object != NULL && object->type() == type) ? indexof(type, *object) : -1;
+}
+
+
+//-------------------------------------------------
+// find - find a device by type + index
+//-------------------------------------------------
+
+device_t *device_list::find(device_type type, int index) const
+{
+ for (device_t *cur = first(type); cur != NULL; cur = cur->typenext())
+ if (index-- == 0) return cur;
+ return NULL;
+}
+
+
+//-------------------------------------------------
+// static_exit - tear down all the devices
+//-------------------------------------------------
+
+void device_list::exit()
+{
+ // first let the debugger save comments
+ if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ debug_comment_save(machine());
+
+ // stop all the devices before we go away
+ stop_all();
+
+ // then nuke the devices
+ reset();
+}
+
+
+//-------------------------------------------------
+// presave_all - tell all the devices we are
+// about to save
+//-------------------------------------------------
+
+void device_list::presave_all()
+{
+ for (device_t *device = first(); device != NULL; device = device->next())
+ device->pre_save();
+}
+
+
+//-------------------------------------------------
+// postload_all - tell all the devices we just
+// completed a load
+//-------------------------------------------------
+
+void device_list::postload_all()
+{
+ for (device_t *device = first(); device != NULL; device = device->next())
+ device->post_load();
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE MANAGEMENT
+//**************************************************************************
+
+//-------------------------------------------------
+// device_t - constructor for a new
+// running device; initial state is derived
+// from the provided config
+//-------------------------------------------------
+
+device_t::device_t(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock)
+ : m_debug(NULL),
+ m_execute(NULL),
+ m_memory(NULL),
+ m_state(NULL),
+ m_next(NULL),
+ m_owner(owner),
+ m_interface_list(NULL),
+ m_type(type),
+ m_configured_clock(clock),
+ m_machine_config(mconfig),
+ m_static_config(NULL),
+ m_input_defaults(NULL),
+ m_name(name),
+ m_started(false),
+ m_clock(clock),
+ m_region(NULL),
+ m_unscaled_clock(clock),
+ m_clock_scale(1.0),
+ m_attoseconds_per_clock((clock == 0) ? 0 : HZ_TO_ATTOSECONDS(clock)),
+ m_auto_finder_list(NULL),
+ m_machine(NULL),
+ m_save(NULL),
+ m_tag(tag),
+ m_config_complete(false)
+{
+ static_set_clock(*this, clock);
+}
+
+
+device_t::device_t(const machine_config &mconfig, device_type type, const char *name, const char *shortname, const char *tag, device_t *owner, UINT32 clock)
+ : m_debug(NULL),
+ m_execute(NULL),
+ m_memory(NULL),
+ m_state(NULL),
+ m_next(NULL),
+ m_owner(owner),
+ m_interface_list(NULL),
+ m_type(type),
+ m_configured_clock(clock),
+ m_machine_config(mconfig),
+ m_static_config(NULL),
+ m_input_defaults(NULL),
+ m_name(name),
+ m_shortname(shortname),
+ m_searchpath(shortname),
+ m_started(false),
+ m_clock(clock),
+ m_region(NULL),
+ m_unscaled_clock(clock),
+ m_clock_scale(1.0),
+ m_attoseconds_per_clock((clock == 0) ? 0 : HZ_TO_ATTOSECONDS(clock)),
+ m_auto_finder_list(NULL),
+ m_machine(NULL),
+ m_save(NULL),
+ m_tag(tag),
+ m_config_complete(false)
+{
+ static_set_clock(*this, clock);
+}
+
+
+//-------------------------------------------------
+// ~device_t - destructor for a device_t
+//-------------------------------------------------
+
+device_t::~device_t()
+{
+}
+
+
+//-------------------------------------------------
+// subregion - return a pointer to the region
+// info for a given region
+//-------------------------------------------------
+
+const memory_region *device_t::subregion(const char *_tag) const
+{
+ // safety first
+ if (this == NULL)
+ return NULL;
+
+ // build a fully-qualified name
+ astring tempstring;
+ return machine().region(subtag(tempstring, _tag));
+}
+
+
+//-------------------------------------------------
+// subdevice - return a pointer to the given
+// device that is owned by us
+//-------------------------------------------------
+
+device_t *device_t::subdevice(const char *_tag) const
+{
+ // safety first
+ if (this == NULL)
+ return NULL;
+
+ // build a fully-qualified name
+ astring tempstring;
+ return mconfig().devicelist().find((const char *)subtag(tempstring, _tag));
+}
+
+
+//-------------------------------------------------
+// siblingdevice - return a pointer to the given
+// device that is owned by our same owner
+//-------------------------------------------------
+
+device_t *device_t::siblingdevice(const char *_tag) const
+{
+ // safety first
+ if (this == NULL)
+ return NULL;
+
+ // build a fully-qualified name
+ astring tempstring;
+ return mconfig().devicelist().find((const char *)siblingtag(tempstring, _tag));
+}
+
+
+//-------------------------------------------------
+// static_set_clock - set/change the clock on
+// a device
+//-------------------------------------------------
+
+void device_t::static_set_clock(device_t &device, UINT32 clock)
+{
+ // derive the clock from our owner if requested
+ if ((clock & 0xff000000) == 0xff000000)
+ {
+ assert(device.m_owner != NULL);
+ clock = device.m_owner->m_configured_clock * ((clock >> 12) & 0xfff) / ((clock >> 0) & 0xfff);
+ }
+
+ device.m_clock = device.m_unscaled_clock = device.m_configured_clock = clock;
+ device.m_attoseconds_per_clock = (clock == 0) ? 0 : HZ_TO_ATTOSECONDS(clock);
+}
+
+
+//-------------------------------------------------
+// config_complete - called when the
+// configuration of a device is complete
+//-------------------------------------------------
+
+void device_t::config_complete()
+{
+ // first notify the interfaces
+ for (device_interface *intf = m_interface_list; intf != NULL; intf = intf->interface_next())
+ intf->interface_config_complete();
+
+ // then notify the device itself
+ device_config_complete();
+
+ // then mark ourselves complete
+ m_config_complete = true;
+}
+
+
+//-------------------------------------------------
+// validity_check - validate a device after the
+// configuration has been constructed
+//-------------------------------------------------
+
+bool device_t::validity_check(emu_options &options, const game_driver &driver) const
+{
+ bool error = false;
+
+ // validate via the interfaces
+ for (device_interface *intf = m_interface_list; intf != NULL; intf = intf->interface_next())
+ if (intf->interface_validity_check(options, driver))
+ error = true;
+
+ // let the device itself validate
+ if (device_validity_check(options, driver))
+ error = true;
+
+ return error;
+}
+
+
+//-------------------------------------------------
+// reset - reset a device
+//-------------------------------------------------
+
+void device_t::reset()
+{
+ // let the interfaces do their pre-work
+ for (device_interface *intf = m_interface_list; intf != NULL; intf = intf->interface_next())
+ intf->interface_pre_reset();
+
+ // reset the device
+ device_reset();
+
+ // let the interfaces do their post-work
+ for (device_interface *intf = m_interface_list; intf != NULL; intf = intf->interface_next())
+ intf->interface_post_reset();
+}
+
+
+//-------------------------------------------------
+// set_unscaled_clock - sets the given device's
+// unscaled clock
+//-------------------------------------------------
+
+void device_t::set_unscaled_clock(UINT32 clock)
+{
+ m_unscaled_clock = clock;
+ m_clock = m_unscaled_clock * m_clock_scale;
+ m_attoseconds_per_clock = HZ_TO_ATTOSECONDS(m_clock);
+ notify_clock_changed();
+}
+
+
+//-------------------------------------------------
+// set_clock_scale - sets a scale factor for the
+// device's clock
+//-------------------------------------------------
+
+void device_t::set_clock_scale(double clockscale)
+{
+ m_clock_scale = clockscale;
+ m_clock = m_unscaled_clock * m_clock_scale;
+ m_attoseconds_per_clock = HZ_TO_ATTOSECONDS(m_clock);
+ notify_clock_changed();
+}
+
+
+//-------------------------------------------------
+// clocks_to_attotime - converts a number of
+// clock ticks to an attotime
+//-------------------------------------------------
+
+attotime device_t::clocks_to_attotime(UINT64 numclocks) const
+{
+ if (numclocks < m_clock)
+ return attotime(0, numclocks * m_attoseconds_per_clock);
+ else
+ {
+ UINT32 remainder;
+ UINT32 quotient = divu_64x32_rem(numclocks, m_clock, &remainder);
+ return attotime(quotient, (UINT64)remainder * (UINT64)m_attoseconds_per_clock);
+ }
+}
+
+
+//-------------------------------------------------
+// attotime_to_clocks - converts a duration as
+// attotime to CPU clock ticks
+//-------------------------------------------------
+
+UINT64 device_t::attotime_to_clocks(attotime duration) const
+{
+ return mulu_32x32(duration.seconds, m_clock) + (UINT64)duration.attoseconds / (UINT64)m_attoseconds_per_clock;
+}
+
+
+//-------------------------------------------------
+// timer_alloc - allocate a timer for our device
+// callback
+//-------------------------------------------------
+
+emu_timer *device_t::timer_alloc(device_timer_id id, void *ptr)
+{
+ return machine().scheduler().timer_alloc(*this, id, ptr);
+}
+
+
+//-------------------------------------------------
+// timer_set - set a temporary timer that will
+// call our device callback
+//-------------------------------------------------
+
+void device_t::timer_set(attotime duration, device_timer_id id, int param, void *ptr)
+{
+ machine().scheduler().timer_set(duration, *this, id, param, ptr);
+}
+
+
+//-------------------------------------------------
+// set_machine - notify that the machine now
+// exists
+//-------------------------------------------------
+
+void device_t::set_machine(running_machine &machine)
+{
+ m_machine = &machine;
+ m_save = &machine.save();
+}
+
+
+//-------------------------------------------------
+// start - start a device
+//-------------------------------------------------
+
+void device_t::start()
+{
+ // populate the machine and the region field
+ m_region = machine().region(tag());
+
+ // find all the registered devices
+ for (auto_finder_base *autodev = m_auto_finder_list; autodev != NULL; autodev = autodev->m_next)
+ autodev->findit(*this);
+
+ // let the interfaces do their pre-work
+ for (device_interface *intf = m_interface_list; intf != NULL; intf = intf->interface_next())
+ intf->interface_pre_start();
+
+ // remember the number of state registrations
+ int state_registrations = machine().save().registration_count();
+
+ // start the device
+ device_start();
+
+ // complain if nothing was registered by the device
+ state_registrations = machine().save().registration_count() - state_registrations;
+ device_execute_interface *exec;
+ device_sound_interface *sound;
+ if (state_registrations == 0 && (interface(exec) || interface(sound)))
+ {
+ logerror("Device '%s' did not register any state to save!\n", tag());
+ if ((machine().system().flags & GAME_SUPPORTS_SAVE) != 0)
+ fatalerror("Device '%s' did not register any state to save!", tag());
+ }
+
+ // let the interfaces do their post-work
+ for (device_interface *intf = m_interface_list; intf != NULL; intf = intf->interface_next())
+ intf->interface_post_start();
+
+ // force an update of the clock
+ notify_clock_changed();
+
+ // if we're debugging, create a device_debug object
+ if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ {
+ m_debug = auto_alloc(machine(), device_debug(*this));
+ debug_setup();
+ }
+
+ // register our save states
+ save_item(NAME(m_clock));
+ save_item(NAME(m_unscaled_clock));
+ save_item(NAME(m_clock_scale));
+
+ // we're now officially started
+ m_started = true;
+}
+
+
+//-------------------------------------------------
+// stop - stop a device
+//-------------------------------------------------
+
+void device_t::stop()
+{
+ // let the interfaces do their pre-work
+ for (device_interface *intf = m_interface_list; intf != NULL; intf = intf->interface_next())
+ intf->interface_pre_stop();
+
+ // stop the device
+ device_stop();
+
+ // let the interfaces do their post-work
+ for (device_interface *intf = m_interface_list; intf != NULL; intf = intf->interface_next())
+ intf->interface_post_stop();
+
+ // free any debugging info
+ auto_free(machine(), m_debug);
+
+ // we're now officially stopped, and the machine is off-limits
+ m_started = false;
+ m_machine = NULL;
+}
+
+
+//-------------------------------------------------
+// debug_setup - set up for debugging
+//-------------------------------------------------
+
+void device_t::debug_setup()
+{
+ // notify the interface
+ for (device_interface *intf = m_interface_list; intf != NULL; intf = intf->interface_next())
+ intf->interface_debug_setup();
+
+ // notify the device
+ device_debug_setup();
+}
+
+
+//-------------------------------------------------
+// pre_save - tell the device and its interfaces
+// that we are about to save
+//-------------------------------------------------
+
+void device_t::pre_save()
+{
+ // notify the interface
+ for (device_interface *intf = m_interface_list; intf != NULL; intf = intf->interface_next())
+ intf->interface_pre_save();
+
+ // notify the device
+ device_pre_save();
+}
+
+
+//-------------------------------------------------
+// post_load - tell the device and its interfaces
+// that we just completed a load
+//-------------------------------------------------
+
+void device_t::post_load()
+{
+ // notify the interface
+ for (device_interface *intf = m_interface_list; intf != NULL; intf = intf->interface_next())
+ intf->interface_post_load();
+
+ // notify the device
+ device_post_load();
+}
+
+
+//-------------------------------------------------
+// notify_clock_changed - notify all interfaces
+// that the clock has changed
+//-------------------------------------------------
+
+void device_t::notify_clock_changed()
+{
+ // first notify interfaces
+ for (device_interface *intf = m_interface_list; intf != NULL; intf = intf->interface_next())
+ intf->interface_clock_changed();
+
+ // then notify the device
+ device_clock_changed();
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void device_t::device_config_complete()
+{
+ // do nothing by default
+}
+
+
+//-------------------------------------------------
+// device_validity_check - validate a device after
+// the configuration has been constructed
+//-------------------------------------------------
+
+bool device_t::device_validity_check(emu_options &options, const game_driver &driver) const
+{
+ // indicate no error by default
+ return false;
+}
+
+
+//-------------------------------------------------
+// rom_region - return a pointer to the implicit
+// rom region description for this device
+//-------------------------------------------------
+
+const rom_entry *device_t::device_rom_region() const
+{
+ // none by default
+ return NULL;
+}
+
+
+//-------------------------------------------------
+// machine_config - return a pointer to a machine
+// config constructor describing sub-devices for
+// this device
+//-------------------------------------------------
+
+machine_config_constructor device_t::device_mconfig_additions() const
+{
+ // none by default
+ return NULL;
+}
+
+
+
+//-------------------------------------------------
+// input_ports - return a pointer to the implicit
+// input ports description for this device
+//-------------------------------------------------
+
+ioport_constructor device_t::device_input_ports() const
+{
+ // none by default
+ return NULL;
+}
+
+
+//-------------------------------------------------
+// device_reset - actually handle resetting of
+// a device; designed to be overriden by the
+// actual device implementation
+//-------------------------------------------------
+
+void device_t::device_reset()
+{
+ // do nothing by default
+}
+
+
+//-------------------------------------------------
+// device_stop - clean up anything that needs to
+// happen before the running_machine goes away
+//-------------------------------------------------
+
+void device_t::device_stop()
+{
+ // do nothing by default
+}
+
+
+//-------------------------------------------------
+// device_pre_save - called prior to saving the
+// state, so that registered variables can be
+// properly normalized
+//-------------------------------------------------
+
+void device_t::device_pre_save()
+{
+ // do nothing by default
+}
+
+
+//-------------------------------------------------
+// device_post_load - called after the loading a
+// saved state, so that registered variables can
+// be expaneded as necessary
+//-------------------------------------------------
+
+void device_t::device_post_load()
+{
+ // do nothing by default
+}
+
+
+//-------------------------------------------------
+// device_clock_changed - called when the
+// device clock is altered in any way; designed
+// to be overridden by the actual device
+// implementation
+//-------------------------------------------------
+
+void device_t::device_clock_changed()
+{
+ // do nothing by default
+}
+
+
+//-------------------------------------------------
+// device_debug_setup - called when the debugger
+// is active to allow for device-specific setup
+//-------------------------------------------------
+
+void device_t::device_debug_setup()
+{
+ // do nothing by default
+}
+
+
+//-------------------------------------------------
+// device_timer - called whenever a device timer
+// fires
+//-------------------------------------------------
+
+void device_t::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ // do nothing by default
+}
+
+
+//-------------------------------------------------
+// register_auto_finder - add a new item to the
+// list of stuff to find after we go live
+//-------------------------------------------------
+
+void device_t::register_auto_finder(auto_finder_base &autodev)
+{
+ // add to this list
+ autodev.m_next = m_auto_finder_list;
+ m_auto_finder_list = &autodev;
+}
+
+
+//-------------------------------------------------
+// auto_finder_base - constructor
+//-------------------------------------------------
+
+device_t::auto_finder_base::auto_finder_base(device_t &base, const char *tag)
+ : m_next(NULL),
+ m_tag(tag)
+{
+ // register ourselves with our device class
+ base.register_auto_finder(*this);
+}
+
+
+//-------------------------------------------------
+// ~auto_finder_base - destructor
+//-------------------------------------------------
+
+device_t::auto_finder_base::~auto_finder_base()
+{
+}
+
+
+//-------------------------------------------------
+// find_device - find a device; done here instead
+// of inline in the template due to include
+// dependency ordering
+//-------------------------------------------------
+
+device_t *device_t::auto_finder_base::find_device(device_t &base, const char *tag)
+{
+ return base.subdevice(tag);
+}
+
+
+//-------------------------------------------------
+// find_shared_ptr - find a shared pointer
+//-------------------------------------------------
+
+void *device_t::auto_finder_base::find_shared_ptr(device_t &base, const char *tag)
+{
+ return memory_get_shared(base.machine(), tag);
+}
+
+
+//-------------------------------------------------
+// find_shared_size - find a shared pointer size
+//-------------------------------------------------
+
+size_t device_t::auto_finder_base::find_shared_size(device_t &base, const char *tag)
+{
+ size_t result = 0;
+ memory_get_shared(base.machine(), tag, result);
+ return result;
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE INTERFACES
+//**************************************************************************
+
+//-------------------------------------------------
+// device_interface - constructor
+//-------------------------------------------------
+
+device_interface::device_interface(device_t &device)
+ : m_interface_next(NULL),
+ m_device(device)
+{
+ device_interface **tailptr;
+ for (tailptr = &device.m_interface_list; *tailptr != NULL; tailptr = &(*tailptr)->m_interface_next) ;
+ *tailptr = this;
+}
+
+
+//-------------------------------------------------
+// ~device_interface - destructor
+//-------------------------------------------------
+
+device_interface::~device_interface()
+{
+}
+
+
+//-------------------------------------------------
+// interface_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void device_interface::interface_config_complete()
+{
+ // do nothing by default
+}
+
+
+//-------------------------------------------------
+// interface_validity_check - default validation
+// for a device after the configuration has been
+// constructed
+//-------------------------------------------------
+
+bool device_interface::interface_validity_check(emu_options &options, const game_driver &driver) const
+{
+ return false;
+}
+
+
+//-------------------------------------------------
+// interface_pre_start - called before the
+// device's own start function
+//-------------------------------------------------
+
+void device_interface::interface_pre_start()
+{
+ // do nothing by default
+}
+
+
+//-------------------------------------------------
+// interface_post_start - called after the
+// device's own start function
+//-------------------------------------------------
+
+void device_interface::interface_post_start()
+{
+ // do nothing by default
+}
+
+
+//-------------------------------------------------
+// interface_pre_reset - called before the
+// device's own reset function
+//-------------------------------------------------
+
+void device_interface::interface_pre_reset()
+{
+ // do nothing by default
+}
+
+
+//-------------------------------------------------
+// interface_post_reset - called after the
+// device's own reset function
+//-------------------------------------------------
+
+void device_interface::interface_post_reset()
+{
+ // do nothing by default
+}
+
+
+//-------------------------------------------------
+// interface_pre_stop - called before the
+// device's own stop function
+//-------------------------------------------------
+
+void device_interface::interface_pre_stop()
+{
+ // do nothing by default
+}
+
+
+//-------------------------------------------------
+// interface_post_stop - called after the
+// device's own stop function
+//-------------------------------------------------
+
+void device_interface::interface_post_stop()
+{
+ // do nothing by default
+}
+
+
+//-------------------------------------------------
+// interface_pre_save - called prior to saving the
+// state, so that registered variables can be
+// properly normalized
+//-------------------------------------------------
+
+void device_interface::interface_pre_save()
+{
+ // do nothing by default
+}
+
+
+//-------------------------------------------------
+// interface_post_load - called after the loading a
+// saved state, so that registered variables can
+// be expaneded as necessary
+//-------------------------------------------------
+
+void device_interface::interface_post_load()
+{
+ // do nothing by default
+}
+
+
+//-------------------------------------------------
+// interface_clock_changed - called when the
+// device clock is altered in any way; designed
+// to be overridden by the actual device
+// implementation
+//-------------------------------------------------
+
+void device_interface::interface_clock_changed()
+{
+ // do nothing by default
+}
+
+
+//-------------------------------------------------
+// interface_debug_setup - called to allow
+// interfaces to set up any debugging for this
+// device
+//-------------------------------------------------
+
+void device_interface::interface_debug_setup()
+{
+ // do nothing by default
+}
diff --git a/trunk/src/emu/device.h b/trunk/src/emu/device.h
new file mode 100644
index 00000000000..b5faf4a9a87
--- /dev/null
+++ b/trunk/src/emu/device.h
@@ -0,0 +1,544 @@
+/***************************************************************************
+
+ device.h
+
+ Device interface 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 __EMU_H__
+#error Dont include this file directly; include emu.h instead.
+#endif
+
+#ifndef __DEVINTRF_H__
+#define __DEVINTRF_H__
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+// macro for specifying a clock derived from an owning device
+#define DERIVED_CLOCK(num, den) (0xff000000 | ((num) << 12) | ((den) << 0))
+
+// shorthand for accessing devices by machine/type/tag
+#define devtag_reset(mach,tag) (mach).device(tag)->reset()
+
+
+
+//**************************************************************************
+// DEVICE CONFIGURATION MACROS
+//**************************************************************************
+
+// configure devices
+#define MCFG_DEVICE_CONFIG(_config) \
+ device_t::static_set_static_config(*device, &(_config)); \
+
+#define MCFG_DEVICE_CONFIG_CLEAR() \
+ device_t::static_set_static_config(*device, NULL); \
+
+#define MCFG_DEVICE_CLOCK(_clock) \
+ device_t::static_set_clock(*device, _clock); \
+
+#define MCFG_DEVICE_INPUT_DEFAULTS(_config) \
+ device_t::static_set_input_default(*device, DEVICE_INPUT_DEFAULTS_NAME(_config)); \
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// forward references
+class memory_region;
+class device_debug;
+class device_t;
+class device_interface;
+class device_execute_interface;
+class device_memory_interface;
+class device_state_interface;
+struct rom_entry;
+class machine_config;
+class emu_timer;
+typedef struct _input_device_default input_device_default;
+
+
+// exception classes
+class device_missing_dependencies : public emu_exception { };
+
+
+// a device_type is simply a pointer to its alloc function
+typedef device_t *(*device_type)(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+
+// this template function creates a stub which constructs a device
+template<class _DeviceClass>
+device_t *device_creator(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+{
+ return global_alloc(_DeviceClass(mconfig, tag, owner, clock));
+}
+
+
+// timer IDs for devices
+typedef UINT32 device_timer_id;
+
+
+// read/write types for I/O lines (similar to read/write handlers but no offset)
+typedef int (*read_line_device_func)(device_t *device);
+typedef void (*write_line_device_func)(device_t *device, int state);
+
+
+
+// ======================> tagged_device_list
+
+// tagged_device_list is a tagged_list with additional searching based on type
+class device_list : public tagged_list<device_t>
+{
+ typedef tagged_list<device_t> super;
+
+public:
+ // construction/destruction
+ device_list(resource_pool &pool = global_resource_pool);
+
+ // getters
+ running_machine &machine() const { assert(m_machine != NULL); return *m_machine; }
+
+ // bulk operations
+ void set_machine_all(running_machine &machine);
+ void start_all();
+ void start_new_devices();
+ void reset_all();
+ void stop_all();
+
+ // pull the generic forms forward
+ using super::first;
+ using super::count;
+ using super::indexof;
+ using super::find;
+
+ // provide type-specific overrides
+ device_t *first(device_type type) const;
+ int count(device_type type) const;
+ int indexof(device_type type, device_t &object) const;
+ int indexof(device_type type, const char *tag) const;
+ device_t *find(device_type type, int index) const;
+
+ // provide interface-specific overrides
+ template<class _InterfaceClass>
+ bool first(_InterfaceClass *&intf) const;
+
+private:
+ // internal helpers
+ void exit();
+ void presave_all();
+ void postload_all();
+
+ // internal state
+ running_machine *m_machine;
+};
+
+
+
+// ======================> device_t
+
+// device_t represents a device
+class device_t : public delegate_late_bind
+{
+ DISABLE_COPYING(device_t);
+
+ friend class device_interface;
+ friend class device_memory_interface;
+ friend class device_state_interface;
+ friend class device_execute_interface;
+ friend class simple_list<device_t>;
+ friend class device_list;
+
+protected:
+ // construction/destruction
+ device_t(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
+ device_t(const machine_config &mconfig, device_type type, const char *name, const char *shortname, const char *tag, device_t *owner, UINT32 clock);
+ virtual ~device_t();
+
+public:
+ // getters
+ running_machine &machine() const { assert(m_machine != NULL); return *m_machine; }
+ device_type type() const { return m_type; }
+ UINT32 configured_clock() const { return m_configured_clock; }
+ const char *name() const { return m_name; }
+ const char *shortname() const { return m_shortname; }
+ const char *searchpath() const { return m_searchpath; }
+ const char *tag() const { return m_tag; }
+ const void *static_config() const { return m_static_config; }
+ const machine_config &mconfig() const { return m_machine_config; }
+ const input_device_default *input_ports_defaults() const { return m_input_defaults; }
+ const rom_entry *rom_region() const { return device_rom_region(); }
+ machine_config_constructor machine_config_additions() const { return device_mconfig_additions(); }
+ ioport_constructor input_ports() const { return device_input_ports(); }
+
+ // iteration helpers
+ device_t *next() const { return m_next; }
+ device_t *typenext() const;
+ device_t *owner() const { return m_owner; }
+
+ // interface helpers
+ template<class _DeviceClass> bool interface(_DeviceClass *&intf) { intf = dynamic_cast<_DeviceClass *>(this); return (intf != NULL); }
+ template<class _DeviceClass> bool interface(_DeviceClass *&intf) const { intf = dynamic_cast<const _DeviceClass *>(this); return (intf != NULL); }
+ template<class _DeviceClass> bool next(_DeviceClass *&intf) const
+ {
+ for (device_t *cur = m_next; cur != NULL; cur = cur->m_next)
+ if (cur->interface(intf))
+ return true;
+ return false;
+ }
+
+ // specialized helpers for common core interfaces
+ bool interface(device_execute_interface *&intf) { intf = m_execute; return (intf != NULL); }
+ bool interface(device_execute_interface *&intf) const { intf = m_execute; return (intf != NULL); }
+ bool interface(device_memory_interface *&intf) { intf = m_memory; return (intf != NULL); }
+ bool interface(device_memory_interface *&intf) const { intf = m_memory; return (intf != NULL); }
+ bool interface(device_state_interface *&intf) { intf = m_state; return (intf != NULL); }
+ bool interface(device_state_interface *&intf) const { intf = m_state; return (intf != NULL); }
+ device_execute_interface &execute() const { assert(m_execute != NULL); return *m_execute; }
+ device_memory_interface &memory() const { assert(m_memory != NULL); return *m_memory; }
+
+ // owned object helpers
+ astring &subtag(astring &dest, const char *tag) const;
+ astring &siblingtag(astring &dest, const char *tag) const;
+ const memory_region *subregion(const char *tag) const;
+ device_t *subdevice(const char *tag) const;
+ device_t *siblingdevice(const char *tag) const;
+ template<class _DeviceClass> inline _DeviceClass *subdevice(const char *tag) { return downcast<_DeviceClass *>(subdevice(tag)); }
+ template<class _DeviceClass> inline _DeviceClass *siblingdevice(const char *tag) { return downcast<_DeviceClass *>(siblingdevice(tag)); }
+ const memory_region *region() const { return m_region; }
+
+ // configuration helpers
+ static void static_set_clock(device_t &device, UINT32 clock);
+ static void static_set_static_config(device_t &device, const void *config) { device.m_static_config = config; }
+ static void static_set_input_default(device_t &device, const input_device_default *config) { device.m_input_defaults = config; }
+
+ // state helpers
+ void config_complete();
+ bool configured() const { return m_config_complete; }
+ bool validity_check(emu_options &options, const game_driver &driver) const;
+ bool started() const { return m_started; }
+ void reset();
+
+ // clock/timing accessors
+ UINT32 clock() const { return m_clock; }
+ UINT32 unscaled_clock() const { return m_unscaled_clock; }
+ void set_unscaled_clock(UINT32 clock);
+ double clock_scale() const { return m_clock_scale; }
+ void set_clock_scale(double clockscale);
+ attotime clocks_to_attotime(UINT64 clocks) const;
+ UINT64 attotime_to_clocks(attotime duration) const;
+
+ // timer interfaces
+ emu_timer *timer_alloc(device_timer_id id = 0, void *ptr = NULL);
+ void timer_set(attotime duration, device_timer_id id = 0, int param = 0, void *ptr = NULL);
+ void synchronize(device_timer_id id = 0, int param = 0, void *ptr = NULL) { timer_set(attotime::zero, id, param, ptr); }
+ void timer_expired(emu_timer &timer, device_timer_id id, int param, void *ptr) { device_timer(timer, id, param, ptr); }
+
+ // state saving interfaces
+ template<typename _ItemType>
+ void save_item(_ItemType &value, const char *valname, int index = 0) { assert(m_save != NULL); m_save->save_item(name(), tag(), index, value, valname); }
+ template<typename _ItemType>
+ void save_pointer(_ItemType *value, const char *valname, UINT32 count, int index = 0) { assert(m_save != NULL); m_save->save_pointer(name(), tag(), index, value, valname, count); }
+
+ // debugging
+ device_debug *debug() const { return m_debug; }
+
+protected:
+ // miscellaneous helpers
+ void set_machine(running_machine &machine);
+ void start();
+ void stop();
+ void debug_setup();
+ void pre_save();
+ void post_load();
+ void notify_clock_changed();
+
+ //------------------- begin derived class overrides
+
+ // device-level overrides
+ virtual const rom_entry *device_rom_region() const;
+ virtual machine_config_constructor device_mconfig_additions() const;
+ virtual ioport_constructor device_input_ports() const;
+ virtual void device_config_complete();
+ virtual bool device_validity_check(emu_options &options, const game_driver &driver) const;
+ virtual void device_start() = 0;
+ virtual void device_stop();
+ virtual void device_reset();
+ virtual void device_pre_save();
+ virtual void device_post_load();
+ virtual void device_clock_changed();
+ virtual void device_debug_setup();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+ //------------------- end derived class overrides
+
+ device_debug * m_debug;
+
+ // core device interfaces for speed
+ device_execute_interface *m_execute;
+ device_memory_interface *m_memory;
+ device_state_interface *m_state;
+
+ // device relationships
+ device_t * m_next; // next device (of any type/class)
+ device_t * m_owner; // device that owns us, or NULL if nobody
+ device_interface * m_interface_list; // head of interface list
+
+ const device_type m_type; // device type
+ UINT32 m_configured_clock; // originally configured device clock
+
+ const machine_config & m_machine_config; // reference to the machine's configuration
+ const void * m_static_config; // static device configuration
+ const input_device_default *m_input_defaults; // devices input ports default overrides
+
+ astring m_name; // name of the device
+ astring m_shortname; // short name of the device
+ astring m_searchpath; // search path, used for media loading
+
+ bool m_started; // true if the start function has succeeded
+ UINT32 m_clock; // device clock
+ const memory_region * m_region; // our device-local region
+
+ UINT32 m_unscaled_clock; // unscaled clock
+ double m_clock_scale; // clock scale factor
+ attoseconds_t m_attoseconds_per_clock;// period in attoseconds
+
+ // helper class to request auto-object discovery in the constructor of a derived class
+ class auto_finder_base
+ {
+ public:
+ // construction/destruction
+ auto_finder_base(device_t &base, const char *tag);
+ virtual ~auto_finder_base();
+
+ // getters
+ virtual void findit(device_t &base) = 0;
+
+ // helpers
+ device_t *find_device(device_t &device, const char *tag);
+ void *find_shared_ptr(device_t &device, const char *tag);
+ size_t find_shared_size(device_t &device, const char *tag);
+
+ // internal state
+ auto_finder_base *m_next;
+ const char *m_tag;
+ };
+
+ // templated version bound to a specific type
+ template<typename _TargetType, bool _Required>
+ class auto_finder_type : public auto_finder_base
+ {
+ public:
+ // construction/destruction
+ auto_finder_type(device_t &base, const char *tag)
+ : auto_finder_base(base, tag),
+ m_target(0) { }
+
+ // operators to make use transparent
+ operator _TargetType() { return m_target; }
+ operator _TargetType() const { return m_target; }
+ _TargetType operator->() { return m_target; }
+
+ // getter for explicit fetching
+ _TargetType target() const { return m_target; }
+
+ // setter for setting the object
+ void set_target(_TargetType target)
+ {
+ m_target = target;
+ if (target == 0 && _Required)
+ throw emu_fatalerror("Unable to find required object '%s'", this->m_tag);
+ }
+
+ // internal state
+ _TargetType m_target;
+ };
+
+ // optional device finder
+ template<class _DeviceClass>
+ class optional_device : public auto_finder_type<_DeviceClass *, false>
+ {
+ public:
+ optional_device(device_t &base, const char *tag) : auto_finder_type<_DeviceClass *, false>(base, tag) { }
+ virtual void findit(device_t &base) { this->set_target(downcast<_DeviceClass *>(this->find_device(base, this->m_tag))); }
+ };
+
+ // required devices are similar but throw an error if they are not found
+ template<class _DeviceClass>
+ class required_device : public auto_finder_type<_DeviceClass *, true>
+ {
+ public:
+ required_device(device_t &base, const char *tag) : auto_finder_type<_DeviceClass *, true>(base, tag) { }
+ virtual void findit(device_t &base) { this->set_target(downcast<_DeviceClass *>(this->find_device(base, this->m_tag))); }
+ };
+
+ // optional shared pointer finder
+ template<typename _PointerType>
+ class optional_shared_ptr : public auto_finder_type<_PointerType *, false>
+ {
+ public:
+ optional_shared_ptr(device_t &base, const char *tag) : auto_finder_type<_PointerType *, false>(base, tag) { }
+ virtual void findit(device_t &base) { this->set_target(reinterpret_cast<_PointerType *>(this->find_shared_ptr(base, this->m_tag))); }
+ };
+
+ // required shared pointer finder
+ template<typename _PointerType>
+ class required_shared_ptr : public auto_finder_type<_PointerType *, true>
+ {
+ public:
+ required_shared_ptr(device_t &base, const char *tag) : auto_finder_type<_PointerType *, true>(base, tag) { }
+ virtual void findit(device_t &base) { this->set_target(reinterpret_cast<_PointerType *>(this->find_shared_ptr(base, this->m_tag))); }
+ };
+
+ // optional shared pointer size finder
+ class optional_shared_size : public auto_finder_type<size_t, false>
+ {
+ public:
+ optional_shared_size(device_t &base, const char *tag) : auto_finder_type<size_t, false>(base, tag) { }
+ virtual void findit(device_t &base) { this->set_target(find_shared_size(base, this->m_tag)); }
+ };
+
+ // required shared pointer size finder
+ class required_shared_size : public auto_finder_type<size_t, true>
+ {
+ public:
+ required_shared_size(device_t &base, const char *tag) : auto_finder_type<size_t, true>(base, tag) { }
+ virtual void findit(device_t &base) { this->set_target(find_shared_size(base, this->m_tag)); }
+ };
+
+ // internal helpers
+ void register_auto_finder(auto_finder_base &autodev);
+
+ auto_finder_base * m_auto_finder_list;
+
+private:
+ // private state; accessor use required
+ running_machine * m_machine;
+ save_manager * m_save;
+ astring m_tag; // tag for this instance
+ bool m_config_complete; // have we completed our configuration?
+};
+
+
+
+// ======================> device_interface
+
+// device_interface represents runtime information for a particular device interface
+class device_interface
+{
+ DISABLE_COPYING(device_interface);
+
+protected:
+ // construction/destruction
+ device_interface(device_t &device);
+ virtual ~device_interface();
+
+public:
+ // casting helpers
+ device_t &device() { return m_device; }
+ const device_t &device() const { return m_device; }
+ operator device_t &() { return m_device; }
+ operator device_t *() { return &m_device; }
+
+ // iteration helpers
+ device_interface *interface_next() const { return m_interface_next; }
+ template<class _InterfaceClass> bool next(_InterfaceClass *&intf) const { return m_device.next(intf); }
+
+ // optional operation overrides
+ virtual void interface_config_complete();
+ virtual bool interface_validity_check(emu_options &options, const game_driver &driver) const;
+ virtual void interface_pre_start();
+ virtual void interface_post_start();
+ virtual void interface_pre_reset();
+ virtual void interface_post_reset();
+ virtual void interface_pre_stop();
+ virtual void interface_post_stop();
+ virtual void interface_pre_save();
+ virtual void interface_post_load();
+ virtual void interface_clock_changed();
+ virtual void interface_debug_setup();
+
+protected:
+ // internal state
+ device_interface * m_interface_next;
+ device_t & m_device;
+};
+
+
+
+//**************************************************************************
+// INLINE FUNCTIONS
+//**************************************************************************
+
+
+// ======================> device config helpers
+
+// find the next device_t of the same type
+inline device_t *device_t::typenext() const
+{
+ device_t *cur;
+ for (cur = m_next; cur != NULL && cur->m_type != m_type; cur = cur->m_next) ;
+ return cur;
+}
+
+// create a tag for an object that is owned by this device
+inline astring &device_t::subtag(astring &dest, const char *_tag) const
+{
+ // temp. for now: don't include the root tag in the full tag name
+ return (this != NULL && m_owner != NULL) ? dest.cpy(m_tag).cat(":").cat(_tag) : dest.cpy(_tag);
+}
+
+// create a tag for an object that a sibling to this device
+inline astring &device_t::siblingtag(astring &dest, const char *_tag) const
+{
+ return (this != NULL && m_owner != NULL) ? m_owner->subtag(dest, _tag) : dest.cpy(_tag);
+}
+
+
+template<class _InterfaceClass>
+bool device_list::first(_InterfaceClass *&intf) const
+{
+ for (device_t *cur = super::first(); cur != NULL; cur = cur->next())
+ if (cur->interface(intf))
+ return true;
+ return false;
+}
+
+#endif /* __DEVINTRF_H__ */
diff --git a/trunk/src/emu/devimage.c b/trunk/src/emu/devimage.c
new file mode 100644
index 00000000000..7ab5318b8b6
--- /dev/null
+++ b/trunk/src/emu/devimage.c
@@ -0,0 +1,181 @@
+/***************************************************************************
+
+ devimage.c
+
+ Legacy image device helpers.
+
+****************************************************************************
+
+ Copyright Miodrag Milanovic
+ 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 "devlegcy.h"
+
+
+//**************************************************************************
+// LEGACY IMAGE DEVICE CONFIGURATION
+//**************************************************************************
+
+//-------------------------------------------------
+// legacy_device_base - destructor
+//-------------------------------------------------
+
+legacy_image_device_base::~legacy_image_device_base()
+{
+}
+
+//**************************************************************************
+// LIVE LEGACY IMAGE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// legacy_image_device_base - constructor
+//-------------------------------------------------
+
+legacy_image_device_base::legacy_image_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, device_get_config_func get_config)
+ : legacy_device_base(mconfig, type, tag, owner, clock, get_config),
+ device_image_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// device_config_complete - update configuration
+// based on completed device setup
+//-------------------------------------------------
+
+void legacy_image_device_base::device_config_complete()
+{
+ image_device_format **formatptr;
+ image_device_format *format;
+ formatptr = &m_formatlist;
+ int cnt = 0;
+
+ int format_count = get_legacy_int(DEVINFO_INT_IMAGE_CREATE_OPTCOUNT);
+
+ for (int i = 0; i < format_count; i++)
+ {
+ // only add if creatable
+ if (get_legacy_string(DEVINFO_PTR_IMAGE_CREATE_OPTSPEC + i)) {
+ // allocate a new format
+ format = global_alloc_clear(image_device_format);
+
+ // populate it
+ format->m_index = cnt;
+ format->m_name = get_legacy_string(DEVINFO_STR_IMAGE_CREATE_OPTNAME + i);
+ format->m_description = get_legacy_string(DEVINFO_STR_IMAGE_CREATE_OPTDESC + i);
+ format->m_extensions = get_legacy_string(DEVINFO_STR_IMAGE_CREATE_OPTEXTS + i);
+ format->m_optspec = get_legacy_string(DEVINFO_PTR_IMAGE_CREATE_OPTSPEC + i);
+
+ // and append it to the list
+ *formatptr = format;
+ formatptr = &format->m_next;
+ cnt++;
+ }
+ }
+
+ update_names();
+
+ // Override in case of hardcoded values
+ if (strlen(get_legacy_string(DEVINFO_STR_IMAGE_INSTANCE_NAME))>0) {
+ m_instance_name = get_legacy_string(DEVINFO_STR_IMAGE_INSTANCE_NAME);
+ }
+ if (strlen(get_legacy_string(DEVINFO_STR_IMAGE_BRIEF_INSTANCE_NAME))>0) {
+ m_brief_instance_name = get_legacy_string(DEVINFO_STR_IMAGE_BRIEF_INSTANCE_NAME);
+ }
+}
+
+
+bool legacy_image_device_base::call_load()
+{
+ device_image_load_func func = reinterpret_cast<device_image_load_func>(get_legacy_fct(DEVINFO_FCT_IMAGE_LOAD));
+ if (func) {
+ return (*func)(*this);
+ } else {
+ return FALSE;
+ }
+}
+
+bool legacy_image_device_base::call_softlist_load(char *swlist, char *swname, rom_entry *start_entry)
+{
+ device_image_softlist_load_func func = reinterpret_cast<device_image_softlist_load_func>(get_legacy_fct(DEVINFO_FCT_IMAGE_SOFTLIST_LOAD));
+ if (func) {
+ return (*func)(*this,swlist,swname,start_entry);
+ } else {
+ return FALSE;
+ }
+}
+
+bool legacy_image_device_base::call_create(int format_type, option_resolution *format_options)
+{
+ device_image_create_func func = reinterpret_cast<device_image_create_func>(get_legacy_fct(DEVINFO_FCT_IMAGE_CREATE));
+ if (func) {
+ return (*func)(*this,format_type,format_options);
+ } else {
+ return FALSE;
+ }
+}
+
+void legacy_image_device_base::call_unload()
+{
+ device_image_unload_func func = reinterpret_cast<device_image_unload_func>(get_legacy_fct(DEVINFO_FCT_IMAGE_UNLOAD));
+ if (func) (*func)(*this);
+}
+
+void legacy_image_device_base::call_display()
+{
+ device_image_display_func func = reinterpret_cast<device_image_display_func>(get_legacy_fct(DEVINFO_FCT_IMAGE_DISPLAY));
+ if (func) (*func)(*this);
+}
+
+void legacy_image_device_base::call_display_info()
+{
+ device_image_display_info_func func = reinterpret_cast<device_image_display_info_func>(get_legacy_fct(DEVINFO_FCT_IMAGE_DISPLAY_INFO));
+ if (func) (*func)(*this);
+}
+
+void legacy_image_device_base::call_get_devices()
+{
+ device_image_get_devices_func func = reinterpret_cast<device_image_get_devices_func>(get_legacy_fct(DEVINFO_FCT_IMAGE_GET_DEVICES));
+ if (func) (*func)(*this);
+}
+
+device_image_partialhash_func legacy_image_device_base::get_partial_hash() const
+{
+ return reinterpret_cast<device_image_partialhash_func>(get_legacy_fct(DEVINFO_FCT_IMAGE_PARTIAL_HASH));
+}
+
+void *legacy_image_device_base::get_device_specific_call()
+{
+ return (void*) get_legacy_fct(DEVINFO_FCT_DEVICE_SPECIFIC);
+}
diff --git a/trunk/src/emu/devlegcy.c b/trunk/src/emu/devlegcy.c
new file mode 100644
index 00000000000..1b15e10a2cf
--- /dev/null
+++ b/trunk/src/emu/devlegcy.c
@@ -0,0 +1,359 @@
+/***************************************************************************
+
+ devlegcy.c
+
+ Legacy device helpers.
+
+****************************************************************************
+
+ 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 "devlegcy.h"
+
+
+//**************************************************************************
+// LEGACY DEVICE CONFIGURATION
+//**************************************************************************
+
+//-------------------------------------------------
+// legacy_device_base - constructor
+//-------------------------------------------------
+
+legacy_device_base::legacy_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, device_get_config_func get_config)
+ : device_t(mconfig, type, "Legacy Device", tag, owner, clock),
+ m_get_config_func(get_config),
+ m_inline_config(NULL),
+ m_token(NULL)
+{
+ // allocate a buffer for the inline configuration
+ UINT32 configlen = (UINT32)get_legacy_int(DEVINFO_INT_INLINE_CONFIG_BYTES);
+ if (configlen != 0)
+ m_inline_config = global_alloc_array_clear(UINT8, configlen);
+
+ // set the proper name
+ m_name = get_legacy_string(DEVINFO_STR_NAME);
+ m_shortname = get_legacy_string(DEVINFO_STR_SHORTNAME);
+ m_searchpath = m_shortname;
+
+ // create the token
+ int tokenbytes = get_legacy_int(DEVINFO_INT_TOKEN_BYTES);
+ if (tokenbytes != 0)
+ m_token = global_alloc_array_clear(UINT8, tokenbytes);
+}
+
+
+//-------------------------------------------------
+// ~legacy_device_base - destructor
+//-------------------------------------------------
+
+legacy_device_base::~legacy_device_base()
+{
+ global_free(m_token);
+ global_free(m_inline_config);
+}
+
+
+//-------------------------------------------------
+// get_legacy_int - return a legacy
+// configuration parameter as an integer
+//-------------------------------------------------
+
+INT64 legacy_device_base::get_legacy_int(UINT32 state) const
+{
+ deviceinfo info = { 0 };
+ (*m_get_config_func)(this, state, &info);
+ return info.i;
+}
+
+
+//-------------------------------------------------
+// get_legacy_ptr - return a legacy
+// configuration parameter as a pointer
+//-------------------------------------------------
+
+void *legacy_device_base::get_legacy_ptr(UINT32 state) const
+{
+ deviceinfo info = { 0 };
+ (*m_get_config_func)(this, state, &info);
+ return info.p;
+}
+
+
+//-------------------------------------------------
+// get_legacy_fct - return a legacy
+// configuration parameter as a function pointer
+//-------------------------------------------------
+
+genf *legacy_device_base::get_legacy_fct(UINT32 state) const
+{
+ deviceinfo info = { 0 };
+ (*m_get_config_func)(this, state, &info);
+ return info.f;
+}
+
+
+//-------------------------------------------------
+// get_legacy_string - return a legacy
+// configuration parameter as a string pointer
+//-------------------------------------------------
+
+const char *legacy_device_base::get_legacy_string(UINT32 state) const
+{
+ deviceinfo info;
+ info.s = get_temp_string_buffer();
+ (*m_get_config_func)(this, state, &info);
+ return info.s;
+}
+
+
+//-------------------------------------------------
+// static_set_inline32 - configuration helper to
+// set a 32-bit value in the inline configuration
+//-------------------------------------------------
+
+void legacy_device_base::static_set_inline32(device_t &device, UINT32 offset, UINT32 size, UINT32 value)
+{
+ legacy_device_base &legacy = downcast<legacy_device_base &>(device);
+ void *dest = reinterpret_cast<UINT8 *>(legacy.m_inline_config) + offset;
+ if (size == 1)
+ *reinterpret_cast<UINT8 *>(dest) = value;
+ else if (size == 2)
+ *reinterpret_cast<UINT16 *>(dest) = value;
+ else if (size == 4)
+ *reinterpret_cast<UINT32 *>(dest) = value;
+ else
+ throw emu_fatalerror("Unexpected size %d in legacy_device_base::static_set_inline32", size);
+}
+
+
+//-------------------------------------------------
+// static_set_inline64 - configuration helper to
+// set a 64-bit value in the inline configuration
+//-------------------------------------------------
+
+void legacy_device_base::static_set_inline64(device_t &device, UINT32 offset, UINT32 size, UINT64 value)
+{
+ legacy_device_base &legacy = downcast<legacy_device_base &>(device);
+ void *dest = reinterpret_cast<UINT8 *>(legacy.m_inline_config) + offset;
+ if (size == 1)
+ *reinterpret_cast<UINT8 *>(dest) = value;
+ else if (size == 2)
+ *reinterpret_cast<UINT16 *>(dest) = value;
+ else if (size == 4)
+ *reinterpret_cast<UINT32 *>(dest) = value;
+ else if (size == 8)
+ *reinterpret_cast<UINT64 *>(dest) = value;
+ else
+ throw emu_fatalerror("Unexpected size %d in legacy_device_base::static_set_inline64", size);
+}
+
+
+//-------------------------------------------------
+// static_set_inline_float - configuration helper
+// to set a floating-point value in the inline
+// configuration
+//-------------------------------------------------
+
+void legacy_device_base::static_set_inline_float(device_t &device, UINT32 offset, UINT32 size, float value)
+{
+ legacy_device_base &legacy = downcast<legacy_device_base &>(device);
+ void *dest = reinterpret_cast<UINT8 *>(legacy.m_inline_config) + offset;
+ if (size == 4)
+ *reinterpret_cast<float *>(dest) = value;
+ else
+ throw emu_fatalerror("Unexpected size %d in legacy_device_base::static_set_inline_float", size);
+}
+
+
+//-------------------------------------------------
+// device_validity_check - perform validity
+// checks on a device configuration
+//-------------------------------------------------
+
+bool legacy_device_base::device_validity_check(emu_options &options, const game_driver &driver) const
+{
+ device_validity_check_func validity_func = reinterpret_cast<device_validity_check_func>(get_legacy_fct(DEVINFO_FCT_VALIDITY_CHECK));
+ if (validity_func != NULL)
+ return (*validity_func)(&driver, this, options);
+ return false;
+}
+
+
+//-------------------------------------------------
+// device_start - called to start up a device
+//-------------------------------------------------
+
+void legacy_device_base::device_start()
+{
+ device_start_func start_func = reinterpret_cast<device_start_func>(get_legacy_fct(DEVINFO_FCT_START));
+ assert(start_func != NULL);
+ (*start_func)(this);
+}
+
+
+//-------------------------------------------------
+// device_reset - called to reset a device
+//-------------------------------------------------
+
+void legacy_device_base::device_reset()
+{
+ device_reset_func reset_func = reinterpret_cast<device_reset_func>(get_legacy_fct(DEVINFO_FCT_RESET));
+ if (reset_func != NULL)
+ (*reset_func)(this);
+}
+
+
+//-------------------------------------------------
+// device_stop - called to stop a device
+//-------------------------------------------------
+
+void legacy_device_base::device_stop()
+{
+ if (m_started)
+ {
+ device_stop_func stop_func = reinterpret_cast<device_stop_func>(get_legacy_fct(DEVINFO_FCT_STOP));
+ if (stop_func != NULL)
+ (*stop_func)(this);
+ }
+}
+
+
+//**************************************************************************
+// LEGACY SOUND DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// legacy_sound_device_base - constructor
+//-------------------------------------------------
+
+legacy_sound_device_base::legacy_sound_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, device_get_config_func get_config)
+ : legacy_device_base(mconfig, type, tag, owner, clock, get_config),
+ device_sound_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// sound_stream_update - handle a stream update
+//-------------------------------------------------
+
+void legacy_sound_device_base::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+{
+ // should never get here
+ fatalerror("legacy_sound_device_base::sound_stream_update called; not applicable to legacy sound devices\n");
+}
+
+
+
+//**************************************************************************
+// LEGACY MEMORY DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// legacy_memory_device_base - constructor
+//-------------------------------------------------
+
+legacy_memory_device_base::legacy_memory_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, device_get_config_func get_config)
+ : legacy_device_base(mconfig, type, tag, owner, clock, get_config),
+ device_memory_interface(mconfig, *this)
+{
+ memset(&m_space_config, 0, sizeof(m_space_config));
+}
+
+
+//-------------------------------------------------
+// device_config_complete - update configuration
+// based on completed device setup
+//-------------------------------------------------
+
+void legacy_memory_device_base::device_config_complete()
+{
+ m_space_config.m_name = "memory";
+ m_space_config.m_endianness = static_cast<endianness_t>(get_legacy_int(DEVINFO_INT_ENDIANNESS));
+ m_space_config.m_databus_width = get_legacy_int(DEVINFO_INT_DATABUS_WIDTH);
+ m_space_config.m_addrbus_width = get_legacy_int(DEVINFO_INT_ADDRBUS_WIDTH);
+ m_space_config.m_addrbus_shift = get_legacy_int(DEVINFO_INT_ADDRBUS_SHIFT);
+ m_space_config.m_logaddr_width = m_space_config.m_addrbus_width;
+ m_space_config.m_page_shift = 0;
+ m_space_config.m_internal_map = reinterpret_cast<address_map_constructor>(get_legacy_fct(DEVINFO_PTR_INTERNAL_MEMORY_MAP));
+ m_space_config.m_default_map = reinterpret_cast<address_map_constructor>(get_legacy_fct(DEVINFO_PTR_DEFAULT_MEMORY_MAP));
+}
+
+
+
+//**************************************************************************
+// LEGACY NVRAM DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// legacy_nvram_device_base - constructor
+//-------------------------------------------------
+
+legacy_nvram_device_base::legacy_nvram_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, device_get_config_func get_config)
+ : legacy_device_base(mconfig, type, tag, owner, clock, get_config),
+ device_nvram_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// nvram_default - generate the default NVRAM
+//-------------------------------------------------
+
+void legacy_nvram_device_base::nvram_default()
+{
+ device_nvram_func nvram_func = reinterpret_cast<device_nvram_func>(get_legacy_fct(DEVINFO_FCT_NVRAM));
+ (*nvram_func)(this, NULL, FALSE);
+}
+
+
+//-------------------------------------------------
+// nvram_read - read NVRAM from the given file
+//-------------------------------------------------
+
+void legacy_nvram_device_base::nvram_read(emu_file &file)
+{
+ device_nvram_func nvram_func = reinterpret_cast<device_nvram_func>(get_legacy_fct(DEVINFO_FCT_NVRAM));
+ (*nvram_func)(this, &file, FALSE);
+}
+
+
+//-------------------------------------------------
+// nvram_write - write NVRAM to the given file
+//-------------------------------------------------
+
+void legacy_nvram_device_base::nvram_write(emu_file &file)
+{
+ device_nvram_func nvram_func = reinterpret_cast<device_nvram_func>(get_legacy_fct(DEVINFO_FCT_NVRAM));
+ (*nvram_func)(this, &file, TRUE);
+}
diff --git a/trunk/src/emu/devlegcy.h b/trunk/src/emu/devlegcy.h
new file mode 100644
index 00000000000..52d685cd780
--- /dev/null
+++ b/trunk/src/emu/devlegcy.h
@@ -0,0 +1,546 @@
+/***************************************************************************
+
+ devlegcy.h
+
+ Legacy device helpers.
+
+****************************************************************************
+
+ 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 __DEVLEGCY_H__
+#define __DEVLEGCY_H__
+
+#include <stddef.h>
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+#define DEVINFO_IMAGE_CREATE_OPTMAX 32
+
+// state constants passed to the device_get_config_func
+enum
+{
+ // --- the following bits of info are returned as 64-bit signed integers ---
+ DEVINFO_INT_FIRST = 0x00000,
+
+ DEVINFO_INT_TOKEN_BYTES = DEVINFO_INT_FIRST, // R/O: bytes to allocate for the token
+ DEVINFO_INT_INLINE_CONFIG_BYTES, // R/O: bytes to allocate for the inline configuration
+
+ DEVINFO_INT_ENDIANNESS, // R/O: either ENDIANNESS_BIG or ENDIANNESS_LITTLE
+ DEVINFO_INT_DATABUS_WIDTH, // R/O: data bus size for each address space (8,16,32,64)
+ DEVINFO_INT_DATABUS_WIDTH_0 = DEVINFO_INT_DATABUS_WIDTH + 0,
+ DEVINFO_INT_DATABUS_WIDTH_1 = DEVINFO_INT_DATABUS_WIDTH + 1,
+ DEVINFO_INT_DATABUS_WIDTH_2 = DEVINFO_INT_DATABUS_WIDTH + 2,
+ DEVINFO_INT_DATABUS_WIDTH_3 = DEVINFO_INT_DATABUS_WIDTH + 3,
+ DEVINFO_INT_DATABUS_WIDTH_LAST = DEVINFO_INT_DATABUS_WIDTH + ADDRESS_SPACES - 1,
+ DEVINFO_INT_ADDRBUS_WIDTH, // R/O: address bus size for each address space (12-32)
+ DEVINFO_INT_ADDRBUS_WIDTH_0 = DEVINFO_INT_ADDRBUS_WIDTH + 0,
+ DEVINFO_INT_ADDRBUS_WIDTH_1 = DEVINFO_INT_ADDRBUS_WIDTH + 1,
+ DEVINFO_INT_ADDRBUS_WIDTH_2 = DEVINFO_INT_ADDRBUS_WIDTH + 2,
+ DEVINFO_INT_ADDRBUS_WIDTH_3 = DEVINFO_INT_ADDRBUS_WIDTH + 3,
+ DEVINFO_INT_ADDRBUS_WIDTH_LAST = DEVINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACES - 1,
+ DEVINFO_INT_ADDRBUS_SHIFT, // R/O: shift applied to addresses each address space (+3 means >>3, -1 means <<1)
+ DEVINFO_INT_ADDRBUS_SHIFT_0 = DEVINFO_INT_ADDRBUS_SHIFT + 0,
+ DEVINFO_INT_ADDRBUS_SHIFT_1 = DEVINFO_INT_ADDRBUS_SHIFT + 1,
+ DEVINFO_INT_ADDRBUS_SHIFT_2 = DEVINFO_INT_ADDRBUS_SHIFT + 2,
+ DEVINFO_INT_ADDRBUS_SHIFT_3 = DEVINFO_INT_ADDRBUS_SHIFT + 3,
+ DEVINFO_INT_ADDRBUS_SHIFT_LAST = DEVINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACES - 1,
+
+ DEVINFO_INT_CLASS_SPECIFIC = 0x04000, // R/W: device-specific values start here
+ DEVINFO_INT_DEVICE_SPECIFIC = 0x08000, // R/W: device-specific values start here
+ DEVINFO_INT_LAST = 0x0ffff,
+
+ // --- the following bits of info are returned as pointers ---
+ DEVINFO_PTR_FIRST = 0x10000,
+
+ DEVINFO_PTR_ROM_REGION = DEVINFO_PTR_FIRST, // R/O: pointer to device-specific ROM region
+ DEVINFO_PTR_MACHINE_CONFIG, // R/O: pointer to device-specific machine config
+ DEVINFO_PTR_INPUT_PORTS,
+
+ DEVINFO_PTR_INTERNAL_MEMORY_MAP, // R/O: address_map_constructor map
+ DEVINFO_PTR_INTERNAL_MEMORY_MAP_0 = DEVINFO_PTR_INTERNAL_MEMORY_MAP + 0,
+ DEVINFO_PTR_INTERNAL_MEMORY_MAP_1 = DEVINFO_PTR_INTERNAL_MEMORY_MAP + 1,
+ DEVINFO_PTR_INTERNAL_MEMORY_MAP_2 = DEVINFO_PTR_INTERNAL_MEMORY_MAP + 2,
+ DEVINFO_PTR_INTERNAL_MEMORY_MAP_3 = DEVINFO_PTR_INTERNAL_MEMORY_MAP + 3,
+ DEVINFO_PTR_INTERNAL_MEMORY_MAP_LAST = DEVINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACES - 1,
+
+ DEVINFO_PTR_DEFAULT_MEMORY_MAP, // R/O: address_map_constructor map
+ DEVINFO_PTR_DEFAULT_MEMORY_MAP_0 = DEVINFO_PTR_DEFAULT_MEMORY_MAP + 0,
+ DEVINFO_PTR_DEFAULT_MEMORY_MAP_1 = DEVINFO_PTR_DEFAULT_MEMORY_MAP + 1,
+ DEVINFO_PTR_DEFAULT_MEMORY_MAP_2 = DEVINFO_PTR_DEFAULT_MEMORY_MAP + 2,
+ DEVINFO_PTR_DEFAULT_MEMORY_MAP_3 = DEVINFO_PTR_DEFAULT_MEMORY_MAP + 3,
+ DEVINFO_PTR_DEFAULT_MEMORY_MAP_LAST = DEVINFO_PTR_DEFAULT_MEMORY_MAP + ADDRESS_SPACES - 1,
+
+ DEVINFO_PTR_CLASS_SPECIFIC = 0x14000, // R/W: device-specific values start here
+ DEVINFO_PTR_DEVICE_SPECIFIC = 0x18000, // R/W: device-specific values start here
+ DEVINFO_PTR_LAST = 0x1ffff,
+
+ // --- the following bits of info are returned as pointers to functions ---
+ DEVINFO_FCT_FIRST = 0x20000,
+
+ DEVINFO_FCT_START = DEVINFO_FCT_FIRST, // R/O: device_start_func
+ DEVINFO_FCT_STOP, // R/O: device_stop_func
+ DEVINFO_FCT_RESET, // R/O: device_reset_func
+ DEVINFO_FCT_EXECUTE, // R/O: device_execute_func
+ DEVINFO_FCT_NVRAM, // R/O: device_nvram_func
+ DEVINFO_FCT_VALIDITY_CHECK, // R/O: device_validity_check_func
+
+ DEVINFO_FCT_CLASS_SPECIFIC = 0x24000, // R/W: device-specific values start here
+ DEVINFO_FCT_DEVICE_SPECIFIC = 0x28000, // R/W: device-specific values start here
+ DEVINFO_FCT_LAST = 0x2ffff,
+
+ // --- the following bits of info are returned as NULL-terminated strings ---
+ DEVINFO_STR_FIRST = 0x30000,
+
+ DEVINFO_STR_NAME = DEVINFO_STR_FIRST, // R/O: name of the device
+ DEVINFO_STR_SHORTNAME, // R/O: search path of device, used for media loading
+ DEVINFO_STR_FAMILY, // R/O: family of the device
+ DEVINFO_STR_VERSION, // R/O: version of the device
+ DEVINFO_STR_SOURCE_FILE, // R/O: file containing the device implementation
+ DEVINFO_STR_CREDITS, // R/O: credits for the device implementation
+
+ DEVINFO_STR_CLASS_SPECIFIC = 0x34000, // R/W: device-specific values start here
+ DEVINFO_STR_DEVICE_SPECIFIC = 0x38000, // R/W: device-specific values start here
+ DEVINFO_STR_LAST = 0x3ffff,
+
+ /* --- image device related --- */
+ /* --- the following bits of info are returned as integers --- */
+ DEVINFO_INT_IMAGE_FIRST = DEVINFO_INT_FIRST + 0x7000,
+ DEVINFO_INT_IMAGE_TYPE,
+ DEVINFO_INT_IMAGE_READABLE,
+ DEVINFO_INT_IMAGE_WRITEABLE,
+ DEVINFO_INT_IMAGE_CREATABLE,
+ DEVINFO_INT_IMAGE_MUST_BE_LOADED,
+ DEVINFO_INT_IMAGE_RESET_ON_LOAD,
+ DEVINFO_INT_IMAGE_CREATE_OPTCOUNT,
+ DEVINFO_INT_IMAGE_LAST = DEVINFO_INT_IMAGE_FIRST + 0x0fff,
+
+ /* --- the following bits of info are returned as pointers --- */
+ DEVINFO_PTR_IMAGE_FIRST = DEVINFO_PTR_FIRST + 0x7000,
+ DEVINFO_PTR_IMAGE_CREATE_OPTGUIDE,
+ DEVINFO_PTR_IMAGE_CREATE_OPTSPEC,
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ DEVINFO_FCT_IMAGE_FIRST = DEVINFO_FCT_FIRST + 0x7000,
+ DEVINFO_FCT_IMAGE_LOAD, /* R/O: device_image_load_func */
+ DEVINFO_FCT_IMAGE_CREATE, /* R/O: device_image_create_func */
+ DEVINFO_FCT_IMAGE_UNLOAD, /* R/O: device_image_unload_func */
+ DEVINFO_FCT_IMAGE_DISPLAY, /* R/O: device_image_display_func */
+ DEVINFO_FCT_IMAGE_PARTIAL_HASH, /* R/O: device_image_partialhash_func */
+ DEVINFO_FCT_IMAGE_DISPLAY_INFO, /* R/O: device_image_display_info_func */
+ DEVINFO_FCT_IMAGE_GET_DEVICES, /* R/O: device_image_get_devices_func */
+ DEVINFO_FCT_IMAGE_SOFTLIST_LOAD, /* R/O: device_image_softlist_load_func */
+ DEVINFO_FCT_IMAGE_LAST = DEVINFO_FCT_FIRST + 0x0fff,
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ DEVINFO_STR_IMAGE_FIRST = DEVINFO_STR_FIRST + 0x7000,
+ DEVINFO_STR_IMAGE_FILE_EXTENSIONS,
+ DEVINFO_STR_IMAGE_INSTANCE_NAME,
+ DEVINFO_STR_IMAGE_BRIEF_INSTANCE_NAME,
+ DEVINFO_STR_IMAGE_CREATE_OPTNAME,
+ DEVINFO_STR_IMAGE_CREATE_OPTDESC = DEVINFO_STR_IMAGE_CREATE_OPTNAME + DEVINFO_IMAGE_CREATE_OPTMAX,
+ DEVINFO_STR_IMAGE_CREATE_OPTEXTS = DEVINFO_STR_IMAGE_CREATE_OPTDESC + DEVINFO_IMAGE_CREATE_OPTMAX,
+ DEVINFO_STR_IMAGE_INTERFACE,
+ DEVINFO_STR_IMAGE_LAST = DEVINFO_STR_IMAGE_FIRST + 0x0fff
+};
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+// macro for declaring the configuration and device classes of a legacy device
+#define _DECLARE_LEGACY_DEVICE(name, basename, deviceclass, basedeviceclass) \
+ \
+DEVICE_GET_INFO( basename ); \
+ \
+class deviceclass : public basedeviceclass \
+{ \
+public: \
+ deviceclass(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock); \
+}; \
+ \
+extern const device_type name
+
+// macro for defining the implementation needed for configuration and device classes
+#define _DEFINE_LEGACY_DEVICE(name, basename, deviceclass, basedeviceclass) \
+ \
+deviceclass::deviceclass(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock) \
+ : basedeviceclass(mconfig, type, tag, owner, clock, DEVICE_GET_INFO_NAME(basename)) \
+{ \
+} \
+ \
+const device_type name = &legacy_device_creator<deviceclass>
+
+// this template function creates a stub which constructs a device
+template<class _DeviceClass>
+device_t *legacy_device_creator(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+{
+ return global_alloc(_DeviceClass(mconfig, &legacy_device_creator<_DeviceClass>, tag, owner, clock));
+}
+
+
+// reduced macros that are easier to use, and map to the above two macros
+#define DECLARE_LEGACY_DEVICE(name, basename) _DECLARE_LEGACY_DEVICE(name, basename, basename##_device, legacy_device_base)
+#define DECLARE_LEGACY_SOUND_DEVICE(name, basename) _DECLARE_LEGACY_DEVICE(name, basename, basename##_device, legacy_sound_device_base)
+#define DECLARE_LEGACY_MEMORY_DEVICE(name, basename) _DECLARE_LEGACY_DEVICE(name, basename, basename##_device, legacy_memory_device_base)
+#define DECLARE_LEGACY_NVRAM_DEVICE(name, basename) _DECLARE_LEGACY_DEVICE(name, basename, basename##_device, legacy_nvram_device_base)
+#define DECLARE_LEGACY_IMAGE_DEVICE(name, basename) _DECLARE_LEGACY_DEVICE(name, basename, basename##_device, legacy_image_device_base)
+
+#define DEFINE_LEGACY_DEVICE(name, basename) _DEFINE_LEGACY_DEVICE(name, basename, basename##_device, legacy_device_base)
+#define DEFINE_LEGACY_SOUND_DEVICE(name, basename) _DEFINE_LEGACY_DEVICE(name, basename, basename##_device, legacy_sound_device_base)
+#define DEFINE_LEGACY_MEMORY_DEVICE(name, basename) _DEFINE_LEGACY_DEVICE(name, basename, basename##_device, legacy_memory_device_base)
+#define DEFINE_LEGACY_NVRAM_DEVICE(name, basename) _DEFINE_LEGACY_DEVICE(name, basename, basename##_device, legacy_nvram_device_base)
+#define DEFINE_LEGACY_IMAGE_DEVICE(name, basename) _DEFINE_LEGACY_DEVICE(name, basename, basename##_device, legacy_image_device_base)
+
+
+// macros to wrap legacy device functions
+#define DEVICE_GET_INFO_NAME(name) device_get_config_##name
+#define DEVICE_GET_INFO(name) void DEVICE_GET_INFO_NAME(name)(const device_t *device, UINT32 state, deviceinfo *info)
+#define DEVICE_GET_INFO_CALL(name) DEVICE_GET_INFO_NAME(name)(device, state, info)
+
+#define DEVICE_VALIDITY_CHECK_NAME(name) device_validity_check_##name
+#define DEVICE_VALIDITY_CHECK(name) int DEVICE_VALIDITY_CHECK_NAME(name)(const game_driver *driver, const device_t *device, emu_options &options)
+#define DEVICE_VALIDITY_CHECK_CALL(name) DEVICE_VALIDITY_CHECK_NAME(name)(driver, device)
+
+#define DEVICE_START_NAME(name) device_start_##name
+#define DEVICE_START(name) void DEVICE_START_NAME(name)(device_t *device)
+#define DEVICE_START_CALL(name) DEVICE_START_NAME(name)(device)
+
+#define DEVICE_STOP_NAME(name) device_stop_##name
+#define DEVICE_STOP(name) void DEVICE_STOP_NAME(name)(device_t *device)
+#define DEVICE_STOP_CALL(name) DEVICE_STOP_NAME(name)(device)
+
+#define DEVICE_RESET_NAME(name) device_reset_##name
+#define DEVICE_RESET(name) void DEVICE_RESET_NAME(name)(device_t *device)
+#define DEVICE_RESET_CALL(name) DEVICE_RESET_NAME(name)(device)
+
+#define DEVICE_EXECUTE_NAME(name) device_execute_##name
+#define DEVICE_EXECUTE(name) INT32 DEVICE_EXECUTE_NAME(name)(device_t *device, INT32 clocks)
+#define DEVICE_EXECUTE_CALL(name) DEVICE_EXECUTE_NAME(name)(device, clocks)
+
+#define DEVICE_NVRAM_NAME(name) device_nvram_##name
+#define DEVICE_NVRAM(name) void DEVICE_NVRAM_NAME(name)(device_t *device, emu_file *file, int read_or_write)
+#define DEVICE_NVRAM_CALL(name) DEVICE_NVRAM_NAME(name)(device, file, read_or_write)
+
+
+
+//**************************************************************************
+// DEVICE_CONFIGURATION_MACROS
+//**************************************************************************
+
+#define structsizeof(_struct, _field) sizeof(((_struct *)NULL)->_field)
+
+// inline device configurations that require 32 bits of storage in the token
+#define MCFG_DEVICE_CONFIG_DATA32_EXPLICIT(_size, _offset, _val) \
+ legacy_device_base::static_set_inline32(*device, _offset, _size, (UINT32)(_val));
+
+#define MCFG_DEVICE_CONFIG_DATA32(_struct, _field, _val) \
+ MCFG_DEVICE_CONFIG_DATA32_EXPLICIT(structsizeof(_struct, _field), offsetof(_struct, _field), _val)
+
+#define MCFG_DEVICE_CONFIG_DATA32_ARRAY(_struct, _field, _index, _val) \
+ MCFG_DEVICE_CONFIG_DATA32_EXPLICIT(structsizeof(_struct, _field[0]), offsetof(_struct, _field) + (_index) * structsizeof(_struct, _field[0]), _val)
+
+#define MCFG_DEVICE_CONFIG_DATA32_ARRAY_MEMBER(_struct, _field, _index, _memstruct, _member, _val) \
+ MCFG_DEVICE_CONFIG_DATA32_EXPLICIT(structsizeof(_memstruct, _member), offsetof(_struct, _field) + (_index) * structsizeof(_struct, _field[0]) + offsetof(_memstruct, _member), _val)
+
+#define MCFG_NEW_DEVICE_CONFIG_DATA32(_struct, _field, _val) \
+ MCFG_DEVICE_CONFIG_DATA32_EXPLICIT(DEVCONFIG_SIZEOF(_struct, _field), DEVCONFIG_OFFSETOF(_struct, _field), _val)
+
+#define MCFG_NEW_DEVICE_CONFIG_DATA32_ARRAY(_struct, _field, _index, _val) \
+ MCFG_DEVICE_CONFIG_DATA32_EXPLICIT(DEVCONFIG_SIZEOF(_struct, _field[0]), DEVCONFIG_OFFSETOF(_struct, _field) + (_index) * DEVCONFIG_SIZEOF(_struct, _field[0]), _val)
+
+#define MCFG_NEW_DEVICE_CONFIG_DATA32_ARRAY_MEMBER(_struct, _field, _index, _memstruct, _member, _val) \
+ MCFG_DEVICE_CONFIG_DATA32_EXPLICIT(DEVCONFIG_SIZEOF(_memstruct, _member), DEVCONFIG_OFFSETOF(_struct, _field) + (_index) * DEVCONFIG_SIZEOF(_struct, _field[0]) + DEVCONFIG_OFFSETOF(_memstruct, _member), _val)
+
+
+// inline device configurations that require 32 bits of fixed-point storage in the token
+#define MCFG_DEVICE_CONFIG_DATAFP32_EXPLICIT(_size, _offset, _val, _fixbits) \
+ legacy_device_base::static_set_inline_float(*device, _offset, _size, (float)(_val));
+
+#define MCFG_DEVICE_CONFIG_DATAFP32(_struct, _field, _val, _fixbits) \
+ MCFG_DEVICE_CONFIG_DATAFP32_EXPLICIT(structsizeof(_struct, _field), offsetof(_struct, _field), _val, _fixbits)
+
+#define MCFG_DEVICE_CONFIG_DATAFP32_ARRAY(_struct, _field, _index, _val, _fixbits) \
+ MCFG_DEVICE_CONFIG_DATAFP32_EXPLICIT(structsizeof(_struct, _field[0]), offsetof(_struct, _field) + (_index) * structsizeof(_struct, _field[0]), _val, _fixbits)
+
+#define MCFG_DEVICE_CONFIG_DATAFP32_ARRAY_MEMBER(_struct, _field, _index, _memstruct, _member, _val, _fixbits) \
+ MCFG_DEVICE_CONFIG_DATAFP32_EXPLICIT(structsizeof(_memstruct, _member), offsetof(_struct, _field) + (_index) * structsizeof(_struct, _field[0]) + offsetof(_memstruct, _member), _val, _fixbits)
+
+#define MCFG_DEVICE_NEW_CONFIG_DATAFP32(_struct, _field, _val, _fixbits) \
+ MCFG_DEVICE_CONFIG_DATAFP32_EXPLICIT(DEVCONFIG_SIZEOF(_struct, _field), DEVCONFIG_OFFSETOF(_struct, _field), _val, _fixbits)
+
+#define MCFG_DEVICE_NEW_CONFIG_DATAFP32_ARRAY(_struct, _field, _index, _val, _fixbits) \
+ MCFG_DEVICE_CONFIG_DATAFP32_EXPLICIT(DEVCONFIG_SIZEOF(_struct, _field[0]), DEVCONFIG_OFFSETOF(_struct, _field) + (_index) * DEVCONFIG_SIZEOF(_struct, _field[0]), _val, _fixbits)
+
+#define MCFG_DEVICE_NEW_CONFIG_DATAFP32_ARRAY_MEMBER(_struct, _field, _index, _memstruct, _member, _val, _fixbits) \
+ MCFG_DEVICE_CONFIG_DATAFP32_EXPLICIT(DEVCONFIG_SIZEOF(_memstruct, _member), DEVCONFIG_OFFSETOF(_struct, _field) + (_index) * DEVCONFIG_SIZEOF(_struct, _field[0]) + DEVCONFIG_OFFSETOF(_memstruct, _member), _val, _fixbits)
+
+
+// inline device configurations that require 64 bits of storage in the token
+#define MCFG_DEVICE_CONFIG_DATA64_EXPLICIT(_size, _offset, _val) \
+ legacy_device_base::static_set_inline64(*device, _offset, _size, (UINT64)(_val));
+
+#define MCFG_DEVICE_CONFIG_DATA64(_struct, _field, _val) \
+ MCFG_DEVICE_CONFIG_DATA64_EXPLICIT(structsizeof(_struct, _field), offsetof(_struct, _field), _val)
+
+#define MCFG_DEVICE_CONFIG_DATA64_ARRAY(_struct, _field, _index, _val) \
+ MCFG_DEVICE_CONFIG_DATA64_EXPLICIT(structsizeof(_struct, _field[0]), offsetof(_struct, _field) + (_index) * structsizeof(_struct, _field[0]), _val)
+
+#define MCFG_DEVICE_CONFIG_DATA64_ARRAY_MEMBER(_struct, _field, _index, _memstruct, _member, _val) \
+ MCFG_DEVICE_CONFIG_DATA64_EXPLICIT(structsizeof(_memstruct, _member), offsetof(_struct, _field) + (_index) * structsizeof(_struct, _field[0]) + offsetof(_memstruct, _member), _val)
+
+#define MCFG_DEVICE_NEW_CONFIG_DATA64(_struct, _field, _val) \
+ MCFG_DEVICE_CONFIG_DATA64_EXPLICIT(DEVCONFIG_SIZEOF(_struct, _field), DEVCONFIG_OFFSETOF(_struct, _field), _val)
+
+#define MCFG_DEVICE_NEW_CONFIG_DATA64_ARRAY(_struct, _field, _index, _val) \
+ MCFG_DEVICE_CONFIG_DATA64_EXPLICIT(DEVCONFIG_SIZEOF(_struct, _field[0]), DEVCONFIG_OFFSETOF(_struct, _field) + (_index) * DEVCONFIG_SIZEOF(_struct, _field[0]), _val)
+
+#define MCFG_DEVICE_NEW_CONFIG_DATA64_ARRAY_MEMBER(_struct, _field, _index, _memstruct, _member, _val) \
+ MCFG_DEVICE_CONFIG_DATA64_EXPLICIT(DEVCONFIG_SIZEOF(_memstruct, _member), DEVCONFIG_OFFSETOF(_struct, _field) + (_index) * DEVCONFIG_SIZEOF(_struct, _field[0]) + DEVCONFIG_OFFSETOF(_memstruct, _member), _val)
+
+
+// inline device configurations that require a pointer-sized amount of storage in the token
+#ifdef PTR64
+#define MCFG_DEVICE_CONFIG_DATAPTR_EXPLICIT(_struct, _size, _offset) MCFG_DEVICE_CONFIG_DATA64_EXPLICIT(_struct, _size, _offset)
+#define MCFG_DEVICE_CONFIG_DATAPTR(_struct, _field, _val) MCFG_DEVICE_CONFIG_DATA64(_struct, _field, _val)
+#define MCFG_DEVICE_CONFIG_DATAPTR_ARRAY(_struct, _field, _index, _val) MCFG_DEVICE_CONFIG_DATA64_ARRAY(_struct, _field, _index, _val)
+#define MCFG_DEVICE_CONFIG_DATAPTR_ARRAY_MEMBER(_struct, _field, _index, _memstruct, _member, _val) MCFG_DEVICE_CONFIG_DATA64_ARRAY_MEMBER(_struct, _field, _index, _memstruct, _member, _val)
+#define MCFG_DEVICE_NEW_CONFIG_DATAPTR(_struct, _field, _val) MCFG_DEVICE_NEW_CONFIG_DATA64(_struct, _field, _val)
+#define MCFG_DEVICE_NEW_CONFIG_DATAPTR_ARRAY(_struct, _field, _index, _val) MCFG_DEVICE_NEW_CONFIG_DATA64_ARRAY(_struct, _field, _index, _val)
+#define MCFG_DEVICE_NEW_CONFIG_DATAPTR_ARRAY_MEMBER(_struct, _field, _index, _memstruct, _member, _val) MCFG_DEVICE_NEW_CONFIG_DATA64_ARRAY_MEMBER(_struct, _field, _index, _memstruct, _member, _val)
+#else
+#define MCFG_DEVICE_CONFIG_DATAPTR_EXPLICIT(_struct, _size, _offset) MCFG_DEVICE_CONFIG_DATA32_EXPLICIT(_struct, _size, _offset)
+#define MCFG_DEVICE_CONFIG_DATAPTR(_struct, _field, _val) MCFG_DEVICE_CONFIG_DATA32(_struct, _field, _val)
+#define MCFG_DEVICE_CONFIG_DATAPTR_ARRAY(_struct, _field, _index, _val) MCFG_DEVICE_CONFIG_DATA32_ARRAY(_struct, _field, _index, _val)
+#define MCFG_DEVICE_CONFIG_DATAPTR_ARRAY_MEMBER(_struct, _field, _index, _memstruct, _member, _val) MCFG_DEVICE_CONFIG_DATA32_ARRAY_MEMBER(_struct, _field, _index, _memstruct, _member, _val)
+#define MCFG_DEVICE_CONFIG_NEW_DATAPTR(_struct, _field, _val) MCFG_DEVICE_NEW_CONFIG_DATA32(_struct, _field, _val)
+#define MCFG_DEVICE_CONFIG_NEW_DATAPTR_ARRAY(_struct, _field, _index, _val) MCFG_DEVICE_NEW_CONFIG_DATA32_ARRAY(_struct, _field, _index, _val)
+#define MCFG_DEVICE_CONFIG_NEW_DATAPTR_ARRAY_MEMBER(_struct, _field, _index, _memstruct, _member, _val) MCFG_DEVICE_NEW_CONFIG_DATA32_ARRAY_MEMBER(_struct, _field, _index, _memstruct, _member, _val)
+#endif
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+union deviceinfo;
+class machine_config;
+class device_t;
+
+char *get_temp_string_buffer(void);
+resource_pool &machine_get_pool(running_machine &machine);
+
+
+// device interface function types
+typedef void (*device_get_config_func)(const device_t *device, UINT32 state, deviceinfo *info);
+typedef int (*device_validity_check_func)(const game_driver *driver, const device_t *device, emu_options &options);
+
+typedef void (*device_start_func)(device_t *device);
+typedef void (*device_stop_func)(device_t *device);
+typedef INT32 (*device_execute_func)(device_t *device, INT32 clocks);
+typedef void (*device_reset_func)(device_t *device);
+typedef void (*device_nvram_func)(device_t *device, emu_file *file, int read_or_write);
+
+// the actual deviceinfo union
+union deviceinfo
+{
+ INT64 i; // generic integers
+ void * p; // generic pointers
+ genf * f; // generic function pointers
+ char * s; // generic strings
+
+ device_start_func start; // DEVINFO_FCT_START
+ device_stop_func stop; // DEVINFO_FCT_STOP
+ device_reset_func reset; // DEVINFO_FCT_RESET
+ device_execute_func execute; // DEVINFO_FCT_EXECUTE
+ device_nvram_func nvram; // DEVINFO_FCT_NVRAM
+ const rom_entry * romregion; // DEVINFO_PTR_ROM_REGION
+ machine_config_constructor machine_config; // DEVINFO_PTR_MACHINE_CONFIG
+ ioport_constructor ipt; // DEVINFO_PTR_INPUT_PORTS
+ address_map_constructor internal_map8; // DEVINFO_PTR_INTERNAL_MEMORY_MAP
+ address_map_constructor internal_map16; // DEVINFO_PTR_INTERNAL_MEMORY_MAP
+ address_map_constructor internal_map32; // DEVINFO_PTR_INTERNAL_MEMORY_MAP
+ address_map_constructor internal_map64; // DEVINFO_PTR_INTERNAL_MEMORY_MAP
+ address_map_constructor default_map8; // DEVINFO_PTR_DEFAULT_MEMORY_MAP
+ address_map_constructor default_map16; // DEVINFO_PTR_DEFAULT_MEMORY_MAP
+ address_map_constructor default_map32; // DEVINFO_PTR_DEFAULT_MEMORY_MAP
+ address_map_constructor default_map64; // DEVINFO_PTR_DEFAULT_MEMORY_MAP
+};
+
+
+// ======================> legacy_device_base
+
+// legacy_device_base serves as a common base class for legacy devices
+class legacy_device_base : public device_t
+{
+protected:
+ // construction/destruction
+ legacy_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, device_get_config_func get_config);
+ virtual ~legacy_device_base();
+
+public:
+ // access to legacy inline configuartion
+ void *inline_config() const { return m_inline_config; }
+
+ // inline configuration helpers
+ static void static_set_inline32(device_t &device, UINT32 offset, UINT32 size, UINT32 value);
+ static void static_set_inline64(device_t &device, UINT32 offset, UINT32 size, UINT64 value);
+ static void static_set_inline_float(device_t &device, UINT32 offset, UINT32 size, float value);
+
+ // access to legacy token
+ void *token() const { assert(m_token != NULL); return m_token; }
+
+protected:
+ // device-level overrides
+ virtual const rom_entry *device_rom_region() const { return reinterpret_cast<const rom_entry *>(get_legacy_ptr(DEVINFO_PTR_ROM_REGION)); }
+ virtual machine_config_constructor device_mconfig_additions() const { return reinterpret_cast<machine_config_constructor>(get_legacy_ptr(DEVINFO_PTR_MACHINE_CONFIG)); }
+ virtual ioport_constructor device_input_ports() const { return reinterpret_cast<ioport_constructor>(get_legacy_ptr(DEVINFO_PTR_INPUT_PORTS)); }
+ virtual bool device_validity_check(emu_options &options, const game_driver &driver) const;
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_stop();
+
+ // access to legacy configuration info
+ INT64 get_legacy_int(UINT32 state) const;
+ void *get_legacy_ptr(UINT32 state) const;
+ genf *get_legacy_fct(UINT32 state) const;
+ const char *get_legacy_string(UINT32 state) const;
+
+ // configuration state
+ device_get_config_func m_get_config_func;
+ void * m_inline_config;
+
+ // internal state
+ void * m_token;
+};
+
+
+
+// ======================> legacy_sound_device_base
+
+// legacy_sound_device is a legacy_device_base with a sound interface
+class legacy_sound_device_base : public legacy_device_base,
+ public device_sound_interface
+{
+protected:
+ // construction/destruction
+ legacy_sound_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, device_get_config_func get_config);
+
+ // sound stream update overrides
+ virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
+};
+
+
+
+// ======================> legacy_memory_device_base
+
+// legacy_memory_device is a legacy_device_base with a memory interface
+class legacy_memory_device_base : public legacy_device_base,
+ public device_memory_interface
+{
+protected:
+ // construction/destruction
+ legacy_memory_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, device_get_config_func get_config);
+
+ // device overrides
+ virtual void device_config_complete();
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return (spacenum == 0) ? &m_space_config : NULL; }
+
+ // internal state
+ address_space_config m_space_config;
+};
+
+
+
+// ======================> legacy_nvram_device
+
+// legacy_nvram_device is a legacy_device_base with a nvram interface
+class legacy_nvram_device_base : public legacy_device_base,
+ public device_nvram_interface
+{
+protected:
+ // construction/destruction
+ legacy_nvram_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, device_get_config_func get_config);
+
+ // device_nvram_interface overrides
+ virtual void nvram_default();
+ virtual void nvram_read(emu_file &file);
+ virtual void nvram_write(emu_file &file);
+};
+
+
+
+// ======================> legacy_image_device
+
+// legacy_image_device is a legacy_device_base with a image interface
+class legacy_image_device_base : public legacy_device_base,
+ public device_image_interface
+{
+public:
+ virtual bool call_load();
+ virtual bool call_softlist_load(char *swlist, char *swname, rom_entry *start_entry);
+ virtual bool call_create(int format_type, option_resolution *format_options);
+ virtual void call_unload();
+ virtual void call_display();
+ virtual void call_display_info();
+ virtual device_image_partialhash_func get_partial_hash() const;
+ virtual void call_get_devices();
+ virtual void *get_device_specific_call();
+
+ virtual iodevice_t image_type() const { return static_cast<iodevice_t>(get_legacy_int(DEVINFO_INT_IMAGE_TYPE)); }
+
+ virtual bool is_readable() const { return get_legacy_int(DEVINFO_INT_IMAGE_READABLE)!=0; }
+ virtual bool is_writeable() const { return get_legacy_int(DEVINFO_INT_IMAGE_WRITEABLE)!=0; }
+ virtual bool is_creatable() const { return get_legacy_int(DEVINFO_INT_IMAGE_CREATABLE)!=0; }
+ virtual bool must_be_loaded() const { return get_legacy_int(DEVINFO_INT_IMAGE_MUST_BE_LOADED)!=0; }
+ virtual bool is_reset_on_load() const { return get_legacy_int(DEVINFO_INT_IMAGE_RESET_ON_LOAD)!=0; }
+ virtual const char *image_interface() const { return get_legacy_string(DEVINFO_STR_IMAGE_INTERFACE); }
+ virtual const char *file_extensions() const { return get_legacy_string(DEVINFO_STR_IMAGE_FILE_EXTENSIONS); }
+ virtual const option_guide *create_option_guide() const { return reinterpret_cast<const option_guide *>(get_legacy_ptr(DEVINFO_PTR_IMAGE_CREATE_OPTGUIDE)); }
+protected:
+ // device overrides
+ virtual void device_config_complete();
+
+ // construction/destruction
+ legacy_image_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, device_get_config_func get_config);
+ ~legacy_image_device_base();
+};
+
+
+#endif /* __DEVLEGCY_H__ */
diff --git a/trunk/src/emu/devtempl.h b/trunk/src/emu/devtempl.h
new file mode 100644
index 00000000000..7b71d815493
--- /dev/null
+++ b/trunk/src/emu/devtempl.h
@@ -0,0 +1,327 @@
+/***************************************************************************
+
+ devtempl.h
+
+ Template include for defining devices.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+****************************************************************************
+
+ Typical usage is as follows:
+
+static const char DEVTEMPLATE_SOURCE[] = __FILE__;
+
+// for a primary device....
+#define DEVTEMPLATE_ID(p,s) p##devicenameprefix##s
+#define DEVTEMPLATE_FEATURES DT_HAS_xxx | DT_HAS_yyy | ...
+#define DEVTEMPLATE_NAME "Device Name String"
+#include "devtempl.h"
+
+// for a derived device....
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##derivednameprefix##s
+#define DEVTEMPLATE_DERIVED_FEATURES DT_HAS_xxx | DT_HAS_yyy | ...
+#define DEVTEMPLATE_NAME "Derived Name String"
+#include "devtempl.h"
+
+****************************************************************************
+
+ Parameters are as follows:
+
+ DEVTEMPLATE_ID(p,s) - required - macro to produce device function and
+ type names with a prefix of 'p' and a suffix of 's'
+
+ DEVTEMPLATE_FEATURES - required - bitmask consisting of one of the
+ DT_HAS_* flags, indicating which standard-named callbacks or
+ pointers are specified by this device (everything else is assumed
+ to be NULL, which is the default)
+
+ DEVTEMPLATE_NAME - required - a string describing the device
+
+ DEVTEMPLATE_STATE - optional - the name of the device's state
+ structure; by default, this is assumed to be
+ DEVTEMPLATE_ID(,_state)
+
+***************************************************************************/
+
+
+#define DEVTEMPLATE_ID1(x) DEVTEMPLATE_ID(x,)
+#define DEVTEMPLATE_DERIVED_ID1(x) DEVTEMPLATE_DERIVED_ID(x,)
+
+/* flag bits for DEVTEMPLATE_FEATURES */
+#define DT_HAS_START 0x0001
+#define DT_HAS_RESET 0x0002
+#define DT_HAS_STOP 0x0004
+#define DT_HAS_EXECUTE 0x0008
+#define DT_HAS_NVRAM 0x0010
+#define DT_HAS_CUSTOM_CONFIG 0x0040
+#define DT_HAS_ROM_REGION 0x0080
+#define DT_HAS_MACHINE_CONFIG 0x0100
+#define DT_HAS_INLINE_CONFIG 0x0200
+#define DT_HAS_PROGRAM_SPACE 0x1000
+#define DT_HAS_DATA_SPACE 0x2000
+#define DT_HAS_IO_SPACE 0x4000
+
+
+/* verify core stuff is specified */
+#ifndef DEVTEMPLATE_ID
+#error DEVTEMPLATE_ID must be specified!
+#endif
+
+#ifndef DEVTEMPLATE_FEATURES
+#error DEVTEMPLATE_FEATURES must be specified!
+#endif
+
+#if (((DEVTEMPLATE_FEATURES) & DT_HAS_START) == 0)
+#error Device start routine is required!
+#endif
+
+#ifndef DEVTEMPLATE_NAME
+#error DEVTEMPLATE_NAME must be specified!
+#endif
+
+#if (((DEVTEMPLATE_FEATURES) & (DT_HAS_PROGRAM_SPACE | DT_HAS_DATA_SPACE | DT_HAS_IO_SPACE)) != 0)
+#ifndef DEVTEMPLATE_ENDIANNESS
+#error DEVTEMPLATE_ENDIANNESS must be specified if an address space is present!
+#endif
+#endif
+
+#ifdef DEVTEMPLATE_DERIVED_FEATURES
+#ifndef DEVTEMPLATE_DERIVED_NAME
+#error DEVTEMPLATE_DERIVED_NAME must be specified!
+#endif
+#endif
+
+
+/* primary device case */
+#ifndef DEVTEMPLATE_DERIVED_FEATURES
+
+/* derive standard state name (unless explicitly provided) */
+#ifndef DEVTEMPLATE_STATE
+#define DEVTEMPLATE_STATE DEVTEMPLATE_ID(,_state)
+#endif
+
+/* default to version 1.0 */
+#ifndef DEVTEMPLATE_VERSION
+#define DEVTEMPLATE_VERSION "1.0"
+#endif
+
+/* default to the standard copyright attribution */
+#ifndef DEVTEMPLATE_CREDITS
+#define DEVTEMPLATE_CREDITS "Copyright Nicola Salmoria and the MAME Team"
+#endif
+
+/* declare callback functions */
+static DEVICE_START( DEVTEMPLATE_ID(,) );
+#if ((DEVTEMPLATE_FEATURES) & DT_HAS_RESET)
+static DEVICE_RESET( DEVTEMPLATE_ID(,) );
+#endif
+#if ((DEVTEMPLATE_FEATURES) & DT_HAS_STOP)
+static DEVICE_STOP( DEVTEMPLATE_ID(,) );
+#endif
+#if ((DEVTEMPLATE_FEATURES) & DT_HAS_EXECUTE)
+static DEVICE_EXECUTE( DEVTEMPLATE_ID(,) );
+#endif
+#if ((DEVTEMPLATE_FEATURES) & DT_HAS_NVRAM)
+static DEVICE_NVRAM( DEVTEMPLATE_ID(,) );
+#endif
+#if ((DEVTEMPLATE_FEATURES) & DT_HAS_CUSTOM_CONFIG)
+static DEVICE_CUSTOM_CONFIG( DEVTEMPLATE_ID(,) );
+#endif
+
+/* the actual get_info function */
+DEVICE_GET_INFO( DEVTEMPLATE_ID(,) )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(DEVTEMPLATE_STATE); break;
+#if ((DEVTEMPLATE_FEATURES) & DT_HAS_INLINE_CONFIG)
+ case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = sizeof(DEVTEMPLATE_ID(,_config)); break;
+#endif
+#ifdef DEVTEMPLATE_ENDIANNESS
+ case DEVINFO_INT_ENDIANNESS: info->i = DEVTEMPLATE_ENDIANNESS; break;
+#endif
+#if ((DEVTEMPLATE_FEATURES) & DT_HAS_PROGRAM_SPACE)
+ case DEVINFO_INT_DATABUS_WIDTH_0: info->i = DEVTEMPLATE_PGM_DATAWIDTH; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH_0: info->i = DEVTEMPLATE_PGM_ADDRWIDTH; break;
+#ifdef DEVTEMPLATE_PGM_ADDRSHIFT
+ case DEVINFO_INT_ADDRBUS_SHIFT_0: info->i = DEVTEMPLATE_PGM_ADDRSHIFT; break;
+#endif
+#endif
+#if ((DEVTEMPLATE_FEATURES) & DT_HAS_DATA_SPACE)
+ case DEVINFO_INT_DATABUS_WIDTH_1: info->i = DEVTEMPLATE_DATA_DATAWIDTH; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH_1: info->i = DEVTEMPLATE_DATA_ADDRWIDTH; break;
+#ifdef DEVTEMPLATE_DATA_ADDRSHIFT
+ case DEVINFO_INT_ADDRBUS_SHIFT_1: info->i = DEVTEMPLATE_DATA_ADDRSHIFT; break;
+#endif
+#endif
+#if ((DEVTEMPLATE_FEATURES) & DT_HAS_IO_SPACE)
+ case DEVINFO_INT_DATABUS_WIDTH_2: info->i = DEVTEMPLATE_IO_DATAWIDTH; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH_2: info->i = DEVTEMPLATE_IO_ADDRWIDTH; break;
+#ifdef DEVTEMPLATE_IO_ADDRSHIFT
+ case DEVINFO_INT_ADDRBUS_SHIFT_2: info->i = DEVTEMPLATE_IO_ADDRSHIFT; break;
+#endif
+#endif
+
+ /* --- the following bits of info are returned as pointers --- */
+#if ((DEVTEMPLATE_FEATURES) & DT_HAS_ROM_REGION)
+ case DEVINFO_PTR_ROM_REGION: info->romregion = DEVTEMPLATE_ID1(ROM_NAME()); break;
+#endif
+#if ((DEVTEMPLATE_FEATURES) & DT_HAS_MACHINE_CONFIG)
+ case DEVINFO_PTR_MACHINE_CONFIG: info->machine_config = DEVTEMPLATE_ID1(MACHINE_CONFIG_NAME()); break;
+#endif
+#if ((DEVTEMPLATE_FEATURES) & DT_HAS_PROGRAM_SPACE)
+#ifdef DEVTEMPLATE_PGM_INTMAP
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP_0: info->p = (void *)DEVTEMPLATE_PGM_INTMAP; break;
+#endif
+#ifdef DEVTEMPLATE_PGM_DEFMAP
+ case DEVINFO_PTR_DEFAULT_MEMORY_MAP_0: info->p = (void *)DEVTEMPLATE_PGM_DEFMAP; break;
+#endif
+#endif
+#if ((DEVTEMPLATE_FEATURES) & DT_HAS_DATA_SPACE)
+#ifdef DEVTEMPLATE_DATA_INTMAP
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP_0: info->p = (void *)DEVTEMPLATE_DATA_INTMAP; break;
+#endif
+#ifdef DEVTEMPLATE_DATA_DEFMAP
+ case DEVINFO_PTR_DEFAULT_MEMORY_MAP_0: info->p = (void *)DEVTEMPLATE_DATA_DEFMAP; break;
+#endif
+#endif
+#if ((DEVTEMPLATE_FEATURES) & DT_HAS_IO_SPACE)
+#ifdef DEVTEMPLATE_IO_INTMAP
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP_0: info->p = (void *)DEVTEMPLATE_IO_INTMAP; break;
+#endif
+#ifdef DEVTEMPLATE_IO_DEFMAP
+ case DEVINFO_PTR_DEFAULT_MEMORY_MAP_0: info->p = (void *)DEVTEMPLATE_IO_DEFMAP; break;
+#endif
+#endif
+
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+#if ((DEVTEMPLATE_FEATURES) & DT_HAS_START)
+ case DEVINFO_FCT_START: info->start = DEVTEMPLATE_ID1(DEVICE_START_NAME()); break;
+#endif
+#if ((DEVTEMPLATE_FEATURES) & DT_HAS_RESET)
+ case DEVINFO_FCT_RESET: info->reset = DEVTEMPLATE_ID1(DEVICE_RESET_NAME()); break;
+#endif
+#if ((DEVTEMPLATE_FEATURES) & DT_HAS_STOP)
+ case DEVINFO_FCT_STOP: info->stop = DEVTEMPLATE_ID1(DEVICE_STOP_NAME()); break;
+#endif
+#if ((DEVTEMPLATE_FEATURES) & DT_HAS_EXECUTE)
+ case DEVINFO_FCT_EXECUTE: info->execute = DEVTEMPLATE_ID1(DEVICE_EXECUTE_NAME()); break;
+#endif
+#if ((DEVTEMPLATE_FEATURES) & DT_HAS_NVRAM)
+ case DEVINFO_FCT_NVRAM: info->nvram = DEVTEMPLATE_ID1(DEVICE_NVRAM_NAME()); break;
+#endif
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, DEVTEMPLATE_NAME); break;
+#ifdef DEVTEMPLATE_SHORTNAME
+ case DEVINFO_STR_SHORTNAME: strcpy(info->s, DEVTEMPLATE_SHORTNAME); break;
+#endif
+ }
+}
+
+
+/* derived device case */
+#else
+
+/* declare callback functions */
+#if ((DEVTEMPLATE_DERIVED_FEATURES) & DT_HAS_START)
+static DEVICE_START( DEVTEMPLATE_DERIVED_ID(,) );
+#endif
+#if ((DEVTEMPLATE_DERIVED_FEATURES) & DT_HAS_RESET)
+static DEVICE_RESET( DEVTEMPLATE_DERIVED_ID(,) );
+#endif
+#if ((DEVTEMPLATE_DERIVED_FEATURES) & DT_HAS_STOP)
+static DEVICE_STOP( DEVTEMPLATE_DERIVED_ID(,) );
+#endif
+#if ((DEVTEMPLATE_DERIVED_FEATURES) & DT_HAS_EXECUTE)
+static DEVICE_EXECUTE( DEVTEMPLATE_DERIVED_ID(,) );
+#endif
+#if ((DEVTEMPLATE_DERIVED_FEATURES) & DT_HAS_NVRAM)
+static DEVICE_NVRAM( DEVTEMPLATE_DERIVED_ID(,) );
+#endif
+#if ((DEVTEMPLATE_DERIVED_FEATURES) & DT_HAS_CUSTOM_CONFIG)
+static DEVICE_CUSTOM_CONFIG( DEVTEMPLATE_DERIVED_ID(,) );
+#endif
+
+/* the actual get_info function */
+DEVICE_GET_INFO( DEVTEMPLATE_DERIVED_ID(,) )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+#if ((DEVTEMPLATE_DERIVED_FEATURES) & DT_HAS_PROGRAM_SPACE)
+ case DEVINFO_INT_DATABUS_WIDTH_0: info->i = DEVTEMPLATE_DERIVED_PGM_DATAWIDTH; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH_0: info->i = DEVTEMPLATE_DERIVED_PGM_ADDRWIDTH; break;
+#ifdef DEVTEMPLATE_PGM_ADDRSHIFT
+ case DEVINFO_INT_ADDRBUS_SHIFT_0: info->i = DEVTEMPLATE_DERIVED_PGM_ADDRSHIFT; break;
+#endif
+#endif
+#if ((DEVTEMPLATE_DERIVED_FEATURES) & DT_HAS_DATA_SPACE)
+ case DEVINFO_INT_DATABUS_WIDTH_1: info->i = DEVTEMPLATE_DERIVED_DATA_DATAWIDTH; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH_1: info->i = DEVTEMPLATE_DERIVED_DATA_ADDRWIDTH; break;
+#ifdef DEVTEMPLATE_DATA_ADDRSHIFT
+ case DEVINFO_INT_ADDRBUS_SHIFT_1: info->i = DEVTEMPLATE_DERIVED_DATA_ADDRSHIFT; break;
+#endif
+#endif
+#if ((DEVTEMPLATE_DERIVED_FEATURES) & DT_HAS_IO_SPACE)
+ case DEVINFO_INT_DATABUS_WIDTH_2: info->i = DEVTEMPLATE_DERIVED_IO_DATAWIDTH; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH_2: info->i = DEVTEMPLATE_DERIVED_IO_ADDRWIDTH; break;
+#ifdef DEVTEMPLATE_IO_ADDRSHIFT
+ case DEVINFO_INT_ADDRBUS_SHIFT_2: info->i = DEVTEMPLATE_DERIVED_IO_ADDRSHIFT; break;
+#endif
+#endif
+
+ /* --- the following bits of info are returned as pointers --- */
+#if ((DEVTEMPLATE_DERIVED_FEATURES) & DT_HAS_ROM_REGION)
+ case DEVINFO_PTR_ROM_REGION: info->romregion = DEVTEMPLATE_DERIVED_ID1(ROM_NAME()); break;
+#endif
+#if ((DEVTEMPLATE_DERIVED_FEATURES) & DT_HAS_MACHINE_CONFIG)
+ case DEVINFO_PTR_MACHINE_CONFIG: info->machine_config = DEVTEMPLATE_DERIVED_ID1(MACHINE_CONFIG_NAME()); break;
+#endif
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+#if ((DEVTEMPLATE_DERIVED_FEATURES) & DT_HAS_START)
+ case DEVINFO_FCT_START: info->start = DEVTEMPLATE_DERIVED_ID1(DEVICE_START_NAME()); break;
+#endif
+#if ((DEVTEMPLATE_DERIVED_FEATURES) & DT_HAS_RESET)
+ case DEVINFO_FCT_RESET: info->reset = DEVTEMPLATE_DERIVED_ID1(DEVICE_RESET_NAME()); break;
+#endif
+#if ((DEVTEMPLATE_DERIVED_FEATURES) & DT_HAS_STOP)
+ case DEVINFO_FCT_STOP: info->stop = DEVTEMPLATE_DERIVED_ID1(DEVICE_STORE_NAME()); break;
+#endif
+#if ((DEVTEMPLATE_DERIVED_FEATURES) & DT_HAS_EXECUTE)
+ case DEVINFO_FCT_EXECUTE: info->execute = DEVTEMPLATE_DERIVED_ID1(DEVICE_EXECUTE_NAME()); break;
+#endif
+#if ((DEVTEMPLATE_DERIVED_FEATURES) & DT_HAS_NVRAM)
+ case DEVINFO_FCT_NVRAM: info->nvram = DEVTEMPLATE_DERIVED_ID1(DEVICE_NVRAM_NAME()); break;
+#endif
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, DEVTEMPLATE_DERIVED_NAME); break;
+ default: DEVICE_GET_INFO_CALL(DEVTEMPLATE_ID(,)); break;
+ }
+}
+
+#endif
+
+
+
+#undef DT_HAS_RESET
+#undef DT_HAS_STOP
+#undef DT_HAS_EXECUTE
+#undef DT_HAS_NVRAM
+#undef DT_HAS_CUSTOM_CONFIG
+#undef DT_HAS_ROM_REGION
+#undef DT_HAS_MACHINE_CONFIG
+#undef DT_HAS_INLINE_CONFIG
+#undef DT_HAS_PROGRAM_SPACE
+#undef DT_HAS_DATA_SPACE
+#undef DT_HAS_IO_SPACE
+
+#undef DEVTEMPLATE_DERIVED_ID
+#undef DEVTEMPLATE_DERIVED_FEATURES
+#undef DEVTEMPLATE_DERIVED_NAME
diff --git a/trunk/src/emu/didisasm.c b/trunk/src/emu/didisasm.c
new file mode 100644
index 00000000000..0ea48b8b3d0
--- /dev/null
+++ b/trunk/src/emu/didisasm.c
@@ -0,0 +1,63 @@
+/***************************************************************************
+
+ didisasm.c
+
+ Device disasm interfaces.
+
+****************************************************************************
+
+ 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"
+
+
+//**************************************************************************
+// DEVICE DISASM INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_disasm_interface - constructor
+//-------------------------------------------------
+
+device_disasm_interface::device_disasm_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device)
+{
+}
+
+
+//-------------------------------------------------
+// ~device_disasm_interface - destructor
+//-------------------------------------------------
+
+device_disasm_interface::~device_disasm_interface()
+{
+}
diff --git a/trunk/src/emu/didisasm.h b/trunk/src/emu/didisasm.h
new file mode 100644
index 00000000000..f6debcb4cdf
--- /dev/null
+++ b/trunk/src/emu/didisasm.h
@@ -0,0 +1,102 @@
+/***************************************************************************
+
+ didisasm.h
+
+ Device disassembly interfaces.
+
+****************************************************************************
+
+ 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 __DIDISASM_H__
+#define __DIDISASM_H__
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// Disassembler constants
+const UINT32 DASMFLAG_SUPPORTED = 0x80000000; // are disassembly flags supported?
+const UINT32 DASMFLAG_STEP_OUT = 0x40000000; // this instruction should be the end of a step out sequence
+const UINT32 DASMFLAG_STEP_OVER = 0x20000000; // this instruction should be stepped over by setting a breakpoint afterwards
+const UINT32 DASMFLAG_OVERINSTMASK = 0x18000000; // number of extra instructions to skip when stepping over
+const UINT32 DASMFLAG_OVERINSTSHIFT = 27; // bits to shift after masking to get the value
+const UINT32 DASMFLAG_LENGTHMASK = 0x0000ffff; // the low 16-bits contain the actual length
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+#define DASMFLAG_STEP_OVER_EXTRA(x) ((x) << DASMFLAG_OVERINSTSHIFT)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> device_disasm_interface
+
+// class representing interface-specific live disasm
+class device_disasm_interface : public device_interface
+{
+public:
+ // construction/destruction
+ device_disasm_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_disasm_interface();
+
+ // configuration access
+ UINT32 min_opcode_bytes() const { return disasm_min_opcode_bytes(); }
+ UINT32 max_opcode_bytes() const { return disasm_max_opcode_bytes(); }
+
+ // interface for disassembly
+ offs_t disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options = 0) { return disasm_disassemble(buffer, pc, oprom, opram, options); }
+
+protected:
+ // required operation overrides
+ virtual UINT32 disasm_min_opcode_bytes() const = 0;
+ virtual UINT32 disasm_max_opcode_bytes() const = 0;
+ virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) = 0;
+};
+
+
+#endif /* __DIDISASM_H__ */
diff --git a/trunk/src/emu/diexec.c b/trunk/src/emu/diexec.c
new file mode 100644
index 00000000000..f72cb7d4049
--- /dev/null
+++ b/trunk/src/emu/diexec.c
@@ -0,0 +1,1001 @@
+/***************************************************************************
+
+ diexec.c
+
+ Device execution interfaces.
+
+****************************************************************************
+
+ 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 "profiler.h"
+#include "debugger.h"
+
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+#define TEMPLOG 0
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+const int TRIGGER_INT = -2000;
+const int TRIGGER_SUSPENDTIME = -4000;
+
+
+
+//**************************************************************************
+// EXECUTING DEVICE CONFIG
+//**************************************************************************
+
+//-------------------------------------------------
+// device_execute_interface - constructor
+//-------------------------------------------------
+
+device_execute_interface::device_execute_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device),
+ m_cothread(cothread_entry_delegate(FUNC(device_execute_interface::run_thread_wrapper), this)),
+ m_disabled(false),
+ m_vblank_interrupt(NULL),
+ m_vblank_interrupts_per_frame(0),
+ m_vblank_interrupt_screen(NULL),
+ m_timed_interrupt(NULL),
+ m_timed_interrupt_period(attotime::zero),
+ m_nextexec(NULL),
+ m_driver_irq(0),
+ m_timedint_timer(NULL),
+ m_iloops(0),
+ m_partial_frame_timer(NULL),
+ m_profiler(PROFILER_IDLE),
+ m_icountptr(NULL),
+ m_cycles_running(0),
+ m_cycles_stolen(0),
+ m_suspend(0),
+ m_nextsuspend(0),
+ m_eatcycles(0),
+ m_nexteatcycles(0),
+ m_trigger(0),
+ m_inttrigger(0),
+ m_totalcycles(0),
+ m_divisor(0),
+ m_divshift(0),
+ m_cycles_per_second(0),
+ m_attoseconds_per_cycle(0)
+{
+ memset(&m_localtime, 0, sizeof(m_localtime));
+
+ // configure the fast accessor
+ device.m_execute = this;
+}
+
+
+//-------------------------------------------------
+// device_execute_interface - destructor
+//-------------------------------------------------
+
+device_execute_interface::~device_execute_interface()
+{
+}
+
+
+//-------------------------------------------------
+// static_set_disable - configuration helper to
+// set the disabled state of a device
+//-------------------------------------------------
+
+void device_execute_interface::static_set_disable(device_t &device)
+{
+ device_execute_interface *exec;
+ if (!device.interface(exec))
+ throw emu_fatalerror("MCFG_DEVICE_DISABLE called on device '%s' with no execute interface", device.tag());
+ exec->m_disabled = true;
+}
+
+
+//-------------------------------------------------
+// static_set_vblank_int - configuration helper
+// to set up VBLANK interrupts on the device
+//-------------------------------------------------
+
+void device_execute_interface::static_set_vblank_int(device_t &device, device_interrupt_func function, const char *tag, int rate)
+{
+ device_execute_interface *exec;
+ if (!device.interface(exec))
+ throw emu_fatalerror("MCFG_DEVICE_VBLANK_INT called on device '%s' with no execute interface", device.tag());
+ exec->m_vblank_interrupt = function;
+ exec->m_vblank_interrupts_per_frame = rate;
+ exec->m_vblank_interrupt_screen = tag;
+}
+
+
+//-------------------------------------------------
+// static_set_periodic_int - configuration helper
+// to set up periodic interrupts on the device
+//-------------------------------------------------
+
+void device_execute_interface::static_set_periodic_int(device_t &device, device_interrupt_func function, attotime rate)
+{
+ device_execute_interface *exec;
+ if (!device.interface(exec))
+ throw emu_fatalerror("MCFG_DEVICE_PERIODIC_INT called on device '%s' with no execute interface", device.tag());
+ exec->m_timed_interrupt = function;
+ exec->m_timed_interrupt_period = rate;
+}
+
+
+//-------------------------------------------------
+// executing - return true if this device is
+// within its execute function
+//-------------------------------------------------
+
+bool device_execute_interface::executing() const
+{
+ return (this == device().machine().scheduler().currently_executing());
+}
+
+
+//-------------------------------------------------
+// cycles_remaining - return the number of cycles
+// remaining in this timeslice
+//-------------------------------------------------
+
+INT32 device_execute_interface::cycles_remaining() const
+{
+ return executing() ? *m_icountptr : 0;
+}
+
+
+//-------------------------------------------------
+// eat_cycles - safely eats cycles so we don't
+// cross a timeslice boundary
+//-------------------------------------------------
+
+void device_execute_interface::eat_cycles(int cycles)
+{
+ // ignore if not the executing device
+ if (!executing())
+ return;
+
+ // clamp cycles to the icount and update
+ if (cycles > *m_icountptr)
+ cycles = *m_icountptr;
+ *m_icountptr -= cycles;
+}
+
+
+//-------------------------------------------------
+// adjust_icount - apply a +/- to the current
+// icount
+//-------------------------------------------------
+
+void device_execute_interface::adjust_icount(int delta)
+{
+ // ignore if not the executing device
+ if (!executing())
+ return;
+
+ // aply the delta directly
+ *m_icountptr += delta;
+}
+
+
+//-------------------------------------------------
+// abort_timeslice - abort execution for the
+// current timeslice, allowing other devices to
+// run before we run again
+//-------------------------------------------------
+
+void device_execute_interface::abort_timeslice()
+{
+ // ignore if not the executing device
+ if (this != device().machine().scheduler().currently_executing())
+ return;
+
+ // swallow the remaining cycles
+ if (m_icountptr != NULL)
+ {
+ int delta = *m_icountptr;
+ m_cycles_stolen += delta;
+ m_cycles_running -= delta;
+ *m_icountptr -= delta;
+ }
+}
+
+
+//-------------------------------------------------
+// set_irq_callback - install a driver-specific
+// callback for IRQ acknowledge
+//-------------------------------------------------
+
+void device_execute_interface::set_irq_callback(device_irq_callback callback)
+{
+ m_driver_irq = callback;
+}
+
+
+//-------------------------------------------------
+// suspend - set a suspend reason for this device
+//-------------------------------------------------
+
+void device_execute_interface::suspend(UINT32 reason, bool eatcycles)
+{
+if (TEMPLOG) printf("suspend %s (%X)\n", device().tag(), reason);
+ // set the suspend reason and eat cycles flag
+ m_nextsuspend |= reason;
+ m_nexteatcycles = eatcycles;
+
+ // if we're active, synchronize
+ abort_timeslice();
+}
+
+
+//-------------------------------------------------
+// resume - clear a suspend reason for this
+// device
+//-------------------------------------------------
+
+void device_execute_interface::resume(UINT32 reason)
+{
+if (TEMPLOG) printf("resume %s (%X)\n", device().tag(), reason);
+ // clear the suspend reason and eat cycles flag
+ m_nextsuspend &= ~reason;
+
+ // if we're active, synchronize
+ abort_timeslice();
+}
+
+
+//-------------------------------------------------
+// spin_until_time - burn cycles for a specific
+// period of time
+//-------------------------------------------------
+
+void device_execute_interface::spin_until_time(attotime duration)
+{
+ static int timetrig = 0;
+
+ // suspend until the given trigger fires
+ suspend_until_trigger(TRIGGER_SUSPENDTIME + timetrig, true);
+
+ // then set a timer for it
+ device().machine().scheduler().timer_set(duration, FUNC(static_timed_trigger_callback), TRIGGER_SUSPENDTIME + timetrig, this);
+ timetrig = (timetrig + 1) % 256;
+}
+
+
+//-------------------------------------------------
+// suspend_until_trigger - suspend execution
+// until the given trigger fires
+//-------------------------------------------------
+
+void device_execute_interface::suspend_until_trigger(int trigid, bool eatcycles)
+{
+ // suspend the device immediately if it's not already
+ suspend(SUSPEND_REASON_TRIGGER, eatcycles);
+
+ // set the trigger
+ m_trigger = trigid;
+}
+
+
+//-------------------------------------------------
+// trigger - respond to a trigger event
+//-------------------------------------------------
+
+void device_execute_interface::trigger(int trigid)
+{
+ // if we're executing, for an immediate abort
+ abort_timeslice();
+
+ // see if this is a matching trigger
+ if ((m_nextsuspend & SUSPEND_REASON_TRIGGER) != 0 && m_trigger == trigid)
+ {
+ resume(SUSPEND_REASON_TRIGGER);
+ m_trigger = 0;
+ }
+}
+
+
+//-------------------------------------------------
+// local_time - returns the current local time
+// for a device
+//-------------------------------------------------
+
+attotime device_execute_interface::local_time() const
+{
+ // if we're active, add in the time from the current slice
+ attotime result = m_localtime;
+ if (executing())
+ {
+ assert(m_cycles_running >= *m_icountptr);
+ int cycles = m_cycles_running - *m_icountptr;
+ result += cycles_to_attotime(cycles);
+ }
+ return result;
+}
+
+
+//-------------------------------------------------
+// total_cycles - return the total number of
+// cycles executed on this device
+//-------------------------------------------------
+
+UINT64 device_execute_interface::total_cycles() const
+{
+ if (executing())
+ {
+ assert(m_cycles_running >= *m_icountptr);
+ return m_totalcycles + m_cycles_running - *m_icountptr;
+ }
+ else
+ return m_totalcycles;
+}
+
+
+//-------------------------------------------------
+// run_thread_wrapper - wrapper for our cothread
+// which just calls run and then returns to the
+// scheduler thread, over and over
+//-------------------------------------------------
+
+void device_execute_interface::run_thread_wrapper()
+{
+ // loop infinitely
+ device_scheduler &scheduler = device().machine().scheduler();
+ while (1)
+ {
+ // call the classic run function, then swap back to the scheduler's thread
+ execute_run();
+ scheduler.make_active();
+ }
+}
+
+
+//-------------------------------------------------
+// execute_clocks_to_cycles - convert the number
+// of clocks to cycles, rounding down if necessary
+//-------------------------------------------------
+
+UINT64 device_execute_interface::execute_clocks_to_cycles(UINT64 clocks) const
+{
+ return clocks;
+}
+
+
+//-------------------------------------------------
+// execute_cycles_to_clocks - convert the number
+// of cycles to clocks, rounding down if necessary
+//-------------------------------------------------
+
+UINT64 device_execute_interface::execute_cycles_to_clocks(UINT64 cycles) const
+{
+ return cycles;
+}
+
+
+//-------------------------------------------------
+// execute_min_cycles - return the smallest number
+// of cycles that a single instruction or
+// operation can take
+//-------------------------------------------------
+
+UINT32 device_execute_interface::execute_min_cycles() const
+{
+ return 1;
+}
+
+
+//-------------------------------------------------
+// execute_max_cycles - return the maximum number
+// of cycles that a single instruction or
+// operation can take
+//-------------------------------------------------
+
+UINT32 device_execute_interface::execute_max_cycles() const
+{
+ return 1;
+}
+
+
+//-------------------------------------------------
+// execute_input_lines - return the total number
+// of input lines for the device
+//-------------------------------------------------
+
+UINT32 device_execute_interface::execute_input_lines() const
+{
+ return 0;
+}
+
+
+//-------------------------------------------------
+// execute_default_irq_vector - return the default
+// IRQ vector when an acknowledge is processed
+//-------------------------------------------------
+
+UINT32 device_execute_interface::execute_default_irq_vector() const
+{
+ return 0;
+}
+
+
+//-------------------------------------------------
+// execute_burn - called after we consume a bunch
+// of cycles for artifical reasons (such as
+// spinning devices for performance optimization)
+//-------------------------------------------------
+
+void device_execute_interface::execute_burn(INT32 cycles)
+{
+ // by default, do nothing
+}
+
+
+//-------------------------------------------------
+// execute_set_input - called when a synchronized
+// input is changed
+//-------------------------------------------------
+
+void device_execute_interface::execute_set_input(int linenum, int state)
+{
+ // by default, do nothing
+}
+
+
+//-------------------------------------------------
+// interface_validity_check - validation for a
+// device after the configuration has been
+// constructed
+//-------------------------------------------------
+
+bool device_execute_interface::interface_validity_check(emu_options &options, const game_driver &driver) const
+{
+ bool error = false;
+
+ /* validate the interrupts */
+ if (m_vblank_interrupt != NULL)
+ {
+ if (device().mconfig().devicelist().count(SCREEN) == 0)
+ {
+ mame_printf_error("%s: %s device '%s' has a VBLANK interrupt, but the driver is screenless!\n", driver.source_file, driver.name, device().tag());
+ error = true;
+ }
+ else if (m_vblank_interrupt_screen != NULL && m_vblank_interrupts_per_frame != 0)
+ {
+ mame_printf_error("%s: %s device '%s' has a new VBLANK interrupt handler with >1 interrupts!\n", driver.source_file, driver.name, device().tag());
+ error = true;
+ }
+ else if (m_vblank_interrupt_screen != NULL && device().mconfig().devicelist().find(m_vblank_interrupt_screen) == NULL)
+ {
+ mame_printf_error("%s: %s device '%s' VBLANK interrupt with a non-existant screen tag (%s)!\n", driver.source_file, driver.name, device().tag(), m_vblank_interrupt_screen);
+ error = true;
+ }
+ else if (m_vblank_interrupt_screen == NULL && m_vblank_interrupts_per_frame == 0)
+ {
+ mame_printf_error("%s: %s device '%s' has a VBLANK interrupt handler with 0 interrupts!\n", driver.source_file, driver.name, device().tag());
+ error = true;
+ }
+ }
+ else if (m_vblank_interrupts_per_frame != 0)
+ {
+ mame_printf_error("%s: %s device '%s' has no VBLANK interrupt handler but a non-0 interrupt count is given!\n", driver.source_file, driver.name, device().tag());
+ error = true;
+ }
+
+ if (m_timed_interrupt != NULL && m_timed_interrupt_period == attotime::zero)
+ {
+ mame_printf_error("%s: %s device '%s' has a timer interrupt handler with 0 period!\n", driver.source_file, driver.name, device().tag());
+ error = true;
+ }
+ else if (m_timed_interrupt == NULL && m_timed_interrupt_period != attotime::zero)
+ {
+ mame_printf_error("%s: %s device '%s' has a no timer interrupt handler but has a non-0 period given!\n", driver.source_file, driver.name, device().tag());
+ error = true;
+ }
+
+ return error;
+}
+
+
+//-------------------------------------------------
+// interface_pre_start - work to be done prior to
+// actually starting a device
+//-------------------------------------------------
+
+void device_execute_interface::interface_pre_start()
+{
+ // fill in the initial states
+ int index = device().machine().devicelist().indexof(m_device);
+ m_suspend = SUSPEND_REASON_RESET;
+ m_profiler = profile_type(index + PROFILER_DEVICE_FIRST);
+ m_inttrigger = index + TRIGGER_INT;
+
+ // fill in the input states and IRQ callback information
+ for (int line = 0; line < ARRAY_LENGTH(m_input); line++)
+ m_input[line].start(this, line);
+
+ // allocate timers if we need them
+ if (m_vblank_interrupts_per_frame > 1)
+ m_partial_frame_timer = device().machine().scheduler().timer_alloc(FUNC(static_trigger_partial_frame_interrupt), (void *)this);
+ if (m_timed_interrupt_period != attotime::zero)
+ m_timedint_timer = device().machine().scheduler().timer_alloc(FUNC(static_trigger_periodic_interrupt), (void *)this);
+
+ // register for save states
+ m_device.save_item(NAME(m_suspend));
+ m_device.save_item(NAME(m_nextsuspend));
+ m_device.save_item(NAME(m_eatcycles));
+ m_device.save_item(NAME(m_nexteatcycles));
+ m_device.save_item(NAME(m_trigger));
+ m_device.save_item(NAME(m_totalcycles));
+ m_device.save_item(NAME(m_localtime));
+ m_device.save_item(NAME(m_iloops));
+}
+
+
+//-------------------------------------------------
+// interface_post_start - work to be done after
+// actually starting a device
+//-------------------------------------------------
+
+void device_execute_interface::interface_post_start()
+{
+ // make sure somebody set us up the icount
+ assert_always(m_icountptr != NULL, "m_icountptr never initialized!");
+}
+
+
+//-------------------------------------------------
+// interface_pre_reset - work to be done prior to
+// actually resetting a device
+//-------------------------------------------------
+
+void device_execute_interface::interface_pre_reset()
+{
+ // reset the total number of cycles
+ m_totalcycles = 0;
+
+ // enable all devices (except for disabled devices)
+ if (!disabled())
+ resume(SUSPEND_ANY_REASON);
+ else
+ suspend(SUSPEND_REASON_DISABLE, true);
+}
+
+
+//-------------------------------------------------
+// interface_post_reset - work to be done after a
+// device is reset
+//-------------------------------------------------
+
+void device_execute_interface::interface_post_reset()
+{
+ // reset the interrupt vectors and queues
+ for (int line = 0; line < ARRAY_LENGTH(m_input); line++)
+ m_input[line].reset();
+
+ // reconfingure VBLANK interrupts
+ if (m_vblank_interrupts_per_frame > 0 || m_vblank_interrupt_screen != NULL)
+ {
+ // get the screen that will trigger the VBLANK
+
+ // new style - use screen tag directly
+ screen_device *screen;
+ if (m_vblank_interrupt_screen != NULL)
+ screen = downcast<screen_device *>(device().machine().device(m_vblank_interrupt_screen));
+
+ // old style 'hack' setup - use screen #0
+ else
+ screen = device().machine().first_screen();
+
+ assert(screen != NULL);
+ screen->register_vblank_callback(vblank_state_delegate(FUNC(device_execute_interface::on_vblank), this));
+ }
+
+ // reconfigure periodic interrupts
+ if (m_timed_interrupt_period != attotime::zero)
+ {
+ attotime timedint_period = m_timed_interrupt_period;
+ assert(m_timedint_timer != NULL);
+ m_timedint_timer->adjust(timedint_period, 0, timedint_period);
+ }
+}
+
+
+//-------------------------------------------------
+// interface_clock_changed - recomputes clock
+// information for this device
+//-------------------------------------------------
+
+void device_execute_interface::interface_clock_changed()
+{
+ // recompute cps and spc
+ m_cycles_per_second = clocks_to_cycles(m_device.clock());
+ m_attoseconds_per_cycle = HZ_TO_ATTOSECONDS(m_cycles_per_second);
+
+ // update the device's divisor
+ INT64 attos = m_attoseconds_per_cycle;
+ m_divshift = 0;
+ while (attos >= (1UL << 31))
+ {
+ m_divshift++;
+ attos >>= 1;
+ }
+ m_divisor = attos;
+
+ // re-compute the perfect interleave factor
+ device().machine().scheduler().compute_perfect_interleave();
+}
+
+
+//-------------------------------------------------
+// static_standard_irq_callback - IRQ acknowledge
+// callback; handles HOLD_LINE case and signals
+// to the debugger
+//-------------------------------------------------
+
+IRQ_CALLBACK( device_execute_interface::static_standard_irq_callback )
+{
+ return device_execute(device)->standard_irq_callback(irqline);
+}
+
+int device_execute_interface::standard_irq_callback(int irqline)
+{
+ // get the default vector and acknowledge the interrupt if needed
+ int vector = m_input[irqline].default_irq_callback();
+ LOG(("static_standard_irq_callback('%s', %d) $%04x\n", m_device.tag(), irqline, vector));
+
+ // if there's a driver callback, run it to get the vector
+ if (m_driver_irq != NULL)
+ vector = (*m_driver_irq)(&m_device, irqline);
+
+ // notify the debugger
+ debugger_interrupt_hook(&m_device, irqline);
+ return vector;
+}
+
+
+//-------------------------------------------------
+// minimum_quantum - return the minimum quantum
+// required for this device
+//-------------------------------------------------
+
+attoseconds_t device_execute_interface::minimum_quantum() const
+{
+ // if we don't have that information, compute it
+ attoseconds_t basetick = m_attoseconds_per_cycle;
+ if (basetick == 0)
+ basetick = HZ_TO_ATTOSECONDS(clocks_to_cycles(m_device.clock()));
+
+ // apply the minimum cycle count
+ return basetick * min_cycles();
+}
+
+
+//-------------------------------------------------
+// static_timed_trigger_callback - signal a timed
+// trigger
+//-------------------------------------------------
+
+TIMER_CALLBACK( device_execute_interface::static_timed_trigger_callback )
+{
+ device_execute_interface *device = reinterpret_cast<device_execute_interface *>(ptr);
+ device->trigger(param);
+}
+
+
+//-------------------------------------------------
+// on_vblank - calls any external callbacks
+// for this screen
+//-------------------------------------------------
+
+void device_execute_interface::on_vblank(screen_device &screen, bool vblank_state)
+{
+ // ignore VBLANK end
+ if (!vblank_state)
+ return;
+
+ // start the interrupt counter
+ if (!suspended(SUSPEND_REASON_DISABLE))
+ m_iloops = 0;
+ else
+ m_iloops = -1;
+
+ // generate the interrupt callback
+ if (!suspended(SUSPEND_REASON_HALT | SUSPEND_REASON_RESET | SUSPEND_REASON_DISABLE))
+ (*m_vblank_interrupt)(&m_device);
+
+ // if we have more than one interrupt per frame, start the timer now to trigger the rest of them
+ if (m_vblank_interrupts_per_frame > 1 && !suspended(SUSPEND_REASON_DISABLE))
+ {
+ m_partial_frame_period = device().machine().primary_screen->frame_period() / m_vblank_interrupts_per_frame;
+ m_partial_frame_timer->adjust(m_partial_frame_period);
+ }
+}
+
+
+//-------------------------------------------------
+// static_trigger_partial_frame_interrupt -
+// called to trigger a partial frame interrupt
+//-------------------------------------------------
+
+TIMER_CALLBACK( device_execute_interface::static_trigger_partial_frame_interrupt )
+{
+ reinterpret_cast<device_execute_interface *>(ptr)->trigger_partial_frame_interrupt();
+}
+
+void device_execute_interface::trigger_partial_frame_interrupt()
+{
+ // when we hit 0, reset to the total count
+ if (m_iloops == 0)
+ m_iloops = m_vblank_interrupts_per_frame;
+
+ // count one more "iloop"
+ m_iloops--;
+
+ // call the interrupt handler if we're not suspended
+ if (!suspended(SUSPEND_REASON_HALT | SUSPEND_REASON_RESET | SUSPEND_REASON_DISABLE))
+ (*m_vblank_interrupt)(&m_device);
+
+ // set up to retrigger if there's more interrupts to generate
+ if (m_iloops > 1)
+ m_partial_frame_timer->adjust(m_partial_frame_period);
+}
+
+
+//-------------------------------------------------
+// static_trigger_periodic_interrupt - timer
+// callback for timed interrupts
+//-------------------------------------------------
+
+TIMER_CALLBACK( device_execute_interface::static_trigger_periodic_interrupt )
+{
+ reinterpret_cast<device_execute_interface *>(ptr)->trigger_periodic_interrupt();
+}
+
+void device_execute_interface::trigger_periodic_interrupt()
+{
+ // bail if there is no routine
+ if (m_timed_interrupt != NULL && !suspended(SUSPEND_REASON_HALT | SUSPEND_REASON_RESET | SUSPEND_REASON_DISABLE))
+ (*m_timed_interrupt)(&m_device);
+}
+
+
+
+//**************************************************************************
+// DEVICE INPUT
+//**************************************************************************
+
+//-------------------------------------------------
+// device_input - constructor
+//-------------------------------------------------
+
+device_execute_interface::device_input::device_input()
+ : m_execute(NULL),
+ m_device(NULL),
+ m_linenum(0),
+ m_stored_vector(0),
+ m_curvector(0),
+ m_curstate(CLEAR_LINE),
+ m_qindex(0)
+{
+ memset(m_queue, 0, sizeof(m_queue));
+}
+
+
+//-------------------------------------------------
+// start - called by interface_pre_start so we
+// can set ourselves up
+//-------------------------------------------------
+
+void device_execute_interface::device_input::start(device_execute_interface *execute, int linenum)
+{
+ m_execute = execute;
+ m_device = &m_execute->m_device;
+ m_linenum = linenum;
+
+ reset();
+
+ m_device->save_item(NAME(m_stored_vector), m_linenum);
+ m_device->save_item(NAME(m_curvector), m_linenum);
+ m_device->save_item(NAME(m_curstate), m_linenum);
+}
+
+
+//-------------------------------------------------
+// reset - reset our input states
+//-------------------------------------------------
+
+void device_execute_interface::device_input::reset()
+{
+ m_curvector = m_stored_vector = m_execute->default_irq_vector();
+ m_qindex = 0;
+}
+
+
+//-------------------------------------------------
+// set_state_synced - enqueue an event for later
+// execution via timer
+//-------------------------------------------------
+
+void device_execute_interface::device_input::set_state_synced(int state, int vector)
+{
+ LOG(("set_state_synced('%s',%d,%d,%02x)\n", m_device->tag(), m_linenum, state, vector));
+
+if (TEMPLOG) printf("setline(%s,%d,%d,%d)\n", m_device->tag(), m_linenum, state, (vector == USE_STORED_VECTOR) ? 0 : vector);
+ assert(state == ASSERT_LINE || state == HOLD_LINE || state == CLEAR_LINE || state == PULSE_LINE);
+
+ // treat PULSE_LINE as ASSERT+CLEAR
+ if (state == PULSE_LINE)
+ {
+ // catch errors where people use PULSE_LINE for devices that don't support it
+ if (m_linenum != INPUT_LINE_NMI && m_linenum != INPUT_LINE_RESET)
+ throw emu_fatalerror("device '%s': PULSE_LINE can only be used for NMI and RESET lines\n", m_device->tag());
+
+ set_state_synced(ASSERT_LINE, vector);
+ set_state_synced(CLEAR_LINE, vector);
+ return;
+ }
+
+ // if we're full of events, flush the queue and log a message
+ int event_index = m_qindex++;
+ if (event_index >= ARRAY_LENGTH(m_queue))
+ {
+ m_qindex--;
+ empty_event_queue();
+ event_index = m_qindex++;
+ logerror("Exceeded pending input line event queue on device '%s'!\n", m_device->tag());
+ }
+
+ // enqueue the event
+ if (event_index < ARRAY_LENGTH(m_queue))
+ {
+ if (vector == USE_STORED_VECTOR)
+ vector = m_stored_vector;
+ m_queue[event_index] = (state & 0xff) | (vector << 8);
+
+ // if this is the first one, set the timer
+ if (event_index == 0)
+ m_execute->device().machine().scheduler().synchronize(FUNC(static_empty_event_queue), 0, (void *)this);
+ }
+}
+
+
+//-------------------------------------------------
+// empty_event_queue - empty our event queue
+//-------------------------------------------------
+
+TIMER_CALLBACK( device_execute_interface::device_input::static_empty_event_queue )
+{
+ reinterpret_cast<device_input *>(ptr)->empty_event_queue();
+}
+
+void device_execute_interface::device_input::empty_event_queue()
+{
+if (TEMPLOG) printf("empty_queue(%s,%d,%d)\n", m_device->tag(), m_linenum, m_qindex);
+ // loop over all events
+ for (int curevent = 0; curevent < m_qindex; curevent++)
+ {
+ INT32 input_event = m_queue[curevent];
+
+ // set the input line state and vector
+ m_curstate = input_event & 0xff;
+ m_curvector = input_event >> 8;
+if (TEMPLOG) printf(" (%d,%d)\n", m_curstate, m_curvector);
+
+ assert(m_curstate == ASSERT_LINE || m_curstate == HOLD_LINE || m_curstate == CLEAR_LINE);
+
+ // special case: RESET
+ if (m_linenum == INPUT_LINE_RESET)
+ {
+ // if we're asserting the line, just halt the device
+ if (m_curstate == ASSERT_LINE)
+ m_execute->suspend(SUSPEND_REASON_RESET, true);
+
+ // if we're clearing the line that was previously asserted, reset the device
+ else if (m_execute->suspended(SUSPEND_REASON_RESET))
+ {
+ m_device->reset();
+ m_execute->resume(SUSPEND_REASON_RESET);
+ }
+ }
+
+ // special case: HALT
+ else if (m_linenum == INPUT_LINE_HALT)
+ {
+ // if asserting, halt the device
+ if (m_curstate == ASSERT_LINE)
+ m_execute->suspend(SUSPEND_REASON_HALT, true);
+
+ // if clearing, unhalt the device
+ else if (m_curstate == CLEAR_LINE)
+ m_execute->resume(SUSPEND_REASON_HALT);
+ }
+
+ // all other cases
+ else
+ {
+ // switch off the requested state
+ switch (m_curstate)
+ {
+ case HOLD_LINE:
+ case ASSERT_LINE:
+ m_execute->execute_set_input(m_linenum, ASSERT_LINE);
+ break;
+
+ case CLEAR_LINE:
+ m_execute->execute_set_input(m_linenum, CLEAR_LINE);
+ break;
+
+ default:
+ logerror("empty_event_queue device '%s', line %d, unknown state %d\n", m_device->tag(), m_linenum, m_curstate);
+ break;
+ }
+
+ // generate a trigger to unsuspend any devices waiting on the interrupt
+ if (m_curstate != CLEAR_LINE)
+ m_execute->signal_interrupt_trigger();
+ }
+ }
+
+ // reset counter
+ m_qindex = 0;
+}
+
+
+//-------------------------------------------------
+// default_irq_callback - the default IRQ
+// callback for this input line
+//-------------------------------------------------
+
+int device_execute_interface::device_input::default_irq_callback()
+{
+ int vector = m_curvector;
+
+ // if the IRQ state is HOLD_LINE, clear it
+ if (m_curstate == HOLD_LINE)
+ {
+ LOG(("->set_irq_line('%s',%d,%d)\n", m_device->tag(), m_linenum, CLEAR_LINE));
+ m_execute->execute_set_input(m_linenum, CLEAR_LINE);
+ m_curstate = CLEAR_LINE;
+ }
+ return vector;
+}
diff --git a/trunk/src/emu/diexec.h b/trunk/src/emu/diexec.h
new file mode 100644
index 00000000000..33cb3aff849
--- /dev/null
+++ b/trunk/src/emu/diexec.h
@@ -0,0 +1,475 @@
+/***************************************************************************
+
+ diexec.h
+
+ Device execution interfaces.
+
+****************************************************************************
+
+ 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 __DIEXEC_H__
+#define __DIEXEC_H__
+
+
+// set to 1 to execute on cothread instead of directly
+#define USE_COTHREADS 1
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// suspension reasons for executing devices
+const UINT32 SUSPEND_REASON_HALT = 0x0001; // HALT line set (or equivalent)
+const UINT32 SUSPEND_REASON_RESET = 0x0002; // RESET line set (or equivalent)
+const UINT32 SUSPEND_REASON_SPIN = 0x0004; // currently spinning
+const UINT32 SUSPEND_REASON_TRIGGER = 0x0008; // waiting for a trigger
+const UINT32 SUSPEND_REASON_DISABLE = 0x0010; // disabled (due to disable flag)
+const UINT32 SUSPEND_REASON_TIMESLICE = 0x0020; // waiting for the next timeslice
+const UINT32 SUSPEND_ANY_REASON = ~0; // all of the above
+
+
+// I/O line states
+enum line_state
+{
+ CLEAR_LINE = 0, // clear (a fired or held) line
+ ASSERT_LINE, // assert an interrupt immediately
+ HOLD_LINE, // hold interrupt line until acknowledged
+ PULSE_LINE // pulse interrupt line instantaneously (only for NMI, RESET)
+};
+
+
+// I/O line definitions
+enum
+{
+ // input lines
+ MAX_INPUT_LINES = 32+3,
+ INPUT_LINE_IRQ0 = 0,
+ INPUT_LINE_IRQ1 = 1,
+ INPUT_LINE_IRQ2 = 2,
+ INPUT_LINE_IRQ3 = 3,
+ INPUT_LINE_IRQ4 = 4,
+ INPUT_LINE_IRQ5 = 5,
+ INPUT_LINE_IRQ6 = 6,
+ INPUT_LINE_IRQ7 = 7,
+ INPUT_LINE_IRQ8 = 8,
+ INPUT_LINE_IRQ9 = 9,
+ INPUT_LINE_NMI = MAX_INPUT_LINES - 3,
+
+ // special input lines that are implemented in the core
+ INPUT_LINE_RESET = MAX_INPUT_LINES - 2,
+ INPUT_LINE_HALT = MAX_INPUT_LINES - 1
+};
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+// IRQ callback to be called by device implementations when an IRQ is actually taken
+#define IRQ_CALLBACK(func) int func(device_t *device, int irqline)
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_DEVICE_DISABLE() \
+ device_execute_interface::static_set_disable(*device); \
+
+#define MCFG_DEVICE_VBLANK_INT(_tag, _func) \
+ device_execute_interface::static_set_vblank_int(*device, _func, _tag); \
+
+#define MCFG_DEVICE_PERIODIC_INT(_func, _rate) \
+ device_execute_interface::static_set_periodic_int(*device, _func, attotime::from_hz(_rate)); \
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class emu_timer;
+class screen_device;
+
+
+// interrupt callback for VBLANK and timed interrupts
+typedef void (*device_interrupt_func)(device_t *device);
+
+// IRQ callback to be called by executing devices when an IRQ is actually taken
+typedef int (*device_irq_callback)(device_t *device, int irqnum);
+
+
+
+// ======================> device_execute_interface
+
+class device_execute_interface : public device_interface
+{
+ friend class device_scheduler;
+
+public:
+ // construction/destruction
+ device_execute_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_execute_interface();
+
+ // configuration access
+ bool disabled() const { return m_disabled; }
+ UINT64 clocks_to_cycles(UINT64 clocks) const { return execute_clocks_to_cycles(clocks); }
+ UINT64 cycles_to_clocks(UINT64 cycles) const { return execute_cycles_to_clocks(cycles); }
+ UINT32 min_cycles() const { return execute_min_cycles(); }
+ UINT32 max_cycles() const { return execute_max_cycles(); }
+ attotime cycles_to_attotime(UINT64 cycles) const { return device().clocks_to_attotime(cycles_to_clocks(cycles)); }
+ UINT64 attotime_to_cycles(attotime duration) const { return clocks_to_cycles(device().attotime_to_clocks(duration)); }
+ UINT32 input_lines() const { return execute_input_lines(); }
+ UINT32 default_irq_vector() const { return execute_default_irq_vector(); }
+
+ // static inline configuration helpers
+ static void static_set_disable(device_t &device);
+ static void static_set_vblank_int(device_t &device, device_interrupt_func function, const char *tag, int rate = 0);
+ static void static_set_periodic_int(device_t &device, device_interrupt_func function, attotime rate);
+
+ // execution management
+ bool executing() const;
+ INT32 cycles_remaining() const;
+ void eat_cycles(int cycles);
+ void adjust_icount(int delta);
+ void abort_timeslice();
+
+ // input and interrupt management
+ void set_input_line(int linenum, int state) { m_input[linenum].set_state_synced(state); }
+ void set_input_line_vector(int linenum, int vector) { m_input[linenum].set_vector(vector); }
+ void set_input_line_and_vector(int linenum, int state, int vector) { m_input[linenum].set_state_synced(state, vector); }
+ int input_state(int linenum) { return m_input[linenum].m_curstate; }
+ void set_irq_callback(device_irq_callback callback);
+
+ // deprecated, but still needed for older drivers
+ int iloops() const { return m_iloops; }
+
+ // suspend/resume
+ void suspend(UINT32 reason, bool eatcycles);
+ void resume(UINT32 reason);
+ bool suspended(UINT32 reason = SUSPEND_ANY_REASON) { return (m_nextsuspend & reason) != 0; }
+ void yield() { suspend(SUSPEND_REASON_TIMESLICE, false); }
+ void spin() { suspend(SUSPEND_REASON_TIMESLICE, true); }
+ void spin_until_trigger(int trigid) { suspend_until_trigger(trigid, true); }
+ void spin_until_time(attotime duration);
+ void spin_until_interrupt() { spin_until_trigger(m_inttrigger); }
+
+ // triggers
+ void suspend_until_trigger(int trigid, bool eatcycles);
+ void trigger(int trigid);
+ void signal_interrupt_trigger() { trigger(m_inttrigger); }
+
+ // time and cycle accounting
+ attotime local_time() const;
+ UINT64 total_cycles() const;
+
+ // required operation overrides
+#if USE_COTHREADS
+ void run() { m_cothread.make_active(); }
+#else
+ void run() { execute_run(); }
+#endif
+
+protected:
+ // internal helpers
+ void run_thread_wrapper();
+
+ // clock and cycle information getters
+ virtual UINT64 execute_clocks_to_cycles(UINT64 clocks) const;
+ virtual UINT64 execute_cycles_to_clocks(UINT64 cycles) const;
+ virtual UINT32 execute_min_cycles() const;
+ virtual UINT32 execute_max_cycles() const;
+
+ // input line information getters
+ virtual UINT32 execute_input_lines() const;
+ virtual UINT32 execute_default_irq_vector() const;
+
+ // optional operation overrides
+ virtual void execute_run() = 0;
+ virtual void execute_burn(INT32 cycles);
+ virtual void execute_set_input(int linenum, int state);
+
+ // interface-level overrides
+ virtual bool interface_validity_check(emu_options &options, const game_driver &driver) const;
+ virtual void interface_pre_start();
+ virtual void interface_post_start();
+ virtual void interface_pre_reset();
+ virtual void interface_post_reset();
+ virtual void interface_clock_changed();
+
+ // for use by devcpu for now...
+ static IRQ_CALLBACK( static_standard_irq_callback );
+ int standard_irq_callback(int irqline);
+
+ // internal information about the state of inputs
+ class device_input
+ {
+ static const int USE_STORED_VECTOR = 0xff000000;
+
+ public:
+ device_input();
+
+ void start(device_execute_interface *execute, int linenum);
+ void reset();
+
+ void set_state_synced(int state, int vector = USE_STORED_VECTOR);
+ void set_vector(int vector) { m_stored_vector = vector; }
+ int default_irq_callback();
+
+ device_execute_interface *m_execute;// pointer to the execute interface
+ device_t * m_device; // pointer to our device
+ int m_linenum; // which input line we are
+
+ INT32 m_stored_vector; // most recently written vector
+ INT32 m_curvector; // most recently processed vector
+ UINT8 m_curstate; // most recently processed state
+ INT32 m_queue[32]; // queue of pending events
+ int m_qindex; // index within the queue
+
+ private:
+ static void static_empty_event_queue(running_machine &machine, void *ptr, int param);
+ void empty_event_queue();
+ };
+
+ // internal state
+ cothread m_cothread; // thread used for execution
+
+ // configuration
+ bool m_disabled; // disabled from executing?
+ device_interrupt_func m_vblank_interrupt; // for interrupts tied to VBLANK
+ int m_vblank_interrupts_per_frame; // usually 1
+ const char * m_vblank_interrupt_screen; // the screen that causes the VBLANK interrupt
+ device_interrupt_func m_timed_interrupt; // for interrupts not tied to VBLANK
+ attotime m_timed_interrupt_period; // period for periodic interrupts
+
+ // execution lists
+ device_execute_interface *m_nextexec; // pointer to the next device to execute, in order
+
+ // input states and IRQ callbacks
+ device_irq_callback m_driver_irq; // driver-specific IRQ callback
+ device_input m_input[MAX_INPUT_LINES]; // data about inputs
+ emu_timer * m_timedint_timer; // reference to this device's periodic interrupt timer
+
+ // these below are hacks to support multiple interrupts per frame
+ INT32 m_iloops; // number of interrupts remaining this frame
+ emu_timer * m_partial_frame_timer; // the timer that triggers partial frame interrupts
+ attotime m_partial_frame_period; // the length of one partial frame for interrupt purposes
+
+ // cycle counting and executing
+ profile_type m_profiler; // profiler tag
+ int * m_icountptr; // pointer to the icount
+ int m_cycles_running; // number of cycles we are executing
+ int m_cycles_stolen; // number of cycles we artificially stole
+
+ // suspend states
+ UINT32 m_suspend; // suspend reason mask (0 = not suspended)
+ UINT32 m_nextsuspend; // pending suspend reason mask
+ UINT8 m_eatcycles; // true if we eat cycles while suspended
+ UINT8 m_nexteatcycles; // pending value
+ INT32 m_trigger; // pending trigger to release a trigger suspension
+ INT32 m_inttrigger; // interrupt trigger index
+
+ // clock and timing information
+ UINT64 m_totalcycles; // total device cycles executed
+ attotime m_localtime; // local time, relative to the timer system's global time
+ INT32 m_divisor; // 32-bit attoseconds_per_cycle divisor
+ UINT8 m_divshift; // right shift amount to fit the divisor into 32 bits
+ UINT32 m_cycles_per_second; // cycles per second, adjusted for multipliers
+ attoseconds_t m_attoseconds_per_cycle; // attoseconds per adjusted clock cycle
+
+private:
+ // callbacks
+ static void static_timed_trigger_callback(running_machine &machine, void *ptr, int param);
+
+ void on_vblank(screen_device &screen, bool vblank_state);
+
+ static void static_trigger_partial_frame_interrupt(running_machine &machine, void *ptr, int param);
+ void trigger_partial_frame_interrupt();
+
+ static void static_trigger_periodic_interrupt(running_machine &machine, void *ptr, int param);
+ void trigger_periodic_interrupt();
+
+ attoseconds_t minimum_quantum() const;
+};
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// device_execute - return a pointer to the device
+// execute interface for this device
+//-------------------------------------------------
+
+inline device_execute_interface *device_execute(device_t *device)
+{
+ device_execute_interface *intf;
+ if (!device->interface(intf))
+ throw emu_fatalerror("Device '%s' does not have execute interface", device->tag());
+ return intf;
+}
+
+
+
+// ======================> device scheduling
+
+// suspend the given device for a specific reason
+inline void device_suspend(device_t *device, int reason, bool eatcycles)
+{
+ device_execute(device)->suspend(reason, eatcycles);
+}
+
+// resume the given device for a specific reason
+inline void device_resume(device_t *device, int reason)
+{
+ device_execute(device)->resume(reason);
+}
+
+
+
+// ======================> synchronization helpers
+
+// yield the given device until the end of the current timeslice
+inline void device_yield(device_t *device)
+{
+ device_execute(device)->yield();
+}
+
+// burn device cycles until the end of the current timeslice
+inline void device_spin(device_t *device)
+{
+ device_execute(device)->spin();
+}
+
+// burn specified device cycles until a trigger
+inline void device_spin_until_trigger(device_t *device, int trigger)
+{
+ device_execute(device)->spin_until_trigger(trigger);
+}
+
+// burn device cycles for a specific period of time
+inline void device_spin_until_time(device_t *device, attotime duration)
+{
+ device_execute(device)->spin_until_time(duration);
+}
+
+
+
+// ======================> device timing
+
+// returns the current local time for a device
+inline attotime device_get_local_time(device_t *device)
+{
+ return device_execute(device)->local_time();
+}
+
+// safely eats cycles so we don't cross a timeslice boundary
+inline void device_eat_cycles(device_t *device, int cycles)
+{
+ device_execute(device)->eat_cycles(cycles);
+}
+
+// apply a +/- to the current icount
+inline void device_adjust_icount(device_t *device, int delta)
+{
+ device_execute(device)->adjust_icount(delta);
+}
+
+// abort execution for the current timeslice, allowing other devices to run before we run again
+inline void device_abort_timeslice(device_t *device)
+{
+ device_execute(device)->abort_timeslice();
+}
+
+
+
+// ======================> triggers
+
+// generate a trigger corresponding to an interrupt on the given device
+inline void device_triggerint(device_t *device)
+{
+ device_execute(device)->signal_interrupt_trigger();
+}
+
+
+
+// ======================> interrupts
+
+// set the logical state (ASSERT_LINE/CLEAR_LINE) of the an input line on a device
+inline void device_set_input_line(device_t *device, int line, int state)
+{
+ device_execute(device)->set_input_line(line, state);
+}
+
+// set the vector to be returned during a device's interrupt acknowledge cycle
+inline void device_set_input_line_vector(device_t *device, int line, int vector)
+{
+ device_execute(device)->set_input_line_vector(line, vector);
+}
+
+// set the logical state (ASSERT_LINE/CLEAR_LINE) of the an input line on a device and its associated vector
+inline void device_set_input_line_and_vector(device_t *device, int line, int state, int vector)
+{
+ device_execute(device)->set_input_line_and_vector(line, state, vector);
+}
+
+// install a driver-specific callback for IRQ acknowledge
+inline void device_set_irq_callback(device_t *device, device_irq_callback callback)
+{
+ device_execute(device)->set_irq_callback(callback);
+}
+
+
+
+// ======================> additional helpers
+
+// burn device cycles until the next interrupt
+inline void device_spin_until_interrupt(device_t *device)
+{
+ device_execute(device)->spin_until_interrupt();
+}
+
+
+
+#endif /* __DIEXEC_H__ */
diff --git a/trunk/src/emu/diimage.c b/trunk/src/emu/diimage.c
new file mode 100644
index 00000000000..fadf1d94c31
--- /dev/null
+++ b/trunk/src/emu/diimage.c
@@ -0,0 +1,1035 @@
+/***************************************************************************
+
+ diimage.c
+
+ Device image interfaces.
+
+****************************************************************************
+
+ Copyright Miodrag Milanovic
+ 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 "ui.h"
+#include "zippath.h"
+
+
+//**************************************************************************
+// DEVICE CONFIG IMAGE INTERFACE
+//**************************************************************************
+const image_device_type_info device_image_interface::m_device_info_array[] =
+ {
+ { IO_CARTSLOT, "cartridge", "cart" }, /* 0 */
+ { IO_FLOPPY, "floppydisk", "flop" }, /* 1 */
+ { IO_HARDDISK, "harddisk", "hard" }, /* 2 */
+ { IO_CYLINDER, "cylinder", "cyln" }, /* 3 */
+ { IO_CASSETTE, "cassette", "cass" }, /* 4 */
+ { IO_PUNCHCARD, "punchcard", "pcrd" }, /* 5 */
+ { IO_PUNCHTAPE, "punchtape", "ptap" }, /* 6 */
+ { IO_PRINTER, "printer", "prin" }, /* 7 */
+ { IO_SERIAL, "serial", "serl" }, /* 8 */
+ { IO_PARALLEL, "parallel", "parl" }, /* 9 */
+ { IO_SNAPSHOT, "snapshot", "dump" }, /* 10 */
+ { IO_QUICKLOAD, "quickload", "quik" }, /* 11 */
+ { IO_MEMCARD, "memcard", "memc" }, /* 12 */
+ { IO_CDROM, "cdrom", "cdrm" }, /* 13 */
+ { IO_MAGTAPE, "magtape", "magt" }, /* 14 */
+ };
+
+
+//**************************************************************************
+// DEVICE IMAGE INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_image_interface - constructor
+//-------------------------------------------------
+
+device_image_interface::device_image_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device),
+ m_file(NULL),
+ m_mame_file(NULL),
+ m_full_software_name(NULL),
+ m_software_info_ptr(NULL),
+ m_software_part_ptr(NULL),
+ m_readonly(false),
+ m_created(false),
+ m_formatlist(NULL),
+ m_is_loading(FALSE)
+{
+}
+
+
+//-------------------------------------------------
+// ~device_image_interface - destructor
+//-------------------------------------------------
+
+device_image_interface::~device_image_interface()
+{
+ image_device_format **formatptr = &m_formatlist;
+
+ /* free all entries */
+ while (*formatptr != NULL)
+ {
+ image_device_format *entry = *formatptr;
+ *formatptr = entry->m_next;
+ global_free(entry);
+ }
+}
+
+//-------------------------------------------------
+// find_device_type - search trough list of
+// device types to extact data
+//-------------------------------------------------
+
+const image_device_type_info *device_image_interface::find_device_type(iodevice_t type)
+{
+ int i;
+ for (i = 0; i < ARRAY_LENGTH(device_image_interface::m_device_info_array); i++)
+ {
+ if (m_device_info_array[i].m_type == type)
+ return &m_device_info_array[i];
+ }
+ return NULL;
+}
+
+//-------------------------------------------------
+// device_typename - retrieves device type name
+//-------------------------------------------------
+
+const char *device_image_interface::device_typename(iodevice_t type)
+{
+ const image_device_type_info *info = find_device_type(type);
+ return (info != NULL) ? info->m_name : NULL;
+}
+
+//-------------------------------------------------
+// device_brieftypename - retrieves device
+// brief type name
+//-------------------------------------------------
+
+const char *device_image_interface::device_brieftypename(iodevice_t type)
+{
+ const image_device_type_info *info = find_device_type(type);
+ return (info != NULL) ? info->m_shortname : NULL;
+}
+
+//-------------------------------------------------
+// device_typeid - retrieves device type id
+//-------------------------------------------------
+
+iodevice_t device_image_interface::device_typeid(const char *name)
+{
+ int i;
+ for (i = 0; i < ARRAY_LENGTH(device_image_interface::m_device_info_array); i++)
+ {
+ if (!mame_stricmp(name, m_device_info_array[i].m_name) || !mame_stricmp(name, m_device_info_array[i].m_shortname))
+ return m_device_info_array[i].m_type;
+ }
+ return (iodevice_t)-1;
+}
+
+/*-------------------------------------------------
+ device_compute_hash - compute a hash,
+ using this device's partial hash if appropriate
+-------------------------------------------------*/
+
+void device_image_interface::device_compute_hash(hash_collection &hashes, const void *data, size_t length, const char *types) const
+{
+ /* retrieve the partial hash func */
+ device_image_partialhash_func partialhash = get_partial_hash();
+
+ /* compute the hash */
+ if (partialhash)
+ partialhash(hashes, (const unsigned char*)data, length, types);
+ else
+ hashes.compute(reinterpret_cast<const UINT8 *>(data), length, types);
+}
+
+/*-------------------------------------------------
+ set_image_filename - specifies the filename of
+ an image
+-------------------------------------------------*/
+
+image_error_t device_image_interface::set_image_filename(const char *filename)
+{
+ m_image_name = filename;
+ zippath_parent(&m_working_directory, filename);
+ m_basename.cpy(m_image_name);
+
+ int loc1 = m_image_name.rchr(0,'\\');
+ int loc2 = m_image_name.rchr(0,'/');
+ int loc3 = m_image_name.rchr(0,':');
+ int loc = MAX(loc1,MAX(loc2,loc3));
+ if (loc!=-1) {
+ m_basename = m_basename.substr(loc + 1,m_basename.len()-loc);
+ }
+ m_basename_noext = m_basename.cpy(m_basename);
+ m_filetype = "";
+ loc = m_basename_noext.rchr(0,'.');
+ if (loc!=-1) {
+ m_basename_noext = m_basename_noext.substr(0,loc);
+ m_filetype = m_basename.cpy(m_basename);
+ m_filetype = m_filetype.substr(loc + 1,m_filetype.len()-loc);
+ }
+
+ return IMAGE_ERROR_SUCCESS;
+}
+
+/****************************************************************************
+ CREATION FORMATS
+****************************************************************************/
+
+/*-------------------------------------------------
+ device_get_indexed_creatable_format -
+ accesses a specific image format available for
+ image creation by index
+-------------------------------------------------*/
+
+const image_device_format *device_image_interface::device_get_indexed_creatable_format(int index)
+{
+ const image_device_format *format = device_get_creatable_formats();
+ while(index-- && (format != NULL))
+ format = format->m_next;
+ return format;
+}
+
+
+
+/*-------------------------------------------------
+ device_get_named_creatable_format -
+ accesses a specific image format available for
+ image creation by name
+-------------------------------------------------*/
+
+const image_device_format *device_image_interface::device_get_named_creatable_format(const char *format_name)
+{
+ const image_device_format *format = device_get_creatable_formats();
+ while((format != NULL) && strcmp(format->m_name, format_name))
+ format = format->m_next;
+ return format;
+}
+
+/****************************************************************************
+ ERROR HANDLING
+****************************************************************************/
+
+/*-------------------------------------------------
+ image_clear_error - clear out any specified
+ error
+-------------------------------------------------*/
+
+void device_image_interface::clear_error()
+{
+ m_err = IMAGE_ERROR_SUCCESS;
+ if (m_err_message)
+ {
+ m_err_message.reset();
+ }
+}
+
+
+
+/*-------------------------------------------------
+ error - returns the error text for an image
+ error
+-------------------------------------------------*/
+static const char *const messages[] =
+{
+ "",
+ "Internal error",
+ "Unsupported operation",
+ "Out of memory",
+ "File not found",
+ "Invalid image",
+ "File already open",
+ "Unspecified error"
+};
+
+const char *device_image_interface::error()
+{
+ return (m_err_message) ? m_err_message.cstr() : messages[m_err];
+}
+
+
+
+/*-------------------------------------------------
+ seterror - specifies an error on an image
+-------------------------------------------------*/
+
+void device_image_interface::seterror(image_error_t err, const char *message)
+{
+ clear_error();
+ m_err = err;
+ if (message != NULL)
+ {
+ m_err_message = message;
+ }
+}
+
+
+
+/*-------------------------------------------------
+ message - used to display a message while
+ loading
+-------------------------------------------------*/
+
+void device_image_interface::message(const char *format, ...)
+{
+ va_list args;
+ char buffer[256];
+
+ /* format the message */
+ va_start(args, format);
+ vsnprintf(buffer, ARRAY_LENGTH(buffer), format, args);
+ va_end(args);
+
+ /* display the popup for a standard amount of time */
+ ui_popup_time(5, "%s: %s",
+ basename(),
+ buffer);
+}
+
+
+/***************************************************************************
+ WORKING DIRECTORIES
+***************************************************************************/
+
+/*-------------------------------------------------
+ try_change_working_directory - tries to change
+ the working directory, but only if the directory
+ actually exists
+-------------------------------------------------*/
+bool device_image_interface::try_change_working_directory(const char *subdir)
+{
+ osd_directory *directory;
+ const osd_directory_entry *entry;
+ bool success = FALSE;
+ bool done = FALSE;
+
+ directory = osd_opendir(m_working_directory.cstr());
+ if (directory != NULL)
+ {
+ while(!done && (entry = osd_readdir(directory)) != NULL)
+ {
+ if (!mame_stricmp(subdir, entry->name))
+ {
+ done = TRUE;
+ success = entry->type == ENTTYPE_DIR;
+ }
+ }
+
+ osd_closedir(directory);
+ }
+
+ /* did we successfully identify the directory? */
+ if (success)
+ zippath_combine(&m_working_directory, m_working_directory, subdir);
+
+ return success;
+}
+/*-------------------------------------------------
+ setup_working_directory - sets up the working
+ directory according to a few defaults
+-------------------------------------------------*/
+
+void device_image_interface::setup_working_directory()
+{
+ char *dst = NULL;
+
+ osd_get_full_path(&dst,".");
+ /* first set up the working directory to be the starting directory */
+ m_working_directory = dst;
+
+ /* now try browsing down to "software" */
+ if (try_change_working_directory("software"))
+ {
+ /* now down to a directory for this computer */
+ int gamedrv = driver_list::find(device().machine().system());
+ while(gamedrv != -1 && !try_change_working_directory(driver_list::driver(gamedrv).name))
+ {
+ gamedrv = driver_list::compatible_with(gamedrv);
+ }
+ }
+ osd_free(dst);
+}
+
+//-------------------------------------------------
+// working_directory - returns the working
+// directory to use for this image; this is
+// valid even if not mounted
+//-------------------------------------------------
+
+const char * device_image_interface::working_directory()
+{
+ /* check to see if we've never initialized the working directory */
+ if (!m_working_directory)
+ setup_working_directory();
+
+ return m_working_directory;
+}
+
+
+/*-------------------------------------------------
+ get_software_region
+-------------------------------------------------*/
+
+UINT8 *device_image_interface::get_software_region(const char *tag)
+{
+ char full_tag[256];
+
+ if ( m_software_info_ptr == NULL || m_software_part_ptr == NULL )
+ return NULL;
+
+ sprintf( full_tag, "%s:%s", device().tag(), tag );
+ return device().machine().region( full_tag )->base();
+}
+
+
+/*-------------------------------------------------
+ image_get_software_region_length
+-------------------------------------------------*/
+
+UINT32 device_image_interface::get_software_region_length(const char *tag)
+{
+ char full_tag[256];
+
+ sprintf( full_tag, "%s:%s", device().tag(), tag );
+ return device().machine().region( full_tag )->bytes();
+}
+
+
+/*-------------------------------------------------
+ image_get_feature
+ -------------------------------------------------*/
+
+const char *device_image_interface::get_feature(const char *feature_name)
+{
+ feature_list *feature;
+
+ if ( ! m_software_part_ptr->featurelist )
+ return NULL;
+
+ for ( feature = m_software_part_ptr->featurelist; feature; feature = feature->next )
+ {
+ if ( ! strcmp( feature->name, feature_name ) )
+ return feature->value;
+ }
+
+ return NULL;
+}
+
+/****************************************************************************
+ Hash info loading
+
+ If the hash is not checked and the relevant info not loaded, force that info
+ to be loaded
+****************************************************************************/
+
+void device_image_interface::run_hash(void (*partialhash)(hash_collection &, const unsigned char *, unsigned long, const char *),
+ hash_collection &hashes, const char *types)
+{
+ UINT32 size;
+ UINT8 *buf = NULL;
+
+ hashes.reset();
+ size = (UINT32) length();
+
+ buf = (UINT8*)malloc(size);
+ memset(buf,0,size);
+
+ /* read the file */
+ fseek(0, SEEK_SET);
+ fread(buf, size);
+
+ if (partialhash)
+ partialhash(hashes, buf, size, types);
+ else
+ hashes.compute(buf, size, types);
+
+ /* cleanup */
+ free(buf);
+ fseek(0, SEEK_SET);
+}
+
+
+
+void device_image_interface::image_checkhash()
+{
+ device_image_partialhash_func partialhash;
+
+ /* only calculate CRC if it hasn't been calculated, and the open_mode is read only */
+ if (m_hash.first() == NULL && m_readonly && !m_created)
+ {
+ /* do not cause a linear read of 600 megs please */
+ /* TODO: use SHA1 in the CHD header as the hash */
+ if (image_type() == IO_CDROM)
+ return;
+
+ /* Skip calculating the hash when we have an image mounted through a software list */
+ if ( m_software_info_ptr )
+ return;
+
+ /* retrieve the partial hash func */
+ partialhash = get_partial_hash();
+
+ run_hash(partialhash, m_hash, hash_collection::HASH_TYPES_ALL);
+ }
+ return;
+}
+
+UINT32 device_image_interface::crc()
+{
+ UINT32 crc = 0;
+
+ image_checkhash();
+ m_hash.crc(crc);
+
+ return crc;
+}
+
+/****************************************************************************
+ Battery functions
+
+ These functions provide transparent access to battery-backed RAM on an
+ image; typically for cartridges.
+****************************************************************************/
+
+
+/*-------------------------------------------------
+ battery_load - retrieves the battery
+ backed RAM for an image. The file name is
+ created from the machine driver name and the
+ image name.
+-------------------------------------------------*/
+void device_image_interface::battery_load(void *buffer, int length, int fill)
+{
+ astring *fname = astring_assemble_4(astring_alloc(), device().machine().system().name, PATH_SEPARATOR, m_basename_noext, ".nv");
+
+ image_battery_load_by_name(device().machine().options(), astring_c(fname), buffer, length, fill);
+ astring_free(fname);
+}
+
+/*-------------------------------------------------
+ battery_save - stores the battery
+ backed RAM for an image. The file name is
+ created from the machine driver name and the
+ image name.
+-------------------------------------------------*/
+void device_image_interface::battery_save(const void *buffer, int length)
+{
+ astring *fname = astring_assemble_4(astring_alloc(), device().machine().system().name, PATH_SEPARATOR, m_basename_noext, ".nv");
+
+ image_battery_save_by_name(device().machine().options(), astring_c(fname), buffer, length);
+ astring_free(fname);
+}
+
+//-------------------------------------------------
+// uses_file_extension - update configuration
+// based on completed device setup
+//-------------------------------------------------
+
+bool device_image_interface::uses_file_extension(const char *file_extension) const
+{
+ bool result = FALSE;
+
+ if (file_extension[0] == '.')
+ file_extension++;
+
+ /* find the extensions */
+ astring extensions(file_extensions());
+ char *ext = strtok((char*)extensions.cstr(),",");
+ while (ext != NULL)
+ {
+ if (!mame_stricmp(ext, file_extension))
+ {
+ result = TRUE;
+ break;
+ }
+ ext = strtok (NULL, ",");
+ }
+ return result;
+}
+
+/****************************************************************************
+ IMAGE LOADING
+****************************************************************************/
+
+/*-------------------------------------------------
+ is_loaded - quick check to determine whether an
+ image is loaded
+-------------------------------------------------*/
+
+bool device_image_interface::is_loaded()
+{
+ return (m_file != NULL);
+}
+
+/*-------------------------------------------------
+ load_image_by_path - loads an image with a
+ specific path
+-------------------------------------------------*/
+
+image_error_t device_image_interface::load_image_by_path(UINT32 open_flags, const char *path)
+{
+ file_error filerr = FILERR_NOT_FOUND;
+ image_error_t err = IMAGE_ERROR_FILENOTFOUND;
+ astring revised_path;
+
+ /* attempt to read the file */
+ filerr = zippath_fopen(path, open_flags, &m_file, &revised_path);
+
+ /* did the open succeed? */
+ switch(filerr)
+ {
+ case FILERR_NONE:
+ /* success! */
+ m_readonly = (open_flags & OPEN_FLAG_WRITE) ? 0 : 1;
+ m_created = (open_flags & OPEN_FLAG_CREATE) ? 1 : 0;
+ err = IMAGE_ERROR_SUCCESS;
+ break;
+
+ case FILERR_NOT_FOUND:
+ case FILERR_ACCESS_DENIED:
+ /* file not found (or otherwise cannot open); continue */
+ err = IMAGE_ERROR_FILENOTFOUND;
+ break;
+
+ case FILERR_OUT_OF_MEMORY:
+ /* out of memory */
+ err = IMAGE_ERROR_OUTOFMEMORY;
+ break;
+
+ case FILERR_ALREADY_OPEN:
+ /* this shouldn't happen */
+ err = IMAGE_ERROR_ALREADYOPEN;
+ break;
+
+ case FILERR_FAILURE:
+ case FILERR_TOO_MANY_FILES:
+ case FILERR_INVALID_DATA:
+ default:
+ /* other errors */
+ err = IMAGE_ERROR_INTERNAL;
+ break;
+ }
+
+ /* if successful, set the file name */
+ if (filerr == FILERR_NONE)
+ set_image_filename(revised_path);
+
+ return err;
+}
+
+/*-------------------------------------------------
+ determine_open_plan - determines which open
+ flags to use, and in what order
+-------------------------------------------------*/
+
+void device_image_interface::determine_open_plan(int is_create, UINT32 *open_plan)
+{
+ int i = 0;
+
+ /* emit flags */
+ if (!is_create && is_readable() && is_writeable())
+ open_plan[i++] = OPEN_FLAG_READ | OPEN_FLAG_WRITE;
+ if (!is_create && !is_readable() && is_writeable())
+ open_plan[i++] = OPEN_FLAG_WRITE;
+ if (!is_create && is_readable())
+ open_plan[i++] = OPEN_FLAG_READ;
+ if (is_writeable() && is_creatable())
+ open_plan[i++] = OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE;
+ open_plan[i] = 0;
+}
+
+/*-------------------------------------------------
+ load_software - software image loading
+-------------------------------------------------*/
+bool device_image_interface::load_software(char *swlist, char *swname, rom_entry *start)
+{
+ astring locationtag, breakstr("%");
+ const rom_entry *region;
+ astring regiontag;
+ bool retVal = FALSE;
+ for (region = start; region != NULL; region = rom_next_region(region))
+ {
+ /* loop until we hit the end of this region */
+ const rom_entry *romp = region + 1;
+ while (!ROMENTRY_ISREGIONEND(romp))
+ {
+ /* handle files */
+ if (ROMENTRY_ISFILE(romp))
+ {
+ file_error filerr = FILERR_NOT_FOUND;
+
+ UINT32 crc = 0;
+ bool has_crc = hash_collection(ROM_GETHASHDATA(romp)).crc(crc);
+
+ // attempt reading up the chain through the parents and create a locationtag astring in the format
+ // " swlist % clonename % parentname "
+ // below, we have the code to split the elements and to create paths to load from
+
+ software_list *software_list_ptr = software_list_open(device().machine().options(), swlist, FALSE, NULL);
+ if (software_list_ptr)
+ {
+ for (software_info *swinfo = software_list_find(software_list_ptr, swname, NULL); swinfo != NULL; )
+ {
+ {
+ astring tmp(swinfo->shortname);
+ locationtag.cat(tmp);
+ locationtag.cat(breakstr);
+ //printf("%s\n", locationtag.cstr());
+ }
+
+ const char *parentname = software_get_clone(device().machine().options(), swlist, swinfo->shortname);
+ if (parentname != NULL)
+ swinfo = software_list_find(software_list_ptr, parentname, NULL);
+ else
+ swinfo = NULL;
+ }
+ // strip the final '%'
+ locationtag.del(locationtag.len() - 1, 1);
+ software_list_close(software_list_ptr);
+ }
+
+ if (software_get_support(device().machine().options(), swlist, swname) == SOFTWARE_SUPPORTED_PARTIAL)
+ mame_printf_error("WARNING: support for software %s (in list %s) is only partial\n", swname, swlist);
+
+ if (software_get_support(device().machine().options(), swlist, swname) == SOFTWARE_SUPPORTED_NO)
+ mame_printf_error("WARNING: support for software %s (in list %s) is only preliminary\n", swname, swlist);
+
+ // check if locationtag actually contains two locations separated by '%'
+ // (i.e. check if we are dealing with a clone in softwarelist)
+ astring tag2, tag3, tag4(locationtag), tag5;
+ int separator = tag4.chr(0, '%');
+ if (separator != -1)
+ {
+ // we are loading a clone through softlists, split the setname from the parentname
+ tag5.cpysubstr(tag4, separator + 1, tag4.len() - separator + 1);
+ tag4.del(separator, tag4.len() - separator);
+ }
+
+ // prepare locations where we have to load from: list/parentname & list/clonename
+ astring tag1(swlist);
+ tag1.cat(PATH_SEPARATOR);
+ tag2.cpy(tag1.cat(tag4));
+ tag1.cpy(swlist);
+ tag1.cat(PATH_SEPARATOR);
+ tag3.cpy(tag1.cat(tag5));
+
+ if (tag5.chr(0, '%') != -1)
+ fatalerror("We do not support clones of clones!\n");
+
+ // try to load from the available location(s):
+ // - if we are not using lists, we have regiontag only;
+ // - if we are using lists, we have: list/clonename, list/parentname, clonename, parentname
+ // try to load from list/setname
+ if ((m_mame_file == NULL) && (tag2.cstr() != NULL))
+ filerr = common_process_file(device().machine().options(), tag2.cstr(), has_crc, crc, romp, &m_mame_file);
+ // try to load from list/parentname
+ if ((m_mame_file == NULL) && (tag3.cstr() != NULL))
+ filerr = common_process_file(device().machine().options(), tag3.cstr(), has_crc, crc, romp, &m_mame_file);
+ // try to load from setname
+ if ((m_mame_file == NULL) && (tag4.cstr() != NULL))
+ filerr = common_process_file(device().machine().options(), tag4.cstr(), has_crc, crc, romp, &m_mame_file);
+ // try to load from parentname
+ if ((m_mame_file == NULL) && (tag5.cstr() != NULL))
+ filerr = common_process_file(device().machine().options(), tag5.cstr(), has_crc, crc, romp, &m_mame_file);
+
+ if (filerr == FILERR_NONE)
+ {
+ m_file = *m_mame_file;
+ retVal = TRUE;
+ }
+
+ break; // load first item for start
+ }
+ romp++; /* something else; skip */
+ }
+ }
+ return retVal;
+}
+
+/*-------------------------------------------------
+ load_internal - core image loading
+-------------------------------------------------*/
+
+bool device_image_interface::load_internal(const char *path, bool is_create, int create_format, option_resolution *create_args)
+{
+ UINT32 open_plan[4];
+ int i;
+ bool softload = FALSE;
+ m_from_swlist = FALSE;
+
+ // if the path contains no period, we are using softlists, so we won't create an image
+ astring pathstr(path);
+ bool filename_has_period = (pathstr.rchr(0, '.') != -1) ? TRUE : FALSE;
+
+ /* first unload the image */
+ unload();
+
+ /* clear any possible error messages */
+ clear_error();
+
+ /* we are now loading */
+ m_is_loading = TRUE;
+
+ /* record the filename */
+ m_err = set_image_filename(path);
+
+ if (m_err)
+ goto done;
+
+ /* Check if there's a software list defined for this device and use that if we're not creating an image */
+ if (!filename_has_period)
+ {
+ softload = load_software_part( device().machine().options(), this, path, &m_software_info_ptr, &m_software_part_ptr, &m_full_software_name );
+ // if we had launched from softlist with a specified part, e.g. "shortname:part"
+ // we would have recorded the wrong name, so record it again based on software_info
+ if (m_software_info_ptr && m_software_info_ptr->shortname)
+ m_err = set_image_filename(m_software_info_ptr->shortname);
+
+ m_from_swlist = TRUE;
+ }
+
+ if (is_create || filename_has_period)
+ {
+ /* determine open plan */
+ determine_open_plan(is_create, open_plan);
+
+ /* attempt to open the file in various ways */
+ for (i = 0; !m_file && open_plan[i]; i++)
+ {
+ /* open the file */
+ m_err = load_image_by_path(open_plan[i], path);
+ if (m_err && (m_err != IMAGE_ERROR_FILENOTFOUND))
+ goto done;
+ }
+ }
+
+ /* Copy some image information when we have been loaded through a software list */
+ if ( m_software_info_ptr )
+ {
+ m_longname = m_software_info_ptr->longname;
+ m_manufacturer = m_software_info_ptr->publisher;
+ m_year = m_software_info_ptr->year;
+ //m_playable = m_software_info_ptr->supported;
+ }
+
+ /* did we fail to find the file? */
+ if (!is_loaded() && !softload)
+ {
+ m_err = IMAGE_ERROR_FILENOTFOUND;
+ goto done;
+ }
+
+ /* call device load or create */
+ m_create_format = create_format;
+ m_create_args = create_args;
+
+ if (m_init_phase==FALSE) {
+ m_err = (image_error_t)finish_load();
+ if (m_err)
+ goto done;
+ }
+ /* success! */
+
+done:
+ if (m_err!=0) {
+ if (!m_init_phase)
+ {
+ if (device().machine().phase() == MACHINE_PHASE_RUNNING)
+ popmessage("Error: Unable to %s image '%s': %s\n", is_create ? "create" : "load", path, error());
+ else
+ mame_printf_error("Error: Unable to %s image '%s': %s", is_create ? "create" : "load", path, error());
+ }
+ clear();
+ }
+ else {
+ /* do we need to reset the CPU? only schedule it if load/create is successful */
+ if (device().machine().time() > attotime::zero && is_reset_on_load())
+ device().machine().schedule_hard_reset();
+ else
+ {
+ if (!m_init_phase)
+ {
+ if (device().machine().phase() == MACHINE_PHASE_RUNNING)
+ popmessage("Image '%s' was successfully %s.", path, is_create ? "created" : "loaded");
+ else
+ mame_printf_info("Image '%s' was successfully %s.\n", path, is_create ? "created" : "loaded");
+ }
+ }
+ }
+ return m_err ? IMAGE_INIT_FAIL : IMAGE_INIT_PASS;
+}
+
+
+
+/*-------------------------------------------------
+ load - load an image into MESS
+-------------------------------------------------*/
+
+bool device_image_interface::load(const char *path)
+{
+ return load_internal(path, FALSE, 0, NULL);
+}
+
+
+/*-------------------------------------------------
+ image_finish_load - special call - only use
+ from core
+-------------------------------------------------*/
+
+bool device_image_interface::finish_load()
+{
+ bool err = IMAGE_INIT_PASS;
+
+ if (m_is_loading)
+ {
+ image_checkhash();
+
+ if (m_from_swlist)
+ call_display_info();
+
+ if (has_been_created() )// && get_legacy_fct(DEVINFO_FCT_IMAGE_CREATE) != NULL)
+ {
+ err = call_create(m_create_format, m_create_args);
+ if (err)
+ {
+ if (!m_err)
+ m_err = IMAGE_ERROR_UNSPECIFIED;
+ }
+ }
+ else
+ {
+ /* using device load */
+ err = call_load();
+ if (err)
+ {
+ if (!m_err)
+ m_err = IMAGE_ERROR_UNSPECIFIED;
+ }
+ }
+ }
+ m_is_loading = FALSE;
+ m_create_format = 0;
+ m_create_args = NULL;
+ m_init_phase = FALSE;
+ return err;
+}
+
+/*-------------------------------------------------
+ create - create a image
+-------------------------------------------------*/
+
+bool device_image_interface::create(const char *path, const image_device_format *create_format, option_resolution *create_args)
+{
+ int format_index = (create_format != NULL) ? create_format->m_index : 0;
+ return load_internal(path, TRUE, format_index, create_args);
+}
+
+
+/*-------------------------------------------------
+ clear - clear all internal data pertaining
+ to an image
+-------------------------------------------------*/
+
+void device_image_interface::clear()
+{
+ if (m_mame_file)
+ {
+ global_free(m_mame_file);
+ m_mame_file = NULL;
+ m_file = NULL;
+ } else {
+ if (m_file)
+ {
+ core_fclose(m_file);
+ m_file = NULL;
+ }
+ }
+
+ m_image_name.reset();
+ m_readonly = false;
+ m_created = false;
+
+ m_longname.reset();
+ m_manufacturer.reset();
+ m_year.reset();
+ m_basename.reset();
+ m_basename_noext.reset();
+ m_filetype.reset();
+
+ m_full_software_name = NULL;
+ m_software_info_ptr = NULL;
+ m_software_part_ptr = NULL;
+}
+
+/*-------------------------------------------------
+ unload - main call to unload an image
+-------------------------------------------------*/
+
+void device_image_interface::unload()
+{
+ if (is_loaded()) {
+ call_unload();
+ }
+ clear();
+ clear_error();
+}
+
+/*-------------------------------------------------
+ update_names - update brief and instance names
+-------------------------------------------------*/
+
+void device_image_interface::update_names()
+{
+ const device_image_interface *image = NULL;
+ int count = 0;
+ int index = -1;
+
+ for (bool gotone = device().mconfig().devicelist().first(image); gotone; gotone = image->next(image))
+ {
+ if (this == image)
+ index = count;
+ if (image->image_type() == image_type())
+ count++;
+ }
+ if (count > 1) {
+ m_instance_name.printf("%s%d", device_typename(image_type()), index + 1);
+ m_brief_instance_name.printf("%s%d", device_brieftypename(image_type()), index + 1);
+ }
+ else
+ {
+ m_instance_name = device_typename(image_type());
+ m_brief_instance_name = device_brieftypename(image_type());
+ }
+}
diff --git a/trunk/src/emu/diimage.h b/trunk/src/emu/diimage.h
new file mode 100644
index 00000000000..f87622638e0
--- /dev/null
+++ b/trunk/src/emu/diimage.h
@@ -0,0 +1,325 @@
+/***************************************************************************
+
+ diimage.h
+
+ Device image interfaces.
+
+****************************************************************************
+
+ Copyright Miodrag Milanovic
+ 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 __DIIMAGE_H__
+#define __DIIMAGE_H__
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+enum iodevice_t
+{
+ /* List of all supported devices. Refer to the device by these names only */
+ IO_UNKNOWN,
+ IO_CARTSLOT, /* 1 - Cartridge Port, as found on most console and on some computers */
+ IO_FLOPPY, /* 2 - Floppy Disk unit */
+ IO_HARDDISK, /* 3 - Hard Disk unit */
+ IO_CYLINDER, /* 4 - Magnetically-Coated Cylinder */
+ IO_CASSETTE, /* 5 - Cassette Recorder (common on early home computers) */
+ IO_PUNCHCARD, /* 6 - Card Puncher/Reader */
+ IO_PUNCHTAPE, /* 7 - Tape Puncher/Reader (reels instead of punchcards) */
+ IO_PRINTER, /* 8 - Printer device */
+ IO_SERIAL, /* 9 - Generic Serial Port */
+ IO_PARALLEL, /* 10 - Generic Parallel Port */
+ IO_SNAPSHOT, /* 11 - Complete 'snapshot' of the state of the computer */
+ IO_QUICKLOAD, /* 12 - Allow to load program/data into memory, without matching any actual device */
+ IO_MEMCARD, /* 13 - Memory card */
+ IO_CDROM, /* 14 - optical CD-ROM disc */
+ IO_MAGTAPE, /* 15 - Magentic tape */
+ IO_COUNT /* 16 - Total Number of IO_devices for searching */
+};
+
+enum image_error_t
+{
+ IMAGE_ERROR_SUCCESS,
+ IMAGE_ERROR_INTERNAL,
+ IMAGE_ERROR_UNSUPPORTED,
+ IMAGE_ERROR_OUTOFMEMORY,
+ IMAGE_ERROR_FILENOTFOUND,
+ IMAGE_ERROR_INVALIDIMAGE,
+ IMAGE_ERROR_ALREADYOPEN,
+ IMAGE_ERROR_UNSPECIFIED
+};
+
+struct image_device_type_info
+{
+ iodevice_t m_type;
+ const char *m_name;
+ const char *m_shortname;
+};
+
+struct image_device_format
+{
+ image_device_format *m_next;
+ int m_index;
+ astring m_name;
+ astring m_description;
+ astring m_extensions;
+ astring m_optspec;
+};
+
+class device_image_interface;
+struct feature_list;
+struct software_part;
+struct software_info;
+
+// device image interface function types
+typedef int (*device_image_load_func)(device_image_interface &image);
+typedef int (*device_image_create_func)(device_image_interface &image, int format_type, option_resolution *format_options);
+typedef void (*device_image_unload_func)(device_image_interface &image);
+typedef void (*device_image_display_func)(device_image_interface &image);
+typedef void (*device_image_partialhash_func)(hash_collection &, const unsigned char *, unsigned long, const char *);
+typedef void (*device_image_get_devices_func)(device_image_interface &device);
+typedef bool (*device_image_softlist_load_func)(device_image_interface &image, char *swlist, char *swname, rom_entry *start_entry);
+typedef void (*device_image_display_info_func)(device_image_interface &image);
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+#define IMAGE_INIT_PASS FALSE
+#define IMAGE_INIT_FAIL TRUE
+#define IMAGE_VERIFY_PASS FALSE
+#define IMAGE_VERIFY_FAIL TRUE
+
+#define DEVICE_IMAGE_LOAD_NAME(name) device_load_##name
+#define DEVICE_IMAGE_LOAD(name) int DEVICE_IMAGE_LOAD_NAME(name)(device_image_interface &image)
+
+#define DEVICE_IMAGE_CREATE_NAME(name) device_create_##name
+#define DEVICE_IMAGE_CREATE(name) int DEVICE_IMAGE_CREATE_NAME(name)(device_image_interface &image, int create_format, option_resolution *create_args)
+
+#define DEVICE_IMAGE_UNLOAD_NAME(name) device_unload_##name
+#define DEVICE_IMAGE_UNLOAD(name) void DEVICE_IMAGE_UNLOAD_NAME(name)(device_image_interface &image)
+
+#define DEVICE_IMAGE_DISPLAY_NAME(name) device_image_display_func##name
+#define DEVICE_IMAGE_DISPLAY(name) void DEVICE_IMAGE_DISPLAY_NAME(name)(device_image_interface &image)
+
+#define DEVICE_IMAGE_DISPLAY_INFO_NAME(name) device_image_display_info_func##name
+#define DEVICE_IMAGE_DISPLAY_INFO(name) void DEVICE_IMAGE_DISPLAY_INFO_NAME(name)(device_image_interface &image)
+
+#define DEVICE_IMAGE_GET_DEVICES_NAME(name) device_image_get_devices_##name
+#define DEVICE_IMAGE_GET_DEVICES(name) void DEVICE_IMAGE_GET_DEVICES_NAME(name)(device_image_interface &image)
+
+#define DEVICE_IMAGE_SOFTLIST_LOAD_NAME(name) device_softlist_load_##name
+#define DEVICE_IMAGE_SOFTLIST_LOAD(name) bool DEVICE_IMAGE_SOFTLIST_LOAD_NAME(name)(device_image_interface &image, char *swlist, char *swname, rom_entry *start_entry)
+
+
+
+// ======================> device_image_interface
+
+// class representing interface-specific live image
+class device_image_interface : public device_interface
+{
+public:
+ // construction/destruction
+ device_image_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_image_interface();
+
+ static const char *device_typename(iodevice_t type);
+ static const char *device_brieftypename(iodevice_t type);
+ static iodevice_t device_typeid(const char *name);
+
+ virtual void device_compute_hash(hash_collection &hashes, const void *data, size_t length, const char *types) const;
+
+ virtual bool call_load() { return FALSE; }
+ virtual bool call_softlist_load(char *swlist, char *swname, rom_entry *start_entry) { return FALSE; }
+ virtual bool call_create(int format_type, option_resolution *format_options) { return FALSE; }
+ virtual void call_unload() { }
+ virtual void call_display() { }
+ virtual void call_display_info() { }
+ virtual void call_get_devices() { }
+ virtual void *get_device_specific_call() { return NULL; }
+ virtual device_image_partialhash_func get_partial_hash() const { return NULL; }
+ virtual iodevice_t image_type() const = 0;
+ virtual bool is_readable() const = 0;
+ virtual bool is_writeable() const = 0;
+ virtual bool is_creatable() const = 0;
+ virtual bool must_be_loaded() const = 0;
+ virtual bool is_reset_on_load() const = 0;
+ virtual const char *image_interface() const { return NULL; }
+ virtual const char *file_extensions() const = 0;
+ virtual const option_guide *create_option_guide() const = 0;
+
+ const image_device_format *device_get_indexed_creatable_format(int index);
+ const image_device_format *device_get_named_creatable_format(const char *format_name);
+ const option_guide *device_get_creation_option_guide() { return create_option_guide(); }
+ const image_device_format *device_get_creatable_formats() { return formatlist(); }
+
+ const char *error();
+ void seterror(image_error_t err, const char *message);
+ void message(const char *format, ...);
+
+ bool exists() { return m_image_name; }
+ const char *filename() { if (!m_image_name) return NULL; else return m_image_name; }
+ const char *basename() { if (!m_basename) return NULL; else return m_basename; }
+ const char *basename_noext() { if (!m_basename_noext) return NULL; else return m_basename_noext; }
+ const char *filetype() { if (!m_filetype) return NULL; else return m_filetype; }
+ core_file *image_core_file() { return m_file; }
+ UINT64 length() { check_for_file(); return core_fsize(m_file); }
+ bool is_readonly() { return m_readonly; }
+ bool has_been_created() { return m_created; }
+ void make_readonly() { m_readonly = true; }
+ UINT32 fread(void *buffer, UINT32 length) { check_for_file(); return core_fread(m_file, buffer, length); }
+ UINT32 fwrite(const void *buffer, UINT32 length) { check_for_file(); return core_fwrite(m_file, buffer, length); }
+ int fseek(INT64 offset, int whence) { check_for_file(); return core_fseek(m_file, offset, whence); }
+ UINT64 ftell() { check_for_file(); return core_ftell(m_file); }
+ int fgetc() { char ch; if (fread(&ch, 1) != 1) ch = '\0'; return ch; }
+ char *fgets(char *buffer, UINT32 length) { check_for_file(); return core_fgets(buffer, length, m_file); }
+ int image_feof() { check_for_file(); return core_feof(m_file); }
+ void *ptr() {check_for_file(); return (void *) core_fbuffer(m_file); }
+ // configuration access
+ void set_init_phase() { m_init_phase = TRUE; }
+
+ const char* longname() { return m_longname; }
+ const char* manufacturer() { return m_manufacturer; }
+ const char* year() { return m_year; }
+ UINT32 supported() { return m_supported; }
+
+ const software_info *software_entry() { return m_software_info_ptr; }
+ const software_part *part_entry() { return m_software_part_ptr; }
+
+ void set_working_directory(const char *working_directory) { m_working_directory = working_directory; }
+ const char * working_directory();
+
+ UINT8 *get_software_region(const char *tag);
+ UINT32 get_software_region_length(const char *tag);
+ const char *get_feature(const char *feature_name);
+
+ UINT32 crc();
+ hash_collection& hash() { return m_hash; }
+
+ void battery_load(void *buffer, int length, int fill);
+ void battery_save(const void *buffer, int length);
+
+ const char *image_type_name() const { return device_typename(image_type()); }
+
+
+
+ const char *instance_name() const { return m_instance_name; }
+ const char *brief_instance_name() const { return m_brief_instance_name; }
+ bool uses_file_extension(const char *file_extension) const;
+ image_device_format *formatlist() const { return m_formatlist; }
+
+ bool load(const char *path);
+ bool finish_load();
+ void unload();
+ bool create(const char *path, const image_device_format *create_format, option_resolution *create_args);
+ bool load_software(char *swlist, char *swname, rom_entry *entry);
+protected:
+ bool load_internal(const char *path, bool is_create, int create_format, option_resolution *create_args);
+ void determine_open_plan(int is_create, UINT32 *open_plan);
+ image_error_t load_image_by_path(UINT32 open_flags, const char *path);
+ void clear();
+ bool is_loaded();
+
+ image_error_t set_image_filename(const char *filename);
+
+ void clear_error();
+
+ void check_for_file() { assert_always(m_file != NULL, "Illegal operation on unmounted image"); }
+
+ void setup_working_directory();
+ bool try_change_working_directory(const char *subdir);
+
+ int read_hash_config(const char *sysname);
+ void run_hash(void (*partialhash)(hash_collection &, const unsigned char *, unsigned long, const char *), hash_collection &hashes, const char *types);
+ void image_checkhash();
+ void update_names();
+ // derived class overrides
+
+ // configuration
+ static const image_device_type_info *find_device_type(iodevice_t type);
+ static const image_device_type_info m_device_info_array[];
+
+ /* error related info */
+ image_error_t m_err;
+ astring m_err_message;
+
+ /* variables that are only non-zero when an image is mounted */
+ core_file *m_file;
+ emu_file *m_mame_file;
+ astring m_image_name;
+ astring m_basename;
+ astring m_basename_noext;
+ astring m_filetype;
+
+ /* working directory; persists across mounts */
+ astring m_working_directory;
+
+ /* Software information */
+ char *m_full_software_name;
+ software_info *m_software_info_ptr;
+ software_part *m_software_part_ptr;
+
+ /* info read from the hash file/software list */
+ astring m_longname;
+ astring m_manufacturer;
+ astring m_year;
+ UINT32 m_supported;
+
+ /* flags */
+ bool m_readonly;
+ bool m_created;
+ bool m_init_phase;
+ bool m_from_swlist;
+
+ /* special - used when creating */
+ int m_create_format;
+ option_resolution *m_create_args;
+
+ hash_collection m_hash;
+
+ astring m_brief_instance_name;
+ astring m_instance_name;
+
+ /* creation info */
+ image_device_format *m_formatlist;
+
+ bool m_is_loading;
+};
+
+
+#endif /* __DIIMAGE_H__ */
diff --git a/trunk/src/emu/dimemory.c b/trunk/src/emu/dimemory.c
new file mode 100644
index 00000000000..c647596ff8b
--- /dev/null
+++ b/trunk/src/emu/dimemory.c
@@ -0,0 +1,379 @@
+/***************************************************************************
+
+ dimemory.c
+
+ Device memory interfaces.
+
+****************************************************************************
+
+ 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 "validity.h"
+
+
+//**************************************************************************
+// PARAMETERS
+//**************************************************************************
+
+#define DETECT_OVERLAPPING_MEMORY (0)
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+const int TRIGGER_SUSPENDTIME = -4000;
+
+
+
+//**************************************************************************
+// ADDRESS SPACE CONFIG
+//**************************************************************************
+
+//-------------------------------------------------
+// address_space_config - constructors
+//-------------------------------------------------
+
+address_space_config::address_space_config()
+ : m_name("unknown"),
+ m_endianness(ENDIANNESS_NATIVE),
+ m_databus_width(0),
+ m_addrbus_width(0),
+ m_addrbus_shift(0),
+ m_logaddr_width(0),
+ m_page_shift(0),
+ m_internal_map(NULL),
+ m_default_map(NULL)
+{
+}
+
+address_space_config::address_space_config(const char *name, endianness_t endian, UINT8 datawidth, UINT8 addrwidth, INT8 addrshift, address_map_constructor internal, address_map_constructor defmap)
+ : m_name(name),
+ m_endianness(endian),
+ m_databus_width(datawidth),
+ m_addrbus_width(addrwidth),
+ m_addrbus_shift(addrshift),
+ m_logaddr_width(addrwidth),
+ m_page_shift(0),
+ m_internal_map(internal),
+ m_default_map(defmap)
+{
+}
+
+address_space_config::address_space_config(const char *name, endianness_t endian, UINT8 datawidth, UINT8 addrwidth, INT8 addrshift, UINT8 logwidth, UINT8 pageshift, address_map_constructor internal, address_map_constructor defmap)
+ : m_name(name),
+ m_endianness(endian),
+ m_databus_width(datawidth),
+ m_addrbus_width(addrwidth),
+ m_addrbus_shift(addrshift),
+ m_logaddr_width(logwidth),
+ m_page_shift(pageshift),
+ m_internal_map(internal),
+ m_default_map(defmap)
+{
+}
+
+
+
+//**************************************************************************
+// MEMORY DEVICE MANAGEMENT
+//**************************************************************************
+
+//-------------------------------------------------
+// device_memory_interface - constructor
+//-------------------------------------------------
+
+device_memory_interface::device_memory_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device)
+{
+ memset(m_address_map, 0, sizeof(m_address_map));
+ memset(m_addrspace, 0, sizeof(m_addrspace));
+
+ // configure the fast accessor
+ device.m_memory = this;
+}
+
+
+//-------------------------------------------------
+// ~device_memory_interface - destructor
+//-------------------------------------------------
+
+device_memory_interface::~device_memory_interface()
+{
+}
+
+
+//-------------------------------------------------
+// static_set_vblank_int - configuration helper
+// to set up VBLANK interrupts on the device
+//-------------------------------------------------
+
+void device_memory_interface::static_set_addrmap(device_t &device, address_spacenum spacenum, address_map_constructor map)
+{
+ device_memory_interface *memory;
+ if (!device.interface(memory))
+ throw emu_fatalerror("MCFG_DEVICE_ADDRESS_MAP called on device '%s' with no memory interface", device.tag());
+ if (spacenum >= ARRAY_LENGTH(memory->m_address_map))
+ throw emu_fatalerror("MCFG_DEVICE_ADDRESS_MAP called with out-of-range space number %d", device.tag(), spacenum);
+ memory->m_address_map[spacenum] = map;
+}
+
+
+//-------------------------------------------------
+// set_address_space - connect an address space
+// to a device
+//-------------------------------------------------
+
+void device_memory_interface::set_address_space(address_spacenum spacenum, address_space &space)
+{
+ assert(spacenum < ARRAY_LENGTH(m_addrspace));
+ m_addrspace[spacenum] = &space;
+}
+
+
+//-------------------------------------------------
+// memory_translate - translate from logical to
+// phyiscal addresses; designed to be overridden
+// by the actual device implementation if address
+// translation is supported
+//-------------------------------------------------
+
+bool device_memory_interface::memory_translate(address_spacenum spacenum, int intention, offs_t &address)
+{
+ // by default it maps directly
+ return true;
+}
+
+
+//-------------------------------------------------
+// memory_read - perform internal memory
+// operations that bypass the memory system;
+// designed to be overridden by the actual device
+// implementation if internal read operations are
+// handled by bypassing the memory system
+//-------------------------------------------------
+
+bool device_memory_interface::memory_read(address_spacenum spacenum, offs_t offset, int size, UINT64 &value)
+{
+ // by default, we don't do anything
+ return false;
+}
+
+
+//-------------------------------------------------
+// memory_write - perform internal memory
+// operations that bypass the memory system;
+// designed to be overridden by the actual device
+// implementation if internal write operations are
+// handled by bypassing the memory system
+//-------------------------------------------------
+
+bool device_memory_interface::memory_write(address_spacenum spacenum, offs_t offset, int size, UINT64 value)
+{
+ // by default, we don't do anything
+ return false;
+}
+
+
+//-------------------------------------------------
+// memory_readop - perform internal memory
+// operations that bypass the memory system;
+// designed to be overridden by the actual device
+// implementation if internal opcode fetching
+// operations are handled by bypassing the memory
+// system
+//-------------------------------------------------
+
+bool device_memory_interface::memory_readop(offs_t offset, int size, UINT64 &value)
+{
+ // by default, we don't do anything
+ return false;
+}
+
+
+//-------------------------------------------------
+// interface_validity_check - perform validity
+// checks on the memory configuration
+//-------------------------------------------------
+
+bool device_memory_interface::interface_validity_check(emu_options &options, const game_driver &driver) const
+{
+ bool detected_overlap = DETECT_OVERLAPPING_MEMORY ? false : true;
+ bool error = false;
+
+ // loop over all address spaces
+ for (address_spacenum spacenum = AS_0; spacenum < ADDRESS_SPACES; spacenum++)
+ {
+ const address_space_config *spaceconfig = space_config(spacenum);
+ if (spaceconfig != NULL)
+ {
+ int datawidth = spaceconfig->m_databus_width;
+ int alignunit = datawidth / 8;
+
+ // construct the maps
+ ::address_map *map = global_alloc(::address_map(device(), spacenum));
+
+ // if this is an empty map, just skip it
+ if (map->m_entrylist.first() == NULL)
+ {
+ global_free(map);
+ continue;
+ }
+
+ // validate the global map parameters
+ if (map->m_spacenum != spacenum)
+ {
+ mame_printf_error("%s: %s device '%s' space %d has address space %d handlers!\n", driver.source_file, driver.name, device().tag(), spacenum, map->m_spacenum);
+ error = true;
+ }
+ if (map->m_databits != datawidth)
+ {
+ mame_printf_error("%s: %s device '%s' uses wrong memory handlers for %s space! (width = %d, memory = %08x)\n", driver.source_file, driver.name, device().tag(), spaceconfig->m_name, datawidth, map->m_databits);
+ error = true;
+ }
+
+ // loop over entries and look for errors
+ for (address_map_entry *entry = map->m_entrylist.first(); entry != NULL; entry = entry->next())
+ {
+ UINT32 bytestart = spaceconfig->addr2byte(entry->m_addrstart);
+ UINT32 byteend = spaceconfig->addr2byte_end(entry->m_addrend);
+
+ // look for overlapping entries
+ if (!detected_overlap)
+ {
+ address_map_entry *scan;
+ for (scan = map->m_entrylist.first(); scan != entry; scan = scan->next())
+ if (entry->m_addrstart <= scan->m_addrend && entry->m_addrend >= scan->m_addrstart &&
+ ((entry->m_read.m_type != AMH_NONE && scan->m_read.m_type != AMH_NONE) ||
+ (entry->m_write.m_type != AMH_NONE && scan->m_write.m_type != AMH_NONE)))
+ {
+ mame_printf_warning("%s: %s '%s' %s space has overlapping memory (%X-%X,%d,%d) vs (%X-%X,%d,%d)\n", driver.source_file, driver.name, device().tag(), spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_read.m_type, entry->m_write.m_type, scan->m_addrstart, scan->m_addrend, scan->m_read.m_type, scan->m_write.m_type);
+ detected_overlap = true;
+ break;
+ }
+ }
+
+ // look for inverted start/end pairs
+ if (byteend < bytestart)
+ {
+ mame_printf_error("%s: %s wrong %s memory read handler start = %08x > end = %08x\n", driver.source_file, driver.name, spaceconfig->m_name, entry->m_addrstart, entry->m_addrend);
+ error = true;
+ }
+
+ // look for misaligned entries
+ if ((bytestart & (alignunit - 1)) != 0 || (byteend & (alignunit - 1)) != (alignunit - 1))
+ {
+ mame_printf_error("%s: %s wrong %s memory read handler start = %08x, end = %08x ALIGN = %d\n", driver.source_file, driver.name, spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, alignunit);
+ error = true;
+ }
+
+ // if this is a program space, auto-assign implicit ROM entries
+ if (entry->m_read.m_type == AMH_ROM && entry->m_region == NULL)
+ {
+ entry->m_region = device().tag();
+ entry->m_rgnoffs = entry->m_addrstart;
+ }
+
+ // if this entry references a memory region, validate it
+ if (entry->m_region != NULL && entry->m_share == 0)
+ {
+ // look for the region
+ bool found = false;
+ for (const rom_source *source = rom_first_source(device().mconfig()); source != NULL && !found; source = rom_next_source(*source))
+ for (const rom_entry *romp = rom_first_region(*source); !ROMENTRY_ISEND(romp) && !found; romp++)
+ {
+ const char *regiontag_c = ROMREGION_GETTAG(romp);
+ if (regiontag_c != NULL)
+ {
+ astring fulltag;
+ astring regiontag;
+ if (strchr(entry->m_region,':')) {
+ regiontag = entry->m_region;
+ } else {
+ device().siblingtag(regiontag, entry->m_region);
+ }
+ rom_region_name(fulltag, &driver, source, romp);
+ if (fulltag.cmp(regiontag) == 0)
+ {
+ // verify the address range is within the region's bounds
+ offs_t length = ROMREGION_GETLENGTH(romp);
+ if (entry->m_rgnoffs + (byteend - bytestart + 1) > length)
+ {
+ mame_printf_error("%s: %s device '%s' %s space memory map entry %X-%X extends beyond region '%s' size (%X)\n", driver.source_file, driver.name, device().tag(), spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_region, length);
+ error = true;
+ }
+ found = true;
+ }
+ }
+ }
+
+ // error if not found
+ if (!found)
+ {
+ mame_printf_error("%s: %s device '%s' %s space memory map entry %X-%X references non-existant region '%s'\n", driver.source_file, driver.name, device().tag(), spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_region);
+ error = true;
+ }
+ }
+
+ // make sure all devices exist
+ if ((entry->m_read.m_type == AMH_LEGACY_DEVICE_HANDLER && entry->m_read.m_tag != NULL && device().mconfig().devicelist().find(entry->m_read.m_tag) == NULL) ||
+ (entry->m_write.m_type == AMH_LEGACY_DEVICE_HANDLER && entry->m_write.m_tag != NULL && device().mconfig().devicelist().find(entry->m_write.m_tag) == NULL))
+ {
+ mame_printf_error("%s: %s device '%s' %s space memory map entry references nonexistant device '%s'\n", driver.source_file, driver.name, device().tag(), spaceconfig->m_name, entry->m_write.m_tag);
+ error = true;
+ }
+
+ // make sure ports exist
+// if ((entry->m_read.m_type == AMH_PORT && entry->m_read.m_tag != NULL && portlist.find(entry->m_read.m_tag) == NULL) ||
+// (entry->m_write.m_type == AMH_PORT && entry->m_write.m_tag != NULL && portlist.find(entry->m_write.m_tag) == NULL))
+// {
+// mame_printf_error("%s: %s device '%s' %s space memory map entry references nonexistant port tag '%s'\n", driver.source_file, driver.name, device().tag(), spaceconfig->m_name, entry->m_read.tag);
+// error = true;
+// }
+
+ // validate bank and share tags
+ if (entry->m_read.m_type == AMH_BANK && !validate_tag(driver, "bank", entry->m_read.m_tag))
+ error = true ;
+ if (entry->m_write.m_type == AMH_BANK && !validate_tag(driver, "bank", entry->m_write.m_tag))
+ error = true;
+ if (entry->m_share != NULL && !validate_tag(driver, "share", entry->m_share))
+ error = true;
+ }
+
+ // release the address map
+ global_free(map);
+ }
+ }
+ return error;
+}
diff --git a/trunk/src/emu/dimemory.h b/trunk/src/emu/dimemory.h
new file mode 100644
index 00000000000..b0e2da346bb
--- /dev/null
+++ b/trunk/src/emu/dimemory.h
@@ -0,0 +1,164 @@
+/***************************************************************************
+
+ dimemory.h
+
+ Device memory interfaces.
+
+****************************************************************************
+
+ 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 __DIMEMORY_H__
+#define __DIMEMORY_H__
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// Translation intentions
+const int TRANSLATE_TYPE_MASK = 0x03; // read write or fetch
+const int TRANSLATE_USER_MASK = 0x04; // user mode or fully privileged
+const int TRANSLATE_DEBUG_MASK = 0x08; // debug mode (no side effects)
+
+const int TRANSLATE_READ = 0; // translate for read
+const int TRANSLATE_WRITE = 1; // translate for write
+const int TRANSLATE_FETCH = 2; // translate for instruction fetch
+const int TRANSLATE_READ_USER = (TRANSLATE_READ | TRANSLATE_USER_MASK);
+const int TRANSLATE_WRITE_USER = (TRANSLATE_WRITE | TRANSLATE_USER_MASK);
+const int TRANSLATE_FETCH_USER = (TRANSLATE_FETCH | TRANSLATE_USER_MASK);
+const int TRANSLATE_READ_DEBUG = (TRANSLATE_READ | TRANSLATE_DEBUG_MASK);
+const int TRANSLATE_WRITE_DEBUG = (TRANSLATE_WRITE | TRANSLATE_DEBUG_MASK);
+const int TRANSLATE_FETCH_DEBUG = (TRANSLATE_FETCH | TRANSLATE_DEBUG_MASK);
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_DEVICE_ADDRESS_MAP(_space, _map) \
+ device_memory_interface::static_set_addrmap(*device, _space, ADDRESS_MAP_NAME(_map));
+
+#define MCFG_DEVICE_PROGRAM_MAP(_map) \
+ MCFG_DEVICE_ADDRESS_MAP(AS_PROGRAM, _map)
+
+#define MCFG_DEVICE_DATA_MAP(_map) \
+ MCFG_DEVICE_ADDRESS_MAP(AS_DATA, _map)
+
+#define MCFG_DEVICE_IO_MAP(_map) \
+ MCFG_DEVICE_ADDRESS_MAP(AS_IO, _map)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> device_memory_interface
+
+class device_memory_interface : public device_interface
+{
+ friend class device_scheduler;
+
+public:
+ // construction/destruction
+ device_memory_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_memory_interface();
+
+ // configuration access
+ address_map_constructor address_map(address_spacenum spacenum = AS_0) const { return (spacenum < ARRAY_LENGTH(m_address_map)) ? m_address_map[spacenum] : NULL; }
+ const address_space_config *space_config(address_spacenum spacenum = AS_0) const { return memory_space_config(spacenum); }
+
+ // static inline configuration helpers
+ static void static_set_addrmap(device_t &device, address_spacenum spacenum, address_map_constructor map);
+
+ // basic information getters
+ address_space *space(int index = 0) const { return m_addrspace[index]; }
+ address_space *space(address_spacenum index) const { return m_addrspace[static_cast<int>(index)]; }
+
+ // address space accessors
+ void set_address_space(address_spacenum spacenum, address_space &space);
+
+ // address translation
+ bool translate(address_spacenum spacenum, int intention, offs_t &address) { return memory_translate(spacenum, intention, address); }
+
+ // read/write access
+ bool read(address_spacenum spacenum, offs_t offset, int size, UINT64 &value) { return memory_read(spacenum, offset, size, value); }
+ bool write(address_spacenum spacenum, offs_t offset, int size, UINT64 value) { return memory_write(spacenum, offset, size, value); }
+ bool readop(offs_t offset, int size, UINT64 &value) { return memory_readop(offset, size, value); }
+
+protected:
+ // required overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum) const = 0;
+
+ // optional operation overrides
+ virtual bool memory_translate(address_spacenum spacenum, int intention, offs_t &address);
+ virtual bool memory_read(address_spacenum spacenum, offs_t offset, int size, UINT64 &value);
+ virtual bool memory_write(address_spacenum spacenum, offs_t offset, int size, UINT64 value);
+ virtual bool memory_readop(offs_t offset, int size, UINT64 &value);
+
+ // interface-level overrides
+ virtual bool interface_validity_check(emu_options &options, const game_driver &driver) const;
+
+ // configuration
+ address_map_constructor m_address_map[ADDRESS_SPACES]; // address maps for each address space
+ address_space * m_addrspace[ADDRESS_SPACES]; // reported address spaces
+};
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// device_get_space_config - return a pointer
+// to sthe given address space's configuration
+//-------------------------------------------------
+
+inline const address_space_config *device_get_space_config(const device_t &device, address_spacenum spacenum = AS_0)
+{
+ const device_memory_interface *intf;
+ if (!device.interface(intf))
+ throw emu_fatalerror("Device '%s' does not have memory interface", device.tag());
+ return intf->space_config(spacenum);
+}
+
+
+#endif /* __DIMEMORY_H__ */
diff --git a/trunk/src/emu/dinvram.c b/trunk/src/emu/dinvram.c
new file mode 100644
index 00000000000..60594c1e6de
--- /dev/null
+++ b/trunk/src/emu/dinvram.c
@@ -0,0 +1,64 @@
+/***************************************************************************
+
+ dinvram.c
+
+ Device NVRAM interfaces.
+
+****************************************************************************
+
+ 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"
+
+
+
+//**************************************************************************
+// DEVICE NVRAM INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_nvram_interface - constructor
+//-------------------------------------------------
+
+device_nvram_interface::device_nvram_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device)
+{
+}
+
+
+//-------------------------------------------------
+// ~device_nvram_interface - destructor
+//-------------------------------------------------
+
+device_nvram_interface::~device_nvram_interface()
+{
+}
diff --git a/trunk/src/emu/dinvram.h b/trunk/src/emu/dinvram.h
new file mode 100644
index 00000000000..30b490c60a1
--- /dev/null
+++ b/trunk/src/emu/dinvram.h
@@ -0,0 +1,78 @@
+/***************************************************************************
+
+ dinvram.h
+
+ Device NVRAM interfaces.
+
+****************************************************************************
+
+ 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 __DINVRAM_H__
+#define __DINVRAM_H__
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> device_nvram_interface
+
+// class representing interface-specific live nvram
+class device_nvram_interface : public device_interface
+{
+public:
+ // construction/destruction
+ device_nvram_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_nvram_interface();
+
+ // public accessors... for now
+ void nvram_reset() { nvram_default(); }
+ void nvram_load(emu_file &file) { nvram_read(file); }
+ void nvram_save(emu_file &file) { nvram_write(file); }
+
+protected:
+ // derived class overrides
+ virtual void nvram_default() = 0;
+ virtual void nvram_read(emu_file &file) = 0;
+ virtual void nvram_write(emu_file &file) = 0;
+};
+
+
+#endif /* __DINVRAM_H__ */
diff --git a/trunk/src/emu/dirtc.c b/trunk/src/emu/dirtc.c
new file mode 100644
index 00000000000..0483be355ac
--- /dev/null
+++ b/trunk/src/emu/dirtc.c
@@ -0,0 +1,33 @@
+/***************************************************************************
+
+ dirtc.c
+
+ Device Real Time Clock interfaces.
+
+***************************************************************************/
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// DEVICE RTC INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_rtc_interface - constructor
+//-------------------------------------------------
+
+device_rtc_interface::device_rtc_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device)
+{
+}
+
+
+//-------------------------------------------------
+// ~device_rtc_interface - destructor
+//-------------------------------------------------
+
+device_rtc_interface::~device_rtc_interface()
+{
+}
diff --git a/trunk/src/emu/dirtc.h b/trunk/src/emu/dirtc.h
new file mode 100644
index 00000000000..ba1b238eecf
--- /dev/null
+++ b/trunk/src/emu/dirtc.h
@@ -0,0 +1,41 @@
+/***************************************************************************
+
+ dirtc.h
+
+ Device Real Time Clock interfaces.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __EMU_H__
+#error Dont include this file directly; include emu.h instead.
+#endif
+
+#ifndef __DIRTC_H__
+#define __DIRTC_H__
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> device_rtc_interface
+
+// class representing interface-specific live rtc
+class device_rtc_interface : public device_interface
+{
+public:
+ // construction/destruction
+ device_rtc_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_rtc_interface();
+
+protected:
+ // derived class overrides
+ virtual void rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second) = 0;
+ virtual bool rtc_is_year_2000_compliant() = 0;
+};
+
+
+#endif /* __DIRTC_H__ */
diff --git a/trunk/src/emu/dislot.c b/trunk/src/emu/dislot.c
new file mode 100644
index 00000000000..175ea8eaedb
--- /dev/null
+++ b/trunk/src/emu/dislot.c
@@ -0,0 +1,52 @@
+/***************************************************************************
+
+ Slot device
+
+***************************************************************************/
+
+#include "emu.h"
+#include "emuopts.h"
+
+device_slot_interface::device_slot_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device)
+{
+}
+
+device_slot_interface::~device_slot_interface()
+{
+}
+
+
+void device_slot_interface::static_set_slot_info(device_t &device, const slot_interface *slots_info, const char *default_card,const input_device_default *default_input)
+{
+ device_slot_interface *slot;
+ if (!device.interface(slot))
+ throw emu_fatalerror("set_default_slot_card called on device '%s' with no slot interface", device.tag());
+
+ slot->m_slot_interfaces = slots_info;
+ slot->m_default_card = default_card;
+ slot->m_input_defaults = default_input;
+}
+
+device_t* device_slot_interface::get_card_device()
+{
+ const char *subtag = device().machine().options().value(device().tag());
+ device_t *dev = NULL;
+ if (subtag) {
+ device_slot_card_interface *intf = NULL;
+ dev = device().subdevice(subtag);
+ if (dev!=NULL && !dev->interface(intf))
+ throw emu_fatalerror("get_card_device called for device '%s' with no slot card interface", dev->tag());
+ }
+ return dev;
+}
+
+device_slot_card_interface::device_slot_card_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device)
+{
+}
+
+device_slot_card_interface::~device_slot_card_interface()
+{
+}
+
diff --git a/trunk/src/emu/dislot.h b/trunk/src/emu/dislot.h
new file mode 100644
index 00000000000..20e5eb361b1
--- /dev/null
+++ b/trunk/src/emu/dislot.h
@@ -0,0 +1,68 @@
+#pragma once
+
+#ifndef __EMU_H__
+#error Dont include this file directly; include emu.h instead.
+#endif
+
+#ifndef __DISLOT_H__
+#define __DISLOT_H__
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+// ======================> device_slot_interface
+
+struct slot_interface
+{
+ const char * name;
+ const device_type & devtype;
+};
+
+#define MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, _def_inp) \
+ device_slot_interface::static_set_slot_info(*device, SLOT_INTERFACE_NAME(_slot_intf), _def_slot, DEVICE_INPUT_DEFAULTS_NAME(_def_inp));
+
+#define SLOT_INTERFACE_NAME(name) slot_interface_##name
+
+#define SLOT_INTERFACE_START(name) \
+ const slot_interface slot_interface_##name[] = \
+ { \
+
+#define SLOT_INTERFACE(tag,device) \
+ { tag, device }, \
+
+#define SLOT_INTERFACE_END \
+ { NULL, NULL } \
+ };
+
+class device_slot_card_interface;
+
+class device_slot_interface : public device_interface
+{
+public:
+ // construction/destruction
+ device_slot_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_slot_interface();
+
+ static void static_set_slot_info(device_t &device, const slot_interface *slots_info, const char *default_card,const input_device_default *default_input);
+ const slot_interface* get_slot_interfaces() const { return m_slot_interfaces; };
+ virtual const char * get_default_card(const device_list &devlist, emu_options &options) const { return m_default_card; };
+ const input_device_default *input_ports_defaults() const { return m_input_defaults; }
+ device_t* get_card_device();
+protected:
+ const char *m_default_card;
+ const input_device_default *m_input_defaults;
+ const slot_interface *m_slot_interfaces;
+};
+
+// ======================> device_slot_card_interface
+
+class device_slot_card_interface : public device_interface
+{
+public:
+ // construction/destruction
+ device_slot_card_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_slot_card_interface();
+};
+
+#endif /* __DISLOT_H__ */
diff --git a/trunk/src/emu/disound.c b/trunk/src/emu/disound.c
new file mode 100644
index 00000000000..4045c72ce58
--- /dev/null
+++ b/trunk/src/emu/disound.c
@@ -0,0 +1,366 @@
+/***************************************************************************
+
+ disound.c
+
+ Device sound interfaces.
+
+****************************************************************************
+
+ 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"
+
+
+
+//**************************************************************************
+// DEVICE CONFIG SOUND INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_sound_interface - constructor
+//-------------------------------------------------
+
+device_sound_interface::device_sound_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device),
+ m_outputs(0),
+ m_auto_allocated_inputs(0)
+{
+}
+
+
+//-------------------------------------------------
+// ~device_sound_interface - destructor
+//-------------------------------------------------
+
+device_sound_interface::~device_sound_interface()
+{
+}
+
+
+//-------------------------------------------------
+// static_add_route - configuration helper to add
+// a new route to the device
+//-------------------------------------------------
+
+void device_sound_interface::static_add_route(device_t &device, UINT32 output, const char *target, double gain, UINT32 input)
+{
+ // find our sound interface
+ device_sound_interface *sound;
+ if (!device.interface(sound))
+ throw emu_fatalerror("MCFG_SOUND_ROUTE called on device '%s' with no sound interface", device.tag());
+
+ // append a new route to the list
+ astring devtag;
+ device.siblingtag(devtag, target);
+ sound->m_route_list.append(*global_alloc(sound_route(output, input, gain, devtag.cstr())));
+}
+
+
+//-------------------------------------------------
+// static_reset_routes - configuration helper to
+// reset all existing routes to the device
+//-------------------------------------------------
+
+void device_sound_interface::static_reset_routes(device_t &device)
+{
+ // find our sound interface
+ device_sound_interface *sound;
+ if (!device.interface(sound))
+ throw emu_fatalerror("MCFG_SOUND_ROUTES_RESET called on device '%s' with no sound interface", device.tag());
+
+ // reset the routine list
+ sound->m_route_list.reset();
+}
+
+
+//-------------------------------------------------
+// inputs - return the total number of inputs
+// for the given device
+//-------------------------------------------------
+
+int device_sound_interface::inputs() const
+{
+ // scan the list counting streams we own and summing their inputs
+ int inputs = 0;
+ for (sound_stream *stream = m_device.machine().sound().first_stream(); stream != NULL; stream = stream->next())
+ if (&stream->device() == &m_device)
+ inputs += stream->input_count();
+ return inputs;
+}
+
+
+//-------------------------------------------------
+// outputs - return the total number of outputs
+// for the given device
+//-------------------------------------------------
+
+int device_sound_interface::outputs() const
+{
+ // scan the list counting streams we own and summing their outputs
+ int outputs = 0;
+ for (sound_stream *stream = m_device.machine().sound().first_stream(); stream != NULL; stream = stream->next())
+ if (&stream->device() == &m_device)
+ outputs += stream->output_count();
+ return outputs;
+}
+
+
+//-------------------------------------------------
+// input_to_stream_input - convert a device's
+// input index to a stream and the input index
+// on that stream
+//-------------------------------------------------
+
+sound_stream *device_sound_interface::input_to_stream_input(int inputnum, int &stream_inputnum)
+{
+ assert(inputnum >= 0);
+
+ // scan the list looking for streams owned by this device
+ for (sound_stream *stream = m_device.machine().sound().first_stream(); stream != NULL; stream = stream->next())
+ if (&stream->device() == &m_device)
+ {
+ if (inputnum < stream->input_count())
+ {
+ stream_inputnum = inputnum;
+ return stream;
+ }
+ inputnum -= stream->input_count();
+ }
+
+ // not found
+ return NULL;
+}
+
+
+//-------------------------------------------------
+// output_to_stream_output - convert a device's
+// output index to a stream and the output index
+// on that stream
+//-------------------------------------------------
+
+sound_stream *device_sound_interface::output_to_stream_output(int outputnum, int &stream_outputnum)
+{
+ assert(outputnum >= 0);
+
+ // scan the list looking for streams owned by this device
+ for (sound_stream *stream = m_device.machine().sound().first_stream(); stream != NULL; stream = stream->next())
+ if (&stream->device() == &device())
+ {
+ if (outputnum < stream->output_count())
+ {
+ stream_outputnum = outputnum;
+ return stream;
+ }
+ outputnum -= stream->output_count();
+ }
+
+ // not found
+ return NULL;
+}
+
+
+//-------------------------------------------------
+// set_output_gain - set the gain on the given
+// output index of the device
+//-------------------------------------------------
+
+void device_sound_interface::set_output_gain(int outputnum, float gain)
+{
+ // handle ALL_OUTPUTS as a special case
+ if (outputnum == ALL_OUTPUTS)
+ {
+ for (sound_stream *stream = m_device.machine().sound().first_stream(); stream != NULL; stream = stream->next())
+ if (&stream->device() == &device())
+ for (int outputnum = 0; outputnum < stream->output_count(); outputnum++)
+ stream->set_output_gain(outputnum, gain);
+ }
+
+ // look up the stream and stream output index
+ else
+ {
+ int stream_outputnum;
+ sound_stream *stream = output_to_stream_output(outputnum, stream_outputnum);
+ if (stream != NULL)
+ stream->set_output_gain(stream_outputnum, gain);
+ }
+}
+
+
+//-------------------------------------------------
+// interface_validity_check - validation for a
+// device after the configuration has been
+// constructed
+//-------------------------------------------------
+
+bool device_sound_interface::interface_validity_check(emu_options &options, const game_driver &driver) const
+{
+ bool error = false;
+
+ // loop over all the routes
+ for (const sound_route *route = first_route(); route != NULL; route = route->next())
+ {
+ // find a device with the requested tag
+ const device_t *target = device().mconfig().devicelist().find(route->m_target.cstr());
+ if (target == NULL)
+ {
+ mame_printf_error("%s: %s attempting to route sound to non-existant device '%s'\n", driver.source_file, driver.name, route->m_target.cstr());
+ error = true;
+ }
+
+ // if it's not a speaker or a sound device, error
+ const device_sound_interface *sound;
+ if (target != NULL && target->type() != SPEAKER && !target->interface(sound))
+ {
+ mame_printf_error("%s: %s attempting to route sound to a non-sound device '%s' (%s)\n", driver.source_file, driver.name, route->m_target.cstr(), target->name());
+ error = true;
+ }
+ }
+ return error;
+}
+
+
+//-------------------------------------------------
+// interface_pre_start - make sure all our input
+// devices are started
+//-------------------------------------------------
+
+void device_sound_interface::interface_pre_start()
+{
+ // scan all the sound devices
+ device_sound_interface *sound = NULL;
+ for (bool gotone = m_device.machine().devicelist().first(sound); gotone; gotone = sound->next(sound))
+ {
+ // scan each route on the device
+ for (const sound_route *route = sound->first_route(); route != NULL; route = route->next())
+ {
+ // see if we are the target of this route; if we are, make sure the source device is started
+ device_t *target_device = m_device.machine().device(route->m_target);
+ if (target_device == &m_device && !sound->device().started())
+ throw device_missing_dependencies();
+ }
+ }
+
+ // now iterate through devices again and assign any auto-allocated inputs
+ m_auto_allocated_inputs = 0;
+ for (bool gotone = m_device.machine().devicelist().first(sound); gotone; gotone = sound->next(sound))
+ {
+ // scan each route on the device
+ for (const sound_route *route = sound->first_route(); route != NULL; route = route->next())
+ {
+ // see if we are the target of this route
+ device_t *target_device = m_device.machine().device(route->m_target);
+ if (target_device == &m_device && route->m_input == AUTO_ALLOC_INPUT)
+ {
+ const_cast<sound_route *>(route)->m_input = m_auto_allocated_inputs;
+ m_auto_allocated_inputs += (route->m_output == ALL_OUTPUTS) ? sound->outputs() : 1;
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// interface_post_start - verify that state was
+// properly set up
+//-------------------------------------------------
+
+void device_sound_interface::interface_post_start()
+{
+ // iterate over all the sound devices
+ device_sound_interface *sound = NULL;
+ for (bool gotone = m_device.machine().devicelist().first(sound); gotone; gotone = sound->next(sound))
+ {
+ // scan each route on the device
+ for (const sound_route *route = sound->first_route(); route != NULL; route = route->next())
+ {
+ // if we are the target of this route, hook it up
+ device_t *target_device = m_device.machine().device(route->m_target);
+ if (target_device == &m_device)
+ {
+ // iterate over all outputs, matching any that apply
+ int inputnum = route->m_input;
+ int numoutputs = sound->outputs();
+ for (int outputnum = 0; outputnum < numoutputs; outputnum++)
+ if (route->m_output == outputnum || route->m_output == ALL_OUTPUTS)
+ {
+ // find the output stream to connect from
+ int streamoutputnum;
+ sound_stream *outputstream = sound->output_to_stream_output(outputnum, streamoutputnum);
+ if (outputstream == NULL)
+ fatalerror("Sound device '%s' specifies route for non-existant output #%d", route->m_target.cstr(), outputnum);
+
+ // find the input stream to connect to
+ int streaminputnum;
+ sound_stream *inputstream = input_to_stream_input(inputnum++, streaminputnum);
+ if (inputstream == NULL)
+ fatalerror("Sound device '%s' targeted output #%d to non-existant device '%s' input %d", route->m_target.cstr(), outputnum, m_device.tag(), inputnum - 1);
+
+ // set the input
+ inputstream->set_input(streaminputnum, outputstream, streamoutputnum, route->m_gain);
+ }
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// interface_pre_reset - called prior to
+// resetting the device
+//-------------------------------------------------
+
+void device_sound_interface::interface_pre_reset()
+{
+ // update all streams on this device prior to reset
+ for (sound_stream *stream = m_device.machine().sound().first_stream(); stream != NULL; stream = stream->next())
+ if (&stream->device() == &device())
+ stream->update();
+}
+
+
+
+//**************************************************************************
+// SOUND ROUTE
+//**************************************************************************
+
+//-------------------------------------------------
+// sound_route - constructor
+//-------------------------------------------------
+
+device_sound_interface::sound_route::sound_route(int output, int input, float gain, const char *target)
+ : m_next(NULL),
+ m_output(output),
+ m_input(input),
+ m_gain(gain),
+ m_target(target)
+{
+}
diff --git a/trunk/src/emu/disound.h b/trunk/src/emu/disound.h
new file mode 100644
index 00000000000..6eae08c3076
--- /dev/null
+++ b/trunk/src/emu/disound.h
@@ -0,0 +1,150 @@
+/***************************************************************************
+
+ disound.h
+
+ Device sound interfaces.
+
+****************************************************************************
+
+ 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 __DISOUND_H__
+#define __DISOUND_H__
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+const int ALL_OUTPUTS = 65535; // special value indicating all outputs for the current chip
+const int AUTO_ALLOC_INPUT = 65535;
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_SOUND_ADD(_tag, _type, _clock) \
+ MCFG_DEVICE_ADD(_tag, _type, _clock) \
+
+#define MCFG_SOUND_MODIFY(_tag) \
+ MCFG_DEVICE_MODIFY(_tag)
+
+#define MCFG_SOUND_CLOCK(_clock) \
+ MCFG_DEVICE_CLOCK(_clock)
+
+#define MCFG_SOUND_REPLACE(_tag, _type, _clock) \
+ MCFG_DEVICE_REPLACE(_tag, _type, _clock)
+
+#define MCFG_SOUND_CONFIG(_config) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MCFG_SOUND_ROUTE_EX(_output, _target, _gain, _input) \
+ device_sound_interface::static_add_route(*device, _output, _target, _gain, _input); \
+
+#define MCFG_SOUND_ROUTE(_output, _target, _gain) \
+ MCFG_SOUND_ROUTE_EX(_output, _target, _gain, AUTO_ALLOC_INPUT)
+
+#define MCFG_SOUND_ROUTES_RESET() \
+ device_sound_interface::static_reset_routes(*device); \
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class sound_stream;
+
+
+// ======================> device_sound_interface
+
+class device_sound_interface : public device_interface
+{
+public:
+ class sound_route
+ {
+ public:
+ sound_route(int output, int input, float gain, const char *target);
+
+ const sound_route *next() const { return m_next; }
+
+ sound_route * m_next; // pointer to next route
+ UINT32 m_output; // output index, or ALL_OUTPUTS
+ UINT32 m_input; // target input index
+ float m_gain; // gain
+ astring m_target; // target tag
+ };
+
+ // construction/destruction
+ device_sound_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_sound_interface();
+
+ // configuration access
+ const sound_route *first_route() const { return m_route_list.first(); }
+
+ // static inline configuration helpers
+ static void static_add_route(device_t &device, UINT32 output, const char *target, double gain, UINT32 input = AUTO_ALLOC_INPUT);
+ static void static_reset_routes(device_t &device);
+
+ // sound stream update overrides
+ virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) = 0;
+
+ // helpers
+ int inputs() const;
+ int outputs() const;
+ sound_stream *input_to_stream_input(int inputnum, int &stream_inputnum);
+ sound_stream *output_to_stream_output(int outputnum, int &stream_outputnum);
+ void set_output_gain(int outputnum, float gain);
+
+protected:
+ // optional operation overrides
+ virtual bool interface_validity_check(emu_options &options, const game_driver &driver) const;
+ virtual void interface_pre_start();
+ virtual void interface_post_start();
+ virtual void interface_pre_reset();
+
+ // internal state
+ simple_list<sound_route> m_route_list; // list of sound routes
+ int m_outputs; // number of outputs from this instance
+ int m_auto_allocated_inputs; // number of auto-allocated inputs targeting us
+};
+
+
+#endif /* __DISOUND_H__ */
diff --git a/trunk/src/emu/distate.c b/trunk/src/emu/distate.c
new file mode 100644
index 00000000000..903306f27ea
--- /dev/null
+++ b/trunk/src/emu/distate.c
@@ -0,0 +1,608 @@
+/***************************************************************************
+
+ distate.c
+
+ Device state interfaces.
+
+****************************************************************************
+
+ 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"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const UINT64 device_state_entry::k_decimal_divisor[] =
+{
+ 1,
+ 10,
+ 100,
+ 1000,
+ 10000,
+ 100000,
+ 1000000,
+ 10000000,
+ 100000000,
+ 1000000000,
+ U64(10000000000),
+ U64(100000000000),
+ U64(1000000000000),
+ U64(10000000000000),
+ U64(100000000000000),
+ U64(1000000000000000),
+ U64(10000000000000000),
+ U64(100000000000000000),
+ U64(1000000000000000000),
+ U64(10000000000000000000)
+};
+
+
+
+//**************************************************************************
+// DEVICE STATE ENTRY
+//**************************************************************************
+
+//-------------------------------------------------
+// device_state_entry - constructor
+//-------------------------------------------------
+
+device_state_entry::device_state_entry(int index, const char *symbol, void *dataptr, UINT8 size)
+ : m_next(NULL),
+ m_index(index),
+ m_datamask(0),
+ m_datasize(size),
+ m_flags(0),
+ m_symbol(symbol),
+ m_default_format(true),
+ m_sizemask(0)
+{
+ // set the data pointer
+ m_dataptr.v = dataptr;
+
+ // convert the size to a mask
+ assert(size == 1 || size == 2 || size == 4 || size == 8);
+ if (size == 1)
+ m_sizemask = 0xff;
+ else if (size == 2)
+ m_sizemask = 0xffff;
+ else if (size == 4)
+ m_sizemask = 0xffffffff;
+ else
+ m_sizemask = ~U64(0);
+
+ // default the data mask to the same
+ m_datamask = m_sizemask;
+ format_from_mask();
+
+ // override well-known symbols
+ if (index == STATE_GENPC)
+ m_symbol.cpy("CURPC");
+ else if (index == STATE_GENPCBASE)
+ m_symbol.cpy("CURPCBASE");
+ else if (index == STATE_GENSP)
+ m_symbol.cpy("CURSP");
+ else if (index == STATE_GENFLAGS)
+ m_symbol.cpy("CURFLAGS");
+}
+
+
+//-------------------------------------------------
+// formatstr - specify a format string
+//-------------------------------------------------
+
+device_state_entry &device_state_entry::formatstr(const char *_format)
+{
+ m_format.cpy(_format);
+ m_default_format = false;
+
+ // set the DSF_CUSTOM_STRING flag by formatting with a NULL string
+ m_flags &= ~DSF_CUSTOM_STRING;
+ astring dummy;
+ format(dummy, NULL);
+
+ return *this;
+}
+
+
+//-------------------------------------------------
+// format_from_mask - make a format based on
+// the data mask
+//-------------------------------------------------
+
+void device_state_entry::format_from_mask()
+{
+ // skip if we have a user-provided format
+ if (!m_default_format)
+ return;
+
+ // make up a format based on the mask
+ int width = 0;
+ for (UINT64 tempmask = m_datamask; tempmask != 0; tempmask >>= 4)
+ width++;
+ m_format.printf("%%0%dX", width);
+}
+
+
+//-------------------------------------------------
+// value - return the current value as a UINT64
+//-------------------------------------------------
+
+UINT64 device_state_entry::value() const
+{
+ // pick up the value
+ UINT64 result = ~(UINT64)0;
+ switch (m_datasize)
+ {
+ default:
+ case 1: result = *m_dataptr.u8; break;
+ case 2: result = *m_dataptr.u16; break;
+ case 4: result = *m_dataptr.u32; break;
+ case 8: result = *m_dataptr.u64; break;
+ }
+ return result & m_datamask;
+}
+
+
+//-------------------------------------------------
+// format - return the value of the given
+// pieces of indexed state as a string
+//-------------------------------------------------
+
+astring &device_state_entry::format(astring &dest, const char *string, bool maxout) const
+{
+ UINT64 result = value();
+
+ // parse the format
+ bool leadzero = false;
+ bool percent = false;
+ bool explicitsign = false;
+ bool hitnonzero = false;
+ bool reset = true;
+ int width = 0;
+ for (const char *fptr = m_format; *fptr != 0; fptr++)
+ {
+ // reset any accumulated state
+ if (reset)
+ {
+ leadzero = maxout;
+ percent = explicitsign = reset = false;
+ width = 0;
+ }
+
+ // if we're not within a format, then anything other than a % outputs directly
+ if (!percent && *fptr != '%')
+ {
+ dest.cat(fptr, 1);
+ continue;
+ }
+
+ // handle each character in turn
+ switch (*fptr)
+ {
+ // % starts a format; %% outputs a single %
+ case '%':
+ if (!percent)
+ percent = true;
+ else
+ {
+ dest.cat(fptr, 1);
+ percent = false;
+ }
+ break;
+
+ // 0 means insert leading 0s, unless it follows another width digit
+ case '0':
+ if (width == 0)
+ leadzero = true;
+ else
+ width *= 10;
+ break;
+
+ // 1-9 accumulate into the width
+ case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9':
+ width = width * 10 + (*fptr - '0');
+ break;
+
+ // + means explicit sign
+ case '+':
+ explicitsign = true;
+ break;
+
+ // X outputs as hexadecimal
+ case 'X':
+ if (width == 0)
+ throw emu_fatalerror("Width required for %%X formats\n");
+ hitnonzero = false;
+ while (leadzero && width > 16)
+ {
+ dest.cat(" ");
+ width--;
+ }
+ for (int digitnum = 15; digitnum >= 0; digitnum--)
+ {
+ int digit = (result >> (4 * digitnum)) & 0x0f;
+ if (digit != 0)
+ {
+ static const char hexchars[] = "0123456789ABCDEF";
+ dest.cat(&hexchars[digit], 1);
+ hitnonzero = true;
+ }
+ else if (hitnonzero || (leadzero && digitnum < width) || digitnum == 0)
+ dest.cat("0");
+ }
+ reset = true;
+ break;
+
+ // d outputs as signed decimal
+ case 'd':
+ if (width == 0)
+ throw emu_fatalerror("Width required for %%d formats\n");
+ if ((result & m_datamask) > (m_datamask >> 1))
+ {
+ result = -result & m_datamask;
+ dest.cat("-");
+ width--;
+ }
+ else if (explicitsign)
+ {
+ dest.cat("+");
+ width--;
+ }
+ // fall through to unsigned case
+
+ // u outputs as unsigned decimal
+ case 'u':
+ if (width == 0)
+ throw emu_fatalerror("Width required for %%u formats\n");
+ hitnonzero = false;
+ while (leadzero && width > ARRAY_LENGTH(k_decimal_divisor))
+ {
+ dest.cat(" ");
+ width--;
+ }
+ for (int digitnum = ARRAY_LENGTH(k_decimal_divisor) - 1; digitnum >= 0; digitnum--)
+ {
+ int digit = (result >= k_decimal_divisor[digitnum]) ? (result / k_decimal_divisor[digitnum]) % 10 : 0;
+ if (digit != 0)
+ {
+ static const char decchars[] = "0123456789";
+ dest.cat(&decchars[digit], 1);
+ hitnonzero = true;
+ }
+ else if (hitnonzero || (leadzero && digitnum < width) || digitnum == 0)
+ dest.cat("0");
+ }
+ reset = true;
+ break;
+
+ // s outputs a custom string
+ case 's':
+ if (width == 0)
+ throw emu_fatalerror("Width required for %%s formats\n");
+ if (string == NULL)
+ {
+ const_cast<device_state_entry *>(this)->m_flags |= DSF_CUSTOM_STRING;
+ return dest;
+ }
+ if (strlen(string) <= width)
+ {
+ dest.cat(string);
+ width -= strlen(string);
+ while (width-- != 0)
+ dest.cat(" ");
+ }
+ else
+ dest.cat(string, width);
+ reset = true;
+ break;
+
+ // other formats unknown
+ default:
+ throw emu_fatalerror("Unknown format character '%c'\n", *fptr);
+ break;
+ }
+ }
+ return dest;
+}
+
+
+//-------------------------------------------------
+// set_value - set the value from a UINT64
+//-------------------------------------------------
+
+void device_state_entry::set_value(UINT64 value) const
+{
+ // apply the mask
+ value &= m_datamask;
+
+ // sign-extend if necessary
+ if ((m_flags & DSF_IMPORT_SEXT) != 0 && value > (m_datamask >> 1))
+ value |= ~m_datamask;
+
+ // store the value
+ switch (m_datasize)
+ {
+ default:
+ case 1: *m_dataptr.u8 = value; break;
+ case 2: *m_dataptr.u16 = value; break;
+ case 4: *m_dataptr.u32 = value; break;
+ case 8: *m_dataptr.u64 = value; break;
+ }
+}
+
+
+//-------------------------------------------------
+// set_value - set the value from a string
+//-------------------------------------------------
+
+void device_state_entry::set_value(const char *string) const
+{
+ // not implemented
+}
+
+
+
+//**************************************************************************
+// DEVICE STATE INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_state_interface - constructor
+//-------------------------------------------------
+
+device_state_interface::device_state_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device)
+{
+ memset(m_fast_state, 0, sizeof(m_fast_state));
+
+ // configure the fast accessor
+ device.m_state = this;
+}
+
+
+//-------------------------------------------------
+// ~device_state_interface - destructor
+//-------------------------------------------------
+
+device_state_interface::~device_state_interface()
+{
+}
+
+
+//-------------------------------------------------
+// state - return the value of the given piece
+// of indexed state as a UINT64
+//-------------------------------------------------
+
+UINT64 device_state_interface::state(int index)
+{
+ // NULL or out-of-range entry returns 0
+ const device_state_entry *entry = state_find_entry(index);
+ if (entry == NULL)
+ return 0;
+
+ // call the exporter before we do anything
+ if (entry->needs_export())
+ state_export(*entry);
+
+ // pick up the value
+ return entry->value();
+}
+
+
+//-------------------------------------------------
+// state_string - return the value of the given
+// pieces of indexed state as a string
+//-------------------------------------------------
+
+astring &device_state_interface::state_string(int index, astring &dest)
+{
+ // NULL or out-of-range entry returns bogus string
+ const device_state_entry *entry = state_find_entry(index);
+ if (entry == NULL)
+ return dest.cpy("???");
+
+ // get the custom string if needed
+ astring custom;
+ if (entry->needs_custom_string())
+ state_string_export(*entry, custom);
+
+ // ask the entry to format itself
+ return entry->format(dest, custom);
+}
+
+
+//-------------------------------------------------
+// state_string_max_length - return the maximum
+// length of the given state string
+//-------------------------------------------------
+
+int device_state_interface::state_string_max_length(int index)
+{
+ // NULL or out-of-range entry returns bogus string
+ const device_state_entry *entry = state_find_entry(index);
+ if (entry == NULL)
+ return 3;
+
+ // ask the entry to format itself maximally
+ astring tempstring;
+ return entry->format(tempstring, "", true).len();
+}
+
+
+//-------------------------------------------------
+// set_state - set the value of the given piece
+// of indexed state from a UINT64
+//-------------------------------------------------
+
+void device_state_interface::set_state(int index, UINT64 value)
+{
+ // NULL or out-of-range entry is a no-op
+ const device_state_entry *entry = state_find_entry(index);
+ if (entry == NULL)
+ return;
+
+ // set the value
+ entry->set_value(value);
+
+ // call the importer to finish up
+ if (entry->needs_import())
+ state_import(*entry);
+}
+
+
+//-------------------------------------------------
+// set_state - set the value of the given piece
+// of indexed state from a string
+//-------------------------------------------------
+
+void device_state_interface::set_state(int index, const char *string)
+{
+ // NULL or out-of-range entry is a no-op
+ const device_state_entry *entry = state_find_entry(index);
+ if (entry == NULL)
+ return;
+
+ // set the value
+ entry->set_value(string);
+
+ // call the importer to finish up
+ if (entry->needs_import())
+ state_import(*entry);
+}
+
+
+//-------------------------------------------------
+// state_add - return the value of the given
+// pieces of indexed state as a UINT64
+//-------------------------------------------------
+
+device_state_entry &device_state_interface::state_add(int index, const char *symbol, void *data, UINT8 size)
+{
+ // assert validity of incoming parameters
+ assert(size == 1 || size == 2 || size == 4 || size == 8);
+ assert(symbol != NULL);
+
+ // allocate new entry
+ device_state_entry *entry = auto_alloc(device().machine(), device_state_entry(index, symbol, data, size));
+
+ // append to the end of the list
+ m_state_list.append(*entry);
+
+ // set the fast entry if applicable
+ if (index >= k_fast_state_min && index <= k_fast_state_max)
+ m_fast_state[index - k_fast_state_min] = entry;
+
+ return *entry;
+}
+
+
+//-------------------------------------------------
+// state_import - called after new state is
+// written to perform any post-processing
+//-------------------------------------------------
+
+void device_state_interface::state_import(const device_state_entry &entry)
+{
+ // do nothing by default
+}
+
+
+//-------------------------------------------------
+// state_export - called prior to new state
+// reading the state
+//-------------------------------------------------
+
+void device_state_interface::state_export(const device_state_entry &entry)
+{
+ // do nothing by default
+}
+
+
+//-------------------------------------------------
+// state_string_import - called after new state is
+// written to perform any post-processing
+//-------------------------------------------------
+
+void device_state_interface::state_string_import(const device_state_entry &entry, astring &string)
+{
+ // do nothing by default
+}
+
+
+//-------------------------------------------------
+// state_string_export - called after new state is
+// written to perform any post-processing
+//-------------------------------------------------
+
+void device_state_interface::state_string_export(const device_state_entry &entry, astring &string)
+{
+ // do nothing by default
+}
+
+
+//-------------------------------------------------
+// interface_post_start - verify that state was
+// properly set up
+//-------------------------------------------------
+
+void device_state_interface::interface_post_start()
+{
+ // make sure we got something during startup
+ if (m_state_list.count() == 0)
+ throw emu_fatalerror("No state registered for device '%s' that supports it!", m_device.tag());
+}
+
+
+//-------------------------------------------------
+// state_find_entry - return a pointer to the
+// state entry for the given index
+//-------------------------------------------------
+
+const device_state_entry *device_state_interface::state_find_entry(int index)
+{
+ // use fast lookup if possible
+ if (index >= k_fast_state_min && index <= k_fast_state_max)
+ return m_fast_state[index - k_fast_state_min];
+
+ // otherwise, scan the first
+ for (const device_state_entry *entry = m_state_list.first(); entry != NULL; entry = entry->m_next)
+ if (entry->m_index == index)
+ return entry;
+
+ // handle failure by returning NULL
+ return NULL;
+}
diff --git a/trunk/src/emu/distate.h b/trunk/src/emu/distate.h
new file mode 100644
index 00000000000..ca034523b6c
--- /dev/null
+++ b/trunk/src/emu/distate.h
@@ -0,0 +1,218 @@
+/***************************************************************************
+
+ distate.h
+
+ Device state interfaces.
+
+****************************************************************************
+
+ 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 __DISTATE_H__
+#define __DISTATE_H__
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// standard state indexes
+enum
+{
+ STATE_GENPC = -1, // generic program counter (live)
+ STATE_GENPCBASE = -2, // generic program counter (base of current instruction)
+ STATE_GENSP = -3, // generic stack pointer
+ STATE_GENFLAGS = -4 // generic flags
+};
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> device_state_entry
+
+// class describing a single item of exposed device state
+class device_state_entry
+{
+ friend class device_state_interface;
+ friend class simple_list<device_state_entry>;
+
+private:
+ // construction/destruction
+ device_state_entry(int index, const char *symbol, void *dataptr, UINT8 size);
+
+public:
+ // post-construction modifiers
+ device_state_entry &mask(UINT64 _mask) { m_datamask = _mask; format_from_mask(); return *this; }
+ device_state_entry &signed_mask(UINT64 _mask) { m_datamask = _mask; m_flags |= DSF_IMPORT_SEXT; format_from_mask(); return *this; }
+ device_state_entry &formatstr(const char *_format);
+ device_state_entry &callimport() { m_flags |= DSF_IMPORT; return *this; }
+ device_state_entry &callexport() { m_flags |= DSF_EXPORT; return *this; }
+ device_state_entry &noshow() { m_flags |= DSF_NOSHOW; return *this; }
+
+ // iteration helpers
+ const device_state_entry *next() const { return m_next; }
+
+ // query information
+ int index() const { return m_index; }
+ void *dataptr() const { return m_dataptr.v; }
+ const char *symbol() const { return m_symbol; }
+ bool visible() const { return ((m_flags & DSF_NOSHOW) == 0); }
+
+protected:
+ // device state flags
+ static const UINT8 DSF_NOSHOW = 0x01; // don't display this entry in the registers view
+ static const UINT8 DSF_IMPORT = 0x02; // call the import function after writing new data
+ static const UINT8 DSF_IMPORT_SEXT = 0x04; // sign-extend the data when writing new data
+ static const UINT8 DSF_EXPORT = 0x08; // call the export function prior to fetching the data
+ static const UINT8 DSF_CUSTOM_STRING = 0x10; // set if the format has a custom string
+
+ // helpers
+ bool needs_custom_string() const { return ((m_flags & DSF_CUSTOM_STRING) != 0); }
+ void format_from_mask();
+
+ // return the current value -- only for our friends who handle export
+ bool needs_export() const { return ((m_flags & DSF_EXPORT) != 0); }
+ UINT64 value() const;
+ astring &format(astring &dest, const char *string, bool maxout = false) const;
+
+ // set the current value -- only for our friends who handle import
+ bool needs_import() const { return ((m_flags & DSF_IMPORT) != 0); }
+ void set_value(UINT64 value) const;
+ void set_value(const char *string) const;
+
+ // statics
+ static const UINT64 k_decimal_divisor[20]; // divisors for outputting decimal values
+
+ // public state description
+ device_state_entry * m_next; // link to next item
+ UINT32 m_index; // index by which this item is referred
+ generic_ptr m_dataptr; // pointer to where the data lives
+ UINT64 m_datamask; // mask that applies to the data
+ UINT8 m_datasize; // size of the data
+ UINT8 m_flags; // flags for this data
+ astring m_symbol; // symbol for display; all lower-case version for expressions
+ astring m_format; // supported formats
+ bool m_default_format; // true if we are still using default format
+ UINT64 m_sizemask; // mask derived from the data size
+};
+
+
+
+// ======================> device_state_interface
+
+// class representing interface-specific live state
+class device_state_interface : public device_interface
+{
+public:
+ // construction/destruction
+ device_state_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_state_interface();
+
+ // configuration access
+ const device_state_entry *state_first() const { return m_state_list.first(); }
+
+ // state getters
+ UINT64 state(int index);
+ offs_t pc() { return state(STATE_GENPC); }
+ offs_t pcbase() { return state(STATE_GENPCBASE); }
+ offs_t sp() { return state(STATE_GENSP); }
+ UINT64 flags() { return state(STATE_GENFLAGS); }
+ astring &state_string(int index, astring &dest);
+ int state_string_max_length(int index);
+
+ // state setters
+ void set_state(int index, UINT64 value);
+ void set_state(int index, const char *string);
+
+public: // protected eventually
+
+ // add a new state item
+ template<class _ItemType> device_state_entry &state_add(int index, const char *symbol, _ItemType &data)
+ {
+ return state_add(index, symbol, &data, sizeof(data));
+ }
+ device_state_entry &state_add(int index, const char *symbol, void *data, UINT8 size);
+
+protected:
+ // derived class overrides
+ virtual void state_import(const device_state_entry &entry);
+ virtual void state_export(const device_state_entry &entry);
+ virtual void state_string_import(const device_state_entry &entry, astring &string);
+ virtual void state_string_export(const device_state_entry &entry, astring &string);
+
+ // internal operation overrides
+ virtual void interface_post_start();
+
+ // find the entry for a given index
+ const device_state_entry *state_find_entry(int index);
+
+ // constants
+ static const int k_fast_state_min = -4; // range for fast state
+ static const int k_fast_state_max = 256; // lookups
+
+ // state
+ simple_list<device_state_entry> m_state_list; // head of state list
+ device_state_entry * m_fast_state[k_fast_state_max + 1 - k_fast_state_min];
+ // fast access to common entries
+};
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// device_state - return a pointer to the device
+// state interface for this device
+//-------------------------------------------------
+
+inline device_state_interface *device_state(device_t *device)
+{
+ device_state_interface *intf;
+ if (!device->interface(intf))
+ throw emu_fatalerror("Device '%s' does not have state interface", device->tag());
+ return intf;
+}
+
+
+#endif /* __DISTATE_H__ */
diff --git a/trunk/src/emu/drawgfx.c b/trunk/src/emu/drawgfx.c
new file mode 100644
index 00000000000..aafb041581c
--- /dev/null
+++ b/trunk/src/emu/drawgfx.c
@@ -0,0 +1,2014 @@
+/*********************************************************************
+
+ drawgfx.c
+
+ Generic graphic functions.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "drawgfxm.h"
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+/* if this line errors during compile, the size of NO_PRIORITY is wrong and I need to use something else */
+UINT8 no_priority_size_is_wrong[2 * (sizeof(NO_PRIORITY) == 3) - 1];
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void decodechar(const gfx_element *gfx, UINT32 code, const UINT8 *src);
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ readbit - read a single bit from a base
+ offset
+-------------------------------------------------*/
+
+INLINE int readbit(const UINT8 *src, unsigned int bitnum)
+{
+ return src[bitnum / 8] & (0x80 >> (bitnum % 8));
+}
+
+
+/*-------------------------------------------------
+ normalize_xscroll - normalize an X scroll
+ value for a bitmap to be positive and less
+ than the width
+-------------------------------------------------*/
+
+INLINE INT32 normalize_xscroll(bitmap_t *bitmap, INT32 xscroll)
+{
+ return (xscroll >= 0) ? xscroll % bitmap->width : (bitmap->width - (-xscroll) % bitmap->width);
+}
+
+
+/*-------------------------------------------------
+ normalize_yscroll - normalize a Y scroll
+ value for a bitmap to be positive and less
+ than the height
+-------------------------------------------------*/
+
+INLINE INT32 normalize_yscroll(bitmap_t *bitmap, INT32 yscroll)
+{
+ return (yscroll >= 0) ? yscroll % bitmap->height : (bitmap->height - (-yscroll) % bitmap->height);
+}
+
+
+
+/***************************************************************************
+ GRAPHICS ELEMENTS
+***************************************************************************/
+
+/*-------------------------------------------------
+ gfx_init - allocate memory for the graphics
+ elements referenced by a machine
+-------------------------------------------------*/
+
+void gfx_init(running_machine &machine)
+{
+ const gfx_decode_entry *gfxdecodeinfo = machine.config().m_gfxdecodeinfo;
+ int curgfx;
+
+ /* skip if nothing to do */
+ if (gfxdecodeinfo == NULL)
+ return;
+
+ /* loop over all elements */
+ for (curgfx = 0; curgfx < MAX_GFX_ELEMENTS && gfxdecodeinfo[curgfx].gfxlayout != NULL; curgfx++)
+ {
+ const gfx_decode_entry *gfxdecode = &gfxdecodeinfo[curgfx];
+ const memory_region *region = (gfxdecode->memory_region != NULL) ? machine.region(gfxdecode->memory_region) : NULL;
+ UINT32 region_length = (region != NULL) ? (8 * region->bytes()) : 0;
+ const UINT8 *region_base = (region != NULL) ? region->base() : NULL;
+ UINT32 xscale = (gfxdecode->xscale == 0) ? 1 : gfxdecode->xscale;
+ UINT32 yscale = (gfxdecode->yscale == 0) ? 1 : gfxdecode->yscale;
+ UINT32 *extpoffs, extxoffs[MAX_ABS_GFX_SIZE], extyoffs[MAX_ABS_GFX_SIZE];
+ const gfx_layout *gl = gfxdecode->gfxlayout;
+ int israw = (gl->planeoffset[0] == GFX_RAW);
+ int planes = gl->planes;
+ UINT32 width = gl->width;
+ UINT32 height = gl->height;
+ UINT32 total = gl->total;
+ UINT32 charincrement = gl->charincrement;
+ gfx_layout glcopy;
+ int j;
+
+ /* make a copy of the layout */
+ glcopy = *gfxdecode->gfxlayout;
+
+ /* copy the X and Y offsets into temporary arrays */
+ memcpy(extxoffs, glcopy.xoffset, sizeof(glcopy.xoffset));
+ memcpy(extyoffs, glcopy.yoffset, sizeof(glcopy.yoffset));
+
+ /* if there are extended offsets, copy them over top */
+ if (glcopy.extxoffs != NULL)
+ memcpy(extxoffs, glcopy.extxoffs, glcopy.width * sizeof(extxoffs[0]));
+ if (glcopy.extyoffs != NULL)
+ memcpy(extyoffs, glcopy.extyoffs, glcopy.height * sizeof(extyoffs[0]));
+
+ /* always use the extended offsets here */
+ glcopy.extxoffs = extxoffs;
+ glcopy.extyoffs = extyoffs;
+
+ extpoffs = glcopy.planeoffset;
+
+ /* expand X and Y by the scale factors */
+ if (xscale > 1)
+ {
+ width *= xscale;
+ for (j = width - 1; j >= 0; j--)
+ extxoffs[j] = extxoffs[j / xscale];
+ }
+ if (yscale > 1)
+ {
+ height *= yscale;
+ for (j = height - 1; j >= 0; j--)
+ extyoffs[j] = extyoffs[j / yscale];
+ }
+
+ /* if the character count is a region fraction, compute the effective total */
+ if (IS_FRAC(total))
+ {
+ assert(region_length != 0);
+ total = region_length / charincrement * FRAC_NUM(total) / FRAC_DEN(total);
+ }
+
+ /* for non-raw graphics, decode the X and Y offsets */
+ if (!israw)
+ {
+ /* loop over all the planes, converting fractions */
+ for (j = 0; j < planes; j++)
+ {
+ UINT32 value1 = extpoffs[j];
+ if (IS_FRAC(value1))
+ {
+ assert(region_length != 0);
+ extpoffs[j] = FRAC_OFFSET(value1) + region_length * FRAC_NUM(value1) / FRAC_DEN(value1);
+ }
+ }
+
+ /* loop over all the X/Y offsets, converting fractions */
+ for (j = 0; j < width; j++)
+ {
+ UINT32 value2 = extxoffs[j];
+ if (IS_FRAC(value2))
+ {
+ assert(region_length != 0);
+ extxoffs[j] = FRAC_OFFSET(value2) + region_length * FRAC_NUM(value2) / FRAC_DEN(value2);
+ }
+ }
+
+ for (j = 0; j < height; j++)
+ {
+ UINT32 value3 = extyoffs[j];
+ if (IS_FRAC(value3))
+ {
+ assert(region_length != 0);
+ extyoffs[j] = FRAC_OFFSET(value3) + region_length * FRAC_NUM(value3) / FRAC_DEN(value3);
+ }
+ }
+ }
+
+ /* otherwise, just use the line modulo */
+ else
+ {
+ int base = gfxdecode->start;
+ int end = region_length/8;
+ int linemod = gl->yoffset[0];
+ while (total > 0)
+ {
+ int elementbase = base + (total - 1) * charincrement / 8;
+ int lastpixelbase = elementbase + height * linemod / 8 - 1;
+ if (lastpixelbase < end)
+ break;
+ total--;
+ }
+ }
+
+ /* update glcopy */
+ glcopy.width = width;
+ glcopy.height = height;
+ glcopy.total = total;
+
+ /* allocate the graphics */
+ machine.gfx[curgfx] = gfx_element_alloc(machine, &glcopy, (region_base != NULL) ? region_base + gfxdecode->start : NULL, gfxdecode->total_color_codes, gfxdecode->color_codes_start);
+ }
+}
+
+
+
+/*-------------------------------------------------
+ gfx_element_alloc - allocate a gfx_element structure
+ based on a given layout
+-------------------------------------------------*/
+
+gfx_element *gfx_element_alloc(running_machine &machine, const gfx_layout *gl, const UINT8 *srcdata, UINT32 total_colors, UINT32 color_base)
+{
+ int israw = (gl->planeoffset[0] == GFX_RAW);
+ int planes = gl->planes;
+ UINT16 width = gl->width;
+ UINT16 height = gl->height;
+ UINT32 total = gl->total;
+ gfx_element *gfx;
+
+ /* allocate memory for the gfx_element structure */
+ gfx = auto_alloc_clear(machine, gfx_element(machine));
+
+ /* fill in the data */
+ gfx->width = width;
+ gfx->height = height;
+
+ gfx->origwidth = width;
+ gfx->origheight = height;
+ gfx->total_elements = total;
+
+ gfx->color_base = color_base;
+ gfx->color_depth = 1 << planes;
+ gfx->color_granularity = 1 << planes;
+ gfx->total_colors = total_colors;
+
+ gfx->srcdata = srcdata;
+
+ /* copy the layout */
+ gfx->layout = *gl;
+ if (gfx->layout.extxoffs != NULL)
+ {
+ if (gfx->layout.width < ARRAY_LENGTH(gfx->layout.xoffset))
+ {
+ memcpy(gfx->layout.xoffset, gfx->layout.extxoffs, sizeof(gfx->layout.xoffset[0]) * gfx->layout.width);
+ gfx->layout.extxoffs = NULL;
+ }
+ else
+ {
+ UINT32 *buffer = auto_alloc_array(machine, UINT32, gfx->layout.width);
+ memcpy(buffer, gfx->layout.extxoffs, sizeof(gfx->layout.extxoffs[0]) * gfx->layout.width);
+ gfx->layout.extxoffs = buffer;
+ }
+ }
+
+ if (gfx->layout.extyoffs != NULL)
+ {
+ if (gfx->layout.height < ARRAY_LENGTH(gfx->layout.yoffset))
+ {
+ memcpy(gfx->layout.yoffset, gfx->layout.extyoffs, sizeof(gfx->layout.yoffset[0]) * gfx->layout.height);
+ gfx->layout.extyoffs = NULL;
+ }
+ else
+ {
+ UINT32 *buffer = auto_alloc_array(machine, UINT32, gfx->layout.height);
+ memcpy(buffer, gfx->layout.extyoffs, sizeof(gfx->layout.extyoffs[0]) * gfx->layout.height);
+ gfx->layout.extyoffs = buffer;
+ }
+ }
+
+ /* allocate a pen usage array for entries with 32 pens or less */
+ if (gfx->color_depth <= 32)
+ gfx->pen_usage = auto_alloc_array(machine, UINT32, gfx->total_elements);
+
+ /* allocate a dirty array */
+ gfx->dirty = auto_alloc_array(machine, UINT8, gfx->total_elements);
+ memset(gfx->dirty, 1, gfx->total_elements * sizeof(*gfx->dirty));
+
+ /* raw graphics case */
+ if (israw)
+ {
+ /* modulos are determined for us by the layout */
+ gfx->line_modulo = (gl->extyoffs ? gl->extyoffs[0] : gl->yoffset[0]) / 8;
+ gfx->char_modulo = gl->charincrement / 8;
+
+ /* don't free the data because we will get a pointer at decode time */
+ gfx->flags |= GFX_ELEMENT_DONT_FREE;
+ if (planes <= 4)
+ gfx->flags |= GFX_ELEMENT_PACKED;
+
+ /* RAW graphics must have a pointer up front */
+ gfx->gfxdata = (UINT8 *)gfx->srcdata;
+ }
+
+ /* decoded graphics case */
+ else
+ {
+ /* we get to pick our own modulos */
+ gfx->line_modulo = gfx->origwidth;
+ gfx->char_modulo = gfx->line_modulo * gfx->origheight;
+
+ /* allocate memory for the data */
+ gfx->gfxdata = auto_alloc_array(machine, UINT8, gfx->total_elements * gfx->char_modulo);
+ }
+
+ return gfx;
+}
+
+
+/*-------------------------------------------------
+ gfx_element_decode - update a single code in
+ a gfx_element
+-------------------------------------------------*/
+
+void gfx_element_decode(const gfx_element *gfx, UINT32 code)
+{
+ decodechar(gfx, code, gfx->srcdata);
+}
+
+
+/*-------------------------------------------------
+ gfx_element_free - free a gfx_element
+-------------------------------------------------*/
+
+void gfx_element_free(gfx_element *gfx)
+{
+ /* ignore NULL frees */
+ if (gfx == NULL)
+ return;
+
+ /* free our data */
+ auto_free(gfx->machine(), gfx->layout.extyoffs);
+ auto_free(gfx->machine(), gfx->layout.extxoffs);
+ auto_free(gfx->machine(), gfx->pen_usage);
+ auto_free(gfx->machine(), gfx->dirty);
+ auto_free(gfx->machine(), gfx->gfxdata);
+ auto_free(gfx->machine(), gfx);
+}
+
+
+/*-------------------------------------------------
+ gfx_element_build_temporary - create a
+ temporary one-off gfx_element
+-------------------------------------------------*/
+
+void gfx_element_build_temporary(gfx_element *gfx, running_machine &machine, UINT8 *base, UINT32 width, UINT32 height, UINT32 rowbytes, UINT32 color_base, UINT32 color_granularity, UINT32 flags)
+{
+ static UINT8 not_dirty = 0;
+
+ gfx->width = width;
+ gfx->height = height;
+ gfx->startx = 0;
+ gfx->starty = 0;
+
+ gfx->origwidth = width;
+ gfx->origheight = height;
+ gfx->flags = flags;
+ gfx->total_elements = 1;
+
+ gfx->color_base = color_base;
+ gfx->color_depth = color_granularity;
+ gfx->color_granularity = color_granularity;
+ gfx->total_colors = (machine.total_colors() - color_base) / color_granularity;
+
+ gfx->pen_usage = NULL;
+
+ gfx->gfxdata = base;
+ gfx->line_modulo = rowbytes;
+ gfx->char_modulo = 0;
+ gfx->srcdata = base;
+ gfx->dirty = &not_dirty;
+ gfx->dirtyseq = 0;
+}
+
+
+/*-------------------------------------------------
+ calc_penusage - calculate the pen usage for
+ a given graphics tile
+-------------------------------------------------*/
+
+static void calc_penusage(const gfx_element *gfx, UINT32 code)
+{
+ const UINT8 *dp = gfx->gfxdata + code * gfx->char_modulo;
+ UINT32 usage = 0;
+ int x, y;
+
+ /* if nothing allocated, don't do it */
+ if (gfx->pen_usage == NULL)
+ return;
+
+ /* packed case */
+ if (gfx->flags & GFX_ELEMENT_PACKED)
+ for (y = 0; y < gfx->origheight; y++)
+ {
+ for (x = 0; x < gfx->origwidth/2; x++)
+ usage |= (1 << (dp[x] & 0x0f)) | (1 << (dp[x] >> 4));
+
+ dp += gfx->line_modulo;
+ }
+
+ /* unpacked case */
+ else
+ for (y = 0; y < gfx->origheight; y++)
+ {
+ for (x = 0; x < gfx->origwidth; x++)
+ usage |= 1 << dp[x];
+
+ dp += gfx->line_modulo;
+ }
+
+ /* store the final result */
+ gfx->pen_usage[code] = usage;
+}
+
+
+/*-------------------------------------------------
+ decodechar - decode a single character based
+ on a specified layout
+-------------------------------------------------*/
+
+static void decodechar(const gfx_element *gfx, UINT32 code, const UINT8 *src)
+{
+ const gfx_layout *gl = &gfx->layout;
+ int israw = (gl->planeoffset[0] == GFX_RAW);
+ int planes = gl->planes;
+ UINT32 charincrement = gl->charincrement;
+ const UINT32 *poffset = gl->planeoffset;
+ const UINT32 *xoffset = gl->extxoffs ? gl->extxoffs : gl->xoffset;
+ const UINT32 *yoffset = gl->extyoffs ? gl->extyoffs : gl->yoffset;
+ UINT8 *dp = gfx->gfxdata + code * gfx->char_modulo;
+ int plane, x, y;
+
+ if (!israw)
+ {
+ /* zap the data to 0 */
+ memset(dp, 0, gfx->char_modulo);
+
+ /* packed case */
+ if (gfx->flags & GFX_ELEMENT_PACKED)
+ for (plane = 0; plane < planes; plane++)
+ {
+ int planebit = 1 << (planes - 1 - plane);
+ int planeoffs = code * charincrement + poffset[plane];
+
+ for (y = 0; y < gfx->origheight; y++)
+ {
+ int yoffs = planeoffs + yoffset[y];
+
+ dp = gfx->gfxdata + code * gfx->char_modulo + y * gfx->line_modulo;
+ for (x = 0; x < gfx->origwidth; x += 2)
+ {
+ if (readbit(src, yoffs + xoffset[x+0]))
+ dp[x+0] |= planebit;
+ if (readbit(src, yoffs + xoffset[x+1]))
+ dp[x+1] |= planebit;
+ }
+ }
+ }
+
+ /* unpacked case */
+ else
+ for (plane = 0; plane < planes; plane++)
+ {
+ int planebit = 1 << (planes - 1 - plane);
+ int planeoffs = code * charincrement + poffset[plane];
+
+ for (y = 0; y < gfx->origheight; y++)
+ {
+ int yoffs = planeoffs + yoffset[y];
+
+ dp = gfx->gfxdata + code * gfx->char_modulo + y * gfx->line_modulo;
+ for (x = 0; x < gfx->origwidth; x++)
+ if (readbit(src, yoffs + xoffset[x]))
+ dp[x] |= planebit;
+ }
+ }
+ }
+
+ /* compute pen usage */
+ calc_penusage(gfx, code);
+
+ /* no longer dirty */
+ gfx->dirty[code] = 0;
+}
+
+
+/***************************************************************************
+ DRAWGFX IMPLEMENTATIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ drawgfx_opaque - render a gfx element with
+ no transparency
+-------------------------------------------------*/
+
+void drawgfx_opaque(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty)
+{
+ bitmap_t *priority = NULL; /* dummy, no priority in this case */
+ const pen_t *paldata;
+
+ assert(dest != NULL);
+ assert(dest->bpp == 16 || dest->bpp == 32);
+ assert(gfx != NULL);
+
+ /* get final code and color, and grab lookup tables */
+ code %= gfx->total_elements;
+ color %= gfx->total_colors;
+ paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * color];
+
+ /* render based on dest bitmap depth */
+ if (dest->bpp == 16)
+ DRAWGFX_CORE(UINT16, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
+ else
+ DRAWGFX_CORE(UINT32, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
+}
+
+
+/*-------------------------------------------------
+ drawgfx_transpen - render a gfx element with
+ a single transparent pen
+-------------------------------------------------*/
+
+void drawgfx_transpen(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 transpen)
+{
+ bitmap_t *priority = NULL; /* dummy, no priority in this case */
+ const pen_t *paldata;
+
+ /* special case invalid pens to opaque */
+ if (transpen > 0xff)
+ {
+ drawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty);
+ return;
+ }
+
+ assert(dest != NULL);
+ assert(dest->bpp == 16 || dest->bpp == 32);
+ assert(gfx != NULL);
+
+ /* get final code and color, and grab lookup tables */
+ code %= gfx->total_elements;
+ color %= gfx->total_colors;
+ paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * color];
+
+ /* use pen usage to optimize */
+ if (gfx->pen_usage != NULL && !gfx->dirty[code])
+ {
+ UINT32 usage = gfx->pen_usage[code];
+
+ /* fully transparent; do nothing */
+ if ((usage & ~(1 << transpen)) == 0)
+ return;
+
+ /* fully opaque; draw as such */
+ if ((usage & (1 << transpen)) == 0)
+ {
+ drawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty);
+ return;
+ }
+ }
+
+ /* render based on dest bitmap depth */
+ if (dest->bpp == 16)
+ DRAWGFX_CORE(UINT16, PIXEL_OP_REMAP_TRANSPEN, NO_PRIORITY);
+ else
+ DRAWGFX_CORE(UINT32, PIXEL_OP_REMAP_TRANSPEN, NO_PRIORITY);
+}
+
+
+/*-------------------------------------------------
+ drawgfx_transpen_raw - render a gfx element
+ with a single transparent pen and no color
+ lookups
+-------------------------------------------------*/
+
+void drawgfx_transpen_raw(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 transpen)
+{
+ bitmap_t *priority = NULL; /* dummy, no priority in this case */
+
+ assert(dest != NULL);
+ assert(dest->bpp == 16 || dest->bpp == 32);
+ assert(gfx != NULL);
+
+ /* get final code and color, and grab lookup tables */
+ code %= gfx->total_elements;
+
+ /* early out if completely transparent */
+ if (gfx->pen_usage != NULL && !gfx->dirty[code] && (gfx->pen_usage[code] & ~(1 << transpen)) == 0)
+ return;
+
+ /* render based on dest bitmap depth */
+ if (dest->bpp == 16)
+ DRAWGFX_CORE(UINT16, PIXEL_OP_REBASE_TRANSPEN, NO_PRIORITY);
+ else
+ DRAWGFX_CORE(UINT32, PIXEL_OP_REBASE_TRANSPEN, NO_PRIORITY);
+}
+
+
+/*-------------------------------------------------
+ drawgfx_transmask - render a gfx element
+ with a multiple transparent pens provided as
+ a mask
+-------------------------------------------------*/
+
+void drawgfx_transmask(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 transmask)
+{
+ bitmap_t *priority = NULL; /* dummy, no priority in this case */
+ const pen_t *paldata;
+
+ /* special case 0 mask to opaque */
+ if (transmask == 0)
+ {
+ drawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty);
+ return;
+ }
+
+ assert(dest != NULL);
+ assert(dest->bpp == 16 || dest->bpp == 32);
+ assert(gfx != NULL);
+
+ /* get final code and color, and grab lookup tables */
+ code %= gfx->total_elements;
+ color %= gfx->total_colors;
+ paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * color];
+
+ /* use pen usage to optimize */
+ if (gfx->pen_usage != NULL && !gfx->dirty[code])
+ {
+ UINT32 usage = gfx->pen_usage[code];
+
+ /* fully transparent; do nothing */
+ if ((usage & ~transmask) == 0)
+ return;
+
+ /* fully opaque; draw as such */
+ if ((usage & transmask) == 0)
+ {
+ drawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty);
+ return;
+ }
+ }
+
+ /* render based on dest bitmap depth */
+ if (dest->bpp == 16)
+ DRAWGFX_CORE(UINT16, PIXEL_OP_REMAP_TRANSMASK, NO_PRIORITY);
+ else
+ DRAWGFX_CORE(UINT32, PIXEL_OP_REMAP_TRANSMASK, NO_PRIORITY);
+}
+
+
+/*-------------------------------------------------
+ drawgfx_transtable - render a gfx element
+ using a table to look up which pens are
+ transparent, opaque, or shadowing
+-------------------------------------------------*/
+
+void drawgfx_transtable(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ const UINT8 *pentable, const pen_t *shadowtable)
+{
+ bitmap_t *priority = NULL; /* dummy, no priority in this case */
+ const pen_t *paldata;
+
+ assert(dest != NULL);
+ assert(dest->bpp == 16 || dest->bpp == 32);
+ assert(gfx != NULL);
+ assert(pentable != NULL);
+
+ /* get final code and color, and grab lookup tables */
+ code %= gfx->total_elements;
+ color %= gfx->total_colors;
+ paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * color];
+
+ /* render based on dest bitmap depth */
+ if (dest->bpp == 16)
+ DRAWGFX_CORE(UINT16, PIXEL_OP_REMAP_TRANSTABLE16, NO_PRIORITY);
+ else
+ DRAWGFX_CORE(UINT32, PIXEL_OP_REMAP_TRANSTABLE32, NO_PRIORITY);
+}
+
+
+/*-------------------------------------------------
+ drawgfx_alpha - render a gfx element with
+ a single transparent pen, alpha blending the
+ remaining pixels with a fixed alpha value
+-------------------------------------------------*/
+
+void drawgfx_alpha(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 transpen, UINT8 alpha)
+{
+ bitmap_t *priority = NULL; /* dummy, no priority in this case */
+ const pen_t *paldata;
+
+ /* special case alpha = 0xff */
+ if (alpha == 0xff)
+ {
+ drawgfx_transpen(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, transpen);
+ return;
+ }
+
+ assert(dest != NULL);
+ assert(dest->bpp == 16 || dest->bpp == 32);
+ assert(gfx != NULL);
+
+ /* get final code and color, and grab lookup tables */
+ code %= gfx->total_elements;
+ color %= gfx->total_colors;
+ paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * color];
+
+ /* early out if completely transparent */
+ if (gfx->pen_usage != NULL && !gfx->dirty[code] && (gfx->pen_usage[code] & ~(1 << transpen)) == 0)
+ return;
+
+ /* render based on dest bitmap depth */
+ if (dest->bpp == 16)
+ DRAWGFX_CORE(UINT16, PIXEL_OP_REMAP_TRANSPEN_ALPHA16, NO_PRIORITY);
+ else
+ DRAWGFX_CORE(UINT32, PIXEL_OP_REMAP_TRANSPEN_ALPHA32, NO_PRIORITY);
+}
+
+
+
+/***************************************************************************
+ DRAWGFXZOOM IMPLEMENTATIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ drawgfxzoom_opaque - render a scaled gfx
+ element with no transparency
+-------------------------------------------------*/
+
+void drawgfxzoom_opaque(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley)
+{
+ bitmap_t *priority = NULL; /* dummy, no priority in this case */
+ const pen_t *paldata;
+
+ /* non-zoom case */
+ if (scalex == 0x10000 && scaley == 0x10000)
+ {
+ drawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty);
+ return;
+ }
+
+ assert(dest != NULL);
+ assert(dest->bpp == 16 || dest->bpp == 32);
+ assert(gfx != NULL);
+
+ /* get final code and color, and grab lookup tables */
+ code %= gfx->total_elements;
+ color %= gfx->total_colors;
+ paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * color];
+
+ /* render based on dest bitmap depth */
+ if (dest->bpp == 16)
+ DRAWGFXZOOM_CORE(UINT16, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
+ else
+ DRAWGFXZOOM_CORE(UINT32, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
+}
+
+
+/*-------------------------------------------------
+ drawgfxzoom_transpen - render a scaled gfx
+ element with a single transparent pen
+-------------------------------------------------*/
+
+void drawgfxzoom_transpen(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, UINT32 transpen)
+{
+ bitmap_t *priority = NULL; /* dummy, no priority in this case */
+ const pen_t *paldata;
+
+ /* non-zoom case */
+ if (scalex == 0x10000 && scaley == 0x10000)
+ {
+ drawgfx_transpen(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, transpen);
+ return;
+ }
+
+ /* special case invalid pens to opaque */
+ if (transpen > 0xff)
+ {
+ drawgfxzoom_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, scalex, scaley);
+ return;
+ }
+
+ assert(dest != NULL);
+ assert(dest->bpp == 16 || dest->bpp == 32);
+ assert(gfx != NULL);
+
+ /* get final code and color, and grab lookup tables */
+ code %= gfx->total_elements;
+ color %= gfx->total_colors;
+ paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * color];
+
+ /* use pen usage to optimize */
+ if (gfx->pen_usage != NULL && !gfx->dirty[code])
+ {
+ UINT32 usage = gfx->pen_usage[code];
+
+ /* fully transparent; do nothing */
+ if ((usage & ~(1 << transpen)) == 0)
+ return;
+
+ /* fully opaque; draw as such */
+ if ((usage & (1 << transpen)) == 0)
+ {
+ drawgfxzoom_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, scalex, scaley);
+ return;
+ }
+ }
+
+ /* render based on dest bitmap depth */
+ if (dest->bpp == 16)
+ DRAWGFXZOOM_CORE(UINT16, PIXEL_OP_REMAP_TRANSPEN, NO_PRIORITY);
+ else
+ DRAWGFXZOOM_CORE(UINT32, PIXEL_OP_REMAP_TRANSPEN, NO_PRIORITY);
+}
+
+
+/*-------------------------------------------------
+ drawgfxzoom_transpen_raw - render a scaled gfx
+ element with a single transparent pen and no
+ color lookups
+-------------------------------------------------*/
+
+void drawgfxzoom_transpen_raw(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, UINT32 transpen)
+{
+ bitmap_t *priority = NULL; /* dummy, no priority in this case */
+
+ /* non-zoom case */
+ if (scalex == 0x10000 && scaley == 0x10000)
+ {
+ drawgfx_transpen_raw(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, transpen);
+ return;
+ }
+
+ assert(dest != NULL);
+ assert(dest->bpp == 16 || dest->bpp == 32);
+ assert(gfx != NULL);
+
+ /* get final code and color, and grab lookup tables */
+ code %= gfx->total_elements;
+
+ /* early out if completely transparent */
+ if (gfx->pen_usage != NULL && !gfx->dirty[code] && (gfx->pen_usage[code] & ~(1 << transpen)) == 0)
+ return;
+
+ /* render based on dest bitmap depth */
+ if (dest->bpp == 16)
+ DRAWGFXZOOM_CORE(UINT16, PIXEL_OP_REBASE_TRANSPEN, NO_PRIORITY);
+ else
+ DRAWGFXZOOM_CORE(UINT32, PIXEL_OP_REBASE_TRANSPEN, NO_PRIORITY);
+}
+
+
+/*-------------------------------------------------
+ drawgfxzoom_transmask - render a scaled gfx
+ element with a multiple transparent pens
+ provided as a mask
+-------------------------------------------------*/
+
+void drawgfxzoom_transmask(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, UINT32 transmask)
+{
+ bitmap_t *priority = NULL; /* dummy, no priority in this case */
+ const pen_t *paldata;
+
+ /* non-zoom case */
+ if (scalex == 0x10000 && scaley == 0x10000)
+ {
+ drawgfx_transmask(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, transmask);
+ return;
+ }
+
+ /* special case 0 mask to opaque */
+ if (transmask == 0)
+ {
+ drawgfxzoom_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, scalex, scaley);
+ return;
+ }
+
+ assert(dest != NULL);
+ assert(dest->bpp == 16 || dest->bpp == 32);
+ assert(gfx != NULL);
+
+ /* get final code and color, and grab lookup tables */
+ code %= gfx->total_elements;
+ color %= gfx->total_colors;
+ paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * color];
+
+ /* use pen usage to optimize */
+ if (gfx->pen_usage != NULL && !gfx->dirty[code])
+ {
+ UINT32 usage = gfx->pen_usage[code];
+
+ /* fully transparent; do nothing */
+ if ((usage & ~transmask) == 0)
+ return;
+
+ /* fully opaque; draw as such */
+ if ((usage & transmask) == 0)
+ {
+ drawgfxzoom_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, scalex, scaley);
+ return;
+ }
+ }
+
+ /* render based on dest bitmap depth */
+ if (dest->bpp == 16)
+ DRAWGFXZOOM_CORE(UINT16, PIXEL_OP_REMAP_TRANSMASK, NO_PRIORITY);
+ else
+ DRAWGFXZOOM_CORE(UINT32, PIXEL_OP_REMAP_TRANSMASK, NO_PRIORITY);
+}
+
+
+/*-------------------------------------------------
+ drawgfxzoom_transtable - render a scaled gfx
+ element using a table to look up which pens
+ are transparent, opaque, or shadowing
+-------------------------------------------------*/
+
+void drawgfxzoom_transtable(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, const UINT8 *pentable, const pen_t *shadowtable)
+{
+ bitmap_t *priority = NULL; /* dummy, no priority in this case */
+ const pen_t *paldata;
+
+ /* non-zoom case */
+ if (scalex == 0x10000 && scaley == 0x10000)
+ {
+ drawgfx_transtable(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, pentable, shadowtable);
+ return;
+ }
+
+ assert(dest != NULL);
+ assert(dest->bpp == 16 || dest->bpp == 32);
+ assert(gfx != NULL);
+ assert(pentable != NULL);
+
+ /* get final code and color, and grab lookup tables */
+ code %= gfx->total_elements;
+ color %= gfx->total_colors;
+ paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * color];
+
+ /* render based on dest bitmap depth */
+ if (dest->bpp == 16)
+ DRAWGFXZOOM_CORE(UINT16, PIXEL_OP_REMAP_TRANSTABLE16, NO_PRIORITY);
+ else
+ DRAWGFXZOOM_CORE(UINT32, PIXEL_OP_REMAP_TRANSTABLE32, NO_PRIORITY);
+}
+
+
+/*-------------------------------------------------
+ drawgfxzoom_alpha - render a scaled gfx element
+ with a single transparent pen, alpha blending
+ the remaining pixels with a fixed alpha value
+-------------------------------------------------*/
+
+void drawgfxzoom_alpha(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, UINT32 transpen, UINT8 alpha)
+{
+ bitmap_t *priority = NULL; /* dummy, no priority in this case */
+ const pen_t *paldata;
+
+ /* non-zoom case */
+ if (scalex == 0x10000 && scaley == 0x10000)
+ {
+ drawgfx_alpha(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, transpen, alpha);
+ return;
+ }
+
+ /* special case alpha = 0xff */
+ if (alpha == 0xff)
+ {
+ drawgfxzoom_transpen(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, scalex, scaley, transpen);
+ return;
+ }
+
+ assert(dest != NULL);
+ assert(dest->bpp == 16 || dest->bpp == 32);
+ assert(gfx != NULL);
+
+ /* get final code and color, and grab lookup tables */
+ code %= gfx->total_elements;
+ color %= gfx->total_colors;
+ paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * color];
+
+ /* early out if completely transparent */
+ if (gfx->pen_usage != NULL && !gfx->dirty[code] && (gfx->pen_usage[code] & ~(1 << transpen)) == 0)
+ return;
+
+ /* render based on dest bitmap depth */
+ if (dest->bpp == 16)
+ DRAWGFXZOOM_CORE(UINT16, PIXEL_OP_REMAP_TRANSPEN_ALPHA16, NO_PRIORITY);
+ else
+ DRAWGFXZOOM_CORE(UINT32, PIXEL_OP_REMAP_TRANSPEN_ALPHA32, NO_PRIORITY);
+}
+
+
+
+/***************************************************************************
+ PDRAWGFX IMPLEMENTATIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ pdrawgfx_opaque - render a gfx element with
+ no transparency, checking against the priority
+ bitmap
+-------------------------------------------------*/
+
+void pdrawgfx_opaque(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ bitmap_t *priority, UINT32 pmask)
+{
+ const pen_t *paldata;
+
+ assert(dest != NULL);
+ assert(dest->bpp == 16 || dest->bpp == 32);
+ assert(gfx != NULL);
+
+ /* get final code and color, and grab lookup tables */
+ code %= gfx->total_elements;
+ color %= gfx->total_colors;
+ paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * color];
+
+ /* high bit of the mask is implicitly on */
+ pmask |= 1 << 31;
+
+ /* render based on dest bitmap depth */
+ if (dest->bpp == 16)
+ DRAWGFX_CORE(UINT16, PIXEL_OP_REMAP_OPAQUE_PRIORITY, UINT8);
+ else
+ DRAWGFX_CORE(UINT32, PIXEL_OP_REMAP_OPAQUE_PRIORITY, UINT8);
+}
+
+
+/*-------------------------------------------------
+ pdrawgfx_transpen - render a gfx element with
+ a single transparent pen, checking against the
+ priority bitmap
+-------------------------------------------------*/
+
+void pdrawgfx_transpen(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ bitmap_t *priority, UINT32 pmask, UINT32 transpen)
+{
+ const pen_t *paldata;
+
+ /* special case invalid pens to opaque */
+ if (transpen > 0xff)
+ {
+ pdrawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask);
+ return;
+ }
+
+ assert(dest != NULL);
+ assert(dest->bpp == 16 || dest->bpp == 32);
+ assert(gfx != NULL);
+
+ /* get final code and color, and grab lookup tables */
+ code %= gfx->total_elements;
+ color %= gfx->total_colors;
+ paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * color];
+
+ /* use pen usage to optimize */
+ if (gfx->pen_usage != NULL && !gfx->dirty[code])
+ {
+ UINT32 usage = gfx->pen_usage[code];
+
+ /* fully transparent; do nothing */
+ if ((usage & ~(1 << transpen)) == 0)
+ return;
+
+ /* fully opaque; draw as such */
+ if ((usage & (1 << transpen)) == 0)
+ {
+ pdrawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask);
+ return;
+ }
+ }
+
+ /* high bit of the mask is implicitly on */
+ pmask |= 1 << 31;
+
+ /* render based on dest bitmap depth */
+ if (dest->bpp == 16)
+ DRAWGFX_CORE(UINT16, PIXEL_OP_REMAP_TRANSPEN_PRIORITY, UINT8);
+ else
+ DRAWGFX_CORE(UINT32, PIXEL_OP_REMAP_TRANSPEN_PRIORITY, UINT8);
+}
+
+
+/*-------------------------------------------------
+ pdrawgfx_transpen_raw - render a gfx element
+ with a single transparent pen and no color
+ lookups, checking against the priority bitmap
+-------------------------------------------------*/
+
+void pdrawgfx_transpen_raw(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ bitmap_t *priority, UINT32 pmask, UINT32 transpen)
+{
+ assert(dest != NULL);
+ assert(dest->bpp == 16 || dest->bpp == 32);
+ assert(gfx != NULL);
+
+ /* get final code and color, and grab lookup tables */
+ code %= gfx->total_elements;
+
+ /* early out if completely transparent */
+ if (gfx->pen_usage != NULL && !gfx->dirty[code] && (gfx->pen_usage[code] & ~(1 << transpen)) == 0)
+ return;
+
+ /* high bit of the mask is implicitly on */
+ pmask |= 1 << 31;
+
+ /* render based on dest bitmap depth */
+ if (dest->bpp == 16)
+ DRAWGFX_CORE(UINT16, PIXEL_OP_REBASE_TRANSPEN_PRIORITY, UINT8);
+ else
+ DRAWGFX_CORE(UINT32, PIXEL_OP_REBASE_TRANSPEN_PRIORITY, UINT8);
+}
+
+
+/*-------------------------------------------------
+ pdrawgfx_transmask - render a gfx element
+ with a multiple transparent pens provided as
+ a mask, checking against the priority bitmap
+-------------------------------------------------*/
+
+void pdrawgfx_transmask(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ bitmap_t *priority, UINT32 pmask, UINT32 transmask)
+{
+ const pen_t *paldata;
+
+ /* special case 0 mask to opaque */
+ if (transmask == 0)
+ {
+ pdrawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask);
+ return;
+ }
+
+ assert(dest != NULL);
+ assert(dest->bpp == 16 || dest->bpp == 32);
+ assert(gfx != NULL);
+
+ /* get final code and color, and grab lookup tables */
+ code %= gfx->total_elements;
+ color %= gfx->total_colors;
+ paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * color];
+
+ /* use pen usage to optimize */
+ if (gfx->pen_usage != NULL && !gfx->dirty[code])
+ {
+ UINT32 usage = gfx->pen_usage[code];
+
+ /* fully transparent; do nothing */
+ if ((usage & ~transmask) == 0)
+ return;
+
+ /* fully opaque; draw as such */
+ if ((usage & transmask) == 0)
+ {
+ pdrawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask);
+ return;
+ }
+ }
+
+ /* high bit of the mask is implicitly on */
+ pmask |= 1 << 31;
+
+ /* render based on dest bitmap depth */
+ if (dest->bpp == 16)
+ DRAWGFX_CORE(UINT16, PIXEL_OP_REMAP_TRANSMASK_PRIORITY, UINT8);
+ else
+ DRAWGFX_CORE(UINT32, PIXEL_OP_REMAP_TRANSMASK_PRIORITY, UINT8);
+}
+
+
+/*-------------------------------------------------
+ pdrawgfx_transtable - render a gfx element
+ using a table to look up which pens are
+ transparent, opaque, or shadowing, checking
+ against the priority bitmap
+-------------------------------------------------*/
+
+void pdrawgfx_transtable(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ bitmap_t *priority, UINT32 pmask, const UINT8 *pentable, const pen_t *shadowtable)
+{
+ const pen_t *paldata;
+
+ assert(dest != NULL);
+ assert(dest->bpp == 16 || dest->bpp == 32);
+ assert(gfx != NULL);
+ assert(pentable != NULL);
+
+ /* get final code and color, and grab lookup tables */
+ code %= gfx->total_elements;
+ color %= gfx->total_colors;
+ paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * color];
+
+ /* high bit of the mask is implicitly on */
+ pmask |= 1 << 31;
+
+ /* render based on dest bitmap depth */
+ if (dest->bpp == 16)
+ DRAWGFX_CORE(UINT16, PIXEL_OP_REMAP_TRANSTABLE16_PRIORITY, UINT8);
+ else
+ DRAWGFX_CORE(UINT32, PIXEL_OP_REMAP_TRANSTABLE32_PRIORITY, UINT8);
+}
+
+
+/*-------------------------------------------------
+ pdrawgfx_alpha - render a gfx element with
+ a single transparent pen, alpha blending the
+ remaining pixels with a fixed alpha value,
+ checking against the priority bitmap
+-------------------------------------------------*/
+
+void pdrawgfx_alpha(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ bitmap_t *priority, UINT32 pmask, UINT32 transpen, UINT8 alpha)
+{
+ const pen_t *paldata;
+
+ assert(dest != NULL);
+ assert(dest->bpp == 16 || dest->bpp == 32);
+ assert(gfx != NULL);
+
+ /* special case alpha = 0xff */
+ if (alpha == 0xff)
+ {
+ pdrawgfx_transpen(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask, transpen);
+ return;
+ }
+
+ /* get final code and color, and grab lookup tables */
+ code %= gfx->total_elements;
+ color %= gfx->total_colors;
+ paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * color];
+
+ /* early out if completely transparent */
+ if (gfx->pen_usage != NULL && !gfx->dirty[code] && (gfx->pen_usage[code] & ~(1 << transpen)) == 0)
+ return;
+
+ /* high bit of the mask is implicitly on */
+ pmask |= 1 << 31;
+
+ /* render based on dest bitmap depth */
+ if (dest->bpp == 16)
+ DRAWGFX_CORE(UINT16, PIXEL_OP_REMAP_TRANSPEN_ALPHA16_PRIORITY, UINT8);
+ else
+ DRAWGFX_CORE(UINT32, PIXEL_OP_REMAP_TRANSPEN_ALPHA32_PRIORITY, UINT8);
+}
+
+
+
+/***************************************************************************
+ PDRAWGFXZOOM IMPLEMENTATIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ pdrawgfxzoom_opaque - render a scaled gfx
+ element with no transparency, checking against
+ the priority bitmap
+-------------------------------------------------*/
+
+void pdrawgfxzoom_opaque(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, bitmap_t *priority, UINT32 pmask)
+{
+ const pen_t *paldata;
+
+ /* non-zoom case */
+ if (scalex == 0x10000 && scaley == 0x10000)
+ {
+ pdrawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask);
+ return;
+ }
+
+ assert(dest != NULL);
+ assert(dest->bpp == 16 || dest->bpp == 32);
+ assert(gfx != NULL);
+
+ /* get final code and color, and grab lookup tables */
+ code %= gfx->total_elements;
+ color %= gfx->total_colors;
+ paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * color];
+
+ /* high bit of the mask is implicitly on */
+ pmask |= 1 << 31;
+
+ /* render based on dest bitmap depth */
+ if (dest->bpp == 16)
+ DRAWGFXZOOM_CORE(UINT16, PIXEL_OP_REMAP_OPAQUE_PRIORITY, UINT8);
+ else
+ DRAWGFXZOOM_CORE(UINT32, PIXEL_OP_REMAP_OPAQUE_PRIORITY, UINT8);
+}
+
+
+/*-------------------------------------------------
+ pdrawgfxzoom_transpen - render a scaled gfx
+ element with a single transparent pen,
+ checking against the priority bitmap
+-------------------------------------------------*/
+
+void pdrawgfxzoom_transpen(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, bitmap_t *priority, UINT32 pmask,
+ UINT32 transpen)
+{
+ const pen_t *paldata;
+
+ /* non-zoom case */
+ if (scalex == 0x10000 && scaley == 0x10000)
+ {
+ pdrawgfx_transpen(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask, transpen);
+ return;
+ }
+
+ /* special case invalid pens to opaque */
+ if (transpen > 0xff)
+ {
+ pdrawgfxzoom_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask);
+ return;
+ }
+
+ assert(dest != NULL);
+ assert(dest->bpp == 16 || dest->bpp == 32);
+ assert(gfx != NULL);
+
+ /* get final code and color, and grab lookup tables */
+ code %= gfx->total_elements;
+ color %= gfx->total_colors;
+ paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * color];
+
+ /* use pen usage to optimize */
+ if (gfx->pen_usage != NULL && !gfx->dirty[code])
+ {
+ UINT32 usage = gfx->pen_usage[code];
+
+ /* fully transparent; do nothing */
+ if ((usage & ~(1 << transpen)) == 0)
+ return;
+
+ /* fully opaque; draw as such */
+ if ((usage & (1 << transpen)) == 0)
+ {
+ pdrawgfxzoom_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask);
+ return;
+ }
+ }
+
+ /* high bit of the mask is implicitly on */
+ pmask |= 1 << 31;
+
+ /* render based on dest bitmap depth */
+ if (dest->bpp == 16)
+ DRAWGFXZOOM_CORE(UINT16, PIXEL_OP_REMAP_TRANSPEN_PRIORITY, UINT8);
+ else
+ DRAWGFXZOOM_CORE(UINT32, PIXEL_OP_REMAP_TRANSPEN_PRIORITY, UINT8);
+}
+
+
+/*-------------------------------------------------
+ pdrawgfxzoom_transpen_raw - render a scaled gfx
+ element with a single transparent pen and no
+ color lookups, checking against the priority
+ bitmap
+-------------------------------------------------*/
+
+void pdrawgfxzoom_transpen_raw(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, bitmap_t *priority, UINT32 pmask,
+ UINT32 transpen)
+{
+ /* non-zoom case */
+ if (scalex == 0x10000 && scaley == 0x10000)
+ {
+ pdrawgfx_transpen_raw(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask, transpen);
+ return;
+ }
+
+ assert(dest != NULL);
+ assert(dest->bpp == 16 || dest->bpp == 32);
+ assert(gfx != NULL);
+
+ /* get final code and color, and grab lookup tables */
+ code %= gfx->total_elements;
+
+ /* early out if completely transparent */
+ if (gfx->pen_usage != NULL && !gfx->dirty[code] && (gfx->pen_usage[code] & ~(1 << transpen)) == 0)
+ return;
+
+ /* high bit of the mask is implicitly on */
+ pmask |= 1 << 31;
+
+ /* render based on dest bitmap depth */
+ if (dest->bpp == 16)
+ DRAWGFXZOOM_CORE(UINT16, PIXEL_OP_REBASE_TRANSPEN_PRIORITY, UINT8);
+ else
+ DRAWGFXZOOM_CORE(UINT32, PIXEL_OP_REBASE_TRANSPEN_PRIORITY, UINT8);
+}
+
+
+/*-------------------------------------------------
+ pdrawgfxzoom_transmask - render a scaled gfx
+ element with a multiple transparent pens
+ provided as a mask, checking against the
+ priority bitmap
+-------------------------------------------------*/
+
+void pdrawgfxzoom_transmask(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, bitmap_t *priority, UINT32 pmask,
+ UINT32 transmask)
+{
+ const pen_t *paldata;
+
+ /* non-zoom case */
+ if (scalex == 0x10000 && scaley == 0x10000)
+ {
+ pdrawgfx_transmask(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask, transmask);
+ return;
+ }
+
+ /* special case 0 mask to opaque */
+ if (transmask == 0)
+ {
+ pdrawgfxzoom_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask);
+ return;
+ }
+
+ assert(dest != NULL);
+ assert(dest->bpp == 16 || dest->bpp == 32);
+ assert(gfx != NULL);
+
+ /* get final code and color, and grab lookup tables */
+ code %= gfx->total_elements;
+ color %= gfx->total_colors;
+ paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * color];
+
+ /* use pen usage to optimize */
+ if (gfx->pen_usage != NULL && !gfx->dirty[code])
+ {
+ UINT32 usage = gfx->pen_usage[code];
+
+ /* fully transparent; do nothing */
+ if ((usage & ~transmask) == 0)
+ return;
+
+ /* fully opaque; draw as such */
+ if ((usage & transmask) == 0)
+ {
+ pdrawgfxzoom_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask);
+ return;
+ }
+ }
+
+ /* high bit of the mask is implicitly on */
+ pmask |= 1 << 31;
+
+ /* render based on dest bitmap depth */
+ if (dest->bpp == 16)
+ DRAWGFXZOOM_CORE(UINT16, PIXEL_OP_REMAP_TRANSMASK_PRIORITY, UINT8);
+ else
+ DRAWGFXZOOM_CORE(UINT32, PIXEL_OP_REMAP_TRANSMASK_PRIORITY, UINT8);
+}
+
+
+/*-------------------------------------------------
+ pdrawgfxzoom_transtable - render a scaled gfx
+ element using a table to look up which pens
+ are transparent, opaque, or shadowing,
+ checking against the priority bitmap
+-------------------------------------------------*/
+
+void pdrawgfxzoom_transtable(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, bitmap_t *priority, UINT32 pmask,
+ const UINT8 *pentable, const pen_t *shadowtable)
+{
+ const pen_t *paldata;
+
+ /* non-zoom case */
+ if (scalex == 0x10000 && scaley == 0x10000)
+ {
+ pdrawgfx_transtable(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask, pentable, shadowtable);
+ return;
+ }
+
+ assert(dest != NULL);
+ assert(dest->bpp == 16 || dest->bpp == 32);
+ assert(gfx != NULL);
+ assert(pentable != NULL);
+
+ /* get final code and color, and grab lookup tables */
+ code %= gfx->total_elements;
+ color %= gfx->total_colors;
+ paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * color];
+
+ /* high bit of the mask is implicitly on */
+ pmask |= 1 << 31;
+
+ /* render based on dest bitmap depth */
+ if (dest->bpp == 16)
+ DRAWGFXZOOM_CORE(UINT16, PIXEL_OP_REMAP_TRANSTABLE16_PRIORITY, UINT8);
+ else
+ DRAWGFXZOOM_CORE(UINT32, PIXEL_OP_REMAP_TRANSTABLE32_PRIORITY, UINT8);
+}
+
+
+/*-------------------------------------------------
+ pdrawgfxzoom_alpha - render a scaled gfx
+ element with a single transparent pen, alpha
+ blending the remaining pixels with a fixed
+ alpha value, checking against the priority
+ bitmap
+-------------------------------------------------*/
+
+void pdrawgfxzoom_alpha(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, bitmap_t *priority, UINT32 pmask,
+ UINT32 transpen, UINT8 alpha)
+{
+ const pen_t *paldata;
+
+ /* non-zoom case */
+ if (scalex == 0x10000 && scaley == 0x10000)
+ {
+ pdrawgfx_alpha(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask, transpen, alpha);
+ return;
+ }
+
+ /* special case alpha = 0xff */
+ if (alpha == 0xff)
+ {
+ pdrawgfxzoom_transpen(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask, transpen);
+ return;
+ }
+
+ assert(dest != NULL);
+ assert(dest->bpp == 16 || dest->bpp == 32);
+ assert(gfx != NULL);
+
+ /* get final code and color, and grab lookup tables */
+ code %= gfx->total_elements;
+ color %= gfx->total_colors;
+ paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * color];
+
+ /* early out if completely transparent */
+ if (gfx->pen_usage != NULL && !gfx->dirty[code] && (gfx->pen_usage[code] & ~(1 << transpen)) == 0)
+ return;
+
+ /* high bit of the mask is implicitly on */
+ pmask |= 1 << 31;
+
+ /* render based on dest bitmap depth */
+ if (dest->bpp == 16)
+ DRAWGFXZOOM_CORE(UINT16, PIXEL_OP_REMAP_TRANSPEN_ALPHA16_PRIORITY, UINT8);
+ else
+ DRAWGFXZOOM_CORE(UINT32, PIXEL_OP_REMAP_TRANSPEN_ALPHA32_PRIORITY, UINT8);
+}
+
+
+
+/***************************************************************************
+ DRAW_SCANLINE IMPLEMENTATIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ draw_scanline8 - copy pixels from an 8bpp
+ buffer to a single scanline of a bitmap
+-------------------------------------------------*/
+
+void draw_scanline8(bitmap_t *bitmap, INT32 destx, INT32 desty, INT32 length, const UINT8 *srcptr, const pen_t *paldata)
+{
+ bitmap_t *priority = NULL; /* dummy, no priority in this case */
+
+ assert(bitmap != NULL);
+ assert(bitmap->bpp == 16 || bitmap->bpp == 32);
+
+ /* palette lookup case */
+ if (paldata != NULL)
+ {
+ /* 16bpp case */
+ if (bitmap->bpp == 16)
+ DRAWSCANLINE_CORE(UINT16, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
+ else
+ DRAWSCANLINE_CORE(UINT32, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
+ }
+
+ /* raw copy case */
+ else
+ {
+ /* 16bpp case */
+ if (bitmap->bpp == 16)
+ DRAWSCANLINE_CORE(UINT16, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
+ else
+ DRAWSCANLINE_CORE(UINT32, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
+ }
+}
+
+
+/*-------------------------------------------------
+ draw_scanline16 - copy pixels from a 16bpp
+ buffer to a single scanline of a bitmap
+-------------------------------------------------*/
+
+void draw_scanline16(bitmap_t *bitmap, INT32 destx, INT32 desty, INT32 length, const UINT16 *srcptr, const pen_t *paldata)
+{
+ bitmap_t *priority = NULL; /* dummy, no priority in this case */
+
+ assert(bitmap != NULL);
+ assert(bitmap->bpp == 16 || bitmap->bpp == 32);
+
+ /* palette lookup case */
+ if (paldata != NULL)
+ {
+ /* 16bpp case */
+ if (bitmap->bpp == 16)
+ DRAWSCANLINE_CORE(UINT16, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
+ else
+ DRAWSCANLINE_CORE(UINT32, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
+ }
+
+ /* raw copy case */
+ else
+ {
+ /* 16bpp case */
+ if (bitmap->bpp == 16)
+ DRAWSCANLINE_CORE(UINT16, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
+ else
+ DRAWSCANLINE_CORE(UINT32, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
+ }
+}
+
+
+/*-------------------------------------------------
+ draw_scanline32 - copy pixels from a 32bpp
+ buffer to a single scanline of a bitmap
+-------------------------------------------------*/
+
+void draw_scanline32(bitmap_t *bitmap, INT32 destx, INT32 desty, INT32 length, const UINT32 *srcptr, const pen_t *paldata)
+{
+ bitmap_t *priority = NULL; /* dummy, no priority in this case */
+
+ assert(bitmap != NULL);
+ assert(bitmap->bpp == 16 || bitmap->bpp == 32);
+
+ /* palette lookup case */
+ if (paldata != NULL)
+ {
+ /* 16bpp case */
+ if (bitmap->bpp == 16)
+ DRAWSCANLINE_CORE(UINT16, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
+ else
+ DRAWSCANLINE_CORE(UINT32, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
+ }
+
+ /* raw copy case */
+ else
+ {
+ /* 16bpp case */
+ if (bitmap->bpp == 16)
+ DRAWSCANLINE_CORE(UINT16, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
+ else
+ DRAWSCANLINE_CORE(UINT32, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
+ }
+}
+
+
+
+/***************************************************************************
+ EXTRACT_SCANLINE IMPLEMENTATIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ extract_scanline8 - copy pixels from a single
+ scanline of a bitmap to an 8bpp buffer
+-------------------------------------------------*/
+
+void extract_scanline8(bitmap_t *bitmap, INT32 srcx, INT32 srcy, INT32 length, UINT8 *destptr)
+{
+ assert(bitmap != NULL);
+ assert(bitmap->bpp == 16 || bitmap->bpp == 32);
+
+ /* 16bpp case */
+ if (bitmap->bpp == 16)
+ EXTRACTSCANLINE_CORE(UINT16);
+ else
+ EXTRACTSCANLINE_CORE(UINT32);
+}
+
+
+/*-------------------------------------------------
+ extract_scanline16 - copy pixels from a single
+ scanline of a bitmap to a 16bpp buffer
+-------------------------------------------------*/
+
+void extract_scanline16(bitmap_t *bitmap, INT32 srcx, INT32 srcy, INT32 length, UINT16 *destptr)
+{
+ assert(bitmap != NULL);
+ assert(bitmap->bpp == 16 || bitmap->bpp == 32);
+
+ /* 16bpp case */
+ if (bitmap->bpp == 16)
+ EXTRACTSCANLINE_CORE(UINT16);
+ else
+ EXTRACTSCANLINE_CORE(UINT32);
+}
+
+
+/*-------------------------------------------------
+ extract_scanline32 - copy pixels from a single
+ scanline of a bitmap to a 32bpp buffer
+-------------------------------------------------*/
+
+void extract_scanline32(bitmap_t *bitmap, INT32 srcx, INT32 srcy, INT32 length, UINT32 *destptr)
+{
+ assert(bitmap != NULL);
+ assert(bitmap->bpp == 16 || bitmap->bpp == 32);
+
+ /* 16bpp case */
+ if (bitmap->bpp == 16)
+ EXTRACTSCANLINE_CORE(UINT16);
+ else
+ EXTRACTSCANLINE_CORE(UINT32);
+}
+
+
+
+/***************************************************************************
+ COPYBITMAP IMPLEMENTATIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ copybitmap - copy from one bitmap to another,
+ copying all unclipped pixels
+-------------------------------------------------*/
+
+void copybitmap(bitmap_t *dest, bitmap_t *src, int flipx, int flipy, INT32 destx, INT32 desty, const rectangle *cliprect)
+{
+ bitmap_t *priority = NULL; /* dummy, no priority in this case */
+
+ assert(dest != NULL);
+ assert(src != NULL);
+ assert(dest->bpp == 8 || dest->bpp == 16 || dest->bpp == 32);
+ assert(src->bpp == dest->bpp);
+
+ if (dest->bpp == 8)
+ COPYBITMAP_CORE(UINT8, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
+ else if (dest->bpp == 16)
+ COPYBITMAP_CORE(UINT16, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
+ else
+ COPYBITMAP_CORE(UINT32, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
+}
+
+
+/*-------------------------------------------------
+ copybitmap_trans - copy from one bitmap to
+ another, copying all unclipped pixels except
+ those that match transpen
+-------------------------------------------------*/
+
+void copybitmap_trans(bitmap_t *dest, bitmap_t *src, int flipx, int flipy, INT32 destx, INT32 desty, const rectangle *cliprect, UINT32 transpen)
+{
+ bitmap_t *priority = NULL; /* dummy, no priority in this case */
+
+ assert(dest != NULL);
+ assert(src != NULL);
+ assert(dest->bpp == 8 || dest->bpp == 16 || dest->bpp == 32);
+ assert(src->bpp == dest->bpp);
+
+ if (dest->bpp == 8)
+ {
+ if (transpen > 0xff)
+ copybitmap(dest, src, flipx, flipy, destx, desty, cliprect);
+ else
+ COPYBITMAP_CORE(UINT8, PIXEL_OP_COPY_TRANSPEN, NO_PRIORITY);
+ }
+ else if (dest->bpp == 16)
+ {
+ if (transpen > 0xffff)
+ copybitmap(dest, src, flipx, flipy, destx, desty, cliprect);
+ else
+ COPYBITMAP_CORE(UINT16, PIXEL_OP_COPY_TRANSPEN, NO_PRIORITY);
+ }
+ else
+ {
+ if (transpen == 0xffffffff)
+ copybitmap(dest, src, flipx, flipy, destx, desty, cliprect);
+ else
+ COPYBITMAP_CORE(UINT32, PIXEL_OP_COPY_TRANSPEN, NO_PRIORITY);
+ }
+}
+
+
+
+/***************************************************************************
+ COPYSCROLLBITMAP IMPLEMENTATIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ copyscrollbitmap - copy from one bitmap to
+ another, copying all unclipped pixels, and
+ applying scrolling to one or more rows/colums
+-------------------------------------------------*/
+
+void copyscrollbitmap(bitmap_t *dest, bitmap_t *src, UINT32 numrows, const INT32 *rowscroll, UINT32 numcols, const INT32 *colscroll, const rectangle *cliprect)
+{
+ /* just call through to the transparent case as the underlying copybitmap will
+ optimize for pen == 0xffffffff */
+ copyscrollbitmap_trans(dest, src, numrows, rowscroll, numcols, colscroll, cliprect, 0xffffffff);
+}
+
+
+/*-------------------------------------------------
+ copyscrollbitmap_trans - copy from one bitmap
+ to another, copying all unclipped pixels
+ except those that match transpen, and applying
+ scrolling to one or more rows/colums
+-------------------------------------------------*/
+
+void copyscrollbitmap_trans(bitmap_t *dest, bitmap_t *src, UINT32 numrows, const INT32 *rowscroll, UINT32 numcols, const INT32 *colscroll, const rectangle *cliprect, UINT32 transpen)
+{
+ /* no rowscroll and no colscroll means no scroll */
+ if (numrows == 0 && numcols == 0)
+ {
+ copybitmap_trans(dest, src, 0, 0, 0, 0, cliprect, transpen);
+ return;
+ }
+
+ assert(dest != NULL);
+ assert(src != NULL);
+ assert(dest->bpp == 8 || dest->bpp == 16 || dest->bpp == 32);
+ assert(dest->bpp == src->bpp);
+ assert(numrows != 0 || rowscroll == NULL);
+ assert(numrows == 0 || rowscroll != NULL);
+ assert(numcols != 0 || colscroll == NULL);
+ assert(numcols == 0 || colscroll != NULL);
+
+ /* NULL clip means use the full bitmap */
+ if (cliprect == NULL)
+ cliprect = &dest->cliprect;
+
+ /* fully scrolling X,Y playfield */
+ if (numrows <= 1 && numcols <= 1)
+ {
+ INT32 xscroll = normalize_xscroll(src, (numrows == 0) ? 0 : rowscroll[0]);
+ INT32 yscroll = normalize_yscroll(src, (numcols == 0) ? 0 : colscroll[0]);
+ INT32 sx, sy;
+
+ /* iterate over all portions of the scroll that overlap the destination */
+ for (sx = xscroll - src->width; sx < dest->width; sx += src->width)
+ for (sy = yscroll - src->height; sy < dest->height; sy += src->height)
+ copybitmap_trans(dest, src, 0, 0, sx, sy, cliprect, transpen);
+ }
+
+ /* scrolling columns plus horizontal scroll */
+ else if (numrows <= 1)
+ {
+ INT32 xscroll = normalize_xscroll(src, (numrows == 0) ? 0 : rowscroll[0]);
+ rectangle subclip = *cliprect;
+ int col, colwidth, groupcols;
+
+ /* determine width of each column */
+ colwidth = src->width / numcols;
+ assert(src->width % colwidth == 0);
+
+ /* iterate over each column */
+ for (col = 0; col < numcols; col += groupcols)
+ {
+ INT32 yscroll = colscroll[col];
+ INT32 sx, sy;
+
+ /* count consecutive columns scrolled by the same amount */
+ for (groupcols = 1; col + groupcols < numcols; groupcols++)
+ if (colscroll[col + groupcols] != yscroll)
+ break;
+
+ /* iterate over reps of the columns in question */
+ yscroll = normalize_yscroll(src, yscroll);
+ for (sx = xscroll - src->width; sx < dest->width; sx += src->width)
+ {
+ /* compute the cliprect for this group */
+ subclip.min_x = col * colwidth + sx;
+ subclip.max_x = (col + groupcols) * colwidth - 1 + sx;
+ sect_rect(&subclip, cliprect);
+
+ /* iterate over all portions of the scroll that overlap the destination */
+ for (sy = yscroll - src->height; sy < dest->height; sy += src->height)
+ copybitmap_trans(dest, src, 0, 0, sx, sy, &subclip, transpen);
+ }
+ }
+ }
+
+ /* scrolling rows plus vertical scroll */
+ else if (numcols <= 1)
+ {
+ INT32 yscroll = normalize_yscroll(src, (numcols == 0) ? 0 : colscroll[0]);
+ rectangle subclip = *cliprect;
+ int row, rowheight, grouprows;
+
+ /* determine width of each rows */
+ rowheight = src->height / numrows;
+ assert(src->height % rowheight == 0);
+
+ /* iterate over each row */
+ for (row = 0; row < numrows; row += grouprows)
+ {
+ INT32 xscroll = rowscroll[row];
+ INT32 sx, sy;
+
+ /* count consecutive rows scrolled by the same amount */
+ for (grouprows = 1; row + grouprows < numrows; grouprows++)
+ if (rowscroll[row + grouprows] != xscroll)
+ break;
+
+ /* iterate over reps of the rows in question */
+ xscroll = normalize_xscroll(src, xscroll);
+ for (sy = yscroll - src->height; sy < dest->height; sy += src->height)
+ {
+ /* compute the cliprect for this group */
+ subclip.min_y = row * rowheight + sy;
+ subclip.max_y = (row + grouprows) * rowheight - 1 + sy;
+ sect_rect(&subclip, cliprect);
+
+ /* iterate over all portions of the scroll that overlap the destination */
+ for (sx = xscroll - src->width; sx < dest->width; sx += src->width)
+ copybitmap_trans(dest, src, 0, 0, sx, sy, &subclip, transpen);
+ }
+ }
+ }
+}
+
+
+
+/***************************************************************************
+ COPYROZBITMAP IMPLEMENTATIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ copyrozbitmap - copy from one bitmap to another,
+ with zoom and rotation, copying all unclipped
+ pixels
+-------------------------------------------------*/
+
+void copyrozbitmap(bitmap_t *dest, const rectangle *cliprect, bitmap_t *src, INT32 startx, INT32 starty, INT32 incxx, INT32 incxy, INT32 incyx, INT32 incyy, int wraparound)
+{
+ bitmap_t *priority = NULL; /* dummy, no priority in this case */
+
+ assert(dest != NULL);
+ assert(src != NULL);
+ assert(dest->bpp == 8 || dest->bpp == 16 || dest->bpp == 32);
+ assert(src->bpp == dest->bpp);
+
+ if (dest->bpp == 8)
+ COPYROZBITMAP_CORE(UINT8, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
+ else if (dest->bpp == 16)
+ COPYROZBITMAP_CORE(UINT16, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
+ else
+ COPYROZBITMAP_CORE(UINT32, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
+}
+
+
+/*-------------------------------------------------
+ copyrozbitmap_trans - copy from one bitmap to
+ another, with zoom and rotation, copying all
+ unclipped pixels whose values do not match
+ transpen
+-------------------------------------------------*/
+
+void copyrozbitmap_trans(bitmap_t *dest, const rectangle *cliprect, bitmap_t *src, INT32 startx, INT32 starty, INT32 incxx, INT32 incxy, INT32 incyx, INT32 incyy, int wraparound, UINT32 transpen)
+{
+ bitmap_t *priority = NULL; /* dummy, no priority in this case */
+
+ assert(dest != NULL);
+ assert(src != NULL);
+ assert(dest->bpp == 8 || dest->bpp == 16 || dest->bpp == 32);
+ assert(src->bpp == dest->bpp);
+
+ if (dest->bpp == 8)
+ COPYROZBITMAP_CORE(UINT8, PIXEL_OP_COPY_TRANSPEN, NO_PRIORITY);
+ else if (dest->bpp == 16)
+ COPYROZBITMAP_CORE(UINT16, PIXEL_OP_COPY_TRANSPEN, NO_PRIORITY);
+ else
+ COPYROZBITMAP_CORE(UINT32, PIXEL_OP_COPY_TRANSPEN, NO_PRIORITY);
+}
diff --git a/trunk/src/emu/drawgfx.h b/trunk/src/emu/drawgfx.h
new file mode 100644
index 00000000000..a715dfafb22
--- /dev/null
+++ b/trunk/src/emu/drawgfx.h
@@ -0,0 +1,426 @@
+/*********************************************************************
+
+ drawgfx.h
+
+ Generic graphic functions.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+#pragma once
+
+#ifndef __EMU_H__
+#error Dont include this file directly; include emu.h instead.
+#endif
+
+#ifndef __DRAWGFX_H__
+#define __DRAWGFX_H__
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define MAX_GFX_PLANES 8
+#define MAX_GFX_SIZE 32
+#define MAX_ABS_GFX_SIZE 1024
+
+#define EXTENDED_XOFFS { 0 }
+#define EXTENDED_YOFFS { 0 }
+
+#define GFX_ELEMENT_PACKED 1 /* two 4bpp pixels are packed in one byte of gfxdata */
+#define GFX_ELEMENT_DONT_FREE 2 /* gfxdata was not malloc()ed, so don't free it on exit */
+
+#define GFX_RAW 0x12345678
+/* When planeoffset[0] is set to GFX_RAW, the gfx data is left as-is, with no conversion.
+ No buffer is allocated for the decoded data, and gfxdata is set to point to the source
+ data.
+ xoffset[0] is an optional displacement (*8) from the beginning of the source data, while
+ yoffset[0] is the line modulo (*8) and charincrement the char modulo (*8). They are *8
+ for consistency with the usual behaviour, but the bottom 3 bits are not used.
+ GFX_ELEMENT_PACKED is automatically set if planes is <= 4.
+
+ This special mode can be used to save memory in games that require several different
+ handlings of the same ROM data (e.g. metro.c can use both 4bpp and 8bpp tiles, and both
+ 8x8 and 16x16; cps.c has 8x8, 16x16 and 32x32 tiles all fetched from the same ROMs).
+*/
+
+enum
+{
+ DRAWMODE_NONE,
+ DRAWMODE_SOURCE,
+ DRAWMODE_SHADOW
+};
+
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+/* these macros describe gfx_layouts in terms of fractions of a region */
+/* they can be used for total, planeoffset, xoffset, yoffset */
+#define RGN_FRAC(num,den) (0x80000000 | (((num) & 0x0f) << 27) | (((den) & 0x0f) << 23))
+#define IS_FRAC(offset) ((offset) & 0x80000000)
+#define FRAC_NUM(offset) (((offset) >> 27) & 0x0f)
+#define FRAC_DEN(offset) (((offset) >> 23) & 0x0f)
+#define FRAC_OFFSET(offset) ((offset) & 0x007fffff)
+
+/* these macros are useful in gfx_layouts */
+#define STEP2(START,STEP) (START),(START)+(STEP)
+#define STEP4(START,STEP) STEP2(START,STEP),STEP2((START)+2*(STEP),STEP)
+#define STEP8(START,STEP) STEP4(START,STEP),STEP4((START)+4*(STEP),STEP)
+#define STEP16(START,STEP) STEP8(START,STEP),STEP8((START)+8*(STEP),STEP)
+#define STEP32(START,STEP) STEP16(START,STEP),STEP16((START)+16*(STEP),STEP)
+#define STEP64(START,STEP) STEP32(START,STEP),STEP32((START)+32*(STEP),STEP)
+#define STEP128(START,STEP) STEP64(START,STEP),STEP64((START)+64*(STEP),STEP)
+#define STEP256(START,STEP) STEP128(START,STEP),STEP128((START)+128*(STEP),STEP)
+#define STEP512(START,STEP) STEP256(START,STEP),STEP256((START)+256*(STEP),STEP)
+#define STEP1024(START,STEP) STEP512(START,STEP),STEP512((START)+512*(STEP),STEP)
+#define STEP2048(START,STEP) STEP1024(START,STEP),STEP1024((START)+1024*(STEP),STEP)
+
+
+/* these macros are used for declaring gfx_decode_entry_entry info arrays. */
+#define GFXDECODE_NAME( name ) gfxdecodeinfo_##name
+#define GFXDECODE_EXTERN( name ) extern const gfx_decode_entry GFXDECODE_NAME(name)[]
+#define GFXDECODE_START( name ) const gfx_decode_entry GFXDECODE_NAME(name)[] = {
+#define GFXDECODE_ENTRY(region,offset,layout,start,colors) { region, offset, &layout, start, colors, 0, 0 },
+#define GFXDECODE_SCALE(region,offset,layout,start,colors,xscale,yscale) { region, offset, &layout, start, colors, xscale, yscale },
+#define GFXDECODE_END { 0 } };
+
+/* these macros are used for declaring gfx_layout structures. */
+#define GFXLAYOUT_RAW( name, planes, width, height, linemod, charmod ) \
+const gfx_layout name = { width, height, RGN_FRAC(1,1), planes, { GFX_RAW }, { 0 }, { linemod }, charmod };
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _gfx_layout gfx_layout;
+struct _gfx_layout
+{
+ UINT16 width; /* pixel width of each element */
+ UINT16 height; /* pixel height of each element */
+ UINT32 total; /* total number of elements, or RGN_FRAC() */
+ UINT16 planes; /* number of bitplanes */
+ UINT32 planeoffset[MAX_GFX_PLANES]; /* bit offset of each bitplane */
+ UINT32 xoffset[MAX_GFX_SIZE]; /* bit offset of each horizontal pixel */
+ UINT32 yoffset[MAX_GFX_SIZE]; /* bit offset of each vertical pixel */
+ UINT32 charincrement; /* distance between two consecutive elements (in bits) */
+ const UINT32 * extxoffs; /* extended X offset array for really big layouts */
+ const UINT32 * extyoffs; /* extended Y offset array for really big layouts */
+};
+
+
+class gfx_element
+{
+public:
+ gfx_element(running_machine &machine)
+ : m_machine(machine) { }
+
+ running_machine &machine() const { return m_machine; }
+
+ UINT16 width; /* current pixel width of each element (changeble with source clipping) */
+ UINT16 height; /* current pixel height of each element (changeble with source clipping) */
+ UINT16 startx; /* current source clip X offset */
+ UINT16 starty; /* current source clip Y offset */
+
+ UINT16 origwidth; /* starting pixel width of each element */
+ UINT16 origheight; /* staring pixel height of each element */
+ UINT8 flags; /* one of the GFX_ELEMENT_* flags above */
+ UINT32 total_elements; /* total number of decoded elements */
+
+ UINT32 color_base; /* base color for rendering */
+ UINT16 color_depth; /* number of colors each pixel can represent */
+ UINT16 color_granularity; /* number of colors for each color code */
+ UINT32 total_colors; /* number of color codes */
+
+ UINT32 * pen_usage; /* bitmask of pens that are used (pens 0-31 only) */
+
+ UINT8 * gfxdata; /* pixel data, 8bpp or 4bpp (if GFX_ELEMENT_PACKED) */
+ UINT32 line_modulo; /* bytes between each row of data */
+ UINT32 char_modulo; /* bytes between each element */
+ const UINT8 * srcdata; /* pointer to the source data for decoding */
+ UINT8 * dirty; /* dirty array for detecting tiles that need decoding */
+ UINT32 dirtyseq; /* sequence number; incremented each time a tile is dirtied */
+
+ gfx_layout layout; /* copy of the original layout */
+
+private:
+ running_machine &m_machine; /* pointer to the owning machine */
+};
+
+
+struct gfx_decode_entry
+{
+ const char * memory_region; /* memory region where the data resides */
+ UINT32 start; /* offset of beginning of data to decode */
+ const gfx_layout *gfxlayout; /* pointer to gfx_layout describing the layout; NULL marks the end of the array */
+ UINT16 color_codes_start; /* offset in the color lookup table where color codes start */
+ UINT16 total_color_codes; /* total number of color codes */
+ UINT8 xscale; /* optional horizontal scaling factor; 0 means 1x */
+ UINT8 yscale; /* optional vertical scaling factor; 0 means 1x */
+};
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+
+/* ----- graphics elements ----- */
+
+/* allocate memory for the graphics elements referenced by a machine */
+void gfx_init(running_machine &machine);
+
+/* allocate a gfx_element structure based on a given layout */
+gfx_element *gfx_element_alloc(running_machine &machine, const gfx_layout *gl, const UINT8 *srcdata, UINT32 total_colors, UINT32 color_base);
+
+/* update a single code in a gfx_element */
+void gfx_element_decode(const gfx_element *gfx, UINT32 code);
+
+/* free a gfx_element */
+void gfx_element_free(gfx_element *gfx);
+
+/* create a temporary one-off gfx_element */
+void gfx_element_build_temporary(gfx_element *gfx, running_machine &machine, UINT8 *base, UINT32 width, UINT32 height, UINT32 rowbytes, UINT32 color_base, UINT32 color_granularity, UINT32 flags);
+
+
+
+/* ----- core graphics drawing ----- */
+
+/* specific drawgfx implementations for each transparency type */
+void drawgfx_opaque(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty);
+void drawgfx_transpen(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty, UINT32 transpen);
+void drawgfx_transpen_raw(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty, UINT32 transpen);
+void drawgfx_transmask(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty, UINT32 transmask);
+void drawgfx_transtable(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty, const UINT8 *pentable, const pen_t *shadowtable);
+void drawgfx_alpha(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty, UINT32 transpen, UINT8 alpha);
+
+
+
+/* ----- zoomed graphics drawing ----- */
+
+/* specific drawgfxzoom implementations for each transparency type */
+void drawgfxzoom_opaque(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty, UINT32 scalex, UINT32 scaley);
+void drawgfxzoom_transpen(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty, UINT32 scalex, UINT32 scaley, UINT32 transpen);
+void drawgfxzoom_transpen_raw(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty, UINT32 scalex, UINT32 scaley, UINT32 transpen);
+void drawgfxzoom_transmask(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty, UINT32 scalex, UINT32 scaley, UINT32 transmask);
+void drawgfxzoom_transtable(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty, UINT32 scalex, UINT32 scaley, const UINT8 *pentable, const pen_t *shadowtable);
+void drawgfxzoom_alpha(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty, UINT32 scalex, UINT32 scaley, UINT32 transpen, UINT8 alpha);
+
+
+
+/* ----- priority masked graphics drawing ----- */
+
+/* specific pdrawgfx implementations for each transparency type */
+void pdrawgfx_opaque(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty, bitmap_t *priority, UINT32 pmask);
+void pdrawgfx_transpen(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty, bitmap_t *priority, UINT32 pmask, UINT32 transpen);
+void pdrawgfx_transpen_raw(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty, bitmap_t *priority, UINT32 pmask, UINT32 transpen);
+void pdrawgfx_transmask(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty, bitmap_t *priority, UINT32 pmask, UINT32 transmask);
+void pdrawgfx_transtable(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty, bitmap_t *priority, UINT32 pmask, const UINT8 *pentable, const pen_t *shadowtable);
+void pdrawgfx_alpha(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty, bitmap_t *priority, UINT32 pmask, UINT32 transpen, UINT8 alpha);
+
+
+
+/* ----- priority masked zoomed graphics drawing ----- */
+
+/* specific pdrawgfxzoom implementations for each transparency type */
+void pdrawgfxzoom_opaque(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty, UINT32 scalex, UINT32 scaley, bitmap_t *priority, UINT32 pmask);
+void pdrawgfxzoom_transpen(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty, UINT32 scalex, UINT32 scaley, bitmap_t *priority, UINT32 pmask, UINT32 transpen);
+void pdrawgfxzoom_transpen_raw(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty, UINT32 scalex, UINT32 scaley, bitmap_t *priority, UINT32 pmask, UINT32 transpen);
+void pdrawgfxzoom_transmask(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty, UINT32 scalex, UINT32 scaley, bitmap_t *priority, UINT32 pmask, UINT32 transmask);
+void pdrawgfxzoom_transtable(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty, UINT32 scalex, UINT32 scaley, bitmap_t *priority, UINT32 pmask, const UINT8 *pentable, const pen_t *shadowtable);
+void pdrawgfxzoom_alpha(bitmap_t *dest, const rectangle *cliprect, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty, UINT32 scalex, UINT32 scaley, bitmap_t *priority, UINT32 pmask, UINT32 transpen, UINT8 alpha);
+
+
+
+/* ----- scanline copying ----- */
+
+/* copy pixels from an 8bpp buffer to a single scanline of a bitmap */
+void draw_scanline8(bitmap_t *bitmap, INT32 destx, INT32 desty, INT32 length, const UINT8 *srcptr, const pen_t *paldata);
+
+/* copy pixels from a 16bpp buffer to a single scanline of a bitmap */
+void draw_scanline16(bitmap_t *bitmap, INT32 destx, INT32 desty, INT32 length, const UINT16 *srcptr, const pen_t *paldata);
+
+/* copy pixels from a 32bpp buffer to a single scanline of a bitmap */
+void draw_scanline32(bitmap_t *bitmap, INT32 destx, INT32 desty, INT32 length, const UINT32 *srcptr, const pen_t *paldata);
+
+
+
+/* ----- scanline extraction ----- */
+
+/* copy pixels from a single scanline of a bitmap to an 8bpp buffer */
+void extract_scanline8(bitmap_t *bitmap, INT32 srcx, INT32 srcy, INT32 length, UINT8 *destptr);
+
+/* copy pixels from a single scanline of a bitmap to a 16bpp buffer */
+void extract_scanline16(bitmap_t *bitmap, INT32 srcx, INT32 srcy, INT32 length, UINT16 *destptr);
+
+/* copy pixels from a single scanline of a bitmap to a 32bpp buffer */
+void extract_scanline32(bitmap_t *bitmap, INT32 srcx, INT32 srcy, INT32 length, UINT32 *destptr);
+
+
+
+/* ----- bitmap copying ----- */
+
+/* copy from one bitmap to another, copying all unclipped pixels */
+void copybitmap(bitmap_t *dest, bitmap_t *src, int flipx, int flipy, INT32 destx, INT32 desty, const rectangle *cliprect);
+
+/* copy from one bitmap to another, copying all unclipped pixels except those that match transpen */
+void copybitmap_trans(bitmap_t *dest, bitmap_t *src, int flipx, int flipy, INT32 destx, INT32 desty, const rectangle *cliprect, UINT32 transpen);
+
+/*
+ Copy a bitmap onto another with scroll and wraparound.
+ These functions support multiple independently scrolling rows/columns.
+ "rows" is the number of indepentently scrolling rows. "rowscroll" is an
+ array of integers telling how much to scroll each row. Same thing for
+ "numcols" and "colscroll".
+ If the bitmap cannot scroll in one direction, set numrows or columns to 0.
+ If the bitmap scrolls as a whole, set numrows and/or numcols to 1.
+ Bidirectional scrolling is, of course, supported only if the bitmap
+ scrolls as a whole in at least one direction.
+*/
+
+/* copy from one bitmap to another, copying all unclipped pixels, and applying scrolling to one or more rows/colums */
+void copyscrollbitmap(bitmap_t *dest, bitmap_t *src, UINT32 numrows, const INT32 *rowscroll, UINT32 numcols, const INT32 *colscroll, const rectangle *cliprect);
+
+/* copy from one bitmap to another, copying all unclipped pixels except those that match transpen, and applying scrolling to one or more rows/colums */
+void copyscrollbitmap_trans(bitmap_t *dest, bitmap_t *src, UINT32 numrows, const INT32 *rowscroll, UINT32 numcols, const INT32 *colscroll, const rectangle *cliprect, UINT32 transpen);
+
+/*
+ Copy a bitmap applying rotation, zooming, and arbitrary distortion.
+ This function works in a way that mimics some real hardware like the Konami
+ 051316, so it requires little or no further processing on the caller side.
+
+ Two 16.16 fixed point counters are used to keep track of the position on
+ the source bitmap. startx and starty are the initial values of those counters,
+ indicating the source pixel that will be drawn at coordinates (0,0) in the
+ destination bitmap. The destination bitmap is scanned left to right, top to
+ bottom; every time the cursor moves one pixel to the right, incxx is added
+ to startx and incxy is added to starty. Every time the cursor moves to the
+ next line, incyx is added to startx and incyy is added to startyy.
+
+ What this means is that if incxy and incyx are both 0, the bitmap will be
+ copied with only zoom and no rotation. If e.g. incxx and incyy are both 0x8000,
+ the source bitmap will be doubled.
+
+ Rotation is performed this way:
+ incxx = 0x10000 * cos(theta)
+ incxy = 0x10000 * -sin(theta)
+ incyx = 0x10000 * sin(theta)
+ incyy = 0x10000 * cos(theta)
+ this will perform a rotation around (0,0), you'll have to adjust startx and
+ starty to move the center of rotation elsewhere.
+
+ Optionally the bitmap can be tiled across the screen instead of doing a single
+ copy. This is obtained by setting the wraparound parameter to true.
+*/
+
+/* copy from one bitmap to another, with zoom and rotation, copying all unclipped pixels */
+void copyrozbitmap(bitmap_t *dest, const rectangle *cliprect, bitmap_t *src, INT32 startx, INT32 starty, INT32 incxx, INT32 incxy, INT32 incyx, INT32 incyy, int wraparound);
+
+/* copy from one bitmap to another, with zoom and rotation, copying all unclipped pixels whose values do not match transpen */
+void copyrozbitmap_trans(bitmap_t *dest, const rectangle *cliprect, bitmap_t *src, INT32 startx, INT32 starty, INT32 incxx, INT32 incxy, INT32 incyx, INT32 incyy, int wraparound, UINT32 transparent_color);
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ gfx_element_set_source - set a pointer to
+ the source of a gfx_element
+-------------------------------------------------*/
+
+INLINE void gfx_element_set_source(gfx_element *gfx, const UINT8 *source)
+{
+ gfx->srcdata = source;
+ memset(gfx->dirty, 1, gfx->total_elements);
+}
+
+
+/*-------------------------------------------------
+ gfx_element_get_data - return a pointer to
+ the base of the given code within a
+ gfx_element, decoding it if it is dirty
+-------------------------------------------------*/
+
+INLINE const UINT8 *gfx_element_get_data(const gfx_element *gfx, UINT32 code)
+{
+ assert(code < gfx->total_elements);
+ if (gfx->dirty[code])
+ gfx_element_decode(gfx, code);
+ return gfx->gfxdata + code * gfx->char_modulo + gfx->starty * gfx->line_modulo + gfx->startx;
+}
+
+
+/*-------------------------------------------------
+ gfx_element_mark_dirty - mark a code of a
+ gfx_element dirty
+-------------------------------------------------*/
+
+INLINE void gfx_element_mark_dirty(gfx_element *gfx, UINT32 code)
+{
+ if (code < gfx->total_elements)
+ {
+ gfx->dirty[code] = 1;
+ gfx->dirtyseq++;
+ }
+}
+
+
+/*-------------------------------------------------
+ gfx_element_set_source_clip - set a source
+ clipping area to apply to subsequent renders
+-------------------------------------------------*/
+
+INLINE void gfx_element_set_source_clip(gfx_element *gfx, UINT32 xoffs, UINT32 width, UINT32 yoffs, UINT32 height)
+{
+ assert(xoffs < gfx->origwidth);
+ assert(yoffs < gfx->origheight);
+ assert(xoffs + width <= gfx->origwidth);
+ assert(yoffs + height <= gfx->origheight);
+
+ gfx->width = width;
+ gfx->height = height;
+ gfx->startx = xoffs;
+ gfx->starty = yoffs;
+}
+
+
+/*-------------------------------------------------
+ alpha_blend_r16 - alpha blend two 16-bit
+ 5-5-5 RGB pixels
+-------------------------------------------------*/
+
+INLINE UINT32 alpha_blend_r16(UINT32 d, UINT32 s, UINT8 level)
+{
+ int alphad = 256 - level;
+ return ((((s & 0x001f) * level + (d & 0x001f) * alphad) >> 8)) |
+ ((((s & 0x03e0) * level + (d & 0x03e0) * alphad) >> 8) & 0x03e0) |
+ ((((s & 0x7c00) * level + (d & 0x7c00) * alphad) >> 8) & 0x7c00);
+}
+
+
+/*-------------------------------------------------
+ alpha_blend_r32 - alpha blend two 32-bit
+ 8-8-8 RGB pixels
+-------------------------------------------------*/
+
+INLINE UINT32 alpha_blend_r32(UINT32 d, UINT32 s, UINT8 level)
+{
+ int alphad = 256 - level;
+ return ((((s & 0x0000ff) * level + (d & 0x0000ff) * alphad) >> 8)) |
+ ((((s & 0x00ff00) * level + (d & 0x00ff00) * alphad) >> 8) & 0x00ff00) |
+ ((((s & 0xff0000) * level + (d & 0xff0000) * alphad) >> 8) & 0xff0000);
+}
+
+
+#endif /* __DRAWGFX_H__ */
diff --git a/trunk/src/emu/drawgfxm.h b/trunk/src/emu/drawgfxm.h
new file mode 100644
index 00000000000..19e2a4fc98f
--- /dev/null
+++ b/trunk/src/emu/drawgfxm.h
@@ -0,0 +1,1394 @@
+/*********************************************************************
+
+ drawgfxm.h
+
+ Macros implementing drawgfx core operations. Drivers can use
+ these if they need custom behavior not provided by the existing
+ drawgfx functions.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+
+ How to use these macros:
+
+ There are two sets of macros. The PIXEL_OP* macros are simple
+ per-pixel operations, designed to take a SOURCE pixel and
+ copy it to the DEST, perhaps updating the PRIORITY pixel as
+ well. On their own, they are not particularly useful.
+
+ The second set of macros represents the core gfx/bitmap walking
+ and rendering code. These macros generally take the target pixel
+ type (UINT8, UINT16, UINT32), one of the PIXEL_OP* macros,
+ and a priority bitmap pixel type (UINT8, UINT16, UINT32, or the
+ special type NO_PRIORITY).
+
+ Although the code may look inefficient at first, the compiler is
+ able to easily optimize out unused cases due to the way the
+ macros are written, leaving behind just the cases we are
+ interested in.
+
+ The general approach for using these macros is:
+
+ my_drawing_function(params)
+ {
+ // ensure that all the required parameters for the mega
+ // macro are defined (if they are not needed, just declare
+ // the variables and set them equal to a known constant
+ // value to help the compiler)
+
+ // set up any additional variables needed by the PIXEL_OP*
+ // macro you want to use (each macro has its own
+ // requirements)
+
+ MEGA_MACRO(BITMAP_TYPE, PIXEL_OP, PRIORITY_TYPE);
+ }
+
+*********************************************************************/
+
+#pragma once
+
+#ifndef __DRAWGFXM_H__
+#define __DRAWGFXM_H__
+
+#include "profiler.h"
+
+
+/* special priority type meaning "none" */
+typedef struct { char dummy[3]; } NO_PRIORITY;
+
+
+/* macros for using the optional priority */
+#define PRIORITY_VALID(x) (sizeof(x) != sizeof(NO_PRIORITY))
+#define PRIORITY_ADDR(p,t,y,x) (PRIORITY_VALID(t) ? BITMAP_ADDR(p, t, y, x) : NULL)
+#define PRIORITY_ADVANCE(t,p,i) do { if (PRIORITY_VALID(t)) (p) += (i); } while (0)
+
+
+/***************************************************************************
+ PIXEL OPERATIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ PIXEL_OP_COPY_OPAQUE - render all pixels
+ regardless of pen, copying directly
+-------------------------------------------------*/
+
+#define PIXEL_OP_COPY_OPAQUE(DEST, PRIORITY, SOURCE) \
+do \
+{ \
+ (DEST) = SOURCE; \
+} \
+while (0) \
+
+
+/*-------------------------------------------------
+ PIXEL_OP_COPY_TRANSPEN - render all pixels
+ except those matching 'transpen', copying
+ directly
+-------------------------------------------------*/
+
+#define PIXEL_OP_COPY_TRANSPEN(DEST, PRIORITY, SOURCE) \
+do \
+{ \
+ UINT32 srcdata = (SOURCE); \
+ if (srcdata != transpen) \
+ (DEST) = SOURCE; \
+} \
+while (0) \
+
+
+/*-------------------------------------------------
+ PIXEL_OP_REMAP_OPAQUE - render all pixels
+ regardless of pen, mapping the pen via the
+ 'paldata' array
+-------------------------------------------------*/
+
+#define PIXEL_OP_REMAP_OPAQUE(DEST, PRIORITY, SOURCE) \
+do \
+{ \
+ (DEST) = paldata[SOURCE]; \
+} \
+while (0) \
+
+#define PIXEL_OP_REMAP_OPAQUE_PRIORITY(DEST, PRIORITY, SOURCE) \
+do \
+{ \
+ if (((1 << ((PRIORITY) & 0x1f)) & pmask) == 0) \
+ (DEST) = paldata[SOURCE]; \
+ (PRIORITY) = 31; \
+} \
+while (0) \
+
+
+/*-------------------------------------------------
+ PIXEL_OP_REMAP_TRANSPEN - render all pixels
+ except those matching 'transpen', mapping the
+ pen via the 'paldata' array
+-------------------------------------------------*/
+
+#define PIXEL_OP_REMAP_TRANSPEN(DEST, PRIORITY, SOURCE) \
+do \
+{ \
+ UINT32 srcdata = (SOURCE); \
+ if (srcdata != transpen) \
+ (DEST) = paldata[srcdata]; \
+} \
+while (0) \
+
+#define PIXEL_OP_REMAP_TRANSPEN_PRIORITY(DEST, PRIORITY, SOURCE) \
+do \
+{ \
+ UINT32 srcdata = (SOURCE); \
+ if (srcdata != transpen) \
+ { \
+ if (((1 << ((PRIORITY) & 0x1f)) & pmask) == 0) \
+ (DEST) = paldata[srcdata]; \
+ (PRIORITY) = 31; \
+ } \
+} \
+while (0) \
+
+
+/*-------------------------------------------------
+ PIXEL_OP_REBASE_TRANSPEN - render all pixels
+ except those matching 'transpen', adding
+ 'color' to the pen value
+-------------------------------------------------*/
+
+#define PIXEL_OP_REBASE_TRANSPEN(DEST, PRIORITY, SOURCE) \
+do \
+{ \
+ UINT32 srcdata = (SOURCE); \
+ if (srcdata != transpen) \
+ (DEST) = color + srcdata; \
+} \
+while (0) \
+
+#define PIXEL_OP_REBASE_TRANSPEN_PRIORITY(DEST, PRIORITY, SOURCE) \
+do \
+{ \
+ UINT32 srcdata = (SOURCE); \
+ if (srcdata != transpen) \
+ { \
+ if (((1 << ((PRIORITY) & 0x1f)) & pmask) == 0) \
+ (DEST) = color + srcdata; \
+ (PRIORITY) = 31; \
+ } \
+} \
+while (0) \
+
+
+/*-------------------------------------------------
+ PIXEL_OP_REMAP_TRANSMASK - render all pixels
+ except those matching 'transmask', mapping the
+ pen via the 'paldata' array
+-------------------------------------------------*/
+
+#define PIXEL_OP_REMAP_TRANSMASK(DEST, PRIORITY, SOURCE) \
+do \
+{ \
+ UINT32 srcdata = (SOURCE); \
+ if (((transmask >> srcdata) & 1) == 0) \
+ (DEST) = paldata[srcdata]; \
+} \
+while (0) \
+
+#define PIXEL_OP_REMAP_TRANSMASK_PRIORITY(DEST, PRIORITY, SOURCE) \
+do \
+{ \
+ UINT32 srcdata = (SOURCE); \
+ if (((transmask >> srcdata) & 1) == 0) \
+ { \
+ if (((1 << ((PRIORITY) & 0x1f)) & pmask) == 0) \
+ (DEST) = paldata[srcdata]; \
+ (PRIORITY) = 31; \
+ } \
+} \
+while (0) \
+
+
+/*-------------------------------------------------
+ PIXEL_OP_REMAP_TRANSTABLE - look up each pen in
+ 'pentable'; if the entry is DRAWMODE_NONE,
+ don't draw it; if the entry is DRAWMODE_SOURCE,
+ look up the pen via the 'paldata' array; if the
+ entry is DRAWMODE_SHADOW, generate a shadow of
+ the destination pixel using 'shadowtable'
+-------------------------------------------------*/
+
+#define PIXEL_OP_REMAP_TRANSTABLE16(DEST, PRIORITY, SOURCE) \
+do \
+{ \
+ UINT32 srcdata = (SOURCE); \
+ UINT32 entry = pentable[srcdata]; \
+ if (entry != DRAWMODE_NONE) \
+ { \
+ if (entry == DRAWMODE_SOURCE) \
+ (DEST) = paldata[srcdata]; \
+ else \
+ (DEST) = shadowtable[DEST]; \
+ } \
+} \
+while (0) \
+
+#define PIXEL_OP_REMAP_TRANSTABLE32(DEST, PRIORITY, SOURCE) \
+do \
+{ \
+ UINT32 srcdata = (SOURCE); \
+ UINT32 entry = pentable[srcdata]; \
+ if (entry != DRAWMODE_NONE) \
+ { \
+ if (entry == DRAWMODE_SOURCE) \
+ (DEST) = paldata[srcdata]; \
+ else \
+ (DEST) = shadowtable[rgb_to_rgb15(DEST)]; \
+ } \
+} \
+while (0) \
+
+#define PIXEL_OP_REMAP_TRANSTABLE16_PRIORITY(DEST, PRIORITY, SOURCE) \
+do \
+{ \
+ UINT32 srcdata = (SOURCE); \
+ UINT32 entry = pentable[srcdata]; \
+ if (entry != DRAWMODE_NONE) \
+ { \
+ UINT8 pridata = (PRIORITY); \
+ if (entry == DRAWMODE_SOURCE) \
+ { \
+ if (((1 << (pridata & 0x1f)) & pmask) == 0) \
+ (DEST) = paldata[srcdata]; \
+ (PRIORITY) = 31; \
+ } \
+ else if ((pridata & 0x80) == 0 && ((1 << (pridata & 0x1f)) & pmask) == 0) \
+ { \
+ (DEST) = shadowtable[DEST]; \
+ (PRIORITY) = pridata | 0x80; \
+ } \
+ } \
+} \
+while (0) \
+
+#define PIXEL_OP_REMAP_TRANSTABLE32_PRIORITY(DEST, PRIORITY, SOURCE) \
+do \
+{ \
+ UINT32 srcdata = (SOURCE); \
+ UINT32 entry = pentable[srcdata]; \
+ if (entry != DRAWMODE_NONE) \
+ { \
+ UINT8 pridata = (PRIORITY); \
+ if (entry == DRAWMODE_SOURCE) \
+ { \
+ if (((1 << (pridata & 0x1f)) & pmask) == 0) \
+ (DEST) = paldata[srcdata]; \
+ (PRIORITY) = 31; \
+ } \
+ else if ((pridata & 0x80) == 0 && ((1 << (pridata & 0x1f)) & pmask) == 0) \
+ { \
+ (DEST) = shadowtable[rgb_to_rgb15(DEST)]; \
+ (PRIORITY) = pridata | 0x80; \
+ } \
+ } \
+} \
+while (0) \
+
+
+/*-------------------------------------------------
+ PIXEL_OP_REMAP_TRANSPEN_ALPHA - render all
+ pixels except those matching 'transpen',
+ mapping the pen to via the 'paldata' array;
+ the resulting color is RGB alpha blended
+ against the destination using 'alpha'
+-------------------------------------------------*/
+
+#define PIXEL_OP_REMAP_TRANSPEN_ALPHA16(DEST, PRIORITY, SOURCE) \
+do \
+{ \
+ UINT32 srcdata = (SOURCE); \
+ if (srcdata != transpen) \
+ (DEST) = alpha_blend_r16((DEST), paldata[srcdata], alpha); \
+} \
+while (0) \
+
+#define PIXEL_OP_REMAP_TRANSPEN_ALPHA32(DEST, PRIORITY, SOURCE) \
+do \
+{ \
+ UINT32 srcdata = (SOURCE); \
+ if (srcdata != transpen) \
+ (DEST) = alpha_blend_r32((DEST), paldata[srcdata], alpha); \
+} \
+while (0) \
+
+#define PIXEL_OP_REMAP_TRANSPEN_ALPHA16_PRIORITY(DEST, PRIORITY, SOURCE) \
+do \
+{ \
+ UINT32 srcdata = (SOURCE); \
+ if (srcdata != transpen) \
+ { \
+ if (((1 << ((PRIORITY) & 0x1f)) & pmask) == 0) \
+ (DEST) = alpha_blend_r16((DEST), paldata[srcdata], alpha); \
+ (PRIORITY) = 31; \
+ } \
+} \
+while (0) \
+
+#define PIXEL_OP_REMAP_TRANSPEN_ALPHA32_PRIORITY(DEST, PRIORITY, SOURCE) \
+do \
+{ \
+ UINT32 srcdata = (SOURCE); \
+ if (srcdata != transpen) \
+ { \
+ if (((1 << ((PRIORITY) & 0x1f)) & pmask) == 0) \
+ (DEST) = alpha_blend_r32((DEST), paldata[srcdata], alpha); \
+ (PRIORITY) = 31; \
+ } \
+} \
+while (0) \
+
+
+
+/***************************************************************************
+ BASIC DRAWGFX CORE
+***************************************************************************/
+
+/*
+ Assumed input parameters or local variables:
+
+ bitmap_t *dest - the bitmap to render to
+ const rectangle *cliprect - a clipping rectangle (assumed to be clipped to the size of 'dest')
+ const gfx_element *gfx - pointer to the gfx_element to render
+ UINT32 code - index of the entry within gfx_element
+ UINT32 color - index of the color within gfx_element
+ int flipx - non-zero means render right-to-left instead of left-to-right
+ int flipy - non-zero means render bottom-to-top instead of top-to-bottom
+ INT32 destx - the top-left X coordinate to render to
+ INT32 desty - the top-left Y coordinate to render to
+ bitmap_t *priority - the priority bitmap (even if PRIORITY_TYPE is NO_PRIORITY, at least needs a dummy)
+*/
+
+
+#define DRAWGFX_CORE(PIXEL_TYPE, PIXEL_OP, PRIORITY_TYPE) \
+do { \
+ g_profiler.start(PROFILER_DRAWGFX); \
+ do { \
+ const UINT8 *srcdata; \
+ INT32 destendx, destendy; \
+ INT32 srcx, srcy; \
+ INT32 curx, cury; \
+ INT32 dy; \
+ \
+ assert(dest != NULL); \
+ assert(gfx != NULL); \
+ assert(!PRIORITY_VALID(PRIORITY_TYPE) || priority != NULL); \
+ assert(cliprect == NULL || cliprect->min_x >= 0); \
+ assert(cliprect == NULL || cliprect->max_x < dest->width); \
+ assert(cliprect == NULL || cliprect->min_y >= 0); \
+ assert(cliprect == NULL || cliprect->max_y < dest->height); \
+ \
+ /* NULL clip means use the full bitmap */ \
+ if (cliprect == NULL) \
+ cliprect = &dest->cliprect; \
+ \
+ /* ignore empty/invalid cliprects */ \
+ if (cliprect->min_x > cliprect->max_x || cliprect->min_y > cliprect->max_y) \
+ break; \
+ \
+ /* compute final pixel in X and exit if we are entirely clipped */ \
+ destendx = destx + gfx->width - 1; \
+ if (destx > cliprect->max_x || destendx < cliprect->min_x) \
+ break; \
+ \
+ /* apply left clip */ \
+ srcx = 0; \
+ if (destx < cliprect->min_x) \
+ { \
+ srcx = cliprect->min_x - destx; \
+ destx = cliprect->min_x; \
+ } \
+ \
+ /* apply right clip */ \
+ if (destendx > cliprect->max_x) \
+ destendx = cliprect->max_x; \
+ \
+ /* compute final pixel in Y and exit if we are entirely clipped */ \
+ destendy = desty + gfx->height - 1; \
+ if (desty > cliprect->max_y || destendy < cliprect->min_y) \
+ break; \
+ \
+ /* apply top clip */ \
+ srcy = 0; \
+ if (desty < cliprect->min_y) \
+ { \
+ srcy = cliprect->min_y - desty; \
+ desty = cliprect->min_y; \
+ } \
+ \
+ /* apply bottom clip */ \
+ if (destendy > cliprect->max_y) \
+ destendy = cliprect->max_y; \
+ \
+ /* apply X flipping */ \
+ if (flipx) \
+ srcx = gfx->width - 1 - srcx; \
+ \
+ /* apply Y flipping */ \
+ dy = gfx->line_modulo; \
+ if (flipy) \
+ { \
+ srcy = gfx->height - 1 - srcy; \
+ dy = -dy; \
+ } \
+ \
+ /* fetch the source data */ \
+ srcdata = gfx_element_get_data(gfx, code); \
+ \
+ /* draw normal 8bpp source data */ \
+ if (!(gfx->flags & GFX_ELEMENT_PACKED)) \
+ { \
+ /* compute how many blocks of 4 pixels we have */ \
+ UINT32 numblocks = (destendx + 1 - destx) / 4; \
+ UINT32 leftovers = (destendx + 1 - destx) - 4 * numblocks; \
+ \
+ /* adjust srcdata to point to the first source pixel of the row */ \
+ srcdata += srcy * gfx->line_modulo + srcx; \
+ \
+ /* non-flipped 8bpp case */ \
+ if (!flipx) \
+ { \
+ /* iterate over pixels in Y */ \
+ for (cury = desty; cury <= destendy; cury++) \
+ { \
+ PRIORITY_TYPE *priptr = PRIORITY_ADDR(priority, PRIORITY_TYPE, cury, destx); \
+ PIXEL_TYPE *destptr = BITMAP_ADDR(dest, PIXEL_TYPE, cury, destx); \
+ const UINT8 *srcptr = srcdata; \
+ srcdata += dy; \
+ \
+ /* iterate over unrolled blocks of 4 */ \
+ for (curx = 0; curx < numblocks; curx++) \
+ { \
+ PIXEL_OP(destptr[0], priptr[0], srcptr[0]); \
+ PIXEL_OP(destptr[1], priptr[1], srcptr[1]); \
+ PIXEL_OP(destptr[2], priptr[2], srcptr[2]); \
+ PIXEL_OP(destptr[3], priptr[3], srcptr[3]); \
+ \
+ srcptr += 4; \
+ destptr += 4; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 4); \
+ } \
+ \
+ /* iterate over leftover pixels */ \
+ for (curx = 0; curx < leftovers; curx++) \
+ { \
+ PIXEL_OP(destptr[0], priptr[0], srcptr[0]); \
+ srcptr++; \
+ destptr++; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 1); \
+ } \
+ } \
+ } \
+ \
+ /* flipped 8bpp case */ \
+ else \
+ { \
+ /* iterate over pixels in Y */ \
+ for (cury = desty; cury <= destendy; cury++) \
+ { \
+ PRIORITY_TYPE *priptr = PRIORITY_ADDR(priority, PRIORITY_TYPE, cury, destx); \
+ PIXEL_TYPE *destptr = BITMAP_ADDR(dest, PIXEL_TYPE, cury, destx); \
+ const UINT8 *srcptr = srcdata; \
+ srcdata += dy; \
+ \
+ /* iterate over unrolled blocks of 4 */ \
+ for (curx = 0; curx < numblocks; curx++) \
+ { \
+ PIXEL_OP(destptr[0], priptr[0], srcptr[ 0]); \
+ PIXEL_OP(destptr[1], priptr[1], srcptr[-1]); \
+ PIXEL_OP(destptr[2], priptr[2], srcptr[-2]); \
+ PIXEL_OP(destptr[3], priptr[3], srcptr[-3]); \
+ \
+ srcptr -= 4; \
+ destptr += 4; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 4); \
+ } \
+ \
+ /* iterate over leftover pixels */ \
+ for (curx = 0; curx < leftovers; curx++) \
+ { \
+ PIXEL_OP(destptr[0], priptr[0], srcptr[0]); \
+ srcptr--; \
+ destptr++; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 1); \
+ } \
+ } \
+ } \
+ } \
+ \
+ /* draw packed 4bpp source data */ \
+ else \
+ { \
+ /* adjust srcdata to point to the first source pixel of the row */ \
+ srcdata += srcy * gfx->line_modulo + srcx / 2; \
+ \
+ /* non-flipped 4bpp case */ \
+ if (!flipx) \
+ { \
+ /* compute how many blocks of 2 pixels we have */ \
+ UINT32 oddstart = srcx & 1; \
+ UINT32 numblocks = (destendx + 1 - destx - oddstart) / 2; \
+ UINT32 leftovers = (destendx + 1 - destx - oddstart) - 2 * numblocks; \
+ \
+ /* iterate over pixels in Y */ \
+ for (cury = desty; cury <= destendy; cury++) \
+ { \
+ PRIORITY_TYPE *priptr = PRIORITY_ADDR(priority, PRIORITY_TYPE, cury, destx); \
+ PIXEL_TYPE *destptr = BITMAP_ADDR(dest, PIXEL_TYPE, cury, destx); \
+ const UINT8 *srcptr = srcdata; \
+ srcdata += dy; \
+ \
+ /* odd starting pixel */ \
+ if (oddstart) \
+ { \
+ PIXEL_OP(destptr[0], priptr[0], srcptr[0] >> 4); \
+ srcptr++; \
+ destptr++; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 1); \
+ } \
+ \
+ /* iterate over unrolled blocks of 2 */ \
+ for (curx = 0; curx < numblocks; curx++) \
+ { \
+ UINT8 srcbyte = *srcptr++; \
+ PIXEL_OP(destptr[0], priptr[0], srcbyte & 15); \
+ PIXEL_OP(destptr[1], priptr[1], srcbyte >> 4); \
+ destptr += 2; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 2); \
+ } \
+ \
+ /* iterate over leftover pixels */ \
+ if (leftovers > 0) \
+ PIXEL_OP(destptr[0], priptr[0], srcptr[0] & 15); \
+ } \
+ } \
+ \
+ /* flipped 4bpp case */ \
+ else \
+ { \
+ /* compute how many blocks of 2 pixels we have */ \
+ UINT32 oddstart = ~srcx & 1; \
+ UINT32 numblocks = (destendx + 1 - destx - oddstart) / 2; \
+ UINT32 leftovers = (destendx + 1 - destx - oddstart) - 2 * numblocks; \
+ \
+ /* iterate over pixels in Y */ \
+ for (cury = desty; cury <= destendy; cury++) \
+ { \
+ PRIORITY_TYPE *priptr = PRIORITY_ADDR(priority, PRIORITY_TYPE, cury, destx); \
+ PIXEL_TYPE *destptr = BITMAP_ADDR(dest, PIXEL_TYPE, cury, destx); \
+ const UINT8 *srcptr = srcdata; \
+ srcdata += dy; \
+ \
+ /* odd right pixel */ \
+ if (oddstart) \
+ { \
+ PIXEL_OP(destptr[0], priptr[0], srcptr[0] & 15); \
+ srcptr--; \
+ destptr++; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 1); \
+ } \
+ \
+ /* middle pixels */ \
+ for (curx = 0; curx < numblocks; curx++) \
+ { \
+ UINT8 srcbyte = *srcptr--; \
+ PIXEL_OP(destptr[0], priptr[0], srcbyte >> 4); \
+ PIXEL_OP(destptr[1], priptr[1], srcbyte & 15); \
+ destptr += 2; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 2); \
+ } \
+ \
+ /* odd left pixel */ \
+ if (leftovers > 0) \
+ PIXEL_OP(destptr[0], priptr[0], srcptr[0] >> 4); \
+ } \
+ } \
+ } \
+ } while (0); \
+ g_profiler.stop(); \
+} while (0)
+
+
+
+/***************************************************************************
+ BASIC DRAWGFXZOOM CORE
+***************************************************************************/
+
+/*
+ Assumed input parameters or local variables:
+
+ bitmap_t *dest - the bitmap to render to
+ const rectangle *cliprect - a clipping rectangle (assumed to be clipped to the size of 'dest')
+ const gfx_element *gfx - pointer to the gfx_element to render
+ UINT32 code - index of the entry within gfx_element
+ UINT32 color - index of the color within gfx_element
+ int flipx - non-zero means render right-to-left instead of left-to-right
+ int flipy - non-zero means render bottom-to-top instead of top-to-bottom
+ INT32 destx - the top-left X coordinate to render to
+ INT32 desty - the top-left Y coordinate to render to
+ UINT32 scalex - the 16.16 scale factor in the X dimension
+ UINT32 scaley - the 16.16 scale factor in the Y dimension
+ bitmap_t *priority - the priority bitmap (even if PRIORITY_TYPE is NO_PRIORITY, at least needs a dummy)
+*/
+
+
+#define DRAWGFXZOOM_CORE(PIXEL_TYPE, PIXEL_OP, PRIORITY_TYPE) \
+do { \
+ g_profiler.start(PROFILER_DRAWGFX); \
+ do { \
+ const UINT8 *srcdata; \
+ UINT32 dstwidth, dstheight; \
+ INT32 destendx, destendy; \
+ INT32 srcx, srcy; \
+ INT32 curx, cury; \
+ INT32 dx, dy; \
+ \
+ assert(dest != NULL); \
+ assert(gfx != NULL); \
+ assert(!PRIORITY_VALID(PRIORITY_TYPE) || priority != NULL); \
+ assert(cliprect == NULL || cliprect->min_x >= 0); \
+ assert(cliprect == NULL || cliprect->max_x < dest->width); \
+ assert(cliprect == NULL || cliprect->min_y >= 0); \
+ assert(cliprect == NULL || cliprect->max_y < dest->height); \
+ \
+ /* NULL clip means use the full bitmap */ \
+ if (cliprect == NULL) \
+ cliprect = &dest->cliprect; \
+ \
+ /* ignore empty/invalid cliprects */ \
+ if (cliprect->min_x > cliprect->max_x || cliprect->min_y > cliprect->max_y) \
+ break; \
+ \
+ /* compute scaled size */ \
+ dstwidth = (scalex * gfx->width + 0x8000) >> 16; \
+ dstheight = (scaley * gfx->height + 0x8000) >> 16; \
+ if (dstwidth < 1 || dstheight < 1) \
+ break; \
+ \
+ /* compute 16.16 source steps in dx and dy */ \
+ dx = (gfx->width << 16) / dstwidth; \
+ dy = (gfx->height << 16) / dstheight; \
+ \
+ /* compute final pixel in X and exit if we are entirely clipped */ \
+ destendx = destx + dstwidth - 1; \
+ if (destx > cliprect->max_x || destendx < cliprect->min_x) \
+ break; \
+ \
+ /* apply left clip */ \
+ srcx = 0; \
+ if (destx < cliprect->min_x) \
+ { \
+ srcx = (cliprect->min_x - destx) * dx; \
+ destx = cliprect->min_x; \
+ } \
+ \
+ /* apply right clip */ \
+ if (destendx > cliprect->max_x) \
+ destendx = cliprect->max_x; \
+ \
+ /* compute final pixel in Y and exit if we are entirely clipped */ \
+ destendy = desty + dstheight - 1; \
+ if (desty > cliprect->max_y || destendy < cliprect->min_y) \
+ { \
+ g_profiler.stop(); \
+ return; \
+ } \
+ \
+ /* apply top clip */ \
+ srcy = 0; \
+ if (desty < cliprect->min_y) \
+ { \
+ srcy = (cliprect->min_y - desty) * dy; \
+ desty = cliprect->min_y; \
+ } \
+ \
+ /* apply bottom clip */ \
+ if (destendy > cliprect->max_y) \
+ destendy = cliprect->max_y; \
+ \
+ /* apply X flipping */ \
+ if (flipx) \
+ { \
+ srcx = (dstwidth - 1) * dx - srcx; \
+ dx = -dx; \
+ } \
+ \
+ /* apply Y flipping */ \
+ if (flipy) \
+ { \
+ srcy = (dstheight - 1) * dy - srcy; \
+ dy = -dy; \
+ } \
+ \
+ /* fetch the source data */ \
+ srcdata = gfx_element_get_data(gfx, code); \
+ \
+ /* draw normal */ \
+ if (!(gfx->flags & GFX_ELEMENT_PACKED)) \
+ { \
+ /* compute how many blocks of 4 pixels we have */ \
+ UINT32 numblocks = (destendx + 1 - destx) / 4; \
+ UINT32 leftovers = (destendx + 1 - destx) - 4 * numblocks; \
+ \
+ /* iterate over pixels in Y */ \
+ for (cury = desty; cury <= destendy; cury++) \
+ { \
+ PRIORITY_TYPE *priptr = PRIORITY_ADDR(priority, PRIORITY_TYPE, cury, destx); \
+ PIXEL_TYPE *destptr = BITMAP_ADDR(dest, PIXEL_TYPE, cury, destx); \
+ const UINT8 *srcptr = srcdata + (srcy >> 16) * gfx->line_modulo; \
+ INT32 cursrcx = srcx; \
+ srcy += dy; \
+ \
+ /* iterate over unrolled blocks of 4 */ \
+ for (curx = 0; curx < numblocks; curx++) \
+ { \
+ PIXEL_OP(destptr[0], priptr[0], srcptr[cursrcx >> 16]); \
+ cursrcx += dx; \
+ PIXEL_OP(destptr[1], priptr[1], srcptr[cursrcx >> 16]); \
+ cursrcx += dx; \
+ PIXEL_OP(destptr[2], priptr[2], srcptr[cursrcx >> 16]); \
+ cursrcx += dx; \
+ PIXEL_OP(destptr[3], priptr[3], srcptr[cursrcx >> 16]); \
+ cursrcx += dx; \
+ \
+ destptr += 4; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 4); \
+ } \
+ \
+ /* iterate over leftover pixels */ \
+ for (curx = 0; curx < leftovers; curx++) \
+ { \
+ PIXEL_OP(destptr[0], priptr[0], srcptr[cursrcx >> 16]); \
+ cursrcx += dx; \
+ destptr++; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 1); \
+ } \
+ } \
+ } \
+ \
+ /* draw packed */ \
+ else \
+ { \
+ /* iterate over pixels in Y */ \
+ for (cury = desty; cury <= destendy; cury++) \
+ { \
+ PRIORITY_TYPE *priptr = PRIORITY_ADDR(priority, PRIORITY_TYPE, cury, destx); \
+ PIXEL_TYPE *destptr = BITMAP_ADDR(dest, PIXEL_TYPE, cury, destx); \
+ const UINT8 *srcptr = srcdata + (srcy >> 16) * gfx->line_modulo; \
+ INT32 cursrcx = srcx; \
+ srcy += dy; \
+ \
+ /* iterate over pixels in X */ \
+ for (curx = destx; curx <= destendx; curx++) \
+ { \
+ PIXEL_OP(destptr[0], priptr[0], (srcptr[cursrcx >> 17] >> ((cursrcx >> 14) & 4)) & 15); \
+ cursrcx += dx; \
+ destptr++; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 1); \
+ } \
+ } \
+ } \
+ } while (0); \
+ g_profiler.stop(); \
+} while (0)
+
+
+
+/***************************************************************************
+ BASIC COPYBITMAP CORE
+***************************************************************************/
+
+/*
+ Assumed input parameters or local variables:
+
+ bitmap_t *dest - the bitmap to copy to
+ bitmap_t *src - the bitmap to copy from (must be same bpp as dest)
+ const rectangle *cliprect - a clipping rectangle (assumed to be clipped to the size of 'dest')
+ int flipx - non-zero means render right-to-left instead of left-to-right
+ int flipy - non-zero means render bottom-to-top instead of top-to-bottom
+ INT32 destx - the top-left X coordinate to copy to
+ INT32 desty - the top-left Y coordinate to copy to
+ bitmap_t *priority - the priority bitmap (even if PRIORITY_TYPE is NO_PRIORITY, at least needs a dummy)
+*/
+
+#define COPYBITMAP_CORE(PIXEL_TYPE, PIXEL_OP, PRIORITY_TYPE) \
+do { \
+ g_profiler.start(PROFILER_COPYBITMAP); \
+ do { \
+ const PIXEL_TYPE *srcdata; \
+ UINT32 numblocks, leftovers; \
+ INT32 destendx, destendy; \
+ INT32 srcx, srcy; \
+ INT32 curx, cury; \
+ INT32 dx, dy; \
+ \
+ assert(dest != NULL); \
+ assert(src != NULL); \
+ assert(!PRIORITY_VALID(PRIORITY_TYPE) || priority != NULL); \
+ assert(cliprect == NULL || cliprect->min_x >= 0); \
+ assert(cliprect == NULL || cliprect->max_x < dest->width); \
+ assert(cliprect == NULL || cliprect->min_y >= 0); \
+ assert(cliprect == NULL || cliprect->max_y < dest->height); \
+ \
+ /* NULL clip means use the full bitmap */ \
+ if (cliprect == NULL) \
+ cliprect = &dest->cliprect; \
+ \
+ /* ignore empty/invalid cliprects */ \
+ if (cliprect->min_x > cliprect->max_x || cliprect->min_y > cliprect->max_y) \
+ break; \
+ \
+ /* standard setup; dx counts bytes in X, dy counts pixels in Y */ \
+ dx = 1; \
+ dy = src->rowpixels; \
+ \
+ /* compute final pixel in X and exit if we are entirely clipped */ \
+ destendx = destx + src->width - 1; \
+ if (destx > cliprect->max_x || destendx < cliprect->min_x) \
+ break; \
+ \
+ /* apply left clip */ \
+ srcx = 0; \
+ if (destx < cliprect->min_x) \
+ { \
+ srcx = cliprect->min_x - destx; \
+ destx = cliprect->min_x; \
+ } \
+ \
+ /* apply right clip */ \
+ if (destendx > cliprect->max_x) \
+ destendx = cliprect->max_x; \
+ \
+ /* compute final pixel in Y and exit if we are entirely clipped */ \
+ destendy = desty + src->height - 1; \
+ if (desty > cliprect->max_y || destendy < cliprect->min_y) \
+ break; \
+ \
+ /* apply top clip */ \
+ srcy = 0; \
+ if (desty < cliprect->min_y) \
+ { \
+ srcy = cliprect->min_y - desty; \
+ desty = cliprect->min_y; \
+ } \
+ \
+ /* apply bottom clip */ \
+ if (destendy > cliprect->max_y) \
+ destendy = cliprect->max_y; \
+ \
+ /* apply X flipping */ \
+ if (flipx) \
+ { \
+ srcx = src->width - 1 - srcx; \
+ dx = -dx; \
+ } \
+ \
+ /* apply Y flipping */ \
+ if (flipy) \
+ { \
+ srcy = src->height - 1 - srcy; \
+ dy = -dy; \
+ } \
+ \
+ /* compute how many blocks of 4 pixels we have */ \
+ numblocks = (destendx + 1 - destx) / 4; \
+ leftovers = (destendx + 1 - destx) - 4 * numblocks; \
+ \
+ /* compute the address of the first source pixel of the first row */ \
+ srcdata = BITMAP_ADDR(src, PIXEL_TYPE, srcy, srcx); \
+ \
+ /* non-flipped case */ \
+ if (!flipx) \
+ { \
+ /* iterate over pixels in Y */ \
+ for (cury = desty; cury <= destendy; cury++) \
+ { \
+ PRIORITY_TYPE *priptr = PRIORITY_ADDR(priority, PRIORITY_TYPE, cury, destx); \
+ PIXEL_TYPE *destptr = BITMAP_ADDR(dest, PIXEL_TYPE, cury, destx); \
+ const PIXEL_TYPE *srcptr = srcdata; \
+ srcdata += dy; \
+ \
+ /* iterate over unrolled blocks of 4 */ \
+ for (curx = 0; curx < numblocks; curx++) \
+ { \
+ PIXEL_OP(destptr[0], priptr[0], srcptr[0]); \
+ PIXEL_OP(destptr[1], priptr[1], srcptr[1]); \
+ PIXEL_OP(destptr[2], priptr[2], srcptr[2]); \
+ PIXEL_OP(destptr[3], priptr[3], srcptr[3]); \
+ \
+ srcptr += 4; \
+ destptr += 4; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 4); \
+ } \
+ \
+ /* iterate over leftover pixels */ \
+ for (curx = 0; curx < leftovers; curx++) \
+ { \
+ PIXEL_OP(destptr[0], priptr[0], srcptr[0]); \
+ srcptr++; \
+ destptr++; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 1); \
+ } \
+ } \
+ } \
+ \
+ /* flipped case */ \
+ else \
+ { \
+ /* iterate over pixels in Y */ \
+ for (cury = desty; cury <= destendy; cury++) \
+ { \
+ PRIORITY_TYPE *priptr = PRIORITY_ADDR(priority, PRIORITY_TYPE, cury, destx); \
+ PIXEL_TYPE *destptr = BITMAP_ADDR(dest, PIXEL_TYPE, cury, destx); \
+ const PIXEL_TYPE *srcptr = srcdata; \
+ srcdata += dy; \
+ \
+ /* iterate over unrolled blocks of 4 */ \
+ for (curx = 0; curx < numblocks; curx++) \
+ { \
+ PIXEL_OP(destptr[0], priptr[0], srcptr[ 0]); \
+ PIXEL_OP(destptr[1], priptr[1], srcptr[-1]); \
+ PIXEL_OP(destptr[2], priptr[2], srcptr[-2]); \
+ PIXEL_OP(destptr[3], priptr[3], srcptr[-3]); \
+ \
+ srcptr -= 4; \
+ destptr += 4; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 4); \
+ } \
+ \
+ /* iterate over leftover pixels */ \
+ for (curx = 0; curx < leftovers; curx++) \
+ { \
+ PIXEL_OP(destptr[0], priptr[0], srcptr[0]); \
+ srcptr--; \
+ destptr++; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 1); \
+ } \
+ } \
+ } \
+ } while (0); \
+ g_profiler.stop(); \
+} while (0)
+
+
+
+/***************************************************************************
+ BASIC COPYROZBITMAP CORE
+***************************************************************************/
+
+/*
+ Assumed input parameters or local variables:
+
+ bitmap_t *dest - the bitmap to copy to
+ bitmap_t *src - the bitmap to copy from (must be same bpp as dest)
+ const rectangle *cliprect - a clipping rectangle (assumed to be clipped to the size of 'dest')
+ INT32 destx - the 16.16 source X position at destination pixel (0,0)
+ INT32 desty - the 16.16 source Y position at destination pixel (0,0)
+ INT32 incxx - the 16.16 amount to increment in source X for each destination X pixel
+ INT32 incyx - the 16.16 amount to increment in source Y for each destination X pixel
+ INT32 incxy - the 16.16 amount to increment in source X for each destination Y pixel
+ INT32 incyy - the 16.16 amount to increment in source Y for each destination Y pixel
+ int wraparound - non-zero means wrap when hitting the edges of the source
+ bitmap_t *priority - the priority bitmap (even if PRIORITY_TYPE is NO_PRIORITY, at least needs a dummy)
+*/
+
+#define COPYROZBITMAP_CORE(PIXEL_TYPE, PIXEL_OP, PRIORITY_TYPE) \
+do { \
+ UINT32 srcfixwidth, srcfixheight; \
+ UINT32 numblocks, leftovers; \
+ INT32 curx, cury; \
+ \
+ g_profiler.start(PROFILER_COPYBITMAP); \
+ \
+ assert(dest != NULL); \
+ assert(src != NULL); \
+ assert(!PRIORITY_VALID(PRIORITY_TYPE) || priority != NULL); \
+ assert(cliprect == NULL || cliprect->min_x >= 0); \
+ assert(cliprect == NULL || cliprect->max_x < dest->width); \
+ assert(cliprect == NULL || cliprect->min_y >= 0); \
+ assert(cliprect == NULL || cliprect->max_y < dest->height); \
+ assert(!wraparound || (src->width & (src->width - 1)) == 0); \
+ assert(!wraparound || (src->height & (src->height - 1)) == 0); \
+ \
+ /* NULL clip means use the full bitmap */ \
+ if (cliprect == NULL) \
+ cliprect = &dest->cliprect; \
+ \
+ /* ignore empty/invalid cliprects */ \
+ if (cliprect->min_x > cliprect->max_x || cliprect->min_y > cliprect->max_y) \
+ break; \
+ \
+ /* compute fixed-point 16.16 size of the source bitmap */ \
+ srcfixwidth = src->width << 16; \
+ srcfixheight = src->height << 16; \
+ \
+ /* advance the starting coordinates to the top-left of the cliprect */ \
+ startx += cliprect->min_x * incxx + cliprect->min_y * incyx; \
+ starty += cliprect->min_x * incxy + cliprect->min_y * incyy; \
+ \
+ /* compute how many blocks of 4 pixels we have */ \
+ numblocks = (cliprect->max_x + 1 - cliprect->min_x) / 4; \
+ leftovers = (cliprect->max_x + 1 - cliprect->min_x) - 4 * numblocks; \
+ \
+ /* if incxy and incyx are 0, then we aren't rotating, just zooming */ \
+ if (incxy == 0 && incyx == 0) \
+ { \
+ /* zoom-only, non-wraparound case */ \
+ if (!wraparound) \
+ { \
+ /* iterate over pixels in Y */ \
+ for (cury = cliprect->min_y; cury <= cliprect->max_y; cury++) \
+ { \
+ PRIORITY_TYPE *priptr = PRIORITY_ADDR(priority, PRIORITY_TYPE, cury, cliprect->min_x); \
+ PIXEL_TYPE *destptr = BITMAP_ADDR(dest, PIXEL_TYPE, cury, cliprect->min_x); \
+ const PIXEL_TYPE *srcptr; \
+ INT32 srcx = startx; \
+ INT32 srcy = starty; \
+ \
+ starty += incyy; \
+ \
+ /* check srcy for the whole row at once */ \
+ if ((UINT32)srcy < srcfixheight) \
+ { \
+ srcptr = BITMAP_ADDR(src, PIXEL_TYPE, srcy >> 16, 0); \
+ \
+ /* iterate over unrolled blocks of 4 */ \
+ for (curx = 0; curx < numblocks; curx++) \
+ { \
+ if ((UINT32)srcx < srcfixwidth) \
+ PIXEL_OP(destptr[0], priptr[0], srcptr[srcx >> 16]); \
+ srcx += incxx; \
+ \
+ if ((UINT32)srcx < srcfixwidth) \
+ PIXEL_OP(destptr[1], priptr[1], srcptr[srcx >> 16]); \
+ srcx += incxx; \
+ \
+ if ((UINT32)srcx < srcfixwidth) \
+ PIXEL_OP(destptr[2], priptr[2], srcptr[srcx >> 16]); \
+ srcx += incxx; \
+ \
+ if ((UINT32)srcx < srcfixwidth) \
+ PIXEL_OP(destptr[3], priptr[3], srcptr[srcx >> 16]); \
+ srcx += incxx; \
+ \
+ destptr += 4; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 4); \
+ } \
+ \
+ /* iterate over leftover pixels */ \
+ for (curx = 0; curx < leftovers; curx++) \
+ { \
+ if ((UINT32)srcx < srcfixwidth) \
+ PIXEL_OP(destptr[0], priptr[0], srcptr[srcx >> 16]); \
+ srcx += incxx; \
+ destptr++; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 1); \
+ } \
+ } \
+ } \
+ } \
+ \
+ /* zoom-only, wraparound case */ \
+ else \
+ { \
+ /* convert srcfixwidth/height into a mask and apply */ \
+ srcfixwidth--; \
+ srcfixheight--; \
+ startx &= srcfixwidth; \
+ starty &= srcfixheight; \
+ \
+ /* iterate over pixels in Y */ \
+ for (cury = cliprect->min_y; cury <= cliprect->max_y; cury++) \
+ { \
+ PRIORITY_TYPE *priptr = PRIORITY_ADDR(priority, PRIORITY_TYPE, cury, cliprect->min_x); \
+ PIXEL_TYPE *destptr = BITMAP_ADDR(dest, PIXEL_TYPE, cury, cliprect->min_x); \
+ const PIXEL_TYPE *srcptr = BITMAP_ADDR(src, PIXEL_TYPE, starty >> 16, 0); \
+ INT32 srcx = startx; \
+ \
+ starty = (starty + incyy) & srcfixheight; \
+ \
+ /* iterate over unrolled blocks of 4 */ \
+ for (curx = 0; curx < numblocks; curx++) \
+ { \
+ PIXEL_OP(destptr[0], priptr[0], srcptr[srcx >> 16]); \
+ srcx = (srcx + incxx) & srcfixwidth; \
+ \
+ PIXEL_OP(destptr[1], priptr[1], srcptr[srcx >> 16]); \
+ srcx = (srcx + incxx) & srcfixwidth; \
+ \
+ PIXEL_OP(destptr[2], priptr[2], srcptr[srcx >> 16]); \
+ srcx = (srcx + incxx) & srcfixwidth; \
+ \
+ PIXEL_OP(destptr[3], priptr[3], srcptr[srcx >> 16]); \
+ srcx = (srcx + incxx) & srcfixwidth; \
+ \
+ destptr += 4; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 4); \
+ } \
+ \
+ /* iterate over leftover pixels */ \
+ for (curx = 0; curx < leftovers; curx++) \
+ { \
+ PIXEL_OP(destptr[0], priptr[0], srcptr[srcx >> 16]); \
+ srcx = (srcx + incxx) & srcfixwidth; \
+ destptr++; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 1); \
+ } \
+ } \
+ } \
+ } \
+ \
+ /* full rotation case */ \
+ else \
+ { \
+ /* full rotation, non-wraparound case */ \
+ if (!wraparound) \
+ { \
+ /* iterate over pixels in Y */ \
+ for (cury = cliprect->min_y; cury <= cliprect->max_y; cury++) \
+ { \
+ PRIORITY_TYPE *priptr = PRIORITY_ADDR(priority, PRIORITY_TYPE, cury, cliprect->min_x); \
+ PIXEL_TYPE *destptr = BITMAP_ADDR(dest, PIXEL_TYPE, cury, cliprect->min_x); \
+ const PIXEL_TYPE *srcptr; \
+ INT32 srcx = startx; \
+ INT32 srcy = starty; \
+ \
+ startx += incyx; \
+ starty += incyy; \
+ \
+ /* iterate over unrolled blocks of 4 */ \
+ for (curx = 0; curx < numblocks; curx++) \
+ { \
+ if ((UINT32)srcx < srcfixwidth && (UINT32)srcy < srcfixheight) \
+ { \
+ srcptr = BITMAP_ADDR(src, PIXEL_TYPE, srcy >> 16, srcx >> 16); \
+ PIXEL_OP(destptr[0], priptr[0], srcptr[0]); \
+ } \
+ srcx += incxx; \
+ srcy += incxy; \
+ \
+ if ((UINT32)srcx < srcfixwidth && (UINT32)srcy < srcfixheight) \
+ { \
+ srcptr = BITMAP_ADDR(src, PIXEL_TYPE, srcy >> 16, srcx >> 16); \
+ PIXEL_OP(destptr[1], priptr[1], srcptr[0]); \
+ } \
+ srcx += incxx; \
+ srcy += incxy; \
+ \
+ if ((UINT32)srcx < srcfixwidth && (UINT32)srcy < srcfixheight) \
+ { \
+ srcptr = BITMAP_ADDR(src, PIXEL_TYPE, srcy >> 16, srcx >> 16); \
+ PIXEL_OP(destptr[2], priptr[2], srcptr[0]); \
+ } \
+ srcx += incxx; \
+ srcy += incxy; \
+ \
+ if ((UINT32)srcx < srcfixwidth && (UINT32)srcy < srcfixheight) \
+ { \
+ srcptr = BITMAP_ADDR(src, PIXEL_TYPE, srcy >> 16, srcx >> 16); \
+ PIXEL_OP(destptr[3], priptr[3], srcptr[0]); \
+ } \
+ srcx += incxx; \
+ srcy += incxy; \
+ \
+ destptr += 4; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 4); \
+ } \
+ \
+ /* iterate over leftover pixels */ \
+ for (curx = 0; curx < leftovers; curx++) \
+ { \
+ if ((UINT32)srcx < srcfixwidth && (UINT32)srcy < srcfixheight) \
+ { \
+ srcptr = BITMAP_ADDR(src, PIXEL_TYPE, srcy >> 16, srcx >> 16); \
+ PIXEL_OP(destptr[0], priptr[0], srcptr[0]); \
+ } \
+ srcx += incxx; \
+ srcy += incxy; \
+ destptr++; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 1); \
+ } \
+ } \
+ } \
+ \
+ /* zoom-only, wraparound case */ \
+ else \
+ { \
+ /* convert srcfixwidth/height into a mask and apply */ \
+ srcfixwidth--; \
+ srcfixheight--; \
+ startx &= srcfixwidth; \
+ starty &= srcfixheight; \
+ \
+ /* iterate over pixels in Y */ \
+ for (cury = cliprect->min_y; cury <= cliprect->max_y; cury++) \
+ { \
+ PRIORITY_TYPE *priptr = PRIORITY_ADDR(priority, PRIORITY_TYPE, cury, cliprect->min_x); \
+ PIXEL_TYPE *destptr = BITMAP_ADDR(dest, PIXEL_TYPE, cury, cliprect->min_x); \
+ const PIXEL_TYPE *srcptr; \
+ INT32 srcx = startx; \
+ INT32 srcy = starty; \
+ \
+ startx = (startx + incyx) & srcfixwidth; \
+ starty = (starty + incyy) & srcfixheight; \
+ \
+ /* iterate over unrolled blocks of 4 */ \
+ for (curx = 0; curx < numblocks; curx++) \
+ { \
+ srcptr = BITMAP_ADDR(src, PIXEL_TYPE, srcy >> 16, srcx >> 16); \
+ PIXEL_OP(destptr[0], priptr[0], srcptr[0]); \
+ srcx = (srcx + incxx) & srcfixwidth; \
+ srcy = (srcy + incxy) & srcfixheight; \
+ \
+ srcptr = BITMAP_ADDR(src, PIXEL_TYPE, srcy >> 16, srcx >> 16); \
+ PIXEL_OP(destptr[1], priptr[1], srcptr[0]); \
+ srcx = (srcx + incxx) & srcfixwidth; \
+ srcy = (srcy + incxy) & srcfixheight; \
+ \
+ srcptr = BITMAP_ADDR(src, PIXEL_TYPE, srcy >> 16, srcx >> 16); \
+ PIXEL_OP(destptr[2], priptr[2], srcptr[0]); \
+ srcx = (srcx + incxx) & srcfixwidth; \
+ srcy = (srcy + incxy) & srcfixheight; \
+ \
+ srcptr = BITMAP_ADDR(src, PIXEL_TYPE, srcy >> 16, srcx >> 16); \
+ PIXEL_OP(destptr[3], priptr[3], srcptr[0]); \
+ srcx = (srcx + incxx) & srcfixwidth; \
+ srcy = (srcy + incxy) & srcfixheight; \
+ \
+ destptr += 4; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 4); \
+ } \
+ \
+ /* iterate over leftover pixels */ \
+ for (curx = 0; curx < leftovers; curx++) \
+ { \
+ srcptr = BITMAP_ADDR(src, PIXEL_TYPE, srcy >> 16, srcx >> 16); \
+ PIXEL_OP(destptr[0], priptr[0], srcptr[0]); \
+ srcx = (srcx + incxx) & srcfixwidth; \
+ srcy = (srcy + incxy) & srcfixheight; \
+ destptr++; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 1); \
+ } \
+ } \
+ } \
+ } \
+ g_profiler.stop(); \
+} while (0)
+
+
+
+/***************************************************************************
+ BASIC DRAWSCANLINE CORE
+***************************************************************************/
+
+/*
+ Assumed input parameters or local variables:
+
+ bitmap_t *bitmap - the bitmap to copy to
+ INT32 destx - the X coordinate to copy to
+ INT32 desty - the Y coordinate to copy to
+ INT32 length - the total number of pixels to copy
+ const UINTx *srcptr - pointer to memory containing the source pixels
+ bitmap_t *priority - the priority bitmap (even if PRIORITY_TYPE is NO_PRIORITY, at least needs a dummy)
+*/
+
+#define DRAWSCANLINE_CORE(PIXEL_TYPE, PIXEL_OP, PRIORITY_TYPE) \
+do { \
+ assert(bitmap != NULL); \
+ assert(destx >= 0); \
+ assert(destx + length <= bitmap->width); \
+ assert(desty >= 0); \
+ assert(desty < bitmap->height); \
+ assert(srcptr != NULL); \
+ assert(!PRIORITY_VALID(PRIORITY_TYPE) || priority != NULL); \
+ \
+ { \
+ PRIORITY_TYPE *priptr = PRIORITY_ADDR(priority, PRIORITY_TYPE, desty, destx); \
+ PIXEL_TYPE *destptr = BITMAP_ADDR(bitmap, PIXEL_TYPE, desty, destx); \
+ \
+ /* iterate over unrolled blocks of 4 */ \
+ while (length >= 4) \
+ { \
+ PIXEL_OP(destptr[0], priptr[0], srcptr[0]); \
+ PIXEL_OP(destptr[1], priptr[1], srcptr[1]); \
+ PIXEL_OP(destptr[2], priptr[2], srcptr[2]); \
+ PIXEL_OP(destptr[3], priptr[3], srcptr[3]); \
+ \
+ length -= 4; \
+ srcptr += 4; \
+ destptr += 4; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 4); \
+ } \
+ \
+ /* iterate over leftover pixels */ \
+ while (length-- > 0) \
+ { \
+ PIXEL_OP(destptr[0], priptr[0], srcptr[0]); \
+ srcptr++; \
+ destptr++; \
+ PRIORITY_ADVANCE(PRIORITY_TYPE, priptr, 1); \
+ } \
+ } \
+} while (0)
+
+
+
+/***************************************************************************
+ BASIC EXTRACTSCANLINE CORE
+***************************************************************************/
+
+/*
+ Assumed input parameters:
+
+ bitmap_t *bitmap - the bitmap to extract from
+ INT32 srcx - the X coordinate to begin extraction
+ INT32 srcy - the Y coordinate to begin extraction
+ INT32 length - the total number of pixels to extract
+ UINTx *destptr - pointer to memory to receive the extracted pixels
+*/
+
+#define EXTRACTSCANLINE_CORE(PIXEL_TYPE) \
+do { \
+ assert(bitmap != NULL); \
+ assert(srcx >= 0); \
+ assert(srcx + length <= bitmap->width); \
+ assert(srcy >= 0); \
+ assert(srcy < bitmap->height); \
+ assert(destptr != NULL); \
+ \
+ { \
+ const PIXEL_TYPE *srcptr = BITMAP_ADDR(bitmap, PIXEL_TYPE, srcy, srcx); \
+ \
+ /* iterate over unrolled blocks of 4 */ \
+ while (length >= 4) \
+ { \
+ destptr[0] = srcptr[0]; \
+ destptr[1] = srcptr[1]; \
+ destptr[2] = srcptr[2]; \
+ destptr[3] = srcptr[3]; \
+ length -= 4; \
+ srcptr += 4; \
+ destptr += 4; \
+ } \
+ \
+ /* iterate over leftover pixels */ \
+ while (length > 0) \
+ { \
+ destptr[0] = srcptr[0]; \
+ length--; \
+ srcptr++; \
+ destptr++; \
+ } \
+ } \
+} while (0)
+
+
+#endif /* __DRAWGFXM_H__ */
diff --git a/trunk/src/emu/driver.c b/trunk/src/emu/driver.c
new file mode 100644
index 00000000000..9f3ef905a1f
--- /dev/null
+++ b/trunk/src/emu/driver.c
@@ -0,0 +1,430 @@
+/***************************************************************************
+
+ driver.c
+
+ Driver enumeration helpers.
+
+****************************************************************************
+
+ 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 <ctype.h>
+
+
+
+//**************************************************************************
+// DRIVER LIST
+//**************************************************************************
+
+//-------------------------------------------------
+// driver_list - constructor
+//-------------------------------------------------
+
+driver_list::driver_list()
+{
+}
+
+
+//-------------------------------------------------
+// find - find a driver by name
+//-------------------------------------------------
+
+int driver_list::find(const char *name)
+{
+ // if no name, bail
+ if (name == NULL)
+ return -1;
+
+ // create a dummy item for comparison purposes
+ game_driver driver;
+ driver.name = name;
+ game_driver *driverptr = &driver;
+
+ // binary search to find it
+ const game_driver **result = reinterpret_cast<const game_driver **>(bsearch(&driverptr, s_drivers_sorted, s_driver_count, sizeof(*s_drivers_sorted), driver_sort_callback));
+ return (result == NULL) ? -1 : result - s_drivers_sorted;
+}
+
+
+//-------------------------------------------------
+// matches - true if we match, taking into
+// account wildcards in the wildstring
+//-------------------------------------------------
+
+bool driver_list::matches(const char *wildstring, const char *string)
+{
+ // can only match internal drivers if the wildstring starts with an underscore
+ if (string[0] == '_' && (wildstring == NULL || wildstring[0] != '_'))
+ return false;
+
+ // match everything else normally
+ return (wildstring == NULL || mame_strwildcmp(wildstring, string) == 0);
+}
+
+
+//-------------------------------------------------
+// driver_sort_callback - compare two items in
+// an array of game_driver pointers
+//-------------------------------------------------
+
+int driver_list::driver_sort_callback(const void *elem1, const void *elem2)
+{
+ const game_driver * const *item1 = reinterpret_cast<const game_driver * const *>(elem1);
+ const game_driver * const *item2 = reinterpret_cast<const game_driver * const *>(elem2);
+ return mame_stricmp((*item1)->name, (*item2)->name);
+}
+
+
+//-------------------------------------------------
+// penalty_compare - compare two strings for
+// closeness and assign a score.
+//-------------------------------------------------
+
+int driver_list::penalty_compare(const char *source, const char *target)
+{
+ int gaps = 1;
+ bool last = true;
+
+ // scan the strings
+ for ( ; *source && *target; target++)
+ {
+ // do a case insensitive match
+ bool match = (tolower((UINT8)*source) == tolower((UINT8)*target));
+
+ // if we matched, advance the source
+ if (match)
+ source++;
+
+ // if the match state changed, count gaps
+ if (match != last)
+ {
+ last = match;
+ if (!match)
+ gaps++;
+ }
+ }
+
+ // penalty if short string does not completely fit in
+ for ( ; *source; source++)
+ gaps++;
+
+ // if we matched perfectly, gaps == 0
+ if (gaps == 1 && *source == 0 && *target == 0)
+ gaps = 0;
+
+ return gaps;
+}
+
+
+
+//**************************************************************************
+// DRIVER ENUMERATOR
+//**************************************************************************
+
+//-------------------------------------------------
+// driver_enumerator - constructor
+//-------------------------------------------------
+
+driver_enumerator::driver_enumerator(emu_options &options)
+ : m_current(-1),
+ m_filtered_count(0),
+ m_options(options),
+ m_included(global_alloc_array(UINT8, s_driver_count)),
+ m_config(global_alloc_array_clear(machine_config *, s_driver_count))
+{
+ include_all();
+}
+
+
+driver_enumerator::driver_enumerator(emu_options &options, const char *string)
+ : m_current(-1),
+ m_filtered_count(0),
+ m_options(options),
+ m_included(global_alloc_array(UINT8, s_driver_count)),
+ m_config(global_alloc_array_clear(machine_config *, s_driver_count))
+{
+ filter(string);
+}
+
+
+driver_enumerator::driver_enumerator(emu_options &options, const game_driver &driver)
+ : m_current(-1),
+ m_filtered_count(0),
+ m_options(options),
+ m_included(global_alloc_array(UINT8, s_driver_count)),
+ m_config(global_alloc_array_clear(machine_config *, s_driver_count))
+{
+ filter(driver);
+}
+
+
+//-------------------------------------------------
+// ~driver_enumerator - destructor
+//-------------------------------------------------
+
+driver_enumerator::~driver_enumerator()
+{
+ // free any configs
+ for (int index = 0; index < s_driver_count; index++)
+ global_free(m_config[index]);
+
+ // free the arrays
+ global_free(m_included);
+ global_free(m_config);
+}
+
+
+//-------------------------------------------------
+// config - return a machine_config for the given
+// driver, allocating on demand if needed
+//-------------------------------------------------
+
+machine_config &driver_enumerator::config(int index) const
+{
+ assert(index >= 0 && index < s_driver_count);
+
+ // if we don't have it cached, add it
+ if (m_config[index] == NULL)
+ {
+ // if our cache is full, release the head entry
+ if (m_config_cache.count() == CONFIG_CACHE_COUNT)
+ {
+ config_entry *first = m_config_cache.first();
+ m_config[first->index()] = NULL;
+ m_config_cache.remove(*first);
+ }
+
+ // allocate the config and add it to the end of the list
+ machine_config *config = m_config[index] = global_alloc(machine_config(*s_drivers_sorted[index], m_options));
+ m_config_cache.append(*global_alloc(config_entry(*config, index)));
+ }
+ return *m_config[index];
+}
+
+
+//-------------------------------------------------
+// filter - filter the driver list against the
+// given string
+//-------------------------------------------------
+
+int driver_enumerator::filter(const char *filterstring)
+{
+ // reset the count
+ exclude_all();
+
+ // match name against each driver in the list
+ for (int index = 0; index < s_driver_count; index++)
+ if (matches(filterstring, s_drivers_sorted[index]->name))
+ include(index);
+
+ return m_filtered_count;
+}
+
+
+//-------------------------------------------------
+// filter - filter the driver list against the
+// given driver
+//-------------------------------------------------
+
+int driver_enumerator::filter(const game_driver &driver)
+{
+ // reset the count
+ exclude_all();
+
+ // match name against each driver in the list
+ for (int index = 0; index < s_driver_count; index++)
+ if (s_drivers_sorted[index] == &driver)
+ include(index);
+
+ return m_filtered_count;
+}
+
+
+//-------------------------------------------------
+// include_all - include all non-internal drivers
+//-------------------------------------------------
+
+void driver_enumerator::include_all()
+{
+ memset(m_included, 1, sizeof(m_included[0]) * s_driver_count); m_filtered_count = s_driver_count;
+ int empty = find("___empty");
+ assert(empty != -1);
+ m_included[empty] = 0;
+}
+
+
+//-------------------------------------------------
+// next - get the next driver matching the given
+// filter
+//-------------------------------------------------
+
+bool driver_enumerator::next()
+{
+ // always advance one
+ m_current++;
+
+ // if we have a filter, scan forward to the next match
+ while (m_current < s_driver_count)
+ {
+ if (m_included[m_current])
+ break;
+ m_current++;
+ }
+
+ // return true if we end up in range
+ return (m_current >= 0 && m_current < s_driver_count);
+}
+
+
+//-------------------------------------------------
+// next_excluded - get the next driver that is
+// not currently included in the list
+//-------------------------------------------------
+
+bool driver_enumerator::next_excluded()
+{
+ // always advance one
+ m_current++;
+
+ // if we have a filter, scan forward to the next match
+ while (m_current < s_driver_count)
+ {
+ if (!m_included[m_current])
+ break;
+ m_current++;
+ }
+
+ // return true if we end up in range
+ return (m_current >= 0 && m_current < s_driver_count);
+}
+
+
+//-------------------------------------------------
+// driver_sort_callback - compare two items in
+// an array of game_driver pointers
+//-------------------------------------------------
+
+void driver_enumerator::find_approximate_matches(const char *string, int count, int *results)
+{
+#undef rand
+
+ // if no name, pick random entries
+ if (string == NULL || string[0] == 0)
+ {
+ // seed the RNG first
+ srand(osd_ticks());
+
+ // allocate a temporary list
+ int *templist = global_alloc_array(int, m_filtered_count);
+ int arrayindex = 0;
+ for (int index = 0; index < s_driver_count; index++)
+ if (m_included[index])
+ templist[arrayindex++] = index;
+ assert(arrayindex == m_filtered_count);
+
+ // shuffle
+ for (int shufnum = 0; shufnum < 4 * s_driver_count; shufnum++)
+ {
+ int item1 = rand() % m_filtered_count;
+ int item2 = rand() % m_filtered_count;
+ int temp = templist[item1];
+ templist[item1] = templist[item2];
+ templist[item2] = temp;
+ }
+
+ // copy out the first few entries
+ for (int matchnum = 0; matchnum < count; matchnum++)
+ results[matchnum] = templist[matchnum % m_filtered_count];
+
+ global_free(templist);
+ return;
+ }
+
+ // allocate memory to track the penalty value
+ int *penalty = global_alloc_array(int, count);
+
+ // initialize everyone's states
+ for (int matchnum = 0; matchnum < count; matchnum++)
+ {
+ penalty[matchnum] = 9999;
+ results[matchnum] = -1;
+ }
+
+ // scan the entire drivers array
+ for (int index = 0; index < s_driver_count; index++)
+ if (m_included[index])
+ {
+ // skip things that can't run
+ if ((s_drivers_sorted[index]->flags & GAME_NO_STANDALONE) != 0)
+ continue;
+
+ // pick the best match between driver name and description
+ int curpenalty = penalty_compare(string, s_drivers_sorted[index]->description);
+ int tmp = penalty_compare(string, s_drivers_sorted[index]->name);
+ curpenalty = MIN(curpenalty, tmp);
+
+ // insert into the sorted table of matches
+ for (int matchnum = count - 1; matchnum >= 0; matchnum--)
+ {
+ // stop if we're worse than the current entry
+ if (curpenalty >= penalty[matchnum])
+ break;
+
+ // as long as this isn't the last entry, bump this one down
+ if (matchnum < count - 1)
+ {
+ penalty[matchnum + 1] = penalty[matchnum];
+ results[matchnum + 1] = results[matchnum];
+ }
+ results[matchnum] = index;
+ penalty[matchnum] = curpenalty;
+ }
+ }
+
+ // free our temp memory
+ global_free(penalty);
+}
+
+
+driver_enumerator::config_entry::config_entry(machine_config &config, int index)
+ : m_next(NULL),
+ m_config(&config),
+ m_index(index)
+{
+}
+
+
+driver_enumerator::config_entry::~config_entry()
+{
+ global_free(m_config);
+}
diff --git a/trunk/src/emu/driver.h b/trunk/src/emu/driver.h
new file mode 100644
index 00000000000..25db865ccb3
--- /dev/null
+++ b/trunk/src/emu/driver.h
@@ -0,0 +1,338 @@
+/***************************************************************************
+
+ driver.h
+
+ Driver enumeration helpers.
+
+****************************************************************************
+
+ 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 __DRIVER_H__
+#define __DRIVER_H__
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* maxima */
+#define MAX_DRIVER_NAME_CHARS 8
+
+
+
+/* ----- flags for game drivers ----- */
+
+#define ORIENTATION_MASK 0x00000007
+#define GAME_NOT_WORKING 0x00000008
+#define GAME_UNEMULATED_PROTECTION 0x00000010 /* game's protection not fully emulated */
+#define GAME_WRONG_COLORS 0x00000020 /* colors are totally wrong */
+#define GAME_IMPERFECT_COLORS 0x00000040 /* colors are not 100% accurate, but close */
+#define GAME_IMPERFECT_GRAPHICS 0x00000080 /* graphics are wrong/incomplete */
+#define GAME_NO_COCKTAIL 0x00000100 /* screen flip support is missing */
+#define GAME_NO_SOUND 0x00000200 /* sound is missing */
+#define GAME_IMPERFECT_SOUND 0x00000400 /* sound is known to be wrong */
+#define GAME_SUPPORTS_SAVE 0x00000800 /* game supports save states */
+#define GAME_IS_BIOS_ROOT 0x00001000 /* this driver entry is a BIOS root */
+#define GAME_NO_STANDALONE 0x00002000 /* this driver cannot stand alone */
+#define GAME_REQUIRES_ARTWORK 0x00004000 /* the driver requires external artwork for key elements of the game */
+#define GAME_UNOFFICIAL 0x00008000 /* unofficial hardware change */
+#define GAME_NO_SOUND_HW 0x00010000 /* sound hardware not available */
+#define GAME_MECHANICAL 0x00020000 /* contains mechanical parts (pinball, redemption games,...) */
+#define GAME_TYPE_ARCADE 0x00040000 /* arcade machine (coin operated machines) */
+#define GAME_TYPE_CONSOLE 0x00080000 /* console system */
+#define GAME_TYPE_COMPUTER 0x00100000 /* any kind of computer including home computers, minis, calcs,... */
+#define GAME_TYPE_OTHER 0x00200000 /* any other emulated system that doesn't fit above (ex. clock, satelite receiver,...) */
+
+/* ----- flags to return from video_update ----- */
+#define UPDATE_HAS_NOT_CHANGED 0x0001 /* the video has not changed */
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef void (*driver_init_func)(running_machine &machine);
+
+
+struct game_driver
+{
+ const char * source_file; /* set this to __FILE__ */
+ const char * parent; /* if this is a clone, the name of the parent */
+ const char * name; /* short (8-character) name of the game */
+ const char * description; /* full name of the game */
+ const char * year; /* year the game was released */
+ const char * manufacturer; /* manufacturer of the game */
+ machine_config_constructor machine_config; /* machine driver tokens */
+ ioport_constructor ipt; /* pointer to array of input port tokens */
+ void (*driver_init)(running_machine &machine); /* DRIVER_INIT callback */
+ const rom_entry * rom; /* pointer to list of ROMs for the game */
+ const char * compatible_with;
+ UINT32 flags; /* orientation and other flags; see defines below */
+ const char * default_layout; /* default internally defined layout */
+};
+
+
+// driver_list is a purely static class that wraps the global driver list
+class driver_list
+{
+ DISABLE_COPYING(driver_list);
+
+protected:
+ // construction/destruction
+ driver_list();
+
+public:
+ // getters
+ static int total() { return s_driver_count; }
+
+ // any item by index
+ static const game_driver &driver(int index) { assert(index >= 0 && index < s_driver_count); return *s_drivers_sorted[index]; }
+ static int clone(int index) { return find(driver(index).parent); }
+ static int non_bios_clone(int index) { int result = find(driver(index).parent); return (result != -1 && (driver(result).flags & GAME_IS_BIOS_ROOT) == 0) ? result : -1; }
+ static int compatible_with(int index) { return find(driver(index).compatible_with); }
+
+ // any item by driver
+ static int clone(const game_driver &driver) { int index = find(driver); assert(index != -1); return clone(index); }
+ static int non_bios_clone(const game_driver &driver) { int index = find(driver); assert(index != -1); return non_bios_clone(index); }
+ static int compatible_with(const game_driver &driver) { int index = find(driver); assert(index != -1); return compatible_with(index); }
+
+ // general helpers
+ static int find(const char *name);
+ static int find(const game_driver &driver) { return find(driver.name); }
+
+ // static helpers
+ static bool matches(const char *wildstring, const char *string);
+
+protected:
+ // internal helpers
+ static int driver_sort_callback(const void *elem1, const void *elem2);
+ static int penalty_compare(const char *source, const char *target);
+
+ // internal state
+ static int s_driver_count;
+ static const game_driver * const s_drivers_sorted[];
+};
+
+
+// driver_enumerator enables efficient iteration through the driver list
+class driver_enumerator : public driver_list
+{
+ DISABLE_COPYING(driver_enumerator);
+
+public:
+ // construction/destruction
+ driver_enumerator(emu_options &options);
+ driver_enumerator(emu_options &options, const char *filter);
+ driver_enumerator(emu_options &options, const game_driver &filter);
+ ~driver_enumerator();
+
+ // getters
+ int count() const { return m_filtered_count; }
+ int current() const { return m_current; }
+ emu_options &options() const { return m_options; }
+
+ // current item
+ const game_driver &driver() const { return driver_list::driver(m_current); }
+ machine_config &config() const { return config(m_current); }
+ int clone() { return driver_list::clone(m_current); }
+ int non_bios_clone() { return driver_list::non_bios_clone(m_current); }
+ int compatible_with() { return driver_list::compatible_with(m_current); }
+ void include() { include(m_current); }
+ void exclude() { exclude(m_current); }
+
+ // any item by index
+ bool included(int index) const { assert(index >= 0 && index < s_driver_count); return m_included[index]; }
+ bool excluded(int index) const { assert(index >= 0 && index < s_driver_count); return !m_included[index]; }
+ machine_config &config(int index) const;
+ void include(int index) { assert(index >= 0 && index < s_driver_count); if (!m_included[index]) { m_included[index] = true; m_filtered_count++; } }
+ void exclude(int index) { assert(index >= 0 && index < s_driver_count); if (m_included[index]) { m_included[index] = false; m_filtered_count--; } }
+ using driver_list::driver;
+ using driver_list::clone;
+ using driver_list::non_bios_clone;
+ using driver_list::compatible_with;
+
+ // filtering/iterating
+ int filter(const char *string = NULL);
+ int filter(const game_driver &driver);
+ void include_all();
+ void exclude_all() { memset(m_included, 0, sizeof(m_included[0]) * s_driver_count); m_filtered_count = 0; }
+ void reset() { m_current = -1; }
+ bool next();
+ bool next_excluded();
+
+ // general helpers
+ void set_current(int index) { assert(index >= -1 && index <= s_driver_count); m_current = index; }
+ void find_approximate_matches(const char *string, int count, int *results);
+
+private:
+ // entry in the config cache
+ struct config_entry
+ {
+ friend class simple_list<config_entry>;
+
+ public:
+ // construction/destruction
+ config_entry(machine_config &config, int index);
+ ~config_entry();
+
+ // getters
+ config_entry *next() const { return m_next; }
+ int index() const { return m_index; }
+ machine_config *config() const { return m_config; }
+
+ private:
+ // internal state
+ config_entry * m_next;
+ machine_config * m_config;
+ int m_index;
+ };
+
+ static const int CONFIG_CACHE_COUNT = 100;
+
+ // internal state
+ int m_current;
+ int m_filtered_count;
+ emu_options & m_options;
+ UINT8 * m_included;
+ machine_config ** m_config;
+ mutable simple_list<config_entry> m_config_cache;
+};
+
+
+
+/***************************************************************************
+ MACROS FOR BUILDING GAME DRIVERS
+***************************************************************************/
+
+
+#define DRIVER_INIT_NAME(name) driver_init_##name
+#define DRIVER_INIT(name) void DRIVER_INIT_NAME(name)(running_machine &machine)
+#define DRIVER_INIT_CALL(name) DRIVER_INIT_NAME(name)(machine)
+
+#define driver_init_0 NULL
+
+
+#define GAME_NAME(name) driver_##name
+#define GAME_EXTERN(name) extern const game_driver GAME_NAME(name)
+
+#define GAME(YEAR,NAME,PARENT,MACHINE,INPUT,INIT,MONITOR,COMPANY,FULLNAME,FLAGS) \
+ GAMEL(YEAR,NAME,PARENT,MACHINE,INPUT,INIT,MONITOR,COMPANY,FULLNAME,FLAGS,((const char *)0))
+
+#define GAMEL(YEAR,NAME,PARENT,MACHINE,INPUT,INIT,MONITOR,COMPANY,FULLNAME,FLAGS,LAYOUT) \
+extern const game_driver GAME_NAME(NAME) = \
+{ \
+ __FILE__, \
+ #PARENT, \
+ #NAME, \
+ FULLNAME, \
+ #YEAR, \
+ COMPANY, \
+ MACHINE_CONFIG_NAME(MACHINE), \
+ INPUT_PORTS_NAME(INPUT), \
+ DRIVER_INIT_NAME(INIT), \
+ ROM_NAME(NAME), \
+ NULL, \
+ (MONITOR)|(FLAGS)|GAME_TYPE_ARCADE, \
+ &LAYOUT[0] \
+};
+
+#define CONS(YEAR,NAME,PARENT,COMPAT,MACHINE,INPUT,INIT,COMPANY,FULLNAME,FLAGS) \
+extern const game_driver GAME_NAME(NAME) = \
+{ \
+ __FILE__, \
+ #PARENT, \
+ #NAME, \
+ FULLNAME, \
+ #YEAR, \
+ COMPANY, \
+ MACHINE_CONFIG_NAME(MACHINE), \
+ INPUT_PORTS_NAME(INPUT), \
+ DRIVER_INIT_NAME(INIT), \
+ ROM_NAME(NAME), \
+ #COMPAT, \
+ ROT0|(FLAGS)|GAME_TYPE_CONSOLE, \
+ NULL \
+};
+
+#define COMP(YEAR,NAME,PARENT,COMPAT,MACHINE,INPUT,INIT,COMPANY,FULLNAME,FLAGS) \
+extern const game_driver GAME_NAME(NAME) = \
+{ \
+ __FILE__, \
+ #PARENT, \
+ #NAME, \
+ FULLNAME, \
+ #YEAR, \
+ COMPANY, \
+ MACHINE_CONFIG_NAME(MACHINE), \
+ INPUT_PORTS_NAME(INPUT), \
+ DRIVER_INIT_NAME(INIT), \
+ ROM_NAME(NAME), \
+ #COMPAT, \
+ ROT0|(FLAGS)|GAME_TYPE_COMPUTER, \
+ NULL \
+};
+
+#define SYST(YEAR,NAME,PARENT,COMPAT,MACHINE,INPUT,INIT,COMPANY,FULLNAME,FLAGS) \
+extern const game_driver GAME_NAME(NAME) = \
+{ \
+ __FILE__, \
+ #PARENT, \
+ #NAME, \
+ FULLNAME, \
+ #YEAR, \
+ COMPANY, \
+ MACHINE_CONFIG_NAME(MACHINE), \
+ INPUT_PORTS_NAME(INPUT), \
+ DRIVER_INIT_NAME(INIT), \
+ ROM_NAME(NAME), \
+ #COMPAT, \
+ ROT0|(FLAGS)|GAME_TYPE_OTHER, \
+ NULL \
+};
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+GAME_EXTERN(___empty);
+
+
+
+#endif
diff --git a/trunk/src/emu/drivers/empty.c b/trunk/src/emu/drivers/empty.c
new file mode 100644
index 00000000000..d4ce7079f31
--- /dev/null
+++ b/trunk/src/emu/drivers/empty.c
@@ -0,0 +1,69 @@
+/*************************************************************************
+
+ empty.c
+
+ Empty driver.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**************************************************************************/
+
+#include "emu.h"
+#include "render.h"
+#include "uimenu.h"
+
+
+/*************************************
+ *
+ * Machine "start"
+ *
+ *************************************/
+
+static MACHINE_START( ___empty )
+{
+ /* force the UI to show the game select screen */
+ ui_menu_force_game_select(machine, &machine.render().ui_container());
+}
+
+
+
+/*************************************
+ *
+ * Machine drivers
+ *
+ *************************************/
+
+static MACHINE_CONFIG_START( ___empty, driver_device )
+
+ MCFG_MACHINE_START(___empty)
+
+ /* video hardware */
+ MCFG_SCREEN_ADD("screen", RASTER)
+ MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
+ MCFG_SCREEN_SIZE(640,480)
+ MCFG_SCREEN_VISIBLE_AREA(0,639, 0,479)
+ MCFG_SCREEN_REFRESH_RATE(30)
+MACHINE_CONFIG_END
+
+
+
+/*************************************
+ *
+ * ROM definitions
+ *
+ *************************************/
+
+ROM_START( ___empty )
+ ROM_REGION( 0x10, "user1", ROMREGION_ERASEFF )
+ROM_END
+
+
+
+/*************************************
+ *
+ * Game drivers
+ *
+ *************************************/
+
+GAME( 2007, ___empty, 0, ___empty, 0, 0, ROT0, "MAME", "No Driver Loaded", GAME_NO_SOUND )
diff --git a/trunk/src/emu/drivers/emudummy.c b/trunk/src/emu/drivers/emudummy.c
new file mode 100644
index 00000000000..af5f26f9743
--- /dev/null
+++ b/trunk/src/emu/drivers/emudummy.c
@@ -0,0 +1,67 @@
+/***************************************************************************
+
+ emudummy.c
+
+ Dummy driver file that references CPU devices which are in turn
+ referenced by devices in libemu.a.
+
+ The reason we need this is due to link ordering issues with gcc
+ if the actual drivers being linked don't reference these CPU
+ devices. Since we link libcpu first, if libemu needs stuff from
+ libcpu that wasn't previously referenced, it will fail the link.
+
+****************************************************************************
+
+ 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 "cpu/mcs48/mcs48.h"
+#include "cpu/z80/z80.h"
+
+
+MACHINE_CONFIG_START( __dummy, driver_device )
+ MCFG_CPU_ADD("dummy1", I8049, 1000000)
+ MCFG_CPU_ADD("dummy2", I8748, 1000000)
+ MCFG_CPU_ADD("dummy3", Z80, 1000000)
+MACHINE_CONFIG_END
+
+
+ROM_START( __dummy )
+ ROM_REGION( 0x1000, "dummy1", ROMREGION_ERASEFF )
+ ROM_REGION( 0x1000, "dummy2", ROMREGION_ERASEFF )
+ ROM_REGION( 0x1000, "dummy3", ROMREGION_ERASEFF )
+ROM_END
+
+
+GAME( 1900, __dummy, 0, __dummy, 0, 0, ROT0, "(none)", "Dummy", GAME_NO_SOUND )
+
+
diff --git a/trunk/src/emu/drivers/xtal.h b/trunk/src/emu/drivers/xtal.h
new file mode 100644
index 00000000000..6c266818715
--- /dev/null
+++ b/trunk/src/emu/drivers/xtal.h
@@ -0,0 +1,573 @@
+/*************************************************************************
+
+ xtal.h
+
+ Documentation and consistent naming for known existing crystals.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************
+
+ PCB Crystal Reference
+ ----------------------
+ _____ ________
+ |16 | |o |
+ |MHZ| |16.0MHZ |
+ |___| |________|
+ | |
+
+ There is a finite list of _manufactured_ crystals. This file aims
+ to document all of the known speeds that crystals were available in.
+ Feel free to add to the list if you find another speed crystal on
+ a PCB, but please DON'T GUESS!
+
+ Remember that some very high frequencies (typically above 100MHz) are
+ generated by a frequency multiplying IC from a lower frequency
+ crystal.
+
+ This is intended as a reference of existing parts to prevent incorrect
+ clock speed measurements with digital frequency counters being used
+ in drivers. When measuring clocks, remember that most parts have a
+ tolerance so be sure to reference existing parts only and not just
+ accept direct readings as 100% true.
+
+ MAME doesn't yet support fractions in crystal frequencies. For example,
+ XTAL_3_579545MHz should actually be 3579545.454545...Hz (39375000/11).
+ This is no problem though: see above note about tolerance.
+
+ (Thanks to Guru for starting this documentation.)
+
+**************************************************************************/
+
+enum
+{
+/*
+ Name = Frequency Examples
+ ------------------ ------------ ------------------------------------------------------------ */
+ XTAL_32_768kHz = 32768, /* 32.768kHz, used to drive RTC chips */
+ XTAL_1MHz = 1000000, /* Used to drive OKI M6295 chips */
+ XTAL_1_75MHz = 1750000, /* RCA CDP1861 */
+ XTAL_1_8432MHz = 1843200, /* Bondwell 12/14 */
+ XTAL_2MHz = 2000000,
+ XTAL_2_01216MHz = 2012160, /* Cidelsa Draco sound board */
+ XTAL_2_4576MHz = 2457600, /* Atari ST MFP */
+ XTAL_3MHz = 3000000, /* Probably only used to drive 68705 or similar MCUs on 80's Taito PCBs */
+ XTAL_3_12MHz = 3120000, /* SP0250 clock on Gottlieb games */
+ XTAL_3_52128MHz = 3521280, /* RCA COSMAC VIP */
+ XTAL_3_579545MHz = 3579545, /* NTSC color subcarrier, extremely common, used on 100's of PCBs */
+ XTAL_3_6864MHz = 3686400, /* CPS3 */
+ XTAL_4MHz = 4000000,
+ XTAL_4_028MHz = 4028000, /* Sony SMC-777 */
+ XTAL_4_096MHz = 4096000, /* Used to drive OKI M9810 chips */
+ XTAL_4_224MHz = 4224000, /* Used to drive OKI M6295 chips, usually with /4 divider */
+ XTAL_4_41MHz = 4410000, /* Pioneer PR-8210 ldplayer */
+ XTAL_4_43361MHz = 4433610, /* Cidelsa Draco */
+ XTAL_4_433619MHz = 4433619, /* PAL color subcarrier */
+ XTAL_4_608MHz = 4608000, /* Luxor ABC-77 keyboard */
+ XTAL_4_9152MHz = 4915200,
+ XTAL_5MHz = 5000000, /* Mutant Night */
+ XTAL_5_0688MHz = 5068800, /* Xerox 820, DEC VK100 */
+ XTAL_5_626MHz = 5626000, /* RCA CDP1869 PAL dot clock */
+ XTAL_5_67MHz = 5670000, /* RCA CDP1869 NTSC dot clock */
+ XTAL_5_7143MHz = 5714300, /* Cidelsa Destroyer */
+ XTAL_5_9904MHz = 5990400, /* Luxor ABC 800 keyboard */
+ XTAL_6MHz = 6000000, /* American Poker II */
+ XTAL_6_5MHz = 6500000, /* Jupiter Ace */
+ XTAL_6_144MHz = 6144000, /* Used on Alpha Denshi early 80's games sound board */
+ XTAL_7MHz = 7000000, /* Jaleco Mega System PCBs */
+ XTAL_7_15909MHz = 7159090, /* Blood Bros */
+ XTAL_7_3728MHz = 7372800,
+ XTAL_7_8643MHz = 7864300, /* Used on InterFlip games as video clock */
+ XTAL_8MHz = 8000000, /* Extremely common, used on 100's of PCBs */
+ XTAL_8_2MHz = 8200000, /* Universal Mr. Do - Model 8021 PCB */
+ XTAL_8_4672MHz = 8467200, /* Subsino's Ying Hua Lian */
+ XTAL_8_664MHz = 8664000, /* Touchmaster */
+ XTAL_8_867236MHz = 8867236, /* RCA CDP1869 PAL color clock */
+ XTAL_8_867238MHz = 8867238, /* ETI-660 */
+ XTAL_9_216MHz = 9216000, /* Conitec PROF-180X */
+ XTAL_8_945MHz = 8945000, /* Hit Me */
+ XTAL_9_828MHz = 9828000, /* Universal PCBs */
+ XTAL_9_8304MHz = 9830400, /* Epson PX-8 */
+ XTAL_9_987MHz = 9987000, /* Crazy Balloon */
+ XTAL_10MHz = 10000000,
+ XTAL_10_245MHz = 10245000, /* PES Speech box */
+ XTAL_10_595MHz = 10595000, /* Mad Alien */
+ XTAL_10_6875MHz = 10687500, /* BBC Bridge Companion */
+ XTAL_10_69425MHz = 10694250, /* Xerox 820 */
+ XTAL_10_730MHz = 10730000, /* Ruleta RE-900 VDP Clock */
+ XTAL_10_733MHz = 10733000, /* The Fairyland Story */
+ XTAL_10_738635MHz = 10738635, /* TMS9918 family */
+ XTAL_10_816MHz = 10816000, /* Universal 1979-1980 (Cosmic Alien, etc) */
+ XTAL_11MHz = 11000000, /* Mario I8039 sound */
+ XTAL_11_0592MHz = 11059200, /* Lethal Justice, Ruleta RE-900 */
+ XTAL_11_2MHz = 11200000, /* New York, New York */
+ XTAL_11_289MHz = 11289000, /* Vanguard */
+ XTAL_11_6688MHz = 11668800, /* Gameplan pixel clock */
+ XTAL_12MHz = 12000000, /* Extremely common, used on 100's of PCBs */
+ XTAL_12_096MHz = 12096000, /* Some early 80's Atari games */
+ XTAL_12_288MHz = 12288000, /* Sega Model 3 digital audio board */
+ XTAL_12_4725MHz = 12472500, /* Bonanza's Mini Boy 7 */
+ XTAL_12_48MHz = 12480000, /* TRS-80 Model II */
+ XTAL_12_5MHz = 12500000, /* Red Alert audio board */
+ XTAL_12_9792MHz = 12979200, /* Exidy 440 */
+ XTAL_13_3MHz = 13300000, /* BMC bowling */
+ XTAL_13_33056MHz = 13330560, /* Taito L */
+ XTAL_13_4MHz = 13400000, /* TNK3, Ikari Warriors h/w */
+ XTAL_13_4952MHz = 13495200, /* Used on Shadow Force pcb and maybe other Technos pcbs? */
+ XTAL_14MHz = 14000000,
+ XTAL_14_112MHz = 14112000, /* Timex/Sinclair TS2068 */
+ XTAL_14_31818MHz = 14318181, /* Extremely common, used on 100's of PCBs */
+ XTAL_14_705882MHz = 14705882, /* Aleck64 */
+ XTAL_14_7456MHz = 14745600, /* Namco System 12 & System Super 22/23 for H8/3002 CPU */
+ XTAL_15MHz = 15000000, /* Sinclair QL */
+ XTAL_15_36MHz = 15360000, /* Visual 1050 */
+ XTAL_15_468MHz = 15468000, /* Bank Panic h/w, Sega G80 */
+ XTAL_16MHz = 16000000, /* Extremely common, used on 100's of PCBs */
+ XTAL_16_9344MHz = 16934400, /* Usually used to drive 90's Yamaha OPL/FM chips */
+ XTAL_17_36MHz = 17360000, /* OMTI Series 10 SCSI controller */
+ XTAL_17_73447MHz = 17734470, /* 4 times the PAL subcarrier */
+ XTAL_18MHz = 18000000, /* S.A.R, Ikari Warriors 3 */
+ XTAL_18_432MHz = 18432000, /* Extremely common, used on 100's of PCBs */
+ XTAL_18_720MHz = 18720000, /* Nokia MikroMikko 1 */
+ XTAL_19_6MHz = 19600000, /* Universal Mr. Do - Model 8021 PCB */
+ XTAL_19_6608MHz = 19660800, /* Euro League (bootleg), labeled as "UKI 19.6608 20PF" */
+ XTAL_19_923MHz = 19923000, /* Cinematronics vectors */
+ XTAL_19_968MHz = 19968000, /* Used mostly by some Taito games */
+ XTAL_20MHz = 20000000,
+ XTAL_20_16MHz = 20160000, /* Nintendo 8080 */
+ XTAL_20_079MHz = 20790000, /* Blockade-hardware Gremlin games */
+ XTAL_21MHz = 21000000, /* Lock-On pixel clock */
+ XTAL_21_3MHz = 21300000,
+ XTAL_21_4772MHz = 21477272, /* BMC bowling, some Data East 90's games, Vtech Socrates; NTSC color subcarrier * 6 */
+ XTAL_22MHz = 22000000,
+ XTAL_22_1184MHz = 22118400,
+ XTAL_23_9616MHz = 23961600, /* Osborne 4 (Vixen) */
+ XTAL_24MHz = 24000000, /* Mario, 80's Data East games, 80's Konami games */
+ XTAL_24_576MHz = 24576000, /* Pole Position h/w, Model 3 CPU board */
+ XTAL_24_8832MHz = 24883200, /* DEC VT100 */
+ XTAL_25MHz = 25000000, /* Namco System 22, Taito GNET, Dogyuun h/w */
+ XTAL_25_1748MHz = 25174800, /* Sega S16A, S16B */
+ XTAL_25_447MHz = 25447000, /* Namco EVA3A (Funcube2) */
+ XTAL_25_590906MHz = 25590906, /* Atari Jaguar NTSC */
+ XTAL_25_593900MHz = 25593900, /* Atari Jaguar PAL */
+ XTAL_25_601712MHz = 25601712, /* Astro Corp.'s Show Hand */
+ XTAL_26_66666MHz = 26666666, /* Irem M92 but most use 27MHz */
+ XTAL_26_686MHz = 26686000, /* Typically used on 90's Taito PCBs to drive the custom chips */
+ XTAL_27MHz = 27000000, /* Some Banpresto games macrossp, Irem M92 and 90's Toaplan games */
+ XTAL_27_164MHz = 27164000, /* Typically used on 90's Taito PCBs to drive the custom chips */
+ XTAL_27_2109MHz = 27210900, /* LA Girl */
+ XTAL_28MHz = 28000000,
+ XTAL_28_37516MHz = 28375160, /* Amiga PAL systems */
+ XTAL_28_48MHz = 28480000, /* Chromatics CGC-7900 */
+ XTAL_28_63636MHz = 28636363, /* Later Leland games and Atari GT, Amiga NTSC , Raiden2 h/w */
+ XTAL_30MHz = 30000000, /* Impera Magic Card */
+ XTAL_30_4761MHz = 30476100, /* Taito JC */
+ XTAL_32MHz = 32000000,
+ XTAL_32_22MHz = 32220000, /* Typically used on 90's Data East PCBs */
+ XTAL_32_5304MHz = 32530400, /* Seta 2 */
+ XTAL_33MHz = 33000000, /* Sega Model 3 video board */
+ XTAL_33_333MHz = 33333000, /* Sega Model 3 CPU board, Vegas */
+ XTAL_33_8688MHz = 33868800, /* Usually used to drive 90's Yamaha OPL/FM chips with /2 divider */
+ XTAL_36MHz = 36000000, /* Sega Model 1 video board */
+ XTAL_38_76922MHz = 38769220, /* Namco System 21 video board */
+ XTAL_40MHz = 40000000,
+ XTAL_42_9545MHz = 42954545, /* CPS3 */
+ XTAL_44_1MHz = 44100000, /* Subsino's Bishou Jan */
+ XTAL_45MHz = 45000000, /* Eolith with Hyperstone CPUs */
+ XTAL_45_158MHz = 45158000, /* Sega Model 2A video board, Model 3 CPU board */
+ XTAL_45_6192Mhz = 45619200, /* DEC VK100 */
+ XTAL_48MHz = 48000000, /* Williams/Midway Y/Z-unit system */
+ XTAL_48_66MHz = 48660000, /* Zaxxon */
+ XTAL_49_152MHz = 49152000, /* Used on some Namco PCBs, Baraduke h/w, System 21, Super System 22 */
+ XTAL_50MHz = 50000000, /* Williams/Midway T/W/V-unit system */
+ XTAL_52MHz = 52000000, /* Cojag */
+ XTAL_53_693175MHz = 53693175, /* PSX-based h/w, Sony ZN1-2-based */
+ XTAL_54MHz = 54000000, /* Taito JC */
+ XTAL_57_2727MHz = 57272727, /* Psikyo SH2 with /2 divider */
+ XTAL_60MHz = 60000000,
+ XTAL_61_44MHz = 61440000, /* dkong */
+ XTAL_64MHz = 64000000, /* BattleToads */
+ XTAL_66_6667MHz = 66666700, /* Later Midway games */
+ XTAL_67_7376MHz = 67737600, /* PSX-based h/w, Sony ZN1-2-based */
+ XTAL_73_728MHz = 73728000, /* Ms. Pac-Man/Galaga 20th Anniversary */
+ XTAL_100MHz = 100000000, /* PSX-based Namco System 12, Vegas, Sony ZN1-2-based */
+ XTAL_101_4912MHz = 101491200, /* PSX-based Namco System 10 */
+ XTAL_200MHz = 200000000, /* Base SH4 CPU (Naomi, Hikaru etc.) */
+
+/* Resonators (There are probably more. Almost always used for driving OKI sound chips) */
+
+ XTAL_384kHz = 384000,
+ XTAL_400kHz = 400000, /* Used on Great Swordman h/w */
+ XTAL_455kHz = 455000, /* Used on Gladiator h/w */
+ XTAL_640kHz = 640000,
+ XTAL_1_056MHz = 1056000 /* used on Trio The Punch */
+};
+
+
+/*
+
+For further reference:
+
+A search at http://search.digikey.com/scripts/DkSearch/dksus.dll?Cat=852333;keywords=cry
+reveals the following shipping frequencies as of 1/1/2008:
+
+20kHz
+25.600kHz
+26.667kHz
+28kHz
+
+30kHz
+30.720kHz
+30.76kHz
+31.2kHz
+31.25kHz
+31.5kHz
+32.000kHz
+32.56kHz
+32.768kHz
+32.919kHz
+34kHz
+36kHz
+38kHz
+38.4kHz
+39.500kHz
+
+40kHz
+44.100kHz
+46.604kHz
+46.6084kHz
+
+50kHz
+59.787kHz
+
+60.000kHz
+60.002kHz
+60.005kHz
+65.535kHz
+65.536kHz
+69kHz
+
+70kHz
+71kHz
+72kHz
+73kHz
+74kHz
+74.3kHz
+74.4kHz
+75kHz
+76kHz
+76.79kHz
+76.8kHz
+76.81kHz
+77kHz
+77.204kHz
+77.287kHz
+77.500kHz
+77.503kHz
+77.504kHz
+78kHz
+79kHz
+
+83kHz
+
+96kHz
+96.006kHz
+
+100kHz
+111kHz
+117.72kHz
+120kHz
+120.8475kHz
+125kHz
+131.072kHz
+149.475kHz
+153.600kHz
+
+200kHz
+
+307.2kHz
+
+1.000MHz
+1.8432MHz
+
+2.000MHz
+2.048MHz
+2.097152MHz
+2.4576MHz
+2.5MHz
+2.560MHz
+2.949120MHz
+
+3.000MHz
+3.276MHz
+3.2768MHz
+3.579MHz
+3.579545MHz
+3.640MHz
+3.6864MHz
+3.700MHz
+3.859MHz
+3.93216MHz
+
+4.000MHz
+4.032MHz
+4.096MHz
+4.09625MHz
+4.194MHz
+4.194304MHz
+4.332MHz
+4.433MHz
+4.433616MHz
+4.433618MHz
+4.433619MHz
+4.74687MHz
+4.800MHz
+4.8970MHz
+4.90625MHz
+4.915MHz
+4.9152MHz
+
+5.000MHz
+5.0688MHz
+5.120MHz
+5.185MHz
+5.223438MHz
+5.5MHz
+5.5296MHz
+5.9904MHz
+
+6.000MHz
+6.14MHz
+6.144MHz
+6.1760MHz
+6.400 MHz
+6.49830MHz
+6.5MHz
+6.5536MHz
+6.612813MHz
+6.7458MHz
+6.757MHz
+6.76438MHz
+
+7.1505MHz
+7.15909 MHz
+7.2MHz
+7.3728MHz
+7.68MHz
+7.94888MHz
+
+8.000MHz
+8.000156MHz
+8.192MHz
+8.388608MHz
+8.432MHz
+8.5MHz
+8.6432MHz
+
+9.000MHz
+9.216MHz
+9.509375MHz
+9.545MHz
+9.6MHz
+9.7941MHz
+9.830MHz
+9.8304MHz
+9.84375MHz
+9.8438MHz
+
+10.000MHz
+10.240MHz
+10.245MHz
+10.6244MHz
+10.738635MHz
+10.73865MHz
+
+11.000MHz
+11.046MHz
+11.0592MHz
+11.228MHz
+11.2896MHz
+11.520MHz
+11.981350MHz
+
+12.000MHz
+12.000393MHz
+12.096MHz
+12.1875MHz
+12.288MHz
+12.352MHz
+12.500MHz
+12.688MHz
+12.800MHz
+12.96MHz
+
+13.000MHz
+13.0625MHz
+13.225MHz
+13.2256MHz
+13.500MHz
+13.5168MHz
+13.56MHz
+13.605MHz
+13.824MHz
+13.94916MHz
+
+14.00MHz
+14.318MHz
+14.31818MHz
+14.3359MHz
+14.3594MHz
+14.4MHz
+14.5MHz
+14.69MHz
+14.7456MHz
+14.850MHz
+
+15MHz
+15.360MHz
+
+16.000MHz
+16.000312MHz
+16.128MHz
+16.257MHz
+16.3676MHz
+16.368MHz
+16.384MHz
+16.576MHz
+16.6660MHz
+16.667MHz
+16.670MHz
+16.800MHz
+16.934MHz
+16.9344MHz
+
+17.734475MHz
+
+18.000MHz
+18.432MHz
+18.869MHz
+
+19.200MHz
+19.440MHz
+19.660MHz
+19.6608MHz
+19.68MHz
+19.800MHz
+
+20.000MHz
+20.35625MHz
+20.3563MHz
+20.480MHz
+
+21.47727MHz
+
+22.000MHz
+22.118MHz
+22.1184MHz
+22.400MHz
+22.5MHz
+22.5792MHz
+22.6278MHz
+
+23MHz
+23.2643MHz
+23.5MHz
+23.5122MHz
+23.592MHz
+
+24.000MHz
+24.00014MHz
+24.5MHz
+24.545454 MHz
+24.5535MHz
+24.576MHz
+24.704MHz
+24.7456MHz
+
+25.000MHz
+25MHz
+25.175MHz
+25.2235MHz
+25.4563MHz
+25.5MHz
+
+26.000MHz
+26.45125MHz
+26.4513MHz
+26.5MHz
+26.5971MHz
+26.800MHz
+
+27.000MHz
+27.1344MHz
+27.3067MHz
+27.4688MHz
+
+28.000MHz
+28.224MHz
+28.259375MHz
+28.2594MHz
+28.322MHz
+28.375MHz
+28.5938MHz
+28.636MHz
+28.6363MHz
+28.63636MHz
+
+29.4912MHz
+29.498928MHz
+29.500MHz
+
+30.000MHz
+32.000MHz
+32.514MHz
+32.768MHz
+33.000MHz
+33.333MHz
+33.3333MHz
+33.8688MHz
+35.2512MHz
+35.3280MHz
+36.000MHz
+38.000MHz
+38.00053MHz
+38.400MHz
+38.880MHz
+39MHz
+
+40.000MHz
+40.320MHz
+40.960 MHz
+42.000MHz
+44.000MHz
+44.2368MHz
+44.545MHz
+44.736MHz
+44.800MHz
+44.900MHz
+45.000MHz
+46.000MHz
+48.000MHz
+49.152MHz
+49.86MHz
+
+50.000MHz
+53.125MHz
+55.000MHz
+
+60.000MHz
+64.000MHz
+66.000MHz
+66.666MHz
+66.6666MHz
+
+73.66979MHz
+75.957292MHz
+76.121875MHz
+
+80.000MHz
+
+100.00MHz
+
+*/
diff --git a/trunk/src/emu/eigccppc.h b/trunk/src/emu/eigccppc.h
new file mode 100644
index 00000000000..268853cce55
--- /dev/null
+++ b/trunk/src/emu/eigccppc.h
@@ -0,0 +1,493 @@
+/***************************************************************************
+
+ eigccppc.h
+
+ PowerPC (32 and 64-bit) inline implementations for GCC compilers. This
+ code is automatically included if appropriate by eminline.h.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#ifndef __EIGCCPPC__
+#define __EIGCCPPC__
+
+
+/***************************************************************************
+ INLINE MATH FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ mul_32x32 - perform a signed 32 bit x 32 bit
+ multiply and return the full 64 bit result
+-------------------------------------------------*/
+
+/* GCC can do a good job of this. */
+
+
+/*-------------------------------------------------
+ mulu_32x32 - perform an unsigned 32 bit x
+ 32 bit multiply and return the full 64 bit
+ result
+-------------------------------------------------*/
+
+/* GCC can do a good job of this */
+
+
+/*-------------------------------------------------
+ mul_32x32_hi - perform a signed 32 bit x 32 bit
+ multiply and return the upper 32 bits of the
+ result
+-------------------------------------------------*/
+
+#define mul_32x32_hi _mul_32x32_hi
+INLINE INT32 ATTR_CONST ATTR_FORCE_INLINE
+_mul_32x32_hi(INT32 val1, INT32 val2)
+{
+ register INT32 result;
+
+ __asm__ (
+ " mulhw %[result], %[val1], %[val2] \n"
+ : [result] "=r" (result)
+ : [val1] "%r" (val1)
+ , [val2] "r" (val2)
+ );
+
+ return result;
+}
+
+
+/*-------------------------------------------------
+ mulu_32x32_hi - perform an unsigned 32 bit x
+ 32 bit multiply and return the upper 32 bits
+ of the result
+-------------------------------------------------*/
+
+#define mulu_32x32_hi _mulu_32x32_hi
+INLINE UINT32 ATTR_CONST ATTR_FORCE_INLINE
+_mulu_32x32_hi(UINT32 val1, UINT32 val2)
+{
+ register UINT32 result;
+
+ __asm__ (
+ " mulhwu %[result], %[val1], %[val2] \n"
+ : [result] "=r" (result)
+ : [val1] "%r" (val1)
+ , [val2] "r" (val2)
+ );
+
+ return result;
+}
+
+
+/*-------------------------------------------------
+ mul_32x32_shift - perform a signed 32 bit x
+ 32 bit multiply and shift the result by the
+ given number of bits before truncating the
+ result to 32 bits
+-------------------------------------------------*/
+
+#if !defined(__ppc64__) && !defined(__PPC64__) && !defined(_ARCH_PPC64)
+#define mul_32x32_shift _mul_32x32_shift
+INLINE INT32 ATTR_CONST ATTR_FORCE_INLINE
+_mul_32x32_shift(INT32 val1, INT32 val2, UINT8 shift)
+{
+ register INT32 result;
+
+ /* Valid for (0 <= shift <= 32) */
+ __asm__ (
+ " mullw %[result], %[val1], %[val2] \n"
+ " mulhw %[val1], %[val1], %[val2] \n"
+ " srw %[result], %[result], %[shift] \n"
+ " subfic %[shift], %[shift], 0x20 \n"
+ " slw %[val1], %[val1], %[shift] \n"
+ " or %[result], %[result], %[val1] \n"
+ : [result] "=&r" (result)
+ , [shift] "+r" (shift)
+ , [val1] "+r" (val1)
+ : [val2] "r" (val2)
+ : "xer"
+ );
+
+ return result;
+}
+#endif
+
+
+/*-------------------------------------------------
+ mulu_32x32_shift - perform an unsigned 32 bit x
+ 32 bit multiply and shift the result by the
+ given number of bits before truncating the
+ result to 32 bits
+-------------------------------------------------*/
+
+#if !defined(__ppc64__) && !defined(__PPC64__) && !defined(_ARCH_PPC64)
+#define mulu_32x32_shift _mulu_32x32_shift
+INLINE UINT32 ATTR_CONST ATTR_FORCE_INLINE
+_mulu_32x32_shift(UINT32 val1, UINT32 val2, UINT8 shift)
+{
+ register UINT32 result;
+
+ /* Valid for (0 <= shift <= 32) */
+ __asm__ (
+ " mullw %[result], %[val1], %[val2] \n"
+ " mulhwu %[val1], %[val1], %[val2] \n"
+ " srw %[result], %[result], %[shift] \n"
+ " subfic %[shift], %[shift], 0x20 \n"
+ " slw %[val1], %[val1], %[shift] \n"
+ " or %[result], %[result], %[val1] \n"
+ : [result] "=&r" (result)
+ , [shift] "+r" (shift)
+ , [val1] "+r" (val1)
+ : [val2] "r" (val2)
+ : "xer"
+ );
+
+ return result;
+}
+#endif
+
+
+/*-------------------------------------------------
+ div_64x32 - perform a signed 64 bit x 32 bit
+ divide and return the 32 bit quotient
+-------------------------------------------------*/
+
+/* TBD */
+
+
+/*-------------------------------------------------
+ divu_64x32 - perform an unsigned 64 bit x 32 bit
+ divide and return the 32 bit quotient
+-------------------------------------------------*/
+
+/* TBD */
+
+
+/*-------------------------------------------------
+ div_64x32_rem - perform a signed 64 bit x 32
+ bit divide and return the 32 bit quotient and
+ 32 bit remainder
+-------------------------------------------------*/
+
+/* TBD */
+
+
+/*-------------------------------------------------
+ divu_64x32_rem - perform an unsigned 64 bit x
+ 32 bit divide and return the 32 bit quotient
+ and 32 bit remainder
+-------------------------------------------------*/
+
+/* TBD */
+
+
+/*-------------------------------------------------
+ div_32x32_shift - perform a signed divide of
+ two 32 bit values, shifting the first before
+ division, and returning the 32 bit quotient
+-------------------------------------------------*/
+
+/* TBD */
+
+
+/*-------------------------------------------------
+ divu_32x32_shift - perform an unsigned divide of
+ two 32 bit values, shifting the first before
+ division, and returning the 32 bit quotient
+-------------------------------------------------*/
+
+/* TBD */
+
+
+/*-------------------------------------------------
+ mod_64x32 - perform a signed 64 bit x 32 bit
+ divide and return the 32 bit remainder
+-------------------------------------------------*/
+
+/* TBD */
+
+
+/*-------------------------------------------------
+ modu_64x32 - perform an unsigned 64 bit x 32 bit
+ divide and return the 32 bit remainder
+-------------------------------------------------*/
+
+/* TBD */
+
+
+/*-------------------------------------------------
+ recip_approx - compute an approximate floating
+ point reciprocal
+-------------------------------------------------*/
+
+#define recip_approx _recip_approx
+INLINE float ATTR_CONST ATTR_FORCE_INLINE
+_recip_approx(float value)
+{
+ register float result;
+
+ __asm__ (
+ " fres %[result], %[value] \n"
+ : [result] "=f" (result)
+ : [value] "f" (value)
+ );
+
+ return result;
+}
+
+
+
+/***************************************************************************
+ INLINE BIT MANIPULATION FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ count_leading_zeros - return the number of
+ leading zero bits in a 32-bit value
+-------------------------------------------------*/
+
+#define count_leading_zeros _count_leading_zeros
+INLINE UINT8 ATTR_CONST ATTR_FORCE_INLINE
+_count_leading_zeros(UINT32 value)
+{
+ register UINT32 result;
+
+ __asm__ (
+ " cntlzw %[result], %[value] \n"
+ : [result] "=r" (result) /* result can be in any register */
+ : [value] "r" (value) /* 'value' can be in any register */
+ );
+
+ return result;
+}
+
+
+/*-------------------------------------------------
+ count_leading_ones - return the number of
+ leading one bits in a 32-bit value
+-------------------------------------------------*/
+
+#define count_leading_ones _count_leading_ones
+INLINE UINT8 ATTR_CONST ATTR_FORCE_INLINE
+_count_leading_ones(UINT32 value)
+{
+ register UINT32 result;
+
+ __asm__ (
+ " not %[result], %[value] \n"
+ " cntlzw %[result], %[result] \n"
+ : [result] "=r" (result) /* result can be in any register */
+ : [value] "r" (value) /* 'value' can be in any register */
+ );
+
+ return result;
+}
+
+
+
+/***************************************************************************
+ INLINE SYNCHRONIZATION FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ compare_exchange32 - compare the 'compare'
+ value against the memory at 'ptr'; if equal,
+ swap in the 'exchange' value. Regardless,
+ return the previous value at 'ptr'.
+-------------------------------------------------*/
+
+#define compare_exchange32 _compare_exchange32
+INLINE INT32 ATTR_NONNULL(1) ATTR_FORCE_INLINE
+_compare_exchange32(INT32 volatile *ptr, INT32 compare, INT32 exchange)
+{
+ register INT32 result;
+
+ __asm__ __volatile__ (
+ "1: lwarx %[result], 0, %[ptr] \n"
+ " cmpw %[compare], %[result] \n"
+ " bne 2f \n"
+ " sync \n"
+ " stwcx. %[exchange], 0, %[ptr] \n"
+ " bne- 1b \n"
+ "2: "
+ : [dummy] "+m" (*ptr) /* Lets GCC know that *ptr will be read/written in case it's not marked volatile */
+ , [result] "=&r" (result)
+ : [ptr] "r" (ptr)
+ , [exchange] "r" (exchange)
+ , [compare] "r" (compare)
+ : "cr0"
+ );
+
+ return result;
+}
+
+
+/*-------------------------------------------------
+ compare_exchange64 - compare the 'compare'
+ value against the memory at 'ptr'; if equal,
+ swap in the 'exchange' value. Regardless,
+ return the previous value at 'ptr'.
+-------------------------------------------------*/
+
+#if defined(__ppc64__) || defined(__PPC64__)
+#define compare_exchange64 _compare_exchange64
+INLINE INT64 ATTR_NONNULL(1) ATTR_FORCE_INLINE
+_compare_exchange64(INT64 volatile *ptr, INT64 compare, INT64 exchange)
+{
+ register INT64 result;
+
+ __asm__ __volatile__ (
+ "1: ldarx %[result], 0, %[ptr] \n"
+ " cmpd %[compare], %[result] \n"
+ " bne 2f \n"
+ " stdcx. %[exchange], 0, %[ptr] \n"
+ " bne- 1b \n"
+ "2: "
+ : [dummy] "+m" (*ptr) /* Lets GCC know that *ptr will be read/written in case it's not marked volatile */
+ , [result] "=&r" (result)
+ : [ptr] "r" (ptr)
+ , [exchange] "r" (exchange)
+ , [compare] "r" (compare)
+ : "cr0"
+ );
+
+ return result;
+}
+#endif
+
+
+/*-------------------------------------------------
+ atomic_exchange32 - atomically exchange the
+ exchange value with the memory at 'ptr',
+ returning the original value.
+-------------------------------------------------*/
+
+#define atomic_exchange32 _atomic_exchange32
+INLINE INT32 ATTR_NONNULL(1) ATTR_FORCE_INLINE
+_atomic_exchange32(INT32 volatile *ptr, INT32 exchange)
+{
+ register INT32 result;
+
+ __asm__ __volatile__ (
+ "1: lwarx %[result], 0, %[ptr] \n"
+ " sync \n"
+ " stwcx. %[exchange], 0, %[ptr] \n"
+ " bne- 1b \n"
+ : [dummy] "+m" (*ptr) /* Lets GCC know that *ptr will be read/written in case it's not marked volatile */
+ , [result] "=&r" (result)
+ : [ptr] "r" (ptr)
+ , [exchange] "r" (exchange)
+ : "cr0"
+ );
+
+ return result;
+}
+
+
+/*-------------------------------------------------
+ atomic_add32 - atomically add the delta value
+ to the memory at 'ptr', returning the final
+ result.
+-------------------------------------------------*/
+
+#define atomic_add32 _atomic_add32
+INLINE INT32 ATTR_NONNULL(1) ATTR_FORCE_INLINE
+_atomic_add32(INT32 volatile *ptr, INT32 delta)
+{
+ register INT32 result;
+
+ __asm__ __volatile__ (
+ "1: lwarx %[result], 0, %[ptr] \n"
+ " add %[result], %[result], %[delta] \n"
+ " sync \n"
+ " stwcx. %[result], 0, %[ptr] \n"
+ " bne- 1b \n"
+ : [dummy] "+m" (*ptr) /* Lets GCC know that *ptr will be read/written in case it's not marked volatile */
+ , [result] "=&b" (result)
+ : [ptr] "r" (ptr)
+ , [delta] "r" (delta)
+ : "cr0"
+ );
+
+ return result;
+}
+
+
+/*-------------------------------------------------
+ atomic_increment32 - atomically increment the
+ 32-bit value in memory at 'ptr', returning the
+ final result.
+-------------------------------------------------*/
+
+#define atomic_increment32 _atomic_increment32
+INLINE INT32 ATTR_NONNULL(1) ATTR_FORCE_INLINE
+_atomic_increment32(INT32 volatile *ptr)
+{
+ register INT32 result;
+
+ __asm__ __volatile__ (
+ "1: lwarx %[result], 0, %[ptr] \n"
+ " addi %[result], %[result], 1 \n"
+ " sync \n"
+ " stwcx. %[result], 0, %[ptr] \n"
+ " bne- 1b \n"
+ : [dummy] "+m" (*ptr) /* Lets GCC know that *ptr will be read/written in case it's not marked volatile */
+ , [result] "=&b" (result)
+ : [ptr] "r" (ptr)
+ : "cr0"
+ );
+
+ return result;
+}
+
+
+/*-------------------------------------------------
+ atomic_decrement32 - atomically decrement the
+ 32-bit value in memory at 'ptr', returning the
+ final result.
+-------------------------------------------------*/
+
+#define atomic_decrement32 _atomic_decrement32
+INLINE INT32 ATTR_NONNULL(1) ATTR_FORCE_INLINE
+_atomic_decrement32(INT32 volatile *ptr)
+{
+ register INT32 result;
+
+ __asm__ __volatile__ (
+ "1: lwarx %[result], 0, %[ptr] \n"
+ " addi %[result], %[result], -1 \n"
+ " sync \n"
+ " stwcx. %[result], 0, %[ptr] \n"
+ " bne- 1b \n"
+ : [dummy] "+m" (*ptr) /* Lets GCC know that *ptr will be read/written in case it's not marked volatile */
+ , [result] "=&b" (result)
+ : [ptr] "r" (ptr)
+ : "cr0"
+ );
+
+ return result;
+}
+
+
+
+/***************************************************************************
+ INLINE TIMING FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ get_profile_ticks - return a tick counter
+ from the processor that can be used for
+ profiling. It does not need to run at any
+ particular rate.
+-------------------------------------------------*/
+
+#define get_profile_ticks _get_profile_ticks
+INLINE INT64 ATTR_UNUSED ATTR_FORCE_INLINE _get_profile_ticks(void)
+{
+ // fix me - should use the time base
+ return osd_ticks();
+}
+
+#endif /* __EIGCCPPC__ */
diff --git a/trunk/src/emu/eigccx86.h b/trunk/src/emu/eigccx86.h
new file mode 100644
index 00000000000..e1f1bdfa020
--- /dev/null
+++ b/trunk/src/emu/eigccx86.h
@@ -0,0 +1,688 @@
+/***************************************************************************
+
+ eigccx86.h
+
+ x86 (32 and 64-bit) inline implementations for GCC compilers. This
+ code is automatically included if appropriate by eminline.h.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#ifndef __EIGCCX86__
+#define __EIGCCX86__
+
+/* Include MMX/SSE intrinsics headers */
+
+#ifdef __SSE2__
+#include <stdlib.h>
+#include <mmintrin.h> /* MMX */
+#include <xmmintrin.h> /* SSE */
+#include <emmintrin.h> /* SSE2 */
+#endif
+
+
+/***************************************************************************
+ INLINE MATH FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ mul_32x32 - perform a signed 32 bit x 32 bit
+ multiply and return the full 64 bit result
+-------------------------------------------------*/
+
+#ifndef __x86_64__
+#define mul_32x32 _mul_32x32
+INLINE INT64 ATTR_CONST ATTR_FORCE_INLINE
+_mul_32x32(INT32 a, INT32 b)
+{
+ register INT64 result;
+
+ __asm__ (
+ " imull %[b] ;"
+ : [result] "=A" (result) /* result in edx:eax */
+ : [a] "%a" (a) /* 'a' should also be in eax on entry */
+ , [b] "rm" (b) /* 'b' can be memory or register */
+ : "cc" /* Clobbers condition codes */
+ );
+
+ return result;
+}
+#endif
+
+
+/*-------------------------------------------------
+ mulu_32x32 - perform an unsigned 32 bit x
+ 32 bit multiply and return the full 64 bit
+ result
+-------------------------------------------------*/
+
+#ifndef __x86_64__
+#define mulu_32x32 _mulu_32x32
+INLINE UINT64 ATTR_CONST ATTR_FORCE_INLINE
+_mulu_32x32(UINT32 a, UINT32 b)
+{
+ register UINT64 result;
+
+ __asm__ (
+ " mull %[b] ;"
+ : [result] "=A" (result) /* result in edx:eax */
+ : [a] "%a" (a) /* 'a' should also be in eax on entry */
+ , [b] "rm" (b) /* 'b' can be memory or register */
+ : "cc" /* Clobbers condition codes */
+ );
+
+ return result;
+}
+#endif
+
+
+/*-------------------------------------------------
+ mul_32x32_hi - perform a signed 32 bit x 32 bit
+ multiply and return the upper 32 bits of the
+ result
+-------------------------------------------------*/
+
+#define mul_32x32_hi _mul_32x32_hi
+INLINE INT32 ATTR_CONST ATTR_FORCE_INLINE
+_mul_32x32_hi(INT32 a, INT32 b)
+{
+ register INT32 result, temp;
+
+ __asm__ (
+ " imull %[b] ;"
+ : [result] "=d" (result) /* result in edx */
+ , [temp] "=a" (temp) /* This is effectively a clobber */
+ : [a] "a" (a) /* 'a' should be in eax on entry */
+ , [b] "rm" (b) /* 'b' can be memory or register */
+ : "cc" /* Clobbers condition codes */
+ );
+
+ return result;
+}
+
+
+/*-------------------------------------------------
+ mulu_32x32_hi - perform an unsigned 32 bit x
+ 32 bit multiply and return the upper 32 bits
+ of the result
+-------------------------------------------------*/
+
+#define mulu_32x32_hi _mulu_32x32_hi
+INLINE UINT32 ATTR_CONST ATTR_FORCE_INLINE
+_mulu_32x32_hi(UINT32 a, UINT32 b)
+{
+ register UINT32 result, temp;
+
+ __asm__ (
+ " mull %[b] ;"
+ : [result] "=d" (result) /* result in edx */
+ , [temp] "=a" (temp) /* This is effectively a clobber */
+ : [a] "a" (a) /* 'a' should be in eax on entry */
+ , [b] "rm" (b) /* 'b' can be memory or register */
+ : "cc" /* Clobbers condition codes */
+ );
+
+ return result;
+}
+
+
+/*-------------------------------------------------
+ mul_32x32_shift - perform a signed 32 bit x
+ 32 bit multiply and shift the result by the
+ given number of bits before truncating the
+ result to 32 bits
+-------------------------------------------------*/
+
+#ifndef __x86_64__
+#define mul_32x32_shift _mul_32x32_shift
+INLINE INT32 ATTR_CONST ATTR_FORCE_INLINE
+_mul_32x32_shift(INT32 a, INT32 b, UINT8 shift)
+{
+ register INT32 result;
+
+ /* Valid for (0 <= shift <= 31) */
+ __asm__ (
+ " imull %[b] ;"
+ " shrdl %[shift], %%edx, %[result] ;"
+ : [result] "=a" (result) /* result ends up in eax */
+ : [a] "%0" (a) /* 'a' should also be in eax on entry */
+ , [b] "rm" (b) /* 'b' can be memory or register */
+ , [shift] "Ic" (shift) /* 'shift' must be constant in 0-31 range or in cl */
+ : "%edx", "cc" /* clobbers edx and condition codes */
+ );
+
+ return result;
+}
+#endif
+
+
+/*-------------------------------------------------
+ mulu_32x32_shift - perform an unsigned 32 bit x
+ 32 bit multiply and shift the result by the
+ given number of bits before truncating the
+ result to 32 bits
+-------------------------------------------------*/
+
+#ifndef __x86_64__
+#define mulu_32x32_shift _mulu_32x32_shift
+INLINE UINT32 ATTR_CONST ATTR_FORCE_INLINE
+_mulu_32x32_shift(UINT32 a, UINT32 b, UINT8 shift)
+{
+ register UINT32 result;
+
+ /* Valid for (0 <= shift <= 31) */
+ __asm__ (
+ " mull %[b] ;"
+ " shrdl %[shift], %%edx, %[result] ;"
+ : [result] "=a" (result) /* result ends up in eax */
+ : [a] "%0" (a) /* 'a' should also be in eax on entry */
+ , [b] "rm" (b) /* 'b' can be memory or register */
+ , [shift] "Ic" (shift) /* 'shift' must be constant in 0-31 range or in cl */
+ : "%edx", "cc" /* clobbers edx and condition codes */
+ );
+
+ return result;
+}
+#endif
+
+
+/*-------------------------------------------------
+ div_64x32 - perform a signed 64 bit x 32 bit
+ divide and return the 32 bit quotient
+-------------------------------------------------*/
+
+#ifndef __x86_64__
+#define div_64x32 _div_64x32
+INLINE INT32 ATTR_CONST ATTR_FORCE_INLINE
+_div_64x32(INT64 a, INT32 b)
+{
+ register INT32 result, temp;
+
+ /* Throws arithmetic exception if result doesn't fit in 32 bits */
+ __asm__ (
+ " idivl %[b] ;"
+ : [result] "=a" (result) /* Result ends up in eax */
+ , [temp] "=d" (temp) /* This is effectively a clobber */
+ : [a] "A" (a) /* 'a' in edx:eax */
+ , [b] "rm" (b) /* 'b' in register or memory */
+ : "cc" /* Clobbers condition codes */
+ );
+
+ return result;
+}
+#endif
+
+
+/*-------------------------------------------------
+ divu_64x32 - perform an unsigned 64 bit x 32 bit
+ divide and return the 32 bit quotient
+-------------------------------------------------*/
+
+#ifndef __x86_64__
+#define divu_64x32 _divu_64x32
+INLINE UINT32 ATTR_CONST ATTR_FORCE_INLINE
+_divu_64x32(UINT64 a, UINT32 b)
+{
+ register UINT32 result, temp;
+
+ /* Throws arithmetic exception if result doesn't fit in 32 bits */
+ __asm__ (
+ " divl %[b] ;"
+ : [result] "=a" (result) /* Result ends up in eax */
+ , [temp] "=d" (temp) /* This is effectively a clobber */
+ : [a] "A" (a) /* 'a' in edx:eax */
+ , [b] "rm" (b) /* 'b' in register or memory */
+ : "cc" /* Clobbers condition codes */
+ );
+
+ return result;
+}
+#endif
+
+
+/*-------------------------------------------------
+ div_64x32_rem - perform a signed 64 bit x 32
+ bit divide and return the 32 bit quotient and
+ 32 bit remainder
+-------------------------------------------------*/
+
+#ifndef __x86_64__
+#define div_64x32_rem _div_64x32_rem
+INLINE INT32 ATTR_FORCE_INLINE
+_div_64x32_rem(INT64 dividend, INT32 divisor, INT32 *remainder)
+{
+ register INT32 quotient;
+
+ /* Throws arithmetic exception if result doesn't fit in 32 bits */
+ __asm__ (
+ " idivl %[divisor] ;"
+ : [result] "=a" (quotient) /* Quotient ends up in eax */
+ , [remainder] "=d" (*remainder) /* Remainder ends up in edx */
+ : [dividend] "A" (dividend) /* 'dividend' in edx:eax */
+ , [divisor] "rm" (divisor) /* 'divisor' in register or memory */
+ : "cc" /* Clobbers condition codes */
+ );
+
+ return quotient;
+}
+#endif
+
+
+/*-------------------------------------------------
+ divu_64x32_rem - perform an unsigned 64 bit x
+ 32 bit divide and return the 32 bit quotient
+ and 32 bit remainder
+-------------------------------------------------*/
+
+#ifndef __x86_64__
+#define divu_64x32_rem _divu_64x32_rem
+INLINE UINT32 ATTR_FORCE_INLINE
+_divu_64x32_rem(UINT64 dividend, UINT32 divisor, UINT32 *remainder)
+{
+ register UINT32 quotient;
+
+ /* Throws arithmetic exception if result doesn't fit in 32 bits */
+ __asm__ (
+ " divl %[divisor] ;"
+ : [result] "=a" (quotient) /* Quotient ends up in eax */
+ , [remainder] "=d" (*remainder) /* Remainder ends up in edx */
+ : [dividend] "A" (dividend) /* 'dividend' in edx:eax */
+ , [divisor] "rm" (divisor) /* 'divisor' in register or memory */
+ : "cc" /* Clobbers condition codes */
+ );
+
+ return quotient;
+}
+#endif
+
+
+/*-------------------------------------------------
+ div_32x32_shift - perform a signed divide of
+ two 32 bit values, shifting the first before
+ division, and returning the 32 bit quotient
+-------------------------------------------------*/
+
+#ifndef __x86_64__
+#define div_32x32_shift _div_32x32_shift
+INLINE INT32 ATTR_CONST ATTR_FORCE_INLINE
+_div_32x32_shift(INT32 a, INT32 b, UINT8 shift)
+{
+ register INT32 result;
+
+ /* Valid for (0 <= shift <= 31) */
+ /* Throws arithmetic exception if result doesn't fit in 32 bits */
+ __asm__ (
+ " cdq ;"
+ " shldl %[shift], %[a], %%edx ;"
+ " shll %[shift], %[a] ;"
+ " idivl %[b] ;"
+ : [result] "=&a" (result) /* result ends up in eax */
+ : [a] "0" (a) /* 'a' should also be in eax on entry */
+ , [b] "rm" (b) /* 'b' can be memory or register */
+ , [shift] "Ic" (shift) /* 'shift' must be constant in 0-31 range or in cl */
+ : "%edx", "cc" /* clobbers edx and condition codes */
+ );
+
+ return result;
+}
+#endif
+
+
+/*-------------------------------------------------
+ divu_32x32_shift - perform an unsigned divide of
+ two 32 bit values, shifting the first before
+ division, and returning the 32 bit quotient
+-------------------------------------------------*/
+
+#ifndef __x86_64__
+#define divu_32x32_shift _divu_32x32_shift
+INLINE UINT32 ATTR_CONST ATTR_FORCE_INLINE
+_divu_32x32_shift(UINT32 a, UINT32 b, UINT8 shift)
+{
+ register INT32 result;
+
+ /* Valid for (0 <= shift <= 31) */
+ /* Throws arithmetic exception if result doesn't fit in 32 bits */
+ __asm__ (
+ " clr %%edx ;"
+ " shldl %[shift], %[a], %%edx ;"
+ " shll %[shift], %[a] ;"
+ " divl %[b] ;"
+ : [result] "=&a" (result) /* result ends up in eax */
+ : [a] "0" (a) /* 'a' should also be in eax on entry */
+ , [b] "rm" (b) /* 'b' can be memory or register */
+ , [shift] "Ic" (shift) /* 'shift' must be constant in 0-31 range or in cl */
+ : "%edx", "cc" /* clobbers edx and condition codes */
+ );
+
+ return result;
+}
+#endif
+
+
+/*-------------------------------------------------
+ mod_64x32 - perform a signed 64 bit x 32 bit
+ divide and return the 32 bit remainder
+-------------------------------------------------*/
+
+#ifndef __x86_64__
+#define mod_64x32 _mod_64x32
+INLINE INT32 ATTR_CONST ATTR_FORCE_INLINE
+_mod_64x32(INT64 a, INT32 b)
+{
+ register INT32 result, temp;
+
+ /* Throws arithmetic exception if quotient doesn't fit in 32 bits */
+ __asm__ (
+ " idivl %[b] ;"
+ : [result] "=d" (result) /* Result ends up in edx */
+ , [temp] "=a" (temp) /* This is effectively a clobber */
+ : [a] "A" (a) /* 'a' in edx:eax */
+ , [b] "rm" (b) /* 'b' in register or memory */
+ : "cc" /* Clobbers condition codes */
+ );
+
+ return result;
+}
+#endif
+
+
+/*-------------------------------------------------
+ modu_64x32 - perform an unsigned 64 bit x 32 bit
+ divide and return the 32 bit remainder
+-------------------------------------------------*/
+
+#ifndef __x86_64__
+#define modu_64x32 _modu_64x32
+INLINE UINT32 ATTR_CONST ATTR_FORCE_INLINE
+_modu_64x32(UINT64 a, UINT32 b)
+{
+ register UINT32 result, temp;
+
+ /* Throws arithmetic exception if quotient doesn't fit in 32 bits */
+ __asm__ (
+ " divl %[b] ;"
+ : [result] "=d" (result) /* Result ends up in edx */
+ , [temp] "=a" (temp) /* This is effectively a clobber */
+ : [a] "A" (a) /* 'a' in edx:eax */
+ , [b] "rm" (b) /* 'b' in register or memory */
+ : "cc" /* Clobbers condition codes */
+ );
+
+ return result;
+}
+#endif
+
+
+/*-------------------------------------------------
+ recip_approx - compute an approximate floating
+ point reciprocal
+-------------------------------------------------*/
+
+#ifdef __SSE2__
+#define recip_approx _recip_approx
+INLINE float ATTR_CONST
+_recip_approx(float value)
+{
+ __m128 value_xmm = _mm_set_ss(value);
+ __m128 result_xmm = _mm_rcp_ss(value_xmm);
+ float result;
+ _mm_store_ss(&result, result_xmm);
+ return result;
+}
+#endif
+
+
+
+/***************************************************************************
+ INLINE BIT MANIPULATION FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ count_leading_zeros - return the number of
+ leading zero bits in a 32-bit value
+-------------------------------------------------*/
+
+#define count_leading_zeros _count_leading_zeros
+INLINE UINT8 ATTR_CONST ATTR_FORCE_INLINE
+_count_leading_zeros(UINT32 value)
+{
+ register UINT32 result;
+
+ __asm__ (
+ " bsrl %[value], %[result] ;"
+ " jnz 1f ;"
+ " movl $63, %[result] ;"
+ "1: xorl $31, %[result] ;"
+ : [result] "=r" (result) /* result can be in any register */
+ : [value] "rm" (value) /* 'value' can be register or memory */
+ : "cc" /* clobbers condition codes */
+ );
+
+ return result;
+}
+
+
+/*-------------------------------------------------
+ count_leading_ones - return the number of
+ leading one bits in a 32-bit value
+-------------------------------------------------*/
+
+#define count_leading_ones _count_leading_ones
+INLINE UINT8 ATTR_CONST ATTR_FORCE_INLINE
+_count_leading_ones(UINT32 value)
+{
+ register UINT32 result;
+
+ __asm__ (
+ " movl %[value], %[result] ;"
+ " notl %[result] ;"
+ " bsrl %[result], %[result] ;"
+ " jnz 1f ;"
+ " movl $63, %[result] ;"
+ "1: xorl $31, %[result] ;"
+ : [result] "=r" (result) /* result can be in any register */
+ : [value] "rmi" (value) /* 'value' can be register, memory or immediate */
+ : "cc" /* clobbers condition codes */
+ );
+
+ return result;
+}
+
+
+
+/***************************************************************************
+ INLINE SYNCHRONIZATION FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ compare_exchange32 - compare the 'compare'
+ value against the memory at 'ptr'; if equal,
+ swap in the 'exchange' value. Regardless,
+ return the previous value at 'ptr'.
+-------------------------------------------------*/
+
+#define compare_exchange32 _compare_exchange32
+INLINE INT32 ATTR_NONNULL(1) ATTR_FORCE_INLINE
+_compare_exchange32(INT32 volatile *ptr, INT32 compare, INT32 exchange)
+{
+ register INT32 result;
+
+ __asm__ __volatile__ (
+ " lock ; cmpxchgl %[exchange], %[ptr] ;"
+ : [ptr] "+m" (*ptr)
+ , [result] "=a" (result)
+ : [compare] "1" (compare)
+ , [exchange] "q" (exchange)
+ : "cc"
+ );
+
+ return result;
+}
+
+
+/*-------------------------------------------------
+ compare_exchange64 - compare the 'compare'
+ value against the memory at 'ptr'; if equal,
+ swap in the 'exchange' value. Regardless,
+ return the previous value at 'ptr'.
+-------------------------------------------------*/
+
+#ifdef __x86_64__
+#define compare_exchange64 _compare_exchange64
+INLINE INT64 ATTR_NONNULL(1) ATTR_FORCE_INLINE
+_compare_exchange64(INT64 volatile *ptr, INT64 compare, INT64 exchange)
+{
+ register INT64 result;
+
+ __asm__ __volatile__ (
+ " lock ; cmpxchgq %[exchange], %[ptr] ;"
+ : [ptr] "+m" (*ptr)
+ , [result] "=a" (result)
+ : [compare] "1" (compare)
+ , [exchange] "q" (exchange)
+ : "cc"
+ );
+
+ return result;
+}
+#endif
+
+
+/*-------------------------------------------------
+ atomic_exchange32 - atomically exchange the
+ exchange value with the memory at 'ptr',
+ returning the original value.
+-------------------------------------------------*/
+
+#define atomic_exchange32 _atomic_exchange32
+INLINE INT32 ATTR_NONNULL(1) ATTR_FORCE_INLINE
+_atomic_exchange32(INT32 volatile *ptr, INT32 exchange)
+{
+ register INT32 result;
+
+ __asm__ __volatile__ (
+ " lock ; xchgl %[exchange], %[ptr] ;"
+ : [ptr] "+m" (*ptr)
+ , [result] "=r" (result)
+ : [exchange] "1" (exchange)
+ );
+
+ return result;
+}
+
+
+/*-------------------------------------------------
+ atomic_add32 - atomically add the delta value
+ to the memory at 'ptr', returning the final
+ result.
+-------------------------------------------------*/
+
+#define atomic_add32 _atomic_add32
+INLINE INT32 ATTR_NONNULL(1) ATTR_FORCE_INLINE
+_atomic_add32(INT32 volatile *ptr, INT32 delta)
+{
+ register INT32 result = delta;
+
+ __asm__ __volatile__ (
+ " lock ; xaddl %[result], %[ptr] ;"
+ : [ptr] "+m" (*ptr)
+ , [result] "+r" (result)
+ :
+ : "cc"
+ );
+
+ return result + delta;
+}
+
+
+/*-------------------------------------------------
+ atomic_increment32 - atomically increment the
+ 32-bit value in memory at 'ptr', returning the
+ final result.
+-------------------------------------------------*/
+
+#define atomic_increment32 _atomic_increment32
+INLINE INT32 ATTR_NONNULL(1) ATTR_FORCE_INLINE
+_atomic_increment32(INT32 volatile *ptr)
+{
+ register INT32 result = 1;
+
+ __asm__ __volatile__ (
+ " lock ; xaddl %[result], %[ptr] ;"
+ : [ptr] "+m" (*ptr)
+ , [result] "+r" (result)
+ :
+ : "cc"
+ );
+
+ return result + 1;
+}
+
+
+/*-------------------------------------------------
+ atomic_decrement32 - atomically decrement the
+ 32-bit value in memory at 'ptr', returning the
+ final result.
+-------------------------------------------------*/
+
+#define atomic_decrement32 _atomic_decrement32
+INLINE INT32 ATTR_NONNULL(1) ATTR_FORCE_INLINE
+_atomic_decrement32(INT32 volatile *ptr)
+{
+ register INT32 result = -1;
+
+ __asm__ __volatile__ (
+ " lock ; xaddl %[result], %[ptr] ;"
+ : [ptr] "+m" (*ptr)
+ , [result] "+r" (result)
+ :
+ : "cc"
+ );
+
+ return result - 1;
+}
+
+
+
+/***************************************************************************
+ INLINE TIMING FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ get_profile_ticks - return a tick counter
+ from the processor that can be used for
+ profiling. It does not need to run at any
+ particular rate.
+-------------------------------------------------*/
+
+#define get_profile_ticks _get_profile_ticks
+
+#ifndef __x86_64__
+INLINE INT64 ATTR_UNUSED ATTR_FORCE_INLINE _get_profile_ticks(void)
+{
+ UINT64 result;
+ __asm__ __volatile__ (
+ "rdtsc"
+ : "=A" (result)
+ );
+ return (INT64) (result & U64(0x7fffffffffffffff));
+}
+#else
+INLINE INT64 ATTR_UNUSED ATTR_FORCE_INLINE _get_profile_ticks(void)
+{
+ UINT64 result;
+ UINT32 r1, r2;
+ __asm__ __volatile__ (
+ "rdtsc"
+ : "=a" (r1), "=d" (r2)
+ );
+
+ result = ((UINT64)r2<<32) | (UINT64)r1;
+ return (INT64) (result & U64(0x7fffffffffffffff));
+}
+#endif
+
+#endif /* __EIGCCX86__ */
diff --git a/trunk/src/emu/eminline.h b/trunk/src/emu/eminline.h
new file mode 100644
index 00000000000..992a5039cf9
--- /dev/null
+++ b/trunk/src/emu/eminline.h
@@ -0,0 +1,453 @@
+/***************************************************************************
+
+ eminline.h
+
+ Definitions for inline functions that can be overriden by OSD-
+ specific code.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#ifndef __EMINLINE__
+#define __EMINLINE__
+
+/* we come with implementations for GCC x86 and PPC */
+#if defined(__GNUC__) && !defined(SDLMAME_NOASM)
+
+#if defined(__i386__) || defined(__x86_64__)
+#include "eigccx86.h"
+#elif defined(__ppc__) || defined (__PPC__) || defined(__ppc64__) || defined(__PPC64__)
+#include "eigccppc.h"
+#else
+#include "osinline.h"
+#endif
+
+#else
+
+#include "osinline.h"
+
+#endif
+
+
+/***************************************************************************
+ INLINE MATH FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ mul_32x32 - perform a signed 32 bit x 32 bit
+ multiply and return the full 64 bit result
+-------------------------------------------------*/
+
+#ifndef mul_32x32
+INLINE INT64 mul_32x32(INT32 a, INT32 b)
+{
+ return (INT64)a * (INT64)b;
+}
+#endif
+
+
+/*-------------------------------------------------
+ mulu_32x32 - perform an unsigned 32 bit x
+ 32 bit multiply and return the full 64 bit
+ result
+-------------------------------------------------*/
+
+#ifndef mulu_32x32
+INLINE UINT64 mulu_32x32(UINT32 a, UINT32 b)
+{
+ return (UINT64)a * (UINT64)b;
+}
+#endif
+
+
+/*-------------------------------------------------
+ mul_32x32_hi - perform a signed 32 bit x 32 bit
+ multiply and return the upper 32 bits of the
+ result
+-------------------------------------------------*/
+
+#ifndef mul_32x32_hi
+INLINE INT32 mul_32x32_hi(INT32 a, INT32 b)
+{
+ return (UINT32)(((INT64)a * (INT64)b) >> 32);
+}
+#endif
+
+
+/*-------------------------------------------------
+ mulu_32x32_hi - perform an unsigned 32 bit x
+ 32 bit multiply and return the upper 32 bits
+ of the result
+-------------------------------------------------*/
+
+#ifndef mulu_32x32_hi
+INLINE UINT32 mulu_32x32_hi(UINT32 a, UINT32 b)
+{
+ return (UINT32)(((UINT64)a * (UINT64)b) >> 32);
+}
+#endif
+
+
+/*-------------------------------------------------
+ mul_32x32_shift - perform a signed 32 bit x
+ 32 bit multiply and shift the result by the
+ given number of bits before truncating the
+ result to 32 bits
+-------------------------------------------------*/
+
+#ifndef mul_32x32_shift
+INLINE INT32 mul_32x32_shift(INT32 a, INT32 b, UINT8 shift)
+{
+ return (INT32)(((INT64)a * (INT64)b) >> shift);
+}
+#endif
+
+
+/*-------------------------------------------------
+ mulu_32x32_shift - perform an unsigned 32 bit x
+ 32 bit multiply and shift the result by the
+ given number of bits before truncating the
+ result to 32 bits
+-------------------------------------------------*/
+
+#ifndef mulu_32x32_shift
+INLINE UINT32 mulu_32x32_shift(UINT32 a, UINT32 b, UINT8 shift)
+{
+ return (UINT32)(((UINT64)a * (UINT64)b) >> shift);
+}
+#endif
+
+
+/*-------------------------------------------------
+ div_64x32 - perform a signed 64 bit x 32 bit
+ divide and return the 32 bit quotient
+-------------------------------------------------*/
+
+#ifndef div_64x32
+INLINE INT32 div_64x32(INT64 a, INT32 b)
+{
+ return a / (INT64)b;
+}
+#endif
+
+
+/*-------------------------------------------------
+ divu_64x32 - perform an unsigned 64 bit x 32 bit
+ divide and return the 32 bit quotient
+-------------------------------------------------*/
+
+#ifndef divu_64x32
+INLINE UINT32 divu_64x32(UINT64 a, UINT32 b)
+{
+ return a / (UINT64)b;
+}
+#endif
+
+
+/*-------------------------------------------------
+ div_64x32_rem - perform a signed 64 bit x 32
+ bit divide and return the 32 bit quotient and
+ 32 bit remainder
+-------------------------------------------------*/
+
+#ifndef div_64x32_rem
+INLINE INT32 div_64x32_rem(INT64 a, INT32 b, INT32 *remainder)
+{
+ *remainder = a % (INT64)b;
+ return a / (INT64)b;
+}
+#endif
+
+
+/*-------------------------------------------------
+ divu_64x32_rem - perform an unsigned 64 bit x
+ 32 bit divide and return the 32 bit quotient
+ and 32 bit remainder
+-------------------------------------------------*/
+
+#ifndef divu_64x32_rem
+INLINE UINT32 divu_64x32_rem(UINT64 a, UINT32 b, UINT32 *remainder)
+{
+ *remainder = a % (UINT64)b;
+ return a / (UINT64)b;
+}
+#endif
+
+
+/*-------------------------------------------------
+ div_32x32_shift - perform a signed divide of
+ two 32 bit values, shifting the first before
+ division, and returning the 32 bit quotient
+-------------------------------------------------*/
+
+#ifndef div_32x32_shift
+INLINE INT32 div_32x32_shift(INT32 a, INT32 b, UINT8 shift)
+{
+ return ((INT64)a << shift) / (INT64)b;
+}
+#endif
+
+
+/*-------------------------------------------------
+ divu_32x32_shift - perform an unsigned divide of
+ two 32 bit values, shifting the first before
+ division, and returning the 32 bit quotient
+-------------------------------------------------*/
+
+#ifndef divu_32x32_shift
+INLINE UINT32 divu_32x32_shift(UINT32 a, UINT32 b, UINT8 shift)
+{
+ return ((UINT64)a << shift) / (UINT64)b;
+}
+#endif
+
+
+/*-------------------------------------------------
+ mod_64x32 - perform a signed 64 bit x 32 bit
+ divide and return the 32 bit remainder
+-------------------------------------------------*/
+
+#ifndef mod_64x32
+INLINE INT32 mod_64x32(INT64 a, INT32 b)
+{
+ return a % (INT64)b;
+}
+#endif
+
+
+/*-------------------------------------------------
+ modu_64x32 - perform an unsigned 64 bit x 32 bit
+ divide and return the 32 bit remainder
+-------------------------------------------------*/
+
+#ifndef modu_64x32
+INLINE UINT32 modu_64x32(UINT64 a, UINT32 b)
+{
+ return a % (UINT64)b;
+}
+#endif
+
+
+/*-------------------------------------------------
+ recip_approx - compute an approximate floating
+ point reciprocal
+-------------------------------------------------*/
+
+#ifndef recip_approx
+INLINE float recip_approx(float value)
+{
+ return 1.0f / value;
+}
+#endif
+
+
+
+/***************************************************************************
+ INLINE BIT MANIPULATION FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ count_leading_zeros - return the number of
+ leading zero bits in a 32-bit value
+-------------------------------------------------*/
+
+#ifndef count_leading_zeros
+INLINE UINT8 count_leading_zeros(UINT32 val)
+{
+ UINT8 count;
+ for (count = 0; (INT32)val >= 0; count++) val <<= 1;
+ return count;
+}
+#endif
+
+
+/*-------------------------------------------------
+ count_leading_ones - return the number of
+ leading one bits in a 32-bit value
+-------------------------------------------------*/
+
+#ifndef count_leading_ones
+INLINE UINT8 count_leading_ones(UINT32 val)
+{
+ UINT8 count;
+ for (count = 0; (INT32)val < 0; count++) val <<= 1;
+ return count;
+}
+#endif
+
+
+
+/***************************************************************************
+ INLINE SYNCHRONIZATION FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ compare_exchange32 - compare the 'compare'
+ value against the memory at 'ptr'; if equal,
+ swap in the 'exchange' value. Regardless,
+ return the previous value at 'ptr'.
+
+ Note that the default implementation does
+ no synchronization. You MUST override this
+ in osinline.h for it to be useful in a
+ multithreaded environment!
+-------------------------------------------------*/
+
+#ifndef compare_exchange32
+INLINE INT32 compare_exchange32(INT32 volatile *ptr, INT32 compare, INT32 exchange)
+{
+ INT32 oldval = *ptr;
+ if (*ptr == compare)
+ *ptr = exchange;
+ return oldval;
+}
+#endif
+
+
+/*-------------------------------------------------
+ compare_exchange64 - compare the 'compare'
+ value against the memory at 'ptr'; if equal,
+ swap in the 'exchange' value. Regardless,
+ return the previous value at 'ptr'.
+
+ Note that the default implementation does
+ no synchronization. You MUST override this
+ in osinline.h for it to be useful in a
+ multithreaded environment!
+-------------------------------------------------*/
+
+#ifdef PTR64
+#ifndef compare_exchange64
+INLINE INT64 compare_exchange64(INT64 volatile *ptr, INT64 compare, INT64 exchange)
+{
+ INT64 oldval = *ptr;
+ if (*ptr == compare)
+ *ptr = exchange;
+ return oldval;
+}
+#endif
+#endif
+
+
+/*-------------------------------------------------
+ compare_exchange_ptr - compare the 'compare'
+ value against the memory at 'ptr'; if equal,
+ swap in the 'exchange' value. Regardless,
+ return the previous value at 'ptr'.
+-------------------------------------------------*/
+
+#ifndef compare_exchange_ptr
+INLINE void *compare_exchange_ptr(void * volatile *ptr, void *compare, void *exchange)
+{
+#ifdef PTR64
+ INT64 result;
+ result = compare_exchange64((INT64 volatile *)ptr, (INT64)compare, (INT64)exchange);
+#else
+ INT32 result;
+ result = compare_exchange32((INT32 volatile *)ptr, (INT32)compare, (INT32)exchange);
+#endif
+ return (void *)result;
+}
+#endif
+
+
+/*-------------------------------------------------
+ atomic_exchange32 - atomically exchange the
+ exchange value with the memory at 'ptr',
+ returning the original value.
+
+ Note that the default implementation does
+ no synchronization. You MUST override this
+ in osinline.h for it to be useful in a
+ multithreaded environment!
+-------------------------------------------------*/
+
+#ifndef atomic_exchange32
+INLINE INT32 atomic_exchange32(INT32 volatile *ptr, INT32 exchange)
+{
+ INT32 oldval = *ptr;
+ *ptr = exchange;
+ return oldval;
+}
+#endif
+
+
+/*-------------------------------------------------
+ atomic_add32 - atomically add the delta value
+ to the memory at 'ptr', returning the final
+ result.
+
+ Note that the default implementation does
+ no synchronization. You MUST override this
+ in osinline.h for it to be useful in a
+ multithreaded environment!
+-------------------------------------------------*/
+
+#ifndef atomic_add32
+INLINE INT32 atomic_add32(INT32 volatile *ptr, INT32 delta)
+{
+ return (*ptr += delta);
+}
+#endif
+
+
+/*-------------------------------------------------
+ atomic_increment32 - atomically increment the
+ 32-bit value in memory at 'ptr', returning the
+ final result.
+
+ Note that the default implementation does
+ no synchronization. You MUST override this
+ in osinline.h for it to be useful in a
+ multithreaded environment!
+-------------------------------------------------*/
+
+#ifndef atomic_increment32
+INLINE INT32 atomic_increment32(INT32 volatile *ptr)
+{
+ return atomic_add32(ptr, 1);
+}
+#endif
+
+
+/*-------------------------------------------------
+ atomic_decrement32 - atomically decrement the
+ 32-bit value in memory at 'ptr', returning the
+ final result.
+
+ Note that the default implementation does
+ no synchronization. You MUST override this
+ in osinline.h for it to be useful in a
+ multithreaded environment!
+-------------------------------------------------*/
+
+#ifndef atomic_decrement32
+INLINE INT32 atomic_decrement32(INT32 volatile *ptr)
+{
+ return atomic_add32(ptr, -1);
+}
+#endif
+
+
+
+/***************************************************************************
+ INLINE TIMING FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ get_profile_ticks - return a tick counter
+ from the processor that can be used for
+ profiling. It does not need to run at any
+ particular rate.
+-------------------------------------------------*/
+
+#ifndef get_profile_ticks
+INLINE INT64 get_profile_ticks(void)
+{
+ return osd_ticks();
+}
+#endif
+
+#endif /* __EMINLINE__ */
diff --git a/trunk/src/emu/emu.h b/trunk/src/emu/emu.h
new file mode 100644
index 00000000000..80c36b36026
--- /dev/null
+++ b/trunk/src/emu/emu.h
@@ -0,0 +1,137 @@
+/***************************************************************************
+
+ emu.h
+
+ Core header file to be included by most files.
+
+ NOTE: The contents of this file are designed to meet the needs of
+ drivers and devices. In addition to this file, you will also need
+ to include the headers of any CPUs or other devices that are required.
+
+ If you find yourself needing something outside of this file in a
+ driver or device, think carefully about what you are doing.
+
+****************************************************************************
+
+ 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__
+#define __EMU_H__
+
+// core emulator headers -- must be first
+#include "emucore.h"
+#include "emutempl.h"
+#include "eminline.h"
+#include "profiler.h"
+
+// commonly-referenecd utilities imported from lib/util
+#include "chd.h"
+#include "palette.h"
+#include "unicode.h"
+
+// emulator-specific utilities
+#include "attotime.h"
+#include "hash.h"
+#include "fileio.h" // remove me once NVRAM is implemented as device
+#include "delegate.h"
+#include "cothread.h"
+
+// memory and address spaces
+#include "memory.h"
+#include "addrmap.h"
+
+// machine-wide utilities
+#include "romload.h"
+#include "save.h"
+
+// define machine_config_constructor here due to circular dependency
+// between devices and the machine config
+class machine_config;
+typedef device_t * (*machine_config_constructor)(machine_config &config, device_t *owner);
+
+// I/O
+#include "input.h"
+#include "ioport.h"
+#include "output.h"
+
+// devices and callbacks
+#include "device.h"
+#include "distate.h"
+#include "dimemory.h"
+#include "diexec.h"
+#include "opresolv.h"
+#include "diimage.h"
+#include "dislot.h"
+#include "disound.h"
+#include "dinvram.h"
+#include "dirtc.h"
+#include "didisasm.h"
+#include "schedule.h"
+#include "timer.h"
+
+// timers, CPU and scheduling
+#include "devcpu.h"
+#include "watchdog.h"
+
+// machine and driver configuration
+#include "mconfig.h"
+#include "driver.h"
+
+// image-related
+#include "softlist.h"
+#include "image.h"
+
+// the running machine
+#include "machine.h"
+#include "mame.h"
+
+// video-related
+#include "drawgfx.h"
+#include "tilemap.h"
+#include "emupal.h"
+#include "screen.h"
+#include "video.h"
+
+// sound-related
+#include "sound.h"
+#include "speaker.h"
+
+// generic helpers
+#include "devcb.h"
+#include "drivers/xtal.h"
+#include "audio/generic.h"
+#include "machine/generic.h"
+#include "video/generic.h"
+
+#endif /* __EMU_H__ */
diff --git a/trunk/src/emu/emu.mak b/trunk/src/emu/emu.mak
new file mode 100644
index 00000000000..c61202b4e26
--- /dev/null
+++ b/trunk/src/emu/emu.mak
@@ -0,0 +1,363 @@
+###########################################################################
+#
+# emu.mak
+#
+# MAME emulation core makefile
+#
+# Copyright Nicola Salmoria and the MAME Team.
+# Visit http://mamedev.org for licensing and usage restrictions.
+#
+###########################################################################
+
+
+EMUSRC = $(SRC)/emu
+EMUOBJ = $(OBJ)/emu
+
+EMUAUDIO = $(EMUOBJ)/audio
+EMUDRIVERS = $(EMUOBJ)/drivers
+EMULAYOUT = $(EMUOBJ)/layout
+EMUMACHINE = $(EMUOBJ)/machine
+EMUIMAGEDEV = $(EMUOBJ)/imagedev
+EMUVIDEO = $(EMUOBJ)/video
+
+OBJDIRS += \
+ $(EMUOBJ)/cpu \
+ $(EMUOBJ)/sound \
+ $(EMUOBJ)/debug \
+ $(EMUOBJ)/debugint \
+ $(EMUOBJ)/audio \
+ $(EMUOBJ)/drivers \
+ $(EMUOBJ)/machine \
+ $(EMUOBJ)/layout \
+ $(EMUOBJ)/imagedev \
+ $(EMUOBJ)/video \
+
+OSDSRC = $(SRC)/osd
+OSDOBJ = $(OBJ)/osd
+
+OBJDIRS += \
+ $(OSDOBJ)
+
+
+#-------------------------------------------------
+# emulator core objects
+#-------------------------------------------------
+
+EMUOBJS = \
+ $(EMUOBJ)/hashfile.o \
+ $(EMUOBJ)/addrmap.o \
+ $(EMUOBJ)/attotime.o \
+ $(EMUOBJ)/audit.o \
+ $(EMUOBJ)/cheat.o \
+ $(EMUOBJ)/clifront.o \
+ $(EMUOBJ)/config.o \
+ $(EMUOBJ)/cothread.o \
+ $(EMUOBJ)/crsshair.o \
+ $(EMUOBJ)/debugger.o \
+ $(EMUOBJ)/delegate.o \
+ $(EMUOBJ)/devcb.o \
+ $(EMUOBJ)/devcpu.o \
+ $(EMUOBJ)/device.o \
+ $(EMUOBJ)/devimage.o \
+ $(EMUOBJ)/devlegcy.o \
+ $(EMUOBJ)/didisasm.o \
+ $(EMUOBJ)/diexec.o \
+ $(EMUOBJ)/diimage.o \
+ $(EMUOBJ)/dimemory.o \
+ $(EMUOBJ)/dinvram.o \
+ $(EMUOBJ)/dirtc.o \
+ $(EMUOBJ)/dislot.o \
+ $(EMUOBJ)/disound.o \
+ $(EMUOBJ)/distate.o \
+ $(EMUOBJ)/drawgfx.o \
+ $(EMUOBJ)/driver.o \
+ $(EMUOBJ)/emualloc.o \
+ $(EMUOBJ)/emucore.o \
+ $(EMUOBJ)/emuopts.o \
+ $(EMUOBJ)/emupal.o \
+ $(EMUOBJ)/fileio.o \
+ $(EMUOBJ)/hash.o \
+ $(EMUOBJ)/image.o \
+ $(EMUOBJ)/info.o \
+ $(EMUOBJ)/input.o \
+ $(EMUOBJ)/ioport.o \
+ $(EMUOBJ)/mame.o \
+ $(EMUOBJ)/machine.o \
+ $(EMUOBJ)/mconfig.o \
+ $(EMUOBJ)/memory.o \
+ $(EMUOBJ)/output.o \
+ $(EMUOBJ)/render.o \
+ $(EMUOBJ)/rendfont.o \
+ $(EMUOBJ)/rendlay.o \
+ $(EMUOBJ)/rendutil.o \
+ $(EMUOBJ)/romload.o \
+ $(EMUOBJ)/save.o \
+ $(EMUOBJ)/schedule.o \
+ $(EMUOBJ)/screen.o \
+ $(EMUOBJ)/softlist.o \
+ $(EMUOBJ)/sound.o \
+ $(EMUOBJ)/speaker.o \
+ $(EMUOBJ)/tilemap.o \
+ $(EMUOBJ)/timer.o \
+ $(EMUOBJ)/ui.o \
+ $(EMUOBJ)/uigfx.o \
+ $(EMUOBJ)/uiimage.o \
+ $(EMUOBJ)/uiinput.o \
+ $(EMUOBJ)/uiswlist.o \
+ $(EMUOBJ)/uimenu.o \
+ $(EMUOBJ)/validity.o \
+ $(EMUOBJ)/video.o \
+ $(EMUOBJ)/watchdog.o \
+ $(EMUOBJ)/debug/debugcmd.o \
+ $(EMUOBJ)/debug/debugcon.o \
+ $(EMUOBJ)/debug/debugcpu.o \
+ $(EMUOBJ)/debug/debughlp.o \
+ $(EMUOBJ)/debug/debugvw.o \
+ $(EMUOBJ)/debug/dvdisasm.o \
+ $(EMUOBJ)/debug/dvmemory.o \
+ $(EMUOBJ)/debug/dvstate.o \
+ $(EMUOBJ)/debug/dvtext.o \
+ $(EMUOBJ)/debug/express.o \
+ $(EMUOBJ)/debug/textbuf.o \
+ $(EMUOBJ)/debugint/debugint.o \
+ $(EMUOBJ)/profiler.o \
+ $(OSDOBJ)/osdepend.o
+
+EMUSOUNDOBJS = \
+ $(EMUOBJ)/sound/filter.o \
+ $(EMUOBJ)/sound/flt_vol.o \
+ $(EMUOBJ)/sound/flt_rc.o \
+ $(EMUOBJ)/sound/wavwrite.o \
+
+EMUAUDIOOBJS = \
+ $(EMUAUDIO)/generic.o \
+
+EMUDRIVEROBJS = \
+ $(EMUDRIVERS)/empty.o \
+
+EMUMACHINEOBJS = \
+ $(EMUMACHINE)/53c810.o \
+ $(EMUMACHINE)/6522via.o \
+ $(EMUMACHINE)/6525tpi.o \
+ $(EMUMACHINE)/6526cia.o \
+ $(EMUMACHINE)/6532riot.o \
+ $(EMUMACHINE)/6821pia.o \
+ $(EMUMACHINE)/6840ptm.o \
+ $(EMUMACHINE)/6850acia.o \
+ $(EMUMACHINE)/68681.o \
+ $(EMUMACHINE)/74123.o \
+ $(EMUMACHINE)/74148.o \
+ $(EMUMACHINE)/74153.o \
+ $(EMUMACHINE)/74181.o \
+ $(EMUMACHINE)/7474.o \
+ $(EMUMACHINE)/8042kbdc.o \
+ $(EMUMACHINE)/8237dma.o \
+ $(EMUMACHINE)/8255ppi.o \
+ $(EMUMACHINE)/8257dma.o \
+ $(EMUMACHINE)/adc0808.o \
+ $(EMUMACHINE)/adc083x.o \
+ $(EMUMACHINE)/adc1038.o \
+ $(EMUMACHINE)/adc1213x.o \
+ $(EMUMACHINE)/am53cf96.o \
+ $(EMUMACHINE)/am8530h.o \
+ $(EMUMACHINE)/at28c16.o \
+ $(EMUMACHINE)/cdp1852.o \
+ $(EMUMACHINE)/cdp1871.o \
+ $(EMUMACHINE)/com8116.o \
+ $(EMUMACHINE)/cr589.o \
+ $(EMUMACHINE)/ctronics.o \
+ $(EMUMACHINE)/ds1302.o \
+ $(EMUMACHINE)/ds2401.o \
+ $(EMUMACHINE)/ds2404.o \
+ $(EMUMACHINE)/e0516.o \
+ $(EMUMACHINE)/eeprom.o \
+ $(EMUMACHINE)/er2055.o \
+ $(EMUMACHINE)/f3853.o \
+ $(EMUMACHINE)/generic.o \
+ $(EMUMACHINE)/i2cmem.o \
+ $(EMUMACHINE)/i8155.o \
+ $(EMUMACHINE)/i8212.o \
+ $(EMUMACHINE)/i8214.o \
+ $(EMUMACHINE)/i8243.o \
+ $(EMUMACHINE)/i8255.o \
+ $(EMUMACHINE)/i8355.o \
+ $(EMUMACHINE)/idectrl.o \
+ $(EMUMACHINE)/ins8154.o \
+ $(EMUMACHINE)/ins8250.o \
+ $(EMUMACHINE)/intelfsh.o \
+ $(EMUMACHINE)/jvsdev.o \
+ $(EMUMACHINE)/jvshost.o \
+ $(EMUMACHINE)/k033906.o \
+ $(EMUMACHINE)/k053252.o \
+ $(EMUMACHINE)/k056230.o \
+ $(EMUMACHINE)/latch8.o \
+ $(EMUMACHINE)/ldcore.o \
+ $(EMUMACHINE)/ldpr8210.o \
+ $(EMUMACHINE)/ldv1000.o \
+ $(EMUMACHINE)/ldvp931.o \
+ $(EMUMACHINE)/matsucd.o \
+ $(EMUMACHINE)/mb14241.o \
+ $(EMUMACHINE)/mb3773.o \
+ $(EMUMACHINE)/mb87078.o \
+ $(EMUMACHINE)/mc146818.o \
+ $(EMUMACHINE)/mc6852.o \
+ $(EMUMACHINE)/mc68901.o \
+ $(EMUMACHINE)/mccs1850.o \
+ $(EMUMACHINE)/mm74c922.o \
+ $(EMUMACHINE)/microtch.o \
+ $(EMUMACHINE)/mos6529.o \
+ $(EMUMACHINE)/msm5832.o \
+ $(EMUMACHINE)/msm58321.o \
+ $(EMUMACHINE)/msm6242.o \
+ $(EMUMACHINE)/nmc9306.o \
+ $(EMUMACHINE)/nvram.o \
+ $(EMUMACHINE)/pc16552d.o \
+ $(EMUMACHINE)/pci.o \
+ $(EMUMACHINE)/pd4990a.o \
+ $(EMUMACHINE)/pic8259.o \
+ $(EMUMACHINE)/pit8253.o \
+ $(EMUMACHINE)/ram.o \
+ $(EMUMACHINE)/roc10937.o \
+ $(EMUMACHINE)/rp5c01.o \
+ $(EMUMACHINE)/rp5c15.o \
+ $(EMUMACHINE)/rp5h01.o \
+ $(EMUMACHINE)/rtc65271.o \
+ $(EMUMACHINE)/s3c2400.o \
+ $(EMUMACHINE)/s3c2410.o \
+ $(EMUMACHINE)/s3c2440.o \
+ $(EMUMACHINE)/scsi.o \
+ $(EMUMACHINE)/scsicd.o \
+ $(EMUMACHINE)/scsidev.o \
+ $(EMUMACHINE)/scsihd.o \
+ $(EMUMACHINE)/secflash.o \
+ $(EMUMACHINE)/smc91c9x.o \
+ $(EMUMACHINE)/timekpr.o \
+ $(EMUMACHINE)/tmp68301.o \
+ $(EMUMACHINE)/tms6100.o \
+ $(EMUMACHINE)/upd1990a.o \
+ $(EMUMACHINE)/upd4701.o \
+ $(EMUMACHINE)/upd7201.o \
+ $(EMUMACHINE)/wd17xx.o \
+ $(EMUMACHINE)/wd33c93.o \
+ $(EMUMACHINE)/x2212.o \
+ $(EMUMACHINE)/x76f041.o \
+ $(EMUMACHINE)/x76f100.o \
+ $(EMUMACHINE)/z80ctc.o \
+ $(EMUMACHINE)/z80dart.o \
+ $(EMUMACHINE)/z80dma.o \
+ $(EMUMACHINE)/z80pio.o \
+ $(EMUMACHINE)/z80sio.o \
+ $(EMUMACHINE)/z80sti.o \
+ $(EMUMACHINE)/z8536.o \
+
+EMUVIDEOOBJS = \
+ $(EMUVIDEO)/cdp1861.o \
+ $(EMUVIDEO)/cdp1862.o \
+ $(EMUVIDEO)/crt9007.o \
+ $(EMUVIDEO)/crt9021.o \
+ $(EMUVIDEO)/crt9212.o \
+ $(EMUVIDEO)/dm9368.o \
+ $(EMUVIDEO)/generic.o \
+ $(EMUVIDEO)/hd44102.o \
+ $(EMUVIDEO)/hd61830.o \
+ $(EMUVIDEO)/hd63484.o \
+ $(EMUVIDEO)/i8275.o \
+ $(EMUVIDEO)/k053250.o \
+ $(EMUVIDEO)/mc6845.o \
+ $(EMUVIDEO)/msm6255.o \
+ $(EMUVIDEO)/pc_vga.o \
+ $(EMUVIDEO)/poly.o \
+ $(EMUVIDEO)/psx.o \
+ $(EMUVIDEO)/resnet.o \
+ $(EMUVIDEO)/rgbutil.o \
+ $(EMUVIDEO)/s2636.o \
+ $(EMUVIDEO)/saa5050.o \
+ $(EMUVIDEO)/sed1330.o \
+ $(EMUVIDEO)/tlc34076.o \
+ $(EMUVIDEO)/tms34061.o \
+ $(EMUVIDEO)/tms9927.o \
+ $(EMUVIDEO)/tms9928a.o \
+ $(EMUVIDEO)/upd3301.o \
+ $(EMUVIDEO)/v9938.o \
+ $(EMUVIDEO)/vector.o \
+ $(EMUVIDEO)/voodoo.o \
+
+EMUIMAGEDEVOBJS = \
+ $(EMUIMAGEDEV)/bitbngr.o \
+ $(EMUIMAGEDEV)/cartslot.o \
+ $(EMUIMAGEDEV)/cassette.o \
+ $(EMUIMAGEDEV)/chd_cd.o \
+ $(EMUIMAGEDEV)/flopdrv.o \
+ $(EMUIMAGEDEV)/floppy.o \
+ $(EMUIMAGEDEV)/harddriv.o \
+ $(EMUIMAGEDEV)/multcart.o \
+ $(EMUIMAGEDEV)/printer.o \
+ $(EMUIMAGEDEV)/snapquik.o \
+
+
+LIBEMUOBJS = $(EMUOBJS) $(EMUSOUNDOBJS) $(EMUAUDIOOBJS) $(EMUDRIVEROBJS) $(EMUMACHINEOBJS) $(EMUIMAGEDEVOBJS) $(EMUVIDEOOBJS)
+
+$(LIBEMU): $(LIBEMUOBJS)
+
+
+
+#-------------------------------------------------
+# CPU core objects
+#-------------------------------------------------
+
+include $(EMUSRC)/cpu/cpu.mak
+
+$(LIBCPU): $(CPUOBJS)
+
+$(LIBDASM): $(DASMOBJS)
+
+
+
+#-------------------------------------------------
+# sound core objects
+#-------------------------------------------------
+
+include $(EMUSRC)/sound/sound.mak
+
+$(LIBSOUND): $(SOUNDOBJS)
+
+
+
+#-------------------------------------------------
+# additional dependencies
+#-------------------------------------------------
+
+$(EMUOBJ)/rendfont.o: $(EMUOBJ)/uismall.fh
+
+$(EMUOBJ)/video.o: $(EMUSRC)/rendersw.c
+$(EMUVIDEO)/v9938.o: $(EMUSRC)/video/v9938mod.c
+
+$(EMUMACHINE)/s3c2400.o: $(EMUSRC)/machine/s3c24xx.c
+$(EMUMACHINE)/s3c2410.o: $(EMUSRC)/machine/s3c24xx.c
+$(EMUMACHINE)/s3c2440.o: $(EMUSRC)/machine/s3c24xx.c
+
+
+#-------------------------------------------------
+# core layouts
+#-------------------------------------------------
+
+$(EMUOBJ)/rendlay.o: $(EMULAYOUT)/dualhovu.lh \
+ $(EMULAYOUT)/dualhsxs.lh \
+ $(EMULAYOUT)/dualhuov.lh \
+ $(EMULAYOUT)/horizont.lh \
+ $(EMULAYOUT)/triphsxs.lh \
+ $(EMULAYOUT)/quadhsxs.lh \
+ $(EMULAYOUT)/vertical.lh \
+ $(EMULAYOUT)/ho20ffff.lh \
+ $(EMULAYOUT)/ho2eff2e.lh \
+ $(EMULAYOUT)/ho4f893d.lh \
+ $(EMULAYOUT)/ho88ffff.lh \
+ $(EMULAYOUT)/hoa0a0ff.lh \
+ $(EMULAYOUT)/hoffe457.lh \
+ $(EMULAYOUT)/hoffff20.lh \
+ $(EMULAYOUT)/voffff20.lh \
+ $(EMULAYOUT)/lcd.lh \
+ $(EMULAYOUT)/lcd_rot.lh \
+ $(EMULAYOUT)/noscreens.lh \
+
+$(EMUOBJ)/video.o: $(EMULAYOUT)/snap.lh
diff --git a/trunk/src/emu/emualloc.c b/trunk/src/emu/emualloc.c
new file mode 100644
index 00000000000..a091add4b67
--- /dev/null
+++ b/trunk/src/emu/emualloc.c
@@ -0,0 +1,607 @@
+/***************************************************************************
+
+ emualloc.c
+
+ Memory allocation helpers for the core 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.
+
+***************************************************************************/
+
+#include "emucore.h"
+#include "coreutil.h"
+
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define LOG_ALLOCS (0)
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// align all allocated memory to this size
+const int memory_align = 16;
+
+// number of memory_entries to allocate in a block
+const int memory_block_alloc_chunk = 256;
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+// enable deletion
+#undef delete
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// this struct is allocated in pools to track memory allocations
+// it must be a POD type!!
+class memory_entry
+{
+public:
+ memory_entry * m_next; // link to the next entry
+ memory_entry * m_prev; // link to the previous entry
+ size_t m_size; // size of the allocation (not including this header)
+ void * m_base; // base of the allocation
+ const char * m_file; // file the allocation was made from
+ int m_line; // line number within that file
+ UINT64 m_id; // unique id
+
+ static const int k_hash_prime = 6151;
+
+ static UINT64 s_curid; // current ID
+ static osd_lock * s_lock; // lock for managing the list
+ static bool s_lock_alloc; // set to true temporarily during lock allocation
+ static bool s_tracking; // set to true when tracking is live
+ static memory_entry *s_hash[k_hash_prime];// hash table based on pointer
+ static memory_entry *s_freehead; // pointer to the head of the free list
+
+ static memory_entry *allocate(size_t size, void *base, const char *file, int line);
+ static memory_entry *find(void *ptr);
+ static void release(memory_entry *entry);
+ static void report_unfreed();
+
+private:
+ static void acquire_lock();
+ static void release_lock();
+};
+
+
+
+//**************************************************************************
+// GLOBALS
+//**************************************************************************
+
+// global resource pool to handle allocations outside of the emulator context
+resource_pool global_resource_pool(6151);
+
+// dummy zeromem object
+const zeromem_t zeromem = { };
+
+// globals for memory_entry
+UINT64 memory_entry::s_curid = 1;
+osd_lock *memory_entry::s_lock = NULL;
+bool memory_entry::s_lock_alloc = false;
+bool memory_entry::s_tracking = false;
+memory_entry *memory_entry::s_hash[memory_entry::k_hash_prime] = { NULL };
+memory_entry *memory_entry::s_freehead = NULL;
+
+
+
+//**************************************************************************
+// GLOBAL HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// malloc_file_line - allocate memory with file
+// and line number information
+//-------------------------------------------------
+
+void *malloc_file_line(size_t size, const char *file, int line)
+{
+ // allocate the memory and fail if we can't
+ void *result = osd_malloc(size);
+ if (result == NULL)
+ return NULL;
+
+ // add a new entry
+ memory_entry::allocate(size, result, file, line);
+
+#ifdef MAME_DEBUG
+ // randomize the memory
+ rand_memory(result, size);
+#endif
+
+ return result;
+}
+
+
+//-------------------------------------------------
+// malloc_array_file_line - allocate memory with
+// file and line number information, and a hint
+// that this object is an array
+//-------------------------------------------------
+
+void *malloc_array_file_line(size_t size, const char *file, int line)
+{
+ // allocate the memory and fail if we can't
+ void *result = osd_malloc_array(size);
+ if (result == NULL)
+ return NULL;
+
+ // add a new entry
+ memory_entry::allocate(size, result, file, line);
+
+#ifdef MAME_DEBUG
+ // randomize the memory
+ rand_memory(result, size);
+#endif
+
+ return result;
+}
+
+
+//-------------------------------------------------
+// free_file_line - free memory with file
+// and line number information
+//-------------------------------------------------
+
+void free_file_line(void *memory, const char *file, int line)
+{
+ // find the memory entry
+ memory_entry *entry = memory_entry::find(memory);
+
+ // warn about untracked frees
+ if (entry == NULL)
+ {
+ fprintf(stderr, "Error: attempt to free untracked memory in %s(%d)!\n", file, line);
+ osd_break_into_debugger("Error: attempt to free untracked memory");
+ return;
+ }
+
+#ifdef MAME_DEBUG
+ // clear memory to a bogus value
+ memset(memory, 0xfc, entry->m_size);
+#endif
+
+ // free the entry and the memory
+ memory_entry::release(entry);
+ osd_free(memory);
+}
+
+
+//-------------------------------------------------
+// dump_unfreed_mem - called from the exit path
+// of any code that wants to check for unfreed
+// memory
+//-------------------------------------------------
+
+void track_memory(bool track)
+{
+ memory_entry::s_tracking = track;
+}
+
+
+//-------------------------------------------------
+// dump_unfreed_mem - called from the exit path
+// of any code that wants to check for unfreed
+// memory
+//-------------------------------------------------
+
+void dump_unfreed_mem()
+{
+#ifdef MAME_DEBUG
+ memory_entry::report_unfreed();
+#endif
+}
+
+
+
+//**************************************************************************
+// RESOURCE POOL
+//**************************************************************************
+
+//-------------------------------------------------
+// resource_pool - constructor for a new resource
+// pool
+//-------------------------------------------------
+
+resource_pool::resource_pool(int hash_size)
+ : m_hash_size(hash_size),
+ m_listlock(osd_lock_alloc()),
+ m_hash(new resource_pool_item *[hash_size]),
+ m_ordered_head(NULL),
+ m_ordered_tail(NULL)
+{
+ memset(m_hash, 0, hash_size * sizeof(m_hash[0]));
+}
+
+
+//-------------------------------------------------
+// ~resource_pool - destructor for a resource
+// pool; make sure all tracked objects are
+// deleted
+//-------------------------------------------------
+
+resource_pool::~resource_pool()
+{
+ clear();
+ if (m_listlock != NULL)
+ osd_lock_free(m_listlock);
+ delete[] m_hash;
+}
+
+
+//-------------------------------------------------
+// add - add a new item to the resource pool
+//-------------------------------------------------
+
+void resource_pool::add(resource_pool_item &item)
+{
+ osd_lock_acquire(m_listlock);
+
+ // insert into hash table
+ int hashval = reinterpret_cast<FPTR>(item.m_ptr) % m_hash_size;
+ item.m_next = m_hash[hashval];
+ m_hash[hashval] = &item;
+
+ // fetch the ID of this item's pointer; some implementations put hidden data
+ // before, so if we don't find it, check 4 bytes ahead
+ memory_entry *entry = memory_entry::find(item.m_ptr);
+ if (entry == NULL)
+ entry = memory_entry::find(reinterpret_cast<UINT8 *>(item.m_ptr) - sizeof(size_t));
+ assert(entry != NULL);
+ item.m_id = entry->m_id;
+ if (LOG_ALLOCS)
+ fprintf(stderr, "#%06d, add %d bytes (%s:%d)\n", (UINT32)entry->m_id, static_cast<UINT32>(entry->m_size), entry->m_file, (int)entry->m_line);
+
+ // find the entry to insert after
+ resource_pool_item *insert_after;
+ for (insert_after = m_ordered_tail; insert_after != NULL; insert_after = insert_after->m_ordered_prev)
+ if (insert_after->m_id < item.m_id)
+ break;
+
+ // insert into the appropriate spot
+ if (insert_after != NULL)
+ {
+ item.m_ordered_next = insert_after->m_ordered_next;
+ if (item.m_ordered_next != NULL)
+ item.m_ordered_next->m_ordered_prev = &item;
+ else
+ m_ordered_tail = &item;
+ item.m_ordered_prev = insert_after;
+ insert_after->m_ordered_next = &item;
+ }
+ else
+ {
+ item.m_ordered_next = m_ordered_head;
+ if (item.m_ordered_next != NULL)
+ item.m_ordered_next->m_ordered_prev = &item;
+ else
+ m_ordered_tail = &item;
+ item.m_ordered_prev = NULL;
+ m_ordered_head = &item;
+ }
+
+ osd_lock_release(m_listlock);
+}
+
+
+//-------------------------------------------------
+// remove - remove a specific item from the
+// resource pool
+//-------------------------------------------------
+
+void resource_pool::remove(void *ptr)
+{
+ // ignore NULLs
+ if (ptr == NULL)
+ return;
+
+ // search for the item
+ osd_lock_acquire(m_listlock);
+
+ int hashval = reinterpret_cast<FPTR>(ptr) % m_hash_size;
+ for (resource_pool_item **scanptr = &m_hash[hashval]; *scanptr != NULL; scanptr = &(*scanptr)->m_next)
+
+ // must match the pointer
+ if ((*scanptr)->m_ptr == ptr)
+ {
+ // remove from hash table
+ resource_pool_item *deleteme = *scanptr;
+ *scanptr = deleteme->m_next;
+
+ // remove from ordered list
+ if (deleteme->m_ordered_prev != NULL)
+ deleteme->m_ordered_prev->m_ordered_next = deleteme->m_ordered_next;
+ else
+ m_ordered_head = deleteme->m_ordered_next;
+ if (deleteme->m_ordered_next != NULL)
+ deleteme->m_ordered_next->m_ordered_prev = deleteme->m_ordered_prev;
+ else
+ m_ordered_tail = deleteme->m_ordered_prev;
+
+ // delete the object and break
+ if (LOG_ALLOCS)
+ fprintf(stderr, "#%06d, delete %d bytes\n", (UINT32)deleteme->m_id, static_cast<UINT32>(deleteme->m_size));
+ delete deleteme;
+ break;
+ }
+
+ osd_lock_release(m_listlock);
+}
+
+
+//-------------------------------------------------
+// find - find a specific item in the resource
+// pool
+//-------------------------------------------------
+
+resource_pool_item *resource_pool::find(void *ptr)
+{
+ // search for the item
+ osd_lock_acquire(m_listlock);
+
+ int hashval = reinterpret_cast<FPTR>(ptr) % m_hash_size;
+ resource_pool_item *item;
+ for (item = m_hash[hashval]; item != NULL; item = item->m_next)
+ if (item->m_ptr == ptr)
+ break;
+
+ osd_lock_release(m_listlock);
+
+ return item;
+}
+
+
+//-------------------------------------------------
+// contains - return true if given ptr is
+// contained by one of the objects in the pool
+//-------------------------------------------------
+
+bool resource_pool::contains(void *_ptrstart, void *_ptrend)
+{
+ UINT8 *ptrstart = reinterpret_cast<UINT8 *>(_ptrstart);
+ UINT8 *ptrend = reinterpret_cast<UINT8 *>(_ptrend);
+
+ // search for the item
+ osd_lock_acquire(m_listlock);
+
+ resource_pool_item *item = NULL;
+ for (item = m_ordered_head; item != NULL; item = item->m_ordered_next)
+ {
+ UINT8 *objstart = reinterpret_cast<UINT8 *>(item->m_ptr);
+ UINT8 *objend = objstart + item->m_size;
+ if (ptrstart >= objstart && ptrend <= objend)
+ goto found;
+ }
+
+found:
+ osd_lock_release(m_listlock);
+
+ return (item != NULL);
+}
+
+
+//-------------------------------------------------
+// clear - remove all items from a resource pool
+//-------------------------------------------------
+
+void resource_pool::clear()
+{
+ osd_lock_acquire(m_listlock);
+
+ // important: delete from earliest to latest; this allows objects to clean up after
+ // themselves if they wish
+ while (m_ordered_head != NULL)
+ remove(m_ordered_head->m_ptr);
+
+ osd_lock_release(m_listlock);
+}
+
+
+
+//**************************************************************************
+// MEMORY ENTRY
+//**************************************************************************
+
+//-------------------------------------------------
+// acquire_lock - acquire the memory entry lock,
+// creating a new one if needed
+//-------------------------------------------------
+
+void memory_entry::acquire_lock()
+{
+ // allocate a lock on first usage
+ // note that osd_lock_alloc() may re-enter this path, so protect against recursion!
+ if (s_lock == NULL)
+ {
+ if (s_lock_alloc)
+ return;
+ s_lock_alloc = true;
+ s_lock = osd_lock_alloc();
+ s_lock_alloc = false;
+ }
+ osd_lock_acquire(s_lock);
+}
+
+
+//-------------------------------------------------
+// release_lock - release the memory entry lock
+//-------------------------------------------------
+
+void memory_entry::release_lock()
+{
+ osd_lock_release(s_lock);
+}
+
+
+//-------------------------------------------------
+// allocate - allocate a new memory entry
+//-------------------------------------------------
+
+memory_entry *memory_entry::allocate(size_t size, void *base, const char *file, int line)
+{
+ acquire_lock();
+
+ // if we're out of free entries, allocate a new chunk
+ if (s_freehead == NULL)
+ {
+ // create a new chunk, and fail if we can't
+ memory_entry *entry = reinterpret_cast<memory_entry *>(osd_malloc_array(memory_block_alloc_chunk * sizeof(memory_entry)));
+ if (entry == NULL)
+ {
+ release_lock();
+ return NULL;
+ }
+
+ // add all the entries to the list
+ for (int entrynum = 0; entrynum < memory_block_alloc_chunk; entrynum++)
+ {
+ entry->m_next = s_freehead;
+ s_freehead = entry++;
+ }
+ }
+
+ // grab a free entry
+ memory_entry *entry = s_freehead;
+ s_freehead = entry->m_next;
+
+ // populate it
+ entry->m_size = size;
+ entry->m_base = base;
+ entry->m_file = s_tracking ? file : NULL;
+ entry->m_line = s_tracking ? line : 0;
+ entry->m_id = s_curid++;
+ if (LOG_ALLOCS)
+ fprintf(stderr, "#%06d, alloc %d bytes (%s:%d)\n", (UINT32)entry->m_id, static_cast<UINT32>(entry->m_size), entry->m_file, (int)entry->m_line);
+
+ // add it to the alloc list
+ int hashval = reinterpret_cast<FPTR>(base) % k_hash_prime;
+ entry->m_next = s_hash[hashval];
+ if (entry->m_next != NULL)
+ entry->m_next->m_prev = entry;
+ entry->m_prev = NULL;
+ s_hash[hashval] = entry;
+
+ release_lock();
+ return entry;
+}
+
+
+//-------------------------------------------------
+// find - find a memory entry
+//-------------------------------------------------
+
+memory_entry *memory_entry::find(void *ptr)
+{
+ // NULL maps to nothing
+ if (ptr == NULL)
+ return NULL;
+
+ // scan the list under the lock
+ acquire_lock();
+
+ int hashval = reinterpret_cast<FPTR>(ptr) % k_hash_prime;
+ memory_entry *entry;
+ for (entry = s_hash[hashval]; entry != NULL; entry = entry->m_next)
+ if (entry->m_base == ptr)
+ break;
+
+ release_lock();
+ return entry;
+}
+
+
+//-------------------------------------------------
+// release - release a memory entry
+//-------------------------------------------------
+
+void memory_entry::release(memory_entry *entry)
+{
+ acquire_lock();
+
+ // remove ourselves from the alloc list
+ int hashval = reinterpret_cast<FPTR>(entry->m_base) % k_hash_prime;
+ if (entry->m_prev != NULL)
+ entry->m_prev->m_next = entry->m_next;
+ else
+ s_hash[hashval] = entry->m_next;
+ if (entry->m_next != NULL)
+ entry->m_next->m_prev = entry->m_prev;
+
+ // add ourself to the free list
+ entry->m_next = s_freehead;
+ s_freehead = entry;
+
+ release_lock();
+}
+
+
+//-------------------------------------------------
+// report_unfreed - print a list of unfreed
+// memory to the target file
+//-------------------------------------------------
+
+void memory_entry::report_unfreed()
+{
+ acquire_lock();
+
+ // check for leaked memory
+ UINT32 total = 0;
+
+ for (int hashnum = 0; hashnum < k_hash_prime; hashnum++)
+ for (memory_entry *entry = s_hash[hashnum]; entry != NULL; entry = entry->m_next)
+ if (entry->m_file != NULL)
+ {
+ if (total == 0)
+ fprintf(stderr, "--- memory leak warning ---\n");
+ total += entry->m_size;
+ fprintf(stderr, "#%06d, nofree %d bytes (%s:%d)\n", (UINT32)entry->m_id, static_cast<UINT32>(entry->m_size), entry->m_file, (int)entry->m_line);
+ }
+
+ release_lock();
+
+ if (total > 0)
+ fprintf(stderr, "a total of %d bytes were not freed\n", total);
+}
diff --git a/trunk/src/emu/emualloc.h b/trunk/src/emu/emualloc.h
new file mode 100644
index 00000000000..84a6d864ed3
--- /dev/null
+++ b/trunk/src/emu/emualloc.h
@@ -0,0 +1,336 @@
+/***************************************************************************
+
+ emualloc.h
+
+ Memory allocation helpers for the core 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 __EMUALLOC_H__
+#define __EMUALLOC_H__
+
+#include <new>
+#include "osdcore.h"
+
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+// set to 1 to track memory allocated by emualloc.h itself as well
+#define TRACK_SELF_MEMORY (0)
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+// self-allocation helpers
+#if TRACK_SELF_MEMORY
+#define EMUALLOC_SELF_NEW new(__FILE__, __LINE__)
+#else
+#define EMUALLOC_SELF_NEW new
+#endif
+
+// pool allocation helpers
+#define pool_alloc(_pool, _type) (_pool).add_object(new(__FILE__, __LINE__) _type)
+#define pool_alloc_clear(_pool, _type) (_pool).add_object(new(__FILE__, __LINE__, zeromem) _type)
+#define pool_alloc_array(_pool, _type, _num) (_pool).add_array(new(__FILE__, __LINE__) _type[_num], (_num))
+#define pool_alloc_array_clear(_pool, _type, _num) (_pool).add_array(new(__FILE__, __LINE__, zeromem) _type[_num], (_num))
+#define pool_free(_pool, v) (_pool).remove(v)
+
+// global allocation helpers
+#define global_alloc(_type) pool_alloc(global_resource_pool, _type)
+#define global_alloc_clear(_type) pool_alloc_clear(global_resource_pool, _type)
+#define global_alloc_array(_type, _num) pool_alloc_array(global_resource_pool, _type, _num)
+#define global_alloc_array_clear(_type, _num) pool_alloc_array_clear(global_resource_pool, _type, _num)
+#define global_free(v) pool_free(global_resource_pool, v)
+
+
+
+//**************************************************************************
+// FUNCTION PROTOTYPES
+//**************************************************************************
+
+// allocate memory with file and line number information
+void *malloc_file_line(size_t size, const char *file, int line);
+void *malloc_array_file_line(size_t size, const char *file, int line);
+
+// free memory with file and line number information
+void free_file_line(void *memory, const char *file, int line);
+
+// called from the exit path of any code that wants to check for unfreed memory
+void track_memory(bool track);
+void dump_unfreed_mem();
+
+
+
+//**************************************************************************
+// INLINE FUNCTIONS
+//**************************************************************************
+
+// zeromem_t is a dummy class used to tell new to zero memory after allocation
+class zeromem_t { };
+
+
+// standard new/delete operators (try to avoid using)
+ATTR_FORCE_INLINE inline void *operator new(std::size_t size) throw (std::bad_alloc)
+{
+ void *result = malloc_file_line(size, NULL, 0);
+ if (result == NULL)
+ throw std::bad_alloc();
+ return result;
+}
+
+ATTR_FORCE_INLINE inline void *operator new[](std::size_t size) throw (std::bad_alloc)
+{
+ void *result = malloc_array_file_line(size, NULL, 0);
+ if (result == NULL)
+ throw std::bad_alloc();
+ return result;
+}
+
+ATTR_FORCE_INLINE inline void operator delete(void *ptr) throw()
+{
+ if (ptr != NULL)
+ free_file_line(ptr, NULL, 0);
+}
+
+ATTR_FORCE_INLINE inline void operator delete[](void *ptr) throw()
+{
+ if (ptr != NULL)
+ free_file_line(ptr, NULL, 0);
+}
+
+
+// file/line new/delete operators
+ATTR_FORCE_INLINE inline void *operator new(std::size_t size, const char *file, int line) throw (std::bad_alloc)
+{
+ void *result = malloc_file_line(size, file, line);
+ if (result == NULL)
+ throw std::bad_alloc();
+ return result;
+}
+
+ATTR_FORCE_INLINE inline void *operator new[](std::size_t size, const char *file, int line) throw (std::bad_alloc)
+{
+ void *result = malloc_array_file_line(size, file, line);
+ if (result == NULL)
+ throw std::bad_alloc();
+ return result;
+}
+
+ATTR_FORCE_INLINE inline void operator delete(void *ptr, const char *file, int line)
+{
+ if (ptr != NULL)
+ free_file_line(ptr, file, line);
+}
+
+ATTR_FORCE_INLINE inline void operator delete[](void *ptr, const char *file, int line)
+{
+ if (ptr != NULL)
+ free_file_line(ptr, file, line);
+}
+
+
+// file/line new/delete operators with zeroing
+ATTR_FORCE_INLINE inline void *operator new(std::size_t size, const char *file, int line, const zeromem_t &) throw (std::bad_alloc)
+{
+ void *result = malloc_file_line(size, file, line);
+ if (result == NULL)
+ throw std::bad_alloc();
+ memset(result, 0, size);
+ return result;
+}
+
+ATTR_FORCE_INLINE inline void *operator new[](std::size_t size, const char *file, int line, const zeromem_t &) throw (std::bad_alloc)
+{
+ void *result = malloc_array_file_line(size, file, line);
+ if (result == NULL)
+ throw std::bad_alloc();
+ memset(result, 0, size);
+ return result;
+}
+
+ATTR_FORCE_INLINE inline void operator delete(void *ptr, const char *file, int line, const zeromem_t &)
+{
+ if (ptr != NULL)
+ free_file_line(ptr, file, line);
+}
+
+ATTR_FORCE_INLINE inline void operator delete[](void *ptr, const char *file, int line, const zeromem_t &)
+{
+ if (ptr != NULL)
+ free_file_line(ptr, file, line);
+}
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// resource_pool_item is a base class for items that are tracked by a resource pool
+class resource_pool_item
+{
+private:
+ resource_pool_item(const resource_pool_item &);
+ resource_pool_item &operator=(const resource_pool_item &);
+
+public:
+ resource_pool_item(void *ptr, size_t size)
+ : m_next(NULL),
+ m_ordered_next(NULL),
+ m_ordered_prev(NULL),
+ m_ptr(ptr),
+ m_size(size),
+ m_id(~(UINT64)0) { }
+ virtual ~resource_pool_item() { }
+
+ resource_pool_item * m_next;
+ resource_pool_item * m_ordered_next;
+ resource_pool_item * m_ordered_prev;
+ void * m_ptr;
+ size_t m_size;
+ UINT64 m_id;
+};
+
+
+// a resource_pool_object is a simple object wrapper for the templatized type
+template<class _ObjectClass>
+class resource_pool_object : public resource_pool_item
+{
+private:
+ resource_pool_object<_ObjectClass>(const resource_pool_object<_ObjectClass> &);
+ resource_pool_object<_ObjectClass> &operator=(const resource_pool_object<_ObjectClass> &);
+
+public:
+ resource_pool_object(_ObjectClass *object)
+ : resource_pool_item(reinterpret_cast<void *>(object), sizeof(_ObjectClass)),
+ m_object(object) { }
+ virtual ~resource_pool_object() { delete m_object; }
+
+private:
+ _ObjectClass * m_object;
+};
+
+
+// a resource_pool_array is a simple object wrapper for an allocated array of
+// the templatized type
+template<class _ObjectClass> class resource_pool_array : public resource_pool_item
+{
+private:
+ resource_pool_array<_ObjectClass>(const resource_pool_array<_ObjectClass> &);
+ resource_pool_array<_ObjectClass> &operator=(const resource_pool_array<_ObjectClass> &);
+
+public:
+ resource_pool_array(_ObjectClass *array, int count)
+ : resource_pool_item(reinterpret_cast<void *>(array), sizeof(_ObjectClass) * count),
+ m_array(array),
+ m_count(count) { }
+ virtual ~resource_pool_array() { delete[] m_array; }
+
+private:
+ _ObjectClass * m_array;
+ int m_count;
+};
+
+
+// a resource pool tracks items and frees them upon reset or destruction
+class resource_pool
+{
+private:
+ resource_pool(const resource_pool &);
+ resource_pool &operator=(const resource_pool &);
+
+public:
+ resource_pool(int hash_size = 193);
+ ~resource_pool();
+
+ void add(resource_pool_item &item);
+ void remove(resource_pool_item &item) { remove(item.m_ptr); }
+ void remove(void *ptr);
+ void remove(const void *ptr) { remove(const_cast<void *>(ptr)); }
+ resource_pool_item *find(void *ptr);
+ bool contains(void *ptrstart, void *ptrend);
+ void clear();
+
+ template<class _ObjectClass> _ObjectClass *add_object(_ObjectClass* object) { add(*EMUALLOC_SELF_NEW resource_pool_object<_ObjectClass>(object)); return object; }
+ template<class _ObjectClass> _ObjectClass *add_array(_ObjectClass* array, int count) { add(*EMUALLOC_SELF_NEW resource_pool_array<_ObjectClass>(array, count)); return array; }
+
+private:
+ int m_hash_size;
+ osd_lock * m_listlock;
+ resource_pool_item ** m_hash;
+ resource_pool_item * m_ordered_head;
+ resource_pool_item * m_ordered_tail;
+};
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// global resource pool
+extern resource_pool global_resource_pool;
+
+// dummy objects to pass to the specialized new variants
+extern const zeromem_t zeromem;
+
+
+
+//**************************************************************************
+// ADDDITIONAL MACROS
+//**************************************************************************
+
+// re-route classic malloc-style allocations
+#undef malloc
+#undef calloc
+#undef realloc
+#undef free
+
+#define malloc(x) malloc_array_file_line(x, __FILE__, __LINE__)
+#define calloc(x,y) __error_use_auto_alloc_clear_or_global_alloc_clear_instead__
+#define realloc(x,y) __error_realloc_is_dangerous__
+#define free(x) free_file_line(x, __FILE__, __LINE__)
+
+// disable direct deletion
+#define delete __error_use_pool_free_mechanisms__
+
+
+#endif /* __EMUALLOC_H__ */
diff --git a/trunk/src/emu/emucore.c b/trunk/src/emu/emucore.c
new file mode 100644
index 00000000000..feea859693e
--- /dev/null
+++ b/trunk/src/emu/emucore.c
@@ -0,0 +1,11 @@
+/***************************************************************************
+
+ mamecore.c
+
+ Simple core functions that are defined in emucore.h and which may
+ need to be accessed by other MAME-related tools.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+****************************************************************************/
diff --git a/trunk/src/emu/emucore.h b/trunk/src/emu/emucore.h
new file mode 100644
index 00000000000..20f392b1bb8
--- /dev/null
+++ b/trunk/src/emu/emucore.h
@@ -0,0 +1,455 @@
+/***************************************************************************
+
+ emucore.h
+
+ General core utilities and macros used throughout the emulator.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __EMUCORE_H__
+#define __EMUCORE_H__
+
+// standard C includes
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+// some cleanups for Solaris for things defined in stdlib.h
+#ifdef SDLMAME_SOLARIS
+#undef si_status
+#undef WWORD
+#endif
+
+// standard C++ includes
+#include <exception>
+#include <typeinfo>
+
+// core system includes
+#include "osdcomm.h"
+#include "emualloc.h"
+#include "corestr.h"
+#include "astring.h"
+#include "bitmap.h"
+#include "tagmap.h"
+
+
+
+//**************************************************************************
+// COMPILER-SPECIFIC NASTINESS
+//**************************************************************************
+
+// Suppress warnings about redefining the macro 'PPC' on LinuxPPC.
+#undef PPC
+
+// Suppress warnings about redefining the macro 'ARM' on ARM.
+#undef ARM
+
+
+
+//**************************************************************************
+// FUNDAMENTAL TYPES
+//**************************************************************************
+
+// genf is a generic function pointer; cast function pointers to this instead of void *
+typedef void genf(void);
+
+// FPTR is used to cast a pointer to a scalar
+#ifdef PTR64
+typedef UINT64 FPTR;
+#else
+typedef UINT32 FPTR;
+#endif
+
+// pen_t is used to represent pixel values in bitmaps
+typedef UINT32 pen_t;
+
+// stream_sample_t is used to represent a single sample in a sound stream
+typedef INT32 stream_sample_t;
+
+// running_machine is core to pretty much everything
+class running_machine;
+
+
+
+//**************************************************************************
+// USEFUL COMPOSITE TYPES
+//**************************************************************************
+
+// generic_ptr is a union of pointers to various sizes
+union generic_ptr
+{
+ void * v;
+ INT8 * i8;
+ UINT8 * u8;
+ INT16 * i16;
+ UINT16 * u16;
+ INT32 * i32;
+ UINT32 * u32;
+ INT64 * i64;
+ UINT64 * u64;
+};
+
+
+// PAIR is an endian-safe union useful for representing 32-bit CPU registers
+union PAIR
+{
+#ifdef LSB_FIRST
+ struct { UINT8 l,h,h2,h3; } b;
+ struct { UINT16 l,h; } w;
+ struct { INT8 l,h,h2,h3; } sb;
+ struct { INT16 l,h; } sw;
+#else
+ struct { UINT8 h3,h2,h,l; } b;
+ struct { INT8 h3,h2,h,l; } sb;
+ struct { UINT16 h,l; } w;
+ struct { INT16 h,l; } sw;
+#endif
+ UINT32 d;
+ INT32 sd;
+};
+
+
+// PAIR64 is a 64-bit extension of a PAIR
+union PAIR64
+{
+#ifdef LSB_FIRST
+ struct { UINT8 l,h,h2,h3,h4,h5,h6,h7; } b;
+ struct { UINT16 l,h,h2,h3; } w;
+ struct { UINT32 l,h; } d;
+ struct { INT8 l,h,h2,h3,h4,h5,h6,h7; } sb;
+ struct { INT16 l,h,h2,h3; } sw;
+ struct { INT32 l,h; } sd;
+#else
+ struct { UINT8 h7,h6,h5,h4,h3,h2,h,l; } b;
+ struct { UINT16 h3,h2,h,l; } w;
+ struct { UINT32 h,l; } d;
+ struct { INT8 h7,h6,h5,h4,h3,h2,h,l; } sb;
+ struct { INT16 h3,h2,h,l; } sw;
+ struct { INT32 h,l; } sd;
+#endif
+ UINT64 q;
+ INT64 sq;
+};
+
+
+
+//**************************************************************************
+// COMMON CONSTANTS
+//**************************************************************************
+
+// constants for expression endianness
+enum endianness_t
+{
+ ENDIANNESS_LITTLE,
+ ENDIANNESS_BIG
+};
+
+
+// declare native endianness to be one or the other
+#ifdef LSB_FIRST
+const endianness_t ENDIANNESS_NATIVE = ENDIANNESS_LITTLE;
+#else
+const endianness_t ENDIANNESS_NATIVE = ENDIANNESS_BIG;
+#endif
+
+
+// M_PI is not part of the C/C++ standards and is not present on
+// strict ANSI compilers or when compiling under GCC with -ansi
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+
+// orientation of bitmaps
+#define ORIENTATION_FLIP_X 0x0001 /* mirror everything in the X direction */
+#define ORIENTATION_FLIP_Y 0x0002 /* mirror everything in the Y direction */
+#define ORIENTATION_SWAP_XY 0x0004 /* mirror along the top-left/bottom-right diagonal */
+
+#define ROT0 0
+#define ROT90 (ORIENTATION_SWAP_XY | ORIENTATION_FLIP_X) /* rotate clockwise 90 degrees */
+#define ROT180 (ORIENTATION_FLIP_X | ORIENTATION_FLIP_Y) /* rotate 180 degrees */
+#define ROT270 (ORIENTATION_SWAP_XY | ORIENTATION_FLIP_Y) /* rotate counter-clockwise 90 degrees */
+
+
+
+//**************************************************************************
+// COMMON MACROS
+//**************************************************************************
+
+// macro for defining a copy constructor and assignment operator to prevent copying
+#define DISABLE_COPYING(_Type) \
+private: \
+ _Type(const _Type &); \
+ _Type &operator=(const _Type &) \
+
+
+// macro for declaring enumerator operators that increment/decrement like plain old C
+#define DECLARE_ENUM_OPERATORS(_Type) \
+inline void operator++(_Type &value) { value = (_Type)((int)value + 1); } \
+inline void operator++(_Type &value, int) { value = (_Type)((int)value + 1); } \
+inline void operator--(_Type &value) { value = (_Type)((int)value - 1); } \
+inline void operator--(_Type &value, int) { value = (_Type)((int)value - 1); }
+
+
+// this macro passes an item followed by a string version of itself as two consecutive parameters
+#define NAME(x) x, #x
+
+// this macro wraps a function 'x' and can be used to pass a function followed by its name
+#define FUNC(x) &x, #x
+#define FUNC_NULL NULL, "(null)"
+
+
+// standard assertion macros
+#undef assert
+#undef assert_always
+
+#ifdef MAME_DEBUG
+#define assert(x) do { if (!(x)) throw emu_fatalerror("assert: %s:%d: %s", __FILE__, __LINE__, #x); } while (0)
+#define assert_always(x, msg) do { if (!(x)) throw emu_fatalerror("Fatal error: %s\nCaused by assert: %s:%d: %s", msg, __FILE__, __LINE__, #x); } while (0)
+#else
+#define assert(x) do { } while (0)
+#define assert_always(x, msg) do { if (!(x)) throw emu_fatalerror("Fatal error: %s (%s:%d)", msg, __FILE__, __LINE__); } while (0)
+#endif
+
+
+// map mame_* helpers to core_* helpers */
+#define mame_stricmp core_stricmp
+#define mame_strnicmp core_strnicmp
+#define mame_strdup core_strdup
+#define mame_strwildcmp core_strwildcmp
+
+
+// macros to convert radians to degrees and degrees to radians
+#define RADIAN_TO_DEGREE(x) ((180.0 / M_PI) * (x))
+#define DEGREE_TO_RADIAN(x) ((M_PI / 180.0) * (x))
+
+
+// endian-based value: first value is if 'endian' is little-endian, second is if 'endian' is big-endian
+#define ENDIAN_VALUE_LE_BE(endian,leval,beval) (((endian) == ENDIANNESS_LITTLE) ? (leval) : (beval))
+
+// endian-based value: first value is if native endianness is little-endian, second is if native is big-endian
+#define NATIVE_ENDIAN_VALUE_LE_BE(leval,beval) ENDIAN_VALUE_LE_BE(ENDIANNESS_NATIVE, leval, beval)
+
+// endian-based value: first value is if 'endian' matches native, second is if 'endian' doesn't match native
+#define ENDIAN_VALUE_NE_NNE(endian,leval,beval) (((endian) == ENDIANNESS_NATIVE) ? (neval) : (nneval))
+
+
+// useful macros to deal with bit shuffling encryptions
+#define BIT(x,n) (((x)>>(n))&1)
+
+#define BITSWAP8(val,B7,B6,B5,B4,B3,B2,B1,B0) \
+ ((BIT(val,B7) << 7) | (BIT(val,B6) << 6) | (BIT(val,B5) << 5) | (BIT(val,B4) << 4) | \
+ (BIT(val,B3) << 3) | (BIT(val,B2) << 2) | (BIT(val,B1) << 1) | (BIT(val,B0) << 0))
+
+#define BITSWAP16(val,B15,B14,B13,B12,B11,B10,B9,B8,B7,B6,B5,B4,B3,B2,B1,B0) \
+ ((BIT(val,B15) << 15) | (BIT(val,B14) << 14) | (BIT(val,B13) << 13) | (BIT(val,B12) << 12) | \
+ (BIT(val,B11) << 11) | (BIT(val,B10) << 10) | (BIT(val, B9) << 9) | (BIT(val, B8) << 8) | \
+ (BIT(val, B7) << 7) | (BIT(val, B6) << 6) | (BIT(val, B5) << 5) | (BIT(val, B4) << 4) | \
+ (BIT(val, B3) << 3) | (BIT(val, B2) << 2) | (BIT(val, B1) << 1) | (BIT(val, B0) << 0))
+
+#define BITSWAP24(val,B23,B22,B21,B20,B19,B18,B17,B16,B15,B14,B13,B12,B11,B10,B9,B8,B7,B6,B5,B4,B3,B2,B1,B0) \
+ ((BIT(val,B23) << 23) | (BIT(val,B22) << 22) | (BIT(val,B21) << 21) | (BIT(val,B20) << 20) | \
+ (BIT(val,B19) << 19) | (BIT(val,B18) << 18) | (BIT(val,B17) << 17) | (BIT(val,B16) << 16) | \
+ (BIT(val,B15) << 15) | (BIT(val,B14) << 14) | (BIT(val,B13) << 13) | (BIT(val,B12) << 12) | \
+ (BIT(val,B11) << 11) | (BIT(val,B10) << 10) | (BIT(val, B9) << 9) | (BIT(val, B8) << 8) | \
+ (BIT(val, B7) << 7) | (BIT(val, B6) << 6) | (BIT(val, B5) << 5) | (BIT(val, B4) << 4) | \
+ (BIT(val, B3) << 3) | (BIT(val, B2) << 2) | (BIT(val, B1) << 1) | (BIT(val, B0) << 0))
+
+#define BITSWAP32(val,B31,B30,B29,B28,B27,B26,B25,B24,B23,B22,B21,B20,B19,B18,B17,B16,B15,B14,B13,B12,B11,B10,B9,B8,B7,B6,B5,B4,B3,B2,B1,B0) \
+ ((BIT(val,B31) << 31) | (BIT(val,B30) << 30) | (BIT(val,B29) << 29) | (BIT(val,B28) << 28) | \
+ (BIT(val,B27) << 27) | (BIT(val,B26) << 26) | (BIT(val,B25) << 25) | (BIT(val,B24) << 24) | \
+ (BIT(val,B23) << 23) | (BIT(val,B22) << 22) | (BIT(val,B21) << 21) | (BIT(val,B20) << 20) | \
+ (BIT(val,B19) << 19) | (BIT(val,B18) << 18) | (BIT(val,B17) << 17) | (BIT(val,B16) << 16) | \
+ (BIT(val,B15) << 15) | (BIT(val,B14) << 14) | (BIT(val,B13) << 13) | (BIT(val,B12) << 12) | \
+ (BIT(val,B11) << 11) | (BIT(val,B10) << 10) | (BIT(val, B9) << 9) | (BIT(val, B8) << 8) | \
+ (BIT(val, B7) << 7) | (BIT(val, B6) << 6) | (BIT(val, B5) << 5) | (BIT(val, B4) << 4) | \
+ (BIT(val, B3) << 3) | (BIT(val, B2) << 2) | (BIT(val, B1) << 1) | (BIT(val, B0) << 0))
+
+
+
+//**************************************************************************
+// EXCEPTION CLASSES
+//**************************************************************************
+
+// emu_exception is the base class for all emu-related exceptions
+class emu_exception : public std::exception { };
+
+
+// emu_fatalerror is a generic fatal exception that provides an error string
+class emu_fatalerror : public emu_exception
+{
+public:
+ emu_fatalerror(const char *format, ...)
+ : code(0)
+ {
+ va_list ap;
+ va_start(ap, format);
+ vsprintf(text, format, ap);
+ va_end(ap);
+ osd_break_into_debugger(text);
+ }
+
+ emu_fatalerror(const char *format, va_list ap)
+ : code(0)
+ {
+ vsprintf(text, format, ap);
+ osd_break_into_debugger(text);
+ }
+
+ emu_fatalerror(int _exitcode, const char *format, ...)
+ : code(_exitcode)
+ {
+ va_list ap;
+ va_start(ap, format);
+ vsprintf(text, format, ap);
+ va_end(ap);
+ }
+
+ emu_fatalerror(int _exitcode, const char *format, va_list ap)
+ : code(_exitcode)
+ {
+ vsprintf(text, format, ap);
+ }
+
+ const char *string() const { return text; }
+ int exitcode() const { return code; }
+
+private:
+ char text[1024];
+ int code;
+};
+
+
+
+//**************************************************************************
+// CASTING TEMPLATES
+//**************************************************************************
+
+// template function for casting from a base class to a derived class that is checked
+// in debug builds and fast in release builds
+template<class _Dest, class _Source>
+inline _Dest downcast(_Source *src)
+{
+ assert(dynamic_cast<_Dest>(src) == src);
+ return static_cast<_Dest>(src);
+}
+
+template<class _Dest, class _Source>
+inline _Dest downcast(_Source &src)
+{
+ assert(&dynamic_cast<_Dest>(src) == &src);
+ return static_cast<_Dest>(src);
+}
+
+
+// template function for cross-casting from one class to another that throws a bad_cast
+// exception instead of returning NULL
+template<class _Dest, class _Source>
+inline _Dest crosscast(_Source *src)
+{
+ _Dest result = dynamic_cast<_Dest>(src);
+ assert(result != NULL);
+ if (result == NULL)
+ throw std::bad_cast();
+ return result;
+}
+
+
+
+//**************************************************************************
+// FUNCTION PROTOTYPES
+//**************************************************************************
+
+DECL_NORETURN void fatalerror(const char *format, ...) ATTR_PRINTF(1,2) ATTR_NORETURN;
+DECL_NORETURN void fatalerror_exitcode(running_machine &machine, int exitcode, const char *format, ...) ATTR_PRINTF(3,4) ATTR_NORETURN;
+
+inline void fatalerror(const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ throw emu_fatalerror(format, ap);
+ va_end(ap);
+}
+
+inline void fatalerror_exitcode(running_machine &machine, int exitcode, const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ throw emu_fatalerror(exitcode, format, ap);
+ va_end(ap);
+}
+
+
+
+//**************************************************************************
+// INLINE FUNCTIONS
+//**************************************************************************
+
+// population count
+#ifndef SDLMAME_NETBSD
+inline int popcount(UINT32 val)
+{
+ int count;
+
+ for (count = 0; val != 0; count++)
+ val &= val - 1;
+ return count;
+}
+#endif
+
+
+// convert a series of 32 bits into a float
+inline float u2f(UINT32 v)
+{
+ union {
+ float ff;
+ UINT32 vv;
+ } u;
+ u.vv = v;
+ return u.ff;
+}
+
+
+// convert a float into a series of 32 bits
+inline UINT32 f2u(float f)
+{
+ union {
+ float ff;
+ UINT32 vv;
+ } u;
+ u.ff = f;
+ return u.vv;
+}
+
+
+// convert a series of 64 bits into a double
+inline double u2d(UINT64 v)
+{
+ union {
+ double dd;
+ UINT64 vv;
+ } u;
+ u.vv = v;
+ return u.dd;
+}
+
+
+// convert a double into a series of 64 bits
+inline UINT64 d2u(double d)
+{
+ union {
+ double dd;
+ UINT64 vv;
+ } u;
+ u.dd = d;
+ return u.vv;
+}
+
+#endif /* __EMUCORE_H__ */
diff --git a/trunk/src/emu/emuopts.c b/trunk/src/emu/emuopts.c
new file mode 100644
index 00000000000..6dbe7545797
--- /dev/null
+++ b/trunk/src/emu/emuopts.c
@@ -0,0 +1,514 @@
+/***************************************************************************
+
+ emuopts.c
+
+ Options file and command line 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 "emuopts.h"
+
+#include <ctype.h>
+
+
+
+//**************************************************************************
+// CORE EMULATOR OPTIONS
+//**************************************************************************
+
+const options_entry emu_options::s_option_entries[] =
+{
+ // unadorned options - only a single one supported at the moment
+ { OPTION_SYSTEMNAME, NULL, OPTION_STRING, NULL },
+ { OPTION_SOFTWARENAME, NULL, OPTION_STRING, NULL },
+
+ // config options
+ { NULL, NULL, OPTION_HEADER, "CORE CONFIGURATION OPTIONS" },
+ { OPTION_READCONFIG ";rc", "1", OPTION_BOOLEAN, "enable loading of configuration files" },
+ { OPTION_WRITECONFIG ";wc", "0", OPTION_BOOLEAN, "writes configuration to (driver).ini on exit" },
+
+ // seach path options
+ { NULL, NULL, OPTION_HEADER, "CORE SEARCH PATH OPTIONS" },
+ { OPTION_MEDIAPATH ";rp;biospath;bp", "roms", OPTION_STRING, "path to ROMsets and hard disk images" },
+ { OPTION_HASHPATH ";hash_directory;hash", "hash", OPTION_STRING, "path to hash files" },
+ { OPTION_SAMPLEPATH ";sp", "samples", OPTION_STRING, "path to samplesets" },
+ { OPTION_ARTPATH, "artwork", OPTION_STRING, "path to artwork files" },
+ { OPTION_CTRLRPATH, "ctrlr", OPTION_STRING, "path to controller definitions" },
+ { OPTION_INIPATH, ".;ini", OPTION_STRING, "path to ini files" },
+ { OPTION_FONTPATH, ".", OPTION_STRING, "path to font files" },
+ { OPTION_CHEATPATH, "cheat", OPTION_STRING, "path to cheat files" },
+ { OPTION_CROSSHAIRPATH, "crosshair", OPTION_STRING, "path to crosshair files" },
+
+ // output directory options
+ { NULL, NULL, OPTION_HEADER, "CORE OUTPUT DIRECTORY OPTIONS" },
+ { OPTION_CFG_DIRECTORY, "cfg", OPTION_STRING, "directory to save configurations" },
+ { OPTION_NVRAM_DIRECTORY, "nvram", OPTION_STRING, "directory to save nvram contents" },
+ { OPTION_MEMCARD_DIRECTORY, "memcard", OPTION_STRING, "directory to save memory card contents" },
+ { OPTION_INPUT_DIRECTORY, "inp", OPTION_STRING, "directory to save input device logs" },
+ { OPTION_STATE_DIRECTORY, "sta", OPTION_STRING, "directory to save states" },
+ { OPTION_SNAPSHOT_DIRECTORY, "snap", OPTION_STRING, "directory to save screenshots" },
+ { OPTION_DIFF_DIRECTORY, "diff", OPTION_STRING, "directory to save hard drive image difference files" },
+ { OPTION_COMMENT_DIRECTORY, "comments", OPTION_STRING, "directory to save debugger comments" },
+
+ // state/playback options
+ { NULL, NULL, OPTION_HEADER, "CORE STATE/PLAYBACK OPTIONS" },
+ { OPTION_STATE, NULL, OPTION_STRING, "saved state to load" },
+ { OPTION_AUTOSAVE, "0", OPTION_BOOLEAN, "enable automatic restore at startup, and automatic save at exit time" },
+ { OPTION_PLAYBACK ";pb", NULL, OPTION_STRING, "playback an input file" },
+ { OPTION_RECORD ";rec", NULL, OPTION_STRING, "record an input file" },
+ { OPTION_MNGWRITE, NULL, OPTION_STRING, "optional filename to write a MNG movie of the current session" },
+ { OPTION_AVIWRITE, NULL, OPTION_STRING, "optional filename to write an AVI movie of the current session" },
+ { OPTION_WAVWRITE, NULL, OPTION_STRING, "optional filename to write a WAV file of the current session" },
+ { OPTION_SNAPNAME, "%g/%i", OPTION_STRING, "override of the default snapshot/movie naming; %g == gamename, %i == index" },
+ { OPTION_SNAPSIZE, "auto", OPTION_STRING, "specify snapshot/movie resolution (<width>x<height>) or 'auto' to use minimal size " },
+ { OPTION_SNAPVIEW, "internal", OPTION_STRING, "specify snapshot/movie view or 'internal' to use internal pixel-aspect views" },
+ { OPTION_BURNIN, "0", OPTION_BOOLEAN, "create burn-in snapshots for each screen" },
+
+ // performance options
+ { NULL, NULL, OPTION_HEADER, "CORE PERFORMANCE OPTIONS" },
+ { OPTION_AUTOFRAMESKIP ";afs", "0", OPTION_BOOLEAN, "enable automatic frameskip selection" },
+ { OPTION_FRAMESKIP ";fs(0-10)", "0", OPTION_INTEGER, "set frameskip to fixed value, 0-10 (autoframeskip must be disabled)" },
+ { OPTION_SECONDS_TO_RUN ";str", "0", OPTION_INTEGER, "number of emulated seconds to run before automatically exiting" },
+ { OPTION_THROTTLE, "1", OPTION_BOOLEAN, "enable throttling to keep game running in sync with real time" },
+ { OPTION_SLEEP, "1", OPTION_BOOLEAN, "enable sleeping, which gives time back to other applications when idle" },
+ { OPTION_SPEED "(0.01-100)", "1.0", OPTION_FLOAT, "controls the speed of gameplay, relative to realtime; smaller numbers are slower" },
+ { OPTION_REFRESHSPEED ";rs", "0", OPTION_BOOLEAN, "automatically adjusts the speed of gameplay to keep the refresh rate lower than the screen" },
+
+ // rotation options
+ { NULL, NULL, OPTION_HEADER, "CORE ROTATION OPTIONS" },
+ { OPTION_ROTATE, "1", OPTION_BOOLEAN, "rotate the game screen according to the game's orientation needs it" },
+ { OPTION_ROR, "0", OPTION_BOOLEAN, "rotate screen clockwise 90 degrees" },
+ { OPTION_ROL, "0", OPTION_BOOLEAN, "rotate screen counterclockwise 90 degrees" },
+ { OPTION_AUTOROR, "0", OPTION_BOOLEAN, "automatically rotate screen clockwise 90 degrees if vertical" },
+ { OPTION_AUTOROL, "0", OPTION_BOOLEAN, "automatically rotate screen counterclockwise 90 degrees if vertical" },
+ { OPTION_FLIPX, "0", OPTION_BOOLEAN, "flip screen left-right" },
+ { OPTION_FLIPY, "0", OPTION_BOOLEAN, "flip screen upside-down" },
+
+ // artwork options
+ { NULL, NULL, OPTION_HEADER, "CORE ARTWORK OPTIONS" },
+ { OPTION_ARTWORK_CROP ";artcrop", "0", OPTION_BOOLEAN, "crop artwork to game screen size" },
+ { OPTION_USE_BACKDROPS ";backdrop", "1", OPTION_BOOLEAN, "enable backdrops if artwork is enabled and available" },
+ { OPTION_USE_OVERLAYS ";overlay", "1", OPTION_BOOLEAN, "enable overlays if artwork is enabled and available" },
+ { OPTION_USE_BEZELS ";bezel", "1", OPTION_BOOLEAN, "enable bezels if artwork is enabled and available" },
+ { OPTION_USE_CPANELS ";cpanel", "1", OPTION_BOOLEAN, "enable cpanels if artwork is enabled and available" },
+ { OPTION_USE_MARQUEES ";marquee", "1", OPTION_BOOLEAN, "enable marquees if artwork is enabled and available" },
+
+ // screen options
+ { NULL, NULL, OPTION_HEADER, "CORE SCREEN OPTIONS" },
+ { OPTION_BRIGHTNESS "(0.1-2.0)", "1.0", OPTION_FLOAT, "default game screen brightness correction" },
+ { OPTION_CONTRAST "(0.1-2.0)", "1.0", OPTION_FLOAT, "default game screen contrast correction" },
+ { OPTION_GAMMA "(0.1-3.0)", "1.0", OPTION_FLOAT, "default game screen gamma correction" },
+ { OPTION_PAUSE_BRIGHTNESS "(0.0-1.0)", "0.65", OPTION_FLOAT, "amount to scale the screen brightness when paused" },
+ { OPTION_EFFECT, "none", OPTION_STRING, "name of a PNG file to use for visual effects, or 'none'" },
+
+ // vector options
+ { NULL, NULL, OPTION_HEADER, "CORE VECTOR OPTIONS" },
+ { OPTION_ANTIALIAS ";aa", "1", OPTION_BOOLEAN, "use antialiasing when drawing vectors" },
+ { OPTION_BEAM, "1.0", OPTION_FLOAT, "set vector beam width" },
+ { OPTION_FLICKER, "0", OPTION_FLOAT, "set vector flicker effect" },
+
+ // sound options
+ { NULL, NULL, OPTION_HEADER, "CORE SOUND OPTIONS" },
+ { OPTION_SOUND, "1", OPTION_BOOLEAN, "enable sound output" },
+ { OPTION_SAMPLERATE ";sr(1000-1000000)", "48000", OPTION_INTEGER, "set sound output sample rate" },
+ { OPTION_SAMPLES, "1", OPTION_BOOLEAN, "enable the use of external samples if available" },
+ { OPTION_VOLUME ";vol", "0", OPTION_INTEGER, "sound volume in decibels (-32 min, 0 max)" },
+
+ // input options
+ { NULL, NULL, OPTION_HEADER, "CORE INPUT OPTIONS" },
+ { OPTION_COIN_LOCKOUT ";coinlock", "1", OPTION_BOOLEAN, "enable coin lockouts to actually lock out coins" },
+ { OPTION_CTRLR, NULL, OPTION_STRING, "preconfigure for specified controller" },
+ { OPTION_MOUSE, "0", OPTION_BOOLEAN, "enable mouse input" },
+ { OPTION_JOYSTICK ";joy", "1", OPTION_BOOLEAN, "enable joystick input" },
+ { OPTION_LIGHTGUN ";gun", "0", OPTION_BOOLEAN, "enable lightgun input" },
+ { OPTION_MULTIKEYBOARD ";multikey", "0", OPTION_BOOLEAN, "enable separate input from each keyboard device (if present)" },
+ { OPTION_MULTIMOUSE, "0", OPTION_BOOLEAN, "enable separate input from each mouse device (if present)" },
+ { OPTION_STEADYKEY ";steady", "0", OPTION_BOOLEAN, "enable steadykey support" },
+ { OPTION_OFFSCREEN_RELOAD ";reload", "0", OPTION_BOOLEAN, "convert lightgun button 2 into offscreen reload" },
+ { OPTION_JOYSTICK_MAP ";joymap", "auto", OPTION_STRING, "explicit joystick map, or auto to auto-select" },
+ { OPTION_JOYSTICK_DEADZONE ";joy_deadzone;jdz", "0.3", OPTION_FLOAT, "center deadzone range for joystick where change is ignored (0.0 center, 1.0 end)" },
+ { OPTION_JOYSTICK_SATURATION ";joy_saturation;jsat", "0.85", OPTION_FLOAT, "end of axis saturation range for joystick where change is ignored (0.0 center, 1.0 end)" },
+ { OPTION_NATURAL_KEYBOARD ";nat", "0", OPTION_BOOLEAN, "specifies whether to use a natural keyboard or not" },
+
+ // input autoenable options
+ { NULL, NULL, OPTION_HEADER, "CORE INPUT AUTOMATIC ENABLE OPTIONS" },
+ { OPTION_PADDLE_DEVICE ";paddle", "keyboard", OPTION_STRING, "enable (none|keyboard|mouse|lightgun|joystick) if a paddle control is present" },
+ { OPTION_ADSTICK_DEVICE ";adstick", "keyboard", OPTION_STRING, "enable (none|keyboard|mouse|lightgun|joystick) if an analog joystick control is present" },
+ { OPTION_PEDAL_DEVICE ";pedal", "keyboard", OPTION_STRING, "enable (none|keyboard|mouse|lightgun|joystick) if a pedal control is present" },
+ { OPTION_DIAL_DEVICE ";dial", "keyboard", OPTION_STRING, "enable (none|keyboard|mouse|lightgun|joystick) if a dial control is present" },
+ { OPTION_TRACKBALL_DEVICE ";trackball", "keyboard", OPTION_STRING, "enable (none|keyboard|mouse|lightgun|joystick) if a trackball control is present" },
+ { OPTION_LIGHTGUN_DEVICE, "keyboard", OPTION_STRING, "enable (none|keyboard|mouse|lightgun|joystick) if a lightgun control is present" },
+ { OPTION_POSITIONAL_DEVICE, "keyboard", OPTION_STRING, "enable (none|keyboard|mouse|lightgun|joystick) if a positional control is present" },
+ { OPTION_MOUSE_DEVICE, "mouse", OPTION_STRING, "enable (none|keyboard|mouse|lightgun|joystick) if a mouse control is present" },
+
+ // debugging options
+ { NULL, NULL, OPTION_HEADER, "CORE DEBUGGING OPTIONS" },
+ { OPTION_LOG, "0", OPTION_BOOLEAN, "generate an error.log file" },
+ { OPTION_VERBOSE ";v", "0", OPTION_BOOLEAN, "display additional diagnostic information" },
+ { OPTION_UPDATEINPAUSE, "0", OPTION_BOOLEAN, "keep calling video updates while in pause" },
+ { OPTION_DEBUG ";d", "0", OPTION_BOOLEAN, "enable/disable debugger" },
+ { OPTION_DEBUGSCRIPT, NULL, OPTION_STRING, "script for debugger" },
+ { OPTION_DEBUG_INTERNAL ";di", "0", OPTION_BOOLEAN, "use the internal debugger for debugging" },
+
+ // misc options
+ { NULL, NULL, OPTION_HEADER, "CORE MISC OPTIONS" },
+ { OPTION_BIOS, NULL, OPTION_STRING, "select the system BIOS to use" },
+ { OPTION_CHEAT ";c", "0", OPTION_BOOLEAN, "enable cheat subsystem" },
+ { OPTION_SKIP_GAMEINFO, "0", OPTION_BOOLEAN, "skip displaying the information screen at startup" },
+ { OPTION_UI_FONT, "default", OPTION_STRING, "specify a font to use" },
+ { OPTION_RAMSIZE ";ram", NULL, OPTION_STRING, "size of RAM (if supported by driver)" },
+ { OPTION_CONFIRM_QUIT, "0", OPTION_BOOLEAN, "display confirm quit screen on exit" },
+ { NULL }
+};
+
+
+
+//**************************************************************************
+// EMU OPTIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// emu_options - constructor
+//-------------------------------------------------
+
+emu_options::emu_options()
+{
+ add_entries(s_option_entries);
+}
+
+
+//-------------------------------------------------
+// add_slot_options - add all of the slot
+// options for the configured system
+//-------------------------------------------------
+
+bool emu_options::add_slot_options(bool isfirst)
+{
+ // look up the system configured by name; if no match, do nothing
+ const game_driver *cursystem = system();
+ if (cursystem == NULL)
+ return false;
+
+ // iterate through all slot devices
+ options_entry entry[2] = { { 0 }, { 0 } };
+ bool first = true;
+ const device_slot_interface *slot = NULL;
+ // create the configuration
+ machine_config config(*cursystem, *this);
+ bool added = false;
+ for (bool gotone = config.devicelist().first(slot); gotone; gotone = slot->next(slot))
+ {
+ // first device? add the header as to be pretty
+ if (first && isfirst)
+ {
+ entry[0].name = NULL;
+ entry[0].description = "SLOT DEVICES";
+ entry[0].flags = OPTION_HEADER | OPTION_FLAG_DEVICE;
+ entry[0].defvalue = NULL;
+ add_entries(entry);
+ }
+ first = false;
+
+ // retrieve info about the device instance
+ astring option_name;
+ option_name.printf("%s;%s", slot->device().tag(), slot->device().tag());
+
+ if (!exists(slot->device().tag())) {
+
+ // add the option
+ entry[0].name = slot->device().tag();
+ entry[0].description = NULL;
+ entry[0].flags = OPTION_STRING | OPTION_FLAG_DEVICE;
+ entry[0].defvalue = (slot->get_slot_interfaces() != NULL) ? slot->get_default_card(config.devicelist(),*this) : NULL;
+ add_entries(entry, true);
+
+ added = true;
+ }
+ }
+ return added;
+}
+
+//-------------------------------------------------
+// add_device_options - add all of the device
+// options for the configured system
+//-------------------------------------------------
+
+void emu_options::add_device_options(bool isfirst)
+{
+ // look up the system configured by name; if no match, do nothing
+ const game_driver *cursystem = system();
+ if (cursystem == NULL)
+ return;
+
+ // iterate through all slot devices
+ options_entry entry[2] = { { 0 }, { 0 } };
+ bool first = true;
+ // iterate through all image devices
+ const device_image_interface *image = NULL;
+ machine_config config(*cursystem, *this);
+ for (bool gotone = config.devicelist().first(image); gotone; gotone = image->next(image))
+ {
+ // first device? add the header as to be pretty
+ if (first && isfirst)
+ {
+ entry[0].name = NULL;
+ entry[0].description = "IMAGE DEVICES";
+ entry[0].flags = OPTION_HEADER | OPTION_FLAG_DEVICE;
+ entry[0].defvalue = NULL;
+ add_entries(entry);
+ }
+ first = false;
+
+ // retrieve info about the device instance
+ astring option_name;
+ option_name.printf("%s;%s", image->instance_name(), image->brief_instance_name());
+
+ // add the option
+ if (!exists(image->instance_name())) {
+ entry[0].name = option_name;
+ entry[0].description = NULL;
+ entry[0].flags = OPTION_STRING | OPTION_FLAG_DEVICE;
+ entry[0].defvalue = NULL;
+ add_entries(entry, true);
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// remove_device_options - remove device options
+//-------------------------------------------------
+
+void emu_options::remove_device_options()
+{
+ // iterate through options and remove interesting ones
+ entry *nextentry;
+ for (entry *curentry = first(); curentry != NULL; curentry = nextentry)
+ {
+ // pre-fetch the next entry in case we delete this one
+ nextentry = curentry->next();
+
+ // if this is a device option, nuke it
+ if ((curentry->flags() & OPTION_FLAG_DEVICE) != 0)
+ remove_entry(*curentry);
+ }
+}
+
+
+//-------------------------------------------------
+// parse_slot_devices - parse the command line
+// and update slot and image devices
+//-------------------------------------------------
+
+bool emu_options::parse_slot_devices(int argc, char *argv[], astring &error_string, const char *name, const char *value)
+{
+ remove_device_options();
+ add_device_options(true);
+ if (name && exists(name)) {
+ set_value(name, value, OPTION_PRIORITY_CMDLINE, error_string);
+ }
+ bool isfirst = true;
+ bool result = core_options::parse_command_line(argc, argv, OPTION_PRIORITY_CMDLINE, error_string);
+ while (add_slot_options(isfirst)) {
+ result = core_options::parse_command_line(argc, argv, OPTION_PRIORITY_CMDLINE, error_string);
+ add_device_options(false);
+ if (name && exists(name)) {
+ set_value(name, value, OPTION_PRIORITY_CMDLINE, error_string);
+ }
+ isfirst = false;
+ }
+ result = core_options::parse_command_line(argc, argv, OPTION_PRIORITY_CMDLINE, error_string);
+ return result;
+}
+
+//-------------------------------------------------
+// parse_command_line - parse the command line
+// and update the devices
+//-------------------------------------------------
+
+bool emu_options::parse_command_line(int argc, char *argv[], astring &error_string)
+{
+ // remember the original system name
+ astring old_system_name(system_name());
+
+ // parse as normal
+ bool result = core_options::parse_command_line(argc, argv, OPTION_PRIORITY_CMDLINE, error_string);
+
+ // if the system name changed, fix up the device options
+ if (old_system_name != system_name())
+ {
+ // remove any existing device options
+ result = parse_slot_devices(argc, argv, error_string, NULL, NULL);
+ }
+ return result;
+}
+
+
+//-------------------------------------------------
+// parse_standard_inis - parse the standard set
+// of INI files
+//-------------------------------------------------
+
+void emu_options::parse_standard_inis(astring &error_string)
+{
+ // start with an empty string
+ error_string.reset();
+
+ // parse the INI file defined by the platform (e.g., "mame.ini")
+ // we do this twice so that the first file can change the INI path
+ parse_one_ini(CONFIGNAME, OPTION_PRIORITY_MAME_INI);
+ parse_one_ini(CONFIGNAME, OPTION_PRIORITY_MAME_INI, &error_string);
+
+ // debug mode: parse "debug.ini" as well
+ if (debug())
+ parse_one_ini("debug", OPTION_PRIORITY_DEBUG_INI, &error_string);
+
+ // if we have a valid system driver, parse system-specific INI files
+ const game_driver *cursystem = system();
+ if (cursystem == NULL)
+ return;
+
+ // parse "vertical.ini" or "horizont.ini"
+ if (cursystem->flags & ORIENTATION_SWAP_XY)
+ parse_one_ini("vertical", OPTION_PRIORITY_ORIENTATION_INI, &error_string);
+ else
+ parse_one_ini("horizont", OPTION_PRIORITY_ORIENTATION_INI, &error_string);
+
+ // parse "vector.ini" for vector games
+ {
+ machine_config config(*cursystem, *this);
+ for (const screen_device *device = config.first_screen(); device != NULL; device = device->next_screen())
+ if (device->screen_type() == SCREEN_TYPE_VECTOR)
+ {
+ parse_one_ini("vector", OPTION_PRIORITY_VECTOR_INI, &error_string);
+ break;
+ }
+ }
+
+ // next parse "source/<sourcefile>.ini"; if that doesn't exist, try <sourcefile>.ini
+ astring sourcename;
+ core_filename_extract_base(&sourcename, cursystem->source_file, TRUE)->ins(0, "source" PATH_SEPARATOR);
+ if (!parse_one_ini(sourcename, OPTION_PRIORITY_SOURCE_INI, &error_string))
+ {
+ core_filename_extract_base(&sourcename, cursystem->source_file, TRUE);
+ parse_one_ini(sourcename, OPTION_PRIORITY_SOURCE_INI, &error_string);
+ }
+
+ // then parse the grandparent, parent, and system-specific INIs
+ int parent = driver_list::clone(*cursystem);
+ int gparent = (parent != -1) ? driver_list::clone(parent) : -1;
+ if (gparent != -1)
+ parse_one_ini(driver_list::driver(gparent).name, OPTION_PRIORITY_GPARENT_INI, &error_string);
+ if (parent != -1)
+ parse_one_ini(driver_list::driver(parent).name, OPTION_PRIORITY_PARENT_INI, &error_string);
+ parse_one_ini(cursystem->name, OPTION_PRIORITY_DRIVER_INI, &error_string);
+}
+
+
+//-------------------------------------------------
+// system - return a pointer to the specified
+// system driver, or NULL if no match
+//-------------------------------------------------
+
+const game_driver *emu_options::system() const
+{
+ astring tempstr;
+ int index = driver_list::find(*core_filename_extract_base(&tempstr, system_name(), TRUE));
+ return (index != -1) ? &driver_list::driver(index) : NULL;
+}
+
+
+//-------------------------------------------------
+// set_system_name - set a new system name
+//-------------------------------------------------
+
+void emu_options::set_system_name(const char *name)
+{
+ // remember the original system name
+ astring old_system_name(system_name());
+
+ // if the system name changed, fix up the device options
+ if (old_system_name != name)
+ {
+ // first set the new name
+ astring error;
+ set_value(OPTION_SYSTEMNAME, name, OPTION_PRIORITY_CMDLINE, error);
+ assert(!error);
+ // remove any existing device options
+ remove_device_options();
+ // then add the options
+ add_device_options(true);
+ }
+}
+
+
+//-------------------------------------------------
+// device_option - return the value of the
+// device-specific option
+//-------------------------------------------------
+
+const char *emu_options::device_option(device_image_interface &image)
+{
+ return value(image.instance_name());
+}
+
+
+//-------------------------------------------------
+// parse_one_ini - parse a single INI file
+//-------------------------------------------------
+
+bool emu_options::parse_one_ini(const char *basename, int priority, astring *error_string)
+{
+ // don't parse if it has been disabled
+ if (!read_config())
+ return false;
+
+ // open the file; if we fail, that's ok
+ emu_file file(ini_path(), OPEN_FLAG_READ);
+ file_error filerr = file.open(basename, ".ini");
+ if (filerr != FILERR_NONE)
+ return false;
+
+ // parse the file
+ mame_printf_verbose("Parsing %s.ini\n", basename);
+ astring error;
+ bool result = parse_ini_file(file, priority, OPTION_PRIORITY_DRIVER_INI, error);
+
+ // append errors if requested
+ if (error && error_string != NULL)
+ error_string->catprintf("While parsing %s:\n%s\n", file.fullpath(), error.cstr());
+
+ return result;
+}
diff --git a/trunk/src/emu/emuopts.h b/trunk/src/emu/emuopts.h
new file mode 100644
index 00000000000..4bbc3f3fa41
--- /dev/null
+++ b/trunk/src/emu/emuopts.h
@@ -0,0 +1,364 @@
+/***************************************************************************
+
+ emuopts.h
+
+ Options file and command line 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 __EMUOPTS_H__
+#define __EMUOPTS_H__
+
+#include "options.h"
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// option priorities
+enum
+{
+ // command-line options are HIGH priority
+ OPTION_PRIORITY_CMDLINE = OPTION_PRIORITY_HIGH,
+
+ // INI-based options are NORMAL priority, in increasing order:
+ OPTION_PRIORITY_INI = OPTION_PRIORITY_NORMAL,
+ OPTION_PRIORITY_MAME_INI,
+ OPTION_PRIORITY_DEBUG_INI,
+ OPTION_PRIORITY_ORIENTATION_INI,
+ OPTION_PRIORITY_VECTOR_INI,
+ OPTION_PRIORITY_SOURCE_INI,
+ OPTION_PRIORITY_GPARENT_INI,
+ OPTION_PRIORITY_PARENT_INI,
+ OPTION_PRIORITY_DRIVER_INI
+};
+
+// core options
+#define OPTION_SYSTEMNAME core_options::unadorned(0)
+#define OPTION_SOFTWARENAME core_options::unadorned(1)
+
+// core configuration options
+#define OPTION_READCONFIG "readconfig"
+#define OPTION_WRITECONFIG "writeconfig"
+
+// core search path options
+#define OPTION_MEDIAPATH "rompath"
+#define OPTION_HASHPATH "hashpath"
+#define OPTION_SAMPLEPATH "samplepath"
+#define OPTION_ARTPATH "artpath"
+#define OPTION_CTRLRPATH "ctrlrpath"
+#define OPTION_INIPATH "inipath"
+#define OPTION_FONTPATH "fontpath"
+#define OPTION_CHEATPATH "cheatpath"
+#define OPTION_CROSSHAIRPATH "crosshairpath"
+
+// core directory options
+#define OPTION_CFG_DIRECTORY "cfg_directory"
+#define OPTION_NVRAM_DIRECTORY "nvram_directory"
+#define OPTION_MEMCARD_DIRECTORY "memcard_directory"
+#define OPTION_INPUT_DIRECTORY "input_directory"
+#define OPTION_STATE_DIRECTORY "state_directory"
+#define OPTION_SNAPSHOT_DIRECTORY "snapshot_directory"
+#define OPTION_DIFF_DIRECTORY "diff_directory"
+#define OPTION_COMMENT_DIRECTORY "comment_directory"
+
+// core state/playback options
+#define OPTION_STATE "state"
+#define OPTION_AUTOSAVE "autosave"
+#define OPTION_PLAYBACK "playback"
+#define OPTION_RECORD "record"
+#define OPTION_MNGWRITE "mngwrite"
+#define OPTION_AVIWRITE "aviwrite"
+#define OPTION_WAVWRITE "wavwrite"
+#define OPTION_SNAPNAME "snapname"
+#define OPTION_SNAPSIZE "snapsize"
+#define OPTION_SNAPVIEW "snapview"
+#define OPTION_BURNIN "burnin"
+
+// core performance options
+#define OPTION_AUTOFRAMESKIP "autoframeskip"
+#define OPTION_FRAMESKIP "frameskip"
+#define OPTION_SECONDS_TO_RUN "seconds_to_run"
+#define OPTION_THROTTLE "throttle"
+#define OPTION_SLEEP "sleep"
+#define OPTION_SPEED "speed"
+#define OPTION_REFRESHSPEED "refreshspeed"
+
+// core rotation options
+#define OPTION_ROTATE "rotate"
+#define OPTION_ROR "ror"
+#define OPTION_ROL "rol"
+#define OPTION_AUTOROR "autoror"
+#define OPTION_AUTOROL "autorol"
+#define OPTION_FLIPX "flipx"
+#define OPTION_FLIPY "flipy"
+
+// core artwork options
+#define OPTION_ARTWORK_CROP "artwork_crop"
+#define OPTION_USE_BACKDROPS "use_backdrops"
+#define OPTION_USE_OVERLAYS "use_overlays"
+#define OPTION_USE_BEZELS "use_bezels"
+#define OPTION_USE_CPANELS "use_cpanels"
+#define OPTION_USE_MARQUEES "use_marquees"
+
+// core screen options
+#define OPTION_BRIGHTNESS "brightness"
+#define OPTION_CONTRAST "contrast"
+#define OPTION_GAMMA "gamma"
+#define OPTION_PAUSE_BRIGHTNESS "pause_brightness"
+#define OPTION_EFFECT "effect"
+
+// core vector options
+#define OPTION_ANTIALIAS "antialias"
+#define OPTION_BEAM "beam"
+#define OPTION_FLICKER "flicker"
+
+// core sound options
+#define OPTION_SOUND "sound"
+#define OPTION_SAMPLERATE "samplerate"
+#define OPTION_SAMPLES "samples"
+#define OPTION_VOLUME "volume"
+
+// core input options
+#define OPTION_COIN_LOCKOUT "coin_lockout"
+#define OPTION_CTRLR "ctrlr"
+#define OPTION_MOUSE "mouse"
+#define OPTION_JOYSTICK "joystick"
+#define OPTION_LIGHTGUN "lightgun"
+#define OPTION_MULTIKEYBOARD "multikeyboard"
+#define OPTION_MULTIMOUSE "multimouse"
+#define OPTION_STEADYKEY "steadykey"
+#define OPTION_OFFSCREEN_RELOAD "offscreen_reload"
+#define OPTION_JOYSTICK_MAP "joystick_map"
+#define OPTION_JOYSTICK_DEADZONE "joystick_deadzone"
+#define OPTION_JOYSTICK_SATURATION "joystick_saturation"
+#define OPTION_NATURAL_KEYBOARD "natural"
+
+// input autoenable options
+#define OPTION_PADDLE_DEVICE "paddle_device"
+#define OPTION_ADSTICK_DEVICE "adstick_device"
+#define OPTION_PEDAL_DEVICE "pedal_device"
+#define OPTION_DIAL_DEVICE "dial_device"
+#define OPTION_TRACKBALL_DEVICE "trackball_device"
+#define OPTION_LIGHTGUN_DEVICE "lightgun_device"
+#define OPTION_POSITIONAL_DEVICE "positional_device"
+#define OPTION_MOUSE_DEVICE "mouse_device"
+
+// core debugging options
+#define OPTION_LOG "log"
+#define OPTION_VERBOSE "verbose"
+#define OPTION_UPDATEINPAUSE "update_in_pause"
+#define OPTION_DEBUG "debug"
+#define OPTION_DEBUG_INTERNAL "debug_internal"
+#define OPTION_DEBUGSCRIPT "debugscript"
+
+// core misc options
+#define OPTION_BIOS "bios"
+#define OPTION_CHEAT "cheat"
+#define OPTION_SKIP_GAMEINFO "skip_gameinfo"
+#define OPTION_UI_FONT "uifont"
+#define OPTION_RAMSIZE "ramsize"
+
+#define OPTION_CONFIRM_QUIT "confirm_quit"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// forward references
+struct game_driver;
+
+
+class emu_options : public core_options
+{
+ static const UINT32 OPTION_FLAG_DEVICE = 0x80000000;
+
+public:
+ // construction/destruction
+ emu_options();
+
+ // parsing wrappers
+ bool parse_command_line(int argc, char *argv[], astring &error_string);
+ void parse_standard_inis(astring &error_string);
+ bool parse_slot_devices(int argc, char *argv[], astring &error_string, const char *name, const char *value);
+
+ // core options
+ const char *system_name() const { return value(OPTION_SYSTEMNAME); }
+ const char *software_name() const { return value(OPTION_SOFTWARENAME); }
+ const game_driver *system() const;
+ void set_system_name(const char *name);
+
+ // core configuration options
+ bool read_config() const { return bool_value(OPTION_READCONFIG); }
+ bool write_config() const { return bool_value(OPTION_WRITECONFIG); }
+
+ // core search path options
+ const char *media_path() const { return value(OPTION_MEDIAPATH); }
+ const char *hash_path() const { return value(OPTION_HASHPATH); }
+ const char *sample_path() const { return value(OPTION_SAMPLEPATH); }
+ const char *art_path() const { return value(OPTION_ARTPATH); }
+ const char *ctrlr_path() const { return value(OPTION_CTRLRPATH); }
+ const char *ini_path() const { return value(OPTION_INIPATH); }
+ const char *font_path() const { return value(OPTION_FONTPATH); }
+ const char *cheat_path() const { return value(OPTION_CHEATPATH); }
+ const char *crosshair_path() const { return value(OPTION_CROSSHAIRPATH); }
+
+ // core directory options
+ const char *cfg_directory() const { return value(OPTION_CFG_DIRECTORY); }
+ const char *nvram_directory() const { return value(OPTION_NVRAM_DIRECTORY); }
+ const char *memcard_directory() const { return value(OPTION_MEMCARD_DIRECTORY); }
+ const char *input_directory() const { return value(OPTION_INPUT_DIRECTORY); }
+ const char *state_directory() const { return value(OPTION_STATE_DIRECTORY); }
+ const char *snapshot_directory() const { return value(OPTION_SNAPSHOT_DIRECTORY); }
+ const char *diff_directory() const { return value(OPTION_DIFF_DIRECTORY); }
+ const char *comment_directory() const { return value(OPTION_COMMENT_DIRECTORY); }
+
+ // core state/playback options
+ const char *state() const { return value(OPTION_STATE); }
+ bool autosave() const { return bool_value(OPTION_AUTOSAVE); }
+ const char *playback() const { return value(OPTION_PLAYBACK); }
+ const char *record() const { return value(OPTION_RECORD); }
+ const char *mng_write() const { return value(OPTION_MNGWRITE); }
+ const char *avi_write() const { return value(OPTION_AVIWRITE); }
+ const char *wav_write() const { return value(OPTION_WAVWRITE); }
+ const char *snap_name() const { return value(OPTION_SNAPNAME); }
+ const char *snap_size() const { return value(OPTION_SNAPSIZE); }
+ const char *snap_view() const { return value(OPTION_SNAPVIEW); }
+ bool burnin() const { return bool_value(OPTION_BURNIN); }
+
+ // core performance options
+ bool auto_frameskip() const { return bool_value(OPTION_AUTOFRAMESKIP); }
+ int frameskip() const { return int_value(OPTION_FRAMESKIP); }
+ int seconds_to_run() const { return int_value(OPTION_SECONDS_TO_RUN); }
+ bool throttle() const { return bool_value(OPTION_THROTTLE); }
+ bool sleep() const { return bool_value(OPTION_SLEEP); }
+ float speed() const { return float_value(OPTION_SPEED); }
+ bool refresh_speed() const { return bool_value(OPTION_REFRESHSPEED); }
+
+ // core rotation options
+ bool rotate() const { return bool_value(OPTION_ROTATE); }
+ bool ror() const { return bool_value(OPTION_ROR); }
+ bool rol() const { return bool_value(OPTION_ROL); }
+ bool auto_ror() const { return bool_value(OPTION_AUTOROR); }
+ bool auto_rol() const { return bool_value(OPTION_AUTOROL); }
+ bool flipx() const { return bool_value(OPTION_FLIPX); }
+ bool flipy() const { return bool_value(OPTION_FLIPY); }
+
+ // core artwork options
+ bool artwork_crop() const { return bool_value(OPTION_ARTWORK_CROP); }
+ bool use_backdrops() const { return bool_value(OPTION_USE_BACKDROPS); }
+ bool use_overlays() const { return bool_value(OPTION_USE_OVERLAYS); }
+ bool use_bezels() const { return bool_value(OPTION_USE_BEZELS); }
+ bool use_cpanels() const { return bool_value(OPTION_USE_CPANELS); }
+ bool use_marquees() const { return bool_value(OPTION_USE_MARQUEES); }
+
+ // core screen options
+ float brightness() const { return float_value(OPTION_BRIGHTNESS); }
+ float contrast() const { return float_value(OPTION_CONTRAST); }
+ float gamma() const { return float_value(OPTION_GAMMA); }
+ float pause_brightness() const { return float_value(OPTION_PAUSE_BRIGHTNESS); }
+ const char *effect() const { return value(OPTION_EFFECT); }
+
+ // core vector options
+ bool antialias() const { return bool_value(OPTION_ANTIALIAS); }
+ float beam() const { return float_value(OPTION_BEAM); }
+ float flicker() const { return float_value(OPTION_FLICKER); }
+
+ // core sound options
+ bool sound() const { return bool_value(OPTION_SOUND); }
+ int sample_rate() const { return int_value(OPTION_SAMPLERATE); }
+ bool samples() const { return bool_value(OPTION_SAMPLES); }
+ int volume() const { return int_value(OPTION_VOLUME); }
+
+ // core input options
+ bool coin_lockout() const { return bool_value(OPTION_COIN_LOCKOUT); }
+ const char *ctrlr() const { return value(OPTION_CTRLR); }
+ bool mouse() const { return bool_value(OPTION_MOUSE); }
+ bool joystick() const { return bool_value(OPTION_JOYSTICK); }
+ bool lightgun() const { return bool_value(OPTION_LIGHTGUN); }
+ bool multi_keyboard() const { return bool_value(OPTION_MULTIKEYBOARD); }
+ bool multi_mouse() const { return bool_value(OPTION_MULTIMOUSE); }
+ const char *paddle_device() const { return value(OPTION_PADDLE_DEVICE); }
+ const char *adstick_device() const { return value(OPTION_ADSTICK_DEVICE); }
+ const char *pedal_device() const { return value(OPTION_PEDAL_DEVICE); }
+ const char *dial_device() const { return value(OPTION_DIAL_DEVICE); }
+ const char *trackball_device() const { return value(OPTION_TRACKBALL_DEVICE); }
+ const char *lightgun_device() const { return value(OPTION_LIGHTGUN_DEVICE); }
+ const char *positional_device() const { return value(OPTION_POSITIONAL_DEVICE); }
+ const char *mouse_device() const { return value(OPTION_MOUSE_DEVICE); }
+ const char *joystick_map() const { return value(OPTION_JOYSTICK_MAP); }
+ float joystick_deadzone() const { return float_value(OPTION_JOYSTICK_DEADZONE); }
+ float joystick_saturation() const { return float_value(OPTION_JOYSTICK_SATURATION); }
+ bool steadykey() const { return bool_value(OPTION_STEADYKEY); }
+ bool offscreen_reload() const { return bool_value(OPTION_OFFSCREEN_RELOAD); }
+ bool natural_keyboard() const { return bool_value(OPTION_NATURAL_KEYBOARD); }
+
+ // core debugging options
+ bool verbose() const { return bool_value(OPTION_VERBOSE); }
+ bool log() const { return bool_value(OPTION_LOG); }
+ bool debug() const { return bool_value(OPTION_DEBUG); }
+ bool debug_internal() const { return bool_value(OPTION_DEBUG_INTERNAL); }
+ const char *debug_script() const { return value(OPTION_DEBUGSCRIPT); }
+ bool update_in_pause() const { return bool_value(OPTION_UPDATEINPAUSE); }
+
+ // core misc options
+ const char *bios() const { return value(OPTION_BIOS); }
+ bool cheat() const { return bool_value(OPTION_CHEAT); }
+ bool skip_gameinfo() const { return bool_value(OPTION_SKIP_GAMEINFO); }
+ const char *ui_font() const { return value(OPTION_UI_FONT); }
+ const char *ram_size() const { return value(OPTION_RAMSIZE); }
+
+ bool confirm_quit() const { return bool_value(OPTION_CONFIRM_QUIT); }
+
+ // device-specific options
+ const char *device_option(device_image_interface &image);
+
+private:
+ // device-specific option handling
+ void add_device_options(bool isfirst);
+ bool add_slot_options(bool isfirst);
+ void remove_device_options();
+
+ // INI parsing helper
+ bool parse_one_ini(const char *basename, int priority, astring *error_string = NULL);
+
+ static const options_entry s_option_entries[];
+};
+
+
+#endif /* __EMUOPTS_H__ */
diff --git a/trunk/src/emu/emupal.c b/trunk/src/emu/emupal.c
new file mode 100644
index 00000000000..c92566d9a04
--- /dev/null
+++ b/trunk/src/emu/emupal.c
@@ -0,0 +1,770 @@
+/******************************************************************************
+
+ emupal.c
+
+ Emulator palette handling functions.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+******************************************************************************/
+
+#include "emu.h"
+
+#define VERBOSE 0
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define PEN_BRIGHTNESS_BITS 8
+#define MAX_PEN_BRIGHTNESS (4 << PEN_BRIGHTNESS_BITS)
+#define MAX_SHADOW_PRESETS 4
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/* information about a shadow table */
+typedef struct _shadow_table_data shadow_table_data;
+struct _shadow_table_data
+{
+ UINT32 * base; /* pointer to the base of the table */
+ INT16 dr; /* delta red value */
+ INT16 dg; /* delta green value */
+ INT16 db; /* delta blue value */
+ UINT8 noclip; /* clip? */
+};
+
+
+/* typedef struct _palette_private palette_private; */
+struct _palette_private
+{
+ bitmap_format format; /* format assumed for palette data */
+
+ UINT32 shadow_group; /* index of the shadow group, or 0 if none */
+ UINT32 hilight_group; /* index of the hilight group, or 0 if none */
+
+ pen_t black_pen; /* precomputed black pen value */
+ pen_t white_pen; /* precomputed white pen value */
+
+ shadow_table_data shadow_table[MAX_SHADOW_PRESETS]; /* array of shadow table data */
+
+ pen_t * save_pen; /* pens for save/restore */
+ float * save_bright; /* brightness for save/restore */
+};
+
+
+/* typedef struct _colortable_t colortable_t; */
+class colortable_t
+{
+public:
+ colortable_t(running_machine &machine)
+ : m_machine(machine) { }
+
+ running_machine &machine() const { return m_machine; }
+
+ UINT32 entries; /* number of entries */
+ UINT32 palentries; /* number of palette entries */
+ UINT16 * raw; /* raw data about each entry */
+ rgb_t * palette; /* palette entries */
+
+private:
+ running_machine & m_machine; /* associated machine */
+};
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void palette_presave(running_machine &machine);
+static void palette_postload(running_machine &machine);
+static void palette_exit(running_machine &machine);
+static void allocate_palette(running_machine &machine, palette_private *palette);
+static void allocate_color_tables(running_machine &machine, palette_private *palette);
+static void allocate_shadow_tables(running_machine &machine, palette_private *palette);
+static void configure_rgb_shadows(running_machine &machine, int mode, float factor);
+
+
+
+/***************************************************************************
+ INITIALIZATION AND CONFIGURATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ palette_init - palette initialization that
+ takes place before the display is created
+-------------------------------------------------*/
+
+void palette_init(running_machine &machine)
+{
+ palette_private *palette = auto_alloc_clear(machine, palette_private);
+ screen_device *device = machine.first_screen();
+
+ /* get the format from the first screen, or use BITMAP_FORMAT_INVALID, if screenless */
+ bitmap_format format = (device != NULL) ? device->format() : BITMAP_FORMAT_INVALID;
+
+ /* request cleanup */
+ machine.palette_data = palette;
+ machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(palette_exit), &machine));
+
+ /* reset all our data */
+ palette->format = format;
+
+ /* determine the color mode */
+ switch (format)
+ {
+ case BITMAP_FORMAT_INDEXED16:
+ case BITMAP_FORMAT_RGB15:
+ case BITMAP_FORMAT_RGB32:
+ /* indexed and RGB modes are fine for everything */
+ break;
+
+ case BITMAP_FORMAT_INVALID:
+ /* invalid format means no palette - or at least it should */
+ /* Do not assert for now, palette manager should be added */
+ /* in order to make possible adding of palette items per */
+ /* device otherwise we need to set total colors per driver */
+ //assert(machine.total_colors() == 0);
+ return;
+
+ default:
+ fatalerror("Unsupported screen bitmap format!");
+ break;
+ }
+
+ /* allocate all the data structures */
+ if (machine.total_colors() > 0)
+ {
+ int numcolors;
+
+ allocate_palette(machine, palette);
+ allocate_color_tables(machine, palette);
+ allocate_shadow_tables(machine, palette);
+
+ /* set up save/restore of the palette */
+ numcolors = palette_get_num_colors(machine.palette);
+ palette->save_pen = auto_alloc_array(machine, pen_t, numcolors);
+ palette->save_bright = auto_alloc_array(machine, float, numcolors);
+ state_save_register_global_pointer(machine, palette->save_pen, numcolors);
+ state_save_register_global_pointer(machine, palette->save_bright, numcolors);
+ machine.save().register_presave(save_prepost_delegate(FUNC(palette_presave), &machine));
+ machine.save().register_postload(save_prepost_delegate(FUNC(palette_postload), &machine));
+ }
+}
+
+
+
+/***************************************************************************
+ SHADOW/HIGHLIGHT CONFIGURATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ palette_set_shadow_factor - set the global
+ shadow brightness factor
+-------------------------------------------------*/
+
+void palette_set_shadow_factor(running_machine &machine, double factor)
+{
+ palette_private *palette = machine.palette_data;
+
+ assert(palette->shadow_group != 0);
+ palette_group_set_contrast(machine.palette, palette->shadow_group, factor);
+}
+
+
+/*-------------------------------------------------
+ palette_set_highlight_factor - set the global
+ highlight brightness factor
+-------------------------------------------------*/
+
+void palette_set_highlight_factor(running_machine &machine, double factor)
+{
+ palette_private *palette = machine.palette_data;
+
+ assert(palette->hilight_group != 0);
+ palette_group_set_contrast(machine.palette, palette->hilight_group, factor);
+}
+
+
+
+/***************************************************************************
+ SHADOW TABLE CONFIGURATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ palette_set_shadow_mode(mode)
+
+ mode: 0 = use preset 0 (default shadow)
+ 1 = use preset 1 (default highlight)
+ 2 = use preset 2 *
+ 3 = use preset 3 *
+
+ * Preset 2 & 3 work independently under 32bpp,
+ supporting up to four different types of
+ shadows at one time. They mirror preset 1 & 2
+ in lower depth settings to maintain
+ compatibility.
+
+
+ palette_set_shadow_dRGB32(mode, dr, dg, db, noclip)
+
+ mode: 0 to 3 (which preset to configure)
+
+ dr: -255 to 255 ( red displacement )
+ dg: -255 to 255 ( green displacement )
+ db: -255 to 255 ( blue displacement )
+
+ noclip: 0 = resultant RGB clipped at 0x00/0xff
+ 1 = resultant RGB wraparound 0x00/0xff
+
+
+ * Color shadows only work under 32bpp.
+ This function has no effect in lower color
+ depths where
+
+ palette_set_shadow_factor() or
+ palette_set_highlight_factor()
+
+ should be used instead.
+
+ * 32-bit shadows are lossy. Even with zero RGB
+ displacements the affected area will still look
+ slightly darkened.
+
+ Drivers should ensure all shadow pens in
+ gfx_drawmode_table[] are set to DRAWMODE_NONE
+ when RGB displacements are zero to avoid the
+ darkening effect.
+-------------------------------------------------*/
+
+/*-------------------------------------------------
+ palette_set_shadow_mode - select 1 of 4
+ different live shadow tables
+-------------------------------------------------*/
+
+void palette_set_shadow_mode(running_machine &machine, int mode)
+{
+ palette_private *palette = machine.palette_data;
+ assert(mode >= 0 && mode < MAX_SHADOW_PRESETS);
+ machine.shadow_table = palette->shadow_table[mode].base;
+}
+
+
+/*-------------------------------------------------
+ palette_set_shadow_dRGB32 - configure delta
+ RGB values for 1 of 4 shadow tables
+-------------------------------------------------*/
+
+void palette_set_shadow_dRGB32(running_machine &machine, int mode, int dr, int dg, int db, int noclip)
+{
+ palette_private *palette = machine.palette_data;
+ shadow_table_data *stable = &palette->shadow_table[mode];
+ int i;
+
+ /* only applies to RGB direct modes */
+ assert(palette->format != BITMAP_FORMAT_INDEXED16);
+ assert(stable->base != NULL);
+
+ /* clamp the deltas (why?) */
+ if (dr < -0xff) dr = -0xff; else if (dr > 0xff) dr = 0xff;
+ if (dg < -0xff) dg = -0xff; else if (dg > 0xff) dg = 0xff;
+ if (db < -0xff) db = -0xff; else if (db > 0xff) db = 0xff;
+
+ /* early exit if nothing changed */
+ if (dr == stable->dr && dg == stable->dg && db == stable->db && noclip == stable->noclip)
+ return;
+ stable->dr = dr;
+ stable->dg = dg;
+ stable->db = db;
+ stable->noclip = noclip;
+
+ if (VERBOSE)
+ popmessage("shadow %d recalc %d %d %d %02x", mode, dr, dg, db, noclip);
+
+ /* regenerate the table */
+ for (i = 0; i < 32768; i++)
+ {
+ int r = pal5bit(i >> 10) + dr;
+ int g = pal5bit(i >> 5) + dg;
+ int b = pal5bit(i >> 0) + db;
+ pen_t final;
+
+ /* apply clipping */
+ if (!noclip)
+ {
+ r = rgb_clamp(r);
+ g = rgb_clamp(g);
+ b = rgb_clamp(b);
+ }
+ final = MAKE_RGB(r, g, b);
+
+ /* store either 16 or 32 bit */
+ if (palette->format == BITMAP_FORMAT_RGB32)
+ stable->base[i] = final;
+ else
+ stable->base[i] = rgb_to_rgb15(final);
+ }
+}
+
+
+
+/***************************************************************************
+ COLORTABLE MANAGEMENT
+***************************************************************************/
+
+/*-------------------------------------------------
+ colortable_alloc - allocate a new colortable
+ with the given number of entries
+-------------------------------------------------*/
+
+colortable_t *colortable_alloc(running_machine &machine, UINT32 palettesize)
+{
+ colortable_t *ctable;
+ UINT32 index;
+
+ assert(palettesize > 0);
+
+ /* allocate the colortable */
+ ctable = auto_alloc_clear(machine, colortable_t(machine));
+
+ /* fill in the basics */
+ ctable->entries = machine.total_colors();
+ ctable->palentries = palettesize;
+
+ /* allocate the raw colortable */
+ ctable->raw = auto_alloc_array(machine, UINT16, ctable->entries);
+ for (index = 0; index < ctable->entries; index++)
+ ctable->raw[index] = index % ctable->palentries;
+ state_save_register_global_pointer(machine, ctable->raw, ctable->entries);
+
+ /* allocate the palette */
+ ctable->palette = auto_alloc_array(machine, rgb_t, ctable->palentries);
+ for (index = 0; index < ctable->palentries; index++)
+ ctable->palette[index] = MAKE_ARGB(0x80,0xff,0xff,0xff);
+ state_save_register_global_pointer(machine, ctable->palette, ctable->palentries);
+
+ return ctable;
+}
+
+
+/*-------------------------------------------------
+ colortable_entry_set_value - set the value
+ of a colortable entry
+-------------------------------------------------*/
+
+void colortable_entry_set_value(colortable_t *ctable, UINT32 entry, UINT16 value)
+{
+ /* ensure values are within range */
+ assert(ctable != NULL);
+ assert(entry < ctable->entries);
+ assert(value < ctable->palentries);
+
+ /* update if it has changed */
+ if (ctable->raw[entry] != value)
+ {
+ ctable->raw[entry] = value;
+ palette_set_color(ctable->machine(), entry, ctable->palette[value]);
+ }
+}
+
+
+/*-------------------------------------------------
+ colortable_entry_get_value - return the value
+ of a colortable entry
+-------------------------------------------------*/
+
+UINT16 colortable_entry_get_value(colortable_t *ctable, UINT32 entry)
+{
+ assert(ctable != NULL);
+ assert(entry < ctable->entries);
+ return ctable->raw[entry];
+}
+
+
+/*-------------------------------------------------
+ colortable_palette_set_color - change the
+ color of a colortable palette entry
+-------------------------------------------------*/
+
+void colortable_palette_set_color(colortable_t *ctable, UINT32 entry, rgb_t color)
+{
+ /* ensure values are within range */
+ assert(ctable != NULL);
+ assert(entry < ctable->palentries);
+
+ /* alpha doesn't matter */
+ color &= 0xffffff;
+
+ /* update if it has changed */
+ if (ctable->palette[entry] != color)
+ {
+ UINT32 index;
+
+ ctable->palette[entry] = color;
+
+ /* update the palette for any colortable entries that reference it */
+ for (index = 0; index < ctable->entries; index++)
+ if (ctable->raw[index] == entry)
+ palette_set_color(ctable->machine(), index, color);
+ }
+}
+
+
+/*-------------------------------------------------
+ colortable_entry_get_value - return the color
+ of a colortable palette entry
+-------------------------------------------------*/
+
+rgb_t colortable_palette_get_color(colortable_t *ctable, UINT32 entry)
+{
+ assert(ctable != NULL);
+ assert(entry < ctable->palentries);
+ return ctable->palette[entry];
+}
+
+
+/*-------------------------------------------------
+ colortable_get_transpen_mask - return a 32-bit
+ transparency mask for a given gfx element and
+ color
+-------------------------------------------------*/
+
+UINT32 colortable_get_transpen_mask(colortable_t *ctable, const gfx_element *gfx, int color, int transcolor)
+{
+ UINT32 entry = gfx->color_base + (color % gfx->total_colors) * gfx->color_granularity;
+ UINT32 mask = 0;
+ UINT32 count, bit;
+
+ /* make sure we are in range */
+ assert(ctable != NULL);
+ assert(entry < ctable->entries);
+ assert(gfx->color_depth <= 32);
+
+ /* either gfx->color_depth entries or as many as we can get up until the end */
+ count = MIN(gfx->color_depth, ctable->entries - entry);
+
+ /* set a bit anywhere the transcolor matches */
+ for (bit = 0; bit < count; bit++)
+ if (ctable->raw[entry++] == transcolor)
+ mask |= 1 << bit;
+
+ /* return the final mask */
+ return mask;
+}
+
+
+/*-------------------------------------------------
+ colortable_configure_tilemap_groups -
+ configure groups in a tilemap to represent
+ transparency based on colortable entries
+ (each group maps to a gfx color)
+-------------------------------------------------*/
+
+void colortable_configure_tilemap_groups(colortable_t *ctable, tilemap_t *tmap, const gfx_element *gfx, int transcolor)
+{
+ int color;
+
+ assert(ctable != NULL);
+ assert(gfx != NULL);
+ assert(tmap != NULL);
+ assert(gfx->total_colors <= TILEMAP_NUM_GROUPS);
+
+ /* iterate over all colors in the tilemap */
+ for (color = 0; color < gfx->total_colors; color++)
+ tilemap_set_transmask(tmap, color, colortable_get_transpen_mask(ctable, gfx, color, transcolor), 0);
+}
+
+
+/*-------------------------------------------------
+ colortable_palette_get_size -
+ return the number of entries in a colortable
+-------------------------------------------------*/
+
+UINT32 colortable_palette_get_size(colortable_t *ctable)
+{
+ assert(ctable != NULL);
+ return ctable->palentries;
+}
+
+
+
+/***************************************************************************
+ UTILITIES
+***************************************************************************/
+
+/*-------------------------------------------------
+ get_black_pen - return the pen for a fixed
+ black color
+-------------------------------------------------*/
+
+pen_t get_black_pen(running_machine &machine)
+{
+ palette_private *palette = machine.palette_data;
+ return palette->black_pen;
+}
+
+
+/*-------------------------------------------------
+ get_white_pen - return the pen for a fixed
+ white color
+-------------------------------------------------*/
+
+pen_t get_white_pen(running_machine &machine)
+{
+ palette_private *palette = machine.palette_data;
+ return palette->white_pen;
+}
+
+
+
+/***************************************************************************
+ INTERNAL FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ palette_presave - prepare the save arrays
+ for saving
+-------------------------------------------------*/
+
+static void palette_presave(running_machine &machine)
+{
+ int numcolors = palette_get_num_colors(machine.palette);
+ palette_private *palette = machine.palette_data;
+ int index;
+
+ /* fill the save arrays with updated pen and brightness information */
+ for (index = 0; index < numcolors; index++)
+ {
+ palette->save_pen[index] = palette_entry_get_color(machine.palette, index);
+ palette->save_bright[index] = palette_entry_get_contrast(machine.palette, index);
+ }
+}
+
+
+/*-------------------------------------------------
+ palette_postload - called after restore to
+ actually update the palette
+-------------------------------------------------*/
+
+static void palette_postload(running_machine &machine)
+{
+ int numcolors = palette_get_num_colors(machine.palette);
+ palette_private *palette = machine.palette_data;
+ int index;
+
+ /* reset the pen and brightness for each entry */
+ for (index = 0; index < numcolors; index++)
+ {
+ palette_entry_set_color(machine.palette, index, palette->save_pen[index]);
+ palette_entry_set_contrast(machine.palette, index, palette->save_bright[index]);
+ }
+}
+
+
+/*-------------------------------------------------
+ palette_exit - free any allocated memory
+-------------------------------------------------*/
+
+static void palette_exit(running_machine &machine)
+{
+ /* dereference the palette */
+ if (machine.palette != NULL)
+ palette_deref(machine.palette);
+}
+
+
+/*-------------------------------------------------
+ allocate_palette - allocate and configure the
+ palette object itself
+-------------------------------------------------*/
+
+static void allocate_palette(running_machine &machine, palette_private *palette)
+{
+ int numgroups, index;
+
+ /* determine the number of groups we need */
+ numgroups = 1;
+ if (machine.config().m_video_attributes & VIDEO_HAS_SHADOWS)
+ palette->shadow_group = numgroups++;
+ if (machine.config().m_video_attributes & VIDEO_HAS_HIGHLIGHTS)
+ palette->hilight_group = numgroups++;
+ assert_always(machine.total_colors() * numgroups <= 65536, "Error: palette has more than 65536 colors.");
+
+ /* allocate a palette object containing all the colors and groups */
+ machine.palette = palette_alloc(machine.total_colors(), numgroups);
+ assert_always(machine.palette != NULL, "Failed to allocate system palette");
+
+ /* configure the groups */
+ if (palette->shadow_group != 0)
+ palette_group_set_contrast(machine.palette, palette->shadow_group, (float)PALETTE_DEFAULT_SHADOW_FACTOR);
+ if (palette->hilight_group != 0)
+ palette_group_set_contrast(machine.palette, palette->hilight_group, (float)PALETTE_DEFAULT_HIGHLIGHT_FACTOR);
+
+ /* set the initial colors to a standard rainbow */
+ for (index = 0; index < machine.total_colors(); index++)
+ palette_entry_set_color(machine.palette, index, MAKE_RGB(pal1bit(index >> 0), pal1bit(index >> 1), pal1bit(index >> 2)));
+
+ /* switch off the color mode */
+ switch (palette->format)
+ {
+ /* 16-bit paletteized case */
+ case BITMAP_FORMAT_INDEXED16:
+ palette->black_pen = palette_get_black_entry(machine.palette);
+ palette->white_pen = palette_get_white_entry(machine.palette);
+ if (palette->black_pen >= 65536)
+ palette->black_pen = 0;
+ if (palette->white_pen >= 65536)
+ palette->white_pen = 65536;
+ break;
+
+ /* 15-bit direct case */
+ case BITMAP_FORMAT_RGB15:
+ palette->black_pen = rgb_to_rgb15(MAKE_RGB(0x00,0x00,0x00));
+ palette->white_pen = rgb_to_rgb15(MAKE_RGB(0xff,0xff,0xff));
+ break;
+
+ /* 32-bit direct case */
+ case BITMAP_FORMAT_RGB32:
+ palette->black_pen = MAKE_RGB(0x00,0x00,0x00);
+ palette->white_pen = MAKE_RGB(0xff,0xff,0xff);
+ break;
+
+ /* screenless case */
+ case BITMAP_FORMAT_INVALID:
+ default:
+ break;
+ }
+}
+
+
+/*-------------------------------------------------
+ allocate_color_tables - allocate memory for
+ pen and color tables
+-------------------------------------------------*/
+
+static void allocate_color_tables(running_machine &machine, palette_private *palette)
+{
+ int total_colors = palette_get_num_colors(machine.palette) * palette_get_num_groups(machine.palette);
+ pen_t *pentable;
+ int i;
+
+ /* allocate memory for the pen table */
+ switch (palette->format)
+ {
+ case BITMAP_FORMAT_INDEXED16:
+ /* create a dummy 1:1 mapping */
+ machine.pens = pentable = auto_alloc_array(machine, pen_t, total_colors + 2);
+ for (i = 0; i < total_colors + 2; i++)
+ pentable[i] = i;
+ break;
+
+ case BITMAP_FORMAT_RGB15:
+ machine.pens = palette_entry_list_adjusted_rgb15(machine.palette);
+ break;
+
+ case BITMAP_FORMAT_RGB32:
+ machine.pens = palette_entry_list_adjusted(machine.palette);
+ break;
+
+ default:
+ machine.pens = NULL;
+ break;
+ }
+}
+
+
+/*-------------------------------------------------
+ allocate_shadow_tables - allocate memory for
+ shadow tables
+-------------------------------------------------*/
+
+static void allocate_shadow_tables(running_machine &machine, palette_private *palette)
+{
+ /* if we have shadows, allocate shadow tables */
+ if (machine.config().m_video_attributes & VIDEO_HAS_SHADOWS)
+ {
+ pen_t *table = auto_alloc_array(machine, pen_t, 65536);
+ int i;
+
+ /* palettized mode gets a single 64k table in slots 0 and 2 */
+ if (palette->format == BITMAP_FORMAT_INDEXED16)
+ {
+ palette->shadow_table[0].base = palette->shadow_table[2].base = table;
+ for (i = 0; i < 65536; i++)
+ table[i] = (i < machine.total_colors()) ? (i + machine.total_colors()) : i;
+ }
+
+ /* RGB mode gets two 32k tables in slots 0 and 2 */
+ else
+ {
+ palette->shadow_table[0].base = table;
+ palette->shadow_table[2].base = table + 32768;
+ configure_rgb_shadows(machine, 0, (float)PALETTE_DEFAULT_SHADOW_FACTOR);
+ }
+ }
+
+ /* if we have hilights, allocate shadow tables */
+ if (machine.config().m_video_attributes & VIDEO_HAS_HIGHLIGHTS)
+ {
+ pen_t *table = auto_alloc_array(machine, pen_t, 65536);
+ int i;
+
+ /* palettized mode gets a single 64k table in slots 1 and 3 */
+ if (palette->format == BITMAP_FORMAT_INDEXED16)
+ {
+ palette->shadow_table[1].base = palette->shadow_table[3].base = table;
+ for (i = 0; i < 65536; i++)
+ table[i] = (i < machine.total_colors()) ? (i + 2 * machine.total_colors()) : i;
+ }
+
+ /* RGB mode gets two 32k tables in slots 1 and 3 */
+ else
+ {
+ palette->shadow_table[1].base = table;
+ palette->shadow_table[3].base = table + 32768;
+ configure_rgb_shadows(machine, 1, (float)PALETTE_DEFAULT_HIGHLIGHT_FACTOR);
+ }
+ }
+
+ /* set the default table */
+ machine.shadow_table = palette->shadow_table[0].base;
+}
+
+
+/*-------------------------------------------------
+ configure_rgb_shadows - configure shadows
+ for the RGB tables
+-------------------------------------------------*/
+
+static void configure_rgb_shadows(running_machine &machine, int mode, float factor)
+{
+ palette_private *palette = machine.palette_data;
+ shadow_table_data *stable = &palette->shadow_table[mode];
+ int ifactor = (int)(factor * 256.0f);
+ int i;
+
+ /* only applies to RGB direct modes */
+ assert(palette->format != BITMAP_FORMAT_INDEXED16);
+ assert(stable->base != NULL);
+
+ /* regenerate the table */
+ for (i = 0; i < 32768; i++)
+ {
+ UINT8 r = rgb_clamp((pal5bit(i >> 10) * ifactor) >> 8);
+ UINT8 g = rgb_clamp((pal5bit(i >> 5) * ifactor) >> 8);
+ UINT8 b = rgb_clamp((pal5bit(i >> 0) * ifactor) >> 8);
+ pen_t final = MAKE_RGB(r, g, b);
+
+ /* store either 16 or 32 bit */
+ if (palette->format == BITMAP_FORMAT_RGB32)
+ stable->base[i] = final;
+ else
+ stable->base[i] = rgb_to_rgb15(final);
+ }
+}
diff --git a/trunk/src/emu/emupal.h b/trunk/src/emu/emupal.h
new file mode 100644
index 00000000000..1180cfdb25a
--- /dev/null
+++ b/trunk/src/emu/emupal.h
@@ -0,0 +1,250 @@
+/******************************************************************************
+
+ emupal.h
+
+ Emulator palette handling functions.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+ There are several levels of abstraction in the way MAME handles the palette,
+ and several display modes which can be used by the drivers.
+
+ Palette
+ -------
+ Note: in the following text, "color" refers to a color in the emulated
+ game's virtual palette. For example, a game might be able to display 1024
+ colors at the same time. If the game uses RAM to change the available
+ colors, the term "palette" refers to the colors available at any given time,
+ not to the whole range of colors which can be produced by the hardware. The
+ latter is referred to as "color space".
+ The term "pen" refers to one of the maximum MAX_PENS colors that can be
+ used to generate the display.
+
+ So, to summarize, the three layers of palette abstraction are:
+
+ P1) The game virtual palette (the "colors")
+ P2) MAME's MAX_PENS colors palette (the "pens")
+ P3) The OS specific hardware color registers (the "OS specific pens")
+
+ The array Machine->pens[] is a lookup table which maps game colors to OS
+ specific pens (P1 to P3). When you are working on bitmaps at the pixel level,
+ *always* use Machine->pens to map the color numbers. *Never* use constants.
+ For example if you want to make pixel (x,y) of color 3, do:
+ *BITMAP_ADDR(bitmap, <type>, y, x) = Machine->pens[3];
+
+
+ Lookup table
+ ------------
+ Palettes are only half of the story. To map the gfx data to colors, the
+ graphics routines use a lookup table. For example if we have 4bpp tiles,
+ which can have 256 different color codes, the lookup table for them will have
+ 256 * 2^4 = 4096 elements. For games using a palette RAM, the lookup table is
+ usually a 1:1 map. For games using PROMs, the lookup table is often larger
+ than the palette itself so for example the game can display 256 colors out
+ of a palette of 16.
+
+ The palette and the lookup table are initialized to default values by the
+ main core, but can be initialized by the driver using the function
+ MachineDriver->vh_init_palette(). For games using palette RAM, that
+ function is usually not needed, and the lookup table can be set up by
+ properly initializing the color_codes_start and total_color_codes fields in
+ the GfxDecodeInfo array.
+ When vh_init_palette() initializes the lookup table, it maps gfx codes
+ to game colors (P1 above). The lookup table will be converted by the core to
+ map to OS specific pens (P3 above), and stored in Machine->remapped_colortable.
+
+
+ Display modes
+ -------------
+ The available display modes can be summarized in three categories:
+ 1) Static palette. Use this for games which use PROMs for color generation.
+ The palette is initialized by palette_init(), and never changed
+ again.
+ 2) Dynamic palette. Use this for games which use RAM for color generation.
+ The palette can be dynamically modified by the driver using the function
+ palette_set_color().
+ 3) Direct mapped 16-bit or 32-bit color. This should only be used in special
+ cases, e.g. to support alpha blending.
+ MachineDriver->video_attributes must contain VIDEO_RGB_DIRECT.
+
+
+ Shadows(Highlights) Quick Reference
+ -----------------------------------
+
+ 1) declare MCFG_VIDEO_ATTRIBUTES( ... VIDEO_HAS_SHADOWS | VIDEO_HAS_HIGHLIGHTS ... )
+
+ 2) make a pen table fill with DRAWMODE_NONE, DRAWMODE_SOURCE or DRAWMODE_SHADOW
+
+ 3) (optional) set shadow darkness or highlight brightness by
+ palette_set_shadow_factor(0.0-1.0) or
+ palette_set_highlight_factor(1.0-n.n)
+
+ 4) before calling drawgfx use
+ palette_set_shadow_mode(0) to arm shadows or
+ palette_set_shadow_mode(1) to arm highlights
+
+ 5) call drawgfx_transtable
+ drawgfx_transtable( ..., pentable )
+
+******************************************************************************/
+
+#pragma once
+
+#ifndef __EMU_H__
+#error Dont include this file directly; include emu.h instead.
+#endif
+
+#ifndef __EMUPAL_H__
+#define __EMUPAL_H__
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define PALETTE_DEFAULT_SHADOW_FACTOR (0.6)
+#define PALETTE_DEFAULT_HIGHLIGHT_FACTOR (1/PALETTE_DEFAULT_SHADOW_FACTOR)
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+class colortable_t;
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+
+/* ----- initialization and configuration ----- */
+
+/* palette initialization that takes place before the display is created */
+void palette_init(running_machine &machine);
+
+
+
+/* ----- shadow/hilight configuration ----- */
+
+/* set the global shadow brightness factor */
+void palette_set_shadow_factor(running_machine &machine, double factor);
+
+/* set the global highlight brightness factor */
+void palette_set_highlight_factor(running_machine &machine, double factor);
+
+
+
+/* ----- shadow table configuration ----- */
+
+/* select 1 of 4 different live shadow tables */
+void palette_set_shadow_mode(running_machine &machine, int mode);
+
+/* configure delta RGB values for 1 of 4 shadow tables */
+void palette_set_shadow_dRGB32(running_machine &machine, int mode, int dr, int dg, int db, int noclip);
+
+
+
+/* ----- colortable management ----- */
+
+/* allocate a new colortable with the given number of entries */
+colortable_t *colortable_alloc(running_machine &machine, UINT32 palettesize);
+
+/* set the value of a colortable entry */
+void colortable_entry_set_value(colortable_t *ctable, UINT32 entry, UINT16 value);
+
+/* return the value of a colortable entry */
+UINT16 colortable_entry_get_value(colortable_t *ctable, UINT32 entry);
+
+/* change the color of a colortable palette entry */
+void colortable_palette_set_color(colortable_t *ctable, UINT32 entry, rgb_t color);
+
+/* return the color of a colortable palette entry */
+rgb_t colortable_palette_get_color(colortable_t *ctable, UINT32 entry);
+
+/* return a 32-bit transparency mask for a given gfx element and color */
+UINT32 colortable_get_transpen_mask(colortable_t *ctable, const gfx_element *gfx, int color, int transcolor);
+
+/* configure groups in a tilemap to represent transparency based on colortable entries (each group maps to a gfx color) */
+void colortable_configure_tilemap_groups(colortable_t *ctable, tilemap_t *tmap, const gfx_element *gfx, int transcolor);
+
+/* return the number of entries in a colortable */
+UINT32 colortable_palette_get_size(colortable_t *ctable);
+
+
+
+/* ----- utilities ----- */
+
+/* return the pen for a fixed black color */
+pen_t get_black_pen(running_machine &machine);
+
+/* return the pen for a fixed white color */
+pen_t get_white_pen(running_machine &machine);
+
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ palette_set_color - set a single palette
+ entry
+-------------------------------------------------*/
+
+INLINE void palette_set_color(running_machine &machine, pen_t pen, rgb_t rgb)
+{
+ palette_entry_set_color(machine.palette, pen, rgb);
+}
+
+
+/*-------------------------------------------------
+ palette_set_color_rgb - set a single palette
+ entry with individual R,G,B components
+-------------------------------------------------*/
+
+INLINE void palette_set_color_rgb(running_machine &machine, pen_t pen, UINT8 r, UINT8 g, UINT8 b)
+{
+ palette_entry_set_color(machine.palette, pen, MAKE_RGB(r, g, b));
+}
+
+
+/*-------------------------------------------------
+ palette_get_color - return a single palette
+ entry
+-------------------------------------------------*/
+
+INLINE rgb_t palette_get_color(running_machine &machine, pen_t pen)
+{
+ return palette_entry_get_color(machine.palette, pen);
+}
+
+
+/*-------------------------------------------------
+ palette_set_pen_contrast - set the per-pen
+ contrast factor
+-------------------------------------------------*/
+
+INLINE void palette_set_pen_contrast(running_machine &machine, pen_t pen, double bright)
+{
+ palette_entry_set_contrast(machine.palette, pen, bright);
+}
+
+
+/*-------------------------------------------------
+ palette_set_colors - set multiple palette
+ entries from an array of rgb_t values
+-------------------------------------------------*/
+
+INLINE void palette_set_colors(running_machine &machine, pen_t color_base, const rgb_t *colors, int color_count)
+{
+ while (color_count--)
+ palette_entry_set_color(machine.palette, color_base++, *colors++);
+}
+
+
+#endif /* __PALETTE_H__ */
diff --git a/trunk/src/emu/emutempl.h b/trunk/src/emu/emutempl.h
new file mode 100644
index 00000000000..fcd89c03eb7
--- /dev/null
+++ b/trunk/src/emu/emutempl.h
@@ -0,0 +1,431 @@
+/***************************************************************************
+
+ emutempl.h
+
+ Core templates for basic non-string types.
+
+****************************************************************************
+
+ 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 __EMUTEMPL_H__
+#define __EMUTEMPL_H__
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> simple_list
+
+// a simple_list is a singly-linked list whose 'next' pointer is owned
+// by the object
+template<class _ElementType>
+class simple_list
+{
+ // we don't support deep copying
+ DISABLE_COPYING(simple_list);
+
+public:
+ // construction/destruction
+ simple_list(resource_pool &pool = global_resource_pool) :
+ m_head(NULL),
+ m_tail(NULL),
+ m_pool(pool),
+ m_count(0) { }
+
+ virtual ~simple_list() { reset(); }
+
+ // simple getters
+ resource_pool &pool() const { return m_pool; }
+ _ElementType *first() const { return m_head; }
+ _ElementType *last() const { return m_tail; }
+ int count() const { return m_count; }
+
+ // remove (free) all objects in the list, leaving an empty list
+ void reset()
+ {
+ while (m_head != NULL)
+ remove(*m_head);
+ }
+
+ // add the given object to the head of the list
+ _ElementType &prepend(_ElementType &object)
+ {
+ object.m_next = m_head;
+ m_head = &object;
+ if (m_tail == NULL)
+ m_tail = m_head;
+ m_count++;
+ return object;
+ }
+
+ // add the given list to the head of the list
+ void prepend_list(simple_list<_ElementType> &list)
+ {
+ int count = list.count();
+ if (count == 0)
+ return;
+ _ElementType *tail = list.last();
+ _ElementType *head = list.detach_all();
+ tail->m_next = m_head;
+ m_head = head;
+ if (m_tail == NULL)
+ m_tail = tail;
+ m_count += count;
+ }
+
+ // add the given object to the tail of the list
+ _ElementType &append(_ElementType &object)
+ {
+ object.m_next = NULL;
+ if (m_tail != NULL)
+ m_tail = m_tail->m_next = &object;
+ else
+ m_tail = m_head = &object;
+ m_count++;
+ return object;
+ }
+
+ // add the given list to the tail of the list
+ void append_list(simple_list<_ElementType> &list)
+ {
+ int count = list.count();
+ if (count == 0)
+ return;
+ _ElementType *tail = list.last();
+ _ElementType *head = list.detach_all();
+ if (m_tail != NULL)
+ m_tail->m_next = head;
+ else
+ m_head = head;
+ m_tail = tail;
+ m_count += count;
+ }
+
+ // insert the given object after a particular object (NULL means prepend)
+ _ElementType &insert_after(_ElementType &object, _ElementType *insert_after)
+ {
+ if (insert_after == NULL)
+ return prepend(object);
+ object.m_next = insert_after->m_next;
+ insert_after->m_next = &object;
+ if (m_tail == insert_after)
+ m_tail = &object;
+ m_count++;
+ return object;
+ }
+
+ // insert the given object before a particular object (NULL means append)
+ _ElementType &insert_before(_ElementType &object, _ElementType *insert_before)
+ {
+ if (insert_before == NULL)
+ return append(object);
+ for (_ElementType **curptr = &m_head; *curptr != NULL; curptr = &(*curptr)->m_next)
+ if (*curptr == insert_before)
+ {
+ object.m_next = insert_before;
+ *curptr = &object;
+ if (m_head == insert_before)
+ m_head = &object;
+ m_count++;
+ return object;
+ }
+ return object;
+ }
+
+ // replace an item in the list at the same location, and remove it
+ _ElementType &replace_and_remove(_ElementType &object, _ElementType &toreplace)
+ {
+ _ElementType *prev = NULL;
+ for (_ElementType *cur = m_head; cur != NULL; prev = cur, cur = cur->m_next)
+ if (cur == &toreplace)
+ {
+ if (prev != NULL)
+ prev->m_next = &object;
+ else
+ m_head = &object;
+ if (m_tail == &toreplace)
+ m_tail = &object;
+ object.m_next = toreplace.m_next;
+ pool_free(m_pool, &toreplace);
+ return object;
+ }
+ return append(object);
+ }
+
+ // detach the head item from the list, but don't free its memory
+ _ElementType *detach_head()
+ {
+ _ElementType *result = m_head;
+ if (result != NULL)
+ {
+ m_head = result->m_next;
+ m_count--;
+ if (m_head == NULL)
+ m_tail = NULL;
+ }
+ return result;
+ }
+
+ // detach the given item from the list, but don't free its memory
+ _ElementType &detach(_ElementType &object)
+ {
+ _ElementType *prev = NULL;
+ for (_ElementType *cur = m_head; cur != NULL; prev = cur, cur = cur->m_next)
+ if (cur == &object)
+ {
+ if (prev != NULL)
+ prev->m_next = object.m_next;
+ else
+ m_head = object.m_next;
+ if (m_tail == &object)
+ m_tail = prev;
+ m_count--;
+ return object;
+ }
+ return object;
+ }
+
+ // deatch the entire list, returning the head, but don't free memory
+ _ElementType *detach_all()
+ {
+ _ElementType *result = m_head;
+ m_head = m_tail = NULL;
+ m_count = 0;
+ return result;
+ }
+
+ // remove the given object and free its memory
+ void remove(_ElementType &object)
+ {
+ detach(object);
+ pool_free(m_pool, &object);
+ }
+
+ // find an object by index in the list
+ _ElementType *find(int index) const
+ {
+ for (_ElementType *cur = m_head; cur != NULL; cur = cur->m_next)
+ if (index-- == 0)
+ return cur;
+ return NULL;
+ }
+
+ // return the index of the given object in the list
+ int indexof(const _ElementType &object) const
+ {
+ int index = 0;
+ for (_ElementType *cur = m_head; cur != NULL; cur = cur->m_next)
+ {
+ if (cur == &object)
+ return index;
+ index++;
+ }
+ return -1;
+ }
+
+private:
+ // internal state
+ _ElementType * m_head; // head of the singly-linked list
+ _ElementType * m_tail; // tail of the singly-linked list
+ resource_pool & m_pool; // resource pool where objects are freed
+ int m_count; // number of objects in the list
+};
+
+
+// ======================> simple_list_wrapper
+
+// a simple_list_wrapper wraps an existing object with a next pointer so it
+// can live in a simple_list without requiring the object to have a next
+// pointer
+template<class _ObjectType>
+class simple_list_wrapper
+{
+public:
+ // construction/destruction
+ simple_list_wrapper(_ObjectType *object)
+ : m_next(NULL),
+ m_object(object) { }
+
+ // operators
+ operator _ObjectType *() { return m_object; }
+ operator _ObjectType *() const { return m_object; }
+ _ObjectType *operator *() { return m_object; }
+ _ObjectType *operator *() const { return m_object; }
+
+ // getters
+ simple_list_wrapper *next() const { return m_next; }
+ _ObjectType *object() const { return m_object; }
+
+private:
+ // internal state
+ simple_list_wrapper * m_next;
+ _ObjectType * m_object;
+};
+
+
+// ======================> fixed_allocator
+
+// a fixed_allocator is a simple class that maintains a free pool of objects
+template<class _ItemType>
+class fixed_allocator
+{
+ // we don't support deep copying
+ DISABLE_COPYING(fixed_allocator);
+
+public:
+ // construction/destruction
+ fixed_allocator(resource_pool &pool = global_resource_pool)
+ : m_freelist(pool) { }
+
+ // allocate a new item, either by recycling an old one, or by allocating a new one
+ _ItemType *alloc()
+ {
+ _ItemType *result = m_freelist.detach_head();
+ if (result == NULL)
+ result = m_freelist.pool().add_object(new _ItemType);
+ return result;
+ }
+
+ // reclaim an item by adding it to the free list
+ void reclaim(_ItemType *item) { if (item != NULL) m_freelist.append(*item); }
+ void reclaim(_ItemType &item) { m_freelist.append(item); }
+
+ // reclaim all items from a list
+ void reclaim_all(simple_list<_ItemType> &list) { m_freelist.append_list(list); }
+
+private:
+ // internal state
+ simple_list<_ItemType> m_freelist; // list of free objects
+};
+
+
+// ======================> tagged_list
+
+// a tagged_list is a class that maintains a list of objects that can be quickly looked up by tag
+template<class _ElementType>
+class tagged_list
+{
+ // we don't support deep copying
+ DISABLE_COPYING(tagged_list);
+
+public:
+ // construction/destruction
+ tagged_list(resource_pool &pool = global_resource_pool) :
+ m_list(pool) { }
+
+ // simple getters
+ resource_pool &pool() const { return m_list.pool(); }
+ _ElementType *first() const { return m_list.first(); }
+ _ElementType *last() const { return m_list.last(); }
+ int count() const { return m_list.count(); }
+
+ // remove (free) all objects in the list, leaving an empty list
+ void reset() { m_list.reset(); m_map.reset(); }
+
+ // add the given object to the head of the list
+ _ElementType &prepend(const char *tag, _ElementType &object)
+ {
+ if (m_map.add_unique_hash(tag, &object, false) != TMERR_NONE)
+ throw emu_fatalerror("Error adding object named '%s'", tag);
+ return m_list.prepend(object);
+ }
+
+ // add the given object to the tail of the list
+ _ElementType &append(const char *tag, _ElementType &object)
+ {
+ if (m_map.add_unique_hash(tag, &object, false) != TMERR_NONE)
+ throw emu_fatalerror("Error adding object named '%s'", tag);
+ return m_list.append(object);
+ }
+
+ // insert the given object after a particular object (NULL means prepend)
+ _ElementType &insert_after(const char *tag, _ElementType &object, _ElementType *insert_after)
+ {
+ if (m_map.add_unique_hash(tag, &object, false) != TMERR_NONE)
+ throw emu_fatalerror("Error adding object named '%s'", tag);
+ return m_list.insert_after(object, insert_after);
+ }
+
+ // replace an item in the list at the same location, and remove it
+ _ElementType &replace_and_remove(const char *tag, _ElementType &object, _ElementType &toreplace)
+ {
+ m_map.remove(&toreplace);
+ m_list.replace_and_remove(object, toreplace);
+ if (m_map.add_unique_hash(tag, &object, false) != TMERR_NONE)
+ throw emu_fatalerror("Error replacing object named '%s'", tag);
+ return object;
+ }
+
+ // detach the given item from the list, but don't free its memory
+ _ElementType &detach(_ElementType &object)
+ {
+ m_map.remove(&object);
+ return m_list.detach(object);
+ }
+
+ // remove the given object and free its memory
+ void remove(_ElementType &object)
+ {
+ m_map.remove(&object);
+ return m_list.remove(object);
+ }
+
+ // find an object by index in the list
+ _ElementType *find(int index) const
+ {
+ return m_list.find(index);
+ }
+
+ // return the index of the given object in the list
+ int indexof(const _ElementType &object) const
+ {
+ return m_list.indexof(object);
+ }
+
+ // operations by tag
+ _ElementType &replace_and_remove(const char *tag, _ElementType &object) { _ElementType *existing = find(tag); return (existing == NULL) ? append(tag, object) : replace_and_remove(tag, object, *existing); }
+ void remove(const char *tag) { _ElementType *object = find(tag); if (object != NULL) remove(*object); }
+ _ElementType *find(const char *tag) const { return m_map.find_hash_only(tag); }
+ int indexof(const char *tag) const { _ElementType *object = find(tag); return (object != NULL) ? m_list.indexof(*object) : NULL; }
+
+private:
+ // internal state
+ simple_list<_ElementType> m_list;
+ tagmap_t<_ElementType *> m_map;
+};
+
+
+#endif /* __EMUTEMPL_H__ */
diff --git a/trunk/src/emu/fileio.c b/trunk/src/emu/fileio.c
new file mode 100644
index 00000000000..bf0e61e62bf
--- /dev/null
+++ b/trunk/src/emu/fileio.c
@@ -0,0 +1,769 @@
+/***************************************************************************
+
+ fileio.c
+
+ File access 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 "hash.h"
+#include "unzip.h"
+#include "fileio.h"
+
+
+const UINT32 OPEN_FLAG_HAS_CRC = 0x10000;
+
+
+
+//**************************************************************************
+// PATH ITERATOR
+//**************************************************************************
+
+//-------------------------------------------------
+// path_iterator - constructor
+//-------------------------------------------------
+
+path_iterator::path_iterator(const char *rawsearchpath)
+ : m_base(rawsearchpath),
+ m_current(m_base),
+ m_index(0)
+{
+}
+
+
+//-------------------------------------------------
+// path_iterator_get_next - get the next entry
+// in a multipath sequence
+//-------------------------------------------------
+
+bool path_iterator::next(astring &buffer, const char *name)
+{
+ // if none left, return FALSE to indicate we are done
+ if (m_index != 0 && *m_current == 0)
+ return false;
+
+ // copy up to the next semicolon
+ const char *semi = strchr(m_current, ';');
+ if (semi == NULL)
+ semi = m_current + strlen(m_current);
+ buffer.cpy(m_current, semi - m_current);
+ m_current = (*semi == 0) ? semi : semi + 1;
+
+ // append the name if we have one
+ if (name != NULL)
+ {
+ // compute the full pathname
+ if (buffer.len() > 0)
+ buffer.cat(PATH_SEPARATOR);
+ buffer.cat(name);
+ }
+
+ // bump the index and return TRUE
+ m_index++;
+ return true;
+}
+
+
+
+//**************************************************************************
+// FILE ENUMERATOR
+//**************************************************************************
+
+//-------------------------------------------------
+// file_enumerator - constructor
+//-------------------------------------------------
+
+file_enumerator::file_enumerator(const char *searchpath)
+ : m_iterator(searchpath),
+ m_curdir(NULL),
+ m_buflen(0)
+{
+}
+
+
+//-------------------------------------------------
+// ~file_enumerator - destructor
+//-------------------------------------------------
+
+file_enumerator::~file_enumerator()
+{
+ // close anything open
+ if (m_curdir != NULL)
+ osd_closedir(m_curdir);
+}
+
+
+//-------------------------------------------------
+// next - return information about the next file
+// in the search path
+//-------------------------------------------------
+
+const osd_directory_entry *file_enumerator::next()
+{
+ // loop over potentially empty directories
+ while (1)
+ {
+ // if no open directory, get the next path
+ while (m_curdir == NULL)
+ {
+ // if we fail to get anything more, we're done
+ if (!m_iterator.next(m_pathbuffer))
+ return NULL;
+
+ // open the path
+ m_curdir = osd_opendir(m_pathbuffer);
+ }
+
+ // get the next entry from the current directory
+ const osd_directory_entry *result = osd_readdir(m_curdir);
+ if (result != NULL)
+ return result;
+
+ // we're done; close this directory
+ osd_closedir(m_curdir);
+ m_curdir = NULL;
+ }
+}
+
+
+
+//**************************************************************************
+// EMU FILE
+//**************************************************************************
+
+//-------------------------------------------------
+// emu_file - constructor
+//-------------------------------------------------
+
+emu_file::emu_file(UINT32 openflags)
+ : m_file(NULL),
+ m_iterator(""),
+ m_crc(0),
+ m_openflags(openflags),
+ m_zipfile(NULL),
+ m_zipdata(NULL),
+ m_ziplength(0),
+ m_remove_on_close(false)
+{
+ // sanity check the open flags
+ if ((m_openflags & OPEN_FLAG_HAS_CRC) && (m_openflags & OPEN_FLAG_WRITE))
+ throw emu_fatalerror("Attempted to open a file for write with OPEN_FLAG_HAS_CRC");
+}
+
+emu_file::emu_file(const char *searchpath, UINT32 openflags)
+ : m_file(NULL),
+ m_iterator(searchpath),
+ m_crc(0),
+ m_openflags(openflags),
+ m_zipfile(NULL),
+ m_zipdata(NULL),
+ m_ziplength(0),
+ m_remove_on_close(false)
+{
+ // sanity check the open flags
+ if ((m_openflags & OPEN_FLAG_HAS_CRC) && (m_openflags & OPEN_FLAG_WRITE))
+ throw emu_fatalerror("Attempted to open a file for write with OPEN_FLAG_HAS_CRC");
+}
+
+
+//-------------------------------------------------
+// ~emu_file - destructor
+//-------------------------------------------------
+
+emu_file::~emu_file()
+{
+ // close in the standard way
+ close();
+}
+
+
+//-------------------------------------------------
+// operator core_file - automatically convert
+// ourselves to a core_file pointer
+//-------------------------------------------------
+
+emu_file::operator core_file *()
+{
+ // load the ZIP file now if we haven't yet
+ if (m_zipfile != NULL && load_zipped_file() != FILERR_NONE)
+ return NULL;
+
+ // return the core file
+ return m_file;
+}
+
+emu_file::operator core_file &()
+{
+ // load the ZIP file now if we haven't yet
+ if (m_zipfile != NULL && load_zipped_file() != FILERR_NONE)
+ throw emu_fatalerror("operator core_file & used on invalid file");
+
+ // return the core file
+ return *m_file;
+}
+
+
+//-------------------------------------------------
+// hash - returns the hash for a file
+//-------------------------------------------------
+
+hash_collection &emu_file::hashes(const char *types)
+{
+ // determine which hashes we need
+ astring needed;
+ for (const char *scan = types; *scan != 0; scan++)
+ if (m_hashes.hash(*scan) == NULL)
+ needed.cat(*scan);
+
+ // if we need nothing, skip it
+ if (!needed)
+ return m_hashes;
+
+ // load the ZIP file if needed
+ if (m_zipfile != NULL && load_zipped_file() != FILERR_NONE)
+ return m_hashes;
+ if (m_file == NULL)
+ return m_hashes;
+
+ // if we have ZIP data, just hash that directly
+ if (m_zipdata != NULL)
+ {
+ m_hashes.compute(m_zipdata, m_ziplength, needed);
+ return m_hashes;
+ }
+
+ // read the data if we can
+ const UINT8 *filedata = (const UINT8 *)core_fbuffer(m_file);
+ if (filedata == NULL)
+ return m_hashes;
+
+ // compute the hash
+ m_hashes.compute(filedata, core_fsize(m_file), needed);
+ return m_hashes;
+}
+
+
+//-------------------------------------------------
+// open - open a file by searching paths
+//-------------------------------------------------
+
+file_error emu_file::open(const char *name)
+{
+ // remember the filename and CRC info
+ m_filename = name;
+ m_crc = 0;
+ m_openflags &= ~OPEN_FLAG_HAS_CRC;
+
+ // reset the iterator and open_next
+ m_iterator.reset();
+ return open_next();
+}
+
+file_error emu_file::open(const char *name1, const char *name2)
+{
+ // concatenate the strings and do a standard open
+ astring name(name1, name2);
+ return open(name);
+}
+
+file_error emu_file::open(const char *name1, const char *name2, const char *name3)
+{
+ // concatenate the strings and do a standard open
+ astring name(name1, name2, name3);
+ return open(name);
+}
+
+file_error emu_file::open(const char *name1, const char *name2, const char *name3, const char *name4)
+{
+ // concatenate the strings and do a standard open
+ astring name(name1, name2, name3, name4);
+ return open(name);
+}
+
+file_error emu_file::open(const char *name, UINT32 crc)
+{
+ // remember the filename and CRC info
+ m_filename = name;
+ m_crc = crc;
+ m_openflags |= OPEN_FLAG_HAS_CRC;
+
+ // reset the iterator and open_next
+ m_iterator.reset();
+ return open_next();
+}
+
+file_error emu_file::open(const char *name1, const char *name2, UINT32 crc)
+{
+ // concatenate the strings and do a standard open
+ astring name(name1, name2);
+ return open(name, crc);
+}
+
+file_error emu_file::open(const char *name1, const char *name2, const char *name3, UINT32 crc)
+{
+ // concatenate the strings and do a standard open
+ astring name(name1, name2, name3);
+ return open(name, crc);
+}
+
+file_error emu_file::open(const char *name1, const char *name2, const char *name3, const char *name4, UINT32 crc)
+{
+ // concatenate the strings and do a standard open
+ astring name(name1, name2, name3, name4);
+ return open(name, crc);
+}
+
+
+//-------------------------------------------------
+// open_next - open the next file that matches
+// the filename by iterating over paths
+//-------------------------------------------------
+
+file_error emu_file::open_next()
+{
+ // if we're open from a previous attempt, close up now
+ if (m_file != NULL)
+ close();
+
+ // loop over paths
+ file_error filerr = FILERR_NOT_FOUND;
+ while (m_iterator.next(m_fullpath, m_filename))
+ {
+ // attempt to open the file directly
+ filerr = core_fopen(m_fullpath, m_openflags, &m_file);
+ if (filerr == FILERR_NONE)
+ break;
+
+ // if we're opening for read-only we have other options
+ if ((m_openflags & (OPEN_FLAG_READ | OPEN_FLAG_WRITE)) == OPEN_FLAG_READ)
+ {
+ filerr = attempt_zipped();
+ if (filerr == FILERR_NONE)
+ break;
+ }
+ }
+ return filerr;
+}
+
+
+//-------------------------------------------------
+// open_ram - open a "file" which is actually
+// just an array of data in RAM
+//-------------------------------------------------
+
+file_error emu_file::open_ram(const void *data, UINT32 length)
+{
+ // set a fake filename and CRC
+ m_filename = "RAM";
+ m_crc = 0;
+
+ // use the core_file's built-in RAM support
+ return core_fopen_ram(data, length, m_openflags, &m_file);
+}
+
+
+//-------------------------------------------------
+// close - close a file and free all data; also
+// remove the file if requested
+//-------------------------------------------------
+
+void emu_file::close()
+{
+ // close files and free memory
+ if (m_zipfile != NULL)
+ zip_file_close(m_zipfile);
+ m_zipfile = NULL;
+
+ if (m_file != NULL)
+ core_fclose(m_file);
+ m_file = NULL;
+
+ if (m_zipdata != NULL)
+ global_free(m_zipdata);
+ m_zipdata = NULL;
+
+ if (m_remove_on_close)
+ osd_rmfile(m_fullpath);
+ m_remove_on_close = false;
+
+ // reset our hashes and path as well
+ m_hashes.reset();
+ m_fullpath.reset();
+}
+
+
+//-------------------------------------------------
+// compress - enable/disable streaming file
+// compression via zlib; level is 0 to disable
+// compression, or up to 9 for max compression
+//-------------------------------------------------
+
+file_error emu_file::compress(int level)
+{
+ return core_fcompress(m_file, level);
+}
+
+
+//-------------------------------------------------
+// seek - seek within a file
+//-------------------------------------------------
+
+int emu_file::seek(INT64 offset, int whence)
+{
+ // load the ZIP file now if we haven't yet
+ if (m_zipfile != NULL && load_zipped_file() != FILERR_NONE)
+ return 1;
+
+ // seek if we can
+ if (m_file != NULL)
+ return core_fseek(m_file, offset, whence);
+
+ return 1;
+}
+
+
+//-------------------------------------------------
+// tell - return the current file position
+//-------------------------------------------------
+
+UINT64 emu_file::tell()
+{
+ // load the ZIP file now if we haven't yet
+ if (m_zipfile != NULL && load_zipped_file() != FILERR_NONE)
+ return 0;
+
+ // tell if we can
+ if (m_file != NULL)
+ return core_ftell(m_file);
+
+ return 0;
+}
+
+
+//-------------------------------------------------
+// eof - return true if we're at the end of file
+//-------------------------------------------------
+
+bool emu_file::eof()
+{
+ // load the ZIP file now if we haven't yet
+ if (m_zipfile != NULL && load_zipped_file() != FILERR_NONE)
+ return 0;
+
+ // return EOF if we can
+ if (m_file != NULL)
+ return core_feof(m_file);
+
+ return 0;
+}
+
+
+//-------------------------------------------------
+// size - returns the size of a file
+//-------------------------------------------------
+
+UINT64 emu_file::size()
+{
+ // use the ZIP length if present
+ if (m_zipfile != NULL)
+ return m_ziplength;
+
+ // return length if we can
+ if (m_file != NULL)
+ return core_fsize(m_file);
+
+ return 0;
+}
+
+
+//-------------------------------------------------
+// read - read from a file
+//-------------------------------------------------
+
+UINT32 emu_file::read(void *buffer, UINT32 length)
+{
+ // load the ZIP file now if we haven't yet
+ if (m_zipfile != NULL && load_zipped_file() != FILERR_NONE)
+ return 0;
+
+ // read the data if we can
+ if (m_file != NULL)
+ return core_fread(m_file, buffer, length);
+
+ return 0;
+}
+
+
+//-------------------------------------------------
+// getc - read a character from a file
+//-------------------------------------------------
+
+int emu_file::getc()
+{
+ // load the ZIP file now if we haven't yet
+ if (m_zipfile != NULL && load_zipped_file() != FILERR_NONE)
+ return EOF;
+
+ // read the data if we can
+ if (m_file != NULL)
+ return core_fgetc(m_file);
+
+ return EOF;
+}
+
+
+//-------------------------------------------------
+// ungetc - put back a character read from a file
+//-------------------------------------------------
+
+int emu_file::ungetc(int c)
+{
+ // load the ZIP file now if we haven't yet
+ if (m_zipfile != NULL && load_zipped_file() != FILERR_NONE)
+ return 1;
+
+ // read the data if we can
+ if (m_file != NULL)
+ return core_ungetc(c, m_file);
+
+ return 1;
+}
+
+
+//-------------------------------------------------
+// gets - read a line from a text file
+//-------------------------------------------------
+
+char *emu_file::gets(char *s, int n)
+{
+ // load the ZIP file now if we haven't yet
+ if (m_zipfile != NULL && load_zipped_file() != FILERR_NONE)
+ return NULL;
+
+ // read the data if we can
+ if (m_file != NULL)
+ return core_fgets(s, n, m_file);
+
+ return NULL;
+}
+
+
+//-------------------------------------------------
+// write - write to a file
+//-------------------------------------------------
+
+UINT32 emu_file::write(const void *buffer, UINT32 length)
+{
+ // write the data if we can
+ if (m_file != NULL)
+ return core_fwrite(m_file, buffer, length);
+
+ return 0;
+}
+
+
+//-------------------------------------------------
+// puts - write a line to a text file
+//-------------------------------------------------
+
+int emu_file::puts(const char *s)
+{
+ // write the data if we can
+ if (m_file != NULL)
+ return core_fputs(m_file, s);
+
+ return 0;
+}
+
+
+//-------------------------------------------------
+// printf - vfprintf to a text file
+//-------------------------------------------------
+
+int CLIB_DECL emu_file::printf(const char *fmt, ...)
+{
+ int rc;
+ va_list va;
+ va_start(va, fmt);
+ rc = vprintf(fmt, va);
+ va_end(va);
+ return rc;
+}
+
+
+//-------------------------------------------------
+// mame_vfprintf - vfprintf to a text file
+//-------------------------------------------------
+
+int emu_file::vprintf(const char *fmt, va_list va)
+{
+ // write the data if we can
+ return (m_file != NULL) ? core_vfprintf(m_file, fmt, va) : 0;
+}
+
+
+
+//-------------------------------------------------
+// attempt_zipped - attempt to open a ZIPped file
+//-------------------------------------------------
+
+file_error emu_file::attempt_zipped()
+{
+ astring filename;
+
+ // loop over directory parts up to the start of filename
+ while (1)
+ {
+ // find the final path separator
+ int dirsep = m_fullpath.rchr(0, PATH_SEPARATOR[0]);
+ if (dirsep == -1)
+ return FILERR_NOT_FOUND;
+
+ // insert the part from the right of the separator into the head of the filename
+ if (filename.len() > 0)
+ filename.ins(0, "/");
+ filename.inssubstr(0, m_fullpath, dirsep + 1, -1);
+
+ // remove this part of the filename and append a .zip extension
+ m_fullpath.substr(0, dirsep).cat(".zip");
+
+ // attempt to open the ZIP file
+ zip_file *zip;
+ zip_error ziperr = zip_file_open(m_fullpath, &zip);
+
+ // chop the .zip back off the filename before continuing
+ m_fullpath.substr(0, dirsep);
+
+ // if we failed to open this file, continue scanning
+ if (ziperr != ZIPERR_NONE)
+ continue;
+
+ // see if we can find a file with the right name and (if available) crc
+ const zip_file_header *header;
+ for (header = zip_file_first_file(zip); header != NULL; header = zip_file_next_file(zip))
+ if (zip_filename_match(*header, filename) && (!(m_openflags & OPEN_FLAG_HAS_CRC) || header->crc == m_crc))
+ break;
+
+ // if that failed, look for a file with the right crc, but the wrong filename
+ if (header == NULL && (m_openflags & OPEN_FLAG_HAS_CRC))
+ for (header = zip_file_first_file(zip); header != NULL; header = zip_file_next_file(zip))
+ if (header->crc == m_crc && !zip_header_is_path(*header))
+ break;
+
+ // if that failed, look for a file with the right name; reporting a bad checksum
+ // is more helpful and less confusing than reporting "rom not found"
+ if (header == NULL)
+ for (header = zip_file_first_file(zip); header != NULL; header = zip_file_next_file(zip))
+ if (zip_filename_match(*header, filename))
+ break;
+
+ // if we got it, read the data
+ if (header != NULL)
+ {
+ m_zipfile = zip;
+ m_ziplength = header->uncompressed_length;
+
+ // build a hash with just the CRC
+ m_hashes.reset();
+ m_hashes.add_crc(header->crc);
+ return (m_openflags & OPEN_FLAG_NO_PRELOAD) ? FILERR_NONE : load_zipped_file();
+ }
+
+ // close up the ZIP file and try the next level
+ zip_file_close(zip);
+ }
+}
+
+
+//-------------------------------------------------
+// load_zipped_file - load a ZIPped file
+//-------------------------------------------------
+
+file_error emu_file::load_zipped_file()
+{
+ assert(m_file == NULL);
+ assert(m_zipdata == NULL);
+ assert(m_zipfile != NULL);
+
+ // allocate some memory
+ m_zipdata = global_alloc_array(UINT8, m_ziplength);
+
+ // read the data into our buffer and return
+ zip_error ziperr = zip_file_decompress(m_zipfile, m_zipdata, m_ziplength);
+ if (ziperr != ZIPERR_NONE)
+ {
+ global_free(m_zipdata);
+ m_zipdata = NULL;
+ return FILERR_FAILURE;
+ }
+
+ // convert to RAM file
+ file_error filerr = core_fopen_ram(m_zipdata, m_ziplength, m_openflags, &m_file);
+ if (filerr != FILERR_NONE)
+ {
+ global_free(m_zipdata);
+ m_zipdata = NULL;
+ return FILERR_FAILURE;
+ }
+
+ // close out the ZIP file
+ zip_file_close(m_zipfile);
+ m_zipfile = NULL;
+ return FILERR_NONE;
+}
+
+
+//-------------------------------------------------
+// zip_filename_match - compare zip filename
+// to expected filename, ignoring any directory
+//-------------------------------------------------
+
+bool emu_file::zip_filename_match(const zip_file_header &header, const astring &filename)
+{
+ const char *zipfile = header.filename + header.filename_length - filename.len();
+ return (zipfile >= header.filename && filename.icmp(zipfile) == 0 && (zipfile == header.filename || zipfile[-1] == '/'));
+}
+
+
+//-------------------------------------------------
+// zip_header_is_path - check whether filename
+// in header is a path
+//-------------------------------------------------
+
+bool emu_file::zip_header_is_path(const zip_file_header &header)
+{
+ const char *zipfile = header.filename + header.filename_length - 1;
+ return (zipfile >= header.filename && zipfile[0] == '/');
+}
diff --git a/trunk/src/emu/fileio.h b/trunk/src/emu/fileio.h
new file mode 100644
index 00000000000..c9cb549036b
--- /dev/null
+++ b/trunk/src/emu/fileio.h
@@ -0,0 +1,183 @@
+/***************************************************************************
+
+ fileio.h
+
+ Core file I/O interface functions and 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 __FILEIO_H__
+#define __FILEIO_H__
+
+#include "corefile.h"
+#include "hash.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// forward declarations
+typedef struct _zip_file_header zip_file_header;
+typedef struct _zip_file zip_file;
+
+
+// ======================> path_iterator
+
+// helper class for iterating over configured paths
+class path_iterator
+{
+public:
+ // construction/destruction
+ path_iterator(const char *searchpath);
+
+ // getters
+ bool next(astring &buffer, const char *name = NULL);
+
+ // reset
+ void reset() { m_current = m_base; m_index = 0; }
+
+private:
+ // internal state
+ const char * m_base;
+ const char * m_current;
+ int m_index;
+};
+
+
+
+// ======================> file_enumerator
+
+// iterate over all files in all paths specified in the searchpath
+class file_enumerator
+{
+public:
+ // construction/destruction
+ file_enumerator(const char *searchpath);
+ ~file_enumerator();
+
+ // iterator
+ const osd_directory_entry *next();
+
+private:
+ // internal state
+ path_iterator m_iterator;
+ osd_directory * m_curdir;
+ astring m_pathbuffer;
+ int m_buflen;
+};
+
+
+
+// ======================> emu_file
+
+class emu_file
+{
+public:
+ // file open/creation
+ emu_file(UINT32 openflags);
+ emu_file(const char *searchpath, UINT32 openflags);
+ virtual ~emu_file();
+
+ // getters
+ operator core_file *();
+ operator core_file &();
+ bool is_open() const { return (m_file != NULL); }
+ const char *filename() const { return m_filename; }
+ const char *fullpath() const { return m_fullpath; }
+ UINT32 openflags() const { return m_openflags; }
+ hash_collection &hashes(const char *types);
+
+ // setters
+ void remove_on_close() { m_remove_on_close = true; }
+ void set_openflags(UINT32 openflags) { assert(m_file == NULL); m_openflags = openflags; }
+
+ // open/close
+ file_error open(const char *name);
+ file_error open(const char *name1, const char *name2);
+ file_error open(const char *name1, const char *name2, const char *name3);
+ file_error open(const char *name1, const char *name2, const char *name3, const char *name4);
+ file_error open(const char *name, UINT32 crc);
+ file_error open(const char *name1, const char *name2, UINT32 crc);
+ file_error open(const char *name1, const char *name2, const char *name3, UINT32 crc);
+ file_error open(const char *name1, const char *name2, const char *name3, const char *name4, UINT32 crc);
+ file_error open_next();
+ file_error open_ram(const void *data, UINT32 length);
+ void close();
+
+ // control
+ file_error compress(int compress);
+ int seek(INT64 offset, int whence);
+ UINT64 tell();
+ bool eof();
+ UINT64 size();
+
+ // reading
+ UINT32 read(void *buffer, UINT32 length);
+ int getc();
+ int ungetc(int c);
+ char *gets(char *s, int n);
+
+ // writing
+ UINT32 write(const void *buffer, UINT32 length);
+ int puts(const char *s);
+ int vprintf(const char *fmt, va_list va);
+ int printf(const char *fmt, ...);
+
+private:
+ // internal helpers
+ file_error attempt_zipped();
+ file_error load_zipped_file();
+ bool zip_filename_match(const zip_file_header &header, const astring &filename);
+ bool zip_header_is_path(const zip_file_header &header);
+
+ // internal state
+ astring m_filename; // original filename provided
+ astring m_fullpath; // full filename
+ core_file * m_file; // core file pointer
+ path_iterator m_iterator; // iterator for paths
+ UINT32 m_crc; // iterator for paths
+ UINT32 m_openflags; // flags we used for the open
+ hash_collection m_hashes; // collection of hashes
+ zip_file * m_zipfile; // ZIP file pointer
+ UINT8 * m_zipdata; // ZIP file data
+ UINT64 m_ziplength; // ZIP file length
+ bool m_remove_on_close; // flag: remove the file when closing
+};
+
+
+#endif /* __FILEIO_H__ */
diff --git a/trunk/src/emu/hash.c b/trunk/src/emu/hash.c
new file mode 100644
index 00000000000..07a57587531
--- /dev/null
+++ b/trunk/src/emu/hash.c
@@ -0,0 +1,739 @@
+/***************************************************************************
+
+ hash.c
+
+ Function to handle hash functions (checksums)
+
+ Based on original idea by Farfetch'd
+
+****************************************************************************
+
+ 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 "zlib.h"
+#include "sha1.h"
+#include <ctype.h>
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> hash_crc
+
+// CRC-32 hash implementation
+class hash_crc : public hash_base
+{
+public:
+ // construction/destruction
+ hash_crc();
+
+ // operators
+ operator UINT32() const { return (m_buffer[0] << 24) | (m_buffer[1] << 16) | (m_buffer[2] << 8) | m_buffer[3]; }
+
+ // creation
+ virtual void begin();
+ virtual void buffer(const UINT8 *data, UINT32 length);
+ virtual void end();
+
+private:
+ // internal state
+ UINT8 m_buffer[4];
+};
+
+
+
+// ======================> hash_sha1
+
+// SHA1 hash implementation
+class hash_sha1 : public hash_base
+{
+public:
+ // construction/destruction
+ hash_sha1();
+
+ // creation
+ virtual void begin();
+ virtual void buffer(const UINT8 *data, UINT32 length);
+ virtual void end();
+
+private:
+ // internal state
+ UINT8 m_buffer[20];
+ struct sha1_ctx m_context;
+};
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const char *hash_collection::HASH_TYPES_CRC = "R";
+const char *hash_collection::HASH_TYPES_CRC_SHA1 = "RS";
+const char *hash_collection::HASH_TYPES_ALL = "RS";
+
+
+
+//**************************************************************************
+// HASH BASE
+//**************************************************************************
+
+//-------------------------------------------------
+// hash_base - constructor
+//-------------------------------------------------
+
+hash_base::hash_base(char id, const char *name, UINT8 length, UINT8 *bufptr)
+ : m_next(NULL),
+ m_name(name),
+ m_in_progress(false),
+ m_parse_error(false),
+ m_id(id),
+ m_length(length),
+ m_bufptr(bufptr)
+{
+ memset(m_bufptr, 0, length);
+}
+
+
+//-------------------------------------------------
+// fromhex - convert a character to a hex value
+//-------------------------------------------------
+
+int hash_base::fromhex(char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ else if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ else if (c >= 'a' && c <= 'f')
+ return (c - 'a' + 10);
+ else
+ return -1;
+}
+
+
+//-------------------------------------------------
+// from_buffer - copy a raw buffer into the
+// current hash
+//-------------------------------------------------
+
+bool hash_base::from_buffer(const UINT8 *buffer, int buflen)
+{
+ // fail if we're too small
+ if (buflen < m_length)
+ return false;
+ memcpy(m_bufptr, buffer, m_length);
+ return true;
+}
+
+
+//-------------------------------------------------
+// string - output a string for the current hash
+//-------------------------------------------------
+
+const char *hash_base::string(astring &buffer)
+{
+ buffer.reset();
+ for (int index = 0; index < m_length; index++)
+ buffer.catprintf("%02x", m_bufptr[index]);
+ return buffer;
+}
+
+
+//-------------------------------------------------
+// from_string - parse a string into the current
+// hash
+//-------------------------------------------------
+
+bool hash_base::from_string(const char *&string, int length)
+{
+ // reset the error and our buffer
+ m_parse_error = false;
+ memset(m_bufptr, 0, m_length);
+
+ // special case for idiom HASH(1) to map to a dummy (0) hash
+ if (string[0] == '1' && fromhex(string[1]) == -1)
+ {
+ string++;
+ return true;
+ }
+
+ // fail if we're too short
+ if (length < 2 * m_length)
+ return false;
+
+ // loop over bytes
+ for (int index = 0; index < m_length; index++)
+ {
+ // parse the upper digit
+ int upper = fromhex(string[0]);
+ if (upper == -1)
+ {
+ m_parse_error = true;
+ return false;
+ }
+
+ // parse the lower digit
+ int lower = fromhex(string[1]);
+ if (lower == -1)
+ {
+ m_parse_error = true;
+ return false;
+ }
+
+ // set the byte and advance
+ m_bufptr[index] = (upper << 4) | lower;
+ string += 2;
+ }
+ return true;
+}
+
+
+
+//**************************************************************************
+// HASH CRC
+//**************************************************************************
+
+//-------------------------------------------------
+// hash_crc - constructor
+//-------------------------------------------------
+
+hash_crc::hash_crc()
+ : hash_base(hash_collection::HASH_CRC, "crc", sizeof(m_buffer), m_buffer)
+{
+}
+
+
+//-------------------------------------------------
+// begin - initialize state for hash computation
+//-------------------------------------------------
+
+void hash_crc::begin()
+{
+ m_in_progress = true;
+ memset(m_buffer, 0, sizeof(m_buffer));
+}
+
+
+//-------------------------------------------------
+// buffer - hash a buffer's worth of data
+//-------------------------------------------------
+
+void hash_crc::buffer(const UINT8 *data, UINT32 length)
+{
+ UINT32 crc = crc32(*this, data, length);
+ m_buffer[0] = crc >> 24;
+ m_buffer[1] = crc >> 16;
+ m_buffer[2] = crc >> 8;
+ m_buffer[3] = crc >> 0;
+}
+
+
+//-------------------------------------------------
+// end - finish hash computation
+//-------------------------------------------------
+
+void hash_crc::end()
+{
+ m_in_progress = false;
+}
+
+
+
+//**************************************************************************
+// HASH SHA1
+//**************************************************************************
+
+//-------------------------------------------------
+// hash_sha1 - constructor
+//-------------------------------------------------
+
+hash_sha1::hash_sha1()
+ : hash_base(hash_collection::HASH_SHA1, "sha1", sizeof(m_buffer), m_buffer)
+{
+}
+
+
+//-------------------------------------------------
+// begin - initialize state for hash computation
+//-------------------------------------------------
+
+void hash_sha1::begin()
+{
+ m_in_progress = true;
+ sha1_init(&m_context);
+}
+
+
+//-------------------------------------------------
+// buffer - hash a buffer's worth of data
+//-------------------------------------------------
+
+void hash_sha1::buffer(const UINT8 *data, UINT32 length)
+{
+ sha1_update(&m_context, length, data);
+}
+
+
+//-------------------------------------------------
+// end - finish hash computation
+//-------------------------------------------------
+
+void hash_sha1::end()
+{
+ sha1_final(&m_context);
+ sha1_digest(&m_context, sizeof(m_buffer), m_buffer);
+ m_in_progress = false;
+}
+
+
+
+//**************************************************************************
+// HASH COLLECTION
+//**************************************************************************
+
+//-------------------------------------------------
+// hash_collection - constructor
+//-------------------------------------------------
+
+hash_collection::hash_collection()
+{
+}
+
+
+hash_collection::hash_collection(const char *string)
+{
+ from_internal_string(string);
+}
+
+
+hash_collection::hash_collection(const hash_collection &src)
+{
+ copyfrom(src);
+}
+
+
+//-------------------------------------------------
+// ~hash_collection - destructor
+//-------------------------------------------------
+
+hash_collection::~hash_collection()
+{
+}
+
+
+//-------------------------------------------------
+// operator= - assignment operator
+//-------------------------------------------------
+
+hash_collection &hash_collection::operator=(const hash_collection &src)
+{
+ // ignore self-assignment
+ if (this != &src)
+ copyfrom(src);
+ return *this;
+}
+
+
+//-------------------------------------------------
+// operator== - test for equality
+//-------------------------------------------------
+
+bool hash_collection::operator==(const hash_collection &rhs) const
+{
+ // look for a mismatch in any hash; do not fail if one is missing
+ int matches = 0;
+ for (hash_base *hash = m_hashlist.first(); hash != NULL; hash = hash->next())
+ {
+ hash_base *rhs_hash = rhs.hash(hash->id());
+ if (rhs_hash != NULL)
+ {
+ if (*hash != *rhs_hash)
+ return false;
+ matches++;
+ }
+ }
+
+ // if all shared hashes match, return true
+ return (matches > 0);
+}
+
+
+//-------------------------------------------------
+// hash - return a hash of the given type
+//-------------------------------------------------
+
+hash_base *hash_collection::hash(char type) const
+{
+ // look for a mismatch in any hash; do not fail if one is missing
+ for (hash_base *hash = m_hashlist.first(); hash != NULL; hash = hash->next())
+ if (hash->id() == type)
+ return hash;
+ return NULL;
+}
+
+
+//-------------------------------------------------
+// hash_types - return a list of hash types as
+// a string
+//-------------------------------------------------
+
+const char *hash_collection::hash_types(astring &buffer) const
+{
+ buffer.reset();
+ for (hash_base *hash = m_hashlist.first(); hash != NULL; hash = hash->next())
+ buffer.cat(hash->id());
+ return buffer;
+}
+
+
+//-------------------------------------------------
+// reset - reset the hash collection to an empty
+// set of hashes and flags
+//-------------------------------------------------
+
+bool hash_collection::parse_errors() const
+{
+ for (hash_base *hash = m_hashlist.first(); hash != NULL; hash = hash->next())
+ if (hash->parse_error())
+ return true;
+ return false;
+}
+
+
+//-------------------------------------------------
+// reset - reset the hash collection to an empty
+// set of hashes and flags
+//-------------------------------------------------
+
+void hash_collection::reset()
+{
+ m_hashlist.reset();
+ m_flags.reset();
+}
+
+
+//-------------------------------------------------
+// add_from_buffer - add a new hash, importing
+// from a buffer
+//-------------------------------------------------
+
+hash_base *hash_collection::add_from_buffer(char type, const UINT8 *buffer, int bufflen)
+{
+ // nuke any existing hash with the same ID
+ hash_base *existing = hash(type);
+ if (existing != NULL)
+ m_hashlist.remove(*existing);
+
+ // first allocate by ID
+ hash_base *newhash = alloc_by_id(type);
+ if (newhash == NULL)
+ return NULL;
+
+ // then import
+ if (!newhash->from_buffer(buffer, bufflen))
+ {
+ global_free(newhash);
+ return NULL;
+ }
+
+ // and append to our list
+ return &m_hashlist.append(*newhash);
+}
+
+
+//-------------------------------------------------
+// add_from_string - add a new hash, importing
+// from a string
+//-------------------------------------------------
+
+hash_base *hash_collection::add_from_string(char type, const char *buffer, int length)
+{
+ // nuke any existing hash with the same ID
+ hash_base *existing = hash(type);
+ if (existing != NULL)
+ m_hashlist.remove(*existing);
+
+ // first allocate by ID
+ hash_base *newhash = alloc_by_id(type);
+ if (newhash == NULL)
+ return NULL;
+
+ // then import
+ if (!newhash->from_string(buffer, length))
+ {
+ global_free(newhash);
+ return NULL;
+ }
+
+ // and append to our list
+ return &m_hashlist.append(*newhash);
+}
+
+
+//-------------------------------------------------
+// remove - remove a hash of the given type
+//-------------------------------------------------
+
+bool hash_collection::remove(char type)
+{
+ // scan the list of hashes for a match
+ for (hash_base *hash = m_hashlist.first(); hash != NULL; hash = hash->next())
+ if (hash->id() == type)
+ {
+ m_hashlist.remove(*hash);
+ return true;
+ }
+
+ // didn't find it
+ return false;
+}
+
+
+//-------------------------------------------------
+// crc - return the CRC hash if present
+//-------------------------------------------------
+
+bool hash_collection::crc(UINT32 &result) const
+{
+ // attempt to find the CRC hash; if we fail, return false
+ hash_base *crchash = hash(HASH_CRC);
+ if (crchash == NULL)
+ return false;
+
+ // downcast to a hash_crc and convert to a UINT32
+ result = *downcast<const hash_crc *>(crchash);
+ return true;
+}
+
+
+//-------------------------------------------------
+// add_crc - add a CRC hash
+//-------------------------------------------------
+
+hash_base *hash_collection::add_crc(UINT32 crc)
+{
+ // expand to a buffer
+ UINT8 buffer[4];
+ buffer[0] = crc >> 24;
+ buffer[1] = crc >> 16;
+ buffer[2] = crc >> 8;
+ buffer[3] = crc >> 0;
+
+ // add it the standard way
+ return add_from_buffer(HASH_CRC, buffer, sizeof(buffer));
+}
+
+
+//-------------------------------------------------
+// internal_string - convert set of hashes and
+// flags to a string in our internal compact
+// format
+//-------------------------------------------------
+
+const char *hash_collection::internal_string(astring &buffer) const
+{
+ astring temp;
+
+ // output hashes first
+ buffer.reset();
+ for (hash_base *hash = m_hashlist.first(); hash != NULL; hash = hash->next())
+ buffer.cat(hash->id()).cat(hash->string(temp));
+
+ // append flags
+ buffer.cat(m_flags);
+ return buffer;
+}
+
+
+//-------------------------------------------------
+// macro_string - convert set of hashes and
+// flags to a string in the macroized format
+//-------------------------------------------------
+
+const char *hash_collection::macro_string(astring &buffer) const
+{
+ astring temp;
+
+ // output hashes first
+ buffer.reset();
+ for (hash_base *hash = m_hashlist.first(); hash != NULL; hash = hash->next())
+ {
+ buffer.cat(temp.cpy(hash->name()).toupper());
+ buffer.cat("(").cat(hash->string(temp)).cat(") ");
+ }
+
+ // append flags
+ if (flag(FLAG_NO_DUMP))
+ buffer.cat("NO_DUMP ");
+ if (flag(FLAG_BAD_DUMP))
+ buffer.cat("BAD_DUMP ");
+ return buffer.trimspace();
+}
+
+
+//-------------------------------------------------
+// from_internal_string - convert an internal
+// compact string to set of hashes and flags
+//-------------------------------------------------
+
+bool hash_collection::from_internal_string(const char *string)
+{
+ // start fresh
+ reset();
+
+ // determine the end of the string
+ const char *stringend = string + strlen(string);
+ const char *ptr = string;
+
+ // loop until we hit it
+ bool errors = false;
+ while (ptr < stringend)
+ {
+ char c = *ptr++;
+ char lc = tolower(c);
+
+ // non-hex alpha values specify a hash type
+ if (lc >= 'g' && lc <= 'z')
+ {
+ hash_base *hash = alloc_by_id(c);
+ if (hash != NULL)
+ {
+ if (!hash->from_string(ptr, stringend - ptr))
+ errors = true;
+ m_hashlist.append(*hash);
+ }
+ else
+ errors = true;
+ }
+
+ // hex values are ignored, though unexpected
+ else if ((lc >= '0' && lc <= '9') || (lc >= 'a' && lc <= 'f'))
+ errors = true;
+
+ // anything else is a flag
+ else
+ m_flags.cat(c);
+ }
+ return !errors;
+}
+
+
+//-------------------------------------------------
+// begin - begin hashing
+//-------------------------------------------------
+
+void hash_collection::begin(const char *types)
+{
+ // by default use all types
+ if (types == NULL)
+ {
+ m_hashlist.append(*alloc_by_id(HASH_CRC)).begin();
+ m_hashlist.append(*alloc_by_id(HASH_SHA1)).begin();
+ }
+
+ // otherwise, just allocate the ones that are specified
+ else
+ {
+ for (const char *scan = types; *scan != 0; scan++)
+ {
+ // nuke any existing hash of this type
+ hash_base *existing = hash(*scan);
+ if (existing != NULL)
+ m_hashlist.remove(*existing);
+
+ // append a new one
+ m_hashlist.append(*alloc_by_id(*scan)).begin();
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// buffer - add the given buffer to the hash
+//-------------------------------------------------
+
+void hash_collection::buffer(const UINT8 *data, UINT32 length)
+{
+ // buffer each hash appropriately
+ for (hash_base *hash = m_hashlist.first(); hash != NULL; hash = hash->next())
+ if (hash->in_progress())
+ hash->buffer(data, length);
+}
+
+
+//-------------------------------------------------
+// end - stop hashing
+//-------------------------------------------------
+
+void hash_collection::end()
+{
+ // end each hash
+ for (hash_base *hash = m_hashlist.first(); hash != NULL; hash = hash->next())
+ if (hash->in_progress())
+ hash->end();
+}
+
+
+//-------------------------------------------------
+// alloc_by_id - based on the ID character,
+// allocate a new hash
+//-------------------------------------------------
+
+hash_base *hash_collection::alloc_by_id(char id)
+{
+ switch (id)
+ {
+ case HASH_CRC: return global_alloc(hash_crc);
+ case HASH_SHA1: return global_alloc(hash_sha1);
+ default: return NULL;
+ }
+}
+
+
+//-------------------------------------------------
+// copyfrom - copy everything from another
+// collection
+//-------------------------------------------------
+
+void hash_collection::copyfrom(const hash_collection &src)
+{
+ // copy flags directly
+ m_flags = src.m_flags;
+
+ // rebuild the hashlist by copying from the source
+ m_hashlist.reset();
+ for (hash_base *hash = src.first(); hash != NULL; hash = hash->next())
+ add_from_buffer(hash->id(), hash->buffer(), hash->length());
+}
diff --git a/trunk/src/emu/hash.h b/trunk/src/emu/hash.h
new file mode 100644
index 00000000000..04c25853856
--- /dev/null
+++ b/trunk/src/emu/hash.h
@@ -0,0 +1,187 @@
+/***************************************************************************
+
+ hash.h
+
+ Function to handle hash functions (checksums)
+
+ Based on original idea by Farfetch'd
+
+****************************************************************************
+
+ 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 __HASH_H__
+#define __HASH_H__
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+// use these to define compile-time internal-format hash strings
+#define CRC(x) "R" #x
+#define SHA1(x) "S" #x
+#define NO_DUMP "!"
+#define BAD_DUMP "^"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> hash_base
+
+// base class for all hash types, which does most of the heavy lifting
+class hash_base
+{
+ friend class simple_list<hash_base>;
+
+public:
+ // construction/destruction
+ hash_base(char id, const char *name, UINT8 length, UINT8 *bufptr);
+ virtual ~hash_base() { }
+
+ // operators
+ bool operator==(const hash_base &rhs) const { return (m_length == rhs.m_length && memcmp(m_bufptr, rhs.m_bufptr, m_length) == 0); }
+ bool operator!=(const hash_base &rhs) const { return (m_length != rhs.m_length || memcmp(m_bufptr, rhs.m_bufptr, m_length) != 0); }
+
+ // getters
+ hash_base *next() const { return m_next; }
+ char id() const { return m_id; }
+ const char *name() const { return m_name; }
+ int length() const { return m_length; }
+ bool in_progress() const { return m_in_progress; }
+ bool parse_error() const { return m_parse_error; }
+ UINT8 byte(int index) const { return (index >= 0 && index < m_length) ? m_bufptr[index] : 0; }
+
+ // buffer conversion
+ const UINT8 *buffer() { return m_bufptr; }
+ bool from_buffer(const UINT8 *buffer, int buflen);
+
+ // string conversion
+ const char *string(astring &buffer);
+ bool from_string(const char *&string, int length);
+
+ // creation
+ virtual void begin() = 0;
+ virtual void buffer(const UINT8 *data, UINT32 length) = 0;
+ virtual void end() = 0;
+
+protected:
+ // internal helpers
+ int fromhex(char c);
+
+ // internal state
+ hash_base * m_next;
+ const char * m_name;
+ bool m_in_progress;
+ bool m_parse_error;
+ char m_id;
+ UINT8 m_length;
+ UINT8 * m_bufptr;
+};
+
+
+// ======================> hash_collection
+
+// a collection of the various supported hashes and flags
+class hash_collection
+{
+public:
+ // hash types are identified by non-hex alpha values (G-Z)
+ static const char HASH_CRC = 'R';
+ static const char HASH_SHA1 = 'S';
+
+ // common combinations for requests
+ static const char *HASH_TYPES_CRC;
+ static const char *HASH_TYPES_CRC_SHA1;
+ static const char *HASH_TYPES_ALL;
+
+ // flags are identified by punctuation marks
+ static const char FLAG_NO_DUMP = '!';
+ static const char FLAG_BAD_DUMP = '^';
+
+ // construction/destruction
+ hash_collection();
+ hash_collection(const char *string);
+ hash_collection(const hash_collection &src);
+ ~hash_collection();
+
+ // operators
+ hash_collection &operator=(const hash_collection &src);
+ bool operator==(const hash_collection &rhs) const;
+ bool operator!=(const hash_collection &rhs) const { return !(*this == rhs); }
+
+ // getters
+ bool flag(char flag) const { return (m_flags.chr(0, flag) != -1); }
+ hash_base *hash(char type) const;
+ hash_base *first() const { return m_hashlist.first(); }
+ const char *hash_types(astring &buffer) const;
+ bool parse_errors() const;
+
+ // hash manipulators
+ void reset();
+ hash_base *add_from_buffer(char type, const UINT8 *buffer, int bufflen);
+ hash_base *add_from_string(char type, const char *buffer, int length);
+ bool remove(char type);
+
+ // CRC-specific helpers
+ bool crc(UINT32 &result) const;
+ hash_base *add_crc(UINT32 crc);
+
+ // string conversion
+ const char *internal_string(astring &buffer) const;
+ const char *macro_string(astring &buffer) const;
+ bool from_internal_string(const char *string);
+
+ // creation
+ void begin(const char *types = NULL);
+ void buffer(const UINT8 *data, UINT32 length);
+ void end();
+ void compute(const UINT8 *data, UINT32 length, const char *types = NULL) { begin(types); buffer(data, length); end(); }
+
+private:
+ // internal helpers
+ static hash_base *alloc_by_id(char id);
+ void copyfrom(const hash_collection &src);
+
+ // internal state
+ astring m_flags;
+ simple_list<hash_base> m_hashlist;
+};
+
+
+#endif /* __HASH_H__ */
diff --git a/trunk/src/emu/hashfile.c b/trunk/src/emu/hashfile.c
new file mode 100644
index 00000000000..f80b21158d8
--- /dev/null
+++ b/trunk/src/emu/hashfile.c
@@ -0,0 +1,626 @@
+/*********************************************************************
+
+ hashfile.c
+
+ Code for parsing hash info (*.hsi) files
+
+*********************************************************************/
+
+#include "hashfile.h"
+#include "pool.h"
+#include "expat.h"
+#include "emuopts.h"
+#include "hash.h"
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _hash_info hash_info;
+struct _hash_info
+{
+ hash_collection *hashes;
+ const char *extrainfo;
+};
+
+typedef struct _hash_file hash_file;
+
+typedef void (*hashfile_error_func)(const char *message);
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+/* opens a hash file; if is_preload is non-zero, the entire file is preloaded */
+hash_file *hashfile_open(emu_options &options, const char *sysname, int is_preload, hashfile_error_func error_proc);
+
+/* closes a hash file and associated resources */
+void hashfile_close(hash_file *hashfile);
+
+/* looks up information in a hash file */
+const hash_info *hashfile_lookup(hash_file *hashfile, const hash_collection *hashes);
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+struct _hash_file
+{
+ emu_file *file;
+ object_pool *pool;
+ astring functions[IO_COUNT];
+
+ hash_info **preloaded_hashes;
+ int preloaded_hash_count;
+
+ void (*error_proc)(const char *message);
+};
+
+
+
+enum hash_parse_position
+{
+ HASH_POS_ROOT,
+ HASH_POS_MAIN,
+ HASH_POS_HASH
+};
+
+
+
+struct hash_parse_state
+{
+ XML_Parser parser;
+ hash_file *hashfile;
+ int done;
+
+ int (*selector_proc)(hash_file *hashfile, void *param, const char *name, const hash_collection *hashes);
+ void (*use_proc)(hash_file *hashfile, void *param, hash_info *hi);
+ void (*error_proc)(const char *message);
+ void *param;
+
+ enum hash_parse_position pos;
+ char **text_dest;
+ hash_info *hi;
+};
+
+
+
+/***************************************************************************
+ PROTOTYPES
+***************************************************************************/
+
+static void *expat_malloc(size_t size);
+static void *expat_realloc(void *ptr, size_t size);
+static void expat_free(void *ptr);
+
+
+
+/***************************************************************************
+ CORE IMPLEMENTATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ parse_error
+-------------------------------------------------*/
+
+static void ATTR_PRINTF(2,3) parse_error(struct hash_parse_state *state, const char *fmt, ...)
+{
+ char buf[256];
+ va_list va;
+
+ if (state->error_proc)
+ {
+ va_start(va, fmt);
+ vsnprintf(buf, ARRAY_LENGTH(buf), fmt, va);
+ va_end(va);
+ (*state->error_proc)(buf);
+ }
+}
+
+
+
+/*-------------------------------------------------
+ unknown_tag
+-------------------------------------------------*/
+
+static void unknown_tag(struct hash_parse_state *state, const char *tagname)
+{
+ parse_error(state, "[%lu:%lu]: Unknown tag: %s\n",
+ XML_GetCurrentLineNumber(state->parser),
+ XML_GetCurrentColumnNumber(state->parser),
+ tagname);
+}
+
+
+
+/*-------------------------------------------------
+ unknown_attribute
+-------------------------------------------------*/
+
+static void unknown_attribute(struct hash_parse_state *state, const char *attrname)
+{
+ parse_error(state, "[%lu:%lu]: Unknown attribute: %s\n",
+ XML_GetCurrentLineNumber(state->parser),
+ XML_GetCurrentColumnNumber(state->parser),
+ attrname);
+}
+
+
+
+/*-------------------------------------------------
+ unknown_attribute_value
+-------------------------------------------------*/
+
+static void unknown_attribute_value(struct hash_parse_state *state,
+ const char *attrname, const char *attrvalue)
+{
+ parse_error(state, "[%lu:%lu]: Unknown attribute value: %s\n",
+ XML_GetCurrentLineNumber(state->parser),
+ XML_GetCurrentColumnNumber(state->parser),
+ attrvalue);
+}
+
+
+
+/*-------------------------------------------------
+ start_handler
+-------------------------------------------------*/
+
+static void start_handler(void *data, const char *tagname, const char **attributes)
+{
+ struct hash_parse_state *state = (struct hash_parse_state *) data;
+ const char *name;
+ hash_info *hi;
+ char **text_dest;
+ hash_collection hashes;
+ astring all_functions;
+ char functions;
+// iodevice_t device;
+ int i;
+
+ switch(state->pos)
+ {
+ case HASH_POS_ROOT:
+ if (!strcmp(tagname, "hashfile"))
+ {
+ }
+ else
+ {
+ unknown_tag(state, tagname);
+ }
+ break;
+
+ case HASH_POS_MAIN:
+ if (!strcmp(tagname, "hash"))
+ {
+ // we are now examining a hash tag
+ name = NULL;
+// device = IO_COUNT;
+
+ while(attributes[0])
+ {
+ functions = 0;
+ if (!strcmp(attributes[0], "name"))
+ {
+ /* name attribute */
+ name = attributes[1];
+ }
+ else if (!strcmp(attributes[0], "crc32"))
+ {
+ /* crc32 attribute */
+ functions = hash_collection::HASH_CRC;
+ }
+ else if (!strcmp(attributes[0], "sha1"))
+ {
+ /* sha1 attribute */
+ functions = hash_collection::HASH_SHA1;
+ }
+ else if (!strcmp(attributes[0], "type"))
+ {
+ /* type attribute */
+ i = 0;//device_typeid(attributes[1]);
+ if (i < 0)
+ unknown_attribute_value(state, attributes[0], attributes[1]);
+ else
+ {
+ // device = (iodevice_t) i;
+ }
+ }
+ else
+ {
+ /* unknown attribute */
+ unknown_attribute(state, attributes[0]);
+ }
+
+ if (functions)
+ {
+ hashes.add_from_string(functions, attributes[1], strlen(attributes[1]));
+ all_functions.cat(functions);
+ }
+
+ attributes += 2;
+ }
+
+ /* do we use this hash? */
+ if (!state->selector_proc || state->selector_proc(state->hashfile, state->param, name, &hashes))
+ {
+ hi = (hash_info*)pool_malloc_lib(state->hashfile->pool, sizeof(hash_info));
+ if (!hi)
+ return;
+ memset(hi, 0, sizeof(*hi));
+
+ hi->hashes = &hashes;
+ state->hi = hi;
+ }
+ }
+ else
+ {
+ unknown_tag(state, tagname);
+ }
+ break;
+
+ case HASH_POS_HASH:
+ text_dest = NULL;
+
+ if (!strcmp(tagname, "year")) {
+ }
+ else if (!strcmp(tagname, "manufacturer")){
+ }
+ else if (!strcmp(tagname, "status")){
+ }
+ else if (!strcmp(tagname, "pcb")){
+ }
+ else if (!strcmp(tagname, "extrainfo")) {
+ text_dest = (char **) &state->hi->extrainfo;
+ }
+ else
+ unknown_tag(state, tagname);
+
+ if (text_dest && state->hi)
+ state->text_dest = text_dest;
+ break;
+ }
+ state->pos = (hash_parse_position) (state->pos + 1);
+}
+
+
+
+/*-------------------------------------------------
+ end_handler
+-------------------------------------------------*/
+
+static void end_handler(void *data, const char *name)
+{
+ struct hash_parse_state *state = (struct hash_parse_state *) data;
+ state->text_dest = NULL;
+
+ state->pos = (hash_parse_position) (state->pos - 1);
+ switch(state->pos)
+ {
+ case HASH_POS_ROOT:
+ case HASH_POS_HASH:
+ break;
+
+ case HASH_POS_MAIN:
+ if (state->hi)
+ {
+ if (state->use_proc)
+ (*state->use_proc)(state->hashfile, state->param, state->hi);
+ state->hi = NULL;
+ }
+ break;
+ }
+}
+
+
+
+/*-------------------------------------------------
+ data_handler
+-------------------------------------------------*/
+
+static void data_handler(void *data, const XML_Char *s, int len)
+{
+ struct hash_parse_state *state = (struct hash_parse_state *) data;
+ int text_len;
+ char *text;
+
+ if (state->text_dest)
+ {
+ text = *state->text_dest;
+
+ text_len = text ? strlen(text) : 0;
+ text = (char*)pool_realloc_lib(state->hashfile->pool, text, text_len + len + 1);
+ if (!text)
+ return;
+
+ memcpy(&text[text_len], s, len);
+ text[text_len + len] = '\0';
+ *state->text_dest = text;
+ }
+}
+
+
+
+/*-------------------------------------------------
+ hashfile_parse
+-------------------------------------------------*/
+
+static void hashfile_parse(hash_file *hashfile,
+ int (*selector_proc)(hash_file *hashfile, void *param, const char *name, const hash_collection *hashes),
+ void (*use_proc)(hash_file *hashfile, void *param, hash_info *hi),
+ void (*error_proc)(const char *message),
+ void *param)
+{
+ struct hash_parse_state state;
+ char buf[1024];
+ UINT32 len;
+ XML_Memory_Handling_Suite memcallbacks;
+
+ hashfile->file->seek(0, SEEK_SET);
+
+ memset(&state, 0, sizeof(state));
+ state.hashfile = hashfile;
+ state.selector_proc = selector_proc;
+ state.use_proc = use_proc;
+ state.error_proc = error_proc;
+ state.param = param;
+
+ /* create the XML parser */
+ memcallbacks.malloc_fcn = expat_malloc;
+ memcallbacks.realloc_fcn = expat_realloc;
+ memcallbacks.free_fcn = expat_free;
+ state.parser = XML_ParserCreate_MM(NULL, &memcallbacks, NULL);
+ if (!state.parser)
+ goto done;
+
+ XML_SetUserData(state.parser, &state);
+ XML_SetElementHandler(state.parser, start_handler, end_handler);
+ XML_SetCharacterDataHandler(state.parser, data_handler);
+
+ while(!state.done)
+ {
+ len = hashfile->file->read(buf, sizeof(buf));
+ state.done = hashfile->file->eof();
+ if (XML_Parse(state.parser, buf, len, state.done) == XML_STATUS_ERROR)
+ {
+ parse_error(&state, "[%lu:%lu]: %s\n",
+ XML_GetCurrentLineNumber(state.parser),
+ XML_GetCurrentColumnNumber(state.parser),
+ XML_ErrorString(XML_GetErrorCode(state.parser)));
+ goto done;
+ }
+ }
+
+done:
+ if (state.parser)
+ XML_ParserFree(state.parser);
+}
+
+
+
+/*-------------------------------------------------
+ preload_use_proc
+-------------------------------------------------*/
+
+static void preload_use_proc(hash_file *hashfile, void *param, hash_info *hi)
+{
+ hash_info **new_preloaded_hashes;
+
+ new_preloaded_hashes = (hash_info **)pool_realloc_lib(hashfile->pool, hashfile->preloaded_hashes,
+ (hashfile->preloaded_hash_count + 1) * sizeof(*new_preloaded_hashes));
+ if (!new_preloaded_hashes)
+ return;
+
+ hashfile->preloaded_hashes = new_preloaded_hashes;
+ hashfile->preloaded_hashes[hashfile->preloaded_hash_count++] = hi;
+}
+
+
+
+/*-------------------------------------------------
+ hashfile_open
+-------------------------------------------------*/
+
+hash_file *hashfile_open(emu_options &options, const char *sysname, int is_preload,
+ void (*error_proc)(const char *message))
+{
+ hash_file *hashfile = NULL;
+ object_pool *pool = NULL;
+ file_error filerr;
+
+ /* create a pool for this hash file */
+ pool = pool_alloc_lib(error_proc);
+ if (!pool)
+ goto error;
+
+ /* allocate space for this hash file */
+ hashfile = (hash_file *) pool_malloc_lib(pool, sizeof(*hashfile));
+ if (!hashfile)
+ goto error;
+
+ /* set up the hashfile structure */
+ memset(hashfile, 0, sizeof(*hashfile));
+ hashfile->pool = pool;
+ hashfile->error_proc = error_proc;
+
+ /* open a file */
+ hashfile->file = global_alloc(emu_file(options.hash_path(), OPEN_FLAG_READ));
+ filerr = hashfile->file->open(sysname, ".hsi");
+ if (filerr != FILERR_NONE)
+ {
+ global_free(hashfile->file);
+ hashfile->file = NULL;
+ goto error;
+ }
+
+ if (is_preload)
+ hashfile_parse(hashfile, NULL, preload_use_proc, hashfile->error_proc, NULL);
+
+ return hashfile;
+
+error:
+ if (hashfile != NULL)
+ hashfile_close(hashfile);
+ return NULL;
+}
+
+
+
+/*-------------------------------------------------
+ hashfile_close
+-------------------------------------------------*/
+
+void hashfile_close(hash_file *hashfile)
+{
+ global_free(hashfile->file);
+ pool_free_lib(hashfile->pool);
+}
+
+
+
+/*-------------------------------------------------
+ singular_selector_proc
+-------------------------------------------------*/
+
+struct hashlookup_params
+{
+ const hash_collection *hashes;
+ hash_info *hi;
+};
+
+static int singular_selector_proc(hash_file *hashfile, void *param, const char *name, const hash_collection *hashes)
+{
+ astring tempstr;
+ struct hashlookup_params *hlparams = (struct hashlookup_params *) param;
+ return (*hashes == *hlparams->hashes);
+}
+
+
+
+/*-------------------------------------------------
+ singular_use_proc
+-------------------------------------------------*/
+
+static void singular_use_proc(hash_file *hashfile, void *param, hash_info *hi)
+{
+ struct hashlookup_params *hlparams = (struct hashlookup_params *) param;
+ hlparams->hi = hi;
+}
+
+
+
+/*-------------------------------------------------
+ hashfile_lookup
+-------------------------------------------------*/
+
+const hash_info *hashfile_lookup(hash_file *hashfile, const hash_collection *hashes)
+{
+ struct hashlookup_params param;
+ int i;
+
+ param.hashes = hashes;
+ param.hi = NULL;
+
+ for (i = 0; i < hashfile->preloaded_hash_count; i++)
+ {
+ if (singular_selector_proc(hashfile, &param, NULL, hashfile->preloaded_hashes[i]->hashes))
+ return hashfile->preloaded_hashes[i];
+ }
+
+ hashfile_parse(hashfile, singular_selector_proc, singular_use_proc,
+ hashfile->error_proc, (void *) &param);
+ return param.hi;
+}
+
+const char *extra_info = NULL;
+
+const char *read_hash_config(device_image_interface &image, const char *sysname)
+{
+ hash_file *hashfile = NULL;
+ const hash_info *info = NULL;
+
+ /* open the hash file */
+ hashfile = hashfile_open(image.device().machine().options(), sysname, FALSE, NULL);
+ if (!hashfile)
+ return NULL;
+
+ /* look up this entry in the hash file */
+ info = hashfile_lookup(hashfile, &image.hash());
+
+ if (!info || !info->extrainfo)
+ {
+ hashfile_close(hashfile);
+ return NULL;
+ }
+
+ extra_info = auto_strdup(image.device().machine(), info->extrainfo);
+ if (!extra_info)
+ {
+ hashfile_close(hashfile);
+ return NULL;
+ }
+
+ /* copy the relevant entries */
+ hashfile_close(hashfile);
+
+ return extra_info;
+}
+
+const char *hashfile_extrainfo(device_image_interface &image)
+{
+ const char *rc;
+
+ /* now read the hash file */
+ image.crc();
+ extra_info = NULL;
+ int drv = driver_list::find(image.device().machine().system());
+ int compat, open = drv;
+ do
+ {
+ rc = read_hash_config(image, driver_list::driver(open).name);
+ // first check if there are compatible systems
+ compat = driver_list::compatible_with(open);
+ // if so, try to open its hashfile
+ if (compat != -1)
+ open = compat;
+ // otherwise, try with the parent
+ else
+ {
+ drv = driver_list::clone(drv);
+ open = drv;
+ }
+ }
+ // if no extrainfo has been found but we can try a compatible or a parent set, go back
+ while (rc == NULL && open != -1);
+ return rc;
+}
+
+/***************************************************************************
+ EXPAT INTERFACES
+***************************************************************************/
+
+/*-------------------------------------------------
+ expat_malloc/expat_realloc/expat_free -
+ wrappers for memory allocation functions so
+ that they pass through out memory tracking
+ systems
+-------------------------------------------------*/
+
+static void *expat_malloc(size_t size)
+{
+ return global_alloc_array_clear(UINT8,size);
+}
+
+static void *expat_realloc(void *ptr, size_t size)
+{
+ if (ptr) global_free(ptr);
+ return global_alloc_array_clear(UINT8,size);
+}
+
+static void expat_free(void *ptr)
+{
+ global_free(ptr);
+}
diff --git a/trunk/src/emu/hashfile.h b/trunk/src/emu/hashfile.h
new file mode 100644
index 00000000000..c59421487f2
--- /dev/null
+++ b/trunk/src/emu/hashfile.h
@@ -0,0 +1,17 @@
+/*********************************************************************
+
+ hashfile.h
+
+ Code for parsing hash info (*.hsi) files
+
+*********************************************************************/
+
+#ifndef __HASHFILE_H__
+#define __HASHFILE_H__
+
+#include "emu.h"
+
+
+const char *hashfile_extrainfo(device_image_interface &image);
+
+#endif /* __HASHFILE_H__ */
diff --git a/trunk/src/emu/image.c b/trunk/src/emu/image.c
new file mode 100644
index 00000000000..6dd8e70a926
--- /dev/null
+++ b/trunk/src/emu/image.c
@@ -0,0 +1,495 @@
+/***************************************************************************
+
+ image.c
+
+ Core image functions and definitions.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+#include <ctype.h>
+
+#include "emu.h"
+#include "emuopts.h"
+#include "image.h"
+#include "config.h"
+#include "xmlfile.h"
+#include "formats/ioprocs.h"
+
+/* ----------------------------------------------------------------------- */
+
+static int image_fseek_thunk(void *file, INT64 offset, int whence)
+{
+ device_image_interface *image = (device_image_interface *) file;
+ return image->fseek(offset, whence);
+}
+
+static size_t image_fread_thunk(void *file, void *buffer, size_t length)
+{
+ device_image_interface *image = (device_image_interface *) file;
+ return image->fread(buffer, length);
+}
+
+static size_t image_fwrite_thunk(void *file, const void *buffer, size_t length)
+{
+ device_image_interface *image = (device_image_interface *) file;
+ return image->fwrite(buffer, length);
+}
+
+static UINT64 image_fsize_thunk(void *file)
+{
+ device_image_interface *image = (device_image_interface *) file;
+ return image->length();
+}
+
+/* ----------------------------------------------------------------------- */
+
+struct io_procs image_ioprocs =
+{
+ NULL,
+ image_fseek_thunk,
+ image_fread_thunk,
+ image_fwrite_thunk,
+ image_fsize_thunk
+};
+
+/***************************************************************************
+ INITIALIZATION HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ image_dirs_load - loads image device directory
+ configuration items
+-------------------------------------------------*/
+
+static void image_dirs_load(running_machine &machine, int config_type, xml_data_node *parentnode)
+{
+ xml_data_node *node;
+ const char *dev_instance;
+ const char *working_directory;
+ device_image_interface *image = NULL;
+
+ if ((config_type == CONFIG_TYPE_GAME) && (parentnode != NULL))
+ {
+ for (node = xml_get_sibling(parentnode->child, "device"); node; node = xml_get_sibling(node->next, "device"))
+ {
+ dev_instance = xml_get_attribute_string(node, "instance", NULL);
+
+ if ((dev_instance != NULL) && (dev_instance[0] != '\0'))
+ {
+ for (bool gotone = machine.devicelist().first(image); gotone; gotone = image->next(image))
+ {
+ if (!strcmp(dev_instance, image->instance_name())) {
+ working_directory = xml_get_attribute_string(node, "directory", NULL);
+ if (working_directory != NULL)
+ image->set_working_directory(working_directory);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+
+/*-------------------------------------------------
+ image_dirs_save - saves out image device
+ directories to the configuration file
+-------------------------------------------------*/
+
+static void image_dirs_save(running_machine &machine, int config_type, xml_data_node *parentnode)
+{
+ xml_data_node *node;
+ const char *dev_instance;
+ device_image_interface *image = NULL;
+
+ /* only care about game-specific data */
+ if (config_type == CONFIG_TYPE_GAME)
+ {
+ for (bool gotone = machine.devicelist().first(image); gotone; gotone = image->next(image))
+ {
+ dev_instance = image->instance_name();
+
+ node = xml_add_child(parentnode, "device", NULL);
+ if (node != NULL)
+ {
+ xml_set_attribute(node, "instance", dev_instance);
+ xml_set_attribute(node, "directory", image->working_directory());
+ }
+ }
+ }
+}
+
+/*-------------------------------------------------
+ write_config - emit current option statuses as
+ INI files
+-------------------------------------------------*/
+
+static int write_config(emu_options &options, const char *filename, const game_driver *gamedrv)
+{
+ char buffer[128];
+ int retval = 1;
+
+ if (gamedrv != NULL)
+ {
+ sprintf(buffer, "%s.ini", gamedrv->name);
+ filename = buffer;
+ }
+
+ emu_file file(options.ini_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE);
+ file_error filerr = file.open(filename);
+ if (filerr == FILERR_NONE)
+ {
+ astring inistring;
+ options.output_ini(inistring);
+ file.puts(inistring);
+ retval = 0;
+ }
+ return retval;
+}
+
+/*-------------------------------------------------
+ image_options_extract - extract device options
+ out of core into the options
+-------------------------------------------------*/
+
+static void image_options_extract(running_machine &machine)
+{
+ /* only extract the device options if we've added them
+ no need to assert in case they are missing */
+ {
+ int index = 0;
+ device_image_interface *image = NULL;
+
+ for (bool gotone = machine.devicelist().first(image); gotone; gotone = image->next(image))
+ {
+ const char *filename = image->filename();
+
+ /* and set the option */
+ astring error;
+ machine.options().set_value(image->instance_name(), filename ? filename : "", OPTION_PRIORITY_CMDLINE, error);
+
+ index++;
+ }
+ }
+
+ /* write the config, if appropriate */
+ if (machine.options().write_config())
+ write_config(machine.options(), NULL, &machine.system());
+}
+
+/*-------------------------------------------------
+ image_unload_all - unload all images and
+ extract options
+-------------------------------------------------*/
+
+void image_unload_all(running_machine &machine)
+{
+ device_image_interface *image = NULL;
+
+ // extract the options
+ image_options_extract(machine);
+
+ for (bool gotone = machine.devicelist().first(image); gotone; gotone = image->next(image))
+ {
+ // unload this image
+ image->unload();
+ }
+}
+/*-------------------------------------------------
+ image_device_init - initialize devices for a specific
+ running_machine
+-------------------------------------------------*/
+
+void image_device_init(running_machine &machine)
+{
+ const char *image_name;
+ device_image_interface *image = NULL;
+
+ /* make sure that any required devices have been allocated */
+ for (bool gotone = machine.devicelist().first(image); gotone; gotone = image->next(image))
+ {
+ /* is an image specified for this image */
+ image_name = machine.options().device_option(*image);
+
+ if ((image_name != NULL) && (image_name[0] != '\0'))
+ {
+ /* mark init state */
+ image->set_init_phase();
+
+ /* try to load this image */
+ bool result = image->load(image_name);
+
+ /* did the image load fail? */
+ if (result)
+ {
+ /* retrieve image error message */
+ astring image_err = astring(image->error());
+ astring image_basename(image_name);
+
+ /* unload all images */
+ image_unload_all(machine);
+
+ fatalerror_exitcode(machine, MAMERR_DEVICE, "Device %s load (%s) failed: %s",
+ image->device().name(),
+ image_basename.cstr(),
+ image_err.cstr());
+ }
+ }
+ else
+ {
+ /* no image... must this device be loaded? */
+ if (image->must_be_loaded())
+ {
+ fatalerror_exitcode(machine, MAMERR_DEVICE, "Driver requires that device \"%s\" must have an image to load", image->instance_name());
+ }
+ }
+
+ image->call_get_devices();
+ }
+}
+
+/*-------------------------------------------------
+ image_postdevice_init - initialize devices for a specific
+ running_machine
+-------------------------------------------------*/
+
+void image_postdevice_init(running_machine &machine)
+{
+ device_image_interface *image = NULL;
+
+ /* make sure that any required devices have been allocated */
+ for (bool gotone = machine.devicelist().first(image); gotone; gotone = image->next(image))
+ {
+ int result = image->finish_load();
+ /* did the image load fail? */
+ if (result)
+ {
+ /* retrieve image error message */
+ astring image_err = astring(image->error());
+
+ /* unload all images */
+ image_unload_all(machine);
+
+ fatalerror_exitcode(machine, MAMERR_DEVICE, "Device %s load failed: %s",
+ image->device().name(),
+ image_err.cstr());
+ }
+ }
+
+ /* add a callback for when we shut down */
+ machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(image_unload_all), &machine));
+}
+/***************************************************************************
+ INITIALIZATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ image_init - start up the image system
+-------------------------------------------------*/
+
+void image_init(running_machine &machine)
+{
+ image_device_init(machine);
+ config_register(machine, "image_directories", config_saveload_delegate(FUNC(image_dirs_load), &machine), config_saveload_delegate(FUNC(image_dirs_save), &machine));
+}
+
+
+/****************************************************************************
+ Battery functions
+
+ These functions provide transparent access to battery-backed RAM on an
+ image; typically for cartridges.
+****************************************************************************/
+
+static char *stripspace(const char *src)
+{
+ static char buff[512];
+ if( src )
+ {
+ char *dst;
+ while( *src && isspace(*src) )
+ src++;
+ strcpy(buff, src);
+ dst = buff + strlen(buff);
+ while( dst >= buff && isspace(*--dst) )
+ *dst = '\0';
+ return buff;
+ }
+ return NULL;
+}
+
+//============================================================
+// strip_extension
+//============================================================
+
+static char *strip_extension(const char *filename)
+{
+ char *newname;
+ char *c;
+
+ // NULL begets NULL
+ if (!filename)
+ return NULL;
+
+ // allocate space for it
+ newname = (char *) malloc(strlen(filename) + 1);
+ if (!newname)
+ return NULL;
+
+ // copy in the name
+ strcpy(newname, filename);
+
+ // search backward for a period, failing if we hit a slash or a colon
+ for (c = newname + strlen(newname) - 1; c >= newname; c--)
+ {
+ // if we hit a period, NULL terminate and break
+ if (*c == '.')
+ {
+ *c = 0;
+ break;
+ }
+
+ // if we hit a slash or colon just stop
+ if (*c == '\\' || *c == '/' || *c == ':')
+ break;
+ }
+
+ return newname;
+}
+
+/*-------------------------------------------------
+ image_info_astring - populate an allocated
+ string with the image info text
+-------------------------------------------------*/
+
+astring *image_info_astring(running_machine &machine, astring *string)
+{
+ device_image_interface *image = NULL;
+
+ astring_printf(string, "%s\n\n", machine.system().description);
+
+#if 0
+ if (mess_ram_size > 0)
+ {
+ char buf2[RAM_STRING_BUFLEN];
+ astring_catprintf(string, "RAM: %s\n\n", ram_string(buf2, mess_ram_size));
+ }
+#endif
+
+ for (bool gotone = machine.devicelist().first(image); gotone; gotone = image->next(image))
+ {
+ const char *name = image->filename();
+ if (name != NULL)
+ {
+ const char *base_filename;
+ const char *info;
+ char *base_filename_noextension;
+
+ base_filename = image->basename();
+ base_filename_noextension = strip_extension(base_filename);
+
+ /* display device type and filename */
+ astring_catprintf(string, "%s: %s\n", image->device().name(), base_filename);
+
+ /* display long filename, if present and doesn't correspond to name */
+ info = image->longname();
+ if (info && (!base_filename_noextension || mame_stricmp(info, base_filename_noextension)))
+ astring_catprintf(string, "%s\n", info);
+
+ /* display manufacturer, if available */
+ info = image->manufacturer();
+ if (info != NULL)
+ {
+ astring_catprintf(string, "%s", info);
+ info = stripspace(image->year());
+ if (info && *info)
+ astring_catprintf(string, ", %s", info);
+ astring_catprintf(string,"\n");
+ }
+
+ /* display supported information, if available */
+ switch(image->supported()) {
+ case SOFTWARE_SUPPORTED_NO : astring_catprintf(string, "Not supported\n"); break;
+ case SOFTWARE_SUPPORTED_PARTIAL : astring_catprintf(string, "Partialy supported\n"); break;
+ default : break;
+ }
+
+ if (base_filename_noextension != NULL)
+ free(base_filename_noextension);
+ }
+ else
+ {
+ astring_catprintf(string, "%s: ---\n", image->device().name());
+ }
+ }
+ return string;
+}
+
+
+/*-------------------------------------------------
+ image_battery_load_by_name - retrieves the battery
+ backed RAM for an image. A filename may be supplied
+ to the function.
+-------------------------------------------------*/
+
+void image_battery_load_by_name(emu_options &options, const char *filename, void *buffer, int length, int fill)
+{
+ file_error filerr;
+ int bytes_read = 0;
+
+ assert_always(buffer && (length > 0), "Must specify sensical buffer/length");
+
+ /* try to open the battery file and read it in, if possible */
+ emu_file file(options.nvram_directory(), OPEN_FLAG_READ);
+ filerr = file.open(filename);
+ if (filerr == FILERR_NONE)
+ bytes_read = file.read(buffer, length);
+
+ /* fill remaining bytes (if necessary) */
+ memset(((char *) buffer) + bytes_read, fill, length - bytes_read);
+}
+
+/*-------------------------------------------------
+ image_battery_save_by_name - stores the battery
+ backed RAM for an image. A filename may be supplied
+ to the function.
+-------------------------------------------------*/
+void image_battery_save_by_name(emu_options &options, const char *filename, const void *buffer, int length)
+{
+ assert_always(buffer && (length > 0), "Must specify sensical buffer/length");
+
+ /* try to open the battery file and write it out, if possible */
+ emu_file file(options.nvram_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ file_error filerr = file.open(filename);
+ if (filerr == FILERR_NONE)
+ file.write(buffer, length);
+}
+
+/*-------------------------------------------------
+ image_from_absolute_index - retreives index number
+ of image in device list
+-------------------------------------------------*/
+device_image_interface *image_from_absolute_index(running_machine &machine, int absolute_index)
+{
+ device_image_interface *image = NULL;
+ int cnt = 0;
+ /* make sure that any required devices have been allocated */
+ for (bool gotone = machine.devicelist().first(image); gotone; gotone = image->next(image))
+ {
+ if (cnt==absolute_index) return image;
+ cnt++;
+ }
+ return NULL;
+}
+
+/*-------------------------------------------------
+ image_add_device_with_subdevices - adds
+ device with parameters sent, and all subdevices
+ from it's machine config devices list
+-------------------------------------------------*/
+void image_add_device_with_subdevices(device_t *owner, device_type type, const char *tag, UINT32 clock)
+{
+ owner->machine().add_dynamic_device(*owner, type, tag, clock);
+}
diff --git a/trunk/src/emu/image.h b/trunk/src/emu/image.h
new file mode 100644
index 00000000000..f1c963ffd3c
--- /dev/null
+++ b/trunk/src/emu/image.h
@@ -0,0 +1,35 @@
+/***************************************************************************
+
+ image.h
+
+ Core image interface functions and definitions.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __EMU_H__
+#error Dont include this file directly; include emu.h instead.
+#endif
+
+#ifndef __IMAGE_H__
+#define __IMAGE_H__
+
+void image_init(running_machine &machine);
+void image_postdevice_init(running_machine &machine);
+
+extern struct io_procs image_ioprocs;
+
+void image_battery_load_by_name(emu_options &options, const char *filename, void *buffer, int length, int fill);
+void image_battery_save_by_name(emu_options &options, const char *filename, const void *buffer, int length);
+
+astring *image_info_astring(running_machine &machine, astring *string);
+
+device_image_interface *image_from_absolute_index(running_machine &machine, int absolute_index);
+
+void image_add_device_with_subdevices(device_t *owner, device_type type, const char *tag, UINT32 clock);
+
+#endif /* __IMAGE_H__ */
diff --git a/trunk/src/emu/imagedev/bitbngr.c b/trunk/src/emu/imagedev/bitbngr.c
new file mode 100644
index 00000000000..9bbef4ecc83
--- /dev/null
+++ b/trunk/src/emu/imagedev/bitbngr.c
@@ -0,0 +1,523 @@
+/*********************************************************************
+
+ bitbngr.c
+
+ TRS style "bitbanger" serial port
+
+*********************************************************************/
+
+#include "emu.h"
+#include "bitbngr.h"
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _bitbanger_token bitbanger_token;
+struct _bitbanger_token
+{
+ emu_timer *bitbanger_output_timer;
+ emu_timer *bitbanger_input_timer;
+ int output_value;
+ int build_count;
+ int build_byte;
+ attotime idle_delay;
+ attotime current_baud;
+ UINT32 input_buffer_size;
+ UINT32 input_buffer_cursor;
+ int mode;
+ int baud;
+ int tune;
+ UINT8 input_buffer[1000];
+};
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static TIMER_CALLBACK(bitbanger_output_timer);
+static TIMER_CALLBACK(bitbanger_input_timer);
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+
+/*-------------------------------------------------
+ get_token - safely gets the bitbanger data
+-------------------------------------------------*/
+
+INLINE bitbanger_token *get_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == BITBANGER);
+ return (bitbanger_token *) downcast<legacy_device_base *>(device)->token();
+}
+
+
+/*-------------------------------------------------
+ get_config - safely gets the bitbanger config
+-------------------------------------------------*/
+
+INLINE const bitbanger_config *get_config(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == BITBANGER);
+ return (const bitbanger_config *) device->static_config();
+}
+
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+
+/*-------------------------------------------------
+ native_output - outputs data to a file
+-------------------------------------------------*/
+
+static void native_output(device_t *bitbanger, UINT8 data)
+{
+ device_image_interface *image = dynamic_cast<device_image_interface *>(bitbanger);
+ if (image->exists())
+ {
+ image->fwrite(&data, 1);
+ }
+}
+
+
+/*-------------------------------------------------
+ native_input - inputs data from a file
+-------------------------------------------------*/
+
+static UINT32 native_input(device_t *bitbanger, void *buffer, UINT32 length)
+{
+ device_image_interface *image = dynamic_cast<device_image_interface *>(bitbanger);
+ if (image->exists())
+ {
+ return image->fread(buffer, length);
+ }
+
+ return 0;
+}
+
+
+/*-------------------------------------------------
+ bitbanger_mode_string
+-------------------------------------------------*/
+const char *bitbanger_mode_string(device_t *device)
+{
+ bitbanger_token *bi = get_token(device);
+ static const char *const modes[] = {"Printer", "Modem"};
+
+ return(modes[bi->mode]);
+}
+
+
+/*-------------------------------------------------
+ bitbanger_inc_mode
+-------------------------------------------------*/
+bool bitbanger_inc_mode(device_t *device, bool test)
+{
+ bitbanger_token *bi = get_token(device);
+ int adjust_mode = (int)bi->mode + 1;
+
+ if( adjust_mode >= BITBANGER_MODE_MAX )
+ return FALSE;
+
+ if( !test)
+ bi->mode = adjust_mode;
+
+ return TRUE;
+}
+
+
+/*-------------------------------------------------
+ bitbanger_dec_mode
+-------------------------------------------------*/
+bool bitbanger_dec_mode(device_t *device, bool test)
+{
+ bitbanger_token *bi = get_token(device);
+ int adjust_mode = bi->mode - 1;
+
+ if( adjust_mode < 0 )
+ return FALSE;
+
+ if( !test)
+ bi->mode = adjust_mode;
+
+ return TRUE;
+}
+
+
+/*-------------------------------------------------
+ bitbanger_tune_string
+-------------------------------------------------*/
+const char *bitbanger_tune_string(device_t *device)
+{
+ bitbanger_token *bi = get_token(device);
+ static const char *const tunes[] = {"-2.0%", "-1.75%", "-1.5%", "-1.25%", "-1.0%", "-0.75%", "-0.5", "-0.25%", "\xc2\xb1""0%",
+ "+0.25%", "+0.5%", "+0.75%", "+1.0%", "+1.25%", "+1.5%", "+1.75%", "+2.0%"};
+
+ return(tunes[bi->tune]);
+}
+
+
+/*-------------------------------------------------
+ bitbanger_tune_value
+-------------------------------------------------*/
+static float bitbanger_tune_value(device_t *device)
+{
+ bitbanger_token *bi = get_token(device);
+ static const float tunes[] = {0.97f, 0.9825f, 0.985f, 0.9875f, 0.99f, 0.9925f, 0.995f, 0.9975f, 1.0f,
+ 1.0025f, 1.005f, 1.0075f, 1.01f, 1.0125f, 1.015f, 1.0175f, 1.02f};
+
+ return(tunes[bi->tune]);
+}
+
+
+/*-------------------------------------------------
+ bitbanger_baud_value
+-------------------------------------------------*/
+
+static UINT32 bitbanger_baud_value(device_t *device)
+{
+ bitbanger_token *bi = get_token(device);
+ static const float bauds[] = { 150.0f, 300.0f, 600.0f, 1200.0f, 2400.0f, 4800.0f, 9600.0f,
+ 14400.0f, 28800.0f, 38400.0f, 57600.0f, 115200.0f};
+ float result = bitbanger_tune_value(device) * bauds[bi->baud];
+ return (UINT32)result;
+}
+
+
+/*-------------------------------------------------
+ bitbanger_baud_string
+-------------------------------------------------*/
+
+const char *bitbanger_baud_string(device_t *device)
+{
+ bitbanger_token *bi = get_token(device);
+ static const char *const bauds[] = { "150", "300", "600", "1200", "2400", "4800",
+ "9600", "14400", "28800", "38400", "57600", "115200"};
+
+ return(bauds[bi->baud]);
+}
+
+
+/*-------------------------------------------------
+ bitbanger_inc_baud
+-------------------------------------------------*/
+bool bitbanger_inc_baud(device_t *device, bool test)
+{
+ bitbanger_token *bi = get_token(device);
+ int adjust_baud = (int)bi->baud + 1;
+
+ if( adjust_baud >= BITBANGER_BAUD_MAX )
+ return FALSE;
+
+ if( !test)
+ {
+ bi->baud = adjust_baud;
+ bi->current_baud = attotime::from_hz(bitbanger_baud_value(device));
+ }
+
+ return TRUE;
+}
+
+
+/*-------------------------------------------------
+ bitbanger_dec_baud
+-------------------------------------------------*/
+bool bitbanger_dec_baud(device_t *device, bool test)
+{
+ bitbanger_token *bi = get_token(device);
+ int adjust_baud = bi->baud - 1;
+
+ if( adjust_baud < 0 )
+ return FALSE;
+
+ if( !test)
+ {
+ bi->baud = adjust_baud;
+ bi->current_baud = attotime::from_hz(bitbanger_baud_value(device));
+ }
+
+ return TRUE;
+}
+
+
+/*-------------------------------------------------
+ bitbanger_inc_tune
+-------------------------------------------------*/
+bool bitbanger_inc_tune(device_t *device, bool test)
+{
+ bitbanger_token *bi = get_token(device);
+ int adjust_tune = (int)bi->tune + 1;
+
+ if( adjust_tune >= BITBANGER_TUNE_MAX )
+ return FALSE;
+
+ if( !test)
+ {
+ bi->tune = adjust_tune;
+ bi->current_baud = attotime::from_hz(bitbanger_baud_value(device));
+ }
+
+ return TRUE;
+}
+
+
+/*-------------------------------------------------
+ bitbanger_dec_tune
+-------------------------------------------------*/
+bool bitbanger_dec_tune(device_t *device, bool test)
+{
+ bitbanger_token *bi = get_token(device);
+ int adjust_tune = bi->tune - 1;
+
+ if( adjust_tune < 0 )
+ return FALSE;
+
+ if( !test)
+ {
+ bi->tune = adjust_tune;
+ bi->current_baud = attotime::from_hz(bitbanger_baud_value(device));
+ }
+
+ return TRUE;
+}
+
+
+/*-------------------------------------------------
+ bitbanger_bytes_to_bits_81N
+-------------------------------------------------*/
+static void bitbanger_bytes_to_bits_81N(device_t *img)
+{
+ bitbanger_token *bi = get_token(img);
+ UINT8 byte_buffer[100];
+ UINT32 byte_buffer_size, bit_buffer_size;
+ int i, j;
+ static const UINT8 bitmask[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
+
+ bit_buffer_size = 0;
+ byte_buffer_size = native_input(img, byte_buffer, sizeof(byte_buffer));
+
+ /* Translate byte buffer into bit buffer using: 1 start bit, 8 data bits, 1 stop bit, no parity */
+
+ for( i=0; i<byte_buffer_size; i++ )
+ {
+ bi->input_buffer[bit_buffer_size++] = 0;
+
+ for( j=0; j<8; j++ )
+ {
+ if( byte_buffer[i] & bitmask[j] )
+ bi->input_buffer[bit_buffer_size++] = 1;
+ else
+ bi->input_buffer[bit_buffer_size++] = 0;
+ }
+
+ bi->input_buffer[bit_buffer_size++] = 1;
+ }
+
+ bi->input_buffer_size = bit_buffer_size;
+ bi->input_buffer_cursor = 0;
+}
+
+
+/*-------------------------------------------------
+ DEVICE_START(bitbanger)
+-------------------------------------------------*/
+
+static DEVICE_START(bitbanger)
+{
+ bitbanger_token *bi;
+ const bitbanger_config *config = get_config(device);
+
+ bi = get_token(device);
+
+ /* output config */
+ bi->build_count = 0;
+ bi->bitbanger_output_timer = device->machine().scheduler().timer_alloc(FUNC(bitbanger_output_timer), (void *) device);
+
+ /* input config */
+ bi->bitbanger_input_timer = device->machine().scheduler().timer_alloc(FUNC(bitbanger_input_timer), (void *) device );
+ bi->idle_delay = attotime::from_seconds(1);
+ bi->input_buffer_size = 0;
+ bi->input_buffer_cursor = 0;
+
+ bi->mode = config->default_mode;
+ bi->baud = config->default_baud;
+ bi->tune = config->default_tune;
+ bi->current_baud = attotime::from_hz(bitbanger_baud_value(device));
+
+ /* test callback */
+ if(!config->input_callback)
+ fatalerror("Misconfigured bitbanger device: input_callback cannot be NULL\n");
+}
+
+
+/*-------------------------------------------------
+ TIMER_CALLBACK(bitbanger_output_timer)
+-------------------------------------------------*/
+
+static TIMER_CALLBACK(bitbanger_output_timer)
+{
+ device_t *device = (device_t *) ptr;
+ bitbanger_token *bi = get_token(device);
+
+ /* this ia harded coded for 8-1-N */
+ if( bi->output_value )
+ bi->build_byte |= 0x200;
+
+ bi->build_byte >>= 1;
+ bi->build_count--;
+
+ if(bi->build_count == 0)
+ {
+ if( bi->output_value == 1 )
+ native_output( device, bi->build_byte );
+ else
+ logerror("Bitbanger: Output framing error.\n" );
+
+ bi->bitbanger_output_timer->reset();
+ }
+}
+
+
+/*-------------------------------------------------
+ TIMER_CALLBACK(bitbanger_input_timer)
+-------------------------------------------------*/
+
+static TIMER_CALLBACK(bitbanger_input_timer)
+{
+ device_t *device = (device_t *) ptr;
+ bitbanger_token *bi = get_token(device);
+ const bitbanger_config *config = get_config(device);
+
+ if(bi->input_buffer_cursor == bi->input_buffer_size)
+ {
+ /* get more data */
+ bitbanger_bytes_to_bits_81N(device);
+
+ if(bi->input_buffer_size == 0)
+ {
+ /* no more data, wait and try again */
+ bi->idle_delay = min(bi->idle_delay + attotime::from_msec(100), attotime::from_seconds(1));
+ bi->bitbanger_input_timer->adjust(bi->idle_delay);
+
+
+ if( bi->mode == BITBANGER_MODEM )
+ config->input_callback(machine, 1);
+ else
+ config->input_callback(machine, 0);
+
+ return;
+ }
+ else
+ {
+ bi->idle_delay = bi->current_baud;
+ bi->bitbanger_input_timer->adjust(bi->idle_delay, 0, bi->idle_delay);
+ }
+ }
+
+ /* send bit to driver */
+ config->input_callback(machine, bi->input_buffer[(bi->input_buffer_cursor)++]);
+}
+
+
+/*-------------------------------------------------
+ bitbanger_output - outputs data to a bitbanger
+ port
+-------------------------------------------------*/
+
+void bitbanger_output(device_t *device, int value)
+{
+ bitbanger_token *bi = get_token(device);
+ attotime one_point_five_baud;
+
+ if( bi->build_count == 0 && bi->output_value == 1 && value == 0 )
+ {
+ /* we found our start bit */
+ /* eight bits of data, plus one of stop */
+ bi->build_count = 9;
+ bi->build_byte = 0;
+
+ one_point_five_baud = bi->current_baud + bi->current_baud / 2;
+ bi->bitbanger_output_timer->adjust(one_point_five_baud, 0, bi->current_baud);
+ }
+
+ //fprintf(stderr,"%s, %d\n", device->machine().time().as_string(9), value);
+ bi->output_value = value;
+}
+
+
+/*-------------------------------------------------
+ DEVICE_IMAGE_LOAD( bitbanger )
+-------------------------------------------------*/
+
+static DEVICE_IMAGE_LOAD( bitbanger )
+{
+ device_t *device = &image.device();
+ bitbanger_token *bi;
+ bi = get_token(device);
+
+ bi->bitbanger_input_timer->enable(true);
+ bi->bitbanger_input_timer->adjust(attotime::zero, 0, attotime::from_seconds(1));
+
+ /* we don't need to do anything special */
+ return IMAGE_INIT_PASS;
+}
+
+
+/*-------------------------------------------------
+ DEVICE_IMAGE_UNLOAD( bitbanger )
+-------------------------------------------------*/
+
+static DEVICE_IMAGE_UNLOAD( bitbanger )
+{
+ device_t *device = &image.device();
+ bitbanger_token *bi;
+ bi = get_token(device);
+
+ bi->bitbanger_input_timer->enable(false);
+}
+
+
+/*-------------------------------------------------
+ DEVICE_GET_INFO(bitbanger) - device getinfo
+ function
+-------------------------------------------------*/
+
+DEVICE_GET_INFO(bitbanger)
+{
+ switch(state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(bitbanger_token); break;
+ case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break;
+ case DEVINFO_INT_IMAGE_TYPE: info->i = IO_PRINTER; break;
+ case DEVINFO_INT_IMAGE_READABLE: info->i = 1; break;
+ case DEVINFO_INT_IMAGE_WRITEABLE: info->i = 1; break;
+ case DEVINFO_INT_IMAGE_CREATABLE: info->i = 1; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(bitbanger); break;
+ case DEVINFO_FCT_IMAGE_LOAD: info->f = (genf *) DEVICE_IMAGE_LOAD_NAME(bitbanger); break;
+ case DEVINFO_FCT_IMAGE_UNLOAD: info->f = (genf *) DEVICE_IMAGE_UNLOAD_NAME(bitbanger); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Bitbanger"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Bitbanger"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_IMAGE_FILE_EXTENSIONS: strcpy(info->s, "prn"); break;
+ }
+}
+
+DEFINE_LEGACY_IMAGE_DEVICE(BITBANGER, bitbanger);
diff --git a/trunk/src/emu/imagedev/bitbngr.h b/trunk/src/emu/imagedev/bitbngr.h
new file mode 100644
index 00000000000..18999a336d7
--- /dev/null
+++ b/trunk/src/emu/imagedev/bitbngr.h
@@ -0,0 +1,99 @@
+/*********************************************************************
+
+ bitbngr.h
+
+ TRS style "bitbanger" serial port
+
+*********************************************************************/
+
+#ifndef __BITBNGR_H__
+#define __BITBNGR_H__
+
+#include "image.h"
+
+
+enum
+{
+ BITBANGER_PRINTER = 0,
+ BITBANGER_MODEM,
+ BITBANGER_MODE_MAX,
+
+ BITBANGER_150 = 0,
+ BITBANGER_300,
+ BITBANGER_600,
+ BITBANGER_1200,
+ BITBANGER_2400,
+ BITBANGER_4800,
+ BITBANGER_9600,
+ BITBANGER_14400,
+ BITBANGER_28800,
+ BITBANGER_38400,
+ BITBANGER_57600,
+ BITBANGER_115200,
+ BITBANGER_BAUD_MAX,
+
+ BITBANGER_NEG40PERCENT = 0,
+ BITBANGER_NEG35PERCENT,
+ BITBANGER_NEG30PERCENT,
+ BITBANGER_NEG25PERCENT,
+ BITBANGER_NEG20PERCENT,
+ BITBANGER_NEG15PERCENT,
+ BITBANGER_NEG10PERCENT,
+ BITBANGER_NEG5PERCENT,
+ BITBANGER_0PERCENT,
+ BITBANGER_POS5PERCENT,
+ BITBANGER_POS10PERCENT,
+ BITBANGER_POS15PERCENT,
+ BITBANGER_POS20PERCENT,
+ BITBANGER_POS25PERCENT,
+ BITBANGER_POS30PERCENT,
+ BITBANGER_POS35PERCENT,
+ BITBANGER_POS40PERCENT,
+ BITBANGER_TUNE_MAX
+};
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+DECLARE_LEGACY_IMAGE_DEVICE(BITBANGER, bitbanger);
+
+#define MCFG_BITBANGER_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, BITBANGER, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _bitbanger_config bitbanger_config;
+struct _bitbanger_config
+{
+ /* callback to driver */
+ void (*input_callback)(running_machine &machine, UINT8 bit);
+ int default_mode; /* emulating a printer or modem */
+ int default_baud; /* output bits per second */
+ int default_tune; /* fine tune adjustment to the baud */
+};
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+/* outputs data to a bitbanger port */
+void bitbanger_output(device_t *device, int value);
+
+/* ui functions */
+const char *bitbanger_mode_string(device_t *device);
+const char *bitbanger_baud_string(device_t *device);
+const char *bitbanger_tune_string(device_t *device);
+bool bitbanger_inc_mode(device_t *device, bool test);
+bool bitbanger_dec_mode(device_t *device, bool test);
+bool bitbanger_inc_tune(device_t *device, bool test);
+bool bitbanger_dec_tune(device_t *device, bool test);
+bool bitbanger_inc_baud(device_t *device, bool test);
+bool bitbanger_dec_baud(device_t *device, bool test);
+
+#endif /* __BITBNGR_H__ */
diff --git a/trunk/src/emu/imagedev/cartslot.c b/trunk/src/emu/imagedev/cartslot.c
new file mode 100644
index 00000000000..bc5c7444b9a
--- /dev/null
+++ b/trunk/src/emu/imagedev/cartslot.c
@@ -0,0 +1,315 @@
+/**********************************************************************
+
+ cartslot.c
+
+ Cartridge device
+
+**********************************************************************/
+
+#include <ctype.h>
+#include "emu.h"
+#include "cartslot.h"
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+enum _process_mode
+{
+ PROCESS_CLEAR,
+ PROCESS_LOAD
+};
+typedef enum _process_mode process_mode;
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE const cartslot_config *get_config(const device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == CARTSLOT);
+ return (const cartslot_config *) downcast<const legacy_device_base *>(device)->inline_config();
+}
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ load_cartridge
+-------------------------------------------------*/
+
+static int load_cartridge(device_image_interface *image, const rom_entry *romrgn, const rom_entry *roment, process_mode mode)
+{
+ const char *region;
+ const char *type;
+ UINT32 flags;
+ offs_t offset, length, read_length, pos = 0, len;
+ UINT8 *ptr;
+ UINT8 clear_val;
+ int datawidth, littleendian, i, j;
+ device_t *cpu;
+
+ astring regiontag;
+ image->device().siblingtag(regiontag, ROMREGION_GETTAG(romrgn));
+ region = regiontag.cstr();
+ offset = ROM_GETOFFSET(roment);
+ length = ROM_GETLENGTH(roment);
+ flags = ROM_GETFLAGS(roment);
+ ptr = ((UINT8 *) image->device().machine().region(region)->base()) + offset;
+
+ if (mode == PROCESS_LOAD)
+ {
+ if (image->software_entry() == NULL)
+ {
+ /* must this be full size */
+ if (flags & ROM_FULLSIZE)
+ {
+ if (image->length() != length)
+ return IMAGE_INIT_FAIL;
+ }
+
+ /* read the ROM */
+ pos = read_length = image->fread(ptr, length);
+
+ /* reset the ROM to the initial point. */
+ /* eventually, we could add a flag to allow the ROM to continue instead of restarting whenever a new cart region is present */
+ image->fseek(0, SEEK_SET);
+ }
+ else
+ {
+ /* must this be full size */
+ if (flags & ROM_FULLSIZE)
+ {
+ if (image->get_software_region_length("rom") != length)
+ return IMAGE_INIT_FAIL;
+ }
+
+ /* read the ROM */
+ pos = read_length = image->get_software_region_length("rom");
+ memcpy(ptr, image->get_software_region("rom"), read_length);
+ }
+
+ /* do we need to mirror the ROM? */
+ if (flags & ROM_MIRROR)
+ {
+ while(pos < length)
+ {
+ len = MIN(read_length, length - pos);
+ memcpy(ptr + pos, ptr, len);
+ pos += len;
+ }
+ }
+
+ /* postprocess this region */
+ type = regiontag.cstr();
+ littleendian = ROMREGION_ISLITTLEENDIAN(romrgn);
+ datawidth = ROMREGION_GETWIDTH(romrgn) / 8;
+
+ /* if the region is inverted, do that now */
+ device_memory_interface *memory;
+ cpu = image->device().machine().device(type);
+ if (cpu!=NULL && cpu->interface(memory))
+ {
+ datawidth = cpu->memory().space_config(AS_PROGRAM)->m_databus_width / 8;
+ littleendian = (cpu->memory().space_config()->m_endianness == ENDIANNESS_LITTLE);
+ }
+
+ /* swap the endianness if we need to */
+#ifdef LSB_FIRST
+ if (datawidth > 1 && !littleendian)
+#else
+ if (datawidth > 1 && littleendian)
+#endif
+ {
+ for (i = 0; i < length; i += datawidth)
+ {
+ UINT8 temp[8];
+ memcpy(temp, &ptr[i], datawidth);
+ for (j = datawidth - 1; j >= 0; j--)
+ ptr[i + j] = temp[datawidth - 1 - j];
+ }
+ }
+ }
+
+ /* clear out anything that remains */
+ if (!(flags & ROM_NOCLEAR))
+ {
+ clear_val = (flags & ROM_FILL_FF) ? 0xFF : 0x00;
+ memset(ptr + pos, clear_val, length - pos);
+ }
+ return IMAGE_INIT_PASS;
+}
+
+
+
+/*-------------------------------------------------
+ process_cartridge
+-------------------------------------------------*/
+
+static int process_cartridge(device_image_interface *image, process_mode mode)
+{
+ const rom_source *source;
+ const rom_entry *romrgn, *roment;
+ int result = 0;
+
+ for (source = rom_first_source(image->device().machine().config()); source != NULL; source = rom_next_source(*source))
+ {
+ for (romrgn = rom_first_region(*source); romrgn != NULL; romrgn = rom_next_region(romrgn))
+ {
+ roment = romrgn + 1;
+ while(!ROMENTRY_ISREGIONEND(roment))
+ {
+ if (ROMENTRY_GETTYPE(roment) == ROMENTRYTYPE_CARTRIDGE)
+ {
+ astring regiontag;
+ image->device().siblingtag(regiontag, roment->_hashdata);
+
+ if (strcmp(regiontag.cstr(),image->device().tag())==0)
+ {
+ result |= load_cartridge(image, romrgn, roment, mode);
+
+ /* if loading failed in any cart region, stop loading */
+ if (result)
+ return result;
+ }
+ }
+ roment++;
+ }
+ }
+ }
+
+ return IMAGE_INIT_PASS;
+}
+
+/*-------------------------------------------------
+ DEVICE_START( cartslot )
+-------------------------------------------------*/
+
+static DEVICE_START( cartslot )
+{
+ const cartslot_config *config = get_config(device);
+
+ /* if this cartridge has a custom DEVICE_START, use it */
+ if (config->device_start != NULL)
+ {
+ (*config->device_start)(device);
+ }
+}
+
+
+/*-------------------------------------------------
+ DEVICE_IMAGE_LOAD( cartslot )
+-------------------------------------------------*/
+
+static DEVICE_IMAGE_LOAD( cartslot )
+{
+ device_t *device = &image.device();
+ const cartslot_config *config = get_config(device);
+
+ /* if this cartridge has a custom DEVICE_IMAGE_LOAD, use it */
+ if (config->device_load != NULL)
+ return (*config->device_load)(image);
+
+ /* otherwise try the normal route */
+ return process_cartridge(&image, PROCESS_LOAD);
+}
+
+
+/*-------------------------------------------------
+ DEVICE_IMAGE_UNLOAD( cartslot )
+-------------------------------------------------*/
+
+static DEVICE_IMAGE_UNLOAD( cartslot )
+{
+ device_t *device = &image.device();
+ const cartslot_config *config = get_config(device);
+
+ /* if this cartridge has a custom DEVICE_IMAGE_UNLOAD, use it */
+ if (config->device_unload != NULL)
+ {
+ (*config->device_unload)(image);
+ return;
+ }
+ process_cartridge(&image, PROCESS_CLEAR);
+}
+
+/*-------------------------------------------------
+ DEVICE_IMAGE_SOFTLIST_LOAD(cartslot)
+-------------------------------------------------*/
+static DEVICE_IMAGE_SOFTLIST_LOAD(cartslot)
+{
+ load_software_part_region( &image.device(), swlist, swname, start_entry );
+ return TRUE;
+}
+
+/*-------------------------------------------------
+ DEVICE_GET_INFO( cartslot )
+-------------------------------------------------*/
+
+DEVICE_GET_INFO( cartslot )
+{
+ switch(state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = 0; break;
+ case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = sizeof(cartslot_config); break;
+ case DEVINFO_INT_IMAGE_TYPE: info->i = IO_CARTSLOT; break;
+ case DEVINFO_INT_IMAGE_READABLE: info->i = 1; break;
+ case DEVINFO_INT_IMAGE_WRITEABLE: info->i = 0; break;
+ case DEVINFO_INT_IMAGE_CREATABLE: info->i = 0; break;
+ case DEVINFO_INT_IMAGE_RESET_ON_LOAD: info->i = 1; break;
+ case DEVINFO_INT_IMAGE_MUST_BE_LOADED:
+ if ( device && downcast<const legacy_image_device_base *>(device)->inline_config()) {
+ info->i = get_config(device)->must_be_loaded;
+ } else {
+ info->i = 0;
+ }
+ break;
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(cartslot); break;
+ case DEVINFO_FCT_IMAGE_LOAD: info->f = (genf *) DEVICE_IMAGE_LOAD_NAME(cartslot); break;
+ case DEVINFO_FCT_IMAGE_UNLOAD: info->f = (genf *) DEVICE_IMAGE_UNLOAD_NAME(cartslot); break;
+ case DEVINFO_FCT_IMAGE_SOFTLIST_LOAD: info->f = (genf *) DEVICE_IMAGE_SOFTLIST_LOAD_NAME(cartslot); break;
+ case DEVINFO_FCT_IMAGE_PARTIAL_HASH:
+ if ( device && downcast<const legacy_image_device_base *>(device)->inline_config() && get_config(device)->device_partialhash) {
+ info->f = (genf *) get_config(device)->device_partialhash;
+ } else {
+ info->f = NULL;
+ }
+ break;
+ case DEVINFO_FCT_IMAGE_DISPLAY_INFO:
+ if ( device && downcast<const legacy_image_device_base *>(device)->inline_config() && get_config(device)->device_displayinfo) {
+ info->f = (genf *) get_config(device)->device_displayinfo;
+ } else {
+ info->f = NULL;
+ }
+ break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Cartslot"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Cartslot"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_IMAGE_FILE_EXTENSIONS:
+ if ( device && downcast<const legacy_image_device_base *>(device)->inline_config() && get_config(device)->extensions )
+ {
+ strcpy(info->s, get_config(device)->extensions);
+ }
+ else
+ {
+ strcpy(info->s, "bin");
+ }
+ break;
+ case DEVINFO_STR_IMAGE_INTERFACE:
+ if ( device && downcast<const legacy_image_device_base *>(device)->inline_config() && get_config(device)->interface )
+ {
+ strcpy(info->s, get_config(device)->interface );
+ }
+ break;
+ }
+}
+
+DEFINE_LEGACY_IMAGE_DEVICE(CARTSLOT, cartslot);
diff --git a/trunk/src/emu/imagedev/cartslot.h b/trunk/src/emu/imagedev/cartslot.h
new file mode 100644
index 00000000000..2b31a3beb01
--- /dev/null
+++ b/trunk/src/emu/imagedev/cartslot.h
@@ -0,0 +1,84 @@
+/***************************************************************************
+
+ Cartrige loading
+
+***************************************************************************/
+
+#ifndef __CARTSLOT_H__
+#define __CARTSLOT_H__
+
+#include "image.h"
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+#define ROM_CART_LOAD(tag,offset,length,flags) \
+ { NULL, tag, offset, length, ROMENTRYTYPE_CARTRIDGE | (flags) },
+
+#define ROM_MIRROR 0x01000000
+#define ROM_NOMIRROR 0x00000000
+#define ROM_FULLSIZE 0x02000000
+#define ROM_FILL_FF 0x04000000
+#define ROM_NOCLEAR 0x08000000
+
+DECLARE_LEGACY_IMAGE_DEVICE(CARTSLOT, cartslot);
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _cartslot_config cartslot_config;
+struct _cartslot_config
+{
+ const char * extensions;
+ const char * interface;
+ int must_be_loaded;
+ device_start_func device_start;
+ device_image_load_func device_load;
+ device_image_unload_func device_unload;
+ device_image_partialhash_func device_partialhash;
+ device_image_display_info_func device_displayinfo;
+};
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_CARTSLOT_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, CARTSLOT, 0) \
+
+#define MCFG_CARTSLOT_MODIFY(_tag) \
+ MCFG_DEVICE_MODIFY(_tag) \
+
+#define MCFG_CARTSLOT_EXTENSION_LIST(_extensions) \
+ MCFG_DEVICE_CONFIG_DATAPTR(cartslot_config, extensions, _extensions)
+
+#define MCFG_CARTSLOT_NOT_MANDATORY \
+ MCFG_DEVICE_CONFIG_DATA32(cartslot_config, must_be_loaded, FALSE)
+
+#define MCFG_CARTSLOT_MANDATORY \
+ MCFG_DEVICE_CONFIG_DATA32(cartslot_config, must_be_loaded, TRUE)
+
+#define MCFG_CARTSLOT_START(_start) \
+ MCFG_DEVICE_CONFIG_DATAPTR(cartslot_config, device_start, DEVICE_START_NAME(_start))
+
+#define MCFG_CARTSLOT_LOAD(_load) \
+ MCFG_DEVICE_CONFIG_DATAPTR(cartslot_config, device_load, DEVICE_IMAGE_LOAD_NAME(_load))
+
+#define MCFG_CARTSLOT_UNLOAD(_unload) \
+ MCFG_DEVICE_CONFIG_DATAPTR(cartslot_config, device_unload, DEVICE_IMAGE_UNLOAD_NAME(_unload))
+
+#define MCFG_CARTSLOT_DISPLAY_INFO(_displayinfo) \
+ MCFG_DEVICE_CONFIG_DATAPTR(cartslot_config, device_displayinfo, DEVICE_IMAGE_DISPLAY_INFO_NAME(_displayinfo))
+
+#define MCFG_CARTSLOT_PARTIALHASH(_partialhash) \
+ MCFG_DEVICE_CONFIG_DATAPTR(cartslot_config, device_partialhash, _partialhash)
+
+#define MCFG_CARTSLOT_INTERFACE(_interface) \
+ MCFG_DEVICE_CONFIG_DATAPTR(cartslot_config, interface, _interface )
+
+#endif /* __cart_slot_H__ */
diff --git a/trunk/src/emu/imagedev/cassette.c b/trunk/src/emu/imagedev/cassette.c
new file mode 100644
index 00000000000..0ff99eccc01
--- /dev/null
+++ b/trunk/src/emu/imagedev/cassette.c
@@ -0,0 +1,380 @@
+/*********************************************************************
+
+ cassette.c
+
+ Interface to the cassette image abstraction code
+
+*********************************************************************/
+
+#include "emu.h"
+#include "formats/imageutl.h"
+#include "cassette.h"
+#include "ui.h"
+
+
+#define ANIMATION_FPS 1
+#define ANIMATION_FRAMES 4
+
+#define VERBOSE 0
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+/* Default cassette_interface for drivers only wav files */
+const cassette_interface default_cassette_interface =
+{
+ cassette_default_formats,
+ NULL,
+ CASSETTE_PLAY,
+ NULL,
+ NULL
+};
+
+
+// device type definition
+const device_type CASSETTE = &device_creator<cassette_image_device>;
+
+//-------------------------------------------------
+// cassette_image_device - constructor
+//-------------------------------------------------
+
+cassette_image_device::cassette_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, CASSETTE, "Cassette", tag, owner, clock),
+ device_image_interface(mconfig, *this)
+{
+
+}
+
+//-------------------------------------------------
+// cassette_image_device - destructor
+//-------------------------------------------------
+
+cassette_image_device::~cassette_image_device()
+{
+}
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void cassette_image_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const cassette_interface *intf = reinterpret_cast<const cassette_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<cassette_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_formats, 0, sizeof(m_formats));
+ memset(&m_create_opts, 0, sizeof(m_create_opts));
+ memset(&m_default_state, 0, sizeof(m_default_state));
+ memset(&m_interface, 0, sizeof(m_interface));
+ memset(&m_device_displayinfo, 0, sizeof(m_device_displayinfo));
+ }
+
+ m_extension_list[0] = '\0';
+ for (int i = 0; m_formats[i]; i++ )
+ image_specify_extension( m_extension_list, 256, m_formats[i]->extensions );
+
+ // set brief and instance name
+ update_names();
+}
+
+
+/*********************************************************************
+ cassette IO
+*********************************************************************/
+
+bool cassette_image_device::is_motor_on()
+{
+ if ((m_state & CASSETTE_MASK_UISTATE) == CASSETTE_STOPPED)
+ return FALSE;
+ if ((m_state & CASSETTE_MASK_MOTOR) != CASSETTE_MOTOR_ENABLED)
+ return FALSE;
+ return TRUE;
+}
+
+
+
+void cassette_image_device::update()
+{
+ double cur_time = device().machine().time().as_double();
+
+ if (is_motor_on())
+ {
+ double new_position = m_position + (cur_time - m_position_time);
+
+ switch(m_state & CASSETTE_MASK_UISTATE) {
+ case CASSETTE_RECORD:
+ cassette_put_sample(m_cassette, 0, m_position, new_position - m_position, m_value);
+ break;
+
+ case CASSETTE_PLAY:
+ if ( m_cassette )
+ {
+ cassette_get_sample(m_cassette, 0, new_position, 0.0, &m_value);
+ /* See if reached end of tape */
+ double length = get_length();
+ if (new_position > length)
+ {
+ m_state = (cassette_state)(( m_state & ~CASSETTE_MASK_UISTATE ) | CASSETTE_STOPPED);
+ new_position = length;
+ }
+ }
+ break;
+ }
+ m_position = new_position;
+ }
+ m_position_time = cur_time;
+}
+
+void cassette_image_device::change_state(cassette_state state, cassette_state mask)
+{
+ cassette_state new_state;
+
+ new_state = m_state;
+ new_state = (cassette_state)(new_state & ~mask);
+ new_state = (cassette_state)(new_state | (state & mask));
+
+ if (new_state != m_state)
+ {
+ update();
+ m_state = new_state;
+ }
+}
+
+
+
+double cassette_image_device::input()
+{
+ INT32 sample;
+ double double_value;
+
+ update();
+ sample = m_value;
+ double_value = sample / ((double) 0x7FFFFFFF);
+
+ LOG(("cassette_input(): time_index=%g value=%g\n", m_position, double_value));
+
+ return double_value;
+}
+
+
+
+void cassette_image_device::output(double value)
+{
+ if (((m_state & CASSETTE_MASK_UISTATE) == CASSETTE_RECORD) && (m_value != value))
+ {
+ update();
+
+ value = MIN(value, 1.0);
+ value = MAX(value, -1.0);
+
+ m_value = (INT32) (value * 0x7FFFFFFF);
+ }
+}
+
+
+double cassette_image_device::get_position()
+{
+ double position = m_position;
+
+ if (is_motor_on())
+ position += device().machine().time().as_double() - m_position_time;
+ return position;
+}
+
+
+
+double cassette_image_device::get_length()
+{
+ struct CassetteInfo info;
+
+ cassette_get_info(m_cassette, &info);
+ return ((double) info.sample_count) / info.sample_frequency;
+}
+
+
+
+void cassette_image_device::seek(double time, int origin)
+{
+ double length;
+
+ update();
+
+ length = get_length();
+
+ switch(origin) {
+ case SEEK_SET:
+ break;
+
+ case SEEK_END:
+ time += length;
+ break;
+
+ case SEEK_CUR:
+ time += get_position();
+ break;
+ }
+
+ /* clip position into legal bounds */
+ if (time < 0)
+ time = 0;
+ else
+ if (time > length)
+ time = length;
+
+ m_position = time;
+}
+
+
+
+/*********************************************************************
+ cassette device init/load/unload/specify
+*********************************************************************/
+
+void cassette_image_device::device_start()
+{
+ /* set to default state */
+ m_cassette = NULL;
+ m_state = m_default_state;
+}
+
+bool cassette_image_device::call_create(int format_type, option_resolution *format_options)
+{
+ return call_load();
+}
+
+bool cassette_image_device::call_load()
+{
+ casserr_t err;
+ int cassette_flags;
+ const char *extension;
+ int is_writable;
+ device_image_interface *image = NULL;
+ interface(image);
+
+ if (has_been_created())
+ {
+ /* creating an image */
+ err = cassette_create((void *)image, &image_ioprocs, &wavfile_format, m_create_opts, CASSETTE_FLAG_READWRITE|CASSETTE_FLAG_SAVEONEXIT, &m_cassette);
+ if (err)
+ goto error;
+ }
+ else
+ {
+ /* opening an image */
+ do
+ {
+ is_writable = !is_readonly();
+ cassette_flags = is_writable ? (CASSETTE_FLAG_READWRITE|CASSETTE_FLAG_SAVEONEXIT) : CASSETTE_FLAG_READONLY;
+ extension = filetype();
+ err = cassette_open_choices((void *)image, &image_ioprocs, extension, m_formats, cassette_flags, &m_cassette);
+
+ /* this is kind of a hack */
+ if (err && is_writable)
+ make_readonly();
+ }
+ while(err && is_writable);
+
+ if (err)
+ goto error;
+ }
+
+ /* set to default state, but only change the UI state */
+ change_state(m_default_state, CASSETTE_MASK_UISTATE);
+
+ /* reset the position */
+ m_position = 0.0;
+ m_position_time = device().machine().time().as_double();
+
+ return IMAGE_INIT_PASS;
+
+error:
+ return IMAGE_INIT_FAIL;
+}
+
+
+
+void cassette_image_device::call_unload()
+{
+
+ /* if we are recording, write the value to the image */
+ if ((m_state & CASSETTE_MASK_UISTATE) == CASSETTE_RECORD)
+ update();
+
+ /* close out the cassette */
+ cassette_close(m_cassette);
+ m_cassette = NULL;
+
+ /* set to default state, but only change the UI state */
+ change_state(CASSETTE_STOPPED, CASSETTE_MASK_UISTATE);
+}
+
+
+
+/*
+ display a small tape icon, with the current position in the tape image
+*/
+void cassette_image_device::call_display()
+{
+ char buf[65];
+ float x, y;
+ int n;
+ double position, length;
+ cassette_state uistate;
+ device_t *dev;
+ static const UINT8 shapes[8] = { 0x2d, 0x5c, 0x7c, 0x2f, 0x2d, 0x20, 0x20, 0x20 };
+
+ /* abort if we should not be showing the image */
+ if (!exists())
+ return;
+ if (!is_motor_on())
+ return;
+
+ /* figure out where we are in the cassette */
+ position = get_position();
+ length = get_length();
+ uistate = (cassette_state)(get_state() & CASSETTE_MASK_UISTATE);
+
+ /* choose a location on the screen */
+ x = 0.2f;
+ y = 0.5f;
+
+ dev = device().machine().devicelist().first(CASSETTE );
+
+ while ( dev && strcmp( dev->tag(), device().tag() ) )
+ {
+ y += 1;
+ dev = dev->typenext();
+ }
+
+ y *= ui_get_line_height(device().machine()) + 2.0f * UI_BOX_TB_BORDER;
+ /* choose which frame of the animation we are at */
+ n = ((int) position / ANIMATION_FPS) % ANIMATION_FRAMES;
+ /* Since you can have anything in a BDF file, we will use crude ascii characters instead */
+ snprintf(buf, ARRAY_LENGTH(buf), "%c%c %c %02d:%02d (%04d) [%02d:%02d (%04d)]",
+#if 0
+ /* THE ANIMATION HASN'T WORKED SINCE 0.114 - LEFT HERE FOR REFERENCE */
+ /* NEVER SEEN THE PLAY / RECORD ICONS */
+ /* character pairs 2-3, 4-5, 6-7, 8-9 form little tape cassette images */
+ n * 2 + 2, /* cassette icon left */
+ n * 2 + 3, /* cassette icon right */
+ (uistate == CASSETTE_PLAY) ? 16 : 14, /* play or record icon */
+#else
+ shapes[n], /* cassette icon left */
+ shapes[n|4], /* cassette icon right */
+ (uistate == CASSETTE_PLAY) ? 0x50 : 0x52, /* play (P) or record (R) */
+#endif
+ ((int) position / 60),
+ ((int) position % 60),
+ (int) position,
+ ((int) length / 60),
+ ((int) length % 60),
+ (int) length);
+
+ /* draw the cassette */
+ ui_draw_text_box(&device().machine().render().ui_container(), buf, JUSTIFY_LEFT, x, y, UI_BACKGROUND_COLOR);
+}
diff --git a/trunk/src/emu/imagedev/cassette.h b/trunk/src/emu/imagedev/cassette.h
new file mode 100644
index 00000000000..c7476e169a0
--- /dev/null
+++ b/trunk/src/emu/imagedev/cassette.h
@@ -0,0 +1,132 @@
+/*********************************************************************
+
+ cassette.h
+
+ Interface to the cassette image abstraction code
+
+*********************************************************************/
+
+#ifndef CASSETTE_H
+#define CASSETTE_H
+
+#include "image.h"
+#include "formats/cassimg.h"
+
+
+enum _cassette_state
+{
+ /* this part of the state is controlled by the UI */
+ CASSETTE_STOPPED = 0,
+ CASSETTE_PLAY = 1,
+ CASSETTE_RECORD = 2,
+
+ /* this part of the state is controlled by drivers */
+ CASSETTE_MOTOR_ENABLED = 0,
+ CASSETTE_MOTOR_DISABLED = 4,
+ CASSETTE_SPEAKER_ENABLED = 0,
+ CASSETTE_SPEAKER_MUTED = 8,
+
+ /* masks */
+ CASSETTE_MASK_UISTATE = 3,
+ CASSETTE_MASK_MOTOR = 4,
+ CASSETTE_MASK_SPEAKER = 8,
+ CASSETTE_MASK_DRVSTATE = 12
+};
+
+typedef enum _cassette_state cassette_state;
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+// ======================> cassette_interface
+
+struct cassette_interface
+{
+ const struct CassetteFormat* const *m_formats;
+ const struct CassetteOptions *m_create_opts;
+ cassette_state m_default_state;
+ const char * m_interface;
+ device_image_display_info_func m_device_displayinfo;
+};
+
+// ======================> cassette_image_device
+
+class cassette_image_device : public device_t,
+ public cassette_interface,
+ public device_image_interface
+{
+public:
+ // construction/destruction
+ cassette_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ virtual ~cassette_image_device();
+
+ // image-level overrides
+ virtual bool call_load();
+ virtual bool call_create(int format_type, option_resolution *format_options);
+ virtual void call_unload();
+ virtual void call_display();
+ virtual void call_display_info() { if (m_device_displayinfo) m_device_displayinfo(*this); }
+ virtual bool call_softlist_load(char *swlist, char *swname, rom_entry *start_entry) { return load_software(swlist, swname, start_entry); }
+
+ virtual iodevice_t image_type() const { return IO_CASSETTE; }
+
+ virtual bool is_readable() const { return 1; }
+ virtual bool is_writeable() const { return 1; }
+ virtual bool is_creatable() const { return 1; }
+ virtual bool must_be_loaded() const { return 0; }
+ virtual bool is_reset_on_load() const { return 0; }
+ virtual const char *image_interface() const { return m_interface; }
+ virtual const char *file_extensions() const { return m_extension_list; }
+ virtual const option_guide *create_option_guide() const { return NULL; }
+
+ // specific implementation
+ cassette_state get_state() { return m_state; }
+ void set_state(cassette_state state) { change_state(m_state, (cassette_state)(~0)); }
+ void change_state(cassette_state state, cassette_state mask);
+
+ double input();
+ void output(double value);
+
+ cassette_image *get_image() { return m_cassette; }
+ double get_position();
+ double get_length();
+ void seek(double time, int origin);
+
+protected:
+ bool is_motor_on();
+ void update();
+
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+private:
+ cassette_image *m_cassette;
+ cassette_state m_state;
+ double m_position;
+ double m_position_time;
+ INT32 m_value;
+ char m_extension_list[256];
+};
+
+// device type definition
+extern const device_type CASSETTE;
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+#define CASSETTE_TAG "cassette"
+#define CASSETTE2_TAG "cassette2"
+
+#define MCFG_CASSETTE_ADD(_tag, _config) \
+ MCFG_DEVICE_ADD(_tag, CASSETTE, 0) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MCFG_CASSETTE_MODIFY(_tag, _config) \
+ MCFG_DEVICE_MODIFY(_tag) \
+ MCFG_DEVICE_CONFIG(_config)
+
+extern const cassette_interface default_cassette_interface;
+
+#endif /* CASSETTE_H */
diff --git a/trunk/src/emu/imagedev/chd_cd.c b/trunk/src/emu/imagedev/chd_cd.c
new file mode 100644
index 00000000000..dea7020cf1f
--- /dev/null
+++ b/trunk/src/emu/imagedev/chd_cd.c
@@ -0,0 +1,165 @@
+/*********************************************************************
+
+ Code to interface the image code with CHD-CD core.
+
+ Based on harddriv.c by Raphael Nabet 2003
+
+*********************************************************************/
+
+#include "emu.h"
+#include "cdrom.h"
+#include "chd_cd.h"
+
+
+static const char *const error_strings[] =
+{
+ "no error",
+ "no drive interface",
+ "out of memory",
+ "invalid file",
+ "invalid parameter",
+ "invalid data",
+ "file not found",
+ "requires parent",
+ "file not writeable",
+ "read error",
+ "write error",
+ "codec error",
+ "invalid parent",
+ "hunk out of range",
+ "decompression error",
+ "compression error",
+ "can't create file",
+ "can't verify file"
+ "operation not supported",
+ "can't find metadata",
+ "invalid metadata size",
+ "unsupported CHD version"
+};
+
+static const char *chd_get_error_string(int chderr)
+{
+ if ((chderr < 0 ) || (chderr >= ARRAY_LENGTH(error_strings)))
+ return NULL;
+ return error_strings[chderr];
+}
+
+
+static OPTION_GUIDE_START(cd_option_guide)
+ OPTION_INT('K', "hunksize", "Hunk Bytes")
+OPTION_GUIDE_END
+
+static const char cd_option_spec[] = "K512/1024/2048/[4096]";
+
+// device type definition
+const device_type CDROM = &device_creator<cdrom_image_device>;
+
+//-------------------------------------------------
+// cdrom_image_device - constructor
+//-------------------------------------------------
+
+cdrom_image_device::cdrom_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, CDROM, "Cdrom", tag, owner, clock),
+ device_image_interface(mconfig, *this)
+{
+
+}
+
+//-------------------------------------------------
+// cdrom_image_device - destructor
+//-------------------------------------------------
+
+cdrom_image_device::~cdrom_image_device()
+{
+}
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void cdrom_image_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const cdrom_interface *intf = reinterpret_cast<const cdrom_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<cdrom_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_interface, 0, sizeof(m_interface));
+ memset(&m_device_displayinfo, 0, sizeof(m_device_displayinfo));
+ }
+
+ image_device_format *format = global_alloc_clear(image_device_format);;
+ format->m_index = 0;
+ format->m_name = "chdcd";
+ format->m_description = "CD-ROM drive";
+ format->m_extensions = "chd,cue,toc,nrg,gdi";
+ format->m_optspec = cd_option_spec;
+ format->m_next = NULL;
+
+ m_formatlist = format;
+
+ // set brief and instance name
+ update_names();
+}
+
+const option_guide *cdrom_image_device::create_option_guide() const
+{
+ return cd_option_guide;
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void cdrom_image_device::device_start()
+{
+ m_cdrom_handle = NULL;
+}
+
+bool cdrom_image_device::call_load()
+{
+ chd_error err = (chd_error)0;
+ chd_file *chd = NULL;
+ astring tempstring;
+
+ if (software_entry() == NULL)
+ {
+ if (strstr(m_image_name,".chd")) {
+ err = chd_open_file( image_core_file(), CHD_OPEN_READ, NULL, &chd ); /* CDs are never writeable */
+ if ( err )
+ goto error;
+ }
+ } else {
+ chd = get_disk_handle(device().machine(), device().subtag(tempstring,"cdrom"));
+ }
+
+ /* open the CHD file */
+ if (chd) {
+ m_cdrom_handle = cdrom_open( chd );
+ } else {
+ m_cdrom_handle = cdrom_open( m_image_name );
+ }
+ if ( ! m_cdrom_handle )
+ goto error;
+
+ return IMAGE_INIT_PASS;
+
+error:
+ if ( chd )
+ chd_close( chd );
+ if ( err )
+ seterror( IMAGE_ERROR_UNSPECIFIED, chd_get_error_string( err ) );
+ return IMAGE_INIT_FAIL;
+}
+
+void cdrom_image_device::call_unload()
+{
+ assert(m_cdrom_handle);
+ cdrom_close(m_cdrom_handle);
+ m_cdrom_handle = NULL;
+}
diff --git a/trunk/src/emu/imagedev/chd_cd.h b/trunk/src/emu/imagedev/chd_cd.h
new file mode 100644
index 00000000000..fecb1f7e6b0
--- /dev/null
+++ b/trunk/src/emu/imagedev/chd_cd.h
@@ -0,0 +1,76 @@
+/*********************************************************************
+
+ chd_cd.h
+
+ Interface to the CHD CDROM code
+
+*********************************************************************/
+
+#ifndef CHD_CD_H
+#define CHD_CD_H
+
+#include "cdrom.h"
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+// ======================> cdrom_interface
+
+struct cdrom_interface
+{
+ const char * m_interface;
+ device_image_display_info_func m_device_displayinfo;
+};
+
+// ======================> cdrom_image_device
+
+class cdrom_image_device : public device_t,
+ public cdrom_interface,
+ public device_image_interface
+{
+public:
+ // construction/destruction
+ cdrom_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ virtual ~cdrom_image_device();
+
+ // image-level overrides
+ virtual bool call_load();
+ virtual void call_unload();
+ virtual void call_display_info() { if (m_device_displayinfo) m_device_displayinfo(*this); }
+ virtual bool call_softlist_load(char *swlist, char *swname, rom_entry *start_entry) { load_software_part_region(this, swlist, swname, start_entry ); return TRUE; }
+
+ virtual iodevice_t image_type() const { return IO_CDROM; }
+
+ virtual bool is_readable() const { return 1; }
+ virtual bool is_writeable() const { return 0; }
+ virtual bool is_creatable() const { return 0; }
+ virtual bool must_be_loaded() const { return 0; }
+ virtual bool is_reset_on_load() const { return 0; }
+ virtual const char *image_interface() const { return m_interface; }
+ virtual const char *file_extensions() const { return "chd"; }
+ virtual const option_guide *create_option_guide() const;
+
+ // specific implementation
+ cdrom_file *get_cdrom_file() { return m_cdrom_handle; }
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+
+ cdrom_file *m_cdrom_handle;
+ image_device_format m_format;
+};
+
+// device type definition
+extern const device_type CDROM;
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+
+#define MCFG_CDROM_ADD(_tag, _config) \
+ MCFG_DEVICE_ADD(_tag, CDROM, 0) \
+ MCFG_DEVICE_CONFIG(_config) \
+
+#endif /* CHD_CD_H */
diff --git a/trunk/src/emu/imagedev/flopdrv.c b/trunk/src/emu/imagedev/flopdrv.c
new file mode 100644
index 00000000000..87f220289fd
--- /dev/null
+++ b/trunk/src/emu/imagedev/flopdrv.c
@@ -0,0 +1,1071 @@
+/*
+ This code handles the floppy drives.
+ All FDD actions should be performed using these functions.
+
+ The functions are emulated and a disk image is used.
+
+ Real disk operation:
+ - set unit id
+
+ TODO:
+ - Override write protect if disk image has been opened in read mode
+*/
+
+#include "emu.h"
+#include "formats/imageutl.h"
+#include "flopdrv.h"
+
+#define VERBOSE 0
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define FLOPDRVTAG "flopdrv"
+#define LOG_FLOPPY 0
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _floppy_drive floppy_drive;
+struct _floppy_drive
+{
+ /* callbacks */
+ devcb_resolved_write_line out_idx_func;
+ devcb_resolved_read_line in_mon_func;
+ devcb_resolved_write_line out_tk00_func;
+ devcb_resolved_write_line out_wpt_func;
+ devcb_resolved_write_line out_rdy_func;
+ devcb_resolved_write_line out_dskchg_func;
+
+ /* state of input lines */
+ int drtn; /* direction */
+ int stp; /* step */
+ int wtg; /* write gate */
+ int mon; /* motor on */
+
+ /* state of output lines */
+ int idx; /* index pulse */
+ int tk00; /* track 00 */
+ int wpt; /* write protect */
+ int rdy; /* ready */
+ int dskchg; /* disk changed */
+
+ /* drive select logic */
+ int drive_id;
+ int active;
+
+ const floppy_interface *config;
+
+ /* flags */
+ int flags;
+ /* maximum track allowed */
+ int max_track;
+ /* num sides */
+ int num_sides;
+ /* current track - this may or may not relate to the present cylinder number
+ stored by the fdc */
+ int current_track;
+
+ /* index pulse timer */
+ emu_timer *index_timer;
+ /* index pulse callback */
+ void (*index_pulse_callback)(device_t *controller,device_t *image, int state);
+ /* rotation per minute => gives index pulse frequency */
+ float rpm;
+
+ void (*ready_state_change_callback)(device_t *controller,device_t *img, int state);
+
+ int id_index;
+
+ device_t *controller;
+
+ floppy_image_legacy *floppy;
+ int track;
+ void (*load_proc)(device_image_interface &image);
+ void (*unload_proc)(device_image_interface &image);
+ void *custom_data;
+ int floppy_drive_type;
+};
+
+
+typedef struct _floppy_error_map floppy_error_map;
+struct _floppy_error_map
+{
+ floperr_t ferr;
+ image_error_t ierr;
+ const char *message;
+};
+
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+static const floppy_error_map errmap[] =
+{
+ { FLOPPY_ERROR_SUCCESS, IMAGE_ERROR_SUCCESS },
+ { FLOPPY_ERROR_INTERNAL, IMAGE_ERROR_INTERNAL },
+ { FLOPPY_ERROR_UNSUPPORTED, IMAGE_ERROR_UNSUPPORTED },
+ { FLOPPY_ERROR_OUTOFMEMORY, IMAGE_ERROR_OUTOFMEMORY },
+ { FLOPPY_ERROR_INVALIDIMAGE, IMAGE_ERROR_INVALIDIMAGE }
+};
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+DECLARE_LEGACY_IMAGE_DEVICE(FLOPPY_APPLE, apple525);
+DECLARE_LEGACY_IMAGE_DEVICE(FLOPPY_SONY, sonydriv);
+
+INLINE floppy_drive *get_safe_token(device_t *device)
+{
+ assert( device != NULL );
+ assert( device->type() == LEGACY_FLOPPY || device->type() == FLOPPY_APPLE || device->type() == FLOPPY_SONY);
+ return (floppy_drive *) downcast<legacy_device_base *>(device)->token();
+}
+
+floppy_image_legacy *flopimg_get_image(device_t *image)
+{
+ return get_safe_token(image)->floppy;
+}
+
+void *flopimg_get_custom_data(device_t *image)
+{
+ floppy_drive *flopimg = get_safe_token( image );
+ return flopimg->custom_data;
+}
+
+void flopimg_alloc_custom_data(device_t *image,void *custom)
+{
+ floppy_drive *flopimg = get_safe_token( image );
+ flopimg->custom_data = custom;
+}
+
+static int flopimg_get_sectors_per_track(device_t *image, int side)
+{
+ floperr_t err;
+ int sector_count;
+ floppy_drive *flopimg = get_safe_token( image );
+
+ if (!flopimg || !flopimg->floppy)
+ return 0;
+
+ err = floppy_get_sector_count(flopimg->floppy, side, flopimg->track, &sector_count);
+ if (err)
+ return 0;
+ return sector_count;
+}
+
+static void flopimg_get_id_callback(device_t *image, chrn_id *id, int id_index, int side)
+{
+ floppy_drive *flopimg;
+ int cylinder, sector, N;
+ unsigned long flags;
+ UINT32 sector_length;
+
+ flopimg = get_safe_token( image );
+ if (!flopimg || !flopimg->floppy)
+ return;
+
+ floppy_get_indexed_sector_info(flopimg->floppy, side, flopimg->track, id_index, &cylinder, &side, &sector, &sector_length, &flags);
+
+ N = compute_log2(sector_length);
+
+ id->C = cylinder;
+ id->H = side;
+ id->R = sector;
+ id->data_id = id_index;
+ id->flags = flags;
+ id->N = ((N >= 7) && (N <= 10)) ? N - 7 : 0;
+}
+
+static void log_readwrite(const char *name, int head, int track, int sector, const char *buf, int length)
+{
+ char membuf[1024];
+ int i;
+ for (i = 0; i < length; i++)
+ sprintf(membuf + i*2, "%02x", (int) (UINT8) buf[i]);
+ logerror("%s: head=%i track=%i sector=%i buffer='%s'\n", name, head, track, sector, membuf);
+}
+
+static void floppy_drive_set_geometry_absolute(device_t *img, int tracks, int sides)
+{
+ floppy_drive *pDrive = get_safe_token( img );
+ pDrive->max_track = tracks;
+ pDrive->num_sides = sides;
+}
+
+void floppy_drive_set_geometry(device_t *img, floppy_type_t type)
+{
+ floppy_drive_set_geometry_absolute(img, type.max_track_number, type.head_number);
+}
+
+static TIMER_CALLBACK(floppy_drive_index_callback);
+
+/* this is called on device init */
+static void floppy_drive_init(device_t *img)
+{
+ floppy_drive *pDrive = get_safe_token( img );
+
+ /* initialise flags */
+ pDrive->flags = 0;
+ pDrive->index_pulse_callback = NULL;
+ pDrive->ready_state_change_callback = NULL;
+ pDrive->index_timer = img->machine().scheduler().timer_alloc(FUNC(floppy_drive_index_callback), (void *) img);
+ pDrive->idx = 0;
+
+ floppy_drive_set_geometry(img, ((floppy_interface*)img->static_config())->floppy_type);
+
+ /* initialise id index - not so important */
+ pDrive->id_index = 0;
+ /* initialise track */
+ pDrive->current_track = 0;
+
+ /* default RPM */
+ pDrive->rpm = 300;
+
+ pDrive->controller = NULL;
+
+ pDrive->custom_data = NULL;
+
+ pDrive->floppy_drive_type = FLOPPY_TYPE_REGULAR;
+}
+
+/* index pulses at rpm/60 Hz, and stays high 1/20th of time */
+static void floppy_drive_index_func(device_t *img)
+{
+ floppy_drive *drive = get_safe_token( img );
+
+ double ms = 1000.0 / (drive->rpm / 60.0);
+
+ if (drive->idx)
+ {
+ drive->idx = 0;
+ drive->index_timer->adjust(attotime::from_double(ms*19/20/1000.0));
+ }
+ else
+ {
+ drive->idx = 1;
+ drive->index_timer->adjust(attotime::from_double(ms/20/1000.0));
+ }
+
+ drive->out_idx_func(drive->idx);
+
+ if (drive->index_pulse_callback)
+ drive->index_pulse_callback(drive->controller, img, drive->idx);
+}
+
+static TIMER_CALLBACK(floppy_drive_index_callback)
+{
+ device_t *image = (device_t *) ptr;
+ floppy_drive_index_func(image);
+}
+
+/*************************************************************************/
+/* IO_FLOPPY device functions */
+
+/* set flag state */
+void floppy_drive_set_flag_state(device_t *img, int flag, int state)
+{
+ floppy_drive *drv = get_safe_token( img );
+ int prev_state;
+ int new_state;
+
+ /* get old state */
+ prev_state = drv->flags & flag;
+
+ /* set new state */
+ drv->flags &= ~flag;
+ if (state)
+ drv->flags |= flag;
+
+ /* get new state */
+ new_state = drv->flags & flag;
+
+ /* changed state? */
+ if (prev_state ^ new_state)
+ {
+ if (flag & FLOPPY_DRIVE_READY)
+ {
+ /* trigger state change callback */
+ drv->out_rdy_func(new_state ? ASSERT_LINE : CLEAR_LINE);
+
+ if (drv->ready_state_change_callback)
+ drv->ready_state_change_callback(drv->controller, img, new_state);
+ }
+ }
+}
+
+/* for pc, drive is always ready, for amstrad,pcw,spectrum it is only ready under
+a fixed set of circumstances */
+/* use this to set ready state of drive */
+void floppy_drive_set_ready_state(device_t *img, int state, int flag)
+{
+ floppy_drive *drive = get_safe_token(img);
+ device_image_interface *image = dynamic_cast<device_image_interface *>(img);
+ if (flag)
+ {
+ /* set ready only if drive is present, disk is in the drive,
+ and disk motor is on - for Amstrad, Spectrum and PCW*/
+
+ /* drive present? */
+ /* disk inserted? */
+ if (image->exists())
+ {
+ if (drive->mon == CLEAR_LINE)
+ {
+ /* set state */
+ floppy_drive_set_flag_state(img, FLOPPY_DRIVE_READY, state);
+ return;
+ }
+ }
+ floppy_drive_set_flag_state(img, FLOPPY_DRIVE_READY, 0);
+ }
+ else
+ {
+ /* force ready state - for PC driver */
+ floppy_drive_set_flag_state(img, FLOPPY_DRIVE_READY, state);
+ }
+}
+
+/* get flag state */
+int floppy_drive_get_flag_state(device_t *img, int flag)
+{
+ floppy_drive *drv = get_safe_token( img );
+ int drive_flags;
+ int flags;
+
+ flags = 0;
+
+ drive_flags = drv->flags;
+
+ /* these flags are independent of a real drive/disk image */
+ flags |= drive_flags & (FLOPPY_DRIVE_READY | FLOPPY_DRIVE_INDEX);
+
+ flags &= flag;
+
+ return flags;
+}
+
+
+void floppy_drive_seek(device_t *img, signed int signed_tracks)
+{
+ device_image_interface *image = dynamic_cast<device_image_interface *>(img);
+ floppy_drive *pDrive;
+
+ pDrive = get_safe_token( img );
+
+ LOG(("seek from: %d delta: %d\n",pDrive->current_track, signed_tracks));
+
+ /* update position */
+ pDrive->current_track+=signed_tracks;
+
+ if (pDrive->current_track<0)
+ {
+ pDrive->current_track = 0;
+ }
+ else
+ if (pDrive->current_track>=pDrive->max_track)
+ {
+ pDrive->current_track = pDrive->max_track-1;
+ }
+
+ /* set track 0 flag */
+ pDrive->tk00 = (pDrive->current_track == 0) ? CLEAR_LINE : ASSERT_LINE;
+ pDrive->out_tk00_func(pDrive->tk00);
+
+ /* clear disk changed flag */
+ pDrive->dskchg = ASSERT_LINE;
+ //flopimg->out_dskchg_func(flopimg->dskchg);
+
+ /* inform disk image of step operation so it can cache information */
+ if (image->exists())
+ pDrive->track = pDrive->current_track;
+
+ pDrive->id_index = 0;
+}
+
+
+/* this is not accurate. But it will do for now */
+int floppy_drive_get_next_id(device_t *img, int side, chrn_id *id)
+{
+ floppy_drive *pDrive;
+ int spt;
+
+ pDrive = get_safe_token( img );
+
+ /* get sectors per track */
+ spt = flopimg_get_sectors_per_track(img, side);
+
+ /* set index */
+ if ((pDrive->id_index==(spt-1)) || (spt==0))
+ {
+ floppy_drive_set_flag_state(img, FLOPPY_DRIVE_INDEX, 1);
+ }
+ else
+ {
+ floppy_drive_set_flag_state(img, FLOPPY_DRIVE_INDEX, 0);
+ }
+
+ /* get id */
+ if (spt!=0)
+ {
+ flopimg_get_id_callback(img, id, pDrive->id_index, side);
+ }
+
+ pDrive->id_index++;
+ if (spt!=0)
+ pDrive->id_index %= spt;
+ else
+ pDrive->id_index = 0;
+
+ return (spt == 0) ? 0 : 1;
+}
+
+void floppy_drive_read_track_data_info_buffer(device_t *img, int side, void *ptr, int *length )
+{
+ floppy_drive *flopimg;
+ device_image_interface *image = dynamic_cast<device_image_interface *>(img);
+
+ if (image->exists())
+ {
+ flopimg = get_safe_token( img );
+ if (!flopimg || !flopimg->floppy)
+ return;
+
+ floppy_read_track_data(flopimg->floppy, side, flopimg->track, ptr, *length);
+ }
+}
+
+void floppy_drive_write_track_data_info_buffer(device_t *img, int side, const void *ptr, int *length )
+{
+ floppy_drive *flopimg;
+ device_image_interface *image = dynamic_cast<device_image_interface *>(img);
+
+ if (image->exists())
+ {
+ flopimg = get_safe_token( img );
+ if (!flopimg || !flopimg->floppy)
+ return;
+
+ floppy_write_track_data(flopimg->floppy, side, flopimg->track, ptr, *length);
+ }
+}
+
+void floppy_drive_format_sector(device_t *img, int side, int sector_index,int c,int h, int r, int n, int filler)
+{
+ device_image_interface *image = dynamic_cast<device_image_interface *>(img);
+
+ if (image->exists())
+ {
+/* if (drv->interface_.format_sector)
+ drv->interface_.format_sector(img, side, sector_index,c, h, r, n, filler);*/
+ }
+}
+
+void floppy_drive_read_sector_data(device_t *img, int side, int index1, void *ptr, int length)
+{
+ floppy_drive *flopimg;
+ device_image_interface *image = dynamic_cast<device_image_interface *>(img);
+
+ if (image->exists())
+ {
+ flopimg = get_safe_token( img );
+ if (!flopimg || !flopimg->floppy)
+ return;
+
+ floppy_read_indexed_sector(flopimg->floppy, side, flopimg->track, index1, 0, ptr, length);
+
+ if (LOG_FLOPPY)
+ log_readwrite("sector_read", side, flopimg->track, index1, (const char *)ptr, length);
+
+ }
+}
+
+void floppy_drive_write_sector_data(device_t *img, int side, int index1, const void *ptr,int length, int ddam)
+{
+ floppy_drive *flopimg;
+ device_image_interface *image = dynamic_cast<device_image_interface *>(img);
+
+ if (image->exists())
+ {
+ flopimg = get_safe_token( img );
+ if (!flopimg || !flopimg->floppy)
+ return;
+
+ if (LOG_FLOPPY)
+ log_readwrite("sector_write", side, flopimg->track, index1, (const char *)ptr, length);
+
+ floppy_write_indexed_sector(flopimg->floppy, side, flopimg->track, index1, 0, ptr, length, ddam);
+ }
+}
+
+void floppy_install_load_proc(device_t *image, void (*proc)(device_image_interface &image))
+{
+ floppy_drive *flopimg = get_safe_token( image );
+ flopimg->load_proc = proc;
+}
+
+void floppy_install_unload_proc(device_t *image, void (*proc)(device_image_interface &image))
+{
+ floppy_drive *flopimg = get_safe_token( image );
+ flopimg->unload_proc = proc;
+}
+
+/* set the callback for the index pulse */
+void floppy_drive_set_index_pulse_callback(device_t *img, void (*callback)(device_t *controller,device_t *image, int state))
+{
+ floppy_drive *pDrive = get_safe_token( img );
+ pDrive->index_pulse_callback = callback;
+}
+
+
+void floppy_drive_set_ready_state_change_callback(device_t *img, void (*callback)(device_t *controller,device_t *img, int state))
+{
+ floppy_drive *pDrive = get_safe_token( img );
+ pDrive->ready_state_change_callback = callback;
+}
+
+int floppy_drive_get_current_track(device_t *img)
+{
+ floppy_drive *drv = get_safe_token( img );
+ return drv->current_track;
+}
+
+UINT64 floppy_drive_get_current_track_size(device_t *img, int head)
+{
+ floppy_drive *drv = get_safe_token( img );
+ int size = 0;
+ device_image_interface *image = dynamic_cast<device_image_interface *>(img);
+
+ if (image->exists())
+ {
+ size = floppy_get_track_size(drv->floppy, head, drv->current_track);
+ }
+
+ return size;
+}
+
+void floppy_drive_set_rpm(device_t *img, float rpm)
+{
+ floppy_drive *drv = get_safe_token( img );
+ drv->rpm = rpm;
+}
+
+void floppy_drive_set_controller(device_t *img, device_t *controller)
+{
+ floppy_drive *drv = get_safe_token( img );
+ drv->controller = controller;
+}
+
+/* ----------------------------------------------------------------------- */
+DEVICE_START( floppy )
+{
+ floppy_drive *floppy = get_safe_token( device );
+ floppy->config = (const floppy_interface*)device->static_config();
+ floppy_drive_init(device);
+
+ floppy->drive_id = floppy_get_drive(device);
+ floppy->active = FALSE;
+
+ /* resolve callbacks */
+ floppy->out_idx_func.resolve(floppy->config->out_idx_func, *device);
+ floppy->in_mon_func.resolve(floppy->config->in_mon_func, *device);
+ floppy->out_tk00_func.resolve(floppy->config->out_tk00_func, *device);
+ floppy->out_wpt_func.resolve(floppy->config->out_wpt_func, *device);
+ floppy->out_rdy_func.resolve(floppy->config->out_rdy_func, *device);
+// floppy->out_dskchg_func.resolve(floppy->config->out_dskchg_func, *device);
+
+ /* by default we are not write-protected */
+ floppy->wpt = ASSERT_LINE;
+ floppy->out_wpt_func(floppy->wpt);
+
+ /* not at track 0 */
+ floppy->tk00 = ASSERT_LINE;
+ floppy->out_tk00_func(floppy->tk00);
+
+ /* motor off */
+ floppy->mon = ASSERT_LINE;
+
+ /* disk changed */
+ floppy->dskchg = CLEAR_LINE;
+// floppy->out_dskchg_func(floppy->dskchg);
+}
+
+static int internal_floppy_device_load(device_image_interface *image, int create_format, option_resolution *create_args)
+{
+ floperr_t err;
+ floppy_drive *flopimg;
+ const struct FloppyFormat *floppy_options;
+ int floppy_flags, i;
+ const char *extension;
+
+ /* look up instance data */
+ flopimg = get_safe_token( &image->device() );
+
+ /* figure out the floppy options */
+ floppy_options = ((floppy_interface*)image->device().static_config())->formats;
+
+ if (image->has_been_created())
+ {
+ /* creating an image */
+ assert(create_format >= 0);
+ err = floppy_create((void *) image, &image_ioprocs, &floppy_options[create_format], create_args, &flopimg->floppy);
+ if (err)
+ goto error;
+ }
+ else
+ {
+ /* opening an image */
+ floppy_flags = !image->is_readonly() ? FLOPPY_FLAGS_READWRITE : FLOPPY_FLAGS_READONLY;
+ extension = image->filetype();
+ err = floppy_open_choices((void *) image, &image_ioprocs, extension, floppy_options, floppy_flags, &flopimg->floppy);
+ if (err)
+ goto error;
+ }
+ if (floppy_callbacks(flopimg->floppy)->get_heads_per_disk && floppy_callbacks(flopimg->floppy)->get_tracks_per_disk)
+ {
+ floppy_drive_set_geometry_absolute(&image->device(),
+ floppy_get_tracks_per_disk(flopimg->floppy),
+ floppy_get_heads_per_disk(flopimg->floppy));
+ }
+ /* disk changed */
+ flopimg->dskchg = CLEAR_LINE;
+
+ return IMAGE_INIT_PASS;
+
+error:
+ for (i = 0; i < ARRAY_LENGTH(errmap); i++)
+ {
+ if (err == errmap[i].ferr)
+ image->seterror(errmap[i].ierr, errmap[i].message);
+ }
+ return IMAGE_INIT_FAIL;
+}
+
+static TIMER_CALLBACK( set_wpt )
+{
+ floppy_drive *flopimg = (floppy_drive *)ptr;
+
+ flopimg->wpt = param;
+ flopimg->out_wpt_func(param);
+}
+
+DEVICE_IMAGE_LOAD( floppy )
+{
+ floppy_drive *flopimg;
+ int retVal = internal_floppy_device_load(&image, -1, NULL);
+ flopimg = get_safe_token( &image.device() );
+ if (retVal==IMAGE_INIT_PASS) {
+ /* if we have one of our hacky unload procs, call it */
+ if (flopimg->load_proc)
+ flopimg->load_proc(image);
+ }
+
+ /* push disk halfway into drive */
+ flopimg->wpt = CLEAR_LINE;
+ flopimg->out_wpt_func(flopimg->wpt);
+
+ /* set timer for disk load */
+ int next_wpt;
+
+ if (!image.is_readonly())
+ next_wpt = ASSERT_LINE;
+ else
+ next_wpt = CLEAR_LINE;
+
+ image.device().machine().scheduler().timer_set(attotime::from_msec(250), FUNC(set_wpt), next_wpt, flopimg);
+
+ return retVal;
+}
+
+DEVICE_IMAGE_CREATE( floppy )
+{
+ return internal_floppy_device_load(&image, create_format, create_args);
+}
+
+DEVICE_IMAGE_UNLOAD( floppy )
+{
+ floppy_drive *flopimg = get_safe_token( &image.device() );
+ if (flopimg->unload_proc)
+ flopimg->unload_proc(image);
+
+ floppy_close(flopimg->floppy);
+ flopimg->floppy = NULL;
+
+ /* disk changed */
+ flopimg->dskchg = CLEAR_LINE;
+ //flopimg->out_dskchg_func(flopimg->dskchg);
+
+ /* pull disk halfway out of drive */
+ flopimg->wpt = CLEAR_LINE;
+ flopimg->out_wpt_func(flopimg->wpt);
+
+ /* set timer for disk eject */
+ image.device().machine().scheduler().timer_set(attotime::from_msec(250), FUNC(set_wpt), ASSERT_LINE, flopimg);
+}
+
+device_t *floppy_get_device(running_machine &machine,int drive)
+{
+ switch(drive) {
+ case 0 : return machine.device(FLOPPY_0);
+ case 1 : return machine.device(FLOPPY_1);
+ case 2 : return machine.device(FLOPPY_2);
+ case 3 : return machine.device(FLOPPY_3);
+ }
+ return NULL;
+}
+
+int floppy_get_drive_type(device_t *image)
+{
+ floppy_drive *flopimg = get_safe_token( image );
+ return flopimg->floppy_drive_type;
+}
+
+void floppy_set_type(device_t *image,int ftype)
+{
+ floppy_drive *flopimg = get_safe_token( image );
+ flopimg->floppy_drive_type = ftype;
+}
+
+device_t *floppy_get_device_by_type(running_machine &machine,int ftype,int drive)
+{
+ int i;
+ int cnt = 0;
+ for (i=0;i<4;i++) {
+ device_t *disk = floppy_get_device(machine,i);
+ if (floppy_get_drive_type(disk)==ftype) {
+ if (cnt==drive) {
+ return disk;
+ }
+ cnt++;
+ }
+ }
+ return NULL;
+}
+
+int floppy_get_drive(device_t *image)
+{
+ int drive =0;
+ if (strcmp(image->tag(), FLOPPY_0) == 0) drive = 0;
+ if (strcmp(image->tag(), FLOPPY_1) == 0) drive = 1;
+ if (strcmp(image->tag(), FLOPPY_2) == 0) drive = 2;
+ if (strcmp(image->tag(), FLOPPY_3) == 0) drive = 3;
+ return drive;
+}
+
+int floppy_get_drive_by_type(device_t *image,int ftype)
+{
+ int i,drive =0;
+ for (i=0;i<4;i++) {
+ device_t *disk = floppy_get_device(image->machine(),i);
+ if (floppy_get_drive_type(disk)==ftype) {
+ if (image==disk) {
+ return drive;
+ }
+ drive++;
+ }
+ }
+ return drive;
+}
+
+int floppy_get_count(running_machine &machine)
+{
+ int cnt = 0;
+ if (machine.device(FLOPPY_0)) cnt++;
+ if (machine.device(FLOPPY_1)) cnt++;
+ if (machine.device(FLOPPY_2)) cnt++;
+ if (machine.device(FLOPPY_3)) cnt++;
+ return cnt;
+}
+
+
+/* drive select 0 */
+WRITE_LINE_DEVICE_HANDLER( floppy_ds0_w )
+{
+ floppy_drive *drive = get_safe_token(device);
+
+ if (state == CLEAR_LINE)
+ drive->active = (drive->drive_id == 0);
+}
+
+/* drive select 1 */
+WRITE_LINE_DEVICE_HANDLER( floppy_ds1_w )
+{
+ floppy_drive *drive = get_safe_token(device);
+
+ if (state == CLEAR_LINE)
+ drive->active = (drive->drive_id == 1);
+}
+
+/* drive select 2 */
+WRITE_LINE_DEVICE_HANDLER( floppy_ds2_w )
+{
+ floppy_drive *drive = get_safe_token(device);
+
+ if (state == CLEAR_LINE)
+ drive->active = (drive->drive_id == 2);
+}
+
+/* drive select 3 */
+WRITE_LINE_DEVICE_HANDLER( floppy_ds3_w )
+{
+ floppy_drive *drive = get_safe_token(device);
+
+ if (state == CLEAR_LINE)
+ drive->active = (drive->drive_id == 3);
+}
+
+/* shortcut to write all four ds lines */
+WRITE8_DEVICE_HANDLER( floppy_ds_w )
+{
+ floppy_ds0_w(device, BIT(data, 0));
+ floppy_ds1_w(device, BIT(data, 1));
+ floppy_ds2_w(device, BIT(data, 2));
+ floppy_ds3_w(device, BIT(data, 3));
+}
+
+/* motor on, active low */
+WRITE_LINE_DEVICE_HANDLER( floppy_mon_w )
+{
+ floppy_drive *drive = get_safe_token(device);
+ device_image_interface *image = dynamic_cast<device_image_interface *>(device);
+ /* force off if there is no attached image */
+ if (!image->exists())
+ state = ASSERT_LINE;
+
+ /* off -> on */
+ if (drive->mon && state == CLEAR_LINE)
+ {
+ drive->idx = 0;
+ floppy_drive_index_func(device);
+ }
+
+ /* on -> off */
+ else if (drive->mon == CLEAR_LINE && state)
+ drive->index_timer->adjust(attotime::zero);
+
+ drive->mon = state;
+}
+
+/* direction */
+WRITE_LINE_DEVICE_HANDLER( floppy_drtn_w )
+{
+ floppy_drive *drive = get_safe_token(device);
+ drive->drtn = state;
+}
+
+/* write data */
+WRITE_LINE_DEVICE_HANDLER( floppy_wtd_w )
+{
+
+}
+
+/* step */
+WRITE_LINE_DEVICE_HANDLER( floppy_stp_w )
+{
+ floppy_drive *drive = get_safe_token(device);
+
+ /* move head one track when going from high to low and write gate is high */
+ if (drive->active && drive->stp && state == CLEAR_LINE && drive->wtg)
+ {
+ /* move head according to the direction line */
+ if (drive->drtn)
+ {
+ /* move head outward */
+ if (drive->current_track > 0)
+ drive->current_track--;
+
+ /* are we at track 0 now? */
+ drive->tk00 = (drive->current_track == 0) ? CLEAR_LINE : ASSERT_LINE;
+ }
+ else
+ {
+ /* move head inward */
+ if (drive->current_track < drive->max_track)
+ drive->current_track++;
+
+ /* we can't be at track 0 here, so reset the line */
+ drive->tk00 = ASSERT_LINE;
+ }
+
+ /* update track 0 line with new status */
+ drive->out_tk00_func(drive->tk00);
+ }
+
+ drive->stp = state;
+}
+
+/* write gate */
+WRITE_LINE_DEVICE_HANDLER( floppy_wtg_w )
+{
+ floppy_drive *drive = get_safe_token(device);
+ drive->wtg = state;
+}
+
+/* write protect signal, active low */
+READ_LINE_DEVICE_HANDLER( floppy_wpt_r )
+{
+ floppy_drive *drive = get_safe_token(device);
+ return drive->wpt;
+}
+
+/* track 0 detect */
+READ_LINE_DEVICE_HANDLER( floppy_tk00_r )
+{
+ floppy_drive *drive = get_safe_token(device);
+ return drive->tk00;
+}
+
+/* disk changed */
+READ_LINE_DEVICE_HANDLER( floppy_dskchg_r )
+{
+ floppy_drive *drive = get_safe_token(device);
+ return drive->dskchg;
+}
+
+/* 2-sided disk */
+READ_LINE_DEVICE_HANDLER( floppy_twosid_r )
+{
+ floppy_drive *drive = get_safe_token(device);
+
+ if (drive->floppy == NULL)
+ return ASSERT_LINE;
+ else
+ return !floppy_get_heads_per_disk(drive->floppy);
+}
+
+READ_LINE_DEVICE_HANDLER( floppy_index_r )
+{
+ floppy_drive *drive = get_safe_token(device);
+ return drive->idx;
+}
+
+READ_LINE_DEVICE_HANDLER( floppy_ready_r )
+{
+ return !(floppy_drive_get_flag_state(device, FLOPPY_DRIVE_READY) == FLOPPY_DRIVE_READY);
+}
+
+/*-------------------------------------------------
+ DEVICE_IMAGE_SOFTLIST_LOAD(floppy)
+-------------------------------------------------*/
+static DEVICE_IMAGE_SOFTLIST_LOAD(floppy)
+{
+ return image.load_software(swlist, swname, start_entry);
+}
+
+/*************************************
+ *
+ * Device specification function
+ *
+ *************************************/
+/*-------------------------------------------------
+ safe_strcpy - hack
+-------------------------------------------------*/
+
+static void safe_strcpy(char *dst, const char *src)
+{
+ strcpy(dst, src ? src : "");
+}
+
+DEVICE_GET_INFO(floppy)
+{
+ switch( state )
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(floppy_drive); break;
+ case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break;
+ case DEVINFO_INT_IMAGE_TYPE: info->i = IO_FLOPPY; break;
+ case DEVINFO_INT_IMAGE_READABLE: info->i = 1; break;
+ case DEVINFO_INT_IMAGE_WRITEABLE: info->i = 1; break;
+ case DEVINFO_INT_IMAGE_CREATABLE:
+ {
+ int cnt = 0;
+ if ( device && device->static_config() )
+ {
+ const struct FloppyFormat *floppy_options = ((floppy_interface*)device->static_config())->formats;
+ int i;
+ for ( i = 0; floppy_options[i].construct; i++ ) {
+ if(floppy_options[i].param_guidelines) cnt++;
+ }
+ }
+ info->i = (cnt>0) ? 1 : 0;
+ }
+ break;
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(floppy); break;
+ case DEVINFO_FCT_IMAGE_CREATE: info->f = (genf *) DEVICE_IMAGE_CREATE_NAME(floppy); break;
+ case DEVINFO_FCT_IMAGE_LOAD: info->f = (genf *) DEVICE_IMAGE_LOAD_NAME(floppy); break;
+ case DEVINFO_FCT_IMAGE_UNLOAD: info->f = (genf *) DEVICE_IMAGE_UNLOAD_NAME(floppy); break;
+ case DEVINFO_FCT_IMAGE_SOFTLIST_LOAD: info->f = (genf *) DEVICE_IMAGE_SOFTLIST_LOAD_NAME(floppy); break;
+ case DEVINFO_FCT_IMAGE_DISPLAY_INFO:
+ if (device->type() == FLOPPY_APPLE) {
+ info->f = NULL;
+ } else {
+ if ( device && downcast<const legacy_image_device_base *>(device)->static_config() && ((floppy_interface*)(device)->static_config())->device_displayinfo) {
+ info->f = (genf *) ((floppy_interface*)(device)->static_config())->device_displayinfo;
+ } else {
+ info->f = NULL;
+ }
+ }
+ break;
+
+ case DEVINFO_PTR_IMAGE_CREATE_OPTGUIDE: info->p = (void *)floppy_option_guide; break;
+ case DEVINFO_INT_IMAGE_CREATE_OPTCOUNT:
+ {
+ const struct FloppyFormat *floppy_options = ((floppy_interface*)device->static_config())->formats;
+ int count;
+ for (count = 0; floppy_options[count].construct; count++)
+ ;
+ info->i = count;
+ break;
+ }
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Floppy Disk"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Floppy Disk"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_IMAGE_FILE_EXTENSIONS:
+ if ( device && device->static_config() )
+ {
+ const struct FloppyFormat *floppy_options = ((floppy_interface*)device->static_config())->formats;
+ int i;
+ /* set up a temporary string */
+ info->s[0] = '\0';
+ for ( i = 0; floppy_options[i].construct; i++ )
+ image_specify_extension( info->s, 256, floppy_options[i].extensions );
+ }
+ break;
+ case DEVINFO_STR_IMAGE_INTERFACE:
+ if ( device && device->static_config() && ((floppy_interface *)device->static_config())->interface)
+ {
+ strcpy(info->s, ((floppy_interface *)device->static_config())->interface );
+ }
+ break;
+ default:
+ {
+ if ( device && device->static_config() )
+ {
+ const struct FloppyFormat *floppy_options = ((floppy_interface*)device->static_config())->formats;
+ if ((state >= DEVINFO_PTR_IMAGE_CREATE_OPTSPEC) && (state < DEVINFO_PTR_IMAGE_CREATE_OPTSPEC + DEVINFO_IMAGE_CREATE_OPTMAX)) {
+ info->p = (void *) floppy_options[state - DEVINFO_PTR_IMAGE_CREATE_OPTSPEC].param_guidelines;
+ } else if ((state >= DEVINFO_STR_IMAGE_CREATE_OPTNAME) && (state < DEVINFO_STR_IMAGE_CREATE_OPTNAME + DEVINFO_IMAGE_CREATE_OPTMAX)) {
+ safe_strcpy(info->s,floppy_options[state - DEVINFO_STR_IMAGE_CREATE_OPTNAME].name);
+ }
+ else if ((state >= DEVINFO_STR_IMAGE_CREATE_OPTDESC) && (state < DEVINFO_STR_IMAGE_CREATE_OPTDESC + DEVINFO_IMAGE_CREATE_OPTMAX)) {
+ safe_strcpy(info->s,floppy_options[state - DEVINFO_STR_IMAGE_CREATE_OPTDESC].description);
+ }
+ else if ((state >= DEVINFO_STR_IMAGE_CREATE_OPTEXTS) && (state < DEVINFO_STR_IMAGE_CREATE_OPTEXTS + DEVINFO_IMAGE_CREATE_OPTMAX)) {
+ safe_strcpy(info->s,floppy_options[state - DEVINFO_STR_IMAGE_CREATE_OPTEXTS].extensions);
+ }
+ }
+ }
+
+ break;
+ }
+}
+
+DEFINE_LEGACY_IMAGE_DEVICE(LEGACY_FLOPPY, floppy);
diff --git a/trunk/src/emu/imagedev/flopdrv.h b/trunk/src/emu/imagedev/flopdrv.h
new file mode 100644
index 00000000000..0e326a207df
--- /dev/null
+++ b/trunk/src/emu/imagedev/flopdrv.h
@@ -0,0 +1,249 @@
+/* flopdrv provides simple emulation of a disc drive */
+/* the 8271, upd765 and wd179x use this */
+
+#ifndef __FLOPDRV_H__
+#define __FLOPDRV_H__
+
+#include "devcb.h"
+#include "image.h"
+#include "formats/flopimg.h"
+
+#define FLOPPY_TYPE_REGULAR 0
+#define FLOPPY_TYPE_APPLE 1
+#define FLOPPY_TYPE_SONY 2
+
+#define FLOPPY_DRIVE_2_8_INCH 1
+#define FLOPPY_DRIVE_3_INCH 2
+#define FLOPPY_DRIVE_3_5_INCH 3
+#define FLOPPY_DRIVE_5_25_INCH 4
+#define FLOPPY_DRIVE_8_INCH 5
+
+// Maximum supported density
+#define FLOPPY_DRIVE_SD 1
+#define FLOPPY_DRIVE_DD 2
+#define FLOPPY_DRIVE_QD 3
+#define FLOPPY_DRIVE_HD 4
+#define FLOPPY_DRIVE_ED 5
+
+#define FLOPPY_STANDARD_3_SSDD { FLOPPY_DRIVE_3_INCH, 1, 42, FLOPPY_DRIVE_DD }
+#define FLOPPY_STANDARD_3_DSDD { FLOPPY_DRIVE_3_INCH, 2, 42, FLOPPY_DRIVE_DD }
+#define FLOPPY_STANDARD_3_5_DSDD { FLOPPY_DRIVE_3_5_INCH, 2, 83, FLOPPY_DRIVE_DD }
+#define FLOPPY_STANDARD_3_5_DSHD { FLOPPY_DRIVE_3_5_INCH, 2, 83, FLOPPY_DRIVE_HD }
+#define FLOPPY_STANDARD_3_5_DSED { FLOPPY_DRIVE_3_5_INCH, 2, 83, FLOPPY_DRIVE_ED }
+#define FLOPPY_STANDARD_5_25_SSSD_35 { FLOPPY_DRIVE_5_25_INCH, 1, 37, FLOPPY_DRIVE_SD }
+#define FLOPPY_STANDARD_5_25_DSSD_35 { FLOPPY_DRIVE_5_25_INCH, 2, 37, FLOPPY_DRIVE_SD }
+#define FLOPPY_STANDARD_5_25_SSSD { FLOPPY_DRIVE_5_25_INCH, 1, 42, FLOPPY_DRIVE_SD }
+#define FLOPPY_STANDARD_5_25_DSSD { FLOPPY_DRIVE_5_25_INCH, 2, 42, FLOPPY_DRIVE_SD }
+#define FLOPPY_STANDARD_5_25_SSDD_40 { FLOPPY_DRIVE_5_25_INCH, 1, 42, FLOPPY_DRIVE_DD }
+#define FLOPPY_STANDARD_5_25_DSDD_40 { FLOPPY_DRIVE_5_25_INCH, 2, 42, FLOPPY_DRIVE_DD }
+#define FLOPPY_STANDARD_5_25_SSDD { FLOPPY_DRIVE_5_25_INCH, 1, 83, FLOPPY_DRIVE_DD }
+#define FLOPPY_STANDARD_5_25_DSDD { FLOPPY_DRIVE_5_25_INCH, 2, 83, FLOPPY_DRIVE_DD }
+#define FLOPPY_STANDARD_5_25_DSQD { FLOPPY_DRIVE_5_25_INCH, 2, 83, FLOPPY_DRIVE_QD }
+#define FLOPPY_STANDARD_5_25_DSHD { FLOPPY_DRIVE_5_25_INCH, 2, 83, FLOPPY_DRIVE_HD }
+#define FLOPPY_STANDARD_8_SSSD { FLOPPY_DRIVE_8_INCH, 1, 77, FLOPPY_DRIVE_SD }
+#define FLOPPY_STANDARD_8_DSSD { FLOPPY_DRIVE_8_INCH, 2, 77, FLOPPY_DRIVE_SD }
+#define FLOPPY_STANDARD_8_DSDD { FLOPPY_DRIVE_8_INCH, 2, 77, FLOPPY_DRIVE_DD }
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+// ======================> floppy_type_t
+
+struct floppy_type_t
+{
+ UINT8 media_size;
+ UINT8 head_number;
+ UINT8 max_track_number;
+ UINT8 max_density;
+};
+
+// ======================> floppy_interface
+
+struct floppy_interface
+{
+ devcb_write_line out_idx_func; /* index */
+ devcb_read_line in_mon_func; /* motor on */
+ devcb_write_line out_tk00_func; /* track 00 */
+ devcb_write_line out_wpt_func; /* write protect */
+ devcb_write_line out_rdy_func; /* ready */
+// devcb_write_line out_dskchg_func; /* disk changed */
+
+ floppy_type_t floppy_type;
+ const struct FloppyFormat *formats;
+ const char *interface;
+ device_image_display_info_func device_displayinfo;
+};
+
+struct chrn_id
+{
+ unsigned char C;
+ unsigned char H;
+ unsigned char R;
+ unsigned char N;
+ int data_id; // id for read/write data command
+ unsigned long flags;
+};
+
+/* set if drive is ready */
+#define FLOPPY_DRIVE_READY 0x0010
+/* set if index has just occurred */
+#define FLOPPY_DRIVE_INDEX 0x0020
+
+/* a callback which will be executed if the ready state of the drive changes e.g. not ready->ready, ready->not ready */
+void floppy_drive_set_ready_state_change_callback(device_t *img, void (*callback)(device_t *controller,device_t *img, int state));
+
+void floppy_drive_set_index_pulse_callback(device_t *img, void (*callback)(device_t *controller,device_t *image, int state));
+
+/* set flag state */
+int floppy_drive_get_flag_state(device_t *img, int flag);
+/* get flag state */
+void floppy_drive_set_flag_state(device_t *img, int flag, int state);
+/* get current physical track drive is on */
+int floppy_drive_get_current_track(device_t *img);
+/* get current physical track size */
+UINT64 floppy_drive_get_current_track_size(device_t *img, int head);
+
+/* get next id from track, 1 if got a id, 0 if no id was got */
+int floppy_drive_get_next_id(device_t *img, int side, chrn_id *);
+/* set ready state of drive. If flag == 1, set ready state only if drive present,
+disk is in drive, and motor is on. Otherwise set ready state to the state passed */
+void floppy_drive_set_ready_state(device_t *img, int state, int flag);
+
+/* seek up or down */
+void floppy_drive_seek(device_t *img, signed int signed_tracks);
+
+void floppy_drive_read_track_data_info_buffer(device_t *img, int side, void *ptr, int *length );
+void floppy_drive_write_track_data_info_buffer(device_t *img, int side, const void *ptr, int *length );
+void floppy_drive_format_sector(device_t *img, int side, int sector_index, int c, int h, int r, int n, int filler);
+void floppy_drive_read_sector_data(device_t *img, int side, int index1, void *pBuffer, int length);
+void floppy_drive_write_sector_data(device_t *img, int side, int index1, const void *pBuffer, int length, int ddam);
+
+/* set motor speed to get correct index pulses
+ standard RPM are 300 RPM (common) and 360 RPM
+ Note: this actually only works for soft sectored disks: one index pulse per
+ track.
+*/
+void floppy_drive_set_rpm(device_t *image, float rpm);
+
+void floppy_drive_set_controller(device_t *img, device_t *controller);
+
+floppy_image_legacy *flopimg_get_image(device_t *image);
+
+/* hack for apple II; replace this when we think of something better */
+void floppy_install_unload_proc(device_t *image, void (*proc)(device_image_interface &image));
+
+void floppy_install_load_proc(device_t *image, void (*proc)(device_image_interface &image));
+
+device_t *floppy_get_device(running_machine &machine,int drive);
+device_t *floppy_get_device_by_type(running_machine &machine,int ftype,int drive);
+int floppy_get_drive_type(device_t *image);
+void floppy_set_type(device_t *image,int ftype);
+int floppy_get_count(running_machine &machine);
+
+int floppy_get_drive(device_t *image);
+int floppy_get_drive_by_type(device_t *image,int ftype);
+
+void *flopimg_get_custom_data(device_t *image);
+void flopimg_alloc_custom_data(device_t *image,void *custom);
+
+void floppy_drive_set_geometry(device_t *img, floppy_type_t type);
+
+/* drive select lines */
+WRITE_LINE_DEVICE_HANDLER( floppy_ds0_w );
+WRITE_LINE_DEVICE_HANDLER( floppy_ds1_w );
+WRITE_LINE_DEVICE_HANDLER( floppy_ds2_w );
+WRITE_LINE_DEVICE_HANDLER( floppy_ds3_w );
+WRITE8_DEVICE_HANDLER( floppy_ds_w );
+
+WRITE_LINE_DEVICE_HANDLER( floppy_mon_w );
+WRITE_LINE_DEVICE_HANDLER( floppy_drtn_w );
+WRITE_LINE_DEVICE_HANDLER( floppy_stp_w );
+WRITE_LINE_DEVICE_HANDLER( floppy_wtd_w );
+WRITE_LINE_DEVICE_HANDLER( floppy_wtg_w );
+
+/* write-protect */
+READ_LINE_DEVICE_HANDLER( floppy_wpt_r );
+
+/* track 0 detect */
+READ_LINE_DEVICE_HANDLER( floppy_tk00_r );
+
+/* disk changed */
+READ_LINE_DEVICE_HANDLER( floppy_dskchg_r );
+
+/* 2-sided disk */
+READ_LINE_DEVICE_HANDLER( floppy_twosid_r );
+
+// index pulse
+READ_LINE_DEVICE_HANDLER( floppy_index_r );
+
+// drive ready
+READ_LINE_DEVICE_HANDLER( floppy_ready_r );
+
+DECLARE_LEGACY_IMAGE_DEVICE(LEGACY_FLOPPY, floppy);
+
+extern DEVICE_START( floppy );
+extern DEVICE_IMAGE_LOAD( floppy );
+extern DEVICE_IMAGE_CREATE( floppy );
+extern DEVICE_IMAGE_UNLOAD( floppy );
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+#define FLOPPY_0 "floppy0"
+#define FLOPPY_1 "floppy1"
+#define FLOPPY_2 "floppy2"
+#define FLOPPY_3 "floppy3"
+
+
+#define MCFG_LEGACY_FLOPPY_DRIVE_ADD(_tag, _config) \
+ MCFG_DEVICE_ADD(_tag, LEGACY_FLOPPY, 0) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MCFG_LEGACY_FLOPPY_DRIVE_MODIFY(_tag, _config) \
+ MCFG_DEVICE_MODIFY(_tag) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MCFG_LEGACY_FLOPPY_4_DRIVES_ADD(_config) \
+ MCFG_DEVICE_ADD(FLOPPY_0, LEGACY_FLOPPY, 0) \
+ MCFG_DEVICE_CONFIG(_config) \
+ MCFG_DEVICE_ADD(FLOPPY_1, LEGACY_FLOPPY, 0) \
+ MCFG_DEVICE_CONFIG(_config) \
+ MCFG_DEVICE_ADD(FLOPPY_2, LEGACY_FLOPPY, 0) \
+ MCFG_DEVICE_CONFIG(_config) \
+ MCFG_DEVICE_ADD(FLOPPY_3, LEGACY_FLOPPY, 0) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MCFG_LEGACY_FLOPPY_4_DRIVES_MODIFY(_config) \
+ MCFG_DEVICE_MODIFY(FLOPPY_0) \
+ MCFG_DEVICE_CONFIG(_config) \
+ MCFG_DEVICE_MODIFY(FLOPPY_1) \
+ MCFG_DEVICE_CONFIG(_config) \
+ MCFG_DEVICE_MODIFY(FLOPPY_2) \
+ MCFG_DEVICE_CONFIG(_config) \
+ MCFG_DEVICE_MODIFY(FLOPPY_3) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MCFG_LEGACY_FLOPPY_4_DRIVES_REMOVE() \
+ MCFG_DEVICE_REMOVE(FLOPPY_0) \
+ MCFG_DEVICE_REMOVE(FLOPPY_1) \
+ MCFG_DEVICE_REMOVE(FLOPPY_2) \
+ MCFG_DEVICE_REMOVE(FLOPPY_3)
+
+#define MCFG_LEGACY_FLOPPY_2_DRIVES_ADD(_config) \
+ MCFG_DEVICE_ADD(FLOPPY_0, LEGACY_FLOPPY, 0) \
+ MCFG_DEVICE_CONFIG(_config) \
+ MCFG_DEVICE_ADD(FLOPPY_1, LEGACY_FLOPPY, 0) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MCFG_LEGACY_FLOPPY_2_DRIVES_MODIFY(_config) \
+ MCFG_DEVICE_MODIFY(FLOPPY_0) \
+ MCFG_DEVICE_CONFIG(_config) \
+ MCFG_DEVICE_MODIFY(FLOPPY_1) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MCFG_LEGACY_FLOPPY_2_DRIVES_REMOVE() \
+ MCFG_DEVICE_REMOVE(FLOPPY_0) \
+ MCFG_DEVICE_REMOVE(FLOPPY_1)
+
+#endif /* __FLOPDRV_H__ */
diff --git a/trunk/src/emu/imagedev/floppy.c b/trunk/src/emu/imagedev/floppy.c
new file mode 100644
index 00000000000..0041603dff3
--- /dev/null
+++ b/trunk/src/emu/imagedev/floppy.c
@@ -0,0 +1,216 @@
+/*********************************************************************
+
+
+
+*********************************************************************/
+
+#include "emu.h"
+#include "floppy.h"
+#include "formats/imageutl.h"
+
+// device type definition
+const device_type FLOPPY = &device_creator<floppy_image_device>;
+
+//-------------------------------------------------
+// floppy_image_device - constructor
+//-------------------------------------------------
+
+floppy_image_device::floppy_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, FLOPPY, "Floppy drive", tag, owner, clock),
+ device_image_interface(mconfig, *this),
+ m_image(NULL)
+{
+
+}
+
+//-------------------------------------------------
+// floppy_image_device - destructor
+//-------------------------------------------------
+
+floppy_image_device::~floppy_image_device()
+{
+}
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void floppy_image_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const floppy_interface *intf = reinterpret_cast<const floppy_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<floppy_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_formats, 0, sizeof(m_formats));
+ memset(&m_interface, 0, sizeof(m_interface));
+ memset(&m_device_displayinfo, 0, sizeof(m_device_displayinfo));
+ memset(&m_load_func, 0, sizeof(m_load_func));
+ memset(&m_unload_func, 0, sizeof(m_unload_func));
+ }
+
+ image_device_format **formatptr;
+ image_device_format *format;
+ formatptr = &m_formatlist;
+ int cnt = 0;
+ m_extension_list[0] = '\0';
+ while (m_formats[cnt].name)
+ {
+ // allocate a new format
+ format = global_alloc_clear(image_device_format);
+ format->m_index = cnt;
+ format->m_name = m_formats[cnt].name;
+ format->m_description = m_formats[cnt].description;
+ format->m_extensions = m_formats[cnt].extensions;
+ format->m_optspec = (m_formats[cnt].param_guidelines) ? m_formats[cnt].param_guidelines : "";
+
+ image_specify_extension( m_extension_list, 256, m_formats[cnt].extensions );
+ // and append it to the list
+ *formatptr = format;
+ formatptr = &format->m_next;
+ cnt++;
+ }
+
+ // set brief and instance name
+ update_names();
+}
+
+static TIMER_CALLBACK(floppy_drive_index_callback)
+{
+ floppy_image_device *image = (floppy_image_device *) ptr;
+ image->index_func();
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void floppy_image_device::device_start()
+{
+ // resolve callbacks
+ m_out_idx_func.resolve(m_out_idx_cb, *this);
+
+ m_idx = 0;
+
+ /* motor off */
+ m_mon = 1;
+ /* set write protect on */
+ m_wpt = 0;
+
+ m_rpm = 300.0f;
+
+ m_cyl = 0;
+ m_ss = 1;
+ m_stp = 1;
+ m_dskchg = 0;
+ m_index_timer = machine().scheduler().timer_alloc(FUNC(floppy_drive_index_callback), (void *)this);
+}
+
+bool floppy_image_device::call_load()
+{
+ device_image_interface *image = this;
+ int best;
+ m_image = global_alloc(floppy_image((void *) image, &image_ioprocs, m_formats));
+ const struct floppy_format_def *format = m_image->identify(&best);
+ m_dskchg = 0;
+ if (format) {
+ m_image->load(best);
+ if (m_load_func)
+ return m_load_func(*this);
+ } else {
+ return IMAGE_INIT_FAIL;
+ }
+ return IMAGE_INIT_PASS;
+}
+
+void floppy_image_device::call_unload()
+{
+ m_dskchg = 0;
+
+ if (m_image)
+ global_free(m_image);
+ if (m_unload_func)
+ m_unload_func(*this);
+}
+
+/* motor on, active low */
+void floppy_image_device::mon_w(int state)
+{
+ /* force off if there is no attached image */
+ if (!exists())
+ state = 1;
+
+ /* off -> on */
+ if (m_mon && state == 0)
+ {
+ m_idx = 0;
+ index_func();
+ }
+
+ /* on -> off */
+ else if (m_mon == 0 && state)
+ m_index_timer->adjust(attotime::zero);
+
+ m_mon = state;
+}
+
+/* index pulses at rpm/60 Hz, and stays high 1/20th of time */
+void floppy_image_device::index_func()
+{
+ double ms = 1000.0 / (m_rpm / 60.0);
+
+ if (m_idx)
+ {
+ m_idx = 0;
+ m_index_timer->adjust(attotime::from_double(ms*19/20/1000.0));
+ }
+ else
+ {
+ m_idx = 1;
+ m_index_timer->adjust(attotime::from_double(ms/20/1000.0));
+ }
+
+ m_out_idx_func(m_idx);
+}
+
+int floppy_image_device::ready_r()
+{
+ if (exists())
+ {
+ if (m_mon == 0)
+ {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+double floppy_image_device::get_pos()
+{
+ return m_index_timer->elapsed().as_double();
+}
+
+void floppy_image_device::stp_w(int state)
+{
+ if ( m_stp != state ) {
+ m_stp = state;
+ if ( m_stp == 0 ) {
+ if ( m_dir ) {
+ if ( m_cyl ) m_cyl--;
+ } else {
+ if ( m_cyl < 83 ) m_cyl++;
+ }
+ /* Update disk detection if applicable */
+ if (exists())
+ {
+ if (m_dskchg==0) m_dskchg = 1;
+ }
+ }
+ }
+
+}
diff --git a/trunk/src/emu/imagedev/floppy.h b/trunk/src/emu/imagedev/floppy.h
new file mode 100644
index 00000000000..24abf9c6d10
--- /dev/null
+++ b/trunk/src/emu/imagedev/floppy.h
@@ -0,0 +1,125 @@
+/*********************************************************************
+
+ floppy.h
+
+*********************************************************************/
+
+#ifndef FLOPPY_H
+#define FLOPPY_H
+
+#include "formats/flopimg.h"
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+// ======================> floppy_interface
+
+struct floppy_interface
+{
+ devcb_write_line m_out_idx_cb; /* index */
+
+ const struct floppy_format_def *m_formats;
+ const char * m_interface;
+ device_image_display_info_func m_device_displayinfo;
+ device_image_load_func m_load_func;
+ device_image_unload_func m_unload_func;
+};
+
+// ======================> cdrom_image_device
+
+class floppy_image_device : public device_t,
+ public floppy_interface,
+ public device_image_interface
+{
+public:
+ // construction/destruction
+ floppy_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ virtual ~floppy_image_device();
+
+ // image-level overrides
+ virtual bool call_load();
+ virtual void call_unload();
+ virtual void call_display_info() { if (m_device_displayinfo) m_device_displayinfo(*this); }
+ virtual bool call_softlist_load(char *swlist, char *swname, rom_entry *start_entry) { return load_software(swlist, swname, start_entry); }
+
+ virtual iodevice_t image_type() const { return IO_FLOPPY; }
+
+ virtual bool is_readable() const { return 1; }
+ virtual bool is_writeable() const { return 1; }
+ virtual bool is_creatable() const { return 0; }
+ virtual bool must_be_loaded() const { return 0; }
+ virtual bool is_reset_on_load() const { return 0; }
+ virtual const char *image_interface() const { return m_interface; }
+ virtual const char *file_extensions() const { return m_extension_list; }
+ virtual const option_guide *create_option_guide() const { return NULL; }
+
+ UINT8* get_buffer() { return m_image->get_buffer(m_cyl,m_ss ^ 1); }
+
+ void mon_w(int state);
+ void index_func();
+ int ready_r();
+ double get_pos();
+
+ int wpt_r() { return m_wpt; }
+ int dskchg_r() { return m_dskchg; }
+ int trk00_r() { return (m_cyl==0) ? 0 : 1; }
+
+ void stp_w(int state);
+ void dir_w(int state) { m_dir = state; }
+ void ss_w(int state) { m_ss = state; }
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+
+ image_device_format m_format;
+ floppy_image *m_image;
+ char m_extension_list[256];
+
+ /* index pulse timer */
+ emu_timer *m_index_timer;
+
+ /* state of input lines */
+ int m_dir; /* direction */
+ int m_stp; /* step */
+ int m_wtg; /* write gate */
+ int m_mon; /* motor on */
+ int m_ss; /* side select */
+
+ /* state of output lines */
+ int m_idx; /* index pulse */
+ int m_tk00; /* track 00 */
+ int m_wpt; /* write protect */
+ int m_rdy; /* ready */
+ int m_dskchg; /* disk changed */
+
+ /* rotation per minute => gives index pulse frequency */
+ float m_rpm;
+
+ int m_cyl;
+ devcb_resolved_write_line m_out_idx_func;
+};
+
+// device type definition
+extern const device_type FLOPPY;
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+#define FLOPPY_0 "floppy0"
+#define FLOPPY_1 "floppy1"
+#define FLOPPY_2 "floppy2"
+#define FLOPPY_3 "floppy3"
+
+#define MCFG_FLOPPY_DRIVE_ADD(_config) \
+ MCFG_DEVICE_ADD(FLOPPY_0, FLOPPY, 0) \
+ MCFG_DEVICE_CONFIG(_config) \
+
+#define MCFG_FLOPPY_2_DRIVES_ADD(_config) \
+ MCFG_DEVICE_ADD(FLOPPY_0, FLOPPY, 0) \
+ MCFG_DEVICE_CONFIG(_config) \
+ MCFG_DEVICE_ADD(FLOPPY_1, FLOPPY, 0) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#endif /* FLOPPY_H */
diff --git a/trunk/src/emu/imagedev/harddriv.c b/trunk/src/emu/imagedev/harddriv.c
new file mode 100644
index 00000000000..19ec4128a5e
--- /dev/null
+++ b/trunk/src/emu/imagedev/harddriv.c
@@ -0,0 +1,268 @@
+/*********************************************************************
+
+ Code to interface the image code with harddisk core.
+
+ We do not support diff files as it will involve some changes in
+ the image code. Additionally, the need for diff files comes
+ from MAME's need for "cannonical" hard drive images.
+
+ Raphael Nabet 2003
+
+ Update: 23-Feb-2004 - Unlike floppy disks, for which we support
+ myriad formats on many systems, it is my intention for MESS to
+ standardize on the CHD file format for hard drives so I made a few
+ changes to support this
+
+*********************************************************************/
+
+#include "emu.h"
+#include "harddisk.h"
+#include "harddriv.h"
+
+
+static const char *const error_strings[] =
+{
+ "no error",
+ "no drive interface",
+ "out of memory",
+ "invalid file",
+ "invalid parameter",
+ "invalid data",
+ "file not found",
+ "requires parent",
+ "file not writeable",
+ "read error",
+ "write error",
+ "codec error",
+ "invalid parent",
+ "hunk out of range",
+ "decompression error",
+ "compression error",
+ "can't create file",
+ "can't verify file"
+ "operation not supported",
+ "can't find metadata",
+ "invalid metadata size",
+ "unsupported CHD version"
+};
+
+static const char *chd_get_error_string(int chderr)
+{
+ if ((chderr < 0 ) || (chderr >= ARRAY_LENGTH(error_strings)))
+ return NULL;
+ return error_strings[chderr];
+}
+
+
+
+static OPTION_GUIDE_START(hd_option_guide)
+ OPTION_INT('C', "cylinders", "Cylinders")
+ OPTION_INT('H', "heads", "Heads")
+ OPTION_INT('S', "sectors", "Sectors")
+ OPTION_INT('L', "sectorlength", "Sector Bytes")
+ OPTION_INT('K', "hunksize", "Hunk Bytes")
+OPTION_GUIDE_END
+
+static const char *hd_option_spec =
+ "C1-[512]-1024;H1/2/[4]/8;S1-[16]-64;L128/256/[512]/1024;K512/1024/2048/[4096]";
+
+
+// device type definition
+const device_type HARDDISK = &device_creator<harddisk_image_device>;
+
+//-------------------------------------------------
+// harddisk_image_device - constructor
+//-------------------------------------------------
+
+harddisk_image_device::harddisk_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, HARDDISK, "Harddisk", tag, owner, clock),
+ device_image_interface(mconfig, *this)
+{
+
+}
+
+//-------------------------------------------------
+// harddisk_image_device - destructor
+//-------------------------------------------------
+
+harddisk_image_device::~harddisk_image_device()
+{
+}
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void harddisk_image_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const harddisk_interface *intf = reinterpret_cast<const harddisk_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<harddisk_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_device_image_load, 0, sizeof(m_device_image_load));
+ memset(&m_device_image_unload, 0, sizeof(m_device_image_unload));
+ }
+
+ image_device_format *format = global_alloc_clear(image_device_format);;
+ format->m_index = 0;
+ format->m_name = "chd";
+ format->m_description = "CHD Hard drive";
+ format->m_extensions = "chd,hd";
+ format->m_optspec = hd_option_spec;
+ format->m_next = NULL;
+
+ m_formatlist = format;
+
+ // set brief and instance name
+ update_names();
+}
+
+const option_guide *harddisk_image_device::create_option_guide() const
+{
+ return hd_option_guide;
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void harddisk_image_device::device_start()
+{
+ m_chd = NULL;
+ m_hard_disk_handle = NULL;
+}
+
+bool harddisk_image_device::call_load()
+{
+ int our_result;
+
+ our_result = internal_load_hd(NULL);
+
+ /* Check if there is an image_load callback defined */
+ if ( m_device_image_load )
+ {
+ /* Let the override do some additional work/checks */
+ our_result = m_device_image_load(*this);
+ }
+ return our_result;
+
+}
+
+bool harddisk_image_device::call_create(int create_format, option_resolution *create_args)
+{
+ int err;
+ char metadata[256];
+ UINT32 sectorsize, hunksize;
+ UINT32 cylinders, heads, sectors, totalsectors;
+
+ cylinders = option_resolution_lookup_int(create_args, 'C');
+ heads = option_resolution_lookup_int(create_args, 'H');
+ sectors = option_resolution_lookup_int(create_args, 'S');
+ sectorsize = option_resolution_lookup_int(create_args, 'L');
+ hunksize = option_resolution_lookup_int(create_args, 'K');
+
+ totalsectors = cylinders * heads * sectors;
+
+ /* create the CHD file */
+ err = chd_create_file(image_core_file(), (UINT64)totalsectors * (UINT64)sectorsize, hunksize, CHDCOMPRESSION_NONE, NULL);
+ if (err != CHDERR_NONE)
+ goto error;
+
+ sprintf(metadata, HARD_DISK_METADATA_FORMAT, cylinders, heads, sectors, sectorsize);
+ return internal_load_hd(metadata);
+
+error:
+ return IMAGE_INIT_FAIL;
+}
+
+void harddisk_image_device::call_unload()
+{
+ /* Check if there is an image_unload callback defined */
+ if ( m_device_image_unload )
+ {
+ m_device_image_unload(*this);
+ }
+
+ if (m_hard_disk_handle != NULL)
+ {
+ hard_disk_close(m_hard_disk_handle);
+ m_hard_disk_handle = NULL;
+ }
+
+ if (m_chd != NULL)
+ {
+ chd_close(m_chd);
+ m_chd = NULL;
+ }
+}
+
+int harddisk_image_device::internal_load_hd(const char *metadata)
+{
+ chd_error err = (chd_error)0;
+ int is_writeable;
+
+ /* open the CHD file */
+ do
+ {
+ is_writeable = !is_readonly();
+ m_chd = NULL;
+ err = chd_open_file(image_core_file(), is_writeable ? CHD_OPEN_READWRITE : CHD_OPEN_READ, NULL, &m_chd);
+
+ /* special case; if we get CHDERR_FILE_NOT_WRITEABLE, make the
+ * image read only and repeat */
+ if (err == CHDERR_FILE_NOT_WRITEABLE)
+ make_readonly();
+ }
+ while(!m_chd && is_writeable && (err == CHDERR_FILE_NOT_WRITEABLE));
+ if (!m_chd)
+ goto done;
+
+ /* if we created the image and hence, have metadata to set, set the metadata */
+ if (metadata)
+ {
+ err = chd_set_metadata(m_chd, HARD_DISK_METADATA_TAG, 0, metadata, strlen(metadata) + 1, 0);
+ if (err != CHDERR_NONE)
+ goto done;
+ }
+
+ /* open the hard disk file */
+ m_hard_disk_handle = hard_disk_open(m_chd);
+ if (!m_hard_disk_handle)
+ goto done;
+
+done:
+ if (err)
+ {
+ /* if we had an error, close out the CHD */
+ if (m_chd != NULL)
+ {
+ chd_close(m_chd);
+ m_chd = NULL;
+ }
+
+ seterror(IMAGE_ERROR_UNSPECIFIED, chd_get_error_string(err));
+ }
+ return err ? IMAGE_INIT_FAIL : IMAGE_INIT_PASS;
+}
+
+/*************************************
+ *
+ * Get the CHD file (from the src/chd.c core)
+ * after an image has been opened with the hd core
+ *
+ *************************************/
+
+chd_file *harddisk_image_device::get_chd_file()
+{
+ chd_file *result = NULL;
+ hard_disk_file *hd_file = get_hard_disk_file();
+ if (hd_file)
+ result = hard_disk_get_chd(hd_file);
+ return result;
+}
diff --git a/trunk/src/emu/imagedev/harddriv.h b/trunk/src/emu/imagedev/harddriv.h
new file mode 100644
index 00000000000..10420c23bdf
--- /dev/null
+++ b/trunk/src/emu/imagedev/harddriv.h
@@ -0,0 +1,84 @@
+/*********************************************************************
+
+ harddriv.h
+
+ Interface to the CHD code
+
+*********************************************************************/
+
+#ifndef HARDDRIV_H
+#define HARDDRIV_H
+
+#include "image.h"
+#include "harddisk.h"
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+// ======================> harddisk_interface
+
+struct harddisk_interface
+{
+ device_image_load_func m_device_image_load;
+ device_image_unload_func m_device_image_unload;
+};
+
+// ======================> harddisk_image_device
+
+class harddisk_image_device : public device_t,
+ public harddisk_interface,
+ public device_image_interface
+{
+public:
+ // construction/destruction
+ harddisk_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ virtual ~harddisk_image_device();
+
+ // image-level overrides
+ virtual bool call_load();
+ virtual bool call_create(int create_format, option_resolution *create_args);
+ virtual void call_unload();
+
+ virtual iodevice_t image_type() const { return IO_HARDDISK; }
+
+ virtual bool is_readable() const { return 1; }
+ virtual bool is_writeable() const { return 1; }
+ virtual bool is_creatable() const { return 0; }
+ virtual bool must_be_loaded() const { return 0; }
+ virtual bool is_reset_on_load() const { return 0; }
+ virtual const char *file_extensions() const { return "chd,hd"; }
+ virtual const option_guide *create_option_guide() const;
+
+ // specific implementation
+ hard_disk_file *get_hard_disk_file() { return m_hard_disk_handle; }
+ chd_file *get_chd_file();
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+
+ int internal_load_hd(const char *metadata);
+
+ chd_file *m_chd;
+ hard_disk_file *m_hard_disk_handle;
+
+ image_device_format m_format;
+};
+
+// device type definition
+extern const device_type HARDDISK;
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_HARDDISK_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, HARDDISK, 0) \
+
+#define MCFG_HARDDISK_CONFIG_ADD(_tag,_config) \
+ MCFG_DEVICE_ADD(_tag, HARDDISK, 0) \
+ MCFG_DEVICE_CONFIG(_config) \
+
+#endif /* HARDDRIV_H */
diff --git a/trunk/src/emu/imagedev/multcart.c b/trunk/src/emu/imagedev/multcart.c
new file mode 100644
index 00000000000..506e1231126
--- /dev/null
+++ b/trunk/src/emu/imagedev/multcart.c
@@ -0,0 +1,888 @@
+/*********************************************************************
+
+ multcart.c
+
+ Multi-cartridge handling code
+
+*********************************************************************/
+
+#include "emu.h"
+#include "multcart.h"
+#include "pool.h"
+#include "unzip.h"
+#include "corestr.h"
+#include "xmlfile.h"
+#include "hash.h"
+#include "machine/ram.h"
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+struct _multicart_private
+{
+ object_pool * pool;
+ zip_file * zip;
+};
+
+
+typedef struct _multicart_load_state multicart_load_state;
+struct _multicart_load_state
+{
+ multicart_t * multicart;
+ zip_file * zip;
+ xml_data_node * layout_xml;
+ xml_data_node * resources_node;
+ xml_data_node * pcb_node;
+ multicart_resource * resources;
+ multicart_socket * sockets;
+};
+
+static const char error_text[14][30] =
+{
+ "no error",
+ "not a multicart",
+ "module definition corrupt",
+ "out of memory",
+ "xml format error",
+ "invalid file reference",
+ "zip file error",
+ "missing ram length",
+ "invalid ram specification",
+ "unknown resource type",
+ "invalid resource reference",
+ "invalid file format",
+ "missing layout",
+ "no pcb or resource found"
+};
+
+const char *multicart_error_text(multicart_open_error error)
+{
+ return error_text[(int)error];
+}
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE multicartslot_t *get_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == MULTICARTSLOT);
+ return (multicartslot_t *) downcast<legacy_device_base *>(device)->token();
+}
+
+
+INLINE const multicartslot_config *get_config(const device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == MULTICARTSLOT);
+ return (const multicartslot_config *) downcast<const legacy_device_base *>(device)->inline_config();
+}
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ cartslot_get_pcb
+-------------------------------------------------*/
+
+device_t *cartslot_get_pcb(device_t *device)
+{
+ multicartslot_t *cart = get_token(device);
+ return cart->pcb_device;
+}
+
+
+/*-------------------------------------------------
+ cartslot_get_socket
+-------------------------------------------------*/
+
+void *cartslot_get_socket(device_t *device, const char *socket_name)
+{
+ multicartslot_t *cart = get_token(device);
+ device_image_interface *image = dynamic_cast<device_image_interface *>(device);
+ void *result = NULL;
+
+ if (cart->mc != NULL)
+ {
+ const multicart_socket *socket;
+ for (socket = cart->mc->sockets; socket != NULL; socket = socket->next)
+ {
+ if (!strcmp(socket->id, socket_name))
+ break;
+ }
+ result = socket ? socket->ptr : NULL;
+ }
+ else if (socket_name[0] == '\0')
+ {
+ result = image->ptr();
+ }
+ return result;
+}
+
+/*-------------------------------------------------
+ cartslot_get_resource_length
+-------------------------------------------------*/
+
+int cartslot_get_resource_length(device_t *device, const char *socket_name)
+{
+ multicartslot_t *cart = get_token(device);
+ int result = 0;
+
+ if (cart->mc != NULL)
+ {
+ const multicart_socket *socket;
+
+ for (socket = cart->mc->sockets; socket != NULL; socket = socket->next)
+ {
+ if (!strcmp(socket->id, socket_name)) {
+ break;
+ }
+ }
+ if (socket != NULL)
+ result = socket->resource->length;
+ }
+ else
+ result = 0;
+
+ return result;
+}
+/*-------------------------------------------------
+ identify_pcb
+-------------------------------------------------*/
+
+static const multicartslot_pcb_type *identify_pcb(device_image_interface &image)
+{
+ const multicartslot_config *config = get_config(&image.device());
+ astring pcb_name;
+ const multicartslot_pcb_type *pcb_type = NULL;
+ multicart_t *mc;
+ int i;
+
+ if (image.exists())
+ {
+ /* try opening this as if it were a multicart */
+ multicart_open_error me = multicart_open(image.device().machine().options(), image.filename(), image.device().machine().system().name, MULTICART_FLAGS_DONT_LOAD_RESOURCES, &mc);
+ if (me == MCERR_NONE)
+ {
+ /* this was a multicart - read from it */
+ astring_cpyc(&pcb_name, mc->pcb_type);
+ multicart_close(image.device().machine().options(), mc);
+ }
+ else
+ {
+ if (me != MCERR_NOT_MULTICART)
+ fatalerror("multicart error: %s", multicart_error_text(me));
+ }
+
+ /* look for PCB type with matching name */
+ for (i = 0; (i < ARRAY_LENGTH(config->pcb_types)) && (config->pcb_types[i].name != NULL); i++)
+ {
+ if ((config->pcb_types[i].name[0] == '\0') || !strcmp(astring_c(&pcb_name), config->pcb_types[i].name))
+ {
+ pcb_type = &config->pcb_types[i];
+ break;
+ }
+ }
+
+ /* check for unknown PCB type */
+ if ((mc != NULL) && (pcb_type == NULL))
+ fatalerror("Unknown PCB type \"%s\"", astring_c(&pcb_name));
+ }
+ else
+ {
+ /* no device loaded; use the default */
+ pcb_type = (config->pcb_types[0].name != NULL) ? &config->pcb_types[0] : NULL;
+ }
+ return pcb_type;
+}
+
+/*-------------------------------------------------
+ DEVICE_IMAGE_GET_DEVICES(cartslot)
+-------------------------------------------------*/
+static DEVICE_IMAGE_GET_DEVICES(multicartslot)
+{
+ const multicartslot_pcb_type *pcb_type;
+ device_t *device = &image.device();
+
+ pcb_type = identify_pcb(image);
+ if (pcb_type != NULL)
+ {
+ image_add_device_with_subdevices(device,pcb_type->devtype,TAG_PCB,0);
+ }
+}
+
+
+/*-------------------------------------------------
+ find_file
+-------------------------------------------------*/
+
+static const zip_file_header *find_file(zip_file *zip, const char *filename)
+{
+ const zip_file_header *header;
+ for (header = zip_file_first_file(zip); header != NULL; header = zip_file_next_file(zip))
+ {
+ if (!core_stricmp(header->filename, filename))
+ return header;
+ }
+ return NULL;
+}
+
+static const zip_file_header *find_file_crc(zip_file *zip, const char *filename, UINT32 crc)
+{
+ const zip_file_header *header;
+ for (header = zip_file_first_file(zip); header != NULL; header = zip_file_next_file(zip))
+ {
+ // if the CRC and name both match, we're good
+ // if the CRC matches and the name doesn't, we're still good
+ if ((!core_stricmp(header->filename, filename)) && (header->crc == crc))
+ {
+ return header;
+ }
+ else if (header->crc == crc)
+ {
+ return header;
+ }
+ }
+ return NULL;
+}
+
+/*-------------------------------------------------
+ find_pcb_and_resource_nodes
+-------------------------------------------------*/
+
+static int find_pcb_and_resource_nodes(xml_data_node *layout_xml,
+ xml_data_node **pcb_node, xml_data_node **resource_node)
+{
+ xml_data_node *romset_node;
+ xml_data_node *configuration_node;
+
+ *pcb_node = NULL;
+ *resource_node = NULL;
+
+ romset_node = xml_get_sibling(layout_xml->child, "romset");
+ if (romset_node == NULL)
+ return FALSE;
+
+ configuration_node = xml_get_sibling(romset_node->child, "configuration");
+ if (configuration_node == NULL)
+ return FALSE;
+
+ *pcb_node = xml_get_sibling(configuration_node->child, "pcb");
+ if (*pcb_node == NULL)
+ return FALSE;
+
+ *resource_node = xml_get_sibling(romset_node->child, "resources");
+ if (*resource_node == NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/*-------------------------------------------------
+ get_resource_type
+-------------------------------------------------*/
+
+static multicart_resource_type get_resource_type(const char *s)
+{
+ multicart_resource_type result;
+ if (!strcmp(s, "rom"))
+ result = MULTICART_RESOURCE_TYPE_ROM;
+ else if (!strcmp(s, "ram"))
+ result = MULTICART_RESOURCE_TYPE_RAM;
+ else
+ result = MULTICART_RESOURCE_TYPE_INVALID;
+ return result;
+}
+
+
+/*-------------------------------------------------
+ load_rom_resource
+-------------------------------------------------*/
+
+static multicart_open_error load_rom_resource(multicart_load_state *state, xml_data_node *resource_node,
+ multicart_resource *resource)
+{
+ const char *file, *crcstr, *sha1;
+ const zip_file_header *header;
+ zip_error ziperr;
+ UINT32 crc;
+
+ /* locate the 'file' attribute */
+ file = xml_get_attribute_string(resource_node, "file", NULL);
+ if (file == NULL)
+ return MCERR_XML_ERROR;
+
+ if (!(crcstr = xml_get_attribute_string(resource_node, "crc", NULL)))
+ {
+ /* locate the file in the ZIP file */
+ header = find_file(state->zip, file);
+ }
+ else /* CRC tag is present, use it */
+ {
+ crc = strtoul(crcstr, NULL, 16);
+ header = find_file_crc(state->zip, file, crc);
+ }
+ if (header == NULL)
+ return MCERR_INVALID_FILE_REF;
+ resource->length = header->uncompressed_length;
+
+ /* allocate bytes for this resource */
+ resource->ptr = pool_malloc_lib(state->multicart->data->pool, resource->length);
+ if (resource->ptr == NULL)
+ return MCERR_OUT_OF_MEMORY;
+
+ /* and decompress it */
+ ziperr = zip_file_decompress(state->zip, resource->ptr, resource->length);
+ if (ziperr != ZIPERR_NONE)
+ return MCERR_ZIP_ERROR;
+
+ /* check SHA1 now */
+ if ((sha1 = xml_get_attribute_string(resource_node, "sha1", NULL)))
+ {
+ hash_collection actual_hashes;
+ actual_hashes.compute((const UINT8 *)resource->ptr, resource->length, hash_collection::HASH_TYPES_CRC_SHA1);
+
+ hash_collection expected_hashes;
+ expected_hashes.add_from_string(hash_collection::HASH_SHA1, sha1, strlen(sha1));
+
+ if (actual_hashes != expected_hashes)
+ {
+ return MCERR_INVALID_FILE_REF;
+ }
+ }
+
+ return MCERR_NONE;
+}
+
+
+/*-------------------------------------------------
+ load_ram_resource
+-------------------------------------------------*/
+
+static multicart_open_error load_ram_resource(emu_options &options, multicart_load_state *state, xml_data_node *resource_node,
+ multicart_resource *resource)
+{
+ const char *length_string;
+ const char *ram_type;
+ const char *ram_filename;
+
+ astring *ram_pathname;
+
+ /* locate the 'length' attribute */
+ length_string = xml_get_attribute_string(resource_node, "length", NULL);
+ if (length_string == NULL)
+ return MCERR_MISSING_RAM_LENGTH;
+
+ /* ...and parse it */
+ resource->length = ram_parse_string(length_string);
+ if (resource->length <= 0)
+ return MCERR_INVALID_RAM_SPEC;
+
+ /* allocate bytes for this resource */
+ resource->ptr = pool_malloc_lib(state->multicart->data->pool, resource->length);
+ if (resource->ptr == NULL)
+ return MCERR_OUT_OF_MEMORY;
+
+ /* Is this a persistent RAM resource? Then try to load it. */
+ ram_type = xml_get_attribute_string(resource_node, "type", NULL);
+ if (ram_type != NULL)
+ {
+ if (strcmp(ram_type, "persistent")==0)
+ {
+ astring tmp;
+
+ /* Get the file name. */
+ ram_filename = xml_get_attribute_string(resource_node, "file", NULL);
+ if (ram_filename==NULL)
+ return MCERR_XML_ERROR;
+
+ ram_pathname = astring_assemble_3(&tmp, state->multicart->gamedrv_name, PATH_SEPARATOR, ram_filename);
+
+ /* Save the file name so that we can write the contents on unloading.
+ If the RAM resource has no filename, we know that it was volatile only. */
+ resource->filename = pool_strdup_lib(state->multicart->data->pool, astring_c(ram_pathname));
+
+ if (resource->filename == NULL)
+ return MCERR_OUT_OF_MEMORY;
+
+ image_battery_load_by_name(options, resource->filename, resource->ptr, resource->length, 0x00);
+ }
+ /* else this type is volatile, in which case we just have
+ a memory expansion */
+ }
+ return MCERR_NONE;
+}
+
+
+/*-------------------------------------------------
+ load_resource
+-------------------------------------------------*/
+
+static multicart_open_error load_resource(emu_options &options, multicart_load_state *state, xml_data_node *resource_node,
+ multicart_resource_type resource_type)
+{
+ const char *id;
+ multicart_open_error err;
+ multicart_resource *resource;
+ multicart_resource **next_resource;
+
+ /* get the 'id' attribute; error if not present */
+ id = xml_get_attribute_string(resource_node, "id", NULL);
+ if (id == NULL)
+ return MCERR_XML_ERROR;
+
+ /* allocate memory for the resource */
+ resource = (multicart_resource *)pool_malloc_lib(state->multicart->data->pool, sizeof(*resource));
+ if (resource == NULL)
+ return MCERR_OUT_OF_MEMORY;
+ memset(resource, 0, sizeof(*resource));
+ resource->type = resource_type;
+
+ /* copy id */
+ resource->id = pool_strdup_lib(state->multicart->data->pool, id);
+ if (resource->id == NULL)
+ return MCERR_OUT_OF_MEMORY;
+
+ switch(resource->type)
+ {
+ case MULTICART_RESOURCE_TYPE_ROM:
+ err = load_rom_resource(state, resource_node, resource);
+ if (err != MCERR_NONE)
+ return err;
+ break;
+
+ case MULTICART_RESOURCE_TYPE_RAM:
+ err = load_ram_resource(options, state, resource_node, resource);
+ if (err != MCERR_NONE)
+ return err;
+ break;
+
+ default:
+ return MCERR_UNKNOWN_RESOURCE_TYPE;
+ }
+
+ /* append the resource */
+ for (next_resource = &state->resources; *next_resource; next_resource = &(*next_resource)->next)
+ ;
+ *next_resource = resource;
+
+ return MCERR_NONE;
+}
+
+
+/*-------------------------------------------------
+ load_all_resources
+-------------------------------------------------*/
+
+static multicart_open_error load_all_resources(emu_options &options, multicart_load_state *state)
+{
+ multicart_open_error err;
+ xml_data_node *resource_node;
+ multicart_resource_type resource_type;
+
+ for (resource_node = state->resources_node->child; resource_node != NULL; resource_node = resource_node->next)
+ {
+ resource_type = get_resource_type(resource_node->name);
+ if (resource_type != MULTICART_RESOURCE_TYPE_INVALID)
+ {
+ err = load_resource(options, state, resource_node, resource_type);
+ if (err != MCERR_NONE)
+ return err;
+ }
+ }
+
+ state->multicart->resources = state->resources;
+ return MCERR_NONE;
+}
+
+/*-------------------------------------------------
+ save_ram_resources. This is important for persistent RAM. All
+ resources were allocated within the memory pool of this device and will
+ be freed on multicart_close.
+-------------------------------------------------*/
+
+static multicart_open_error save_ram_resources(emu_options &options, multicart_t *cart)
+{
+ const multicart_resource *resource;
+
+ for (resource = cart->resources; resource != NULL; resource = resource->next)
+ {
+ if ((resource->type == MULTICART_RESOURCE_TYPE_RAM) && (resource->filename != NULL))
+ {
+ image_battery_save_by_name(options, resource->filename, resource->ptr, resource->length);
+ }
+ }
+ return MCERR_NONE;
+}
+
+/*-------------------------------------------------
+ load_socket
+-------------------------------------------------*/
+
+static multicart_open_error load_socket(multicart_load_state *state, xml_data_node *socket_node)
+{
+ const char *id;
+ const char *uses;
+ const multicart_resource *resource;
+ multicart_socket *socket;
+ multicart_socket **next_socket;
+
+ /* get the 'id' and 'uses' attributes; error if not present */
+ id = xml_get_attribute_string(socket_node, "id", NULL);
+ uses = xml_get_attribute_string(socket_node, "uses", NULL);
+ if ((id == NULL) || (uses == NULL))
+ return MCERR_XML_ERROR;
+
+ /* find the resource */
+ for (resource = state->multicart->resources; resource != NULL; resource = resource->next)
+ {
+ if (!strcmp(uses, resource->id))
+ break;
+ }
+ if (resource == NULL)
+ return MCERR_INVALID_RESOURCE_REF;
+
+ /* create the socket */
+ socket = (multicart_socket *)pool_malloc_lib(state->multicart->data->pool, sizeof(*socket));
+ if (socket == NULL)
+ return MCERR_OUT_OF_MEMORY;
+ memset(socket, 0, sizeof(*socket));
+ socket->resource = resource;
+ socket->ptr = resource->ptr;
+
+ /* copy id */
+ socket->id = pool_strdup_lib(state->multicart->data->pool, id);
+ if (socket->id == NULL)
+ return MCERR_OUT_OF_MEMORY;
+
+ /* which pointer should I use? */
+ if (resource->ptr != NULL)
+ {
+ /* use the resource's ptr */
+ socket->ptr = resource->ptr;
+ }
+ else
+ {
+ /* allocate bytes for this socket */
+ socket->ptr = pool_malloc_lib(state->multicart->data->pool, resource->length);
+ if (socket->ptr == NULL)
+ return MCERR_OUT_OF_MEMORY;
+
+ /* ...and clear it */
+ memset(socket->ptr, 0xCD, resource->length);
+ }
+
+ /* append the resource */
+ for (next_socket = &state->sockets; *next_socket; next_socket = &(*next_socket)->next)
+ ;
+ *next_socket = socket;
+
+ return MCERR_NONE;
+}
+
+
+/*-------------------------------------------------
+ load_all_sockets
+-------------------------------------------------*/
+
+static multicart_open_error load_all_sockets(multicart_load_state *state)
+{
+ multicart_open_error err;
+ xml_data_node *socket_node;
+
+ for (socket_node = xml_get_sibling(state->pcb_node->child, "socket"); socket_node != NULL;
+ socket_node = xml_get_sibling(socket_node->next, "socket"))
+ {
+ err = load_socket(state, socket_node);
+ if (err != MCERR_NONE)
+ return err;
+ }
+
+ state->multicart->sockets = state->sockets;
+ return MCERR_NONE;
+}
+
+
+/*-------------------------------------------------
+ multicart_open - opens a multicart
+-------------------------------------------------*/
+
+multicart_open_error multicart_open(emu_options &options, const char *filename, const char *gamedrv, multicart_load_flags load_flags, multicart_t **cart)
+{
+ multicart_open_error err;
+ zip_error ziperr;
+ object_pool *pool;
+ multicart_load_state state = {0, };
+ const zip_file_header *header;
+ const char *pcb_type;
+ char *layout_text = NULL;
+
+ /* allocate an object pool */
+ pool = pool_alloc_lib(NULL);
+ if (pool == NULL)
+ {
+ err = MCERR_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ /* allocate the multicart */
+ state.multicart = (multicart_t*)pool_malloc_lib(pool, sizeof(*state.multicart));
+ if (state.multicart == NULL)
+ {
+ err = MCERR_OUT_OF_MEMORY;
+ goto done;
+ }
+ memset(state.multicart, 0, sizeof(*state.multicart));
+
+ /* allocate the multicart's private data */
+ state.multicart->data = (multicart_private*)pool_malloc_lib(pool, sizeof(*state.multicart->data));
+ if (state.multicart->data == NULL)
+ {
+ err = MCERR_OUT_OF_MEMORY;
+ goto done;
+ }
+ memset(state.multicart->data, 0, sizeof(*state.multicart->data));
+ state.multicart->data->pool = pool;
+ pool = NULL;
+
+ /* open the ZIP file */
+ ziperr = zip_file_open(filename, &state.zip);
+ if (ziperr != ZIPERR_NONE)
+ {
+ err = MCERR_NOT_MULTICART;
+ goto done;
+ }
+
+ /* find the layout.xml file */
+ header = find_file(state.zip, "layout.xml");
+ if (header == NULL)
+ {
+ err = MCERR_MISSING_LAYOUT;
+ goto done;
+ }
+
+ /* reserve space for the layout text */
+ layout_text = (char*)malloc(header->uncompressed_length + 1);
+ if (layout_text == NULL)
+ {
+ err = MCERR_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ /* uncompress the layout text */
+ ziperr = zip_file_decompress(state.zip, layout_text, header->uncompressed_length);
+ if (ziperr != ZIPERR_NONE)
+ {
+ err = MCERR_ZIP_ERROR;
+ goto done;
+ }
+ layout_text[header->uncompressed_length] = '\0';
+
+ /* parse the layout text */
+ state.layout_xml = xml_string_read(layout_text, NULL);
+ if (state.layout_xml == NULL)
+ {
+ err = MCERR_XML_ERROR;
+ goto done;
+ }
+
+ /* locate the PCB node */
+ if (!find_pcb_and_resource_nodes(state.layout_xml, &state.pcb_node, &state.resources_node))
+ {
+ err = MCERR_NO_PCB_OR_RESOURCES;
+ goto done;
+ }
+
+ /* get the PCB resource_type */
+ pcb_type = xml_get_attribute_string(state.pcb_node, "type", "");
+ state.multicart->pcb_type = pool_strdup_lib(state.multicart->data->pool, pcb_type);
+ if (state.multicart->pcb_type == NULL)
+ {
+ err = MCERR_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ state.multicart->gamedrv_name = pool_strdup_lib(state.multicart->data->pool, gamedrv);
+ if (state.multicart->gamedrv_name == NULL)
+ {
+ err = MCERR_OUT_OF_MEMORY;
+ goto done;
+ }
+
+ /* do we have to load resources? */
+ if (load_flags & MULTICART_FLAGS_LOAD_RESOURCES)
+ {
+ err = load_all_resources(options, &state);
+ if (err != MCERR_NONE)
+ goto done;
+
+ err = load_all_sockets(&state);
+ if (err != MCERR_NONE)
+ goto done;
+ }
+
+ err = MCERR_NONE;
+
+done:
+ if (pool != NULL)
+ pool_free_lib(pool);
+ if (state.zip != NULL)
+ zip_file_close(state.zip);
+ if (layout_text != NULL)
+ free(layout_text);
+ if (state.layout_xml != NULL)
+ xml_file_free(state.layout_xml);
+
+ if ((err != MCERR_NONE) && (state.multicart != NULL))
+ {
+ multicart_close(options, state.multicart);
+ state.multicart = NULL;
+ }
+ *cart = state.multicart;
+ return err;
+}
+
+
+/*-------------------------------------------------
+ multicart_close - closes a multicart
+-------------------------------------------------*/
+
+void multicart_close(emu_options &options, multicart_t *cart)
+{
+ save_ram_resources(options, cart);
+ pool_free_lib(cart->data->pool);
+}
+
+/*-------------------------------------------------
+ DEVICE_START( multicartslot )
+-------------------------------------------------*/
+
+static DEVICE_START( multicartslot )
+{
+ const multicartslot_config *config = get_config(device);
+
+ /* if this cartridge has a custom DEVICE_START, use it */
+ if (config->device_start != NULL)
+ {
+ (*config->device_start)(device);
+ }
+}
+
+
+/*-------------------------------------------------
+ DEVICE_IMAGE_LOAD( cartslot )
+-------------------------------------------------*/
+
+static DEVICE_IMAGE_LOAD( multicartslot )
+{
+ device_t *device = &image.device();
+ const multicartslot_config *config = get_config(device);
+
+ /* if this cartridge has a custom DEVICE_IMAGE_LOAD, use it */
+ if (config->device_load != NULL)
+ return (*config->device_load)(image);
+
+ /* otherwise try the normal route */
+ return IMAGE_INIT_PASS;
+}
+
+
+/*-------------------------------------------------
+ DEVICE_IMAGE_UNLOAD( multicartslot )
+-------------------------------------------------*/
+
+static DEVICE_IMAGE_UNLOAD( multicartslot )
+{
+ device_t *device = &image.device();
+ const multicartslot_config *config = get_config(device);
+
+ /* if this cartridge has a custom DEVICE_IMAGE_UNLOAD, use it */
+ if (config->device_unload != NULL)
+ {
+ (*config->device_unload)(image);
+ return;
+ }
+}
+/*-------------------------------------------------
+ DEVICE_GET_INFO( multicartslot )
+-------------------------------------------------*/
+
+DEVICE_GET_INFO( multicartslot )
+{
+ switch(state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(multicartslot_t); break;
+ case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = sizeof(multicartslot_config); break;
+ case DEVINFO_INT_IMAGE_TYPE: info->i = IO_CARTSLOT; break;
+ case DEVINFO_INT_IMAGE_READABLE: info->i = 1; break;
+ case DEVINFO_INT_IMAGE_WRITEABLE: info->i = 0; break;
+ case DEVINFO_INT_IMAGE_CREATABLE: info->i = 0; break;
+ case DEVINFO_INT_IMAGE_RESET_ON_LOAD: info->i = 1; break;
+ case DEVINFO_INT_IMAGE_MUST_BE_LOADED: info->i = 0; break;
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(multicartslot); break;
+ case DEVINFO_FCT_IMAGE_LOAD: info->f = (genf *) DEVICE_IMAGE_LOAD_NAME(multicartslot); break;
+ case DEVINFO_FCT_IMAGE_UNLOAD: info->f = (genf *) DEVICE_IMAGE_UNLOAD_NAME(multicartslot); break;
+ case DEVINFO_FCT_IMAGE_GET_DEVICES: info->f = (genf *) DEVICE_IMAGE_GET_DEVICES_NAME(multicartslot); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "MultiCartslot"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "MultiCartslot"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_IMAGE_FILE_EXTENSIONS:
+ if ( device && downcast<const legacy_image_device_base *>(device)->inline_config() && get_config(device)->extensions )
+ {
+ strcpy(info->s, get_config(device)->extensions);
+ }
+ else
+ {
+ strcpy(info->s, "bin");
+ }
+ break;
+ }
+}
+
+DEFINE_LEGACY_IMAGE_DEVICE(MULTICARTSLOT, multicartslot);
+
+//**************************************************************************
+// DEVICE CARTSLOT INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_cart_slot_interface - constructor
+//-------------------------------------------------
+
+device_cart_slot_interface::device_cart_slot_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device)
+{
+}
+
+
+//-------------------------------------------------
+// ~device_cart_slot_interface - destructor
+//-------------------------------------------------
+
+device_cart_slot_interface::~device_cart_slot_interface()
+{
+}
+
+//**************************************************************************
+// LIVE LEGACY cart_slot DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// legacy_cart_slot_device_base - constructor
+//-------------------------------------------------
+
+legacy_cart_slot_device_base::legacy_cart_slot_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, device_get_config_func get_config)
+ : legacy_device_base(mconfig, type, tag, owner, clock, get_config),
+ device_cart_slot_interface(mconfig, *this)
+{
+}
diff --git a/trunk/src/emu/imagedev/multcart.h b/trunk/src/emu/imagedev/multcart.h
new file mode 100644
index 00000000000..801e9daa7b1
--- /dev/null
+++ b/trunk/src/emu/imagedev/multcart.h
@@ -0,0 +1,194 @@
+/*********************************************************************
+
+ multcart.h
+
+ Multi-cartridge handling code
+
+*********************************************************************/
+
+#ifndef __MULTCART_H__
+#define __MULTCART_H__
+
+#include "osdcore.h"
+
+#define TAG_PCB "pcb"
+
+DECLARE_LEGACY_IMAGE_DEVICE(MULTICARTSLOT, multicartslot);
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+enum _multicart_load_flags
+{
+ MULTICART_FLAGS_DONT_LOAD_RESOURCES = 0x00,
+ MULTICART_FLAGS_LOAD_RESOURCES = 0x01
+};
+typedef enum _multicart_load_flags multicart_load_flags;
+
+enum _multicart_resource_type
+{
+ MULTICART_RESOURCE_TYPE_INVALID,
+ MULTICART_RESOURCE_TYPE_ROM,
+ MULTICART_RESOURCE_TYPE_RAM
+};
+typedef enum _multicart_resource_type multicart_resource_type;
+
+typedef struct _multicart_resource multicart_resource;
+struct _multicart_resource
+{
+ const char * id;
+ const char * filename;
+ multicart_resource * next;
+ multicart_resource_type type;
+ UINT32 length;
+ void * ptr;
+};
+
+
+typedef struct _multicart_socket multicart_socket;
+struct _multicart_socket
+{
+ const char * id;
+ multicart_socket * next;
+ const multicart_resource * resource;
+ void * ptr;
+};
+
+
+typedef struct _multicart_private multicart_private;
+
+typedef struct _multicart_t multicart_t;
+struct _multicart_t
+{
+ const multicart_resource * resources;
+ const multicart_socket * sockets;
+ const char * pcb_type;
+ const char * gamedrv_name; /* need this to find the path to the nvram files */
+ multicart_private * data;
+};
+
+typedef struct _multicartslot_t multicartslot_t;
+struct _multicartslot_t
+{
+ device_t *pcb_device;
+ multicart_t *mc;
+};
+
+
+typedef struct _multicartslot_pcb_type multicartslot_pcb_type;
+struct _multicartslot_pcb_type
+{
+ const char * name;
+ device_type devtype;
+};
+
+
+typedef struct _multicartslot_config multicartslot_config;
+struct _multicartslot_config
+{
+ const char * extensions;
+ device_start_func device_start;
+ device_image_load_func device_load;
+ device_image_unload_func device_unload;
+ multicartslot_pcb_type pcb_types[16];
+};
+
+enum _multicart_open_error
+{
+ MCERR_NONE,
+ MCERR_NOT_MULTICART,
+ MCERR_CORRUPT,
+ MCERR_OUT_OF_MEMORY,
+ MCERR_XML_ERROR,
+ MCERR_INVALID_FILE_REF,
+ MCERR_ZIP_ERROR,
+ MCERR_MISSING_RAM_LENGTH,
+ MCERR_INVALID_RAM_SPEC,
+ MCERR_UNKNOWN_RESOURCE_TYPE,
+ MCERR_INVALID_RESOURCE_REF,
+ MCERR_INVALID_FILE_FORMAT,
+ MCERR_MISSING_LAYOUT,
+ MCERR_NO_PCB_OR_RESOURCES
+};
+typedef enum _multicart_open_error multicart_open_error;
+
+const char *multicart_error_text(multicart_open_error error);
+
+/***************************************************************************
+ PROTOTYPES
+***************************************************************************/
+
+/* opens a multicart */
+multicart_open_error multicart_open(emu_options &options, const char *filename, const char *drvname, multicart_load_flags load_flags, multicart_t **cart);
+
+/* closes a multicart */
+void multicart_close(emu_options &options, multicart_t *cart);
+
+/* accesses the PCB associated with this cartslot */
+device_t *cartslot_get_pcb(device_t *device);
+
+/* accesses a particular socket */
+void *cartslot_get_socket(device_t *device, const char *socket_name);
+
+/* accesses a particular socket; gets the length of the associated resource */
+int cartslot_get_resource_length(device_t *device, const char *socket_name);
+
+#define DECLARE_LEGACY_CART_SLOT_DEVICE(name, basename) _DECLARE_LEGACY_DEVICE(name, basename, basename##_device, legacy_cart_slot_device_base)
+#define DEFINE_LEGACY_CART_SLOT_DEVICE(name, basename) _DEFINE_LEGACY_DEVICE(name, basename, basename##_device, legacy_cart_slot_device_base)
+
+#define MCFG_MULTICARTSLOT_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, MULTICARTSLOT, 0) \
+
+#define MCFG_MULTICARTSLOT_MODIFY(_tag) \
+ MCFG_DEVICE_MODIFY(_tag) \
+
+#define MCFG_MULTICARTSLOT_PCBTYPE(_index, _pcb_type_name, _pcb_devtype) \
+ MCFG_DEVICE_CONFIG_DATAPTR_ARRAY_MEMBER(multicartslot_config, pcb_types, _index, multicartslot_pcb_type, name, _pcb_type_name) \
+ MCFG_DEVICE_CONFIG_DATAPTR_ARRAY_MEMBER(multicartslot_config, pcb_types, _index, multicartslot_pcb_type, devtype, _pcb_devtype)
+
+#define MCFG_MULTICARTSLOT_START(_start) \
+ MCFG_DEVICE_CONFIG_DATAPTR(multicartslot_config, device_start, DEVICE_START_NAME(_start))
+
+#define MCFG_MULTICARTSLOT_LOAD(_load) \
+ MCFG_DEVICE_CONFIG_DATAPTR(multicartslot_config, device_load, DEVICE_IMAGE_LOAD_NAME(_load))
+
+#define MCFG_MULTICARTSLOT_UNLOAD(_unload) \
+ MCFG_DEVICE_CONFIG_DATAPTR(multicartslot_config, device_unload, DEVICE_IMAGE_UNLOAD_NAME(_unload))
+
+#define MCFG_MULTICARTSLOT_EXTENSION_LIST(_extensions) \
+ MCFG_DEVICE_CONFIG_DATAPTR(multicartslot_config, extensions, _extensions)
+
+
+// ======================> device_cart_slot_interface
+
+// class representing interface-specific live cart_slot
+class device_cart_slot_interface : public device_interface
+{
+public:
+ // construction/destruction
+ device_cart_slot_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_cart_slot_interface();
+};
+
+
+// ======================> legacy_cart_slot_device
+
+// legacy_cart_slot_device is a legacy_device_base with a cart_slot interface
+class legacy_cart_slot_device_base : public legacy_device_base,
+ public device_cart_slot_interface
+{
+protected:
+ // construction/destruction
+ legacy_cart_slot_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, device_get_config_func get_config);
+
+public:
+ using legacy_device_base::get_legacy_int;
+ using legacy_device_base::get_legacy_fct;
+ using legacy_device_base::get_legacy_ptr;
+
+ // device_cart_slot_interface overrides
+};
+
+
+#endif /* __MULTCART_H__ */
diff --git a/trunk/src/emu/imagedev/printer.c b/trunk/src/emu/imagedev/printer.c
new file mode 100644
index 00000000000..0164ca60282
--- /dev/null
+++ b/trunk/src/emu/imagedev/printer.c
@@ -0,0 +1,120 @@
+/****************************************************************************
+
+ printer.c
+
+ Code for handling printer devices
+
+****************************************************************************/
+
+#include "emu.h"
+#include "printer.h"
+
+
+// device type definition
+const device_type PRINTER = &device_creator<printer_image_device>;
+
+//-------------------------------------------------
+// printer_image_device - constructor
+//-------------------------------------------------
+
+printer_image_device::printer_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, PRINTER, "Printer", tag, owner, clock),
+ device_image_interface(mconfig, *this)
+{
+
+}
+
+//-------------------------------------------------
+// printer_image_device - destructor
+//-------------------------------------------------
+
+printer_image_device::~printer_image_device()
+{
+}
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void printer_image_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const printer_interface *intf = reinterpret_cast<const printer_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<printer_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_online, 0, sizeof(m_online));
+ }
+
+ // set brief and instance name
+ update_names();
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void printer_image_device::device_start()
+{
+ m_online_func.resolve(m_online, *this);
+}
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ printer_is_ready - checks to see if a printer
+ is ready
+-------------------------------------------------*/
+
+int printer_image_device::is_ready()
+{
+ return exists() != 0;
+}
+
+
+
+/*-------------------------------------------------
+ printer_output - outputs data to a printer
+-------------------------------------------------*/
+
+void printer_image_device::output(UINT8 data)
+{
+ if (exists())
+ {
+ fwrite(&data, 1);
+ }
+}
+
+
+/*-------------------------------------------------
+ DEVICE_IMAGE_LOAD( printer )
+-------------------------------------------------*/
+bool printer_image_device::call_load()
+{
+ /* send notify that the printer is now online */
+ if (!m_online_func.isnull())
+ m_online_func(TRUE);
+
+ /* we don't need to do anything special */
+ return IMAGE_INIT_PASS;
+}
+
+
+/*-------------------------------------------------
+ DEVICE_IMAGE_UNLOAD( printer )
+-------------------------------------------------*/
+void printer_image_device::call_unload()
+{
+ /* send notify that the printer is now offline */
+ if (!m_online_func.isnull())
+ m_online_func(FALSE);
+}
+
diff --git a/trunk/src/emu/imagedev/printer.h b/trunk/src/emu/imagedev/printer.h
new file mode 100644
index 00000000000..5e059e87b8d
--- /dev/null
+++ b/trunk/src/emu/imagedev/printer.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+
+ printer.h
+
+ Code for handling printer devices
+
+****************************************************************************/
+
+#ifndef __PRINTER_H__
+#define __PRINTER_H__
+
+#include "diimage.h"
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+// ======================> printer_interface
+
+struct printer_interface
+{
+ devcb_write_line m_online;
+};
+
+// ======================> printer_image_device
+
+class printer_image_device : public device_t,
+ public printer_interface,
+ public device_image_interface
+{
+public:
+ // construction/destruction
+ printer_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ virtual ~printer_image_device();
+
+ // image-level overrides
+ virtual bool call_load();
+ virtual void call_unload();
+
+ virtual iodevice_t image_type() const { return IO_PRINTER; }
+
+ virtual bool is_readable() const { return 0; }
+ virtual bool is_writeable() const { return 1; }
+ virtual bool is_creatable() const { return 1; }
+ virtual bool must_be_loaded() const { return 0; }
+ virtual bool is_reset_on_load() const { return 0; }
+ virtual const char *image_interface() const { return NULL; }
+ virtual const char *file_extensions() const { return "prn"; }
+ virtual const option_guide *create_option_guide() const { return NULL; }
+
+ // specific implementation
+
+ /* checks to see if a printer is ready */
+ int is_ready();
+ /* outputs data to a printer */
+ void output(UINT8 data);
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+
+ devcb_resolved_write_line m_online_func;
+};
+
+
+// device type definition
+extern const device_type PRINTER;
+
+
+#define MCFG_PRINTER_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, PRINTER, 0) \
+
+#endif /* __PRINTER_H__ */
diff --git a/trunk/src/emu/imagedev/snapquik.c b/trunk/src/emu/imagedev/snapquik.c
new file mode 100644
index 00000000000..c15f82d597e
--- /dev/null
+++ b/trunk/src/emu/imagedev/snapquik.c
@@ -0,0 +1,373 @@
+/*********************************************************************
+
+ snapquik.h
+
+ Snapshots and quickloads
+
+*********************************************************************/
+
+#include "emu.h"
+#include "snapquik.h"
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _snapquick_token snapquick_token;
+struct _snapquick_token
+{
+ emu_timer *timer;
+ snapquick_load_func load;
+};
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ assert_is_snapshot_or_quickload - asserts/confirms
+ that a given device is a snapshot or quickload
+-------------------------------------------------*/
+
+INLINE void assert_is_snapshot_or_quickload(device_t *device)
+{
+ assert(device != NULL);
+ assert(downcast<const legacy_device_base *>(device)->inline_config() != NULL);
+ assert((device->type() == SNAPSHOT) || (device->type() == QUICKLOAD)
+ || (device->type() == Z80BIN));
+}
+
+
+
+/*-------------------------------------------------
+ get_token - safely gets the snapshot/quickload data
+-------------------------------------------------*/
+
+INLINE snapquick_token *get_token(device_t *device)
+{
+ assert_is_snapshot_or_quickload(device);
+ return (snapquick_token *) downcast<legacy_device_base *>(device)->token();
+}
+
+
+
+/*-------------------------------------------------
+ get_config - safely gets the quickload config
+-------------------------------------------------*/
+
+INLINE const snapquick_config *get_config(device_t *device)
+{
+ assert_is_snapshot_or_quickload(device);
+ return (const snapquick_config *) downcast<const legacy_device_base *>(device)->inline_config();
+}
+
+INLINE const snapquick_config *get_config_dev(const device_t *device)
+{
+ assert(device != NULL);
+ assert((device->type() == SNAPSHOT) || (device->type() == QUICKLOAD)
+ || (device->type() == Z80BIN));
+ return (const snapquick_config *) downcast<const legacy_device_base *>(device)->inline_config();
+}
+
+/*-------------------------------------------------
+ log_quickload - logs and displays useful
+ data for the end user
+-------------------------------------------------*/
+
+void log_quickload(const char *type, UINT32 start, UINT32 length, UINT32 exec, const char *exec_format)
+{
+ astring tempstring;
+
+ logerror("Loading %04X bytes of RAM at %04X\n", length, start);
+
+ tempstring.catprintf("Quickload type: %s Length: %d bytes\n", type, length);
+ tempstring.catprintf("Start: 0x%04X End: 0x%04X Exec: ", start, start + length - 1);
+
+ logerror("Quickload loaded.\n");
+ if (!mame_stricmp(exec_format, EXEC_NA))
+ tempstring.cat("N/A");
+ else
+ {
+ logerror("Execution can resume with ");
+ logerror(exec_format, exec);
+ logerror("\n");
+ tempstring.catprintf(exec_format, exec);
+ }
+
+ ui_popup_time(10, "%s", tempstring.cstr());
+}
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ TIMER_CALLBACK(process_snapshot_or_quickload)
+-------------------------------------------------*/
+
+static TIMER_CALLBACK(process_snapshot_or_quickload)
+{
+ device_image_interface *image = (device_image_interface *) ptr;
+ snapquick_token *token = get_token(&image->device());
+
+ /* invoke the load */
+ (*token->load)(*image,
+ image->filetype(),
+ image->length());
+
+ /* unload the device */
+ image->unload();
+}
+
+
+
+/*-------------------------------------------------
+ DEVICE_START( snapquick )
+-------------------------------------------------*/
+
+static DEVICE_START( snapquick )
+{
+ snapquick_token *token = get_token(device);
+
+ /* allocate a timer */
+ token->timer = device->machine().scheduler().timer_alloc(FUNC(process_snapshot_or_quickload), (void *) dynamic_cast<device_image_interface *>(device));
+
+}
+
+
+
+/*-------------------------------------------------
+ DEVICE_IMAGE_LOAD( snapquick )
+-------------------------------------------------*/
+
+static DEVICE_IMAGE_LOAD( snapquick )
+{
+ const snapquick_config *config = get_config(image);
+ snapquick_token *token = get_token(image);
+
+ /* locate the load function */
+ token->load = (snapquick_load_func) reinterpret_cast<snapquick_load_func>(image.get_device_specific_call());
+
+ /* adjust the timer */
+
+ token->timer->adjust(
+ attotime(config->delay_seconds, config->delay_attoseconds),
+ 0);
+
+ return IMAGE_INIT_PASS;
+}
+
+
+
+/*-------------------------------------------------
+ DEVICE_GET_INFO(snapquick) - device getinfo
+ function
+-------------------------------------------------*/
+
+static DEVICE_GET_INFO(snapquick)
+{
+ switch(state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(snapquick_token); break;
+ case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = sizeof(snapquick_config); break;
+ case DEVINFO_INT_IMAGE_READABLE: info->i = 1; break;
+ case DEVINFO_INT_IMAGE_WRITEABLE: info->i = 0; break;
+ case DEVINFO_INT_IMAGE_CREATABLE: info->i = 0; break;
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(snapquick); break;
+ case DEVINFO_FCT_IMAGE_LOAD: info->f = (genf *) DEVICE_IMAGE_LOAD_NAME(snapquick); break;
+ case DEVINFO_FCT_SNAPSHOT_QUICKLOAD_LOAD: info->f = (genf *) get_config_dev(device)->load; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_IMAGE_FILE_EXTENSIONS: strcpy(info->s, get_config_dev(device)->file_extensions); break;
+ }
+}
+
+
+
+/*-------------------------------------------------
+ DEVICE_GET_INFO(snapshot) - device getinfo
+ function
+-------------------------------------------------*/
+
+DEVICE_GET_INFO(snapshot)
+{
+ switch(state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_IMAGE_TYPE: info->i = IO_SNAPSHOT; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Snapshot"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Snapshot"); break;
+
+ default: DEVICE_GET_INFO_CALL(snapquick); break;
+ }
+}
+
+
+
+/*-------------------------------------------------
+ DEVICE_GET_INFO(quickload) - device getinfo
+ function
+-------------------------------------------------*/
+
+DEVICE_GET_INFO(quickload)
+{
+ switch(state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_IMAGE_TYPE: info->i = IO_QUICKLOAD; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Quickload"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Quickload"); break;
+
+ default: DEVICE_GET_INFO_CALL(snapquick); break;
+ }
+}
+/*-------------------------------------------------
+ z80bin_load_file - load a z80bin file into
+ memory
+-------------------------------------------------*/
+
+static int z80bin_load_file(device_image_interface *image, const char *file_type, UINT16 *exec_addr, UINT16 *start_addr, UINT16 *end_addr )
+{
+ int ch;
+ UINT16 args[3];
+ UINT16 i=0, j, size;
+ UINT8 data;
+ char pgmname[256];
+ char message[256];
+
+ image->fseek(7, SEEK_SET);
+
+ while((ch = image->fgetc()) != 0x1A)
+ {
+ if (ch == EOF)
+ {
+ image->seterror(IMAGE_ERROR_INVALIDIMAGE, "Unexpected EOF while getting file name");
+ image->message(" Unexpected EOF while getting file name");
+ return IMAGE_INIT_FAIL;
+ }
+
+ if (ch != '\0')
+ {
+ if (i >= (ARRAY_LENGTH(pgmname) - 1))
+ {
+ image->seterror(IMAGE_ERROR_INVALIDIMAGE, "File name too long");
+ image->message(" File name too long");
+ return IMAGE_INIT_FAIL;
+ }
+
+ pgmname[i] = ch; /* build program name */
+ i++;
+ }
+ }
+
+ pgmname[i] = '\0'; /* terminate string with a null */
+
+ if (image->fread(args, sizeof(args)) != sizeof(args))
+ {
+ image->seterror(IMAGE_ERROR_INVALIDIMAGE, "Unexpected EOF while getting file size");
+ image->message(" Unexpected EOF while getting file size");
+ return IMAGE_INIT_FAIL;
+ }
+
+ exec_addr[0] = LITTLE_ENDIANIZE_INT16(args[0]);
+ start_addr[0] = LITTLE_ENDIANIZE_INT16(args[1]);
+ end_addr[0] = LITTLE_ENDIANIZE_INT16(args[2]);
+
+ size = (end_addr[0] - start_addr[0] + 1) & 0xffff;
+
+ /* display a message about the loaded quickload */
+ image->message(" %s\nsize=%04X : start=%04X : end=%04X : exec=%04X",pgmname,size,start_addr[0],end_addr[0],exec_addr[0]);
+
+ for (i = 0; i < size; i++)
+ {
+ j = (start_addr[0] + i) & 0xffff;
+ if (image->fread(&data, 1) != 1)
+ {
+ snprintf(message, ARRAY_LENGTH(message), "%s: Unexpected EOF while writing byte to %04X", pgmname, (unsigned) j);
+ image->seterror(IMAGE_ERROR_INVALIDIMAGE, message);
+ image->message("%s: Unexpected EOF while writing byte to %04X", pgmname, (unsigned) j);
+ return IMAGE_INIT_FAIL;
+ }
+ image->device().machine().device("maincpu")->memory().space(AS_PROGRAM)->write_byte(j, data);
+ }
+
+ return IMAGE_INIT_PASS;
+}
+
+
+
+/*-------------------------------------------------
+ QUICKLOAD_LOAD( z80bin )
+-------------------------------------------------*/
+
+static QUICKLOAD_LOAD( z80bin )
+{
+ const z80bin_config *config;
+ UINT16 exec_addr, start_addr, end_addr;
+ int autorun;
+
+ /* load the binary into memory */
+ if (z80bin_load_file(&image, file_type, &exec_addr, &start_addr, &end_addr) == IMAGE_INIT_FAIL)
+ return IMAGE_INIT_FAIL;
+
+ /* is this file executable? */
+ if (exec_addr != 0xffff)
+ {
+ config = (const z80bin_config *)downcast<const legacy_device_base &>(image.device()).inline_config();
+
+ /* check to see if autorun is on (I hate how this works) */
+ autorun = input_port_read_safe(image.device().machine(), "CONFIG", 0xFF) & 1;
+
+ /* start program */
+ if (config->execute != NULL)
+ {
+ (*config->execute)(image.device().machine(), start_addr, end_addr, exec_addr, autorun);
+ }
+ else
+ {
+ if (autorun)
+ cpu_set_reg(image.device().machine().device("maincpu"), STATE_GENPC, exec_addr);
+ }
+ }
+
+ return IMAGE_INIT_PASS;
+}
+
+
+
+/*-------------------------------------------------
+ DEVICE_GET_INFO(z80bin)
+-------------------------------------------------*/
+
+DEVICE_GET_INFO(z80bin)
+{
+ /* quickload */
+ switch(state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = sizeof(z80bin_config); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_IMAGE_FILE_EXTENSIONS: strcpy(info->s, "bin"); break;
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case DEVINFO_FCT_SNAPSHOT_QUICKLOAD_LOAD: info->f = (genf *) quickload_load_z80bin; break;
+
+ default: DEVICE_GET_INFO_CALL(quickload); break;
+ }
+}
+
+DEFINE_LEGACY_IMAGE_DEVICE(Z80BIN, z80bin);
+DEFINE_LEGACY_IMAGE_DEVICE(SNAPSHOT, snapshot);
+DEFINE_LEGACY_IMAGE_DEVICE(QUICKLOAD, quickload);
diff --git a/trunk/src/emu/imagedev/snapquik.h b/trunk/src/emu/imagedev/snapquik.h
new file mode 100644
index 00000000000..126c47c8807
--- /dev/null
+++ b/trunk/src/emu/imagedev/snapquik.h
@@ -0,0 +1,115 @@
+/*********************************************************************
+
+ snapquik.h
+
+ Snapshots and quickloads
+
+*********************************************************************/
+
+#ifndef __SNAPQUIK_H__
+#define __SNAPQUIK_H__
+
+#include "image.h"
+#include "ui.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+enum
+{
+ DEVINFO_FCT_SNAPSHOT_QUICKLOAD_LOAD = DEVINFO_FCT_DEVICE_SPECIFIC
+};
+
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+DECLARE_LEGACY_IMAGE_DEVICE(SNAPSHOT, snapshot);
+DECLARE_LEGACY_IMAGE_DEVICE(QUICKLOAD, quickload);
+DECLARE_LEGACY_IMAGE_DEVICE(Z80BIN, z80bin);
+
+#define SNAPSHOT_LOAD_NAME(name) snapshot_load_##name
+#define SNAPSHOT_LOAD(name) int SNAPSHOT_LOAD_NAME(name)(device_image_interface &image, const char *file_type, int snapshot_size)
+
+#define QUICKLOAD_LOAD_NAME(name) quickload_load_##name
+#define QUICKLOAD_LOAD(name) int QUICKLOAD_LOAD_NAME(name)(device_image_interface &image, const char *file_type, int quickload_size)
+
+#define Z80BIN_EXECUTE_NAME(name) z80bin_execute_##name
+#define Z80BIN_EXECUTE(name) void Z80BIN_EXECUTE_NAME(name)(running_machine &machine, UINT16 start_address, UINT16 end_address, UINT16 execute_address, int autorun)
+
+#define LOAD_REG(_cpu, _reg, _data) \
+ do { \
+ cpu_set_reg(_cpu, _reg, (_data)); \
+ } while (0)
+
+#define EXEC_NA "N/A"
+#define z80bin_execute_default NULL
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef int (*snapquick_load_func)(device_image_interface &image, const char *file_type, int file_size);
+
+typedef struct _snapquick_config snapquick_config;
+struct _snapquick_config
+{
+ snapquick_load_func load; /* loading function */
+ const char * file_extensions; /* file extensions */
+ seconds_t delay_seconds; /* loading delay (seconds) */
+ attoseconds_t delay_attoseconds; /* loading delay (attoseconds) */
+};
+
+typedef void (*z80bin_execute_func)(running_machine &machine, UINT16 start_address, UINT16 end_address, UINT16 execute_address, int autorun);
+
+typedef struct _z80bin_config z80bin_config;
+struct _z80bin_config
+{
+ snapquick_config base;
+ z80bin_execute_func execute;
+};
+
+/***************************************************************************
+ SNAPSHOT DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_SNAPSHOT_ADD(_tag, _load, _file_extensions, _delay) \
+ MCFG_DEVICE_ADD(_tag, SNAPSHOT, 0) \
+ MCFG_DEVICE_CONFIG_DATAPTR(snapquick_config, load, SNAPSHOT_LOAD_NAME(_load)) \
+ MCFG_DEVICE_CONFIG_DATAPTR(snapquick_config, file_extensions, _file_extensions) \
+ MCFG_DEVICE_CONFIG_DATA64(snapquick_config, delay_seconds, (seconds_t) (_delay)) \
+ MCFG_DEVICE_CONFIG_DATA64(snapquick_config, delay_attoseconds, (attoseconds_t) (((_delay) - (int)(_delay)) * ATTOSECONDS_PER_SECOND)) \
+
+/***************************************************************************
+ QUICKLOAD DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_QUICKLOAD_ADD(_tag, _load, _file_extensions, _delay) \
+ MCFG_DEVICE_ADD(_tag, QUICKLOAD, 0) \
+ MCFG_DEVICE_CONFIG_DATAPTR(snapquick_config, load, QUICKLOAD_LOAD_NAME(_load)) \
+ MCFG_DEVICE_CONFIG_DATAPTR(snapquick_config, file_extensions, _file_extensions) \
+ MCFG_DEVICE_CONFIG_DATA64(snapquick_config, delay_seconds, (seconds_t) (_delay)) \
+ MCFG_DEVICE_CONFIG_DATA64(snapquick_config, delay_attoseconds, (attoseconds_t) (((_delay) - (int)(_delay)) * ATTOSECONDS_PER_SECOND)) \
+
+/***************************************************************************
+ Z80BIN QUICKLOAD DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_Z80BIN_QUICKLOAD_ADD(_tag, _execute, _delay) \
+ MCFG_DEVICE_ADD(_tag, Z80BIN, 0) \
+ MCFG_DEVICE_CONFIG_DATA64(snapquick_config, delay_seconds, (seconds_t) (_delay)) \
+ MCFG_DEVICE_CONFIG_DATA64(snapquick_config, delay_attoseconds, (attoseconds_t) (((_delay) - (int)(_delay)) * ATTOSECONDS_PER_SECOND)) \
+ MCFG_DEVICE_CONFIG_DATAPTR(z80bin_config, execute, Z80BIN_EXECUTE_NAME(_execute))
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+void log_quickload(const char *type, UINT32 start, UINT32 length, UINT32 exec, const char *exec_format);
+
+
+#endif /* __SNAPQUIK_H__ */
diff --git a/trunk/src/emu/info.c b/trunk/src/emu/info.c
new file mode 100644
index 00000000000..12e0b73f499
--- /dev/null
+++ b/trunk/src/emu/info.c
@@ -0,0 +1,1231 @@
+/***************************************************************************
+
+ info.c
+
+ Dumps the MAME internal data as an XML file.
+
+****************************************************************************
+
+ 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 "machine/ram.h"
+#include "sound/samples.h"
+#include "info.h"
+#include "xmlfile.h"
+#include "hash.h"
+#include "config.h"
+
+#include <ctype.h>
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// DTD string describing the data
+const char info_xml_creator::s_dtd_string[] =
+"<!DOCTYPE " XML_ROOT " [\n"
+"<!ELEMENT " XML_ROOT " (" XML_TOP "+)>\n"
+"\t<!ATTLIST " XML_ROOT " build CDATA #IMPLIED>\n"
+"\t<!ATTLIST " XML_ROOT " debug (yes|no) \"no\">\n"
+"\t<!ATTLIST " XML_ROOT " mameconfig CDATA #REQUIRED>\n"
+"\t<!ELEMENT " XML_TOP " (description, year?, manufacturer?, biosset*, rom*, disk*, device_ref*, sample*, chip*, display*, sound?, input?, dipswitch*, configuration*, adjuster*, driver?, device*, slot*, softwarelist*, ramoption*)>\n"
+"\t\t<!ATTLIST " XML_TOP " name CDATA #REQUIRED>\n"
+"\t\t<!ATTLIST " XML_TOP " sourcefile CDATA #IMPLIED>\n"
+"\t\t<!ATTLIST " XML_TOP " isbios (yes|no) \"no\">\n"
+"\t\t<!ATTLIST " XML_TOP " isdevice (yes|no) \"no\">\n"
+"\t\t<!ATTLIST " XML_TOP " ismechanical (yes|no) \"no\">\n"
+"\t\t<!ATTLIST " XML_TOP " runnable (yes|no) \"yes\">\n"
+"\t\t<!ATTLIST " XML_TOP " cloneof CDATA #IMPLIED>\n"
+"\t\t<!ATTLIST " XML_TOP " romof CDATA #IMPLIED>\n"
+"\t\t<!ATTLIST " XML_TOP " sampleof CDATA #IMPLIED>\n"
+"\t\t<!ELEMENT description (#PCDATA)>\n"
+"\t\t<!ELEMENT year (#PCDATA)>\n"
+"\t\t<!ELEMENT manufacturer (#PCDATA)>\n"
+"\t\t<!ELEMENT biosset EMPTY>\n"
+"\t\t\t<!ATTLIST biosset name CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST biosset description CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST biosset default (yes|no) \"no\">\n"
+"\t\t<!ELEMENT rom EMPTY>\n"
+"\t\t\t<!ATTLIST rom name CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST rom bios CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST rom size CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST rom crc CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST rom sha1 CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST rom merge CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST rom region CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST rom offset CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST rom status (baddump|nodump|good) \"good\">\n"
+"\t\t\t<!ATTLIST rom optional (yes|no) \"no\">\n"
+"\t\t<!ELEMENT disk EMPTY>\n"
+"\t\t\t<!ATTLIST disk name CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST disk sha1 CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST disk merge CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST disk region CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST disk index CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST disk writable (yes|no) \"no\">\n"
+"\t\t\t<!ATTLIST disk status (baddump|nodump|good) \"good\">\n"
+"\t\t\t<!ATTLIST disk optional (yes|no) \"no\">\n"
+"\t\t<!ELEMENT device_ref EMPTY>\n"
+"\t\t\t<!ATTLIST device_ref name CDATA #REQUIRED>\n"
+"\t\t<!ELEMENT sample EMPTY>\n"
+"\t\t\t<!ATTLIST sample name CDATA #REQUIRED>\n"
+"\t\t<!ELEMENT chip EMPTY>\n"
+"\t\t\t<!ATTLIST chip name CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST chip tag CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST chip type (cpu|audio) #REQUIRED>\n"
+"\t\t\t<!ATTLIST chip clock CDATA #IMPLIED>\n"
+"\t\t<!ELEMENT display EMPTY>\n"
+"\t\t\t<!ATTLIST display type (raster|vector|lcd|unknown) #REQUIRED>\n"
+"\t\t\t<!ATTLIST display rotate (0|90|180|270) #REQUIRED>\n"
+"\t\t\t<!ATTLIST display flipx (yes|no) \"no\">\n"
+"\t\t\t<!ATTLIST display width CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST display height CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST display refresh CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST display pixclock CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST display htotal CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST display hbend CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST display hbstart CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST display vtotal CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST display vbend CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST display vbstart CDATA #IMPLIED>\n"
+"\t\t<!ELEMENT sound EMPTY>\n"
+"\t\t\t<!ATTLIST sound channels CDATA #REQUIRED>\n"
+"\t\t<!ELEMENT input (control*)>\n"
+"\t\t\t<!ATTLIST input service (yes|no) \"no\">\n"
+"\t\t\t<!ATTLIST input tilt (yes|no) \"no\">\n"
+"\t\t\t<!ATTLIST input players CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST input buttons CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST input coins CDATA #IMPLIED>\n"
+"\t\t\t<!ELEMENT control EMPTY>\n"
+"\t\t\t\t<!ATTLIST control type CDATA #REQUIRED>\n"
+"\t\t\t\t<!ATTLIST control minimum CDATA #IMPLIED>\n"
+"\t\t\t\t<!ATTLIST control maximum CDATA #IMPLIED>\n"
+"\t\t\t\t<!ATTLIST control sensitivity CDATA #IMPLIED>\n"
+"\t\t\t\t<!ATTLIST control keydelta CDATA #IMPLIED>\n"
+"\t\t\t\t<!ATTLIST control reverse (yes|no) \"no\">\n"
+"\t\t<!ELEMENT dipswitch (dipvalue*)>\n"
+"\t\t\t<!ATTLIST dipswitch name CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST dipswitch tag CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST dipswitch mask CDATA #REQUIRED>\n"
+"\t\t\t<!ELEMENT dipvalue EMPTY>\n"
+"\t\t\t\t<!ATTLIST dipvalue name CDATA #REQUIRED>\n"
+"\t\t\t\t<!ATTLIST dipvalue value CDATA #REQUIRED>\n"
+"\t\t\t\t<!ATTLIST dipvalue default (yes|no) \"no\">\n"
+"\t\t<!ELEMENT configuration (confsetting*)>\n"
+"\t\t\t<!ATTLIST configuration name CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST configuration tag CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST configuration mask CDATA #REQUIRED>\n"
+"\t\t\t<!ELEMENT confsetting EMPTY>\n"
+"\t\t\t\t<!ATTLIST confsetting name CDATA #REQUIRED>\n"
+"\t\t\t\t<!ATTLIST confsetting value CDATA #REQUIRED>\n"
+"\t\t\t\t<!ATTLIST confsetting default (yes|no) \"no\">\n"
+"\t\t<!ELEMENT adjuster EMPTY>\n"
+"\t\t\t<!ATTLIST adjuster name CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST adjuster default CDATA #REQUIRED>\n"
+"\t\t<!ELEMENT driver EMPTY>\n"
+"\t\t\t<!ATTLIST driver status (good|imperfect|preliminary) #REQUIRED>\n"
+"\t\t\t<!ATTLIST driver emulation (good|imperfect|preliminary) #REQUIRED>\n"
+"\t\t\t<!ATTLIST driver color (good|imperfect|preliminary) #REQUIRED>\n"
+"\t\t\t<!ATTLIST driver sound (good|imperfect|preliminary) #REQUIRED>\n"
+"\t\t\t<!ATTLIST driver graphic (good|imperfect|preliminary) #REQUIRED>\n"
+"\t\t\t<!ATTLIST driver cocktail (good|imperfect|preliminary) #IMPLIED>\n"
+"\t\t\t<!ATTLIST driver protection (good|imperfect|preliminary) #IMPLIED>\n"
+"\t\t\t<!ATTLIST driver savestate (supported|unsupported) #REQUIRED>\n"
+"\t\t\t<!ATTLIST driver palettesize CDATA #REQUIRED>\n"
+"\t\t<!ELEMENT device (instance*, extension*)>\n"
+"\t\t\t<!ATTLIST device type CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST device tag CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST device mandatory CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST device interface CDATA #IMPLIED>\n"
+"\t\t\t<!ELEMENT instance EMPTY>\n"
+"\t\t\t\t<!ATTLIST instance name CDATA #REQUIRED>\n"
+"\t\t\t\t<!ATTLIST instance briefname CDATA #REQUIRED>\n"
+"\t\t\t<!ELEMENT extension EMPTY>\n"
+"\t\t\t\t<!ATTLIST extension name CDATA #REQUIRED>\n"
+"\t\t<!ELEMENT slot (slotoption*)>\n"
+"\t\t\t<!ATTLIST slot name CDATA #REQUIRED>\n"
+"\t\t\t<!ELEMENT slotoption EMPTY>\n"
+"\t\t\t\t<!ATTLIST slotoption name CDATA #REQUIRED>\n"
+"\t\t\t\t<!ATTLIST slotoption default (yes|no) \"no\">\n"
+"\t\t<!ELEMENT softwarelist EMPTY>\n"
+"\t\t\t<!ATTLIST softwarelist name CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST softwarelist status (original|compatible) #REQUIRED>\n"
+"\t\t<!ELEMENT ramoption (#PCDATA)>\n"
+"\t\t\t<!ATTLIST ramoption default CDATA #IMPLIED>\n"
+"]>";
+
+
+extern const device_type *s_devices_sorted[];
+extern int m_device_count;
+
+//**************************************************************************
+// INFO XML CREATOR
+//**************************************************************************
+
+//-------------------------------------------------
+// info_xml_creator - constructor
+//-------------------------------------------------
+
+info_xml_creator::info_xml_creator(driver_enumerator &drivlist)
+ : m_output(NULL),
+ m_drivlist(drivlist)
+{
+}
+
+
+//-------------------------------------------------
+// output_mame_xml - print the XML information
+// for all known games
+//-------------------------------------------------
+
+void info_xml_creator::output(FILE *out)
+{
+ m_output = out;
+
+ // output the DTD
+ fprintf(m_output, "<?xml version=\"1.0\"?>\n");
+ fprintf(m_output, "%s\n\n", s_dtd_string);
+
+ // top-level tag
+ fprintf(m_output, "<" XML_ROOT " build=\"%s\" debug=\""
+#ifdef MAME_DEBUG
+ "yes"
+#else
+ "no"
+#endif
+ "\" mameconfig=\"%d\">\n",
+ xml_normalize_string(build_version),
+ CONFIG_VERSION
+ );
+
+ m_device_used = global_alloc_array_clear(UINT8, m_device_count);
+
+ // iterate through the drivers, outputting one at a time
+ while (m_drivlist.next())
+ output_one();
+
+ // iterate through the devices, and output their roms
+ output_devices();
+
+ global_free(m_device_used);
+
+ // close the top level tag
+ fprintf(m_output, "</" XML_ROOT ">\n");
+}
+
+
+//-------------------------------------------------
+// output_devices - print the XML information
+// for one particular game driver
+//-------------------------------------------------
+
+void info_xml_creator::output_devices()
+{
+ m_drivlist.reset();
+ m_drivlist.next();
+ machine_config &config = m_drivlist.config();
+ device_t *owner = config.devicelist().first();
+ // check if all are listed, note that empty one is included
+ bool display_all = driver_list::total() == (m_drivlist.count()+1);
+ for(int i=0;i<m_device_count;i++) {
+ if (display_all || (m_device_used[i]!=0)) {
+ device_type type = *s_devices_sorted[i];
+ device_t *dev = (*type)(config, "dummy", owner, 0);
+ dev->config_complete();
+
+ // print the header and the game name
+ fprintf(m_output, "\t<" XML_TOP);
+ fprintf(m_output, " name=\"%s\"", xml_normalize_string(dev->shortname()));
+ fprintf(m_output, " isdevice=\"yes\"");
+ fprintf(m_output, " runnable=\"no\"");
+ fprintf(m_output, ">\n");
+
+ // output device description
+ if (dev->name() != NULL)
+ fprintf(m_output, "\t\t<description>%s</description>\n", xml_normalize_string(dev->name()));
+
+ output_rom(dev);
+
+ // close the topmost tag
+ fprintf(m_output, "\t</" XML_TOP ">\n");
+ global_free(dev);
+ }
+ }
+}
+
+//-------------------------------------------------
+// output_one - print the XML information
+// for one particular game driver
+//-------------------------------------------------
+
+void info_xml_creator::output_one()
+{
+ // no action if not a game
+ const game_driver &driver = m_drivlist.driver();
+ if (driver.flags & GAME_NO_STANDALONE)
+ return;
+
+ // allocate input ports
+ machine_config &config = m_drivlist.config();
+ ioport_list portlist;
+ astring errors;
+ for (device_t *device = config.devicelist().first(); device != NULL; device = device->next())
+ input_port_list_init(*device, portlist, errors);
+
+ // print the header and the game name
+ fprintf(m_output, "\t<" XML_TOP);
+ fprintf(m_output, " name=\"%s\"", xml_normalize_string(driver.name));
+
+ // strip away any path information from the source_file and output it
+ const char *start = strrchr(driver.source_file, '/');
+ if (start == NULL)
+ start = strrchr(driver.source_file, '\\');
+ if (start == NULL)
+ start = driver.source_file - 1;
+ fprintf(m_output, " sourcefile=\"%s\"", xml_normalize_string(start + 1));
+
+ // append bios and runnable flags
+ if (driver.flags & GAME_IS_BIOS_ROOT)
+ fprintf(m_output, " isbios=\"yes\"");
+ if (driver.flags & GAME_NO_STANDALONE)
+ fprintf(m_output, " runnable=\"no\"");
+ if (driver.flags & GAME_MECHANICAL)
+ fprintf(m_output, " ismechanical=\"yes\"");
+
+ // display clone information
+ int clone_of = m_drivlist.find(driver.parent);
+ if (clone_of != -1 && !(m_drivlist.driver(clone_of).flags & GAME_IS_BIOS_ROOT))
+ fprintf(m_output, " cloneof=\"%s\"", xml_normalize_string(m_drivlist.driver(clone_of).name));
+ if (clone_of != -1)
+ fprintf(m_output, " romof=\"%s\"", xml_normalize_string(m_drivlist.driver(clone_of).name));
+
+ // display sample information and close the game tag
+ output_sampleof();
+ fprintf(m_output, ">\n");
+
+ // output game description
+ if (driver.description != NULL)
+ fprintf(m_output, "\t\t<description>%s</description>\n", xml_normalize_string(driver.description));
+
+ // print the year only if is a number or another allowed character (? or +)
+ if (driver.year != NULL && strspn(driver.year, "0123456789?+") == strlen(driver.year))
+ fprintf(m_output, "\t\t<year>%s</year>\n", xml_normalize_string(driver.year));
+
+ // print the manufacturer information
+ if (driver.manufacturer != NULL)
+ fprintf(m_output, "\t\t<manufacturer>%s</manufacturer>\n", xml_normalize_string(driver.manufacturer));
+
+ // now print various additional information
+ output_bios();
+ output_rom(rom_first_source(m_drivlist.config()));
+ output_device_roms();
+ output_sample();
+ output_chips();
+ output_display();
+ output_sound();
+ output_input(portlist);
+ output_switches(portlist, IPT_DIPSWITCH, "dipswitch", "dipvalue");
+ output_switches(portlist, IPT_CONFIG, "configuration", "confsetting");
+ output_adjusters(portlist);
+ output_driver();
+ output_images();
+ output_slots();
+ output_software_list();
+ output_ramoptions();
+
+ // close the topmost tag
+ fprintf(m_output, "\t</" XML_TOP ">\n");
+}
+
+//------------------------------------------------
+// output_device_roms - print the device
+// with roms, if appropriate
+//-------------------------------------------------
+
+void info_xml_creator::output_device_roms()
+{
+ int cnt=0;
+ for (const rom_source *source = rom_first_source(m_drivlist.config()); source != NULL; source = rom_next_source(*source))
+ {
+ if (cnt!=0) {
+ fprintf(m_output, "\t\t<device_ref name=\"%s\"/>\n", xml_normalize_string(source->shortname()));
+ for(int i=0;i<m_device_count;i++) {
+ if (source->type() == *s_devices_sorted[i]) m_device_used[i] = 1;
+ }
+ }
+ cnt++;
+ }
+}
+
+//------------------------------------------------
+// output_sampleof - print the 'sampleof'
+// attribute, if appropriate
+//-------------------------------------------------
+
+void info_xml_creator::output_sampleof()
+{
+ // iterate over sample devices
+ for (const device_t *device = m_drivlist.config().devicelist().first(SAMPLES); device != NULL; device = device->typenext())
+ {
+ const char *const *samplenames = ((const samples_interface *)device->static_config())->samplenames;
+ if (samplenames != NULL)
+
+ // iterate over sample names
+ for (int sampnum = 0; samplenames[sampnum] != NULL; sampnum++)
+ {
+ // only output sampleof if different from the game name
+ const char *cursampname = samplenames[sampnum];
+ if (cursampname[0] == '*' && strcmp(cursampname + 1, m_drivlist.driver().name) != 0)
+ fprintf(m_output, " sampleof=\"%s\"", xml_normalize_string(cursampname + 1));
+
+ // must stop here, as there can only be one attribute of the same name
+ return;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// output_bios - print the BIOS set for a
+// game
+//-------------------------------------------------
+
+void info_xml_creator::output_bios()
+{
+ // skip if no ROMs
+ if (m_drivlist.driver().rom == NULL)
+ return;
+
+ // iterate over ROM entries and look for BIOSes
+ for (const rom_entry *rom = m_drivlist.driver().rom; !ROMENTRY_ISEND(rom); rom++)
+ if (ROMENTRY_ISSYSTEM_BIOS(rom))
+ {
+ // output extracted name and descriptions
+ fprintf(m_output, "\t\t<biosset");
+ fprintf(m_output, " name=\"%s\"", xml_normalize_string(ROM_GETNAME(rom)));
+ fprintf(m_output, " description=\"%s\"", xml_normalize_string(ROM_GETHASHDATA(rom)));
+ if (ROM_GETBIOSFLAGS(rom) == 1)
+ fprintf(m_output, " default=\"yes\"");
+ fprintf(m_output, "/>\n");
+ }
+}
+
+
+//-------------------------------------------------
+// output_rom - print the roms section of
+// the XML output
+//-------------------------------------------------
+
+void info_xml_creator::output_rom(const rom_source *source)
+{
+ // iterate over 3 different ROM "types": BIOS, ROMs, DISKs
+ for (int rom_type = 0; rom_type < 3; rom_type++)
+ {
+ for (const rom_entry *region = rom_first_region(*source); region != NULL; region = rom_next_region(region))
+ {
+ bool is_disk = ROMREGION_ISDISKDATA(region);
+
+ // disk regions only work for disks
+ if ((is_disk && rom_type != 2) || (!is_disk && rom_type == 2))
+ continue;
+
+ // iterate through ROM entries
+ for (const rom_entry *rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom))
+ {
+ bool is_bios = ROM_GETBIOSFLAGS(rom);
+ const char *name = ROM_GETNAME(rom);
+ int offset = ROM_GETOFFSET(rom);
+ const char *merge_name = NULL;
+ char bios_name[100];
+
+ // BIOS ROMs only apply to bioses
+ if ((is_bios && rom_type != 0) || (!is_bios && rom_type == 0))
+ continue;
+
+ // if we have a valid ROM and we are a clone, see if we can find the parent ROM
+ hash_collection hashes(ROM_GETHASHDATA(rom));
+ if (!hashes.flag(hash_collection::FLAG_NO_DUMP))
+ merge_name = get_merge_name(hashes);
+
+ // scan for a BIOS name
+ bios_name[0] = 0;
+ if (!is_disk && is_bios)
+ {
+ // scan backwards through the ROM entries
+ for (const rom_entry *brom = rom - 1; brom != m_drivlist.driver().rom; brom--)
+ if (ROMENTRY_ISSYSTEM_BIOS(brom))
+ {
+ strcpy(bios_name, ROM_GETNAME(brom));
+ break;
+ }
+ }
+
+ // opening tag
+ if (!is_disk)
+ fprintf(m_output, "\t\t<rom");
+ else
+ fprintf(m_output, "\t\t<disk");
+
+ // add name, merge, bios, and size tags */
+ if (name != NULL && name[0] != 0)
+ fprintf(m_output, " name=\"%s\"", xml_normalize_string(name));
+ if (merge_name != NULL)
+ fprintf(m_output, " merge=\"%s\"", xml_normalize_string(merge_name));
+ if (bios_name[0] != 0)
+ fprintf(m_output, " bios=\"%s\"", xml_normalize_string(bios_name));
+ if (!is_disk)
+ fprintf(m_output, " size=\"%d\"", rom_file_size(rom));
+
+ // dump checksum information only if there is a known dump
+ if (!hashes.flag(hash_collection::FLAG_NO_DUMP))
+ {
+ // iterate over hash function types and print m_output their values
+ astring tempstr;
+ for (hash_base *hash = hashes.first(); hash != NULL; hash = hash->next())
+ fprintf(m_output, " %s=\"%s\"", hash->name(), hash->string(tempstr));
+ }
+
+ // append a region name
+ fprintf(m_output, " region=\"%s\"", ROMREGION_GETTAG(region));
+
+ // add nodump/baddump flags
+ if (hashes.flag(hash_collection::FLAG_NO_DUMP))
+ fprintf(m_output, " status=\"nodump\"");
+ if (hashes.flag(hash_collection::FLAG_BAD_DUMP))
+ fprintf(m_output, " status=\"baddump\"");
+
+ // for non-disk entries, print offset
+ if (!is_disk)
+ fprintf(m_output, " offset=\"%x\"", offset);
+
+ // for disk entries, add the disk index
+ else
+ {
+ fprintf(m_output, " index=\"%x\"", DISK_GETINDEX(rom));
+ fprintf(m_output, " writable=\"%s\"", DISK_ISREADONLY(rom) ? "no" : "yes");
+ }
+
+ // add optional flag
+ if ((!is_disk && ROM_ISOPTIONAL(rom)) || (is_disk && DISK_ISOPTIONAL(rom)))
+ fprintf(m_output, " optional=\"yes\"");
+
+ fprintf(m_output, "/>\n");
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// output_sample - print a list of all
+// samples referenced by a game_driver
+//-------------------------------------------------
+
+void info_xml_creator::output_sample()
+{
+ // iterate over sample devices
+ for (const device_t *device = m_drivlist.config().devicelist().first(SAMPLES); device != NULL; device = device->typenext())
+ {
+ const char *const *samplenames = ((const samples_interface *)device->static_config())->samplenames;
+ if (samplenames != NULL)
+
+ // iterate over sample names
+ for (int sampnum = 0; samplenames[sampnum] != NULL; sampnum++)
+ {
+ // ignore the special '*' samplename
+ const char *cursampname = samplenames[sampnum];
+ if (sampnum == 0 && cursampname[0] == '*')
+ continue;
+
+ // filter m_output duplicates
+ int dupnum;
+ for (dupnum = 0; dupnum < sampnum; dupnum++)
+ if (strcmp(samplenames[dupnum], cursampname) == 0)
+ break;
+ if (dupnum < sampnum)
+ continue;
+
+ // output the sample name
+ fprintf(m_output, "\t\t<sample name=\"%s\"/>\n", xml_normalize_string(cursampname));
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ output_chips - print a list of CPU and
+ sound chips used by a game
+-------------------------------------------------*/
+
+void info_xml_creator::output_chips()
+{
+ // iterate over executable devices
+ device_execute_interface *exec = NULL;
+ for (bool gotone = m_drivlist.config().devicelist().first(exec); gotone; gotone = exec->next(exec))
+ {
+ fprintf(m_output, "\t\t<chip");
+ fprintf(m_output, " type=\"cpu\"");
+ fprintf(m_output, " tag=\"%s\"", xml_normalize_string(exec->device().tag()));
+ fprintf(m_output, " name=\"%s\"", xml_normalize_string(exec->device().name()));
+ fprintf(m_output, " clock=\"%d\"", exec->device().clock());
+ fprintf(m_output, "/>\n");
+ }
+
+ // iterate over sound devices
+ device_sound_interface *sound = NULL;
+ for (bool gotone = m_drivlist.config().devicelist().first(sound); gotone; gotone = sound->next(sound))
+ {
+ fprintf(m_output, "\t\t<chip");
+ fprintf(m_output, " type=\"audio\"");
+ fprintf(m_output, " tag=\"%s\"", xml_normalize_string(sound->device().tag()));
+ fprintf(m_output, " name=\"%s\"", xml_normalize_string(sound->device().name()));
+ if (sound->device().clock() != 0)
+ fprintf(m_output, " clock=\"%d\"", sound->device().clock());
+ fprintf(m_output, "/>\n");
+ }
+}
+
+
+//-------------------------------------------------
+// output_display - print a list of all the
+// displays
+//-------------------------------------------------
+
+void info_xml_creator::output_display()
+{
+ // iterate over screens
+ for (const screen_device *device = m_drivlist.config().first_screen(); device != NULL; device = device->next_screen())
+ {
+ fprintf(m_output, "\t\t<display");
+
+ switch (device->screen_type())
+ {
+ case SCREEN_TYPE_RASTER: fprintf(m_output, " type=\"raster\""); break;
+ case SCREEN_TYPE_VECTOR: fprintf(m_output, " type=\"vector\""); break;
+ case SCREEN_TYPE_LCD: fprintf(m_output, " type=\"lcd\""); break;
+ default: fprintf(m_output, " type=\"unknown\""); break;
+ }
+
+ // output the orientation as a string
+ switch (m_drivlist.driver().flags & ORIENTATION_MASK)
+ {
+ case ORIENTATION_FLIP_X:
+ fprintf(m_output, " rotate=\"0\" flipx=\"yes\"");
+ break;
+ case ORIENTATION_FLIP_Y:
+ fprintf(m_output, " rotate=\"180\" flipx=\"yes\"");
+ break;
+ case ORIENTATION_FLIP_X|ORIENTATION_FLIP_Y:
+ fprintf(m_output, " rotate=\"180\"");
+ break;
+ case ORIENTATION_SWAP_XY:
+ fprintf(m_output, " rotate=\"90\" flipx=\"yes\"");
+ break;
+ case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_X:
+ fprintf(m_output, " rotate=\"90\"");
+ break;
+ case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_Y:
+ fprintf(m_output, " rotate=\"270\"");
+ break;
+ case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_X|ORIENTATION_FLIP_Y:
+ fprintf(m_output, " rotate=\"270\" flipx=\"yes\"");
+ break;
+ default:
+ fprintf(m_output, " rotate=\"0\"");
+ break;
+ }
+
+ // output width and height only for games that are not vector
+ if (device->screen_type() != SCREEN_TYPE_VECTOR)
+ {
+ const rectangle &visarea = device->visible_area();
+ fprintf(m_output, " width=\"%d\"", visarea.max_x - visarea.min_x + 1);
+ fprintf(m_output, " height=\"%d\"", visarea.max_y - visarea.min_y + 1);
+ }
+
+ // output refresh rate
+ fprintf(m_output, " refresh=\"%f\"", ATTOSECONDS_TO_HZ(device->refresh_attoseconds()));
+
+ // output raw video parameters only for games that are not vector
+ // and had raw parameters specified
+ if (device->screen_type() != SCREEN_TYPE_VECTOR && !device->oldstyle_vblank_supplied())
+ {
+ int pixclock = device->width() * device->height() * ATTOSECONDS_TO_HZ(device->refresh_attoseconds());
+
+ fprintf(m_output, " pixclock=\"%d\"", pixclock);
+ fprintf(m_output, " htotal=\"%d\"", device->width());
+ fprintf(m_output, " hbend=\"%d\"", device->visible_area().min_x);
+ fprintf(m_output, " hbstart=\"%d\"", device->visible_area().max_x+1);
+ fprintf(m_output, " vtotal=\"%d\"", device->height());
+ fprintf(m_output, " vbend=\"%d\"", device->visible_area().min_y);
+ fprintf(m_output, " vbstart=\"%d\"", device->visible_area().max_y+1);
+ }
+ fprintf(m_output, " />\n");
+ }
+}
+
+
+//-------------------------------------------------
+// output_sound - print a list of all the
+// displays
+//------------------------------------------------
+
+void info_xml_creator::output_sound()
+{
+ int speakers = m_drivlist.config().devicelist().count(SPEAKER);
+
+ // if we have no sound, zero m_output the speaker count
+ const device_sound_interface *sound = NULL;
+ if (!m_drivlist.config().devicelist().first(sound))
+ speakers = 0;
+
+ fprintf(m_output, "\t\t<sound channels=\"%d\"/>\n", speakers);
+}
+
+
+//-------------------------------------------------
+// output_input - print a summary of a game's
+// input
+//-------------------------------------------------
+
+void info_xml_creator::output_input(const ioport_list &portlist)
+{
+ // enumerated list of control types
+ enum
+ {
+ ANALOG_TYPE_JOYSTICK,
+ ANALOG_TYPE_DIAL,
+ ANALOG_TYPE_TRACKBALL,
+ ANALOG_TYPE_PADDLE,
+ ANALOG_TYPE_LIGHTGUN,
+ ANALOG_TYPE_PEDAL,
+ ANALOG_TYPE_COUNT
+ };
+
+ // directions
+ const UINT8 DIR_LEFTRIGHT = 0x01;
+ const UINT8 DIR_UPDOWN = 0x02;
+ const UINT8 DIR_4WAY = 0x04;
+ const UINT8 DIR_DUAL = 0x08;
+
+ // initialize the list of control types
+ struct
+ {
+ const char * type; /* general type of input */
+ bool analog;
+ bool keyb;
+ INT32 min; /* analog minimum value */
+ INT32 max; /* analog maximum value */
+ INT32 sensitivity; /* default analog sensitivity */
+ INT32 keydelta; /* default analog keydelta */
+ bool reverse; /* default analog reverse setting */
+ } control_info[ANALOG_TYPE_COUNT];
+
+ memset(&control_info, 0, sizeof(control_info));
+
+ // tracking info as we iterate
+ int nplayer = 0;
+ int nbutton = 0;
+ int ncoin = 0;
+ UINT8 joytype = 0;
+ bool service = false;
+ bool tilt = false;
+ bool keypad = false;
+ bool keyboard = false;
+
+ // iterate over the ports
+ for (input_port_config *port = portlist.first(); port != NULL; port = port->next())
+ for (input_field_config *field = port->fieldlist().first(); field != NULL; field = field->next())
+ {
+ int analogtype = -1;
+
+ // track the highest player number
+ if (nplayer < field->player + 1)
+ nplayer = field->player + 1;
+
+ // switch off of the type
+ switch (field->type)
+ {
+ // map which joystick directions are present
+ case IPT_JOYSTICKRIGHT_LEFT:
+ case IPT_JOYSTICKRIGHT_RIGHT:
+ case IPT_JOYSTICKLEFT_LEFT:
+ case IPT_JOYSTICKLEFT_RIGHT:
+ joytype |= DIR_DUAL;
+ // fall through...
+
+ case IPT_JOYSTICK_LEFT:
+ case IPT_JOYSTICK_RIGHT:
+ joytype |= DIR_LEFTRIGHT | ((field->way == 4) ? DIR_4WAY : 0);
+ break;
+
+ case IPT_JOYSTICKRIGHT_UP:
+ case IPT_JOYSTICKRIGHT_DOWN:
+ case IPT_JOYSTICKLEFT_UP:
+ case IPT_JOYSTICKLEFT_DOWN:
+ joytype |= DIR_DUAL;
+ // fall through...
+
+ case IPT_JOYSTICK_UP:
+ case IPT_JOYSTICK_DOWN:
+ joytype |= DIR_UPDOWN | ((field->way == 4) ? DIR_4WAY : 0);
+ break;
+
+ // mark as an analog input, and get analog stats after switch
+ case IPT_PADDLE:
+ control_info[analogtype = ANALOG_TYPE_PADDLE].type = "paddle";
+ break;
+
+ case IPT_DIAL:
+ control_info[analogtype = ANALOG_TYPE_DIAL].type = "dial";
+ analogtype = ANALOG_TYPE_DIAL;
+ break;
+
+ case IPT_TRACKBALL_X:
+ case IPT_TRACKBALL_Y:
+ control_info[analogtype = ANALOG_TYPE_TRACKBALL].type = "trackball";
+ analogtype = ANALOG_TYPE_TRACKBALL;
+ break;
+
+ case IPT_AD_STICK_X:
+ case IPT_AD_STICK_Y:
+ control_info[analogtype = ANALOG_TYPE_JOYSTICK].type = "stick";
+ break;
+
+ case IPT_LIGHTGUN_X:
+ case IPT_LIGHTGUN_Y:
+ control_info[analogtype = ANALOG_TYPE_LIGHTGUN].type = "lightgun";
+ break;
+
+ case IPT_PEDAL:
+ case IPT_PEDAL2:
+ case IPT_PEDAL3:
+ control_info[analogtype = ANALOG_TYPE_PEDAL].type = "pedal";
+ break;
+
+ // track maximum button index
+ case IPT_BUTTON1:
+ case IPT_BUTTON2:
+ case IPT_BUTTON3:
+ case IPT_BUTTON4:
+ case IPT_BUTTON5:
+ case IPT_BUTTON6:
+ case IPT_BUTTON7:
+ case IPT_BUTTON8:
+ case IPT_BUTTON9:
+ case IPT_BUTTON10:
+ case IPT_BUTTON11:
+ case IPT_BUTTON12:
+ case IPT_BUTTON13:
+ case IPT_BUTTON14:
+ case IPT_BUTTON15:
+ case IPT_BUTTON16:
+ nbutton = MAX(nbutton, field->type - IPT_BUTTON1 + 1);
+ break;
+
+ // track maximum coin index
+ case IPT_COIN1:
+ case IPT_COIN2:
+ case IPT_COIN3:
+ case IPT_COIN4:
+ case IPT_COIN5:
+ case IPT_COIN6:
+ case IPT_COIN7:
+ case IPT_COIN8:
+ ncoin = MAX(ncoin, field->type - IPT_COIN1 + 1);
+ break;
+
+ // track presence of these guys
+ case IPT_KEYPAD:
+ keypad = true;
+ break;
+
+ case IPT_KEYBOARD:
+ keyboard = true;
+ break;
+
+ // additional types
+ case IPT_SERVICE:
+ service = true;
+ break;
+
+ case IPT_TILT:
+ tilt = true;
+ break;
+ }
+
+ // get the analog stats
+ if (analogtype != -1)
+ {
+ if (field->min != 0)
+ control_info[analogtype].min = field->min;
+ if (field->max != 0)
+ control_info[analogtype].max = field->max;
+ if (field->sensitivity != 0)
+ control_info[analogtype].sensitivity = field->sensitivity;
+ if (field->delta != 0)
+ control_info[analogtype].keydelta = field->delta;
+ if ((field->flags & ANALOG_FLAG_REVERSE) != 0)
+ control_info[analogtype].reverse = true;
+ }
+ }
+
+ // output the basic info
+ fprintf(m_output, "\t\t<input");
+ fprintf(m_output, " players=\"%d\"", nplayer);
+ if (nbutton != 0)
+ fprintf(m_output, " buttons=\"%d\"", nbutton);
+ if (ncoin != 0)
+ fprintf(m_output, " coins=\"%d\"", ncoin);
+ if (service)
+ fprintf(m_output, " service=\"yes\"");
+ if (tilt)
+ fprintf(m_output, " tilt=\"yes\"");
+ fprintf(m_output, ">\n");
+
+ // output the joystick types
+ if (joytype != 0)
+ {
+ const char *vertical = ((joytype & DIR_LEFTRIGHT) == 0) ? "v" : "";
+ const char *doubletype = ((joytype & DIR_DUAL) != 0) ? "doublejoy" : "joy";
+ const char *way = ((joytype & DIR_LEFTRIGHT) == 0 || (joytype & DIR_UPDOWN) == 0) ? "2way" : ((joytype & DIR_4WAY) != 0) ? "4way" : "8way";
+ fprintf(m_output, "\t\t\t<control type=\"%s%s%s\"/>\n", vertical, doubletype, way);
+ }
+
+ // output analog types
+ for (int type = 0; type < ANALOG_TYPE_COUNT; type++)
+ if (control_info[type].type != NULL)
+ {
+ fprintf(m_output, "\t\t\t<control type=\"%s\"", xml_normalize_string(control_info[type].type));
+ if (control_info[type].min != 0 || control_info[type].max != 0)
+ {
+ fprintf(m_output, " minimum=\"%d\"", control_info[type].min);
+ fprintf(m_output, " maximum=\"%d\"", control_info[type].max);
+ }
+ if (control_info[type].sensitivity != 0)
+ fprintf(m_output, " sensitivity=\"%d\"", control_info[type].sensitivity);
+ if (control_info[type].keydelta != 0)
+ fprintf(m_output, " keydelta=\"%d\"", control_info[type].keydelta);
+ if (control_info[type].reverse)
+ fprintf(m_output, " reverse=\"yes\"");
+
+ fprintf(m_output, "/>\n");
+ }
+
+ // output keypad and keyboard
+ if (keypad)
+ fprintf(m_output, "\t\t\t<control type=\"keypad\"/>\n");
+ if (keyboard)
+ fprintf(m_output, "\t\t\t<control type=\"keyboard\"/>\n");
+
+ fprintf(m_output, "\t\t</input>\n");
+}
+
+
+//-------------------------------------------------
+// output_switches - print the configurations or
+// DIP switch settings
+//-------------------------------------------------
+
+void info_xml_creator::output_switches(const ioport_list &portlist, int type, const char *outertag, const char *innertag)
+{
+ // iterate looking for DIP switches
+ for (input_port_config *port = portlist.first(); port != NULL; port = port->next())
+ for (input_field_config *field = port->fieldlist().first(); field != NULL; field = field->next())
+ if (field->type == type)
+ {
+ // output the switch name information
+ fprintf(m_output, "\t\t<%s name=\"%s\"", outertag, xml_normalize_string(input_field_name(field)));
+ fprintf(m_output, " tag=\"%s\"", xml_normalize_string(field->port().tag()));
+ fprintf(m_output, " mask=\"%u\"", field->mask);
+ fprintf(m_output, ">\n");
+
+ // loop over settings
+ for (input_setting_config *setting = field->settinglist().first(); setting != NULL; setting = setting->next())
+ {
+ fprintf(m_output, "\t\t\t<%s name=\"%s\"", innertag, xml_normalize_string(setting->name));
+ fprintf(m_output, " value=\"%u\"", setting->value);
+ if (setting->value == field->defvalue)
+ fprintf(m_output, " default=\"yes\"");
+ fprintf(m_output, "/>\n");
+ }
+
+ // terminate the switch entry
+ fprintf(m_output, "\t\t</%s>\n", outertag);
+ }
+}
+
+
+//-------------------------------------------------
+// output_adjusters - print the Analog
+// Adjusters for a game
+//-------------------------------------------------
+
+void info_xml_creator::output_adjusters(const ioport_list &portlist)
+{
+ // iterate looking for Adjusters
+ for (input_port_config *port = portlist.first(); port != NULL; port = port->next())
+ for (input_field_config *field = port->fieldlist().first(); field != NULL; field = field->next())
+ if (field->type == IPT_ADJUSTER)
+ fprintf(m_output, "\t\t<adjuster name=\"%s\" default=\"%d\"/>\n", xml_normalize_string(input_field_name(field)), field->defvalue);
+}
+
+
+//-------------------------------------------------
+// output_driver - print driver status
+//-------------------------------------------------
+
+void info_xml_creator::output_driver()
+{
+ fprintf(m_output, "\t\t<driver");
+
+ /* The status entry is an hint for frontend authors */
+ /* to select working and not working games without */
+ /* the need to know all the other status entries. */
+ /* Games marked as status=good are perfectly emulated, games */
+ /* marked as status=imperfect are emulated with only */
+ /* some minor issues, games marked as status=preliminary */
+ /* don't work or have major emulation problems. */
+
+ if (m_drivlist.driver().flags & (GAME_NOT_WORKING | GAME_UNEMULATED_PROTECTION | GAME_NO_SOUND | GAME_WRONG_COLORS))
+ fprintf(m_output, " status=\"preliminary\"");
+ else if (m_drivlist.driver().flags & (GAME_IMPERFECT_COLORS | GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS))
+ fprintf(m_output, " status=\"imperfect\"");
+ else
+ fprintf(m_output, " status=\"good\"");
+
+ if (m_drivlist.driver().flags & GAME_NOT_WORKING)
+ fprintf(m_output, " emulation=\"preliminary\"");
+ else
+ fprintf(m_output, " emulation=\"good\"");
+
+ if (m_drivlist.driver().flags & GAME_WRONG_COLORS)
+ fprintf(m_output, " color=\"preliminary\"");
+ else if (m_drivlist.driver().flags & GAME_IMPERFECT_COLORS)
+ fprintf(m_output, " color=\"imperfect\"");
+ else
+ fprintf(m_output, " color=\"good\"");
+
+ if (m_drivlist.driver().flags & GAME_NO_SOUND)
+ fprintf(m_output, " sound=\"preliminary\"");
+ else if (m_drivlist.driver().flags & GAME_IMPERFECT_SOUND)
+ fprintf(m_output, " sound=\"imperfect\"");
+ else
+ fprintf(m_output, " sound=\"good\"");
+
+ if (m_drivlist.driver().flags & GAME_IMPERFECT_GRAPHICS)
+ fprintf(m_output, " graphic=\"imperfect\"");
+ else
+ fprintf(m_output, " graphic=\"good\"");
+
+ if (m_drivlist.driver().flags & GAME_NO_COCKTAIL)
+ fprintf(m_output, " cocktail=\"preliminary\"");
+
+ if (m_drivlist.driver().flags & GAME_UNEMULATED_PROTECTION)
+ fprintf(m_output, " protection=\"preliminary\"");
+
+ if (m_drivlist.driver().flags & GAME_SUPPORTS_SAVE)
+ fprintf(m_output, " savestate=\"supported\"");
+ else
+ fprintf(m_output, " savestate=\"unsupported\"");
+
+ fprintf(m_output, " palettesize=\"%d\"", m_drivlist.config().m_total_colors);
+
+ fprintf(m_output, "/>\n");
+}
+
+
+//-------------------------------------------------
+// output_images - prints m_output all info on
+// image devices
+//-------------------------------------------------
+
+void info_xml_creator::output_images()
+{
+ const device_image_interface *dev = NULL;
+ for (bool gotone = m_drivlist.config().devicelist().first(dev); gotone; gotone = dev->next(dev))
+ {
+ // print m_output device type
+ fprintf(m_output, "\t\t<device type=\"%s\"", xml_normalize_string(dev->image_type_name()));
+
+ // does this device have a tag?
+ if (dev->device().tag())
+ fprintf(m_output, " tag=\"%s\"", xml_normalize_string(dev->device().tag()));
+
+ // is this device mandatory?
+ if (dev->must_be_loaded())
+ fprintf(m_output, " mandatory=\"1\"");
+
+ if (dev->image_interface() && dev->image_interface()[0])
+ fprintf(m_output, " interface=\"%s\"", xml_normalize_string(dev->image_interface()));
+
+ // close the XML tag
+ fprintf(m_output, ">\n");
+
+ const char *name = dev->instance_name();
+ const char *shortname = dev->brief_instance_name();
+
+ fprintf(m_output, "\t\t\t<instance");
+ fprintf(m_output, " name=\"%s\"", xml_normalize_string(name));
+ fprintf(m_output, " briefname=\"%s\"", xml_normalize_string(shortname));
+ fprintf(m_output, "/>\n");
+
+ astring extensions(dev->file_extensions());
+
+ char *ext = strtok((char *)extensions.cstr(), ",");
+ while (ext != NULL)
+ {
+ fprintf(m_output, "\t\t\t<extension");
+ fprintf(m_output, " name=\"%s\"", xml_normalize_string(ext));
+ fprintf(m_output, "/>\n");
+ ext = strtok(NULL, ",");
+ }
+
+ fprintf(m_output, "\t\t</device>\n");
+ }
+}
+
+
+//-------------------------------------------------
+// output_images - prints all info about slots
+//-------------------------------------------------
+
+void info_xml_creator::output_slots()
+{
+ const device_slot_interface *slot = NULL;
+ for (bool gotone = m_drivlist.config().devicelist().first(slot); gotone; gotone = slot->next(slot))
+ {
+ // print m_output device type
+ fprintf(m_output, "\t\t<slot name=\"%s\">\n", xml_normalize_string(slot->device().tag()));
+
+ /*
+ if (slot->slot_interface()[0])
+ fprintf(m_output, " interface=\"%s\"", xml_normalize_string(slot->slot_interface()));
+ */
+
+ const slot_interface* intf = slot->get_slot_interfaces();
+ for (int i = 0; intf[i].name != NULL; i++)
+ {
+ fprintf(m_output, "\t\t\t<slotoption");
+ fprintf(m_output, " name=\"%s\"", xml_normalize_string(intf[i].name));
+ if (slot->get_default_card(m_drivlist.config().devicelist(), m_drivlist.options()))
+ {
+ if (slot->get_default_card(m_drivlist.config().devicelist(), m_drivlist.options()) == intf[i].name)
+ fprintf(m_output, " default=\"yes\"");
+ }
+ fprintf(m_output, "/>\n");
+ }
+
+ fprintf(m_output, "\t\t</slot>\n");
+ }
+}
+
+
+//-------------------------------------------------
+// output_software_list - print the information
+// for all known software lists for this system
+//-------------------------------------------------
+
+void info_xml_creator::output_software_list()
+{
+ 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 i = 0; i < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; i++)
+ if (swlist->list_name[i])
+ {
+ fprintf(m_output, "\t\t<softwarelist name=\"%s\" ", swlist->list_name[i]);
+ fprintf(m_output, "status=\"%s\" />\n", (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM) ? "original" : "compatible");
+ }
+ }
+}
+
+
+
+//-------------------------------------------------
+// output_ramoptions - prints m_output all RAM
+// options for this system
+//-------------------------------------------------
+
+void info_xml_creator::output_ramoptions()
+{
+ for (const device_t *device = m_drivlist.config().devicelist().first(RAM); device != NULL; device = device->typenext())
+ {
+ ram_config *ram = (ram_config *)downcast<const legacy_device_base *>(device)->inline_config();
+ fprintf(m_output, "\t\t<ramoption default=\"1\">%u</ramoption>\n", ram_parse_string(ram->default_size));
+
+ if (ram->extra_options != NULL)
+ {
+ astring options(ram->extra_options);
+ for (int start = 0, end = options.chr(0, ','); ; start = end + 1, end = options.chr(start, ','))
+ {
+ astring option;
+ option.cpysubstr(options, start, (end == -1) ? -1 : end - start);
+ fprintf(m_output, "\t\t<ramoption>%u</ramoption>\n", ram_parse_string(option));
+ if (end == -1)
+ break;
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// get_merge_name - get the rom name from a
+// parent set
+//-------------------------------------------------
+
+const char *info_xml_creator::get_merge_name(const hash_collection &romhashes)
+{
+ const char *merge_name = NULL;
+
+ // walk the parent chain
+ for (int clone_of = m_drivlist.find(m_drivlist.driver().parent); clone_of != -1; clone_of = m_drivlist.find(m_drivlist.driver(clone_of).parent))
+
+ // look in the parent's ROMs
+ for (const rom_source *psource = rom_first_source(m_drivlist.config(clone_of)); psource != NULL; psource = rom_next_source(*psource))
+ for (const rom_entry *pregion = rom_first_region(*psource); pregion != NULL; pregion = rom_next_region(pregion))
+ for (const rom_entry *prom = rom_first_file(pregion); prom != NULL; prom = rom_next_file(prom))
+ {
+ hash_collection phashes(ROM_GETHASHDATA(prom));
+ if (!phashes.flag(hash_collection::FLAG_NO_DUMP) && romhashes == phashes)
+ {
+ // stop when we find a match
+ merge_name = ROM_GETNAME(prom);
+ break;
+ }
+ }
+
+ return merge_name;
+}
diff --git a/trunk/src/emu/info.h b/trunk/src/emu/info.h
new file mode 100644
index 00000000000..41d6443e556
--- /dev/null
+++ b/trunk/src/emu/info.h
@@ -0,0 +1,94 @@
+/***************************************************************************
+
+ info.h
+
+ Dumps the MAME internal data as an XML file.
+
+****************************************************************************
+
+ 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 __INFO_H__
+#define __INFO_H__
+
+
+//**************************************************************************
+// FUNCTION PROTOTYPES
+//**************************************************************************
+
+// helper class to putput
+class info_xml_creator
+{
+public:
+ // construction/destruction
+ info_xml_creator(driver_enumerator &drivlist);
+
+ // output
+ void output(FILE *out);
+
+private:
+ // internal helper
+ void output_one();
+ void output_sampleof();
+ void output_bios();
+ void output_rom(const rom_source *source);
+ void output_device_roms();
+ void output_sample();
+ void output_chips();
+ void output_display();
+ void output_sound();
+ void output_input(const ioport_list &portlist);
+ void output_switches(const ioport_list &portlist, int type, const char *outertag, const char *innertag);
+ void output_adjusters(const ioport_list &portlist);
+ void output_categories(const ioport_list &portlist);
+ void output_driver();
+ void output_images();
+ void output_slots();
+ void output_software_list();
+ void output_ramoptions();
+
+ void output_devices();
+
+ const char *get_merge_name(const hash_collection &romhashes);
+
+ // internal state
+ FILE * m_output;
+ driver_enumerator & m_drivlist;
+ UINT8 * m_device_used;
+
+ static const char s_dtd_string[];
+};
+
+
+#endif /* __INFO_H__ */
diff --git a/trunk/src/emu/inpttype.h b/trunk/src/emu/inpttype.h
new file mode 100644
index 00000000000..a4f9c8cc514
--- /dev/null
+++ b/trunk/src/emu/inpttype.h
@@ -0,0 +1,672 @@
+/***************************************************************************
+
+ inpttype.h
+
+ Array of core-defined input types and default mappings.
+
+****************************************************************************
+
+ 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.
+
+***************************************************************************/
+
+
+/***************************************************************************
+ BUILT-IN CORE MAPPINGS
+***************************************************************************/
+
+#define INPUT_PORT_DIGITAL_TYPE(_player,_group,_type,_name,_seq) \
+ typelist.append(*global_alloc(input_type_entry(IPT_##_type, IPG_##_group, (_player == 0) ? _player : (_player) - 1, (_player == 0) ? #_type : ("P" #_player "_" #_type), _name, _seq)));
+
+#define INPUT_PORT_ANALOG_TYPE(_player,_group,_type,_name,_seq,_decseq,_incseq) \
+ typelist.append(*global_alloc(input_type_entry(IPT_##_type, IPG_##_group, (_player == 0) ? _player : (_player) - 1, (_player == 0) ? #_type : ("P" #_player "_" #_type), _name, _seq, _decseq, _incseq)));
+
+
+void construct_core_types(simple_list<input_type_entry> &typelist)
+{
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICK_UP, "P1 Up", input_seq(KEYCODE_UP, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICK_DOWN, "P1 Down", input_seq(KEYCODE_DOWN, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICK_LEFT, "P1 Left", input_seq(KEYCODE_LEFT, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICK_RIGHT, "P1 Right", input_seq(KEYCODE_RIGHT, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKRIGHT_UP, "P1 Right/Up", input_seq(KEYCODE_I, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKRIGHT_DOWN, "P1 Right/Down", input_seq(KEYCODE_K, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKRIGHT_LEFT, "P1 Right/Left", input_seq(KEYCODE_J, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKRIGHT_RIGHT, "P1 Right/Right", input_seq(KEYCODE_L, input_seq::or_code, JOYCODE_BUTTON4_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKLEFT_UP, "P1 Left/Up", input_seq(KEYCODE_E, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKLEFT_DOWN, "P1 Left/Down", input_seq(KEYCODE_D, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKLEFT_LEFT, "P1 Left/Left", input_seq(KEYCODE_S, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICKLEFT_RIGHT, "P1 Left/Right", input_seq(KEYCODE_F, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON1, "P1 Button 1", input_seq(KEYCODE_LCONTROL, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(0), input_seq::or_code, MOUSECODE_BUTTON1_INDEXED(0), input_seq::or_code, GUNCODE_BUTTON1_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON2, "P1 Button 2", input_seq(KEYCODE_LALT, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(0), input_seq::or_code, MOUSECODE_BUTTON3_INDEXED(0), input_seq::or_code, GUNCODE_BUTTON2_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON3, "P1 Button 3", input_seq(KEYCODE_SPACE, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(0), input_seq::or_code, MOUSECODE_BUTTON2_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON4, "P1 Button 4", input_seq(KEYCODE_LSHIFT, input_seq::or_code, JOYCODE_BUTTON4_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON5, "P1 Button 5", input_seq(KEYCODE_Z, input_seq::or_code, JOYCODE_BUTTON5_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON6, "P1 Button 6", input_seq(KEYCODE_X, input_seq::or_code, JOYCODE_BUTTON6_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON7, "P1 Button 7", input_seq(KEYCODE_C, input_seq::or_code, JOYCODE_BUTTON7_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON8, "P1 Button 8", input_seq(KEYCODE_V, input_seq::or_code, JOYCODE_BUTTON8_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON9, "P1 Button 9", input_seq(KEYCODE_B, input_seq::or_code, JOYCODE_BUTTON9_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON10, "P1 Button 10", input_seq(KEYCODE_N, input_seq::or_code, JOYCODE_BUTTON10_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON11, "P1 Button 11", input_seq(KEYCODE_M, input_seq::or_code, JOYCODE_BUTTON11_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON12, "P1 Button 12", input_seq(KEYCODE_COMMA, input_seq::or_code, JOYCODE_BUTTON12_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON13, "P1 Button 13", input_seq(KEYCODE_STOP, input_seq::or_code, JOYCODE_BUTTON13_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON14, "P1 Button 14", input_seq(KEYCODE_SLASH, input_seq::or_code, JOYCODE_BUTTON14_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON15, "P1 Button 15", input_seq(KEYCODE_RSHIFT, input_seq::or_code, JOYCODE_BUTTON15_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, BUTTON16, "P1 Button 16", input_seq(JOYCODE_BUTTON16_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, START, "P1 Start", input_seq(KEYCODE_1, input_seq::or_code, JOYCODE_START_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, SELECT, "P1 Select", input_seq(KEYCODE_5, input_seq::or_code, JOYCODE_SELECT_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_A, "P1 Mahjong A", input_seq(KEYCODE_A) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_B, "P1 Mahjong B", input_seq(KEYCODE_B) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_C, "P1 Mahjong C", input_seq(KEYCODE_C) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_D, "P1 Mahjong D", input_seq(KEYCODE_D) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_E, "P1 Mahjong E", input_seq(KEYCODE_E) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_F, "P1 Mahjong F", input_seq(KEYCODE_F) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_G, "P1 Mahjong G", input_seq(KEYCODE_G) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_H, "P1 Mahjong H", input_seq(KEYCODE_H) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_I, "P1 Mahjong I", input_seq(KEYCODE_I) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_J, "P1 Mahjong J", input_seq(KEYCODE_J) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_K, "P1 Mahjong K", input_seq(KEYCODE_K) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_L, "P1 Mahjong L", input_seq(KEYCODE_L) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_M, "P1 Mahjong M", input_seq(KEYCODE_M) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_N, "P1 Mahjong N", input_seq(KEYCODE_N) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_O, "P1 Mahjong O", input_seq(KEYCODE_O) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_P, "P1 Mahjong P", input_seq(KEYCODE_COLON) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_Q, "P1 Mahjong Q", input_seq(KEYCODE_Q) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_KAN, "P1 Mahjong Kan", input_seq(KEYCODE_LCONTROL) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_PON, "P1 Mahjong Pon", input_seq(KEYCODE_LALT) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_CHI, "P1 Mahjong Chi", input_seq(KEYCODE_SPACE) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_REACH, "P1 Mahjong Reach", input_seq(KEYCODE_LSHIFT) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_RON, "P1 Mahjong Ron", input_seq(KEYCODE_Z) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_BET, "P1 Mahjong Bet", input_seq(KEYCODE_3) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_LAST_CHANCE, "P1 Mahjong Last Chance", input_seq(KEYCODE_RALT) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_SCORE, "P1 Mahjong Score", input_seq(KEYCODE_RCONTROL) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_DOUBLE_UP, "P1 Mahjong Double Up", input_seq(KEYCODE_RSHIFT) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_FLIP_FLOP, "P1 Mahjong Flip Flop", input_seq(KEYCODE_Y) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_BIG, "P1 Mahjong Big", input_seq(KEYCODE_ENTER) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, MAHJONG_SMALL, "P1 Mahjong Small", input_seq(KEYCODE_BACKSPACE) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_A, "P1 Hanafuda A / 1", input_seq(KEYCODE_A) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_B, "P1 Hanafuda B / 2", input_seq(KEYCODE_B) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_C, "P1 Hanafuda C / 3", input_seq(KEYCODE_C) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_D, "P1 Hanafuda D / 4", input_seq(KEYCODE_D) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_E, "P1 Hanafuda E / 5", input_seq(KEYCODE_E) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_F, "P1 Hanafuda F / 6", input_seq(KEYCODE_F) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_G, "P1 Hanafuda G / 7", input_seq(KEYCODE_G) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_H, "P1 Hanafuda H / 8", input_seq(KEYCODE_H) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_YES, "P1 Hanafuda Yes", input_seq(KEYCODE_M) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, HANAFUDA_NO, "P1 Hanafuda No", input_seq(KEYCODE_N) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, GAMBLE_HIGH, "High", input_seq(KEYCODE_A) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, GAMBLE_LOW, "Low", input_seq(KEYCODE_S) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, GAMBLE_HALF, "Half Gamble", input_seq(KEYCODE_D) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, GAMBLE_DEAL, "Deal", input_seq(KEYCODE_2) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, GAMBLE_D_UP, "Double Up", input_seq(KEYCODE_3) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, GAMBLE_TAKE, "Take", input_seq(KEYCODE_4) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, GAMBLE_STAND, "Stand", input_seq(KEYCODE_L) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, GAMBLE_BET, "Bet", input_seq(KEYCODE_M) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, GAMBLE_KEYIN, "Key In", input_seq(KEYCODE_Q) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, GAMBLE_KEYOUT, "Key Out", input_seq(KEYCODE_W) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, GAMBLE_PAYOUT, "Payout", input_seq(KEYCODE_I) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, GAMBLE_DOOR, "Door", input_seq(KEYCODE_O) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, GAMBLE_SERVICE, "Service", input_seq(KEYCODE_9) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, GAMBLE_BOOK, "Book-Keeping", input_seq(KEYCODE_0) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, POKER_HOLD1, "Hold 1", input_seq(KEYCODE_Z) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, POKER_HOLD2, "Hold 2", input_seq(KEYCODE_X) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, POKER_HOLD3, "Hold 3", input_seq(KEYCODE_C) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, POKER_HOLD4, "Hold 4", input_seq(KEYCODE_V) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, POKER_HOLD5, "Hold 5", input_seq(KEYCODE_B) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, POKER_CANCEL, "Cancel", input_seq(KEYCODE_N) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, POKER_BET, "Bet", input_seq(KEYCODE_1) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, SLOT_STOP1, "Stop Reel 1", input_seq(KEYCODE_X) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, SLOT_STOP2, "Stop Reel 2", input_seq(KEYCODE_C) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, SLOT_STOP3, "Stop Reel 3", input_seq(KEYCODE_V) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, SLOT_STOP4, "Stop Reel 4", input_seq(KEYCODE_B) )
+ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, SLOT_STOP_ALL, "Stop All Reels", input_seq(KEYCODE_Z) )
+
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICK_UP, "P2 Up", input_seq(KEYCODE_R, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(1)) )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICK_DOWN, "P2 Down", input_seq(KEYCODE_F, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(1)) )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICK_LEFT, "P2 Left", input_seq(KEYCODE_D, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(1)) )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICK_RIGHT, "P2 Right", input_seq(KEYCODE_G, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(1)) )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKRIGHT_UP, "P2 Right/Up", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKRIGHT_DOWN, "P2 Right/Down", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKRIGHT_LEFT, "P2 Right/Left", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKRIGHT_RIGHT, "P2 Right/Right", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKLEFT_UP, "P2 Left/Up", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKLEFT_DOWN, "P2 Left/Down", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKLEFT_LEFT, "P2 Left/Left", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, JOYSTICKLEFT_RIGHT, "P2 Left/Right", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON1, "P2 Button 1", input_seq(KEYCODE_A, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(1), input_seq::or_code, MOUSECODE_BUTTON1_INDEXED(1), input_seq::or_code, GUNCODE_BUTTON1_INDEXED(1)) )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON2, "P2 Button 2", input_seq(KEYCODE_S, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(1), input_seq::or_code, MOUSECODE_BUTTON3_INDEXED(1), input_seq::or_code, GUNCODE_BUTTON2_INDEXED(1)) )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON3, "P2 Button 3", input_seq(KEYCODE_Q, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(1), input_seq::or_code, MOUSECODE_BUTTON2_INDEXED(1)) )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON4, "P2 Button 4", input_seq(KEYCODE_W, input_seq::or_code, JOYCODE_BUTTON4_INDEXED(1)) )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON5, "P2 Button 5", input_seq(JOYCODE_BUTTON5_INDEXED(1)) )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON6, "P2 Button 6", input_seq(JOYCODE_BUTTON6_INDEXED(1)) )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON7, "P2 Button 7", input_seq(JOYCODE_BUTTON7_INDEXED(1)) )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON8, "P2 Button 8", input_seq(JOYCODE_BUTTON8_INDEXED(1)) )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON9, "P2 Button 9", input_seq(JOYCODE_BUTTON9_INDEXED(1)) )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON10, "P2 Button 10", input_seq(JOYCODE_BUTTON10_INDEXED(1)) )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON11, "P2 Button 11", input_seq(JOYCODE_BUTTON11_INDEXED(1)) )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON12, "P2 Button 12", input_seq(JOYCODE_BUTTON12_INDEXED(1)) )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON13, "P2 Button 13", input_seq(JOYCODE_BUTTON13_INDEXED(1)) )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON14, "P2 Button 14", input_seq(JOYCODE_BUTTON14_INDEXED(1)) )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON15, "P2 Button 15", input_seq(JOYCODE_BUTTON15_INDEXED(1)) )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, BUTTON16, "P2 Button 16", input_seq(JOYCODE_BUTTON16_INDEXED(1)) )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, START, "P2 Start", input_seq(KEYCODE_2, input_seq::or_code, JOYCODE_START_INDEXED(1)) )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, SELECT, "P2 Select", input_seq(KEYCODE_6, input_seq::or_code, JOYCODE_SELECT_INDEXED(1)) )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_A, "P2 Mahjong A", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_B, "P2 Mahjong B", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_C, "P2 Mahjong C", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_D, "P2 Mahjong D", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_E, "P2 Mahjong E", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_F, "P2 Mahjong F", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_G, "P2 Mahjong G", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_H, "P2 Mahjong H", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_I, "P2 Mahjong I", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_J, "P2 Mahjong J", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_K, "P2 Mahjong K", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_L, "P2 Mahjong L", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_M, "P2 Mahjong M", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_N, "P2 Mahjong N", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_O, "P2 Mahjong O", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_P, "P2 Mahjong P", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_Q, "P2 Mahjong Q", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_KAN, "P2 Mahjong Kan", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_PON, "P2 Mahjong Pon", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_CHI, "P2 Mahjong Chi", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_REACH, "P2 Mahjong Reach", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_RON, "P2 Mahjong Ron", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_BET, "P2 Mahjong Bet", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_LAST_CHANCE, "P2 Mahjong Last Chance", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_SCORE, "P2 Mahjong Score", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_DOUBLE_UP, "P2 Mahjong Double Up", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_FLIP_FLOP, "P2 Mahjong Flip Flop", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_BIG, "P2 Mahjong Big", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, MAHJONG_SMALL, "P2 Mahjong Small", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_A, "P2 Hanafuda A / 1", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_B, "P2 Hanafuda B / 2", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_C, "P2 Hanafuda C / 3", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_D, "P2 Hanafuda D / 4", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_E, "P2 Hanafuda E / 5", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_F, "P2 Hanafuda F / 6", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_G, "P2 Hanafuda G / 7", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_H, "P2 Hanafuda H / 8", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_YES, "P2 Hanafuda Yes", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 2, PLAYER2, HANAFUDA_NO, "P2 Hanafuda No", input_seq() )
+
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICK_UP, "P3 Up", input_seq(KEYCODE_I, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(2)) )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICK_DOWN, "P3 Down", input_seq(KEYCODE_K, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(2)) )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICK_LEFT, "P3 Left", input_seq(KEYCODE_J, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(2)) )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICK_RIGHT, "P3 Right", input_seq(KEYCODE_L, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(2)) )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKRIGHT_UP, "P3 Right/Up", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKRIGHT_DOWN, "P3 Right/Down", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKRIGHT_LEFT, "P3 Right/Left", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKRIGHT_RIGHT, "P3 Right/Right", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKLEFT_UP, "P3 Left/Up", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKLEFT_DOWN, "P3 Left/Down", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKLEFT_LEFT, "P3 Left/Left", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, JOYSTICKLEFT_RIGHT, "P3 Left/Right", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON1, "P3 Button 1", input_seq(KEYCODE_RCONTROL, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(2), input_seq::or_code, GUNCODE_BUTTON1_INDEXED(2)) )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON2, "P3 Button 2", input_seq(KEYCODE_RSHIFT, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(2), input_seq::or_code, GUNCODE_BUTTON2_INDEXED(2)) )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON3, "P3 Button 3", input_seq(KEYCODE_ENTER, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(2)) )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON4, "P3 Button 4", input_seq(JOYCODE_BUTTON4_INDEXED(2)) )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON5, "P3 Button 5", input_seq(JOYCODE_BUTTON5_INDEXED(2)) )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON6, "P3 Button 6", input_seq(JOYCODE_BUTTON6_INDEXED(2)) )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON7, "P3 Button 7", input_seq(JOYCODE_BUTTON7_INDEXED(2)) )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON8, "P3 Button 8", input_seq(JOYCODE_BUTTON8_INDEXED(2)) )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON9, "P3 Button 9", input_seq(JOYCODE_BUTTON9_INDEXED(2)) )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON10, "P3 Button 10", input_seq(JOYCODE_BUTTON10_INDEXED(2)) )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON11, "P3 Button 11", input_seq(JOYCODE_BUTTON11_INDEXED(2)) )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON12, "P3 Button 12", input_seq(JOYCODE_BUTTON12_INDEXED(2)) )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON13, "P3 Button 13", input_seq(JOYCODE_BUTTON13_INDEXED(2)) )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON14, "P3 Button 14", input_seq(JOYCODE_BUTTON14_INDEXED(2)) )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON15, "P3 Button 15", input_seq(JOYCODE_BUTTON15_INDEXED(2)) )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, BUTTON16, "P3 Button 16", input_seq(JOYCODE_BUTTON16_INDEXED(2)) )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, START, "P3 Start", input_seq(KEYCODE_3, input_seq::or_code, JOYCODE_START_INDEXED(2)) )
+ INPUT_PORT_DIGITAL_TYPE( 3, PLAYER3, SELECT, "P3 Select", input_seq(KEYCODE_7, input_seq::or_code, JOYCODE_SELECT_INDEXED(2)) )
+
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICK_UP, "P4 Up", input_seq(KEYCODE_8_PAD, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(3)) )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICK_DOWN, "P4 Down", input_seq(KEYCODE_2_PAD, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(3)) )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICK_LEFT, "P4 Left", input_seq(KEYCODE_4_PAD, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(3)) )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICK_RIGHT, "P4 Right", input_seq(KEYCODE_6_PAD, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(3)) )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKRIGHT_UP, "P4 Right/Up", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKRIGHT_DOWN, "P4 Right/Down", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKRIGHT_LEFT, "P4 Right/Left", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKRIGHT_RIGHT, "P4 Right/Right", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKLEFT_UP, "P4 Left/Up", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKLEFT_DOWN, "P4 Left/Down", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKLEFT_LEFT, "P4 Left/Left", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, JOYSTICKLEFT_RIGHT, "P4 Left/Right", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON1, "P4 Button 1", input_seq(KEYCODE_0_PAD, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(3)) )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON2, "P4 Button 2", input_seq(KEYCODE_DEL_PAD, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(3)) )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON3, "P4 Button 3", input_seq(KEYCODE_ENTER_PAD, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(3)) )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON4, "P4 Button 4", input_seq(JOYCODE_BUTTON4_INDEXED(3)) )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON5, "P4 Button 5", input_seq(JOYCODE_BUTTON5_INDEXED(3)) )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON6, "P4 Button 6", input_seq(JOYCODE_BUTTON6_INDEXED(3)) )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON7, "P4 Button 7", input_seq(JOYCODE_BUTTON7_INDEXED(3)) )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON8, "P4 Button 8", input_seq(JOYCODE_BUTTON8_INDEXED(3)) )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON9, "P4 Button 9", input_seq(JOYCODE_BUTTON9_INDEXED(3)) )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON10, "P4 Button 10", input_seq(JOYCODE_BUTTON10_INDEXED(3)) )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON11, "P4 Button 11", input_seq(JOYCODE_BUTTON11_INDEXED(3)) )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON12, "P4 Button 12", input_seq(JOYCODE_BUTTON12_INDEXED(3)) )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON13, "P4 Button 13", input_seq(JOYCODE_BUTTON13_INDEXED(3)) )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON14, "P4 Button 14", input_seq(JOYCODE_BUTTON14_INDEXED(3)) )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON15, "P4 Button 15", input_seq(JOYCODE_BUTTON15_INDEXED(3)) )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, BUTTON16, "P4 Button 16", input_seq(JOYCODE_BUTTON16_INDEXED(3)) )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, START, "P4 Start", input_seq(KEYCODE_4, input_seq::or_code, JOYCODE_START_INDEXED(3)) )
+ INPUT_PORT_DIGITAL_TYPE( 4, PLAYER4, SELECT, "P4 Select", input_seq(KEYCODE_8, input_seq::or_code, JOYCODE_SELECT_INDEXED(3)) )
+
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICK_UP, "P5 Up", input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(4)) )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICK_DOWN, "P5 Down", input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(4)) )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICK_LEFT, "P5 Left", input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(4)) )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICK_RIGHT, "P5 Right", input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(4)) )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKRIGHT_UP, "P5 Right/Up", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKRIGHT_DOWN, "P5 Right/Down", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKRIGHT_LEFT, "P5 Right/Left", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKRIGHT_RIGHT, "P5 Right/Right", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKLEFT_UP, "P5 Left/Up", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKLEFT_DOWN, "P5 Left/Down", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKLEFT_LEFT, "P5 Left/Left", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, JOYSTICKLEFT_RIGHT, "P5 Left/Right", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON1, "P5 Button 1", input_seq(JOYCODE_BUTTON1_INDEXED(4)) )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON2, "P5 Button 2", input_seq(JOYCODE_BUTTON2_INDEXED(4)) )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON3, "P5 Button 3", input_seq(JOYCODE_BUTTON3_INDEXED(4)) )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON4, "P5 Button 4", input_seq(JOYCODE_BUTTON4_INDEXED(4)) )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON5, "P5 Button 5", input_seq(JOYCODE_BUTTON5_INDEXED(4)) )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON6, "P5 Button 6", input_seq(JOYCODE_BUTTON6_INDEXED(4)) )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON7, "P5 Button 7", input_seq(JOYCODE_BUTTON7_INDEXED(4)) )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON8, "P5 Button 8", input_seq(JOYCODE_BUTTON8_INDEXED(4)) )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON9, "P5 Button 9", input_seq(JOYCODE_BUTTON9_INDEXED(4)) )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON10, "P5 Button 10", input_seq(JOYCODE_BUTTON10_INDEXED(4)) )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON11, "P5 Button 11", input_seq(JOYCODE_BUTTON11_INDEXED(4)) )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON12, "P5 Button 12", input_seq(JOYCODE_BUTTON12_INDEXED(4)) )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON13, "P5 Button 13", input_seq(JOYCODE_BUTTON13_INDEXED(4)) )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON14, "P5 Button 14", input_seq(JOYCODE_BUTTON14_INDEXED(4)) )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON15, "P5 Button 15", input_seq(JOYCODE_BUTTON15_INDEXED(4)) )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, BUTTON16, "P5 Button 16", input_seq(JOYCODE_BUTTON16_INDEXED(4)) )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, START, "P5 Start", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 5, PLAYER5, SELECT, "P5 Select", input_seq() )
+
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICK_UP, "P6 Up", input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(5)) )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICK_DOWN, "P6 Down", input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(5)) )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICK_LEFT, "P6 Left", input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(5)) )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICK_RIGHT, "P6 Right", input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(5)) )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKRIGHT_UP, "P6 Right/Up", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKRIGHT_DOWN, "P6 Right/Down", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKRIGHT_LEFT, "P6 Right/Left", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKRIGHT_RIGHT, "P6 Right/Right", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKLEFT_UP, "P6 Left/Up", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKLEFT_DOWN, "P6 Left/Down", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKLEFT_LEFT, "P6 Left/Left", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, JOYSTICKLEFT_RIGHT, "P6 Left/Right", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON1, "P6 Button 1", input_seq(JOYCODE_BUTTON1_INDEXED(5)) )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON2, "P6 Button 2", input_seq(JOYCODE_BUTTON2_INDEXED(5)) )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON3, "P6 Button 3", input_seq(JOYCODE_BUTTON3_INDEXED(5)) )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON4, "P6 Button 4", input_seq(JOYCODE_BUTTON4_INDEXED(5)) )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON5, "P6 Button 5", input_seq(JOYCODE_BUTTON5_INDEXED(5)) )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON6, "P6 Button 6", input_seq(JOYCODE_BUTTON6_INDEXED(5)) )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON7, "P6 Button 7", input_seq(JOYCODE_BUTTON7_INDEXED(5)) )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON8, "P6 Button 8", input_seq(JOYCODE_BUTTON8_INDEXED(5)) )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON9, "P6 Button 9", input_seq(JOYCODE_BUTTON9_INDEXED(5)) )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON10, "P6 Button 10", input_seq(JOYCODE_BUTTON10_INDEXED(5)) )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON11, "P6 Button 11", input_seq(JOYCODE_BUTTON11_INDEXED(5)) )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON12, "P6 Button 12", input_seq(JOYCODE_BUTTON12_INDEXED(5)) )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON13, "P6 Button 13", input_seq(JOYCODE_BUTTON13_INDEXED(5)) )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON14, "P6 Button 14", input_seq(JOYCODE_BUTTON14_INDEXED(5)) )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON15, "P6 Button 15", input_seq(JOYCODE_BUTTON15_INDEXED(5)) )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, BUTTON16, "P6 Button 16", input_seq(JOYCODE_BUTTON16_INDEXED(5)) )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, START, "P6 Start", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 6, PLAYER6, SELECT, "P6 Select", input_seq() )
+
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICK_UP, "P7 Up", input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(6)) )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICK_DOWN, "P7 Down", input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(6)) )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICK_LEFT, "P7 Left", input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(6)) )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICK_RIGHT, "P7 Right", input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(6)) )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKRIGHT_UP, "P7 Right/Up", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKRIGHT_DOWN, "P7 Right/Down", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKRIGHT_LEFT, "P7 Right/Left", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKRIGHT_RIGHT, "P7 Right/Right", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKLEFT_UP, "P7 Left/Up", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKLEFT_DOWN, "P7 Left/Down", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKLEFT_LEFT, "P7 Left/Left", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, JOYSTICKLEFT_RIGHT, "P7 Left/Right", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON1, "P7 Button 1", input_seq(JOYCODE_BUTTON1_INDEXED(6)) )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON2, "P7 Button 2", input_seq(JOYCODE_BUTTON2_INDEXED(6)) )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON3, "P7 Button 3", input_seq(JOYCODE_BUTTON3_INDEXED(6)) )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON4, "P7 Button 4", input_seq(JOYCODE_BUTTON4_INDEXED(6)) )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON5, "P7 Button 5", input_seq(JOYCODE_BUTTON5_INDEXED(6)) )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON6, "P7 Button 6", input_seq(JOYCODE_BUTTON6_INDEXED(6)) )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON7, "P7 Button 7", input_seq(JOYCODE_BUTTON7_INDEXED(6)) )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON8, "P7 Button 8", input_seq(JOYCODE_BUTTON8_INDEXED(6)) )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON9, "P7 Button 9", input_seq(JOYCODE_BUTTON9_INDEXED(6)) )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON10, "P7 Button 10", input_seq(JOYCODE_BUTTON10_INDEXED(6)) )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON11, "P7 Button 11", input_seq(JOYCODE_BUTTON11_INDEXED(6)) )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON12, "P7 Button 12", input_seq(JOYCODE_BUTTON12_INDEXED(6)) )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON13, "P7 Button 13", input_seq(JOYCODE_BUTTON13_INDEXED(6)) )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON14, "P7 Button 14", input_seq(JOYCODE_BUTTON14_INDEXED(6)) )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON15, "P7 Button 15", input_seq(JOYCODE_BUTTON15_INDEXED(6)) )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, BUTTON16, "P7 Button 16", input_seq(JOYCODE_BUTTON16_INDEXED(6)) )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, START, "P7 Start", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 7, PLAYER7, SELECT, "P7 Select", input_seq() )
+
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICK_UP, "P8 Up", input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(7)) )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICK_DOWN, "P8 Down", input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(7)) )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICK_LEFT, "P8 Left", input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(7)) )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICK_RIGHT, "P8 Right", input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(7)) )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKRIGHT_UP, "P8 Right/Up", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKRIGHT_DOWN, "P8 Right/Down", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKRIGHT_LEFT, "P8 Right/Left", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKRIGHT_RIGHT, "P8 Right/Right", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKLEFT_UP, "P8 Left/Up", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKLEFT_DOWN, "P8 Left/Down", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKLEFT_LEFT, "P8 Left/Left", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, JOYSTICKLEFT_RIGHT, "P8 Left/Right", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON1, "P8 Button 1", input_seq(JOYCODE_BUTTON1_INDEXED(7)) )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON2, "P8 Button 2", input_seq(JOYCODE_BUTTON2_INDEXED(7)) )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON3, "P8 Button 3", input_seq(JOYCODE_BUTTON3_INDEXED(7)) )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON4, "P8 Button 4", input_seq(JOYCODE_BUTTON4_INDEXED(7)) )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON5, "P8 Button 5", input_seq(JOYCODE_BUTTON5_INDEXED(7)) )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON6, "P8 Button 6", input_seq(JOYCODE_BUTTON6_INDEXED(7)) )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON7, "P8 Button 7", input_seq(JOYCODE_BUTTON7_INDEXED(7)) )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON8, "P8 Button 8", input_seq(JOYCODE_BUTTON8_INDEXED(7)) )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON9, "P8 Button 9", input_seq(JOYCODE_BUTTON9_INDEXED(7)) )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON10, "P8 Button 10", input_seq(JOYCODE_BUTTON10_INDEXED(7)) )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON11, "P8 Button 11", input_seq(JOYCODE_BUTTON11_INDEXED(7)) )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON12, "P8 Button 12", input_seq(JOYCODE_BUTTON12_INDEXED(7)) )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON13, "P8 Button 13", input_seq(JOYCODE_BUTTON13_INDEXED(7)) )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON14, "P8 Button 14", input_seq(JOYCODE_BUTTON14_INDEXED(7)) )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON15, "P8 Button 15", input_seq(JOYCODE_BUTTON15_INDEXED(7)) )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, BUTTON16, "P8 Button 16", input_seq(JOYCODE_BUTTON16_INDEXED(7)) )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, START, "P8 Start", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 8, PLAYER8, SELECT, "P8 Select", input_seq() )
+
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, START1, "1 Player Start", input_seq(KEYCODE_1, input_seq::or_code, JOYCODE_START_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, START2, "2 Players Start", input_seq(KEYCODE_2, input_seq::or_code, JOYCODE_START_INDEXED(1)) )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, START3, "3 Players Start", input_seq(KEYCODE_3, input_seq::or_code, JOYCODE_START_INDEXED(2)) )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, START4, "4 Players Start", input_seq(KEYCODE_4, input_seq::or_code, JOYCODE_START_INDEXED(3)) )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, START5, "5 Players Start", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, START6, "6 Players Start", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, START7, "7 Players Start", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, START8, "8 Players Start", input_seq() )
+
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN1, "Coin 1", input_seq(KEYCODE_5, input_seq::or_code, JOYCODE_SELECT_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN2, "Coin 2", input_seq(KEYCODE_6, input_seq::or_code, JOYCODE_SELECT_INDEXED(1)) )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN3, "Coin 3", input_seq(KEYCODE_7, input_seq::or_code, JOYCODE_SELECT_INDEXED(2)) )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN4, "Coin 4", input_seq(KEYCODE_8, input_seq::or_code, JOYCODE_SELECT_INDEXED(3)) )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN5, "Coin 5", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN6, "Coin 6", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN7, "Coin 7", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN8, "Coin 8", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN9, "Coin 9", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN10, "Coin 10", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN11, "Coin 11", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, COIN12, "Coin 12", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, BILL1, "Bill 1", input_seq(KEYCODE_BACKSPACE) )
+
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, SERVICE1, "Service 1", input_seq(KEYCODE_9) )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, SERVICE2, "Service 2", input_seq(KEYCODE_0) )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, SERVICE3, "Service 3", input_seq(KEYCODE_MINUS) )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, SERVICE4, "Service 4", input_seq(KEYCODE_EQUALS) )
+
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, TILT1, "Tilt 1", input_seq(KEYCODE_T) )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, TILT2, "Tilt 2", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, TILT3, "Tilt 3", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, TILT4, "Tilt 4", input_seq() )
+
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, SERVICE, "Service", input_seq(KEYCODE_F2) )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, TILT, "Tilt", input_seq(KEYCODE_T) )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, INTERLOCK, "Door Interlock", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, VOLUME_DOWN, "Volume Down", input_seq(KEYCODE_MINUS) )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, VOLUME_UP, "Volume Up", input_seq(KEYCODE_EQUALS) )
+
+ INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, PEDAL, "P1 Pedal 1", input_seq(JOYCODE_Y_NEG_ABSOLUTE_INDEXED(0)), input_seq(), input_seq(KEYCODE_LCONTROL, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(0)) )
+ INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, PEDAL, "P2 Pedal 1", input_seq(JOYCODE_Y_NEG_ABSOLUTE_INDEXED(1)), input_seq(), input_seq(KEYCODE_A, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(1)) )
+ INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, PEDAL, "P3 Pedal 1", input_seq(JOYCODE_Y_NEG_ABSOLUTE_INDEXED(2)), input_seq(), input_seq(KEYCODE_RCONTROL, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(2)) )
+ INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, PEDAL, "P4 Pedal 1", input_seq(JOYCODE_Y_NEG_ABSOLUTE_INDEXED(3)), input_seq(), input_seq(KEYCODE_0_PAD, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(3)) )
+ INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, PEDAL, "P5 Pedal 1", input_seq(JOYCODE_Y_NEG_ABSOLUTE_INDEXED(4)), input_seq(), input_seq(JOYCODE_BUTTON1_INDEXED(4)) )
+ INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, PEDAL, "P6 Pedal 1", input_seq(JOYCODE_Y_NEG_ABSOLUTE_INDEXED(5)), input_seq(), input_seq(JOYCODE_BUTTON1_INDEXED(5)) )
+ INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, PEDAL, "P7 Pedal 1", input_seq(JOYCODE_Y_NEG_ABSOLUTE_INDEXED(6)), input_seq(), input_seq(JOYCODE_BUTTON1_INDEXED(6)) )
+ INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, PEDAL, "P8 Pedal 1", input_seq(JOYCODE_Y_NEG_ABSOLUTE_INDEXED(7)), input_seq(), input_seq(JOYCODE_BUTTON1_INDEXED(7)) )
+
+ INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, PEDAL2, "P1 Pedal 2", input_seq(JOYCODE_Y_POS_ABSOLUTE_INDEXED(0)), input_seq(), input_seq(KEYCODE_LALT, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(0)) )
+ INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, PEDAL2, "P2 Pedal 2", input_seq(JOYCODE_Y_POS_ABSOLUTE_INDEXED(1)), input_seq(), input_seq(KEYCODE_S, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(1)) )
+ INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, PEDAL2, "P3 Pedal 2", input_seq(JOYCODE_Y_POS_ABSOLUTE_INDEXED(2)), input_seq(), input_seq(KEYCODE_RSHIFT, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(2)) )
+ INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, PEDAL2, "P4 Pedal 2", input_seq(JOYCODE_Y_POS_ABSOLUTE_INDEXED(3)), input_seq(), input_seq(KEYCODE_DEL_PAD, input_seq::or_code, JOYCODE_BUTTON2_INDEXED(3)) )
+ INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, PEDAL2, "P5 Pedal 2", input_seq(JOYCODE_Y_POS_ABSOLUTE_INDEXED(4)), input_seq(), input_seq(JOYCODE_BUTTON2_INDEXED(4)) )
+ INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, PEDAL2, "P6 Pedal 2", input_seq(JOYCODE_Y_POS_ABSOLUTE_INDEXED(5)), input_seq(), input_seq(JOYCODE_BUTTON2_INDEXED(5)) )
+ INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, PEDAL2, "P7 Pedal 2", input_seq(JOYCODE_Y_POS_ABSOLUTE_INDEXED(6)), input_seq(), input_seq(JOYCODE_BUTTON2_INDEXED(6)) )
+ INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, PEDAL2, "P8 Pedal 2", input_seq(JOYCODE_Y_POS_ABSOLUTE_INDEXED(7)), input_seq(), input_seq(JOYCODE_BUTTON2_INDEXED(7)) )
+
+ INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, PEDAL3, "P1 Pedal 3", input_seq(), input_seq(), input_seq(KEYCODE_SPACE, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(0)) )
+ INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, PEDAL3, "P2 Pedal 3", input_seq(), input_seq(), input_seq(KEYCODE_Q, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(1)) )
+ INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, PEDAL3, "P3 Pedal 3", input_seq(), input_seq(), input_seq(KEYCODE_ENTER, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(2)) )
+ INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, PEDAL3, "P4 Pedal 3", input_seq(), input_seq(), input_seq(KEYCODE_ENTER_PAD, input_seq::or_code, JOYCODE_BUTTON3_INDEXED(3)) )
+ INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, PEDAL3, "P5 Pedal 3", input_seq(), input_seq(), input_seq(JOYCODE_BUTTON3_INDEXED(4)) )
+ INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, PEDAL3, "P6 Pedal 3", input_seq(), input_seq(), input_seq(JOYCODE_BUTTON3_INDEXED(5)) )
+ INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, PEDAL3, "P7 Pedal 3", input_seq(), input_seq(), input_seq(JOYCODE_BUTTON3_INDEXED(6)) )
+ INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, PEDAL3, "P8 Pedal 3", input_seq(), input_seq(), input_seq(JOYCODE_BUTTON3_INDEXED(7)) )
+
+ INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, PADDLE, "Paddle", input_seq(MOUSECODE_X_INDEXED(0), input_seq::or_code, JOYCODE_X_INDEXED(0)), input_seq(KEYCODE_LEFT, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(0)), input_seq(KEYCODE_RIGHT, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(0)) )
+ INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, PADDLE, "Paddle 2", input_seq(MOUSECODE_X_INDEXED(1), input_seq::or_code, JOYCODE_X_INDEXED(1)), input_seq(KEYCODE_D, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(1)), input_seq(KEYCODE_G, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(1)) )
+ INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, PADDLE, "Paddle 3", input_seq(MOUSECODE_X_INDEXED(2), input_seq::or_code, JOYCODE_X_INDEXED(2)), input_seq(KEYCODE_J, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(2)), input_seq(KEYCODE_L, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(2)) )
+ INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, PADDLE, "Paddle 4", input_seq(MOUSECODE_X_INDEXED(3), input_seq::or_code, JOYCODE_X_INDEXED(3)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(3)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(3)) )
+ INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, PADDLE, "Paddle 5", input_seq(MOUSECODE_X_INDEXED(4), input_seq::or_code, JOYCODE_X_INDEXED(4)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(4)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(4)) )
+ INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, PADDLE, "Paddle 6", input_seq(MOUSECODE_X_INDEXED(5), input_seq::or_code, JOYCODE_X_INDEXED(5)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(5)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(5)) )
+ INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, PADDLE, "Paddle 7", input_seq(MOUSECODE_X_INDEXED(6), input_seq::or_code, JOYCODE_X_INDEXED(6)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(6)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(6)) )
+ INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, PADDLE, "Paddle 8", input_seq(MOUSECODE_X_INDEXED(7), input_seq::or_code, JOYCODE_X_INDEXED(7)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(7)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(7)) )
+
+ INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, PADDLE_V, "Paddle V", input_seq(MOUSECODE_Y_INDEXED(0), input_seq::or_code, JOYCODE_Y_INDEXED(0)), input_seq(KEYCODE_UP, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(0)), input_seq(KEYCODE_DOWN, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(0)) )
+ INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, PADDLE_V, "Paddle V 2", input_seq(MOUSECODE_Y_INDEXED(1), input_seq::or_code, JOYCODE_Y_INDEXED(1)), input_seq(KEYCODE_R, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(1)), input_seq(KEYCODE_F, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(1)) )
+ INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, PADDLE_V, "Paddle V 3", input_seq(MOUSECODE_Y_INDEXED(2), input_seq::or_code, JOYCODE_Y_INDEXED(2)), input_seq(KEYCODE_I, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(2)), input_seq(KEYCODE_K, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(2)) )
+ INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, PADDLE_V, "Paddle V 4", input_seq(MOUSECODE_Y_INDEXED(3), input_seq::or_code, JOYCODE_Y_INDEXED(3)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(3)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(3)) )
+ INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, PADDLE_V, "Paddle V 5", input_seq(MOUSECODE_Y_INDEXED(4), input_seq::or_code, JOYCODE_Y_INDEXED(4)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(4)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(4)) )
+ INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, PADDLE_V, "Paddle V 6", input_seq(MOUSECODE_Y_INDEXED(5), input_seq::or_code, JOYCODE_Y_INDEXED(5)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(5)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(5)) )
+ INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, PADDLE_V, "Paddle V 7", input_seq(MOUSECODE_Y_INDEXED(6), input_seq::or_code, JOYCODE_Y_INDEXED(6)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(6)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(6)) )
+ INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, PADDLE_V, "Paddle V 8", input_seq(MOUSECODE_Y_INDEXED(7), input_seq::or_code, JOYCODE_Y_INDEXED(7)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(7)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(7)) )
+
+ INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, POSITIONAL, "Positional", input_seq(MOUSECODE_X_INDEXED(0), input_seq::or_code, JOYCODE_X_INDEXED(0)), input_seq(KEYCODE_LEFT, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(0)), input_seq(KEYCODE_RIGHT, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(0)) )
+ INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, POSITIONAL, "Positional 2", input_seq(MOUSECODE_X_INDEXED(1), input_seq::or_code, JOYCODE_X_INDEXED(1)), input_seq(KEYCODE_D, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(1)), input_seq(KEYCODE_G, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(1)) )
+ INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, POSITIONAL, "Positional 3", input_seq(MOUSECODE_X_INDEXED(2), input_seq::or_code, JOYCODE_X_INDEXED(2)), input_seq(KEYCODE_J, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(2)), input_seq(KEYCODE_L, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(2)) )
+ INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, POSITIONAL, "Positional 4", input_seq(MOUSECODE_X_INDEXED(3), input_seq::or_code, JOYCODE_X_INDEXED(3)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(3)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(3)) )
+ INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, POSITIONAL, "Positional 5", input_seq(MOUSECODE_X_INDEXED(4), input_seq::or_code, JOYCODE_X_INDEXED(4)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(4)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(4)) )
+ INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, POSITIONAL, "Positional 6", input_seq(MOUSECODE_X_INDEXED(5), input_seq::or_code, JOYCODE_X_INDEXED(5)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(5)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(5)) )
+ INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, POSITIONAL, "Positional 7", input_seq(MOUSECODE_X_INDEXED(6), input_seq::or_code, JOYCODE_X_INDEXED(6)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(6)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(6)) )
+ INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, POSITIONAL, "Positional 8", input_seq(MOUSECODE_X_INDEXED(7), input_seq::or_code, JOYCODE_X_INDEXED(7)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(7)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(7)) )
+
+ INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, POSITIONAL_V, "Positional V", input_seq(MOUSECODE_Y_INDEXED(0), input_seq::or_code, JOYCODE_Y_INDEXED(0)), input_seq(KEYCODE_UP, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(0)), input_seq(KEYCODE_DOWN, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(0)) )
+ INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, POSITIONAL_V, "Positional V 2", input_seq(MOUSECODE_Y_INDEXED(1), input_seq::or_code, JOYCODE_Y_INDEXED(1)), input_seq(KEYCODE_R, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(1)), input_seq(KEYCODE_F, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(1)) )
+ INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, POSITIONAL_V, "Positional V 3", input_seq(MOUSECODE_Y_INDEXED(2), input_seq::or_code, JOYCODE_Y_INDEXED(2)), input_seq(KEYCODE_I, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(2)), input_seq(KEYCODE_K, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(2)) )
+ INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, POSITIONAL_V, "Positional V 4", input_seq(MOUSECODE_Y_INDEXED(3), input_seq::or_code, JOYCODE_Y_INDEXED(3)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(3)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(3)) )
+ INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, POSITIONAL_V, "Positional V 5", input_seq(MOUSECODE_Y_INDEXED(4), input_seq::or_code, JOYCODE_Y_INDEXED(4)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(4)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(4)) )
+ INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, POSITIONAL_V, "Positional V 6", input_seq(MOUSECODE_Y_INDEXED(5), input_seq::or_code, JOYCODE_Y_INDEXED(5)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(5)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(5)) )
+ INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, POSITIONAL_V, "Positional V 7", input_seq(MOUSECODE_Y_INDEXED(6), input_seq::or_code, JOYCODE_Y_INDEXED(6)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(6)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(6)) )
+ INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, POSITIONAL_V, "Positional V 8", input_seq(MOUSECODE_Y_INDEXED(7), input_seq::or_code, JOYCODE_Y_INDEXED(7)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(7)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(7)) )
+
+ INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, DIAL, "Dial", input_seq(MOUSECODE_X_INDEXED(0), input_seq::or_code, JOYCODE_X_INDEXED(0)), input_seq(KEYCODE_LEFT, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(0)), input_seq(KEYCODE_RIGHT, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(0)) )
+ INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, DIAL, "Dial 2", input_seq(MOUSECODE_X_INDEXED(1), input_seq::or_code, JOYCODE_X_INDEXED(1)), input_seq(KEYCODE_D, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(1)), input_seq(KEYCODE_G, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(1)) )
+ INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, DIAL, "Dial 3", input_seq(MOUSECODE_X_INDEXED(2), input_seq::or_code, JOYCODE_X_INDEXED(2)), input_seq(KEYCODE_J, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(2)), input_seq(KEYCODE_L, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(2)) )
+ INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, DIAL, "Dial 4", input_seq(MOUSECODE_X_INDEXED(3), input_seq::or_code, JOYCODE_X_INDEXED(3)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(3)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(3)) )
+ INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, DIAL, "Dial 5", input_seq(MOUSECODE_X_INDEXED(4), input_seq::or_code, JOYCODE_X_INDEXED(4)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(4)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(4)) )
+ INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, DIAL, "Dial 6", input_seq(MOUSECODE_X_INDEXED(5), input_seq::or_code, JOYCODE_X_INDEXED(5)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(5)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(5)) )
+ INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, DIAL, "Dial 7", input_seq(MOUSECODE_X_INDEXED(6), input_seq::or_code, JOYCODE_X_INDEXED(6)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(6)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(6)) )
+ INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, DIAL, "Dial 8", input_seq(MOUSECODE_X_INDEXED(7), input_seq::or_code, JOYCODE_X_INDEXED(7)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(7)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(7)) )
+
+ INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, DIAL_V, "Dial V", input_seq(MOUSECODE_Y_INDEXED(0), input_seq::or_code, JOYCODE_Y_INDEXED(0)), input_seq(KEYCODE_UP, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(0)), input_seq(KEYCODE_DOWN, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(0)) )
+ INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, DIAL_V, "Dial V 2", input_seq(MOUSECODE_Y_INDEXED(1), input_seq::or_code, JOYCODE_Y_INDEXED(1)), input_seq(KEYCODE_R, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(1)), input_seq(KEYCODE_F, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(1)) )
+ INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, DIAL_V, "Dial V 3", input_seq(MOUSECODE_Y_INDEXED(2), input_seq::or_code, JOYCODE_Y_INDEXED(2)), input_seq(KEYCODE_I, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(2)), input_seq(KEYCODE_K, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(2)) )
+ INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, DIAL_V, "Dial V 4", input_seq(MOUSECODE_Y_INDEXED(3), input_seq::or_code, JOYCODE_Y_INDEXED(3)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(3)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(3)) )
+ INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, DIAL_V, "Dial V 5", input_seq(MOUSECODE_Y_INDEXED(4), input_seq::or_code, JOYCODE_Y_INDEXED(4)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(4)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(4)) )
+ INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, DIAL_V, "Dial V 6", input_seq(MOUSECODE_Y_INDEXED(5), input_seq::or_code, JOYCODE_Y_INDEXED(5)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(5)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(5)) )
+ INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, DIAL_V, "Dial V 7", input_seq(MOUSECODE_Y_INDEXED(6), input_seq::or_code, JOYCODE_Y_INDEXED(6)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(6)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(6)) )
+ INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, DIAL_V, "Dial V 8", input_seq(MOUSECODE_Y_INDEXED(7), input_seq::or_code, JOYCODE_Y_INDEXED(7)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(7)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(7)) )
+
+ INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, TRACKBALL_X, "Track X", input_seq(MOUSECODE_X_INDEXED(0), input_seq::or_code, JOYCODE_X_INDEXED(0)), input_seq(KEYCODE_LEFT, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(0)), input_seq(KEYCODE_RIGHT, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(0)) )
+ INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, TRACKBALL_X, "Track X 2", input_seq(MOUSECODE_X_INDEXED(1), input_seq::or_code, JOYCODE_X_INDEXED(1)), input_seq(KEYCODE_D, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(1)), input_seq(KEYCODE_G, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(1)) )
+ INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, TRACKBALL_X, "Track X 3", input_seq(MOUSECODE_X_INDEXED(2), input_seq::or_code, JOYCODE_X_INDEXED(2)), input_seq(KEYCODE_J, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(2)), input_seq(KEYCODE_L, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(2)) )
+ INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, TRACKBALL_X, "Track X 4", input_seq(MOUSECODE_X_INDEXED(3), input_seq::or_code, JOYCODE_X_INDEXED(3)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(3)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(3)) )
+ INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, TRACKBALL_X, "Track X 5", input_seq(MOUSECODE_X_INDEXED(4), input_seq::or_code, JOYCODE_X_INDEXED(4)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(4)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(4)) )
+ INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, TRACKBALL_X, "Track X 6", input_seq(MOUSECODE_X_INDEXED(5), input_seq::or_code, JOYCODE_X_INDEXED(5)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(5)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(5)) )
+ INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, TRACKBALL_X, "Track X 7", input_seq(MOUSECODE_X_INDEXED(6), input_seq::or_code, JOYCODE_X_INDEXED(6)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(6)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(6)) )
+ INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, TRACKBALL_X, "Track X 8", input_seq(MOUSECODE_X_INDEXED(7), input_seq::or_code, JOYCODE_X_INDEXED(7)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(7)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(7)) )
+
+ INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, TRACKBALL_Y, "Track Y", input_seq(MOUSECODE_Y_INDEXED(0), input_seq::or_code, JOYCODE_Y_INDEXED(0)), input_seq(KEYCODE_UP, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(0)), input_seq(KEYCODE_DOWN, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(0)) )
+ INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, TRACKBALL_Y, "Track Y 2", input_seq(MOUSECODE_Y_INDEXED(1), input_seq::or_code, JOYCODE_Y_INDEXED(1)), input_seq(KEYCODE_R, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(1)), input_seq(KEYCODE_F, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(1)) )
+ INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, TRACKBALL_Y, "Track Y 3", input_seq(MOUSECODE_Y_INDEXED(2), input_seq::or_code, JOYCODE_Y_INDEXED(2)), input_seq(KEYCODE_I, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(2)), input_seq(KEYCODE_K, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(2)) )
+ INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, TRACKBALL_Y, "Track Y 4", input_seq(MOUSECODE_Y_INDEXED(3), input_seq::or_code, JOYCODE_Y_INDEXED(3)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(3)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(3)) )
+ INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, TRACKBALL_Y, "Track Y 5", input_seq(MOUSECODE_Y_INDEXED(4), input_seq::or_code, JOYCODE_Y_INDEXED(4)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(4)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(4)) )
+ INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, TRACKBALL_Y, "Track Y 6", input_seq(MOUSECODE_Y_INDEXED(5), input_seq::or_code, JOYCODE_Y_INDEXED(5)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(5)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(5)) )
+ INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, TRACKBALL_Y, "Track Y 7", input_seq(MOUSECODE_Y_INDEXED(6), input_seq::or_code, JOYCODE_Y_INDEXED(6)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(6)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(6)) )
+ INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, TRACKBALL_Y, "Track Y 8", input_seq(MOUSECODE_Y_INDEXED(7), input_seq::or_code, JOYCODE_Y_INDEXED(7)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(7)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(7)) )
+
+ INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, AD_STICK_X, "AD Stick X", input_seq(JOYCODE_X_INDEXED(0), input_seq::or_code, MOUSECODE_X_INDEXED(0)), input_seq(KEYCODE_LEFT, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(0)), input_seq(KEYCODE_RIGHT, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(0)) )
+ INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, AD_STICK_X, "AD Stick X 2", input_seq(JOYCODE_X_INDEXED(1), input_seq::or_code, MOUSECODE_X_INDEXED(1)), input_seq(KEYCODE_D, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(1)), input_seq(KEYCODE_G, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(1)) )
+ INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, AD_STICK_X, "AD Stick X 3", input_seq(JOYCODE_X_INDEXED(2), input_seq::or_code, MOUSECODE_X_INDEXED(2)), input_seq(KEYCODE_J, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(2)), input_seq(KEYCODE_L, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(2)) )
+ INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, AD_STICK_X, "AD Stick X 4", input_seq(JOYCODE_X_INDEXED(3), input_seq::or_code, MOUSECODE_X_INDEXED(3)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(3)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(3)) )
+ INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, AD_STICK_X, "AD Stick X 5", input_seq(JOYCODE_X_INDEXED(4), input_seq::or_code, MOUSECODE_X_INDEXED(4)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(4)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(4)) )
+ INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, AD_STICK_X, "AD Stick X 6", input_seq(JOYCODE_X_INDEXED(5), input_seq::or_code, MOUSECODE_X_INDEXED(5)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(5)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(5)) )
+ INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, AD_STICK_X, "AD Stick X 7", input_seq(JOYCODE_X_INDEXED(6), input_seq::or_code, MOUSECODE_X_INDEXED(6)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(6)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(6)) )
+ INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, AD_STICK_X, "AD Stick X 8", input_seq(JOYCODE_X_INDEXED(7), input_seq::or_code, MOUSECODE_X_INDEXED(7)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(7)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(7)) )
+
+ INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, AD_STICK_Y, "AD Stick Y", input_seq(JOYCODE_Y_INDEXED(0), input_seq::or_code, MOUSECODE_Y_INDEXED(0)), input_seq(KEYCODE_UP, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(0)), input_seq(KEYCODE_DOWN, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(0)) )
+ INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, AD_STICK_Y, "AD Stick Y 2", input_seq(JOYCODE_Y_INDEXED(1), input_seq::or_code, MOUSECODE_Y_INDEXED(1)), input_seq(KEYCODE_R, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(1)), input_seq(KEYCODE_F, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(1)) )
+ INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, AD_STICK_Y, "AD Stick Y 3", input_seq(JOYCODE_Y_INDEXED(2), input_seq::or_code, MOUSECODE_Y_INDEXED(2)), input_seq(KEYCODE_I, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(2)), input_seq(KEYCODE_K, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(2)) )
+ INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, AD_STICK_Y, "AD Stick Y 4", input_seq(JOYCODE_Y_INDEXED(3), input_seq::or_code, MOUSECODE_Y_INDEXED(3)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(3)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(3)) )
+ INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, AD_STICK_Y, "AD Stick Y 5", input_seq(JOYCODE_Y_INDEXED(4), input_seq::or_code, MOUSECODE_Y_INDEXED(4)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(4)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(4)) )
+ INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, AD_STICK_Y, "AD Stick Y 6", input_seq(JOYCODE_Y_INDEXED(5), input_seq::or_code, MOUSECODE_Y_INDEXED(5)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(5)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(5)) )
+ INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, AD_STICK_Y, "AD Stick Y 7", input_seq(JOYCODE_Y_INDEXED(6), input_seq::or_code, MOUSECODE_Y_INDEXED(6)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(6)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(6)) )
+ INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, AD_STICK_Y, "AD Stick Y 8", input_seq(JOYCODE_Y_INDEXED(7), input_seq::or_code, MOUSECODE_Y_INDEXED(7)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(7)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(7)) )
+
+ INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, AD_STICK_Z, "AD Stick Z", input_seq(JOYCODE_Z_INDEXED(0)), input_seq(), input_seq() )
+ INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, AD_STICK_Z, "AD Stick Z 2", input_seq(JOYCODE_Z_INDEXED(1)), input_seq(), input_seq() )
+ INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, AD_STICK_Z, "AD Stick Z 3", input_seq(JOYCODE_Z_INDEXED(2)), input_seq(), input_seq() )
+ INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, AD_STICK_Z, "AD Stick Z 4", input_seq(JOYCODE_Z_INDEXED(3)), input_seq(), input_seq() )
+ INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, AD_STICK_Z, "AD Stick Z 5", input_seq(JOYCODE_Z_INDEXED(4)), input_seq(), input_seq() )
+ INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, AD_STICK_Z, "AD Stick Z 6", input_seq(JOYCODE_Z_INDEXED(5)), input_seq(), input_seq() )
+ INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, AD_STICK_Z, "AD Stick Z 7", input_seq(JOYCODE_Z_INDEXED(6)), input_seq(), input_seq() )
+ INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, AD_STICK_Z, "AD Stick Z 8", input_seq(JOYCODE_Z_INDEXED(7)), input_seq(), input_seq() )
+
+ INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, LIGHTGUN_X, "Lightgun X", input_seq(GUNCODE_X_INDEXED(0), input_seq::or_code, MOUSECODE_X_INDEXED(0), input_seq::or_code, JOYCODE_X_INDEXED(0)), input_seq(KEYCODE_LEFT, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(0)), input_seq(KEYCODE_RIGHT, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(0)) )
+ INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, LIGHTGUN_X, "Lightgun X 2", input_seq(GUNCODE_X_INDEXED(1), input_seq::or_code, MOUSECODE_X_INDEXED(1), input_seq::or_code, JOYCODE_X_INDEXED(1)), input_seq(KEYCODE_D, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(1)), input_seq(KEYCODE_G, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(1)) )
+ INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, LIGHTGUN_X, "Lightgun X 3", input_seq(GUNCODE_X_INDEXED(2), input_seq::or_code, MOUSECODE_X_INDEXED(2), input_seq::or_code, JOYCODE_X_INDEXED(2)), input_seq(KEYCODE_J, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(2)), input_seq(KEYCODE_L, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(2)) )
+ INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, LIGHTGUN_X, "Lightgun X 4", input_seq(GUNCODE_X_INDEXED(3), input_seq::or_code, MOUSECODE_X_INDEXED(3), input_seq::or_code, JOYCODE_X_INDEXED(3)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(3)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(3)) )
+ INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, LIGHTGUN_X, "Lightgun X 5", input_seq(GUNCODE_X_INDEXED(4), input_seq::or_code, MOUSECODE_X_INDEXED(4), input_seq::or_code, JOYCODE_X_INDEXED(4)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(4)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(4)) )
+ INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, LIGHTGUN_X, "Lightgun X 6", input_seq(GUNCODE_X_INDEXED(5), input_seq::or_code, MOUSECODE_X_INDEXED(5), input_seq::or_code, JOYCODE_X_INDEXED(5)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(5)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(5)) )
+ INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, LIGHTGUN_X, "Lightgun X 7", input_seq(GUNCODE_X_INDEXED(6), input_seq::or_code, MOUSECODE_X_INDEXED(6), input_seq::or_code, JOYCODE_X_INDEXED(6)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(6)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(6)) )
+ INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, LIGHTGUN_X, "Lightgun X 8", input_seq(GUNCODE_X_INDEXED(7), input_seq::or_code, MOUSECODE_X_INDEXED(7), input_seq::or_code, JOYCODE_X_INDEXED(7)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(7)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(7)) )
+
+ INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, LIGHTGUN_Y, "Lightgun Y", input_seq(GUNCODE_Y_INDEXED(0), input_seq::or_code, MOUSECODE_Y_INDEXED(0), input_seq::or_code, JOYCODE_Y_INDEXED(0)), input_seq(KEYCODE_UP, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(0)), input_seq(KEYCODE_DOWN, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(0)) )
+ INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, LIGHTGUN_Y, "Lightgun Y 2", input_seq(GUNCODE_Y_INDEXED(1), input_seq::or_code, MOUSECODE_Y_INDEXED(1), input_seq::or_code, JOYCODE_Y_INDEXED(1)), input_seq(KEYCODE_R, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(1)), input_seq(KEYCODE_F, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(1)) )
+ INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, LIGHTGUN_Y, "Lightgun Y 3", input_seq(GUNCODE_Y_INDEXED(2), input_seq::or_code, MOUSECODE_Y_INDEXED(2), input_seq::or_code, JOYCODE_Y_INDEXED(2)), input_seq(KEYCODE_I, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(2)), input_seq(KEYCODE_K, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(2)) )
+ INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, LIGHTGUN_Y, "Lightgun Y 4", input_seq(GUNCODE_Y_INDEXED(3), input_seq::or_code, MOUSECODE_Y_INDEXED(3), input_seq::or_code, JOYCODE_Y_INDEXED(3)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(3)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(3)) )
+ INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, LIGHTGUN_Y, "Lightgun Y 5", input_seq(GUNCODE_Y_INDEXED(4), input_seq::or_code, MOUSECODE_Y_INDEXED(4), input_seq::or_code, JOYCODE_Y_INDEXED(4)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(4)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(4)) )
+ INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, LIGHTGUN_Y, "Lightgun Y 6", input_seq(GUNCODE_Y_INDEXED(5), input_seq::or_code, MOUSECODE_Y_INDEXED(5), input_seq::or_code, JOYCODE_Y_INDEXED(5)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(5)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(5)) )
+ INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, LIGHTGUN_Y, "Lightgun Y 7", input_seq(GUNCODE_Y_INDEXED(6), input_seq::or_code, MOUSECODE_Y_INDEXED(6), input_seq::or_code, JOYCODE_Y_INDEXED(6)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(6)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(6)) )
+ INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, LIGHTGUN_Y, "Lightgun Y 8", input_seq(GUNCODE_Y_INDEXED(7), input_seq::or_code, MOUSECODE_Y_INDEXED(7), input_seq::or_code, JOYCODE_Y_INDEXED(7)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(7)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(7)) )
+
+ INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, MOUSE_X, "Mouse X", input_seq(MOUSECODE_X_INDEXED(0)), input_seq(KEYCODE_LEFT, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(0)), input_seq(KEYCODE_RIGHT, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(0)) )
+ INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, MOUSE_X, "Mouse X 2", input_seq(MOUSECODE_X_INDEXED(1)), input_seq(KEYCODE_D, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(1)), input_seq(KEYCODE_G, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(1)) )
+ INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, MOUSE_X, "Mouse X 3", input_seq(MOUSECODE_X_INDEXED(2)), input_seq(KEYCODE_J, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(2)), input_seq(KEYCODE_L, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(2)) )
+ INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, MOUSE_X, "Mouse X 4", input_seq(MOUSECODE_X_INDEXED(3)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(3)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(3)) )
+ INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, MOUSE_X, "Mouse X 5", input_seq(MOUSECODE_X_INDEXED(4)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(4)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(4)) )
+ INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, MOUSE_X, "Mouse X 6", input_seq(MOUSECODE_X_INDEXED(5)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(5)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(5)) )
+ INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, MOUSE_X, "Mouse X 7", input_seq(MOUSECODE_X_INDEXED(6)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(6)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(6)) )
+ INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, MOUSE_X, "Mouse X 8", input_seq(MOUSECODE_X_INDEXED(7)), input_seq(JOYCODE_X_LEFT_SWITCH_INDEXED(7)), input_seq(JOYCODE_X_RIGHT_SWITCH_INDEXED(7)) )
+
+ INPUT_PORT_ANALOG_TYPE( 1, PLAYER1, MOUSE_Y, "Mouse Y", input_seq(MOUSECODE_Y_INDEXED(0)), input_seq(KEYCODE_UP, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(0)), input_seq(KEYCODE_DOWN, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(0)) )
+ INPUT_PORT_ANALOG_TYPE( 2, PLAYER2, MOUSE_Y, "Mouse Y 2", input_seq(MOUSECODE_Y_INDEXED(1)), input_seq(KEYCODE_R, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(1)), input_seq(KEYCODE_F, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(1)) )
+ INPUT_PORT_ANALOG_TYPE( 3, PLAYER3, MOUSE_Y, "Mouse Y 3", input_seq(MOUSECODE_Y_INDEXED(2)), input_seq(KEYCODE_I, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(2)), input_seq(KEYCODE_K, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(2)) )
+ INPUT_PORT_ANALOG_TYPE( 4, PLAYER4, MOUSE_Y, "Mouse Y 4", input_seq(MOUSECODE_Y_INDEXED(3)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(3)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(3)) )
+ INPUT_PORT_ANALOG_TYPE( 5, PLAYER5, MOUSE_Y, "Mouse Y 5", input_seq(MOUSECODE_Y_INDEXED(4)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(4)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(4)) )
+ INPUT_PORT_ANALOG_TYPE( 6, PLAYER6, MOUSE_Y, "Mouse Y 6", input_seq(MOUSECODE_Y_INDEXED(5)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(5)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(5)) )
+ INPUT_PORT_ANALOG_TYPE( 7, PLAYER7, MOUSE_Y, "Mouse Y 7", input_seq(MOUSECODE_Y_INDEXED(6)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(6)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(6)) )
+ INPUT_PORT_ANALOG_TYPE( 8, PLAYER8, MOUSE_Y, "Mouse Y 8", input_seq(MOUSECODE_Y_INDEXED(7)), input_seq(JOYCODE_Y_UP_SWITCH_INDEXED(7)), input_seq(JOYCODE_Y_DOWN_SWITCH_INDEXED(7)) )
+
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, KEYPAD, "Keypad", input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, OTHER, KEYBOARD, "Keyboard", input_seq() )
+
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ON_SCREEN_DISPLAY,"On Screen Display", input_seq(KEYCODE_TILDE) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_DEBUG_BREAK, "Break in Debugger", input_seq(KEYCODE_TILDE) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_CONFIGURE, "Config Menu", input_seq(KEYCODE_TAB) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAUSE, "Pause", input_seq(KEYCODE_P) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_RESET_MACHINE, "Reset Game", input_seq(KEYCODE_F3, KEYCODE_LSHIFT) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SOFT_RESET, "Soft Reset", input_seq(KEYCODE_F3, input_seq::not_code, KEYCODE_LSHIFT) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SHOW_GFX, "Show Gfx", input_seq(KEYCODE_F4) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FRAMESKIP_DEC, "Frameskip Dec", input_seq(KEYCODE_F8) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FRAMESKIP_INC, "Frameskip Inc", input_seq(KEYCODE_F9) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_THROTTLE, "Throttle", input_seq(KEYCODE_F10) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FAST_FORWARD, "Fast Forward", input_seq(KEYCODE_INSERT) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SHOW_FPS, "Show FPS", input_seq(KEYCODE_F11, input_seq::not_code, KEYCODE_LCONTROL, input_seq::not_code, KEYCODE_LSHIFT) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SNAPSHOT, "Save Snapshot", input_seq(KEYCODE_F12, input_seq::not_code, KEYCODE_LSHIFT) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_RECORD_MOVIE, "Record Movie", input_seq(KEYCODE_F12, KEYCODE_LSHIFT) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_TOGGLE_CHEAT, "Toggle Cheat", input_seq(KEYCODE_F6) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_UP, "UI Up", input_seq(KEYCODE_UP, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_DOWN, "UI Down", input_seq(KEYCODE_DOWN, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_LEFT, "UI Left", input_seq(KEYCODE_LEFT, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_RIGHT, "UI Right", input_seq(KEYCODE_RIGHT, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_HOME, "UI Home", input_seq(KEYCODE_HOME) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_END, "UI End", input_seq(KEYCODE_END) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAGE_UP, "UI Page Up", input_seq(KEYCODE_PGUP) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAGE_DOWN, "UI Page Down", input_seq(KEYCODE_PGDN) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SELECT, "UI Select", input_seq(KEYCODE_ENTER, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(0)) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_CANCEL, "UI Cancel", input_seq(KEYCODE_ESC) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_DISPLAY_COMMENT, "UI Display Comment", input_seq(KEYCODE_SPACE) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_CLEAR, "UI Clear", input_seq(KEYCODE_DEL) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ZOOM_IN, "UI Zoom In", input_seq(KEYCODE_EQUALS) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ZOOM_OUT, "UI Zoom Out", input_seq(KEYCODE_MINUS) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PREV_GROUP, "UI Previous Group", input_seq(KEYCODE_OPENBRACE) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_NEXT_GROUP, "UI Next Group", input_seq(KEYCODE_CLOSEBRACE) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ROTATE, "UI Rotate", input_seq(KEYCODE_R) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SHOW_PROFILER, "Show Profiler", input_seq(KEYCODE_F11, KEYCODE_LSHIFT) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_TOGGLE_UI, "UI Toggle", input_seq(KEYCODE_SCRLOCK, input_seq::not_code, KEYCODE_LSHIFT) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PASTE, "UI Paste Text", input_seq(KEYCODE_SCRLOCK, KEYCODE_LSHIFT) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_TOGGLE_DEBUG, "Toggle Debugger", input_seq(KEYCODE_F5) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SAVE_STATE, "Save State", input_seq(KEYCODE_F7, KEYCODE_LSHIFT) )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_LOAD_STATE, "Load State", input_seq(KEYCODE_F7, input_seq::not_code, KEYCODE_LSHIFT) )
+
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_1, NULL, input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_2, NULL, input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_3, NULL, input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_4, NULL, input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_5, NULL, input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_6, NULL, input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_7, NULL, input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_8, NULL, input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_9, NULL, input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_10, NULL, input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_11, NULL, input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_12, NULL, input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_13, NULL, input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_14, NULL, input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_15, NULL, input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_16, NULL, input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, INVALID, UNKNOWN, NULL, input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, INVALID, UNUSED, NULL, input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, INVALID, SPECIAL, NULL, input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, INVALID, OTHER, NULL, input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, INVALID, ADJUSTER, NULL, input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, INVALID, DIPSWITCH, NULL, input_seq() )
+ INPUT_PORT_DIGITAL_TYPE( 0, INVALID, CONFIG, NULL, input_seq() )
+}
diff --git a/trunk/src/emu/input.c b/trunk/src/emu/input.c
new file mode 100644
index 00000000000..097de87c213
--- /dev/null
+++ b/trunk/src/emu/input.c
@@ -0,0 +1,2432 @@
+/***************************************************************************
+
+ input.c
+
+ Handle input from the user.
+
+****************************************************************************
+
+ 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.
+
+****************************************************************************
+
+ To do:
+ * auto-selecting joystick configs
+ * per-joystick configs?
+ * test half-axis selections
+ * add input test menu
+ * get rid of osd_customize_inputport_list
+
+***************************************************************************/
+
+#include "emu.h"
+#include "emuopts.h"
+#include "profiler.h"
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// invalid memory value for axis polling
+const INT32 INVALID_AXIS_VALUE = 0x7fffffff;
+
+// additional expanded input codes for sequences
+const input_code input_seq::end_code(DEVICE_CLASS_INTERNAL, 0, ITEM_CLASS_INVALID, ITEM_MODIFIER_NONE, ITEM_ID_SEQ_END);
+const input_code input_seq::default_code(DEVICE_CLASS_INTERNAL, 0, ITEM_CLASS_INVALID, ITEM_MODIFIER_NONE, ITEM_ID_SEQ_DEFAULT);
+const input_code input_seq::not_code(DEVICE_CLASS_INTERNAL, 0, ITEM_CLASS_INVALID, ITEM_MODIFIER_NONE, ITEM_ID_SEQ_NOT);
+const input_code input_seq::or_code(DEVICE_CLASS_INTERNAL, 0, ITEM_CLASS_INVALID, ITEM_MODIFIER_NONE, ITEM_ID_SEQ_OR);
+
+// constant sequences
+const input_seq input_seq::empty_seq;
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> input_device_item
+
+// a single item on an input device
+class input_device_item
+{
+protected:
+ // construction/destruction
+ input_device_item(input_device &device, const char *name, void *internal, input_item_id itemid, item_get_state_func getstate, input_item_class itemclass);
+ virtual ~input_device_item() { }
+
+public:
+ // getters
+ input_device &device() const { return m_device; }
+ input_manager &manager() const { return m_device.manager(); }
+ running_machine &machine() const { return m_device.machine(); }
+ const char *name() const { return m_name; }
+ void *internal() const { return m_internal; }
+ input_item_id itemid() const { return m_itemid; }
+ input_item_class itemclass() const { return m_itemclass; }
+ const char *token() const { return m_token; }
+ INT32 current() const { return m_current; }
+ INT32 memory() const { return m_memory; }
+
+ // helpers
+ INT32 update_value() { return m_current = (*m_getstate)(m_device.internal(), m_internal); }
+ void set_memory(INT32 value) { m_memory = value; }
+
+ // readers
+ virtual INT32 read_as_switch(input_item_modifier modifier) = 0;
+ virtual INT32 read_as_relative(input_item_modifier modifier) = 0;
+ virtual INT32 read_as_absolute(input_item_modifier modifier) = 0;
+
+protected:
+ // internal state
+ input_device & m_device; // reference to our owning device
+ astring m_name; // string name of item
+ void * m_internal; // internal callback pointer
+ input_item_id m_itemid; // originally specified item id
+ input_item_class m_itemclass; // class of the item
+ item_get_state_func m_getstate; // get state callback
+ astring m_token; // tokenized name for non-standard items
+
+ // live state
+ INT32 m_current; // current raw value
+ INT32 m_memory; // "memory" value, to remember where we started during polling
+};
+
+
+// ======================> input_device_switch_item
+
+// derived input item representing a switch input
+class input_device_switch_item : public input_device_item
+{
+public:
+ // construction/destruction
+ input_device_switch_item(input_device &device, const char *name, void *internal, input_item_id itemid, item_get_state_func getstate);
+
+ // readers
+ virtual INT32 read_as_switch(input_item_modifier modifier);
+ virtual INT32 read_as_relative(input_item_modifier modifier);
+ virtual INT32 read_as_absolute(input_item_modifier modifier);
+
+ // steadykey helper
+ bool steadykey_changed();
+ void steadykey_update_to_current() { m_steadykey = m_current; }
+
+private:
+ // internal state
+ INT32 m_steadykey; // the live steadykey state
+ INT32 m_oldkey; // old live state
+};
+
+
+// ======================> input_device_switch_item
+
+// derived input item representing a relative axis input
+class input_device_relative_item : public input_device_item
+{
+public:
+ // construction/destruction
+ input_device_relative_item(input_device &device, const char *name, void *internal, input_item_id itemid, item_get_state_func getstate);
+
+ // readers
+ virtual INT32 read_as_switch(input_item_modifier modifier);
+ virtual INT32 read_as_relative(input_item_modifier modifier);
+ virtual INT32 read_as_absolute(input_item_modifier modifier);
+};
+
+
+// ======================> input_device_switch_item
+
+// derived input item representing an absolute axis input
+class input_device_absolute_item : public input_device_item
+{
+public:
+ // construction/destruction
+ input_device_absolute_item(input_device &device, const char *name, void *internal, input_item_id itemid, item_get_state_func getstate);
+
+ // readers
+ virtual INT32 read_as_switch(input_item_modifier modifier);
+ virtual INT32 read_as_relative(input_item_modifier modifier);
+ virtual INT32 read_as_absolute(input_item_modifier modifier);
+};
+
+
+// ======================> code_string_table
+
+// simple class to match codes to strings
+struct code_string_table
+{
+ UINT32 operator[](const char *string) const
+ {
+ for (const code_string_table *current = this; current->m_code != ~0; current++)
+ if (strcmp(current->m_string, string) == 0)
+ return current->m_code;
+ return ~0;
+ }
+
+ const char *operator[](UINT32 code) const
+ {
+ for (const code_string_table *current = this; current->m_code != ~0; current++)
+ if (current->m_code == code)
+ return current->m_string;
+ return NULL;
+ }
+
+ UINT32 m_code;
+ const char * m_string;
+};
+
+
+
+//**************************************************************************
+// TOKEN/STRING TABLES
+//**************************************************************************
+
+// token strings for device classes
+static const code_string_table devclass_token_table[] =
+{
+ { DEVICE_CLASS_KEYBOARD, "KEYCODE" },
+ { DEVICE_CLASS_MOUSE, "MOUSECODE" },
+ { DEVICE_CLASS_LIGHTGUN, "GUNCODE" },
+ { DEVICE_CLASS_JOYSTICK, "JOYCODE" },
+ { ~0, "UNKCODE" }
+};
+
+// friendly strings for device classes
+static const code_string_table devclass_string_table[] =
+{
+ { DEVICE_CLASS_KEYBOARD, "Kbd" },
+ { DEVICE_CLASS_MOUSE, "Mouse" },
+ { DEVICE_CLASS_LIGHTGUN, "Gun" },
+ { DEVICE_CLASS_JOYSTICK, "Joy" },
+ { ~0, "Unk" }
+};
+
+// token strings for item modifiers
+static const code_string_table modifier_token_table[] =
+{
+ { ITEM_MODIFIER_POS, "POS" },
+ { ITEM_MODIFIER_NEG, "NEG" },
+ { ITEM_MODIFIER_LEFT, "LEFT" },
+ { ITEM_MODIFIER_RIGHT, "RIGHT" },
+ { ITEM_MODIFIER_UP, "UP" },
+ { ITEM_MODIFIER_DOWN, "DOWN" },
+ { ~0, "" }
+};
+
+// friendly strings for item modifiers
+static const code_string_table modifier_string_table[] =
+{
+ { ITEM_MODIFIER_POS, "+" },
+ { ITEM_MODIFIER_NEG, "-" },
+ { ITEM_MODIFIER_LEFT, "Left" },
+ { ITEM_MODIFIER_RIGHT, "Right" },
+ { ITEM_MODIFIER_UP, "Up" },
+ { ITEM_MODIFIER_DOWN, "Down" },
+ { ~0, "" }
+};
+
+// token strings for item classes
+static const code_string_table itemclass_token_table[] =
+{
+ { ITEM_CLASS_SWITCH, "SWITCH" },
+ { ITEM_CLASS_ABSOLUTE, "ABSOLUTE" },
+ { ITEM_CLASS_RELATIVE, "RELATIVE" },
+ { ~0, "" }
+};
+
+// token strings for standard item ids
+static const code_string_table itemid_token_table[] =
+{
+ // standard keyboard codes
+ { ITEM_ID_A, "A" },
+ { ITEM_ID_B, "B" },
+ { ITEM_ID_C, "C" },
+ { ITEM_ID_D, "D" },
+ { ITEM_ID_E, "E" },
+ { ITEM_ID_F, "F" },
+ { ITEM_ID_G, "G" },
+ { ITEM_ID_H, "H" },
+ { ITEM_ID_I, "I" },
+ { ITEM_ID_J, "J" },
+ { ITEM_ID_K, "K" },
+ { ITEM_ID_L, "L" },
+ { ITEM_ID_M, "M" },
+ { ITEM_ID_N, "N" },
+ { ITEM_ID_O, "O" },
+ { ITEM_ID_P, "P" },
+ { ITEM_ID_Q, "Q" },
+ { ITEM_ID_R, "R" },
+ { ITEM_ID_S, "S" },
+ { ITEM_ID_T, "T" },
+ { ITEM_ID_U, "U" },
+ { ITEM_ID_V, "V" },
+ { ITEM_ID_W, "W" },
+ { ITEM_ID_X, "X" },
+ { ITEM_ID_Y, "Y" },
+ { ITEM_ID_Z, "Z" },
+ { ITEM_ID_0, "0" },
+ { ITEM_ID_1, "1" },
+ { ITEM_ID_2, "2" },
+ { ITEM_ID_3, "3" },
+ { ITEM_ID_4, "4" },
+ { ITEM_ID_5, "5" },
+ { ITEM_ID_6, "6" },
+ { ITEM_ID_7, "7" },
+ { ITEM_ID_8, "8" },
+ { ITEM_ID_9, "9" },
+ { ITEM_ID_F1, "F1" },
+ { ITEM_ID_F2, "F2" },
+ { ITEM_ID_F3, "F3" },
+ { ITEM_ID_F4, "F4" },
+ { ITEM_ID_F5, "F5" },
+ { ITEM_ID_F6, "F6" },
+ { ITEM_ID_F7, "F7" },
+ { ITEM_ID_F8, "F8" },
+ { ITEM_ID_F9, "F9" },
+ { ITEM_ID_F10, "F10" },
+ { ITEM_ID_F11, "F11" },
+ { ITEM_ID_F12, "F12" },
+ { ITEM_ID_F13, "F13" },
+ { ITEM_ID_F14, "F14" },
+ { ITEM_ID_F15, "F15" },
+ { ITEM_ID_ESC, "ESC" },
+ { ITEM_ID_TILDE, "TILDE" },
+ { ITEM_ID_MINUS, "MINUS" },
+ { ITEM_ID_EQUALS, "EQUALS" },
+ { ITEM_ID_BACKSPACE, "BACKSPACE" },
+ { ITEM_ID_TAB, "TAB" },
+ { ITEM_ID_OPENBRACE, "OPENBRACE" },
+ { ITEM_ID_CLOSEBRACE, "CLOSEBRACE" },
+ { ITEM_ID_ENTER, "ENTER" },
+ { ITEM_ID_COLON, "COLON" },
+ { ITEM_ID_QUOTE, "QUOTE" },
+ { ITEM_ID_BACKSLASH, "BACKSLASH" },
+ { ITEM_ID_BACKSLASH2, "BACKSLASH2" },
+ { ITEM_ID_COMMA, "COMMA" },
+ { ITEM_ID_STOP, "STOP" },
+ { ITEM_ID_SLASH, "SLASH" },
+ { ITEM_ID_SPACE, "SPACE" },
+ { ITEM_ID_INSERT, "INSERT" },
+ { ITEM_ID_DEL, "DEL" },
+ { ITEM_ID_HOME, "HOME" },
+ { ITEM_ID_END, "END" },
+ { ITEM_ID_PGUP, "PGUP" },
+ { ITEM_ID_PGDN, "PGDN" },
+ { ITEM_ID_LEFT, "LEFT" },
+ { ITEM_ID_RIGHT, "RIGHT" },
+ { ITEM_ID_UP, "UP" },
+ { ITEM_ID_DOWN, "DOWN" },
+ { ITEM_ID_0_PAD, "0PAD" },
+ { ITEM_ID_1_PAD, "1PAD" },
+ { ITEM_ID_2_PAD, "2PAD" },
+ { ITEM_ID_3_PAD, "3PAD" },
+ { ITEM_ID_4_PAD, "4PAD" },
+ { ITEM_ID_5_PAD, "5PAD" },
+ { ITEM_ID_6_PAD, "6PAD" },
+ { ITEM_ID_7_PAD, "7PAD" },
+ { ITEM_ID_8_PAD, "8PAD" },
+ { ITEM_ID_9_PAD, "9PAD" },
+ { ITEM_ID_SLASH_PAD, "SLASHPAD" },
+ { ITEM_ID_ASTERISK, "ASTERISK" },
+ { ITEM_ID_MINUS_PAD, "MINUSPAD" },
+ { ITEM_ID_PLUS_PAD, "PLUSPAD" },
+ { ITEM_ID_DEL_PAD, "DELPAD" },
+ { ITEM_ID_ENTER_PAD, "ENTERPAD" },
+ { ITEM_ID_PRTSCR, "PRTSCR" },
+ { ITEM_ID_PAUSE, "PAUSE" },
+ { ITEM_ID_LSHIFT, "LSHIFT" },
+ { ITEM_ID_RSHIFT, "RSHIFT" },
+ { ITEM_ID_LCONTROL, "LCONTROL" },
+ { ITEM_ID_RCONTROL, "RCONTROL" },
+ { ITEM_ID_LALT, "LALT" },
+ { ITEM_ID_RALT, "RALT" },
+ { ITEM_ID_SCRLOCK, "SCRLOCK" },
+ { ITEM_ID_NUMLOCK, "NUMLOCK" },
+ { ITEM_ID_CAPSLOCK, "CAPSLOCK" },
+ { ITEM_ID_LWIN, "LWIN" },
+ { ITEM_ID_RWIN, "RWIN" },
+ { ITEM_ID_MENU, "MENU" },
+ { ITEM_ID_CANCEL, "CANCEL" },
+
+ // standard mouse/joystick/gun codes
+ { ITEM_ID_XAXIS, "XAXIS" },
+ { ITEM_ID_YAXIS, "YAXIS" },
+ { ITEM_ID_ZAXIS, "ZAXIS" },
+ { ITEM_ID_RXAXIS, "RXAXIS" },
+ { ITEM_ID_RYAXIS, "RYAXIS" },
+ { ITEM_ID_RZAXIS, "RZAXIS" },
+ { ITEM_ID_SLIDER1, "SLIDER1" },
+ { ITEM_ID_SLIDER2, "SLIDER2" },
+ { ITEM_ID_BUTTON1, "BUTTON1" },
+ { ITEM_ID_BUTTON2, "BUTTON2" },
+ { ITEM_ID_BUTTON3, "BUTTON3" },
+ { ITEM_ID_BUTTON4, "BUTTON4" },
+ { ITEM_ID_BUTTON5, "BUTTON5" },
+ { ITEM_ID_BUTTON6, "BUTTON6" },
+ { ITEM_ID_BUTTON7, "BUTTON7" },
+ { ITEM_ID_BUTTON8, "BUTTON8" },
+ { ITEM_ID_BUTTON9, "BUTTON9" },
+ { ITEM_ID_BUTTON10, "BUTTON10" },
+ { ITEM_ID_BUTTON11, "BUTTON11" },
+ { ITEM_ID_BUTTON12, "BUTTON12" },
+ { ITEM_ID_BUTTON13, "BUTTON13" },
+ { ITEM_ID_BUTTON14, "BUTTON14" },
+ { ITEM_ID_BUTTON15, "BUTTON15" },
+ { ITEM_ID_BUTTON16, "BUTTON16" },
+ { ITEM_ID_START, "START" },
+ { ITEM_ID_SELECT, "SELECT" },
+
+ // Hats
+ { ITEM_ID_HAT1UP, "HAT1UP" },
+ { ITEM_ID_HAT1DOWN, "HAT1DOWN" },
+ { ITEM_ID_HAT1LEFT, "HAT1LEFT" },
+ { ITEM_ID_HAT1RIGHT, "HAT1RIGHT" },
+ { ITEM_ID_HAT2UP, "HAT2UP" },
+ { ITEM_ID_HAT2DOWN, "HAT2DOWN" },
+ { ITEM_ID_HAT2LEFT, "HAT2LEFT" },
+ { ITEM_ID_HAT2RIGHT, "HAT2RIGHT" },
+ { ITEM_ID_HAT3UP, "HAT3UP" },
+ { ITEM_ID_HAT3DOWN, "HAT3DOWN" },
+ { ITEM_ID_HAT3LEFT, "HAT3LEFT" },
+ { ITEM_ID_HAT3RIGHT, "HAT3RIGHT" },
+ { ITEM_ID_HAT4UP, "HAT4UP" },
+ { ITEM_ID_HAT4DOWN, "HAT4DOWN" },
+ { ITEM_ID_HAT4LEFT, "HAT4LEFT" },
+ { ITEM_ID_HAT4RIGHT, "HAT4RIGHT" },
+
+ // Additional IDs
+ { ITEM_ID_ADD_SWITCH1, "ADDSW1" },
+ { ITEM_ID_ADD_SWITCH2, "ADDSW2" },
+ { ITEM_ID_ADD_SWITCH3, "ADDSW3" },
+ { ITEM_ID_ADD_SWITCH4, "ADDSW4" },
+ { ITEM_ID_ADD_SWITCH5, "ADDSW5" },
+ { ITEM_ID_ADD_SWITCH6, "ADDSW6" },
+ { ITEM_ID_ADD_SWITCH7, "ADDSW7" },
+ { ITEM_ID_ADD_SWITCH8, "ADDSW8" },
+ { ITEM_ID_ADD_SWITCH9, "ADDSW9" },
+ { ITEM_ID_ADD_SWITCH10, "ADDSW10" },
+ { ITEM_ID_ADD_SWITCH11, "ADDSW11" },
+ { ITEM_ID_ADD_SWITCH12, "ADDSW12" },
+ { ITEM_ID_ADD_SWITCH13, "ADDSW13" },
+ { ITEM_ID_ADD_SWITCH14, "ADDSW14" },
+ { ITEM_ID_ADD_SWITCH15, "ADDSW15" },
+ { ITEM_ID_ADD_SWITCH16, "ADDSW16" },
+ { ITEM_ID_ADD_ABSOLUTE1, "ADDAXIS1" },
+ { ITEM_ID_ADD_ABSOLUTE2, "ADDAXIS2" },
+ { ITEM_ID_ADD_ABSOLUTE3, "ADDAXIS3" },
+ { ITEM_ID_ADD_ABSOLUTE4, "ADDAXIS4" },
+ { ITEM_ID_ADD_ABSOLUTE5, "ADDAXIS5" },
+ { ITEM_ID_ADD_ABSOLUTE6, "ADDAXIS6" },
+ { ITEM_ID_ADD_ABSOLUTE7, "ADDAXIS7" },
+ { ITEM_ID_ADD_ABSOLUTE8, "ADDAXIS8" },
+ { ITEM_ID_ADD_ABSOLUTE9, "ADDAXIS9" },
+ { ITEM_ID_ADD_ABSOLUTE10,"ADDAXIS10" },
+ { ITEM_ID_ADD_ABSOLUTE11,"ADDAXIS11" },
+ { ITEM_ID_ADD_ABSOLUTE12,"ADDAXIS12" },
+ { ITEM_ID_ADD_ABSOLUTE13,"ADDAXIS13" },
+ { ITEM_ID_ADD_ABSOLUTE14,"ADDAXIS14" },
+ { ITEM_ID_ADD_ABSOLUTE15,"ADDAXIS15" },
+ { ITEM_ID_ADD_ABSOLUTE16,"ADDAXIS16" },
+ { ITEM_ID_ADD_RELATIVE1, "ADDREL1" },
+ { ITEM_ID_ADD_RELATIVE2, "ADDREL2" },
+ { ITEM_ID_ADD_RELATIVE3, "ADDREL3" },
+ { ITEM_ID_ADD_RELATIVE4, "ADDREL4" },
+ { ITEM_ID_ADD_RELATIVE5, "ADDREL5" },
+ { ITEM_ID_ADD_RELATIVE6, "ADDREL6" },
+ { ITEM_ID_ADD_RELATIVE7, "ADDREL7" },
+ { ITEM_ID_ADD_RELATIVE8, "ADDREL8" },
+ { ITEM_ID_ADD_RELATIVE9, "ADDREL9" },
+ { ITEM_ID_ADD_RELATIVE10,"ADDREL10" },
+ { ITEM_ID_ADD_RELATIVE11,"ADDREL11" },
+ { ITEM_ID_ADD_RELATIVE12,"ADDREL12" },
+ { ITEM_ID_ADD_RELATIVE13,"ADDREL13" },
+ { ITEM_ID_ADD_RELATIVE14,"ADDREL14" },
+ { ITEM_ID_ADD_RELATIVE15,"ADDREL15" },
+ { ITEM_ID_ADD_RELATIVE16,"ADDREL16" },
+
+ { ~0, NULL }
+};
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// standard joystick mappings
+const char joystick_map_8way[] = "7778...4445";
+const char joystick_map_4way_sticky[] = "s8.4s8.44s8.4445";
+const char joystick_map_4way_diagonal[] = "4444s8888..444458888.444555888.ss5.222555666.222256666.2222s6666.2222s6666";
+
+
+
+//**************************************************************************
+// JOYSTICK MAP
+//**************************************************************************
+
+//-------------------------------------------------
+// joystick_map - constructor
+//-------------------------------------------------
+
+joystick_map::joystick_map()
+ : m_lastmap(JOYSTICK_MAP_NEUTRAL)
+{
+ // parse the standard 8-way map as default
+ parse(joystick_map_8way);
+}
+
+
+//-------------------------------------------------
+// parse - parse a string into a joystick map
+//-------------------------------------------------
+
+bool joystick_map::parse(const char *mapstring)
+{
+ // save a copy of the original string
+ m_origstring = mapstring;
+
+ // iterate over rows
+ for (int rownum = 0; rownum < 9; rownum++)
+ {
+ // if we're done, copy from another row
+ if (*mapstring == 0 || *mapstring == '.')
+ {
+ bool symmetric = (rownum >= 5 && *mapstring == 0);
+ const UINT8 *srcrow = &m_map[symmetric ? (8 - rownum) : (rownum - 1)][0];
+
+ // if this is row 0, we don't have a source row -- invalid
+ if (rownum == 0)
+ return false;
+
+ // copy from the srcrow, applying up/down symmetry if in the bottom half
+ for (int colnum = 0; colnum < 9; colnum++)
+ {
+ UINT8 val = srcrow[colnum];
+ if (symmetric)
+ val = (val & (JOYSTICK_MAP_LEFT | JOYSTICK_MAP_RIGHT)) | ((val & JOYSTICK_MAP_UP) << 1) | ((val & JOYSTICK_MAP_DOWN) >> 1);
+ m_map[rownum][colnum] = val;
+ }
+ }
+
+ // otherwise, parse this column
+ else
+ {
+ for (int colnum = 0; colnum < 9; colnum++)
+ {
+ // if we're at the end of row, copy previous to the middle, then apply left/right symmetry
+ if (colnum > 0 && (*mapstring == 0 || *mapstring == '.'))
+ {
+ bool symmetric = (colnum >= 5);
+ UINT8 val = m_map[rownum][symmetric ? (8 - colnum) : (colnum - 1)];
+ if (symmetric)
+ val = (val & (JOYSTICK_MAP_UP | JOYSTICK_MAP_DOWN)) | ((val & JOYSTICK_MAP_LEFT) << 1) | ((val & JOYSTICK_MAP_RIGHT) >> 1);
+ m_map[rownum][colnum] = val;
+ }
+
+ // otherwise, convert the character to its value
+ else
+ {
+ static const UINT8 charmap[] =
+ {
+ JOYSTICK_MAP_UP | JOYSTICK_MAP_LEFT,
+ JOYSTICK_MAP_UP,
+ JOYSTICK_MAP_UP | JOYSTICK_MAP_RIGHT,
+ JOYSTICK_MAP_LEFT,
+ JOYSTICK_MAP_NEUTRAL,
+ JOYSTICK_MAP_RIGHT,
+ JOYSTICK_MAP_DOWN | JOYSTICK_MAP_LEFT,
+ JOYSTICK_MAP_DOWN,
+ JOYSTICK_MAP_DOWN | JOYSTICK_MAP_RIGHT,
+ JOYSTICK_MAP_STICKY
+ };
+ static const char validchars[] = "789456123s";
+ const char *ptr = strchr(validchars, *mapstring++);
+
+ // invalid characters exit immediately
+ if (ptr == NULL)
+ return false;
+ m_map[rownum][colnum] = charmap[ptr - validchars];
+ }
+ }
+ }
+
+ // if we ended with a period, advance to the next row
+ if (*mapstring == '.')
+ mapstring++;
+ }
+ return true;
+}
+
+
+//-------------------------------------------------
+// to_string - output the map as a string for
+// friendly display
+//-------------------------------------------------
+
+const char *joystick_map::to_string(astring &string) const
+{
+ string.printf("%s\n", m_origstring.cstr());
+ for (int rownum = 0; rownum < 9; rownum++)
+ {
+ string.catprintf(" ");
+ for (int colnum = 0; colnum < 9; colnum++)
+ switch (m_map[rownum][colnum])
+ {
+ case JOYSTICK_MAP_UP | JOYSTICK_MAP_LEFT: string.catprintf("7"); break;
+ case JOYSTICK_MAP_UP: string.catprintf("8"); break;
+ case JOYSTICK_MAP_UP | JOYSTICK_MAP_RIGHT: string.catprintf("9"); break;
+ case JOYSTICK_MAP_LEFT: string.catprintf("4"); break;
+ case JOYSTICK_MAP_NEUTRAL: string.catprintf("5"); break;
+ case JOYSTICK_MAP_RIGHT: string.catprintf("6"); break;
+ case JOYSTICK_MAP_DOWN | JOYSTICK_MAP_LEFT: string.catprintf("1"); break;
+ case JOYSTICK_MAP_DOWN: string.catprintf("2"); break;
+ case JOYSTICK_MAP_DOWN | JOYSTICK_MAP_RIGHT:string.catprintf("3"); break;
+ case JOYSTICK_MAP_STICKY: string.catprintf("s"); break;
+ default: string.catprintf("?"); break;
+ }
+
+ string.catprintf("\n");
+ }
+ return string;
+}
+
+
+//-------------------------------------------------
+// update - update the state of the joystick
+// map based on the given X/Y axis values
+//-------------------------------------------------
+
+UINT8 joystick_map::update(INT32 xaxisval, INT32 yaxisval)
+{
+ // now map the X and Y axes to a 9x9 grid using the raw values
+ xaxisval = ((xaxisval - INPUT_ABSOLUTE_MIN) * 9) / (INPUT_ABSOLUTE_MAX - INPUT_ABSOLUTE_MIN + 1);
+ yaxisval = ((yaxisval - INPUT_ABSOLUTE_MIN) * 9) / (INPUT_ABSOLUTE_MAX - INPUT_ABSOLUTE_MIN + 1);
+ UINT8 mapval = m_map[yaxisval][xaxisval];
+
+ // handle stickiness
+ if (mapval == JOYSTICK_MAP_STICKY)
+ mapval = m_lastmap;
+ else
+ m_lastmap = mapval;
+
+ // return based on whether the appropriate bit is set
+ return mapval;
+}
+
+
+
+//**************************************************************************
+// INPUT CODE
+//**************************************************************************
+
+//-------------------------------------------------
+// input_code - construct an input code from a
+// device/item pair
+//-------------------------------------------------
+
+input_code::input_code(input_device &device, input_item_id itemid)
+{
+ assert(itemid < ITEM_ID_ABSOLUTE_MAXIMUM);
+ input_device_item *item = device.item(itemid);
+ assert(item != NULL);
+ m_internal = ((device.devclass() & 0xf) << 28) | ((device.devindex() & 0xff) << 20) | ((item->itemclass() & 0xf) << 16) | (ITEM_MODIFIER_NONE << 12) | (item->itemid() & 0xfff);
+}
+
+
+
+//**************************************************************************
+// INPUT SEQ
+//**************************************************************************
+
+//-------------------------------------------------
+// operator+= - append a code to the end of an
+// input sequence
+//-------------------------------------------------
+
+input_seq &input_seq::operator+=(input_code code)
+{
+ // if not enough room, return FALSE
+ int curlength = length();
+ if (curlength < ARRAY_LENGTH(m_code) - 1)
+ {
+ m_code[curlength++] = code;
+ m_code[curlength] = end_code;
+ }
+ return *this;
+}
+
+
+//-------------------------------------------------
+// operator|= - append a code to a sequence; if
+// the sequence is non-empty, insert an OR
+// before the new code
+//-------------------------------------------------
+
+input_seq &input_seq::operator|=(input_code code)
+{
+ // overwrite end/default with the new code
+ if (m_code[0] == end_code || m_code[0] == default_code)
+ m_code[0] = code;
+
+ // otherwise, append an OR token and then the new code
+ else
+ {
+ *this += or_code;
+ *this += code;
+ }
+ return *this;
+}
+
+
+//-------------------------------------------------
+// length - return the length of the sequence
+//-------------------------------------------------
+
+int input_seq::length() const
+{
+ // find the end token; error if none found
+ for (int seqnum = 0; seqnum < ARRAY_LENGTH(m_code); seqnum++)
+ if (m_code[seqnum] == end_code)
+ return seqnum;
+ return ARRAY_LENGTH(m_code);
+}
+
+
+//-------------------------------------------------
+// is_valid - return true if a given sequence is
+// valid
+//-------------------------------------------------
+
+bool input_seq::is_valid() const
+{
+ // "default" can only be of length 1
+ if (m_code[0] == default_code)
+ return (length() == 1);
+
+ // scan the sequence for valid codes
+ input_item_class lastclass = ITEM_CLASS_INVALID;
+ input_code lastcode = INPUT_CODE_INVALID;
+ int positive_code_count = 0;
+ for (int seqnum = 0; seqnum < ARRAY_LENGTH(m_code); seqnum++)
+ {
+ // invalid codes are never permitted
+ input_code code = m_code[seqnum];
+ if (code == INPUT_CODE_INVALID)
+ return false;
+
+ // if we hit an OR or the end, validate the previous chunk
+ if (code == or_code || code == end_code)
+ {
+ // must be at least one positive code
+ if (positive_code_count == 0)
+ return false;
+
+ // last code must not have been an internal code
+ if (lastcode.internal())
+ return false;
+
+ // if this is the end, we're ok
+ if (code == end_code)
+ return true;
+
+ // reset the state for the next chunk
+ positive_code_count = 0;
+ lastclass = ITEM_CLASS_INVALID;
+ }
+
+ // if we hit a NOT, make sure we don't have a double
+ else if (code == not_code)
+ {
+ if (lastcode == not_code)
+ return false;
+ }
+
+ // anything else
+ else
+ {
+ // count positive codes
+ if (lastcode != not_code)
+ positive_code_count++;
+
+ // non-switch items can't have a NOT
+ input_item_class itemclass = code.item_class();
+ if (itemclass != ITEM_CLASS_SWITCH && lastcode == not_code)
+ return FALSE;
+
+ // absolute/relative items must all be the same class
+ if ((lastclass == ITEM_CLASS_ABSOLUTE && itemclass != ITEM_CLASS_ABSOLUTE) ||
+ (lastclass == ITEM_CLASS_RELATIVE && itemclass != ITEM_CLASS_RELATIVE))
+ return false;
+ }
+
+ // remember the last code
+ lastcode = code;
+ }
+
+ // if we got here, we were missing an END token; fail
+ return false;
+}
+
+
+//-------------------------------------------------
+// set - directly set up to the first 7 codes
+//-------------------------------------------------
+
+void input_seq::set(input_code code0, input_code code1, input_code code2, input_code code3, input_code code4, input_code code5, input_code code6)
+{
+ m_code[0] = code0;
+ m_code[1] = code1;
+ m_code[2] = code2;
+ m_code[3] = code3;
+ m_code[4] = code4;
+ m_code[5] = code5;
+ m_code[6] = code6;
+ for (int codenum = 7; codenum < ARRAY_LENGTH(m_code); codenum++)
+ m_code[codenum] = end_code;
+}
+
+
+//-------------------------------------------------
+// backspace - "backspace" over the last entry in
+// a sequence
+//-------------------------------------------------
+
+void input_seq::backspace()
+{
+ // if we have at least one entry, remove it
+ int curlength = length();
+ if (curlength > 0)
+ m_code[curlength - 1] = end_code;
+}
+
+
+//-------------------------------------------------
+// replace - replace all instances of oldcode
+// with newcode in a sequence
+//-------------------------------------------------
+
+void input_seq::replace(input_code oldcode, input_code newcode)
+{
+ for (int codenum = 0; codenum < ARRAY_LENGTH(m_code); codenum++)
+ if (m_code[codenum] == oldcode)
+ m_code[codenum] = newcode;
+}
+
+
+
+//**************************************************************************
+// INPUT DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// input_device - constructor
+//-------------------------------------------------
+
+input_device::input_device(input_class &_class, int devindex, const char *name, void *internal)
+ : m_class(_class),
+ m_name(name),
+ m_devindex(devindex),
+ m_maxitem(input_item_id(0)),
+ m_internal(internal),
+ m_joystick_deadzone((INT32)(_class.manager().machine().options().joystick_deadzone() * INPUT_ABSOLUTE_MAX)),
+ m_joystick_saturation((INT32)(_class.manager().machine().options().joystick_saturation() * INPUT_ABSOLUTE_MAX)),
+ m_steadykey_enabled(_class.manager().machine().options().steadykey()),
+ m_lightgun_reload_button(_class.manager().machine().options().offscreen_reload())
+{
+ // reset the items
+ memset(m_item, 0, sizeof(m_item));
+
+ // additional work for joysticks
+ if (devclass() == DEVICE_CLASS_JOYSTICK)
+ {
+ // get the default joystick map
+ const char *mapstring = machine().options().joystick_map();
+ if (mapstring[0] == 0 || strcmp(mapstring, "auto") == 0)
+ mapstring = joystick_map_8way;
+
+ // parse it
+ astring tempstr;
+ if (!m_joymap.parse(mapstring))
+ {
+ mame_printf_error("Invalid joystick map: %s\n", mapstring);
+ m_joymap.parse(joystick_map_8way);
+ }
+ else if (mapstring != joystick_map_8way)
+ mame_printf_verbose("Input: Default joystick map = %s", m_joymap.to_string(tempstr));
+ }
+}
+
+
+//-------------------------------------------------
+// add_item - add a new item to an input device
+//-------------------------------------------------
+
+input_item_id input_device::add_item(const char *name, input_item_id itemid, item_get_state_func getstate, void *internal)
+{
+ assert_always(machine().phase() == MACHINE_PHASE_INIT, "Can only call input_device::add_item at init time!");
+ assert(name != NULL);
+ assert(itemid > ITEM_ID_INVALID && itemid < ITEM_ID_MAXIMUM);
+ assert(getstate != NULL);
+
+ // if we have a generic ID, pick a new internal one
+ input_item_id originalid = itemid;
+ if (itemid >= ITEM_ID_OTHER_SWITCH && itemid <= ITEM_ID_OTHER_AXIS_RELATIVE)
+ for (itemid = (input_item_id)(ITEM_ID_MAXIMUM + 1); itemid <= ITEM_ID_ABSOLUTE_MAXIMUM; itemid++)
+ if (m_item[itemid] == NULL)
+ break;
+ assert(itemid <= ITEM_ID_ABSOLUTE_MAXIMUM);
+
+ // make sure we don't have any overlap
+ assert(m_item[itemid] == NULL);
+
+ // determine the class and create the appropriate item class
+ input_device_item *item = NULL;
+ switch (m_class.standard_item_class(originalid))
+ {
+ case ITEM_CLASS_SWITCH:
+ item = auto_alloc(machine(), input_device_switch_item(*this, name, internal, itemid, getstate));
+ break;
+
+ case ITEM_CLASS_RELATIVE:
+ item = auto_alloc(machine(), input_device_relative_item(*this, name, internal, itemid, getstate));
+ break;
+
+ case ITEM_CLASS_ABSOLUTE:
+ item = auto_alloc(machine(), input_device_absolute_item(*this, name, internal, itemid, getstate));
+ break;
+
+ default:
+ assert(false);
+ }
+
+ // assign the new slot and update the maximum
+ m_item[itemid] = item;
+ m_maxitem = MAX(m_maxitem, itemid);
+ return itemid;
+}
+
+
+//-------------------------------------------------
+// apply_deadzone_and_saturation - apply global
+// deadzone and saturation parameters to an
+// absolute value
+//-------------------------------------------------
+
+INT32 input_device::apply_deadzone_and_saturation(INT32 result) const
+{
+ // ignore for non-joysticks
+ if (devclass() != DEVICE_CLASS_JOYSTICK)
+ return result;
+
+ // properties are symmetric
+ bool negative = false;
+ if (result < 0)
+ {
+ negative = true;
+ result = -result;
+ }
+
+ // if in the deadzone, return 0
+ if (result < m_joystick_deadzone)
+ result = 0;
+
+ // if saturated, return the max
+ else if (result > m_joystick_saturation)
+ result = INPUT_ABSOLUTE_MAX;
+
+ // otherwise, scale
+ else
+ result = (INT64)(result - m_joystick_deadzone) * (INT64)INPUT_ABSOLUTE_MAX / (INT64)(m_joystick_saturation - m_joystick_deadzone);
+
+ // re-apply sign and return
+ return negative ? -result : result;
+}
+
+
+//-------------------------------------------------
+// apply_steadykey - apply steadykey option if
+// enabled
+//-------------------------------------------------
+
+void input_device::apply_steadykey() const
+{
+ // ignore if not enabled
+ if (!m_steadykey_enabled)
+ return;
+
+ // update the state of all the keys and see if any changed state
+ bool anything_changed = false;
+ for (input_item_id itemid = ITEM_ID_FIRST_VALID; itemid <= m_maxitem; itemid++)
+ {
+ input_device_item *item = m_item[itemid];
+ if (item != NULL && item->itemclass() == ITEM_CLASS_SWITCH)
+ if (downcast<input_device_switch_item *>(item)->steadykey_changed())
+ anything_changed = true;
+ }
+
+ // if the keyboard state is stable, flush the current state
+ if (!anything_changed)
+ for (input_item_id itemid = ITEM_ID_FIRST_VALID; itemid <= m_maxitem; itemid++)
+ {
+ input_device_item *item = m_item[itemid];
+ if (item != NULL && item->itemclass() == ITEM_CLASS_SWITCH)
+ downcast<input_device_switch_item *>(item)->steadykey_update_to_current();
+ }
+}
+
+
+
+//**************************************************************************
+// INPUT CLASS
+//**************************************************************************
+
+//-------------------------------------------------
+// input_class - constructor
+//-------------------------------------------------
+
+input_class::input_class(input_manager &manager, input_device_class devclass, bool enabled, bool multi)
+ : m_manager(manager),
+ m_devclass(devclass),
+ m_maxindex(0),
+ m_enabled(enabled),
+ m_multi(multi)
+{
+ memset(m_device, 0, sizeof(m_device));
+
+ // request a per-frame callback for the keyboard class
+ if (devclass == DEVICE_CLASS_KEYBOARD)
+ machine().add_notifier(MACHINE_NOTIFY_FRAME, machine_notify_delegate(FUNC(input_class::frame_callback), this));
+}
+
+
+//-------------------------------------------------
+// add_device - add a new input device
+//-------------------------------------------------
+
+input_device *input_class::add_device(const char *name, void *internal)
+{
+ // find the next empty index
+ int devindex;
+ for (devindex = 0; devindex < DEVICE_INDEX_MAXIMUM; devindex++)
+ if (m_device[devindex] == NULL)
+ break;
+
+ // call through
+ return add_device(devindex, name, internal);
+}
+
+input_device *input_class::add_device(int devindex, const char *name, void *internal)
+{
+ assert_always(machine().phase() == MACHINE_PHASE_INIT, "Can only call input_class::add_device at init time!");
+ assert(name != NULL);
+ assert(devindex >= 0 && devindex < DEVICE_INDEX_MAXIMUM);
+ assert(m_device[devindex] == NULL);
+
+ // allocate a new device
+ input_device *device = m_device[devindex] = auto_alloc(machine(), input_device(*this, devindex, name, internal));
+
+ // update the maximum index found
+ m_maxindex = MAX(m_maxindex, devindex);
+
+ mame_printf_verbose("Input: Adding %s #%d: %s\n", (*devclass_string_table)[m_devclass], devindex, name);
+ return device;
+}
+
+
+//-------------------------------------------------
+// standard_item_class - return the class of a
+// standard item
+//-------------------------------------------------
+
+input_item_class input_class::standard_item_class(input_item_id itemid)
+{
+ // most everything standard is a switch, apart from the axes
+ if (itemid == ITEM_ID_OTHER_SWITCH || itemid < ITEM_ID_XAXIS || (itemid > ITEM_ID_SLIDER2 && itemid < ITEM_ID_ADD_ABSOLUTE1))
+ return ITEM_CLASS_SWITCH;
+
+ // standard mouse axes are relative
+ else if (m_devclass == DEVICE_CLASS_MOUSE || itemid == ITEM_ID_OTHER_AXIS_RELATIVE || (itemid >= ITEM_ID_ADD_RELATIVE1 && itemid <= ITEM_ID_ADD_RELATIVE16))
+ return ITEM_CLASS_RELATIVE;
+
+ // all other standard axes are absolute
+ else
+ return ITEM_CLASS_ABSOLUTE;
+}
+
+
+//-------------------------------------------------
+// frame_callback - per-frame callback for various
+// bookkeeping
+//-------------------------------------------------
+
+void input_class::frame_callback()
+{
+ // iterate over all devices in our class
+ for (int devnum = 0; devnum <= m_maxindex; devnum++)
+ if (m_device[devnum] != NULL)
+ m_device[devnum]->apply_steadykey();
+}
+
+
+
+//**************************************************************************
+// INPUT MANAGER
+//**************************************************************************
+
+//-------------------------------------------------
+// input_manager - constructor
+//-------------------------------------------------
+
+input_manager::input_manager(running_machine &machine)
+ : m_machine(machine),
+ m_keyboard_class(*this, DEVICE_CLASS_KEYBOARD, true, machine.options().multi_keyboard()),
+ m_mouse_class(*this, DEVICE_CLASS_MOUSE, machine.options().mouse(), machine.options().multi_mouse()),
+ m_joystick_class(*this, DEVICE_CLASS_JOYSTICK, machine.options().joystick(), true),
+ m_lightgun_class(*this, DEVICE_CLASS_LIGHTGUN, machine.options().lightgun(), true),
+ m_poll_seq_last_ticks(0),
+ m_poll_seq_class(ITEM_CLASS_SWITCH)
+{
+ // reset code memory
+ reset_memory();
+
+ // create pointers for the classes
+ memset(m_class, 0, sizeof(m_class));
+ m_class[DEVICE_CLASS_KEYBOARD] = &m_keyboard_class;
+ m_class[DEVICE_CLASS_MOUSE] = &m_mouse_class;
+ m_class[DEVICE_CLASS_JOYSTICK] = &m_joystick_class;
+ m_class[DEVICE_CLASS_LIGHTGUN] = &m_lightgun_class;
+}
+
+
+//-------------------------------------------------
+// code_value - return the value of a given
+// input code
+//-------------------------------------------------
+
+INT32 input_manager::code_value(input_code code)
+{
+ g_profiler.start(PROFILER_INPUT);
+ INT32 result = 0;
+
+ // dummy loop to allow clean early exits
+ do
+ {
+ // return 0 for any invalid devices
+ input_device *device = device_from_code(code);
+ if (device == NULL)
+ break;
+
+ // also return 0 if the device class is disabled
+ input_class &devclass = *m_class[code.device_class()];
+ if (!devclass.enabled())
+ break;
+
+ // if this is not a multi device, only return data for item 0 and iterate over all
+ int startindex = code.device_index();
+ int stopindex = startindex;
+ if (!devclass.multi())
+ {
+ if (startindex != 0)
+ break;
+ stopindex = devclass.maxindex();
+ }
+
+ // iterate over all device indices
+ input_item_class targetclass = code.item_class();
+ for (int curindex = startindex; curindex <= stopindex; curindex++)
+ {
+ // lookup the item for the appropriate index
+ code.set_device_index(curindex);
+ input_device_item *item = item_from_code(code);
+ if (item == NULL)
+ continue;
+
+ // process items according to their native type
+ switch (targetclass)
+ {
+ case ITEM_CLASS_ABSOLUTE:
+ if (result == 0)
+ result = item->read_as_absolute(code.item_modifier());
+ break;
+
+ case ITEM_CLASS_RELATIVE:
+ result += item->read_as_relative(code.item_modifier());
+ break;
+
+ case ITEM_CLASS_SWITCH:
+ result |= item->read_as_switch(code.item_modifier());
+ break;
+
+ default:
+ break;
+ }
+ }
+ } while (0);
+
+ // stop the profiler before exiting
+ g_profiler.stop();
+ return result;
+}
+
+
+//-------------------------------------------------
+// code_pressed_once - return non-zero if a given
+// input code has transitioned from off to on
+// since the last call
+//-------------------------------------------------
+
+bool input_manager::code_pressed_once(input_code code)
+{
+ // look for the code in the memory
+ bool curvalue = code_pressed(code);
+ int empty = -1;
+ for (int memnum = 0; memnum < ARRAY_LENGTH(m_switch_memory); memnum++)
+ {
+ // were we previous pressed on the last time through here?
+ if (m_switch_memory[memnum] == code)
+ {
+ // if no longer pressed, clear entry
+ if (curvalue == false)
+ m_switch_memory[memnum] = INPUT_CODE_INVALID;
+
+ // always return false
+ return false;
+ }
+
+ // remember the first empty entry
+ if (empty == -1 && m_switch_memory[memnum] == INPUT_CODE_INVALID)
+ empty = memnum;
+ }
+
+ // if we get here, we were not previously pressed; if still not pressed, return 0
+ if (curvalue == false)
+ return false;
+
+ // otherwise, add ourself to the memory and return 1
+ assert(empty != -1);
+ if (empty != -1)
+ m_switch_memory[empty] = code;
+ return true;
+}
+
+
+//-------------------------------------------------
+// reset_polling - reset memories in preparation
+// for polling
+//-------------------------------------------------
+
+void input_manager::reset_polling()
+{
+ // reset switch memory
+ reset_memory();
+
+ // iterate over device classes and devices
+ for (input_device_class devclass = DEVICE_CLASS_FIRST_VALID; devclass <= DEVICE_CLASS_LAST_VALID; devclass++)
+ for (int devnum = 0; devnum <= m_class[devclass]->maxindex(); devnum++)
+ {
+ // fetch the device; ignore if NULL
+ input_device *device = m_class[devclass]->device(devnum);
+ if (device == NULL)
+ continue;
+
+ // iterate over items within each device
+ for (input_item_id itemid = ITEM_ID_FIRST_VALID; itemid <= device->maxitem(); itemid++)
+ {
+ // for any non-switch items, set memory equal to the current value
+ input_device_item *item = device->item(itemid);
+ if (item != NULL && item->itemclass() != ITEM_CLASS_SWITCH)
+ item->set_memory(code_value(input_code(*device, itemid)));
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// poll_switches - poll for any input
+//-------------------------------------------------
+
+input_code input_manager::poll_switches()
+{
+ // iterate over device classes and devices
+ for (input_device_class devclass = DEVICE_CLASS_FIRST_VALID; devclass <= DEVICE_CLASS_LAST_VALID; devclass++)
+ for (int devnum = 0; devnum <= m_class[devclass]->maxindex(); devnum++)
+ {
+ // fetch the device; ignore if NULL
+ input_device *device = m_class[devclass]->device(devnum);
+ if (device == NULL)
+ continue;
+
+ // iterate over items within each device
+ for (input_item_id itemid = ITEM_ID_FIRST_VALID; itemid <= device->maxitem(); itemid++)
+ {
+ input_device_item *item = device->item(itemid);
+ if (item != NULL)
+ {
+ input_code code(*device, itemid);
+
+ // if the item is natively a switch, poll it
+ if (item->itemclass() == ITEM_CLASS_SWITCH)
+ {
+ if (code_pressed_once(code))
+ return code;
+ else
+ continue;
+ }
+
+ // skip if there is not enough axis movement
+ if (!code_check_axis(*item, code))
+ continue;
+
+ // otherwise, poll axes digitally
+ code.set_item_class(ITEM_CLASS_SWITCH);
+
+ // if this is a joystick X axis, check with left/right modifiers
+ if (devclass == DEVICE_CLASS_JOYSTICK && code.item_id() == ITEM_ID_XAXIS)
+ {
+ code.set_item_modifier(ITEM_MODIFIER_LEFT);
+ if (code_pressed_once(code))
+ return code;
+ code.set_item_modifier(ITEM_MODIFIER_RIGHT);
+ if (code_pressed_once(code))
+ return code;
+ }
+
+ // if this is a joystick Y axis, check with up/down modifiers
+ else if (devclass == DEVICE_CLASS_JOYSTICK && code.item_id() == ITEM_ID_YAXIS)
+ {
+ code.set_item_modifier(ITEM_MODIFIER_UP);
+ if (code_pressed_once(code))
+ return code;
+ code.set_item_modifier(ITEM_MODIFIER_DOWN);
+ if (code_pressed_once(code))
+ return code;
+ }
+
+ // any other axis, check with pos/neg modifiers
+ else
+ {
+ code.set_item_modifier(ITEM_MODIFIER_POS);
+ if (code_pressed_once(code))
+ return code;
+ code.set_item_modifier(ITEM_MODIFIER_NEG);
+ if (code_pressed_once(code))
+ return code;
+ }
+ }
+ }
+ }
+
+ // if nothing, return an invalid code
+ return INPUT_CODE_INVALID;
+}
+
+
+//-------------------------------------------------
+// poll_keyboard_switches - poll for any
+// keyboard-specific input
+//-------------------------------------------------
+
+input_code input_manager::poll_keyboard_switches()
+{
+ // iterate over devices within each class
+ for (int devnum = 0; devnum < m_keyboard_class.maxindex(); devnum++)
+ {
+ // fetch the device; ignore if NULL
+ input_device *device = m_keyboard_class.device(devnum);
+ if (device == NULL)
+ continue;
+
+ // iterate over items within each device
+ for (input_item_id itemid = ITEM_ID_FIRST_VALID; itemid <= device->maxitem(); itemid++)
+ {
+ input_device_item *item = device->item(itemid);
+ if (item != NULL && item->itemclass() == ITEM_CLASS_SWITCH)
+ {
+ input_code code(*device, itemid);
+ if (code_pressed_once(code))
+ return code;
+ }
+ }
+ }
+
+ // if nothing, return an invalid code
+ return INPUT_CODE_INVALID;
+}
+
+
+//-------------------------------------------------
+// code_check_axis - see if axis has moved far
+// enough to trigger a read when polling
+//-------------------------------------------------
+
+bool input_manager::code_check_axis(input_device_item &item, input_code code)
+{
+ // if we've already reported this one, don't bother
+ if (item.memory() == INVALID_AXIS_VALUE)
+ return false;
+
+ // ignore min/max for lightguns
+ // so the selection will not be affected by a gun going out of range
+ INT32 curval = code_value(code);
+ if (code.device_class() == DEVICE_CLASS_LIGHTGUN &&
+ (code.item_id() == ITEM_ID_XAXIS || code.item_id() == ITEM_ID_YAXIS) &&
+ (curval == INPUT_ABSOLUTE_MAX || curval == INPUT_ABSOLUTE_MIN))
+ return false;
+
+ // compute the diff against memory
+ INT32 diff = curval - item.memory();
+ if (diff < 0)
+ diff = -diff;
+
+ // for absolute axes, look for 25% of maximum
+ if (item.itemclass() == ITEM_CLASS_ABSOLUTE && diff > (INPUT_ABSOLUTE_MAX - INPUT_ABSOLUTE_MIN) / 4)
+ {
+ item.set_memory(INVALID_AXIS_VALUE);
+ return true;
+ }
+
+ // for relative axes, look for ~20 pixels movement
+ if (item.itemclass() == ITEM_CLASS_RELATIVE && diff > 20 * INPUT_RELATIVE_PER_PIXEL)
+ {
+ item.set_memory(INVALID_AXIS_VALUE);
+ return true;
+ }
+ return false;
+}
+
+
+//-------------------------------------------------
+// poll_axes - poll for any input
+//-------------------------------------------------
+
+input_code input_manager::poll_axes()
+{
+ // iterate over device classes and devices
+ for (input_device_class devclass = DEVICE_CLASS_FIRST_VALID; devclass <= DEVICE_CLASS_LAST_VALID; devclass++)
+ for (int devnum = 0; devnum <= m_class[devclass]->maxindex(); devnum++)
+ {
+ // fetch the device; ignore if NULL
+ input_device *device = m_class[devclass]->device(devnum);
+ if (device == NULL)
+ continue;
+
+ // iterate over items within each device
+ for (input_item_id itemid = ITEM_ID_FIRST_VALID; itemid <= device->maxitem(); itemid++)
+ {
+ input_device_item *item = device->item(itemid);
+ if (item != NULL && item->itemclass() != ITEM_CLASS_SWITCH)
+ {
+ input_code code(*device, itemid);
+ if (code_check_axis(*item, code))
+ return code;
+ }
+ }
+ }
+
+ // if nothing, return an invalid code
+ return INPUT_CODE_INVALID;
+}
+
+
+//-------------------------------------------------
+// device_from_code - given an input_code return
+// a pointer to the associated device
+//-------------------------------------------------
+
+input_device *input_manager::device_from_code(input_code code) const
+{
+ // if the class is valid, return the appropriate device pointer
+ input_device_class devclass = code.device_class();
+ if (devclass >= DEVICE_CLASS_FIRST_VALID && devclass <= DEVICE_CLASS_LAST_VALID)
+ return m_class[devclass]->device(code.device_index());
+
+ // otherwise, return NULL
+ return NULL;
+}
+
+
+//-------------------------------------------------
+// item_from_code - given an input_code return
+// a pointer to the appropriate input_device_item
+//-------------------------------------------------
+
+input_device_item *input_manager::item_from_code(input_code code) const
+{
+ // first get the device; if none, then we don't have an item
+ input_device *device = device_from_code(code);
+ if (device == NULL)
+ return NULL;
+
+ // then return the device's item
+ return device->item(code.item_id());
+}
+
+
+//-------------------------------------------------
+// reset_memory - reset the array of memory for
+// pressed switches
+//-------------------------------------------------
+
+void input_manager::reset_memory()
+{
+ // reset all entries in switch memory to invalid
+ for (int memnum = 0; memnum < ARRAY_LENGTH(m_switch_memory); memnum++)
+ m_switch_memory[memnum] = INPUT_CODE_INVALID;
+}
+
+
+//-------------------------------------------------
+// code_from_itemid - translates an input_item_id
+// to an input_code
+//-------------------------------------------------
+
+input_code input_manager::code_from_itemid(input_item_id itemid) const
+{
+ // iterate over device classes and devices
+ for (input_device_class devclass = DEVICE_CLASS_FIRST_VALID; devclass <= DEVICE_CLASS_LAST_VALID; devclass++)
+ for (int devnum = 0; devnum <= m_class[devclass]->maxindex(); devnum++)
+ {
+ input_device *device = m_class[devclass]->device(devnum);
+ if (device != NULL && device->item(itemid) != NULL)
+ return input_code(*device, itemid);
+ }
+
+ return INPUT_CODE_INVALID;
+}
+
+
+//-------------------------------------------------
+// code_name - convert an input code into a
+// friendly name
+//-------------------------------------------------
+
+const char *input_manager::code_name(astring &string, input_code code) const
+{
+ string.reset();
+
+ // if nothing there, return an empty string
+ input_device_item *item = item_from_code(code);
+ if (item == NULL)
+ return string;
+
+ // determine the devclass part
+ const char *devclass = (*devclass_string_table)[code.device_class()];
+
+ // determine the devindex part
+ astring devindex;
+ devindex.printf("%d", code.device_index() + 1);
+
+ // if we're unifying all devices, don't display a number
+ if (!m_class[code.device_class()]->multi())
+ devindex.reset();
+
+ // keyboard 0 doesn't show a class or index if it is the only one
+ input_device_class device_class = item->device().devclass();
+ if (device_class == DEVICE_CLASS_KEYBOARD && m_keyboard_class.maxindex() == 0)
+ {
+ devclass = "";
+ devindex.reset();
+ }
+
+ // devcode part comes from the item name
+ const char *devcode = item->name();
+
+ // determine the modifier part
+ const char *modifier = (*modifier_string_table)[code.item_modifier()];
+
+ // devcode is redundant with joystick switch left/right/up/down
+ if (device_class == DEVICE_CLASS_JOYSTICK && code.item_class() == ITEM_CLASS_SWITCH)
+ if (code.item_modifier() >= ITEM_MODIFIER_LEFT && code.item_modifier() <= ITEM_MODIFIER_DOWN)
+ devcode = "";
+
+ // concatenate the strings
+ string.cpy(devclass);
+ if (devindex)
+ string.cat(" ").cat(devindex);
+ if (devcode[0] != 0)
+ string.cat(" ").cat(devcode);
+ if (modifier != NULL)
+ string.cat(" ").cat(modifier);
+
+ // delete any leading spaces
+ return string.trimspace();
+}
+
+
+//-------------------------------------------------
+// code_to_token - create a token for a given code
+//-------------------------------------------------
+
+const char *input_manager::code_to_token(astring &string, input_code code) const
+{
+ // determine the devclass part
+ const char *devclass = (*devclass_token_table)[code.device_class()];
+
+ // determine the devindex part; keyboard 0 doesn't show an index
+ astring devindex;
+ devindex.printf("%d", code.device_index() + 1);
+ if (code.device_class() == DEVICE_CLASS_KEYBOARD && code.device_index() == 0)
+ devindex.reset();
+
+ // determine the itemid part; look up in the table if we don't have a token
+ input_device_item *item = item_from_code(code);
+ const char *devcode = (item != NULL) ? item->token() : "UNKNOWN";
+
+ // determine the modifier part
+ const char *modifier = (*modifier_token_table)[code.item_modifier()];
+
+ // determine the itemclass part; if we match the native class, we don't include this
+ const char *itemclass = "";
+ if (item == NULL || item->itemclass() != code.item_class())
+ itemclass = (*itemclass_token_table)[code.item_class()];
+
+ // concatenate the strings
+ string.cpy(devclass);
+ if (devindex)
+ string.cat("_").cat(devindex);
+ if (devcode[0] != 0)
+ string.cat("_").cat(devcode);
+ if (modifier != NULL)
+ string.cat("_").cat(modifier);
+ if (itemclass[0] != 0)
+ string.cat("_").cat(itemclass);
+ return string;
+}
+
+
+//-------------------------------------------------
+// code_from_token - extract an input code from a
+// token
+//-------------------------------------------------
+
+input_code input_manager::code_from_token(const char *_token)
+{
+ // copy the token and break it into pieces
+ astring token[6];
+ int numtokens;
+ for (numtokens = 0; numtokens < ARRAY_LENGTH(token); )
+ {
+ // make a token up to the next underscore
+ char *score = (char *)strchr(_token, '_');
+ token[numtokens++].cpy(_token, (score == NULL) ? strlen(_token) : (score - _token));
+
+ // if we hit the end, we're done, else advance our pointer
+ if (score == NULL)
+ break;
+ _token = score + 1;
+ }
+
+ // first token should be the devclass
+ int curtok = 0;
+ input_device_class devclass = input_device_class((*devclass_token_table)[token[curtok++].cstr()]);
+ if (devclass == ~0)
+ return INPUT_CODE_INVALID;
+
+ // second token might be index; look for number
+ int devindex = 0;
+ if (numtokens > 2 && sscanf(token[curtok], "%d", &devindex) == 1)
+ {
+ curtok++;
+ devindex--;
+ }
+ if (curtok >= numtokens)
+ return INPUT_CODE_INVALID;
+
+ // next token is the item ID
+ input_item_id itemid = input_item_id((*itemid_token_table)[token[curtok].cstr()]);
+ bool standard = (itemid != ~0);
+
+ // if we're a standard code, default the itemclass based on it
+ input_item_class itemclass = ITEM_CLASS_INVALID;
+ if (standard)
+ itemclass = m_class[devclass]->standard_item_class(itemid);
+
+ // otherwise, keep parsing
+ else
+ {
+ // if this is an invalid device, we have nothing to look up
+ input_device *device = m_class[devclass]->device(devindex);
+ if (device == NULL)
+ return INPUT_CODE_INVALID;
+
+ // if not a standard code, look it up in the device specific codes
+ for (itemid = ITEM_ID_FIRST_VALID; itemid <= device->maxitem(); itemid++)
+ {
+ input_device_item *item = device->item(itemid);
+ if (item != NULL && token[curtok].cmp(item->token()) == 0)
+ {
+ // take the itemclass from the item
+ itemclass = item->itemclass();
+ break;
+ }
+ }
+
+ // bail on fail
+ if (itemid > device->maxitem())
+ return INPUT_CODE_INVALID;
+ }
+ curtok++;
+
+ // if we have another token, it is probably a modifier
+ input_item_modifier modifier = ITEM_MODIFIER_NONE;
+ if (curtok < numtokens)
+ {
+ modifier = input_item_modifier((*modifier_token_table)[token[curtok].cstr()]);
+ if (modifier != ~0)
+ curtok++;
+ else
+ modifier = ITEM_MODIFIER_NONE;
+ }
+
+ // if we have another token, it is the item class
+ if (curtok < numtokens)
+ {
+ UINT32 temp = (*itemclass_token_table)[token[curtok].cstr()];
+ if (temp != ~0)
+ {
+ curtok++;
+ itemclass = input_item_class(temp);
+ }
+ }
+
+ // we should have consumed all tokens
+ if (curtok != numtokens)
+ return INPUT_CODE_INVALID;
+
+ // assemble the final code
+ return input_code(devclass, devindex, itemclass, modifier, itemid);
+}
+
+
+//-------------------------------------------------
+// seq_pressed - return true if the given sequence
+// of switch inputs is "pressed"
+//-------------------------------------------------
+
+bool input_manager::seq_pressed(const input_seq &seq)
+{
+ // iterate over all of the codes
+ bool result = false;
+ bool invert = false;
+ bool first = true;
+ for (int codenum = 0; ; codenum++)
+ {
+ // handle NOT
+ input_code code = seq[codenum];
+ if (code == input_seq::not_code)
+ invert = true;
+
+ // handle OR and END
+ else if (code == input_seq::or_code || code == input_seq::end_code)
+ {
+ // if we have a positive result from the previous set, we're done
+ if (result || code == input_seq::end_code)
+ break;
+
+ // otherwise, reset our state
+ result = false;
+ invert = false;
+ first = true;
+ }
+
+ // handle everything else as a series of ANDs
+ else
+ {
+ // if this is the first in the sequence, result is set equal
+ if (first)
+ result = code_pressed(code) ^ invert;
+
+ // further values are ANDed
+ else if (result)
+ result &= code_pressed(code) ^ invert;
+
+ // no longer first, and clear the invert flag
+ first = invert = false;
+ }
+ }
+
+ // return the result if we queried at least one switch
+ return result;
+}
+
+
+//-------------------------------------------------
+// seq_axis_value - return the value of an axis
+// defined in an input sequence
+//-------------------------------------------------
+
+INT32 input_manager::seq_axis_value(const input_seq &seq, input_item_class &itemclass)
+{
+ // start with no valid classes
+ input_item_class itemclasszero = ITEM_CLASS_INVALID;
+ itemclass = ITEM_CLASS_INVALID;
+
+ // iterate over all of the codes
+ INT32 result = 0;
+ bool invert = false;
+ bool enable = true;
+ for (int codenum = 0; ; codenum++)
+ {
+ // handle NOT
+ input_code code = seq[codenum];
+ if (code == input_seq::not_code)
+ invert = true;
+
+ // handle OR and END
+ else if (code == input_seq::or_code || code == input_seq::end_code)
+ {
+ // if we have a positive result from the previous set, we're done
+ if (itemclass != ITEM_CLASS_INVALID || code == input_seq::end_code)
+ break;
+
+ // otherwise, reset our state
+ result = 0;
+ invert = false;
+ enable = true;
+ }
+
+ // handle everything else only if we're still enabled
+ else if (enable)
+ {
+ // switch codes serve as enables
+ if (code.item_class() == ITEM_CLASS_SWITCH)
+ {
+ // AND against previous digital codes
+ if (enable)
+ enable &= code_pressed(code) ^ invert;
+ }
+
+ // non-switch codes are analog values
+ else
+ {
+ INT32 value = code_value(code);
+
+ // if we got a 0 value, don't do anything except remember the first type
+ if (value == 0)
+ {
+ if (itemclasszero == ITEM_CLASS_INVALID)
+ itemclasszero = code.item_class();
+ }
+
+ // non-zero absolute values stick
+ else if (code.item_class() == ITEM_CLASS_ABSOLUTE)
+ {
+ itemclass = ITEM_CLASS_ABSOLUTE;
+ result = value;
+ }
+
+ // non-zero relative values accumulate
+ else if (code.item_class() == ITEM_CLASS_RELATIVE)
+ {
+ itemclass = ITEM_CLASS_RELATIVE;
+ result += value;
+ }
+ }
+
+ // clear the invert flag
+ invert = false;
+ }
+ }
+
+ // if the caller wants to know the type, provide it
+ if (result == 0)
+ itemclass = itemclasszero;
+ return result;
+}
+
+
+//-------------------------------------------------
+// seq_poll_start - begin polling for a new
+// sequence of the given itemclass
+//-------------------------------------------------
+
+void input_manager::seq_poll_start(input_item_class itemclass, const input_seq *startseq)
+{
+ assert(itemclass == ITEM_CLASS_SWITCH || itemclass == ITEM_CLASS_ABSOLUTE || itemclass == ITEM_CLASS_RELATIVE);
+
+ // reset the recording count and the clock
+ m_poll_seq_last_ticks = 0;
+ m_poll_seq_class = itemclass;
+ m_poll_seq.reset();
+
+ // grab the starting sequence to append to, and append an OR
+ if (startseq != NULL)
+ {
+ m_poll_seq = *startseq;
+ if (m_poll_seq.length() > 0)
+ m_poll_seq += input_seq::or_code;
+ }
+
+ // flush out any goobers
+ reset_polling();
+ input_code dummycode = KEYCODE_ENTER;
+ while (dummycode != INPUT_CODE_INVALID)
+ dummycode = (m_poll_seq_class == ITEM_CLASS_SWITCH) ? poll_switches() : poll_axes();
+}
+
+
+//-------------------------------------------------
+// input_seq_poll - continue polling
+//-------------------------------------------------
+
+bool input_manager::seq_poll()
+{
+ int curlen = m_poll_seq.length();
+ input_code lastcode = m_poll_seq[curlen - 1];
+
+ // switch case: see if we have a new code to process
+ input_code newcode;
+ if (m_poll_seq_class == ITEM_CLASS_SWITCH)
+ {
+ newcode = poll_switches();
+ if (newcode != INPUT_CODE_INVALID)
+ {
+ // if code is duplicate, toggle the NOT state on the code
+ if (curlen > 0 && newcode == lastcode)
+ {
+ // back up over the existing code
+ m_poll_seq.backspace();
+
+ // if there was a NOT preceding it, delete it as well, otherwise append a fresh one
+ if (m_poll_seq[curlen - 2] == input_seq::not_code)
+ m_poll_seq.backspace();
+ else
+ m_poll_seq += input_seq::not_code;
+ }
+ }
+ }
+
+ // absolute/relative case: see if we have an analog change of sufficient amount
+ else
+ {
+ bool has_or = false;
+ if (lastcode == input_seq::or_code)
+ {
+ lastcode = m_poll_seq[curlen - 2];
+ has_or = true;
+ }
+ newcode = poll_axes();
+
+ // if the last code doesn't match absolute/relative of this code, ignore the new one
+ if ((lastcode.item_class() == ITEM_CLASS_ABSOLUTE && newcode.item_class() != ITEM_CLASS_ABSOLUTE) ||
+ (lastcode.item_class() == ITEM_CLASS_RELATIVE && newcode.item_class() != ITEM_CLASS_RELATIVE))
+ newcode = INPUT_CODE_INVALID;
+
+ // if the new code is valid, check for half-axis toggles on absolute controls
+ if (newcode != INPUT_CODE_INVALID && curlen > 0 && newcode.item_class() == ITEM_CLASS_ABSOLUTE)
+ {
+ input_code last_nomodifier = lastcode;
+ last_nomodifier.set_item_modifier(ITEM_MODIFIER_NONE);
+ if (newcode == last_nomodifier)
+ {
+ // increment the modifier, wrapping back to none
+ switch (lastcode.item_modifier())
+ {
+ case ITEM_MODIFIER_NONE: newcode.set_item_modifier(ITEM_MODIFIER_POS); break;
+ case ITEM_MODIFIER_POS: newcode.set_item_modifier(ITEM_MODIFIER_NEG); break;
+ default:
+ case ITEM_MODIFIER_NEG: newcode.set_item_modifier(ITEM_MODIFIER_NONE); break;
+ }
+
+ // back up over the previous code so we can re-append
+ if (has_or)
+ m_poll_seq.backspace();
+ m_poll_seq.backspace();
+ }
+ }
+ }
+
+ // if we got a new code to append it, append it and reset the timer
+ if (newcode != INPUT_CODE_INVALID)
+ {
+ m_poll_seq += newcode;
+ m_poll_seq_last_ticks = osd_ticks();
+ }
+
+ // if we're recorded at least one item and 2/3 of a second has passed, we're done
+ if (m_poll_seq_last_ticks != 0 && osd_ticks() > m_poll_seq_last_ticks + osd_ticks_per_second() * 2 / 3)
+ {
+ // if the final result is invalid, reset to nothing
+ if (!m_poll_seq.is_valid())
+ m_poll_seq.reset();
+
+ // return true to indicate that we are finished
+ return true;
+ }
+
+ // return false to indicate we are still polling
+ return false;
+}
+
+
+//-------------------------------------------------
+// seq_name - generate the friendly name of a
+// sequence
+//-------------------------------------------------
+
+const char *input_manager::seq_name(astring &string, const input_seq &seq) const
+{
+ // make a copy of our sequence, removing any invalid bits
+ input_code clean_codes[sizeof(seq) / sizeof(input_code)];
+ int clean_index = 0;
+ astring codestr;
+ for (int codenum = 0; seq[codenum] != input_seq::end_code; codenum++)
+ {
+ // if this is a code item which is not valid, don't copy it and remove any preceding ORs/NOTs
+ input_code code = seq[codenum];
+ if (!code.internal() && strlen(code_name(codestr, code)) == 0)
+ {
+ while (clean_index > 0 && clean_codes[clean_index - 1].internal())
+ clean_index--;
+ }
+ else if (clean_index > 0 || !code.internal())
+ clean_codes[clean_index++] = code;
+ }
+
+ // special case: empty
+ if (clean_index == 0)
+ return string.cpy((seq.length() == 0) ? "None" : "n/a");
+
+ // start with an empty buffer
+ string.reset();
+
+ // loop until we hit the end
+ for (int codenum = 0; codenum < clean_index; codenum++)
+ {
+ // append a space if not the first code
+ if (codenum != 0)
+ string.cat(" ");
+
+ // handle OR/NOT codes here
+ input_code code = clean_codes[codenum];
+ if (code == input_seq::or_code)
+ string.cat("or");
+ else if (code == input_seq::not_code)
+ string.cat("not");
+
+ // otherwise, assume it is an input code and ask the input system to generate it
+ else
+ string.cat(code_name(codestr, code));
+ }
+ return string;
+}
+
+
+//-------------------------------------------------
+// seq_to_tokens - generate the tokenized form of
+// a sequence
+//-------------------------------------------------
+
+const char *input_manager::seq_to_tokens(astring &string, const input_seq &seq) const
+{
+ // start with an empty buffer
+ string.reset();
+
+ // loop until we hit the end
+ astring codestr;
+ for (int codenum = 0; seq[codenum] != input_seq::end_code; codenum++)
+ {
+ // append a space if not the first code
+ if (codenum != 0)
+ string.cat(" ");
+
+ // handle OR/NOT codes here
+ input_code code = seq[codenum];
+ if (code == input_seq::or_code)
+ string.cat("OR");
+ else if (code == input_seq::not_code)
+ string.cat("NOT");
+ else if (code == input_seq::default_code)
+ string.cat("DEFAULT");
+
+ // otherwise, assume it is an input code and ask the input system to generate it
+ else
+ string.cat(code_to_token(codestr, code));
+ }
+ return string;
+}
+
+
+//-------------------------------------------------
+// seq_from_tokens - generate the tokenized form
+// of a sequence
+//-------------------------------------------------
+
+void input_manager::seq_from_tokens(input_seq &seq, const char *string)
+{
+ // start with a blank sequence
+ seq.reset();
+
+ // loop until we're done
+ astring strcopy = string;
+ char *str = const_cast<char *>(strcopy.cstr());
+ while (1)
+ {
+ // trim any leading spaces
+ while (*str != 0 && isspace((UINT8)*str))
+ str++;
+
+ // bail if we're done
+ if (*str == 0)
+ return;
+
+ // find the end of the token and make it upper-case along the way
+ char *strtemp;
+ for (strtemp = str; *strtemp != 0 && !isspace((UINT8)*strtemp); strtemp++)
+ *strtemp = toupper((UINT8)*strtemp);
+ char origspace = *strtemp;
+ *strtemp = 0;
+
+ // look for common stuff
+ input_code code;
+ if (strcmp(str, "OR") == 0)
+ code = input_seq::or_code;
+ else if (strcmp(str, "NOT") == 0)
+ code = input_seq::not_code;
+ else if (strcmp(str, "DEFAULT") == 0)
+ code = input_seq::default_code;
+ else
+ code = code_from_token(str);
+
+ // translate and add to the sequence
+ seq += code;
+
+ // advance
+ if (origspace == 0)
+ return;
+ str = strtemp + 1;
+ }
+}
+
+
+//-------------------------------------------------
+// set_global_joystick_map - set the joystick map
+// for all devices
+//-------------------------------------------------
+
+bool input_manager::set_global_joystick_map(const char *mapstring)
+{
+ // parse the map
+ joystick_map map;
+ if (!map.parse(mapstring))
+ return false;
+
+ astring tempstr;
+ mame_printf_verbose("Input: Changing default joystick map = %s", map.to_string(tempstr));
+
+ // iterate over joysticks and set the map
+ for (int joynum = 0; joynum <= m_joystick_class.maxindex(); joynum++)
+ {
+ input_device *device = m_joystick_class.device(joynum);
+ if (device != NULL)
+ device->set_joystick_map(map);
+ }
+ return true;
+}
+
+
+
+//**************************************************************************
+// INPUT DEVICE ITEM
+//**************************************************************************
+
+//-------------------------------------------------
+// input_device_item - constructor
+//-------------------------------------------------
+
+input_device_item::input_device_item(input_device &device, const char *name, void *internal, input_item_id itemid, item_get_state_func getstate, input_item_class itemclass)
+ : m_device(device),
+ m_name(name),
+ m_internal(internal),
+ m_itemid(itemid),
+ m_itemclass(itemclass),
+ m_getstate(getstate),
+ m_current(0),
+ m_memory(0)
+{
+ // use a standard token name for know item IDs
+ if (itemid <= ITEM_ID_MAXIMUM && (*itemid_token_table)[itemid] != NULL)
+ m_token.cpy((*itemid_token_table)[itemid]);
+
+ // otherwise, create a tokenized name
+ else
+ m_token.cpy(name).toupper().delchr(' ').delchr('_');
+}
+
+
+
+//**************************************************************************
+// INPUT DEVICE SWITCH ITEM
+//**************************************************************************
+
+//-------------------------------------------------
+// input_device_switch_item - constructor
+//-------------------------------------------------
+
+input_device_switch_item::input_device_switch_item(input_device &device, const char *name, void *internal, input_item_id itemid, item_get_state_func getstate)
+ : input_device_item(device, name, internal, itemid, getstate, ITEM_CLASS_SWITCH),
+ m_steadykey(0),
+ m_oldkey(0)
+{
+}
+
+
+//-------------------------------------------------
+// read_as_switch - return the raw switch value,
+// modified as necessary
+//-------------------------------------------------
+
+INT32 input_device_switch_item::read_as_switch(input_item_modifier modifier)
+{
+ // if we're doing a lightgun reload hack, button 1 and 2 operate differently
+ input_device_class devclass = m_device.devclass();
+ if (devclass == DEVICE_CLASS_LIGHTGUN && m_device.lightgun_reload_button())
+ {
+ // button 1 is pressed if either button 1 or 2 are active
+ if (m_itemid == ITEM_ID_BUTTON1)
+ {
+ input_device_item *button2_item = m_device.item(ITEM_ID_BUTTON2);
+ if (button2_item != NULL)
+ return button2_item->update_value() | update_value();
+ }
+
+ // button 2 is never officially pressed
+ if (m_itemid == ITEM_ID_BUTTON2)
+ return 0;
+ }
+
+ // steadykey for keyboards
+ if (devclass == DEVICE_CLASS_KEYBOARD && m_device.steadykey_enabled())
+ return m_steadykey;
+
+ // everything else is just the current value as-is
+ return update_value();
+}
+
+
+//-------------------------------------------------
+// read_as_relative - return the switch input as
+// a relative axis value
+//-------------------------------------------------
+
+INT32 input_device_switch_item::read_as_relative(input_item_modifier modifier)
+{
+ // no translation to relative
+ return 0;
+}
+
+
+//-------------------------------------------------
+// read_as_absolute - return the switch input as
+// an absolute axis value
+//-------------------------------------------------
+
+INT32 input_device_switch_item::read_as_absolute(input_item_modifier modifier)
+{
+ // no translation to absolute
+ return 0;
+}
+
+
+//-------------------------------------------------
+// steadykey_changed - update for steadykey
+// behavior, returning true if the current state
+// has changed since the last call
+//-------------------------------------------------
+
+bool input_device_switch_item::steadykey_changed()
+{
+ INT32 old = m_oldkey;
+ m_oldkey = update_value();
+ if (((m_current ^ old) & 1) == 0)
+ return false;
+
+ // if the keypress was missed, turn it on for one frame
+ if (((m_current | m_steadykey) & 1) == 0)
+ m_steadykey = 1;
+ return true;
+}
+
+
+
+//**************************************************************************
+// INPUT DEVICE RELATIVE ITEM
+//**************************************************************************
+
+//-------------------------------------------------
+// input_device_relative_item - constructor
+//-------------------------------------------------
+
+input_device_relative_item::input_device_relative_item(input_device &device, const char *name, void *internal, input_item_id itemid, item_get_state_func getstate)
+ : input_device_item(device, name, internal, itemid, getstate, ITEM_CLASS_RELATIVE)
+{
+}
+
+
+//-------------------------------------------------
+// read_as_switch - return the relative value as
+// a switch result based on the modifier
+//-------------------------------------------------
+
+INT32 input_device_relative_item::read_as_switch(input_item_modifier modifier)
+{
+ // process according to modifiers
+ if (modifier == ITEM_MODIFIER_POS || modifier == ITEM_MODIFIER_RIGHT || modifier == ITEM_MODIFIER_DOWN)
+ return (update_value() > 0);
+ else if (modifier == ITEM_MODIFIER_NEG || modifier == ITEM_MODIFIER_LEFT || modifier == ITEM_MODIFIER_UP)
+ return (update_value() < 0);
+
+ // all other cases just return 0
+ return 0;
+}
+
+
+//-------------------------------------------------
+// read_as_relative - return the relative input
+// as a relative axis value
+//-------------------------------------------------
+
+INT32 input_device_relative_item::read_as_relative(input_item_modifier modifier)
+{
+ // just return directly
+ return update_value();
+}
+
+
+//-------------------------------------------------
+// read_as_absolute - return the relative input
+// as an absolute axis value
+//-------------------------------------------------
+
+INT32 input_device_relative_item::read_as_absolute(input_item_modifier modifier)
+{
+ // no translation to absolute
+ return 0;
+}
+
+
+
+//**************************************************************************
+// INPUT DEVICE ABSOLUTE ITEM
+//**************************************************************************
+
+//-------------------------------------------------
+// input_device_absolute_item - constructor
+//-------------------------------------------------
+
+input_device_absolute_item::input_device_absolute_item(input_device &device, const char *name, void *internal, input_item_id itemid, item_get_state_func getstate)
+ : input_device_item(device, name, internal, itemid, getstate, ITEM_CLASS_ABSOLUTE)
+{
+}
+
+
+//-------------------------------------------------
+// read_as_switch - return the absolute value as
+// a switch result based on the modifier
+//-------------------------------------------------
+
+INT32 input_device_absolute_item::read_as_switch(input_item_modifier modifier)
+{
+ // start with the current value
+ INT32 result = m_device.apply_deadzone_and_saturation(update_value());
+ assert(result >= INPUT_ABSOLUTE_MIN && result <= INPUT_ABSOLUTE_MAX);
+
+ // left/right/up/down: if this is a joystick, fetch the paired X/Y axis values and convert
+ if (m_device.devclass() == DEVICE_CLASS_JOYSTICK && modifier >= ITEM_MODIFIER_LEFT && modifier <= ITEM_MODIFIER_DOWN)
+ {
+ input_device_item *xaxis_item = m_device.item(ITEM_ID_XAXIS);
+ input_device_item *yaxis_item = m_device.item(ITEM_ID_YAXIS);
+ if (xaxis_item != NULL && yaxis_item != NULL)
+ {
+ // determine which item we didn't update, and update it
+ assert(this == xaxis_item || this == yaxis_item);
+ if (this == xaxis_item)
+ yaxis_item->update_value();
+ else
+ xaxis_item->update_value();
+
+ // now map the X and Y axes to a 9x9 grid using the raw values
+ return (m_device.joymap().update(xaxis_item->current(), yaxis_item->current()) >> (modifier - ITEM_MODIFIER_LEFT)) & 1;
+ }
+ }
+
+ // positive/negative: TRUE if past the deadzone in either direction
+ if (modifier == ITEM_MODIFIER_POS || modifier == ITEM_MODIFIER_RIGHT || modifier == ITEM_MODIFIER_DOWN)
+ return (result > 0);
+ else if (modifier == ITEM_MODIFIER_NEG || modifier == ITEM_MODIFIER_LEFT || modifier == ITEM_MODIFIER_UP)
+ return (result < 0);
+
+ // all other cases just return 0
+ return 0;
+}
+
+
+//-------------------------------------------------
+// read_as_relative - return the absolute input
+// as a relative axis value
+//-------------------------------------------------
+
+INT32 input_device_absolute_item::read_as_relative(input_item_modifier modifier)
+{
+ // no translation to relative
+ return 0;
+}
+
+
+//-------------------------------------------------
+// read_as_absolute - return the absolute input
+// as an absolute axis value, with appropriate
+// tweaks
+//-------------------------------------------------
+
+INT32 input_device_absolute_item::read_as_absolute(input_item_modifier modifier)
+{
+ // start with the current value
+ INT32 result = m_device.apply_deadzone_and_saturation(update_value());
+ assert(result >= INPUT_ABSOLUTE_MIN && result <= INPUT_ABSOLUTE_MAX);
+
+ // if we're doing a lightgun reload hack, override the value
+ if (m_device.devclass() == DEVICE_CLASS_LIGHTGUN && m_device.lightgun_reload_button())
+ {
+ // if it is pressed, return (min,max)
+ input_device_item *button2_item = m_device.item(ITEM_ID_BUTTON2);
+ if (button2_item != NULL && button2_item->update_value())
+ result = (m_itemid == ITEM_ID_XAXIS) ? INPUT_ABSOLUTE_MIN : INPUT_ABSOLUTE_MAX;
+ }
+
+ // positive/negative: scale to full axis
+ if (modifier == ITEM_MODIFIER_POS)
+ result = MAX(result, 0) * 2 + INPUT_ABSOLUTE_MIN;
+ if (modifier == ITEM_MODIFIER_NEG)
+ result = MAX(-result, 0) * 2 + INPUT_ABSOLUTE_MIN;
+ return result;
+}
diff --git a/trunk/src/emu/input.h b/trunk/src/emu/input.h
new file mode 100644
index 00000000000..22fb8f6d339
--- /dev/null
+++ b/trunk/src/emu/input.h
@@ -0,0 +1,1087 @@
+/***************************************************************************
+
+ input.h
+
+ Handle input from the user.
+
+****************************************************************************
+
+ 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 __INPUT_H__
+#define __INPUT_H__
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// relative devices return ~512 units per onscreen pixel
+const INT32 INPUT_RELATIVE_PER_PIXEL = 512;
+
+// absolute devices return values between -65536 and +65536
+const INT32 INPUT_ABSOLUTE_MIN = -65536;
+const INT32 INPUT_ABSOLUTE_MAX = 65536;
+
+// maximum number of axis/buttons/hats with ITEM_IDs for use by osd layer
+const int INPUT_MAX_AXIS = 8;
+const int INPUT_MAX_BUTTONS = 16;
+const int INPUT_MAX_HATS = 4;
+const int INPUT_MAX_ADD_SWITCH = 16;
+const int INPUT_MAX_ADD_ABSOLUTE = 16;
+const int INPUT_MAX_ADD_RELATIVE = 16;
+
+
+// device classes
+enum input_device_class
+{
+ DEVICE_CLASS_INVALID,
+ DEVICE_CLASS_FIRST_VALID,
+ DEVICE_CLASS_KEYBOARD = DEVICE_CLASS_FIRST_VALID,
+ DEVICE_CLASS_MOUSE,
+ DEVICE_CLASS_LIGHTGUN,
+ DEVICE_CLASS_JOYSTICK,
+ DEVICE_CLASS_LAST_VALID = DEVICE_CLASS_JOYSTICK,
+ DEVICE_CLASS_INTERNAL,
+ DEVICE_CLASS_MAXIMUM
+};
+DECLARE_ENUM_OPERATORS(input_device_class)
+
+
+// device index
+const int DEVICE_INDEX_MAXIMUM = 0xff;
+
+
+// input item classes
+enum input_item_class
+{
+ ITEM_CLASS_INVALID,
+ ITEM_CLASS_SWITCH,
+ ITEM_CLASS_ABSOLUTE,
+ ITEM_CLASS_RELATIVE,
+ ITEM_CLASS_MAXIMUM
+};
+
+
+// input item modifiers
+enum input_item_modifier
+{
+ ITEM_MODIFIER_NONE,
+ ITEM_MODIFIER_POS,
+ ITEM_MODIFIER_NEG,
+ ITEM_MODIFIER_LEFT,
+ ITEM_MODIFIER_RIGHT,
+ ITEM_MODIFIER_UP,
+ ITEM_MODIFIER_DOWN,
+ ITEM_MODIFIER_MAXIMUM
+};
+
+
+// standard item IDs
+enum input_item_id
+{
+ ITEM_ID_INVALID,
+ ITEM_ID_FIRST_VALID,
+
+ // standard keyboard IDs
+ ITEM_ID_A = ITEM_ID_FIRST_VALID,
+ ITEM_ID_B,
+ ITEM_ID_C,
+ ITEM_ID_D,
+ ITEM_ID_E,
+ ITEM_ID_F,
+ ITEM_ID_G,
+ ITEM_ID_H,
+ ITEM_ID_I,
+ ITEM_ID_J,
+ ITEM_ID_K,
+ ITEM_ID_L,
+ ITEM_ID_M,
+ ITEM_ID_N,
+ ITEM_ID_O,
+ ITEM_ID_P,
+ ITEM_ID_Q,
+ ITEM_ID_R,
+ ITEM_ID_S,
+ ITEM_ID_T,
+ ITEM_ID_U,
+ ITEM_ID_V,
+ ITEM_ID_W,
+ ITEM_ID_X,
+ ITEM_ID_Y,
+ ITEM_ID_Z,
+ ITEM_ID_0,
+ ITEM_ID_1,
+ ITEM_ID_2,
+ ITEM_ID_3,
+ ITEM_ID_4,
+ ITEM_ID_5,
+ ITEM_ID_6,
+ ITEM_ID_7,
+ ITEM_ID_8,
+ ITEM_ID_9,
+ ITEM_ID_F1,
+ ITEM_ID_F2,
+ ITEM_ID_F3,
+ ITEM_ID_F4,
+ ITEM_ID_F5,
+ ITEM_ID_F6,
+ ITEM_ID_F7,
+ ITEM_ID_F8,
+ ITEM_ID_F9,
+ ITEM_ID_F10,
+ ITEM_ID_F11,
+ ITEM_ID_F12,
+ ITEM_ID_F13,
+ ITEM_ID_F14,
+ ITEM_ID_F15,
+ ITEM_ID_ESC,
+ ITEM_ID_TILDE,
+ ITEM_ID_MINUS,
+ ITEM_ID_EQUALS,
+ ITEM_ID_BACKSPACE,
+ ITEM_ID_TAB,
+ ITEM_ID_OPENBRACE,
+ ITEM_ID_CLOSEBRACE,
+ ITEM_ID_ENTER,
+ ITEM_ID_COLON,
+ ITEM_ID_QUOTE,
+ ITEM_ID_BACKSLASH,
+ ITEM_ID_BACKSLASH2,
+ ITEM_ID_COMMA,
+ ITEM_ID_STOP,
+ ITEM_ID_SLASH,
+ ITEM_ID_SPACE,
+ ITEM_ID_INSERT,
+ ITEM_ID_DEL,
+ ITEM_ID_HOME,
+ ITEM_ID_END,
+ ITEM_ID_PGUP,
+ ITEM_ID_PGDN,
+ ITEM_ID_LEFT,
+ ITEM_ID_RIGHT,
+ ITEM_ID_UP,
+ ITEM_ID_DOWN,
+ ITEM_ID_0_PAD,
+ ITEM_ID_1_PAD,
+ ITEM_ID_2_PAD,
+ ITEM_ID_3_PAD,
+ ITEM_ID_4_PAD,
+ ITEM_ID_5_PAD,
+ ITEM_ID_6_PAD,
+ ITEM_ID_7_PAD,
+ ITEM_ID_8_PAD,
+ ITEM_ID_9_PAD,
+ ITEM_ID_SLASH_PAD,
+ ITEM_ID_ASTERISK,
+ ITEM_ID_MINUS_PAD,
+ ITEM_ID_PLUS_PAD,
+ ITEM_ID_DEL_PAD,
+ ITEM_ID_ENTER_PAD,
+ ITEM_ID_PRTSCR,
+ ITEM_ID_PAUSE,
+ ITEM_ID_LSHIFT,
+ ITEM_ID_RSHIFT,
+ ITEM_ID_LCONTROL,
+ ITEM_ID_RCONTROL,
+ ITEM_ID_LALT,
+ ITEM_ID_RALT,
+ ITEM_ID_SCRLOCK,
+ ITEM_ID_NUMLOCK,
+ ITEM_ID_CAPSLOCK,
+ ITEM_ID_LWIN,
+ ITEM_ID_RWIN,
+ ITEM_ID_MENU,
+ ITEM_ID_CANCEL,
+
+ // standard mouse/joystick/gun IDs
+ ITEM_ID_XAXIS,
+ ITEM_ID_YAXIS,
+ ITEM_ID_ZAXIS,
+ ITEM_ID_RXAXIS,
+ ITEM_ID_RYAXIS,
+ ITEM_ID_RZAXIS,
+ ITEM_ID_SLIDER1,
+ ITEM_ID_SLIDER2,
+ ITEM_ID_BUTTON1,
+ ITEM_ID_BUTTON2,
+ ITEM_ID_BUTTON3,
+ ITEM_ID_BUTTON4,
+ ITEM_ID_BUTTON5,
+ ITEM_ID_BUTTON6,
+ ITEM_ID_BUTTON7,
+ ITEM_ID_BUTTON8,
+ ITEM_ID_BUTTON9,
+ ITEM_ID_BUTTON10,
+ ITEM_ID_BUTTON11,
+ ITEM_ID_BUTTON12,
+ ITEM_ID_BUTTON13,
+ ITEM_ID_BUTTON14,
+ ITEM_ID_BUTTON15,
+ ITEM_ID_BUTTON16,
+ ITEM_ID_START,
+ ITEM_ID_SELECT,
+
+ // Hats
+ ITEM_ID_HAT1UP,
+ ITEM_ID_HAT1DOWN,
+ ITEM_ID_HAT1LEFT,
+ ITEM_ID_HAT1RIGHT,
+ ITEM_ID_HAT2UP,
+ ITEM_ID_HAT2DOWN,
+ ITEM_ID_HAT2LEFT,
+ ITEM_ID_HAT2RIGHT,
+ ITEM_ID_HAT3UP,
+ ITEM_ID_HAT3DOWN,
+ ITEM_ID_HAT3LEFT,
+ ITEM_ID_HAT3RIGHT,
+ ITEM_ID_HAT4UP,
+ ITEM_ID_HAT4DOWN,
+ ITEM_ID_HAT4LEFT,
+ ITEM_ID_HAT4RIGHT,
+
+ // Additional IDs
+ ITEM_ID_ADD_SWITCH1,
+ ITEM_ID_ADD_SWITCH2,
+ ITEM_ID_ADD_SWITCH3,
+ ITEM_ID_ADD_SWITCH4,
+ ITEM_ID_ADD_SWITCH5,
+ ITEM_ID_ADD_SWITCH6,
+ ITEM_ID_ADD_SWITCH7,
+ ITEM_ID_ADD_SWITCH8,
+ ITEM_ID_ADD_SWITCH9,
+ ITEM_ID_ADD_SWITCH10,
+ ITEM_ID_ADD_SWITCH11,
+ ITEM_ID_ADD_SWITCH12,
+ ITEM_ID_ADD_SWITCH13,
+ ITEM_ID_ADD_SWITCH14,
+ ITEM_ID_ADD_SWITCH15,
+ ITEM_ID_ADD_SWITCH16,
+
+ ITEM_ID_ADD_ABSOLUTE1,
+ ITEM_ID_ADD_ABSOLUTE2,
+ ITEM_ID_ADD_ABSOLUTE3,
+ ITEM_ID_ADD_ABSOLUTE4,
+ ITEM_ID_ADD_ABSOLUTE5,
+ ITEM_ID_ADD_ABSOLUTE6,
+ ITEM_ID_ADD_ABSOLUTE7,
+ ITEM_ID_ADD_ABSOLUTE8,
+ ITEM_ID_ADD_ABSOLUTE9,
+ ITEM_ID_ADD_ABSOLUTE10,
+ ITEM_ID_ADD_ABSOLUTE11,
+ ITEM_ID_ADD_ABSOLUTE12,
+ ITEM_ID_ADD_ABSOLUTE13,
+ ITEM_ID_ADD_ABSOLUTE14,
+ ITEM_ID_ADD_ABSOLUTE15,
+ ITEM_ID_ADD_ABSOLUTE16,
+
+ ITEM_ID_ADD_RELATIVE1,
+ ITEM_ID_ADD_RELATIVE2,
+ ITEM_ID_ADD_RELATIVE3,
+ ITEM_ID_ADD_RELATIVE4,
+ ITEM_ID_ADD_RELATIVE5,
+ ITEM_ID_ADD_RELATIVE6,
+ ITEM_ID_ADD_RELATIVE7,
+ ITEM_ID_ADD_RELATIVE8,
+ ITEM_ID_ADD_RELATIVE9,
+ ITEM_ID_ADD_RELATIVE10,
+ ITEM_ID_ADD_RELATIVE11,
+ ITEM_ID_ADD_RELATIVE12,
+ ITEM_ID_ADD_RELATIVE13,
+ ITEM_ID_ADD_RELATIVE14,
+ ITEM_ID_ADD_RELATIVE15,
+ ITEM_ID_ADD_RELATIVE16,
+
+ // generic other IDs
+ ITEM_ID_OTHER_SWITCH,
+ ITEM_ID_OTHER_AXIS_ABSOLUTE,
+ ITEM_ID_OTHER_AXIS_RELATIVE,
+ ITEM_ID_MAXIMUM,
+
+ // internal codes for sequences
+ ITEM_ID_SEQ_END,
+ ITEM_ID_SEQ_DEFAULT,
+ ITEM_ID_SEQ_NOT,
+ ITEM_ID_SEQ_OR,
+
+ // absolute maximum ID
+ ITEM_ID_ABSOLUTE_MAXIMUM = 0xfff
+};
+DECLARE_ENUM_OPERATORS(input_item_id)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// forward declarations
+class input_device_item;
+class input_device;
+class input_class;
+class input_manager;
+
+
+// callback for getting the value of an item on a device
+typedef INT32 (*item_get_state_func)(void *device_internal, void *item_internal);
+
+
+// ======================> joystick_map
+
+// a 9x9 joystick map
+class joystick_map
+{
+public:
+ // construction/destruction
+ joystick_map();
+ joystick_map(const joystick_map &src) { copy(src); }
+
+ // operators
+ joystick_map &operator=(const joystick_map &src) { if (this != &src) copy(src); return *this; }
+
+ // parse from a string
+ bool parse(const char *mapstring);
+
+ // create a friendly string
+ const char *to_string(astring &string) const;
+
+ // update the state of a live map
+ UINT8 update(INT32 xaxisval, INT32 yaxisval);
+
+ // joystick mapping codes
+ static const UINT8 JOYSTICK_MAP_NEUTRAL = 0x00;
+ static const UINT8 JOYSTICK_MAP_LEFT = 0x01;
+ static const UINT8 JOYSTICK_MAP_RIGHT = 0x02;
+ static const UINT8 JOYSTICK_MAP_UP = 0x04;
+ static const UINT8 JOYSTICK_MAP_DOWN = 0x08;
+ static const UINT8 JOYSTICK_MAP_STICKY = 0x0f;
+
+private:
+ // internal helpers
+ void copy(const joystick_map &src)
+ {
+ memcpy(m_map, src.m_map, sizeof(m_map));
+ m_lastmap = JOYSTICK_MAP_NEUTRAL;
+ m_origstring = src.m_origstring;
+ }
+
+ // internal state
+ UINT8 m_map[9][9]; // 9x9 grid
+ UINT8 m_lastmap; // last value returned (for sticky tracking)
+ astring m_origstring; // originally parsed string
+};
+
+
+// ======================> input_code
+
+// a combined code that describes a particular input on a particular device
+class input_code
+{
+public:
+ // construction/destruction
+ input_code(input_device_class devclass = DEVICE_CLASS_INVALID, int devindex = 0, input_item_class itemclass = ITEM_CLASS_INVALID, input_item_modifier modifier = ITEM_MODIFIER_NONE, input_item_id itemid = ITEM_ID_INVALID)
+ : m_internal(((devclass & 0xf) << 28) | ((devindex & 0xff) << 20) | ((itemclass & 0xf) << 16) | ((modifier & 0xf) << 12) | (itemid & 0xfff))
+ {
+ assert(devclass >= 0 && devclass < DEVICE_CLASS_MAXIMUM);
+ assert(devindex >= 0 && devindex < DEVICE_INDEX_MAXIMUM);
+ assert(itemclass >= 0 && itemclass < ITEM_CLASS_MAXIMUM);
+ assert(modifier >= 0 && modifier < ITEM_MODIFIER_MAXIMUM);
+ assert(itemid >= 0 && itemid < ITEM_ID_ABSOLUTE_MAXIMUM);
+ }
+ input_code(const input_code &src)
+ : m_internal(src.m_internal) { }
+ input_code(input_device &device, input_item_id itemid);
+
+ // operators
+ bool operator==(const input_code &rhs) const { return m_internal == rhs.m_internal; }
+ bool operator!=(const input_code &rhs) const { return m_internal != rhs.m_internal; }
+
+ // getters
+ bool internal() const { return device_class() == DEVICE_CLASS_INTERNAL; }
+ input_device_class device_class() const { return input_device_class((m_internal >> 28) & 0xf); }
+ int device_index() const { return ((m_internal >> 20) & 0xff); }
+ input_item_class item_class() const { return input_item_class((m_internal >> 16) & 0xf); }
+ input_item_modifier item_modifier() const { return input_item_modifier((m_internal >> 12) & 0xf); }
+ input_item_id item_id() const { return input_item_id(m_internal & 0xfff); }
+
+ // setters
+ void set_device_class(input_device_class devclass) { assert(devclass >= 0 && devclass <= 0xf); m_internal = (m_internal & ~(0xf << 28)) | ((devclass & 0xf) << 28); }
+ void set_device_index(int devindex) { assert(devindex >= 0 && devindex <= 0xff); m_internal = (m_internal & ~(0xff << 20)) | ((devindex & 0xff) << 20); }
+ void set_item_class(input_item_class itemclass) { assert(itemclass >= 0 && itemclass <= 0xf); m_internal = (m_internal & ~(0xf << 16)) | ((itemclass & 0xf) << 16); }
+ void set_item_modifier(input_item_modifier modifier) { assert(modifier >= 0 && modifier <= 0xf); m_internal = (m_internal & ~(0xf << 12)) | ((modifier & 0xf) << 12); }
+ void set_item_id(input_item_id itemid) { assert(itemid >= 0 && itemid <= 0xfff); m_internal = (m_internal & ~0xfff) | (itemid & 0xfff); }
+
+private:
+ // internal state
+ UINT32 m_internal;
+};
+
+
+// ======================> input_seq
+
+// a sequence of input_codes, supporting AND/OR and inversion
+class input_seq
+{
+public:
+ // construction/destruction
+ input_seq(input_code code0 = input_seq::end_code, input_code code1 = input_seq::end_code, input_code code2 = input_seq::end_code, input_code code3 = input_seq::end_code, input_code code4 = input_seq::end_code, input_code code5 = input_seq::end_code, input_code code6 = input_seq::end_code)
+ { set(code0, code1, code2, code3, code4, code5, code6); }
+ input_seq(const input_seq &rhs) { memcpy(m_code, rhs.m_code, sizeof(m_code)); }
+
+ // operators
+ bool operator==(const input_seq &rhs) const { return (memcmp(m_code, rhs.m_code, sizeof(m_code)) == 0); }
+ bool operator!=(const input_seq &rhs) const { return (memcmp(m_code, rhs.m_code, sizeof(m_code)) != 0); }
+ input_code operator[](int index) const { return (index >= 0 && index < ARRAY_LENGTH(m_code)) ? m_code[index] : input_seq::end_code; }
+ input_seq &operator+=(input_code code);
+ input_seq &operator|=(input_code code);
+
+ // getters
+ int length() const;
+ bool is_valid() const;
+ bool is_default() const { return m_code[0] == default_code; }
+
+ // setters
+ void set(input_code code0 = input_seq::end_code, input_code code1 = input_seq::end_code, input_code code2 = input_seq::end_code, input_code code3 = input_seq::end_code, input_code code4 = input_seq::end_code, input_code code5 = input_seq::end_code, input_code code6 = input_seq::end_code);
+ void reset() { set(); }
+ void set_default() { set(default_code); }
+ void backspace();
+ void replace(input_code oldcode, input_code newcode);
+
+ // constant codes used in sequences
+ static const input_code end_code;
+ static const input_code default_code;
+ static const input_code not_code;
+ static const input_code or_code;
+
+ // constant sequences
+ static const input_seq empty_seq;
+
+private:
+ // internal state
+ input_code m_code[16];
+};
+
+
+// ======================> input_device
+
+// a logical device of a given class that can provide input
+class input_device
+{
+ friend class input_class;
+
+ // construction/destruction
+ input_device(input_class &_class, int _devindex, const char *_name, void *_internal);
+
+public:
+ // getters
+ input_class &device_class() const { return m_class; }
+ input_manager &manager() const;
+ running_machine &machine() const;
+ input_device_class devclass() const;
+ const char *name() const { return m_name; }
+ int devindex() const { return m_devindex; }
+ input_device_item *item(input_item_id index) const { return m_item[index]; }
+ input_item_id maxitem() const { return m_maxitem; }
+ void *internal() const { return m_internal; }
+ joystick_map &joymap() { return m_joymap; }
+ bool steadykey_enabled() const { return m_steadykey_enabled; }
+ bool lightgun_reload_button() const { return m_lightgun_reload_button; }
+
+ // item management
+ input_item_id add_item(const char *name, input_item_id itemid, item_get_state_func getstate, void *internal = NULL);
+ void set_joystick_map(const joystick_map &map) { m_joymap = map; }
+
+ // helpers
+ INT32 apply_deadzone_and_saturation(INT32 value) const;
+ void apply_steadykey() const;
+
+private:
+ // internal state
+ input_class & m_class; // reference to our class
+ astring m_name; // string name of device
+ int m_devindex; // device index of this device
+ input_device_item * m_item[ITEM_ID_ABSOLUTE_MAXIMUM]; // array of pointers to items
+ input_item_id m_maxitem; // maximum item index
+ void * m_internal; // internal callback pointer
+
+ // joystick information
+ joystick_map m_joymap; // joystick map for this device
+ INT32 m_joystick_deadzone; // deadzone for joystick
+ INT32 m_joystick_saturation; // saturation position for joystick
+ bool m_steadykey_enabled; // steadykey enabled for keyboards
+ bool m_lightgun_reload_button; // lightgun reload hack
+};
+
+
+// ======================> input_class
+
+// a class of device that provides input
+class input_class
+{
+public:
+ // construction/destruction
+ input_class(input_manager &manager, input_device_class devclass, bool enabled = false, bool multi = false);
+
+ // getters
+ input_manager &manager() const { return m_manager; }
+ running_machine &machine() const;
+ input_device *device(int index) const { return (index <= m_maxindex) ? m_device[index] : NULL; }
+ input_device_class devclass() const { return m_devclass; }
+ int maxindex() const { return m_maxindex; }
+ bool enabled() const { return m_enabled; }
+ bool multi() const { return m_multi; }
+
+ // setters
+ void enable(bool state = true) { m_enabled = state; }
+ void set_multi(bool multi = true) { m_multi = multi; }
+
+ // device management
+ input_device *add_device(const char *name, void *internal = NULL);
+ input_device *add_device(int devindex, const char *name, void *internal = NULL);
+
+ // misc helpers
+ input_item_class standard_item_class(input_item_id itemid);
+
+private:
+ // internal helpers
+ void frame_callback();
+
+ // internal state
+ input_manager & m_manager; // reference to our manager
+ input_device * m_device[DEVICE_INDEX_MAXIMUM]; // array of devices in this class
+ input_device_class m_devclass; // our device class
+ int m_maxindex; // maximum populated index
+ bool m_enabled; // is this class enabled?
+ bool m_multi; // are multiple instances of this class allowed?
+};
+
+
+// ======================> input_manager
+
+// global machine-level information about devices
+class input_manager
+{
+public:
+ // construction/destruction
+ input_manager(running_machine &machine);
+
+ // getters
+ running_machine &machine() const { return m_machine; }
+ input_class &device_class(input_device_class devclass) { assert(devclass < ARRAY_LENGTH(m_class)); assert(m_class[devclass] != NULL); return *m_class[devclass]; }
+
+ // input code readers
+ INT32 code_value(input_code code);
+ bool code_pressed(input_code code) { return code_value(code) != 0; }
+ bool code_pressed_once(input_code code);
+
+ // input code polling
+ void reset_polling();
+ input_code poll_axes();
+ input_code poll_switches();
+ input_code poll_keyboard_switches();
+
+ // input code helpers
+ input_device *device_from_code(input_code code) const;
+ input_device_item *item_from_code(input_code code) const;
+ input_code code_from_itemid(input_item_id itemid) const;
+ const char *code_name(astring &string, input_code code) const;
+ const char *code_to_token(astring &string, input_code code) const;
+ input_code code_from_token(const char *_token);
+
+ // input sequence readers
+ bool seq_pressed(const input_seq &seq);
+ INT32 seq_axis_value(const input_seq &seq, input_item_class &itemclass);
+
+ // input sequence polling
+ void seq_poll_start(input_item_class itemclass, const input_seq *startseq = NULL);
+ bool seq_poll();
+ const input_seq &seq_poll_final() const { return m_poll_seq; }
+
+ // input sequence helpers
+ const char *seq_name(astring &string, const input_seq &seq) const;
+ const char *seq_to_tokens(astring &string, const input_seq &seq) const;
+ void seq_from_tokens(input_seq &seq, const char *_token);
+
+ // misc
+ bool set_global_joystick_map(const char *mapstring);
+
+private:
+ // internal helpers
+ void reset_memory();
+ bool code_check_axis(input_device_item &item, input_code code);
+
+ // internal state
+ running_machine & m_machine;
+ input_code m_switch_memory[64];
+
+ // classes
+ input_class m_keyboard_class;
+ input_class m_mouse_class;
+ input_class m_joystick_class;
+ input_class m_lightgun_class;
+ input_class * m_class[DEVICE_CLASS_MAXIMUM];
+
+ // sequence polling state
+ input_seq m_poll_seq;
+ osd_ticks_t m_poll_seq_last_ticks;
+ input_item_class m_poll_seq_class;
+};
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+// invalid codes
+#define INPUT_CODE_INVALID input_code()
+
+// keyboard codes
+#define KEYCODE_A_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_A)
+#define KEYCODE_B_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_B)
+#define KEYCODE_C_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_C)
+#define KEYCODE_D_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_D)
+#define KEYCODE_E_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_E)
+#define KEYCODE_F_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_F)
+#define KEYCODE_G_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_G)
+#define KEYCODE_H_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_H)
+#define KEYCODE_I_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_I)
+#define KEYCODE_J_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_J)
+#define KEYCODE_K_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_K)
+#define KEYCODE_L_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_L)
+#define KEYCODE_M_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_M)
+#define KEYCODE_N_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_N)
+#define KEYCODE_O_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_O)
+#define KEYCODE_P_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_P)
+#define KEYCODE_Q_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_Q)
+#define KEYCODE_R_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_R)
+#define KEYCODE_S_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_S)
+#define KEYCODE_T_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_T)
+#define KEYCODE_U_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_U)
+#define KEYCODE_V_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_V)
+#define KEYCODE_W_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_W)
+#define KEYCODE_X_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_X)
+#define KEYCODE_Y_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_Y)
+#define KEYCODE_Z_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_Z)
+#define KEYCODE_0_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_0)
+#define KEYCODE_1_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_1)
+#define KEYCODE_2_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_2)
+#define KEYCODE_3_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_3)
+#define KEYCODE_4_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_4)
+#define KEYCODE_5_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_5)
+#define KEYCODE_6_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_6)
+#define KEYCODE_7_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_7)
+#define KEYCODE_8_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_8)
+#define KEYCODE_9_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_9)
+#define KEYCODE_F1_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_F1)
+#define KEYCODE_F2_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_F2)
+#define KEYCODE_F3_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_F3)
+#define KEYCODE_F4_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_F4)
+#define KEYCODE_F5_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_F5)
+#define KEYCODE_F6_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_F6)
+#define KEYCODE_F7_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_F7)
+#define KEYCODE_F8_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_F8)
+#define KEYCODE_F9_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_F9)
+#define KEYCODE_F10_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_F10)
+#define KEYCODE_F11_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_F11)
+#define KEYCODE_F12_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_F12)
+#define KEYCODE_F13_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_F13)
+#define KEYCODE_F14_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_F14)
+#define KEYCODE_F15_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_F15)
+#define KEYCODE_ESC_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_ESC)
+#define KEYCODE_TILDE_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_TILDE)
+#define KEYCODE_MINUS_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_MINUS)
+#define KEYCODE_EQUALS_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_EQUALS)
+#define KEYCODE_BACKSPACE_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BACKSPACE)
+#define KEYCODE_TAB_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_TAB)
+#define KEYCODE_OPENBRACE_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_OPENBRACE)
+#define KEYCODE_CLOSEBRACE_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_CLOSEBRACE)
+#define KEYCODE_ENTER_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_ENTER)
+#define KEYCODE_COLON_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_COLON)
+#define KEYCODE_QUOTE_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_QUOTE)
+#define KEYCODE_BACKSLASH_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BACKSLASH)
+#define KEYCODE_BACKSLASH2_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BACKSLASH2)
+#define KEYCODE_COMMA_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_COMMA)
+#define KEYCODE_STOP_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_STOP)
+#define KEYCODE_SLASH_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_SLASH)
+#define KEYCODE_SPACE_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_SPACE)
+#define KEYCODE_INSERT_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_INSERT)
+#define KEYCODE_DEL_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_DEL)
+#define KEYCODE_HOME_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_HOME)
+#define KEYCODE_END_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_END)
+#define KEYCODE_PGUP_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_PGUP)
+#define KEYCODE_PGDN_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_PGDN)
+#define KEYCODE_LEFT_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_LEFT)
+#define KEYCODE_RIGHT_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_RIGHT)
+#define KEYCODE_UP_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_UP)
+#define KEYCODE_DOWN_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_DOWN)
+#define KEYCODE_0_PAD_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_0_PAD)
+#define KEYCODE_1_PAD_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_1_PAD)
+#define KEYCODE_2_PAD_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_2_PAD)
+#define KEYCODE_3_PAD_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_3_PAD)
+#define KEYCODE_4_PAD_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_4_PAD)
+#define KEYCODE_5_PAD_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_5_PAD)
+#define KEYCODE_6_PAD_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_6_PAD)
+#define KEYCODE_7_PAD_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_7_PAD)
+#define KEYCODE_8_PAD_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_8_PAD)
+#define KEYCODE_9_PAD_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_9_PAD)
+#define KEYCODE_SLASH_PAD_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_SLASH_PAD)
+#define KEYCODE_ASTERISK_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_ASTERISK)
+#define KEYCODE_MINUS_PAD_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_MINUS_PAD)
+#define KEYCODE_PLUS_PAD_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_PLUS_PAD)
+#define KEYCODE_DEL_PAD_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_DEL_PAD)
+#define KEYCODE_ENTER_PAD_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_ENTER_PAD)
+#define KEYCODE_PRTSCR_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_PRTSCR)
+#define KEYCODE_PAUSE_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_PAUSE)
+#define KEYCODE_LSHIFT_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_LSHIFT)
+#define KEYCODE_RSHIFT_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_RSHIFT)
+#define KEYCODE_LCONTROL_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_LCONTROL)
+#define KEYCODE_RCONTROL_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_RCONTROL)
+#define KEYCODE_LALT_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_LALT)
+#define KEYCODE_RALT_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_RALT)
+#define KEYCODE_SCRLOCK_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_SCRLOCK)
+#define KEYCODE_NUMLOCK_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_NUMLOCK)
+#define KEYCODE_CAPSLOCK_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_CAPSLOCK)
+#define KEYCODE_LWIN_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_LWIN)
+#define KEYCODE_RWIN_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_RWIN)
+#define KEYCODE_MENU_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_MENU)
+#define KEYCODE_CANCEL_INDEXED(n) input_code(DEVICE_CLASS_KEYBOARD, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_CANCEL)
+
+#define KEYCODE_A KEYCODE_A_INDEXED(0)
+#define KEYCODE_B KEYCODE_B_INDEXED(0)
+#define KEYCODE_C KEYCODE_C_INDEXED(0)
+#define KEYCODE_D KEYCODE_D_INDEXED(0)
+#define KEYCODE_E KEYCODE_E_INDEXED(0)
+#define KEYCODE_F KEYCODE_F_INDEXED(0)
+#define KEYCODE_G KEYCODE_G_INDEXED(0)
+#define KEYCODE_H KEYCODE_H_INDEXED(0)
+#define KEYCODE_I KEYCODE_I_INDEXED(0)
+#define KEYCODE_J KEYCODE_J_INDEXED(0)
+#define KEYCODE_K KEYCODE_K_INDEXED(0)
+#define KEYCODE_L KEYCODE_L_INDEXED(0)
+#define KEYCODE_M KEYCODE_M_INDEXED(0)
+#define KEYCODE_N KEYCODE_N_INDEXED(0)
+#define KEYCODE_O KEYCODE_O_INDEXED(0)
+#define KEYCODE_P KEYCODE_P_INDEXED(0)
+#define KEYCODE_Q KEYCODE_Q_INDEXED(0)
+#define KEYCODE_R KEYCODE_R_INDEXED(0)
+#define KEYCODE_S KEYCODE_S_INDEXED(0)
+#define KEYCODE_T KEYCODE_T_INDEXED(0)
+#define KEYCODE_U KEYCODE_U_INDEXED(0)
+#define KEYCODE_V KEYCODE_V_INDEXED(0)
+#define KEYCODE_W KEYCODE_W_INDEXED(0)
+#define KEYCODE_X KEYCODE_X_INDEXED(0)
+#define KEYCODE_Y KEYCODE_Y_INDEXED(0)
+#define KEYCODE_Z KEYCODE_Z_INDEXED(0)
+#define KEYCODE_0 KEYCODE_0_INDEXED(0)
+#define KEYCODE_1 KEYCODE_1_INDEXED(0)
+#define KEYCODE_2 KEYCODE_2_INDEXED(0)
+#define KEYCODE_3 KEYCODE_3_INDEXED(0)
+#define KEYCODE_4 KEYCODE_4_INDEXED(0)
+#define KEYCODE_5 KEYCODE_5_INDEXED(0)
+#define KEYCODE_6 KEYCODE_6_INDEXED(0)
+#define KEYCODE_7 KEYCODE_7_INDEXED(0)
+#define KEYCODE_8 KEYCODE_8_INDEXED(0)
+#define KEYCODE_9 KEYCODE_9_INDEXED(0)
+#define KEYCODE_F1 KEYCODE_F1_INDEXED(0)
+#define KEYCODE_F2 KEYCODE_F2_INDEXED(0)
+#define KEYCODE_F3 KEYCODE_F3_INDEXED(0)
+#define KEYCODE_F4 KEYCODE_F4_INDEXED(0)
+#define KEYCODE_F5 KEYCODE_F5_INDEXED(0)
+#define KEYCODE_F6 KEYCODE_F6_INDEXED(0)
+#define KEYCODE_F7 KEYCODE_F7_INDEXED(0)
+#define KEYCODE_F8 KEYCODE_F8_INDEXED(0)
+#define KEYCODE_F9 KEYCODE_F9_INDEXED(0)
+#define KEYCODE_F10 KEYCODE_F10_INDEXED(0)
+#define KEYCODE_F11 KEYCODE_F11_INDEXED(0)
+#define KEYCODE_F12 KEYCODE_F12_INDEXED(0)
+#define KEYCODE_F13 KEYCODE_F13_INDEXED(0)
+#define KEYCODE_F14 KEYCODE_F14_INDEXED(0)
+#define KEYCODE_F15 KEYCODE_F15_INDEXED(0)
+#define KEYCODE_ESC KEYCODE_ESC_INDEXED(0)
+#define KEYCODE_TILDE KEYCODE_TILDE_INDEXED(0)
+#define KEYCODE_MINUS KEYCODE_MINUS_INDEXED(0)
+#define KEYCODE_EQUALS KEYCODE_EQUALS_INDEXED(0)
+#define KEYCODE_BACKSPACE KEYCODE_BACKSPACE_INDEXED(0)
+#define KEYCODE_TAB KEYCODE_TAB_INDEXED(0)
+#define KEYCODE_OPENBRACE KEYCODE_OPENBRACE_INDEXED(0)
+#define KEYCODE_CLOSEBRACE KEYCODE_CLOSEBRACE_INDEXED(0)
+#define KEYCODE_ENTER KEYCODE_ENTER_INDEXED(0)
+#define KEYCODE_COLON KEYCODE_COLON_INDEXED(0)
+#define KEYCODE_QUOTE KEYCODE_QUOTE_INDEXED(0)
+#define KEYCODE_BACKSLASH KEYCODE_BACKSLASH_INDEXED(0)
+#define KEYCODE_BACKSLASH2 KEYCODE_BACKSLASH2_INDEXED(0)
+#define KEYCODE_COMMA KEYCODE_COMMA_INDEXED(0)
+#define KEYCODE_STOP KEYCODE_STOP_INDEXED(0)
+#define KEYCODE_SLASH KEYCODE_SLASH_INDEXED(0)
+#define KEYCODE_SPACE KEYCODE_SPACE_INDEXED(0)
+#define KEYCODE_INSERT KEYCODE_INSERT_INDEXED(0)
+#define KEYCODE_DEL KEYCODE_DEL_INDEXED(0)
+#define KEYCODE_HOME KEYCODE_HOME_INDEXED(0)
+#define KEYCODE_END KEYCODE_END_INDEXED(0)
+#define KEYCODE_PGUP KEYCODE_PGUP_INDEXED(0)
+#define KEYCODE_PGDN KEYCODE_PGDN_INDEXED(0)
+#define KEYCODE_LEFT KEYCODE_LEFT_INDEXED(0)
+#define KEYCODE_RIGHT KEYCODE_RIGHT_INDEXED(0)
+#define KEYCODE_UP KEYCODE_UP_INDEXED(0)
+#define KEYCODE_DOWN KEYCODE_DOWN_INDEXED(0)
+#define KEYCODE_0_PAD KEYCODE_0_PAD_INDEXED(0)
+#define KEYCODE_1_PAD KEYCODE_1_PAD_INDEXED(0)
+#define KEYCODE_2_PAD KEYCODE_2_PAD_INDEXED(0)
+#define KEYCODE_3_PAD KEYCODE_3_PAD_INDEXED(0)
+#define KEYCODE_4_PAD KEYCODE_4_PAD_INDEXED(0)
+#define KEYCODE_5_PAD KEYCODE_5_PAD_INDEXED(0)
+#define KEYCODE_6_PAD KEYCODE_6_PAD_INDEXED(0)
+#define KEYCODE_7_PAD KEYCODE_7_PAD_INDEXED(0)
+#define KEYCODE_8_PAD KEYCODE_8_PAD_INDEXED(0)
+#define KEYCODE_9_PAD KEYCODE_9_PAD_INDEXED(0)
+#define KEYCODE_SLASH_PAD KEYCODE_SLASH_PAD_INDEXED(0)
+#define KEYCODE_ASTERISK KEYCODE_ASTERISK_INDEXED(0)
+#define KEYCODE_MINUS_PAD KEYCODE_MINUS_PAD_INDEXED(0)
+#define KEYCODE_PLUS_PAD KEYCODE_PLUS_PAD_INDEXED(0)
+#define KEYCODE_DEL_PAD KEYCODE_DEL_PAD_INDEXED(0)
+#define KEYCODE_ENTER_PAD KEYCODE_ENTER_PAD_INDEXED(0)
+#define KEYCODE_PRTSCR KEYCODE_PRTSCR_INDEXED(0)
+#define KEYCODE_PAUSE KEYCODE_PAUSE_INDEXED(0)
+#define KEYCODE_LSHIFT KEYCODE_LSHIFT_INDEXED(0)
+#define KEYCODE_RSHIFT KEYCODE_RSHIFT_INDEXED(0)
+#define KEYCODE_LCONTROL KEYCODE_LCONTROL_INDEXED(0)
+#define KEYCODE_RCONTROL KEYCODE_RCONTROL_INDEXED(0)
+#define KEYCODE_LALT KEYCODE_LALT_INDEXED(0)
+#define KEYCODE_RALT KEYCODE_RALT_INDEXED(0)
+#define KEYCODE_SCRLOCK KEYCODE_SCRLOCK_INDEXED(0)
+#define KEYCODE_NUMLOCK KEYCODE_NUMLOCK_INDEXED(0)
+#define KEYCODE_CAPSLOCK KEYCODE_CAPSLOCK_INDEXED(0)
+#define KEYCODE_LWIN KEYCODE_LWIN_INDEXED(0)
+#define KEYCODE_RWIN KEYCODE_RWIN_INDEXED(0)
+#define KEYCODE_MENU KEYCODE_MENU_INDEXED(0)
+#define KEYCODE_CANCEL KEYCODE_CANCEL_INDEXED(0)
+
+// mouse axes as relative devices
+#define MOUSECODE_X_INDEXED(n) input_code(DEVICE_CLASS_MOUSE, n, ITEM_CLASS_RELATIVE, ITEM_MODIFIER_NONE, ITEM_ID_XAXIS)
+#define MOUSECODE_Y_INDEXED(n) input_code(DEVICE_CLASS_MOUSE, n, ITEM_CLASS_RELATIVE, ITEM_MODIFIER_NONE, ITEM_ID_YAXIS)
+#define MOUSECODE_Z_INDEXED(n) input_code(DEVICE_CLASS_MOUSE, n, ITEM_CLASS_RELATIVE, ITEM_MODIFIER_NONE, ITEM_ID_ZAXIS)
+
+#define MOUSECODE_X MOUSECODE_X_INDEXED(0)
+#define MOUSECODE_Y MOUSECODE_Y_INDEXED(0)
+#define MOUSECODE_Z MOUSECODE_Z_INDEXED(0)
+
+// mouse axes as switches in +/- direction
+#define MOUSECODE_X_POS_SWITCH_INDEXED(n) input_code(DEVICE_CLASS_MOUSE, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_POS, ITEM_ID_XAXIS)
+#define MOUSECODE_X_NEG_SWITCH_INDEXED(n) input_code(DEVICE_CLASS_MOUSE, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, ITEM_ID_XAXIS)
+#define MOUSECODE_Y_POS_SWITCH_INDEXED(n) input_code(DEVICE_CLASS_MOUSE, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_POS, ITEM_ID_YAXIS)
+#define MOUSECODE_Y_NEG_SWITCH_INDEXED(n) input_code(DEVICE_CLASS_MOUSE, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, ITEM_ID_YAXIS)
+#define MOUSECODE_Z_POS_SWITCH_INDEXED(n) input_code(DEVICE_CLASS_MOUSE, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_POS, ITEM_ID_ZAXIS)
+#define MOUSECODE_Z_NEG_SWITCH_INDEXED(n) input_code(DEVICE_CLASS_MOUSE, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, ITEM_ID_ZAXIS)
+
+#define MOUSECODE_X_POS_SWITCH MOUSECODE_X_POS_SWITCH_INDEXED(0)
+#define MOUSECODE_X_NEG_SWITCH MOUSECODE_X_NEG_SWITCH_INDEXED(0)
+#define MOUSECODE_Y_POS_SWITCH MOUSECODE_Y_POS_SWITCH_INDEXED(0)
+#define MOUSECODE_Y_NEG_SWITCH MOUSECODE_Y_NEG_SWITCH_INDEXED(0)
+#define MOUSECODE_Z_POS_SWITCH MOUSECODE_Z_POS_SWITCH_INDEXED(0)
+#define MOUSECODE_Z_NEG_SWITCH MOUSECODE_Z_NEG_SWITCH_INDEXED(0)
+
+// mouse buttons
+#define MOUSECODE_BUTTON1_INDEXED(n) input_code(DEVICE_CLASS_MOUSE, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON1)
+#define MOUSECODE_BUTTON2_INDEXED(n) input_code(DEVICE_CLASS_MOUSE, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON2)
+#define MOUSECODE_BUTTON3_INDEXED(n) input_code(DEVICE_CLASS_MOUSE, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON3)
+#define MOUSECODE_BUTTON4_INDEXED(n) input_code(DEVICE_CLASS_MOUSE, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON4)
+#define MOUSECODE_BUTTON5_INDEXED(n) input_code(DEVICE_CLASS_MOUSE, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON5)
+#define MOUSECODE_BUTTON6_INDEXED(n) input_code(DEVICE_CLASS_MOUSE, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON6)
+#define MOUSECODE_BUTTON7_INDEXED(n) input_code(DEVICE_CLASS_MOUSE, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON7)
+#define MOUSECODE_BUTTON8_INDEXED(n) input_code(DEVICE_CLASS_MOUSE, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON8)
+
+#define MOUSECODE_BUTTON1 MOUSECODE_BUTTON1_INDEXED(0)
+#define MOUSECODE_BUTTON2 MOUSECODE_BUTTON2_INDEXED(0)
+#define MOUSECODE_BUTTON3 MOUSECODE_BUTTON3_INDEXED(0)
+#define MOUSECODE_BUTTON4 MOUSECODE_BUTTON4_INDEXED(0)
+#define MOUSECODE_BUTTON5 MOUSECODE_BUTTON5_INDEXED(0)
+#define MOUSECODE_BUTTON6 MOUSECODE_BUTTON6_INDEXED(0)
+#define MOUSECODE_BUTTON7 MOUSECODE_BUTTON7_INDEXED(0)
+#define MOUSECODE_BUTTON8 MOUSECODE_BUTTON8_INDEXED(0)
+
+// gun axes as absolute devices
+#define GUNCODE_X_INDEXED(n) input_code(DEVICE_CLASS_LIGHTGUN, n, ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NONE, ITEM_ID_XAXIS)
+#define GUNCODE_Y_INDEXED(n) input_code(DEVICE_CLASS_LIGHTGUN, n, ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NONE, ITEM_ID_YAXIS)
+
+#define GUNCODE_X GUNCODE_X_INDEXED(0)
+#define GUNCODE_Y GUNCODE_Y_INDEXED(0)
+
+// gun buttons
+#define GUNCODE_BUTTON1_INDEXED(n) input_code(DEVICE_CLASS_LIGHTGUN, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON1)
+#define GUNCODE_BUTTON2_INDEXED(n) input_code(DEVICE_CLASS_LIGHTGUN, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON2)
+#define GUNCODE_BUTTON3_INDEXED(n) input_code(DEVICE_CLASS_LIGHTGUN, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON3)
+#define GUNCODE_BUTTON4_INDEXED(n) input_code(DEVICE_CLASS_LIGHTGUN, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON4)
+#define GUNCODE_BUTTON5_INDEXED(n) input_code(DEVICE_CLASS_LIGHTGUN, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON5)
+#define GUNCODE_BUTTON6_INDEXED(n) input_code(DEVICE_CLASS_LIGHTGUN, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON6)
+#define GUNCODE_BUTTON7_INDEXED(n) input_code(DEVICE_CLASS_LIGHTGUN, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON7)
+#define GUNCODE_BUTTON8_INDEXED(n) input_code(DEVICE_CLASS_LIGHTGUN, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON8)
+
+#define GUNCODE_BUTTON1 GUNCODE_BUTTON1_INDEXED(0)
+#define GUNCODE_BUTTON2 GUNCODE_BUTTON2_INDEXED(0)
+#define GUNCODE_BUTTON3 GUNCODE_BUTTON3_INDEXED(0)
+#define GUNCODE_BUTTON4 GUNCODE_BUTTON4_INDEXED(0)
+#define GUNCODE_BUTTON5 GUNCODE_BUTTON5_INDEXED(0)
+#define GUNCODE_BUTTON6 GUNCODE_BUTTON6_INDEXED(0)
+#define GUNCODE_BUTTON7 GUNCODE_BUTTON7_INDEXED(0)
+#define GUNCODE_BUTTON8 GUNCODE_BUTTON8_INDEXED(0)
+
+// joystick axes as absolute devices
+#define JOYCODE_X_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NONE, ITEM_ID_XAXIS)
+#define JOYCODE_Y_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NONE, ITEM_ID_YAXIS)
+#define JOYCODE_Z_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NONE, ITEM_ID_ZAXIS)
+#define JOYCODE_U_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NONE, ITEM_ID_RXAXIS)
+#define JOYCODE_V_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NONE, ITEM_ID_RYAXIS)
+
+#define JOYCODE_X JOYCODE_X_INDEXED(0)
+#define JOYCODE_Y JOYCODE_Y_INDEXED(0)
+#define JOYCODE_Z JOYCODE_Z_INDEXED(0)
+#define JOYCODE_U JOYCODE_U_INDEXED(0)
+#define JOYCODE_V JOYCODE_V_INDEXED(0)
+
+// joystick axes as absolute half-axes
+#define JOYCODE_X_POS_ABSOLUTE_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_POS, ITEM_ID_XAXIS)
+#define JOYCODE_X_NEG_ABSOLUTE_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NEG, ITEM_ID_XAXIS)
+#define JOYCODE_Y_POS_ABSOLUTE_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_POS, ITEM_ID_YAXIS)
+#define JOYCODE_Y_NEG_ABSOLUTE_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NEG, ITEM_ID_YAXIS)
+#define JOYCODE_Z_POS_ABSOLUTE_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_POS, ITEM_ID_ZAXIS)
+#define JOYCODE_Z_NEG_ABSOLUTE_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NEG, ITEM_ID_ZAXIS)
+#define JOYCODE_U_POS_ABSOLUTE_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_POS, ITEM_ID_RXAXIS)
+#define JOYCODE_U_NEG_ABSOLUTE_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NEG, ITEM_ID_RXAXIS)
+#define JOYCODE_V_POS_ABSOLUTE_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_POS, ITEM_ID_RYAXIS)
+#define JOYCODE_V_NEG_ABSOLUTE_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_ABSOLUTE, ITEM_MODIFIER_NEG, ITEM_ID_RYAXIS)
+
+#define JOYCODE_X_POS_ABSOLUTE JOYCODE_X_POS_ABSOLUTE_INDEXED(0)
+#define JOYCODE_X_NEG_ABSOLUTE JOYCODE_X_NEG_ABSOLUTE_INDEXED(0)
+#define JOYCODE_Y_POS_ABSOLUTE JOYCODE_Y_POS_ABSOLUTE_INDEXED(0)
+#define JOYCODE_Y_NEG_ABSOLUTE JOYCODE_Y_NEG_ABSOLUTE_INDEXED(0)
+#define JOYCODE_Z_POS_ABSOLUTE JOYCODE_Z_POS_ABSOLUTE_INDEXED(0)
+#define JOYCODE_Z_NEG_ABSOLUTE JOYCODE_Z_NEG_ABSOLUTE_INDEXED(0)
+#define JOYCODE_U_POS_ABSOLUTE JOYCODE_U_POS_ABSOLUTE_INDEXED(0)
+#define JOYCODE_U_NEG_ABSOLUTE JOYCODE_U_NEG_ABSOLUTE_INDEXED(0)
+#define JOYCODE_V_POS_ABSOLUTE JOYCODE_V_POS_ABSOLUTE_INDEXED(0)
+#define JOYCODE_V_NEG_ABSOLUTE JOYCODE_V_NEG_ABSOLUTE_INDEXED(0)
+
+// joystick axes as switches; X/Y are specially handled for left/right/up/down mapping
+#define JOYCODE_X_LEFT_SWITCH_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_LEFT, ITEM_ID_XAXIS)
+#define JOYCODE_X_RIGHT_SWITCH_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_RIGHT, ITEM_ID_XAXIS)
+#define JOYCODE_Y_UP_SWITCH_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_UP, ITEM_ID_YAXIS)
+#define JOYCODE_Y_DOWN_SWITCH_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_DOWN, ITEM_ID_YAXIS)
+#define JOYCODE_Z_POS_SWITCH_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_POS, ITEM_ID_ZAXIS)
+#define JOYCODE_Z_NEG_SWITCH_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, ITEM_ID_ZAXIS)
+#define JOYCODE_U_POS_SWITCH_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_POS, ITEM_ID_RXAXIS)
+#define JOYCODE_U_NEG_SWITCH_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, ITEM_ID_RXAXIS)
+#define JOYCODE_V_POS_SWITCH_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_POS, ITEM_ID_RYAXIS)
+#define JOYCODE_V_NEG_SWITCH_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NEG, ITEM_ID_RYAXIS)
+
+#define JOYCODE_X_LEFT_SWITCH JOYCODE_X_LEFT_SWITCH_INDEXED(0)
+#define JOYCODE_X_RIGHT_SWITCH JOYCODE_X_RIGHT_SWITCH_INDEXED(0)
+#define JOYCODE_Y_UP_SWITCH JOYCODE_Y_UP_SWITCH_INDEXED(0)
+#define JOYCODE_Y_DOWN_SWITCH JOYCODE_Y_DOWN_SWITCH_INDEXED(0)
+#define JOYCODE_Z_POS_SWITCH JOYCODE_Z_POS_SWITCH_INDEXED(0)
+#define JOYCODE_Z_NEG_SWITCH JOYCODE_Z_NEG_SWITCH_INDEXED(0)
+#define JOYCODE_U_POS_SWITCH JOYCODE_U_POS_SWITCH_INDEXED(0)
+#define JOYCODE_U_NEG_SWITCH JOYCODE_U_NEG_SWITCH_INDEXED(0)
+#define JOYCODE_V_POS_SWITCH JOYCODE_V_POS_SWITCH_INDEXED(0)
+#define JOYCODE_V_NEG_SWITCH JOYCODE_V_NEG_SWITCH_INDEXED(0)
+
+// joystick buttons
+#define JOYCODE_BUTTON1_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON1)
+#define JOYCODE_BUTTON2_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON2)
+#define JOYCODE_BUTTON3_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON3)
+#define JOYCODE_BUTTON4_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON4)
+#define JOYCODE_BUTTON5_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON5)
+#define JOYCODE_BUTTON6_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON6)
+#define JOYCODE_BUTTON7_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON7)
+#define JOYCODE_BUTTON8_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON8)
+#define JOYCODE_BUTTON9_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON9)
+#define JOYCODE_BUTTON10_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON10)
+#define JOYCODE_BUTTON11_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON11)
+#define JOYCODE_BUTTON12_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON12)
+#define JOYCODE_BUTTON13_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON13)
+#define JOYCODE_BUTTON14_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON14)
+#define JOYCODE_BUTTON15_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON15)
+#define JOYCODE_BUTTON16_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_BUTTON16)
+#define JOYCODE_START_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_START)
+#define JOYCODE_SELECT_INDEXED(n) input_code(DEVICE_CLASS_JOYSTICK, n, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, ITEM_ID_SELECT)
+
+#define JOYCODE_BUTTON1 JOYCODE_BUTTON1_INDEXED(0)
+#define JOYCODE_BUTTON2 JOYCODE_BUTTON2_INDEXED(0)
+#define JOYCODE_BUTTON3 JOYCODE_BUTTON3_INDEXED(0)
+#define JOYCODE_BUTTON4 JOYCODE_BUTTON4_INDEXED(0)
+#define JOYCODE_BUTTON5 JOYCODE_BUTTON5_INDEXED(0)
+#define JOYCODE_BUTTON6 JOYCODE_BUTTON6_INDEXED(0)
+#define JOYCODE_BUTTON7 JOYCODE_BUTTON7_INDEXED(0)
+#define JOYCODE_BUTTON8 JOYCODE_BUTTON8_INDEXED(0)
+#define JOYCODE_BUTTON9 JOYCODE_BUTTON9_INDEXED(0)
+#define JOYCODE_BUTTON10 JOYCODE_BUTTON10_INDEXED(0)
+#define JOYCODE_BUTTON11 JOYCODE_BUTTON11_INDEXED(0)
+#define JOYCODE_BUTTON12 JOYCODE_BUTTON12_INDEXED(0)
+#define JOYCODE_BUTTON13 JOYCODE_BUTTON13_INDEXED(0)
+#define JOYCODE_BUTTON14 JOYCODE_BUTTON14_INDEXED(0)
+#define JOYCODE_BUTTON15 JOYCODE_BUTTON15_INDEXED(0)
+#define JOYCODE_BUTTON16 JOYCODE_BUTTON16_INDEXED(0)
+#define JOYCODE_START JOYCODE_START_INDEXED(0)
+#define JOYCODE_SELECT JOYCODE_SELECT_INDEXED(0)
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// joystick maps
+extern const char joystick_map_8way[];
+extern const char joystick_map_4way_sticky[];
+extern const char joystick_map_4way_diagonal[];
+
+
+//**************************************************************************
+// INLINE FUNCTIONS
+//**************************************************************************
+
+// input_device helpers
+inline input_manager &input_device::manager() const { return m_class.manager(); }
+inline running_machine &input_device::machine() const { return m_class.machine(); }
+inline input_device_class input_device::devclass() const { return m_class.devclass(); }
+
+// input_class helpers
+inline running_machine &input_class::machine() const { return m_manager.machine(); }
+
+
+#endif // __INPUT_H__
diff --git a/trunk/src/emu/ioport.c b/trunk/src/emu/ioport.c
new file mode 100644
index 00000000000..7b00ad2cf75
--- /dev/null
+++ b/trunk/src/emu/ioport.c
@@ -0,0 +1,4892 @@
+/***************************************************************************
+
+ ioport.c
+
+ Input/output port handling.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+****************************************************************************
+
+ Theory of operation
+
+ ------------
+ OSD controls
+ ------------
+
+ There are three types of controls that the OSD can provide as potential
+ input devices: digital controls, absolute analog controls, and relative
+ analog controls.
+
+ Digital controls have only two states: on or off. They are generally
+ mapped to buttons and digital joystick directions (like a gamepad or a
+ joystick hat). The OSD layer must return either 0 (off) or 1 (on) for
+ these types of controls.
+
+ Absolute analog controls are analog in the sense that they return a
+ range of values depending on how much a given control is moved, but they
+ are physically bounded. This means that there is a minimum and maximum
+ limit to how far the control can be moved. They are generally mapped to
+ analog joystick axes, lightguns, most PC steering wheels, and pedals.
+ The OSD layer must determine the minimum and maximum range of each
+ analog device and scale that to a value between -65536 and +65536
+ representing the position of the control. -65536 generally refers to
+ the topmost or leftmost position, while +65536 refers to the bottommost
+ or rightmost position. Note that pedals are a special case here, the
+ OSD layer needs to return half axis as full -65536 to + 65536 range.
+
+ Relative analog controls are analog as well, but are not physically
+ bounded. They can be moved continually in one direction without limit.
+ They are generally mapped to trackballs and mice. Because they are
+ unbounded, the OSD layer can only return delta values since the last
+ read. Because of this, it is difficult to scale appropriately. For
+ MAME's purposes, when mapping a mouse devices to a relative analog
+ control, one pixel of movement should correspond to 512 units. Other
+ analog control types should be scaled to return values of a similar
+ magnitude. Like absolute analog controls, negative values refer to
+ upward or leftward movement, while positive values refer to downward
+ or rightward movement.
+
+ -------------
+ Game controls
+ -------------
+
+ Similarly, the types of controls used by arcade games fall into the same
+ three categories: digital, absolute analog, and relative analog. The
+ tricky part is how to map any arbitrary type of OSD control to an
+ arbitrary type of game control.
+
+ Digital controls: used for game buttons and standard 4/8-way joysticks,
+ as well as many other types of game controls. Mapping an OSD digital
+ control to a game's OSD control is trivial. For OSD analog controls,
+ the MAME core does not directly support mapping any OSD analog devices
+ to digital controls. However, the OSD layer is free to enumerate digital
+ equivalents for analog devices. For example, each analog axis in the
+ Windows OSD code enumerates to two digital controls, one for the
+ negative direction (up/left) and one for the position direction
+ (down/right). When these "digital" inputs are queried, the OSD layer
+ checks the axis position against the center, adding in a dead zone,
+ and returns 0 or 1 to indicate its position.
+
+ Absolute analog controls: used for analog joysticks, lightguns, pedals,
+ and wheel controls. Mapping an OSD absolute analog control to this type
+ is easy. OSD relative analog controls can be mapped here as well by
+ accumulating the deltas and bounding the results. OSD digital controls
+ are mapped to these types of controls in pairs, one for a decrement and
+ one for an increment, but apart from that, operate the same as the OSD
+ relative analog controls by accumulating deltas and applying bounds.
+ The speed of the digital delta is user-configurable per analog input.
+ In addition, most absolute analog control types have an autocentering
+ feature that is activated when using the digital increment/decrement
+ sequences, which returns the control back to the center at a user-
+ controllable speed if no digital sequences are pressed.
+
+ Relative analog controls: used for trackballs and dial controls. Again,
+ mapping an OSD relative analog control to this type is straightforward.
+ OSD absolute analog controls can't map directly to these, but if the OSD
+ layer provides a digital equivalent for each direction, it can be done.
+ OSD digital controls map just like they do for absolute analog controls,
+ except that the accumulated deltas are not bounded, but rather wrap.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "emuopts.h"
+#include "config.h"
+#include "xmlfile.h"
+#include "profiler.h"
+#include "ui.h"
+#include "uiinput.h"
+#include "debug/debugcon.h"
+
+#include <ctype.h>
+#include <time.h>
+
+/* temporary: set this to 1 to enable the originally defined behavior that
+ a field specified via PORT_MODIFY which intersects a previously-defined
+ field completely wipes out the previous definition */
+#define INPUT_PORT_OVERRIDE_FULLY_NUKES_PREVIOUS 1
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define DIGITAL_JOYSTICKS_PER_PLAYER 3
+
+/* these constants must match the order of the joystick directions in the IPT definition */
+#define JOYDIR_UP 0
+#define JOYDIR_DOWN 1
+#define JOYDIR_LEFT 2
+#define JOYDIR_RIGHT 3
+
+#define JOYDIR_UP_BIT (1 << JOYDIR_UP)
+#define JOYDIR_DOWN_BIT (1 << JOYDIR_DOWN)
+#define JOYDIR_LEFT_BIT (1 << JOYDIR_LEFT)
+#define JOYDIR_RIGHT_BIT (1 << JOYDIR_RIGHT)
+
+#define NUM_SIMUL_KEYS (UCHAR_SHIFT_END - UCHAR_SHIFT_BEGIN + 1)
+#define LOG_INPUTX 0
+#define SPACE_COUNT 3
+#define INVALID_CHAR '?'
+#define IP_NAME_DEFAULT NULL
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/* live analog field information */
+typedef struct _analog_field_state analog_field_state;
+struct _analog_field_state
+{
+ analog_field_state * next; /* link to the next analog state for this port */
+ const input_field_config * field; /* pointer to the input field referenced */
+
+ /* adjusted values (right-justified and tweaked) */
+ UINT8 shift; /* shift to align final value in the port */
+ INT32 adjdefvalue; /* adjusted default value from the config */
+ INT32 adjmin; /* adjusted minimum value from the config */
+ INT32 adjmax; /* adjusted maximum value from the config */
+
+ /* live values of configurable parameters */
+ INT32 sensitivity; /* current live sensitivity (100=normal) */
+ UINT8 reverse; /* current live reverse flag */
+ INT32 delta; /* current live delta to apply each frame a digital inc/dec key is pressed */
+ INT32 centerdelta; /* current live delta to apply each frame no digital inputs are pressed */
+
+ /* live analog value tracking */
+ INT32 accum; /* accumulated value (including relative adjustments) */
+ INT32 previous; /* previous adjusted value */
+ INT32 previousanalog; /* previous analog value */
+
+ /* parameters for modifying live values */
+ INT32 minimum; /* minimum adjusted value */
+ INT32 maximum; /* maximum adjusted value */
+ INT32 center; /* center adjusted value for autocentering */
+ INT32 reverse_val; /* value where we subtract from to reverse directions */
+
+ /* scaling factors */
+ INT64 scalepos; /* scale factor to apply to positive adjusted values */
+ INT64 scaleneg; /* scale factor to apply to negative adjusted values */
+ INT64 keyscalepos; /* scale factor to apply to the key delta field when pos */
+ INT64 keyscaleneg; /* scale factor to apply to the key delta field when neg */
+ INT64 positionalscale; /* scale factor to divide a joystick into positions */
+
+ /* misc flags */
+ UINT8 absolute; /* is this an absolute or relative input? */
+ UINT8 wraps; /* does the control wrap around? */
+ UINT8 autocenter; /* autocenter this input? */
+ UINT8 single_scale; /* scale joystick differently if default is between min/max */
+ UINT8 interpolate; /* should we do linear interpolation for mid-frame reads? */
+ UINT8 lastdigital; /* was the last modification caused by a digital form? */
+};
+
+
+/* shared digital joystick state */
+typedef struct _digital_joystick_state digital_joystick_state;
+struct _digital_joystick_state
+{
+ const input_field_config * field[4]; /* input field for up, down, left, right respectively */
+ UINT8 inuse; /* is this joystick used? */
+ UINT8 current; /* current value */
+ UINT8 current4way; /* current 4-way value */
+ UINT8 previous; /* previous value */
+};
+
+
+/* live device field information */
+typedef struct _device_field_info device_field_info;
+struct _device_field_info
+{
+ device_field_info * next; /* linked list of info for this port */
+ const input_field_config * field; /* pointer to the input field referenced */
+ device_t * device; /* device */
+ UINT8 shift; /* shift to apply to the final result */
+ input_port_value oldval; /* last value */
+};
+
+
+/* internal live state of an input field */
+struct _input_field_state
+{
+ analog_field_state * analog; /* pointer to live analog data if this is an analog field */
+ digital_joystick_state * joystick; /* pointer to digital joystick information */
+ input_seq seq[SEQ_TYPE_TOTAL];/* currently configured input sequences */
+ input_port_value value; /* current value of this port */
+ UINT8 impulse; /* counter for impulse controls */
+ UINT8 last; /* were we pressed last time? */
+ UINT8 joydir; /* digital joystick direction index */
+ char * name; /* overridden name */
+};
+
+
+/* internal live state of an input port */
+struct _input_port_state
+{
+ analog_field_state * analoglist; /* pointer to list of analog port info */
+ device_field_info * readdevicelist; /* pointer to list of input device info */
+ device_field_info * writedevicelist; /* pointer to list of output device info */
+ input_port_value defvalue; /* combined default value across the port */
+ input_port_value digital; /* current value from all digital inputs */
+ input_port_value vblank; /* value of all IPT_VBLANK bits */
+ input_port_value outputvalue; /* current value for outputs */
+};
+
+
+typedef struct _inputx_code inputx_code;
+struct _inputx_code
+{
+ unicode_char ch;
+ const input_field_config * field[NUM_SIMUL_KEYS];
+};
+
+typedef struct _key_buffer key_buffer;
+struct _key_buffer
+{
+ int begin_pos;
+ int end_pos;
+ unsigned int status_keydown : 1;
+ unicode_char buffer[4096];
+};
+
+typedef struct _char_info char_info;
+struct _char_info
+{
+ unicode_char ch;
+ const char *name;
+ const char *alternate; /* alternative string, in UTF-8 */
+};
+
+
+/* private input port state */
+struct _input_port_private
+{
+ /* global state */
+ UINT8 safe_to_read; /* clear at start; set after state is loaded */
+
+ /* types */
+ simple_list<input_type_entry> typelist; /* list of live type states */
+ input_type_entry * type_to_entry[__ipt_max][MAX_PLAYERS]; /* map from type/player to type state */
+
+ /* specific special global input states */
+ digital_joystick_state joystick_info[MAX_PLAYERS][DIGITAL_JOYSTICKS_PER_PLAYER]; /* joystick states */
+
+ /* frame time tracking */
+ attotime last_frame_time; /* time of the last frame callback */
+ attoseconds_t last_delta_nsec; /* nanoseconds that passed since the previous callback */
+
+ /* playback/record information */
+ emu_file * record_file; /* recording file (NULL if not recording) */
+ emu_file * playback_file; /* playback file (NULL if not recording) */
+ UINT64 playback_accumulated_speed;/* accumulated speed during playback */
+ UINT32 playback_accumulated_frames;/* accumulated frames during playback */
+
+ /* inputx */
+ inputx_code *codes;
+ key_buffer *keybuffer;
+ emu_timer *inputx_timer;
+ int (*queue_chars)(running_machine &machine, const unicode_char *text, size_t text_len);
+ int (*accept_char)(running_machine &machine, unicode_char ch);
+ int (*charqueue_empty)(running_machine &machine);
+ attotime current_rate;
+};
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define APPLY_SENSITIVITY(x,s) (((INT64)(x) * (s)) / 100)
+#define APPLY_INVERSE_SENSITIVITY(x,s) (((INT64)(x) * 100) / (s))
+
+#define COMPUTE_SCALE(num,den) (((INT64)(num) << 24) / (den))
+#define RECIP_SCALE(s) (((INT64)1 << 48) / (s))
+#define APPLY_SCALE(x,s) (((INT64)(x) * (s)) >> 24)
+
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+/* XML attributes for the different types */
+static const char *const seqtypestrings[] = { "standard", "decrement", "increment" };
+
+
+static const char_info charinfo[] =
+{
+ { 0x0008, "Backspace", NULL }, /* Backspace */
+ { 0x0009, "Tab", " " }, /* Tab */
+ { 0x000c, "Clear", NULL }, /* Clear */
+ { 0x000d, "Enter", NULL }, /* Enter */
+ { 0x001a, "Esc", NULL }, /* Esc */
+ { 0x0020, "Space", " " }, /* Space */
+ { 0x0061, NULL, "A" }, /* a */
+ { 0x0062, NULL, "B" }, /* b */
+ { 0x0063, NULL, "C" }, /* c */
+ { 0x0064, NULL, "D" }, /* d */
+ { 0x0065, NULL, "E" }, /* e */
+ { 0x0066, NULL, "F" }, /* f */
+ { 0x0067, NULL, "G" }, /* g */
+ { 0x0068, NULL, "H" }, /* h */
+ { 0x0069, NULL, "I" }, /* i */
+ { 0x006a, NULL, "J" }, /* j */
+ { 0x006b, NULL, "K" }, /* k */
+ { 0x006c, NULL, "L" }, /* l */
+ { 0x006d, NULL, "M" }, /* m */
+ { 0x006e, NULL, "N" }, /* n */
+ { 0x006f, NULL, "O" }, /* o */
+ { 0x0070, NULL, "P" }, /* p */
+ { 0x0071, NULL, "Q" }, /* q */
+ { 0x0072, NULL, "R" }, /* r */
+ { 0x0073, NULL, "S" }, /* s */
+ { 0x0074, NULL, "T" }, /* t */
+ { 0x0075, NULL, "U" }, /* u */
+ { 0x0076, NULL, "V" }, /* v */
+ { 0x0077, NULL, "W" }, /* w */
+ { 0x0078, NULL, "X" }, /* x */
+ { 0x0079, NULL, "Y" }, /* y */
+ { 0x007a, NULL, "Z" }, /* z */
+ { 0x00a0, NULL, " " }, /* non breaking space */
+ { 0x00a1, NULL, "!" }, /* inverted exclaimation mark */
+ { 0x00a6, NULL, "|" }, /* broken bar */
+ { 0x00a9, NULL, "(c)" }, /* copyright sign */
+ { 0x00ab, NULL, "<<" }, /* left pointing double angle */
+ { 0x00ae, NULL, "(r)" }, /* registered sign */
+ { 0x00bb, NULL, ">>" }, /* right pointing double angle */
+ { 0x00bc, NULL, "1/4" }, /* vulgar fraction one quarter */
+ { 0x00bd, NULL, "1/2" }, /* vulgar fraction one half */
+ { 0x00be, NULL, "3/4" }, /* vulgar fraction three quarters */
+ { 0x00bf, NULL, "?" }, /* inverted question mark */
+ { 0x00c0, NULL, "A" }, /* 'A' grave */
+ { 0x00c1, NULL, "A" }, /* 'A' acute */
+ { 0x00c2, NULL, "A" }, /* 'A' circumflex */
+ { 0x00c3, NULL, "A" }, /* 'A' tilde */
+ { 0x00c4, NULL, "A" }, /* 'A' diaeresis */
+ { 0x00c5, NULL, "A" }, /* 'A' ring above */
+ { 0x00c6, NULL, "AE" }, /* 'AE' ligature */
+ { 0x00c7, NULL, "C" }, /* 'C' cedilla */
+ { 0x00c8, NULL, "E" }, /* 'E' grave */
+ { 0x00c9, NULL, "E" }, /* 'E' acute */
+ { 0x00ca, NULL, "E" }, /* 'E' circumflex */
+ { 0x00cb, NULL, "E" }, /* 'E' diaeresis */
+ { 0x00cc, NULL, "I" }, /* 'I' grave */
+ { 0x00cd, NULL, "I" }, /* 'I' acute */
+ { 0x00ce, NULL, "I" }, /* 'I' circumflex */
+ { 0x00cf, NULL, "I" }, /* 'I' diaeresis */
+ { 0x00d0, NULL, "D" }, /* 'ETH' */
+ { 0x00d1, NULL, "N" }, /* 'N' tilde */
+ { 0x00d2, NULL, "O" }, /* 'O' grave */
+ { 0x00d3, NULL, "O" }, /* 'O' acute */
+ { 0x00d4, NULL, "O" }, /* 'O' circumflex */
+ { 0x00d5, NULL, "O" }, /* 'O' tilde */
+ { 0x00d6, NULL, "O" }, /* 'O' diaeresis */
+ { 0x00d7, NULL, "X" }, /* multiplication sign */
+ { 0x00d8, NULL, "O" }, /* 'O' stroke */
+ { 0x00d9, NULL, "U" }, /* 'U' grave */
+ { 0x00da, NULL, "U" }, /* 'U' acute */
+ { 0x00db, NULL, "U" }, /* 'U' circumflex */
+ { 0x00dc, NULL, "U" }, /* 'U' diaeresis */
+ { 0x00dd, NULL, "Y" }, /* 'Y' acute */
+ { 0x00df, NULL, "SS" }, /* sharp S */
+ { 0x00e0, NULL, "a" }, /* 'a' grave */
+ { 0x00e1, NULL, "a" }, /* 'a' acute */
+ { 0x00e2, NULL, "a" }, /* 'a' circumflex */
+ { 0x00e3, NULL, "a" }, /* 'a' tilde */
+ { 0x00e4, NULL, "a" }, /* 'a' diaeresis */
+ { 0x00e5, NULL, "a" }, /* 'a' ring above */
+ { 0x00e6, NULL, "ae" }, /* 'ae' ligature */
+ { 0x00e7, NULL, "c" }, /* 'c' cedilla */
+ { 0x00e8, NULL, "e" }, /* 'e' grave */
+ { 0x00e9, NULL, "e" }, /* 'e' acute */
+ { 0x00ea, NULL, "e" }, /* 'e' circumflex */
+ { 0x00eb, NULL, "e" }, /* 'e' diaeresis */
+ { 0x00ec, NULL, "i" }, /* 'i' grave */
+ { 0x00ed, NULL, "i" }, /* 'i' acute */
+ { 0x00ee, NULL, "i" }, /* 'i' circumflex */
+ { 0x00ef, NULL, "i" }, /* 'i' diaeresis */
+ { 0x00f0, NULL, "d" }, /* 'eth' */
+ { 0x00f1, NULL, "n" }, /* 'n' tilde */
+ { 0x00f2, NULL, "o" }, /* 'o' grave */
+ { 0x00f3, NULL, "o" }, /* 'o' acute */
+ { 0x00f4, NULL, "o" }, /* 'o' circumflex */
+ { 0x00f5, NULL, "o" }, /* 'o' tilde */
+ { 0x00f6, NULL, "o" }, /* 'o' diaeresis */
+ { 0x00f8, NULL, "o" }, /* 'o' stroke */
+ { 0x00f9, NULL, "u" }, /* 'u' grave */
+ { 0x00fa, NULL, "u" }, /* 'u' acute */
+ { 0x00fb, NULL, "u" }, /* 'u' circumflex */
+ { 0x00fc, NULL, "u" }, /* 'u' diaeresis */
+ { 0x00fd, NULL, "y" }, /* 'y' acute */
+ { 0x00ff, NULL, "y" }, /* 'y' diaeresis */
+ { 0x2010, NULL, "-" }, /* hyphen */
+ { 0x2011, NULL, "-" }, /* non-breaking hyphen */
+ { 0x2012, NULL, "-" }, /* figure dash */
+ { 0x2013, NULL, "-" }, /* en dash */
+ { 0x2014, NULL, "-" }, /* em dash */
+ { 0x2015, NULL, "-" }, /* horizontal dash */
+ { 0x2018, NULL, "\'" }, /* left single quotation mark */
+ { 0x2019, NULL, "\'" }, /* right single quotation mark */
+ { 0x201a, NULL, "\'" }, /* single low quotation mark */
+ { 0x201b, NULL, "\'" }, /* single high reversed quotation mark */
+ { 0x201c, NULL, "\"" }, /* left double quotation mark */
+ { 0x201d, NULL, "\"" }, /* right double quotation mark */
+ { 0x201e, NULL, "\"" }, /* double low quotation mark */
+ { 0x201f, NULL, "\"" }, /* double high reversed quotation mark */
+ { 0x2024, NULL, "." }, /* one dot leader */
+ { 0x2025, NULL, ".." }, /* two dot leader */
+ { 0x2026, NULL, "..." }, /* horizontal ellipsis */
+ { 0x2047, NULL, "??" }, /* double question mark */
+ { 0x2048, NULL, "?!" }, /* question exclamation mark */
+ { 0x2049, NULL, "!?" }, /* exclamation question mark */
+ { 0xff01, NULL, "!" }, /* fullwidth exclamation point */
+ { 0xff02, NULL, "\"" }, /* fullwidth quotation mark */
+ { 0xff03, NULL, "#" }, /* fullwidth number sign */
+ { 0xff04, NULL, "$" }, /* fullwidth dollar sign */
+ { 0xff05, NULL, "%" }, /* fullwidth percent sign */
+ { 0xff06, NULL, "&" }, /* fullwidth ampersand */
+ { 0xff07, NULL, "\'" }, /* fullwidth apostrophe */
+ { 0xff08, NULL, "(" }, /* fullwidth left parenthesis */
+ { 0xff09, NULL, ")" }, /* fullwidth right parenthesis */
+ { 0xff0a, NULL, "*" }, /* fullwidth asterisk */
+ { 0xff0b, NULL, "+" }, /* fullwidth plus */
+ { 0xff0c, NULL, "," }, /* fullwidth comma */
+ { 0xff0d, NULL, "-" }, /* fullwidth minus */
+ { 0xff0e, NULL, "." }, /* fullwidth period */
+ { 0xff0f, NULL, "/" }, /* fullwidth slash */
+ { 0xff10, NULL, "0" }, /* fullwidth zero */
+ { 0xff11, NULL, "1" }, /* fullwidth one */
+ { 0xff12, NULL, "2" }, /* fullwidth two */
+ { 0xff13, NULL, "3" }, /* fullwidth three */
+ { 0xff14, NULL, "4" }, /* fullwidth four */
+ { 0xff15, NULL, "5" }, /* fullwidth five */
+ { 0xff16, NULL, "6" }, /* fullwidth six */
+ { 0xff17, NULL, "7" }, /* fullwidth seven */
+ { 0xff18, NULL, "8" }, /* fullwidth eight */
+ { 0xff19, NULL, "9" }, /* fullwidth nine */
+ { 0xff1a, NULL, ":" }, /* fullwidth colon */
+ { 0xff1b, NULL, ";" }, /* fullwidth semicolon */
+ { 0xff1c, NULL, "<" }, /* fullwidth less than sign */
+ { 0xff1d, NULL, "=" }, /* fullwidth equals sign */
+ { 0xff1e, NULL, ">" }, /* fullwidth greater than sign */
+ { 0xff1f, NULL, "?" }, /* fullwidth question mark */
+ { 0xff20, NULL, "@" }, /* fullwidth at sign */
+ { 0xff21, NULL, "A" }, /* fullwidth 'A' */
+ { 0xff22, NULL, "B" }, /* fullwidth 'B' */
+ { 0xff23, NULL, "C" }, /* fullwidth 'C' */
+ { 0xff24, NULL, "D" }, /* fullwidth 'D' */
+ { 0xff25, NULL, "E" }, /* fullwidth 'E' */
+ { 0xff26, NULL, "F" }, /* fullwidth 'F' */
+ { 0xff27, NULL, "G" }, /* fullwidth 'G' */
+ { 0xff28, NULL, "H" }, /* fullwidth 'H' */
+ { 0xff29, NULL, "I" }, /* fullwidth 'I' */
+ { 0xff2a, NULL, "J" }, /* fullwidth 'J' */
+ { 0xff2b, NULL, "K" }, /* fullwidth 'K' */
+ { 0xff2c, NULL, "L" }, /* fullwidth 'L' */
+ { 0xff2d, NULL, "M" }, /* fullwidth 'M' */
+ { 0xff2e, NULL, "N" }, /* fullwidth 'N' */
+ { 0xff2f, NULL, "O" }, /* fullwidth 'O' */
+ { 0xff30, NULL, "P" }, /* fullwidth 'P' */
+ { 0xff31, NULL, "Q" }, /* fullwidth 'Q' */
+ { 0xff32, NULL, "R" }, /* fullwidth 'R' */
+ { 0xff33, NULL, "S" }, /* fullwidth 'S' */
+ { 0xff34, NULL, "T" }, /* fullwidth 'T' */
+ { 0xff35, NULL, "U" }, /* fullwidth 'U' */
+ { 0xff36, NULL, "V" }, /* fullwidth 'V' */
+ { 0xff37, NULL, "W" }, /* fullwidth 'W' */
+ { 0xff38, NULL, "X" }, /* fullwidth 'X' */
+ { 0xff39, NULL, "Y" }, /* fullwidth 'Y' */
+ { 0xff3a, NULL, "Z" }, /* fullwidth 'Z' */
+ { 0xff3b, NULL, "[" }, /* fullwidth left bracket */
+ { 0xff3c, NULL, "\\" }, /* fullwidth backslash */
+ { 0xff3d, NULL, "]" }, /* fullwidth right bracket */
+ { 0xff3e, NULL, "^" }, /* fullwidth caret */
+ { 0xff3f, NULL, "_" }, /* fullwidth underscore */
+ { 0xff40, NULL, "`" }, /* fullwidth backquote */
+ { 0xff41, NULL, "a" }, /* fullwidth 'a' */
+ { 0xff42, NULL, "b" }, /* fullwidth 'b' */
+ { 0xff43, NULL, "c" }, /* fullwidth 'c' */
+ { 0xff44, NULL, "d" }, /* fullwidth 'd' */
+ { 0xff45, NULL, "e" }, /* fullwidth 'e' */
+ { 0xff46, NULL, "f" }, /* fullwidth 'f' */
+ { 0xff47, NULL, "g" }, /* fullwidth 'g' */
+ { 0xff48, NULL, "h" }, /* fullwidth 'h' */
+ { 0xff49, NULL, "i" }, /* fullwidth 'i' */
+ { 0xff4a, NULL, "j" }, /* fullwidth 'j' */
+ { 0xff4b, NULL, "k" }, /* fullwidth 'k' */
+ { 0xff4c, NULL, "l" }, /* fullwidth 'l' */
+ { 0xff4d, NULL, "m" }, /* fullwidth 'm' */
+ { 0xff4e, NULL, "n" }, /* fullwidth 'n' */
+ { 0xff4f, NULL, "o" }, /* fullwidth 'o' */
+ { 0xff50, NULL, "p" }, /* fullwidth 'p' */
+ { 0xff51, NULL, "q" }, /* fullwidth 'q' */
+ { 0xff52, NULL, "r" }, /* fullwidth 'r' */
+ { 0xff53, NULL, "s" }, /* fullwidth 's' */
+ { 0xff54, NULL, "t" }, /* fullwidth 't' */
+ { 0xff55, NULL, "u" }, /* fullwidth 'u' */
+ { 0xff56, NULL, "v" }, /* fullwidth 'v' */
+ { 0xff57, NULL, "w" }, /* fullwidth 'w' */
+ { 0xff58, NULL, "x" }, /* fullwidth 'x' */
+ { 0xff59, NULL, "y" }, /* fullwidth 'y' */
+ { 0xff5a, NULL, "z" }, /* fullwidth 'z' */
+ { 0xff5b, NULL, "{" }, /* fullwidth left brace */
+ { 0xff5c, NULL, "|" }, /* fullwidth vertical bar */
+ { 0xff5d, NULL, "}" }, /* fullwidth right brace */
+ { 0xff5e, NULL, "~" }, /* fullwidth tilde */
+ { 0xff5f, NULL, "((" }, /* fullwidth double left parenthesis */
+ { 0xff60, NULL, "))" }, /* fullwidth double right parenthesis */
+ { 0xffe0, NULL, "\xC2\xA2" }, /* fullwidth cent sign */
+ { 0xffe1, NULL, "\xC2\xA3" }, /* fullwidth pound sign */
+ { 0xffe4, NULL, "\xC2\xA4" }, /* fullwidth broken bar */
+ { 0xffe5, NULL, "\xC2\xA5" }, /* fullwidth yen sign */
+ { 0xffe6, NULL, "\xE2\x82\xA9" }, /* fullwidth won sign */
+ { 0xffe9, NULL, "\xE2\x86\x90" }, /* fullwidth left arrow */
+ { 0xffea, NULL, "\xE2\x86\x91" }, /* fullwidth up arrow */
+ { 0xffeb, NULL, "\xE2\x86\x92" }, /* fullwidth right arrow */
+ { 0xffec, NULL, "\xE2\x86\x93" }, /* fullwidth down arrow */
+ { 0xffed, NULL, "\xE2\x96\xAA" }, /* fullwidth solid box */
+ { 0xffee, NULL, "\xE2\x97\xA6" }, /* fullwidth open circle */
+ { UCHAR_SHIFT_1, "Shift", NULL }, /* Shift key */
+ { UCHAR_SHIFT_2, "Ctrl", NULL }, /* Ctrl key */
+ { UCHAR_MAMEKEY(F1), "F1", NULL }, /* F1 function key */
+ { UCHAR_MAMEKEY(F2), "F2", NULL }, /* F2 function key */
+ { UCHAR_MAMEKEY(F3), "F3", NULL }, /* F3 function key */
+ { UCHAR_MAMEKEY(F4), "F4", NULL }, /* F4 function key */
+ { UCHAR_MAMEKEY(F5), "F5", NULL }, /* F5 function key */
+ { UCHAR_MAMEKEY(F6), "F6", NULL }, /* F6 function key */
+ { UCHAR_MAMEKEY(F7), "F7", NULL }, /* F7 function key */
+ { UCHAR_MAMEKEY(F8), "F8", NULL }, /* F8 function key */
+ { UCHAR_MAMEKEY(F9), "F9", NULL }, /* F9 function key */
+ { UCHAR_MAMEKEY(F10), "F10", NULL }, /* F10 function key */
+ { UCHAR_MAMEKEY(F11), "F11", NULL }, /* F11 function key */
+ { UCHAR_MAMEKEY(F12), "F12", NULL }, /* F12 function key */
+ { UCHAR_MAMEKEY(F13), "F13", NULL }, /* F13 function key */
+ { UCHAR_MAMEKEY(F14), "F14", NULL }, /* F14 function key */
+ { UCHAR_MAMEKEY(F15), "F15", NULL }, /* F15 function key */
+ { UCHAR_MAMEKEY(ESC), "Esc", "\033" }, /* Esc key */
+ { UCHAR_MAMEKEY(INSERT), "Insert", NULL }, /* Insert key */
+ { UCHAR_MAMEKEY(DEL), "Delete", "\010" }, /* Delete key */
+ { UCHAR_MAMEKEY(HOME), "Home", "\014" }, /* Home key */
+ { UCHAR_MAMEKEY(END), "End", NULL }, /* End key */
+ { UCHAR_MAMEKEY(PGUP), "Page Up", NULL }, /* Page Up key */
+ { UCHAR_MAMEKEY(PGDN), "Page Down", NULL }, /* Page Down key */
+ { UCHAR_MAMEKEY(LEFT), "Cursor Left", NULL }, /* Cursor Left */
+ { UCHAR_MAMEKEY(RIGHT), "Cursor Right", NULL }, /* Cursor Right */
+ { UCHAR_MAMEKEY(UP), "Cursor Up", NULL }, /* Cursor Up */
+ { UCHAR_MAMEKEY(DOWN), "Cursor Down", NULL }, /* Cursor Down */
+ { UCHAR_MAMEKEY(0_PAD), "Keypad 0", NULL }, /* 0 on the numeric keypad */
+ { UCHAR_MAMEKEY(1_PAD), "Keypad 1", NULL }, /* 1 on the numeric keypad */
+ { UCHAR_MAMEKEY(2_PAD), "Keypad 2", NULL }, /* 2 on the numeric keypad */
+ { UCHAR_MAMEKEY(3_PAD), "Keypad 3", NULL }, /* 3 on the numeric keypad */
+ { UCHAR_MAMEKEY(4_PAD), "Keypad 4", NULL }, /* 4 on the numeric keypad */
+ { UCHAR_MAMEKEY(5_PAD), "Keypad 5", NULL }, /* 5 on the numeric keypad */
+ { UCHAR_MAMEKEY(6_PAD), "Keypad 6", NULL }, /* 6 on the numeric keypad */
+ { UCHAR_MAMEKEY(7_PAD), "Keypad 7", NULL }, /* 7 on the numeric keypad */
+ { UCHAR_MAMEKEY(8_PAD), "Keypad 8", NULL }, /* 8 on the numeric keypad */
+ { UCHAR_MAMEKEY(9_PAD), "Keypad 9", NULL }, /* 9 on the numeric keypad */
+ { UCHAR_MAMEKEY(SLASH_PAD), "Keypad /", NULL }, /* / on the numeric keypad */
+ { UCHAR_MAMEKEY(ASTERISK), "Keypad *", NULL }, /* * on the numeric keypad */
+ { UCHAR_MAMEKEY(MINUS_PAD), "Keypad -", NULL }, /* - on the numeric Keypad */
+ { UCHAR_MAMEKEY(PLUS_PAD), "Keypad +", NULL }, /* + on the numeric Keypad */
+ { UCHAR_MAMEKEY(DEL_PAD), "Keypad .", NULL }, /* . on the numeric keypad */
+ { UCHAR_MAMEKEY(ENTER_PAD), "Keypad Enter", NULL }, /* Enter on the numeric keypad */
+ { UCHAR_MAMEKEY(PRTSCR), "Print Screen", NULL }, /* Print Screen key */
+ { UCHAR_MAMEKEY(PAUSE), "Pause", NULL }, /* Pause key */
+ { UCHAR_MAMEKEY(LSHIFT), "Left Shift", NULL }, /* Left Shift key */
+ { UCHAR_MAMEKEY(RSHIFT), "Right Shift", NULL }, /* Right Shift key */
+ { UCHAR_MAMEKEY(LCONTROL), "Left Ctrl", NULL }, /* Left Control key */
+ { UCHAR_MAMEKEY(RCONTROL), "Right Ctrl", NULL }, /* Right Control key */
+ { UCHAR_MAMEKEY(LALT), "Left Alt", NULL }, /* Left Alt key */
+ { UCHAR_MAMEKEY(RALT), "Right Alt", NULL }, /* Right Alt key */
+ { UCHAR_MAMEKEY(SCRLOCK), "Scroll Lock", NULL }, /* Scroll Lock key */
+ { UCHAR_MAMEKEY(NUMLOCK), "Num Lock", NULL }, /* Num Lock key */
+ { UCHAR_MAMEKEY(CAPSLOCK), "Caps Lock", NULL }, /* Caps Lock key */
+ { UCHAR_MAMEKEY(LWIN), "Left Win", NULL }, /* Left Win key */
+ { UCHAR_MAMEKEY(RWIN), "Right Win", NULL }, /* Right Win key */
+ { UCHAR_MAMEKEY(MENU), "Menu", NULL }, /* Menu key */
+ { UCHAR_MAMEKEY(CANCEL), "Break", NULL } /* Break/Pause key */
+};
+
+static TIMER_CALLBACK(inputx_timerproc);
+
+
+/* Debugging commands and handlers. */
+static void execute_input(running_machine &machine, int ref, int params, const char *param[]);
+static void execute_dumpkbd(running_machine &machine, int ref, int params, const char *param[]);
+
+/***************************************************************************
+ COMMON SHARED STRINGS
+***************************************************************************/
+
+static const struct
+{
+ UINT32 id;
+ const char *string;
+} input_port_default_strings[] =
+{
+ { INPUT_STRING_Off, "Off" },
+ { INPUT_STRING_On, "On" },
+ { INPUT_STRING_No, "No" },
+ { INPUT_STRING_Yes, "Yes" },
+ { INPUT_STRING_Lives, "Lives" },
+ { INPUT_STRING_Bonus_Life, "Bonus Life" },
+ { INPUT_STRING_Difficulty, "Difficulty" },
+ { INPUT_STRING_Demo_Sounds, "Demo Sounds" },
+ { INPUT_STRING_Coinage, "Coinage" },
+ { INPUT_STRING_Coin_A, "Coin A" },
+ { INPUT_STRING_Coin_B, "Coin B" },
+ { INPUT_STRING_9C_1C, "9 Coins/1 Credit" },
+ { INPUT_STRING_8C_1C, "8 Coins/1 Credit" },
+ { INPUT_STRING_7C_1C, "7 Coins/1 Credit" },
+ { INPUT_STRING_6C_1C, "6 Coins/1 Credit" },
+ { INPUT_STRING_5C_1C, "5 Coins/1 Credit" },
+ { INPUT_STRING_4C_1C, "4 Coins/1 Credit" },
+ { INPUT_STRING_3C_1C, "3 Coins/1 Credit" },
+ { INPUT_STRING_8C_3C, "8 Coins/3 Credits" },
+ { INPUT_STRING_4C_2C, "4 Coins/2 Credits" },
+ { INPUT_STRING_2C_1C, "2 Coins/1 Credit" },
+ { INPUT_STRING_5C_3C, "5 Coins/3 Credits" },
+ { INPUT_STRING_3C_2C, "3 Coins/2 Credits" },
+ { INPUT_STRING_4C_3C, "4 Coins/3 Credits" },
+ { INPUT_STRING_4C_4C, "4 Coins/4 Credits" },
+ { INPUT_STRING_3C_3C, "3 Coins/3 Credits" },
+ { INPUT_STRING_2C_2C, "2 Coins/2 Credits" },
+ { INPUT_STRING_1C_1C, "1 Coin/1 Credit" },
+ { INPUT_STRING_4C_5C, "4 Coins/5 Credits" },
+ { INPUT_STRING_3C_4C, "3 Coins/4 Credits" },
+ { INPUT_STRING_2C_3C, "2 Coins/3 Credits" },
+ { INPUT_STRING_4C_7C, "4 Coins/7 Credits" },
+ { INPUT_STRING_2C_4C, "2 Coins/4 Credits" },
+ { INPUT_STRING_1C_2C, "1 Coin/2 Credits" },
+ { INPUT_STRING_2C_5C, "2 Coins/5 Credits" },
+ { INPUT_STRING_2C_6C, "2 Coins/6 Credits" },
+ { INPUT_STRING_1C_3C, "1 Coin/3 Credits" },
+ { INPUT_STRING_2C_7C, "2 Coins/7 Credits" },
+ { INPUT_STRING_2C_8C, "2 Coins/8 Credits" },
+ { INPUT_STRING_1C_4C, "1 Coin/4 Credits" },
+ { INPUT_STRING_1C_5C, "1 Coin/5 Credits" },
+ { INPUT_STRING_1C_6C, "1 Coin/6 Credits" },
+ { INPUT_STRING_1C_7C, "1 Coin/7 Credits" },
+ { INPUT_STRING_1C_8C, "1 Coin/8 Credits" },
+ { INPUT_STRING_1C_9C, "1 Coin/9 Credits" },
+ { INPUT_STRING_Free_Play, "Free Play" },
+ { INPUT_STRING_Cabinet, "Cabinet" },
+ { INPUT_STRING_Upright, "Upright" },
+ { INPUT_STRING_Cocktail, "Cocktail" },
+ { INPUT_STRING_Flip_Screen, "Flip Screen" },
+ { INPUT_STRING_Service_Mode, "Service Mode" },
+ { INPUT_STRING_Pause, "Pause" },
+ { INPUT_STRING_Test, "Test" },
+ { INPUT_STRING_Tilt, "Tilt" },
+ { INPUT_STRING_Version, "Version" },
+ { INPUT_STRING_Region, "Region" },
+ { INPUT_STRING_International, "International" },
+ { INPUT_STRING_Japan, "Japan" },
+ { INPUT_STRING_USA, "USA" },
+ { INPUT_STRING_Europe, "Europe" },
+ { INPUT_STRING_Asia, "Asia" },
+ { INPUT_STRING_World, "World" },
+ { INPUT_STRING_Hispanic, "Hispanic" },
+ { INPUT_STRING_Language, "Language" },
+ { INPUT_STRING_English, "English" },
+ { INPUT_STRING_Japanese, "Japanese" },
+ { INPUT_STRING_German, "German" },
+ { INPUT_STRING_French, "French" },
+ { INPUT_STRING_Italian, "Italian" },
+ { INPUT_STRING_Spanish, "Spanish" },
+ { INPUT_STRING_Very_Easy, "Very Easy" },
+ { INPUT_STRING_Easiest, "Easiest" },
+ { INPUT_STRING_Easier, "Easier" },
+ { INPUT_STRING_Easy, "Easy" },
+ { INPUT_STRING_Medium_Easy, "Medium Easy" },
+ { INPUT_STRING_Normal, "Normal" },
+ { INPUT_STRING_Medium, "Medium" },
+ { INPUT_STRING_Medium_Hard, "Medium Hard" },
+ { INPUT_STRING_Hard, "Hard" },
+ { INPUT_STRING_Harder, "Harder" },
+ { INPUT_STRING_Hardest, "Hardest" },
+ { INPUT_STRING_Very_Hard, "Very Hard" },
+ { INPUT_STRING_Medium_Difficult, "Medium Difficult" },
+ { INPUT_STRING_Difficult, "Difficult" },
+ { INPUT_STRING_More_Difficult, "More Difficult" },
+ { INPUT_STRING_Most_Difficult, "Most Difficult" },
+ { INPUT_STRING_Very_Difficult, "Very Difficult" },
+ { INPUT_STRING_Very_Low, "Very Low" },
+ { INPUT_STRING_Low, "Low" },
+ { INPUT_STRING_High, "High" },
+ { INPUT_STRING_Higher, "Higher" },
+ { INPUT_STRING_Highest, "Highest" },
+ { INPUT_STRING_Very_High, "Very High" },
+ { INPUT_STRING_Players, "Players" },
+ { INPUT_STRING_Controls, "Controls" },
+ { INPUT_STRING_Dual, "Dual" },
+ { INPUT_STRING_Single, "Single" },
+ { INPUT_STRING_Game_Time, "Game Time" },
+ { INPUT_STRING_Continue_Price, "Continue Price" },
+ { INPUT_STRING_Controller, "Controller" },
+ { INPUT_STRING_Light_Gun, "Light Gun" },
+ { INPUT_STRING_Joystick, "Joystick" },
+ { INPUT_STRING_Trackball, "Trackball" },
+ { INPUT_STRING_Continues, "Continues" },
+ { INPUT_STRING_Allow_Continue, "Allow Continue" },
+ { INPUT_STRING_Level_Select, "Level Select" },
+ { INPUT_STRING_Infinite, "Infinite" },
+ { INPUT_STRING_Stereo, "Stereo" },
+ { INPUT_STRING_Mono, "Mono" },
+ { INPUT_STRING_Unused, "Unused" },
+ { INPUT_STRING_Unknown, "Unknown" },
+ { INPUT_STRING_Standard, "Standard" },
+ { INPUT_STRING_Reverse, "Reverse" },
+ { INPUT_STRING_Alternate, "Alternate" },
+ { INPUT_STRING_None, "None" }
+};
+
+
+
+/***************************************************************************
+ BUILT-IN CORE MAPPINGS
+***************************************************************************/
+
+#include "inpttype.h"
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+/* core system management */
+static void input_port_exit(running_machine &machine);
+
+/* port reading */
+static INT32 apply_analog_settings(INT32 current, analog_field_state *analog);
+
+/* initialization helpers */
+static void init_port_types(running_machine &machine);
+static void init_port_state(running_machine &machine);
+static void init_autoselect_devices(running_machine &machine, int type1, int type2, int type3, const char *option, const char *ananame);
+static device_field_info *init_field_device_info(const input_field_config *field,const char *device_name);
+static analog_field_state *init_field_analog_state(const input_field_config *field);
+
+/* once-per-frame updates */
+static void frame_update_callback(running_machine &machine);
+static void frame_update(running_machine &machine);
+static void frame_update_digital_joysticks(running_machine &machine);
+static void frame_update_analog_field(running_machine &machine, analog_field_state *analog);
+static int frame_get_digital_field_state(const input_field_config *field, int mouse_down);
+
+/* tokenization helpers */
+static int token_to_input_field_type(running_machine &machine, const char *string, int *player);
+static const char *input_field_type_to_token(running_machine &machine, int type, int player);
+static int token_to_seq_type(const char *string);
+
+/* settings load */
+static void load_config_callback(running_machine &machine, int config_type, xml_data_node *parentnode);
+static void load_remap_table(running_machine &machine, xml_data_node *parentnode);
+static int load_default_config(running_machine &machine, xml_data_node *portnode, int type, int player, const input_seq *newseq);
+static int load_game_config(running_machine &machine, xml_data_node *portnode, int type, int player, const input_seq *newseq);
+
+/* settings save */
+static void save_config_callback(running_machine &machine, int config_type, xml_data_node *parentnode);
+static void save_sequence(running_machine &machine, xml_data_node *parentnode, int type, int porttype, const input_seq &seq);
+static int save_this_input_field_type(int type);
+static void save_default_inputs(running_machine &machine, xml_data_node *parentnode);
+static void save_game_inputs(running_machine &machine, xml_data_node *parentnode);
+
+/* input playback */
+static time_t playback_init(running_machine &machine);
+static void playback_end(running_machine &machine, const char *message);
+static void playback_frame(running_machine &machine, attotime curtime);
+static void playback_port(const input_port_config *port);
+
+/* input recording */
+static void record_init(running_machine &machine);
+static void record_end(running_machine &machine, const char *message);
+static void record_frame(running_machine &machine, attotime curtime);
+static void record_port(const input_port_config *port);
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ apply_analog_min_max - clamp the given input
+ value to the appropriate min/max for the
+ analog control
+-------------------------------------------------*/
+
+INLINE INT32 apply_analog_min_max(const analog_field_state *analog, INT32 value)
+{
+ /* take the analog minimum and maximum values and apply the inverse of the */
+ /* sensitivity so that we can clamp against them before applying sensitivity */
+ INT32 adjmin = APPLY_INVERSE_SENSITIVITY(analog->minimum, analog->sensitivity);
+ INT32 adjmax = APPLY_INVERSE_SENSITIVITY(analog->maximum, analog->sensitivity);
+
+ /* for absolute devices, clamp to the bounds absolutely */
+ if (!analog->wraps)
+ {
+ if (value > adjmax)
+ value = adjmax;
+ else if (value < adjmin)
+ value = adjmin;
+ }
+
+ /* for relative devices, wrap around when we go past the edge */
+ else
+ {
+ INT32 adj1 = APPLY_INVERSE_SENSITIVITY(INPUT_RELATIVE_PER_PIXEL, analog->sensitivity);
+ INT32 range = adjmax - adjmin + adj1;
+ /* rolls to other end when 1 position past end. */
+ adjmax += adj1;
+ adjmin -= adj1;
+
+ while (value >= adjmax)
+ {
+ value -= range;;
+ }
+ while (value <= adjmin)
+ {
+ value += range;;
+ }
+ }
+
+ return value;
+}
+
+
+/*-------------------------------------------------
+ get_port_tag - return a guaranteed tag for
+ a port
+-------------------------------------------------*/
+
+INLINE const char *get_port_tag(const input_port_config *port, char *tempbuffer)
+{
+ return port->tag();
+}
+
+
+/*-------------------------------------------------
+ condition_equal - TRUE if two conditions are
+ equivalent
+-------------------------------------------------*/
+
+INLINE int condition_equal(const input_condition *cond1, const input_condition *cond2)
+{
+ return (cond1->mask == cond2->mask && cond1->value == cond2->value && cond1->condition == cond2->condition && strcmp(cond1->tag, cond2->tag) == 0);
+}
+
+
+
+/***************************************************************************
+ CORE SYSTEM MANAGEMENT
+***************************************************************************/
+
+/*-------------------------------------------------
+ input_port_init - initialize the input port
+ system
+-------------------------------------------------*/
+
+time_t input_port_init(running_machine &machine)
+{
+ //input_port_private *portdata;
+ time_t basetime;
+
+ /* allocate memory for our data structure */
+ machine.input_port_data = auto_alloc_clear(machine, input_port_private);
+ //portdata = machine.input_port_data;
+
+ /* add an exit callback and a frame callback */
+ machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(input_port_exit), &machine));
+ machine.add_notifier(MACHINE_NOTIFY_FRAME, machine_notify_delegate(FUNC(frame_update_callback), &machine));
+
+ /* initialize the default port info from the OSD */
+ init_port_types(machine);
+
+ /* if we have a token list, proceed */
+ for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next())
+ {
+ astring errors;
+ input_port_list_init(*device, machine.m_portlist, errors);
+ if (errors)
+ mame_printf_error("Input port errors:\n%s", errors.cstr());
+ }
+
+ init_port_state(machine);
+ /* register callbacks for when we load configurations */
+ config_register(machine, "input", config_saveload_delegate(FUNC(load_config_callback), &machine), config_saveload_delegate(FUNC(save_config_callback), &machine));
+
+ /* open playback and record files if specified */
+ basetime = playback_init(machine);
+ record_init(machine);
+
+ return basetime;
+}
+
+
+/*-------------------------------------------------
+ input_port_exit - exit callback to ensure
+ we clean up and close our files
+-------------------------------------------------*/
+
+static void input_port_exit(running_machine &machine)
+{
+ /* close any playback or recording files */
+ playback_end(machine, NULL);
+ record_end(machine, NULL);
+}
+
+
+
+/***************************************************************************
+ PORT CONFIGURATIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ input_port_list_init - initialize an input
+ port list structure and allocate ports
+ according to the given tokens
+-------------------------------------------------*/
+
+void input_port_list_init(device_t &device, ioport_list &portlist, astring &errorbuf)
+{
+ /* no constructor, no list */
+ ioport_constructor constructor = device.input_ports();
+ if (constructor == NULL)
+ return;
+
+ /* reset error buffer */
+ errorbuf.reset();
+
+ /* detokenize into the list */
+ (*constructor)(device, portlist, errorbuf);
+
+ // collapse fields and sort the list
+ for (input_port_config *port = portlist.first(); port != NULL; port = port->next())
+ port->collapse_fields(errorbuf);
+}
+
+
+/*-------------------------------------------------
+ input_field_by_tag_and_mask - return a pointer
+ to the first field that intersects the given
+ mask on the tagged port
+-------------------------------------------------*/
+
+const input_field_config *input_field_by_tag_and_mask(const ioport_list &portlist, const char *tag, input_port_value mask)
+{
+ const input_port_config *port = portlist.find(tag);
+
+ /* if we got the port, look for the field */
+ if (port != NULL)
+ for (const input_field_config *field = port->first_field(); field != NULL; field = field->next())
+ if ((field->mask & mask) != 0)
+ return field;
+
+ return NULL;
+}
+
+
+
+/***************************************************************************
+ ACCESSORS FOR INPUT FIELDS
+***************************************************************************/
+
+/*-------------------------------------------------
+ input_field_name - return the field name for
+ a given input field
+-------------------------------------------------*/
+
+const char *input_field_name(const input_field_config *field)
+{
+ /* if we have a non-default name, use that */
+ if ((field->state != NULL) && (field->state->name != NULL))
+ return field->state->name;
+ if (field->name != NULL)
+ return field->name;
+
+ /* otherwise, return the name associated with the type */
+ return input_type_name(field->machine(), field->type, field->player);
+}
+
+
+/*-------------------------------------------------
+ input_field_seq - return the input sequence
+ for the given input field
+-------------------------------------------------*/
+
+const input_seq &input_field_seq(const input_field_config *field, input_seq_type seqtype)
+{
+ /* if the field is disabled, return no key */
+ if (field->flags & FIELD_FLAG_UNUSED)
+ return input_seq::empty_seq;
+
+ /* select either the live or config state depending on whether we have live state */
+ const input_seq &portseq = (field->state == NULL) ? field->seq[seqtype] : field->state->seq[seqtype];
+
+ /* if the portseq is the special default code, return the expanded default value */
+ if (portseq.is_default())
+ return input_type_seq(field->machine(), field->type, field->player, seqtype);
+
+ /* otherwise, return the sequence as-is */
+ return portseq;
+}
+
+
+/*-------------------------------------------------
+ input_field_get_user_settings - return the current
+ settings for the given input field
+-------------------------------------------------*/
+
+void input_field_get_user_settings(const input_field_config *field, input_field_user_settings *settings)
+{
+ int seqtype;
+
+ /* zap the entire structure */
+ memset(settings, 0, sizeof(*settings));
+
+ /* copy the basics */
+ for (seqtype = 0; seqtype < ARRAY_LENGTH(settings->seq); seqtype++)
+ settings->seq[seqtype] = field->state->seq[seqtype];
+
+ /* if there's a list of settings or we're an adjuster, copy the current value */
+ if (field->settinglist().count() != 0 || field->type == IPT_ADJUSTER)
+ settings->value = field->state->value;
+
+ /* if there's analog data, extract the analog settings */
+ if (field->state->analog != NULL)
+ {
+ settings->sensitivity = field->state->analog->sensitivity;
+ settings->delta = field->state->analog->delta;
+ settings->centerdelta = field->state->analog->centerdelta;
+ settings->reverse = field->state->analog->reverse;
+ }
+}
+
+
+/*-------------------------------------------------
+ input_field_set_user_settings - modify the current
+ settings for the given input field
+-------------------------------------------------*/
+
+void input_field_set_user_settings(const input_field_config *field, const input_field_user_settings *settings)
+{
+ int seqtype;
+
+ /* copy the basics */
+ for (seqtype = 0; seqtype < ARRAY_LENGTH(settings->seq); seqtype++)
+ {
+ const input_seq &defseq = input_type_seq(field->machine(), field->type, field->player, (input_seq_type)seqtype);
+ if (defseq == settings->seq[seqtype])
+ field->state->seq[seqtype].set_default();
+ else
+ field->state->seq[seqtype] = settings->seq[seqtype];
+ }
+
+ /* if there's a list of settings or we're an adjuster, copy the current value */
+ if (field->settinglist().count() != 0 || field->type == IPT_ADJUSTER)
+ field->state->value = settings->value;
+
+ /* if there's analog data, extract the analog settings */
+ if (field->state->analog != NULL)
+ {
+ field->state->analog->sensitivity = settings->sensitivity;
+ field->state->analog->delta = settings->delta;
+ field->state->analog->centerdelta = settings->centerdelta;
+ field->state->analog->reverse = settings->reverse;
+ }
+}
+
+
+/*-------------------------------------------------
+ input_field_setting_name - return the expanded
+ setting name for a field
+-------------------------------------------------*/
+
+const char *input_field_setting_name(const input_field_config *field)
+{
+ const input_setting_config *setting;
+
+ /* only makes sense if we have settings */
+ assert(field->settinglist().count() != 0);
+
+ /* scan the list of settings looking for a match on the current value */
+ for (setting = field->settinglist().first(); setting != NULL; setting = setting->next())
+ if (input_condition_true(field->machine(), &setting->condition, field->port().owner()))
+ if (setting->value == field->state->value)
+ return setting->name;
+
+ return "INVALID";
+}
+
+
+/*-------------------------------------------------
+ input_field_has_previous_setting - return TRUE
+ if the given field has a "previous" setting
+-------------------------------------------------*/
+
+int input_field_has_previous_setting(const input_field_config *field)
+{
+ const input_setting_config *setting;
+
+ /* only makes sense if we have settings */
+ assert(field->settinglist().count() != 0);
+
+ /* scan the list of settings looking for a match on the current value */
+ for (setting = field->settinglist().first(); setting != NULL; setting = setting->next())
+ if (input_condition_true(field->machine(), &setting->condition, field->port().owner()))
+ return (setting->value != field->state->value);
+
+ return FALSE;
+}
+
+
+/*-------------------------------------------------
+ input_field_select_previous_setting - select
+ the previous item for a DIP switch or
+ configuration field
+-------------------------------------------------*/
+
+void input_field_select_previous_setting(const input_field_config *field)
+{
+ const input_setting_config *setting, *prevsetting;
+ int found_match = FALSE;
+
+ /* only makes sense if we have settings */
+ assert(field->settinglist().count() != 0);
+
+ /* scan the list of settings looking for a match on the current value */
+ prevsetting = NULL;
+ for (setting = field->settinglist().first(); setting != NULL; setting = setting->next())
+ if (input_condition_true(field->machine(), &setting->condition, field->port().owner()))
+ {
+ if (setting->value == field->state->value)
+ {
+ found_match = TRUE;
+ if (prevsetting != NULL)
+ break;
+ }
+ prevsetting = setting;
+ }
+
+ /* if we didn't find a matching value, select the first */
+ if (!found_match)
+ {
+ for (prevsetting = field->settinglist().first(); prevsetting != NULL; prevsetting = prevsetting->next())
+ if (input_condition_true(field->machine(), &prevsetting->condition, field->port().owner()))
+ break;
+ }
+
+ /* update the value to the previous one */
+ if (prevsetting != NULL)
+ field->state->value = prevsetting->value;
+}
+
+
+/*-------------------------------------------------
+ input_field_has_next_setting - return TRUE
+ if the given field has a "next" setting
+-------------------------------------------------*/
+
+int input_field_has_next_setting(const input_field_config *field)
+{
+ const input_setting_config *setting;
+ int found = FALSE;
+
+ /* only makes sense if we have settings */
+ assert(field->settinglist().count() != 0);
+
+ /* scan the list of settings looking for a match on the current value */
+ for (setting = field->settinglist().first(); setting != NULL; setting = setting->next())
+ if (input_condition_true(field->machine(), &setting->condition, field->port().owner()))
+ {
+ if (found)
+ return TRUE;
+ if (setting->value == field->state->value)
+ found = TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/*-------------------------------------------------
+ input_field_select_next_setting - select the
+ next item for a DIP switch or
+ configuration field
+-------------------------------------------------*/
+
+void input_field_select_next_setting(const input_field_config *field)
+{
+ const input_setting_config *setting, *nextsetting;
+
+ /* only makes sense if we have settings */
+ assert(field->settinglist().count() != 0);
+
+ /* scan the list of settings looking for a match on the current value */
+ nextsetting = NULL;
+ for (setting = field->settinglist().first(); setting != NULL; setting = setting->next())
+ if (input_condition_true(field->machine(), &setting->condition, field->port().owner()))
+ if (setting->value == field->state->value)
+ break;
+
+ /* if we found one, scan forward for the next valid one */
+ if (setting != NULL)
+ for (nextsetting = setting->next(); nextsetting != NULL; nextsetting = nextsetting->next())
+ if (input_condition_true(field->machine(), &nextsetting->condition, field->port().owner()))
+ break;
+
+ /* if we hit the end, search from the beginning */
+ if (nextsetting == NULL)
+ for (nextsetting = field->settinglist().first(); nextsetting != NULL; nextsetting = nextsetting->next())
+ if (input_condition_true(field->machine(), &nextsetting->condition, field->port().owner()))
+ break;
+
+ /* update the value to the previous one */
+ if (nextsetting != NULL)
+ field->state->value = nextsetting->value;
+}
+
+
+
+/***************************************************************************
+ ACCESSORS FOR INPUT TYPES
+***************************************************************************/
+
+/*-------------------------------------------------
+ input_type_is_analog - return TRUE if
+ the given type represents an analog control
+-------------------------------------------------*/
+
+int input_type_is_analog(int type)
+{
+ return (type >= __ipt_analog_start && type <= __ipt_analog_end);
+}
+
+
+/*-------------------------------------------------
+ input_type_name - return the name
+ for the given type/player
+-------------------------------------------------*/
+
+const char *input_type_name(running_machine &machine, int type, int player)
+{
+ /* if we have a machine, use the live state and quick lookup */
+ input_port_private *portdata = machine.input_port_data;
+ input_type_entry *entry = portdata->type_to_entry[type][player];
+ if (entry != NULL)
+ return entry->name;
+
+ /* if we find nothing, return an invalid group */
+ return "???";
+}
+
+
+/*-------------------------------------------------
+ input_type_group - return the group
+ for the given type/player
+-------------------------------------------------*/
+
+int input_type_group(running_machine &machine, int type, int player)
+{
+ input_port_private *portdata = machine.input_port_data;
+ input_type_entry *entry = portdata->type_to_entry[type][player];
+ if (entry != NULL)
+ return entry->group;
+
+ /* if we find nothing, return an invalid group */
+ return IPG_INVALID;
+}
+
+
+/*-------------------------------------------------
+ input_type_seq - return the input
+ sequence for the given type/player
+-------------------------------------------------*/
+
+const input_seq &input_type_seq(running_machine &machine, int type, int player, input_seq_type seqtype)
+{
+ assert(type >= 0 && type < __ipt_max);
+ assert(player >= 0 && player < MAX_PLAYERS);
+
+ /* if we have a machine, use the live state and quick lookup */
+ input_port_private *portdata = machine.input_port_data;
+ input_type_entry *entry = portdata->type_to_entry[type][player];
+ if (entry != NULL)
+ return entry->seq[seqtype];
+
+ /* if we find nothing, return an empty sequence */
+ return input_seq::empty_seq;
+}
+
+
+/*-------------------------------------------------
+ input_type_set_seq - change the input
+ sequence for the given type/player
+-------------------------------------------------*/
+
+void input_type_set_seq(running_machine &machine, int type, int player, input_seq_type seqtype, const input_seq *newseq)
+{
+ input_port_private *portdata = machine.input_port_data;
+ input_type_entry *entry = portdata->type_to_entry[type][player];
+ if (entry != NULL)
+ entry->seq[seqtype] = *newseq;
+}
+
+
+/*-------------------------------------------------
+ input_type_pressed - return TRUE if
+ the sequence for the given input type/player
+ is pressed
+-------------------------------------------------*/
+
+int input_type_pressed(running_machine &machine, int type, int player)
+{
+ return machine.input().seq_pressed(input_type_seq(machine, type, player, SEQ_TYPE_STANDARD));
+}
+
+
+/*-------------------------------------------------
+ input_type_list - return the list of types
+-------------------------------------------------*/
+
+const simple_list<input_type_entry> &input_type_list(running_machine &machine)
+{
+ input_port_private *portdata = machine.input_port_data;
+ return portdata->typelist;
+}
+
+
+
+/***************************************************************************
+ PORT CHECKING
+***************************************************************************/
+
+
+/*-------------------------------------------------
+ input_port_exists - return whether an input
+ port exists
+-------------------------------------------------*/
+
+bool input_port_exists(running_machine &machine, const char *tag)
+{
+ return machine.port(tag) != 0;
+}
+
+
+/*-------------------------------------------------
+ input_port_active - return a bitmask of which
+ bits of an input port are active (i.e. not
+ unused or unknown)
+-------------------------------------------------*/
+
+input_port_value input_port_active(running_machine &machine, const char *tag)
+{
+ const input_port_config *port = machine.port(tag);
+ if (port == NULL)
+ fatalerror("Unable to locate input port '%s'", tag);
+ return port->active;
+}
+
+
+/*-------------------------------------------------
+ input_port_active_safe - return a bitmask of
+ which bits of an input port are active (i.e.
+ not unused or unknown), or a default value if
+ the port does not exist
+-------------------------------------------------*/
+
+input_port_value input_port_active_safe(running_machine &machine, const char *tag, input_port_value defvalue)
+{
+ const input_port_config *port = machine.port(tag);
+ return port == NULL ? defvalue : port->active;
+}
+
+
+
+/***************************************************************************
+ PORT READING
+***************************************************************************/
+
+/*-------------------------------------------------
+ input_port_read_direct - return the value of
+ an input port
+-------------------------------------------------*/
+
+input_port_value input_port_read_direct(const input_port_config *port)
+{
+ input_port_private *portdata = port->machine().input_port_data;
+ analog_field_state *analog;
+ device_field_info *device_field;
+ input_port_value result;
+
+ assert_always(portdata->safe_to_read, "Input ports cannot be read at init time!");
+
+ /* start with the digital */
+ result = port->state->digital;
+
+ /* update read values */
+ for (device_field = port->state->readdevicelist; device_field != NULL; device_field = device_field->next)
+ if (input_condition_true(port->machine(), &device_field->field->condition, port->owner()))
+ {
+ /* replace the bits with bits from the device */
+ input_port_value newval = device_field->field->read(*device_field->field, device_field->field->read_param);
+ device_field->oldval = newval;
+ result = (result & ~device_field->field->mask) | ((newval << device_field->shift) & device_field->field->mask);
+ }
+
+ /* update VBLANK bits */
+ if (port->state->vblank != 0)
+ {
+ if (port->machine().primary_screen->vblank())
+ result |= port->state->vblank;
+ else
+ result &= ~port->state->vblank;
+ }
+
+ /* apply active high/low state to digital, read, and VBLANK inputs */
+ result ^= port->state->defvalue;
+
+ /* merge in analog portions */
+ for (analog = port->state->analoglist; analog != NULL; analog = analog->next)
+ if (input_condition_true(port->machine(), &analog->field->condition, port->owner()))
+ {
+ /* start with the raw value */
+ INT32 value = analog->accum;
+
+ /* interpolate if appropriate and if time has passed since the last update */
+ if (analog->interpolate && !(analog->field->flags & ANALOG_FLAG_RESET) && portdata->last_delta_nsec != 0)
+ {
+ attoseconds_t nsec_since_last = (port->machine().time() - portdata->last_frame_time).as_attoseconds() / ATTOSECONDS_PER_NANOSECOND;
+ value = analog->previous + ((INT64)(analog->accum - analog->previous) * nsec_since_last / portdata->last_delta_nsec);
+ }
+
+ /* apply standard analog settings */
+ value = apply_analog_settings(value, analog);
+
+ /* remap the value if needed */
+ if (analog->field->remap_table != NULL)
+ value = analog->field->remap_table[value];
+
+ /* invert bits if needed */
+ if (analog->field->flags & ANALOG_FLAG_INVERT)
+ value = ~value;
+
+ /* insert into the port */
+ result = (result & ~analog->field->mask) | ((value << analog->shift) & analog->field->mask);
+ }
+
+ return result;
+}
+
+
+/*-------------------------------------------------
+ input_port_read - return the value of
+ an input port specified by tag
+-------------------------------------------------*/
+
+input_port_value input_port_read(running_machine &machine, const char *tag)
+{
+ const input_port_config *port = machine.port(tag);
+ if (port == NULL)
+ fatalerror("Unable to locate input port '%s'", tag);
+ return input_port_read_direct(port);
+}
+
+
+/*-------------------------------------------------
+ input_port_read - return the value of
+ a device input port specified by tag
+-------------------------------------------------*/
+
+input_port_value input_port_read(device_t *device, const char *tag)
+{
+ astring tempstring;
+ const input_port_config *port = device->machine().port(device->subtag(tempstring, tag));
+ if (port == NULL)
+ fatalerror("Unable to locate input port '%s'", tag);
+ return input_port_read_direct(port);
+}
+
+
+/*-------------------------------------------------
+ input_port_read_safe - return the value of
+ an input port specified by tag, or a default
+ value if the port does not exist
+-------------------------------------------------*/
+
+input_port_value input_port_read_safe(running_machine &machine, const char *tag, UINT32 defvalue)
+{
+ const input_port_config *port = machine.port(tag);
+ return (port == NULL) ? defvalue : input_port_read_direct(port);
+}
+
+
+/*-------------------------------------------------
+ input_port_read_crosshair - return the
+ extracted crosshair values for the given
+ player
+-------------------------------------------------*/
+
+int input_port_get_crosshair_position(running_machine &machine, int player, float *x, float *y)
+{
+ const input_port_config *port;
+ const input_field_config *field;
+ int gotx = FALSE, goty = FALSE;
+
+ /* read all the lightgun values */
+ for (port = machine.m_portlist.first(); port != NULL; port = port->next())
+ for (field = port->first_field(); field != NULL; field = field->next())
+ if (field->player == player && field->crossaxis != CROSSHAIR_AXIS_NONE)
+ if (input_condition_true(machine, &field->condition, port->owner()))
+ {
+ analog_field_state *analog = field->state->analog;
+ INT32 rawvalue = apply_analog_settings(analog->accum, analog) & (analog->field->mask >> analog->shift);
+ float value = (float)(rawvalue - field->state->analog->adjmin) / (float)(field->state->analog->adjmax - field->state->analog->adjmin);
+
+ /* apply the scale and offset */
+ if (field->crossscale < 0)
+ value = -(1.0 - value) * field->crossscale;
+ else
+ value *= field->crossscale;
+ value += field->crossoffset;
+
+ /* apply custom mapping if necessary */
+ if (!field->crossmapper.isnull())
+ value = field->crossmapper(*field, value);
+
+ /* handle X axis */
+ if (field->crossaxis == CROSSHAIR_AXIS_X)
+ {
+ *x = value;
+ gotx = TRUE;
+ if (field->crossaltaxis != 0)
+ {
+ *y = field->crossaltaxis;
+ goty = TRUE;
+ }
+ }
+
+ /* handle Y axis */
+ else
+ {
+ *y = value;
+ goty = TRUE;
+ if (field->crossaltaxis != 0)
+ {
+ *x = field->crossaltaxis;
+ gotx = TRUE;
+ }
+ }
+
+ /* if we got both, stop */
+ if (gotx && goty)
+ break;
+ }
+
+ return (gotx && goty);
+}
+
+
+/*-------------------------------------------------
+ input_port_update_defaults - force an update
+ to the input port values based on current
+ conditions
+-------------------------------------------------*/
+
+void input_port_update_defaults(running_machine &machine)
+{
+ int loopnum;
+
+ /* two passes to catch conditionals properly */
+ for (loopnum = 0; loopnum < 2; loopnum++)
+ {
+ const input_port_config *port;
+
+ /* loop over all input ports */
+ for (port = machine.m_portlist.first(); port != NULL; port = port->next())
+ {
+ const input_field_config *field;
+
+ /* only clear on the first pass */
+ if (loopnum == 0)
+ port->state->defvalue = 0;
+
+ /* first compute the default value for the entire port */
+ for (field = port->first_field(); field != NULL; field = field->next())
+ if (input_condition_true(machine, &field->condition, port->owner()))
+ port->state->defvalue = (port->state->defvalue & ~field->mask) | (field->state->value & field->mask);
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ apply_analog_settings - return the value of
+ an input port
+-------------------------------------------------*/
+
+static INT32 apply_analog_settings(INT32 value, analog_field_state *analog)
+{
+ /* apply the min/max and then the sensitivity */
+ value = apply_analog_min_max(analog, value);
+ value = APPLY_SENSITIVITY(value, analog->sensitivity);
+
+ /* apply reversal if needed */
+ if (analog->reverse)
+ value = analog->reverse_val - value;
+ else if (analog->single_scale)
+ /* it's a pedal or the default value is equal to min/max */
+ /* so we need to adjust the center to the minimum */
+ value -= INPUT_ABSOLUTE_MIN;
+
+ /* map differently for positive and negative values */
+ if (value >= 0)
+ value = APPLY_SCALE(value, analog->scalepos);
+ else
+ value = APPLY_SCALE(value, analog->scaleneg);
+ value += analog->adjdefvalue;
+
+ return value;
+}
+
+
+
+/***************************************************************************
+ PORT WRITING
+***************************************************************************/
+
+/*-------------------------------------------------
+ input_port_write_direct - write a value
+ to a port
+-------------------------------------------------*/
+
+void input_port_write_direct(const input_port_config *port, input_port_value data, input_port_value mem_mask)
+{
+ /* call device line write handlers */
+ device_field_info *device_field;
+
+ COMBINE_DATA(&port->state->outputvalue);
+
+ for (device_field = port->state->writedevicelist; device_field; device_field = device_field->next)
+ if (device_field->field->type == IPT_OUTPUT && input_condition_true(port->machine(), &device_field->field->condition, port->owner()))
+ {
+ input_port_value newval = ( (port->state->outputvalue ^ device_field->field->defvalue ) & device_field->field->mask) >> device_field->shift;
+
+ /* if the bits have write, call the handler */
+ if (device_field->oldval != newval)
+ {
+ device_field->field->write(*device_field->field, device_field->field->write_param, device_field->oldval, newval);
+
+ device_field->oldval = newval;
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ input_port_write - write a value to a
+ port specified by tag
+-------------------------------------------------*/
+
+void input_port_write(running_machine &machine, const char *tag, input_port_value value, input_port_value mask)
+{
+ const input_port_config *port = machine.port(tag);
+ if (port == NULL)
+ fatalerror("Unable to locate input port '%s'", tag);
+ input_port_write_direct(port, value, mask);
+}
+
+
+/*-------------------------------------------------
+ input_port_write_safe - write a value to
+ a port, ignore if the port does not exist
+-------------------------------------------------*/
+
+void input_port_write_safe(running_machine &machine, const char *tag, input_port_value value, input_port_value mask)
+{
+ const input_port_config *port = machine.port(tag);
+ if (port != NULL)
+ input_port_write_direct(port, value, mask);
+}
+
+
+
+/***************************************************************************
+ MISC HELPER FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ input_condition_true - return the TRUE
+ if the given condition attached is true
+-------------------------------------------------*/
+
+int input_condition_true(running_machine &machine, const input_condition *condition,device_t &owner)
+{
+ input_port_value condvalue;
+
+ /* always condition is always true */
+ if (condition->condition == PORTCOND_ALWAYS)
+ return TRUE;
+
+ /* otherwise, read the referenced port */
+ astring conditiontag;
+ owner.subtag(conditiontag, condition->tag);
+ condvalue = input_port_read(machine, conditiontag.cstr());
+
+ /* based on the condition encoded, determine truth */
+ switch (condition->condition)
+ {
+ case PORTCOND_EQUALS:
+ return ((condvalue & condition->mask) == condition->value);
+
+ case PORTCOND_NOTEQUALS:
+ return ((condvalue & condition->mask) != condition->value);
+
+ case PORTCOND_GREATERTHAN:
+ return ((condvalue & condition->mask) > condition->value);
+
+ case PORTCOND_NOTGREATERTHAN:
+ return ((condvalue & condition->mask) <= condition->value);
+
+ case PORTCOND_LESSTHAN:
+ return ((condvalue & condition->mask) < condition->value);
+
+ case PORTCOND_NOTLESSTHAN:
+ return ((condvalue & condition->mask) >= condition->value);
+ }
+ return TRUE;
+}
+
+
+/*-------------------------------------------------
+ input_port_string_from_token - convert an
+ input_port_token to a default string
+-------------------------------------------------*/
+
+const char *input_port_string_from_token(const char *string)
+{
+ int index;
+
+ /* 0 is an invalid index */
+ if (string == NULL)
+ return NULL;
+
+ /* if the index is greater than the count, assume it to be a pointer */
+ if (FPTR(string) >= INPUT_STRING_COUNT)
+ return string;
+
+ /* otherwise, scan the list for a matching string and return it */
+ for (index = 0; index < ARRAY_LENGTH(input_port_default_strings); index++)
+ if (input_port_default_strings[index].id == FPTR(string))
+ return input_port_default_strings[index].string;
+ return "(Unknown Default)";
+}
+
+
+
+/***************************************************************************
+ INITIALIZATION HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ init_port_types - initialize the default
+ type list
+-------------------------------------------------*/
+
+static void init_port_types(running_machine &machine)
+{
+ input_port_private *portdata = machine.input_port_data;
+
+ /* convert the array into a list of type states that can be modified */
+ construct_core_types(portdata->typelist);
+
+ /* ask the OSD to customize the list */
+ machine.osd().customize_input_type_list(portdata->typelist);
+
+ /* now iterate over the OSD-modified types */
+ for (input_type_entry *curtype = portdata->typelist.first(); curtype != NULL; curtype = curtype->next())
+ {
+ /* first copy all the OSD-updated sequences into our current state */
+ for (int seqtype = 0; seqtype < ARRAY_LENGTH(curtype->seq); seqtype++)
+ curtype->seq[seqtype] = curtype->defseq[seqtype];
+
+ /* also make a lookup table mapping type/player to the appropriate type list entry */
+ portdata->type_to_entry[curtype->type][curtype->player] = curtype;
+ }
+}
+
+
+/*-------------------------------------------------
+ get_keyboard_code - accesses a particular
+ keyboard code
+-------------------------------------------------*/
+
+static unicode_char get_keyboard_code(const input_field_config *field, int i)
+{
+ unicode_char ch = field->chars[i];
+
+ /* special hack to allow for PORT_CODE('\xA3') */
+ if ((ch >= 0xFFFFFF80) && (ch <= 0xFFFFFFFF))
+ ch &= 0xFF;
+ return ch;
+}
+
+
+/***************************************************************************
+ MISCELLANEOUS
+***************************************************************************/
+
+/*-------------------------------------------------
+ find_charinfo - looks up information about a
+ particular character
+-------------------------------------------------*/
+
+static const char_info *find_charinfo(unicode_char target_char)
+{
+ int low = 0;
+ int high = ARRAY_LENGTH(charinfo);
+ int i;
+ unicode_char ch;
+
+ /* perform a simple binary search to find the proper alternate */
+ while(high > low)
+ {
+ i = (high + low) / 2;
+ ch = charinfo[i].ch;
+ if (ch < target_char)
+ low = i + 1;
+ else if (ch > target_char)
+ high = i;
+ else
+ return &charinfo[i];
+ }
+ return NULL;
+}
+
+/*-------------------------------------------------
+ inputx_key_name - returns the name of a
+ specific key
+-------------------------------------------------*/
+
+static const char *inputx_key_name(unicode_char ch)
+{
+ static char buf[UTF8_CHAR_MAX + 1];
+ const char_info *ci;
+ const char *result;
+ int pos;
+
+ ci = find_charinfo(ch);
+ result = ci ? ci->name : NULL;
+
+ if (ci && ci->name)
+ {
+ result = ci->name;
+ }
+ else
+ {
+ if ((ch > 0x7F) || isprint(ch))
+ {
+ pos = utf8_from_uchar(buf, ARRAY_LENGTH(buf), ch);
+ buf[pos] = '\0';
+ result = buf;
+ }
+ else
+ result = "???";
+ }
+ return result;
+}
+
+/*-------------------------------------------------
+ get_keyboard_key_name - builds the name of
+ a key based on natural keyboard characters
+-------------------------------------------------*/
+
+static astring *get_keyboard_key_name(const input_field_config *field)
+{
+ astring *result = astring_alloc();
+ int i;
+ unicode_char ch;
+
+
+ /* loop through each character on the field*/
+ for (i = 0; i < ARRAY_LENGTH(field->chars) && (field->chars[i] != '\0'); i++)
+ {
+ ch = get_keyboard_code(field, i);
+ astring_printf(result, "%s%-*s ", astring_c(result), MAX(SPACE_COUNT - 1, 0), inputx_key_name(ch));
+ }
+
+ /* trim extra spaces */
+ astring_trimspace(result);
+
+ /* special case */
+ if (astring_len(result) == 0)
+ astring_cpyc(result, "Unnamed Key");
+
+ return result;
+}
+
+/*-------------------------------------------------
+ init_port_state - initialize the live port
+ states based on the tokens
+-------------------------------------------------*/
+
+inline const char *get_device_tag(const device_t &device, const char *tag, astring &finaltag)
+{
+ if (strcmp(tag, DEVICE_SELF) == 0)
+ finaltag.cpy(device.tag());
+ else if (strcmp(tag, DEVICE_SELF_OWNER) == 0)
+ {
+ assert(device.owner() != NULL);
+ finaltag.cpy(device.owner()->tag());
+ }
+ else
+ device.subtag(finaltag, tag);
+ return finaltag;
+}
+
+static void init_port_state(running_machine &machine)
+{
+ const char *joystick_map_default = machine.options().joystick_map();
+ input_port_private *portdata = machine.input_port_data;
+ input_field_config *field;
+ input_port_config *port;
+
+ /* allocate live structures to mirror the configuration */
+ for (port = machine.m_portlist.first(); port != NULL; port = port->next())
+ {
+ analog_field_state **analogstatetail;
+ device_field_info **readdevicetail;
+ device_field_info **writedevicetail;
+ input_port_state *portstate;
+
+ /* allocate a new input_port_info structure */
+ portstate = auto_alloc_clear(machine, input_port_state);
+ ((input_port_config *)port)->state = portstate;
+
+ /* start with tail pointers to all the data */
+ analogstatetail = &portstate->analoglist;
+ readdevicetail = &portstate->readdevicelist;
+ writedevicetail = &portstate->writedevicelist;
+
+ /* iterate over fields */
+ for (field = port->first_field(); field != NULL; field = field->next())
+ {
+ input_field_state *fieldstate;
+ int seqtype;
+
+ /* allocate a new input_field_info structure */
+ fieldstate = auto_alloc_clear(machine, input_field_state);
+ ((input_field_config *)field)->state = fieldstate;
+
+ /* fill in the basic values */
+ for (seqtype = 0; seqtype < ARRAY_LENGTH(fieldstate->seq); seqtype++)
+ fieldstate->seq[seqtype] = field->seq[seqtype];
+ fieldstate->value = field->defvalue;
+
+ /* if this is an analog field, allocate memory for the analog data */
+ if (field->type >= __ipt_analog_start && field->type <= __ipt_analog_end)
+ {
+ *analogstatetail = fieldstate->analog = init_field_analog_state(field);
+ analogstatetail = &(*analogstatetail)->next;
+ }
+
+ /* if this is a digital joystick field, make a note of it */
+ if (field->type >= __ipt_digital_joystick_start && field->type <= __ipt_digital_joystick_end)
+ {
+ fieldstate->joystick = &portdata->joystick_info[field->player][(field->type - __ipt_digital_joystick_start) / 4];
+ fieldstate->joydir = (field->type - __ipt_digital_joystick_start) % 4;
+ fieldstate->joystick->field[fieldstate->joydir] = field;
+ fieldstate->joystick->inuse = TRUE;
+ }
+
+ /* if this entry has device input, allocate memory for the tracking structure */
+ astring devicetag;
+ if (!field->read.isnull())
+ {
+ *readdevicetail = init_field_device_info(field, get_device_tag(port->owner(), field->read_device, devicetag));
+ field->read.late_bind(*(*readdevicetail)->device);
+ readdevicetail = &(*readdevicetail)->next;
+ }
+
+ /* if this entry has device output, allocate memory for the tracking structure */
+ if (!field->write.isnull())
+ {
+ *writedevicetail = init_field_device_info(field, get_device_tag(port->owner(), field->write_device, devicetag));
+ field->write.late_bind(*(*writedevicetail)->device);
+ writedevicetail = &(*writedevicetail)->next;
+ }
+
+ /* if this entry has device output, allocate memory for the tracking structure */
+ if (!field->crossmapper.isnull())
+ {
+ device_t *device = machine.device(get_device_tag(port->owner(), field->crossmapper_device, devicetag));
+ field->crossmapper.late_bind(*device);
+ }
+
+ /* Name keyboard key names */
+ if ((field->type == IPT_KEYBOARD || field->type == IPT_KEYPAD) && (field->name == NULL))
+ {
+ astring *name = get_keyboard_key_name(field);
+ if (name != NULL)
+ {
+ field->state->name = auto_strdup(machine, astring_c(name));
+ astring_free(name);
+ }
+ }
+ }
+ }
+
+ /* handle autoselection of devices */
+ init_autoselect_devices(machine, IPT_PADDLE, IPT_PADDLE_V, 0, OPTION_PADDLE_DEVICE, "paddle");
+ init_autoselect_devices(machine, IPT_AD_STICK_X, IPT_AD_STICK_Y, IPT_AD_STICK_Z, OPTION_ADSTICK_DEVICE, "analog joystick");
+ init_autoselect_devices(machine, IPT_LIGHTGUN_X, IPT_LIGHTGUN_Y, 0, OPTION_LIGHTGUN_DEVICE, "lightgun");
+ init_autoselect_devices(machine, IPT_PEDAL, IPT_PEDAL2, IPT_PEDAL3, OPTION_PEDAL_DEVICE, "pedal");
+ init_autoselect_devices(machine, IPT_DIAL, IPT_DIAL_V, 0, OPTION_DIAL_DEVICE, "dial");
+ init_autoselect_devices(machine, IPT_TRACKBALL_X, IPT_TRACKBALL_Y, 0, OPTION_TRACKBALL_DEVICE, "trackball");
+ init_autoselect_devices(machine, IPT_POSITIONAL, IPT_POSITIONAL_V, 0, OPTION_POSITIONAL_DEVICE, "positional");
+ init_autoselect_devices(machine, IPT_MOUSE_X, IPT_MOUSE_Y, 0, OPTION_MOUSE_DEVICE, "mouse");
+
+ /* look for 4-way joysticks and change the default map if we find any */
+ if (joystick_map_default[0] == 0 || strcmp(joystick_map_default, "auto") == 0)
+ for (port = machine.m_portlist.first(); port != NULL; port = port->next())
+ for (field = port->first_field(); field != NULL; field = field->next())
+ if (field->state->joystick != NULL && field->way == 4)
+ {
+ machine.input().set_global_joystick_map((field->flags & FIELD_FLAG_ROTATED) ? joystick_map_4way_diagonal : joystick_map_4way_sticky);
+ break;
+ }
+}
+
+
+/*-------------------------------------------------
+ init_autoselect_devices - autoselect a single
+ device based on the input port list passed
+ in and the corresponding option
+-------------------------------------------------*/
+
+static void init_autoselect_devices(running_machine &machine, int type1, int type2, int type3, const char *option, const char *ananame)
+{
+ const ioport_list &portlist = machine.m_portlist;
+ const char *stemp = machine.options().value(option);
+ input_device_class autoenable = DEVICE_CLASS_KEYBOARD;
+ const char *autostring = "keyboard";
+ const input_field_config *field;
+ const input_port_config *port;
+
+ /* if nothing specified, ignore the option */
+ if (stemp[0] == 0)
+ return;
+
+ /* extract valid strings */
+ if (strcmp(stemp, "mouse") == 0)
+ {
+ autoenable = DEVICE_CLASS_MOUSE;
+ autostring = "mouse";
+ }
+ else if (strcmp(stemp, "joystick") == 0)
+ {
+ autoenable = DEVICE_CLASS_JOYSTICK;
+ autostring = "joystick";
+ }
+ else if (strcmp(stemp, "lightgun") == 0)
+ {
+ autoenable = DEVICE_CLASS_LIGHTGUN;
+ autostring = "lightgun";
+ }
+ else if (strcmp(stemp, "none") == 0)
+ {
+ /* nothing specified */
+ return;
+ }
+ else if (strcmp(stemp, "keyboard") != 0)
+ mame_printf_error("Invalid %s value %s; reverting to keyboard\n", option, stemp);
+
+ /* only scan the list if we haven't already enabled this class of control */
+ if (portlist.first() != NULL && !machine.input().device_class(autoenable).enabled())
+ for (port = portlist.first(); port != NULL; port = port->next())
+ for (field = port->first_field(); field != NULL; field = field->next())
+
+ /* if this port type is in use, apply the autoselect criteria */
+ if ((type1 != 0 && field->type == type1) ||
+ (type2 != 0 && field->type == type2) ||
+ (type3 != 0 && field->type == type3))
+ {
+ mame_printf_verbose("Input: Autoenabling %s due to presence of a %s\n", autostring, ananame);
+ machine.input().device_class(autoenable).enable();
+ break;
+ }
+}
+
+
+/*-------------------------------------------------
+ init_field_device_info - allocate and populate
+ information about a device callback
+-------------------------------------------------*/
+
+static device_field_info *init_field_device_info(const input_field_config *field, const char *device_name)
+{
+ device_field_info *info;
+ input_port_value mask;
+
+ /* allocate memory */
+ info = auto_alloc_clear(field->machine(), device_field_info);
+
+ /* fill in the data */
+ info->field = field;
+ for (mask = field->mask; !(mask & 1); mask >>= 1)
+ info->shift++;
+
+ info->device = (device_name != NULL) ? field->machine().device(device_name) : &field->port().owner();
+
+ info->oldval = field->defvalue >> info->shift;
+ return info;
+}
+
+
+/*-------------------------------------------------
+ init_field_analog_state - allocate and populate
+ information about an analog port
+-------------------------------------------------*/
+
+static analog_field_state *init_field_analog_state(const input_field_config *field)
+{
+ analog_field_state *state;
+ input_port_value mask;
+
+ /* allocate memory */
+ state = auto_alloc_clear(field->machine(), analog_field_state);
+
+ /* compute the shift amount and number of bits */
+ for (mask = field->mask; !(mask & 1); mask >>= 1)
+ state->shift++;
+
+ /* initialize core data */
+ state->field = field;
+ state->adjdefvalue = (field->defvalue & field->mask) >> state->shift;
+ state->adjmin = (field->min & field->mask) >> state->shift;
+ state->adjmax = (field->max & field->mask) >> state->shift;
+ state->sensitivity = field->sensitivity;
+ state->reverse = ((field->flags & ANALOG_FLAG_REVERSE) != 0);
+ state->delta = field->delta;
+ state->centerdelta = field->centerdelta;
+ state->minimum = INPUT_ABSOLUTE_MIN;
+ state->maximum = INPUT_ABSOLUTE_MAX;
+
+ /* set basic parameters based on the configured type */
+ switch (field->type)
+ {
+ /* pedals start at and autocenter to the min range */
+ case IPT_PEDAL:
+ case IPT_PEDAL2:
+ case IPT_PEDAL3:
+ state->center = INPUT_ABSOLUTE_MIN;
+ state->accum = APPLY_INVERSE_SENSITIVITY(state->center, state->sensitivity);
+ state->absolute = TRUE;
+ state->autocenter = TRUE;
+ state->interpolate = TRUE;
+ break;
+
+ /* paddles and analog joysticks are absolute and autocenter */
+ case IPT_AD_STICK_X:
+ case IPT_AD_STICK_Y:
+ case IPT_AD_STICK_Z:
+ case IPT_PADDLE:
+ case IPT_PADDLE_V:
+ state->absolute = TRUE;
+ state->autocenter = TRUE;
+ state->interpolate = TRUE;
+ break;
+
+ /* lightguns are absolute as well, but don't autocenter and don't interpolate their values */
+ case IPT_LIGHTGUN_X:
+ case IPT_LIGHTGUN_Y:
+ state->absolute = TRUE;
+ state->autocenter = FALSE;
+ state->interpolate = FALSE;
+ break;
+
+ /* dials, mice and trackballs are relative devices */
+ /* these have fixed "min" and "max" values based on how many bits are in the port */
+ /* in addition, we set the wrap around min/max values to 512 * the min/max values */
+ /* this takes into account the mapping that one mouse unit ~= 512 analog units */
+ case IPT_DIAL:
+ case IPT_DIAL_V:
+ case IPT_MOUSE_X:
+ case IPT_MOUSE_Y:
+ case IPT_TRACKBALL_X:
+ case IPT_TRACKBALL_Y:
+ state->absolute = FALSE;
+ state->wraps = TRUE;
+ state->interpolate = TRUE;
+ break;
+
+ /* positional devices are abolute, but can also wrap like relative devices */
+ /* set each position to be 512 units */
+ case IPT_POSITIONAL:
+ case IPT_POSITIONAL_V:
+ state->positionalscale = COMPUTE_SCALE(field->max, INPUT_ABSOLUTE_MAX - INPUT_ABSOLUTE_MIN);
+ state->adjmin = 0;
+ state->adjmax = field->max - 1;
+ state->wraps = ((field->flags & ANALOG_FLAG_WRAPS) != 0);
+ state->autocenter = !state->wraps;
+ break;
+
+ default:
+ fatalerror("Unknown analog port type -- don't know if it is absolute or not");
+ break;
+ }
+
+ /* further processing for absolute controls */
+ if (state->absolute)
+ {
+ /* if the default value is pegged at the min or max, use a single scale value for the whole axis */
+ state->single_scale = (state->adjdefvalue == state->adjmin) || (state->adjdefvalue == state->adjmax);
+
+ /* if not "single scale", compute separate scales for each side of the default */
+ if (!state->single_scale)
+ {
+ /* unsigned */
+ state->scalepos = COMPUTE_SCALE(state->adjmax - state->adjdefvalue, INPUT_ABSOLUTE_MAX - 0);
+ state->scaleneg = COMPUTE_SCALE(state->adjdefvalue - state->adjmin, 0 - INPUT_ABSOLUTE_MIN);
+
+ if (state->adjmin > state->adjmax)
+ state->scaleneg = -state->scaleneg;
+
+ /* reverse point is at center */
+ state->reverse_val = 0;
+ }
+ else
+ {
+ /* single axis that increases from default */
+ state->scalepos = COMPUTE_SCALE(state->adjmax - state->adjmin, INPUT_ABSOLUTE_MAX - INPUT_ABSOLUTE_MIN);
+
+ /* move from default */
+ if (state->adjdefvalue == state->adjmax)
+ state->scalepos = -state->scalepos;
+
+ /* make the scaling the same for easier coding when we need to scale */
+ state->scaleneg = state->scalepos;
+
+ /* reverse point is at max */
+ state->reverse_val = state->maximum;
+ }
+ }
+
+ /* relative and positional controls all map directly with a 512x scale factor */
+ else
+ {
+ /* The relative code is set up to allow specifing PORT_MINMAX and default values. */
+ /* The validity checks are purposely set up to not allow you to use anything other */
+ /* a default of 0 and PORT_MINMAX(0,mask). This is in case the need arises to use */
+ /* this feature in the future. Keeping the code in does not hurt anything. */
+ if (state->adjmin > state->adjmax)
+ /* adjust for signed */
+ state->adjmin = -state->adjmin;
+
+ state->minimum = (state->adjmin - state->adjdefvalue) * INPUT_RELATIVE_PER_PIXEL;
+ state->maximum = (state->adjmax - state->adjdefvalue) * INPUT_RELATIVE_PER_PIXEL;
+
+ /* make the scaling the same for easier coding when we need to scale */
+ state->scaleneg = state->scalepos = COMPUTE_SCALE(1, INPUT_RELATIVE_PER_PIXEL);
+
+ if (field->flags & ANALOG_FLAG_RESET)
+ /* delta values reverse from center */
+ state->reverse_val = 0;
+ else
+ {
+ /* positional controls reverse from their max range */
+ state->reverse_val = state->maximum + state->minimum;
+
+ /* relative controls reverse from 1 past their max range */
+ if (state->positionalscale == 0)
+ state->reverse_val += INPUT_RELATIVE_PER_PIXEL;
+ }
+ }
+
+ /* compute scale for keypresses */
+ state->keyscalepos = RECIP_SCALE(state->scalepos);
+ state->keyscaleneg = RECIP_SCALE(state->scaleneg);
+
+ return state;
+}
+
+
+
+/***************************************************************************
+ ONCE-PER-FRAME UPDATES
+***************************************************************************/
+
+/*-------------------------------------------------
+ frame_update_callback - system-wide callback to
+ update the input ports once per frame, but
+ only if we are not paused
+-------------------------------------------------*/
+
+static void frame_update_callback(running_machine &machine)
+{
+ /* if we're paused, don't do anything */
+ if (machine.paused())
+ return;
+
+ /* otherwise, use the common code */
+ frame_update(machine);
+}
+
+static key_buffer *get_buffer(running_machine &machine)
+{
+ input_port_private *portdata = machine.input_port_data;
+ assert(inputx_can_post(machine));
+ return (key_buffer *)portdata->keybuffer;
+}
+
+
+
+static const inputx_code *find_code(inputx_code *codes, unicode_char ch)
+{
+ int i;
+
+ assert(codes);
+ for (i = 0; codes[i].ch; i++)
+ {
+ if (codes[i].ch == ch)
+ return &codes[i];
+ }
+ return NULL;
+}
+
+/*-------------------------------------------------
+ input_port_update_hook - hook function
+ called from core to allow for natural keyboard
+-------------------------------------------------*/
+
+static void input_port_update_hook(running_machine &machine, const input_port_config *port, input_port_value *digital)
+{
+ input_port_private *portdata = machine.input_port_data;
+ const key_buffer *keybuf;
+ const inputx_code *code;
+ unicode_char ch;
+ int i;
+ UINT32 value;
+
+ if (inputx_can_post(machine))
+ {
+ keybuf = get_buffer(machine);
+
+ /* is the key down right now? */
+ if (keybuf && keybuf->status_keydown && (keybuf->begin_pos != keybuf->end_pos))
+ {
+ /* identify the character that is down right now, and its component codes */
+ ch = keybuf->buffer[keybuf->begin_pos];
+ code = find_code(portdata->codes, ch);
+
+ /* loop through this character's component codes */
+ if (code != NULL)
+ {
+ for (i = 0; i < ARRAY_LENGTH(code->field) && (code->field[i] != NULL); i++)
+ {
+ if (&code->field[i]->port() == port)
+ {
+ value = code->field[i]->mask;
+ *digital |= value;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ frame_update - core logic for per-frame input
+ port updating
+-------------------------------------------------*/
+
+static void frame_update(running_machine &machine)
+{
+ input_port_private *portdata = machine.input_port_data;
+ const input_field_config *mouse_field = NULL;
+ int ui_visible = ui_is_menu_active();
+ attotime curtime = machine.time();
+ const input_port_config *port;
+ render_target *mouse_target;
+ INT32 mouse_target_x;
+ INT32 mouse_target_y;
+ int mouse_button;
+
+g_profiler.start(PROFILER_INPUT);
+
+ /* record/playback information about the current frame */
+ playback_frame(machine, curtime);
+ record_frame(machine, curtime);
+
+ /* track the duration of the previous frame */
+ portdata->last_delta_nsec = (curtime - portdata->last_frame_time).as_attoseconds() / ATTOSECONDS_PER_NANOSECOND;
+ portdata->last_frame_time = curtime;
+
+ /* update the digital joysticks */
+ frame_update_digital_joysticks(machine);
+
+ /* compute default values for all the ports */
+ input_port_update_defaults(machine);
+
+ /* perform the mouse hit test */
+ mouse_target = ui_input_find_mouse(machine, &mouse_target_x, &mouse_target_y, &mouse_button);
+ if (mouse_button && mouse_target)
+ {
+ const char *tag = NULL;
+ input_port_value mask;
+ float x, y;
+ if (mouse_target->map_point_input(mouse_target_x, mouse_target_y, tag, mask, x, y))
+ mouse_field = input_field_by_tag_and_mask(machine.m_portlist, tag, mask);
+ }
+
+ /* loop over all input ports */
+ for (port = machine.m_portlist.first(); port != NULL; port = port->next())
+ {
+ const input_field_config *field;
+ device_field_info *device_field;
+ input_port_value newvalue;
+
+ /* start with 0 values for the digital and VBLANK bits */
+ port->state->digital = 0;
+ port->state->vblank = 0;
+
+ /* now loop back and modify based on the inputs */
+ for (field = port->first_field(); field != NULL; field = field->next())
+ if (input_condition_true(port->machine(), &field->condition, port->owner()))
+ {
+ /* accumulate VBLANK bits */
+ if (field->type == IPT_VBLANK)
+ port->state->vblank ^= field->mask;
+
+ /* handle analog inputs */
+ else if (field->state->analog != NULL)
+ frame_update_analog_field(machine, field->state->analog);
+
+ /* handle non-analog types, but only when the UI isn't visible */
+ else if (!ui_visible && frame_get_digital_field_state(field, field == mouse_field))
+ port->state->digital |= field->mask;
+ }
+
+ /* hook for MESS's natural keyboard support */
+ input_port_update_hook(machine, port, &port->state->digital);
+
+ /* handle playback/record */
+ playback_port(port);
+ record_port(port);
+
+ /* call device line write handlers */
+ newvalue = input_port_read_direct(port);
+ for (device_field = port->state->writedevicelist; device_field; device_field = device_field->next)
+ if (device_field->field->type != IPT_OUTPUT && input_condition_true(port->machine(), &device_field->field->condition, port->owner()))
+ {
+ input_port_value newval = (newvalue & device_field->field->mask) >> device_field->shift;
+
+ /* if the bits have write, call the handler */
+ if (device_field->oldval != newval)
+ {
+ device_field->field->write(*device_field->field, device_field->field->write_param, device_field->oldval, newval);
+
+ device_field->oldval = newval;
+ }
+ }
+ }
+
+g_profiler.stop();
+}
+
+
+/*-------------------------------------------------
+ frame_update_digital_joysticks - update the
+ state of digital joysticks prior to
+ accumulating the results in a port
+-------------------------------------------------*/
+
+static void frame_update_digital_joysticks(running_machine &machine)
+{
+ input_port_private *portdata = machine.input_port_data;
+ int player, joyindex;
+
+ /* loop over all the joysticks */
+ for (player = 0; player < MAX_PLAYERS; player++)
+ for (joyindex = 0; joyindex < DIGITAL_JOYSTICKS_PER_PLAYER; joyindex++)
+ {
+ digital_joystick_state *joystick = &portdata->joystick_info[player][joyindex];
+ if (joystick->inuse)
+ {
+ joystick->previous = joystick->current;
+ joystick->current = 0;
+
+ /* read all the associated ports */
+ if (joystick->field[JOYDIR_UP] != NULL && machine.input().seq_pressed(input_field_seq(joystick->field[JOYDIR_UP], SEQ_TYPE_STANDARD)))
+ joystick->current |= JOYDIR_UP_BIT;
+ if (joystick->field[JOYDIR_DOWN] != NULL && machine.input().seq_pressed(input_field_seq(joystick->field[JOYDIR_DOWN], SEQ_TYPE_STANDARD)))
+ joystick->current |= JOYDIR_DOWN_BIT;
+ if (joystick->field[JOYDIR_LEFT] != NULL && machine.input().seq_pressed(input_field_seq(joystick->field[JOYDIR_LEFT], SEQ_TYPE_STANDARD)))
+ joystick->current |= JOYDIR_LEFT_BIT;
+ if (joystick->field[JOYDIR_RIGHT] != NULL && machine.input().seq_pressed(input_field_seq(joystick->field[JOYDIR_RIGHT], SEQ_TYPE_STANDARD)))
+ joystick->current |= JOYDIR_RIGHT_BIT;
+
+ /* lock out opposing directions (left + right or up + down) */
+ if ((joystick->current & (JOYDIR_UP_BIT | JOYDIR_DOWN_BIT)) == (JOYDIR_UP_BIT | JOYDIR_DOWN_BIT))
+ joystick->current &= ~(JOYDIR_UP_BIT | JOYDIR_DOWN_BIT);
+ if ((joystick->current & (JOYDIR_LEFT_BIT | JOYDIR_RIGHT_BIT)) == (JOYDIR_LEFT_BIT | JOYDIR_RIGHT_BIT))
+ joystick->current &= ~(JOYDIR_LEFT_BIT | JOYDIR_RIGHT_BIT);
+
+ /* only update 4-way case if joystick has moved */
+ if (joystick->current != joystick->previous)
+ {
+ joystick->current4way = joystick->current;
+
+ /*
+ If joystick is pointing at a diagonal, acknowledge that the player moved
+ the joystick by favoring a direction change. This minimizes frustration
+ when using a keyboard for input, and maximizes responsiveness.
+
+ For example, if you are holding "left" then switch to "up" (where both left
+ and up are briefly pressed at the same time), we'll transition immediately
+ to "up."
+
+ Zero any switches that didn't change from the previous to current state.
+ */
+ if ((joystick->current4way & (JOYDIR_UP_BIT | JOYDIR_DOWN_BIT)) &&
+ (joystick->current4way & (JOYDIR_LEFT_BIT | JOYDIR_RIGHT_BIT)))
+ {
+ joystick->current4way ^= joystick->current4way & joystick->previous;
+ }
+
+ /*
+ If we are still pointing at a diagonal, we are in an indeterminant state.
+
+ This could happen if the player moved the joystick from the idle position directly
+ to a diagonal, or from one diagonal directly to an extreme diagonal.
+
+ The chances of this happening with a keyboard are slim, but we still need to
+ constrain this case.
+
+ For now, just resolve randomly.
+ */
+ if ((joystick->current4way & (JOYDIR_UP_BIT | JOYDIR_DOWN_BIT)) &&
+ (joystick->current4way & (JOYDIR_LEFT_BIT | JOYDIR_RIGHT_BIT)))
+ {
+ if (machine.rand() & 1)
+ joystick->current4way &= ~(JOYDIR_LEFT_BIT | JOYDIR_RIGHT_BIT);
+ else
+ joystick->current4way &= ~(JOYDIR_UP_BIT | JOYDIR_DOWN_BIT);
+ }
+ }
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ frame_update_analog_field - update the
+ internals of a single analog field
+-------------------------------------------------*/
+
+static void frame_update_analog_field(running_machine &machine, analog_field_state *analog)
+{
+ input_item_class itemclass;
+ int keypressed = FALSE;
+ INT64 keyscale;
+ INT32 rawvalue;
+ INT32 delta = 0;
+
+ /* clamp the previous value to the min/max range and remember it */
+ analog->previous = analog->accum = apply_analog_min_max(analog, analog->accum);
+
+ /* get the new raw analog value and its type */
+ rawvalue = machine.input().seq_axis_value(input_field_seq(analog->field, SEQ_TYPE_STANDARD), itemclass);
+
+ /* if we got an absolute input, it overrides everything else */
+ if (itemclass == ITEM_CLASS_ABSOLUTE)
+ {
+ if (analog->previousanalog != rawvalue)
+ {
+ /* only update if analog value changed */
+ analog->previousanalog = rawvalue;
+
+ /* apply the inverse of the sensitivity to the raw value so that */
+ /* it will still cover the full min->max range requested after */
+ /* we apply the sensitivity adjustment */
+ if (analog->absolute || (analog->field->flags & ANALOG_FLAG_RESET))
+ {
+ /* if port is absolute, then just return the absolute data supplied */
+ analog->accum = APPLY_INVERSE_SENSITIVITY(rawvalue, analog->sensitivity);
+ }
+ else if (analog->positionalscale != 0)
+ {
+ /* if port is positional, we will take the full analog control and divide it */
+ /* into positions, that way as the control is moved full scale, */
+ /* it moves through all the positions */
+ rawvalue = APPLY_SCALE(rawvalue - INPUT_ABSOLUTE_MIN, analog->positionalscale) * INPUT_RELATIVE_PER_PIXEL + analog->minimum;
+
+ /* clamp the high value so it does not roll over */
+ rawvalue = MIN(rawvalue, analog->maximum);
+ analog->accum = APPLY_INVERSE_SENSITIVITY(rawvalue, analog->sensitivity);
+ }
+ else
+ /* if port is relative, we use the value to simulate the speed of relative movement */
+ /* sensitivity adjustment is allowed for this mode */
+ analog->accum += rawvalue;
+
+ analog->lastdigital = 0;
+ /* do not bother with other control types if the analog data is changing */
+ return;
+ }
+ else
+ {
+ /* we still have to update fake relative from joystick control */
+ if (!analog->absolute && analog->positionalscale == 0)
+ analog->accum += rawvalue;
+ }
+ }
+
+ /* if we got it from a relative device, use that as the starting delta */
+ /* also note that the last input was not a digital one */
+ if (itemclass == ITEM_CLASS_RELATIVE && rawvalue != 0)
+ {
+ delta = rawvalue;
+ analog->lastdigital = 0;
+ }
+
+ keyscale = (analog->accum >= 0) ? analog->keyscalepos : analog->keyscaleneg;
+
+ /* if the decrement code sequence is pressed, add the key delta to */
+ /* the accumulated delta; also note that the last input was a digital one */
+ if (machine.input().seq_pressed(input_field_seq(analog->field, SEQ_TYPE_DECREMENT)))
+ {
+ keypressed = TRUE;
+ if (analog->delta != 0)
+ delta -= APPLY_SCALE(analog->delta, keyscale);
+ else if (!analog->lastdigital)
+ /* decrement only once when first pressed */
+ delta -= APPLY_SCALE(1, keyscale);
+ analog->lastdigital = TRUE;
+ }
+
+ /* same for the increment code sequence */
+ if (machine.input().seq_pressed(input_field_seq(analog->field, SEQ_TYPE_INCREMENT)))
+ {
+ keypressed = TRUE;
+ if (analog->delta)
+ delta += APPLY_SCALE(analog->delta, keyscale);
+ else if (!analog->lastdigital)
+ /* increment only once when first pressed */
+ delta += APPLY_SCALE(1, keyscale);
+ analog->lastdigital = TRUE;
+ }
+
+ /* if resetting is requested, clear the accumulated position to 0 before */
+ /* applying the deltas so that we only return this frame's delta */
+ /* note that centering only works for relative controls */
+ /* no need to check if absolute here because it is checked by the validity tests */
+ if (analog->field->flags & ANALOG_FLAG_RESET)
+ analog->accum = 0;
+
+ /* apply the delta to the accumulated value */
+ analog->accum += delta;
+
+ /* if our last movement was due to a digital input, and if this control */
+ /* type autocenters, and if neither the increment nor the decrement seq */
+ /* was pressed, apply autocentering */
+ if (analog->autocenter)
+ {
+ INT32 center = APPLY_INVERSE_SENSITIVITY(analog->center, analog->sensitivity);
+ if (analog->lastdigital && !keypressed)
+ {
+ /* autocenter from positive values */
+ if (analog->accum >= center)
+ {
+ analog->accum -= APPLY_SCALE(analog->centerdelta, analog->keyscalepos);
+ if (analog->accum < center)
+ {
+ analog->accum = center;
+ analog->lastdigital = FALSE;
+ }
+ }
+
+ /* autocenter from negative values */
+ else
+ {
+ analog->accum += APPLY_SCALE(analog->centerdelta, analog->keyscaleneg);
+ if (analog->accum > center)
+ {
+ analog->accum = center;
+ analog->lastdigital = FALSE;
+ }
+ }
+ }
+ }
+ else if (!keypressed)
+ analog->lastdigital = FALSE;
+}
+
+
+/*-------------------------------------------------
+ frame_get_digital_field_state - get the state
+ of a digital field
+-------------------------------------------------*/
+
+static int frame_get_digital_field_state(const input_field_config *field, int mouse_down)
+{
+ int curstate = mouse_down || field->machine().input().seq_pressed(input_field_seq(field, SEQ_TYPE_STANDARD));
+ int changed = FALSE;
+
+ /* if the state changed, look for switch down/switch up */
+ if (curstate != field->state->last)
+ {
+ field->state->last = curstate;
+ changed = TRUE;
+ }
+
+ if (field->type == IPT_KEYBOARD && ui_get_use_natural_keyboard(field->machine()))
+ return FALSE;
+
+ /* if this is a switch-down event, handle impulse and toggle */
+ if (changed && curstate)
+ {
+ /* impluse controls: reset the impulse counter */
+ if (field->impulse != 0 && field->state->impulse == 0)
+ field->state->impulse = field->impulse;
+
+ /* toggle controls: flip the toggle state or advance to the next setting */
+ if (field->flags & FIELD_FLAG_TOGGLE)
+ {
+ if (field->settinglist().count() == 0)
+ field->state->value ^= field->mask;
+ else
+ input_field_select_next_setting(field);
+ }
+ }
+
+ /* update the current state with the impulse state */
+ if (field->impulse != 0)
+ {
+ if (field->state->impulse != 0)
+ {
+ field->state->impulse--;
+ curstate = TRUE;
+ }
+ else
+ curstate = FALSE;
+ }
+
+ /* for toggle switches, the current value is folded into the port's default value */
+ /* so we always return FALSE here */
+ if (field->flags & FIELD_FLAG_TOGGLE)
+ curstate = FALSE;
+
+ /* additional logic to restrict digital joysticks */
+ if (curstate && !mouse_down && field->state->joystick != NULL && field->way != 16)
+ {
+ UINT8 mask = (field->way == 4) ? field->state->joystick->current4way : field->state->joystick->current;
+ if (!(mask & (1 << field->state->joydir)))
+ curstate = FALSE;
+ }
+
+ /* skip locked-out coin inputs */
+ if (curstate && field->type >= IPT_COIN1 && field->type <= IPT_COIN12 && coin_lockout_get_state(field->machine(), field->type - IPT_COIN1) && field->machine().options().coin_lockout())
+ {
+ int verbose = field->machine().options().verbose();
+#ifdef MAME_DEBUG
+ verbose = 1;
+#endif
+ if (verbose)
+ ui_popup_time(3, "Coinlock disabled %s.", input_field_name(field));
+ return FALSE;
+ }
+ return curstate;
+}
+
+
+
+/***************************************************************************
+ PORT CONFIGURATION HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ port_default_value - updates default value
+ of port settings according to device settings
+-------------------------------------------------*/
+
+UINT32 port_default_value(const char *fulltag, UINT32 mask, UINT32 defval, device_t &owner)
+{
+ astring tempstring;
+ const input_device_default *def = NULL;
+ def = owner.input_ports_defaults();
+ if (def!=NULL) {
+ while (def->tag!=NULL) {
+ if ((strcmp(fulltag,owner.subtag(tempstring,def->tag))==0) && (def->mask == mask)) {
+ return def->defvalue;
+ }
+ def++;
+ }
+ }
+ return defval;
+}
+
+
+/*-------------------------------------------------
+ input_port_config - constructor for an
+ I/O port configuration object
+-------------------------------------------------*/
+
+input_port_config::input_port_config(device_t &owner, const char *tag)
+ : state(NULL),
+ active(0),
+ m_next(NULL),
+ m_owner(owner),
+ m_tag(tag),
+ m_modcount(0)
+{
+}
+
+
+running_machine &input_port_config::machine() const
+{
+ return m_owner.machine();
+}
+
+
+/*-------------------------------------------------
+ field_config_alloc - allocate a new input
+ port field config
+-------------------------------------------------*/
+
+input_field_config::input_field_config(input_port_config &port, int _type, input_port_value _defvalue, input_port_value _maskbits, const char *_name)
+ : mask(_maskbits),
+ defvalue(_defvalue & _maskbits),
+ type(_type),
+ player(0),
+ flags(0),
+ impulse(0),
+ name(_name),
+ read_param(NULL),
+ read_device(DEVICE_SELF),
+ write_param(NULL),
+ write_device(DEVICE_SELF),
+ min(0),
+ max(_maskbits),
+ sensitivity(0),
+ delta(0),
+ centerdelta(0),
+ crossaxis(0),
+ crossscale(0),
+ crossoffset(0),
+ crossaltaxis(0),
+ crossmapper_device(DEVICE_SELF),
+ full_turn_count(0),
+ remap_table(NULL),
+ way(0),
+ state(NULL),
+ m_next(NULL),
+ m_port(port),
+ m_modcount(port.modcount())
+{
+ memset(&condition, 0, sizeof(condition));
+ for (int seqtype = 0; seqtype < ARRAY_LENGTH(seq); seqtype++)
+ seq[seqtype].set_default();
+ chars[0] = chars[1] = chars[2] = (unicode_char) 0;
+}
+
+
+input_setting_config::input_setting_config(input_field_config &field, input_port_value _value, const char *_name)
+ : value(_value),
+ name(_name),
+ m_field(field),
+ m_next(NULL)
+{
+ memset(&condition, 0, sizeof(condition));
+}
+
+input_field_diplocation::input_field_diplocation(const char *string, UINT8 _swnum, bool _invert)
+ : swname(string),
+ swnum(_swnum),
+ invert(_invert)
+{
+}
+
+/*-------------------------------------------------
+ field_config_insert - insert an allocated
+ input port field config, replacing any
+ intersecting fields already present and
+ inserting at the correct sorted location
+-------------------------------------------------*/
+
+void input_port_config::collapse_fields(astring &errorbuf)
+{
+ input_field_config *list = m_fieldlist.detach_all();
+ input_port_value maskbits = 0;
+ int lastmodcount = -1;
+ while (list != NULL)
+ {
+ if (list->modcount() != lastmodcount)
+ {
+ lastmodcount = list->modcount();
+ maskbits = 0;
+ }
+ input_field_config *current = list;
+ list = list->next();
+ field_config_insert(*current, maskbits, errorbuf);
+ }
+}
+
+void field_config_insert(input_field_config &newfield, input_port_value &disallowedbits, astring &errorbuf)
+{
+ input_port_value lowbit;
+
+ /* verify against the disallowed bits, but only if we are condition-free */
+ if (newfield.condition.condition == PORTCOND_ALWAYS)
+ {
+ if ((newfield.mask & disallowedbits) != 0)
+ errorbuf.catprintf("INPUT_TOKEN_FIELD specifies duplicate port bits (port=%s mask=%X)\n", newfield.port().tag(), newfield.mask);
+ disallowedbits |= newfield.mask;
+ }
+
+ /* first modify/nuke any entries that intersect our maskbits */
+ input_field_config *nextfield;
+ for (input_field_config *field = newfield.port().fieldlist().first(); field != NULL; field = nextfield)
+ {
+ nextfield = field->next();
+ if ((field->mask & newfield.mask) != 0 && (newfield.condition.condition == PORTCOND_ALWAYS ||
+ field->condition.condition == PORTCOND_ALWAYS ||
+ condition_equal(&field->condition, &newfield.condition)))
+ {
+ /* reduce the mask of the field we found */
+ field->mask &= ~newfield.mask;
+
+ /* if the new entry fully overrides the previous one, we nuke */
+ if (INPUT_PORT_OVERRIDE_FULLY_NUKES_PREVIOUS || field->mask == 0)
+ newfield.port().fieldlist().remove(*field);
+ }
+ }
+
+ /* make a mask of just the low bit */
+ lowbit = (newfield.mask ^ (newfield.mask - 1)) & newfield.mask;
+
+ /* scan forward to find where to insert ourselves */
+ input_field_config *field;
+ for (field = newfield.port().fieldlist().first(); field != NULL; field = field->next())
+ if (field->mask > lowbit)
+ break;
+
+ /* insert it into the list */
+ newfield.port().fieldlist().insert_before(newfield, field);
+}
+
+
+/*-------------------------------------------------
+ diplocation_expand - expand a string-based
+ DIP location into a linked list of
+ descriptions
+-------------------------------------------------*/
+
+void diplocation_list_alloc(input_field_config &field, const char *location, astring &errorbuf)
+{
+ /* if nothing present, bail */
+ if (location == NULL)
+ return;
+
+ field.diploclist().reset();
+
+ /* parse the string */
+ astring name; // Don't move this variable inside the loop, lastname's lifetime depends on it being outside
+ const char *lastname = NULL;
+ const char *curentry = location;
+ int entries = 0;
+ while (*curentry != 0)
+ {
+ /* find the end of this entry */
+ const char *comma = strchr(curentry, ',');
+ if (comma == NULL)
+ comma = curentry + strlen(curentry);
+
+ /* extract it to tempbuf */
+ astring tempstr;
+ tempstr.cpy(curentry, comma - curentry);
+
+ /* first extract the switch name if present */
+ const char *number = tempstr;
+ const char *colon = strchr(tempstr, ':');
+
+ /* allocate and copy the name if it is present */
+ if (colon != NULL)
+ {
+ lastname = name.cpy(number, colon - number);
+ number = colon + 1;
+ }
+
+ /* otherwise, just copy the last name */
+ else
+ {
+ if (lastname == NULL)
+ {
+ errorbuf.catprintf("Switch location '%s' missing switch name!\n", location);
+ lastname = (char *)"UNK";
+ }
+ name.cpy(lastname);
+ }
+
+ /* if the number is preceded by a '!' it's active high */
+ bool invert = false;
+ if (*number == '!')
+ {
+ invert = true;
+ number++;
+ }
+
+ /* now scan the switch number */
+ int swnum = -1;
+ if (sscanf(number, "%d", &swnum) != 1)
+ errorbuf.catprintf("Switch location '%s' has invalid format!\n", location);
+
+ /* allocate a new entry */
+ field.diploclist().append(*global_alloc(input_field_diplocation(name, swnum, invert)));
+ entries++;
+
+ /* advance to the next item */
+ curentry = comma;
+ if (*curentry != 0)
+ curentry++;
+ }
+
+ /* then verify the number of bits in the mask matches */
+ input_port_value temp;
+ int bits;
+ for (bits = 0, temp = field.mask; temp != 0 && bits < 32; bits++)
+ temp &= temp - 1;
+ if (bits != entries)
+ errorbuf.catprintf("Switch location '%s' does not describe enough bits for mask %X\n", location, field.mask);
+}
+
+
+
+/***************************************************************************
+ TOKENIZATION HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ token_to_input_field_type - convert a string
+ token to an input field type and player
+-------------------------------------------------*/
+
+static int token_to_input_field_type(running_machine &machine, const char *string, int *player)
+{
+ input_port_private *portdata = machine.input_port_data;
+ int ipnum;
+
+ /* check for our failsafe case first */
+ if (sscanf(string, "TYPE_OTHER(%d,%d)", &ipnum, player) == 2)
+ return ipnum;
+
+ /* find the token in the list */
+ for (input_type_entry *entry = portdata->typelist.first(); entry != NULL; entry = entry->next())
+ if (entry->token != NULL && !strcmp(entry->token, string))
+ {
+ *player = entry->player;
+ return entry->type;
+ }
+
+ /* if we fail, return IPT_UNKNOWN */
+ *player = 0;
+ return IPT_UNKNOWN;
+}
+
+
+/*-------------------------------------------------
+ input_field_type_to_token - convert an input
+ field type and player to a string token
+-------------------------------------------------*/
+
+static const char *input_field_type_to_token(running_machine &machine, int type, int player)
+{
+ input_port_private *portdata = machine.input_port_data;
+ static char tempbuf[32];
+
+ /* look up the port and return the token */
+ input_type_entry *entry = portdata->type_to_entry[type][player];
+ if (entry != NULL)
+ return entry->token;
+
+ /* if that fails, carry on */
+ sprintf(tempbuf, "TYPE_OTHER(%d,%d)", type, player);
+ return tempbuf;
+}
+
+
+/*-------------------------------------------------
+ token_to_seq_type - convert a string to
+ a sequence type
+-------------------------------------------------*/
+
+static int token_to_seq_type(const char *string)
+{
+ int seqindex;
+
+ /* look up the string in the table of possible sequence types and return the index */
+ for (seqindex = 0; seqindex < ARRAY_LENGTH(seqtypestrings); seqindex++)
+ if (!mame_stricmp(string, seqtypestrings[seqindex]))
+ return seqindex;
+
+ return -1;
+}
+
+
+
+/***************************************************************************
+ SETTINGS LOAD
+***************************************************************************/
+
+/*-------------------------------------------------
+ load_config_callback - callback to extract
+ configuration data from the XML nodes
+-------------------------------------------------*/
+
+static void load_config_callback(running_machine &machine, int config_type, xml_data_node *parentnode)
+{
+ input_port_private *portdata = machine.input_port_data;
+ xml_data_node *portnode;
+ int seqtype;
+
+ /* in the completion phase, we finish the initialization with the final ports */
+ if (config_type == CONFIG_TYPE_FINAL)
+ {
+ portdata->safe_to_read = TRUE;
+ frame_update(machine);
+ }
+
+ /* early exit if no data to parse */
+ if (parentnode == NULL)
+ return;
+
+ /* iterate over all the remap nodes for controller configs only */
+ if (config_type == CONFIG_TYPE_CONTROLLER)
+ load_remap_table(machine, parentnode);
+
+ /* iterate over all the port nodes */
+ for (portnode = xml_get_sibling(parentnode->child, "port"); portnode; portnode = xml_get_sibling(portnode->next, "port"))
+ {
+ input_seq newseq[SEQ_TYPE_TOTAL], tempseq;
+ xml_data_node *seqnode;
+ int type, player;
+
+ /* get the basic port info from the attributes */
+ type = token_to_input_field_type(machine, xml_get_attribute_string(portnode, "type", ""), &player);
+
+ /* initialize sequences to invalid defaults */
+ for (seqtype = 0; seqtype < ARRAY_LENGTH(newseq); seqtype++)
+ newseq[seqtype].set(INPUT_CODE_INVALID);
+
+ /* loop over new sequences */
+ for (seqnode = xml_get_sibling(portnode->child, "newseq"); seqnode; seqnode = xml_get_sibling(seqnode->next, "newseq"))
+ {
+ /* with a valid type, parse out the new sequence */
+ seqtype = token_to_seq_type(xml_get_attribute_string(seqnode, "type", ""));
+ if (seqtype != -1 && seqnode->value != NULL)
+ {
+ if (strcmp(seqnode->value, "NONE") == 0)
+ newseq[seqtype].set();
+ else
+ machine.input().seq_from_tokens(newseq[seqtype], seqnode->value);
+ }
+ }
+
+ /* if we're loading default ports, apply to the defaults */
+ if (config_type != CONFIG_TYPE_GAME)
+ load_default_config(machine, portnode, type, player, newseq);
+ else
+ load_game_config(machine, portnode, type, player, newseq);
+ }
+
+ /* after applying the controller config, push that back into the backup, since that is */
+ /* what we will diff against */
+ if (config_type == CONFIG_TYPE_CONTROLLER)
+ for (input_type_entry *entry = portdata->typelist.first(); entry != NULL; entry = entry->next())
+ for (seqtype = 0; seqtype < ARRAY_LENGTH(entry->seq); seqtype++)
+ entry->defseq[seqtype] = entry->seq[seqtype];
+}
+
+
+/*-------------------------------------------------
+ load_remap_table - extract and apply the
+ global remapping table
+-------------------------------------------------*/
+
+static void load_remap_table(running_machine &machine, xml_data_node *parentnode)
+{
+ input_port_private *portdata = machine.input_port_data;
+ input_code *oldtable, *newtable;
+ xml_data_node *remapnode;
+ int count;
+
+ /* count items first so we can allocate */
+ count = 0;
+ for (remapnode = xml_get_sibling(parentnode->child, "remap"); remapnode != NULL; remapnode = xml_get_sibling(remapnode->next, "remap"))
+ count++;
+
+ /* if we have some, deal with them */
+ if (count > 0)
+ {
+ int remapnum;
+
+ /* allocate tables */
+ oldtable = global_alloc_array(input_code, count);
+ newtable = global_alloc_array(input_code, count);
+
+ /* build up the remap table */
+ count = 0;
+ for (remapnode = xml_get_sibling(parentnode->child, "remap"); remapnode != NULL; remapnode = xml_get_sibling(remapnode->next, "remap"))
+ {
+ input_code origcode = machine.input().code_from_token(xml_get_attribute_string(remapnode, "origcode", ""));
+ input_code newcode = machine.input().code_from_token(xml_get_attribute_string(remapnode, "newcode", ""));
+ if (origcode != INPUT_CODE_INVALID && newcode != INPUT_CODE_INVALID)
+ {
+ oldtable[count] = origcode;
+ newtable[count] = newcode;
+ count++;
+ }
+ }
+
+ /* loop over the remapping table, operating only if something was specified */
+ for (remapnum = 0; remapnum < count; remapnum++)
+ {
+ input_code oldcode = oldtable[remapnum];
+ input_code newcode = newtable[remapnum];
+
+ /* loop over all default ports, remapping the requested keys */
+ for (input_type_entry *entry = portdata->typelist.first(); entry != NULL; entry = entry->next())
+ {
+ /* remap anything in the default sequences */
+ for (int seqtype = 0; seqtype < ARRAY_LENGTH(entry->seq); seqtype++)
+ entry->seq[seqtype].replace(oldcode, newcode);
+ }
+ }
+
+ /* release the tables */
+ global_free(oldtable);
+ global_free(newtable);
+ }
+}
+
+
+/*-------------------------------------------------
+ load_default_config - apply configuration
+ data to the default mappings
+-------------------------------------------------*/
+
+static int load_default_config(running_machine &machine, xml_data_node *portnode, int type, int player, const input_seq *newseq)
+{
+ input_port_private *portdata = machine.input_port_data;
+
+ /* find a matching port in the list */
+ for (input_type_entry *entry = portdata->typelist.first(); entry != NULL; entry = entry->next())
+ if (entry->type == type && entry->player == player)
+ {
+ for (int seqtype = 0; seqtype < ARRAY_LENGTH(entry->seq); seqtype++)
+ if (newseq[seqtype][0] != INPUT_CODE_INVALID)
+ entry->seq[seqtype] = newseq[seqtype];
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/*-------------------------------------------------
+ load_game_config - apply configuration
+ data to the current set of input ports
+-------------------------------------------------*/
+
+static int load_game_config(running_machine &machine, xml_data_node *portnode, int type, int player, const input_seq *newseq)
+{
+ input_port_value mask, defvalue;
+ const input_field_config *field;
+ const input_port_config *port;
+ char tempbuffer[20];
+ const char *tag;
+
+ /* read the mask, index, and defvalue attributes */
+ tag = xml_get_attribute_string(portnode, "tag", NULL);
+ mask = xml_get_attribute_int(portnode, "mask", 0);
+ defvalue = xml_get_attribute_int(portnode, "defvalue", 0);
+
+ /* find the port we want; if no tag, search them all */
+ for (port = machine.m_portlist.first(); port != NULL; port = port->next())
+ if (tag == NULL || strcmp(get_port_tag(port, tempbuffer), tag) == 0)
+ for (field = port->first_field(); field != NULL; field = field->next())
+
+ /* find the matching mask and defvalue */
+ if (field->type == type && field->player == player &&
+ field->mask == mask && (field->defvalue & mask) == (defvalue & mask))
+ {
+ const char *revstring;
+ int seqtype;
+
+ /* if a sequence was specified, copy it in */
+ for (seqtype = 0; seqtype < ARRAY_LENGTH(field->state->seq); seqtype++)
+ if (newseq[seqtype][0] != INPUT_CODE_INVALID)
+ field->state->seq[seqtype] = newseq[seqtype];
+
+ /* for non-analog fields, fetch the value */
+ if (field->state->analog == NULL)
+ field->state->value = xml_get_attribute_int(portnode, "value", field->defvalue);
+
+ /* for analog fields, fetch configurable analog attributes */
+ else
+ {
+ /* get base attributes */
+ field->state->analog->delta = xml_get_attribute_int(portnode, "keydelta", field->delta);
+ field->state->analog->centerdelta = xml_get_attribute_int(portnode, "centerdelta", field->centerdelta);
+ field->state->analog->sensitivity = xml_get_attribute_int(portnode, "sensitivity", field->sensitivity);
+
+ /* fetch yes/no for reverse setting */
+ revstring = xml_get_attribute_string(portnode, "reverse", NULL);
+ if (revstring != NULL)
+ field->state->analog->reverse = (strcmp(revstring, "yes") == 0);
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+/***************************************************************************
+ SETTINGS SAVE
+***************************************************************************/
+
+/*-------------------------------------------------
+ save_config_callback - config callback for
+ saving input port configuration
+-------------------------------------------------*/
+
+static void save_config_callback(running_machine &machine, int config_type, xml_data_node *parentnode)
+{
+ /* if no parentnode, ignore */
+ if (parentnode == NULL)
+ return;
+
+ /* default ports save differently */
+ if (config_type == CONFIG_TYPE_DEFAULT)
+ save_default_inputs(machine, parentnode);
+ else
+ save_game_inputs(machine, parentnode);
+}
+
+
+/*-------------------------------------------------
+ save_sequence - add a node for an input
+ sequence
+-------------------------------------------------*/
+
+static void save_sequence(running_machine &machine, xml_data_node *parentnode, int type, int porttype, const input_seq &seq)
+{
+ astring seqstring;
+ xml_data_node *seqnode;
+
+ /* get the string for the sequence */
+ if (seq.length() == 0)
+ seqstring.cpy("NONE");
+ else
+ machine.input().seq_to_tokens(seqstring, seq);
+
+ /* add the new node */
+ seqnode = xml_add_child(parentnode, "newseq", seqstring);
+ if (seqnode != NULL)
+ xml_set_attribute(seqnode, "type", seqtypestrings[type]);
+}
+
+
+/*-------------------------------------------------
+ save_this_input_field_type - determine if the given
+ port type is worth saving
+-------------------------------------------------*/
+
+static int save_this_input_field_type(int type)
+{
+ switch (type)
+ {
+ case IPT_UNUSED:
+ case IPT_END:
+ case IPT_PORT:
+ case IPT_VBLANK:
+ case IPT_UNKNOWN:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/*-------------------------------------------------
+ save_default_inputs - add nodes for any default
+ mappings that have changed
+-------------------------------------------------*/
+
+static void save_default_inputs(running_machine &machine, xml_data_node *parentnode)
+{
+ input_port_private *portdata = machine.input_port_data;
+ input_type_entry *entry;
+
+ /* iterate over ports */
+ for (entry = portdata->typelist.first(); entry != NULL; entry = entry->next())
+ {
+ /* only save if this port is a type we save */
+ if (save_this_input_field_type(entry->type))
+ {
+ int seqtype;
+
+ /* see if any of the sequences have changed */
+ for (seqtype = 0; seqtype < ARRAY_LENGTH(entry->seq); seqtype++)
+ if (entry->seq[seqtype] != entry->defseq[seqtype])
+ break;
+
+ /* if so, we need to add a node */
+ if (seqtype < ARRAY_LENGTH(entry->seq))
+ {
+ /* add a new port node */
+ xml_data_node *portnode = xml_add_child(parentnode, "port", NULL);
+ if (portnode != NULL)
+ {
+ /* add the port information and attributes */
+ xml_set_attribute(portnode, "type", input_field_type_to_token(machine, entry->type, entry->player));
+
+ /* add only the sequences that have changed from the defaults */
+ for (seqtype = 0; seqtype < ARRAY_LENGTH(entry->seq); seqtype++)
+ if (entry->seq[seqtype] != entry->defseq[seqtype])
+ save_sequence(machine, portnode, seqtype, entry->type, entry->seq[seqtype]);
+ }
+ }
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ save_game_inputs - add nodes for any game
+ mappings that have changed
+-------------------------------------------------*/
+
+static void save_game_inputs(running_machine &machine, xml_data_node *parentnode)
+{
+ const input_field_config *field;
+ const input_port_config *port;
+
+ /* iterate over ports */
+ for (port = machine.m_portlist.first(); port != NULL; port = port->next())
+ for (field = port->first_field(); field != NULL; field = field->next())
+ if (save_this_input_field_type(field->type))
+ {
+ bool changed = false;
+ int seqtype;
+
+ /* determine if we changed */
+ for (seqtype = 0; seqtype < ARRAY_LENGTH(field->state->seq); seqtype++)
+ changed |= (field->state->seq[seqtype] != field->seq[seqtype]);
+
+ /* non-analog changes */
+ if (field->state->analog == NULL)
+ changed |= ((field->state->value & field->mask) != (field->defvalue & field->mask));
+
+ /* analog changes */
+ else
+ {
+ changed |= (field->state->analog->delta != field->delta);
+ changed |= (field->state->analog->centerdelta != field->centerdelta);
+ changed |= (field->state->analog->sensitivity != field->sensitivity);
+ changed |= (field->state->analog->reverse != ((field->flags & ANALOG_FLAG_REVERSE) != 0));
+ }
+
+ /* if we did change, add a new node */
+ if (changed)
+ {
+ /* add a new port node */
+ xml_data_node *portnode = xml_add_child(parentnode, "port", NULL);
+ if (portnode != NULL)
+ {
+ char tempbuffer[20];
+
+ /* add the identifying information and attributes */
+ xml_set_attribute(portnode, "tag", get_port_tag(port, tempbuffer));
+ xml_set_attribute(portnode, "type", input_field_type_to_token(machine, field->type, field->player));
+ xml_set_attribute_int(portnode, "mask", field->mask);
+ xml_set_attribute_int(portnode, "defvalue", field->defvalue & field->mask);
+
+ /* add sequences if changed */
+ for (seqtype = 0; seqtype < ARRAY_LENGTH(field->state->seq); seqtype++)
+ if (field->state->seq[seqtype] != field->seq[seqtype])
+ save_sequence(machine, portnode, seqtype, field->type, field->state->seq[seqtype]);
+
+ /* write out non-analog changes */
+ if (field->state->analog == NULL)
+ {
+ if ((field->state->value & field->mask) != (field->defvalue & field->mask))
+ xml_set_attribute_int(portnode, "value", field->state->value & field->mask);
+ }
+
+ /* write out analog changes */
+ else
+ {
+ if (field->state->analog->delta != field->delta)
+ xml_set_attribute_int(portnode, "keydelta", field->state->analog->delta);
+ if (field->state->analog->centerdelta != field->centerdelta)
+ xml_set_attribute_int(portnode, "centerdelta", field->state->analog->centerdelta);
+ if (field->state->analog->sensitivity != field->sensitivity)
+ xml_set_attribute_int(portnode, "sensitivity", field->state->analog->sensitivity);
+ if (field->state->analog->reverse != ((field->flags & ANALOG_FLAG_REVERSE) != 0))
+ xml_set_attribute(portnode, "reverse", field->state->analog->reverse ? "yes" : "no");
+ }
+ }
+ }
+ }
+}
+
+
+
+/***************************************************************************
+ INPUT PLAYBACK
+***************************************************************************/
+
+/*-------------------------------------------------
+ playback_read_uint8 - read an 8-bit value
+ from the playback file
+-------------------------------------------------*/
+
+static UINT8 playback_read_uint8(running_machine &machine)
+{
+ input_port_private *portdata = machine.input_port_data;
+ UINT8 result;
+
+ /* protect against NULL handles if previous reads fail */
+ if (portdata->playback_file == NULL)
+ return 0;
+
+ /* read the value; if we fail, end playback */
+ if (portdata->playback_file->read(&result, sizeof(result)) != sizeof(result))
+ {
+ playback_end(machine, "End of file");
+ return 0;
+ }
+
+ /* return the appropriate value */
+ return result;
+}
+
+
+/*-------------------------------------------------
+ playback_read_uint32 - read a 32-bit value
+ from the playback file
+-------------------------------------------------*/
+
+static UINT32 playback_read_uint32(running_machine &machine)
+{
+ input_port_private *portdata = machine.input_port_data;
+ UINT32 result;
+
+ /* protect against NULL handles if previous reads fail */
+ if (portdata->playback_file == NULL)
+ return 0;
+
+ /* read the value; if we fail, end playback */
+ if (portdata->playback_file->read(&result, sizeof(result)) != sizeof(result))
+ {
+ playback_end(machine, "End of file");
+ return 0;
+ }
+
+ /* return the appropriate value */
+ return LITTLE_ENDIANIZE_INT32(result);
+}
+
+
+/*-------------------------------------------------
+ playback_read_uint64 - read a 64-bit value
+ from the playback file
+-------------------------------------------------*/
+
+static UINT64 playback_read_uint64(running_machine &machine)
+{
+ input_port_private *portdata = machine.input_port_data;
+ UINT64 result;
+
+ /* protect against NULL handles if previous reads fail */
+ if (portdata->playback_file == NULL)
+ return 0;
+
+ /* read the value; if we fail, end playback */
+ if (portdata->playback_file->read(&result, sizeof(result)) != sizeof(result))
+ {
+ playback_end(machine, "End of file");
+ return 0;
+ }
+
+ /* return the appropriate value */
+ return LITTLE_ENDIANIZE_INT64(result);
+}
+
+
+/*-------------------------------------------------
+ playback_init - initialize INP playback
+-------------------------------------------------*/
+
+static time_t playback_init(running_machine &machine)
+{
+ const char *filename = machine.options().playback();
+ input_port_private *portdata = machine.input_port_data;
+ UINT8 header[INP_HEADER_SIZE];
+ time_t basetime;
+
+ /* if no file, nothing to do */
+ if (filename[0] == 0)
+ return 0;
+
+ /* open the playback file */
+ portdata->playback_file = auto_alloc(machine, emu_file(machine.options().input_directory(), OPEN_FLAG_READ));
+ file_error filerr = portdata->playback_file->open(filename);
+ assert_always(filerr == FILERR_NONE, "Failed to open file for playback");
+
+ /* read the header and verify that it is a modern version; if not, print an error */
+ if (portdata->playback_file->read(header, sizeof(header)) != sizeof(header))
+ fatalerror("Input file is corrupt or invalid (missing header)");
+ if (memcmp(header, "MAMEINP\0", 8) != 0)
+ fatalerror("Input file invalid or in an older, unsupported format");
+ if (header[0x10] != INP_HEADER_MAJVERSION)
+ fatalerror("Input file format version mismatch");
+
+ /* output info to console */
+ mame_printf_info("Input file: %s\n", filename);
+ mame_printf_info("INP version %d.%d\n", header[0x10], header[0x11]);
+ basetime = header[0x08] | (header[0x09] << 8) | (header[0x0a] << 16) | (header[0x0b] << 24) |
+ ((UINT64)header[0x0c] << 32) | ((UINT64)header[0x0d] << 40) | ((UINT64)header[0x0e] << 48) | ((UINT64)header[0x0f] << 56);
+ mame_printf_info("Created %s", ctime(&basetime));
+ mame_printf_info("Recorded using %s\n", header + 0x20);
+
+ /* verify the header against the current game */
+ if (memcmp(machine.system().name, header + 0x14, strlen(machine.system().name) + 1) != 0)
+ mame_printf_info("Input file is for " GAMENOUN " '%s', not for current " GAMENOUN " '%s'\n", header + 0x14, machine.system().name);
+
+ /* enable compression */
+ portdata->playback_file->compress(FCOMPRESS_MEDIUM);
+
+ return basetime;
+}
+
+
+/*-------------------------------------------------
+ playback_end - end INP playback
+-------------------------------------------------*/
+
+static void playback_end(running_machine &machine, const char *message)
+{
+ input_port_private *portdata = machine.input_port_data;
+
+ /* only applies if we have a live file */
+ if (portdata->playback_file != NULL)
+ {
+ /* close the file */
+ auto_free(machine, portdata->playback_file);
+ portdata->playback_file = NULL;
+
+ /* pop a message */
+ if (message != NULL)
+ popmessage("Playback Ended\nReason: %s", message);
+
+ /* display speed stats */
+ portdata->playback_accumulated_speed /= portdata->playback_accumulated_frames;
+ mame_printf_info("Total playback frames: %d\n", (UINT32)portdata->playback_accumulated_frames);
+ mame_printf_info("Average recorded speed: %d%%\n", (UINT32)((portdata->playback_accumulated_speed * 200 + 1) >> 21));
+ }
+}
+
+
+/*-------------------------------------------------
+ playback_frame - start of frame callback for
+ playback
+-------------------------------------------------*/
+
+static void playback_frame(running_machine &machine, attotime curtime)
+{
+ input_port_private *portdata = machine.input_port_data;
+
+ /* if playing back, fetch the information and verify */
+ if (portdata->playback_file != NULL)
+ {
+ attotime readtime;
+
+ /* first the absolute time */
+ readtime.seconds = playback_read_uint32(machine);
+ readtime.attoseconds = playback_read_uint64(machine);
+ if (readtime != curtime)
+ playback_end(machine, "Out of sync");
+
+ /* then the speed */
+ portdata->playback_accumulated_speed += playback_read_uint32(machine);
+ portdata->playback_accumulated_frames++;
+ }
+}
+
+
+/*-------------------------------------------------
+ playback_port - per-port callback for playback
+-------------------------------------------------*/
+
+static void playback_port(const input_port_config *port)
+{
+ input_port_private *portdata = port->machine().input_port_data;
+
+ /* if playing back, fetch information about this port */
+ if (portdata->playback_file != NULL)
+ {
+ analog_field_state *analog;
+
+ /* read the default value and the digital state */
+ port->state->defvalue = playback_read_uint32(port->machine());
+ port->state->digital = playback_read_uint32(port->machine());
+
+ /* loop over analog ports and save their data */
+ for (analog = port->state->analoglist; analog != NULL; analog = analog->next)
+ {
+ /* read current and previous values */
+ analog->accum = playback_read_uint32(port->machine());
+ analog->previous = playback_read_uint32(port->machine());
+
+ /* read configuration information */
+ analog->sensitivity = playback_read_uint32(port->machine());
+ analog->reverse = playback_read_uint8(port->machine());
+ }
+ }
+}
+
+
+
+/***************************************************************************
+ INPUT RECORDING
+***************************************************************************/
+
+/*-------------------------------------------------
+ record_write_uint8 - write an 8-bit value
+ to the record file
+-------------------------------------------------*/
+
+static void record_write_uint8(running_machine &machine, UINT8 data)
+{
+ input_port_private *portdata = machine.input_port_data;
+ UINT8 result = data;
+
+ /* protect against NULL handles if previous reads fail */
+ if (portdata->record_file == NULL)
+ return;
+
+ /* read the value; if we fail, end playback */
+ if (portdata->record_file->write(&result, sizeof(result)) != sizeof(result))
+ record_end(machine, "Out of space");
+}
+
+
+/*-------------------------------------------------
+ record_write_uint32 - write a 32-bit value
+ to the record file
+-------------------------------------------------*/
+
+static void record_write_uint32(running_machine &machine, UINT32 data)
+{
+ input_port_private *portdata = machine.input_port_data;
+ UINT32 result = LITTLE_ENDIANIZE_INT32(data);
+
+ /* protect against NULL handles if previous reads fail */
+ if (portdata->record_file == NULL)
+ return;
+
+ /* read the value; if we fail, end playback */
+ if (portdata->record_file->write(&result, sizeof(result)) != sizeof(result))
+ record_end(machine, "Out of space");
+}
+
+
+/*-------------------------------------------------
+ record_write_uint64 - write a 64-bit value
+ to the record file
+-------------------------------------------------*/
+
+static void record_write_uint64(running_machine &machine, UINT64 data)
+{
+ input_port_private *portdata = machine.input_port_data;
+ UINT64 result = LITTLE_ENDIANIZE_INT64(data);
+
+ /* protect against NULL handles if previous reads fail */
+ if (portdata->record_file == NULL)
+ return;
+
+ /* read the value; if we fail, end playback */
+ if (portdata->record_file->write(&result, sizeof(result)) != sizeof(result))
+ record_end(machine, "Out of space");
+}
+
+
+/*-------------------------------------------------
+ record_init - initialize INP recording
+-------------------------------------------------*/
+
+static void record_init(running_machine &machine)
+{
+ const char *filename = machine.options().record();
+ input_port_private *portdata = machine.input_port_data;
+ UINT8 header[INP_HEADER_SIZE];
+ system_time systime;
+
+ /* if no file, nothing to do */
+ if (filename[0] == 0)
+ return;
+
+ /* open the record file */
+ portdata->record_file = auto_alloc(machine, emu_file(machine.options().input_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS));
+ file_error filerr = portdata->record_file->open(filename);
+ assert_always(filerr == FILERR_NONE, "Failed to open file for recording");
+
+ /* get the base time */
+ machine.base_datetime(systime);
+
+ /* fill in the header */
+ memset(header, 0, sizeof(header));
+ memcpy(header, "MAMEINP\0", 8);
+ header[0x08] = systime.time >> 0;
+ header[0x09] = systime.time >> 8;
+ header[0x0a] = systime.time >> 16;
+ header[0x0b] = systime.time >> 24;
+ header[0x0c] = systime.time >> 32;
+ header[0x0d] = systime.time >> 40;
+ header[0x0e] = systime.time >> 48;
+ header[0x0f] = systime.time >> 56;
+ header[0x10] = INP_HEADER_MAJVERSION;
+ header[0x11] = INP_HEADER_MINVERSION;
+ strcpy((char *)header + 0x14, machine.system().name);
+ sprintf((char *)header + 0x20, APPNAME " %s", build_version);
+
+ /* write it */
+ portdata->record_file->write(header, sizeof(header));
+
+ /* enable compression */
+ portdata->record_file->compress(FCOMPRESS_MEDIUM);
+}
+
+
+/*-------------------------------------------------
+ record_end - end INP recording
+-------------------------------------------------*/
+
+static void record_end(running_machine &machine, const char *message)
+{
+ input_port_private *portdata = machine.input_port_data;
+
+ /* only applies if we have a live file */
+ if (portdata->record_file != NULL)
+ {
+ /* close the file */
+ auto_free(machine, portdata->record_file);
+ portdata->record_file = NULL;
+
+ /* pop a message */
+ if (message != NULL)
+ popmessage("Recording Ended\nReason: %s", message);
+ }
+}
+
+
+/*-------------------------------------------------
+ record_frame - start of frame callback for
+ recording
+-------------------------------------------------*/
+
+static void record_frame(running_machine &machine, attotime curtime)
+{
+ input_port_private *portdata = machine.input_port_data;
+
+ /* if recording, record information about the current frame */
+ if (portdata->record_file != NULL)
+ {
+ /* first the absolute time */
+ record_write_uint32(machine, curtime.seconds);
+ record_write_uint64(machine, curtime.attoseconds);
+
+ /* then the current speed */
+ record_write_uint32(machine, machine.video().speed_percent() * (double)(1 << 20));
+ }
+}
+
+
+/*-------------------------------------------------
+ record_port - per-port callback for record
+-------------------------------------------------*/
+
+static void record_port(const input_port_config *port)
+{
+ input_port_private *portdata = port->machine().input_port_data;
+
+ /* if recording, store information about this port */
+ if (portdata->record_file != NULL)
+ {
+ analog_field_state *analog;
+
+ /* store the default value and digital state */
+ record_write_uint32(port->machine(), port->state->defvalue);
+ record_write_uint32(port->machine(), port->state->digital);
+
+ /* loop over analog ports and save their data */
+ for (analog = port->state->analoglist; analog != NULL; analog = analog->next)
+ {
+ /* store current and previous values */
+ record_write_uint32(port->machine(), analog->accum);
+ record_write_uint32(port->machine(), analog->previous);
+
+ /* store configuration information */
+ record_write_uint32(port->machine(), analog->sensitivity);
+ record_write_uint8(port->machine(), analog->reverse);
+ }
+ }
+}
+
+int input_machine_has_keyboard(running_machine &machine)
+{
+ int have_keyboard = FALSE;
+ const input_field_config *field;
+ const input_port_config *port;
+ for (port = machine.m_portlist.first(); port != NULL; port = port->next())
+ {
+ for (field = port->first_field(); field != NULL; field = field->next())
+ {
+ // if we are at init, check IPT_KEYBOARD for inputx_init
+ if (!port->machine().input_port_data->safe_to_read && field->type == IPT_KEYBOARD)
+ {
+ have_keyboard = TRUE;
+ break;
+ }
+
+ // else, check if there is a keyboard and if such a keyboard is enabled
+ if (field->type == IPT_KEYBOARD && input_condition_true(field->machine(), &field->condition, field->port().owner()))
+ {
+ have_keyboard = TRUE;
+ break;
+ }
+ }
+ }
+ return have_keyboard;
+}
+
+/***************************************************************************
+ CODE ASSEMBLING
+***************************************************************************/
+
+/*-------------------------------------------------
+ code_point_string - obtain a string representation of a
+ given code; used for logging and debugging
+-------------------------------------------------*/
+
+static const char *code_point_string(running_machine &machine, unicode_char ch)
+{
+ static char buf[16];
+ const char *result = buf;
+
+ switch(ch)
+ {
+ /* check some magic values */
+ case '\0': strcpy(buf, "\\0"); break;
+ case '\r': strcpy(buf, "\\r"); break;
+ case '\n': strcpy(buf, "\\n"); break;
+ case '\t': strcpy(buf, "\\t"); break;
+
+ default:
+ if ((ch >= 32) && (ch < 128))
+ {
+ /* seven bit ASCII is easy */
+ buf[0] = (char) ch;
+ buf[1] = '\0';
+ }
+ else if (ch >= UCHAR_MAMEKEY_BEGIN)
+ {
+ /* try to obtain a codename with code_name(); this can result in an empty string */
+ input_code code(DEVICE_CLASS_KEYBOARD, 0, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, input_item_id(ch - UCHAR_MAMEKEY_BEGIN));
+ astring tempstr;
+ snprintf(buf, ARRAY_LENGTH(buf), "%s", machine.input().code_name(tempstr, code));
+ }
+ else
+ {
+ /* empty string; resolve later */
+ buf[0] = '\0';
+ }
+
+ /* did we fail to resolve? if so, we have a last resort */
+ if (buf[0] == '\0')
+ snprintf(buf, ARRAY_LENGTH(buf), "U+%04X", (unsigned) ch);
+ break;
+ }
+ return result;
+}
+
+
+/*-------------------------------------------------
+ scan_keys - scans through input ports and
+ sets up natural keyboard input mapping
+-------------------------------------------------*/
+
+static int scan_keys(running_machine &machine, const input_port_config *portconfig, inputx_code *codes, const input_port_config * *ports, const input_field_config * *shift_ports, int keys, int shift)
+{
+ int code_count = 0;
+ const input_port_config *port;
+ const input_field_config *field;
+ unicode_char code;
+
+ assert(keys < NUM_SIMUL_KEYS);
+
+ for (port = portconfig; port != NULL; port = port->next())
+ {
+ for (field = port->first_field(); field != NULL; field = field->next())
+ {
+ if (field->type == IPT_KEYBOARD)
+ {
+ code = get_keyboard_code(field, shift);
+ if (code != 0)
+ {
+ /* is this a shifter key? */
+ if ((code >= UCHAR_SHIFT_BEGIN) && (code <= UCHAR_SHIFT_END))
+ {
+ shift_ports[keys] = field;
+ code_count += scan_keys(machine,
+ portconfig,
+ codes ? &codes[code_count] : NULL,
+ ports,
+ shift_ports,
+ keys+1,
+ code - UCHAR_SHIFT_1 + 1);
+ }
+ else
+ {
+ /* not a shifter key; record normally */
+ if (codes)
+ {
+ /* if we have a destination, record the codes used here */
+ memcpy((void *) codes[code_count].field, shift_ports, sizeof(shift_ports[0]) * keys);
+ codes[code_count].ch = code;
+ codes[code_count].field[keys] = field;
+ }
+
+ /* increment the count */
+ code_count++;
+
+ if (LOG_INPUTX)
+ logerror("inputx: code=%i (%s) port=%p field->name='%s'\n", (int) code, code_point_string(machine, code), port, field->name);
+ }
+ }
+ }
+ }
+ }
+ return code_count;
+}
+
+
+
+/*-------------------------------------------------
+ build_codes - given an input port table, create
+ a input code table useful for mapping unicode
+ chars
+-------------------------------------------------*/
+
+static inputx_code *build_codes(running_machine &machine, const input_port_config *portconfig)
+{
+ inputx_code *codes = NULL;
+ const input_port_config *ports[NUM_SIMUL_KEYS];
+ const input_field_config *fields[NUM_SIMUL_KEYS];
+ int code_count;
+
+ /* first count the number of codes */
+ code_count = scan_keys(machine, portconfig, NULL, ports, fields, 0, 0);
+ if (code_count > 0)
+ {
+ /* allocate the codes */
+ codes = auto_alloc_array_clear(machine, inputx_code, code_count + 1);
+
+ /* and populate them */
+ scan_keys(machine, portconfig, codes, ports, fields, 0, 0);
+ }
+ return codes;
+}
+
+
+
+/***************************************************************************
+ VALIDITY CHECKS
+***************************************************************************/
+
+/*-------------------------------------------------
+ validate_natural_keyboard_statics -
+ validates natural keyboard static data
+-------------------------------------------------*/
+
+int validate_natural_keyboard_statics(void)
+{
+ int i;
+ int error = FALSE;
+ unicode_char last_char = 0;
+ const char_info *ci;
+
+ /* check to make sure that charinfo is in order */
+ for (i = 0; i < ARRAY_LENGTH(charinfo); i++)
+ {
+ if (last_char >= charinfo[i].ch)
+ {
+ mame_printf_error("inputx: charinfo is out of order; 0x%08x should be higher than 0x%08x\n", charinfo[i].ch, last_char);
+ error = TRUE;
+ }
+ last_char = charinfo[i].ch;
+ }
+
+ /* check to make sure that I can look up everything on alternate_charmap */
+ for (i = 0; i < ARRAY_LENGTH(charinfo); i++)
+ {
+ ci = find_charinfo(charinfo[i].ch);
+ if (ci != &charinfo[i])
+ {
+ mame_printf_error("inputx: expected find_charinfo(0x%08x) to work properly\n", charinfo[i].ch);
+ error = TRUE;
+ }
+ }
+ return error;
+}
+
+
+
+/***************************************************************************
+ CORE IMPLEMENTATION
+***************************************************************************/
+
+static void clear_keybuffer(running_machine &machine)
+{
+ input_port_private *portdata = machine.input_port_data;
+ portdata->keybuffer = NULL;
+ portdata->queue_chars = NULL;
+ portdata->codes = NULL;
+}
+
+
+
+static void setup_keybuffer(running_machine &machine)
+{
+ input_port_private *portdata = machine.input_port_data;
+ portdata->inputx_timer = machine.scheduler().timer_alloc(FUNC(inputx_timerproc));
+ portdata->keybuffer = auto_alloc_clear(machine, key_buffer);
+ machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(clear_keybuffer), &machine));
+}
+
+
+
+void inputx_init(running_machine &machine)
+{
+ input_port_private *portdata = machine.input_port_data;
+ portdata->codes = NULL;
+ portdata->inputx_timer = NULL;
+ portdata->queue_chars = NULL;
+ portdata->accept_char = NULL;
+ portdata->charqueue_empty = NULL;
+ portdata->keybuffer = NULL;
+
+ if (machine.debug_flags & DEBUG_FLAG_ENABLED)
+ {
+ debug_console_register_command(machine, "input", CMDFLAG_NONE, 0, 1, 1, execute_input);
+ debug_console_register_command(machine, "dumpkbd", CMDFLAG_NONE, 0, 0, 1, execute_dumpkbd);
+ }
+
+ /* posting keys directly only makes sense for a computer */
+ if (input_machine_has_keyboard(machine))
+ {
+ portdata->codes = build_codes(machine, machine.m_portlist.first());
+ setup_keybuffer(machine);
+ }
+}
+
+
+
+void inputx_setup_natural_keyboard(
+ running_machine &machine,
+ int (*queue_chars)(running_machine &machine, const unicode_char *text, size_t text_len),
+ int (*accept_char)(running_machine &machine, unicode_char ch),
+ int (*charqueue_empty)(running_machine &machine))
+{
+ input_port_private *portdata = machine.input_port_data;
+ portdata->queue_chars = queue_chars;
+ portdata->accept_char = accept_char;
+ portdata->charqueue_empty = charqueue_empty;
+}
+
+int inputx_can_post(running_machine &machine)
+{
+ input_port_private *portdata = machine.input_port_data;
+ return portdata->queue_chars || portdata->codes;
+}
+
+
+static int can_post_key_directly(running_machine &machine, unicode_char ch)
+{
+ input_port_private *portdata = machine.input_port_data;
+ int rc = FALSE;
+ const inputx_code *code;
+
+ if (portdata->queue_chars)
+ {
+ rc = portdata->accept_char ? (*portdata->accept_char)(machine, ch) : TRUE;
+ }
+ else
+ {
+ code = find_code(portdata->codes, ch);
+ if (code)
+ rc = code->field[0] != NULL;
+ }
+ return rc;
+}
+
+
+
+static int can_post_key_alternate(running_machine &machine, unicode_char ch)
+{
+ const char *s;
+ const char_info *ci;
+ unicode_char uchar;
+ int rc;
+
+ ci = find_charinfo(ch);
+ s = ci ? ci->alternate : NULL;
+ if (!s)
+ return 0;
+
+ while(*s)
+ {
+ rc = uchar_from_utf8(&uchar, s, strlen(s));
+ if (rc <= 0)
+ return 0;
+ if (!can_post_key_directly(machine, uchar))
+ return 0;
+ s += rc;
+ }
+ return 1;
+}
+
+static attotime choose_delay(input_port_private *portdata, unicode_char ch)
+{
+ if (portdata->current_rate != attotime::zero)
+ return portdata->current_rate;
+
+ attotime delay = attotime::zero;
+ if (portdata->queue_chars)
+ {
+ /* systems with queue_chars can afford a much smaller delay */
+ delay = attotime::from_msec(10);
+ }
+ else
+ {
+ switch(ch) {
+ case '\r':
+ delay = attotime::from_msec(200);
+ break;
+
+ default:
+ delay = attotime::from_msec(50);
+ break;
+ }
+ }
+ return delay;
+}
+
+
+
+static void internal_post_key(running_machine &machine, unicode_char ch)
+{
+ input_port_private *portdata = machine.input_port_data;
+ key_buffer *keybuf;
+
+ keybuf = get_buffer(machine);
+
+ /* need to start up the timer? */
+ if (keybuf->begin_pos == keybuf->end_pos)
+ {
+ portdata->inputx_timer->adjust(choose_delay(portdata, ch));
+ keybuf->status_keydown = 0;
+ }
+
+ keybuf->buffer[keybuf->end_pos++] = ch;
+ keybuf->end_pos %= ARRAY_LENGTH(keybuf->buffer);
+}
+
+
+
+static int buffer_full(running_machine &machine)
+{
+ key_buffer *keybuf;
+ keybuf = get_buffer(machine);
+ return ((keybuf->end_pos + 1) % ARRAY_LENGTH(keybuf->buffer)) == keybuf->begin_pos;
+}
+
+
+
+static void inputx_postn_rate(running_machine &machine, const unicode_char *text, size_t text_len, attotime rate)
+{
+ input_port_private *portdata = machine.input_port_data;
+ int last_cr = 0;
+ unicode_char ch;
+ const char *s;
+ const char_info *ci;
+ const inputx_code *code;
+
+ portdata->current_rate = rate;
+
+ if (inputx_can_post(machine))
+ {
+ while((text_len > 0) && !buffer_full(machine))
+ {
+ ch = *(text++);
+ text_len--;
+
+ /* change all eolns to '\r' */
+ if ((ch != '\n') || !last_cr)
+ {
+ if (ch == '\n')
+ ch = '\r';
+ else
+ last_cr = (ch == '\r');
+
+ if (LOG_INPUTX)
+ {
+ code = find_code(portdata->codes, ch);
+ logerror("inputx_postn(): code=%i (%s) field->name='%s'\n", (int) ch, code_point_string(machine, ch), (code && code->field[0]) ? code->field[0]->name : "<null>");
+ }
+
+ if (can_post_key_directly(machine, ch))
+ {
+ /* we can post this key in the queue directly */
+ internal_post_key(machine, ch);
+ }
+ else if (can_post_key_alternate(machine, ch))
+ {
+ /* we can post this key with an alternate representation */
+ ci = find_charinfo(ch);
+ assert(ci && ci->alternate);
+ s = ci->alternate;
+ while(*s)
+ {
+ s += uchar_from_utf8(&ch, s, strlen(s));
+ internal_post_key(machine, ch);
+ }
+ }
+ }
+ else
+ {
+ last_cr = 0;
+ }
+ }
+ }
+}
+
+
+
+static TIMER_CALLBACK(inputx_timerproc)
+{
+ input_port_private *portdata = machine.input_port_data;
+ key_buffer *keybuf;
+ attotime delay;
+
+ keybuf = get_buffer(machine);
+
+ if (portdata->queue_chars)
+ {
+ /* the driver has a queue_chars handler */
+ while((keybuf->begin_pos != keybuf->end_pos) && (*portdata->queue_chars)(machine, &keybuf->buffer[keybuf->begin_pos], 1))
+ {
+ keybuf->begin_pos++;
+ keybuf->begin_pos %= ARRAY_LENGTH(keybuf->buffer);
+
+ if (portdata->current_rate != attotime::zero)
+ break;
+ }
+ }
+ else
+ {
+ /* the driver does not have a queue_chars handler */
+ if (keybuf->status_keydown)
+ {
+ keybuf->status_keydown = FALSE;
+ keybuf->begin_pos++;
+ keybuf->begin_pos %= ARRAY_LENGTH(keybuf->buffer);
+ }
+ else
+ {
+ keybuf->status_keydown = TRUE;
+ }
+ }
+
+ /* need to make sure timerproc is called again if buffer not empty */
+ if (keybuf->begin_pos != keybuf->end_pos)
+ {
+ delay = choose_delay(portdata, keybuf->buffer[keybuf->begin_pos]);
+ portdata->inputx_timer->adjust(delay);
+ }
+}
+
+int inputx_is_posting(running_machine &machine)
+{
+ input_port_private *portdata = machine.input_port_data;
+ const key_buffer *keybuf;
+ keybuf = get_buffer(machine);
+ return (keybuf->begin_pos != keybuf->end_pos) || (portdata->charqueue_empty && !(*portdata->charqueue_empty)(machine));
+}
+
+/***************************************************************************
+
+ Coded input
+
+***************************************************************************/
+static void inputx_postc_rate(running_machine &machine, unicode_char ch, attotime rate);
+
+static void inputx_postn_coded_rate(running_machine &machine, const char *text, size_t text_len, attotime rate)
+{
+ size_t i, j, key_len, increment;
+ unicode_char ch;
+
+ static const struct
+ {
+ const char *key;
+ unicode_char code;
+ } codes[] =
+ {
+ { "BACKSPACE", 8 },
+ { "BS", 8 },
+ { "BKSP", 8 },
+ { "DEL", UCHAR_MAMEKEY(DEL) },
+ { "DELETE", UCHAR_MAMEKEY(DEL) },
+ { "END", UCHAR_MAMEKEY(END) },
+ { "ENTER", 13 },
+ { "ESC", '\033' },
+ { "HOME", UCHAR_MAMEKEY(HOME) },
+ { "INS", UCHAR_MAMEKEY(INSERT) },
+ { "INSERT", UCHAR_MAMEKEY(INSERT) },
+ { "PGDN", UCHAR_MAMEKEY(PGDN) },
+ { "PGUP", UCHAR_MAMEKEY(PGUP) },
+ { "SPACE", 32 },
+ { "TAB", 9 },
+ { "F1", UCHAR_MAMEKEY(F1) },
+ { "F2", UCHAR_MAMEKEY(F2) },
+ { "F3", UCHAR_MAMEKEY(F3) },
+ { "F4", UCHAR_MAMEKEY(F4) },
+ { "F5", UCHAR_MAMEKEY(F5) },
+ { "F6", UCHAR_MAMEKEY(F6) },
+ { "F7", UCHAR_MAMEKEY(F7) },
+ { "F8", UCHAR_MAMEKEY(F8) },
+ { "F9", UCHAR_MAMEKEY(F9) },
+ { "F10", UCHAR_MAMEKEY(F10) },
+ { "F11", UCHAR_MAMEKEY(F11) },
+ { "F12", UCHAR_MAMEKEY(F12) },
+ { "QUOTE", '\"' }
+ };
+
+ i = 0;
+ while(i < text_len)
+ {
+ ch = text[i];
+ increment = 1;
+
+ if (ch == '{')
+ {
+ for (j = 0; j < ARRAY_LENGTH(codes); j++)
+ {
+ key_len = strlen(codes[j].key);
+ if (i + key_len + 2 <= text_len)
+ {
+ if (!memcmp(codes[j].key, &text[i + 1], key_len) && (text[i + key_len + 1] == '}'))
+ {
+ ch = codes[j].code;
+ increment = key_len + 2;
+ }
+ }
+ }
+ }
+
+ if (ch)
+ inputx_postc_rate(machine, ch, rate);
+ i += increment;
+ }
+}
+
+
+
+/***************************************************************************
+
+ Alternative calls
+
+***************************************************************************/
+
+static void inputx_postc_rate(running_machine &machine, unicode_char ch, attotime rate)
+{
+ inputx_postn_rate(machine, &ch, 1, rate);
+}
+
+void inputx_postc(running_machine &machine, unicode_char ch)
+{
+ inputx_postc_rate(machine, ch, attotime::zero);
+}
+
+static void inputx_postn_utf8_rate(running_machine &machine, const char *text, size_t text_len, attotime rate)
+{
+ size_t len = 0;
+ unicode_char buf[256];
+ unicode_char c;
+ int rc;
+
+ while(text_len > 0)
+ {
+ if (len == ARRAY_LENGTH(buf))
+ {
+ inputx_postn_rate(machine, buf, len, attotime::zero);
+ len = 0;
+ }
+
+ rc = uchar_from_utf8(&c, text, text_len);
+ if (rc < 0)
+ {
+ rc = 1;
+ c = INVALID_CHAR;
+ }
+ text += rc;
+ text_len -= rc;
+ buf[len++] = c;
+ }
+ inputx_postn_rate(machine, buf, len, rate);
+}
+
+void inputx_post_utf8(running_machine &machine, const char *text)
+{
+ inputx_postn_utf8_rate(machine, text, strlen(text), attotime::zero);
+}
+
+void inputx_post_utf8_rate(running_machine &machine, const char *text, attotime rate)
+{
+ inputx_postn_utf8_rate(machine, text, strlen(text), rate);
+}
+
+/***************************************************************************
+
+ Other stuff
+
+ This stuff is here more out of convienience than anything else
+***************************************************************************/
+
+int input_classify_port(const input_field_config *field)
+{
+ int result;
+
+ switch(field->type)
+ {
+ case IPT_JOYSTICK_UP:
+ case IPT_JOYSTICK_DOWN:
+ case IPT_JOYSTICK_LEFT:
+ case IPT_JOYSTICK_RIGHT:
+ case IPT_JOYSTICKLEFT_UP:
+ case IPT_JOYSTICKLEFT_DOWN:
+ case IPT_JOYSTICKLEFT_LEFT:
+ case IPT_JOYSTICKLEFT_RIGHT:
+ case IPT_JOYSTICKRIGHT_UP:
+ case IPT_JOYSTICKRIGHT_DOWN:
+ case IPT_JOYSTICKRIGHT_LEFT:
+ case IPT_JOYSTICKRIGHT_RIGHT:
+ case IPT_BUTTON1:
+ case IPT_BUTTON2:
+ case IPT_BUTTON3:
+ case IPT_BUTTON4:
+ case IPT_BUTTON5:
+ case IPT_BUTTON6:
+ case IPT_BUTTON7:
+ case IPT_BUTTON8:
+ case IPT_BUTTON9:
+ case IPT_BUTTON10:
+ case IPT_AD_STICK_X:
+ case IPT_AD_STICK_Y:
+ case IPT_AD_STICK_Z:
+ case IPT_TRACKBALL_X:
+ case IPT_TRACKBALL_Y:
+ case IPT_LIGHTGUN_X:
+ case IPT_LIGHTGUN_Y:
+ case IPT_MOUSE_X:
+ case IPT_MOUSE_Y:
+ case IPT_START:
+ case IPT_SELECT:
+ result = INPUT_CLASS_CONTROLLER;
+ break;
+
+ case IPT_KEYPAD:
+ case IPT_KEYBOARD:
+ result = INPUT_CLASS_KEYBOARD;
+ break;
+
+ case IPT_CONFIG:
+ result = INPUT_CLASS_CONFIG;
+ break;
+
+ case IPT_DIPSWITCH:
+ result = INPUT_CLASS_DIPSWITCH;
+ break;
+
+ case 0:
+ if (field->name && (field->name != (const char *) -1))
+ result = INPUT_CLASS_MISC;
+ else
+ result = INPUT_CLASS_INTERNAL;
+ break;
+
+ default:
+ result = INPUT_CLASS_INTERNAL;
+ break;
+ }
+ return result;
+}
+
+
+
+int input_player_number(const input_field_config *port)
+{
+ return port->player;
+}
+
+
+
+/*-------------------------------------------------
+ input_has_input_class - checks to see if a
+ particular input class is present
+-------------------------------------------------*/
+
+int input_has_input_class(running_machine &machine, int inputclass)
+{
+ const input_port_config *port;
+ const input_field_config *field;
+
+ for (port = machine.m_portlist.first(); port != NULL; port = port->next())
+ {
+ for (field = port->first_field(); field != NULL; field = field->next())
+ {
+ if (input_classify_port(field) == inputclass)
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+
+/*-------------------------------------------------
+ input_count_players - counts the number of
+ active players
+-------------------------------------------------*/
+
+int input_count_players(running_machine &machine)
+{
+ const input_port_config *port;
+ const input_field_config *field;
+ int joystick_count;
+
+ joystick_count = 0;
+ for (port = machine.m_portlist.first(); port != NULL; port = port->next())
+ {
+ for (field = port->first_field(); field != NULL; field = field->next())
+ {
+ if (input_classify_port(field) == INPUT_CLASS_CONTROLLER)
+ {
+ if (joystick_count <= field->player + 1)
+ joystick_count = field->player + 1;
+ }
+ }
+ }
+ return joystick_count;
+}
+
+
+
+/***************************************************************************
+ DEBUGGER SUPPORT
+***************************************************************************/
+
+/*-------------------------------------------------
+ execute_input - debugger command to enter
+ natural keyboard input
+-------------------------------------------------*/
+
+static void execute_input(running_machine &machine, int ref, int params, const char *param[])
+{
+ inputx_postn_coded_rate(machine, param[0], strlen(param[0]), attotime::zero);
+}
+
+
+
+/*-------------------------------------------------
+ execute_dumpkbd - debugger command to natural
+ keyboard codes
+-------------------------------------------------*/
+
+static void execute_dumpkbd(running_machine &machine, int ref, int params, const char *param[])
+{
+ inputx_code *codes = machine.input_port_data->codes;
+ const char *filename;
+ FILE *file = NULL;
+ const inputx_code *code;
+ char buffer[512];
+ size_t pos;
+ int i, j;
+ size_t left_column_width = 24;
+
+ /* was there a file specified? */
+ filename = (params > 0) ? param[0] : NULL;
+ if (filename != NULL)
+ {
+ /* if so, open it */
+ file = fopen(filename, "w");
+ if (file == NULL)
+ {
+ debug_console_printf(machine, "Cannot open \"%s\"\n", filename);
+ return;
+ }
+ }
+
+ if ((codes != NULL) && (codes[0].ch != 0))
+ {
+ /* loop through all codes */
+ for (i = 0; codes[i].ch; i++)
+ {
+ code = &codes[i];
+ pos = 0;
+
+ /* describe the character code */
+ pos += snprintf(&buffer[pos], ARRAY_LENGTH(buffer) - pos, "%08X (%s) ",
+ code->ch,
+ code_point_string(machine, code->ch));
+
+ /* pad with spaces */
+ while(pos < left_column_width)
+ buffer[pos++] = ' ';
+ buffer[pos] = '\0';
+
+ /* identify the keys used */
+ for (j = 0; j < ARRAY_LENGTH(code->field) && (code->field[j] != NULL); j++)
+ {
+ pos += snprintf(&buffer[pos], ARRAY_LENGTH(buffer) - pos, "%s'%s'",
+ (j > 0) ? ", " : "",
+ code->field[j]->name);
+ }
+
+ /* and output it as appropriate */
+ if (file != NULL)
+ fprintf(file, "%s\n", buffer);
+ else
+ debug_console_printf(machine, "%s\n", buffer);
+ }
+ }
+ else
+ {
+ debug_console_printf(machine, "No natural keyboard support\n");
+ }
+
+ /* cleanup */
+ if (file != NULL)
+ fclose(file);
+
+}
+
+
+
+input_port_config *ioconfig_alloc_port(ioport_list &portlist, device_t &device, const char *tag)
+{
+ astring fulltag;
+ device.subtag(fulltag, tag);
+ return &portlist.append(fulltag, *global_alloc(input_port_config(device, fulltag)));
+}
+
+input_port_config *ioconfig_modify_port(ioport_list &portlist, device_t &device, const char *tag)
+{
+ astring fulltag;
+ device.subtag(fulltag, tag);
+ input_port_config *port = portlist.find(fulltag.cstr());
+ if (port == NULL)
+ throw emu_fatalerror("Requested to modify nonexistent port '%s'", fulltag.cstr());
+ port->bump_modcount();
+ return port;
+}
+
+input_field_config *ioconfig_alloc_field(input_port_config &port, int type, input_port_value defval, input_port_value mask, const char *name)
+{
+ if (&port == NULL)
+ throw emu_fatalerror("INPUT_TOKEN_FIELD encountered with no active port (mask=%X defval=%X)\n", mask, defval); \
+ if (type != IPT_UNKNOWN && type != IPT_UNUSED)
+ port.active |= mask;
+ if (type == IPT_DIPSWITCH || type == IPT_CONFIG)
+ defval = port_default_value(port.tag(), mask, defval, port.owner());
+ return &port.fieldlist().append(*global_alloc(input_field_config(port, type, defval, mask, input_port_string_from_token(name))));
+}
+
+input_field_config *ioconfig_alloc_onoff(input_port_config &port, const char *name, input_port_value defval, input_port_value mask, const char *diplocation, astring &errorbuf)
+{
+ input_field_config *curfield = ioconfig_alloc_field(port, IPT_DIPSWITCH, defval, mask, name);
+ if (name == DEF_STR(Service_Mode))
+ {
+ curfield->flags |= FIELD_FLAG_TOGGLE;
+ curfield->seq[SEQ_TYPE_STANDARD].set(KEYCODE_F2);
+ }
+ if (diplocation != NULL)
+ diplocation_list_alloc(*curfield, diplocation, errorbuf);
+ ioconfig_alloc_setting(*curfield, defval & mask, DEF_STR(Off));
+ ioconfig_alloc_setting(*curfield, ~defval & mask, DEF_STR(On));
+ return curfield;
+}
+
+input_setting_config *ioconfig_alloc_setting(input_field_config &field, input_port_value value, const char *name)
+{
+ return &field.settinglist().append(*global_alloc(input_setting_config(field, value, input_port_string_from_token(name))));
+}
+
+void ioconfig_field_add_char(input_field_config &field, unicode_char ch, astring &errorbuf)
+{
+ for (int index = 0; index < ARRAY_LENGTH(field.chars); index++)
+ if (field.chars[index] == 0)
+ {
+ field.chars[index] = ch;
+ break;
+ }
+}
+
+void ioconfig_add_code(input_field_config &field, int which, input_code code)
+{
+ field.seq[which] |= code;
+}
+
+
+
+input_type_entry::input_type_entry(UINT32 _type, ioport_group _group, int _player, const char *_token, const char *_name, input_seq standard)
+ : type(_type),
+ group(_group),
+ player(_player),
+ token(_token),
+ name(_name),
+ m_next(NULL)
+{
+ defseq[SEQ_TYPE_STANDARD] = seq[SEQ_TYPE_STANDARD] = standard;
+}
+
+input_type_entry::input_type_entry(UINT32 _type, ioport_group _group, int _player, const char *_token, const char *_name, input_seq standard, input_seq decrement, input_seq increment)
+ : type(_type),
+ group(_group),
+ player(_player),
+ token(_token),
+ name(_name),
+ m_next(NULL)
+{
+ defseq[SEQ_TYPE_STANDARD] = seq[SEQ_TYPE_STANDARD] = standard;
+ defseq[SEQ_TYPE_INCREMENT] = seq[SEQ_TYPE_INCREMENT] = increment;
+ defseq[SEQ_TYPE_DECREMENT] = seq[SEQ_TYPE_DECREMENT] = decrement;
+}
diff --git a/trunk/src/emu/ioport.h b/trunk/src/emu/ioport.h
new file mode 100644
index 00000000000..58b449f55c1
--- /dev/null
+++ b/trunk/src/emu/ioport.h
@@ -0,0 +1,1287 @@
+/***************************************************************************
+
+ ioport.h
+
+ Input/output port handling.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __EMU_H__
+#error Dont include this file directly; include emu.h instead.
+#endif
+
+#ifndef __INPTPORT_H__
+#define __INPTPORT_H__
+
+#include <time.h>
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define MAX_PLAYERS 8
+
+#define IP_ACTIVE_HIGH 0x00000000
+#define IP_ACTIVE_LOW 0xffffffff
+
+
+/* flags for input_field_configs */
+#define FIELD_FLAG_UNUSED 0x01 /* set if this field is unused but relevant to other games on the same hw */
+#define FIELD_FLAG_COCKTAIL 0x02 /* set if this field is relevant only for cocktail cabinets */
+#define FIELD_FLAG_TOGGLE 0x04 /* set if this field should behave as a toggle */
+#define FIELD_FLAG_ROTATED 0x08 /* set if this field represents a rotated control */
+#define ANALOG_FLAG_REVERSE 0x10 /* analog only: reverse the sense of the axis */
+#define ANALOG_FLAG_RESET 0x20 /* analog only: always preload in->default for relative axes, returning only deltas */
+#define ANALOG_FLAG_WRAPS 0x40 /* analog only: positional count wraps around */
+#define ANALOG_FLAG_INVERT 0x80 /* analog only: bitwise invert bits */
+
+
+/* INP file information */
+#define INP_HEADER_SIZE 64
+#define INP_HEADER_MAJVERSION 3
+#define INP_HEADER_MINVERSION 0
+
+
+/* sequence types for input_port_seq() call */
+enum _input_seq_type
+{
+ SEQ_TYPE_STANDARD = 0,
+ SEQ_TYPE_INCREMENT,
+ SEQ_TYPE_DECREMENT,
+ SEQ_TYPE_TOTAL
+};
+typedef enum _input_seq_type input_seq_type;
+DECLARE_ENUM_OPERATORS(input_seq_type)
+
+
+/* conditions for DIP switches */
+enum
+{
+ PORTCOND_ALWAYS = 0,
+ PORTCOND_EQUALS,
+ PORTCOND_NOTEQUALS,
+ PORTCOND_GREATERTHAN,
+ PORTCOND_NOTGREATERTHAN,
+ PORTCOND_LESSTHAN,
+ PORTCOND_NOTLESSTHAN
+};
+
+
+/* crosshair types */
+enum
+{
+ CROSSHAIR_AXIS_NONE = 0,
+ CROSSHAIR_AXIS_X,
+ CROSSHAIR_AXIS_Y
+};
+
+
+/* groups for input ports */
+enum ioport_group
+{
+ IPG_UI = 0,
+ IPG_PLAYER1,
+ IPG_PLAYER2,
+ IPG_PLAYER3,
+ IPG_PLAYER4,
+ IPG_PLAYER5,
+ IPG_PLAYER6,
+ IPG_PLAYER7,
+ IPG_PLAYER8,
+ IPG_OTHER,
+ IPG_TOTAL_GROUPS,
+ IPG_INVALID
+};
+
+
+/* various input port types */
+enum
+{
+ /* pseudo-port types */
+ IPT_INVALID = 0,
+ IPT_UNUSED,
+ IPT_END,
+ IPT_UNKNOWN,
+ IPT_PORT,
+ IPT_DIPSWITCH,
+ IPT_VBLANK,
+ IPT_CONFIG,
+
+ /* start buttons */
+ IPT_START1,
+ IPT_START2,
+ IPT_START3,
+ IPT_START4,
+ IPT_START5,
+ IPT_START6,
+ IPT_START7,
+ IPT_START8,
+
+ /* coin slots */
+ IPT_COIN1,
+ IPT_COIN2,
+ IPT_COIN3,
+ IPT_COIN4,
+ IPT_COIN5,
+ IPT_COIN6,
+ IPT_COIN7,
+ IPT_COIN8,
+ IPT_COIN9,
+ IPT_COIN10,
+ IPT_COIN11,
+ IPT_COIN12,
+ IPT_BILL1,
+
+ /* service coin */
+ IPT_SERVICE1,
+ IPT_SERVICE2,
+ IPT_SERVICE3,
+ IPT_SERVICE4,
+
+ /* tilt inputs */
+ IPT_TILT1,
+ IPT_TILT2,
+ IPT_TILT3,
+ IPT_TILT4,
+
+ /* misc other digital inputs */
+ IPT_SERVICE,
+ IPT_TILT,
+ IPT_INTERLOCK,
+ IPT_VOLUME_UP,
+ IPT_VOLUME_DOWN,
+ IPT_START, /* MESS only */
+ IPT_SELECT, /* MESS only */
+ IPT_KEYPAD, /* MESS only */
+ IPT_KEYBOARD, /* MESS only */
+
+#define __ipt_digital_joystick_start IPT_JOYSTICK_UP
+ /* use IPT_JOYSTICK for panels where the player has one single joystick */
+ IPT_JOYSTICK_UP,
+ IPT_JOYSTICK_DOWN,
+ IPT_JOYSTICK_LEFT,
+ IPT_JOYSTICK_RIGHT,
+
+ /* use IPT_JOYSTICKLEFT and IPT_JOYSTICKRIGHT for dual joystick panels */
+ IPT_JOYSTICKRIGHT_UP,
+ IPT_JOYSTICKRIGHT_DOWN,
+ IPT_JOYSTICKRIGHT_LEFT,
+ IPT_JOYSTICKRIGHT_RIGHT,
+ IPT_JOYSTICKLEFT_UP,
+ IPT_JOYSTICKLEFT_DOWN,
+ IPT_JOYSTICKLEFT_LEFT,
+ IPT_JOYSTICKLEFT_RIGHT,
+#define __ipt_digital_joystick_end IPT_JOYSTICKLEFT_RIGHT
+
+ /* action buttons */
+ IPT_BUTTON1,
+ IPT_BUTTON2,
+ IPT_BUTTON3,
+ IPT_BUTTON4,
+ IPT_BUTTON5,
+ IPT_BUTTON6,
+ IPT_BUTTON7,
+ IPT_BUTTON8,
+ IPT_BUTTON9,
+ IPT_BUTTON10,
+ IPT_BUTTON11,
+ IPT_BUTTON12,
+ IPT_BUTTON13,
+ IPT_BUTTON14,
+ IPT_BUTTON15,
+ IPT_BUTTON16,
+
+ /* mahjong inputs */
+ IPT_MAHJONG_A,
+ IPT_MAHJONG_B,
+ IPT_MAHJONG_C,
+ IPT_MAHJONG_D,
+ IPT_MAHJONG_E,
+ IPT_MAHJONG_F,
+ IPT_MAHJONG_G,
+ IPT_MAHJONG_H,
+ IPT_MAHJONG_I,
+ IPT_MAHJONG_J,
+ IPT_MAHJONG_K,
+ IPT_MAHJONG_L,
+ IPT_MAHJONG_M,
+ IPT_MAHJONG_N,
+ IPT_MAHJONG_O,
+ IPT_MAHJONG_P,
+ IPT_MAHJONG_Q,
+ IPT_MAHJONG_KAN,
+ IPT_MAHJONG_PON,
+ IPT_MAHJONG_CHI,
+ IPT_MAHJONG_REACH,
+ IPT_MAHJONG_RON,
+ IPT_MAHJONG_BET,
+ IPT_MAHJONG_LAST_CHANCE,
+ IPT_MAHJONG_SCORE,
+ IPT_MAHJONG_DOUBLE_UP,
+ IPT_MAHJONG_FLIP_FLOP,
+ IPT_MAHJONG_BIG,
+ IPT_MAHJONG_SMALL,
+
+ /* hanafuda inputs */
+ IPT_HANAFUDA_A,
+ IPT_HANAFUDA_B,
+ IPT_HANAFUDA_C,
+ IPT_HANAFUDA_D,
+ IPT_HANAFUDA_E,
+ IPT_HANAFUDA_F,
+ IPT_HANAFUDA_G,
+ IPT_HANAFUDA_H,
+ IPT_HANAFUDA_YES,
+ IPT_HANAFUDA_NO,
+
+ /* gambling inputs */
+ IPT_GAMBLE_HIGH,
+ IPT_GAMBLE_LOW,
+ IPT_GAMBLE_HALF,
+ IPT_GAMBLE_DEAL,
+ IPT_GAMBLE_D_UP,
+ IPT_GAMBLE_TAKE,
+ IPT_GAMBLE_STAND,
+ IPT_GAMBLE_BET,
+ IPT_GAMBLE_KEYIN,
+ IPT_GAMBLE_KEYOUT,
+ IPT_GAMBLE_PAYOUT,
+ IPT_GAMBLE_DOOR,
+ IPT_GAMBLE_SERVICE,
+ IPT_GAMBLE_BOOK,
+
+ /* poker-specific inputs */
+ IPT_POKER_HOLD1,
+ IPT_POKER_HOLD2,
+ IPT_POKER_HOLD3,
+ IPT_POKER_HOLD4,
+ IPT_POKER_HOLD5,
+ IPT_POKER_CANCEL,
+ IPT_POKER_BET,
+
+ /* slot-specific inputs */
+ IPT_SLOT_STOP1,
+ IPT_SLOT_STOP2,
+ IPT_SLOT_STOP3,
+ IPT_SLOT_STOP4,
+ IPT_SLOT_STOP_ALL,
+
+ /* analog inputs */
+#define __ipt_analog_start IPT_PADDLE
+#define __ipt_analog_absolute_start IPT_PADDLE
+ IPT_PADDLE, /* absolute */
+ IPT_PADDLE_V, /* absolute */
+ IPT_AD_STICK_X, /* absolute */
+ IPT_AD_STICK_Y, /* absolute */
+ IPT_AD_STICK_Z, /* absolute */
+ IPT_LIGHTGUN_X, /* absolute */
+ IPT_LIGHTGUN_Y, /* absolute */
+ IPT_PEDAL, /* absolute */
+ IPT_PEDAL2, /* absolute */
+ IPT_PEDAL3, /* absolute */
+ IPT_POSITIONAL, /* absolute */
+ IPT_POSITIONAL_V, /* absolute */
+#define __ipt_analog_absolute_end IPT_POSITIONAL_V
+
+ IPT_DIAL, /* relative */
+ IPT_DIAL_V, /* relative */
+ IPT_TRACKBALL_X, /* relative */
+ IPT_TRACKBALL_Y, /* relative */
+ IPT_MOUSE_X, /* relative */
+ IPT_MOUSE_Y, /* relative */
+#define __ipt_analog_end IPT_MOUSE_Y
+
+ /* analog adjuster support */
+ IPT_ADJUSTER,
+
+ /* the following are special codes for user interface handling - not to be used by drivers! */
+#define __ipt_ui_start IPT_UI_CONFIGURE
+ IPT_UI_CONFIGURE,
+ IPT_UI_ON_SCREEN_DISPLAY,
+ IPT_UI_DEBUG_BREAK,
+ IPT_UI_PAUSE,
+ IPT_UI_RESET_MACHINE,
+ IPT_UI_SOFT_RESET,
+ IPT_UI_SHOW_GFX,
+ IPT_UI_FRAMESKIP_DEC,
+ IPT_UI_FRAMESKIP_INC,
+ IPT_UI_THROTTLE,
+ IPT_UI_FAST_FORWARD,
+ IPT_UI_SHOW_FPS,
+ IPT_UI_SNAPSHOT,
+ IPT_UI_RECORD_MOVIE,
+ IPT_UI_TOGGLE_CHEAT,
+ IPT_UI_UP,
+ IPT_UI_DOWN,
+ IPT_UI_LEFT,
+ IPT_UI_RIGHT,
+ IPT_UI_HOME,
+ IPT_UI_END,
+ IPT_UI_PAGE_UP,
+ IPT_UI_PAGE_DOWN,
+ IPT_UI_SELECT,
+ IPT_UI_CANCEL,
+ IPT_UI_DISPLAY_COMMENT,
+ IPT_UI_CLEAR,
+ IPT_UI_ZOOM_IN,
+ IPT_UI_ZOOM_OUT,
+ IPT_UI_PREV_GROUP,
+ IPT_UI_NEXT_GROUP,
+ IPT_UI_ROTATE,
+ IPT_UI_SHOW_PROFILER,
+ IPT_UI_TOGGLE_UI,
+ IPT_UI_TOGGLE_DEBUG,
+ IPT_UI_PASTE,
+ IPT_UI_SAVE_STATE,
+ IPT_UI_LOAD_STATE,
+
+ /* additional OSD-specified UI port types (up to 16) */
+ IPT_OSD_1,
+ IPT_OSD_2,
+ IPT_OSD_3,
+ IPT_OSD_4,
+ IPT_OSD_5,
+ IPT_OSD_6,
+ IPT_OSD_7,
+ IPT_OSD_8,
+ IPT_OSD_9,
+ IPT_OSD_10,
+ IPT_OSD_11,
+ IPT_OSD_12,
+ IPT_OSD_13,
+ IPT_OSD_14,
+ IPT_OSD_15,
+ IPT_OSD_16,
+#define __ipt_ui_end IPT_OSD_16
+
+ /* other meaning not mapped to standard defaults */
+ IPT_OTHER,
+
+ /* special meaning handled by custom code */
+ IPT_SPECIAL,
+ IPT_OUTPUT,
+
+ __ipt_max
+};
+
+
+/* default strings used in port definitions */
+enum
+{
+ INPUT_STRING_Off = 1,
+ INPUT_STRING_On,
+ INPUT_STRING_No,
+ INPUT_STRING_Yes,
+ INPUT_STRING_Lives,
+ INPUT_STRING_Bonus_Life,
+ INPUT_STRING_Difficulty,
+ INPUT_STRING_Demo_Sounds,
+ INPUT_STRING_Coinage,
+ INPUT_STRING_Coin_A,
+ INPUT_STRING_Coin_B,
+ INPUT_STRING_9C_1C,
+ INPUT_STRING_8C_1C,
+ INPUT_STRING_7C_1C,
+ INPUT_STRING_6C_1C,
+ INPUT_STRING_5C_1C,
+ INPUT_STRING_4C_1C,
+ INPUT_STRING_3C_1C,
+ INPUT_STRING_8C_3C,
+ INPUT_STRING_4C_2C,
+ INPUT_STRING_2C_1C,
+ INPUT_STRING_5C_3C,
+ INPUT_STRING_3C_2C,
+ INPUT_STRING_4C_3C,
+ INPUT_STRING_4C_4C,
+ INPUT_STRING_3C_3C,
+ INPUT_STRING_2C_2C,
+ INPUT_STRING_1C_1C,
+ INPUT_STRING_4C_5C,
+ INPUT_STRING_3C_4C,
+ INPUT_STRING_2C_3C,
+ INPUT_STRING_4C_7C,
+ INPUT_STRING_2C_4C,
+ INPUT_STRING_1C_2C,
+ INPUT_STRING_2C_5C,
+ INPUT_STRING_2C_6C,
+ INPUT_STRING_1C_3C,
+ INPUT_STRING_2C_7C,
+ INPUT_STRING_2C_8C,
+ INPUT_STRING_1C_4C,
+ INPUT_STRING_1C_5C,
+ INPUT_STRING_1C_6C,
+ INPUT_STRING_1C_7C,
+ INPUT_STRING_1C_8C,
+ INPUT_STRING_1C_9C,
+ INPUT_STRING_Free_Play,
+ INPUT_STRING_Cabinet,
+ INPUT_STRING_Upright,
+ INPUT_STRING_Cocktail,
+ INPUT_STRING_Flip_Screen,
+ INPUT_STRING_Service_Mode,
+ INPUT_STRING_Pause,
+ INPUT_STRING_Test,
+ INPUT_STRING_Tilt,
+ INPUT_STRING_Version,
+ INPUT_STRING_Region,
+ INPUT_STRING_International,
+ INPUT_STRING_Japan,
+ INPUT_STRING_USA,
+ INPUT_STRING_Europe,
+ INPUT_STRING_Asia,
+ INPUT_STRING_World,
+ INPUT_STRING_Hispanic,
+ INPUT_STRING_Language,
+ INPUT_STRING_English,
+ INPUT_STRING_Japanese,
+ INPUT_STRING_German,
+ INPUT_STRING_French,
+ INPUT_STRING_Italian,
+ INPUT_STRING_Spanish,
+ INPUT_STRING_Very_Easy,
+ INPUT_STRING_Easiest,
+ INPUT_STRING_Easier,
+ INPUT_STRING_Easy,
+ INPUT_STRING_Medium_Easy,
+ INPUT_STRING_Normal,
+ INPUT_STRING_Medium,
+ INPUT_STRING_Medium_Hard,
+ INPUT_STRING_Hard,
+ INPUT_STRING_Harder,
+ INPUT_STRING_Hardest,
+ INPUT_STRING_Very_Hard,
+ INPUT_STRING_Medium_Difficult,
+ INPUT_STRING_Difficult,
+ INPUT_STRING_More_Difficult,
+ INPUT_STRING_Most_Difficult,
+ INPUT_STRING_Very_Difficult,
+ INPUT_STRING_Very_Low,
+ INPUT_STRING_Low,
+ INPUT_STRING_High,
+ INPUT_STRING_Higher,
+ INPUT_STRING_Highest,
+ INPUT_STRING_Very_High,
+ INPUT_STRING_Players,
+ INPUT_STRING_Controls,
+ INPUT_STRING_Dual,
+ INPUT_STRING_Single,
+ INPUT_STRING_Game_Time,
+ INPUT_STRING_Continue_Price,
+ INPUT_STRING_Controller,
+ INPUT_STRING_Light_Gun,
+ INPUT_STRING_Joystick,
+ INPUT_STRING_Trackball,
+ INPUT_STRING_Continues,
+ INPUT_STRING_Allow_Continue,
+ INPUT_STRING_Level_Select,
+ INPUT_STRING_Infinite,
+ INPUT_STRING_Stereo,
+ INPUT_STRING_Mono,
+ INPUT_STRING_Unused,
+ INPUT_STRING_Unknown,
+ INPUT_STRING_Standard,
+ INPUT_STRING_Reverse,
+ INPUT_STRING_Alternate,
+ INPUT_STRING_None,
+
+ INPUT_STRING_COUNT
+};
+
+
+/* input classes */
+enum
+{
+ INPUT_CLASS_INTERNAL,
+ INPUT_CLASS_KEYBOARD,
+ INPUT_CLASS_CONTROLLER,
+ INPUT_CLASS_CONFIG,
+ INPUT_CLASS_DIPSWITCH,
+ INPUT_CLASS_MISC
+};
+
+#define UCHAR_PRIVATE (0x100000)
+#define UCHAR_SHIFT_1 (UCHAR_PRIVATE + 0)
+#define UCHAR_SHIFT_2 (UCHAR_PRIVATE + 1)
+#define UCHAR_MAMEKEY_BEGIN (UCHAR_PRIVATE + 2)
+#define UCHAR_MAMEKEY(code) (UCHAR_MAMEKEY_BEGIN + ITEM_ID_##code)
+
+#define UCHAR_SHIFT_BEGIN (UCHAR_SHIFT_1)
+#define UCHAR_SHIFT_END (UCHAR_SHIFT_2)
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/* input ports support up to 32 bits each */
+typedef UINT32 input_port_value;
+
+
+/* opaque types pointing to live state */
+typedef struct _input_port_state input_port_state;
+typedef struct _input_field_state input_field_state;
+
+
+/* forward declarations */
+class input_port_config;
+class input_field_config;
+
+
+/* template specializations */
+typedef tagged_list<input_port_config> ioport_list;
+
+
+/* read input port callback function */
+typedef delegate<UINT32 (const input_field_config &, void *)> input_field_read_delegate;
+
+/* input port write callback function */
+typedef delegate<void (const input_field_config &, void *, input_port_value, input_port_value)> input_field_write_delegate;
+
+/* crosshair mapping function */
+typedef delegate<float (const input_field_config &, float)> input_field_crossmap_delegate;
+
+
+/* encapsulates a condition on a port field or setting */
+typedef struct _input_condition input_condition;
+struct _input_condition
+{
+ const char * tag; /* tag of port whose condition is to be tested */
+ input_port_value mask; /* mask to apply to the port */
+ input_port_value value; /* value to compare against */
+ UINT8 condition; /* condition to use */
+};
+
+
+/* a single setting for a configuration or DIP switch */
+class input_setting_config
+{
+ DISABLE_COPYING(input_setting_config);
+ friend class simple_list<input_setting_config>;
+
+public:
+ input_setting_config(input_field_config &field, input_port_value value, const char *name);
+ input_setting_config *next() const { return m_next; }
+
+ input_port_value value; /* value of the bits in this setting */
+ input_condition condition; /* condition under which this setting is valid */
+ const char * name; /* user-friendly name to display */
+
+private:
+ input_field_config & m_field; /* pointer back to the field that owns us */
+ input_setting_config * m_next; /* pointer to next setting in sequence */
+};
+
+
+/* a mapping from a bit to a physical DIP switch description */
+class input_field_diplocation
+{
+ DISABLE_COPYING(input_field_diplocation);
+ friend class simple_list<input_field_diplocation>;
+
+public:
+ input_field_diplocation(const char *string, UINT8 swnum, bool invert);
+ input_field_diplocation *next() const { return m_next; }
+
+ astring swname; /* name of the physical DIP switch */
+ UINT8 swnum; /* physical switch number */
+ bool invert; /* is this an active-high DIP? */
+
+private:
+ input_field_diplocation * m_next; /* pointer to the next bit */
+};
+
+
+/* a single bitfield within an input port */
+class input_field_config
+{
+ DISABLE_COPYING(input_field_config);
+ friend class simple_list<input_field_config>;
+
+public:
+ input_field_config(input_port_config &port, int type, input_port_value defvalue, input_port_value maskbits, const char *name = NULL);
+
+ input_field_config *next() const { return m_next; }
+ input_port_config &port() const { return m_port; }
+ running_machine &machine() const;
+ simple_list<input_setting_config> &settinglist() { return m_settinglist; }
+ const simple_list<input_setting_config> &settinglist() const { return m_settinglist; }
+ simple_list<input_field_diplocation> &diploclist() { return m_diploclist; }
+ int modcount() const { return m_modcount; }
+
+ /* generally-applicable data */
+ input_port_value mask; /* mask of bits belonging to the field */
+ input_port_value defvalue; /* default value of these bits */
+ input_condition condition; /* condition under which this field is relevant */
+ UINT32 type; /* IPT_* type for this port */
+ UINT8 player; /* player number (0-based) */
+ UINT32 flags; /* combination of FIELD_FLAG_* and ANALOG_FLAG_* above */
+ UINT8 impulse; /* number of frames before reverting to defvalue */
+ const char * name; /* user-friendly name to display */
+ input_seq seq[SEQ_TYPE_TOTAL];/* sequences of all types */
+ input_field_read_delegate read; /* read callback routine */
+ void * read_param; /* parameter for read callback routine */
+ const char * read_device; /* parameter for read callback routine */
+ input_field_write_delegate write; /* write callback routine */
+ void * write_param; /* parameter for write callback routine */
+ const char * write_device; /* parameter for write callback routine */
+
+ /* data relevant to analog control types */
+ INT32 min; /* minimum value for absolute axes */
+ INT32 max; /* maximum value for absolute axes */
+ INT32 sensitivity; /* sensitivity (100=normal) */
+ INT32 delta; /* delta to apply each frame a digital inc/dec key is pressed */
+ INT32 centerdelta; /* delta to apply each frame no digital inputs are pressed */
+ UINT8 crossaxis; /* crosshair axis */
+ double crossscale; /* crosshair scale */
+ double crossoffset; /* crosshair offset */
+ double crossaltaxis; /* crosshair alternate axis value */
+ input_field_crossmap_delegate crossmapper; /* crosshair mapping function */
+ const char * crossmapper_device; /* parameter for write callback routine */
+ UINT16 full_turn_count;/* number of optical counts for 1 full turn of the original control */
+ const input_port_value * remap_table; /* pointer to an array that remaps the port value */
+
+ /* data relevant to other specific types */
+ UINT8 way; /* digital joystick 2/4/8-way descriptions */
+ unicode_char chars[3]; /* (MESS-specific) unicode key data */
+
+ /* this field is only valid if the device is live */
+ input_field_state * state; /* live state of field (NULL if not live) */
+
+private:
+ input_field_config * m_next; /* pointer to next field in sequence */
+ input_port_config & m_port; /* pointer back to the port that owns us */
+ int m_modcount;
+ simple_list<input_setting_config> m_settinglist; /* list of input_setting_configs */
+ simple_list<input_field_diplocation> m_diploclist; /* list of locations for various bits */
+};
+
+
+/* user-controllable settings for a field */
+typedef struct _input_field_user_settings input_field_user_settings;
+struct _input_field_user_settings
+{
+ input_port_value value; /* for DIP switches */
+ input_seq seq[SEQ_TYPE_TOTAL];/* sequences of all types */
+ INT32 sensitivity; /* for analog controls */
+ INT32 delta; /* for analog controls */
+ INT32 centerdelta; /* for analog controls */
+ UINT8 reverse; /* for analog controls */
+};
+
+/* device defined default input settings */
+typedef struct _input_device_default input_device_default;
+struct _input_device_default
+{
+ const char * tag; /* tag of port to update */
+ input_port_value mask; /* mask to apply to the port */
+ input_port_value defvalue; /* new default value */
+};
+
+/* a single input port configuration */
+class input_port_config
+{
+ DISABLE_COPYING(input_port_config);
+ friend class simple_list<input_port_config>;
+
+public:
+ // construction/destruction
+ input_port_config(device_t &owner, const char *tag);
+
+ // getters
+ input_port_config *next() const { return m_next; }
+ device_t &owner() const { return m_owner; }
+ running_machine &machine() const;
+ input_field_config *first_field() const { return m_fieldlist.first(); }
+ simple_list<input_field_config> &fieldlist() { return m_fieldlist; }
+ const char *tag() const { return m_tag; }
+ int modcount() const { return m_modcount; }
+
+ void bump_modcount() { m_modcount++; }
+
+ void collapse_fields(astring &errorbuf);
+
+ /* these fields are only valid if the port is live */
+ input_port_state * state; /* live state of port (NULL if not live) */
+ input_port_value active; /* mask of active bits in the port */
+
+private:
+ input_port_config * m_next; /* pointer to next port */
+ device_t & m_owner; /* associated device, when appropriate */
+ simple_list<input_field_config> m_fieldlist; /* list of input_field_configs */
+ astring m_tag; /* pointer to this port's tag */
+ int m_modcount;
+};
+
+
+/* describes a fundamental input type, including default input sequences */
+class input_type_entry
+{
+ friend class simple_list<input_type_entry>;
+
+public:
+ input_type_entry(UINT32 type, ioport_group group, int player, const char *token, const char *name, input_seq standard);
+ input_type_entry(UINT32 type, ioport_group group, int player, const char *token, const char *name, input_seq standard, input_seq decrement, input_seq increment);
+
+ input_type_entry *next() const { return m_next; }
+
+ UINT32 type; /* IPT_* for this entry */
+ ioport_group group; /* which group the port belongs to */
+ UINT8 player; /* player number (0 is player 1) */
+ const char * token; /* token used to store settings */
+ const char * name; /* user-friendly name */
+ input_seq defseq[SEQ_TYPE_TOTAL];/* default input sequence */
+ input_seq seq[SEQ_TYPE_TOTAL];/* currently configured sequences */
+
+private:
+ input_type_entry * m_next; /* next description in the list */
+};
+
+
+/* header at the front of INP files */
+typedef struct _inp_header inp_header;
+struct _inp_header
+{
+ char header[8]; /* +00: 8 byte header - must be "MAMEINP\0" */
+ UINT64 basetime; /* +08: base time of recording */
+ UINT8 majversion; /* +10: major INP version */
+ UINT8 minversion; /* +11: minor INP version */
+ UINT8 reserved[2]; /* +12: must be zero */
+ char gamename[12]; /* +14: game name string, NULL-terminated */
+ char version[32]; /* +20: system version string, NULL-terminated */
+};
+
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+/* macro for a read callback function (PORT_CUSTOM) */
+#define CUSTOM_INPUT(name) input_port_value name(device_t &device, const input_field_config &field, void *param)
+#define CUSTOM_INPUT_MEMBER(name) input_port_value name(const input_field_config &field, void *param)
+#define DECLARE_CUSTOM_INPUT_MEMBER(name) input_port_value name(const input_field_config &field, void *param)
+
+/* macro for port write callback functions (PORT_CHANGED) */
+#define INPUT_CHANGED(name) void name(device_t &device, const input_field_config &field, void *param, input_port_value oldval, input_port_value newval)
+#define INPUT_CHANGED_MEMBER(name) void name(const input_field_config &field, void *param, input_port_value oldval, input_port_value newval)
+#define DECLARE_INPUT_CHANGED_MEMBER(name) void name(const input_field_config &field, void *param, input_port_value oldval, input_port_value newval)
+
+/* macro for port changed callback functions (PORT_CROSSHAIR_MAPPER) */
+#define CROSSHAIR_MAPPER(name) float name(device_t &device, const input_field_config &field, float linear_value)
+#define CROSSHAIR_MAPPER_MEMBER(name) float name(const input_field_config &field, float linear_value)
+#define DECLARE_CROSSHAIR_MAPPER_MEMBER(name) float name(const input_field_config &field, float linear_value)
+
+/* macro for wrapping a default string */
+#define DEF_STR(str_num) ((const char *)INPUT_STRING_##str_num)
+
+
+template<int (*_FunctionPointer)(device_t *)>
+input_port_value ioport_read_line_wrapper(device_t &device, const input_field_config &field, void *param)
+{
+ return (*_FunctionPointer)(&device);
+}
+
+template<class _FunctionClass, int (_FunctionClass::*_FunctionPointer)()>
+input_port_value ioport_read_line_wrapper(_FunctionClass &device, const input_field_config &field, void *param)
+{
+ return (device.*_FunctionPointer)();
+}
+
+template<void (*_FunctionPointer)(device_t *, int)>
+void ioport_write_line_wrapper(device_t &device, const input_field_config &field, void *param, input_port_value oldval, input_port_value newval)
+{
+ return (*_FunctionPointer)(&device, newval);
+}
+
+template<class _FunctionClass, void (_FunctionClass::*_FunctionPointer)(int)>
+void ioport_write_line_wrapper(_FunctionClass &device, const input_field_config &field, void *param, input_port_value oldval, input_port_value newval)
+{
+ return (device.*_FunctionPointer)(newval);
+}
+
+
+
+/***************************************************************************
+ MACROS FOR BUILDING INPUT PORTS
+***************************************************************************/
+
+typedef void (*ioport_constructor)(device_t &owner, ioport_list &portlist, astring &errorbuf);
+
+/* so that "0" can be used for unneeded input ports */
+#define construct_ioport_0 NULL
+
+/* name of table */
+#define INPUT_PORTS_NAME(_name) construct_ioport_##_name
+
+/* start of table */
+#define INPUT_PORTS_START(_name) \
+void INPUT_PORTS_NAME(_name)(device_t &owner, ioport_list &portlist, astring &errorbuf) \
+{ \
+ astring fulltag; \
+ input_setting_config *cursetting = NULL; \
+ input_field_config *curfield = NULL; \
+ input_port_config *curport = NULL; \
+ input_port_value maskbits = 0; \
+ (void)cursetting; (void)curfield; (void)curport; (void)maskbits; \
+
+/* end of table */
+#define INPUT_PORTS_END \
+}
+
+/* aliasing */
+#define INPUT_PORTS_EXTERN(_name) \
+ extern void INPUT_PORTS_NAME(_name)(device_t &owner, ioport_list &portlist, astring &errorbuf)
+
+/* including */
+#define PORT_INCLUDE(_name) \
+ INPUT_PORTS_NAME(_name)(owner, portlist, errorbuf); \
+
+/* start of a new input port (with included tag) */
+#define PORT_START(_tag) \
+ curport = ioconfig_alloc_port(portlist, owner, _tag); \
+ curfield = NULL; \
+ cursetting = NULL; \
+ maskbits = 0; \
+
+/* modify an existing port */
+#define PORT_MODIFY(_tag) \
+ curport = ioconfig_modify_port(portlist, owner, _tag); \
+ curfield = NULL; \
+ cursetting = NULL; \
+ maskbits = 0; \
+
+/* input bit definition */
+#define PORT_BIT(_mask, _default, _type) \
+ curfield = ioconfig_alloc_field(*curport, (_type), (_default), (_mask)); \
+ cursetting = NULL;
+
+#define PORT_SPECIAL_ONOFF(_mask, _default, _strindex) PORT_SPECIAL_ONOFF_DIPLOC(_mask, _default, _strindex, NULL)
+
+#define PORT_SPECIAL_ONOFF_DIPLOC(_mask, _default, _strindex, _diploc) \
+ curfield = ioconfig_alloc_onoff(*curport, DEF_STR(_strindex), _default, _mask, _diploc, errorbuf); \
+ cursetting = NULL;
+
+/* append a code */
+#define PORT_CODE(_code) \
+ ioconfig_add_code(*curfield, SEQ_TYPE_STANDARD, _code);
+
+#define PORT_CODE_DEC(_code) \
+ ioconfig_add_code(*curfield, SEQ_TYPE_DECREMENT, _code);
+
+#define PORT_CODE_INC(_code) \
+ ioconfig_add_code(*curfield, SEQ_TYPE_INCREMENT, _code);
+
+/* joystick flags */
+#define PORT_2WAY \
+ curfield->way = 2;
+
+#define PORT_4WAY \
+ curfield->way = 4;
+
+#define PORT_8WAY \
+ curfield->way = 8;
+
+#define PORT_16WAY \
+ curfield->way = 16;
+
+#define PORT_ROTATED \
+ curfield->flags |= FIELD_FLAG_ROTATED
+
+/* general flags */
+#define PORT_NAME(_name) \
+ curfield->name = input_port_string_from_token(_name);
+
+#define PORT_PLAYER(_player) \
+ curfield->player = (_player) - 1;
+
+#define PORT_COCKTAIL \
+ curfield->flags |= FIELD_FLAG_COCKTAIL; \
+ curfield->player = 1;
+
+#define PORT_TOGGLE \
+ curfield->flags |= FIELD_FLAG_TOGGLE;
+
+#define PORT_IMPULSE(_duration) \
+ curfield->impulse = _duration;
+
+#define PORT_REVERSE \
+ curfield->flags |= ANALOG_FLAG_REVERSE;
+
+#define PORT_RESET \
+ curfield->flags |= ANALOG_FLAG_RESET;
+
+#define PORT_UNUSED \
+ curfield->flags |= FIELD_FLAG_UNUSED;
+
+/* analog settings */
+/* if this macro is not used, the minimum defaluts to 0 and maximum defaults to the mask value */
+#define PORT_MINMAX(_min, _max) \
+ curfield->min = _min; \
+ curfield->max = _max;
+
+#define PORT_SENSITIVITY(_sensitivity) \
+ curfield->sensitivity = _sensitivity;
+
+#define PORT_KEYDELTA(_delta) \
+ curfield->delta = curfield->centerdelta = _delta;
+
+/* note that PORT_CENTERDELTA must appear after PORT_KEYDELTA */
+#define PORT_CENTERDELTA(_delta) \
+ curfield->centerdelta = _delta;
+
+#define PORT_CROSSHAIR(axis, scale, offset, altaxis) \
+ curfield->crossaxis = CROSSHAIR_AXIS_##axis; \
+ curfield->crossaltaxis = altaxis; \
+ curfield->crossscale = scale; \
+ curfield->crossoffset = offset;
+
+#define PORT_CROSSHAIR_MAPPER(_callback) \
+ curfield->crossmapper = input_field_crossmap_delegate(_callback, #_callback, (device_t *)NULL); \
+ curfield->crossmapper_device = DEVICE_SELF;
+
+#define PORT_CROSSHAIR_MAPPER_MEMBER(_device, _class, _member) \
+ curfield->crossmapper = input_field_crossmap_delegate(&_class::_member, #_class "::" #_member, (_class *)NULL); \
+ curfield->crossmapper_device = _device;
+
+/* how many optical counts for 1 full turn of the control */
+#define PORT_FULL_TURN_COUNT(_count) \
+ curfield->full_turn_count = _count;
+
+/* positional controls can be binary or 1 of X */
+/* 1 of X not completed yet */
+/* if it is specified as PORT_REMAP_TABLE then it is binary, but remapped */
+/* otherwise it is binary */
+#define PORT_POSITIONS(_positions) \
+ curfield->max = _positions;
+
+/* positional control wraps at min/max */
+#define PORT_WRAPS \
+ curfield->flags |= ANALOG_FLAG_WRAPS;
+
+/* positional control uses this remap table */
+#define PORT_REMAP_TABLE(_table) \
+ curfield->remap_table = _table;
+
+/* positional control bits are active low */
+#define PORT_INVERT \
+ curfield->flags |= ANALOG_FLAG_INVERT;
+
+/* read callbacks */
+#define PORT_CUSTOM(_callback, _param) \
+ curfield->read = input_field_read_delegate(_callback, #_callback, (device_t *)NULL); \
+ curfield->read_param = (void *)(_param); \
+ curfield->read_device = DEVICE_SELF;
+
+#define PORT_CUSTOM_MEMBER(_device, _class, _member, _param) \
+ curfield->read = input_field_read_delegate(&_class::_member, #_class "::" #_member, (_class *)NULL); \
+ curfield->read_param = (void *)(_param); \
+ curfield->read_device = (_device);
+
+/* write callbacks */
+#define PORT_CHANGED(_callback, _param) \
+ curfield->write = input_field_write_delegate(_callback, #_callback, (device_t *)NULL); \
+ curfield->write_param = (void *)(_param); \
+ curfield->write_device = DEVICE_SELF;
+
+#define PORT_CHANGED_MEMBER(_device, _class, _member, _param) \
+ curfield->write = input_field_write_delegate(&_class::_member, #_class "::" #_member, (_class *)NULL); \
+ curfield->write_param = (void *)(_param); \
+ curfield->write_device = (_device);
+
+/* input device handler */
+#define PORT_READ_LINE_DEVICE(_device, _read_line_device) \
+ curfield->read = input_field_read_delegate(&ioport_read_line_wrapper<_read_line_device>, #_read_line_device, (device_t *)NULL); \
+ curfield->read_param = NULL; \
+ curfield->read_device = _device;
+
+#define PORT_READ_LINE_DEVICE_MEMBER(_device, _class, _member) \
+ curfield->read = input_field_read_delegate(&ioport_read_line_wrapper<_class, &_class::_member>, #_class "::" #_member, (_class *)NULL); \
+ curfield->read_param = NULL; \
+ curfield->read_device = _device;
+
+/* output device handler */
+#define PORT_WRITE_LINE_DEVICE(_device, _write_line_device) \
+ curfield->write = input_field_write_delegate(&ioport_write_line_wrapper<_write_line_device>, #_write_line_device, (device_t *)NULL); \
+ curfield->write_param = NULL; \
+ curfield->write_device = _device;
+
+#define PORT_WRITE_LINE_DEVICE_MEMBER(_device, _class, _member) \
+ curfield->write = input_field_write_delegate(&ioport_write_line_wrapper<_class, &_class::_member>, #_class "::" #_member, (_class *)NULL); \
+ curfield->write_param = NULL; \
+ curfield->write_device = _device;
+
+/* dip switch definition */
+#define PORT_DIPNAME(_mask, _default, _name) \
+ curfield = ioconfig_alloc_field(*curport, IPT_DIPSWITCH, (_default), (_mask), (_name)); \
+ cursetting = NULL;
+
+#define PORT_DIPSETTING(_default, _name) \
+ cursetting = ioconfig_alloc_setting(*curfield, (_default) & curfield->mask, (_name));
+
+/* physical location, of the form: name:[!]sw,[name:][!]sw,... */
+/* note that these are specified LSB-first */
+#define PORT_DIPLOCATION(_location) \
+ diplocation_list_alloc(*curfield, _location, errorbuf);
+
+/* conditionals for dip switch settings */
+#define PORT_CONDITION(_tag, _mask, _condition, _value) \
+{ \
+ input_condition &condition = (cursetting != NULL) ? cursetting->condition : curfield->condition; \
+ condition.tag = (_tag); \
+ condition.mask = (_mask); \
+ condition.condition = (_condition); \
+ condition.value = (_value); \
+}
+
+/* analog adjuster definition */
+#define PORT_ADJUSTER(_default, _name) \
+ curfield = ioconfig_alloc_field(*curport, IPT_ADJUSTER, (_default), 0xff, (_name)); \
+ cursetting = NULL; \
+
+/* config definition */
+#define PORT_CONFNAME(_mask, _default, _name) \
+ curfield = ioconfig_alloc_field(*curport, IPT_CONFIG, (_default), (_mask), (_name)); \
+ cursetting = NULL; \
+
+#define PORT_CONFSETTING(_default, _name) \
+ cursetting = ioconfig_alloc_setting(*curfield, (_default) & curfield->mask, (_name));
+
+/* keyboard chars */
+#define PORT_CHAR(_ch) \
+ ioconfig_field_add_char(*curfield, _ch, errorbuf);
+
+
+/* name of table */
+#define DEVICE_INPUT_DEFAULTS_NAME(_name) device_iptdef_##_name
+
+#define device_iptdef_0 NULL
+#define device_iptdef___null NULL
+
+/* start of table */
+#define DEVICE_INPUT_DEFAULTS_START(_name) \
+ const input_device_default DEVICE_INPUT_DEFAULTS_NAME(_name)[] = {
+
+/* end of table */
+#define DEVICE_INPUT_DEFAULTS(_tag,_mask,_defval) \
+ { _tag ,_mask, _defval }, \
+
+/* end of table */
+#define DEVICE_INPUT_DEFAULTS_END \
+ {NULL,0,0} };
+
+/***************************************************************************
+ HELPER MACROS
+***************************************************************************/
+
+#define PORT_DIPUNUSED_DIPLOC(_mask, _default, _diploc) \
+ PORT_SPECIAL_ONOFF_DIPLOC(_mask, _default, Unused, _diploc)
+
+#define PORT_DIPUNUSED(_mask, _default) \
+ PORT_SPECIAL_ONOFF(_mask, _default, Unused)
+
+#define PORT_DIPUNKNOWN_DIPLOC(_mask, _default, _diploc) \
+ PORT_SPECIAL_ONOFF_DIPLOC(_mask, _default, Unknown, _diploc)
+
+#define PORT_DIPUNKNOWN(_mask, _default) \
+ PORT_SPECIAL_ONOFF(_mask, _default, Unknown)
+
+#define PORT_SERVICE_DIPLOC(_mask, _default, _diploc) \
+ PORT_SPECIAL_ONOFF_DIPLOC(_mask, _default, Service_Mode, _diploc)
+
+#define PORT_SERVICE(_mask, _default) \
+ PORT_SPECIAL_ONOFF(_mask, _default, Service_Mode)
+
+#define PORT_SERVICE_NO_TOGGLE(_mask, _default) \
+ PORT_BIT( _mask, _mask & _default, IPT_SERVICE ) PORT_NAME( DEF_STR( Service_Mode ))
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+
+/* ----- core system management ----- */
+
+/* initialize the input ports, processing the given token list */
+time_t input_port_init(running_machine &machine);
+
+
+
+/* ----- port configurations ----- */
+
+/* initialize an input port list structure and allocate ports according to the given tokens */
+void input_port_list_init(device_t &device, ioport_list &portlist, astring &errorbuf);
+
+/* return the field that matches the given tag and mask */
+const input_field_config *input_field_by_tag_and_mask(const ioport_list &portlist, const char *tag, input_port_value mask);
+
+
+
+/* ----- accessors for input types ----- */
+
+/* return TRUE if the given type represents an analog control */
+int input_type_is_analog(int type);
+
+/* return the name for the given type/player */
+const char *input_type_name(running_machine &machine, int type, int player);
+
+/* return the group for the given type/player */
+int input_type_group(running_machine &machine, int type, int player);
+
+/* return the global input mapping sequence for the given type/player */
+const input_seq &input_type_seq(running_machine &machine, int type, int player, input_seq_type seqtype);
+
+/* change the global input sequence for the given type/player */
+void input_type_set_seq(running_machine &machine, int type, int player, input_seq_type seqtype, const input_seq *newseq);
+
+/* return TRUE if the sequence for the given input type/player is pressed */
+int input_type_pressed(running_machine &machine, int type, int player);
+
+/* return the list of default mappings */
+const simple_list<input_type_entry> &input_type_list(running_machine &machine);
+
+
+
+/* ----- accessors for input fields ----- */
+
+/* return the expanded string name of the field */
+const char *input_field_name(const input_field_config *field);
+
+/* return the input sequence for the given input field */
+const input_seq &input_field_seq(const input_field_config *field, input_seq_type seqtype);
+
+/* return the current settings for the given input field */
+void input_field_get_user_settings(const input_field_config *field, input_field_user_settings *settings);
+
+/* modify the current settings for the given input field */
+void input_field_set_user_settings(const input_field_config *field, const input_field_user_settings *settings);
+
+/* return the expanded setting name for a field */
+const char *input_field_setting_name(const input_field_config *field);
+
+/* return TRUE if the given field has a "previous" setting */
+int input_field_has_previous_setting(const input_field_config *field);
+
+/* select the previous item for a DIP switch or configuration field */
+void input_field_select_previous_setting(const input_field_config *field);
+
+/* return TRUE if the given field has a "next" setting */
+int input_field_has_next_setting(const input_field_config *field);
+
+/* select the next item for a DIP switch or configuration field */
+void input_field_select_next_setting(const input_field_config *field);
+
+
+/* ----- port checking ----- */
+
+/* return whether an input port exists */
+bool input_port_exists(running_machine &machine, const char *tag);
+
+/* return a bitmask of which bits of an input port are active (i.e. not unused or unknown) */
+input_port_value input_port_active(running_machine &machine, const char *tag);
+
+/* return a bitmask of which bits of an input port are active (i.e. not unused or unknown), or a default value if the port does not exist */
+input_port_value input_port_active_safe(running_machine &machine, const char *tag, input_port_value defvalue);
+
+
+/* ----- port reading ----- */
+
+/* return the value of an input port */
+input_port_value input_port_read_direct(const input_port_config *port);
+
+/* return the value of an input port specified by tag */
+input_port_value input_port_read(running_machine &machine, const char *tag);
+
+/* return the value of a device input port specified by tag */
+input_port_value input_port_read(device_t *device, const char *tag);
+
+/* return the value of an input port specified by tag, or a default value if the port does not exist */
+input_port_value input_port_read_safe(running_machine &machine, const char *tag, input_port_value defvalue);
+
+/* return the extracted crosshair values for the given player */
+int input_port_get_crosshair_position(running_machine &machine, int player, float *x, float *y);
+
+/* force an update to the input port values based on current conditions */
+void input_port_update_defaults(running_machine &machine);
+
+
+
+/* ----- port writing ----- */
+
+/* write a value to a port */
+void input_port_write_direct(const input_port_config *port, input_port_value value, input_port_value mask);
+
+/* write a value to a port specified by tag */
+void input_port_write(running_machine &machine, const char *tag, input_port_value value, input_port_value mask);
+
+/* write a value to a port, ignore if the port does not exist */
+void input_port_write_safe(running_machine &machine, const char *tag, input_port_value value, input_port_value mask);
+
+
+
+/* ----- misc helper functions ----- */
+
+/* return the TRUE if the given condition attached is true */
+int input_condition_true(running_machine &machine, const input_condition *condition,device_t &owner);
+
+/* convert an input_port_token to a default string */
+const char *input_port_string_from_token(const char *token);
+
+/* return TRUE if machine use full keyboard emulation */
+int input_machine_has_keyboard(running_machine &machine);
+
+/* these are called by the core; they should not be called from FEs */
+void inputx_init(running_machine &machine);
+
+/* called by drivers to setup natural keyboard support */
+void inputx_setup_natural_keyboard(running_machine &machine,
+ int (*queue_chars)(running_machine &machine, const unicode_char *text, size_t text_len),
+ int (*accept_char)(running_machine &machine, unicode_char ch),
+ int (*charqueue_empty)(running_machine &machine));
+
+/* validity checks */
+int validate_natural_keyboard_statics(void);
+
+/* these can be called from FEs */
+int inputx_can_post(running_machine &machine);
+
+/* various posting functions; can be called from FEs */
+void inputx_postc(running_machine &machine, unicode_char ch);
+void inputx_post_utf8(running_machine &machine, const char *text);
+void inputx_post_utf8_rate(running_machine &machine, const char *text, attotime rate);
+int inputx_is_posting(running_machine &machine);
+
+/* miscellaneous functions */
+int input_classify_port(const input_field_config *field);
+int input_has_input_class(running_machine &machine, int inputclass);
+int input_player_number(const input_field_config *field);
+int input_count_players(running_machine &machine);
+
+
+inline running_machine &input_field_config::machine() const
+{
+ return m_port.machine();
+}
+
+
+// temporary construction helpers
+void field_config_insert(input_field_config &newfield, input_port_value &disallowedbits, astring &errorbuf);
+void diplocation_list_alloc(input_field_config &field, const char *location, astring &errorbuf);
+
+
+input_port_config *ioconfig_alloc_port(ioport_list &portlist, device_t &device, const char *tag);
+input_port_config *ioconfig_modify_port(ioport_list &portlist, device_t &device, const char *tag);
+input_field_config *ioconfig_alloc_field(input_port_config &port, int type, input_port_value defval, input_port_value mask, const char *name = NULL);
+input_field_config *ioconfig_alloc_onoff(input_port_config &port, const char *name, input_port_value defval, input_port_value mask, const char *diplocation, astring &errorbuf);
+input_setting_config *ioconfig_alloc_setting(input_field_config &field, input_port_value value, const char *name);
+void ioconfig_field_add_char(input_field_config &field, unicode_char ch, astring &errorbuf);
+void ioconfig_add_code(input_field_config &field, int which, input_code code);
+
+#endif /* __INPTPORT_H__ */
diff --git a/trunk/src/emu/layout/dualhovu.lay b/trunk/src/emu/layout/dualhovu.lay
new file mode 100644
index 00000000000..d4be6a75e8e
--- /dev/null
+++ b/trunk/src/emu/layout/dualhovu.lay
@@ -0,0 +1,72 @@
+<?xml version="1.0"?>
+<mamelayout version="2">
+ <view name="Screen 0 Standard (4:3)">
+ <screen index="0">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </screen>
+ </view>
+
+ <view name="Screen 1 Standard (4:3)">
+ <screen index="1">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </screen>
+ </view>
+
+ <view name="Screen 0 Pixel Aspect (~scr0nativexaspect~:~scr0nativeyaspect~)">
+ <screen index="0">
+ <bounds left="0" top="0" right="~scr0width~" bottom="~scr0height~" />
+ </screen>
+ </view>
+
+ <view name="Screen 1 Pixel Aspect (~scr1nativexaspect~:~scr1nativeyaspect~)">
+ <screen index="1">
+ <bounds left="0" top="0" right="~scr1width~" bottom="~scr1height~" />
+ </screen>
+ </view>
+
+ <view name="Dual Over-Under">
+ <screen index="0">
+ <bounds x="0" y="-3.03" width="4" height="3" />
+ </screen>
+ <screen index="1">
+ <bounds x="0" y="0" width="4" height="3" />
+ </screen>
+ </view>
+
+ <view name="Dual Over-Under (Gapless)">
+ <screen index="0">
+ <bounds x="0" y="-3" width="4" height="3" />
+ </screen>
+ <screen index="1">
+ <bounds x="0" y="0" width="4" height="3" />
+ </screen>
+ </view>
+
+ <view name="Dual Side-by-Side">
+ <screen index="0">
+ <bounds x="0" y="0" width="4" height="3" />
+ </screen>
+ <screen index="1">
+ <bounds x="4.03" y="0" width="4" height="3" />
+ </screen>
+ </view>
+
+ <view name="Dual Side-by-Side (Gapless)">
+ <screen index="0">
+ <bounds x="0" y="0" width="4" height="3" />
+ </screen>
+ <screen index="1">
+ <bounds x="4" y="0" width="4" height="3" />
+ </screen>
+ </view>
+
+ <view name="Cocktail">
+ <screen index="1">
+ <bounds x="0" y="-3.03" width="4" height="3" />
+ <orientation rotate="180" />
+ </screen>
+ <screen index="0">
+ <bounds x="0" y="0" width="4" height="3" />
+ </screen>
+ </view>
+</mamelayout>
diff --git a/trunk/src/emu/layout/dualhsxs.lay b/trunk/src/emu/layout/dualhsxs.lay
new file mode 100644
index 00000000000..37b4f7b9499
--- /dev/null
+++ b/trunk/src/emu/layout/dualhsxs.lay
@@ -0,0 +1,72 @@
+<?xml version="1.0"?>
+<mamelayout version="2">
+ <view name="Screen 0 Standard (4:3)">
+ <screen index="0">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </screen>
+ </view>
+
+ <view name="Screen 1 Standard (4:3)">
+ <screen index="1">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </screen>
+ </view>
+
+ <view name="Screen 0 Pixel Aspect (~scr0nativexaspect~:~scr0nativeyaspect~)">
+ <screen index="0">
+ <bounds left="0" top="0" right="~scr0width~" bottom="~scr0height~" />
+ </screen>
+ </view>
+
+ <view name="Screen 1 Pixel Aspect (~scr1nativexaspect~:~scr1nativeyaspect~)">
+ <screen index="1">
+ <bounds left="0" top="0" right="~scr1width~" bottom="~scr1height~" />
+ </screen>
+ </view>
+
+ <view name="Dual Side-by-Side">
+ <screen index="0">
+ <bounds x="0" y="0" width="4" height="3" />
+ </screen>
+ <screen index="1">
+ <bounds x="4.03" y="0" width="4" height="3" />
+ </screen>
+ </view>
+
+ <view name="Dual Side-by-Side (Gapless)">
+ <screen index="0">
+ <bounds x="0" y="0" width="4" height="3" />
+ </screen>
+ <screen index="1">
+ <bounds x="4" y="0" width="4" height="3" />
+ </screen>
+ </view>
+
+ <view name="Dual Over-Under">
+ <screen index="0">
+ <bounds x="0" y="0" width="4" height="3" />
+ </screen>
+ <screen index="1">
+ <bounds x="0" y="-3.03" width="4" height="3" />
+ </screen>
+ </view>
+
+ <view name="Dual Over-Under (Gapless)">
+ <screen index="0">
+ <bounds x="0" y="0" width="4" height="3" />
+ </screen>
+ <screen index="1">
+ <bounds x="0" y="-3" width="4" height="3" />
+ </screen>
+ </view>
+
+ <view name="Cocktail">
+ <screen index="1">
+ <bounds x="0" y="-3.03" width="4" height="3" />
+ <orientation rotate="180" />
+ </screen>
+ <screen index="0">
+ <bounds x="0" y="0" width="4" height="3" />
+ </screen>
+ </view>
+</mamelayout>
diff --git a/trunk/src/emu/layout/dualhuov.lay b/trunk/src/emu/layout/dualhuov.lay
new file mode 100644
index 00000000000..1eced2b16ff
--- /dev/null
+++ b/trunk/src/emu/layout/dualhuov.lay
@@ -0,0 +1,72 @@
+<?xml version="1.0"?>
+<mamelayout version="2">
+ <view name="Screen 0 Standard (4:3)">
+ <screen index="0">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </screen>
+ </view>
+
+ <view name="Screen 1 Standard (4:3)">
+ <screen index="1">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </screen>
+ </view>
+
+ <view name="Screen 0 Pixel Aspect (~scr0nativexaspect~:~scr0nativeyaspect~)">
+ <screen index="0">
+ <bounds left="0" top="0" right="~scr0width~" bottom="~scr0height~" />
+ </screen>
+ </view>
+
+ <view name="Screen 1 Pixel Aspect (~scr1nativexaspect~:~scr1nativeyaspect~)">
+ <screen index="1">
+ <bounds left="0" top="0" right="~scr1width~" bottom="~scr1height~" />
+ </screen>
+ </view>
+
+ <view name="Dual Under-Over">
+ <screen index="1">
+ <bounds x="0" y="-3.03" width="4" height="3" />
+ </screen>
+ <screen index="0">
+ <bounds x="0" y="0" width="4" height="3" />
+ </screen>
+ </view>
+
+ <view name="Dual Under-Over (Gapless)">
+ <screen index="1">
+ <bounds x="0" y="-3" width="4" height="3" />
+ </screen>
+ <screen index="0">
+ <bounds x="0" y="0" width="4" height="3" />
+ </screen>
+ </view>
+
+ <view name="Dual Side-by-Side">
+ <screen index="1">
+ <bounds x="0" y="0" width="4" height="3" />
+ </screen>
+ <screen index="0">
+ <bounds x="4.03" y="0" width="4" height="3" />
+ </screen>
+ </view>
+
+ <view name="Dual Side-by-Side (Gapless)">
+ <screen index="1">
+ <bounds x="0" y="0" width="4" height="3" />
+ </screen>
+ <screen index="0">
+ <bounds x="4" y="0" width="4" height="3" />
+ </screen>
+ </view>
+
+ <view name="Cocktail">
+ <screen index="0">
+ <bounds x="0" y="-3.03" width="4" height="3" />
+ <orientation rotate="180" />
+ </screen>
+ <screen index="1">
+ <bounds x="0" y="0" width="4" height="3" />
+ </screen>
+ </view>
+</mamelayout>
diff --git a/trunk/src/emu/layout/ho20ffff.lay b/trunk/src/emu/layout/ho20ffff.lay
new file mode 100644
index 00000000000..03e947099c5
--- /dev/null
+++ b/trunk/src/emu/layout/ho20ffff.lay
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<mamelayout version="2">
+ <element name="overlay">
+ <rect>
+ <bounds left="0" top="0" right="1" bottom="1" />
+ <color red="0.125" green="1.0" blue="1.0" />
+ </rect>
+ </element>
+
+ <view name="Color Overlay">
+ <screen index="0">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </screen>
+ <overlay element="overlay">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </overlay>
+ </view>
+</mamelayout>
diff --git a/trunk/src/emu/layout/ho2eff2e.lay b/trunk/src/emu/layout/ho2eff2e.lay
new file mode 100644
index 00000000000..c530ff1eb6f
--- /dev/null
+++ b/trunk/src/emu/layout/ho2eff2e.lay
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<mamelayout version="2">
+ <element name="overlay">
+ <rect>
+ <bounds left="0" top="0" right="1" bottom="1" />
+ <color red="0.180" green="1" blue="0.180" />
+ </rect>
+ </element>
+
+ <view name="Color Overlay">
+ <screen index="0">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </screen>
+ <overlay element="overlay">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </overlay>
+ </view>
+</mamelayout>
diff --git a/trunk/src/emu/layout/ho4f893d.lay b/trunk/src/emu/layout/ho4f893d.lay
new file mode 100644
index 00000000000..7e073813f9d
--- /dev/null
+++ b/trunk/src/emu/layout/ho4f893d.lay
@@ -0,0 +1,21 @@
+<mamelayout version="2">
+
+ <element name="overlay">
+ <rect>
+ <bounds left="0" top="0" right="4" bottom="3" />
+ <color red=".310" green=".537" blue=".239" />
+ </rect>
+ </element>
+
+
+ <view name="Color Overlay">
+ <screen index="0">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </screen>
+ <overlay element="overlay">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </overlay>
+ </view>
+
+
+</mamelayout>
diff --git a/trunk/src/emu/layout/ho88ffff.lay b/trunk/src/emu/layout/ho88ffff.lay
new file mode 100644
index 00000000000..711dc65b96a
--- /dev/null
+++ b/trunk/src/emu/layout/ho88ffff.lay
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<mamelayout version="2">
+ <element name="overlay">
+ <rect>
+ <bounds left="0" top="0" right="1" bottom="1" />
+ <color red="0.5333" green="1.0" blue="1.0" />
+ </rect>
+ </element>
+
+ <view name="Color Overlay">
+ <screen index="0">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </screen>
+ <overlay element="overlay">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </overlay>
+ </view>
+</mamelayout>
diff --git a/trunk/src/emu/layout/hoa0a0ff.lay b/trunk/src/emu/layout/hoa0a0ff.lay
new file mode 100644
index 00000000000..dc1ccafde5a
--- /dev/null
+++ b/trunk/src/emu/layout/hoa0a0ff.lay
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<mamelayout version="2">
+ <element name="overlay">
+ <rect>
+ <bounds left="0" top="0" right="1" bottom="1" />
+ <color red="0.625" green="0.625" blue="1" />
+ </rect>
+ </element>
+
+ <view name="Color Overlay">
+ <screen index="0">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </screen>
+ <overlay element="overlay">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </overlay>
+ </view>
+</mamelayout>
diff --git a/trunk/src/emu/layout/hoffe457.lay b/trunk/src/emu/layout/hoffe457.lay
new file mode 100644
index 00000000000..304801126bf
--- /dev/null
+++ b/trunk/src/emu/layout/hoffe457.lay
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<mamelayout version="2">
+ <element name="overlay">
+ <rect>
+ <bounds left="0" top="0" right="1" bottom="1" />
+ <color red="1.0" green="0.894" blue="0.341" />
+ </rect>
+ </element>
+
+ <view name="Color Overlay">
+ <screen index="0">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </screen>
+ <overlay element="overlay">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </overlay>
+ </view>
+</mamelayout>
diff --git a/trunk/src/emu/layout/hoffff20.lay b/trunk/src/emu/layout/hoffff20.lay
new file mode 100644
index 00000000000..dea4ab2b0f7
--- /dev/null
+++ b/trunk/src/emu/layout/hoffff20.lay
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<mamelayout version="2">
+ <element name="overlay">
+ <rect>
+ <bounds left="0" top="0" right="1" bottom="1" />
+ <color red="1.0" green="1.0" blue="0.125" />
+ </rect>
+ </element>
+
+ <view name="Color Overlay">
+ <screen index="0">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </screen>
+ <overlay element="overlay">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </overlay>
+ </view>
+</mamelayout>
diff --git a/trunk/src/emu/layout/horizont.lay b/trunk/src/emu/layout/horizont.lay
new file mode 100644
index 00000000000..908804832af
--- /dev/null
+++ b/trunk/src/emu/layout/horizont.lay
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<mamelayout version="2">
+ <view name="Standard (4:3)">
+ <screen index="0">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </screen>
+ </view>
+
+ <view name="Pixel Aspect (~scr0nativexaspect~:~scr0nativeyaspect~)">
+ <screen index="0">
+ <bounds left="0" top="0" right="~scr0width~" bottom="~scr0height~" />
+ </screen>
+ </view>
+
+ <view name="Cocktail">
+ <screen index="0">
+ <bounds x="0" y="-3.03" width="4" height="3" />
+ <orientation rotate="180" />
+ </screen>
+ <screen index="0">
+ <bounds x="0" y="0" width="4" height="3" />
+ </screen>
+ </view>
+</mamelayout>
diff --git a/trunk/src/emu/layout/lcd.lay b/trunk/src/emu/layout/lcd.lay
new file mode 100644
index 00000000000..8de4141324a
--- /dev/null
+++ b/trunk/src/emu/layout/lcd.lay
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<mamelayout version="2">
+ <view name="LCD with square pixels">
+ <screen index="0">
+ <bounds left="0" top="0" right="~scr0width~" bottom="~scr0height~" />
+ </screen>
+ </view>
+</mamelayout>
diff --git a/trunk/src/emu/layout/lcd_rot.lay b/trunk/src/emu/layout/lcd_rot.lay
new file mode 100644
index 00000000000..95176d24a06
--- /dev/null
+++ b/trunk/src/emu/layout/lcd_rot.lay
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<mamelayout version="2">
+ <view name="LCD with square pixels">
+ <screen index="0">
+ <bounds left="0" top="0" right="~scr0height~" bottom="~scr0width~" />
+ </screen>
+ </view>
+</mamelayout>
diff --git a/trunk/src/emu/layout/noscreens.lay b/trunk/src/emu/layout/noscreens.lay
new file mode 100644
index 00000000000..fe0587f1f60
--- /dev/null
+++ b/trunk/src/emu/layout/noscreens.lay
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<mamelayout version="2">
+ <element name="background">
+ <rect>
+ <bounds left="0" top="0" right="1" bottom="1" />
+ <color red="0.0" green="0.0" blue="0.0" />
+ </rect>
+ </element>
+ <element name="warning">
+ <text string="No screens attached to the system">
+ <color red="1.0" green="0.5" blue="0.5" />
+ </text>
+ </element>
+ <view name="No screens attached">
+ <bezel element="background">
+ <bounds left="0" top="0" right="280" bottom="150" />
+ </bezel>
+ <bezel name="warning_txt" element="warning">
+ <bounds left="50" right="230" top="50" bottom="65" />
+ </bezel>
+ </view>
+</mamelayout>
diff --git a/trunk/src/emu/layout/quadhsxs.lay b/trunk/src/emu/layout/quadhsxs.lay
new file mode 100644
index 00000000000..b07a04e7b11
--- /dev/null
+++ b/trunk/src/emu/layout/quadhsxs.lay
@@ -0,0 +1,110 @@
+<?xml version="1.0"?>
+<mamelayout version="2">
+ <view name="Screen 0 Standard (4:3)">
+ <screen index="0">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </screen>
+ </view>
+
+ <view name="Screen 1 Standard (4:3)">
+ <screen index="1">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </screen>
+ </view>
+
+ <view name="Screen 2 Standard (4:3)">
+ <screen index="2">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </screen>
+ </view>
+
+ <view name="Screen 3 Standard (4:3)">
+ <screen index="3">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </screen>
+ </view>
+
+ <view name="Screen 0 Pixel Aspect (~scr0nativexaspect~:~scr0nativeyaspect~)">
+ <screen index="0">
+ <bounds left="0" top="0" right="~scr0width~" bottom="~scr0height~" />
+ </screen>
+ </view>
+
+ <view name="Screen 1 Pixel Aspect (~scr1nativexaspect~:~scr1nativeyaspect~)">
+ <screen index="1">
+ <bounds left="0" top="0" right="~scr1width~" bottom="~scr1height~" />
+ </screen>
+ </view>
+
+ <view name="Screen 2 Pixel Aspect (~scr2nativexaspect~:~scr2nativeyaspect~)">
+ <screen index="2">
+ <bounds left="0" top="0" right="~scr2width~" bottom="~scr2height~" />
+ </screen>
+ </view>
+
+ <view name="Screen 3 Pixel Aspect (~scr3nativexaspect~:~scr3nativeyaspect~)">
+ <screen index="3">
+ <bounds left="0" top="0" right="~scr3width~" bottom="~scr3height~" />
+ </screen>
+ </view>
+
+ <view name="Quad Side-by-Side">
+ <screen index="0">
+ <bounds x="0" y="0" width="4" height="3" />
+ </screen>
+ <screen index="1">
+ <bounds x="4.03" y="0" width="4" height="3" />
+ </screen>
+ <screen index="2">
+ <bounds x="8.06" y="0" width="4" height="3" />
+ </screen>
+ <screen index="3">
+ <bounds x="12.09" y="0" width="4" height="3" />
+ </screen>
+ </view>
+
+ <view name="Quad Side-by-Side (Gapless)">
+ <screen index="0">
+ <bounds x="0" y="0" width="4" height="3" />
+ </screen>
+ <screen index="1">
+ <bounds x="4" y="0" width="4" height="3" />
+ </screen>
+ <screen index="2">
+ <bounds x="8" y="0" width="4" height="3" />
+ </screen>
+ <screen index="3">
+ <bounds x="12" y="0" width="4" height="3" />
+ </screen>
+ </view>
+
+ <view name="Quad 2 by 2">
+ <screen index="0">
+ <bounds x="0" y="0" width="4" height="3" />
+ </screen>
+ <screen index="1">
+ <bounds x="4.03" y="0" width="4" height="3" />
+ </screen>
+ <screen index="2">
+ <bounds x="0" y="3.03" width="4" height="3" />
+ </screen>
+ <screen index="3">
+ <bounds x="4.03" y="3.03" width="4" height="3" />
+ </screen>
+ </view>
+
+ <view name="Quad 2 by 2 (Gapless)">
+ <screen index="0">
+ <bounds x="0" y="0" width="4" height="3" />
+ </screen>
+ <screen index="1">
+ <bounds x="4" y="0" width="4" height="3" />
+ </screen>
+ <screen index="2">
+ <bounds x="0" y="3" width="4" height="3" />
+ </screen>
+ <screen index="3">
+ <bounds x="4" y="3" width="4" height="3" />
+ </screen>
+ </view>
+</mamelayout>
diff --git a/trunk/src/emu/layout/snap.lay b/trunk/src/emu/layout/snap.lay
new file mode 100644
index 00000000000..76dfb93d60c
--- /dev/null
+++ b/trunk/src/emu/layout/snap.lay
@@ -0,0 +1,50 @@
+<?xml version="1.0"?>
+<mamelayout version="2">
+ <view name="s0">
+ <screen index="0">
+ <bounds left="0" top="0" right="1" bottom="1" />
+ </screen>
+ </view>
+
+ <view name="s1">
+ <screen index="1">
+ <bounds left="0" top="0" right="1" bottom="1" />
+ </screen>
+ </view>
+
+ <view name="s2">
+ <screen index="2">
+ <bounds left="0" top="0" right="1" bottom="1" />
+ </screen>
+ </view>
+
+ <view name="s3">
+ <screen index="3">
+ <bounds left="0" top="0" right="1" bottom="1" />
+ </screen>
+ </view>
+
+ <view name="s4">
+ <screen index="4">
+ <bounds left="0" top="0" right="1" bottom="1" />
+ </screen>
+ </view>
+
+ <view name="s5">
+ <screen index="5">
+ <bounds left="0" top="0" right="1" bottom="1" />
+ </screen>
+ </view>
+
+ <view name="s6">
+ <screen index="6">
+ <bounds left="0" top="0" right="1" bottom="1" />
+ </screen>
+ </view>
+
+ <view name="s7">
+ <screen index="7">
+ <bounds left="0" top="0" right="1" bottom="1" />
+ </screen>
+ </view>
+</mamelayout>
diff --git a/trunk/src/emu/layout/triphsxs.lay b/trunk/src/emu/layout/triphsxs.lay
new file mode 100644
index 00000000000..fe0c9237273
--- /dev/null
+++ b/trunk/src/emu/layout/triphsxs.lay
@@ -0,0 +1,62 @@
+<?xml version="1.0"?>
+<mamelayout version="2">
+ <view name="Screen 0 Standard (4:3)">
+ <screen index="0">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </screen>
+ </view>
+
+ <view name="Screen 1 Standard (4:3)">
+ <screen index="1">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </screen>
+ </view>
+
+ <view name="Screen 2 Standard (4:3)">
+ <screen index="2">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </screen>
+ </view>
+
+ <view name="Screen 0 Pixel Aspect (~scr0nativexaspect~:~scr0nativeyaspect~)">
+ <screen index="0">
+ <bounds left="0" top="0" right="~scr0width~" bottom="~scr0height~" />
+ </screen>
+ </view>
+
+ <view name="Screen 1 Pixel Aspect (~scr1nativexaspect~:~scr1nativeyaspect~)">
+ <screen index="1">
+ <bounds left="0" top="0" right="~scr1width~" bottom="~scr1height~" />
+ </screen>
+ </view>
+
+ <view name="Screen 2 Pixel Aspect (~scr2nativexaspect~:~scr2nativeyaspect~)">
+ <screen index="2">
+ <bounds left="0" top="0" right="~scr2width~" bottom="~scr2height~" />
+ </screen>
+ </view>
+
+ <view name="Triple Side-by-Side">
+ <screen index="0">
+ <bounds x="0" y="0" width="4" height="3" />
+ </screen>
+ <screen index="1">
+ <bounds x="4.03" y="0" width="4" height="3" />
+ </screen>
+ <screen index="2">
+ <bounds x="8.06" y="0" width="4" height="3" />
+ </screen>
+ </view>
+
+ <view name="Triple Side-by-Side (Gapless)">
+ <screen index="0">
+ <bounds x="0" y="0" width="4" height="3" />
+ </screen>
+ <screen index="1">
+ <bounds x="4" y="0" width="4" height="3" />
+ </screen>
+ <screen index="2">
+ <bounds x="8" y="0" width="4" height="3" />
+ </screen>
+ </view>
+</mamelayout>
diff --git a/trunk/src/emu/layout/vertical.lay b/trunk/src/emu/layout/vertical.lay
new file mode 100644
index 00000000000..2d66df317f8
--- /dev/null
+++ b/trunk/src/emu/layout/vertical.lay
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<mamelayout version="2">
+ <view name="Standard (3:4)">
+ <screen index="0">
+ <bounds left="0" top="0" right="3" bottom="4" />
+ </screen>
+ </view>
+
+ <view name="Pixel Aspect (~scr0nativeyaspect~:~scr0nativexaspect~)">
+ <screen index="0">
+ <bounds left="0" top="0" right="~scr0height~" bottom="~scr0width~" />
+ </screen>
+ </view>
+
+ <view name="Cocktail">
+ <screen index="0">
+ <bounds x="-3.03" y="0" width="3" height="4" />
+ <orientation rotate="180" />
+ </screen>
+ <screen index="0">
+ <bounds x="0" y="0" width="3" height="4" />
+ </screen>
+ </view>
+
+ <element name="dbgdis">
+ </element>
+
+ <view name="Debug">
+ <screen index="0">
+ <bounds left="0" top="0" right="3" bottom="4" />
+ </screen>
+ <bezel element="dbgdis">
+ <bounds x="-2.5" y="0" width="8" height="6" />
+ </bezel>
+ </view>
+
+</mamelayout>
diff --git a/trunk/src/emu/layout/voffff20.lay b/trunk/src/emu/layout/voffff20.lay
new file mode 100644
index 00000000000..72ed5d25ee3
--- /dev/null
+++ b/trunk/src/emu/layout/voffff20.lay
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<mamelayout version="2">
+ <element name="overlay">
+ <rect>
+ <bounds left="0" top="0" right="1" bottom="1" />
+ <color red="1.0" green="1.0" blue="0.125" />
+ </rect>
+ </element>
+
+ <view name="Color Overlay">
+ <screen index="0">
+ <bounds left="0" top="0" right="3" bottom="4" />
+ </screen>
+ <overlay element="overlay">
+ <bounds left="0" top="0" right="3" bottom="4" />
+ </overlay>
+ </view>
+</mamelayout>
diff --git a/trunk/src/emu/machine.c b/trunk/src/emu/machine.c
new file mode 100644
index 00000000000..840a17591a0
--- /dev/null
+++ b/trunk/src/emu/machine.c
@@ -0,0 +1,1241 @@
+/***************************************************************************
+
+ machine.c
+
+ Controls execution of the core MAME 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.
+
+****************************************************************************
+
+ Since there has been confusion in the past over the order of
+ initialization and other such things, here it is, all spelled out
+ as of January, 2008:
+
+ main()
+ - does platform-specific init
+ - calls mame_execute() [mame.c]
+
+ mame_execute() [mame.c]
+ - calls mame_validitychecks() [validity.c] to perform validity checks on all compiled drivers
+ - begins resource tracking (level 1)
+ - calls create_machine [mame.c] to initialize the running_machine structure
+ - calls init_machine() [mame.c]
+
+ init_machine() [mame.c]
+ - calls fileio_init() [fileio.c] to initialize file I/O info
+ - calls config_init() [config.c] to initialize configuration system
+ - calls input_init() [input.c] to initialize the input system
+ - calls output_init() [output.c] to initialize the output system
+ - calls state_init() [state.c] to initialize save state system
+ - calls state_save_allow_registration() [state.c] to allow registrations
+ - calls palette_init() [palette.c] to initialize palette system
+ - calls render_init() [render.c] to initialize the rendering system
+ - calls ui_init() [ui.c] to initialize the user interface
+ - calls generic_machine_init() [machine/generic.c] to initialize generic machine structures
+ - calls generic_video_init() [video/generic.c] to initialize generic video structures
+ - calls generic_sound_init() [audio/generic.c] to initialize generic sound structures
+ - calls timer_init() [timer.c] to reset the timer system
+ - calls osd_init() [osdepend.h] to do platform-specific initialization
+ - calls input_port_init() [inptport.c] to set up the input ports
+ - calls rom_init() [romload.c] to load the game's ROMs
+ - calls memory_init() [memory.c] to process the game's memory maps
+ - calls watchdog_init() [watchdog.c] to initialize the watchdog system
+ - calls the driver's DRIVER_INIT callback
+ - calls device_list_start() [devintrf.c] to start any devices
+ - calls video_init() [video.c] to start the video system
+ - calls tilemap_init() [tilemap.c] to start the tilemap system
+ - calls crosshair_init() [crsshair.c] to configure the crosshairs
+ - calls sound_init() [sound.c] to start the audio system
+ - calls debugger_init() [debugger.c] to set up the debugger
+ - calls the driver's MACHINE_START, SOUND_START, and VIDEO_START callbacks
+ - calls cheat_init() [cheat.c] to initialize the cheat system
+ - calls image_init() [image.c] to initialize the image system
+
+ - calls config_load_settings() [config.c] to load the configuration file
+ - calls nvram_load [machine/generic.c] to load NVRAM
+ - calls ui_display_startup_screens() [ui.c] to display the the startup screens
+ - begins resource tracking (level 2)
+ - calls soft_reset() [mame.c] to reset all systems
+
+ -------------------( at this point, we're up and running )----------------------
+
+ - calls scheduler->timeslice() [schedule.c] over and over until we exit
+ - ends resource tracking (level 2), freeing all auto_mallocs and timers
+ - calls the nvram_save() [machine/generic.c] to save NVRAM
+ - calls config_save_settings() [config.c] to save the game's configuration
+ - calls all registered exit routines [mame.c]
+ - ends resource tracking (level 1), freeing all auto_mallocs and timers
+
+ - exits the program
+
+***************************************************************************/
+
+#include "emu.h"
+#include "emuopts.h"
+#include "osdepend.h"
+#include "config.h"
+#include "debugger.h"
+#include "image.h"
+#include "profiler.h"
+#include "render.h"
+#include "cheat.h"
+#include "ui.h"
+#include "uimenu.h"
+#include "uiinput.h"
+#include "crsshair.h"
+#include "validity.h"
+#include "unzip.h"
+#include "debug/debugcon.h"
+
+#include <time.h>
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// a giant string buffer for temporary strings
+static char giant_string_buffer[65536] = { 0 };
+
+
+
+//**************************************************************************
+// RUNNING MACHINE
+//**************************************************************************
+
+//-------------------------------------------------
+// running_machine - constructor
+//-------------------------------------------------
+
+running_machine::running_machine(const machine_config &_config, osd_interface &osd, bool exit_to_game_select)
+ : firstcpu(NULL),
+ primary_screen(NULL),
+ palette(NULL),
+ pens(NULL),
+ colortable(NULL),
+ shadow_table(NULL),
+ priority_bitmap(NULL),
+ debug_flags(0),
+ memory_data(NULL),
+ palette_data(NULL),
+ tilemap_data(NULL),
+ romload_data(NULL),
+ input_data(NULL),
+ input_port_data(NULL),
+ ui_input_data(NULL),
+ debugcpu_data(NULL),
+ generic_machine_data(NULL),
+ generic_video_data(NULL),
+ generic_audio_data(NULL),
+
+ m_config(_config),
+ m_system(_config.gamedrv()),
+ m_osd(osd),
+ m_regionlist(m_respool),
+ m_save(*this),
+ m_scheduler(*this),
+ m_cheat(NULL),
+ m_render(NULL),
+ m_input(NULL),
+ m_sound(NULL),
+ m_video(NULL),
+ m_debug_view(NULL),
+ m_driver_device(NULL),
+ m_current_phase(MACHINE_PHASE_PREINIT),
+ m_paused(false),
+ m_hard_reset_pending(false),
+ m_exit_pending(false),
+ m_exit_to_game_select(exit_to_game_select),
+ m_new_driver_pending(NULL),
+ m_soft_reset_timer(NULL),
+ m_rand_seed(0x9d14abd7),
+ m_ui_active(false),
+ m_basename(_config.gamedrv().name),
+ m_sample_rate(_config.options().sample_rate()),
+ m_logfile(NULL),
+ m_saveload_schedule(SLS_NONE),
+ m_saveload_schedule_time(attotime::zero),
+ m_saveload_searchpath(NULL),
+ m_logerror_list(m_respool)
+{
+ memset(gfx, 0, sizeof(gfx));
+ memset(&generic, 0, sizeof(generic));
+ memset(&m_base_time, 0, sizeof(m_base_time));
+
+ // set the machine on all devices
+ const_cast<device_list &>(devicelist()).set_machine_all(*this);
+
+ // find the driver device config and tell it which game
+ m_driver_device = device<driver_device>("root");
+ if (m_driver_device == NULL)
+ throw emu_fatalerror("Machine configuration missing driver_device");
+
+ // find devices
+ primary_screen = downcast<screen_device *>(devicelist().first(SCREEN));
+ for (device_t *device = devicelist().first(); device != NULL; device = device->next())
+ if (dynamic_cast<cpu_device *>(device) != NULL)
+ {
+ firstcpu = downcast<cpu_device *>(device);
+ break;
+ }
+
+ // fetch core options
+ if (options().debug())
+ debug_flags = (DEBUG_FLAG_ENABLED | DEBUG_FLAG_CALL_HOOK) | (options().debug_internal() ? 0 : DEBUG_FLAG_OSD_ENABLED);
+}
+
+
+//-------------------------------------------------
+// ~running_machine - destructor
+//-------------------------------------------------
+
+running_machine::~running_machine()
+{
+}
+
+
+//-------------------------------------------------
+// describe_context - return a string describing
+// which device is currently executing and its
+// PC
+//-------------------------------------------------
+
+const char *running_machine::describe_context()
+{
+ device_execute_interface *executing = m_scheduler.currently_executing();
+ if (executing != NULL)
+ {
+ cpu_device *cpu = downcast<cpu_device *>(&executing->device());
+ if (cpu != NULL)
+ m_context.printf("'%s' (%s)", cpu->tag(), core_i64_hex_format(cpu->pc(), cpu->space(AS_PROGRAM)->logaddrchars()));
+ }
+ else
+ m_context.cpy("(no context)");
+
+ return m_context;
+}
+
+
+//-------------------------------------------------
+// start - initialize the emulated machine
+//-------------------------------------------------
+
+void running_machine::start()
+{
+ // initialize basic can't-fail systems here
+ config_init(*this);
+ m_input = auto_alloc(*this, input_manager(*this));
+ output_init(*this);
+ palette_init(*this);
+ m_render = auto_alloc(*this, render_manager(*this));
+ generic_machine_init(*this);
+ generic_sound_init(*this);
+
+ // allocate a soft_reset timer
+ m_soft_reset_timer = m_scheduler.timer_alloc(timer_expired_delegate(FUNC(running_machine::soft_reset), this));
+
+ // init the osd layer
+ m_osd.init(*this);
+
+ // create the video manager
+ m_video = auto_alloc(*this, video_manager(*this));
+ ui_init(*this);
+
+ // initialize the base time (needed for doing record/playback)
+ ::time(&m_base_time);
+
+ // initialize the input system and input ports for the game
+ // this must be done before memory_init in order to allow specifying
+ // callbacks based on input port tags
+ time_t newbase = input_port_init(*this);
+ if (newbase != 0)
+ m_base_time = newbase;
+
+ // intialize UI input
+ ui_input_init(*this);
+
+ // initialize the streams engine before the sound devices start
+ m_sound = auto_alloc(*this, sound_manager(*this));
+
+ // first load ROMs, then populate memory, and finally initialize CPUs
+ // these operations must proceed in this order
+ rom_init(*this);
+ memory_init(*this);
+ watchdog_init(*this);
+
+ // must happen after memory_init because this relies on generic.spriteram
+ generic_video_init(*this);
+
+ // allocate the gfx elements prior to device initialization
+ gfx_init(*this);
+
+ // initialize natural keyboard support
+ inputx_init(*this);
+
+ // initialize image devices
+ image_init(*this);
+ tilemap_init(*this);
+ crosshair_init(*this);
+
+ // initialize the debugger
+ if ((debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ debugger_init(*this);
+
+ // call the game driver's init function
+ // this is where decryption is done and memory maps are altered
+ // so this location in the init order is important
+ ui_set_startup_text(*this, "Initializing...", true);
+
+ // start up the devices
+ const_cast<device_list &>(devicelist()).start_all();
+
+ // if we're coming in with a savegame request, process it now
+ const char *savegame = options().state();
+ if (savegame[0] != 0)
+ schedule_load(savegame);
+
+ // if we're in autosave mode, schedule a load
+ else if (options().autosave() && (m_system.flags & GAME_SUPPORTS_SAVE) != 0)
+ schedule_load("auto");
+
+ // set up the cheat engine
+ m_cheat = auto_alloc(*this, cheat_manager(*this));
+
+ // disallow save state registrations starting here
+ m_save.allow_registration(false);
+}
+
+
+//-------------------------------------------------
+// add_dynamic_device - dynamically add a device
+//-------------------------------------------------
+
+device_t &running_machine::add_dynamic_device(device_t &owner, device_type type, const char *tag, UINT32 clock)
+{
+ // allocate and append this device
+ astring fulltag;
+ owner.subtag(fulltag, tag);
+ device_t &device = const_cast<device_list &>(devicelist()).append(fulltag, *type(m_config, fulltag, &owner, clock));
+
+ // append any machine config additions from new devices
+ for (device_t *curdevice = devicelist().first(); curdevice != NULL; curdevice = curdevice->next())
+ if (!curdevice->configured())
+ {
+ machine_config_constructor machconfig = curdevice->machine_config_additions();
+ if (machconfig != NULL)
+ (*machconfig)(const_cast<machine_config &>(m_config), curdevice);
+ }
+
+ // notify any new devices that their configurations are complete
+ for (device_t *curdevice = devicelist().first(); curdevice != NULL; curdevice = curdevice->next())
+ if (!curdevice->configured())
+ curdevice->config_complete();
+ return device;
+}
+
+
+//-------------------------------------------------
+// run - execute the machine
+//-------------------------------------------------
+
+int running_machine::run(bool firstrun)
+{
+ int error = MAMERR_NONE;
+
+ // use try/catch for deep error recovery
+ try
+ {
+ // move to the init phase
+ m_current_phase = MACHINE_PHASE_INIT;
+
+ // if we have a logfile, set up the callback
+ if (options().log())
+ {
+ m_logfile = auto_alloc(*this, emu_file(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS));
+ file_error filerr = m_logfile->open("error.log");
+ assert_always(filerr == FILERR_NONE, "unable to open log file");
+ add_logerror_callback(logfile_callback);
+ }
+
+ // then finish setting up our local machine
+ start();
+
+ // load the configuration settings and NVRAM
+ bool settingsloaded = config_load_settings(*this);
+ nvram_load(*this);
+ sound().ui_mute(false);
+
+ // display the startup screens
+ ui_display_startup_screens(*this, firstrun, !settingsloaded);
+
+ // perform a soft reset -- this takes us to the running phase
+ soft_reset();
+
+ // run the CPUs until a reset or exit
+ m_hard_reset_pending = false;
+ while ((!m_hard_reset_pending && !m_exit_pending) || m_saveload_schedule != SLS_NONE)
+ {
+ g_profiler.start(PROFILER_EXTRA);
+
+ // execute CPUs if not paused
+ if (!m_paused)
+ m_scheduler.timeslice();
+
+ // otherwise, just pump video updates through
+ else
+ m_video->frame_update();
+
+ // handle save/load
+ if (m_saveload_schedule != SLS_NONE)
+ handle_saveload();
+
+ g_profiler.stop();
+ }
+
+ // and out via the exit phase
+ m_current_phase = MACHINE_PHASE_EXIT;
+
+ // save the NVRAM and configuration
+ sound().ui_mute(true);
+ nvram_save(*this);
+ config_save_settings(*this);
+ }
+ catch (emu_fatalerror &fatal)
+ {
+ mame_printf_error("%s\n", fatal.string());
+ error = MAMERR_FATALERROR;
+ if (fatal.exitcode() != 0)
+ error = fatal.exitcode();
+ }
+ catch (emu_exception &)
+ {
+ mame_printf_error("Caught unhandled emulator exception\n");
+ error = MAMERR_FATALERROR;
+ }
+ catch (std::bad_alloc &)
+ {
+ mame_printf_error("Out of memory!\n");
+ error = MAMERR_FATALERROR;
+ }
+
+ // call all exit callbacks registered
+ call_notifiers(MACHINE_NOTIFY_EXIT);
+ zip_file_cache_clear();
+
+ // close the logfile
+ auto_free(*this, m_logfile);
+ return error;
+}
+
+
+//-------------------------------------------------
+// schedule_exit - schedule a clean exit
+//-------------------------------------------------
+
+void running_machine::schedule_exit()
+{
+ // if we are in-game but we started with the select game menu, return to that instead
+ if (m_exit_to_game_select && options().system_name()[0] != 0)
+ {
+ options().set_system_name("");
+ ui_menu_force_game_select(*this, &render().ui_container());
+ }
+
+ // otherwise, exit for real
+ else
+ m_exit_pending = true;
+
+ // if we're executing, abort out immediately
+ m_scheduler.eat_all_cycles();
+
+ // if we're autosaving on exit, schedule a save as well
+ if (options().autosave() && (m_system.flags & GAME_SUPPORTS_SAVE) && this->time() > attotime::zero)
+ schedule_save("auto");
+}
+
+
+//-------------------------------------------------
+// schedule_hard_reset - schedule a hard-reset of
+// the machine
+//-------------------------------------------------
+
+void running_machine::schedule_hard_reset()
+{
+ m_hard_reset_pending = true;
+
+ // if we're executing, abort out immediately
+ m_scheduler.eat_all_cycles();
+}
+
+
+//-------------------------------------------------
+// schedule_soft_reset - schedule a soft-reset of
+// the system
+//-------------------------------------------------
+
+void running_machine::schedule_soft_reset()
+{
+ m_soft_reset_timer->adjust(attotime::zero);
+
+ // we can't be paused since the timer needs to fire
+ resume();
+
+ // if we're executing, abort out immediately
+ m_scheduler.eat_all_cycles();
+}
+
+
+//-------------------------------------------------
+// schedule_new_driver - schedule a new game to
+// be loaded
+//-------------------------------------------------
+
+void running_machine::schedule_new_driver(const game_driver &driver)
+{
+ m_hard_reset_pending = true;
+ m_new_driver_pending = &driver;
+
+ // if we're executing, abort out immediately
+ m_scheduler.eat_all_cycles();
+}
+
+
+//-------------------------------------------------
+// set_saveload_filename - specifies the filename
+// for state loading/saving
+//-------------------------------------------------
+
+void running_machine::set_saveload_filename(const char *filename)
+{
+ // free any existing request and allocate a copy of the requested name
+ if (osd_is_absolute_path(filename))
+ {
+ m_saveload_searchpath = NULL;
+ m_saveload_pending_file.cpy(filename);
+ }
+ else
+ {
+ m_saveload_searchpath = options().state_directory();
+ m_saveload_pending_file.cpy(basename()).cat(PATH_SEPARATOR).cat(filename).cat(".sta");
+ }
+}
+
+
+//-------------------------------------------------
+// schedule_save - schedule a save to occur as
+// soon as possible
+//-------------------------------------------------
+
+void running_machine::schedule_save(const char *filename)
+{
+ // specify the filename to save or load
+ set_saveload_filename(filename);
+
+ // note the start time and set a timer for the next timeslice to actually schedule it
+ m_saveload_schedule = SLS_SAVE;
+ m_saveload_schedule_time = this->time();
+
+ // we can't be paused since we need to clear out anonymous timers
+ resume();
+}
+
+
+//-------------------------------------------------
+// schedule_load - schedule a load to occur as
+// soon as possible
+//-------------------------------------------------
+
+void running_machine::schedule_load(const char *filename)
+{
+ // specify the filename to save or load
+ set_saveload_filename(filename);
+
+ // note the start time and set a timer for the next timeslice to actually schedule it
+ m_saveload_schedule = SLS_LOAD;
+ m_saveload_schedule_time = this->time();
+
+ // we can't be paused since we need to clear out anonymous timers
+ resume();
+}
+
+
+//-------------------------------------------------
+// pause - pause the system
+//-------------------------------------------------
+
+void running_machine::pause()
+{
+ // ignore if nothing has changed
+ if (m_paused)
+ return;
+ m_paused = true;
+
+ // call the callbacks
+ call_notifiers(MACHINE_NOTIFY_PAUSE);
+}
+
+
+//-------------------------------------------------
+// resume - resume the system
+//-------------------------------------------------
+
+void running_machine::resume()
+{
+ // ignore if nothing has changed
+ if (!m_paused)
+ return;
+ m_paused = false;
+
+ // call the callbacks
+ call_notifiers(MACHINE_NOTIFY_RESUME);
+}
+
+
+//-------------------------------------------------
+// region_alloc - allocates memory for a region
+//-------------------------------------------------
+
+memory_region *running_machine::region_alloc(const char *name, UINT32 length, UINT8 width, endianness_t endian)
+{
+ // make sure we don't have a region of the same name; also find the end of the list
+ memory_region *info = m_regionlist.find(name);
+ if (info != NULL)
+ fatalerror("region_alloc called with duplicate region name \"%s\"\n", name);
+
+ // allocate the region
+ return &m_regionlist.append(name, *auto_alloc(*this, memory_region(*this, name, length, width, endian)));
+}
+
+
+//-------------------------------------------------
+// region_free - releases memory for a region
+//-------------------------------------------------
+
+void running_machine::region_free(const char *name)
+{
+ m_regionlist.remove(name);
+}
+
+
+//-------------------------------------------------
+// add_notifier - add a notifier of the
+// given type
+//-------------------------------------------------
+
+void running_machine::add_notifier(machine_notification event, machine_notify_delegate callback)
+{
+ assert_always(m_current_phase == MACHINE_PHASE_INIT, "Can only call add_notifier at init time!");
+
+ // exit notifiers are added to the head, and executed in reverse order
+ if (event == MACHINE_NOTIFY_EXIT)
+ m_notifier_list[event].prepend(*global_alloc(notifier_callback_item(callback)));
+
+ // all other notifiers are added to the tail, and executed in the order registered
+ else
+ m_notifier_list[event].append(*global_alloc(notifier_callback_item(callback)));
+}
+
+
+//-------------------------------------------------
+// add_logerror_callback - adds a callback to be
+// called on logerror()
+//-------------------------------------------------
+
+void running_machine::add_logerror_callback(logerror_callback callback)
+{
+ assert_always(m_current_phase == MACHINE_PHASE_INIT, "Can only call add_logerror_callback at init time!");
+ m_logerror_list.append(*auto_alloc(*this, logerror_callback_item(callback)));
+}
+
+
+//-------------------------------------------------
+// logerror - printf-style error logging
+//-------------------------------------------------
+
+void CLIB_DECL running_machine::logerror(const char *format, ...)
+{
+ // process only if there is a target
+ if (m_logerror_list.first() != NULL)
+ {
+ va_list arg;
+ va_start(arg, format);
+ vlogerror(format, arg);
+ va_end(arg);
+ }
+}
+
+
+//-------------------------------------------------
+// vlogerror - vprintf-style error logging
+//-------------------------------------------------
+
+void CLIB_DECL running_machine::vlogerror(const char *format, va_list args)
+{
+ // process only if there is a target
+ if (m_logerror_list.first() != NULL)
+ {
+ g_profiler.start(PROFILER_LOGERROR);
+
+ // dump to the buffer
+ vsnprintf(giant_string_buffer, ARRAY_LENGTH(giant_string_buffer), format, args);
+
+ // log to all callbacks
+ for (logerror_callback_item *cb = m_logerror_list.first(); cb != NULL; cb = cb->next())
+ (*cb->m_func)(*this, giant_string_buffer);
+
+ g_profiler.stop();
+ }
+}
+
+
+//-------------------------------------------------
+// base_datetime - retrieve the time of the host
+// system; useful for RTC implementations
+//-------------------------------------------------
+
+void running_machine::base_datetime(system_time &systime)
+{
+ systime.set(m_base_time);
+}
+
+
+//-------------------------------------------------
+// current_datetime - retrieve the current time
+// (offset by the base); useful for RTC
+// implementations
+//-------------------------------------------------
+
+void running_machine::current_datetime(system_time &systime)
+{
+ systime.set(m_base_time + this->time().seconds);
+}
+
+
+//-------------------------------------------------
+// rand - standardized random numbers
+//-------------------------------------------------
+
+UINT32 running_machine::rand()
+{
+ m_rand_seed = 1664525 * m_rand_seed + 1013904223;
+
+ // return rotated by 16 bits; the low bits have a short period
+ // and are frequently used
+ return (m_rand_seed >> 16) | (m_rand_seed << 16);
+}
+
+
+//-------------------------------------------------
+// call_notifiers - call notifiers of the given
+// type
+//-------------------------------------------------
+
+void running_machine::call_notifiers(machine_notification which)
+{
+ for (notifier_callback_item *cb = m_notifier_list[which].first(); cb != NULL; cb = cb->next())
+ cb->m_func();
+}
+
+
+//-------------------------------------------------
+// handle_saveload - attempt to perform a save
+// or load
+//-------------------------------------------------
+
+void running_machine::handle_saveload()
+{
+ UINT32 openflags = (m_saveload_schedule == SLS_LOAD) ? OPEN_FLAG_READ : (OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ const char *opnamed = (m_saveload_schedule == SLS_LOAD) ? "loaded" : "saved";
+ const char *opname = (m_saveload_schedule == SLS_LOAD) ? "load" : "save";
+ file_error filerr = FILERR_NONE;
+
+ // if no name, bail
+ emu_file file(m_saveload_searchpath, openflags);
+ if (!m_saveload_pending_file)
+ goto cancel;
+
+ // if there are anonymous timers, we can't save just yet, and we can't load yet either
+ // because the timers might overwrite data we have loaded
+ if (!m_scheduler.can_save())
+ {
+ // if more than a second has passed, we're probably screwed
+ if ((this->time() - m_saveload_schedule_time) > attotime::from_seconds(1))
+ {
+ popmessage("Unable to %s due to pending anonymous timers. See error.log for details.", opname);
+ goto cancel;
+ }
+ return;
+ }
+
+ // open the file
+ filerr = file.open(m_saveload_pending_file);
+ if (filerr == FILERR_NONE)
+ {
+ // read/write the save state
+ save_error saverr = (m_saveload_schedule == SLS_LOAD) ? m_save.read_file(file) : m_save.write_file(file);
+
+ // handle the result
+ switch (saverr)
+ {
+ case STATERR_ILLEGAL_REGISTRATIONS:
+ popmessage("Error: Unable to %s state due to illegal registrations. See error.log for details.", opname);
+ break;
+
+ case STATERR_INVALID_HEADER:
+ popmessage("Error: Unable to %s state due to an invalid header. Make sure the save state is correct for this game.", opname);
+ break;
+
+ case STATERR_READ_ERROR:
+ popmessage("Error: Unable to %s state due to a read error (file is likely corrupt).", opname);
+ break;
+
+ case STATERR_WRITE_ERROR:
+ popmessage("Error: Unable to %s state due to a write error. Verify there is enough disk space.", opname);
+ break;
+
+ case STATERR_NONE:
+ if (!(m_system.flags & GAME_SUPPORTS_SAVE))
+ popmessage("State successfully %s.\nWarning: Save states are not officially supported for this game.", opnamed);
+ else
+ popmessage("State successfully %s.", opnamed);
+ break;
+
+ default:
+ popmessage("Error: Unknown error during state %s.", opnamed);
+ break;
+ }
+
+ // close and perhaps delete the file
+ if (saverr != STATERR_NONE && m_saveload_schedule == SLS_SAVE)
+ file.remove_on_close();
+ }
+ else
+ popmessage("Error: Failed to open file for %s operation.", opname);
+
+ // unschedule the operation
+cancel:
+ m_saveload_pending_file.reset();
+ m_saveload_searchpath = NULL;
+ m_saveload_schedule = SLS_NONE;
+}
+
+
+//-------------------------------------------------
+// soft_reset - actually perform a soft-reset
+// of the system
+//-------------------------------------------------
+
+void running_machine::soft_reset(void *ptr, INT32 param)
+{
+ logerror("Soft reset\n");
+
+ // temporarily in the reset phase
+ m_current_phase = MACHINE_PHASE_RESET;
+
+ // call all registered reset callbacks
+ call_notifiers(MACHINE_NOTIFY_RESET);
+
+ // now we're running
+ m_current_phase = MACHINE_PHASE_RUNNING;
+}
+
+
+//-------------------------------------------------
+// logfile_callback - callback for logging to
+// logfile
+//-------------------------------------------------
+
+void running_machine::logfile_callback(running_machine &machine, const char *buffer)
+{
+ if (machine.m_logfile != NULL)
+ machine.m_logfile->puts(buffer);
+}
+
+
+
+/***************************************************************************
+ MEMORY REGIONS
+***************************************************************************/
+
+//-------------------------------------------------
+// memory_region - constructor
+//-------------------------------------------------
+
+memory_region::memory_region(running_machine &machine, const char *name, UINT32 length, UINT8 width, endianness_t endian)
+ : m_machine(machine),
+ m_next(NULL),
+ m_name(name),
+ m_length(length),
+ m_width(width),
+ m_endianness(endian)
+{
+ assert(width == 1 || width == 2 || width == 4 || width == 8);
+ m_base.u8 = auto_alloc_array(machine, UINT8, length);
+}
+
+
+//-------------------------------------------------
+// ~memory_region - destructor
+//-------------------------------------------------
+
+memory_region::~memory_region()
+{
+ auto_free(machine(), m_base.v);
+}
+
+
+
+//**************************************************************************
+// CALLBACK ITEMS
+//**************************************************************************
+
+//-------------------------------------------------
+// notifier_callback_item - constructor
+//-------------------------------------------------
+
+running_machine::notifier_callback_item::notifier_callback_item(machine_notify_delegate func)
+ : m_next(NULL),
+ m_func(func)
+{
+}
+
+
+//-------------------------------------------------
+// logerror_callback_item - constructor
+//-------------------------------------------------
+
+running_machine::logerror_callback_item::logerror_callback_item(logerror_callback func)
+ : m_next(NULL),
+ m_func(func)
+{
+}
+
+
+
+//**************************************************************************
+// DRIVER DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// driver_device - constructor
+//-------------------------------------------------
+
+driver_device::driver_device(const machine_config &mconfig, device_type type, const char *tag)
+ : device_t(mconfig, type, "Driver Device", tag, NULL, 0),
+ m_system(NULL),
+ m_palette_init(NULL)
+{
+ memset(m_callbacks, 0, sizeof(m_callbacks));
+}
+
+
+//-------------------------------------------------
+// driver_device - destructor
+//-------------------------------------------------
+
+driver_device::~driver_device()
+{
+}
+
+
+//-------------------------------------------------
+// static_set_game - set the game in the device
+// configuration
+//-------------------------------------------------
+
+void driver_device::static_set_game(device_t &device, const game_driver &game)
+{
+ driver_device &driver = downcast<driver_device &>(device);
+
+ // set the system
+ driver.m_system = &game;
+
+ // set the short name to the game's name
+ driver.m_shortname = game.name;
+
+ // and set the search path to include all parents
+ driver.m_searchpath = game.name;
+ for (int parent = driver_list::clone(game); parent != -1; parent = driver_list::clone(parent))
+ driver.m_searchpath.cat(";").cat(driver_list::driver(parent).name);
+}
+
+
+//-------------------------------------------------
+// static_set_machine_start - set the legacy
+// machine start callback in the device
+// configuration
+//-------------------------------------------------
+
+void driver_device::static_set_callback(device_t &device, callback_type type, legacy_callback_func callback)
+{
+ downcast<driver_device &>(device).m_callbacks[type] = callback;
+}
+
+
+//-------------------------------------------------
+// static_set_palette_init - set the legacy
+// palette init callback in the device
+// configuration
+//-------------------------------------------------
+
+void driver_device::static_set_palette_init(device_t &device, palette_init_func callback)
+{
+ downcast<driver_device &>(device).m_palette_init = callback;
+}
+
+
+//-------------------------------------------------
+// driver_start - default implementation which
+// does nothing
+//-------------------------------------------------
+
+void driver_device::driver_start()
+{
+}
+
+
+//-------------------------------------------------
+// machine_start - default implementation which
+// calls to the legacy machine_start function
+//-------------------------------------------------
+
+void driver_device::machine_start()
+{
+ if (m_callbacks[CB_MACHINE_START] != NULL)
+ (*m_callbacks[CB_MACHINE_START])(machine());
+}
+
+
+//-------------------------------------------------
+// sound_start - default implementation which
+// calls to the legacy sound_start function
+//-------------------------------------------------
+
+void driver_device::sound_start()
+{
+ if (m_callbacks[CB_SOUND_START] != NULL)
+ (*m_callbacks[CB_SOUND_START])(machine());
+}
+
+
+//-------------------------------------------------
+// video_start - default implementation which
+// calls to the legacy video_start function
+//-------------------------------------------------
+
+void driver_device::video_start()
+{
+ if (m_callbacks[CB_VIDEO_START] != NULL)
+ (*m_callbacks[CB_VIDEO_START])(machine());
+}
+
+
+//-------------------------------------------------
+// driver_reset - default implementation which
+// does nothing
+//-------------------------------------------------
+
+void driver_device::driver_reset()
+{
+}
+
+
+//-------------------------------------------------
+// machine_reset - default implementation which
+// calls to the legacy machine_reset function
+//-------------------------------------------------
+
+void driver_device::machine_reset()
+{
+ if (m_callbacks[CB_MACHINE_RESET] != NULL)
+ (*m_callbacks[CB_MACHINE_RESET])(machine());
+}
+
+
+//-------------------------------------------------
+// sound_reset - default implementation which
+// calls to the legacy sound_reset function
+//-------------------------------------------------
+
+void driver_device::sound_reset()
+{
+ if (m_callbacks[CB_SOUND_RESET] != NULL)
+ (*m_callbacks[CB_SOUND_RESET])(machine());
+}
+
+
+//-------------------------------------------------
+// video_reset - default implementation which
+// calls to the legacy video_reset function
+//-------------------------------------------------
+
+void driver_device::video_reset()
+{
+ if (m_callbacks[CB_VIDEO_RESET] != NULL)
+ (*m_callbacks[CB_VIDEO_RESET])(machine());
+}
+
+
+//-------------------------------------------------
+// video_update - default implementation which
+// calls to the legacy video_update function
+//-------------------------------------------------
+
+bool driver_device::screen_update(screen_device &screen, bitmap_t &bitmap, const rectangle &cliprect)
+{
+ return 0;
+}
+
+
+//-------------------------------------------------
+// video_eof - default implementation which
+// calls to the legacy video_eof function
+//-------------------------------------------------
+
+void driver_device::screen_eof()
+{
+}
+
+
+//-------------------------------------------------
+// device_rom_region - return a pointer to the
+// game's ROMs
+//-------------------------------------------------
+
+const rom_entry *driver_device::device_rom_region() const
+{
+ return m_system->rom;
+}
+
+
+//-------------------------------------------------
+// device_input_ports - return a pointer to the
+// game's input ports
+//-------------------------------------------------
+
+ioport_constructor driver_device::device_input_ports() const
+{
+ return m_system->ipt;
+}
+
+
+//-------------------------------------------------
+// device_start - device override which calls
+// the various helpers
+//-------------------------------------------------
+
+void driver_device::device_start()
+{
+ // reschedule ourselves to be last
+ if (next() != NULL)
+ throw device_missing_dependencies();
+
+ // call the game-specific init
+ if (m_system->driver_init != NULL)
+ (*m_system->driver_init)(machine());
+
+ // finish image devices init process
+ image_postdevice_init(machine());
+
+ // call palette_init if present
+ if (m_palette_init != NULL)
+ (*m_palette_init)(machine(), machine().region("proms")->base());
+
+ // start the various pieces
+ driver_start();
+ machine_start();
+ sound_start();
+ video_start();
+}
+
+
+//-------------------------------------------------
+// device_reset - device override which calls
+// the various helpers
+//-------------------------------------------------
+
+void driver_device::device_reset()
+{
+ // reset each piece
+ driver_reset();
+ machine_reset();
+ sound_reset();
+ video_reset();
+}
+
+
+
+//**************************************************************************
+// SYSTEM TIME
+//**************************************************************************
+
+//-------------------------------------------------
+// system_time - constructor
+//-------------------------------------------------
+
+system_time::system_time()
+{
+ set(0);
+}
+
+
+//-------------------------------------------------
+// set - fills out a system_time structure
+//-------------------------------------------------
+
+void system_time::set(time_t t)
+{
+ time = t;
+ local_time.set(*localtime(&t));
+ utc_time.set(*gmtime(&t));
+}
+
+
+//-------------------------------------------------
+// get_tm_time - converts a tm struction to a
+// MAME mame_system_tm structure
+//-------------------------------------------------
+
+void system_time::full_time::set(struct tm &t)
+{
+ second = t.tm_sec;
+ minute = t.tm_min;
+ hour = t.tm_hour;
+ mday = t.tm_mday;
+ month = t.tm_mon;
+ year = t.tm_year + 1900;
+ weekday = t.tm_wday;
+ day = t.tm_yday;
+ is_dst = t.tm_isdst;
+}
diff --git a/trunk/src/emu/machine.h b/trunk/src/emu/machine.h
new file mode 100644
index 00000000000..01b2c665bd5
--- /dev/null
+++ b/trunk/src/emu/machine.h
@@ -0,0 +1,624 @@
+/***************************************************************************
+
+ machine.h
+
+ Controls execution of the core MAME 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 __EMU_H__
+#error Dont include this file directly; include emu.h instead.
+#endif
+
+#ifndef __MACHINE_H__
+#define __MACHINE_H__
+
+#include <time.h>
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+const int MAX_GFX_ELEMENTS = 32;
+
+
+// machine phases
+enum machine_phase
+{
+ MACHINE_PHASE_PREINIT,
+ MACHINE_PHASE_INIT,
+ MACHINE_PHASE_RESET,
+ MACHINE_PHASE_RUNNING,
+ MACHINE_PHASE_EXIT
+};
+
+
+// notification callback types
+enum machine_notification
+{
+ MACHINE_NOTIFY_FRAME,
+ MACHINE_NOTIFY_RESET,
+ MACHINE_NOTIFY_PAUSE,
+ MACHINE_NOTIFY_RESUME,
+ MACHINE_NOTIFY_EXIT,
+ MACHINE_NOTIFY_COUNT
+};
+
+
+// output channels
+enum output_channel
+{
+ OUTPUT_CHANNEL_ERROR,
+ OUTPUT_CHANNEL_WARNING,
+ OUTPUT_CHANNEL_INFO,
+ OUTPUT_CHANNEL_DEBUG,
+ OUTPUT_CHANNEL_VERBOSE,
+ OUTPUT_CHANNEL_LOG,
+ OUTPUT_CHANNEL_COUNT
+};
+
+
+// debug flags
+const int DEBUG_FLAG_ENABLED = 0x00000001; // debugging is enabled
+const int DEBUG_FLAG_CALL_HOOK = 0x00000002; // CPU cores must call instruction hook
+const int DEBUG_FLAG_WPR_PROGRAM = 0x00000010; // watchpoints are enabled for PROGRAM memory reads
+const int DEBUG_FLAG_WPR_DATA = 0x00000020; // watchpoints are enabled for DATA memory reads
+const int DEBUG_FLAG_WPR_IO = 0x00000040; // watchpoints are enabled for IO memory reads
+const int DEBUG_FLAG_WPW_PROGRAM = 0x00000100; // watchpoints are enabled for PROGRAM memory writes
+const int DEBUG_FLAG_WPW_DATA = 0x00000200; // watchpoints are enabled for DATA memory writes
+const int DEBUG_FLAG_WPW_IO = 0x00000400; // watchpoints are enabled for IO memory writes
+const int DEBUG_FLAG_OSD_ENABLED = 0x00001000; // The OSD debugger is enabled
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+// macros to wrap legacy callbacks
+#define MACHINE_START_NAME(name) machine_start_##name
+#define MACHINE_START(name) void MACHINE_START_NAME(name)(running_machine &machine)
+#define MACHINE_START_CALL(name) MACHINE_START_NAME(name)(machine)
+
+#define MACHINE_RESET_NAME(name) machine_reset_##name
+#define MACHINE_RESET(name) void MACHINE_RESET_NAME(name)(running_machine &machine)
+#define MACHINE_RESET_CALL(name) MACHINE_RESET_NAME(name)(machine)
+
+#define SOUND_START_NAME(name) sound_start_##name
+#define SOUND_START(name) void SOUND_START_NAME(name)(running_machine &machine)
+#define SOUND_START_CALL(name) SOUND_START_NAME(name)(machine)
+
+#define SOUND_RESET_NAME(name) sound_reset_##name
+#define SOUND_RESET(name) void SOUND_RESET_NAME(name)(running_machine &machine)
+#define SOUND_RESET_CALL(name) SOUND_RESET_NAME(name)(machine)
+
+#define VIDEO_START_NAME(name) video_start_##name
+#define VIDEO_START(name) void VIDEO_START_NAME(name)(running_machine &machine)
+#define VIDEO_START_CALL(name) VIDEO_START_NAME(name)(machine)
+
+#define VIDEO_RESET_NAME(name) video_reset_##name
+#define VIDEO_RESET(name) void VIDEO_RESET_NAME(name)(running_machine &machine)
+#define VIDEO_RESET_CALL(name) VIDEO_RESET_NAME(name)(machine)
+
+#define PALETTE_INIT_NAME(name) palette_init_##name
+#define PALETTE_INIT(name) void PALETTE_INIT_NAME(name)(running_machine &machine, const UINT8 *color_prom)
+#define PALETTE_INIT_CALL(name) PALETTE_INIT_NAME(name)(machine, color_prom)
+
+
+
+// NULL versions
+#define machine_start_0 NULL
+#define machine_reset_0 NULL
+#define sound_start_0 NULL
+#define sound_reset_0 NULL
+#define video_start_0 NULL
+#define video_reset_0 NULL
+#define palette_init_0 NULL
+
+
+
+// global allocation helpers
+#define auto_alloc(m, t) pool_alloc(static_cast<running_machine &>(m).respool(), t)
+#define auto_alloc_clear(m, t) pool_alloc_clear(static_cast<running_machine &>(m).respool(), t)
+#define auto_alloc_array(m, t, c) pool_alloc_array(static_cast<running_machine &>(m).respool(), t, c)
+#define auto_alloc_array_clear(m, t, c) pool_alloc_array_clear(static_cast<running_machine &>(m).respool(), t, c)
+#define auto_free(m, v) pool_free(static_cast<running_machine &>(m).respool(), v)
+
+#define auto_bitmap_alloc(m, w, h, f) auto_alloc(m, bitmap_t(w, h, f))
+#define auto_strdup(m, s) strcpy(auto_alloc_array(m, char, strlen(s) + 1), s)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// forward declarations
+class gfx_element;
+class colortable_t;
+class cheat_manager;
+class render_manager;
+class sound_manager;
+class video_manager;
+class debug_view_manager;
+class osd_interface;
+
+typedef struct _memory_private memory_private;
+typedef struct _palette_private palette_private;
+typedef struct _tilemap_private tilemap_private;
+typedef struct _romload_private romload_private;
+typedef struct _input_private input_private;
+typedef struct _input_port_private input_port_private;
+typedef struct _ui_input_private ui_input_private;
+typedef struct _debugcpu_private debugcpu_private;
+typedef struct _generic_machine_private generic_machine_private;
+typedef struct _generic_video_private generic_video_private;
+typedef struct _generic_audio_private generic_audio_private;
+
+
+// legacy callback functions
+typedef void (*legacy_callback_func)(running_machine &machine);
+typedef void (*palette_init_func)(running_machine &machine, const UINT8 *color_prom);
+
+
+
+// ======================> memory_region
+
+// memory region object; should eventually be renamed memory_region
+class memory_region
+{
+ DISABLE_COPYING(memory_region);
+
+ friend class running_machine;
+ friend class simple_list<memory_region>;
+ friend resource_pool_object<memory_region>::~resource_pool_object();
+
+ // construction/destruction
+ memory_region(running_machine &machine, const char *name, UINT32 length, UINT8 width, endianness_t endian);
+ ~memory_region();
+
+public:
+ // getters
+ running_machine &machine() const { return m_machine; }
+ memory_region *next() const { return m_next; }
+ UINT8 *base() const { return (this != NULL) ? m_base.u8 : NULL; }
+ UINT8 *end() const { return (this != NULL) ? m_base.u8 + m_length : NULL; }
+ UINT32 bytes() const { return (this != NULL) ? m_length : 0; }
+ const char *name() const { return m_name; }
+
+ // flag expansion
+ endianness_t endianness() const { return m_endianness; }
+ UINT8 width() const { return m_width; }
+
+ // data access
+ UINT8 &u8(offs_t offset = 0) const { return m_base.u8[offset]; }
+ UINT16 &u16(offs_t offset = 0) const { return m_base.u16[offset]; }
+ UINT32 &u32(offs_t offset = 0) const { return m_base.u32[offset]; }
+ UINT64 &u64(offs_t offset = 0) const { return m_base.u64[offset]; }
+
+ // allow passing a region for any common pointer
+ operator void *() const { return (this != NULL) ? m_base.v : NULL; }
+ operator INT8 *() const { return (this != NULL) ? m_base.i8 : NULL; }
+ operator UINT8 *() const { return (this != NULL) ? m_base.u8 : NULL; }
+ operator INT16 *() const { return (this != NULL) ? m_base.i16 : NULL; }
+ operator UINT16 *() const { return (this != NULL) ? m_base.u16 : NULL; }
+ operator INT32 *() const { return (this != NULL) ? m_base.i32 : NULL; }
+ operator UINT32 *() const { return (this != NULL) ? m_base.u32 : NULL; }
+ operator INT64 *() const { return (this != NULL) ? m_base.i64 : NULL; }
+ operator UINT64 *() const { return (this != NULL) ? m_base.u64 : NULL; }
+
+private:
+ // internal data
+ running_machine & m_machine;
+ memory_region * m_next;
+ astring m_name;
+ generic_ptr m_base;
+ UINT32 m_length;
+ UINT8 m_width;
+ endianness_t m_endianness;
+};
+
+
+
+// ======================> generic_pointers
+
+// holds generic pointers that are commonly used
+struct generic_pointers
+{
+ generic_ptr spriteram; // spriteram
+ UINT32 spriteram_size;
+ generic_ptr spriteram2; // secondary spriteram
+ UINT32 spriteram2_size;
+ generic_ptr buffered_spriteram; // buffered spriteram
+ generic_ptr buffered_spriteram2;// secondary buffered spriteram
+ generic_ptr paletteram; // palette RAM
+ generic_ptr paletteram2; // secondary palette RAM
+ bitmap_t * tmpbitmap; // temporary bitmap
+};
+
+
+
+// ======================> system_time
+
+// system time description, both local and UTC
+class system_time
+{
+public:
+ system_time();
+ void set(time_t t);
+
+ struct full_time
+ {
+ void set(struct tm &t);
+
+ UINT8 second; // seconds (0-59)
+ UINT8 minute; // minutes (0-59)
+ UINT8 hour; // hours (0-23)
+ UINT8 mday; // day of month (1-31)
+ UINT8 month; // month (0-11)
+ INT32 year; // year (1=1 AD)
+ UINT8 weekday; // day of week (0-6)
+ UINT16 day; // day of year (0-365)
+ UINT8 is_dst; // is this daylight savings?
+ };
+
+ INT64 time; // number of seconds elapsed since midnight, January 1 1970 UTC
+ full_time local_time; // local time
+ full_time utc_time; // UTC coordinated time
+};
+
+
+
+// ======================> running_machine
+
+typedef delegate<void ()> machine_notify_delegate;
+
+// description of the currently-running machine
+class running_machine
+{
+ DISABLE_COPYING(running_machine);
+
+ friend void debugger_init(running_machine &machine);
+ friend class sound_manager;
+
+ typedef void (*logerror_callback)(running_machine &machine, const char *string);
+
+ // must be at top of member variables
+ resource_pool m_respool; // pool of resources for this machine
+
+public:
+ // construction/destruction
+ running_machine(const machine_config &config, osd_interface &osd, bool exit_to_game_select = false);
+ ~running_machine();
+
+ // getters
+ const machine_config &config() const { return m_config; }
+ const device_list &devicelist() const { return m_config.devicelist(); }
+ const game_driver &system() const { return m_system; }
+ osd_interface &osd() const { return m_osd; }
+ resource_pool &respool() { return m_respool; }
+ device_scheduler &scheduler() { return m_scheduler; }
+ save_manager &save() { return m_save; }
+ cheat_manager &cheat() const { assert(m_cheat != NULL); return *m_cheat; }
+ render_manager &render() const { assert(m_render != NULL); return *m_render; }
+ input_manager &input() const { assert(m_input != NULL); return *m_input; }
+ sound_manager &sound() const { assert(m_sound != NULL); return *m_sound; }
+ video_manager &video() const { assert(m_video != NULL); return *m_video; }
+ debug_view_manager &debug_view() const { assert(m_debug_view != NULL); return *m_debug_view; }
+ driver_device *driver_data() const { return m_driver_device; }
+ template<class _DriverClass> _DriverClass *driver_data() const { return downcast<_DriverClass *>(m_driver_device); }
+ machine_phase phase() const { return m_current_phase; }
+ bool paused() const { return m_paused || (m_current_phase != MACHINE_PHASE_RUNNING); }
+ bool exit_pending() const { return m_exit_pending; }
+ bool new_driver_pending() const { return (m_new_driver_pending != NULL); }
+ const char *new_driver_name() const { return m_new_driver_pending->name; }
+ bool ui_active() const { return m_ui_active; }
+ const char *basename() const { return m_basename; }
+ int sample_rate() const { return m_sample_rate; }
+ bool save_or_load_pending() const { return m_saveload_pending_file; }
+ screen_device *first_screen() const { return primary_screen; }
+
+ // additional helpers
+ emu_options &options() const { return m_config.options(); }
+ memory_region *first_region() const { return m_regionlist.first(); }
+ attotime time() const { return m_scheduler.time(); }
+ bool scheduled_event_pending() const { return m_exit_pending || m_hard_reset_pending; }
+
+ // fetch items by name
+ inline device_t *device(const char *tag);
+ template<class _DeviceClass> inline _DeviceClass *device(const char *tag) { return downcast<_DeviceClass *>(device(tag)); }
+ inline const input_port_config *port(const char *tag);
+ inline const memory_region *region(const char *tag);
+
+ // configuration helpers
+ device_t &add_dynamic_device(device_t &owner, device_type type, const char *tag, UINT32 clock);
+ UINT32 total_colors() const { return m_config.m_total_colors; }
+
+ // immediate operations
+ int run(bool firstrun);
+ void pause();
+ void resume();
+ void add_notifier(machine_notification event, machine_notify_delegate callback);
+ void call_notifiers(machine_notification which);
+ void add_logerror_callback(logerror_callback callback);
+ void set_ui_active(bool active) { m_ui_active = active; }
+
+ // scheduled operations
+ void schedule_exit();
+ void schedule_hard_reset();
+ void schedule_soft_reset();
+ void schedule_new_driver(const game_driver &driver);
+ void schedule_save(const char *filename);
+ void schedule_load(const char *filename);
+
+ // date & time
+ void base_datetime(system_time &systime);
+ void current_datetime(system_time &systime);
+
+ // regions
+ memory_region *region_alloc(const char *name, UINT32 length, UINT8 width, endianness_t endian);
+ void region_free(const char *name);
+
+ // misc
+ void CLIB_DECL logerror(const char *format, ...);
+ void CLIB_DECL vlogerror(const char *format, va_list args);
+ UINT32 rand();
+ const char *describe_context();
+
+ // internals
+ ioport_list m_portlist; // points to a list of input port configurations
+
+ // CPU information
+ cpu_device * firstcpu; // first CPU (allows for quick iteration via typenext)
+
+ // video-related information
+ gfx_element * gfx[MAX_GFX_ELEMENTS];// array of pointers to graphic sets (chars, sprites)
+ screen_device * primary_screen; // the primary screen device, or NULL if screenless
+ palette_t * palette; // global palette object
+
+ // palette-related information
+ const pen_t * pens; // remapped palette pen numbers
+ colortable_t * colortable; // global colortable for remapping
+ pen_t * shadow_table; // table for looking up a shadowed pen
+ bitmap_t * priority_bitmap; // priority bitmap
+
+ // debugger-related information
+ UINT32 debug_flags; // the current debug flags
+
+ // generic pointers
+ generic_pointers generic; // generic pointers
+
+ // internal core information
+ memory_private * memory_data; // internal data from memory.c
+ palette_private * palette_data; // internal data from palette.c
+ tilemap_private * tilemap_data; // internal data from tilemap.c
+ romload_private * romload_data; // internal data from romload.c
+ input_private * input_data; // internal data from input.c
+ input_port_private * input_port_data; // internal data from inptport.c
+ ui_input_private * ui_input_data; // internal data from uiinput.c
+ debugcpu_private * debugcpu_data; // internal data from debugcpu.c
+ generic_machine_private *generic_machine_data; // internal data from machine/generic.c
+ generic_video_private * generic_video_data; // internal data from video/generic.c
+ generic_audio_private * generic_audio_data; // internal data from audio/generic.c
+
+private:
+ // internal helpers
+ void start();
+ void set_saveload_filename(const char *filename);
+ void fill_systime(system_time &systime, time_t t);
+ void handle_saveload();
+ void soft_reset(void *ptr = NULL, INT32 param = 0);
+
+ // internal callbacks
+ static void logfile_callback(running_machine &machine, const char *buffer);
+
+ // internal state
+ const machine_config & m_config; // reference to the constructed machine_config
+ const game_driver & m_system; // reference to the definition of the game machine
+ osd_interface & m_osd; // reference to OSD system
+
+ // embedded managers and objects
+ tagged_list<memory_region> m_regionlist; // list of memory regions
+ save_manager m_save; // save manager
+ device_scheduler m_scheduler; // scheduler object
+
+ // managers
+ cheat_manager * m_cheat; // internal data from cheat.c
+ render_manager * m_render; // internal data from render.c
+ input_manager * m_input; // internal data from input.c
+ sound_manager * m_sound; // internal data from sound.c
+ video_manager * m_video; // internal data from video.c
+ debug_view_manager * m_debug_view; // internal data from debugvw.c
+
+ // driver state
+ driver_device * m_driver_device; // pointer to the current driver device
+
+ // system state
+ machine_phase m_current_phase; // current execution phase
+ bool m_paused; // paused?
+ bool m_hard_reset_pending; // is a hard reset pending?
+ bool m_exit_pending; // is an exit pending?
+ bool m_exit_to_game_select; // when we exit, go we go back to the game select?
+ const game_driver * m_new_driver_pending; // pointer to the next pending driver
+ emu_timer * m_soft_reset_timer; // timer used to schedule a soft reset
+
+ // misc state
+ UINT32 m_rand_seed; // current random number seed
+ bool m_ui_active; // ui active or not (useful for games / systems with keyboard inputs)
+ time_t m_base_time; // real time at initial emulation time
+ astring m_basename; // basename used for game-related paths
+ astring m_context; // context string buffer
+ int m_sample_rate; // the digital audio sample rate
+ emu_file * m_logfile; // pointer to the active log file
+
+ // load/save management
+ enum saveload_schedule
+ {
+ SLS_NONE,
+ SLS_SAVE,
+ SLS_LOAD
+ };
+ saveload_schedule m_saveload_schedule;
+ attotime m_saveload_schedule_time;
+ astring m_saveload_pending_file;
+ const char * m_saveload_searchpath;
+
+ // notifier callbacks
+ struct notifier_callback_item
+ {
+ // construction/destruction
+ notifier_callback_item(machine_notify_delegate func);
+
+ // getters
+ notifier_callback_item *next() const { return m_next; }
+
+ // state
+ notifier_callback_item * m_next;
+ machine_notify_delegate m_func;
+ };
+ simple_list<notifier_callback_item> m_notifier_list[MACHINE_NOTIFY_COUNT];
+
+ // logerror callbacks
+ class logerror_callback_item
+ {
+ public:
+ // construction/destruction
+ logerror_callback_item(logerror_callback func);
+
+ // getters
+ logerror_callback_item *next() const { return m_next; }
+
+ // state
+ logerror_callback_item * m_next;
+ logerror_callback m_func;
+ };
+ simple_list<logerror_callback_item> m_logerror_list;
+};
+
+
+
+// ======================> driver_device
+
+// base class for machine driver-specific devices
+class driver_device : public device_t
+{
+public:
+ // construction/destruction
+ driver_device(const machine_config &mconfig, device_type type, const char *tag);
+ virtual ~driver_device();
+
+ // indexes into our generic callbacks
+ enum callback_type
+ {
+ CB_MACHINE_START,
+ CB_MACHINE_RESET,
+ CB_SOUND_START,
+ CB_SOUND_RESET,
+ CB_VIDEO_START,
+ CB_VIDEO_RESET,
+ CB_COUNT
+ };
+
+ // inline configuration helpers
+ static void static_set_game(device_t &device, const game_driver &game);
+ static void static_set_callback(device_t &device, callback_type type, legacy_callback_func callback);
+ static void static_set_palette_init(device_t &device, palette_init_func callback);
+
+ // additional video helpers
+ virtual bool screen_update(screen_device &screen, bitmap_t &bitmap, const rectangle &cliprect);
+ virtual void screen_eof();
+
+protected:
+ // helpers called at startup
+ virtual void driver_start();
+ virtual void machine_start();
+ virtual void sound_start();
+ virtual void video_start();
+
+ // helpers called at reset
+ virtual void driver_reset();
+ virtual void machine_reset();
+ virtual void sound_reset();
+ virtual void video_reset();
+
+ // device-level overrides
+ virtual const rom_entry *device_rom_region() const;
+ virtual ioport_constructor device_input_ports() const;
+ virtual void device_start();
+ virtual void device_reset();
+
+ // internal state
+ const game_driver * m_system; // pointer to the game driver
+
+ legacy_callback_func m_callbacks[CB_COUNT]; // generic legacy callbacks
+ palette_init_func m_palette_init; // one-time palette init callback
+};
+
+
+// this template function creates a stub which constructs a device
+template<class _DriverClass>
+device_t *driver_device_creator(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+{
+ assert(owner == NULL);
+ assert(clock == 0);
+ return global_alloc_clear(_DriverClass(mconfig, &driver_device_creator<_DriverClass>, tag));
+}
+
+
+
+//**************************************************************************
+// INLINE FUNCTIONS
+//**************************************************************************
+
+inline device_t *running_machine::device(const char *tag)
+{
+ return devicelist().find(tag);
+}
+
+inline const input_port_config *running_machine::port(const char *tag)
+{
+ return m_portlist.find(tag);
+}
+
+inline const memory_region *running_machine::region(const char *tag)
+{
+ return m_regionlist.find(tag);
+}
+
+
+#endif /* __MACHINE_H__ */
diff --git a/trunk/src/emu/machine/53c810.c b/trunk/src/emu/machine/53c810.c
new file mode 100644
index 00000000000..9e4b7f6f3e1
--- /dev/null
+++ b/trunk/src/emu/machine/53c810.c
@@ -0,0 +1,919 @@
+/* LSI Logic LSI53C810A PCI to SCSI I/O Processor */
+
+#include "emu.h"
+#include "53c810.h"
+
+#define DMA_MAX_ICOUNT 512 /* Maximum number of DMA Scripts opcodes to run */
+#define DASM_OPCODES 0
+
+static SCSIInstance *devices[8]; /* SCSI IDs 0-7 */
+static const struct LSI53C810interface *intf;
+static UINT8 last_id;
+
+static struct {
+ UINT8 scntl0;
+ UINT8 scntl1;
+ UINT8 scntl2;
+ UINT8 scntl3;
+ UINT8 scid;
+ UINT8 sxfer;
+ UINT8 socl;
+ UINT8 istat;
+ UINT8 dstat;
+ UINT8 sstat0;
+ UINT8 sstat1;
+ UINT8 sstat2;
+ UINT8 dien;
+ UINT8 dcntl;
+ UINT8 dmode;
+ UINT32 temp;
+ UINT32 dsa;
+ UINT32 dsp;
+ UINT32 dsps;
+ UINT32 dcmd;
+ UINT8 sien0;
+ UINT8 sien1;
+ UINT8 stime0;
+ UINT8 respid;
+ UINT8 stest1;
+ UINT8 scratch_a[4];
+ UINT8 scratch_b[4];
+ int dma_icount;
+ int halted;
+ int carry;
+ UINT32 (* fetch)(UINT32 dsp);
+ void (* irq_callback)(running_machine &machine);
+ void (* dma_callback)(UINT32, UINT32, int, int);
+} lsi810;
+
+typedef void (*opcode_handler)(running_machine &machine);
+#define OPCODE_HANDLER(name) void name(running_machine &machine)
+static opcode_handler dma_opcode[256];
+
+INLINE UINT32 FETCH(running_machine &machine)
+{
+ UINT32 r = intf->fetch(machine, lsi810.dsp);
+ lsi810.dsp += 4;
+ return r;
+}
+
+#ifdef UNUSED_FUNCTION
+static UINT32 sign_extend24(UINT32 val)
+{
+ if (val & 0x00800000)
+ val |= 0xFF000000;
+ else
+ val &= ~0xFF000000;
+ return val;
+}
+#endif
+
+static OPCODE_HANDLER( dmaop_invalid )
+{
+ fatalerror("LSI53C810: Invalid SCRIPTS DMA opcode %08X at %08X", lsi810.dcmd, lsi810.dsp);
+}
+
+static OPCODE_HANDLER( dmaop_move_memory )
+{
+ UINT32 src = FETCH(machine);
+ UINT32 dst = FETCH(machine);
+ int count;
+
+ count = lsi810.dcmd & 0xffffff;
+ if(intf->dma_callback != NULL) {
+ intf->dma_callback(machine, src, dst, count, 1);
+ }
+}
+
+static OPCODE_HANDLER( dmaop_interrupt )
+{
+ if(lsi810.dcmd & 0x100000) {
+ fatalerror("LSI53C810: INTFLY opcode not implemented");
+ }
+ lsi810.dsps = FETCH(machine);
+
+ lsi810.istat |= 0x1; /* DMA interrupt pending */
+ lsi810.dstat |= 0x4; /* SIR (SCRIPTS Interrupt Instruction Received) */
+
+ if(intf->irq_callback != NULL) {
+ intf->irq_callback(machine, 1);
+ }
+ lsi810.dma_icount = 0;
+ lsi810.halted = 1;
+}
+
+static OPCODE_HANDLER( dmaop_block_move )
+{
+ UINT32 address;
+ UINT32 count;
+ INT32 dsps;
+
+ address = FETCH(machine);
+ count = lsi810.dcmd & 0x00ffffff;
+
+ // normal indirect
+ if (lsi810.dcmd & 0x20000000)
+ address = intf->fetch(machine, address);
+
+ // table indirect
+ if (lsi810.dcmd & 0x10000000)
+ {
+ dsps = (INT32)address&0xffffff;
+ // sign extend
+ if (dsps & 0x00800000)
+ {
+ dsps |= 0xff000000;
+ }
+ logerror("table offset: %x, DSA = %x\n", dsps, lsi810.dsa);
+ dsps += lsi810.dsa;
+
+ logerror("Loading from table at %x\n", dsps);
+ count = lsi810.fetch(dsps);
+ address = lsi810.fetch(dsps+4);
+ }
+
+ logerror("block move: address %x count %x phase %x\n", address, count, (lsi810.dcmd>>24)&7);
+
+ if (lsi810.scntl0 & 0x01)
+ {
+ /* target mode */
+ fatalerror("LSI53C810: dmaop_block_move not implemented in target mode");
+ }
+ else
+ {
+ /* initiator mode */
+ logerror("53c810: block_move not actually implemented\n");
+ }
+}
+
+static OPCODE_HANDLER( dmaop_select )
+{
+// UINT32 operand;
+
+// operand = FETCH(machine);
+
+ if (lsi810.scntl0 & 0x01)
+ {
+ /* target mode */
+ logerror("LSI53C810: reselect ID #%d\n", (lsi810.dcmd >> 16) & 0x07);
+ }
+ else
+ {
+ /* initiator mode */
+ logerror("53c810: SELECT: our ID %d, target ID %d\n", lsi810.scid&7, (lsi810.dcmd>>16)&7);
+
+ lsi810.sstat1 &= ~0x07; // clear current bus phase
+ if (lsi810.dcmd & 0x01000000) // select with ATN
+ {
+ mame_printf_debug("53c810: want select with ATN, setting message phase\n");
+ lsi810.sstat1 |= 0x7; // ATN means we want message in phase
+ }
+ }
+}
+
+static OPCODE_HANDLER( dmaop_wait_disconnect )
+{
+// UINT32 operand;
+
+// operand = FETCH(machine);
+
+ if (lsi810.scntl0 & 0x01)
+ {
+ /* target mode */
+ fatalerror("LSI53C810: dmaop_wait_disconnect not implemented in target mode");
+ }
+ else
+ {
+ /* initiator mode */
+ fatalerror("LSI53C810: dmaop_wait_disconnect not implemented");
+ }
+}
+
+static OPCODE_HANDLER( dmaop_wait_reselect )
+{
+ // UINT32 operand;
+
+// operand = FETCH(machine);
+
+ if (lsi810.scntl0 & 0x01)
+ {
+ /* target mode */
+ fatalerror("LSI53C810: dmaop_wait_reselect not implemented in target mode");
+ }
+ else
+ {
+ /* initiator mode */
+ fatalerror("LSI53C810: dmaop_wait_reselect not implemented");
+ }
+}
+
+static OPCODE_HANDLER( dmaop_set )
+{
+// UINT32 operand;
+
+// operand = FETCH(machine);
+
+ /* initiator mode */
+ if (lsi810.dcmd & 0x8)
+ {
+ // set ATN in SOCL
+ lsi810.socl |= 0x08;
+ }
+ if (lsi810.dcmd & 0x40)
+ {
+ // set ACK in SOCL
+ lsi810.socl |= 0x40;
+ }
+ if (lsi810.dcmd & 0x200)
+ {
+ // set target mode
+ lsi810.scntl0 |= 0x01;
+ }
+ if (lsi810.dcmd & 0x400)
+ {
+ // set carry in ALU
+ lsi810.carry = 1;
+ }
+}
+
+static OPCODE_HANDLER( dmaop_clear )
+{
+// UINT32 operand;
+
+// operand = FETCH(machine);
+
+ /* initiator mode */
+ if (lsi810.dcmd & 0x8)
+ {
+ // clear ATN in SOCL
+ lsi810.socl &= ~0x08;
+ }
+ if (lsi810.dcmd & 0x40)
+ {
+ // clear ACK in SOCL
+ lsi810.socl &= ~0x40;
+ }
+ if (lsi810.dcmd & 0x200)
+ {
+ // clear target mode
+ lsi810.scntl0 &= ~0x01;
+ }
+ if (lsi810.dcmd & 0x400)
+ {
+ // clear carry in ALU
+ lsi810.carry = 0;
+ }
+}
+
+static OPCODE_HANDLER( dmaop_move_from_sfbr )
+{
+ fatalerror("LSI53C810: dmaop_move_from_sfbr not implemented in target mode");
+}
+
+static OPCODE_HANDLER( dmaop_move_to_sfbr )
+{
+ fatalerror("LSI53C810: dmaop_move_to_sfbr not implemented");
+}
+
+static OPCODE_HANDLER( dmaop_read_modify_write )
+{
+ fatalerror("LSI53C810: dmaop_read_modify_write not implemented");
+}
+
+static int scripts_compute_branch(void)
+{
+ int dtest, ptest, wanted, passed;
+
+// |jump if true
+// 878b0000 ||compare data
+// 1000 0111 1000 1011 0000 0000 0000 0000
+// | |rel ||wait valid phase
+// | |compare phase
+// |desired phase: message in
+
+ if (lsi810.dcmd & 0x00200000)
+ {
+ fatalerror("LSI53C810: jump with carry test not implemented");
+ }
+
+ if (lsi810.dcmd & 0x00100000)
+ {
+ fatalerror("LSI53C810: jump with interrupt on the fly not implemented");
+ }
+
+ // set desired result to take jump
+ wanted = (lsi810.dcmd & 0x00080000) ? 1 : 0;
+ // default to passing the tests in case they're disabled
+ dtest = ptest = wanted;
+
+ // phase test?
+ if (lsi810.dcmd & 0x00020000)
+ {
+ logerror("53c810: phase test. current: %x. target: %x\n", lsi810.sstat1 & 7, (lsi810.dcmd>>24)&7);
+
+ // do the phases match?
+ if (((lsi810.dcmd>>24)&7) == (lsi810.sstat1 & 7))
+ {
+ ptest = 1;
+ }
+ else
+ {
+ ptest = 0;
+ }
+ }
+
+ // data test?
+ if (lsi810.dcmd & 0x00040000)
+ {
+ logerror("53c810: data test. target: %x [not yet implemented]\n", lsi810.dcmd&0xff);
+ }
+
+ // if all conditions go, take the jump
+ passed = 0;
+ if ((ptest == dtest) && (dtest == wanted))
+ {
+ passed = 1;
+ }
+
+ logerror("53c810: phase test %d data test %d wanted %d => pass %d\n", ptest, dtest, wanted, passed);
+
+ return passed;
+}
+
+static UINT32 scripts_get_jump_dest(running_machine &machine)
+{
+ INT32 dsps;
+ UINT32 dest;
+
+ dsps = FETCH(machine);
+
+ /* relative or absolute addressing? */
+ if (lsi810.dcmd & 0x00800000)
+ {
+ // sign-extend the 24-bit value
+ if (dsps & 0x00800000)
+ {
+ dsps |= 0xff000000;
+ }
+
+ logerror("dsps = %x, dsp = %x\n", dsps, lsi810.dsp);
+ dsps += lsi810.dsp;
+ }
+
+ dest = (UINT32)dsps;
+
+ logerror("cur DSP %x, dest %x\n", lsi810.dsp, dest);
+
+ return dest;
+}
+
+static OPCODE_HANDLER( dmaop_jump )
+{
+ if (scripts_compute_branch())
+ {
+ lsi810.dsp = scripts_get_jump_dest(machine);
+ }
+ else
+ {
+ FETCH(machine); // skip operand to continue on
+ }
+}
+
+static OPCODE_HANDLER( dmaop_call )
+{
+ if (scripts_compute_branch())
+ {
+ // save return address
+ lsi810.temp = lsi810.dsp;
+
+ // and go
+ lsi810.dsp = scripts_get_jump_dest(machine);
+ }
+ else
+ {
+ FETCH(machine); // skip operand to continue on
+ }
+}
+
+static OPCODE_HANDLER( dmaop_return )
+{
+ // is this correct? return only happens if the condition is true?
+ if (scripts_compute_branch())
+ {
+ // restore return address
+ lsi810.dsp = lsi810.temp;
+ }
+ else
+ {
+ FETCH(machine); // skip operand to continue on
+ }
+}
+
+static OPCODE_HANDLER( dmaop_store )
+{
+ fatalerror("LSI53C810: dmaop_store not implemented");
+}
+
+static OPCODE_HANDLER( dmaop_load )
+{
+ fatalerror("LSI53C810: dmaop_load not implemented");
+}
+
+
+
+static void dma_exec(running_machine &machine)
+{
+ lsi810.dma_icount = DMA_MAX_ICOUNT;
+
+ while(lsi810.dma_icount > 0)
+ {
+ int op;
+
+ if (DASM_OPCODES)
+ {
+ char buf[256];
+ lsi53c810_dasm(machine, buf, lsi810.dsp);
+ logerror("0x%08X: %s\n", lsi810.dsp, buf);
+ }
+
+ lsi810.dcmd = FETCH(machine);
+
+ op = (lsi810.dcmd >> 24) & 0xff;
+ dma_opcode[op](machine);
+
+ lsi810.dma_icount--;
+ }
+}
+
+READ8_HANDLER( lsi53c810_reg_r )
+{
+ logerror("53c810: read reg %d:0x%x (PC=%x)\n", offset, offset, cpu_get_pc(&space->device()));
+ switch(offset)
+ {
+ case 0x00: /* SCNTL0 */
+ return lsi810.scntl0;
+ case 0x01: /* SCNTL1 */
+ return lsi810.scntl1;
+ case 0x02: /* SCNTL2 */
+ return lsi810.scntl2;
+ case 0x03: /* SCNTL3 */
+ return lsi810.scntl3;
+ case 0x04: /* SCID */
+ return lsi810.scid;
+ case 0x05: /* SXFER */
+ return lsi810.sxfer;
+ case 0x09: /* SOCL */
+ return lsi810.socl;
+ case 0x0c: /* DSTAT */
+ return lsi810.dstat;
+ case 0x0d: /* SSTAT0 */
+ return lsi810.sstat0;
+ case 0x0e: /* SSTAT1 */
+ return lsi810.sstat1;
+ case 0x0f: /* SSTAT2 */
+ return lsi810.sstat2;
+ case 0x10: /* DSA [7-0] */
+ return lsi810.dsa & 0xff;
+ case 0x11: /* DSA [15-8] */
+ return (lsi810.dsa >> 8) & 0xff;
+ case 0x12: /* DSA [23-16] */
+ return (lsi810.dsa >> 16) & 0xff;
+ case 0x13: /* DSA [31-24] */
+ return (lsi810.dsa >> 24) & 0xff;
+ case 0x14: /* ISTAT */
+ // clear the interrupt on service
+ if(intf->irq_callback != NULL)
+ {
+ intf->irq_callback(space->machine(), 0);
+ }
+
+ return lsi810.istat;
+ case 0x2c: /* DSP [7-0] */
+ return lsi810.dsp & 0xff;
+ case 0x2d: /* DSP [15-8] */
+ return (lsi810.dsp >> 8) & 0xff;
+ case 0x2e: /* DSP [23-16] */
+ return (lsi810.dsp >> 16) & 0xff;
+ case 0x2f: /* DSP [31-24] */
+ return (lsi810.dsp >> 24) & 0xff;
+ case 0x34: /* SCRATCH A */
+ case 0x35:
+ case 0x36:
+ case 0x37:
+ return lsi810.scratch_a[offset % 4];
+ case 0x39: /* DIEN */
+ return lsi810.dien;
+ case 0x3b: /* DCNTL */
+ return lsi810.dcntl;
+ case 0x40: /* SIEN0 */
+ return lsi810.sien0;
+ case 0x41: /* SIEN1 */
+ return lsi810.sien1;
+ case 0x48: /* STIME0 */
+ return lsi810.stime0;
+ case 0x4a: /* RESPID */
+ return lsi810.respid;
+ case 0x4d: /* STEST1 */
+ return lsi810.stest1;
+ case 0x5c: /* SCRATCH B */
+ case 0x5d:
+ case 0x5e:
+ case 0x5f:
+ return lsi810.scratch_b[offset % 4];
+
+ default:
+ fatalerror("LSI53C810: reg_r: Unknown reg %02X", offset);
+ }
+
+ return 0;
+}
+
+WRITE8_HANDLER( lsi53c810_reg_w )
+{
+ logerror("53c810: %02x to reg %d:0x%x (PC=%x)\n", data, offset, offset, cpu_get_pc(&space->device()));
+ switch(offset)
+ {
+ case 0x00: /* SCNTL0 */
+ lsi810.scntl0 = data;
+ break;
+ case 0x01: /* SCNTL1 */
+ lsi810.scntl1 = data;
+ break;
+ case 0x02: /* SCNTL2 */
+ lsi810.scntl2 = data;
+ break;
+ case 0x03: /* SCNTL3 */
+ lsi810.scntl3 = data;
+ break;
+ case 0x04: /* SCID */
+ lsi810.scid = data;
+ break;
+ case 0x05: /* SXFER */
+ lsi810.sxfer = data;
+ break;
+ case 0x09: /* SOCL */
+ lsi810.socl = data;
+ break;
+ case 0x0d: /* SSTAT0 */
+ lsi810.sstat0 = data;
+ break;
+ case 0x0e: /* SSTAT1 */
+ lsi810.sstat1 = data;
+ break;
+ case 0x0f: /* SSTAT2 */
+ lsi810.sstat2 = data;
+ break;
+ case 0x10: /* DSA [7-0] */
+ lsi810.dsa &= 0xffffff00;
+ lsi810.dsa |= data;
+ break;
+ case 0x11: /* DSA [15-8] */
+ lsi810.dsa &= 0xffff00ff;
+ lsi810.dsa |= data << 8;
+ break;
+ case 0x12: /* DSA [23-16] */
+ lsi810.dsa &= 0xff00ffff;
+ lsi810.dsa |= data << 16;
+ break;
+ case 0x13: /* DSA [31-24] */
+ lsi810.dsa &= 0x00ffffff;
+ lsi810.dsa |= data << 24;
+ break;
+ case 0x14: /* ISTAT */
+ lsi810.istat = data;
+ break;
+ case 0x2c: /* DSP [7-0] */
+ lsi810.dsp &= 0xffffff00;
+ lsi810.dsp |= data;
+ break;
+ case 0x2d: /* DSP [15-8] */
+ lsi810.dsp &= 0xffff00ff;
+ lsi810.dsp |= data << 8;
+ break;
+ case 0x2e: /* DSP [23-16] */
+ lsi810.dsp &= 0xff00ffff;
+ lsi810.dsp |= data << 16;
+ break;
+ case 0x2f: /* DSP [31-24] */
+ lsi810.dsp &= 0x00ffffff;
+ lsi810.dsp |= data << 24;
+ lsi810.halted = 0;
+ if((lsi810.dmode & 0x1) == 0 && !lsi810.halted) {
+ dma_exec(space->machine());
+ }
+ break;
+ case 0x34: /* SCRATCH A */
+ case 0x35:
+ case 0x36:
+ case 0x37:
+ lsi810.scratch_a[offset % 4] = data;
+ break;
+ case 0x38: /* DMODE */
+ lsi810.dmode = data;
+ break;
+ case 0x39: /* DIEN */
+ lsi810.dien = data;
+ break;
+ case 0x3b: /* DCNTL */
+ lsi810.dcntl = data;
+
+ if(lsi810.dcntl & 0x14 && !lsi810.halted) /* single-step & start DMA */
+ {
+ int op;
+ lsi810.dcmd = FETCH(space->machine());
+ op = (lsi810.dcmd >> 24) & 0xff;
+ dma_opcode[op](space->machine());
+
+ lsi810.istat |= 0x3; /* DMA interrupt pending */
+ lsi810.dstat |= 0x8; /* SSI (Single Step Interrupt) */
+ if(intf->irq_callback != NULL) {
+ intf->irq_callback(space->machine(), 1);
+ }
+ }
+ else if(lsi810.dcntl & 0x04 && !lsi810.halted) /* manual start DMA */
+ {
+ dma_exec(space->machine());
+ }
+ break;
+ case 0x40: /* SIEN0 */
+ lsi810.sien0 = data;
+ break;
+ case 0x41: /* SIEN1 */
+ lsi810.sien1 = data;
+ break;
+ case 0x48: /* STIME0 */
+ lsi810.stime0 = data;
+ break;
+ case 0x4a: /* RESPID */
+ lsi810.respid = data;
+ break;
+ case 0x4d: /* STEST1 */
+ lsi810.stest1 = data;
+ break;
+ case 0x5c: /* SCRATCH B */
+ case 0x5d:
+ case 0x5e:
+ case 0x5f:
+ lsi810.scratch_b[offset % 4] = data;
+ break;
+
+ default:
+ fatalerror("LSI53C810: reg_w: Unknown reg %02X, %02X", offset, data);
+ }
+}
+
+static void add_opcode(UINT8 op, UINT8 mask, opcode_handler handler)
+{
+ int i;
+ for(i=0; i < 256; i++) {
+ if((i & mask) == op) {
+ dma_opcode[i] = handler;
+ }
+ }
+}
+
+void lsi53c810_init(running_machine &machine, const struct LSI53C810interface *interface)
+{
+ int i;
+
+ // save interface pointer for later
+ intf = interface;
+
+ memset(&lsi810, 0, sizeof(lsi810));
+ for(i = 0; i < 256; i++)
+ {
+ dma_opcode[i] = dmaop_invalid;
+ }
+
+ add_opcode(0x00, 0xc0, dmaop_block_move);
+ add_opcode(0x40, 0xf8, dmaop_select);
+ add_opcode(0x48, 0xf8, dmaop_wait_disconnect);
+ add_opcode(0x50, 0xf8, dmaop_wait_reselect);
+ add_opcode(0x58, 0xf8, dmaop_set);
+ add_opcode(0x60, 0xf8, dmaop_clear);
+ add_opcode(0x68, 0xf8, dmaop_move_from_sfbr);
+ add_opcode(0x70, 0xf8, dmaop_move_to_sfbr);
+ add_opcode(0x78, 0xf8, dmaop_read_modify_write);
+ add_opcode(0x80, 0xf8, dmaop_jump);
+ add_opcode(0x88, 0xf8, dmaop_call);
+ add_opcode(0x90, 0xf8, dmaop_return);
+ add_opcode(0x98, 0xf8, dmaop_interrupt);
+ add_opcode(0xc0, 0xfe, dmaop_move_memory);
+ add_opcode(0xe0, 0xed, dmaop_store);
+ add_opcode(0xe1, 0xed, dmaop_load);
+
+ memset(devices, 0, sizeof(devices));
+
+ // try to open the devices
+ for (i = 0; i < interface->scsidevs->devs_present; i++)
+ {
+ SCSIAllocInstance( machine, interface->scsidevs->devices[i].scsiClass, &devices[interface->scsidevs->devices[i].scsiID], interface->scsidevs->devices[i].diskregion );
+ }
+}
+
+void lsi53c810_exit(const struct LSI53C810interface *interface)
+{
+ int i;
+
+ for (i = 0; i < interface->scsidevs->devs_present; i++)
+ {
+ SCSIDeleteInstance( devices[interface->scsidevs->devices[i].scsiID] );
+ }
+}
+
+void lsi53c810_read_data(int bytes, UINT8 *pData)
+{
+ if (devices[last_id])
+ {
+ SCSIReadData( devices[last_id], pData, bytes);
+ }
+ else
+ {
+ logerror("lsi53c810: read unknown device SCSI ID %d\n", last_id);
+ }
+}
+
+void lsi53c810_write_data(int bytes, UINT8 *pData)
+{
+ if (devices[last_id])
+ {
+ SCSIWriteData( devices[last_id], pData, bytes );
+ }
+ else
+ {
+ logerror("lsi53c810: write to unknown device SCSI ID %d\n", last_id);
+ }
+}
+
+void *lsi53c810_get_device(int id)
+{
+ void *ret;
+
+ if (devices[id])
+ {
+ logerror("lsi53c810: fetching dev pointer for SCSI ID %d\n", id);
+ SCSIGetDevice( devices[id], &ret );
+
+ return ret;
+ }
+
+ return NULL;
+}
+
+/*************************************
+ *
+ * Disassembler
+ *
+ *************************************/
+
+static UINT32 lsi53c810_dasm_fetch(running_machine &machine, UINT32 pc)
+{
+ return intf->fetch(machine, pc);
+}
+
+unsigned lsi53c810_dasm(running_machine &machine, char *buf, UINT32 pc)
+{
+ unsigned result = 0;
+ const char *op_mnemonic = NULL;
+ UINT32 op = lsi53c810_dasm_fetch(machine, pc);
+ UINT32 dest;
+ int i;
+
+ static const char *const phases[] =
+ {
+ "DATA_OUT", "DATA_IN", "CMD", "STATUS",
+ "RESERVED_OUT??", "RESERVED_IN??", "MSG_OUT", "MSG_IN"
+ };
+
+ if ((op & 0xF8000000) == 0x40000000)
+ {
+ /* SELECT */
+ dest = lsi53c810_dasm_fetch(machine, pc + 4);
+
+ buf += sprintf(buf, "SELECT%s %d, 0x%08X",
+ (op & 0x01000000) ? " ATN" : "",
+ (op >> 16) & 0x07,
+ dest);
+
+ result = 8;
+ }
+ else if (((op & 0xF8000000) == 0x58000000)
+ | ((op & 0xF8000000) == 0x60000000))
+ {
+ static const struct
+ {
+ UINT32 flag;
+ const char *text;
+ } flags[] =
+ {
+ { 0x00000008, "ATN" },
+ { 0x00000040, "ACK" },
+ { 0x00000200, "TARGET" },
+ { 0x00000400, "CARRY" }
+ };
+ int need_cojunction = FALSE;
+
+ /* SET/CLEAR */
+ switch(op & 0xF8000000)
+ {
+ case 0x58000000: op_mnemonic = "SET"; break;
+ case 0x60000000: op_mnemonic = "CLEAR"; break;
+ }
+
+ buf += sprintf(buf, "%s ", op_mnemonic);
+ need_cojunction = FALSE;
+
+ for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++)
+ {
+ if (op & flags[i].flag)
+ {
+ if (need_cojunction)
+ buf += sprintf(buf, " AND ");
+ else
+ need_cojunction = TRUE;
+ buf += sprintf(buf, "%s", flags[i].text);
+ }
+ }
+ }
+ else if (((op & 0xF8000000) == 0x80000000)
+ | ((op & 0xF8000000) == 0x88000000)
+ | ((op & 0xF8000000) == 0x98000000))
+ {
+ /* JUMP/CALL/INT */
+ switch(op & 0xF8000000)
+ {
+ case 0x80000000: op_mnemonic = "JUMP"; break;
+ case 0x88000000: op_mnemonic = "CALL"; break;
+ case 0x98000000: op_mnemonic = "INT"; break;
+ }
+
+ dest = lsi53c810_dasm_fetch(machine, pc + 4);
+
+ if (op & 0x00800000)
+ {
+ /* relative */
+ if (dest & 0x00800000)
+ dest |= 0xFF000000;
+ else
+ dest &= 0x00FFFFFF;
+ dest = (pc + 8) + dest;
+ buf += sprintf(buf, "%s REL(0x%08X)", op_mnemonic, dest);
+ }
+ else
+ {
+ /* absolute */
+ buf += sprintf(buf, "%s 0x%08X", op_mnemonic, dest);
+ }
+
+ switch(op & 0x000B0000)
+ {
+ case 0x00000000:
+ buf += sprintf(buf, ", NOT??");
+ break;
+
+ case 0x00080000:
+ break;
+
+ case 0x00020000:
+ case 0x00030000:
+ case 0x000A0000:
+ case 0x000B0000:
+ buf += sprintf(buf, ", %s%s %s",
+ (op & 0x00010000) ? "WHEN" : "IF",
+ (op & 0x00080000) ? "" : " NOT",
+ phases[(op >> 24) & 0x07]);
+ break;
+
+ default:
+ fatalerror("unknown op 0x%08X", op);
+ break;
+ }
+ result = 8;
+ }
+ else if ((op & 0xE0000000) == 0x00000000)
+ {
+ /* MOVE FROM */
+ dest = lsi53c810_dasm_fetch(machine, pc + 4);
+
+ buf += sprintf(buf, "MOVE FROM 0x%08X, WHEN %s",
+ dest, phases[(op >> 24) & 0x07]);
+
+ result = 8;
+ }
+ else if ((op & 0xE0000000) == 0x20000000)
+ {
+ /* MOVE PTR */
+ dest = lsi53c810_dasm_fetch(machine, pc + 4);
+
+ buf += sprintf(buf, "MOVE 0x%08X, PTR 0x%08X, WHEN %s",
+ (op & 0x00FFFFFF), dest, phases[(op >> 24) & 0x07]);
+
+ result = 8;
+ }
+ else
+ {
+ fatalerror("unknown op 0x%08X", op);
+ }
+ return result;
+}
+
diff --git a/trunk/src/emu/machine/53c810.h b/trunk/src/emu/machine/53c810.h
new file mode 100644
index 00000000000..3c49d8d0f15
--- /dev/null
+++ b/trunk/src/emu/machine/53c810.h
@@ -0,0 +1,27 @@
+#ifndef LSI53C810_H
+#define LSI53C810_H
+
+#include "machine/scsi.h"
+
+struct LSI53C810interface
+{
+ const SCSIConfigTable *scsidevs; /* SCSI devices */
+ void (*irq_callback)(running_machine &machine, int); /* IRQ callback */
+ void (*dma_callback)(running_machine &machine, UINT32, UINT32, int, int); /* DMA callback */
+ UINT32 (*fetch)(running_machine &machine, UINT32 dsp);
+};
+
+extern void lsi53c810_init(running_machine &machine, const struct LSI53C810interface *interface);
+extern void lsi53c810_exit(const struct LSI53C810interface *interface);
+
+extern void lsi53c810_read_data(int bytes, UINT8 *pData);
+extern void lsi53c810_write_data(int bytes, UINT8 *pData);
+
+extern void *lsi53c810_get_device(int id);
+
+READ8_HANDLER( lsi53c810_reg_r );
+WRITE8_HANDLER( lsi53c810_reg_w );
+
+unsigned lsi53c810_dasm(running_machine &machine, char *buf, UINT32 pc);
+
+#endif
diff --git a/trunk/src/emu/machine/6522via.c b/trunk/src/emu/machine/6522via.c
new file mode 100644
index 00000000000..1b3f89f0d3b
--- /dev/null
+++ b/trunk/src/emu/machine/6522via.c
@@ -0,0 +1,1072 @@
+/**********************************************************************
+
+ Rockwell 6522 VIA interface and emulation
+
+ This function emulates the functionality of up to 8 6522
+ versatile interface adapters.
+
+ This is based on the M6821 emulation in MAME.
+
+ To do:
+
+ T2 pulse counting mode
+ Pulse mode handshake output
+ More shift register
+
+**********************************************************************/
+
+/*
+ 1999-Dec-22 PeT
+ vc20 random number generation only partly working
+ (reads (uninitialized) timer 1 and timer 2 counter)
+ timer init, reset, read changed
+ */
+
+#include "emu.h"
+#include "6522via.h"
+#include "devhelpr.h"
+
+/***************************************************************************
+ PARAMETERS
+***************************************************************************/
+
+#define TRACE_VIA 0
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+/* Macros for PCR */
+#define CA1_LOW_TO_HIGH(c) (c & 0x01)
+#define CA1_HIGH_TO_LOW(c) (!(c & 0x01))
+
+#define CB1_LOW_TO_HIGH(c) (c & 0x10)
+#define CB1_HIGH_TO_LOW(c) (!(c & 0x10))
+
+#define CA2_INPUT(c) (!(c & 0x08))
+#define CA2_LOW_TO_HIGH(c) ((c & 0x0c) == 0x04)
+#define CA2_HIGH_TO_LOW(c) ((c & 0x0c) == 0x00)
+#define CA2_IND_IRQ(c) ((c & 0x0a) == 0x02)
+
+#define CA2_OUTPUT(c) (c & 0x08)
+#define CA2_AUTO_HS(c) ((c & 0x0c) == 0x08)
+#define CA2_HS_OUTPUT(c) ((c & 0x0e) == 0x08)
+#define CA2_PULSE_OUTPUT(c) ((c & 0x0e) == 0x0a)
+#define CA2_FIX_OUTPUT(c) ((c & 0x0c) == 0x0c)
+#define CA2_OUTPUT_LEVEL(c) ((c & 0x02) >> 1)
+
+#define CB2_INPUT(c) (!(c & 0x80))
+#define CB2_LOW_TO_HIGH(c) ((c & 0xc0) == 0x40)
+#define CB2_HIGH_TO_LOW(c) ((c & 0xc0) == 0x00)
+#define CB2_IND_IRQ(c) ((c & 0xa0) == 0x20)
+
+#define CB2_OUTPUT(c) (c & 0x80)
+#define CB2_AUTO_HS(c) ((c & 0xc0) == 0x80)
+#define CB2_HS_OUTPUT(c) ((c & 0xe0) == 0x80)
+#define CB2_PULSE_OUTPUT(c) ((c & 0xe0) == 0xa0)
+#define CB2_FIX_OUTPUT(c) ((c & 0xc0) == 0xc0)
+#define CB2_OUTPUT_LEVEL(c) ((c & 0x20) >> 5)
+
+/* Macros for ACR */
+#define PA_LATCH_ENABLE(c) (c & 0x01)
+#define PB_LATCH_ENABLE(c) (c & 0x02)
+
+#define SR_DISABLED(c) (!(c & 0x1c))
+#define SI_T2_CONTROL(c) ((c & 0x1c) == 0x04)
+#define SI_O2_CONTROL(c) ((c & 0x1c) == 0x08)
+#define SI_EXT_CONTROL(c) ((c & 0x1c) == 0x0c)
+#define SO_T2_RATE(c) ((c & 0x1c) == 0x10)
+#define SO_T2_CONTROL(c) ((c & 0x1c) == 0x14)
+#define SO_O2_CONTROL(c) ((c & 0x1c) == 0x18)
+#define SO_EXT_CONTROL(c) ((c & 0x1c) == 0x1c)
+
+#define T1_SET_PB7(c) (c & 0x80)
+#define T1_CONTINUOUS(c) (c & 0x40)
+#define T2_COUNT_PB6(c) (c & 0x20)
+
+/* Interrupt flags */
+#define INT_CA2 0x01
+#define INT_CA1 0x02
+#define INT_SR 0x04
+#define INT_CB2 0x08
+#define INT_CB1 0x10
+#define INT_T2 0x20
+#define INT_T1 0x40
+#define INT_ANY 0x80
+
+#define CLR_PA_INT() clear_int(INT_CA1 | ((!CA2_IND_IRQ(m_pcr)) ? INT_CA2: 0))
+#define CLR_PB_INT() clear_int(INT_CB1 | ((!CB2_IND_IRQ(m_pcr)) ? INT_CB2: 0))
+
+#define IFR_DELAY 3
+
+#define TIMER1_VALUE (m_t1ll+(m_t1lh<<8))
+#define TIMER2_VALUE (m_t2ll+(m_t2lh<<8))
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+attotime via6522_device::cycles_to_time(int c)
+{
+ return attotime::from_hz(clock()) * c;
+}
+
+
+UINT32 via6522_device::time_to_cycles(attotime t)
+{
+ return (t * clock()).as_double();
+}
+
+
+UINT16 via6522_device::get_counter1_value()
+{
+ UINT16 val;
+
+ if(m_t1_active)
+ {
+ val = time_to_cycles(m_t1->remaining()) - IFR_DELAY;
+ }
+ else
+ {
+ val = 0xffff - time_to_cycles(machine().time() - m_time1);
+ }
+
+ return val;
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type VIA6522 = &device_creator<via6522_device>;
+
+//-------------------------------------------------
+// via6522_device - constructor
+//-------------------------------------------------
+
+via6522_device::via6522_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, VIA6522, "6522 VIA", tag, owner, clock)
+{
+
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void via6522_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const via6522_interface *intf = reinterpret_cast<const via6522_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<via6522_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_in_a_cb, 0, sizeof(m_in_a_cb));
+ memset(&m_in_b_cb, 0, sizeof(m_in_b_cb));
+ memset(&m_in_ca1_cb, 0, sizeof(m_in_ca1_cb));
+ memset(&m_in_cb1_cb, 0, sizeof(m_in_cb1_cb));
+ memset(&m_in_ca2_cb, 0, sizeof(m_in_ca2_cb));
+ memset(&m_in_cb2_cb, 0, sizeof(m_in_cb2_cb));
+ memset(&m_out_a_cb, 0, sizeof(m_out_a_cb));
+ memset(&m_out_b_cb, 0, sizeof(m_out_b_cb));
+ memset(&m_out_ca2_cb, 0, sizeof(m_out_ca2_cb));
+ memset(&m_out_cb2_cb, 0, sizeof(m_out_cb2_cb));
+ memset(&m_irq_cb, 0, sizeof(m_irq_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void via6522_device::device_start()
+{
+ m_in_a_func.resolve(m_in_a_cb, *this);
+ m_in_b_func.resolve(m_in_b_cb, *this);
+ m_in_ca1_func.resolve(m_in_ca1_cb, *this);
+ m_in_cb1_func.resolve(m_in_cb1_cb, *this);
+ m_in_ca2_func.resolve(m_in_ca2_cb, *this);
+ m_in_cb2_func.resolve(m_in_cb2_cb, *this);
+ m_out_a_func.resolve(m_out_a_cb, *this);
+ m_out_b_func.resolve(m_out_b_cb, *this);
+ m_out_ca1_func.resolve(m_out_ca1_cb, *this);
+ m_out_cb1_func.resolve(m_out_cb1_cb, *this);
+ m_out_ca2_func.resolve(m_out_ca2_cb, *this);
+ m_out_cb2_func.resolve(m_out_cb2_cb, *this);
+ m_irq_func.resolve(m_irq_cb, *this);
+
+ m_t1ll = 0xf3; /* via at 0x9110 in vic20 show these values */
+ m_t1lh = 0xb5; /* ports are not written by kernel! */
+ m_t2ll = 0xff; /* taken from vice */
+ m_t2lh = 0xff;
+ m_time2 = m_time1 = machine().time();
+ m_t1 = timer_alloc(TIMER_T1);
+ m_t2 = timer_alloc(TIMER_T2);
+ m_shift_timer = timer_alloc(TIMER_SHIFT);
+
+ /* Default clock is from CPU1 */
+ if (clock() == 0)
+ {
+ set_unscaled_clock(machine().firstcpu->clock());
+ }
+
+ /* save state register */
+ save_item(NAME(m_in_a));
+ save_item(NAME(m_in_ca1));
+ save_item(NAME(m_in_ca2));
+ save_item(NAME(m_out_a));
+ save_item(NAME(m_out_ca2));
+ save_item(NAME(m_ddr_a));
+ save_item(NAME(m_in_b));
+ save_item(NAME(m_in_cb1));
+ save_item(NAME(m_in_cb2));
+ save_item(NAME(m_out_b));
+ save_item(NAME(m_out_cb2));
+ save_item(NAME(m_ddr_b));
+ save_item(NAME(m_t1cl));
+ save_item(NAME(m_t1ch));
+ save_item(NAME(m_t1ll));
+ save_item(NAME(m_t1lh));
+ save_item(NAME(m_t2cl));
+ save_item(NAME(m_t2ch));
+ save_item(NAME(m_t2ll));
+ save_item(NAME(m_t2lh));
+ save_item(NAME(m_sr));
+ save_item(NAME(m_pcr));
+ save_item(NAME(m_acr));
+ save_item(NAME(m_ier));
+ save_item(NAME(m_ifr));
+ save_item(NAME(m_t1_active));
+ save_item(NAME(m_t2_active));
+ save_item(NAME(m_shift_counter));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void via6522_device::device_reset()
+{
+ m_in_a = 0;
+ m_in_ca1 = 0;
+ m_in_ca2 = 0;
+ m_out_a = 0;
+ m_out_ca2 = 0;
+ m_ddr_a = 0;
+ m_in_b = 0;
+ m_in_cb1 = 0;
+ m_in_cb2 = 0;
+ m_out_b = 0;
+ m_out_cb2 = 0;
+ m_ddr_b = 0;
+
+ m_t1cl = 0;
+ m_t1ch = 0;
+ m_t2cl = 0;
+ m_t2ch = 0;
+
+ m_sr = 0;
+ m_pcr = 0;
+ m_acr = 0;
+ m_ier = 0;
+ m_ifr = 0;
+ m_t1_active = 0;
+ m_t2_active = 0;
+ m_shift_counter = 0;
+}
+
+
+/*-------------------------------------------------
+ via_set_int - external interrupt check
+-------------------------------------------------*/
+
+void via6522_device::set_int(int data)
+{
+ m_ifr |= data;
+ if (TRACE_VIA)
+ {
+ logerror("%s:6522VIA chip %s: IFR = %02X\n", machine().describe_context(), tag(), m_ifr);
+ }
+
+ if (m_ier & m_ifr)
+ {
+ m_ifr |= INT_ANY;
+ m_irq_func(ASSERT_LINE);
+ }
+}
+
+
+/*-------------------------------------------------
+ via_clear_int - external interrupt check
+-------------------------------------------------*/
+
+void via6522_device::clear_int(int data)
+{
+ m_ifr = (m_ifr & ~data) & 0x7f;
+
+ if (TRACE_VIA)
+ {
+ logerror("%s:6522VIA chip %s: IFR = %02X\n", machine().describe_context(), tag(), m_ifr);
+ }
+
+ if (m_ifr & m_ier)
+ {
+ m_ifr |= INT_ANY;
+ }
+ else
+ {
+ m_irq_func(CLEAR_LINE);
+ }
+}
+
+
+/*-------------------------------------------------
+ via_shift
+-------------------------------------------------*/
+
+void via6522_device::shift()
+{
+ if (SO_O2_CONTROL(m_acr) || SO_T2_CONTROL(m_acr))
+ {
+ m_out_cb2 = (m_sr >> 7) & 1;
+ m_sr = (m_sr << 1) | m_out_cb2;
+
+ m_out_cb2_func(m_out_cb2);
+
+ m_in_cb1=1;
+
+ /* this should be one cycle wide */
+ m_out_cb1_func(0);
+ m_out_cb1_func(1);
+
+ m_shift_counter = (m_shift_counter + 1) % 8;
+
+ if (m_shift_counter)
+ {
+ if (SO_O2_CONTROL(m_acr)) {
+ m_shift_timer->adjust(cycles_to_time(2));
+ } else {
+ m_shift_timer->adjust(cycles_to_time((m_t2ll + 2)*2));
+ }
+ }
+ else
+ {
+ if (!(m_ifr & INT_SR))
+ {
+ set_int(INT_SR);
+ }
+ }
+ }
+ if (SO_EXT_CONTROL(m_acr))
+ {
+ m_out_cb2 = (m_sr >> 7) & 1;
+ m_sr = (m_sr << 1) | m_out_cb2;
+
+ m_out_cb2_func(m_out_cb2);
+
+ m_shift_counter = (m_shift_counter + 1) % 8;
+
+ if (m_shift_counter == 0)
+ {
+ if (!(m_ifr & INT_SR))
+ {
+ set_int(INT_SR);
+ }
+ }
+ }
+ if (SI_EXT_CONTROL(m_acr))
+ {
+ if (!m_in_cb2_func.isnull())
+ {
+ m_in_cb2 = m_in_cb2_func();
+ }
+
+ m_sr = (m_sr << 1) | (m_in_cb2 & 1);
+
+ m_shift_counter = (m_shift_counter + 1) % 8;
+
+ if (m_shift_counter == 0)
+ {
+ if (!(m_ifr & INT_SR))
+ {
+ set_int(INT_SR);
+ }
+ }
+ }
+}
+
+
+void via6522_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ // shift timer
+ case TIMER_SHIFT:
+ shift();
+ break;
+
+ // t1 timeout
+ case TIMER_T1:
+ if (T1_CONTINUOUS (m_acr))
+ {
+ if (T1_SET_PB7(m_acr))
+ {
+ m_out_b ^= 0x80;
+ }
+ m_t1->adjust(cycles_to_time(TIMER1_VALUE + IFR_DELAY));
+ }
+ else
+ {
+ if (T1_SET_PB7(m_acr))
+ {
+ m_out_b |= 0x80;
+ }
+ m_t1_active = 0;
+ m_time1 = machine().time();
+ }
+ if (m_ddr_b)
+ {
+ UINT8 write_data = (m_out_b & m_ddr_b) | (m_ddr_b ^ 0xff);
+ m_out_b_func(0, write_data);
+ }
+
+ if (!(m_ifr & INT_T1))
+ {
+ set_int(INT_T1);
+ }
+ break;
+
+ // t2 timeout
+ case TIMER_T2:
+ m_t2_active = 0;
+ m_time2 = machine().time();
+
+ if (!(m_ifr & INT_T2))
+ {
+ set_int(INT_T2);
+ }
+ break;
+ }
+}
+
+/*-------------------------------------------------
+ via_r - CPU interface for VIA read
+-------------------------------------------------*/
+
+READ8_MEMBER( via6522_device::read )
+{
+ int val = 0;
+
+ offset &= 0xf;
+
+ switch (offset)
+ {
+ case VIA_PB:
+ /* update the input */
+ if (PB_LATCH_ENABLE(m_acr) == 0)
+ {
+ if (m_ddr_b != 0xff)
+ {
+ if (!m_in_b_func.isnull())
+ {
+ m_in_b = m_in_b_func(0);
+ }
+ else
+ {
+ logerror("%s:6522VIA chip %s: Port B is being read but has no handler\n", machine().describe_context(), tag());
+ }
+ }
+ }
+
+ CLR_PB_INT();
+
+ /* combine input and output values, hold DDRB bit 7 high if T1_SET_PB7 */
+ if (T1_SET_PB7(m_acr))
+ {
+ val = (m_out_b & (m_ddr_b | 0x80)) | (m_in_b & ~(m_ddr_b | 0x80));
+ }
+ else
+ {
+ val = (m_out_b & m_ddr_b) + (m_in_b & ~m_ddr_b);
+ }
+ break;
+
+ case VIA_PA:
+ /* update the input */
+ if (PA_LATCH_ENABLE(m_acr) == 0)
+ {
+ if (m_ddr_a != 0xff)
+ {
+ if (!m_in_a_func.isnull())
+ {
+ m_in_a = m_in_a_func(0);
+ }
+ else
+ {
+ logerror("%s:6522VIA chip %s: Port A is being read but has no handler\n", machine().describe_context(), tag());
+ }
+ }
+ }
+
+ /* combine input and output values */
+ val = (m_out_a & m_ddr_a) + (m_in_a & ~m_ddr_a);
+
+ CLR_PA_INT();
+
+ /* If CA2 is configured as output and in pulse or handshake mode,
+ CA2 is set now */
+ if (CA2_AUTO_HS(m_pcr))
+ {
+ if (m_out_ca2)
+ {
+ /* set CA2 */
+ m_out_ca2 = 0;
+
+ /* call the CA2 output function */
+ m_out_ca2_func(0);
+ }
+ }
+
+ break;
+
+ case VIA_PANH:
+ /* update the input */
+ if (PA_LATCH_ENABLE(m_acr) == 0)
+ {
+ if (!m_in_a_func.isnull())
+ {
+ m_in_a = m_in_a_func(0);
+ }
+ else
+ {
+ logerror("%s:6522VIA chip %s: Port A is being read but has no handler\n", machine().describe_context(), tag());
+ }
+ }
+
+ /* combine input and output values */
+ val = (m_out_a & m_ddr_a) + (m_in_a & ~m_ddr_a);
+ break;
+
+ case VIA_DDRB:
+ val = m_ddr_b;
+ break;
+
+ case VIA_DDRA:
+ val = m_ddr_a;
+ break;
+
+ case VIA_T1CL:
+ clear_int(INT_T1);
+ val = get_counter1_value() & 0xFF;
+ break;
+
+ case VIA_T1CH:
+ val = get_counter1_value() >> 8;
+ break;
+
+ case VIA_T1LL:
+ val = m_t1ll;
+ break;
+
+ case VIA_T1LH:
+ val = m_t1lh;
+ break;
+
+ case VIA_T2CL:
+ clear_int(INT_T2);
+ if (m_t2_active)
+ {
+ val = time_to_cycles(m_t2->remaining()) & 0xff;
+ }
+ else
+ {
+ if (T2_COUNT_PB6(m_acr))
+ {
+ val = m_t2cl;
+ }
+ else
+ {
+ val = (0x10000 - (time_to_cycles(machine().time() - m_time2) & 0xffff) - 1) & 0xff;
+ }
+ }
+ break;
+
+ case VIA_T2CH:
+ if (m_t2_active)
+ {
+ val = time_to_cycles(m_t2->remaining()) >> 8;
+ }
+ else
+ {
+ if (T2_COUNT_PB6(m_acr))
+ {
+ val = m_t2ch;
+ }
+ else
+ {
+ val = (0x10000 - (time_to_cycles(machine().time() - m_time2) & 0xffff) - 1) >> 8;
+ }
+ }
+ break;
+
+ case VIA_SR:
+ val = m_sr;
+ m_shift_counter=0;
+ clear_int(INT_SR);
+ if (SO_O2_CONTROL(m_acr))
+ {
+ m_shift_timer->adjust(cycles_to_time(2));
+ }
+ if (SO_T2_CONTROL(m_acr))
+ {
+ m_shift_timer->adjust(cycles_to_time((m_t2ll + 2)*2));
+ }
+ break;
+
+ case VIA_PCR:
+ val = m_pcr;
+ break;
+
+ case VIA_ACR:
+ val = m_acr;
+ break;
+
+ case VIA_IER:
+ val = m_ier | 0x80;
+ break;
+
+ case VIA_IFR:
+ val = m_ifr;
+ break;
+ }
+ return val;
+}
+
+
+/*-------------------------------------------------
+ via_w - CPU interface for VIA write
+-------------------------------------------------*/
+
+WRITE8_MEMBER( via6522_device::write )
+{
+ offset &=0x0f;
+
+ switch (offset)
+ {
+ case VIA_PB:
+ if (T1_SET_PB7(m_acr))
+ m_out_b = (m_out_b & 0x80) | (data & 0x7f);
+ else
+ m_out_b = data;
+
+ if (m_ddr_b)
+ {
+ UINT8 write_data = (m_out_b & m_ddr_b) | (m_ddr_b ^ 0xff);
+ m_out_b_func(0, write_data);
+ }
+
+ CLR_PB_INT();
+
+ /* If CB2 is configured as output and in pulse or handshake mode,
+ CB2 is set now */
+ if (CB2_AUTO_HS(m_pcr))
+ {
+ if (m_out_cb2)
+ {
+ /* set CB2 */
+ m_out_cb2 = 0;
+
+ /* call the CB2 output function */
+ m_out_cb2_func(0);
+ }
+ }
+ break;
+
+ case VIA_PA:
+ m_out_a = data;
+
+ if (m_ddr_a)
+ {
+ UINT8 write_data = (m_out_a & m_ddr_a) | (m_ddr_a ^ 0xff);
+ m_out_a_func(0, write_data);
+ }
+
+ CLR_PA_INT();
+
+ /* If CA2 is configured as output and in pulse or handshake mode,
+ CA2 is set now */
+ if (CA2_PULSE_OUTPUT(m_pcr))
+ {
+ /* call the CA2 output function */
+ m_out_ca2_func(0);
+ m_out_ca2_func(1);
+
+ /* set CA2 (shouldn't be needed) */
+ m_out_ca2 = 1;
+ }
+ else if (CA2_AUTO_HS(m_pcr))
+ {
+ if (m_out_ca2)
+ {
+ /* set CA2 */
+ m_out_ca2 = 0;
+
+ /* call the CA2 output function */
+ m_out_ca2_func(0);
+ }
+ }
+
+ break;
+
+ case VIA_PANH:
+ m_out_a = data;
+
+ if (m_ddr_a)
+ {
+ UINT8 write_data = (m_out_a & m_ddr_a) | (m_ddr_a ^ 0xff);
+ m_out_a_func(0, write_data);
+ }
+
+ break;
+
+ case VIA_DDRB:
+ /* EHC 03/04/2000 - If data direction changed, present output on the lines */
+ if ( data != m_ddr_b )
+ {
+ m_ddr_b = data;
+
+ //if (m_ddr_b)
+ {
+ UINT8 write_data = (m_out_b & m_ddr_b) | (m_ddr_b ^ 0xff);
+ m_out_b_func(0, write_data);
+ }
+ }
+ break;
+
+ case VIA_DDRA:
+ /* EHC 03/04/2000 - If data direction changed, present output on the lines */
+ if ( data != m_ddr_a )
+ {
+ m_ddr_a = data;
+
+ //if (m_ddr_a)
+ {
+ UINT8 write_data = (m_out_a & m_ddr_a) | (m_ddr_a ^ 0xff);
+ m_out_a_func(0, write_data);
+ }
+ }
+ break;
+
+ case VIA_T1CL:
+ case VIA_T1LL:
+ m_t1ll = data;
+ break;
+
+ case VIA_T1LH:
+ m_t1lh = data;
+ clear_int(INT_T1);
+ break;
+
+ case VIA_T1CH:
+ m_t1ch = m_t1lh = data;
+ m_t1cl = m_t1ll;
+
+ clear_int(INT_T1);
+
+ if (T1_SET_PB7(m_acr))
+ {
+ m_out_b &= 0x7f;
+
+ //if (m_ddr_b)
+ {
+ UINT8 write_data = (m_out_b & m_ddr_b) | (m_ddr_b ^ 0xff);
+ m_out_b_func(0, write_data);
+ }
+ }
+ m_t1->adjust(cycles_to_time(TIMER1_VALUE + IFR_DELAY));
+ m_t1_active = 1;
+ break;
+
+ case VIA_T2CL:
+ m_t2ll = data;
+ break;
+
+ case VIA_T2CH:
+ m_t2ch = m_t2lh = data;
+ m_t2cl = m_t2ll;
+
+ clear_int(INT_T2);
+
+ if (!T2_COUNT_PB6(m_acr))
+ {
+ m_t2->adjust(cycles_to_time(TIMER2_VALUE + IFR_DELAY));
+ m_t2_active = 1;
+ }
+ else
+ {
+ m_t2->adjust(cycles_to_time(TIMER2_VALUE));
+ m_t2_active = 1;
+ m_time2 = machine().time();
+ }
+ break;
+
+ case VIA_SR:
+ m_sr = data;
+ m_shift_counter=0;
+ clear_int(INT_SR);
+ if (SO_O2_CONTROL(m_acr))
+ {
+ m_shift_timer->adjust(cycles_to_time(2));
+ }
+ if (SO_T2_CONTROL(m_acr))
+ {
+ m_shift_timer->adjust(cycles_to_time((m_t2ll + 2)*2));
+ }
+ break;
+
+ case VIA_PCR:
+ m_pcr = data;
+
+ if (TRACE_VIA)
+ {
+ logerror("%s:6522VIA chip %s: PCR = %02X\n", machine().describe_context(), tag(), data);
+ }
+
+ if (CA2_FIX_OUTPUT(data) && CA2_OUTPUT_LEVEL(data) ^ m_out_ca2)
+ {
+ m_out_ca2 = CA2_OUTPUT_LEVEL(data);
+ m_out_ca2_func(m_out_ca2);
+ }
+
+ if (CB2_FIX_OUTPUT(data) && CB2_OUTPUT_LEVEL(data) ^ m_out_cb2)
+ {
+ m_out_cb2 = CB2_OUTPUT_LEVEL(data);
+ m_out_cb2_func(m_out_cb2);
+ }
+ break;
+
+ case VIA_ACR:
+ {
+ UINT16 counter1 = get_counter1_value();
+ m_acr = data;
+ if (T1_SET_PB7(m_acr))
+ {
+ if (m_t1_active)
+ {
+ m_out_b &= ~0x80;
+ }
+ else
+ {
+ m_out_b |= 0x80;
+ }
+
+ //if (m_ddr_b)
+ {
+ UINT8 write_data = (m_out_b & m_ddr_b) | (m_ddr_b ^ 0xff);
+ m_out_b_func(0, write_data);
+ }
+ }
+ if (T1_CONTINUOUS(data))
+ {
+ m_t1->adjust(cycles_to_time(counter1 + IFR_DELAY));
+ m_t1_active = 1;
+ }
+ }
+ break;
+
+ case VIA_IER:
+ if (data & 0x80)
+ {
+ m_ier |= data & 0x7f;
+ }
+ else
+ {
+ m_ier &= ~(data & 0x7f);
+ }
+
+ if (m_ifr & INT_ANY)
+ {
+ if (((m_ifr & m_ier) & 0x7f) == 0)
+ {
+ m_ifr &= ~INT_ANY;
+ m_irq_func(CLEAR_LINE);
+ }
+ }
+ else
+ {
+ if ((m_ier & m_ifr) & 0x7f)
+ {
+ m_ifr |= INT_ANY;
+ m_irq_func(ASSERT_LINE);
+ }
+ }
+ break;
+
+ case VIA_IFR:
+ if (data & INT_ANY)
+ {
+ data = 0x7f;
+ }
+ clear_int(data);
+ break;
+ }
+}
+
+
+/*-------------------------------------------------
+ ca1_w - interface setting VIA port CA1 input
+-------------------------------------------------*/
+
+WRITE_LINE_MEMBER( via6522_device::write_ca1 )
+{
+ /* handle the active transition */
+ if (state != m_in_ca1)
+ {
+ if (TRACE_VIA)
+ logerror("%s:6522VIA chip %s: CA1 = %02X\n", machine().describe_context(), tag(), state);
+
+ if ((CA1_LOW_TO_HIGH(m_pcr) && state) || (CA1_HIGH_TO_LOW(m_pcr) && !state))
+ {
+ if (PA_LATCH_ENABLE(m_acr))
+ {
+ if (!m_in_a_func.isnull())
+ {
+ m_in_a = m_in_a_func(0);
+ }
+ else
+ {
+ logerror("%s:6522VIA chip %s: Port A is being read but has no handler\n", machine().describe_context(), tag());
+ }
+ }
+
+ set_int(INT_CA1);
+
+ /* CA2 is configured as output and in pulse or handshake mode,
+ CA2 is cleared now */
+ if (CA2_AUTO_HS(m_pcr))
+ {
+ if (!m_out_ca2)
+ {
+ /* clear CA2 */
+ m_out_ca2 = 1;
+
+ /* call the CA2 output function */
+ m_out_ca2_func(1);
+ }
+ }
+ }
+
+ m_in_ca1 = state;
+ }
+}
+
+
+/*-------------------------------------------------
+ ca2_w - interface setting VIA port CA2 input
+-------------------------------------------------*/
+
+WRITE_LINE_MEMBER( via6522_device::write_ca2 )
+{
+ /* CA2 is in input mode */
+ if (CA2_INPUT(m_pcr))
+ {
+ /* the new state has caused a transition */
+ if (m_in_ca2 != state)
+ {
+ /* handle the active transition */
+ if ((state && CA2_LOW_TO_HIGH(m_pcr)) || (!state && CA2_HIGH_TO_LOW(m_pcr)))
+ {
+ /* mark the IRQ */
+ set_int(INT_CA2);
+ }
+ /* set the new value for CA2 */
+ m_in_ca2 = state;
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ cb1_w - interface setting VIA port CB1 input
+-------------------------------------------------*/
+
+WRITE_LINE_MEMBER( via6522_device::write_cb1 )
+{
+ /* handle the active transition */
+ if (state != m_in_cb1)
+ {
+ if ((CB1_LOW_TO_HIGH(m_pcr) && state) || (CB1_HIGH_TO_LOW(m_pcr) && !state))
+ {
+ if (PB_LATCH_ENABLE(m_acr))
+ {
+ if (!m_in_b_func.isnull())
+ {
+ m_in_b = m_in_b_func(0);
+ }
+ else
+ {
+ logerror("%s:6522VIA chip %s: Port B is being read but has no handler\n", machine().describe_context(), tag());
+ }
+ }
+ if (SO_EXT_CONTROL(m_acr) || SI_EXT_CONTROL(m_acr))
+ {
+ shift();
+ }
+
+ set_int(INT_CB1);
+
+ /* CB2 is configured as output and in pulse or handshake mode,
+ CB2 is cleared now */
+ if (CB2_AUTO_HS(m_pcr))
+ {
+ if (!m_out_cb2)
+ {
+ /* clear CB2 */
+ m_out_cb2 = 1;
+
+ /* call the CB2 output function */
+ m_out_cb2_func(1);
+ }
+ }
+ }
+ m_in_cb1 = state;
+ }
+}
+
+
+/*-------------------------------------------------
+ cb2_w - interface setting VIA port CB2 input
+-------------------------------------------------*/
+
+WRITE_LINE_MEMBER( via6522_device::write_cb2 )
+{
+ /* CB2 is in input mode */
+ if (CB2_INPUT(m_pcr))
+ {
+ /* the new state has caused a transition */
+ if (m_in_cb2 != state)
+ {
+ /* handle the active transition */
+ if ((state && CB2_LOW_TO_HIGH(m_pcr)) || (!state && CB2_HIGH_TO_LOW(m_pcr)))
+ {
+ /* mark the IRQ */
+ set_int(INT_CB2);
+ }
+ /* set the new value for CB2 */
+ m_in_cb2 = state;
+ }
+ }
+}
diff --git a/trunk/src/emu/machine/6522via.h b/trunk/src/emu/machine/6522via.h
new file mode 100644
index 00000000000..ba3373a133e
--- /dev/null
+++ b/trunk/src/emu/machine/6522via.h
@@ -0,0 +1,190 @@
+/**********************************************************************
+
+ Rockwell 6522 VIA interface and emulation
+
+ This function emulates all the functionality of 6522
+ versatile interface adapters.
+
+ This is based on the pre-existing 6821 emulation.
+
+ Written by Mathis Rosenhauer
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __6522VIA_H__
+#define __6522VIA_H__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_VIA6522_ADD(_tag, _clock, _intrf) \
+ MCFG_DEVICE_ADD(_tag, VIA6522, _clock) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+
+
+/***************************************************************************
+ MACROS / CONSTANTS
+***************************************************************************/
+
+#define VIA_PB 0
+#define VIA_PA 1
+#define VIA_DDRB 2
+#define VIA_DDRA 3
+#define VIA_T1CL 4
+#define VIA_T1CH 5
+#define VIA_T1LL 6
+#define VIA_T1LH 7
+#define VIA_T2CL 8
+#define VIA_T2CH 9
+#define VIA_SR 10
+#define VIA_ACR 11
+#define VIA_PCR 12
+#define VIA_IFR 13
+#define VIA_IER 14
+#define VIA_PANH 15
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+
+// ======================> via6522_interface
+
+struct via6522_interface
+{
+ devcb_read8 m_in_a_cb;
+ devcb_read8 m_in_b_cb;
+ devcb_read_line m_in_ca1_cb;
+ devcb_read_line m_in_cb1_cb;
+ devcb_read_line m_in_ca2_cb;
+ devcb_read_line m_in_cb2_cb;
+ devcb_write8 m_out_a_cb;
+ devcb_write8 m_out_b_cb;
+ devcb_write_line m_out_ca1_cb;
+ devcb_write_line m_out_cb1_cb;
+ devcb_write_line m_out_ca2_cb;
+ devcb_write_line m_out_cb2_cb;
+ devcb_write_line m_irq_cb;
+};
+
+
+// ======================> via6522_device
+
+class via6522_device : public device_t,
+ public via6522_interface
+{
+ friend class dart_channel;
+
+public:
+ // construction/destruction
+ via6522_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_READ8_MEMBER( read );
+ DECLARE_WRITE8_MEMBER( write );
+
+ DECLARE_WRITE8_MEMBER( write_porta ) { m_in_a = data; }
+
+ DECLARE_READ8_MEMBER( read_portb ) { return m_in_b; }
+ DECLARE_WRITE8_MEMBER( write_portb ) { m_in_b = data; }
+
+ DECLARE_READ_LINE_MEMBER( read_ca1 ) { return m_in_ca1; }
+ DECLARE_WRITE_LINE_MEMBER( write_ca1 );
+
+ DECLARE_READ_LINE_MEMBER( read_ca2 ) { return m_in_ca2; }
+ DECLARE_WRITE_LINE_MEMBER( write_ca2 );
+
+ DECLARE_READ_LINE_MEMBER( read_cb1 ) { return m_in_cb1; }
+ DECLARE_WRITE_LINE_MEMBER( write_cb1 );
+
+ DECLARE_READ_LINE_MEMBER( read_cb2 ) { return m_in_cb2; }
+ DECLARE_WRITE_LINE_MEMBER( write_cb2 );
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+private:
+ static const device_timer_id TIMER_SHIFT = 0;
+ static const device_timer_id TIMER_T1 = 1;
+ static const device_timer_id TIMER_T2 = 2;
+
+ attotime cycles_to_time(int c);
+ UINT32 time_to_cycles(attotime t);
+ UINT16 get_counter1_value();
+
+ void set_int(int data);
+ void clear_int(int data);
+ void shift();
+
+ devcb_resolved_read8 m_in_a_func;
+ devcb_resolved_read8 m_in_b_func;
+ devcb_resolved_read_line m_in_ca1_func;
+ devcb_resolved_read_line m_in_cb1_func;
+ devcb_resolved_read_line m_in_ca2_func;
+ devcb_resolved_read_line m_in_cb2_func;
+ devcb_resolved_write8 m_out_a_func;
+ devcb_resolved_write8 m_out_b_func;
+ devcb_resolved_write_line m_out_ca1_func;
+ devcb_resolved_write_line m_out_cb1_func;
+ devcb_resolved_write_line m_out_ca2_func;
+ devcb_resolved_write_line m_out_cb2_func;
+ devcb_resolved_write_line m_irq_func;
+
+ UINT8 m_in_a;
+ UINT8 m_in_ca1;
+ UINT8 m_in_ca2;
+ UINT8 m_out_a;
+ UINT8 m_out_ca2;
+ UINT8 m_ddr_a;
+
+ UINT8 m_in_b;
+ UINT8 m_in_cb1;
+ UINT8 m_in_cb2;
+ UINT8 m_out_b;
+ UINT8 m_out_cb2;
+ UINT8 m_ddr_b;
+
+ UINT8 m_t1cl;
+ UINT8 m_t1ch;
+ UINT8 m_t1ll;
+ UINT8 m_t1lh;
+ UINT8 m_t2cl;
+ UINT8 m_t2ch;
+ UINT8 m_t2ll;
+ UINT8 m_t2lh;
+
+ UINT8 m_sr;
+ UINT8 m_pcr;
+ UINT8 m_acr;
+ UINT8 m_ier;
+ UINT8 m_ifr;
+
+ emu_timer *m_t1;
+ attotime m_time1;
+ UINT8 m_t1_active;
+ emu_timer *m_t2;
+ attotime m_time2;
+ UINT8 m_t2_active;
+
+ emu_timer *m_shift_timer;
+ UINT8 m_shift_counter;
+};
+
+
+// device type definition
+extern const device_type VIA6522;
+
+
+#endif /* __6522VIA_H__ */
diff --git a/trunk/src/emu/machine/6525tpi.c b/trunk/src/emu/machine/6525tpi.c
new file mode 100644
index 00000000000..db0709fc7fc
--- /dev/null
+++ b/trunk/src/emu/machine/6525tpi.c
@@ -0,0 +1,623 @@
+/***************************************************************************
+ mos tri port interface 6525
+ mos triple interface adapter 6523
+
+ peter.trauner@jk.uni-linz.ac.at
+
+ used in commodore b series
+ used in commodore c1551 floppy disk drive
+***************************************************************************/
+
+/*
+ mos tpi 6525
+ 40 pin package
+ 3 8 bit ports (pa, pb, pc)
+ 8 registers to pc
+ 0 port a 0 in low
+ 1 port a data direction register 1 output
+ 2 port b
+ 3 port b ddr
+ 4 port c
+ handshaking, interrupt mode
+ 0 interrupt 0 input, 1 interrupt enabled
+ interrupt set on falling edge
+ 1 interrupt 1 input
+ 2 interrupt 2 input
+ 3 interrupt 3 input
+ 4 interrupt 4 input
+ 5 irq output
+ 6 ca handshake line (read handshake answer on I3 preferred)
+ 7 cb handshake line (write handshake clear on I4 preferred)
+ 5 port c ddr
+
+ 6 cr configuration register
+ 0 mc
+ 0 port c normal input output mode like port a and b
+ 1 port c used for handshaking and interrupt input
+ 1 1 interrupt prioritized
+ 2 i3 configure edge
+ 1 interrupt set on positive edge
+ 3 i4 configure edge
+ 5,4 ca handshake
+ 00 on read
+ rising edge of i3 sets ca high
+ read a data from computers sets ca low
+ 01 pulse output
+ 1 microsecond low after read a operation
+ 10 manual output low
+ 11 manual output high
+ 7,6 cb handshake
+ 00 handshake on write
+ write b data from computer sets cb 0
+ rising edge of i4 sets cb high
+ 01 pulse output
+ 1 microsecond low after write b operation
+ 10 manual output low
+ 11 manual output high
+ 7 air active interrupt register
+ 0 I0 occurred
+ 1 I1 occurred
+ 2 I2 occurred
+ 3 I3 occurred
+ 4 I4 occurred
+ read clears interrupt
+
+ non prioritized interrupts
+ interrupt is set when occurred
+ read clears all interrupts
+
+ prioritized interrupts
+ I4>I3>I2>I1>I0
+ highest interrupt can be found in air register
+ read clears highest interrupt
+*/
+
+#include "emu.h"
+#include "6525tpi.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define VERBOSE_LEVEL 0
+#define DBG_LOG( MACHINE, N, M, A ) \
+ do { \
+ if(VERBOSE_LEVEL >= N) \
+ { \
+ if( M ) \
+ logerror("%11.6f: %-24s", MACHINE.time().as_double(), (char*) M ); \
+ logerror A; \
+ } \
+ } while (0)
+
+
+#define INTERRUPT_MODE (tpi6525->cr & 1)
+#define PRIORIZED_INTERRUPTS (tpi6525->cr & 2)
+#define INTERRUPT3_RISING_EDGE (tpi6525->cr & 4)
+#define INTERRUPT4_RISING_EDGE (tpi6525->cr & 8)
+#define CA_MANUAL_OUT (tpi6525->cr & 0x20)
+#define CA_MANUAL_LEVEL ((tpi6525->cr & 0x10) ? 1 : 0)
+#define CB_MANUAL_OUT (tpi6525->cr & 0x80)
+#define CB_MANUAL_LEVEL ((tpi6525->cr & 0x40) ? 1 : 0)
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _tpi6525_state tpi6525_state;
+struct _tpi6525_state
+{
+ devcb_resolved_write_line out_irq_func;
+ devcb_resolved_read8 in_pa_func;
+ devcb_resolved_write8 out_pa_func;
+ devcb_resolved_read8 in_pb_func;
+ devcb_resolved_write8 out_pb_func;
+ devcb_resolved_read8 in_pc_func;
+ devcb_resolved_write8 out_pc_func;
+ devcb_resolved_write_line out_ca_func;
+ devcb_resolved_write_line out_cb_func;
+
+ UINT8 port_a, ddr_a, in_a;
+ UINT8 port_b, ddr_b, in_b;
+ UINT8 port_c, ddr_c, in_c;
+
+ UINT8 ca_level, cb_level, interrupt_level;
+
+ UINT8 cr;
+ UINT8 air;
+
+ UINT8 irq_level[5];
+};
+
+
+/*****************************************************************************
+ INLINE FUNCTIONS
+*****************************************************************************/
+
+INLINE tpi6525_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == TPI6525);
+
+ return (tpi6525_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+/*****************************************************************************
+ DEVICE INTERFACE
+*****************************************************************************/
+
+static DEVICE_START( tpi6525 )
+{
+ tpi6525_state *tpi6525 = get_safe_token(device);
+ const tpi6525_interface *intf = (const tpi6525_interface*)device->static_config();
+
+ // resolve callbacks
+ tpi6525->out_irq_func.resolve(intf->out_irq_func, *device);
+ tpi6525->in_pa_func.resolve(intf->in_pa_func, *device);
+ tpi6525->out_pa_func.resolve(intf->out_pa_func, *device);
+ tpi6525->in_pb_func.resolve(intf->in_pb_func, *device);
+ tpi6525->out_pb_func.resolve(intf->out_pb_func, *device);
+ tpi6525->in_pc_func.resolve(intf->in_pc_func, *device);
+ tpi6525->out_pc_func.resolve(intf->out_pc_func, *device);
+ tpi6525->out_ca_func.resolve(intf->out_ca_func, *device);
+ tpi6525->out_cb_func.resolve(intf->out_cb_func, *device);
+
+ /* verify that we have an interface assigned */
+ assert(device->static_config() != NULL);
+
+ /* register for state saving */
+ device->save_item(NAME(tpi6525->port_a));
+ device->save_item(NAME(tpi6525->ddr_a));
+ device->save_item(NAME(tpi6525->in_a));
+ device->save_item(NAME(tpi6525->port_b));
+ device->save_item(NAME(tpi6525->ddr_b));
+ device->save_item(NAME(tpi6525->in_b));
+ device->save_item(NAME(tpi6525->port_c));
+ device->save_item(NAME(tpi6525->ddr_c));
+ device->save_item(NAME(tpi6525->in_c));
+ device->save_item(NAME(tpi6525->ca_level));
+ device->save_item(NAME(tpi6525->cb_level));
+ device->save_item(NAME(tpi6525->interrupt_level));
+ device->save_item(NAME(tpi6525->cr));
+ device->save_item(NAME(tpi6525->air));
+ device->save_item(NAME(tpi6525->irq_level));
+}
+
+
+static DEVICE_RESET( tpi6525 )
+{
+ tpi6525_state *tpi6525 = get_safe_token(device);
+
+ /* setup some initial values */
+ tpi6525->in_a = 0xff;
+ tpi6525->in_b = 0xff;
+ tpi6525->in_c = 0xff;
+}
+
+
+DEVICE_GET_INFO( tpi6525 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(tpi6525_state); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( tpi6525 ); break;
+ case DEVINFO_FCT_STOP: /* Nothing */ break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME( tpi6525 ); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "6525 TPI"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "6525 TPI"); 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 MESS Team"); break;
+ }
+}
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+static void tpi6525_set_interrupt(device_t *device)
+{
+ tpi6525_state *tpi6525 = get_safe_token(device);
+
+ if (!tpi6525->interrupt_level && (tpi6525->air != 0))
+ {
+ tpi6525->interrupt_level = 1;
+
+ DBG_LOG(device->machine(), 3, "tpi6525", ("%s set interrupt\n", device->tag()));
+
+ tpi6525->out_irq_func(tpi6525->interrupt_level);
+ }
+}
+
+
+static void tpi6525_clear_interrupt(device_t *device)
+{
+ tpi6525_state *tpi6525 = get_safe_token(device);
+
+ if (tpi6525->interrupt_level && (tpi6525->air == 0))
+ {
+ tpi6525->interrupt_level = 0;
+
+ DBG_LOG(device->machine(), 3, "tpi6525", ("%s clear interrupt\n", device->tag()));
+
+ tpi6525->out_irq_func(tpi6525->interrupt_level);
+ }
+}
+
+
+WRITE_LINE_DEVICE_HANDLER( tpi6525_i0_w )
+{
+ tpi6525_state *tpi6525 = get_safe_token(device);
+
+ if (INTERRUPT_MODE && (state != tpi6525->irq_level[0]))
+ {
+ tpi6525->irq_level[0] = state;
+
+ if ((state == 0) && !(tpi6525->air & 1) && (tpi6525->ddr_c & 1))
+ {
+ tpi6525->air |= 1;
+ tpi6525_set_interrupt(device);
+ }
+ }
+}
+
+
+WRITE_LINE_DEVICE_HANDLER( tpi6525_i1_w )
+{
+ tpi6525_state *tpi6525 = get_safe_token(device);
+
+ if (INTERRUPT_MODE && (state != tpi6525->irq_level[1]))
+ {
+ tpi6525->irq_level[1] = state;
+
+ if ((state == 0) && !(tpi6525->air & 2) && (tpi6525->ddr_c & 2))
+ {
+ tpi6525->air |= 2;
+ tpi6525_set_interrupt(device);
+ }
+ }
+}
+
+
+WRITE_LINE_DEVICE_HANDLER( tpi6525_i2_w )
+{
+ tpi6525_state *tpi6525 = get_safe_token(device);
+
+ if (INTERRUPT_MODE && (state != tpi6525->irq_level[2]))
+ {
+ tpi6525->irq_level[2] = state;
+
+ if ((state == 0) && !(tpi6525->air & 4) && (tpi6525->ddr_c & 4))
+ {
+ tpi6525->air |= 4;
+ tpi6525_set_interrupt(device);
+ }
+ }
+}
+
+
+WRITE_LINE_DEVICE_HANDLER( tpi6525_i3_w )
+{
+ tpi6525_state *tpi6525 = get_safe_token(device);
+
+ if (INTERRUPT_MODE && (state != tpi6525->irq_level[3]))
+ {
+ tpi6525->irq_level[3] = state;
+
+ if (((INTERRUPT3_RISING_EDGE && (state == 1))
+ || (!INTERRUPT3_RISING_EDGE && (state == 0)))
+ && !(tpi6525->air & 8) && (tpi6525->ddr_c & 8))
+ {
+ tpi6525->air |= 8;
+ tpi6525_set_interrupt(device);
+ }
+ }
+}
+
+
+WRITE_LINE_DEVICE_HANDLER( tpi6525_i4_w )
+{
+ tpi6525_state *tpi6525 = get_safe_token(device);
+
+ if (INTERRUPT_MODE && (state != tpi6525->irq_level[4]) )
+ {
+ tpi6525->irq_level[4] = state;
+
+ if (((INTERRUPT4_RISING_EDGE && (state == 1))
+ ||(!INTERRUPT4_RISING_EDGE&&(state == 0)))
+ && !(tpi6525->air & 0x10) && (tpi6525->ddr_c & 0x10))
+ {
+ tpi6525->air |= 0x10;
+ tpi6525_set_interrupt(device);
+ }
+ }
+}
+
+
+READ8_DEVICE_HANDLER( tpi6525_porta_r )
+{
+ tpi6525_state *tpi6525 = get_safe_token(device);
+ UINT8 data = tpi6525->in_a;
+
+ if (!tpi6525->in_pa_func.isnull())
+ data = tpi6525->in_pa_func(offset);
+
+ data = (data & ~tpi6525->ddr_a) | (tpi6525->ddr_a & tpi6525->port_a);
+
+ return data;
+}
+
+
+WRITE8_DEVICE_HANDLER( tpi6525_porta_w )
+{
+ tpi6525_state *tpi6525 = get_safe_token(device);
+
+ tpi6525->in_a = data;
+}
+
+
+READ8_DEVICE_HANDLER( tpi6525_portb_r )
+{
+ tpi6525_state *tpi6525 = get_safe_token(device);
+ UINT8 data = tpi6525->in_b;
+
+ if (!tpi6525->in_pb_func.isnull())
+ data = tpi6525->in_pb_func(offset);
+
+ data = (data & ~tpi6525->ddr_b) | (tpi6525->ddr_b & tpi6525->port_b);
+
+ return data;
+}
+
+
+WRITE8_DEVICE_HANDLER( tpi6525_portb_w )
+{
+ tpi6525_state *tpi6525 = get_safe_token(device);
+
+ tpi6525->in_b = data;
+}
+
+
+READ8_DEVICE_HANDLER( tpi6525_portc_r )
+{
+ tpi6525_state *tpi6525 = get_safe_token(device);
+ UINT8 data = tpi6525->in_c;
+
+ if (!tpi6525->in_pc_func.isnull())
+ data &= tpi6525->in_pc_func(offset);
+
+ data = (data & ~tpi6525->ddr_c) | (tpi6525->ddr_c & tpi6525->port_c);
+
+ return data;
+}
+
+
+WRITE8_DEVICE_HANDLER( tpi6525_portc_w )
+{
+ tpi6525_state *tpi6525 = get_safe_token(device);
+
+ tpi6525->in_c = data;
+}
+
+
+READ8_DEVICE_HANDLER( tpi6525_r )
+{
+ tpi6525_state *tpi6525 = get_safe_token(device);
+ UINT8 data = 0xff;
+
+ switch (offset & 7)
+ {
+ case 0:
+ data = tpi6525->in_a;
+
+ if (!tpi6525->in_pa_func.isnull())
+ data &= tpi6525->in_pa_func(0);
+
+ data = (data & ~tpi6525->ddr_a) | (tpi6525->ddr_a & tpi6525->port_a);
+
+ break;
+
+ case 1:
+ data = tpi6525->in_b;
+
+ if (!tpi6525->in_pb_func.isnull())
+ data &= tpi6525->in_pb_func(0);
+
+ data = (data & ~tpi6525->ddr_b) | (tpi6525->ddr_b & tpi6525->port_b);
+
+ break;
+
+ case 2:
+ if (INTERRUPT_MODE)
+ {
+ data = 0;
+
+ if (tpi6525->irq_level[0]) data |= 0x01;
+ if (tpi6525->irq_level[1]) data |= 0x02;
+ if (tpi6525->irq_level[2]) data |= 0x04;
+ if (tpi6525->irq_level[3]) data |= 0x08;
+ if (tpi6525->irq_level[4]) data |= 0x10;
+ if (!tpi6525->interrupt_level) data |= 0x20;
+ if (tpi6525->ca_level) data |= 0x40;
+ if (tpi6525->cb_level) data |= 0x80;
+ }
+ else
+ {
+ data = tpi6525->in_c;
+
+ if (!tpi6525->in_pc_func.isnull())
+ data &= tpi6525->in_pc_func(0);
+
+ data = (data & ~tpi6525->ddr_c) | (tpi6525->ddr_c & tpi6525->port_c);
+ }
+
+ DBG_LOG(device->machine(), 2, "tpi6525", ("%s read %.2x %.2x\n", device->tag(), offset, data));
+ break;
+
+ case 3:
+ data = tpi6525->ddr_a;
+ break;
+
+ case 4:
+ data = tpi6525->ddr_b;
+ break;
+
+ case 5:
+ data = tpi6525->ddr_c;
+ break;
+
+ case 6:
+ data = tpi6525->cr;
+ break;
+
+ case 7: /* air */
+ if (PRIORIZED_INTERRUPTS)
+ {
+ if (tpi6525->air & 0x10)
+ {
+ data = 0x10;
+ tpi6525->air &= ~0x10;
+ }
+ else if (tpi6525->air & 8)
+ {
+ data = 8;
+ tpi6525->air &= ~8;
+ }
+ else if (tpi6525->air & 4)
+ {
+ data = 4;
+ tpi6525->air &= ~4;
+ }
+ else if (tpi6525->air & 2)
+ {
+ data = 2;
+ tpi6525->air &= ~2;
+ }
+ else if (tpi6525->air & 1)
+ {
+ data = 1;
+ tpi6525->air &= ~1;
+ }
+ }
+ else
+ {
+ data = tpi6525->air;
+ tpi6525->air = 0;
+ }
+
+ tpi6525_clear_interrupt(device);
+ break;
+
+ }
+
+ DBG_LOG(device->machine(), 3, "tpi6525", ("%s read %.2x %.2x\n", device->tag(), offset, data));
+
+ return data;
+}
+
+
+WRITE8_DEVICE_HANDLER( tpi6525_w )
+{
+ tpi6525_state *tpi6525 = get_safe_token(device);
+
+ DBG_LOG(device->machine(), 2, "tpi6525", ("%s write %.2x %.2x\n", device->tag(), offset, data));
+
+ switch (offset & 7)
+ {
+ case 0:
+ tpi6525->port_a = data;
+ tpi6525->out_pa_func(0, tpi6525->port_a & tpi6525->ddr_a);
+ break;
+
+ case 1:
+ tpi6525->port_b = data;
+ tpi6525->out_pb_func(0, tpi6525->port_b & tpi6525->ddr_b);
+ break;
+
+ case 2:
+ tpi6525->port_c = data;
+
+ if (!INTERRUPT_MODE)
+ tpi6525->out_pc_func(0, tpi6525->port_c & tpi6525->ddr_c);
+ break;
+
+ case 3:
+ tpi6525->ddr_a = data;
+ tpi6525->out_pa_func(0, tpi6525->port_a & tpi6525->ddr_a);
+
+ break;
+
+ case 4:
+ tpi6525->ddr_b = data;
+ tpi6525->out_pb_func(0, tpi6525->port_b & tpi6525->ddr_b);
+ break;
+
+ case 5:
+ tpi6525->ddr_c = data;
+
+ if (!INTERRUPT_MODE)
+ tpi6525->out_pc_func(0, tpi6525->port_c & tpi6525->ddr_c);
+ break;
+
+ case 6:
+ tpi6525->cr = data;
+
+ if (INTERRUPT_MODE)
+ {
+ if (CA_MANUAL_OUT)
+ {
+ if (tpi6525->ca_level != CA_MANUAL_LEVEL)
+ {
+ tpi6525->ca_level = CA_MANUAL_LEVEL;
+ tpi6525->out_ca_func(tpi6525->ca_level);
+ }
+ }
+ if (CB_MANUAL_OUT)
+ {
+ if (tpi6525->cb_level != CB_MANUAL_LEVEL)
+ {
+ tpi6525->cb_level = CB_MANUAL_LEVEL;
+ tpi6525->out_cb_func(tpi6525->cb_level);
+ }
+ }
+ }
+
+ break;
+
+ case 7:
+ /* tpi6525->air = data; */
+ break;
+ }
+}
+
+
+/* this should probably be done better, needed for amigacd.c */
+
+UINT8 tpi6525_get_ddr_a(device_t *device)
+{
+ tpi6525_state *tpi6525 = get_safe_token(device);
+ return tpi6525->ddr_a;
+}
+
+UINT8 tpi6525_get_ddr_b(device_t *device)
+{
+ tpi6525_state *tpi6525 = get_safe_token(device);
+ return tpi6525->ddr_b;
+}
+
+UINT8 tpi6525_get_ddr_c(device_t *device)
+{
+ tpi6525_state *tpi6525 = get_safe_token(device);
+ return tpi6525->ddr_c;
+}
+
+DEFINE_LEGACY_DEVICE(TPI6525, tpi6525);
diff --git a/trunk/src/emu/machine/6525tpi.h b/trunk/src/emu/machine/6525tpi.h
new file mode 100644
index 00000000000..794e1244c88
--- /dev/null
+++ b/trunk/src/emu/machine/6525tpi.h
@@ -0,0 +1,94 @@
+/*****************************************************************************
+ *
+ * machine/tpi6525.h
+ *
+ * mos tri port interface 6525
+ * mos triple interface adapter 6523
+ *
+ * peter.trauner@jk.uni-linz.ac.at
+ *
+ * used in commodore b series
+ * used in commodore c1551 floppy disk drive
+ *
+ * tia6523 is a tpi6525 without control register!?
+ *
+ * tia6523
+ * only some lines of port b and c are in the pinout!
+ *
+ * connector to floppy c1551 (delivered with c1551 as c16 expansion)
+ * port a for data read/write
+ * port b
+ * 0 status 0
+ * 1 status 1
+ * port c
+ * 6 dav output edge data on port a available
+ * 7 ack input edge ready for next datum
+ *
+ ****************************************************************************/
+
+#ifndef __TPI6525_H__
+#define __TPI6525_H__
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _tpi6525_interface tpi6525_interface;
+struct _tpi6525_interface
+{
+ devcb_write_line out_irq_func;
+
+ devcb_read8 in_pa_func;
+ devcb_write8 out_pa_func;
+
+ devcb_read8 in_pb_func;
+ devcb_write8 out_pb_func;
+
+ devcb_read8 in_pc_func;
+ devcb_write8 out_pc_func;
+
+ devcb_write_line out_ca_func;
+ devcb_write_line out_cb_func;
+};
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+DECLARE_LEGACY_DEVICE(TPI6525, tpi6525);
+
+#define MCFG_TPI6525_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, TPI6525, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+READ8_DEVICE_HANDLER( tpi6525_r );
+WRITE8_DEVICE_HANDLER( tpi6525_w );
+
+READ8_DEVICE_HANDLER( tpi6525_porta_r );
+WRITE8_DEVICE_HANDLER( tpi6525_porta_w );
+
+READ8_DEVICE_HANDLER( tpi6525_portb_r );
+WRITE8_DEVICE_HANDLER( tpi6525_portb_w );
+
+READ8_DEVICE_HANDLER( tpi6525_portc_r );
+WRITE8_DEVICE_HANDLER( tpi6525_portc_w );
+
+WRITE_LINE_DEVICE_HANDLER( tpi6525_i0_w );
+WRITE_LINE_DEVICE_HANDLER( tpi6525_i1_w );
+WRITE_LINE_DEVICE_HANDLER( tpi6525_i2_w );
+WRITE_LINE_DEVICE_HANDLER( tpi6525_i3_w );
+WRITE_LINE_DEVICE_HANDLER( tpi6525_i4_w );
+
+UINT8 tpi6525_get_ddr_a(device_t *device);
+UINT8 tpi6525_get_ddr_b(device_t *device);
+UINT8 tpi6525_get_ddr_c(device_t *device);
+
+
+#endif /* __TPI6525_H__ */
diff --git a/trunk/src/emu/machine/6526cia.c b/trunk/src/emu/machine/6526cia.c
new file mode 100644
index 00000000000..e1bf6c5477f
--- /dev/null
+++ b/trunk/src/emu/machine/6526cia.c
@@ -0,0 +1,921 @@
+/**********************************************************************
+
+ MOS 6526/8520 CIA interface and emulation
+
+ This function emulates all the functionality MOS6526 or
+ MOS8520 complex interface adapters.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "6526cia.h"
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* CIA registers */
+#define CIA_PRA 0
+#define CIA_PRB 1
+#define CIA_DDRA 2
+#define CIA_DDRB 3
+#define CIA_TALO 4
+#define CIA_TAHI 5
+#define CIA_TBLO 6
+#define CIA_TBHI 7
+#define CIA_TOD0 8 /* 6526: 1/10 seconds 8520: bits 0- 7 */
+#define CIA_TOD1 9 /* 6526: seconds 8520: bits 8-15 */
+#define CIA_TOD2 10 /* 6526: minutes 8520: bits 16-23 */
+#define CIA_TOD3 11 /* 6526: hours 8520: N/A */
+#define CIA_SDR 12
+#define CIA_ICR 13
+#define CIA_CRA 14
+#define CIA_CRB 15
+
+#define CIA_CRA_START 0x01
+#define CIA_CRA_PBON 0x02
+#define CIA_CRA_OUTMODE 0x04
+#define CIA_CRA_RUNMODE 0x08
+#define CIA_CRA_LOAD 0x10
+#define CIA_CRA_INMODE 0x20
+#define CIA_CRA_SPMODE 0x40
+#define CIA_CRA_TODIN 0x80
+
+//**************************************************************************
+// DEVICE CONFIGURATION
+//**************************************************************************
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type MOS6526R1 = &device_creator<mos6526r1_device>;
+const device_type MOS6526R2 = &device_creator<mos6526r2_device>;
+const device_type MOS8520 = &device_creator<mos8520_device>;
+
+//-------------------------------------------------
+// mos6526_device - constructor
+//-------------------------------------------------
+
+mos6526_device::mos6526_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, type, name, tag, owner, clock)
+{
+}
+
+mos6526r1_device::mos6526r1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : mos6526_device(mconfig, MOS6526R1, "MOS6526r1", tag, owner, clock) { }
+
+mos6526r2_device::mos6526r2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : mos6526_device(mconfig, MOS6526R2, "MOS6526r2", tag, owner, clock) { }
+
+mos8520_device::mos8520_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : mos6526_device(mconfig, MOS8520, "MOS8520", tag, owner, clock) { }
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void mos6526_device::device_reset()
+{
+ /* clear things out */
+ m_port[0].m_latch = 0x00;
+ m_port[0].m_in = 0x00;
+ m_port[0].m_out = 0x00;
+ m_port[0].m_mask_value = 0xff;
+ m_port[1].m_latch = 0x00;
+ m_port[1].m_in = 0x00;
+ m_port[1].m_out = 0x00;
+ m_port[1].m_mask_value = 0xff;
+ m_tod = 0;
+ m_tod_latch = 0;
+ m_alarm = 0;
+ m_icr = 0x00;
+ m_ics = 0x00;
+ m_irq = 0;
+ m_shift = 0;
+ m_loaded = 0;
+ m_cnt = 1;
+ m_sp = 0;
+
+ /* initialize data direction registers */
+ m_port[0].m_ddr = !strcmp(tag(), "cia_0") ? 0x03 : 0xff;
+ m_port[1].m_ddr = !strcmp(tag(), "cia_0") ? 0x00 : 0xff;
+
+ /* TOD running by default */
+ m_tod_running = TRUE;
+
+ /* initialize timers */
+ for(int t = 0; t < 2; t++)
+ {
+ cia_timer *timer = &m_timer[t];
+ timer->m_cia = this;
+ timer->m_clock = clock();
+ timer->m_latch = 0xffff;
+ timer->m_count = 0x0000;
+ timer->m_mode = 0x00;
+ }
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void mos6526_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const mos6526_interface *intf = reinterpret_cast<const mos6526_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<mos6526_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ m_tod_clock = 0;
+ memset(&m_out_irq_cb, 0, sizeof(m_out_irq_cb));
+ memset(&m_out_pc_cb, 0, sizeof(m_out_pc_cb));
+ memset(&m_out_cnt_cb, 0, sizeof(m_out_cnt_cb));
+ memset(&m_out_sp_cb, 0, sizeof(m_out_sp_cb));
+ memset(&m_in_pa_cb, 0, sizeof(m_in_pa_cb));
+ memset(&m_out_pa_cb, 0, sizeof(m_out_pa_cb));
+ memset(&m_in_pb_cb, 0, sizeof(m_in_pb_cb));
+ memset(&m_out_pb_cb, 0, sizeof(m_out_pb_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mos6526_device::device_start()
+{
+ /* clear out CIA structure, and copy the interface */
+ m_out_irq_func.resolve(m_out_irq_cb, *this);
+ m_out_pc_func.resolve(m_out_pc_cb, *this);
+ m_out_cnt_func.resolve(m_out_cnt_cb, *this);
+ m_out_sp_func.resolve(m_out_sp_cb, *this);
+ m_flag = 1;
+
+ /* setup ports */
+ m_port[0].m_read.resolve(m_in_pa_cb, *this);
+ m_port[0].m_write.resolve(m_out_pa_cb, *this);
+ m_port[1].m_read.resolve(m_in_pb_cb, *this);
+ m_port[1].m_write.resolve(m_out_pb_cb, *this);
+
+ for (int p = 0; p < (sizeof(m_port) / sizeof(m_port[0])); p++)
+ {
+ m_port[p].m_mask_value = 0xff;
+ }
+
+ /* setup timers */
+ for (int t = 0; t < (sizeof(m_timer) / sizeof(m_timer[0])); t++)
+ {
+ cia_timer *timer = &m_timer[t];
+ timer->m_timer = machine().scheduler().timer_alloc(FUNC(timer_proc), (void*)this);
+ timer->m_cia = this;
+ timer->m_irq = 0x01 << t;
+ }
+
+ /* setup TOD timer, if appropriate */
+ if (m_tod_clock != 0)
+ {
+ machine().scheduler().timer_pulse(attotime::from_hz(m_tod_clock), FUNC(clock_tod_callback), 0, (void *)this);
+ }
+
+ /* state save support */
+ save_item(NAME(m_port[0].m_ddr));
+ save_item(NAME(m_port[0].m_latch));
+ save_item(NAME(m_port[0].m_in));
+ save_item(NAME(m_port[0].m_out));
+ save_item(NAME(m_port[0].m_mask_value));
+ save_item(NAME(m_port[1].m_ddr));
+ save_item(NAME(m_port[1].m_latch));
+ save_item(NAME(m_port[1].m_in));
+ save_item(NAME(m_port[1].m_out));
+ save_item(NAME(m_port[1].m_mask_value));
+ save_item(NAME(m_timer[0].m_latch));
+ save_item(NAME(m_timer[0].m_count));
+ save_item(NAME(m_timer[0].m_mode));
+ save_item(NAME(m_timer[0].m_irq));
+ save_item(NAME(m_timer[1].m_latch));
+ save_item(NAME(m_timer[1].m_count));
+ save_item(NAME(m_timer[1].m_mode));
+ save_item(NAME(m_timer[1].m_irq));
+ save_item(NAME(m_tod));
+ save_item(NAME(m_tod_latch));
+ save_item(NAME(m_tod_latched));
+ save_item(NAME(m_tod_running));
+ save_item(NAME(m_alarm));
+ save_item(NAME(m_icr));
+ save_item(NAME(m_ics));
+ save_item(NAME(m_irq));
+ save_item(NAME(m_flag));
+ save_item(NAME(m_loaded));
+ save_item(NAME(m_sdr));
+ save_item(NAME(m_sp));
+ save_item(NAME(m_cnt));
+ save_item(NAME(m_shift));
+ save_item(NAME(m_serial));
+}
+
+
+/*-------------------------------------------------
+ set_port_mask_value
+-------------------------------------------------*/
+
+void mos6526_device::set_port_mask_value(int port, int data)
+{
+ m_port[port].m_mask_value = data;
+}
+
+/*-------------------------------------------------
+ update_pc - pulse /pc output
+-------------------------------------------------*/
+
+void mos6526_device::update_pc()
+{
+ /* this should really be one cycle long */
+ m_out_pc_func(0);
+ m_out_pc_func(1);
+}
+
+/*-------------------------------------------------
+ update_interrupts
+-------------------------------------------------*/
+
+void mos6526_device::update_interrupts()
+{
+ UINT8 new_irq;
+
+ /* always update the high bit of ICS */
+ if (m_ics & 0x7f)
+ {
+ m_ics |= 0x80;
+ }
+ else
+ {
+ m_ics &= ~0x80;
+ }
+
+ /* based on what is enabled, set/clear the IRQ via the custom chip */
+ new_irq = (m_ics & m_icr) ? 1 : 0;
+ if (m_irq != new_irq)
+ {
+ m_irq = new_irq;
+ m_out_irq_func(m_irq);
+ }
+}
+
+
+/*-------------------------------------------------
+ timer_bump
+-------------------------------------------------*/
+
+void mos6526_device::timer_bump(int timer)
+{
+ m_timer[timer].update(timer, -1);
+
+ if (m_timer[timer].m_count == 0x00)
+ {
+ timer_underflow(timer);
+ }
+ else
+ {
+ m_timer[timer].update(timer, m_timer[timer].m_count - 1);
+ }
+}
+
+/*-------------------------------------------------
+ cia_timer_underflow
+-------------------------------------------------*/
+
+void mos6526_device::timer_underflow(int timer)
+{
+ assert((timer == 0) || (timer == 1));
+
+ /* set the status and update interrupts */
+ m_ics |= m_timer[timer].m_irq;
+ update_interrupts();
+
+ /* if one-shot mode, turn it off */
+ if (m_timer[timer].m_mode & 0x08)
+ {
+ m_timer[timer].m_mode &= 0xfe;
+ }
+
+ /* reload the timer */
+ m_timer[timer].update(timer, m_timer[timer].m_latch);
+
+ /* timer A has some interesting properties */
+ if (timer == 0)
+ {
+ /* such as cascading to timer B */
+ if ((m_timer[1].m_mode & 0x41) == 0x41)
+ {
+ if (m_cnt || !(m_timer[1].m_mode & 0x20))
+ {
+ timer_bump(1);
+ }
+ }
+
+ /* also the serial line */
+ if ((m_timer[timer].m_irq == 0x01) && (m_timer[timer].m_mode & CIA_CRA_SPMODE))
+ {
+ if (m_loaded || m_shift)
+ {
+ /* falling edge */
+ if (m_cnt)
+ {
+ if (m_shift == 0)
+ {
+ /* load shift register */
+ m_loaded = 0;
+ m_serial = m_sdr;
+ }
+
+ /* transmit MSB */
+ m_sp = BIT(m_serial, 7);
+ m_out_sp_func(m_sp);
+
+ /* toggle CNT */
+ m_cnt = !m_cnt;
+ m_out_cnt_func(m_cnt);
+
+ /* shift data */
+ m_serial <<= 1;
+ m_shift++;
+
+ if (m_shift == 8)
+ {
+ /* signal interrupt */
+ m_ics |= 0x08;
+ update_interrupts();
+ }
+ }
+ else
+ {
+ /* toggle CNT */
+ m_cnt = !m_cnt;
+ m_out_cnt_func(m_cnt);
+
+ if (m_shift == 8)
+ {
+ m_shift = 0;
+ }
+ }
+ }
+ }
+ }
+}
+
+/*-------------------------------------------------
+ TIMER_CALLBACK( cia_timer_proc )
+-------------------------------------------------*/
+
+TIMER_CALLBACK( mos6526_device::timer_proc )
+{
+ mos6526_device *cia = reinterpret_cast<mos6526_device *>(ptr);
+
+ cia->timer_underflow(param);
+}
+
+/*-------------------------------------------------
+ bcd_increment
+-------------------------------------------------*/
+
+static UINT8 bcd_increment(UINT8 value)
+{
+ value++;
+ if ((value & 0x0f) >= 0x0a)
+ value += 0x10 - 0x0a;
+ return value;
+}
+
+/*-------------------------------------------------
+ cia6526_increment
+-------------------------------------------------*/
+
+void mos6526_device::increment()
+{
+ /* break down TOD value into components */
+ UINT8 subsecond = (UINT8) (m_tod >> 0);
+ UINT8 second = (UINT8) (m_tod >> 8);
+ UINT8 minute = (UINT8) (m_tod >> 16);
+ UINT8 hour = (UINT8) (m_tod >> 24);
+
+ subsecond = bcd_increment(subsecond);
+ if (subsecond >= 0x10)
+ {
+ subsecond = 0x00;
+ second = bcd_increment(second);
+ if (second >= ((m_timer[0].m_mode & 0x80) ? 0x50 : 0x60))
+ {
+ second = 0x00;
+ minute = bcd_increment(minute);
+ if (minute >= 0x60)
+ {
+ minute = 0x00;
+ if (hour == 0x91)
+ hour = 0x00;
+ else if (hour == 0x89)
+ hour = 0x90;
+ else if (hour == 0x11)
+ hour = 0x80;
+ else if (hour == 0x09)
+ hour = 0x10;
+ else
+ hour++;
+ }
+ }
+ }
+
+ /* update the TOD with new value */
+ m_tod = (((UINT32) subsecond) << 0)
+ | (((UINT32) second) << 8)
+ | (((UINT32) minute) << 16)
+ | (((UINT32) hour) << 24);
+}
+
+/*-------------------------------------------------
+ cia_clock_tod - Update TOD on CIA A
+-------------------------------------------------*/
+
+void mos6526_device::clock_tod()
+{
+ if (m_tod_running)
+ {
+ if ((type() == MOS6526R1) || (type() == MOS6526R2))
+ {
+ /* The 6526 split the value into hours, minutes, seconds and
+ * subseconds */
+ increment();
+ }
+ else if (type() == MOS8520)
+ {
+ /* the 8520 has a straight 24-bit counter */
+ m_tod++;
+ m_tod &= 0xffffff;
+ }
+
+ if (m_tod == m_alarm)
+ {
+ m_ics |= 0x04;
+ update_interrupts();
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ clock_tod_callback
+-------------------------------------------------*/
+
+TIMER_CALLBACK( mos6526_device::clock_tod_callback )
+{
+ mos6526_device *cia = reinterpret_cast<mos6526_device *>(ptr);
+ cia->clock_tod();
+}
+
+
+/*-------------------------------------------------
+ cnt_w
+-------------------------------------------------*/
+
+void mos6526_device::cnt_w(UINT8 state)
+{
+ /* is this a rising edge? */
+ if (!m_cnt && state)
+ {
+ if (m_timer[0].m_mode & CIA_CRA_START)
+ {
+ /* does timer #0 bump on CNT? */
+ if (m_timer[0].m_mode & CIA_CRA_INMODE)
+ {
+ timer_bump(0);
+ }
+ }
+
+ /* if the serial port is set to input, the CNT will shift the port */
+ if (!(m_timer[0].m_mode & CIA_CRA_SPMODE))
+ {
+ m_serial <<= 1;
+ m_shift++;
+
+ if (m_sp)
+ {
+ m_serial |= 0x01;
+ }
+
+ if (m_shift == 8)
+ {
+ m_sdr = m_serial;
+ m_serial = 0;
+ m_shift = 0;
+ m_ics |= 0x08;
+ update_interrupts();
+ }
+ }
+
+ /* does timer #1 bump on CNT? */
+ if ((m_timer[1].m_mode & 0x61) == 0x21)
+ {
+ timer_bump(1);
+ }
+ }
+
+ m_cnt = state;
+}
+
+void mos6526_device::flag_w(UINT8 state)
+{
+ /* falling edge */
+ if (m_flag && !state)
+ {
+ m_ics |= 0x10;
+ update_interrupts();
+ }
+
+ m_flag = state;
+}
+
+/*-------------------------------------------------
+ reg_r
+-------------------------------------------------*/
+
+UINT8 mos6526_device::reg_r(UINT8 offset)
+{
+ cia_timer *timer;
+ cia_port *port;
+ UINT8 data = 0x00;
+
+ offset &= 0x0F;
+
+ switch(offset)
+ {
+ /* port A/B data */
+ case CIA_PRA:
+ case CIA_PRB:
+ port = &m_port[offset & 1];
+ data = port->m_read(0);
+ data = ((data & ~port->m_ddr) | (port->m_latch & port->m_ddr)) & port->m_mask_value;
+
+ port->m_in = data;
+
+ if (offset == CIA_PRB)
+ {
+ /* timer #0 can change PB6 */
+ if (m_timer[0].m_mode & 0x02)
+ {
+ m_timer[0].update(0, -1);
+ if (m_timer[0].m_count != 0)
+ {
+ data |= 0x40;
+ }
+ else
+ {
+ data &= ~0x40;
+ }
+ }
+
+ /* timer #1 can change PB7 */
+ if (m_timer[1].m_mode & 0x02)
+ {
+ m_timer[1].update(1, -1);
+ if (m_timer[1].m_count != 0)
+ {
+ data |= 0x80;
+ }
+ else
+ {
+ data &= ~0x80;
+ }
+ }
+
+ /* pulse /PC following the read */
+ update_pc();
+ }
+ break;
+
+ /* port A/B direction */
+ case CIA_DDRA:
+ case CIA_DDRB:
+ port = &m_port[offset & 1];
+ data = port->m_ddr;
+ break;
+
+ /* timer A/B low byte */
+ case CIA_TALO:
+ case CIA_TBLO:
+ timer = &m_timer[(offset >> 1) & 1];
+ data = timer->get_count() >> 0;
+ break;
+
+ /* timer A/B high byte */
+ case CIA_TAHI:
+ case CIA_TBHI:
+ timer = &m_timer[(offset >> 1) & 1];
+ data = timer->get_count() >> 8;
+ break;
+
+ /* TOD counter */
+ case CIA_TOD0:
+ case CIA_TOD1:
+ case CIA_TOD2:
+ case CIA_TOD3:
+ if (type() == MOS8520)
+ {
+ if (offset == CIA_TOD2)
+ {
+ m_tod_latch = m_tod;
+ m_tod_latched = TRUE;
+ }
+ }
+ else
+ {
+ if (offset == CIA_TOD3)
+ {
+ m_tod_latch = m_tod;
+ m_tod_latched = TRUE;
+ }
+ }
+ if (offset == CIA_TOD0)
+ {
+ m_tod_latched = FALSE;
+ }
+
+ if (m_tod_latched)
+ {
+ data = m_tod_latch >> ((offset - CIA_TOD0) * 8);
+ }
+ else
+ {
+ data = m_tod >> ((offset - CIA_TOD0) * 8);
+ }
+ break;
+
+ /* serial data ready */
+ case CIA_SDR:
+ data = m_sdr;
+ break;
+
+ /* interrupt status/clear */
+ case CIA_ICR:
+ data = m_ics;
+ m_ics = 0; /* clear on read */
+ update_interrupts();
+ break;
+
+ /* timer A/B mode */
+ case CIA_CRA:
+ case CIA_CRB:
+ timer = &m_timer[offset & 1];
+ data = timer->m_mode;
+ break;
+ }
+
+ return data;
+}
+
+/*-------------------------------------------------
+ reg_w
+-------------------------------------------------*/
+
+void mos6526_device::reg_w(UINT8 offset, UINT8 data)
+{
+ cia_timer *timer;
+ cia_port *port;
+ int shift;
+
+ offset &= 0x0F;
+
+ switch(offset)
+ {
+ /* port A/B data */
+ case CIA_PRA:
+ case CIA_PRB:
+ port = &m_port[offset & 1];
+ port->m_latch = data;
+ port->m_out = (data & port->m_ddr) | (port->m_in & ~port->m_ddr);
+ port->m_write(0, port->m_out);
+
+ /* pulse /PC following the write */
+ if (offset == CIA_PRB)
+ {
+ update_pc();
+ }
+
+ break;
+
+ /* port A/B direction */
+ case CIA_DDRA:
+ case CIA_DDRB:
+ port = &m_port[offset & 1];
+ port->m_ddr = data;
+ break;
+
+ /* timer A/B latch low */
+ case CIA_TALO:
+ case CIA_TBLO:
+ timer = &m_timer[(offset >> 1) & 1];
+ timer->m_latch = (timer->m_latch & 0xff00) | (data << 0);
+ break;
+
+ /* timer A latch high */
+ case CIA_TAHI:
+ case CIA_TBHI:
+ timer = &m_timer[(offset >> 1) & 1];
+ timer->m_latch = (timer->m_latch & 0x00ff) | (data << 8);
+
+ /* if the timer is one-shot, then force a start on it */
+ if (timer->m_mode & 0x08)
+ {
+ timer->m_mode |= 1;
+ timer->update((offset >> 1) & 1, timer->m_latch);
+ }
+ else
+ {
+ /* if the timer is off, update the count */
+ if (!(timer->m_mode & 0x01))
+ {
+ timer->update((offset >> 1) & 1, timer->m_latch);
+ }
+ }
+ break;
+
+ /* time of day latches */
+ case CIA_TOD0:
+ case CIA_TOD1:
+ case CIA_TOD2:
+ case CIA_TOD3:
+ shift = 8 * ((offset - CIA_TOD0));
+
+ /* alarm setting mode? */
+ if (m_timer[1].m_mode & 0x80)
+ {
+ m_alarm = (m_alarm & ~(0xff << shift)) | (data << shift);
+ }
+ /* counter setting mode */
+ else
+ {
+ m_tod = (m_tod & ~(0xff << shift)) | (data << shift);
+ }
+
+ if (type() == MOS8520)
+ {
+ if (offset == CIA_TOD2)
+ {
+ m_tod_running = FALSE;
+ }
+ }
+ else
+ {
+ if (offset == CIA_TOD3)
+ {
+ m_tod_running = FALSE;
+ }
+ }
+ if (offset == CIA_TOD0)
+ {
+ m_tod_running = TRUE;
+ }
+ break;
+
+ /* serial data ready */
+ case CIA_SDR:
+ m_sdr = data;
+ if (m_timer[0].m_mode & 0x40)
+ {
+ m_loaded = 1;
+ }
+ break;
+
+ /* interrupt control register */
+ case CIA_ICR:
+ if (data & 0x80)
+ {
+ m_icr |= data & 0x7f;
+ }
+ else
+ {
+ m_icr &= ~(data & 0x7f);
+ }
+ update_interrupts();
+ break;
+
+ /* timer A/B modes */
+ case CIA_CRA:
+ case CIA_CRB:
+ timer = &m_timer[offset & 1];
+ timer->m_mode = data & 0xef;
+
+ /* force load? */
+ if (data & 0x10)
+ {
+ timer->update(offset & 1, timer->m_latch);
+ }
+ else
+ {
+ timer->update(offset & 1, -1);
+ }
+ break;
+ }
+}
+
+/*-------------------------------------------------
+ is_timer_active
+-------------------------------------------------*/
+
+static int is_timer_active(emu_timer *timer)
+{
+ attotime t = timer->expire();
+ return (t != attotime::never);
+}
+
+/*-------------------------------------------------
+ update - updates the count and emu_timer for
+ a given CIA timer
+-------------------------------------------------*/
+
+void mos6526_device::cia_timer::update(int which, INT32 new_count)
+{
+ /* sanity check arguments */
+ assert((new_count >= -1) && (new_count <= 0xffff));
+
+ /* update the timer count, if necessary */
+ if ((new_count == -1) && is_timer_active(m_timer))
+ {
+ UINT16 current_count = (m_timer->elapsed() * m_clock).as_double();
+ m_count = m_count - MIN(m_count, current_count);
+ }
+
+ /* set the timer if we are instructed to */
+ if (new_count != -1)
+ {
+ m_count = new_count;
+ }
+
+ /* now update the MAME timer */
+ if ((m_mode & 0x01) && ((m_mode & (which ? 0x60 : 0x20)) == 0x00))
+ {
+ /* timer is on and is connected to clock */
+ attotime period = attotime::from_hz(m_clock) * (m_count ? m_count : 0x10000);
+ m_timer->adjust(period, which);
+ }
+ else
+ {
+ /* timer is off or not connected to clock */
+ m_timer->adjust(attotime::never, which);
+ }
+}
+
+/*-------------------------------------------------
+ get_count - get the count for a given CIA
+ timer
+-------------------------------------------------*/
+
+UINT16 mos6526_device::cia_timer::get_count()
+{
+ UINT16 count;
+
+ if (is_timer_active(m_timer))
+ {
+ UINT16 current_count = (m_timer->elapsed() * m_clock).as_double();
+ count = m_count - MIN(m_count, current_count);
+ }
+ else
+ {
+ count = m_count;
+ }
+
+ return count;
+}
+
+/***************************************************************************
+ TRAMPOLINES
+***************************************************************************/
+
+void cia_set_port_mask_value(device_t *device, int port, int data) { downcast<mos6526_device *>(device)->set_port_mask_value(port, data); }
+
+READ8_DEVICE_HANDLER( mos6526_r ) { return downcast<mos6526_device *>(device)->reg_r(offset); }
+WRITE8_DEVICE_HANDLER( mos6526_w ) { downcast<mos6526_device *>(device)->reg_w(offset, data); }
+
+READ8_DEVICE_HANDLER( mos6526_pa_r ) { return downcast<mos6526_device *>(device)->pa_r(offset); }
+READ8_DEVICE_HANDLER( mos6526_pb_r ) { return downcast<mos6526_device *>(device)->pb_r(offset); }
+
+READ_LINE_DEVICE_HANDLER( mos6526_irq_r ) { return downcast<mos6526_device *>(device)->irq_r(); }
+
+WRITE_LINE_DEVICE_HANDLER( mos6526_tod_w ) { downcast<mos6526_device *>(device)->tod_w(state); }
+
+READ_LINE_DEVICE_HANDLER( mos6526_cnt_r ) { return downcast<mos6526_device *>(device)->cnt_r(); }
+WRITE_LINE_DEVICE_HANDLER( mos6526_cnt_w ) { downcast<mos6526_device *>(device)->cnt_w(state); }
+
+READ_LINE_DEVICE_HANDLER( mos6526_sp_r ) { return downcast<mos6526_device *>(device)->sp_r(); }
+WRITE_LINE_DEVICE_HANDLER( mos6526_sp_w ) { downcast<mos6526_device *>(device)->sp_w(state); }
+
+WRITE_LINE_DEVICE_HANDLER( mos6526_flag_w ) { downcast<mos6526_device *>(device)->flag_w(state); }
diff --git a/trunk/src/emu/machine/6526cia.h b/trunk/src/emu/machine/6526cia.h
new file mode 100644
index 00000000000..ab17474524c
--- /dev/null
+++ b/trunk/src/emu/machine/6526cia.h
@@ -0,0 +1,264 @@
+/**********************************************************************
+
+ MOS 6526/8520 Complex Interface Adapter emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ Vss 1 |* \_/ | 40 CNT
+ PA0 2 | | 39 SP
+ PA1 3 | | 38 RS0
+ PA2 4 | | 37 RS1
+ PA3 5 | | 36 RS2
+ PA4 6 | | 35 RS3
+ PA5 7 | | 34 _RES
+ PA6 8 | | 33 DB0
+ PA7 9 | | 32 DB1
+ PB0 10 | MOS6526 | 31 DB2
+ PB1 11 | MOS8520 | 30 DB3
+ PB2 12 | | 29 DB4
+ PB3 13 | | 28 DB5
+ PB4 14 | | 27 DB6
+ PB5 15 | | 26 DB7
+ PB6 16 | | 25 phi2
+ PB7 17 | | 24 _FLAG
+ _PC 18 | | 23 _CS
+ TOD 19 | | 22 R/W
+ Vcc 20 |_____________| 21 _IRQ
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __6526CIA_H__
+#define __6526CIA_H__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_MOS6526R1_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD(_tag, MOS6526R1, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MCFG_MOS6526R2_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD(_tag, MOS6526R2, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MCFG_MOS8520_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD(_tag, MOS8520, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MOS6526_INTERFACE(name) \
+ const mos6526_interface (name)=
+
+#define MOS8520_INTERFACE(name) \
+ const mos6526_interface (name)=
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+
+// ======================> mos6526_interface
+
+struct mos6526_interface
+{
+ int m_tod_clock;
+
+ devcb_write_line m_out_irq_cb;
+ devcb_write_line m_out_pc_cb;
+ devcb_write_line m_out_cnt_cb;
+ devcb_write_line m_out_sp_cb;
+
+ devcb_read8 m_in_pa_cb;
+ devcb_write8 m_out_pa_cb;
+
+ devcb_read8 m_in_pb_cb;
+ devcb_write8 m_out_pb_cb;
+};
+
+
+
+// ======================> mos6526_device
+
+class mos6526_device : public device_t,
+ public mos6526_interface
+{
+ friend class dart_channel;
+
+protected:
+ // construction/destruction
+ mos6526_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
+
+public:
+ UINT8 reg_r(UINT8 offset);
+ void reg_w(UINT8 offset, UINT8 data);
+
+ /* port access */
+ UINT8 pa_r(UINT8 offset) { return (m_port[0].m_latch | ~m_port[0].m_ddr); }
+ UINT8 pb_r(UINT8 offset) { return (m_port[1].m_latch | ~m_port[1].m_ddr); }
+
+ /* interrupt request */
+ UINT8 irq_r() { return m_irq; }
+
+ /* time of day clock */
+ void tod_w(UINT8 state) { if(state) clock_tod(); }
+
+ /* serial counter */
+ UINT8 cnt_r() { return m_cnt; }
+ void cnt_w(UINT8 state);
+
+ /* serial port */
+ UINT8 sp_r() { return m_sp; }
+ void sp_w(UINT8 state) { m_sp = state; }
+
+ /* flag */
+ void flag_w(UINT8 state);
+
+ /* port mask */
+ void set_port_mask_value(int port, int data);
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_post_load() { }
+ virtual void device_clock_changed() { }
+
+ static TIMER_CALLBACK( timer_proc );
+ static TIMER_CALLBACK( clock_tod_callback );
+
+private:
+
+ void update_pc();
+ void update_interrupts();
+ void timer_bump(int timer);
+ void timer_underflow(int timer);
+ void increment();
+ void clock_tod();
+
+ struct cia_timer
+ {
+ public:
+ cia_timer() { }
+
+ UINT16 get_count();
+ void update(int which, INT32 new_count);
+
+ UINT32 m_clock;
+ UINT16 m_latch;
+ UINT16 m_count;
+ UINT8 m_mode;
+ UINT8 m_irq;
+ emu_timer* m_timer;
+ mos6526_device* m_cia;
+ };
+
+ struct cia_port
+ {
+ UINT8 m_ddr;
+ UINT8 m_latch;
+ UINT8 m_in;
+ UINT8 m_out;
+ devcb_resolved_read8 m_read;
+ devcb_resolved_write8 m_write;
+ UINT8 m_mask_value; /* in READ operation the value can be forced by a extern electric circuit */
+ };
+
+ devcb_resolved_write_line m_out_irq_func;
+ devcb_resolved_write_line m_out_pc_func;
+ devcb_resolved_write_line m_out_cnt_func;
+ devcb_resolved_write_line m_out_sp_func;
+
+ cia_port m_port[2];
+ cia_timer m_timer[2];
+
+ /* Time Of the Day clock (TOD) */
+ UINT32 m_tod;
+ UINT32 m_tod_latch;
+ UINT8 m_tod_latched;
+ UINT8 m_tod_running;
+ UINT32 m_alarm;
+
+ /* Interrupts */
+ UINT8 m_icr;
+ UINT8 m_ics;
+ UINT8 m_irq;
+ int m_flag;
+
+ /* Serial */
+ UINT8 m_loaded;
+ UINT8 m_sdr;
+ UINT8 m_sp;
+ UINT8 m_cnt;
+ UINT8 m_shift;
+ UINT8 m_serial;
+};
+
+class mos6526r1_device : public mos6526_device
+{
+public:
+ mos6526r1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class mos6526r2_device : public mos6526_device
+{
+public:
+ mos6526r2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class mos8520_device : public mos6526_device
+{
+public:
+ mos8520_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+
+// device type definition
+extern const device_type MOS6526R1;
+extern const device_type MOS6526R2;
+extern const device_type MOS8520;
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+/* register access */
+READ8_DEVICE_HANDLER( mos6526_r );
+WRITE8_DEVICE_HANDLER( mos6526_w );
+
+/* port access */
+READ8_DEVICE_HANDLER( mos6526_pa_r );
+READ8_DEVICE_HANDLER( mos6526_pb_r );
+
+/* interrupt request */
+READ_LINE_DEVICE_HANDLER( mos6526_irq_r );
+
+/* time of day clock */
+WRITE_LINE_DEVICE_HANDLER( mos6526_tod_w );
+
+/* serial counter */
+READ_LINE_DEVICE_HANDLER( mos6526_cnt_r );
+WRITE_LINE_DEVICE_HANDLER( mos6526_cnt_w );
+
+/* serial port */
+READ_LINE_DEVICE_HANDLER( mos6526_sp_r );
+WRITE_LINE_DEVICE_HANDLER( mos6526_sp_w );
+
+/* flag */
+WRITE_LINE_DEVICE_HANDLER( mos6526_flag_w );
+
+/* port mask */
+void cia_set_port_mask_value(device_t *device, int port, int data);
+
+#endif /* __6526CIA_H__ */
diff --git a/trunk/src/emu/machine/6532riot.c b/trunk/src/emu/machine/6532riot.c
new file mode 100644
index 00000000000..1e0b0897455
--- /dev/null
+++ b/trunk/src/emu/machine/6532riot.c
@@ -0,0 +1,544 @@
+/***************************************************************************
+
+ RIOT 6532 emulation
+
+The timer seems to follow these rules:
+- When the timer flag changes from 0 to 1 the timer continues to count
+ down at a 1 cycle rate.
+- When the timer is being read or written the timer flag is reset.
+- When the timer flag is set and the timer contents are 0, the counting
+ stops.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "6532riot.h"
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// device type definition
+const device_type RIOT6532 = &device_creator<riot6532_device>;
+
+enum
+{
+ TIMER_IDLE,
+ TIMER_COUNTING,
+ TIMER_FINISHING
+};
+
+#define TIMER_FLAG 0x80
+#define PA7_FLAG 0x40
+
+
+
+
+/***************************************************************************
+ INTERNAL FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ update_irqstate - update the IRQ state
+ based on interrupt enables
+-------------------------------------------------*/
+
+void riot6532_device::update_irqstate()
+{
+ int state = (m_irqstate & m_irqenable);
+
+ if (!m_irq_func.isnull())
+ {
+ m_irq_func((state != 0) ? ASSERT_LINE : CLEAR_LINE);
+ }
+ else
+ {
+ logerror("%s:6532RIOT chip #%d: no irq callback function\n", machine().describe_context(), m_index);
+ }
+}
+
+
+/*-------------------------------------------------
+ apply_ddr - combine inputs and outputs
+ according to the DDR
+-------------------------------------------------*/
+
+UINT8 riot6532_device::apply_ddr(const riot6532_port *port)
+{
+ return (port->m_out & port->m_ddr) | (port->m_in & ~port->m_ddr);
+}
+
+
+/*-------------------------------------------------
+ update_pa7_state - see if PA7 has changed
+ and signal appropriately
+-------------------------------------------------*/
+
+void riot6532_device::update_pa7_state()
+{
+ UINT8 data = apply_ddr(&m_port[0]) & 0x80;
+
+ /* if the state changed in the correct direction, set the PA7 flag and update IRQs */
+ if ((m_pa7prev ^ data) && (m_pa7dir ^ data) == 0)
+ {
+ m_irqstate |= PA7_FLAG;
+ update_irqstate();
+ }
+ m_pa7prev = data;
+}
+
+
+/*-------------------------------------------------
+ get_timer - return the current timer value
+-------------------------------------------------*/
+
+UINT8 riot6532_device::get_timer()
+{
+ /* if idle, return 0 */
+ if (m_timerstate == TIMER_IDLE)
+ {
+ return 0;
+ }
+
+ /* if counting, return the number of ticks remaining */
+ else if (m_timerstate == TIMER_COUNTING)
+ {
+ return m_timer->remaining().as_ticks(clock()) >> m_timershift;
+ }
+
+ /* if finishing, return the number of ticks without the shift */
+ else
+ {
+ return m_timer->remaining().as_ticks(clock());
+ }
+}
+
+
+
+/*-------------------------------------------------
+ timer_end_callback - callback to process the
+ timer
+-------------------------------------------------*/
+
+TIMER_CALLBACK( riot6532_device::timer_end_callback )
+{
+ riot6532_device *via = reinterpret_cast<riot6532_device *>(ptr);
+ via->timer_end();
+}
+
+void riot6532_device::timer_end()
+{
+ assert(m_timerstate != TIMER_IDLE);
+
+ /* if we finished counting, switch to the finishing state */
+ if(m_timerstate == TIMER_COUNTING)
+ {
+ m_timerstate = TIMER_FINISHING;
+ m_timer->adjust(attotime::from_ticks(256, clock()));
+
+ /* signal timer IRQ as well */
+ m_irqstate |= TIMER_FLAG;
+ update_irqstate();
+ }
+
+ /* if we finished finishing, keep spinning */
+ else if (m_timerstate == TIMER_FINISHING)
+ {
+ m_timer->adjust(attotime::from_ticks(256, clock()));
+ }
+}
+
+
+
+/***************************************************************************
+ I/O ACCESS
+***************************************************************************/
+
+/*-------------------------------------------------
+ riot6532_w - master I/O write access
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER( riot6532_w )
+{
+ riot6532_device *via = downcast<riot6532_device *>(device);
+ via->reg_w(offset, data);
+}
+
+void riot6532_device::reg_w(UINT8 offset, UINT8 data)
+{
+ /* if A4 == 1 and A2 == 1, we are writing to the timer */
+ if ((offset & 0x14) == 0x14)
+ {
+ static const UINT8 timershift[4] = { 0, 3, 6, 10 };
+ attotime curtime = machine().time();
+ INT64 target;
+
+ /* A0-A1 contain the timer divisor */
+ m_timershift = timershift[offset & 3];
+
+ /* A3 contains the timer IRQ enable */
+ if (offset & 8)
+ m_irqenable |= TIMER_FLAG;
+ else
+ m_irqenable &= ~TIMER_FLAG;
+
+ /* writes here clear the timer flag */
+ if (m_timerstate != TIMER_FINISHING || get_timer() != 0xff)
+ {
+ m_irqstate &= ~TIMER_FLAG;
+ }
+ update_irqstate();
+
+ /* update the timer */
+ m_timerstate = TIMER_COUNTING;
+ target = curtime.as_ticks(clock()) + 1 + (data << m_timershift);
+ m_timer->adjust(attotime::from_ticks(target, clock()) - curtime);
+ }
+
+ /* if A4 == 0 and A2 == 1, we are writing to the edge detect control */
+ else if ((offset & 0x14) == 0x04)
+ {
+ /* A1 contains the A7 IRQ enable */
+ if (offset & 2)
+ {
+ m_irqenable |= PA7_FLAG;
+ }
+ else
+ {
+ m_irqenable &= ~PA7_FLAG;
+ }
+
+ /* A0 specifies the edge detect direction: 0=negative, 1=positive */
+ m_pa7dir = (offset & 1) << 7;
+ }
+
+ /* if A4 == anything and A2 == 0, we are writing to the I/O section */
+ else
+ {
+ /* A1 selects the port */
+ riot6532_port *port = &m_port[(offset >> 1) & 1];
+
+ /* if A0 == 1, we are writing to the port's DDR */
+ if (offset & 1)
+ {
+ port->m_ddr = data;
+ }
+
+ /* if A0 == 0, we are writing to the port's output */
+ else
+ {
+ port->m_out = data;
+ if (!port->m_out_func.isnull())
+ {
+ port->m_out_func(0, data);
+ }
+ else
+ {
+ logerror("%s:6532RIOT chip %s: Port %c is being written to but has no handler. %02X\n", machine().describe_context(), tag(), 'A' + (offset & 1), data);
+ }
+ }
+
+ /* writes to port A need to update the PA7 state */
+ if (port == &m_port[0])
+ {
+ update_pa7_state();
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ riot6532_r - master I/O read access
+-------------------------------------------------*/
+
+READ8_DEVICE_HANDLER( riot6532_r )
+{
+ riot6532_device *via = downcast<riot6532_device *>(device);
+ return via->reg_r(offset);
+}
+
+UINT8 riot6532_device::reg_r(UINT8 offset)
+{
+ UINT8 val = 0;
+
+ /* if A2 == 1 and A0 == 1, we are reading interrupt flags */
+ if ((offset & 0x05) == 0x05)
+ {
+ val = m_irqstate;
+
+ /* implicitly clears the PA7 flag */
+ m_irqstate &= ~PA7_FLAG;
+ update_irqstate();
+ }
+
+ /* if A2 == 1 and A0 == 0, we are reading the timer */
+ else if ((offset & 0x05) == 0x04)
+ {
+ val = get_timer();
+
+ /* A3 contains the timer IRQ enable */
+ if (offset & 8)
+ {
+ m_irqenable |= TIMER_FLAG;
+ }
+ else
+ {
+ m_irqenable &= ~TIMER_FLAG;
+ }
+
+ /* implicitly clears the timer flag */
+ if (m_timerstate != TIMER_FINISHING || val != 0xff)
+ {
+ m_irqstate &= ~TIMER_FLAG;
+ }
+ update_irqstate();
+ }
+
+ /* if A2 == 0 and A0 == anything, we are reading from ports */
+ else
+ {
+ /* A1 selects the port */
+ riot6532_port *port = &m_port[(offset >> 1) & 1];
+
+ /* if A0 == 1, we are reading the port's DDR */
+ if (offset & 1)
+ {
+ val = port->m_ddr;
+ }
+
+ /* if A0 == 0, we are reading the port as an input */
+ else
+ {
+ /* call the input callback if it exists */
+ if (!port->m_in_func.isnull())
+ {
+ port->m_in = port->m_in_func(0);
+
+ /* changes to port A need to update the PA7 state */
+ if (port == &m_port[0])
+ {
+ update_pa7_state();
+ }
+ }
+ else
+ {
+ logerror("%s:6532RIOT chip %s: Port %c is being read but has no handler\n", machine().describe_context(), tag(), 'A' + (offset & 1));
+ }
+
+ /* apply the DDR to the result */
+ val = apply_ddr(port);
+ }
+ }
+ return val;
+}
+
+
+/*-------------------------------------------------
+ porta_in_set - set port A input value
+-------------------------------------------------*/
+
+void riot6532_porta_in_set(device_t *device, UINT8 data, UINT8 mask)
+{
+ riot6532_device *via = downcast<riot6532_device *>(device);
+ via->porta_in_set(data, mask);
+}
+
+void riot6532_device::porta_in_set(UINT8 data, UINT8 mask)
+{
+ m_port[0].m_in = (m_port[0].m_in & ~mask) | (data & mask);
+ update_pa7_state();
+}
+
+
+/*-------------------------------------------------
+ portb_in_set - set port B input value
+-------------------------------------------------*/
+
+void riot6532_portb_in_set(device_t *device, UINT8 data, UINT8 mask)
+{
+ riot6532_device *via = downcast<riot6532_device *>(device);
+ via->portb_in_set(data, mask);
+}
+
+void riot6532_device::portb_in_set(UINT8 data, UINT8 mask)
+{
+ m_port[1].m_in = (m_port[1].m_in & ~mask) | (data & mask);
+}
+
+
+/*-------------------------------------------------
+ porta_in_get - return port A input value
+-------------------------------------------------*/
+
+UINT8 riot6532_porta_in_get(device_t *device)
+{
+ riot6532_device *via = downcast<riot6532_device *>(device);
+ return via->porta_in_get();
+}
+
+UINT8 riot6532_device::porta_in_get()
+{
+ return m_port[0].m_in;
+}
+
+
+/*-------------------------------------------------
+ portb_in_get - return port B input value
+-------------------------------------------------*/
+
+UINT8 riot6532_portb_in_get(device_t *device)
+{
+ riot6532_device *via = downcast<riot6532_device *>(device);
+ return via->portb_in_get();
+}
+
+UINT8 riot6532_device::portb_in_get()
+{
+ return m_port[1].m_in;
+}
+
+
+/*-------------------------------------------------
+ porta_in_get - return port A output value
+-------------------------------------------------*/
+
+UINT8 riot6532_porta_out_get(device_t *device)
+{
+ riot6532_device *via = downcast<riot6532_device *>(device);
+ return via->porta_out_get();
+}
+
+UINT8 riot6532_device::porta_out_get()
+{
+ return m_port[0].m_out;
+}
+
+
+/*-------------------------------------------------
+ portb_in_get - return port B output value
+-------------------------------------------------*/
+
+UINT8 riot6532_portb_out_get(device_t *device)
+{
+ riot6532_device *via = downcast<riot6532_device *>(device);
+ return via->portb_out_get();
+}
+
+UINT8 riot6532_device::portb_out_get()
+{
+ return m_port[1].m_out;
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// riot6532_device - constructor
+//-------------------------------------------------
+
+riot6532_device::riot6532_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, RIOT6532, "6532 (RIOT)", tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void riot6532_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const riot6532_interface *intf = reinterpret_cast<const riot6532_interface *>(static_config());
+ if (intf != NULL)
+ {
+ *static_cast<riot6532_interface *>(this) = *intf;
+ }
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_in_a_cb, 0, sizeof(m_in_a_cb));
+ memset(&m_in_b_cb, 0, sizeof(m_in_b_cb));
+ memset(&m_out_a_cb, 0, sizeof(m_out_a_cb));
+ memset(&m_out_b_cb, 0, sizeof(m_out_b_cb));
+ memset(&m_irq_cb, 0, sizeof(m_irq_cb));
+ }
+}
+
+
+/*-------------------------------------------------
+ device_start - device-specific startup
+-------------------------------------------------*/
+
+void riot6532_device::device_start()
+{
+ /* validate arguments */
+ assert(this != NULL);
+
+ /* set static values */
+ m_index = machine().devicelist().indexof(RIOT6532, tag());
+
+ /* configure the ports */
+ m_port[0].m_in_func.resolve(m_in_a_cb, *this);
+ m_port[0].m_out_func.resolve(m_out_a_cb, *this);
+ m_port[1].m_in_func.resolve(m_in_b_cb, *this);
+ m_port[1].m_out_func.resolve(m_out_b_cb, *this);
+
+ /* resolve irq func */
+ m_irq_func.resolve(m_irq_cb, *this);
+
+ /* allocate timers */
+ m_timer = machine().scheduler().timer_alloc(FUNC(timer_end_callback), (void *)this);
+
+ /* register for save states */
+ save_item(NAME(m_port[0].m_in));
+ save_item(NAME(m_port[0].m_out));
+ save_item(NAME(m_port[0].m_ddr));
+ save_item(NAME(m_port[1].m_in));
+ save_item(NAME(m_port[1].m_out));
+ save_item(NAME(m_port[1].m_ddr));
+
+ save_item(NAME(m_irqstate));
+ save_item(NAME(m_irqenable));
+
+ save_item(NAME(m_pa7dir));
+ save_item(NAME(m_pa7prev));
+
+ save_item(NAME(m_timershift));
+ save_item(NAME(m_timerstate));
+}
+
+
+
+/*-------------------------------------------------
+ device_reset - device-specific reset
+-------------------------------------------------*/
+
+void riot6532_device::device_reset()
+{
+ /* reset I/O states */
+ m_port[0].m_out = 0;
+ m_port[0].m_ddr = 0;
+ m_port[1].m_out = 0;
+ m_port[1].m_ddr = 0;
+
+ /* reset IRQ states */
+ m_irqenable = 0;
+ m_irqstate = 0;
+ update_irqstate();
+
+ /* reset PA7 states */
+ m_pa7dir = 0;
+ m_pa7prev = 0;
+
+ /* reset timer states */
+ m_timershift = 0;
+ m_timerstate = TIMER_IDLE;
+ m_timer->adjust(attotime::never);
+}
diff --git a/trunk/src/emu/machine/6532riot.h b/trunk/src/emu/machine/6532riot.h
new file mode 100644
index 00000000000..50ed7a39d44
--- /dev/null
+++ b/trunk/src/emu/machine/6532riot.h
@@ -0,0 +1,132 @@
+/***************************************************************************
+
+ RIOT 6532 emulation
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __RIOT6532_H__
+#define __RIOT6532_H__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_RIOT6532_ADD(_tag, _clock, _intrf) \
+ MCFG_DEVICE_ADD(_tag, RIOT6532, _clock) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+
+// ======================> riot6532_interface
+
+struct riot6532_interface
+{
+ devcb_read8 m_in_a_cb;
+ devcb_read8 m_in_b_cb;
+ devcb_write8 m_out_a_cb;
+ devcb_write8 m_out_b_cb;
+ devcb_write_line m_irq_cb;
+};
+
+
+
+// ======================> riot6532_device
+
+class riot6532_device : public device_t,
+ public riot6532_interface
+{
+public:
+ // construction/destruction
+ riot6532_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ UINT8 reg_r(UINT8 offset);
+ void reg_w(UINT8 offset, UINT8 data);
+
+ void porta_in_set(UINT8 data, UINT8 mask);
+ void portb_in_set(UINT8 data, UINT8 mask);
+
+ UINT8 porta_in_get();
+ UINT8 portb_in_get();
+
+ UINT8 porta_out_get();
+ UINT8 portb_out_get();
+
+ void timer_end();
+
+protected:
+ class riot6532_port
+ {
+ public:
+ UINT8 m_in;
+ UINT8 m_out;
+ UINT8 m_ddr;
+ devcb_resolved_read8 m_in_func;
+ devcb_resolved_write8 m_out_func;
+ };
+
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_post_load() { }
+ virtual void device_clock_changed() { }
+
+ static TIMER_CALLBACK( timer_end_callback );
+
+private:
+ void update_irqstate();
+ UINT8 apply_ddr(const riot6532_port *port);
+ void update_pa7_state();
+ UINT8 get_timer();
+
+ int m_index;
+
+ riot6532_port m_port[2];
+
+ devcb_resolved_write_line m_irq_func;
+
+ UINT8 m_irqstate;
+ UINT8 m_irqenable;
+
+ UINT8 m_pa7dir; /* 0x80 = high-to-low, 0x00 = low-to-high */
+ UINT8 m_pa7prev;
+
+ UINT8 m_timershift;
+ UINT8 m_timerstate;
+ emu_timer * m_timer;
+};
+
+
+// device type definition
+extern const device_type RIOT6532;
+
+
+
+/***************************************************************************
+ PROTOTYPES
+***************************************************************************/
+
+READ8_DEVICE_HANDLER( riot6532_r );
+WRITE8_DEVICE_HANDLER( riot6532_w );
+
+void riot6532_porta_in_set(device_t *device, UINT8 data, UINT8 mask);
+void riot6532_portb_in_set(device_t *device, UINT8 data, UINT8 mask);
+
+UINT8 riot6532_porta_in_get(device_t *device);
+UINT8 riot6532_portb_in_get(device_t *device);
+
+UINT8 riot6532_porta_out_get(device_t *device);
+UINT8 riot6532_portb_out_get(device_t *device);
+
+#endif
diff --git a/trunk/src/emu/machine/6821pia.c b/trunk/src/emu/machine/6821pia.c
new file mode 100644
index 00000000000..7672defa065
--- /dev/null
+++ b/trunk/src/emu/machine/6821pia.c
@@ -0,0 +1,1210 @@
+/**********************************************************************
+
+ Motorola 6821 PIA interface and emulation
+
+**********************************************************************/
+
+#include "emu.h"
+#include "6821pia.h"
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+#define PIA_IRQ1 (0x80)
+#define PIA_IRQ2 (0x40)
+
+#define IRQ1_ENABLED(c) ( (((c) >> 0) & 0x01))
+#define C1_LOW_TO_HIGH(c) ( (((c) >> 1) & 0x01))
+#define C1_HIGH_TO_LOW(c) (!(((c) >> 1) & 0x01))
+#define OUTPUT_SELECTED(c) ( (((c) >> 2) & 0x01))
+#define IRQ2_ENABLED(c) ( (((c) >> 3) & 0x01))
+#define STROBE_E_RESET(c) ( (((c) >> 3) & 0x01))
+#define STROBE_C1_RESET(c) (!(((c) >> 3) & 0x01))
+#define C2_SET(c) ( (((c) >> 3) & 0x01))
+#define C2_LOW_TO_HIGH(c) ( (((c) >> 4) & 0x01))
+#define C2_HIGH_TO_LOW(c) (!(((c) >> 4) & 0x01))
+#define C2_SET_MODE(c) ( (((c) >> 4) & 0x01))
+#define C2_STROBE_MODE(c) (!(((c) >> 4) & 0x01))
+#define C2_OUTPUT(c) ( (((c) >> 5) & 0x01))
+#define C2_INPUT(c) (!(((c) >> 5) & 0x01))
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type PIA6821 = &device_creator<pia6821_device>;
+
+
+//-------------------------------------------------
+// pia6821_device - constructor
+//-------------------------------------------------
+
+pia6821_device::pia6821_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, PIA6821, "6822 PIA", tag, owner, clock)
+{
+ memset(static_cast<pia6821_interface *>(this), 0, sizeof(pia6821_interface));
+}
+
+
+//-------------------------------------------------
+// static_set_interface - set the interface
+// struct
+//-------------------------------------------------
+
+void pia6821_device::static_set_interface(device_t &device, const pia6821_interface &interface)
+{
+ pia6821_device &ptm = downcast<pia6821_device &>(device);
+ static_cast<pia6821_interface &>(ptm) = interface;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void pia6821_device::device_start()
+{
+ // resolve callbacks
+ m_in_a_func.resolve(m_in_a_cb, *this);
+ m_in_b_func.resolve(m_in_b_cb, *this);
+ m_in_ca1_func.resolve(m_in_ca1_cb, *this);
+ m_in_cb1_func.resolve(m_in_cb1_cb, *this);
+ m_in_ca2_func.resolve(m_in_ca2_cb, *this);
+ m_in_cb2_func.resolve(m_in_cb2_cb, *this);
+ m_out_a_func.resolve(m_out_a_cb, *this);
+ m_out_b_func.resolve(m_out_b_cb, *this);
+ m_out_ca2_func.resolve(m_out_ca2_cb, *this);
+ m_out_cb2_func.resolve(m_out_cb2_cb, *this);
+ m_irq_a_func.resolve(m_irq_a_cb, *this);
+ m_irq_b_func.resolve(m_irq_b_cb, *this);
+
+ save_item(NAME(m_in_a));
+ save_item(NAME(m_in_ca1));
+ save_item(NAME(m_in_ca2));
+ save_item(NAME(m_out_a));
+ save_item(NAME(m_out_ca2));
+ save_item(NAME(m_port_a_z_mask));
+ save_item(NAME(m_ddr_a));
+ save_item(NAME(m_ctl_a));
+ save_item(NAME(m_irq_a1));
+ save_item(NAME(m_irq_a2));
+ save_item(NAME(m_irq_a_state));
+ save_item(NAME(m_in_b));
+ save_item(NAME(m_in_cb1));
+ save_item(NAME(m_in_cb2));
+ save_item(NAME(m_out_b));
+ save_item(NAME(m_out_cb2));
+ save_item(NAME(m_last_out_cb2_z));
+ save_item(NAME(m_ddr_b));
+ save_item(NAME(m_ctl_b));
+ save_item(NAME(m_irq_b1));
+ save_item(NAME(m_irq_b2));
+ save_item(NAME(m_irq_b_state));
+ save_item(NAME(m_in_a_pushed));
+ save_item(NAME(m_out_a_needs_pulled));
+ save_item(NAME(m_in_ca1_pushed));
+ save_item(NAME(m_in_ca2_pushed));
+ save_item(NAME(m_out_ca2_needs_pulled));
+ save_item(NAME(m_in_b_pushed));
+ save_item(NAME(m_out_b_needs_pulled));
+ save_item(NAME(m_in_cb1_pushed));
+ save_item(NAME(m_in_cb2_pushed));
+ save_item(NAME(m_out_cb2_needs_pulled));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void pia6821_device::device_reset()
+{
+ //
+ // set default read values.
+ //
+ // ports A,CA1,CA2 default to 1
+ // ports B,CB1,CB2 are three-state and undefined (set to 0)
+ //
+ m_in_a = 0xff;
+ m_in_ca1 = TRUE;
+ m_in_ca2 = TRUE;
+ m_out_a = 0;
+ m_out_ca2 = 0;
+ m_port_a_z_mask = 0;
+ m_ddr_a = 0;
+ m_ctl_a = 0;
+ m_irq_a1 = 0;
+ m_irq_a2 = 0;
+ m_irq_a_state = 0;
+ m_in_b = 0;
+ m_in_cb1 = 0;
+ m_in_cb2 = 0;
+ m_out_b = 0;
+ m_out_cb2 = 0;
+ m_last_out_cb2_z = 0;
+ m_ddr_b = 0;
+ m_ctl_b = 0;
+ m_irq_b1 = 0;
+ m_irq_b2 = 0;
+ m_irq_b_state = 0;
+ m_in_a_pushed = false;
+ m_out_a_needs_pulled = false;
+ m_in_ca1_pushed = false;
+ m_in_ca2_pushed = false;
+ m_out_ca2_needs_pulled = false;
+ m_in_b_pushed = false;
+ m_out_b_needs_pulled = false;
+ m_in_cb1_pushed = false;
+ m_in_cb2_pushed = false;
+ m_out_cb2_needs_pulled = false;
+ m_logged_port_a_not_connected = false;
+ m_logged_port_b_not_connected = false;
+ m_logged_ca1_not_connected = false;
+ m_logged_ca2_not_connected = false;
+ m_logged_cb1_not_connected = false;
+ m_logged_cb2_not_connected = false;
+
+
+ // clear the IRQs
+ m_irq_a_func(FALSE);
+ m_irq_b_func(FALSE);
+}
+
+
+//-------------------------------------------------
+// update_interrupts
+//-------------------------------------------------
+
+void pia6821_device::update_interrupts()
+{
+ // start with IRQ A
+ int new_state = (m_irq_a1 && IRQ1_ENABLED(m_ctl_a)) || (m_irq_a2 && IRQ2_ENABLED(m_ctl_a));
+
+ if (new_state != m_irq_a_state)
+ {
+ m_irq_a_state = new_state;
+ m_irq_a_func(m_irq_a_state);
+ }
+
+ // then do IRQ B
+ new_state = (m_irq_b1 && IRQ1_ENABLED(m_ctl_b)) || (m_irq_b2 && IRQ2_ENABLED(m_ctl_b));
+
+ if (new_state != m_irq_b_state)
+ {
+ m_irq_b_state = new_state;
+ m_irq_b_func(m_irq_b_state);
+ }
+}
+
+
+//-------------------------------------------------
+// get_in_a_value
+//-------------------------------------------------
+
+UINT8 pia6821_device::get_in_a_value()
+{
+ UINT8 port_a_data = 0;
+ UINT8 ret;
+
+ // update the input
+ if (!m_in_a_func.isnull())
+ {
+ port_a_data = m_in_a_func(0);
+ }
+ else
+ {
+ if (m_in_a_pushed)
+ {
+ port_a_data = m_in_a;
+ }
+ else
+ {
+ // mark all pins disconnected
+ m_port_a_z_mask = 0xff;
+
+ if (!m_logged_port_a_not_connected && (m_ddr_a != 0xff))
+ {
+ logerror("PIA #%s: Warning! No port A read handler. Assuming pins 0x%02X not connected\n", tag(), m_ddr_a ^ 0xff);
+ m_logged_port_a_not_connected = true;
+ }
+ }
+ }
+
+ // - connected pins are always read
+ // - disconnected pins read the output buffer in output mode
+ // - disconnected pins are HI in input mode
+ ret = (~m_port_a_z_mask & port_a_data) |
+ ( m_port_a_z_mask & m_ddr_a & m_out_a) |
+ ( m_port_a_z_mask & ~m_ddr_a);
+
+ return ret;
+}
+
+
+//-------------------------------------------------
+// get_in_b_value
+//-------------------------------------------------
+
+UINT8 pia6821_device::get_in_b_value()
+{
+ UINT8 ret;
+
+ if (m_ddr_b == 0xff)
+ {
+ // all output, just return buffer
+ ret = m_out_b;
+ }
+ else
+ {
+ UINT8 port_b_data;
+
+ // update the input
+ if (!m_in_b_func.isnull())
+ {
+ port_b_data = m_in_b_func(0);
+ }
+ else
+ {
+ if (m_in_b_pushed)
+ {
+ port_b_data = m_in_b;
+ }
+ else
+ {
+ if (!m_logged_port_b_not_connected && (m_ddr_b != 0xff))
+ {
+ logerror("PIA #%s: Error! No port B read handler. Three-state pins 0x%02X are undefined\n", tag(), m_ddr_b ^ 0xff);
+ m_logged_port_b_not_connected = true;
+ }
+
+ // undefined -- need to return something
+ port_b_data = 0x00;
+ }
+ }
+
+ // the DDR determines if the pin or the output buffer is read
+ ret = (m_out_b & m_ddr_b) | (port_b_data & ~m_ddr_b);
+ }
+
+ return ret;
+}
+
+
+//-------------------------------------------------
+// get_out_a_value
+//-------------------------------------------------
+
+UINT8 pia6821_device::get_out_a_value()
+{
+ UINT8 ret;
+
+ if (m_ddr_a == 0xff)
+ {
+ // all output
+ ret = m_out_a;
+ }
+ else
+ {
+ // input pins don't change
+ ret = (m_out_a & m_ddr_a) | (get_in_a_value() & ~m_ddr_a);
+ }
+
+ return ret;
+}
+
+
+//-------------------------------------------------
+// get_out_b_value
+//-------------------------------------------------
+
+UINT8 pia6821_device::get_out_b_value()
+{
+ // input pins are high-impedance - we just send them as zeros for backwards compatibility
+ return m_out_b & m_ddr_b;
+}
+
+
+//-------------------------------------------------
+// set_out_ca2
+//-------------------------------------------------
+
+void pia6821_device::set_out_ca2(int data)
+{
+ if (data != m_out_ca2)
+ {
+ m_out_ca2 = data;
+
+ // send to output function
+ if (!m_out_ca2_func.isnull())
+ {
+ m_out_ca2_func(m_out_ca2);
+ }
+ else
+ {
+ if (m_out_ca2_needs_pulled)
+ {
+ logerror("PIA #%s: Warning! No port CA2 write handler. Previous value has been lost!\n", tag());
+ }
+
+ m_out_ca2_needs_pulled = true;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// set_out_cb2
+//-------------------------------------------------
+
+void pia6821_device::set_out_cb2(int data)
+{
+ int z = cb2_output_z();
+
+ if ((data != m_out_cb2) || (z != m_last_out_cb2_z))
+ {
+ m_out_cb2 = data;
+ m_last_out_cb2_z = z;
+
+ // send to output function
+ if (!m_out_cb2_func.isnull())
+ {
+ m_out_cb2_func(m_out_cb2);
+ }
+ else
+ {
+ if (m_out_cb2_needs_pulled)
+ {
+ logerror("PIA #%s: Warning! No port CB2 write handler. Previous value has been lost!\n", tag());
+ }
+
+ m_out_cb2_needs_pulled = true;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// port_a_r
+//-------------------------------------------------
+
+UINT8 pia6821_device::port_a_r()
+{
+ UINT8 ret = get_in_a_value();
+
+ // IRQ flags implicitly cleared by a read
+ m_irq_a1 = FALSE;
+ m_irq_a2 = FALSE;
+ update_interrupts();
+
+ // CA2 is configured as output and in read strobe mode
+ if(C2_OUTPUT(m_ctl_a) && C2_STROBE_MODE(m_ctl_a))
+ {
+ // this will cause a transition low
+ set_out_ca2(FALSE);
+
+ // if the CA2 strobe is cleared by the E, reset it right away
+ if(STROBE_E_RESET(m_ctl_a))
+ {
+ set_out_ca2(TRUE);
+ }
+ }
+
+ LOG(("PIA #%s: port A read = %02X\n", tag(), ret));
+
+ return ret;
+}
+
+
+//-------------------------------------------------
+// ddr_a_r
+//-------------------------------------------------
+
+UINT8 pia6821_device::ddr_a_r()
+{
+ UINT8 ret = m_ddr_a;
+
+ LOG(("PIA #%s: DDR A read = %02X\n", tag(), ret));
+
+ return ret;
+}
+
+
+//-------------------------------------------------
+// port_b_r
+//-------------------------------------------------
+
+UINT8 pia6821_device::port_b_r()
+{
+ UINT8 ret = get_in_b_value();
+
+ // This read will implicitly clear the IRQ B1 flag. If CB2 is in write-strobe
+ // mode with CB1 restore, and a CB1 active transition set the flag,
+ // clearing it will cause CB2 to go high again. Note that this is different
+ // from what happens with port A.
+ if(m_irq_b1 && C2_STROBE_MODE(m_ctl_b) && STROBE_C1_RESET(m_ctl_b))
+ {
+ set_out_cb2(TRUE);
+ }
+
+ // IRQ flags implicitly cleared by a read
+ m_irq_b1 = FALSE;
+ m_irq_b2 = FALSE;
+ update_interrupts();
+
+ LOG(("PIA #%s: port B read = %02X\n", tag(), ret));
+
+ return ret;
+}
+
+
+//-------------------------------------------------
+// ddr_b_r
+//-------------------------------------------------
+
+UINT8 pia6821_device::ddr_b_r()
+{
+ UINT8 ret = m_ddr_b;
+
+ LOG(("PIA #%s: DDR B read = %02X\n", tag(), ret));
+
+ return ret;
+}
+
+
+//-------------------------------------------------
+// control_a_r
+//-------------------------------------------------
+
+UINT8 pia6821_device::control_a_r()
+{
+ UINT8 ret;
+
+ // update CA1 & CA2 if callback exists, these in turn may update IRQ's
+ if (!m_in_ca1_func.isnull())
+ {
+ ca1_w(m_in_ca1_func());
+ }
+ else if(!m_logged_ca1_not_connected && (!m_in_ca1_pushed))
+ {
+ logerror("PIA #%s: Warning! No CA1 read handler. Assuming pin not connected\n", tag());
+ m_logged_ca1_not_connected = true;
+ }
+
+ if (!m_in_ca2_func.isnull())
+ {
+ ca2_w(m_in_ca2_func());
+ }
+ else if ( !m_logged_ca2_not_connected && C2_INPUT(m_ctl_a) && !m_in_ca2_pushed)
+ {
+ logerror("PIA #%s: Warning! No CA2 read handler. Assuming pin not connected\n", tag());
+ m_logged_ca2_not_connected = true;
+ }
+
+ // read control register
+ ret = m_ctl_a;
+
+ // set the IRQ flags if we have pending IRQs
+ if(m_irq_a1)
+ {
+ ret |= PIA_IRQ1;
+ }
+
+ if(m_irq_a2 && C2_INPUT(m_ctl_a))
+ {
+ ret |= PIA_IRQ2;
+ }
+
+ LOG(("PIA #%s: control A read = %02X\n", tag(), ret));
+
+ return ret;
+}
+
+
+//-------------------------------------------------
+// control_b_r
+//-------------------------------------------------
+
+UINT8 pia6821_device::control_b_r()
+{
+ UINT8 ret;
+
+ // update CB1 & CB2 if callback exists, these in turn may update IRQ's
+ if(!m_in_cb1_func.isnull())
+ {
+ cb1_w(m_in_cb1_func());
+ }
+ else if(!m_logged_cb1_not_connected && !m_in_cb1_pushed)
+ {
+ logerror("PIA #%s: Error! no CB1 read handler. Three-state pin is undefined\n", tag());
+ m_logged_cb1_not_connected = true;
+ }
+
+ if(!m_in_cb2_func.isnull())
+ {
+ cb2_w(m_in_cb2_func());
+ }
+ else if(!m_logged_cb2_not_connected && C2_INPUT(m_ctl_b) && !m_in_cb2_pushed)
+ {
+ logerror("PIA #%s: Error! No CB2 read handler. Three-state pin is undefined\n", tag());
+ m_logged_cb2_not_connected = true;
+ }
+
+ // read control register
+ ret = m_ctl_b;
+
+ // set the IRQ flags if we have pending IRQs
+ if(m_irq_b1)
+ {
+ ret |= PIA_IRQ1;
+ }
+
+ if(m_irq_b2 && C2_INPUT(m_ctl_b))
+ {
+ ret |= PIA_IRQ2;
+ }
+
+ LOG(("PIA #%s: control B read = %02X\n", tag(), ret));
+
+ return ret;
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+READ8_MEMBER( pia6821_device::read )
+{
+ return reg_r(offset);
+}
+
+UINT8 pia6821_device::reg_r(UINT8 offset)
+{
+ UINT8 ret;
+
+ switch (offset & 0x03)
+ {
+ default: // impossible
+ case 0x00:
+ if (OUTPUT_SELECTED(m_ctl_a))
+ {
+ ret = port_a_r();
+ }
+ else
+ {
+ ret = ddr_a_r();
+ }
+ break;
+
+ case 0x01:
+ ret = control_a_r();
+ break;
+
+ case 0x02:
+ if (OUTPUT_SELECTED(m_ctl_b))
+ {
+ ret = port_b_r();
+ }
+ else
+ {
+ ret = ddr_b_r();
+ }
+ break;
+
+ case 0x03:
+ ret = control_b_r();
+ break;
+ }
+
+ return ret;
+}
+
+
+//-------------------------------------------------
+// pia6821_alt_r
+//-------------------------------------------------
+
+READ8_MEMBER( pia6821_device::read_alt )
+{
+ return reg_r(((offset << 1) & 0x02) | ((offset >> 1) & 0x01));
+}
+
+
+
+//-------------------------------------------------
+// send_to_out_a_func
+//-------------------------------------------------
+
+void pia6821_device::send_to_out_a_func(const char* message)
+{
+ // input pins are pulled high
+ UINT8 data = get_out_a_value();
+
+ LOG(("PIA #%s: %s = %02X\n", tag(), message, data));
+
+ if(!m_out_a_func.isnull())
+ {
+ m_out_a_func(0, data);
+ }
+ else
+ {
+ if(m_out_a_needs_pulled)
+ {
+ logerror("PIA #%s: Warning! No port A write handler. Previous value has been lost!\n", tag());
+ }
+
+ m_out_a_needs_pulled = true;
+ }
+}
+
+
+//-------------------------------------------------
+// send_to_out_b_func
+//-------------------------------------------------
+
+void pia6821_device::send_to_out_b_func(const char* message)
+{
+ // input pins are high-impedance - we just send them as zeros for backwards compatibility
+ UINT8 data = get_out_b_value();
+
+ LOG(("PIA #%s: %s = %02X\n", tag(), message, data));
+
+ if(!m_out_b_func.isnull())
+ {
+ m_out_b_func(0, data);
+ }
+ else
+ {
+ if(m_out_b_needs_pulled)
+ {
+ logerror("PIA #%s: Warning! No port B write handler. Previous value has been lost!\n", tag());
+ }
+
+ m_out_b_needs_pulled = true;
+ }
+}
+
+
+//-------------------------------------------------
+// port_a_w
+//-------------------------------------------------
+
+void pia6821_device::port_a_w(UINT8 data)
+{
+ // buffer the output value
+ m_out_a = data;
+
+ send_to_out_a_func("port A write");
+}
+
+
+//-------------------------------------------------
+// ddr_a_w
+//-------------------------------------------------
+
+void pia6821_device::ddr_a_w(UINT8 data)
+{
+ if(data == 0x00)
+ {
+ LOG(("PIA #%s: DDR A write = %02X (input mode)\n", tag(), data));
+ }
+ else if(data == 0xff)
+ {
+ LOG(("PIA #%s: DDR A write = %02X (output mode)\n", tag(), data));
+ }
+ else
+ {
+ LOG(("PIA #%s: DDR A write = %02X (mixed mode)\n", tag(), data));
+ }
+
+ if(m_ddr_a != data)
+ {
+ // DDR changed, call the callback again
+ m_ddr_a = data;
+ m_logged_port_a_not_connected = false;
+ send_to_out_a_func("port A write due to DDR change");
+ }
+}
+
+
+//-------------------------------------------------
+// port_b_w
+//-------------------------------------------------
+
+void pia6821_device::port_b_w(UINT8 data)
+{
+ // buffer the output value
+ m_out_b = data;
+
+ send_to_out_b_func("port B write");
+
+ // CB2 in write strobe mode
+ if(C2_STROBE_MODE(m_ctl_b))
+ {
+ // this will cause a transition low
+ set_out_cb2(FALSE);
+
+ // if the CB2 strobe is cleared by the E, reset it right away
+ if(STROBE_E_RESET(m_ctl_b))
+ {
+ set_out_cb2(TRUE);
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// ddr_b_w
+//-------------------------------------------------
+
+void pia6821_device::ddr_b_w(UINT8 data)
+{
+ if (data == 0x00)
+ {
+ LOG(("PIA #%s: DDR B write = %02X (input mode)\n", tag(), data));
+ }
+ else if (data == 0xff)
+ {
+ LOG(("PIA #%s: DDR B write = %02X (output mode)\n", tag(), data));
+ }
+ else
+ {
+ LOG(("PIA #%s: DDR B write = %02X (mixed mode)\n", tag(), data));
+ }
+
+ if(m_ddr_b != data)
+ {
+ // DDR changed, call the callback again
+ m_ddr_b = data;
+ m_logged_port_b_not_connected = false;
+ send_to_out_b_func("port B write due to DDR change");
+ }
+}
+
+
+//-------------------------------------------------
+// control_a_w
+//-------------------------------------------------
+
+void pia6821_device::control_a_w(UINT8 data)
+{
+ // bit 7 and 6 are read only
+ data &= 0x3f;
+
+ LOG(("PIA #%s: control A write = %02X\n", tag(), data));
+
+ // update the control register
+ m_ctl_a = data;
+
+ // CA2 is configured as output
+ if(C2_OUTPUT(m_ctl_a))
+ {
+ int temp;
+
+ if(C2_SET_MODE(m_ctl_a))
+ {
+ // set/reset mode - bit value determines the new output
+ temp = C2_SET(m_ctl_a);
+ }
+ else
+ {
+ // strobe mode - output is always high unless strobed
+ temp = TRUE;
+ }
+
+ set_out_ca2(temp);
+ }
+
+ // update externals
+ update_interrupts();
+}
+
+
+//-------------------------------------------------
+// control_b_w
+//-------------------------------------------------
+
+void pia6821_device::control_b_w(UINT8 data)
+{
+ int temp;
+
+ // bit 7 and 6 are read only
+ data &= 0x3f;
+
+ LOG(("PIA #%s: control B write = %02X\n", tag(), data));
+
+ // update the control register
+ m_ctl_b = data;
+
+ if (C2_SET_MODE(m_ctl_b))
+ {
+ // set/reset mode - bit value determines the new output
+ temp = C2_SET(m_ctl_b);
+ }
+ else
+ {
+ // strobe mode - output is always high unless strobed
+ temp = TRUE;
+ }
+
+ set_out_cb2(temp);
+
+ // update externals
+ update_interrupts();
+}
+
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+WRITE8_MEMBER( pia6821_device::write )
+{
+ reg_w(offset, data);
+}
+
+void pia6821_device::reg_w(UINT8 offset, UINT8 data)
+{
+ switch (offset & 0x03)
+ {
+ default: // impossible
+ case 0x00:
+ if (OUTPUT_SELECTED(m_ctl_a))
+ {
+ port_a_w(data);
+ }
+ else
+ {
+ ddr_a_w(data);
+ }
+ break;
+
+ case 0x01:
+ control_a_w( data);
+ break;
+
+ case 0x02:
+ if(OUTPUT_SELECTED(m_ctl_b))
+ {
+ port_b_w(data);
+ }
+ else
+ {
+ ddr_b_w(data);
+ }
+ break;
+
+ case 0x03:
+ control_b_w(data);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// write_alt
+//-------------------------------------------------
+
+WRITE8_MEMBER( pia6821_device::write_alt )
+{
+ reg_w(((offset << 1) & 0x02) | ((offset >> 1) & 0x01), data);
+}
+
+
+//-------------------------------------------------
+// porta_r
+//-------------------------------------------------
+
+READ8_MEMBER( pia6821_device::porta_r )
+{
+ return m_in_a;
+}
+
+
+//-------------------------------------------------
+// set_a_input
+//-------------------------------------------------
+
+void pia6821_device::set_a_input(UINT8 data, UINT8 z_mask)
+{
+ assert_always(m_in_a_func.isnull(), "pia6821_porta_w() called when in_a_func implemented");
+
+ LOG(("PIA #%s: set input port A = %02X\n", tag(), data));
+
+ m_in_a = data;
+ m_port_a_z_mask = z_mask;
+ m_in_a_pushed = true;
+}
+
+
+//-------------------------------------------------
+// pia6821_porta_w
+//-------------------------------------------------
+
+WRITE8_MEMBER( pia6821_device::porta_w )
+{
+ set_a_input(data, 0);
+}
+
+
+//-------------------------------------------------
+// a_output
+//-------------------------------------------------
+
+UINT8 pia6821_device::a_output()
+{
+ m_out_a_needs_pulled = false;
+
+ return get_out_a_value();
+}
+
+
+//-------------------------------------------------
+// ca1_r
+//-------------------------------------------------
+
+READ_LINE_MEMBER( pia6821_device::ca1_r )
+{
+ return m_in_ca1;
+}
+
+
+//-------------------------------------------------
+// ca1_w
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( pia6821_device::ca1_w )
+{
+ LOG(("PIA #%s: set input CA1 = %d\n", tag(), state));
+
+ // the new state has caused a transition
+ if((m_in_ca1 != state) && ((state && C1_LOW_TO_HIGH(m_ctl_a)) || (!state && C1_HIGH_TO_LOW(m_ctl_a))))
+ {
+ LOG(("PIA #%s: CA1 triggering\n", tag()));
+
+ // mark the IRQ
+ m_irq_a1 = TRUE;
+
+ // update externals
+ update_interrupts();
+
+ // CA2 is configured as output and in read strobe mode and cleared by a CA1 transition
+ if(C2_OUTPUT(m_ctl_a) && C2_STROBE_MODE(m_ctl_a) && STROBE_C1_RESET(m_ctl_a))
+ {
+ set_out_ca2(TRUE);
+ }
+ }
+
+ // set the new value for CA1
+ m_in_ca1 = state;
+ m_in_ca1_pushed = true;
+}
+
+
+//-------------------------------------------------
+// ca2_r
+//-------------------------------------------------
+
+READ_LINE_MEMBER( pia6821_device::ca2_r )
+{
+ return m_in_ca2;
+}
+
+
+//-------------------------------------------------
+// ca2_w
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( pia6821_device::ca2_w )
+{
+ LOG(("PIA #%s: set input CA2 = %d\n", tag(), state));
+
+ // if input mode and the new state has caused a transition
+ if(C2_INPUT(m_ctl_a) && (m_in_ca2 != state) && ((state && C2_LOW_TO_HIGH(m_ctl_a)) || (!state && C2_HIGH_TO_LOW(m_ctl_a))))
+ {
+ LOG(("PIA #%s: CA2 triggering\n", tag()));
+
+ // mark the IRQ
+ m_irq_a2 = TRUE;
+
+ // update externals
+ update_interrupts();
+ }
+
+ // set the new value for CA2
+ m_in_ca2 = state;
+ m_in_ca2_pushed = true;
+}
+
+
+//-------------------------------------------------
+// ca2_output
+//-------------------------------------------------
+
+int pia6821_device::ca2_output()
+{
+ m_out_ca2_needs_pulled = false;
+
+ return m_out_ca2;
+}
+
+
+//-------------------------------------------------
+// ca2_output_z - version of ca2_output which
+// takes account of internal pullup resistor
+//-------------------------------------------------
+
+int pia6821_device::ca2_output_z()
+{
+ m_out_ca2_needs_pulled = false;
+
+ // If it's an output, output the bit, if it's an input, it's
+ // pulled up
+ return m_out_ca2 | C2_INPUT(m_ctl_a);
+}
+
+
+//-------------------------------------------------
+// portb_r
+//-------------------------------------------------
+
+READ8_MEMBER( pia6821_device::portb_r )
+{
+ return m_in_b;
+}
+
+
+//-------------------------------------------------
+// portb_w
+//-------------------------------------------------
+
+WRITE8_MEMBER( pia6821_device::portb_w )
+{
+ assert_always(m_in_b_func.isnull(), "pia_set_input_b() called when in_b_func implemented");
+
+ LOG(("PIA #%s: set input port B = %02X\n", tag(), data));
+
+ m_in_b = data;
+ m_in_b_pushed = true;
+}
+
+
+//-------------------------------------------------
+// b_output
+//-------------------------------------------------
+
+UINT8 pia6821_device::b_output()
+{
+ m_out_b_needs_pulled = false;
+
+ return get_out_b_value();
+}
+
+
+//-------------------------------------------------
+// cb1_r
+//-------------------------------------------------
+
+READ_LINE_MEMBER( pia6821_device::cb1_r )
+{
+ return m_in_cb1;
+}
+
+
+//-------------------------------------------------
+// cb1_w
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( pia6821_device::cb1_w )
+{
+ LOG(("PIA #%s: set input CB1 = %d\n", tag(), state));
+
+ // the new state has caused a transition
+ if((m_in_cb1 != state) && ((state && C1_LOW_TO_HIGH(m_ctl_b)) || (!state && C1_HIGH_TO_LOW(m_ctl_b))))
+ {
+ LOG(("PIA #%s: CB1 triggering\n", tag()));
+
+ // mark the IRQ
+ m_irq_b1 = 1;
+
+ // update externals
+ update_interrupts();
+
+ // If CB2 is configured as a write-strobe output which is reset by a CB1
+ // transition, this reset will only happen when a read from port B implicitly
+ // clears the IRQ B1 flag. So we handle the CB2 reset there. Note that this
+ // is different from what happens with port A.
+ }
+
+ // set the new value for CB1
+ m_in_cb1 = state;
+ m_in_cb1_pushed = true;
+}
+
+
+//-------------------------------------------------
+// cb2_r
+//-------------------------------------------------
+
+READ_LINE_MEMBER( pia6821_device::cb2_r )
+{
+ return m_in_cb2;
+}
+
+
+//-------------------------------------------------
+// cb2_w
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( pia6821_device::cb2_w )
+{
+ LOG(("PIA #%s: set input CB2 = %d\n", tag(), state));
+
+ // if input mode and the new state has caused a transition
+ if (C2_INPUT(m_ctl_b) &&
+ (m_in_cb2 != state) &&
+ ((state && C2_LOW_TO_HIGH(m_ctl_b)) || (!state && C2_HIGH_TO_LOW(m_ctl_b))))
+ {
+ LOG(("PIA #%s: CB2 triggering\n", tag()));
+
+ // mark the IRQ
+ m_irq_b2 = 1;
+
+ // update externals
+ update_interrupts();
+ }
+
+ // set the new value for CA2
+ m_in_cb2 = state;
+ m_in_cb2_pushed = true;
+}
+
+
+//-------------------------------------------------
+// output_cb2
+//-------------------------------------------------
+
+int pia6821_device::cb2_output()
+{
+ m_out_cb2_needs_pulled = false;
+
+ return m_out_cb2;
+}
+
+
+//-------------------------------------------------
+// cb2_output_z
+//-------------------------------------------------
+
+int pia6821_device::cb2_output_z()
+{
+ return !C2_OUTPUT(m_ctl_b);
+}
diff --git a/trunk/src/emu/machine/6821pia.h b/trunk/src/emu/machine/6821pia.h
new file mode 100644
index 00000000000..7c37f5a2e55
--- /dev/null
+++ b/trunk/src/emu/machine/6821pia.h
@@ -0,0 +1,230 @@
+/**********************************************************************
+
+ Motorola 6821 PIA interface and emulation
+
+ Notes:
+ * get_port_b_z_mask() gives the caller the bitmask that shows
+ which bits are high-impendance when reading port B, and thus
+ neither 0 or 1. get_output_cb2_z() returns the same info
+ for the CB2 pin.
+ * set_port_a_z_mask allows the input callback to indicate
+ which port A bits are disconnected. For these bits, the
+ read operation will return the output buffer's contents.
+ * The 'alt' interface functions are used when the A0 and A1
+ address bits are swapped.
+ * All 'int' data or return values are bool, and should be
+ converted to bool at some point.
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __6821PIA_H__
+#define __6821PIA_H__
+
+#include "emu.h"
+
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_PIA6821_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, PIA6821, 0) \
+ pia6821_device::static_set_interface(*device, _intrf);
+
+#define MCFG_PIA6821_MODIFY(_tag, _intrf) \
+ MCFG_DEVICE_MODIFY(_tag) \
+ pia6821_device::static_set_interface(*device, _intrf);
+
+#define MCFG_PIA6822_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, PIA6822, 0) \
+ pia6821_device::static_set_interface(*device, _intrf);
+
+#define MCFG_PIA6822_MODIFY(_tag, _intrf) \
+ MCFG_DEVICE_MODIFY(_tag) \
+ pia6821_device::static_set_interface(*device, _intrf);
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+
+// ======================> pia6821_interface
+
+struct pia6821_interface
+{
+ devcb_read8 m_in_a_cb;
+ devcb_read8 m_in_b_cb;
+ devcb_read_line m_in_ca1_cb;
+ devcb_read_line m_in_cb1_cb;
+ devcb_read_line m_in_ca2_cb;
+ devcb_read_line m_in_cb2_cb;
+ devcb_write8 m_out_a_cb;
+ devcb_write8 m_out_b_cb;
+ devcb_write_line m_out_ca2_cb;
+ devcb_write_line m_out_cb2_cb;
+ devcb_write_line m_irq_a_cb;
+ devcb_write_line m_irq_b_cb;
+};
+
+
+
+// ======================> pia6821_device
+
+class pia6821_device : public device_t,
+ public pia6821_interface
+{
+public:
+ // construction/destruction
+ pia6821_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // static configuration helpers
+ static void static_set_interface(device_t &device, const pia6821_interface &interface);
+
+ DECLARE_READ8_MEMBER( read );
+ DECLARE_WRITE8_MEMBER( write );
+ DECLARE_READ8_MEMBER( read_alt );
+ DECLARE_WRITE8_MEMBER( write_alt );
+
+ UINT8 port_b_z_mask() const { return ~m_ddr_b; } // see first note in .c
+ void set_port_a_z_mask(UINT8 data) { m_port_a_z_mask = data; }// see second note in .c
+
+ DECLARE_READ8_MEMBER( porta_r );
+ UINT8 porta_r() { return porta_r(*memory_nonspecific_space(machine()), 0); }
+ DECLARE_WRITE8_MEMBER( porta_w );
+ void porta_w(UINT8 data) { porta_w(*memory_nonspecific_space(machine()), 0, data); }
+ void set_a_input(UINT8 data, UINT8 z_mask);
+ UINT8 a_output();
+
+ DECLARE_READ_LINE_MEMBER( ca1_r );
+ DECLARE_WRITE_LINE_MEMBER( ca1_w );
+
+ DECLARE_READ_LINE_MEMBER( ca2_r );
+ DECLARE_WRITE_LINE_MEMBER( ca2_w );
+ int ca2_output();
+ int ca2_output_z();
+
+ DECLARE_READ8_MEMBER( portb_r );
+ UINT8 portb_r() { return portb_r(*memory_nonspecific_space(machine()), 0); }
+ DECLARE_WRITE8_MEMBER( portb_w );
+ void portb_w(UINT8 data) { portb_w(*memory_nonspecific_space(machine()), 0, data); }
+ UINT8 b_output();
+
+ DECLARE_READ_LINE_MEMBER( cb1_r );
+ DECLARE_WRITE_LINE_MEMBER( cb1_w );
+
+ DECLARE_READ_LINE_MEMBER( cb2_r );
+ DECLARE_WRITE_LINE_MEMBER( cb2_w );
+ int cb2_output();
+ int cb2_output_z();
+
+ int irq_a_state() const { return m_irq_a_state; }
+ int irq_b_state() const { return m_irq_b_state; }
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+private:
+ UINT8 reg_r(UINT8 offset);
+ void reg_w(UINT8 offset, UINT8 data);
+
+ void update_interrupts();
+
+ UINT8 get_in_a_value();
+ UINT8 get_in_b_value();
+
+ UINT8 get_out_a_value();
+ UINT8 get_out_b_value();
+
+ void set_out_ca2(int data);
+ void set_out_cb2(int data);
+
+ UINT8 port_a_r();
+ UINT8 ddr_a_r();
+ UINT8 control_a_r();
+
+ UINT8 port_b_r();
+ UINT8 ddr_b_r();
+ UINT8 control_b_r();
+
+ void send_to_out_a_func(const char* message);
+ void send_to_out_b_func(const char* message);
+
+ void port_a_w(UINT8 data);
+ void ddr_a_w(UINT8 data);
+
+ void port_b_w(UINT8 data);
+ void ddr_b_w(UINT8 data);
+
+ void control_a_w(UINT8 data);
+ void control_b_w(UINT8 data);
+
+ devcb_resolved_read8 m_in_a_func;
+ devcb_resolved_read8 m_in_b_func;
+ devcb_resolved_read_line m_in_ca1_func;
+ devcb_resolved_read_line m_in_cb1_func;
+ devcb_resolved_read_line m_in_ca2_func;
+ devcb_resolved_read_line m_in_cb2_func;
+ devcb_resolved_write8 m_out_a_func;
+ devcb_resolved_write8 m_out_b_func;
+ devcb_resolved_write_line m_out_ca2_func;
+ devcb_resolved_write_line m_out_cb2_func;
+ devcb_resolved_write_line m_irq_a_func;
+ devcb_resolved_write_line m_irq_b_func;
+
+ UINT8 m_in_a;
+ UINT8 m_in_ca1;
+ UINT8 m_in_ca2;
+ UINT8 m_out_a;
+ UINT8 m_out_ca2;
+ UINT8 m_port_a_z_mask;
+ UINT8 m_ddr_a;
+ UINT8 m_ctl_a;
+ UINT8 m_irq_a1;
+ UINT8 m_irq_a2;
+ UINT8 m_irq_a_state;
+
+ UINT8 m_in_b;
+ UINT8 m_in_cb1;
+ UINT8 m_in_cb2;
+ UINT8 m_out_b;
+ UINT8 m_out_cb2;
+ UINT8 m_last_out_cb2_z;
+ UINT8 m_ddr_b;
+ UINT8 m_ctl_b;
+ UINT8 m_irq_b1;
+ UINT8 m_irq_b2;
+ UINT8 m_irq_b_state;
+
+ // variables that indicate if access a line externally -
+ // used to for logging purposes ONLY
+ bool m_in_a_pushed;
+ bool m_out_a_needs_pulled;
+ bool m_in_ca1_pushed;
+ bool m_in_ca2_pushed;
+ bool m_out_ca2_needs_pulled;
+ bool m_in_b_pushed;
+ bool m_out_b_needs_pulled;
+ bool m_in_cb1_pushed;
+ bool m_in_cb2_pushed;
+ bool m_out_cb2_needs_pulled;
+ bool m_logged_port_a_not_connected;
+ bool m_logged_port_b_not_connected;
+ bool m_logged_ca1_not_connected;
+ bool m_logged_ca2_not_connected;
+ bool m_logged_cb1_not_connected;
+ bool m_logged_cb2_not_connected;
+};
+
+
+// device type definition
+extern const device_type PIA6821;
+
+
+#endif /* __6821PIA_H__ */
diff --git a/trunk/src/emu/machine/6840ptm.c b/trunk/src/emu/machine/6840ptm.c
new file mode 100644
index 00000000000..14034d566ff
--- /dev/null
+++ b/trunk/src/emu/machine/6840ptm.c
@@ -0,0 +1,728 @@
+/***************************************************************************
+
+ Motorola 6840 (PTM)
+
+ Programmable Timer Module
+
+ Written By J.Wallace based on previous work by Aaron Giles,
+ 'Re-Animator' and Mathis Rosenhauer.
+
+ Todo:
+ Confirm handling for 'Single Shot' operation.
+ (Datasheet suggests that output starts high, going low
+ on timeout, opposite of continuous case)
+ Establish whether ptm6840_set_c? routines can replace
+ hard coding of external clock frequencies.
+
+
+ Operation:
+ The interface is arranged as follows:
+
+ Internal Clock frequency,
+ Clock 1 frequency, Clock 2 frequency, Clock 3 frequency,
+ Clock 1 output, Clock 2 output, Clock 3 output,
+ IRQ function
+
+ If the external clock frequencies are not fixed, they should be
+ entered as '0', and the ptm6840_set_c?(which, state) functions
+ should be used instead if necessary (This should allow the VBLANK
+ clock on the MCR units to operate).
+
+
+ 2009-06 Converted to be a device
+
+***************************************************************************/
+
+#include "emu.h"
+#include "6840ptm.h"
+#include "devhelpr.h"
+
+
+#define PTMVERBOSE 0
+#define PLOG(x) do { if (PTMVERBOSE) logerror x; } while (0)
+
+/***************************************************************************
+ LOCAL VARIABLES
+***************************************************************************/
+
+const char *const ptm6840_device::opmode[] =
+{
+ "000 continuous mode",
+ "001 freq comparison mode",
+ "010 continuous mode",
+ "011 pulse width comparison mode",
+ "100 single shot mode",
+ "101 freq comparison mode",
+ "110 single shot mode",
+ "111 pulse width comparison mode"
+};
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+// device type definition
+const device_type PTM6840 = &device_creator<ptm6840_device>;
+
+//-------------------------------------------------
+// ptm6840_device - constructor
+//-------------------------------------------------
+
+ptm6840_device::ptm6840_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, PTM6840, "6840 PTM", tag, owner, clock)
+{
+ memset(static_cast<ptm6840_interface *>(this), 0, sizeof(ptm6840_interface));
+}
+
+
+//-------------------------------------------------
+// static_set_interface - set the interface
+// struct
+//-------------------------------------------------
+
+void ptm6840_device::static_set_interface(device_t &device, const ptm6840_interface &interface)
+{
+ ptm6840_device &ptm = downcast<ptm6840_device &>(device);
+ static_cast<ptm6840_interface &>(ptm) = interface;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void ptm6840_device::device_start()
+{
+ m_internal_clock = m_internal_clock;
+ // resolve callbacks
+ for (int i = 0; i < 3; i++)
+ {
+ m_out_func[i].resolve(m_out_cb[i], *this);
+ }
+
+ for (int i = 0; i < 3; i++)
+ {
+ if ( m_external_clock[i] )
+ {
+ m_external_clock[i] = m_external_clock[i];
+ }
+ else
+ {
+ m_external_clock[i] = 1;
+ }
+ }
+
+
+ m_timer[0] = timer_alloc(0);
+ m_timer[1] = timer_alloc(1);
+ m_timer[2] = timer_alloc(2);
+
+ for (int i = 0; i < 3; i++)
+ {
+ m_timer[i]->enable(false);
+ }
+
+ m_irq_func.resolve(m_irq_cb, *this);
+
+ // register for state saving
+ save_item(NAME(m_lsb_buffer));
+ save_item(NAME(m_msb_buffer));
+ save_item(NAME(m_status_read_since_int));
+ save_item(NAME(m_status_reg));
+ save_item(NAME(m_t3_divisor));
+ save_item(NAME(m_t3_scaler));
+ save_item(NAME(m_internal_clock));
+ save_item(NAME(m_IRQ));
+
+ save_item(NAME(m_control_reg));
+ save_item(NAME(m_output));
+ save_item(NAME(m_gate));
+ save_item(NAME(m_clk));
+ save_item(NAME(m_mode));
+ save_item(NAME(m_fired));
+ save_item(NAME(m_enabled));
+ save_item(NAME(m_external_clock));
+ save_item(NAME(m_counter));
+ save_item(NAME(m_latch));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void ptm6840_device::device_reset()
+{
+ m_control_reg[2] = 0;
+ m_control_reg[1] = 0;
+ m_control_reg[0] = 1;
+ m_status_reg = 0;
+ m_t3_divisor = 1;
+ m_status_read_since_int = 0;
+ m_IRQ = 0;
+ for (int i = 0; i < 3; i++)
+ {
+ m_counter[i] = 0xffff;
+ m_latch[i] = 0xffff;
+ m_output[i] = 0;
+ m_fired[i] = 0;
+ }
+}
+
+
+//-------------------------------------------------
+// device_timer - handle timer callbacks
+//-------------------------------------------------
+
+void ptm6840_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ timeout(id);
+}
+
+
+//-------------------------------------------------
+// subtract_from_counter - Subtract from Counter
+//-------------------------------------------------
+
+void ptm6840_device::subtract_from_counter(int counter, int count)
+{
+ double clock;
+
+ // Determine the clock frequency for this timer
+ if (m_control_reg[counter] & 0x02)
+ {
+ clock = m_internal_clock;
+ }
+ else
+ {
+ clock = m_external_clock[counter];
+ }
+
+ // Dual-byte mode
+ if (m_control_reg[counter] & 0x04)
+ {
+ int lsb = m_counter[counter] & 0xff;
+ int msb = m_counter[counter] >> 8;
+
+ // Count the clocks
+ lsb -= count;
+
+ // Loop while we're less than zero
+ while (lsb < 0)
+ {
+ // Borrow from the MSB
+ lsb += (m_latch[counter] & 0xff) + 1;
+ msb--;
+
+ // If MSB goes less than zero, we've expired
+ if (msb < 0)
+ {
+ timeout(counter);
+ msb = (m_latch[counter] >> 8) + 1;
+ }
+ }
+
+ // Store the result
+ m_counter[counter] = (msb << 8) | lsb;
+ }
+
+ // Word mode
+ else
+ {
+ int word = m_counter[counter];
+
+ // Count the clocks
+ word -= count;
+
+ // loop while we're less than zero
+ while (word < 0)
+ {
+ // Borrow from the MSB
+ word += m_latch[counter] + 1;
+
+ // We've expired
+ timeout(counter);
+ }
+
+ // Store the result
+ m_counter[counter] = word;
+ }
+
+ if (m_enabled[counter])
+ {
+ attotime duration = attotime::from_hz(clock) * m_counter[counter];
+
+ if (counter == 2)
+ {
+ duration *= m_t3_divisor;
+ }
+
+ m_timer[counter]->adjust(duration);
+ }
+}
+
+
+
+//-------------------------------------------------
+// tick
+//-------------------------------------------------
+
+void ptm6840_device::tick(int counter, int count)
+{
+ if (counter == 2)
+ {
+ m_t3_scaler += count;
+
+ if ( m_t3_scaler > m_t3_divisor - 1)
+ {
+ subtract_from_counter(counter, 1);
+ m_t3_scaler = 0;
+ }
+ }
+ else
+ {
+ subtract_from_counter(counter, count);
+ }
+}
+
+
+
+//-------------------------------------------------
+// update_interrupts - Update Internal Interrupts
+//-------------------------------------------------
+
+void ptm6840_device::update_interrupts()
+{
+ int new_state = ((m_status_reg & 0x01) && (m_control_reg[0] & 0x40)) ||
+ ((m_status_reg & 0x02) && (m_control_reg[1] & 0x40)) ||
+ ((m_status_reg & 0x04) && (m_control_reg[2] & 0x40));
+
+ if (new_state != m_IRQ)
+ {
+ m_IRQ = new_state;
+
+ if (m_IRQ)
+ {
+ m_status_reg |= 0x80;
+ }
+ else
+ {
+ m_status_reg &= ~0x80;
+ }
+
+ m_irq_func(m_IRQ);
+ }
+}
+
+
+
+//-------------------------------------------------
+// compute_counter - Compute Counter
+//-------------------------------------------------
+
+UINT16 ptm6840_device::compute_counter( int counter ) const
+{
+ double clock;
+
+ // If there's no timer, return the count
+ if (!m_enabled[counter])
+ {
+ PLOG(("MC6840 #%s: read counter(%d): %d\n", tag(), counter, m_counter[counter]));
+ return m_counter[counter];
+ }
+
+ // determine the clock frequency for this timer
+ if (m_control_reg[counter] & 0x02)
+ {
+ clock = m_internal_clock;
+ PLOG(("MC6840 #%s: %d internal clock freq %f \n", tag(), counter, clock));
+ }
+ else
+ {
+ clock = m_external_clock[counter];
+ PLOG(("MC6840 #%s: %d external clock freq %f \n", tag(), counter, clock));
+ }
+ // See how many are left
+ int remaining = (m_timer[counter]->remaining() * clock).as_double();
+
+ // Adjust the count for dual byte mode
+ if (m_control_reg[counter] & 0x04)
+ {
+ int divisor = (m_counter[counter] & 0xff) + 1;
+ int msb = remaining / divisor;
+ int lsb = remaining % divisor;
+ remaining = (msb << 8) | lsb;
+ }
+ PLOG(("MC6840 #%s: read counter(%d): %d\n", tag(), counter, remaining));
+ return remaining;
+}
+
+
+
+//-------------------------------------------------
+// reload_count - Reload Counter
+//-------------------------------------------------
+
+void ptm6840_device::reload_count(int idx)
+{
+ double clock;
+
+ // Copy the latched value in
+ m_counter[idx] = m_latch[idx];
+
+ // Determine the clock frequency for this timer
+ if (m_control_reg[idx] & 0x02)
+ {
+ clock = m_internal_clock;
+ PLOG(("MC6840 #%s: %d internal clock freq %f \n", tag(), idx, clock));
+ }
+ else
+ {
+ clock = m_external_clock[idx];
+ PLOG(("MC6840 #%s: %d external clock freq %f \n", tag(), idx, clock));
+ }
+
+ // Determine the number of clock periods before we expire
+ int count = m_counter[idx];
+ if (m_control_reg[idx] & 0x04)
+ {
+ count = ((count >> 8) + 1) * ((count & 0xff) + 1);
+ }
+ else
+ {
+ count = count + 1;
+ }
+
+ m_fired[idx] = 0;
+
+ if ((m_mode[idx] == 4) || (m_mode[idx] == 6))
+ {
+ m_output[idx] = 1;
+ if (!m_out_func[idx].isnull())
+ {
+ m_out_func[idx](0, m_output[idx]);
+ }
+ }
+
+ // Set the timer
+ PLOG(("MC6840 #%s: reload_count(%d): clock = %f count = %d\n", tag(), idx, clock, count));
+
+ attotime duration = attotime::from_hz(clock) * count;
+ if (idx == 2)
+ {
+ duration *= m_t3_divisor;
+ }
+
+ PLOG(("MC6840 #%s: reload_count(%d): output = %lf\n", tag(), idx, duration.as_double()));
+
+#if 0
+ if (!(m_control_reg[idx] & 0x02))
+ {
+ if (!m_external_clock[idx])
+ {
+ m_enabled[idx] = 0;
+ m_timer[idx]->enable(false);
+ }
+ }
+ else
+#endif
+ {
+ m_enabled[idx] = 1;
+ m_timer[idx]->adjust(duration);
+ m_timer[idx]->enable(true);
+ }
+}
+
+
+
+//-------------------------------------------------
+// read - Read Timer
+//-------------------------------------------------
+
+READ8_MEMBER( ptm6840_device::read )
+{
+ int val;
+
+ switch ( offset )
+ {
+ case PTM_6840_CTRL1:
+ {
+ val = 0;
+ break;
+ }
+
+ case PTM_6840_STATUS:
+ {
+ PLOG(("%s: MC6840 #%s: Status read = %04X\n", machine().describe_context(), tag(), m_status_reg));
+ m_status_read_since_int |= m_status_reg & 0x07;
+ val = m_status_reg;
+ break;
+ }
+
+ case PTM_6840_MSBBUF1:
+ case PTM_6840_MSBBUF2:
+ case PTM_6840_MSBBUF3:
+ {
+ int idx = (offset - 2) / 2;
+ int result = compute_counter(idx);
+
+ // Clear the interrupt if the status has been read
+ if (m_status_read_since_int & (1 << idx))
+ {
+ m_status_reg &= ~(1 << idx);
+ update_interrupts();
+ }
+
+ m_lsb_buffer = result & 0xff;
+
+ PLOG(("%s: MC6840 #%s: Counter %d read = %04X\n", machine().describe_context(), tag(), idx, result >> 8));
+ val = result >> 8;
+ break;
+ }
+
+ case PTM_6840_LSB1:
+ case PTM_6840_LSB2:
+ case PTM_6840_LSB3:
+ {
+ val = m_lsb_buffer;
+ break;
+ }
+
+ default:
+ {
+ val = 0;
+ break;
+ }
+
+ }
+ return val;
+}
+
+
+//-------------------------------------------------
+// write - Write Timer
+//-------------------------------------------------
+
+WRITE8_MEMBER( ptm6840_device::write )
+{
+ switch ( offset )
+ {
+ case PTM_6840_CTRL1:
+ case PTM_6840_CTRL2:
+ {
+ int idx = (offset == 1) ? 1 : (m_control_reg[1] & 0x01) ? 0 : 2;
+ UINT8 diffs = data ^ m_control_reg[idx];
+ m_t3_divisor = (m_control_reg[2] & 0x01) ? 8 : 1;
+ m_mode[idx] = (data >> 3) & 0x07;
+ m_control_reg[idx] = data;
+
+ PLOG(("MC6840 #%s : Control register %d selected\n", tag(), idx));
+ PLOG(("operation mode = %s\n", opmode[ m_mode[idx] ]));
+ PLOG(("value = %04X\n", m_control_reg[idx]));
+ PLOG(("t3divisor = %d\n", m_t3_divisor));
+
+ if (!(m_control_reg[idx] & 0x80 ))
+ {
+ // Output cleared
+ m_out_func[idx](0, 0);
+ }
+ // Reset?
+ if (idx == 0 && (diffs & 0x01))
+ {
+ // Holding reset down
+ if (data & 0x01)
+ {
+ PLOG(("MC6840 #%s : Timer reset\n", tag()));
+ for (int i = 0; i < 3; i++)
+ {
+ m_timer[i]->enable(false);
+ m_enabled[i] = 0;
+ }
+ }
+ // Releasing reset
+ else
+ {
+ for (int i = 0; i < 3; i++)
+ {
+ reload_count(i);
+ }
+ }
+
+ m_status_reg = 0;
+ update_interrupts();
+
+ // Changing the clock source? (e.g. Zwackery)
+ if (diffs & 0x02)
+ {
+ reload_count(idx);
+ }
+ }
+ break;
+ }
+
+ case PTM_6840_MSBBUF1:
+ case PTM_6840_MSBBUF2:
+ case PTM_6840_MSBBUF3:
+ {
+ PLOG(("MC6840 #%s msbbuf%d = %02X\n", tag(), offset / 2, data));
+ m_msb_buffer = data;
+ break;
+ }
+
+ case PTM_6840_LSB1:
+ case PTM_6840_LSB2:
+ case PTM_6840_LSB3:
+ {
+ int idx = (offset - 3) / 2;
+ m_latch[idx] = (m_msb_buffer << 8) | (data & 0xff);
+
+ // Clear the interrupt
+ m_status_reg &= ~(1 << idx);
+ update_interrupts();
+
+ // Reload the count if in an appropriate mode
+ if (!(m_control_reg[idx] & 0x10))
+ {
+ reload_count(idx);
+ }
+
+ PLOG(("%s:MC6840 #%s: Counter %d latch = %04X\n", machine().describe_context(), tag(), idx, m_latch[idx]));
+ break;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// timeout - Called if timer is mature
+//-------------------------------------------------
+
+void ptm6840_device::timeout(int idx)
+{
+ PLOG(("**ptm6840 %s t%d timeout**\n", tag(), idx));
+
+ // Set the interrupt flag
+ m_status_reg |= (1 << idx);
+ m_status_read_since_int &= ~(1 << idx);
+ update_interrupts();
+
+ if ( m_control_reg[idx] & 0x80 )
+ {
+ if ((m_mode[idx] == 0)||(m_mode[idx] == 2))
+ {
+ m_output[idx] = m_output[idx] ? 0 : 1;
+ PLOG(("**ptm6840 %s t%d output %d **\n", tag(), idx, m_output[idx]));
+
+ m_out_func[idx](0, m_output[idx]);
+ }
+ if ((m_mode[idx] == 4)||(m_mode[idx] == 6))
+ {
+ if (!m_fired[idx])
+ {
+ m_output[idx] = 1;
+ PLOG(("**ptm6840 %s t%d output %d **\n", tag(), idx, m_output[idx]));
+
+ m_out_func[idx](0, m_output[idx]);
+
+ // No changes in output until reinit
+ m_fired[idx] = 1;
+
+ m_status_reg |= (1 << idx);
+ m_status_read_since_int &= ~(1 << idx);
+ update_interrupts();
+ }
+ }
+ }
+ m_enabled[idx]= 0;
+ reload_count(idx);
+}
+
+
+//-------------------------------------------------
+// set_gate - set gate status (0 or 1)
+//-------------------------------------------------
+
+void ptm6840_device::set_gate(int idx, int state)
+{
+ if ((m_mode[idx] & 1) == 0)
+ {
+ if (state == 0 && m_gate[idx])
+ {
+ reload_count(idx);
+ }
+ }
+ m_gate[idx] = state;
+}
+
+WRITE_LINE_MEMBER( ptm6840_device::set_g1 ) { set_gate(0, state); }
+WRITE_LINE_MEMBER( ptm6840_device::set_g2 ) { set_gate(1, state); }
+WRITE_LINE_MEMBER( ptm6840_device::set_g3 ) { set_gate(2, state); }
+
+
+//-------------------------------------------------
+// set_clock - set clock status (0 or 1)
+//-------------------------------------------------
+
+void ptm6840_device::set_clock(int idx, int state)
+{
+ m_clk[idx] = state;
+
+ if (!(m_control_reg[idx] & 0x02))
+ {
+ if (state)
+ {
+ tick(idx, 1);
+ }
+ }
+}
+
+WRITE_LINE_MEMBER( ptm6840_device::set_c1 ) { set_clock(0, state); }
+WRITE_LINE_MEMBER( ptm6840_device::set_c2 ) { set_clock(1, state); }
+WRITE_LINE_MEMBER( ptm6840_device::set_c3 ) { set_clock(2, state); }
+
+
+//-------------------------------------------------
+// set_ext_clock - set external clock frequency
+//-------------------------------------------------
+
+void ptm6840_device::set_ext_clock(int counter, double clock)
+{
+ m_external_clock[counter] = clock;
+
+ if (!(m_control_reg[counter] & 0x02))
+ {
+ if (!m_external_clock[counter])
+ {
+ m_enabled[counter] = 0;
+ m_timer[counter]->enable(false);
+ }
+ }
+ else
+ {
+ int count;
+ attotime duration;
+
+ // Determine the number of clock periods before we expire
+ count = m_counter[counter];
+
+ if (m_control_reg[counter] & 0x04)
+ {
+ count = ((count >> 8) + 1) * ((count & 0xff) + 1);
+ }
+ else
+ {
+ count = count + 1;
+ }
+
+ duration = attotime::from_hz(clock) * count;
+
+ if (counter == 2)
+ {
+ duration *= m_t3_divisor;
+ }
+
+ m_enabled[counter] = 1;
+ m_timer[counter]->adjust(duration);
+ m_timer[counter]->enable(true);
+ }
+}
diff --git a/trunk/src/emu/machine/6840ptm.h b/trunk/src/emu/machine/6840ptm.h
new file mode 100644
index 00000000000..fbf8f18a77d
--- /dev/null
+++ b/trunk/src/emu/machine/6840ptm.h
@@ -0,0 +1,139 @@
+/***************************************************************************
+
+ Motorola 6840 (PTM)
+
+ Programmable Timer Module
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __6840PTM_H__
+#define __6840PTM_H__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// DEVICE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_PTM6840_ADD(_tag, _interface) \
+ MCFG_DEVICE_ADD(_tag, PTM6840, 0) \
+ ptm6840_device::static_set_interface(*device, _interface);
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> ptm6840_interface
+
+struct ptm6840_interface
+{
+ double m_internal_clock;
+ double m_external_clock[3];
+
+ devcb_write8 m_out_cb[3]; // function to call when output[idx] changes
+ devcb_write_line m_irq_cb; // function called if IRQ line changes
+};
+
+
+
+// ======================> ptm6840_device
+
+class ptm6840_device : public device_t,
+ public ptm6840_interface
+{
+public:
+ // construction/destruction
+ ptm6840_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // static configuration helpers
+ static void static_set_interface(device_t &device, const ptm6840_interface &interface);
+
+ int status(int clock) const { return m_enabled[clock]; } // get whether timer is enabled
+ int irq_state() const { return m_IRQ; } // get IRQ state
+ UINT16 count(int counter) const { return compute_counter(counter); } // get counter value
+ void set_ext_clock(int counter, double clock); // set clock frequency
+ int ext_clock(int counter) const { return m_external_clock[counter]; } // get clock frequency
+
+ DECLARE_WRITE8_MEMBER( write );
+ void write(offs_t offset, UINT8 data) { write(*memory_nonspecific_space(machine()), offset, data); }
+ DECLARE_READ8_MEMBER( read );
+ UINT8 read(offs_t offset) { return read(*memory_nonspecific_space(machine()), offset); }
+
+ void set_gate(int idx, int state);
+ DECLARE_WRITE_LINE_MEMBER( set_g1 );
+ DECLARE_WRITE_LINE_MEMBER( set_g2 );
+ DECLARE_WRITE_LINE_MEMBER( set_g3 );
+
+ void set_clock(int idx, int state);
+ DECLARE_WRITE_LINE_MEMBER( set_c1 );
+ DECLARE_WRITE_LINE_MEMBER( set_c2 );
+ DECLARE_WRITE_LINE_MEMBER( set_c3 );
+
+ void update_interrupts();
+
+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);
+
+private:
+ void subtract_from_counter(int counter, int count);
+ void tick(int counter, int count);
+ void timeout(int idx);
+
+ UINT16 compute_counter(int counter) const;
+ void reload_count(int idx);
+
+ enum
+ {
+ PTM_6840_CTRL1 = 0,
+ PTM_6840_CTRL2 = 1,
+ PTM_6840_STATUS = 1,
+ PTM_6840_MSBBUF1 = 2,
+ PTM_6840_LSB1 = 3,
+ PTM_6840_MSBBUF2 = 4,
+ PTM_6840_LSB2 = 5,
+ PTM_6840_MSBBUF3 = 6,
+ PTM_6840_LSB3 = 7,
+ };
+
+ devcb_resolved_write8 m_out_func[3]; // function to call when output[idx] changes
+ devcb_resolved_write_line m_irq_func; // function called if IRQ line changes
+
+ UINT8 m_control_reg[3];
+ UINT8 m_output[3]; // Output states
+ UINT8 m_gate[3]; // Input gate states
+ UINT8 m_clk[3]; // Clock states
+ UINT8 m_enabled[3];
+ UINT8 m_mode[3];
+ UINT8 m_fired[3];
+ UINT8 m_t3_divisor;
+ UINT8 m_t3_scaler;
+ UINT8 m_IRQ;
+ UINT8 m_status_reg;
+ UINT8 m_status_read_since_int;
+ UINT8 m_lsb_buffer;
+ UINT8 m_msb_buffer;
+
+ // Each PTM has 3 timers
+ emu_timer *m_timer[3];
+
+ UINT16 m_latch[3];
+ UINT16 m_counter[3];
+
+ static const char *const opmode[];
+};
+
+
+// device type definition
+extern const device_type PTM6840;
+
+
+#endif /* __6840PTM_H__ */
diff --git a/trunk/src/emu/machine/6850acia.c b/trunk/src/emu/machine/6850acia.c
new file mode 100644
index 00000000000..3fe6cb64177
--- /dev/null
+++ b/trunk/src/emu/machine/6850acia.c
@@ -0,0 +1,746 @@
+/*********************************************************************
+
+ 6850acia.c
+
+ 6850 ACIA code
+
+*********************************************************************/
+
+#include "emu.h"
+#include "6850acia.h"
+#include "devhelpr.h"
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define LOG 0
+
+#define CR1_0 0x03
+#define CR4_2 0x1C
+#define CR6_5 0x60
+#define CR7 0x80
+
+#define TXD(_data) \
+ m_out_tx_func(_data)
+
+#define RTS(_data) \
+ m_out_rts_func(_data)
+
+/***************************************************************************
+ LOCAL VARIABLES
+***************************************************************************/
+
+const int acia6850_device::ACIA6850_DIVIDE[3] = { 1, 16, 64 };
+
+const int acia6850_device::ACIA6850_WORD[8][3] =
+{
+ { 7, EVEN, 2 },
+ { 7, ODD, 2 },
+ { 7, EVEN, 1 },
+ { 7, ODD, 1 },
+ { 8, NONE, 2 },
+ { 8, NONE, 1 },
+ { 8, EVEN, 1 },
+ { 8, ODD, 1 }
+};
+
+
+
+/***************************************************************************
+ LIVE DEVICE
+***************************************************************************/
+
+// device type definition
+const device_type ACIA6850 = &device_creator<acia6850_device>;
+
+//-------------------------------------------------
+// acia6850_device - constructor
+//-------------------------------------------------
+
+acia6850_device::acia6850_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, ACIA6850, "6850 ACIA", tag, owner, clock)
+{
+ memset(static_cast<acia6850_interface *>(this), 0, sizeof(acia6850_interface));
+}
+
+
+//-------------------------------------------------
+// static_set_interface - set the interface
+// struct
+//-------------------------------------------------
+
+void acia6850_device::static_set_interface(device_t &device, const acia6850_interface &interface)
+{
+ acia6850_device &ptm = downcast<acia6850_device &>(device);
+ static_cast<acia6850_interface &>(ptm) = interface;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void acia6850_device::device_start()
+{
+ // resolve callbacks
+ m_in_rx_func.resolve(m_in_rx_cb, *this);
+ m_out_tx_func.resolve(m_out_tx_cb, *this);
+ m_in_cts_func.resolve(m_in_cts_cb, *this);
+ m_out_rts_func.resolve(m_out_rts_cb, *this);
+ m_in_dcd_func.resolve(m_in_dcd_cb, *this);
+ m_out_irq_func.resolve(m_out_irq_cb, *this);
+
+ m_tx_counter = 0;
+ m_rx_counter = 0;
+ m_rx_timer = timer_alloc(TIMER_ID_RECEIVE);
+ m_tx_timer = timer_alloc(TIMER_ID_TRANSMIT);
+ m_first_reset = 1;
+ m_status_read = 0;
+ m_brk = 0;
+
+ m_rx_timer->reset();
+ m_tx_timer->reset();
+
+ save_item(NAME(m_ctrl));
+ save_item(NAME(m_status));
+ save_item(NAME(m_rx_clock));
+ save_item(NAME(m_tx_clock));
+ save_item(NAME(m_rx_counter));
+ save_item(NAME(m_tx_counter));
+ save_item(NAME(m_rx_shift));
+ save_item(NAME(m_tx_shift));
+ save_item(NAME(m_rdr));
+ save_item(NAME(m_tdr));
+ save_item(NAME(m_rx_bits));
+ save_item(NAME(m_tx_bits));
+ save_item(NAME(m_rx_parity));
+ save_item(NAME(m_tx_parity));
+ save_item(NAME(m_tx_int));
+
+ save_item(NAME(m_divide));
+ save_item(NAME(m_overrun));
+ save_item(NAME(m_reset));
+ save_item(NAME(m_first_reset));
+ save_item(NAME(m_rts));
+ save_item(NAME(m_brk));
+ save_item(NAME(m_status_read));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void acia6850_device::device_reset()
+{
+ int cts = m_in_cts_func();
+ int dcd = m_in_dcd_func();
+
+ m_status = (cts << 3) | (dcd << 2) | ACIA6850_STATUS_TDRE;
+ m_tdr = 0;
+ m_rdr = 0;
+ m_tx_shift = 0;
+ m_rx_shift = 0;
+ m_tx_counter = 0;
+ m_rx_counter = 0;
+
+ TXD(1);
+ m_overrun = 0;
+ m_status_read = 0;
+ m_brk = 0;
+
+ m_rx_state = START;
+ m_tx_state = START;
+ m_irq = 0;
+
+ m_out_irq_func(1);
+
+ if (m_first_reset)
+ {
+ m_first_reset = 0;
+
+ RTS(1);
+ }
+ else
+ {
+ RTS(m_rts);
+ }
+}
+
+
+//-------------------------------------------------
+// device_timer - handle timer callbacks
+//-------------------------------------------------
+
+void acia6850_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case TIMER_ID_TRANSMIT:
+ tx_tick();
+ m_tx_counter = 0;
+ break;
+
+ case TIMER_ID_RECEIVE:
+ rx_tick();
+ m_rx_counter = 0;
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// acia6850_stat_r - Read Status Register
+//-------------------------------------------------
+
+READ8_MEMBER( acia6850_device::status_read )
+{
+ UINT8 status;
+
+ m_status_read = 1;
+ status = m_status;
+
+ if (status & ACIA6850_STATUS_CTS)
+ {
+ status &= ~ACIA6850_STATUS_TDRE;
+ }
+
+ return status;
+}
+
+
+//-------------------------------------------------
+// control_write - Write Control Register
+//-------------------------------------------------
+
+WRITE8_MEMBER( acia6850_device::control_write )
+{
+ if (LOG) logerror("MC6850 '%s' Control: %02x\n", tag(), data);
+
+ // Counter Divide Select Bits
+
+ int divide = data & CR1_0;
+
+ if (divide == 3)
+ {
+ m_reset = 1;
+ device_reset();
+ }
+ else
+ {
+ m_reset = 0;
+ m_divide = ACIA6850_DIVIDE[divide];
+ }
+
+ // Word Select Bits
+
+ int wordsel = (data & CR4_2) >> 2;
+
+ m_bits = ACIA6850_WORD[wordsel][0];
+ m_parity = (parity_type)ACIA6850_WORD[wordsel][1];
+ m_stopbits = ACIA6850_WORD[wordsel][2];
+
+ // Transmitter Control Bits
+
+ switch ((data & CR6_5) >> 5)
+ {
+ case 0:
+ m_rts = 0;
+ RTS(m_rts);
+
+ m_tx_int = 0;
+ m_brk = 0;
+ break;
+
+ case 1:
+ m_rts = 0;
+ RTS(m_rts);
+
+ m_tx_int = 1;
+ m_brk = 0;
+ break;
+
+ case 2:
+ m_rts = 1;
+ RTS(m_rts);
+
+ m_tx_int = 0;
+ m_brk = 0;
+ break;
+
+ case 3:
+ m_rts = 0;
+ RTS(m_rts);
+
+ m_tx_int = 0;
+ m_brk = 1;
+ break;
+ }
+
+ check_interrupts();
+
+ // After writing the word type, set the rx/tx clocks (provided the divide values have changed)
+
+ if ((m_ctrl ^ data) & CR1_0)
+ {
+ if (!m_reset)
+ {
+ if (m_rx_clock)
+ {
+ attotime rx_period = attotime::from_hz(m_rx_clock) * m_divide;
+ m_rx_timer->adjust(rx_period, 0, rx_period);
+ }
+
+ if (m_tx_clock)
+ {
+ attotime tx_period = attotime::from_hz(m_tx_clock) * m_divide;
+ m_tx_timer->adjust(tx_period, 0, tx_period);
+ }
+ }
+ }
+ m_ctrl = data;
+}
+
+
+//-------------------------------------------------
+// check_interrupts
+//-------------------------------------------------
+
+void acia6850_device::check_interrupts()
+{
+ int irq = (m_tx_int && (m_status & ACIA6850_STATUS_TDRE) && (~m_status & ACIA6850_STATUS_CTS)) ||
+ ((m_ctrl & 0x80) && ((m_status & (ACIA6850_STATUS_RDRF|ACIA6850_STATUS_DCD)) || m_overrun));
+
+ if (irq != m_irq)
+ {
+ m_irq = irq;
+
+ if (irq)
+ {
+ m_status |= ACIA6850_STATUS_IRQ;
+ m_out_irq_func(0);
+ }
+ else
+ {
+ m_status &= ~ACIA6850_STATUS_IRQ;
+ m_out_irq_func(1);
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// data_write - Write transmit register
+//-------------------------------------------------
+
+WRITE8_MEMBER( acia6850_device::data_write )
+{
+ if (LOG) logerror("MC6850 '%s' Data: %02x\n", tag(), data);
+
+ if (!m_reset)
+ {
+ m_tdr = data;
+ m_status &= ~ACIA6850_STATUS_TDRE;
+ check_interrupts();
+ }
+ else
+ {
+ logerror("%s:ACIA %p: Data write while in reset!\n", machine().describe_context(), this);
+ }
+}
+
+
+//-------------------------------------------------
+// data_r - Read character
+//-------------------------------------------------
+
+READ8_MEMBER( acia6850_device::data_read )
+{
+ m_status &= ~(ACIA6850_STATUS_RDRF | ACIA6850_STATUS_IRQ | ACIA6850_STATUS_PE);
+
+ if (m_status_read)
+ {
+ int dcd = m_in_dcd_func();
+
+ m_status_read = 0;
+ m_status &= ~(ACIA6850_STATUS_OVRN | ACIA6850_STATUS_DCD);
+
+ if (dcd)
+ {
+ m_status |= ACIA6850_STATUS_DCD;
+ }
+ }
+
+ if (m_overrun == 1)
+ {
+ m_status |= ACIA6850_STATUS_OVRN;
+ m_overrun = 0;
+ }
+
+ check_interrupts();
+
+ return m_rdr;
+}
+
+
+//-------------------------------------------------
+// tx_tick - Transmit a bit
+//-------------------------------------------------
+
+void acia6850_device::tx_tick()
+{
+ switch (m_tx_state)
+ {
+ case START:
+ {
+ if (m_brk)
+ {
+ // transmit break
+
+ TXD(0);
+ }
+ else
+ {
+ int _cts = m_in_cts_func();
+
+ if (_cts)
+ {
+ m_status |= ACIA6850_STATUS_CTS;
+ }
+ else
+ {
+ m_status &= ~ACIA6850_STATUS_CTS;
+ }
+
+ check_interrupts();
+
+ if (m_status & ACIA6850_STATUS_TDRE)
+ {
+ // transmitter idle
+ TXD(1);
+ }
+ else
+ {
+ // transmit character
+
+ if (LOG) logerror("MC6850 '%s': TX DATA %x\n", tag(), m_tdr);
+ if (LOG) logerror("MC6850 '%s': TX START BIT\n", tag());
+
+ TXD(0);
+
+ m_tx_bits = m_bits;
+ m_tx_shift = m_tdr;
+ m_tx_parity = 0;
+ m_tx_state = DATA;
+ }
+ }
+ break;
+ }
+ case DATA:
+ {
+ int val = m_tx_shift & 1;
+ if (LOG) logerror("MC6850 '%s': TX DATA BIT %x\n", tag(), val);
+
+ TXD(val);
+ m_tx_parity ^= val;
+ m_tx_shift >>= 1;
+
+ if (--(m_tx_bits) == 0)
+ {
+ m_tx_state = (m_parity == NONE) ? STOP : PARITY;
+ }
+
+ break;
+ }
+ case PARITY:
+ {
+ int parity = 0;
+
+ if (m_parity == EVEN)
+ {
+ parity = (m_tx_parity & 1) ? 1 : 0;
+ }
+ else
+ {
+ parity = (m_tx_parity & 1) ? 0 : 1;
+ }
+
+ TXD(parity);
+
+ if (LOG) logerror("MC6850 '%s': TX PARITY BIT %x\n", tag(), parity);
+ m_tx_state = STOP;
+ break;
+ }
+ case STOP:
+ {
+ if (LOG) logerror("MC6850 '%s': TX STOP BIT\n", tag());
+ TXD(1);
+
+ if (m_stopbits == 1)
+ {
+ m_tx_state = START;
+ m_status |= ACIA6850_STATUS_TDRE;
+ }
+ else
+ {
+ m_tx_state = STOP2;
+ }
+ break;
+ }
+ case STOP2:
+ {
+ if (LOG) logerror("MC6850 '%s': TX STOP BIT\n", tag());
+ TXD(1);
+ m_tx_state = START;
+ m_status |= ACIA6850_STATUS_TDRE;
+ break;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// tx_clock_in - As above, but using the tx pin
+//-------------------------------------------------
+
+void acia6850_device::tx_clock_in()
+{
+ int _cts = m_in_cts_func();
+
+ if (_cts)
+ {
+ m_status |= ACIA6850_STATUS_CTS;
+ }
+ else
+ {
+ m_status &= ~ACIA6850_STATUS_CTS;
+ }
+
+ m_tx_counter ++;
+
+ if ( m_tx_counter > m_divide - 1)
+ {
+ tx_tick();
+ m_tx_counter = 0;
+ }
+
+}
+
+
+//-------------------------------------------------
+// rx_tick - Receive a bit
+//-------------------------------------------------
+
+void acia6850_device::rx_tick()
+{
+ int dcd = m_in_dcd_func();
+
+ if (dcd)
+ {
+ m_status |= ACIA6850_STATUS_DCD;
+ check_interrupts();
+ }
+ else if ((m_status & (ACIA6850_STATUS_DCD | ACIA6850_STATUS_IRQ)) == ACIA6850_STATUS_DCD)
+ {
+ m_status &= ~ACIA6850_STATUS_DCD;
+ }
+
+ if (m_status & ACIA6850_STATUS_DCD)
+ {
+ m_rx_state = START;
+ }
+ else
+ {
+ int rxd = m_in_rx_func();
+
+ switch (m_rx_state)
+ {
+ case START:
+ {
+ if (rxd == 0)
+ {
+ if (LOG) logerror("MC6850 '%s': RX START BIT\n", tag());
+ m_rx_shift = 0;
+ m_rx_parity = 0;
+ m_rx_bits = m_bits;
+ m_rx_state = DATA;
+ }
+ break;
+ }
+ case DATA:
+ {
+ if (LOG) logerror("MC6850 '%s': RX DATA BIT %x\n", tag(), rxd);
+ m_rx_shift |= rxd ? 0x80 : 0;
+ m_rx_parity ^= rxd;
+
+ if (--m_rx_bits == 0)
+ {
+ if (m_status & ACIA6850_STATUS_RDRF)
+ {
+ m_overrun = 1;
+ check_interrupts();
+ }
+
+ m_rx_state = m_parity == NONE ? STOP : PARITY;
+ }
+ else
+ {
+ m_rx_shift >>= 1;
+ }
+ break;
+ }
+ case PARITY:
+ {
+ if (LOG) logerror("MC6850 '%s': RX PARITY BIT %x\n", tag(), rxd);
+ m_rx_parity ^= rxd;
+
+ if (m_parity == EVEN)
+ {
+ if (m_rx_parity)
+ {
+ m_status |= ACIA6850_STATUS_PE;
+ }
+ }
+ else
+ {
+ if (!m_rx_parity)
+ {
+ m_status |= ACIA6850_STATUS_PE;
+ }
+ }
+
+ m_rx_state = STOP;
+ break;
+ }
+ case STOP:
+ {
+ if (rxd == 1)
+ {
+ if (LOG) logerror("MC6850 '%s': RX STOP BIT\n", tag());
+ if (m_stopbits == 1)
+ {
+ m_status &= ~ACIA6850_STATUS_FE;
+
+ if (!(m_status & ACIA6850_STATUS_RDRF))
+ {
+ if (LOG) logerror("MC6850 '%s': RX DATA %x\n", tag(), m_rx_shift);
+ m_rdr = m_rx_shift;
+ m_status |= ACIA6850_STATUS_RDRF;
+ check_interrupts();
+ }
+
+ m_rx_state = START;
+ }
+ else
+ {
+ m_rx_state = STOP2;
+ }
+ }
+ else
+ {
+ m_status |= ACIA6850_STATUS_FE;
+ m_rx_state = START;
+ }
+ break;
+ }
+ case STOP2:
+ {
+ if (rxd == 1)
+ {
+ if (LOG) logerror("MC6850 '%s': RX STOP BIT\n", tag());
+ m_status &= ~ACIA6850_STATUS_FE;
+
+ if (!(m_status & ACIA6850_STATUS_RDRF))
+ {
+ if (LOG) logerror("MC6850 '%s': RX DATA %x\n", tag(), m_rx_shift);
+ m_rdr = m_rx_shift;
+ m_status |= ACIA6850_STATUS_RDRF;
+ check_interrupts();
+ }
+
+ m_rx_state = START;
+ }
+ else
+ {
+ m_status |= ACIA6850_STATUS_FE;
+ m_rx_state = START;
+ }
+ break;
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// rx_clock_in - As above, but using the rx pin
+//-------------------------------------------------
+
+void acia6850_device::rx_clock_in()
+{
+ int dcd = m_in_dcd_func();
+
+ if (dcd)
+ {
+ m_status |= ACIA6850_STATUS_DCD;
+ check_interrupts();
+ }
+ else if ((m_status & (ACIA6850_STATUS_DCD|ACIA6850_STATUS_IRQ)) == ACIA6850_STATUS_DCD)
+ {
+ m_status &= ~ACIA6850_STATUS_DCD;
+ }
+
+ m_rx_counter ++;
+
+ if ( m_rx_counter > m_divide - 1)
+ {
+ rx_tick();
+ m_rx_counter = 0;
+ }
+}
+
+
+//-------------------------------------------------
+// set_rx_clock - set receiver clock
+//-------------------------------------------------
+
+void acia6850_device::set_rx_clock(int clock)
+{
+ m_rx_clock = clock;
+
+ if (m_rx_clock)
+ {
+ attotime rx_period = attotime::from_hz(m_rx_clock) * m_divide;
+ m_rx_timer->adjust(rx_period, 0, rx_period);
+ }
+}
+
+
+//-------------------------------------------------
+// set_tx_clock - set receiver clock
+//-------------------------------------------------
+
+void acia6850_device::set_tx_clock(int clock)
+{
+ m_tx_clock = clock;
+
+ if (m_tx_clock)
+ {
+ attotime tx_period = attotime::from_hz(m_tx_clock) * m_divide;
+ m_tx_timer->adjust(tx_period, 0, tx_period);
+ }
+}
+
+
+//-------------------------------------------------
+// receive_data - receive data byte
+//-------------------------------------------------
+
+void acia6850_device::receive_data(UINT8 data)
+{
+ m_rdr = data;
+ m_status |= ACIA6850_STATUS_RDRF;
+ check_interrupts();
+}
diff --git a/trunk/src/emu/machine/6850acia.h b/trunk/src/emu/machine/6850acia.h
new file mode 100644
index 00000000000..33e7e5325bb
--- /dev/null
+++ b/trunk/src/emu/machine/6850acia.h
@@ -0,0 +1,187 @@
+/*********************************************************************
+
+ 6850acia.h
+
+ 6850 ACIA code
+
+*********************************************************************/
+
+#pragma once
+
+#ifndef __ACIA6850_H__
+#define __ACIA6850_H__
+
+#include "emu.h"
+
+
+
+/***************************************************************************
+ EXTERNAL MACROS
+***************************************************************************/
+
+#define ACIA6850_STATUS_RDRF 0x01
+#define ACIA6850_STATUS_TDRE 0x02
+#define ACIA6850_STATUS_DCD 0x04
+#define ACIA6850_STATUS_CTS 0x08
+#define ACIA6850_STATUS_FE 0x10
+#define ACIA6850_STATUS_OVRN 0x20
+#define ACIA6850_STATUS_PE 0x40
+#define ACIA6850_STATUS_IRQ 0x80
+
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_ACIA6850_ADD(_tag, _interface) \
+ MCFG_DEVICE_ADD(_tag, ACIA6850, 0) \
+ acia6850_device::static_set_interface(*device, _interface);
+
+#define ACIA6850_INTERFACE(_name) \
+ const acia6850_interface(_name) =
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+
+// ======================> acia6850_interface
+
+struct acia6850_interface
+{
+ int m_tx_clock;
+ int m_rx_clock;
+
+ devcb_read_line m_in_rx_cb;
+ devcb_write_line m_out_tx_cb;
+
+ devcb_read_line m_in_cts_cb;
+ devcb_write_line m_out_rts_cb;
+ devcb_read_line m_in_dcd_cb;
+
+ devcb_write_line m_out_irq_cb;
+};
+
+
+
+// ======================> acia6850_device
+
+class acia6850_device : public device_t,
+ public acia6850_interface
+{
+public:
+ // construction/destruction
+ acia6850_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // static configuration helpers
+ static void static_set_interface(device_t &device, const acia6850_interface &interface);
+
+ DECLARE_WRITE8_MEMBER( control_write );
+ DECLARE_READ8_MEMBER( status_read );
+ DECLARE_WRITE8_MEMBER( data_write );
+ DECLARE_READ8_MEMBER( data_read );
+
+ void tx_clock_in();
+ void rx_clock_in();
+
+ void set_rx_clock(int clock);
+ void set_tx_clock(int clock);
+
+ void receive_data(UINT8 data);
+
+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);
+
+private:
+ enum
+ {
+ TIMER_ID_TRANSMIT,
+ TIMER_ID_RECEIVE
+ };
+
+ void check_interrupts();
+
+ void tx_tick();
+ void transmit_event();
+
+ void rx_tick();
+ void receive_event();
+
+ enum serial_state
+ {
+ START,
+ DATA,
+ PARITY,
+ STOP,
+ STOP2,
+ };
+
+ enum parity_type
+ {
+ NONE,
+ ODD,
+ EVEN
+ };
+
+ devcb_resolved_read_line m_in_rx_func;
+ devcb_resolved_write_line m_out_tx_func;
+ devcb_resolved_read_line m_in_cts_func;
+ devcb_resolved_write_line m_out_rts_func;
+ devcb_resolved_read_line m_in_dcd_func;
+ devcb_resolved_write_line m_out_irq_func;
+
+ UINT8 m_ctrl;
+ UINT8 m_status;
+
+ UINT8 m_tdr;
+ UINT8 m_rdr;
+ UINT8 m_rx_shift;
+ UINT8 m_tx_shift;
+
+ UINT8 m_rx_counter;
+ UINT8 m_tx_counter;
+
+ int m_divide;
+
+ // Counters
+ int m_tx_bits;
+ int m_rx_bits;
+ int m_tx_parity;
+ int m_rx_parity;
+
+ // TX/RX state
+ int m_bits;
+ parity_type m_parity;
+ int m_stopbits;
+ int m_tx_int;
+
+ // Signals
+ int m_overrun;
+ int m_reset;
+ int m_rts;
+ int m_brk;
+ int m_first_reset;
+ int m_status_read;
+ serial_state m_rx_state;
+ serial_state m_tx_state;
+ int m_irq;
+
+ emu_timer *m_rx_timer;
+ emu_timer *m_tx_timer;
+
+ static const int ACIA6850_DIVIDE[3];
+ static const int ACIA6850_WORD[8][3];
+};
+
+
+// device type definition
+extern const device_type ACIA6850;
+
+
+
+#endif /* __ACIA6850_H__ */
diff --git a/trunk/src/emu/machine/68681.c b/trunk/src/emu/machine/68681.c
new file mode 100644
index 00000000000..fca5530bca8
--- /dev/null
+++ b/trunk/src/emu/machine/68681.c
@@ -0,0 +1,816 @@
+/*
+ 68681 DUART
+
+ Written by Mariusz Wojcieszek
+ Updated by Jonathan Gevaryahu AKA Lord Nightmare
+*/
+
+#include "emu.h"
+#include "68681.h"
+
+#define VERBOSE 0
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+static const char *const duart68681_reg_read_names[0x10] =
+{
+ "MRA", "SRA", "BRG Test", "RHRA", "IPCR", "ISR", "CTU", "CTL", "MRB", "SRB", "1X/16X Test", "RHRB", "IVR", "Input Ports", "Start Counter", "Stop Counter"
+};
+
+static const char *const duart68681_reg_write_names[0x10] =
+{
+ "MRA", "CSRA", "CRA", "THRA", "ACR", "IMR", "CRUR", "CTLR", "MRB", "CSRB", "CRB", "THRB", "IVR", "OPCR", "Set OP Bits", "Reset OP Bits"
+};
+
+#define INT_INPUT_PORT_CHANGE 0x80
+#define INT_DELTA_BREAK_B 0x40
+#define INT_RXRDY_FFULLB 0x20
+#define INT_TXRDYB 0x10
+#define INT_COUNTER_READY 0x08
+#define INT_DELTA_BREAK_A 0x04
+#define INT_RXRDY_FFULLA 0x02
+#define INT_TXRDYA 0x01
+
+#define STATUS_RECEIVED_BREAK 0x80
+#define STATUS_FRAMING_ERROR 0x40
+#define STATUS_PARITY_ERROR 0x20
+#define STATUS_OVERRUN_ERROR 0x10
+#define STATUS_TRANSMITTER_EMPTY 0x08
+#define STATUS_TRANSMITTER_READY 0x04
+#define STATUS_FIFO_FULL 0x02
+#define STATUS_RECEIVER_READY 0x01
+
+#define MODE_RX_INT_SELECT_BIT 0x40
+
+#define RX_FIFO_SIZE 3
+
+typedef struct
+{
+ /* Registers */
+ UINT8 CR; /* Command register */
+ UINT8 CSR; /* Clock select register */
+ UINT8 MR1; /* Mode register 1 */
+ UINT8 MR2; /* Mode register 2 */
+ UINT8 MR_ptr; /* Mode register pointer */
+ UINT8 SR; /* Status register */
+
+ /* State */
+ int baud_rate;
+
+ /* Receiver */
+ UINT8 rx_enabled;
+ UINT8 rx_fifo[RX_FIFO_SIZE];
+ int rx_fifo_read_ptr;
+ int rx_fifo_write_ptr;
+ int rx_fifo_num;
+
+ /* Transmitter */
+ UINT8 tx_enabled;
+ UINT8 tx_data;
+ UINT8 tx_ready;
+ emu_timer *tx_timer;
+
+} DUART68681_CHANNEL;
+
+typedef struct
+{
+ /* device */
+ device_t *device;
+
+ /* config */
+ const duart68681_config *duart_config;
+
+ /* registers */
+ UINT8 ACR; /* Auxiliary Control Register */
+ UINT8 IMR; /* Interrupt Mask Register */
+ UINT8 ISR; /* Interrupt Status Register */
+ UINT8 IVR; /* Interrupt Vector Register */
+ UINT8 OPCR; /* Output Port Conf. Register */
+ UINT8 OPR; /* Output Port Register */
+ PAIR CTR; /* Counter/Timer Preset Value */
+
+ /* state */
+ UINT8 IP_last_state; /* last state of IP bits */
+
+ /* timer */
+ emu_timer *duart_timer;
+
+ /* UART channels */
+ DUART68681_CHANNEL channel[2];
+
+} duart68681_state;
+
+INLINE duart68681_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == DUART68681);
+
+ return (duart68681_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+static void duart68681_update_interrupts(duart68681_state *duart68681)
+{
+ /* update SR state and update interrupt ISR state for the following bits:
+ SRn: bits 7-4: handled elsewhere.
+ SRn: bit 3 (TxEMTn) (we can assume since we're not actually emulating the delay/timing of sending bits, that as long as TxRDYn is set, TxEMTn is also set since the transmit byte has 'already happened', therefore TxEMTn is always 1 assuming tx is enabled on channel n and the MSR2n mode is 0 or 2; in mode 1 it is explicitly zeroed, and mode 3 is undefined)
+ SRn: bit 2 (TxRDYn) (we COULD assume since we're not emulating delay and timing output, that as long as tx is enabled on channel n, TxRDY is 1 for channel n and the MSR2n mode is 0 or 2; in mode 1 it is explicitly zeroed, and mode 3 is undefined; however, tx_ready is already nicely handled for us elsewhere, so we can use that instead for now, though we may need to retool that code as well)
+ SRn: bit 1 (FFULLn) (this bit we actually emulate; if the receive fifo for channel n is full, this bit is 1, otherwise it is 0. the receive fifo should be three words long.)
+ SRn: bit 0 (RxRDYn) (this bit we also emulate; the bit is always asserted if the receive fifo is not empty)
+ ISR: bit 7: Input Port change; this should be handled elsewhere, on the input port handler
+ ISR: bit 6: Delta Break B; this should be handled elsewhere, on the data receive handler
+ ISR: bit 5: RxRDYB/FFULLB: this is handled here; depending on whether MSR1B bit 6 is 0 or 1, this bit holds the state of SRB bit 0 or bit 1 respectively
+ ISR: bit 4: TxRDYB: this is handled here; it mirrors SRB bit 2
+ ISR: bit 3: Counter ready; this should be handled by the timer generator
+ ISR: bit 2: Delta Break A; this should be handled elsewhere, on the data receive handler
+ ISR: bit 1: RxRDYA/FFULLA: this is handled here; depending on whether MSR1A bit 6 is 0 or 1, this bit holds the state of SRA bit 0 or bit 1 respectively
+ ISR: bit 0: TxRDYA: this is handled here; it mirrors SRA bit 2
+ */
+ UINT8 ch = 0;
+ //logerror("DEBUG: 68681 int check: upon func call, SRA is %02X, SRB is %02X, ISR is %02X\n", duart68681->channel[0].SR, duart68681->channel[1].SR, duart68681->ISR);
+ for (ch = 0; ch < 2; ch++)
+ {
+ //if ( duart68681->channel[ch].rx_enabled )
+ //{
+ if ( duart68681->channel[ch].rx_fifo_num > 0 )
+ {
+ duart68681->channel[ch].SR |= STATUS_RECEIVER_READY;
+ }
+ else
+ {
+ duart68681->channel[ch].SR &= ~STATUS_RECEIVER_READY;
+ }
+ if ( duart68681->channel[ch].rx_fifo_num == RX_FIFO_SIZE )
+ {
+ duart68681->channel[ch].SR |= STATUS_FIFO_FULL;
+ }
+ else
+ {
+ duart68681->channel[ch].SR &= ~STATUS_FIFO_FULL;
+ }
+ //}
+ //else
+ //{
+ //duart68681->channel[ch].SR &= ~STATUS_RECEIVER_READY;
+ //duart68681->channel[ch].SR &= ~STATUS_FIFO_FULL;
+ //}
+ // Handle the TxEMT and TxRDY bits based on mode
+ switch( duart68681->channel[ch].MR2&0xC0) // what mode are we in?
+ {
+ case 0x00: // normal mode
+ if ( duart68681->channel[ch].tx_enabled )
+ {
+ duart68681->channel[ch].SR |= STATUS_TRANSMITTER_EMPTY;
+ }
+ else
+ {
+ duart68681->channel[ch].SR &= ~STATUS_TRANSMITTER_EMPTY;
+ }
+ break;
+ case 0x40: // automatic echo mode
+ duart68681->channel[ch].SR &= ~STATUS_TRANSMITTER_EMPTY;
+ duart68681->channel[ch].SR &= ~STATUS_TRANSMITTER_READY;
+ break;
+ case 0x80: // local loopback mode
+ if ( duart68681->channel[ch].tx_enabled )
+ {
+ duart68681->channel[ch].SR |= STATUS_TRANSMITTER_EMPTY;
+ }
+ else
+ {
+ duart68681->channel[ch].SR &= ~STATUS_TRANSMITTER_EMPTY;
+ }
+ break;
+ case 0xC0: // remote loopback mode
+ // write me, what the txrdy/txemt regs do for remote loopback mode is undocumented afaik, for now just clear both
+ duart68681->channel[ch].SR &= ~STATUS_TRANSMITTER_EMPTY;
+ duart68681->channel[ch].SR &= ~STATUS_TRANSMITTER_READY;
+ break;
+ }
+ // now handle the ISR bits
+ if ( duart68681->channel[ch].SR & STATUS_TRANSMITTER_READY )
+ {
+ if (ch == 0)
+ duart68681->ISR |= INT_TXRDYA;
+ else
+ duart68681->ISR |= INT_TXRDYB;
+ }
+ else
+ {
+ if (ch == 0)
+ duart68681->ISR &= ~INT_TXRDYA;
+ else
+ duart68681->ISR &= ~INT_TXRDYB;
+ }
+ //logerror("DEBUG: 68681 int check: before receiver test, SR%c is %02X, ISR is %02X\n", (ch+0x41), duart68681->channel[ch].SR, duart68681->ISR);
+ if ( duart68681->channel[ch].MR1 & MODE_RX_INT_SELECT_BIT )
+ {
+ if ( duart68681->channel[ch].SR & STATUS_FIFO_FULL )
+ {
+ duart68681->ISR |= ((ch == 0) ? INT_RXRDY_FFULLA : INT_RXRDY_FFULLB);
+ }
+ else
+ {
+ duart68681->ISR &= ((ch == 0) ? ~INT_RXRDY_FFULLA : ~INT_RXRDY_FFULLB);
+ }
+ }
+ else
+ {
+ if ( duart68681->channel[ch].SR & STATUS_RECEIVER_READY )
+ {
+ duart68681->ISR |= ((ch == 0) ? INT_RXRDY_FFULLA : INT_RXRDY_FFULLB);
+ }
+ else
+ {
+ duart68681->ISR &= ((ch == 0) ? ~INT_RXRDY_FFULLA : ~INT_RXRDY_FFULLB);
+ }
+ }
+ //logerror("DEBUG: 68681 int check: after receiver test, SR%c is %02X, ISR is %02X\n", (ch+0x41), duart68681->channel[ch].SR, duart68681->ISR);
+ }
+ if ( (duart68681->ISR & duart68681->IMR) != 0 )
+ {
+ if ( duart68681->duart_config->irq_handler )
+ {
+ LOG(( "68681: Interrupt line active (IMR & ISR = %02X)\n", (duart68681->ISR & duart68681->IMR) ));
+ duart68681->duart_config->irq_handler( duart68681->device, duart68681->IVR );
+ }
+ }
+};
+
+static TIMER_CALLBACK( duart_timer_callback )
+{
+ device_t *device = (device_t *)ptr;
+ duart68681_state *duart68681 = get_safe_token(device);
+
+ duart68681->ISR |= INT_COUNTER_READY;
+ duart68681_update_interrupts(duart68681);
+
+// if ((duart68681->OPCR & 0x0c)== 0x04) {
+// duart68681->OPR ^= 0x08;
+// if (duart68681->duart_config->output_port_write)
+// duart68681->duart_config->output_port_write(duart68681->device, duart68681->OPR ^ 0xff);
+//
+// }
+};
+
+static void duart68681_write_MR(duart68681_state *duart68681, int ch, UINT8 data)
+{
+ if ( duart68681->channel[ch].MR_ptr == 0 )
+ {
+ duart68681->channel[ch].MR1 = data;
+ duart68681->channel[ch].MR_ptr = 1;
+ }
+ else
+ {
+ duart68681->channel[ch].MR2 = data;
+ }
+ duart68681_update_interrupts(duart68681);
+};
+
+static void duart68681_write_CSR(duart68681_state *duart68681, int ch, UINT8 data, UINT8 ACR)
+{
+ static const int baud_rate_ACR_0[] = { 50, 110, 134, 200, 300, 600, 1200, 1050, 2400, 4800, 7200, 9600, 38400, 0, 0, 0 };
+ static const int baud_rate_ACR_1[] = { 75, 110, 134, 150, 300, 600, 1200, 2000, 2400, 4800, 1800, 9600, 19200, 0, 0, 0 };
+
+ duart68681->channel[ch].CSR = data;
+
+ if ( BIT(ACR,7) == 0 )
+ {
+ duart68681->channel[ch].baud_rate = baud_rate_ACR_0[data & 0x0f];
+
+ if (ch == 0)
+ {
+ if ((data & 0xf) == 0xe)
+ {
+ duart68681->channel[ch].baud_rate = duart68681->duart_config->ip3clk/16;
+ }
+ else if ((data & 0xf) == 0xf)
+ {
+ duart68681->channel[ch].baud_rate = duart68681->duart_config->ip3clk;
+ }
+ }
+ else if (ch == 1)
+ {
+ if ((data & 0xf) == 0xe)
+ {
+ duart68681->channel[ch].baud_rate = duart68681->duart_config->ip5clk/16;
+ }
+ else if ((data & 0xf) == 0xf)
+ {
+ duart68681->channel[ch].baud_rate = duart68681->duart_config->ip5clk;
+ }
+ }
+ }
+ else
+ {
+ duart68681->channel[ch].baud_rate = baud_rate_ACR_1[data & 0x0f];
+ }
+ if ( duart68681->channel[ch].baud_rate == 0 )
+ {
+ LOG(( "Unsupported transmitter clock: channel %d, clock select = %02x\n", ch, data ));
+ }
+};
+
+static void duart68681_write_CR(duart68681_state *duart68681, int ch, UINT8 data)
+{
+ duart68681->channel[ch].CR = data;
+
+ switch( (data >> 4) & 0x07 )
+ {
+ case 0: /* No command */
+ break;
+ case 1: /* Reset MR pointer. Causes the Channel A MR pointer to point to MR1 */
+ duart68681->channel[ch].MR_ptr = 0;
+ break;
+ case 2: /* Reset channel A receiver (disable receiver and flush fifo) */
+ duart68681->channel[ch].rx_enabled = 0;
+ duart68681->channel[ch].SR &= ~STATUS_RECEIVER_READY;
+ duart68681->channel[ch].SR &= ~STATUS_OVERRUN_ERROR; // is this correct?
+ duart68681->channel[ch].rx_fifo_read_ptr = 0;
+ duart68681->channel[ch].rx_fifo_write_ptr = 0;
+ duart68681->channel[ch].rx_fifo_num = 0;
+ break;
+ case 3: /* Reset channel A transmitter */
+ duart68681->channel[ch].tx_enabled = 0;
+ duart68681->channel[ch].SR &= ~STATUS_TRANSMITTER_READY;
+ if (ch == 0)
+ duart68681->ISR &= ~INT_TXRDYA;
+ else
+ duart68681->ISR &= ~INT_TXRDYB;
+ duart68681->channel[ch].tx_timer->adjust(attotime::never, ch);
+ break;
+ case 4: /* Reset Error Status */
+ duart68681->channel[ch].SR &= ~(STATUS_RECEIVED_BREAK | STATUS_FRAMING_ERROR | STATUS_PARITY_ERROR | STATUS_OVERRUN_ERROR);
+ break;
+ case 5: /* Reset Channel break change interrupt */
+ if ( ch == 0 )
+ {
+ duart68681->ISR &= ~INT_DELTA_BREAK_A;
+ }
+ else
+ {
+ duart68681->ISR &= ~INT_DELTA_BREAK_B;
+ }
+ break;
+ /* TODO: case 6 and case 7 are start break and stop break respectively, which start or stop holding the TxDA or TxDB line low (space) after whatever data is in the buffer finishes transmitting (following the stop bit?), or after two bit-times if no data is being transmitted */
+ default:
+ LOG(( "68681: Unhandled command (%x) in CR%d\n", (data >> 4) & 0x07, ch ));
+ break;
+ }
+ duart68681_update_interrupts(duart68681);
+
+ if (BIT(data, 0)) {
+ duart68681->channel[ch].rx_enabled = 1;
+ }
+ if (BIT(data, 1)) {
+ duart68681->channel[ch].rx_enabled = 0;
+ duart68681->channel[ch].SR &= ~STATUS_RECEIVER_READY;
+ }
+
+ if (BIT(data, 2)) {
+ duart68681->channel[ch].tx_enabled = 1;
+ duart68681->channel[ch].tx_ready = 1;
+ duart68681->channel[ch].SR |= STATUS_TRANSMITTER_READY;
+ if (ch == 0)
+ duart68681->ISR |= INT_TXRDYA;
+ else
+ duart68681->ISR |= INT_TXRDYB;
+ }
+ if (BIT(data, 3)) {
+ duart68681->channel[ch].tx_enabled = 0;
+ duart68681->channel[ch].tx_ready = 0;
+ duart68681->channel[ch].SR &= ~STATUS_TRANSMITTER_READY;
+ if (ch == 0)
+ duart68681->ISR &= ~INT_TXRDYA;
+ else
+ duart68681->ISR &= ~INT_TXRDYB;
+ }
+
+};
+
+static UINT8 duart68681_read_rx_fifo(duart68681_state *duart68681, int ch)
+{
+ UINT8 r;
+
+ if ( duart68681->channel[ch].rx_fifo_num == 0 )
+ {
+ LOG(( "68681: rx fifo underflow\n" ));
+ return 0x0;
+ }
+
+ r = duart68681->channel[ch].rx_fifo[duart68681->channel[ch].rx_fifo_read_ptr++];
+ if ( duart68681->channel[ch].rx_fifo_read_ptr == RX_FIFO_SIZE )
+ {
+ duart68681->channel[ch].rx_fifo_read_ptr = 0;
+ }
+
+ duart68681->channel[ch].rx_fifo_num--;
+ duart68681_update_interrupts(duart68681);
+
+ return r;
+};
+
+static TIMER_CALLBACK( tx_timer_callback )
+{
+ device_t *device = (device_t *)ptr;
+ duart68681_state *duart68681 = get_safe_token(device);
+ int ch = param & 1;
+
+ // send the byte unless we're in loopback mode;
+ // in loopback mode do NOT 'actually' send the byte: the TXn pin is held high when loopback mode is on.
+ if ((duart68681->duart_config->tx_callback) && ((duart68681->channel[ch].MR2&0xC0) != 0x80))
+ duart68681->duart_config->tx_callback(device, ch, duart68681->channel[ch].tx_data);
+
+ // if local loopback is on, write the transmitted data as if a byte had been received
+ if ((duart68681->channel[ch].MR2 & 0xC0) == 0x80)
+ {
+ if (duart68681->channel[ch].rx_fifo_num >= RX_FIFO_SIZE)
+ {
+ LOG(( "68681: FIFO overflow\n" ));
+ duart68681->channel[ch].SR |= STATUS_OVERRUN_ERROR;
+ }
+ else
+ {
+ duart68681->channel[ch].rx_fifo[duart68681->channel[ch].rx_fifo_write_ptr++]
+ = duart68681->channel[ch].tx_data;
+ if (duart68681->channel[ch].rx_fifo_write_ptr == RX_FIFO_SIZE)
+ {
+ duart68681->channel[ch].rx_fifo_write_ptr = 0;
+ }
+ duart68681->channel[ch].rx_fifo_num++;
+ }
+ }
+
+ duart68681->channel[ch].tx_ready = 1;
+ duart68681->channel[ch].SR |= STATUS_TRANSMITTER_READY;
+
+ if (ch == 0)
+ duart68681->ISR |= INT_TXRDYA;
+ else
+ duart68681->ISR |= INT_TXRDYB;
+
+ duart68681_update_interrupts(duart68681);
+ duart68681->channel[ch].tx_timer->adjust(attotime::never, ch);
+};
+
+static void duart68681_write_TX(duart68681_state* duart68681, int ch, UINT8 data)
+{
+ attotime period;
+
+ duart68681->channel[ch].tx_data = data;
+
+ duart68681->channel[ch].tx_ready = 0;
+ duart68681->channel[ch].SR &= ~STATUS_TRANSMITTER_READY;
+
+ if (ch == 0)
+ duart68681->ISR &= ~INT_TXRDYA;
+ else
+ duart68681->ISR &= ~INT_TXRDYB;
+
+ duart68681_update_interrupts(duart68681);
+
+ period = attotime::from_hz(duart68681->channel[ch].baud_rate / 10 );
+ duart68681->channel[ch].tx_timer->adjust(period, ch);
+
+};
+
+READ8_DEVICE_HANDLER(duart68681_r)
+{
+ duart68681_state* duart68681 = get_safe_token(device);
+ UINT8 r = 0xff;
+
+ offset &= 0xf;
+
+ LOG(( "Reading 68681 (%s) reg %x (%s) ", device->tag(), offset, duart68681_reg_read_names[offset] ));
+
+ switch (offset)
+ {
+ case 0x00: /* MR1A/MR2A */
+ if ( duart68681->channel[0].MR_ptr == 0 )
+ {
+ r = duart68681->channel[0].MR1;
+ duart68681->channel[0].MR_ptr = 1;
+ }
+ else
+ {
+ r = duart68681->channel[0].MR2;
+ }
+ break;
+ case 0x01: /* SRA */
+ r = duart68681->channel[0].SR;
+ break;
+ case 0x03: /* Rx Holding Register A */
+ r = duart68681_read_rx_fifo(duart68681, 0);
+ break;
+ case 0x04: /* IPCR */
+ {
+ UINT8 IP;
+ if ( duart68681->duart_config->input_port_read != NULL )
+ IP = duart68681->duart_config->input_port_read(duart68681->device);
+ else
+ IP = 0x0;
+
+ r = (((duart68681->IP_last_state ^ IP) & 0x0f) << 4) | (IP & 0x0f);
+ duart68681->IP_last_state = IP;
+ duart68681->ISR &= ~INT_INPUT_PORT_CHANGE;
+ duart68681_update_interrupts(duart68681);
+ }
+ break;
+ case 0x05: /* ISR */
+ r = duart68681->ISR;
+ break;
+ case 0x08: /* MR1B/MR2B */
+ if ( duart68681->channel[1].MR_ptr == 0 )
+ {
+ r = duart68681->channel[1].MR1;
+ duart68681->channel[1].MR_ptr = 1;
+ }
+ else
+ {
+ r = duart68681->channel[1].MR2;
+ }
+ break;
+ case 0x09: /* SRB */
+ r = duart68681->channel[1].SR;
+ break;
+ case 0x0b: /* RHRB */
+ r = duart68681_read_rx_fifo(duart68681, 1);
+ break;
+ case 0x0d: /* IP */
+ if ( duart68681->duart_config->input_port_read != NULL )
+ r = duart68681->duart_config->input_port_read(duart68681->device);
+ else
+ {
+ r = 0xff;
+#if 0
+ if (device->machine().input().code_pressed(KEYCODE_1)) r ^= 0x0001;
+ if (device->machine().input().code_pressed(KEYCODE_2)) r ^= 0x0002;
+ if (device->machine().input().code_pressed(KEYCODE_3)) r ^= 0x0004;
+ if (device->machine().input().code_pressed(KEYCODE_4)) r ^= 0x0008;
+ if (device->machine().input().code_pressed(KEYCODE_5)) r ^= 0x0010;
+ if (device->machine().input().code_pressed(KEYCODE_6)) r ^= 0x0020;
+ if (device->machine().input().code_pressed(KEYCODE_7)) r ^= 0x0040;
+ if (device->machine().input().code_pressed(KEYCODE_8)) r ^= 0x0080;
+#endif
+ }
+ break;
+ case 0x0e: /* Start counter command */
+ switch( (duart68681->ACR >> 4) & 0x07 )
+ {
+ /* TODO: implement modes 0,1,2,4,5 */
+ case 0x03: /* Counter, CLK/16 */
+ {
+ attotime rate = attotime::from_hz(2*device->clock()/(2*16*16*duart68681->CTR.w.l));
+ duart68681->duart_timer->adjust(rate, 0, rate);
+ }
+ break;
+ case 0x06: /* Timer, CLK/1 */
+ {
+ attotime rate = attotime::from_hz(2*device->clock()/(2*16*duart68681->CTR.w.l));
+ duart68681->duart_timer->adjust(rate, 0, rate);
+ }
+ break;
+ case 0x07: /* Timer, CLK/16 */
+ {
+ //double hz;
+ //attotime rate = attotime::from_hz(duart68681->clock) * (16*duart68681->CTR.w.l);
+ attotime rate = attotime::from_hz(2*device->clock()/(2*16*16*duart68681->CTR.w.l));
+ //hz = ATTOSECONDS_TO_HZ(rate.attoseconds);
+ duart68681->duart_timer->adjust(rate, 0, rate);
+ }
+ break;
+ }
+ break;
+ case 0x0f: /* Stop counter command */
+ duart68681->ISR &= ~INT_COUNTER_READY;
+ if (((duart68681->ACR >>4)& 0x07) < 4) // if in counter mode...
+ duart68681->duart_timer->adjust(attotime::never); // shut down timer
+ duart68681_update_interrupts(duart68681);
+ break;
+ default:
+ LOG(( "Reading unhandled 68681 reg %x\n", offset ));
+ break;
+ }
+ LOG(("returned %02x\n", r));
+
+ return r;
+}
+
+WRITE8_DEVICE_HANDLER(duart68681_w)
+{
+ duart68681_state* duart68681 = get_safe_token(device);
+
+ offset &= 0x0f;
+ LOG(( "Writing 68681 (%s) reg %x (%s) with %04x\n", device->tag(), offset, duart68681_reg_write_names[offset], data ));
+
+ switch(offset)
+ {
+ case 0x00: /* MRA */
+ duart68681_write_MR(duart68681, 0, data);
+ break;
+ case 0x01: /* CSRA */
+ duart68681_write_CSR(duart68681, 0, data, duart68681->ACR);
+ break;
+ case 0x02: /* CRA */
+ duart68681_write_CR(duart68681, 0, data);
+ break;
+ case 0x03: /* THRA */
+ duart68681_write_TX(duart68681, 0, data);
+ break;
+ case 0x04: /* ACR */
+ duart68681->ACR = data;
+ // bits 6-4: Counter/Timer Mode And Clock Source Select
+ // bits 3-0: IP3-0 Change-Of-State Interrupt Enable
+ switch ((data >> 4) & 0x07)
+ {
+ case 0: case 1: case 2: case 4: case 5: // TODO: handle these cases!
+ logerror( "68681 (%s): Unhandled timer/counter mode %d\n", device->tag(), (data >> 4) & 0x07);
+ break;
+ case 3: case 6: case 7:
+ break;
+ }
+ duart68681_write_CSR(duart68681, 0, duart68681->channel[0].CSR, data);
+ duart68681_write_CSR(duart68681, 1, duart68681->channel[1].CSR, data);
+ duart68681_update_interrupts(duart68681); // need to add ACR checking for IP delta ints
+ break;
+ case 0x05: /* IMR */
+ duart68681->IMR = data;
+ duart68681_update_interrupts(duart68681);
+ break;
+ case 0x06: /* CTUR */
+ duart68681->CTR.b.h = data;
+ break;
+ case 0x07: /* CTLR */
+ duart68681->CTR.b.l = data;
+ break;
+ case 0x08: /* MRB */
+ duart68681_write_MR(duart68681, 1, data);
+ break;
+ case 0x09: /* CSRB */
+ duart68681_write_CSR(duart68681, 1, data, duart68681->ACR);
+ break;
+ case 0x0a: /* CRB */
+ duart68681_write_CR(duart68681, 1, data);
+ break;
+ case 0x0b: /* THRB */
+ duart68681_write_TX(duart68681, 1, data);
+ break;
+ case 0x0c: /* IVR */
+ duart68681->IVR = data;
+ break;
+ case 0x0d: /* OPCR */
+ if (data != 0x00)
+ logerror( "68681 (%s): Unhandled OPCR value: %02x\n", device->tag(), data);
+ duart68681->OPCR = data;
+ break;
+ case 0x0e: /* Set Output Port Bits */
+ duart68681->OPR |= data;
+ if (duart68681->duart_config->output_port_write)
+ duart68681->duart_config->output_port_write(duart68681->device, duart68681->OPR ^ 0xff);
+ break;
+ case 0x0f: /* Reset Output Port Bits */
+ duart68681->OPR &= ~data;
+ if (duart68681->duart_config->output_port_write)
+ duart68681->duart_config->output_port_write(duart68681->device, duart68681->OPR ^ 0xff);
+ break;
+ }
+}
+
+void duart68681_rx_data( device_t* device, int ch, UINT8 data )
+{
+ duart68681_state *duart68681 = get_safe_token(device);
+
+ if ( duart68681->channel[ch].rx_enabled )
+ {
+ if ( duart68681->channel[ch].rx_fifo_num >= RX_FIFO_SIZE )
+ {
+ LOG(( "68681: FIFO overflow\n" ));
+ duart68681->channel[ch].SR |= STATUS_OVERRUN_ERROR;
+ return;
+ }
+ duart68681->channel[ch].rx_fifo[duart68681->channel[ch].rx_fifo_write_ptr++] = data;
+ if ( duart68681->channel[ch].rx_fifo_write_ptr == RX_FIFO_SIZE )
+ {
+ duart68681->channel[ch].rx_fifo_write_ptr = 0;
+ }
+ duart68681->channel[ch].rx_fifo_num++;
+ duart68681_update_interrupts(duart68681);
+ }
+};
+
+/*-------------------------------------------------
+ device start callback
+-------------------------------------------------*/
+
+static DEVICE_START(duart68681)
+{
+ duart68681_state *duart68681 = get_safe_token(device);
+
+ /* validate arguments */
+ assert(device != NULL);
+
+ duart68681->duart_config = (const duart68681_config *)device->static_config();
+ duart68681->device = device;
+
+ duart68681->channel[0].tx_timer = device->machine().scheduler().timer_alloc(FUNC(tx_timer_callback), (void*)device);
+ duart68681->channel[1].tx_timer = device->machine().scheduler().timer_alloc(FUNC(tx_timer_callback), (void*)device);
+ duart68681->duart_timer = device->machine().scheduler().timer_alloc(FUNC(duart_timer_callback), (void*)device);
+
+ device->save_item(NAME(duart68681->ACR));
+ device->save_item(NAME(duart68681->IMR));
+ device->save_item(NAME(duart68681->ISR));
+ device->save_item(NAME(duart68681->IVR));
+ device->save_item(NAME(duart68681->OPCR));
+ device->save_item(NAME(duart68681->CTR));
+ device->save_item(NAME(duart68681->IP_last_state));
+
+ device->save_item(NAME(duart68681->channel[0].CR));
+ device->save_item(NAME(duart68681->channel[0].CSR));
+ device->save_item(NAME(duart68681->channel[0].MR1));
+ device->save_item(NAME(duart68681->channel[0].MR2));
+ device->save_item(NAME(duart68681->channel[0].MR_ptr));
+ device->save_item(NAME(duart68681->channel[0].SR));
+ device->save_item(NAME(duart68681->channel[0].baud_rate));
+ device->save_item(NAME(duart68681->channel[0].rx_enabled));
+ device->save_item(NAME(duart68681->channel[0].rx_fifo));
+ device->save_item(NAME(duart68681->channel[0].rx_fifo_read_ptr));
+ device->save_item(NAME(duart68681->channel[0].rx_fifo_write_ptr));
+ device->save_item(NAME(duart68681->channel[0].rx_fifo_num));
+ device->save_item(NAME(duart68681->channel[0].tx_enabled));
+ device->save_item(NAME(duart68681->channel[0].tx_data));
+ device->save_item(NAME(duart68681->channel[0].tx_ready));
+
+ device->save_item(NAME(duart68681->channel[1].CR));
+ device->save_item(NAME(duart68681->channel[1].CSR));
+ device->save_item(NAME(duart68681->channel[1].MR1));
+ device->save_item(NAME(duart68681->channel[1].MR2));
+ device->save_item(NAME(duart68681->channel[1].MR_ptr));
+ device->save_item(NAME(duart68681->channel[1].SR));
+ device->save_item(NAME(duart68681->channel[1].baud_rate));
+ device->save_item(NAME(duart68681->channel[1].rx_enabled));
+ device->save_item(NAME(duart68681->channel[1].rx_fifo));
+ device->save_item(NAME(duart68681->channel[1].rx_fifo_read_ptr));
+ device->save_item(NAME(duart68681->channel[1].rx_fifo_write_ptr));
+ device->save_item(NAME(duart68681->channel[1].rx_fifo_num));
+ device->save_item(NAME(duart68681->channel[1].tx_enabled));
+ device->save_item(NAME(duart68681->channel[1].tx_data));
+ device->save_item(NAME(duart68681->channel[1].tx_ready));
+}
+
+/*-------------------------------------------------
+ device reset callback
+-------------------------------------------------*/
+
+static DEVICE_RESET(duart68681)
+{
+ duart68681_state *duart68681 = get_safe_token(device);
+ emu_timer *save0, *save1;
+
+ duart68681->ACR = 0; /* Interrupt Vector Register */
+ duart68681->IVR = 0x0f; /* Interrupt Vector Register */
+ duart68681->IMR = 0; /* Interrupt Mask Register */
+ duart68681->ISR = 0; /* Interrupt Status Register */
+ duart68681->OPCR = 0; /* Output Port Conf. Register */
+ duart68681->OPR = 0; /* Output Port Register */
+ duart68681->CTR.d = 0; /* Counter/Timer Preset Value */
+ duart68681->IP_last_state = 0; /* last state of IP bits */
+ // "reset clears internal registers (SRA, SRB, IMR, ISR, OPR, OPCR) puts OP0-7 in the high state, stops the counter/timer, and puts channels a/b in the inactive state"
+ save0 = duart68681->channel[0].tx_timer;
+ save1 = duart68681->channel[1].tx_timer;
+ memset(duart68681->channel, 0, sizeof(duart68681->channel));
+ duart68681->channel[0].tx_timer = save0;
+ duart68681->channel[1].tx_timer = save1;
+
+ if (duart68681->duart_config->output_port_write)
+ duart68681->duart_config->output_port_write(duart68681->device, duart68681->OPR ^ 0xff);
+
+ // reset timers
+ duart68681->channel[0].tx_timer->adjust(attotime::never);
+ duart68681->channel[1].tx_timer->adjust(attotime::never, 1);
+}
+
+/*-------------------------------------------------
+ device get info callback
+-------------------------------------------------*/
+
+DEVICE_GET_INFO(duart68681)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(duart68681_state); break;
+ case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = sizeof(duart68681_config); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(duart68681); break;
+ case DEVINFO_FCT_STOP: /* nothing */ break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(duart68681);break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "DUART 68681"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "DUART"); 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;
+ }
+}
+
+DEFINE_LEGACY_DEVICE(DUART68681, duart68681);
diff --git a/trunk/src/emu/machine/68681.h b/trunk/src/emu/machine/68681.h
new file mode 100644
index 00000000000..25b5df8b7c0
--- /dev/null
+++ b/trunk/src/emu/machine/68681.h
@@ -0,0 +1,30 @@
+#ifndef _68681_H
+#define _68681_H
+
+#include "devlegcy.h"
+
+typedef struct _duart68681_config duart68681_config;
+struct _duart68681_config
+{
+ void (*irq_handler)(device_t *device, UINT8 vector);
+ void (*tx_callback)(device_t *device, int channel, UINT8 data);
+ UINT8 (*input_port_read)(device_t *device);
+ void (*output_port_write)(device_t *device, UINT8 data);
+
+ /* clocks for external baud rates */
+ INT32 ip3clk, ip4clk, ip5clk, ip6clk;
+};
+
+DECLARE_LEGACY_DEVICE(DUART68681, duart68681);
+
+#define MCFG_DUART68681_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD(_tag, DUART68681, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+
+READ8_DEVICE_HANDLER(duart68681_r);
+WRITE8_DEVICE_HANDLER(duart68681_w);
+
+void duart68681_rx_data( device_t* device, int ch, UINT8 data );
+
+#endif //_68681_H
diff --git a/trunk/src/emu/machine/74123.c b/trunk/src/emu/machine/74123.c
new file mode 100644
index 00000000000..eac124eeae4
--- /dev/null
+++ b/trunk/src/emu/machine/74123.c
@@ -0,0 +1,304 @@
+/*****************************************************************************
+
+ 74123 monoflop emulator - see 74123.h for pin out and truth table
+
+ Formulas came from the TI datasheet revised on March 1998
+
+ *****************************************************************************/
+
+#include "emu.h"
+#include "machine/74123.h"
+#include "machine/rescap.h"
+
+
+#define LOG (0)
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type TTL74123 = &device_creator<ttl74123_device>;
+
+//-------------------------------------------------
+// ttl74123_device - constructor
+//-------------------------------------------------
+
+ttl74123_device::ttl74123_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, TTL74123, "TTL74123", tag, owner, clock)
+{
+
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void ttl74123_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const ttl74123_interface *intf = reinterpret_cast<const ttl74123_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<ttl74123_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ m_connection_type = TTL74123_NOT_GROUNDED_NO_DIODE;
+ m_res = 1.0;
+ m_cap = 1.0;
+ m_a = 0;
+ m_b = 0;
+ m_clear = 0;
+ memset(&m_output_changed_cb, 0, sizeof(m_output_changed_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void ttl74123_device::device_start()
+{
+ m_timer = machine().scheduler().timer_alloc(FUNC(clear_callback), (void *)this);
+
+ /* register for state saving */
+ save_item(NAME(m_a));
+ save_item(NAME(m_b));
+ save_item(NAME(m_clear));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void ttl74123_device::device_reset()
+{
+ set_output();
+}
+
+
+
+//-------------------------------------------------
+// compute_duration - compute timer duration
+//-------------------------------------------------
+
+attotime ttl74123_device::compute_duration()
+{
+ double duration;
+
+ switch (m_connection_type)
+ {
+ case TTL74123_NOT_GROUNDED_NO_DIODE:
+ duration = 0.28 * m_res * m_cap * (1.0 + (700.0 / m_res));
+ break;
+
+ case TTL74123_NOT_GROUNDED_DIODE:
+ duration = 0.25 * m_res * m_cap * (1.0 + (700.0 / m_res));
+ break;
+
+ case TTL74123_GROUNDED:
+ default:
+ if (m_cap < CAP_U(0.1))
+ {
+ /* this is really a curve - a very flat one in the 0.1uF-.01uF range */
+ duration = 0.32 * m_res * m_cap;
+ }
+ else
+ {
+ duration = 0.33 * m_res * m_cap;
+ }
+ break;
+ }
+
+ return attotime::from_double(duration);
+}
+
+
+//-------------------------------------------------
+// timer_running - is the timer running?
+//-------------------------------------------------
+
+int ttl74123_device::timer_running()
+{
+ return (m_timer->remaining() > attotime::zero) &&
+ (m_timer->remaining() != attotime::never);
+}
+
+
+/*-------------------------------------------------
+ TIMER_CALLBACK( output_callback )
+-------------------------------------------------*/
+
+TIMER_CALLBACK( ttl74123_device::output_callback )
+{
+ ttl74123_device *dev = reinterpret_cast<ttl74123_device*>(ptr);
+ dev->output(param);
+}
+
+void ttl74123_device::output(INT32 param)
+{
+ m_output_changed_cb(this, 0, param);
+}
+
+
+//-------------------------------------------------
+// set_output - set the output line state
+//-------------------------------------------------
+
+void ttl74123_device::set_output()
+{
+ int output = timer_running();
+
+ machine().scheduler().timer_set( attotime::zero, FUNC(output_callback ), output, (void *)this);
+
+ if (LOG) logerror("74123 %s: Output: %d\n", tag(), output);
+}
+
+
+/*-------------------------------------------------
+ TIMER_CALLBACK( clear_callback )
+-------------------------------------------------*/
+
+TIMER_CALLBACK( ttl74123_device::clear_callback )
+{
+ ttl74123_device *dev = reinterpret_cast<ttl74123_device*>(ptr);
+ dev->clear();
+}
+
+void ttl74123_device::clear()
+{
+ int output = timer_running();
+
+ m_output_changed_cb(this, 0, output);
+}
+
+
+//-------------------------------------------------
+// start_pulse - begin timing
+//-------------------------------------------------
+
+void ttl74123_device::start_pulse()
+{
+ attotime duration = compute_duration();
+
+ if(timer_running())
+ {
+ /* retriggering, but not if we are called to quickly */
+ attotime delay_time = attotime(0, ATTOSECONDS_PER_SECOND * m_cap * 220);
+
+ if(m_timer->elapsed() >= delay_time)
+ {
+ m_timer->adjust(duration);
+
+ if (LOG) logerror("74123 %s: Retriggering pulse. Duration: %f\n", tag(), duration.as_double());
+ }
+ else
+ {
+ if (LOG) logerror("74123 %s: Retriggering failed.\n", tag());
+ }
+ }
+ else
+ {
+ /* starting */
+ m_timer->adjust(duration);
+
+ set_output();
+
+ if (LOG) logerror("74123 %s: Starting pulse. Duration: %f\n", tag(), duration.as_double());
+ }
+}
+
+
+//-------------------------------------------------
+// a_w - write register a data
+//-------------------------------------------------
+
+WRITE8_DEVICE_HANDLER( ttl74123_a_w )
+{
+ ttl74123_device *dev = downcast<ttl74123_device *>(device);
+ dev->a_w(data);
+}
+
+void ttl74123_device::a_w(UINT8 data)
+{
+ /* start/regtrigger pulse if B=HI and falling edge on A (while clear is HI) */
+ if (!data && m_a && m_b && m_clear)
+ {
+ start_pulse();
+ }
+
+ m_a = data;
+}
+
+
+//-------------------------------------------------
+// b_w - write register b data
+//-------------------------------------------------
+
+WRITE8_DEVICE_HANDLER( ttl74123_b_w )
+{
+ ttl74123_device *dev = downcast<ttl74123_device *>(device);
+ dev->b_w(data);
+}
+
+void ttl74123_device::b_w(UINT8 data)
+{
+ /* start/regtrigger pulse if A=LO and rising edge on B (while clear is HI) */
+ if (data && !m_b && !m_a && m_clear)
+ {
+ start_pulse();
+ }
+
+ m_b = data;
+}
+
+
+//-------------------------------------------------
+// clear_w - write register clear data
+//-------------------------------------------------
+
+WRITE8_DEVICE_HANDLER( ttl74123_clear_w )
+{
+ ttl74123_device *dev = downcast<ttl74123_device *>(device);
+ dev->clear_w(data);
+}
+
+void ttl74123_device::clear_w(UINT8 data)
+{
+ /* start/regtrigger pulse if B=HI and A=LO and rising edge on clear */
+ if (data && !m_a && m_b && !m_clear)
+ {
+ start_pulse();
+ }
+ else if (!data) /* clear the output */
+ {
+ m_timer->adjust(attotime::zero);
+
+ if (LOG) logerror("74123 #%s: Cleared\n", tag() );
+ }
+ m_clear = data;
+}
+
+
+//-------------------------------------------------
+// reset_w - reset device
+//-------------------------------------------------
+
+WRITE8_DEVICE_HANDLER( ttl74123_reset_w )
+{
+ ttl74123_device *dev = downcast<ttl74123_device *>(device);
+ dev->reset_w();
+}
+
+void ttl74123_device::reset_w()
+{
+ set_output();
+}
diff --git a/trunk/src/emu/machine/74123.h b/trunk/src/emu/machine/74123.h
new file mode 100644
index 00000000000..1338c4e825d
--- /dev/null
+++ b/trunk/src/emu/machine/74123.h
@@ -0,0 +1,142 @@
+/*****************************************************************************
+
+ 74123 monoflop emulator
+
+ There are 2 monoflops per chips.
+
+ Pin out:
+
+ +--------+
+ B1 |1 | | 16| Vcc
+ A1 o|2 - 15| RCext1
+ Clear1 o|3 14| Cext1
+ *Output1 o|4 13| Output1
+ Output2 |5 12|o *Output2
+ Cext2 |6 11|o Clear2
+ RCext2 |7 10| B2
+ GND |8 9|o A2
+ +--------+
+
+ All resistor values in Ohms.
+ All capacitor values in Farads.
+
+
+ Truth table:
+
+ C A B | Q /Q
+ ----------|-------
+ L X X | L H
+ X H X | L H
+ X X L | L H
+ H L _- |_-_ -_-
+ H -_ H |_-_ -_-
+ _- L H |_-_ -_-
+ ------------------
+ C = clear
+ L = LO (0)
+ H = HI (1)
+ X = any state
+ _- = raising edge
+ -_ = falling edge
+ _-_ = positive pulse
+ -_- = negative pulse
+
+*****************************************************************************/
+
+#pragma once
+
+#ifndef __TTL74123_H__
+#define __TTL74123_H__
+
+#include "emu.h"
+
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_TTL74123_ADD(_tag, _config) \
+ MCFG_DEVICE_ADD(_tag, TTL74123, 0) \
+ MCFG_DEVICE_CONFIG(_config)
+
+/* constants for the different ways the cap/res can be connected.
+ This determines the formula for calculating the pulse width */
+#define TTL74123_NOT_GROUNDED_NO_DIODE (1)
+#define TTL74123_NOT_GROUNDED_DIODE (2)
+#define TTL74123_GROUNDED (3)
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+
+// ======================> ttl74123_interface
+
+struct ttl74123_interface
+{
+ int m_connection_type; /* the hook up type - one of the constants above */
+ double m_res; /* resistor connected to RCext */
+ double m_cap; /* capacitor connected to Cext and RCext */
+ int m_a; /* initial/constant value of the A pin */
+ int m_b; /* initial/constant value of the B pin */
+ int m_clear; /* initial/constant value of the Clear pin */
+ write8_device_func m_output_changed_cb;
+};
+
+
+
+// ======================> ttl74123_device
+
+class ttl74123_device : public device_t,
+ public ttl74123_interface
+{
+public:
+ // construction/destruction
+ ttl74123_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ void a_w(UINT8 data);
+ void b_w(UINT8 data);
+ void clear_w(UINT8 data);
+ void reset_w();
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_post_load() { }
+ virtual void device_clock_changed() { }
+
+ static TIMER_CALLBACK( output_callback );
+ static TIMER_CALLBACK( clear_callback );
+
+private:
+
+ int timer_running();
+ void start_pulse();
+ void output(INT32 param);
+ void set_output();
+ attotime compute_duration();
+ void clear();
+
+ emu_timer *m_timer;
+};
+
+
+// device type definition
+extern const device_type TTL74123;
+
+
+
+/***************************************************************************
+ PROTOTYPES
+***************************************************************************/
+
+WRITE8_DEVICE_HANDLER( ttl74123_a_w );
+WRITE8_DEVICE_HANDLER( ttl74123_b_w );
+WRITE8_DEVICE_HANDLER( ttl74123_clear_w );
+WRITE8_DEVICE_HANDLER( ttl74123_reset_w ); /* reset the latch */
+
+#endif
diff --git a/trunk/src/emu/machine/74148.c b/trunk/src/emu/machine/74148.c
new file mode 100644
index 00000000000..accc2af5915
--- /dev/null
+++ b/trunk/src/emu/machine/74148.c
@@ -0,0 +1,226 @@
+/*****************************************************************************
+
+ 74148 8-line-to-3-line priority encoder
+
+
+ Pin layout and functions to access pins:
+
+ input_line_w(4) [1] /IN4 VCC [16]
+ input_line_w(5) [2] /IN5 /EO [15] enable_output_r
+ input_line_w(6) [3] /IN6 /GS [14] output_valid_r
+ input_line_w(7) [4] /IN7 /IN3 [13] input_line_w(3)
+ enable_input_w [5] /EI /IN2 [12] input_line_w(2)
+ output_r [6] /A2 /IN1 [11] input_line_w(1)
+ output_r [7] /A1 /IN0 [10] input_line_w(0)
+ [8] GND /A0 [9] output_r
+
+
+ Truth table (all logic levels indicate the actual voltage on the line):
+
+ INPUTS | OUTPUTS
+ |
+ EI I0 I1 I2 I3 I4 I5 I6 I7 | A2 A1 A0 | GS EO
+ ----------------------------+----------+------
+ 1 H X X X X X X X X | H H H | H H
+ 2 L H H H H H H H H | H H H | H L
+ 3 L X X X X X X X L | L L L | L H
+ 4 L X X X X X X L H | L L H | L H
+ 5 L X X X X X L H H | L H L | L H
+ 6 L X X X X L H H H | L H H | L H
+ 7 L X X X L H H H H | H L L | L H
+ 8 L X X L H H H H H | H L H | L H
+ 9 L X L H H H H H H | H H L | L H
+ 10 L L H H H H H H H | H H H | L H
+ ----------------------------+----------+------
+ L = lo (0)
+ H = hi (1)
+ X = any state
+
+*****************************************************************************/
+
+#include "emu.h"
+#include "machine/74148.h"
+
+
+typedef struct _ttl74148_state ttl74148_state;
+struct _ttl74148_state
+{
+ /* callback */
+ void (*output_cb)(device_t *device);
+
+ /* inputs */
+ int input_lines[8]; /* pins 1-4,10-13 */
+ int enable_input; /* pin 5 */
+
+ /* outputs */
+ int output; /* pins 6,7,9 */
+ int output_valid; /* pin 14 */
+ int enable_output; /* pin 15 */
+
+ /* internals */
+ int last_output;
+ int last_output_valid;
+ int last_enable_output;
+};
+
+
+INLINE ttl74148_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == TTL74148);
+
+ return (ttl74148_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+void ttl74148_update(device_t *device)
+{
+ ttl74148_state *state = get_safe_token(device);
+
+ if (state->enable_input)
+ {
+ // row 1 in truth table
+ state->output = 0x07;
+ state->output_valid = 1;
+ state->enable_output = 1;
+ }
+ else
+ {
+ int bit0, bit1, bit2;
+
+ /* this comes straight off the data sheet schematics */
+ bit0 = !(((!state->input_lines[1]) &
+ state->input_lines[2] &
+ state->input_lines[4] &
+ state->input_lines[6]) |
+ ((!state->input_lines[3]) &
+ state->input_lines[4] &
+ state->input_lines[6]) |
+ ((!state->input_lines[5]) &
+ state->input_lines[6]) |
+ (!state->input_lines[7]));
+
+ bit1 = !(((!state->input_lines[2]) &
+ state->input_lines[4] &
+ state->input_lines[5]) |
+ ((!state->input_lines[3]) &
+ state->input_lines[4] &
+ state->input_lines[5]) |
+ (!state->input_lines[6]) |
+ (!state->input_lines[7]));
+
+ bit2 = !((!state->input_lines[4]) |
+ (!state->input_lines[5]) |
+ (!state->input_lines[6]) |
+ (!state->input_lines[7]));
+
+ state->output = (bit2 << 2) | (bit1 << 1) | bit0;
+
+ state->output_valid = (state->input_lines[0] &
+ state->input_lines[1] &
+ state->input_lines[2] &
+ state->input_lines[3] &
+ state->input_lines[4] &
+ state->input_lines[5] &
+ state->input_lines[6] &
+ state->input_lines[7]);
+
+ state->enable_output = !state->output_valid;
+ }
+
+
+ /* call callback if any of the outputs changed */
+ if ( state->output_cb &&
+ ((state->output != state->last_output) ||
+ (state->output_valid != state->last_output_valid) ||
+ (state->enable_output != state->last_enable_output)))
+ {
+ state->last_output = state->output;
+ state->last_output_valid = state->output_valid;
+ state->last_enable_output = state->enable_output;
+
+ state->output_cb(device);
+ }
+}
+
+
+void ttl74148_input_line_w(device_t *device, int input_line, int data)
+{
+ ttl74148_state *state = get_safe_token(device);
+ state->input_lines[input_line] = data ? 1 : 0;
+}
+
+
+void ttl74148_enable_input_w(device_t *device, int data)
+{
+ ttl74148_state *state = get_safe_token(device);
+ state->enable_input = data ? 1 : 0;
+}
+
+
+int ttl74148_output_r(device_t *device)
+{
+ ttl74148_state *state = get_safe_token(device);
+ return state->output;
+}
+
+
+int ttl74148_output_valid_r(device_t *device)
+{
+ ttl74148_state *state = get_safe_token(device);
+ return state->output_valid;
+}
+
+
+int ttl74148_enable_output_r(device_t *device)
+{
+ ttl74148_state *state = get_safe_token(device);
+ return state->enable_output;
+}
+
+
+static DEVICE_START( ttl74148 )
+{
+ ttl74148_config *config = (ttl74148_config *)downcast<const legacy_device_base *>(device)->inline_config();
+ ttl74148_state *state = get_safe_token(device);
+ state->output_cb = config->output_cb;
+
+ device->save_item(NAME(state->input_lines));
+ device->save_item(NAME(state->enable_input));
+ device->save_item(NAME(state->output));
+ device->save_item(NAME(state->output_valid));
+ device->save_item(NAME(state->enable_output));
+ device->save_item(NAME(state->last_output));
+ device->save_item(NAME(state->last_output_valid));
+ device->save_item(NAME(state->last_enable_output));
+}
+
+
+static DEVICE_RESET( ttl74148 )
+{
+ ttl74148_state *state = get_safe_token(device);
+
+ state->enable_input = 1;
+ state->input_lines[0] = 1;
+ state->input_lines[1] = 1;
+ state->input_lines[2] = 1;
+ state->input_lines[3] = 1;
+ state->input_lines[4] = 1;
+ state->input_lines[5] = 1;
+ state->input_lines[6] = 1;
+ state->input_lines[7] = 1;
+
+ state->last_output = -1;
+ state->last_output_valid = -1;
+ state->last_enable_output = -1;
+}
+
+
+static const char DEVTEMPLATE_SOURCE[] = __FILE__;
+
+#define DEVTEMPLATE_ID(p,s) p##ttl74148##s
+#define DEVTEMPLATE_FEATURES DT_HAS_START | DT_HAS_RESET | DT_HAS_INLINE_CONFIG
+#define DEVTEMPLATE_NAME "74148"
+#define DEVTEMPLATE_FAMILY "TTL"
+#include "devtempl.h"
+
+DEFINE_LEGACY_DEVICE(TTL74148, ttl74148);
diff --git a/trunk/src/emu/machine/74148.h b/trunk/src/emu/machine/74148.h
new file mode 100644
index 00000000000..05dc7c28168
--- /dev/null
+++ b/trunk/src/emu/machine/74148.h
@@ -0,0 +1,70 @@
+/*****************************************************************************
+
+ 74148 8-line-to-3-line priority encoder
+
+
+ Pin layout and functions to access pins:
+
+ input_line_w(4) [1] /IN4 VCC [16]
+ input_line_w(5) [2] /IN5 /EO [15] enable_output_r
+ input_line_w(6) [3] /IN6 /GS [14] output_valid_r
+ input_line_w(7) [4] /IN7 /IN3 [13] input_line_w(3)
+ enable_input_w [5] /EI /IN2 [12] input_line_w(2)
+ output_r [6] /A2 /IN1 [11] input_line_w(1)
+ output_r [7] /A1 /IN0 [10] input_line_w(0)
+ [8] GND /A0 [9] output_r
+
+
+ Truth table (all logic levels indicate the actual voltage on the line):
+
+ INPUTS | OUTPUTS
+ |
+ EI I0 I1 I2 I3 I4 I5 I6 I7 | A2 A1 A0 | GS EO
+ ----------------------------+----------+------
+ H X X X X X X X X | H H H | H H
+ L H H H H H H H H | H H H | H L
+ L X X X X X X X L | L L L | L H
+ L X X X X X X L H | L L H | L H
+ L X X X X X L H H | L H L | L H
+ L X X X X L H H H | L H H | L H
+ L X X X L H H H H | H L L | L H
+ L X X L H H H H H | H L H | L H
+ L X L H H H H H H | H H L | L H
+ L L H H H H H H H | H H H | L H
+ ----------------------------+----------+------
+ L = lo (0)
+ H = hi (1)
+ X = any state
+
+*****************************************************************************/
+
+#ifndef TTL74148_H
+#define TTL74148_H
+
+#include "devlegcy.h"
+
+
+typedef struct _ttl74148_config ttl74148_config;
+struct _ttl74148_config
+{
+ void (*output_cb)(device_t *device);
+};
+
+
+#define MCFG_74148_ADD(_tag, _output_cb) \
+ MCFG_DEVICE_ADD(_tag, TTL74148, 0) \
+ MCFG_DEVICE_CONFIG_DATAPTR(ttl74148_config, output_cb, _output_cb)
+
+
+/* must call ttl74148_update() after setting the inputs */
+void ttl74148_update(device_t *device);
+
+void ttl74148_input_line_w(device_t *device, int input_line, int data);
+void ttl74148_enable_input_w(device_t *device, int data);
+int ttl74148_output_r(device_t *device);
+int ttl74148_output_valid_r(device_t *device);
+int ttl74148_enable_output_r(device_t *device);
+
+DECLARE_LEGACY_DEVICE(TTL74148, ttl74148);
+
+#endif
diff --git a/trunk/src/emu/machine/74153.c b/trunk/src/emu/machine/74153.c
new file mode 100644
index 00000000000..cbb44d251ff
--- /dev/null
+++ b/trunk/src/emu/machine/74153.c
@@ -0,0 +1,188 @@
+/*****************************************************************************
+
+ 74153 Dual 4-line to 1-line data selectors/multiplexers
+
+
+ Pin layout and functions to access pins:
+
+ enable_w(0) [1] /1G VCC [16]
+ b_w [2] B /2G [15] enable_w(1)
+ input_line_w(0,3) [3] 1C3 A [14] a_w
+ input_line_w(0,2) [4] 1C2 2C3 [13] input_line_w(1,3)
+ input_line_w(0,1) [5] 1C1 2C2 [12] input_line_w(1,2)
+ input_line_w(0,0) [6] 1C0 2C1 [11] input_line_w(1,1)
+ output_r(0) [7] 1Y 2C0 [10] input_line_w(1,0)
+ [8] GND 2Y [9] output_r(1)
+
+
+ Truth table (all logic levels indicate the actual voltage on the line):
+
+ INPUTS | OUTPUT
+ |
+ G | B A | C0 C1 C2 C3 | Y
+ --+------+-------------+---
+1 H | X X | X X X X | L
+2 L | L L | X X X X | C0
+3 L | L H | X X X X | C1
+4 L | H L | X X X X | C2
+5 L | H H | X X X X | C3
+ --+------+-------------+---
+ L = lo (0)
+ H = hi (1)
+ X = any state
+
+*****************************************************************************/
+
+#include "emu.h"
+#include "machine/74153.h"
+
+
+typedef struct _ttl74153_state ttl74153_state;
+struct _ttl74153_state
+{
+ /* callback */
+ void (*output_cb)(device_t *device);
+
+ /* inputs */
+ int a; /* pin 14 */
+ int b; /* pin 2 */
+ int input_lines[2][4]; /* pins 3-6,10-13 */
+ int enable[2]; /* pins 1,15 */
+
+ /* output */
+ int output[2]; /* pins 7,9 */
+
+ /* internals */
+ int last_output[2];
+};
+
+INLINE ttl74153_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == TTL74153);
+
+ return (ttl74153_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+
+void ttl74153_update(device_t *device)
+{
+ ttl74153_state *state = get_safe_token(device);
+ int sel;
+ int section;
+
+
+ sel = (state->b << 1) | state->a;
+
+
+ /* process both sections */
+ for (section = 0; section < 2; section++)
+ {
+ if (state->enable[section])
+ state->output[section] = 0; // row 1 in truth table
+ else
+ state->output[section] = state->input_lines[section][sel];
+ }
+
+
+ /* call callback if either of the outputs changed */
+ if ( state->output_cb &&
+ ((state->output[0] != state->last_output[0]) ||
+ (state->output[1] != state->last_output[1])))
+ {
+ state->last_output[0] = state->output[0];
+ state->last_output[1] = state->output[1];
+
+ state->output_cb(device);
+ }
+}
+
+
+void ttl74153_a_w(device_t *device, int data)
+{
+ ttl74153_state *state = get_safe_token(device);
+ state->a = data ? 1 : 0;
+}
+
+
+void ttl74153_b_w(device_t *device, int data)
+{
+ ttl74153_state *state = get_safe_token(device);
+ state->b = data ? 1 : 0;
+}
+
+
+void ttl74153_input_line_w(device_t *device, int section, int input_line, int data)
+{
+ ttl74153_state *state = get_safe_token(device);
+ state->input_lines[section][input_line] = data ? 1 : 0;
+}
+
+
+void ttl74153_enable_w(device_t *device, int section, int data)
+{
+ ttl74153_state *state = get_safe_token(device);
+ state->enable[section] = data ? 1 : 0;
+}
+
+
+int ttl74153_output_r(device_t *device, int section)
+{
+ ttl74153_state *state = get_safe_token(device);
+ return state->output[section];
+}
+
+
+static DEVICE_START( ttl74153 )
+{
+ ttl74153_config *config = (ttl74153_config *)downcast<const legacy_device_base *>(device)->inline_config();
+ ttl74153_state *state = get_safe_token(device);
+ state->output_cb = config->output_cb;
+
+ device->save_item(NAME(state->enable));
+ device->save_item(NAME(state->last_output));
+ device->save_item(NAME(state->input_lines[0][0]));
+ device->save_item(NAME(state->input_lines[0][1]));
+ device->save_item(NAME(state->input_lines[0][2]));
+ device->save_item(NAME(state->input_lines[0][3]));
+ device->save_item(NAME(state->input_lines[1][0]));
+ device->save_item(NAME(state->input_lines[1][1]));
+ device->save_item(NAME(state->input_lines[1][2]));
+ device->save_item(NAME(state->input_lines[1][3]));
+ device->save_item(NAME(state->a));
+ device->save_item(NAME(state->b));
+}
+
+
+static DEVICE_RESET( ttl74153 )
+{
+ ttl74153_state *state = get_safe_token(device);
+
+ state->a = 1;
+ state->b = 1;
+ state->enable[0] = 1;
+ state->enable[1] = 1;
+ state->input_lines[0][0] = 1;
+ state->input_lines[0][1] = 1;
+ state->input_lines[0][2] = 1;
+ state->input_lines[0][3] = 1;
+ state->input_lines[1][0] = 1;
+ state->input_lines[1][1] = 1;
+ state->input_lines[1][2] = 1;
+ state->input_lines[1][3] = 1;
+
+ state->last_output[0] = -1;
+ state->last_output[1] = -1;
+}
+
+
+static const char DEVTEMPLATE_SOURCE[] = __FILE__;
+
+#define DEVTEMPLATE_ID(p,s) p##ttl74153##s
+#define DEVTEMPLATE_FEATURES DT_HAS_START | DT_HAS_RESET | DT_HAS_INLINE_CONFIG
+#define DEVTEMPLATE_NAME "74153"
+#define DEVTEMPLATE_FAMILY "TTL"
+#include "devtempl.h"
+
+DEFINE_LEGACY_DEVICE(TTL74153, ttl74153);
diff --git a/trunk/src/emu/machine/74153.h b/trunk/src/emu/machine/74153.h
new file mode 100644
index 00000000000..6a40c3c2619
--- /dev/null
+++ b/trunk/src/emu/machine/74153.h
@@ -0,0 +1,66 @@
+/*****************************************************************************
+
+ 74153 Dual 4-line to 1-line data selectors/multiplexers
+
+
+ Pin layout and functions to access pins:
+
+ enable_w(0) [1] /1G VCC [16]
+ b_w [2] B /2G [15] enable_w(1)
+ input_line_w(0,3) [3] 1C3 A [14] a_w
+ input_line_w(0,2) [4] 1C2 2C3 [13] input_line_w(1,3)
+ input_line_w(0,1) [5] 1C1 2C2 [12] input_line_w(1,2)
+ input_line_w(0,0) [6] 1C0 2C1 [11] input_line_w(1,1)
+ output_r(0) [7] 1Y 2C0 [10] input_line_w(1,0)
+ [8] GND 2Y [9] output_r(1)
+
+
+ Truth table (all logic levels indicate the actual voltage on the line):
+
+ INPUTS | OUTPUT
+ |
+ G | B A | C0 C1 C2 C3 | Y
+ --+------+-------------+---
+ H | X X | X X X X | L
+ L | L L | X X X X | C0
+ L | L H | X X X X | C1
+ L | H L | X X X X | C2
+ L | H H | X X X X | C3
+ --+------+-------------+---
+ L = lo (0)
+ H = hi (1)
+ X = any state
+
+*****************************************************************************/
+
+#ifndef TTL74153_H
+#define TTL74153_H
+
+#include "devlegcy.h"
+
+
+typedef struct _ttl74153_config ttl74153_config;
+struct _ttl74153_config
+{
+ void (*output_cb)(device_t *device);
+};
+
+
+#define MCFG_74153_ADD(_tag, _output_cb) \
+ MCFG_DEVICE_ADD(_tag, TTL74153, 0) \
+ MCFG_DEVICE_CONFIG_DATAPTR(ttl74153_config, output_cb, _output_cb)
+
+
+
+/* must call TTL74153_update() after setting the inputs */
+void ttl74153_update(device_t *device);
+
+void ttl74153_a_w(device_t *device, int data);
+void ttl74153_b_w(device_t *device, int data);
+void ttl74153_input_line_w(device_t *device, int section, int input_line, int data);
+void ttl74153_enable_w(device_t *device, int section, int data);
+int ttl74153_output_r(device_t *device, int section);
+
+DECLARE_LEGACY_DEVICE(TTL74153, ttl74153);
+
+#endif
diff --git a/trunk/src/emu/machine/74181.c b/trunk/src/emu/machine/74181.c
new file mode 100644
index 00000000000..dca07ad01fe
--- /dev/null
+++ b/trunk/src/emu/machine/74181.c
@@ -0,0 +1,165 @@
+/*
+ * 74181
+ *
+ * 4-bit arithmetic Logic Unit
+ *
+ */
+
+#include "emu.h"
+#include "74181.h"
+
+
+
+#define TTL74181_MAX_CHIPS (2)
+#define TTL74181_INPUT_TOTAL (14)
+#define TTL74181_OUTPUT_TOTAL (8)
+
+
+
+typedef struct _TTL74181_state TTL74181_state;
+struct _TTL74181_state
+{
+ UINT8 inputs[TTL74181_INPUT_TOTAL];
+ UINT8 outputs[TTL74181_OUTPUT_TOTAL];
+ UINT8 dirty;
+};
+
+static TTL74181_state chips[TTL74181_MAX_CHIPS];
+
+
+void TTL74181_config(running_machine &machine, int which, void *intf)
+{
+ TTL74181_state *c;
+
+ assert_always(machine.phase() == MACHINE_PHASE_INIT, "Can only call at init time!");
+ assert_always(intf == 0, "Interface must be NULL");
+ assert_always((which >= 0) && (which < TTL74181_MAX_CHIPS), "Exceeded maximum number of 74181 chips");
+
+ c = &chips[which];
+
+ c->dirty = 1;
+
+ state_save_register_item_array(machine, "TTL74181", NULL, which, c->inputs);
+ state_save_register_item_array(machine, "TTL74181", NULL, which, c->outputs);
+ state_save_register_item (machine, "TTL74181", NULL, which, c->dirty);
+}
+
+
+void TTL74181_reset(int which)
+{
+ /* nothing to do */
+}
+
+
+static void TTL74181_update(int which)
+{
+ TTL74181_state *c = &chips[which];
+
+ UINT8 a0 = c->inputs[TTL74181_INPUT_A0];
+ UINT8 a1 = c->inputs[TTL74181_INPUT_A1];
+ UINT8 a2 = c->inputs[TTL74181_INPUT_A2];
+ UINT8 a3 = c->inputs[TTL74181_INPUT_A3];
+
+ UINT8 b0 = c->inputs[TTL74181_INPUT_B0];
+ UINT8 b1 = c->inputs[TTL74181_INPUT_B1];
+ UINT8 b2 = c->inputs[TTL74181_INPUT_B2];
+ UINT8 b3 = c->inputs[TTL74181_INPUT_B3];
+
+ UINT8 s0 = c->inputs[TTL74181_INPUT_S0];
+ UINT8 s1 = c->inputs[TTL74181_INPUT_S1];
+ UINT8 s2 = c->inputs[TTL74181_INPUT_S2];
+ UINT8 s3 = c->inputs[TTL74181_INPUT_S3];
+
+ UINT8 cp = c->inputs[TTL74181_INPUT_C];
+ UINT8 mp = !c->inputs[TTL74181_INPUT_M];
+
+ UINT8 ap0 = !(a0 | (b0 & s0) | (s1 & !b0));
+ UINT8 bp0 = !(((!b0) & s2 & a0) | (a0 & b0 & s3));
+ UINT8 ap1 = !(a1 | (b1 & s0) | (s1 & !b1));
+ UINT8 bp1 = !(((!b1) & s2 & a1) | (a1 & b1 & s3));
+ UINT8 ap2 = !(a2 | (b2 & s0) | (s1 & !b2));
+ UINT8 bp2 = !(((!b2) & s2 & a2) | (a2 & b2 & s3));
+ UINT8 ap3 = !(a3 | (b3 & s0) | (s1 & !b3));
+ UINT8 bp3 = !(((!b3) & s2 & a3) | (a3 & b3 & s3));
+
+ UINT8 fp0 = !(cp & mp) ^ ((!ap0) & bp0);
+ UINT8 fp1 = (!((mp & ap0) | (mp & bp0 & cp))) ^ ((!ap1) & bp1);
+ UINT8 fp2 = (!((mp & ap1) | (mp & ap0 & bp1) | (mp & cp & bp0 & bp1))) ^ ((!ap2) & bp2);
+ UINT8 fp3 = (!((mp & ap2) | (mp & ap1 & bp2) | (mp & ap0 & bp1 & bp2) | (mp & cp & bp0 & bp1 & bp2))) ^ ((!ap3) & bp3);
+
+ UINT8 aeqb = fp0 & fp1 & fp2 & fp3;
+ UINT8 pp = !(bp0 & bp1 & bp2 & bp3);
+ UINT8 gp = !((ap0 & bp1 & bp2 & bp3) | (ap1 & bp2 & bp3) | (ap2 & bp3) | ap3);
+ UINT8 cn4 = (!(cp & bp0 & bp1 & bp2 & bp3)) | gp;
+
+ c->outputs[TTL74181_OUTPUT_F0] = fp0;
+ c->outputs[TTL74181_OUTPUT_F1] = fp1;
+ c->outputs[TTL74181_OUTPUT_F2] = fp2;
+ c->outputs[TTL74181_OUTPUT_F3] = fp3;
+ c->outputs[TTL74181_OUTPUT_AEQB] = aeqb;
+ c->outputs[TTL74181_OUTPUT_P] = pp;
+ c->outputs[TTL74181_OUTPUT_G] = gp;
+ c->outputs[TTL74181_OUTPUT_CN4] = cn4;
+}
+
+
+void TTL74181_write(int which, int startline, int lines, UINT8 data)
+{
+ int line;
+ TTL74181_state *c;
+
+ assert_always((which >= 0) && (which < TTL74181_MAX_CHIPS), "Chip index out of range");
+
+ c = &chips[which];
+
+ assert_always(c != NULL, "Invalid index - chip has not been configured");
+ assert_always(lines >= 1, "Must set at least one line");
+ assert_always(lines <= 4, "Can't set more than 4 lines at once");
+ assert_always((startline + lines) <= TTL74181_INPUT_TOTAL, "Input line index out of range");
+
+ for (line = 0; line < lines; line++)
+ {
+ UINT8 input = (data >> line) & 0x01;
+
+ if (c->inputs[startline + line] != input)
+ {
+ c->inputs[startline + line] = input;
+
+ c->dirty = 1;
+ }
+ }
+}
+
+
+UINT8 TTL74181_read(int which, int startline, int lines)
+{
+ int line;
+ UINT8 data;
+ TTL74181_state *c;
+
+ assert_always((which >= 0) && (which < TTL74181_MAX_CHIPS), "Chip index out of range");
+
+ c = &chips[which];
+
+ assert_always(c != NULL, "Invalid index - chip has not been configured");
+ assert_always(lines >= 1, "Must read at least one line");
+ assert_always(lines <= 4, "Can't read more than 4 lines at once");
+ assert_always((startline + lines) <= TTL74181_OUTPUT_TOTAL, "Output line index out of range");
+
+ if (c->dirty)
+ {
+ TTL74181_update(which);
+
+ c->dirty = 0;
+ }
+
+
+ data = 0;
+
+ for (line = 0; line < lines; line++)
+ {
+ data = data | (c->outputs[startline + line] << line);
+ }
+
+ return data;
+}
diff --git a/trunk/src/emu/machine/74181.h b/trunk/src/emu/machine/74181.h
new file mode 100644
index 00000000000..5d15bdac9cf
--- /dev/null
+++ b/trunk/src/emu/machine/74181.h
@@ -0,0 +1,40 @@
+/*
+ * 74181
+ *
+ * 4-Bit Arithmetic Logic Unit
+ *
+ */
+
+
+/* constants for setting input lines */
+#define TTL74181_INPUT_A0 (0)
+#define TTL74181_INPUT_A1 (1)
+#define TTL74181_INPUT_A2 (2)
+#define TTL74181_INPUT_A3 (3)
+#define TTL74181_INPUT_B0 (4)
+#define TTL74181_INPUT_B1 (5)
+#define TTL74181_INPUT_B2 (6)
+#define TTL74181_INPUT_B3 (7)
+#define TTL74181_INPUT_S0 (8)
+#define TTL74181_INPUT_S1 (9)
+#define TTL74181_INPUT_S2 (10)
+#define TTL74181_INPUT_S3 (11)
+#define TTL74181_INPUT_C (12)
+#define TTL74181_INPUT_M (13)
+
+/* constants for reads output lines */
+#define TTL74181_OUTPUT_F0 (0)
+#define TTL74181_OUTPUT_F1 (1)
+#define TTL74181_OUTPUT_F2 (2)
+#define TTL74181_OUTPUT_F3 (3)
+#define TTL74181_OUTPUT_AEQB (4)
+#define TTL74181_OUTPUT_P (5)
+#define TTL74181_OUTPUT_G (6)
+#define TTL74181_OUTPUT_CN4 (7)
+
+
+void TTL74181_config(running_machine &machine, int chip, void *interface);
+void TTL74181_reset(int chip);
+
+void TTL74181_write(int chip, int startline, int lines, UINT8 data);
+UINT8 TTL74181_read(int chip, int startline, int lines);
diff --git a/trunk/src/emu/machine/7474.c b/trunk/src/emu/machine/7474.c
new file mode 100644
index 00000000000..5a9c957cc57
--- /dev/null
+++ b/trunk/src/emu/machine/7474.c
@@ -0,0 +1,266 @@
+/*****************************************************************************
+
+ 7474 positive-edge-triggered D-type flip-flop with preset, clear and
+ complementary outputs. There are 2 flip-flops per chips
+
+
+ Pin layout and functions to access pins:
+
+ clear_w [1] /1CLR VCC [14]
+ d_w [2] 1D /2CLR [13] clear_w
+ clock_w [3] 1CLK 2D [12] d_w
+ preset_w [4] /1PR 2CLK [11] clock_w
+ output_r [5] 1Q /2PR [10] preset_w
+ output_comp_r [6] /1Q 2Q [9] output_r
+ [7] GND /2Q [8] output_comp_r
+
+
+ Truth table (all logic levels indicate the actual voltage on the line):
+
+ INPUTS | OUTPUTS
+ |
+ PR CLR CLK D | Q /Q
+ --------------+-------
+ 1 L H X X | H L
+ 2 H L X X | L H
+ 3 L L X X | H H (Note 1)
+ 4 H H _- X | D /D
+ 5 H H L X | Q0 /Q0
+ --------------+-------
+ L = lo (0)
+ H = hi (1)
+ X = any state
+ _- = raising edge
+ Q0 = previous state
+
+ Note 1: Non-stable configuration
+
+*****************************************************************************/
+
+#include "emu.h"
+#include "7474.h"
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type MACHINE_TTL7474 = &device_creator<ttl7474_device>;
+
+//-------------------------------------------------
+// ttl7474_device - constructor
+//-------------------------------------------------
+
+ttl7474_device::ttl7474_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, MACHINE_TTL7474, "7474", tag, owner, clock)
+{
+ memset(&m_output_cb, 0, sizeof(m_output_cb));
+ memset(&m_comp_output_cb, 0, sizeof(m_comp_output_cb));
+ init();
+}
+
+
+//-------------------------------------------------
+// static_set_target_tag - configuration helper
+// to set the target tag
+//-------------------------------------------------
+
+void ttl7474_device::static_set_target_tag(device_t &device, const char *tag)
+{
+ ttl7474_device &ttl7474 = downcast<ttl7474_device &>(device);
+ ttl7474.m_output_cb.tag = tag;
+ ttl7474.m_comp_output_cb.tag = tag;
+}
+
+
+//-------------------------------------------------
+// static_set_output_cb - configuration helper
+// to set the output callback
+//-------------------------------------------------
+
+void ttl7474_device::static_set_output_cb(device_t &device, write_line_device_func callback)
+{
+ ttl7474_device &ttl7474 = downcast<ttl7474_device &>(device);
+ if (callback != NULL)
+ {
+ ttl7474.m_output_cb.type = DEVCB_TYPE_DEVICE;
+ ttl7474.m_output_cb.index = DEVCB_DEVICE_OTHER;
+ ttl7474.m_output_cb.writeline = callback;
+ }
+ else
+ ttl7474.m_output_cb.type = DEVCB_TYPE_NULL;
+}
+
+
+//-------------------------------------------------
+// static_set_comp_output_cb - configuration
+// helper to set the comp. output callback
+//-------------------------------------------------
+
+void ttl7474_device::static_set_comp_output_cb(device_t &device, write_line_device_func callback)
+{
+ ttl7474_device &ttl7474 = downcast<ttl7474_device &>(device);
+ if (callback != NULL)
+ {
+ ttl7474.m_comp_output_cb.type = DEVCB_TYPE_DEVICE;
+ ttl7474.m_comp_output_cb.index = DEVCB_DEVICE_OTHER;
+ ttl7474.m_comp_output_cb.writeline = callback;
+ }
+ else
+ ttl7474.m_comp_output_cb.type = DEVCB_TYPE_NULL;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void ttl7474_device::device_start()
+{
+ save_item(NAME(m_clear));
+ save_item(NAME(m_preset));
+ save_item(NAME(m_clk));
+ save_item(NAME(m_d));
+ save_item(NAME(m_output));
+ save_item(NAME(m_output_comp));
+ save_item(NAME(m_last_clock));
+ save_item(NAME(m_last_output));
+ save_item(NAME(m_last_output_comp));
+
+ m_output_func.resolve(m_output_cb, *this);
+ m_comp_output_func.resolve(m_comp_output_cb, *this);
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void ttl7474_device::device_reset()
+{
+ init();
+}
+
+
+//-------------------------------------------------
+// update - update internal state
+//-------------------------------------------------
+
+void ttl7474_device::update()
+{
+ if (!m_preset && m_clear) // line 1 in truth table
+ {
+ m_output = 1;
+ m_output_comp = 0;
+ }
+ else if (m_preset && !m_clear) // line 2 in truth table
+ {
+ m_output = 0;
+ m_output_comp = 1;
+ }
+ else if (!m_preset && !m_clear) // line 3 in truth table
+ {
+ m_output = 1;
+ m_output_comp = 1;
+ }
+ else if (!m_last_clock && m_clk) // line 4 in truth table
+ {
+ m_output = m_d;
+ m_output_comp = !m_d;
+ }
+
+ m_last_clock = m_clk;
+
+
+ // call callback if any of the outputs changed
+ if (m_output != m_last_output)
+ {
+ m_last_output = m_output;
+ m_output_func(m_output);
+ }
+ // call callback if any of the outputs changed
+ if (m_output_comp != m_last_output_comp)
+ {
+ m_last_output_comp = m_output_comp;
+ m_comp_output_func(m_output_comp);
+ }
+}
+
+
+//-------------------------------------------------
+// clear_w - set the clear line state
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( ttl7474_device::clear_w )
+{
+ m_clear = state & 1;
+ update();
+}
+
+
+//-------------------------------------------------
+// clear_w - set the clear line state
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( ttl7474_device::preset_w )
+{
+ m_preset = state & 1;
+ update();
+}
+
+
+//-------------------------------------------------
+// clock_w - set the clock line state
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( ttl7474_device::clock_w )
+{
+ m_clk = state & 1;
+ update();
+}
+
+
+//-------------------------------------------------
+// d_w - set the d line state
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( ttl7474_device::d_w )
+{
+ m_d = state & 1;
+ update();
+}
+
+
+//-------------------------------------------------
+// output_r - get the output line state
+//-------------------------------------------------
+
+READ_LINE_MEMBER( ttl7474_device::output_r )
+{
+ return m_output;
+}
+
+
+//-----------------------------------------------------
+// output_comp_r - get the output-compare line state
+//-----------------------------------------------------
+
+READ_LINE_MEMBER( ttl7474_device::output_comp_r )
+{
+ return m_output_comp;
+}
+
+void ttl7474_device::init()
+{
+ m_clear = 1;
+ m_preset = 1;
+ m_clk = 1;
+ m_d = 1;
+
+ m_output = -1;
+ m_last_clock = 1;
+ m_last_output = -1;
+ m_last_output_comp = -1;
+}
diff --git a/trunk/src/emu/machine/7474.h b/trunk/src/emu/machine/7474.h
new file mode 100644
index 00000000000..026b7d1c5db
--- /dev/null
+++ b/trunk/src/emu/machine/7474.h
@@ -0,0 +1,141 @@
+/*****************************************************************************
+
+ 7474 positive-edge-triggered D-type flip-flop with preset, clear and
+ complementary outputs. There are 2 flip-flops per chips
+
+
+ Pin layout and functions to access pins:
+
+ clear_w [1] /1CLR VCC [14]
+ d_w [2] 1D /2CLR [13] clear_w
+ clock_w [3] 1CLK 2D [12] d_w
+ preset_w [4] /1PR 2CLK [11] clock_w
+ output_r [5] 1Q /2PR [10] preset_w
+ output_comp_r [6] /1Q 2Q [9] output_r
+ [7] GND /2Q [8] output_comp_r
+
+
+ Truth table (all logic levels indicate the actual voltage on the line):
+
+ INPUTS | OUTPUTS
+ |
+ PR CLR CLK D | Q /Q
+ --------------+-------
+ L H X X | H L
+ H L X X | L H
+ L L X X | H H (Note 1)
+ H H _- X | D /D
+ H H L X | Q0 /Q01
+ --------------+-------
+ L = lo (0)
+ H = hi (1)
+ X = any state
+ _- = raising edge
+ Q0 = previous state
+
+ Note 1: Non-stable configuration
+
+*****************************************************************************/
+
+#pragma once
+
+#ifndef __TTL7474_H__
+#define __TTL7474_H__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_7474_ADD(_tag, _target_tag, _output_cb, _comp_output_cb) \
+ MCFG_DEVICE_ADD(_tag, MACHINE_TTL7474, 0) \
+ MCFG_7474_TARGET_TAG(_target_tag) \
+ MCFG_7474_OUTPUT_CB(_output_cb) \
+ MCFG_7474_COMP_OUTPUT_CB(_comp_output_cb)
+
+#define MCFG_7474_REPLACE(_tag, _target_tag, _output_cb, _comp_output_cb) \
+ MCFG_DEVICE_REPLACE(_tag, TTL7474, 0) \
+ MCFG_7474_TARGET_TAG(_target_tag) \
+ MCFG_7474_OUTPUT_CB(_output_cb) \
+ MCFG_7474_COMP_OUTPUT_CB(_comp_output_cb)
+
+#define MCFG_7474_TARGET_TAG(_target_tag) \
+ ttl7474_device::static_set_target_tag(*device, _target_tag); \
+
+#define MCFG_7474_OUTPUT_CB(_cb) \
+ ttl7474_device::static_set_output_cb(*device, _cb); \
+
+#define MCFG_7474_COMP_OUTPUT_CB(_cb) \
+ ttl7474_device::static_set_comp_output_cb(*device, _cb); \
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> ttl7474_device
+
+class ttl7474_device : public device_t
+{
+public:
+ // construction/destruction
+ ttl7474_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // inline configuration helpers
+ static void static_set_target_tag(device_t &device, const char *tag);
+ static void static_set_output_cb(device_t &device, write_line_device_func callback);
+ static void static_set_comp_output_cb(device_t &device, write_line_device_func callback);
+
+ // public interfaces
+ DECLARE_WRITE_LINE_MEMBER( clear_w );
+ DECLARE_WRITE_LINE_MEMBER( preset_w );
+ DECLARE_WRITE_LINE_MEMBER( clock_w );
+ DECLARE_WRITE_LINE_MEMBER( d_w );
+ DECLARE_READ_LINE_MEMBER( output_r );
+ DECLARE_READ_LINE_MEMBER( output_comp_r ); // NOT strictly the same as !output_r()
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_post_load() { }
+ virtual void device_clock_changed() { }
+
+ // configuration state
+ devcb_write_line m_output_cb;
+ devcb_write_line m_comp_output_cb;
+
+private:
+ // callbacks
+ devcb_resolved_write_line m_output_func;
+ devcb_resolved_write_line m_comp_output_func;
+
+ // inputs
+ UINT8 m_clear; // pin 1/13
+ UINT8 m_preset; // pin 4/10
+ UINT8 m_clk; // pin 3/11
+ UINT8 m_d; // pin 2/12
+
+ // outputs
+ UINT8 m_output; // pin 5/9
+ UINT8 m_output_comp; // pin 6/8
+
+ // internal
+ UINT8 m_last_clock;
+ UINT8 m_last_output;
+ UINT8 m_last_output_comp;
+
+ void update();
+ void init();
+};
+
+
+// device type definition
+extern const device_type MACHINE_TTL7474;
+
+
+#endif /* __TTL7474_H__ */
diff --git a/trunk/src/emu/machine/8042kbdc.c b/trunk/src/emu/machine/8042kbdc.c
new file mode 100644
index 00000000000..9e13c4af7f7
--- /dev/null
+++ b/trunk/src/emu/machine/8042kbdc.c
@@ -0,0 +1,622 @@
+/*********************************************************************
+
+ 8042kbdc.c
+
+ Code specific to fun IBM AT stuff
+
+
+ PeT's notes about various Power On Self Tests (POSTs)
+
+ at post
+ -------
+ f81d2 01
+ f82e6 05
+ f8356 07
+ f83e5 0a
+ f847e 0e
+ f8e7c 10
+ f8f3a 13
+ f9058 1a
+ f913a 1e
+ fa8ba 30
+ fa96c 36
+ fa9d3 3c
+ fa9f4 3e
+ ff122 50
+ ff226 5b
+ ff29f 5f
+ f9228 70
+ f92b2 74 ide?
+
+ ibm at bios
+ -----------
+ f0101 after switch to real mode jump back!!!!!!!!!!
+ jumping table
+ f0123
+ f098e memory tests
+ f10b4 ???
+ not reached
+ f1050
+ f1617
+ f0119
+ f10d8
+ f10b7 system board error
+
+ f019f
+ f025b
+ f02e6
+ f0323
+ f03b3 0e
+ f03d7 0f
+ f058d
+ at8042 signal timing test
+ sets errorcode!
+
+ f0655
+ f06a3 postcode 15
+ f06ba 16
+ f0747 18
+ f0763 enter pm! (0x81, 0x85)
+ f0766 1a
+ f07b3 first 640kb memory test
+ f084c 1c
+ f086e extended memory test
+ f0928 1f
+ f097d 20
+ ???
+ f0ff4 34
+ ???
+ f1675 f0
+ f16cb f2
+ illegal access trap test!!!!
+ f16fe f3
+ task descriptor test!!!!
+ f174a f4
+ f17af f5
+ f1800 f6 writing to non write segment
+ f1852 f7 arpl
+ f1880 f8 lar, lsl
+ f18ca fa
+ f10d8
+ f10ec 35
+ f1106 36
+ f1137 !!!!!!!keyboard test fails
+
+ f11aa 3a
+ f1240 3c harddisk controller test!!!
+ f13f3 3b
+ f1a6d xthdd bios init
+ f1429
+ f1462
+ f1493 40
+ f1532
+ keyboard lock
+ f1 to unlock
+ f155c
+ jumps to f0050 (reset) without enabling of the a20 gate --> hangs
+ 0412 bit 5 must be set to reach f1579
+ f1579
+ f15c3 41
+ f1621 43
+
+ routines
+ f1945 read cmos ram
+ f195f write to cmos al value ah
+ f1a3a poll 0x61 bit 4
+ f1a49 sets something in cmos ram
+ f1d30 switch to protected mode
+
+ neat
+ ----
+ f80b9
+
+ at386
+ -----
+ fd28c fd
+ fd2c3 fc
+ f40dc
+ fd949
+ fd8e3
+ fd982
+ f4219 01
+ f4296 03
+ f42f3 04
+ f4377 05
+ f43ec 06
+ f4430 08
+ f6017 switches to PM
+ f4456 09
+ f55a2
+ f44ec 0d
+ f4557 20
+ f462d 27 my special friend, the keyboard controller once more
+ ed0a1
+ f4679 28
+ fa16a
+ f46d6
+ f4768 2c
+ f47f0 2e
+ f5081
+ fa16a
+ f9a83
+ Message: "Checksum Error on Extended CMOS"
+ f4840 34
+ f488c 35
+ reset
+ f48ee
+ f493e 3a
+ f49cd
+ f4fc7
+ fe842
+ f4a5a
+ f4b01 38
+ (Memory Test)
+ f4b41 3b
+ f4c0f
+ Message: "Invalid configuration information - please run SETUP program"
+ f4c5c
+ f86fc
+ f8838
+ f4c80
+ f4ca2
+ f4d4c
+ f4e15 (int 19h)
+
+ [f9a83 output text at return address!, return after text]
+
+
+ at486
+ -----
+ f81a5 03
+ f1096 0f 09 wbinvd i486 instruction
+
+*********************************************************************/
+
+
+#include "emu.h"
+#include "memconv.h"
+
+#include "machine/pckeybrd.h"
+#include "machine/8042kbdc.h"
+#include "machine/pcshare.h"
+
+
+/***************************************************************************
+
+ Constants & macros
+
+***************************************************************************/
+
+#define PS2_MOUSE_ON 1
+#define KEYBOARD_ON 1
+
+#define LOG_KEYBOARD 0
+#define LOG_ACCESSES 0
+
+
+
+/***************************************************************************
+
+ Type definitions
+
+***************************************************************************/
+
+static struct
+{
+ kbdc8042_type_t type;
+ void (*set_gate_a20)(running_machine &machine, int a20);
+ void (*keyboard_interrupt)(running_machine &machine, int state);
+ int (*get_out2)(running_machine &machine);
+
+ UINT8 inport, outport, data, command;
+
+ struct {
+ int received;
+ int on;
+ } keyboard;
+ struct {
+ int received;
+ int on;
+ } mouse;
+
+ int last_write_to_control;
+ int sending;
+ int send_to_mouse;
+
+ int operation_write_state;
+ int status_read_mode;
+
+ int speaker;
+
+ /* temporary hack */
+ int offset1;
+} kbdc8042;
+
+static int poll_delay;
+
+static void at_8042_check_keyboard(running_machine &machine);
+
+
+
+/***************************************************************************
+
+ Code
+
+***************************************************************************/
+
+static void at_8042_set_outport(running_machine &machine, UINT8 data, int initial)
+{
+ UINT8 change;
+ change = initial ? 0xFF : (kbdc8042.outport ^ data);
+ kbdc8042.outport = data;
+ if (change & 0x02)
+ {
+ if (kbdc8042.set_gate_a20)
+ kbdc8042.set_gate_a20(machine, data & 0x02 ? 1 : 0);
+ }
+}
+
+
+
+static TIMER_CALLBACK( kbdc8042_time )
+{
+ at_keyboard_polling();
+ at_8042_check_keyboard(machine);
+}
+
+
+
+void kbdc8042_init(running_machine &machine, const struct kbdc8042_interface *intf)
+{
+ poll_delay = 10;
+ memset(&kbdc8042, 0, sizeof(kbdc8042));
+ kbdc8042.type = intf->type;
+ kbdc8042.set_gate_a20 = intf->set_gate_a20;
+ kbdc8042.keyboard_interrupt = intf->keyboard_interrupt;
+ kbdc8042.get_out2 = intf->get_out2;
+
+ /* ibmat bios wants 0x20 set! (keyboard locked when not set) 0x80 */
+ kbdc8042.inport = 0xa0;
+ at_8042_set_outport(machine, 0xfe, 1);
+
+ machine.scheduler().timer_pulse(attotime::from_hz(60), FUNC(kbdc8042_time));
+}
+
+static void at_8042_receive(running_machine &machine, UINT8 data)
+{
+ if (LOG_KEYBOARD)
+ logerror("at_8042_receive Received 0x%02x\n", data);
+
+ kbdc8042.data = data;
+ kbdc8042.keyboard.received = 1;
+
+ if (kbdc8042.keyboard_interrupt)
+ {
+ kbdc8042.keyboard_interrupt(machine, 1);
+ kbdc8042.keyboard_interrupt(machine, 0);
+ }
+}
+
+static void at_8042_check_keyboard(running_machine &machine)
+{
+ int data;
+
+ if (!kbdc8042.keyboard.received
+ && !kbdc8042.mouse.received)
+ {
+ if ( (data = at_keyboard_read())!=-1)
+ at_8042_receive(machine, data);
+ }
+}
+
+
+
+static void at_8042_clear_keyboard_received(void)
+{
+ if (kbdc8042.keyboard.received)
+ {
+ if (LOG_KEYBOARD)
+ logerror("kbdc8042_8_r(): Clearing kbdc8042.keyboard.received\n");
+ }
+
+ kbdc8042.keyboard.received = 0;
+ kbdc8042.mouse.received = 0;
+}
+
+
+
+/* **************************************************************************
+ * Port 0x60 Input and Output Buffer (keyboard and mouse data)
+ * Port 0x64 Read Status Register
+ * Write operation for controller
+ *
+ * Output port controller:
+ * 7: Keyboard data
+ * 6: Keyboard clock
+ * 5: Mouse buffer full
+ * 4: Keyboard buffer full
+ * 3: Mouse clock
+ * 2: Mouse data
+ * 1: 0 A20 cleared
+ * 0: 0 system reset
+ *
+ * Input port controller
+ * 7: 0=Keyboard Locked
+ * 6: 1 = Monochrome 0 = Color (true for real IBM, clones are undefined and use CMOS RAM data)
+ * 5..2: reserved
+ * 1: Mouse data in
+ * 0: Keyboard data in
+ */
+
+READ8_HANDLER(kbdc8042_8_r)
+{
+ UINT8 data = 0;
+
+ switch (offset) {
+ case 0:
+ data = kbdc8042.data;
+ if (kbdc8042.type != KBDC8042_AT386 || (data != 0x55))
+ {
+ /* at386 self test doesn't like this */
+ at_8042_clear_keyboard_received();
+ }
+ at_8042_check_keyboard(space->machine());
+ break;
+
+ case 1:
+ data = kbdc8042.speaker;
+ data &= ~0xc0; /* AT BIOS don't likes this being set */
+
+ /* needed for AMI BIOS, maybe only some keyboard controller revisions! */
+ at_8042_clear_keyboard_received();
+
+ /* polled for changes in ibmat bios */
+ if (--poll_delay < 0)
+ {
+ if (kbdc8042.type != KBDC8042_PS2)
+ poll_delay = 4; /* ibmat */
+ else
+ poll_delay = 8; /* ibm ps2m30 */
+ kbdc8042.offset1 ^= 0x10;
+ }
+ data = (data & ~0x10) | kbdc8042.offset1;
+
+ if (kbdc8042.speaker & 1)
+ data |= 0x20;
+ else
+ data &= ~0x20; /* ps2m30 wants this */
+ break;
+
+ case 2:
+ if (kbdc8042.get_out2(space->machine()))
+ data |= 0x20;
+ else
+ data &= ~0x20;
+ break;
+
+ case 4:
+ at_8042_check_keyboard(space->machine());
+
+ if (kbdc8042.keyboard.received || kbdc8042.mouse.received)
+ data |= 1;
+ if (kbdc8042.sending)
+ data |= 2;
+
+ kbdc8042.sending = 0; /* quicker than normal */
+ data |= 4; /* selftest ok */
+
+ if (kbdc8042.last_write_to_control)
+ data |= 8;
+
+ switch (kbdc8042.status_read_mode) {
+ case 0:
+ if (!kbdc8042.keyboard.on) data|=0x10;
+ if (kbdc8042.mouse.received) data|=0x20;
+ break;
+ case 1:
+ data |= kbdc8042.inport&0xf;
+ break;
+ case 2:
+ data |= kbdc8042.inport<<4;
+ break;
+ }
+ break;
+ }
+
+ if (LOG_ACCESSES)
+ logerror("kbdc8042_8_r(): offset=%d data=0x%02x\n", offset, (unsigned) data);
+ return data;
+}
+
+
+
+WRITE8_HANDLER(kbdc8042_8_w)
+{
+ switch (offset) {
+ case 0:
+ kbdc8042.last_write_to_control = 0;
+ kbdc8042.status_read_mode = 0;
+ switch (kbdc8042.operation_write_state) {
+ case 0:
+ /* normal case */
+ kbdc8042.data = data;
+ kbdc8042.sending=1;
+ at_keyboard_write(space->machine(), data);
+ break;
+
+ case 1:
+ /* preceded by writing 0xD1 to port 60h
+ * |7|6|5|4|3|2|1|0| 8042 Output Port
+ * | | | | | | | `---- system reset line
+ * | | | | | | `----- gate A20
+ * | | | | `-------- undefined
+ * | | | `--------- output buffer full
+ * | | `---------- input buffer empty
+ * | `----------- keyboard clock (output)
+ * `------------ keyboard data (output)
+ */
+ at_8042_set_outport(space->machine(), data, 0);
+ break;
+
+ case 2:
+ /* preceded by writing 0xD2 to port 60h */
+ kbdc8042.data = data;
+ kbdc8042.sending=1;
+ at_keyboard_write(space->machine(), data);
+ break;
+
+ case 3:
+ /* preceded by writing 0xD3 to port 60h */
+ kbdc8042.data = data;
+ break;
+
+ case 4:
+ /* preceded by writing 0xD4 to port 60h */
+ kbdc8042.data = data;
+ break;
+
+ case 5:
+ /* preceded by writing 0x60 to port 60h */
+ kbdc8042.command = data;
+ break;
+ }
+ kbdc8042.operation_write_state = 0;
+ break;
+
+ case 1:
+ kbdc8042.speaker = data;
+ break;
+
+ case 4:
+ kbdc8042.last_write_to_control=0;
+
+ /* switch based on the command */
+ switch(data) {
+ case 0x20: /* current 8042 command byte is placed on port 60h */
+ kbdc8042.data = kbdc8042.command;
+ break;
+ case 0x60: /* next data byte is placed in 8042 command byte */
+ kbdc8042.operation_write_state = 5;
+ kbdc8042.send_to_mouse = 0;
+ break;
+ case 0xa7: /* disable auxilary interface */
+ kbdc8042.mouse.on = 0;
+ break;
+ case 0xa8: /* enable auxilary interface */
+ kbdc8042.mouse.on = 1;
+ break;
+ case 0xa9: /* test mouse */
+ at_8042_receive(space->machine(), PS2_MOUSE_ON ? 0x00 : 0xff);
+ break;
+ case 0xaa: /* selftest */
+ at_8042_receive(space->machine(), 0x55);
+ break;
+ case 0xab: /* test keyboard */
+ at_8042_receive(space->machine(), KEYBOARD_ON ? 0x00 : 0xff);
+ break;
+ case 0xad: /* disable keyboard interface */
+ kbdc8042.keyboard.on = 0;
+ break;
+ case 0xae: /* enable keyboard interface */
+ kbdc8042.keyboard.on = 1;
+ break;
+ case 0xc0: /* read input port */
+ /* |7|6|5|4|3 2 1 0| 8042 Input Port
+ * | | | | |
+ * | | | | `------- undefined
+ * | | | |
+ * | | | `--------- 1=enable 2nd 256k of Motherboard RAM
+ * | | `---------- 1=manufacturing jumper installed
+ * | `----------- 1=primary display is MDA, 0=CGA
+ * `------------ 1=keyboard not inhibited; 0=inhibited
+ */
+ at_8042_receive(space->machine(), kbdc8042.inport);
+ break;
+ case 0xc1: /* read input port 3..0 until write to 0x60 */
+ kbdc8042.status_read_mode = 1;
+ break;
+ case 0xc2: /* read input port 7..4 until write to 0x60 */
+ kbdc8042.status_read_mode = 2;
+ break;
+ case 0xd0: /* read output port */
+ at_8042_receive(space->machine(), kbdc8042.outport);
+ break;
+ case 0xd1:
+ /* write output port; next byte written to port 60h is placed on
+ * 8042 output port */
+ kbdc8042.operation_write_state = 1;
+ break;
+ case 0xd2:
+ /* write keyboard output register; on PS/2 systems next port 60h
+ * write is written to port 60h output register as if initiated
+ * by a device; invokes interrupt if enabled */
+ kbdc8042.operation_write_state = 2;
+ kbdc8042.send_to_mouse = 0;
+ break;
+ case 0xd3:
+ /* write auxillary output register; on PS/2 systems next port 60h
+ * write is written to port 60h input register as if initiated
+ * by a device; invokes interrupt if enabled */
+ kbdc8042.operation_write_state = 3;
+ kbdc8042.send_to_mouse = 1;
+ break;
+ case 0xd4:
+ /* write auxillary device; on PS/2 systems the next data byte
+ * written to input register a port at 60h is sent to the
+ * auxiliary device */
+ kbdc8042.operation_write_state = 4;
+ break;
+ case 0xe0:
+ /* read test inputs; read T1/T0 test inputs into bit 1/0 */
+ at_8042_receive(space->machine(), 0x00);
+ break;
+
+ case 0xf0:
+ case 0xf2:
+ case 0xf4:
+ case 0xf6:
+ case 0xf8:
+ case 0xfa:
+ case 0xfc:
+ case 0xfe:
+ /* Commands 0xF0...0xFF causes certain output lines to be pulsed
+ * low for six milliseconds. The bits pulsed low correspond to
+ * the bits low set in the command byte. The only pulse that has
+ * an effect currently is bit 0, which pulses the CPU's reset line
+ */
+ device_set_input_line(space->machine().firstcpu, INPUT_LINE_RESET, PULSE_LINE);
+ at_8042_set_outport(space->machine(), kbdc8042.outport | 0x02, 0);
+ break;
+ }
+ kbdc8042.sending = 1;
+ break;
+ }
+}
+
+
+
+READ32_HANDLER( kbdc8042_32le_r )
+{
+ return read32le_with_read8_handler(kbdc8042_8_r, space, offset, mem_mask);
+}
+
+
+
+WRITE32_HANDLER( kbdc8042_32le_w )
+{
+ write32le_with_write8_handler(kbdc8042_8_w, space, offset, data, mem_mask);
+}
+
+
+
+READ64_HANDLER( kbdc8042_64be_r )
+{
+ return read64be_with_read8_handler(kbdc8042_8_r, space, offset, mem_mask);
+}
+
+
+
+WRITE64_HANDLER( kbdc8042_64be_w )
+{
+ write64be_with_write8_handler(kbdc8042_8_w, space, offset, data, mem_mask);
+}
diff --git a/trunk/src/emu/machine/8042kbdc.h b/trunk/src/emu/machine/8042kbdc.h
new file mode 100644
index 00000000000..35dc301d570
--- /dev/null
+++ b/trunk/src/emu/machine/8042kbdc.h
@@ -0,0 +1,41 @@
+/**********************************************************************
+
+ 8042 Keyboard Controller Emulation
+
+ This is the keyboard controller used in the IBM AT and further
+ models. It is a popular controller for PC style keyboards
+
+**********************************************************************/
+
+#ifndef KBDC8042_H
+#define KBDC8042_H
+
+typedef enum
+{
+ KBDC8042_STANDARD,
+ KBDC8042_PS2, /* another timing of integrated controller */
+ KBDC8042_AT386 /* hack for at386 driver */
+} kbdc8042_type_t;
+
+
+struct kbdc8042_interface
+{
+ kbdc8042_type_t type;
+ void (*set_gate_a20)(running_machine &machine, int a20);
+ void (*keyboard_interrupt)(running_machine &machine, int state);
+ int (*get_out2)(running_machine &machine);
+};
+
+
+
+void kbdc8042_init(running_machine &machine, const struct kbdc8042_interface *intf);
+
+READ8_HANDLER(kbdc8042_8_r);
+WRITE8_HANDLER(kbdc8042_8_w);
+READ32_HANDLER(kbdc8042_32le_r);
+WRITE32_HANDLER(kbdc8042_32le_w);
+READ64_HANDLER(kbdc8042_64be_r);
+WRITE64_HANDLER(kbdc8042_64be_w);
+
+#endif /* KBDC8042_H */
+
diff --git a/trunk/src/emu/machine/8237dma.c b/trunk/src/emu/machine/8237dma.c
new file mode 100644
index 00000000000..c49650987e7
--- /dev/null
+++ b/trunk/src/emu/machine/8237dma.c
@@ -0,0 +1,711 @@
+/**********************************************************************
+
+ 8237 DMA interface and emulation
+
+ The DMA works like this:
+ (summarized from http://www.infran.ru/TechInfo/BSD/handbook258.html#410)
+
+ 1. The device asserts the DRQn line
+ 2. The DMA clears the TC (terminal count) line
+ 3. The DMA asserts the CPU's HRQ (halt request) line
+ 4. Upon acknowledgement of the halt, the DMA will let the device
+ know that it needs to send information by asserting the DACKn
+ line
+ 5. The DMA will read the byte from the device
+ 6. The device clears the DRQn line
+ 7. The DMA clears the CPU's HRQ line
+ 8. (steps 3-7 are repeated for every byte in the chain)
+
+**********************************************************************/
+
+#include "emu.h"
+#include "memconv.h"
+#include "8237dma.h"
+#include "devhelpr.h"
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define DMA_MODE_CHANNEL(mode) ((mode) & 0x03)
+#define DMA_MODE_OPERATION(mode) ((mode) & 0x0c)
+#define DMA_MODE_AUTO_INIT(mode) ((mode) & 0x10)
+#define DMA_MODE_DIRECTION(mode) ((mode) & 0x20)
+#define DMA_MODE_TRANSFERMODE(mode) ((mode) & 0xc0)
+
+#define DMA8237_VERIFY_TRANSFER 0x00
+#define DMA8237_WRITE_TRANSFER 0x04
+#define DMA8237_READ_TRANSFER 0x08
+#define DMA8237_ILLEGAL_TRANSFER 0x0c
+
+#define DMA8237_DEMAND_MODE 0x00
+#define DMA8237_SINGLE_MODE 0x40
+#define DMA8237_BLOCK_MODE 0x80
+#define DMA8237_CASCADE_MODE 0xc0
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type I8237 = &device_creator<i8237_device>;
+
+//-------------------------------------------------
+// i8237_device - constructor
+//-------------------------------------------------
+
+i8237_device::i8237_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, I8237, "Intel 8237", tag, owner, clock)
+{
+}
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void i8237_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const i8237_interface *intf = reinterpret_cast<const i8237_interface *>(static_config());
+ if (intf != NULL)
+ {
+ *static_cast<i8237_interface *>(this) = *intf;
+ }
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_out_hrq_cb, 0, sizeof(m_out_hrq_cb));
+ memset(&m_out_eop_cb, 0, sizeof(m_out_eop_cb));
+ memset(&m_in_memr_cb, 0, sizeof(m_in_memr_cb));
+ memset(&m_out_memw_cb, 0, sizeof(m_out_memw_cb));
+ memset(&m_in_ior_cb[0], 0, sizeof(m_in_ior_cb[0]));
+ memset(&m_in_ior_cb[1], 0, sizeof(m_in_ior_cb[1]));
+ memset(&m_in_ior_cb[2], 0, sizeof(m_in_ior_cb[2]));
+ memset(&m_in_ior_cb[3], 0, sizeof(m_in_ior_cb[3]));
+ memset(&m_out_iow_cb[0], 0, sizeof(m_out_iow_cb[0]));
+ memset(&m_out_iow_cb[1], 0, sizeof(m_out_iow_cb[1]));
+ memset(&m_out_iow_cb[2], 0, sizeof(m_out_iow_cb[2]));
+ memset(&m_out_iow_cb[3], 0, sizeof(m_out_iow_cb[3]));
+ memset(&m_out_dack_cb[0], 0, sizeof(m_out_dack_cb[0]));
+ memset(&m_out_dack_cb[1], 0, sizeof(m_out_dack_cb[1]));
+ memset(&m_out_dack_cb[2], 0, sizeof(m_out_dack_cb[2]));
+ memset(&m_out_dack_cb[3], 0, sizeof(m_out_dack_cb[3]));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void i8237_device::device_start()
+{
+ /* resolve callbacks */
+ m_out_hrq_func.resolve(m_out_hrq_cb, *this);
+ m_out_eop_func.resolve(m_out_eop_cb, *this);
+ m_in_memr_func.resolve(m_in_memr_cb, *this);
+ m_out_memw_func.resolve(m_out_memw_cb, *this);
+
+ for (int i = 0; i < 4; i++)
+ {
+ m_chan[i].m_in_ior_func.resolve(m_in_ior_cb[i], *this);
+ m_chan[i].m_out_iow_func.resolve(m_out_iow_cb[i], *this);
+ m_chan[i].m_out_dack_func.resolve(m_out_dack_cb[i], *this);
+ }
+
+ m_timer = machine().scheduler().timer_alloc(FUNC(i8237_timerproc_callback), (void *)this);
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void i8237_device::device_reset()
+{
+ m_status = 0x0F;
+ m_eop = 1;
+ m_state = DMA8237_SI;
+ m_last_service_channel = 3;
+
+ m_command = 0;
+ m_drq = 0;
+ m_mask = 0x00;
+ m_status = 0x0F;
+ m_hrq = 0;
+ m_hlda = 0;
+ m_chan[0].m_mode = 0;
+ m_chan[1].m_mode = 0;
+ m_chan[2].m_mode = 0;
+ m_chan[3].m_mode = 0;
+
+ m_timer->adjust(attotime::from_hz(clock()), 0, attotime::from_hz(clock()));
+}
+
+
+void i8237_device::i8237_do_read()
+{
+ int channel = m_service_channel;
+
+ switch( DMA_MODE_OPERATION( m_chan[ channel ].m_mode ) )
+ {
+ case DMA8237_WRITE_TRANSFER:
+ m_temporary_data = m_chan[channel].m_in_ior_func(0);
+ break;
+ case DMA8237_READ_TRANSFER:
+ m_temporary_data = m_in_memr_func(m_chan[ channel ].m_address);
+ break;
+ case DMA8237_VERIFY_TRANSFER:
+ case DMA8237_ILLEGAL_TRANSFER:
+ break;
+ }
+}
+
+
+void i8237_device::i8237_do_write()
+{
+ int channel = m_service_channel;
+
+ switch( DMA_MODE_OPERATION( m_chan[ channel ].m_mode ) )
+ {
+ case DMA8237_WRITE_TRANSFER:
+ m_out_memw_func(m_chan[ channel ].m_address, m_temporary_data);
+ break;
+ case DMA8237_READ_TRANSFER:
+ m_chan[channel].m_out_iow_func(0, m_temporary_data);
+ break;
+ case DMA8237_VERIFY_TRANSFER:
+ case DMA8237_ILLEGAL_TRANSFER:
+ break;
+ }
+}
+
+
+void i8237_device::i8237_advance()
+{
+ int channel = m_service_channel;
+ int mode = m_chan[channel].m_mode;
+
+ switch ( DMA_MODE_OPERATION( mode ) )
+ {
+ case DMA8237_VERIFY_TRANSFER:
+ case DMA8237_WRITE_TRANSFER:
+ case DMA8237_READ_TRANSFER:
+ m_chan[channel].m_high_address_changed = 0;
+
+ if ( DMA_MODE_DIRECTION( mode ) )
+ {
+ m_chan[channel].m_address -= 1;
+ if ( ( m_chan[channel].m_address & 0xFF ) == 0xFF )
+ {
+ m_chan[channel].m_high_address_changed = 1;
+ }
+ }
+ else
+ {
+ m_chan[channel].m_address += 1;
+ if ( ( m_chan[channel].m_address & 0xFF ) == 0x00 )
+ {
+ m_chan[channel].m_high_address_changed = 1;
+ }
+ }
+
+ m_chan[channel].m_count--;
+
+ if ( m_chan[channel].m_count == 0xFFFF )
+ {
+ /* Set TC bit for this channel */
+ m_status |= ( 0x01 << channel );
+
+ if ( DMA_MODE_AUTO_INIT( mode ) )
+ {
+ m_chan[channel].m_address = m_chan[channel].m_base_address;
+ m_chan[channel].m_count = m_chan[channel].m_base_count;
+ m_chan[channel].m_high_address_changed = 1;
+ }
+ else
+ {
+ m_mask |= ( 0x01 << channel );
+ }
+ }
+ break;
+ case DMA8237_ILLEGAL_TRANSFER:
+ break;
+ }
+}
+
+
+void i8237_device::i8327_set_dack(int channel)
+{
+ for (int i = 0; i < 4; i++)
+ {
+ int state = (i == channel) ^ !BIT(m_command, 7);
+
+ m_chan[i].m_out_dack_func(state);
+ }
+}
+
+
+TIMER_CALLBACK( i8237_device::i8237_timerproc_callback )
+{
+ reinterpret_cast<i8237_device*>(ptr)->i8237_timerproc();
+}
+
+
+void i8237_device::i8237_timerproc()
+{
+ /* Check if operation is disabled */
+ if ( m_command & 0x04 )
+ {
+ return;
+ }
+
+ switch ( m_state )
+ {
+
+ case DMA8237_SI:
+ {
+ /* Make sure EOP is high */
+ if ( !m_eop )
+ {
+ m_eop = 1;
+ m_out_eop_func(m_eop ? ASSERT_LINE : CLEAR_LINE);
+ }
+
+ /* Check if a new DMA request has been received. */
+ /* Bit 6 of the command register determines whether the DREQ signals are active
+ high or active low. */
+ UINT16 pending_request = ( ( m_command & 0x40 ) ? ~m_drq : m_drq ) & ~m_mask;
+
+ if ( pending_request & 0x0f )
+ {
+ int prio_channel = 0;
+
+ /* Determine the channel that should be serviced */
+ int channel = ( m_command & 0x10 ) ? m_last_service_channel : 3;
+ for ( int i = 0; i < 4; i++ )
+ {
+ if ( pending_request & ( 1 << channel ) )
+ {
+ prio_channel = channel;
+ }
+ channel = ( channel - 1 ) & 0x03;
+ }
+
+ /* Store the channel we will be servicing and go to the next state */
+ m_service_channel = prio_channel;
+ m_last_service_channel = prio_channel;
+
+ m_hrq = 1;
+ m_out_hrq_func(m_hrq);
+ m_state = DMA8237_S0;
+
+ m_timer->enable( true );
+ }
+ else if (m_command == 3 && (m_drq & 1))
+ {
+ /* Memory-to-memory transfers */
+ m_hlda = 1;
+ m_state = DMA8237_S0;
+ }
+ else
+ {
+ m_timer->enable( false );
+ }
+ break;
+ }
+
+ case DMA8237_S0:
+ /* S0 is the first of the DMA service. We have requested a hold but are waiting
+ for confirmation. */
+ if ( m_hlda )
+ {
+ if ( DMA_MODE_TRANSFERMODE( m_chan[m_service_channel].m_mode ) == DMA8237_CASCADE_MODE )
+ {
+ /* Cascade Mode, set DACK */
+ i8327_set_dack(m_service_channel);
+
+ /* Wait until peripheral is done */
+ m_state = DMA8237_SC;
+ }
+ else
+ {
+ if ( m_command & 0x01 )
+ {
+ /* Memory-to-memory transfers */
+ m_state = DMA8237_S11;
+ }
+ else
+ {
+ /* Regular transfers */
+ m_state = DMA8237_S1;
+ }
+ }
+ }
+ break;
+
+ case DMA8237_SC: /* Cascade mode, waiting until peripheral is done */
+ if ( ! ( m_drq & ( 0x01 << m_service_channel ) ) )
+ {
+ m_hrq = 0;
+ m_hlda = 0;
+ m_out_hrq_func(m_hrq);
+ m_state = DMA8237_SI;
+
+ /* Clear DACK */
+ i8327_set_dack(-1);
+ }
+
+ /* Not sure if this is correct, documentation is not clear */
+ /* Check if EOP output needs to be asserted */
+ if ( m_status & ( 0x01 << m_service_channel ) )
+ {
+ m_eop = 0;
+ m_out_eop_func(m_eop ? ASSERT_LINE : CLEAR_LINE);
+ }
+ break;
+
+ case DMA8237_S1: /* Output A8-A15 */
+ m_state = DMA8237_S2;
+ break;
+
+ case DMA8237_S2: /* Output A7-A0 */
+ /* set DACK */
+ i8327_set_dack(m_service_channel);
+
+ /* Check for compressed timing */
+ if ( m_command & 0x08 )
+ {
+ m_state = DMA8237_S4;
+ }
+ else
+ {
+ m_state = DMA8237_S3;
+ }
+ break;
+
+ case DMA8237_S3: /* Initiate read */
+ i8237_do_read();
+ m_state = DMA8237_S4;
+ break;
+
+ case DMA8237_S4: /* Perform read/write */
+ /* Perform read when in compressed timing mode */
+ if ( m_command & 0x08 )
+ {
+ i8237_do_read();
+ }
+
+ /* Perform write */
+ i8237_do_write();
+
+
+ /* Advance */
+ i8237_advance();
+
+ {
+ int channel = m_service_channel;
+
+ switch( DMA_MODE_TRANSFERMODE( m_chan[channel].m_mode ) )
+ {
+ case DMA8237_DEMAND_MODE:
+ /* Check for terminal count or EOP signal or DREQ begin de-asserted */
+ if ( ( m_status & ( 0x01 << channel ) ) || !m_eop || !( m_drq & ( 0x01 << channel ) ) )
+ {
+ m_hrq = 0;
+ m_hlda = 0;
+ m_out_hrq_func(m_hrq);
+ m_state = DMA8237_SI;
+ }
+ else
+ {
+ m_state = m_chan[channel].m_high_address_changed ? DMA8237_S1 : DMA8237_S2;
+ }
+ break;
+
+ case DMA8237_SINGLE_MODE:
+ m_hrq = 0;
+ m_hlda = 0;
+ m_out_hrq_func(m_hrq);
+ m_state = DMA8237_SI;
+ break;
+
+ case DMA8237_BLOCK_MODE:
+ /* Check for terminal count or EOP signal */
+ if ( ( m_status & ( 0x01 << channel ) ) || !m_eop )
+ {
+ m_hrq = 0;
+ m_hlda = 0;
+ m_out_hrq_func(m_hrq);
+ m_state = DMA8237_SI;
+ }
+ else
+ {
+ m_state = m_chan[channel].m_high_address_changed ? DMA8237_S1 : DMA8237_S2;
+ }
+ break;
+ }
+
+ /* Check if EOP output needs to be asserted */
+ if ( m_status & ( 0x01 << channel ) )
+ {
+ m_eop = 0;
+ m_out_eop_func(m_eop ? ASSERT_LINE : CLEAR_LINE);
+ }
+ }
+
+ /* clear DACK */
+ if ( m_state == DMA8237_SI )
+ {
+ i8327_set_dack(-1);
+ }
+ break;
+
+ case DMA8237_S11: /* Output A8-A15 */
+
+// logerror("###### dma8237_timerproc %s: from %04x count=%x to %04x count=%x\n", tag(),
+// m_chan[0].m_address, m_chan[0].m_count,
+// m_chan[1].m_address, m_chan[1].m_count);
+
+ // FIXME: this will copy bytes correct, but not 16 bit words
+ m_temporary_data = m_in_memr_func(m_chan[0].m_address);
+ m_out_memw_func(m_chan[1].m_address, m_temporary_data);
+
+ m_service_channel = 0;
+
+ /* Advance */
+ i8237_advance();
+
+ // advance destination channel as well
+ m_chan[1].m_count--;
+ m_chan[1].m_address++;
+
+ if (m_chan[0].m_count == 0xFFFF || m_chan[1].m_count == 0xFFFF) {
+ m_hrq = 0;
+ m_hlda = 0;
+ m_out_hrq_func(m_hrq);
+ m_state = DMA8237_SI;
+ m_status |= 3; // set TC for channel 0 and 1
+ m_drq &= ~3; // clear drq for channel 0 and 1
+
+ // logerror("!!! dma8237_timerproc DMA8237_S11 %s: m_drq=%x m_command=%x\n", tag(), m_drq, m_command);
+ }
+ break;
+ }
+}
+
+
+READ8_DEVICE_HANDLER_TRAMPOLINE(i8237, i8237_r)
+{
+ UINT8 data = 0xFF;
+
+ offset &= 0x0F;
+
+ switch(offset) {
+ case 0:
+ case 2:
+ case 4:
+ case 6:
+ /* DMA address register */
+ data = m_chan[offset / 2].m_address >> (m_msb ? 8 : 0);
+ m_msb ^= 1;
+ break;
+
+ case 1:
+ case 3:
+ case 5:
+ case 7:
+ /* DMA count register */
+ data = m_chan[offset / 2].m_count >> (m_msb ? 8 : 0);
+ m_msb ^= 1;
+ break;
+
+ case 8:
+ /* DMA status register */
+ data = (UINT8) m_status;
+
+ /* TC bits are cleared on a status read */
+ m_status &= 0xF0;
+ break;
+
+ case 10:
+ /* DMA mask register */
+ data = m_mask;
+ break;
+
+ case 13:
+ /* DMA master clear */
+ data = m_temp;
+ break;
+
+ case 9: /* DMA write request register */
+ case 11: /* DMA mode register */
+ case 12: /* DMA clear byte pointer flip-flop */
+ case 14: /* DMA clear mask register */
+ case 15: /* DMA write mask register */
+ data = 0xFF;
+ break;
+ }
+
+ return data;
+}
+
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(i8237, i8237_w)
+{
+ offset &= 0x0F;
+
+// logerror("i8237_w: offset = %02x, data = %02x\n", offset, data );
+
+ switch(offset) {
+ case 0:
+ case 2:
+ case 4:
+ case 6:
+ {
+ /* DMA address register */
+ int channel = offset / 2;
+ if (m_msb)
+ {
+ m_chan[channel].m_base_address = ( m_chan[channel].m_base_address & 0x00FF ) | ( data << 8 );
+ m_chan[channel].m_address = ( m_chan[channel].m_address & 0x00FF ) | ( data << 8 );
+ }
+ else
+ {
+ m_chan[channel].m_base_address = ( m_chan[channel].m_base_address & 0xFF00 ) | data;
+ m_chan[channel].m_address = ( m_chan[channel].m_address & 0xFF00 ) | data;
+ }
+ m_msb ^= 1;
+ break;
+ }
+
+ case 1:
+ case 3:
+ case 5:
+ case 7:
+ {
+ /* DMA count register */
+ int channel = offset / 2;
+ if (m_msb)
+ {
+ m_chan[channel].m_base_count = ( m_chan[channel].m_base_count & 0x00FF ) | ( data << 8 );
+ m_chan[channel].m_count = ( m_chan[channel].m_count & 0x00FF ) | ( data << 8 );
+ }
+ else
+ {
+ m_chan[channel].m_base_count = ( m_chan[channel].m_base_count & 0xFF00 ) | data;
+ m_chan[channel].m_count = ( m_chan[channel].m_count & 0xFF00 ) | data;
+ }
+ m_msb ^= 1;
+ break;
+ }
+
+ case 8:
+ /* DMA command register */
+ m_command = data;
+ m_timer->enable( ( m_command & 0x04 ) ? 0 : 1 );
+ break;
+
+ case 9:
+ {
+ /* DMA request register */
+ int channel = DMA_MODE_CHANNEL(data);
+ if ( data & 0x04 )
+ {
+ m_drq |= 0x01 << channel;
+ m_timer->enable( ( m_command & 0x04 ) ? 0 : 1 );
+ }
+ else
+ {
+ m_status &= ~ ( 0x10 << channel );
+ m_drq &= ~ ( 0x01 << channel );
+ }
+ break;
+ }
+
+ case 10:
+ {
+ /* DMA mask register */
+ int channel = DMA_MODE_CHANNEL(data);
+ if (data & 0x04)
+ {
+ m_mask |= 0x11 << channel;
+ }
+ else
+ {
+ m_mask &= ~(0x11 << channel);
+ }
+ break;
+ }
+
+ case 11:
+ {
+ /* DMA mode register */
+ int channel = DMA_MODE_CHANNEL(data);
+ m_chan[channel].m_mode = data;
+ /* Apparently mode writes also clear the TC bit(?) */
+ m_status &= ~ ( 1 << channel );
+ break;
+ }
+
+ case 12:
+ /* DMA clear byte pointer flip-flop */
+ m_temp = data;
+ m_msb = 0;
+ break;
+
+ case 13:
+ /* DMA master clear */
+ m_msb = 0;
+ m_mask = 0x0f;
+ m_state = DMA8237_SI;
+ m_status &= 0xF0;
+ m_temp = 0;
+ break;
+
+ case 14:
+ /* DMA clear mask register */
+ m_mask &= ~data;
+ m_mask = 0;
+ break;
+
+ case 15:
+ /* DMA write mask register */
+ m_mask = data & 0x0f;
+ break;
+ }
+}
+
+
+void i8237_device::i8237_drq_write(int channel, int state)
+{
+ if (state)
+ {
+ m_drq |= ( 0x01 << channel );
+ }
+ else
+ {
+ m_drq &= ~( 0x01 << channel );
+ }
+
+ m_timer->enable( ( m_command & 0x04 ) ? 0 : 1 );
+
+}
+
+
+
+/***************************************************************************
+ TRAMPOLINES
+***************************************************************************/
+
+WRITE_LINE_DEVICE_HANDLER( i8237_hlda_w ) { downcast<i8237_device*>(device)->i8237_hlda_w(state); }
+WRITE_LINE_DEVICE_HANDLER( i8237_ready_w ) { }
+WRITE_LINE_DEVICE_HANDLER( i8237_dreq0_w ) { downcast<i8237_device*>(device)->i8237_drq_write(0, state); }
+WRITE_LINE_DEVICE_HANDLER( i8237_dreq1_w ) { downcast<i8237_device*>(device)->i8237_drq_write(1, state); }
+WRITE_LINE_DEVICE_HANDLER( i8237_dreq2_w ) { downcast<i8237_device*>(device)->i8237_drq_write(2, state); }
+WRITE_LINE_DEVICE_HANDLER( i8237_dreq3_w ) { downcast<i8237_device*>(device)->i8237_drq_write(3, state); }
+WRITE_LINE_DEVICE_HANDLER( i8237_eop_w ) { }
diff --git a/trunk/src/emu/machine/8237dma.h b/trunk/src/emu/machine/8237dma.h
new file mode 100644
index 00000000000..864aba746ad
--- /dev/null
+++ b/trunk/src/emu/machine/8237dma.h
@@ -0,0 +1,210 @@
+/***************************************************************************
+
+ Intel 8237 Programmable DMA Controller emulation
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+****************************************************************************
+ _____ _____
+ _I/OR 1 |* \_/ | 40 A7
+ _I/OW 2 | | 39 A6
+ _MEMR 3 | | 38 A5
+ _MEMW 4 | | 37 A4
+ 5 | | 36 _EOP
+ READY 6 | | 35 A3
+ HLDA 7 | | 34 A2
+ ADSTB 8 | | 33 A1
+ AEN 9 | | 32 A0
+ HRQ 10 | 8237 | 31 Vcc
+ _CS 11 | | 30 DB0
+ CLK 12 | | 29 DB1
+ RESET 13 | | 28 DB2
+ DACK2 14 | | 27 DB3
+ DACK3 15 | | 26 DB4
+ DREQ3 16 | | 25 DACK0
+ DREQ2 17 | | 24 DACK1
+ DREQ1 18 | | 23 DB5
+ DREQ0 19 | | 22 DB6
+ GND 20 |_____________| 21 DB7
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __I8237__
+#define __I8237__
+
+#include "emu.h"
+
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_I8237_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD(_tag, I8237, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define I8237_INTERFACE(_name) \
+ const i8237_interface (_name) =
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+
+// ======================> i8237_interface
+
+struct i8237_interface
+{
+ devcb_write_line m_out_hrq_cb;
+ devcb_write_line m_out_eop_cb;
+
+ /* accessors to main memory */
+ devcb_read8 m_in_memr_cb;
+ devcb_write8 m_out_memw_cb;
+
+ /* channel accessors */
+ devcb_read8 m_in_ior_cb[4];
+ devcb_write8 m_out_iow_cb[4];
+ devcb_write_line m_out_dack_cb[4];
+};
+
+
+
+// ======================> i8237_device
+
+class i8237_device : public device_t,
+ public i8237_interface
+{
+public:
+ // construction/destruction
+ i8237_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ /* register access */
+ UINT8 i8237_r(UINT32 offset);
+ void i8237_w(UINT32 offset, UINT8 data);
+
+ /* hold acknowledge */
+ void i8237_hlda_w(UINT8 state) { m_hlda = state; }
+
+ /* data request */
+ void i8237_drq_write(int channel, int state);
+
+ void i8237_timerproc();
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_post_load() { }
+ virtual void device_clock_changed() { }
+
+ static TIMER_CALLBACK( i8237_timerproc_callback );
+ static TIMER_CALLBACK( receive_event_callback );
+
+private:
+
+ void i8237_do_read();
+ void i8237_do_write();
+ void i8237_advance();
+ void i8327_set_dack(int channel);
+
+ /* States that the i8237 device can be in */
+ enum dma8237_state
+ {
+ DMA8237_SI, /* Idle state */
+ DMA8237_S0, /* HRQ has been triggered, waiting to receive HLDA */
+ // DMA8237_SW, /* Wait state */
+ DMA8237_SC, /* Cascade mode, waiting for peripheral */
+
+ /* Normal transfer states */
+ DMA8237_S1, /* Output A8-A15; only used when A8-A15 really needs to be output */
+ DMA8237_S2, /* Output A0-A7 */
+ DMA8237_S3, /* Initiate read; skipped in compressed timing. On the S2->S3 transition DACK is set. */
+ DMA8237_S4, /* Perform read/write */
+
+ /* Memory to memory transfer states */
+ DMA8237_S11, /* Output A8-A15 */
+ // DMA8237_S12, /* Output A0-A7 */
+ // DMA8237_S13, /* Initiate read */
+ // DMA8237_S14, /* Perform read/write */
+ // DMA8237_S21, /* Output A8-A15 */
+ // DMA8237_S22, /* Output A0-A7 */
+ // DMA8237_S23, /* Initiate read */
+ // DMA8237_S24, /* Perform read/write */
+ };
+
+ devcb_resolved_write_line m_out_hrq_func;
+ devcb_resolved_write_line m_out_eop_func;
+ devcb_resolved_read8 m_in_memr_func;
+ devcb_resolved_write8 m_out_memw_func;
+
+ emu_timer *m_timer;
+
+ struct
+ {
+ devcb_resolved_read8 m_in_ior_func;
+ devcb_resolved_write8 m_out_iow_func;
+ devcb_resolved_write_line m_out_dack_func;
+ UINT16 m_base_address;
+ UINT16 m_base_count;
+ UINT16 m_address;
+ UINT16 m_count;
+ UINT8 m_mode;
+ int m_high_address_changed;
+ } m_chan[4];
+
+ UINT32 m_msb : 1;
+ UINT32 m_eop : 1;
+ UINT8 m_temp;
+ UINT8 m_temporary_data;
+ UINT8 m_command;
+ UINT8 m_drq;
+ UINT8 m_mask;
+ UINT8 m_hrq;
+ UINT8 m_hlda;
+
+ /* bits 0- 3 : Terminal count for channels 0-3
+ * bits 4- 7 : Transfer in progress for channels 0-3 */
+ UINT8 m_status;
+
+ dma8237_state m_state; /* State the device is currently in */
+ int m_service_channel; /* Channel we will be servicing */
+ int m_last_service_channel; /* Previous channel we serviced; used to determine channel priority. */
+};
+
+
+// device type definition
+extern const device_type I8237;
+
+
+
+/***************************************************************************
+ PROTOTYPES
+***************************************************************************/
+
+/* register access */
+READ8_DEVICE_HANDLER( i8237_r );
+WRITE8_DEVICE_HANDLER( i8237_w );
+
+/* hold acknowledge */
+WRITE_LINE_DEVICE_HANDLER( i8237_hlda_w );
+
+/* ready */
+WRITE_LINE_DEVICE_HANDLER( i8237_ready_w );
+
+/* data request */
+WRITE_LINE_DEVICE_HANDLER( i8237_dreq0_w );
+WRITE_LINE_DEVICE_HANDLER( i8237_dreq1_w );
+WRITE_LINE_DEVICE_HANDLER( i8237_dreq2_w );
+WRITE_LINE_DEVICE_HANDLER( i8237_dreq3_w );
+
+/* end of process */
+WRITE_LINE_DEVICE_HANDLER( i8237_eop_w );
+
+#endif
diff --git a/trunk/src/emu/machine/8255ppi.c b/trunk/src/emu/machine/8255ppi.c
new file mode 100644
index 00000000000..a3028cca15d
--- /dev/null
+++ b/trunk/src/emu/machine/8255ppi.c
@@ -0,0 +1,666 @@
+/*********************************************************************
+
+ 8255ppi.c
+
+ Intel 8255 PPI I/O chip
+
+
+ NOTE: When port is input, then data present on the ports
+ outputs is 0xff
+
+ The 8255 PPI has three basic modes:
+
+ Mode 0: Basic Input/Output
+ Mode 1: Strobed Input/Output
+ Mode 2: Strobed Bi-directional Bus
+
+ Control Word:
+
+ bit 7 - Mode set flag (1=active)
+ bit 6-5 - Group A Mode selection
+ 00 - Mode 0
+ 01 - Mode 1
+ 1x - Mode 2
+ bit 4 - Port A direction (1=input 0=output)
+ bit 3 - Port C upper direction (1=input 0=output)
+ bit 2 - Group B Mode selection
+ 0 - Mode 0
+ 1 - Mode 1
+ bit 1 - Port B direction (1=input 0=output)
+ bit 0 - Port C lower direction (1=input 0=output)
+
+ Port A and Port C upper are in group A, and Port B and Port C lower
+ are in group B
+
+
+ Mode 0: Basic Input/Output
+ In Mode 0, each of the ports (A, B and C) operate as independent
+ ports for whom direction can be set independently.
+
+ Port C Usage In Mode 0:
+
+ bits 7-4 Input/Output A (direction specified by ctrl bit 3)
+ bits 3-0 Input/Output B (direction specified by ctrl bit 0)
+
+ Mode 1: Strobed Input/Output
+ In Mode 1, Port A and Port B use their resepective parts of Port C to
+ either generate or accept handshaking signals. The STB (strobe) input
+ "loads" data into the port, and the IBF (input buffer full) output is
+ then asserted, and the INTR (interrupt request) output is triggered if
+ interrupts are enabled. Bits 7-6 of Port C remain usable as
+ conventional IO.
+
+ Group A Port C Usage In Mode 1:
+
+ bits 7-6 Input/Output (direction specified by ctrl bit 3)
+ bit 5 IBFa (input buffer full A) output
+ bit 4 !STBa (strobe A) input
+ bit 3 INTRa (interrupt request A) output
+
+ Group B Port C Usage In Mode 1:
+
+ bit 2 !STBb (strobe B) input
+ bit 1 IBFb (input buffer full B) output
+ bit 0 INTRb (interrupt request B) output
+
+
+ Mode 2: Strobed Bi-directional Bus
+ Mode 2 is used to implement a two way handshaking bus.
+
+ When data is written to port A, the OBF (output buffer full) output
+ will be asserted by the PPI. However, port A will not be asserted
+ unless the ACK input is asserted, otherwise port A will be high
+ impedence.
+
+ The STB input and IBF output behaves similar to how it does under mode
+ 1. Bits 2-0 of Port C remain usable as conventional IO.
+
+ Port C Usage In Mode 2:
+
+ bit 7 !OBFa (output buffer full A) output
+ bit 6 !ACKa (acknowledge A) input
+ bit 5 IBFa (interrupt buffer full A) output
+ bit 4 !STBa (strobe A) input
+ bit 3 INTRa (interrupt A) output
+ bit 2-0 Reserved by Group B
+
+ KT 10/01/2000 - Added bit set/reset feature for control port
+ - Added more accurate port i/o data handling
+ - Added output reset when control mode is programmed
+
+*********************************************************************/
+
+#include "emu.h"
+#include "8255ppi.h"
+#include "devhelpr.h"
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type PPI8255 = &device_creator<ppi8255_device>;
+
+//-------------------------------------------------
+// ppi8255_device - constructor
+//-------------------------------------------------
+
+ppi8255_device::ppi8255_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, PPI8255, "Intel PPI8255", tag, owner, clock),
+ m_control(0)
+{
+
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void ppi8255_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const ppi8255_interface *intf = reinterpret_cast<const ppi8255_interface *>(static_config());
+ if (intf != NULL)
+ {
+ *static_cast<ppi8255_interface *>(this) = *intf;
+ }
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_port_a_read, 0, sizeof(m_port_a_read));
+ memset(&m_port_b_read, 0, sizeof(m_port_b_read));
+ memset(&m_port_c_read, 0, sizeof(m_port_c_read));
+ memset(&m_port_a_write, 0, sizeof(m_port_a_write));
+ memset(&m_port_b_write, 0, sizeof(m_port_b_write));
+ memset(&m_port_c_write, 0, sizeof(m_port_c_write));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void ppi8255_device::device_start()
+{
+ m_port_read[0].resolve(m_port_a_read, *this);
+ m_port_read[1].resolve(m_port_b_read, *this);
+ m_port_read[2].resolve(m_port_c_read, *this);
+
+ m_port_write[0].resolve(m_port_a_write, *this);
+ m_port_write[1].resolve(m_port_b_write, *this);
+ m_port_write[2].resolve(m_port_c_write, *this);
+
+ /* register for state saving */
+ save_item(NAME(m_group_a_mode));
+ save_item(NAME(m_group_b_mode));
+ save_item(NAME(m_port_a_dir));
+ save_item(NAME(m_port_b_dir));
+ save_item(NAME(m_port_ch_dir));
+ save_item(NAME(m_port_cl_dir));
+ save_item(NAME(m_obf_a));
+ save_item(NAME(m_obf_b));
+ save_item(NAME(m_ibf_a));
+ save_item(NAME(m_ibf_b));
+ save_item(NAME(m_inte_a));
+ save_item(NAME(m_inte_b));
+ save_item(NAME(m_inte_1));
+ save_item(NAME(m_inte_2));
+ save_item(NAME(m_in_mask));
+ save_item(NAME(m_out_mask));
+ save_item(NAME(m_read));
+ save_item(NAME(m_latch));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void ppi8255_device::device_reset()
+{
+ m_group_a_mode = 0;
+ m_group_b_mode = 0;
+ m_port_a_dir = 0;
+ m_port_b_dir = 0;
+ m_port_ch_dir = 0;
+ m_port_cl_dir = 0;
+ m_obf_a = m_ibf_a = 0;
+ m_obf_b = m_ibf_b = 0;
+ m_inte_a = m_inte_b = m_inte_1 = m_inte_2 = 0;
+
+ for (int i = 0; i < 3; i++)
+ {
+ m_in_mask[i] = m_out_mask[i] = m_read[i] = m_latch[i] = m_output[i] = 0;
+ }
+
+ set_mode(0x9b, 0); /* Mode 0, all ports set to input */
+}
+
+
+void ppi8255_device::ppi8255_get_handshake_signals(int is_read, UINT8 *result)
+{
+ UINT8 handshake = 0x00;
+ UINT8 mask = 0x00;
+
+ /* group A */
+ if (m_group_a_mode == 1)
+ {
+ if (m_port_a_dir)
+ {
+ handshake |= m_ibf_a ? 0x20 : 0x00;
+ handshake |= (m_ibf_a && m_inte_a) ? 0x08 : 0x00;
+ mask |= 0x28;
+ }
+ else
+ {
+ handshake |= m_obf_a ? 0x00 : 0x80;
+ handshake |= (m_obf_a && m_inte_a) ? 0x08 : 0x00;
+ mask |= 0x88;
+ }
+ }
+ else if (m_group_a_mode == 2)
+ {
+ handshake |= m_obf_a ? 0x00 : 0x80;
+ handshake |= m_ibf_a ? 0x20 : 0x00;
+ handshake |= ((m_obf_a && m_inte_1) || (m_ibf_a && m_inte_2)) ? 0x08 : 0x00;
+ mask |= 0xA8;
+ }
+
+ /* group B */
+ if (m_group_b_mode == 1)
+ {
+ if (m_port_b_dir)
+ {
+ handshake |= m_ibf_b ? 0x02 : 0x00;
+ handshake |= (m_ibf_b && m_inte_b) ? 0x01 : 0x00;
+ mask |= 0x03;
+ }
+ else
+ {
+ handshake |= m_obf_b ? 0x00 : 0x02;
+ handshake |= (m_obf_b && m_inte_b) ? 0x01 : 0x00;
+ mask |= 0x03;
+ }
+ }
+
+ *result &= ~mask;
+ *result |= handshake & mask;
+}
+
+
+
+void ppi8255_device::ppi8255_input(int port, UINT8 data)
+{
+ int changed = 0;
+
+ m_read[port] = data;
+
+ /* port C is special */
+ if (port == 2)
+ {
+ if (((m_group_a_mode == 1) && (m_port_a_dir == 0)) || (m_group_a_mode == 2))
+ {
+ /* is !ACKA asserted? */
+ if (m_obf_a && !(data & 0x40))
+ {
+ m_obf_a = 0;
+ changed = 1;
+ }
+ }
+
+ if (((m_group_a_mode == 1) && (m_port_a_dir == 1)) || (m_group_a_mode == 2))
+ {
+ /* is !STBA asserted? */
+ if (!m_ibf_a && !(data & 0x10))
+ {
+ m_ibf_a = 1;
+ changed = 1;
+ }
+ }
+
+ if ((m_group_b_mode == 1) && (m_port_b_dir == 0))
+ {
+ /* is !ACKB asserted? */
+ if (m_obf_b && !(data & 0x04))
+ {
+ m_obf_b = 0;
+ changed = 1;
+ }
+ }
+
+ if ((m_group_b_mode == 1) && (m_port_b_dir == 1))
+ {
+ /* is !STBB asserted? */
+ if (!m_ibf_b && !(data & 0x04))
+ {
+ m_ibf_b = 1;
+ changed = 1;
+ }
+ }
+
+ if (changed)
+ {
+ ppi8255_write_port(2);
+ }
+ }
+}
+
+
+
+UINT8 ppi8255_device::ppi8255_read_port(int port)
+{
+ UINT8 result = 0x00;
+
+ if (m_in_mask[port])
+ {
+ ppi8255_input(port, m_port_read[port](0));
+ result |= m_read[port] & m_in_mask[port];
+ }
+ result |= m_latch[port] & m_out_mask[port];
+
+ switch (port)
+ {
+ case 0:
+ /* clear input buffer full flag */
+ m_ibf_a = 0;
+ break;
+
+ case 1:
+ /* clear input buffer full flag */
+ m_ibf_b = 0;
+ break;
+
+ case 2:
+ /* read special port 2 signals */
+ ppi8255_get_handshake_signals(1, &result);
+ break;
+ }
+
+ return result;
+}
+
+
+
+READ8_DEVICE_HANDLER_TRAMPOLINE(ppi8255, ppi8255_r)
+{
+ UINT8 result = 0;
+
+ offset %= 4;
+
+ switch(offset)
+ {
+ case 0: /* Port A read */
+ case 1: /* Port B read */
+ case 2: /* Port C read */
+ result = ppi8255_read_port(offset);
+ break;
+
+ case 3: /* Control word */
+ result = m_control;
+ break;
+ }
+
+ return result;
+}
+
+
+
+void ppi8255_device::ppi8255_write_port(int port)
+{
+ UINT8 write_data = m_latch[port] & m_out_mask[port];
+ write_data |= 0xFF & ~m_out_mask[port];
+
+ /* write out special port 2 signals */
+ if (port == 2)
+ {
+ ppi8255_get_handshake_signals(0, &write_data);
+ }
+
+ m_output[port] = write_data;
+ m_port_write[port](0, write_data);
+}
+
+
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(ppi8255, ppi8255_w)
+{
+ offset %= 4;
+
+ switch( offset )
+ {
+ case 0: /* Port A write */
+ case 1: /* Port B write */
+ case 2: /* Port C write */
+ m_latch[offset] = data;
+ ppi8255_write_port(offset);
+
+ switch(offset)
+ {
+ case 0:
+ if (!m_port_a_dir && (m_group_a_mode != 0))
+ {
+ m_obf_a = 1;
+ ppi8255_write_port(2);
+ }
+ break;
+
+ case 1:
+ if (!m_port_b_dir && (m_group_b_mode != 0))
+ {
+ m_obf_b = 1;
+ ppi8255_write_port(2);
+ }
+ break;
+ }
+ break;
+
+ case 3: /* Control word */
+ if (data & 0x80)
+ {
+ set_mode(data & 0x7f, 1);
+ }
+ else
+ {
+ /* bit set/reset */
+ int bit = (data >> 1) & 0x07;
+
+ if (data & 1)
+ {
+ m_latch[2] |= (1 << bit); /* set bit */
+ }
+ else
+ {
+ m_latch[2] &= ~(1 << bit); /* reset bit */
+ }
+
+ if (m_group_b_mode == 1)
+ {
+ if (bit == 2)
+ {
+ m_inte_b = data & 1;
+ }
+ }
+
+ if (m_group_a_mode == 1)
+ {
+ if (bit == 4 && m_port_a_dir)
+ {
+ m_inte_a = data & 1;
+ }
+ if (bit == 6 && !m_port_a_dir)
+ {
+ m_inte_a = data & 1;
+ }
+ }
+
+ if (m_group_a_mode == 2)
+ {
+ if (bit == 4)
+ {
+ m_inte_2 = data & 1;
+ }
+ if (bit == 6)
+ {
+ m_inte_1 = data & 1;
+ }
+ }
+
+ ppi8255_write_port(2);
+ }
+ break;
+ }
+}
+
+
+void ppi8255_device::set_mode(int data, int call_handlers)
+{
+ /* parse out mode */
+ m_group_a_mode = (data >> 5) & 3;
+ m_group_b_mode = (data >> 2) & 1;
+ m_port_a_dir = (data >> 4) & 1;
+ m_port_b_dir = (data >> 1) & 1;
+ m_port_ch_dir = (data >> 3) & 1;
+ m_port_cl_dir = (data >> 0) & 1;
+
+ /* normalize group_a_mode */
+ if (m_group_a_mode == 3)
+ {
+ m_group_a_mode = 2;
+ }
+
+ /* Port A direction */
+ if (m_group_a_mode == 2)
+ {
+ m_in_mask[0] = 0xFF;
+ m_out_mask[0] = 0xFF; /* bidirectional */
+ }
+ else
+ {
+ if (m_port_a_dir)
+ {
+ m_in_mask[0] = 0xFF;
+ m_out_mask[0] = 0x00; /* input */
+ }
+ else
+ {
+ m_in_mask[0] = 0x00;
+ m_out_mask[0] = 0xFF; /* output */
+ }
+ }
+
+ /* Port B direction */
+ if (m_port_b_dir)
+ {
+ m_in_mask[1] = 0xFF;
+ m_out_mask[1] = 0x00; /* input */
+ }
+ else
+ {
+ m_in_mask[1] = 0x00;
+ m_out_mask[1] = 0xFF; /* output */
+ }
+
+ /* Port C upper direction */
+ if (m_port_ch_dir)
+ {
+ m_in_mask[2] = 0xF0;
+ m_out_mask[2] = 0x00; /* input */
+ }
+ else
+ {
+ m_in_mask[2] = 0x00;
+ m_out_mask[2] = 0xF0; /* output */
+ }
+
+ /* Port C lower direction */
+ if (m_port_cl_dir)
+ {
+ m_in_mask[2] |= 0x0F; /* input */
+ }
+ else
+ {
+ m_out_mask[2] |= 0x0F; /* output */
+ }
+
+ /* now depending on the group modes, certain Port C lines may be replaced
+ * with varying control signals */
+ switch(m_group_a_mode)
+ {
+ case 0: /* Group A mode 0 */
+ /* no changes */
+ break;
+
+ case 1: /* Group A mode 1 */
+ /* bits 5-3 are reserved by Group A mode 1 */
+ m_in_mask[2] &= ~0x38;
+ m_out_mask[2] &= ~0x38;
+ break;
+
+ case 2: /* Group A mode 2 */
+ /* bits 7-3 are reserved by Group A mode 2 */
+ m_in_mask[2] &= ~0xF8;
+ m_out_mask[2] &= ~0xF8;
+ break;
+ }
+
+ switch(m_group_b_mode)
+ {
+ case 0: /* Group B mode 0 */
+ /* no changes */
+ break;
+
+ case 1: /* Group B mode 1 */
+ /* bits 2-0 are reserved by Group B mode 1 */
+ m_in_mask[2] &= ~0x07;
+ m_out_mask[2] &= ~0x07;
+ break;
+ }
+
+ /* KT: 25-Dec-99 - 8255 resets latches when mode set */
+ m_latch[0] = m_latch[1] = m_latch[2] = 0;
+
+ if (call_handlers)
+ {
+ for (int i = 0; i < 3; i++)
+ {
+ ppi8255_write_port(i);
+ }
+ }
+
+ /* reset flip-flops */
+ m_obf_a = m_ibf_a = 0;
+ m_obf_b = m_ibf_b = 0;
+ m_inte_a = m_inte_b = m_inte_1 = m_inte_2 = 0;
+
+ /* store control word */
+ m_control = data;
+}
+
+void ppi8255_set_port_a_read(device_t *device, const devcb_read8 *config)
+{
+ downcast<ppi8255_device*>(device)->ppi8255_set_port_read(0, *config);
+}
+
+void ppi8255_set_port_b_read(device_t *device, const devcb_read8 *config)
+{
+ downcast<ppi8255_device*>(device)->ppi8255_set_port_read(1, *config);
+}
+
+void ppi8255_set_port_c_read(device_t *device, const devcb_read8 *config)
+{
+ downcast<ppi8255_device*>(device)->ppi8255_set_port_read(2, *config);
+}
+
+
+void ppi8255_set_port_a_write(device_t *device, const devcb_write8 *config)
+{
+ downcast<ppi8255_device*>(device)->ppi8255_set_port_write(0, *config);
+}
+
+void ppi8255_set_port_b_write(device_t *device, const devcb_write8 *config)
+{
+ downcast<ppi8255_device*>(device)->ppi8255_set_port_write(1, *config);
+}
+
+void ppi8255_set_port_c_write(device_t *device, const devcb_write8 *config)
+{
+ downcast<ppi8255_device*>(device)->ppi8255_set_port_write(2, *config);
+}
+
+
+void ppi8255_set_port_a( device_t *device, UINT8 data )
+{
+ downcast<ppi8255_device*>(device)->ppi8255_set_port(0, data);
+}
+
+void ppi8255_set_port_b( device_t *device, UINT8 data )
+{
+ downcast<ppi8255_device*>(device)->ppi8255_set_port(1, data);
+}
+
+void ppi8255_set_port_c( device_t *device, UINT8 data )
+{
+ downcast<ppi8255_device*>(device)->ppi8255_set_port(2, data);
+}
+
+
+UINT8 ppi8255_get_port_a( device_t *device )
+{
+ return downcast<ppi8255_device*>(device)->ppi8255_get_port(0);
+}
+
+UINT8 ppi8255_get_port_b( device_t *device )
+{
+ return downcast<ppi8255_device*>(device)->ppi8255_get_port(1);
+}
+
+UINT8 ppi8255_get_port_c( device_t *device )
+{
+ return downcast<ppi8255_device*>(device)->ppi8255_get_port(2);
+}
diff --git a/trunk/src/emu/machine/8255ppi.h b/trunk/src/emu/machine/8255ppi.h
new file mode 100644
index 00000000000..d85c56439da
--- /dev/null
+++ b/trunk/src/emu/machine/8255ppi.h
@@ -0,0 +1,153 @@
+/*********************************************************************
+
+ 8255ppi.h
+
+ Intel 8255 PPI I/O chip
+
+*********************************************************************/
+
+#pragma once
+
+#ifndef __8255PPI_H__
+#define __8255PPI_H__
+
+#include "emu.h"
+
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_PPI8255_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, PPI8255, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_PPI8255_RECONFIG(_tag, _intrf) \
+ MCFG_DEVICE_MODIFY(_tag) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+
+// ======================> ppi8255_interface
+
+struct ppi8255_interface
+{
+ devcb_read8 m_port_a_read;
+ devcb_read8 m_port_b_read;
+ devcb_read8 m_port_c_read;
+ devcb_write8 m_port_a_write;
+ devcb_write8 m_port_b_write;
+ devcb_write8 m_port_c_write;
+};
+
+
+// ======================> ppi8255_device
+
+class ppi8255_device : public device_t,
+ public ppi8255_interface
+{
+public:
+ // construction/destruction
+ ppi8255_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ UINT8 ppi8255_r(UINT32 offset);
+ void ppi8255_w(UINT32 offset, UINT8 data);
+
+ void ppi8255_set_port_read(int which, const devcb_read8 &config) { m_port_read[which].resolve(config, *this); }
+ void ppi8255_set_port_write(int which, const devcb_write8 &config) { m_port_write[which].resolve(config, *this); }
+
+ void ppi8255_set_port(int which, UINT8 data) { ppi8255_input(which, data); }
+ UINT8 ppi8255_get_port(int which) { return m_output[which]; }
+
+ void ppi8255_set_port_a(UINT8 data);
+ void ppi8255_set_port_b(UINT8 data);
+ void ppi8255_set_port_c(UINT8 data);
+
+ UINT8 ppi8255_get_port_a();
+ UINT8 ppi8255_get_port_b();
+ UINT8 ppi8255_get_port_c();
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_post_load() { }
+ virtual void device_clock_changed() { }
+
+ static TIMER_CALLBACK( callback );
+
+private:
+
+ void ppi8255_get_handshake_signals(int is_read, UINT8 *result);
+ void ppi8255_input(int port, UINT8 data);
+
+ UINT8 ppi8255_read_port(int port);
+ void ppi8255_write_port(int port);
+
+ void set_mode(int data, int call_handlers);
+
+ devcb_resolved_read8 m_port_read[3];
+ devcb_resolved_write8 m_port_write[3];
+
+ /* mode flags */
+ UINT8 m_group_a_mode;
+ UINT8 m_group_b_mode;
+ UINT8 m_port_a_dir;
+ UINT8 m_port_b_dir;
+ UINT8 m_port_ch_dir;
+ UINT8 m_port_cl_dir;
+
+ /* handshake signals (1=asserted; 0=non-asserted) */
+ UINT8 m_obf_a;
+ UINT8 m_obf_b;
+ UINT8 m_ibf_a;
+ UINT8 m_ibf_b;
+ UINT8 m_inte_a;
+ UINT8 m_inte_b;
+ UINT8 m_inte_1;
+ UINT8 m_inte_2;
+
+ UINT8 m_in_mask[3]; /* input mask */
+ UINT8 m_out_mask[3]; /* output mask */
+ UINT8 m_read[3]; /* data read from ports */
+ UINT8 m_latch[3]; /* data written to ports */
+ UINT8 m_output[3]; /* actual output data */
+ UINT8 m_control; /* mode control word */
+};
+
+
+// device type definition
+extern const device_type PPI8255;
+
+
+
+/***************************************************************************
+ PROTOTYPES
+***************************************************************************/
+
+READ8_DEVICE_HANDLER( ppi8255_r );
+WRITE8_DEVICE_HANDLER( ppi8255_w );
+
+void ppi8255_set_port_a_read( device_t *device, const devcb_read8 *config );
+void ppi8255_set_port_b_read( device_t *device, const devcb_read8 *config );
+void ppi8255_set_port_c_read( device_t *device, const devcb_read8 *config );
+
+void ppi8255_set_port_a_write( device_t *device, const devcb_write8 *config );
+void ppi8255_set_port_b_write( device_t *device, const devcb_write8 *config );
+void ppi8255_set_port_c_write( device_t *device, const devcb_write8 *config );
+
+void ppi8255_set_port_a( device_t *device, UINT8 data );
+void ppi8255_set_port_b( device_t *device, UINT8 data );
+void ppi8255_set_port_c( device_t *device, UINT8 data );
+
+UINT8 ppi8255_get_port_a( device_t *device );
+UINT8 ppi8255_get_port_b( device_t *device );
+UINT8 ppi8255_get_port_c( device_t *device );
+
+#endif /* __8255PPI_H_ */
diff --git a/trunk/src/emu/machine/8257dma.c b/trunk/src/emu/machine/8257dma.c
new file mode 100644
index 00000000000..c6673d087f9
--- /dev/null
+++ b/trunk/src/emu/machine/8257dma.c
@@ -0,0 +1,454 @@
+/**********************************************************************
+
+ 8257 DMA interface and emulation
+
+ For datasheet http://www.threedee.com/jcm/library/index.html
+
+ 2008/05 Miodrag Milanovic
+
+ - added support for autoload mode
+ - fixed bug in calculating count
+
+ 2007/11 couriersud
+
+ - architecture copied from 8237 DMA
+ - significant changes to implementation
+
+ The DMA works like this:
+
+ 1. The device asserts the DRQn line
+ 2. The DMA clears the TC (terminal count) line
+ 3. The DMA asserts the CPU's HRQ (halt request) line
+ 4. Upon acknowledgement of the halt, the DMA will let the device
+ know that it needs to send information by asserting the DACKn
+ line
+ 5. The DMA will read the byte from the device
+ 6. The device clears the DRQn line
+ 7. The DMA clears the CPU's HRQ line
+ 8. (steps 3-7 are repeated for every byte in the chain)
+
+**********************************************************************/
+
+#include "emu.h"
+#include "memconv.h"
+#include "8257dma.h"
+#include "devhelpr.h"
+
+#define I8257_STATUS_UPDATE 0x10
+#define I8257_STATUS_TC_CH3 0x08
+#define I8257_STATUS_TC_CH2 0x04
+#define I8257_STATUS_TC_CH1 0x02
+#define I8257_STATUS_TC_CH0 0x01
+
+#define DMA_MODE_AUTOLOAD(mode) ((mode) & 0x80)
+#define DMA_MODE_TCSTOP(mode) ((mode) & 0x40)
+#define DMA_MODE_EXWRITE(mode) ((mode) & 0x20)
+#define DMA_MODE_ROTPRIO(mode) ((mode) & 0x10)
+#define DMA_MODE_CH_EN(mode, chan) ((mode) & (1 << (chan)))
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type I8257 = &device_creator<i8257_device>;
+
+//-------------------------------------------------
+// i8257_device - constructor
+//-------------------------------------------------
+
+i8257_device::i8257_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, I8257, "DMA8257", tag, owner, clock),
+ m_mode(0),
+ m_rr(0),
+ m_msb(0),
+ m_drq(0),
+ m_status(0x0f)
+{
+ memset(m_registers, 0, sizeof(m_registers));
+ memset(m_address, 0, sizeof(m_address));
+ memset(m_count, 0, sizeof(m_count));
+ memset(m_rwmode, 0, sizeof(m_rwmode));
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void i8257_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const i8257_interface *intf = reinterpret_cast<const i8257_interface *>(static_config());
+ if (intf != NULL)
+ {
+ *static_cast<i8257_interface *>(this) = *intf;
+ }
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_out_hrq_cb, 0, sizeof(m_out_hrq_cb));
+ memset(&m_out_tc_cb, 0, sizeof(m_out_tc_cb));
+ memset(&m_out_mark_cb, 0, sizeof(m_out_mark_cb));
+ memset(&m_in_memr_cb, 0, sizeof(m_in_memr_cb));
+ memset(&m_out_memw_cb, 0, sizeof(m_out_memw_cb));
+ memset(&m_in_ior_cb[0], 0, sizeof(m_in_ior_cb[0]));
+ memset(&m_in_ior_cb[1], 0, sizeof(m_in_ior_cb[1]));
+ memset(&m_in_ior_cb[2], 0, sizeof(m_in_ior_cb[2]));
+ memset(&m_in_ior_cb[3], 0, sizeof(m_in_ior_cb[3]));
+ memset(&m_out_iow_cb[0], 0, sizeof(m_out_iow_cb[0]));
+ memset(&m_out_iow_cb[1], 0, sizeof(m_out_iow_cb[1]));
+ memset(&m_out_iow_cb[2], 0, sizeof(m_out_iow_cb[2]));
+ memset(&m_out_iow_cb[3], 0, sizeof(m_out_iow_cb[3]));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void i8257_device::device_start()
+{
+ /* validate arguments */
+ assert(this != NULL);
+
+ /* resolve callbacks */
+ m_out_hrq_func.resolve(m_out_hrq_cb, *this);
+ m_out_tc_func.resolve(m_out_tc_cb, *this);
+ m_out_mark_func.resolve(m_out_mark_cb, *this);
+ m_in_memr_func.resolve(m_in_memr_cb, *this);
+ m_out_memw_func.resolve(m_out_memw_cb, *this);
+
+ for (int i = 0; i < I8257_NUM_CHANNELS; i++)
+ {
+ m_in_ior_func[i].resolve(m_in_ior_cb[i], *this);
+ m_out_iow_func[i].resolve(m_out_iow_cb[i], *this);
+ }
+
+ /* set initial values */
+ m_timer = timer_alloc(TIMER_OPERATION);
+ m_msbflip_timer = timer_alloc(TIMER_MSBFLIP);
+
+ /* register for state saving */
+ save_item(NAME(m_address));
+ save_item(NAME(m_count));
+ save_item(NAME(m_rwmode));
+ save_item(NAME(m_registers));
+ save_item(NAME(m_mode));
+ save_item(NAME(m_rr));
+ save_item(NAME(m_msb));
+ save_item(NAME(m_drq));
+ save_item(NAME(m_status));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void i8257_device::device_reset()
+{
+ m_status &= 0xf0;
+ m_mode = 0;
+ i8257_update_status();
+}
+
+
+int i8257_device::i8257_do_operation(int channel)
+{
+ int done;
+ UINT8 data;
+
+ UINT8 mode = m_rwmode[channel];
+ if (m_count[channel] == 0x0000)
+ {
+ m_status |= (0x01 << channel);
+
+ m_out_tc_func(ASSERT_LINE);
+ }
+ switch(mode) {
+ case 1:
+ if (!m_in_memr_func.isnull())
+ {
+ data = m_in_memr_func(m_address[channel]);
+ }
+ else
+ {
+ data = 0;
+ logerror("8257: No memory read function defined.\n");
+ }
+ if (!m_out_iow_func[channel].isnull())
+ {
+ m_out_iow_func[channel](m_address[channel], data);
+ }
+ else
+ {
+ logerror("8257: No channel write function for channel %d defined.\n",channel);
+ }
+
+ m_address[channel]++;
+ m_count[channel]--;
+ done = (m_count[channel] == 0xFFFF);
+ break;
+
+ case 2:
+ if (!m_in_ior_func[channel].isnull())
+ {
+ data = m_in_ior_func[channel](m_address[channel]);
+ }
+ else
+ {
+ data = 0;
+ logerror("8257: No channel read function for channel %d defined.\n",channel);
+ }
+
+ if (!m_out_memw_func.isnull())
+ {
+ m_out_memw_func(m_address[channel], data);
+ }
+ else
+ {
+ logerror("8257: No memory write function defined.\n");
+ }
+ m_address[channel]++;
+ m_count[channel]--;
+ done = (m_count[channel] == 0xFFFF);
+ break;
+ case 0: /* verify */
+ m_address[channel]++;
+ m_count[channel]--;
+ done = (m_count[channel] == 0xFFFF);
+ break;
+ default:
+ fatalerror("i8257_do_operation: invalid mode!\n");
+ break;
+ }
+ if (done)
+ {
+ if ((channel==2) && DMA_MODE_AUTOLOAD(m_mode))
+ {
+ /* in case of autoload at the end channel 3 info is */
+ /* copied to channel 2 info */
+ m_registers[4] = m_registers[6];
+ m_registers[5] = m_registers[7];
+ }
+
+ m_out_tc_func(CLEAR_LINE);
+ }
+ return done;
+}
+
+
+void i8257_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case TIMER_OPERATION:
+ {
+ int i, channel = 0, rr;
+ int done;
+
+ rr = DMA_MODE_ROTPRIO(m_mode) ? m_rr : 0;
+ for (i = 0; i < I8257_NUM_CHANNELS; i++)
+ {
+ channel = (i + rr) % I8257_NUM_CHANNELS;
+ if ((m_status & (1 << channel)) == 0)
+ {
+ if (m_mode & m_drq & (1 << channel))
+ {
+ break;
+ }
+ }
+ }
+ done = i8257_do_operation(channel);
+
+ m_rr = (channel + 1) & 0x03;
+
+ if (done)
+ {
+ m_drq &= ~(0x01 << channel);
+ i8257_update_status();
+ if (!(DMA_MODE_AUTOLOAD(m_mode) && channel==2))
+ {
+ if (DMA_MODE_TCSTOP(m_mode))
+ {
+ m_mode &= ~(0x01 << channel);
+ }
+ }
+ }
+ break;
+ }
+
+ case TIMER_MSBFLIP:
+ m_msb ^= 1;
+ break;
+
+ case TIMER_DRQ_SYNC:
+ {
+ int channel = param >> 1;
+ int state = param & 0x01;
+
+ /* normalize state */
+ if (state)
+ {
+ m_drq |= 0x01 << channel;
+ m_address[channel] = m_registers[channel * 2];
+ m_count[channel] = m_registers[channel * 2 + 1] & 0x3FFF;
+ m_rwmode[channel] = m_registers[channel * 2 + 1] >> 14;
+ /* clear channel TC */
+ m_status &= ~(0x01 << channel);
+ }
+ else
+ m_drq &= ~(0x01 << channel);
+
+ i8257_update_status();
+ break;
+ }
+ }
+}
+
+
+void i8257_device::i8257_update_status()
+{
+ UINT16 pending_transfer;
+ attotime next;
+
+ /* no transfer is active right now; is there a transfer pending right now? */
+ pending_transfer = m_drq & (m_mode & 0x0F);
+
+ if (pending_transfer)
+ {
+ next = attotime::from_hz(clock() / 4 );
+ m_timer->adjust(
+ attotime::zero,
+ 0,
+ /* 1 byte transferred in 4 clock cycles */
+ next);
+ }
+ else
+ {
+ /* no transfers active right now */
+ m_timer->reset();
+ }
+
+ /* set the halt line */
+ m_out_hrq_func(pending_transfer ? ASSERT_LINE : CLEAR_LINE);
+}
+
+
+void i8257_device::i8257_prepare_msb_flip()
+{
+ m_msbflip_timer->adjust(attotime::zero);
+}
+
+
+READ8_DEVICE_HANDLER_TRAMPOLINE(i8257, i8257_r)
+{
+ UINT8 data = 0xFF;
+
+ switch(offset)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ /* DMA address/count register */
+ data = ( m_registers[offset] >> (m_msb ? 8 : 0) ) & 0xFF;
+ i8257_prepare_msb_flip();
+ break;
+
+ case 8:
+ /* DMA status register */
+ data = (UINT8) m_status;
+ /* read resets status ! */
+ m_status &= 0xF0;
+
+ break;
+
+ default:
+ logerror("8257: Read from register %d.\n", offset);
+ data = 0xFF;
+ break;
+ }
+ return data;
+}
+
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(i8257, i8257_w)
+{
+ switch(offset)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ /* DMA address/count register */
+ if (m_msb)
+ {
+ m_registers[offset] |= ((UINT16) data) << 8;
+ }
+ else
+ {
+ m_registers[offset] = data;
+ }
+
+ if (DMA_MODE_AUTOLOAD(m_mode))
+ {
+ /* in case of autoload when inserting channel 2 info */
+ /* it is automaticaly copied to channel 3 info */
+ switch(offset)
+ {
+ case 4:
+ case 5:
+ if (m_msb)
+ {
+ m_registers[offset+2] |= ((UINT16) data) << 8;
+ }
+ else
+ {
+ m_registers[offset+2] = data;
+ }
+ }
+ }
+
+ i8257_prepare_msb_flip();
+ break;
+
+ case 8:
+ /* DMA mode register */
+ m_mode = data;
+ break;
+
+ default:
+ logerror("8257: Write to register %d.\n", offset);
+ break;
+ }
+}
+
+
+void i8257_device::i8257_drq_w(int channel, int state)
+{
+ int param = (channel << 1) | (state ? 1 : 0);
+
+ synchronize(TIMER_DRQ_SYNC, param);
+}
+
+WRITE_LINE_DEVICE_HANDLER( i8257_hlda_w ) { }
+WRITE_LINE_DEVICE_HANDLER( i8257_ready_w ) { }
+WRITE_LINE_DEVICE_HANDLER( i8257_drq0_w ) { downcast<i8257_device*>(device)->i8257_drq_w(0, state); }
+WRITE_LINE_DEVICE_HANDLER( i8257_drq1_w ) { downcast<i8257_device*>(device)->i8257_drq_w(1, state); }
+WRITE_LINE_DEVICE_HANDLER( i8257_drq2_w ) { downcast<i8257_device*>(device)->i8257_drq_w(2, state); }
+WRITE_LINE_DEVICE_HANDLER( i8257_drq3_w ) { downcast<i8257_device*>(device)->i8257_drq_w(3, state); }
diff --git a/trunk/src/emu/machine/8257dma.h b/trunk/src/emu/machine/8257dma.h
new file mode 100644
index 00000000000..0c96150dfa7
--- /dev/null
+++ b/trunk/src/emu/machine/8257dma.h
@@ -0,0 +1,165 @@
+/***************************************************************************
+
+ Intel 8257 Programmable DMA Controller emulation
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+****************************************************************************
+ _____ _____
+ _I/OR 1 |* \_/ | 40 A7
+ _I/OW 2 | | 39 A6
+ _MEMR 3 | | 38 A5
+ _MEMW 4 | | 37 A4
+ MARK 5 | | 36 TC
+ READY 6 | | 35 A3
+ HLDA 7 | | 34 A2
+ ADSTB 8 | | 33 A1
+ AEN 9 | | 32 A0
+ HRQ 10 | 8257 | 31 Vcc
+ _CS 11 | | 30 D0
+ CLK 12 | | 29 D1
+ RESET 13 | | 28 D2
+ _DACK2 14 | | 27 D3
+ _DACK3 15 | | 26 D4
+ DRQ3 16 | | 25 _DACK0
+ DRQ2 17 | | 24 _DACK1
+ DRQ1 18 | | 23 D5
+ DRQ0 19 | | 22 D6
+ GND 20 |_____________| 21 D7
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __I8257__
+#define __I8257__
+
+#include "emu.h"
+
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_I8257_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD(_tag, I8257, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define I8257_INTERFACE(_name) \
+ const i8257_interface (_name) =
+
+#define I8257_NUM_CHANNELS (4)
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+
+// ======================> i8257_interface
+
+struct i8257_interface
+{
+ devcb_write_line m_out_hrq_cb;
+ devcb_write_line m_out_tc_cb;
+ devcb_write_line m_out_mark_cb;
+
+ /* accessors to main memory */
+ devcb_read8 m_in_memr_cb; // TODO m_in_memr_cb[I8257_NUM_CHANNELS];
+ devcb_write8 m_out_memw_cb; // TODO m_out_memw_cb[I8257_NUM_CHANNELS];
+
+ /* channel accesors */
+ devcb_read8 m_in_ior_cb[I8257_NUM_CHANNELS];
+ devcb_write8 m_out_iow_cb[I8257_NUM_CHANNELS];
+};
+
+
+
+// ======================> i8257_device
+
+class i8257_device : public device_t,
+ public i8257_interface
+{
+public:
+ // construction/destruction
+ i8257_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ /* register access */
+ UINT8 i8257_r(UINT32 offset);
+ void i8257_w(UINT32 offset, UINT8 data);
+
+ /* data request */
+ void i8257_drq_w(int channel, int state);
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+private:
+ static const device_timer_id TIMER_OPERATION = 0;
+ static const device_timer_id TIMER_MSBFLIP = 1;
+ static const device_timer_id TIMER_DRQ_SYNC = 2;
+
+ int i8257_do_operation(int channel);
+ void i8257_update_status();
+ void i8257_prepare_msb_flip();
+
+ devcb_resolved_write_line m_out_hrq_func;
+ devcb_resolved_write_line m_out_tc_func;
+ devcb_resolved_write_line m_out_mark_func;
+ devcb_resolved_read8 m_in_memr_func;
+ devcb_resolved_write8 m_out_memw_func;
+ devcb_resolved_read8 m_in_ior_func[I8257_NUM_CHANNELS];
+ devcb_resolved_write8 m_out_iow_func[I8257_NUM_CHANNELS];
+
+ emu_timer *m_timer;
+ emu_timer *m_msbflip_timer;
+
+ UINT16 m_registers[I8257_NUM_CHANNELS*2];
+
+ UINT16 m_address[I8257_NUM_CHANNELS];
+ UINT16 m_count[I8257_NUM_CHANNELS];
+ UINT8 m_rwmode[I8257_NUM_CHANNELS];
+
+ UINT8 m_mode;
+ UINT8 m_rr;
+
+ UINT8 m_msb;
+ UINT8 m_drq;
+
+ /* bits 0- 3 : Terminal count for channels 0-3 */
+ UINT8 m_status;
+};
+
+
+// device type definition
+extern const device_type I8257;
+
+
+
+/***************************************************************************
+ PROTOTYPES
+***************************************************************************/
+
+/* register access */
+READ8_DEVICE_HANDLER( i8257_r );
+WRITE8_DEVICE_HANDLER( i8257_w );
+
+/* hold acknowledge */
+WRITE_LINE_DEVICE_HANDLER( i8257_hlda_w );
+
+/* ready */
+WRITE_LINE_DEVICE_HANDLER( i8257_ready_w );
+
+/* data request */
+WRITE_LINE_DEVICE_HANDLER( i8257_drq0_w );
+WRITE_LINE_DEVICE_HANDLER( i8257_drq1_w );
+WRITE_LINE_DEVICE_HANDLER( i8257_drq2_w );
+WRITE_LINE_DEVICE_HANDLER( i8257_drq3_w );
+
+#endif
diff --git a/trunk/src/emu/machine/adc0808.c b/trunk/src/emu/machine/adc0808.c
new file mode 100644
index 00000000000..1c7f125e026
--- /dev/null
+++ b/trunk/src/emu/machine/adc0808.c
@@ -0,0 +1,171 @@
+/**********************************************************************
+
+ National Semiconductor ADC0808/ADC0809 8-Bit A/D Converter emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "adc0808.h"
+#include "machine/devhelpr.h"
+
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type ADC0808 = &device_creator<adc0808_device>;
+
+//-------------------------------------------------
+// adc0808_device - constructor
+//-------------------------------------------------
+
+adc0808_device::adc0808_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, ADC0808, "ADC0808", tag, owner, clock),
+ m_address(0),
+ m_start(0),
+ m_next_eoc(0),
+ m_cycle(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void adc0808_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const adc0808_interface *intf = reinterpret_cast<const adc0808_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<adc0808_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_out_eoc_cb, 0, sizeof(m_out_eoc_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void adc0808_device::device_start()
+{
+ // resolve callbacks
+ m_out_eoc_func.resolve(m_out_eoc_cb, *this);
+
+ // allocate timers
+ m_cycle_timer = timer_alloc();
+ m_cycle_timer->adjust(attotime::zero, 0, attotime::from_hz(clock()));
+
+ // register for state saving
+ save_item(NAME(m_address));
+ save_item(NAME(m_start));
+ save_item(NAME(m_eoc));
+ save_item(NAME(m_next_eoc));
+ save_item(NAME(m_sar));
+ save_item(NAME(m_cycle));
+ save_item(NAME(m_bit));
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void adc0808_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ if (!m_start)
+ {
+ if (m_cycle == 7)
+ {
+ m_bit++;
+
+ if (m_bit == 8)
+ {
+ /* sample input */
+ double vref_pos = m_in_vref_pos_func(this);
+ double vref_neg = m_in_vref_neg_func(this);
+
+ double input = m_in_in_func[m_address](this);
+
+ m_sar = (255 * (input - vref_neg)) / (vref_pos - vref_neg);
+
+ /* trigger end of conversion */
+ m_next_eoc = 1;
+ }
+ }
+ }
+
+ if (m_cycle == 0)
+ {
+ /* set end of conversion pin */
+ if (m_next_eoc != m_eoc)
+ {
+ m_out_eoc_func(m_next_eoc);
+ m_eoc = m_next_eoc;
+ }
+ }
+
+ m_cycle++;
+
+ if (m_cycle == 8)
+ {
+ m_cycle = 0;
+ }
+}
+
+
+//-------------------------------------------------
+// data_r - data read
+//-------------------------------------------------
+
+READ8_MEMBER( adc0808_device::data_r )
+{
+ return m_sar;
+}
+
+
+//-------------------------------------------------
+// ale_w - address write
+//-------------------------------------------------
+
+WRITE8_MEMBER( adc0808_device::ale_w )
+{
+ m_address = data;
+}
+
+
+//-------------------------------------------------
+// start_w - start conversion
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( adc0808_device::start_w )
+{
+ if (!m_start && state) // rising edge
+ {
+ // reset registers
+
+ m_sar = 0;
+ m_bit = 0;
+ }
+ else if (m_start && !state) // falling edge
+ {
+ // start conversion
+
+ m_next_eoc = 0;
+ }
+
+ m_start = state;
+}
diff --git a/trunk/src/emu/machine/adc0808.h b/trunk/src/emu/machine/adc0808.h
new file mode 100644
index 00000000000..68c132bdf9f
--- /dev/null
+++ b/trunk/src/emu/machine/adc0808.h
@@ -0,0 +1,116 @@
+/**********************************************************************
+
+ National Semiconductor ADC0808/ADC0809 8-Bit A/D Converter emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ IN3 1 |* \_/ | 28 IN2
+ IN4 2 | | 27 IN1
+ IN5 3 | | 26 IN0
+ IN6 4 | | 25 ADD A
+ IN7 5 | | 24 ADD B
+ START 6 | | 23 ADD C
+ EOC 7 | ADC0808 | 22 ALE
+ 2-5 8 | ADC0809 | 21 2-1 MSB
+ OUTPUT ENABLE 9 | | 20 2-2
+ CLOCK 10 | | 19 2-3
+ Vcc 11 | | 18 2-4
+ Vref+ 12 | | 17 2-8 LSB
+ GND 13 | | 16 Vref-
+ 2-7 14 |_____________| 15 2-6
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __ADC0808__
+#define __ADC0808__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_ADC0808_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD(_tag, ADC0808, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+
+#define ADC0808_INTERFACE(name) \
+ const adc0808_interface (name) =
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> adc0808_analog_read
+
+typedef double (*adc0808_analog_read) (device_t *device);
+#define ADC0808_ANALOG_READ(name) double name(device_t *device)
+
+
+// ======================> adc0808_interface
+
+struct adc0808_interface
+{
+ devcb_write_line m_out_eoc_cb;
+
+ adc0808_analog_read m_in_vref_pos_func;
+ adc0808_analog_read m_in_vref_neg_func;
+
+ adc0808_analog_read m_in_in_func[8];
+};
+
+
+// ======================> adc0808_device
+
+class adc0808_device : public device_t,
+ public adc0808_interface
+{
+public:
+ // construction/destruction
+ adc0808_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_READ8_MEMBER( data_r );
+ DECLARE_WRITE8_MEMBER( ale_w );
+
+ DECLARE_WRITE_LINE_MEMBER( start_w );
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+private:
+ devcb_resolved_write_line m_out_eoc_func;
+
+ int m_address; // analog channel address
+ int m_start; // start conversion pin
+ int m_eoc; // end of conversion pin
+ int m_next_eoc; // next value end of conversion pin
+
+ UINT8 m_sar; // successive approximation register
+
+ int m_cycle; // clock cycle counter
+ int m_bit; // bit counter
+
+ // timers
+ emu_timer *m_cycle_timer;
+};
+
+
+// device type definition
+extern const device_type ADC0808;
+
+
+
+#endif
diff --git a/trunk/src/emu/machine/adc083x.c b/trunk/src/emu/machine/adc083x.c
new file mode 100644
index 00000000000..aab3d868600
--- /dev/null
+++ b/trunk/src/emu/machine/adc083x.c
@@ -0,0 +1,539 @@
+/***************************************************************************
+
+ National Semiconductor ADC0831 / ADC0832 / ADC0834 / ADC0838
+
+ 8-Bit serial I/O A/D Converters with Muliplexer Options
+
+***************************************************************************/
+
+#include "emu.h"
+#include "adc083x.h"
+
+#define VERBOSE_LEVEL ( 0 )
+
+INLINE void ATTR_PRINTF( 3, 4 ) verboselog( int n_level, running_machine &machine, 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 );
+ }
+}
+
+/***************************************************************************
+ PARAMETERS
+***************************************************************************/
+
+enum
+{
+ STATE_IDLE,
+ STATE_WAIT_FOR_START,
+ STATE_SHIFT_MUX,
+ STATE_MUX_SETTLE,
+ STATE_OUTPUT_MSB_FIRST,
+ STATE_WAIT_FOR_SE,
+ STATE_OUTPUT_LSB_FIRST,
+ STATE_FINISHED
+};
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _adc0831_state adc0831_state;
+struct _adc0831_state
+{
+ adc083x_input_convert_func input_callback_r;
+
+ INT32 cs;
+ INT32 clk;
+ INT32 di;
+ INT32 se;
+ INT32 sars;
+ INT32 _do;
+ INT32 sgl;
+ INT32 odd;
+ INT32 sel1;
+ INT32 sel0;
+ INT32 state;
+ INT32 bit;
+ INT32 output;
+ INT32 mux_bits;
+};
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE adc0831_state *get_safe_token( device_t *device )
+{
+ assert( device != NULL );
+ assert( ( device->type() == ADC0831 ) || ( device->type() == ADC0832 ) || ( device->type() == ADC0834 ) || ( device->type() == ADC0838 ) );
+ return (adc0831_state *) downcast<legacy_device_base *>(device)->token();
+}
+
+INLINE const adc083x_interface *get_interface( device_t *device )
+{
+ assert( device != NULL );
+ assert( ( device->type() == ADC0831 ) || ( device->type() == ADC0832 ) || ( device->type() == ADC0834 ) || ( device->type() == ADC0838 ) );
+ return (const adc083x_interface *) device->static_config();
+}
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ adc083x_clear_sars
+-------------------------------------------------*/
+
+static void adc083x_clear_sars( device_t *device, adc0831_state *adc083x )
+{
+ if( device->type() == ADC0834 ||device->type() == ADC0838 )
+ {
+ adc083x->sars = 1;
+ }
+ else
+ {
+ adc083x->sars = 0;
+ }
+}
+
+/*-------------------------------------------------
+ adc083x_cs_write
+-------------------------------------------------*/
+
+WRITE_LINE_DEVICE_HANDLER( adc083x_cs_write )
+{
+ adc0831_state *adc083x = get_safe_token( device );
+
+ if( adc083x->cs != state )
+ {
+ verboselog( 2, device->machine(), "adc083x_cs_write( %s, %d )\n", device->tag(), state );
+ }
+
+ if( adc083x->cs == 0 && state != 0 )
+ {
+ adc083x->state = STATE_IDLE;
+ adc083x_clear_sars( device, adc083x );
+ adc083x->_do = 1;
+ }
+
+ if( adc083x->cs != 0 && state == 0 )
+ {
+ if( device->type() == ADC0831 )
+ {
+ adc083x->state = STATE_MUX_SETTLE;
+ }
+ else
+ {
+ adc083x->state = STATE_WAIT_FOR_START;
+ }
+
+ adc083x_clear_sars( device, adc083x );
+ adc083x->_do = 1;
+ }
+
+ adc083x->cs = state;
+}
+
+/*-------------------------------------------------
+ adc083x_conversion
+-------------------------------------------------*/
+
+static UINT8 adc083x_conversion( device_t *device )
+{
+ adc0831_state *adc083x = get_safe_token( device );
+ int result;
+ int positive_channel = ADC083X_AGND;
+ int negative_channel = ADC083X_AGND;
+ double positive = 0;
+ double negative = 0;
+ double gnd = adc083x->input_callback_r( device, ADC083X_AGND );
+ double vref = adc083x->input_callback_r( device, ADC083X_VREF );
+
+ if( device->type() == ADC0831 )
+ {
+ positive_channel = ADC083X_CH0;
+ negative_channel = ADC083X_CH1;
+ }
+ else if( device->type() == ADC0832 )
+ {
+ positive_channel = ADC083X_CH0 + adc083x->odd;
+ if( adc083x->sgl == 0 )
+ {
+ negative_channel = positive_channel ^ 1;
+ }
+ else
+ {
+ negative_channel = ADC083X_AGND;
+ }
+ }
+ else if( device->type() == ADC0834 )
+ {
+ positive_channel = ADC083X_CH0 + adc083x->odd + ( adc083x->sel1 * 2 );
+ if( adc083x->sgl == 0 )
+ {
+ negative_channel = positive_channel ^ 1;
+ }
+ else
+ {
+ negative_channel = ADC083X_AGND;
+ }
+ }
+ else if( device->type() == ADC0838 )
+ {
+ positive_channel = ADC083X_CH0 + adc083x->odd + ( adc083x->sel0 * 2 ) + ( adc083x->sel1 * 4 );
+ if( adc083x->sgl == 0 )
+ {
+ negative_channel = positive_channel ^ 1;
+ }
+ else
+ {
+ negative_channel = ADC083X_COM;
+ }
+ }
+
+ if( positive_channel != ADC083X_AGND )
+ {
+ positive = adc083x->input_callback_r( device, positive_channel ) - gnd;
+ }
+
+ if( negative_channel != ADC083X_AGND )
+ {
+ negative = adc083x->input_callback_r( device, negative_channel ) - gnd;
+ }
+
+ result = (int) ( ( ( positive - negative ) * 255 ) / vref );
+ if( result < 0 )
+ {
+ result = 0;
+ }
+ else if( result > 255 )
+ {
+ result = 255;
+ }
+
+ return result;
+}
+
+/*-------------------------------------------------
+ adc083x_clk_write
+-------------------------------------------------*/
+
+WRITE_LINE_DEVICE_HANDLER( adc083x_clk_write )
+{
+ adc0831_state *adc083x = get_safe_token( device );
+
+ if( adc083x->clk != state )
+ {
+ verboselog( 2, device->machine(), "adc083x_clk_write( %s, %d )\n", device->tag(), state );
+ }
+
+ if( adc083x->cs == 0 )
+ {
+ if( adc083x->clk == 0 && state != 0 )
+ {
+ switch( adc083x->state )
+ {
+ case STATE_WAIT_FOR_START:
+ if( adc083x->di != 0 )
+ {
+ verboselog( 1, device->machine(), "adc083x %s got start bit\n", device->tag() );
+ adc083x->state = STATE_SHIFT_MUX;
+ adc083x->sars = 0;
+ adc083x->sgl = 0;
+ adc083x->odd = 0;
+ adc083x->sel1 = 0;
+ adc083x->sel0 = 0;
+ adc083x->bit = 0;
+ }
+ else
+ {
+ verboselog( 1, device->machine(), "adc083x %s not start bit\n", device->tag() );
+ }
+ break;
+
+ case STATE_SHIFT_MUX:
+ switch( adc083x->bit )
+ {
+ case 0:
+ if( adc083x->di != 0 )
+ {
+ adc083x->sgl = 1;
+ }
+ verboselog( 1, device->machine(), "adc083x %s sgl <- %d\n", device->tag(), adc083x->sgl );
+ break;
+
+ case 1:
+ if( adc083x->di != 0 )
+ {
+ adc083x->odd = 1;
+ }
+ verboselog( 1, device->machine(), "adc083x %s odd <- %d\n", device->tag(), adc083x->odd );
+ break;
+
+ case 2:
+ if( adc083x->di != 0 )
+ {
+ adc083x->sel1 = 1;
+ }
+ verboselog( 1, device->machine(), "adc083x %s sel1 <- %d\n", device->tag(), adc083x->sel1 );
+ break;
+
+ case 3:
+ if( adc083x->di != 0 )
+ {
+ adc083x->sel0 = 1;
+ }
+ verboselog( 1, device->machine(), "adc083x %s sel0 <- %d\n", device->tag(), adc083x->sel0 );
+ break;
+ }
+
+ adc083x->bit++;
+ if( adc083x->bit == adc083x->mux_bits )
+ {
+ adc083x->state = STATE_MUX_SETTLE;
+ }
+
+ break;
+
+ case STATE_WAIT_FOR_SE:
+ adc083x->sars = 0;
+ if( device->type() == ADC0838 && adc083x->se != 0 )
+ {
+ verboselog( 1, device->machine(), "adc083x %s not se\n", device->tag() );
+ }
+ else
+ {
+ verboselog( 1, device->machine(), "adc083x %s got se\n", device->tag() );
+ adc083x->state = STATE_OUTPUT_LSB_FIRST;
+ adc083x->bit = 1;
+ }
+ break;
+ }
+ }
+
+ if( adc083x->clk != 0 && state == 0 )
+ {
+ switch( adc083x->state )
+ {
+ case STATE_MUX_SETTLE:
+ verboselog( 1, device->machine(), "adc083x %s mux settle\n", device->tag() );
+ adc083x->output = adc083x_conversion( device );
+ adc083x->state = STATE_OUTPUT_MSB_FIRST;
+ adc083x->bit = 7;
+ adc083x_clear_sars( device, adc083x );
+ adc083x->_do = 0;
+ break;
+
+ case STATE_OUTPUT_MSB_FIRST:
+ adc083x->_do = ( adc083x->output >> adc083x->bit ) & 1;
+ verboselog( 1, device->machine(), "adc083x %s msb %d -> %d\n", device->tag(), adc083x->bit, adc083x->_do );
+
+ adc083x->bit--;
+ if( adc083x->bit < 0 )
+ {
+ if( device->type() == ADC0831 )
+ {
+ adc083x->state = STATE_FINISHED;
+ }
+ else
+ {
+ adc083x->state = STATE_WAIT_FOR_SE;
+ }
+ }
+ break;
+
+ case STATE_OUTPUT_LSB_FIRST:
+ adc083x->_do = ( adc083x->output >> adc083x->bit ) & 1;
+ verboselog( 1, device->machine(), "adc083x %s lsb %d -> %d\n", device->tag(), adc083x->bit, adc083x->_do );
+
+ adc083x->bit++;
+ if( adc083x->bit == 8 )
+ {
+ adc083x->state = STATE_FINISHED;
+ }
+ break;
+
+ case STATE_FINISHED:
+ adc083x->state = STATE_IDLE;
+ adc083x->_do = 0;
+ break;
+ }
+ }
+ }
+
+ adc083x->clk = state;
+}
+
+/*-------------------------------------------------
+ adc083x_di_write
+-------------------------------------------------*/
+
+WRITE_LINE_DEVICE_HANDLER( adc083x_di_write )
+{
+ adc0831_state *adc083x = get_safe_token( device );
+
+ if( adc083x->di != state )
+ {
+ verboselog( 2, device->machine(), "adc083x_di_write( %s, %d )\n", device->tag(), state );
+ }
+
+ adc083x->di = state;
+}
+
+/*-------------------------------------------------
+ adc083x_se_write
+-------------------------------------------------*/
+
+WRITE_LINE_DEVICE_HANDLER( adc083x_se_write )
+{
+ adc0831_state *adc083x = get_safe_token( device );
+
+ if( adc083x->se != state )
+ {
+ verboselog( 2, device->machine(), "adc083x_se_write( %s, %d )\n", device->tag(), state );
+ }
+
+ adc083x->se = state;
+}
+
+/*-------------------------------------------------
+ adc083x_sars_read
+-------------------------------------------------*/
+
+READ_LINE_DEVICE_HANDLER( adc083x_sars_read )
+{
+ adc0831_state *adc083x = get_safe_token( device );
+
+ verboselog( 1, device->machine(), "adc083x_sars_read( %s ) %d\n", device->tag(), adc083x->sars );
+ return adc083x->sars;
+}
+
+/*-------------------------------------------------
+ adc083x_do_read
+-------------------------------------------------*/
+
+READ_LINE_DEVICE_HANDLER( adc083x_do_read )
+{
+ adc0831_state *adc083x = get_safe_token( device );
+
+ verboselog( 1, device->machine(), "adc083x_do_read( %s ) %d\n", device->tag(), adc083x->_do );
+ return adc083x->_do;
+}
+
+
+/*-------------------------------------------------
+ DEVICE_START( adc083x )
+-------------------------------------------------*/
+
+static DEVICE_START( adc0831 )
+{
+ adc0831_state *adc083x = get_safe_token( device );
+ const adc083x_interface *intf = get_interface( device );
+
+ adc083x->cs = 0;
+ adc083x->clk = 0;
+ adc083x->di = 0;
+ adc083x->se = 0;
+ adc083x_clear_sars( device, adc083x );
+ adc083x->_do = 1;
+ adc083x->sgl = 0;
+ adc083x->odd = 0;
+ adc083x->sel1 = 0;
+ adc083x->sel0 = 0;
+ adc083x->state = STATE_IDLE;
+ adc083x->bit = 0;
+ adc083x->output = 0;
+
+ if( device->type() == ADC0831 )
+ {
+ adc083x->mux_bits = 0;
+ }
+ else if( device->type() == ADC0832 )
+ {
+ adc083x->mux_bits = 2;
+ }
+ else if( device->type() == ADC0834 )
+ {
+ adc083x->mux_bits = 3;
+ }
+ else if( device->type() == ADC0838 )
+ {
+ adc083x->mux_bits = 4;
+ }
+
+ /* resolve callbacks */
+ adc083x->input_callback_r = intf->input_callback_r;
+
+ /* register for state saving */
+ device->save_item( NAME(adc083x->cs) );
+ device->save_item( NAME(adc083x->clk) );
+ device->save_item( NAME(adc083x->di) );
+ device->save_item( NAME(adc083x->se) );
+ device->save_item( NAME(adc083x->sars) );
+ device->save_item( NAME(adc083x->_do) );
+ device->save_item( NAME(adc083x->sgl) );
+ device->save_item( NAME(adc083x->odd) );
+ device->save_item( NAME(adc083x->sel1) );
+ device->save_item( NAME(adc083x->sel0) );
+ device->save_item( NAME(adc083x->state) );
+ device->save_item( NAME(adc083x->bit) );
+ device->save_item( NAME(adc083x->output) );
+ device->save_item( NAME(adc083x->mux_bits) );
+}
+
+
+/*-------------------------------------------------
+ DEVICE_RESET( adc083x )
+-------------------------------------------------*/
+
+static DEVICE_RESET( adc0831 )
+{
+ adc0831_state *adc083x = get_safe_token( device );
+
+ adc083x_clear_sars( device, adc083x );
+ adc083x->_do = 1;
+ adc083x->state = STATE_IDLE;
+}
+
+/*-------------------------------------------------
+ device definition
+-------------------------------------------------*/
+
+static const char DEVTEMPLATE_SOURCE[] = __FILE__;
+
+#define DEVTEMPLATE_ID( p, s ) p##adc0831##s
+#define DEVTEMPLATE_FEATURES DT_HAS_START | DT_HAS_RESET
+#define DEVTEMPLATE_NAME "A/D Converters 0831"
+#define DEVTEMPLATE_FAMILY "National Semiconductor A/D Converters 083x"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID( p, s ) p##adc0832##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "A/D Converters 0832"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID( p, s ) p##adc0834##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "A/D Converters 0834"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID( p, s ) p##adc0838##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "A/D Converters 0838"
+#include "devtempl.h"
+
+
+DEFINE_LEGACY_DEVICE(ADC0831, adc0831);
+DEFINE_LEGACY_DEVICE(ADC0832, adc0832);
+DEFINE_LEGACY_DEVICE(ADC0834, adc0834);
+DEFINE_LEGACY_DEVICE(ADC0838, adc0838);
diff --git a/trunk/src/emu/machine/adc083x.h b/trunk/src/emu/machine/adc083x.h
new file mode 100644
index 00000000000..6528e695c76
--- /dev/null
+++ b/trunk/src/emu/machine/adc083x.h
@@ -0,0 +1,81 @@
+/***************************************************************************
+
+ National Semiconductor ADC0831 / ADC0832 / ADC0834 / ADC0838
+
+ 8-Bit serial I/O A/D Converters with Muliplexer Options
+
+***************************************************************************/
+
+#ifndef __ADC083X_H__
+#define __ADC083X_H__
+
+#include "devlegcy.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define ADC083X_CH0 0
+#define ADC083X_CH1 1
+#define ADC083X_CH2 2
+#define ADC083X_CH3 3
+#define ADC083X_CH4 4
+#define ADC083X_CH5 5
+#define ADC083X_CH6 6
+#define ADC083X_CH7 7
+#define ADC083X_COM 8
+#define ADC083X_AGND 9
+#define ADC083X_VREF 10
+
+/***************************************************************************
+ MACROS / CONSTANTS
+***************************************************************************/
+
+DECLARE_LEGACY_DEVICE(ADC0831, adc0831);
+DECLARE_LEGACY_DEVICE(ADC0832, adc0832);
+DECLARE_LEGACY_DEVICE(ADC0834, adc0834);
+DECLARE_LEGACY_DEVICE(ADC0838, adc0838);
+
+#define MCFG_ADC0831_ADD(_tag, _config) \
+ MCFG_DEVICE_ADD(_tag, ADC0831, 0) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MCFG_ADC0832_ADD(_tag, _config) \
+ MCFG_DEVICE_ADD(_tag, ADC0832, 0) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MCFG_ADC0834_ADD(_tag, _config) \
+ MCFG_DEVICE_ADD(_tag, ADC0834, 0) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MCFG_ADC0838_ADD(_tag, _config) \
+ MCFG_DEVICE_ADD(_tag, ADC0838, 0) \
+ MCFG_DEVICE_CONFIG(_config)
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef double (*adc083x_input_convert_func)(device_t *device, UINT8 input);
+
+typedef struct _adc083x_interface adc083x_interface;
+struct _adc083x_interface
+{
+ adc083x_input_convert_func input_callback_r;
+};
+
+
+/***************************************************************************
+ PROTOTYPES
+***************************************************************************/
+
+extern WRITE_LINE_DEVICE_HANDLER( adc083x_cs_write );
+extern WRITE_LINE_DEVICE_HANDLER( adc083x_clk_write );
+extern WRITE_LINE_DEVICE_HANDLER( adc083x_di_write );
+extern WRITE_LINE_DEVICE_HANDLER( adc083x_se_write );
+extern READ_LINE_DEVICE_HANDLER( adc083x_sars_read );
+extern READ_LINE_DEVICE_HANDLER( adc083x_do_read );
+
+#endif /* __ADC083X_H__ */
diff --git a/trunk/src/emu/machine/adc1038.c b/trunk/src/emu/machine/adc1038.c
new file mode 100644
index 00000000000..acf2ee32274
--- /dev/null
+++ b/trunk/src/emu/machine/adc1038.c
@@ -0,0 +1,177 @@
+/***************************************************************************
+
+ National Semiconductor ADC1038
+
+ 10-Bit Serial I/O A/D Converters with Analog Multiplexer and
+ Track/hold Function
+
+***************************************************************************/
+
+#include "emu.h"
+#include "adc1038.h"
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _adc1038_state adc1038_state;
+struct _adc1038_state
+{
+ int cycle;
+ int clk;
+ int adr;
+ int data_in;
+ int data_out;
+ int adc_data;
+ int sars;
+ adc1038_input_read_func input_callback_r;
+
+ int gticlub_hack;
+};
+
+/*****************************************************************************
+ INLINE FUNCTIONS
+*****************************************************************************/
+
+INLINE adc1038_state *adc1038_get_safe_token( device_t *device )
+{
+ assert(device != NULL);
+ assert(device->type() == ADC1038);
+
+ return (adc1038_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+INLINE const adc1038_interface *adc1038_get_interface( device_t *device )
+{
+ assert(device != NULL);
+ assert((device->type() == ADC1038));
+ return (const adc1038_interface *) device->static_config();
+}
+
+/*****************************************************************************
+ DEVICE HANDLERS
+*****************************************************************************/
+
+READ_LINE_DEVICE_HANDLER( adc1038_do_read )
+{
+ adc1038_state *adc1038 = adc1038_get_safe_token(device);
+
+ //printf("ADC DO\n");
+ return adc1038->data_out;
+}
+
+WRITE_LINE_DEVICE_HANDLER( adc1038_di_write )
+{
+ adc1038_state *adc1038 = adc1038_get_safe_token(device);
+
+ adc1038->data_in = state;
+}
+
+WRITE_LINE_DEVICE_HANDLER( adc1038_clk_write )
+{
+ adc1038_state *adc1038 = adc1038_get_safe_token(device);
+
+ // GTI Club doesn't sync on SARS
+ if (adc1038->gticlub_hack)
+ {
+ if (adc1038->clk == 0 && state == 0)
+ {
+ adc1038->cycle = 0;
+
+ /* notice that adc1038->adr is always < 7! */
+ adc1038->adc_data = adc1038->input_callback_r(device, adc1038->adr);
+ }
+ }
+
+ if (state == 1)
+ {
+ //printf("ADC CLK, DI = %d, cycle = %d\n", adc1038->data_in, adc1038->cycle);
+
+ if (adc1038->cycle == 0) // A2
+ {
+ adc1038->adr = 0;
+ adc1038->adr |= (adc1038->data_in << 2);
+ }
+ else if (adc1038->cycle == 1) // A1
+ {
+ adc1038->adr |= (adc1038->data_in << 1);
+ }
+ else if (adc1038->cycle == 2) // A0
+ {
+ adc1038->adr |= (adc1038->data_in << 0);
+ }
+
+ adc1038->data_out = (adc1038->adc_data & 0x200) ? 1 : 0;
+ adc1038->adc_data <<= 1;
+
+ adc1038->cycle++;
+ }
+
+ adc1038->clk = state;
+}
+
+READ_LINE_DEVICE_HANDLER( adc1038_sars_read )
+{
+ adc1038_state *adc1038 = adc1038_get_safe_token(device);
+
+ adc1038->cycle = 0;
+
+ /* notice that adc1038->adr is always < 7! */
+ adc1038->adc_data = adc1038->input_callback_r(device, adc1038->adr);
+
+ adc1038->data_out = (adc1038->adc_data & 0x200) ? 1 : 0;
+ adc1038->adc_data <<= 1;
+
+ adc1038->sars ^= 1;
+ return adc1038->sars;
+}
+
+
+/*****************************************************************************
+ DEVICE INTERFACE
+*****************************************************************************/
+
+static DEVICE_START( adc1038 )
+{
+ adc1038_state *adc1038 = adc1038_get_safe_token(device);
+ const adc1038_interface *intf = adc1038_get_interface(device);
+
+ adc1038->gticlub_hack = intf->gticlub_hack;
+ adc1038->input_callback_r = intf->input_callback_r;
+
+ device->save_item(NAME(adc1038->cycle));
+ device->save_item(NAME(adc1038->clk));
+ device->save_item(NAME(adc1038->adr));
+ device->save_item(NAME(adc1038->data_in));
+ device->save_item(NAME(adc1038->data_out));
+ device->save_item(NAME(adc1038->adc_data));
+ device->save_item(NAME(adc1038->sars));
+}
+
+static DEVICE_RESET( adc1038 )
+{
+ adc1038_state *adc1038 = adc1038_get_safe_token(device);
+
+ adc1038->cycle = 0;
+ adc1038->clk = 0;
+ adc1038->adr = 0;
+ adc1038->data_in = 0;
+ adc1038->data_out = 0;
+ adc1038->adc_data = 0;
+ adc1038->sars = 1;
+}
+
+/*-------------------------------------------------
+ device definition
+-------------------------------------------------*/
+
+static const char DEVTEMPLATE_SOURCE[] = __FILE__;
+
+#define DEVTEMPLATE_ID( p, s ) p##adc1038##s
+#define DEVTEMPLATE_FEATURES DT_HAS_START | DT_HAS_RESET
+#define DEVTEMPLATE_NAME "A/D Converters 1038"
+#define DEVTEMPLATE_FAMILY "National Semiconductor A/D Converters 1038"
+#include "devtempl.h"
+
+
+DEFINE_LEGACY_DEVICE(ADC1038, adc1038);
diff --git a/trunk/src/emu/machine/adc1038.h b/trunk/src/emu/machine/adc1038.h
new file mode 100644
index 00000000000..47dcee0d862
--- /dev/null
+++ b/trunk/src/emu/machine/adc1038.h
@@ -0,0 +1,50 @@
+/***************************************************************************
+
+ National Semiconductor ADC1038
+
+ 10-Bit Serial I/O A/D Converters with Analog Multiplexer and
+ Track/hold Function
+
+***************************************************************************/
+
+#ifndef __ADC1038_H__
+#define __ADC1038_H__
+
+#include "devlegcy.h"
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef int (*adc1038_input_read_func)(device_t *device, int input);
+
+typedef struct _adc1038_interface adc1038_interface;
+struct _adc1038_interface
+{
+ int gticlub_hack;
+ adc1038_input_read_func input_callback_r;
+};
+
+
+/***************************************************************************
+ MACROS / CONSTANTS
+***************************************************************************/
+
+DECLARE_LEGACY_DEVICE(ADC1038, adc1038);
+
+#define MCFG_ADC1038_ADD(_tag, _config) \
+ MCFG_DEVICE_ADD(_tag, ADC1038, 0) \
+ MCFG_DEVICE_CONFIG(_config)
+
+
+/***************************************************************************
+ DEVICE I/O FUNCTIONS
+***************************************************************************/
+
+extern READ_LINE_DEVICE_HANDLER( adc1038_do_read );
+extern READ_LINE_DEVICE_HANDLER( adc1038_sars_read );
+extern WRITE_LINE_DEVICE_HANDLER( adc1038_di_write );
+extern WRITE_LINE_DEVICE_HANDLER( adc1038_clk_write );
+
+#endif /* __ADC1038_H__ */
diff --git a/trunk/src/emu/machine/adc1213x.c b/trunk/src/emu/machine/adc1213x.c
new file mode 100644
index 00000000000..38a589c122d
--- /dev/null
+++ b/trunk/src/emu/machine/adc1213x.c
@@ -0,0 +1,377 @@
+/***************************************************************************
+
+ National Semiconductor ADC12130 / ADC12132 / ADC12138
+
+ Self-calibrating 12-bit Plus Sign Serial I/O A/D Converters with MUX
+ and Sample/Hold
+
+ TODO:
+ - Only ADC12138 currently supported
+
+ 2009-06 Converted to be a device
+
+***************************************************************************/
+
+#include "emu.h"
+#include "adc1213x.h"
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _adc12138_state adc12138_state;
+struct _adc12138_state
+{
+ adc1213x_input_convert_func input_callback_r;
+
+ int cycle;
+ int data_out;
+ int data_in;
+ int conv_mode;
+ int auto_cal;
+ int auto_zero;
+ int acq_time;
+ int data_out_sign;
+ int mode;
+ int input_shift_reg;
+ int output_shift_reg;
+ int end_conv;
+};
+
+
+#define ADC1213X_CONV_MODE_12_MSB_FIRST 0
+#define ADC1213X_CONV_MODE_16_MSB_FIRST 1
+#define ADC1213X_CONV_MODE_12_LSB_FIRST 2
+#define ADC1213X_CONV_MODE_16_LSB_FIRST 3
+
+#define ADC1213X_ACQUISITION_TIME_6_CCLK 0
+#define ADC1213X_ACQUISITION_TIME_10_CCLK 1
+#define ADC1213X_ACQUISITION_TIME_18_CCLK 2
+#define ADC1213X_ACQUISITION_TIME_34_CCLK 3
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE adc12138_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert((device->type() == ADC12130) || (device->type() == ADC12132) || (device->type() == ADC12138));
+ return (adc12138_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+INLINE const adc12138_interface *get_interface(device_t *device)
+{
+ assert(device != NULL);
+ assert((device->type() == ADC12130) || (device->type() == ADC12132) || (device->type() == ADC12138));
+ return (const adc12138_interface *) device->static_config();
+}
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ adc1213x_di_w
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER( adc1213x_di_w )
+{
+ adc12138_state *adc1213x = get_safe_token(device);
+ adc1213x->data_in = data & 1;
+}
+
+/*-------------------------------------------------
+ adc1213x_convert
+-------------------------------------------------*/
+
+static void adc1213x_convert(device_t *device, int channel, int bits16, int lsbfirst)
+{
+ adc12138_state *adc1213x = get_safe_token(device);
+ int i;
+ int bits;
+ int input_value;
+ double input = 0;
+
+ if (bits16)
+ fatalerror("ADC1213X: 16-bit mode not supported\n");
+
+ if (lsbfirst)
+ fatalerror("ADC1213X: LSB first not supported\n");
+
+ switch (channel)
+ {
+ case 0x8: // H L L L - CH0 (single-ended)
+ {
+ input = adc1213x->input_callback_r(device, 0);
+ break;
+ }
+ case 0xc: // H H L L - CH1 (single-ended)
+ {
+ input = adc1213x->input_callback_r(device, 1);
+ break;
+ }
+ case 0x9: // H L L H - CH2 (single-ended)
+ {
+ input = adc1213x->input_callback_r(device, 2);
+ break;
+ }
+ case 0xd: // H H L H - CH3 (single-ended)
+ {
+ input = adc1213x->input_callback_r(device, 3);
+ break;
+ }
+ case 0xa: // H L H L - CH4 (single-ended)
+ {
+ input = adc1213x->input_callback_r(device, 4);
+ break;
+ }
+ case 0xe: // H H H L - CH5 (single-ended)
+ {
+ input = adc1213x->input_callback_r(device, 5);
+ break;
+ }
+ case 0xb: // H L H H - CH6 (single-ended)
+ {
+ input = adc1213x->input_callback_r(device, 6);
+ break;
+ }
+ case 0xf: // H H H H - CH7 (single-ended)
+ {
+ input = adc1213x->input_callback_r(device, 7);
+ break;
+ }
+ default:
+ {
+ fatalerror("ADC1213X: unsupported channel %02X\n", channel);
+ }
+ }
+
+ input_value = (int)(input * 2047.0);
+
+ bits = 12;
+
+ // sign-extend if needed
+ if (adc1213x->data_out_sign)
+ {
+ input_value = input_value | ((input_value & 0x800) << 1);
+ bits++;
+ }
+
+ adc1213x->output_shift_reg = 0;
+
+ for (i=0; i < bits; i++)
+ {
+ if (input_value & (1 << ((bits-1) - i)))
+ {
+ adc1213x->output_shift_reg |= (1 << i);
+ }
+ }
+
+ adc1213x->data_out = adc1213x->output_shift_reg & 1;
+ adc1213x->output_shift_reg >>= 1;
+}
+
+/*-------------------------------------------------
+ adc1213x_cs_w
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER( adc1213x_cs_w )
+{
+ adc12138_state *adc1213x = get_safe_token(device);
+
+ if (data)
+ {
+ //printf("ADC: CS\n");
+
+ if (adc1213x->cycle >= 7)
+ {
+ int mode = adc1213x->input_shift_reg >> (adc1213x->cycle - 8);
+
+ switch (mode & 0xf)
+ {
+ case 0x0: // X X X X L L L L - 12 or 13 Bit MSB First conversion
+ {
+ adc1213x_convert(device, (mode >> 4) & 0xf, 0, 0);
+ break;
+ }
+ case 0x1: // X X X X L L L H - 16 or 17 Bit MSB First conversion
+ {
+ adc1213x_convert(device, (mode >> 4) & 0xf, 1, 0);
+ break;
+ }
+ case 0x4: // X X X X L H L L - 12 or 13 Bit LSB First conversion
+ {
+ adc1213x_convert(device, (mode >> 4) & 0xf, 0, 1);
+ break;
+ }
+ case 0x5: // X X X X L H L H - 16 or 17 Bit LSB First conversion
+ {
+ adc1213x_convert(device, (mode >> 4) & 0xf, 1, 1);
+ break;
+ }
+
+ default:
+ {
+ switch (mode)
+ {
+ case 0x08: // L L L L H L L L - Auto cal
+ {
+ adc1213x->auto_cal = 1;
+ break;
+ }
+
+ case 0x0e: // L L L L H H H L - Acquisition time 6 CCLK cycles
+ {
+ adc1213x->acq_time = ADC1213X_ACQUISITION_TIME_6_CCLK;
+ break;
+ }
+
+ case 0x8d: // H L L L H H L H - Data out with sign
+ {
+ adc1213x->data_out_sign = 1;
+ break;
+ }
+
+ default:
+ {
+ fatalerror("ADC1213X: unknown config mode %02X\n", mode);
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ adc1213x->cycle = 0;
+ adc1213x->input_shift_reg = 0;
+
+ adc1213x->end_conv = 0;
+ }
+}
+
+/*-------------------------------------------------
+ adc1213x_sclk_w
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER( adc1213x_sclk_w )
+{
+ adc12138_state *adc1213x = get_safe_token(device);
+
+ if (data)
+ {
+ //printf("ADC: cycle %d, DI = %d\n", adc1213x->cycle, adc1213x->data_in);
+
+ adc1213x->input_shift_reg <<= 1;
+ adc1213x->input_shift_reg |= adc1213x->data_in;
+
+ adc1213x->data_out = adc1213x->output_shift_reg & 1;
+ adc1213x->output_shift_reg >>= 1;
+
+ adc1213x->cycle++;
+ }
+}
+
+/*-------------------------------------------------
+ adc1213x_conv_w
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER( adc1213x_conv_w )
+{
+ adc12138_state *adc1213x = get_safe_token(device);
+ adc1213x->end_conv = 1;
+}
+
+/*-------------------------------------------------
+ adc1213x_do_r
+-------------------------------------------------*/
+
+READ8_DEVICE_HANDLER( adc1213x_do_r )
+{
+ adc12138_state *adc1213x = get_safe_token(device);
+
+ //printf("ADC: DO\n");
+ return adc1213x->data_out;
+}
+
+/*-------------------------------------------------
+ adc1213x_eoc_r
+-------------------------------------------------*/
+
+READ8_DEVICE_HANDLER( adc1213x_eoc_r )
+{
+ adc12138_state *adc1213x = get_safe_token(device);
+ return adc1213x->end_conv;
+}
+
+/*-------------------------------------------------
+ DEVICE_START( adc1213x )
+-------------------------------------------------*/
+
+static DEVICE_START( adc12138 )
+{
+ adc12138_state *adc1213x = get_safe_token(device);
+ const adc12138_interface *intf = get_interface(device);
+
+ /* resolve callbacks */
+ adc1213x->input_callback_r = intf->input_callback_r;
+
+ /* register for state saving */
+ device->save_item(NAME(adc1213x->cycle));
+ device->save_item(NAME(adc1213x->data_out));
+ device->save_item(NAME(adc1213x->data_in));
+ device->save_item(NAME(adc1213x->conv_mode));
+ device->save_item(NAME(adc1213x->auto_cal));
+ device->save_item(NAME(adc1213x->auto_zero));
+ device->save_item(NAME(adc1213x->acq_time));
+ device->save_item(NAME(adc1213x->data_out_sign));
+ device->save_item(NAME(adc1213x->mode));
+ device->save_item(NAME(adc1213x->input_shift_reg));
+ device->save_item(NAME(adc1213x->output_shift_reg));
+ device->save_item(NAME(adc1213x->end_conv));
+}
+
+
+/*-------------------------------------------------
+ DEVICE_RESET( adc1213x )
+-------------------------------------------------*/
+
+static DEVICE_RESET( adc12138 )
+{
+ adc12138_state *adc1213x = get_safe_token(device);
+
+ adc1213x->conv_mode = ADC1213X_CONV_MODE_12_MSB_FIRST;
+ adc1213x->data_out_sign = 1;
+ adc1213x->auto_cal = 0;
+ adc1213x->auto_zero = 0;
+ adc1213x->acq_time = ADC1213X_ACQUISITION_TIME_10_CCLK;
+}
+
+/*-------------------------------------------------
+ device definition
+-------------------------------------------------*/
+
+static const char DEVTEMPLATE_SOURCE[] = __FILE__;
+
+#define DEVTEMPLATE_ID(p,s) p##adc12138##s
+#define DEVTEMPLATE_FEATURES DT_HAS_START | DT_HAS_RESET
+#define DEVTEMPLATE_NAME "A/D Converter 12138"
+#define DEVTEMPLATE_FAMILY "National Semiconductor A/D Converters 1213x"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##adc12130##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "A/D Converter 12130"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##adc12132##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "A/D Converter 12132"
+#include "devtempl.h"
+
+
+DEFINE_LEGACY_DEVICE(ADC12130, adc12130);
+DEFINE_LEGACY_DEVICE(ADC12132, adc12132);
+DEFINE_LEGACY_DEVICE(ADC12138, adc12138);
diff --git a/trunk/src/emu/machine/adc1213x.h b/trunk/src/emu/machine/adc1213x.h
new file mode 100644
index 00000000000..4bb45bb2e46
--- /dev/null
+++ b/trunk/src/emu/machine/adc1213x.h
@@ -0,0 +1,60 @@
+/***************************************************************************
+
+ National Semiconductor ADC12130 / ADC12132 / ADC12138
+
+ Self-calibrating 12-bit Plus Sign Serial I/O A/D Converters with MUX
+ and Sample/Hold
+
+***************************************************************************/
+
+#ifndef __ADC1213X_H__
+#define __ADC1213X_H__
+
+#include "devlegcy.h"
+
+
+/***************************************************************************
+ MACROS / CONSTANTS
+***************************************************************************/
+
+DECLARE_LEGACY_DEVICE(ADC12130, adc12130);
+DECLARE_LEGACY_DEVICE(ADC12132, adc12132);
+DECLARE_LEGACY_DEVICE(ADC12138, adc12138);
+
+#define MCFG_ADC12130_ADD(_tag, _config) \
+ MCFG_DEVICE_ADD(_tag, ADC12130, 0) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MCFG_ADC12132_ADD(_tag, _config) \
+ MCFG_DEVICE_ADD(_tag, ADC12132, 0) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MCFG_ADC12138_ADD(_tag, _config) \
+ MCFG_DEVICE_ADD(_tag, ADC12138, 0) \
+ MCFG_DEVICE_CONFIG(_config)
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef double (*adc1213x_input_convert_func)(device_t *device, UINT8 input);
+
+typedef struct _adc12138_interface adc12138_interface;
+struct _adc12138_interface
+{
+ adc1213x_input_convert_func input_callback_r;
+};
+
+/***************************************************************************
+ PROTOTYPES
+***************************************************************************/
+
+extern WRITE8_DEVICE_HANDLER( adc1213x_di_w );
+extern WRITE8_DEVICE_HANDLER( adc1213x_cs_w );
+extern WRITE8_DEVICE_HANDLER( adc1213x_sclk_w );
+extern WRITE8_DEVICE_HANDLER( adc1213x_conv_w );
+extern READ8_DEVICE_HANDLER( adc1213x_do_r );
+extern READ8_DEVICE_HANDLER( adc1213x_eoc_r );
+
+#endif /* __ADC1213X_H__ */
diff --git a/trunk/src/emu/machine/am53cf96.c b/trunk/src/emu/machine/am53cf96.c
new file mode 100644
index 00000000000..e994969d477
--- /dev/null
+++ b/trunk/src/emu/machine/am53cf96.c
@@ -0,0 +1,289 @@
+/*
+ * am53cf96.c
+ *
+ * AMD/NCR/Symbios 53CF96 SCSI-2 controller.
+ * Qlogic FAS-236 and Emulex ESP-236 are equivalents
+ *
+ * References:
+ * AMD Am53CF96 manual
+ *
+ */
+
+#include "emu.h"
+#include "am53cf96.h"
+
+static UINT8 scsi_regs[32], fifo[16], fptr = 0, xfer_state, last_id;
+static const struct AM53CF96interface *intf;
+
+static SCSIInstance *devices[8]; // SCSI IDs 0-7
+
+// 53CF96 register set
+enum
+{
+ REG_XFERCNTLOW = 0, // read = current xfer count lo byte, write = set xfer count lo byte
+ REG_XFERCNTMID, // read = current xfer count mid byte, write = set xfer count mid byte
+ REG_FIFO, // read/write = FIFO
+ REG_COMMAND, // read/write = command
+
+ REG_STATUS, // read = status, write = destination SCSI ID (4)
+ REG_IRQSTATE, // read = IRQ status, write = timeout (5)
+ REG_INTSTATE, // read = internal state, write = sync xfer period (6)
+ REG_FIFOSTATE, // read = FIFO status, write = sync offset
+ REG_CTRL1, // read/write = control 1
+ REG_CLOCKFCTR, // clock factor (write only)
+ REG_TESTMODE, // test mode (write only)
+ REG_CTRL2, // read/write = control 2
+ REG_CTRL3, // read/write = control 3
+ REG_CTRL4, // read/write = control 4
+ REG_XFERCNTHI, // read = current xfer count hi byte, write = set xfer count hi byte
+ REG_DATAALIGN // data alignment (write only)
+};
+
+READ32_HANDLER( am53cf96_r )
+{
+ int reg, shift, rv;
+ static const int states[] = { 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 0 };
+
+ reg = offset * 2;
+ if (mem_mask == 0x000000ff)
+ {
+ shift = 0;
+ }
+ else
+ {
+ reg++;
+ shift = 16;
+ }
+
+ if (reg == REG_STATUS)
+ {
+ scsi_regs[REG_STATUS] &= ~0x7;
+ scsi_regs[REG_STATUS] |= states[xfer_state];
+ if (xfer_state < 10)
+ {
+ xfer_state++;
+ }
+ }
+
+ rv = scsi_regs[reg]<<shift;
+
+ if (reg == REG_FIFO)
+ {
+// mame_printf_debug("53cf96: read FIFO PC=%x\n", cpu_get_pc(&space->device()));
+ return 0;
+ }
+
+// logerror("53cf96: read reg %d = %x (PC=%x)\n", reg, rv>>shift, cpu_get_pc(&space->device()));
+
+ if (reg == REG_IRQSTATE)
+ {
+ scsi_regs[REG_STATUS] &= ~0x80; // clear IRQ flag
+ }
+
+ return rv;
+}
+
+static TIMER_CALLBACK( am53cf96_irq )
+{
+ scsi_regs[REG_IRQSTATE] = 8; // indicate success
+ scsi_regs[REG_STATUS] |= 0x80; // indicate IRQ
+ intf->irq_callback(machine);
+}
+
+WRITE32_HANDLER( am53cf96_w )
+{
+ int reg, val/*, dma*/;
+
+ reg = offset * 2;
+ val = data;
+ if (mem_mask == 0x000000ff)
+ {
+ }
+ else
+ {
+ reg++;
+ val >>= 16;
+ }
+ val &= 0xff;
+
+// logerror("53cf96: w %x to reg %d (ofs %02x data %08x mask %08x PC=%x)\n", val, reg, offset, data, mem_mask, cpu_get_pc(&space->device()));
+
+ // if writing to the target ID, cache it off for later
+ if (reg == REG_STATUS)
+ {
+ last_id = val;
+ }
+
+ if (reg == REG_XFERCNTLOW || reg == REG_XFERCNTMID || reg == REG_XFERCNTHI)
+ {
+ scsi_regs[REG_STATUS] &= ~0x10; // clear CTZ bit
+ }
+
+ // FIFO
+ if (reg == REG_FIFO)
+ {
+// mame_printf_debug("%02x to FIFO @ %02d\n", val, fptr);
+ fifo[fptr++] = val;
+ if (fptr > 15)
+ {
+ fptr = 15;
+ }
+ }
+
+ // command
+ if (reg == REG_COMMAND)
+ {
+ //dma = (val & 0x80) ? 1 : 0;
+ fptr = 0;
+ switch (val & 0x7f)
+ {
+ case 0: // NOP
+ scsi_regs[REG_IRQSTATE] = 8; // indicate success
+ xfer_state = 0;
+ break;
+ case 2: // reset device
+ scsi_regs[REG_IRQSTATE] = 8; // indicate success
+
+ logerror("53cf96: reset target ID = %d (PC = %x)\n", last_id, cpu_get_pc(&space->device()));
+ if (devices[last_id])
+ {
+ SCSIReset( devices[last_id] );
+ }
+ else
+ {
+ logerror("53cf96: reset request for unknown device SCSI ID %d\n", last_id);
+ }
+
+ xfer_state = 0;
+ break;
+ case 3: // reset SCSI bus
+ scsi_regs[REG_INTSTATE] = 4; // command sent OK
+ xfer_state = 0;
+ space->machine().scheduler().timer_set( attotime::from_hz( 16384 ), FUNC(am53cf96_irq ));
+ break;
+ case 0x42: // select with ATN steps
+ space->machine().scheduler().timer_set( attotime::from_hz( 16384 ), FUNC(am53cf96_irq ));
+ if ((fifo[1] == 0) || (fifo[1] == 0x48) || (fifo[1] == 0x4b))
+ {
+ scsi_regs[REG_INTSTATE] = 6;
+ }
+ else
+ {
+ scsi_regs[REG_INTSTATE] = 4;
+ }
+
+ logerror("53cf96: command %x exec. target ID = %d (PC = %x)\n", fifo[1], last_id, cpu_get_pc(&space->device()));
+ if (devices[last_id])
+ {
+ int length;
+
+ SCSISetCommand( devices[last_id], &fifo[1], 12 );
+ SCSIExecCommand( devices[last_id], &length );
+ }
+ else
+ {
+ logerror("53cf96: request for unknown device SCSI ID %d\n", last_id);
+ }
+ xfer_state = 0;
+ break;
+ case 0x44: // enable selection/reselection
+ xfer_state = 0;
+ break;
+ case 0x10: // information transfer (must not change xfer_state)
+ case 0x11: // second phase of information transfer
+ case 0x12: // message accepted
+ space->machine().scheduler().timer_set( attotime::from_hz( 16384 ), FUNC(am53cf96_irq ));
+ scsi_regs[REG_INTSTATE] = 6; // command sent OK
+ break;
+ default:
+ printf( "unsupported command %02x\n", val );
+ break;
+ }
+ }
+
+ // only update the register mirror if it's not a write-only reg
+ if (reg != REG_STATUS && reg != REG_INTSTATE && reg != REG_IRQSTATE && reg != REG_FIFOSTATE)
+ {
+ scsi_regs[reg] = val;
+ }
+}
+
+void am53cf96_init( running_machine &machine, const struct AM53CF96interface *interface )
+{
+ int i;
+
+ // save interface pointer for later
+ intf = interface;
+
+ memset(scsi_regs, 0, sizeof(scsi_regs));
+ memset(devices, 0, sizeof(devices));
+
+ // try to open the devices
+ for (i = 0; i < interface->scsidevs->devs_present; i++)
+ {
+ SCSIAllocInstance( machine, interface->scsidevs->devices[i].scsiClass, &devices[interface->scsidevs->devices[i].scsiID], interface->scsidevs->devices[i].diskregion );
+ }
+
+ state_save_register_global_array(machine, scsi_regs);
+ state_save_register_global_array(machine, fifo);
+ state_save_register_global(machine, fptr);
+ state_save_register_global(machine, xfer_state);
+ state_save_register_global(machine, last_id);
+}
+
+void am53cf96_exit( const struct AM53CF96interface *interface )
+{
+ int i;
+
+ for (i = 0; i < interface->scsidevs->devs_present; i++)
+ {
+ SCSIDeleteInstance( devices[interface->scsidevs->devices[i].scsiID] );
+ }
+}
+
+// retrieve data from the SCSI controller
+void am53cf96_read_data(int bytes, UINT8 *pData)
+{
+ scsi_regs[REG_STATUS] |= 0x10; // indicate DMA finished
+
+ if (devices[last_id])
+ {
+ SCSIReadData( devices[last_id], pData, bytes );
+ }
+ else
+ {
+ logerror("53cf96: request for unknown device SCSI ID %d\n", last_id);
+ }
+}
+
+// write data to the SCSI controller
+void am53cf96_write_data(int bytes, UINT8 *pData)
+{
+// int i;
+
+ scsi_regs[REG_STATUS] |= 0x10; // indicate DMA finished
+
+ if (devices[last_id])
+ {
+ SCSIWriteData( devices[last_id], pData, bytes );
+ }
+ else
+ {
+ logerror("53cf96: request for unknown device SCSI ID %d\n", last_id);
+ }
+}
+
+// get the device handle (HD or CD) for the specified SCSI ID
+void *am53cf96_get_device(int id)
+{
+ void *ret;
+
+ if (devices[id])
+ {
+ logerror("53cf96: fetching dev pointer for SCSI ID %d\n", id);
+ SCSIGetDevice( devices[id], &ret );
+ return ret;
+ }
+
+ return NULL;
+}
diff --git a/trunk/src/emu/machine/am53cf96.h b/trunk/src/emu/machine/am53cf96.h
new file mode 100644
index 00000000000..df74b4a80aa
--- /dev/null
+++ b/trunk/src/emu/machine/am53cf96.h
@@ -0,0 +1,25 @@
+/*
+ * am53cf96.h
+ *
+ */
+
+#ifndef _AM53CF96_H_
+#define _AM53CF96_H_
+
+#include "scsi.h"
+
+struct AM53CF96interface
+{
+ const SCSIConfigTable *scsidevs; /* SCSI devices */
+ void (*irq_callback)(running_machine &machine); /* irq callback */
+};
+
+extern void am53cf96_init( running_machine &machine, const struct AM53CF96interface *interface );
+extern void am53cf96_exit( const struct AM53CF96interface *interface );
+extern void am53cf96_read_data(int bytes, UINT8 *pData);
+void am53cf96_write_data(int bytes, UINT8 *pData);
+void *am53cf96_get_device(int id);
+extern READ32_HANDLER( am53cf96_r );
+extern WRITE32_HANDLER( am53cf96_w );
+
+#endif
diff --git a/trunk/src/emu/machine/am8530h.c b/trunk/src/emu/machine/am8530h.c
new file mode 100644
index 00000000000..7c5e311f908
--- /dev/null
+++ b/trunk/src/emu/machine/am8530h.c
@@ -0,0 +1,57 @@
+#include "am8530h.h"
+
+const device_type AM8530H = &device_creator<am8530h_device>;
+
+am8530h_device::am8530h_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, AM8530H, "AM8530H", tag, owner, clock)
+{
+}
+
+void am8530h_device::set_int_change_cb(int_cb_t _int_change_cb)
+{
+ int_change_cb = _int_change_cb;
+}
+
+
+void am8530h_device::device_start()
+{
+}
+
+READ8_MEMBER( am8530h_device::ca_r )
+{
+ return 0xff;
+}
+
+READ8_MEMBER( am8530h_device::cb_r )
+{
+ return 0xff;
+}
+
+READ8_MEMBER( am8530h_device::da_r )
+{
+ return 0x40;
+}
+
+READ8_MEMBER( am8530h_device::db_r )
+{
+ return 0x40;
+}
+
+WRITE8_MEMBER( am8530h_device::ca_w )
+{
+ fprintf(stderr, "ca_w %x, %02x\n", offset, data);
+}
+
+WRITE8_MEMBER( am8530h_device::cb_w )
+{
+ fprintf(stderr, "cb_w %x, %02x\n", offset, data);
+}
+
+WRITE8_MEMBER( am8530h_device::da_w )
+{
+ fprintf(stderr, "da_w %x, %02x\n", offset, data);
+}
+
+WRITE8_MEMBER( am8530h_device::db_w )
+{
+ fprintf(stderr, "db_w %x, %02x\n", offset, data);
+}
diff --git a/trunk/src/emu/machine/am8530h.h b/trunk/src/emu/machine/am8530h.h
new file mode 100644
index 00000000000..6797e16e20c
--- /dev/null
+++ b/trunk/src/emu/machine/am8530h.h
@@ -0,0 +1,42 @@
+#ifndef __AM8530H_H__
+#define __AM8530H_H__
+
+#include "emu.h"
+
+#define MCFG_AM8530H_ADD(_tag, _int_change_cb) \
+ MCFG_DEVICE_ADD(_tag, AM8530H, 0) \
+ downcast<am8530h_device *>(device)->set_int_change_cb(_int_change_cb);
+
+class am8530h_device : public device_t {
+public:
+ typedef delegate<void ()> int_cb_t;
+
+ am8530h_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ void set_int_change_cb(int_cb_t int_change_cb);
+
+ DECLARE_READ8_MEMBER(ca_r);
+ DECLARE_READ8_MEMBER(cb_r);
+ DECLARE_READ8_MEMBER(da_r);
+ DECLARE_READ8_MEMBER(db_r);
+
+ DECLARE_WRITE8_MEMBER(ca_w);
+ DECLARE_WRITE8_MEMBER(cb_w);
+ DECLARE_WRITE8_MEMBER(da_w);
+ DECLARE_WRITE8_MEMBER(db_w);
+
+ void data_a_w(UINT8 val);
+ void data_b_w(UINT8 val);
+
+ void int_ack();
+ bool int_level_get();
+
+protected:
+ virtual void device_start();
+
+private:
+ int_cb_t int_change_cb;
+};
+
+extern const device_type AM8530H;
+
+#endif
diff --git a/trunk/src/emu/machine/at28c16.c b/trunk/src/emu/machine/at28c16.c
new file mode 100644
index 00000000000..1101b3ee8e4
--- /dev/null
+++ b/trunk/src/emu/machine/at28c16.c
@@ -0,0 +1,295 @@
+/***************************************************************************
+ ATMEL AT28C16
+
+ 16K ( 2K x 8 ) Parallel EEPROM
+
+***************************************************************************/
+
+#include "emu.h"
+#include "machine/at28c16.h"
+
+#define AT28C16_DATA_BYTES ( 0x800 )
+#define AT28C16_ID_BYTES ( 0x20 )
+#define AT28C16_TOTAL_BYTES ( AT28C16_DATA_BYTES + AT28C16_ID_BYTES )
+
+#define AT28C16_ID_OFFSET ( AT28C16_DATA_BYTES - AT28C16_ID_BYTES )
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+static ADDRESS_MAP_START( at28c16_map8, AS_PROGRAM, 8 )
+ AM_RANGE(0x0000, 0x081f) AM_RAM
+ADDRESS_MAP_END
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type AT28C16 = &device_creator<at28c16_device>;
+
+//-------------------------------------------------
+// at28c16_device - constructor
+//-------------------------------------------------
+
+at28c16_device::at28c16_device( const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock )
+ : device_t(mconfig, AT28C16, "AT28C16", tag, owner, clock),
+ device_memory_interface(mconfig, *this),
+ device_nvram_interface(mconfig, *this),
+ m_a9_12v( 0 ),
+ m_oe_12v( 0 ),
+ m_last_write( -1 )
+{
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void at28c16_device::device_config_complete()
+{
+ m_space_config = address_space_config( "at28c16", ENDIANNESS_BIG, 8, 12, 0, *ADDRESS_MAP_NAME( at28c16_map8 ) );
+}
+
+
+//-------------------------------------------------
+// device_validity_check - perform validity checks
+// on this device
+//-------------------------------------------------
+
+bool at28c16_device::device_validity_check( emu_options &options, const game_driver &driver ) const
+{
+ return false;
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return a description of
+// any address spaces owned by this device
+//-------------------------------------------------
+
+const address_space_config *at28c16_device::memory_space_config( address_spacenum spacenum ) const
+{
+ return ( spacenum == 0 ) ? &m_space_config : NULL;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void at28c16_device::device_start()
+{
+ m_write_timer = machine().scheduler().timer_alloc( FUNC(write_finished), this );
+
+ save_item( NAME(m_a9_12v) );
+ save_item( NAME(m_oe_12v) );
+ save_item( NAME(m_last_write) );
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void at28c16_device::device_reset()
+{
+}
+
+
+//-------------------------------------------------
+// nvram_default - called to initialize NVRAM to
+// its default state
+//-------------------------------------------------
+
+void at28c16_device::nvram_default()
+{
+ UINT16 default_value = 0xff;
+ for( offs_t offs = 0; offs < AT28C16_TOTAL_BYTES; offs++ )
+ {
+ m_addrspace[ 0 ]->write_byte( offs, default_value );
+ }
+
+ /* populate from a memory region if present */
+ if( m_region != NULL )
+ {
+ if( m_region->bytes() != AT28C16_DATA_BYTES )
+ {
+ fatalerror( "at28c16 region '%s' wrong size (expected size = 0x%X)", tag(), AT28C16_DATA_BYTES );
+ }
+
+ if( m_region->width() != 1 )
+ {
+ fatalerror( "at28c16 region '%s' needs to be an 8-bit region", tag() );
+ }
+
+ for( offs_t offs = 0; offs < AT28C16_DATA_BYTES; offs++ )
+ {
+ m_addrspace[ 0 ]->write_byte( offs, m_region->u8( offs ) );
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// nvram_read - called to read NVRAM from the
+// .nv file
+//-------------------------------------------------
+
+void at28c16_device::nvram_read( emu_file &file )
+{
+ UINT8 *buffer = auto_alloc_array( machine(), UINT8, AT28C16_TOTAL_BYTES );
+
+ file.read( buffer, AT28C16_TOTAL_BYTES );
+
+ for( offs_t offs = 0; offs < AT28C16_TOTAL_BYTES; offs++ )
+ {
+ m_addrspace[ 0 ]->write_byte( offs, buffer[ offs ] );
+ }
+
+ auto_free( machine(), buffer );
+}
+
+//-------------------------------------------------
+// nvram_write - called to write NVRAM to the
+// .nv file
+//-------------------------------------------------
+
+void at28c16_device::nvram_write( emu_file &file )
+{
+ UINT8 *buffer = auto_alloc_array( machine(), UINT8, AT28C16_TOTAL_BYTES );
+
+ for( offs_t offs = 0; offs < AT28C16_TOTAL_BYTES; offs++ )
+ {
+ buffer[ offs ] = m_addrspace[ 0 ]->read_byte( offs );
+ }
+
+ file.write( buffer, AT28C16_TOTAL_BYTES );
+
+ auto_free( machine(), buffer );
+}
+
+
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+WRITE8_DEVICE_HANDLER( at28c16_w )
+{
+ downcast<at28c16_device *>( device )->write( offset, data );
+}
+
+void at28c16_device::write( offs_t offset, UINT8 data )
+{
+ if( m_last_write >= 0 )
+ {
+// logerror( "%s: AT28C16: write( %04x, %02x ) busy\n", machine.describe_context(), offset, data );
+ }
+ else if( m_oe_12v )
+ {
+// logerror( "%s: AT28C16: write( %04x, %02x ) erase\n", machine.describe_context(), offset, data );
+ if( m_last_write < 0 )
+ {
+ for( offs_t offs = 0; offs < AT28C16_TOTAL_BYTES; offs++ )
+ {
+ m_addrspace[ 0 ]->write_byte( offs, 0xff );
+ }
+
+ m_last_write = 0xff;
+ m_write_timer->adjust( attotime::from_usec( 200 ) );
+ }
+ }
+ else
+ {
+ if( m_a9_12v && offset >= AT28C16_ID_OFFSET )
+ {
+ offset += AT28C16_ID_BYTES;
+ }
+
+// logerror( "%s: AT28C16: write( %04x, %02x )\n", machine.describe_context(), offset, data );
+ if( m_last_write < 0 && m_addrspace[ 0 ]->read_byte( offset ) != data )
+ {
+ m_addrspace[ 0 ]->write_byte( offset, data );
+ m_last_write = data;
+ m_write_timer->adjust( attotime::from_usec( 200 ) );
+ }
+ }
+}
+
+
+READ8_DEVICE_HANDLER( at28c16_r )
+{
+ return downcast<at28c16_device *>( device )->read( offset );
+}
+
+UINT8 at28c16_device::read( offs_t offset )
+{
+ if( m_last_write >= 0 )
+ {
+ UINT8 data = m_last_write ^ 0x80;
+// logerror( "%s: AT28C16: read( %04x ) write status %02x\n", machine.describe_context(), offset, data );
+ return data;
+ }
+ else
+ {
+ if( m_a9_12v && offset >= AT28C16_ID_OFFSET )
+ {
+ offset += AT28C16_ID_BYTES;
+ }
+
+ UINT8 data = m_addrspace[ 0 ]->read_byte( offset );
+// logerror( "%s: AT28C16: read( %04x ) data %02x\n", machine.describe_context(), offset, data );
+ return data;
+ }
+}
+
+
+WRITE_LINE_DEVICE_HANDLER( at28c16_a9_12v )
+{
+ downcast<at28c16_device *>( device )->set_a9_12v( state );
+}
+
+void at28c16_device::set_a9_12v( int state )
+{
+ state &= 1;
+ if( m_a9_12v != state )
+ {
+// logerror( "%s: AT28C16: set_a9_12v( %d )\n", machine.describe_context(), state );
+ m_a9_12v = state;
+ }
+}
+
+
+WRITE_LINE_DEVICE_HANDLER( at28c16_oe_12v )
+{
+ downcast<at28c16_device *>( device )->set_oe_12v( state );
+}
+
+void at28c16_device::set_oe_12v( int state )
+{
+ state &= 1;
+ if( m_oe_12v != state )
+ {
+// logerror( "%s: AT28C16: set_oe_12v( %d )\n", machine.describe_context(), state );
+ m_oe_12v = state;
+ }
+}
+
+
+//**************************************************************************
+// INTERNAL HELPERS
+//**************************************************************************
+
+TIMER_CALLBACK( at28c16_device::write_finished )
+{
+ reinterpret_cast<at28c16_device *>(ptr)->m_last_write = -1;
+}
diff --git a/trunk/src/emu/machine/at28c16.h b/trunk/src/emu/machine/at28c16.h
new file mode 100644
index 00000000000..a891d51881b
--- /dev/null
+++ b/trunk/src/emu/machine/at28c16.h
@@ -0,0 +1,92 @@
+/***************************************************************************
+
+ ATMEL AT28C16
+
+ 16K ( 2K x 8 ) Parallel EEPROM
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __AT28C16_H__
+#define __AT28C16_H__
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_AT28C16_ADD( _tag, _interface ) \
+ MCFG_DEVICE_ADD( _tag, AT28C16, 0 )
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> at28c16_interface
+
+struct at28c16_interface
+{
+};
+
+
+// ======================> at28c16_device
+
+class at28c16_device :
+ public device_t,
+ public device_memory_interface,
+ public device_nvram_interface,
+ public at28c16_interface
+{
+public:
+ // construction/destruction
+ at28c16_device( const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock );
+
+ // I/O operations
+ void write( offs_t offset, UINT8 data );
+ UINT8 read( offs_t offset );
+ void set_a9_12v( int state );
+ void set_oe_12v( int state );
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual bool device_validity_check( emu_options &options, const game_driver &driver ) const;
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config( address_spacenum spacenum = AS_0 ) const;
+
+ // device_nvram_interface overrides
+ virtual void nvram_default();
+ virtual void nvram_read( emu_file &file );
+ virtual void nvram_write( emu_file &file );
+
+ // internal helpers
+ static TIMER_CALLBACK( write_finished );
+
+ // internal state
+ address_space_config m_space_config;
+ emu_timer *m_write_timer;
+ int m_a9_12v;
+ int m_oe_12v;
+ int m_last_write;
+};
+
+
+// device type definition
+extern const device_type AT28C16;
+
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+WRITE8_DEVICE_HANDLER( at28c16_w );
+READ8_DEVICE_HANDLER( at28c16_r );
+WRITE_LINE_DEVICE_HANDLER( at28c16_a9_12v );
+WRITE_LINE_DEVICE_HANDLER( at28c16_oe_12v );
+
+#endif
diff --git a/trunk/src/emu/machine/cdp1852.c b/trunk/src/emu/machine/cdp1852.c
new file mode 100644
index 00000000000..ea11fdb15e6
--- /dev/null
+++ b/trunk/src/emu/machine/cdp1852.c
@@ -0,0 +1,221 @@
+/**********************************************************************
+
+ RCA CDP1852 Byte-Wide Input/Output Port emulation
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "cdp1852.h"
+#include "machine/devhelpr.h"
+
+
+// device type definition
+const device_type CDP1852 = &device_creator<cdp1852_device>;
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+enum
+{
+ MODE_INPUT = 0,
+ MODE_OUTPUT
+};
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// get_mode -
+//-------------------------------------------------
+
+int cdp1852_device::get_mode()
+{
+ return m_in_mode_func();
+}
+
+
+//-------------------------------------------------
+// set_sr_line -
+//-------------------------------------------------
+
+void cdp1852_device::set_sr_line(int state)
+{
+ if (m_sr != state)
+ {
+ m_sr = state;
+
+ m_out_sr_func(m_sr);
+ }
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// cdp1852_device - constructor
+//-------------------------------------------------
+
+cdp1852_device::cdp1852_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, CDP1852, "CDP1852", tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void cdp1852_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const cdp1852_interface *intf = reinterpret_cast<const cdp1852_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<cdp1852_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_in_mode_cb, 0, sizeof(m_in_mode_cb));
+ memset(&m_out_sr_cb, 0, sizeof(m_out_sr_cb));
+ memset(&m_in_data_cb, 0, sizeof(m_in_data_cb));
+ memset(&m_out_data_cb, 0, sizeof(m_out_data_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void cdp1852_device::device_start()
+{
+ // resolve callbacks
+ m_in_mode_func.resolve(m_in_mode_cb, *this);
+ m_out_sr_func.resolve(m_out_sr_cb, *this);
+ m_in_data_func.resolve(m_in_data_cb, *this);
+ m_out_data_func.resolve(m_out_data_cb, *this);
+
+ // allocate timers
+ if (clock() > 0)
+ {
+ m_scan_timer = timer_alloc();
+ m_scan_timer->adjust(attotime::zero, 0, attotime::from_hz(clock()));
+ }
+
+ // register for state saving
+ save_item(NAME(m_new_data));
+ save_item(NAME(m_data));
+ save_item(NAME(m_next_data));
+ save_item(NAME(m_sr));
+ save_item(NAME(m_next_sr));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void cdp1852_device::device_reset()
+{
+ // reset data register
+ m_data = 0;
+
+ if (get_mode() == MODE_INPUT)
+ {
+ // reset service request flip-flop
+ set_sr_line(1);
+ }
+ else
+ {
+ // output data
+ m_out_data_func(0, m_data);
+
+ // reset service request flip-flop
+ set_sr_line(0);
+ }
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void cdp1852_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (get_mode())
+ {
+ case MODE_INPUT:
+ // input data into register
+ m_data = m_in_data_func(0);
+
+ // signal processor
+ set_sr_line(0);
+ break;
+
+ case MODE_OUTPUT:
+ if (m_new_data)
+ {
+ m_new_data = 0;
+
+ // latch data into register
+ m_data = m_next_data;
+
+ // output data
+ m_out_data_func(0, m_data);
+
+ // signal peripheral device
+ set_sr_line(1);
+
+ m_next_sr = 0;
+ }
+ else
+ {
+ set_sr_line(m_next_sr);
+ }
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// read - data read
+//-------------------------------------------------
+
+READ8_MEMBER( cdp1852_device::read )
+{
+ if ((get_mode() == MODE_INPUT) && (clock() == 0))
+ {
+ // input data into register
+ m_data = m_in_data_func(0);
+ }
+
+ set_sr_line(1);
+
+ return m_data;
+}
+
+
+//-------------------------------------------------
+// write - data write
+//-------------------------------------------------
+
+WRITE8_MEMBER( cdp1852_device::write )
+{
+ if (get_mode() == MODE_OUTPUT)
+ {
+ m_next_data = data;
+ m_new_data = 1;
+ }
+}
diff --git a/trunk/src/emu/machine/cdp1852.h b/trunk/src/emu/machine/cdp1852.h
new file mode 100644
index 00000000000..6ddf7eaf8aa
--- /dev/null
+++ b/trunk/src/emu/machine/cdp1852.h
@@ -0,0 +1,124 @@
+/**********************************************************************
+
+ RCA CDP1852 Byte-Wide Input/Output Port emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ CSI/_CSI 1 |* \_/ | 24 Vdd
+ MODE 2 | | 23 _SR/SR
+ DI0 3 | | 22 DI7
+ DO0 4 | | 21 DO7
+ DI1 5 | | 20 DI6
+ DO1 6 | CDP1852 | 19 DO6
+ DI2 7 | | 18 DI5
+ DO2 8 | | 17 DO5
+ DI3 9 | | 16 DI4
+ DO3 10 | | 15 DO4
+ CLOCK 11 | | 14 _CLEAR
+ Vss 12 |_____________| 13 CS2
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __CDP1852__
+#define __CDP1852__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define CDP1852_CLOCK_HIGH 0
+
+#define CDP1852_MODE_INPUT \
+ DEVCB_LINE_GND
+
+#define CDP1852_MODE_OUTPUT \
+ DEVCB_LINE_VCC
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_CDP1852_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD(_tag, CDP1852, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+
+#define CDP1852_INTERFACE(name) \
+ const cdp1852_interface (name)=
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> cdp1852_interface
+
+struct cdp1852_interface
+{
+ devcb_read_line m_in_mode_cb;
+
+ devcb_read8 m_in_data_cb;
+ devcb_write8 m_out_data_cb;
+
+ devcb_write_line m_out_sr_cb;
+};
+
+
+// ======================> cdp1852_device
+
+class cdp1852_device : public device_t,
+ public cdp1852_interface
+{
+public:
+ // construction/destruction
+ cdp1852_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_READ8_MEMBER( read );
+ DECLARE_WRITE8_MEMBER( write );
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+private:
+ int get_mode();
+ inline void set_sr_line(int state);
+
+ devcb_resolved_read_line m_in_mode_func;
+ devcb_resolved_write_line m_out_sr_func;
+ devcb_resolved_read8 m_in_data_func;
+ devcb_resolved_write8 m_out_data_func;
+
+ int m_new_data; // new data written
+ UINT8 m_data; // data latch
+ UINT8 m_next_data; // next data
+
+ int m_sr; // service request flag
+ int m_next_sr; // next value of service request flag
+
+ // timers
+ emu_timer *m_scan_timer;
+};
+
+
+// device type definition
+extern const device_type CDP1852;
+
+
+
+#endif
diff --git a/trunk/src/emu/machine/cdp1871.c b/trunk/src/emu/machine/cdp1871.c
new file mode 100644
index 00000000000..c87ceb54ab8
--- /dev/null
+++ b/trunk/src/emu/machine/cdp1871.c
@@ -0,0 +1,305 @@
+/**********************************************************************
+
+ RCA CDP1871 Keyboard Encoder emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "cdp1871.h"
+#include "cpu/mcs48/mcs48.h"
+#include "machine/devhelpr.h"
+
+
+// device type definition
+const device_type CDP1871 = &device_creator<cdp1871_device>;
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+static const UINT8 CDP1871_KEY_CODES[4][11][8] =
+{
+ // normal
+ {
+ { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 },
+ { 0x38, 0x39, 0x3a, 0x3b, 0x2c, 0x2d, 0x2e, 0x2f },
+ { 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67 },
+ { 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f },
+ { 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77 },
+ { 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f },
+ { 0x20, 0xff, 0x0a, 0x1b, 0xff, 0x0d, 0xff, 0x7f },
+ { 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87 },
+ { 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f },
+ { 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97 },
+ { 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f }
+ },
+
+ // alpha
+ {
+ { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 },
+ { 0x38, 0x39, 0x3a, 0x3b, 0x2c, 0x2d, 0x2e, 0x2f },
+ { 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 },
+ { 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f },
+ { 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57 },
+ { 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f },
+ { 0x20, 0xff, 0x0a, 0x1b, 0xff, 0x0d, 0xff, 0x7f },
+ { 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87 },
+ { 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f },
+ { 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97 },
+ { 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f }
+ },
+
+ // shift
+ {
+ { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27 },
+ { 0x28, 0x29, 0x2a, 0x2b, 0x3c, 0x3d, 0x3e, 0x3f },
+ { 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 },
+ { 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f },
+ { 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57 },
+ { 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f },
+ { 0x20, 0xff, 0x0a, 0x1b, 0xff, 0x0d, 0xff, 0x7f },
+ { 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87 },
+ { 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f },
+ { 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97 },
+ { 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f }
+ },
+
+ // control
+ {
+ { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+ { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
+ { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
+ { 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+ { 0x20, 0xff, 0x0a, 0x1b, 0xff, 0x0d, 0xff, 0x7f },
+ { 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87 },
+ { 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f },
+ { 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97 },
+ { 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f }
+ }
+};
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// cdp1871_device - constructor
+//-------------------------------------------------
+
+cdp1871_device::cdp1871_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, CDP1871, "RCA CDP1871", tag, owner, clock),
+ m_inhibit(false),
+ m_sense(0),
+ m_drive(0),
+ m_next_da(CLEAR_LINE),
+ m_next_rpt(CLEAR_LINE)
+{
+
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void cdp1871_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const cdp1871_interface *intf = reinterpret_cast<const cdp1871_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<cdp1871_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&out_da_cb, 0, sizeof(out_da_cb));
+ memset(&out_rpt_cb, 0, sizeof(out_rpt_cb));
+ // m_in_d_cb[]
+ memset(&in_shift_cb, 0, sizeof(in_shift_cb));
+ memset(&in_control_cb, 0, sizeof(in_control_cb));
+ memset(&in_alpha_cb, 0, sizeof(in_alpha_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void cdp1871_device::device_start()
+{
+ // resolve callbacks
+ m_out_da_func.resolve(out_da_cb, *this);
+ m_out_rpt_func.resolve(out_rpt_cb, *this);
+ m_in_d_func[0].resolve(in_d1_cb, *this);
+ m_in_d_func[1].resolve(in_d2_cb, *this);
+ m_in_d_func[2].resolve(in_d3_cb, *this);
+ m_in_d_func[3].resolve(in_d4_cb, *this);
+ m_in_d_func[4].resolve(in_d5_cb, *this);
+ m_in_d_func[5].resolve(in_d6_cb, *this);
+ m_in_d_func[6].resolve(in_d7_cb, *this);
+ m_in_d_func[7].resolve(in_d8_cb, *this);
+ m_in_d_func[8].resolve(in_d9_cb, *this);
+ m_in_d_func[9].resolve(in_d10_cb, *this);
+ m_in_d_func[10].resolve(in_d11_cb, *this);
+ m_in_shift_func.resolve(in_shift_cb, *this);
+ m_in_control_func.resolve(in_control_cb, *this);
+ m_in_alpha_func.resolve(in_alpha_cb, *this);
+
+ // set initial values
+ change_output_lines();
+
+ // allocate timers
+ m_scan_timer = timer_alloc();
+ m_scan_timer->adjust(attotime::zero, 0, attotime::from_hz(clock()));
+
+ // register for state saving
+ save_item(NAME(m_inhibit));
+ save_item(NAME(m_sense));
+ save_item(NAME(m_drive));
+ save_item(NAME(m_shift));
+ save_item(NAME(m_control));
+ save_item(NAME(m_da));
+ save_item(NAME(m_next_da));
+ save_item(NAME(m_rpt));
+ save_item(NAME(m_next_rpt));
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void cdp1871_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ change_output_lines();
+ clock_scan_counters();
+ detect_keypress();
+}
+
+
+//-------------------------------------------------
+// change_output_lines - change output lines
+//-------------------------------------------------
+
+void cdp1871_device::change_output_lines()
+{
+ if (m_next_da != m_da)
+ {
+ m_da = m_next_da;
+
+ m_out_da_func(m_da);
+ }
+
+ if (m_next_rpt != m_rpt)
+ {
+ m_rpt = m_next_rpt;
+
+ m_out_rpt_func(m_rpt);
+ }
+}
+
+
+//-------------------------------------------------
+// clock_scan_counters - clock the keyboard
+// scan counters
+//-------------------------------------------------
+
+void cdp1871_device::clock_scan_counters()
+{
+ if (!m_inhibit)
+ {
+ m_sense++;
+
+ if (m_sense == 8)
+ {
+ m_sense = 0;
+ m_drive++;
+
+ if (m_drive == 11)
+ {
+ m_drive = 0;
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// detect_keypress - detect key press
+//-------------------------------------------------
+
+void cdp1871_device::detect_keypress()
+{
+ UINT8 data = 0;
+
+ data = m_in_d_func[m_drive](0);
+
+ if (data == (1 << m_sense))
+ {
+ if (!m_inhibit)
+ {
+ m_shift = m_in_shift_func();
+ m_control = m_in_control_func();
+ m_inhibit = true;
+ m_next_da = ASSERT_LINE;
+ }
+ else
+ {
+ m_next_rpt = ASSERT_LINE;
+ }
+ }
+ else
+ {
+ m_inhibit = false;
+ m_next_rpt = CLEAR_LINE;
+ }
+}
+
+
+//-------------------------------------------------
+// data_r - keyboard data read
+//-------------------------------------------------
+
+READ8_MEMBER( cdp1871_device::data_r )
+{
+ int table = 0;
+ int alpha = m_in_alpha_func();
+
+ if (m_control) table = 3; else if (m_shift) table = 2; else if (alpha) table = 1;
+
+ // reset DA on next TPB
+ m_next_da = CLEAR_LINE;
+
+ return CDP1871_KEY_CODES[table][m_drive][m_sense];
+}
+
+
+//-------------------------------------------------
+// da_r - data available
+//-------------------------------------------------
+
+READ_LINE_MEMBER( cdp1871_device::da_r )
+{
+ return m_da;
+}
+
+
+//-------------------------------------------------
+// rpt_r - keyboard repeat
+//-------------------------------------------------
+
+READ_LINE_MEMBER( cdp1871_device::rpt_r )
+{
+ return m_rpt;
+}
diff --git a/trunk/src/emu/machine/cdp1871.h b/trunk/src/emu/machine/cdp1871.h
new file mode 100644
index 00000000000..cc803c83821
--- /dev/null
+++ b/trunk/src/emu/machine/cdp1871.h
@@ -0,0 +1,148 @@
+/**********************************************************************
+
+ RCA CDP1871 Keyboard Encoder emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ D1 1 |* \_/ | 40 Vdd
+ D2 2 | | 39 SHIFT
+ D3 3 | | 38 CONTROL
+ D4 4 | | 37 ALPHA
+ D5 5 | | 36 DEBOUNCE
+ D6 6 | | 35 _RTP
+ D7 7 | | 34 TPB
+ D8 8 | | 33 _DA
+ D9 9 | | 32 BUS 7
+ D10 10 | CDP1871 | 31 BUS 6
+ D11 11 | | 30 BUS 5
+ S1 12 | | 29 BUS 4
+ S2 13 | | 28 BUS 3
+ S3 14 | | 27 BUS 2
+ S4 15 | | 26 BUS 1
+ S5 16 | | 25 BUS 0
+ S6 17 | | 24 CS4
+ S7 18 | | 23 CS3
+ S8 19 | | 22 CS2
+ Vss 20 |_____________| 21 _CS1
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __CDP1871__
+#define __CDP1871__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_CDP1871_ADD(_tag, _intrf, _clock) \
+ MCFG_DEVICE_ADD(_tag, CDP1871, _clock) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define CDP1871_INTERFACE(name) \
+ const cdp1871_interface (name)=
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> cdp1871_interface
+
+struct cdp1871_interface
+{
+ devcb_read8 in_d1_cb;
+ devcb_read8 in_d2_cb;
+ devcb_read8 in_d3_cb;
+ devcb_read8 in_d4_cb;
+ devcb_read8 in_d5_cb;
+ devcb_read8 in_d6_cb;
+ devcb_read8 in_d7_cb;
+ devcb_read8 in_d8_cb;
+ devcb_read8 in_d9_cb;
+ devcb_read8 in_d10_cb;
+ devcb_read8 in_d11_cb;
+
+ devcb_read_line in_shift_cb;
+ devcb_read_line in_control_cb;
+ devcb_read_line in_alpha_cb;
+
+ // this gets called for every change of the DA pin (pin 33)
+ devcb_write_line out_da_cb;
+
+ // this gets called for every change of the RPT pin (pin 35)
+ devcb_write_line out_rpt_cb;
+};
+
+
+// ======================> cdp1871_device
+
+class cdp1871_device : public device_t,
+ public cdp1871_interface
+{
+public:
+ // construction/destruction
+ cdp1871_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_READ8_MEMBER( data_r );
+
+ DECLARE_READ_LINE_MEMBER( da_r );
+ DECLARE_READ_LINE_MEMBER( rpt_r );
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+ void change_output_lines();
+ void clock_scan_counters();
+ void detect_keypress();
+
+private:
+ devcb_resolved_write_line m_out_da_func;
+ devcb_resolved_write_line m_out_rpt_func;
+ devcb_resolved_read8 m_in_d_func[11];
+ devcb_resolved_read_line m_in_shift_func;
+ devcb_resolved_read_line m_in_control_func;
+ devcb_resolved_read_line m_in_alpha_func;
+
+ bool m_inhibit; // scan counter clock inhibit
+ int m_sense; // sense input scan counter
+ int m_drive; // modifier inputs
+
+ int m_shift; // latched shift modifier
+ int m_control; // latched control modifier
+
+ int m_da; // data available flag
+ int m_next_da; // next value of data available flag
+ int m_rpt; // repeat flag
+ int m_next_rpt; // next value of repeat flag
+
+ // timers
+ emu_timer *m_scan_timer; // keyboard scan timer
+};
+
+
+// device type definition
+extern const device_type CDP1871;
+
+
+
+#endif
diff --git a/trunk/src/emu/machine/com8116.c b/trunk/src/emu/machine/com8116.c
new file mode 100644
index 00000000000..74623916653
--- /dev/null
+++ b/trunk/src/emu/machine/com8116.c
@@ -0,0 +1,135 @@
+/**********************************************************************
+
+ COM8116 Dual Baud Rate Generator (Programmable Divider) emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "com8116.h"
+#include "machine/devhelpr.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type COM8116 = &device_creator<com8116_device>;
+
+//-------------------------------------------------
+// com8116_device - constructor
+//-------------------------------------------------
+
+com8116_device::com8116_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, COM8116, "COM8116", tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void com8116_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const com8116_interface *intf = reinterpret_cast<const com8116_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<com8116_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_out_fx4_cb, 0, sizeof(m_out_fx4_cb));
+ memset(&m_out_fr_cb, 0, sizeof(m_out_fr_cb));
+ memset(&m_out_ft_cb, 0, sizeof(m_out_ft_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void com8116_device::device_start()
+{
+ // resolve callbacks
+ m_out_fx4_func.resolve(m_out_fx4_cb, *this);
+ m_out_fr_func.resolve(m_out_fr_cb, *this);
+ m_out_ft_func.resolve(m_out_ft_cb, *this);
+
+ // allocate timers
+ m_fx4_timer = timer_alloc(TIMER_FX4);
+ m_fx4_timer->adjust(attotime::zero, 0, attotime::from_hz(clock() / 4));
+ m_fr_timer = timer_alloc(TIMER_FR);
+ m_ft_timer = timer_alloc(TIMER_FT);
+
+ // register for state saving
+ save_item(NAME(m_fr));
+ save_item(NAME(m_ft));
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void com8116_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case TIMER_FX4:
+ m_out_fx4_func(1);
+ break;
+
+ case TIMER_FR:
+ m_out_fr_func(1);
+ break;
+
+ case TIMER_FT:
+ m_out_ft_func(1);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// str_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( com8116_device::str_w )
+{
+ if (LOG) logerror("COM8116 '%s' Receiver Divider %01x\n", tag(), data & 0x0f);
+
+ m_fr = data & 0x0f;
+
+ m_fr_timer->adjust(attotime::zero, 0, attotime::from_hz(clock() / m_fr_divisors[m_fr] / 2));
+}
+
+
+//-------------------------------------------------
+// stt_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( com8116_device::stt_w )
+{
+ if (LOG) logerror("COM8116 '%s' Transmitter Divider %01x\n", tag(), data & 0x0f);
+
+ m_ft = data & 0x0f;
+
+ m_ft_timer->adjust(attotime::zero, 0, attotime::from_hz(clock() / m_ft_divisors[m_ft] / 2));
+}
diff --git a/trunk/src/emu/machine/com8116.h b/trunk/src/emu/machine/com8116.h
new file mode 100644
index 00000000000..41137a5e95a
--- /dev/null
+++ b/trunk/src/emu/machine/com8116.h
@@ -0,0 +1,108 @@
+/**********************************************************************
+
+ COM8116 Dual Baud Rate Generator (Programmable Divider) emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ XTAL/EXT1 1 |* \_/ | 18 XTAL/EXT2
+ +5V 2 | | 17 fT
+ fR 3 | | 16 Ta
+ Ra 4 | COM8116 | 15 Tb
+ Rb 5 | COM8116T | 14 Tc
+ Rc 6 | COM8136 | 13 Td
+ Rd 7 | COM8136T | 12 STT
+ STR 8 | | 11 GND
+ NC 9 |_____________| 10 fX/4
+
+**********************************************************************/
+
+
+#pragma once
+
+#ifndef __COM8116__
+#define __COM8116__
+
+#include "emu.h"
+
+
+
+///*************************************************************************
+// INTERFACE CONFIGURATION MACROS
+///*************************************************************************
+
+#define MCFG_COM8116_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD(_tag, COM8116, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+
+#define COM8116_INTERFACE(name) \
+ const com8116_interface (name) =
+
+
+
+///*************************************************************************
+// TYPE DEFINITIONS
+///*************************************************************************
+
+// ======================> com8116_interface
+
+struct com8116_interface
+{
+ devcb_write_line m_out_fx4_cb;
+ devcb_write_line m_out_fr_cb;
+ devcb_write_line m_out_ft_cb;
+
+ // receiver divisor ROM (19-bit)
+ UINT32 m_fr_divisors[16];
+
+ // transmitter divisor ROM (19-bit)
+ UINT32 m_ft_divisors[16];
+};
+
+
+// ======================> com8116_device
+
+class com8116_device : public device_t,
+ public com8116_interface
+{
+public:
+ // construction/destruction
+ com8116_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_WRITE8_MEMBER( str_w );
+ DECLARE_WRITE8_MEMBER( stt_w );
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int m_param, void *ptr);
+
+private:
+ static const device_timer_id TIMER_FX4 = 0;
+ static const device_timer_id TIMER_FR = 1;
+ static const device_timer_id TIMER_FT = 2;
+
+ devcb_resolved_write_line m_out_fx4_func;
+ devcb_resolved_write_line m_out_fr_func;
+ devcb_resolved_write_line m_out_ft_func;
+
+ int m_fr; // receiver frequency
+ int m_ft; // transmitter frequency
+
+ // timers
+ emu_timer *m_fx4_timer;
+ emu_timer *m_fr_timer;
+ emu_timer *m_ft_timer;
+};
+
+
+// device type definition
+extern const device_type COM8116;
+
+
+
+#endif
diff --git a/trunk/src/emu/machine/cr589.c b/trunk/src/emu/machine/cr589.c
new file mode 100644
index 00000000000..1297b3a893a
--- /dev/null
+++ b/trunk/src/emu/machine/cr589.c
@@ -0,0 +1,156 @@
+/*
+ * Matsushita CR-589
+ *
+ */
+
+#include "emu.h"
+#include "cr589.h"
+
+typedef struct
+{
+ int download;
+ UINT8 buffer[ 65536 ];
+ int bufferOffset;
+} SCSICr589;
+
+static const int identity_offset = 0x3ab;
+static const char download_identity[] = "MATSHITA CD98Q4 DOWNLOADGS0N";
+
+static int cr589_exec_command( SCSIInstance *scsiInstance, UINT8 *statusCode )
+{
+ UINT8 *command;
+ int commandLength;
+ SCSICr589 *our_this = (SCSICr589 *)SCSIThis( &SCSIClassCr589, scsiInstance );
+ SCSIGetCommand( scsiInstance, &command, &commandLength );
+
+ switch( command[ 0 ] )
+ {
+ case 0x3b: // WRITE BUFFER
+ our_this->bufferOffset = ( command[ 3 ] << 16 ) | ( command[ 4 ] << 8 ) | command[ 5 ];
+ SCSISetPhase( scsiInstance, SCSI_PHASE_DATAOUT );
+ return ( command[ 6 ] << 16 ) | ( command[ 7 ] << 8 ) | command[ 8 ];
+
+ case 0x3c: // READ BUFFER
+ our_this->bufferOffset = ( command[ 3 ] << 16 ) | ( command[ 4 ] << 8 ) | command[ 5 ];
+ SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
+ return ( command[ 6 ] << 16 ) | ( command[ 7 ] << 8 ) | command[ 8 ];
+
+ case 0xcc: // FIRMWARE DOWNLOAD ENABLE
+ SCSISetPhase( scsiInstance, SCSI_PHASE_DATAOUT );
+ return SCSILengthFromUINT16( &command[7] );
+
+ default:
+ return SCSIBase( &SCSIClassCr589, SCSIOP_EXEC_COMMAND, scsiInstance, 0, NULL );
+ }
+}
+
+static void cr589_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataLength )
+{
+ UINT8 *command;
+ int commandLength;
+ SCSICr589 *our_this = (SCSICr589 *)SCSIThis( &SCSIClassCr589, scsiInstance );
+ SCSIGetCommand( scsiInstance, &command, &commandLength );
+
+ switch( command[ 0 ] )
+ {
+ case 0x12: // INQUIRY
+ SCSIBase( &SCSIClassCr589, SCSIOP_READ_DATA, scsiInstance, dataLength, data );
+
+ if( our_this->download )
+ {
+ memcpy( &data[ 8 ], download_identity, 28 );
+ }
+ else
+ {
+ memcpy( &data[ 8 ], &our_this->buffer[ identity_offset ], 28 );
+ }
+ break;
+
+ case 0x3c: // READ BUFFER
+ memcpy( data, &our_this->buffer[ our_this->bufferOffset ], dataLength );
+ our_this->bufferOffset += dataLength;
+ break;
+
+ default:
+ SCSIBase( &SCSIClassCr589, SCSIOP_READ_DATA, scsiInstance, dataLength, data );
+ break;
+ }
+}
+
+static void cr589_write_data( SCSIInstance *scsiInstance, UINT8 *data, int dataLength )
+{
+ UINT8 *command;
+ int commandLength;
+ SCSICr589 *our_this = (SCSICr589 *)SCSIThis( &SCSIClassCr589, scsiInstance );
+ SCSIGetCommand( scsiInstance, &command, &commandLength );
+
+ switch( command[ 0 ] )
+ {
+ case 0x3b: // WRITE BUFFER
+ memcpy( &our_this->buffer[ our_this->bufferOffset ], data + 32, dataLength - 32 );
+ our_this->bufferOffset += dataLength;
+ break;
+
+ case 0xcc: // FIRMWARE DOWNLOAD ENABLE
+ if( memcmp( data, &our_this->buffer[ identity_offset ], 28 ) == 0 )
+ {
+ our_this->download = 1;
+ }
+ else if( memcmp( data, download_identity, 28 ) == 0 )
+ {
+ our_this->download = 0;
+ }
+ break;
+
+ default:
+ SCSIBase( &SCSIClassCr589, SCSIOP_WRITE_DATA, scsiInstance, dataLength, data );
+ break;
+ }
+}
+
+static void cr589_alloc_instance( SCSIInstance *scsiInstance, const char *diskregion )
+{
+ running_machine &machine = scsiInstance->machine();
+ SCSICr589 *our_this = (SCSICr589 *)SCSIThis( &SCSIClassCr589, scsiInstance );
+
+ our_this->download = 0;
+ memcpy( &our_this->buffer[ identity_offset ], "MATSHITACD-ROM CR-589 GS0N", 28 );
+
+ state_save_register_item( machine, "cr589", diskregion, 0, our_this->download );
+ state_save_register_item_array( machine, "cr589", diskregion, 0, our_this->buffer );
+ state_save_register_item( machine, "cr589", diskregion, 0, our_this->bufferOffset );
+}
+
+static int cr589_dispatch( int operation, void *file, INT64 intparm, void *ptrparm )
+{
+ SCSIAllocInstanceParams *params;
+
+ switch( operation )
+ {
+ case SCSIOP_EXEC_COMMAND:
+ return cr589_exec_command( (SCSIInstance *)file, (UINT8 *)ptrparm );
+
+ case SCSIOP_READ_DATA:
+ cr589_read_data( (SCSIInstance *)file, (UINT8 *)ptrparm, intparm );
+ return 0;
+
+ case SCSIOP_WRITE_DATA:
+ cr589_write_data( (SCSIInstance *)file, (UINT8 *)ptrparm, intparm );
+ return 0;
+
+ case SCSIOP_ALLOC_INSTANCE:
+ params = (SCSIAllocInstanceParams *)ptrparm;
+ SCSIBase( &SCSIClassCr589, operation, (SCSIInstance *)file, intparm, (UINT8 *)ptrparm );
+ cr589_alloc_instance( params->instance, params->diskregion );
+ return 0;
+ }
+
+ return SCSIBase( &SCSIClassCr589, operation, (SCSIInstance *)file, intparm, (UINT8 *)ptrparm );
+}
+
+const SCSIClass SCSIClassCr589 =
+{
+ &SCSIClassCDROM,
+ cr589_dispatch,
+ sizeof( SCSICr589 )
+};
diff --git a/trunk/src/emu/machine/cr589.h b/trunk/src/emu/machine/cr589.h
new file mode 100644
index 00000000000..1f27614eb01
--- /dev/null
+++ b/trunk/src/emu/machine/cr589.h
@@ -0,0 +1,3 @@
+#include "scsi.h"
+
+extern const SCSIClass SCSIClassCr589;
diff --git a/trunk/src/emu/machine/ctronics.c b/trunk/src/emu/machine/ctronics.c
new file mode 100644
index 00000000000..2fb045b8894
--- /dev/null
+++ b/trunk/src/emu/machine/ctronics.c
@@ -0,0 +1,395 @@
+/***************************************************************************
+
+ Centronics printer interface
+
+***************************************************************************/
+
+#include "emu.h"
+#include "ctronics.h"
+#include "imagedev/printer.h"
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static WRITE_LINE_DEVICE_HANDLER( centronics_printer_online );
+static TIMER_CALLBACK( ack_callback );
+static TIMER_CALLBACK( busy_callback );
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _centronics_state centronics_state;
+struct _centronics_state
+{
+ printer_image_device *printer;
+
+ devcb_resolved_write_line out_ack_func;
+ devcb_resolved_write_line out_busy_func;
+ devcb_resolved_write_line out_not_busy_func;
+
+ int strobe;
+ int busy;
+ int ack;
+ int auto_fd;
+ int pe;
+ int fault;
+
+ UINT8 data;
+};
+
+
+/*****************************************************************************
+ INLINE FUNCTIONS
+*****************************************************************************/
+
+INLINE centronics_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == CENTRONICS);
+
+ return (centronics_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+/*****************************************************************************
+ GLOBAL VARIABLES
+*****************************************************************************/
+
+const centronics_interface standard_centronics =
+{
+ FALSE,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL
+};
+
+
+/*****************************************************************************
+ PRINTER INTERFACE
+*****************************************************************************/
+const struct printer_interface centronics_printer_config =
+{
+ DEVCB_LINE(centronics_printer_online)
+};
+
+static MACHINE_CONFIG_FRAGMENT( centronics )
+ MCFG_PRINTER_ADD("printer")
+ MCFG_DEVICE_CONFIG(centronics_printer_config)
+MACHINE_CONFIG_END
+
+
+/*****************************************************************************
+ DEVICE INTERFACE
+*****************************************************************************/
+
+static DEVICE_START( centronics )
+{
+ centronics_state *centronics = get_safe_token(device);
+ const centronics_interface *intf = (const centronics_interface *)device->static_config();
+
+ /* validate some basic stuff */
+ assert(device->static_config() != NULL);
+
+ /* set some initial values */
+ centronics->pe = FALSE;
+ centronics->fault = FALSE;
+ centronics->busy = TRUE;
+ centronics->strobe = TRUE;
+
+ /* get printer device */
+ centronics->printer = downcast<printer_image_device *>(device->subdevice("printer"));
+
+ /* resolve callbacks */
+ centronics->out_ack_func.resolve(intf->out_ack_func, *device);
+ centronics->out_busy_func.resolve(intf->out_busy_func, *device);
+ centronics->out_not_busy_func.resolve(intf->out_not_busy_func, *device);
+
+ /* register for state saving */
+ device->save_item(NAME(centronics->auto_fd));
+ device->save_item(NAME(centronics->strobe));
+ device->save_item(NAME(centronics->busy));
+ device->save_item(NAME(centronics->ack));
+ device->save_item(NAME(centronics->data));
+}
+
+static DEVICE_RESET( centronics )
+{
+}
+
+DEVICE_GET_INFO( centronics )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(centronics_state); break;
+ case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break;
+
+ /* --- the following bits of info are returned as pointers --- */
+ case DEVINFO_PTR_MACHINE_CONFIG: info->machine_config = MACHINE_CONFIG_NAME(centronics); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(centronics); break;
+ case DEVINFO_FCT_STOP: /* Nothing */ break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(centronics); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Centronics"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Centronics"); 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 MESS Team"); break;
+ }
+}
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ centronics_printer_online - callback that
+ sets us busy when the printer goes offline
+-------------------------------------------------*/
+
+WRITE_LINE_DEVICE_HANDLER(centronics_printer_online)
+{
+ centronics_state *centronics = get_safe_token(device->owner());
+
+ /* when going online, set PE and FAULT high and BUSY low */
+ centronics->pe = state;
+ centronics->fault = state;
+ centronics->busy = !state;
+}
+
+
+static TIMER_CALLBACK( ack_callback )
+{
+ centronics_state *centronics = (centronics_state *)ptr;
+
+ /* signal change */
+ centronics->out_ack_func(param);
+ centronics->ack = param;
+
+ if (param == FALSE)
+ {
+ /* data is now ready, output it */
+ centronics->printer->output(centronics->data);
+
+ /* ready to receive more data, return BUSY to low */
+ machine.scheduler().timer_set(attotime::from_usec(7), FUNC(busy_callback), FALSE, ptr);
+ }
+}
+
+
+static TIMER_CALLBACK( busy_callback )
+{
+ centronics_state *centronics = (centronics_state *)ptr;
+
+ /* signal change */
+ centronics->out_busy_func(param);
+ centronics->out_not_busy_func(!param);
+ centronics->busy = param;
+
+ if (param == TRUE)
+ {
+ /* timer to turn ACK low to receive data */
+ machine.scheduler().timer_set(attotime::from_usec(10), FUNC(ack_callback), FALSE, ptr);
+ }
+ else
+ {
+ /* timer to return ACK to high state */
+ machine.scheduler().timer_set(attotime::from_usec(5), FUNC(ack_callback), TRUE, ptr);
+ }
+}
+
+
+/*-------------------------------------------------
+ centronics_data_w - write print data
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER( centronics_data_w )
+{
+ centronics_state *centronics = get_safe_token(device);
+ centronics->data = data;
+}
+
+
+/*-------------------------------------------------
+ centronics_data_r - return current data
+-------------------------------------------------*/
+
+READ8_DEVICE_HANDLER( centronics_data_r )
+{
+ centronics_state *centronics = get_safe_token(device);
+ return centronics->data;
+}
+
+
+/*-------------------------------------------------
+ set_line - helper to set individual bits
+-------------------------------------------------*/
+
+static void set_line(device_t *device, int line, int state)
+{
+ centronics_state *centronics = get_safe_token(device);
+
+ if (state)
+ centronics->data |= 1 << line;
+ else
+ centronics->data &= ~(1 << line);
+}
+
+
+/*-------------------------------------------------
+ centronics_dx_w - write line dx print data
+-------------------------------------------------*/
+
+WRITE_LINE_DEVICE_HANDLER( centronics_d0_w ) { set_line(device, 0, state); }
+WRITE_LINE_DEVICE_HANDLER( centronics_d1_w ) { set_line(device, 1, state); }
+WRITE_LINE_DEVICE_HANDLER( centronics_d2_w ) { set_line(device, 2, state); }
+WRITE_LINE_DEVICE_HANDLER( centronics_d3_w ) { set_line(device, 3, state); }
+WRITE_LINE_DEVICE_HANDLER( centronics_d4_w ) { set_line(device, 4, state); }
+WRITE_LINE_DEVICE_HANDLER( centronics_d5_w ) { set_line(device, 5, state); }
+WRITE_LINE_DEVICE_HANDLER( centronics_d6_w ) { set_line(device, 6, state); }
+WRITE_LINE_DEVICE_HANDLER( centronics_d7_w ) { set_line(device, 7, state); }
+
+
+/*-------------------------------------------------
+ centronics_strobe_w - signal that data is
+ ready
+-------------------------------------------------*/
+
+WRITE_LINE_DEVICE_HANDLER( centronics_strobe_w )
+{
+ centronics_state *centronics = get_safe_token(device);
+
+ /* look for a high -> low transition */
+ if (centronics->strobe == TRUE && state == FALSE && centronics->busy == FALSE)
+ {
+ /* STROBE has gone low, data is ready */
+ device->machine().scheduler().timer_set(attotime::zero, FUNC(busy_callback), TRUE, centronics);
+ }
+
+ centronics->strobe = state;
+}
+
+
+/*-------------------------------------------------
+ centronics_prime_w - initialize and reset
+ printer (centronics mode)
+-------------------------------------------------*/
+
+WRITE_LINE_DEVICE_HANDLER( centronics_prime_w )
+{
+ assert(((const centronics_interface *)device->static_config())->is_ibmpc == FALSE);
+
+ /* reset printer if line is low */
+ if (state == FALSE)
+ DEVICE_RESET_CALL( centronics );
+}
+
+
+/*-------------------------------------------------
+ centronics_init_w - initialize and reset
+ printer (ibm mode)
+-------------------------------------------------*/
+
+WRITE_LINE_DEVICE_HANDLER( centronics_init_w )
+{
+ assert(((const centronics_interface *)device->static_config())->is_ibmpc == TRUE);
+
+ /* reset printer if line is low */
+ if (state == FALSE)
+ DEVICE_RESET_CALL( centronics );
+}
+
+
+/*-------------------------------------------------
+ centronics_autofeed_w - auto line feed
+-------------------------------------------------*/
+
+WRITE_LINE_DEVICE_HANDLER( centronics_autofeed_w )
+{
+ centronics_state *centronics = get_safe_token(device);
+ assert(((const centronics_interface *)device->static_config())->is_ibmpc == TRUE);
+
+ centronics->auto_fd = state;
+}
+
+
+/*-------------------------------------------------
+ centronics_ack_r - return the state of the
+ ack line
+-------------------------------------------------*/
+
+READ_LINE_DEVICE_HANDLER( centronics_ack_r )
+{
+ centronics_state *centronics = get_safe_token(device);
+ return centronics->ack;
+}
+
+
+/*-------------------------------------------------
+ centronics_busy_r - return the state of the
+ busy line
+-------------------------------------------------*/
+
+READ_LINE_DEVICE_HANDLER( centronics_busy_r )
+{
+ centronics_state *centronics = get_safe_token(device);
+ return centronics->busy;
+}
+
+
+/*-------------------------------------------------
+ centronics_pe_r - return the state of the
+ pe line
+-------------------------------------------------*/
+
+READ_LINE_DEVICE_HANDLER( centronics_pe_r )
+{
+ centronics_state *centronics = get_safe_token(device);
+ return centronics->pe;
+}
+
+
+/*-------------------------------------------------
+ centronics_not_busy_r - return the state of the
+ not busy line
+-------------------------------------------------*/
+
+READ_LINE_DEVICE_HANDLER( centronics_not_busy_r )
+{
+ centronics_state *centronics = get_safe_token(device);
+ return !centronics->busy;
+}
+
+
+/*-------------------------------------------------
+ centronics_vcc_r - return the state of the
+ vcc line
+-------------------------------------------------*/
+
+READ_LINE_DEVICE_HANDLER( centronics_vcc_r )
+{
+ /* always return high */
+ return TRUE;
+}
+
+
+/*-------------------------------------------------
+ centronics_fault_r - return the state of the
+ fault line
+-------------------------------------------------*/
+
+READ_LINE_DEVICE_HANDLER( centronics_fault_r )
+{
+ centronics_state *centronics = get_safe_token(device);
+ return centronics->fault;
+}
+
+DEFINE_LEGACY_DEVICE(CENTRONICS, centronics);
diff --git a/trunk/src/emu/machine/ctronics.h b/trunk/src/emu/machine/ctronics.h
new file mode 100644
index 00000000000..a5d3bdf8e1a
--- /dev/null
+++ b/trunk/src/emu/machine/ctronics.h
@@ -0,0 +1,75 @@
+/***************************************************************************
+
+ Centronics printer interface
+
+***************************************************************************/
+
+#ifndef __CTRONICS_H__
+#define __CTRONICS_H__
+
+#include "devcb.h"
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _centronics_interface centronics_interface;
+struct _centronics_interface
+{
+ int is_ibmpc;
+
+ devcb_write_line out_ack_func;
+ devcb_write_line out_busy_func;
+ devcb_write_line out_not_busy_func;
+};
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+WRITE8_DEVICE_HANDLER( centronics_data_w );
+READ8_DEVICE_HANDLER( centronics_data_r );
+
+/* access to the individual bits */
+WRITE_LINE_DEVICE_HANDLER( centronics_d0_w );
+WRITE_LINE_DEVICE_HANDLER( centronics_d1_w );
+WRITE_LINE_DEVICE_HANDLER( centronics_d2_w );
+WRITE_LINE_DEVICE_HANDLER( centronics_d3_w );
+WRITE_LINE_DEVICE_HANDLER( centronics_d4_w );
+WRITE_LINE_DEVICE_HANDLER( centronics_d5_w );
+WRITE_LINE_DEVICE_HANDLER( centronics_d6_w );
+WRITE_LINE_DEVICE_HANDLER( centronics_d7_w );
+
+WRITE_LINE_DEVICE_HANDLER( centronics_strobe_w );
+WRITE_LINE_DEVICE_HANDLER( centronics_prime_w );
+WRITE_LINE_DEVICE_HANDLER( centronics_init_w );
+WRITE_LINE_DEVICE_HANDLER( centronics_autofeed_w );
+
+READ_LINE_DEVICE_HANDLER( centronics_ack_r );
+READ_LINE_DEVICE_HANDLER( centronics_busy_r );
+READ_LINE_DEVICE_HANDLER( centronics_pe_r );
+READ_LINE_DEVICE_HANDLER( centronics_not_busy_r );
+READ_LINE_DEVICE_HANDLER( centronics_vcc_r );
+READ_LINE_DEVICE_HANDLER( centronics_fault_r );
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+DECLARE_LEGACY_DEVICE(CENTRONICS, centronics);
+
+#define MCFG_CENTRONICS_ADD(_tag, _intf) \
+ MCFG_DEVICE_ADD(_tag, CENTRONICS, 0) \
+ MCFG_DEVICE_CONFIG(_intf)
+
+
+/***************************************************************************
+ DEFAULT INTERFACES
+***************************************************************************/
+
+extern const centronics_interface standard_centronics;
+
+
+#endif /* __CTRONICS_H__ */
diff --git a/trunk/src/emu/machine/devhelpr.h b/trunk/src/emu/machine/devhelpr.h
new file mode 100644
index 00000000000..2593ba39b9a
--- /dev/null
+++ b/trunk/src/emu/machine/devhelpr.h
@@ -0,0 +1,41 @@
+/**********************************************************************
+
+ Generic modern device trampolines and other helpers, to minimize
+ the amount of redundant copy/pasting between modernized devices.
+
+**********************************************************************/
+
+#ifndef __DEVHELPR_H__
+#define __DEVHELPR_H__
+
+#define READ32_DEVICE_HANDLER_TRAMPOLINE(devname, funcname) \
+ READ32_DEVICE_HANDLER( funcname ) \
+ { return downcast<devname##_device*>(device)->funcname(offset); } \
+ UINT32 devname##_device::funcname(UINT32 offset)
+
+#define WRITE32_DEVICE_HANDLER_TRAMPOLINE(devname, funcname) \
+ WRITE32_DEVICE_HANDLER( funcname ) \
+ { downcast<devname##_device*>(device)->funcname(offset, data, mem_mask); } \
+ void devname##_device::funcname(UINT32 offset, UINT32 data, UINT32 mem_mask)
+
+#define READ8_DEVICE_HANDLER_TRAMPOLINE(devname, funcname) \
+ READ8_DEVICE_HANDLER( funcname ) \
+ { return downcast<devname##_device*>(device)->funcname(offset); } \
+ UINT8 devname##_device::funcname(UINT32 offset)
+
+#define WRITE8_DEVICE_HANDLER_TRAMPOLINE(devname, funcname) \
+ WRITE8_DEVICE_HANDLER( funcname ) \
+ { downcast<devname##_device*>(device)->funcname(offset, data); } \
+ void devname##_device::funcname(UINT32 offset, UINT8 data)
+
+#define READ_LINE_DEVICE_HANDLER_TRAMPOLINE(devname, funcname) \
+ READ_LINE_DEVICE_HANDLER( funcname ) \
+ { return downcast<devname##_device *>(device)->funcname(); } \
+ void devname##_device::funcname()
+
+#define WRITE_LINE_DEVICE_HANDLER_TRAMPOLINE(devname, funcname) \
+ WRITE_LINE_DEVICE_HANDLER( funcname ) \
+ { return downcast<devname##_device *>(device)->funcname(state); } \
+ void devname##_device::funcname(UINT8 state)
+
+#endif // __DEVHELPR_H__
diff --git a/trunk/src/emu/machine/ds1302.c b/trunk/src/emu/machine/ds1302.c
new file mode 100644
index 00000000000..1f6bd0c4d91
--- /dev/null
+++ b/trunk/src/emu/machine/ds1302.c
@@ -0,0 +1,215 @@
+/************************************************************
+
+ DALLAS DS1302
+
+ RTC + BACKUP RAM
+
+
+
+ Emulation by ElSemi
+
+
+ Missing Features:
+ - Burst Mode
+ - Clock programming (useless)
+
+
+
+ 2009-05 Converted to be a device
+
+************************************************************/
+
+
+#include "emu.h"
+#include "ds1302.h"
+#include "devhelpr.h"
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE UINT8 convert_to_bcd(int val)
+{
+ return ((val / 10) << 4) | (val % 10);
+}
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type DS1302 = &device_creator<ds1302_device>;
+
+//-------------------------------------------------
+// ds1302_device - constructor
+//-------------------------------------------------
+
+ds1302_device::ds1302_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, DS1302, "Dallas DS1302 RTC", tag, owner, clock)
+{
+
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void ds1302_device::device_start()
+{
+ save_item(NAME(m_shift_in));
+ save_item(NAME(m_shift_out));
+ save_item(NAME(m_icount));
+ save_item(NAME(m_last_clk));
+ save_item(NAME(m_last_cmd));
+ save_item(NAME(m_sram));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void ds1302_device::device_reset()
+{
+ m_shift_in = 0;
+ m_shift_out = 0;
+ m_icount = 0;
+ m_last_clk = 0;
+ m_last_cmd = 0;
+}
+
+
+/*-------------------------------------------------
+ ds1302_dat_w
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(ds1302, ds1302_dat_w)
+{
+ if (data)
+ {
+ m_shift_in |= (1 << m_icount);
+ }
+ else
+ {
+ m_shift_in &= ~(1 << m_icount);
+ }
+}
+
+
+/*-------------------------------------------------
+ ds1302_clk_w
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(ds1302, ds1302_clk_w)
+{
+ if (data != m_last_clk)
+ {
+ if (data) //Rising, shift in command
+ {
+ m_icount++;
+ if(m_icount == 8) //Command start
+ {
+ system_time systime;
+ machine().base_datetime(systime);
+
+ switch(m_shift_in)
+ {
+ case 0x81: //Sec
+ m_shift_out = convert_to_bcd(systime.local_time.second);
+ break;
+
+ case 0x83: //Min
+ m_shift_out = convert_to_bcd(systime.local_time.minute);
+ break;
+
+ case 0x85: //Hour
+ m_shift_out = convert_to_bcd(systime.local_time.hour);
+ break;
+
+ case 0x87: //Day
+ m_shift_out = convert_to_bcd(systime.local_time.mday);
+ break;
+
+ case 0x89: //Month
+ m_shift_out = convert_to_bcd(systime.local_time.month + 1);
+ break;
+
+ case 0x8b: //weekday
+ m_shift_out = convert_to_bcd(systime.local_time.weekday);
+ break;
+
+ case 0x8d: //Year
+ m_shift_out = convert_to_bcd(systime.local_time.year % 100);
+ break;
+
+ default:
+ m_shift_out = 0x0;
+ }
+
+ if(m_shift_in > 0xc0)
+ {
+ m_shift_out = m_sram[(m_shift_in >> 1) & 0x1f];
+ }
+ m_last_cmd = m_shift_in & 0xff;
+ m_icount++;
+ }
+
+ if(m_icount == 17 && !(m_last_cmd & 1))
+ {
+ UINT8 val = (m_shift_in >> 9) & 0xff;
+
+ switch(m_last_cmd)
+ {
+ case 0x80: //Sec
+ break;
+
+ case 0x82: //Min
+ break;
+
+ case 0x84: //Hour
+ break;
+
+ case 0x86: //Day
+ break;
+
+ case 0x88: //Month
+ break;
+
+ case 0x8a: //weekday
+ break;
+
+ case 0x8c: //Year
+ break;
+
+ default:
+ m_shift_out = 0x0;
+ }
+
+ if(m_last_cmd > 0xc0)
+ {
+ m_sram[(m_last_cmd >> 1) & 0x1f] = val;
+ }
+
+
+
+ }
+ }
+ }
+ m_last_clk = data;
+}
+
+
+/*-------------------------------------------------
+ ds1302_read
+-------------------------------------------------*/
+
+READ8_DEVICE_HANDLER_TRAMPOLINE(ds1302, ds1302_read)
+{
+ return (m_shift_out & (1 << (m_icount - 9))) ? 1 : 0;
+}
diff --git a/trunk/src/emu/machine/ds1302.h b/trunk/src/emu/machine/ds1302.h
new file mode 100644
index 00000000000..30f53c1aa52
--- /dev/null
+++ b/trunk/src/emu/machine/ds1302.h
@@ -0,0 +1,75 @@
+/**********************************************************************
+
+ DALLAS DS1302
+
+ RTC + BACKUP RAM
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __DS1302_H__
+#define __DS1302_H__
+
+#include "emu.h"
+
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_DS1302_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, DS1302, 0)
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+
+// ======================> ds1302_device
+
+class ds1302_device : public device_t
+{
+public:
+ // construction/destruction
+ ds1302_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ void ds1302_dat_w(UINT32 offset, UINT8 data);
+ void ds1302_clk_w(UINT32 offset, UINT8 data);
+ UINT8 ds1302_read(UINT32 offset);
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_post_load() { }
+ virtual void device_clock_changed() { }
+
+private:
+
+ UINT32 m_shift_in;
+ UINT8 m_shift_out;
+ UINT8 m_icount;
+ UINT8 m_last_clk;
+ UINT8 m_last_cmd;
+ UINT8 m_sram[0x20];
+};
+
+
+// device type definition
+extern const device_type DS1302;
+
+
+
+/***************************************************************************
+ PROTOTYPES
+***************************************************************************/
+
+extern WRITE8_DEVICE_HANDLER( ds1302_dat_w );
+extern WRITE8_DEVICE_HANDLER( ds1302_clk_w );
+extern READ8_DEVICE_HANDLER( ds1302_read );
+
+
+#endif /* __DS1302_H__ */
diff --git a/trunk/src/emu/machine/ds2401.c b/trunk/src/emu/machine/ds2401.c
new file mode 100644
index 00000000000..f0e9e5ce33c
--- /dev/null
+++ b/trunk/src/emu/machine/ds2401.c
@@ -0,0 +1,239 @@
+/*
+ * DS2401
+ *
+ * Dallas Semiconductor
+ * Silicon Serial Number
+ *
+ */
+
+#include "emu.h"
+#include "machine/ds2401.h"
+
+#define VERBOSE_LEVEL 0
+
+inline void ATTR_PRINTF(3,4) ds2401_device::verboselog(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("ds2401 %s %s: %s", tag(), machine().describe_context(), buf);
+ }
+}
+
+// device type definition
+const device_type DS2401 = &device_creator<ds2401_device>;
+
+ds2401_device::ds2401_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, DS2401, "DS2401", tag, owner, clock)
+{
+}
+
+void ds2401_device::device_start()
+{
+ t_samp = attotime::from_usec( 30);
+ t_rdv = attotime::from_usec( 30);
+ t_rstl = attotime::from_usec(480);
+ t_pdh = attotime::from_usec( 30);
+ t_pdl = attotime::from_usec(120);
+
+ save_item(NAME(state));
+ save_item(NAME(bit));
+ save_item(NAME(byte));
+ save_item(NAME(shift));
+ save_item(NAME(rx));
+ save_item(NAME(tx));
+
+ timer_main = timer_alloc(TIMER_MAIN);
+ timer_reset = timer_alloc(TIMER_RESET);
+}
+
+void ds2401_device::device_reset()
+{
+ state = STATE_IDLE;
+ bit = 0;
+ byte = 0;
+ shift = 0;
+ rx = true;
+ tx = true;
+
+ if(m_region)
+ {
+ // Ensure the size is correct though
+ if(m_region->bytes() != SIZE_DATA)
+ logerror("ds2401 %s: Wrong region length for id data, expected 0x%x, got 0x%x\n",
+ tag(),
+ SIZE_DATA,
+ m_region->bytes());
+ else {
+ UINT8 *rb = m_region->base();
+ memcpy(data, rb, SIZE_DATA);
+ return;
+ }
+ }
+
+ // That chip is useless without an id, so bitch if there
+ // isn't one
+ logerror("ds2401 %s: Warning, no id provided, answer will be all zeroes.\n", tag());
+ memset(data, 0, SIZE_DATA);
+}
+
+void ds2401_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch(id) {
+ case TIMER_RESET:
+ verboselog(1, "timer_reset\n");
+ state = STATE_RESET;
+ timer_reset->adjust(attotime::never);
+ break;
+
+ case TIMER_MAIN:
+ switch(state) {
+ case STATE_RESET1:
+ verboselog(2, "timer_main state_reset1 %d\n", rx);
+ tx = false;
+ state = STATE_RESET2;
+ timer_main->adjust(t_pdl);
+ break;
+
+ case STATE_RESET2:
+ verboselog(2, "timer_main state_reset2 %d\n", rx);
+ tx = true;
+ bit = 0;
+ shift = 0;
+ state = STATE_COMMAND;
+ break;
+
+ case STATE_COMMAND:
+ verboselog(2, "timer_main state_command %d\n", rx);
+ shift >>= 1;
+ if(rx)
+ shift |= 0x80;
+ bit++;
+ if(bit == 8) {
+ switch(shift) {
+ case COMMAND_READROM:
+ verboselog(1, "timer_main readrom\n");
+ bit = 0;
+ byte = 0;
+ state = STATE_READROM;
+ break;
+ default:
+ verboselog(0, "timer_main command not handled %02x\n", shift);
+ state = STATE_IDLE;
+ break;
+ }
+ }
+ break;
+
+ case STATE_READROM:
+ tx = true;
+ if(byte == SIZE_DATA) {
+ verboselog(1, "timer_main readrom finished\n");
+ state = STATE_IDLE;
+ } else {
+ verboselog(2, "timer_main readrom window closed\n");
+ }
+ break;
+ default:
+ verboselog(0, "timer_main state not handled: %d\n", state);
+ break;
+ }
+ }
+}
+
+void ds2401_device::write(bool line)
+{
+ verboselog(1, "write(%d)\n", line);
+
+ if(!line && rx) {
+ switch(state) {
+ case STATE_IDLE:
+ break;
+ case STATE_COMMAND:
+ verboselog(2, "state_command\n");
+ timer_main->adjust(t_samp);
+ break;
+ case STATE_READROM:
+ if(!bit) {
+ shift = data[7 - byte];
+ verboselog(1, "<- data %02x\n", shift);
+ }
+ tx = shift & 1;
+ shift >>= 1;
+ bit++;
+ if(bit == 8) {
+ bit = 0;
+ byte++;
+ }
+ verboselog(2, "state_readrom %d\n", tx);
+ timer_main->adjust(t_rdv);
+ break;
+ default:
+ verboselog(0, "state not handled: %d\n", state );
+ break;
+ }
+ timer_reset->adjust(t_rstl);
+ } else if(line && !rx) {
+ switch(state) {
+ case STATE_RESET:
+ state = STATE_RESET1;
+ timer_main->adjust(t_pdh);
+ break;
+ }
+ timer_reset->adjust(attotime::never);
+ }
+ rx = line;
+}
+
+bool ds2401_device::read()
+{
+ verboselog(2, "read %d\n", tx && rx);
+ return tx && rx;
+}
+
+UINT8 ds2401_device::direct_read(int index)
+{
+ return data[index];
+}
+
+/*
+
+app74.pdf
+
+Under normal circumstances an ibutton will sample the line 30us after the falling edge of the start condition.
+The internal time base of ibutton may deviate from its nominal value. The allowed tollerance band ranges from 15us to 60us.
+This means that the actual slave sampling may occur anywhere from 15 and 60us after the start condition, which is a ratio of 1 to 4.
+During this time frame the voltage on the data line must stay below Vilmax or above Vihmin.
+
+In the 1-Wire system, the logical values 1 and 0 are represented by certain voltages in special waveforms.
+The waveforms needed to write commands or data to ibuttons are called write-1 and write-0 time slots.
+The duration of a low pulse to write a 1 must be shorter than 15us.
+To write a 0, the duration of the low pulse must be at least 60us to cope with worst-case conditions.
+
+The duration of the active part of a time slot can be extended beyond 60us.
+The maximum extension is limited by the fact that a low pulse of a duration of at least eight active time slots ( 480us ) is defined as a Reset Pulse.
+Allowing the same worst-case tolerance ratio, a low pulse of 120us might be sufficient for a reset.
+This limits the extension of the active part of a time slot to a maximum of 120us to prevent misinterpretation with reset.
+
+Commands and data are sent to ibuttons by combining write-0 and write-1 time slots.
+To read data, the master has to generate read-data time slots to define the start condition of each bit.
+The read-data time slots looks essentially the same as a write-1 time slot from the masters point of view.
+Starting at the high-to-low transition, the ibuttons sends 1 bit of its addressed contents.
+If the data bit is a 1, the ibutton leaves the pulse unchanged.
+If the data bit is a 0, the ibutton will pull the data line low for 15us.
+In this time frame data is valid for reading by the master.
+The duration of the low pulse sent by the master should be a minimum of 1us with a maximum value as short as possible to maximize the master sampling window.
+
+The Reset Pulse provides a clear starting condition that supersedes any time slot synchronisation.
+It is defined as single low pulse of minimum duration of eight time slots or 480us followed by a Reset-high time tRSTH of another 480us.
+After a Reset Pulse has been sent, the ibutton will wait for the time tPDH and then generate a Pulse-Presence Pulse of duration tPDL.
+No other communication on the 1-Wire bus is allowed during tRSTH.
+
+There are 1,000 microseconds in a millisecond, and 1,000 milliseconds in a second.
+Thus, there are 1,000,000 microseconds in a second. Why is it "usec"?
+The "u" is supposed to look like the Greek letter Mu that we use for "micro". .
+*/
diff --git a/trunk/src/emu/machine/ds2401.h b/trunk/src/emu/machine/ds2401.h
new file mode 100644
index 00000000000..353735899f7
--- /dev/null
+++ b/trunk/src/emu/machine/ds2401.h
@@ -0,0 +1,69 @@
+/*
+ * DS2401
+ *
+ * Dallas Semiconductor
+ * Silicon Serial Number
+ *
+ */
+
+#ifndef __DS2401_H__
+#define __DS2401_H__
+
+#define MCFG_DS2401_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, DS2401, 0)
+
+#include "emu.h"
+
+class ds2401_device : public device_t
+{
+public:
+ // construction/destruction
+ ds2401_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ void write(bool line);
+ bool read();
+ UINT8 direct_read(int index);
+
+protected:
+ enum {
+ SIZE_DATA = 8,
+
+ COMMAND_READROM = 0x33
+ };
+
+ enum {
+ STATE_IDLE,
+ STATE_RESET,
+ STATE_RESET1,
+ STATE_RESET2,
+ STATE_COMMAND,
+ STATE_READROM
+ };
+
+ enum {
+ TIMER_MAIN,
+ TIMER_RESET
+ };
+
+ // 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);
+
+ // internal state
+ int state, bit, shift;
+ UINT8 byte;
+ bool rx, tx;
+ UINT8 data[SIZE_DATA];
+ emu_timer *timer_main, *timer_reset;
+ attotime t_samp, t_rdv, t_rstl, t_pdh, t_pdl;
+
+private:
+ inline void ATTR_PRINTF(3,4) verboselog(int n_level, const char *s_fmt, ...);
+};
+
+
+// device type definition
+extern const device_type DS2401;
+
+#endif
diff --git a/trunk/src/emu/machine/ds2404.c b/trunk/src/emu/machine/ds2404.c
new file mode 100644
index 00000000000..8ce9c29c900
--- /dev/null
+++ b/trunk/src/emu/machine/ds2404.c
@@ -0,0 +1,388 @@
+/**********************************************************************
+
+ DALLAS DS2404
+
+ RTC + BACKUP RAM
+
+**********************************************************************/
+
+#include "emu.h"
+#include "ds2404.h"
+#include <time.h>
+#include "devhelpr.h"
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type DS2404 = &device_creator<ds2404_device>;
+
+//-------------------------------------------------
+// ds2404_device - constructor
+//-------------------------------------------------
+
+ds2404_device::ds2404_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, DS2404, "DS2404", tag, owner, clock),
+ device_nvram_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// static_set_ref_year - configuration helper
+// to set the reference year
+//-------------------------------------------------
+
+void ds2404_device::static_set_ref_year(device_t &device, UINT32 year)
+{
+ ds2404_device &ds2404 = downcast<ds2404_device &>(device);
+ ds2404.m_ref_year = year;
+}
+
+
+//-------------------------------------------------
+// static_set_ref_month - configuration helper
+// to set the reference month
+//-------------------------------------------------
+
+void ds2404_device::static_set_ref_month(device_t &device, UINT8 month)
+{
+ ds2404_device &ds2404 = downcast<ds2404_device &>(device);
+ ds2404.m_ref_month = month;
+}
+
+
+//-------------------------------------------------
+// static_set_ref_day - configuration helper
+// to set the reference day
+//-------------------------------------------------
+
+void ds2404_device::static_set_ref_day(device_t &device, UINT8 day)
+{
+ ds2404_device &ds2404 = downcast<ds2404_device &>(device);
+ ds2404.m_ref_day = day;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void ds2404_device::device_start()
+{
+ struct tm ref_tm;
+
+ memset(&ref_tm, 0, sizeof(ref_tm));
+ ref_tm.tm_year = m_ref_year - 1900;
+ ref_tm.tm_mon = m_ref_month - 1;
+ ref_tm.tm_mday = m_ref_day;
+
+ time_t ref_time = mktime(&ref_tm);
+
+ time_t current_time;
+ time(&current_time);
+ current_time -= ref_time;
+
+ m_rtc[0] = 0x0;
+ m_rtc[1] = (current_time >> 0) & 0xff;
+ m_rtc[2] = (current_time >> 8) & 0xff;
+ m_rtc[3] = (current_time >> 16) & 0xff;
+ m_rtc[4] = (current_time >> 24) & 0xff;
+
+ emu_timer *timer = machine().scheduler().timer_alloc(FUNC(ds2404_tick_callback), (void *)this);
+ timer->adjust(attotime::from_hz(256), 0, attotime::from_hz(256));
+}
+
+
+void ds2404_device::ds2404_rom_cmd(UINT8 cmd)
+{
+ switch(cmd)
+ {
+ case 0xcc: /* Skip ROM */
+ m_state[0] = DS2404_STATE_COMMAND;
+ m_state_ptr = 0;
+ break;
+
+ default:
+ fatalerror("DS2404: Unknown ROM command %02X", cmd);
+ break;
+ }
+}
+
+void ds2404_device::ds2404_cmd(UINT8 cmd)
+{
+ switch(cmd)
+ {
+ case 0x0f: /* Write scratchpad */
+ m_state[0] = DS2404_STATE_ADDRESS1;
+ m_state[1] = DS2404_STATE_ADDRESS2;
+ m_state[2] = DS2404_STATE_INIT_COMMAND;
+ m_state[3] = DS2404_STATE_WRITE_SCRATCHPAD;
+ m_state_ptr = 0;
+ break;
+
+ case 0x55: /* Copy scratchpad */
+ m_state[0] = DS2404_STATE_ADDRESS1;
+ m_state[1] = DS2404_STATE_ADDRESS2;
+ m_state[2] = DS2404_STATE_OFFSET;
+ m_state[3] = DS2404_STATE_INIT_COMMAND;
+ m_state[4] = DS2404_STATE_COPY_SCRATCHPAD;
+ m_state_ptr = 0;
+ break;
+
+ case 0xf0: /* Read memory */
+ m_state[0] = DS2404_STATE_ADDRESS1;
+ m_state[1] = DS2404_STATE_ADDRESS2;
+ m_state[2] = DS2404_STATE_INIT_COMMAND;
+ m_state[3] = DS2404_STATE_READ_MEMORY;
+ m_state_ptr = 0;
+ break;
+
+ default:
+ fatalerror("DS2404: Unknown command %02X", cmd);
+ break;
+ }
+}
+
+UINT8 ds2404_device::ds2404_readmem()
+{
+ if( m_address < 0x200 )
+ {
+ return m_sram[ m_address ];
+ }
+ else if( m_address >= 0x202 && m_address <= 0x206 )
+ {
+ return m_rtc[ m_address - 0x202 ];
+ }
+ return 0;
+}
+
+void ds2404_device::ds2404_writemem(UINT8 value)
+{
+ if( m_address < 0x200 )
+ {
+ m_sram[ m_address ] = value;
+ }
+ else if( m_address >= 0x202 && m_address <= 0x206 )
+ {
+ m_rtc[ m_address - 0x202 ] = value;
+ }
+}
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(ds2404, ds2404_1w_reset_w)
+{
+ m_state[0] = DS2404_STATE_IDLE;
+ m_state_ptr = 0;
+}
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(ds2404, ds2404_3w_reset_w)
+{
+ m_state[0] = DS2404_STATE_COMMAND;
+ m_state_ptr = 0;
+}
+
+READ8_DEVICE_HANDLER_TRAMPOLINE(ds2404, ds2404_data_r)
+{
+ UINT8 value = 0;
+ switch(m_state[m_state_ptr])
+ {
+ case DS2404_STATE_IDLE:
+ case DS2404_STATE_COMMAND:
+ case DS2404_STATE_ADDRESS1:
+ case DS2404_STATE_ADDRESS2:
+ case DS2404_STATE_OFFSET:
+ case DS2404_STATE_INIT_COMMAND:
+ break;
+
+ case DS2404_STATE_READ_MEMORY:
+ value = ds2404_readmem();
+ break;
+
+ case DS2404_STATE_READ_SCRATCHPAD:
+ if(m_offset < 0x20)
+ {
+ value = m_ram[m_offset];
+ m_offset++;
+ }
+ break;
+
+ case DS2404_STATE_WRITE_SCRATCHPAD:
+ break;
+
+ case DS2404_STATE_COPY_SCRATCHPAD:
+ break;
+ }
+ return value;
+}
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(ds2404, ds2404_data_w)
+{
+ switch( m_state[m_state_ptr] )
+ {
+ case DS2404_STATE_IDLE:
+ ds2404_rom_cmd(data & 0xff);
+ break;
+
+ case DS2404_STATE_COMMAND:
+ ds2404_cmd(data & 0xff);
+ break;
+
+ case DS2404_STATE_ADDRESS1:
+ m_a1 = data & 0xff;
+ m_state_ptr++;
+ break;
+
+ case DS2404_STATE_ADDRESS2:
+ m_a2 = data & 0xff;
+ m_state_ptr++;
+ break;
+
+ case DS2404_STATE_OFFSET:
+ m_end_offset = data & 0xff;
+ m_state_ptr++;
+ break;
+
+ case DS2404_STATE_INIT_COMMAND:
+ break;
+
+ case DS2404_STATE_READ_MEMORY:
+ break;
+
+ case DS2404_STATE_READ_SCRATCHPAD:
+ break;
+
+ case DS2404_STATE_WRITE_SCRATCHPAD:
+ if( m_offset < 0x20 )
+ {
+ m_ram[m_offset] = data & 0xff;
+ m_offset++;
+ }
+ else
+ {
+ /* Set OF flag */
+ }
+ break;
+
+ case DS2404_STATE_COPY_SCRATCHPAD:
+ break;
+ }
+
+ if( m_state[m_state_ptr] == DS2404_STATE_INIT_COMMAND )
+ {
+ switch( m_state[m_state_ptr + 1] )
+ {
+ case DS2404_STATE_IDLE:
+ case DS2404_STATE_COMMAND:
+ case DS2404_STATE_ADDRESS1:
+ case DS2404_STATE_ADDRESS2:
+ case DS2404_STATE_OFFSET:
+ case DS2404_STATE_INIT_COMMAND:
+ break;
+
+ case DS2404_STATE_READ_MEMORY:
+ m_address = (m_a2 << 8) | m_a1;
+ m_address -= 1;
+ break;
+
+ case DS2404_STATE_WRITE_SCRATCHPAD:
+ m_address = (m_a2 << 8) | m_a1;
+ m_offset = m_address & 0x1f;
+ break;
+
+ case DS2404_STATE_READ_SCRATCHPAD:
+ m_address = (m_a2 << 8) | m_a1;
+ m_offset = m_address & 0x1f;
+ break;
+
+ case DS2404_STATE_COPY_SCRATCHPAD:
+ m_address = (m_a2 << 8) | m_a1;
+
+ for(int i = 0; i <= m_end_offset; i++)
+ {
+ ds2404_writemem(m_ram[i]);
+ m_address++;
+ }
+ break;
+ }
+ m_state_ptr++;
+ }
+}
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(ds2404, ds2404_clk_w)
+{
+ switch( m_state[m_state_ptr] )
+ {
+ case DS2404_STATE_IDLE:
+ case DS2404_STATE_COMMAND:
+ case DS2404_STATE_ADDRESS1:
+ case DS2404_STATE_ADDRESS2:
+ case DS2404_STATE_OFFSET:
+ case DS2404_STATE_INIT_COMMAND:
+ break;
+
+ case DS2404_STATE_READ_MEMORY:
+ m_address++;
+ break;
+
+ case DS2404_STATE_READ_SCRATCHPAD:
+ break;
+
+ case DS2404_STATE_WRITE_SCRATCHPAD:
+ break;
+
+ case DS2404_STATE_COPY_SCRATCHPAD:
+ break;
+ }
+}
+
+TIMER_CALLBACK( ds2404_device::ds2404_tick_callback )
+{
+ reinterpret_cast<ds2404_device*>(ptr)->ds2404_tick();
+}
+
+void ds2404_device::ds2404_tick()
+{
+ for(int i = 0; i < 5; i++)
+ {
+ m_rtc[ i ]++;
+ if(m_rtc[ i ] != 0)
+ {
+ break;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// nvram_default - called to initialize NVRAM to
+// its default state
+//-------------------------------------------------
+
+void ds2404_device::nvram_default()
+{
+ memset(m_sram, 0, sizeof(m_sram));
+}
+
+
+//-------------------------------------------------
+// nvram_read - called to read NVRAM from the
+// .nv file
+//-------------------------------------------------
+
+void ds2404_device::nvram_read(emu_file &file)
+{
+ file.read(m_sram, sizeof(m_sram));
+}
+
+
+//-------------------------------------------------
+// nvram_write - called to write NVRAM to the
+// .nv file
+//-------------------------------------------------
+
+void ds2404_device::nvram_write(emu_file &file)
+{
+ file.write(m_sram, sizeof(m_sram));
+}
diff --git a/trunk/src/emu/machine/ds2404.h b/trunk/src/emu/machine/ds2404.h
new file mode 100644
index 00000000000..8f28e2164c4
--- /dev/null
+++ b/trunk/src/emu/machine/ds2404.h
@@ -0,0 +1,140 @@
+/**********************************************************************
+
+ DALLAS DS2404
+
+ RTC + BACKUP RAM
+
+**********************************************************************/
+
+#ifndef __DS2404_H__
+#define __DS2404_H__
+
+#include "emu.h"
+
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_DS2404_ADD(_tag, _ref_year, _ref_month, _ref_day) \
+ MCFG_DEVICE_ADD(_tag, DS2404, 0) \
+ MCFG_DS2404_REF_YEAR(_ref_year) \
+ MCFG_DS2404_REF_MONTH(_ref_month) \
+ MCFG_DS2404_REF_DAY(_ref_day)
+
+#define MCFG_DS2404_REF_YEAR(_ref_year) \
+ ds2404_device::static_set_ref_year(*device, _ref_year);
+
+#define MCFG_DS2404_REF_MONTH(_ref_month) \
+ ds2404_device::static_set_ref_month(*device, _ref_month);
+
+#define MCFG_DS2404_REF_DAY(_ref_day) \
+ ds2404_device::static_set_ref_day(*device, _ref_day);
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> ds2404_device
+
+class ds2404_device : public device_t,
+ public device_nvram_interface
+{
+public:
+ // construction/destruction
+ ds2404_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // inline configuration helpers
+ static void static_set_ref_year(device_t &device, UINT32 m_ref_year);
+ static void static_set_ref_month(device_t &device, UINT8 m_ref_month);
+ static void static_set_ref_day(device_t &device, UINT8 m_ref_day);
+
+ /* 1-wire interface reset */
+ void ds2404_1w_reset_w(UINT32 offset, UINT8 data);
+
+ /* 3-wire interface reset */
+ void ds2404_3w_reset_w(UINT32 offset, UINT8 data);
+
+ UINT8 ds2404_data_r(UINT32 offset);
+ void ds2404_data_w(UINT32 offset, UINT8 data);
+ void ds2404_clk_w(UINT32 offset, UINT8 data);
+
+ void ds2404_tick();
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset() { }
+ virtual void device_post_load() { }
+ virtual void device_clock_changed() { }
+
+ // device_nvram_interface overrides
+ virtual void nvram_default();
+ virtual void nvram_read(emu_file &file);
+ virtual void nvram_write(emu_file &file);
+
+ static TIMER_CALLBACK( ds2404_tick_callback );
+
+private:
+
+ void ds2404_rom_cmd(UINT8 cmd);
+ void ds2404_cmd(UINT8 cmd);
+
+ UINT8 ds2404_readmem();
+ void ds2404_writemem(UINT8 value);
+
+ enum DS2404_STATE
+ {
+ DS2404_STATE_IDLE = 1, /* waiting for ROM command, in 1-wire mode */
+ DS2404_STATE_COMMAND, /* waiting for memory command */
+ DS2404_STATE_ADDRESS1, /* waiting for address bits 0-7 */
+ DS2404_STATE_ADDRESS2, /* waiting for address bits 8-15 */
+ DS2404_STATE_OFFSET, /* waiting for ending offset */
+ DS2404_STATE_INIT_COMMAND,
+ DS2404_STATE_READ_MEMORY, /* Read Memory command active */
+ DS2404_STATE_WRITE_SCRATCHPAD, /* Write Scratchpad command active */
+ DS2404_STATE_READ_SCRATCHPAD, /* Read Scratchpad command active */
+ DS2404_STATE_COPY_SCRATCHPAD /* Copy Scratchpad command active */
+ };
+
+ // configuration state
+ UINT32 m_ref_year;
+ UINT8 m_ref_month;
+ UINT8 m_ref_day;
+
+ UINT16 m_address;
+ UINT16 m_offset;
+ UINT16 m_end_offset;
+ UINT8 m_a1;
+ UINT8 m_a2;
+ UINT8 m_sram[512]; /* 4096 bits */
+ UINT8 m_ram[32]; /* scratchpad ram, 256 bits */
+ UINT8 m_rtc[5]; /* 40-bit RTC counter */
+ DS2404_STATE m_state[8];
+ int m_state_ptr;
+};
+
+
+// device type definition
+extern const device_type DS2404;
+
+
+
+/***************************************************************************
+ PROTOTYPES
+***************************************************************************/
+
+/* 1-wire interface reset */
+WRITE8_DEVICE_HANDLER( ds2404_1w_reset_w );
+
+/* 3-wire interface reset */
+WRITE8_DEVICE_HANDLER( ds2404_3w_reset_w );
+
+READ8_DEVICE_HANDLER( ds2404_data_r );
+WRITE8_DEVICE_HANDLER( ds2404_data_w );
+WRITE8_DEVICE_HANDLER( ds2404_clk_w );
+
+#endif
diff --git a/trunk/src/emu/machine/e0516.c b/trunk/src/emu/machine/e0516.c
new file mode 100644
index 00000000000..dcfeab3b0ad
--- /dev/null
+++ b/trunk/src/emu/machine/e0516.c
@@ -0,0 +1,274 @@
+/**********************************************************************
+
+ E05-16 Real Time Clock emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "e0516.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+
+// states
+enum
+{
+ STATE_ADDRESS = 0,
+ STATE_DATA
+};
+
+
+// registers
+enum
+{
+ SECOND = 0,
+ MINUTE,
+ HOUR,
+ DAY,
+ MONTH,
+ DAY_OF_WEEK,
+ YEAR,
+ ALL
+};
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// advance_seconds -
+//-------------------------------------------------
+
+inline void e0516_device::advance_seconds()
+{
+ m_register[SECOND]++;
+
+ if (m_register[SECOND] == 60)
+ {
+ m_register[SECOND] = 0;
+ m_register[MINUTE]++;
+ }
+
+ if (m_register[MINUTE] == 60)
+ {
+ m_register[MINUTE] = 0;
+ m_register[HOUR]++;
+ }
+
+ if (m_register[HOUR] == 24)
+ {
+ m_register[HOUR] = 0;
+ m_register[DAY]++;
+ m_register[DAY_OF_WEEK]++;
+ }
+
+ if (m_register[DAY_OF_WEEK] == 8)
+ {
+ m_register[DAY_OF_WEEK] = 1;
+ }
+
+ if (m_register[DAY] == 32)
+ {
+ m_register[DAY] = 1;
+ m_register[MONTH]++;
+ }
+
+ if (m_register[MONTH] == 13)
+ {
+ m_register[MONTH] = 1;
+ m_register[YEAR]++;
+ }
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type E0516 = &device_creator<e0516_device>;
+
+//-------------------------------------------------
+// e0516_device - constructor
+//-------------------------------------------------
+
+e0516_device::e0516_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, E0516, "E05-16", tag, owner, clock),
+ device_rtc_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void e0516_device::device_start()
+{
+ // allocate timers
+ m_timer = timer_alloc();
+ m_timer->adjust(attotime::from_hz(clock() / 32768), 0, attotime::from_hz(clock() / 32768));
+
+ // state saving
+ save_item(NAME(m_cs));
+ save_item(NAME(m_clk));
+ save_item(NAME(m_data_latch));
+ save_item(NAME(m_reg_latch));
+ save_item(NAME(m_read_write));
+ save_item(NAME(m_state));
+ save_item(NAME(m_bits));
+ save_item(NAME(m_dio));
+ save_item(NAME(m_register));
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific reset
+//-------------------------------------------------
+
+void e0516_device::device_reset()
+{
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void e0516_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ advance_seconds();
+}
+
+
+//-------------------------------------------------
+// rtc_set_time - called to initialize the RTC to
+// a known state
+//-------------------------------------------------
+
+void e0516_device::rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second)
+{
+ m_register[YEAR] = year;
+ m_register[MONTH] = month;
+ m_register[DAY] = day;
+ m_register[DAY_OF_WEEK] = day_of_week + 1;
+ m_register[HOUR] = hour;
+ m_register[MINUTE] = minute;
+ m_register[SECOND] = second;
+}
+
+
+//-------------------------------------------------
+// cs_w - chip select input
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( e0516_device::cs_w )
+{
+ m_cs = state;
+
+ if (m_cs)
+ {
+ m_data_latch = 0;
+ m_reg_latch = 0;
+ m_bits = 0;
+ m_state = STATE_ADDRESS;
+ }
+}
+
+
+//-------------------------------------------------
+// clk_w - serial clock input
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( e0516_device::clk_w )
+{
+ m_clk = state;
+
+ if (m_cs || m_clk) return;
+
+ m_bits++;
+
+ if (m_state == STATE_ADDRESS)
+ {
+ if (LOG) logerror("E05-16 '%s' Command Bit %u\n", tag(), m_dio);
+
+ // command
+ m_reg_latch |= m_dio << 3;
+ m_reg_latch >>= 1;
+
+ if (m_bits == 4)
+ {
+ m_state = STATE_DATA;
+ m_bits = 0;
+
+ if (BIT(m_reg_latch, 0))
+ {
+ // load register value to data latch
+ m_data_latch = m_register[m_reg_latch >> 1];
+ }
+ }
+ }
+ else
+ {
+ // data
+ if (BIT(m_reg_latch, 0))
+ {
+ // read
+ if (LOG) logerror("E05-16 '%s' Data Bit OUT %u\n", tag(), m_dio);
+
+ m_dio = BIT(m_data_latch, 0);
+ m_data_latch >>= 1;
+ }
+ else
+ {
+ // write
+ if (LOG) logerror("E05-16 '%s' Data Bit IN %u\n", tag(), m_dio);
+
+ m_data_latch |= m_dio << 7;
+ m_data_latch >>= 1;
+ }
+
+ if (m_bits == 8)
+ {
+ m_state = STATE_ADDRESS;
+ m_bits = 0;
+
+ if (!BIT(m_reg_latch, 0))
+ {
+ // write latched data to register
+ m_register[m_reg_latch >> 1] = m_data_latch;
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// dio_w - serial data input
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( e0516_device::dio_w )
+{
+ m_dio = state;
+}
+
+
+//-------------------------------------------------
+// do_r - serial data output
+//-------------------------------------------------
+
+READ_LINE_MEMBER( e0516_device::dio_r )
+{
+ return m_dio;
+}
diff --git a/trunk/src/emu/machine/e0516.h b/trunk/src/emu/machine/e0516.h
new file mode 100644
index 00000000000..ea2c04da29b
--- /dev/null
+++ b/trunk/src/emu/machine/e0516.h
@@ -0,0 +1,92 @@
+/**********************************************************************
+
+ E05-16 Real Time Clock emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ Vdd1 1 |* \_/ | 16 Vdd2
+ OSC IN 2 | | 15 Clk
+ OSC OUT 3 | | 14 XOUT
+ _STOP 4 | E05-16 | 13 DI/O
+ _RESET 5 | E050-16 | 12 _SEC
+ _OUTSEL 6 | | 11 _MIN
+ _DAY 7 | | 10 _HRS
+ Vss 8 |_____________| 9 _CS
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __E0516__
+#define __E0516__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_E0516_ADD(_tag, _clock) \
+ MCFG_DEVICE_ADD(_tag, E0516, _clock)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> e0516_device
+
+class e0516_device : public device_t,
+ public device_rtc_interface
+{
+public:
+ // construction/destruction
+ e0516_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_WRITE_LINE_MEMBER( cs_w );
+ DECLARE_WRITE_LINE_MEMBER( clk_w );
+ DECLARE_WRITE_LINE_MEMBER( dio_w );
+ DECLARE_READ_LINE_MEMBER( dio_r );
+
+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_rtc_interface overrides
+ virtual void rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second);
+ virtual bool rtc_is_year_2000_compliant() { return false; }
+
+private:
+ inline void advance_seconds();
+
+ int m_cs; // chip select
+ int m_clk; // clock
+ int m_data_latch; // data latch
+ int m_reg_latch; // register latch
+ int m_read_write; // read/write data
+ int m_state; // state
+ int m_bits; // number of bits transferred
+ int m_dio; // data pin
+
+ UINT8 m_register[8]; // registers
+
+ // timers
+ emu_timer *m_timer;
+};
+
+
+// device type definition
+extern const device_type E0516;
+
+
+
+#endif
diff --git a/trunk/src/emu/machine/eeprom.c b/trunk/src/emu/machine/eeprom.c
new file mode 100644
index 00000000000..07ef93e25bf
--- /dev/null
+++ b/trunk/src/emu/machine/eeprom.c
@@ -0,0 +1,563 @@
+/***************************************************************************
+
+ eeprom.c
+
+ Serial eeproms.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "machine/eeprom.h"
+
+
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define VERBOSE 0
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+const device_type EEPROM = &device_creator<eeprom_device>;
+
+const eeprom_interface eeprom_interface_93C46 =
+{
+ 6, // address bits 6
+ 16, // data bits 16
+ "*110", // read 1 10 aaaaaa
+ "*101", // write 1 01 aaaaaa dddddddddddddddd
+ "*111", // erase 1 11 aaaaaa
+ "*10000xxxx", // lock 1 00 00xxxx
+ "*10011xxxx", // unlock 1 00 11xxxx
+ 1, // enable_multi_read
+ 0 // reset_delay
+// "*10001xxxx" // write all 1 00 01xxxx dddddddddddddddd
+// "*10010xxxx" // erase all 1 00 10xxxx
+};
+
+const eeprom_interface eeprom_interface_93C46_8bit =
+{
+ 7, // address bits 7
+ 8, // data bits 8
+ "*110", // read 1 10 aaaaaa
+ "*101", // write 1 01 aaaaaa dddddddd
+ "*111", // erase 1 11 aaaaaa
+ "*10000xxxx", // lock 1 00 00xxxx
+ "*10011xxxx", // unlock 1 00 11xxxx
+ 1, // enable_multi_read
+ 0 // reset_delay
+// "*10001xxxx" // write all 1 00 01xxxx dddddddd
+// "*10010xxxx" // erase all 1 00 10xxxx
+};
+
+const eeprom_interface eeprom_interface_93C66B =
+{
+ 8, // address bits
+ 16, // data bits
+ "*110", // read command
+ "*101", // write command
+ "*111", // erase command
+ "*10000xxxxxx", // lock command
+ "*10011xxxxxx", // unlock command
+ 1, // enable_multi_read
+ 0 // reset_delay
+// "*10001xxxxxx", // write all
+// "*10010xxxxxx", // erase all
+};
+
+
+static ADDRESS_MAP_START( eeprom_map8, AS_PROGRAM, 8 )
+ AM_RANGE(0x0000, 0x0fff) AM_RAM
+ADDRESS_MAP_END
+
+
+static ADDRESS_MAP_START( eeprom_map16, AS_PROGRAM, 16 )
+ AM_RANGE(0x0000, 0x07ff) AM_RAM
+ADDRESS_MAP_END
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// eeprom_device - constructor
+//-------------------------------------------------
+
+eeprom_device::eeprom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, EEPROM, "EEPROM", tag, owner, clock),
+ device_memory_interface(mconfig, *this),
+ device_nvram_interface(mconfig, *this),
+ m_default_data_size(0),
+ m_default_value(0),
+ m_serial_count(0),
+ m_data_buffer(0),
+ m_read_address(0),
+ m_clock_count(0),
+ m_latch(0),
+ m_reset_line(CLEAR_LINE),
+ m_clock_line(CLEAR_LINE),
+ m_sending(0),
+ m_locked(false),
+ m_reset_counter(0)
+{
+ m_default_data.u8 = NULL;
+ memset(downcast<eeprom_interface *>(this), 0, sizeof(eeprom_interface));
+}
+
+
+//-------------------------------------------------
+// static_set_interface - configuration helper
+// to set the interface
+//-------------------------------------------------
+
+void eeprom_device::static_set_interface(device_t &device, const eeprom_interface &interface)
+{
+ eeprom_device &eeprom = downcast<eeprom_device &>(device);
+ static_cast<eeprom_interface &>(eeprom) = interface;
+
+ // describe our address space
+ if (eeprom.m_data_bits == 8)
+ eeprom.m_space_config = address_space_config("eeprom", ENDIANNESS_BIG, 8, eeprom.m_address_bits, 0, *ADDRESS_MAP_NAME(eeprom_map8));
+ else
+ eeprom.m_space_config = address_space_config("eeprom", ENDIANNESS_BIG, 16, eeprom.m_address_bits * 2, 0, *ADDRESS_MAP_NAME(eeprom_map16));
+}
+
+
+//-------------------------------------------------
+// static_set_default_data - configuration helpers
+// to set the default data
+//-------------------------------------------------
+
+void eeprom_device::static_set_default_data(device_t &device, const UINT8 *data, UINT32 size)
+{
+ eeprom_device &eeprom = downcast<eeprom_device &>(device);
+ assert(eeprom.m_data_bits == 8);
+ eeprom.m_default_data.u8 = const_cast<UINT8 *>(data);
+ eeprom.m_default_data_size = size;
+}
+
+void eeprom_device::static_set_default_data(device_t &device, const UINT16 *data, UINT32 size)
+{
+ eeprom_device &eeprom = downcast<eeprom_device &>(device);
+ assert(eeprom.m_data_bits == 16);
+ eeprom.m_default_data.u16 = const_cast<UINT16 *>(data);
+ eeprom.m_default_data_size = size / 2;
+}
+
+
+//-------------------------------------------------
+// static_set_default_value - configuration helper
+// to set the default value
+//-------------------------------------------------
+
+void eeprom_device::static_set_default_value(device_t &device, UINT16 value)
+{
+ downcast<eeprom_device &>(device).m_default_value = 0x10000 | value;
+}
+
+
+//-------------------------------------------------
+// device_validity_check - perform validity checks
+// on this device
+//-------------------------------------------------
+
+bool eeprom_device::device_validity_check(emu_options &options, const game_driver &driver) const
+{
+ bool error = false;
+
+ if (m_data_bits != 8 && m_data_bits != 16)
+ {
+ mame_printf_error("%s: %s eeprom device '%s' specified invalid data width %d\n", driver.source_file, driver.name, tag(), m_data_bits);
+ error = true;
+ }
+
+ return error;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void eeprom_device::device_start()
+{
+ m_locked = (m_cmd_unlock != NULL);
+
+ save_pointer(NAME(m_serial_buffer), SERIAL_BUFFER_LENGTH);
+ save_item(NAME(m_clock_line));
+ save_item(NAME(m_reset_line));
+ save_item(NAME(m_locked));
+ save_item(NAME(m_serial_count));
+ save_item(NAME(m_latch));
+ save_item(NAME(m_reset_counter));
+ save_item(NAME(m_clock_count));
+ save_item(NAME(m_data_buffer));
+ save_item(NAME(m_read_address));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void eeprom_device::device_reset()
+{
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return a description of
+// any address spaces owned by this device
+//-------------------------------------------------
+
+const address_space_config *eeprom_device::memory_space_config(address_spacenum spacenum) const
+{
+ return (spacenum == 0) ? &m_space_config : NULL;
+}
+
+
+//-------------------------------------------------
+// nvram_default - called to initialize NVRAM to
+// its default state
+//-------------------------------------------------
+
+void eeprom_device::nvram_default()
+{
+ UINT32 eeprom_length = 1 << m_address_bits;
+ UINT32 eeprom_bytes = eeprom_length * m_data_bits / 8;
+
+ /* initialize to the default value */
+ UINT16 default_value = 0xffff;
+ if (m_default_value != 0)
+ default_value = m_default_value;
+ for (offs_t offs = 0; offs < eeprom_length; offs++)
+ if (m_data_bits == 8)
+ m_addrspace[0]->write_byte(offs, default_value);
+ else
+ m_addrspace[0]->write_word(offs * 2, default_value);
+
+ /* handle hard-coded data from the driver */
+ if (m_default_data.u8 != NULL)
+ for (offs_t offs = 0; offs < m_default_data_size; offs++)
+ if (m_data_bits == 8)
+ m_addrspace[0]->write_byte(offs, m_default_data.u8[offs]);
+ else
+ m_addrspace[0]->write_word(offs * 2, m_default_data.u16[offs]);
+
+ /* populate from a memory region if present */
+ if (m_region != NULL)
+ {
+ if (m_region->bytes() != eeprom_bytes)
+ fatalerror("eeprom region '%s' wrong size (expected size = 0x%X)", tag(), eeprom_bytes);
+ if (m_data_bits == 8 && m_region->width() != 1)
+ fatalerror("eeprom region '%s' needs to be an 8-bit region", tag());
+ if (m_data_bits == 16 && (m_region->width() != 2 || m_region->endianness() != ENDIANNESS_BIG))
+ fatalerror("eeprom region '%s' needs to be a 16-bit big-endian region", tag());
+
+ for (offs_t offs = 0; offs < eeprom_length; offs++)
+ if (m_data_bits == 8)
+ m_addrspace[0]->write_byte(offs, m_region->u8(offs));
+ else
+ m_addrspace[0]->write_word(offs * 2, m_region->u16(offs));
+ }
+}
+
+
+//-------------------------------------------------
+// nvram_read - called to read NVRAM from the
+// .nv file
+//-------------------------------------------------
+
+void eeprom_device::nvram_read(emu_file &file)
+{
+ UINT32 eeprom_length = 1 << m_address_bits;
+ UINT32 eeprom_bytes = eeprom_length * m_data_bits / 8;
+
+ UINT8 *buffer = auto_alloc_array(machine(), UINT8, eeprom_bytes);
+ file.read(buffer, eeprom_bytes);
+ for (offs_t offs = 0; offs < eeprom_bytes; offs++)
+ m_addrspace[0]->write_byte(offs, buffer[offs]);
+ auto_free(machine(), buffer);
+}
+
+
+//-------------------------------------------------
+// nvram_write - called to write NVRAM to the
+// .nv file
+//-------------------------------------------------
+
+void eeprom_device::nvram_write(emu_file &file)
+{
+ UINT32 eeprom_length = 1 << m_address_bits;
+ UINT32 eeprom_bytes = eeprom_length * m_data_bits / 8;
+
+ UINT8 *buffer = auto_alloc_array(machine(), UINT8, eeprom_bytes);
+ for (offs_t offs = 0; offs < eeprom_bytes; offs++)
+ buffer[offs] = m_addrspace[0]->read_byte(offs);
+ file.write(buffer, eeprom_bytes);
+ auto_free(machine(), buffer);
+}
+
+
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+WRITE_LINE_MEMBER( eeprom_device::write_bit )
+{
+ LOG(("write bit %d\n",state));
+ m_latch = state;
+}
+
+
+READ_LINE_DEVICE_HANDLER( eeprom_read_bit )
+{
+ return downcast<eeprom_device *>(device)->read_bit();
+}
+
+READ_LINE_MEMBER( eeprom_device::read_bit )
+{
+ int res;
+
+ if (m_sending)
+ res = (m_data_buffer >> m_data_bits) & 1;
+ else
+ {
+ if (m_reset_counter > 0)
+ {
+ /* this is needed by wbeachvl */
+ m_reset_counter--;
+ res = 0;
+ }
+ else
+ res = 1;
+ }
+
+ LOG(("read bit %d\n",res));
+
+ return res;
+}
+
+
+
+WRITE_LINE_MEMBER( eeprom_device::set_cs_line )
+{
+ LOG(("set reset line %d\n",state));
+ m_reset_line = state;
+
+ if (m_reset_line != CLEAR_LINE)
+ {
+ if (m_serial_count)
+ logerror("EEPROM %s reset, buffer = %s\n", tag(), m_serial_buffer);
+
+ m_serial_count = 0;
+ m_sending = 0;
+ m_reset_counter = m_reset_delay; /* delay a little before returning setting data to 1 (needed by wbeachvl) */
+ }
+}
+
+
+
+WRITE_LINE_MEMBER( eeprom_device::set_clock_line )
+{
+ LOG(("set clock line %d\n",state));
+ if (state == PULSE_LINE || (m_clock_line == CLEAR_LINE && state != CLEAR_LINE))
+ {
+ if (m_reset_line == CLEAR_LINE)
+ {
+ if (m_sending)
+ {
+ if (m_clock_count == m_data_bits && m_enable_multi_read)
+ {
+ m_read_address = (m_read_address + 1) & ((1 << m_address_bits) - 1);
+ if (m_data_bits == 16)
+ m_data_buffer = m_addrspace[0]->read_word(m_read_address * 2);
+ else
+ m_data_buffer = m_addrspace[0]->read_byte(m_read_address);
+ m_clock_count = 0;
+ logerror("EEPROM %s read %04x from address %02x\n", tag(), m_data_buffer, m_read_address);
+ }
+ m_data_buffer = (m_data_buffer << 1) | 1;
+ m_clock_count++;
+ }
+ else
+ write(m_latch);
+ }
+ }
+
+ m_clock_line = state;
+}
+
+
+
+//**************************************************************************
+// INTERNAL HELPERS
+//**************************************************************************
+
+void eeprom_device::write(int bit)
+{
+ LOG(("EEPROM %s write bit %d\n", tag(), bit));
+
+ if (m_serial_count >= SERIAL_BUFFER_LENGTH-1)
+ {
+ logerror("error: EEPROM %s serial buffer overflow\n", tag());
+ return;
+ }
+
+ m_serial_buffer[m_serial_count++] = (bit ? '1' : '0');
+ m_serial_buffer[m_serial_count] = 0; /* nul terminate so we can treat it as a string */
+
+ if ( (m_serial_count > m_address_bits) &&
+ command_match((char*)(m_serial_buffer),m_cmd_read,strlen((char*)(m_serial_buffer))-m_address_bits) )
+ {
+ int i,address;
+
+ address = 0;
+ for (i = m_serial_count-m_address_bits;i < m_serial_count;i++)
+ {
+ address <<= 1;
+ if (m_serial_buffer[i] == '1') address |= 1;
+ }
+ if (m_data_bits == 16)
+ m_data_buffer = m_addrspace[0]->read_word(address * 2);
+ else
+ m_data_buffer = m_addrspace[0]->read_byte(address);
+ m_read_address = address;
+ m_clock_count = 0;
+ m_sending = 1;
+ m_serial_count = 0;
+ logerror("EEPROM %s read %04x from address %02x\n", tag(), m_data_buffer,address);
+ }
+ else if ( (m_serial_count > m_address_bits) &&
+ command_match((char*)(m_serial_buffer),m_cmd_erase,strlen((char*)(m_serial_buffer))-m_address_bits) )
+ {
+ int i,address;
+
+ address = 0;
+ for (i = m_serial_count-m_address_bits;i < m_serial_count;i++)
+ {
+ address <<= 1;
+ if (m_serial_buffer[i] == '1') address |= 1;
+ }
+ logerror("EEPROM %s erase address %02x\n", tag(), address);
+ if (m_locked == 0)
+ {
+ if (m_data_bits == 16)
+ m_addrspace[0]->write_word(address * 2, 0x0000);
+ else
+ m_addrspace[0]->write_byte(address, 0x00);
+ }
+ else
+ logerror("Error: EEPROM %s is locked\n", tag());
+ m_serial_count = 0;
+ }
+ else if ( (m_serial_count > (m_address_bits + m_data_bits)) &&
+ command_match((char*)(m_serial_buffer),m_cmd_write,strlen((char*)(m_serial_buffer))-(m_address_bits + m_data_bits)) )
+ {
+ int i,address,data;
+
+ address = 0;
+ for (i = m_serial_count-m_data_bits-m_address_bits;i < (m_serial_count-m_data_bits);i++)
+ {
+ address <<= 1;
+ if (m_serial_buffer[i] == '1') address |= 1;
+ }
+ data = 0;
+ for (i = m_serial_count-m_data_bits;i < m_serial_count;i++)
+ {
+ data <<= 1;
+ if (m_serial_buffer[i] == '1') data |= 1;
+ }
+ logerror("EEPROM %s write %04x to address %02x\n", tag(), data, address);
+ if (m_locked == 0)
+ {
+ if (m_data_bits == 16)
+ m_addrspace[0]->write_word(address * 2, data);
+ else
+ m_addrspace[0]->write_byte(address, data);
+ }
+ else
+ logerror("Error: EEPROM %s is locked\n", tag());
+ m_serial_count = 0;
+ }
+ else if ( command_match((char*)(m_serial_buffer),m_cmd_lock,strlen((char*)(m_serial_buffer))) )
+ {
+ logerror("EEPROM %s lock\n", tag());
+ m_locked = 1;
+ m_serial_count = 0;
+ }
+ else if ( command_match((char*)(m_serial_buffer),m_cmd_unlock,strlen((char*)(m_serial_buffer))) )
+ {
+ logerror("EEPROM %s unlock\n", tag());
+ m_locked = 0;
+ m_serial_count = 0;
+ }
+}
+
+
+/*
+ command_match:
+
+ Try to match the first (len) digits in the EEPROM serial buffer
+ string (*buf) with an EEPROM command string (*cmd).
+ Return non zero if a match was found.
+
+ The serial buffer only contains '0' or '1' (e.g. "1001").
+ The command can contain: '0' or '1' or these wildcards:
+
+ 'x' : match both '0' and '1'
+ "*1": match "1", "01", "001", "0001" etc.
+ "*0": match "0", "10", "110", "1110" etc.
+
+ Note: (cmd) may be NULL. Return 0 (no match) in this case.
+*/
+bool eeprom_device::command_match(const char *buf, const char *cmd, int len)
+{
+ if ( cmd == 0 ) return false;
+ if ( len == 0 ) return false;
+
+ for (;len>0;)
+ {
+ char b = *buf;
+ char c = *cmd;
+
+ if ((b==0) || (c==0))
+ return (b==c);
+
+ switch ( c )
+ {
+ case '0':
+ case '1':
+ if (b != c) return false;
+ case 'X':
+ case 'x':
+ buf++;
+ len--;
+ cmd++;
+ break;
+
+ case '*':
+ c = cmd[1];
+ switch( c )
+ {
+ case '0':
+ case '1':
+ if (b == c) { cmd++; }
+ else { buf++; len--; }
+ break;
+ default: return false;
+ }
+ }
+ }
+ return (*cmd==0);
+}
diff --git a/trunk/src/emu/machine/eeprom.h b/trunk/src/emu/machine/eeprom.h
new file mode 100644
index 00000000000..31c44d15ec1
--- /dev/null
+++ b/trunk/src/emu/machine/eeprom.h
@@ -0,0 +1,142 @@
+/***************************************************************************
+
+ eeprom.h
+
+ Serial eeproms.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __EEPROMDEV_H__
+#define __EEPROMDEV_H__
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_EEPROM_ADD(_tag, _interface) \
+ MCFG_DEVICE_ADD(_tag, EEPROM, 0) \
+ eeprom_device::static_set_interface(*device, _interface); \
+
+#define MCFG_EEPROM_93C46_ADD(_tag) \
+ MCFG_EEPROM_ADD(_tag, eeprom_interface_93C46)
+
+#define MCFG_EEPROM_93C46_8BIT_ADD(_tag) \
+ MCFG_EEPROM_ADD(_tag, eeprom_interface_93C46_8bit)
+
+#define MCFG_EEPROM_93C66B_ADD(_tag) \
+ MCFG_EEPROM_ADD(_tag, eeprom_interface_93C66B)
+
+#define MCFG_EEPROM_DATA(_data, _size) \
+ eeprom_device::static_set_default_data(*device, _data, _size); \
+
+#define MCFG_EEPROM_DEFAULT_VALUE(_value) \
+ eeprom_device::static_set_default_value(*device, _value); \
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> eeprom_interface
+
+struct eeprom_interface
+{
+ UINT8 m_address_bits; // EEPROM has 2^address_bits cells
+ UINT8 m_data_bits; // every cell has this many bits (8 or 16)
+ const char *m_cmd_read; // read command string, e.g. "0110"
+ const char *m_cmd_write; // write command string, e.g. "0111"
+ const char *m_cmd_erase; // erase command string, or 0 if n/a
+ const char *m_cmd_lock; // lock command string, or 0 if n/a
+ const char *m_cmd_unlock; // unlock command string, or 0 if n/a
+ bool m_enable_multi_read; // set to 1 to enable multiple values to be read from one read command
+ int m_reset_delay; // number of times eeprom_read_bit() should return 0 after a reset,
+ // before starting to return 1.
+};
+
+
+
+// ======================> eeprom_device
+
+class eeprom_device : public device_t,
+ public device_memory_interface,
+ public device_nvram_interface,
+ public eeprom_interface
+{
+public:
+ // construction/destruction
+ eeprom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // inline configuration helpers
+ static void static_set_interface(device_t &device, const eeprom_interface &interface);
+ static void static_set_default_data(device_t &device, const UINT8 *data, UINT32 size);
+ static void static_set_default_data(device_t &device, const UINT16 *data, UINT32 size);
+ static void static_set_default_value(device_t &device, UINT16 value);
+
+ // I/O operations
+ DECLARE_WRITE_LINE_MEMBER( write_bit );
+ DECLARE_READ_LINE_MEMBER( read_bit );
+ DECLARE_WRITE_LINE_MEMBER( set_cs_line );
+ DECLARE_WRITE_LINE_MEMBER( set_clock_line );
+
+protected:
+ // device-level overrides
+ virtual bool device_validity_check(emu_options &options, const game_driver &driver) const;
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
+
+ // device_nvram_interface overrides
+ virtual void nvram_default();
+ virtual void nvram_read(emu_file &file);
+ virtual void nvram_write(emu_file &file);
+
+ // internal helpers
+ void write(int bit);
+ bool command_match(const char *buf, const char *cmd, int len);
+
+ static const int SERIAL_BUFFER_LENGTH = 40;
+
+ // configuration state
+ address_space_config m_space_config;
+ generic_ptr m_default_data;
+ int m_default_data_size;
+ UINT32 m_default_value;
+
+ // runtime state
+ int m_serial_count;
+ UINT8 m_serial_buffer[SERIAL_BUFFER_LENGTH];
+ int m_data_buffer;
+ int m_read_address;
+ int m_clock_count;
+ int m_latch;
+ int m_reset_line;
+ int m_clock_line;
+ int m_sending;
+ int m_locked;
+ int m_reset_counter;
+};
+
+
+// device type definition
+extern const device_type EEPROM;
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+extern const eeprom_interface eeprom_interface_93C46;
+extern const eeprom_interface eeprom_interface_93C46_8bit;
+extern const eeprom_interface eeprom_interface_93C66B;
+
+
+#endif
diff --git a/trunk/src/emu/machine/er2055.c b/trunk/src/emu/machine/er2055.c
new file mode 100644
index 00000000000..a4e336e83ab
--- /dev/null
+++ b/trunk/src/emu/machine/er2055.c
@@ -0,0 +1,205 @@
+/***************************************************************************
+
+ er2055.c
+
+ GI 512 bit electrically alterable read-only memory.
+
+****************************************************************************
+
+ 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 "machine/er2055.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+const device_type ER2055 = &device_creator<er2055_device>;
+
+static ADDRESS_MAP_START( er2055_map, AS_PROGRAM, 8 )
+ AM_RANGE(0x0000, 0x003f) AM_RAM
+ADDRESS_MAP_END
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// er2055_device - constructor
+//-------------------------------------------------
+
+er2055_device::er2055_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, ER2055, "ER2055", tag, owner, clock),
+ device_memory_interface(mconfig, *this),
+ device_nvram_interface(mconfig, *this),
+ m_space_config("EAROM", ENDIANNESS_BIG, 8, 6, 0, *ADDRESS_MAP_NAME(er2055_map)),
+ m_control_state(0),
+ m_address(0),
+ m_data(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void er2055_device::device_start()
+{
+ save_item(NAME(m_control_state));
+ save_item(NAME(m_address));
+ save_item(NAME(m_data));
+
+ m_control_state = 0;
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return a description of
+// any address spaces owned by this device
+//-------------------------------------------------
+
+const address_space_config *er2055_device::memory_space_config(address_spacenum spacenum) const
+{
+ return (spacenum == 0) ? &m_space_config : NULL;
+}
+
+
+//-------------------------------------------------
+// nvram_default - called to initialize NVRAM to
+// its default state
+//-------------------------------------------------
+
+void er2055_device::nvram_default()
+{
+ // default to all-0xff
+ for (int byte = 0; byte < SIZE_DATA; byte++)
+ m_addrspace[0]->write_byte(byte, 0xff);
+
+ // populate from a memory region if present
+ if (m_region != NULL)
+ {
+ if (m_region->bytes() != SIZE_DATA)
+ fatalerror("er2055 region '%s' wrong size (expected size = 0x100)", tag());
+ if (m_region->width() != 1)
+ fatalerror("er2055 region '%s' needs to be an 8-bit region", tag());
+
+ for (int byte = 0; byte < SIZE_DATA; byte++)
+ m_addrspace[0]->write_byte(byte, m_region->u8(byte));
+ }
+}
+
+
+//-------------------------------------------------
+// nvram_read - called to read NVRAM from the
+// .nv file
+//-------------------------------------------------
+
+void er2055_device::nvram_read(emu_file &file)
+{
+ UINT8 buffer[SIZE_DATA];
+ file.read(buffer, sizeof(buffer));
+ for (int byte = 0; byte < SIZE_DATA; byte++)
+ m_addrspace[0]->write_byte(byte, buffer[byte]);
+}
+
+
+//-------------------------------------------------
+// nvram_write - called to write NVRAM to the
+// .nv file
+//-------------------------------------------------
+
+void er2055_device::nvram_write(emu_file &file)
+{
+ UINT8 buffer[SIZE_DATA];
+ for (int byte = 0; byte < SIZE_DATA; byte++)
+ buffer[byte] = m_addrspace[0]->read_byte(byte);
+ file.write(buffer, sizeof(buffer));
+}
+
+
+
+//**************************************************************************
+// I/O OPERATIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// set_control - set the control lines; these
+// must be done simultaneously because the chip
+// reacts to various combinations
+//-------------------------------------------------
+
+void er2055_device::set_control(UINT8 cs1, UINT8 cs2, UINT8 c1, UINT8 c2, UINT8 ck)
+{
+ // create a new composite control state
+ UINT8 oldstate = m_control_state;
+ m_control_state = (ck != 0) ? CK : 0;
+ m_control_state |= (c1 != 0) ? C1 : 0;
+ m_control_state |= (c2 != 0) ? C2 : 0;
+ m_control_state |= (cs1 != 0) ? CS1 : 0;
+ m_control_state |= (cs2 != 0) ? CS2 : 0;
+
+ // if not selected, or if change from previous, we're done
+ if ((m_control_state & (CS1 | CS2)) != (CS1 | CS2) || m_control_state == oldstate)
+ return;
+
+ // something changed, see what it is based on what mode we're in
+ switch (m_control_state & (C1 | C2))
+ {
+ // write mode; erasing is required, so we perform an AND against previous
+ // data to simulate incorrect behavior if erasing was not done
+ case 0:
+ m_addrspace[0]->write_byte(m_address, m_addrspace[0]->read_byte(m_address) & m_data);
+//printf("Write %02X = %02X\n", m_address, m_data);
+ break;
+
+ // erase mode
+ case C2:
+ m_addrspace[0]->write_byte(m_address, 0xff);
+//printf("Erase %02X\n", m_address);
+ break;
+
+ // read mode
+ case C1:
+ if ((oldstate & CK) != 0 && (m_control_state & CK) == 0)
+ {
+ m_data = m_addrspace[0]->read_byte(m_address);
+//printf("Read %02X = %02X\n", m_address, m_data);
+ }
+ break;
+ }
+}
diff --git a/trunk/src/emu/machine/er2055.h b/trunk/src/emu/machine/er2055.h
new file mode 100644
index 00000000000..f47b503d57c
--- /dev/null
+++ b/trunk/src/emu/machine/er2055.h
@@ -0,0 +1,113 @@
+/***************************************************************************
+
+ er2055.h
+
+ GI 512 bit electrically alterable read-only memory.
+
+****************************************************************************
+
+ 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 __ER2055_H__
+#define __ER2055_H__
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_ER2055_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, ER2055, 0) \
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> er2055_device
+
+class er2055_device : public device_t,
+ public device_memory_interface,
+ public device_nvram_interface
+{
+public:
+ // construction/destruction
+ er2055_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // I/O operations
+ UINT8 data() const { return m_data; }
+ void set_address(UINT8 address) { m_address = address & 0x3f; }
+ void set_data(UINT8 data) { m_data = data; }
+
+ // control lines -- all lines are specified as active-high (even CS2)
+ void set_control(UINT8 cs1, UINT8 cs2, UINT8 c1, UINT8 c2, UINT8 ck);
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
+
+ // device_nvram_interface overrides
+ virtual void nvram_default();
+ virtual void nvram_read(emu_file &file);
+ virtual void nvram_write(emu_file &file);
+
+ static const int SIZE_DATA = 0x40;
+
+ static const UINT8 CK = 0x01;
+ static const UINT8 C1 = 0x02;
+ static const UINT8 C2 = 0x04;
+ static const UINT8 CS1 = 0x08;
+ static const UINT8 CS2 = 0x10;
+
+ // configuration state
+ address_space_config m_space_config;
+
+ // internal state
+ UINT8 m_control_state;
+ UINT8 m_address;
+ UINT8 m_data;
+};
+
+
+// device type definition
+extern const device_type ER2055;
+
+
+#endif
diff --git a/trunk/src/emu/machine/f3853.c b/trunk/src/emu/machine/f3853.c
new file mode 100644
index 00000000000..993028d4595
--- /dev/null
+++ b/trunk/src/emu/machine/f3853.c
@@ -0,0 +1,253 @@
+/**********************************************************************
+
+ Fairchild F3853 SRAM interface with integrated interrupt
+ controller and timer (SMI)
+
+ This chip is a timer shift register, basically the same as in the
+ F3851.
+
+ Based on a datasheet obtained from www.freetradezone.com
+
+ The SMI does not have DC0 and DC1, only DC0; as a result, it does
+ not respond to the main CPU's DC0/DC1 swap instruction. This may
+ lead to two devices responding to the same DC0 address and
+ attempting to place their bytes on the data bus simultaneously!
+
+ 8-bit shift register:
+ Feedback in0 = !((out3 ^ out4) ^ (out5 ^ out7))
+ Interrupts are at 0xfe
+ 0xff stops the register (0xfe is never reached)
+
+**********************************************************************/
+
+#include "emu.h"
+#include "f3853.h"
+#include "devhelpr.h"
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define INTERRUPT_VECTOR(external) ( external ? m_low | ( m_high << 8 ) | 0x80 \
+: ( m_low | ( m_high << 8 ) ) & ~0x80 )
+
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type F3853 = &device_creator<f3853_device>;
+
+//-------------------------------------------------
+// f3853_device - constructor
+//-------------------------------------------------
+
+f3853_device::f3853_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, F3853, "F3853", tag, owner, clock)
+{
+
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void f3853_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const f3853_interface *intf = reinterpret_cast<const f3853_interface *>(static_config());
+ if (intf != NULL)
+ {
+ *static_cast<f3853_interface *>(this) = *intf;
+ }
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_interrupt_request, 0, sizeof(m_interrupt_request));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void f3853_device::device_start()
+{
+ UINT8 reg = 0xfe;
+ for(INT32 i=254 /* Known to get 0xfe after 255 cycles */; i >= 0; i--)
+ {
+ INT32 o7 = (reg & 0x80) ? TRUE : FALSE;
+ INT32 o5 = (reg & 0x20) ? TRUE : FALSE;
+ INT32 o4 = (reg & 0x10) ? TRUE : FALSE;
+ INT32 o3 = (reg & 0x08) ? TRUE : FALSE;
+ m_value_to_cycle[reg] = i;
+ reg <<= 1;
+ if(!((o7 != o5) != (o4 != o3)))
+ {
+ reg |= 1;
+ }
+ }
+
+ m_timer = machine().scheduler().timer_alloc(FUNC(f3853_timer_callback), (void *)this );
+
+ save_item(NAME(m_high) );
+ save_item(NAME(m_low) );
+ save_item(NAME(m_external_enable) );
+ save_item(NAME(m_timer_enable) );
+ save_item(NAME(m_request_flipflop) );
+ save_item(NAME(m_priority_line) );
+ save_item(NAME(m_external_interrupt_line) );
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void f3853_device::device_reset()
+{
+ m_high = 0;
+ m_low = 0;
+ m_external_enable = 0;
+ m_timer_enable = 0;
+ m_request_flipflop = 0;
+ m_priority_line = FALSE;
+ m_external_interrupt_line = TRUE;
+
+ m_timer->enable(false);
+}
+
+
+void f3853_device::f3853_set_interrupt_request_line()
+{
+ if(!m_interrupt_request)
+ {
+ return;
+ }
+
+ if(m_external_enable && !m_priority_line)
+ {
+ m_interrupt_request(this, INTERRUPT_VECTOR(TRUE), TRUE);
+ }
+ else if( m_timer_enable && !m_priority_line && m_request_flipflop)
+ {
+ m_interrupt_request(this, INTERRUPT_VECTOR(FALSE), TRUE);
+ }
+ else
+ {
+ m_interrupt_request(this, 0, FALSE);
+ }
+}
+
+
+void f3853_device::f3853_timer_start(UINT8 value)
+{
+ attotime period = (value != 0xff) ? attotime::from_hz(clock()) * (m_value_to_cycle[value]*31) : attotime::never;
+
+ m_timer->adjust(period);
+}
+
+
+TIMER_CALLBACK( f3853_device::f3853_timer_callback )
+{
+ reinterpret_cast<f3853_device*>(ptr)->f3853_timer();
+}
+
+void f3853_device::f3853_timer()
+{
+ if(m_timer_enable)
+ {
+ m_request_flipflop = TRUE;
+ f3853_set_interrupt_request_line();
+ }
+ f3853_timer_start(0xfe);
+}
+
+
+void f3853_set_external_interrupt_in_line(device_t *device, int level)
+{
+ downcast<f3853_device*>(device)->f3853_set_external_interrupt_in_line(level);
+}
+
+void f3853_device::f3853_set_external_interrupt_in_line(int level)
+{
+ if(m_external_interrupt_line && !level && m_external_enable)
+ {
+ m_request_flipflop = TRUE;
+ }
+ m_external_interrupt_line = level;
+ f3853_set_interrupt_request_line();
+}
+
+
+void f3853_set_priority_in_line(device_t *device, int level)
+{
+ downcast<f3853_device*>(device)->f3853_set_priority_in_line(level);
+}
+
+void f3853_device::f3853_set_priority_in_line(int level)
+{
+ m_priority_line = level;
+ f3853_set_interrupt_request_line();
+}
+
+
+READ8_DEVICE_HANDLER_TRAMPOLINE(f3853, f3853_r)
+{
+ UINT8 data = 0;
+
+ switch (offset)
+ {
+ case 0:
+ data = m_high;
+ break;
+
+ case 1:
+ data = m_low;
+ break;
+
+ case 2: // Interrupt control; not readable
+ case 3: // Timer; not readable
+ break;
+ }
+
+ return data;
+}
+
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(f3853, f3853_w)
+{
+ switch(offset)
+ {
+ case 0:
+ m_high = data;
+ break;
+
+ case 1:
+ m_low = data;
+ break;
+
+ case 2: //interrupt control
+ m_external_enable = ((data & 3) == 1);
+ m_timer_enable = ((data & 3) == 3);
+ f3853_set_interrupt_request_line();
+ break;
+
+ case 3: //timer
+ m_request_flipflop = FALSE;
+ f3853_set_interrupt_request_line();
+ f3853_timer_start(data);
+ break;
+ }
+}
diff --git a/trunk/src/emu/machine/f3853.h b/trunk/src/emu/machine/f3853.h
new file mode 100644
index 00000000000..9ee50c68c13
--- /dev/null
+++ b/trunk/src/emu/machine/f3853.h
@@ -0,0 +1,129 @@
+/***************************************************************************
+
+ Fairchild F3853 SRAM interface with integrated interrupt
+ controller and timer
+
+ This chip is a timer shift register, basically the same as in the
+ F3851.
+
+****************************************************************************
+ _____ _____
+ Vgg 1 |* \_/ | 40 Vdd
+ PHI 2 | | 39 ROMC4
+ WRITE 3 | | 38 ROMC3
+ _INT REQ 4 | | 37 ROMC2
+ _PRI IN 5 | | 36 ROMC1
+ _RAM WRITE 6 | | 35 ROMC0
+ _EXT INT 7 | | 34 CPU READ
+ ADDR7 8 | | 33 REG DR
+ ADDR6 9 | | 32 ADDR15
+ ADDR5 10 | F3853 | 31 ADDR14
+ ADDR4 11 | | 30 ADDR13
+ ADDR3 12 | | 29 ADDR12
+ ADDR2 13 | | 28 ADDR11
+ ADDR1 14 | | 27 ADDR10
+ ADDR0 15 | | 26 ADDR9
+ DB0 16 | | 25 ADDR8
+ DB1 17 | | 24 DB7
+ DB2 18 | | 23 DB6
+ DB3 19 | | 22 DB5
+ Vss 20 |_____________| 21 DB4
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __F3853_H__
+#define __F3853_H__
+
+#include "emu.h"
+
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_F3853_ADD(_tag, _clock, _intrf) \
+ MCFG_DEVICE_ADD(_tag, F3853, _clock) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+
+// ======================> f3853_interface
+
+struct f3853_interface
+{
+ void (*m_interrupt_request)(device_t *device, UINT16 addr, int level);
+};
+
+
+// ======================> f3853_device
+
+class f3853_device : public device_t,
+ public f3853_interface
+{
+public:
+ // construction/destruction
+ f3853_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ UINT8 f3853_r(UINT32 offset);
+ void f3853_w(UINT32 offset, UINT8 data);
+
+ void f3853_set_external_interrupt_in_line(int level);
+ void f3853_set_priority_in_line(int level);
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_post_load() { }
+ virtual void device_clock_changed() { }
+
+ static TIMER_CALLBACK( f3853_timer_callback );
+
+private:
+
+ void f3853_set_interrupt_request_line();
+ void f3853_timer_start(UINT8 value);
+ void f3853_timer();
+
+ UINT8 m_high;
+ UINT8 m_low; // Bit 7 is set to 0 for timer interrupts, 1 for external interrupts
+ INT32 m_external_enable;
+ INT32 m_timer_enable;
+
+ INT32 m_request_flipflop;
+
+ INT32 m_priority_line; /* inverted level*/
+ INT32 m_external_interrupt_line; /* inverted level */
+
+ emu_timer *m_timer;
+
+ UINT8 m_value_to_cycle[0x100];
+};
+
+
+// device type definition
+extern const device_type F3853;
+
+
+
+/***************************************************************************
+ PROTOTYPES
+***************************************************************************/
+
+READ8_DEVICE_HANDLER( f3853_r );
+WRITE8_DEVICE_HANDLER( f3853_w );
+
+void f3853_set_external_interrupt_in_line(device_t *device, int level);
+void f3853_set_priority_in_line(device_t *device, int level);
+
+#endif /* __F3853_H__ */
diff --git a/trunk/src/emu/machine/generic.c b/trunk/src/emu/machine/generic.c
new file mode 100644
index 00000000000..b2d2f6ee15e
--- /dev/null
+++ b/trunk/src/emu/machine/generic.c
@@ -0,0 +1,769 @@
+/*********************************************************************
+
+ generic.c
+
+ Generic simple machine functions.
+
+ 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"
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void counters_load(running_machine &machine, int config_type, xml_data_node *parentnode);
+static void counters_save(running_machine &machine, int config_type, xml_data_node *parentnode);
+static void interrupt_reset(running_machine &machine);
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+struct _generic_machine_private
+{
+ /* tickets and coin counters */
+ UINT32 dispensed_tickets;
+ UINT32 coin_count[COIN_COUNTERS];
+ UINT32 coinlockedout[COIN_COUNTERS];
+ UINT32 lastcoin[COIN_COUNTERS];
+
+ /* memory card status */
+ int memcard_inserted;
+
+ /* interrupt status for up to 8 CPUs */
+ device_t * interrupt_device[8];
+ UINT8 interrupt_enable[8];
+};
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ interrupt_enabled - return true if interrupts
+ are enabled for the given CPU
+-------------------------------------------------*/
+
+INLINE int interrupt_enabled(device_t *device)
+{
+ generic_machine_private *state = device->machine().generic_machine_data;
+ for (int index = 0; index < ARRAY_LENGTH(state->interrupt_device); index++)
+ if (state->interrupt_device[index] == device)
+ return state->interrupt_enable[index];
+ return TRUE;
+}
+
+
+
+/***************************************************************************
+ INITIALIZATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ generic_machine_init - initialize globals and
+ register for save states
+-------------------------------------------------*/
+
+void generic_machine_init(running_machine &machine)
+{
+ generic_machine_private *state;
+ int counternum;
+
+ /* allocate our state */
+ machine.generic_machine_data = auto_alloc_clear(machine, generic_machine_private);
+ state = machine.generic_machine_data;
+
+ /* reset coin counters */
+ for (counternum = 0; counternum < COIN_COUNTERS; counternum++)
+ {
+ state->lastcoin[counternum] = 0;
+ state->coinlockedout[counternum] = 0;
+ }
+
+ // map devices to the interrupt state
+ memset(state->interrupt_device, 0, sizeof(state->interrupt_device));
+ device_execute_interface *exec = NULL;
+ int index = 0;
+ for (bool gotone = machine.devicelist().first(exec); gotone && index < ARRAY_LENGTH(state->interrupt_device); gotone = exec->next(exec))
+ state->interrupt_device[index++] = &exec->device();
+
+ /* register coin save state */
+ machine.save().save_item(NAME(state->coin_count));
+ machine.save().save_item(NAME(state->coinlockedout));
+ machine.save().save_item(NAME(state->lastcoin));
+
+ /* reset memory card info */
+ state->memcard_inserted = -1;
+
+ /* register a reset callback and save state for interrupt enable */
+ machine.add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(FUNC(interrupt_reset), &machine));
+ machine.save().save_item(NAME(state->interrupt_enable));
+
+ /* register for configuration */
+ config_register(machine, "counters", config_saveload_delegate(FUNC(counters_load), &machine), config_saveload_delegate(FUNC(counters_save), &machine));
+
+ /* for memory cards, request save state and an exit callback */
+ if (machine.config().m_memcard_handler != NULL)
+ {
+ state_save_register_global(machine, state->memcard_inserted);
+ machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(memcard_eject), &machine));
+ }
+}
+
+
+
+/***************************************************************************
+ TICKETS
+***************************************************************************/
+
+/*-------------------------------------------------
+ get_dispensed_tickets - return the number of
+ tickets dispensed
+-------------------------------------------------*/
+
+int get_dispensed_tickets(running_machine &machine)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ return state->dispensed_tickets;
+}
+
+
+/*-------------------------------------------------
+ increment_dispensed_tickets - increment the
+ number of dispensed tickets
+-------------------------------------------------*/
+
+void increment_dispensed_tickets(running_machine &machine, int delta)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ state->dispensed_tickets += delta;
+}
+
+
+
+/***************************************************************************
+ COIN COUNTERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ counters_load - load the state of the counters
+ and tickets
+-------------------------------------------------*/
+
+static void counters_load(running_machine &machine, int config_type, xml_data_node *parentnode)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ xml_data_node *coinnode, *ticketnode;
+
+ /* on init, reset the counters */
+ if (config_type == CONFIG_TYPE_INIT)
+ {
+ memset(state->coin_count, 0, sizeof(state->coin_count));
+ state->dispensed_tickets = 0;
+ }
+
+ /* only care about game-specific data */
+ if (config_type != CONFIG_TYPE_GAME)
+ return;
+
+ /* might not have any data */
+ if (parentnode == NULL)
+ return;
+
+ /* iterate over coins nodes */
+ for (coinnode = xml_get_sibling(parentnode->child, "coins"); coinnode; coinnode = xml_get_sibling(coinnode->next, "coins"))
+ {
+ int index = xml_get_attribute_int(coinnode, "index", -1);
+ if (index >= 0 && index < COIN_COUNTERS)
+ state->coin_count[index] = xml_get_attribute_int(coinnode, "number", 0);
+ }
+
+ /* get the single tickets node */
+ ticketnode = xml_get_sibling(parentnode->child, "tickets");
+ if (ticketnode != NULL)
+ state->dispensed_tickets = xml_get_attribute_int(ticketnode, "number", 0);
+}
+
+
+/*-------------------------------------------------
+ counters_save - save the state of the counters
+ and tickets
+-------------------------------------------------*/
+
+static void counters_save(running_machine &machine, int config_type, xml_data_node *parentnode)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ int i;
+
+ /* only care about game-specific data */
+ if (config_type != CONFIG_TYPE_GAME)
+ return;
+
+ /* iterate over coin counters */
+ for (i = 0; i < COIN_COUNTERS; i++)
+ if (state->coin_count[i] != 0)
+ {
+ xml_data_node *coinnode = xml_add_child(parentnode, "coins", NULL);
+ if (coinnode != NULL)
+ {
+ xml_set_attribute_int(coinnode, "index", i);
+ xml_set_attribute_int(coinnode, "number", state->coin_count[i]);
+ }
+ }
+
+ /* output tickets */
+ if (state->dispensed_tickets != 0)
+ {
+ xml_data_node *tickets = xml_add_child(parentnode, "tickets", NULL);
+ if (tickets != NULL)
+ xml_set_attribute_int(tickets, "number", state->dispensed_tickets);
+ }
+}
+
+
+/*-------------------------------------------------
+ coin_counter_w - sets input for coin counter
+-------------------------------------------------*/
+
+void coin_counter_w(running_machine &machine, int num, int on)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ if (num >= ARRAY_LENGTH(state->coin_count))
+ return;
+
+ /* Count it only if the data has changed from 0 to non-zero */
+ if (on && (state->lastcoin[num] == 0))
+ state->coin_count[num]++;
+ state->lastcoin[num] = on;
+}
+
+
+/*-------------------------------------------------
+ coin_counter_get_count - return the coin count
+ for a given coin
+-------------------------------------------------*/
+
+int coin_counter_get_count(running_machine &machine, int num)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ if (num >= ARRAY_LENGTH(state->coin_count))
+ return 0;
+ return state->coin_count[num];
+}
+
+
+/*-------------------------------------------------
+ coin_lockout_w - locks out one coin input
+-------------------------------------------------*/
+
+void coin_lockout_w(running_machine &machine, int num,int on)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ if (num >= ARRAY_LENGTH(state->coinlockedout))
+ return;
+ state->coinlockedout[num] = on;
+}
+
+
+/*-------------------------------------------------
+ coin_lockout_get_state - return current lockout
+ state for a particular coin
+-------------------------------------------------*/
+
+int coin_lockout_get_state(running_machine &machine, int num)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ if (num >= ARRAY_LENGTH(state->coinlockedout))
+ return FALSE;
+ return state->coinlockedout[num];
+}
+
+
+/*-------------------------------------------------
+ coin_lockout_global_w - locks out all the coin
+ inputs
+-------------------------------------------------*/
+
+void coin_lockout_global_w(running_machine &machine, int on)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ int i;
+
+ for (i = 0; i < ARRAY_LENGTH(state->coinlockedout); i++)
+ coin_lockout_w(machine, i, on);
+}
+
+
+
+/***************************************************************************
+ NVRAM MANAGEMENT
+***************************************************************************/
+
+/*-------------------------------------------------
+ nvram_filename - returns filename of system's
+ NVRAM depending of selected BIOS
+-------------------------------------------------*/
+
+static astring nvram_filename(running_machine &machine, astring &result)
+{
+ if (rom_system_bios(machine) == 0 || rom_default_bios(machine) == rom_system_bios(machine)) {
+ result.printf("%s",machine.basename());
+ } else {
+ result.printf("%s_%d",machine.basename(),rom_system_bios(machine) - 1);
+ }
+ return result;
+}
+
+/*-------------------------------------------------
+ nvram_load - load a system's NVRAM
+-------------------------------------------------*/
+
+void nvram_load(running_machine &machine)
+{
+ // only need to do something if we have an NVRAM device or an nvram_handler
+ device_nvram_interface *nvram = NULL;
+ if (!machine.devicelist().first(nvram) && machine.config().m_nvram_handler == NULL)
+ return;
+
+ // open the file; if it exists, call everyone to read from it
+ astring filename;
+ emu_file file(machine.options().nvram_directory(), OPEN_FLAG_READ);
+ if (file.open(nvram_filename(machine,filename), ".nv") == FILERR_NONE)
+ {
+ // read data from general NVRAM handler first
+ if (machine.config().m_nvram_handler != NULL)
+ (*machine.config().m_nvram_handler)(machine, &file, FALSE);
+
+ // find all devices with NVRAM handlers, and read from them next
+ for (bool gotone = (nvram != NULL); gotone; gotone = nvram->next(nvram))
+ nvram->nvram_load(file);
+ }
+
+ // otherwise, tell everyone to initialize their NVRAM areas
+ else
+ {
+ // initialize via the general NVRAM handler first
+ if (machine.config().m_nvram_handler != NULL)
+ (*machine.config().m_nvram_handler)(machine, NULL, FALSE);
+
+ // find all devices with NVRAM handlers, and read from them next
+ for (bool gotone = (nvram != NULL); gotone; gotone = nvram->next(nvram))
+ nvram->nvram_reset();
+ }
+}
+
+
+/*-------------------------------------------------
+ nvram_save - save a system's NVRAM
+-------------------------------------------------*/
+
+void nvram_save(running_machine &machine)
+{
+ // only need to do something if we have an NVRAM device or an nvram_handler
+ device_nvram_interface *nvram = NULL;
+ if (!machine.devicelist().first(nvram) && machine.config().m_nvram_handler == NULL)
+ return;
+
+ // open the file; if it exists, call everyone to read from it
+ astring filename;
+ emu_file file(machine.options().nvram_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ if (file.open(nvram_filename(machine,filename), ".nv") == FILERR_NONE)
+ {
+ // write data via general NVRAM handler first
+ if (machine.config().m_nvram_handler != NULL)
+ (*machine.config().m_nvram_handler)(machine, &file, TRUE);
+
+ // find all devices with NVRAM handlers, and tell them to write next
+ for (bool gotone = (nvram != NULL); gotone; gotone = nvram->next(nvram))
+ nvram->nvram_save(file);
+ }
+}
+
+
+
+/***************************************************************************
+ MEMORY CARD MANAGEMENT
+***************************************************************************/
+
+/*-------------------------------------------------
+ memcard_name - determine the name of a memcard
+ file
+-------------------------------------------------*/
+
+INLINE void memcard_name(int index, char *buffer)
+{
+ sprintf(buffer, "memcard.%03d", index);
+}
+
+
+/*-------------------------------------------------
+ memcard_create - create a new memory card with
+ the given index
+-------------------------------------------------*/
+
+int memcard_create(running_machine &machine, int index, int overwrite)
+{
+ char name[16];
+
+ /* create a name */
+ memcard_name(index, name);
+
+ /* if we can't overwrite, fail if the file already exists */
+ astring fname(machine.basename(), PATH_SEPARATOR, name);
+ if (!overwrite)
+ {
+ emu_file testfile(machine.options().memcard_directory(), OPEN_FLAG_READ);
+ if (testfile.open(fname) == FILERR_NONE)
+ return 1;
+ }
+
+ /* create a new file */
+ emu_file file(machine.options().memcard_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ file_error filerr = file.open(fname);
+ if (filerr != FILERR_NONE)
+ return 1;
+
+ /* initialize and then save the card */
+ if (machine.config().m_memcard_handler)
+ (*machine.config().m_memcard_handler)(machine, file, MEMCARD_CREATE);
+
+ /* close the file */
+ return 0;
+}
+
+
+/*-------------------------------------------------
+ memcard_insert - insert an existing memory card
+ with the given index
+-------------------------------------------------*/
+
+int memcard_insert(running_machine &machine, int index)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ char name[16];
+
+ /* if a card is already inserted, eject it first */
+ if (state->memcard_inserted != -1)
+ memcard_eject(machine);
+ assert(state->memcard_inserted == -1);
+
+ /* create a name */
+ memcard_name(index, name);
+
+ /* open the file; if we can't, it's an error */
+ emu_file file(machine.options().memcard_directory(), OPEN_FLAG_READ);
+ file_error filerr = file.open(machine.basename(), PATH_SEPARATOR, name);
+ if (filerr != FILERR_NONE)
+ return 1;
+
+ /* initialize and then load the card */
+ if (machine.config().m_memcard_handler)
+ (*machine.config().m_memcard_handler)(machine, file, MEMCARD_INSERT);
+
+ /* close the file */
+ state->memcard_inserted = index;
+ return 0;
+}
+
+
+/*-------------------------------------------------
+ memcard_eject - eject a memory card, saving
+ its contents along the way
+-------------------------------------------------*/
+
+void memcard_eject(running_machine &machine)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ char name[16];
+
+ /* if no card is preset, just ignore */
+ if (state->memcard_inserted == -1)
+ return;
+
+ /* create a name */
+ memcard_name(state->memcard_inserted, name);
+
+ /* open the file; if we can't, it's an error */
+ emu_file file(machine.options().memcard_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ file_error filerr = file.open(machine.basename(), PATH_SEPARATOR, name);
+ if (filerr != FILERR_NONE)
+ return;
+
+ /* initialize and then load the card */
+ if (machine.config().m_memcard_handler)
+ (*machine.config().m_memcard_handler)(machine, file, MEMCARD_EJECT);
+
+ /* close the file */
+ state->memcard_inserted = -1;
+}
+
+
+/*-------------------------------------------------
+ memcard_present - return the currently loaded
+ card index, or -1 if none
+-------------------------------------------------*/
+
+int memcard_present(running_machine &machine)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ return state->memcard_inserted;
+}
+
+
+
+/***************************************************************************
+ LED CODE
+***************************************************************************/
+
+/*-------------------------------------------------
+ set_led_status - set the state of a given LED
+-------------------------------------------------*/
+
+void set_led_status(running_machine &machine, int num, int on)
+{
+ output_set_led_value(num, on);
+}
+
+
+
+/***************************************************************************
+ INTERRUPT ENABLE AND VECTOR HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ interrupt_reset - reset the interrupt enable
+ states on a reset
+-------------------------------------------------*/
+
+static void interrupt_reset(running_machine &machine)
+{
+ generic_machine_private *state = machine.generic_machine_data;
+ int cpunum;
+
+ /* on a reset, enable all interrupts */
+ for (cpunum = 0; cpunum < ARRAY_LENGTH(state->interrupt_enable); cpunum++)
+ state->interrupt_enable[cpunum] = 1;
+}
+
+
+/*-------------------------------------------------
+ clear_all_lines - sets the state of all input
+ lines and the NMI line to clear
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( clear_all_lines )
+{
+ cpu_device *cpudevice = reinterpret_cast<cpu_device *>(ptr);
+
+ // clear NMI
+ cpudevice->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
+
+ // clear all other inputs
+ int inputcount = cpudevice->input_lines();
+ for (int line = 0; line < inputcount; line++)
+ cpudevice->set_input_line(line, CLEAR_LINE);
+}
+
+
+/*-------------------------------------------------
+ irq_pulse_clear - clear a "pulsed" IRQ line
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( irq_pulse_clear )
+{
+ device_t *device = (device_t *)ptr;
+ int irqline = param;
+ device_set_input_line(device, irqline, CLEAR_LINE);
+}
+
+
+/*-------------------------------------------------
+ generic_pulse_irq_line - "pulse" an IRQ line by
+ asserting it and then clearing it 1 cycle
+ later
+-------------------------------------------------*/
+
+void generic_pulse_irq_line(device_t *device, int irqline)
+{
+ assert(irqline != INPUT_LINE_NMI && irqline != INPUT_LINE_RESET);
+ device_set_input_line(device, irqline, ASSERT_LINE);
+
+ cpu_device *cpudevice = downcast<cpu_device *>(device);
+ attotime target_time = cpudevice->local_time() + cpudevice->cycles_to_attotime(cpudevice->min_cycles());
+ device->machine().scheduler().timer_set(target_time - device->machine().time(), FUNC(irq_pulse_clear), irqline, (void *)device);
+}
+
+
+/*-------------------------------------------------
+ generic_pulse_irq_line_and_vector - "pulse" an
+ IRQ line by asserting it and then clearing it
+ 1 cycle later, specifying a vector
+-------------------------------------------------*/
+
+void generic_pulse_irq_line_and_vector(device_t *device, int irqline, int vector)
+{
+ assert(irqline != INPUT_LINE_NMI && irqline != INPUT_LINE_RESET);
+ device_set_input_line_and_vector(device, irqline, ASSERT_LINE, vector);
+
+ cpu_device *cpudevice = downcast<cpu_device *>(device);
+ attotime target_time = cpudevice->local_time() + cpudevice->cycles_to_attotime(cpudevice->min_cycles());
+ device->machine().scheduler().timer_set(target_time - device->machine().time(), FUNC(irq_pulse_clear), irqline, (void *)device);
+}
+
+
+/*-------------------------------------------------
+ cpu_interrupt_enable - controls the enable/
+ disable value for global interrupts
+-------------------------------------------------*/
+
+void cpu_interrupt_enable(device_t *device, int enabled)
+{
+ cpu_device *cpudevice = downcast<cpu_device *>(device);
+
+ generic_machine_private *state = device->machine().generic_machine_data;
+ int index;
+ for (index = 0; index < ARRAY_LENGTH(state->interrupt_device); index++)
+ if (state->interrupt_device[index] == device)
+ break;
+ assert_always(index < ARRAY_LENGTH(state->interrupt_enable), "cpu_interrupt_enable() called for invalid CPU!");
+
+ /* set the new state */
+ if (index < ARRAY_LENGTH(state->interrupt_enable))
+ state->interrupt_enable[index] = enabled;
+
+ /* make sure there are no queued interrupts */
+ if (enabled == 0)
+ device->machine().scheduler().synchronize(FUNC(clear_all_lines), 0, (void *)cpudevice);
+}
+
+
+/*-------------------------------------------------
+ interrupt_enable_w - set the global interrupt
+ enable
+-------------------------------------------------*/
+
+WRITE8_HANDLER( interrupt_enable_w )
+{
+ cpu_interrupt_enable(&space->device(), data);
+}
+
+
+/*-------------------------------------------------
+ interrupt_enable_r - read the global interrupt
+ enable
+-------------------------------------------------*/
+
+READ8_HANDLER( interrupt_enable_r )
+{
+ return interrupt_enabled(&space->device());
+}
+
+
+
+/***************************************************************************
+ INTERRUPT GENERATION CALLBACK HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ NMI callbacks
+-------------------------------------------------*/
+
+INTERRUPT_GEN( nmi_line_pulse ) { if (interrupt_enabled(device)) device_set_input_line(device, INPUT_LINE_NMI, PULSE_LINE); }
+INTERRUPT_GEN( nmi_line_assert ) { if (interrupt_enabled(device)) device_set_input_line(device, INPUT_LINE_NMI, ASSERT_LINE); }
+
+
+/*-------------------------------------------------
+ IRQn callbacks
+-------------------------------------------------*/
+
+INTERRUPT_GEN( irq0_line_hold ) { if (interrupt_enabled(device)) device_set_input_line(device, 0, HOLD_LINE); }
+INTERRUPT_GEN( irq0_line_pulse ) { if (interrupt_enabled(device)) generic_pulse_irq_line(device, 0); }
+INTERRUPT_GEN( irq0_line_assert ) { if (interrupt_enabled(device)) device_set_input_line(device, 0, ASSERT_LINE); }
+
+INTERRUPT_GEN( irq1_line_hold ) { if (interrupt_enabled(device)) device_set_input_line(device, 1, HOLD_LINE); }
+INTERRUPT_GEN( irq1_line_pulse ) { if (interrupt_enabled(device)) generic_pulse_irq_line(device, 1); }
+INTERRUPT_GEN( irq1_line_assert ) { if (interrupt_enabled(device)) device_set_input_line(device, 1, ASSERT_LINE); }
+
+INTERRUPT_GEN( irq2_line_hold ) { if (interrupt_enabled(device)) device_set_input_line(device, 2, HOLD_LINE); }
+INTERRUPT_GEN( irq2_line_pulse ) { if (interrupt_enabled(device)) generic_pulse_irq_line(device, 2); }
+INTERRUPT_GEN( irq2_line_assert ) { if (interrupt_enabled(device)) device_set_input_line(device, 2, ASSERT_LINE); }
+
+INTERRUPT_GEN( irq3_line_hold ) { if (interrupt_enabled(device)) device_set_input_line(device, 3, HOLD_LINE); }
+INTERRUPT_GEN( irq3_line_pulse ) { if (interrupt_enabled(device)) generic_pulse_irq_line(device, 3); }
+INTERRUPT_GEN( irq3_line_assert ) { if (interrupt_enabled(device)) device_set_input_line(device, 3, ASSERT_LINE); }
+
+INTERRUPT_GEN( irq4_line_hold ) { if (interrupt_enabled(device)) device_set_input_line(device, 4, HOLD_LINE); }
+INTERRUPT_GEN( irq4_line_pulse ) { if (interrupt_enabled(device)) generic_pulse_irq_line(device, 4); }
+INTERRUPT_GEN( irq4_line_assert ) { if (interrupt_enabled(device)) device_set_input_line(device, 4, ASSERT_LINE); }
+
+INTERRUPT_GEN( irq5_line_hold ) { if (interrupt_enabled(device)) device_set_input_line(device, 5, HOLD_LINE); }
+INTERRUPT_GEN( irq5_line_pulse ) { if (interrupt_enabled(device)) generic_pulse_irq_line(device, 5); }
+INTERRUPT_GEN( irq5_line_assert ) { if (interrupt_enabled(device)) device_set_input_line(device, 5, ASSERT_LINE); }
+
+INTERRUPT_GEN( irq6_line_hold ) { if (interrupt_enabled(device)) device_set_input_line(device, 6, HOLD_LINE); }
+INTERRUPT_GEN( irq6_line_pulse ) { if (interrupt_enabled(device)) generic_pulse_irq_line(device, 6); }
+INTERRUPT_GEN( irq6_line_assert ) { if (interrupt_enabled(device)) device_set_input_line(device, 6, ASSERT_LINE); }
+
+INTERRUPT_GEN( irq7_line_hold ) { if (interrupt_enabled(device)) device_set_input_line(device, 7, HOLD_LINE); }
+INTERRUPT_GEN( irq7_line_pulse ) { if (interrupt_enabled(device)) generic_pulse_irq_line(device, 7); }
+INTERRUPT_GEN( irq7_line_assert ) { if (interrupt_enabled(device)) device_set_input_line(device, 7, ASSERT_LINE); }
+
+
+
+/***************************************************************************
+ WATCHDOG READ/WRITE HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ 8-bit reset read/write handlers
+-------------------------------------------------*/
+
+WRITE8_HANDLER( watchdog_reset_w ) { watchdog_reset(space->machine()); }
+READ8_HANDLER( watchdog_reset_r ) { watchdog_reset(space->machine()); return space->unmap(); }
+
+
+/*-------------------------------------------------
+ 16-bit reset read/write handlers
+-------------------------------------------------*/
+
+WRITE16_HANDLER( watchdog_reset16_w ) { watchdog_reset(space->machine()); }
+READ16_HANDLER( watchdog_reset16_r ) { watchdog_reset(space->machine()); return space->unmap(); }
+
+
+/*-------------------------------------------------
+ 32-bit reset read/write handlers
+-------------------------------------------------*/
+
+WRITE32_HANDLER( watchdog_reset32_w ) { watchdog_reset(space->machine()); }
+READ32_HANDLER( watchdog_reset32_r ) { watchdog_reset(space->machine()); return space->unmap(); }
+
+
+
+/***************************************************************************
+ PORT READING HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ custom_port_read - act like input_port_read
+ but it is a custom port, it is useful for
+ e.g. input ports which expect the same port
+ repeated both in the upper and lower half
+-------------------------------------------------*/
+
+CUSTOM_INPUT( custom_port_read )
+{
+ const char *tag = (const char *)param;
+ return input_port_read(field.machine(), tag);
+}
diff --git a/trunk/src/emu/machine/generic.h b/trunk/src/emu/machine/generic.h
new file mode 100644
index 00000000000..3cc006c5e5e
--- /dev/null
+++ b/trunk/src/emu/machine/generic.h
@@ -0,0 +1,177 @@
+/*********************************************************************
+
+ generic.h
+
+ Generic simple machine functions.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+#pragma once
+
+#ifndef __MACHINE_GENERIC_H__
+#define __MACHINE_GENERIC_H__
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* total # of coin counters */
+#define COIN_COUNTERS 8
+
+/* memory card actions */
+#define MEMCARD_CREATE 0
+#define MEMCARD_INSERT 1
+#define MEMCARD_EJECT 2
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+
+/* ----- initialization ----- */
+
+/* set up all the common systems */
+void generic_machine_init(running_machine &machine);
+
+
+
+/* ----- tickets ----- */
+
+/* return the number of tickets dispensed */
+int get_dispensed_tickets(running_machine &machine);
+
+/* increment the number of dispensed tickets */
+void increment_dispensed_tickets(running_machine &machine, int delta);
+
+
+
+/* ----- coin counters ----- */
+
+/* write to a particular coin counter (clocks on active high edge) */
+void coin_counter_w(running_machine &machine, int num, int on);
+
+/* return the coin count for a given coin */
+int coin_counter_get_count(running_machine &machine, int num);
+
+/* enable/disable coin lockout for a particular coin */
+void coin_lockout_w(running_machine &machine, int num, int on);
+
+/* return current lockout state for a particular coin */
+int coin_lockout_get_state(running_machine &machine, int num);
+
+/* enable/disable global coin lockout */
+void coin_lockout_global_w(running_machine &machine, int on);
+
+
+
+/* ----- NVRAM management ----- */
+
+/* load NVRAM from a file */
+void nvram_load(running_machine &machine);
+
+/* save NVRAM to a file */
+void nvram_save(running_machine &machine);
+
+
+
+/* ----- memory card management ----- */
+
+/* create a new memory card with the given index */
+int memcard_create(running_machine &machine, int index, int overwrite);
+
+/* "insert" a memory card with the given index and load its data */
+int memcard_insert(running_machine &machine, int index);
+
+/* "eject" a memory card and save its data */
+void memcard_eject(running_machine &machine);
+
+/* returns the index of the current memory card, or -1 if none */
+int memcard_present(running_machine &machine);
+
+
+
+/* ----- miscellaneous bits & pieces ----- */
+
+/* set the status of an LED */
+void set_led_status(running_machine &machine, int num, int value);
+
+
+
+/* ----- interrupt enable and vector helpers ----- */
+
+void generic_pulse_irq_line(device_t *device, int irqline);
+void generic_pulse_irq_line_and_vector(device_t *device, int irqline, int vector);
+void cpu_interrupt_enable(device_t *device, int enabled);
+READ8_HANDLER( interrupt_enable_r );
+WRITE8_HANDLER( interrupt_enable_w );
+
+
+
+/* ----- common interrupt callbacks ----- */
+
+INTERRUPT_GEN( nmi_line_pulse );
+INTERRUPT_GEN( nmi_line_assert );
+
+INTERRUPT_GEN( irq0_line_hold );
+INTERRUPT_GEN( irq0_line_pulse );
+INTERRUPT_GEN( irq0_line_assert );
+
+INTERRUPT_GEN( irq1_line_hold );
+INTERRUPT_GEN( irq1_line_pulse );
+INTERRUPT_GEN( irq1_line_assert );
+
+INTERRUPT_GEN( irq2_line_hold );
+INTERRUPT_GEN( irq2_line_pulse );
+INTERRUPT_GEN( irq2_line_assert );
+
+INTERRUPT_GEN( irq3_line_hold );
+INTERRUPT_GEN( irq3_line_pulse );
+INTERRUPT_GEN( irq3_line_assert );
+
+INTERRUPT_GEN( irq4_line_hold );
+INTERRUPT_GEN( irq4_line_pulse );
+INTERRUPT_GEN( irq4_line_assert );
+
+INTERRUPT_GEN( irq5_line_hold );
+INTERRUPT_GEN( irq5_line_pulse );
+INTERRUPT_GEN( irq5_line_assert );
+
+INTERRUPT_GEN( irq6_line_hold );
+INTERRUPT_GEN( irq6_line_pulse );
+INTERRUPT_GEN( irq6_line_assert );
+
+INTERRUPT_GEN( irq7_line_hold );
+INTERRUPT_GEN( irq7_line_pulse );
+INTERRUPT_GEN( irq7_line_assert );
+
+
+
+/* ----- generic watchdog reset handlers ----- */
+
+/* 8-bit watchdog read/write handlers */
+WRITE8_HANDLER( watchdog_reset_w );
+READ8_HANDLER( watchdog_reset_r );
+
+/* 16-bit watchdog read/write handlers */
+WRITE16_HANDLER( watchdog_reset16_w );
+READ16_HANDLER( watchdog_reset16_r );
+
+/* 32-bit watchdog read/write handlers */
+WRITE32_HANDLER( watchdog_reset32_w );
+READ32_HANDLER( watchdog_reset32_r );
+
+
+
+/* ----- generic input port helpers ----- */
+
+/* custom handler */
+CUSTOM_INPUT( custom_port_read );
+
+#endif /* __MACHINE_GENERIC_H__ */
diff --git a/trunk/src/emu/machine/i2cmem.c b/trunk/src/emu/machine/i2cmem.c
new file mode 100644
index 00000000000..0aaacf24026
--- /dev/null
+++ b/trunk/src/emu/machine/i2cmem.c
@@ -0,0 +1,566 @@
+/***************************************************************************
+
+I2C Memory
+
+Generic ram/rom/eeprom/flash on an i2c bus. Supports specifying the slave address,
+the data size & the page size for writing.
+
+inputs:
+ e0,e1,e2 lower 3 bits of the slave address
+ sda serial data
+ scl serial clock
+ wc write protect
+
+outputs:
+ sda serial data
+
+The memory address is only 8 bits, devices larger than this have multiple slave addresses.
+The top five address bits are set at manufacture time, two values are standard.
+Up to 4096 bytes can be addressed.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "machine/i2cmem.h"
+
+#define STATE_IDLE ( 0 )
+#define STATE_DEVSEL ( 1 )
+#define STATE_BYTEADDR ( 2 )
+#define STATE_DATAIN ( 3 )
+#define STATE_DATAOUT ( 4 )
+
+#define DEVSEL_RW ( 1 )
+#define DEVSEL_ADDRESS ( 0xfe )
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define VERBOSE_LEVEL ( 0 )
+
+INLINE void ATTR_PRINTF( 3, 4 ) verboselog( device_t *device, 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: I2CMEM(%s) %s", device->machine().describe_context( ), device->tag(), buf );
+ }
+}
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+const device_type I2CMEM = &device_creator<i2cmem_device>;
+
+static ADDRESS_MAP_START( i2cmem_map8, AS_PROGRAM, 8 )
+ AM_RANGE(0x0000, 0x0fff) AM_RAM
+ADDRESS_MAP_END
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// i2cmem_device - constructor
+//-------------------------------------------------
+
+i2cmem_device::i2cmem_device( const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock )
+ : device_t(mconfig, I2CMEM, "I2CMEM", tag, owner, clock),
+ device_memory_interface(mconfig, *this),
+ device_nvram_interface(mconfig, *this),
+ m_scl( 0 ),
+ m_sdaw( 0 ),
+ m_e0( 0 ),
+ m_e1( 0 ),
+ m_e2( 0 ),
+ m_wc( 0 ),
+ m_sdar( 1 ),
+ m_state( STATE_IDLE )
+{
+ m_address_bits = 0;
+
+ int i = m_data_size - 1;
+ while( i > 0 )
+ {
+ m_address_bits++;
+ i >>= 1;
+ }
+}
+
+
+//-------------------------------------------------
+// static_set_interface - set the device
+// configuration
+//-------------------------------------------------
+
+void i2cmem_device::static_set_interface(device_t &device, const i2cmem_interface &interface)
+{
+ i2cmem_device &i2cmem = downcast<i2cmem_device &>(device);
+ static_cast<i2cmem_interface &>(i2cmem) = interface;
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void i2cmem_device::device_config_complete()
+{
+ m_space_config = address_space_config( "i2cmem", ENDIANNESS_BIG, 8, m_address_bits, 0, *ADDRESS_MAP_NAME( i2cmem_map8 ) );
+}
+
+
+//-------------------------------------------------
+// device_validity_check - perform validity checks
+// on this device
+//-------------------------------------------------
+
+bool i2cmem_device::device_validity_check( emu_options &options, const game_driver &driver ) const
+{
+ bool error = false;
+ return error;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void i2cmem_device::device_start()
+{
+ if( m_page_size > 0 )
+ {
+ m_page = auto_alloc_array( machine(), UINT8, m_page_size );
+ }
+
+ save_item( NAME(m_scl) );
+ save_item( NAME(m_sdaw) );
+ save_item( NAME(m_e0) );
+ save_item( NAME(m_e1) );
+ save_item( NAME(m_e2) );
+ save_item( NAME(m_wc) );
+ save_item( NAME(m_sdar) );
+ save_item( NAME(m_state) );
+ save_item( NAME(m_bits) );
+ save_item( NAME(m_shift) );
+ save_item( NAME(m_devsel) );
+ save_item( NAME(m_byteaddr) );
+ save_pointer( NAME(m_page), m_page_size );
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void i2cmem_device::device_reset()
+{
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return a description of
+// any address spaces owned by this device
+//-------------------------------------------------
+
+const address_space_config *i2cmem_device::memory_space_config( address_spacenum spacenum ) const
+{
+ return ( spacenum == 0 ) ? &m_space_config : NULL;
+}
+
+
+//-------------------------------------------------
+// nvram_default - called to initialize NVRAM to
+// its default state
+//-------------------------------------------------
+
+void i2cmem_device::nvram_default()
+{
+ int i2cmem_bytes = m_data_size;
+
+ UINT16 default_value = 0xff;
+ for( offs_t offs = 0; offs < i2cmem_bytes; offs++ )
+ {
+ m_addrspace[ 0 ]->write_byte( offs, default_value );
+ }
+
+ /* populate from a memory region if present */
+ if( m_region != NULL )
+ {
+ if( m_region->bytes() != i2cmem_bytes )
+ {
+ fatalerror( "i2cmem region '%s' wrong size (expected size = 0x%X)", tag(), i2cmem_bytes );
+ }
+
+ if( m_region->width() != 1 )
+ {
+ fatalerror( "i2cmem region '%s' needs to be an 8-bit region", tag() );
+ }
+
+ for( offs_t offs = 0; offs < i2cmem_bytes; offs++ )
+ {
+ m_addrspace[ 0 ]->write_byte( offs, m_region->u8( offs ) );
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// nvram_read - called to read NVRAM from the
+// .nv file
+//-------------------------------------------------
+
+void i2cmem_device::nvram_read( emu_file &file )
+{
+ int i2cmem_bytes = m_data_size;
+ UINT8 *buffer = auto_alloc_array( machine(), UINT8, i2cmem_bytes );
+
+ file.read( buffer, i2cmem_bytes );
+
+ for( offs_t offs = 0; offs < i2cmem_bytes; offs++ )
+ {
+ m_addrspace[ 0 ]->write_byte( offs, buffer[ offs ] );
+ }
+
+ auto_free( machine(), buffer );
+}
+
+//-------------------------------------------------
+// nvram_write - called to write NVRAM to the
+// .nv file
+//-------------------------------------------------
+
+void i2cmem_device::nvram_write( emu_file &file )
+{
+ int i2cmem_bytes = m_data_size;
+ UINT8 *buffer = auto_alloc_array( machine(), UINT8, i2cmem_bytes );
+
+ for( offs_t offs = 0; offs < i2cmem_bytes; offs++ )
+ {
+ buffer[ offs ] = m_addrspace[ 0 ]->read_byte( offs );
+ }
+
+ file.write( buffer, i2cmem_bytes );
+
+ auto_free( machine(), buffer );
+}
+
+
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+WRITE_LINE_DEVICE_HANDLER( i2cmem_e0_write )
+{
+ downcast<i2cmem_device *>( device )->set_e0_line( state );
+}
+
+void i2cmem_device::set_e0_line( int state )
+{
+ state &= 1;
+ if( m_e0 != state )
+ {
+ verboselog( this, 2, "set e0 %d\n", state );
+ m_e0 = state;
+ }
+}
+
+
+WRITE_LINE_DEVICE_HANDLER( i2cmem_e1_write )
+{
+ downcast<i2cmem_device *>( device )->set_e1_line( state );
+}
+
+void i2cmem_device::set_e1_line( int state )
+{
+ state &= 1;
+ if( m_e1 != state )
+ {
+ verboselog( this, 2, "set e1 %d\n", state );
+ m_e1 = state;
+ }
+}
+
+
+WRITE_LINE_DEVICE_HANDLER( i2cmem_e2_write )
+{
+ downcast<i2cmem_device *>( device )->set_e2_line( state );
+}
+
+void i2cmem_device::set_e2_line( int state )
+{
+ state &= 1;
+ if( m_e2 != state )
+ {
+ verboselog( this, 2, "set e2 %d\n", state );
+ m_e2 = state;
+ }
+}
+
+
+WRITE_LINE_DEVICE_HANDLER( i2cmem_sda_write )
+{
+ downcast<i2cmem_device *>( device )->set_sda_line( state );
+}
+
+void i2cmem_device::set_sda_line( int state )
+{
+ state &= 1;
+ if( m_sdaw != state )
+ {
+ verboselog( this, 2, "set sda %d\n", state );
+ m_sdaw = state;
+
+ if( m_scl )
+ {
+ if( m_sdaw )
+ {
+ verboselog( this, 1, "stop\n" );
+ m_state = STATE_IDLE;
+ }
+ else
+ {
+ verboselog( this, 2, "start\n" );
+ m_state = STATE_DEVSEL;
+ m_bits = 0;
+ }
+
+ m_sdar = 1;
+ }
+ }
+}
+
+WRITE_LINE_DEVICE_HANDLER( i2cmem_scl_write )
+{
+ downcast<i2cmem_device *>( device )->set_scl_line( state );
+}
+
+void i2cmem_device::set_scl_line( int state )
+{
+ if( m_scl != state )
+ {
+ m_scl = state;
+ verboselog( this, 2, "set_scl_line %d\n", m_scl );
+
+ switch( m_state )
+ {
+ case STATE_DEVSEL:
+ case STATE_BYTEADDR:
+ case STATE_DATAIN:
+ if( m_bits < 8 )
+ {
+ if( m_scl )
+ {
+ m_shift = ( ( m_shift << 1 ) | m_sdaw ) & 0xff;
+ m_bits++;
+ }
+ }
+ else
+ {
+ if( m_scl )
+ {
+ switch( m_state )
+ {
+ case STATE_DEVSEL:
+ m_devsel = m_shift;
+
+ if( !select_device() )
+ {
+ verboselog( this, 1, "devsel %02x: not this device\n", m_devsel );
+ m_state = STATE_IDLE;
+ }
+ else if( ( m_devsel & DEVSEL_RW ) == 0 )
+ {
+ verboselog( this, 1, "devsel %02x: write\n", m_devsel );
+ m_state = STATE_BYTEADDR;
+ }
+ else
+ {
+ verboselog( this, 1, "devsel %02x: read\n", m_devsel );
+ m_state = STATE_DATAOUT;
+ }
+ break;
+
+ case STATE_BYTEADDR:
+ m_byteaddr = m_shift;
+ m_page_offset = 0;
+
+ verboselog( this, 1, "byteaddr %02x\n", m_byteaddr );
+
+ m_state = STATE_DATAIN;
+ break;
+
+ case STATE_DATAIN:
+ if( m_wc )
+ {
+ verboselog( this, 0, "write not enabled\n" );
+ m_state = STATE_IDLE;
+ }
+ else if( m_page_size > 0 )
+ {
+ m_page[ m_page_offset ] = m_shift;
+ verboselog( this, 1, "page[ %04x ] <- %02x\n", m_page_offset, m_page[ m_page_offset ] );
+
+ m_page_offset++;
+ if( m_page_offset == m_page_size )
+ {
+ int offset = data_offset() & ~( m_page_size - 1 );
+
+ verboselog( this, 1, "data[ %04x to %04x ] = page\n", offset, offset + m_page_size - 1 );
+
+ for( int i = 0; i < m_page_size; i++ )
+ {
+ m_addrspace[ 0 ]->write_byte( offset + i, m_page[ i ] );
+ }
+
+ m_page_offset = 0;
+ }
+ }
+ else
+ {
+ int offset = data_offset();
+
+ verboselog( this, 1, "data[ %04x ] <- %02x\n", offset, m_shift );
+ m_addrspace[ 0 ]->write_byte( offset, m_shift );
+
+ m_byteaddr++;
+ }
+ break;
+ }
+
+ m_bits++;
+ }
+ else
+ {
+ if( m_bits == 8 )
+ {
+ m_sdar = 0;
+ }
+ else
+ {
+ m_bits = 0;
+ m_sdar = 1;
+ }
+ }
+ }
+ break;
+
+ case STATE_DATAOUT:
+ if( m_bits < 8 )
+ {
+ if( m_scl )
+ {
+ if( m_bits == 0 )
+ {
+ int offset = data_offset();
+
+ m_shift = m_addrspace[ 0 ]->read_byte( offset );
+ verboselog( this, 1, "data[ %04x ] -> %02x\n", offset, m_shift );
+ m_byteaddr++;
+ }
+
+ m_sdar = ( m_shift >> 7 ) & 1;
+
+ m_shift = ( m_shift << 1 ) & 0xff;
+ m_bits++;
+ }
+ }
+ else
+ {
+ if( m_scl )
+ {
+ if( m_sdaw )
+ {
+ verboselog( this, 1, "sleep\n" );
+ m_state = STATE_IDLE;
+ m_sdar = 0;
+ }
+
+ m_bits++;
+ }
+ else
+ {
+ if( m_bits == 8 )
+ {
+ m_sdar = 1;
+ }
+ else
+ {
+ m_bits = 0;
+ }
+ }
+ }
+ break;
+ }
+ }
+}
+
+
+WRITE_LINE_DEVICE_HANDLER( i2cmem_wc_write )
+{
+ downcast<i2cmem_device *>( device )->set_wc_line( state );
+}
+
+void i2cmem_device::set_wc_line( int state )
+{
+ state &= 1;
+ if( m_wc != state )
+ {
+ verboselog( this, 2, "set wc %d\n", state );
+ m_wc = state;
+ }
+}
+
+
+READ_LINE_DEVICE_HANDLER( i2cmem_sda_read )
+{
+ return downcast<i2cmem_device *>( device )->read_sda_line();
+}
+
+int i2cmem_device::read_sda_line()
+{
+ int res = m_sdar & 1;
+
+ verboselog( this, 2, "read sda %d\n", res );
+
+ return res;
+}
+
+
+//**************************************************************************
+// INTERNAL HELPERS
+//**************************************************************************
+
+int i2cmem_device::address_mask()
+{
+ return (m_data_size - 1);
+}
+
+int i2cmem_device::select_device()
+{
+ int device = ( m_slave_address & 0xf0 ) | ( m_e2 << 3 ) | ( m_e1 << 2 ) | ( m_e0 << 1 );
+ int mask = DEVSEL_ADDRESS & ~( address_mask() >> 7 );
+
+ if( ( m_devsel & mask ) == ( device & mask ) )
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+int i2cmem_device::data_offset()
+{
+ return ( ( ( m_devsel << 7 ) & 0xff00 ) | ( m_byteaddr & 0xff ) ) & address_mask();
+}
diff --git a/trunk/src/emu/machine/i2cmem.h b/trunk/src/emu/machine/i2cmem.h
new file mode 100644
index 00000000000..f0c6aa14deb
--- /dev/null
+++ b/trunk/src/emu/machine/i2cmem.h
@@ -0,0 +1,128 @@
+/***************************************************************************
+
+ i2cmem.h
+
+ I2C Memory
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __I2CMEM_H__
+#define __I2CMEM_H__
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define I2CMEM_SLAVE_ADDRESS ( 0xa0 )
+#define I2CMEM_SLAVE_ADDRESS_ALT ( 0xb0 )
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_I2CMEM_ADD( _tag, _interface ) \
+ MCFG_DEVICE_ADD( _tag, I2CMEM, 0 ) \
+ i2cmem_device::static_set_interface(*device, _interface);
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> i2cmem_interface
+
+struct i2cmem_interface
+{
+ int m_slave_address;
+ int m_page_size;
+ int m_data_size;
+};
+
+
+// ======================> i2cmem_device
+
+class i2cmem_device :
+ public device_t,
+ public device_memory_interface,
+ public device_nvram_interface,
+ public i2cmem_interface
+{
+public:
+ // construction/destruction
+ i2cmem_device( const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock );
+
+ // inline configuration
+ static void static_set_interface(device_t &device, const i2cmem_interface &interface);
+
+ // I/O operations
+ void set_e0_line( int state );
+ void set_e1_line( int state );
+ void set_e2_line( int state );
+ void set_sda_line( int state );
+ void set_scl_line( int state );
+ void set_wc_line( int state );
+ int read_sda_line();
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual bool device_validity_check( emu_options &options, const game_driver &driver ) const;
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config( address_spacenum spacenum = AS_0 ) const;
+
+ // device_nvram_interface overrides
+ virtual void nvram_default();
+ virtual void nvram_read( emu_file &file );
+ virtual void nvram_write( emu_file &file );
+
+ // internal helpers
+ int address_mask();
+ int select_device();
+ int data_offset();
+
+ // device-specific configuration
+ address_space_config m_space_config;
+ int m_address_bits;
+
+ // internal state
+ int m_scl;
+ int m_sdaw;
+ int m_e0;
+ int m_e1;
+ int m_e2;
+ int m_wc;
+ int m_sdar;
+ int m_state;
+ int m_bits;
+ int m_shift;
+ int m_devsel;
+ int m_byteaddr;
+ UINT8 *m_page;
+ int m_page_offset;
+};
+
+
+// device type definition
+extern const device_type I2CMEM;
+
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+WRITE_LINE_DEVICE_HANDLER( i2cmem_e0_write );
+WRITE_LINE_DEVICE_HANDLER( i2cmem_e1_write );
+WRITE_LINE_DEVICE_HANDLER( i2cmem_e2_write );
+WRITE_LINE_DEVICE_HANDLER( i2cmem_sda_write );
+WRITE_LINE_DEVICE_HANDLER( i2cmem_scl_write );
+WRITE_LINE_DEVICE_HANDLER( i2cmem_wc_write );
+READ_LINE_DEVICE_HANDLER( i2cmem_sda_read );
+
+#endif /* __I2CMEM_H__ */
diff --git a/trunk/src/emu/machine/i8155.c b/trunk/src/emu/machine/i8155.c
new file mode 100644
index 00000000000..cc69c83b4ab
--- /dev/null
+++ b/trunk/src/emu/machine/i8155.c
@@ -0,0 +1,614 @@
+/**********************************************************************
+
+ Intel 8155 - 2048-Bit Static MOS RAM with I/O Ports and Timer emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+/*
+
+ TODO:
+
+ - strobed mode
+
+*/
+
+#include "emu.h"
+#include "i8155.h"
+
+
+// device type definition
+const device_type I8155 = &device_creator<i8155_device>;
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 1
+
+enum
+{
+ REGISTER_COMMAND = 0,
+ REGISTER_STATUS = 0,
+ REGISTER_PORT_A,
+ REGISTER_PORT_B,
+ REGISTER_PORT_C,
+ REGISTER_TIMER_LOW,
+ REGISTER_TIMER_HIGH
+};
+
+enum
+{
+ PORT_A = 0,
+ PORT_B,
+ PORT_C,
+ PORT_COUNT
+};
+
+enum
+{
+ PORT_MODE_INPUT = 0,
+ PORT_MODE_OUTPUT,
+ PORT_MODE_STROBED_PORT_A, // not supported
+ PORT_MODE_STROBED // not supported
+};
+
+enum
+{
+ MEMORY = 0,
+ IO
+};
+
+#define COMMAND_PA 0x01
+#define COMMAND_PB 0x02
+#define COMMAND_PC_MASK 0x0c
+#define COMMAND_PC_ALT_1 0x00
+#define COMMAND_PC_ALT_2 0x0c
+#define COMMAND_PC_ALT_3 0x04 // not supported
+#define COMMAND_PC_ALT_4 0x08 // not supported
+#define COMMAND_IEA 0x10 // not supported
+#define COMMAND_IEB 0x20 // not supported
+#define COMMAND_TM_MASK 0xc0
+#define COMMAND_TM_NOP 0x00
+#define COMMAND_TM_STOP 0x40
+#define COMMAND_TM_STOP_AFTER_TC 0x80
+#define COMMAND_TM_START 0xc0
+
+#define STATUS_INTR_A 0x01 // not supported
+#define STATUS_A_BF 0x02 // not supported
+#define STATUS_INTE_A 0x04 // not supported
+#define STATUS_INTR_B 0x08 // not supported
+#define STATUS_B_BF 0x10 // not supported
+#define STATUS_INTE_B 0x20 // not supported
+#define STATUS_TIMER 0x40
+
+#define TIMER_MODE_MASK 0xc0
+#define TIMER_MODE_LOW 0x00
+#define TIMER_MODE_SQUARE_WAVE 0x40
+#define TIMER_MODE_SINGLE_PULSE 0x80
+#define TIMER_MODE_AUTOMATIC_RELOAD 0xc0
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// default address map
+static ADDRESS_MAP_START( i8155, AS_0, 8 )
+ AM_RANGE(0x00, 0xff) AM_RAM
+ADDRESS_MAP_END
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+inline UINT8 i8155_device::get_timer_mode()
+{
+ return (m_count_length >> 8) & TIMER_MODE_MASK;
+}
+
+inline void i8155_device::timer_output()
+{
+ m_out_to_func(m_to);
+
+ if (LOG) logerror("8155 '%s' Timer Output: %u\n", tag(), m_to);
+}
+
+inline void i8155_device::pulse_timer_output()
+{
+ m_to = 0; timer_output();
+ m_to = 1; timer_output();
+}
+
+inline int i8155_device::get_port_mode(int port)
+{
+ int mode = -1;
+
+ switch (port)
+ {
+ case PORT_A:
+ mode = (m_command & COMMAND_PA) ? PORT_MODE_OUTPUT : PORT_MODE_INPUT;
+ break;
+
+ case PORT_B:
+ mode = (m_command & COMMAND_PB) ? PORT_MODE_OUTPUT : PORT_MODE_INPUT;
+ break;
+
+ case PORT_C:
+ switch (m_command & COMMAND_PC_MASK)
+ {
+ case COMMAND_PC_ALT_1: mode = PORT_MODE_INPUT; break;
+ case COMMAND_PC_ALT_2: mode = PORT_MODE_OUTPUT; break;
+ case COMMAND_PC_ALT_3: mode = PORT_MODE_STROBED_PORT_A; break;
+ case COMMAND_PC_ALT_4: mode = PORT_MODE_STROBED; break;
+ }
+ break;
+ }
+
+ return mode;
+}
+
+inline UINT8 i8155_device::read_port(int port)
+{
+ UINT8 data = 0;
+
+ switch (port)
+ {
+ case PORT_A:
+ case PORT_B:
+ switch (get_port_mode(port))
+ {
+ case PORT_MODE_INPUT:
+ data = m_in_port_func[port](0);
+ break;
+
+ case PORT_MODE_OUTPUT:
+ data = m_output[port];
+ break;
+ }
+ break;
+
+ case PORT_C:
+ switch (get_port_mode(PORT_C))
+ {
+ case PORT_MODE_INPUT:
+ data = m_in_port_func[port](0) & 0x3f;
+ break;
+
+ case PORT_MODE_OUTPUT:
+ data = m_output[port] & 0x3f;
+ break;
+
+ default:
+ logerror("8155 '%s' Unsupported Port C mode!\n", tag());
+ }
+ break;
+ }
+
+ return data;
+}
+
+inline void i8155_device::write_port(int port, UINT8 data)
+{
+ switch (get_port_mode(port))
+ {
+ case PORT_MODE_OUTPUT:
+ m_output[port] = data;
+ m_out_port_func[port](0, m_output[port]);
+ break;
+ }
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// i8155_device - constructor
+//-------------------------------------------------
+
+i8155_device::i8155_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, I8155, "Intel 8155", tag, owner, clock),
+ device_memory_interface(mconfig, *this),
+ m_space_config("ram", ENDIANNESS_LITTLE, 8, 8, 0, NULL, *ADDRESS_MAP_NAME(i8155))
+{
+
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void i8155_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const i8155_interface *intf = reinterpret_cast<const i8155_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<i8155_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&in_pa_cb, 0, sizeof(in_pa_cb));
+ memset(&out_pa_cb, 0, sizeof(out_pa_cb));
+ memset(&in_pb_cb, 0, sizeof(in_pb_cb));
+ memset(&out_pb_cb, 0, sizeof(out_pb_cb));
+ memset(&in_pc_cb, 0, sizeof(in_pc_cb));
+ memset(&out_pc_cb, 0, sizeof(out_pc_cb));
+ memset(&out_to_cb, 0, sizeof(out_to_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void i8155_device::device_start()
+{
+ // resolve callbacks
+ m_in_port_func[0].resolve(in_pa_cb, *this);
+ m_in_port_func[1].resolve(in_pb_cb, *this);
+ m_in_port_func[2].resolve(in_pc_cb, *this);
+ m_out_port_func[0].resolve(out_pa_cb, *this);
+ m_out_port_func[1].resolve(out_pb_cb, *this);
+ m_out_port_func[2].resolve(out_pc_cb, *this);
+ m_out_to_func.resolve(out_to_cb, *this);
+
+ // allocate timers
+ m_timer = timer_alloc();
+
+ // register for state saving
+ save_item(NAME(m_io_m));
+ save_item(NAME(m_ad));
+ save_item(NAME(m_command));
+ save_item(NAME(m_status));
+ save_item(NAME(m_output));
+ save_item(NAME(m_count_length));
+ save_item(NAME(m_counter));
+ save_item(NAME(m_to));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void i8155_device::device_reset()
+{
+ // clear output registers
+ m_output[PORT_A] = 0;
+ m_output[PORT_B] = 0;
+ m_output[PORT_C] = 0;
+
+ // set ports to input mode
+ register_w(REGISTER_COMMAND, m_command & ~(COMMAND_PA | COMMAND_PB | COMMAND_PC_MASK));
+
+ // clear timer flag
+ m_status &= ~STATUS_TIMER;
+
+ // stop counting
+ m_timer->enable(0);
+
+ // clear timer output
+ m_to = 1;
+ timer_output();
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void i8155_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ // count down
+ m_counter--;
+
+ if (get_timer_mode() == TIMER_MODE_LOW)
+ {
+ // pulse on every count
+ pulse_timer_output();
+ }
+
+ if (m_counter == 0)
+ {
+ if (LOG) logerror("8155 '%s' Timer Count Reached\n", tag());
+
+ switch (m_command & COMMAND_TM_MASK)
+ {
+ case COMMAND_TM_STOP_AFTER_TC:
+ // stop timer
+ m_timer->enable(0);
+
+ if (LOG) logerror("8155 '%s' Timer Stopped\n", tag());
+ break;
+ }
+
+ switch (get_timer_mode())
+ {
+ case TIMER_MODE_SQUARE_WAVE:
+ // toggle timer output
+ m_to = !m_to;
+ timer_output();
+ break;
+
+ case TIMER_MODE_SINGLE_PULSE:
+ // single pulse upon TC being reached
+ pulse_timer_output();
+
+ // clear timer mode setting
+ m_command &= ~COMMAND_TM_MASK;
+ break;
+
+ case TIMER_MODE_AUTOMATIC_RELOAD:
+ // automatic reload, i.e. single pulse every time TC is reached
+ pulse_timer_output();
+ break;
+ }
+
+ // set timer flag
+ m_status |= STATUS_TIMER;
+
+ // reload timer counter
+ m_counter = m_count_length & 0x3fff;
+ }
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return a description of
+// any address spaces owned by this device
+//-------------------------------------------------
+
+const address_space_config *i8155_device::memory_space_config(address_spacenum spacenum) const
+{
+ return (spacenum == AS_0) ? &m_space_config : NULL;
+}
+
+
+//-------------------------------------------------
+// io_r - register read
+//-------------------------------------------------
+
+READ8_MEMBER( i8155_device::io_r )
+{
+ UINT8 data = 0;
+
+ switch (offset & 0x03)
+ {
+ case REGISTER_STATUS:
+ data = m_status;
+
+ // clear timer flag
+ m_status &= ~STATUS_TIMER;
+ break;
+
+ case REGISTER_PORT_A:
+ data = read_port(PORT_A);
+ break;
+
+ case REGISTER_PORT_B:
+ data = read_port(PORT_B);
+ break;
+
+ case REGISTER_PORT_C:
+ data = read_port(PORT_C);
+ break;
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// register_w - register write
+//-------------------------------------------------
+
+void i8155_device::register_w(int offset, UINT8 data)
+{
+ switch (offset & 0x07)
+ {
+ case REGISTER_COMMAND:
+ m_command = data;
+
+ if (LOG) logerror("8155 '%s' Port A Mode: %s\n", tag(), (data & COMMAND_PA) ? "output" : "input");
+ if (LOG) logerror("8155 '%s' Port B Mode: %s\n", tag(), (data & COMMAND_PB) ? "output" : "input");
+
+ if (LOG) logerror("8155 '%s' Port A Interrupt: %s\n", tag(), (data & COMMAND_IEA) ? "enabled" : "disabled");
+ if (LOG) logerror("8155 '%s' Port B Interrupt: %s\n", tag(), (data & COMMAND_IEB) ? "enabled" : "disabled");
+
+ switch (data & COMMAND_PC_MASK)
+ {
+ case COMMAND_PC_ALT_1:
+ if (LOG) logerror("8155 '%s' Port C Mode: Alt 1\n", tag());
+ break;
+
+ case COMMAND_PC_ALT_2:
+ if (LOG) logerror("8155 '%s' Port C Mode: Alt 2\n", tag());
+ break;
+
+ case COMMAND_PC_ALT_3:
+ if (LOG) logerror("8155 '%s' Port C Mode: Alt 3\n", tag());
+ break;
+
+ case COMMAND_PC_ALT_4:
+ if (LOG) logerror("8155 '%s' Port C Mode: Alt 4\n", tag());
+ break;
+ }
+
+ switch (data & COMMAND_TM_MASK)
+ {
+ case COMMAND_TM_NOP:
+ // do not affect counter operation
+ break;
+
+ case COMMAND_TM_STOP:
+ // NOP if timer has not started, stop counting if the timer is running
+ if (LOG) logerror("8155 '%s' Timer Command: Stop\n", tag());
+ m_timer->enable(0);
+ break;
+
+ case COMMAND_TM_STOP_AFTER_TC:
+ // stop immediately after present TC is reached (NOP if timer has not started)
+ if (LOG) logerror("8155 '%s' Timer Command: Stop after TC\n", tag());
+ break;
+
+ case COMMAND_TM_START:
+ if (LOG) logerror("8155 '%s' Timer Command: Start\n", tag());
+
+ if (m_timer->enabled())
+ {
+ // if timer is running, start the new mode and CNT length immediately after present TC is reached
+ }
+ else
+ {
+ // load mode and CNT length and start immediately after loading (if timer is not running)
+ m_counter = m_count_length;
+ m_timer->adjust(attotime::zero, 0, attotime::from_hz(clock()));
+ }
+ break;
+ }
+ break;
+
+ case REGISTER_PORT_A:
+ write_port(PORT_A, data);
+ break;
+
+ case REGISTER_PORT_B:
+ write_port(PORT_B, data);
+ break;
+
+ case REGISTER_PORT_C:
+ write_port(PORT_C, data);
+ break;
+
+ case REGISTER_TIMER_LOW:
+ m_count_length = (m_count_length & 0xff00) | data;
+ if (LOG) logerror("8155 '%s' Count Length Low: %04x\n", tag(), m_count_length);
+ break;
+
+ case REGISTER_TIMER_HIGH:
+ m_count_length = (data << 8) | (m_count_length & 0xff);
+ if (LOG) logerror("8155 '%s' Count Length High: %04x\n", tag(), m_count_length);
+
+ switch (data & TIMER_MODE_MASK)
+ {
+ case TIMER_MODE_LOW:
+ // puts out LOW during second half of count
+ if (LOG) logerror("8155 '%s' Timer Mode: LOW\n", tag());
+ break;
+
+ case TIMER_MODE_SQUARE_WAVE:
+ // square wave, i.e. the period of the square wave equals the count length programmed with automatic reload at terminal count
+ if (LOG) logerror("8155 '%s' Timer Mode: Square wave\n", tag());
+ break;
+
+ case TIMER_MODE_SINGLE_PULSE:
+ // single pulse upon TC being reached
+ if (LOG) logerror("8155 '%s' Timer Mode: Single pulse\n", tag());
+ break;
+
+ case TIMER_MODE_AUTOMATIC_RELOAD:
+ // automatic reload, i.e. single pulse every time TC is reached
+ if (LOG) logerror("8155 '%s' Timer Mode: Automatic reload\n", tag());
+ break;
+ }
+ break;
+ }
+}
+
+//-------------------------------------------------
+// io_w - register write
+//-------------------------------------------------
+
+WRITE8_MEMBER( i8155_device::io_w )
+{
+ register_w(offset, data);
+}
+
+
+//-------------------------------------------------
+// memory_r - internal RAM read
+//-------------------------------------------------
+
+READ8_MEMBER( i8155_device::memory_r )
+{
+ return this->space()->read_byte(offset);
+}
+
+
+//-------------------------------------------------
+// memory_w - internal RAM write
+//-------------------------------------------------
+
+WRITE8_MEMBER( i8155_device::memory_w )
+{
+ this->space()->write_byte(offset, data);
+}
+
+
+//-------------------------------------------------
+// ale_w - address latch write
+//-------------------------------------------------
+
+WRITE8_MEMBER( i8155_device::ale_w )
+{
+ // I/O / memory select
+ m_io_m = BIT(offset, 0);
+
+ // address
+ m_ad = data;
+}
+
+
+//-------------------------------------------------
+// read - memory or I/O read
+//-------------------------------------------------
+
+READ8_MEMBER( i8155_device::read )
+{
+ UINT8 data = 0;
+
+ switch (m_io_m)
+ {
+ case MEMORY:
+ data = memory_r(space, m_ad);
+ break;
+
+ case IO:
+ data = io_r(space, m_ad);
+ break;
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// write - memory or I/O write
+//-------------------------------------------------
+
+WRITE8_MEMBER( i8155_device::write )
+{
+ switch (m_io_m)
+ {
+ case MEMORY:
+ memory_w(space, m_ad, data);
+ break;
+
+ case IO:
+ io_w(space, m_ad, data);
+ break;
+ }
+}
diff --git a/trunk/src/emu/machine/i8155.h b/trunk/src/emu/machine/i8155.h
new file mode 100644
index 00000000000..56929d9caf0
--- /dev/null
+++ b/trunk/src/emu/machine/i8155.h
@@ -0,0 +1,154 @@
+/**********************************************************************
+
+ Intel 8155 - 2048-Bit Static MOS RAM with I/O Ports and Timer emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ PC3 1 |* \_/ | 40 Vcc
+ PC4 2 | | 39 PC2
+ TIMER IN 3 | | 38 PC1
+ RESET 4 | | 37 PC0
+ PC5 5 | | 36 PB7
+ _TIMER OUT 6 | | 35 PB6
+ IO/_M 7 | | 34 PB5
+ CE or _CE 8 | | 33 PB4
+ _RD 9 | | 32 PB3
+ _WR 10 | 8155 | 31 PB2
+ ALE 11 | 8156 | 30 PB1
+ AD0 12 | | 29 PB0
+ AD1 13 | | 28 PA7
+ AD2 14 | | 27 PA6
+ AD3 15 | | 26 PA5
+ AD4 16 | | 25 PA4
+ AD5 17 | | 24 PA3
+ AD6 18 | | 23 PA2
+ AD7 19 | | 22 PA1
+ Vss 20 |_____________| 21 PA0
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __I8155__
+#define __I8155__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_I8155_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD((_tag), I8155, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define I8155_INTERFACE(name) \
+ const i8155_interface (name) =
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> i8155_interface
+
+struct i8155_interface
+{
+ devcb_read8 in_pa_cb;
+ devcb_write8 out_pa_cb;
+
+ devcb_read8 in_pb_cb;
+ devcb_write8 out_pb_cb;
+
+ devcb_read8 in_pc_cb;
+ devcb_write8 out_pc_cb;
+
+ // this gets called for each change of the TIMER OUT pin (pin 6)
+ devcb_write_line out_to_cb;
+};
+
+
+
+// ======================> i8155_device
+
+class i8155_device : public device_t,
+ public device_memory_interface,
+ public i8155_interface
+{
+public:
+ // construction/destruction
+ i8155_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_READ8_MEMBER( io_r );
+ DECLARE_WRITE8_MEMBER( io_w );
+
+ DECLARE_READ8_MEMBER( memory_r );
+ DECLARE_WRITE8_MEMBER( memory_w );
+
+ DECLARE_WRITE8_MEMBER( ale_w );
+ DECLARE_READ8_MEMBER( read );
+ DECLARE_WRITE8_MEMBER( write );
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
+
+ inline UINT8 get_timer_mode();
+ inline void timer_output();
+ inline void pulse_timer_output();
+ inline int get_port_mode(int port);
+ inline UINT8 read_port(int port);
+ inline void write_port(int port, UINT8 data);
+
+ void register_w(int offset, UINT8 data);
+
+private:
+ devcb_resolved_read8 m_in_port_func[3];
+ devcb_resolved_write8 m_out_port_func[3];
+ devcb_resolved_write_line m_out_to_func;
+
+ // CPU interface
+ int m_io_m; // I/O or memory select
+ UINT8 m_ad; // address
+
+ // registers
+ UINT8 m_command; // command register
+ UINT8 m_status; // status register
+ UINT8 m_output[3]; // output latches
+
+ // counter
+ UINT16 m_count_length; // count length register
+ UINT16 m_counter; // counter register
+ int m_to; // timer output
+
+ // timers
+ emu_timer *m_timer; // counter timer
+
+ const address_space_config m_space_config;
+};
+
+
+// device type definition
+extern const device_type I8155;
+
+
+
+#endif
diff --git a/trunk/src/emu/machine/i8212.c b/trunk/src/emu/machine/i8212.c
new file mode 100644
index 00000000000..aff8d4bca8b
--- /dev/null
+++ b/trunk/src/emu/machine/i8212.c
@@ -0,0 +1,165 @@
+/**********************************************************************
+
+ Intel 8212 8-Bit Input/Output Port emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "machine/devhelpr.h"
+#include "i8212.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type I8212 = &device_creator<i8212_device>;
+
+//-------------------------------------------------
+// i8212_device - constructor
+//-------------------------------------------------
+
+i8212_device::i8212_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, I8212, "Intel 8212", tag, owner, clock),
+ m_md(I8212_MODE_INPUT),
+ m_stb(0)
+{
+
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void i8212_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const i8212_interface *intf = reinterpret_cast<const i8212_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<i8212_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_out_int_cb, 0, sizeof(m_out_int_cb));
+ memset(&m_in_di_cb, 0, sizeof(m_in_di_cb));
+ memset(&m_out_do_cb, 0, sizeof(m_out_do_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void i8212_device::device_start()
+{
+ // resolve callbacks
+ m_out_int_func.resolve(m_out_int_cb, *this);
+ m_in_di_func.resolve(m_in_di_cb, *this);
+ m_out_do_func.resolve(m_out_do_cb, *this);
+
+ // register for state saving
+ save_item(NAME(m_md));
+ save_item(NAME(m_stb));
+ save_item(NAME(m_data));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void i8212_device::device_reset()
+{
+ m_data = 0;
+
+ if (m_md == I8212_MODE_OUTPUT)
+ {
+ // output data
+ m_out_do_func(0, m_data);
+ }
+}
+
+
+//-------------------------------------------------
+// data_r - data latch read
+//-------------------------------------------------
+
+READ8_MEMBER( i8212_device::data_r )
+{
+ // clear interrupt line
+ m_out_int_func(CLEAR_LINE);
+
+ if (LOG) logerror("I8212 '%s' INT: %u\n", tag(), CLEAR_LINE);
+
+ return m_data;
+}
+
+
+//-------------------------------------------------
+// data_w - data latch write
+//-------------------------------------------------
+
+WRITE8_MEMBER( i8212_device::data_w )
+{
+ // latch data
+ m_data = data;
+
+ // output data
+ m_out_do_func(0, m_data);
+}
+
+
+//-------------------------------------------------
+// md_w - mode write
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( i8212_device::md_w )
+{
+ if (LOG) logerror("I8212 '%s' Mode: %s\n", tag(), state ? "output" : "input");
+
+ m_md = state;
+}
+
+
+//-------------------------------------------------
+// stb_w - data strobe write
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( i8212_device::stb_w )
+{
+ if (LOG) logerror("I8212 '%s' STB: %u\n", tag(), state);
+
+ if (m_md == I8212_MODE_INPUT)
+ {
+ if (m_stb && !state)
+ {
+ // input data
+ m_data = m_in_di_func(0);
+
+ // assert interrupt line
+ m_out_int_func(ASSERT_LINE);
+
+ if (LOG) logerror("I8212 '%s' INT: %u\n", tag(), ASSERT_LINE);
+ }
+ }
+
+ m_stb = state;
+}
diff --git a/trunk/src/emu/machine/i8212.h b/trunk/src/emu/machine/i8212.h
new file mode 100644
index 00000000000..3ed32cbbfe9
--- /dev/null
+++ b/trunk/src/emu/machine/i8212.h
@@ -0,0 +1,111 @@
+/**********************************************************************
+
+ Intel 8212 8-Bit Input/Output Port emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ _DS1 1 |* \_/ | 24 Vcc
+ MD 2 | | 23 _INT
+ DI1 3 | | 22 DI8
+ DO1 4 | | 21 DO8
+ DI2 5 | | 20 DI7
+ DO2 6 | 8212 | 19 DO7
+ DI3 7 | | 18 DI6
+ DO3 8 | | 17 DO6
+ DI4 9 | | 16 DI5
+ DO4 10 | | 15 DO5
+ STB 11 | | 14 _CLR
+ GND 12 |_____________| 13 DS2
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __I8212__
+#define __I8212__
+
+#include "emu.h"
+
+
+
+///*************************************************************************
+// MACROS / CONSTANTS
+///*************************************************************************
+
+enum
+{
+ I8212_MODE_INPUT = 0,
+ I8212_MODE_OUTPUT
+};
+
+
+
+///*************************************************************************
+// INTERFACE CONFIGURATION MACROS
+///*************************************************************************
+
+#define MCFG_I8212_ADD(_tag, _config) \
+ MCFG_DEVICE_ADD((_tag), I8212, 0) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define I8212_INTERFACE(name) \
+ const i8212_interface (name) =
+
+
+
+///*************************************************************************
+// TYPE DEFINITIONS
+///*************************************************************************
+
+// ======================> i8212_interface
+
+struct i8212_interface
+{
+ devcb_write_line m_out_int_cb;
+
+ devcb_read8 m_in_di_cb;
+ devcb_write8 m_out_do_cb;
+};
+
+
+
+// ======================> i8212_device
+
+class i8212_device : public device_t, public i8212_interface
+{
+public:
+ // construction/destruction
+ i8212_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_READ8_MEMBER( data_r );
+ DECLARE_WRITE8_MEMBER( data_w );
+
+ DECLARE_WRITE_LINE_MEMBER( md_w );
+ DECLARE_WRITE_LINE_MEMBER( stb_w );
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+
+private:
+ devcb_resolved_write_line m_out_int_func;
+ devcb_resolved_read8 m_in_di_func;
+ devcb_resolved_write8 m_out_do_func;
+
+ int m_md; // mode
+ int m_stb; // strobe
+ UINT8 m_data; // data latch
+};
+
+
+// device type definition
+extern const device_type I8212;
+
+
+
+#endif
diff --git a/trunk/src/emu/machine/i8214.c b/trunk/src/emu/machine/i8214.c
new file mode 100644
index 00000000000..75ce421f94f
--- /dev/null
+++ b/trunk/src/emu/machine/i8214.c
@@ -0,0 +1,225 @@
+/**********************************************************************
+
+ Intel 8214 Priority Interrupt Controller emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "i8214.h"
+#include "machine/devhelpr.h"
+
+
+
+// device type definition
+const device_type I8214 = &device_creator<i8214_device>;
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// trigger_interrupt -
+//-------------------------------------------------
+
+inline void i8214_device::trigger_interrupt(int level)
+{
+ if (LOG) logerror("I8214 '%s' Interrupt Level %u\n", tag(), level);
+
+ m_a = level;
+
+ // disable interrupts
+ m_int_dis = 1;
+
+ // disable next level group
+ m_out_enlg_func(0);
+
+ // toggle interrupt line
+ m_out_int_func(ASSERT_LINE);
+ m_out_int_func(CLEAR_LINE);
+}
+
+
+//-------------------------------------------------
+// check_interrupt -
+//-------------------------------------------------
+
+inline void i8214_device::check_interrupt()
+{
+ int level;
+
+ if (m_int_dis || !m_etlg) return;
+
+ for (level = 7; level >= 0; level--)
+ {
+ if (!BIT(m_r, 7 - level))
+ {
+ if (m_sgs)
+ {
+ if (level > m_b)
+ {
+ trigger_interrupt(level);
+ }
+ }
+ else
+ {
+ trigger_interrupt(level);
+ }
+ }
+ }
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// i8214_device - constructor
+//-------------------------------------------------
+
+i8214_device::i8214_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, I8214, "I8214", tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void i8214_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const i8214_interface *intf = reinterpret_cast<const i8214_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<i8214_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_out_int_cb, 0, sizeof(m_out_int_cb));
+ memset(&m_out_enlg_cb, 0, sizeof(m_out_enlg_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void i8214_device::device_start()
+{
+ // resolve callbacks
+ m_out_int_func.resolve(m_out_int_cb, *this);
+ m_out_enlg_func.resolve(m_out_enlg_cb, *this);
+
+ // register for state saving
+ save_item(NAME(m_inte));
+ save_item(NAME(m_int_dis));
+ save_item(NAME(m_a));
+ save_item(NAME(m_b));
+ save_item(NAME(m_r));
+ save_item(NAME(m_sgs));
+ save_item(NAME(m_etlg));
+}
+
+
+//-------------------------------------------------
+// a_r -
+//-------------------------------------------------
+
+UINT8 i8214_device::a_r()
+{
+ UINT8 a = m_a & 0x07;
+
+ if (LOG) logerror("I8214 '%s' A: %01x\n", tag(), a);
+
+ return a;
+}
+
+
+//-------------------------------------------------
+// b_w -
+//-------------------------------------------------
+
+void i8214_device::b_w(UINT8 data)
+{
+ m_b = data & 0x07;
+
+ if (LOG) logerror("I8214 '%s' B: %01x\n", tag(), m_b);
+
+ // enable interrupts
+ m_int_dis = 0;
+
+ // enable next level group
+ m_out_enlg_func(1);
+
+ check_interrupt();
+}
+
+
+//-------------------------------------------------
+// r_w -
+//-------------------------------------------------
+
+void i8214_device::r_w(UINT8 data)
+{
+ if (LOG) logerror("I8214 '%s' R: %02x\n", tag(), data);
+
+ m_r = data;
+
+ check_interrupt();
+}
+
+
+//-------------------------------------------------
+// sgs_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( i8214_device::sgs_w )
+{
+ if (LOG) logerror("I8214 '%s' SGS: %u\n", tag(), state);
+
+ m_sgs = state;
+
+ check_interrupt();
+}
+
+
+//-------------------------------------------------
+// etlg_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( i8214_device::etlg_w )
+{
+ if (LOG) logerror("I8214 '%s' ETLG: %u\n", tag(), state);
+
+ m_etlg = state;
+}
+
+
+//-------------------------------------------------
+// inte_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( i8214_device::inte_w )
+{
+ if (LOG) logerror("I8214 '%s' INTE: %u\n", tag(), state);
+
+ m_inte = state;
+}
diff --git a/trunk/src/emu/machine/i8214.h b/trunk/src/emu/machine/i8214.h
new file mode 100644
index 00000000000..29c528c7997
--- /dev/null
+++ b/trunk/src/emu/machine/i8214.h
@@ -0,0 +1,104 @@
+/**********************************************************************
+
+ Intel 8214 Priority Interrupt Controller emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ _B0 1 |* \_/ | 24 Vcc
+ _B1 2 | | 23 _ECS
+ _B2 3 | | 22 _R7
+ _SGS 4 | | 21 _R6
+ _INT 5 | | 20 _R5
+ _CLK 6 | 8214 | 19 _R4
+ INTE 7 | | 18 _R3
+ _A0 8 | | 17 _R2
+ _A1 9 | | 16 _R1
+ _A2 10 | | 15 _R0
+ _ELR 11 | | 14 ENLG
+ GND 12 |_____________| 13 ETLG
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __I8214__
+#define __I8214__
+
+#include "emu.h"
+
+
+
+///*************************************************************************
+// INTERFACE CONFIGURATION MACROS
+///*************************************************************************
+
+#define MCFG_I8214_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD(_tag, I8214, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+
+#define I8214_INTERFACE(name) \
+ const i8214_interface (name) =
+
+
+
+///*************************************************************************
+// TYPE DEFINITIONS
+///*************************************************************************
+
+// ======================> i8214_interface
+
+struct i8214_interface
+{
+ devcb_write_line m_out_int_cb;
+ devcb_write_line m_out_enlg_cb;
+};
+
+
+// ======================> i8214_device
+
+class i8214_device : public device_t, public i8214_interface
+{
+public:
+ // construction/destruction
+ i8214_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_WRITE_LINE_MEMBER( sgs_w );
+ DECLARE_WRITE_LINE_MEMBER( etlg_w );
+ DECLARE_WRITE_LINE_MEMBER( inte_w );
+
+ UINT8 a_r();
+ void b_w(UINT8 data);
+ void r_w(UINT8 data);
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+
+private:
+ inline void trigger_interrupt(int level);
+ inline void check_interrupt();
+
+ devcb_resolved_write_line m_out_int_func;
+ devcb_resolved_write_line m_out_enlg_func;
+
+ int m_inte; // interrupt enable
+ int m_int_dis; // interrupt disable flip-flop
+ int m_a; // request level
+ int m_b; // current status register
+ UINT8 m_r; // interrupt request latch
+ int m_sgs; // status group select
+ int m_etlg; // enable this level group
+};
+
+
+// device type definition
+extern const device_type I8214;
+
+
+
+#endif
diff --git a/trunk/src/emu/machine/i8243.c b/trunk/src/emu/machine/i8243.c
new file mode 100644
index 00000000000..cf1355585eb
--- /dev/null
+++ b/trunk/src/emu/machine/i8243.c
@@ -0,0 +1,168 @@
+/***************************************************************************
+
+ i8243.c
+
+ Intel 8243 Port Expander
+
+ Copyright Aaron Giles
+
+***************************************************************************/
+
+#include "emu.h"
+#include "i8243.h"
+#include "devhelpr.h"
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type I8243 = &device_creator<i8243_device>;
+
+//-------------------------------------------------
+// i8243_device - constructor
+//-------------------------------------------------
+
+i8243_device::i8243_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, I8243, "I8243", tag, owner, clock)
+{
+
+}
+
+
+//-------------------------------------------------
+// static_set_read_handler - configuration helper
+// to set the read handler
+//-------------------------------------------------
+
+void i8243_device::static_set_read_handler(device_t &device, read8_device_func callback)
+{
+ i8243_device &i8243 = downcast<i8243_device &>(device);
+ if(callback != NULL)
+ {
+ i8243.m_readhandler_cb.type = DEVCB_TYPE_DEVICE;
+ i8243.m_readhandler_cb.index = DEVCB_DEVICE_SELF;
+ i8243.m_readhandler_cb.readdevice = callback;
+ }
+ else
+ {
+ i8243.m_readhandler_cb.type = DEVCB_TYPE_NULL;
+ }
+}
+
+
+//-------------------------------------------------
+// static_set_write_handler - configuration helper
+// to set the write handler
+//-------------------------------------------------
+
+void i8243_device::static_set_write_handler(device_t &device, write8_device_func callback)
+{
+ i8243_device &i8243 = downcast<i8243_device &>(device);
+ if(callback != NULL)
+ {
+ i8243.m_writehandler_cb.type = DEVCB_TYPE_DEVICE;
+ i8243.m_writehandler_cb.index = DEVCB_DEVICE_SELF;
+ i8243.m_writehandler_cb.writedevice = callback;
+ }
+ else
+ {
+ i8243.m_writehandler_cb.type = DEVCB_TYPE_NULL;
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void i8243_device::device_start()
+{
+ m_readhandler.resolve(m_readhandler_cb, *this);
+ m_writehandler.resolve(m_writehandler_cb, *this);
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void i8243_device::device_reset()
+{
+ m_p2 = 0x0f;
+ m_p2out = 0x0f;
+ m_prog = 1;
+}
+
+
+/*-------------------------------------------------
+ i8243_p2_r - handle a read from port 2
+-------------------------------------------------*/
+
+READ8_DEVICE_HANDLER_TRAMPOLINE(i8243, i8243_p2_r)
+{
+ return m_p2out;
+}
+
+
+/*-------------------------------------------------
+ i8243_p2_r - handle a write to port 2
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(i8243, i8243_p2_w)
+{
+ m_p2 = data & 0x0f;
+}
+
+
+/*-------------------------------------------------
+ i8243_prog_w - handle a change in the PROG
+ line state
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(i8243, i8243_prog_w)
+{
+ /* only care about low bit */
+ data &= 1;
+
+ /* on high->low transition state, latch opcode/port */
+ if(m_prog && !data)
+ {
+ m_opcode = m_p2;
+
+ /* if this is a read opcode, copy result to p2out */
+ if((m_opcode >> 2) == MCS48_EXPANDER_OP_READ)
+ {
+ if (m_readhandler.isnull())
+ {
+ m_p[m_opcode & 3] = m_readhandler(m_opcode & 3);
+ }
+ m_p2out = m_p[m_opcode & 3] & 0x0f;
+ }
+ }
+
+ /* on low->high transition state, act on opcode */
+ else if(!m_prog && data)
+ {
+ switch(m_opcode >> 2)
+ {
+ case MCS48_EXPANDER_OP_WRITE:
+ m_p[m_opcode & 3] = m_p2 & 0x0f;
+ m_writehandler(m_opcode & 3, m_p[m_opcode & 3]);
+ break;
+
+ case MCS48_EXPANDER_OP_OR:
+ m_p[m_opcode & 3] |= m_p2 & 0x0f;
+ m_writehandler(m_opcode & 3, m_p[m_opcode & 3]);
+ break;
+
+ case MCS48_EXPANDER_OP_AND:
+ m_p[m_opcode & 3] &= m_p2 & 0x0f;
+ m_writehandler(m_opcode & 3, m_p[m_opcode & 3]);
+ break;
+ }
+ }
+
+ /* remember the state */
+ m_prog = data;
+}
diff --git a/trunk/src/emu/machine/i8243.h b/trunk/src/emu/machine/i8243.h
new file mode 100644
index 00000000000..325a1bdf5ba
--- /dev/null
+++ b/trunk/src/emu/machine/i8243.h
@@ -0,0 +1,97 @@
+/***************************************************************************
+
+ i8243.h
+
+ Intel 8243 Port Expander
+
+ Copyright Aaron Giles
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __I8243_H__
+#define __I8243_H__
+
+#include "emu.h"
+#include "cpu/mcs48/mcs48.h"
+
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_I8243_ADD(_tag, _read, _write) \
+ MCFG_DEVICE_ADD(_tag, I8243, 0) \
+ MCFG_I8243_READHANDLER(_read) \
+ MCFG_I8243_WRITEHANDLER(_write) \
+
+#define MCFG_I8243_READHANDLER(_read) \
+ i8243_device::static_set_read_handler(*device, _read); \
+
+#define MCFG_I8243_WRITEHANDLER(_write) \
+ i8243_device::static_set_write_handler(*device, _write); \
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+
+// ======================> i8243_device
+
+class i8243_device : public device_t
+{
+public:
+ // construction/destruction
+ i8243_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // inline configuration helpers
+ static void static_set_read_handler(device_t &device, read8_device_func callback);
+ static void static_set_write_handler(device_t &device, write8_device_func callback);
+
+
+ UINT8 i8243_p2_r(UINT32 offset);
+ void i8243_p2_w(UINT32 offset, UINT8 data);
+
+ void i8243_prog_w(UINT32 offset, UINT8 data);
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_post_load() { }
+ virtual void device_clock_changed() { }
+
+private:
+
+ UINT8 m_p[4]; /* 4 ports' worth of data */
+ UINT8 m_p2out; /* port 2 bits that will be returned */
+ UINT8 m_p2; /* most recent port 2 value */
+ UINT8 m_opcode; /* latched opcode */
+ UINT8 m_prog; /* previous PROG state */
+
+ devcb_read8 m_readhandler_cb;
+ devcb_write8 m_writehandler_cb;
+
+ devcb_resolved_read8 m_readhandler;
+ devcb_resolved_write8 m_writehandler;
+};
+
+
+// device type definition
+extern const device_type I8243;
+
+
+
+/***************************************************************************
+ PROTOTYPES
+***************************************************************************/
+
+READ8_DEVICE_HANDLER( i8243_p2_r );
+WRITE8_DEVICE_HANDLER( i8243_p2_w );
+
+WRITE8_DEVICE_HANDLER( i8243_prog_w );
+
+
+#endif /* __I8243_H__ */
diff --git a/trunk/src/emu/machine/i8255.c b/trunk/src/emu/machine/i8255.c
new file mode 100644
index 00000000000..b2543a5a231
--- /dev/null
+++ b/trunk/src/emu/machine/i8255.c
@@ -0,0 +1,1031 @@
+/**********************************************************************
+
+ Intel 8255(A) Programmable Peripheral Interface emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "i8255.h"
+#include "machine/devhelpr.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+
+enum
+{
+ PORT_A = 0,
+ PORT_B,
+ PORT_C,
+ CONTROL
+};
+
+
+enum
+{
+ GROUP_A = 0,
+ GROUP_B
+};
+
+
+enum
+{
+ MODE_0 = 0,
+ MODE_1,
+ MODE_2
+};
+
+
+enum
+{
+ MODE_OUTPUT = 0,
+ MODE_INPUT,
+};
+
+
+#define CONTROL_PORT_C_LOWER_INPUT 0x01
+#define CONTROL_PORT_B_INPUT 0x02
+#define CONTROL_GROUP_B_MODE_1 0x04
+#define CONTROL_PORT_C_UPPER_INPUT 0x08
+#define CONTROL_PORT_A_INPUT 0x10
+#define CONTROL_GROUP_A_MODE_MASK 0x60
+#define CONTROL_MODE_SET 0x80
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type I8255 = &device_creator<i8255_device>;
+const device_type I8255A = &device_creator<i8255_device>;
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// check_interrupt -
+//-------------------------------------------------
+
+inline void i8255_device::check_interrupt(int port)
+{
+ switch (group_mode(port))
+ {
+ case MODE_1:
+ switch (port_mode(port))
+ {
+ case MODE_INPUT:
+ set_intr(port, (m_inte[port] && m_ibf[port]));
+ break;
+
+ case MODE_OUTPUT:
+ set_intr(port, (m_inte[port] && m_obf[port]));
+ break;
+ }
+ break;
+
+ case MODE_2:
+ set_intr(port, ((m_inte1 && m_obf[port]) || (m_inte2 && m_ibf[port])));
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// set_ibf -
+//-------------------------------------------------
+
+inline void i8255_device::set_ibf(int port, int state)
+{
+ if (LOG) logerror("I8255 '%s' Port %c IBF: %u\n", tag(), 'A' + port, state);
+
+ m_ibf[port] = state;
+
+ check_interrupt(port);
+}
+
+
+//-------------------------------------------------
+// set_obf -
+//-------------------------------------------------
+
+inline void i8255_device::set_obf(int port, int state)
+{
+ if (LOG) logerror("I8255 '%s' Port %c OBF: %u\n", tag(), 'A' + port, state);
+
+ m_obf[port] = state;
+
+ check_interrupt(port);
+}
+
+
+//-------------------------------------------------
+// set_inte -
+//-------------------------------------------------
+
+inline void i8255_device::set_inte(int port, int state)
+{
+ if (LOG) logerror("I8255 '%s' Port %c INTE: %u\n", tag(), 'A' + port, state);
+
+ m_inte[port] = state;
+
+ check_interrupt(port);
+}
+
+
+//-------------------------------------------------
+// set_inte1 -
+//-------------------------------------------------
+
+inline void i8255_device::set_inte1(int state)
+{
+ if (LOG) logerror("I8255 '%s' Port A INTE1: %u\n", tag(), state);
+
+ m_inte1 = state;
+
+ check_interrupt(PORT_A);
+}
+
+
+//-------------------------------------------------
+// set_inte2 -
+//-------------------------------------------------
+
+inline void i8255_device::set_inte2(int state)
+{
+ if (LOG) logerror("I8255 '%s' Port A INTE2: %u\n", tag(), state);
+
+ m_inte2 = state;
+
+ check_interrupt(PORT_A);
+}
+
+
+//-------------------------------------------------
+// set_intr -
+//-------------------------------------------------
+
+inline void i8255_device::set_intr(int port, int state)
+{
+ if (LOG) logerror("I8255 '%s' Port %c INTR: %u\n", tag(), 'A' + port, state);
+
+ m_intr[port] = state;
+
+ output_pc();
+}
+
+
+//-------------------------------------------------
+// group_mode -
+//-------------------------------------------------
+
+inline int i8255_device::group_mode(int group)
+{
+ int mode = 0;
+
+ switch (group)
+ {
+ case GROUP_A:
+ switch ((m_control & CONTROL_GROUP_A_MODE_MASK) >> 5)
+ {
+ case 0: mode = MODE_0; break;
+ case 1: mode = MODE_1; break;
+ case 2: case 3: mode = MODE_2; break;
+ }
+ break;
+
+ case GROUP_B:
+ mode = m_control & CONTROL_GROUP_B_MODE_1 ? MODE_1 : MODE_0;
+ break;
+ }
+
+ return mode;
+}
+
+
+//-------------------------------------------------
+// port_mode -
+//-------------------------------------------------
+
+inline int i8255_device::port_mode(int port)
+{
+ int mode = 0;
+
+ switch (port)
+ {
+ case PORT_A: mode = m_control & CONTROL_PORT_A_INPUT ? MODE_INPUT : MODE_OUTPUT; break;
+ case PORT_B: mode = m_control & CONTROL_PORT_B_INPUT ? MODE_INPUT : MODE_OUTPUT; break;
+ }
+
+ return mode;
+}
+
+
+//-------------------------------------------------
+// port_c_lower_mode -
+//-------------------------------------------------
+
+inline int i8255_device::port_c_lower_mode()
+{
+ return m_control & CONTROL_PORT_C_LOWER_INPUT ? MODE_INPUT : MODE_OUTPUT;
+}
+
+
+//-------------------------------------------------
+// port_c_upper_mode -
+//-------------------------------------------------
+
+inline int i8255_device::port_c_upper_mode()
+{
+ return m_control & CONTROL_PORT_C_UPPER_INPUT ? MODE_INPUT : MODE_OUTPUT;
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// i8255_device - constructor
+//-------------------------------------------------
+
+i8255_device::i8255_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, I8255, "I8255", tag, owner, clock)
+{
+ m_intr[PORT_A] = m_intr[PORT_B] = 0;
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void i8255_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const i8255_interface *intf = reinterpret_cast<const i8255_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<i8255_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_in_pa_cb, 0, sizeof(m_in_pa_cb));
+ memset(&m_out_pa_cb, 0, sizeof(m_out_pa_cb));
+ memset(&m_in_pb_cb, 0, sizeof(m_in_pb_cb));
+ memset(&m_out_pb_cb, 0, sizeof(m_out_pb_cb));
+ memset(&m_in_pc_cb, 0, sizeof(m_in_pc_cb));
+ memset(&m_out_pc_cb, 0, sizeof(m_out_pc_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void i8255_device::device_start()
+{
+ // resolve callbacks
+ m_in_port_func[PORT_A].resolve(m_in_pa_cb, *this);
+ m_out_port_func[PORT_A].resolve(m_out_pa_cb, *this);
+ m_in_port_func[PORT_B].resolve(m_in_pb_cb, *this);
+ m_out_port_func[PORT_B].resolve(m_out_pb_cb, *this);
+ m_in_port_func[PORT_C].resolve(m_in_pc_cb, *this);
+ m_out_port_func[PORT_C].resolve(m_out_pc_cb, *this);
+
+ // register for state saving
+ save_item(NAME(m_control));
+ save_item(NAME(m_output));
+ save_item(NAME(m_input));
+ save_item(NAME(m_ibf));
+ save_item(NAME(m_obf));
+ save_item(NAME(m_inte));
+ save_item(NAME(m_inte1));
+ save_item(NAME(m_inte2));
+ save_item(NAME(m_intr));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void i8255_device::device_reset()
+{
+ set_mode(0x9b);
+}
+
+
+//-------------------------------------------------
+// read_mode0 -
+//-------------------------------------------------
+
+UINT8 i8255_device::read_mode0(int port)
+{
+ UINT8 data = 0;
+
+ if (port_mode(port) == MODE_OUTPUT)
+ {
+ // read data from output latch
+ data = m_output[port];
+ }
+ else
+ {
+ // read data from port
+ data = m_in_port_func[port](0);
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// read_mode1 -
+//-------------------------------------------------
+
+UINT8 i8255_device::read_mode1(int port)
+{
+ UINT8 data = 0;
+
+ if (port_mode(port) == MODE_OUTPUT)
+ {
+ // read data from output latch
+ data = m_output[port];
+ }
+ else
+ {
+ // read data from input latch
+ data = m_input[port];
+
+ // clear input buffer full flag
+ set_ibf(port, 0);
+
+ // clear interrupt
+ set_intr(port, 0);
+
+ // clear input latch
+ m_input[port] = 0;
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// read_mode2 -
+//-------------------------------------------------
+
+UINT8 i8255_device::read_mode2()
+{
+ UINT8 data = 0;
+
+ // read data from input latch
+ data = m_input[PORT_A];
+
+ // clear input buffer full flag
+ set_ibf(PORT_A, 0);
+
+ // clear interrupt
+ set_intr(PORT_A, 0);
+
+ // clear input latch
+ m_input[PORT_A] = 0;
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// read_pc -
+//-------------------------------------------------
+
+UINT8 i8255_device::read_pc()
+{
+ UINT8 data = 0;
+ UINT8 mask = 0;
+
+ // PC upper
+ switch (group_mode(GROUP_A))
+ {
+ case MODE_0:
+ if (port_c_upper_mode() == MODE_OUTPUT)
+ {
+ // read data from output latch
+ data |= m_output[PORT_C] & 0xf0;
+ }
+ else
+ {
+ // read data from port
+ mask |= 0xf0;
+ }
+ break;
+
+ case MODE_1:
+ data |= m_intr[PORT_A] ? 0x08 : 0x00;
+
+ if (port_mode(PORT_A) == MODE_OUTPUT)
+ {
+ data |= m_obf[PORT_A] ? 0x80 : 0x00;
+ data |= m_inte[PORT_A] ? 0x40 : 0x00;
+ mask |= 0x30;
+ }
+ else
+ {
+ data |= m_ibf[PORT_A] ? 0x20 : 0x00;
+ data |= m_inte[PORT_A] ? 0x10 : 0x00;
+ mask |= 0xc0;
+ }
+ break;
+
+ case MODE_2:
+ data |= m_intr[PORT_A] ? 0x08 : 0x00;
+ data |= m_inte2 ? 0x10 : 0x00;
+ data |= m_ibf[PORT_A] ? 0x20 : 0x00;
+ data |= m_inte1 ? 0x40 : 0x00;
+ data |= m_obf[PORT_A] ? 0x80 : 0x00;
+ break;
+ }
+
+ // PC lower
+ switch (group_mode(GROUP_B))
+ {
+ case MODE_0:
+ if (port_c_lower_mode() == MODE_OUTPUT)
+ {
+ // read data from output latch
+ data |= m_output[PORT_C] & 0x0f;
+ }
+ else
+ {
+ // read data from port
+ mask |= 0x0f;
+ }
+ break;
+
+ case MODE_1:
+ data |= m_inte[PORT_B] ? 0x04 : 0x00;
+ data |= m_intr[PORT_B] ? 0x01 : 0x00;
+
+ if (port_mode(PORT_B) == MODE_OUTPUT)
+ {
+ data |= m_obf[PORT_B] ? 0x02 : 0x00;
+ }
+ else
+ {
+ data |= m_ibf[PORT_B] ? 0x02 : 0x00;
+ }
+ }
+
+ if (mask)
+ {
+ // read data from port
+ data |= m_in_port_func[PORT_C](0) & mask;
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// write_mode0 -
+//-------------------------------------------------
+
+void i8255_device::write_mode0(int port, UINT8 data)
+{
+ if (port_mode(port) == MODE_OUTPUT)
+ {
+ // latch output data
+ m_output[port] = data;
+
+ // write data to port
+ m_out_port_func[port](0, data);
+ }
+}
+
+
+//-------------------------------------------------
+// write_mode1 -
+//-------------------------------------------------
+
+void i8255_device::write_mode1(int port, UINT8 data)
+{
+ if (port_mode(port) == MODE_OUTPUT)
+ {
+ // latch output data
+ m_output[port] = data;
+
+ // write data to port
+ m_out_port_func[port](0, data);
+
+ // set output buffer full flag
+ set_obf(port, 0);
+
+ // clear interrupt
+ set_intr(port, 0);
+ }
+}
+
+
+//-------------------------------------------------
+// write_mode2 -
+//-------------------------------------------------
+
+void i8255_device::write_mode2(UINT8 data)
+{
+ // latch output data
+ m_output[PORT_A] = data;
+
+ // write data to port
+ m_out_port_func[PORT_A](0, data);
+
+ // set output buffer full flag
+ set_obf(PORT_A, 0);
+
+ // clear interrupt
+ set_intr(PORT_A, 0);
+}
+
+
+//-------------------------------------------------
+// write_pc -
+//-------------------------------------------------
+
+void i8255_device::write_pc(UINT8 data)
+{
+ int changed = 0;
+
+ if (group_mode(GROUP_A) == MODE_0)
+ {
+ // PC upper
+ if (port_c_upper_mode() == MODE_OUTPUT)
+ {
+ m_output[PORT_C] = (data & 0xf0) | (m_output[PORT_C] & 0x0f);
+ changed = 1;
+ }
+
+ // PC lower
+ if (port_c_lower_mode() == MODE_OUTPUT)
+ {
+ m_output[PORT_C] = (m_output[PORT_C] & 0xf0) | (data & 0x0f);
+ changed = 1;
+ }
+ }
+
+ if (changed)
+ {
+ output_pc();
+ }
+}
+
+
+//-------------------------------------------------
+// output_pc -
+//-------------------------------------------------
+
+void i8255_device::output_pc()
+{
+ UINT8 data = 0;
+ UINT8 mask = 0;
+
+ // PC upper
+ switch (group_mode(GROUP_A))
+ {
+ case MODE_0:
+ if (port_c_upper_mode() == MODE_OUTPUT)
+ {
+ mask |= 0xf0;
+ }
+ else
+ {
+ // TTL inputs float high
+ data |= 0xf0;
+ }
+ break;
+
+ case MODE_1:
+ data |= m_intr[PORT_A] ? 0x08 : 0x00;
+
+ if (port_mode(PORT_A) == MODE_OUTPUT)
+ {
+ data |= m_obf[PORT_A] ? 0x80 : 0x00;
+ mask |= 0x30;
+ }
+ else
+ {
+ data |= m_ibf[PORT_A] ? 0x20 : 0x00;
+ mask |= 0xc0;
+ }
+ break;
+
+ case MODE_2:
+ data |= m_intr[PORT_A] ? 0x08 : 0x00;
+ data |= m_ibf[PORT_A] ? 0x20 : 0x00;
+ data |= m_obf[PORT_A] ? 0x80 : 0x00;
+ break;
+ }
+
+ // PC lower
+ switch (group_mode(GROUP_B))
+ {
+ case MODE_0:
+ if (port_c_lower_mode() == MODE_OUTPUT)
+ {
+ mask |= 0x0f;
+ }
+ else
+ {
+ // TTL inputs float high
+ data |= 0x0f;
+ }
+ break;
+
+ case MODE_1:
+ data |= m_intr[PORT_B] ? 0x01 : 0x00;
+
+ if (port_mode(PORT_B) == MODE_OUTPUT)
+ {
+ data |= m_obf[PORT_B] ? 0x02 : 0x00;
+ }
+ else
+ {
+ data |= m_ibf[PORT_B] ? 0x02 : 0x00;
+ }
+ }
+
+ data |= m_output[PORT_C] & mask;
+
+ m_out_port_func[PORT_C](0, data);
+}
+
+
+//-------------------------------------------------
+// set_mode -
+//-------------------------------------------------
+
+void i8255_device::set_mode(UINT8 data)
+{
+ m_control = data;
+
+ // group A
+ m_output[PORT_A] = 0;
+ m_input[PORT_A] = 0;
+ m_ibf[PORT_A] = 0;
+ m_obf[PORT_A] = 1;
+ m_inte[PORT_A] = 0;
+ m_inte1 = 0;
+ m_inte2 = 0;
+
+ if (port_mode(PORT_A) == MODE_OUTPUT)
+ {
+ m_out_port_func[PORT_A](0, m_output[PORT_A]);
+ }
+ else
+ {
+ // TTL inputs float high
+ m_out_port_func[PORT_A](0, 0xff);
+ }
+
+ if (LOG)
+ {
+ logerror("I8255 '%s' Group A Mode: %u\n", tag(), group_mode(GROUP_A));
+ logerror("I8255 '%s' Port A Mode: %s\n", tag(), (port_mode(PORT_A) == MODE_OUTPUT) ? "output" : "input");
+ logerror("I8255 '%s' Port C Upper Mode: %s\n", tag(), (port_c_upper_mode() == MODE_OUTPUT) ? "output" : "input");
+ logerror("I8255 '%s' Group B Mode: %u\n", tag(), group_mode(GROUP_B));
+ logerror("I8255 '%s' Port B Mode: %s\n", tag(), (port_mode(PORT_B) == MODE_OUTPUT) ? "output" : "input");
+ logerror("I8255 '%s' Port C Lower Mode: %s\n", tag(), (port_c_lower_mode() == MODE_OUTPUT) ? "output" : "input");
+ }
+
+ // group B
+ m_output[PORT_B] = 0;
+ m_input[PORT_B] = 0;
+ m_ibf[PORT_B] = 0;
+ m_obf[PORT_B] = 1;
+ m_inte[PORT_B] = 0;
+
+ if (port_mode(PORT_B) == MODE_OUTPUT)
+ {
+ m_out_port_func[PORT_B](0, m_output[PORT_B]);
+ }
+ else
+ {
+ // TTL inputs float high
+ m_out_port_func[PORT_B](0, 0xff);
+ }
+
+ m_output[PORT_C] = 0;
+ m_input[PORT_C] = 0;
+
+ output_pc();
+}
+
+
+//-------------------------------------------------
+// set_pc_bit -
+//-------------------------------------------------
+
+void i8255_device::set_pc_bit(int bit, int state)
+{
+ // set output latch bit
+ m_output[PORT_C] &= ~(1 << bit);
+ m_output[PORT_C] |= state << bit;
+
+ switch (group_mode(GROUP_A))
+ {
+ case MODE_1:
+ if (port_mode(PORT_A) == MODE_OUTPUT)
+ {
+ switch (bit)
+ {
+ case 3: set_intr(PORT_A, state); break;
+ case 6: set_inte(PORT_A, state); break;
+ case 7: set_obf(PORT_A, state); break;
+ }
+ }
+ else
+ {
+ switch (bit)
+ {
+ case 3: set_intr(PORT_A, state); break;
+ case 4: set_inte(PORT_A, state); break;
+ case 5: set_ibf(PORT_A, state); break;
+ }
+ }
+ break;
+
+ case MODE_2:
+ switch (bit)
+ {
+ case 3: set_intr(PORT_A, state); break;
+ case 4: set_inte2(state); break;
+ case 5: set_ibf(PORT_A, state); break;
+ case 6: set_inte1(state); break;
+ case 7: set_obf(PORT_A, state); break;
+ }
+ break;
+ }
+
+ if (group_mode(GROUP_B) == MODE_1)
+ {
+ switch (bit)
+ {
+ case 0: set_intr(PORT_B, state); break;
+ case 1:
+ if (port_mode(PORT_B) == MODE_OUTPUT)
+ set_obf(PORT_B, state);
+ else
+ set_ibf(PORT_B, state);
+ break;
+ case 2: set_inte(PORT_B, state); break;
+ }
+ }
+
+ output_pc();
+}
+
+
+//-------------------------------------------------
+// read -
+//-------------------------------------------------
+
+READ8_MEMBER( i8255_device::read )
+{
+ UINT8 data = 0;
+
+ switch (offset & 0x03)
+ {
+ case PORT_A:
+ switch (group_mode(GROUP_A))
+ {
+ case MODE_0: data = read_mode0(PORT_A); break;
+ case MODE_1: data = read_mode1(PORT_A); break;
+ case MODE_2: data = read_mode2(); break;
+ }
+ if (LOG) logerror("I8255 '%s' Port A Read: %02x\n", tag(), data);
+ break;
+
+ case PORT_B:
+ switch (group_mode(GROUP_B))
+ {
+ case MODE_0: data = read_mode0(PORT_B); break;
+ case MODE_1: data = read_mode1(PORT_B); break;
+ }
+ if (LOG) logerror("I8255 '%s' Port B Read: %02x\n", tag(), data);
+ break;
+
+ case PORT_C:
+ data = read_pc();
+ if (LOG) logerror("I8255 '%s' Port C Read: %02x\n", tag(), data);
+ break;
+
+ case CONTROL:
+ data = m_control;
+ if (LOG) logerror("I8255 '%s' Mode Control Word Read: %02x\n", tag(), data);
+ break;
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// write -
+//-------------------------------------------------
+
+WRITE8_MEMBER( i8255_device::write )
+{
+ switch (offset & 0x03)
+ {
+ case PORT_A:
+ if (LOG) logerror("I8255 '%s' Port A Write: %02x\n", tag(), data);
+
+ switch (group_mode(GROUP_A))
+ {
+ case MODE_0: write_mode0(PORT_A, data); break;
+ case MODE_1: write_mode1(PORT_A, data); break;
+ case MODE_2: write_mode2(data); break;
+ }
+ break;
+
+ case PORT_B:
+ if (LOG) logerror("I8255 '%s' Port B Write: %02x\n", tag(), data);
+
+ switch (group_mode(GROUP_B))
+ {
+ case MODE_0: write_mode0(PORT_B, data); break;
+ case MODE_1: write_mode1(PORT_B, data); break;
+ }
+ break;
+
+ case PORT_C:
+ if (LOG) logerror("I8255 '%s' Port C Write: %02x\n", tag(), data);
+
+ write_pc(data);
+ break;
+
+ case CONTROL:
+ if (data & CONTROL_MODE_SET)
+ {
+ if (LOG) logerror("I8255 '%s' Mode Control Word: %02x\n", tag(), data);
+
+ set_mode(data);
+ }
+ else
+ {
+ int bit = (data >> 1) & 0x07;
+ int state = BIT(data, 0);
+
+ if (LOG) logerror("I8255 '%s' %s Port C Bit %u\n", tag(), state ? "Set" : "Reset", bit);
+
+ set_pc_bit(bit, state);
+ }
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// pa_r -
+//-------------------------------------------------
+
+READ8_MEMBER( i8255_device::pa_r )
+{
+ return pa_r();
+}
+
+
+//-------------------------------------------------
+// pb_r - port A read
+//-------------------------------------------------
+
+UINT8 i8255_device::pa_r()
+{
+ UINT8 data = 0xff;
+
+ if (port_mode(PORT_A) == MODE_OUTPUT)
+ {
+ data = m_output[PORT_A];
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// pb_r -
+//-------------------------------------------------
+
+READ8_MEMBER( i8255_device::pb_r )
+{
+ return pb_r();
+}
+
+
+//-------------------------------------------------
+// pb_r - port B read
+//-------------------------------------------------
+
+UINT8 i8255_device::pb_r()
+{
+ UINT8 data = 0xff;
+
+ if (port_mode(PORT_B) == MODE_OUTPUT)
+ {
+ data = m_output[PORT_B];
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// pc2_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( i8255_device::pc2_w )
+{
+ if (group_mode(GROUP_B) == 1)
+ {
+ if (port_mode(PORT_B) == MODE_OUTPUT)
+ {
+ // port B acknowledge
+ if (!m_obf[PORT_B] && !state)
+ {
+ if (LOG) logerror("I8255 '%s' Port B Acknowledge\n", tag());
+
+ // clear output buffer flag
+ set_obf(PORT_B, 1);
+ }
+ }
+ else
+ {
+ // port B strobe
+ if (!m_ibf[PORT_B] && !state)
+ {
+ if (LOG) logerror("I8255 '%s' Port B Strobe\n", tag());
+
+ // read port into latch
+ m_input[PORT_B] = m_in_port_func[PORT_B](0);
+
+ // set input buffer flag
+ set_ibf(PORT_B, 1);
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// pc4_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( i8255_device::pc4_w )
+{
+ if ((group_mode(GROUP_A) == 2) || ((group_mode(GROUP_A) == 1) && (port_mode(PORT_A) == MODE_INPUT)))
+ {
+ // port A strobe
+ if (!m_ibf[PORT_A] && !state)
+ {
+ if (LOG) logerror("I8255 '%s' Port A Strobe\n", tag());
+
+ // read port into latch
+ m_input[PORT_A] = m_in_port_func[PORT_A](0);
+
+ // set input buffer flag
+ set_ibf(PORT_A, 1);
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// pc6_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( i8255_device::pc6_w )
+{
+ if ((group_mode(GROUP_A) == 2) || ((group_mode(GROUP_A) == 1) && (port_mode(PORT_A) == MODE_OUTPUT)))
+ {
+ // port A acknowledge
+ if (!m_obf[PORT_A] && !state)
+ {
+ if (LOG) logerror("I8255 '%s' Port A Acknowledge\n", tag());
+
+ // clear output buffer flag
+ set_obf(PORT_A, 1);
+ }
+ }
+}
diff --git a/trunk/src/emu/machine/i8255.h b/trunk/src/emu/machine/i8255.h
new file mode 100644
index 00000000000..15498292084
--- /dev/null
+++ b/trunk/src/emu/machine/i8255.h
@@ -0,0 +1,156 @@
+/**********************************************************************
+
+ Intel 8255(A) Programmable Peripheral Interface emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ PA3 1 |* \_/ | 40 PA4
+ PA2 2 | | 39 PA5
+ PA1 3 | | 38 PA6
+ PA0 4 | | 37 PA7
+ _RD 5 | | 36 WR
+ _CS 6 | | 35 RESET
+ GND 7 | | 34 D0
+ A1 8 | | 33 D1
+ A0 9 | | 32 D2
+ PC7 10 | 8255 | 31 D3
+ PC6 11 | 8255A | 30 D4
+ PC5 12 | | 29 D5
+ PC4 13 | | 28 D6
+ PC0 14 | | 27 D7
+ PC1 15 | | 26 Vcc
+ PC2 16 | | 25 PB7
+ PC3 17 | | 24 PB6
+ PB0 18 | | 23 PB5
+ PB1 19 | | 22 PB4
+ PB2 20 |_____________| 21 PB3
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __I8255__
+#define __I8255__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_I8255_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, I8255, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+
+#define MCFG_I8255A_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, I8255A, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+
+#define I8255_INTERFACE(name) \
+ const i8255_interface (name) =
+
+
+#define I8255A_INTERFACE(name) \
+ const i8255_interface (name) =
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> i8255_interface
+
+struct i8255_interface
+{
+ devcb_read8 m_in_pa_cb;
+ devcb_write8 m_out_pa_cb;
+ devcb_read8 m_in_pb_cb;
+ devcb_write8 m_out_pb_cb;
+ devcb_read8 m_in_pc_cb;
+ devcb_write8 m_out_pc_cb;
+};
+
+
+// ======================> i8255_device
+
+class i8255_device : public device_t,
+ public i8255_interface
+{
+public:
+ // construction/destruction
+ i8255_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_READ8_MEMBER( read );
+ DECLARE_WRITE8_MEMBER( write );
+
+ DECLARE_READ8_MEMBER( pa_r );
+ UINT8 pa_r();
+
+ DECLARE_READ8_MEMBER( pb_r );
+ UINT8 pb_r();
+
+ DECLARE_WRITE_LINE_MEMBER( pc2_w );
+ DECLARE_WRITE_LINE_MEMBER( pc4_w );
+ DECLARE_WRITE_LINE_MEMBER( pc6_w );
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+
+private:
+ inline void check_interrupt(int port);
+ inline void set_ibf(int port, int state);
+ inline void set_obf(int port, int state);
+ inline void set_inte(int port, int state);
+ inline void set_inte1(int state);
+ inline void set_inte2(int state);
+ inline void set_intr(int port, int state);
+ inline int group_mode(int group);
+ inline int port_mode(int port);
+ inline int port_c_lower_mode();
+ inline int port_c_upper_mode();
+
+ UINT8 read_mode0(int port);
+ UINT8 read_mode1(int port);
+ UINT8 read_mode2();
+ UINT8 read_pc();
+ void write_mode0(int port, UINT8 data);
+ void write_mode1(int port, UINT8 data);
+ void write_mode2(UINT8 data);
+ void write_pc(UINT8 data);
+ void output_pc();
+ void set_mode(UINT8 data);
+ void set_pc_bit(int bit, int state);
+
+ devcb_resolved_read8 m_in_port_func[3];
+ devcb_resolved_write8 m_out_port_func[3];
+
+ UINT8 m_control; // mode control word
+ UINT8 m_output[3]; // output latch
+ UINT8 m_input[3]; // input latch
+
+ int m_ibf[2]; // input buffer full flag
+ int m_obf[2]; // output buffer full flag, negative logic
+ int m_inte[2]; // interrupt enable
+ int m_inte1; // interrupt enable
+ int m_inte2; // interrupt enable
+ int m_intr[2]; // interrupt
+};
+
+
+// device type definition
+extern const device_type I8255;
+extern const device_type I8255A;
+
+
+
+#endif
diff --git a/trunk/src/emu/machine/i8355.c b/trunk/src/emu/machine/i8355.c
new file mode 100644
index 00000000000..a3a03c90de1
--- /dev/null
+++ b/trunk/src/emu/machine/i8355.c
@@ -0,0 +1,231 @@
+/**********************************************************************
+
+ Intel 8355 - 16,384-Bit ROM with I/O emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "i8355.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+enum
+{
+ REGISTER_PORT_A = 0,
+ REGISTER_PORT_B,
+ REGISTER_PORT_A_DDR,
+ REGISTER_PORT_B_DDR
+};
+
+enum
+{
+ PORT_A = 0,
+ PORT_B,
+ PORT_COUNT
+};
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+const device_type I8355 = &device_creator<i8355_device>;
+
+// default address map
+static ADDRESS_MAP_START( i8355, AS_0, 8 )
+ AM_RANGE(0x000, 0x7ff) AM_ROM
+ADDRESS_MAP_END
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// read_port - read from input port
+//-------------------------------------------------
+
+inline UINT8 i8355_device::read_port(int port)
+{
+ UINT8 data = m_output[port] & m_ddr[port];
+
+ if (m_ddr[port] != 0xff)
+ {
+ data |= m_in_port_func[port](0) & ~m_ddr[port];
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// write_port - write to output port
+//-------------------------------------------------
+
+inline void i8355_device::write_port(int port, UINT8 data)
+{
+ m_output[port] = data;
+
+ m_out_port_func[port](0, m_output[port] & m_ddr[port]);
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// i8355_device - constructor
+//-------------------------------------------------
+
+i8355_device::i8355_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, I8355, "Intel 8355", tag, owner, clock),
+ device_memory_interface(mconfig, *this),
+ m_space_config("ram", ENDIANNESS_LITTLE, 8, 11, 0, NULL, *ADDRESS_MAP_NAME(i8355))
+{
+
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void i8355_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const i8355_interface *intf = reinterpret_cast<const i8355_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<i8355_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_in_pa_cb, 0, sizeof(m_in_pa_cb));
+ memset(&m_out_pa_cb, 0, sizeof(m_out_pa_cb));
+ memset(&m_in_pb_cb, 0, sizeof(m_in_pb_cb));
+ memset(&m_out_pb_cb, 0, sizeof(m_out_pb_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void i8355_device::device_start()
+{
+ // resolve callbacks
+ m_in_port_func[0].resolve(m_in_pa_cb, *this);
+ m_in_port_func[1].resolve(m_in_pb_cb, *this);
+ m_out_port_func[0].resolve(m_out_pa_cb, *this);
+ m_out_port_func[1].resolve(m_out_pb_cb, *this);
+
+ // register for state saving
+ save_item(NAME(m_output));
+ save_item(NAME(m_ddr));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void i8355_device::device_reset()
+{
+ // set ports to input mode
+ m_ddr[PORT_A] = 0;
+ m_ddr[PORT_B] = 0;
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return a description of
+// any address spaces owned by this device
+//-------------------------------------------------
+
+const address_space_config *i8355_device::memory_space_config(address_spacenum spacenum) const
+{
+ return (spacenum == AS_0) ? &m_space_config : NULL;
+}
+
+
+
+//-------------------------------------------------
+// io_r - register read
+//-------------------------------------------------
+
+READ8_MEMBER( i8355_device::io_r )
+{
+ int port = offset & 0x01;
+
+ UINT8 data = 0;
+
+ switch (offset & 0x03)
+ {
+ case REGISTER_PORT_A:
+ case REGISTER_PORT_B:
+ data = read_port(port);
+ break;
+
+ case REGISTER_PORT_A_DDR:
+ case REGISTER_PORT_B_DDR:
+ // write only
+ break;
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// io_w - register write
+//-------------------------------------------------
+
+WRITE8_MEMBER( i8355_device::io_w )
+{
+ int port = offset & 0x01;
+
+ switch (offset & 0x03)
+ {
+ case REGISTER_PORT_A:
+ case REGISTER_PORT_B:
+ if (LOG) logerror("I8355 '%s' Port %c Write %02x\n", tag(), 'A' + port, data);
+
+ write_port(port, data);
+ break;
+
+ case REGISTER_PORT_A_DDR:
+ case REGISTER_PORT_B_DDR:
+ if (LOG) logerror("I8355 '%s' Port %c DDR: %02x\n", tag(), 'A' + port, data);
+
+ m_ddr[port] = data;
+ write_port(port, data);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// memory_r - internal ROM read
+//-------------------------------------------------
+
+READ8_MEMBER( i8355_device::memory_r )
+{
+ return this->space()->read_byte(offset);
+}
diff --git a/trunk/src/emu/machine/i8355.h b/trunk/src/emu/machine/i8355.h
new file mode 100644
index 00000000000..142b4a36ef1
--- /dev/null
+++ b/trunk/src/emu/machine/i8355.h
@@ -0,0 +1,124 @@
+/**********************************************************************
+
+ Intel 8355 - 16,384-Bit ROM with I/O emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ _CE1 1 |* \_/ | 40 Vcc
+ CE2 2 | | 39 PB7
+ CLK 3 | | 38 PB6
+ RESET 4 | | 37 PB5
+ N.C. 5 | | 36 PB4
+ READY 6 | | 35 PB3
+ IO/_M 7 | | 34 PB2
+ _IOR 8 | | 33 PB1
+ _RD 9 | | 32 PB0
+ _IOW 10 | 8355 | 31 PA7
+ ALE 11 | 8355-2 | 30 PA6
+ AD0 12 | | 29 PA5
+ AD1 13 | | 28 PA4
+ AD2 14 | | 27 PA3
+ AD3 15 | | 26 PA2
+ AD4 16 | | 25 PA1
+ AD5 17 | | 24 PA0
+ AD6 18 | | 23 A10
+ AD7 19 | | 22 A9
+ Vss 20 |_____________| 21 A8
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __I8355__
+#define __I8355__
+
+#include "emu.h"
+
+
+
+///*************************************************************************
+// MACROS / CONSTANTS
+///*************************************************************************
+
+
+
+
+///*************************************************************************
+// INTERFACE CONFIGURATION MACROS
+///*************************************************************************
+
+#define MCFG_I8355_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD((_tag), I8355, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define I8355_INTERFACE(name) \
+ const i8355_interface (name) =
+
+
+
+///*************************************************************************
+// TYPE DEFINITIONS
+///*************************************************************************
+
+// ======================> i8355_interface
+
+struct i8355_interface
+{
+ devcb_read8 m_in_pa_cb;
+ devcb_write8 m_out_pa_cb;
+
+ devcb_read8 m_in_pb_cb;
+ devcb_write8 m_out_pb_cb;
+};
+
+
+
+// ======================> i8355_device
+
+class i8355_device : public device_t,
+ public device_memory_interface,
+ public i8355_interface
+{
+public:
+ // construction/destruction
+ i8355_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_READ8_MEMBER( io_r );
+ DECLARE_WRITE8_MEMBER( io_w );
+
+ DECLARE_READ8_MEMBER( memory_r );
+ DECLARE_WRITE8_MEMBER( memory_w );
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
+
+ inline UINT8 read_port(int port);
+ inline void write_port(int port, UINT8 data);
+
+private:
+ devcb_resolved_read8 m_in_port_func[2];
+ devcb_resolved_write8 m_out_port_func[2];
+
+ // registers
+ UINT8 m_output[2]; // output latches
+ UINT8 m_ddr[2]; // DDR latches
+
+ const address_space_config m_space_config;
+};
+
+
+// device type definition
+extern const device_type I8355;
+
+
+
+#endif
diff --git a/trunk/src/emu/machine/idectrl.c b/trunk/src/emu/machine/idectrl.c
new file mode 100644
index 00000000000..c93d6c1844e
--- /dev/null
+++ b/trunk/src/emu/machine/idectrl.c
@@ -0,0 +1,2033 @@
+/***************************************************************************
+
+ Generic (PC-style) IDE controller implementation
+
+***************************************************************************/
+
+#include "emu.h"
+#include "idectrl.h"
+#include "debugger.h"
+#include "imagedev/harddriv.h"
+
+/***************************************************************************
+ DEBUGGING
+***************************************************************************/
+
+#define VERBOSE 0
+#define PRINTF_IDE_COMMANDS 0
+#define PRINTF_IDE_PASSWORD 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+#define LOGPRINT(x) do { if (VERBOSE) logerror x; if (PRINTF_IDE_COMMANDS) mame_printf_debug x; } while (0)
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define IDE_DISK_SECTOR_SIZE 512
+
+#define MINIMUM_COMMAND_TIME (attotime::from_usec(10))
+
+#define TIME_PER_SECTOR (attotime::from_usec(100))
+#define TIME_PER_ROTATION (attotime::from_hz(5400/60))
+#define TIME_SECURITY_ERROR (attotime::from_msec(1000))
+
+#define TIME_SEEK_MULTISECTOR (attotime::from_msec(13))
+#define TIME_NO_SEEK_MULTISECTOR (attotime::from_nsec(16300))
+
+#define IDE_STATUS_ERROR 0x01
+#define IDE_STATUS_HIT_INDEX 0x02
+#define IDE_STATUS_BUFFER_READY 0x08
+#define IDE_STATUS_SEEK_COMPLETE 0x10
+#define IDE_STATUS_DRIVE_READY 0x40
+#define IDE_STATUS_BUSY 0x80
+
+#define IDE_CONFIG_REGISTERS 0x10
+
+#define BANK(b, v) (((v) << 4) | (b))
+
+#define IDE_BANK0_DATA BANK(0, 0)
+#define IDE_BANK0_ERROR BANK(0, 1)
+#define IDE_BANK0_SECTOR_COUNT BANK(0, 2)
+#define IDE_BANK0_SECTOR_NUMBER BANK(0, 3)
+#define IDE_BANK0_CYLINDER_LSB BANK(0, 4)
+#define IDE_BANK0_CYLINDER_MSB BANK(0, 5)
+#define IDE_BANK0_HEAD_NUMBER BANK(0, 6)
+#define IDE_BANK0_STATUS_COMMAND BANK(0, 7)
+
+#define IDE_BANK1_STATUS_CONTROL BANK(1, 6)
+
+#define IDE_BANK2_CONFIG_UNK BANK(2, 4)
+#define IDE_BANK2_CONFIG_REGISTER BANK(2, 8)
+#define IDE_BANK2_CONFIG_DATA BANK(2, 0xc)
+
+#define IDE_COMMAND_READ_MULTIPLE 0x20
+#define IDE_COMMAND_READ_MULTIPLE_ONCE 0x21
+#define IDE_COMMAND_WRITE_MULTIPLE 0x30
+#define IDE_COMMAND_DIAGNOSTIC 0x90
+#define IDE_COMMAND_SET_CONFIG 0x91
+#define IDE_COMMAND_READ_MULTIPLE_BLOCK 0xc4
+#define IDE_COMMAND_WRITE_MULTIPLE_BLOCK 0xc5
+#define IDE_COMMAND_SET_BLOCK_COUNT 0xc6
+#define IDE_COMMAND_READ_DMA 0xc8
+#define IDE_COMMAND_WRITE_DMA 0xca
+#define IDE_COMMAND_GET_INFO 0xec
+#define IDE_COMMAND_SET_FEATURES 0xef
+#define IDE_COMMAND_SECURITY_UNLOCK 0xf2
+#define IDE_COMMAND_UNKNOWN_F9 0xf9
+#define IDE_COMMAND_VERIFY_MULTIPLE 0x40
+#define IDE_COMMAND_VERIFY_NORETRY 0x41
+#define IDE_COMMAND_ATAPI_IDENTIFY 0xa1
+#define IDE_COMMAND_RECALIBRATE 0x10
+#define IDE_COMMAND_SEEK 0x70
+#define IDE_COMMAND_IDLE_IMMEDIATE 0xe1
+#define IDE_COMMAND_IDLE 0xe3
+#define IDE_COMMAND_TAITO_GNET_UNLOCK_1 0xfe
+#define IDE_COMMAND_TAITO_GNET_UNLOCK_2 0xfc
+#define IDE_COMMAND_TAITO_GNET_UNLOCK_3 0x0f
+
+#define IDE_ERROR_NONE 0x00
+#define IDE_ERROR_DEFAULT 0x01
+#define IDE_ERROR_UNKNOWN_COMMAND 0x04
+#define IDE_ERROR_BAD_LOCATION 0x10
+#define IDE_ERROR_BAD_SECTOR 0x80
+
+#define IDE_BUSMASTER_STATUS_ACTIVE 0x01
+#define IDE_BUSMASTER_STATUS_ERROR 0x02
+#define IDE_BUSMASTER_STATUS_IRQ 0x04
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _ide_state ide_state;
+struct _ide_state
+{
+ device_t *device;
+
+ UINT8 adapter_control;
+ UINT8 status;
+ UINT8 error;
+ UINT8 command;
+ UINT8 interrupt_pending;
+ UINT8 precomp_offset;
+
+ UINT8 buffer[IDE_DISK_SECTOR_SIZE];
+ UINT8 features[IDE_DISK_SECTOR_SIZE];
+ UINT16 buffer_offset;
+ UINT16 sector_count;
+
+ UINT16 block_count;
+ UINT16 sectors_until_int;
+ UINT8 verify_only;
+
+ UINT8 dma_active;
+ address_space *dma_space;
+ UINT8 dma_address_xor;
+ UINT8 dma_last_buffer;
+ offs_t dma_address;
+ offs_t dma_descriptor;
+ UINT32 dma_bytes_left;
+
+ UINT8 bus_master_command;
+ UINT8 bus_master_status;
+ UINT32 bus_master_descriptor;
+
+ UINT16 cur_cylinder;
+ UINT8 cur_sector;
+ UINT8 cur_head;
+ UINT8 cur_head_reg;
+
+ UINT32 cur_lba;
+
+ UINT16 num_cylinders;
+ UINT8 num_sectors;
+ UINT8 num_heads;
+
+ UINT8 config_unknown;
+ UINT8 config_register[IDE_CONFIG_REGISTERS];
+ UINT8 config_register_num;
+
+ chd_file *handle;
+ hard_disk_file *disk;
+ emu_timer * last_status_timer;
+ emu_timer * reset_timer;
+
+ UINT8 master_password_enable;
+ UINT8 user_password_enable;
+ const UINT8 * master_password;
+ const UINT8 * user_password;
+
+ UINT8 gnetreadlock;
+};
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static TIMER_CALLBACK( reset_callback );
+
+static void ide_build_features(ide_state *ide);
+
+static void continue_read(ide_state *ide);
+static void read_sector_done(ide_state *ide);
+static TIMER_CALLBACK( read_sector_done_callback );
+static void read_first_sector(ide_state *ide);
+static void read_next_sector(ide_state *ide);
+
+static UINT32 ide_controller_read(device_t *device, int bank, offs_t offset, int size);
+static void ide_controller_write(device_t *device, int bank, offs_t offset, int size, UINT32 data);
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ get_safe_token - makes sure that the passed
+ in device is, in fact, an IDE controller
+-------------------------------------------------*/
+
+INLINE ide_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == IDE_CONTROLLER);
+
+ return (ide_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+INLINE void signal_interrupt(ide_state *ide)
+{
+ const ide_config *config = (const ide_config *)downcast<const legacy_device_base *>(ide->device)->inline_config();
+
+ LOG(("IDE interrupt assert\n"));
+
+ /* signal an interrupt */
+ if (config->interrupt != NULL)
+ (*config->interrupt)(ide->device, ASSERT_LINE);
+ ide->interrupt_pending = 1;
+ ide->bus_master_status |= IDE_BUSMASTER_STATUS_IRQ;
+}
+
+
+INLINE void clear_interrupt(ide_state *ide)
+{
+ const ide_config *config = (const ide_config *)downcast<const legacy_device_base *>(ide->device)->inline_config();
+
+ LOG(("IDE interrupt clear\n"));
+
+ /* clear an interrupt */
+ if (config->interrupt != NULL)
+ (*config->interrupt)(ide->device, CLEAR_LINE);
+ ide->interrupt_pending = 0;
+}
+
+
+
+/***************************************************************************
+ DELAYED INTERRUPT HANDLING
+***************************************************************************/
+
+static TIMER_CALLBACK( delayed_interrupt )
+{
+ ide_state *ide = (ide_state *)ptr;
+ ide->status &= ~IDE_STATUS_BUSY;
+ signal_interrupt(ide);
+}
+
+
+static TIMER_CALLBACK( delayed_interrupt_buffer_ready )
+{
+ ide_state *ide = (ide_state *)ptr;
+ ide->status &= ~IDE_STATUS_BUSY;
+ ide->status |= IDE_STATUS_BUFFER_READY;
+ signal_interrupt(ide);
+}
+
+
+INLINE void signal_delayed_interrupt(ide_state *ide, attotime time, int buffer_ready)
+{
+ /* clear buffer ready and set the busy flag */
+ ide->status &= ~IDE_STATUS_BUFFER_READY;
+ ide->status |= IDE_STATUS_BUSY;
+
+ /* set a timer */
+ if (buffer_ready)
+ ide->device->machine().scheduler().timer_set(time, FUNC(delayed_interrupt_buffer_ready), 0, ide);
+ else
+ ide->device->machine().scheduler().timer_set(time, FUNC(delayed_interrupt), 0, ide);
+}
+
+
+
+/***************************************************************************
+ INITIALIZATION AND RESET
+***************************************************************************/
+
+UINT8 *ide_get_features(device_t *device)
+{
+ ide_state *ide = get_safe_token(device);
+ return ide->features;
+}
+
+void ide_set_gnet_readlock(device_t *device, const UINT8 onoff)
+{
+ ide_state *ide = get_safe_token(device);
+ ide->gnetreadlock = onoff;
+}
+
+void ide_set_master_password(device_t *device, const UINT8 *password)
+{
+ ide_state *ide = get_safe_token(device);
+
+ ide->master_password = password;
+ ide->master_password_enable = (ide->master_password != NULL);
+}
+
+
+void ide_set_user_password(device_t *device, const UINT8 *password)
+{
+ ide_state *ide = get_safe_token(device);
+
+ ide->user_password = password;
+ ide->user_password_enable = (ide->user_password != NULL);
+}
+
+
+static TIMER_CALLBACK( reset_callback )
+{
+ reinterpret_cast<device_t *>(ptr)->reset();
+}
+
+
+
+/*************************************
+ *
+ * Convert offset/mem_mask to offset
+ * and size
+ *
+ *************************************/
+
+INLINE int convert_to_offset_and_size32(offs_t *offset, UINT32 mem_mask)
+{
+ int size = 4;
+
+ /* determine which real offset */
+ if (!ACCESSING_BITS_0_7)
+ {
+ (*offset)++, size = 3;
+ if (!ACCESSING_BITS_8_15)
+ {
+ (*offset)++, size = 2;
+ if (!ACCESSING_BITS_16_23)
+ (*offset)++, size = 1;
+ }
+ }
+
+ /* determine the real size */
+ if (ACCESSING_BITS_24_31)
+ return size;
+ size--;
+ if (ACCESSING_BITS_16_23)
+ return size;
+ size--;
+ if (ACCESSING_BITS_8_15)
+ return size;
+ size--;
+ return size;
+}
+
+INLINE int convert_to_offset_and_size16(offs_t *offset, UINT32 mem_mask)
+{
+ int size = 2;
+
+ /* determine which real offset */
+ if (!ACCESSING_BITS_0_7)
+ (*offset)++, size = 1;
+
+ if (ACCESSING_BITS_8_15)
+ return size;
+ size--;
+ return size;
+}
+
+
+
+/*************************************
+ *
+ * Compute the LBA address
+ *
+ *************************************/
+
+INLINE UINT32 lba_address(ide_state *ide)
+{
+ /* LBA direct? */
+ if (ide->cur_head_reg & 0x40)
+ return ide->cur_sector + ide->cur_cylinder * 256 + ide->cur_head * 16777216;
+
+ /* standard CHS */
+ else
+ return (ide->cur_cylinder * ide->num_heads + ide->cur_head) * ide->num_sectors + ide->cur_sector - 1;
+}
+
+
+
+/*************************************
+ *
+ * Advance to the next sector
+ *
+ *************************************/
+
+INLINE void next_sector(ide_state *ide)
+{
+ /* LBA direct? */
+ if (ide->cur_head_reg & 0x40)
+ {
+ ide->cur_sector++;
+ if (ide->cur_sector == 0)
+ {
+ ide->cur_cylinder++;
+ if (ide->cur_cylinder == 0)
+ ide->cur_head++;
+ }
+ }
+
+ /* standard CHS */
+ else
+ {
+ /* sectors are 1-based */
+ ide->cur_sector++;
+ if (ide->cur_sector > ide->num_sectors)
+ {
+ /* heads are 0 based */
+ ide->cur_sector = 1;
+ ide->cur_head++;
+ if (ide->cur_head >= ide->num_heads)
+ {
+ ide->cur_head = 0;
+ ide->cur_cylinder++;
+ }
+ }
+ }
+
+ ide->cur_lba = lba_address(ide);
+}
+
+
+
+/*************************************
+ *
+ * Build a features page
+ *
+ *************************************/
+
+static void swap_strncpy(UINT8 *dst, const char *src, int field_size_in_words)
+{
+ int i;
+
+ assert(strlen(src) <= (field_size_in_words*2));
+
+ for (i = 0; i < strlen(src); i++)
+ dst[i ^ 1] = src[i];
+ for ( ; i < field_size_in_words * 2; i++)
+ dst[i ^ 1] = ' ';
+}
+
+
+static void ide_generate_features(ide_state *ide)
+{
+ int total_sectors = ide->num_cylinders * ide->num_heads * ide->num_sectors;
+ int sectors_per_track = ide->num_heads * ide->num_sectors;
+
+ /* basic geometry */
+ ide->features[ 0*2+0] = 0x5a; /* 0: configuration bits */
+ ide->features[ 0*2+1] = 0x04;
+ ide->features[ 1*2+0] = ide->num_cylinders & 0xff; /* 1: logical cylinders */
+ ide->features[ 1*2+1] = ide->num_cylinders >> 8;
+ ide->features[ 2*2+0] = 0; /* 2: reserved */
+ ide->features[ 2*2+1] = 0;
+ ide->features[ 3*2+0] = ide->num_heads & 0xff; /* 3: logical heads */
+ ide->features[ 3*2+1] = 0;/*ide->num_heads >> 8;*/
+ ide->features[ 4*2+0] = 0; /* 4: vendor specific (obsolete) */
+ ide->features[ 4*2+1] = 0;
+ ide->features[ 5*2+0] = 0; /* 5: vendor specific (obsolete) */
+ ide->features[ 5*2+1] = 0;
+ ide->features[ 6*2+0] = ide->num_sectors & 0xff; /* 6: logical sectors per logical track */
+ ide->features[ 6*2+1] = 0;/*ide->num_sectors >> 8;*/
+ ide->features[ 7*2+0] = 0; /* 7: vendor-specific */
+ ide->features[ 7*2+1] = 0;
+ ide->features[ 8*2+0] = 0; /* 8: vendor-specific */
+ ide->features[ 8*2+1] = 0;
+ ide->features[ 9*2+0] = 0; /* 9: vendor-specific */
+ ide->features[ 9*2+1] = 0;
+ swap_strncpy(&ide->features[10*2+0], /* 10-19: serial number */
+ "00000000000000000000", 10);
+ ide->features[20*2+0] = 0; /* 20: vendor-specific */
+ ide->features[20*2+1] = 0;
+ ide->features[21*2+0] = 0; /* 21: vendor-specific */
+ ide->features[21*2+1] = 0;
+ ide->features[22*2+0] = 4; /* 22: # of vendor-specific bytes on read/write long commands */
+ ide->features[22*2+1] = 0;
+ swap_strncpy(&ide->features[23*2+0], /* 23-26: firmware revision */
+ "1.0", 4);
+ swap_strncpy(&ide->features[27*2+0], /* 27-46: model number */
+ "MAME Compressed Hard Disk", 20);
+ ide->features[47*2+0] = 0x01; /* 47: read/write multiple support */
+ ide->features[47*2+1] = 0x80;
+ ide->features[48*2+0] = 0; /* 48: reserved */
+ ide->features[48*2+1] = 0;
+ ide->features[49*2+0] = 0x03; /* 49: capabilities */
+ ide->features[49*2+1] = 0x0f;
+ ide->features[50*2+0] = 0; /* 50: reserved */
+ ide->features[50*2+1] = 0;
+ ide->features[51*2+0] = 2; /* 51: PIO data transfer cycle timing mode */
+ ide->features[51*2+1] = 0;
+ ide->features[52*2+0] = 2; /* 52: single word DMA transfer cycle timing mode */
+ ide->features[52*2+1] = 0;
+ ide->features[53*2+0] = 3; /* 53: field validity */
+ ide->features[53*2+1] = 0;
+ ide->features[54*2+0] = ide->num_cylinders & 0xff; /* 54: number of current logical cylinders */
+ ide->features[54*2+1] = ide->num_cylinders >> 8;
+ ide->features[55*2+0] = ide->num_heads & 0xff; /* 55: number of current logical heads */
+ ide->features[55*2+1] = 0;/*ide->num_heads >> 8;*/
+ ide->features[56*2+0] = ide->num_sectors & 0xff; /* 56: number of current logical sectors per track */
+ ide->features[56*2+1] = 0;/*ide->num_sectors >> 8;*/
+ ide->features[57*2+0] = sectors_per_track & 0xff; /* 57-58: number of current logical sectors per track */
+ ide->features[57*2+1] = sectors_per_track >> 8;
+ ide->features[58*2+0] = sectors_per_track >> 16;
+ ide->features[58*2+1] = sectors_per_track >> 24;
+ ide->features[59*2+0] = 0; /* 59: multiple sector timing */
+ ide->features[59*2+1] = 0;
+ ide->features[60*2+0] = total_sectors & 0xff; /* 60-61: total user addressable sectors */
+ ide->features[60*2+1] = total_sectors >> 8;
+ ide->features[61*2+0] = total_sectors >> 16;
+ ide->features[61*2+1] = total_sectors >> 24;
+ ide->features[62*2+0] = 0x07; /* 62: single word dma transfer */
+ ide->features[62*2+1] = 0x00;
+ ide->features[63*2+0] = 0x07; /* 63: multiword DMA transfer */
+ ide->features[63*2+1] = 0x04;
+ ide->features[64*2+0] = 0x03; /* 64: flow control PIO transfer modes supported */
+ ide->features[64*2+1] = 0x00;
+ ide->features[65*2+0] = 0x78; /* 65: minimum multiword DMA transfer cycle time per word */
+ ide->features[65*2+1] = 0x00;
+ ide->features[66*2+0] = 0x78; /* 66: mfr's recommended multiword DMA transfer cycle time */
+ ide->features[66*2+1] = 0x00;
+ ide->features[67*2+0] = 0x4d; /* 67: minimum PIO transfer cycle time without flow control */
+ ide->features[67*2+1] = 0x01;
+ ide->features[68*2+0] = 0x78; /* 68: minimum PIO transfer cycle time with IORDY */
+ ide->features[68*2+1] = 0x00;
+ ide->features[69*2+0] = 0x00; /* 69-70: reserved */
+ ide->features[69*2+1] = 0x00;
+ ide->features[71*2+0] = 0x00; /* 71: reserved for IDENTIFY PACKET command */
+ ide->features[71*2+1] = 0x00;
+ ide->features[72*2+0] = 0x00; /* 72: reserved for IDENTIFY PACKET command */
+ ide->features[72*2+1] = 0x00;
+ ide->features[73*2+0] = 0x00; /* 73: reserved for IDENTIFY PACKET command */
+ ide->features[73*2+1] = 0x00;
+ ide->features[74*2+0] = 0x00; /* 74: reserved for IDENTIFY PACKET command */
+ ide->features[74*2+1] = 0x00;
+ ide->features[75*2+0] = 0x00; /* 75: queue depth */
+ ide->features[75*2+1] = 0x00;
+ ide->features[76*2+0] = 0x00; /* 76-79: reserved */
+ ide->features[76*2+1] = 0x00;
+ ide->features[80*2+0] = 0x00; /* 80: major version number */
+ ide->features[80*2+1] = 0x00;
+ ide->features[81*2+0] = 0x00; /* 81: minor version number */
+ ide->features[81*2+1] = 0x00;
+ ide->features[82*2+0] = 0x00; /* 82: command set supported */
+ ide->features[82*2+1] = 0x00;
+ ide->features[83*2+0] = 0x00; /* 83: command sets supported */
+ ide->features[83*2+1] = 0x00;
+ ide->features[84*2+0] = 0x00; /* 84: command set/feature supported extension */
+ ide->features[84*2+1] = 0x00;
+ ide->features[85*2+0] = 0x00; /* 85: command set/feature enabled */
+ ide->features[85*2+1] = 0x00;
+ ide->features[86*2+0] = 0x00; /* 86: command set/feature enabled */
+ ide->features[86*2+1] = 0x00;
+ ide->features[87*2+0] = 0x00; /* 87: command set/feature default */
+ ide->features[87*2+1] = 0x00;
+ ide->features[88*2+0] = 0x00; /* 88: additional DMA modes */
+ ide->features[88*2+1] = 0x00;
+ ide->features[89*2+0] = 0x00; /* 89: time required for security erase unit completion */
+ ide->features[89*2+1] = 0x00;
+ ide->features[90*2+0] = 0x00; /* 90: time required for enhanced security erase unit completion */
+ ide->features[90*2+1] = 0x00;
+ ide->features[91*2+0] = 0x00; /* 91: current advanced power management value */
+ ide->features[91*2+1] = 0x00;
+ ide->features[92*2+0] = 0x00; /* 92: master password revision code */
+ ide->features[92*2+1] = 0x00;
+ ide->features[93*2+0] = 0x00; /* 93: hardware reset result */
+ ide->features[93*2+1] = 0x00;
+ ide->features[94*2+0] = 0x00; /* 94: acoustic management values */
+ ide->features[94*2+1] = 0x00;
+ ide->features[95*2+0] = 0x00; /* 95-99: reserved */
+ ide->features[95*2+1] = 0x00;
+ ide->features[100*2+0] = total_sectors & 0xff; /* 100-103: maximum 48-bit LBA */
+ ide->features[100*2+1] = total_sectors >> 8;
+ ide->features[101*2+0] = total_sectors >> 16;
+ ide->features[101*2+1] = total_sectors >> 24;
+ ide->features[102*2+0] = 0x00;
+ ide->features[102*2+1] = 0x00;
+ ide->features[103*2+0] = 0x00;
+ ide->features[103*2+1] = 0x00;
+ ide->features[104*2+0] = 0x00; /* 104-126: reserved */
+ ide->features[104*2+1] = 0x00;
+ ide->features[127*2+0] = 0x00; /* 127: removable media status notification */
+ ide->features[127*2+1] = 0x00;
+ ide->features[128*2+0] = 0x00; /* 128: security status */
+ ide->features[128*2+1] = 0x00;
+ ide->features[129*2+0] = 0x00; /* 129-159: vendor specific */
+ ide->features[129*2+1] = 0x00;
+ ide->features[160*2+0] = 0x00; /* 160: CFA power mode 1 */
+ ide->features[160*2+1] = 0x00;
+ ide->features[161*2+0] = 0x00; /* 161-175: reserved for CompactFlash */
+ ide->features[161*2+1] = 0x00;
+ ide->features[176*2+0] = 0x00; /* 176-205: current media serial number */
+ ide->features[176*2+1] = 0x00;
+ ide->features[206*2+0] = 0x00; /* 206-254: reserved */
+ ide->features[206*2+1] = 0x00;
+ ide->features[255*2+0] = 0x00; /* 255: integrity word */
+ ide->features[255*2+1] = 0x00;
+}
+
+
+static void ide_build_features(ide_state *ide)
+{
+ memset(ide->features, 0, IDE_DISK_SECTOR_SIZE);
+ if (chd_get_metadata (ide->handle, HARD_DISK_IDENT_METADATA_TAG, 0, ide->features, IDE_DISK_SECTOR_SIZE, 0, 0, 0) != CHDERR_NONE)
+ ide_generate_features (ide);
+}
+
+/*************************************
+ *
+ * security error handling
+ *
+ *************************************/
+
+static TIMER_CALLBACK( security_error_done )
+{
+ ide_state *ide = (ide_state *)ptr;
+
+ /* clear error state */
+ ide->status &= ~IDE_STATUS_ERROR;
+ ide->status |= IDE_STATUS_DRIVE_READY;
+}
+
+static void security_error(ide_state *ide)
+{
+ /* set error state */
+ ide->status |= IDE_STATUS_ERROR;
+ ide->status &= ~IDE_STATUS_DRIVE_READY;
+
+ /* just set a timer and mark ourselves error */
+ ide->device->machine().scheduler().timer_set(TIME_SECURITY_ERROR, FUNC(security_error_done), 0, ide);
+}
+
+
+
+/*************************************
+ *
+ * Sector reading
+ *
+ *************************************/
+
+static void continue_read(ide_state *ide)
+{
+ /* reset the totals */
+ ide->buffer_offset = 0;
+
+ /* clear the buffer ready and busy flag */
+ ide->status &= ~IDE_STATUS_BUFFER_READY;
+ ide->status &= ~IDE_STATUS_BUSY;
+
+ if (ide->master_password_enable || ide->user_password_enable)
+ {
+ security_error(ide);
+
+ ide->sector_count = 0;
+ ide->bus_master_status &= ~IDE_BUSMASTER_STATUS_ACTIVE;
+ ide->dma_active = 0;
+
+ return;
+ }
+
+ /* if there is more data to read, keep going */
+ if (ide->sector_count > 0)
+ ide->sector_count--;
+ if (ide->sector_count > 0)
+ read_next_sector(ide);
+ else
+ {
+ ide->bus_master_status &= ~IDE_BUSMASTER_STATUS_ACTIVE;
+ ide->dma_active = 0;
+ }
+}
+
+
+static void write_buffer_to_dma(ide_state *ide)
+{
+ int bytesleft = IDE_DISK_SECTOR_SIZE;
+ UINT8 *data = ide->buffer;
+
+// LOG(("Writing sector to %08X\n", ide->dma_address));
+
+ /* loop until we've consumed all bytes */
+ while (bytesleft--)
+ {
+ /* if we're out of space, grab the next descriptor */
+ if (ide->dma_bytes_left == 0)
+ {
+ /* if we're out of buffer space, that's bad */
+ if (ide->dma_last_buffer)
+ {
+ LOG(("DMA Out of buffer space!\n"));
+ return;
+ }
+
+ /* fetch the address */
+ ide->dma_address = ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor);
+ ide->dma_address |= ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor) << 8;
+ ide->dma_address |= ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor) << 16;
+ ide->dma_address |= ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor) << 24;
+ ide->dma_address &= 0xfffffffe;
+
+ /* fetch the length */
+ ide->dma_bytes_left = ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor);
+ ide->dma_bytes_left |= ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor) << 8;
+ ide->dma_bytes_left |= ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor) << 16;
+ ide->dma_bytes_left |= ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor) << 24;
+ ide->dma_last_buffer = (ide->dma_bytes_left >> 31) & 1;
+ ide->dma_bytes_left &= 0xfffe;
+ if (ide->dma_bytes_left == 0)
+ ide->dma_bytes_left = 0x10000;
+
+// LOG(("New DMA descriptor: address = %08X bytes = %04X last = %d\n", ide->dma_address, ide->dma_bytes_left, ide->dma_last_buffer));
+ }
+
+ /* write the next byte */
+ ide->dma_space->write_byte(ide->dma_address++, *data++);
+ ide->dma_bytes_left--;
+ }
+}
+
+
+static void read_sector_done(ide_state *ide)
+{
+ int lba = lba_address(ide), count = 0;
+
+ /* GNET readlock check */
+ if (ide->gnetreadlock) {
+ ide->status &= ~IDE_STATUS_ERROR;
+ ide->status &= ~IDE_STATUS_BUSY;
+ return;
+ }
+ /* now do the read */
+ if (ide->disk)
+ count = hard_disk_read(ide->disk, lba, ide->buffer);
+
+ /* by default, mark the buffer ready and the seek complete */
+ if (!ide->verify_only)
+ ide->status |= IDE_STATUS_BUFFER_READY;
+ ide->status |= IDE_STATUS_SEEK_COMPLETE;
+
+ /* and clear the busy and error flags */
+ ide->status &= ~IDE_STATUS_ERROR;
+ ide->status &= ~IDE_STATUS_BUSY;
+
+ /* if we succeeded, advance to the next sector and set the nice bits */
+ if (count == 1)
+ {
+ /* advance the pointers, unless this is the last sector */
+ /* Gauntlet: Dark Legacy checks to make sure we stop on the last sector */
+ if (ide->sector_count != 1)
+ next_sector(ide);
+
+ /* clear the error value */
+ ide->error = IDE_ERROR_NONE;
+
+ /* signal an interrupt */
+ if (!ide->verify_only)
+ ide->sectors_until_int--;
+ if (ide->sectors_until_int == 0 || ide->sector_count == 1)
+ {
+ ide->sectors_until_int = ((ide->command == IDE_COMMAND_READ_MULTIPLE_BLOCK) ? ide->block_count : 1);
+ signal_interrupt(ide);
+ }
+
+ /* handle DMA */
+ if (ide->dma_active)
+ write_buffer_to_dma(ide);
+
+ /* if we're just verifying or if we DMA'ed the data, we can read the next sector */
+ if (ide->verify_only || ide->dma_active)
+ continue_read(ide);
+ }
+
+ /* if we got an error, we need to report it */
+ else
+ {
+ /* set the error flag and the error */
+ ide->status |= IDE_STATUS_ERROR;
+ ide->error = IDE_ERROR_BAD_SECTOR;
+ ide->bus_master_status |= IDE_BUSMASTER_STATUS_ERROR;
+ ide->bus_master_status &= ~IDE_BUSMASTER_STATUS_ACTIVE;
+
+ /* signal an interrupt */
+ signal_interrupt(ide);
+ }
+}
+
+
+static TIMER_CALLBACK( read_sector_done_callback )
+{
+ read_sector_done((ide_state *)ptr);
+}
+
+
+static void read_first_sector(ide_state *ide)
+{
+ /* mark ourselves busy */
+ ide->status |= IDE_STATUS_BUSY;
+
+ /* just set a timer */
+ if (ide->command == IDE_COMMAND_READ_MULTIPLE_BLOCK)
+ {
+ int new_lba = lba_address(ide);
+ attotime seek_time;
+
+ if (new_lba == ide->cur_lba || new_lba == ide->cur_lba + 1)
+ seek_time = TIME_NO_SEEK_MULTISECTOR;
+ else
+ seek_time = TIME_SEEK_MULTISECTOR;
+
+ ide->cur_lba = new_lba;
+ ide->device->machine().scheduler().timer_set(seek_time, FUNC(read_sector_done_callback), 0, ide);
+ }
+ else
+ ide->device->machine().scheduler().timer_set(TIME_PER_SECTOR, FUNC(read_sector_done_callback), 0, ide);
+}
+
+
+static void read_next_sector(ide_state *ide)
+{
+ /* mark ourselves busy */
+ ide->status |= IDE_STATUS_BUSY;
+
+ if (ide->command == IDE_COMMAND_READ_MULTIPLE_BLOCK)
+ {
+ if (ide->sectors_until_int != 1)
+ /* make ready now */
+ read_sector_done(ide);
+ else
+ /* just set a timer */
+ ide->device->machine().scheduler().timer_set(attotime::from_usec(1), FUNC(read_sector_done_callback), 0, ide);
+ }
+ else
+ /* just set a timer */
+ ide->device->machine().scheduler().timer_set(TIME_PER_SECTOR, FUNC(read_sector_done_callback), 0, ide);
+}
+
+
+
+/*************************************
+ *
+ * Sector writing
+ *
+ *************************************/
+
+static void write_sector_done(ide_state *ide);
+static TIMER_CALLBACK( write_sector_done_callback );
+
+static void continue_write(ide_state *ide)
+{
+ /* reset the totals */
+ ide->buffer_offset = 0;
+
+ /* clear the buffer ready flag */
+ ide->status &= ~IDE_STATUS_BUFFER_READY;
+ ide->status |= IDE_STATUS_BUSY;
+
+ if (ide->command == IDE_COMMAND_WRITE_MULTIPLE_BLOCK)
+ {
+ if (ide->sectors_until_int != 1)
+ {
+ /* ready to write now */
+ write_sector_done(ide);
+ }
+ else
+ {
+ /* set a timer to do the write */
+ ide->device->machine().scheduler().timer_set(TIME_PER_SECTOR, FUNC(write_sector_done_callback), 0, ide);
+ }
+ }
+ else
+ {
+ /* set a timer to do the write */
+ ide->device->machine().scheduler().timer_set(TIME_PER_SECTOR, FUNC(write_sector_done_callback), 0, ide);
+ }
+}
+
+
+static void read_buffer_from_dma(ide_state *ide)
+{
+ int bytesleft = IDE_DISK_SECTOR_SIZE;
+ UINT8 *data = ide->buffer;
+
+// LOG(("Reading sector from %08X\n", ide->dma_address));
+
+ /* loop until we've consumed all bytes */
+ while (bytesleft--)
+ {
+ /* if we're out of space, grab the next descriptor */
+ if (ide->dma_bytes_left == 0)
+ {
+ /* if we're out of buffer space, that's bad */
+ if (ide->dma_last_buffer)
+ {
+ LOG(("DMA Out of buffer space!\n"));
+ return;
+ }
+
+ /* fetch the address */
+ ide->dma_address = ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor);
+ ide->dma_address |= ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor) << 8;
+ ide->dma_address |= ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor) << 16;
+ ide->dma_address |= ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor) << 24;
+ ide->dma_address &= 0xfffffffe;
+
+ /* fetch the length */
+ ide->dma_bytes_left = ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor);
+ ide->dma_bytes_left |= ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor) << 8;
+ ide->dma_bytes_left |= ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor) << 16;
+ ide->dma_bytes_left |= ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor) << 24;
+ ide->dma_last_buffer = (ide->dma_bytes_left >> 31) & 1;
+ ide->dma_bytes_left &= 0xfffe;
+ if (ide->dma_bytes_left == 0)
+ ide->dma_bytes_left = 0x10000;
+
+// LOG(("New DMA descriptor: address = %08X bytes = %04X last = %d\n", ide->dma_address, ide->dma_bytes_left, ide->dma_last_buffer));
+ }
+
+ /* read the next byte */
+ *data++ = ide->dma_space->read_byte(ide->dma_address++);
+ ide->dma_bytes_left--;
+ }
+}
+
+
+static void write_sector_done(ide_state *ide)
+{
+ int lba = lba_address(ide), count = 0;
+
+ /* now do the write */
+ if (ide->disk)
+ count = hard_disk_write(ide->disk, lba, ide->buffer);
+
+ /* by default, mark the buffer ready and the seek complete */
+ ide->status |= IDE_STATUS_BUFFER_READY;
+ ide->status |= IDE_STATUS_SEEK_COMPLETE;
+
+ /* and clear the busy adn error flags */
+ ide->status &= ~IDE_STATUS_ERROR;
+ ide->status &= ~IDE_STATUS_BUSY;
+
+ /* if we succeeded, advance to the next sector and set the nice bits */
+ if (count == 1)
+ {
+ /* advance the pointers, unless this is the last sector */
+ /* Gauntlet: Dark Legacy checks to make sure we stop on the last sector */
+ if (ide->sector_count != 1)
+ next_sector(ide);
+
+ /* clear the error value */
+ ide->error = IDE_ERROR_NONE;
+
+ /* signal an interrupt */
+ if (--ide->sectors_until_int == 0 || ide->sector_count == 1)
+ {
+ ide->sectors_until_int = ((ide->command == IDE_COMMAND_WRITE_MULTIPLE_BLOCK) ? ide->block_count : 1);
+ signal_interrupt(ide);
+ }
+
+ /* signal an interrupt if there's more data needed */
+ if (ide->sector_count > 0)
+ ide->sector_count--;
+ if (ide->sector_count == 0)
+ ide->status &= ~IDE_STATUS_BUFFER_READY;
+
+ /* keep going for DMA */
+ if (ide->dma_active && ide->sector_count != 0)
+ {
+ read_buffer_from_dma(ide);
+ continue_write(ide);
+ }
+ else
+ ide->dma_active = 0;
+ }
+
+ /* if we got an error, we need to report it */
+ else
+ {
+ /* set the error flag and the error */
+ ide->status |= IDE_STATUS_ERROR;
+ ide->error = IDE_ERROR_BAD_SECTOR;
+ ide->bus_master_status |= IDE_BUSMASTER_STATUS_ERROR;
+ ide->bus_master_status &= ~IDE_BUSMASTER_STATUS_ACTIVE;
+
+ /* signal an interrupt */
+ signal_interrupt(ide);
+ }
+}
+
+
+static TIMER_CALLBACK( write_sector_done_callback )
+{
+ write_sector_done((ide_state *)ptr);
+}
+
+
+
+/*************************************
+ *
+ * Handle IDE commands
+ *
+ *************************************/
+
+static void handle_command(ide_state *ide, UINT8 command)
+{
+ UINT8 key[5];
+
+ /* implicitly clear interrupts here */
+ clear_interrupt(ide);
+
+ ide->command = command;
+ switch (command)
+ {
+ case IDE_COMMAND_READ_MULTIPLE:
+ case IDE_COMMAND_READ_MULTIPLE_ONCE:
+ LOGPRINT(("IDE Read multiple: C=%d H=%d S=%d LBA=%d count=%d\n",
+ ide->cur_cylinder, ide->cur_head, ide->cur_sector, lba_address(ide), ide->sector_count));
+
+ /* reset the buffer */
+ ide->buffer_offset = 0;
+ ide->sectors_until_int = 1;
+ ide->dma_active = 0;
+ ide->verify_only = 0;
+
+ /* start the read going */
+ read_first_sector(ide);
+ break;
+
+ case IDE_COMMAND_READ_MULTIPLE_BLOCK:
+ LOGPRINT(("IDE Read multiple block: C=%d H=%d S=%d LBA=%d count=%d\n",
+ ide->cur_cylinder, ide->cur_head, ide->cur_sector, lba_address(ide), ide->sector_count));
+
+ /* reset the buffer */
+ ide->buffer_offset = 0;
+ ide->sectors_until_int = 1;
+ ide->dma_active = 0;
+ ide->verify_only = 0;
+
+ /* start the read going */
+ read_first_sector(ide);
+ break;
+
+ case IDE_COMMAND_VERIFY_MULTIPLE:
+ case IDE_COMMAND_VERIFY_NORETRY:
+ LOGPRINT(("IDE Read verify multiple with/without retries: C=%d H=%d S=%d LBA=%d count=%d\n",
+ ide->cur_cylinder, ide->cur_head, ide->cur_sector, lba_address(ide), ide->sector_count));
+
+ /* reset the buffer */
+ ide->buffer_offset = 0;
+ ide->sectors_until_int = 1;
+ ide->dma_active = 0;
+ ide->verify_only = 1;
+
+ /* start the read going */
+ read_first_sector(ide);
+ break;
+
+ case IDE_COMMAND_READ_DMA:
+ LOGPRINT(("IDE Read multiple DMA: C=%d H=%d S=%d LBA=%d count=%d\n",
+ ide->cur_cylinder, ide->cur_head, ide->cur_sector, lba_address(ide), ide->sector_count));
+
+ /* reset the buffer */
+ ide->buffer_offset = 0;
+ ide->sectors_until_int = ide->sector_count;
+ ide->dma_active = 1;
+ ide->verify_only = 0;
+
+ /* start the read going */
+ if (ide->bus_master_command & 1)
+ read_first_sector(ide);
+ break;
+
+ case IDE_COMMAND_WRITE_MULTIPLE:
+ LOGPRINT(("IDE Write multiple: C=%d H=%d S=%d LBA=%d count=%d\n",
+ ide->cur_cylinder, ide->cur_head, ide->cur_sector, lba_address(ide), ide->sector_count));
+
+ /* reset the buffer */
+ ide->buffer_offset = 0;
+ ide->sectors_until_int = 1;
+ ide->dma_active = 0;
+
+ /* mark the buffer ready */
+ ide->status |= IDE_STATUS_BUFFER_READY;
+ break;
+
+ case IDE_COMMAND_WRITE_MULTIPLE_BLOCK:
+ LOGPRINT(("IDE Write multiple block: C=%d H=%d S=%d LBA=%d count=%d\n",
+ ide->cur_cylinder, ide->cur_head, ide->cur_sector, lba_address(ide), ide->sector_count));
+
+ /* reset the buffer */
+ ide->buffer_offset = 0;
+ ide->sectors_until_int = 1;
+ ide->dma_active = 0;
+
+ /* mark the buffer ready */
+ ide->status |= IDE_STATUS_BUFFER_READY;
+ break;
+
+ case IDE_COMMAND_WRITE_DMA:
+ LOGPRINT(("IDE Write multiple DMA: C=%d H=%d S=%d LBA=%d count=%d\n",
+ ide->cur_cylinder, ide->cur_head, ide->cur_sector, lba_address(ide), ide->sector_count));
+
+ /* reset the buffer */
+ ide->buffer_offset = 0;
+ ide->sectors_until_int = ide->sector_count;
+ ide->dma_active = 1;
+
+ /* start the read going */
+ if (ide->bus_master_command & 1)
+ {
+ read_buffer_from_dma(ide);
+ continue_write(ide);
+ }
+ break;
+
+ case IDE_COMMAND_SECURITY_UNLOCK:
+ LOGPRINT(("IDE Security Unlock\n"));
+
+ /* reset the buffer */
+ ide->buffer_offset = 0;
+ ide->sectors_until_int = 0;
+ ide->dma_active = 0;
+
+ /* mark the buffer ready */
+ ide->status |= IDE_STATUS_BUFFER_READY;
+ signal_interrupt(ide);
+ break;
+
+ case IDE_COMMAND_GET_INFO:
+ LOGPRINT(("IDE Read features\n"));
+
+ /* reset the buffer */
+ ide->buffer_offset = 0;
+ ide->sector_count = 1;
+
+ /* build the features page */
+ memcpy(ide->buffer, ide->features, sizeof(ide->buffer));
+
+ /* indicate everything is ready */
+ ide->status |= IDE_STATUS_BUFFER_READY;
+ ide->status |= IDE_STATUS_SEEK_COMPLETE;
+ ide->status |= IDE_STATUS_DRIVE_READY;
+
+ /* and clear the busy adn error flags */
+ ide->status &= ~IDE_STATUS_ERROR;
+ ide->status &= ~IDE_STATUS_BUSY;
+
+ /* clear the error too */
+ ide->error = IDE_ERROR_NONE;
+
+ /* signal an interrupt */
+ signal_delayed_interrupt(ide, MINIMUM_COMMAND_TIME, 1);
+ break;
+
+ case IDE_COMMAND_DIAGNOSTIC:
+ ide->error = IDE_ERROR_DEFAULT;
+
+ /* signal an interrupt */
+ signal_interrupt(ide);
+ break;
+
+ case IDE_COMMAND_RECALIBRATE:
+ /* clear the error too */
+ ide->error = IDE_ERROR_NONE;
+
+ /* signal an interrupt */
+ signal_interrupt(ide);
+ break;
+
+ case IDE_COMMAND_IDLE:
+ /* clear the error too */
+ ide->error = IDE_ERROR_NONE;
+
+ /* for timeout disabled value is 0 */
+ ide->sector_count = 0;
+ /* signal an interrupt */
+ signal_interrupt(ide);
+ break;
+
+ case IDE_COMMAND_SET_CONFIG:
+ LOGPRINT(("IDE Set configuration (%d heads, %d sectors)\n", ide->cur_head + 1, ide->sector_count));
+ ide->status &= ~IDE_STATUS_ERROR;
+ ide->error = IDE_ERROR_NONE;
+
+ ide->num_sectors = ide->sector_count;
+ ide->num_heads = ide->cur_head + 1;
+
+ /* signal an interrupt */
+ signal_interrupt(ide);
+ break;
+
+ case IDE_COMMAND_UNKNOWN_F9:
+ /* only used by Killer Instinct AFAICT */
+ LOGPRINT(("IDE unknown command (F9)\n"));
+
+ /* signal an interrupt */
+ signal_interrupt(ide);
+ break;
+
+ case IDE_COMMAND_SET_FEATURES:
+ LOGPRINT(("IDE Set features (%02X %02X %02X %02X %02X)\n", ide->precomp_offset, ide->sector_count & 0xff, ide->cur_sector, ide->cur_cylinder & 0xff, ide->cur_cylinder >> 8));
+
+ /* signal an interrupt */
+ signal_delayed_interrupt(ide, MINIMUM_COMMAND_TIME, 0);
+ break;
+
+ case IDE_COMMAND_SET_BLOCK_COUNT:
+ LOGPRINT(("IDE Set block count (%02X)\n", ide->sector_count));
+
+ ide->block_count = ide->sector_count;
+ // judge dredd wants 'drive ready' on this command
+ ide->status |= IDE_STATUS_DRIVE_READY;
+
+ /* signal an interrupt */
+ signal_interrupt(ide);
+ break;
+
+ case IDE_COMMAND_TAITO_GNET_UNLOCK_1:
+ LOGPRINT(("IDE GNET Unlock 1\n"));
+
+ ide->sector_count = 1;
+ ide->status |= IDE_STATUS_DRIVE_READY;
+ ide->status &= ~IDE_STATUS_ERROR;
+ signal_interrupt(ide);
+ break;
+
+ case IDE_COMMAND_TAITO_GNET_UNLOCK_2:
+ LOGPRINT(("IDE GNET Unlock 2\n"));
+
+ /* reset the buffer */
+ ide->buffer_offset = 0;
+ ide->sectors_until_int = 0;
+ ide->dma_active = 0;
+
+ /* mark the buffer ready */
+ ide->status |= IDE_STATUS_BUFFER_READY;
+ signal_interrupt(ide);
+ break;
+
+ case IDE_COMMAND_TAITO_GNET_UNLOCK_3:
+ LOGPRINT(("IDE GNET Unlock 3\n"));
+
+ /* key check */
+ chd_get_metadata (ide->handle, HARD_DISK_KEY_METADATA_TAG, 0, key, 5, 0, 0, 0);
+ if ((ide->precomp_offset == key[0]) && (ide->sector_count == key[1]) && (ide->cur_sector == key[2]) && (ide->cur_cylinder == (((UINT16)key[4]<<8)|key[3])))
+ {
+ ide->gnetreadlock= 0;
+ }
+
+ /* update flags */
+ ide->status |= IDE_STATUS_DRIVE_READY;
+ ide->status &= ~IDE_STATUS_ERROR;
+ signal_interrupt(ide);
+ break;
+
+ case IDE_COMMAND_SEEK:
+ /*
+ cur_cylinder, cur_sector and cur_head
+ are all already set in this case so no need
+ so that implements actual seek
+ */
+ /* clear the error too */
+ ide->error = IDE_ERROR_NONE;
+
+ /* for timeout disabled value is 0 */
+ ide->sector_count = 0;
+ /* signal an interrupt */
+ signal_interrupt(ide);
+ break;
+
+
+ default:
+ LOGPRINT(("IDE unknown command (%02X)\n", command));
+ ide->status |= IDE_STATUS_ERROR;
+ ide->error = IDE_ERROR_UNKNOWN_COMMAND;
+ signal_interrupt(ide);
+ //debugger_break(ide->device->machine());
+ break;
+ }
+}
+
+
+
+/*************************************
+ *
+ * IDE controller read
+ *
+ *************************************/
+
+static UINT32 ide_controller_read(device_t *device, int bank, offs_t offset, int size)
+{
+ ide_state *ide = get_safe_token(device);
+ UINT32 result = 0;
+
+ /* logit */
+// if (BANK(bank, offset) != IDE_BANK0_DATA && BANK(bank, offset) != IDE_BANK0_STATUS_COMMAND && BANK(bank, offset) != IDE_BANK1_STATUS_CONTROL)
+ LOG(("%s:IDE read at %d:%X, size=%d\n", device->machine().describe_context(), bank, offset, size));
+
+ switch (BANK(bank, offset))
+ {
+ /* unknown config register */
+ case IDE_BANK2_CONFIG_UNK:
+ return ide->config_unknown;
+
+ /* active config register */
+ case IDE_BANK2_CONFIG_REGISTER:
+ return ide->config_register_num;
+
+ /* data from active config register */
+ case IDE_BANK2_CONFIG_DATA:
+ if (ide->config_register_num < IDE_CONFIG_REGISTERS)
+ return ide->config_register[ide->config_register_num];
+ return 0;
+
+ /* read data if there's data to be read */
+ case IDE_BANK0_DATA:
+ if (ide->status & IDE_STATUS_BUFFER_READY)
+ {
+ /* fetch the correct amount of data */
+ result = ide->buffer[ide->buffer_offset++];
+ if (size > 1)
+ result |= ide->buffer[ide->buffer_offset++] << 8;
+ if (size > 2)
+ {
+ result |= ide->buffer[ide->buffer_offset++] << 16;
+ result |= ide->buffer[ide->buffer_offset++] << 24;
+ }
+
+ /* if we're at the end of the buffer, handle it */
+ if (ide->buffer_offset >= IDE_DISK_SECTOR_SIZE)
+ {
+ LOG(("%s:IDE completed PIO read\n", device->machine().describe_context()));
+ continue_read(ide);
+ ide->error = IDE_ERROR_DEFAULT;
+ }
+ }
+ break;
+
+ /* return the current error */
+ case IDE_BANK0_ERROR:
+ return ide->error;
+
+ /* return the current sector count */
+ case IDE_BANK0_SECTOR_COUNT:
+ return ide->sector_count;
+
+ /* return the current sector */
+ case IDE_BANK0_SECTOR_NUMBER:
+ return ide->cur_sector;
+
+ /* return the current cylinder LSB */
+ case IDE_BANK0_CYLINDER_LSB:
+ return ide->cur_cylinder & 0xff;
+
+ /* return the current cylinder MSB */
+ case IDE_BANK0_CYLINDER_MSB:
+ return ide->cur_cylinder >> 8;
+
+ /* return the current head */
+ case IDE_BANK0_HEAD_NUMBER:
+ return ide->cur_head_reg;
+
+ /* return the current status and clear any pending interrupts */
+ case IDE_BANK0_STATUS_COMMAND:
+ /* return the current status but don't clear interrupts */
+ case IDE_BANK1_STATUS_CONTROL:
+ result = ide->status;
+ if (ide->last_status_timer->elapsed() > TIME_PER_ROTATION)
+ {
+ result |= IDE_STATUS_HIT_INDEX;
+ ide->last_status_timer->adjust(attotime::never);
+ }
+
+ /* clear interrutps only when reading the real status */
+ if (BANK(bank, offset) == IDE_BANK0_STATUS_COMMAND)
+ {
+ if (ide->interrupt_pending)
+ clear_interrupt(ide);
+ }
+ break;
+
+ /* log anything else */
+ default:
+ logerror("%s:unknown IDE read at %03X, size=%d\n", device->machine().describe_context(), offset, size);
+ break;
+ }
+
+ /* return the result */
+ return result;
+}
+
+
+
+/*************************************
+ *
+ * IDE controller write
+ *
+ *************************************/
+
+static void ide_controller_write(device_t *device, int bank, offs_t offset, int size, UINT32 data)
+{
+ ide_state *ide = get_safe_token(device);
+
+ /* logit */
+ if (BANK(bank, offset) != IDE_BANK0_DATA)
+ LOG(("%s:IDE write to %d:%X = %08X, size=%d\n", device->machine().describe_context(), bank, offset, data, size));
+ // fprintf(stderr, "ide write %03x %02x size=%d\n", offset, data, size);
+ switch (BANK(bank, offset))
+ {
+ /* unknown config register */
+ case IDE_BANK2_CONFIG_UNK:
+ ide->config_unknown = data;
+ break;
+
+ /* active config register */
+ case IDE_BANK2_CONFIG_REGISTER:
+ ide->config_register_num = data;
+ break;
+
+ /* data from active config register */
+ case IDE_BANK2_CONFIG_DATA:
+ if (ide->config_register_num < IDE_CONFIG_REGISTERS)
+ ide->config_register[ide->config_register_num] = data;
+ break;
+
+ /* write data */
+ case IDE_BANK0_DATA:
+ if (ide->status & IDE_STATUS_BUFFER_READY)
+ {
+ /* store the correct amount of data */
+ ide->buffer[ide->buffer_offset++] = data;
+ if (size > 1)
+ ide->buffer[ide->buffer_offset++] = data >> 8;
+ if (size > 2)
+ {
+ ide->buffer[ide->buffer_offset++] = data >> 16;
+ ide->buffer[ide->buffer_offset++] = data >> 24;
+ }
+
+ /* if we're at the end of the buffer, handle it */
+ if (ide->buffer_offset >= IDE_DISK_SECTOR_SIZE)
+ {
+ LOG(("%s:IDE completed PIO write\n", device->machine().describe_context()));
+ if (ide->command == IDE_COMMAND_SECURITY_UNLOCK)
+ {
+ if (ide->user_password_enable && memcmp(ide->buffer, ide->user_password, 2 + 32) == 0)
+ {
+ LOGPRINT(("IDE Unlocked user password\n"));
+ ide->user_password_enable = 0;
+ }
+ if (ide->master_password_enable && memcmp(ide->buffer, ide->master_password, 2 + 32) == 0)
+ {
+ LOGPRINT(("IDE Unlocked master password\n"));
+ ide->master_password_enable = 0;
+ }
+ if (PRINTF_IDE_PASSWORD)
+ {
+ int i;
+
+ for (i = 0; i < 34; i += 2)
+ {
+ if (i % 8 == 2)
+ mame_printf_debug("\n");
+
+ mame_printf_debug("0x%02x, 0x%02x, ", ide->buffer[i], ide->buffer[i + 1]);
+ //mame_printf_debug("0x%02x%02x, ", ide->buffer[i], ide->buffer[i + 1]);
+ }
+ mame_printf_debug("\n");
+ }
+
+ /* clear the busy and error flags */
+ ide->status &= ~IDE_STATUS_ERROR;
+ ide->status &= ~IDE_STATUS_BUSY;
+ ide->status &= ~IDE_STATUS_BUFFER_READY;
+
+ if (ide->master_password_enable || ide->user_password_enable)
+ security_error(ide);
+ else
+ ide->status |= IDE_STATUS_DRIVE_READY;
+ }
+ else if (ide->command == IDE_COMMAND_TAITO_GNET_UNLOCK_2)
+ {
+ UINT8 key[5] = { 0, 0, 0, 0, 0 };
+ int i, bad = 0;
+ chd_get_metadata (ide->handle, HARD_DISK_KEY_METADATA_TAG, 0, key, 5, 0, 0, 0);
+
+ for (i=0; !bad && i<512; i++)
+ bad = ((i < 2 || i >= 7) && ide->buffer[i]) || ((i >= 2 && i < 7) && ide->buffer[i] != key[i-2]);
+
+ ide->status &= ~IDE_STATUS_BUSY;
+ ide->status &= ~IDE_STATUS_BUFFER_READY;
+ if (bad)
+ ide->status |= IDE_STATUS_ERROR;
+ else {
+ ide->status &= ~IDE_STATUS_ERROR;
+ ide->gnetreadlock= 0;
+ }
+ }
+ else
+ continue_write(ide);
+
+ }
+ }
+ break;
+
+ /* precompensation offset?? */
+ case IDE_BANK0_ERROR:
+ ide->precomp_offset = data;
+ break;
+
+ /* sector count */
+ case IDE_BANK0_SECTOR_COUNT:
+ ide->sector_count = data ? data : 256;
+ break;
+
+ /* current sector */
+ case IDE_BANK0_SECTOR_NUMBER:
+ ide->cur_sector = data;
+ break;
+
+ /* current cylinder LSB */
+ case IDE_BANK0_CYLINDER_LSB:
+ ide->cur_cylinder = (ide->cur_cylinder & 0xff00) | (data & 0xff);
+ break;
+
+ /* current cylinder MSB */
+ case IDE_BANK0_CYLINDER_MSB:
+ ide->cur_cylinder = (ide->cur_cylinder & 0x00ff) | ((data & 0xff) << 8);
+ break;
+
+ /* current head */
+ case IDE_BANK0_HEAD_NUMBER:
+ ide->cur_head = data & 0x0f;
+ ide->cur_head_reg = data;
+ // drive index = data & 0x10
+ // LBA mode = data & 0x40
+ break;
+
+ /* command */
+ case IDE_BANK0_STATUS_COMMAND:
+ handle_command(ide, data);
+ break;
+
+ /* adapter control */
+ case IDE_BANK1_STATUS_CONTROL:
+ ide->adapter_control = data;
+
+ /* handle controller reset */
+ //if (data == 0x04)
+ if (data & 0x04)
+ {
+ ide->status |= IDE_STATUS_BUSY;
+ ide->status &= ~IDE_STATUS_DRIVE_READY;
+ ide->reset_timer->adjust(attotime::from_msec(5));
+ }
+ break;
+ }
+}
+
+
+
+/*************************************
+ *
+ * Bus master read
+ *
+ *************************************/
+
+static UINT32 ide_bus_master_read(device_t *device, offs_t offset, int size)
+{
+ ide_state *ide = get_safe_token(device);
+
+ LOG(("%s:ide_bus_master_read(%d, %d)\n", device->machine().describe_context(), offset, size));
+
+ /* command register */
+ if (offset == 0)
+ return ide->bus_master_command | (ide->bus_master_status << 16);
+
+ /* status register */
+ if (offset == 2)
+ return ide->bus_master_status;
+
+ /* descriptor table register */
+ if (offset == 4)
+ return ide->bus_master_descriptor;
+
+ return 0xffffffff;
+}
+
+
+
+/*************************************
+ *
+ * Bus master write
+ *
+ *************************************/
+
+static void ide_bus_master_write(device_t *device, offs_t offset, int size, UINT32 data)
+{
+ ide_state *ide = get_safe_token(device);
+
+ LOG(("%s:ide_bus_master_write(%d, %d, %08X)\n", device->machine().describe_context(), offset, size, data));
+
+ /* command register */
+ if (offset == 0)
+ {
+ UINT8 old = ide->bus_master_command;
+ UINT8 val = data & 0xff;
+
+ /* save the read/write bit and the start/stop bit */
+ ide->bus_master_command = (old & 0xf6) | (val & 0x09);
+ ide->bus_master_status = (ide->bus_master_status & ~IDE_BUSMASTER_STATUS_ACTIVE) | (val & 0x01);
+
+ /* handle starting a transfer */
+ if (!(old & 1) && (val & 1))
+ {
+ /* reset all the DMA data */
+ ide->dma_bytes_left = 0;
+ ide->dma_last_buffer = 0;
+ ide->dma_descriptor = ide->bus_master_descriptor;
+
+ /* if we're going live, start the pending read/write */
+ if (ide->dma_active)
+ {
+ if (ide->bus_master_command & 8)
+ read_next_sector(ide);
+ else
+ {
+ read_buffer_from_dma(ide);
+ continue_write(ide);
+ }
+ }
+ }
+ }
+
+ /* status register */
+ if (offset <= 2 && offset + size > 2)
+ {
+ UINT8 old = ide->bus_master_status;
+ UINT8 val = data >> (8 * (2 - offset));
+
+ /* save the DMA capable bits */
+ ide->bus_master_status = (old & 0x9f) | (val & 0x60);
+
+ /* clear interrupt and error bits */
+ if (val & IDE_BUSMASTER_STATUS_IRQ)
+ ide->bus_master_status &= ~IDE_BUSMASTER_STATUS_IRQ;
+ if (val & IDE_BUSMASTER_STATUS_ERROR)
+ ide->bus_master_status &= ~IDE_BUSMASTER_STATUS_ERROR;
+ }
+
+ /* descriptor table register */
+ if (offset == 4)
+ ide->bus_master_descriptor = data & 0xfffffffc;
+}
+
+
+
+/*************************************
+ *
+ * IDE direct handlers (16-bit)
+ *
+ *************************************/
+
+/*
+ ide_bus_r()
+
+ Read a 16-bit word from the IDE bus directly.
+
+ select: 0->CS1Fx active, 1->CS3Fx active
+ offset: register offset (state of DA2-DA0)
+*/
+int ide_bus_r(device_t *device, int select, int offset)
+{
+ return ide_controller_read(device, select ? 1 : 0, offset, select == 0 && offset == 0 ? 2 : 1);
+}
+
+/*
+ ide_bus_w()
+
+ Write a 16-bit word to the IDE bus directly.
+
+ select: 0->CS1Fx active, 1->CS3Fx active
+ offset: register offset (state of DA2-DA0)
+ data: data written (state of D0-D15 or D0-D7)
+*/
+void ide_bus_w(device_t *device, int select, int offset, int data)
+{
+ if (select == 0 && offset == 0)
+ ide_controller_write(device, 0, 0, 2, data);
+ else
+ ide_controller_write(device, select ? 1 : 0, offset, 1, data & 0xff);
+}
+
+UINT32 ide_controller_r(device_t *device, int reg, int size)
+{
+ if (reg >= 0x1f0 && reg < 0x1f8)
+ return ide_controller_read(device, 0, reg & 7, size);
+ if (reg >= 0x3f0 && reg < 0x3f8)
+ return ide_controller_read(device, 1, reg & 7, size);
+ if (reg >= 0x030 && reg < 0x040)
+ return ide_controller_read(device, 2, reg & 0xf, size);
+ return 0xffffffff;
+}
+
+void ide_controller_w(device_t *device, int reg, int size, UINT32 data)
+{
+ if (reg >= 0x1f0 && reg < 0x1f8)
+ ide_controller_write(device, 0, reg & 7, size, data);
+ if (reg >= 0x3f0 && reg < 0x3f8)
+ ide_controller_write(device, 1, reg & 7, size, data);
+ if (reg >= 0x030 && reg < 0x040)
+ ide_controller_write(device, 2, reg & 0xf, size, data);
+}
+
+
+/*************************************
+ *
+ * 32-bit IDE handlers
+ *
+ *************************************/
+
+READ32_DEVICE_HANDLER( ide_controller32_r )
+{
+ int size;
+
+ offset *= 4;
+ size = convert_to_offset_and_size32(&offset, mem_mask);
+
+ return ide_controller_r(device, offset, size) << ((offset & 3) * 8);
+}
+
+
+WRITE32_DEVICE_HANDLER( ide_controller32_w )
+{
+ int size;
+
+ offset *= 4;
+ size = convert_to_offset_and_size32(&offset, mem_mask);
+ data = data >> ((offset & 3) * 8);
+
+ ide_controller_w(device, offset, size, data);
+}
+
+
+READ32_DEVICE_HANDLER( ide_controller32_pcmcia_r )
+{
+ int size;
+ UINT32 res = 0xffffffff;
+
+ offset *= 4;
+ size = convert_to_offset_and_size32(&offset, mem_mask);
+
+ if (offset >= 0x000 && offset < 0x008)
+ res = ide_controller_read(device, 0, offset & 7, size);
+ if (offset >= 0x008 && offset < 0x010)
+ res = ide_controller_read(device, 1, offset & 7, size);
+
+ return res << ((offset & 3) * 8);
+}
+
+
+WRITE32_DEVICE_HANDLER( ide_controller32_pcmcia_w )
+{
+ int size;
+
+ offset *= 4;
+ size = convert_to_offset_and_size32(&offset, mem_mask);
+ data = data >> ((offset & 3) * 8);
+
+ if (offset >= 0x000 && offset < 0x008)
+ ide_controller_write(device, 0, offset & 7, size, data);
+ if (offset >= 0x008 && offset < 0x010)
+ ide_controller_write(device, 1, offset & 7, size, data);
+}
+
+READ32_DEVICE_HANDLER( ide_bus_master32_r )
+{
+ int size;
+
+ offset *= 4;
+ size = convert_to_offset_and_size32(&offset, mem_mask);
+
+ return ide_bus_master_read(device, offset, size) << ((offset & 3) * 8);
+}
+
+
+WRITE32_DEVICE_HANDLER( ide_bus_master32_w )
+{
+ int size;
+
+ offset *= 4;
+ size = convert_to_offset_and_size32(&offset, mem_mask);
+
+ ide_bus_master_write(device, offset, size, data >> ((offset & 3) * 8));
+}
+
+
+
+/*************************************
+ *
+ * 16-bit IDE handlers
+ *
+ *************************************/
+
+READ16_DEVICE_HANDLER( ide_controller16_r )
+{
+ int size;
+
+ offset *= 2;
+ size = convert_to_offset_and_size16(&offset, mem_mask);
+
+ return ide_controller_r(device, offset, size) << ((offset & 1) * 8);
+}
+
+
+WRITE16_DEVICE_HANDLER( ide_controller16_w )
+{
+ int size;
+
+ offset *= 2;
+ size = convert_to_offset_and_size16(&offset, mem_mask);
+
+ ide_controller_w(device, offset, size, data >> ((offset & 1) * 8));
+}
+
+
+
+/***************************************************************************
+ DEVICE INTERFACE
+***************************************************************************/
+
+/*-------------------------------------------------
+ device start callback
+-------------------------------------------------*/
+
+static DEVICE_START( ide_controller )
+{
+ ide_state *ide = get_safe_token(device);
+ const hard_disk_info *hdinfo;
+ const ide_config *config;
+
+ /* validate some basic stuff */
+ assert(device != NULL);
+ assert(device->static_config() == NULL);
+ assert(downcast<const legacy_device_base *>(device)->inline_config() != NULL);
+
+ /* store a pointer back to the device */
+ ide->device = device;
+
+ /* set MAME harddisk handle */
+ config = (const ide_config *)downcast<const legacy_device_base *>(device)->inline_config();
+ ide->handle = get_disk_handle(device->machine(), (config->master != NULL) ? config->master : device->tag());
+ ide->disk = hard_disk_open(ide->handle);
+ assert_always(config->slave == NULL, "IDE controller does not yet support slave drives\n");
+
+ /* find the bus master space */
+ if (config->bmcpu != NULL)
+ {
+ device_t *bmtarget = device->machine().device(config->bmcpu);
+ if (bmtarget == NULL)
+ throw emu_fatalerror("IDE controller '%s' bus master target '%s' doesn't exist!", device->tag(), config->bmcpu);
+ device_memory_interface *memory;
+ if (!bmtarget->interface(memory))
+ throw emu_fatalerror("IDE controller '%s' bus master target '%s' has no memory!", device->tag(), config->bmcpu);
+ ide->dma_space = memory->space(config->bmspace);
+ if (ide->dma_space == NULL)
+ throw emu_fatalerror("IDE controller '%s' bus master target '%s' does not have specified space %d!", device->tag(), config->bmcpu, config->bmspace);
+ ide->dma_address_xor = (ide->dma_space->endianness() == ENDIANNESS_LITTLE) ? 0 : 3;
+ }
+
+ /* get and copy the geometry */
+ if (ide->disk != NULL)
+ {
+ hdinfo = hard_disk_get_info(ide->disk);
+ if (hdinfo->sectorbytes == IDE_DISK_SECTOR_SIZE)
+ {
+ ide->num_cylinders = hdinfo->cylinders;
+ ide->num_sectors = hdinfo->sectors;
+ ide->num_heads = hdinfo->heads;
+ if (PRINTF_IDE_COMMANDS) mame_printf_debug("CHS: %d %d %d\n", ide->num_cylinders, ide->num_heads, ide->num_sectors);
+ }
+
+ /* build the features page */
+ ide_build_features(ide);
+ }
+
+ /* create a timer for timing status */
+ ide->last_status_timer = device->machine().scheduler().timer_alloc(FUNC_NULL);
+ ide->reset_timer = device->machine().scheduler().timer_alloc(FUNC(reset_callback), (void *)device);
+
+ /* register ide states */
+ device->save_item(NAME(ide->adapter_control));
+ device->save_item(NAME(ide->status));
+ device->save_item(NAME(ide->error));
+ device->save_item(NAME(ide->command));
+ device->save_item(NAME(ide->interrupt_pending));
+ device->save_item(NAME(ide->precomp_offset));
+
+ device->save_item(NAME(ide->buffer));
+ device->save_item(NAME(ide->features));
+ device->save_item(NAME(ide->buffer_offset));
+ device->save_item(NAME(ide->sector_count));
+
+ device->save_item(NAME(ide->block_count));
+ device->save_item(NAME(ide->sectors_until_int));
+
+ device->save_item(NAME(ide->dma_active));
+ device->save_item(NAME(ide->dma_last_buffer));
+ device->save_item(NAME(ide->dma_address));
+ device->save_item(NAME(ide->dma_descriptor));
+ device->save_item(NAME(ide->dma_bytes_left));
+
+ device->save_item(NAME(ide->bus_master_command));
+ device->save_item(NAME(ide->bus_master_status));
+ device->save_item(NAME(ide->bus_master_descriptor));
+
+ device->save_item(NAME(ide->cur_cylinder));
+ device->save_item(NAME(ide->cur_sector));
+ device->save_item(NAME(ide->cur_head));
+ device->save_item(NAME(ide->cur_head_reg));
+
+ device->save_item(NAME(ide->cur_lba));
+
+ device->save_item(NAME(ide->num_cylinders));
+ device->save_item(NAME(ide->num_sectors));
+ device->save_item(NAME(ide->num_heads));
+
+ device->save_item(NAME(ide->config_unknown));
+ device->save_item(NAME(ide->config_register));
+ device->save_item(NAME(ide->config_register_num));
+
+ device->save_item(NAME(ide->master_password_enable));
+ device->save_item(NAME(ide->user_password_enable));
+
+ device->save_item(NAME(ide->gnetreadlock));
+}
+
+
+/*-------------------------------------------------
+ device exit callback
+-------------------------------------------------*/
+
+static DEVICE_STOP( ide_controller )
+{
+ ide_state *ide = get_safe_token(device);
+
+ /* close the hard disk */
+ if (ide->disk != NULL)
+ hard_disk_close(ide->disk);
+}
+
+
+/*-------------------------------------------------
+ device reset callback
+-------------------------------------------------*/
+
+static DEVICE_RESET( ide_controller )
+{
+ ide_state *ide = get_safe_token(device);
+
+ LOG(("IDE controller reset performed\n"));
+ astring hardtag;
+ device->siblingtag(hardtag, "harddisk");
+
+ if (device->machine().device( hardtag.cstr() )) {
+ if (!ide->disk)
+ {
+ ide->handle = device->machine().device<harddisk_image_device>(hardtag.cstr())->get_chd_file(); // should be config->master
+
+ if (ide->handle)
+ {
+ ide->disk = device->machine().device<harddisk_image_device>(hardtag.cstr())->get_hard_disk_file(); // should be config->master
+
+ if (ide->disk != NULL)
+ {
+ const hard_disk_info *hdinfo;
+
+ hdinfo = hard_disk_get_info(ide->disk);
+ if (hdinfo->sectorbytes == IDE_DISK_SECTOR_SIZE)
+ {
+ ide->num_cylinders = hdinfo->cylinders;
+ ide->num_sectors = hdinfo->sectors;
+ ide->num_heads = hdinfo->heads;
+ if (PRINTF_IDE_COMMANDS) printf("CHS: %d %d %d\n", ide->num_cylinders, ide->num_heads, ide->num_sectors);
+ }
+
+ /* build the features page */
+ ide_build_features(ide);
+ }
+ }
+ }
+ }
+
+ /* reset the drive state */
+ ide->status = IDE_STATUS_DRIVE_READY | IDE_STATUS_SEEK_COMPLETE;
+ ide->error = IDE_ERROR_DEFAULT;
+ ide->buffer_offset = 0;
+ ide->gnetreadlock = 0;
+ ide->master_password_enable = (ide->master_password != NULL);
+ ide->user_password_enable = (ide->user_password != NULL);
+ clear_interrupt(ide);
+}
+
+
+/*-------------------------------------------------
+ device get info callback
+-------------------------------------------------*/
+
+DEVICE_GET_INFO( ide_controller )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(ide_state); break;
+ case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = sizeof(ide_config); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(ide_controller); break;
+ case DEVINFO_FCT_STOP: info->stop = DEVICE_STOP_NAME(ide_controller); break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(ide_controller);break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "IDE Controller"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Disk Controller"); 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;
+ }
+}
+
+
+DEFINE_LEGACY_DEVICE(IDE_CONTROLLER, ide_controller);
diff --git a/trunk/src/emu/machine/idectrl.h b/trunk/src/emu/machine/idectrl.h
new file mode 100644
index 00000000000..3b27e8588aa
--- /dev/null
+++ b/trunk/src/emu/machine/idectrl.h
@@ -0,0 +1,89 @@
+/***************************************************************************
+
+ idectrl.h
+
+ Generic (PC-style) IDE controller implementation.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __IDECTRL_H__
+#define __IDECTRL_H__
+
+#include "devlegcy.h"
+
+#include "harddisk.h"
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _ide_config ide_config;
+struct _ide_config
+{
+ void (*interrupt)(device_t *device, int state);
+ const char *master; /* name of master region (defaults to device tag) */
+ const char *slave; /* name of slave region (defaults to NULL) */
+ const char *bmcpu; /* name of bus master CPU */
+ UINT32 bmspace; /* address space of bus master transfer */
+};
+
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_IDE_CONTROLLER_ADD(_tag, _callback) \
+ MCFG_DEVICE_ADD(_tag, IDE_CONTROLLER, 0) \
+ MCFG_DEVICE_CONFIG_DATAPTR(ide_config, interrupt, _callback)
+
+#define MCFG_IDE_CONTROLLER_REGIONS(_master, _slave) \
+ MCFG_DEVICE_CONFIG_DATAPTR(ide_config, master, _master) \
+ MCFG_DEVICE_CONFIG_DATAPTR(ide_config, master, _slave)
+
+#define MCFG_IDE_BUS_MASTER_SPACE(_cpu, _space) \
+ MCFG_DEVICE_CONFIG_DATAPTR(ide_config, bmcpu, _cpu) \
+ MCFG_DEVICE_CONFIG_DATA32(ide_config, bmspace, AS_##_space)
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+UINT8 *ide_get_features(device_t *device);
+
+void ide_set_master_password(device_t *device, const UINT8 *password);
+void ide_set_user_password(device_t *device, const UINT8 *password);
+
+void ide_set_gnet_readlock(device_t *device, const UINT8 onoff);
+
+int ide_bus_r(device_t *config, int select, int offset);
+void ide_bus_w(device_t *config, int select, int offset, int data);
+
+UINT32 ide_controller_r(device_t *config, int reg, int size);
+void ide_controller_w(device_t *config, int reg, int size, UINT32 data);
+
+READ32_DEVICE_HANDLER( ide_controller32_r );
+WRITE32_DEVICE_HANDLER( ide_controller32_w );
+READ32_DEVICE_HANDLER( ide_controller32_pcmcia_r );
+WRITE32_DEVICE_HANDLER( ide_controller32_pcmcia_w );
+READ32_DEVICE_HANDLER( ide_bus_master32_r );
+WRITE32_DEVICE_HANDLER( ide_bus_master32_w );
+
+READ16_DEVICE_HANDLER( ide_controller16_r );
+WRITE16_DEVICE_HANDLER( ide_controller16_w );
+
+
+/* ----- device interface ----- */
+
+DECLARE_LEGACY_DEVICE(IDE_CONTROLLER, ide_controller);
+
+
+#endif /* __IDECTRL_H__ */
diff --git a/trunk/src/emu/machine/ins8154.c b/trunk/src/emu/machine/ins8154.c
new file mode 100644
index 00000000000..57e37387cf9
--- /dev/null
+++ b/trunk/src/emu/machine/ins8154.c
@@ -0,0 +1,271 @@
+/***************************************************************************
+
+ National Semiconductor INS8154
+
+ N-Channel 128-by-8 Bit RAM Input/Output (RAM I/O)
+
+
+ TODO: Strobed modes
+
+***************************************************************************/
+
+#include "emu.h"
+#include "ins8154.h"
+#include "devhelpr.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define VERBOSE 1
+
+/* Mode Definition Register */
+enum
+{
+ MDR_BASIC = 0x00,
+ MDR_STROBED_INPUT = 0x20,
+ MDR_STROBED_OUTPUT = 0x60,
+ MDR_STROBED_OUTPUT_3STATE = 0xe0
+};
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type INS8154 = &device_creator<ins8154_device>;
+
+//-------------------------------------------------
+// ins8154_device - constructor
+//-------------------------------------------------
+
+ins8154_device::ins8154_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, INS8154, "INS8154", tag, owner, clock)
+{
+
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void ins8154_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const ins8154_interface *intf = reinterpret_cast<const ins8154_interface *>(static_config());
+ if (intf != NULL)
+ {
+ *static_cast<ins8154_interface *>(this) = *intf;
+ }
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_in_a_cb, 0, sizeof(m_in_a_cb));
+ memset(&m_in_b_cb, 0, sizeof(m_in_b_cb));
+ memset(&m_out_a_cb, 0, sizeof(m_out_a_cb));
+ memset(&m_out_b_cb, 0, sizeof(m_out_b_cb));
+ memset(&m_out_irq_cb, 0, sizeof(m_out_irq_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void ins8154_device::device_start()
+{
+ /* resolve callbacks */
+ m_in_a_func.resolve(m_in_a_cb, *this);
+ m_out_a_func.resolve(m_out_a_cb, *this);
+ m_in_b_func.resolve(m_in_b_cb, *this);
+ m_out_b_func.resolve(m_out_b_cb, *this);
+ m_out_irq_func.resolve(m_out_irq_cb, *this);
+
+ /* register for state saving */
+ save_item(NAME(m_in_a));
+ save_item(NAME(m_in_b));
+ save_item(NAME(m_out_a));
+ save_item(NAME(m_out_b));
+ save_item(NAME(m_mdr));
+ save_item(NAME(m_odra));
+ save_item(NAME(m_odrb));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void ins8154_device::device_reset()
+{
+ m_in_a = 0;
+ m_in_b = 0;
+ m_out_a = 0;
+ m_out_b = 0;
+ m_mdr = 0;
+ m_odra = 0;
+ m_odrb = 0;
+}
+
+
+READ8_DEVICE_HANDLER_TRAMPOLINE(ins8154, ins8154_r)
+{
+ UINT8 val = 0xff;
+
+ if (offset > 0x24)
+ {
+ if (VERBOSE)
+ {
+ logerror("%s: INS8154 '%s' Read from invalid offset %02x!\n", machine().describe_context(), tag(), offset);
+ }
+ return 0xff;
+ }
+
+ switch (offset)
+ {
+ case 0x20:
+ if(!m_in_a_func.isnull())
+ {
+ val = m_in_a_func(0);
+ }
+ m_in_a = val;
+ break;
+
+ case 0x21:
+ if(!m_in_b_func.isnull())
+ {
+ val = m_in_b_func(0);
+ }
+ m_in_b = val;
+ break;
+
+ default:
+ if (offset < 0x08)
+ {
+ if(!m_in_a_func.isnull())
+ {
+ val = (m_in_a_func(0) << (8 - offset)) & 0x80;
+ }
+ m_in_a = val;
+ }
+ else
+ {
+ if(!m_in_b_func.isnull())
+ {
+ val = (m_in_b_func(0) << (8 - (offset >> 4))) & 0x80;
+ }
+ m_in_b = val;
+ }
+ break;
+ }
+
+ return val;
+}
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(ins8154, ins8154_porta_w)
+{
+ m_out_a = data;
+
+ /* Test if any pins are set as outputs */
+ if (m_odra)
+ {
+ m_out_a_func(0, (data & m_odra) | (m_odra ^ 0xff));
+ }
+}
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(ins8154, ins8154_portb_w)
+{
+ m_out_b = data;
+
+ /* Test if any pins are set as outputs */
+ if (m_odrb)
+ {
+ m_out_b_func(0, (data & m_odrb) | (m_odrb ^ 0xff));
+ }
+}
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(ins8154, ins8154_w)
+{
+ if (offset > 0x24)
+ {
+ if (VERBOSE)
+ {
+ logerror("%s: INS8154 '%s' Write %02x to invalid offset %02x!\n", machine().describe_context(), tag(), data, offset);
+ }
+ return;
+ }
+
+ switch (offset)
+ {
+ case 0x20:
+ ins8154_porta_w(0, data);
+ break;
+
+ case 0x21:
+ ins8154_portb_w(0, data);
+ break;
+
+ case 0x22:
+ if (VERBOSE)
+ {
+ logerror("%s: INS8154 '%s' ODRA set to %02x\n", machine().describe_context(), tag(), data);
+ }
+
+ m_odra = data;
+ break;
+
+ case 0x23:
+ if (VERBOSE)
+ {
+ logerror("%s: INS8154 '%s' ODRB set to %02x\n", machine().describe_context(), tag(), data);
+ }
+
+ m_odrb = data;
+ break;
+
+ case 0x24:
+ if (VERBOSE)
+ {
+ logerror("%s: INS8154 '%s' MDR set to %02x\n", machine().describe_context(), tag(), data);
+ }
+
+ m_mdr = data;
+ break;
+
+ default:
+ if (offset & 0x10)
+ {
+ /* Set bit */
+ if (offset < 0x08)
+ {
+ ins8154_porta_w(0, m_out_a |= offset & 0x07);
+ }
+ else
+ {
+ ins8154_portb_w(0, m_out_b |= (offset >> 4) & 0x07);
+ }
+ }
+ else
+ {
+ /* Clear bit */
+ if (offset < 0x08)
+ {
+ ins8154_porta_w(0, m_out_a & ~(offset & 0x07));
+ }
+ else
+ {
+ ins8154_portb_w(0, m_out_b & ~((offset >> 4) & 0x07));
+ }
+ }
+
+ break;
+ }
+}
diff --git a/trunk/src/emu/machine/ins8154.h b/trunk/src/emu/machine/ins8154.h
new file mode 100644
index 00000000000..1857a428223
--- /dev/null
+++ b/trunk/src/emu/machine/ins8154.h
@@ -0,0 +1,126 @@
+/***************************************************************************
+
+ National Semiconductor INS8154
+
+ N-Channel 128-by-8 Bit RAM Input/Output (RAM I/O)
+
+ _____ _____
+ PB6 1 |* \_/ | 40 VCC
+ PB5 2 | | 39 PB7
+ PB4 3 | | 38 NWDS
+ PB3 4 | | 37 NRDS
+ PB2 5 | | 36 NRST
+ PB1 6 | | 35 _CS0
+ PB0 7 | | 34 CS1
+ DB7 8 | | 33 M/_IO
+ DB6 9 | | 32 AD6
+ DB5 10 | INS8154 | 31 AD5
+ DB4 11 | | 30 AD4
+ DB3 12 | | 29 AD3
+ DB2 13 | | 28 AD2
+ DB1 14 | | 27 AD1
+ DB0 15 | | 26 AD0
+ PA7 16 | | 25 INTR
+ PA6 17 | | 24 PA0
+ PA5 18 | | 23 PA1
+ PA4 19 | | 22 PA2
+ GND 20 |_____________| 21 PA3
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __INS8154_H__
+#define __INS8154_H__
+
+#include "emu.h"
+
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_INS8154_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, INS8154, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+
+// ======================> ins8154_interface
+
+struct ins8154_interface
+{
+ devcb_read8 m_in_a_cb;
+ devcb_write8 m_out_a_cb;
+ devcb_read8 m_in_b_cb;
+ devcb_write8 m_out_b_cb;
+ devcb_write_line m_out_irq_cb;
+};
+
+
+
+// ======================> ins8154_device
+
+class ins8154_device : public device_t,
+ public ins8154_interface
+{
+public:
+ // construction/destruction
+ ins8154_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ UINT8 ins8154_r(UINT32 offset);
+ void ins8154_w(UINT32 offset, UINT8 data);
+
+ void ins8154_porta_w(UINT32 offset, UINT8 data);
+ void ins8154_portb_w(UINT32 offset, UINT8 data);
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_post_load() { }
+ virtual void device_clock_changed() { }
+
+private:
+
+ /* i/o lines */
+ devcb_resolved_read8 m_in_a_func;
+ devcb_resolved_write8 m_out_a_func;
+ devcb_resolved_read8 m_in_b_func;
+ devcb_resolved_write8 m_out_b_func;
+ devcb_resolved_write_line m_out_irq_func;
+
+ /* registers */
+ UINT8 m_in_a; /* Input Latch Port A */
+ UINT8 m_in_b; /* Input Latch Port B */
+ UINT8 m_out_a; /* Output Latch Port A */
+ UINT8 m_out_b; /* Output Latch Port B */
+ UINT8 m_mdr; /* Mode Definition Register */
+ UINT8 m_odra; /* Output Definition Register Port A */
+ UINT8 m_odrb; /* Output Definition Register Port B */
+};
+
+
+// device type definition
+extern const device_type INS8154;
+
+
+
+/***************************************************************************
+ PROTOTYPES
+***************************************************************************/
+
+READ8_DEVICE_HANDLER( ins8154_r );
+WRITE8_DEVICE_HANDLER( ins8154_w );
+
+WRITE8_DEVICE_HANDLER( ins8154_porta_w );
+WRITE8_DEVICE_HANDLER( ins8154_portb_w );
+
+
+#endif /* __INS8154_H__ */
diff --git a/trunk/src/emu/machine/ins8250.c b/trunk/src/emu/machine/ins8250.c
new file mode 100644
index 00000000000..8fa8aea7aec
--- /dev/null
+++ b/trunk/src/emu/machine/ins8250.c
@@ -0,0 +1,715 @@
+/**********************************************************************
+
+ National Semiconductor 8250 UART interface and emulation
+
+ More information on the different models can be found in
+ section 1.6 at this location:
+ http://www.freebsd.org/doc/en_US.ISO8859-1/articles/serial-uart/
+
+Model overview (from page above):
+
+INS8250
+This part was used in the original IBM PC and IBM PC/XT. The original name
+for this part was the INS8250 ACE (Asynchronous Communications Element) and
+it is made from NMOS technology.
+
+The 8250 uses eight I/O ports and has a one-byte send and a one-byte receive
+buffer. This original UART has several race conditions and other flaws. The
+original IBM BIOS includes code to work around these flaws, but this made
+the BIOS dependent on the flaws being present, so subsequent parts like the
+8250A, 16450 or 16550 could not be used in the original IBM PC or IBM PC/XT.
+
+INS8250-B
+This is the slower speed of the INS8250 made from NMOS technology. It contains
+the same problems as the original INS8250.
+
+INS8250A
+An improved version of the INS8250 using XMOS technology with various functional
+flaws corrected. The INS8250A was used initially in PC clone computers by vendors
+who used "clean" BIOS designs. Because of the corrections in the chip, this part
+could not be used with a BIOS compatible with the INS8250 or INS8250B.
+
+INS82C50A
+This is a CMOS version (low power consumption) of the INS8250A and has similar
+functional characteristics.
+
+NS16450
+Same as NS8250A with improvements so it can be used with faster CPU bus designs.
+IBM used this part in the IBM AT and updated the IBM BIOS to no longer rely on
+the bugs in the INS8250.
+
+NS16C450
+This is a CMOS version (low power consumption) of the NS16450.
+
+NS16550
+Same as NS16450 with a 16-byte send and receive buffer but the buffer design
+was flawed and could not be reliably be used.
+
+NS16550A
+Same as NS16550 with the buffer flaws corrected. The 16550A and its successors
+have become the most popular UART design in the PC industry, mainly due to
+its ability to reliably handle higher data rates on operating systems with
+sluggish interrupt response times.
+
+NS16C552
+This component consists of two NS16C550A CMOS UARTs in a single package.
+
+PC16550D
+Same as NS16550A with subtle flaws corrected. This is revision D of the
+16550 family and is the latest design available from National Semiconductor.
+
+
+Known issues:
+- MESS does currently not handle all these model specific features.
+
+
+History:
+ KT - 14-Jun-2000 - Improved Interrupt setting/clearing
+ KT - moved into separate file so it can be used in Super I/O emulation and
+ any other system which uses a PC type COM port
+ KT - 24-Jun-2000 - removed pc specific input port tests. More compatible
+ with PCW16 and PCW16 doesn't requre the PC input port definitions
+ which are not required by the PCW16 hardware
+
+**********************************************************************/
+
+#include "emu.h"
+#include "machine/ins8250.h"
+
+
+#define LOG(LEVEL,N,M,A) \
+ do { \
+ if(LEVEL>=N) \
+ { \
+ if( M ) \
+ logerror("%-24s",(char*)M ); \
+ logerror A; \
+ } \
+ } while (0)
+
+
+/* device types */
+enum {
+ TYPE_INS8250 = 0,
+ TYPE_INS8250A,
+ TYPE_NS16450,
+ TYPE_NS16550,
+ TYPE_NS16550A,
+ TYPE_PC16550D,
+
+ NUM_TYPES
+};
+
+
+/* device tags */
+static const char * const device_tags[NUM_TYPES] = { "ins8250", "ins8250a", "ns16450", "ns16550", "ns16550a", "pc16550d" };
+
+
+#define VERBOSE_COM 0
+#define COM_LOG(n,m,a) LOG(VERBOSE_COM,n,m,a)
+
+typedef struct {
+ devcb_resolved_write_line out_intr_func;
+ const ins8250_interface *interface;
+ int device_type;
+
+ UINT8 thr; /* 0 -W transmitter holding register */
+ UINT8 rbr; /* 0 R- receiver buffer register */
+ UINT8 ier; /* 1 RW interrupt enable register */
+ UINT8 dll; /* 0 RW divisor latch lsb (if DLAB = 1) */
+ UINT8 dlm; /* 1 RW divisor latch msb (if DLAB = 1) */
+ UINT8 iir; /* 2 R- interrupt identification register */
+ UINT8 lcr; /* 3 RW line control register (bit 7: DLAB) */
+ UINT8 mcr; /* 4 RW modem control register */
+ UINT8 lsr; /* 5 R- line status register */
+ UINT8 msr; /* 6 R- modem status register */
+ UINT8 scr; /* 7 RW scratch register */
+
+/* holds int pending state for com */
+ UINT8 int_pending;
+
+ // sending circuit
+ struct {
+ int active;
+ UINT8 data;
+ double time;
+ } send;
+} ins8250_t;
+
+/* int's pending */
+#define COM_INT_PENDING_RECEIVED_DATA_AVAILABLE 0x0001
+#define COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY 0x0002
+#define COM_INT_PENDING_RECEIVER_LINE_STATUS 0x0004
+#define COM_INT_PENDING_MODEM_STATUS_REGISTER 0x0008
+
+
+INLINE ins8250_t *get_safe_token(device_t *device)
+{
+ assert( device != NULL );
+ assert( ( device->type() == INS8250 ) ||
+ ( device->type() == INS8250A ) ||
+ ( device->type() == NS16450 ) ||
+ ( device->type() == NS16550 ) ||
+ ( device->type() == NS16550A ) ||
+ ( device->type() == PC16550D ) );
+ return (ins8250_t *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+/* setup iir with the priority id */
+static void ins8250_setup_iir(device_t *device)
+{
+ ins8250_t *ins8250 = get_safe_token(device);
+
+ ins8250->iir &= ~(0x04|0x02);
+
+ /* highest to lowest */
+ if (ins8250->ier & ins8250->int_pending & COM_INT_PENDING_RECEIVER_LINE_STATUS)
+ {
+ ins8250->iir |=0x04|0x02;
+ return;
+ }
+
+ if (ins8250->ier & ins8250->int_pending & COM_INT_PENDING_RECEIVED_DATA_AVAILABLE)
+ {
+ ins8250->iir |=0x04;
+ return;
+ }
+
+ if (ins8250->ier & ins8250->int_pending & COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY)
+ {
+ ins8250->iir |=0x02;
+ return;
+ }
+
+ /* modem status has both bits clear */
+}
+
+
+/* ints will continue to be set for as long as there are ints pending */
+static void ins8250_update_interrupt(device_t *device)
+{
+ ins8250_t *ins8250 = get_safe_token(device);
+ int state;
+
+ /* if any bits are set and are enabled */
+ if (((ins8250->int_pending&ins8250->ier) & 0x0f) != 0)
+ {
+ /* trigger next highest priority int */
+
+ /* set int */
+ state = 1;
+ ins8250_setup_iir(device);
+
+ /* int pending */
+ ins8250->iir &= ~0x01;
+ }
+ else
+ {
+ /* clear int */
+ state = 0;
+
+ /* no ints pending */
+ ins8250->iir |= 0x01;
+ /* priority level */
+ ins8250->iir &= ~(0x04|0x02);
+ }
+
+ /* set or clear the int */
+ ins8250->out_intr_func(state);
+}
+
+
+
+/* set pending bit and trigger int */
+static void ins8250_trigger_int(device_t *device, int flag)
+{
+ ins8250_t *ins8250 = get_safe_token(device);
+
+ ins8250->int_pending |= flag;
+ ins8250_update_interrupt(device);
+}
+
+
+
+/* clear pending bit, if any ints are pending, then int will be triggered, otherwise it
+will be cleared */
+static void ins8250_clear_int(device_t *device, int flag)
+{
+ ins8250_t *ins8250 = get_safe_token(device);
+
+ ins8250->int_pending &= ~flag;
+ ins8250_update_interrupt(device);
+}
+
+
+WRITE8_DEVICE_HANDLER( ins8250_w )
+{
+ static const char P[] = "NONENHNL"; /* names for parity select */
+ ins8250_t *ins8250 = get_safe_token(device);
+ int tmp;
+
+ switch (offset)
+ {
+ case 0:
+ if (ins8250->lcr & 0x80)
+ {
+ ins8250->dll = data;
+ tmp = ins8250->dlm * 256 + ins8250->dll;
+ COM_LOG(1,"COM_dll_w",("COM \"%s\" $%02x: [$%04x = %d baud]\n", device->tag(),
+ data, tmp, (tmp)?(int)(ins8250->interface->clockin/16/tmp):0));
+ }
+ else
+ {
+ ins8250->thr = data;
+ COM_LOG(2,"COM_thr_w",("COM $%02x\n", data));
+
+ if ( ins8250->mcr & 0x10 )
+ {
+ ins8250->lsr |= 1;
+ ins8250->rbr = data;
+ ins8250_trigger_int( device, COM_INT_PENDING_RECEIVED_DATA_AVAILABLE );
+ }
+
+ if ( ins8250->interface->transmit )
+ ins8250->interface->transmit(device, ins8250->thr);
+
+ /* writing to thr will clear the int */
+ ins8250_clear_int(device, COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY);
+ }
+ break;
+ case 1:
+ if (ins8250->lcr & 0x80)
+ {
+ ins8250->dlm = data;
+ tmp = ins8250->dlm * 256 + ins8250->dll;
+ COM_LOG(1,"COM_dlm_w",("COM \"%s\" $%02x: [$%04x = %d baud]\n", device->tag(),
+ data, tmp, (tmp)?(int)(ins8250->interface->clockin/16/tmp):0));
+ }
+ else
+ {
+ ins8250->ier = data;
+ COM_LOG(2,"COM_ier_w",("COM \"%s\" $%02x: enable int on RX %d, THRE %d, RLS %d, MS %d\n", device->tag(),
+ data, data&1, (data>>1)&1, (data>>2)&1, (data>>3)&1));
+ COM_LOG(2,"COM_ier_w",("COM \"%s\" lsr = $%02x, int_pending = $%02x\n", device->tag(), ins8250->lsr, ins8250->int_pending ));
+ ins8250_update_interrupt(device);
+ }
+ break;
+ case 2:
+ COM_LOG(1,"COM_fcr_w",("COM \"%s\" $%02x (16550 only)\n", device->tag(), data));
+ break;
+ case 3:
+ ins8250->lcr = data;
+ COM_LOG(1,"COM_lcr_w",("COM \"%s\" $%02x word length %d, stop bits %d, parity %c, break %d, DLAB %d\n", device->tag(),
+ data, 5+(data&3), 1+((data>>2)&1), P[(data>>3)&7], (data>>6)&1, (data>>7)&1));
+ break;
+ case 4:
+ if ( ( ins8250->mcr & 0x1f ) != ( data & 0x1f ) )
+ {
+ ins8250->mcr = data & 0x1f;
+ COM_LOG(1,"COM_mcr_w",("COM \"%s\" $%02x DTR %d, RTS %d, OUT1 %d, OUT2 %d, loopback %d\n", device->tag(),
+ data, data&1, (data>>1)&1, (data>>2)&1, (data>>3)&1, (data>>4)&1));
+ if (ins8250->interface->handshake_out)
+ ins8250->interface->handshake_out(device,data);
+
+ if ( ins8250->mcr & 0x10 ) /* loopback test */
+ {
+ data = ( ( ins8250->mcr & 0x0c ) << 4 ) | ( ( ins8250->mcr & 0x01 ) << 5 ) | ( ( ins8250->mcr & 0x02 ) << 3 );
+ if ( ( ins8250->msr & 0x20 ) != ( data & 0x20 ) )
+ {
+ data |= 0x02;
+ }
+ if ( ( ins8250->msr & 0x10 ) != ( data & 0x10 ) )
+ {
+ data |= 0x01;
+ }
+ if ( ( ins8250->msr & 0x40 ) && ! ( data & 0x40 ) )
+ {
+ data |= 0x04;
+ }
+ if ( ( ins8250->msr & 0x80 ) != ( data & 0x80 ) )
+ {
+ data |= 0x08;
+ }
+ ins8250->msr = data;
+ }
+ }
+ break;
+ case 5:
+ /*
+ This register can be written, but if you write a 1 bit into any of
+ bits 5 - 0, you could cause an interrupt if the appropriate IER bit
+ is set.
+ */
+ COM_LOG(1,"COM_lsr_w",("COM \"%s\" $%02x\n", device->tag(), data ));
+
+ ins8250->lsr = data;
+
+ tmp = 0;
+ tmp |= ( ins8250->lsr & 0x01 ) ? COM_INT_PENDING_RECEIVED_DATA_AVAILABLE : 0;
+ tmp |= ( ins8250->lsr & 0x1e ) ? COM_INT_PENDING_RECEIVER_LINE_STATUS : 0;
+ tmp |= ( ins8250->lsr & 0x20 ) ? COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY : 0;
+ ins8250_trigger_int( device, tmp );
+
+ break;
+ case 6:
+ /*
+ This register can be written, but if you write a 1 bit into any of
+ bits 3 - 0, you could cause an interrupt if the appropriate IER bit
+ is set.
+ */
+ COM_LOG(1,"COM_msr_w",("COM \"%s\" $%02x\n", device->tag(), data ));
+
+ ins8250->msr = data;
+
+ if ( ins8250->msr & 0x0f )
+ {
+ ins8250_trigger_int( device, COM_INT_PENDING_MODEM_STATUS_REGISTER );
+ }
+ break;
+ case 7:
+ ins8250->scr = data;
+ COM_LOG(2,"COM_scr_w",("COM \"%s\" $%02x\n", device->tag(), data));
+ break;
+ }
+
+ if (ins8250->interface->refresh_connected)
+ ins8250->interface->refresh_connected(device);
+}
+
+
+
+READ8_DEVICE_HANDLER( ins8250_r )
+{
+ ins8250_t *ins8250 = get_safe_token(device);
+ int data = 0x0ff;
+
+ switch (offset)
+ {
+ case 0:
+ if (ins8250->lcr & 0x80)
+ {
+ data = ins8250->dll;
+ COM_LOG(1,"COM_dll_r",("COM \"%s\" $%02x\n", device->tag(), data));
+ }
+ else
+ {
+ data = ins8250->rbr;
+ if( ins8250->lsr & 0x01 )
+ {
+ ins8250->lsr &= ~0x01; /* clear data ready status */
+ COM_LOG(2,"COM_rbr_r",("COM \"%s\" $%02x\n", device->tag(), data));
+ }
+
+ ins8250_clear_int(device, COM_INT_PENDING_RECEIVED_DATA_AVAILABLE);
+ }
+ break;
+ case 1:
+ if (ins8250->lcr & 0x80)
+ {
+ data = ins8250->dlm;
+ COM_LOG(1,"COM_dlm_r",("COM \"%s\" $%02x\n", device->tag(), data));
+ }
+ else
+ {
+ data = ins8250->ier & 0x0f;
+ COM_LOG(2,"COM_ier_r",("COM \"%s\" $%02x\n", device->tag(), data));
+ }
+ break;
+ case 2:
+ data = ins8250->iir;
+ COM_LOG(2,"COM_iir_r",("COM \"%s\" $%02x\n", device->tag(), data));
+ /* The documentation says that reading this register will
+ clear the int if this is the source of the int */
+ if ( ins8250->ier & COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY )
+ {
+ ins8250_clear_int(device, COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY);
+ }
+ break;
+ case 3:
+ data = ins8250->lcr;
+ COM_LOG(2,"COM_lcr_r",("COM \"%s\" $%02x\n", device->tag(), data));
+ break;
+ case 4:
+ data = ins8250->mcr;
+ COM_LOG(2,"COM_mcr_r",("COM \"%s\" $%02x\n", device->tag(), data));
+ break;
+ case 5:
+
+#if 0
+ if (ins8250->send.active && (machine.time()-ins8250->send.time>uart_byte_time(n)))
+ {
+ // currently polling is enough for pc1512
+ ins8250->lsr |= 0x40; /* set TSRE */
+ ins8250->send.active = 0;
+ if ( ins8250->mcr & 0x10 )
+ {
+ ins8250->lsr |= 1;
+ ins8250->rbr = ins8250->send.data;
+ }
+ }
+#endif
+ ins8250->lsr |= 0x60; /* set THRE */
+ data = ins8250->lsr;
+ if( ins8250->lsr & 0x1f )
+ {
+ ins8250->lsr &= 0xe1; /* clear FE, PE and OE and BREAK bits */
+ COM_LOG(2,"COM_lsr_r",("COM \"%s\" $%02x, DR %d, OE %d, PE %d, FE %d, BREAK %d, THRE %d, TSRE %d\n", device->tag(),
+ data, data&1, (data>>1)&1, (data>>2)&1, (data>>3)&1, (data>>4)&1, (data>>5)&1, (data>>6)&1));
+ }
+
+ /* reading line status register clears int */
+ ins8250_clear_int(device, COM_INT_PENDING_RECEIVER_LINE_STATUS);
+ break;
+ case 6:
+ data = ins8250->msr;
+ ins8250->msr &= 0xf0; /* reset delta values */
+ COM_LOG(2,"COM_msr_r",("COM \"%s\" $%02x\n", device->tag(), data));
+
+ /* reading msr clears int */
+ ins8250_clear_int(device, COM_INT_PENDING_MODEM_STATUS_REGISTER);
+
+ break;
+ case 7:
+ data = ins8250->scr;
+ COM_LOG(2,"COM_scr_r",("COM \"%s\" $%02x\n", device->tag(), data));
+ break;
+ }
+
+ if (ins8250->interface->refresh_connected)
+ ins8250->interface->refresh_connected(device);
+
+ return data;
+}
+
+
+
+void ins8250_receive(device_t *device, int data)
+{
+ ins8250_t *ins8250 = get_safe_token(device);
+
+ /* check if data rate 1200 baud is set */
+ if( ins8250->dlm != 0x00 || ins8250->dll != 0x60 )
+ ins8250->lsr |= 0x08; /* set framing error */
+
+ /* if data not yet serviced */
+ if( ins8250->lsr & 0x01 )
+ ins8250->lsr |= 0x02; /* set overrun error */
+
+ /* put data into receiver buffer register */
+ ins8250->rbr = data;
+
+ /* set data ready status */
+ ins8250->lsr |= 0x01;
+
+ /* set pending state for this interrupt. */
+ ins8250_trigger_int(device, COM_INT_PENDING_RECEIVED_DATA_AVAILABLE);
+
+
+// /* OUT2 + received line data avail interrupt enabled? */
+// if( (COM_mcr[n] & 0x08) && (COM_ier[n] & 0x01) )
+// {
+// if (com_interface.interrupt)
+// com_interface.interrupt(4-(n&1), 1);
+//
+// }
+}
+
+/**************************************************************************
+ * change the modem status register
+ **************************************************************************/
+void ins8250_handshake_in(device_t *device, int new_msr)
+{
+ ins8250_t *ins8250 = get_safe_token(device);
+
+ /* no change in modem status bits? */
+ if( ((ins8250->msr ^ new_msr) & 0xf0) == 0 )
+ return;
+
+ /* set delta status bits 0..3 and new modem status bits 4..7 */
+ ins8250->msr = (((ins8250->msr ^ new_msr) >> 4) & 0x0f) | (new_msr & 0xf0);
+
+ ins8250_trigger_int(device, COM_INT_PENDING_MODEM_STATUS_REGISTER);
+
+// /* set up interrupt information register */
+ // COM_iir[n] &= ~(0x06 | 0x01);
+
+// /* OUT2 + modem status interrupt enabled? */
+// if( (COM_mcr[n] & 0x08) && (COM_ier[n] & 0x08) )
+// {
+// if (com_interface.interrupt)
+// com_interface.interrupt(4-(n&1), 1);
+// }
+}
+
+
+static void common_start( device_t *device, int device_type )
+{
+ ins8250_t *ins8250 = get_safe_token(device);
+
+ ins8250->interface = (const ins8250_interface*)device->static_config();
+ ins8250->device_type = device_type;
+
+ ins8250->out_intr_func.resolve(ins8250->interface->out_intr_cb, *device);
+}
+
+
+static DEVICE_START( ins8250 )
+{
+ common_start( device, TYPE_INS8250 );
+}
+
+
+static DEVICE_START( ins8250a )
+{
+ common_start( device, TYPE_INS8250A );
+}
+
+
+static DEVICE_START( ns16450 )
+{
+ common_start( device, TYPE_NS16450 );
+}
+
+
+static DEVICE_START( ns16550 )
+{
+ common_start( device, TYPE_NS16550 );
+}
+
+
+static DEVICE_START( ns16550a )
+{
+ common_start( device, TYPE_NS16550A );
+}
+
+
+static DEVICE_START( pc16550d )
+{
+ common_start( device, TYPE_PC16550D );
+}
+
+
+static DEVICE_RESET( ins8250 )
+{
+ ins8250_t *ins8250 = get_safe_token(device);
+
+ ins8250->ier = 0;
+ ins8250->iir = 1;
+ ins8250->lcr = 0;
+ ins8250->mcr = 0;
+ ins8250->lsr = (1<<5) | (1<<6);
+
+ ins8250->send.active=0;
+
+ /* refresh with reset state of register */
+ if (ins8250->interface->refresh_connected)
+ ins8250->interface->refresh_connected(device);
+}
+
+
+DEVICE_GET_INFO( ins8250 )
+{
+ switch ( state )
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(ins8250_t); break;
+ case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(ins8250); break;
+ case DEVINFO_FCT_STOP: /* nothing */ break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(ins8250); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "National Semiconductor INS8250/INS8250B"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "INS8250"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.00"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright the MESS Team"); break;
+ }
+}
+
+
+DEVICE_GET_INFO( ins8250a )
+{
+ switch ( state )
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "National Semiconductor INS8250A/INS82C50A"); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(ins8250a); break;
+
+ default: DEVICE_GET_INFO_CALL(ins8250); break;
+ }
+}
+
+
+DEVICE_GET_INFO( ns16450 )
+{
+ switch ( state )
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "National Semiconductor NS16450/PC16450"); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(ns16450); break;
+
+ default: DEVICE_GET_INFO_CALL(ins8250); break;
+ }
+}
+
+
+DEVICE_GET_INFO( ns16550 )
+{
+ switch ( state )
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "National Semiconductor NS16550/PC16550"); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(ns16550); break;
+
+ default: DEVICE_GET_INFO_CALL(ins8250); break;
+ }
+}
+
+
+DEVICE_GET_INFO( ns16550a )
+{
+ switch ( state )
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "National Semiconductor NS16550A/PC16550A"); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(ns16550a); break;
+
+ default: DEVICE_GET_INFO_CALL(ins8250); break;
+ }
+}
+
+
+DEVICE_GET_INFO( pc16550d )
+{
+ switch ( state )
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "National Semiconductor PC16550D"); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(pc16550d); break;
+
+ default: DEVICE_GET_INFO_CALL(ins8250); break;
+ }
+}
+
+
+
+DEFINE_LEGACY_DEVICE(INS8250, ins8250);
+DEFINE_LEGACY_DEVICE(INS8250A, ins8250a);
+DEFINE_LEGACY_DEVICE(NS16450, ns16450);
+DEFINE_LEGACY_DEVICE(NS16550, ns16550);
+DEFINE_LEGACY_DEVICE(NS16550A, ns16550a);
+DEFINE_LEGACY_DEVICE(PC16550D, pc16550d);
diff --git a/trunk/src/emu/machine/ins8250.h b/trunk/src/emu/machine/ins8250.h
new file mode 100644
index 00000000000..ef00e544573
--- /dev/null
+++ b/trunk/src/emu/machine/ins8250.h
@@ -0,0 +1,83 @@
+/**********************************************************************
+
+ 8250 UART interface and emulation
+
+**********************************************************************/
+
+#ifndef __INS8250_H_
+#define __INS8250_H_
+
+#include "devlegcy.h"
+
+DECLARE_LEGACY_DEVICE(INS8250, ins8250);
+DECLARE_LEGACY_DEVICE(INS8250A, ins8250a);
+DECLARE_LEGACY_DEVICE(NS16450, ns16450);
+DECLARE_LEGACY_DEVICE(NS16550, ns16550);
+DECLARE_LEGACY_DEVICE(NS16550A, ns16550a);
+DECLARE_LEGACY_DEVICE(PC16550D, pc16550d);
+
+#define UART8250_HANDSHAKE_OUT_DTR 0x01
+#define UART8250_HANDSHAKE_OUT_RTS 0x02
+
+#define UART8250_HANDSHAKE_IN_DSR 0x020
+#define UART8250_HANDSHAKE_IN_CTS 0x010
+#define UART8250_INPUTS_RING_INDICATOR 0x0040
+#define UART8250_INPUTS_DATA_CARRIER_DETECT 0x0080
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef void (*ins8250_transmit_func)(device_t *device, int data);
+typedef void (*ins8250_handshake_out_func)(device_t *device, int data);
+typedef void (*ins8250_refresh_connect_func)(device_t *device);
+
+#define INS8250_TRANSMIT(name) void name(device_t *device, int data)
+#define INS8250_HANDSHAKE_OUT(name) void name(device_t *device, int data)
+#define INS8250_REFRESH_CONNECT(name) void name(device_t *device)
+
+typedef struct
+{
+ long clockin;
+ devcb_write_line out_intr_cb;
+
+ ins8250_transmit_func transmit;
+ ins8250_handshake_out_func handshake_out;
+
+ // refresh object connected to this port
+ ins8250_refresh_connect_func refresh_connected;
+} ins8250_interface;
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_INS8250_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, INS8250, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+
+#define MCFG_NS16450_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, NS16450, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+
+#define MCFG_NS16550_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, NS16550, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+void ins8250_receive(device_t *device, int data);
+void ins8250_handshake_in(device_t *device, int new_msr);
+
+READ8_DEVICE_HANDLER( ins8250_r );
+WRITE8_DEVICE_HANDLER( ins8250_w );
+
+
+#endif /* __INS8250_H_ */
diff --git a/trunk/src/emu/machine/intelfsh.c b/trunk/src/emu/machine/intelfsh.c
new file mode 100644
index 00000000000..56ae07c9df9
--- /dev/null
+++ b/trunk/src/emu/machine/intelfsh.c
@@ -0,0 +1,753 @@
+/*
+ Flash ROM emulation
+
+ Explicitly supports:
+ Intel 28F016S5 (byte-wide)
+ AMD/Fujitsu 29F016 (byte-wide)
+ Sharp LH28F400 (word-wide)
+
+ Flash ROMs use a standardized command set across manufacturers,
+ so this emulation should work even for non-Intel and non-Sharp chips
+ as long as the game doesn't query the maker ID.
+*/
+
+#include "emu.h"
+#include "intelfsh.h"
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+enum
+{
+ FM_NORMAL, // normal read/write
+ FM_READID, // read ID
+ FM_READSTATUS, // read status
+ FM_WRITEPART1, // first half of programming, awaiting second
+ FM_CLEARPART1, // first half of clear, awaiting second
+ FM_SETMASTER, // first half of set master lock, awaiting on/off
+ FM_READAMDID1, // part 1 of alt ID sequence
+ FM_READAMDID2, // part 2 of alt ID sequence
+ FM_READAMDID3, // part 3 of alt ID sequence
+ FM_ERASEAMD1, // part 1 of AMD erase sequence
+ FM_ERASEAMD2, // part 2 of AMD erase sequence
+ FM_ERASEAMD3, // part 3 of AMD erase sequence
+ FM_ERASEAMD4, // part 4 of AMD erase sequence
+ FM_BYTEPROGRAM,
+ FM_BANKSELECT,
+};
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+const device_type INTEL_28F016S5 = &device_creator<intel_28f016s5_device>;
+const device_type SHARP_LH28F016S = &device_creator<sharp_lh28f016s_device>;
+const device_type FUJITSU_29F016A = &device_creator<fujitsu_29f016a_device>;
+const device_type FUJITSU_29DL16X = &device_creator<fujitsu_29dl16x_device>;
+const device_type INTEL_E28F400 = &device_creator<intel_e28f400_device>;
+const device_type MACRONIX_29L001MC = &device_creator<macronix_29l001mc_device>;
+const device_type PANASONIC_MN63F805MNP = &device_creator<panasonic_mn63f805mnp_device>;
+const device_type SANYO_LE26FV10N1TS = &device_creator<sanyo_le26fv10n1ts_device>;
+
+const device_type SHARP_LH28F400 = &device_creator<sharp_lh28f400_device>;
+const device_type INTEL_E28F008SA = &device_creator<intel_e28f008sa_device>;
+const device_type INTEL_TE28F160 = &device_creator<intel_te28f160_device>;
+const device_type SHARP_UNK128MBIT = &device_creator<sharp_unk128mbit_device>;
+
+static ADDRESS_MAP_START( memory_map8_512Kb, AS_PROGRAM, 8 )
+ AM_RANGE(0x00000, 0x00ffff) AM_RAM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( memory_map8_1Mb, AS_PROGRAM, 8 )
+ AM_RANGE(0x00000, 0x01ffff) AM_RAM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( memory_map8_8Mb, AS_PROGRAM, 8 )
+ AM_RANGE(0x00000, 0x0fffff) AM_RAM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( memory_map8_16Mb, AS_PROGRAM, 8 )
+ AM_RANGE(0x00000, 0x1fffff) AM_RAM
+ADDRESS_MAP_END
+
+
+static ADDRESS_MAP_START( memory_map16_4Mb, AS_PROGRAM, 16 )
+ AM_RANGE(0x00000, 0x03ffff) AM_RAM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( memory_map16_16Mb, AS_PROGRAM, 16 )
+ AM_RANGE(0x00000, 0x0fffff) AM_RAM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( memory_map16_64Mb, AS_PROGRAM, 16 )
+ AM_RANGE(0x00000, 0x3fffff) AM_RAM
+ADDRESS_MAP_END
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// intelfsh_device - constructor
+//-------------------------------------------------
+
+intelfsh_device::intelfsh_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT32 variant)
+ : device_t(mconfig, type, name, tag, owner, clock),
+ device_memory_interface(mconfig, *this),
+ device_nvram_interface(mconfig, *this),
+ m_type(variant),
+ m_size(0),
+ m_bits(8),
+ m_device_id(0),
+ m_maker_id(0),
+ m_sector_is_4k(false),
+ m_status(0x80),
+ m_erase_sector(0),
+ m_flash_mode(FM_NORMAL),
+ m_flash_master_lock(false),
+ m_timer(NULL),
+ m_bank(0)
+{
+ address_map_constructor map = NULL;
+
+ switch( variant )
+ {
+ case FLASH_INTEL_28F016S5:
+ case FLASH_SHARP_LH28F016S:
+ m_bits = 8;
+ m_size = 0x200000;
+ m_maker_id = 0x89;
+ m_device_id = 0xaa;
+ map = ADDRESS_MAP_NAME( memory_map8_16Mb );
+ break;
+ case FLASH_SHARP_LH28F400:
+ case FLASH_INTEL_E28F400:
+ m_bits = 16;
+ m_size = 0x80000;
+ m_maker_id = 0xb0;
+ m_device_id = 0xed;
+ map = ADDRESS_MAP_NAME( memory_map16_4Mb );
+ break;
+ case FLASH_FUJITSU_29F016A:
+ m_bits = 8;
+ m_size = 0x200000;
+ m_maker_id = 0x04;
+ m_device_id = 0xad;
+ map = ADDRESS_MAP_NAME( memory_map8_16Mb );
+ break;
+ case FLASH_FUJITSU_29DL16X:
+ m_bits = 8;
+ m_size = 0x200000;
+ m_maker_id = 0x04;
+ m_device_id = 0x35;
+ map = ADDRESS_MAP_NAME( memory_map8_16Mb );
+ break;
+ case FLASH_INTEL_E28F008SA:
+ m_bits = 8;
+ m_size = 0x100000;
+ m_maker_id = 0x89;
+ m_device_id = 0xa2;
+ map = ADDRESS_MAP_NAME( memory_map8_8Mb );
+ break;
+ case FLASH_INTEL_TE28F160:
+ m_bits = 16;
+ m_size = 0x200000;
+ m_maker_id = 0xb0;
+ m_device_id = 0xd0;
+ map = ADDRESS_MAP_NAME( memory_map16_16Mb );
+ break;
+ case FLASH_SHARP_UNK128MBIT:
+ m_bits = 16;
+ m_size = 0x800000;
+ m_maker_id = 0xb0;
+ m_device_id = 0xb0;
+ map = ADDRESS_MAP_NAME( memory_map16_64Mb );
+ break;
+ case FLASH_MACRONIX_29L001MC:
+ m_bits = 8;
+ m_size = 0x20000;
+ m_maker_id = 0xc2;
+ m_device_id = 0x51;
+ map = ADDRESS_MAP_NAME( memory_map8_1Mb );
+ break;
+ case FLASH_PANASONIC_MN63F805MNP:
+ m_bits = 8;
+ m_size = 0x10000;
+ m_maker_id = 0x32;
+ m_device_id = 0x1b;
+ m_sector_is_4k = true;
+ map = ADDRESS_MAP_NAME( memory_map8_512Kb );
+ break;
+ case FLASH_SANYO_LE26FV10N1TS:
+ m_bits = 8;
+ m_size = 0x20000;
+ m_maker_id = 0x62;
+ m_device_id = 0x13;
+ m_sector_is_4k = true;
+ map = ADDRESS_MAP_NAME( memory_map8_1Mb );
+ break;
+ }
+
+ int addrbits;
+ for (addrbits = 24; addrbits > 0; addrbits--)
+ if ((m_size & (1 << addrbits)) != 0)
+ break;
+
+ m_space_config = address_space_config("flash", ENDIANNESS_BIG, m_bits, addrbits, (m_bits == 8) ? 0 : -1, map);
+}
+
+intelfsh8_device::intelfsh8_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT32 variant)
+ : intelfsh_device(mconfig, type, name, tag, owner, clock, variant) { }
+
+intelfsh16_device::intelfsh16_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT32 variant)
+ : intelfsh_device(mconfig, type, name, tag, owner, clock, variant) { }
+
+
+intel_28f016s5_device::intel_28f016s5_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : intelfsh8_device(mconfig, INTEL_28F016S5, "Intel 28F016S5 Flash", tag, owner, clock, FLASH_INTEL_28F016S5) { }
+
+fujitsu_29f016a_device::fujitsu_29f016a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : intelfsh8_device(mconfig, FUJITSU_29F016A, "Fujitsu 29F016A Flash", tag, owner, clock, FLASH_FUJITSU_29F016A) { }
+
+fujitsu_29dl16x_device::fujitsu_29dl16x_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : intelfsh8_device(mconfig, FUJITSU_29DL16X, "Fujitsu 29DL16X Flash", tag, owner, clock, FLASH_FUJITSU_29DL16X) { }
+
+sharp_lh28f016s_device::sharp_lh28f016s_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : intelfsh8_device(mconfig, SHARP_LH28F016S, "Sharp LH28F016S Flash", tag, owner, clock, FLASH_SHARP_LH28F016S) { }
+
+intel_e28f008sa_device::intel_e28f008sa_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : intelfsh8_device(mconfig, INTEL_E28F008SA, "Intel E28F008SA Flash", tag, owner, clock, FLASH_INTEL_E28F008SA) { }
+
+macronix_29l001mc_device::macronix_29l001mc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : intelfsh8_device(mconfig, MACRONIX_29L001MC, "Macronix 29L001MC Flash", tag, owner, clock, FLASH_MACRONIX_29L001MC) { }
+
+panasonic_mn63f805mnp_device::panasonic_mn63f805mnp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : intelfsh8_device(mconfig, PANASONIC_MN63F805MNP, "Panasonic MN63F805MNP Flash", tag, owner, clock, FLASH_PANASONIC_MN63F805MNP) { }
+
+sanyo_le26fv10n1ts_device::sanyo_le26fv10n1ts_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : intelfsh8_device(mconfig, SANYO_LE26FV10N1TS, "Sanyo LE26FV10N1TS Flash", tag, owner, clock, FLASH_SANYO_LE26FV10N1TS) { }
+
+sharp_lh28f400_device::sharp_lh28f400_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : intelfsh16_device(mconfig, SHARP_LH28F400, "Sharp LH28F400 Flash", tag, owner, clock, FLASH_SHARP_LH28F400) { }
+
+intel_te28f160_device::intel_te28f160_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : intelfsh16_device(mconfig, INTEL_TE28F160, "Intel TE28F160 Flash", tag, owner, clock, FLASH_INTEL_TE28F160) { }
+
+intel_e28f400_device::intel_e28f400_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : intelfsh16_device(mconfig, INTEL_E28F400, "Intel E28F400 Flash", tag, owner, clock, FLASH_INTEL_E28F400) { }
+
+sharp_unk128mbit_device::sharp_unk128mbit_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : intelfsh16_device(mconfig, SHARP_UNK128MBIT, "Sharp Unknown 128Mbit Flash", tag, owner, clock, FLASH_SHARP_UNK128MBIT) { }
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void intelfsh_device::device_start()
+{
+ m_timer = timer_alloc();
+
+ save_item( NAME(m_status) );
+ save_item( NAME(m_flash_mode) );
+ save_item( NAME(m_flash_master_lock) );
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void intelfsh_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch( m_flash_mode )
+ {
+ case FM_READSTATUS:
+ m_status = 0x80;
+ break;
+
+ case FM_ERASEAMD4:
+ m_flash_mode = FM_NORMAL;
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return a description of
+// any address spaces owned by this device
+//-------------------------------------------------
+
+const address_space_config *intelfsh_device::memory_space_config(address_spacenum spacenum) const
+{
+ return (spacenum == 0) ? &m_space_config : NULL;
+}
+
+
+//-------------------------------------------------
+// nvram_default - called to initialize NVRAM to
+// its default state
+//-------------------------------------------------
+
+void intelfsh_device::nvram_default()
+{
+ // region always wins
+ if (m_region != NULL)
+ {
+ UINT32 bytes = m_region->bytes();
+ if (bytes > m_size)
+ bytes = m_size;
+
+ if (m_bits == 8)
+ {
+ for (offs_t offs = 0; offs < bytes; offs++)
+ m_addrspace[0]->write_byte(offs, m_region->u8(offs));
+ }
+ else
+ {
+ for (offs_t offs = 0; offs < bytes; offs += 2)
+ m_addrspace[0]->write_word(offs, m_region->u16(offs / 2));
+ }
+ return;
+ }
+
+ // otherwise, default to 0xff
+ for (offs_t offs = 0; offs < m_size; offs++)
+ m_addrspace[0]->write_byte(offs, 0xff);
+}
+
+
+//-------------------------------------------------
+// nvram_read - called to read NVRAM from the
+// .nv file
+//-------------------------------------------------
+
+void intelfsh_device::nvram_read(emu_file &file)
+{
+ UINT8 *buffer = global_alloc_array(UINT8, m_size);
+ file.read(buffer, m_size);
+ for (int byte = 0; byte < m_size; byte++)
+ m_addrspace[0]->write_byte(byte, buffer[byte]);
+ global_free(buffer);
+}
+
+
+//-------------------------------------------------
+// nvram_write - called to write NVRAM to the
+// .nv file
+//-------------------------------------------------
+
+void intelfsh_device::nvram_write(emu_file &file)
+{
+ UINT8 *buffer = global_alloc_array(UINT8, m_size);
+ for (int byte = 0; byte < m_size; byte++)
+ buffer[byte] = m_addrspace[0]->read_byte(byte);
+ file.write(buffer, m_size);
+ global_free(buffer);
+}
+
+
+//-------------------------------------------------
+// read_full - generic read, called by the
+// bit-width-specific readers
+//-------------------------------------------------
+
+UINT32 intelfsh_device::read_full(UINT32 address)
+{
+ UINT32 data = 0;
+ address += m_bank << 16;
+ switch( m_flash_mode )
+ {
+ default:
+ case FM_NORMAL:
+ switch( m_bits )
+ {
+ case 8:
+ {
+ data = m_addrspace[0]->read_byte(address);
+ }
+ break;
+ case 16:
+ {
+ data = m_addrspace[0]->read_word(address * 2);
+ }
+ break;
+ }
+ break;
+ case FM_READSTATUS:
+ data = m_status;
+ break;
+ case FM_READAMDID3:
+ if (m_maker_id == 0x04 && m_device_id == 0x35)
+ {
+ //used in Fujitsu 29DL16X 8bits mode
+ switch (address)
+ {
+ case 0: data = m_maker_id; break;
+ case 2: data = m_device_id; break;
+ case 4: data = 0; break;
+ }
+ }
+ else
+ {
+ switch (address)
+ {
+ case 0: data = m_maker_id; break;
+ case 1: data = m_device_id; break;
+ case 2: data = 0; break;
+ }
+ }
+ break;
+ case FM_READID:
+ switch (address)
+ {
+ case 0: // maker ID
+ data = m_maker_id;
+ break;
+ case 1: // chip ID
+ data = m_device_id;
+ break;
+ case 2: // block lock config
+ data = 0; // we don't support this yet
+ break;
+ case 3: // master lock config
+ if (m_flash_master_lock)
+ {
+ data = 1;
+ }
+ else
+ {
+ data = 0;
+ }
+ break;
+ }
+ break;
+ case FM_ERASEAMD4:
+ // reads outside of the erasing sector return normal data
+ if ((address < m_erase_sector) || (address >= m_erase_sector+(64*1024)))
+ {
+ switch( m_bits )
+ {
+ case 8:
+ {
+ data = m_addrspace[0]->read_byte(address);
+ }
+ break;
+ case 16:
+ {
+ data = m_addrspace[0]->read_word(address * 2);
+ }
+ break;
+ }
+ }
+ else
+ {
+ m_status ^= ( 1 << 6 ) | ( 1 << 2 );
+ data = m_status;
+ }
+ break;
+ }
+
+// logerror( "intelflash_read( %d, %08x ) %08x\n", chip, address, data );
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// write_full - generic write, called by the
+// bit-width-specific writers
+//-------------------------------------------------
+
+void intelfsh_device::write_full(UINT32 address, UINT32 data)
+{
+// logerror( "intelflash_write( %d, %08x, %08x )\n", chip, address, data );
+
+ address += m_bank << 16;
+
+ switch( m_flash_mode )
+ {
+ case FM_NORMAL:
+ case FM_READSTATUS:
+ case FM_READID:
+ case FM_READAMDID3:
+ switch( data & 0xff )
+ {
+ case 0xf0:
+ case 0xff: // reset chip mode
+ m_flash_mode = FM_NORMAL;
+ break;
+ case 0x90: // read ID
+ m_flash_mode = FM_READID;
+ break;
+ case 0x40:
+ case 0x10: // program
+ m_flash_mode = FM_WRITEPART1;
+ break;
+ case 0x50: // clear status reg
+ m_status = 0x80;
+ m_flash_mode = FM_READSTATUS;
+ break;
+ case 0x20: // block erase
+ m_flash_mode = FM_CLEARPART1;
+ break;
+ case 0x60: // set master lock
+ m_flash_mode = FM_SETMASTER;
+ break;
+ case 0x70: // read status
+ m_flash_mode = FM_READSTATUS;
+ break;
+ case 0xaa: // AMD ID select part 1
+ if( ( address & 0xfff ) == 0x555 )
+ {
+ m_flash_mode = FM_READAMDID1;
+ }
+ else if( ( address & 0xfff ) == 0xaaa )
+ {
+ m_flash_mode = FM_READAMDID1;
+ }
+ break;
+ default:
+ logerror( "Unknown flash mode byte %x\n", data & 0xff );
+ break;
+ }
+ break;
+ case FM_READAMDID1:
+ if( ( address & 0xffff ) == 0x2aa && ( data & 0xff ) == 0x55 )
+ {
+ m_flash_mode = FM_READAMDID2;
+ }
+ else if( ( address & 0xffff ) == 0x2aaa && ( data & 0xff ) == 0x55 )
+ {
+ m_flash_mode = FM_READAMDID2;
+ }
+ else if( ( address & 0xfff ) == 0x555 && ( data & 0xff ) == 0x55 )
+ {
+ m_flash_mode = FM_READAMDID2;
+ }
+ else
+ {
+ logerror( "unexpected %08x=%02x in FM_READAMDID1\n", address, data & 0xff );
+ m_flash_mode = FM_NORMAL;
+ }
+ break;
+ case FM_READAMDID2:
+ if( ( address & 0xffff ) == 0x555 && ( data & 0xff ) == 0x90 )
+ {
+ m_flash_mode = FM_READAMDID3;
+ }
+ else if( ( address & 0xffff ) == 0x5555 && ( data & 0xff ) == 0x90 )
+ {
+ m_flash_mode = FM_READAMDID3;
+ }
+ else if( ( address & 0xfff ) == 0xaaa && ( data & 0xff ) == 0x90 )
+ {
+ m_flash_mode = FM_READAMDID3;
+ }
+ else if( ( address & 0xffff ) == 0x555 && ( data & 0xff ) == 0x80 )
+ {
+ m_flash_mode = FM_ERASEAMD1;
+ }
+ else if( ( address & 0xffff ) == 0x5555 && ( data & 0xff ) == 0x80 )
+ {
+ m_flash_mode = FM_ERASEAMD1;
+ }
+ else if( ( address & 0xfff ) == 0xaaa && ( data & 0xff ) == 0x80 )
+ {
+ m_flash_mode = FM_ERASEAMD1;
+ }
+ else if( ( address & 0xffff ) == 0x555 && ( data & 0xff ) == 0xa0 )
+ {
+ m_flash_mode = FM_BYTEPROGRAM;
+ }
+ else if( ( address & 0xffff ) == 0x5555 && ( data & 0xff ) == 0xa0 )
+ {
+ m_flash_mode = FM_BYTEPROGRAM;
+ }
+ else if( ( address & 0xfff ) == 0xaaa && ( data & 0xff ) == 0xa0 )
+ {
+ m_flash_mode = FM_BYTEPROGRAM;
+ }
+ else if( ( address & 0xffff ) == 0x555 && ( data & 0xff ) == 0xf0 )
+ {
+ m_flash_mode = FM_NORMAL;
+ }
+ else if( ( address & 0xffff ) == 0x5555 && ( data & 0xff ) == 0xf0 )
+ {
+ m_flash_mode = FM_NORMAL;
+ }
+ else if( ( address & 0xfff ) == 0xaaa && ( data & 0xff ) == 0xf0 )
+ {
+ m_flash_mode = FM_NORMAL;
+ }
+ else if( ( address & 0xffff ) == 0x5555 && ( data & 0xff ) == 0xb0 && m_maker_id == 0x62 && m_device_id == 0x13 )
+ {
+ m_flash_mode = FM_BANKSELECT;
+ }
+ else
+ {
+ logerror( "unexpected %08x=%02x in FM_READAMDID2\n", address, data & 0xff );
+ m_flash_mode = FM_NORMAL;
+ }
+ break;
+ case FM_ERASEAMD1:
+ if( ( address & 0xfff ) == 0x555 && ( data & 0xff ) == 0xaa )
+ {
+ m_flash_mode = FM_ERASEAMD2;
+ }
+ else if( ( address & 0xfff ) == 0xaaa && ( data & 0xff ) == 0xaa )
+ {
+ m_flash_mode = FM_ERASEAMD2;
+ }
+ else
+ {
+ logerror( "unexpected %08x=%02x in FM_ERASEAMD1\n", address, data & 0xff );
+ }
+ break;
+ case FM_ERASEAMD2:
+ if( ( address & 0xffff ) == 0x2aa && ( data & 0xff ) == 0x55 )
+ {
+ m_flash_mode = FM_ERASEAMD3;
+ }
+ else if( ( address & 0xffff ) == 0x2aaa && ( data & 0xff ) == 0x55 )
+ {
+ m_flash_mode = FM_ERASEAMD3;
+ }
+ else if( ( address & 0xfff ) == 0x555 && ( data & 0xff ) == 0x55 )
+ {
+ m_flash_mode = FM_ERASEAMD3;
+ }
+ else
+ {
+ logerror( "unexpected %08x=%02x in FM_ERASEAMD2\n", address, data & 0xff );
+ }
+ break;
+ case FM_ERASEAMD3:
+ if( (( address & 0xfff ) == 0x555 && ( data & 0xff ) == 0x10 ) ||
+ (( address & 0xfff ) == 0xaaa && ( data & 0xff ) == 0x10 ) )
+ {
+ // chip erase
+ for (offs_t offs = 0; offs < m_size; offs++)
+ m_addrspace[0]->write_byte(offs, 0xff);
+
+ m_status = 1 << 3;
+ m_flash_mode = FM_ERASEAMD4;
+
+ if (m_sector_is_4k)
+ {
+ m_timer->adjust( attotime::from_seconds( 1 ) );
+ }
+ else
+ {
+ m_timer->adjust( attotime::from_seconds( 16 ) );
+ }
+ }
+ else if( ( data & 0xff ) == 0x30 )
+ {
+ // sector erase
+ // clear the 4k/64k block containing the current address to all 0xffs
+ UINT32 base = address * ((m_bits == 16) ? 2 : 1);
+ if (m_sector_is_4k)
+ {
+ for (offs_t offs = 0; offs < 4 * 1024; offs++)
+ m_addrspace[0]->write_byte((base & ~0xfff) + offs, 0xff);
+ m_erase_sector = address & ((m_bits == 16) ? ~0x7ff : ~0xfff);
+ m_timer->adjust( attotime::from_msec( 125 ) );
+ }
+ else
+ {
+ for (offs_t offs = 0; offs < 64 * 1024; offs++)
+ m_addrspace[0]->write_byte((base & ~0xffff) + offs, 0xff);
+ m_erase_sector = address & ((m_bits == 16) ? ~0x7fff : ~0xffff);
+ m_timer->adjust( attotime::from_seconds( 1 ) );
+ }
+
+ m_status = 1 << 3;
+ m_flash_mode = FM_ERASEAMD4;
+ }
+ else
+ {
+ logerror( "unexpected %08x=%02x in FM_ERASEAMD3\n", address, data & 0xff );
+ }
+ break;
+ case FM_BYTEPROGRAM:
+ switch( m_bits )
+ {
+ case 8:
+ {
+ m_addrspace[0]->write_byte(address, data);
+ }
+ break;
+ default:
+ logerror( "FM_BYTEPROGRAM not supported when m_bits == %d\n", m_bits );
+ break;
+ }
+ m_flash_mode = FM_NORMAL;
+ break;
+ case FM_WRITEPART1:
+ switch( m_bits )
+ {
+ case 8:
+ {
+ m_addrspace[0]->write_byte(address, data);
+ }
+ break;
+ case 16:
+ {
+ m_addrspace[0]->write_word(address * 2, data);
+ }
+ break;
+ default:
+ logerror( "FM_WRITEPART1 not supported when m_bits == %d\n", m_bits );
+ break;
+ }
+ m_status = 0x80;
+ m_flash_mode = FM_READSTATUS;
+ break;
+ case FM_CLEARPART1:
+ if( ( data & 0xff ) == 0xd0 )
+ {
+ // clear the 64k block containing the current address to all 0xffs
+ UINT32 base = address * ((m_bits == 16) ? 2 : 1);
+ for (offs_t offs = 0; offs < 64 * 1024; offs++)
+ m_addrspace[0]->write_byte((base & ~0xffff) + offs, 0xff);
+
+ m_status = 0x00;
+ m_flash_mode = FM_READSTATUS;
+
+ m_timer->adjust( attotime::from_seconds( 1 ) );
+ break;
+ }
+ else
+ {
+ logerror( "unexpected %02x in FM_CLEARPART1\n", data & 0xff );
+ }
+ break;
+ case FM_SETMASTER:
+ switch( data & 0xff )
+ {
+ case 0xf1:
+ m_flash_master_lock = true;
+ break;
+ case 0xd0:
+ m_flash_master_lock = false;
+ break;
+ default:
+ logerror( "unexpected %08x=%02x in FM_SETMASTER:\n", address, data & 0xff );
+ break;
+ }
+ m_flash_mode = FM_NORMAL;
+ break;
+ case FM_BANKSELECT:
+ m_bank = data & 0xff;
+ m_flash_mode = FM_NORMAL;
+ break;
+ }
+}
diff --git a/trunk/src/emu/machine/intelfsh.h b/trunk/src/emu/machine/intelfsh.h
new file mode 100644
index 00000000000..c913f0dcf87
--- /dev/null
+++ b/trunk/src/emu/machine/intelfsh.h
@@ -0,0 +1,255 @@
+/*
+ Intel Flash ROM emulation
+*/
+
+#ifndef _INTELFLASH_H_
+#define _INTELFLASH_H_
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_INTEL_28F016S5_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, INTEL_28F016S5, 0)
+
+#define MCFG_SHARP_LH28F016S_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, SHARP_LH28F016S, 0)
+
+#define MCFG_FUJITSU_29F016A_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, FUJITSU_29F016A, 0)
+
+#define MCFG_FUJITSU_29DL16X_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, FUJITSU_29DL16X, 0)
+
+#define MCFG_INTEL_E28F400_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, INTEL_E28F400, 0)
+
+#define MCFG_MACRONIX_29L001MC_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, MACRONIX_29L001MC, 0)
+
+#define MCFG_PANASONIC_MN63F805MNP_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, PANASONIC_MN63F805MNP, 0)
+
+#define MCFG_SANYO_LE26FV10N1TS_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, SANYO_LE26FV10N1TS, 0)
+
+#define MCFG_SHARP_LH28F400_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, SHARP_LH28F400, 0)
+
+#define MCFG_INTEL_E28F008SA_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, INTEL_E28F008SA, 0)
+
+#define MCFG_INTEL_TE28F160_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, INTEL_TE28F160, 0)
+
+#define MCFG_SHARP_UNK128MBIT_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, SHARP_UNK128MBIT, 0)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class intelfsh_device;
+
+
+// ======================> intelfsh_device
+
+class intelfsh_device : public device_t,
+ public device_memory_interface,
+ public device_nvram_interface
+{
+public:
+ enum
+ {
+ // 8-bit variants
+ FLASH_INTEL_28F016S5 = 0x0800,
+ FLASH_FUJITSU_29F016A,
+ FLASH_FUJITSU_29DL16X,
+ FLASH_SHARP_LH28F016S,
+ FLASH_INTEL_E28F008SA,
+ FLASH_MACRONIX_29L001MC,
+ FLASH_PANASONIC_MN63F805MNP,
+ FLASH_SANYO_LE26FV10N1TS,
+
+ // 16-bit variants
+ FLASH_SHARP_LH28F400 = 0x1000,
+ FLASH_INTEL_E28F400,
+ FLASH_INTEL_TE28F160,
+ FLASH_SHARP_UNK128MBIT
+ };
+
+protected:
+ // construction/destruction
+ intelfsh_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT32 variant);
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
+
+ // device_nvram_interface overrides
+ virtual void nvram_default();
+ virtual void nvram_read(emu_file &file);
+ virtual void nvram_write(emu_file &file);
+
+ // derived helpers
+ UINT32 read_full(UINT32 offset);
+ void write_full(UINT32 offset, UINT32 data);
+
+ // configuration state
+ address_space_config m_space_config;
+ UINT32 m_type;
+ INT32 m_size;
+ UINT8 m_bits;
+ UINT8 m_device_id;
+ UINT8 m_maker_id;
+ bool m_sector_is_4k;
+
+ // internal state
+ UINT8 m_status;
+ INT32 m_erase_sector;
+ INT32 m_flash_mode;
+ bool m_flash_master_lock;
+ emu_timer * m_timer;
+ INT32 m_bank;
+};
+
+
+// ======================> intelfsh8_device
+
+class intelfsh8_device : public intelfsh_device
+{
+protected:
+ // construction/destruction
+ intelfsh8_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT32 variant);
+
+public:
+ // public interface
+ UINT8 read(offs_t offset) { return read_full(offset); }
+ void write(offs_t offset, UINT8 data) { write_full(offset, data); }
+
+ UINT8 read_raw(offs_t offset) { return m_addrspace[0]->read_byte(offset); }
+ void write_raw(offs_t offset, UINT8 data) { m_addrspace[0]->write_byte(offset, data); }
+};
+
+
+// ======================> intelfsh16_device
+
+class intelfsh16_device : public intelfsh_device
+{
+protected:
+ // construction/destruction
+ intelfsh16_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT32 variant);
+
+public:
+ // public interface
+ UINT16 read(offs_t offset) { return read_full(offset); }
+ void write(offs_t offset, UINT16 data) { write_full(offset, data); }
+
+ UINT16 read_raw(offs_t offset) { return m_addrspace[0]->read_word(offset * 2); }
+ void write_raw(offs_t offset, UINT16 data) { m_addrspace[0]->write_word(offset * 2, data); }
+};
+
+
+// ======================> trivial variants
+
+// 8-bit variants
+class intel_28f016s5_device : public intelfsh8_device
+{
+public:
+ intel_28f016s5_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class fujitsu_29f016a_device : public intelfsh8_device
+{
+public:
+ fujitsu_29f016a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class fujitsu_29dl16x_device : public intelfsh8_device
+{
+public:
+ fujitsu_29dl16x_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class sharp_lh28f016s_device : public intelfsh8_device
+{
+public:
+ sharp_lh28f016s_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class intel_e28f008sa_device : public intelfsh8_device
+{
+public:
+ intel_e28f008sa_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class macronix_29l001mc_device : public intelfsh8_device
+{
+public:
+ macronix_29l001mc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class panasonic_mn63f805mnp_device : public intelfsh8_device
+{
+public:
+ panasonic_mn63f805mnp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class sanyo_le26fv10n1ts_device : public intelfsh8_device
+{
+public:
+ sanyo_le26fv10n1ts_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+
+// 16-bit variants
+class sharp_lh28f400_device : public intelfsh16_device
+{
+public:
+ sharp_lh28f400_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class intel_te28f160_device : public intelfsh16_device
+{
+public:
+ intel_te28f160_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class intel_e28f400_device : public intelfsh16_device
+{
+public:
+ intel_e28f400_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class sharp_unk128mbit_device : public intelfsh16_device
+{
+public:
+ sharp_unk128mbit_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+
+
+// device type definition
+extern const device_type INTEL_28F016S5;
+extern const device_type SHARP_LH28F016S;
+extern const device_type FUJITSU_29F016A;
+extern const device_type FUJITSU_29DL16X;
+extern const device_type INTEL_E28F400;
+extern const device_type MACRONIX_29L001MC;
+extern const device_type PANASONIC_MN63F805MNP;
+extern const device_type SANYO_LE26FV10N1TS;
+
+extern const device_type SHARP_LH28F400;
+extern const device_type INTEL_E28F008SA;
+extern const device_type INTEL_TE28F160;
+extern const device_type SHARP_UNK128MBIT;
+
+
+#endif
diff --git a/trunk/src/emu/machine/jvsdev.c b/trunk/src/emu/machine/jvsdev.c
new file mode 100644
index 00000000000..ebed2095d40
--- /dev/null
+++ b/trunk/src/emu/machine/jvsdev.c
@@ -0,0 +1,254 @@
+#include "jvsdev.h"
+#include "jvshost.h"
+
+void jvs_device::static_set_jvs_host_tag(device_t &device, const char *jvs_host_tag)
+{
+ jvs_device &jvsdev = downcast<jvs_device &>(device);
+ jvsdev.jvs_host_tag = jvs_host_tag;
+}
+
+jvs_device::jvs_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, type, name, tag, owner, clock)
+{
+ jvs_host_tag = 0;
+ next_device = 0;
+}
+
+const char *jvs_device::device_id()
+{
+ return "";
+}
+
+UINT8 jvs_device::command_format_version()
+{
+ return 0x13;
+}
+
+UINT8 jvs_device::jvs_standard_version()
+{
+ return 0x30;
+}
+
+UINT8 jvs_device::comm_method_version()
+{
+ return 0x10;
+}
+
+void jvs_device::chain(jvs_device *dev)
+{
+ if(next_device)
+ next_device->chain(dev);
+ else
+ next_device = dev;
+}
+
+void jvs_device::message(UINT8 dest, const UINT8 *send_buffer, UINT32 send_size, UINT8 *recv_buffer, UINT32 &recv_size)
+{
+ recv_size = 0;
+
+ // Set Address special case
+ if(send_size == 2 && send_buffer[0] == 0xf1) {
+ if(next_device && !next_device->get_address_set_line())
+ next_device->message(dest, send_buffer, send_size, recv_buffer, recv_size);
+ else {
+ jvs_address = send_buffer[1];
+ recv_size = 2;
+ recv_buffer[0] = 0x01;
+ recv_buffer[1] = 0x01;
+ }
+ return;
+ }
+
+ // dest=0xff is broadcast
+ if(dest == 0xff || dest == jvs_address) {
+ const UINT8 *s = send_buffer;
+ UINT8 *d = recv_buffer;
+ *d++ = 0x01;
+ while(s < send_buffer + send_size) {
+ int len = handle_message(s, send_size-(s-send_buffer), d);
+ if(len == -1) {
+ // Unknown command
+ recv_size = 1;
+ recv_buffer[0] = 0x02;
+ return;
+ } else if(len == 0) {
+ // Incorrect parameter
+ *d++ = 0x02;
+ break;
+ } else
+ s += len;
+ }
+ recv_size = d - recv_buffer;
+ }
+
+ // Pass along the message if the device hasn't replied
+ // Should we cumulate answers instead?
+ if(next_device && !recv_size)
+ next_device->message(dest, send_buffer, send_size, recv_buffer, recv_size);
+}
+
+int jvs_device::handle_message(const UINT8 *send_buffer, UINT32 send_size, UINT8 *&recv_buffer)
+{
+ UINT32 old_reset_counter = jvs_reset_counter;
+ jvs_reset_counter = 0;
+
+ switch(send_buffer[0]) {
+ case 0xf0:
+ if(send_size < 2 || send_buffer[1] != 0xd9)
+ return 0;
+
+ // Reset, must be sent twice
+ jvs_reset_counter = old_reset_counter+1;
+ if(jvs_reset_counter == 2)
+ device_reset();
+ return 2;
+
+ case 0x10: {
+ const char *id = device_id();
+ int len = strlen(id)+1;
+ *recv_buffer++ = 0x01;
+ memcpy(recv_buffer, id, len);
+ recv_buffer += len;
+ return 1;
+ }
+
+ case 0x11:
+ *recv_buffer++ = 0x01;
+ *recv_buffer++ = command_format_version();
+ return 1;
+
+ case 0x12:
+ *recv_buffer++ = 0x01;
+ *recv_buffer++ = jvs_standard_version();
+ return 1;
+
+ case 0x13:
+ *recv_buffer++ = 0x01;
+ *recv_buffer++ = comm_method_version();
+ return 1;
+
+ case 0x14:
+ *recv_buffer++ = 0x01;
+ function_list(recv_buffer);
+ *recv_buffer++ = 0x00;
+ return 1;
+
+ case 0x20:
+ if(send_size < 3)
+ return 0;
+ *recv_buffer++ = 0x01;
+ return switches(recv_buffer, send_buffer[1], send_buffer[2]) ? 3 : 0;
+
+ case 0x21:
+ if(send_size < 2)
+ return 0;
+ *recv_buffer++ = 0x01;
+ return coin_counters(recv_buffer, send_buffer[1]) ? 2 : 0;
+
+ case 0x22:
+ if(send_size < 2)
+ return 0;
+ *recv_buffer++ = 0x01;
+ return analogs(recv_buffer, send_buffer[1]) ? 2 : 0;
+
+ case 0x30:
+ if(send_size < 4)
+ return 0;
+ *recv_buffer++ = 0x01;
+ return coin_add(send_buffer[1], -((send_buffer[2] << 8) | send_buffer[3])) ? 4 : 0;
+
+ case 0x31:
+ if(send_size < 4)
+ return 0;
+ *recv_buffer++ = 0x01;
+ return coin_add(send_buffer[1], ((send_buffer[2] << 8) | send_buffer[3])) ? 4 : 0;
+
+ case 0x32:
+ if(send_size < 2 || send_size < 2+send_buffer[1])
+ return 0;
+ *recv_buffer++ = 0x01;
+ return swoutputs(send_buffer[1], send_buffer+2) ? 2+send_buffer[1] : 0;
+
+ case 0x38:
+ if(send_size < 3)
+ return 0;
+ *recv_buffer++ = 0x01;
+ return swoutputs(send_buffer[1], send_buffer[2]) ? 3 : 0;
+
+ default:
+ logerror("JVSDEV: unhandled command %02x\n", send_buffer[0]);
+ return 0;
+ }
+
+ return -1;
+}
+
+bool jvs_device::get_address_set_line()
+{
+ return jvs_address != 0xff && (!next_device || next_device->get_address_set_line());
+}
+
+void jvs_device::device_start()
+{
+ jvs_host *host = machine().device<jvs_host>(jvs_host_tag);
+ if(!host)
+ fatalerror("JVS device %s could not find JVS host %s\n", tag(), jvs_host_tag);
+ host->add_device(this);
+
+ save_item(NAME(jvs_address));
+ save_item(NAME(jvs_reset_counter));
+}
+
+void jvs_device::device_reset()
+{
+ jvs_address = 0xff;
+ jvs_reset_counter = 0;
+ jvs_outputs = 0;
+}
+
+void jvs_device::function_list(UINT8 *&buf)
+{
+}
+
+bool jvs_device::coin_counters(UINT8 *&buf, UINT8 count)
+{
+ return false;
+}
+
+bool jvs_device::coin_add(UINT8 slot, INT32 count)
+{
+ return false;
+}
+
+
+bool jvs_device::switches(UINT8 *&buf, UINT8 count_players, UINT8 bytes_per_switch)
+{
+ return false;
+}
+
+bool jvs_device::analogs(UINT8 *&buf, UINT8 count)
+{
+ return false;
+}
+
+bool jvs_device::swoutputs(UINT8 count, const UINT8 *vals)
+{
+ return false;
+}
+
+bool jvs_device::swoutputs(UINT8 id, UINT8 val)
+{
+ return false;
+}
+
+void jvs_device::handle_output(const char *tag, UINT8 id, UINT8 val)
+{
+ UINT32 m = 1 << id;
+ switch(val) {
+ case 0: jvs_outputs &= ~m; break;
+ case 1: jvs_outputs |= m; break;
+ case 2: jvs_outputs ^= m; break;
+ }
+
+ input_port_write_safe(machine(), tag, jvs_outputs, m);
+}
+
diff --git a/trunk/src/emu/machine/jvsdev.h b/trunk/src/emu/machine/jvsdev.h
new file mode 100644
index 00000000000..23e01a88861
--- /dev/null
+++ b/trunk/src/emu/machine/jvsdev.h
@@ -0,0 +1,53 @@
+#ifndef __JVSDEV_H__
+#define __JVSDEV_H__
+
+#include "emu.h"
+
+#define MCFG_JVS_DEVICE_ADD(_tag, _type, _host) \
+ MCFG_DEVICE_ADD(_tag, _type, 0) \
+ jvs_device::static_set_jvs_host_tag(*device, _host); \
+
+class jvs_host;
+
+class jvs_device : public device_t
+{
+public:
+ jvs_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
+ static void static_set_jvs_host_tag(device_t &device, const char *jvs_host_tag);
+
+ void chain(jvs_device *dev);
+ void message(UINT8 dest, const UINT8 *send_buffer, UINT32 send_size, UINT8 *recv_buffer, UINT32 &recv_size);
+ bool get_address_set_line();
+
+protected:
+ UINT32 jvs_outputs;
+
+ void handle_output(const char *tag, UINT8 id, UINT8 val);
+
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // JVS device overrides
+ virtual const char *device_id();
+ virtual UINT8 command_format_version();
+ virtual UINT8 jvs_standard_version();
+ virtual UINT8 comm_method_version();
+ virtual void function_list(UINT8 *&buf);
+ virtual bool switches(UINT8 *&buf, UINT8 count_players, UINT8 bytes_per_switch);
+ virtual bool coin_counters(UINT8 *&buf, UINT8 count);
+ virtual bool coin_add(UINT8 slot, INT32 count);
+ virtual bool analogs(UINT8 *&buf, UINT8 count);
+ virtual bool swoutputs(UINT8 count, const UINT8 *vals);
+ virtual bool swoutputs(UINT8 id, UINT8 val);
+
+private:
+ const char *jvs_host_tag;
+ jvs_device *next_device;
+ UINT8 jvs_address;
+ UINT32 jvs_reset_counter;
+
+ int handle_message(const UINT8 *send_buffer, UINT32 send_size, UINT8 *&recv_buffer);
+};
+
+#endif
diff --git a/trunk/src/emu/machine/jvshost.c b/trunk/src/emu/machine/jvshost.c
new file mode 100644
index 00000000000..438c75b538d
--- /dev/null
+++ b/trunk/src/emu/machine/jvshost.c
@@ -0,0 +1,157 @@
+#include "jvshost.h"
+#include "jvsdev.h"
+
+void jvs_host::add_device(jvs_device *dev)
+{
+ if(first_device)
+ first_device->chain(dev);
+ else
+ first_device = dev;
+}
+
+void jvs_host::device_start()
+{
+ save_item(NAME(send_size));
+ save_item(NAME(recv_size));
+ save_item(NAME(send_buffer));
+ save_item(NAME(recv_buffer));
+ save_item(NAME(recv_is_encoded));
+}
+
+void jvs_host::device_reset()
+{
+ send_size = recv_size = 0;
+ recv_is_encoded = false;
+ memset(send_buffer, 0, sizeof(send_buffer));
+ memset(recv_buffer, 0, sizeof(recv_buffer));
+}
+
+jvs_host::jvs_host(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, type, name, tag, owner, clock)
+{
+ first_device = 0;
+}
+
+void jvs_host::push(UINT8 val)
+{
+ send_buffer[send_size++] = val;
+}
+
+void jvs_host::commit_raw()
+{
+ recv_size = 0;
+ if(!send_size)
+ return;
+
+ // Message must:
+ // - have a non-zero destination in the first byte
+ // - have the message length without the two header bytes but with the checksum byte in the second byte
+ // - have at least one command byte
+ if(send_size < 3 || send_buffer[0] == 0x00 || send_buffer[1] != send_size-1) {
+ logerror("JVS checksum error\n");
+ // "This message is crap" doesn't exist so call it checksum error
+ recv_buffer[0] = 0x00;
+ recv_buffer[1] = 0x02;
+ recv_buffer[2] = 0x03;
+ recv_size = 3;
+
+ } else {
+ if(first_device) {
+ first_device->message(send_buffer[0], send_buffer+2, send_size-2, recv_buffer+2, recv_size);
+ recv_is_encoded = false;
+ if(recv_size) {
+ // Add the reply header, host is always destination 0x00
+ recv_buffer[0] = 0x00;
+ recv_buffer[1] = recv_size+1;
+ recv_size += 2;
+ }
+ } else
+ recv_size = 0;
+ }
+ send_size = 0;
+}
+
+void jvs_host::commit_encoded()
+{
+ recv_size = 0;
+ if(!send_size)
+ return;
+ decode(send_buffer, send_size);
+ commit_raw();
+}
+
+
+void jvs_host::get_raw_reply(const UINT8 *&buffer, UINT32 &size)
+{
+ if(recv_is_encoded) {
+ decode(recv_buffer, recv_size);
+ recv_is_encoded = false;
+ }
+ buffer = recv_buffer;
+ size = recv_size;
+}
+
+void jvs_host::get_encoded_reply(const UINT8 *&buffer, UINT32 &size)
+{
+ if(!recv_is_encoded) {
+ encode(recv_buffer, recv_size);
+ recv_is_encoded = true;
+ }
+ buffer = recv_buffer;
+ size = recv_size;
+}
+
+bool jvs_host::get_presence_line()
+{
+ return first_device != 0;
+}
+
+bool jvs_host::get_address_set_line()
+{
+ return first_device && first_device->get_address_set_line();
+}
+
+
+void jvs_host::encode(UINT8 *buffer, UINT32 &size)
+{
+ if(!size)
+ return;
+ UINT32 add = 1;
+ for(UINT32 i=0; i<size; i++)
+ if(buffer[i] == 0xd0 || buffer[i] == 0xe0)
+ add++;
+ UINT32 nsize = size+add;
+ for(UINT32 i=size; i; i--) {
+ UINT8 t = buffer[i-1];
+ if(t == 0xd0 || t == 0xe0) {
+ buffer[i+add-1] = t-1;
+ buffer[i+add-2] = 0xd0;
+ add--;
+ } else
+ buffer[i+add-1] = t;
+ }
+ buffer[0] = 0xe0;
+ UINT8 sum = 0;
+ for(UINT32 i=1; i<nsize; i++)
+ sum += buffer[i];
+ buffer[nsize++] = sum;
+ size = nsize;
+}
+
+void jvs_host::decode(UINT8 *buffer, UINT32 &size)
+{
+ if(!size)
+ return;
+ UINT32 pos = 0;
+ for(UINT32 i=0; i<size-1; i++) {
+ UINT8 t = buffer[i];
+ if(!i && t == 0xe0)
+ continue;
+ if(t == 0xd0) {
+ i++;
+ t = buffer[i]+1;
+ }
+ buffer[pos++] = t;
+ }
+ size = pos;
+}
+
diff --git a/trunk/src/emu/machine/jvshost.h b/trunk/src/emu/machine/jvshost.h
new file mode 100644
index 00000000000..3a1fcc47add
--- /dev/null
+++ b/trunk/src/emu/machine/jvshost.h
@@ -0,0 +1,45 @@
+#ifndef __JVSHOST_H__
+#define __JVSHOST_H__
+
+#include "emu.h"
+
+class jvs_device;
+
+class jvs_host : public device_t {
+public:
+ jvs_host(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
+
+ void add_device(jvs_device *dev);
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+
+ void push(UINT8 val);
+ void commit_raw();
+ void commit_encoded();
+
+ void get_raw_reply(const UINT8 *&buffer, UINT32 &size);
+ void get_encoded_reply(const UINT8 *&buffer, UINT32 &size);
+
+ bool get_presence_line();
+ bool get_address_set_line();
+
+private:
+ enum { BUFFER_SIZE = 512 };
+
+ jvs_device *first_device;
+
+ UINT32 send_size, recv_size;
+ UINT8 send_buffer[BUFFER_SIZE];
+ UINT8 recv_buffer[BUFFER_SIZE];
+
+ bool recv_is_encoded;
+
+ void encode(UINT8 *buffer, UINT32 &size);
+ void decode(UINT8 *buffer, UINT32 &size);
+};
+
+#endif
diff --git a/trunk/src/emu/machine/k033906.c b/trunk/src/emu/machine/k033906.c
new file mode 100644
index 00000000000..2e8aa7dac70
--- /dev/null
+++ b/trunk/src/emu/machine/k033906.c
@@ -0,0 +1,161 @@
+/***************************************************************************
+
+ Konami IC 033906 (PCI bridge)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "k033906.h"
+#include "video/voodoo.h"
+#include "devhelpr.h"
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type K033906 = &device_creator<k033906_device>;
+
+//-------------------------------------------------
+// k033906_device - constructor
+//-------------------------------------------------
+
+k033906_device::k033906_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, K033906, "Konami 033906", tag, owner, clock)
+{
+
+}
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void k033906_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const k033906_interface *intf = reinterpret_cast<const k033906_interface *>(static_config());
+ if (intf != NULL)
+ {
+ *static_cast<k033906_interface *>(this) = *intf;
+ }
+
+ // or initialize to defaults if none provided
+ else
+ {
+ m_voodoo_tag = NULL;
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void k033906_device::device_start()
+{
+ m_voodoo = machine().device(m_voodoo_tag);
+
+ m_reg = auto_alloc_array(machine(), UINT32, 256);
+ m_ram = auto_alloc_array(machine(), UINT32, 32768);
+
+ m_reg_set = 0;
+
+ save_pointer(NAME(m_reg), 256);
+ save_pointer(NAME(m_ram), 32768);
+ save_item(NAME(m_reg_set));
+}
+
+
+WRITE_LINE_DEVICE_HANDLER_TRAMPOLINE(k033906, k033906_set_reg)
+{
+ m_reg_set = state & 1;
+}
+
+UINT32 k033906_device::k033906_reg_r(int reg)
+{
+ switch (reg)
+ {
+ case 0x00: return 0x0001121a; // PCI Vendor ID (0x121a = 3dfx), Device ID (0x0001 = Voodoo)
+ case 0x02: return 0x04000000; // Revision ID
+ case 0x04: return m_reg[0x04]; // memBaseAddr
+ case 0x0f: return m_reg[0x0f]; // interrupt_line, interrupt_pin, min_gnt, max_lat
+
+ default:
+ fatalerror("%s: k033906_reg_r: %08X", machine().describe_context(), reg);
+ }
+ return 0;
+}
+
+void k033906_device::k033906_reg_w(int reg, UINT32 data)
+{
+ switch (reg)
+ {
+ case 0x00:
+ break;
+
+ case 0x01: // command register
+ break;
+
+ case 0x04: // memBaseAddr
+ {
+ if (data == 0xffffffff)
+ {
+ m_reg[0x04] = 0xff000000;
+ }
+ else
+ {
+ m_reg[0x04] = data & 0xff000000;
+ }
+ break;
+ }
+
+ case 0x0f: // interrupt_line, interrupt_pin, min_gnt, max_lat
+ {
+ m_reg[0x0f] = data;
+ break;
+ }
+
+ case 0x10: // initEnable
+ {
+ voodoo_set_init_enable(m_voodoo, data);
+ break;
+ }
+
+ case 0x11: // busSnoop0
+ case 0x12: // busSnoop1
+ break;
+
+ case 0x38: // ???
+ break;
+
+ default:
+ fatalerror("%s:K033906_w: %08X, %08X", machine().describe_context(), data, reg);
+ }
+}
+
+READ32_DEVICE_HANDLER_TRAMPOLINE(k033906, k033906_r)
+{
+ if(m_reg_set)
+ {
+ return k033906_reg_r(offset);
+ }
+ else
+ {
+ return m_ram[offset];
+ }
+}
+
+WRITE32_DEVICE_HANDLER_TRAMPOLINE(k033906, k033906_w)
+{
+ if(m_reg_set)
+ {
+ k033906_reg_w(offset, data);
+ }
+ else
+ {
+ m_ram[offset] = data;
+ }
+}
diff --git a/trunk/src/emu/machine/k033906.h b/trunk/src/emu/machine/k033906.h
new file mode 100644
index 00000000000..7a46d253539
--- /dev/null
+++ b/trunk/src/emu/machine/k033906.h
@@ -0,0 +1,89 @@
+/***************************************************************************
+
+ Konami 033906
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __K033906_H__
+#define __K033906_H__
+
+#include "emu.h"
+
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_K033906_ADD(_tag, _config) \
+ MCFG_DEVICE_ADD(_tag, K033906, 0) \
+ MCFG_DEVICE_CONFIG(_config)
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+
+// ======================> k033906_interface
+
+struct k033906_interface
+{
+ const char *m_voodoo_tag;
+};
+
+
+
+// ======================> k033906_device
+
+class k033906_device : public device_t,
+ public k033906_interface
+{
+public:
+ // construction/destruction
+ k033906_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ UINT32 k033906_r(UINT32 offset);
+ void k033906_w(UINT32 offset, UINT32 data, UINT32 mem_mask);
+ void k033906_set_reg(UINT8 state);
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset() { }
+ virtual void device_post_load() { }
+ virtual void device_clock_changed() { }
+
+private:
+
+ UINT32 k033906_reg_r(int reg);
+ void k033906_reg_w(int reg, UINT32 data);
+
+ /* i/o lines */
+ UINT32 * m_reg;
+ UINT32 * m_ram;
+
+ int m_reg_set; // 1 = access reg / 0 = access ram
+
+ device_t *m_voodoo;
+};
+
+
+// device type definition
+extern const device_type K033906;
+
+
+
+/***************************************************************************
+ PROTOTYPES
+***************************************************************************/
+
+extern READ32_DEVICE_HANDLER( k033906_r );
+extern WRITE32_DEVICE_HANDLER( k033906_w );
+extern WRITE_LINE_DEVICE_HANDLER( k033906_set_reg );
+
+
+#endif /* __K033906_H__ */
diff --git a/trunk/src/emu/machine/k053252.c b/trunk/src/emu/machine/k053252.c
new file mode 100644
index 00000000000..76437b56eba
--- /dev/null
+++ b/trunk/src/emu/machine/k053252.c
@@ -0,0 +1,256 @@
+/***************************************************************************************************************************
+
+ Konami 053252 chip emulation, codenamed "CCU"
+
+ device emulation by Angelo Salese, based off notes by Olivier Galibert
+
+============================================================================================================================
+
+left res = current in game, right res = computed
+
+hexion: 02 FF 00 4D 00 73 00 00 01 1F 05 0E B7 7C 00 00 512x256 ~ 512x256 <- writes to e and f regs, in an irq ack fashion
+overdriv: 01 7F 00 22 00 0D 00 03 01 07 10 0F 73 00 00 00 304x256 ~ 305x224
+esckids: 01 7F 00 12 00 0D 00 01 01 07 08 07 73 00 00 00 304x224 ~ 321x240
+rollerg: 01 7F 00 23 00 1D 02 00 01 07 10 0F 73 00 02 00 288x224 ~ 288x224 <- writes to 6 and e regs, in an irq ack fashion
+gaiapols: 01 FB 00 19 00 37 00 00 01 06 10 0E 75 00 D1 00 376x224 ~ 380x224
+mmaulers: 01 7F 00 19 00 27 00 00 01 07 10 0F 73 00 00 00 288x224 ~ 288x224
+mystwarr: 01 7F 00 12 00 2E 00 00 01 07 11 0E 73 00 00 00 288x224 ~ 288x224
+metamrph: 01 7F 00 11 00 27 01 00 01 07 10 0F 74 00 00 00 288x224 ~ 288x224
+viostorm: 01 FF 00 16 00 39 00 00 01 07 11 0E 75 00 00 00 384x224 ~ 385x224
+mtlchamp: 01 FF 00 21 00 37 00 00 01 07 11 0E 74 00 00 00 384x224 ~ 384x224
+dbz: 01 FF 00 21 00 37 00 00 01 20 0C 0E 54 00 00 00 384x256 ~ 384x256
+dbz2: 01 FF 00 21 00 37 00 00 01 20 0C 0E 54 00 00 00 384x256 ~ 384x256
+xexex: 01 FF 00 21 00 37 01 00 00 20 0C 0E 54 00 00 00 384x256 ~ 384x256 (*)
+(all konamigx, cowboys of moo mesa, run & gun, dj main)
+
+(*) hblank duration 512 (0x200), hdisp 384 (0x180), vblank duration 288 (0x120), vdisp 256 (0x100)
+
+ Definitions from GX, look similar, all values big-endian, write-only:
+
+ 0-1: bits 9-0: HC - Total hblank duration (-1) Hres ~ (HC+1) - HFP - HBP - 8*(HSW+1)
+ 2-3: bits 8-0: HFP - HBlank front porch
+ 4-5: bits 8-0: HBP - HBlank back porch
+ 6 : bits 7-0: INT1EN
+ 7 : bits 7-0: INT2EN
+ 8-9: bits 8-0: VC - Total vblank duration
+ a : bits 7-0: VFP - VBlank front porch Vres ~ VC - VFP - VBP - (VSW+1)
+ b : bits 7-0: VBP - VBlank back porch
+ c : bits 7-4: VSW - V-Sync Width
+ c : bits 3-0: HSW - H-Sync Width
+ d : bits 7-0: INT-TIME
+ e : bits 7-0: INT1ACK
+ f : bits 7-0: INT2ACK
+
+ Read-only:
+ e-f: bits 8-0: VCT
+
+TODO:
+- xexex sets up 0x20 as the VC? default value?
+- xexex layers are offsetted if you try to use the CCU
+- understand how to interpret the back / front porch values, and remove the offset x/y hack
+
+***************************************************************************************************************************/
+
+
+#include "emu.h"
+#include "k053252.h"
+
+typedef struct _k053252_state k053252_state;
+struct _k053252_state
+{
+ UINT8 regs[16];
+ UINT16 hc,hfp,hbp;
+ UINT16 vc,vfp,vbp;
+ UINT8 vsw,hsw;
+
+ screen_device *screen;
+ devcb_resolved_write_line int1_en;
+ devcb_resolved_write_line int2_en;
+ devcb_resolved_write_line int1_ack;
+ devcb_resolved_write_line int2_ack;
+ //devcb_resolved_write8 int_time;
+ int offsx,offsy;
+};
+
+
+/*****************************************************************************
+ INLINE FUNCTIONS
+*****************************************************************************/
+
+INLINE k053252_state *k053252_get_safe_token( device_t *device )
+{
+ assert(device != NULL);
+ assert(device->type() == K053252);
+
+ return (k053252_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+INLINE const k053252_interface *k053252_get_interface( device_t *device )
+{
+ assert(device != NULL);
+ assert(device->type() == K053252);
+
+ return (const k053252_interface *) device->static_config();
+}
+
+/*****************************************************************************
+ DEVICE HANDLERS
+*****************************************************************************/
+
+READ8_DEVICE_HANDLER( k053252_r )
+{
+ k053252_state *k053252 = k053252_get_safe_token(device);
+
+ //TODO: debugger_access()
+ popmessage("Warning: k053252 read %02x, contact MAMEdev",offset);
+
+ return k053252->regs[offset];
+}
+
+static void k053252_res_change( device_t *device )
+{
+ k053252_state *k053252 = k053252_get_safe_token(device);
+
+ if(k053252->screen != NULL)
+ {
+ if(k053252->hc && k053252->vc &&
+ k053252->hbp && k053252->hfp &&
+ k053252->vbp && k053252->vfp &&
+ k053252->hsw && k053252->vsw) //safety checks
+ {
+ rectangle visarea;
+ //(HC+1) - HFP - HBP - 8*(HSW+1)
+ //VC - VFP - VBP - (VSW+1)
+ attoseconds_t refresh = HZ_TO_ATTOSECONDS(device->clock()) * (k053252->hc) * k053252->vc;
+
+ //printf("H %d %d %d %d\n",k053252->hc,k053252->hfp,k053252->hbp,k053252->hsw);
+ //printf("V %d %d %d %d\n",k053252->vc,k053252->vfp,k053252->vbp,k053252->vsw);
+
+ visarea.min_x = k053252->offsx;
+ visarea.min_y = k053252->offsy;
+ visarea.max_x = k053252->offsx + k053252->hc - k053252->hfp - k053252->hbp - 8*(k053252->hsw) - 1;
+ visarea.max_y = k053252->offsy + k053252->vc - k053252->vfp - k053252->vbp - (k053252->vsw) - 1;
+
+ k053252->screen->configure(k053252->hc, k053252->vc, visarea, refresh);
+ }
+ }
+}
+
+WRITE8_DEVICE_HANDLER( k053252_w )
+{
+ k053252_state *k053252 = k053252_get_safe_token(device);
+
+ k053252->regs[offset] = data;
+
+ switch(offset)
+ {
+ case 0x00:
+ case 0x01:
+ k053252->hc = (k053252->regs[1]&0xff);
+ k053252->hc |= ((k053252->regs[0]&0x03)<<8);
+ k053252->hc ++;
+ logerror("%d (%04x) HC set\n",k053252->hc,k053252->hc);
+ k053252_res_change(device);
+ break;
+ case 0x02:
+ case 0x03:
+ k053252->hfp = (k053252->regs[3]&0xff);
+ k053252->hfp |= ((k053252->regs[2]&0x01)<<8);
+ logerror("%d (%04x) HFP set\n",k053252->hfp,k053252->hfp);
+ k053252_res_change(device);
+ break;
+ case 0x04:
+ case 0x05:
+ k053252->hbp = (k053252->regs[5]&0xff);
+ k053252->hbp |= ((k053252->regs[4]&0x01)<<8);
+ logerror("%d (%04x) HBP set\n",k053252->hbp,k053252->hbp);
+ k053252_res_change(device);
+ break;
+ case 0x06: k053252->int1_en(data); break;
+ case 0x07: k053252->int2_en(data); break;
+ case 0x08:
+ case 0x09:
+ k053252->vc = (k053252->regs[9]&0xff);
+ k053252->vc |= ((k053252->regs[8]&0x01)<<8);
+ logerror("%d (%04x) VC set\n",k053252->vc,k053252->vc);
+ k053252_res_change(device);
+ break;
+ case 0x0a:
+ k053252->vfp = (k053252->regs[0x0a]&0xff);
+ logerror("%d (%04x) VFP set\n",k053252->vfp,k053252->vfp);
+ k053252_res_change(device);
+ break;
+ case 0x0b:
+ k053252->vbp = (k053252->regs[0x0b]&0xff);
+ logerror("%d (%04x) VBP set\n",k053252->vbp,k053252->vbp);
+ k053252_res_change(device);
+ break;
+ case 0x0c:
+ k053252->vsw = ((k053252->regs[0x0c]&0xf0) >> 4) + 1;
+ k053252->hsw = ((k053252->regs[0x0c]&0x0f) >> 0) + 1;
+ logerror("%02x VSW / %02x HSW set\n",k053252->vsw,k053252->hsw);
+ k053252_res_change(device);
+ break;
+ //case 0x0d: k053252->int_time(data); break;
+ case 0x0e: k053252->int1_ack(1); break;
+ case 0x0f: k053252->int2_ack(1); break;
+ }
+}
+
+
+
+/*****************************************************************************
+ DEVICE INTERFACE
+*****************************************************************************/
+
+static DEVICE_START( k053252 )
+{
+ k053252_state *k053252 = k053252_get_safe_token(device);
+ const k053252_interface *intf = k053252_get_interface(device);
+
+ device->save_item(NAME(k053252->regs));
+ k053252->screen = device->machine().device<screen_device>(intf->screen);
+ k053252->int1_en.resolve(intf->int1_en, *device);
+ k053252->int2_en.resolve(intf->int2_en, *device);
+ k053252->int1_ack.resolve(intf->int1_ack, *device);
+ k053252->int2_ack.resolve(intf->int2_ack, *device);
+ //k053252->int_time.resolve(intf->int_time, *device);
+ k053252->offsx = intf->offsx;
+ k053252->offsy = intf->offsy;
+}
+
+static DEVICE_RESET( k053252 )
+{
+ k053252_state *k053252 = k053252_get_safe_token(device);
+ int i;
+
+ for (i = 0; i < 16; i++)
+ k053252->regs[i] = 0;
+
+ k053252->regs[0x08] = 1; // Xexex apparently does a wrong assignment for VC (sets up the INT enable register instead)
+}
+
+
+DEVICE_GET_INFO( k053252 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(k053252_state); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(k053252); break;
+ case DEVINFO_FCT_STOP: /* Nothing */ break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(k053252); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Konami 053252"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Konami Video IC"); 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;
+ }
+}
+
+DEFINE_LEGACY_DEVICE(K053252, k053252);
+
diff --git a/trunk/src/emu/machine/k053252.h b/trunk/src/emu/machine/k053252.h
new file mode 100644
index 00000000000..c6e3ffb1e1f
--- /dev/null
+++ b/trunk/src/emu/machine/k053252.h
@@ -0,0 +1,39 @@
+/** Konami 053252 **/
+/* CRT and interrupt control unit */
+#pragma once
+
+#ifndef __K053252_H__
+#define __K053252_H__
+
+#include "devlegcy.h"
+
+DECLARE_LEGACY_DEVICE(K053252, k053252);
+
+
+
+typedef struct _k053252_interface k053252_interface;
+struct _k053252_interface
+{
+ const char *screen;
+ devcb_write_line int1_en;
+ devcb_write_line int2_en;
+ devcb_write_line int1_ack;
+ devcb_write_line int2_ack;
+// devcb_write8 int_time;
+ int offsx;
+ int offsy;
+};
+
+
+#define MCFG_K053252_ADD(_tag, _clock, _interface) \
+ MCFG_DEVICE_ADD(_tag, K053252, _clock) \
+ MCFG_DEVICE_CONFIG(_interface)
+
+/** Konami 053252 **/
+/* CRT and interrupt control unit */
+READ8_DEVICE_HANDLER( k053252_r ); // CCU registers
+WRITE8_DEVICE_HANDLER( k053252_w );
+
+
+
+#endif /* __K033906_H__ */
diff --git a/trunk/src/emu/machine/k056230.c b/trunk/src/emu/machine/k056230.c
new file mode 100644
index 00000000000..4a5ead590b0
--- /dev/null
+++ b/trunk/src/emu/machine/k056230.c
@@ -0,0 +1,148 @@
+/***************************************************************************
+
+ Konami IC 056230 (LANC)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "k056230.h"
+#include "devhelpr.h"
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type K056230 = &device_creator<k056230_device>;
+
+//-------------------------------------------------
+// k056230_device - constructor
+//-------------------------------------------------
+
+k056230_device::k056230_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, K056230, "Konami 056230", tag, owner, clock)
+{
+
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void k056230_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const k056230_interface *intf = reinterpret_cast<const k056230_interface *>(static_config());
+ if (intf != NULL)
+ {
+ *static_cast<k056230_interface *>(this) = *intf;
+ }
+
+ // or initialize to defaults if none provided
+ else
+ {
+ m_cpu_tag = NULL;
+ m_is_thunderh = false;
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void k056230_device::device_start()
+{
+ if(m_cpu_tag)
+ {
+ m_cpu = machine().device(m_cpu_tag);
+ }
+ else
+ {
+ m_cpu = NULL;
+ }
+
+ m_ram = auto_alloc_array(machine(), UINT32, 0x2000);
+
+ save_pointer(NAME(m_ram), 0x2000);
+}
+
+
+READ8_DEVICE_HANDLER_TRAMPOLINE(k056230, k056230_r)
+{
+ switch (offset)
+ {
+ case 0: // Status register
+ {
+ return 0x08;
+ }
+ }
+
+// mame_printf_debug("k056230_r: %d at %08X\n", offset, cpu_get_pc(&space->device()));
+
+ return 0;
+}
+
+TIMER_CALLBACK( k056230_device::network_irq_clear_callback )
+{
+ reinterpret_cast<k056230_device*>(ptr)->network_irq_clear();
+}
+
+void k056230_device::network_irq_clear()
+{
+ if(m_cpu)
+ {
+ device_set_input_line(m_cpu, INPUT_LINE_IRQ2, CLEAR_LINE);
+ }
+}
+
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(k056230, k056230_w)
+{
+ switch(offset)
+ {
+ case 0: // Mode register
+ {
+ break;
+ }
+ case 1: // Control register
+ {
+ if(data & 0x20)
+ {
+ // Thunder Hurricane breaks otherwise...
+ if(!m_is_thunderh)
+ {
+ if(m_cpu)
+ {
+ device_set_input_line(m_cpu, INPUT_LINE_IRQ2, ASSERT_LINE);
+ }
+ machine().scheduler().timer_set(attotime::from_usec(10), FUNC(network_irq_clear_callback), 0, (void*)this);
+ }
+ }
+// else
+// device_set_input_line(k056230->cpu, INPUT_LINE_IRQ2, CLEAR_LINE);
+ break;
+ }
+ case 2: // Sub ID register
+ {
+ break;
+ }
+ }
+// mame_printf_debug("k056230_w: %d, %02X at %08X\n", offset, data, cpu_get_pc(&space->device()));
+}
+
+READ32_DEVICE_HANDLER_TRAMPOLINE(k056230, lanc_ram_r)
+{
+ //mame_printf_debug("LANC_RAM_r: %08X, %08X at %08X\n", offset, mem_mask, cpu_get_pc(&space->device()));
+ return m_ram[offset & 0x7ff];
+}
+
+WRITE32_DEVICE_HANDLER_TRAMPOLINE(k056230, lanc_ram_w)
+{
+ //mame_printf_debug("LANC_RAM_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, cpu_get_pc(&space->device()));
+ COMBINE_DATA(m_ram + (offset & 0x7ff));
+}
diff --git a/trunk/src/emu/machine/k056230.h b/trunk/src/emu/machine/k056230.h
new file mode 100644
index 00000000000..5d6d67ec103
--- /dev/null
+++ b/trunk/src/emu/machine/k056230.h
@@ -0,0 +1,89 @@
+/***************************************************************************
+
+ Konami 056230
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __K056230_H__
+#define __K056230_H__
+
+#include "emu.h"
+
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_K056230_ADD(_tag, _config) \
+ MCFG_DEVICE_ADD(_tag, K056230, 0) \
+ MCFG_DEVICE_CONFIG(_config)
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+
+// ======================> k056230_interface
+
+struct k056230_interface
+{
+ const char *m_cpu_tag;
+ bool m_is_thunderh;
+};
+
+
+
+// ======================> k056230_device
+
+class k056230_device : public device_t,
+ public k056230_interface
+{
+public:
+ // construction/destruction
+ k056230_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ UINT32 lanc_ram_r(UINT32 offset);
+ void lanc_ram_w(UINT32 offset, UINT32 data, UINT32 mem_mask);
+
+ UINT8 k056230_r(UINT32 offset);
+ void k056230_w(UINT32 offset, UINT8 data);
+
+ static TIMER_CALLBACK( network_irq_clear_callback );
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset() { }
+ virtual void device_post_load() { }
+ virtual void device_clock_changed() { }
+
+private:
+
+ void network_irq_clear();
+
+ UINT32 *m_ram;
+ device_t *m_cpu;
+};
+
+
+// device type definition
+extern const device_type K056230;
+
+
+
+/***************************************************************************
+ PROTOTYPES
+***************************************************************************/
+
+extern READ32_DEVICE_HANDLER( lanc_ram_r );
+extern WRITE32_DEVICE_HANDLER( lanc_ram_w );
+extern READ8_DEVICE_HANDLER( k056230_r );
+extern WRITE8_DEVICE_HANDLER( k056230_w );
+
+
+#endif /* __K056230_H__ */
diff --git a/trunk/src/emu/machine/laserdsc.h b/trunk/src/emu/machine/laserdsc.h
new file mode 100644
index 00000000000..09a3549d1b7
--- /dev/null
+++ b/trunk/src/emu/machine/laserdsc.h
@@ -0,0 +1,240 @@
+/*************************************************************************
+
+ laserdsc.h
+
+ Generic laserdisc support.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*************************************************************************/
+
+#pragma once
+
+#ifndef __LASERDSC_H__
+#define __LASERDSC_H__
+
+#include "chd.h"
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* types of players supported */
+enum
+{
+ LASERDISC_TYPE_UNKNOWN,
+ LASERDISC_TYPE_PIONEER_PR7820, /* Pioneer PR-7820 */
+ LASERDISC_TYPE_PIONEER_PR8210, /* Pioneer PR-8210 / LD-V1100 */
+ LASERDISC_TYPE_SIMUTREK_SPECIAL, /* Pioneer PR-8210 with mods */
+ LASERDISC_TYPE_PIONEER_LDV1000, /* Pioneer LD-V1000 */
+ LASERDISC_TYPE_PHILLIPS_22VP931, /* Phillips 22VP931 */
+ LASERDISC_TYPE_PHILLIPS_22VP932, /* Phillips 22VP932 (PAL) */
+ LASERDISC_TYPE_SONY_LDP1450 /* Sony LDP-1450 */
+};
+
+/* laserdisc control lines */
+#define LASERDISC_LINE_ENTER 0 /* "ENTER" key/line */
+#define LASERDISC_LINE_CONTROL 1 /* "CONTROL" line */
+#define LASERDISC_LINE_RESET 2 /* "RESET" line */
+#define LASERDISC_INPUT_LINES 3
+
+/* laserdisc status lines */
+#define LASERDISC_LINE_READY 0 /* "READY" line */
+#define LASERDISC_LINE_STATUS 1 /* "STATUS STROBE" line */
+#define LASERDISC_LINE_COMMAND 2 /* "COMMAND STROBE" line */
+#define LASERDISC_LINE_DATA_AVAIL 3 /* data available "line" */
+#define LASERDISC_OUTPUT_LINES 4
+
+/* laserdisc field codes */
+#define LASERDISC_CODE_WHITE_FLAG 11 /* boolean white flag */
+#define LASERDISC_CODE_LINE16 16 /* 24-bit line 16 code */
+#define LASERDISC_CODE_LINE17 17 /* 24-bit line 17 code */
+#define LASERDISC_CODE_LINE18 18 /* 24-bit line 18 code */
+#define LASERDISC_CODE_LINE1718 1718 /* 24-bit best of line 17/18 code */
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef chd_file *(*laserdisc_get_disc_func)(device_t *device);
+
+typedef void (*laserdisc_audio_func)(device_t *device, int samplerate, int samples, const INT16 *ch0, const INT16 *ch1);
+
+typedef void (*vp931_data_ready_func)(device_t *device, int state);
+
+typedef struct _laserdisc_config laserdisc_config;
+struct _laserdisc_config
+{
+ laserdisc_get_disc_func getdisc;
+ laserdisc_audio_func audio;
+ const char * sound;
+ const char * screen;
+
+ /* overlay information */
+ screen_update_func overupdate;
+ UINT32 overwidth, overheight, overformat;
+ rectangle overclip;
+ float overposx, overposy;
+ float overscalex, overscaley;
+};
+
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_LASERDISC_ADD(_tag, _type, _screen, _sound) \
+ MCFG_DEVICE_ADD(_tag, _type, 0) \
+ MCFG_DEVICE_CONFIG_DATAPTR(laserdisc_config, screen, _screen) \
+ MCFG_DEVICE_CONFIG_DATAPTR(laserdisc_config, sound, _sound) \
+
+#define MCFG_LASERDISC_GET_DISC(_func) \
+ MCFG_DEVICE_CONFIG_DATAPTR(laserdisc_config, getdisc, _func)
+
+#define MCFG_LASERDISC_AUDIO(_func) \
+ MCFG_DEVICE_CONFIG_DATAPTR(laserdisc_config, audio, _func)
+
+#define MCFG_LASERDISC_OVERLAY(_update, _width, _height, _format) \
+ MCFG_DEVICE_CONFIG_DATAPTR(laserdisc_config, overupdate, SCREEN_UPDATE_NAME(_update)) \
+ MCFG_DEVICE_CONFIG_DATA32(laserdisc_config, overwidth, _width) \
+ MCFG_DEVICE_CONFIG_DATA32(laserdisc_config, overheight, _height) \
+ MCFG_DEVICE_CONFIG_DATA32(laserdisc_config, overformat, _format)
+
+#define MCFG_LASERDISC_OVERLAY_CLIP(_minx, _maxx, _miny, _maxy) \
+ MCFG_DEVICE_CONFIG_DATA32(laserdisc_config, overclip.min_x, _minx) \
+ MCFG_DEVICE_CONFIG_DATA32(laserdisc_config, overclip.max_x, _maxx) \
+ MCFG_DEVICE_CONFIG_DATA32(laserdisc_config, overclip.min_y, _miny) \
+ MCFG_DEVICE_CONFIG_DATA32(laserdisc_config, overclip.max_y, _maxy)
+
+#define MCFG_LASERDISC_OVERLAY_POSITION(_posx, _posy) \
+ MCFG_DEVICE_CONFIG_DATAFP32(laserdisc_config, overposx, _posx, 24) \
+ MCFG_DEVICE_CONFIG_DATAFP32(laserdisc_config, overposy, _posy, 24)
+
+#define MCFG_LASERDISC_OVERLAY_SCALE(_scalex, _scaley) \
+ MCFG_DEVICE_CONFIG_DATAFP32(laserdisc_config, overscalex, _scalex, 24) \
+ MCFG_DEVICE_CONFIG_DATAFP32(laserdisc_config, overscaley, _scaley, 24)
+
+
+/* use these to add laserdisc screens with proper video update parameters */
+#define MCFG_LASERDISC_SCREEN_ADD_NTSC(_tag, _overlayformat) \
+ MCFG_VIDEO_ATTRIBUTES(VIDEO_SELF_RENDER) \
+ \
+ MCFG_SCREEN_ADD(_tag, RASTER) \
+ MCFG_SCREEN_FORMAT(_overlayformat) \
+ MCFG_SCREEN_RAW_PARAMS(XTAL_14_31818MHz*2, 910, 0, 704, 525, 44, 524) \
+ MCFG_SCREEN_UPDATE(laserdisc) \
+
+/* not correct yet; fix me... */
+#define MCFG_LASERDISC_SCREEN_ADD_PAL(_tag, _format) \
+ MCFG_VIDEO_ATTRIBUTES(VIDEO_SELF_RENDER) \
+ \
+ MCFG_SCREEN_ADD(_tag, RASTER) \
+ MCFG_SCREEN_FORMAT(_format) \
+ MCFG_SCREEN_RAW_PARAMS(XTAL_14_31818MHz, 910, 0, 704, 525.0/2, 0, 480/2) \
+ MCFG_SCREEN_UPDATE(laserdisc) \
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+
+/* ----- core control and status ----- */
+
+/* get a bitmap for the current frame; return TRUE if valid or FALSE if video off */
+int laserdisc_get_video(device_t *device, bitmap_t **bitmap);
+
+/* return the raw philips or white flag codes */
+UINT32 laserdisc_get_field_code(device_t *device, UINT32 code, UINT8 zero_if_squelched);
+
+
+
+/* ----- input and output ----- */
+
+/* write to the parallel data port of the player */
+void laserdisc_data_w(device_t *device, UINT8 data);
+
+/* assert or clear a signal line connected to the player */
+void laserdisc_line_w(device_t *device, UINT8 line, UINT8 newstate);
+
+/* read from the parallel data port of the player */
+UINT8 laserdisc_data_r(device_t *device);
+
+/* read the state of a signal line connected to the player */
+UINT8 laserdisc_line_r(device_t *device, UINT8 line);
+
+
+
+/* ----- player specifics ----- */
+
+/* specify the "slow" speed of the Pioneer PR-7820 */
+void pr7820_set_slow_speed(device_t *device, double frame_rate_scaler);
+
+/* set a callback for data ready on the Phillips 22VP931 */
+void vp931_set_data_ready_callback(device_t *device, vp931_data_ready_func callback);
+
+/* control the audio squelch of the Simutrek modified players */
+void simutrek_set_audio_squelch(device_t *device, int state);
+
+
+
+/* ----- video interface ----- */
+
+/* enable/disable the video */
+void laserdisc_video_enable(device_t *device, int enable);
+
+/* enable/disable the overlay */
+void laserdisc_overlay_enable(device_t *device, int enable);
+
+/* video update callback */
+SCREEN_UPDATE( laserdisc );
+
+
+
+/* ----- configuration ----- */
+
+/* return a copy of the current live configuration settings */
+void laserdisc_get_config(device_t *device, laserdisc_config *config);
+
+/* change the current live configuration settings */
+void laserdisc_set_config(device_t *device, const laserdisc_config *config);
+
+
+
+/* ----- device interface ----- */
+
+/* device get info callback */
+DECLARE_LEGACY_DEVICE(PIONEER_PR7820,pioneer_pr7820);
+DECLARE_LEGACY_DEVICE(PIONEER_PR8210,pioneer_pr8210);
+DECLARE_LEGACY_DEVICE(SIMUTREK_SPECIAL,simutrek_special);
+DECLARE_LEGACY_DEVICE(PIONEER_LDV1000,pioneer_ldv1000);
+DECLARE_LEGACY_DEVICE(PHILLIPS_22VP931,phillips_22vp931);
+DECLARE_LEGACY_DEVICE(PHILLIPS_22VP932,phillips_22vp932);
+DECLARE_LEGACY_DEVICE(SONY_LDP1450,sony_ldp1450);
+
+/* audio get info callback */
+DECLARE_LEGACY_SOUND_DEVICE(LASERDISC_SOUND, laserdisc_sound);
+
+/* type setter */
+int laserdisc_get_type(device_t *device);
+void laserdisc_set_type(device_t *device, int type);
+
+INLINE bool device_is_laserdisc(device_t *device)
+{
+ return(device->type() == PIONEER_PR7820 ||
+ device->type() == PIONEER_PR8210 ||
+ device->type() == SIMUTREK_SPECIAL ||
+ device->type() == PIONEER_LDV1000 ||
+ device->type() == PHILLIPS_22VP931 ||
+ device->type() == PHILLIPS_22VP932 ||
+ device->type() == SONY_LDP1450);
+}
+
+#endif /* __LASERDSC_H__ */
diff --git a/trunk/src/emu/machine/latch8.c b/trunk/src/emu/machine/latch8.c
new file mode 100644
index 00000000000..1187a491900
--- /dev/null
+++ b/trunk/src/emu/machine/latch8.c
@@ -0,0 +1,259 @@
+/**********************************************************************
+
+ 8 bit latch interface and emulation
+
+ 2008/08 couriersud
+
+**********************************************************************/
+
+#include "emu.h"
+#include "memconv.h"
+#include "sound/discrete.h"
+#include "latch8.h"
+
+typedef struct _latch8_t latch8_t;
+struct _latch8_t
+{
+ latch8_config *intf;
+ UINT8 value;
+ UINT8 has_node_map;
+ UINT8 has_devread;
+ UINT8 has_read;
+ device_t *devices[8];
+};
+
+/* ----------------------------------------------------------------------- */
+
+INLINE latch8_t *get_safe_token(device_t *device) {
+ assert( device != NULL );
+ assert( device->type() == LATCH8 );
+ return ( latch8_t * ) downcast<legacy_device_base *>(device)->token();
+}
+
+static void update(device_t *device, UINT8 new_val, UINT8 mask)
+{
+ /* temporary hack until the discrete system is a device */
+ latch8_t *latch8 = get_safe_token(device);
+ UINT8 old_val = latch8->value;
+
+ latch8->value = (latch8->value & ~mask) | (new_val & mask);
+
+ if (latch8->has_node_map)
+ {
+ int i;
+ UINT8 changed = old_val ^ latch8->value;
+ for (i=0; i<8; i++)
+ if (((changed & (1<<i)) != 0) && latch8->intf->node_map[i] != 0)
+ discrete_sound_w(device->machine().device(latch8->intf->node_device[i]), latch8->intf->node_map[i] , (latch8->value >> i) & 1);
+ }
+}
+
+static TIMER_CALLBACK( latch8_timerproc )
+{
+ device_t *device = (device_t *)ptr;
+ UINT8 new_val = param & 0xFF;
+ UINT8 mask = param >> 8;
+
+ update(device, new_val, mask);
+}
+
+/* ----------------------------------------------------------------------- */
+
+READ8_DEVICE_HANDLER( latch8_r )
+{
+ latch8_t *latch8 = get_safe_token(device);
+ UINT8 res;
+
+ assert(offset == 0);
+
+ res = latch8->value;
+ if (latch8->has_devread)
+ {
+ int i;
+ for (i=0; i<8; i++)
+ {
+ device_t *read_dev = latch8->devices[i];
+ if (read_dev != NULL)
+ {
+ res &= ~( 1 << i);
+ res |= ((latch8->intf->devread[i].devread_handler(read_dev, 0) >> latch8->intf->devread[i].from_bit) & 0x01) << i;
+ }
+ }
+ }
+ if (latch8->has_read)
+ {
+ /* temporary hack until all relevant systems are devices */
+ address_space *space = device->machine().firstcpu->memory().space(AS_PROGRAM);
+ int i;
+ for (i=0; i<8; i++)
+ {
+ if (latch8->intf->devread[i].read_handler != NULL)
+ {
+ res &= ~( 1 << i);
+ res |= ((latch8->intf->devread[i].read_handler(space, 0) >> latch8->intf->devread[i].from_bit) & 0x01) << i;
+ }
+ }
+ }
+
+ return (res & ~latch8->intf->maskout) ^ latch8->intf->xorvalue;
+}
+
+
+WRITE8_DEVICE_HANDLER( latch8_w )
+{
+ latch8_t *latch8 = get_safe_token(device);
+ assert(offset == 0);
+
+ if (latch8->intf->nosync != 0xff)
+ device->machine().scheduler().synchronize(FUNC(latch8_timerproc), (0xFF << 8) | data, (void *)device);
+ else
+ update(device, data, 0xFF);
+}
+
+
+WRITE8_DEVICE_HANDLER( latch8_reset)
+{
+ latch8_t *latch8 = get_safe_token(device);
+
+ assert(offset == 0);
+
+ latch8->value = 0;
+}
+
+/* read bit x */
+/* return (latch >> x) & 0x01 */
+
+INLINE UINT8 latch8_bitx_r(device_t *device, offs_t offset, int bit)
+{
+ latch8_t *latch8 = get_safe_token(device);
+
+ assert( offset == 0);
+
+ return (latch8->value >> bit) & 0x01;
+}
+
+READ8_DEVICE_HANDLER( latch8_bit0_r) { return latch8_bitx_r(device, offset, 0); }
+READ8_DEVICE_HANDLER( latch8_bit1_r) { return latch8_bitx_r(device, offset, 1); }
+READ8_DEVICE_HANDLER( latch8_bit2_r) { return latch8_bitx_r(device, offset, 2); }
+READ8_DEVICE_HANDLER( latch8_bit3_r) { return latch8_bitx_r(device, offset, 3); }
+READ8_DEVICE_HANDLER( latch8_bit4_r) { return latch8_bitx_r(device, offset, 4); }
+READ8_DEVICE_HANDLER( latch8_bit5_r) { return latch8_bitx_r(device, offset, 5); }
+READ8_DEVICE_HANDLER( latch8_bit6_r) { return latch8_bitx_r(device, offset, 6); }
+READ8_DEVICE_HANDLER( latch8_bit7_r) { return latch8_bitx_r(device, offset, 7); }
+
+READ8_DEVICE_HANDLER( latch8_bit0_q_r) { return latch8_bitx_r(device, offset, 0) ^ 1; }
+READ8_DEVICE_HANDLER( latch8_bit1_q_r) { return latch8_bitx_r(device, offset, 1) ^ 1; }
+READ8_DEVICE_HANDLER( latch8_bit2_q_r) { return latch8_bitx_r(device, offset, 2) ^ 1; }
+READ8_DEVICE_HANDLER( latch8_bit3_q_r) { return latch8_bitx_r(device, offset, 3) ^ 1; }
+READ8_DEVICE_HANDLER( latch8_bit4_q_r) { return latch8_bitx_r(device, offset, 4) ^ 1; }
+READ8_DEVICE_HANDLER( latch8_bit5_q_r) { return latch8_bitx_r(device, offset, 5) ^ 1; }
+READ8_DEVICE_HANDLER( latch8_bit6_q_r) { return latch8_bitx_r(device, offset, 6) ^ 1; }
+READ8_DEVICE_HANDLER( latch8_bit7_q_r) { return latch8_bitx_r(device, offset, 7) ^ 1; }
+
+/* write bit x from data into bit determined by offset */
+/* latch = (latch & ~(1<<offset)) | (((data >> x) & 0x01) << offset) */
+
+INLINE void latch8_bitx_w(device_t *device, int bit, offs_t offset, UINT8 data)
+{
+ latch8_t *latch8 = get_safe_token(device);
+ UINT8 mask = (1<<offset);
+ UINT8 masked_data = (((data >> bit) & 0x01) << offset);
+
+ assert( offset < 8);
+
+ /* No need to synchronize ? */
+ if (latch8->intf->nosync & mask)
+ update(device, masked_data, mask);
+ else
+ device->machine().scheduler().synchronize(FUNC(latch8_timerproc), (mask << 8) | masked_data, (void *) device);
+}
+
+WRITE8_DEVICE_HANDLER( latch8_bit0_w ) { latch8_bitx_w(device, 0, offset, data); }
+WRITE8_DEVICE_HANDLER( latch8_bit1_w ) { latch8_bitx_w(device, 1, offset, data); }
+WRITE8_DEVICE_HANDLER( latch8_bit2_w ) { latch8_bitx_w(device, 2, offset, data); }
+WRITE8_DEVICE_HANDLER( latch8_bit3_w ) { latch8_bitx_w(device, 3, offset, data); }
+WRITE8_DEVICE_HANDLER( latch8_bit4_w ) { latch8_bitx_w(device, 4, offset, data); }
+WRITE8_DEVICE_HANDLER( latch8_bit5_w ) { latch8_bitx_w(device, 0, offset, data); }
+WRITE8_DEVICE_HANDLER( latch8_bit6_w ) { latch8_bitx_w(device, 0, offset, data); }
+WRITE8_DEVICE_HANDLER( latch8_bit7_w ) { latch8_bitx_w(device, 0, offset, data); }
+
+/* ----------------------------------------------------------------------- */
+
+/* device interface */
+
+static DEVICE_START( latch8 )
+{
+ latch8_t *latch8 = get_safe_token(device);
+ int i;
+
+ /* validate arguments */
+ latch8->intf = (latch8_config *)downcast<const legacy_device_base *>(device)->inline_config();
+
+ latch8->value = 0x0;
+
+ /* setup nodemap */
+ for (i=0; i<8; i++)
+ if (latch8->intf->node_map[i] )
+ {
+ if (!latch8->intf->node_device[i])
+ fatalerror("Device %s: Bit %d has invalid discrete device\n", device->tag(), i);
+ latch8->has_node_map = 1;
+ }
+
+ /* setup device read handlers */
+ for (i=0; i<8; i++)
+ if (latch8->intf->devread[i].tag != NULL)
+ {
+ if (latch8->devices[i] != NULL)
+ fatalerror("Device %s: Bit %d already has a handler.\n", device->tag(), i);
+ latch8->devices[i] = device->machine().device(latch8->intf->devread[i].tag);
+ if (latch8->devices[i] == NULL)
+ fatalerror("Device %s: Unable to find device %s\n", device->tag(), latch8->intf->devread[i].tag);
+ latch8->has_devread = 1;
+ }
+
+ /* setup machine read handlers */
+ for (i=0; i<8; i++)
+ if (latch8->intf->devread[i].read_handler != NULL)
+ {
+ if (latch8->devices[i] != NULL)
+ fatalerror("Device %s: Bit %d already has a handler.\n", device->tag(), i);
+ latch8->has_read = 1;
+ }
+
+ device->save_item(NAME(latch8->value));
+}
+
+
+static DEVICE_RESET( latch8 )
+{
+ latch8_t *latch8 = get_safe_token(device);
+
+ latch8->value = 0;
+}
+
+
+DEVICE_GET_INFO( latch8 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(latch8_t); break;
+ case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = sizeof(latch8_config); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(latch8);break;
+ case DEVINFO_FCT_STOP: /* Nothing */ break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(latch8);break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "8 bit latch"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Latches"); 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;
+ }
+}
+
+
+DEFINE_LEGACY_DEVICE(LATCH8, latch8);
diff --git a/trunk/src/emu/machine/latch8.h b/trunk/src/emu/machine/latch8.h
new file mode 100644
index 00000000000..23bea91faef
--- /dev/null
+++ b/trunk/src/emu/machine/latch8.h
@@ -0,0 +1,143 @@
+/**********************************************************************
+
+ 8 bit latch interface and emulation
+
+ Generic emulation of 74LS174/175, 74LS259 and other latches.
+ Apart from providing synched latch operation, these
+ latches can be configured to read their input bitwise from other
+ devices as well and individual bits can be connected to
+ discrete nodes.
+
+ Please see audio/dkong.c for examples.
+
+**********************************************************************/
+
+#ifndef __LATCH8_H_
+#define __LATCH8_H_
+
+#include "devlegcy.h"
+
+DECLARE_LEGACY_DEVICE(LATCH8, latch8);
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _latch8_devread latch8_devread;
+struct _latch8_devread
+{
+ /* only for byte reads, does not affect bit reads and node_map */
+ UINT32 from_bit;
+ const char *tag;
+ read8_device_func devread_handler;
+ read8_space_func read_handler;
+};
+
+typedef struct _latch8_config latch8_config;
+struct _latch8_config
+{
+ /* only for byte reads, does not affect bit reads and node_map */
+ UINT32 maskout;
+ UINT32 xorvalue; /* after mask */
+ UINT32 nosync;
+ UINT32 node_map[8];
+ const char * node_device[8];
+ latch8_devread devread[8];
+};
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+/* add device */
+#define MCFG_LATCH8_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, LATCH8, 0)
+
+/* Bit mask specifying bits to be masked *out* */
+#define MCFG_LATCH8_MASKOUT(_maskout) \
+ MCFG_DEVICE_CONFIG_DATA32(latch8_config, maskout, _maskout)
+
+/* Bit mask specifying bits to be inverted */
+#define MCFG_LATCH8_INVERT(_xor) \
+ MCFG_DEVICE_CONFIG_DATA32(latch8_config, xorvalue, _xor)
+
+/* Bit mask specifying bits not needing cpu synchronization. */
+#define MCFG_LATCH8_NOSYNC(_nosync) \
+ MCFG_DEVICE_CONFIG_DATA32(latch8_config, nosync, _nosync)
+
+/* Write bit to discrete node */
+#define MCFG_LATCH8_DISCRETE_NODE(_device, _bit, _node) \
+ MCFG_DEVICE_CONFIG_DATAPTR_ARRAY(latch8_config, node_device, _bit, _device) \
+ MCFG_DEVICE_CONFIG_DATA32_ARRAY(latch8_config, node_map, _bit, _node)
+
+/* Upon read, replace bits by reading from another device handler */
+#define MCFG_LATCH8_DEVREAD(_bit, _tag, _handler, _from_bit) \
+ MCFG_DEVICE_CONFIG_DATA32_ARRAY_MEMBER(latch8_config, devread, _bit, latch8_devread, from_bit, _from_bit) \
+ MCFG_DEVICE_CONFIG_DATAPTR_ARRAY_MEMBER(latch8_config, devread, _bit, latch8_devread, tag, _tag) \
+ MCFG_DEVICE_CONFIG_DATAPTR_ARRAY_MEMBER(latch8_config, devread, _bit, latch8_devread, devread_handler, _handler) \
+
+/* Upon read, replace bits by reading from another machine handler */
+#define MCFG_LATCH8_READ(_bit, _handler, _from_bit) \
+ MCFG_DEVICE_CONFIG_DATA32_ARRAY_MEMBER(latch8_config, devread, _bit, latch8_devread, from_bit, _from_bit) \
+ MCFG_DEVICE_CONFIG_DATAPTR_ARRAY_MEMBER(latch8_config, devread, _bit, latch8_devread, read_handler, _handler) \
+
+/* Accessor macros */
+
+#define AM_LATCH8_READ(_tag) \
+ AM_DEVREAD(_tag, latch8_r)
+
+#define AM_LATCH8_READBIT(_tag, _bit) \
+ AM_DEVREAD(_tag, latch8_bit ## _bit ## _q_r)
+
+#define AM_LATCH8_WRITE(_tag) \
+ AM_DEVWRITE(_tag, latch8_w)
+
+#define AM_LATCH8_READWRITE(_tag) \
+ AM_DEVREADWRITE(_tag, latch8_r, latch8_w)
+
+/* write & read full byte */
+
+READ8_DEVICE_HANDLER( latch8_r );
+WRITE8_DEVICE_HANDLER( latch8_w );
+
+/* reset the latch */
+
+WRITE8_DEVICE_HANDLER( latch8_reset );
+
+/* read bit x */
+/* return (latch >> x) & 0x01 */
+
+READ8_DEVICE_HANDLER( latch8_bit0_r );
+READ8_DEVICE_HANDLER( latch8_bit1_r );
+READ8_DEVICE_HANDLER( latch8_bit2_r );
+READ8_DEVICE_HANDLER( latch8_bit3_r );
+READ8_DEVICE_HANDLER( latch8_bit4_r );
+READ8_DEVICE_HANDLER( latch8_bit5_r );
+READ8_DEVICE_HANDLER( latch8_bit6_r );
+READ8_DEVICE_HANDLER( latch8_bit7_r );
+
+/* read inverted bit x */
+/* return (latch >> x) & 0x01 */
+
+READ8_DEVICE_HANDLER( latch8_bit0_q_r );
+READ8_DEVICE_HANDLER( latch8_bit1_q_r );
+READ8_DEVICE_HANDLER( latch8_bit2_q_r );
+READ8_DEVICE_HANDLER( latch8_bit3_q_r );
+READ8_DEVICE_HANDLER( latch8_bit4_q_r );
+READ8_DEVICE_HANDLER( latch8_bit5_q_r );
+READ8_DEVICE_HANDLER( latch8_bit6_q_r );
+READ8_DEVICE_HANDLER( latch8_bit7_q_r );
+
+/* write bit x from data into bit determined by offset */
+/* latch = (latch & ~(1<<offset)) | (((data >> x) & 0x01) << offset) */
+
+WRITE8_DEVICE_HANDLER( latch8_bit0_w );
+WRITE8_DEVICE_HANDLER( latch8_bit1_w );
+WRITE8_DEVICE_HANDLER( latch8_bit2_w );
+WRITE8_DEVICE_HANDLER( latch8_bit3_w );
+WRITE8_DEVICE_HANDLER( latch8_bit4_w );
+WRITE8_DEVICE_HANDLER( latch8_bit5_w );
+WRITE8_DEVICE_HANDLER( latch8_bit6_w );
+WRITE8_DEVICE_HANDLER( latch8_bit7_w );
+
+#endif /* __LATCH8_H_ */
diff --git a/trunk/src/emu/machine/ldcore.c b/trunk/src/emu/machine/ldcore.c
new file mode 100644
index 00000000000..58aade8c076
--- /dev/null
+++ b/trunk/src/emu/machine/ldcore.c
@@ -0,0 +1,1716 @@
+/*************************************************************************
+
+ ldcore.c
+
+ Private core laserdisc player implementation.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*************************************************************************/
+
+#include "emu.h"
+#include "ldcore.h"
+#include "avcomp.h"
+#include "vbiparse.h"
+#include "config.h"
+#include "render.h"
+
+
+
+/***************************************************************************
+ DEBUGGING
+***************************************************************************/
+
+#define LOG_SLIDER 0
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* these specs code from IEC 60857, for NTSC players */
+#define LEAD_IN_MIN_RADIUS_IN_UM 53500 /* 53.5 mm */
+#define PROGRAM_MIN_RADIUS_IN_UM 55000 /* 55 mm */
+#define PROGRAM_MAX_RADIUS_IN_UM 145000 /* 145 mm */
+#define LEAD_OUT_MIN_SIZE_IN_UM 2000 /* 2 mm */
+
+/* the track pitch is defined as a range; we pick a nominal pitch
+ that ensures we can fit 54,000 tracks */
+#define MIN_TRACK_PITCH_IN_NM 1400 /* 1.4 um */
+#define MAX_TRACK_PITCH_IN_NM 2000 /* 2 um */
+#define NOMINAL_TRACK_PITCH_IN_NM ((PROGRAM_MAX_RADIUS_IN_UM - PROGRAM_MIN_RADIUS_IN_UM) * 1000 / 54000)
+
+/* we simulate extra lead-in and lead-out tracks */
+#define VIRTUAL_LEAD_IN_TRACKS ((PROGRAM_MIN_RADIUS_IN_UM - LEAD_IN_MIN_RADIUS_IN_UM) * 1000 / NOMINAL_TRACK_PITCH_IN_NM)
+#define MAX_TOTAL_TRACKS 54000
+#define VIRTUAL_LEAD_OUT_TRACKS (LEAD_OUT_MIN_SIZE_IN_UM * 1000 / NOMINAL_TRACK_PITCH_IN_NM)
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/* video frame data */
+typedef struct _frame_data frame_data;
+struct _frame_data
+{
+ bitmap_t * bitmap; /* cached bitmap */
+ bitmap_t * visbitmap; /* wrapper around bitmap with only visible lines */
+ UINT8 numfields; /* number of fields in this frame */
+ INT32 lastfield; /* last absolute field number */
+};
+
+
+/* core-specific data */
+struct _ldcore_data
+{
+ /* general config */
+ laserdisc_config config; /* copy of the inline config */
+ ldplayer_interface intf; /* interface to the player */
+
+ /* disc parameters */
+ chd_file * disc; /* handle to the disc itself */
+ UINT8 * vbidata; /* pointer to precomputed VBI data */
+ int width; /* width of video */
+ int height; /* height of video */
+ UINT32 fps_times_1million; /* frame rate of video */
+ int samplerate; /* audio samplerate */
+ chd_error readresult; /* result of the most recent read */
+ UINT32 chdtracks; /* number of tracks in the CHD */
+ av_codec_decompress_config avconfig; /* decompression configuration */
+
+ /* core states */
+ UINT8 audiosquelch; /* audio squelch state: bit 0 = audio 1, bit 1 = audio 2 */
+ UINT8 videosquelch; /* video squelch state: bit 0 = on/off */
+ UINT8 fieldnum; /* field number (0 or 1) */
+ INT32 curtrack; /* current track at this end of this vsync */
+ UINT32 maxtrack; /* maximum track number */
+ attoseconds_t attospertrack; /* attoseconds per track, or 0 if not moving */
+ attotime sliderupdate; /* time of last slider update */
+
+ /* video data */
+ frame_data frame[3]; /* circular list of frames */
+ UINT8 videoindex; /* index of the current video buffer */
+ bitmap_t videotarget; /* fake target bitmap for decompression */
+ bitmap_t * emptyframe; /* blank frame */
+
+ /* audio data */
+ INT16 * audiobuffer[2]; /* buffer for audio samples */
+ UINT32 audiobufsize; /* size of buffer */
+ UINT32 audiobufin; /* input index */
+ UINT32 audiobufout; /* output index */
+ UINT32 audiocursamples; /* current samples this track */
+ UINT32 audiomaxsamples; /* maximum samples per track */
+ device_t *audiocustom; /* custom sound device */
+
+ /* metadata */
+ vbi_metadata metadata[2]; /* metadata parsed from the stream, for each field */
+
+ /* I/O data */
+ UINT8 datain; /* current input data value */
+ UINT8 linein[LASERDISC_INPUT_LINES]; /* current input line state */
+ UINT8 dataout; /* current output data value */
+ UINT8 lineout[LASERDISC_OUTPUT_LINES]; /* current output line state */
+
+ /* video updating */
+ UINT8 videoenable; /* is video enabled? */
+ render_texture * videotex; /* texture for the video */
+ palette_t * videopalette; /* palette for the video */
+ UINT8 overenable; /* is the overlay enabled? */
+ bitmap_t * overbitmap[2]; /* overlay bitmaps */
+ int overindex; /* index of the overlay bitmap */
+ render_texture * overtex; /* texture for the overlay */
+};
+
+
+/* sound callback info */
+typedef struct _sound_token sound_token;
+struct _sound_token
+{
+ sound_stream * stream;
+ laserdisc_state * ld;
+};
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+/* generic helper functions */
+static TIMER_CALLBACK( perform_player_update );
+static void read_track_data(laserdisc_state *ld);
+static void process_track_data(device_t *device);
+static DEVICE_START( laserdisc_sound );
+static STREAM_UPDATE( custom_stream_callback );
+static void configuration_load(device_t *device, int config_type, xml_data_node *parentnode);
+static void configuration_save(device_t *device, int config_type, xml_data_node *parentnode);
+
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ get_safe_token - makes sure that the passed
+ in device is, in fact, a laserdisc device
+-------------------------------------------------*/
+
+INLINE laserdisc_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device_is_laserdisc(device));
+
+ return (laserdisc_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+/*-------------------------------------------------
+ update_audio - update the audio stream to the
+ current time
+-------------------------------------------------*/
+
+INLINE void update_audio(laserdisc_state *ld)
+{
+ ldcore_data *ldcore = ld->core;
+ if (ldcore->audiocustom != NULL)
+ {
+ sound_token *token = (sound_token *)downcast<legacy_device_base *>(ldcore->audiocustom)->token();
+ token->stream->update();
+ }
+}
+
+
+/*-------------------------------------------------
+ add_and_clamp_track - add a delta to the
+ current track and clamp to minimum/maximum
+ values
+-------------------------------------------------*/
+
+INLINE void add_and_clamp_track(ldcore_data *ldcore, INT32 delta)
+{
+ ldcore->curtrack += delta;
+ ldcore->curtrack = MAX(ldcore->curtrack, 1);
+ ldcore->curtrack = MIN(ldcore->curtrack, ldcore->maxtrack - 1);
+}
+
+
+/*-------------------------------------------------
+ fillbitmap_yuy16 - fill a YUY16 bitmap with a
+ given color pattern
+-------------------------------------------------*/
+
+INLINE void fillbitmap_yuy16(bitmap_t *bitmap, UINT8 yval, UINT8 cr, UINT8 cb)
+{
+ UINT16 color0 = (yval << 8) | cb;
+ UINT16 color1 = (yval << 8) | cr;
+ int x, y;
+
+ /* write 32 bits of color (2 pixels at a time) */
+ for (y = 0; y < bitmap->height; y++)
+ {
+ UINT16 *dest = (UINT16 *)bitmap->base + y * bitmap->rowpixels;
+ for (x = 0; x < bitmap->width / 2; x++)
+ {
+ *dest++ = color0;
+ *dest++ = color1;
+ }
+ }
+}
+
+
+
+/***************************************************************************
+ GENERIC IMPLEMENTATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ update_slider_pos - based on the current
+ speed and elapsed time, update the current
+ track position
+-------------------------------------------------*/
+
+static void update_slider_pos(ldcore_data *ldcore, attotime curtime)
+{
+ /* if not moving, update to now */
+ if (ldcore->attospertrack == 0)
+ ldcore->sliderupdate = curtime;
+
+ /* otherwise, compute the number of tracks covered */
+ else
+ {
+ attoseconds_t delta = (curtime - ldcore->sliderupdate).as_attoseconds();
+ INT32 tracks_covered;
+
+ /* determine how many tracks we covered and advance */
+ if (ldcore->attospertrack >= 0)
+ {
+ tracks_covered = delta / ldcore->attospertrack;
+ add_and_clamp_track(ldcore, tracks_covered);
+ if (tracks_covered != 0)
+ ldcore->sliderupdate += attotime(0, tracks_covered * ldcore->attospertrack);
+ }
+ else
+ {
+ tracks_covered = delta / -ldcore->attospertrack;
+ add_and_clamp_track(ldcore, -tracks_covered);
+ if (tracks_covered != 0)
+ ldcore->sliderupdate += attotime(0, tracks_covered * -ldcore->attospertrack);
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ vblank_state_changed - called on each state
+ change of the VBLANK signal
+-------------------------------------------------*/
+
+static void vblank_state_changed(device_t *device, screen_device &screen, bool vblank_state)
+{
+ laserdisc_state *ld = get_safe_token(device);
+ ldcore_data *ldcore = ld->core;
+ attotime curtime = screen.machine().time();
+
+ /* update current track based on slider speed */
+ update_slider_pos(ldcore, curtime);
+
+ /* on rising edge, process previously-read frame and inform the player */
+ if (vblank_state)
+ {
+ /* call the player's VSYNC callback */
+ if (ldcore->intf.vsync != NULL)
+ (*ldcore->intf.vsync)(ld, &ldcore->metadata[ldcore->fieldnum], ldcore->fieldnum, curtime);
+
+ /* set a timer to begin fetching the next frame just before the VBI data would be fetched */
+ screen.machine().scheduler().timer_set(screen.time_until_pos(16*2), FUNC(perform_player_update), 0, ld);
+ }
+}
+
+
+/*-------------------------------------------------
+ vblank_state_changed - called on each state
+ change of the VBLANK signal
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( perform_player_update )
+{
+ laserdisc_state *ld = (laserdisc_state *)ptr;
+ ldcore_data *ldcore = ld->core;
+ attotime curtime = machine.time();
+
+ /* wait for previous read and decode to finish */
+ process_track_data(ld->device);
+
+ /* update current track based on slider speed */
+ update_slider_pos(ldcore, curtime);
+
+ /* update the state */
+ if (ldcore->intf.update != NULL)
+ add_and_clamp_track(ldcore, (*ldcore->intf.update)(ld, &ldcore->metadata[ldcore->fieldnum], ldcore->fieldnum, curtime));
+
+ /* flush any audio before we read more */
+ update_audio(ld);
+
+ /* start reading the track data for the next round */
+ ldcore->fieldnum ^= 1;
+ read_track_data(ld);
+}
+
+
+/*-------------------------------------------------
+ laserdisc_data_w - write data to the given
+ laserdisc player
+-------------------------------------------------*/
+
+void laserdisc_data_w(device_t *device, UINT8 data)
+{
+ laserdisc_state *ld = get_safe_token(device);
+ ldcore_data *ldcore = ld->core;
+ UINT8 prev = ldcore->datain;
+ ldcore->datain = data;
+
+ /* call through to the player-specific write handler */
+ if (ldcore->intf.writedata != NULL)
+ (*ldcore->intf.writedata)(ld, prev, data);
+}
+
+
+/*-------------------------------------------------
+ laserdisc_line_w - control an input line
+-------------------------------------------------*/
+
+void laserdisc_line_w(device_t *device, UINT8 line, UINT8 newstate)
+{
+ laserdisc_state *ld = get_safe_token(device);
+ ldcore_data *ldcore = ld->core;
+
+ assert(line < LASERDISC_INPUT_LINES);
+ assert(newstate == ASSERT_LINE || newstate == CLEAR_LINE || newstate == PULSE_LINE);
+
+ /* assert */
+ if (newstate == ASSERT_LINE || newstate == PULSE_LINE)
+ {
+ if (ldcore->linein[line] != ASSERT_LINE)
+ {
+ /* call through to the player-specific line handler */
+ if (ldcore->intf.writeline[line] != NULL)
+ (*ldcore->intf.writeline[line])(ld, CLEAR_LINE, ASSERT_LINE);
+ }
+ ldcore->linein[line] = ASSERT_LINE;
+ }
+
+ /* deassert */
+ if (newstate == CLEAR_LINE || newstate == PULSE_LINE)
+ {
+ if (ldcore->linein[line] != CLEAR_LINE)
+ {
+ /* call through to the player-specific line handler */
+ if (ldcore->intf.writeline[line] != NULL)
+ (*ldcore->intf.writeline[line])(ld, ASSERT_LINE, CLEAR_LINE);
+ }
+ ldcore->linein[line] = CLEAR_LINE;
+ }
+}
+
+
+/*-------------------------------------------------
+ laserdisc_data_r - return the current
+ data byte
+-------------------------------------------------*/
+
+UINT8 laserdisc_data_r(device_t *device)
+{
+ laserdisc_state *ld = get_safe_token(device);
+ ldcore_data *ldcore = ld->core;
+ UINT8 result = ldcore->dataout;
+
+ /* call through to the player-specific data handler */
+ if (ldcore->intf.readdata != NULL)
+ result = (*ldcore->intf.readdata)(ld);
+
+ return result;
+}
+
+
+/*-------------------------------------------------
+ laserdisc_line_r - return the current state
+ of an output line
+-------------------------------------------------*/
+
+UINT8 laserdisc_line_r(device_t *device, UINT8 line)
+{
+ laserdisc_state *ld = get_safe_token(device);
+ ldcore_data *ldcore = ld->core;
+ UINT8 result;
+
+ assert(line < LASERDISC_OUTPUT_LINES);
+ result = ldcore->lineout[line];
+
+ /* call through to the player-specific data handler */
+ if (ldcore->intf.readline[line] != NULL)
+ result = (*ldcore->intf.readline[line])(ld);
+
+ return result;
+}
+
+
+/*-------------------------------------------------
+ laserdisc_get_video - return the current
+ video frame; return TRUE if valid or FALSE
+ if video off
+-------------------------------------------------*/
+
+int laserdisc_get_video(device_t *device, bitmap_t **bitmap)
+{
+ laserdisc_state *ld = get_safe_token(device);
+ ldcore_data *ldcore = ld->core;
+ frame_data *frame;
+
+ /* determine the most recent live set of frames */
+ frame = &ldcore->frame[ldcore->videoindex];
+ if (frame->numfields < 2)
+ frame = &ldcore->frame[(ldcore->videoindex + ARRAY_LENGTH(ldcore->frame) - 1) % ARRAY_LENGTH(ldcore->frame)];
+
+ /* if no video present, return the empty frame */
+ if (ldcore->videosquelch || frame->numfields < 2)
+ {
+ *bitmap = ldcore->emptyframe;
+ return FALSE;
+ }
+ else
+ {
+ *bitmap = frame->visbitmap;
+ return TRUE;
+ }
+}
+
+
+/*-------------------------------------------------
+ laserdisc_get_field_code - return raw field
+ information read from the disc
+-------------------------------------------------*/
+
+UINT32 laserdisc_get_field_code(device_t *device, UINT32 code, UINT8 zero_if_squelched)
+{
+ laserdisc_state *ld = get_safe_token(device);
+ ldcore_data *ldcore = ld->core;
+ int field = ldcore->fieldnum;
+
+ /* return nothing if the video is off (external devices can't sense) */
+ if (zero_if_squelched && ldcore->videosquelch)
+ return 0;
+
+ switch (code)
+ {
+ case LASERDISC_CODE_WHITE_FLAG:
+ return ldcore->metadata[field].white;
+
+ case LASERDISC_CODE_LINE16:
+ return ldcore->metadata[field].line16;
+
+ case LASERDISC_CODE_LINE17:
+ return ldcore->metadata[field].line17;
+
+ case LASERDISC_CODE_LINE18:
+ return ldcore->metadata[field].line18;
+
+ case LASERDISC_CODE_LINE1718:
+ return ldcore->metadata[field].line1718;
+ }
+
+ return 0;
+}
+
+
+
+/***************************************************************************
+ PLAYER-TO-CORE INTERFACES
+***************************************************************************/
+
+/*-------------------------------------------------
+ ldcore_get_safe_token - return a token with
+ type checking from a device
+-------------------------------------------------*/
+
+laserdisc_state *ldcore_get_safe_token(device_t *device)
+{
+ return get_safe_token(device);
+}
+
+
+/*-------------------------------------------------
+ ldcore_set_audio_squelch - set the left/right
+ audio squelch states
+-------------------------------------------------*/
+
+void ldcore_set_audio_squelch(laserdisc_state *ld, UINT8 squelchleft, UINT8 squelchright)
+{
+ update_audio(ld);
+ ld->core->audiosquelch = (squelchleft ? 1 : 0) | (squelchright ? 2 : 0);
+}
+
+
+/*-------------------------------------------------
+ ldcore_set_video_squelch - set the video
+ squelch state
+-------------------------------------------------*/
+
+void ldcore_set_video_squelch(laserdisc_state *ld, UINT8 squelch)
+{
+ ld->core->videosquelch = squelch;
+}
+
+
+/*-------------------------------------------------
+ ldcore_set_slider_speed - dynamically change
+ the slider speed
+-------------------------------------------------*/
+
+void ldcore_set_slider_speed(laserdisc_state *ld, INT32 tracks_per_vsync)
+{
+ ldcore_data *ldcore = ld->core;
+ attotime vsyncperiod = ld->screen->frame_period();
+
+ update_slider_pos(ldcore, ld->device->machine().time());
+
+ /* if 0, set the time to 0 */
+ if (tracks_per_vsync == 0)
+ ldcore->attospertrack = 0;
+
+ /* positive values store positive times */
+ else if (tracks_per_vsync > 0)
+ ldcore->attospertrack = (vsyncperiod / tracks_per_vsync).as_attoseconds();
+
+ /* negative values store negative times */
+ else
+ ldcore->attospertrack = -(vsyncperiod / -tracks_per_vsync).as_attoseconds();
+
+ if (LOG_SLIDER)
+ printf("Slider speed = %d\n", tracks_per_vsync);
+}
+
+
+/*-------------------------------------------------
+ ldcore_advance_slider - advance the slider by
+ a certain number of tracks
+-------------------------------------------------*/
+
+void ldcore_advance_slider(laserdisc_state *ld, INT32 numtracks)
+{
+ ldcore_data *ldcore = ld->core;
+
+ update_slider_pos(ldcore, ld->device->machine().time());
+ add_and_clamp_track(ldcore, numtracks);
+ if (LOG_SLIDER)
+ printf("Advance by %d\n", numtracks);
+}
+
+
+/*-------------------------------------------------
+ ldcore_get_slider_position - get the current
+ slider position
+-------------------------------------------------*/
+
+slider_position ldcore_get_slider_position(laserdisc_state *ld)
+{
+ ldcore_data *ldcore = ld->core;
+
+ /* update the slider position first */
+ update_slider_pos(ldcore, ld->device->machine().time());
+
+ /* return the status */
+ if (ldcore->curtrack == 1)
+ return SLIDER_MINIMUM;
+ else if (ldcore->curtrack < VIRTUAL_LEAD_IN_TRACKS)
+ return SLIDER_VIRTUAL_LEADIN;
+ else if (ldcore->curtrack < VIRTUAL_LEAD_IN_TRACKS + ldcore->chdtracks)
+ return SLIDER_CHD;
+ else if (ldcore->curtrack < VIRTUAL_LEAD_IN_TRACKS + MAX_TOTAL_TRACKS)
+ return SLIDER_OUTSIDE_CHD;
+ else if (ldcore->curtrack < ldcore->maxtrack - 1)
+ return SLIDER_VIRTUAL_LEADOUT;
+ else
+ return SLIDER_MAXIMUM;
+}
+
+
+
+/***************************************************************************
+ GENERIC HELPER FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ ldcore_generic_update - generically update in
+ a way that works for most situations
+-------------------------------------------------*/
+
+INT32 ldcore_generic_update(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime, ldplayer_state *newstate)
+{
+ INT32 advanceby = 0;
+ int frame;
+
+ /* start by assuming the state doesn't change */
+ *newstate = ld->state;
+
+ /* handle things based on the state */
+ switch (ld->state.state)
+ {
+ case LDSTATE_EJECTING:
+ /* when time expires, switch to the ejected state */
+ if (curtime >= ld->state.endtime)
+ newstate->state = LDSTATE_EJECTED;
+ break;
+
+ case LDSTATE_EJECTED:
+ /* do nothing */
+ break;
+
+ case LDSTATE_PARKED:
+ /* do nothing */
+ break;
+
+ case LDSTATE_LOADING:
+ /* when time expires, switch to the spinup state */
+ if (curtime >= ld->state.endtime)
+ newstate->state = LDSTATE_SPINUP;
+ advanceby = -GENERIC_SEARCH_SPEED;
+ break;
+
+ case LDSTATE_SPINUP:
+ /* when time expires, switch to the playing state */
+ if (curtime >= ld->state.endtime)
+ newstate->state = LDSTATE_PLAYING;
+ advanceby = -GENERIC_SEARCH_SPEED;
+ break;
+
+ case LDSTATE_PAUSING:
+ /* if he hit the start of a frame, switch to paused state */
+ if (is_start_of_frame(vbi))
+ {
+ newstate->state = LDSTATE_PAUSED;
+ newstate->param = fieldnum;
+ }
+
+ /* else advance until we hit it */
+ else if (fieldnum == 1)
+ advanceby = 1;
+ break;
+
+ case LDSTATE_PAUSED:
+ /* if we paused on field 1, we must flip back and forth */
+ if (ld->state.param == 1)
+ advanceby = (fieldnum == 1) ? 1 : -1;
+ break;
+
+ case LDSTATE_PLAYING:
+ /* if we hit the target frame, switch to the paused state */
+ if (ld->state.param > 0 && is_start_of_frame(vbi) && frame_from_metadata(vbi) == ld->state.param)
+ {
+ newstate->state = LDSTATE_PAUSED;
+ newstate->param = fieldnum;
+ }
+
+ /* otherwise after the second field of each frame */
+ else if (fieldnum == 1)
+ advanceby = 1;
+ break;
+
+ case LDSTATE_PLAYING_SLOW_REVERSE:
+ /* after the second field of each frame, see if we need to advance */
+ if (fieldnum == 1 && ++ld->state.substate > ld->state.param)
+ {
+ advanceby = -1;
+ ld->state.substate = 0;
+ }
+ break;
+
+ case LDSTATE_PLAYING_SLOW_FORWARD:
+ /* after the second field of each frame, see if we need to advance */
+ if (fieldnum == 1 && ++ld->state.substate > ld->state.param)
+ {
+ advanceby = 1;
+ ld->state.substate = 0;
+ }
+ break;
+
+ case LDSTATE_PLAYING_FAST_REVERSE:
+ /* advance after the second field of each frame */
+ if (fieldnum == 1)
+ advanceby = -ld->state.param;
+ break;
+
+ case LDSTATE_PLAYING_FAST_FORWARD:
+ /* advance after the second field of each frame */
+ if (fieldnum == 1)
+ advanceby = ld->state.param;
+ break;
+
+ case LDSTATE_SCANNING:
+ /* advance after the second field of each frame */
+ if (fieldnum == 1)
+ advanceby = ld->state.param >> 8;
+
+ /* after we run out of vsyncs, revert to the saved state */
+ if (++ld->state.substate >= (ld->state.param & 0xff))
+ *newstate = ld->savestate;
+ break;
+
+ case LDSTATE_STEPPING_REVERSE:
+ /* wait for the first field of the frame and then leap backwards */
+ if (is_start_of_frame(vbi))
+ {
+ advanceby = (fieldnum == 1) ? -1 : -2;
+ newstate->state = LDSTATE_PAUSING;
+ }
+ break;
+
+ case LDSTATE_STEPPING_FORWARD:
+ /* wait for the first field of the frame and then switch to pausing state */
+ if (is_start_of_frame(vbi))
+ newstate->state = LDSTATE_PAUSING;
+ break;
+
+ case LDSTATE_SEEKING:
+ /* if we're in the final state, look for a matching frame and pause there */
+ frame = frame_from_metadata(vbi);
+ if (ld->state.substate == 1 && is_start_of_frame(vbi) && frame == ld->state.param)
+ {
+ newstate->state = LDSTATE_PAUSED;
+ newstate->param = fieldnum;
+ }
+
+ /* otherwise, if we got frame data from the VBI, update our seeking logic */
+ else if (ld->state.substate == 0 && frame != FRAME_NOT_PRESENT)
+ {
+ INT32 delta = (ld->state.param - 2) - frame;
+
+ /* if we're within a couple of frames, just play until we hit it */
+ if (delta >= 0 && delta <= 2)
+ ld->state.substate++;
+
+ /* otherwise, compute the delta assuming 1:1 track to frame; this will correct eventually */
+ else
+ {
+ if (delta < 0)
+ delta--;
+ advanceby = delta;
+ advanceby = MIN(advanceby, GENERIC_SEARCH_SPEED);
+ advanceby = MAX(advanceby, -GENERIC_SEARCH_SPEED);
+ }
+ }
+
+ /* otherwise, keep advancing until we know what's up */
+ else
+ {
+ if (fieldnum == 1)
+ advanceby = 1;
+ }
+ break;
+ }
+
+ return advanceby;
+}
+
+
+/*-------------------------------------------------
+ read_track_data - read and process data for
+ a particular video track
+-------------------------------------------------*/
+
+static void read_track_data(laserdisc_state *ld)
+{
+ ldcore_data *ldcore = ld->core;
+ UINT32 tracknum = ldcore->curtrack;
+ UINT32 fieldnum = ldcore->fieldnum;
+ vbi_metadata vbidata = { 0 };
+ frame_data *frame;
+ UINT32 vbiframe;
+ UINT32 readhunk;
+ INT32 chdtrack;
+
+ /* compute the chdhunk number we are going to read */
+ chdtrack = tracknum - 1 - VIRTUAL_LEAD_IN_TRACKS;
+ chdtrack = MAX(chdtrack, 0);
+ chdtrack = MIN(chdtrack, ldcore->chdtracks - 1);
+ readhunk = chdtrack * 2 + fieldnum;
+
+ /* cheat and look up the metadata we are about to retrieve */
+ if (ldcore->vbidata != NULL)
+ vbi_metadata_unpack(&vbidata, NULL, &ldcore->vbidata[readhunk * VBI_PACKED_BYTES]);
+
+ /* if we're in the lead-in area, force the VBI data to be standard lead-in */
+ if (tracknum - 1 < VIRTUAL_LEAD_IN_TRACKS)
+ {
+ vbidata.line16 = 0;
+ vbidata.line17 = vbidata.line18 = vbidata.line1718 = VBI_CODE_LEADIN;
+ }
+//printf("track %5d.%d: %06X %06X %06X\n", tracknum, fieldnum, vbidata.line16, vbidata.line17, vbidata.line18);
+
+ /* if we're about to read the first field in a frame, advance */
+ frame = &ldcore->frame[ldcore->videoindex];
+ if ((vbidata.line1718 & VBI_MASK_CAV_PICTURE) == VBI_CODE_CAV_PICTURE)
+ {
+ if (frame->numfields >= 2)
+ ldcore->videoindex = (ldcore->videoindex + 1) % ARRAY_LENGTH(ldcore->frame);
+ frame = &ldcore->frame[ldcore->videoindex];
+ frame->numfields = 0;
+ }
+
+ /* if we're squelched, reset the frame counter */
+ if (ldcore->videosquelch)
+ frame->numfields = 0;
+
+ /* remember the last field number */
+ frame->lastfield = tracknum * 2 + fieldnum;
+
+ /* set the video target information */
+ ldcore->videotarget.alloc = NULL;
+ ldcore->videotarget.base = BITMAP_ADDR16(frame->bitmap, fieldnum, 0);
+ ldcore->videotarget.rowpixels = frame->bitmap->rowpixels * 2;
+ ldcore->videotarget.width = frame->bitmap->width;
+ ldcore->videotarget.height = frame->bitmap->height / 2;
+ ldcore->videotarget.format = frame->bitmap->format;
+ ldcore->videotarget.bpp = frame->bitmap->bpp;
+ ldcore->videotarget.palette = frame->bitmap->palette;
+ ldcore->videotarget.cliprect = frame->bitmap->cliprect;
+ ldcore->avconfig.video = &ldcore->videotarget;
+
+ /* set the audio target information */
+ if (ldcore->audiobufin + ldcore->audiomaxsamples <= ldcore->audiobufsize)
+ {
+ /* if we can fit without wrapping, just read the data directly */
+ ldcore->avconfig.audio[0] = &ldcore->audiobuffer[0][ldcore->audiobufin];
+ ldcore->avconfig.audio[1] = &ldcore->audiobuffer[1][ldcore->audiobufin];
+ }
+ else
+ {
+ /* otherwise, read to the beginning of the buffer */
+ ldcore->avconfig.audio[0] = &ldcore->audiobuffer[0][0];
+ ldcore->avconfig.audio[1] = &ldcore->audiobuffer[1][0];
+ }
+
+ /* override if we're not decoding */
+ ldcore->avconfig.maxsamples = ldcore->audiomaxsamples;
+ ldcore->avconfig.actsamples = &ldcore->audiocursamples;
+ ldcore->audiocursamples = 0;
+
+ /* set the VBI data for the new field from our precomputed data */
+ if (ldcore->vbidata != NULL)
+ vbi_metadata_unpack(&ldcore->metadata[fieldnum], &vbiframe, &ldcore->vbidata[readhunk * VBI_PACKED_BYTES]);
+
+ /* if we're in the lead-in area, force the VBI data to be standard lead-in */
+ if (tracknum - 1 < VIRTUAL_LEAD_IN_TRACKS)
+ {
+ ldcore->metadata[fieldnum].line16 = 0;
+ ldcore->metadata[fieldnum].line17 = ldcore->metadata[fieldnum].line18 = ldcore->metadata[fieldnum].line1718 = VBI_CODE_LEADIN;
+ }
+
+ /* configure the codec and then read */
+ ldcore->readresult = CHDERR_FILE_NOT_FOUND;
+ if (ldcore->disc != NULL && !ldcore->videosquelch)
+ {
+ ldcore->readresult = chd_codec_config(ldcore->disc, AV_CODEC_DECOMPRESS_CONFIG, &ldcore->avconfig);
+ if (ldcore->readresult == CHDERR_NONE)
+ ldcore->readresult = chd_read_async(ldcore->disc, readhunk, NULL);
+ }
+}
+
+
+/*-------------------------------------------------
+ process_track_data - process data from a
+ track after it has been read
+-------------------------------------------------*/
+
+static void process_track_data(device_t *device)
+{
+ laserdisc_state *ld = get_safe_token(device);
+ ldcore_data *ldcore = ld->core;
+
+ /* wait for the async operation to complete */
+ if (ldcore->readresult == CHDERR_OPERATION_PENDING)
+ ldcore->readresult = chd_async_complete(ldcore->disc);
+
+ /* remove the video if we had an error */
+ if (ldcore->readresult != CHDERR_NONE)
+ ldcore->avconfig.video = NULL;
+
+ /* count the field as read if we are successful */
+ if (ldcore->avconfig.video != NULL)
+ ldcore->frame[ldcore->videoindex].numfields++;
+
+ /* render the display if present */
+ if (ldcore->avconfig.video != NULL && ldcore->intf.overlay != NULL)
+ (*ldcore->intf.overlay)(ld, ldcore->avconfig.video);
+
+ /* pass the audio to the callback */
+ if (ldcore->config.audio != NULL)
+ (*ldcore->config.audio)(device, ldcore->samplerate, ldcore->audiocursamples, ldcore->avconfig.audio[0], ldcore->avconfig.audio[1]);
+
+ /* shift audio data if we read it into the beginning of the buffer */
+ if (ldcore->audiocursamples != 0 && ldcore->audiobufin != 0)
+ {
+ int chnum;
+
+ /* iterate over channels */
+ for (chnum = 0; chnum < 2; chnum++)
+ if (ldcore->avconfig.audio[chnum] == &ldcore->audiobuffer[chnum][0])
+ {
+ int samplesleft;
+
+ /* move data to the end */
+ samplesleft = ldcore->audiobufsize - ldcore->audiobufin;
+ samplesleft = MIN(samplesleft, ldcore->audiocursamples);
+ memmove(&ldcore->audiobuffer[chnum][ldcore->audiobufin], &ldcore->audiobuffer[chnum][0], samplesleft * 2);
+
+ /* shift data at the beginning */
+ if (samplesleft < ldcore->audiocursamples)
+ memmove(&ldcore->audiobuffer[chnum][0], &ldcore->audiobuffer[chnum][samplesleft], (ldcore->audiocursamples - samplesleft) * 2);
+ }
+ }
+
+ /* update the input buffer pointer */
+ ldcore->audiobufin = (ldcore->audiobufin + ldcore->audiocursamples) % ldcore->audiobufsize;
+}
+
+
+/*-------------------------------------------------
+ laserdisc_sound_start - custom audio start
+ for laserdiscs
+-------------------------------------------------*/
+
+static DEVICE_START( laserdisc_sound )
+{
+ sound_token *token = (sound_token *)downcast<legacy_device_base *>(device)->token();
+ token->stream = device->machine().sound().stream_alloc(*device, 0, 2, 48000, token, custom_stream_callback);
+ token->ld = NULL;
+}
+
+
+/*-------------------------------------------------
+ laserdisc_sound_get_info - information
+ callback for laserdisc audio
+-------------------------------------------------*/
+
+DEVICE_GET_INFO( laserdisc_sound )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(sound_token); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(laserdisc_sound);break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Laserdisc Analog"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ }
+}
+
+
+/*-------------------------------------------------
+ custom_stream_callback - audio streamer
+ for laserdiscs
+-------------------------------------------------*/
+
+static STREAM_UPDATE( custom_stream_callback )
+{
+ sound_token *token = (sound_token *)param;
+ laserdisc_state *ld = token->ld;
+ ldcore_data *ldcore = ld->core;
+ stream_sample_t *dst0 = outputs[0];
+ stream_sample_t *dst1 = outputs[1];
+ INT16 leftand, rightand;
+ int samples_avail = 0;
+
+ /* compute AND values based on the squelch */
+ leftand = (ldcore->audiosquelch & 1) ? 0x0000 : 0xffff;
+ rightand = (ldcore->audiosquelch & 2) ? 0x0000 : 0xffff;
+
+ /* see if we have enough samples to fill the buffer; if not, drop out */
+ samples_avail = ldcore->audiobufin - ldcore->audiobufout;
+ if (samples_avail < 0)
+ samples_avail += ldcore->audiobufsize;
+
+ /* if no attached ld, just clear the buffers */
+ if (samples_avail < samples)
+ {
+ memset(dst0, 0, samples * sizeof(dst0[0]));
+ memset(dst1, 0, samples * sizeof(dst1[0]));
+ }
+
+ /* otherwise, stream from our buffer */
+ else
+ {
+ INT16 *buffer0 = ldcore->audiobuffer[0];
+ INT16 *buffer1 = ldcore->audiobuffer[1];
+ int sampout = ldcore->audiobufout;
+
+ /* copy samples, clearing behind us as we go */
+ while (sampout != ldcore->audiobufin && samples-- > 0)
+ {
+ *dst0++ = buffer0[sampout] & leftand;
+ *dst1++ = buffer1[sampout] & rightand;
+ buffer0[sampout] = 0;
+ buffer1[sampout] = 0;
+ sampout++;
+ if (sampout >= ldcore->audiobufsize)
+ sampout = 0;
+ }
+ ldcore->audiobufout = sampout;
+
+ /* clear out the rest of the buffer */
+ if (samples > 0)
+ {
+ sampout = (ldcore->audiobufout == 0) ? ldcore->audiobufsize - 1 : ldcore->audiobufout - 1;
+ stream_sample_t fill0 = buffer0[sampout] & leftand;
+ stream_sample_t fill1 = buffer1[sampout] & rightand;
+
+ while (samples-- > 0)
+ {
+ *dst0++ = fill0;
+ *dst1++ = fill1;
+ }
+ }
+ }
+}
+
+
+
+/***************************************************************************
+ CONFIG SETTINGS ACCESS
+***************************************************************************/
+
+/*-------------------------------------------------
+ configuration_load - read and apply data from
+ the configuration file
+-------------------------------------------------*/
+
+static void configuration_load(device_t *device, int config_type, xml_data_node *parentnode)
+{
+ xml_data_node *overnode;
+ xml_data_node *ldnode;
+
+ /* we only care about game files */
+ if (config_type != CONFIG_TYPE_GAME)
+ return;
+
+ /* might not have any data */
+ if (parentnode == NULL)
+ return;
+
+ /* iterate over overlay nodes */
+ for (ldnode = xml_get_sibling(parentnode->child, "device"); ldnode != NULL; ldnode = xml_get_sibling(ldnode->next, "device"))
+ {
+ const char *devtag = xml_get_attribute_string(ldnode, "tag", "");
+ if (strcmp(devtag,device->tag()) == 0)
+ {
+ laserdisc_state *ld = get_safe_token(device);
+ ldcore_data *ldcore = ld->core;
+
+ /* handle the overlay node */
+ overnode = xml_get_sibling(ldnode->child, "overlay");
+ if (overnode != NULL)
+ {
+ /* fetch positioning controls */
+ ldcore->config.overposx = xml_get_attribute_float(overnode, "hoffset", ldcore->config.overposx);
+ ldcore->config.overscalex = xml_get_attribute_float(overnode, "hstretch", ldcore->config.overscalex);
+ ldcore->config.overposy = xml_get_attribute_float(overnode, "voffset", ldcore->config.overposy);
+ ldcore->config.overscaley = xml_get_attribute_float(overnode, "vstretch", ldcore->config.overscaley);
+ }
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ configuration_save - save data to the
+ configuration file
+-------------------------------------------------*/
+
+static void configuration_save(device_t *device, int config_type, xml_data_node *parentnode)
+{
+ /* we only care about game files */
+ if (config_type != CONFIG_TYPE_GAME)
+ return;
+
+ laserdisc_config *origconfig = (laserdisc_config *)downcast<const legacy_device_base *>(device)->inline_config();
+ laserdisc_state *ld = get_safe_token(device);
+ ldcore_data *ldcore = ld->core;
+ xml_data_node *overnode;
+ xml_data_node *ldnode;
+
+ /* create a node */
+ ldnode = xml_add_child(parentnode, "device", NULL);
+ if (ldnode != NULL)
+ {
+ int changed = FALSE;
+
+ /* output the basics */
+ xml_set_attribute(ldnode, "tag", device->tag());
+
+ /* add an overlay node */
+ overnode = xml_add_child(ldnode, "overlay", NULL);
+ if (overnode != NULL)
+ {
+ /* output the positioning controls */
+ if (ldcore->config.overposx != origconfig->overposx)
+ {
+ xml_set_attribute_float(overnode, "hoffset", ldcore->config.overposx);
+ changed = TRUE;
+ }
+
+ if (ldcore->config.overscalex != origconfig->overscalex)
+ {
+ xml_set_attribute_float(overnode, "hstretch", ldcore->config.overscalex);
+ changed = TRUE;
+ }
+
+ if (ldcore->config.overposy != origconfig->overposy)
+ {
+ xml_set_attribute_float(overnode, "voffset", ldcore->config.overposy);
+ changed = TRUE;
+ }
+
+ if (ldcore->config.overscaley != origconfig->overscaley)
+ {
+ xml_set_attribute_float(overnode, "vstretch", ldcore->config.overscaley);
+ changed = TRUE;
+ }
+ }
+
+ /* if nothing changed, kill the node */
+ if (!changed)
+ xml_delete_node(ldnode);
+ }
+}
+
+
+
+/***************************************************************************
+ VIDEO INTERFACE
+***************************************************************************/
+
+/*-------------------------------------------------
+ laserdisc_video_enable - enable/disable the
+ video
+-------------------------------------------------*/
+
+void laserdisc_video_enable(device_t *device, int enable)
+{
+ laserdisc_state *ld = get_safe_token(device);
+ ld->core->videoenable = enable;
+}
+
+
+/*-------------------------------------------------
+ laserdisc_video_enable - enable/disable the
+ video
+-------------------------------------------------*/
+
+void laserdisc_overlay_enable(device_t *device, int enable)
+{
+ laserdisc_state *ld = get_safe_token(device);
+ ld->core->overenable = enable;
+}
+
+
+/*-------------------------------------------------
+ video update callback
+-------------------------------------------------*/
+
+SCREEN_UPDATE( laserdisc )
+{
+ device_t *laserdisc = screen->machine().device("laserdisc"); // TODO: allow more than one laserdisc
+ if (laserdisc != NULL)
+ {
+ const rectangle &visarea = screen->visible_area();
+ laserdisc_state *ld = (laserdisc_state *)downcast<legacy_device_base *>(laserdisc)->token();
+ ldcore_data *ldcore = ld->core;
+ bitmap_t *overbitmap = ldcore->overbitmap[ldcore->overindex];
+ bitmap_t *vidbitmap = NULL;
+
+ /* handle the overlay if present */
+ if (overbitmap != NULL && ldcore->config.overupdate != NULL)
+ {
+ rectangle clip = *cliprect;
+
+ /* scale the cliprect to the overlay size and then call the update callback */
+ clip.min_x = ldcore->config.overclip.min_x;
+ clip.max_x = ldcore->config.overclip.max_x;
+ clip.min_y = cliprect->min_y * overbitmap->height / bitmap->height;
+ if (cliprect->min_y == visarea.min_y)
+ clip.min_y = MIN(clip.min_y, ldcore->config.overclip.min_y);
+ clip.max_y = (cliprect->max_y + 1) * overbitmap->height / bitmap->height - 1;
+ (*ldcore->config.overupdate)(screen, overbitmap, &clip);
+ }
+
+ /* if this is the last update, do the rendering */
+ if (cliprect->max_y == visarea.max_y)
+ {
+ /* update the texture with the overlay contents */
+ if (overbitmap != NULL)
+ {
+ if (overbitmap->format == BITMAP_FORMAT_INDEXED16)
+ ldcore->overtex->set_bitmap(overbitmap, &ldcore->config.overclip, TEXFORMAT_PALETTEA16, laserdisc->machine().palette);
+ else if (overbitmap->format == BITMAP_FORMAT_RGB32)
+ ldcore->overtex->set_bitmap(overbitmap, &ldcore->config.overclip, TEXFORMAT_ARGB32);
+ }
+
+ /* get the laserdisc video */
+ laserdisc_get_video(laserdisc, &vidbitmap);
+ if (vidbitmap != NULL)
+ ldcore->videotex->set_bitmap(vidbitmap, NULL, TEXFORMAT_YUY16, ldcore->videopalette);
+
+ /* reset the screen contents */
+ screen->container().empty();
+
+ /* add the video texture */
+ if (ldcore->videoenable)
+ screen->container().add_quad(0.0f, 0.0f, 1.0f, 1.0f, MAKE_ARGB(0xff,0xff,0xff,0xff), ldcore->videotex, PRIMFLAG_BLENDMODE(BLENDMODE_NONE) | PRIMFLAG_SCREENTEX(1));
+
+ /* add the overlay */
+ if (ldcore->overenable && overbitmap != NULL)
+ {
+ float x0 = 0.5f - 0.5f * ldcore->config.overscalex + ldcore->config.overposx;
+ float y0 = 0.5f - 0.5f * ldcore->config.overscaley + ldcore->config.overposy;
+ float x1 = x0 + ldcore->config.overscalex;
+ float y1 = y0 + ldcore->config.overscaley;
+ screen->container().add_quad(x0, y0, x1, y1, MAKE_ARGB(0xff,0xff,0xff,0xff), ldcore->overtex, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_SCREENTEX(1));
+ }
+
+ /* swap to the next bitmap */
+ ldcore->overindex = (ldcore->overindex + 1) % ARRAY_LENGTH(ldcore->overbitmap);
+ }
+ }
+
+ return 0;
+}
+
+
+
+/***************************************************************************
+ CONFIGURATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ laserdisc_get_config - return a copy of the
+ current live configuration settings
+-------------------------------------------------*/
+
+void laserdisc_get_config(device_t *device, laserdisc_config *config)
+{
+ laserdisc_state *ld = get_safe_token(device);
+ *config = ld->core->config;
+}
+
+
+/*-------------------------------------------------
+ laserdisc_get_config - change the current live
+ configuration settings
+-------------------------------------------------*/
+
+void laserdisc_set_config(device_t *device, const laserdisc_config *config)
+{
+ laserdisc_state *ld = get_safe_token(device);
+ ld->core->config = *config;
+}
+
+
+
+/***************************************************************************
+ INITIALIZATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ init_disc - initialize the state of the
+ CHD disc
+-------------------------------------------------*/
+
+static void init_disc(device_t *device)
+{
+ const laserdisc_config *config = (const laserdisc_config *)downcast<const legacy_device_base *>(device)->inline_config();
+ laserdisc_state *ld = get_safe_token(device);
+ ldcore_data *ldcore = ld->core;
+ chd_error err;
+
+ /* get a handle to the disc to play */
+ if (config->getdisc != NULL)
+ ldcore->disc = (*config->getdisc)(device);
+ else
+ ldcore->disc = get_disk_handle(device->machine(), device->tag());
+
+ /* set default parameters */
+ ldcore->width = 720;
+ ldcore->height = 240;
+ ldcore->fps_times_1million = 59940000;
+ ldcore->samplerate = 48000;
+
+ /* get the disc metadata and extract the ld */
+ ldcore->chdtracks = 0;
+ ldcore->maxtrack = VIRTUAL_LEAD_IN_TRACKS + MAX_TOTAL_TRACKS + VIRTUAL_LEAD_OUT_TRACKS;
+ if (ldcore->disc != NULL)
+ {
+ UINT32 totalhunks = chd_get_header(ldcore->disc)->totalhunks;
+ int fps, fpsfrac, interlaced, channels;
+ char metadata[256];
+ UINT32 vbilength;
+
+ /* require the A/V codec */
+ if (chd_get_header(ldcore->disc)->compression != CHDCOMPRESSION_AV)
+ fatalerror("Laserdisc video must be compressed with the A/V codec!");
+
+ /* read the metadata */
+ err = chd_get_metadata(ldcore->disc, AV_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL);
+ if (err != CHDERR_NONE)
+ fatalerror("Non-A/V CHD file specified");
+
+ /* extract the metadata */
+ if (sscanf(metadata, AV_METADATA_FORMAT, &fps, &fpsfrac, &ldcore->width, &ldcore->height, &interlaced, &channels, &ldcore->samplerate) != 7)
+ fatalerror("Invalid metadata in CHD file");
+ else
+ ldcore->fps_times_1million = fps * 1000000 + fpsfrac;
+
+ /* require interlaced video */
+ if (!interlaced)
+ fatalerror("Laserdisc video must be interlaced!");
+
+ /* determine the maximum track and allocate a frame buffer */
+ ldcore->chdtracks = totalhunks / 2;
+
+ /* allocate memory for the precomputed per-frame metadata */
+ ldcore->vbidata = auto_alloc_array(device->machine(), UINT8, totalhunks * VBI_PACKED_BYTES);
+ err = chd_get_metadata(ldcore->disc, AV_LD_METADATA_TAG, 0, ldcore->vbidata, totalhunks * VBI_PACKED_BYTES, &vbilength, NULL, NULL);
+ if (err != CHDERR_NONE || vbilength != totalhunks * VBI_PACKED_BYTES)
+ fatalerror("Precomputed VBI metadata missing or incorrect size");
+ }
+ ldcore->maxtrack = MAX(ldcore->maxtrack, VIRTUAL_LEAD_IN_TRACKS + VIRTUAL_LEAD_OUT_TRACKS + ldcore->chdtracks);
+}
+
+
+/*-------------------------------------------------
+ init_video - initialize the state of the
+ video rendering
+-------------------------------------------------*/
+
+static void init_video(device_t *device)
+{
+ laserdisc_state *ld = get_safe_token(device);
+ ldcore_data *ldcore = ld->core;
+ int index;
+
+ /* register for VBLANK callbacks */
+ ld->screen->register_vblank_callback(vblank_state_delegate(FUNC(vblank_state_changed), device));
+
+ /* allocate video frames */
+ for (index = 0; index < ARRAY_LENGTH(ldcore->frame); index++)
+ {
+ frame_data *frame = &ldcore->frame[index];
+
+ /* first allocate a YUY16 bitmap at 2x the height */
+ frame->bitmap = auto_alloc(device->machine(), bitmap_t(ldcore->width, ldcore->height * 2, BITMAP_FORMAT_YUY16));
+ fillbitmap_yuy16(frame->bitmap, 40, 109, 240);
+
+ /* make a copy of the bitmap that clips out the VBI and horizontal blanking areas */
+ frame->visbitmap = auto_alloc(device->machine(), bitmap_t(BITMAP_ADDR16(frame->bitmap, 44, frame->bitmap->width * 8 / 720),
+ frame->bitmap->width - 2 * frame->bitmap->width * 8 / 720,
+ frame->bitmap->height - 44,
+ frame->bitmap->rowpixels, frame->bitmap->format));
+ }
+
+ /* allocate an empty frame of the same size */
+ ldcore->emptyframe = auto_bitmap_alloc(device->machine(), ldcore->width, ldcore->height * 2, BITMAP_FORMAT_YUY16);
+ fillbitmap_yuy16(ldcore->emptyframe, 0, 128, 128);
+
+ /* allocate texture for rendering */
+ ldcore->videoenable = TRUE;
+ ldcore->videotex = device->machine().render().texture_alloc();
+ if (ldcore->videotex == NULL)
+ fatalerror("Out of memory allocating video texture");
+
+ /* allocate palette for applying brightness/contrast/gamma */
+ ldcore->videopalette = palette_alloc(256, 1);
+ if (ldcore->videopalette == NULL)
+ fatalerror("Out of memory allocating video palette");
+ for (index = 0; index < 256; index++)
+ palette_entry_set_color(ldcore->videopalette, index, MAKE_RGB(index, index, index));
+
+ /* allocate overlay */
+ if (ldcore->config.overwidth > 0 && ldcore->config.overheight > 0 && ldcore->config.overupdate != NULL)
+ {
+ ldcore->overenable = TRUE;
+ ldcore->overbitmap[0] = auto_bitmap_alloc(device->machine(), ldcore->config.overwidth, ldcore->config.overheight, (bitmap_format)ldcore->config.overformat);
+ ldcore->overbitmap[1] = auto_bitmap_alloc(device->machine(), ldcore->config.overwidth, ldcore->config.overheight, (bitmap_format)ldcore->config.overformat);
+ ldcore->overtex = device->machine().render().texture_alloc();
+ if (ldcore->overtex == NULL)
+ fatalerror("Out of memory allocating overlay texture");
+ }
+}
+
+
+/*-------------------------------------------------
+ init_audio - initialize the state of the
+ audio rendering
+-------------------------------------------------*/
+
+static void init_audio(device_t *device)
+{
+ laserdisc_state *ld = get_safe_token(device);
+ ldcore_data *ldcore = ld->core;
+
+ /* find the custom audio */
+ ldcore->audiocustom = device->machine().device(ldcore->config.sound);
+
+ /* allocate audio buffers */
+ ldcore->audiomaxsamples = ((UINT64)ldcore->samplerate * 1000000 + ldcore->fps_times_1million - 1) / ldcore->fps_times_1million;
+ ldcore->audiobufsize = ldcore->audiomaxsamples * 4;
+ ldcore->audiobuffer[0] = auto_alloc_array(device->machine(), INT16, ldcore->audiobufsize);
+ ldcore->audiobuffer[1] = auto_alloc_array(device->machine(), INT16, ldcore->audiobufsize);
+}
+
+
+
+/***************************************************************************
+ DEVICE INTERFACE
+***************************************************************************/
+
+/*-------------------------------------------------
+ device start callback
+-------------------------------------------------*/
+
+static DEVICE_START( laserdisc )
+{
+ const laserdisc_config *config = (const laserdisc_config *)downcast<const legacy_device_base *>(device)->inline_config();
+ laserdisc_state *ld = get_safe_token(device);
+ ldcore_data *ldcore;
+
+ /* ensure that our screen is started first */
+ ld->screen = downcast<screen_device *>(device->machine().device(config->screen));
+ assert(ld->screen != NULL);
+ if (!ld->screen->started())
+ throw device_missing_dependencies();
+
+ /* save a copy of the device pointer */
+ ld->device = device;
+
+ /* allocate memory for the core state */
+ ld->core = auto_alloc_clear(device->machine(), ldcore_data);
+ ldcore = ld->core;
+
+ if (device->type() == PIONEER_PR8210)
+ ldcore->intf = pr8210_interface;
+ else if (device->type() == SIMUTREK_SPECIAL)
+ ldcore->intf = simutrek_interface;
+ else if (device->type() == PIONEER_LDV1000)
+ ldcore->intf = ldv1000_interface;
+ else if (device->type() == PHILLIPS_22VP931)
+ ldcore->intf = vp931_interface;
+
+ ld->player = (ldplayer_data *)auto_alloc_array_clear(device->machine(), UINT8, ldcore->intf.statesize);
+
+ /* copy config data to the live state */
+ ldcore->config = *config;
+ if (ldcore->config.overclip.max_x == ldcore->config.overclip.min_x || ldcore->config.overclip.max_y == ldcore->config.overclip.min_y)
+ {
+ ldcore->config.overclip.min_x = ldcore->config.overclip.min_y = 0;
+ ldcore->config.overclip.max_x = ldcore->config.overwidth - 1;
+ ldcore->config.overclip.max_y = ldcore->config.overheight - 1;
+ }
+ if (ldcore->config.overscalex == 0)
+ ldcore->config.overscalex = 1.0f;
+ if (ldcore->config.overscaley == 0)
+ ldcore->config.overscaley = 1.0f;
+
+ /* initialize the various pieces */
+ init_disc(device);
+ init_video(device);
+ init_audio(device);
+
+ /* register callbacks */
+ config_register(device->machine(), "laserdisc", config_saveload_delegate(FUNC(configuration_load), device), config_saveload_delegate(FUNC(configuration_save), device));
+}
+
+
+/*-------------------------------------------------
+ device exit callback
+-------------------------------------------------*/
+
+static DEVICE_STOP( laserdisc )
+{
+ laserdisc_state *ld = get_safe_token(device);
+ ldcore_data *ldcore = ld->core;
+
+ /* make sure all async operations have completed */
+ if (ldcore->disc != NULL)
+ chd_async_complete(ldcore->disc);
+
+ /* free any textures and palettes */
+ device->machine().render().texture_free(ldcore->videotex);
+ if (ldcore->videopalette != NULL)
+ palette_deref(ldcore->videopalette);
+ device->machine().render().texture_free(ldcore->overtex);
+}
+
+
+/*-------------------------------------------------
+ device reset callback
+-------------------------------------------------*/
+
+static DEVICE_RESET( laserdisc )
+{
+ laserdisc_state *ld = get_safe_token(device);
+ attotime curtime = device->machine().time();
+ ldcore_data *ldcore = ld->core;
+ int line;
+
+ /* attempt to wire up the audio */
+ if (ldcore->audiocustom != NULL)
+ {
+ sound_token *token = (sound_token *)downcast<legacy_device_base *>(ldcore->audiocustom)->token();
+ token->ld = ld;
+ token->stream->set_sample_rate(ldcore->samplerate);
+ }
+
+ /* set up the general ld */
+ ldcore->audiosquelch = 3;
+ ldcore->videosquelch = 1;
+ ldcore->fieldnum = 0;
+ ldcore->curtrack = 1;
+ ldcore->attospertrack = 0;
+ ldcore->sliderupdate = curtime;
+
+ /* reset the I/O lines */
+ for (line = 0; line < LASERDISC_INPUT_LINES; line++)
+ ldcore->linein[line] = CLEAR_LINE;
+ for (line = 0; line < LASERDISC_OUTPUT_LINES; line++)
+ ldcore->lineout[line] = CLEAR_LINE;
+
+ /* call the initialization */
+ if (ldcore->intf.init != NULL)
+ (*ldcore->intf.init)(ld);
+}
+
+
+/*-------------------------------------------------
+ device set info callback
+-------------------------------------------------*/
+
+int laserdisc_get_type(device_t *device)
+{
+ if (device->type() == PIONEER_PR7820)
+ return LASERDISC_TYPE_PIONEER_PR7820;
+ if (device->type() == PIONEER_PR8210)
+ return LASERDISC_TYPE_PIONEER_PR8210;
+ if (device->type() == SIMUTREK_SPECIAL)
+ return LASERDISC_TYPE_SIMUTREK_SPECIAL;
+ if (device->type() == PIONEER_LDV1000)
+ return LASERDISC_TYPE_PIONEER_LDV1000;
+ if (device->type() == PHILLIPS_22VP931)
+ return LASERDISC_TYPE_PHILLIPS_22VP931;
+ if (device->type() == PHILLIPS_22VP932)
+ return LASERDISC_TYPE_PHILLIPS_22VP932;
+ if (device->type() == SONY_LDP1450)
+ return LASERDISC_TYPE_SONY_LDP1450;
+ return LASERDISC_TYPE_UNKNOWN;
+}
+
+void laserdisc_set_type(device_t *device, int type)
+{
+ // this is no longer supported
+}
+
+
+DEVICE_GET_INFO( laserdisc )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(laserdisc_state); break;
+ case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = sizeof(laserdisc_config); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(laserdisc); break;
+ case DEVINFO_FCT_STOP: info->stop = DEVICE_STOP_NAME(laserdisc); break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(laserdisc); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Laserdisc Player"); 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;
+ }
+}
+
+DEVICE_GET_INFO( unkldplay )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers --- */
+ case DEVINFO_PTR_ROM_REGION: info->romregion = NULL; return;
+ case DEVINFO_PTR_MACHINE_CONFIG: info->machine_config = NULL; return;
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s,"Unknown Laserdisc Player"); return;
+ case DEVINFO_STR_SHORTNAME: strcpy(info->s,"unkldplay"); return;
+ }
+
+ DEVICE_GET_INFO_CALL( laserdisc );
+}
+
+DEVICE_GET_INFO( pioneer_pr7820 )
+{
+ DEVICE_GET_INFO_CALL( unkldplay );
+}
+
+DEVICE_GET_INFO( pioneer_pr8210 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers --- */
+ case DEVINFO_PTR_ROM_REGION: info->romregion = pr8210_interface.romregion; return;
+ case DEVINFO_PTR_MACHINE_CONFIG: info->machine_config = pr8210_interface.machine_config; return;
+
+ /* --- the following bits of info are returned as NULL-terminated strings -- */
+ case DEVINFO_STR_NAME: strcpy(info->s, pr8210_interface.name); return;
+ case DEVINFO_STR_SHORTNAME: strcpy(info->s, pr8210_interface.shortname); return;
+ }
+
+ DEVICE_GET_INFO_CALL( laserdisc );
+}
+
+DEVICE_GET_INFO( simutrek_special )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers --- */
+ case DEVINFO_PTR_ROM_REGION: info->romregion = simutrek_interface.romregion; return;
+ case DEVINFO_PTR_MACHINE_CONFIG: info->machine_config = simutrek_interface.machine_config; return;
+
+ /* --- the following bits of info are returned as NULL-terminated strings -- */
+ case DEVINFO_STR_NAME: strcpy(info->s, simutrek_interface.name); return;
+ case DEVINFO_STR_SHORTNAME: strcpy(info->s, simutrek_interface.shortname); return;
+ }
+
+ DEVICE_GET_INFO_CALL( laserdisc );
+}
+
+DEVICE_GET_INFO( pioneer_ldv1000 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers --- */
+ case DEVINFO_PTR_ROM_REGION: info->romregion = ldv1000_interface.romregion; return;
+ case DEVINFO_PTR_MACHINE_CONFIG: info->machine_config = ldv1000_interface.machine_config; return;
+
+ /* --- the following bits of info are returned as NULL-terminated strings -- */
+ case DEVINFO_STR_NAME: strcpy(info->s, ldv1000_interface.name); return;
+ case DEVINFO_STR_SHORTNAME: strcpy(info->s, ldv1000_interface.shortname); return;
+ }
+
+ DEVICE_GET_INFO_CALL( laserdisc );
+}
+
+DEVICE_GET_INFO( phillips_22vp931 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers --- */
+ case DEVINFO_PTR_ROM_REGION: info->romregion = vp931_interface.romregion; return;
+ case DEVINFO_PTR_MACHINE_CONFIG: info->machine_config = vp931_interface.machine_config; return;
+
+ /* --- the following bits of info are returned as NULL-terminated strings -- */
+ case DEVINFO_STR_NAME: strcpy(info->s, vp931_interface.name); return;
+ case DEVINFO_STR_SHORTNAME: strcpy(info->s, vp931_interface.shortname); return;
+ }
+
+ DEVICE_GET_INFO_CALL( laserdisc );
+}
+
+DEVICE_GET_INFO( phillips_22vp932 )
+{
+ DEVICE_GET_INFO_CALL( unkldplay );
+}
+
+DEVICE_GET_INFO( sony_ldp1450 )
+{
+ DEVICE_GET_INFO_CALL( unkldplay );
+}
+
+DEFINE_LEGACY_DEVICE(PIONEER_PR7820,pioneer_pr7820);
+DEFINE_LEGACY_DEVICE(PIONEER_PR8210,pioneer_pr8210);
+DEFINE_LEGACY_DEVICE(SIMUTREK_SPECIAL,simutrek_special);
+DEFINE_LEGACY_DEVICE(PIONEER_LDV1000,pioneer_ldv1000);
+DEFINE_LEGACY_DEVICE(PHILLIPS_22VP931,phillips_22vp931);
+DEFINE_LEGACY_DEVICE(PHILLIPS_22VP932,phillips_22vp932);
+DEFINE_LEGACY_DEVICE(SONY_LDP1450,sony_ldp1450);
+DEFINE_LEGACY_SOUND_DEVICE(LASERDISC_SOUND, laserdisc_sound);
diff --git a/trunk/src/emu/machine/ldcore.h b/trunk/src/emu/machine/ldcore.h
new file mode 100644
index 00000000000..24f6361930a
--- /dev/null
+++ b/trunk/src/emu/machine/ldcore.h
@@ -0,0 +1,268 @@
+/*************************************************************************
+
+ ldcore.h
+
+ Private core laserdisc player implementation.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*************************************************************************/
+
+#pragma once
+
+#ifndef __LDCORE_H__
+#define __LDCORE_H__
+
+#include "laserdsc.h"
+#include "vbiparse.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* common laserdisc states */
+enum
+{
+ LDSTATE_NONE, /* unspecified state */
+ LDSTATE_EJECTING, /* in the process of ejecting */
+ LDSTATE_EJECTED, /* fully ejected */
+ LDSTATE_PARKED, /* head parked in lead-in */
+ LDSTATE_LOADING, /* loading from ejected state */
+ LDSTATE_SPINUP, /* spinning up */
+ LDSTATE_PAUSING, /* looking for a frame boundary to pause */
+ LDSTATE_PAUSED, /* found a frame boundary; now paused */
+ /* parameter specifies the fieldnum of the first frame */
+ LDSTATE_PLAYING, /* playing forward normally, with audio */
+ /* parameter specifies the target frame, or 0 if none */
+ LDSTATE_PLAYING_SLOW_REVERSE, /* playing slow in the reverse direction, with no audio */
+ /* parameter specifies the number of times to repeat each track */
+ LDSTATE_PLAYING_SLOW_FORWARD, /* playing slow in the forward direction, with no audio */
+ /* parameter specifies the number of times to repeat each track */
+ LDSTATE_PLAYING_FAST_REVERSE, /* playing fast in the reverse direction, with no audio */
+ /* parameter specifies the number of frames to skip backwards after each frame */
+ LDSTATE_PLAYING_FAST_FORWARD, /* playing fast in the forward direction, with no audio */
+ /* parameter specifies the number of frames to skip forwards after each frame */
+ LDSTATE_STEPPING_REVERSE, /* single frame stepping in the reverse direction */
+ LDSTATE_STEPPING_FORWARD, /* single frame stepping in the forward direction */
+ LDSTATE_SCANNING, /* scanning in the forward or reverse direction */
+ /* parameter(0:7) controls how many vsyncs until revert to savestate */
+ /* parameter(8:31) specifies the speed */
+ LDSTATE_SEEKING, /* seeking to a specific frame */
+ /* parameter specifies the target frame */
+ LDSTATE_OTHER /* other states start here */
+};
+
+
+/* slider position */
+enum _slider_position
+{
+ SLIDER_MINIMUM, /* at the minimum value */
+ SLIDER_VIRTUAL_LEADIN, /* within the virtual lead-in area */
+ SLIDER_CHD, /* within the boundaries of the CHD */
+ SLIDER_OUTSIDE_CHD, /* outside of the CHD area but before the virtual lead-out area */
+ SLIDER_VIRTUAL_LEADOUT, /* within the virtual lead-out area */
+ SLIDER_MAXIMUM /* at the maximum value */
+};
+typedef enum _slider_position slider_position;
+
+
+/* special frame and chapter numbers from VBI conversion */
+#define FRAME_NOT_PRESENT -2 /* no frame number information present */
+#define FRAME_LEAD_IN -1 /* lead-in code detected */
+#define FRAME_LEAD_OUT 99999 /* lead-out code detected */
+#define CHAPTER_NOT_PRESENT -2 /* no chapter number information present */
+#define CHAPTER_LEAD_IN -1 /* lead-in code detected */
+#define CHAPTER_LEAD_OUT 100 /* lead-out code detected */
+
+/* generic head movement speeds; use player-specific information where appropriate */
+#define GENERIC_SLOW_SPEED (5) /* 1/5 normal speed */
+#define GENERIC_FAST_SPEED (3) /* 3x normal speed */
+#define GENERIC_SCAN_SPEED (50) /* 50x normal speed */
+#define GENERIC_SEARCH_SPEED (5000) /* 5000x normal speed */
+
+/* generic timings; use player-specific information where appropriate */
+#define GENERIC_EJECT_TIME (attotime::from_seconds(5))
+#define GENERIC_SPINUP_TIME (attotime::from_seconds(2))
+#define GENERIC_LOAD_TIME (attotime::from_seconds(5))
+
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define SCANNING_PARAM(speed,duration) (((speed) << 8) | ((duration) & 0xff))
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/* core-specific and player-specific data */
+typedef struct _ldplayer_data ldplayer_data;
+typedef struct _ldcore_data ldcore_data;
+
+
+/* player state */
+typedef struct _ldplayer_state ldplayer_state;
+struct _ldplayer_state
+{
+ UINT8 state; /* current state */
+ INT32 substate; /* internal sub-state; starts at 0 on any state change */
+ INT32 param; /* parameter for current state */
+ attotime endtime; /* minimum ending time for current state */
+};
+
+
+/* generic data */
+typedef struct _laserdisc_state laserdisc_state;
+struct _laserdisc_state
+{
+ device_t * device; /* pointer to owning device */
+ screen_device * screen; /* pointer to the screen device */
+ ldcore_data * core; /* private core data */
+ ldplayer_data * player; /* private player data */
+
+ ldplayer_state state; /* active state */
+ ldplayer_state savestate; /* saved state during temporary operations */
+};
+
+
+/* player-specific callbacks */
+typedef void (*laserdisc_init_func)(laserdisc_state *ld);
+typedef void (*laserdisc_vsync_func)(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime);
+typedef INT32 (*laserdisc_update_func)(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime);
+typedef void (*laserdisc_overlay_func)(laserdisc_state *ld, bitmap_t *bitmap);
+typedef void (*laserdisc_w_func)(laserdisc_state *ld, UINT8 prev, UINT8 newval);
+typedef UINT8 (*laserdisc_r_func)(laserdisc_state *ld);
+
+
+/* player configuration */
+typedef struct _ldplayer_interface ldplayer_interface;
+struct _ldplayer_interface
+{
+ int type; /* type of the player */
+ size_t statesize; /* size of the state */
+ const char * name; /* name of the player */
+ const char * shortname; /* shortname of the player */
+ const rom_entry * romregion; /* pointer to ROM region information */
+ machine_config_constructor machine_config; /* pointer to machine configuration */
+ laserdisc_init_func init; /* initialization callback */
+ laserdisc_vsync_func vsync; /* vsync begin callback */
+ laserdisc_update_func update; /* update callback (line 16) */
+ laserdisc_overlay_func overlay; /* overlay callback */
+ laserdisc_w_func writedata; /* parallel data write */
+ laserdisc_w_func writeline[LASERDISC_INPUT_LINES]; /* single line write */
+ laserdisc_r_func readdata; /* parallel data read */
+ laserdisc_r_func readline[LASERDISC_OUTPUT_LINES]; /* single line read */
+};
+
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+/* defined by each player */
+extern const ldplayer_interface pr7820_interface;
+extern const ldplayer_interface pr8210_interface;
+extern const ldplayer_interface simutrek_interface;
+extern const ldplayer_interface ldv1000_interface;
+extern const ldplayer_interface ldp1450_interface;
+extern const ldplayer_interface vp931_interface;
+extern const ldplayer_interface vp932_interface;
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+
+/* ----- player interface ----- */
+
+/* return a token with type checking from a device */
+laserdisc_state *ldcore_get_safe_token(device_t *device);
+
+/* set the left/right audio squelch states */
+void ldcore_set_audio_squelch(laserdisc_state *ld, UINT8 squelchleft, UINT8 squelchright);
+
+/* set the video squelch state */
+void ldcore_set_video_squelch(laserdisc_state *ld, UINT8 squelch);
+
+/* dynamically change the slider speed */
+void ldcore_set_slider_speed(laserdisc_state *ld, INT32 tracks_per_vsync);
+
+/* advance the slider by a certain number of tracks */
+void ldcore_advance_slider(laserdisc_state *ld, INT32 numtracks);
+
+/* get the current slider position */
+slider_position ldcore_get_slider_position(laserdisc_state *ld);
+
+
+
+/* ----- generic implementations ----- */
+
+/* generically update in a way that works for most situations */
+INT32 ldcore_generic_update(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime, ldplayer_state *curstate);
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ is_start_of_frame - return TRUE if this is
+ the start of a frame
+-------------------------------------------------*/
+
+INLINE int is_start_of_frame(const vbi_metadata *vbi)
+{
+ /* is it not known if the white flag or the presence of a frame code
+ determines the start of frame; the former seems to be the "official"
+ way, but the latter seems to be the practical implementation */
+ return (vbi->white || (vbi->line1718 & VBI_MASK_CAV_PICTURE) == VBI_CODE_CAV_PICTURE);
+}
+
+
+/*-------------------------------------------------
+ frame_from_metadata - return the frame number
+ encoded in the metadata, if present, or
+ FRAME_NOT_PRESENT
+-------------------------------------------------*/
+
+INLINE int frame_from_metadata(const vbi_metadata *metadata)
+{
+ if ((metadata->line1718 & VBI_MASK_CAV_PICTURE) == VBI_CODE_CAV_PICTURE)
+ return VBI_CAV_PICTURE(metadata->line1718);
+ else if (metadata->line1718 == VBI_CODE_LEADIN)
+ return FRAME_LEAD_IN;
+ else if (metadata->line1718 == VBI_CODE_LEADOUT)
+ return FRAME_LEAD_OUT;
+ return FRAME_NOT_PRESENT;
+}
+
+
+/*-------------------------------------------------
+ chapter_from_metadata - return the chapter
+ number encoded in the metadata, if present,
+ or CHAPTER_NOT_PRESENT
+-------------------------------------------------*/
+
+INLINE int chapter_from_metadata(const vbi_metadata *metadata)
+{
+ if ((metadata->line1718 & VBI_MASK_CHAPTER) == VBI_CODE_CHAPTER)
+ return VBI_CHAPTER(metadata->line1718);
+ else if (metadata->line1718 == VBI_CODE_LEADIN)
+ return CHAPTER_LEAD_IN;
+ else if (metadata->line1718 == VBI_CODE_LEADOUT)
+ return CHAPTER_LEAD_OUT;
+ return CHAPTER_NOT_PRESENT;
+}
+
+
+#endif
diff --git a/trunk/src/emu/machine/ldpr8210.c b/trunk/src/emu/machine/ldpr8210.c
new file mode 100644
index 00000000000..00f05bbef9d
--- /dev/null
+++ b/trunk/src/emu/machine/ldpr8210.c
@@ -0,0 +1,1271 @@
+/*************************************************************************
+
+ ldpr8210.c
+
+ Pioneer PR-8210 laserdisc emulation.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**************************************************************************
+
+ Still to do:
+
+ * implement SLOW TRG
+ * figure out Simutrek without jump hack
+ * figure out serial protocol issues (current hack works nicely)
+ * determine actual slow/fast speeds
+
+*************************************************************************/
+
+#include "emu.h"
+#include "ldcore.h"
+#include "cpu/mcs48/mcs48.h"
+
+
+
+/***************************************************************************
+ DEBUGGING
+***************************************************************************/
+
+#define LOG_VBLANK_VBI 0
+#define LOG_SERIAL 0
+#define LOG_SIMUTREK 0
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* Overlay constants, related to 720-pixel wide capture */
+#define OVERLAY_GROUP0_X (82.0f / 720.0f)
+#define OVERLAY_GROUP1_X (162.0f / 720.0f)
+#define OVERLAY_GROUP2_X (322.0f / 720.0f)
+#define OVERLAY_GROUP3_X (483.0f / 720.0f)
+#define OVERLAY_Y (104/2)
+#define OVERLAY_PIXEL_WIDTH (4.5f / 720.0f)
+#define OVERLAY_PIXEL_HEIGHT 2
+#define OVERLAY_X_PIXELS 5
+#define OVERLAY_Y_PIXELS 7
+
+/* scanning speeds */
+#define SCAN_SPEED (2000 / 30) /* 2000 frames/second */
+#define SEEK_FAST_SPEED (4000 / 30) /* 4000 frames/second */
+
+/* serial timing, mostly from the service manual, derived from the XTAL */
+#define SERIAL_CLOCK XTAL_455kHz
+#define SERIAL_0_BIT_TIME attotime::from_hz((double)SERIAL_CLOCK / 512)
+#define SERIAL_1_BIT_TIME attotime::from_hz((double)SERIAL_CLOCK / 1024)
+#define SERIAL_MIDPOINT_TIME attotime::from_hz((double)SERIAL_CLOCK / 600)
+#define SERIAL_MAX_BIT_TIME attotime::from_hz((double)SERIAL_CLOCK / 4096)
+#define SERIAL_MAX_WORD_TIME attotime::from_hz((double)SERIAL_CLOCK / 11520)
+#define SERIAL_REJECT_DUPLICATE_TIME attotime::from_hz((double)SERIAL_CLOCK / 11520 / 4)
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/* PIA data */
+typedef struct _pioneer_pia pioneer_pia;
+struct _pioneer_pia
+{
+ UINT8 frame[7]; /* (20-26) 7 characters for the chapter/frame */
+ UINT8 text[17]; /* (20-30) 17 characters for the display */
+ UINT8 control; /* (40) control lines */
+ UINT8 latchdisplay; /* flag: set if the display was latched */
+ UINT8 portb; /* (60) port B value (LEDs) */
+ UINT8 display; /* (80) display enable */
+ UINT8 porta; /* (A0) port A value (from serial decoder) */
+ UINT8 vbi1; /* (C0) VBI decoding state 1 */
+ UINT8 vbi2; /* (E0) VBI decoding state 2 */
+};
+
+
+/* Simutrek-specific data */
+typedef struct _simutrek_data simutrek_data;
+struct _simutrek_data
+{
+ device_t *cpu; /* 8748 CPU device */
+ UINT8 audio_squelch; /* audio squelch value */
+ UINT8 data; /* parallel data for simutrek */
+ UINT8 data_ready; /* ready flag for simutrek data */
+ UINT8 port2; /* 8748 port 2 state */
+ UINT8 controlnext; /* latch to control next pair of fields */
+ UINT8 controlthis; /* latched value for our control over the current pair of fields */
+};
+
+
+/* player-specific data */
+struct _ldplayer_data
+{
+ /* serial/command interface processing */
+ UINT8 lastcommand; /* last command seen */
+ UINT16 accumulator; /* bit accumulator */
+ attotime lastcommandtime; /* time of the last command */
+ attotime lastbittime; /* time of last bit received */
+ attotime firstbittime; /* time of first bit in command */
+
+ /* low-level emulation data */
+ device_t *cpu; /* 8049 CPU device */
+ attotime slowtrg; /* time of the last SLOW TRG */
+ pioneer_pia pia; /* PIA state */
+ UINT8 vsync; /* live VSYNC state */
+ UINT8 port1; /* 8049 port 1 state */
+ UINT8 port2; /* 8049 port 2 state */
+
+ /* Simutrek-specific data */
+ simutrek_data simutrek; /* Simutrek-specific data */
+};
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void pr8210_init(laserdisc_state *ld);
+static void pr8210_vsync(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime);
+static INT32 pr8210_update(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime);
+static void pr8210_overlay(laserdisc_state *ld, bitmap_t *bitmap);
+static void pr8210_control_w(laserdisc_state *ld, UINT8 prev, UINT8 data);
+
+static TIMER_CALLBACK( vsync_off );
+static TIMER_CALLBACK( vbi_data_fetch );
+
+static READ8_HANDLER( pr8210_pia_r );
+static WRITE8_HANDLER( pr8210_pia_w );
+static READ8_HANDLER( pr8210_bus_r );
+static WRITE8_HANDLER( pr8210_port1_w );
+static WRITE8_HANDLER( pr8210_port2_w );
+static READ8_HANDLER( pr8210_t0_r );
+static READ8_HANDLER( pr8210_t1_r );
+
+static void overlay_draw_group(bitmap_t *bitmap, const UINT8 *text, int count, float xstart);
+static void overlay_erase(bitmap_t *bitmap, float xstart, float xend);
+static void overlay_draw_char(bitmap_t *bitmap, UINT8 ch, float xstart);
+
+static void simutrek_init(laserdisc_state *ld);
+static void simutrek_vsync(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime);
+static INT32 simutrek_update(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime);
+static UINT8 simutrek_ready_r(laserdisc_state *ld);
+static UINT8 simutrek_status_r(laserdisc_state *ld);
+static void simutrek_data_w(laserdisc_state *ld, UINT8 prev, UINT8 data);
+
+static TIMER_CALLBACK( simutrek_latched_data_w );
+
+static READ8_HANDLER( simutrek_port2_r );
+static WRITE8_HANDLER( simutrek_port2_w );
+static READ8_HANDLER( simutrek_data_r );
+static READ8_HANDLER( simutrek_t0_r );
+
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+/* bitmaps for the characters */
+static const UINT8 text_bitmap[0x40][7] =
+{
+ { 0 }, /* @ */
+ { 0x20,0x50,0x88,0x88,0xf8,0x88,0x88 }, /* A */
+ { 0 }, /* B */
+ { 0x70,0x88,0x80,0x80,0x80,0x88,0x70 }, /* C */
+ { 0 }, /* D */
+ { 0xf8,0x80,0x80,0xf0,0x80,0x80,0xf8 }, /* E */
+ { 0xf8,0x80,0x80,0xf0,0x80,0x80,0x80 }, /* F */
+ { 0 }, /* G */
+ { 0x88,0x88,0x88,0xf8,0x88,0x88,0x88 }, /* H */
+ { 0 }, /* I */
+ { 0 }, /* J */
+ { 0 }, /* K */
+ { 0 }, /* L */
+ { 0x88,0xd8,0xa8,0xa8,0xa8,0x88,0x88 }, /* M */
+ { 0 }, /* N */
+ { 0 }, /* O */
+ { 0xf0,0x88,0x88,0xf0,0x80,0x80,0x80 }, /* P */
+ { 0 }, /* Q */
+ { 0xf0,0x88,0x88,0xf0,0xa0,0x90,0x88 }, /* R */
+ { 0x70,0x88,0x80,0x70,0x08,0x88,0x70 }, /* S */
+ { 0 }, /* T */
+ { 0 }, /* U */
+ { 0 }, /* V */
+ { 0 }, /* W */
+ { 0 }, /* X */
+ { 0 }, /* Y */
+ { 0 }, /* Z */
+ { 0 }, /* [ */
+ { 0 }, /* \ */
+ { 0 }, /* ] */
+ { 0 }, /* ^ */
+ { 0 }, /* _ */
+
+ { 0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, /* <space> */
+ { 0 }, /* ! */
+ { 0 }, /* " */
+ { 0 }, /* # */
+ { 0 }, /* $ */
+ { 0 }, /* % */
+ { 0 }, /* & */
+ { 0 }, /* ' */
+ { 0 }, /* ( */
+ { 0 }, /* ) */
+ { 0 }, /* * */
+ { 0 }, /* + */
+ { 0 }, /* , */
+ { 0 }, /* - */
+ { 0x00,0x00,0x00,0x00,0x00,0x00,0x40 }, /* . */
+ { 0 }, /* / */
+ { 0x70,0x88,0x88,0x88,0x88,0x88,0x70 }, /* 0 */
+ { 0x20,0x60,0x20,0x20,0x20,0x20,0x70 }, /* 1 */
+ { 0x70,0x88,0x08,0x70,0x80,0x80,0xf8 }, /* 2 */
+ { 0xf8,0x08,0x10,0x30,0x08,0x88,0x70 }, /* 3 */
+ { 0x10,0x30,0x50,0x90,0xf8,0x10,0x10 }, /* 4 */
+ { 0xf8,0x80,0xf0,0x08,0x08,0x88,0x70 }, /* 5 */
+ { 0x78,0x80,0x80,0xf0,0x88,0x88,0x70 }, /* 6 */
+ { 0xf8,0x08,0x08,0x10,0x20,0x40,0x80 }, /* 7 */
+ { 0x70,0x88,0x88,0x70,0x88,0x88,0x70 }, /* 8 */
+ { 0x70,0x88,0x88,0x78,0x08,0x08,0xf0 }, /* 9 */
+ { 0 }, /* : */
+ { 0 }, /* ; */
+ { 0 }, /* < */
+ { 0 }, /* = */
+ { 0 }, /* > */
+ { 0 } /* ? */
+};
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ update_video_squelch - update the state of
+ the video squelch
+-------------------------------------------------*/
+
+INLINE void update_video_squelch(laserdisc_state *ld)
+{
+ ldplayer_data *player = ld->player;
+ ldcore_set_video_squelch(ld, (player->port1 & 0x20) != 0);
+}
+
+
+/*-------------------------------------------------
+ update_audio_squelch - update the state of
+ the audio squelch
+-------------------------------------------------*/
+
+INLINE void update_audio_squelch(laserdisc_state *ld)
+{
+ ldplayer_data *player = ld->player;
+ if (player->simutrek.cpu == NULL)
+ ldcore_set_audio_squelch(ld, (player->port1 & 0x40) || !(player->pia.portb & 0x01), (player->port1 & 0x40) || !(player->pia.portb & 0x02));
+ else
+ ldcore_set_audio_squelch(ld, player->simutrek.audio_squelch, player->simutrek.audio_squelch);
+}
+
+
+
+/***************************************************************************
+ PR-8210 ROM AND MACHINE INTERFACES
+***************************************************************************/
+
+static ADDRESS_MAP_START( pr8210_portmap, AS_IO, 8 )
+ AM_RANGE(0x00, 0xff) AM_READWRITE(pr8210_pia_r, pr8210_pia_w)
+ AM_RANGE(MCS48_PORT_BUS, MCS48_PORT_BUS) AM_READ(pr8210_bus_r)
+ AM_RANGE(MCS48_PORT_P1, MCS48_PORT_P1) AM_WRITE(pr8210_port1_w)
+ AM_RANGE(MCS48_PORT_P2, MCS48_PORT_P2) AM_WRITE(pr8210_port2_w)
+ AM_RANGE(MCS48_PORT_T0, MCS48_PORT_T0) AM_READ(pr8210_t0_r)
+ AM_RANGE(MCS48_PORT_T1, MCS48_PORT_T1) AM_READ(pr8210_t1_r)
+ADDRESS_MAP_END
+
+
+static MACHINE_CONFIG_FRAGMENT( pr8210 )
+ MCFG_CPU_ADD("pr8210", I8049, XTAL_4_41MHz)
+ MCFG_CPU_IO_MAP(pr8210_portmap)
+MACHINE_CONFIG_END
+
+
+ROM_START( pr8210 )
+ ROM_REGION( 0x800, "pr8210", 0 )
+ ROM_LOAD( "pr-8210_mcu_ud6005a.bin", 0x000, 0x800, CRC(120fa83b) SHA1(b514326ca1f52d6d89056868f9d17eabd4e3f31d) )
+ROM_END
+
+
+
+/***************************************************************************
+ PR-8210 PLAYER INTERFACE
+***************************************************************************/
+
+const ldplayer_interface pr8210_interface =
+{
+ LASERDISC_TYPE_PIONEER_PR8210, /* type of the player */
+ sizeof(ldplayer_data), /* size of the state */
+ "Pioneer PR-8210", /* name of the player */
+ "pr8210", /* shortname of the player */
+ ROM_NAME(pr8210), /* pointer to ROM region information */
+ MACHINE_CONFIG_NAME(pr8210), /* pointer to machine configuration */
+ pr8210_init, /* initialization callback */
+ pr8210_vsync, /* vsync callback */
+ pr8210_update, /* update callback */
+ pr8210_overlay, /* overlay callback */
+ NULL, /* parallel data write */
+ { /* single line write: */
+ NULL, /* LASERDISC_LINE_ENTER */
+ pr8210_control_w /* LASERDISC_LINE_CONTROL */
+ },
+ NULL, /* parallel data read */
+ { /* single line read: */
+ NULL, /* LASERDISC_LINE_READY */
+ NULL, /* LASERDISC_LINE_STATUS */
+ NULL, /* LASERDISC_LINE_COMMAND */
+ NULL, /* LASERDISC_LINE_DATA_AVAIL */
+ }
+};
+
+
+
+/***************************************************************************
+ PIONEER PR-8210 IMPLEMENTATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ pr8210_init - player-specific initialization
+-------------------------------------------------*/
+
+static void pr8210_init(laserdisc_state *ld)
+{
+ astring tempstring;
+ attotime curtime = ld->device->machine().time();
+ ldplayer_data *player = ld->player;
+
+ /* reset our state */
+ memset(player, 0, sizeof(*player));
+ player->lastcommandtime = curtime;
+ player->firstbittime = curtime;
+ player->lastbittime = curtime;
+ player->slowtrg = curtime;
+
+ /* find our CPU */
+ player->cpu = ld->device->subdevice("pr8210");
+ assert(player->cpu != NULL);
+
+ /* we don't have the Simutrek player overrides */
+ player->simutrek.cpu = NULL;
+ player->simutrek.audio_squelch = FALSE;
+}
+
+
+/*-------------------------------------------------
+ pr8210_vsync - VSYNC callback, called at the
+ start of the blanking period
+-------------------------------------------------*/
+
+static void pr8210_vsync(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime)
+{
+ ldplayer_data *player = ld->player;
+
+ /* logging */
+ if (LOG_VBLANK_VBI)
+ {
+ if ((vbi->line1718 & VBI_MASK_CAV_PICTURE) == VBI_CODE_CAV_PICTURE)
+ printf("%3d:VSYNC(%d,%05d)\n", ld->screen->vpos(), fieldnum, VBI_CAV_PICTURE(vbi->line1718));
+ else
+ printf("%3d:VSYNC(%d)\n", ld->screen->vpos(), fieldnum);
+ }
+
+ /* signal VSYNC and set a timer to turn it off */
+ player->vsync = TRUE;
+ ld->device->machine().scheduler().timer_set(ld->screen->scan_period() * 4, FUNC(vsync_off), 0, ld);
+
+ /* also set a timer to fetch the VBI data when it is ready */
+ ld->device->machine().scheduler().timer_set(ld->screen->time_until_pos(19*2), FUNC(vbi_data_fetch), 0, ld);
+}
+
+
+/*-------------------------------------------------
+ pr8210_update - update callback, called on
+ the first visible line of the frame
+-------------------------------------------------*/
+
+static INT32 pr8210_update(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime)
+{
+ ldplayer_data *player = ld->player;
+ UINT8 spdl_on = !(player->port1 & 0x10);
+
+ /* logging */
+ if (LOG_VBLANK_VBI)
+ printf("%3d:Update(%d)\n", ld->screen->vpos(), fieldnum);
+
+ /* if the spindle is on, we advance by 1 track after completing field #1 */
+ return (spdl_on) ? fieldnum : 0;
+}
+
+
+/*-------------------------------------------------
+ pr8210_overlay - overlay callback, called
+ during frame processing in update to overlay
+ player data
+-------------------------------------------------*/
+
+static void pr8210_overlay(laserdisc_state *ld, bitmap_t *bitmap)
+{
+ ldplayer_data *player = ld->player;
+
+ /* custom display */
+ if (player->pia.display)
+ {
+ overlay_draw_group(bitmap, &player->pia.text[2], 5, OVERLAY_GROUP1_X);
+ overlay_draw_group(bitmap, &player->pia.text[7], 5, OVERLAY_GROUP2_X);
+ overlay_draw_group(bitmap, &player->pia.text[12], 5, OVERLAY_GROUP3_X);
+ }
+
+ /* chapter/frame display */
+ else
+ {
+ /* frame display */
+ if (player->pia.latchdisplay & 2)
+ overlay_draw_group(bitmap, &player->pia.text[2], 5, OVERLAY_GROUP1_X);
+
+ /* chapter overlay */
+ if (player->pia.latchdisplay & 1)
+ overlay_draw_group(bitmap, &player->pia.text[0], 2, OVERLAY_GROUP0_X);
+ }
+ player->pia.latchdisplay = 0;
+}
+
+
+/*-------------------------------------------------
+ pr8210_control_w - write callback when the
+ CONTROL line is toggled
+-------------------------------------------------*/
+
+static void pr8210_control_w(laserdisc_state *ld, UINT8 prev, UINT8 data)
+{
+ ldplayer_data *player = ld->player;
+
+ /* handle rising edge */
+ if (prev != ASSERT_LINE && data == ASSERT_LINE)
+ {
+ attotime curtime = ld->device->machine().time();
+ attotime delta, overalldelta;
+ int longpulse;
+
+ /* get the time difference from the last assert */
+ /* and update our internal command time */
+ delta = curtime - player->lastbittime;
+ player->lastbittime = curtime;
+
+ /* if we timed out since the first bit, reset the accumulator */
+ overalldelta = curtime - player->firstbittime;
+ if (overalldelta > SERIAL_MAX_WORD_TIME || delta > SERIAL_MAX_BIT_TIME)
+ {
+ player->firstbittime = curtime;
+ player->accumulator = 0x5555;
+ if (LOG_SERIAL)
+ printf("Reset accumulator\n");
+ }
+
+ /* 0 bit delta is 1.05 msec, 1 bit delta is 2.11 msec */
+ longpulse = (delta < SERIAL_MIDPOINT_TIME) ? 0 : 1;
+ player->accumulator = (player->accumulator << 1) | longpulse;
+
+ /* log the deltas for debugging */
+ if (LOG_SERIAL)
+ {
+ int usecdiff = (int)(delta.attoseconds / ATTOSECONDS_IN_USEC(1));
+ printf("bitdelta = %5d (%d) - accum = %04X\n", usecdiff, longpulse, player->accumulator);
+ }
+
+ /* if we have a complete command, signal it */
+ /* a complete command is 0,0,1 followed by 5 bits, followed by 0,0 */
+ if ((player->accumulator & 0x383) == 0x80)
+ {
+ UINT8 newcommand = (player->accumulator >> 2) & 0x1f;
+ attotime rejectuntil;
+
+ /* data is stored to the PIA in bit-reverse order */
+ player->pia.porta = BITSWAP8(newcommand, 0,1,2,3,4,5,6,7);
+
+ /* the MCU logic requires a 0 to execute many commands; however, nobody
+ consistently sends a 0, whereas they do tend to send duplicate commands...
+ if we assume that each duplicate causes a 0, we get the correct results */
+ rejectuntil = player->lastcommandtime + SERIAL_REJECT_DUPLICATE_TIME;
+ player->lastcommandtime = curtime;
+ if (player->pia.porta == player->lastcommand && curtime < rejectuntil)
+ player->pia.porta = 0x00;
+ else
+ player->lastcommand = player->pia.porta;
+
+ /* log the command and wait for a keypress */
+ if (LOG_SERIAL)
+ printf("--- Command = %02X\n", player->pia.porta >> 3);
+
+ /* reset the first bit time so that the accumulator clears on the next write */
+ player->firstbittime = curtime - SERIAL_MAX_WORD_TIME;
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ vsync_off - timer callback to clear the VSYNC
+ flag
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( vsync_off )
+{
+ laserdisc_state *ld = (laserdisc_state *)ptr;
+ ld->player->vsync = FALSE;
+}
+
+
+/*-------------------------------------------------
+ vbi_data_fetch - timer callback to update the
+ VBI data in the PIA as soon as it is ready;
+ this must happy early in the frame because
+ the player logic relies on fetching it here
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( vbi_data_fetch )
+{
+ laserdisc_state *ld = (laserdisc_state *)ptr;
+ ldplayer_data *player = ld->player;
+ UINT8 focus_on = !(player->port1 & 0x08);
+ UINT8 laser_on = !(player->port2 & 0x01);
+ UINT32 line16 = laserdisc_get_field_code(ld->device, LASERDISC_CODE_LINE16, FALSE);
+ UINT32 line1718 = laserdisc_get_field_code(ld->device, LASERDISC_CODE_LINE1718, FALSE);
+
+ /* logging */
+ if (LOG_VBLANK_VBI)
+ {
+ if ((line1718 & VBI_MASK_CAV_PICTURE) == VBI_CODE_CAV_PICTURE)
+ printf("%3d:VBI(%05d)\n", ld->screen->vpos(), VBI_CAV_PICTURE(line1718));
+ else
+ printf("%3d:VBI()\n", ld->screen->vpos());
+ }
+
+ /* update PIA registers based on vbi code */
+ player->pia.vbi1 = 0xff;
+ player->pia.vbi2 = 0xff;
+ if (focus_on && laser_on)
+ {
+ if (line1718 == VBI_CODE_LEADIN)
+ player->pia.vbi1 &= ~0x01;
+ if (line1718 == VBI_CODE_LEADOUT)
+ player->pia.vbi1 &= ~0x02;
+ if (line16 == VBI_CODE_STOP)
+ player->pia.vbi1 &= ~0x04;
+ /* unsure what this bit means: player->pia.vbi1 &= ~0x08; */
+ if ((line1718 & VBI_MASK_CAV_PICTURE) == VBI_CODE_CAV_PICTURE)
+ {
+ player->pia.vbi1 &= ~0x10;
+ player->pia.frame[2] = 0xf0 | ((line1718 >> 16) & 0x07);
+ player->pia.frame[3] = 0xf0 | ((line1718 >> 12) & 0x0f);
+ player->pia.frame[4] = 0xf0 | ((line1718 >> 8) & 0x0f);
+ player->pia.frame[5] = 0xf0 | ((line1718 >> 4) & 0x0f);
+ player->pia.frame[6] = 0xf0 | ((line1718 >> 0) & 0x0f);
+ }
+ if ((line1718 & VBI_MASK_CHAPTER) == VBI_CODE_CHAPTER)
+ {
+ player->pia.vbi2 &= ~0x01;
+ player->pia.frame[0] = 0xf0 | ((line1718 >> 16) & 0x07);
+ player->pia.frame[1] = 0xf0 | ((line1718 >> 12) & 0x0f);
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ pr8210_pia_r - handle reads from the mystery
+ Pioneer PIA
+-------------------------------------------------*/
+
+static READ8_HANDLER( pr8210_pia_r )
+{
+ laserdisc_state *ld = ldcore_get_safe_token(space->device().owner());
+ ldplayer_data *player = ld->player;
+ UINT8 result = 0xff;
+
+ switch (offset)
+ {
+ /* (20-26) 7 characters for the chapter/frame */
+ case 0x20: case 0x21:
+ case 0x22: case 0x23: case 0x24: case 0x25: case 0x26:
+ result = player->pia.frame[offset - 0x20];
+ break;
+
+ /* (1D-1F,27) invalid read but normal */
+ case 0x1d: case 0x1e: case 0x1f:
+ case 0x27:
+ break;
+
+ /* (A0) port A value (from serial decoder) */
+ case 0xa0:
+ result = player->pia.porta;
+ break;
+
+ /* (C0) VBI decoding state 1 */
+ case 0xc0:
+ if (LOG_VBLANK_VBI)
+ printf("%3d:PIA(C0)\n", ld->screen->vpos());
+ result = player->pia.vbi1;
+ break;
+
+ /* (E0) VBI decoding state 2 */
+ case 0xe0:
+ if (LOG_VBLANK_VBI)
+ printf("%3d:PIA(E0)\n", ld->screen->vpos());
+ result = player->pia.vbi2;
+ break;
+
+ default:
+ mame_printf_debug("%03X:Unknown PR-8210 PIA read from offset %02X\n", cpu_get_pc(&space->device()), offset);
+ break;
+ }
+ return result;
+}
+
+
+/*-------------------------------------------------
+ pr8210_pia_w - handle writes to the mystery
+ Pioneer PIA
+-------------------------------------------------*/
+
+static WRITE8_HANDLER( pr8210_pia_w )
+{
+ laserdisc_state *ld = ldcore_get_safe_token(space->device().owner());
+ ldplayer_data *player = ld->player;
+ UINT8 value;
+
+ switch (offset)
+ {
+ /* (20-30) 17 characters for the display */
+ 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: case 0x30:
+ player->pia.text[offset - 0x20] = data;
+ break;
+
+ /* (40) control lines */
+ case 0x40:
+
+ /* toggle bit 0 to latch chapter number into display area */
+ if (!(data & 0x01) && (player->pia.control & 0x01))
+ {
+ memcpy(&player->pia.text[0], &player->pia.frame[0], 2);
+ player->pia.latchdisplay |= 1;
+ }
+
+ /* toggle bit 1 to latch frame number into display area */
+ if (!(data & 0x02) && (player->pia.control & 0x02))
+ {
+ memcpy(&player->pia.text[2], &player->pia.frame[2], 5);
+ player->pia.latchdisplay |= 2;
+ }
+ player->pia.control = data;
+ break;
+
+ /* (60) port B value (LEDs) */
+ case 0x60:
+
+ /* these 4 are direct-connect */
+ output_set_value("pr8210_audio1", (data & 0x01) != 0);
+ output_set_value("pr8210_audio2", (data & 0x02) != 0);
+ output_set_value("pr8210_clv", (data & 0x04) != 0);
+ output_set_value("pr8210_cav", (data & 0x08) != 0);
+
+ /* remaining 3 bits select one of 5 LEDs via a mux */
+ value = ((data & 0x40) >> 6) | ((data & 0x20) >> 4) | ((data & 0x10) >> 2);
+ output_set_value("pr8210_srev", (value == 0));
+ output_set_value("pr8210_sfwd", (value == 1));
+ output_set_value("pr8210_play", (value == 2));
+ output_set_value("pr8210_step", (value == 3));
+ output_set_value("pr8210_pause", (value == 4));
+
+ player->pia.portb = data;
+ update_audio_squelch(ld);
+ break;
+
+ /* (80) display enable */
+ case 0x80:
+ player->pia.display = data & 0x01;
+ break;
+
+ /* no other writes known */
+ default:
+ mame_printf_debug("%03X:Unknown PR-8210 PIA write to offset %02X = %02X\n", cpu_get_pc(&space->device()), offset, data);
+ break;
+ }
+}
+
+
+/*-------------------------------------------------
+ pr8210_bus_r - handle reads from the 8049 BUS
+ input, which is enabled via the PIA above
+-------------------------------------------------*/
+
+static READ8_HANDLER( pr8210_bus_r )
+{
+ /*
+ $80 = n/c
+ $40 = (in) slider pot interrupt source (slider position limit detector, inside and outside)
+ $20 = n/c
+ $10 = (in) /FOCUS LOCK
+ $08 = (in) /SPDL LOCK
+ $04 = (in) SIZE 8/12
+ $02 = (in) FG via op-amp (spindle motor stop detector)
+ $01 = (in) SLOW TIMER OUT
+ */
+ laserdisc_state *ld = ldcore_get_safe_token(space->device().owner());
+ ldplayer_data *player = ld->player;
+ slider_position sliderpos = ldcore_get_slider_position(ld);
+ UINT8 focus_on = !(player->port1 & 0x08);
+ UINT8 spdl_on = !(player->port1 & 0x10);
+ UINT8 result = 0x00;
+
+ /* bus bit 6: slider position limit detector, inside and outside */
+ if (sliderpos != SLIDER_MINIMUM && sliderpos != SLIDER_MAXIMUM)
+ result |= 0x40;
+
+ /* bus bit 4: /FOCUS LOCK */
+ if (!focus_on)
+ result |= 0x10;
+
+ /* bus bit 3: /SPDL LOCK */
+ if (!spdl_on)
+ result |= 0x08;
+
+ /* bus bit 1: spindle motor stop detector */
+ if (!spdl_on)
+ result |= 0x02;
+
+ /* bus bit 0: SLOW TIMER OUT */
+
+ /* loop at beginning waits for $40=0, $02=1 */
+ return result;
+}
+
+
+/*-------------------------------------------------
+ pr8210_port1_w - handle writes to the 8049
+ port #1
+-------------------------------------------------*/
+
+static WRITE8_HANDLER( pr8210_port1_w )
+{
+ /*
+ $80 = (out) SCAN C (F/R)
+ $40 = (out) AUDIO SQ
+ $20 = (out) VIDEO SQ
+ $10 = (out) /SPDL ON
+ $08 = (out) /FOCUS ON
+ $04 = (out) SCAN B (L/H)
+ $02 = (out) SCAN A (/SCAN)
+ $01 = (out) JUMP TRG (jump back trigger, clock on high->low)
+ */
+ laserdisc_state *ld = ldcore_get_safe_token(space->device().owner());
+ ldplayer_data *player = ld->player;
+ UINT8 prev = player->port1;
+ int direction;
+
+ /* set the new value */
+ player->port1 = data;
+
+ /* bit 7 selects the direction of slider movement for JUMP TRG and scanning */
+ direction = (data & 0x80) ? 1 : -1;
+
+ /* on the falling edge of bit 0, jump one track in either direction */
+ if (!(data & 0x01) && (prev & 0x01))
+ {
+ /* special override for the Simutrek, which takes over control of this is some situations */
+ if (player->simutrek.cpu == NULL || !player->simutrek.controlthis)
+ {
+ if (LOG_SIMUTREK)
+ printf("%3d:JUMP TRG\n", ld->screen->vpos());
+ ldcore_advance_slider(ld, direction);
+ }
+ else if (LOG_SIMUTREK)
+ printf("%3d:Skipped JUMP TRG\n", ld->screen->vpos());
+ }
+
+ /* bit 1 low enables scanning */
+ if (!(data & 0x02))
+ {
+ /* bit 2 selects the speed */
+ int delta = (data & 0x04) ? SCAN_SPEED : SEEK_FAST_SPEED;
+ ldcore_set_slider_speed(ld, delta * direction);
+ }
+
+ /* bit 1 high stops scanning */
+ else
+ ldcore_set_slider_speed(ld, 0);
+
+ /* video squelch is controlled by bit 5 */
+ update_video_squelch(ld);
+
+ /* audio squelch is controlled by bit 6 */
+ update_audio_squelch(ld);
+}
+
+
+/*-------------------------------------------------
+ pr8210_port2_w - handle writes to the 8049
+ port #2
+-------------------------------------------------*/
+
+static WRITE8_HANDLER( pr8210_port2_w )
+{
+ /*
+ $80 = (out) /CS on PIA
+ $40 = (out) 0 to self-generate IRQ
+ $20 = (out) SLOW TRG
+ $10 = (out) STANDBY LED
+ $08 = (out) TP2
+ $04 = (out) TP1
+ $02 = (out) ???
+ $01 = (out) LASER ON
+ */
+ laserdisc_state *ld = ldcore_get_safe_token(space->device().owner());
+ ldplayer_data *player = ld->player;
+ UINT8 prev = player->port2;
+
+ /* set the new value */
+ player->port2 = data;
+
+ /* on the falling edge of bit 5, start the slow timer */
+ if (!(data & 0x20) && (prev & 0x20))
+ player->slowtrg = space->machine().time();
+
+ /* bit 6 when low triggers an IRQ on the MCU */
+ if (player->cpu != NULL)
+ device_set_input_line(player->cpu, MCS48_INPUT_IRQ, (data & 0x40) ? CLEAR_LINE : ASSERT_LINE);
+
+ /* standby LED is set accordingl to bit 4 */
+ output_set_value("pr8210_standby", (data & 0x10) != 0);
+}
+
+
+/*-------------------------------------------------
+ pr8210_t0_r - return the state of the 8049
+ T0 input (connected to VSYNC)
+-------------------------------------------------*/
+
+static READ8_HANDLER( pr8210_t0_r )
+{
+ /* returns VSYNC state */
+ laserdisc_state *ld = ldcore_get_safe_token(space->device().owner());
+ return !ld->player->vsync;
+}
+
+
+/*-------------------------------------------------
+ pr8210_t1_r - return the state of the 8049
+ T1 input (pulled high)
+-------------------------------------------------*/
+
+static READ8_HANDLER( pr8210_t1_r )
+{
+ return 1;
+}
+
+
+/*-------------------------------------------------
+ overlay_draw_group - draw a single group of
+ characters
+-------------------------------------------------*/
+
+static void overlay_draw_group(bitmap_t *bitmap, const UINT8 *text, int count, float xstart)
+{
+ int skip = TRUE;
+ int x;
+
+ /* rease the background */
+ overlay_erase(bitmap, xstart, xstart + ((OVERLAY_X_PIXELS + 1) * count + 1) * OVERLAY_PIXEL_WIDTH);
+
+ /* draw each character, suppressing leading 0's */
+ for (x = 0; x < count; x++)
+ if (!skip || x == count - 1 || (text[x] & 0x3f) != 0x30)
+ {
+ skip = FALSE;
+ overlay_draw_char(bitmap, text[x], xstart + ((OVERLAY_X_PIXELS + 1) * x + 1) * OVERLAY_PIXEL_WIDTH);
+ }
+}
+
+
+/*-------------------------------------------------
+ overlay_erase - erase the background area
+ where the text overlay will be displayed
+-------------------------------------------------*/
+
+static void overlay_erase(bitmap_t *bitmap, float xstart, float xend)
+{
+ UINT32 xmin = (UINT32)(xstart * 256.0f * (float)bitmap->width);
+ UINT32 xmax = (UINT32)(xend * 256.0f * (float)bitmap->width);
+ UINT32 x, y;
+
+ for (y = OVERLAY_Y; y < (OVERLAY_Y + (OVERLAY_Y_PIXELS + 2) * OVERLAY_PIXEL_HEIGHT); y++)
+ {
+ UINT16 *dest = BITMAP_ADDR16(bitmap, y, xmin >> 8);
+ UINT16 ymin, ymax, yres;
+
+ ymax = *dest >> 8;
+ ymin = ymax * 3 / 8;
+ yres = ymin + ((ymax - ymin) * (xmin & 0xff)) / 256;
+ *dest = (yres << 8) | (*dest & 0xff);
+ dest++;
+
+ for (x = (xmin | 0xff) + 1; x < xmax; x += 0x100)
+ {
+ yres = (*dest >> 8) * 3 / 8;
+ *dest = (yres << 8) | (*dest & 0xff);
+ dest++;
+ }
+
+ ymax = *dest >> 8;
+ ymin = ymax * 3 / 8;
+ yres = ymin + ((ymax - ymin) * (~xmax & 0xff)) / 256;
+ *dest = (yres << 8) | (*dest & 0xff);
+ dest++;
+ }
+}
+
+
+/*-------------------------------------------------
+ overlay_draw_char - draw a single character
+ of the text overlay
+-------------------------------------------------*/
+
+static void overlay_draw_char(bitmap_t *bitmap, UINT8 ch, float xstart)
+{
+ UINT32 xminbase = (UINT32)(xstart * 256.0f * (float)bitmap->width);
+ UINT32 xsize = (UINT32)(OVERLAY_PIXEL_WIDTH * 256.0f * (float)bitmap->width);
+ const UINT8 *chdataptr = &text_bitmap[ch & 0x3f][0];
+ UINT32 x, y, xx, yy;
+
+ /* iterate over pixels */
+ for (y = 0; y < OVERLAY_Y_PIXELS; y++)
+ {
+ UINT8 chdata = *chdataptr++;
+
+ for (x = 0; x < OVERLAY_X_PIXELS; x++, chdata <<= 1)
+ if (chdata & 0x80)
+ {
+ UINT32 xmin = xminbase + x * xsize;
+ UINT32 xmax = xmin + xsize;
+ for (yy = 0; yy < OVERLAY_PIXEL_HEIGHT; yy++)
+ {
+ UINT16 *dest = BITMAP_ADDR16(bitmap, OVERLAY_Y + (y + 1) * OVERLAY_PIXEL_HEIGHT + yy, xmin >> 8);
+ UINT16 ymin, ymax, yres;
+
+ ymax = 0xff;
+ ymin = *dest >> 8;
+ yres = ymin + ((ymax - ymin) * (~xmin & 0xff)) / 256;
+ *dest = (yres << 8) | (*dest & 0xff);
+ dest++;
+
+ for (xx = (xmin | 0xff) + 1; xx < xmax; xx += 0x100)
+ *dest++ = 0xf080;
+
+ ymax = 0xff;
+ ymin = *dest >> 8;
+ yres = ymin + ((ymax - ymin) * (xmax & 0xff)) / 256;
+ *dest = (yres << 8) | (*dest & 0xff);
+ dest++;
+ }
+ }
+ }
+}
+
+
+
+/***************************************************************************
+ SIMUTREK ROM AND MACHINE INTERFACES
+***************************************************************************/
+
+static ADDRESS_MAP_START( simutrek_portmap, AS_IO, 8 )
+ AM_RANGE(0x00, 0xff) AM_READ(simutrek_data_r)
+ AM_RANGE(MCS48_PORT_P2, MCS48_PORT_P2) AM_READWRITE(simutrek_port2_r, simutrek_port2_w)
+ AM_RANGE(MCS48_PORT_T0, MCS48_PORT_T0) AM_READ(simutrek_t0_r)
+ADDRESS_MAP_END
+
+
+static MACHINE_CONFIG_FRAGMENT( simutrek )
+ MCFG_CPU_ADD("simutrek", I8748, XTAL_6MHz)
+ MCFG_CPU_IO_MAP(simutrek_portmap)
+
+ MCFG_FRAGMENT_ADD(pr8210)
+MACHINE_CONFIG_END
+
+
+ROM_START( simutrek )
+ ROM_REGION( 0x800, "pr8210", 0 )
+ ROM_LOAD( "pr-8210_mcu_ud6005a.bin", 0x000, 0x800, CRC(120fa83b) SHA1(b514326ca1f52d6d89056868f9d17eabd4e3f31d) )
+
+ ROM_REGION( 0x400, "simutrek", 0)
+ ROM_LOAD( "laser_player_interface_d8748_a308.bin", 0x0000, 0x0400, CRC(eed3e728) SHA1(1eb3467f1c41553375b2c21952cd593b167f5416) )
+ROM_END
+
+
+
+/***************************************************************************
+ SIMUTREK PLAYER INTERFACE
+***************************************************************************/
+
+const ldplayer_interface simutrek_interface =
+{
+ LASERDISC_TYPE_SIMUTREK_SPECIAL, /* type of the player */
+ sizeof(ldplayer_data), /* size of the state */
+ "Simutrek Modified PR-8210", /* name of the player */
+ "mpr8210", /* shortname of the player */
+ ROM_NAME(simutrek), /* pointer to ROM region information */
+ MACHINE_CONFIG_NAME(simutrek), /* pointer to machine configuration */
+ simutrek_init, /* initialization callback */
+ simutrek_vsync, /* vsync callback */
+ simutrek_update, /* update callback */
+ pr8210_overlay, /* overlay callback */
+ simutrek_data_w, /* parallel data write */
+ { /* single line write: */
+ NULL, /* LASERDISC_LINE_ENTER */
+ NULL /* LASERDISC_LINE_CONTROL */
+ },
+ NULL, /* parallel data read */
+ { /* single line read: */
+ simutrek_ready_r, /* LASERDISC_LINE_READY */
+ simutrek_status_r, /* LASERDISC_LINE_STATUS */
+ NULL, /* LASERDISC_LINE_COMMAND */
+ NULL, /* LASERDISC_LINE_DATA_AVAIL */
+ }
+};
+
+
+
+/***************************************************************************
+ SIMUTREK IMPLEMENTATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ simutrek_set_audio_squelch - Simutrek-specific
+ command to enable/disable audio squelch
+-------------------------------------------------*/
+
+void simutrek_set_audio_squelch(device_t *device, int state)
+{
+ laserdisc_state *ld = ldcore_get_safe_token(device);
+ ldplayer_data *player = ld->player;
+ if (LOG_SIMUTREK && player->simutrek.audio_squelch != (state == 0))
+ printf("--> audio squelch = %d\n", state == 0);
+ player->simutrek.audio_squelch = (state == 0);
+ update_audio_squelch(ld);
+}
+
+
+/*-------------------------------------------------
+ simutrek_init - Simutrek-specific
+ initialization
+-------------------------------------------------*/
+
+static void simutrek_init(laserdisc_state *ld)
+{
+ astring tempstring;
+ ldplayer_data *player = ld->player;
+
+ /* standard PR-8210 initialization */
+ pr8210_init(ld);
+
+ /* initialize the Simutrek state */
+ /* for proper synchronization of initial attract mode, this needs to be set */
+ player->simutrek.data_ready = 1;
+
+ /* find the Simutrek CPU */
+ player->simutrek.cpu = ld->device->subdevice("simutrek");
+}
+
+
+/*-------------------------------------------------
+ simutrek_vsync - VSYNC callback, called at the
+ start of the blanking period
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( irq_off )
+{
+ laserdisc_state *ld = (laserdisc_state *)ptr;
+ ldplayer_data *player = ld->player;
+ device_set_input_line(player->simutrek.cpu, MCS48_INPUT_IRQ, CLEAR_LINE);
+ if (LOG_SIMUTREK)
+ printf("%3d:**** Simutrek IRQ clear\n", ld->screen->vpos());
+}
+
+static void simutrek_vsync(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime)
+{
+ ldplayer_data *player = ld->player;
+
+ if (fieldnum == 1)
+ {
+ player->simutrek.controlthis = player->simutrek.controlnext;
+ player->simutrek.controlnext = 0;
+ }
+
+ if (LOG_SIMUTREK)
+ printf("%3d:VSYNC(%d)\n", ld->screen->vpos(), fieldnum);
+ pr8210_vsync(ld, vbi, fieldnum, curtime);
+
+ if (player->simutrek.data_ready)
+ {
+ if (LOG_SIMUTREK)
+ printf("%3d:VSYNC IRQ\n", ld->screen->vpos());
+ device_set_input_line(player->simutrek.cpu, MCS48_INPUT_IRQ, ASSERT_LINE);
+ ld->device->machine().scheduler().timer_set(ld->screen->scan_period(), FUNC(irq_off), 0, ld);
+ }
+}
+
+
+/*-------------------------------------------------
+ simutrek_update - update callback, called on
+ the first visible line of the frame
+-------------------------------------------------*/
+
+static INT32 simutrek_update(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime)
+{
+ return pr8210_update(ld, vbi, fieldnum, curtime);
+}
+
+
+/*-------------------------------------------------
+ simutrek_ready_r - read callback when the
+ READY line is read
+-------------------------------------------------*/
+
+static UINT8 simutrek_ready_r(laserdisc_state *ld)
+{
+ return !ld->player->simutrek.data_ready;
+}
+
+
+/*-------------------------------------------------
+ simutrek_status_r - read callback when the
+ STATUS line is read
+-------------------------------------------------*/
+
+static UINT8 simutrek_status_r(laserdisc_state *ld)
+{
+ return ((ld->player->simutrek.port2 & 0x03) == 0x03) ? ASSERT_LINE : CLEAR_LINE;
+}
+
+
+/*-------------------------------------------------
+ simutrek_data_w - write callback when the
+ parallel data port is written to
+-------------------------------------------------*/
+
+static void simutrek_data_w(laserdisc_state *ld, UINT8 prev, UINT8 data)
+{
+ ld->device->machine().scheduler().synchronize(FUNC(simutrek_latched_data_w), data, ld);
+ if (LOG_SIMUTREK)
+ printf("%03d:**** Simutrek Command = %02X\n", ld->screen->vpos(), data);
+}
+
+
+/*-------------------------------------------------
+ simutrek_latched_data_w - deferred write
+ callback for when data is written
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( simutrek_latched_data_w )
+{
+ laserdisc_state *ld = (laserdisc_state *)ptr;
+ ldplayer_data *player = ld->player;
+
+ /* store the data and set the ready flag */
+ player->simutrek.data = param;
+ player->simutrek.data_ready = TRUE;
+}
+
+
+/*-------------------------------------------------
+ simutrek_port2_r - handle reads from the 8748
+ port #2
+-------------------------------------------------*/
+
+static READ8_HANDLER( simutrek_port2_r )
+{
+ laserdisc_state *ld = ldcore_get_safe_token(space->device().owner());
+ ldplayer_data *player = ld->player;
+
+ /* bit $80 is the pr8210 video squelch */
+ return (player->port1 & 0x20) ? 0x00 : 0x80;
+}
+
+
+/*-------------------------------------------------
+ simutrek_port2_w - handle writes to the 8748
+ port #2
+-------------------------------------------------*/
+
+static WRITE8_HANDLER( simutrek_port2_w )
+{
+ laserdisc_state *ld = ldcore_get_safe_token(space->device().owner());
+ ldplayer_data *player = ld->player;
+ UINT8 prev = player->simutrek.port2;
+
+ /* update stat */
+ player->simutrek.port2 = data;
+
+ /* bit $20 goes to the serial line */
+ if ((data ^ prev) & 0x20)
+ pr8210_control_w(ld, (data & 0x20) ? ASSERT_LINE : CLEAR_LINE, (data & 0x20) ? CLEAR_LINE : ASSERT_LINE);
+
+ /* bit $10 goes to JUMP TRG */
+ /* bit $08 controls direction */
+ if (!(data & 0x10) && (prev & 0x10))
+ {
+ int direction = (data & 0x08) ? 1 : -1;
+ if (LOG_SIMUTREK)
+ printf("%3d:JUMP TRG (Simutrek PC=%03X)\n", ld->screen->vpos(), cpu_get_pc(&space->device()));
+ ldcore_advance_slider(ld, direction);
+ }
+
+ /* bit $04 controls who owns the JUMP TRG command */
+ if (LOG_SIMUTREK && ((data ^ prev) & 0x04))
+ printf("%3d:Simutrek ownership line = %d (Simutrek PC=%03X)\n", ld->screen->vpos(), (data >> 2) & 1, cpu_get_pc(&space->device()));
+ player->simutrek.controlnext = (~data >> 2) & 1;
+
+ /* bits $03 control something (status?) */
+ if (LOG_SIMUTREK && ((data ^ prev) & 0x03))
+ printf("Simutrek Status = %d\n", data & 0x03);
+}
+
+
+/*-------------------------------------------------
+ simutrek_data_r - handle external 8748 data
+ reads
+-------------------------------------------------*/
+
+static READ8_HANDLER( simutrek_data_r )
+{
+ laserdisc_state *ld = ldcore_get_safe_token(space->device().owner());
+ ldplayer_data *player = ld->player;
+
+ /* acknowledge the read and clear the data ready flag */
+ player->simutrek.data_ready = FALSE;
+ return player->simutrek.data;
+}
+
+
+/*-------------------------------------------------
+ simutrek_t0_r - return the status of the
+ 8748 T0 input
+-------------------------------------------------*/
+
+static READ8_HANDLER( simutrek_t0_r )
+{
+ /* return 1 if data is waiting from main CPU */
+ laserdisc_state *ld = ldcore_get_safe_token(space->device().owner());
+ return ld->player->simutrek.data_ready;
+}
diff --git a/trunk/src/emu/machine/ldv1000.c b/trunk/src/emu/machine/ldv1000.c
new file mode 100644
index 00000000000..7ee15ce8179
--- /dev/null
+++ b/trunk/src/emu/machine/ldv1000.c
@@ -0,0 +1,761 @@
+/*************************************************************************
+
+ ldv1000.c
+
+ Pioneer LD-V1000 laserdisc emulation.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**************************************************************************
+
+ Still to do:
+
+ * fix issues
+ * add OSD
+
+*************************************************************************/
+
+#include "emu.h"
+#include "ldcore.h"
+#include "machine/8255ppi.h"
+#include "machine/z80ctc.h"
+#include "cpu/z80/z80.h"
+#include "cpu/z80/z80daisy.h"
+
+
+
+/***************************************************************************
+ DEBUGGING
+***************************************************************************/
+
+#define LOG_PORT_IO 0
+#define LOG_STATUS_CHANGES 0
+#define LOG_FRAMES_SEEN 0
+#define LOG_COMMANDS 0
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define SCAN_SPEED (2000 / 30) /* 2000 frames/second */
+#define SEEK_FAST_SPEED (4000 / 30) /* 4000 frames/second */
+
+#define MULTIJUMP_TRACK_TIME attotime::from_usec(50)
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/* player-specific data */
+struct _ldplayer_data
+{
+ /* low-level emulation data */
+ device_t *cpu; /* CPU index of the Z80 */
+ device_t *ctc; /* CTC device */
+ timer_device * multitimer; /* multi-jump timer device */
+
+ /* communication status */
+ UINT8 command; /* command byte to the player */
+ UINT8 status; /* status byte from the player */
+ UINT8 vsync; /* VSYNC state */
+
+ /* I/O port states */
+ UINT8 counter_start; /* starting value for counter */
+ UINT8 counter; /* current counter value */
+ UINT8 portc0; /* port C on PPI 0 */
+ UINT8 portb1; /* port B on PPI 1 */
+ UINT8 portc1; /* port C on PPI 1 */
+
+ /* display/decode circuit emulation */
+ UINT8 portselect; /* selection of which port to access */
+ UINT8 display[2][20]; /* display lines */
+ UINT8 dispindex; /* index within the display line */
+ UINT8 vbi[7*3]; /* VBI data */
+ UINT8 vbiready; /* VBI ready flag */
+ UINT8 vbiindex; /* index within the VBI data */
+};
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void ldv1000_init(laserdisc_state *ld);
+static void ldv1000_vsync(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime);
+static INT32 ldv1000_update(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime);
+static void ldv1000_data_w(laserdisc_state *ld, UINT8 prev, UINT8 data);
+static UINT8 ldv1000_status_strobe_r(laserdisc_state *ld);
+static UINT8 ldv1000_command_strobe_r(laserdisc_state *ld);
+static UINT8 ldv1000_status_r(laserdisc_state *ld);
+
+static TIMER_CALLBACK( vsync_off );
+static TIMER_CALLBACK( vbi_data_fetch );
+static TIMER_DEVICE_CALLBACK( multijump_timer );
+
+static void ctc_interrupt(device_t *device, int state);
+
+static WRITE8_HANDLER( decoder_display_port_w );
+static READ8_HANDLER( decoder_display_port_r );
+static READ8_HANDLER( controller_r );
+static WRITE8_HANDLER( controller_w );
+static WRITE8_DEVICE_HANDLER( ppi0_porta_w );
+static READ8_DEVICE_HANDLER( ppi0_portb_r );
+static READ8_DEVICE_HANDLER( ppi0_portc_r );
+static WRITE8_DEVICE_HANDLER( ppi0_portc_w );
+static READ8_DEVICE_HANDLER( ppi1_porta_r );
+static WRITE8_DEVICE_HANDLER( ppi1_portb_w );
+static WRITE8_DEVICE_HANDLER( ppi1_portc_w );
+
+
+
+/***************************************************************************
+ LD-V1000 ROM AND MACHINE INTERFACES
+***************************************************************************/
+
+static ADDRESS_MAP_START( ldv1000_map, AS_PROGRAM, 8 )
+ AM_RANGE(0x0000, 0x1fff) AM_MIRROR(0x6000) AM_ROM
+ AM_RANGE(0x8000, 0x87ff) AM_MIRROR(0x3800) AM_RAM
+ AM_RANGE(0xc000, 0xc003) AM_MIRROR(0x9ff0) AM_DEVREADWRITE("ldvppi0", ppi8255_r, ppi8255_w)
+ AM_RANGE(0xc004, 0xc007) AM_MIRROR(0x9ff0) AM_DEVREADWRITE("ldvppi1", ppi8255_r, ppi8255_w)
+ADDRESS_MAP_END
+
+
+static ADDRESS_MAP_START( ldv1000_portmap, AS_IO, 8 )
+ ADDRESS_MAP_GLOBAL_MASK(0xff)
+ AM_RANGE(0x00, 0x07) AM_MIRROR(0x38) AM_READWRITE(decoder_display_port_r, decoder_display_port_w)
+ AM_RANGE(0x40, 0x40) AM_MIRROR(0x3f) AM_READ(controller_r)
+ AM_RANGE(0x80, 0x80) AM_MIRROR(0x3f) AM_WRITE(controller_w)
+ AM_RANGE(0xc0, 0xc3) AM_MIRROR(0x3c) AM_DEVREADWRITE("ldvctc", z80ctc_r, z80ctc_w)
+ADDRESS_MAP_END
+
+
+static const ppi8255_interface ppi0intf =
+{
+ DEVCB_NULL, DEVCB_HANDLER(ppi0_portb_r), DEVCB_HANDLER(ppi0_portc_r),
+ DEVCB_HANDLER(ppi0_porta_w), DEVCB_NULL, DEVCB_HANDLER(ppi0_portc_w)
+};
+
+
+static const ppi8255_interface ppi1intf =
+{
+ DEVCB_HANDLER(ppi1_porta_r), DEVCB_NULL, DEVCB_NULL,
+ DEVCB_NULL, DEVCB_HANDLER(ppi1_portb_w), DEVCB_HANDLER(ppi1_portc_w)
+};
+
+
+static Z80CTC_INTERFACE( ctcintf )
+{
+ 0,
+ DEVCB_LINE(ctc_interrupt),
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL
+};
+
+
+static const z80_daisy_config daisy_chain[] =
+{
+ { "ldvctc" },
+ { NULL }
+};
+
+
+static MACHINE_CONFIG_FRAGMENT( ldv1000 )
+ MCFG_CPU_ADD("ldv1000", Z80, XTAL_5MHz/2)
+ MCFG_CPU_CONFIG(daisy_chain)
+ MCFG_CPU_PROGRAM_MAP(ldv1000_map)
+ MCFG_CPU_IO_MAP(ldv1000_portmap)
+
+ MCFG_Z80CTC_ADD("ldvctc", XTAL_5MHz/2 /* same as "ldv1000" */, ctcintf)
+ MCFG_PPI8255_ADD("ldvppi0", ppi0intf)
+ MCFG_PPI8255_ADD("ldvppi1", ppi1intf)
+ MCFG_TIMER_ADD("multitimer", multijump_timer)
+MACHINE_CONFIG_END
+
+
+ROM_START( ldv1000 )
+ ROM_REGION( 0x2000, "ldv1000", 0 )
+ ROM_LOAD( "z03_1001_vyw-053_v1-0.bin", 0x0000, 0x2000, CRC(31ec4687) SHA1(52f91c304a878ba02b2fa1cda1a9489d6dd5a34f) )
+ROM_END
+
+
+
+/***************************************************************************
+ INTERFACES
+***************************************************************************/
+
+const ldplayer_interface ldv1000_interface =
+{
+ LASERDISC_TYPE_PIONEER_LDV1000, /* type of the player */
+ sizeof(ldplayer_data), /* size of the state */
+ "Pioneer LD-V1000", /* name of the player */
+ "ldv1000", /* shortname of the player */
+ ROM_NAME(ldv1000), /* pointer to ROM region information */
+ MACHINE_CONFIG_NAME(ldv1000), /* pointer to machine configuration */
+ ldv1000_init, /* initialization callback */
+ ldv1000_vsync, /* vsync callback */
+ ldv1000_update, /* update callback */
+ NULL, /* overlay callback */
+ ldv1000_data_w, /* parallel data write */
+ { /* single line write: */
+ NULL, /* LASERDISC_LINE_ENTER */
+ NULL /* LASERDISC_LINE_CONTROL */
+ },
+ ldv1000_status_r, /* parallel data read */
+ { /* single line read: */
+ NULL, /* LASERDISC_LINE_READY */
+ ldv1000_status_strobe_r, /* LASERDISC_LINE_STATUS */
+ ldv1000_command_strobe_r, /* LASERDISC_LINE_COMMAND */
+ NULL, /* LASERDISC_LINE_DATA_AVAIL */
+ }
+};
+
+
+
+/***************************************************************************
+ PIONEER LD-V1000 IMPLEMENTATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ ldv1000_init - player-specific initialization
+-------------------------------------------------*/
+
+static void ldv1000_init(laserdisc_state *ld)
+{
+ astring tempstring;
+ ldplayer_data *player = ld->player;
+
+ /* reset our state */
+ memset(player, 0, sizeof(*player));
+
+ /* find our devices */
+ player->cpu = ld->device->subdevice("ldv1000");
+ player->ctc = ld->device->subdevice("ldvctc");
+ player->multitimer = downcast<timer_device *>(ld->device->subdevice("multitimer"));
+ player->multitimer->set_ptr(ld);
+}
+
+
+/*-------------------------------------------------
+ ldv1000_vsync - VSYNC callback, called at the
+ start of the blanking period
+-------------------------------------------------*/
+
+static void ldv1000_vsync(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime)
+{
+ slider_position sliderpos = ldcore_get_slider_position(ld);
+ ldplayer_data *player = ld->player;
+
+ /* generate interrupts if we hit the edges */
+ z80ctc_trg1_w(player->ctc, sliderpos == SLIDER_MINIMUM);
+ z80ctc_trg2_w(player->ctc, sliderpos == SLIDER_MAXIMUM);
+
+ /* signal VSYNC and set a timer to turn it off */
+ player->vsync = TRUE;
+ ld->device->machine().scheduler().timer_set(ld->screen->scan_period() * 4, FUNC(vsync_off), 0, ld);
+
+ /* also set a timer to fetch the VBI data when it is ready */
+ ld->device->machine().scheduler().timer_set(ld->screen->time_until_pos(19*2), FUNC(vbi_data_fetch), 0, ld);
+
+ /* boost interleave for the first 1ms to improve communications */
+ ld->device->machine().scheduler().boost_interleave(attotime::zero, attotime::from_msec(1));
+}
+
+
+/*-------------------------------------------------
+ ldv1000_update - update callback, called on
+ the first visible line of the frame
+-------------------------------------------------*/
+
+static INT32 ldv1000_update(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime)
+{
+ if (LOG_FRAMES_SEEN)
+ {
+ int frame = frame_from_metadata(vbi);
+ if (frame != FRAME_NOT_PRESENT) printf("== %d\n", frame);
+ }
+ return fieldnum;
+}
+
+
+/*-------------------------------------------------
+ ldv1000_data_w - handle a parallel data write
+ to the LD-V1000
+-------------------------------------------------*/
+
+static void ldv1000_data_w(laserdisc_state *ld, UINT8 prev, UINT8 data)
+{
+ ld->player->command = data;
+ if (LOG_COMMANDS)
+ printf("-> COMMAND = %02X (%s)\n", data, (ld->player->portc1 & 0x10) ? "valid" : "invalid");
+}
+
+
+/*-------------------------------------------------
+ ldv1000_status_strobe_r - return state of the
+ status strobe
+-------------------------------------------------*/
+
+static UINT8 ldv1000_status_strobe_r(laserdisc_state *ld)
+{
+ return (ld->player->portc1 & 0x20) ? ASSERT_LINE : CLEAR_LINE;
+}
+
+
+/*-------------------------------------------------
+ ldv1000_command_strobe_r - return state of the
+ command strobe
+-------------------------------------------------*/
+
+static UINT8 ldv1000_command_strobe_r(laserdisc_state *ld)
+{
+ return (ld->player->portc1 & 0x10) ? ASSERT_LINE : CLEAR_LINE;
+}
+
+
+/*-------------------------------------------------
+ ldv1000_status_r - handle a parallel data read
+ from the LD-V1000
+-------------------------------------------------*/
+
+static UINT8 ldv1000_status_r(laserdisc_state *ld)
+{
+ return ld->player->status;
+}
+
+
+/*-------------------------------------------------
+ vsync_off - timer callback to clear the VSYNC
+ flag
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( vsync_off )
+{
+ laserdisc_state *ld = (laserdisc_state *)ptr;
+ ld->player->vsync = FALSE;
+}
+
+
+/*-------------------------------------------------
+ vbi_data_fetch - timer callback to update the
+ VBI data in the PIA as soon as it is ready;
+ this must happy early in the frame because
+ the player logic relies on fetching it here
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( vbi_data_fetch )
+{
+ laserdisc_state *ld = (laserdisc_state *)ptr;
+ ldplayer_data *player = ld->player;
+ UINT8 focus_on = !(player->portb1 & 0x01);
+ UINT8 laser_on = (player->portb1 & 0x40);
+ UINT32 lines[3];
+
+ /* appears to return data in reverse order */
+ lines[0] = laserdisc_get_field_code(ld->device, LASERDISC_CODE_LINE1718, FALSE);
+ lines[1] = laserdisc_get_field_code(ld->device, LASERDISC_CODE_LINE17, FALSE);
+ lines[2] = laserdisc_get_field_code(ld->device, LASERDISC_CODE_LINE16, FALSE);
+
+ /* fill in the details */
+ memset(player->vbi, 0, sizeof(player->vbi));
+ if (focus_on && laser_on)
+ {
+ int line;
+
+ /* loop over lines */
+ for (line = 0; line < 3; line++)
+ {
+ UINT8 *dest = &player->vbi[line * 7];
+ UINT32 data = lines[line];
+
+ /* the logic only processes leadin/leadout/frame number codes */
+ if (data == VBI_CODE_LEADIN || data == VBI_CODE_LEADOUT || (data & VBI_MASK_CAV_PICTURE) == VBI_CODE_CAV_PICTURE)
+ {
+ *dest++ = 0x09 | (((data & VBI_MASK_CAV_PICTURE) == VBI_CODE_CAV_PICTURE) ? 0x02 : 0x00);
+ *dest++ = 0x08;
+ *dest++ = (data >> 16) & 0x0f;
+ *dest++ = (data >> 12) & 0x0f;
+ *dest++ = (data >> 8) & 0x0f;
+ *dest++ = (data >> 4) & 0x0f;
+ *dest++ = (data >> 0) & 0x0f;
+ }
+ }
+ }
+
+ /* signal that data is ready and reset the readback index */
+ player->vbiready = TRUE;
+ player->vbiindex = 0;
+}
+
+
+/*-------------------------------------------------
+ multijump_timer - called once for each track
+ in a multijump sequence; we decrement the
+ down counter and autostop when we hit 0
+-------------------------------------------------*/
+
+static TIMER_DEVICE_CALLBACK( multijump_timer )
+{
+ laserdisc_state *ld = (laserdisc_state *)ptr;
+ ldplayer_data *player = ld->player;
+ int direction;
+
+ /* bit 5 of port B on PPI 1 selects the direction of slider movement */
+ direction = (player->portb1 & 0x20) ? 1 : -1;
+ ldcore_advance_slider(ld, direction);
+
+ /* update down counter and reschedule */
+ if (--player->counter != 0)
+ timer.adjust(MULTIJUMP_TRACK_TIME);
+}
+
+
+/*-------------------------------------------------
+ ctc_interrupt - called when the CTC triggers
+ an interrupt in the daisy chain
+-------------------------------------------------*/
+
+static WRITE_LINE_DEVICE_HANDLER( ctc_interrupt )
+{
+ laserdisc_state *ld = ldcore_get_safe_token(device->owner());
+ if (ld->player->cpu != NULL)
+ device_set_input_line(ld->player->cpu, 0, state ? ASSERT_LINE : CLEAR_LINE);
+}
+
+
+/*-------------------------------------------------
+ decoder_display_port_w - handle writes to the
+ decoder/display chips
+-------------------------------------------------*/
+
+static WRITE8_HANDLER( decoder_display_port_w )
+{
+ /*
+ TX/RX = /A0 (A0=0 -> TX, A0=1 -> RX)
+
+ Display is 6-bit
+ Decoder is 4-bit
+ */
+ laserdisc_state *ld = ldcore_get_safe_token(space->device().owner());
+ ldplayer_data *player = ld->player;
+
+ /* writes to offset 0 select the target for reads/writes of actual data */
+ if (offset == 0)
+ {
+ player->portselect = data;
+ player->dispindex = 0;
+ }
+
+ /* writes to offset 2 constitute actual writes targeted toward the display and decoder chips */
+ else if (offset == 2)
+ {
+ /* selections 0 and 1 represent the two display lines; only 6 bits are transferred */
+ if (player->portselect < 2)
+ player->display[player->portselect][player->dispindex++ % 20] = data & 0x3f;
+ }
+}
+
+
+/*-------------------------------------------------
+ decoder_display_port_r - handle reads from the
+ decoder/display chips
+-------------------------------------------------*/
+
+static READ8_HANDLER( decoder_display_port_r )
+{
+ laserdisc_state *ld = ldcore_get_safe_token(space->device().owner());
+ ldplayer_data *player = ld->player;
+ UINT8 result = 0;
+
+ /* reads from offset 3 constitute actual reads from the display and decoder chips */
+ if (offset == 3)
+ {
+ /* selection 4 represents the VBI data reading */
+ if (player->portselect == 4)
+ {
+ player->vbiready = FALSE;
+ result = player->vbi[player->vbiindex++ % ARRAY_LENGTH(player->vbi)];
+ }
+ }
+ return result;
+}
+
+
+/*-------------------------------------------------
+ controller_r - handle read of the data from
+ the controlling system
+-------------------------------------------------*/
+
+static READ8_HANDLER( controller_r )
+{
+ laserdisc_state *ld = ldcore_get_safe_token(space->device().owner());
+
+ /* note that this is a cheesy implementation; the real thing relies on exquisite timing */
+ UINT8 result = ld->player->command ^ 0xff;
+ ld->player->command = 0xff;
+ return result;
+}
+
+
+/*-------------------------------------------------
+ controller_w - handle status latch writes
+-------------------------------------------------*/
+
+static WRITE8_HANDLER( controller_w )
+{
+ laserdisc_state *ld = ldcore_get_safe_token(space->device().owner());
+ if (LOG_STATUS_CHANGES && data != ld->player->status)
+ printf("%04X:CONTROLLER.W=%02X\n", cpu_get_pc(&space->device()), data);
+ ld->player->status = data;
+}
+
+
+/*-------------------------------------------------
+ ppi0_porta_w - handle writes to port A of
+ PPI #0
+-------------------------------------------------*/
+
+static WRITE8_DEVICE_HANDLER( ppi0_porta_w )
+{
+ laserdisc_state *ld = ldcore_get_safe_token(device->owner());
+ ld->player->counter_start = data;
+ if (LOG_PORT_IO)
+ printf("%s:PORTA.0=%02X\n", device->machine().describe_context(), data);
+}
+
+
+/*-------------------------------------------------
+ ppi0_portb_r - handle reads from port B of
+ PPI #0
+-------------------------------------------------*/
+
+static READ8_DEVICE_HANDLER( ppi0_portb_r )
+{
+ laserdisc_state *ld = ldcore_get_safe_token(device->owner());
+ return ld->player->counter;
+}
+
+
+/*-------------------------------------------------
+ ppi0_portc_r - handle reads from port C of
+ PPI #0
+-------------------------------------------------*/
+
+static READ8_DEVICE_HANDLER( ppi0_portc_r )
+{
+ /*
+ $10 = /VSYNC
+ $20 = IRQ from decoder chip
+ $40 = TRKG LOOP (N24-1)
+ $80 = DUMP (N20-1) -- code reads the state and waits for it to change
+ */
+ laserdisc_state *ld = ldcore_get_safe_token(device->owner());
+ ldplayer_data *player = ld->player;
+ UINT8 result = 0x00;
+
+ if (!player->vsync)
+ result |= 0x10;
+ if (!player->vbiready)
+ result |= 0x20;
+
+ return result;
+}
+
+
+/*-------------------------------------------------
+ ppi0_portc_w - handle writes to port C of
+ PPI #0
+-------------------------------------------------*/
+
+static WRITE8_DEVICE_HANDLER( ppi0_portc_w )
+{
+ /*
+ $01 = preload on up/down counters
+ $02 = /MULTI JUMP TRIG
+ $04 = SCAN MODE
+ $08 = n/c
+ */
+ laserdisc_state *ld = ldcore_get_safe_token(device->owner());
+ ldplayer_data *player = ld->player;
+ UINT8 prev = player->portc0;
+
+ /* set the new value */
+ player->portc0 = data;
+ if (LOG_PORT_IO && ((data ^ prev) & 0x0f) != 0)
+ {
+ printf("%s:PORTC.0=%02X", device->machine().describe_context(), data);
+ if (data & 0x01) printf(" PRELOAD");
+ if (!(data & 0x02)) printf(" /MULTIJUMP");
+ if (data & 0x04) printf(" SCANMODE");
+ printf("\n");
+ }
+
+ /* on the rising edge of bit 0, clock the down counter load */
+ if ((data & 0x01) && !(prev & 0x01))
+ player->counter = player->counter_start;
+
+ /* on the falling edge of bit 1, start the multi-jump timer */
+ if (!(data & 0x02) && (prev & 0x02))
+ player->multitimer->adjust(MULTIJUMP_TRACK_TIME);
+}
+
+
+/*-------------------------------------------------
+ ppi1_porta_r - handle reads from port A of
+ PPI #1
+-------------------------------------------------*/
+
+static READ8_DEVICE_HANDLER( ppi1_porta_r )
+{
+ /*
+ $01 = /FOCS LOCK
+ $02 = /SPDL LOCK
+ $04 = INSIDE
+ $08 = OUTSIDE
+ $10 = MOTOR STOP
+ $20 = +5V/test point
+ $40 = /INT LOCK
+ $80 = 8 INCH CHK
+ */
+ laserdisc_state *ld = ldcore_get_safe_token(device->owner());
+ ldplayer_data *player = ld->player;
+ slider_position sliderpos = ldcore_get_slider_position(ld);
+ UINT8 focus_on = !(player->portb1 & 0x01);
+ UINT8 spdl_on = !(player->portb1 & 0x02);
+ UINT8 result = 0x00;
+
+ /* bit 0: /FOCUS LOCK */
+ if (!focus_on)
+ result |= 0x01;
+
+ /* bit 1: /SPDL LOCK */
+ if (!spdl_on)
+ result |= 0x02;
+
+ /* bit 2: INSIDE signal */
+ if (sliderpos == SLIDER_MINIMUM)
+ result |= 0x04;
+
+ /* bit 3: OUTSIDE signal */
+ if (sliderpos == SLIDER_MAXIMUM)
+ result |= 0x08;
+
+ /* bit 4: MOTOR STOP */
+
+ /* bit 5: +5V/test point */
+ result |= 0x20;
+
+ /* bit 6: /INT LOCK */
+
+ /* bit 7: 8 INCH CHK */
+
+ return result;
+}
+
+
+/*-------------------------------------------------
+ ppi1_portb_w - handle writes to port B of
+ PPI #1
+-------------------------------------------------*/
+
+static WRITE8_DEVICE_HANDLER( ppi1_portb_w )
+{
+ /*
+ $01 = /FOCS ON
+ $02 = /SPDL RUN
+ $04 = /JUMP TRIG
+ $08 = /SCAN A
+ $10 = SCAN B
+ $20 = SCAN C
+ $40 = /LASER ON
+ $80 = /SYNC ST0
+ */
+ laserdisc_state *ld = ldcore_get_safe_token(device->owner());
+ ldplayer_data *player = ld->player;
+ UINT8 prev = player->portb1;
+ int direction;
+
+ /* set the new value */
+ player->portb1 = data;
+ if (LOG_PORT_IO && ((data ^ prev) & 0xff) != 0)
+ {
+ printf("%s:PORTB.1=%02X:", device->machine().describe_context(), data);
+ if (!(data & 0x01)) printf(" FOCSON");
+ if (!(data & 0x02)) printf(" SPDLRUN");
+ if (!(data & 0x04)) printf(" JUMPTRIG");
+ if (!(data & 0x08)) printf(" SCANA (%c %c)", (data & 0x10) ? 'L' : 'H', (data & 0x20) ? 'F' : 'R');
+ if ( (data & 0x40)) printf(" LASERON");
+ if (!(data & 0x80)) printf(" SYNCST0");
+ printf("\n");
+ }
+
+ /* bit 5 selects the direction of slider movement for JUMP TRG and scanning */
+ direction = (data & 0x20) ? 1 : -1;
+
+ /* on the falling edge of bit 2, jump one track in either direction */
+ if (!(data & 0x04) && (prev & 0x04))
+ ldcore_advance_slider(ld, direction);
+
+ /* bit 3 low enables scanning */
+ if (!(data & 0x08))
+ {
+ /* bit 4 selects the speed */
+ int delta = (data & 0x10) ? SCAN_SPEED : SEEK_FAST_SPEED;
+ ldcore_set_slider_speed(ld, delta * direction);
+ }
+
+ /* bit 3 high stops scanning */
+ else
+ ldcore_set_slider_speed(ld, 0);
+}
+
+
+/*-------------------------------------------------
+ ppi1_portc_w - handle writes to port C of
+ PPI #1
+-------------------------------------------------*/
+
+static WRITE8_DEVICE_HANDLER( ppi1_portc_w )
+{
+ /*
+ $01 = AUD 1
+ $02 = AUD 2
+ $04 = AUDIO ENABLE
+ $08 = /VIDEO SQ
+ $10 = COMMAND
+ $20 = STATUS
+ $40 = SIZE 8/12
+ $80 = /LED CAV
+ */
+ laserdisc_state *ld = ldcore_get_safe_token(device->owner());
+ ldplayer_data *player = ld->player;
+ UINT8 prev = player->portc1;
+
+ /* set the new value */
+ player->portc1 = data;
+ if (LOG_PORT_IO && ((data ^ prev) & 0xcf) != 0)
+ {
+ printf("%s:PORTC.1=%02X", device->machine().describe_context(), data);
+ if (data & 0x01) printf(" AUD1");
+ if (data & 0x02) printf(" AUD2");
+ if (data & 0x04) printf(" AUDEN");
+ if (!(data & 0x08)) printf(" VIDEOSQ");
+ if (data & 0x10) printf(" COMMAND");
+ if (data & 0x20) printf(" STATUS");
+ if (data & 0x40) printf(" SIZE8");
+ if (!(data & 0x80)) printf(" CAV");
+ printf("\n");
+ }
+
+ /* video squelch is controlled by bit 3 */
+ ldcore_set_video_squelch(ld, (data & 0x08) == 0);
+
+ /* audio squelch is controlled by bits 0-2 */
+ ldcore_set_audio_squelch(ld, !(data & 0x04) || !(data & 0x01), !(data & 0x04) || !(data & 0x02));
+}
diff --git a/trunk/src/emu/machine/ldvp931.c b/trunk/src/emu/machine/ldvp931.c
new file mode 100644
index 00000000000..f9738c9fcc3
--- /dev/null
+++ b/trunk/src/emu/machine/ldvp931.c
@@ -0,0 +1,781 @@
+/*************************************************************************
+
+ ldvp931.c
+
+ Philips 22VP931 laserdisc emulation.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**************************************************************************
+
+ Still to do:
+
+ * determine actual slow/fast speeds
+ *
+
+*************************************************************************/
+
+#include "emu.h"
+#include "ldcore.h"
+#include "cpu/mcs48/mcs48.h"
+
+
+
+/***************************************************************************
+ DEBUGGING
+***************************************************************************/
+
+#define LOG_COMMANDS 0
+#define LOG_PORTS 0
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* scanning speeds */
+#define SCAN_SPEED (2000 / 30) /* 2000 frames/second */
+#define SCAN_FAST_SPEED (4000 / 30) /* 4000 frames/second */
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/* player-specific data */
+struct _ldplayer_data
+{
+ /* low-level emulation data */
+ device_t *cpu; /* CPU index of the 8049 */
+ timer_device * tracktimer; /* timer device */
+ vp931_data_ready_func data_ready_cb; /* data ready callback */
+
+ /* I/O port states */
+ UINT8 out0; /* output 0 state */
+ UINT8 out1; /* output 1 state */
+ UINT8 port1; /* port 1 state */
+
+ /* DATIC circuit implementation */
+ UINT8 daticval; /* latched DATIC value */
+ UINT8 daticerp; /* /ERP value from DATIC */
+ UINT8 datastrobe; /* DATA STROBE line from DATIC */
+
+ /* communication status */
+ UINT8 fromcontroller; /* command byte from the controller */
+ UINT8 fromcontroller_pending; /* TRUE if data is pending */
+ UINT8 tocontroller; /* command byte to the controller */
+ UINT8 tocontroller_pending; /* TRUE if data is pending */
+
+ /* tracking */
+ INT8 trackdir; /* direction of tracking */
+ UINT8 trackstate; /* state of tracking */
+
+ /* debugging */
+ UINT8 cmdbuf[3]; /* 3 bytes worth of commands */
+ UINT8 cmdcount; /* number of command bytes seen */
+ INT16 advanced; /* number of frames advanced */
+};
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void vp931_init(laserdisc_state *ld);
+static void vp931_vsync(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime);
+static INT32 vp931_update(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime);
+static void vp931_data_w(laserdisc_state *ld, UINT8 prev, UINT8 data);
+static UINT8 vp931_data_r(laserdisc_state *ld);
+static UINT8 vp931_ready(laserdisc_state *ld);
+static UINT8 vp931_data_ready(laserdisc_state *ld);
+
+static TIMER_CALLBACK( vbi_data_fetch );
+static TIMER_CALLBACK( deferred_data_w );
+static TIMER_CALLBACK( irq_off );
+static TIMER_CALLBACK( datastrobe_off );
+static TIMER_CALLBACK( erp_off );
+static TIMER_DEVICE_CALLBACK( track_timer );
+
+static WRITE8_HANDLER( output0_w );
+static WRITE8_HANDLER( output1_w );
+static WRITE8_HANDLER( lcd_w );
+static READ8_HANDLER( unknown_r );
+static READ8_HANDLER( keypad_r );
+static READ8_HANDLER( datic_r );
+static READ8_HANDLER( from_controller_r );
+static WRITE8_HANDLER( to_controller_w );
+static READ8_HANDLER( port1_r );
+static WRITE8_HANDLER( port1_w );
+static READ8_HANDLER( port2_r );
+static WRITE8_HANDLER( port2_w );
+static READ8_HANDLER( t0_r );
+static READ8_HANDLER( t1_r );
+
+
+
+/***************************************************************************
+ 22VP931 ROM AND MACHINE INTERFACES
+***************************************************************************/
+
+static ADDRESS_MAP_START( vp931_portmap, AS_IO, 8 )
+ AM_RANGE(0x00, 0x00) AM_MIRROR(0xcf) AM_READWRITE(keypad_r, output0_w)
+ AM_RANGE(0x10, 0x10) AM_MIRROR(0xcf) AM_READWRITE(unknown_r, output1_w)
+ AM_RANGE(0x20, 0x20) AM_MIRROR(0xcf) AM_READWRITE(datic_r, lcd_w)
+ AM_RANGE(0x30, 0x30) AM_MIRROR(0xcf) AM_READWRITE(from_controller_r, to_controller_w)
+ AM_RANGE(MCS48_PORT_P1, MCS48_PORT_P1) AM_READWRITE(port1_r, port1_w)
+ AM_RANGE(MCS48_PORT_P2, MCS48_PORT_P2) AM_READWRITE(port2_r, port2_w)
+ AM_RANGE(MCS48_PORT_T0, MCS48_PORT_T0) AM_READ(t0_r)
+ AM_RANGE(MCS48_PORT_T1, MCS48_PORT_T1) AM_READ(t1_r)
+ADDRESS_MAP_END
+
+
+static MACHINE_CONFIG_FRAGMENT( vp931 )
+ MCFG_CPU_ADD("vp931", I8049, XTAL_11MHz)
+ MCFG_CPU_IO_MAP(vp931_portmap)
+ MCFG_TIMER_ADD("tracktimer", track_timer)
+MACHINE_CONFIG_END
+
+
+ROM_START( vp931 )
+ ROM_REGION( 0x800, "vp931", 0 )
+ ROM_LOAD( "at-6-1_a.bin", 0x000, 0x800, CRC(e11b3c8d) SHA1(ea2d7f6a044ed085ce5e09d8b1b1a21c37f0e9b8) )
+ROM_END
+
+
+
+/***************************************************************************
+ 22VP931 PLAYER INTERFACE
+***************************************************************************/
+
+const ldplayer_interface vp931_interface =
+{
+ LASERDISC_TYPE_PHILLIPS_22VP931, /* type of the player */
+ sizeof(ldplayer_data), /* size of the state */
+ "Phillips 22VP931", /* name of the player */
+ "22vp931", /* shortname of the player */
+ ROM_NAME(vp931), /* pointer to ROM region information */
+ MACHINE_CONFIG_NAME(vp931), /* pointer to machine configuration */
+ vp931_init, /* initialization callback */
+ vp931_vsync, /* vsync callback */
+ vp931_update, /* update callback */
+ NULL, /* overlay callback */
+ vp931_data_w, /* parallel data write */
+ { /* single line write: */
+ NULL, /* LASERDISC_LINE_ENTER */
+ NULL /* LASERDISC_LINE_CONTROL */
+ },
+ vp931_data_r, /* parallel data read */
+ { /* single line read: */
+ vp931_ready, /* LASERDISC_LINE_READY */
+ NULL, /* LASERDISC_LINE_STATUS */
+ NULL, /* LASERDISC_LINE_COMMAND */
+ vp931_data_ready, /* LASERDISC_LINE_DATA_AVAIL */
+ }
+};
+
+
+
+/***************************************************************************
+ PUBLIC FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ vp931_set_data_ready_callback - set the data
+ ready callback
+-------------------------------------------------*/
+
+void vp931_set_data_ready_callback(device_t *device, vp931_data_ready_func callback)
+{
+ laserdisc_state *ld = ldcore_get_safe_token(device);
+ ld->player->data_ready_cb = callback;
+}
+
+
+
+/***************************************************************************
+ PHILLIPS 22VP931 IMPLEMENTATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ vp931_init - player-specific initialization
+-------------------------------------------------*/
+
+static void vp931_init(laserdisc_state *ld)
+{
+ astring tempstring;
+ ldplayer_data *player = ld->player;
+ vp931_data_ready_func cbsave;
+
+ /* reset our state */
+ cbsave = player->data_ready_cb;
+ memset(player, 0, sizeof(*player));
+ player->data_ready_cb = cbsave;
+
+ /* find our devices */
+ player->cpu = ld->device->subdevice("vp931");
+ player->tracktimer = downcast<timer_device *>(ld->device->subdevice("tracktimer"));
+ player->tracktimer->set_ptr(ld);
+}
+
+
+/*-------------------------------------------------
+ vp931_vsync - VSYNC callback, called at the
+ start of the blanking period
+-------------------------------------------------*/
+
+static void vp931_vsync(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime)
+{
+ /* reset our command counter (debugging only) */
+ ld->player->cmdcount = 0;
+
+ /* set the ERP signal to 1 to indicate start of frame, and set a timer to turn it off */
+ ld->player->daticerp = 1;
+ ld->device->machine().scheduler().timer_set(ld->screen->time_until_pos(15*2), FUNC(erp_off), 0, ld);
+}
+
+
+/*-------------------------------------------------
+ vp931_update - update callback, called on
+ the first visible line of the frame
+-------------------------------------------------*/
+
+static INT32 vp931_update(laserdisc_state *ld, const vbi_metadata *vbi, int fieldnum, attotime curtime)
+{
+ /* set the first VBI timer to go at the start of line 16 */
+ ld->device->machine().scheduler().timer_set(ld->screen->time_until_pos(16*2), FUNC(vbi_data_fetch), LASERDISC_CODE_LINE16 << 2, ld);
+
+ /* play forward by default */
+ return fieldnum;
+}
+
+
+/*-------------------------------------------------
+ vp931_data_w - handle a parallel data write
+ to the 22VP931
+-------------------------------------------------*/
+
+static void vp931_data_w(laserdisc_state *ld, UINT8 prev, UINT8 data)
+{
+ /* set a timer to synchronize execution before sending the data */
+ ld->device->machine().scheduler().synchronize(FUNC(deferred_data_w), data, ld);
+}
+
+
+/*-------------------------------------------------
+ vp931_data_r - handle a parallel data read
+ from the 22VP931
+-------------------------------------------------*/
+
+static UINT8 vp931_data_r(laserdisc_state *ld)
+{
+ ldplayer_data *player = ld->player;
+
+ /* if data is pending, clear the pending flag and notify any callbacks */
+ if (player->tocontroller_pending)
+ {
+ player->tocontroller_pending = FALSE;
+ if (player->data_ready_cb != NULL)
+ (*player->data_ready_cb)(ld->device, FALSE);
+ }
+
+ /* also boost interleave for 4 scanlines to ensure proper communications */
+ ld->device->machine().scheduler().boost_interleave(attotime::zero, ld->screen->scan_period() * 4);
+ return player->tocontroller;
+}
+
+
+/*-------------------------------------------------
+ vp931_ready - return the status of "ready"
+ to the caller (ready to accept another
+ command)
+-------------------------------------------------*/
+
+static UINT8 vp931_ready(laserdisc_state *ld)
+{
+ /* if data is pending, we are not ready */
+ ldplayer_data *player = ld->player;
+ return player->fromcontroller_pending ? CLEAR_LINE : ASSERT_LINE;
+}
+
+
+/*-------------------------------------------------
+ vp931_data_ready - return the status of
+ "data available" to the caller
+-------------------------------------------------*/
+
+static UINT8 vp931_data_ready(laserdisc_state *ld)
+{
+ ldplayer_data *player = ld->player;
+ return player->tocontroller_pending ? ASSERT_LINE : CLEAR_LINE;
+}
+
+
+/*-------------------------------------------------
+ vbi_data_fetch - called 4 times per scanline
+ on lines 16, 17, and 18 to feed the VBI data
+ through one byte at a time
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( vbi_data_fetch )
+{
+ laserdisc_state *ld = (laserdisc_state *)ptr;
+ ldplayer_data *player = ld->player;
+ int which = param & 3;
+ int line = param >> 2;
+ UINT32 code = 0;
+
+ /* fetch the code and compute the DATIC latched value */
+ if (line >= LASERDISC_CODE_LINE16 && line <= LASERDISC_CODE_LINE18)
+ code = laserdisc_get_field_code(ld->device, line, FALSE);
+
+ /* at the start of each line, signal an interrupt and use a timer to turn it off */
+ if (which == 0)
+ {
+ device_set_input_line(player->cpu, MCS48_INPUT_IRQ, ASSERT_LINE);
+ machine.scheduler().timer_set(attotime::from_nsec(5580), FUNC(irq_off), 0, ld);
+ }
+
+ /* clock the data strobe on each subsequent callback */
+ else if (code != 0)
+ {
+ player->daticval = code >> (8 * (3 - which));
+ player->datastrobe = 1;
+ machine.scheduler().timer_set(attotime::from_nsec(5000), FUNC(datastrobe_off), 0, ld);
+ }
+
+ /* determine the next bit to fetch and reprime ourself */
+ if (++which == 4)
+ {
+ which = 0;
+ line++;
+ }
+ if (line <= LASERDISC_CODE_LINE18 + 1)
+ machine.scheduler().timer_set(ld->screen->time_until_pos(line*2, which * 2 * ld->screen->width() / 4), FUNC(vbi_data_fetch), (line << 2), ld);
+}
+
+
+/*-------------------------------------------------
+ deferred_data_w - handle a write from the
+ external controller
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( deferred_data_w )
+{
+ laserdisc_state *ld = (laserdisc_state *)ptr;
+ ldplayer_data *player = ld->player;
+
+ /* set the value and mark it pending */
+ if (LOG_COMMANDS && player->fromcontroller_pending)
+ printf("Dropped previous command byte\n");
+ player->fromcontroller = param;
+ player->fromcontroller_pending = TRUE;
+
+ /* track the commands for debugging purposes */
+ if (player->cmdcount < ARRAY_LENGTH(player->cmdbuf))
+ {
+ player->cmdbuf[player->cmdcount++ % 3] = param;
+ if (LOG_COMMANDS && player->cmdcount % 3 == 0)
+ printf("Cmd: %02X %02X %02X\n", player->cmdbuf[0], player->cmdbuf[1], player->cmdbuf[2]);
+ }
+}
+
+
+/*-------------------------------------------------
+ irq_off - turn off the 8048 IRQ signal
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( irq_off )
+{
+ laserdisc_state *ld = (laserdisc_state *)ptr;
+ device_set_input_line(ld->player->cpu, MCS48_INPUT_IRQ, CLEAR_LINE);
+}
+
+
+/*-------------------------------------------------
+ datastrobe_off - turn off the DATIC data
+ strobe signal
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( datastrobe_off )
+{
+ laserdisc_state *ld = (laserdisc_state *)ptr;
+ ld->player->datastrobe = 0;
+}
+
+
+/*-------------------------------------------------
+ erp_off - turn off the DATIC ERP signal
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( erp_off )
+{
+ laserdisc_state *ld = (laserdisc_state *)ptr;
+ ld->player->daticerp = 0;
+}
+
+
+/*-------------------------------------------------
+ track_timer - advance by one half-track
+-------------------------------------------------*/
+
+static TIMER_DEVICE_CALLBACK( track_timer )
+{
+ laserdisc_state *ld = (laserdisc_state *)ptr;
+ ldplayer_data *player = ld->player;
+
+ /* advance by the count and toggle the state */
+ player->trackstate ^= 1;
+ if ((player->trackdir < 0 && !player->trackstate) || (player->trackdir > 0 && player->trackstate))
+ {
+ ldcore_advance_slider(ld, player->trackdir);
+ player->advanced += player->trackdir;
+ }
+}
+
+
+/*-------------------------------------------------
+ output0_w - controls audio/video squelch
+ and other bits
+-------------------------------------------------*/
+
+static WRITE8_HANDLER( output0_w )
+{
+ laserdisc_state *ld = ldcore_get_safe_token(space->device().owner());
+ ldplayer_data *player = ld->player;
+
+ /*
+ $80 = n/c
+ $40 = LED (?) -> C335
+ $20 = LED (?)
+ $10 = LED (?) -> CX
+ $08 = EJECT
+ $04 = inverted -> AUDIO MUTE II
+ $02 = inverted -> AUDIO MUTE I
+ $01 = inverted -> VIDEO MUTE
+ */
+
+ if (LOG_PORTS && (player->out0 ^ data) & 0xff)
+ {
+ printf("%03X:out0:", cpu_get_pc(&space->device()));
+ if ( (data & 0x80)) printf(" ???");
+ if ( (data & 0x40)) printf(" LED1");
+ if ( (data & 0x20)) printf(" LED2");
+ if ( (data & 0x10)) printf(" LED3");
+ if ( (data & 0x08)) printf(" EJECT");
+ if (!(data & 0x04)) printf(" AUDMUTE2");
+ if (!(data & 0x02)) printf(" AUDMUTE1");
+ if (!(data & 0x01)) printf(" VIDMUTE");
+ printf("\n");
+ player->out0 = data;
+ }
+
+ /* update a/v squelch */
+ ldcore_set_audio_squelch(ld, !(data & 0x02), !(data & 0x04));
+ ldcore_set_video_squelch(ld, !(data & 0x01));
+}
+
+
+/*-------------------------------------------------
+ output1_w - controls scanning behaviors
+-------------------------------------------------*/
+
+static WRITE8_HANDLER( output1_w )
+{
+ laserdisc_state *ld = ldcore_get_safe_token(space->device().owner());
+ ldplayer_data *player = ld->player;
+ INT32 speed = 0;
+
+ /*
+ $80 = n/c
+ $40 = n/c
+ $20 = n/c
+ $10 = n/c
+ $08 = inverted -> SMS
+ $04 = inverted -> SSS
+ $02 = inverted -> SCAN CMD
+ $01 = OSM
+ */
+
+ if (LOG_PORTS && (player->out1 ^ data) & 0x08)
+ {
+ mame_printf_debug("%03X:out1:", cpu_get_pc(&space->device()));
+ if (!(data & 0x08)) mame_printf_debug(" SMS");
+ mame_printf_debug("\n");
+ player->out1 = data;
+ }
+
+ /* speed is 0 unless SCAN CMD is clear */
+ speed = 0;
+ if (!(data & 0x02))
+ {
+ /* fast/slow is based on bit 2 */
+ speed = (data & 0x04) ? SCAN_FAST_SPEED : SCAN_SPEED;
+
+ /* direction is based on bit 0 */
+ if (data & 0x01)
+ speed = -speed;
+ }
+
+ /* update the speed */
+ ldcore_set_slider_speed(ld, speed);
+}
+
+
+/*-------------------------------------------------
+ lcd_w - vestigial LCD frame display
+-------------------------------------------------*/
+
+static WRITE8_HANDLER( lcd_w )
+{
+ /*
+ Frame number is written as 5 digits here; however, it is not actually
+ connected
+ */
+}
+
+
+/*-------------------------------------------------
+ unknown_r - unknown input port
+-------------------------------------------------*/
+
+static READ8_HANDLER( unknown_r )
+{
+ /* only bit $80 is checked and its effects are minor */
+ return 0x00;
+}
+
+
+/*-------------------------------------------------
+ keypad_r - vestigial keypad/button controls
+-------------------------------------------------*/
+
+static READ8_HANDLER( keypad_r )
+{
+ /*
+ From the code, this is apparently a vestigial keypad with basic controls:
+ $01 = play
+ $02 = still
+ $04 = jump 25 frames backward
+ $08 = jump 25 frames forward
+ $10 = search for frame 50(?)
+ $20 = search for frame 350(?)
+ $40 = reset
+ $80 = play reverse
+ */
+ return 0x00;
+}
+
+
+/*-------------------------------------------------
+ datic_r - read the latched value from the
+ DATIC circuit
+-------------------------------------------------*/
+
+static READ8_HANDLER( datic_r )
+{
+ laserdisc_state *ld = ldcore_get_safe_token(space->device().owner());
+ return ld->player->daticval;
+}
+
+
+/*-------------------------------------------------
+ from_controller_r - read the value the
+ external controller wrote
+-------------------------------------------------*/
+
+static READ8_HANDLER( from_controller_r )
+{
+ laserdisc_state *ld = ldcore_get_safe_token(space->device().owner());
+ ldplayer_data *player = ld->player;
+
+ /* clear the pending flag and return the data */
+ player->fromcontroller_pending = FALSE;
+ return player->fromcontroller;
+}
+
+
+/*-------------------------------------------------
+ to_controller_w - write a value back to the
+ external controller
+-------------------------------------------------*/
+
+static WRITE8_HANDLER( to_controller_w )
+{
+ laserdisc_state *ld = ldcore_get_safe_token(space->device().owner());
+ ldplayer_data *player = ld->player;
+
+ /* set the pending flag and stash the data */
+ player->tocontroller_pending = TRUE;
+ player->tocontroller = data;
+
+ /* signal to the callback if provided */
+ if (player->data_ready_cb != NULL)
+ (*player->data_ready_cb)(ld->device, TRUE);
+
+ /* also boost interleave for 4 scanlines to ensure proper communications */
+ ld->device->machine().scheduler().boost_interleave(attotime::zero, ld->screen->scan_period() * 4);
+}
+
+
+/*-------------------------------------------------
+ port1_r - read the 8048 I/O port 1
+-------------------------------------------------*/
+
+static READ8_HANDLER( port1_r )
+{
+ laserdisc_state *ld = ldcore_get_safe_token(space->device().owner());
+ ldplayer_data *player = ld->player;
+ UINT8 result = 0x00;
+
+ /*
+ $80 = P17 = (in) unsure
+ $40 = P16 = (in) /ERP from datic circuit
+ $20 = P15 = (in) D105
+ */
+
+ if (!player->daticerp)
+ result |= 0x40;
+
+ return result;
+}
+
+
+/*-------------------------------------------------
+ port1_w - write the 8048 I/O port 1
+-------------------------------------------------*/
+
+static WRITE8_HANDLER( port1_w )
+{
+ laserdisc_state *ld = ldcore_get_safe_token(space->device().owner());
+ ldplayer_data *player = ld->player;
+
+ /*
+ $10 = P14 = (out) D104 -> /SPEED
+ $08 = P13 = (out) D103 -> /TIMER ENABLE
+ $04 = P12 = (out) D102 -> /REV
+ $02 = P11 = (out) D101 -> /FORW
+ $01 = P10 = (out) D100 -> some op-amp then to C334, B56, B332
+ */
+
+ if (LOG_PORTS && (player->port1 ^ data) & 0x1f)
+ {
+ printf("%03X:port1:", cpu_get_pc(&space->device()));
+ if (!(data & 0x10)) printf(" SPEED");
+ if (!(data & 0x08)) printf(" TIMENABLE");
+ if (!(data & 0x04)) printf(" REV");
+ if (!(data & 0x02)) printf(" FORW");
+ if (!(data & 0x01)) printf(" OPAMP");
+ printf("\n");
+ }
+
+ /* if bit 0 is set, we are not tracking */
+ if (data & 0x01)
+ player->trackdir = 0;
+
+ /* if bit 0 is clear and we weren't tracking before, initialize the state */
+ else if (player->trackdir == 0)
+ {
+ player->advanced = 0;
+
+ /* if bit 2 is clear, we are moving backwards */
+ if (!(data & 0x04))
+ {
+ player->trackdir = -1;
+ player->trackstate = 1;
+ }
+
+ /* if bit 1 is clear, we are moving forward */
+ else if (!(data & 0x02))
+ {
+ player->trackdir = 1;
+ player->trackstate = 0;
+ }
+ }
+
+ /* if we have a timer, adjust it */
+ if (player->tracktimer != NULL)
+ {
+ /* turn it off if we're not tracking */
+ if (player->trackdir == 0)
+ player->tracktimer->reset();
+
+ /* if we just started tracking, or if the speed was changed, reprime the timer */
+ else if (((player->port1 ^ data) & 0x11) != 0)
+ {
+ /* speeds here are just guesses, but work with the player logic; this is the time per half-track */
+ attotime speed = (data & 0x10) ? attotime::from_usec(60) : attotime::from_usec(10);
+
+ /* always start with an initial long delay; the code expects this */
+ player->tracktimer->adjust(attotime::from_usec(100), 0, speed);
+ }
+ }
+
+ player->port1 = data;
+}
+
+
+/*-------------------------------------------------
+ port2_r - read from the 8048 I/O port 2
+-------------------------------------------------*/
+
+static READ8_HANDLER( port2_r )
+{
+ laserdisc_state *ld = ldcore_get_safe_token(space->device().owner());
+ ldplayer_data *player = ld->player;
+ UINT8 result = 0x00;
+
+ /*
+ $80 = P27 = (in) set/reset latch; set by FOC LS, reset by IGR
+ $20 = P25 = (in) D125 -> 0 when data written to controller is preset, reset to 1 when read
+ $10 = P24 = (in) D124 -> 0 when data from controller is present, reset to 1 on a read
+ */
+
+ if (!player->tocontroller_pending)
+ result |= 0x20;
+ if (!player->fromcontroller_pending)
+ result |= 0x10;
+
+ return result;
+}
+
+
+/*-------------------------------------------------
+ port2_w - write the 8048 I/O port 2
+-------------------------------------------------*/
+
+static WRITE8_HANDLER( port2_w )
+{
+ /*
+ $40 = P26 = (out) cleared while data is sent back & forth; set afterwards
+ [Not actually connected, but this is done in the code]
+ */
+}
+
+
+/*-------------------------------------------------
+ t0_r - return the T0 line status, which is
+ connected to the DATIC's data strobe line
+-------------------------------------------------*/
+
+static READ8_HANDLER( t0_r )
+{
+ laserdisc_state *ld = ldcore_get_safe_token(space->device().owner());
+ return ld->player->datastrobe;
+}
+
+
+/*-------------------------------------------------
+ t1_r - return the T1 line status, which is
+ connected to the tracking state and is used
+ to count the number of tracks advanced
+-------------------------------------------------*/
+
+static READ8_HANDLER( t1_r )
+{
+ laserdisc_state *ld = ldcore_get_safe_token(space->device().owner());
+ return ld->player->trackstate;
+}
diff --git a/trunk/src/emu/machine/matsucd.c b/trunk/src/emu/machine/matsucd.c
new file mode 100644
index 00000000000..7778eb5b0db
--- /dev/null
+++ b/trunk/src/emu/machine/matsucd.c
@@ -0,0 +1,766 @@
+/***************************************************************************
+
+ Matsushita/Panasonic CDR521/522 type CDROM drive emulation
+
+Notes:
+This version implements the drive found in Amiga CDTV. There are
+different drives supporting this command-set (look in the sbpcd driver
+in Linux for examples). Most drives support the exact same command
+structure, but the command numbers differ. Eventually this driver
+can be expanded with support for the other drives as needed.
+
+***************************************************************************/
+
+
+#include "emu.h"
+#include "imagedev/chd_cd.h"
+#include "sound/cdda.h"
+#include "machine/matsucd.h"
+
+
+#define MATSU_STATUS_READY ( 1 << 0 ) /* driver ready */
+#define MATSU_STATUS_DOORLOCKED ( 1 << 1 ) /* door locked */
+#define MATSU_STATUS_PLAYING ( 1 << 2 ) /* drive playing */
+#define MATSU_STATUS_SUCCESS ( 1 << 3 ) /* last command was successful */
+#define MATSU_STATUS_ERROR ( 1 << 4 ) /* last command failed */
+#define MATSU_STATUS_MOTOR ( 1 << 5 ) /* spinning */
+#define MATSU_STATUS_MEDIA ( 1 << 6 ) /* media present (in caddy or tray) */
+#define MATSU_STATUS_DOORCLOSED ( 1 << 7 ) /* tray status */
+
+typedef struct
+{
+ UINT8 enabled; /* /ENABLE - Unit enabled */
+ UINT8 cmd_signal; /* /CMD - Command mode */
+ UINT8 stch_signal; /* /STCH - Status Changed */
+ UINT8 sten_signal; /* /STEN - Status Enabled */
+ UINT8 scor_signal; /* /STEN - Subcode Ready */
+ UINT8 input[16];
+ UINT8 input_pos;
+ UINT8 output[16];
+ UINT8 output_pos;
+ UINT8 output_len;
+ UINT8 status;
+ UINT8 motor;
+ UINT16 sector_size;
+ UINT32 lba;
+ UINT16 num_blocks;
+ UINT16 xfer_offset;
+ UINT8 sector_buffer[CD_MAX_SECTOR_DATA];
+ UINT8 cdda_set;
+ void (*sten_cb)( running_machine &machine, int level ); /* Status enabled callback */
+ void (*stch_cb)( running_machine &machine, int level ); /* Status changed callback */
+ void (*scor_cb)( running_machine &machine, int level ); /* Subcode ready callback */
+ cdrom_file *cdrom;
+ device_t *cdda;
+ emu_timer *frame_timer;
+} matsucd;
+
+static matsucd cd;
+
+#define MSF2LBA(msf) (((msf >> 16) & 0xff) * 60 * 75 + ((msf >> 8) & 0xff) * 75 + ((msf >> 0) & 0xff))
+#define LBA2MSF(lba) (((lba / (75 * 60)) << 16) | (((lba / 75) % 60) << 8) | (lba % 75))
+
+static TIMER_CALLBACK(matsu_subcode_proc);
+
+void matsucd_init( cdrom_image_device *cdrom_device, const char *cdda_tag )
+{
+ memset(&cd, 0, sizeof( matsucd ) );
+
+ cd.cdrom = cdrom_device->get_cdrom_file();
+ cd.cdda = cdrom_device->machine().device(cdda_tag);
+
+ cd.frame_timer = cdrom_device->machine().scheduler().timer_alloc(FUNC(matsu_subcode_proc));
+
+ cd.stch_signal = 1;
+}
+
+void matsucd_set_status_enabled_callback( void (*sten_cb)( running_machine &machine, int level ) )
+{
+ /* add the callback for status enabled signal */
+ cd.sten_cb = sten_cb;
+}
+
+void matsucd_set_status_changed_callback( void (*stch_cb)( running_machine &machine, int level ) )
+{
+ /* add the callback for status changed signal */
+ cd.stch_cb = stch_cb;
+}
+
+void matsucd_set_subcode_ready_callback( void (*scor_cb)( running_machine &machine, int level ) )
+{
+ /* add the callback for subcode ready signal */
+ cd.scor_cb = scor_cb;
+}
+
+static int matsucd_getsector_type( void )
+{
+ switch( cd.sector_size )
+ {
+ case 2048: return CD_TRACK_MODE1;
+ case 2324: return CD_TRACK_MODE2_FORM2;
+ case 2336: return CD_TRACK_MODE2;
+ case 2352: return CD_TRACK_MODE2_RAW;
+
+ default: logerror( "MATSUCD: Sector size %d unsupported!\n", cd.sector_size ); break;
+ }
+
+ return CD_TRACK_RAW_DONTCARE;
+}
+
+void matsucd_read_next_block( void )
+{
+ cd.xfer_offset = 0;
+
+ if ( cd.num_blocks )
+ {
+ cd.lba++;
+ cd.num_blocks--;
+
+ if (!cdrom_read_data(cd.cdrom, cd.lba, cd.sector_buffer, matsucd_getsector_type()))
+ {
+ logerror( "MATSUCD - Warning: Read error on CD!\n" );
+ }
+ }
+}
+
+int matsucd_get_next_byte( UINT8 *data )
+{
+ /* no more data to read on this sector */
+ if ( cd.xfer_offset >= cd.sector_size )
+ return -1;
+
+ if ( data )
+ *data = cd.sector_buffer[cd.xfer_offset++];
+
+ return 0;
+}
+
+static void matsucd_cdda_stop( running_machine &machine )
+{
+ device_t *cdda = cdda_from_cdrom(machine, cd.cdrom);
+
+ if (cdda != NULL)
+ {
+ cdda_stop_audio(cdda);
+ cd.frame_timer->reset( );
+ }
+}
+
+static void matsucd_cdda_play( running_machine &machine, UINT32 lba, UINT32 num_blocks )
+{
+ device_t *cdda = cdda_from_cdrom(machine, cd.cdrom);
+ if (cdda != NULL)
+ {
+ cdda_start_audio(cdda, lba, num_blocks);
+ cd.frame_timer->adjust(attotime::from_hz( 75 ));
+ }
+}
+
+static void matsucd_cdda_pause( running_machine &machine, int pause )
+{
+ device_t *cdda = cdda_from_cdrom(machine, cd.cdrom);
+ if (cdda != NULL)
+ {
+ cdda_pause_audio(cdda, pause);
+
+ if ( pause )
+ {
+ cd.frame_timer->reset( );
+ }
+ else
+ {
+ cd.frame_timer->adjust(attotime::from_hz( 75 ));
+ }
+ }
+}
+
+static UINT8 matsucd_cdda_getstatus( running_machine &machine, UINT32 *lba )
+{
+ device_t *cdda = cdda_from_cdrom(machine, cd.cdrom);
+
+ if ( lba ) *lba = 0;
+
+ if (cdda != NULL)
+ {
+ if (cdda_audio_active(cdda))
+ {
+ if ( lba ) *lba = cdda_get_audio_lba(cdda);
+
+ if (cdda_audio_paused(cdda))
+ {
+ return 0x12; /* audio paused */
+ }
+ else
+ {
+ return 0x11; /* audio in progress */
+ }
+ }
+ else if (cdda_audio_ended(cdda))
+ {
+ return 0x13; /* audio ended */
+ }
+ }
+
+ return 0x15; /* no audio status */
+}
+
+void matsucd_enable_w( int level )
+{
+ cd.enabled = ( level ) ? 0 : 1;
+}
+
+void matsucd_cmd_w( int level )
+{
+ cd.cmd_signal = ( level ) ? 0 : 1;
+}
+
+int matsucd_stch_r( void )
+{
+ return cd.stch_signal ? 0 : 1;
+}
+
+int matsucd_sten_r( void )
+{
+ return cd.sten_signal ? 0 : 1;
+}
+
+int matsucd_scor_r( void )
+{
+ return cd.scor_signal ? 0 : 1;
+}
+
+static void update_status_enable( running_machine &machine, int level )
+{
+ cd.sten_signal = level;
+
+ if ( cd.sten_cb )
+ {
+ (*cd.sten_cb)(machine, cd.sten_signal);
+ }
+}
+
+static void update_status_changed( running_machine &machine, int level )
+{
+ cd.stch_signal = level;
+
+ if ( cd.stch_cb )
+ {
+ (*cd.stch_cb)(machine, cd.stch_signal);
+ }
+}
+
+static void update_subcode_ready( running_machine &machine, int level )
+{
+ cd.scor_signal = level;
+
+ if ( cd.scor_cb )
+ {
+ (*cd.scor_cb)(machine, cd.scor_signal);
+ }
+}
+
+static TIMER_CALLBACK(matsucd_set_status_end)
+{
+ update_status_changed( machine, 1 );
+}
+
+static void matsucd_set_status( running_machine &machine, UINT8 status )
+{
+ if ( status != cd.status )
+ {
+ cd.status = status;
+
+ if ( cd.stch_signal != 0 )
+ {
+ update_status_changed( machine, 0 );
+ machine.scheduler().timer_set(attotime::from_msec(1), FUNC(matsucd_set_status_end));
+ }
+ }
+}
+
+static TIMER_CALLBACK(matsu_subcode_proc)
+{
+ device_t *cdda = cdda_from_cdrom(machine, cd.cdrom);
+
+ (void)param;
+
+ if (cdda != NULL)
+ {
+ UINT8 s = matsucd_cdda_getstatus(machine, NULL);
+ UINT8 newstatus = cd.status;
+
+ if ( s == 0x11 || s == 0x12 )
+ {
+ if ( s == 0x11 )
+ {
+ update_subcode_ready( machine, 1 );
+ update_subcode_ready( machine, 0 );
+ }
+
+ newstatus |= MATSU_STATUS_PLAYING;
+
+ cd.frame_timer->adjust(attotime::from_hz( 75 ));
+ }
+ else
+ {
+ newstatus &= ~MATSU_STATUS_PLAYING;
+ }
+
+ matsucd_set_status( machine, newstatus );
+ }
+}
+
+static void matsucd_command_error( running_machine &machine )
+{
+ UINT8 newstatus = cd.status;
+
+ newstatus &= ~MATSU_STATUS_SUCCESS;
+ newstatus |= MATSU_STATUS_ERROR;
+
+ matsucd_set_status( machine, newstatus );
+}
+
+static void matsucd_complete_cmd( running_machine &machine, UINT8 len )
+{
+ UINT8 newstatus = cd.status;
+
+ cd.input_pos = 0;
+ cd.output_pos = 0;
+ cd.output_len = len;
+
+ newstatus &= ~MATSU_STATUS_ERROR;
+ newstatus |= MATSU_STATUS_SUCCESS;
+
+ matsucd_set_status( machine, newstatus );
+
+ update_status_enable( machine, 1 );
+ update_status_enable( machine, 0 );
+}
+
+UINT8 matsucd_response_r( running_machine &machine )
+{
+ UINT8 v = cd.output[cd.output_pos++];
+
+ if ( cd.output_pos < cd.output_len )
+ {
+ update_status_enable( machine, 1 );
+ update_status_enable( machine, 0 );
+ }
+
+ return v;
+}
+
+void matsucd_command_w( running_machine &machine, UINT8 data )
+{
+ UINT8 cmd;
+
+ /* make sure we're enabled */
+ if ( cd.enabled == 0 )
+ return;
+
+ /* make sure /CMD is asserted */
+ if ( cd.cmd_signal == 0 )
+ return;
+
+ if ( cd.cdda_set == 0 )
+ {
+ // 2009-10, FP: for some reason, cdda_from_cdrom was not returning the correct
+ // CDDA device. Hence, as a temp workaround, I added the cdda to the struct
+ // and its tag is configured in matsucd_init
+ if ( cd.cdrom )
+ cdda_set_cdrom( cd.cdda, cd.cdrom);
+
+ cd.cdda_set = 1;
+ }
+
+ cd.input[cd.input_pos++] = data;
+
+ cmd = cd.input[0];
+
+ switch( cmd )
+ {
+ case 0x01: /* seek */
+ {
+ if ( cd.input_pos < 7 )
+ return;
+
+ /* stop CDDA audio if necessary */
+ matsucd_cdda_stop(machine);
+
+ cd.motor = 1;
+
+ memset( cd.output, 0, 6 );
+ matsucd_complete_cmd( machine, 0 );
+ }
+ break;
+
+ case 0x02: /* read sectors */
+ {
+ if ( cd.input_pos < 7 )
+ return;
+
+ /* stop CDDA audio if necessary */
+ matsucd_cdda_stop(machine);
+
+ /* LBA */
+ cd.lba = cd.input[1];
+ cd.lba <<= 8;
+ cd.lba |= cd.input[2];
+ cd.lba <<= 8;
+ cd.lba |= cd.input[3];
+
+ /* Number of blocks */
+ cd.num_blocks = cd.input[4];
+ cd.num_blocks <<= 8;
+ cd.num_blocks |= cd.input[5];
+
+ /* Reset transfer count */
+ cd.xfer_offset = 0;
+
+ /* go ahead and cache the first block */
+ if (!cdrom_read_data(cd.cdrom, cd.lba, cd.sector_buffer, matsucd_getsector_type()))
+ {
+ logerror( "MATSUCD - Warning: Read error on CD!\n" );
+ matsucd_command_error( machine );
+ return;
+ }
+
+ cd.motor = 1;
+
+ memset( cd.output, 0, 6 );
+ matsucd_complete_cmd( machine, 0 );
+ }
+ break;
+
+ case 0x04: /* motor on */
+ {
+ if ( cd.input_pos < 7 )
+ return;
+
+ cd.motor = 1;
+
+ memset( cd.output, 0, 6 );
+ matsucd_complete_cmd( machine, 0 );
+ }
+ break;
+
+ case 0x05: /* motor off */
+ {
+ if ( cd.input_pos < 7 )
+ return;
+
+ /* stop CDDA audio if necessary */
+ matsucd_cdda_stop(machine);
+
+ cd.motor = 0;
+
+ memset( cd.output, 0, 6 );
+ matsucd_complete_cmd( machine, 0 );
+ }
+ break;
+
+ case 0x09: /* play audio cd, LBA mode */
+ {
+ UINT32 lba, numblocks;
+
+ if ( cd.input_pos < 7 )
+ return;
+
+ lba = cd.input[1];
+ lba <<= 8;
+ lba |= cd.input[2];
+ lba <<= 8;
+ lba |= cd.input[3];
+
+ numblocks = cd.input[4];
+ numblocks <<= 8;
+ numblocks |= cd.input[5];
+ numblocks <<= 8;
+ numblocks |= cd.input[6];
+
+ matsucd_cdda_play( machine, lba, numblocks );
+
+ cd.motor = 1;
+
+ memset( cd.output, 0, 6 );
+ matsucd_complete_cmd( machine, 0 );
+ }
+ break;
+
+ case 0x0a: /* play audio cd, MSF mode */
+ {
+ UINT32 start, end, lba_start, lba_end;
+
+ if ( cd.input_pos < 7 )
+ return;
+
+ start = cd.input[1];
+ start <<= 8;
+ start |= cd.input[2];
+ start <<= 8;
+ start |= cd.input[3];
+
+ end = cd.input[4];
+ end <<= 8;
+ end |= cd.input[5];
+ end <<= 8;
+ end |= cd.input[6];
+
+ lba_start = MSF2LBA( start );
+ lba_end = MSF2LBA( end );
+
+ if ( end == 0xffffff )
+ {
+ lba_end = cdrom_get_track_start(cd.cdrom,cdrom_get_last_track(cd.cdrom)-1);
+ lba_end += cdrom_get_toc(cd.cdrom)->tracks[cdrom_get_last_track(cd.cdrom)-1].frames;
+ }
+
+ if ( lba_end <= lba_start )
+ {
+ matsucd_cdda_stop(machine);
+ }
+ else
+ {
+ matsucd_cdda_play( machine, lba_start, lba_end - lba_start );
+ cd.motor = 1;
+ }
+
+ memset( cd.output, 0, 6 );
+ matsucd_complete_cmd( machine, 0 );
+ }
+ break;
+
+ case 0x0b: /* play audio track and index */
+ {
+ UINT8 track_start = cd.input[1];
+ UINT8 index_start = cd.input[2];
+ UINT8 track_end = cd.input[3];
+ UINT8 index_end = cd.input[4];
+ UINT32 lba_start, lba_end;
+
+ /* TODO: Add index support once the CDDA engine supports it */
+ (void)index_start;
+ (void)index_end;
+
+ /* sanitize values */
+ if ( track_start == 0 ) track_start++;
+ if ( track_end == 0 ) track_end++;
+ if ( track_end > cdrom_get_last_track(cd.cdrom) )
+ track_end = cdrom_get_last_track(cd.cdrom);
+
+ /* find the start and stop positions */
+ lba_start = cdrom_get_track_start(cd.cdrom,track_start-1);
+ lba_end = cdrom_get_track_start(cd.cdrom,track_end-1);
+
+ lba_end += cdrom_get_toc(cd.cdrom)->tracks[track_end-1].frames;
+
+ if ( lba_end <= lba_start )
+ {
+ matsucd_cdda_stop(machine);
+ }
+ else
+ {
+ matsucd_cdda_play( machine, lba_start, lba_end - lba_start );
+ cd.motor = 1;
+ }
+
+ memset( cd.output, 0, 6 );
+ matsucd_complete_cmd( machine, 0 );
+ }
+ break;
+
+ case 0x81: /* status read */
+ {
+ UINT8 newstatus = cd.status;
+
+ newstatus &= MATSU_STATUS_SUCCESS | MATSU_STATUS_ERROR | MATSU_STATUS_PLAYING;
+ newstatus |= MATSU_STATUS_READY;
+
+ if (cd.cdrom)
+ {
+ newstatus |= MATSU_STATUS_MEDIA;
+ }
+
+ if (cd.motor)
+ newstatus |= MATSU_STATUS_MOTOR;
+
+ cd.output[0] = newstatus;
+
+ matsucd_set_status( machine, newstatus );
+
+ matsucd_complete_cmd( machine, 1 );
+ }
+ break;
+
+ case 0x82: /* error read */
+ {
+ if ( cd.input_pos < 7 )
+ return;
+
+ memset( cd.output, 0, 6 );
+ matsucd_complete_cmd( machine, 6 );
+ }
+ break;
+
+ case 0x84: /* set mode */
+ {
+ if ( cd.input_pos < 7 )
+ return;
+
+ cd.sector_size = cd.input[2];
+ cd.sector_size <<= 8;
+ cd.sector_size |= cd.input[3];
+
+ memset( cd.output, 0, 6 );
+ matsucd_complete_cmd( machine, 0 );
+ }
+ break;
+
+ case 0x87: /* read SUBQ */
+ {
+ int msfmode;
+ UINT32 lba;
+ UINT8 track;
+
+ if ( cd.input_pos < 7 )
+ return;
+
+ msfmode = (cd.input[1] & 0x02) ? 1 : 0;
+
+ memset( cd.output, 0, 13 );
+
+ cd.output[0] = matsucd_cdda_getstatus( machine, &lba );
+
+ if ( lba > 0 )
+ {
+ UINT32 disk_pos;
+ UINT32 track_pos;
+
+ track = cdrom_get_track(cd.cdrom, lba);
+
+ cd.output[1] = cdrom_get_adr_control(cd.cdrom, track);
+ cd.output[2] = track+1;
+ cd.output[3] = 0; /* index */
+
+ disk_pos = lba;
+ if ( msfmode ) disk_pos = LBA2MSF(disk_pos);
+
+ cd.output[4] = (disk_pos >> 24) & 0xff;
+ cd.output[5] = (disk_pos >> 16) & 0xff;
+ cd.output[6] = (disk_pos >> 8) & 0xff;
+ cd.output[7] = (disk_pos) & 0xff;
+
+ track_pos = lba - cdrom_get_track_start(cd.cdrom, track);
+ if ( msfmode ) track_pos = LBA2MSF(track_pos);
+
+ cd.output[8] = (track_pos >> 24) & 0xff;
+ cd.output[9] = (track_pos >> 16) & 0xff;
+ cd.output[10] = (track_pos >> 8) & 0xff;
+ cd.output[11] = (track_pos) & 0xff;
+
+ /* TODO: UPC flag at offset 12 */
+ cd.output[12] = 0;
+ }
+
+ matsucd_complete_cmd( machine, 13 );
+ }
+ break;
+
+ case 0x89: /* read disk info */
+ {
+ UINT32 end;
+
+ if ( cd.input_pos < 7 )
+ return;
+
+ memset( cd.output, 0, 5 );
+
+ cd.output[0] = cdrom_get_last_track(cd.cdrom) ? 1 : 0;
+ cd.output[1] = cdrom_get_last_track(cd.cdrom);
+ end = cdrom_get_track_start(cd.cdrom,cd.output[1]-1);
+ end += cdrom_get_toc(cd.cdrom)->tracks[cd.output[1]-1].frames;
+ end = LBA2MSF(end);
+ cd.output[2] = (end >> 16) & 0xff;
+ cd.output[3] = (end >> 8) & 0xff;
+ cd.output[4] = (end) & 0xff;
+
+ matsucd_complete_cmd( machine, 5 );
+ }
+ break;
+
+ case 0x8a: /* read toc */
+ {
+ UINT8 track;
+ int msfmode;
+ UINT32 track_start;
+
+ if ( cd.input_pos < 7 )
+ return;
+
+ /* stop CDDA audio if necessary */
+ matsucd_cdda_stop(machine);
+
+ track = cd.input[2];
+ msfmode = (cd.input[1] & 0x02) ? 1 : 0;
+
+ if ( cd.cdrom == NULL )
+ {
+ logerror( "MATSUCD - Warning: Reading TOC without a CD!\n" );
+ matsucd_command_error( machine );
+ return;
+ }
+
+ if ( track > cdrom_get_last_track(cd.cdrom) )
+ {
+ logerror( "MATSUCD - Warning: Reading invalid track entry from TOC!\n" );
+ matsucd_command_error( machine );
+ return;
+ }
+
+ memset( cd.output, 0, 7 );
+
+ track_start = cdrom_get_track_start(cd.cdrom, track > 0 ? (track-1) : track );
+ if ( msfmode ) track_start = LBA2MSF( track_start );
+
+ cd.output[1] = cdrom_get_adr_control(cd.cdrom, track > 0 ? (track-1) : track);
+ cd.output[2] = track;
+ cd.output[3] = (track == 0 ) ? cdrom_get_last_track(cd.cdrom) : 0;
+ cd.output[4] = (track_start >> 24) & 0xff;
+ cd.output[5] = (track_start >> 16) & 0xff;
+ cd.output[6] = (track_start >> 8) & 0xff;
+ cd.output[7] = (track_start) & 0xff;
+
+ cd.motor = 1;
+
+ matsucd_complete_cmd( machine, 8 );
+ }
+ break;
+
+ case 0x8b: /* pause audio */
+ {
+ if ( cd.input_pos < 7 )
+ return;
+
+ matsucd_cdda_pause( machine, (cd.input[1] == 0) ? 1 : 0 );
+ memset( cd.output, 0, 7 );
+ matsucd_complete_cmd( machine, 0 );
+ }
+ break;
+
+ case 0xa3: /* front panel */
+ {
+ if ( cd.input_pos < 7 )
+ return;
+
+ /* TODO: ??? */
+
+ memset( cd.output, 0, 7 );
+ matsucd_complete_cmd( machine, 0 );
+ }
+ break;
+
+ default:
+ logerror( "MATSUCD: Unknown/inimplemented command %08x\n", cmd );
+ break;
+ }
+}
diff --git a/trunk/src/emu/machine/matsucd.h b/trunk/src/emu/machine/matsucd.h
new file mode 100644
index 00000000000..b1e40690f83
--- /dev/null
+++ b/trunk/src/emu/machine/matsucd.h
@@ -0,0 +1,29 @@
+/***************************************************************************
+
+ Matsushita/Panasonic CDR521/522 type CDROM drive emulation
+
+***************************************************************************/
+
+/* initialization */
+void matsucd_init( cdrom_image_device *cdrom_device, const char *cdda_tag );
+
+
+/* signaling */
+extern void matsucd_enable_w( int level ); /* /ENABLE pin */
+extern void matsucd_cmd_w( int level ); /* /CMD pin */
+extern int matsucd_stch_r( void ); /* /STCH pin */
+extern int matsucd_sten_r( void ); /* /STEN pin */
+extern int matsucd_scor_r( void ); /* /SCOR pin */
+
+/* callback for signal changes */
+extern void matsucd_set_status_enabled_callback( void (*sten_cb)( running_machine &machine, int level ) );
+extern void matsucd_set_status_changed_callback( void (*stch_cb)( running_machine &machine, int level ) );
+extern void matsucd_set_subcode_ready_callback( void (*scor_cb)( running_machine &machine, int level ) );
+
+/* data transfer routines */
+extern void matsucd_read_next_block( void );
+extern int matsucd_get_next_byte( UINT8 *data );
+
+/* main command interface */
+extern void matsucd_command_w( running_machine &machine, UINT8 data );
+extern UINT8 matsucd_response_r( running_machine &machine );
diff --git a/trunk/src/emu/machine/mb14241.c b/trunk/src/emu/machine/mb14241.c
new file mode 100644
index 00000000000..9b351ed4690
--- /dev/null
+++ b/trunk/src/emu/machine/mb14241.c
@@ -0,0 +1,80 @@
+/***************************************************************************
+
+ Midway 8080-based black and white hardware
+
+****************************************************************************/
+
+#include "emu.h"
+#include "machine/mb14241.h"
+
+typedef struct _mb14241_state mb14241_state;
+struct _mb14241_state
+{
+ UINT16 shift_data; /* 15 bits only */
+ UINT8 shift_count; /* 3 bits */
+};
+
+/*****************************************************************************
+ INLINE FUNCTIONS
+*****************************************************************************/
+
+INLINE mb14241_state *get_safe_token( device_t *device )
+{
+ assert(device != NULL);
+ assert(device->type() == MB14241);
+
+ return (mb14241_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+/*****************************************************************************
+ IMPLEMENTATION
+*****************************************************************************/
+
+WRITE8_DEVICE_HANDLER( mb14241_shift_count_w )
+{
+ mb14241_state *mb14241 = get_safe_token(device);
+ mb14241->shift_count = ~data & 0x07;
+}
+
+WRITE8_DEVICE_HANDLER( mb14241_shift_data_w )
+{
+ mb14241_state *mb14241 = get_safe_token(device);
+ mb14241->shift_data = (mb14241->shift_data >> 8) | ((UINT16)data << 7);
+}
+
+READ8_DEVICE_HANDLER( mb14241_shift_result_r )
+{
+ mb14241_state *mb14241 = get_safe_token(device);
+ return mb14241->shift_data >> mb14241->shift_count;
+}
+
+/*****************************************************************************
+ DEVICE INTERFACE
+*****************************************************************************/
+
+static DEVICE_START( mb14241 )
+{
+ mb14241_state *mb14241 = get_safe_token(device);
+
+ device->save_item(NAME(mb14241->shift_data));
+ device->save_item(NAME(mb14241->shift_count));
+}
+
+static DEVICE_RESET( mb14241 )
+{
+ mb14241_state *mb14241 = get_safe_token(device);
+
+ mb14241->shift_data = 0;
+ mb14241->shift_count = 0;
+}
+
+static const char DEVTEMPLATE_SOURCE[] = __FILE__;
+
+#define DEVTEMPLATE_ID( p, s ) p##mb14241##s
+#define DEVTEMPLATE_FEATURES DT_HAS_START | DT_HAS_RESET
+#define DEVTEMPLATE_NAME "MB14241"
+#define DEVTEMPLATE_FAMILY "MB14241 Shifter IC"
+#include "devtempl.h"
+
+
+DEFINE_LEGACY_DEVICE(MB14241, mb14241);
diff --git a/trunk/src/emu/machine/mb14241.h b/trunk/src/emu/machine/mb14241.h
new file mode 100644
index 00000000000..120054591a8
--- /dev/null
+++ b/trunk/src/emu/machine/mb14241.h
@@ -0,0 +1,32 @@
+/*****************************************************************************
+
+ MB14241 shifter IC emulation
+
+ *****************************************************************************/
+
+#ifndef __MB14241_H__
+#define __MB14241_H__
+
+#include "devlegcy.h"
+
+
+DECLARE_LEGACY_DEVICE(MB14241, mb14241);
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_MB14241_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, MB14241, 0)
+
+
+/***************************************************************************
+ DEVICE I/O FUNCTIONS
+***************************************************************************/
+
+WRITE8_DEVICE_HANDLER ( mb14241_shift_count_w );
+WRITE8_DEVICE_HANDLER ( mb14241_shift_data_w );
+READ8_DEVICE_HANDLER( mb14241_shift_result_r );
+
+
+#endif /* __MB14241_H__ */
diff --git a/trunk/src/emu/machine/mb3773.c b/trunk/src/emu/machine/mb3773.c
new file mode 100644
index 00000000000..925def0a33f
--- /dev/null
+++ b/trunk/src/emu/machine/mb3773.c
@@ -0,0 +1,114 @@
+/***************************************************************************
+
+ Fujitsu MB3773
+
+ Power Supply Monitor with Watch Dog Timer (i.e. Reset IC)
+
+
+ Todo:
+ Calculate the timeout from parameters.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "mb3773.h"
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type MB3773 = &device_creator<mb3773_device>;
+
+//-------------------------------------------------
+// mb3773_device - constructor
+//-------------------------------------------------
+
+mb3773_device::mb3773_device( const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock )
+ : device_t(mconfig, MB3773, "MB3773", tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void mb3773_device::device_config_complete()
+{
+}
+
+
+//-------------------------------------------------
+// device_validity_check - perform validity checks
+// on this device
+//-------------------------------------------------
+
+bool mb3773_device::device_validity_check( emu_options &options, const game_driver &driver ) const
+{
+ return false;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mb3773_device::device_start()
+{
+ m_watchdog_timer = machine().scheduler().timer_alloc( FUNC(watchdog_timeout), this );
+ reset_timer();
+
+ save_item( NAME(m_ck) );
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void mb3773_device::device_reset()
+{
+ m_ck = 0;
+}
+
+
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+WRITE_LINE_DEVICE_HANDLER( mb3773_set_ck )
+{
+ downcast<mb3773_device *>( device )->set_ck( state );
+}
+
+void mb3773_device::set_ck( int state )
+{
+ state &= 1;
+
+ if( state == 0 && m_ck != 0 )
+ {
+ reset_timer();
+ }
+
+ m_ck = state;
+}
+
+
+//**************************************************************************
+// INTERNAL HELPERS
+//**************************************************************************
+
+void mb3773_device::reset_timer()
+{
+ m_watchdog_timer->adjust( attotime::from_seconds( 5 ) );
+}
+
+TIMER_CALLBACK( mb3773_device::watchdog_timeout )
+{
+ reinterpret_cast<mb3773_device *>(ptr)->machine().schedule_soft_reset();
+}
diff --git a/trunk/src/emu/machine/mb3773.h b/trunk/src/emu/machine/mb3773.h
new file mode 100644
index 00000000000..24874b3f534
--- /dev/null
+++ b/trunk/src/emu/machine/mb3773.h
@@ -0,0 +1,62 @@
+/***************************************************************************
+
+ Fujistu MB3773
+
+ Power Supply Monitor with Watch Dog Timer (i.e. Reset IC)
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __MB3773_H__
+#define __MB3773_H__
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_MB3773_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, MB3773, 0)
+
+
+// ======================> mb3773_device
+
+class mb3773_device :
+ public device_t
+{
+public:
+ // construction/destruction
+ mb3773_device( const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock );
+
+ // I/O operations
+ void set_ck( int state );
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual bool device_validity_check( emu_options &options, const game_driver &driver ) const;
+ virtual void device_start();
+ virtual void device_reset();
+
+ // internal helpers
+ static TIMER_CALLBACK( watchdog_timeout );
+ void reset_timer();
+
+ // internal state
+ emu_timer *m_watchdog_timer;
+ int m_ck;
+};
+
+
+// device type definition
+extern const device_type MB3773;
+
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+WRITE_LINE_DEVICE_HANDLER( mb3773_set_ck );
+
+#endif
diff --git a/trunk/src/emu/machine/mb87078.c b/trunk/src/emu/machine/mb87078.c
new file mode 100644
index 00000000000..26cd8680ac0
--- /dev/null
+++ b/trunk/src/emu/machine/mb87078.c
@@ -0,0 +1,278 @@
+/*****************************************************************************
+
+ Fujitsu MB87078 6-bit, 4-channel electronic volume controller emulator
+
+ An excerpt from the datasheet about the chip functionality:
+ "A digital signal input controls gain every 0.5 dB step from 0dB to -32dB.
+ - Gain variable range: 0 dB to -32 dB by 0.5dB or -infinity
+ - Gain variable range is expanded to connect two channels serially (0 dB to -64 dB)
+ - Each channel gain can be set respectively
+ - Test function is provided (to confirm internal data)
+ - Data is initialized by reset signal (all channels are set to 0dB)
+ - Logic I/O is TTL comatible"
+
+ There are 6 digital data input/output pins and DSEL pin that selects
+ the group (there are two) of internal registers to be read/written.
+
+ Group 0 is 6-bit gain latch
+ Group 1 is 5-bit control latch (2-bits are channel select and 3-bits are volume control)
+
+ Digital I/O Setting:
+ /TC DSEL D0 D1 D2 D3 D4 D5 I/O MODES (when /TC==H ->write)
+ H H DSC1 DSC2 EN C0 C32 X Input mode
+ H L GD0 GD1 GD2 GD3 GD4 GD5 (set)
+ L H DSC1 DSC2 EN C0 C32 L Output mode
+ L L GD0 GD1 GD2 GD3 GD4 GD5 (check)
+
+ Channel Setting:
+ DSC2 DSC1 CHANNEL
+ L L 0
+ L H 1
+ H L 2
+ H H 3
+
+ Electrical Volume Setting:
+ DATA* GAIN
+ GD5 GD4 GD3 GD2 GD1 GD0 EN C0 C32 (dB)
+ 1 1 1 1 1 1 1 0 0 0
+ 1 1 1 1 1 0 1 0 0 -0.5
+ 1 1 1 1 0 1 1 0 0 -1
+ 1 1 1 1 0 0 1 0 0 -1.5
+ 1 1 1 0 1 1 1 0 0 -2
+ [..........................................]
+ 0 0 0 0 0 1 1 0 0 -31
+ 0 0 0 0 0 0 1 0 0 -31.5
+ X X X X X X 1 X 1 -32
+ X X X X X X 1 1 0 0
+ X X X X X X 0 X X -infinity
+
+ X=don't care
+ * When reset, DATA is set to 0 dB (code 111111 100)
+
+
+ MB87078 pins and assigned interface variables/functions
+
+ /[ 1] D0 /TC [24]
+ | [ 2] D1 /WR [23]
+ MB87078_data_w()| [ 3] D2 /CE [22]
+ MB87078_data_r()| [ 4] D3 DSEL [21]-MB87078_data_w()/data_r() parameter
+ | [ 5] D4 /RESET [20]-MB87078_reset_comp_w()
+ \[ 6] D5 /PD [19]
+ [ 7] DGND VDD [18]
+ [ 8] AGND 1/2 VDD [17]
+ [ 9] AIN0 AOUT3 [16]
+ [10] AOUT0 AIN3 [15]
+ [11] AIN1 AOUT2 [14]
+ [12] AOUT1 AIN2 [13]
+
+
+ *****************************************************************************/
+
+#include "emu.h"
+#include "machine/mb87078.h"
+
+typedef struct _mb87078_state mb87078_state;
+struct _mb87078_state
+{
+ int gain[4]; /* gain index 0-63,64,65 */
+ int channel_latch; /* current channel */
+ UINT8 latch[2][4]; /* 6bit+3bit 4 data latches */
+ UINT8 reset_comp;
+
+ mb87078_gain_changed_cb gain_changed_cb;
+};
+
+
+static const float mb87078_gain_decibel[66] = {
+ 0.0, -0.5, -1.0, -1.5, -2.0, -2.5, -3.0, -3.5,
+ -4.0, -4.5, -5.0, -5.5, -6.0, -6.5, -7.0, -7.5,
+ -8.0, -8.5, -9.0, -9.5,-10.0,-10.5,-11.0,-11.5,
+ -12.0,-12.5,-13.0,-13.5,-14.0,-14.5,-15.0,-15.5,
+ -16.0,-16.5,-17.0,-17.5,-18.0,-18.5,-19.0,-19.5,
+ -20.0,-20.5,-21.0,-21.5,-22.0,-22.5,-23.0,-23.5,
+ -24.0,-24.5,-25.0,-25.5,-26.0,-26.5,-27.0,-27.5,
+ -28.0,-28.5,-29.0,-29.5,-30.0,-30.5,-31.0,-31.5,
+ -32.0, -256.0
+ };
+
+static const int mb87078_gain_percent[66] = {
+ 100,94,89,84,79,74,70,66,
+ 63,59,56,53,50,47,44,42,
+ 39,37,35,33,31,29,28,26,
+ 25,23,22,21,19,18,17,16,
+ 15,14,14,13,12,11,11,10,
+ 10, 9, 8, 8, 7, 7, 7, 6,
+ 6, 5, 5, 5, 5, 4, 4, 4,
+ 3, 3, 3, 3, 3, 2, 2, 2,
+ 2, 0
+};
+
+/*****************************************************************************
+ INLINE FUNCTIONS
+*****************************************************************************/
+
+INLINE mb87078_state *get_safe_token( device_t *device )
+{
+ assert(device != NULL);
+ assert(device->type() == MB87078);
+
+ return (mb87078_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+INLINE const mb87078_interface *get_interface( device_t *device )
+{
+ assert(device != NULL);
+ assert((device->type() == MB87078));
+ return (const mb87078_interface *) device->static_config();
+}
+
+/*****************************************************************************
+ IMPLEMENTATION
+*****************************************************************************/
+
+#define GAIN_MAX_INDEX 64
+#define GAIN_INFINITY_INDEX 65
+
+
+static int calc_gain_index( int data0, int data1 )
+{
+//data 0: GD0-GD5
+//data 1: 1 2 4 8 16
+// c1 c2 EN C0 C32
+
+ if (!(data1 & 0x04))
+ {
+ return GAIN_INFINITY_INDEX;
+ }
+ else
+ {
+ if (data1 & 0x10)
+ {
+ return GAIN_MAX_INDEX;
+ }
+ else
+ {
+ if (data1 & 0x08)
+ {
+ return 0;
+ }
+ else
+ {
+ return (data0 ^ 0x3f);
+ }
+ }
+ }
+}
+
+
+static void gain_recalc( device_t *device )
+{
+ mb87078_state *mb87078 = get_safe_token(device);
+ int i;
+
+ for (i = 0; i < 4; i++)
+ {
+ int old_index = mb87078->gain[i];
+ mb87078->gain[i] = calc_gain_index(mb87078->latch[0][i], mb87078->latch[1][i]);
+ if (old_index != mb87078->gain[i])
+ mb87078->gain_changed_cb(device->machine(), i, mb87078_gain_percent[mb87078->gain[i]]);
+ }
+}
+
+
+
+void mb87078_data_w( device_t *device, int data, int dsel )
+{
+ mb87078_state *mb87078 = get_safe_token(device);
+
+ if (mb87078->reset_comp == 0)
+ return;
+
+ if (dsel == 0) /* gd0 - gd5 */
+ {
+ mb87078->latch[0][mb87078->channel_latch] = data & 0x3f;
+ }
+ else /* dcs1, dsc2, en, c0, c32, X */
+ {
+ mb87078->channel_latch = data & 3;
+ mb87078->latch[1][mb87078->channel_latch] = data & 0x1f; //always zero bit 5
+ }
+ gain_recalc(device);
+}
+
+
+float mb87078_gain_decibel_r( device_t *device, int channel )
+{
+ mb87078_state *mb87078 = get_safe_token(device);
+ return mb87078_gain_decibel[mb87078->gain[channel]];
+}
+
+
+int mb87078_gain_percent_r( device_t *device, int channel )
+{
+ mb87078_state *mb87078 = get_safe_token(device);
+ return mb87078_gain_percent[mb87078->gain[channel]];
+}
+
+void mb87078_reset_comp_w( device_t *device, int level )
+{
+ mb87078_state *mb87078 = get_safe_token(device);
+
+ mb87078->reset_comp = level;
+
+ /*this seems to be true, according to the datasheets*/
+ if (level == 0)
+ {
+ mb87078->latch[0][0] = 0x3f;
+ mb87078->latch[0][1] = 0x3f;
+ mb87078->latch[0][2] = 0x3f;
+ mb87078->latch[0][3] = 0x3f;
+
+ mb87078->latch[1][0] = 0x0 | 0x4;
+ mb87078->latch[1][1] = 0x1 | 0x4;
+ mb87078->latch[1][2] = 0x2 | 0x4;
+ mb87078->latch[1][3] = 0x3 | 0x4;
+ }
+
+ gain_recalc(device);
+}
+
+/*****************************************************************************
+ DEVICE INTERFACE
+*****************************************************************************/
+
+static DEVICE_START( mb87078 )
+{
+ mb87078_state *mb87078 = get_safe_token(device);
+ const mb87078_interface *intf = get_interface(device);
+
+ mb87078->gain_changed_cb = intf->gain_changed_cb;
+
+ device->save_item(NAME(mb87078->channel_latch));
+ device->save_item(NAME(mb87078->reset_comp));
+ device->save_item(NAME(mb87078->latch[0]));
+ device->save_item(NAME(mb87078->latch[1]));
+ device->save_item(NAME(mb87078->gain));
+}
+
+static DEVICE_RESET( mb87078 )
+{
+ mb87078_state *mb87078 = get_safe_token(device);
+
+ mb87078->channel_latch = 0;
+
+ /* reset chip */
+ mb87078_reset_comp_w(device, 0);
+ mb87078_reset_comp_w(device, 1);
+}
+
+static const char DEVTEMPLATE_SOURCE[] = __FILE__;
+
+#define DEVTEMPLATE_ID( p, s ) p##mb87078##s
+#define DEVTEMPLATE_FEATURES DT_HAS_START | DT_HAS_RESET
+#define DEVTEMPLATE_NAME "Fujitsu MB87078"
+#define DEVTEMPLATE_FAMILY "Fujitsu Volume Controller MB87078"
+#include "devtempl.h"
+
+
+DEFINE_LEGACY_DEVICE(MB87078, mb87078);
diff --git a/trunk/src/emu/machine/mb87078.h b/trunk/src/emu/machine/mb87078.h
new file mode 100644
index 00000000000..7f62b44c06e
--- /dev/null
+++ b/trunk/src/emu/machine/mb87078.h
@@ -0,0 +1,59 @@
+/*****************************************************************************
+
+ MB87078 6-bit,4-channel electronic volume controller emulator
+
+
+*****************************************************************************/
+
+#ifndef __MB87078_H__
+#define __MB87078_H__
+
+#include "devlegcy.h"
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef void (*mb87078_gain_changed_cb)(running_machine &machine, int channel, int percent /*, float decibels*/);
+
+typedef struct _mb87078_interface mb87078_interface;
+struct _mb87078_interface
+{
+ mb87078_gain_changed_cb gain_changed_cb;
+};
+
+DECLARE_LEGACY_DEVICE(MB87078, mb87078);
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_MB87078_ADD(_tag, _interface) \
+ MCFG_DEVICE_ADD(_tag, MB87078, 0) \
+ MCFG_DEVICE_CONFIG(_interface)
+
+
+/***************************************************************************
+ DEVICE I/O FUNCTIONS
+***************************************************************************/
+
+void mb87078_data_w(device_t *device, int data, int dsel);
+void mb87078_reset_comp_w(device_t *device, int level);
+
+
+/* mb87078_gain_decibel_r will return 'channel' gain on the device.
+ Returned value represents channel gain expressed in decibels,
+ Range from 0 to -32.0 (or -256.0 for -infinity) */
+float mb87078_gain_decibel_r(device_t *device, int channel);
+
+
+/* mb87078_gain_percent_r will return 'channel' gain on the device.
+ Returned value represents channel gain expressed in percents of maximum volume.
+ Range from 100 to 0. (100 = 0dB; 50 = -6dB; 0 = -infinity)
+ This function is designed for use with MAME mixer_xxx() functions. */
+int mb87078_gain_percent_r(device_t *device, int channel);
+
+
+#endif /* __MB87078_H__ */
diff --git a/trunk/src/emu/machine/mc146818.c b/trunk/src/emu/machine/mc146818.c
new file mode 100644
index 00000000000..7060cd2a19b
--- /dev/null
+++ b/trunk/src/emu/machine/mc146818.c
@@ -0,0 +1,514 @@
+/*********************************************************************
+
+ mc146818.c
+
+ Implementation of the MC146818 chip
+
+ Real time clock chip with battery buffered ram (or CMOS)
+ Used in IBM PC/AT, several PC clones, Amstrad NC200, Apollo workstations
+
+ Nathan Woods (npwoods@mess.org)
+ Peter Trauner (peter.trauner@jk.uni-linz.ac.at)
+
+ PC CMOS info (based on info from Padgett Peterson):
+
+ Clock Related:
+ 0x00 Seconds (BCD 00-59, Hex 00-3B) Note: Bit 7 is read only
+ 0x01 Second Alarm (BCD 00-59, Hex 00-3B; "don't care" if C0-FF)
+ 0x02 Minutes (BCD 00-59, Hex 00-3B)
+ 0x03 Minute Alarm (BCD 00-59, Hex 00-3B; "don't care" if C0-FF))
+ 0x04 Hours (BCD 00-23, Hex 00-17 if 24 hr mode)
+ (BCD 01-12, Hex 01-0C if 12 hr am)
+ (BCD 81-92. Hex 81-8C if 12 hr pm)
+ 0x05 Hour Alarm (same as hours; "don't care" if C0-FF))
+ 0x06 Day of Week (01-07 Sunday=1)
+ 0x07 Date of Month (BCD 01-31, Hex 01-1F)
+ 0x08 Month (BCD 01-12, Hex 01-0C)
+ 0x09 Year (BCD 00-99, Hex 00-63)
+ 0x0B Status Register B (read/write)
+ Bit 7 - 1 enables cycle update, 0 disables
+ Bit 6 - 1 enables periodic interrupt
+ Bit 5 - 1 enables alarm interrupt
+ Bit 4 - 1 enables update-ended interrupt
+ Bit 3 - 1 enables square wave output
+ Bit 2 - Data Mode - 0: BCD, 1: Binary
+ Bit 1 - 24/12 hour selection - 1 enables 24 hour mode
+ Bit 0 - Daylight Savings Enable - 1 enables
+ 0x0C Status Register C (Read only)
+ Bit 7 - Interrupt request flag - 1 when any or all of bits 6-4 are
+ 1 and appropriate enables (Register B) are set to 1. Generates
+ IRQ 8 when triggered.
+ Bit 6 - Periodic Interrupt flag
+ Bit 5 - Alarm Interrupt flag
+ Bit 4 - Update-Ended Interrupt Flag
+ Bit 3-0 ???
+ 0x0D Status Register D (read only)
+ Bit 7 - Valid RAM - 1 indicates batery power good, 0 if dead or
+ disconnected.
+ Bit 6-0 ???
+
+ Non-clock related:
+ 0x0E (PS/2) Diagnostic Status Byte
+ Bit 7 - When set (1) indicates clock has lost power
+ Bit 6 - (1) indicates incorrect checksum
+ Bit 5 - (1) indicates that equipment configuration is incorrect
+ power-on check requires that atleast one floppy be installed
+ Bit 4 - (1) indicates error in memory size
+ Bit 3 - (1) indicates that controller or disk drive failed initialization
+ Bit 2 - (1) indicates that time is invalid
+ Bit 1 - (1) indicates installed adaptors do not match configuration
+ Bit 0 - (1) indicates a time-out while reading adaptor ID
+ 0x0E (AMSTRAD) 6 BYTEs time and date machine last used
+ 0x0F Reset Code (IBM PS/2 "Shutdown Status Byte")
+ 0x00-0x03 perform power-on reset
+ 0x04 INT 19h reboot
+ 0x05 flush keyboard and jump via 0040:0067
+ 0x06-0x07 reserved
+ 0x08 used by POST during protected-mode RAM test
+ 0x09 used for INT 15/87h (block move) support
+ 0x0A jump via 0040:0067
+ 0x0B-0xFF perform power-on reset
+
+*********************************************************************/
+
+#include "emu.h"
+#include "coreutil.h"
+#include "machine/mc146818.h"
+
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define LOG_MC146818 0
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+#define USE_UTC 1
+
+#define HOURS_24 (m_data[0xb]&2)
+#define BCD_MODE !(m_data[0xb]&4) // book has other description!
+#define CENTURY m_data[100]
+#define YEAR m_data[9]
+#define MONTH m_data[8]
+#define DAY m_data[7]
+#define WEEK_DAY m_data[6]
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type MC146818 = &device_creator<mc146818_device>;
+
+//-------------------------------------------------
+// mc146818_device - constructor
+//-------------------------------------------------
+
+mc146818_device::mc146818_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, MC146818, "NVRAM", tag, owner, clock),
+ device_rtc_interface(mconfig, *this),
+ device_nvram_interface(mconfig, *this),
+ m_type(MC146818_STANDARD),
+ m_index(0),
+ m_eindex(0),
+ m_updated(false),
+ m_last_refresh(attotime::zero)
+{
+}
+
+
+//-------------------------------------------------
+// static_set_interface - configuration helper
+// to set the interface
+//-------------------------------------------------
+
+void mc146818_device::static_set_type(device_t &device, mc146818_type type)
+{
+ downcast<mc146818_device &>(device).m_type = type;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mc146818_device::device_start()
+{
+ m_last_refresh = machine().time();
+ m_clock_timer = timer_alloc(TIMER_CLOCK);
+ m_periodic_timer = timer_alloc(TIMER_PERIODIC);
+
+ memset(m_data, 0, sizeof(m_data));
+
+ if (m_type == MC146818_UTC) {
+ // hack: for apollo we increase the update frequency to stay in sync with real time
+ m_clock_timer->adjust(attotime::from_hz(2), 0, attotime::from_hz(2));
+ } else {
+ m_clock_timer->adjust(attotime::from_hz(1), 0, attotime::from_hz(1));
+ }
+
+ m_periodic_timer->adjust(attotime::never);
+ m_period = attotime::never;
+
+ set_base_datetime();
+
+ m_out_irq_func.resolve(m_out_irq_cb, *this);
+}
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void mc146818_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const mc146818_interface *intf = reinterpret_cast<const mc146818_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<mc146818_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_out_irq_cb, 0, sizeof(m_out_irq_cb));
+ }
+}
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void mc146818_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ int year/*, month*/;
+
+ if (id == TIMER_PERIODIC) {
+ m_data[0x0c] |= 0xc0;
+ if (!m_out_irq_func.isnull()) m_out_irq_func(CLEAR_LINE);
+ return;
+ }
+
+ if (BCD_MODE)
+ {
+ m_data[0]=bcd_adjust(m_data[0]+1);
+ if (m_data[0]>=0x60)
+ {
+ m_data[0]=0;
+ m_data[2]=bcd_adjust(m_data[2]+1);
+ if (m_data[2]>=0x60)
+ {
+ m_data[2]=0;
+ m_data[4]=bcd_adjust(m_data[4]+1);
+ // different handling of hours
+ if (m_data[4]>=0x24)
+ {
+ m_data[4]=0;
+ WEEK_DAY=bcd_adjust(WEEK_DAY+1)%7;
+ DAY=bcd_adjust(DAY+1);
+ //month=bcd_2_dec(MONTH);
+ year=bcd_2_dec(YEAR);
+ if (m_type!=MC146818_IGNORE_CENTURY) year+=bcd_2_dec(CENTURY)*100;
+ else year+=2000; // save for julian_days_in_month calculation
+ DAY=bcd_adjust(DAY+1);
+ if (DAY>gregorian_days_in_month(MONTH, year))
+ {
+ DAY=1;
+ MONTH=bcd_adjust(MONTH+1);
+ if (MONTH>0x12)
+ {
+ MONTH=1;
+ YEAR=year=bcd_adjust(YEAR+1);
+ if (m_type!=MC146818_IGNORE_CENTURY)
+ {
+ if (year>=0x100)
+ {
+ CENTURY=bcd_adjust(CENTURY+1);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ m_data[0]=m_data[0]+1;
+ if (m_data[0]>=60)
+ {
+ m_data[0]=0;
+ m_data[2]=m_data[2]+1;
+ if (m_data[2]>=60) {
+ m_data[2]=0;
+ m_data[4]=m_data[4]+1;
+ // different handling of hours //?
+ if (m_data[4]>=24) {
+ m_data[4]=0;
+ WEEK_DAY=(WEEK_DAY+1)%7;
+ year=YEAR;
+ if (m_type!=MC146818_IGNORE_CENTURY) year+=CENTURY*100;
+ else year+=2000; // save for julian_days_in_month calculation
+ if (++DAY>gregorian_days_in_month(MONTH, year)) {
+ DAY=1;
+ if (++MONTH>12) {
+ MONTH=1;
+ YEAR++;
+ if (m_type!=MC146818_IGNORE_CENTURY) {
+ if (YEAR>=100) { CENTURY++;YEAR=0; }
+ } else {
+ YEAR%=100;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (m_data[1] == m_data[0] && //
+ m_data[3] == m_data[2] && //
+ m_data[5] == m_data[4]) {
+ // set the alarm interrupt flag AF
+ m_data[0x0c] |= 0x20;
+ } else {
+ // clear the alarm interrupt flag AF
+ m_data[0x0c] &= ~0x20;
+ if ((m_data[0x0c] & 0x70) == 0) {
+ // clear IRQF
+ m_data[0x0c] &= ~0x80;
+ }
+ }
+
+ // set the update-ended interrupt Flag UF
+ m_data[0x0c] |= 0x10;
+
+ // set the interrupt request flag IRQF
+ // FIXME: should throw IRQ line as well
+ if ((m_data[0x0b] & m_data[0x0c] & 0x30) != 0) {
+ m_data[0x0c] |= 0x80;
+ }
+
+ // IRQ line is active low
+ if (!m_out_irq_func.isnull()) m_out_irq_func((m_data[0x0c] & 0x80) ? CLEAR_LINE : ASSERT_LINE);
+
+ m_updated = true; /* clock has been updated */
+ m_last_refresh = machine().time();
+}
+
+
+//-------------------------------------------------
+// rtc_set_time - called to initialize the RTC to
+// a known state
+//-------------------------------------------------
+
+void mc146818_device::rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second)
+{
+ YEAR = year;
+ MONTH = month;
+ DAY = day;
+ WEEK_DAY = day_of_week;
+ m_data[4] = hour;
+ m_data[2] = minute;
+ m_data[0] = second;
+}
+
+
+//-------------------------------------------------
+// nvram_default - called to initialize NVRAM to
+// its default state
+//-------------------------------------------------
+
+void mc146818_device::nvram_default()
+{
+ set_base_datetime();
+}
+
+
+//-------------------------------------------------
+// nvram_read - called to read NVRAM from the
+// .nv file
+//-------------------------------------------------
+
+void mc146818_device::nvram_read(emu_file &file)
+{
+ file.read(m_data, sizeof(m_data));
+ set_base_datetime();
+}
+
+
+//-------------------------------------------------
+// nvram_write - called to write NVRAM to the
+// .nv file
+//-------------------------------------------------
+
+void mc146818_device::nvram_write(emu_file &file)
+{
+ file.write(m_data, sizeof(m_data));
+}
+
+
+//-------------------------------------------------
+// dec_2_local - convert from decimal to BCD if
+// necessary
+//-------------------------------------------------
+
+inline int mc146818_device::dec_2_local(int a)
+{
+ return BCD_MODE ? dec_2_bcd(a) : a;
+}
+
+
+//-------------------------------------------------
+// dec_2_local - convert from decimal to BCD if
+// necessary
+//-------------------------------------------------
+
+void mc146818_device::set_base_datetime()
+{
+ system_time systime;
+ system_time::full_time current_time;
+
+ machine().base_datetime(systime);
+
+ current_time = (m_type == MC146818_UTC) ? systime.utc_time: systime.local_time;
+
+// logerror("mc146818_set_base_datetime %02d/%02d/%02d %02d:%02d:%02d\n",
+// current_time.year % 100, current_time.month + 1, current_time.mday,
+// current_time.hour,current_time.minute, current_time.second);
+
+ if (HOURS_24 || (current_time.hour < 12))
+ m_data[4] = dec_2_local(current_time.hour);
+ else
+ m_data[4] = dec_2_local(current_time.hour - 12) | 0x80;
+
+ if (m_type != MC146818_IGNORE_CENTURY)
+ CENTURY = dec_2_local(current_time.year /100);
+
+ m_data[0] = dec_2_local(current_time.second);
+ m_data[2] = dec_2_local(current_time.minute);
+ DAY = dec_2_local(current_time.mday);
+ MONTH = dec_2_local(current_time.month + 1);
+ YEAR = dec_2_local(current_time.year % 100);
+
+ WEEK_DAY = current_time.weekday;
+ if (current_time.is_dst)
+ m_data[0xb] |= 1;
+ else
+ m_data[0xb] &= ~1;
+}
+
+
+//-------------------------------------------------
+// read - I/O handler for reading
+//-------------------------------------------------
+
+READ8_MEMBER( mc146818_device::read )
+{
+ UINT8 data = 0;
+ switch (offset) {
+ case 0:
+ data = m_index;
+ break;
+
+ case 1:
+ switch (m_index % MC146818_DATA_SIZE) {
+ case 0xa:
+ data = m_data[m_index % MC146818_DATA_SIZE];
+ if ((space.machine().time() - m_last_refresh) < attotime::from_hz(32768))
+ data |= 0x80;
+#if 0
+ /* for pc1512 bios realtime clock test */
+ m_data[m_index % MC146818_DATA_SIZE] ^= 0x80; /* 0x80 update in progress */
+#endif
+ break;
+
+ case 0xc:
+// if(m_updated) /* the clock has been updated */
+// data = 0x10;
+// else
+// data = 0x00;
+ // the unused bits b0 ... b3 are always read as 0
+ data = m_data[m_index % MC146818_DATA_SIZE] & 0xf0;
+ // read 0x0c will clear all IRQ flags in register 0x0c
+ m_data[m_index % MC146818_DATA_SIZE] &= 0x0f;
+ if (!m_out_irq_func.isnull()) m_out_irq_func(ASSERT_LINE);
+ break;
+ case 0xd:
+ /* battery ok */
+ data = m_data[m_index % MC146818_DATA_SIZE] | 0x80;
+ break;
+
+ default:
+ data = m_data[m_index % MC146818_DATA_SIZE];
+ break;
+ }
+ break;
+ }
+
+ if (LOG_MC146818)
+ logerror("mc146818_port_r(): index=0x%02x data=0x%02x\n", m_index, data);
+ return data;
+}
+
+
+//-------------------------------------------------
+// write - I/O handler for writing
+//-------------------------------------------------
+
+WRITE8_MEMBER( mc146818_device::write )
+{
+ attotime rate;
+ if (LOG_MC146818)
+ logerror("mc146818_port_w(): index=0x%02x data=0x%02x\n", m_index, data);
+
+ switch (offset) {
+ case 0:
+ m_index = data;
+ break;
+
+ case 1:
+ switch(m_index % MC146818_DATA_SIZE)
+ {
+ case 0x0a:
+ // fixme: allow different time base
+ data &= 0x0f;
+ if (m_data[0x0b] & 0x40) {
+ if (data > 2)
+ m_period = attotime::from_hz(32768 >> (data - 1));
+ else if (data > 0)
+ m_period = attotime::from_hz(32768 >> (data + 6));
+ else m_period = attotime::never;
+ rate = attotime::zero;
+ } else rate = attotime::never;
+ m_periodic_timer->adjust(rate, 0, m_period);
+ data |= m_data[m_index % MC146818_DATA_SIZE] & 0xf0;
+ m_data[m_index % MC146818_DATA_SIZE] = data;
+ break;
+ case 0x0b:
+ if(data & 0x80)
+ m_updated = false;
+ // this probably isn't right but otherwise
+ // you'll be making a lot of unnecessary callbacks
+ if (data & 0x40)
+ m_periodic_timer->adjust(attotime::zero, 0, m_period);
+ else
+ m_periodic_timer->adjust(attotime::never);
+ m_data[m_index % MC146818_DATA_SIZE] = data;
+ break;
+ case 0x0c:
+ // register 0x0c is readonly
+ break;
+ default:
+ m_data[m_index % MC146818_DATA_SIZE] = data;
+ }
+ break;
+ }
+}
diff --git a/trunk/src/emu/machine/mc146818.h b/trunk/src/emu/machine/mc146818.h
new file mode 100644
index 00000000000..38d3e563888
--- /dev/null
+++ b/trunk/src/emu/machine/mc146818.h
@@ -0,0 +1,118 @@
+/*********************************************************************
+
+ mc146818.h
+
+ Implementation of the MC146818 chip
+
+ Real time clock chip with batteru buffered ram
+ Used in IBM PC/AT, several PC clones, Amstrad NC200
+
+ Peter Trauner (peter.trauner@jk.uni-linz.ac.at)
+
+*********************************************************************/
+
+#ifndef __MC146818_H__
+#define __MC146818_H__
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_MC146818_IRQ_ADD(_tag, _type, _intrf) \
+ MCFG_DEVICE_ADD(_tag, MC146818, 0) \
+ mc146818_device::static_set_type(*device, mc146818_device::_type); \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_MC146818_ADD(_tag, _type) \
+ MCFG_DEVICE_ADD(_tag, MC146818, 0) \
+ mc146818_device::static_set_type(*device, mc146818_device::_type);
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> mc146818_interface
+
+struct mc146818_interface
+{
+ devcb_write_line m_out_irq_cb;
+};
+
+// ======================> mc146818_device
+
+class mc146818_device : public device_t,
+ public device_rtc_interface,
+ public device_nvram_interface,
+ public mc146818_interface
+{
+public:
+ // values
+ enum mc146818_type
+ {
+ MC146818_STANDARD,
+ MC146818_IGNORE_CENTURY, // century is NOT set, for systems having other usage of this byte
+ MC146818_ENHANCED,
+ MC146818_UTC
+ };
+
+ // construction/destruction
+ mc146818_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // inline configuration helpers
+ static void static_set_type(device_t &device, mc146818_type type);
+
+ // read/write access
+ DECLARE_READ8_MEMBER( read );
+ DECLARE_WRITE8_MEMBER( write );
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_config_complete();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+ // device_rtc_interface overrides
+ virtual void rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second);
+ virtual bool rtc_is_year_2000_compliant() { return false; }
+
+ // device_nvram_interface overrides
+ virtual void nvram_default();
+ virtual void nvram_read(emu_file &file);
+ virtual void nvram_write(emu_file &file);
+
+ // internal helpers
+ int dec_2_local(int a);
+ void set_base_datetime();
+
+ // internal state
+ static const int MC146818_DATA_SIZE = 0x80;
+
+ mc146818_type m_type;
+
+ UINT8 m_index;
+ UINT8 m_data[MC146818_DATA_SIZE];
+
+ UINT16 m_eindex;
+ UINT8 m_edata[0x2000];
+
+ bool m_updated; /* update ended interrupt flag */
+
+ attotime m_last_refresh;
+ attotime m_period;
+
+ static const device_timer_id TIMER_CLOCK = 0;
+ static const device_timer_id TIMER_PERIODIC = 1;
+
+ emu_timer *m_clock_timer;
+ emu_timer *m_periodic_timer;
+
+ devcb_resolved_write_line m_out_irq_func;
+};
+
+
+// device type definition
+extern const device_type MC146818;
+
+
+#endif /* __MC146818_H__ */
diff --git a/trunk/src/emu/machine/mc6852.c b/trunk/src/emu/machine/mc6852.c
new file mode 100644
index 00000000000..47c02acaa2a
--- /dev/null
+++ b/trunk/src/emu/machine/mc6852.c
@@ -0,0 +1,370 @@
+/**********************************************************************
+
+ Motorola MC6852 Synchronous Serial Data Adapter emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+/*
+
+ TODO:
+
+ - FIFO
+ - receive
+ - transmit
+ - parity
+ - 1-sync-character mode
+ - 2-sync-character mode
+ - external sync mode
+ - interrupts
+
+*/
+
+#include "emu.h"
+#include "mc6852.h"
+#include "machine/devhelpr.h"
+
+
+// device type definition
+const device_type MC6852 = &device_creator<mc6852_device>;
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+
+#define S_RDA 0x01
+#define S_TDRA 0x02
+#define S_DCD 0x04
+#define S_CTS 0x08
+#define S_TUF 0x10
+#define S_RX_OVRN 0x20
+#define S_PE 0x40
+#define S_IRQ 0x80
+
+
+#define C1_RX_RS 0x01
+#define C1_TX_RS 0x02
+#define C1_STRIP_SYNC 0x04
+#define C1_CLEAR_SYNC 0x08
+#define C1_TIE 0x10
+#define C1_RIE 0x20
+#define C1_AC_MASK 0xc0
+#define C1_AC_C2 0x00
+#define C1_AC_C3 0x40
+#define C1_AC_SYNC 0x80
+#define C1_AC_TX_FIFO 0xc0
+
+
+#define C2_PC1 0x01
+#define C2_PC2 0x02
+#define C2_1_2_BYTE 0x04
+#define C2_WS_MASK 0x38
+#define C2_WS_6_E 0x00
+#define C2_WS_6_O 0x08
+#define C2_WS_7 0x10
+#define C2_WS_8 0x18
+#define C2_WS_7_E 0x20
+#define C2_WS_7_O 0x28
+#define C2_WS_8_E 0x30
+#define C2_WS_8_O 0x38
+#define C2_TX_SYNC 0x40
+#define C2_EIE 0x80
+
+
+#define C3_E_I_SYNC 0x01
+#define C3_1_2_SYNC 0x02
+#define C3_CLEAR_CTS 0x04
+#define C3_CTUF 0x08
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+inline void mc6852_device::receive()
+{
+}
+
+inline void mc6852_device::transmit()
+{
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// mc6852_device - constructor
+//-------------------------------------------------
+
+mc6852_device::mc6852_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, MC6852, "MC6852", tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void mc6852_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const mc6852_interface *intf = reinterpret_cast<const mc6852_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<mc6852_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_in_rx_data_cb, 0, sizeof(m_in_rx_data_cb));
+ memset(&m_out_tx_data_cb, 0, sizeof(m_out_tx_data_cb));
+ memset(&m_out_irq_cb, 0, sizeof(m_out_irq_cb));
+ memset(&m_in_cts_cb, 0, sizeof(m_in_cts_cb));
+ memset(&m_in_dcd_cb, 0, sizeof(m_in_dcd_cb));
+ memset(&m_out_sm_dtr_cb, 0, sizeof(m_out_sm_dtr_cb));
+ memset(&m_out_tuf_cb, 0, sizeof(m_out_tuf_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mc6852_device::device_start()
+{
+ // resolve callbacks
+ m_in_rx_data_func.resolve(m_in_rx_data_cb, *this);
+ m_out_tx_data_func.resolve(m_out_tx_data_cb, *this);
+ m_out_irq_func.resolve(m_out_irq_cb, *this);
+ m_in_cts_func.resolve(m_in_cts_cb, *this);
+ m_in_dcd_func.resolve(m_in_dcd_cb, *this);
+ m_out_sm_dtr_func.resolve(m_out_sm_dtr_cb, *this);
+ m_out_tuf_func.resolve(m_out_tuf_cb, *this);
+
+ if (m_rx_clock > 0)
+ {
+ m_rx_timer = timer_alloc(TIMER_RX);
+ m_rx_timer->adjust(attotime::zero, 0, attotime::from_hz(m_rx_clock));
+ }
+
+ if (m_tx_clock > 0)
+ {
+ m_tx_timer = timer_alloc(TIMER_TX);
+ m_tx_timer->adjust(attotime::zero, 0, attotime::from_hz(m_tx_clock));
+ }
+
+ // register for state saving
+ save_item(NAME(m_status));
+ save_item(NAME(m_cr));
+ save_item(NAME(m_scr));
+ save_item(NAME(m_rx_fifo));
+ save_item(NAME(m_tx_fifo));
+ save_item(NAME(m_tdr));
+ save_item(NAME(m_tsr));
+ save_item(NAME(m_rdr));
+ save_item(NAME(m_rsr));
+ save_item(NAME(m_cts));
+ save_item(NAME(m_dcd));
+ save_item(NAME(m_sm_dtr));
+ save_item(NAME(m_tuf));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void mc6852_device::device_reset()
+{
+ /* set receiver shift register to all 1's */
+ m_rsr = 0xff;
+
+ /* reset and inhibit receiver/transmitter sections */
+ m_cr[0] |= (C1_TX_RS | C1_RX_RS);
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void mc6852_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case TIMER_RX:
+ receive();
+ break;
+
+ case TIMER_TX:
+ transmit();
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// read -
+//-------------------------------------------------
+
+READ8_MEMBER( mc6852_device::read )
+{
+ UINT8 data = 0;
+
+ if (BIT(offset, 0))
+ {
+ /* receive data FIFO */
+ }
+ else
+ {
+ /* status */
+ data = m_status;
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// write -
+//-------------------------------------------------
+
+WRITE8_MEMBER( mc6852_device::write )
+{
+ if (BIT(offset, 0))
+ {
+ switch (m_cr[0] & C1_AC_MASK)
+ {
+ case C1_AC_C2:
+ /* control 2 */
+ m_cr[1] = data;
+ break;
+
+ case C1_AC_C3:
+ /* control 3 */
+ m_cr[2] = data;
+ break;
+
+ case C1_AC_SYNC:
+ /* sync code */
+ m_scr = data;
+ break;
+
+ case C1_AC_TX_FIFO:
+ /* transmit data FIFO */
+ break;
+ }
+ }
+ else
+ {
+ /* receiver reset */
+ if (data & C1_RX_RS)
+ {
+ /* When Rx Rs is set, it clears the receiver
+ control logic, sync logic, error logic, Rx Data FIFO Control,
+ Parity Error status bit, and DCD interrupt. The Receiver Shift
+ Register is set to ones.
+ */
+
+ if (LOG) logerror("MC6852 '%s' Receiver Reset\n", tag());
+
+ m_status &= ~(S_RX_OVRN | S_PE | S_DCD | S_RDA);
+ m_rsr = 0xff;
+ }
+
+ /* transmitter reset */
+ if (data & C1_TX_RS)
+ {
+ /* When Tx Rs is set, it clears the transmitter
+ control section, Transmitter Shift Register, Tx Data FIFO
+ Control (the Tx Data FIFO can be reloaded after one E clock
+ pulse), the Transmitter Underflow status bit, and the CTS interrupt,
+ and inhibits the TDRA status bit (in the one-sync-character
+ and two-sync-character modes).*/
+
+ if (LOG) logerror("MC6852 '%s' Transmitter Reset\n", tag());
+
+ m_status &= ~(S_TUF | S_CTS | S_TDRA);
+ }
+
+ if (LOG)
+ {
+ if (data & C1_STRIP_SYNC) logerror("MC6852 '%s' Strip Synchronization Characters\n", tag());
+ if (data & C1_CLEAR_SYNC) logerror("MC6852 '%s' Clear Synchronization\n", tag());
+ }
+
+ m_cr[0] = data;
+ }
+}
+
+
+//-------------------------------------------------
+// rx_clk_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( mc6852_device::rx_clk_w )
+{
+ if (state) receive();
+}
+
+
+//-------------------------------------------------
+// tx_clk_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( mc6852_device::tx_clk_w )
+{
+ if (state) transmit();
+}
+
+
+//-------------------------------------------------
+// cts_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( mc6852_device::cts_w )
+{
+ m_cts = state;
+}
+
+
+//-------------------------------------------------
+// dcd_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( mc6852_device::dcd_w )
+{
+ m_dcd = state;
+}
+
+
+//-------------------------------------------------
+// sm_dtr_r -
+//-------------------------------------------------
+
+READ_LINE_MEMBER( mc6852_device::sm_dtr_r )
+{
+ return m_sm_dtr;
+}
+
+
+//-------------------------------------------------
+// tuf_r -
+//-------------------------------------------------
+
+READ_LINE_MEMBER( mc6852_device::tuf_r )
+{
+ return m_tuf;
+}
diff --git a/trunk/src/emu/machine/mc6852.h b/trunk/src/emu/machine/mc6852.h
new file mode 100644
index 00000000000..c0c6090d624
--- /dev/null
+++ b/trunk/src/emu/machine/mc6852.h
@@ -0,0 +1,139 @@
+/**********************************************************************
+
+ Motorola MC6852 Synchronous Serial Data Adapter emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ Vss 1 |* \_/ | 24 _CTS
+ Rx DATA 2 | | 23 _DCD
+ Rx CLK 3 | | 22 D0
+ Tx CLK 4 | | 21 D1
+ SM/_DTR 5 | | 20 D2
+ Tx DATA 6 | MC6852 | 19 D3
+ _IRQ 7 | | 18 D4
+ TUF 8 | | 17 D5
+ _RESET 9 | | 16 D6
+ _CS 9 | | 15 D7
+ RS 9 | | 14 E
+ Vcc 10 |_____________| 13 R/_W
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __MC6852__
+#define __MC6852__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_MC6852_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD((_tag), MC6852, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MC6852_INTERFACE(name) \
+ const mc6852_interface (name) =
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> mc6852_interface
+
+struct mc6852_interface
+{
+ UINT32 m_rx_clock;
+ UINT32 m_tx_clock;
+
+ devcb_read_line m_in_rx_data_cb;
+ devcb_write_line m_out_tx_data_cb;
+
+ devcb_write_line m_out_irq_cb;
+
+ devcb_read_line m_in_cts_cb;
+ devcb_read_line m_in_dcd_cb;
+ devcb_write_line m_out_sm_dtr_cb;
+ devcb_write_line m_out_tuf_cb;
+};
+
+
+// ======================> mc6852_device
+
+class mc6852_device : public device_t,
+ public mc6852_interface
+{
+public:
+ // construction/destruction
+ mc6852_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_READ8_MEMBER( read );
+ DECLARE_WRITE8_MEMBER( write );
+
+ DECLARE_WRITE_LINE_MEMBER( rx_clk_w );
+ DECLARE_WRITE_LINE_MEMBER( tx_clk_w );
+ DECLARE_WRITE_LINE_MEMBER( cts_w );
+ DECLARE_WRITE_LINE_MEMBER( dcd_w );
+
+ DECLARE_READ_LINE_MEMBER( sm_dtr_r );
+ DECLARE_READ_LINE_MEMBER( tuf_r );
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int m_param, void *ptr);
+
+private:
+ static const device_timer_id TIMER_RX = 0;
+ static const device_timer_id TIMER_TX = 1;
+
+ inline void receive();
+ inline void transmit();
+
+ devcb_resolved_read_line m_in_rx_data_func;
+ devcb_resolved_write_line m_out_tx_data_func;
+ devcb_resolved_write_line m_out_irq_func;
+ devcb_resolved_read_line m_in_cts_func;
+ devcb_resolved_read_line m_in_dcd_func;
+ devcb_resolved_write_line m_out_sm_dtr_func;
+ devcb_resolved_write_line m_out_tuf_func;
+
+ // registers
+ UINT8 m_status; // status register
+ UINT8 m_cr[3]; // control registers
+ UINT8 m_scr; // sync code register
+ UINT8 m_rx_fifo[3]; // receiver FIFO
+ UINT8 m_tx_fifo[3]; // transmitter FIFO
+ UINT8 m_tdr; // transmit data register
+ UINT8 m_tsr; // transmit shift register
+ UINT8 m_rdr; // receive data register
+ UINT8 m_rsr; // receive shift register
+
+ int m_cts; // clear to send
+ int m_dcd; // data carrier detect
+ int m_sm_dtr; // sync match/data terminal ready
+ int m_tuf; // transmitter underflow
+
+ // timers
+ emu_timer *m_rx_timer;
+ emu_timer *m_tx_timer;
+};
+
+
+// device type definition
+extern const device_type MC6852;
+
+
+
+#endif
diff --git a/trunk/src/emu/machine/mc68901.c b/trunk/src/emu/machine/mc68901.c
new file mode 100644
index 00000000000..186b705e25b
--- /dev/null
+++ b/trunk/src/emu/machine/mc68901.c
@@ -0,0 +1,1476 @@
+/**********************************************************************
+
+ Motorola MC68901 Multi Function Peripheral emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+/*
+
+ TODO:
+
+ - daisy chaining
+ - disable GPIO3/4 interrupts when timer A/B in pulse mode
+ - spurious interrupt
+
+ If you look at the MFP datasheet it is obvious that it can generate the conditions for a spurious interrupt.
+ However the fact that they indeed happen in the ST is quite interesting.
+
+ The MFP will generate a spurious interrupt if interrupts are disabled (by changing the IERA/IERB registers)
+ at the ???precise point???. The precise point would be after the system (but not necessarily the CPU, see below)
+ triggered an MFP interrupt, and before the CPU drives the interrupt acknowledge cycle.
+
+ If the MFP was connected directly to the CPU, spurious interrupts probably couldn???t happen. However in the
+ ST, GLUE seats in the middle and handles all the interrupt timing. It is possible that GLUE introduces a
+ delay between detecting a change in the MFP interrupt request signal and actually propagating the change to
+ the CPU IPL signals (it is even possible that GLUE make some kind of latching). This would create a window
+ long enough for the ???precise point??? described above.
+
+ "yes, the spurious interrupt occurs when i mask a timer. i did not notice an occurance of the SPI when changing data and control registers.
+ if i kill interrupts with the status reg before masking the timer interrupt, then the SPI occurs as soon as the status register is set to re-enable interrupts."
+
+ - divide serial clock by 16
+ - synchronous mode
+ - 1.5/2 stop bits
+ - interrupt on receiver break end
+ - interrupt on character boundaries during break transmission
+ - loopback mode
+
+*/
+
+#include "emu.h"
+#include "mc68901.h"
+#include "cpu/m68000/m68000.h"
+#include "machine/devhelpr.h"
+
+
+// device type definition
+const device_type MC68901 = &device_creator<mc68901_device>;
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+
+enum
+{
+ REGISTER_GPIP = 0,
+ REGISTER_AER,
+ REGISTER_DDR,
+ REGISTER_IERA,
+ REGISTER_IERB,
+ REGISTER_IPRA,
+ REGISTER_IPRB,
+ REGISTER_ISRA,
+ REGISTER_ISRB,
+ REGISTER_IMRA,
+ REGISTER_IMRB,
+ REGISTER_VR,
+ REGISTER_TACR,
+ REGISTER_TBCR,
+ REGISTER_TCDCR,
+ REGISTER_TADR,
+ REGISTER_TBDR,
+ REGISTER_TCDR,
+ REGISTER_TDDR,
+ REGISTER_SCR,
+ REGISTER_UCR,
+ REGISTER_RSR,
+ REGISTER_TSR,
+ REGISTER_UDR
+};
+
+
+enum
+{
+ INT_GPI0 = 0,
+ INT_GPI1,
+ INT_GPI2,
+ INT_GPI3,
+ INT_TIMER_D,
+ INT_TIMER_C,
+ INT_GPI4,
+ INT_GPI5,
+ INT_TIMER_B,
+ INT_XMIT_ERROR,
+ INT_XMIT_BUFFER_EMPTY,
+ INT_RCV_ERROR,
+ INT_RCV_BUFFER_FULL,
+ INT_TIMER_A,
+ INT_GPI6,
+ INT_GPI7
+};
+
+
+enum
+{
+ GPIP_0 = 0,
+ GPIP_1,
+ GPIP_2,
+ GPIP_3,
+ GPIP_4,
+ GPIP_5,
+ GPIP_6,
+ GPIP_7
+};
+
+
+enum
+{
+ TIMER_A = 0,
+ TIMER_B,
+ TIMER_C,
+ TIMER_D,
+ MAX_TIMERS
+};
+
+
+enum
+{
+ SERIAL_START = 0,
+ SERIAL_DATA,
+ SERIAL_PARITY,
+ SERIAL_STOP
+};
+
+
+enum
+{
+ XMIT_OFF = 0,
+ XMIT_STARTING,
+ XMIT_ON,
+ XMIT_BREAK,
+ XMIT_STOPPING
+};
+
+
+#define AER_GPIP_0 0x01
+#define AER_GPIP_1 0x02
+#define AER_GPIP_2 0x04
+#define AER_GPIP_3 0x08
+#define AER_GPIP_4 0x10
+#define AER_GPIP_5 0x20
+#define AER_GPIP_6 0x40
+#define AER_GPIP_7 0x80
+
+
+#define VR_S 0x08
+
+
+#define IR_GPIP_0 0x0001
+#define IR_GPIP_1 0x0002
+#define IR_GPIP_2 0x0004
+#define IR_GPIP_3 0x0008
+#define IR_TIMER_D 0x0010
+#define IR_TIMER_C 0x0020
+#define IR_GPIP_4 0x0040
+#define IR_GPIP_5 0x0080
+#define IR_TIMER_B 0x0100
+#define IR_XMIT_ERROR 0x0200
+#define IR_XMIT_BUFFER_EMPTY 0x0400
+#define IR_RCV_ERROR 0x0800
+#define IR_RCV_BUFFER_FULL 0x1000
+#define IR_TIMER_A 0x2000
+#define IR_GPIP_6 0x4000
+#define IR_GPIP_7 0x8000
+
+
+#define TCR_TIMER_STOPPED 0x00
+#define TCR_TIMER_DELAY_4 0x01
+#define TCR_TIMER_DELAY_10 0x02
+#define TCR_TIMER_DELAY_16 0x03
+#define TCR_TIMER_DELAY_50 0x04
+#define TCR_TIMER_DELAY_64 0x05
+#define TCR_TIMER_DELAY_100 0x06
+#define TCR_TIMER_DELAY_200 0x07
+#define TCR_TIMER_EVENT 0x08
+#define TCR_TIMER_PULSE_4 0x09
+#define TCR_TIMER_PULSE_10 0x0a
+#define TCR_TIMER_PULSE_16 0x0b
+#define TCR_TIMER_PULSE_50 0x0c
+#define TCR_TIMER_PULSE_64 0x0d
+#define TCR_TIMER_PULSE_100 0x0e
+#define TCR_TIMER_PULSE_200 0x0f
+#define TCR_TIMER_RESET 0x10
+
+
+#define UCR_PARITY_ENABLED 0x04
+#define UCR_PARITY_EVEN 0x02
+#define UCR_PARITY_ODD 0x00
+#define UCR_WORD_LENGTH_8 0x00
+#define UCR_WORD_LENGTH_7 0x20
+#define UCR_WORD_LENGTH_6 0x40
+#define UCR_WORD_LENGTH_5 0x60
+#define UCR_START_STOP_0_0 0x00
+#define UCR_START_STOP_1_1 0x08
+#define UCR_START_STOP_1_15 0x10
+#define UCR_START_STOP_1_2 0x18
+#define UCR_CLOCK_DIVIDE_16 0x80
+#define UCR_CLOCK_DIVIDE_1 0x00
+
+
+#define RSR_RCV_ENABLE 0x01
+#define RSR_SYNC_STRIP_ENABLE 0x02
+#define RSR_MATCH 0x04
+#define RSR_CHAR_IN_PROGRESS 0x04
+#define RSR_FOUND_SEARCH 0x08
+#define RSR_BREAK 0x08
+#define RSR_FRAME_ERROR 0x10
+#define RSR_PARITY_ERROR 0x20
+#define RSR_OVERRUN_ERROR 0x40
+#define RSR_BUFFER_FULL 0x80
+
+#define TSR_XMIT_ENABLE 0x01
+#define TSR_OUTPUT_HI_Z 0x00
+#define TSR_OUTPUT_LOW 0x02
+#define TSR_OUTPUT_HIGH 0x04
+#define TSR_OUTPUT_LOOP 0x06
+#define TSR_OUTPUT_MASK 0x06
+#define TSR_BREAK 0x08
+#define TSR_END_OF_XMIT 0x10
+#define TSR_AUTO_TURNAROUND 0x20
+#define TSR_UNDERRUN_ERROR 0x40
+#define TSR_BUFFER_EMPTY 0x80
+
+
+static const int INT_MASK_GPIO[] =
+{
+ IR_GPIP_0, IR_GPIP_1, IR_GPIP_2, IR_GPIP_3,
+ IR_GPIP_4, IR_GPIP_5, IR_GPIP_6, IR_GPIP_7
+};
+
+
+static const int INT_MASK_TIMER[] =
+{
+ IR_TIMER_A, IR_TIMER_B, IR_TIMER_C, IR_TIMER_D
+};
+
+
+static const int GPIO_TIMER[] =
+{
+ GPIP_4, GPIP_3
+};
+
+
+static const int PRESCALER[] = { 0, 4, 10, 16, 50, 64, 100, 200 };
+
+
+#define TXD(_data) m_out_so_func(_data);
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+inline void mc68901_device::check_interrupts()
+{
+ if (m_ipr & m_imr)
+ {
+ m_out_irq_func(ASSERT_LINE);
+ }
+ else
+ {
+ m_out_irq_func(CLEAR_LINE);
+ }
+}
+
+inline void mc68901_device::take_interrupt(UINT16 mask)
+{
+ m_ipr |= mask;
+
+ check_interrupts();
+}
+
+inline void mc68901_device::rx_buffer_full()
+{
+ if (m_ier & IR_RCV_BUFFER_FULL)
+ {
+ take_interrupt(IR_RCV_BUFFER_FULL);
+ }
+}
+
+inline void mc68901_device::rx_error()
+{
+ if (m_ier & IR_RCV_ERROR)
+ {
+ take_interrupt(IR_RCV_ERROR);
+ }
+ else
+ {
+ rx_buffer_full();
+ }
+}
+
+inline void mc68901_device::tx_buffer_empty()
+{
+ if (m_ier & IR_XMIT_BUFFER_EMPTY)
+ {
+ take_interrupt(IR_XMIT_BUFFER_EMPTY);
+ }
+}
+
+inline void mc68901_device::tx_error()
+{
+ if (m_ier & IR_XMIT_ERROR)
+ {
+ take_interrupt(IR_XMIT_ERROR);
+ }
+ else
+ {
+ tx_buffer_empty();
+ }
+}
+
+inline int mc68901_device::get_parity_bit(UINT8 b)
+{
+ b ^= b >> 4;
+ b ^= b >> 2;
+ b ^= b >> 1;
+ return b & 1;
+}
+
+inline void mc68901_device::serial_receive()
+{
+ int rxd;
+
+ if (!(m_rsr & RSR_RCV_ENABLE)) return;
+
+ rxd = m_in_si_func();
+
+ switch (m_rx_state)
+ {
+ case SERIAL_START:
+ if (!rxd)
+ {
+ m_rsr |= RSR_CHAR_IN_PROGRESS;
+ m_rx_bits = 0;
+ m_rx_buffer = 0;
+ m_rx_state = SERIAL_DATA;
+ m_next_rsr = RSR_BREAK;
+ }
+ break;
+
+ case SERIAL_DATA:
+ if ((m_next_rsr & RSR_BREAK) && (rxd == 1) && m_rsr_read)
+ {
+ m_next_rsr &= ~RSR_BREAK;
+ }
+
+ m_rx_buffer >>= 1;
+ m_rx_buffer |= (rxd << 7);
+ m_rx_bits++;
+
+ if (m_rx_bits == m_rxtx_word)
+ {
+ if (m_rxtx_word < 8)
+ {
+ m_rx_buffer >>= (8 - m_rxtx_word);
+ }
+
+ m_rsr &= ~RSR_CHAR_IN_PROGRESS;
+
+ if (m_ucr & UCR_PARITY_ENABLED)
+ {
+ m_rx_state = SERIAL_PARITY;
+ }
+ else
+ {
+ m_rx_state = SERIAL_STOP;
+ }
+ }
+ break;
+
+ case SERIAL_PARITY:
+ m_rx_parity = rxd;
+
+ if (m_rx_parity != (get_parity_bit(m_rx_buffer) ^ ((m_ucr & UCR_PARITY_EVEN) >> 1)))
+ {
+ m_next_rsr |= RSR_PARITY_ERROR;
+ }
+
+ m_rx_state = SERIAL_STOP;
+ break;
+
+ case SERIAL_STOP:
+ if (rxd == 1)
+ {
+ if (!((m_rsr & RSR_SYNC_STRIP_ENABLE) && (m_rx_buffer == m_scr)))
+ {
+ if (!(m_rsr & RSR_OVERRUN_ERROR))
+ {
+ if (m_rsr & RSR_BUFFER_FULL)
+ {
+ // incoming word received but last word in receive buffer has not been read
+ m_next_rsr |= RSR_OVERRUN_ERROR;
+ }
+ else
+ {
+ // incoming word received and receive buffer is empty
+ m_rsr |= RSR_BUFFER_FULL;
+ m_udr = m_rx_buffer;
+ rx_buffer_full();
+ }
+ }
+ }
+ }
+ else
+ {
+ if (m_rx_buffer)
+ {
+ // non-zero data word not followed by a stop bit
+ m_next_rsr |= RSR_FRAME_ERROR;
+ }
+ }
+
+ m_rx_state = SERIAL_START;
+ break;
+ }
+}
+
+
+inline void mc68901_device::tx_disabled()
+{
+ switch (m_tsr & TSR_OUTPUT_MASK)
+ {
+ case TSR_OUTPUT_HI_Z:
+ /* indeterminate state */
+ case TSR_OUTPUT_LOW:
+ TXD(0);
+ break;
+
+ case TSR_OUTPUT_HIGH:
+ case TSR_OUTPUT_LOOP:
+ TXD(1);
+ break;
+ }
+}
+
+
+inline void mc68901_device::tx_starting()
+{
+ if (m_tsr & TSR_XMIT_ENABLE)
+ {
+ /* enable transmitter */
+ TXD(1);
+ m_xmit_state = XMIT_ON;
+ }
+ else
+ {
+ /* disable transmitter */
+ m_tsr |= TSR_END_OF_XMIT;
+ m_xmit_state = XMIT_OFF;
+ }
+}
+
+
+inline void mc68901_device::tx_break()
+{
+ if (m_tsr & TSR_XMIT_ENABLE)
+ {
+ if (m_tsr & TSR_BREAK)
+ {
+ /* transmit break */
+ TXD(1);
+ }
+ else
+ {
+ /* enable transmitter */
+ m_xmit_state = XMIT_ON;
+ }
+ }
+ else
+ {
+ /* disable transmitter */
+ m_tsr |= TSR_END_OF_XMIT;
+ m_xmit_state = XMIT_OFF;
+ }
+}
+
+
+inline void mc68901_device::tx_enabled()
+{
+ switch (m_tx_state)
+ {
+ case SERIAL_START:
+ if (m_tsr & TSR_UNDERRUN_ERROR)
+ {
+ /* buffer underrun condition */
+ if (m_tsr & TSR_XMIT_ENABLE)
+ {
+ /* transmit break */
+ TXD(1);
+ }
+ else
+ {
+ /* transmitter disabled */
+ tx_disabled();
+ }
+ }
+ else
+ {
+ if (m_tsr & TSR_BUFFER_EMPTY)
+ {
+ /* transmit buffer is empty, signal underrun error */
+ m_tsr |= TSR_UNDERRUN_ERROR;
+
+ if (m_tsr & TSR_XMIT_ENABLE)
+ {
+ /* transmit break */
+ TXD(1);
+ }
+ else
+ {
+ /* transmitter disabled */
+ tx_disabled();
+ }
+ }
+ else
+ {
+ /* transmit start bit */
+ TXD(0);
+
+ /* load transmit buffer */
+ m_tx_buffer = m_udr;
+ m_tx_bits = 0;
+
+ /* signal transmit buffer empty */
+ m_tsr |= TSR_BUFFER_EMPTY;
+ tx_buffer_empty();
+
+ /* calculate parity */
+ m_tx_parity = get_parity_bit(m_tx_buffer);
+
+ /* next bit is data */
+ m_tx_state = SERIAL_DATA;
+ }
+ }
+ break;
+
+ case SERIAL_DATA:
+ /* transmit data bit */
+ TXD(m_tx_buffer & 0x01);
+
+ /* shift transmit buffer */
+ m_tx_buffer >>= 1;
+ m_tx_bits++;
+
+ if (m_tx_bits == m_rxtx_word)
+ {
+ /* all data bits transferred */
+ if (m_ucr & UCR_PARITY_ENABLED)
+ {
+ /* next bit is parity */
+ m_tx_state = SERIAL_PARITY;
+ }
+ else
+ {
+ /* next bit is stop */
+ m_tx_state = SERIAL_STOP;
+ }
+ }
+ break;
+
+ case SERIAL_PARITY:
+ if (m_rxtx_word < 8)
+ {
+ /* transmit user-defined parity bit from buffer */
+ TXD(m_tx_buffer & 0x01);
+ }
+ else
+ {
+ /* transmit calculated parity bit */
+ TXD(m_tx_parity ^ ((m_ucr & UCR_PARITY_EVEN) >> 1));
+ }
+
+ /* next bit is stop */
+ m_tx_state = SERIAL_STOP;
+ break;
+
+ case SERIAL_STOP:
+ /* transmit stop bit */
+ TXD(1);
+
+ if (m_tsr & TSR_XMIT_ENABLE)
+ {
+ /* next bit is start */
+ m_tx_state = SERIAL_START;
+ }
+ else
+ {
+ if (m_tsr & TSR_AUTO_TURNAROUND)
+ {
+ /* enable transmitter */
+ m_tsr |= TSR_XMIT_ENABLE;
+
+ /* next bit is start */
+ m_tx_state = SERIAL_START;
+ }
+ else
+ {
+ /* disable transmitter */
+ m_xmit_state = XMIT_OFF;
+ m_tsr |= TSR_END_OF_XMIT;
+
+ /* signal transmit error */
+ tx_error();
+ }
+ }
+ break;
+ }
+}
+
+inline void mc68901_device::serial_transmit()
+{
+ switch (m_xmit_state)
+ {
+ case XMIT_OFF: tx_disabled(); break;
+ case XMIT_STARTING: tx_starting(); break;
+ case XMIT_BREAK: tx_break(); break;
+ case XMIT_ON: tx_enabled(); break;
+ }
+}
+
+
+inline void mc68901_device::timer_count(int index)
+{
+ if (m_tmc[index] == 0x01)
+ {
+ /* toggle timer output signal */
+ m_to[index] = !m_to[index];
+
+ switch (index)
+ {
+ case TIMER_A: m_out_tao_func(m_to[index]); break;
+ case TIMER_B: m_out_tbo_func(m_to[index]); break;
+ case TIMER_C: m_out_tco_func(m_to[index]); break;
+ case TIMER_D: m_out_tdo_func(m_to[index]); break;
+ }
+
+ if (m_ier & INT_MASK_TIMER[index])
+ {
+ /* signal timer elapsed interrupt */
+ take_interrupt(INT_MASK_TIMER[index]);
+ }
+
+ /* load main counter */
+ m_tmc[index] = m_tdr[index];
+ }
+ else
+ {
+ /* count down */
+ m_tmc[index]--;
+ }
+}
+
+
+inline void mc68901_device::timer_input(int index, int value)
+{
+ int bit = GPIO_TIMER[index];
+ int aer = BIT(m_aer, bit);
+ int cr = index ? m_tbcr : m_tacr;
+
+ switch (cr & 0x0f)
+ {
+ case TCR_TIMER_EVENT:
+ if (((m_ti[index] ^ aer) == 1) && ((value ^ aer) == 0))
+ {
+ timer_count(index);
+ }
+
+ m_ti[index] = value;
+ break;
+
+ case TCR_TIMER_PULSE_4:
+ case TCR_TIMER_PULSE_10:
+ case TCR_TIMER_PULSE_16:
+ case TCR_TIMER_PULSE_50:
+ case TCR_TIMER_PULSE_64:
+ case TCR_TIMER_PULSE_100:
+ case TCR_TIMER_PULSE_200:
+ m_timer[index]->enable((value == aer));
+
+ if (((m_ti[index] ^ aer) == 0) && ((value ^ aer) == 1))
+ {
+ if (m_ier & INT_MASK_GPIO[bit])
+ {
+ take_interrupt(INT_MASK_GPIO[bit]);
+ }
+ }
+
+ m_ti[index] = value;
+ break;
+ }
+}
+
+
+inline void mc68901_device::gpio_input(int bit, int state)
+{
+ if (BIT(m_gpip, bit) && !state) // if transition from 1 to 0 is detected...
+ {
+ if (LOG) logerror("MC68901 '%s' Edge Transition Detected on GPIO%u\n", tag(), bit);
+
+ if (m_ier & INT_MASK_GPIO[bit]) // AND interrupt enabled bit is set...
+ {
+ if (LOG) logerror("MC68901 '%s' Interrupt Pending for GPIO%u\n", tag(), bit);
+
+ take_interrupt(INT_MASK_GPIO[bit]); // set interrupt pending bit
+ }
+ }
+
+ m_gpip &= ((1 << bit) ^ 0xff);
+ m_gpip |= (state << bit);
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// mc68901_device - constructor
+//-------------------------------------------------
+
+mc68901_device::mc68901_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, MC68901, "Motorola MC68901", tag, owner, clock),
+ m_gpip(0),
+ m_tsr(TSR_BUFFER_EMPTY)
+{
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void mc68901_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const mc68901_interface *intf = reinterpret_cast<const mc68901_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<mc68901_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+// memset(&in_pa_cb, 0, sizeof(in_pa_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mc68901_device::device_start()
+{
+ /* resolve callbacks */
+ m_in_gpio_func.resolve(m_in_gpio_cb, *this);
+ m_out_gpio_func.resolve(m_out_gpio_cb, *this);
+ m_in_si_func.resolve(m_in_si_cb, *this);
+ m_out_so_func.resolve(m_out_so_cb, *this);
+ m_out_tao_func.resolve(m_out_tao_cb, *this);
+ m_out_tbo_func.resolve(m_out_tbo_cb, *this);
+ m_out_tco_func.resolve(m_out_tco_cb, *this);
+ m_out_tdo_func.resolve(m_out_tdo_cb, *this);
+ m_out_irq_func.resolve(m_out_irq_cb, *this);
+
+ /* create the timers */
+ m_timer[TIMER_A] = timer_alloc(TIMER_A);
+ m_timer[TIMER_B] = timer_alloc(TIMER_B);
+ m_timer[TIMER_C] = timer_alloc(TIMER_C);
+ m_timer[TIMER_D] = timer_alloc(TIMER_D);
+
+ if (m_rx_clock > 0)
+ {
+ m_rx_timer = timer_alloc(TIMER_RX);
+ m_rx_timer->adjust(attotime::zero, 0, attotime::from_hz(m_rx_clock));
+ }
+
+ if (m_tx_clock > 0)
+ {
+ m_tx_timer = timer_alloc(TIMER_TX);
+ m_tx_timer->adjust(attotime::zero, 0, attotime::from_hz(m_tx_clock));
+ }
+
+ /* register for state saving */
+ save_item(NAME(m_gpip));
+ save_item(NAME(m_aer));
+ save_item(NAME(m_ddr));
+ save_item(NAME(m_ier));
+ save_item(NAME(m_ipr));
+ save_item(NAME(m_isr));
+ save_item(NAME(m_imr));
+ save_item(NAME(m_vr));
+ save_item(NAME(m_tacr));
+ save_item(NAME(m_tbcr));
+ save_item(NAME(m_tcdcr));
+ save_item(NAME(m_tdr));
+ save_item(NAME(m_tmc));
+ save_item(NAME(m_to));
+ save_item(NAME(m_ti));
+ save_item(NAME(m_scr));
+ save_item(NAME(m_ucr));
+ save_item(NAME(m_rsr));
+ save_item(NAME(m_tsr));
+ save_item(NAME(m_udr));
+ save_item(NAME(m_rx_bits));
+ save_item(NAME(m_tx_bits));
+ save_item(NAME(m_rx_parity));
+ save_item(NAME(m_tx_parity));
+ save_item(NAME(m_rx_state));
+ save_item(NAME(m_tx_state));
+ save_item(NAME(m_rx_buffer));
+ save_item(NAME(m_tx_buffer));
+ save_item(NAME(m_xmit_state));
+ save_item(NAME(m_rxtx_word));
+ save_item(NAME(m_rxtx_start));
+ save_item(NAME(m_rxtx_stop));
+ save_item(NAME(m_rsr_read));
+ save_item(NAME(m_next_rsr));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void mc68901_device::device_reset()
+{
+ m_xmit_state = XMIT_OFF;
+ m_rx_state = SERIAL_STOP;
+ m_rx_buffer = 0;
+ m_tx_buffer = 0;
+
+ // Avoid read-before-write
+ m_ipr = m_imr = 0;
+
+ register_w(REGISTER_GPIP, 0);
+ register_w(REGISTER_AER, 0);
+ register_w(REGISTER_DDR, 0);
+ register_w(REGISTER_IERA, 0);
+ register_w(REGISTER_IERB, 0);
+ register_w(REGISTER_IPRA, 0);
+ register_w(REGISTER_IPRB, 0);
+ register_w(REGISTER_ISRA, 0);
+ register_w(REGISTER_ISRB, 0);
+ register_w(REGISTER_IMRA, 0);
+ register_w(REGISTER_IMRB, 0);
+ register_w(REGISTER_VR, 0);
+ register_w(REGISTER_TACR, 0);
+ register_w(REGISTER_TBCR, 0);
+ register_w(REGISTER_TCDCR, 0);
+ register_w(REGISTER_SCR, 0);
+ register_w(REGISTER_UCR, 0);
+ register_w(REGISTER_RSR, 0);
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void mc68901_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case TIMER_RX:
+ serial_receive();
+ break;
+
+ case TIMER_TX:
+ serial_transmit();
+ break;
+
+ default:
+ timer_count(id);
+ break;
+ }
+}
+
+
+
+READ8_MEMBER( mc68901_device::read )
+{
+ switch (offset)
+ {
+ case REGISTER_GPIP:
+ m_gpip = m_in_gpio_func(0);
+ return m_gpip;
+
+ case REGISTER_AER: return m_aer;
+ case REGISTER_DDR: return m_ddr;
+
+ case REGISTER_IERA: return m_ier >> 8;
+ case REGISTER_IERB: return m_ier & 0xff;
+ case REGISTER_IPRA: return m_ipr >> 8;
+ case REGISTER_IPRB: return m_ipr & 0xff;
+ case REGISTER_ISRA: return m_isr >> 8;
+ case REGISTER_ISRB: return m_isr & 0xff;
+ case REGISTER_IMRA: return m_imr >> 8;
+ case REGISTER_IMRB: return m_imr & 0xff;
+ case REGISTER_VR: return m_vr;
+
+ case REGISTER_TACR: return m_tacr;
+ case REGISTER_TBCR: return m_tbcr;
+ case REGISTER_TCDCR: return m_tcdcr;
+ case REGISTER_TADR: return m_tmc[TIMER_A];
+ case REGISTER_TBDR: return m_tmc[TIMER_B];
+ case REGISTER_TCDR: return m_tmc[TIMER_C];
+ case REGISTER_TDDR: return m_tmc[TIMER_D];
+
+ case REGISTER_SCR: return m_scr;
+ case REGISTER_UCR: return m_ucr;
+ case REGISTER_RSR:
+ m_rsr_read = 1;
+ return m_rsr;
+
+ case REGISTER_TSR:
+ {
+ /* clear UE bit (in reality, this won't be cleared until one full clock cycle of the transmitter has passed since the bit was set) */
+ UINT8 tsr = m_tsr;
+ m_tsr &= 0xbf;
+
+ return tsr;
+ }
+
+ case REGISTER_UDR:
+ /* load RSR with latched value */
+ m_rsr = (m_next_rsr & 0x7c) | (m_rsr & 0x03);
+ m_next_rsr = 0;
+
+ if (m_rsr & 0x78)
+ {
+ /* signal receiver error interrupt */
+ rx_error();
+ }
+
+ return m_udr;
+
+ default: return 0;
+ }
+}
+
+
+#define DIVISOR PRESCALER[data & 0x07]
+
+void mc68901_device::register_w(offs_t offset, UINT8 data)
+{
+ switch (offset)
+ {
+ case REGISTER_GPIP:
+ if (LOG) logerror("MC68901 '%s' General Purpose I/O : %x\n", tag(), data);
+ m_gpip = data & m_ddr;
+
+ m_out_gpio_func(0, m_gpip);
+ break;
+
+ case REGISTER_AER:
+ if (LOG) logerror("MC68901 '%s' Active Edge Register : %x\n", tag(), data);
+ m_aer = data;
+ break;
+
+ case REGISTER_DDR:
+ if (LOG) logerror("MC68901 '%s' Data Direction Register : %x\n", tag(), data);
+ m_ddr = data;
+ break;
+
+ case REGISTER_IERA:
+ if (LOG) logerror("MC68901 '%s' Interrupt Enable Register A : %x\n", tag(), data);
+ m_ier = (data << 8) | (m_ier & 0xff);
+ m_ipr &= m_ier;
+ check_interrupts();
+ break;
+
+ case REGISTER_IERB:
+ if (LOG) logerror("MC68901 '%s' Interrupt Enable Register B : %x\n", tag(), data);
+ m_ier = (m_ier & 0xff00) | data;
+ m_ipr &= m_ier;
+ check_interrupts();
+ break;
+
+ case REGISTER_IPRA:
+ if (LOG) logerror("MC68901 '%s' Interrupt Pending Register A : %x\n", tag(), data);
+ m_ipr &= (data << 8) | (m_ipr & 0xff);
+ check_interrupts();
+ break;
+
+ case REGISTER_IPRB:
+ if (LOG) logerror("MC68901 '%s' Interrupt Pending Register B : %x\n", tag(), data);
+ m_ipr &= (m_ipr & 0xff00) | data;
+ check_interrupts();
+ break;
+
+ case REGISTER_ISRA:
+ if (LOG) logerror("MC68901 '%s' Interrupt In-Service Register A : %x\n", tag(), data);
+ m_isr &= (data << 8) | (m_isr & 0xff);
+ break;
+
+ case REGISTER_ISRB:
+ if (LOG) logerror("MC68901 '%s' Interrupt In-Service Register B : %x\n", tag(), data);
+ m_isr &= (m_isr & 0xff00) | data;
+ break;
+
+ case REGISTER_IMRA:
+ if (LOG) logerror("MC68901 '%s' Interrupt Mask Register A : %x\n", tag(), data);
+ m_imr = (data << 8) | (m_imr & 0xff);
+ m_isr &= m_imr;
+ check_interrupts();
+ break;
+
+ case REGISTER_IMRB:
+ if (LOG) logerror("MC68901 '%s' Interrupt Mask Register B : %x\n", tag(), data);
+ m_imr = (m_imr & 0xff00) | data;
+ m_isr &= m_imr;
+ check_interrupts();
+ break;
+
+ case REGISTER_VR:
+ if (LOG) logerror("MC68901 '%s' Interrupt Vector : %x\n", tag(), data & 0xf0);
+
+ m_vr = data & 0xf8;
+
+ if (m_vr & VR_S)
+ {
+ if (LOG) logerror("MC68901 '%s' Software End-Of-Interrupt Mode\n", tag());
+ }
+ else
+ {
+ if (LOG) logerror("MC68901 '%s' Automatic End-Of-Interrupt Mode\n", tag());
+
+ m_isr = 0;
+ }
+ break;
+
+ case REGISTER_TACR:
+ m_tacr = data & 0x1f;
+
+ switch (m_tacr & 0x0f)
+ {
+ case TCR_TIMER_STOPPED:
+ if (LOG) logerror("MC68901 '%s' Timer A Stopped\n", tag());
+ m_timer[TIMER_A]->enable(false);
+ break;
+
+ case TCR_TIMER_DELAY_4:
+ case TCR_TIMER_DELAY_10:
+ case TCR_TIMER_DELAY_16:
+ case TCR_TIMER_DELAY_50:
+ case TCR_TIMER_DELAY_64:
+ case TCR_TIMER_DELAY_100:
+ case TCR_TIMER_DELAY_200:
+ {
+ int divisor = PRESCALER[m_tacr & 0x07];
+ if (LOG) logerror("MC68901 '%s' Timer A Delay Mode : %u Prescale\n", tag(), divisor);
+ m_timer[TIMER_A]->adjust(attotime::from_hz(m_timer_clock / divisor), 0, attotime::from_hz(m_timer_clock / divisor));
+ }
+ break;
+
+ case TCR_TIMER_EVENT:
+ if (LOG) logerror("MC68901 '%s' Timer A Event Count Mode\n", tag());
+ m_timer[TIMER_A]->enable(false);
+ break;
+
+ case TCR_TIMER_PULSE_4:
+ case TCR_TIMER_PULSE_10:
+ case TCR_TIMER_PULSE_16:
+ case TCR_TIMER_PULSE_50:
+ case TCR_TIMER_PULSE_64:
+ case TCR_TIMER_PULSE_100:
+ case TCR_TIMER_PULSE_200:
+ {
+ int divisor = PRESCALER[m_tacr & 0x07];
+ if (LOG) logerror("MC68901 '%s' Timer A Pulse Width Mode : %u Prescale\n", tag(), divisor);
+ m_timer[TIMER_A]->adjust(attotime::never, 0, attotime::from_hz(m_timer_clock / divisor));
+ m_timer[TIMER_A]->enable(false);
+ }
+ break;
+ }
+
+ if (m_tacr & TCR_TIMER_RESET)
+ {
+ if (LOG) logerror("MC68901 '%s' Timer A Reset\n", tag());
+
+ m_to[TIMER_A] = 0;
+
+ m_out_tao_func(m_to[TIMER_A]);
+ }
+ break;
+
+ case REGISTER_TBCR:
+ m_tbcr = data & 0x1f;
+
+ switch (m_tbcr & 0x0f)
+ {
+ case TCR_TIMER_STOPPED:
+ if (LOG) logerror("MC68901 '%s' Timer B Stopped\n", tag());
+ m_timer[TIMER_B]->enable(false);
+ break;
+
+ case TCR_TIMER_DELAY_4:
+ case TCR_TIMER_DELAY_10:
+ case TCR_TIMER_DELAY_16:
+ case TCR_TIMER_DELAY_50:
+ case TCR_TIMER_DELAY_64:
+ case TCR_TIMER_DELAY_100:
+ case TCR_TIMER_DELAY_200:
+ {
+ int divisor = PRESCALER[m_tbcr & 0x07];
+ if (LOG) logerror("MC68901 '%s' Timer B Delay Mode : %u Prescale\n", tag(), divisor);
+ m_timer[TIMER_B]->adjust(attotime::from_hz(m_timer_clock / divisor), 0, attotime::from_hz(m_timer_clock / divisor));
+ }
+ break;
+
+ case TCR_TIMER_EVENT:
+ if (LOG) logerror("MC68901 '%s' Timer B Event Count Mode\n", tag());
+ m_timer[TIMER_B]->enable(false);
+ break;
+
+ case TCR_TIMER_PULSE_4:
+ case TCR_TIMER_PULSE_10:
+ case TCR_TIMER_PULSE_16:
+ case TCR_TIMER_PULSE_50:
+ case TCR_TIMER_PULSE_64:
+ case TCR_TIMER_PULSE_100:
+ case TCR_TIMER_PULSE_200:
+ {
+ int divisor = PRESCALER[m_tbcr & 0x07];
+ if (LOG) logerror("MC68901 '%s' Timer B Pulse Width Mode : %u Prescale\n", tag(), DIVISOR);
+ m_timer[TIMER_B]->adjust(attotime::never, 0, attotime::from_hz(m_timer_clock / divisor));
+ m_timer[TIMER_B]->enable(false);
+ }
+ break;
+ }
+
+ if (m_tacr & TCR_TIMER_RESET)
+ {
+ if (LOG) logerror("MC68901 '%s' Timer B Reset\n", tag());
+
+ m_to[TIMER_B] = 0;
+
+ m_out_tbo_func(m_to[TIMER_B]);
+ }
+ break;
+
+ case REGISTER_TCDCR:
+ m_tcdcr = data & 0x6f;
+
+ switch (m_tcdcr & 0x07)
+ {
+ case TCR_TIMER_STOPPED:
+ if (LOG) logerror("MC68901 '%s' Timer D Stopped\n", tag());
+ m_timer[TIMER_D]->enable(false);
+ break;
+
+ case TCR_TIMER_DELAY_4:
+ case TCR_TIMER_DELAY_10:
+ case TCR_TIMER_DELAY_16:
+ case TCR_TIMER_DELAY_50:
+ case TCR_TIMER_DELAY_64:
+ case TCR_TIMER_DELAY_100:
+ case TCR_TIMER_DELAY_200:
+ {
+ int divisor = PRESCALER[m_tcdcr & 0x07];
+ if (LOG) logerror("MC68901 '%s' Timer D Delay Mode : %u Prescale\n", tag(), divisor);
+ m_timer[TIMER_D]->adjust(attotime::from_hz(m_timer_clock / divisor), 0, attotime::from_hz(m_timer_clock / divisor));
+ }
+ break;
+ }
+
+ switch ((m_tcdcr >> 4) & 0x07)
+ {
+ case TCR_TIMER_STOPPED:
+ if (LOG) logerror("MC68901 '%s' Timer C Stopped\n", tag());
+ m_timer[TIMER_C]->enable(false);
+ break;
+
+ case TCR_TIMER_DELAY_4:
+ case TCR_TIMER_DELAY_10:
+ case TCR_TIMER_DELAY_16:
+ case TCR_TIMER_DELAY_50:
+ case TCR_TIMER_DELAY_64:
+ case TCR_TIMER_DELAY_100:
+ case TCR_TIMER_DELAY_200:
+ {
+ int divisor = PRESCALER[(m_tcdcr >> 4) & 0x07];
+ if (LOG) logerror("MC68901 '%s' Timer C Delay Mode : %u Prescale\n", tag(), divisor);
+ m_timer[TIMER_C]->adjust(attotime::from_hz(m_timer_clock / divisor), 0, attotime::from_hz(m_timer_clock / divisor));
+ }
+ break;
+ }
+ break;
+
+ case REGISTER_TADR:
+ if (LOG) logerror("MC68901 '%s' Timer A Data Register : %x\n", tag(), data);
+
+ m_tdr[TIMER_A] = data;
+
+ if (!m_timer[TIMER_A]->enabled())
+ {
+ m_tmc[TIMER_A] = data;
+ }
+ break;
+
+ case REGISTER_TBDR:
+ if (LOG) logerror("MC68901 '%s' Timer B Data Register : %x\n", tag(), data);
+
+ m_tdr[TIMER_B] = data;
+
+ if (!m_timer[TIMER_B]->enabled())
+ {
+ m_tmc[TIMER_B] = data;
+ }
+ break;
+
+ case REGISTER_TCDR:
+ if (LOG) logerror("MC68901 '%s' Timer C Data Register : %x\n", tag(), data);
+
+ m_tdr[TIMER_C] = data;
+
+ if (!m_timer[TIMER_C]->enabled())
+ {
+ m_tmc[TIMER_C] = data;
+ }
+ break;
+
+ case REGISTER_TDDR:
+ if (LOG) logerror("MC68901 '%s' Timer D Data Register : %x\n", tag(), data);
+
+ m_tdr[TIMER_D] = data;
+
+ if (!m_timer[TIMER_D]->enabled())
+ {
+ m_tmc[TIMER_D] = data;
+ }
+ break;
+
+ case REGISTER_SCR:
+ if (LOG) logerror("MC68901 '%s' Sync Character : %x\n", tag(), data);
+
+ m_scr = data;
+ break;
+
+ case REGISTER_UCR:
+ if (data & UCR_PARITY_ENABLED)
+ {
+ if (data & UCR_PARITY_EVEN)
+ {
+ if (LOG) logerror("MC68901 '%s' Parity : Even\n", tag());
+ }
+ else
+ {
+ if (LOG) logerror("MC68901 '%s' Parity : Odd\n", tag());
+ }
+ }
+ else
+ {
+ if (LOG) logerror("MC68901 '%s' Parity : Disabled\n", tag());
+ }
+
+ switch (data & 0x60)
+ {
+ case UCR_WORD_LENGTH_8: m_rxtx_word = 8; break;
+ case UCR_WORD_LENGTH_7: m_rxtx_word = 7; break;
+ case UCR_WORD_LENGTH_6: m_rxtx_word = 6; break;
+ case UCR_WORD_LENGTH_5: m_rxtx_word = 5; break;
+ }
+
+ if (LOG) logerror("MC68901 '%s' Word Length : %u bits\n", tag(), m_rxtx_word);
+
+ switch (data & 0x18)
+ {
+ case UCR_START_STOP_0_0:
+ m_rxtx_start = 0;
+ m_rxtx_stop = 0;
+ if (LOG) logerror("MC68901 '%s' Start Bits : 0, Stop Bits : 0, Format : synchronous\n", tag());
+ break;
+ case UCR_START_STOP_1_1:
+ m_rxtx_start = 1;
+ m_rxtx_stop = 1;
+ if (LOG) logerror("MC68901 '%s' Start Bits : 1, Stop Bits : 1, Format : asynchronous\n", tag());
+ break;
+ case UCR_START_STOP_1_15:
+ m_rxtx_start = 1;
+ m_rxtx_stop = 1;
+ if (LOG) logerror("MC68901 '%s' Start Bits : 1, Stop Bits : 1??, Format : asynchronous\n", tag());
+ break;
+ case UCR_START_STOP_1_2:
+ m_rxtx_start = 1;
+ m_rxtx_stop = 2;
+ if (LOG) logerror("MC68901 '%s' Start Bits : 1, Stop Bits : 2, Format : asynchronous\n", tag());
+ break;
+ }
+
+ if (data & UCR_CLOCK_DIVIDE_16)
+ {
+ if (LOG) logerror("MC68901 '%s' Rx/Tx Clock Divisor : 16\n", tag());
+ }
+ else
+ {
+ if (LOG) logerror("MC68901 '%s' Rx/Tx Clock Divisor : 1\n", tag());
+ }
+
+ m_ucr = data;
+ break;
+
+ case REGISTER_RSR:
+ if ((data & RSR_RCV_ENABLE) == 0)
+ {
+ if (LOG) logerror("MC68901 '%s' Receiver Disabled\n", tag());
+ m_rsr = 0;
+ }
+ else
+ {
+ if (LOG) logerror("MC68901 '%s' Receiver Enabled\n", tag());
+
+ if (data & RSR_SYNC_STRIP_ENABLE)
+ {
+ if (LOG) logerror("MC68901 '%s' Sync Strip Enabled\n", tag());
+ }
+ else
+ {
+ if (LOG) logerror("MC68901 '%s' Sync Strip Disabled\n", tag());
+ }
+
+ if (data & RSR_FOUND_SEARCH)
+ if (LOG) logerror("MC68901 '%s' Receiver Search Mode Enabled\n", tag());
+
+ m_rsr = data & 0x0b;
+ }
+ break;
+
+ case REGISTER_TSR:
+ if ((data & TSR_XMIT_ENABLE) == 0)
+ {
+ if (LOG) logerror("MC68901 '%s' Transmitter Disabled\n", tag());
+
+ m_tsr = data & 0x27;
+ }
+ else
+ {
+ if (LOG) logerror("MC68901 '%s' Transmitter Enabled\n", tag());
+
+ switch (data & 0x06)
+ {
+ case TSR_OUTPUT_HI_Z:
+ if (LOG) logerror("MC68901 '%s' Transmitter Disabled Output State : Hi-Z\n", tag());
+ break;
+ case TSR_OUTPUT_LOW:
+ if (LOG) logerror("MC68901 '%s' Transmitter Disabled Output State : 0\n", tag());
+ break;
+ case TSR_OUTPUT_HIGH:
+ if (LOG) logerror("MC68901 '%s' Transmitter Disabled Output State : 1\n", tag());
+ break;
+ case TSR_OUTPUT_LOOP:
+ if (LOG) logerror("MC68901 '%s' Transmitter Disabled Output State : Loop\n", tag());
+ break;
+ }
+
+ if (data & TSR_BREAK)
+ {
+ if (LOG) logerror("MC68901 '%s' Transmitter Break Enabled\n", tag());
+ }
+ else
+ {
+ if (LOG) logerror("MC68901 '%s' Transmitter Break Disabled\n", tag());
+ }
+
+ if (data & TSR_AUTO_TURNAROUND)
+ {
+ if (LOG) logerror("MC68901 '%s' Transmitter Auto Turnaround Enabled\n", tag());
+ }
+ else
+ {
+ if (LOG) logerror("MC68901 '%s' Transmitter Auto Turnaround Disabled\n", tag());
+ }
+
+ m_tsr = data & 0x2f;
+ m_tsr |= TSR_BUFFER_EMPTY; // x68000 expects the buffer to be empty, so this will do for now
+ }
+ break;
+
+ case REGISTER_UDR:
+ if (LOG) logerror("MC68901 '%s' UDR %x\n", tag(), data);
+ m_udr = data;
+ //m_tsr &= ~TSR_BUFFER_EMPTY;
+ break;
+ }
+}
+
+WRITE8_MEMBER( mc68901_device::write )
+{
+ register_w(offset, data);
+}
+
+
+int mc68901_device::get_vector()
+{
+ int ch;
+
+ for (ch = 15; ch >= 0; ch--)
+ {
+ if (BIT(m_imr, ch) && BIT(m_ipr, ch))
+ {
+ if (m_vr & VR_S)
+ {
+ /* set interrupt-in-service bit */
+ m_isr |= (1 << ch);
+ }
+
+ /* clear interrupt pending bit */
+ m_ipr &= ~(1 << ch);
+
+ check_interrupts();
+
+ return (m_vr & 0xf0) | ch;
+ }
+ }
+
+ return M68K_INT_ACK_SPURIOUS;
+}
+
+WRITE_LINE_MEMBER( mc68901_device::i0_w ) { gpio_input(0, state); }
+WRITE_LINE_MEMBER( mc68901_device::i1_w ) { gpio_input(1, state); }
+WRITE_LINE_MEMBER( mc68901_device::i2_w ) { gpio_input(2, state); }
+WRITE_LINE_MEMBER( mc68901_device::i3_w ) { gpio_input(3, state); }
+WRITE_LINE_MEMBER( mc68901_device::i4_w ) { gpio_input(4, state); }
+WRITE_LINE_MEMBER( mc68901_device::i5_w ) { gpio_input(5, state); }
+WRITE_LINE_MEMBER( mc68901_device::i6_w ) { gpio_input(6, state); }
+WRITE_LINE_MEMBER( mc68901_device::i7_w ) { gpio_input(7, state); }
+
+
+WRITE_LINE_MEMBER( mc68901_device::tai_w )
+{
+ timer_input(TIMER_A, state);
+}
+
+
+WRITE_LINE_MEMBER( mc68901_device::tbi_w )
+{
+ timer_input(TIMER_B, state);
+}
+
+
+WRITE_LINE_MEMBER( mc68901_device::rc_w )
+{
+ if (state)
+ {
+ serial_receive();
+ }
+}
+
+
+WRITE_LINE_MEMBER( mc68901_device::tc_w )
+{
+ if (state)
+ {
+ serial_transmit();
+ }
+}
diff --git a/trunk/src/emu/machine/mc68901.h b/trunk/src/emu/machine/mc68901.h
new file mode 100644
index 00000000000..5bfaf4cb2e7
--- /dev/null
+++ b/trunk/src/emu/machine/mc68901.h
@@ -0,0 +1,232 @@
+/**********************************************************************
+
+ Motorola MC68901 Multi Function Peripheral emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ R/_W 1 |* \_/ | 48 _CS
+ RS1 2 | | 47 _DS
+ RS2 3 | | 46 _DTACK
+ RS3 4 | | 45 _IACK
+ RS4 5 | | 44 D7
+ RS5 6 | | 43 D6
+ TC 7 | | 42 D5
+ SO 8 | | 41 D4
+ SI 9 | | 40 D3
+ RC 10 | | 39 D2
+ Vcc 11 | | 38 D1
+ NC 12 | MC68901 | 37 D0
+ TAO 13 | MK68901 | 36 GND
+ TBO 14 | | 35 CLK
+ TCO 15 | | 34 _IEI
+ TDO 16 | | 33 _IEO
+ XTAL1 17 | | 32 _IRQ
+ XTAL2 18 | | 31 _RR
+ TAI 19 | | 30 _TR
+ TBI 20 | | 29 I7
+ _RESET 21 | | 28 I6
+ I0 22 | | 27 I5
+ I1 23 | | 26 I4
+ I2 24 |_____________| 25 I3
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __MC68901__
+#define __MC68901__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_MC68901_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD((_tag), MC68901, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MC68901_INTERFACE(name) \
+ const mc68901_interface (name) =
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> mc68901_interface
+
+struct mc68901_interface
+{
+ int m_timer_clock; /* timer clock */
+ int m_rx_clock; /* serial receive clock */
+ int m_tx_clock; /* serial transmit clock */
+
+ devcb_write_line m_out_irq_cb;
+
+ devcb_read8 m_in_gpio_cb;
+ devcb_write8 m_out_gpio_cb;
+
+ devcb_write_line m_out_tao_cb;
+ devcb_write_line m_out_tbo_cb;
+ devcb_write_line m_out_tco_cb;
+ devcb_write_line m_out_tdo_cb;
+
+ devcb_read_line m_in_si_cb;
+ devcb_write_line m_out_so_cb;
+ devcb_write_line m_out_rr_cb;
+ devcb_write_line m_out_tr_cb;
+};
+
+
+
+// ======================> mc68901_device
+
+class mc68901_device : public device_t,
+ public mc68901_interface
+{
+public:
+ // construction/destruction
+ mc68901_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_READ8_MEMBER( read );
+ DECLARE_WRITE8_MEMBER( write );
+
+ int get_vector();
+
+ DECLARE_WRITE_LINE_MEMBER( i0_w );
+ DECLARE_WRITE_LINE_MEMBER( i1_w );
+ DECLARE_WRITE_LINE_MEMBER( i2_w );
+ DECLARE_WRITE_LINE_MEMBER( i3_w );
+ DECLARE_WRITE_LINE_MEMBER( i4_w );
+ DECLARE_WRITE_LINE_MEMBER( i5_w );
+ DECLARE_WRITE_LINE_MEMBER( i6_w );
+ DECLARE_WRITE_LINE_MEMBER( i7_w );
+
+ DECLARE_WRITE_LINE_MEMBER( tai_w );
+ DECLARE_WRITE_LINE_MEMBER( tbi_w );
+
+ DECLARE_WRITE_LINE_MEMBER( rc_w );
+ DECLARE_WRITE_LINE_MEMBER( tc_w );
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+ void check_interrupts();
+ void take_interrupt(UINT16 mask);
+ void rx_buffer_full();
+ void rx_error();
+ void tx_buffer_empty();
+ void tx_error();
+ int get_parity_bit(UINT8 b);
+ void serial_receive();
+ void tx_disabled();
+ void tx_starting();
+ void tx_break();
+ void tx_enabled();
+ void serial_transmit();
+ void timer_count(int index);
+ void timer_input(int index, int value);
+ void gpio_input(int bit, int state);
+ void register_w(offs_t offset, UINT8 data);
+
+private:
+ static const device_timer_id TIMER_A = 0;
+ static const device_timer_id TIMER_B = 1;
+ static const device_timer_id TIMER_C = 2;
+ static const device_timer_id TIMER_D = 3;
+ static const device_timer_id TIMER_RX = 4;
+ static const device_timer_id TIMER_TX = 5;
+
+ devcb_resolved_read8 m_in_gpio_func;
+ devcb_resolved_write8 m_out_gpio_func;
+ devcb_resolved_read_line m_in_si_func;
+ devcb_resolved_write_line m_out_so_func;
+ devcb_resolved_write_line m_out_tao_func;
+ devcb_resolved_write_line m_out_tbo_func;
+ devcb_resolved_write_line m_out_tco_func;
+ devcb_resolved_write_line m_out_tdo_func;
+ devcb_resolved_write_line m_out_irq_func;
+
+ int m_device_type; /* device type */
+
+ /* registers */
+ UINT8 m_gpip; /* general purpose I/O register */
+ UINT8 m_aer; /* active edge register */
+ UINT8 m_ddr; /* data direction register */
+
+ UINT16 m_ier; /* interrupt enable register */
+ UINT16 m_ipr; /* interrupt pending register */
+ UINT16 m_isr; /* interrupt in-service register */
+ UINT16 m_imr; /* interrupt mask register */
+ UINT8 m_vr; /* vector register */
+
+ UINT8 m_tacr; /* timer A control register */
+ UINT8 m_tbcr; /* timer B control register */
+ UINT8 m_tcdcr; /* timers C and D control register */
+ UINT8 m_tdr[4]; /* timer data registers */
+
+ UINT8 m_scr; /* synchronous character register */
+ UINT8 m_ucr; /* USART control register */
+ UINT8 m_tsr; /* transmitter status register */
+ UINT8 m_rsr; /* receiver status register */
+ UINT8 m_udr; /* USART data register */
+
+ /* counter timer state */
+ UINT8 m_tmc[4]; /* timer main counters */
+ int m_ti[4]; /* timer in latch */
+ int m_to[4]; /* timer out latch */
+
+ /* interrupt state */
+ int m_irqlevel; /* interrupt level latch */
+
+ /* serial state */
+ UINT8 m_next_rsr; /* receiver status register latch */
+ int m_rsr_read; /* receiver status register read flag */
+ int m_rxtx_word; /* word length */
+ int m_rxtx_start; /* start bits */
+ int m_rxtx_stop; /* stop bits */
+
+ /* receive state */
+ UINT8 m_rx_buffer; /* receive buffer */
+ int m_rx_bits; /* receive bit count */
+ int m_rx_parity; /* receive parity bit */
+ int m_rx_state; /* receive state */
+
+ /* transmit state */
+ UINT8 m_tx_buffer; /* transmit buffer */
+ int m_tx_bits; /* transmit bit count */
+ int m_tx_parity; /* transmit parity bit */
+ int m_tx_state; /* transmit state */
+ int m_xmit_state; /* transmitter state */
+
+ // timers
+ emu_timer *m_timer[4]; /* counter timers */
+ emu_timer *m_rx_timer; /* receive timer */
+ emu_timer *m_tx_timer; /* transmit timer */
+};
+
+
+// device type definition
+extern const device_type MC68901;
+
+
+
+#endif
diff --git a/trunk/src/emu/machine/mccs1850.c b/trunk/src/emu/machine/mccs1850.c
new file mode 100644
index 00000000000..38d446d577c
--- /dev/null
+++ b/trunk/src/emu/machine/mccs1850.c
@@ -0,0 +1,598 @@
+/**********************************************************************
+
+ Motorola MCCS1850 Serial Real-Time Clock emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+/*
+
+ TODO:
+
+ - auto restart
+ - test mode
+
+*/
+
+#include "mccs1850.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+
+#define RAM_SIZE 0x80
+
+
+// serial state
+enum
+{
+ STATE_ADDRESS,
+ STATE_DATA
+};
+
+
+// registers
+enum
+{
+ REGISTER_COUNTER_LATCH = 0x20,
+ REGISTER_ALARM_LATCH = 0x24,
+ REGISTER_STATUS = 0x30,
+ REGISTER_CONTROL = 0x31,
+ REGISTER_TEST_1 = 0x3e,
+ REGISTER_TEST_2 = 0x3f,
+ REGISTER_TEST_KICK_START_COUNTER = 0x40,
+ REGISTER_TEST_PRESCALE_COUNTER = 0x43,
+ REGISTER_TEST_COUNTER_INCREMENT = 0x4f
+};
+
+
+// clock status/interrupt register
+#define STATUS_TM 0x20 // test mode
+#define STATUS_FTU 0x10 // first time up
+#define STATUS_IT 0x08 // interrupt true
+#define STATUS_LB 0x04 // low battery
+#define STATUS_AI 0x02 // alarm
+#define STATUS_RPD 0x01 // request to power down
+
+
+// clock control register
+#define CONTROL_STR_STP 0x80 // start/stop
+#define CONTROL_PD 0x40 // power down
+#define CONTROL_AR 0x20 // auto restart
+#define CONTROL_AE 0x10 // alarm enable
+#define CONTROL_AC 0x08 // alarm clear
+#define CONTROL_FTUC 0x04 // first time up clear
+#define CONTROL_LBE 0x02 // low battery enable
+#define CONTROL_RPCD 0x01 // request to power down clear
+
+
+// test register 1
+#define TEST1_DIV1 0x80 // divide by 1
+#define TEST1_VOVR 0x40 // Vdd override
+#define TEST1_VDDUP 0x20 // Vdd up
+#define TEST1_VDDON 0x10 // Vdd on
+#define TEST1_VRT 0x08 // valid RAM and time
+#define TEST1_LOW_BAT 0x08 // low battery
+#define TEST1_PCC 0x04 // programmable capacitor C (10.0 pF)
+#define TEST1_PCB 0x02 // programmable capacitor B (5.0 pF)
+#define TEST1_PCA 0x01 // programmable capacitor A (2.5 pF)
+
+
+// test register 2
+#define TEST2_OSCBY 0x80 // oscillator bypass
+#define TEST2_COMPOVR 0x40 // comparator override
+#define TEST2_POR 0x20 // power on reset
+#define TEST2_SELTCK 0x10 // select test clock
+#define TEST2_FRZ 0x08 // freeze mode
+#define TEST2_DV_MASK 0x07 // divider bits select
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+const device_type MCCS1850 = &device_creator<mccs1850_device>;
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// check_interrupt -
+//-------------------------------------------------
+
+inline void mccs1850_device::check_interrupt()
+{
+ UINT8 status = m_ram[REGISTER_STATUS];
+ UINT8 control = m_ram[REGISTER_CONTROL];
+
+ bool interrupt = (((status & STATUS_AI) && (control & CONTROL_AE)) // alarm interrupt
+ || ((status & STATUS_LB) && (control & CONTROL_LBE)) // low battery
+ || (status & STATUS_FTU) // first time up
+ || (status & STATUS_RPD)); // request to power down
+
+ if (interrupt)
+ {
+ m_ram[REGISTER_STATUS] |= STATUS_IT;
+ }
+ else
+ {
+ m_ram[REGISTER_STATUS] &= ~STATUS_IT;
+ }
+
+ m_out_int_func(interrupt ? ASSERT_LINE : CLEAR_LINE);
+}
+
+
+//-------------------------------------------------
+// set_pse_line -
+//-------------------------------------------------
+
+inline void mccs1850_device::set_pse_line(int state)
+{
+ m_pse = state;
+
+ m_out_pse_func(m_pse);
+}
+
+
+//-------------------------------------------------
+// read_register -
+//-------------------------------------------------
+
+inline UINT8 mccs1850_device::read_register(offs_t offset)
+{
+ switch (offset)
+ {
+ case REGISTER_COUNTER_LATCH:
+ // load counter value into latch
+ m_ram[REGISTER_COUNTER_LATCH] = m_counter >> 24;
+ m_ram[REGISTER_COUNTER_LATCH + 1] = m_counter >> 16;
+ m_ram[REGISTER_COUNTER_LATCH + 2] = m_counter >> 8;
+ m_ram[REGISTER_COUNTER_LATCH + 3] = m_counter;
+ break;
+
+ case REGISTER_TEST_1:
+ case REGISTER_TEST_2:
+ case REGISTER_TEST_KICK_START_COUNTER:
+ case REGISTER_TEST_PRESCALE_COUNTER:
+ case REGISTER_TEST_COUNTER_INCREMENT:
+ logerror("MCCS1850 '%s' Unsupported read from test register %02x!\n", tag(), offset);
+ break;
+ }
+
+ return m_ram[offset];
+}
+
+
+//-------------------------------------------------
+// write_register -
+//-------------------------------------------------
+
+inline void mccs1850_device::write_register(offs_t offset, UINT8 data)
+{
+ switch (offset)
+ {
+ case REGISTER_STATUS:
+ // read only
+ break;
+
+ case REGISTER_CONTROL:
+ if (LOG) logerror("MCCS1850 '%s' Counter %s\n", tag(), (data & CONTROL_STR_STP) ? "Start" : "Stop");
+ m_clock_timer->enable(data & CONTROL_STR_STP);
+
+ if (data & CONTROL_PD)
+ {
+ if (LOG) logerror("MCCS1850 '%s' Power Down\n", tag());
+ set_pse_line(0);
+ }
+
+ if (data & CONTROL_AR)
+ {
+ if (LOG) logerror("MCCS1850 '%s' Auto Restart\n", tag());
+ }
+
+ if (data & CONTROL_AC)
+ {
+ if (LOG) logerror("MCCS1850 '%s' Alarm Clear\n", tag());
+ m_ram[REGISTER_STATUS] &= ~STATUS_AI;
+ }
+
+ if (data & CONTROL_FTUC)
+ {
+ if (LOG) logerror("MCCS1850 '%s' First Time Up Clear\n", tag());
+ m_ram[REGISTER_STATUS] &= ~STATUS_FTU;
+ }
+
+ if (data & CONTROL_RPCD)
+ {
+ if (LOG) logerror("MCCS1850 '%s' Request to Power Down Clear\n", tag());
+ m_ram[REGISTER_STATUS] &= ~STATUS_RPD;
+ }
+
+ m_ram[REGISTER_CONTROL] = data & 0xb2;
+
+ check_interrupt();
+ break;
+
+ case REGISTER_TEST_1:
+ case REGISTER_TEST_2:
+ case REGISTER_TEST_KICK_START_COUNTER:
+ case REGISTER_TEST_PRESCALE_COUNTER:
+ case REGISTER_TEST_COUNTER_INCREMENT:
+ logerror("MCCS1850 '%s' Unsupported write to test register %02x!\n", tag(), offset);
+ break;
+
+ default:
+ m_ram[offset] = data;
+ }
+}
+
+
+//-------------------------------------------------
+// advance_seconds -
+//-------------------------------------------------
+
+inline void mccs1850_device::advance_seconds()
+{
+ UINT32 alarm = (m_ram[REGISTER_ALARM_LATCH] << 24) | (m_ram[REGISTER_ALARM_LATCH + 1] << 16) | (m_ram[REGISTER_ALARM_LATCH + 2] << 8) | m_ram[REGISTER_ALARM_LATCH + 3];
+
+ m_counter++;
+
+ if (m_counter == alarm)
+ {
+ if (m_pse)
+ {
+ // trigger alarm
+ m_ram[REGISTER_STATUS] |= STATUS_AI;
+
+ check_interrupt();
+ }
+ else
+ {
+ // wake up
+ set_pse_line(1);
+ }
+ }
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// mccs1850_device - constructor
+//-------------------------------------------------
+
+mccs1850_device::mccs1850_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, MCCS1850, "MCCS1850", tag, owner, clock),
+ device_rtc_interface(mconfig, *this),
+ device_nvram_interface(mconfig, *this),
+ m_pse(1),
+ m_ce(0),
+ m_sck(0),
+ m_sdo(1),
+ m_sdi(0),
+ m_state(STATE_ADDRESS),
+ m_bits(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void mccs1850_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const mccs1850_interface *intf = reinterpret_cast<const mccs1850_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<mccs1850_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_out_int_cb, 0, sizeof(m_out_int_cb));
+ memset(&m_out_pse_cb, 0, sizeof(m_out_pse_cb));
+ memset(&m_out_nuc_cb, 0, sizeof(m_out_nuc_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mccs1850_device::device_start()
+{
+ // resolve callbacks
+ m_out_int_func.resolve(m_out_int_cb, *this);
+ m_out_pse_func.resolve(m_out_pse_cb, *this);
+ m_out_nuc_func.resolve(m_out_nuc_cb, *this);
+
+ // allocate timers
+ m_clock_timer = timer_alloc(TIMER_CLOCK);
+ m_clock_timer->adjust(attotime::from_hz(clock() / 32768), 0, attotime::from_hz(clock() / 32768));
+
+ // state saving
+ save_item(NAME(m_pse));
+ save_item(NAME(m_counter));
+ save_item(NAME(m_ce));
+ save_item(NAME(m_sck));
+ save_item(NAME(m_sdo));
+ save_item(NAME(m_sdi));
+ save_item(NAME(m_state));
+ save_item(NAME(m_address));
+ save_item(NAME(m_bits));
+ save_item(NAME(m_shift));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void mccs1850_device::device_reset()
+{
+ m_ram[REGISTER_STATUS] = 0x80 | STATUS_FTU;
+ m_ram[REGISTER_CONTROL] = 0x00;
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void mccs1850_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case TIMER_CLOCK:
+ advance_seconds();
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// rtc_set_time - called to initialize the RTC to
+// a known state
+//-------------------------------------------------
+
+void mccs1850_device::rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second)
+{
+}
+
+
+//-------------------------------------------------
+// nvram_default - called to initialize NVRAM to
+// its default state
+//-------------------------------------------------
+
+void mccs1850_device::nvram_default()
+{
+ memset(m_ram, 0xff, RAM_SIZE);
+
+ if (machine().region(tag()) != NULL)
+ {
+ UINT8 *nvram = machine().region(tag())->base();
+
+ // initialize NVRAM
+ memcpy(m_ram, nvram, 0x20);
+ }
+}
+
+
+//-------------------------------------------------
+// nvram_read - called to read NVRAM from the
+// .nv file
+//-------------------------------------------------
+
+void mccs1850_device::nvram_read(emu_file &file)
+{
+ file.read(m_ram, RAM_SIZE);
+}
+
+
+//-------------------------------------------------
+// nvram_write - called to write NVRAM to the
+// .nv file
+//-------------------------------------------------
+
+void mccs1850_device::nvram_write(emu_file &file)
+{
+ file.write(m_ram, RAM_SIZE);
+}
+
+
+//-------------------------------------------------
+// ce_w - chip enable write
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( mccs1850_device::ce_w )
+{
+ m_ce = state;
+
+ if (!m_ce)
+ {
+ m_state = STATE_ADDRESS;
+ m_bits = 0;
+ }
+}
+
+
+//-------------------------------------------------
+// sck_w - serial clock write
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( mccs1850_device::sck_w )
+{
+ if (!m_ce) return;
+
+ switch (m_state)
+ {
+ case STATE_ADDRESS:
+ if (m_sck && !state)
+ {
+ m_address <<= 1;
+ m_address |= m_sdi;
+ m_bits++;
+
+ if (m_bits == 8)
+ {
+ if (LOG) logerror("MCCS1850 '%s' %s Address %u\n", tag(), BIT(m_address, 7) ? "Write" : "Read", m_address & 0x7f);
+
+ m_bits = 0;
+ m_state = STATE_DATA;
+
+ if (!BIT(m_address, 7))
+ {
+ m_shift = read_register(m_address & 0x7f);
+
+ if (LOG) logerror("MCCS1850 '%s' Data Out %02x\n", tag(), m_shift);
+ }
+ }
+ }
+ break;
+
+ case STATE_DATA:
+ if (BIT(m_address, 7) && m_sck && !state)
+ {
+ // shift data in
+ m_shift <<= 1;
+ m_shift |= m_sdi;
+ m_bits++;
+
+ if (m_bits == 8)
+ {
+ if (LOG) logerror("MCCS1850 '%s' Data In %02x\n", tag(), m_shift);
+
+ write_register(m_address & 0x7f, m_shift);
+
+ m_bits = 0;
+
+ // increment address counter
+ m_address++;
+ m_address &= 0x7f;
+ }
+ }
+ else if (!BIT(m_address, 7) && !m_sck && state)
+ {
+ // shift data out
+ m_sdo = BIT(m_shift, 7);
+ m_shift <<= 1;
+ m_bits++;
+
+ if (m_bits == 8)
+ {
+ m_bits = 0;
+
+ // increment address counter
+ m_address++;
+ m_address &= 0x7f;
+ m_shift = read_register(m_address & 0x7f);
+ }
+ }
+ break;
+ }
+
+ m_sck = state;
+}
+
+
+//-------------------------------------------------
+// sdo_r - serial data out read
+//-------------------------------------------------
+
+READ_LINE_MEMBER( mccs1850_device::sdo_r )
+{
+ if (!m_ce || BIT(m_address, 7))
+ {
+ // Hi-Z
+ return 1;
+ }
+ else
+ {
+ return m_sdo;
+ }
+}
+
+
+//-------------------------------------------------
+// sdi_w - serial data in write
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( mccs1850_device::sdi_w )
+{
+ m_sdi = state;
+}
+
+
+//-------------------------------------------------
+// pwrsw_w - power switch write
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( mccs1850_device::pwrsw_w )
+{
+ if (!state)
+ {
+ if (m_pse)
+ {
+ // request to power down
+ m_ram[REGISTER_STATUS] |= STATUS_RPD;
+ check_interrupt();
+ }
+
+ set_pse_line(1);
+ }
+}
+
+
+//-------------------------------------------------
+// por_w - power on reset write
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( mccs1850_device::por_w )
+{
+ if (!state)
+ {
+ device_reset();
+ }
+}
+
+
+//-------------------------------------------------
+// test_w - test mode write
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( mccs1850_device::test_w )
+{
+ if (state)
+ {
+ if (LOG) logerror("MCCS1850 '%s' Test Mode\n", tag());
+
+ m_ram[REGISTER_STATUS] |= STATUS_TM;
+ }
+ else
+ {
+ if (LOG) logerror("MCCS1850 '%s' Normal Operation\n", tag());
+
+ m_ram[REGISTER_STATUS] &= ~STATUS_TM;
+ }
+}
diff --git a/trunk/src/emu/machine/mccs1850.h b/trunk/src/emu/machine/mccs1850.h
new file mode 100644
index 00000000000..da3e43a72d0
--- /dev/null
+++ b/trunk/src/emu/machine/mccs1850.h
@@ -0,0 +1,135 @@
+/**********************************************************************
+
+ Motorola MCCS1850 Serial Real-Time Clock emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ Vbat 1 |* \_/ | 16 Vdd
+ _POR 2 | | 15 TEST
+ _INT 3 | | 14 XTAL1
+ SCK 4 | MCCS1850 | 13 XTAL2
+ SDI 5 | | 12 _PWRSW
+ SDO 6 | | 11 NUC
+ CE 7 | | 10 _PSE
+ Vss 8 |_____________| 9 PSE
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __MCCS1850__
+#define __MCCS1850__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_MCCS1850_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD(_tag, MCCS1850, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+
+#define MCCS1850_INTERFACE(name) \
+ const mccs1850_interface (name) =
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> mccs1850_interface
+
+struct mccs1850_interface
+{
+ devcb_write_line m_out_int_cb;
+ devcb_write_line m_out_pse_cb;
+ devcb_write_line m_out_nuc_cb;
+};
+
+
+
+// ======================> mccs1850_device
+
+class mccs1850_device : public device_t,
+ public device_rtc_interface,
+ public device_nvram_interface,
+ public mccs1850_interface
+{
+public:
+ // construction/destruction
+ mccs1850_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_WRITE_LINE_MEMBER( ce_w );
+ DECLARE_WRITE_LINE_MEMBER( sck_w );
+ DECLARE_READ_LINE_MEMBER( sdo_r );
+ DECLARE_WRITE_LINE_MEMBER( sdi_w );
+ DECLARE_WRITE_LINE_MEMBER( pwrsw_w );
+ DECLARE_WRITE_LINE_MEMBER( por_w );
+ DECLARE_WRITE_LINE_MEMBER( test_w );
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+ // device_rtc_interface overrides
+ virtual void rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second);
+ virtual bool rtc_is_year_2000_compliant() { return false; }
+
+ // device_nvram_interface overrides
+ virtual void nvram_default();
+ virtual void nvram_read(emu_file &file);
+ virtual void nvram_write(emu_file &file);
+
+private:
+ inline void check_interrupt();
+ inline void set_pse_line(int state);
+ inline UINT8 read_register(offs_t offset);
+ inline void write_register(offs_t offset, UINT8 data);
+ inline void advance_seconds();
+
+ static const device_timer_id TIMER_CLOCK = 0;
+
+ devcb_resolved_write_line m_out_int_func;
+ devcb_resolved_write_line m_out_pse_func;
+ devcb_resolved_write_line m_out_nuc_func;
+
+ UINT8 m_ram[0x80]; // RAM
+
+ // power supply
+ int m_pse; // power supply enable
+
+ // counter
+ UINT32 m_counter; // seconds counter
+
+ // serial interface
+ int m_ce; // chip enable
+ int m_sck; // serial clock
+ int m_sdo; // serial data out
+ int m_sdi; // serial data in
+ int m_state; // serial interface state
+ UINT8 m_address; // address counter
+ int m_bits; // bit counter
+ UINT8 m_shift; // shift register
+
+ // timers
+ emu_timer *m_clock_timer;
+};
+
+
+// device type definition
+extern const device_type MCCS1850;
+
+
+
+#endif
diff --git a/trunk/src/emu/machine/microtch.c b/trunk/src/emu/machine/microtch.c
new file mode 100644
index 00000000000..128dc29c383
--- /dev/null
+++ b/trunk/src/emu/machine/microtch.c
@@ -0,0 +1,254 @@
+/*
+ Microtouch touch screen controller
+
+ Written by Mariusz Wojcieszek
+
+ Notes/ToDo:
+ - calibration mode (command CX)
+ - only tablet format and decimal format are supported for returning touch screen state
+
+*/
+
+#include "emu.h"
+#include "microtch.h"
+
+#define LOG 0
+
+static struct
+{
+ UINT8 rx_buffer[16];
+ int rx_buffer_ptr;
+ emu_timer* timer;
+ UINT8 tx_buffer[16];
+ UINT8 tx_buffer_num;
+ UINT8 tx_buffer_ptr;
+ int reset_done;
+ int format_tablet;
+ int format_decimal;
+ int mode_inactive;
+ int mode_stream;
+ int last_touch_state;
+ int last_x;
+ int last_y;
+ microtouch_tx_func tx_callback;
+ microtouch_touch_func touch_callback;
+} microtouch;
+
+
+static int microtouch_check_command( const char* commandtocheck, int command_len, UINT8* command_data )
+{
+ if ( (command_len == (strlen(commandtocheck) + 2)) &&
+ (command_data[0] == 0x01) &&
+ (strncmp(commandtocheck, (const char*)command_data + 1, strlen(commandtocheck)) == 0) &&
+ (command_data[command_len-1] == 0x0d) )
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static void microtouch_send_format_table_packet(UINT8 flag, int x, int y)
+{
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = flag;
+ // lower byte (7bits) of x coordinate
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = x & 0x7f;
+ // higher byte (7bits) of x coordinate
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = (x >> 7) & 0x7f;
+ // lower byte (7bits) of y coordinate
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = y & 0x7f;
+ // higher byte (7bits) of y coordinate
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = (y >> 7) & 0x7f;
+};
+
+static void microtouch_send_format_decimal_packet(int x, int y)
+{
+ int decx, decy;
+
+ decx = x / 16;
+ if ( decx > 999 )
+ decx = 999;
+ decy = y / 16;
+ if ( decy > 999 )
+ decy = 999;
+
+ // header byte
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = 0x01;
+ // x coordinate in decimal mode
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = (decx / 100) + '0';
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = ((decx / 10) % 10) + '0';
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = (decx % 10) + '0';
+ // comma (separator)
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = ',';
+ // y coordinate in decimal mode
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = (decy / 100) + '0';
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = ((decy / 10) % 10) + '0';
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = (decy % 10) + '0';
+ // terminator
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = 0x0d;
+}
+
+static TIMER_CALLBACK(microtouch_timer_callback)
+{
+ if ( microtouch.tx_buffer_ptr < microtouch.tx_buffer_num )
+ {
+ microtouch.tx_callback( machine, microtouch.tx_buffer[microtouch.tx_buffer_ptr++] );
+ if ( microtouch.tx_buffer_ptr == microtouch.tx_buffer_num )
+ {
+ microtouch.tx_buffer_ptr = microtouch.tx_buffer_num = 0;
+ }
+ return;
+ }
+
+ if ( (microtouch.reset_done == 0) ||
+ ((microtouch.format_tablet == 0) && (microtouch.format_decimal == 0)) ||
+ (microtouch.mode_inactive == 1) ||
+ (microtouch.mode_stream == 0) )
+ {
+ return;
+ }
+
+ // send format tablet packet
+ if ( input_port_read(machine, "TOUCH") & 0x01 )
+ {
+ int tx = input_port_read(machine, "TOUCH_X");
+ int ty = input_port_read(machine, "TOUCH_Y");
+
+ if ( microtouch.touch_callback == NULL ||
+ microtouch.touch_callback( machine, &tx, &ty ) != 0 )
+ {
+ ty = 0x4000 - ty;
+
+ if ( microtouch.format_tablet )
+ {
+ microtouch_send_format_table_packet(0xc8, tx, ty);
+ }
+ else if ( microtouch.format_decimal )
+ {
+ microtouch_send_format_decimal_packet(tx, ty);
+ }
+ microtouch.last_touch_state = 1;
+ microtouch.last_x = tx;
+ microtouch.last_y = ty;
+ }
+ }
+ else
+ {
+ if ( microtouch.last_touch_state == 1 )
+ {
+ microtouch.last_touch_state = 0;
+ if ( microtouch.format_tablet )
+ {
+ microtouch_send_format_table_packet(0x88, microtouch.last_x, microtouch.last_y);
+ }
+ else if ( microtouch.format_decimal )
+ {
+ microtouch_send_format_decimal_packet(microtouch.last_x, microtouch.last_y);
+ }
+ }
+ }
+};
+
+void microtouch_init(running_machine &machine, microtouch_tx_func tx_cb, microtouch_touch_func touch_cb)
+{
+ memset(&microtouch, 0, sizeof(microtouch));
+
+ microtouch.last_touch_state = -1;
+ microtouch.tx_callback = tx_cb;
+ microtouch.touch_callback = touch_cb;
+
+ microtouch.timer = machine.scheduler().timer_alloc(FUNC(microtouch_timer_callback));
+ microtouch.timer->adjust(attotime::from_hz(167*5), 0, attotime::from_hz(167*5));
+
+ state_save_register_item(machine, "microtouch", NULL, 0, microtouch.reset_done);
+ state_save_register_item(machine, "microtouch", NULL, 0, microtouch.format_tablet);
+ state_save_register_item(machine, "microtouch", NULL, 0, microtouch.mode_inactive);
+ state_save_register_item(machine, "microtouch", NULL, 0, microtouch.mode_stream);
+ state_save_register_item(machine, "microtouch", NULL, 0, microtouch.last_touch_state);
+ state_save_register_item(machine, "microtouch", NULL, 0, microtouch.last_x);
+ state_save_register_item(machine, "microtouch", NULL, 0, microtouch.last_y);
+ state_save_register_item_array(machine, "microtouch", NULL, 0, microtouch.rx_buffer);
+ state_save_register_item(machine, "microtouch", NULL, 0, microtouch.rx_buffer_ptr);
+ state_save_register_item_array(machine, "microtouch", NULL, 0, microtouch.tx_buffer);
+ state_save_register_item(machine, "microtouch", NULL, 0, microtouch.tx_buffer_num);
+ state_save_register_item(machine, "microtouch", NULL, 0, microtouch.tx_buffer_ptr);
+ state_save_register_item(machine, "microtouch", NULL, 0, microtouch.format_decimal);
+
+};
+
+
+void microtouch_rx(int count, UINT8* data)
+{
+ int i;
+
+ for ( i = 0; (i < count) && ((microtouch.rx_buffer_ptr + i) < 16); i++ )
+ {
+ microtouch.rx_buffer[i+microtouch.rx_buffer_ptr] = data[i];
+ microtouch.rx_buffer_ptr++;
+ }
+
+ if (microtouch.rx_buffer_ptr > 0 && (microtouch.rx_buffer[microtouch.rx_buffer_ptr-1] == 0x0d))
+ {
+ if (LOG)
+ {
+ char command[16];
+ memset(command, 0, sizeof(command));
+ strncpy( command, (const char*)microtouch.rx_buffer + 1, microtouch.rx_buffer_ptr - 2 );
+ logerror("Microtouch: received command %s\n", command);
+ }
+ // check command
+ if ( microtouch_check_command( "MS", microtouch.rx_buffer_ptr, microtouch.rx_buffer ) )
+ {
+ microtouch.mode_stream = 1;
+ microtouch.mode_inactive = 0;
+ }
+ else if ( microtouch_check_command( "MI", microtouch.rx_buffer_ptr, microtouch.rx_buffer ) )
+ {
+ microtouch.mode_inactive = 1;
+ }
+ else if ( microtouch_check_command( "R", microtouch.rx_buffer_ptr, microtouch.rx_buffer ) )
+ {
+ microtouch.tx_buffer_num = 0;
+ microtouch.reset_done = 1;
+ }
+ else if ( microtouch_check_command( "FT", microtouch.rx_buffer_ptr, microtouch.rx_buffer ) )
+ {
+ microtouch.format_tablet = 1;
+ }
+ else if ( microtouch_check_command( "FD", microtouch.rx_buffer_ptr, microtouch.rx_buffer ) )
+ {
+ microtouch.format_decimal = 1;
+ }
+ else if ( microtouch_check_command("OI", microtouch.rx_buffer_ptr, microtouch.rx_buffer ) )
+ {
+ // output identity - SMT3, ver 01.00
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = 0x01;
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = 'Q';
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = '1';
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = '0';
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = '1';
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = '0';
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = '0';
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = 0x0d;
+ microtouch.rx_buffer_ptr = 0;
+ return;
+ }
+ // send response
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = 0x01;
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = 0x30;
+ microtouch.tx_buffer[microtouch.tx_buffer_num++] = 0x0d;
+ microtouch.rx_buffer_ptr = 0;
+ }
+};
+
+INPUT_PORTS_START(microtouch)
+ PORT_START("TOUCH")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME( "Touch screen" )
+ PORT_START("TOUCH_X")
+ PORT_BIT( 0x3fff, 0x2000, IPT_LIGHTGUN_X ) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(45) PORT_KEYDELTA(15)
+ PORT_START("TOUCH_Y")
+ PORT_BIT( 0x3fff, 0x2000, IPT_LIGHTGUN_Y ) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(45) PORT_KEYDELTA(15)
+INPUT_PORTS_END
+
diff --git a/trunk/src/emu/machine/microtch.h b/trunk/src/emu/machine/microtch.h
new file mode 100644
index 00000000000..d378c49eb91
--- /dev/null
+++ b/trunk/src/emu/machine/microtch.h
@@ -0,0 +1,12 @@
+#ifndef _MICROTOUCH_H
+#define _MICROTOUCH_H
+
+INPUT_PORTS_EXTERN(microtouch);
+
+typedef void (*microtouch_tx_func)(running_machine &machine, UINT8 data);
+typedef int (*microtouch_touch_func)(running_machine &machine, int *touch_x, int *touch_y);
+
+void microtouch_init(running_machine &machine, microtouch_tx_func tx_cb, microtouch_touch_func touch_cb);
+void microtouch_rx(int count, UINT8* data);
+
+#endif //_MICROTOUCH_H
diff --git a/trunk/src/emu/machine/mm74c922.c b/trunk/src/emu/machine/mm74c922.c
new file mode 100644
index 00000000000..a2f0bc1b455
--- /dev/null
+++ b/trunk/src/emu/machine/mm74c922.c
@@ -0,0 +1,217 @@
+/**********************************************************************
+
+ MM74C922/MM74C923 16/20-Key Encoder emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "mm74c922.h"
+#include "machine/devhelpr.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 1
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type MM74C922 = &device_creator<mm74c922_device>;
+const device_type MM74C923 = &device_creator<mm74c922_device>;
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// change_output_lines -
+//-------------------------------------------------
+
+inline void mm74c922_device::change_output_lines()
+{
+ if (m_next_da != m_da)
+ {
+ m_da = m_next_da;
+
+ if (LOG) logerror("MM74C922 '%s' Data Available: %u\n", tag(), m_da);
+
+ m_out_da_func(m_da);
+ }
+}
+
+
+//-------------------------------------------------
+// clock_scan_counters -
+//-------------------------------------------------
+
+inline void mm74c922_device::clock_scan_counters()
+{
+ if (!m_inhibit)
+ {
+ m_x++;
+ m_x &= 0x03;
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+inline void mm74c922_device::detect_keypress()
+{
+ if (m_inhibit)
+ {
+ UINT8 data = m_in_x_func[m_x](0);
+
+ if (BIT(data, m_y))
+ {
+ // key released
+ m_inhibit = 0;
+ m_next_da = 0;
+ m_data = 0xff; // high-Z
+
+ if (LOG) logerror("MM74C922 '%s' Key Released\n", tag());
+ }
+ }
+ else
+ {
+ UINT8 data = m_in_x_func[m_x](0);
+
+ for (int y = 0; y < m_max_y; y++)
+ {
+ if (!BIT(data, y))
+ {
+ // key depressed
+ m_inhibit = 1;
+ m_next_da = 1;
+ m_y = y;
+
+ m_data = (y << 2) | m_x;
+
+ if (LOG) logerror("MM74C922 '%s' Key Depressed: X %u Y %u = %02x\n", tag(), m_x, y, m_data);
+ return;
+ }
+ }
+ }
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// mm74c922_device - constructor
+//-------------------------------------------------
+
+mm74c922_device::mm74c922_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, MM74C922, "MM74C922", tag, owner, clock),
+ m_x(0),
+ m_y(0),
+ m_next_da(0)
+{
+}
+
+
+//-------------------------------------------------
+// static_set_config - configuration helper
+//-------------------------------------------------
+
+void mm74c922_device::static_set_config(device_t &device, int max_y)
+{
+ mm74c922_device &mm74c922 = downcast<mm74c922_device &>(device);
+
+ mm74c922.m_max_y = max_y;
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void mm74c922_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const mm74c922_interface *intf = reinterpret_cast<const mm74c922_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<mm74c922_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_out_da_cb, 0, sizeof(m_out_da_cb));
+ memset(&m_in_x1_cb, 0, sizeof(m_in_x1_cb));
+ memset(&m_in_x2_cb, 0, sizeof(m_in_x2_cb));
+ memset(&m_in_x3_cb, 0, sizeof(m_in_x3_cb));
+ memset(&m_in_x4_cb, 0, sizeof(m_in_x4_cb));
+ memset(&m_in_x5_cb, 0, sizeof(m_in_x5_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mm74c922_device::device_start()
+{
+ // resolve callbacks
+ m_out_da_func.resolve(m_out_da_cb, *this);
+ m_in_x_func[0].resolve(m_in_x1_cb, *this);
+ m_in_x_func[1].resolve(m_in_x2_cb, *this);
+ m_in_x_func[2].resolve(m_in_x3_cb, *this);
+ m_in_x_func[3].resolve(m_in_x4_cb, *this);
+ m_in_x_func[4].resolve(m_in_x5_cb, *this);
+
+ // set initial values
+ change_output_lines();
+
+ // allocate timers
+ m_scan_timer = timer_alloc();
+ m_scan_timer->adjust(attotime::zero, 0, attotime::from_hz(50));
+
+ // register for state saving
+ save_item(NAME(m_inhibit));
+ save_item(NAME(m_x));
+ save_item(NAME(m_y));
+ save_item(NAME(m_data));
+ save_item(NAME(m_da));
+ save_item(NAME(m_next_da));
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void mm74c922_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ change_output_lines();
+ clock_scan_counters();
+ detect_keypress();
+}
+
+
+//-------------------------------------------------
+// data_out_r -
+//-------------------------------------------------
+
+UINT8 mm74c922_device::data_out_r()
+{
+ if (LOG) logerror("MM74C922 '%s' Data Read: %02x\n", tag(), m_data);
+
+ return m_data;
+}
diff --git a/trunk/src/emu/machine/mm74c922.h b/trunk/src/emu/machine/mm74c922.h
new file mode 100644
index 00000000000..a51b85b1152
--- /dev/null
+++ b/trunk/src/emu/machine/mm74c922.h
@@ -0,0 +1,139 @@
+/**********************************************************************
+
+ MM74C922/MM74C923 16/20-Key Encoder emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ ROW Y1 1 |* \_/ | 18 Vcc
+ ROW Y2 2 | | 17 DATA OUT A
+ ROW Y3 3 | | 16 DATA OUT B
+ ROW Y4 4 | | 15 DATA OUT C
+ OSCILLATOR 5 | MM74C922 | 14 DATA OUT D
+ KEYBOUNCE MASK 6 | | 13 _OUTPUT ENABLE
+ COLUMN X4 7 | | 12 DATA AVAILABLE
+ COLUMN X3 8 | | 11 COLUMN X1
+ GND 9 |_____________| 10 COLUMN X2
+
+ _____ _____
+ ROW Y1 1 |* \_/ | 20 Vcc
+ ROW Y2 2 | | 19 DATA OUT A
+ ROW Y3 3 | | 18 DATA OUT B
+ ROW Y4 4 | | 17 DATA OUT C
+ ROW Y5 5 | MM74C923 | 16 DATA OUT D
+ OSCILLATOR 6 | | 15 DATA OUT E
+ KEYBOUNCE MASK 7 | | 14 _OUTPUT ENABLE
+ COLUMN X4 8 | | 13 DATA AVAILABLE
+ COLUMN X3 9 | | 12 COLUMN X1
+ GND 10 |_____________| 11 COLUMN X2
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __MM74C922__
+#define __MM74C922__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_MM74C922_ADD(_tag, _config) \
+ MCFG_DEVICE_ADD(_tag, MM74C922, 0) \
+ MCFG_DEVICE_CONFIG(_config) \
+ mm74c922_device::static_set_config(*device, 4);
+
+
+#define MCFG_MM74C923_ADD(_tag, _config) \
+ MCFG_DEVICE_ADD(_tag, MM74C923, 0) \
+ MCFG_DEVICE_CONFIG(_config) \
+ mm74c922_device::static_set_config(*device, 5);
+
+
+#define MM74C922_INTERFACE(name) \
+ const mm74c922_interface (name)=
+
+
+#define MM74C923_INTERFACE(name) \
+ const mm74c922_interface (name)=
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> mm74c922_interface
+
+struct mm74c922_interface
+{
+ double m_cap_osc;
+ double m_cap_debounce;
+
+ devcb_write_line m_out_da_cb;
+
+ devcb_read8 m_in_x1_cb;
+ devcb_read8 m_in_x2_cb;
+ devcb_read8 m_in_x3_cb;
+ devcb_read8 m_in_x4_cb;
+ devcb_read8 m_in_x5_cb;
+};
+
+
+// ======================> mm74c922_device
+
+class mm74c922_device : public device_t,
+ public mm74c922_interface
+{
+public:
+ // construction/destruction
+ mm74c922_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // inline configuration helpers
+ static void static_set_config(device_t &device, int max_y);
+
+ UINT8 data_out_r();
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+private:
+ inline void change_output_lines();
+ inline void clock_scan_counters();
+ inline void detect_keypress();
+
+ int m_max_y;
+
+ devcb_resolved_write_line m_out_da_func;
+ devcb_resolved_read8 m_in_x_func[5];
+
+ int m_inhibit; // scan counter clock inhibit
+ int m_x; // currently scanned column
+ int m_y; // latched row
+
+ UINT8 m_data; // data latch
+
+ int m_da; // data available flag
+ int m_next_da; // next value of data available flag
+
+ // timers
+ emu_timer *m_scan_timer; // keyboard scan timer
+};
+
+
+// device type definition
+extern const device_type MM74C922;
+extern const device_type MM74C923;
+
+
+
+#endif
diff --git a/trunk/src/emu/machine/mos6529.c b/trunk/src/emu/machine/mos6529.c
new file mode 100644
index 00000000000..5faadccb4f1
--- /dev/null
+++ b/trunk/src/emu/machine/mos6529.c
@@ -0,0 +1,91 @@
+/**********************************************************************
+
+ MOS Technology 6529 Single Port Interface Adapter emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "mos6529.h"
+#include "devhelpr.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type MOS6529 = &device_creator<mos6529_device>;
+
+//-------------------------------------------------
+// mos6529_device - constructor
+//-------------------------------------------------
+
+mos6529_device::mos6529_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, MOS6529, "MOS6529", tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void mos6529_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const mos6529_interface *intf = reinterpret_cast<const mos6529_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<mos6529_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_in_p_cb, 0, sizeof(m_in_p_cb));
+ memset(&m_out_p_cb, 0, sizeof(m_out_p_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mos6529_device::device_start()
+{
+ // resolve callbacks
+ m_in_p_func.resolve(m_in_p_cb, *this);
+ m_out_p_func.resolve(m_out_p_cb, *this);
+}
+
+
+//-------------------------------------------------
+// read -
+//-------------------------------------------------
+
+READ8_MEMBER( mos6529_device::read )
+{
+ return m_in_p_func(0);
+}
+
+
+//-------------------------------------------------
+// write -
+//-------------------------------------------------
+
+WRITE8_MEMBER( mos6529_device::write )
+{
+ m_out_p_func(0, data);
+}
diff --git a/trunk/src/emu/machine/mos6529.h b/trunk/src/emu/machine/mos6529.h
new file mode 100644
index 00000000000..f9ad7a5ad26
--- /dev/null
+++ b/trunk/src/emu/machine/mos6529.h
@@ -0,0 +1,86 @@
+/**********************************************************************
+
+ MOS Technology 6529 Single Port Interface Adapter emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ R/W 1 |* \_/ | 20 Vdd
+ P0 2 | | 19 _CS
+ P1 3 | | 18 D0
+ P2 4 | | 17 D1
+ P3 5 | MOS6529 | 16 D2
+ P4 6 | | 15 D3
+ P5 7 | | 14 D4
+ P6 8 | | 13 D5
+ P7 9 | | 12 D6
+ Vss 10 |_____________| 11 D7
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __MOS6529__
+#define __MOS6529__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_MOS6529_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD(_tag, MOS6529, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MOS6529_INTERFACE(name) \
+ const mos6529_interface (name) =
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> mos6529_interface
+
+struct mos6529_interface
+{
+ devcb_read8 m_in_p_cb;
+ devcb_write8 m_out_p_cb;
+};
+
+
+// ======================> mos6529_device
+
+class mos6529_device : public device_t,
+ public mos6529_interface
+{
+public:
+ // construction/destruction
+ mos6529_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_READ8_MEMBER( read );
+ DECLARE_WRITE8_MEMBER( write );
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+
+private:
+ devcb_resolved_read8 m_in_p_func;
+ devcb_resolved_write8 m_out_p_func;
+};
+
+
+// device type definition
+extern const device_type MOS6529;
+
+
+
+#endif
diff --git a/trunk/src/emu/machine/msm5832.c b/trunk/src/emu/machine/msm5832.c
new file mode 100644
index 00000000000..7f8eb374a39
--- /dev/null
+++ b/trunk/src/emu/machine/msm5832.c
@@ -0,0 +1,377 @@
+/**********************************************************************
+
+ OKI MSM5832 Real Time Clock/Calendar emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+/*
+
+ TODO:
+
+ - 12/24 hour
+ - AM/PM
+ - leap year
+ - test input
+ - reference signal output
+
+*/
+
+#include "msm5832.h"
+
+
+// device type definition
+const device_type MSM5832 = &device_creator<msm5832_device>;
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+
+// registers
+enum
+{
+ REGISTER_S1 = 0,
+ REGISTER_S10,
+ REGISTER_MI1,
+ REGISTER_MI10,
+ REGISTER_H1,
+ REGISTER_H10,
+ REGISTER_W,
+ REGISTER_D1,
+ REGISTER_D10,
+ REGISTER_MO1,
+ REGISTER_MO10,
+ REGISTER_Y1,
+ REGISTER_Y10,
+ REGISTER_REF = 15
+};
+
+
+// days per month
+static const int DAYS_PER_MONTH[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// read_counter -
+//-------------------------------------------------
+
+inline int msm5832_device::read_counter(int counter)
+{
+ return (m_reg[counter + 1] * 10) + m_reg[counter];
+}
+
+
+//-------------------------------------------------
+// write_counter -
+//-------------------------------------------------
+
+inline void msm5832_device::write_counter(int counter, int value)
+{
+ m_reg[counter] = value % 10;
+ m_reg[counter + 1] = value / 10;
+}
+
+
+//-------------------------------------------------
+// advance_seconds -
+//-------------------------------------------------
+
+inline void msm5832_device::advance_seconds()
+{
+ int seconds = read_counter(REGISTER_S1);
+
+ seconds++;
+
+ if (seconds > 59)
+ {
+ seconds = 0;
+
+ advance_minutes();
+ }
+
+ write_counter(REGISTER_S1, seconds);
+}
+
+
+//-------------------------------------------------
+// advance_minutes -
+//-------------------------------------------------
+
+inline void msm5832_device::advance_minutes()
+{
+ int minutes = read_counter(REGISTER_MI1);
+ int hours = read_counter(REGISTER_H1);
+ int days = read_counter(REGISTER_D1);
+ int month = read_counter(REGISTER_MO1);
+ int year = read_counter(REGISTER_Y1);
+ int day_of_week = m_reg[REGISTER_W];
+
+ minutes++;
+
+ if (minutes > 59)
+ {
+ minutes = 0;
+ hours++;
+ }
+
+ if (hours > 23)
+ {
+ hours = 0;
+ days++;
+ day_of_week++;
+ }
+
+ if (day_of_week > 6)
+ {
+ day_of_week++;
+ }
+
+ if (days > DAYS_PER_MONTH[month - 1])
+ {
+ days = 1;
+ month++;
+ }
+
+ if (month > 12)
+ {
+ month = 1;
+ year++;
+ }
+
+ if (year > 99)
+ {
+ year = 0;
+ }
+
+ write_counter(REGISTER_MI1, minutes);
+ write_counter(REGISTER_H1, hours);
+ write_counter(REGISTER_D1, days);
+ write_counter(REGISTER_MO1, month);
+ write_counter(REGISTER_Y1, year);
+ m_reg[REGISTER_W] = day_of_week;
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// msm5832_device - constructor
+//-------------------------------------------------
+
+msm5832_device::msm5832_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, MSM5832, "MSM5832", tag, owner, clock),
+ device_rtc_interface(mconfig, *this),
+ m_hold(0),
+ m_address(0),
+ m_read(0),
+ m_write(0),
+ m_cs(0)
+{
+ for (int i = 0; i < 13; i++)
+ m_reg[i] = 0;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void msm5832_device::device_start()
+{
+ // allocate timers
+ m_clock_timer = timer_alloc(TIMER_CLOCK);
+ m_clock_timer->adjust(attotime::from_hz(clock() / 32768), 0, attotime::from_hz(clock() / 32768));
+
+ // state saving
+ save_item(NAME(m_reg));
+ save_item(NAME(m_hold));
+ save_item(NAME(m_address));
+ save_item(NAME(m_read));
+ save_item(NAME(m_write));
+ save_item(NAME(m_cs));
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void msm5832_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case TIMER_CLOCK:
+ if (!m_hold)
+ {
+ advance_seconds();
+ }
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// rtc_set_time - called to initialize the RTC to
+// a known state
+//-------------------------------------------------
+
+void msm5832_device::rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second)
+{
+ write_counter(REGISTER_Y1, year);
+ write_counter(REGISTER_MO1, month);
+ write_counter(REGISTER_D1, day);
+ m_reg[REGISTER_W] = day_of_week;
+ write_counter(REGISTER_H1, hour);
+ write_counter(REGISTER_MI1, minute);
+ write_counter(REGISTER_S1, second);
+}
+
+
+//-------------------------------------------------
+// data_r -
+//-------------------------------------------------
+
+READ8_MEMBER( msm5832_device::data_r )
+{
+ UINT8 data = 0;
+
+ if (m_cs && m_read)
+ {
+ if (m_address == REGISTER_REF)
+ {
+ // TODO reference output
+ }
+ else
+ {
+ data = m_reg[m_address];
+ }
+ }
+
+ if (LOG) logerror("MSM5832 '%s' Register Read %01x: %01x\n", tag(), m_address, data & 0x0f);
+
+ return data & 0x0f;
+}
+
+
+//-------------------------------------------------
+// data_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( msm5832_device::data_w )
+{
+ if (LOG) logerror("MSM5832 '%s' Register Write %01x: %01x\n", tag(), m_address, data & 0x0f);
+
+ if (m_cs && m_write)
+ {
+ m_reg[m_address] = data & 0x0f;
+ }
+}
+
+
+//-------------------------------------------------
+// address_w -
+//-------------------------------------------------
+
+void msm5832_device::address_w(UINT8 data)
+{
+ if (LOG) logerror("MSM5832 '%s' Address: %01x\n", tag(), data & 0x0f);
+
+ m_address = data & 0x0f;
+}
+
+
+//-------------------------------------------------
+// adj_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm5832_device::adj_w )
+{
+ if (LOG) logerror("MSM5832 '%s' 30 ADJ: %u\n", tag(), state);
+
+ if (state)
+ {
+ int seconds = read_counter(REGISTER_S1);
+
+ if (seconds < 30)
+ {
+ write_counter(REGISTER_S1, 0);
+ }
+ else
+ {
+ write_counter(REGISTER_S1, 0);
+ advance_minutes();
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// test_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm5832_device::test_w )
+{
+ if (LOG) logerror("MSM5832 '%s' TEST: %u\n", tag(), state);
+}
+
+
+//-------------------------------------------------
+// hold_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm5832_device::hold_w )
+{
+ if (LOG) logerror("MSM5832 '%s' HOLD: %u\n", tag(), state);
+
+ m_hold = state;
+}
+
+
+//-------------------------------------------------
+// read_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm5832_device::read_w )
+{
+ if (LOG) logerror("MSM5832 '%s' READ: %u\n", tag(), state);
+
+ m_read = state;
+}
+
+
+//-------------------------------------------------
+// write_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm5832_device::write_w )
+{
+ if (LOG) logerror("MSM5832 '%s' WR: %u\n", tag(), state);
+
+ m_write = state;
+}
+
+
+//-------------------------------------------------
+// cs_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm5832_device::cs_w )
+{
+ if (LOG) logerror("MSM5832 '%s' CS: %u\n", tag(), state);
+
+ m_cs = state;
+}
diff --git a/trunk/src/emu/machine/msm5832.h b/trunk/src/emu/machine/msm5832.h
new file mode 100644
index 00000000000..a93c2589ffc
--- /dev/null
+++ b/trunk/src/emu/machine/msm5832.h
@@ -0,0 +1,102 @@
+/**********************************************************************
+
+ OKI MSM5832 Real Time Clock/Calendar emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ Vdd 1 |* \_/ | 18 HOLD
+ WRITE 2 | | 17 _XT
+ READ 3 | | 16 XT
+ A0 4 | | 15 +- 30 ADJ
+ A1 5 | MSM5832 | 14 TEST
+ A2 6 | | 13 GND
+ A3 7 | | 12 D3
+ CS 8 | | 11 D2
+ D0 9 |_____________| 10 D1
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __MSM5832__
+#define __MSM5832__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_MSM5832_ADD(_tag, _clock) \
+ MCFG_DEVICE_ADD(_tag, MSM5832, _clock)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> msm5832_device
+
+class msm5832_device : public device_t,
+ public device_rtc_interface
+{
+public:
+ // construction/destruction
+ msm5832_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_READ8_MEMBER( data_r );
+ DECLARE_WRITE8_MEMBER( data_w );
+
+ void address_w(UINT8 data);
+
+ DECLARE_WRITE_LINE_MEMBER( adj_w );
+ DECLARE_WRITE_LINE_MEMBER( test_w );
+ DECLARE_WRITE_LINE_MEMBER( hold_w );
+
+ DECLARE_WRITE_LINE_MEMBER( read_w );
+ DECLARE_WRITE_LINE_MEMBER( write_w );
+ DECLARE_WRITE_LINE_MEMBER( cs_w );
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+ // device_rtc_interface overrides
+ virtual void rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second);
+ virtual bool rtc_is_year_2000_compliant() { return false; }
+
+private:
+ static const device_timer_id TIMER_CLOCK = 0;
+
+ inline int read_counter(int counter);
+ inline void write_counter(int counter, int value);
+ inline void advance_seconds();
+ inline void advance_minutes();
+
+ UINT8 m_reg[13]; // registers
+
+ int m_hold; // counter hold
+ int m_address; // address
+
+ int m_read;
+ int m_write;
+ int m_cs;
+
+ // timers
+ emu_timer *m_clock_timer;
+};
+
+
+// device type definition
+extern const device_type MSM5832;
+
+
+
+#endif
diff --git a/trunk/src/emu/machine/msm58321.c b/trunk/src/emu/machine/msm58321.c
new file mode 100644
index 00000000000..9fdeb8c9e66
--- /dev/null
+++ b/trunk/src/emu/machine/msm58321.c
@@ -0,0 +1,452 @@
+/**********************************************************************
+
+ OKI MSM58321RS Real Time Clock/Calendar emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+/*
+
+ TODO:
+
+ - 12/24 hour
+ - AM/PM
+ - leap year
+ - stop
+ - reset
+ - reference registers
+
+*/
+
+#include "msm58321.h"
+
+
+// device type definition
+const device_type MSM58321 = &device_creator<msm58321_device>;
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+
+// registers
+enum
+{
+ REGISTER_S1 = 0,
+ REGISTER_S10,
+ REGISTER_MI1,
+ REGISTER_MI10,
+ REGISTER_H1,
+ REGISTER_H10,
+ REGISTER_W,
+ REGISTER_D1,
+ REGISTER_D10,
+ REGISTER_MO1,
+ REGISTER_MO10,
+ REGISTER_Y1,
+ REGISTER_Y10,
+ REGISTER_RESET,
+ REGISTER_REF0,
+ REGISTER_REF1
+};
+
+
+// days per month
+static const int DAYS_PER_MONTH[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// read_counter -
+//-------------------------------------------------
+
+inline int msm58321_device::read_counter(int counter)
+{
+ return (m_reg[counter + 1] * 10) + m_reg[counter];
+}
+
+
+//-------------------------------------------------
+// write_counter -
+//-------------------------------------------------
+
+inline void msm58321_device::write_counter(int counter, int value)
+{
+ m_reg[counter] = value % 10;
+ m_reg[counter + 1] = value / 10;
+}
+
+
+//-------------------------------------------------
+// advance_seconds -
+//-------------------------------------------------
+
+inline void msm58321_device::advance_seconds()
+{
+ int seconds = read_counter(REGISTER_S1);
+
+ seconds++;
+
+ if (seconds > 59)
+ {
+ seconds = 0;
+
+ advance_minutes();
+ }
+
+ write_counter(REGISTER_S1, seconds);
+}
+
+
+//-------------------------------------------------
+// advance_minutes -
+//-------------------------------------------------
+
+inline void msm58321_device::advance_minutes()
+{
+ int minutes = read_counter(REGISTER_MI1);
+ int hours = read_counter(REGISTER_H1);
+ int days = read_counter(REGISTER_D1);
+ int month = read_counter(REGISTER_MO1);
+ int year = read_counter(REGISTER_Y1);
+ int day_of_week = m_reg[REGISTER_W];
+
+ minutes++;
+
+ if (minutes > 59)
+ {
+ minutes = 0;
+ hours++;
+ }
+
+ if (hours > 23)
+ {
+ hours = 0;
+ days++;
+ day_of_week++;
+ }
+
+ if (day_of_week > 6)
+ {
+ day_of_week++;
+ }
+
+ if (days > DAYS_PER_MONTH[month - 1])
+ {
+ days = 1;
+ month++;
+ }
+
+ if (month > 12)
+ {
+ month = 1;
+ year++;
+ }
+
+ if (year > 99)
+ {
+ year = 0;
+ }
+
+ write_counter(REGISTER_MI1, minutes);
+ write_counter(REGISTER_H1, hours);
+ write_counter(REGISTER_D1, days);
+ write_counter(REGISTER_MO1, month);
+ write_counter(REGISTER_Y1, year);
+ m_reg[REGISTER_W] = day_of_week;
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// msm58321_device - constructor
+//-------------------------------------------------
+
+msm58321_device::msm58321_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, MSM58321, "MSM58321", tag, owner, clock),
+ device_rtc_interface(mconfig, *this)
+{
+ for (int i = 0; i < 13; i++)
+ m_reg[i] = 0;
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void msm58321_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const msm58321_interface *intf = reinterpret_cast<const msm58321_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<msm58321_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_out_busy_cb, 0, sizeof(m_out_busy_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void msm58321_device::device_start()
+{
+ // resolve callbacks
+ m_out_busy_func.resolve(m_out_busy_cb, *this);
+
+ // allocate timers
+ m_clock_timer = timer_alloc(TIMER_CLOCK);
+ m_clock_timer->adjust(attotime::from_hz(clock() / 32768), 0, attotime::from_hz(clock() / 32768));
+
+ m_busy_timer = timer_alloc(TIMER_BUSY);
+ m_busy_timer->adjust(attotime::from_hz(clock() / 16384), 0, attotime::from_hz(clock() / 16384));
+
+ // state saving
+ save_item(NAME(m_cs1));
+ save_item(NAME(m_cs2));
+ save_item(NAME(m_busy));
+ save_item(NAME(m_read));
+ save_item(NAME(m_write));
+ save_item(NAME(m_address_write));
+ save_item(NAME(m_reg));
+ save_item(NAME(m_latch));
+ save_item(NAME(m_address));
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void msm58321_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case TIMER_CLOCK:
+ advance_seconds();
+ break;
+
+ case TIMER_BUSY:
+ m_out_busy_func(m_busy);
+ m_busy = !m_busy;
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// rtc_set_time - called to initialize the RTC to
+// a known state
+//-------------------------------------------------
+
+void msm58321_device::rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second)
+{
+ write_counter(REGISTER_Y1, year);
+ write_counter(REGISTER_MO1, month);
+ write_counter(REGISTER_D1, day);
+ m_reg[REGISTER_W] = day_of_week;
+ write_counter(REGISTER_H1, hour);
+ write_counter(REGISTER_MI1, minute);
+ write_counter(REGISTER_S1, second);
+}
+
+
+//-------------------------------------------------
+// read -
+//-------------------------------------------------
+
+READ8_MEMBER( msm58321_device::read )
+{
+ UINT8 data = 0;
+
+ if (m_cs1 && m_cs2)
+ {
+ if (m_read)
+ {
+ switch (m_address)
+ {
+ case REGISTER_RESET:
+ break;
+
+ case REGISTER_REF0:
+ case REGISTER_REF1:
+ break;
+
+ default:
+ data = m_reg[m_address];
+ break;
+ }
+ }
+
+ if (m_write)
+ {
+ if (m_address >= REGISTER_REF0)
+ {
+ // TODO: output reference values
+ }
+ }
+ }
+
+ if (LOG) logerror("MSM58321 '%s' Register Read %01x: %01x\n", tag(), m_address, data & 0x0f);
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// write -
+//-------------------------------------------------
+
+WRITE8_MEMBER( msm58321_device::write )
+{
+ // latch data for future use
+ m_latch = data & 0x0f;
+
+ if (!m_cs1 || !m_cs2) return;
+
+ if (m_address_write)
+ {
+ if (LOG) logerror("MSM58321 '%s' Latch Address %01x\n", tag(), m_latch);
+
+ // latch address
+ m_address = m_latch;
+ }
+
+ if (m_write)
+ {
+ switch(m_address)
+ {
+ case REGISTER_RESET:
+ if (LOG) logerror("MSM58321 '%s' Reset\n", tag());
+ break;
+
+ case REGISTER_REF0:
+ case REGISTER_REF1:
+ if (LOG) logerror("MSM58321 '%s' Reference Signal\n", tag());
+ break;
+
+ default:
+ if (LOG) logerror("MSM58321 '%s' Register Write %01x: %01x\n", tag(), m_address, data & 0x0f);
+ m_reg[m_address] = m_latch & 0x0f;
+ break;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// cs1_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm58321_device::cs1_w )
+{
+ if (LOG) logerror("MSM58321 '%s' CS1: %u\n", tag(), state);
+
+ m_cs1 = state;
+}
+
+
+//-------------------------------------------------
+// cs2_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm58321_device::cs2_w )
+{
+ if (LOG) logerror("MSM58321 '%s' CS2: %u\n", tag(), state);
+
+ m_cs2 = state;
+}
+
+
+//-------------------------------------------------
+// read_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm58321_device::read_w )
+{
+ if (LOG) logerror("MSM58321 '%s' READ: %u\n", tag(), state);
+
+ m_read = state;
+}
+
+
+//-------------------------------------------------
+// write_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm58321_device::write_w )
+{
+ if (LOG) logerror("MSM58321 '%s' WRITE: %u\n", tag(), state);
+
+ m_write = state;
+}
+
+
+//-------------------------------------------------
+// address_write_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm58321_device::address_write_w )
+{
+ if (LOG) logerror("MSM58321 '%s' ADDRESS WRITE: %u\n", tag(), state);
+
+ m_address_write = state;
+
+ if (m_address_write)
+ {
+ if (LOG) logerror("MSM58321 '%s' Latch Address %01x\n", tag(), m_latch);
+
+ // latch address
+ m_address = m_latch;
+ }
+}
+
+
+//-------------------------------------------------
+// stop_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm58321_device::stop_w )
+{
+ if (LOG) logerror("MSM58321 '%s' STOP: %u\n", tag(), state);
+}
+
+
+//-------------------------------------------------
+// test_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm58321_device::test_w )
+{
+ if (LOG) logerror("MSM58321 '%s' TEST: %u\n", tag(), state);
+}
+
+
+//-------------------------------------------------
+// busy_r -
+//-------------------------------------------------
+
+READ_LINE_MEMBER( msm58321_device::busy_r )
+{
+ return m_busy;
+}
diff --git a/trunk/src/emu/machine/msm58321.h b/trunk/src/emu/machine/msm58321.h
new file mode 100644
index 00000000000..a2e55f00ea7
--- /dev/null
+++ b/trunk/src/emu/machine/msm58321.h
@@ -0,0 +1,121 @@
+/**********************************************************************
+
+ OKI MSM58321RS Real Time Clock/Calendar emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ CS2 1 |* \_/ | 16 Vdd
+ WRITE 2 | | 15 XT
+ READ 3 | | 14 _XT
+ D0 4 | MSM58321 | 13 CS1
+ D1 5 | RTC58321 | 12 TEST
+ D2 6 | | 11 STOP
+ D3 7 | | 10 _BUSY
+ GND 8 |_____________| 9 ADDRESS WRITE
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __MSM58321__
+#define __MSM58321__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_MSM58321_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD(_tag, MSM58321, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MSM58321_INTERFACE(name) \
+ const msm58321_interface (name) =
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> msm58321_interface
+
+struct msm58321_interface
+{
+ devcb_write_line m_out_busy_cb;
+};
+
+
+
+// ======================> msm58321_device
+
+class msm58321_device : public device_t,
+ public device_rtc_interface,
+ public msm58321_interface
+{
+public:
+ // construction/destruction
+ msm58321_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_READ8_MEMBER( read );
+ DECLARE_WRITE8_MEMBER( write );
+
+ DECLARE_WRITE_LINE_MEMBER( cs1_w );
+ DECLARE_WRITE_LINE_MEMBER( cs2_w );
+ DECLARE_WRITE_LINE_MEMBER( read_w );
+ DECLARE_WRITE_LINE_MEMBER( write_w );
+ DECLARE_WRITE_LINE_MEMBER( address_write_w );
+ DECLARE_WRITE_LINE_MEMBER( stop_w );
+ DECLARE_WRITE_LINE_MEMBER( test_w );
+ DECLARE_READ_LINE_MEMBER( busy_r );
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+ // device_rtc_interface overrides
+ virtual void rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second);
+ virtual bool rtc_is_year_2000_compliant() { return false; }
+
+private:
+ static const device_timer_id TIMER_CLOCK = 0;
+ static const device_timer_id TIMER_BUSY = 1;
+
+ inline int read_counter(int counter);
+ inline void write_counter(int counter, int value);
+ inline void advance_seconds();
+ inline void advance_minutes();
+
+ devcb_resolved_write_line m_out_busy_func;
+
+ int m_cs1; // chip select 1
+ int m_cs2; // chip select 2
+ int m_busy; // busy flag
+ int m_read; // read data
+ int m_write; // write data
+ int m_address_write; // write address
+
+ UINT8 m_reg[13]; // registers
+ UINT8 m_latch; // data latch (not present in real chip)
+ UINT8 m_address; // address latch
+
+ // timers
+ emu_timer *m_clock_timer;
+ emu_timer *m_busy_timer;
+};
+
+
+// device type definition
+extern const device_type MSM58321;
+
+
+
+#endif
diff --git a/trunk/src/emu/machine/msm6242.c b/trunk/src/emu/machine/msm6242.c
new file mode 100644
index 00000000000..8ba28098905
--- /dev/null
+++ b/trunk/src/emu/machine/msm6242.c
@@ -0,0 +1,204 @@
+/***************************************************************************
+
+ MSM6242 Real Time Clock
+
+***************************************************************************/
+
+#include "emu.h"
+#include "machine/msm6242.h"
+
+
+enum
+{
+ MSM6242_REG_S1 = 0,
+ MSM6242_REG_S10,
+ MSM6242_REG_MI1,
+ MSM6242_REG_MI10,
+ MSM6242_REG_H1,
+ MSM6242_REG_H10,
+ MSM6242_REG_D1,
+ MSM6242_REG_D10,
+ MSM6242_REG_MO1,
+ MSM6242_REG_MO10,
+ MSM6242_REG_Y1,
+ MSM6242_REG_Y10,
+ MSM6242_REG_W,
+ MSM6242_REG_CD,
+ MSM6242_REG_CE,
+ MSM6242_REG_CF
+};
+
+
+typedef struct _msm6242_t msm6242_t;
+struct _msm6242_t
+{
+ UINT8 reg[3];
+ system_time hold_time;
+};
+
+
+/* makes sure that the passed in device is the right type */
+INLINE msm6242_t *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == MSM6242);
+
+ return (msm6242_t *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+READ8_DEVICE_HANDLER( msm6242_r )
+{
+ system_time curtime, *systime = &curtime;
+ msm6242_t *msm6242 = get_safe_token(device);
+
+ if (msm6242->reg[0] & 1) /* if HOLD is set, use the hold time */
+ {
+ systime = &msm6242->hold_time;
+ }
+ else /* otherwise, use the current time */
+ {
+ device->machine().current_datetime(curtime);
+ }
+
+ switch(offset)
+ {
+ case MSM6242_REG_S1: return systime->local_time.second % 10;
+ case MSM6242_REG_S10: return systime->local_time.second / 10;
+ case MSM6242_REG_MI1: return systime->local_time.minute % 10;
+ case MSM6242_REG_MI10: return systime->local_time.minute / 10;
+ case MSM6242_REG_H1:
+ case MSM6242_REG_H10:
+ {
+ int hour = systime->local_time.hour;
+ int pm = 0;
+
+ /* check for 12/24 hour mode */
+ if ((msm6242->reg[2] & 0x04) == 0) /* 12 hour mode? */
+ {
+ if (hour >= 12)
+ pm = 1;
+
+ hour %= 12;
+
+ if ( hour == 0 )
+ hour = 12;
+ }
+
+ if ( offset == MSM6242_REG_H1 )
+ return hour % 10;
+
+ return (hour / 10) | (pm <<2);
+ }
+
+ case MSM6242_REG_D1: return systime->local_time.mday % 10;
+ case MSM6242_REG_D10: return systime->local_time.mday / 10;
+ case MSM6242_REG_MO1: return (systime->local_time.month+1) % 10;
+ case MSM6242_REG_MO10: return (systime->local_time.month+1) / 10;
+ case MSM6242_REG_Y1: return systime->local_time.year % 10;
+ case MSM6242_REG_Y10: return (systime->local_time.year % 100) / 10;
+ case MSM6242_REG_W: return systime->local_time.weekday;
+ case MSM6242_REG_CD: return msm6242->reg[0];
+ case MSM6242_REG_CE: return msm6242->reg[1];
+ case MSM6242_REG_CF: return msm6242->reg[2];
+ }
+
+ logerror("%s: MSM6242 unmapped offset %02x read\n", device->machine().describe_context(), offset);
+ return 0;
+}
+
+
+WRITE8_DEVICE_HANDLER( msm6242_w )
+{
+ msm6242_t *msm6242 = get_safe_token(device);
+
+ switch(offset)
+ {
+ case MSM6242_REG_CD:
+ {
+ msm6242->reg[0] = data & 0x0f;
+
+ if (data & 1) /* was Hold set? */
+ {
+ device->machine().current_datetime(msm6242->hold_time);
+ }
+
+ return;
+ }
+
+ case MSM6242_REG_CE: msm6242->reg[1] = data & 0x0f; return;
+
+ case MSM6242_REG_CF:
+ {
+ /* the 12/24 mode bit can only be changed while REST is 1 */
+ if ((data ^ msm6242->reg[2]) & 0x04)
+ {
+ msm6242->reg[2] = (msm6242->reg[2] & 0x04) | (data & ~0x04);
+
+ if (msm6242->reg[2] & 1)
+ msm6242->reg[2] = (msm6242->reg[2] & ~0x04) | (data & 0x04);
+ }
+ else
+ {
+ msm6242->reg[2] = data & 0x0f;
+ }
+ return;
+ }
+ }
+
+ logerror("%s: MSM6242 unmapped offset %02x written with %02x\n", device->machine().describe_context(), offset, data);
+}
+
+
+static DEVICE_START( msm6242 )
+{
+ msm6242_t *msm6242 = get_safe_token(device);
+
+ msm6242->reg[0] = 0;
+ msm6242->reg[1] = 0;
+ msm6242->reg[2] = 0;
+ memset(&msm6242->hold_time, 0, sizeof(system_time));
+}
+
+
+DEVICE_GET_INFO( msm6242 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(msm6242_t); break;
+ case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(msm6242); break;
+ case DEVINFO_FCT_STOP: /* Nothing */ break;
+ case DEVINFO_FCT_RESET: /* Nothing */ break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "OKI MSM6242"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "MSM6242 RTC"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.00"); 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;
+ }
+}
+
+
+
+
+
+#if 0
+READ16_HANDLER( msm6242_lsb_r )
+{
+ return msm6242_r(space, offset);
+}
+
+WRITE16_HANDLER( msm6242_lsb_w )
+{
+ if (ACCESSING_BITS_0_7)
+ msm6242_w(space, offset, data);
+}
+#endif
+
+
+DEFINE_LEGACY_DEVICE(MSM6242, msm6242);
diff --git a/trunk/src/emu/machine/msm6242.h b/trunk/src/emu/machine/msm6242.h
new file mode 100644
index 00000000000..9bf403701e9
--- /dev/null
+++ b/trunk/src/emu/machine/msm6242.h
@@ -0,0 +1,28 @@
+/***************************************************************************
+
+ MSM6242 Real Time Clock
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __MSM6242_H__
+#define __MSM6242_H__
+
+#include "devlegcy.h"
+
+
+DECLARE_LEGACY_DEVICE(MSM6242, msm6242);
+
+#define MCFG_MSM6242_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, MSM6242, 0)
+
+
+READ8_DEVICE_HANDLER( msm6242_r );
+WRITE8_DEVICE_HANDLER( msm6242_w );
+
+
+#endif /* __MSM6242_H__ */
diff --git a/trunk/src/emu/machine/nmc9306.c b/trunk/src/emu/machine/nmc9306.c
new file mode 100644
index 00000000000..627f282bd93
--- /dev/null
+++ b/trunk/src/emu/machine/nmc9306.c
@@ -0,0 +1,322 @@
+/**********************************************************************
+
+ National Semiconductor NMC9306 256-Bit Serial EEPROM emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "nmc9306.h"
+#include "machine/devhelpr.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 1
+
+#define RAM_SIZE 32
+
+
+// instructions
+enum
+{
+ OTHER = 0,
+ WRITE, // write register A3A2A1A0
+ READ, // read register A3A2A1A0
+ ERASE // erase register A3A2A1A0
+};
+
+// other instructions
+enum
+{
+ EWDS = 0, // erase/write disable
+ WRAL, // write all registers
+ ERAL, // erase all registers
+ EWEN, // erase/write enable
+};
+
+// states
+enum
+{
+ STATE_IDLE = 0,
+ STATE_COMMAND,
+ STATE_ADDRESS,
+ STATE_DATA_IN,
+ STATE_DATA_OUT,
+ STATE_ERASE
+};
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+// device type definition
+const device_type NMC9306 = &device_creator<nmc9306_device>;
+
+//-------------------------------------------------
+// nmc9306_device - constructor
+//-------------------------------------------------
+
+inline UINT16 nmc9306_device::read(offs_t offset)
+{
+ return m_register[offset];
+}
+
+
+//-------------------------------------------------
+// nmc9306_device - constructor
+//-------------------------------------------------
+
+inline void nmc9306_device::write(offs_t offset, UINT16 data)
+{
+ if (m_ewen)
+ {
+ m_register[offset] &= data;
+ }
+}
+
+
+//-------------------------------------------------
+// nmc9306_device - constructor
+//-------------------------------------------------
+
+inline void nmc9306_device::erase(offs_t offset)
+{
+ if (m_ewen)
+ {
+ m_register[offset] = 0xffff;
+ }
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nmc9306_device - constructor
+//-------------------------------------------------
+
+nmc9306_device::nmc9306_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, NMC9306, "NMC9306", tag, owner, clock),
+ device_nvram_interface(mconfig, *this),
+ m_state(STATE_IDLE),
+ m_ewen(false)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void nmc9306_device::device_start()
+{
+ // state saving
+ save_item(NAME(m_bits));
+ save_item(NAME(m_state));
+ save_item(NAME(m_command));
+ save_item(NAME(m_address));
+ save_item(NAME(m_data));
+ save_item(NAME(m_ewen));
+ save_item(NAME(m_cs));
+ save_item(NAME(m_sk));
+ save_item(NAME(m_do));
+ save_item(NAME(m_di));
+}
+
+
+//-------------------------------------------------
+// nvram_default - called to initialize NVRAM to
+// its default state
+//-------------------------------------------------
+
+void nmc9306_device::nvram_default()
+{
+}
+
+
+//-------------------------------------------------
+// nvram_read - called to read NVRAM from the
+// .nv file
+//-------------------------------------------------
+
+void nmc9306_device::nvram_read(emu_file &file)
+{
+ file.read(m_register, RAM_SIZE);
+}
+
+
+//-------------------------------------------------
+// nvram_write - called to write NVRAM to the
+// .nv file
+//-------------------------------------------------
+
+void nmc9306_device::nvram_write(emu_file &file)
+{
+ file.write(m_register, RAM_SIZE);
+}
+
+
+//-------------------------------------------------
+// cs_w - chip select input
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( nmc9306_device::cs_w )
+{
+ m_cs = state;
+}
+
+
+//-------------------------------------------------
+// ck_w - serial clock input
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( nmc9306_device::sk_w )
+{
+ m_sk = state;
+
+ if (!m_cs || !m_sk) return;
+
+ switch (m_state)
+ {
+ case STATE_IDLE:
+ if (LOG) logerror("NMC9306 '%s' Idle %u\n", tag(), m_di);
+
+ if (m_di)
+ {
+ // start bit received
+ m_state = STATE_COMMAND;
+ m_bits = 0;
+ }
+ break;
+
+ case STATE_COMMAND:
+ if (LOG) logerror("NMC9306 '%s' Command Bit %u\n", tag(), m_di);
+
+ m_command <<= 1;
+ m_command |= m_di;
+ m_bits++;
+
+ if (m_bits == 4)
+ {
+ m_state = STATE_ADDRESS;
+ m_bits = 0;
+ }
+ break;
+
+ case STATE_ADDRESS:
+ if (LOG) logerror("NMC9306 '%s' Address Bit %u\n", tag(), m_di);
+
+ m_address <<= 1;
+ m_address |= m_di;
+ m_bits++;
+
+ if (m_bits == 4)
+ {
+ switch ((m_command >> 2) & 0x03)
+ {
+ case OTHER:
+ switch (m_command & 0x03)
+ {
+ case EWDS:
+ if (LOG) logerror("NMC9306 '%s' EWDS\n", tag());
+ m_ewen = false;
+ m_state = STATE_IDLE;
+ break;
+
+ case WRAL:
+ if (LOG) logerror("NMC9306 '%s' WRAL\n", tag());
+ break;
+
+ case ERAL:
+ if (LOG) logerror("NMC9306 '%s' ERAL\n", tag());
+ break;
+
+ case EWEN:
+ if (LOG) logerror("NMC9306 '%s' EWEN\n", tag());
+ m_ewen = true;
+ m_state = STATE_IDLE;
+ break;
+ }
+ break;
+
+ case WRITE:
+ if (LOG) logerror("NMC9306 '%s' WRITE %u\n", tag(), m_address & 0x0f);
+ m_state = STATE_DATA_IN;
+ break;
+
+ case READ:
+ if (LOG) logerror("NMC9306 '%s' READ %u\n", tag(), m_address & 0x0f);
+ m_data = read(m_address & 0x0f);
+ m_state = STATE_DATA_OUT;
+ break;
+
+ case ERASE:
+ if (LOG) logerror("NMC9306 '%s' ERASE %u\n", tag(), m_address & 0x0f);
+ erase(m_address & 0x0f);
+ m_state = STATE_ERASE;
+ break;
+ }
+
+ m_bits = 0;
+ }
+ break;
+
+ case STATE_DATA_IN:
+ if (LOG) logerror("NMC9306 '%s' Data Bit IN %u\n", tag(), m_di);
+
+ m_data <<= 1;
+ m_data |= m_di;
+ m_bits++;
+
+ if (m_bits == 16)
+ {
+ write(m_address & 0x0f, m_data);
+
+ m_state = STATE_IDLE;
+ }
+ break;
+
+ case STATE_DATA_OUT:
+ if (LOG) logerror("NMC9306 '%s' Data Bit OUT %u\n", tag(), m_di);
+
+ m_do = BIT(m_data, 15);
+ m_data <<= 1;
+ m_bits++;
+
+ if (m_bits == 16)
+ {
+ m_state = STATE_IDLE;
+ }
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// di_w - serial data input
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( nmc9306_device::di_w )
+{
+ m_di = state;
+}
+
+
+//-------------------------------------------------
+// do_r - serial data output
+//-------------------------------------------------
+
+READ_LINE_MEMBER( nmc9306_device::do_r )
+{
+ return m_do;
+}
diff --git a/trunk/src/emu/machine/nmc9306.h b/trunk/src/emu/machine/nmc9306.h
new file mode 100644
index 00000000000..6658775d56e
--- /dev/null
+++ b/trunk/src/emu/machine/nmc9306.h
@@ -0,0 +1,94 @@
+/**********************************************************************
+
+ National Semiconductor NMC9306 256-Bit Serial EEPROM emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ CS 1 |* \_/ | 8 Vcc
+ SK 2 | | 7 NC
+ DI 3 | | 6 NC
+ DO 4 |_____________| 5 GND
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __NMC9306__
+#define __NMC9306__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_NMC9306_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, NMC9306, 0)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> nmc9306_device
+
+class nmc9306_device : public device_t,
+ public device_nvram_interface
+{
+public:
+ // construction/destruction
+ nmc9306_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_WRITE_LINE_MEMBER( cs_w );
+ DECLARE_WRITE_LINE_MEMBER( sk_w );
+ DECLARE_WRITE_LINE_MEMBER( di_w );
+ DECLARE_READ_LINE_MEMBER( do_r );
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+
+ // device_nvram_interface overrides
+ virtual void nvram_default();
+ virtual void nvram_read(emu_file &file);
+ virtual void nvram_write(emu_file &file);
+
+private:
+ inline UINT16 read(offs_t offset);
+ inline void write(offs_t offset, UINT16 data);
+ inline void erase(offs_t offset);
+
+ UINT16 m_register[16];
+
+ int m_bits;
+ int m_state;
+ UINT8 m_command;
+ UINT8 m_address;
+ UINT16 m_data;
+ bool m_ewen;
+ int m_cs;
+ int m_sk;
+ int m_do;
+ int m_di;
+};
+
+
+// device type definition
+extern const device_type NMC9306;
+
+
+#endif
diff --git a/trunk/src/emu/machine/nvram.c b/trunk/src/emu/machine/nvram.c
new file mode 100644
index 00000000000..c243208c203
--- /dev/null
+++ b/trunk/src/emu/machine/nvram.c
@@ -0,0 +1,199 @@
+/***************************************************************************
+
+ nvram.c
+
+ Generic non-volatile RAM.
+
+****************************************************************************
+
+ 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 "machine/nvram.h"
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type NVRAM = &device_creator<nvram_device>;
+
+//-------------------------------------------------
+// nvram_device - constructor
+//-------------------------------------------------
+
+nvram_device::nvram_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, NVRAM, "NVRAM", tag, owner, clock),
+ device_nvram_interface(mconfig, *this),
+ m_default_value(DEFAULT_ALL_1),
+ m_base(NULL),
+ m_length(0)
+{
+}
+
+
+//-------------------------------------------------
+// static_set_interface - configuration helper
+// to set the interface
+//-------------------------------------------------
+
+void nvram_device::static_set_default_value(device_t &device, default_value value)
+{
+ nvram_device &nvram = downcast<nvram_device &>(device);
+ nvram.m_default_value = value;
+}
+
+
+//-------------------------------------------------
+// static_set_custom_handler - configuration
+// helper to set a custom callback
+//-------------------------------------------------
+
+void nvram_device::static_set_custom_handler(device_t &device, nvram_init_delegate handler)
+{
+ nvram_device &nvram = downcast<nvram_device &>(device);
+ nvram.m_default_value = DEFAULT_CUSTOM;
+ nvram.m_custom_handler = handler;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void nvram_device::device_start()
+{
+ // bind our handler
+ if (!m_custom_handler.isnull())
+ m_custom_handler = nvram_init_delegate(m_custom_handler, *m_owner);
+}
+
+
+//-------------------------------------------------
+// nvram_default - called to initialize NVRAM to
+// its default state
+//-------------------------------------------------
+
+void nvram_device::nvram_default()
+{
+ // make sure we have a valid base pointer
+ determine_final_base();
+
+ // region always wins
+ if (m_region != NULL)
+ {
+ memcpy(m_base, *m_region, m_length);
+ return;
+ }
+
+ // default values for other cases
+ switch (m_default_value)
+ {
+ // all-0's
+ case DEFAULT_ALL_0:
+ memset(m_base, 0, m_length);
+ break;
+
+ // all 1's
+ default:
+ case DEFAULT_ALL_1:
+ memset(m_base, 0xff, m_length);
+ break;
+
+ // random values
+ case DEFAULT_RANDOM:
+ {
+ UINT8 *nvram = reinterpret_cast<UINT8 *>(m_base);
+ for (int index = 0; index < m_length; index++)
+ nvram[index] = machine().rand();
+ break;
+ }
+
+ // custom handler
+ case DEFAULT_CUSTOM:
+ m_custom_handler(*this, m_base, m_length);
+ break;
+
+ // none - do nothing
+ case DEFAULT_NONE:
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// nvram_read - called to read NVRAM from the
+// .nv file
+//-------------------------------------------------
+
+void nvram_device::nvram_read(emu_file &file)
+{
+ // make sure we have a valid base pointer
+ determine_final_base();
+
+ file.read(m_base, m_length);
+}
+
+
+//-------------------------------------------------
+// nvram_write - called to write NVRAM to the
+// .nv file
+//-------------------------------------------------
+
+void nvram_device::nvram_write(emu_file &file)
+{
+ file.write(m_base, m_length);
+}
+
+
+//-------------------------------------------------
+// determine_final_base - get the final base
+// pointer by looking up the memory share, unless
+// a pointer was provided to us
+//-------------------------------------------------
+
+void nvram_device::determine_final_base()
+{
+ // find our shared pointer with the target RAM
+ if (m_base == NULL)
+ {
+ m_base = memory_get_shared(machine(), tag(), m_length);
+ if (m_base == NULL)
+ throw emu_fatalerror("NVRAM device '%s' has no corresponding AM_SHARE region", tag());
+ }
+
+ // if we are region-backed for the default, find it now and make sure it's the right size
+ if (m_region != NULL && m_region->bytes() != m_length)
+ throw emu_fatalerror("NVRAM device '%s' has a default region, but it should be 0x%X bytes", tag(), m_length);
+}
diff --git a/trunk/src/emu/machine/nvram.h b/trunk/src/emu/machine/nvram.h
new file mode 100644
index 00000000000..06906161ecc
--- /dev/null
+++ b/trunk/src/emu/machine/nvram.h
@@ -0,0 +1,153 @@
+/***************************************************************************
+
+ nvram.h
+
+ Generic non-volatile RAM.
+
+****************************************************************************
+
+ 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 __NVRAM_H__
+#define __NVRAM_H__
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_NVRAM_ADD_0FILL(_tag) \
+ MCFG_DEVICE_ADD(_tag, NVRAM, 0) \
+ nvram_device::static_set_default_value(*device, nvram_device::DEFAULT_ALL_0); \
+
+#define MCFG_NVRAM_ADD_1FILL(_tag) \
+ MCFG_DEVICE_ADD(_tag, NVRAM, 0) \
+ nvram_device::static_set_default_value(*device, nvram_device::DEFAULT_ALL_1); \
+
+#define MCFG_NVRAM_ADD_RANDOM_FILL(_tag) \
+ MCFG_DEVICE_ADD(_tag, NVRAM, 0) \
+ nvram_device::static_set_default_value(*device, nvram_device::DEFAULT_RANDOM); \
+
+#define MCFG_NVRAM_ADD_NO_FILL(_tag) \
+ MCFG_DEVICE_ADD(_tag, NVRAM, 0) \
+ nvram_device::static_set_default_value(*device, nvram_device::DEFAULT_NONE); \
+
+#define MCFG_NVRAM_ADD_CUSTOM(_tag, _class, _method) \
+ MCFG_DEVICE_ADD(_tag, NVRAM, 0) \
+ nvram_device::static_set_custom_handler(*device, nvram_init_delegate(&_class::_method, #_class "::" #_method, (_class *)0)); \
+
+
+#define MCFG_NVRAM_REPLACE_0FILL(_tag) \
+ MCFG_DEVICE_REPLACE(_tag, NVRAM, 0) \
+ nvram_device::static_set_default_value(*device, nvram_device::DEFAULT_ALL_0); \
+
+#define MCFG_NVRAM_REPLACE_1FILL(_tag) \
+ MCFG_DEVICE_REPLACE(_tag, NVRAM, 0) \
+ nvram_device::static_set_default_value(*device, nvram_device::DEFAULT_ALL_1); \
+
+#define MCFG_NVRAM_REPLACE_RANDOM_FILL(_tag) \
+ MCFG_DEVICE_REPLACE(_tag, NVRAM, 0) \
+ nvram_device::static_set_default_value(*device, nvram_device::DEFAULT_RANDOM); \
+
+#define MCFG_NVRAM_REPLACE_CUSTOM(_tag, _class, _method) \
+ MCFG_DEVICE_REPLACE(_tag, NVRAM, 0) \
+ nvram_device::static_set_custom_handler(*device, nvram_init_delegate(&_class::_method, #_class "::" #_method, (_class *)0)); \
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class nvram_device;
+
+
+// custom initialization for default state
+typedef delegate<void (nvram_device &, void *, size_t)> nvram_init_delegate;
+
+
+// ======================> nvram_device
+
+class nvram_device : public device_t,
+ public device_nvram_interface
+{
+public:
+ // values
+ enum default_value
+ {
+ DEFAULT_ALL_0,
+ DEFAULT_ALL_1,
+ DEFAULT_RANDOM,
+ DEFAULT_CUSTOM,
+ DEFAULT_NONE
+ };
+
+ // construction/destruction
+ nvram_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // inline configuration helpers
+ static void static_set_default_value(device_t &device, default_value value);
+ static void static_set_custom_handler(device_t &device, nvram_init_delegate callback);
+
+ // controls
+ void set_base(void *base, size_t length) { m_base = base; m_length = length; }
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+
+ // device_nvram_interface overrides
+ virtual void nvram_default();
+ virtual void nvram_read(emu_file &file);
+ virtual void nvram_write(emu_file &file);
+
+ // internal helpers
+ void determine_final_base();
+
+ // configuration state
+ default_value m_default_value;
+ nvram_init_delegate m_custom_handler;
+
+ // runtime state
+ void * m_base;
+ size_t m_length;
+};
+
+
+// device type definition
+extern const device_type NVRAM;
+
+
+#endif
diff --git a/trunk/src/emu/machine/pc16552d.c b/trunk/src/emu/machine/pc16552d.c
new file mode 100644
index 00000000000..4595d48a85f
--- /dev/null
+++ b/trunk/src/emu/machine/pc16552d.c
@@ -0,0 +1,439 @@
+/*
+ National Semiconductor PC16552D
+ Dual Universal Asynchronous Receiver/Transmitter with FIFOs
+
+ Written by Ville Linde
+*/
+
+#include "emu.h"
+#include "pc16552d.h"
+
+#define REG_RECV_BUFFER 0x0 // Read
+#define REG_XMIT_HOLD 0x0 // Write
+#define REG_INT_ENABLE 0x1
+#define REG_FIFO_CTRL 0x2 // Write
+#define REG_LINE_CTRL 0x3
+#define REG_MODEL_CTRL 0x4
+#define REG_LINE_STATUS 0x5
+#define REG_MODEM_STATUS 0x6
+#define REG_SCRATCH 0x7
+#define REG_DIV_LATCH_LSB 0x0 // When DLAB == 1
+#define REG_DIV_LATCH_MSB 0x1 // When DLAB == 1
+#define REG_ALT_FUNCTION 0x2 // When DLAB == 1
+
+#define LINE_CTRL_DLAB 0x80
+
+#define IRQ_RX_LINE_STATUS 0x1
+#define IRQ_RX_DATA_AVAILABLE 0x2
+#define IRQ_CHARACTER_TIMEOUT 0x4
+#define IRQ_TX_HOLDING_REG_EMPTY 0x8
+#define IRQ_MODEM_STATUS 0x10
+
+#define INT_ENABLE_RX_DATA 0x01
+#define INT_ENABLE_TX_EMPTY 0x02
+#define INT_ENABLE_RX_LINE_STATUS 0x04
+#define INT_ENABLE_MODEM_STATUS 0x08
+
+typedef struct
+{
+ UINT16 divisor;
+ UINT8 reg[8];
+ UINT8 rx_fifo[16];
+ UINT8 tx_fifo[16];
+ int pending_interrupt;
+ int rx_fifo_read_ptr;
+ int rx_fifo_write_ptr;
+ int rx_fifo_num;
+ int tx_fifo_read_ptr;
+ int tx_fifo_write_ptr;
+ int tx_fifo_num;
+ emu_timer *tx_fifo_timer;
+} PC16552D_CHANNEL;
+
+typedef struct
+{
+ PC16552D_CHANNEL ch[2];
+ int frequency;
+ void (* irq_handler)(running_machine &machine, int channel, int value);
+ void (* tx_callback)(int channel, int count, UINT8* data);
+} PC16552D_REGS;
+
+#define MAX_PC16552D_CHIPS 4
+
+static PC16552D_REGS duart[MAX_PC16552D_CHIPS];
+
+
+
+static const int rx_trigger_level[4] = { 1, 4, 8, 14 };
+
+
+static void check_interrupts(running_machine &machine, int chip, int channel)
+{
+ PC16552D_CHANNEL *ch = &duart[chip].ch[channel];
+ int signal = 0;
+
+ if (ch->pending_interrupt != 0)
+ {
+ if (((ch->reg[REG_INT_ENABLE] & INT_ENABLE_RX_DATA) && (ch->pending_interrupt & IRQ_RX_DATA_AVAILABLE)) ||
+ ((ch->reg[REG_INT_ENABLE] & INT_ENABLE_TX_EMPTY) && (ch->pending_interrupt & IRQ_TX_HOLDING_REG_EMPTY)) ||
+ ((ch->reg[REG_INT_ENABLE] & INT_ENABLE_RX_LINE_STATUS) && (ch->pending_interrupt & IRQ_RX_LINE_STATUS)) ||
+ ((ch->reg[REG_INT_ENABLE] & INT_ENABLE_MODEM_STATUS) && (ch->pending_interrupt & IRQ_MODEM_STATUS)))
+ {
+ signal = 1;
+ }
+ }
+
+ if (duart[chip].irq_handler != NULL)
+ {
+ duart[chip].irq_handler(machine, channel, signal ? ASSERT_LINE : CLEAR_LINE);
+ }
+}
+
+static void duart_push_rx_fifo(running_machine &machine, int chip, int channel, UINT8 data)
+{
+ PC16552D_CHANNEL *ch = &duart[chip].ch[channel];
+
+ if (ch->rx_fifo_num >= 16)
+ {
+ printf("duart_push_rx_fifo: %d, %d, %02X, FIFO overflow\n", chip, channel, data);
+ return;
+ }
+
+ ch->rx_fifo[ch->rx_fifo_write_ptr++] = data;
+ if (ch->rx_fifo_write_ptr == 16)
+ {
+ ch->rx_fifo_write_ptr = 0;
+ }
+ ch->rx_fifo_num++;
+
+ if (ch->rx_fifo_num == rx_trigger_level[(ch->reg[REG_FIFO_CTRL] >> 6) & 3])
+ {
+ ch->pending_interrupt |= IRQ_RX_DATA_AVAILABLE; // INT ID: received data available
+
+ check_interrupts(machine, chip, channel);
+ }
+}
+
+static UINT8 duart_pop_rx_fifo(running_machine &machine, int chip, int channel)
+{
+ UINT8 r;
+ PC16552D_CHANNEL *ch = &duart[chip].ch[channel];
+
+ if (ch->rx_fifo_num == 0)
+ {
+ printf("duart_pop_rx_fifo: %d, %d, FIFO underflow\n", chip, channel);
+ return 0;
+ }
+
+ r = ch->rx_fifo[ch->rx_fifo_read_ptr++];
+ if (ch->rx_fifo_read_ptr == 16)
+ {
+ ch->rx_fifo_read_ptr = 0;
+ }
+ ch->rx_fifo_num--;
+
+ if (ch->rx_fifo_num < rx_trigger_level[(ch->reg[REG_FIFO_CTRL] >> 6) & 3])
+ {
+ ch->pending_interrupt &= ~IRQ_RX_DATA_AVAILABLE;
+
+ check_interrupts(machine, chip, channel);
+ }
+
+ return r;
+}
+
+static TIMER_CALLBACK( tx_fifo_timer_callback )
+{
+ PC16552D_CHANNEL *ch;
+ int chip = param >> 1;
+ int channel = param & 1;
+
+ ch = &duart[chip].ch[channel];
+
+ if (duart[chip].tx_callback)
+ duart[chip].tx_callback(channel, ch->tx_fifo_num, ch->tx_fifo);
+
+ ch->tx_fifo_num = 0;
+
+ // set transmitter empty interrupt
+ ch->pending_interrupt |= IRQ_TX_HOLDING_REG_EMPTY;
+ check_interrupts(machine, chip, channel);
+
+ duart[chip].ch[channel].tx_fifo_timer->adjust(attotime::never, (chip * 2) + channel);
+}
+
+static void duart_push_tx_fifo(int chip, int channel, UINT8 data)
+{
+ attotime period;
+ PC16552D_CHANNEL *ch = &duart[chip].ch[channel];
+
+ ch->tx_fifo[ch->tx_fifo_num] = data;
+ ch->tx_fifo_num++;
+
+ period = attotime::from_hz(duart[chip].frequency) * (ch->divisor * 16 * 16 * 8);
+
+ duart[chip].ch[channel].tx_fifo_timer->adjust(period, (chip * 2) + channel);
+}
+
+#ifdef UNUSED_FUNCTION
+static UINT8 duart_pop_tx_fifo(int chip, int channel, UINT8 data)
+{
+ return 0;
+}
+#endif
+
+
+static UINT8 duart_r(running_machine &machine, int chip, int reg)
+{
+ int channel = (reg >> 3) & 1;
+ PC16552D_CHANNEL *ch = &duart[chip].ch[channel];
+ reg &= 7;
+
+// printf("duart_r: chip %d, ch %d, reg %d\n", chip, channel, reg);
+
+ switch (reg)
+ {
+ case 0:
+ {
+ if (ch->reg[REG_LINE_CTRL] & LINE_CTRL_DLAB)
+ {
+ // Divisor Latch (LSB)
+ return ch->divisor & 0xff;
+ }
+ else
+ {
+ // Receiver Buffer
+ ch->pending_interrupt &= ~IRQ_RX_DATA_AVAILABLE;
+
+ check_interrupts(machine, chip, channel);
+
+ return duart_pop_rx_fifo(machine, chip, channel);
+ }
+ }
+ case 1:
+ {
+ if (ch->reg[REG_LINE_CTRL] & LINE_CTRL_DLAB)
+ {
+ // Divisor Latch (MSB)
+ return (ch->divisor >> 8) & 0xff;
+ }
+ else
+ {
+
+ }
+ break;
+ }
+
+ case 2:
+ {
+ if (ch->reg[REG_LINE_CTRL] & LINE_CTRL_DLAB)
+ {
+ // Alternate Function
+ }
+ else
+ {
+ // Interrupt Identification Register
+ int i;
+ UINT8 r = 0x01;
+
+ for (i=0; i < 5; i++)
+ {
+ if (ch->pending_interrupt & (1 << i))
+ {
+ switch (i)
+ {
+ case 0: r = 0x06; break; // Receiver Line Status
+ case 1: r = 0x04; break; // Received Data Available
+ case 2: r = 0x0c; break; // Character Timeout Indication
+ case 3: r = 0x02; break; // Transmitter Holding Register Empty
+ case 4: r = 0x00; break; // MODEM Status
+ }
+ break;
+ }
+ }
+
+ if (ch->reg[REG_FIFO_CTRL] & 1)
+ {
+ r |= 0xc0;
+ }
+
+ return r;
+ }
+ break;
+ }
+
+ case 5: // Line Status Register
+ {
+ UINT8 r = 0;
+
+ // set Data Ready flag
+ if (ch->rx_fifo_num > 0)
+ {
+ r |= 0x1;
+ }
+
+ // set Transmitter Holding Register Empty flag
+ if (ch->tx_fifo_num == 0)
+ {
+ r |= 0x20;
+ }
+
+ // set Transmitter Empty flag
+ if (ch->tx_fifo_num == 0)
+ {
+ r |= 0x40;
+ }
+
+ return r;
+ }
+ }
+
+ return ch->reg[reg];
+}
+
+static void duart_w(running_machine &machine, int chip, int reg, UINT8 data)
+{
+ int channel = (reg >> 3) & 1;
+ PC16552D_CHANNEL *ch = &duart[chip].ch[channel];
+ reg &= 7;
+
+// printf("duart_w: chip %d, ch %d, reg %d, data %02X\n", chip, channel, reg, data);
+
+ switch (reg)
+ {
+ case 0:
+ {
+ if (ch->reg[REG_LINE_CTRL] & LINE_CTRL_DLAB)
+ {
+ // Divisor Latch (LSB)
+ ch->divisor &= 0xff00;
+ ch->divisor |= data;
+
+ return;
+ }
+ else
+ {
+ // Transmitter Holding Register
+ duart_push_tx_fifo(chip, channel, data);
+
+ ch->pending_interrupt &= ~IRQ_TX_HOLDING_REG_EMPTY;
+ check_interrupts(machine, chip, channel);
+
+ return;
+ }
+ }
+ case 1:
+ {
+ if (ch->reg[REG_LINE_CTRL] & LINE_CTRL_DLAB)
+ {
+ // Divisor Latch (MSB)
+ ch->divisor &= 0x00ff;
+ ch->divisor |= data << 8;
+
+ // printf("DUART %d %d bps\n", chip, duart[chip].frequency / (ch->divisor * 16));
+ return;
+ }
+ else
+ {
+ // Interrupt enable
+ ch->reg[REG_INT_ENABLE] = data;
+
+ check_interrupts(machine, chip, channel);
+ return;
+ }
+ }
+
+ case 2:
+ {
+ if (ch->reg[REG_LINE_CTRL] & LINE_CTRL_DLAB)
+ {
+ // Alternate Function
+
+ return;
+ }
+ else
+ {
+ // FIFO control
+ if (data & 0x02)
+ {
+ ch->rx_fifo_write_ptr = 0;
+ ch->rx_fifo_read_ptr = 0;
+ ch->rx_fifo_num = 0;
+ }
+ if (data & 0x04)
+ {
+ ch->tx_fifo_write_ptr = 0;
+ ch->tx_fifo_read_ptr = 0;
+ ch->tx_fifo_num = 0;
+
+
+ }
+
+ /*if (data & 0x1 && (ch->reg[reg] & 0x1) == 0)
+ {
+ // cause transmitter empty IRQ
+ ch->pending_interrupt |= IRQ_TX_HOLDING_REG_EMPTY;
+
+ check_interrupts(machine, chip, channel);
+ }
+ */
+ }
+ break;
+ }
+ }
+
+ ch->reg[reg] = data;
+}
+
+/*****************************************************************************/
+
+void pc16552d_init(running_machine &machine, int chip, int frequency, void (* irq_handler)(running_machine &machine, int channel, int value), void (* tx_callback)(int channel, int count, UINT8* data))
+{
+ memset(&duart[chip], 0, sizeof(PC16552D_REGS));
+
+ duart[chip].frequency = frequency;
+ duart[chip].irq_handler = irq_handler;
+ duart[chip].tx_callback = tx_callback;
+
+ // clear interrupts
+ duart[chip].ch[0].pending_interrupt = 0;
+ duart[chip].ch[1].pending_interrupt = 0;
+
+ // allocate transmit timers
+ duart[chip].ch[0].tx_fifo_timer = machine.scheduler().timer_alloc(FUNC(tx_fifo_timer_callback));
+ duart[chip].ch[0].tx_fifo_timer->adjust(attotime::never, (chip * 2) + 0);
+
+ duart[chip].ch[1].tx_fifo_timer = machine.scheduler().timer_alloc(FUNC(tx_fifo_timer_callback));
+ duart[chip].ch[1].tx_fifo_timer->adjust(attotime::never, (chip * 2) + 1);
+}
+
+void pc16552d_rx_data(running_machine &machine, int chip, int channel, UINT8 data)
+{
+ if (duart[chip].ch[channel].reg[REG_FIFO_CTRL] & 0x01) // RCVR & XMIT FIFO enable
+ {
+ duart_push_rx_fifo(machine, chip, channel, data);
+ }
+}
+
+/*****************************************************************************/
+/* Read/Write handlers */
+
+READ8_HANDLER(pc16552d_0_r)
+{
+ return duart_r(space->machine(), 0, offset);
+}
+
+WRITE8_HANDLER(pc16552d_0_w)
+{
+ duart_w(space->machine(), 0, offset, data);
+}
+
+READ8_HANDLER(pc16552d_1_r)
+{
+ return duart_r(space->machine(), 1, offset);
+}
+
+WRITE8_HANDLER(pc16552d_1_w)
+{
+ duart_w(space->machine(), 1, offset, data);
+}
diff --git a/trunk/src/emu/machine/pc16552d.h b/trunk/src/emu/machine/pc16552d.h
new file mode 100644
index 00000000000..93f2181e37a
--- /dev/null
+++ b/trunk/src/emu/machine/pc16552d.h
@@ -0,0 +1,12 @@
+#ifndef PC16552D_H
+#define PC16552D_H
+
+void pc16552d_init(running_machine &machine, int chip, int frequency, void (* irq_handler)(running_machine &machine, int channel, int value), void (* tx_callback)(int channel, int count, UINT8* data));
+void pc16552d_rx_data(running_machine &machine, int chip, int channel, UINT8 data);
+
+READ8_HANDLER(pc16552d_0_r);
+WRITE8_HANDLER(pc16552d_0_w);
+READ8_HANDLER(pc16552d_1_r);
+WRITE8_HANDLER(pc16552d_1_w);
+
+#endif
diff --git a/trunk/src/emu/machine/pci.c b/trunk/src/emu/machine/pci.c
new file mode 100644
index 00000000000..df1d1de0da4
--- /dev/null
+++ b/trunk/src/emu/machine/pci.c
@@ -0,0 +1,335 @@
+/***************************************************************************
+
+ machine/pci.c
+
+ PCI bus
+
+ The PCI bus is a 32-bit bus introduced by Intel, so it is little endian
+
+ Control word:
+ bit 31: Enable bit
+ bits 30-24: Reserved
+ bits 23-16: PCI bus number
+ bits 15-11: PCI device number
+ bits 10- 8: PCI function number
+ bits 7- 0: Offset address
+
+ Standard PCI registers:
+ 0x00 2 Vendor ID
+ 0x02 2 Device ID
+ 0x04 2 PCI Command
+ 0x06 2 PCI Status
+ 0x08 1 Revision ID
+ 0x09 1 Programming Interface
+ 0x0A 1 Subclass Code
+ 0x0B 1 Class Code
+
+ Class Code/Subclass Code/Programming Interface
+ 0x00XXXX Pre-PCI 2.0 devices
+ 0x000000 Non-VGA device
+ 0x000101 VGA device
+ 0x01XXXX Storage Controller
+ 0x010000 SCSI
+ 0x0101XX IDE
+ 0x0102XX Floppy
+ 0x0103XX IPI
+ 0x0104XX RAID
+ 0x0180XX Other
+ 0x02XXXX Network Card
+ 0x020000 Ethernet
+ 0x020100 Tokenring
+ 0x020200 FDDI
+ 0x020300 ATM
+ 0x028000 Other
+ 0x03XXXX Display Controller
+ 0x030000 VGA
+ 0x030001 8514 Compatible
+ 0x030100 XGA
+ 0x038000 Other
+ 0x04XXXX Multimedia
+ 0x040000 Video
+ 0x040100 Audio
+ 0x048000 Other
+ 0x05XXXX Memory Controller
+ 0x050000 RAM
+ 0x050100 Flash
+ 0x058000 Other
+ 0x06XXXX Bridge
+ 0x060000 Host/PCI
+ 0x060100 PCI/ISA
+ 0x060200 PCI/EISA
+ 0x060300 PCI/Micro Channel
+ 0x060400 PCI/PCI
+ 0x060500 PCI/PCMCIA
+ 0x060600 PCI/NuBus
+ 0x060700 PCI/CardBus
+ 0x068000 Other
+
+ Information on PCI vendors can be found at http://www.pcidatabase.com/
+
+***************************************************************************/
+
+#include "emu.h"
+#include "devconv.h"
+#include "machine/pci.h"
+
+#define LOG_PCI 0
+
+typedef struct _pci_bus_state pci_bus_state;
+struct _pci_bus_state
+{
+ device_t * busdevice;
+ const pci_bus_config * config;
+ device_t * device[32];
+ pci_bus_state * siblings[8];
+ UINT8 siblings_busnum[8];
+ int siblings_count;
+ offs_t address;
+ INT8 devicenum; // device number we are addressing
+ INT8 busnum; // pci bus number we are addressing
+ pci_bus_state * busnumaddr; // pci bus we are addressing
+};
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ get_safe_token - makes sure that the passed
+ in device is, in fact, a PCI bus
+-------------------------------------------------*/
+
+INLINE pci_bus_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == PCI_BUS);
+
+ return (pci_bus_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+
+READ32_DEVICE_HANDLER( pci_32le_r )
+{
+ pci_bus_state *pcibus = get_safe_token(device);
+ UINT32 result = 0xffffffff;
+ int function, reg;
+
+ offset %= 2;
+
+ switch (offset)
+ {
+ case 0:
+ result = pcibus->address;
+ break;
+
+ case 1:
+ if (pcibus->devicenum != -1)
+ {
+ pci_read_func read = pcibus->busnumaddr->config->device[pcibus->devicenum].read_callback;
+ if (read != NULL)
+ {
+ function = (pcibus->address >> 8) & 0x07;
+ reg = (pcibus->address >> 0) & 0xfc;
+ result = (*read)(pcibus->busnumaddr->busdevice, pcibus->busnumaddr->device[pcibus->devicenum], function, reg, mem_mask);
+ }
+ }
+ break;
+ }
+
+ if (LOG_PCI)
+ logerror("pci_32le_r('%s'): offset=%d result=0x%08X\n", device->tag(), offset, result);
+
+ return result;
+}
+
+
+
+static pci_bus_state *pci_search_bustree(int busnum, int devicenum, pci_bus_state *pcibus)
+{
+int a;
+pci_bus_state *ret;
+
+ if (pcibus->config->busnum == busnum)
+ {
+ return pcibus;
+ }
+ for (a = 0; a < pcibus->siblings_count; a++)
+ {
+ ret = pci_search_bustree(busnum, devicenum, pcibus->siblings[a]);
+ if (ret != NULL)
+ return ret;
+ }
+ return NULL;
+}
+
+
+
+WRITE32_DEVICE_HANDLER( pci_32le_w )
+{
+ pci_bus_state *pcibus = get_safe_token(device);
+
+ offset %= 2;
+
+ if (LOG_PCI)
+ logerror("pci_32le_w('%s'): offset=%d data=0x%08X\n", device->tag(), offset, data);
+
+ switch (offset)
+ {
+ case 0:
+ pcibus->address = data;
+
+ /* lookup current device */
+ if (pcibus->address & 0x80000000)
+ {
+ int busnum = (pcibus->address >> 16) & 0xff;
+ int devicenum = (pcibus->address >> 11) & 0x1f;
+ pcibus->busnumaddr = pci_search_bustree(busnum, devicenum, pcibus);
+ if (pcibus->busnumaddr != NULL)
+ {
+ pcibus->busnum = busnum;
+ pcibus->devicenum = devicenum;
+ }
+ else
+ pcibus->devicenum = -1;
+ if (LOG_PCI)
+ logerror(" bus:%d device:%d\n", busnum, devicenum);
+ }
+ break;
+
+ case 1:
+ if (pcibus->devicenum != -1)
+ {
+ pci_write_func write = pcibus->busnumaddr->config->device[pcibus->devicenum].write_callback;
+ if (write != NULL)
+ {
+ int function = (pcibus->address >> 8) & 0x07;
+ int reg = (pcibus->address >> 0) & 0xfc;
+ (*write)(pcibus->busnumaddr->busdevice, pcibus->busnumaddr->device[pcibus->devicenum], function, reg, data, mem_mask);
+ }
+ if (LOG_PCI)
+ logerror(" function:%d register:%d\n", (pcibus->address >> 8) & 0x07, (pcibus->address >> 0) & 0xfc);
+ }
+ break;
+ }
+}
+
+
+
+READ64_DEVICE_HANDLER(pci_64be_r) { return read64be_with_32le_device_handler(pci_32le_r, device, offset, mem_mask); }
+WRITE64_DEVICE_HANDLER(pci_64be_w) { write64be_with_32le_device_handler(pci_32le_w, device, offset, data, mem_mask); }
+
+
+int pci_add_sibling( running_machine &machine, char *pcitag, char *sibling )
+{
+ device_t *device1 = machine.device(pcitag);
+ device_t *device2 = machine.device(sibling);
+ pci_bus_state *pcibus1 = get_safe_token(device1);
+ pci_bus_state *pcibus2 = get_safe_token(device2);
+ pci_bus_config *config2;
+
+ if ((device1 == NULL) || (device2 == NULL) || (pcibus1 == NULL) || (pcibus2 == NULL))
+ return 0;
+ if (pcibus1->siblings_count == 8)
+ return 0;
+ config2 = (pci_bus_config *)downcast<const legacy_device_base *>(device2)->inline_config();
+ pcibus1->siblings[pcibus1->siblings_count] = get_safe_token(device2);
+ pcibus1->siblings_busnum[pcibus1->siblings_count] = config2->busnum;
+ pcibus1->siblings_count++;
+ return 1;
+}
+
+
+/***************************************************************************
+ DEVICE INTERFACE
+***************************************************************************/
+
+
+static void pci_bus_postload(pci_bus_state *pcibus)
+{
+ if (pcibus->devicenum != -1)
+ {
+ pcibus->busnumaddr = pci_search_bustree(pcibus->busnum, pcibus->devicenum, pcibus);
+ }
+}
+
+
+/*-------------------------------------------------
+ device start callback
+-------------------------------------------------*/
+
+static DEVICE_START( pci_bus )
+{
+ pci_bus_state *pcibus = get_safe_token(device);
+ int devicenum;
+
+ /* validate some basic stuff */
+ assert(device != NULL);
+ assert(device->static_config() == NULL);
+ assert(downcast<const legacy_device_base *>(device)->inline_config() != NULL);
+
+ /* store a pointer back to the device */
+ pcibus->config = (const pci_bus_config *)downcast<const legacy_device_base *>(device)->inline_config();
+ pcibus->busdevice = device;
+ pcibus->devicenum = -1;
+
+ /* find all our devices */
+ for (devicenum = 0; devicenum < ARRAY_LENGTH(pcibus->device); devicenum++)
+ if (pcibus->config->device[devicenum].devtag != NULL)
+ pcibus->device[devicenum] = device->machine().device(pcibus->config->device[devicenum].devtag);
+
+ if (pcibus->config->father != NULL)
+ pci_add_sibling(device->machine(), (char *)pcibus->config->father, (char *)device->tag());
+
+ /* register pci states */
+ device->save_item(NAME(pcibus->address));
+ device->save_item(NAME(pcibus->devicenum));
+ device->save_item(NAME(pcibus->busnum));
+
+ device->machine().save().register_postload(save_prepost_delegate(FUNC(pci_bus_postload), pcibus));
+}
+
+
+/*-------------------------------------------------
+ device reset callback
+-------------------------------------------------*/
+
+static DEVICE_RESET( pci_bus )
+{
+ pci_bus_state *pcibus = get_safe_token(device);
+
+ /* reset the drive state */
+ pcibus->devicenum = -1;
+ pcibus->address = 0;
+}
+
+
+/*-------------------------------------------------
+ device get info callback
+-------------------------------------------------*/
+
+DEVICE_GET_INFO( pci_bus )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(pci_bus_state); break;
+ case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = sizeof(pci_bus_config); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(pci_bus); break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(pci_bus);break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PCI Bus"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Peripherial Bus"); 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;
+ }
+}
+
+
+DEFINE_LEGACY_DEVICE(PCI_BUS, pci_bus);
diff --git a/trunk/src/emu/machine/pci.h b/trunk/src/emu/machine/pci.h
new file mode 100644
index 00000000000..5a2dcb64e6e
--- /dev/null
+++ b/trunk/src/emu/machine/pci.h
@@ -0,0 +1,73 @@
+/***************************************************************************
+
+ machine/pci.h
+
+ PCI bus
+
+***************************************************************************/
+
+#ifndef PCI_H
+#define PCI_H
+
+#include "devlegcy.h"
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef UINT32 (*pci_read_func)(device_t *pcibus, device_t *device, int function, int reg, UINT32 mem_mask);
+typedef void (*pci_write_func)(device_t *pcibus, device_t *device, int function, int reg, UINT32 data, UINT32 mem_mask);
+
+typedef struct _pci_device_entry pci_device_entry;
+struct _pci_device_entry
+{
+ const char * devtag;
+ pci_read_func read_callback;
+ pci_write_func write_callback;
+};
+
+typedef struct _pci_bus_config pci_bus_config;
+struct _pci_bus_config
+{
+ UINT8 busnum;
+ pci_device_entry device[32];
+ const char * father;
+};
+
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_PCI_BUS_ADD(_tag, _busnum) \
+ MCFG_DEVICE_ADD(_tag, PCI_BUS, 0) \
+ MCFG_DEVICE_CONFIG_DATA32(pci_bus_config, busnum, _busnum)
+
+#define MCFG_PCI_BUS_DEVICE(_devnum, _devtag, _configread, _configwrite) \
+ MCFG_DEVICE_CONFIG_DATAPTR_ARRAY_MEMBER(pci_bus_config, device, _devnum, pci_device_entry, devtag, _devtag) \
+ MCFG_DEVICE_CONFIG_DATAPTR_ARRAY_MEMBER(pci_bus_config, device, _devnum, pci_device_entry, read_callback, _configread) \
+ MCFG_DEVICE_CONFIG_DATAPTR_ARRAY_MEMBER(pci_bus_config, device, _devnum, pci_device_entry, write_callback, _configwrite)
+
+#define MCFG_PCI_BUS_SIBLING(_father_tag) \
+ MCFG_DEVICE_CONFIG_DATAPTR(pci_bus_config, father, _father_tag)
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+READ32_DEVICE_HANDLER( pci_32le_r );
+WRITE32_DEVICE_HANDLER( pci_32le_w );
+
+READ64_DEVICE_HANDLER( pci_64be_r );
+WRITE64_DEVICE_HANDLER( pci_64be_w );
+
+int pci_add_sibling( running_machine &machine, char *pcitag, char *sibling );
+
+/* ----- device interface ----- */
+
+DECLARE_LEGACY_DEVICE(PCI_BUS, pci_bus);
+
+#endif /* PCI_H */
diff --git a/trunk/src/emu/machine/pckeybrd.h b/trunk/src/emu/machine/pckeybrd.h
new file mode 100644
index 00000000000..ed1f4c4439a
--- /dev/null
+++ b/trunk/src/emu/machine/pckeybrd.h
@@ -0,0 +1,35 @@
+/**********************************************************************
+
+ pckeybrd.h
+
+ PC-style keyboard emulation
+
+ This emulation is decoupled from the AT 8042 emulation used in the
+ IBM ATs and above
+
+**********************************************************************/
+
+#ifndef PCKEYBRD_H
+#define PCKEYBRD_H
+
+typedef enum
+{
+ AT_KEYBOARD_TYPE_PC,
+ AT_KEYBOARD_TYPE_AT,
+ AT_KEYBOARD_TYPE_MF2
+} AT_KEYBOARD_TYPE;
+
+void at_keyboard_init(running_machine &machine, AT_KEYBOARD_TYPE type);
+
+void at_keyboard_polling(void);
+int at_keyboard_read(void);
+void at_keyboard_write(running_machine &machine, UINT8 data);
+void at_keyboard_reset(running_machine &machine);
+void at_keyboard_set_scan_code_set(int set);
+
+INPUT_PORTS_EXTERN( pc_keyboard );
+INPUT_PORTS_EXTERN( at_keyboard );
+
+#endif /* PCKEYBRD_H */
+
+
diff --git a/trunk/src/emu/machine/pcshare.h b/trunk/src/emu/machine/pcshare.h
new file mode 100644
index 00000000000..a746f7a1982
--- /dev/null
+++ b/trunk/src/emu/machine/pcshare.h
@@ -0,0 +1,14 @@
+/* flags for init_pc_common */
+#define PCCOMMON_KEYBOARD_PC 0
+#define PCCOMMON_KEYBOARD_AT 1
+
+void init_pc_common(running_machine &machine, UINT32 flags, void (*set_keyb_int_func)(running_machine &, int));
+
+void pc_keyboard(void);
+UINT8 pc_keyb_read(void);
+void pc_keyb_set_clock(int on);
+void pc_keyb_clear(void);
+
+extern IRQ_CALLBACK(pcat_irq_callback);
+ADDRESS_MAP_EXTERN(pcat32_io_common, 32);
+MACHINE_CONFIG_EXTERN(pcat_common);
diff --git a/trunk/src/emu/machine/pd4990a.c b/trunk/src/emu/machine/pd4990a.c
new file mode 100644
index 00000000000..86c928cea15
--- /dev/null
+++ b/trunk/src/emu/machine/pd4990a.c
@@ -0,0 +1,537 @@
+/***************************************************************************
+
+ NEC uPD4990A
+
+ Serial I/O Calendar & Clock IC used in the
+ NEO GEO and probably a couple of other machines.
+
+
+ Completed by ElSemi.
+
+ I haven't found any schematics for this device
+ so I had to make some assumptions about how it works.
+
+ The three input bits seem to be used for a serial protocol
+
+ bit 0 - data
+ bit 1 - clock
+ bit 2 - command end (?)
+
+ the commands I've found so far are:
+
+ 0x0 - ?? sent after 2
+ 0x1 - Reset the (probable) shift register used for output
+ 0x2 - Store the contents of the shift reg to the current date
+ 0x3 - Load Shift register with current date
+
+ 0x7 - Switch test bit every frame
+ 0x8 - Switch test bit every half-second
+
+
+ 2009-06 Converted to be a device
+
+***************************************************************************/
+
+#include "emu.h"
+#include "machine/pd4990a.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define DATA_BIT 0x01
+#define CLOCK_BIT 0x02
+#define END_BIT 0x04
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _upd4990a_state upd4990a_state;
+struct _upd4990a_state
+{
+ int seconds; /* seconds BCD */
+ int minutes; /* minutes BCD */
+ int hours; /* hours BCD */
+ int days; /* days BCD */
+ int month; /* month Hexadecimal form */
+ int year; /* year BCD */
+ int weekday; /* weekday BCD */
+
+ UINT32 shiftlo;
+ UINT32 shifthi;
+
+ int retraces; /* Assumes 60 retraces a second */
+ int testwaits;
+ int maxwaits; /* Switch test every frame*/
+ int testbit; /* Pulses a bit in order to simulate test output */
+
+ int outputbit;
+ int bitno;
+ INT8 reading;
+ INT8 writing;
+
+ int clock_line;
+ int command_line; //??
+};
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE upd4990a_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert((device->type() == UPD4990A));
+ return (upd4990a_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+INLINE UINT8 convert_to_bcd(int val)
+{
+ return ((val / 10) << 4) | (val % 10);
+}
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ upd4990a_increment_month
+-------------------------------------------------*/
+
+static void upd4990a_increment_month( device_t *device )
+{
+ upd4990a_state *upd4990a = get_safe_token(device);
+
+ upd4990a->month++;
+ if (upd4990a->month == 13)
+ {
+ upd4990a->month = 1;
+ upd4990a->year++;
+ if ((upd4990a->year & 0x0f) >= 10)
+ {
+ upd4990a->year &= 0xf0;
+ upd4990a->year += 0x10;
+ }
+ if (upd4990a->year == 0xA0)
+ upd4990a->year = 0;
+ }
+}
+
+/*-------------------------------------------------
+ upd4990a_increment_day
+-------------------------------------------------*/
+
+static void upd4990a_increment_day( device_t *device )
+{
+ upd4990a_state *upd4990a = get_safe_token(device);
+ int real_year;
+
+ upd4990a->days++;
+ if ((upd4990a->days & 0x0f) >= 10)
+ {
+ upd4990a->days &= 0xf0;
+ upd4990a->days += 0x10;
+ }
+
+ upd4990a->weekday++;
+ if (upd4990a->weekday == 7)
+ upd4990a->weekday = 0;
+
+ switch (upd4990a->month)
+ {
+ case 1: case 3: case 5: case 7: case 8: case 10: case 12:
+ if (upd4990a->days == 0x32)
+ {
+ upd4990a->days = 1;
+ upd4990a_increment_month(device);
+ }
+ break;
+ case 2:
+ real_year = (upd4990a->year >> 4) * 10 + (upd4990a->year & 0xf);
+ if ((real_year % 4) && (!(real_year % 100) || (real_year % 400)))
+ {
+ if (upd4990a->days == 0x29)
+ {
+ upd4990a->days = 1;
+ upd4990a_increment_month(device);
+ }
+ }
+ else
+ {
+ if (upd4990a->days == 0x30)
+ {
+ upd4990a->days = 1;
+ upd4990a_increment_month(device);
+ }
+ }
+ break;
+ case 4: case 6: case 9: case 11:
+ if (upd4990a->days == 0x31)
+ {
+ upd4990a->days = 1;
+ upd4990a_increment_month(device);
+ }
+ break;
+ }
+}
+
+/*-------------------------------------------------
+ upd4990a_addretrace
+-------------------------------------------------*/
+
+void upd4990a_addretrace( device_t *device )
+{
+ upd4990a_state *upd4990a = get_safe_token(device);
+
+ ++upd4990a->testwaits;
+ if(upd4990a->testwaits >= upd4990a->maxwaits)
+ {
+ upd4990a->testbit ^= 1;
+ upd4990a->testwaits = 0;
+ }
+
+ upd4990a->retraces++;
+ if (upd4990a->retraces < 60)
+ return;
+
+ upd4990a->retraces = 0;
+ upd4990a->seconds++;
+ if ((upd4990a->seconds & 0x0f) < 10)
+ return;
+
+ upd4990a->seconds &= 0xf0;
+ upd4990a->seconds += 0x10;
+ if (upd4990a->seconds < 0x60)
+ return;
+
+ upd4990a->seconds = 0;
+ upd4990a->minutes++;
+ if ((upd4990a->minutes & 0x0f) < 10)
+ return;
+
+ upd4990a->minutes &= 0xf0;
+ upd4990a->minutes += 0x10;
+ if (upd4990a->minutes < 0x60)
+ return;
+
+ upd4990a->minutes = 0;
+ upd4990a->hours++;
+ if ((upd4990a->hours & 0x0f) < 10)
+ return;
+
+ upd4990a->hours &= 0xf0;
+ upd4990a->hours += 0x10;
+ if (upd4990a->hours < 0x24)
+ return;
+
+ upd4990a->hours = 0;
+ upd4990a_increment_day(device);
+}
+
+/*-------------------------------------------------
+ upd4990a_testbit_r
+-------------------------------------------------*/
+
+READ8_DEVICE_HANDLER( upd4990a_testbit_r )
+{
+ upd4990a_state *upd4990a = get_safe_token(device);
+ return upd4990a->testbit;
+}
+
+/*-------------------------------------------------
+ upd4990a_databit_r
+-------------------------------------------------*/
+
+READ8_DEVICE_HANDLER( upd4990a_databit_r )
+{
+ upd4990a_state *upd4990a = get_safe_token(device);
+ return upd4990a->outputbit;
+}
+
+/*-------------------------------------------------
+ upd4990a_readbit
+-------------------------------------------------*/
+
+static void upd4990a_readbit( device_t *device )
+{
+ upd4990a_state *upd4990a = get_safe_token(device);
+
+ switch (upd4990a->bitno)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ case 0x04: case 0x05: case 0x06: case 0x07:
+ upd4990a->outputbit = (upd4990a->seconds >> upd4990a->bitno) & 0x01;
+ break;
+ case 0x08: case 0x09: case 0x0a: case 0x0b:
+ case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ upd4990a->outputbit = (upd4990a->minutes >> (upd4990a->bitno - 0x08)) & 0x01;
+ break;
+ case 0x10: case 0x11: case 0x12: case 0x13:
+ case 0x14: case 0x15: case 0x16: case 0x17:
+ upd4990a->outputbit = (upd4990a->hours >> (upd4990a->bitno - 0x10)) & 0x01;
+ break;
+ case 0x18: case 0x19: case 0x1a: case 0x1b:
+ case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ upd4990a->outputbit = (upd4990a->days >> (upd4990a->bitno - 0x18)) & 0x01;
+ break;
+ case 0x20: case 0x21: case 0x22: case 0x23:
+ upd4990a->outputbit = (upd4990a->weekday >> (upd4990a->bitno - 0x20)) & 0x01;
+ break;
+ case 0x24: case 0x25: case 0x26: case 0x27:
+ upd4990a->outputbit = (upd4990a->month >> (upd4990a->bitno - 0x24)) & 0x01;
+ break;
+ case 0x28: case 0x29: case 0x2a: case 0x2b:
+ case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ upd4990a->outputbit = (upd4990a->year >> (upd4990a->bitno - 0x28)) & 0x01;
+ break;
+ case 0x30: case 0x31: case 0x32: case 0x33:
+ //unknown
+ break;
+ }
+}
+
+/*-------------------------------------------------
+ upd4990a_resetbitstream
+-------------------------------------------------*/
+
+static void upd4990a_resetbitstream( device_t *device )
+{
+ upd4990a_state *upd4990a = get_safe_token(device);
+
+ upd4990a->shiftlo = 0;
+ upd4990a->shifthi = 0;
+ upd4990a->bitno = 0;
+}
+
+/*-------------------------------------------------
+ upd4990a_writebit
+-------------------------------------------------*/
+
+static void upd4990a_writebit( device_t *device , UINT8 bit )
+{
+ upd4990a_state *upd4990a = get_safe_token(device);
+ if (upd4990a->bitno <= 31) //low part
+ upd4990a->shiftlo |= bit << upd4990a->bitno;
+ else //high part
+ upd4990a->shifthi |= bit << (upd4990a->bitno - 32);
+}
+
+/*-------------------------------------------------
+ upd4990a_nextbit
+-------------------------------------------------*/
+
+static void upd4990a_nextbit( device_t *device )
+{
+ upd4990a_state *upd4990a = get_safe_token(device);
+ ++upd4990a->bitno;
+
+ if (upd4990a->reading)
+ upd4990a_readbit(device);
+
+ if (upd4990a->reading && upd4990a->bitno == 0x34)
+ {
+ upd4990a->reading = 0;
+ upd4990a_resetbitstream(device);
+ }
+
+}
+
+/*-------------------------------------------------
+ upd4990a_getcommand
+-------------------------------------------------*/
+
+static UINT8 upd4990a_getcommand( device_t *device )
+{
+ upd4990a_state *upd4990a = get_safe_token(device);
+ //Warning: problems if the 4 bits are in different
+ //parts, It's very strange that this case could happen.
+ if(upd4990a->bitno <= 31)
+ return upd4990a->shiftlo >> (upd4990a->bitno - 4);
+ else
+ return upd4990a->shifthi >> (upd4990a->bitno - 32 - 4);
+}
+
+/*-------------------------------------------------
+ upd4990a_update_date
+-------------------------------------------------*/
+
+static void upd4990a_update_date( device_t *device )
+{
+ upd4990a_state *upd4990a = get_safe_token(device);
+
+ upd4990a->seconds = (upd4990a->shiftlo >> 0 ) & 0xff;
+ upd4990a->minutes = (upd4990a->shiftlo >> 8 ) & 0xff;
+ upd4990a->hours = (upd4990a->shiftlo >> 16) & 0xff;
+ upd4990a->days = (upd4990a->shiftlo >> 24) & 0xff;
+ upd4990a->weekday = (upd4990a->shifthi >> 0 ) & 0x0f;
+ upd4990a->month = (upd4990a->shifthi >> 4 ) & 0x0f;
+ upd4990a->year = (upd4990a->shifthi >> 8 ) & 0xff;
+}
+
+/*-------------------------------------------------
+ upd4990a_process_command
+-------------------------------------------------*/
+
+static void upd4990a_process_command( device_t *device )
+{
+ upd4990a_state *upd4990a = get_safe_token(device);
+
+ switch(upd4990a_getcommand(device))
+ {
+ case 0x1: //load output register
+ upd4990a->bitno = 0;
+ if (upd4990a->reading)
+ upd4990a_readbit(device); //prepare first bit
+ upd4990a->shiftlo = 0;
+ upd4990a->shifthi = 0;
+ break;
+ case 0x2:
+ upd4990a->writing = 0; //store register to current date
+ upd4990a_update_date(device);
+ break;
+ case 0x3: //start reading
+ upd4990a->reading = 1;
+ break;
+ case 0x7: //switch testbit every frame
+ upd4990a->maxwaits = 1;
+ break;
+ case 0x8: //switch testbit every half-second
+ upd4990a->maxwaits = 30;
+ break;
+ }
+ upd4990a_resetbitstream(device);
+}
+
+/*-------------------------------------------------
+ upd4990a_serial_control
+-------------------------------------------------*/
+
+static void upd4990a_serial_control( device_t *device, UINT8 data )
+{
+ upd4990a_state *upd4990a = get_safe_token(device);
+
+ //Check for command end
+ if(upd4990a->command_line && !(data & END_BIT)) //end of command
+ {
+ upd4990a_process_command(device);
+ }
+ upd4990a->command_line = data & END_BIT;
+
+ if(upd4990a->clock_line && !(data & CLOCK_BIT)) //clock lower edge
+ {
+ upd4990a_writebit(device, data & DATA_BIT);
+ upd4990a_nextbit(device);
+ }
+ upd4990a->clock_line = data & CLOCK_BIT;
+}
+
+/*-------------------------------------------------
+ upd4990a_control_16_w
+-------------------------------------------------*/
+
+WRITE16_DEVICE_HANDLER( upd4990a_control_16_w )
+{
+ upd4990a_serial_control(device, data & 0x7);
+}
+
+
+/*-------------------------------------------------
+ DEVICE_START( upd4990a )
+-------------------------------------------------*/
+
+static DEVICE_START( upd4990a )
+{
+ upd4990a_state *upd4990a = get_safe_token(device);
+
+ system_time curtime, *systime = &curtime;
+ device->machine().current_datetime(curtime);
+
+#if 0
+ upd4990a->seconds = 0x00;
+ upd4990a->minutes = 0x00;
+ upd4990a->hours = 0x00;
+ upd4990a->days = 0x09;
+ upd4990a->month = 9;
+ upd4990a->year = 0x73;
+ upd4990a->weekday = 1;
+#endif
+ /* HACK: load time counter from system time */
+ upd4990a->seconds = convert_to_bcd(systime->local_time.second);
+ upd4990a->minutes = convert_to_bcd(systime->local_time.minute);
+ upd4990a->hours = convert_to_bcd(systime->local_time.hour);
+ upd4990a->days = convert_to_bcd(systime->local_time.mday);
+ upd4990a->month = systime->local_time.month + 1;
+ upd4990a->year = ((((systime->local_time.year - 1900) % 100) / 10) << 4) | ((systime->local_time.year - 1900) % 10);
+ upd4990a->weekday = systime->local_time.weekday;
+
+ /* register for state saving */
+ device->save_item(NAME(upd4990a->seconds));
+ device->save_item(NAME(upd4990a->minutes));
+ device->save_item(NAME(upd4990a->hours));
+ device->save_item(NAME(upd4990a->days));
+ device->save_item(NAME(upd4990a->month));
+ device->save_item(NAME(upd4990a->year));
+ device->save_item(NAME(upd4990a->weekday));
+
+ device->save_item(NAME(upd4990a->shiftlo));
+ device->save_item(NAME(upd4990a->shifthi));
+
+ device->save_item(NAME(upd4990a->retraces));
+ device->save_item(NAME(upd4990a->testwaits));
+ device->save_item(NAME(upd4990a->maxwaits));
+ device->save_item(NAME(upd4990a->testbit));
+
+ device->save_item(NAME(upd4990a->outputbit));
+ device->save_item(NAME(upd4990a->bitno));
+ device->save_item(NAME(upd4990a->reading));
+ device->save_item(NAME(upd4990a->writing));
+
+ device->save_item(NAME(upd4990a->clock_line));
+ device->save_item(NAME(upd4990a->command_line));
+}
+
+
+/*-------------------------------------------------
+ DEVICE_RESET( upd4990a )
+-------------------------------------------------*/
+
+static DEVICE_RESET( upd4990a )
+{
+ upd4990a_state *upd4990a = get_safe_token(device);
+
+ upd4990a->shiftlo = 0;
+ upd4990a->shifthi = 0;
+
+ upd4990a->retraces = 0;
+ upd4990a->testwaits = 0;
+ upd4990a->maxwaits = 1;
+ upd4990a->testbit = 0;
+
+ upd4990a->outputbit = 0;
+ upd4990a->bitno = 0;
+ upd4990a->reading = 0;
+ upd4990a->writing = 0;
+
+ upd4990a->clock_line = 0;
+ upd4990a->command_line = 0;
+}
+
+/*-------------------------------------------------
+ device definition
+-------------------------------------------------*/
+
+static const char DEVTEMPLATE_SOURCE[] = __FILE__;
+
+#define DEVTEMPLATE_ID(p,s) p##upd4990a##s
+#define DEVTEMPLATE_FEATURES DT_HAS_START | DT_HAS_RESET
+#define DEVTEMPLATE_NAME "NEC uPD4990A"
+#define DEVTEMPLATE_FAMILY "NEC uPD4990A Calendar & Clock"
+#include "devtempl.h"
+
+
+DEFINE_LEGACY_DEVICE(UPD4990A, upd4990a);
diff --git a/trunk/src/emu/machine/pd4990a.h b/trunk/src/emu/machine/pd4990a.h
new file mode 100644
index 00000000000..4dd0c1b4f0a
--- /dev/null
+++ b/trunk/src/emu/machine/pd4990a.h
@@ -0,0 +1,37 @@
+/***************************************************************************
+
+ NEC uPD4990A
+
+ Serial I/O Calendar & Clock IC
+
+***************************************************************************/
+
+#ifndef __PD4990A_H__
+#define __PD4990A_H__
+
+#include "devlegcy.h"
+
+
+/***************************************************************************
+ MACROS / CONSTANTS
+***************************************************************************/
+
+DECLARE_LEGACY_DEVICE(UPD4990A, upd4990a);
+
+#define MCFG_UPD4990A_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, UPD4990A, 0)
+
+
+/***************************************************************************
+ PROTOTYPES
+***************************************************************************/
+
+/* this should be refactored, once RTCs get unified */
+extern void upd4990a_addretrace( device_t *device );
+
+extern READ8_DEVICE_HANDLER( upd4990a_testbit_r );
+extern READ8_DEVICE_HANDLER( upd4990a_databit_r );
+extern WRITE16_DEVICE_HANDLER( upd4990a_control_16_w );
+
+
+#endif /*__PD4990A_H__*/
diff --git a/trunk/src/emu/machine/pic8259.c b/trunk/src/emu/machine/pic8259.c
new file mode 100644
index 00000000000..6c79303d4be
--- /dev/null
+++ b/trunk/src/emu/machine/pic8259.c
@@ -0,0 +1,475 @@
+/**********************************************************************
+
+ 8259 PIC interface and emulation
+
+ The 8259 is a programmable interrupt controller used to multiplex
+ interrupts for x86 and other computers. The chip is set up by
+ writing a series of Initialization Command Words (ICWs) after which
+ the chip is operational and capable of dispatching interrupts. After
+ this, Operation Command Words (OCWs) can be written to control further
+ behavior.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "machine/pic8259.h"
+
+#define IRQ_COUNT 8
+
+#define LOG_ICW 0
+#define LOG_OCW 0
+#define LOG_GENERAL 0
+
+typedef enum
+{
+ STATE_ICW1,
+ STATE_ICW2,
+ STATE_ICW3,
+ STATE_ICW4,
+ STATE_READY
+} pic8259_state_t;
+
+typedef struct pic8259 pic8259_t;
+
+struct pic8259
+{
+ devcb_resolved_write_line out_int_func;
+
+ devcb_resolved_read_line sp_en_func;
+
+ devcb_resolved_read8 read_slave_ack_func;
+
+ emu_timer *timer;
+
+ pic8259_state_t state;
+
+ UINT8 isr;
+ UINT8 irr;
+ UINT8 prio;
+ UINT8 imr;
+ UINT8 irq_lines;
+
+ UINT8 input;
+ UINT8 ocw3;
+
+ UINT8 master;
+ /* ICW1 state */
+ UINT32 level_trig_mode : 1;
+ UINT32 vector_size : 1;
+ UINT32 cascade : 1;
+ UINT32 icw4_needed : 1;
+ UINT32 vector_addr_low;
+ /* ICW2 state */
+ UINT8 base;
+ UINT8 vector_addr_high;
+
+ /* ICW3 state */
+ UINT8 slave;
+
+ /* ICW4 state */
+ UINT32 nested : 1;
+ UINT32 mode : 2;
+ UINT32 auto_eoi : 1;
+ UINT32 is_x86 : 1;
+};
+
+
+INLINE pic8259_t *get_safe_token(device_t *device) {
+ assert( device != NULL );
+ assert( device->type() == PIC8259 );
+ return ( pic8259_t *) downcast<legacy_device_base *>(device)->token();
+}
+
+
+static TIMER_CALLBACK( pic8259_timerproc )
+{
+ device_t *device = (device_t *)ptr;
+ pic8259_t *pic8259 = get_safe_token(device);
+ int irq;
+ UINT8 mask;
+
+ /* check the various IRQs */
+ for (irq = 0; irq < IRQ_COUNT; irq++)
+ {
+ mask = 1 << irq;
+
+ /* is this IRQ in service? */
+ if (pic8259->isr & mask)
+ {
+ if (LOG_GENERAL)
+ logerror("pic8259_timerproc(): PIC IRQ #%d still in service\n", irq);
+ break;
+ }
+
+ /* is this IRQ pending and enabled? */
+ if ((pic8259->state == STATE_READY) && (pic8259->irr & mask) && !(pic8259->imr & mask))
+ {
+ if (LOG_GENERAL)
+ logerror("pic8259_timerproc(): PIC triggering IRQ #%d\n", irq);
+ if (!BIT(pic8259->ocw3, 2))
+ pic8259->out_int_func(1);
+ return;
+ }
+ }
+ if (!BIT(pic8259->ocw3, 2))
+ pic8259->out_int_func(0);
+}
+
+
+INLINE void pic8259_set_timer(pic8259_t *pic8259)
+{
+ pic8259->timer->adjust(attotime::zero);
+}
+
+
+static void pic8259_set_irq_line(device_t *device, int irq, int state)
+{
+ pic8259_t *pic8259 = get_safe_token(device);
+ UINT8 mask = (1 << irq);
+
+ if (state)
+ {
+ /* setting IRQ line */
+ if (LOG_GENERAL)
+ logerror("pic8259_set_irq_line(): PIC set IRQ line #%d\n", irq);
+
+ if(pic8259->level_trig_mode || (!pic8259->level_trig_mode && !(pic8259->irq_lines & mask)))
+ pic8259->irr |= mask;
+ pic8259->irq_lines |= mask;
+ }
+ else
+ {
+ /* clearing IRQ line */
+ if (LOG_GENERAL)
+ logerror("pic8259_set_irq_line(): PIC cleared IRQ line #%d\n", irq);
+
+ pic8259->irq_lines &= ~mask;
+ pic8259->irr &= ~mask;
+ }
+ if (pic8259->mode & 0x02) pic8259->irr = pic8259->irq_lines;
+ pic8259_set_timer(pic8259);
+}
+
+WRITE_LINE_DEVICE_HANDLER( pic8259_ir0_w ) { pic8259_set_irq_line(device, 0, state); }
+WRITE_LINE_DEVICE_HANDLER( pic8259_ir1_w ) { pic8259_set_irq_line(device, 1, state); }
+WRITE_LINE_DEVICE_HANDLER( pic8259_ir2_w ) { pic8259_set_irq_line(device, 2, state); }
+WRITE_LINE_DEVICE_HANDLER( pic8259_ir3_w ) { pic8259_set_irq_line(device, 3, state); }
+WRITE_LINE_DEVICE_HANDLER( pic8259_ir4_w ) { pic8259_set_irq_line(device, 4, state); }
+WRITE_LINE_DEVICE_HANDLER( pic8259_ir5_w ) { pic8259_set_irq_line(device, 5, state); }
+WRITE_LINE_DEVICE_HANDLER( pic8259_ir6_w ) { pic8259_set_irq_line(device, 6, state); }
+WRITE_LINE_DEVICE_HANDLER( pic8259_ir7_w ) { pic8259_set_irq_line(device, 7, state); }
+
+int pic8259_acknowledge(device_t *device)
+{
+ pic8259_t *pic8259 = get_safe_token(device);
+ UINT8 mask;
+ int irq;
+
+ for (irq = 0; irq < IRQ_COUNT; irq++)
+ {
+ mask = 1 << irq;
+
+ /* is this IRQ pending and enabled? */
+ if ((pic8259->irr & mask) && !(pic8259->imr & mask))
+ {
+ if (LOG_GENERAL)
+ logerror("pic8259_acknowledge(): PIC acknowledge IRQ #%d\n", irq);
+ if (!pic8259->level_trig_mode)
+ pic8259->irr &= ~mask;
+
+ if (!pic8259->auto_eoi)
+ pic8259->isr |= mask;
+
+ pic8259_set_timer(pic8259);
+
+ if ((pic8259->cascade!=0) && (pic8259->master!=0) && (mask & pic8259->slave)) {
+ // it's from slave device
+ return pic8259->read_slave_ack_func(irq);
+ } else {
+ if (pic8259->is_x86) {
+ /* For x86 mode*/
+ return irq + pic8259->base;
+ } else {
+ /* in case of 8080/85) */
+ return 0xcd0000 + (pic8259->vector_addr_high << 8) + pic8259->vector_addr_low + (irq << (3-pic8259->vector_size));
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+
+
+READ8_DEVICE_HANDLER( pic8259_r )
+{
+ pic8259_t *pic8259 = get_safe_token(device);
+
+ /* NPW 18-May-2003 - Changing 0xFF to 0x00 as per Ruslan */
+ UINT8 data = 0x00;
+
+ switch(offset)
+ {
+ case 0: /* PIC acknowledge IRQ */
+ if ( pic8259->ocw3 & 0x04 )
+ {
+ /* Polling mode */
+ if ( pic8259->isr & ~pic8259->imr )
+ pic8259_acknowledge( device );
+
+ if ( pic8259->irr & ~pic8259->imr )
+ {
+ int irq;
+ for ( irq = 0; irq < IRQ_COUNT; irq++ )
+ {
+ if ( ( 1 << irq ) & pic8259->irr & ~pic8259->imr )
+ {
+ data = 0x80 | irq;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ switch ( pic8259->ocw3 & 0x03 )
+ {
+ case 2:
+ data = pic8259->irr;
+ break;
+ case 3:
+ data = pic8259->isr & ~pic8259->imr;
+ break;
+ default:
+ data = 0x00;
+ break;
+ }
+ }
+ break;
+
+ case 1: /* PIC mask register */
+ data = pic8259->imr;
+ break;
+ }
+ return data;
+}
+
+
+
+WRITE8_DEVICE_HANDLER( pic8259_w )
+{
+ pic8259_t *pic8259 = get_safe_token(device);
+
+ switch(offset)
+ {
+ case 0: /* PIC acknowledge IRQ */
+ if (data & 0x10)
+ {
+ /* write ICW1 - this pretty much resets the chip */
+ if (LOG_ICW)
+ logerror("pic8259_w(): ICW1; data=0x%02X\n", data);
+
+ pic8259->imr = 0x00;
+ pic8259->isr = 0x00;
+ pic8259->irr = 0x00;
+ pic8259->level_trig_mode = (data & 0x08) ? 1 : 0;
+ pic8259->vector_size = (data & 0x04) ? 1 : 0;
+ pic8259->cascade = (data & 0x02) ? 0 : 1;
+ pic8259->icw4_needed = (data & 0x01) ? 1 : 0;
+ pic8259->vector_addr_low = (data & 0xe0);
+ pic8259->state = STATE_ICW2;
+ }
+ else if (pic8259->state == STATE_READY)
+ {
+ if ((data & 0x98) == 0x08)
+ {
+ /* write OCW3 */
+ if (LOG_OCW)
+ logerror("pic8259_w(): OCW3; data=0x%02X\n", data);
+
+ pic8259->ocw3 = data;
+ }
+ else if ((data & 0x18) == 0x00)
+ {
+ int n = data & 7;
+ UINT8 mask = 1 << n;
+
+ /* write OCW2 */
+ if (LOG_OCW)
+ logerror("pic8259_w(): OCW2; data=0x%02X\n", data);
+
+ switch (data & 0xe0)
+ {
+ case 0x00:
+ pic8259->prio = 0;
+ break;
+ case 0x20:
+ for (n = 0, mask = 1<<pic8259->prio; n < 8; n++, mask = (mask<<1) | (mask>>7))
+ {
+ if (pic8259->isr & mask)
+ {
+ pic8259->isr &= ~mask;
+ pic8259->irr &= ~mask;
+ break;
+ }
+ }
+ break;
+ case 0x40:
+ break;
+ case 0x60:
+ if( pic8259->isr & mask )
+ {
+ pic8259->isr &= ~mask;
+ }
+ break;
+ case 0x80:
+ pic8259->prio = (pic8259->prio + 1) & 7;
+ break;
+ case 0xa0:
+ for (n = 0, mask = 1<<pic8259->prio; n < 8; n++, mask = (mask<<1) | (mask>>7))
+ {
+ if( pic8259->isr & mask )
+ {
+ pic8259->isr &= ~mask;
+ pic8259->prio = (pic8259->prio + 1) & 7;
+ break;
+ }
+ }
+ break;
+ case 0xc0:
+ pic8259->prio = n & 7;
+ break;
+ case 0xe0:
+ if( pic8259->isr & mask )
+ {
+ pic8259->isr &= ~mask;
+ pic8259->irr &= ~mask;
+ pic8259->prio = (pic8259->prio + 1) & 7;
+ }
+ break;
+ }
+ }
+ }
+ break;
+
+ case 1:
+ switch(pic8259->state)
+ {
+ case STATE_ICW1:
+ break;
+
+ case STATE_ICW2:
+ /* write ICW2 */
+ if (LOG_ICW)
+ logerror("pic8259_w(): ICW2; data=0x%02X\n", data);
+
+ pic8259->base = data & 0xf8;
+ pic8259->vector_addr_high = data ;
+ if (pic8259->cascade)
+ pic8259->state = STATE_ICW3;
+ else
+ pic8259->state = pic8259->icw4_needed ? STATE_ICW4 : STATE_READY;
+ break;
+
+ case STATE_ICW3:
+ /* write ICW3 */
+ if (LOG_ICW)
+ logerror("pic8259_w(): ICW3; data=0x%02X\n", data);
+
+ pic8259->slave = data;
+ pic8259->state = pic8259->icw4_needed ? STATE_ICW4 : STATE_READY;
+ break;
+
+ case STATE_ICW4:
+ /* write ICW4 */
+ if (LOG_ICW)
+ logerror("pic8259_w(): ICW4; data=0x%02X\n", data);
+
+ pic8259->nested = (data & 0x10) ? 1 : 0;
+ pic8259->mode = (data >> 2) & 3;
+ pic8259->auto_eoi = (data & 0x02) ? 1 : 0;
+ pic8259->is_x86 = (data & 0x01) ? 1 : 0;
+ pic8259->state = STATE_READY;
+ break;
+
+ case STATE_READY:
+ /* write OCW1 - set interrupt mask register */
+ if (LOG_OCW)
+ logerror("pic8259_w(): OCW1; data=0x%02X\n", data);
+
+ pic8259->imr = data;
+ break;
+ }
+ break;
+ }
+ pic8259_set_timer(pic8259);
+}
+
+
+
+static DEVICE_START( pic8259 )
+{
+ pic8259_t *pic8259 = get_safe_token(device);
+ const struct pic8259_interface *intf = (const struct pic8259_interface *)device->static_config();
+
+ assert(intf != NULL);
+
+ pic8259->timer = device->machine().scheduler().timer_alloc( FUNC(pic8259_timerproc), (void *)device );
+
+ /* resolve callbacks */
+ pic8259->out_int_func.resolve(intf->out_int_func, *device);
+ pic8259->sp_en_func.resolve(intf->sp_en_func, *device);
+ pic8259->read_slave_ack_func.resolve(intf->read_slave_ack_func, *device);
+}
+
+
+static DEVICE_RESET( pic8259 ) {
+ pic8259_t *pic8259 = get_safe_token(device);
+
+ pic8259->state = STATE_READY;
+ pic8259->isr = 0;
+ pic8259->irr = 0;
+ pic8259->irq_lines = 0;
+ pic8259->prio = 0;
+ pic8259->imr = 0;
+ pic8259->input = 0;
+ pic8259->ocw3 = 2;
+ pic8259->level_trig_mode = 0;
+ pic8259->vector_size = 0;
+ pic8259->cascade = 0;
+ pic8259->icw4_needed = 0;
+ pic8259->base = 0;
+ pic8259->slave = 0;
+ pic8259->nested = 0;
+ pic8259->mode = 0;
+ pic8259->auto_eoi = 0;
+ pic8259->is_x86 = 0;
+ pic8259->vector_addr_low = 0;
+ pic8259->vector_addr_high = 0;
+
+ pic8259->master = pic8259->sp_en_func();
+}
+
+
+DEVICE_GET_INFO( pic8259 ) {
+ switch ( state ) {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(pic8259_t); break;
+ case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(pic8259); break;
+ case DEVINFO_FCT_STOP: /* nothing */ break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(pic8259); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Intel PIC8259"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "PIC8259"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.00"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright the MAME and MESS Teams"); break;
+ }
+}
+
+
+DEFINE_LEGACY_DEVICE(PIC8259, pic8259);
diff --git a/trunk/src/emu/machine/pic8259.h b/trunk/src/emu/machine/pic8259.h
new file mode 100644
index 00000000000..230074880ec
--- /dev/null
+++ b/trunk/src/emu/machine/pic8259.h
@@ -0,0 +1,73 @@
+/***************************************************************************
+
+ Intel 8259A
+
+ Programmable Interrupt Controller
+
+ _____ _____
+ _CS 1 |* \_/ | 28 VCC
+ _WR 2 | | 27 A0
+ _RD 3 | | 26 _INTA
+ D7 4 | | 25 IR7
+ D6 5 | | 24 IR6
+ D5 6 | | 23 IR5
+ D4 7 | 8259A | 22 IR4
+ D3 8 | | 21 IR3
+ D2 9 | | 20 IR2
+ D1 10 | | 19 IR1
+ D0 11 | | 18 IR0
+ CAS0 12 | | 17 INT
+ CAS1 13 | | 16 _SP/_EN
+ GND 14 |_____________| 15 CAS2
+
+***************************************************************************/
+
+#ifndef __PIC8259_H__
+#define __PIC8259_H__
+
+#include "devlegcy.h"
+#include "devcb.h"
+
+DECLARE_LEGACY_DEVICE(PIC8259, pic8259);
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+struct pic8259_interface
+{
+ /* Called when int line changes */
+ devcb_write_line out_int_func;
+ /* 1 - when master, 0 - when slave */
+ devcb_read_line sp_en_func;
+ /* Called when on master slave irq is trigered*/
+ devcb_read8 read_slave_ack_func;
+};
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_PIC8259_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, PIC8259, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+
+/* device interface */
+READ8_DEVICE_HANDLER( pic8259_r );
+WRITE8_DEVICE_HANDLER( pic8259_w );
+int pic8259_acknowledge(device_t *device);
+
+/* interrupt requests */
+WRITE_LINE_DEVICE_HANDLER( pic8259_ir0_w );
+WRITE_LINE_DEVICE_HANDLER( pic8259_ir1_w );
+WRITE_LINE_DEVICE_HANDLER( pic8259_ir2_w );
+WRITE_LINE_DEVICE_HANDLER( pic8259_ir3_w );
+WRITE_LINE_DEVICE_HANDLER( pic8259_ir4_w );
+WRITE_LINE_DEVICE_HANDLER( pic8259_ir5_w );
+WRITE_LINE_DEVICE_HANDLER( pic8259_ir6_w );
+WRITE_LINE_DEVICE_HANDLER( pic8259_ir7_w );
+
+
+#endif /* __PIC8259_H__ */
diff --git a/trunk/src/emu/machine/pit8253.c b/trunk/src/emu/machine/pit8253.c
new file mode 100644
index 00000000000..e37db95ddd4
--- /dev/null
+++ b/trunk/src/emu/machine/pit8253.c
@@ -0,0 +1,1193 @@
+/*****************************************************************************
+ *
+ * Programmable Interval Timer 8253/8254
+ *
+ * Three Independent Timers
+ * (gate, clock, out pins)
+ *
+ * 8254 has an additional readback feature
+ *
+ * Revision History
+ * 1-Apr-2008 - WFP: Changed the implementation into a device.
+ * 8-Jul-2004 - AJ: Fixed some bugs. Styx now runs correctly.
+ * Implemented 8254 features.
+ * 1-Mar-2004 - NPW: Did an almost total rewrite and cleaned out much
+ * of the ugliness in the previous design. Bug #430
+ * seems to be fixed
+ * 1-Jul-2000 - PeT: Split off from PC driver and componentized
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+#include "machine/pit8253.h"
+
+
+
+/***************************************************************************
+
+ Structures & macros
+
+***************************************************************************/
+
+#define MAX_TIMER 3
+#define VERBOSE 0
+
+#define LOG1(msg) do { if (VERBOSE >= 1) logerror msg; } while (0)
+#define LOG2(msg) do { if (VERBOSE >= 2) logerror msg; } while (0)
+
+#define CYCLES_NEVER ((UINT32) -1)
+
+/* device types */
+enum {
+ TYPE_PIT8253 = 0,
+ TYPE_PIT8254,
+
+ NUM_TYPES
+};
+
+
+/* device tags */
+static const char * const device_tags[NUM_TYPES] = { "pit8253", "pit8254" };
+
+
+struct pit8253_timer
+{
+ int index; /* index number of the timer */
+ double clockin; /* input clock frequency in Hz */
+ int clock; /* clock signal when clockin is 0 */
+
+ devcb_resolved_read_line in_gate_func; /* callback for gate input */
+ devcb_resolved_write_line out_out_func; /* callback function for when output changes */
+
+ attotime last_updated; /* time when last updated */
+
+ emu_timer *updatetimer; /* MAME timer to process updates */
+
+ UINT16 value; /* current counter value ("CE" in Intel docs) */
+ UINT16 latch; /* latched counter value ("OL" in Intel docs) */
+ UINT16 count; /* new counter value ("CR" in Intel docs) */
+ UINT8 control; /* 6-bit control byte */
+ UINT8 status; /* status byte - 8254 only */
+ UINT8 lowcount; /* LSB of new counter value for 16-bit writes */
+ INT32 rmsb; /* 1 = Next read is MSB of 16-bit value */
+ INT32 wmsb; /* 1 = Next write is MSB of 16-bit value */
+ INT32 output; /* 0 = low, 1 = high */
+
+ INT32 gate; /* gate input (0 = low, 1 = high) */
+ INT32 latched_count; /* number of bytes of count latched */
+ INT32 latched_status; /* 1 = status latched (8254 only) */
+ INT32 null_count; /* 1 = mode control or count written, 0 = count loaded */
+ INT32 phase; /* see phase definition tables in simulate2(), below */
+
+ UINT32 cycles_to_output; /* cycles until output callback called */
+};
+
+typedef struct _pit8253_t pit8253_t;
+struct _pit8253_t
+{
+ const struct pit8253_config *config;
+ int device_type;
+ struct pit8253_timer timers[MAX_TIMER];
+};
+
+#define CTRL_ACCESS(control) (((control) >> 4) & 0x03)
+#define CTRL_MODE(control) (((control) >> 1) & (((control) & 0x04) ? 0x03 : 0x07))
+#define CTRL_BCD(control) (((control) >> 0) & 0x01)
+
+
+/***************************************************************************
+
+ Functions
+
+***************************************************************************/
+
+/* makes sure that the passed in device is of the right type */
+INLINE pit8253_t *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert((device->type() == PIT8253) || (device->type() == PIT8254));
+
+ return (pit8253_t *) downcast<legacy_device_base *>(device)->token();
+}
+
+
+static struct pit8253_timer *get_timer(struct _pit8253_t *pit,int which)
+{
+ which &= 3;
+ if (which < MAX_TIMER)
+ return &pit->timers[which];
+ return NULL;
+}
+
+
+static int pit8253_gate(struct pit8253_timer *timer)
+{
+ if (!timer->in_gate_func.isnull())
+ return timer->in_gate_func();
+ else
+ return timer->gate;
+}
+
+
+INLINE UINT32 decimal_from_bcd(UINT16 val)
+{
+ /* In BCD mode, a nybble loaded with value A-F counts down the same as in
+ binary mode, but wraps around to 9 instead of F after 0, so loading the
+ count register with 0xFFFF gives a period of
+ 0xF - for the units to count down to 0
+ + 10*0xF - for the tens to count down to 0
+ + 100*0xF - for the hundreds to count down to 0
+ + 1000*0xF - for the thousands to count down to 0
+ = 16665 cycles
+ */
+ return
+ ((val>>12) & 0xF) * 1000 +
+ ((val>> 8) & 0xF) * 100 +
+ ((val>> 4) & 0xF) * 10 +
+ ( val & 0xF);
+}
+
+
+static UINT32 adjusted_count(int bcd,UINT16 val)
+{
+ if (bcd == 0)
+ return val == 0 ? 0x10000 : val;
+ return val == 0 ? 10000 : decimal_from_bcd(val);
+}
+
+
+/* This function subtracts 1 from timer->value "cycles" times, taking into
+ account binary or BCD operation, and wrapping around from 0 to 0xFFFF or
+ 0x9999 as necessary. */
+static void decrease_counter_value(struct pit8253_timer *timer,UINT64 cycles)
+{
+ UINT16 value;
+ int units, tens, hundreds, thousands;
+
+ if (CTRL_BCD(timer->control) == 0)
+ {
+ timer->value -= (cycles & 0xFFFF);
+ return;
+ }
+
+ value = timer->value;
+ units = value & 0xF;
+ tens = (value >> 4) & 0xF;
+ hundreds = (value >> 8) & 0xF;
+ thousands = (value >> 12) & 0xF;
+
+ if (cycles <= units)
+ {
+ units -= cycles;
+ }
+ else
+ {
+ cycles -= units;
+ units = (10 - cycles%10)%10;
+
+ cycles =(cycles+9)/10; /* the +9 is so we get a carry if cycles%10 wasn't 0 */
+ if (cycles <= tens)
+ {
+ tens -= cycles;
+ }
+ else
+ {
+ cycles -= tens;
+ tens = (10 - cycles%10) % 10;
+
+ cycles = (cycles+9) / 10;
+ if (cycles <= hundreds)
+ {
+ hundreds -= cycles;
+ }
+ else
+ {
+ cycles -= hundreds;
+ hundreds = (10 - cycles%10)%10;
+ cycles=(cycles+9)/10;
+ thousands = (10 + thousands - cycles%10)%10;
+ }
+ }
+ }
+
+ timer->value = (thousands << 12) | (hundreds << 8) | (tens << 4) | units;
+}
+
+
+/* Counter loading: transfer of a count from the CR to the CE */
+static void load_counter_value(device_t *device, struct pit8253_timer *timer)
+{
+ timer->value = timer->count;
+ timer->null_count = 1;
+ if ( CTRL_MODE(timer->control) == 3 && timer->output == 0)
+ timer->value &= 0xfffe;
+}
+
+
+static void set_output(device_t *device, struct pit8253_timer *timer,int output)
+{
+ if (output != timer->output)
+ {
+ timer->output = output;
+ timer->out_out_func(timer->output);
+ }
+}
+
+
+/* This emulates timer "timer" for "elapsed_cycles" cycles and assumes no
+ callbacks occur during that time. */
+static void simulate2(device_t *device, struct pit8253_timer *timer, INT64 elapsed_cycles)
+{
+ UINT32 adjusted_value;
+ int bcd = CTRL_BCD(timer->control);
+ int mode = CTRL_MODE(timer->control);
+ int cycles_to_output = 0;
+
+ LOG2(("pit8253: simulate2(): simulating %d cycles for %d in mode %d, bcd = %d, phase = %d, gate = %d, output %d, value = 0x%04x\n",
+ (int)elapsed_cycles,timer->index,mode,bcd,timer->phase,pit8253_gate(timer),timer->output,timer->value));
+
+ switch (mode) {
+ case 0:
+ /* Mode 0: (Interrupt on Terminal Count)
+
+ +------------------
+ |
+ ----------+
+ <- n+1 ->
+
+ ^
+ +- counter load
+
+ phase|output|length |value|next|comment
+ -----+------+--------+-----+----+----------------------------------
+ 0|low |infinity| |1 |waiting for count
+ 1|low |1 | |2 |internal delay when counter loaded
+ 2|low |n |n..1 |3 |counting down
+ 3|high |infinity|0..1 |3 |counting down
+
+ Gate level sensitive only. Low disables counting, high enables it. */
+
+ if (timer->phase == 0)
+ {
+ cycles_to_output = CYCLES_NEVER;
+ }
+ else
+ {
+ if (elapsed_cycles >= 0 && timer->phase == 1)
+ {
+ /* Counter load cycle */
+ if (elapsed_cycles > 0) {
+ --elapsed_cycles;
+ timer->phase = 2;
+ }
+ load_counter_value( device, timer );
+ }
+
+ if ( pit8253_gate(timer) == 0 )
+ {
+ cycles_to_output = CYCLES_NEVER;
+ }
+ else
+ {
+ if (timer->phase == 2)
+ {
+ adjusted_value = adjusted_count(bcd,timer->value);
+ if (elapsed_cycles >= adjusted_value)
+ {
+ /* Counter wrapped, output goes high */
+ elapsed_cycles -= adjusted_value;
+ timer->phase = 3;
+ timer->value = 0;
+ set_output( device, timer, 1 );
+ }
+ }
+
+ decrease_counter_value(timer,elapsed_cycles);
+
+ switch( timer->phase )
+ {
+ case 1: cycles_to_output = 1; break;
+ case 2: cycles_to_output = adjusted_count( bcd, timer->value ); break;
+ case 3: cycles_to_output = adjusted_count( bcd, timer->value ); break;
+ }
+ }
+ }
+ break;
+
+
+ case 1:
+ /* Mode 1: (Hardware Retriggerable One-Shot a.k.a. Programmable One-Shot)
+
+ -----+ +------------------
+ | |
+ +-------+
+ <- n ->
+
+ ^
+ +- trigger
+
+ phase|output|length |value|next|comment
+ -----+------+--------+-----+----+----------------------------------
+ 0|high |infinity| |1 |counting down
+ 1|high |1 | |2 |internal delay to load counter
+ 2|low |n |n..1 |3 |counting down
+ 3|high |infinity|0..1 |3 |counting down
+
+ Gate rising-edge sensitive only.
+ Rising edge initiates counting and resets output after next clock. */
+
+ if ( elapsed_cycles >= 0 && timer->phase == 1 )
+ {
+ /* Counter load cycle, output goes low */
+ if (elapsed_cycles > 0) {
+ --elapsed_cycles;
+ timer->phase = 2;
+ }
+ load_counter_value( device, timer );
+ set_output( device, timer, 0 );
+ }
+
+ if ( timer->phase == 2 )
+ {
+ adjusted_value = adjusted_count( bcd, timer->value );
+ if ( elapsed_cycles >= adjusted_value )
+ {
+ /* Counter wrapped, output goes high */
+ timer->phase = 3;
+ set_output( device, timer, 1 );
+ }
+ }
+
+ decrease_counter_value( timer, elapsed_cycles );
+
+ switch( timer->phase )
+ {
+ case 1: cycles_to_output = 1; break;
+ case 2: cycles_to_output = adjusted_count( bcd, timer->value ); break;
+ default: cycles_to_output = CYCLES_NEVER; break;
+ }
+ break;
+
+
+ case 2:
+ /* Mode 2: (Rate Generator)
+
+ --------------+ +---------+ +----
+ | | | |
+ +-+ +-+
+ <- n -X- n ->
+ <1>
+ ^
+ +- counter load or trigger
+
+ phase|output|length |value|next|comment
+ -----+------+--------+-----+----+----------------------------------
+ 0|high |infinity| |1 |waiting for count
+ 1|high |1 | |2 |internal delay to load counter
+ 2|high |n |n..2 |3 |counting down
+ 3|low |1 |1 |2 |reload counter
+
+ Counter rewrite has no effect until repeated
+
+ Gate rising-edge and level sensitive.
+ Gate low disables counting and sets output immediately high.
+ Rising-edge reloads count and initiates counting
+ Gate high enables counting. */
+
+ if (pit8253_gate(timer) == 0 || timer->phase == 0)
+ {
+ /* Gate low or mode control write forces output high */
+ set_output(device, timer, 1);
+ cycles_to_output = CYCLES_NEVER;
+ }
+ else
+ {
+ if ( elapsed_cycles >= 0 && timer->phase == 1 )
+ {
+ if (elapsed_cycles > 0) {
+ --elapsed_cycles;
+ timer->phase = 2;
+ }
+ load_counter_value( device, timer );
+ }
+
+ adjusted_value = adjusted_count( bcd, timer->value );
+
+ do
+ {
+ if ( timer->phase == 2 )
+ {
+ if ( elapsed_cycles + 1 >= adjusted_value )
+ {
+ /* Coounter hits 1, output goes low */
+ timer->phase = 3;
+ set_output( device, timer, 0 );
+ }
+ }
+
+ if ( elapsed_cycles > 0 && timer->phase == 3 )
+ {
+ /* Reload counter, output goes high */
+ --elapsed_cycles;
+ timer->phase = 2;
+ load_counter_value( device, timer );
+ adjusted_value = adjusted_count( bcd, timer->value );
+ set_output( device, timer, 1 );
+ }
+ }
+ while( elapsed_cycles >= adjusted_value );
+
+ /* Calculate counter value */
+ decrease_counter_value(timer,elapsed_cycles);
+
+ switch( timer->phase )
+ {
+ case 1: cycles_to_output = 1; break;
+ default: cycles_to_output = (timer->value == 1 ? 1 : (adjusted_count(bcd,timer->value) - 1));
+ }
+ }
+ break;
+
+
+ case 3:
+ /* Mode 3: (Square Wave Generator)
+
+ ----------------+ +-----------+ +----
+ | | | |
+ +-----------+ +-----------+
+ <- (n+1)/2 -X- n/2 ->
+ ^
+ +- counter load or trigger
+
+ phase|output|length |value|next|comment
+ -----+------+--------+-----+----+----------------------------------
+ 0|high |infinity| |1 |waiting for count
+ 1|high |1 | |2 |internal delay to load counter
+ 2|high |n/2(+1) |n..0 |3 |counting down double speed, reload counter
+ 3|low |n/2 |n..0 |2 |counting down double speed, reload counter
+
+ Counter rewrite has no effect until repeated (output falling or rising)
+
+ Gate rising-edge and level sensitive.
+ Gate low disables counting and sets output immediately high.
+ Rising-edge reloads count and initiates counting
+ Gate high enables counting. */
+
+ if (pit8253_gate(timer) == 0 || timer->phase == 0)
+ {
+ /* Gate low or mode control write forces output high */
+ set_output(device, timer, 1);
+ cycles_to_output = CYCLES_NEVER;
+ }
+ else
+ {
+ if ( elapsed_cycles >= 0 && timer->phase == 1 )
+ {
+ if (elapsed_cycles > 0) {
+ --elapsed_cycles;
+ timer->phase = 2;
+ }
+ load_counter_value( device, timer );
+ }
+
+ if (elapsed_cycles > 0) {
+ adjusted_value = adjusted_count( bcd, timer->value );
+
+ do
+ {
+ if ( timer->phase == 2 && elapsed_cycles >= ( ( adjusted_value + 1 ) >> 1 ) )
+ {
+ /* High phase expired, output goes low */
+ elapsed_cycles -= ( ( adjusted_value + 1 ) >> 1 );
+ timer->phase = 3;
+ load_counter_value( device, timer );
+ adjusted_value = adjusted_count( bcd, timer->value );
+ set_output( device, timer, 0 );
+ }
+
+ if ( timer->phase == 3 && elapsed_cycles >= ( adjusted_value >> 1 ) )
+ {
+ /* Low phase expired, output goes high */
+ elapsed_cycles -= ( adjusted_value >> 1 );
+ timer->phase = 2;
+ load_counter_value( device, timer );
+ adjusted_value = adjusted_count( bcd, timer->value );
+ set_output( device, timer, 1 );
+ }
+ }
+ while( ( timer->phase == 2 && elapsed_cycles >= ( ( adjusted_value + 1 ) >> 1 ) ) ||
+ ( timer->phase == 3 && elapsed_cycles >= ( adjusted_value >> 1 ) ) );
+
+ decrease_counter_value(timer,elapsed_cycles<<1);
+ switch( timer->phase )
+ {
+ case 1: cycles_to_output = 1; break;
+ case 2: cycles_to_output = ( adjusted_count( bcd, timer->value ) + 1 ) >> 1; break;
+ case 3: cycles_to_output = adjusted_count( bcd, timer->value ) >> 1; break;
+ }
+ }
+ }
+ break;
+
+
+ case 4:
+ case 5:
+ /* Mode 4: (Software Trigger Strobe)
+ Mode 5: (Hardware Trigger Strobe)
+
+ --------------+ +--------------------
+ | |
+ +-+
+ <- n+1 ->
+ ^ <1>
+ +- counter load (mode 4) or trigger (mode 5)
+
+ phase|output|length |value|next|comment
+ -----+------+--------+-----+----+----------------------------------
+ 0|high |infinity|0..1 |0 |waiting for count/counting down
+ 1|high |1 | |2 |internal delay when counter loaded
+ 2|high |n |n..1 |3 |counting down
+ 3|low |1 |0 |0 |strobe
+
+ Mode 4 only: counter rewrite loads new counter
+ Mode 5 only: count not reloaded immediately.
+ Mode control write doesn't stop count but sets output high
+
+ Mode 4 only: Gate level sensitive only. Low disables counting, high enables it.
+ Mode 5 only: Gate rising-edge sensitive only. Rising edge initiates counting */
+
+ if (pit8253_gate(timer) == 0 && mode == 4)
+ {
+ cycles_to_output = CYCLES_NEVER;
+ }
+ else
+ {
+ if (elapsed_cycles >= 0 && timer->phase == 1)
+ {
+ if (elapsed_cycles > 0) {
+ --elapsed_cycles;
+ timer->phase = 2;
+ }
+ load_counter_value( device, timer );
+ }
+
+ if ( timer->value == 0 && timer->phase == 2 )
+ adjusted_value = 0;
+ else
+ adjusted_value = adjusted_count( bcd, timer->value );
+
+ if ( timer->phase == 2 && elapsed_cycles >= adjusted_value )
+ {
+ /* Counter has hit zero, set output to low */
+ elapsed_cycles -= adjusted_value;
+ timer->phase = 3;
+ timer->value = 0;
+ set_output( device, timer, 0 );
+ }
+
+ if (elapsed_cycles > 0 && timer->phase == 3)
+ {
+ --elapsed_cycles;
+ timer->phase = 0;
+ decrease_counter_value(timer,1);
+ set_output( device, timer, 1 );
+ }
+
+ decrease_counter_value(timer,elapsed_cycles);
+
+ switch( timer->phase )
+ {
+ case 1: cycles_to_output = 1; break;
+ case 2: cycles_to_output = adjusted_count( bcd, timer->value ); break;
+ case 3: cycles_to_output = 1; break;
+ }
+ }
+ break;
+ }
+
+ timer->cycles_to_output = cycles_to_output;
+ if (cycles_to_output == CYCLES_NEVER || timer->clockin == 0)
+ {
+ timer->updatetimer->adjust(attotime::never, timer->index);
+ }
+ else
+ {
+ attotime next_fire_time = timer->last_updated + cycles_to_output * attotime::from_hz( timer->clockin );
+
+ timer->updatetimer->adjust(next_fire_time - device->machine().time(), timer->index );
+ }
+
+ LOG2(("pit8253: simulate2(): simulating %d cycles for %d in mode %d, bcd = %d, phase = %d, gate = %d, output %d, value = 0x%04x, cycles_to_output = %04x\n",
+ (int)elapsed_cycles,timer->index,mode,bcd,timer->phase,pit8253_gate(timer),timer->output,timer->value,cycles_to_output));
+}
+
+
+/* This emulates timer "timer" for "elapsed_cycles" cycles, broken down into
+ sections punctuated by callbacks.
+
+ The loop technically should never execute even once. It's here to eliminate
+ the following potential bug:
+
+ 1) The mame timer isn't perfectly accurate.
+ 2) The output callback is executed too late, after an update which
+ brings the timer's local time past the callback time.
+ 3) A short pulse is skipped.
+ 4) That short pulse would have triggered an interrupt. The interrupt is
+ skipped.
+
+ This is a loop instead of an "if" statement in case the mame timer is
+ inaccurate by more than one cycle, and the output changed multiple
+ times during the discrepancy. In practice updates should still be O(1).
+*/
+static void simulate(device_t *device, struct pit8253_timer *timer, INT64 elapsed_cycles)
+{
+ if ( elapsed_cycles > 0 )
+ simulate2(device, timer, elapsed_cycles);
+ else
+ if ( timer->clockin )
+ timer->updatetimer->adjust(attotime::from_hz( timer->clockin ), timer->index );
+}
+
+
+/* This brings timer "timer" up to date */
+static void update(device_t *device, struct pit8253_timer *timer)
+{
+ /* With the 82C54's maximum clockin of 10MHz, 64 bits is nearly 60,000
+ years of time. Should be enough for now. */
+ attotime now = device->machine().time();
+ attotime elapsed_time = now - timer->last_updated;
+ INT64 elapsed_cycles = elapsed_time.as_double() * timer->clockin;
+
+ LOG1(("pit8253: update(): timer %d, %" I64FMT "d elapsed_cycles\n", timer->index, elapsed_cycles));
+
+ if ( timer->clockin )
+ {
+ timer->last_updated += elapsed_cycles * attotime::from_hz(timer->clockin);
+ }
+ else
+ {
+ timer->last_updated = now;
+ }
+
+ simulate(device, timer, elapsed_cycles);
+}
+
+
+static TIMER_CALLBACK( update_timer_cb )
+{
+ device_t *device = (device_t *)ptr;
+ pit8253_t *pit8253 = get_safe_token(device);
+ struct pit8253_timer *timer = get_timer(pit8253,param);
+
+ LOG2(("pit8253: output_changed(): timer %d\n",param));
+
+ update( device, timer );
+}
+
+
+/* We recycle bit 0 of timer->value to hold the phase in mode 3 when count is
+ odd. Since read commands in mode 3 always return even numbers, we need to
+ mask this bit off. */
+static UINT16 masked_value(struct pit8253_timer *timer)
+{
+ LOG2(("pit8253: masked_value\n"));
+
+ if (CTRL_MODE(timer->control) == 3)
+ return timer->value & 0xfffe;
+ return timer->value;
+}
+
+/* Reads only affect the following bits of the counter state:
+ latched_status
+ latched_count
+ rmsb
+ so they don't affect any timer operations except other reads. */
+READ8_DEVICE_HANDLER( pit8253_r )
+{
+ pit8253_t *pit8253 = get_safe_token(device);
+ struct pit8253_timer *timer = get_timer(pit8253,offset);
+ UINT8 data;
+ UINT16 value;
+
+ LOG2(("pit8253_r(): offset %d\n", offset));
+
+ if (timer == NULL)
+ {
+ /* Reading mode control register is illegal according to docs */
+ /* Experimentally determined: reading it returns 0 */
+ data = 0;
+ }
+ else
+ {
+ update(device, timer);
+
+ if (timer->latched_status)
+ {
+ /* Read status register (8254 only) */
+ data = timer->status;
+ timer->latched_status = 0;
+ }
+ else
+ {
+ if (timer->latched_count != 0)
+ {
+ /* Read back latched count */
+ data = (timer->latch >> (timer->rmsb != 0 ? 8 : 0)) & 0xff;
+ timer->rmsb = 1 - timer->rmsb;
+ --timer->latched_count;
+ }
+ else {
+ value = masked_value(timer);
+
+ /* Read back current count */
+ switch(CTRL_ACCESS(timer->control)) {
+ case 0:
+ default:
+ /* This should never happen */
+ data = 0; /* Appease compiler */
+ break;
+
+ case 1:
+ /* read counter bits 0-7 only */
+ data = (value >> 0) & 0xff;
+ break;
+
+ case 2:
+ /* read counter bits 8-15 only */
+ data = (value >> 8) & 0xff;
+ break;
+
+ case 3:
+ /* read bits 0-7 first, then 8-15 */
+ data = (value >> (timer->rmsb != 0 ? 8 : 0)) & 0xff;
+ timer->rmsb = 1 - timer->rmsb;
+ break;
+ }
+ }
+ }
+ }
+
+ LOG2(("pit8253_r(): offset=%d data=0x%02x\n", offset, data));
+ return data;
+}
+
+
+/* Loads a new value from the bus to the count register (CR) */
+static void load_count(device_t *device, struct pit8253_timer *timer, UINT16 newcount)
+{
+ int mode = CTRL_MODE(timer->control);
+
+ LOG1(("pit8253: load_count(): %04x\n",newcount));
+
+ if (newcount == 1)
+ {
+ /* Count of 1 is illegal in modes 2 and 3. What happens here was
+ determined experimentally. */
+ if (mode == 2)
+ newcount = 2;
+ if (mode == 3)
+ newcount = 0;
+ }
+ timer->count = newcount;
+ if (mode == 2 || mode == 3)
+ {
+ if (timer->phase == 0)
+ {
+ timer->phase = 1;
+ }
+ }
+ else
+ {
+ if (mode == 0 || mode == 4)
+ {
+ timer->phase = 1;
+ }
+ }
+}
+
+
+static void readback(device_t *device, struct pit8253_timer *timer,int command)
+{
+ UINT16 value;
+ update(device, timer);
+
+ if ((command & 1) == 0)
+ {
+ /* readback status command */
+ if (timer->latched_status == 0)
+ {
+ timer->status = timer->control | (timer->output != 0 ? 0x80 : 0) | (timer->null_count != 0 ? 0x40 : 0);
+ }
+
+ timer->latched_status = 1;
+ }
+ /* Experimentally determined: the read latch command seems to have no
+ effect if we're halfway through a 16-bit read */
+ if ((command & 2) == 0 && timer->rmsb == 0)
+ {
+ /* readback count command */
+
+ if (timer->latched_count == 0)
+ {
+ value = masked_value(timer);
+ switch(CTRL_ACCESS(timer->control)) {
+ case 0:
+ /* This should never happen */
+ break;
+
+ case 1:
+ /* latch bits 0-7 only */
+ timer->latch = ((value << 8) & 0xff00) | (value & 0xff);
+ timer->latched_count = 1;
+ break;
+
+ case 2:
+ /* read bits 8-15 only */
+ timer->latch = (value & 0xff00) | ((value >> 8) & 0xff);
+ timer->latched_count = 1;
+ break;
+
+ case 3:
+ /* latch all 16 bits */
+ timer->latch = value;
+ timer->latched_count = 2;
+ break;
+ }
+ }
+ }
+}
+
+
+WRITE8_DEVICE_HANDLER( pit8253_w )
+{
+ pit8253_t *pit8253 = get_safe_token(device);
+ struct pit8253_timer *timer = get_timer(pit8253,offset);
+ int read_command;
+
+ LOG2(("pit8253_w(): offset=%d data=0x%02x\n", offset, data));
+
+ if (timer == NULL) {
+ /* Write to mode control register */
+ timer = get_timer(pit8253, (data >> 6) & 3);
+ if (timer == NULL)
+ {
+ /* Readback command. Illegal on 8253 */
+ /* Todo: find out what (if anything) the 8253 hardware actually does here. */
+ if (pit8253->device_type == TYPE_PIT8254)
+ {
+ LOG1(("pit8253_w(): readback %02x\n", data & 0x3f));
+
+ /* Bit 0 of data must be 0. Todo: find out what the hardware does if it isn't. */
+ read_command = (data >> 4) & 3;
+ if ((data & 2) != 0)
+ readback(device, get_timer(pit8253,0), read_command);
+ if ((data & 4) != 0)
+ readback(device, get_timer(pit8253,1), read_command);
+ if ((data & 8) != 0)
+ readback(device, get_timer(pit8253,2), read_command);
+ }
+ return;
+ }
+
+ update(device, timer);
+
+ if (CTRL_ACCESS(data) == 0)
+ {
+ LOG1(("pit8253_write(): timer=%d readback\n", (data >> 6) & 3));
+
+ /* Latch current timer value */
+ /* Experimentally verified: this command does not affect the mode control register */
+ readback(device, timer, 1);
+ }
+ else {
+ LOG1(("pit8253_write(): timer=%d bytes=%d mode=%d bcd=%d\n", (data >> 6) & 3, (data >> 4) & 3, (data >> 1) & 7,data & 1));
+
+ timer->control = (data & 0x3f);
+ timer->null_count = 1;
+ timer->wmsb = timer->rmsb = 0;
+ /* Phase 0 is always the phase after a mode control write */
+ timer->phase = 0;
+ set_output(device, timer, CTRL_MODE(timer->control) ? 1 : 0);
+ }
+ }
+ else
+ {
+ int middle_of_a_cycle = 0;
+
+ update(device, timer);
+
+ if ( device->machine().time() > timer->last_updated && timer->clockin != 0 )
+ {
+ middle_of_a_cycle = 1;
+ }
+
+ switch(CTRL_ACCESS(timer->control)) {
+ case 0:
+ /* This should never happen */
+ break;
+
+ case 1:
+ /* read/write counter bits 0-7 only */
+
+ /* check if we should compensate for not being on a cycle boundary */
+ if ( middle_of_a_cycle )
+ timer->last_updated += attotime::from_hz(timer->clockin);
+
+ load_count(device, timer, data);
+ simulate2(device, timer, 0 );
+ if ( CTRL_MODE(timer->control) == 0 )
+ {
+ set_output( device, timer, 0 );
+ }
+ break;
+
+ case 2:
+ /* read/write counter bits 8-15 only */
+
+ /* check if we should compensate for not being on a cycle boundary */
+ if ( middle_of_a_cycle )
+ timer->last_updated += attotime::from_hz(timer->clockin);
+
+ load_count(device, timer, data << 8);
+ simulate2(device, timer, 0 );
+ break;
+
+ case 3:
+ /* read/write bits 0-7 first, then 8-15 */
+ if (timer->wmsb != 0)
+ {
+ /* check if we should compensate for not being on a cycle boundary */
+ if ( middle_of_a_cycle )
+ timer->last_updated += attotime::from_hz(timer->clockin);
+
+ load_count(device, timer,timer->lowcount | (data << 8));
+ simulate2(device, timer, 0 );
+ }
+ else
+ {
+ timer->lowcount = data;
+ if (CTRL_MODE(timer->control) == 0)
+ {
+ /* The Intel docs say that writing the MSB in mode 0, phase
+ 2 won't stop the count, but this was experimentally
+ determined to be false. */
+ timer->phase = 0;
+ set_output( device, timer, 0 );
+ }
+ }
+ timer->wmsb = 1 - timer->wmsb;
+ break;
+ }
+ }
+}
+
+static void pit8253_gate_w(device_t *device, int gate, int state)
+{
+ pit8253_t *pit8253 = get_safe_token(device);
+ struct pit8253_timer *timer = get_timer(pit8253, gate);
+
+ LOG2(("pit8253_gate_w(): gate=%d state=%d\n", gate, state));
+
+ if (timer == NULL)
+ return;
+
+ if (!timer->in_gate_func.isnull())
+ {
+ logerror("pit8253_gate_w: write has no effect because a read handler is already defined!\n");
+ }
+ else
+ {
+ if (state != timer->gate)
+ {
+ int mode = CTRL_MODE(timer->control);
+
+ update(device, timer);
+ timer->gate = state;
+ if (state != 0 && ( mode == 1 || mode == 2 || mode == 5 ))
+ {
+ timer->phase = 1;
+ }
+ update(device, timer);
+ }
+ }
+}
+
+WRITE_LINE_DEVICE_HANDLER( pit8253_gate0_w ) { pit8253_gate_w(device, 0, state); }
+WRITE_LINE_DEVICE_HANDLER( pit8253_gate1_w ) { pit8253_gate_w(device, 1, state); }
+WRITE_LINE_DEVICE_HANDLER( pit8253_gate2_w ) { pit8253_gate_w(device, 2, state); }
+
+
+/* ----------------------------------------------------------------------- */
+
+int pit8253_get_output(device_t *device, int timerno)
+{
+ pit8253_t *pit8253 = get_safe_token(device);
+ struct pit8253_timer *timer = get_timer(pit8253,timerno);
+ int result;
+
+ update(device, timer);
+ result = timer->output;
+ LOG2(("pit8253_get_output(): PIT timer=%d result=%d\n", timerno, result));
+ return result;
+}
+
+
+
+void pit8253_set_clockin(device_t *device, int timerno, double new_clockin)
+{
+ pit8253_t *pit8253 = get_safe_token(device);
+ struct pit8253_timer *timer = get_timer(pit8253,timerno);
+
+ LOG2(("pit8253_set_clockin(): PIT timer=%d, clockin = %lf\n", timerno,new_clockin));
+
+ update(device, timer);
+ timer->clockin = new_clockin;
+ update(device, timer);
+}
+
+
+static void pit8253_set_clock_signal(device_t *device, int timerno, int state)
+{
+ pit8253_t *pit8253 = get_safe_token(device);
+ struct pit8253_timer *timer = get_timer(pit8253,timerno);
+
+ LOG2(("pit8253_set_clock_signal(): PIT timer=%d, state = %d\n", timerno, state));
+
+ /* Trigger on low to high transition */
+ if ( !timer->clock && state )
+ {
+ /* Advance a cycle */
+ simulate2(device, timer, 1);
+ }
+ timer->clock = state;
+}
+
+WRITE_LINE_DEVICE_HANDLER( pit8253_clk0_w ) { pit8253_set_clock_signal(device, 0, state); }
+WRITE_LINE_DEVICE_HANDLER( pit8253_clk1_w ) { pit8253_set_clock_signal(device, 1, state); }
+WRITE_LINE_DEVICE_HANDLER( pit8253_clk2_w ) { pit8253_set_clock_signal(device, 2, state); }
+
+
+static void common_start( device_t *device, int device_type ) {
+ pit8253_t *pit8253 = get_safe_token(device);
+ int timerno;
+
+ pit8253->config = (const struct pit8253_config *)device->static_config();
+ pit8253->device_type = device_type;
+
+ /* register for state saving */
+ for (timerno = 0; timerno < MAX_TIMER; timerno++)
+ {
+ struct pit8253_timer *timer = get_timer(pit8253, timerno);
+
+ /* initialize timer */
+ timer->clockin = pit8253->config->timer[timerno].clockin;
+ timer->updatetimer = device->machine().scheduler().timer_alloc(FUNC(update_timer_cb), (void *)device);
+ timer->updatetimer->adjust(attotime::never, timerno);
+
+ /* resolve callbacks */
+ timer->in_gate_func.resolve(pit8253->config->timer[timerno].in_gate_func, *device);
+ timer->out_out_func.resolve(pit8253->config->timer[timerno].out_out_func, *device);
+
+ /* set up state save values */
+ device->save_item(NAME(timer->clockin), timerno);
+ device->save_item(NAME(timer->control), timerno);
+ device->save_item(NAME(timer->status), timerno);
+ device->save_item(NAME(timer->lowcount), timerno);
+ device->save_item(NAME(timer->latch), timerno);
+ device->save_item(NAME(timer->count), timerno);
+ device->save_item(NAME(timer->value), timerno);
+ device->save_item(NAME(timer->wmsb), timerno);
+ device->save_item(NAME(timer->rmsb), timerno);
+ device->save_item(NAME(timer->output), timerno);
+ device->save_item(NAME(timer->gate), timerno);
+ device->save_item(NAME(timer->latched_count), timerno);
+ device->save_item(NAME(timer->latched_status), timerno);
+ device->save_item(NAME(timer->null_count), timerno);
+ device->save_item(NAME(timer->phase), timerno);
+ device->save_item(NAME(timer->cycles_to_output), timerno);
+ device->save_item(NAME(timer->last_updated), timerno);
+ device->save_item(NAME(timer->clock), timerno);
+ }
+}
+
+
+static DEVICE_START( pit8253 ) {
+ common_start( device, TYPE_PIT8253 );
+}
+
+
+static DEVICE_START( pit8254 ) {
+ common_start( device, TYPE_PIT8254 );
+}
+
+
+static DEVICE_RESET( pit8253 ) {
+ pit8253_t *pit = get_safe_token(device);
+ int i;
+
+ for (i = 0; i < MAX_TIMER; i++)
+ {
+ struct pit8253_timer *timer = get_timer(pit,i);
+ /* According to Intel's 8254 docs, the state of a timer is undefined
+ until the first mode control word is written. Here we define this
+ undefined behaviour */
+ timer->index = i;
+ timer->control = timer->status = 0x30;
+ timer->rmsb = timer->wmsb = 0;
+ timer->count = timer->value = timer->latch = 0;
+ timer->lowcount = 0;
+
+ if (!timer->in_gate_func.isnull())
+ timer->gate = timer->in_gate_func();
+ else
+ timer->gate = 1;
+
+ timer->output = 2; /* output is undetermined */
+ timer->latched_count = 0;
+ timer->latched_status = 0;
+ timer->null_count = 1;
+ timer->cycles_to_output = CYCLES_NEVER;
+
+ timer->last_updated = device->machine().time();
+
+ update(device, timer);
+ }
+}
+
+
+DEVICE_GET_INFO( pit8253 ) {
+ switch ( state ) {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(pit8253_t); break;
+ case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(pit8253); break;
+ case DEVINFO_FCT_STOP: /* nothing */ break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(pit8253); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Intel PIT8253"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "PIT8253"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.00"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright the MAME and MESS Teams"); break;
+ }
+}
+
+
+DEVICE_GET_INFO( pit8254 ) {
+ switch ( state ) {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Intel PIT8254"); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(pit8254); break;
+
+ default: DEVICE_GET_INFO_CALL(pit8253); break;
+ }
+}
+
+
+DEFINE_LEGACY_DEVICE(PIT8253, pit8253);
+DEFINE_LEGACY_DEVICE(PIT8254, pit8254);
diff --git a/trunk/src/emu/machine/pit8253.h b/trunk/src/emu/machine/pit8253.h
new file mode 100644
index 00000000000..32e05f62498
--- /dev/null
+++ b/trunk/src/emu/machine/pit8253.h
@@ -0,0 +1,83 @@
+/***************************************************************************
+
+ Intel 8253/8254
+
+ Programmable Interval Timer
+
+ _____ _____
+ D7 1 |* \_/ | 24 VCC
+ D6 2 | | 23 _WR
+ D5 3 | | 22 _RD
+ D4 4 | | 21 _CS
+ D3 5 | | 20 A1
+ D2 6 | 8253 | 19 A0
+ D1 7 | | 18 CLK2
+ D0 8 | | 17 OUT2
+ CLK0 9 | | 16 GATE2
+ OUT0 10 | | 15 CLK1
+ GATE0 11 | | 14 GATE1
+ GND 12 |_____________| 13 OUT1
+
+***************************************************************************/
+
+#ifndef __PIT8253_H__
+#define __PIT8253_H__
+
+#include "devlegcy.h"
+#include "devcb.h"
+
+
+struct pit8253_config
+{
+ struct
+ {
+ double clockin; /* timer clock */
+ devcb_read_line in_gate_func; /* gate signal */
+ devcb_write_line out_out_func; /* out signal */
+ } timer[3];
+};
+
+DECLARE_LEGACY_DEVICE(PIT8253, pit8253);
+DECLARE_LEGACY_DEVICE(PIT8254, pit8254);
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_PIT8253_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, PIT8253, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+
+#define MCFG_PIT8254_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, PIT8254, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+
+READ8_DEVICE_HANDLER( pit8253_r );
+WRITE8_DEVICE_HANDLER( pit8253_w );
+
+WRITE_LINE_DEVICE_HANDLER( pit8253_clk0_w );
+WRITE_LINE_DEVICE_HANDLER( pit8253_clk1_w );
+WRITE_LINE_DEVICE_HANDLER( pit8253_clk2_w );
+
+WRITE_LINE_DEVICE_HANDLER( pit8253_gate0_w );
+WRITE_LINE_DEVICE_HANDLER( pit8253_gate1_w );
+WRITE_LINE_DEVICE_HANDLER( pit8253_gate2_w );
+
+/* In the 8253/8254 the CLKx input lines can be attached to a regular clock
+ signal. Another option is to use the output from one timer as the input
+ clock to another timer.
+
+ The functions below should supply both functionalities. If the signal is
+ a regular clock signal, use the pit8253_set_clockin function. If the
+ CLKx input signal is the output of the different source, set the new_clockin
+ to 0 with pit8253_set_clockin and call pit8253_clkX_w to change
+ the state of the input CLKx signal.
+ */
+int pit8253_get_output(device_t *device, int timer);
+void pit8253_set_clockin(device_t *device, int timer, double new_clockin);
+
+
+#endif /* __PIT8253_H__ */
diff --git a/trunk/src/emu/machine/ram.c b/trunk/src/emu/machine/ram.c
new file mode 100644
index 00000000000..7e7aa69196c
--- /dev/null
+++ b/trunk/src/emu/machine/ram.c
@@ -0,0 +1,268 @@
+/*************************************************************************
+
+ RAM device
+
+ Provides a configurable amount of RAM to drivers
+
+**************************************************************************/
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include "emu.h"
+#include "emuopts.h"
+#include "ram.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define RAM_STRING_BUFLEN 16
+#define MAX_RAM_OPTIONS 16
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _ram_state ram_state;
+struct _ram_state
+{
+ UINT32 size; /* total amount of ram configured */
+ UINT8 *ram; /* pointer to the start of ram */
+};
+
+
+/*****************************************************************************
+ INLINE FUNCTIONS
+*****************************************************************************/
+
+INLINE ram_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == RAM);
+
+ return (ram_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+/*****************************************************************************
+ HELPER FUNCTIONS
+*****************************************************************************/
+
+/*-------------------------------------------------
+ ram_parse_string - convert a ram string to an
+ integer value
+-------------------------------------------------*/
+
+UINT32 ram_parse_string(const char *s)
+{
+ UINT32 ram;
+ char suffix = '\0';
+
+ s += sscanf(s, "%u%c", &ram, &suffix);
+
+ switch(tolower(suffix))
+ {
+ case 'k':
+ /* kilobytes */
+ ram *= 1024;
+ break;
+
+ case 'm':
+ /* megabytes */
+ ram *= 1024*1024;
+ break;
+
+ case '\0':
+ /* no suffix */
+ break;
+
+ default:
+ /* parse failure */
+ ram = 0;
+ break;
+ }
+
+ return ram;
+}
+
+/*****************************************************************************
+ DEVICE INTERFACE
+*****************************************************************************/
+
+static DEVICE_START( ram )
+{
+ ram_state *ram = get_safe_token(device);
+ ram_config *config = (ram_config *)downcast<const legacy_device_base *>(device)->inline_config();
+
+ /* the device named 'ram' can get ram options from command line */
+ if (strcmp(device->tag(), RAM_TAG) == 0)
+ {
+ const char *ramsize_string = device->machine().options().ram_size();
+
+ if ((ramsize_string != NULL) && (ramsize_string[0] != '\0'))
+ ram->size = ram_parse_string(ramsize_string);
+ }
+
+ /* if we didn't get a size yet, use the default */
+ if (ram->size == 0)
+ ram->size = ram_parse_string(config->default_size);
+
+ /* allocate space for the ram */
+ ram->ram = auto_alloc_array(device->machine(), UINT8, ram->size);
+
+ /* reset ram to the default value */
+ memset(ram->ram, config->default_value, ram->size);
+
+ /* register for state saving */
+ device->save_item(NAME(ram->size));
+ device->save_pointer(NAME(ram->ram), ram->size);
+}
+
+static DEVICE_VALIDITY_CHECK( ram )
+{
+ ram_config *config = (ram_config *)downcast<const legacy_device_base *>(device)->inline_config();
+ const char *ramsize_string = NULL;
+ int is_valid = FALSE;
+ UINT32 specified_ram = 0;
+ int error = FALSE;
+ const char *gamename_option = NULL;
+
+ /* verify default ram value */
+ if (config!=NULL && ram_parse_string(config->default_size) == 0)
+ {
+ mame_printf_error("%s: '%s' has an invalid default RAM option: %s\n", driver->source_file, driver->name, config->default_size);
+ error = TRUE;
+ }
+
+ /* command line options are only parsed for the device named RAM_TAG */
+ if (device->tag()!=NULL && strcmp(device->tag(), RAM_TAG) == 0)
+ {
+ /* verify command line ram option */
+ ramsize_string = options.ram_size();
+ gamename_option = options.system_name();
+
+ if ((ramsize_string != NULL) && (ramsize_string[0] != '\0'))
+ {
+ specified_ram = ram_parse_string(ramsize_string);
+
+ if (specified_ram == 0)
+ {
+ mame_printf_error("%s: '%s' cannot recognize the RAM option %s\n", driver->source_file, driver->name, ramsize_string);
+ error = TRUE;
+ }
+ if (gamename_option != NULL && *gamename_option != 0 && strcmp(gamename_option, driver->name) == 0)
+ {
+ /* compare command line option to default value */
+ if (ram_parse_string(config->default_size) == specified_ram)
+ is_valid = TRUE;
+
+ /* verify extra ram options */
+ if (config->extra_options != NULL)
+ {
+ int j;
+ int size = strlen(config->extra_options);
+ char * const s = mame_strdup(config->extra_options);
+ char * const e = s + size;
+ char *p = s;
+ for (j=0;j<size;j++) {
+ if (p[j]==',') p[j]=0;
+ }
+
+ /* try to parse each option */
+ while(p <= e)
+ {
+ UINT32 option_ram_size = ram_parse_string(p);
+
+ if (option_ram_size == 0)
+ {
+ mame_printf_error("%s: '%s' has an invalid RAM option: %s\n", driver->source_file, driver->name, p);
+ error = TRUE;
+ }
+
+ if (option_ram_size == specified_ram)
+ is_valid = TRUE;
+
+ p += strlen(p);
+ if (p == e)
+ break;
+ p += 1;
+ }
+
+ osd_free(s);
+ }
+
+ } else {
+ /* if not for this driver then return ok */
+ is_valid = TRUE;
+ }
+ }
+ else
+ {
+ /* not specifying the ramsize on the command line is valid as well */
+ is_valid = TRUE;
+ }
+ }
+ else
+ is_valid = TRUE;
+
+ if (!is_valid)
+ {
+ mame_printf_error("%s: '%s' cannot recognize the RAM option %s", driver->source_file, driver->name, ramsize_string);
+ mame_printf_error(" (valid options are %s", config->default_size);
+
+ if (config->extra_options != NULL)
+ mame_printf_error(",%s).\n", config->extra_options);
+ else
+ mame_printf_error(").\n");
+
+ error = TRUE;
+ }
+
+ return error;
+
+}
+
+
+DEVICE_GET_INFO( ram )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(ram_state); break;
+ case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = sizeof(ram_config); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(ram); break;
+ case DEVINFO_FCT_STOP: /* Nothing */ break;
+ case DEVINFO_FCT_RESET: /* Nothing */ break;
+ case DEVINFO_FCT_VALIDITY_CHECK: info->p = (void*)DEVICE_VALIDITY_CHECK_NAME(ram); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "RAM"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "RAM"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.00"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright MESS Team"); break;
+ }
+}
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+UINT32 ram_get_size(device_t *device)
+{
+ ram_state *ram = get_safe_token(device);
+ return ram->size;
+}
+
+UINT8 *ram_get_ptr(device_t *device)
+{
+ ram_state *ram = get_safe_token(device);
+ return ram->ram;
+}
+
+DEFINE_LEGACY_DEVICE(RAM, ram);
diff --git a/trunk/src/emu/machine/ram.h b/trunk/src/emu/machine/ram.h
new file mode 100644
index 00000000000..ea7bc50a5b0
--- /dev/null
+++ b/trunk/src/emu/machine/ram.h
@@ -0,0 +1,68 @@
+/*************************************************************************
+
+ RAM device
+
+ Provides a configurable amount of RAM to drivers
+
+**************************************************************************/
+
+#ifndef __RAM_H__
+#define __RAM_H__
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define RAM_DEFAULT_VALUE 0xcd
+#define RAM_TAG "ram"
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _ram_config ram_config;
+struct _ram_config
+{
+ const char *default_size;
+ const char *extra_options;
+ UINT8 default_value;
+};
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+DECLARE_LEGACY_DEVICE(RAM, ram);
+
+#define MCFG_RAM_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, RAM, 0) \
+ MCFG_DEVICE_CONFIG_DATA32(ram_config, default_value, RAM_DEFAULT_VALUE)
+
+#define MCFG_RAM_REMOVE(_tag) \
+ MCFG_DEVICE_REMOVE(_tag)
+
+#define MCFG_RAM_MODIFY(_tag) \
+ MCFG_DEVICE_MODIFY(_tag) \
+ MCFG_DEVICE_CONFIG_DATAPTR(ram_config, extra_options, NULL)
+
+#define MCFG_RAM_DEFAULT_SIZE(_default_size) \
+ MCFG_DEVICE_CONFIG_DATAPTR(ram_config, default_size, _default_size)
+
+#define MCFG_RAM_EXTRA_OPTIONS(_extra_options) \
+ MCFG_DEVICE_CONFIG_DATAPTR(ram_config, extra_options, _extra_options)
+
+#define MCFG_RAM_DEFAULT_VALUE(_default_value) \
+ MCFG_DEVICE_CONFIG_DATA32(ram_config, default_value, _default_value)
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+UINT32 ram_get_size(device_t *device);
+UINT8 *ram_get_ptr(device_t *device);
+UINT32 ram_parse_string(const char *s);
+
+#endif /* __RAM_H__ */
diff --git a/trunk/src/emu/machine/rescap.h b/trunk/src/emu/machine/rescap.h
new file mode 100644
index 00000000000..afac4713f8c
--- /dev/null
+++ b/trunk/src/emu/machine/rescap.h
@@ -0,0 +1,23 @@
+#ifndef RC_MACROS_H
+#define RC_MACROS_H
+
+/* Little helpers for magnitude conversions */
+#define RES_R(res) ((double)(res))
+#define RES_K(res) ((double)(res) * 1e3)
+#define RES_M(res) ((double)(res) * 1e6)
+#define CAP_U(cap) ((double)(cap) * 1e-6)
+#define CAP_N(cap) ((double)(cap) * 1e-9)
+#define CAP_P(cap) ((double)(cap) * 1e-12)
+
+/* vin --/\r1/\-- out --/\r2/\-- gnd */
+#define RES_VOLTAGE_DIVIDER(r1, r2) ((double)(r2) / ((double)(r1) + (double)(r2)))
+
+#define RES_2_PARALLEL(r1, r2) (((r1) * (r2)) / ((r1) + (r2)))
+#define RES_3_PARALLEL(r1, r2, r3) (1.0 / (1.0 / (r1) + 1.0 / (r2) + 1.0 / (r3)))
+#define RES_4_PARALLEL(r1, r2, r3, r4) (1.0 / (1.0 / (r1) + 1.0 / (r2) + 1.0 / (r3) + 1.0 / (r4)))
+#define RES_5_PARALLEL(r1, r2, r3, r4, r5) (1.0 / (1.0 / (r1) + 1.0 / (r2) + 1.0 / (r3) + 1.0 / (r4) + 1.0 / (r5)))
+#define RES_6_PARALLEL(r1, r2, r3, r4, r5, r6) (1.0 / (1.0 / (r1) + 1.0 / (r2) + 1.0 / (r3) + 1.0 / (r4) + 1.0 / (r5) + 1.0 / (r6)))
+
+#define RES_2_SERIAL(r1,r2) ((r1)+(r2))
+
+#endif
diff --git a/trunk/src/emu/machine/roc10937.c b/trunk/src/emu/machine/roc10937.c
new file mode 100644
index 00000000000..5e1abcf6583
--- /dev/null
+++ b/trunk/src/emu/machine/roc10937.c
@@ -0,0 +1,398 @@
+/**********************************************************************
+
+ Rockwell 10937/10957 interface and emulation by J.Wallace
+ OKI MSC1937 is a clone of this chip
+
+**********************************************************************/
+
+#include "emu.h"
+#include "roc10937.h"
+
+static struct
+{
+ UINT8 type, // type of alpha display
+
+ reversed, // Allows for the data being written from right to left, not left to right.
+
+ changed, // flag <>0, if contents are changed
+ window_start, // display window start pos 0-15
+ window_end, // display window end pos 0-15
+ window_size; // window size
+
+ INT8 pcursor_pos, // previous cursor pos
+ cursor_pos; // current cursor pos
+
+ UINT16 brightness; // display brightness level 0-31 (31=MAX)
+
+ UINT8 string[18]; // text buffer
+ UINT32 segments[16], // segments
+ outputs[16]; // standardised outputs
+
+ UINT8 count, // bit counter
+ data; // receive register
+
+} roc10937[MAX_ROCK_ALPHAS];
+
+//
+// Rockwell 10937 charset to ASCII conversion table
+//
+static const char roc10937ASCII[]=
+//0123456789ABCDEF0123456789ABC DEF01 23456789ABCDEF0123456789ABCDEF
+ "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ ?\"#$%%'()*+;-./0123456789&%<=>?"
+ "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ ?\"#$%%'()*+;-./0123456789&%<=>?"
+ "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ ?\"#$%%'()*+;-./0123456789&%<=>?";
+
+/*
+ Rockwell 10937 16 segment charset lookup table
+ 0 1
+ ---- ----
+ |\ | /|
+ 7 | \F |8 /9| 2
+ | \ | / |
+ -E-- --A-
+ | / | \ |
+ 6 | /D |C \B| 3
+ |/ | \|
+ ---- ---- .11
+ 5 4 ,10
+
+In 14 segment mode, 0 represents the whole top line,
+and 5 the bottom line, allowing both modes to share
+a charset.
+
+Note that, although we call this a 16 segment display,
+we actually have 18 segments, including the semicolon portions.
+This means our segment maths needs to be more than 16-bit to work!
+*/
+
+static const UINT32 roc10937charset[]=
+{ // 11 10 FEDC BA98 7654 3210
+ 0x0507F, // 0 0 0101 0000 0111 1111 @.
+ 0x044CF, // 0 0 0100 0100 1100 1111 A.
+ 0x0153F, // 0 0 0001 0101 0011 1111 B.
+ 0x000F3, // 0 0 0000 0000 1111 0011 C.
+ 0x0113F, // 0 0 0001 0001 0011 1111 D.
+ 0x040F3, // 0 0 0100 0000 1111 0011 E.
+ 0x040C3, // 0 0 0100 0000 1100 0011 F.
+ 0x004FB, // 0 0 0000 0100 1111 1011 G.
+ 0x044CC, // 0 0 0100 0100 1100 1100 H.
+ 0x01133, // 0 0 0001 0001 0011 0011 I.
+ 0x0007C, // 0 0 0000 0000 0111 1100 J.
+ 0x04AC0, // 0 0 0100 1010 1100 0000 K.
+ 0x000F0, // 0 0 0000 0000 1111 0000 L.
+ 0x082CC, // 0 0 1000 0010 1100 1100 M.
+ 0x088CC, // 0 0 1000 1000 1100 1100 N.
+ 0x000FF, // 0 0 0000 0000 1111 1111 O.
+ 0x044C7, // 0 0 0100 0100 1100 0111 P.
+ 0x008FF, // 0 0 0000 1000 1111 1111 Q.
+ 0x04CC7, // 0 0 0100 1100 1100 0111 R.
+ 0x044BB, // 0 0 0100 0100 1011 1011 S.
+ 0x01103, // 0 0 0001 0001 0000 0011 T.
+ 0x000FC, // 0 0 0000 0000 1111 1100 U.
+ 0x022C0, // 0 0 0010 0010 1100 0000 V.
+ 0x028CC, // 0 0 0010 1000 1100 1100 W.
+ 0x0AA00, // 0 0 1010 1010 0000 0000 X.
+ 0x09200, // 0 0 1001 0010 0000 0000 Y.
+ 0x02233, // 0 0 0010 0010 0011 0011 Z.
+ 0x000E1, // 0 0 0000 0000 1110 0001 [.
+ 0x08800, // 0 0 1000 1000 0000 0000 \.
+ 0x0001E, // 0 0 0000 0000 0001 1110 ].
+ 0x02800, // 0 0 0010 1000 0000 0000 ^.
+ 0x00030, // 0 0 0000 0000 0011 0000 _.
+ 0x00000, // 0 0 0000 0000 0000 0000 dummy.
+ 0x08121, // 0 0 1000 0001 0010 0001 Unknown symbol.
+ 0x00180, // 0 0 0000 0001 1000 0000 ".
+ 0x0553C, // 0 0 0101 0101 0011 1100 #.
+ 0x055BB, // 0 0 0101 0101 1011 1011 $.
+ 0x07799, // 0 0 0111 0111 1001 1001 %.
+ 0x0C979, // 0 0 1100 1001 0111 1001 &.
+ 0x00200, // 0 0 0000 0010 0000 0000 '.
+ 0x00A00, // 0 0 0000 1010 0000 0000 (.
+ 0x0A050, // 0 0 1010 0000 0000 0000 ).
+ 0x0FF00, // 0 0 1111 1111 0000 0000 *.
+ 0x05500, // 0 0 0101 0101 0000 0000 +.
+ 0x30000, // 1 1 0000 0000 0000 0000 ;.
+ 0x04400, // 0 0 0100 0100 0000 0000 --.
+ 0x20000, // 1 0 0000 0000 0000 0000 . .
+ 0x02200, // 0 0 0010 0010 0000 0000 /.
+ 0x022FF, // 0 0 0010 0010 1111 1111 0.
+ 0x01100, // 0 0 0001 0001 0000 0000 1.
+ 0x04477, // 0 0 0100 0100 0111 0111 2.
+ 0x0443F, // 0 0 0100 0100 0011 1111 3.
+ 0x0448C, // 0 0 0100 0100 1000 1100 4.
+ 0x044BB, // 0 0 0100 0100 1011 1011 5.
+ 0x044FB, // 0 0 0100 0100 1111 1011 6.
+ 0x0000E, // 0 0 0000 0000 0000 1110 7.
+ 0x044FF, // 0 0 0100 0100 1111 1111 8.
+ 0x044BF, // 0 0 0100 0100 1011 1111 9.
+ 0x00021, // 0 0 0000 0000 0010 0001 -
+ // -.
+ 0x02001, // 0 0 0010 0000 0000 0001 -
+ // /.
+ 0x02430, // 0 0 0010 0100 0011 0000 <.
+ 0x04430, // 0 0 0100 0100 0011 0000 =.
+ 0x08830, // 0 0 1000 1000 0011 0000 >.
+ 0x01407, // 0 0 0001 0100 0000 0111 ?.
+};
+
+static const int roc10937poslut[]=
+{
+ 1,//0
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11,
+ 12,
+ 13,
+ 14,
+ 15,
+ 0//15
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+void ROC10937_init(int id, int type,int reversed)
+{
+ assert_always((id >= 0) && (id < MAX_ROCK_ALPHAS), "roc10937_init called on an invalid display ID!");
+
+ memset( &roc10937[id], 0, sizeof(roc10937[0]));
+
+ roc10937[id].type = type;
+ roc10937[id].reversed = reversed;
+ ROC10937_reset(id);
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+void ROC10937_reset(int id)
+{
+ roc10937[id].window_end = 15;
+ roc10937[id].window_size = (roc10937[id].window_end - roc10937[id].window_start)+1;
+ memset(roc10937[id].string, ' ', 16);
+
+ roc10937[id].brightness = 31;
+ roc10937[id].count = 0;
+
+ roc10937[id].changed |= 1;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+UINT32 *ROC10937_get_segments(int id)
+{
+ return roc10937[id].segments;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+UINT32 *ROC10937_get_outputs(int id)
+{
+ return roc10937[id].outputs;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+UINT32 *ROC10937_set_outputs(int id)
+{
+ int cursor,val;
+ for (cursor = 0; cursor < 16; cursor++)
+ {
+ if (!roc10937[id].reversed)//Output to the screen is naturally backwards, so we need to invert it
+ {
+ val = 15-cursor;
+ }
+ else
+ {
+ //If the controller is reversed, things look normal.
+ val = cursor;
+ }
+
+ if ( ROC10937_get_segments(id)[val] & 0x0001 ) roc10937[id].outputs[cursor] |= 0x0001;
+ else roc10937[id].outputs[cursor] &= ~0x0001;
+ if ( ROC10937_get_segments(id)[val] & 0x0002 ) roc10937[id].outputs[cursor] |= 0x0002;
+ else roc10937[id].outputs[cursor] &= ~0x0002;
+ if ( ROC10937_get_segments(id)[val] & 0x0004 ) roc10937[id].outputs[cursor] |= 0x0004;
+ else roc10937[id].outputs[cursor] &= ~0x0004;
+ if ( ROC10937_get_segments(id)[val] & 0x0008 ) roc10937[id].outputs[cursor] |= 0x0008;
+ else roc10937[id].outputs[cursor] &= ~0x0008;
+ if ( ROC10937_get_segments(id)[val] & 0x0010 ) roc10937[id].outputs[cursor] |= 0x0010;
+ else roc10937[id].outputs[cursor] &= ~0x0010;
+ if ( ROC10937_get_segments(id)[val] & 0x0020 ) roc10937[id].outputs[cursor] |= 0x0020;
+ else roc10937[id].outputs[cursor] &= ~0x0020;
+ if ( ROC10937_get_segments(id)[val] & 0x0040 ) roc10937[id].outputs[cursor] |= 0x0040;
+ else roc10937[id].outputs[cursor] &= ~0x0040;
+ if ( ROC10937_get_segments(id)[val] & 0x0080 ) roc10937[id].outputs[cursor] |= 0x0080;
+ else roc10937[id].outputs[cursor] &= ~0x0080;
+ if ( ROC10937_get_segments(id)[val] & 0x4000 ) roc10937[id].outputs[cursor] |= 0x0100;
+ else roc10937[id].outputs[cursor] &= ~0x0100;
+ if ( ROC10937_get_segments(id)[val] & 0x0400 ) roc10937[id].outputs[cursor] |= 0x0200;
+ else roc10937[id].outputs[cursor] &= ~0x0200;
+ if ( ROC10937_get_segments(id)[val] & 0x0100 ) roc10937[id].outputs[cursor] |= 0x0400;
+ else roc10937[id].outputs[cursor] &= ~0x0400;
+ if ( ROC10937_get_segments(id)[val] & 0x1000 ) roc10937[id].outputs[cursor] |= 0x0800;
+ else roc10937[id].outputs[cursor] &= ~0x0800;
+ if ( ROC10937_get_segments(id)[val] & 0x2000 ) roc10937[id].outputs[cursor] |= 0x1000;
+ else roc10937[id].outputs[cursor] &= ~0x1000;
+ if ( ROC10937_get_segments(id)[val] & 0x8000 ) roc10937[id].outputs[cursor] |= 0x2000;
+ else roc10937[id].outputs[cursor] &= ~0x2000;
+ if ( ROC10937_get_segments(id)[val] & 0x0200 ) roc10937[id].outputs[cursor] |= 0x4000;
+ else roc10937[id].outputs[cursor] &= ~0x4000;
+ if ( ROC10937_get_segments(id)[val] & 0x0800 ) roc10937[id].outputs[cursor] |= 0x8000;
+ else roc10937[id].outputs[cursor] &= ~0x8000;
+
+ if ( ROC10937_get_segments(id)[val] & 0x10000 ) roc10937[id].outputs[cursor] |= 0x10000;
+ else roc10937[id].outputs[cursor] &= ~0x10000;
+ if ( ROC10937_get_segments(id)[val] & 0x20000 ) roc10937[id].outputs[cursor] |= 0x20000;
+ else roc10937[id].outputs[cursor] &= ~0x20000;
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+char *ROC10937_get_string( int id)
+{
+ return (char *)roc10937[id].string;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+void ROC10937_shift_data(int id, int data)
+{
+ roc10937[id].data <<= 1;
+
+ if ( !data ) roc10937[id].data |= 1;
+
+ if ( ++roc10937[id].count >= 8 )
+ {
+ if ( ROC10937_newdata(id, roc10937[id].data) )
+ {
+ roc10937[id].changed |= 1;
+ }
+
+ roc10937[id].count = 0;
+ roc10937[id].data = 0;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+int ROC10937_newdata(int id, int data)
+{
+ int change = 0;
+
+ if ( data & 0x80 )
+ { // Control data received
+ if ( (data & 0xF0) == 0xA0 ) // 1010 xxxx
+ { // 1 010 xxxx Buffer Pointer control
+ roc10937[id].cursor_pos = roc10937poslut[data & 0x0F];
+ }
+ else if ( (data & 0xF0) == 0xC0 ) // 1100 xxxx
+ { // 1100 xxxx Set number of digits
+ data &= 0x0F;
+
+ if ( data == 0 ) roc10937[id].window_size = 16;
+ else roc10937[id].window_size = data;
+ roc10937[id].window_start = 0;
+ roc10937[id].window_end = roc10937[id].window_size-1;
+ }
+ else if ( (data & 0xE0) == 0xE0 ) // 111x xxxx
+ { // 111x xxxx Set duty cycle ( brightness )
+ roc10937[id].brightness = (data & 0x1F);
+ change = 1;
+ }
+ else if ( (data & 0xE0) == 0x80 ) // 100x ---
+ { // 100x xxxx Test mode
+ }
+ }
+ else
+ { // Display data
+ data &= 0x3F;
+ change = 1;
+
+ switch ( data )
+ {
+ case 0x2C: // ;
+ roc10937[id].segments[roc10937[id].pcursor_pos] |= (1<<16);//.
+ roc10937[id].segments[roc10937[id].pcursor_pos] |= (1<<17);//,
+ break;
+ case 0x2E: //
+ roc10937[id].segments[roc10937[id].pcursor_pos] |= (1<<16);//.
+ break;
+ case 0x6C: // ;
+ roc10937[id].segments[roc10937[id].pcursor_pos] |= (1<<16);//.
+ if ( roc10937[id].type == ROCKWELL10937)
+ {
+ roc10937[id].segments[roc10937[id].pcursor_pos] |= (1<<17);//,
+ }
+ break;
+ case 0x6E: //
+ if ( roc10937[id].type == ROCKWELL10937)
+ {
+ roc10937[id].segments[roc10937[id].pcursor_pos] |= (1<<16);//.
+ }
+ else
+ {
+ roc10937[id].segments[roc10937[id].pcursor_pos] |= (1<<17);//,
+ }
+ break;
+ default :
+ roc10937[id].pcursor_pos = roc10937[id].cursor_pos;
+ roc10937[id].string[ roc10937[id].cursor_pos ] = roc10937ASCII[data];
+ roc10937[id].segments[roc10937[id].cursor_pos] = roc10937charset[data & 0x3F];
+
+ roc10937[id].cursor_pos++;
+ if ( roc10937[id].cursor_pos > roc10937[id].window_end )
+ {
+ roc10937[id].cursor_pos = 0;
+ }
+ break;
+ }
+
+ }
+ return change;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+static void ROC10937_plot(int id, int power)
+{
+ int cursor;
+ ROC10937_set_outputs(id);
+
+ for (cursor = 0; cursor < 16; cursor++)
+ {
+ output_set_indexed_value("vfd", (id*16)+cursor, power?ROC10937_get_outputs(id)[cursor]:0x00000);
+ }
+}
+static void ROC10937_draw(int id, int segs)
+{
+ int cycle;
+ for (cycle = 0; cycle < 32; cycle++)
+ {
+ if ((roc10937[id].brightness < cycle)||(roc10937[id].brightness == cycle))
+ {
+ ROC10937_plot(id,1);
+ }
+ else
+ {
+ ROC10937_plot(id,0);
+ }
+ }
+}
+
+//Helper functions
+void ROC10937_draw_16seg(int id)
+{
+ ROC10937_draw(id,16);
+}
+void ROC10937_draw_14seg(int id)
+{
+ ROC10937_draw(id,14);
+}
diff --git a/trunk/src/emu/machine/roc10937.h b/trunk/src/emu/machine/roc10937.h
new file mode 100644
index 00000000000..75e092e90e9
--- /dev/null
+++ b/trunk/src/emu/machine/roc10937.h
@@ -0,0 +1,34 @@
+/**********************************************************************
+
+ Rockwell 10937/10957 interface and emulation by J.Wallace
+ OKI MSC1937 is a clone of this chip
+
+**********************************************************************/
+
+#ifndef ROC10937
+#define ROC10937
+
+#define MAX_ROCK_ALPHAS 3 // max number of displays emulated
+
+#define ROCKWELL10937 0 // Rockwell 10937
+#define MSC1937 0 // OKI MSC1937 clone of Rockwell 10937
+#define ROCKWELL10957 1 // Rockwell 10957
+
+void ROC10937_init( int id, int type,int reversed ); // setup a display
+
+void ROC10937_reset( int id); // reset the alpha
+
+void ROC10937_shift_data(int id, int data); // clock in a bit of data
+
+int ROC10937_newdata( int id, int data); // clock in 8 bits of data
+
+UINT32 *ROC10937_get_segments(int id); // get current segments displayed
+UINT32 *ROC10937_set_outputs(int id); // convert segments to standard for display
+UINT32 *ROC10937_get_outputs(int id); // get converted segments
+
+char *ROC10937_get_string( int id); // get current string displayed (not as accurate)
+
+void ROC10937_draw_16seg(int id);
+void ROC10937_draw_14seg(int id);
+#endif
+
diff --git a/trunk/src/emu/machine/rp5c01.c b/trunk/src/emu/machine/rp5c01.c
new file mode 100644
index 00000000000..3473e0d398f
--- /dev/null
+++ b/trunk/src/emu/machine/rp5c01.c
@@ -0,0 +1,527 @@
+/**********************************************************************
+
+ Ricoh RP5C01(A) Real Time Clock With Internal RAM emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+/*
+
+ TODO:
+
+ - 12 hour clock
+ - test register
+ - timer reset
+
+*/
+
+#include "rp5c01.h"
+
+
+// device type definition
+const device_type RP5C01 = &device_creator<rp5c01_device>;
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+
+#define RAM_SIZE 13
+
+
+// registers
+enum
+{
+ REGISTER_1_SECOND = 0,
+ REGISTER_10_SECOND,
+ REGISTER_1_MINUTE,
+ REGISTER_10_MINUTE,
+ REGISTER_1_HOUR,
+ REGISTER_10_HOUR,
+ REGISTER_DAY_OF_THE_WEEK,
+ REGISTER_1_DAY,
+ REGISTER_10_DAY,
+ REGISTER_1_MONTH,
+ REGISTER_10_MONTH, REGISTER_12_24_SELECT = REGISTER_10_MONTH,
+ REGISTER_1_YEAR, REGISTER_LEAP_YEAR = REGISTER_1_YEAR,
+ REGISTER_10_YEAR,
+ REGISTER_MODE,
+ REGISTER_TEST,
+ REGISTER_RESET
+};
+
+
+// register write mask
+static const int REGISTER_WRITE_MASK[2][16] =
+{
+ { 0xf, 0x7, 0xf, 0x7, 0xf, 0x3, 0x7, 0xf, 0x3, 0xf, 0x1, 0xf, 0xf, 0xf, 0xf, 0xf },
+ { 0x0, 0x0, 0xf, 0x7, 0xf, 0x3, 0x7, 0xf, 0x3, 0x0, 0x1, 0x3, 0x0, 0xf, 0xf, 0xf }
+};
+
+
+// days per month
+static const int DAYS_PER_MONTH[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+
+// modes
+enum
+{
+ MODE00 = 0,
+ MODE01,
+ BLOCK10,
+ BLOCK11
+};
+
+
+// mode register
+#define MODE_MASK 0x03
+#define MODE_ALARM_EN 0x04
+#define MODE_TIMER_EN 0x08
+
+
+// test register
+#define TEST_0 0x01
+#define TEST_1 0x02
+#define TEST_2 0x04
+#define TEST_3 0x08
+
+
+// reset register
+#define RESET_ALARM 0x01
+#define RESET_TIMER 0x02
+#define RESET_16_HZ 0x04
+#define RESET_1_HZ 0x08
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// set_alarm_line -
+//-------------------------------------------------
+
+inline void rp5c01_device::set_alarm_line()
+{
+ int alarm = ((m_mode & MODE_ALARM_EN) ? m_alarm_on : 1) &
+ ((m_reset & RESET_16_HZ) ? 1 : m_16hz) &
+ ((m_reset & RESET_1_HZ) ? 1 : m_1hz);
+
+ if (m_alarm != alarm)
+ {
+ if (LOG) logerror("RP5C01 '%s' Alarm %u\n", tag(), alarm);
+
+ m_out_alarm_func(alarm);
+ m_alarm = alarm;
+ }
+}
+
+
+//-------------------------------------------------
+// read_counter -
+//-------------------------------------------------
+
+inline int rp5c01_device::read_counter(int counter)
+{
+ return (m_reg[MODE00][counter + 1] * 10) + m_reg[MODE00][counter];
+}
+
+
+//-------------------------------------------------
+// write_counter -
+//-------------------------------------------------
+
+inline void rp5c01_device::write_counter(int counter, int value)
+{
+ m_reg[MODE00][counter] = value % 10;
+ m_reg[MODE00][counter + 1] = value / 10;
+}
+
+
+//-------------------------------------------------
+// advance_seconds -
+//-------------------------------------------------
+
+inline void rp5c01_device::advance_seconds()
+{
+ int seconds = read_counter(REGISTER_1_SECOND);
+
+ seconds++;
+
+ if (seconds > 59)
+ {
+ seconds = 0;
+
+ advance_minutes();
+ }
+
+ write_counter(REGISTER_1_SECOND, seconds);
+}
+
+
+//-------------------------------------------------
+// advance_minutes -
+//-------------------------------------------------
+
+inline void rp5c01_device::advance_minutes()
+{
+ int minutes = read_counter(REGISTER_1_MINUTE);
+ int hours = read_counter(REGISTER_1_HOUR);
+ int days = read_counter(REGISTER_1_DAY);
+ int month = read_counter(REGISTER_1_MONTH);
+ int year = read_counter(REGISTER_1_YEAR);
+ int day_of_week = m_reg[MODE00][REGISTER_DAY_OF_THE_WEEK];
+
+ minutes++;
+
+ if (minutes > 59)
+ {
+ minutes = 0;
+ hours++;
+ }
+
+ if (hours > 23)
+ {
+ hours = 0;
+ days++;
+ day_of_week++;
+ }
+
+ if (day_of_week > 6)
+ {
+ day_of_week++;
+ }
+
+ if (days > DAYS_PER_MONTH[month - 1])
+ {
+ days = 1;
+ month++;
+ }
+
+ if (month > 12)
+ {
+ month = 1;
+ year++;
+ m_reg[MODE01][REGISTER_LEAP_YEAR]++;
+ m_reg[MODE01][REGISTER_LEAP_YEAR] &= 0x03;
+ }
+
+ if (year > 99)
+ {
+ year = 0;
+ }
+
+ write_counter(REGISTER_1_MINUTE, minutes);
+ write_counter(REGISTER_1_HOUR, hours);
+ write_counter(REGISTER_1_DAY, days);
+ write_counter(REGISTER_1_MONTH, month);
+ write_counter(REGISTER_1_YEAR, year);
+ m_reg[MODE00][REGISTER_DAY_OF_THE_WEEK] = day_of_week;
+
+ check_alarm();
+ set_alarm_line();
+}
+
+
+//-------------------------------------------------
+// adjust_seconds -
+//-------------------------------------------------
+
+inline void rp5c01_device::adjust_seconds()
+{
+ int seconds = read_counter(REGISTER_1_SECOND);
+
+ if (seconds < 30)
+ {
+ write_counter(REGISTER_1_SECOND, 0);
+ }
+ else
+ {
+ write_counter(REGISTER_1_SECOND, 0);
+ advance_minutes();
+ }
+}
+
+
+//-------------------------------------------------
+// check_alarm -
+//-------------------------------------------------
+
+inline void rp5c01_device::check_alarm()
+{
+ bool all_match = true;
+ bool all_zeroes = true;
+
+ for (int i = REGISTER_1_MINUTE; i < REGISTER_1_MONTH; i++)
+ {
+ if (m_reg[MODE01][i] != 0) all_zeroes = false;
+ if (m_reg[MODE01][i] != m_reg[MODE00][i]) all_match = false;
+ }
+
+ m_alarm_on = (all_match || (!m_alarm_on && all_zeroes)) ? 0 : 1;
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// rp5c01_device - constructor
+//-------------------------------------------------
+
+rp5c01_device::rp5c01_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, RP5C01, "RP5C01", tag, owner, clock),
+ device_rtc_interface(mconfig, *this),
+ device_nvram_interface(mconfig, *this),
+ m_alarm(1),
+ m_alarm_on(1),
+ m_1hz(1),
+ m_16hz(1)
+{
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void rp5c01_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const rp5c01_interface *intf = reinterpret_cast<const rp5c01_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<rp5c01_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_out_alarm_cb, 0, sizeof(m_out_alarm_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void rp5c01_device::device_start()
+{
+ // resolve callbacks
+ m_out_alarm_func.resolve(m_out_alarm_cb, *this);
+
+ // allocate timers
+ m_clock_timer = timer_alloc(TIMER_CLOCK);
+ m_clock_timer->adjust(attotime::from_hz(clock() / 16384), 0, attotime::from_hz(clock() / 16384));
+
+ m_16hz_timer = timer_alloc(TIMER_16HZ);
+ m_16hz_timer->adjust(attotime::from_hz(clock() / 1024), 0, attotime::from_hz(clock() / 1024));
+
+ // state saving
+ save_item(NAME(m_reg[MODE00]));
+ save_item(NAME(m_reg[MODE01]));
+ save_item(NAME(m_mode));
+ save_item(NAME(m_reset));
+ save_item(NAME(m_alarm));
+ save_item(NAME(m_alarm_on));
+ save_item(NAME(m_1hz));
+ save_item(NAME(m_16hz));
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void rp5c01_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case TIMER_CLOCK:
+ if (m_1hz && (m_mode & MODE_TIMER_EN))
+ {
+ advance_seconds();
+ }
+
+ m_1hz = !m_1hz;
+ set_alarm_line();
+ break;
+
+ case TIMER_16HZ:
+ m_16hz = !m_16hz;
+ set_alarm_line();
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// rtc_set_time - called to initialize the RTC to
+// a known state
+//-------------------------------------------------
+
+void rp5c01_device::rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second)
+{
+ write_counter(REGISTER_1_YEAR, year);
+ write_counter(REGISTER_1_MONTH, month);
+ write_counter(REGISTER_1_DAY, day);
+ m_reg[MODE00][REGISTER_DAY_OF_THE_WEEK] = day_of_week;
+ write_counter(REGISTER_1_HOUR, hour);
+ write_counter(REGISTER_1_MINUTE, minute);
+ write_counter(REGISTER_1_SECOND, second);
+}
+
+
+//-------------------------------------------------
+// nvram_default - called to initialize NVRAM to
+// its default state
+//-------------------------------------------------
+
+void rp5c01_device::nvram_default()
+{
+}
+
+
+//-------------------------------------------------
+// nvram_read - called to read NVRAM from the
+// .nv file
+//-------------------------------------------------
+
+void rp5c01_device::nvram_read(emu_file &file)
+{
+ file.read(m_ram, RAM_SIZE);
+}
+
+
+//-------------------------------------------------
+// nvram_write - called to write NVRAM to the
+// .nv file
+//-------------------------------------------------
+
+void rp5c01_device::nvram_write(emu_file &file)
+{
+ file.write(m_ram, RAM_SIZE);
+}
+
+
+//-------------------------------------------------
+// adj_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( rp5c01_device::adj_w )
+{
+ if (state)
+ {
+ adjust_seconds();
+ }
+}
+
+
+//-------------------------------------------------
+// read -
+//-------------------------------------------------
+
+READ8_MEMBER( rp5c01_device::read )
+{
+ UINT8 data = 0;
+
+ switch (offset & 0x0f)
+ {
+ case REGISTER_MODE:
+ data = m_mode;
+ break;
+
+ case REGISTER_TEST:
+ case REGISTER_RESET:
+ // write only
+ break;
+
+ default:
+ data = m_reg[m_mode & MODE_MASK][offset];
+ break;
+ }
+
+ if (LOG) logerror("RP5C01 '%s' Register %u Read %02x\n", tag(), offset & 0x0f, data);
+
+ return data & 0x0f;
+}
+
+
+//-------------------------------------------------
+// write -
+//-------------------------------------------------
+
+WRITE8_MEMBER( rp5c01_device::write )
+{
+ int mode = m_mode & MODE_MASK;
+
+ switch (offset & 0x0f)
+ {
+ case REGISTER_MODE:
+ m_mode = data & 0x0f;
+
+ if (LOG)
+ {
+ logerror("RP5C01 '%s' Mode %u\n", tag(), data & MODE_MASK);
+ logerror("RP5C01 '%s' Timer %s\n", tag(), (data & MODE_TIMER_EN) ? "enabled" : "disabled");
+ logerror("RP5C01 '%s' Alarm %s\n", tag(), (data & MODE_ALARM_EN) ? "enabled" : "disabled");
+ }
+ break;
+
+ case REGISTER_TEST:
+ if (LOG) logerror("RP5C01 '%s' Test %u not supported!\n", tag(), data);
+ break;
+
+ case REGISTER_RESET:
+ m_reset = data & 0x0f;
+
+ if (data & RESET_ALARM)
+ {
+ int i;
+
+ // reset alarm registers
+ for (i = REGISTER_1_MINUTE; i < REGISTER_1_MONTH; i++)
+ {
+ m_reg[MODE01][i] = 0;
+ }
+ }
+
+ if (LOG)
+ {
+ if (data & RESET_ALARM) logerror("RP5C01 '%s' Alarm Reset\n", tag());
+ if (data & RESET_TIMER) logerror("RP5C01 '%s' Timer Reset not supported!\n", tag());
+ logerror("RP5C01 '%s' 16Hz Signal %s\n", tag(), (data & RESET_16_HZ) ? "disabled" : "enabled");
+ logerror("RP5C01 '%s' 1Hz Signal %s\n", tag(), (data & RESET_1_HZ) ? "disabled" : "enabled");
+ }
+ break;
+
+ default:
+ switch (mode)
+ {
+ case MODE00:
+ case MODE01:
+ m_reg[mode][offset & 0x0f] = data & REGISTER_WRITE_MASK[mode][offset & 0x0f];
+ break;
+
+ case BLOCK10:
+ m_ram[offset & 0x0f] = (m_ram[offset & 0x0f] & 0xf0) | (data & 0x0f);
+ break;
+
+ case BLOCK11:
+ m_ram[offset & 0x0f] = (data << 4) | (m_ram[offset & 0x0f] & 0x0f);
+ break;
+ }
+
+ if (LOG) logerror("RP5C01 '%s' Register %u Write %02x\n", tag(), offset & 0x0f, data);
+ break;
+ }
+}
diff --git a/trunk/src/emu/machine/rp5c01.h b/trunk/src/emu/machine/rp5c01.h
new file mode 100644
index 00000000000..c91a35c45b4
--- /dev/null
+++ b/trunk/src/emu/machine/rp5c01.h
@@ -0,0 +1,123 @@
+/**********************************************************************
+
+ Ricoh RP5C01(A) Real Time Clock With Internal RAM emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ _CS 1 |* \_/ | 18 Vcc
+ CS 2 | | 17 OSCOUT
+ ADJ 3 | | 16 OSCIN
+ A0 4 | RP5C01 | 15 _ALARM
+ A1 5 | RP5C01A | 14 D3
+ A2 6 | RF5C01A | 13 D2
+ A3 7 | TC8521 | 12 D1
+ _RD 8 | | 11 D0
+ GND 9 |_____________| 10 _WR
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __RP5C01__
+#define __RP5C01__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_RP5C01_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD((_tag), RP5C01, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+
+#define RP5C01_INTERFACE(name) \
+ const rp5c01_interface (name) =
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> rp5c01_interface
+
+struct rp5c01_interface
+{
+ devcb_write_line m_out_alarm_cb;
+};
+
+
+
+// ======================> rp5c01_device
+
+class rp5c01_device : public device_t,
+ public device_rtc_interface,
+ public device_nvram_interface,
+ public rp5c01_interface
+{
+public:
+ // construction/destruction
+ rp5c01_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_READ8_MEMBER( read );
+ DECLARE_WRITE8_MEMBER( write );
+ DECLARE_WRITE_LINE_MEMBER( adj_w );
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+ // device_rtc_interface overrides
+ virtual void rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second);
+ virtual bool rtc_is_year_2000_compliant() { return false; }
+
+ // device_nvram_interface overrides
+ virtual void nvram_default();
+ virtual void nvram_read(emu_file &file);
+ virtual void nvram_write(emu_file &file);
+
+private:
+ inline void set_alarm_line();
+ inline int read_counter(int counter);
+ inline void write_counter(int counter, int value);
+ inline void advance_seconds();
+ inline void advance_minutes();
+ inline void adjust_seconds();
+ inline void check_alarm();
+
+ static const device_timer_id TIMER_CLOCK = 0;
+ static const device_timer_id TIMER_16HZ = 1;
+
+ devcb_resolved_write_line m_out_alarm_func;
+
+ UINT8 m_reg[2][13]; // clock registers
+ UINT8 m_ram[13]; // RAM
+
+ UINT8 m_mode; // mode register
+ UINT8 m_reset; // reset register
+ int m_alarm; // alarm output
+ int m_alarm_on; // alarm condition
+ int m_1hz; // 1 Hz condition
+ int m_16hz; // 16 Hz condition
+
+ // timers
+ emu_timer *m_clock_timer;
+ emu_timer *m_16hz_timer;
+};
+
+
+// device type definition
+extern const device_type RP5C01;
+
+
+
+#endif
diff --git a/trunk/src/emu/machine/rp5c15.c b/trunk/src/emu/machine/rp5c15.c
new file mode 100644
index 00000000000..43b1accb5b8
--- /dev/null
+++ b/trunk/src/emu/machine/rp5c15.c
@@ -0,0 +1,552 @@
+/**********************************************************************
+
+ Ricoh RP5C15 Real Time Clock emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+/*
+
+ TODO:
+
+ - 12 hour clock
+ - test register
+ - timer reset
+
+*/
+
+#include "rp5c15.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+
+// registers
+enum
+{
+ REGISTER_1_SECOND = 0, REGISTER_CLOCK_OUTPUT = REGISTER_1_SECOND,
+ REGISTER_10_SECOND, REGISTER_ADJUST = REGISTER_10_SECOND,
+ REGISTER_1_MINUTE,
+ REGISTER_10_MINUTE,
+ REGISTER_1_HOUR,
+ REGISTER_10_HOUR,
+ REGISTER_DAY_OF_THE_WEEK,
+ REGISTER_1_DAY,
+ REGISTER_10_DAY,
+ REGISTER_1_MONTH,
+ REGISTER_10_MONTH, REGISTER_12_24_SELECT = REGISTER_10_MONTH,
+ REGISTER_1_YEAR, REGISTER_LEAP_YEAR = REGISTER_1_YEAR,
+ REGISTER_10_YEAR,
+ REGISTER_MODE,
+ REGISTER_TEST,
+ REGISTER_RESET
+};
+
+
+// clock output select
+enum
+{
+ CLKOUT_Z = 0,
+ CLKOUT_16384_HZ,
+ CLKOUT_1024_HZ,
+ CLKOUT_128_HZ,
+ CLKOUT_16_HZ,
+ CLKOUT_1_HZ,
+ CLKOUT_1_DIV_60_HZ,
+ CLKOUT_L
+};
+
+
+// register write mask
+static const int REGISTER_WRITE_MASK[2][16] =
+{
+ { 0xf, 0x7, 0xf, 0x7, 0xf, 0x3, 0x7, 0xf, 0x3, 0xf, 0x1, 0xf, 0xf, 0xf, 0xf, 0xf },
+ { 0x3, 0x1, 0xf, 0x7, 0xf, 0x3, 0x7, 0xf, 0x3, 0x0, 0x1, 0x3, 0x0, 0xf, 0xf, 0xf }
+};
+
+
+// days per month
+static const int DAYS_PER_MONTH[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+
+// modes
+enum
+{
+ MODE00 = 0,
+ MODE01
+};
+
+
+// mode register
+#define MODE_MASK 0x01
+#define MODE_ALARM_EN 0x04
+#define MODE_TIMER_EN 0x08
+
+
+// test register
+#define TEST_0 0x01
+#define TEST_1 0x02
+#define TEST_2 0x04
+#define TEST_3 0x08
+
+
+// reset register
+#define RESET_ALARM 0x01
+#define RESET_TIMER 0x02
+#define RESET_16_HZ 0x04
+#define RESET_1_HZ 0x08
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// devices
+const device_type RP5C15 = &device_creator<rp5c15_device>;
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// set_alarm_line -
+//-------------------------------------------------
+
+inline void rp5c15_device::set_alarm_line()
+{
+ int alarm = ((m_mode & MODE_ALARM_EN) ? m_alarm_on : 1) &
+ ((m_reset & RESET_16_HZ) ? 1 : m_16hz) &
+ ((m_reset & RESET_1_HZ) ? 1 : m_1hz);
+
+ if (m_alarm != alarm)
+ {
+ if (LOG) logerror("RP5C15 '%s' Alarm %u\n", tag(), alarm);
+
+ m_out_alarm_func(alarm);
+ m_alarm = alarm;
+ }
+}
+
+
+//-------------------------------------------------
+// read_counter -
+//-------------------------------------------------
+
+inline int rp5c15_device::read_counter(int counter)
+{
+ return (m_reg[MODE00][counter + 1] * 10) + m_reg[MODE00][counter];
+}
+
+
+//-------------------------------------------------
+// write_counter -
+//-------------------------------------------------
+
+inline void rp5c15_device::write_counter(int counter, int value)
+{
+ m_reg[MODE00][counter] = value % 10;
+ m_reg[MODE00][counter + 1] = value / 10;
+}
+
+
+//-------------------------------------------------
+// advance_seconds -
+//-------------------------------------------------
+
+inline void rp5c15_device::advance_seconds()
+{
+ int seconds = read_counter(REGISTER_1_SECOND);
+
+ seconds++;
+
+ if (seconds > 59)
+ {
+ seconds = 0;
+
+ advance_minutes();
+ }
+
+ write_counter(REGISTER_1_SECOND, seconds);
+}
+
+
+//-------------------------------------------------
+// advance_minutes -
+//-------------------------------------------------
+
+inline void rp5c15_device::advance_minutes()
+{
+ int minutes = read_counter(REGISTER_1_MINUTE);
+ int hours = read_counter(REGISTER_1_HOUR);
+ int days = read_counter(REGISTER_1_DAY);
+ int month = read_counter(REGISTER_1_MONTH);
+ int year = read_counter(REGISTER_1_YEAR);
+ int day_of_week = m_reg[MODE00][REGISTER_DAY_OF_THE_WEEK];
+
+ minutes++;
+
+ if (minutes > 59)
+ {
+ minutes = 0;
+ hours++;
+ }
+
+ if (hours > 23)
+ {
+ hours = 0;
+ days++;
+ day_of_week++;
+ }
+
+ if (day_of_week > 6)
+ {
+ day_of_week++;
+ }
+
+ if (days > DAYS_PER_MONTH[month - 1])
+ {
+ days = 1;
+ month++;
+ }
+
+ if (month > 12)
+ {
+ month = 1;
+ year++;
+ m_reg[MODE01][REGISTER_LEAP_YEAR]++;
+ m_reg[MODE01][REGISTER_LEAP_YEAR] &= 0x03;
+ }
+
+ if (year > 99)
+ {
+ year = 0;
+ }
+
+ write_counter(REGISTER_1_MINUTE, minutes);
+ write_counter(REGISTER_1_HOUR, hours);
+ write_counter(REGISTER_1_DAY, days);
+ write_counter(REGISTER_1_MONTH, month);
+ write_counter(REGISTER_1_YEAR, year);
+ m_reg[MODE00][REGISTER_DAY_OF_THE_WEEK] = day_of_week;
+
+ check_alarm();
+ set_alarm_line();
+}
+
+
+//-------------------------------------------------
+// adjust_seconds -
+//-------------------------------------------------
+
+inline void rp5c15_device::adjust_seconds()
+{
+ int seconds = read_counter(REGISTER_1_SECOND);
+
+ if (seconds < 30)
+ {
+ write_counter(REGISTER_1_SECOND, 0);
+ }
+ else
+ {
+ write_counter(REGISTER_1_SECOND, 0);
+ advance_minutes();
+ }
+}
+
+
+//-------------------------------------------------
+// check_alarm -
+//-------------------------------------------------
+
+inline void rp5c15_device::check_alarm()
+{
+ bool all_match = true;
+ bool all_zeroes = true;
+
+ for (int i = REGISTER_1_MINUTE; i < REGISTER_1_MONTH; i++)
+ {
+ if (m_reg[MODE01][i] != 0) all_zeroes = false;
+ if (m_reg[MODE01][i] != m_reg[MODE00][i]) all_match = false;
+ }
+
+ m_alarm_on = (all_match || (!m_alarm_on && all_zeroes)) ? 0 : 1;
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// rp5c15_device - constructor
+//-------------------------------------------------
+
+rp5c15_device::rp5c15_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, RP5C15, "RP5C15", tag, owner, clock),
+ device_rtc_interface(mconfig, *this),
+ m_alarm(1),
+ m_alarm_on(1),
+ m_1hz(1),
+ m_16hz(1),
+ m_clkout(1)
+{
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void rp5c15_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const rp5c15_interface *intf = reinterpret_cast<const rp5c15_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<rp5c15_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_out_alarm_cb, 0, sizeof(m_out_alarm_cb));
+ memset(&m_out_clkout_cb, 0, sizeof(m_out_clkout_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void rp5c15_device::device_start()
+{
+ // resolve callbacks
+ m_out_alarm_func.resolve(m_out_alarm_cb, *this);
+ m_out_clkout_func.resolve(m_out_clkout_cb, *this);
+
+ // allocate timers
+ m_clock_timer = timer_alloc(TIMER_CLOCK);
+ m_clock_timer->adjust(attotime::from_hz(clock() / 16384), 0, attotime::from_hz(clock() / 16384));
+
+ m_16hz_timer = timer_alloc(TIMER_16HZ);
+ m_16hz_timer->adjust(attotime::from_hz(clock() / 1024), 0, attotime::from_hz(clock() / 1024));
+
+ m_clkout_timer = timer_alloc(TIMER_CLKOUT);
+
+ // state saving
+ save_item(NAME(m_reg[MODE00]));
+ save_item(NAME(m_reg[MODE01]));
+ save_item(NAME(m_mode));
+ save_item(NAME(m_reset));
+ save_item(NAME(m_alarm));
+ save_item(NAME(m_alarm_on));
+ save_item(NAME(m_1hz));
+ save_item(NAME(m_16hz));
+ save_item(NAME(m_clkout));
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void rp5c15_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case TIMER_CLOCK:
+ if (m_1hz && (m_mode & MODE_TIMER_EN))
+ {
+ advance_seconds();
+ }
+
+ m_1hz = !m_1hz;
+ set_alarm_line();
+ break;
+
+ case TIMER_16HZ:
+ m_16hz = !m_16hz;
+ set_alarm_line();
+ break;
+
+ case TIMER_CLKOUT:
+ m_clkout = !m_clkout;
+ m_out_clkout_func(m_clkout);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// rtc_set_time - called to initialize the RTC to
+// a known state
+//-------------------------------------------------
+
+void rp5c15_device::rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second)
+{
+ write_counter(REGISTER_1_YEAR, year);
+ write_counter(REGISTER_1_MONTH, month);
+ write_counter(REGISTER_1_DAY, day);
+ m_reg[MODE00][REGISTER_DAY_OF_THE_WEEK] = day_of_week;
+ write_counter(REGISTER_1_HOUR, hour);
+ write_counter(REGISTER_1_MINUTE, minute);
+ write_counter(REGISTER_1_SECOND, second);
+}
+
+
+//-------------------------------------------------
+// read -
+//-------------------------------------------------
+
+READ8_MEMBER( rp5c15_device::read )
+{
+ UINT8 data = 0;
+
+ switch (offset & 0x0f)
+ {
+ case REGISTER_MODE:
+ data = m_mode;
+ break;
+
+ case REGISTER_TEST:
+ case REGISTER_RESET:
+ // write only
+ break;
+
+ default:
+ data = m_reg[m_mode & MODE_MASK][offset];
+ break;
+ }
+
+ if (LOG) logerror("RP5C15 '%s' Register %u Read %02x\n", tag(), offset & 0x0f, data);
+
+ return data & 0x0f;
+}
+
+
+//-------------------------------------------------
+// write -
+//-------------------------------------------------
+
+WRITE8_MEMBER( rp5c15_device::write )
+{
+ int mode = m_mode & MODE_MASK;
+
+ switch (offset & 0x0f)
+ {
+ case REGISTER_MODE:
+ m_mode = data & 0x0f;
+
+ if (LOG)
+ {
+ logerror("RP5C15 '%s' Mode %u\n", tag(), data & MODE_MASK);
+ logerror("RP5C15 '%s' Timer %s\n", tag(), (data & MODE_TIMER_EN) ? "enabled" : "disabled");
+ logerror("RP5C15 '%s' Alarm %s\n", tag(), (data & MODE_ALARM_EN) ? "enabled" : "disabled");
+ }
+ break;
+
+ case REGISTER_TEST:
+ if (LOG) logerror("RP5C15 '%s' Test %u not supported!\n", tag(), data);
+ break;
+
+ case REGISTER_RESET:
+ m_reset = data & 0x0f;
+
+ if (data & RESET_ALARM)
+ {
+ int i;
+
+ // reset alarm registers
+ for (i = REGISTER_1_MINUTE; i < REGISTER_1_MONTH; i++)
+ {
+ m_reg[MODE01][i] = 0;
+ }
+ }
+
+ if (LOG)
+ {
+ if (data & RESET_ALARM) logerror("RP5C15 '%s' Alarm Reset\n", tag());
+ if (data & RESET_TIMER) logerror("RP5C15 '%s' Timer Reset not supported!\n", tag());
+ logerror("RP5C15 '%s' 16Hz Signal %s\n", tag(), (data & RESET_16_HZ) ? "disabled" : "enabled");
+ logerror("RP5C15 '%s' 1Hz Signal %s\n", tag(), (data & RESET_1_HZ) ? "disabled" : "enabled");
+ }
+ break;
+
+ default:
+ switch (mode)
+ {
+ case MODE00:
+ m_reg[mode][offset & 0x0f] = data & REGISTER_WRITE_MASK[mode][offset & 0x0f];
+ break;
+
+ case MODE01:
+ switch (offset & 0x0f)
+ {
+ case REGISTER_CLOCK_OUTPUT:
+ switch (data & 0x07)
+ {
+ case CLKOUT_16384_HZ:
+ m_clkout_timer->adjust(attotime::from_hz(clock()), 0, attotime::from_hz(clock()));
+ break;
+
+ case CLKOUT_1024_HZ:
+ m_clkout_timer->adjust(attotime::from_hz(clock() / 16), 0, attotime::from_hz(clock() / 16));
+ break;
+
+ case CLKOUT_128_HZ:
+ m_clkout_timer->adjust(attotime::from_hz(clock() / 128), 0, attotime::from_hz(clock() / 128));
+ break;
+
+ case CLKOUT_16_HZ:
+ m_clkout_timer->adjust(attotime::from_hz(clock() / 1024), 0, attotime::from_hz(clock() / 1024));
+ break;
+
+ case CLKOUT_1_HZ:
+ m_clkout_timer->adjust(attotime::from_hz(clock() / 16384), 0, attotime::from_hz(clock() / 16384));
+ break;
+
+ case CLKOUT_1_DIV_60_HZ:
+ // TODO
+ break;
+
+ case CLKOUT_L:
+ case CLKOUT_Z:
+ m_clkout = 1;
+ m_clkout_timer->adjust(attotime::zero, 0);
+ break;
+ }
+
+ m_reg[mode][offset & 0x0f] = data & REGISTER_WRITE_MASK[mode][offset & 0x0f];
+ break;
+
+ case REGISTER_ADJUST:
+ if (BIT(data, 0))
+ {
+ adjust_seconds();
+ }
+ m_reg[mode][offset & 0x0f] = data & REGISTER_WRITE_MASK[mode][offset & 0x0f];
+ break;
+
+ default:
+ m_reg[mode][offset & 0x0f] = data & REGISTER_WRITE_MASK[mode][offset & 0x0f];
+ break;
+ }
+ break;
+ }
+
+ if (LOG) logerror("RP5C15 '%s' Register %u Write %02x\n", tag(), offset & 0x0f, data);
+ break;
+ }
+}
diff --git a/trunk/src/emu/machine/rp5c15.h b/trunk/src/emu/machine/rp5c15.h
new file mode 100644
index 00000000000..9a2191d6316
--- /dev/null
+++ b/trunk/src/emu/machine/rp5c15.h
@@ -0,0 +1,122 @@
+/**********************************************************************
+
+ Ricoh RP5C15 Real Time Clock emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ _CS 1 |* \_/ | 18 Vcc
+ CS 2 | | 17 OSCOUT
+ CLKOUT 3 | | 16 OSCIN
+ A0 4 | RP5C15 | 15 _ALARM
+ A1 5 | RF5C15 | 14 D3
+ A2 6 | RJ5C15 | 13 D2
+ A3 7 | | 12 D1
+ _RD 8 | | 11 D0
+ GND 9 |_____________| 10 _WR
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __RP5C15__
+#define __RP5C15__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_RP5C15_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD((_tag), RP5C15, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+
+#define RP5C15_INTERFACE(name) \
+ const rp5c15_interface (name) =
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> rp5c15_interface
+
+struct rp5c15_interface
+{
+ devcb_write_line m_out_alarm_cb;
+ devcb_write_line m_out_clkout_cb;
+};
+
+
+
+// ======================> rp5c15_device
+
+class rp5c15_device : public device_t,
+ public device_rtc_interface,
+ public rp5c15_interface
+{
+public:
+ // construction/destruction
+ rp5c15_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_READ8_MEMBER( read );
+ DECLARE_WRITE8_MEMBER( write );
+ DECLARE_WRITE_LINE_MEMBER( adj_w );
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+ // device_rtc_interface overrides
+ virtual void rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second);
+ virtual bool rtc_is_year_2000_compliant() { return false; }
+
+private:
+ inline void set_alarm_line();
+ inline int read_counter(int counter);
+ inline void write_counter(int counter, int value);
+ inline void advance_seconds();
+ inline void advance_minutes();
+ inline void adjust_seconds();
+ inline void check_alarm();
+
+ static const device_timer_id TIMER_CLOCK = 0;
+ static const device_timer_id TIMER_16HZ = 1;
+ static const device_timer_id TIMER_CLKOUT = 2;
+
+ devcb_resolved_write_line m_out_alarm_func;
+ devcb_resolved_write_line m_out_clkout_func;
+
+ UINT8 m_reg[2][13]; // clock registers
+ UINT8 m_ram[13]; // RAM
+
+ UINT8 m_mode; // mode register
+ UINT8 m_reset; // reset register
+ int m_alarm; // alarm output
+ int m_alarm_on; // alarm condition
+ int m_1hz; // 1 Hz condition
+ int m_16hz; // 16 Hz condition
+ int m_clkout; // clock output
+
+ // timers
+ emu_timer *m_clock_timer;
+ emu_timer *m_16hz_timer;
+ emu_timer *m_clkout_timer;
+};
+
+
+// device type definition
+extern const device_type RP5C15;
+
+
+
+#endif
diff --git a/trunk/src/emu/machine/rp5h01.c b/trunk/src/emu/machine/rp5h01.c
new file mode 100644
index 00000000000..115b040d812
--- /dev/null
+++ b/trunk/src/emu/machine/rp5h01.c
@@ -0,0 +1,216 @@
+/***************************************************************************
+
+ RP5H01
+
+
+ 2009-06 Converted to be a device
+
+***************************************************************************/
+
+#include "emu.h"
+#include "machine/rp5h01.h"
+
+
+/***************************************************************************
+ PARAMETERS
+***************************************************************************/
+
+/* these also work as the address masks */
+enum {
+ COUNTER_MODE_6_BITS = 0x3f,
+ COUNTER_MODE_7_BITS = 0x7f
+};
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _rp5h01_state rp5h01_state;
+struct _rp5h01_state
+{
+ int counter;
+ int counter_mode; /* test pin */
+ int enabled; /* chip enable */
+ int old_reset; /* reset pin state (level-triggered) */
+ int old_clock; /* clock pin state (level-triggered) */
+ UINT8 *data;
+};
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE rp5h01_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert((device->type() == RP5H01));
+ return (rp5h01_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ rp5h01_enable_w
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER( rp5h01_enable_w )
+{
+ rp5h01_state *rp5h01 = get_safe_token(device);
+
+ /* process the /CE signal and enable/disable the IC */
+ rp5h01->enabled = (data == 0) ? 1 : 0;
+}
+
+/*-------------------------------------------------
+ rp5h01_reset_w
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER( rp5h01_reset_w )
+{
+ rp5h01_state *rp5h01 = get_safe_token(device);
+ int newstate = (data == 0) ? 0 : 1;
+
+ /* if it's not enabled, ignore */
+ if (!rp5h01->enabled)
+ return;
+
+ /* now look for a 0->1 transition */
+ if (rp5h01->old_reset == 0 && newstate == 1)
+ {
+ /* reset the counter */
+ rp5h01->counter = 0;
+ }
+
+ /* update the pin */
+ rp5h01->old_reset = newstate;
+}
+
+/*-------------------------------------------------
+ rp5h01_clock_w
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER( rp5h01_clock_w )
+{
+ rp5h01_state *rp5h01 = get_safe_token(device);
+ int newstate = (data == 0) ? 0 : 1;
+
+ /* if it's not enabled, ignore */
+ if (!rp5h01->enabled)
+ return;
+
+ /* now look for a 1->0 transition */
+ if (rp5h01->old_clock == 1 && newstate == 0)
+ {
+ /* increment the counter, and mask it with the mode */
+ rp5h01->counter++;
+ }
+
+ /* update the pin */
+ rp5h01->old_clock = newstate;
+}
+
+/*-------------------------------------------------
+ rp5h01_test_w
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER( rp5h01_test_w )
+{
+ rp5h01_state *rp5h01 = get_safe_token(device);
+
+ /* if it's not enabled, ignore */
+ if (!rp5h01->enabled)
+ return;
+
+ /* process the test signal and change the counter mode */
+ rp5h01->counter_mode = (data == 0) ? COUNTER_MODE_6_BITS : COUNTER_MODE_7_BITS;
+}
+
+/*-------------------------------------------------
+ rp5h01_counter_r
+-------------------------------------------------*/
+
+READ8_DEVICE_HANDLER( rp5h01_counter_r )
+{
+ rp5h01_state *rp5h01 = get_safe_token(device);
+
+ /* if it's not enabled, ignore */
+ if (!rp5h01->enabled)
+ return 0; /* ? (should be high impedance) */
+
+ /* return A5 */
+ return (rp5h01->counter >> 5) & 1;
+}
+
+/*-------------------------------------------------
+ rp5h01_data_r
+-------------------------------------------------*/
+
+READ8_DEVICE_HANDLER( rp5h01_data_r )
+{
+ rp5h01_state *rp5h01 = get_safe_token(device);
+ int byte, bit;
+
+ /* if it's not enabled, ignore */
+ if (!rp5h01->enabled)
+ return 0; /* ? (should be high impedance) */
+
+ /* get the byte offset and bit offset */
+ byte = (rp5h01->counter & rp5h01->counter_mode) >> 3;
+ bit = 7 - (rp5h01->counter & 7);
+
+ /* return the data */
+ return (rp5h01->data[byte] >> bit) & 1;
+}
+
+/*-------------------------------------------------
+ DEVICE_START( rp5h01 )
+-------------------------------------------------*/
+
+static DEVICE_START( rp5h01 )
+{
+ rp5h01_state *rp5h01 = get_safe_token(device);
+
+ assert(device->static_config() == NULL);
+
+ rp5h01->data = *device->region();
+
+ /* register for state saving */
+ device->save_item(NAME(rp5h01->counter));
+ device->save_item(NAME(rp5h01->counter_mode));
+ device->save_item(NAME(rp5h01->enabled));
+ device->save_item(NAME(rp5h01->old_reset));
+ device->save_item(NAME(rp5h01->old_clock));
+}
+
+/*-------------------------------------------------
+ DEVICE_RESET( rp5h01 )
+-------------------------------------------------*/
+
+static DEVICE_RESET( rp5h01 )
+{
+ rp5h01_state *rp5h01 = get_safe_token(device);
+
+ rp5h01->counter = 0;
+ rp5h01->counter_mode = COUNTER_MODE_6_BITS;
+ rp5h01->enabled = 0;
+ rp5h01->old_reset = -1;
+ rp5h01->old_clock = -1;
+}
+
+/*-------------------------------------------------
+ device definition
+-------------------------------------------------*/
+
+static const char DEVTEMPLATE_SOURCE[] = __FILE__;
+
+#define DEVTEMPLATE_ID(p,s) p##rp5h01##s
+#define DEVTEMPLATE_FEATURES DT_HAS_START | DT_HAS_RESET
+#define DEVTEMPLATE_NAME "RP5H01"
+#define DEVTEMPLATE_FAMILY "RP5H01"
+#include "devtempl.h"
+
+
+DEFINE_LEGACY_DEVICE(RP5H01, rp5h01);
diff --git a/trunk/src/emu/machine/rp5h01.h b/trunk/src/emu/machine/rp5h01.h
new file mode 100644
index 00000000000..6bca1a2250c
--- /dev/null
+++ b/trunk/src/emu/machine/rp5h01.h
@@ -0,0 +1,39 @@
+/***************************************************************************
+
+ RP5H01
+
+
+***************************************************************************/
+
+#ifndef __RP5H01_H__
+#define __RP5H01_H__
+
+#include "devlegcy.h"
+
+/***************************************************************************
+ MACROS / CONSTANTS
+***************************************************************************/
+
+DECLARE_LEGACY_DEVICE(RP5H01, rp5h01);
+
+#define MCFG_RP5H01_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, RP5H01, 0)
+
+/*
+ * Device uses memory region
+ * with the same tag as the one
+ * assigned to device.
+ */
+
+/***************************************************************************
+ PROTOTYPES
+***************************************************************************/
+
+WRITE8_DEVICE_HANDLER( rp5h01_enable_w ); /* /CE */
+WRITE8_DEVICE_HANDLER( rp5h01_reset_w ); /* RESET */
+WRITE8_DEVICE_HANDLER( rp5h01_clock_w ); /* DATA CLOCK (active low) */
+WRITE8_DEVICE_HANDLER( rp5h01_test_w ); /* TEST */
+READ8_DEVICE_HANDLER( rp5h01_counter_r ); /* COUNTER OUT */
+READ8_DEVICE_HANDLER( rp5h01_data_r ); /* DATA */
+
+#endif /* __RP5H01_H__ */
diff --git a/trunk/src/emu/machine/rtc65271.c b/trunk/src/emu/machine/rtc65271.c
new file mode 100644
index 00000000000..5208579ea65
--- /dev/null
+++ b/trunk/src/emu/machine/rtc65271.c
@@ -0,0 +1,722 @@
+/*
+ rtc65271 emulation
+
+ This chip is an RTC for computer built by Epson and Spezial-Electronic (I
+ think SE is the second source here).
+
+ Reference:
+ * Realtime Clock Module RTC-65271 Application Manual
+ <http://www.bgmicro.com/pdf/rtc65271.pdf>
+
+ Todo:
+ * Support square wave pin output?
+ * Support DSE mode?
+
+ Raphael Nabet, 2003-2004
+*/
+
+#include "emu.h"
+#include "rtc65271.h"
+
+static void field_interrupts(device_t *device);
+static TIMER_CALLBACK( rtc_SQW_callback );
+static TIMER_CALLBACK( rtc_begin_update_callback );
+static TIMER_CALLBACK( rtc_end_update_callback );
+
+/* Delay between the beginning (UIP asserted) and the end (UIP cleared and
+update interrupt asserted) of the update cycle */
+#define UPDATE_CYCLE_TIME attotime::from_usec(1984)
+/* Delay between the assertion of UIP and the effective start of the update
+cycle */
+/*#define UPDATE_CYCLE_DELAY attotime::from_usec(244)*/
+
+typedef struct _rtc65271_state rtc65271_state;
+struct _rtc65271_state
+{
+ /* 64 8-bit registers (10 clock registers, 4 control/status registers, and
+ 50 bytes of user RAM) */
+ UINT8 regs[64];
+ UINT8 cur_reg;
+
+ /* extended RAM: 4kbytes of battery-backed RAM (in pages of 32 bytes) */
+ UINT8 xram[4096];
+ UINT8 cur_xram_page;
+
+ /* update timer: called every second */
+ emu_timer *update_timer;
+
+ /* SQW timer: called every periodic clock half-period */
+ emu_timer *SQW_timer;
+ UINT8 SQW_internal_state;
+
+ /* callback called when interrupt pin state changes (may be NULL) */
+ void (*interrupt_callback)(device_t *device, int state);
+};
+
+INLINE rtc65271_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == RTC65271);
+
+ return (rtc65271_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+enum
+{
+ reg_second = 0,
+ reg_alarm_second,
+ reg_minute,
+ reg_alarm_minute,
+ reg_hour,
+ reg_alarm_hour,
+ reg_weekday,
+ reg_monthday,
+ reg_month,
+ reg_year,
+ reg_A,
+ reg_B,
+ reg_C,
+ reg_D
+};
+
+enum
+{
+ reg_A_UIP = 0x80,
+ reg_A_DV = 0x70,
+ reg_A_RS = 0x0F,
+
+ reg_B_SET = 0x80,
+ reg_B_PIE = 0x40,
+ reg_B_AIE = 0x20,
+ reg_B_UIE = 0x10,
+ reg_B_SQW = 0x08,
+ reg_B_DM = 0x04,
+ reg_B_24h = 0x02,
+ reg_B_DSE = 0x01,
+
+ reg_C_IRQF = 0x80,
+ reg_C_PF = 0x40,
+ reg_C_AF = 0x20,
+ reg_C_UF = 0x10,
+
+ reg_D_VRT = 0x80
+};
+
+static const int SQW_freq_table[16] =
+{
+ 0,
+ 256,
+ 128,
+ 8192,
+ 4096,
+ 2048,
+ 1024,
+ 512,
+ 256,
+ 128,
+ 64,
+ 32,
+ 16,
+ 8,
+ 4,
+ 2,
+};
+
+
+/*
+ BCD utilities
+*/
+
+/*
+ Increment a binary-encoded UINT8
+*/
+static UINT8 increment_binary(UINT8 data)
+{
+ return data+1;
+}
+
+
+/*
+ Increment a BCD-encoded UINT8
+*/
+static UINT8 increment_BCD(UINT8 data)
+{
+ if ((data & 0x0f) < 0x09)
+ {
+ if ((data & 0xf0) < 0xa0)
+ data++;
+ else
+ data = data + 0x01 - 0xa0;
+ }
+ else
+ {
+ if ((data & 0xf0) < 0xa0)
+ data = data - 0x09 + 0x10;
+ else
+ data = data - 0x09 - 0x90;
+ }
+ return data;
+}
+
+
+/*
+ Convert a binary-encoded UINT8 to BCD
+*/
+static UINT8 binary_to_BCD(UINT8 data)
+{
+ data %= 100;
+
+ return ((data / 10) << 4) | (data %10);
+}
+
+
+/*
+ Convert a BCD-encoded UINT8 to binary
+*/
+static UINT8 BCD_to_binary(UINT8 data)
+{
+ if ((data & 0x0f) >= 0x0a)
+ data = data - 0x0a + 0x10;
+ if ((data & 0xf0) >= 0xa0)
+ data = data - 0xa0;
+
+ return (data & 0x0f) + (((data & 0xf0) >> 4) * 10);
+}
+
+
+/*
+ Public functions
+*/
+
+
+/*
+ load the SRAM and register contents from file
+*/
+static int rtc65271_file_load(device_t *device, emu_file &file)
+{
+ rtc65271_state *state = get_safe_token(device);
+ UINT8 buf;
+
+
+ /* version flag */
+ if (file.read(&buf, 1) != 1)
+ return 1;
+ if (buf != 0)
+ return 1;
+
+ /* control registers */
+ if (file.read(&buf, 1) != 1)
+ return 1;
+ state->regs[reg_A] = buf & (reg_A_DV /*| reg_A_RS*/);
+ if (file.read(&buf, 1) != 1)
+ return 1;
+ state->regs[reg_B] = buf & (reg_B_SET | reg_B_DM | reg_B_24h | reg_B_DSE);
+
+ /* alarm registers */
+ if (file.read(&state->regs[reg_alarm_second], 1) != 1)
+ return 1;
+ if (file.read(&state->regs[reg_alarm_minute], 1) != 1)
+ return 1;
+ if (file.read(&state->regs[reg_alarm_hour], 1) != 1)
+ return 1;
+
+ /* user RAM */
+ if (file.read(state->regs+14, 50) != 50)
+ return 1;
+
+ /* extended RAM */
+ if (file.read(state->xram, 4096) != 4096)
+ return 1;
+
+ state->regs[reg_D] |= reg_D_VRT; /* the data was backed up successfully */
+ /*state->dirty = FALSE;*/
+
+ {
+ system_time systime;
+
+ /* get the current date/time from the core */
+ device->machine().current_datetime(systime);
+
+ /* set clock registers */
+ state->regs[reg_second] = systime.local_time.second;
+ state->regs[reg_minute] = systime.local_time.minute;
+ if (state->regs[reg_B] & reg_B_24h)
+ /* 24-hour mode */
+ state->regs[reg_hour] = systime.local_time.hour;
+ else
+ { /* 12-hour mode */
+ if (systime.local_time.hour >= 12)
+ {
+ state->regs[reg_hour] = 0x80;
+ systime.local_time.hour -= 12;
+ }
+ else
+ state->regs[reg_hour] = 0;
+ state->regs[reg_hour] |= systime.local_time.hour ? systime.local_time.hour : 12;
+ }
+ state->regs[reg_weekday] = systime.local_time.weekday + 1;
+ state->regs[reg_monthday] = systime.local_time.mday;
+ state->regs[reg_month] = systime.local_time.month + 1;
+ state->regs[reg_year] = systime.local_time.year % 100;
+ if (! (state->regs[reg_B] & reg_B_DM))
+ { /* BCD mode */
+ state->regs[reg_second] = binary_to_BCD(state->regs[reg_second]);
+ state->regs[reg_minute] = binary_to_BCD(state->regs[reg_minute]);
+ state->regs[reg_hour] = (state->regs[reg_hour] & 0x80) | binary_to_BCD(state->regs[reg_hour] & 0x7f);
+ /*state->regs[reg_weekday] = binary_to_BCD(state->regs[reg_weekday]);*/
+ state->regs[reg_monthday] = binary_to_BCD(state->regs[reg_monthday]);
+ state->regs[reg_month] = binary_to_BCD(state->regs[reg_month]);
+ state->regs[reg_year] = binary_to_BCD(state->regs[reg_year]);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ save the SRAM and register contents to file
+*/
+static int rtc65271_file_save(device_t *device, emu_file &file)
+{
+ rtc65271_state *state = get_safe_token(device);
+ UINT8 buf;
+
+
+ /* version flag */
+ buf = 0;
+ if (file.write(& buf, 1) != 1)
+ return 1;
+
+ /* control registers */
+ buf = state->regs[reg_A] & (reg_A_DV | reg_A_RS);
+ if (file.write(&buf, 1) != 1)
+ return 1;
+ buf = state->regs[reg_B] & (reg_B_SET | reg_B_DM | reg_B_24h | reg_B_DSE);
+ if (file.write(&buf, 1) != 1)
+ return 1;
+
+ /* alarm registers */
+ if (file.write(&state->regs[reg_alarm_second], 1) != 1)
+ return 1;
+ if (file.write(&state->regs[reg_alarm_minute], 1) != 1)
+ return 1;
+ if (file.write(&state->regs[reg_alarm_hour], 1) != 1)
+ return 1;
+
+ /* user RAM */
+ if (file.write(state->regs+14, 50) != 50)
+ return 1;
+
+ /* extended RAM */
+ if (file.write(state->xram, 4096) != 4096)
+ return 1;
+
+ return 0;
+}
+
+/*
+ Read a byte from clock
+
+ xramsel: select RTC register if 0, XRAM if 1
+ offset: address (A0-A5 pins)
+*/
+UINT8 rtc65271_r(device_t *device, int xramsel, offs_t offset)
+{
+ rtc65271_state *state = get_safe_token(device);
+ int reply;
+
+ if (xramsel)
+ {
+ if (offset & 0x20)
+ /* XRAM page register */
+ reply = state->cur_xram_page;
+ else
+ /* XRAM data */
+ reply = state->xram[(offset & 0x1f) + 0x0020*state->cur_xram_page];
+ }
+ else
+ {
+ if (offset & 0x01)
+ /* data register */
+ switch (state->cur_reg)
+ {
+ case reg_C:
+ reply = state->regs[state->cur_reg];
+ state->regs[state->cur_reg] = 0;
+ field_interrupts(device);
+ break;
+ case reg_D:
+ reply = state->regs[state->cur_reg];
+ state->regs[state->cur_reg] = /*0*/reg_D_VRT; /* set VRT flag so that the computer does not complain that the battery is low */
+ break;
+
+ default:
+ reply = state->regs[state->cur_reg];
+ break;
+ }
+ else
+ /* indirect address register */
+ reply = state->cur_reg;
+ }
+
+ return reply;
+}
+
+READ8_DEVICE_HANDLER( rtc65271_rtc_r )
+{
+ return rtc65271_r( device, 0, offset );
+}
+
+READ8_DEVICE_HANDLER( rtc65271_xram_r )
+{
+ return rtc65271_r( device, 1, offset );
+}
+
+/*
+ Write a byte to clock
+
+ xramsel: select RTC register if 0, XRAM if 1
+ offset: address (A0-A5 pins)
+*/
+void rtc65271_w(device_t *device, int xramsel, offs_t offset, UINT8 data)
+{
+ rtc65271_state *state = get_safe_token(device);
+ if (xramsel)
+ {
+ if (offset & 0x20)
+ /* XRAM page register */
+ state->cur_xram_page = data & 0x7f;
+ else
+ /* XRAM data */
+ state->xram[(offset & 0x1f) + 0x0020*state->cur_xram_page] = data;
+ }
+ else
+ {
+ if (offset & 0x01)
+ /* data register */
+ switch (state->cur_reg)
+ {
+ case reg_second:
+ /* the data sheet says bit 7 is read-only. (I have no idea of
+ the reason why it is.) */
+ state->regs[reg_second] = data & 0x7f;
+ break;
+
+ case reg_A:
+ if ((data & reg_A_RS) != (state->regs[state->cur_reg] & reg_A_RS))
+ {
+ if (data & reg_A_RS)
+ {
+ attotime period = attotime::from_hz(SQW_freq_table[data & reg_A_RS]);
+ attotime half_period = period / 2;
+ attotime elapsed = state->update_timer->elapsed();
+
+ if (half_period > elapsed)
+ state->SQW_timer->adjust(half_period - elapsed);
+ else
+ state->SQW_timer->adjust(half_period);
+ }
+ else
+ {
+ state->SQW_internal_state = 0; /* right??? */
+
+ /* Stop the divider used for SQW and periodic interrupts. */
+ state->SQW_timer->adjust(attotime::never);
+ }
+ }
+ /* The UIP bit is read-only */
+ state->regs[reg_A] = (data & ~reg_A_UIP) | (state->regs[reg_A] & reg_A_UIP);
+ break;
+
+ case reg_B:
+ state->regs[state->cur_reg] = data;
+ if (data & reg_B_SET)
+ {
+ /* if we are in SET mode, clear update cycle */
+ state->regs[reg_A] &= ~reg_A_UIP;
+ state->regs[reg_B] &= ~reg_B_UIE; /* the data sheet tells this, but I wonder how much sense it makes */
+ field_interrupts(device);
+ }
+ break;
+
+ case reg_C:
+ case reg_D:
+ break;
+
+ default:
+ state->regs[state->cur_reg] = data;
+ break;
+ }
+ else
+ /* indirect address register */
+ state->cur_reg = data & 0x3f;
+ }
+}
+
+WRITE8_DEVICE_HANDLER( rtc65271_rtc_w )
+{
+ rtc65271_w( device, 0, offset, data );
+}
+
+WRITE8_DEVICE_HANDLER( rtc65271_xram_w )
+{
+ rtc65271_w( device, 1, offset, data );
+}
+
+static void field_interrupts(device_t *device)
+{
+ rtc65271_state *state = get_safe_token(device);
+
+ if (state->regs[reg_C] & state->regs[reg_B] & (reg_C_PF | reg_C_AF | reg_C_UF))
+ {
+ state->regs[reg_C] |= reg_C_IRQF;
+ if (state->interrupt_callback)
+ state->interrupt_callback(device, 1);
+ }
+ else
+ {
+ state->regs[reg_C] &= ~reg_C_IRQF;
+ if (state->interrupt_callback)
+ state->interrupt_callback(device, 0);
+ }
+}
+
+
+/*
+ Timer handlers
+*/
+
+/*
+ Update SQW output state each half-period and assert periodic interrupt each
+ period.
+*/
+static TIMER_CALLBACK( rtc_SQW_callback )
+{
+ device_t *device = (device_t *)ptr;
+ rtc65271_state *state = get_safe_token(device);
+ attotime half_period;
+
+ state->SQW_internal_state = ! state->SQW_internal_state;
+ if (! state->SQW_internal_state)
+ {
+ /* high-to-low??? transition -> interrupt (or should it be low-to-high?) */
+ state->regs[reg_C] |= reg_C_PF;
+ field_interrupts(device);
+ }
+
+ half_period = attotime::from_hz(SQW_freq_table[state->regs[reg_A] & reg_A_RS]) / 2;
+ state->SQW_timer->adjust(half_period);
+}
+
+/*
+ Begin update cycle (called every second)
+*/
+static TIMER_CALLBACK( rtc_begin_update_callback )
+{
+ device_t *device = (device_t *)ptr;
+ rtc65271_state *state = get_safe_token(device);
+
+ if (((state->regs[reg_A] & reg_A_DV) == 0x20) && ! (state->regs[reg_B] & reg_B_SET))
+ {
+ state->regs[reg_A] |= reg_A_UIP;
+
+ /* schedule end of update cycle */
+ device->machine().scheduler().timer_set(UPDATE_CYCLE_TIME, FUNC(rtc_end_update_callback), 0, (void *)device);
+ }
+}
+
+/*
+ End update cycle (called UPDATE_CYCLE_TIME = 1948us after start of update
+ cycle)
+*/
+static TIMER_CALLBACK( rtc_end_update_callback )
+{
+ static const int days_in_month_table[12] =
+ {
+ 31,28,31, 30,31,30,
+ 31,31,30, 31,30,31
+ };
+ device_t *device = (device_t *)ptr;
+ rtc65271_state *state = get_safe_token(device);
+ UINT8 (*increment)(UINT8 data);
+ int c59, c23, c12, c11, c29;
+
+ if (! (state->regs[reg_A] & reg_A_UIP))
+ /* abort if update cycle has been canceled */
+ return;
+
+ if (state->regs[reg_B] & reg_B_DM)
+ {
+ /* binary mode */
+ increment = increment_binary;
+ c59 = 59;
+ c23 = 23;
+ c12 = 12;
+ c11 = 11;
+ c29 = 29;
+ }
+ else
+ {
+ /* BCD mode */
+ increment = increment_BCD;
+ c59 = 0x59;
+ c23 = 0x23;
+ c12 = 0x12;
+ c11 = 0x11;
+ c29 = 0x29;
+ }
+
+ /* increment second */
+ if (state->regs[reg_second] < c59)
+ state->regs[reg_second] = (*increment)(state->regs[reg_second]);
+ else
+ {
+ state->regs[reg_second] = 0;
+
+ /* increment minute */
+ if (state->regs[reg_minute] < c59)
+ state->regs[reg_minute] = (*increment)(state->regs[reg_minute]);
+ else
+ {
+ state->regs[reg_minute] = 0;
+
+ /* increment hour */
+ if (state->regs[reg_B] & reg_B_24h)
+ {
+ /* 24 hour mode */
+ if (state->regs[reg_hour] < c23)
+ state->regs[reg_hour] = (*increment)(state->regs[reg_hour]);
+ else
+ state->regs[reg_hour] = 0;
+ }
+ else
+ {
+ /* 12 hour mode */
+ if (state->regs[reg_hour] < c12)
+ {
+ if ((state->regs[reg_hour] & 0x7f) == c11)
+ state->regs[reg_hour] ^= 0x80;
+ state->regs[reg_hour] = ((*increment)(state->regs[reg_hour] & 0x7f) & 0x7f)
+ | (state->regs[reg_hour] & 0x80);
+ }
+ else
+ state->regs[reg_hour] = 1 | (state->regs[reg_hour] & 0x80);
+ }
+
+ /* increment day if needed */
+ if (state->regs[reg_hour] == ((state->regs[reg_B] & reg_B_24h) ? 0 : c12))
+ {
+ /* increment day */
+ int days_in_month;
+
+ if (state->regs[reg_weekday] < 7)
+ state->regs[reg_weekday]++;
+ else
+ state->regs[reg_weekday] = 1;
+
+ if ((state->regs[reg_month] != 2) || (state->regs[reg_year] & 0x03))
+ {
+ if (state->regs[reg_B] & reg_B_DM)
+ {
+ /* binary mode */
+ days_in_month = days_in_month_table[state->regs[reg_month] - 1];
+ }
+ else
+ {
+ /* BCD mode */
+ days_in_month = binary_to_BCD(days_in_month_table[BCD_to_binary(state->regs[reg_month]) - 1]);
+ }
+ }
+ else
+ days_in_month = c29;
+
+ if (state->regs[reg_monthday] < days_in_month)
+ state->regs[reg_monthday] = (*increment)(state->regs[reg_monthday]);
+ else
+ {
+ /* increment month */
+ state->regs[reg_monthday] = 1;
+
+ if (state->regs[reg_month] < c12)
+ state->regs[reg_month] = (*increment)(state->regs[reg_month]);
+ else
+ {
+ /* increment year */
+ state->regs[reg_month] = 1;
+
+ if (state->regs[reg_B] & reg_B_DM)
+ {
+ /* binary mode */
+ if (state->regs[reg_year] < 99)
+ state->regs[reg_year]++;
+ else
+ state->regs[reg_year] = 0;
+ }
+ else
+ {
+ /* BCD mode */
+ state->regs[reg_year] = increment_BCD(state->regs[reg_year]);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ state->regs[reg_A] &= ~reg_A_UIP;
+ state->regs[reg_C] |= reg_C_UF;
+
+ /* test for alarm (values in range 0xc0-0xff mean "don't care") */
+ if ((((state->regs[reg_alarm_second] & 0xc0) == 0xc0) || (state->regs[reg_alarm_second] == state->regs[reg_second]))
+ && (((state->regs[reg_alarm_minute] & 0xc0) == 0xc0) || (state->regs[reg_alarm_minute] == state->regs[reg_minute]))
+ && (((state->regs[reg_alarm_hour] & 0xc0) == 0xc0) || (state->regs[reg_alarm_hour] == state->regs[reg_hour])))
+ state->regs[reg_C] |= reg_C_AF;
+
+ field_interrupts(device);
+}
+
+/*
+ Initialize clock
+
+ interrupt_callback: callback called when interrupt pin state changes (may
+ be NULL)
+*/
+
+static DEVICE_START( rtc65271 )
+{
+ rtc65271_config *config = (rtc65271_config *)downcast<const legacy_device_base *>(device)->inline_config();
+ rtc65271_state *state = get_safe_token(device);
+
+ state->update_timer = device->machine().scheduler().timer_alloc(FUNC(rtc_begin_update_callback), (void *)device);
+ state->update_timer->adjust(attotime::from_seconds(1), 0, attotime::from_seconds(1));
+ state->SQW_timer = device->machine().scheduler().timer_alloc(FUNC(rtc_SQW_callback), (void *)device);
+ state->interrupt_callback = config->interrupt_callback;
+
+ device->save_item(NAME(state->regs));
+ device->save_item(NAME(state->cur_reg));
+ device->save_item(NAME(state->xram));
+ device->save_item(NAME(state->cur_xram_page));
+ device->save_item(NAME(state->SQW_internal_state));
+}
+
+
+static DEVICE_NVRAM( rtc65271 )
+{
+ if (read_or_write)
+ rtc65271_file_save(device, *file);
+ else if (file)
+ rtc65271_file_load(device, *file);
+}
+
+
+static const char DEVTEMPLATE_SOURCE[] = __FILE__;
+
+#define DEVTEMPLATE_ID(p,s) p##rtc65271##s
+#define DEVTEMPLATE_FEATURES DT_HAS_START | DT_HAS_NVRAM | DT_HAS_INLINE_CONFIG
+#define DEVTEMPLATE_NAME "RTC65271"
+#define DEVTEMPLATE_FAMILY "RTC"
+#include "devtempl.h"
+
+
+DEFINE_LEGACY_NVRAM_DEVICE(RTC65271, rtc65271);
diff --git a/trunk/src/emu/machine/rtc65271.h b/trunk/src/emu/machine/rtc65271.h
new file mode 100644
index 00000000000..2c33a9b9a0d
--- /dev/null
+++ b/trunk/src/emu/machine/rtc65271.h
@@ -0,0 +1,33 @@
+/*
+ rtc65271.h: include file for rtc65271.c
+*/
+
+#ifndef __RTC65271_H__
+#define __RTC65271_H__
+
+#include "devlegcy.h"
+
+typedef struct _rtc65271_config rtc65271_config;
+struct _rtc65271_config
+{
+ void (*interrupt_callback)(device_t *device, int state);
+};
+
+
+#define MCFG_RTC65271_ADD(_tag, _callback) \
+ MCFG_DEVICE_ADD(_tag, RTC65271, 0) \
+ MCFG_DEVICE_CONFIG_DATAPTR(rtc65271_config, interrupt_callback, _callback)
+
+
+UINT8 rtc65271_r(device_t *device, int xramsel, offs_t offset);
+void rtc65271_w(device_t *device, int xramsel, offs_t offset, UINT8 data);
+
+READ8_DEVICE_HANDLER( rtc65271_rtc_r );
+READ8_DEVICE_HANDLER( rtc65271_xram_r );
+WRITE8_DEVICE_HANDLER( rtc65271_rtc_w );
+WRITE8_DEVICE_HANDLER( rtc65271_xram_w );
+
+
+DECLARE_LEGACY_NVRAM_DEVICE(RTC65271, rtc65271);
+
+#endif
diff --git a/trunk/src/emu/machine/s3c2400.c b/trunk/src/emu/machine/s3c2400.c
new file mode 100644
index 00000000000..0b969b191cb
--- /dev/null
+++ b/trunk/src/emu/machine/s3c2400.c
@@ -0,0 +1,92 @@
+/*******************************************************************************
+
+ Samsung S3C2400
+
+ (c) 2010 Tim Schuerewegen
+
+*******************************************************************************/
+
+#include "emu.h"
+#include "cpu/arm7/arm7.h"
+#include "cpu/arm7/arm7core.h"
+#include "machine/s3c2400.h"
+#include "sound/dac.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);
+ }
+}
+
+#define DEVICE_S3C2400
+#include "machine/s3c24xx.c"
+#undef DEVICE_S3C2400
+
+VIDEO_START( s3c2400 )
+{
+ device_t *device = machine.device( S3C2400_TAG);
+ s3c24xx_video_start( device, machine);
+}
+
+SCREEN_UPDATE( s3c2400 )
+{
+ device_t *device = screen->machine().device( S3C2400_TAG);
+ return s3c24xx_video_update( device, screen, bitmap, cliprect);
+}
+
+DEVICE_START( s3c2400 )
+{
+ address_space *space = device->machine().device( "maincpu")->memory().space( AS_PROGRAM);
+ DEVICE_START_CALL(s3c24xx);
+ space->install_legacy_readwrite_handler( *device, 0x14000000, 0x1400003b, FUNC(s3c24xx_memcon_r), FUNC(s3c24xx_memcon_w));
+ space->install_legacy_readwrite_handler( *device, 0x14200000, 0x1420005b, FUNC(s3c24xx_usb_host_r), FUNC(s3c24xx_usb_host_w));
+ space->install_legacy_readwrite_handler( *device, 0x14400000, 0x14400017, FUNC(s3c24xx_irq_r), FUNC(s3c24xx_irq_w));
+ space->install_legacy_readwrite_handler( *device, 0x14600000, 0x1460001b, FUNC(s3c24xx_dma_0_r), FUNC(s3c24xx_dma_0_w));
+ space->install_legacy_readwrite_handler( *device, 0x14600020, 0x1460003b, FUNC(s3c24xx_dma_1_r), FUNC(s3c24xx_dma_1_w));
+ space->install_legacy_readwrite_handler( *device, 0x14600040, 0x1460005b, FUNC(s3c24xx_dma_2_r), FUNC(s3c24xx_dma_2_w));
+ space->install_legacy_readwrite_handler( *device, 0x14600060, 0x1460007b, FUNC(s3c24xx_dma_3_r), FUNC(s3c24xx_dma_3_w));
+ space->install_legacy_readwrite_handler( *device, 0x14800000, 0x14800017, FUNC(s3c24xx_clkpow_r), FUNC(s3c24xx_clkpow_w));
+ space->install_legacy_readwrite_handler( *device, 0x14a00000, 0x14a003ff, FUNC(s3c2400_lcd_r), FUNC(s3c24xx_lcd_w));
+ space->install_legacy_readwrite_handler( *device, 0x14a00400, 0x14a007ff, FUNC(s3c24xx_lcd_palette_r), FUNC(s3c24xx_lcd_palette_w));
+ space->install_legacy_readwrite_handler( *device, 0x15000000, 0x1500002b, FUNC(s3c24xx_uart_0_r), FUNC(s3c24xx_uart_0_w));
+ space->install_legacy_readwrite_handler( *device, 0x15004000, 0x1500402b, FUNC(s3c24xx_uart_1_r), FUNC(s3c24xx_uart_1_w));
+ space->install_legacy_readwrite_handler( *device, 0x15100000, 0x15100043, FUNC(s3c24xx_pwm_r), FUNC(s3c24xx_pwm_w));
+ space->install_legacy_readwrite_handler( *device, 0x15200140, 0x152001fb, FUNC(s3c24xx_usb_device_r), FUNC(s3c24xx_usb_device_w));
+ space->install_legacy_readwrite_handler( *device, 0x15300000, 0x1530000b, FUNC(s3c24xx_wdt_r), FUNC(s3c24xx_wdt_w));
+ space->install_legacy_readwrite_handler( *device, 0x15400000, 0x1540000f, FUNC(s3c24xx_iic_r), FUNC(s3c24xx_iic_w));
+ space->install_legacy_readwrite_handler( *device, 0x15508000, 0x15508013, FUNC(s3c24xx_iis_r), FUNC(s3c24xx_iis_w));
+ space->install_legacy_readwrite_handler( *device, 0x15600000, 0x1560005b, FUNC(s3c24xx_gpio_r), FUNC(s3c24xx_gpio_w));
+ space->install_legacy_readwrite_handler( *device, 0x15700040, 0x1570008b, FUNC(s3c24xx_rtc_r), FUNC(s3c24xx_rtc_w));
+ space->install_legacy_readwrite_handler( *device, 0x15800000, 0x15800007, FUNC(s3c24xx_adc_r), FUNC(s3c24xx_adc_w));
+ space->install_legacy_readwrite_handler( *device, 0x15900000, 0x15900017, FUNC(s3c24xx_spi_0_r), FUNC(s3c24xx_spi_0_w));
+ space->install_legacy_readwrite_handler( *device, 0x15a00000, 0x15a0003f, FUNC(s3c24xx_mmc_r), FUNC(s3c24xx_mmc_w));
+}
+
+DEVICE_GET_INFO( s3c2400 )
+{
+ switch ( state )
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(s3c2400); break;
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Samsung S3C2400"); break;
+ /* --- default --- */
+ default: DEVICE_GET_INFO_CALL(s3c24xx); break;
+ }
+}
+
+void s3c2400_uart_fifo_w( device_t *device, int uart, UINT8 data)
+{
+ s3c24xx_uart_fifo_w( device, uart, data);
+}
+
+DEFINE_LEGACY_DEVICE(S3C2400, s3c2400);
diff --git a/trunk/src/emu/machine/s3c2400.h b/trunk/src/emu/machine/s3c2400.h
new file mode 100644
index 00000000000..e3f930dcf82
--- /dev/null
+++ b/trunk/src/emu/machine/s3c2400.h
@@ -0,0 +1,727 @@
+/*******************************************************************************
+
+ Samsung S3C2400
+
+*******************************************************************************/
+
+#ifndef __S3C2400_H__
+#define __S3C2400_H__
+
+#include "devlegcy.h"
+
+/*******************************************************************************
+ MACROS / CONSTANTS
+*******************************************************************************/
+
+#define S3C2400_TAG "s3c2400"
+
+#define MCFG_S3C2400_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD(_tag, S3C2400, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define S3C2400_INTERFACE(name) \
+ const s3c2400_interface(name) =
+
+enum
+{
+ S3C2400_GPIO_PORT_A = 0,
+ S3C2400_GPIO_PORT_B,
+ S3C2400_GPIO_PORT_C,
+ S3C2400_GPIO_PORT_D,
+ S3C2400_GPIO_PORT_E,
+ S3C2400_GPIO_PORT_F,
+ S3C2400_GPIO_PORT_G
+};
+
+DECLARE_LEGACY_DEVICE(S3C2400, s3c2400);
+
+/*******************************************************************************
+ TYPE DEFINITIONS
+*******************************************************************************/
+
+typedef UINT32 (*s3c24xx_gpio_port_r_func)( device_t *device, int port);
+typedef void (*s3c24xx_gpio_port_w_func)( device_t *device, int port, UINT32 data);
+
+typedef struct _s3c2400_interface_gpio s3c2400_interface_gpio;
+struct _s3c2400_interface_gpio
+{
+ s3c24xx_gpio_port_r_func port_r;
+ s3c24xx_gpio_port_w_func port_w;
+};
+
+typedef struct _s3c2400_interface_i2c s3c2400_interface_i2c;
+struct _s3c2400_interface_i2c
+{
+ write_line_device_func scl_w;
+ read_line_device_func sda_r;
+ write_line_device_func sda_w;
+};
+
+typedef struct _s3c2400_interface_adc s3c2400_interface_adc;
+struct _s3c2400_interface_adc
+{
+ read32_device_func data_r;
+};
+
+typedef struct _s3c2400_interface_i2s s3c2400_interface_i2s;
+struct _s3c2400_interface_i2s
+{
+ write16_device_func data_w;
+};
+
+typedef struct _s3c2400_interface_lcd s3c2400_interface_lcd;
+struct _s3c2400_interface_lcd
+{
+ int flags;
+};
+
+typedef struct _s3c2400_interface s3c2400_interface;
+struct _s3c2400_interface
+{
+ s3c2400_interface_gpio gpio;
+ s3c2400_interface_i2c i2c;
+ s3c2400_interface_adc adc;
+ s3c2400_interface_i2s i2s;
+ s3c2400_interface_lcd lcd;
+};
+
+/*******************************************************************************
+ PROTOTYPES
+*******************************************************************************/
+
+DEVICE_GET_INFO( s3c2400 );
+
+VIDEO_START( s3c2400 );
+SCREEN_UPDATE( s3c2400 );
+
+void s3c2400_uart_fifo_w( device_t *device, int uart, UINT8 data);
+
+/*******************************************************************************
+ MACROS & CONSTANTS
+*******************************************************************************/
+
+/* Interface */
+
+#define S3C24XX_INTERFACE_LCD_REVERSE 1
+
+/* Memory Controller */
+
+#define S3C24XX_BASE_MEMCON 0x14000000
+
+/* USB Host Controller */
+
+#define S3C24XX_BASE_USBHOST 0x14200000
+
+/* Interrupt Controller */
+
+#define S3C24XX_BASE_INT 0x14400000
+
+#define S3C24XX_SRCPND (0x00 / 4) // Interrupt Request Status
+#define S3C24XX_INTMOD (0x04 / 4) // Interrupt Mode Control
+#define S3C24XX_INTMSK (0x08 / 4) // Interrupt Mask Control
+#define S3C24XX_PRIORITY (0x0C / 4) // IRQ Priority Control
+#define S3C24XX_INTPND (0x10 / 4) // Interrupt Request Status
+#define S3C24XX_INTOFFSET (0x14 / 4) // Interrupt Request Source Offset
+
+/* DMA */
+
+#define S3C24XX_BASE_DMA_0 0x14600000
+#define S3C24XX_BASE_DMA_1 0x14600020
+#define S3C24XX_BASE_DMA_2 0x14600040
+#define S3C24XX_BASE_DMA_3 0x14600060
+
+#define S3C24XX_DISRC (0x00 / 4) // DMA Initial Source
+#define S3C24XX_DIDST (0x04 / 4) // DMA Initial Destination
+#define S3C24XX_DCON (0x08 / 4) // DMA Control
+#define S3C24XX_DSTAT (0x0C / 4) // DMA Count
+#define S3C24XX_DCSRC (0x10 / 4) // DMA Current Source Address
+#define S3C24XX_DCDST (0x14 / 4) // DMA Current Destination Address
+#define S3C24XX_DMASKTRIG (0x18 / 4) // DMA Mask Trigger
+
+/* Clock & Power Management */
+
+#define S3C24XX_BASE_CLKPOW 0x14800000
+
+#define S3C24XX_LOCKTIME (0x00 / 4) // PLL Lock Time Counter
+#define S3C24XX_MPLLCON (0x04 / 4) // MPLL Control
+#define S3C24XX_UPLLCON (0x08 / 4) // UPLL Control
+#define S3C24XX_CLKCON (0x0C / 4) // Clock Generator Control
+#define S3C24XX_CLKSLOW (0x10 / 4) // Slow Clock Control
+#define S3C24XX_CLKDIVN (0x14 / 4) // Clock Divider Control
+
+/* LCD Controller */
+
+#define S3C24XX_BASE_LCD 0x14a00000
+#define S3C24XX_BASE_LCDPAL 0x14a00400
+
+#define S3C24XX_LCDCON1 (0x00 / 4) // LCD Control 1
+#define S3C24XX_LCDCON2 (0x04 / 4) // LCD Control 2
+#define S3C24XX_LCDCON3 (0x08 / 4) // LCD Control 3
+#define S3C24XX_LCDCON4 (0x0C / 4) // LCD Control 4
+#define S3C24XX_LCDCON5 (0x10 / 4) // LCD Control 5
+#define S3C24XX_LCDSADDR1 (0x14 / 4) // STN/TFT: Frame Buffer Start Address 1
+#define S3C24XX_LCDSADDR2 (0x18 / 4) // STN/TFT: Frame Buffer Start Address 2
+#define S3C24XX_LCDSADDR3 (0x1C / 4) // STN/TFT: Virtual Screen Address Set
+#define S3C24XX_REDLUT (0x20 / 4) // STN: Red Lookup Table
+#define S3C24XX_GREENLUT (0x24 / 4) // STN: Green Lookup Table
+#define S3C24XX_BLUELUT (0x28 / 4) // STN: Blue Lookup Table
+#define S3C24XX_DITHMODE (0x4C / 4) // STN: Dithering Mode
+#define S3C24XX_TPAL (0x50 / 4) // TFT: Temporary Palette
+
+/* UART */
+
+#define S3C24XX_BASE_UART_0 0x15000000
+#define S3C24XX_BASE_UART_1 0x15004000
+
+#define S3C24XX_ULCON (0x00 / 4) // UART Line Control
+#define S3C24XX_UCON (0x04 / 4) // UART Control
+#define S3C24XX_UFCON (0x08 / 4) // UART FIFO Control
+#define S3C24XX_UMCON (0x0C / 4) // UART Modem Control
+#define S3C24XX_UTRSTAT (0x10 / 4) // UART Tx/Rx Status
+#define S3C24XX_UERSTAT (0x14 / 4) // UART Rx Error Status
+#define S3C24XX_UFSTAT (0x18 / 4) // UART FIFO Status
+#define S3C24XX_UMSTAT (0x1C / 4) // UART Modem Status
+#define S3C24XX_UTXH (0x20 / 4) // UART Transmission Hold
+#define S3C24XX_URXH (0x24 / 4) // UART Receive Buffer
+#define S3C24XX_UBRDIV (0x28 / 4) // UART Baud Rate Divisor
+
+/* PWM Timer */
+
+#define S3C24XX_BASE_PWM 0x15100000
+
+#define S3C24XX_TCFG0 (0x00 / 4) // Timer Configuration
+#define S3C24XX_TCFG1 (0x04 / 4) // Timer Configuration
+#define S3C24XX_TCON (0x08 / 4) // Timer Control
+#define S3C24XX_TCNTB0 (0x0C / 4) // Timer Count Buffer 0
+#define S3C24XX_TCMPB0 (0x10 / 4) // Timer Compare Buffer 0
+#define S3C24XX_TCNTO0 (0x14 / 4) // Timer Count Observation 0
+#define S3C24XX_TCNTB1 (0x18 / 4) // Timer Count Buffer 1
+#define S3C24XX_TCMPB1 (0x1C / 4) // Timer Compare Buffer 1
+#define S3C24XX_TCNTO1 (0x20 / 4) // Timer Count Observation 1
+#define S3C24XX_TCNTB2 (0x24 / 4) // Timer Count Buffer 2
+#define S3C24XX_TCMPB2 (0x28 / 4) // Timer Compare Buffer 2
+#define S3C24XX_TCNTO2 (0x2C / 4) // Timer Count Observation 2
+#define S3C24XX_TCNTB3 (0x30 / 4) // Timer Count Buffer 3
+#define S3C24XX_TCMPB3 (0x34 / 4) // Timer Compare Buffer 3
+#define S3C24XX_TCNTO3 (0x38 / 4) // Timer Count Observation 3
+#define S3C24XX_TCNTB4 (0x3C / 4) // Timer Count Buffer 4
+#define S3C24XX_TCNTO4 (0x40 / 4) // Timer Count Observation 4
+
+/* USB Device */
+
+#define S3C24XX_BASE_USBDEV 0x15200140
+
+/* Watchdog Timer */
+
+#define S3C24XX_BASE_WDT 0x15300000
+
+#define S3C24XX_WTCON (0x00 / 4) // Watchdog Timer Mode
+#define S3C24XX_WTDAT (0x04 / 4) // Watchdog Timer Data
+#define S3C24XX_WTCNT (0x08 / 4) // Watchdog Timer Count
+
+/* IIC */
+
+#define S3C24XX_BASE_IIC 0x15400000
+
+#define S3C24XX_IICCON (0x00 / 4) // IIC Control
+#define S3C24XX_IICSTAT (0x04 / 4) // IIC Status
+#define S3C24XX_IICADD (0x08 / 4) // IIC Address
+#define S3C24XX_IICDS (0x0C / 4) // IIC Data Shift
+
+/* IIS */
+
+#define S3C24XX_BASE_IIS 0x15508000
+
+#define S3C24XX_IISCON (0x00 / 4) // IIS Control
+#define S3C24XX_IISMOD (0x04 / 4) // IIS Mode
+#define S3C24XX_IISPSR (0x08 / 4) // IIS Prescaler
+#define S3C24XX_IISFCON (0x0C / 4) // IIS FIFO Control
+#define S3C24XX_IISFIFO (0x10 / 4) // IIS FIFO Entry
+
+/* I/O Port */
+
+#define S3C24XX_BASE_GPIO 0x15600000
+
+#define S3C24XX_GPACON (0x00 / 4) // Port A Control
+#define S3C24XX_GPADAT (0x04 / 4) // Port A Data
+#define S3C24XX_GPBCON (0x08 / 4) // Port B Control
+#define S3C24XX_GPBDAT (0x0C / 4) // Port B Data
+#define S3C24XX_GPBUP (0x10 / 4) // Pull-up Control B
+#define S3C24XX_GPCCON (0x14 / 4) // Port C Control
+#define S3C24XX_GPCDAT (0x18 / 4) // Port C Data
+#define S3C24XX_GPCUP (0x1C / 4) // Pull-up Control C
+#define S3C24XX_GPDCON (0x20 / 4) // Port D Control
+#define S3C24XX_GPDDAT (0x24 / 4) // Port D Data
+#define S3C24XX_GPDUP (0x28 / 4) // Pull-up Control D
+#define S3C24XX_GPECON (0x2C / 4) // Port E Control
+#define S3C24XX_GPEDAT (0x30 / 4) // Port E Data
+#define S3C24XX_GPEUP (0x34 / 4) // Pull-up Control E
+#define S3C24XX_GPFCON (0x38 / 4) // Port F Control
+#define S3C24XX_GPFDAT (0x3C / 4) // Port F Data
+#define S3C24XX_GPFUP (0x40 / 4) // Pull-up Control F
+#define S3C24XX_GPGCON (0x44 / 4) // Port G Control
+#define S3C24XX_GPGDAT (0x48 / 4) // Port G Data
+#define S3C24XX_GPGUP (0x4C / 4) // Pull-up Control G
+#define S3C24XX_OPENCR (0x50 / 4) // Open Drain Enable
+#define S3C24XX_MISCCR (0x54 / 4) // Miscellaneous Control
+#define S3C24XX_EXTINT (0x58 / 4) // External Interrupt Control
+
+#define S3C24XX_GPADAT_MASK 0x0003FFFF
+#define S3C24XX_GPBDAT_MASK 0x0000FFFF
+#define S3C24XX_GPCDAT_MASK 0x0000FFFF
+#define S3C24XX_GPDDAT_MASK 0x000007FF
+#define S3C24XX_GPEDAT_MASK 0x00000FFF
+#define S3C24XX_GPFDAT_MASK 0x0000007F
+#define S3C24XX_GPGDAT_MASK 0x000003FF
+
+/* RTC */
+
+#define S3C24XX_BASE_RTC 0x15700040
+
+#define S3C24XX_RTCCON (0x00 / 4) // RTC Control
+#define S3C24XX_TICNT (0x04 / 4) // Tick Time count
+#define S3C24XX_RTCALM (0x10 / 4) // RTC Alarm Control
+#define S3C24XX_ALMSEC (0x14 / 4) // Alarm Second
+#define S3C24XX_ALMMIN (0x18 / 4) // Alarm Minute
+#define S3C24XX_ALMHOUR (0x1C / 4) // Alarm Hour
+#define S3C24XX_ALMDAY (0x20 / 4) // Alarm Day
+#define S3C24XX_ALMMON (0x24 / 4) // Alarm Month
+#define S3C24XX_ALMYEAR (0x28 / 4) // Alarm Year
+#define S3C24XX_RTCRST (0x2C / 4) // RTC Round Reset
+#define S3C24XX_BCDSEC (0x30 / 4) // BCD Second
+#define S3C24XX_BCDMIN (0x34 / 4) // BCD Minute
+#define S3C24XX_BCDHOUR (0x38 / 4) // BCD Hour
+#define S3C24XX_BCDDAY (0x3C / 4) // BCD Day
+#define S3C24XX_BCDDOW (0x40 / 4) // BCD Day of Week
+#define S3C24XX_BCDMON (0x44 / 4) // BCD Month
+#define S3C24XX_BCDYEAR (0x48 / 4) // BCD Year
+
+/* A/D Converter */
+
+#define S3C24XX_BASE_ADC 0x15800000
+
+#define S3C24XX_ADCCON (0x00 / 4) // ADC Control
+#define S3C24XX_ADCDAT (0x04 / 4) // ADC Data
+
+/* SPI */
+
+#define S3C24XX_BASE_SPI_0 0x15900000
+
+#define S3C24XX_SPCON (0x00 / 4) // SPI Control
+#define S3C24XX_SPSTA (0x04 / 4) // SPI Status
+#define S3C24XX_SPPIN (0x08 / 4) // SPI Pin Control
+#define S3C24XX_SPPRE (0x0C / 4) // SPI Baud Rate Prescaler
+#define S3C24XX_SPTDAT (0x10 / 4) // SPI Tx Data
+#define S3C24XX_SPRDAT (0x14 / 4) // SPI Rx Data
+
+/* MMC Interface */
+
+#define S3C24XX_BASE_MMC 0x15a00000
+
+/* ... */
+
+#define S3C24XX_INT_ADC 31
+#define S3C24XX_INT_RTC 30
+#define S3C24XX_INT_UTXD1 29
+#define S3C24XX_INT_UTXD0 28
+#define S3C24XX_INT_IIC 27
+#define S3C24XX_INT_USBH 26
+#define S3C24XX_INT_USBD 25
+#define S3C24XX_INT_URXD1 24
+#define S3C24XX_INT_URXD0 23
+#define S3C24XX_INT_SPI 22
+#define S3C24XX_INT_MMC 21
+#define S3C24XX_INT_DMA3 20
+#define S3C24XX_INT_DMA2 19
+#define S3C24XX_INT_DMA1 18
+#define S3C24XX_INT_DMA0 17
+#define S3C24XX_INT_RESERVED 16
+#define S3C24XX_INT_UERR 15
+#define S3C24XX_INT_TIMER4 14
+#define S3C24XX_INT_TIMER3 13
+#define S3C24XX_INT_TIMER2 12
+#define S3C24XX_INT_TIMER1 11
+#define S3C24XX_INT_TIMER0 10
+#define S3C24XX_INT_WDT 9
+#define S3C24XX_INT_TICK 8
+#define S3C24XX_INT_EINT7 7
+#define S3C24XX_INT_EINT6 6
+#define S3C24XX_INT_EINT5 5
+#define S3C24XX_INT_EINT4 4
+#define S3C24XX_INT_EINT3 3
+#define S3C24XX_INT_EINT2 2
+#define S3C24XX_INT_EINT1 1
+#define S3C24XX_INT_EINT0 0
+
+#define S3C24XX_BPPMODE_STN_01 0x00
+#define S3C24XX_BPPMODE_STN_02 0x01
+#define S3C24XX_BPPMODE_STN_04 0x02
+#define S3C24XX_BPPMODE_STN_08 0x03
+#define S3C24XX_BPPMODE_STN_12_P 0x04
+#define S3C24XX_BPPMODE_STN_12_U 0x05
+#define S3C24XX_BPPMODE_STN_16 0x06
+#define S3C24XX_BPPMODE_TFT_01 0x08
+#define S3C24XX_BPPMODE_TFT_02 0x09
+#define S3C24XX_BPPMODE_TFT_04 0x0A
+#define S3C24XX_BPPMODE_TFT_08 0x0B
+#define S3C24XX_BPPMODE_TFT_16 0x0C
+#define S3C24XX_BPPMODE_TFT_24 0x0D
+
+#define S3C24XX_PNRMODE_STN_04_DS 0
+#define S3C24XX_PNRMODE_STN_04_SS 1
+#define S3C24XX_PNRMODE_STN_08_SS 2
+#define S3C24XX_PNRMODE_TFT 3
+
+#define S3C24XX_GPIO_PORT_A S3C2400_GPIO_PORT_A
+#define S3C24XX_GPIO_PORT_B S3C2400_GPIO_PORT_B
+#define S3C24XX_GPIO_PORT_C S3C2400_GPIO_PORT_C
+#define S3C24XX_GPIO_PORT_D S3C2400_GPIO_PORT_D
+#define S3C24XX_GPIO_PORT_E S3C2400_GPIO_PORT_E
+#define S3C24XX_GPIO_PORT_F S3C2400_GPIO_PORT_F
+#define S3C24XX_GPIO_PORT_G S3C2400_GPIO_PORT_G
+
+/*******************************************************************************
+ TYPE DEFINITIONS
+*******************************************************************************/
+
+typedef struct
+{
+ UINT32 data[0x34/4];
+} s3c24xx_memcon_regs_t;
+
+typedef struct
+{
+ UINT32 data[0x5C/4];
+} s3c24xx_usbhost_regs_t;
+
+typedef struct
+{
+ UINT32 srcpnd;
+ UINT32 intmod;
+ UINT32 intmsk;
+ UINT32 priority;
+ UINT32 intpnd;
+ UINT32 intoffset;
+} s3c24xx_irq_regs_t;
+
+typedef struct
+{
+ UINT32 disrc;
+ UINT32 didst;
+ UINT32 dcon;
+ UINT32 dstat;
+ UINT32 dcsrc;
+ UINT32 dcdst;
+ UINT32 dmasktrig;
+} s3c24xx_dma_regs_t;
+
+typedef struct
+{
+ UINT32 locktime;
+ UINT32 mpllcon;
+ UINT32 upllcon;
+ UINT32 clkcon;
+ UINT32 clkslow;
+ UINT32 clkdivn;
+} s3c24xx_clkpow_regs_t;
+
+typedef struct
+{
+ UINT32 lcdcon1;
+ UINT32 lcdcon2;
+ UINT32 lcdcon3;
+ UINT32 lcdcon4;
+ UINT32 lcdcon5;
+ UINT32 lcdsaddr1;
+ UINT32 lcdsaddr2;
+ UINT32 lcdsaddr3;
+ UINT32 redlut;
+ UINT32 greenlut;
+ UINT32 bluelut;
+ UINT32 reserved[8];
+ UINT32 dithmode;
+ UINT32 tpal;
+} s3c24xx_lcd_regs_t;
+
+typedef struct
+{
+ UINT32 data[0x400/4];
+} s3c24xx_lcdpal_regs_t;
+
+typedef struct
+{
+ UINT32 ulcon;
+ UINT32 ucon;
+ UINT32 ufcon;
+ UINT32 umcon;
+ UINT32 utrstat;
+ UINT32 uerstat;
+ UINT32 ufstat;
+ UINT32 umstat;
+ UINT32 utxh;
+ UINT32 urxh;
+ UINT32 ubrdiv;
+} s3c24xx_uart_regs_t;
+
+typedef struct
+{
+ UINT32 tcfg0;
+ UINT32 tcfg1;
+ UINT32 tcon;
+ UINT32 tcntb0;
+ UINT32 tcmpb0;
+ UINT32 tcnto0;
+ UINT32 tcntb1;
+ UINT32 tcmpb1;
+ UINT32 tcnto1;
+ UINT32 tcntb2;
+ UINT32 tcmpb2;
+ UINT32 tcnto2;
+ UINT32 tcntb3;
+ UINT32 tcmpb3;
+ UINT32 tcnto3;
+ UINT32 tcntb4;
+ UINT32 tcnto4;
+} s3c24xx_pwm_regs_t;
+
+typedef struct
+{
+ UINT32 data[0xBC/4];
+} s3c24xx_usbdev_regs_t;
+
+typedef struct
+{
+ UINT32 wtcon;
+ UINT32 wtdat;
+ UINT32 wtcnt;
+} s3c24xx_wdt_regs_t;
+
+typedef struct
+{
+ UINT32 iiccon;
+ UINT32 iicstat;
+ UINT32 iicadd;
+ UINT32 iicds;
+} s3c24xx_iic_regs_t;
+
+typedef struct
+{
+ UINT32 iiscon;
+ UINT32 iismod;
+ UINT32 iispsr;
+ UINT32 iisfcon;
+ UINT32 iisfifo;
+} s3c24xx_iis_regs_t;
+
+typedef struct
+{
+ UINT32 gpacon;
+ UINT32 gpadat;
+ UINT32 gpbcon;
+ UINT32 gpbdat;
+ UINT32 gpbup;
+ UINT32 gpccon;
+ UINT32 gpcdat;
+ UINT32 gpcup;
+ UINT32 gpdcon;
+ UINT32 gpddat;
+ UINT32 gpdup;
+ UINT32 gpecon;
+ UINT32 gpedat;
+ UINT32 gpeup;
+ UINT32 gpfcon;
+ UINT32 gpfdat;
+ UINT32 gpfup;
+ UINT32 gpgcon;
+ UINT32 gpgdat;
+ UINT32 gpgup;
+ UINT32 opencr;
+ UINT32 misccr;
+ UINT32 extint;
+} s3c24xx_gpio_regs_t;
+
+typedef struct
+{
+ UINT32 rtccon;
+ UINT32 ticnt;
+ UINT32 reserved[2];
+ UINT32 rtcalm;
+ UINT32 almsec;
+ UINT32 almmin;
+ UINT32 almhour;
+ UINT32 almday;
+ UINT32 almmon;
+ UINT32 almyear;
+ UINT32 rtcrst;
+ UINT32 bcdsec;
+ UINT32 bcdmin;
+ UINT32 bcdhour;
+ UINT32 bcdday;
+ UINT32 bcddow;
+ UINT32 bcdmon;
+ UINT32 bcdyear;
+} s3c24xx_rtc_regs_t;
+
+typedef struct
+{
+ UINT32 adccon;
+ UINT32 adcdat;
+} s3c24xx_adc_regs_t;
+
+typedef struct
+{
+ UINT32 spcon;
+ UINT32 spsta;
+ UINT32 sppin;
+ UINT32 sppre;
+ UINT32 sptdat;
+ UINT32 sprdat;
+} s3c24xx_spi_regs_t;
+
+typedef struct
+{
+ UINT32 data[0x40/4];
+} s3c24xx_mmc_regs_t;
+
+typedef struct
+{
+ s3c24xx_memcon_regs_t regs;
+} s3c24xx_memcon_t;
+
+typedef struct
+{
+ s3c24xx_usbhost_regs_t regs;
+} s3c24xx_usbhost_t;
+
+typedef struct
+{
+ s3c24xx_irq_regs_t regs;
+ int line_irq, line_fiq;
+} s3c24xx_irq_t;
+
+typedef struct
+{
+ s3c24xx_dma_regs_t regs;
+ emu_timer *timer;
+} s3c24xx_dma_t;
+
+typedef struct
+{
+ s3c24xx_clkpow_regs_t regs;
+} s3c24xx_clkpow_t;
+
+typedef struct
+{
+ s3c24xx_lcd_regs_t regs;
+ emu_timer *timer;
+ bitmap_t *bitmap[2];
+ UINT32 vramaddr_cur;
+ UINT32 vramaddr_max;
+ UINT32 offsize;
+ UINT32 pagewidth_cur;
+ UINT32 pagewidth_max;
+ UINT32 bppmode;
+ UINT32 bswp, hwswp;
+ int vpos, hpos;
+ double framerate;
+ UINT32 tpal;
+ UINT32 hpos_min, hpos_max, vpos_min, vpos_max;
+ UINT32 dma_data, dma_bits;
+} s3c24xx_lcd_t;
+
+typedef struct
+{
+ s3c24xx_lcdpal_regs_t regs;
+} s3c24xx_lcdpal_t;
+
+typedef struct
+{
+ s3c24xx_uart_regs_t regs;
+} s3c24xx_uart_t;
+
+typedef struct
+{
+ s3c24xx_pwm_regs_t regs;
+ emu_timer *timer[5];
+ UINT32 cnt[5];
+ UINT32 cmp[5];
+ UINT32 freq[5];
+} s3c24xx_pwm_t;
+
+typedef struct
+{
+ s3c24xx_usbdev_regs_t regs;
+} s3c24xx_usbdev_t;
+
+typedef struct
+{
+ s3c24xx_wdt_regs_t regs;
+ emu_timer *timer;
+} s3c24xx_wdt_t;
+
+typedef struct
+{
+ s3c24xx_iic_regs_t regs;
+ emu_timer *timer;
+ int count;
+} s3c24xx_iic_t;
+
+typedef struct
+{
+ s3c24xx_iis_regs_t regs;
+ emu_timer *timer;
+ UINT16 fifo[16/2];
+ int fifo_index;
+} s3c24xx_iis_t;
+
+typedef struct
+{
+ s3c24xx_gpio_regs_t regs;
+} s3c24xx_gpio_t;
+
+typedef struct
+{
+ s3c24xx_rtc_regs_t regs;
+ emu_timer *timer_tick_count;
+ emu_timer *timer_update;
+} s3c24xx_rtc_t;
+
+typedef struct
+{
+ s3c24xx_adc_regs_t regs;
+} s3c24xx_adc_t;
+
+typedef struct
+{
+ s3c24xx_spi_regs_t regs;
+} s3c24xx_spi_t;
+
+typedef struct
+{
+ s3c24xx_mmc_regs_t regs;
+} s3c24xx_mmc_t;
+
+typedef struct
+{
+ const s3c2400_interface *iface;
+ s3c24xx_memcon_t memcon;
+ s3c24xx_usbhost_t usbhost;
+ s3c24xx_irq_t irq;
+ s3c24xx_dma_t dma[4];
+ s3c24xx_clkpow_t clkpow;
+ s3c24xx_lcd_t lcd;
+ s3c24xx_lcdpal_t lcdpal;
+ s3c24xx_uart_t uart[2];
+ s3c24xx_pwm_t pwm;
+ s3c24xx_usbdev_t usbdev;
+ s3c24xx_wdt_t wdt;
+ s3c24xx_iic_t iic;
+ s3c24xx_iis_t iis;
+ s3c24xx_gpio_t gpio;
+ s3c24xx_rtc_t rtc;
+ s3c24xx_adc_t adc;
+ s3c24xx_spi_t spi[1];
+ s3c24xx_mmc_t mmc;
+} s3c24xx_t;
+
+#endif
diff --git a/trunk/src/emu/machine/s3c2410.c b/trunk/src/emu/machine/s3c2410.c
new file mode 100644
index 00000000000..9dee05b1fbf
--- /dev/null
+++ b/trunk/src/emu/machine/s3c2410.c
@@ -0,0 +1,116 @@
+/*******************************************************************************
+
+ Samsung S3C2410
+
+ (c) 2010 Tim Schuerewegen
+
+*******************************************************************************/
+
+#include "emu.h"
+#include "cpu/arm7/arm7.h"
+#include "cpu/arm7/arm7core.h"
+#include "machine/s3c2410.h"
+#include "sound/dac.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);
+ }
+}
+
+#define DEVICE_S3C2410
+#include "machine/s3c24xx.c"
+#undef DEVICE_S3C2410
+
+VIDEO_START( s3c2410 )
+{
+ device_t *device = machine.device( S3C2410_TAG);
+ s3c24xx_video_start( device, machine);
+}
+
+SCREEN_UPDATE( s3c2410 )
+{
+ device_t *device = screen->machine().device( S3C2410_TAG);
+ return s3c24xx_video_update( device, screen, bitmap, cliprect);
+}
+
+DEVICE_START( s3c2410 )
+{
+ address_space *space = device->machine().device( "maincpu")->memory().space( AS_PROGRAM);
+ DEVICE_START_CALL(s3c24xx);
+ space->install_legacy_readwrite_handler( *device, 0x48000000, 0x4800003b, FUNC(s3c24xx_memcon_r), FUNC(s3c24xx_memcon_w));
+ space->install_legacy_readwrite_handler( *device, 0x49000000, 0x4900005b, FUNC(s3c24xx_usb_host_r), FUNC(s3c24xx_usb_host_w));
+ space->install_legacy_readwrite_handler( *device, 0x4a000000, 0x4a00001f, FUNC(s3c24xx_irq_r), FUNC(s3c24xx_irq_w));
+ space->install_legacy_readwrite_handler( *device, 0x4b000000, 0x4b000023, FUNC(s3c24xx_dma_0_r), FUNC(s3c24xx_dma_0_w));
+ space->install_legacy_readwrite_handler( *device, 0x4b000040, 0x4b000063, FUNC(s3c24xx_dma_1_r), FUNC(s3c24xx_dma_1_w));
+ space->install_legacy_readwrite_handler( *device, 0x4b000080, 0x4b0000a3, FUNC(s3c24xx_dma_2_r), FUNC(s3c24xx_dma_2_w));
+ space->install_legacy_readwrite_handler( *device, 0x4b0000c0, 0x4b0000e3, FUNC(s3c24xx_dma_3_r), FUNC(s3c24xx_dma_3_w));
+ space->install_legacy_readwrite_handler( *device, 0x4c000000, 0x4c000017, FUNC(s3c24xx_clkpow_r), FUNC(s3c24xx_clkpow_w));
+ space->install_legacy_readwrite_handler( *device, 0x4d000000, 0x4d000063, FUNC(s3c2410_lcd_r), FUNC(s3c24xx_lcd_w));
+ space->install_legacy_readwrite_handler( *device, 0x4d000400, 0x4d0007ff, FUNC(s3c24xx_lcd_palette_r), FUNC(s3c24xx_lcd_palette_w));
+ space->install_legacy_readwrite_handler( *device, 0x4e000000, 0x4e000017, FUNC(s3c24xx_nand_r), FUNC(s3c24xx_nand_w));
+ space->install_legacy_readwrite_handler( *device, 0x50000000, 0x5000002b, FUNC(s3c24xx_uart_0_r), FUNC(s3c24xx_uart_0_w));
+ space->install_legacy_readwrite_handler( *device, 0x50004000, 0x5000402b, FUNC(s3c24xx_uart_1_r), FUNC(s3c24xx_uart_1_w));
+ space->install_legacy_readwrite_handler( *device, 0x50008000, 0x5000802b, FUNC(s3c24xx_uart_2_r), FUNC(s3c24xx_uart_2_w));
+ space->install_legacy_readwrite_handler( *device, 0x51000000, 0x51000043, FUNC(s3c24xx_pwm_r), FUNC(s3c24xx_pwm_w));
+ space->install_legacy_readwrite_handler( *device, 0x52000140, 0x5200026f, FUNC(s3c24xx_usb_device_r), FUNC(s3c24xx_usb_device_w));
+ space->install_legacy_readwrite_handler( *device, 0x53000000, 0x5300000b, FUNC(s3c24xx_wdt_r), FUNC(s3c24xx_wdt_w));
+ space->install_legacy_readwrite_handler( *device, 0x54000000, 0x5400000f, FUNC(s3c24xx_iic_r), FUNC(s3c24xx_iic_w));
+ space->install_legacy_readwrite_handler( *device, 0x55000000, 0x55000013, FUNC(s3c24xx_iis_r), FUNC(s3c24xx_iis_w));
+ space->install_legacy_readwrite_handler( *device, 0x56000000, 0x560000bf, FUNC(s3c24xx_gpio_r), FUNC(s3c24xx_gpio_w));
+ space->install_legacy_readwrite_handler( *device, 0x57000040, 0x5700008b, FUNC(s3c24xx_rtc_r), FUNC(s3c24xx_rtc_w));
+ space->install_legacy_readwrite_handler( *device, 0x58000000, 0x58000013, FUNC(s3c24xx_adc_r), FUNC(s3c24xx_adc_w));
+ space->install_legacy_readwrite_handler( *device, 0x59000000, 0x59000017, FUNC(s3c24xx_spi_0_r), FUNC(s3c24xx_spi_0_w));
+ space->install_legacy_readwrite_handler( *device, 0x59000020, 0x59000037, FUNC(s3c24xx_spi_1_r), FUNC(s3c24xx_spi_1_w));
+ space->install_legacy_readwrite_handler( *device, 0x5a000000, 0x5a000043, FUNC(s3c24xx_sdi_r), FUNC(s3c24xx_sdi_w));
+}
+
+DEVICE_GET_INFO( s3c2410 )
+{
+ switch ( state )
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(s3c2410); break;
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Samsung S3C2410"); break;
+ /* --- default --- */
+ default: DEVICE_GET_INFO_CALL(s3c24xx); break;
+ }
+}
+
+void s3c2410_uart_fifo_w( device_t *device, int uart, UINT8 data)
+{
+ s3c24xx_uart_fifo_w( device, uart, data);
+}
+
+void s3c2410_touch_screen( device_t *device, int state)
+{
+ s3c24xx_touch_screen( device, state);
+}
+
+WRITE_LINE_DEVICE_HANDLER( s3c2410_pin_frnb_w )
+{
+ s3c24xx_pin_frnb_w( device, state);
+}
+
+void s3c2410_nand_calculate_mecc( UINT8 *data, UINT32 size, UINT8 *mecc)
+{
+ mecc[0] = mecc[1] = mecc[2] = mecc[3] = 0;
+ for (int i = 0; i < size; i++) nand_update_mecc( mecc, i, data[i]);
+}
+
+void s3c2410_request_eint( device_t *device, UINT32 number)
+{
+ s3c24xx_request_eint( device, number);
+}
+
+DEFINE_LEGACY_DEVICE(S3C2410, s3c2410);
diff --git a/trunk/src/emu/machine/s3c2410.h b/trunk/src/emu/machine/s3c2410.h
new file mode 100644
index 00000000000..65e07951941
--- /dev/null
+++ b/trunk/src/emu/machine/s3c2410.h
@@ -0,0 +1,863 @@
+/*******************************************************************************
+
+ Samsung S3C2410
+
+*******************************************************************************/
+
+#ifndef __S3C2410_H__
+#define __S3C2410_H__
+
+#include "devlegcy.h"
+
+/*******************************************************************************
+ MACROS / CONSTANTS
+*******************************************************************************/
+
+#define S3C2410_TAG "s3c2410"
+
+#define MCFG_S3C2410_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD(_tag, S3C2410, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define S3C2410_INTERFACE(name) \
+ const s3c2410_interface(name) =
+
+enum
+{
+ S3C2410_GPIO_PORT_A = 0,
+ S3C2410_GPIO_PORT_B,
+ S3C2410_GPIO_PORT_C,
+ S3C2410_GPIO_PORT_D,
+ S3C2410_GPIO_PORT_E,
+ S3C2410_GPIO_PORT_F,
+ S3C2410_GPIO_PORT_G,
+ S3C2410_GPIO_PORT_H
+};
+
+DECLARE_LEGACY_DEVICE(S3C2410, s3c2410);
+
+READ32_DEVICE_HANDLER( s3c2410_lcd_r );
+
+/*******************************************************************************
+ TYPE DEFINITIONS
+*******************************************************************************/
+
+typedef UINT32 (*s3c24xx_gpio_port_r_func)( device_t *device, int port);
+typedef void (*s3c24xx_gpio_port_w_func)( device_t *device, int port, UINT32 data);
+
+typedef struct _s3c2410_interface_gpio s3c2410_interface_gpio;
+struct _s3c2410_interface_gpio
+{
+ s3c24xx_gpio_port_r_func port_r;
+ s3c24xx_gpio_port_w_func port_w;
+};
+
+typedef struct _s3c2410_interface_i2c s3c2410_interface_i2c;
+struct _s3c2410_interface_i2c
+{
+ write_line_device_func scl_w;
+ read_line_device_func sda_r;
+ write_line_device_func sda_w;
+};
+
+typedef struct _s3c2410_interface_adc s3c2410_interface_adc;
+struct _s3c2410_interface_adc
+{
+ read32_device_func data_r;
+};
+
+typedef struct _s3c2410_interface_i2s s3c2410_interface_i2s;
+struct _s3c2410_interface_i2s
+{
+ write16_device_func data_w;
+};
+
+typedef struct _s3c2410_interface_nand s3c2410_interface_nand;
+struct _s3c2410_interface_nand
+{
+ write8_device_func command_w;
+ write8_device_func address_w;
+ read8_device_func data_r;
+ write8_device_func data_w;
+};
+
+typedef struct _s3c2410_interface_lcd s3c2410_interface_lcd;
+struct _s3c2410_interface_lcd
+{
+ int flags;
+};
+
+typedef struct _s3c2410_interface s3c2410_interface;
+struct _s3c2410_interface
+{
+ s3c2410_interface_gpio gpio;
+ s3c2410_interface_i2c i2c;
+ s3c2410_interface_adc adc;
+ s3c2410_interface_i2s i2s;
+ s3c2410_interface_nand nand;
+ s3c2410_interface_lcd lcd;
+};
+
+/*******************************************************************************
+ PROTOTYPES
+*******************************************************************************/
+
+DEVICE_GET_INFO( s3c2410 );
+
+VIDEO_START( s3c2410 );
+SCREEN_UPDATE( s3c2410 );
+
+void s3c2410_uart_fifo_w( device_t *device, int uart, UINT8 data);
+void s3c2410_touch_screen( device_t *device, int state);
+void s3c2410_request_eint( device_t *device, UINT32 number);
+
+WRITE_LINE_DEVICE_HANDLER( s3c2410_pin_frnb_w );
+
+void s3c2410_nand_calculate_mecc( UINT8 *data, UINT32 size, UINT8 *mecc);
+
+/*******************************************************************************
+ MACROS & CONSTANTS
+*******************************************************************************/
+
+/* Interface */
+
+#define S3C24XX_INTERFACE_LCD_REVERSE 1
+
+/* Memory Controller */
+
+#define S3C24XX_BASE_MEMCON 0x48000000
+
+/* USB Host Controller */
+
+#define S3C24XX_BASE_USBHOST 0x49000000
+
+/* Interrupt Controller */
+
+#define S3C24XX_BASE_INT 0x4A000000
+
+#define S3C24XX_SRCPND (0x00 / 4) // Interrupt Request Status
+#define S3C24XX_INTMOD (0x04 / 4) // Interrupt Mode Control
+#define S3C24XX_INTMSK (0x08 / 4) // Interrupt Mask Control
+#define S3C24XX_PRIORITY (0x0C / 4) // IRQ Priority Control
+#define S3C24XX_INTPND (0x10 / 4) // Interrupt Request Status
+#define S3C24XX_INTOFFSET (0x14 / 4) // Interrupt Request Source Offset
+#define S3C24XX_SUBSRCPND (0x18 / 4) // Sub Source Pending
+#define S3C24XX_INTSUBMSK (0x1C / 4) // Interrupt Sub Mask
+
+/* DMA */
+
+#define S3C24XX_BASE_DMA_0 0x4B000000
+#define S3C24XX_BASE_DMA_1 0x4B000040
+#define S3C24XX_BASE_DMA_2 0x4B000080
+#define S3C24XX_BASE_DMA_3 0x4B0000C0
+
+#define S3C24XX_DISRC (0x00 / 4) // DMA Initial Source
+#define S3C24XX_DISRCC (0x04 / 4) // DMA Initial Source Control
+#define S3C24XX_DIDST (0x08 / 4) // DMA Initial Destination
+#define S3C24XX_DIDSTC (0x0C / 4) // DMA Initial Destination Control
+#define S3C24XX_DCON (0x10 / 4) // DMA Control
+#define S3C24XX_DSTAT (0x14 / 4) // DMA Count
+#define S3C24XX_DCSRC (0x18 / 4) // DMA Current Source
+#define S3C24XX_DCDST (0x1C / 4) // DMA Current Destination
+#define S3C24XX_DMASKTRIG (0x20 / 4) // DMA Mask Trigger
+
+/* Clock & Power Management */
+
+#define S3C24XX_BASE_CLKPOW 0x4C000000
+
+#define S3C24XX_LOCKTIME (0x00 / 4) // PLL Lock Time Counter
+#define S3C24XX_MPLLCON (0x04 / 4) // MPLL Control
+#define S3C24XX_UPLLCON (0x08 / 4) // UPLL Control
+#define S3C24XX_CLKCON (0x0C / 4) // Clock Generator Control
+#define S3C24XX_CLKSLOW (0x10 / 4) // Slow Clock Control
+#define S3C24XX_CLKDIVN (0x14 / 4) // Clock Divider Control
+
+/* LCD Controller */
+
+#define S3C24XX_BASE_LCD 0x4D000000
+#define S3C24XX_BASE_LCDPAL 0x4D000400
+
+#define S3C24XX_LCDCON1 (0x00 / 4) // LCD Control 1
+#define S3C24XX_LCDCON2 (0x04 / 4) // LCD Control 2
+#define S3C24XX_LCDCON3 (0x08 / 4) // LCD Control 3
+#define S3C24XX_LCDCON4 (0x0C / 4) // LCD Control 4
+#define S3C24XX_LCDCON5 (0x10 / 4) // LCD Control 5
+#define S3C24XX_LCDSADDR1 (0x14 / 4) // STN/TFT: Frame Buffer Start Address 1
+#define S3C24XX_LCDSADDR2 (0x18 / 4) // STN/TFT: Frame Buffer Start Address 2
+#define S3C24XX_LCDSADDR3 (0x1C / 4) // STN/TFT: Virtual Screen Address Set
+#define S3C24XX_REDLUT (0x20 / 4) // STN: Red Lookup Table
+#define S3C24XX_GREENLUT (0x24 / 4) // STN: Green Lookup Table
+#define S3C24XX_BLUELUT (0x28 / 4) // STN: Blue Lookup Table
+#define S3C24XX_DITHMODE (0x4C / 4) // STN: Dithering Mode
+#define S3C24XX_TPAL (0x50 / 4) // TFT: Temporary Palette
+#define S3C24XX_LCDINTPND (0x54 / 4) // LCD Interrupt Pending
+#define S3C24XX_LCDSRCPND (0x58 / 4) // LCD Interrupt Source
+#define S3C24XX_LCDINTMSK (0x5C / 4) // LCD Interrupt Mask
+#define S3C24XX_LPCSEL (0x60 / 4) // LPC3600 Control
+
+/* NAND Flash */
+
+#define S3C24XX_BASE_NAND 0x4E000000
+
+#define S3C24XX_NFCONF (0x00 / 4) // NAND Flash Configuration
+#define S3C24XX_NFCMD (0x04 / 4) // NAND Flash Command
+#define S3C24XX_NFADDR (0x08 / 4) // NAND Flash Address
+#define S3C24XX_NFDATA (0x0C / 4) // NAND Flash Data
+#define S3C24XX_NFSTAT (0x10 / 4) // NAND Flash Operation Status
+#define S3C24XX_NFECC (0x14 / 4) // NAND Flash ECC
+
+/* UART */
+
+#define S3C24XX_BASE_UART_0 0x50000000
+#define S3C24XX_BASE_UART_1 0x50004000
+#define S3C24XX_BASE_UART_2 0x50008000
+
+#define S3C24XX_ULCON (0x00 / 4) // UART Line Control
+#define S3C24XX_UCON (0x04 / 4) // UART Control
+#define S3C24XX_UFCON (0x08 / 4) // UART FIFO Control
+#define S3C24XX_UMCON (0x0C / 4) // UART Modem Control
+#define S3C24XX_UTRSTAT (0x10 / 4) // UART Tx/Rx Status
+#define S3C24XX_UERSTAT (0x14 / 4) // UART Rx Error Status
+#define S3C24XX_UFSTAT (0x18 / 4) // UART FIFO Status
+#define S3C24XX_UMSTAT (0x1C / 4) // UART Modem Status
+#define S3C24XX_UTXH (0x20 / 4) // UART Transmission Hold
+#define S3C24XX_URXH (0x24 / 4) // UART Receive Buffer
+#define S3C24XX_UBRDIV (0x28 / 4) // UART Baud Rate Divisor
+
+/* PWM Timer */
+
+#define S3C24XX_BASE_PWM 0x51000000
+
+#define S3C24XX_TCFG0 (0x00 / 4) // Timer Configuration
+#define S3C24XX_TCFG1 (0x04 / 4) // Timer Configuration
+#define S3C24XX_TCON (0x08 / 4) // Timer Control
+#define S3C24XX_TCNTB0 (0x0C / 4) // Timer Count Buffer 0
+#define S3C24XX_TCMPB0 (0x10 / 4) // Timer Compare Buffer 0
+#define S3C24XX_TCNTO0 (0x14 / 4) // Timer Count Observation 0
+#define S3C24XX_TCNTB1 (0x18 / 4) // Timer Count Buffer 1
+#define S3C24XX_TCMPB1 (0x1C / 4) // Timer Compare Buffer 1
+#define S3C24XX_TCNTO1 (0x20 / 4) // Timer Count Observation 1
+#define S3C24XX_TCNTB2 (0x24 / 4) // Timer Count Buffer 2
+#define S3C24XX_TCMPB2 (0x28 / 4) // Timer Compare Buffer 2
+#define S3C24XX_TCNTO2 (0x2C / 4) // Timer Count Observation 2
+#define S3C24XX_TCNTB3 (0x30 / 4) // Timer Count Buffer 3
+#define S3C24XX_TCMPB3 (0x34 / 4) // Timer Compare Buffer 3
+#define S3C24XX_TCNTO3 (0x38 / 4) // Timer Count Observation 3
+#define S3C24XX_TCNTB4 (0x3C / 4) // Timer Count Buffer 4
+#define S3C24XX_TCNTO4 (0x40 / 4) // Timer Count Observation 4
+
+/* USB Device */
+
+#define S3C24XX_BASE_USBDEV 0x52000140
+
+/* Watchdog Timer */
+
+#define S3C24XX_BASE_WDT 0x53000000
+
+#define S3C24XX_WTCON (0x00 / 4) // Watchdog Timer Mode
+#define S3C24XX_WTDAT (0x04 / 4) // Watchdog Timer Data
+#define S3C24XX_WTCNT (0x08 / 4) // Watchdog Timer Count
+
+/* IIC */
+
+#define S3C24XX_BASE_IIC 0x54000000
+
+#define S3C24XX_IICCON (0x00 / 4) // IIC Control
+#define S3C24XX_IICSTAT (0x04 / 4) // IIC Status
+#define S3C24XX_IICADD (0x08 / 4) // IIC Address
+#define S3C24XX_IICDS (0x0C / 4) // IIC Data Shift
+
+/* IIS */
+
+#define S3C24XX_BASE_IIS 0x55000000
+
+#define S3C24XX_IISCON (0x00 / 4) // IIS Control
+#define S3C24XX_IISMOD (0x04 / 4) // IIS Mode
+#define S3C24XX_IISPSR (0x08 / 4) // IIS Prescaler
+#define S3C24XX_IISFCON (0x0C / 4) // IIS FIFO Control
+#define S3C24XX_IISFIFO (0x10 / 4) // IIS FIFO Entry
+
+/* I/O Port */
+
+#define S3C24XX_BASE_GPIO 0x56000000
+
+#define S3C24XX_GPACON (0x00 / 4) // Port A Control
+#define S3C24XX_GPADAT (0x04 / 4) // Port A Data
+#define S3C24XX_GPBCON (0x10 / 4) // Port B Control
+#define S3C24XX_GPBDAT (0x14 / 4) // Port B Data
+#define S3C24XX_GPBUP (0x18 / 4) // Pull-up Control B
+#define S3C24XX_GPCCON (0x20 / 4) // Port C Control
+#define S3C24XX_GPCDAT (0x24 / 4) // Port C Data
+#define S3C24XX_GPCUP (0x28 / 4) // Pull-up Control C
+#define S3C24XX_GPDCON (0x30 / 4) // Port D Control
+#define S3C24XX_GPDDAT (0x34 / 4) // Port D Data
+#define S3C24XX_GPDUP (0x38 / 4) // Pull-up Control D
+#define S3C24XX_GPECON (0x40 / 4) // Port E Control
+#define S3C24XX_GPEDAT (0x44 / 4) // Port E Data
+#define S3C24XX_GPEUP (0x48 / 4) // Pull-up Control E
+#define S3C24XX_GPFCON (0x50 / 4) // Port F Control
+#define S3C24XX_GPFDAT (0x54 / 4) // Port F Data
+#define S3C24XX_GPFUP (0x58 / 4) // Pull-up Control F
+#define S3C24XX_GPGCON (0x60 / 4) // Port G Control
+#define S3C24XX_GPGDAT (0x64 / 4) // Port G Data
+#define S3C24XX_GPGUP (0x68 / 4) // Pull-up Control G
+#define S3C24XX_GPHCON (0x70 / 4) // Port H Control
+#define S3C24XX_GPHDAT (0x74 / 4) // Port H Data
+#define S3C24XX_GPHUP (0x78 / 4) // Pull-up Control H
+#define S3C24XX_MISCCR (0x80 / 4) // Miscellaneous Control
+#define S3C24XX_DCLKCON (0x84 / 4) // DCLK0/1 Control
+#define S3C24XX_EXTINT0 (0x88 / 4) // External Interrupt Control Register 0
+#define S3C24XX_EXTINT1 (0x8C / 4) // External Interrupt Control Register 1
+#define S3C24XX_EXTINT2 (0x90 / 4) // External Interrupt Control Register 2
+#define S3C24XX_EINTFLT0 (0x94 / 4) // Reserved
+#define S3C24XX_EINTFLT1 (0x98 / 4) // Reserved
+#define S3C24XX_EINTFLT2 (0x9C / 4) // External Interrupt Filter Control Register 2
+#define S3C24XX_EINTFLT3 (0xA0 / 4) // External Interrupt Filter Control Register 3
+#define S3C24XX_EINTMASK (0xA4 / 4) // External Interrupt Mask
+#define S3C24XX_EINTPEND (0xA8 / 4) // External Interrupt Pending
+#define S3C24XX_GSTATUS0 (0xAC / 4) // External Pin Status
+#define S3C24XX_GSTATUS1 (0xB0 / 4) // Chip ID
+#define S3C24XX_GSTATUS2 (0xB4 / 4) // Reset Status
+#define S3C24XX_GSTATUS3 (0xB8 / 4) // Inform Register
+#define S3C24XX_GSTATUS4 (0xBC / 4) // Inform Register
+
+#define S3C24XX_GPADAT_MASK 0x007FFFFF
+#define S3C24XX_GPBDAT_MASK 0x000007FF
+#define S3C24XX_GPCDAT_MASK 0x0000FFFF
+#define S3C24XX_GPDDAT_MASK 0x0000FFFF
+#define S3C24XX_GPEDAT_MASK 0x0000FFFF
+#define S3C24XX_GPFDAT_MASK 0x000000FF
+#define S3C24XX_GPGDAT_MASK 0x0000FFFF
+#define S3C24XX_GPHDAT_MASK 0x000007FF
+
+/* RTC */
+
+#define S3C24XX_BASE_RTC 0x57000040
+
+#define S3C24XX_RTCCON (0x00 / 4) // RTC Control
+#define S3C24XX_TICNT (0x04 / 4) // Tick Time count
+#define S3C24XX_RTCALM (0x10 / 4) // RTC Alarm Control
+#define S3C24XX_ALMSEC (0x14 / 4) // Alarm Second
+#define S3C24XX_ALMMIN (0x18 / 4) // Alarm Minute
+#define S3C24XX_ALMHOUR (0x1C / 4) // Alarm Hour
+#define S3C24XX_ALMDAY (0x20 / 4) // Alarm Day
+#define S3C24XX_ALMMON (0x24 / 4) // Alarm Month
+#define S3C24XX_ALMYEAR (0x28 / 4) // Alarm Year
+#define S3C24XX_RTCRST (0x2C / 4) // RTC Round Reset
+#define S3C24XX_BCDSEC (0x30 / 4) // BCD Second
+#define S3C24XX_BCDMIN (0x34 / 4) // BCD Minute
+#define S3C24XX_BCDHOUR (0x38 / 4) // BCD Hour
+#define S3C24XX_BCDDAY (0x3C / 4) // BCD Day
+#define S3C24XX_BCDDOW (0x40 / 4) // BCD Day of Week
+#define S3C24XX_BCDMON (0x44 / 4) // BCD Month
+#define S3C24XX_BCDYEAR (0x48 / 4) // BCD Year
+
+/* A/D Converter */
+
+#define S3C24XX_BASE_ADC 0x58000000
+
+#define S3C24XX_ADCCON (0x00 / 4) // ADC Control
+#define S3C24XX_ADCTSC (0x04 / 4) // ADC Touch Screen Control
+#define S3C24XX_ADCDLY (0x08 / 4) // ADC Start or Interval Delay
+#define S3C24XX_ADCDAT0 (0x0C / 4) // ADC Conversion Data
+#define S3C24XX_ADCDAT1 (0x10 / 4) // ADC Conversion Data
+
+/* SPI */
+
+#define S3C24XX_BASE_SPI_0 0x59000000
+#define S3C24XX_BASE_SPI_1 0x59000020
+
+#define S3C24XX_SPCON (0x00 / 4) // SPI Control
+#define S3C24XX_SPSTA (0x04 / 4) // SPI Status
+#define S3C24XX_SPPIN (0x08 / 4) // SPI Pin Control
+#define S3C24XX_SPPRE (0x0C / 4) // SPI Baud Rate Prescaler
+#define S3C24XX_SPTDAT (0x10 / 4) // SPI Tx Data
+#define S3C24XX_SPRDAT (0x14 / 4) // SPI Rx Data
+
+/* SD Interface */
+
+#define S3C24XX_BASE_SDI 0x5A000000
+
+/* ... */
+
+#define S3C24XX_INT_ADC 31
+#define S3C24XX_INT_RTC 30
+#define S3C24XX_INT_SPI1 29
+#define S3C24XX_INT_UART0 28
+#define S3C24XX_INT_IIC 27
+#define S3C24XX_INT_USBH 26
+#define S3C24XX_INT_USBD 25
+#define S3C24XX_INT_24 24
+#define S3C24XX_INT_UART1 23
+#define S3C24XX_INT_SPI0 22
+#define S3C24XX_INT_SDI 21
+#define S3C24XX_INT_DMA3 20
+#define S3C24XX_INT_DMA2 19
+#define S3C24XX_INT_DMA1 18
+#define S3C24XX_INT_DMA0 17
+#define S3C24XX_INT_LCD 16
+#define S3C24XX_INT_UART2 15
+#define S3C24XX_INT_TIMER4 14
+#define S3C24XX_INT_TIMER3 13
+#define S3C24XX_INT_TIMER2 12
+#define S3C24XX_INT_TIMER1 11
+#define S3C24XX_INT_TIMER0 10
+#define S3C24XX_INT_WDT 9
+#define S3C24XX_INT_TICK 8
+#define S3C24XX_INT_BATT_FLT 7
+#define S3C24XX_INT_6 6
+#define S3C24XX_INT_EINT8_23 5
+#define S3C24XX_INT_EINT4_7 4
+#define S3C24XX_INT_EINT3 3
+#define S3C24XX_INT_EINT2 2
+#define S3C24XX_INT_EINT1 1
+#define S3C24XX_INT_EINT0 0
+
+#define S3C24XX_SUBINT_ADC 10
+#define S3C24XX_SUBINT_TC 9
+#define S3C24XX_SUBINT_ERR2 8
+#define S3C24XX_SUBINT_TXD2 7
+#define S3C24XX_SUBINT_RXD2 6
+#define S3C24XX_SUBINT_ERR1 5
+#define S3C24XX_SUBINT_TXD1 4
+#define S3C24XX_SUBINT_RXD1 3
+#define S3C24XX_SUBINT_ERR0 2
+#define S3C24XX_SUBINT_TXD0 1
+#define S3C24XX_SUBINT_RXD0 0
+
+static const UINT32 MAP_SUBINT_TO_INT[11] =
+{
+ S3C24XX_INT_UART0, S3C24XX_INT_UART0, S3C24XX_INT_UART0,
+ S3C24XX_INT_UART1, S3C24XX_INT_UART1, S3C24XX_INT_UART1,
+ S3C24XX_INT_UART2, S3C24XX_INT_UART2, S3C24XX_INT_UART2,
+ S3C24XX_INT_ADC, S3C24XX_INT_ADC
+};
+
+#define S3C24XX_BPPMODE_STN_01 0x00
+#define S3C24XX_BPPMODE_STN_02 0x01
+#define S3C24XX_BPPMODE_STN_04 0x02
+#define S3C24XX_BPPMODE_STN_08 0x03
+#define S3C24XX_BPPMODE_STN_12_P 0x04
+#define S3C24XX_BPPMODE_STN_12_U 0x05
+#define S3C24XX_BPPMODE_STN_16 0x06
+#define S3C24XX_BPPMODE_TFT_01 0x08
+#define S3C24XX_BPPMODE_TFT_02 0x09
+#define S3C24XX_BPPMODE_TFT_04 0x0A
+#define S3C24XX_BPPMODE_TFT_08 0x0B
+#define S3C24XX_BPPMODE_TFT_16 0x0C
+#define S3C24XX_BPPMODE_TFT_24 0x0D
+
+#define S3C24XX_PNRMODE_STN_04_DS 0
+#define S3C24XX_PNRMODE_STN_04_SS 1
+#define S3C24XX_PNRMODE_STN_08_SS 2
+#define S3C24XX_PNRMODE_TFT 3
+
+#define S3C24XX_GPIO_PORT_A S3C2410_GPIO_PORT_A
+#define S3C24XX_GPIO_PORT_B S3C2410_GPIO_PORT_B
+#define S3C24XX_GPIO_PORT_C S3C2410_GPIO_PORT_C
+#define S3C24XX_GPIO_PORT_D S3C2410_GPIO_PORT_D
+#define S3C24XX_GPIO_PORT_E S3C2410_GPIO_PORT_E
+#define S3C24XX_GPIO_PORT_F S3C2410_GPIO_PORT_F
+#define S3C24XX_GPIO_PORT_G S3C2410_GPIO_PORT_G
+#define S3C24XX_GPIO_PORT_H S3C2410_GPIO_PORT_H
+
+/*******************************************************************************
+ TYPE DEFINITIONS
+*******************************************************************************/
+
+typedef struct
+{
+ UINT32 data[0x34/4];
+} s3c24xx_memcon_regs_t;
+
+typedef struct
+{
+ UINT32 data[0x5C/4];
+} s3c24xx_usbhost_regs_t;
+
+typedef struct
+{
+ UINT32 srcpnd;
+ UINT32 intmod;
+ UINT32 intmsk;
+ UINT32 priority;
+ UINT32 intpnd;
+ UINT32 intoffset;
+ UINT32 subsrcpnd;
+ UINT32 intsubmsk;
+} s3c24xx_irq_regs_t;
+
+typedef struct
+{
+ UINT32 disrc;
+ UINT32 disrcc;
+ UINT32 didst;
+ UINT32 didstc;
+ UINT32 dcon;
+ UINT32 dstat;
+ UINT32 dcsrc;
+ UINT32 dcdst;
+ UINT32 dmasktrig;
+} s3c24xx_dma_regs_t;
+
+typedef struct
+{
+ UINT32 locktime;
+ UINT32 mpllcon;
+ UINT32 upllcon;
+ UINT32 clkcon;
+ UINT32 clkslow;
+ UINT32 clkdivn;
+} s3c24xx_clkpow_regs_t;
+
+typedef struct
+{
+ UINT32 lcdcon1;
+ UINT32 lcdcon2;
+ UINT32 lcdcon3;
+ UINT32 lcdcon4;
+ UINT32 lcdcon5;
+ UINT32 lcdsaddr1;
+ UINT32 lcdsaddr2;
+ UINT32 lcdsaddr3;
+ UINT32 redlut;
+ UINT32 greenlut;
+ UINT32 bluelut;
+ UINT32 reserved[8];
+ UINT32 dithmode;
+ UINT32 tpal;
+ UINT32 lcdintpnd;
+ UINT32 lcdsrcpnd;
+ UINT32 lcdintmsk;
+ UINT32 lpcsel;
+} s3c24xx_lcd_regs_t;
+
+typedef struct
+{
+ UINT32 data[0x400/4];
+} s3c24xx_lcdpal_regs_t;
+
+typedef struct
+{
+ UINT32 nfconf;
+ UINT32 nfcmd;
+ UINT32 nfaddr;
+ UINT32 nfdata;
+ UINT32 nfstat;
+ UINT32 nfecc;
+} s3c24xx_nand_regs_t;
+
+typedef struct
+{
+ UINT32 ulcon;
+ UINT32 ucon;
+ UINT32 ufcon;
+ UINT32 umcon;
+ UINT32 utrstat;
+ UINT32 uerstat;
+ UINT32 ufstat;
+ UINT32 umstat;
+ UINT32 utxh;
+ UINT32 urxh;
+ UINT32 ubrdiv;
+} s3c24xx_uart_regs_t;
+
+typedef struct
+{
+ UINT32 tcfg0;
+ UINT32 tcfg1;
+ UINT32 tcon;
+ UINT32 tcntb0;
+ UINT32 tcmpb0;
+ UINT32 tcnto0;
+ UINT32 tcntb1;
+ UINT32 tcmpb1;
+ UINT32 tcnto1;
+ UINT32 tcntb2;
+ UINT32 tcmpb2;
+ UINT32 tcnto2;
+ UINT32 tcntb3;
+ UINT32 tcmpb3;
+ UINT32 tcnto3;
+ UINT32 tcntb4;
+ UINT32 tcnto4;
+} s3c24xx_pwm_regs_t;
+
+typedef struct
+{
+ UINT32 data[0x130/4];
+} s3c24xx_usbdev_regs_t;
+
+typedef struct
+{
+ UINT32 wtcon;
+ UINT32 wtdat;
+ UINT32 wtcnt;
+} s3c24xx_wdt_regs_t;
+
+typedef struct
+{
+ UINT32 iiccon;
+ UINT32 iicstat;
+ UINT32 iicadd;
+ UINT32 iicds;
+} s3c24xx_iic_regs_t;
+
+typedef struct
+{
+ UINT32 iiscon;
+ UINT32 iismod;
+ UINT32 iispsr;
+ UINT32 iisfcon;
+ UINT32 iisfifo;
+} s3c24xx_iis_regs_t;
+
+typedef struct
+{
+ UINT32 gpacon;
+ UINT32 gpadat;
+ UINT32 pad_08;
+ UINT32 pad_0c;
+ UINT32 gpbbon;
+ UINT32 gpbdat;
+ UINT32 gpbup;
+ UINT32 pad_1c;
+ UINT32 gpccon;
+ UINT32 gpcdat;
+ UINT32 gpcup;
+ UINT32 pad_2c;
+ UINT32 gpdcon;
+ UINT32 gpddat;
+ UINT32 gpdup;
+ UINT32 pad_3c;
+ UINT32 gpecon;
+ UINT32 gpedat;
+ UINT32 gpeup;
+ UINT32 pad_4c;
+ UINT32 gpfcon;
+ UINT32 gpfdat;
+ UINT32 gpfup;
+ UINT32 pad_5c;
+ UINT32 gpgcon;
+ UINT32 gpgdat;
+ UINT32 gpgup;
+ UINT32 pad_6c;
+ UINT32 gphcon;
+ UINT32 gphdat;
+ UINT32 gphup;
+ UINT32 pad_7c;
+ UINT32 misccr;
+ UINT32 dclkcon;
+ UINT32 extint0;
+ UINT32 extint1;
+ UINT32 extint2;
+ UINT32 eintflt0;
+ UINT32 eintflt1;
+ UINT32 eintflt2;
+ UINT32 eintflt3;
+ UINT32 eintmask;
+ UINT32 eintpend;
+ UINT32 gstatus0;
+ UINT32 gstatus1;
+ UINT32 gstatus2;
+ UINT32 gstatus3;
+ UINT32 gstatus4;
+} s3c24xx_gpio_regs_t;
+
+typedef struct
+{
+ UINT32 rtccon;
+ UINT32 ticnt;
+ UINT32 reserved[2];
+ UINT32 rtcalm;
+ UINT32 almsec;
+ UINT32 almmin;
+ UINT32 almhour;
+ UINT32 almday;
+ UINT32 almmon;
+ UINT32 almyear;
+ UINT32 rtcrst;
+ UINT32 bcdsec;
+ UINT32 bcdmin;
+ UINT32 bcdhour;
+ UINT32 bcdday;
+ UINT32 bcddow;
+ UINT32 bcdmon;
+ UINT32 bcdyear;
+} s3c24xx_rtc_regs_t;
+
+typedef struct
+{
+ UINT32 adccon;
+ UINT32 adctsc;
+ UINT32 adcdly;
+ UINT32 adcdat0;
+ UINT32 adcdat1;
+} s3c24xx_adc_regs_t;
+
+typedef struct
+{
+ UINT32 spcon;
+ UINT32 spsta;
+ UINT32 sppin;
+ UINT32 sppre;
+ UINT32 sptdat;
+ UINT32 sprdat;
+} s3c24xx_spi_regs_t;
+
+typedef struct
+{
+ UINT32 data[0x44/4];
+} s3c24xx_sdi_regs_t;
+
+typedef struct
+{
+ s3c24xx_memcon_regs_t regs;
+} s3c24xx_memcon_t;
+
+typedef struct
+{
+ s3c24xx_usbhost_regs_t regs;
+} s3c24xx_usbhost_t;
+
+typedef struct
+{
+ s3c24xx_irq_regs_t regs;
+ int line_irq, line_fiq;
+} s3c24xx_irq_t;
+
+typedef struct
+{
+ s3c24xx_dma_regs_t regs;
+ emu_timer *timer;
+} s3c24xx_dma_t;
+
+typedef struct
+{
+ s3c24xx_clkpow_regs_t regs;
+} s3c24xx_clkpow_t;
+
+typedef struct
+{
+ s3c24xx_lcd_regs_t regs;
+ emu_timer *timer;
+ bitmap_t *bitmap[2];
+ UINT32 vramaddr_cur;
+ UINT32 vramaddr_max;
+ UINT32 offsize;
+ UINT32 pagewidth_cur;
+ UINT32 pagewidth_max;
+ UINT32 bppmode;
+ UINT32 bswp, hwswp;
+ int vpos, hpos;
+ double framerate;
+ UINT32 tpal;
+ UINT32 hpos_min, hpos_max, vpos_min, vpos_max;
+ UINT32 dma_data, dma_bits;
+} s3c24xx_lcd_t;
+
+typedef struct
+{
+ s3c24xx_lcdpal_regs_t regs;
+} s3c24xx_lcdpal_t;
+
+typedef struct
+{
+ s3c24xx_nand_regs_t regs;
+ UINT8 mecc[3];
+ int pos;
+} s3c24xx_nand_t;
+
+typedef struct
+{
+ s3c24xx_uart_regs_t regs;
+} s3c24xx_uart_t;
+
+typedef struct
+{
+ s3c24xx_pwm_regs_t regs;
+ emu_timer *timer[5];
+ UINT32 cnt[5];
+ UINT32 cmp[5];
+ UINT32 freq[5];
+} s3c24xx_pwm_t;
+
+typedef struct
+{
+ s3c24xx_usbdev_regs_t regs;
+} s3c24xx_usbdev_t;
+
+typedef struct
+{
+ s3c24xx_wdt_regs_t regs;
+ emu_timer *timer;
+ UINT32 freq, cnt;
+} s3c24xx_wdt_t;
+
+typedef struct
+{
+ s3c24xx_iic_regs_t regs;
+ emu_timer *timer;
+ int count;
+} s3c24xx_iic_t;
+
+typedef struct
+{
+ s3c24xx_iis_regs_t regs;
+ emu_timer *timer;
+ UINT16 fifo[16/2];
+ int fifo_index;
+} s3c24xx_iis_t;
+
+typedef struct
+{
+ s3c24xx_gpio_regs_t regs;
+} s3c24xx_gpio_t;
+
+typedef struct
+{
+ s3c24xx_rtc_regs_t regs;
+ emu_timer *timer_tick_count;
+ emu_timer *timer_update;
+} s3c24xx_rtc_t;
+
+typedef struct
+{
+ s3c24xx_adc_regs_t regs;
+} s3c24xx_adc_t;
+
+typedef struct
+{
+ s3c24xx_spi_regs_t regs;
+} s3c24xx_spi_t;
+
+typedef struct
+{
+ s3c24xx_sdi_regs_t regs;
+} s3c24xx_sdi_t;
+
+typedef struct
+{
+ const s3c2410_interface *iface;
+ s3c24xx_memcon_t memcon;
+ s3c24xx_usbhost_t usbhost;
+ s3c24xx_irq_t irq;
+ s3c24xx_dma_t dma[4];
+ s3c24xx_clkpow_t clkpow;
+ s3c24xx_lcd_t lcd;
+ s3c24xx_lcdpal_t lcdpal;
+ s3c24xx_nand_t nand;
+ s3c24xx_uart_t uart[3];
+ s3c24xx_pwm_t pwm;
+ s3c24xx_usbdev_t usbdev;
+ s3c24xx_wdt_t wdt;
+ s3c24xx_iic_t iic;
+ s3c24xx_iis_t iis;
+ s3c24xx_gpio_t gpio;
+ s3c24xx_rtc_t rtc;
+ s3c24xx_adc_t adc;
+ s3c24xx_spi_t spi[2];
+ s3c24xx_sdi_t sdi;
+} s3c24xx_t;
+
+#endif
diff --git a/trunk/src/emu/machine/s3c2440.c b/trunk/src/emu/machine/s3c2440.c
new file mode 100644
index 00000000000..445053926ed
--- /dev/null
+++ b/trunk/src/emu/machine/s3c2440.c
@@ -0,0 +1,117 @@
+/*******************************************************************************
+
+ Samsung S3C2440
+
+ (c) 2010 Tim Schuerewegen
+
+*******************************************************************************/
+
+#include "emu.h"
+#include "cpu/arm7/arm7.h"
+#include "cpu/arm7/arm7core.h"
+#include "machine/s3c2440.h"
+#include "sound/dac.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);
+ }
+}
+
+#define DEVICE_S3C2440
+#include "machine/s3c24xx.c"
+#undef DEVICE_S3C2440
+
+VIDEO_START( s3c2440 )
+{
+ device_t *device = machine.device( S3C2440_TAG);
+ s3c24xx_video_start( device, machine);
+}
+
+SCREEN_UPDATE( s3c2440 )
+{
+ device_t *device = screen->machine().device( S3C2440_TAG);
+ return s3c24xx_video_update( device, screen, bitmap, cliprect);
+}
+
+DEVICE_START( s3c2440 )
+{
+ address_space *space = device->machine().device( "maincpu")->memory().space( AS_PROGRAM);
+ space->install_legacy_readwrite_handler( *device, 0x48000000, 0x4800003b, FUNC(s3c24xx_memcon_r), FUNC(s3c24xx_memcon_w));
+ space->install_legacy_readwrite_handler( *device, 0x49000000, 0x4900005b, FUNC(s3c24xx_usb_host_r), FUNC(s3c24xx_usb_host_w));
+ space->install_legacy_readwrite_handler( *device, 0x4a000000, 0x4a00001f, FUNC(s3c24xx_irq_r), FUNC(s3c24xx_irq_w));
+ space->install_legacy_readwrite_handler( *device, 0x4b000000, 0x4b000023, FUNC(s3c24xx_dma_0_r), FUNC(s3c24xx_dma_0_w));
+ space->install_legacy_readwrite_handler( *device, 0x4b000040, 0x4b000063, FUNC(s3c24xx_dma_1_r), FUNC(s3c24xx_dma_1_w));
+ space->install_legacy_readwrite_handler( *device, 0x4b000080, 0x4b0000a3, FUNC(s3c24xx_dma_2_r), FUNC(s3c24xx_dma_2_w));
+ space->install_legacy_readwrite_handler( *device, 0x4b0000c0, 0x4b0000e3, FUNC(s3c24xx_dma_3_r), FUNC(s3c24xx_dma_3_w));
+ space->install_legacy_readwrite_handler( *device, 0x4c000000, 0x4c00001b, FUNC(s3c24xx_clkpow_r), FUNC(s3c24xx_clkpow_w));
+ space->install_legacy_readwrite_handler( *device, 0x4d000000, 0x4d000063, FUNC(s3c2440_lcd_r), FUNC(s3c24xx_lcd_w));
+ space->install_legacy_readwrite_handler( *device, 0x4d000400, 0x4d0007ff, FUNC(s3c24xx_lcd_palette_r), FUNC(s3c24xx_lcd_palette_w));
+ space->install_legacy_readwrite_handler( *device, 0x4e000000, 0x4e00003f, FUNC(s3c24xx_nand_r), FUNC(s3c24xx_nand_w));
+ space->install_legacy_readwrite_handler( *device, 0x4f000000, 0x4f0000a3, FUNC(s3c24xx_cam_r), FUNC(s3c24xx_cam_w));
+ space->install_legacy_readwrite_handler( *device, 0x50000000, 0x5000002b, FUNC(s3c24xx_uart_0_r), FUNC(s3c24xx_uart_0_w));
+ space->install_legacy_readwrite_handler( *device, 0x50004000, 0x5000402b, FUNC(s3c24xx_uart_1_r), FUNC(s3c24xx_uart_1_w));
+ space->install_legacy_readwrite_handler( *device, 0x50008000, 0x5000802b, FUNC(s3c24xx_uart_2_r), FUNC(s3c24xx_uart_2_w));
+ space->install_legacy_readwrite_handler( *device, 0x51000000, 0x51000043, FUNC(s3c24xx_pwm_r), FUNC(s3c24xx_pwm_w));
+ space->install_legacy_readwrite_handler( *device, 0x52000140, 0x5200026f, FUNC(s3c24xx_usb_device_r), FUNC(s3c24xx_usb_device_w));
+ space->install_legacy_readwrite_handler( *device, 0x53000000, 0x5300000b, FUNC(s3c24xx_wdt_r), FUNC(s3c24xx_wdt_w));
+ space->install_legacy_readwrite_handler( *device, 0x54000000, 0x54000013, FUNC(s3c24xx_iic_r), FUNC(s3c24xx_iic_w));
+ space->install_legacy_readwrite_handler( *device, 0x55000000, 0x55000013, FUNC(s3c24xx_iis_r), FUNC(s3c24xx_iis_w));
+ space->install_legacy_readwrite_handler( *device, 0x56000000, 0x560000df, FUNC(s3c24xx_gpio_r), FUNC(s3c24xx_gpio_w));
+ space->install_legacy_readwrite_handler( *device, 0x57000040, 0x5700008b, FUNC(s3c24xx_rtc_r), FUNC(s3c24xx_rtc_w));
+ space->install_legacy_readwrite_handler( *device, 0x58000000, 0x58000017, FUNC(s3c24xx_adc_r), FUNC(s3c24xx_adc_w));
+ space->install_legacy_readwrite_handler( *device, 0x59000000, 0x59000017, FUNC(s3c24xx_spi_0_r), FUNC(s3c24xx_spi_0_w));
+ space->install_legacy_readwrite_handler( *device, 0x59000020, 0x59000037, FUNC(s3c24xx_spi_1_r), FUNC(s3c24xx_spi_1_w));
+ space->install_legacy_readwrite_handler( *device, 0x5a000000, 0x5a000043, FUNC(s3c24xx_sdi_r), FUNC(s3c24xx_sdi_w));
+ space->install_legacy_readwrite_handler( *device, 0x5b000000, 0x5b00001f, FUNC(s3c24xx_ac97_r), FUNC(s3c24xx_ac97_w));
+ DEVICE_START_CALL(s3c24xx);
+}
+
+DEVICE_GET_INFO( s3c2440 )
+{
+ switch ( state )
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(s3c2440); break;
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Samsung S3C2440"); break;
+ /* --- default --- */
+ default: DEVICE_GET_INFO_CALL(s3c24xx); break;
+ }
+}
+
+void s3c2440_uart_fifo_w( device_t *device, int uart, UINT8 data)
+{
+ s3c24xx_uart_fifo_w( device, uart, data);
+}
+
+void s3c2440_touch_screen( device_t *device, int state)
+{
+ s3c24xx_touch_screen( device, state);
+}
+
+void s3c2440_request_irq( device_t *device, UINT32 int_type)
+{
+ s3c24xx_request_irq( device, int_type);
+}
+
+void s3c2440_request_eint( device_t *device, UINT32 number)
+{
+ s3c24xx_request_eint( device, number);
+}
+
+WRITE_LINE_DEVICE_HANDLER( s3c2440_pin_frnb_w )
+{
+ s3c24xx_pin_frnb_w( device, state);
+}
+
+DEFINE_LEGACY_DEVICE(S3C2440, s3c2440);
diff --git a/trunk/src/emu/machine/s3c2440.h b/trunk/src/emu/machine/s3c2440.h
new file mode 100644
index 00000000000..0e3b81f9203
--- /dev/null
+++ b/trunk/src/emu/machine/s3c2440.h
@@ -0,0 +1,933 @@
+/*******************************************************************************
+
+ Samsung S3C2440
+
+*******************************************************************************/
+
+#ifndef __S3C2440_H__
+#define __S3C2440_H__
+
+/*******************************************************************************
+ MACROS / CONSTANTS
+*******************************************************************************/
+
+#define S3C2440_TAG "s3c2440"
+
+#define MCFG_S3C2440_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD(_tag, S3C2440, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define S3C2440_INTERFACE(name) \
+ const s3c2440_interface(name) =
+
+enum
+{
+ S3C2440_GPIO_PORT_A = 0,
+ S3C2440_GPIO_PORT_B,
+ S3C2440_GPIO_PORT_C,
+ S3C2440_GPIO_PORT_D,
+ S3C2440_GPIO_PORT_E,
+ S3C2440_GPIO_PORT_F,
+ S3C2440_GPIO_PORT_G,
+ S3C2440_GPIO_PORT_H,
+ S3C2440_GPIO_PORT_J
+};
+
+DECLARE_LEGACY_DEVICE(S3C2440, s3c2440);
+
+/*******************************************************************************
+ TYPE DEFINITIONS
+*******************************************************************************/
+
+typedef UINT32 (*s3c24xx_gpio_port_r_func)( device_t *device, int port);
+typedef void (*s3c24xx_gpio_port_w_func)( device_t *device, int port, UINT32 data);
+
+typedef struct _s3c2440_interface_gpio s3c2440_interface_gpio;
+struct _s3c2440_interface_gpio
+{
+ s3c24xx_gpio_port_r_func port_r;
+ s3c24xx_gpio_port_w_func port_w;
+};
+
+typedef struct _s3c2440_interface_i2c s3c2440_interface_i2c;
+struct _s3c2440_interface_i2c
+{
+ write_line_device_func scl_w;
+ read_line_device_func sda_r;
+ write_line_device_func sda_w;
+};
+
+typedef struct _s3c2440_interface_adc s3c2440_interface_adc;
+struct _s3c2440_interface_adc
+{
+ read32_device_func data_r;
+};
+
+typedef struct _s3c2440_interface_i2s s3c2440_interface_i2s;
+struct _s3c2440_interface_i2s
+{
+ write16_device_func data_w;
+};
+
+typedef struct _s3c2440_interface_nand s3c2440_interface_nand;
+struct _s3c2440_interface_nand
+{
+ write8_device_func command_w;
+ write8_device_func address_w;
+ read8_device_func data_r;
+ write8_device_func data_w;
+};
+
+typedef struct _s3c2440_interface_lcd s3c2440_interface_lcd;
+struct _s3c2440_interface_lcd
+{
+ int flags;
+};
+
+typedef struct _s3c2440_interface s3c2440_interface;
+struct _s3c2440_interface
+{
+ s3c2440_interface_gpio gpio;
+ s3c2440_interface_i2c i2c;
+ s3c2440_interface_adc adc;
+ s3c2440_interface_i2s i2s;
+ s3c2440_interface_nand nand;
+ s3c2440_interface_lcd lcd;
+};
+
+/*******************************************************************************
+ PROTOTYPES
+*******************************************************************************/
+
+DEVICE_GET_INFO( s3c2440 );
+
+VIDEO_START( s3c2440 );
+SCREEN_UPDATE( s3c2440 );
+
+void s3c2440_uart_fifo_w( device_t *device, int uart, UINT8 data);
+void s3c2440_touch_screen( device_t *device, int state);
+void s3c2440_request_irq( device_t *device, UINT32 int_type);
+void s3c2440_request_eint( device_t *device, UINT32 number);
+
+WRITE_LINE_DEVICE_HANDLER( s3c2440_pin_frnb_w );
+
+/*******************************************************************************
+ MACROS & CONSTANTS
+*******************************************************************************/
+
+/* Interface */
+
+#define S3C24XX_INTERFACE_LCD_REVERSE 1
+
+/* Memory Controller */
+
+#define S3C24XX_BASE_MEMCON 0x48000000
+
+/* USB Host Controller */
+
+#define S3C24XX_BASE_USBHOST 0x49000000
+
+/* Interrupt Controller */
+
+#define S3C24XX_BASE_INT 0x4A000000
+
+#define S3C24XX_SRCPND (0x00 / 4) // Interrupt Request Status
+#define S3C24XX_INTMOD (0x04 / 4) // Interrupt Mode Control
+#define S3C24XX_INTMSK (0x08 / 4) // Interrupt Mask Control
+#define S3C24XX_PRIORITY (0x0C / 4) // IRQ Priority Control
+#define S3C24XX_INTPND (0x10 / 4) // Interrupt Request Status
+#define S3C24XX_INTOFFSET (0x14 / 4) // Interrupt Request Source Offset
+#define S3C24XX_SUBSRCPND (0x18 / 4) // Sub Source Pending
+#define S3C24XX_INTSUBMSK (0x1C / 4) // Interrupt Sub Mask
+
+/* DMA */
+
+#define S3C24XX_BASE_DMA_0 0x4B000000
+#define S3C24XX_BASE_DMA_1 0x4B000040
+#define S3C24XX_BASE_DMA_2 0x4B000080
+#define S3C24XX_BASE_DMA_3 0x4B0000C0
+
+#define S3C24XX_DISRC (0x00 / 4) // DMA Initial Source
+#define S3C24XX_DISRCC (0x04 / 4) // DMA Initial Source Control
+#define S3C24XX_DIDST (0x08 / 4) // DMA Initial Destination
+#define S3C24XX_DIDSTC (0x0C / 4) // DMA Initial Destination Control
+#define S3C24XX_DCON (0x10 / 4) // DMA Control
+#define S3C24XX_DSTAT (0x14 / 4) // DMA Count
+#define S3C24XX_DCSRC (0x18 / 4) // DMA Current Source
+#define S3C24XX_DCDST (0x1C / 4) // DMA Current Destination
+#define S3C24XX_DMASKTRIG (0x20 / 4) // DMA Mask Trigger
+
+/* Clock & Power Management */
+
+#define S3C24XX_BASE_CLKPOW 0x4C000000
+
+#define S3C24XX_LOCKTIME (0x00 / 4) // PLL Lock Time Counter
+#define S3C24XX_MPLLCON (0x04 / 4) // MPLL Control
+#define S3C24XX_UPLLCON (0x08 / 4) // UPLL Control
+#define S3C24XX_CLKCON (0x0C / 4) // Clock Generator Control
+#define S3C24XX_CLKSLOW (0x10 / 4) // Slow Clock Control
+#define S3C24XX_CLKDIVN (0x14 / 4) // Clock Divider Control
+#define S3C24XX_CAMDIVN (0x18 / 4) // Camera Clock Divider Control
+
+/* LCD Controller */
+
+#define S3C24XX_BASE_LCD 0x4D000000
+#define S3C24XX_BASE_LCDPAL 0x4D000400
+
+#define S3C24XX_LCDCON1 (0x00 / 4) // LCD Control 1
+#define S3C24XX_LCDCON2 (0x04 / 4) // LCD Control 2
+#define S3C24XX_LCDCON3 (0x08 / 4) // LCD Control 3
+#define S3C24XX_LCDCON4 (0x0C / 4) // LCD Control 4
+#define S3C24XX_LCDCON5 (0x10 / 4) // LCD Control 5
+#define S3C24XX_LCDSADDR1 (0x14 / 4) // STN/TFT: Frame Buffer Start Address 1
+#define S3C24XX_LCDSADDR2 (0x18 / 4) // STN/TFT: Frame Buffer Start Address 2
+#define S3C24XX_LCDSADDR3 (0x1C / 4) // STN/TFT: Virtual Screen Address Set
+#define S3C24XX_REDLUT (0x20 / 4) // STN: Red Lookup Table
+#define S3C24XX_GREENLUT (0x24 / 4) // STN: Green Lookup Table
+#define S3C24XX_BLUELUT (0x28 / 4) // STN: Blue Lookup Table
+#define S3C24XX_DITHMODE (0x4C / 4) // STN: Dithering Mode
+#define S3C24XX_TPAL (0x50 / 4) // TFT: Temporary Palette
+#define S3C24XX_LCDINTPND (0x54 / 4) // LCD Interrupt Pending
+#define S3C24XX_LCDSRCPND (0x58 / 4) // LCD Interrupt Source
+#define S3C24XX_LCDINTMSK (0x5C / 4) // LCD Interrupt Mask
+#define S3C24XX_TCONSEL (0x60 / 4) // TCON (LPC3600/LCC3600) Control
+
+/* NAND Flash */
+
+#define S3C24XX_BASE_NAND 0x4E000000
+
+#define S3C24XX_NFCONF (0x00 / 4) // NAND Flash Configuration
+#define S3C24XX_NFCONT (0x04 / 4) // NAND Flash Control
+#define S3C24XX_NFCMD (0x08 / 4) // NAND Flash Command
+#define S3C24XX_NFADDR (0x0C / 4) // NAND Flash Address
+#define S3C24XX_NFDATA (0x10 / 4) // NAND Flash Data
+#define S3C24XX_NFMECCD0 (0x14 / 4) // NAND Flash Main Area ECC0/1
+#define S3C24XX_NFMECCD1 (0x18 / 4) // NAND Flash Main Area ECC2/3
+#define S3C24XX_NFSECCD (0x1C / 4) // NAND Flash Spare Area Ecc
+#define S3C24XX_NFSTAT (0x20 / 4) // NAND Flash Operation Status
+#define S3C24XX_NFESTAT0 (0x24 / 4) // NAND Flash ECC Status For I/O[7:0]
+#define S3C24XX_NFESTAT1 (0x28 / 4) // NAND Flash ECC Status For I/O[15:8]
+#define S3C24XX_NFMECC0 (0x2C / 4) // NAND Flash Main Area ECC0 Status
+#define S3C24XX_NFMECC1 (0x30 / 4) // NAND Flash Main Area ECC1 Status
+#define S3C24XX_NFSECC (0x34 / 4) // NAND Flash Spare Area ECC Status
+#define S3C24XX_NFSBLK (0x38 / 4) // NAND Flash Start Block Address
+#define S3C24XX_NFEBLK (0x3C / 4) // NAND Flash End Block Address
+
+/* Camera Interface */
+
+#define S3C24XX_BASE_CAM 0x4F000000
+
+/* UART */
+
+#define S3C24XX_BASE_UART_0 0x50000000
+#define S3C24XX_BASE_UART_1 0x50004000
+#define S3C24XX_BASE_UART_2 0x50008000
+
+#define S3C24XX_ULCON (0x00 / 4) // UART Line Control
+#define S3C24XX_UCON (0x04 / 4) // UART Control
+#define S3C24XX_UFCON (0x08 / 4) // UART FIFO Control
+#define S3C24XX_UMCON (0x0C / 4) // UART Modem Control
+#define S3C24XX_UTRSTAT (0x10 / 4) // UART Tx/Rx Status
+#define S3C24XX_UERSTAT (0x14 / 4) // UART Rx Error Status
+#define S3C24XX_UFSTAT (0x18 / 4) // UART FIFO Status
+#define S3C24XX_UMSTAT (0x1C / 4) // UART Modem Status
+#define S3C24XX_UTXH (0x20 / 4) // UART Transmission Hold
+#define S3C24XX_URXH (0x24 / 4) // UART Receive Buffer
+#define S3C24XX_UBRDIV (0x28 / 4) // UART Baud Rate Divisor
+
+/* PWM Timer */
+
+#define S3C24XX_BASE_PWM 0x51000000
+
+#define S3C24XX_TCFG0 (0x00 / 4) // Timer Configuration
+#define S3C24XX_TCFG1 (0x04 / 4) // Timer Configuration
+#define S3C24XX_TCON (0x08 / 4) // Timer Control
+#define S3C24XX_TCNTB0 (0x0C / 4) // Timer Count Buffer 0
+#define S3C24XX_TCMPB0 (0x10 / 4) // Timer Compare Buffer 0
+#define S3C24XX_TCNTO0 (0x14 / 4) // Timer Count Observation 0
+#define S3C24XX_TCNTB1 (0x18 / 4) // Timer Count Buffer 1
+#define S3C24XX_TCMPB1 (0x1C / 4) // Timer Compare Buffer 1
+#define S3C24XX_TCNTO1 (0x20 / 4) // Timer Count Observation 1
+#define S3C24XX_TCNTB2 (0x24 / 4) // Timer Count Buffer 2
+#define S3C24XX_TCMPB2 (0x28 / 4) // Timer Compare Buffer 2
+#define S3C24XX_TCNTO2 (0x2C / 4) // Timer Count Observation 2
+#define S3C24XX_TCNTB3 (0x30 / 4) // Timer Count Buffer 3
+#define S3C24XX_TCMPB3 (0x34 / 4) // Timer Compare Buffer 3
+#define S3C24XX_TCNTO3 (0x38 / 4) // Timer Count Observation 3
+#define S3C24XX_TCNTB4 (0x3C / 4) // Timer Count Buffer 4
+#define S3C24XX_TCNTO4 (0x40 / 4) // Timer Count Observation 4
+
+/* USB Device */
+
+#define S3C24XX_BASE_USBDEV 0x52000140
+
+/* Watchdog Timer */
+
+#define S3C24XX_BASE_WDT 0x53000000
+
+#define S3C24XX_WTCON (0x00 / 4) // Watchdog Timer Mode
+#define S3C24XX_WTDAT (0x04 / 4) // Watchdog Timer Data
+#define S3C24XX_WTCNT (0x08 / 4) // Watchdog Timer Count
+
+/* IIC */
+
+#define S3C24XX_BASE_IIC 0x54000000
+
+#define S3C24XX_IICCON (0x00 / 4) // IIC Control
+#define S3C24XX_IICSTAT (0x04 / 4) // IIC Status
+#define S3C24XX_IICADD (0x08 / 4) // IIC Address
+#define S3C24XX_IICDS (0x0C / 4) // IIC Data Shift
+#define S3C24XX_IICLC (0x10 / 4) // IIC Multi-Master Line Control
+
+/* IIS */
+
+#define S3C24XX_BASE_IIS 0x55000000
+
+#define S3C24XX_IISCON (0x00 / 4) // IIS Control
+#define S3C24XX_IISMOD (0x04 / 4) // IIS Mode
+#define S3C24XX_IISPSR (0x08 / 4) // IIS Prescaler
+#define S3C24XX_IISFCON (0x0C / 4) // IIS FIFO Control
+#define S3C24XX_IISFIFO (0x10 / 4) // IIS FIFO Entry
+
+/* I/O Port */
+
+#define S3C24XX_BASE_GPIO 0x56000000
+
+#define S3C24XX_GPACON (0x00 / 4) // Port A Control
+#define S3C24XX_GPADAT (0x04 / 4) // Port A Data
+#define S3C24XX_GPBCON (0x10 / 4) // Port B Control
+#define S3C24XX_GPBDAT (0x14 / 4) // Port B Data
+#define S3C24XX_GPBUP (0x18 / 4) // Pull-up Control B
+#define S3C24XX_GPCCON (0x20 / 4) // Port C Control
+#define S3C24XX_GPCDAT (0x24 / 4) // Port C Data
+#define S3C24XX_GPCUP (0x28 / 4) // Pull-up Control C
+#define S3C24XX_GPDCON (0x30 / 4) // Port D Control
+#define S3C24XX_GPDDAT (0x34 / 4) // Port D Data
+#define S3C24XX_GPDUP (0x38 / 4) // Pull-up Control D
+#define S3C24XX_GPECON (0x40 / 4) // Port E Control
+#define S3C24XX_GPEDAT (0x44 / 4) // Port E Data
+#define S3C24XX_GPEUP (0x48 / 4) // Pull-up Control E
+#define S3C24XX_GPFCON (0x50 / 4) // Port F Control
+#define S3C24XX_GPFDAT (0x54 / 4) // Port F Data
+#define S3C24XX_GPFUP (0x58 / 4) // Pull-up Control F
+#define S3C24XX_GPGCON (0x60 / 4) // Port G Control
+#define S3C24XX_GPGDAT (0x64 / 4) // Port G Data
+#define S3C24XX_GPGUP (0x68 / 4) // Pull-up Control G
+#define S3C24XX_GPHCON (0x70 / 4) // Port H Control
+#define S3C24XX_GPHDAT (0x74 / 4) // Port H Data
+#define S3C24XX_GPHUP (0x78 / 4) // Pull-up Control H
+#define S3C24XX_MISCCR (0x80 / 4) // Miscellaneous Control
+#define S3C24XX_DCLKCON (0x84 / 4) // DCLK0/1 Control
+#define S3C24XX_EXTINT0 (0x88 / 4) // External Interrupt Control Register 0
+#define S3C24XX_EXTINT1 (0x8C / 4) // External Interrupt Control Register 1
+#define S3C24XX_EXTINT2 (0x90 / 4) // External Interrupt Control Register 2
+#define S3C24XX_EINTFLT0 (0x94 / 4) // Reserved
+#define S3C24XX_EINTFLT1 (0x98 / 4) // Reserved
+#define S3C24XX_EINTFLT2 (0x9C / 4) // External Interrupt Filter Control Register 2
+#define S3C24XX_EINTFLT3 (0xA0 / 4) // External Interrupt Filter Control Register 3
+#define S3C24XX_EINTMASK (0xA4 / 4) // External Interrupt Mask
+#define S3C24XX_EINTPEND (0xA8 / 4) // External Interrupt Pending
+#define S3C24XX_GSTATUS0 (0xAC / 4) // External Pin Status
+#define S3C24XX_GSTATUS1 (0xB0 / 4) // Chip ID
+#define S3C24XX_GSTATUS2 (0xB4 / 4) // Reset Status
+#define S3C24XX_GSTATUS3 (0xB8 / 4) // Inform Register
+#define S3C24XX_GSTATUS4 (0xBC / 4) // Inform Register
+#define S3C24XX_MSLCON (0xCC / 4) // Memory Sleep Control Register
+#define S3C24XX_GPJCON (0xD0 / 4) // Port J Control
+#define S3C24XX_GPJDAT (0xD4 / 4) // Port J Data
+#define S3C24XX_GPJUP (0xD8 / 4) // Pull-up Control J
+
+#define S3C24XX_GPADAT_MASK 0x01FFFFFF
+#define S3C24XX_GPBDAT_MASK 0x000007FF
+#define S3C24XX_GPCDAT_MASK 0x0000FFFF
+#define S3C24XX_GPDDAT_MASK 0x0000FFFF
+#define S3C24XX_GPEDAT_MASK 0x0000FFFF
+#define S3C24XX_GPFDAT_MASK 0x000000FF
+#define S3C24XX_GPGDAT_MASK 0x0000FFFF
+#define S3C24XX_GPHDAT_MASK 0x000007FF
+#define S3C24XX_GPJDAT_MASK 0x0000FFFF
+
+/* RTC */
+
+#define S3C24XX_BASE_RTC 0x57000040
+
+#define S3C24XX_RTCCON (0x00 / 4) // RTC Control
+#define S3C24XX_TICNT (0x04 / 4) // Tick Time count
+#define S3C24XX_RTCALM (0x10 / 4) // RTC Alarm Control
+#define S3C24XX_ALMSEC (0x14 / 4) // Alarm Second
+#define S3C24XX_ALMMIN (0x18 / 4) // Alarm Minute
+#define S3C24XX_ALMHOUR (0x1C / 4) // Alarm Hour
+#define S3C24XX_ALMDAY (0x20 / 4) // Alarm Day
+#define S3C24XX_ALMMON (0x24 / 4) // Alarm Month
+#define S3C24XX_ALMYEAR (0x28 / 4) // Alarm Year
+#define S3C24XX_BCDSEC (0x30 / 4) // BCD Second
+#define S3C24XX_BCDMIN (0x34 / 4) // BCD Minute
+#define S3C24XX_BCDHOUR (0x38 / 4) // BCD Hour
+#define S3C24XX_BCDDAY (0x3C / 4) // BCD Day
+#define S3C24XX_BCDDOW (0x40 / 4) // BCD Day of Week
+#define S3C24XX_BCDMON (0x44 / 4) // BCD Month
+#define S3C24XX_BCDYEAR (0x48 / 4) // BCD Year
+
+/* A/D Converter */
+
+#define S3C24XX_BASE_ADC 0x58000000
+
+#define S3C24XX_ADCCON (0x00 / 4) // ADC Control
+#define S3C24XX_ADCTSC (0x04 / 4) // ADC Touch Screen Control
+#define S3C24XX_ADCDLY (0x08 / 4) // ADC Start or Interval Delay
+#define S3C24XX_ADCDAT0 (0x0C / 4) // ADC Conversion Data
+#define S3C24XX_ADCDAT1 (0x10 / 4) // ADC Conversion Data
+#define S3C24XX_ADCUPDN (0x14 / 4) // Stylus up or down interrupt status
+
+/* SPI */
+
+#define S3C24XX_BASE_SPI_0 0x59000000
+#define S3C24XX_BASE_SPI_1 0x59000020
+
+#define S3C24XX_SPCON (0x00 / 4) // SPI Control
+#define S3C24XX_SPSTA (0x04 / 4) // SPI Status
+#define S3C24XX_SPPIN (0x08 / 4) // SPI Pin Control
+#define S3C24XX_SPPRE (0x0C / 4) // SPI Baud Rate Prescaler
+#define S3C24XX_SPTDAT (0x10 / 4) // SPI Tx Data
+#define S3C24XX_SPRDAT (0x14 / 4) // SPI Rx Data
+
+/* SD Interface */
+
+#define S3C24XX_BASE_SDI 0x5A000000
+
+/* AC97 Interface */
+
+#define S3C24XX_BASE_AC97 0x5B000000
+
+/* ... */
+
+#define S3C24XX_INT_ADC 31
+#define S3C24XX_INT_RTC 30
+#define S3C24XX_INT_SPI1 29
+#define S3C24XX_INT_UART0 28
+#define S3C24XX_INT_IIC 27
+#define S3C24XX_INT_USBH 26
+#define S3C24XX_INT_USBD 25
+#define S3C24XX_INT_NFCON 24
+#define S3C24XX_INT_UART1 23
+#define S3C24XX_INT_SPI0 22
+#define S3C24XX_INT_SDI 21
+#define S3C24XX_INT_DMA3 20
+#define S3C24XX_INT_DMA2 19
+#define S3C24XX_INT_DMA1 18
+#define S3C24XX_INT_DMA0 17
+#define S3C24XX_INT_LCD 16
+#define S3C24XX_INT_UART2 15
+#define S3C24XX_INT_TIMER4 14
+#define S3C24XX_INT_TIMER3 13
+#define S3C24XX_INT_TIMER2 12
+#define S3C24XX_INT_TIMER1 11
+#define S3C24XX_INT_TIMER0 10
+#define S3C24XX_INT_WDT_AC97 9
+#define S3C24XX_INT_TICK 8
+#define S3C24XX_INT_BATT_FLT 7
+#define S3C24XX_INT_CAM 6
+#define S3C24XX_INT_EINT8_23 5
+#define S3C24XX_INT_EINT4_7 4
+#define S3C24XX_INT_EINT3 3
+#define S3C24XX_INT_EINT2 2
+#define S3C24XX_INT_EINT1 1
+#define S3C24XX_INT_EINT0 0
+
+#define S3C24XX_SUBINT_AC97 14
+#define S3C24XX_SUBINT_WDT 13
+#define S3C24XX_SUBINT_CAM_P 12
+#define S3C24XX_SUBINT_CAM_C 11
+#define S3C24XX_SUBINT_ADC_S 10
+#define S3C24XX_SUBINT_TC 9
+#define S3C24XX_SUBINT_ERR2 8
+#define S3C24XX_SUBINT_TXD2 7
+#define S3C24XX_SUBINT_RXD2 6
+#define S3C24XX_SUBINT_ERR1 5
+#define S3C24XX_SUBINT_TXD1 4
+#define S3C24XX_SUBINT_RXD1 3
+#define S3C24XX_SUBINT_ERR0 2
+#define S3C24XX_SUBINT_TXD0 1
+#define S3C24XX_SUBINT_RXD0 0
+
+static const UINT32 MAP_SUBINT_TO_INT[15] =
+{
+ S3C24XX_INT_UART0, S3C24XX_INT_UART0, S3C24XX_INT_UART0,
+ S3C24XX_INT_UART1, S3C24XX_INT_UART1, S3C24XX_INT_UART1,
+ S3C24XX_INT_UART2, S3C24XX_INT_UART2, S3C24XX_INT_UART2,
+ S3C24XX_INT_ADC, S3C24XX_INT_ADC,
+ S3C24XX_INT_CAM, S3C24XX_INT_CAM,
+ S3C24XX_INT_WDT_AC97, S3C24XX_INT_WDT_AC97
+};
+
+#define S3C24XX_BPPMODE_STN_01 0x00
+#define S3C24XX_BPPMODE_STN_02 0x01
+#define S3C24XX_BPPMODE_STN_04 0x02
+#define S3C24XX_BPPMODE_STN_08 0x03
+#define S3C24XX_BPPMODE_STN_12_P 0x04
+#define S3C24XX_BPPMODE_STN_12_U 0x05
+#define S3C24XX_BPPMODE_STN_16 0x06
+#define S3C24XX_BPPMODE_TFT_01 0x08
+#define S3C24XX_BPPMODE_TFT_02 0x09
+#define S3C24XX_BPPMODE_TFT_04 0x0A
+#define S3C24XX_BPPMODE_TFT_08 0x0B
+#define S3C24XX_BPPMODE_TFT_16 0x0C
+#define S3C24XX_BPPMODE_TFT_24 0x0D
+
+#define S3C24XX_PNRMODE_STN_04_DS 0
+#define S3C24XX_PNRMODE_STN_04_SS 1
+#define S3C24XX_PNRMODE_STN_08_SS 2
+#define S3C24XX_PNRMODE_TFT 3
+
+#define S3C24XX_GPIO_PORT_A S3C2440_GPIO_PORT_A
+#define S3C24XX_GPIO_PORT_B S3C2440_GPIO_PORT_B
+#define S3C24XX_GPIO_PORT_C S3C2440_GPIO_PORT_C
+#define S3C24XX_GPIO_PORT_D S3C2440_GPIO_PORT_D
+#define S3C24XX_GPIO_PORT_E S3C2440_GPIO_PORT_E
+#define S3C24XX_GPIO_PORT_F S3C2440_GPIO_PORT_F
+#define S3C24XX_GPIO_PORT_G S3C2440_GPIO_PORT_G
+#define S3C24XX_GPIO_PORT_H S3C2440_GPIO_PORT_H
+#define S3C24XX_GPIO_PORT_J S3C2440_GPIO_PORT_J
+
+/*******************************************************************************
+ TYPE DEFINITIONS
+*******************************************************************************/
+
+typedef struct
+{
+ UINT32 data[0x34/4];
+} s3c24xx_memcon_regs_t;
+
+typedef struct
+{
+ UINT32 data[0x5C/4];
+} s3c24xx_usbhost_regs_t;
+
+typedef struct
+{
+ UINT32 srcpnd;
+ UINT32 intmod;
+ UINT32 intmsk;
+ UINT32 priority;
+ UINT32 intpnd;
+ UINT32 intoffset;
+ UINT32 subsrcpnd;
+ UINT32 intsubmsk;
+} s3c24xx_irq_regs_t;
+
+typedef struct
+{
+ UINT32 disrc;
+ UINT32 disrcc;
+ UINT32 didst;
+ UINT32 didstc;
+ UINT32 dcon;
+ UINT32 dstat;
+ UINT32 dcsrc;
+ UINT32 dcdst;
+ UINT32 dmasktrig;
+} s3c24xx_dma_regs_t;
+
+typedef struct
+{
+ UINT32 locktime;
+ UINT32 mpllcon;
+ UINT32 upllcon;
+ UINT32 clkcon;
+ UINT32 clkslow;
+ UINT32 clkdivn;
+ UINT32 camdivn;
+} s3c24xx_clkpow_regs_t;
+
+typedef struct
+{
+ UINT32 lcdcon1;
+ UINT32 lcdcon2;
+ UINT32 lcdcon3;
+ UINT32 lcdcon4;
+ UINT32 lcdcon5;
+ UINT32 lcdsaddr1;
+ UINT32 lcdsaddr2;
+ UINT32 lcdsaddr3;
+ UINT32 redlut;
+ UINT32 greenlut;
+ UINT32 bluelut;
+ UINT32 reserved[8];
+ UINT32 dithmode;
+ UINT32 tpal;
+ UINT32 lcdintpnd;
+ UINT32 lcdsrcpnd;
+ UINT32 lcdintmsk;
+ UINT32 tconsel;
+} s3c24xx_lcd_regs_t;
+
+typedef struct
+{
+ UINT32 data[0x400/4];
+} s3c24xx_lcdpal_regs_t;
+
+typedef struct
+{
+ UINT32 nfconf;
+ UINT32 nfcont;
+ UINT32 nfcmd;
+ UINT32 nfaddr;
+ UINT32 nfdata;
+ UINT32 nfmeccd0;
+ UINT32 nfmeccd1;
+ UINT32 nfseccd;
+ UINT32 nfstat;
+ UINT32 nfestat0;
+ UINT32 nfestat1;
+ UINT32 nfmecc0;
+ UINT32 nfmecc1;
+ UINT32 nfsecc;
+ UINT32 nfsblk;
+ UINT32 nfeblk;
+} s3c24xx_nand_regs_t;
+
+typedef struct
+{
+ UINT32 data[0xA4/4];
+} s3c24xx_cam_regs_t;
+
+typedef struct
+{
+ UINT32 ulcon;
+ UINT32 ucon;
+ UINT32 ufcon;
+ UINT32 umcon;
+ UINT32 utrstat;
+ UINT32 uerstat;
+ UINT32 ufstat;
+ UINT32 umstat;
+ UINT32 utxh;
+ UINT32 urxh;
+ UINT32 ubrdiv;
+} s3c24xx_uart_regs_t;
+
+typedef struct
+{
+ UINT32 tcfg0;
+ UINT32 tcfg1;
+ UINT32 tcon;
+ UINT32 tcntb0;
+ UINT32 tcmpb0;
+ UINT32 tcnto0;
+ UINT32 tcntb1;
+ UINT32 tcmpb1;
+ UINT32 tcnto1;
+ UINT32 tcntb2;
+ UINT32 tcmpb2;
+ UINT32 tcnto2;
+ UINT32 tcntb3;
+ UINT32 tcmpb3;
+ UINT32 tcnto3;
+ UINT32 tcntb4;
+ UINT32 tcnto4;
+} s3c24xx_pwm_regs_t;
+
+typedef struct
+{
+ UINT32 data[0x130/4];
+} s3c24xx_usbdev_regs_t;
+
+typedef struct
+{
+ UINT32 wtcon;
+ UINT32 wtdat;
+ UINT32 wtcnt;
+} s3c24xx_wdt_regs_t;
+
+typedef struct
+{
+ UINT32 iiccon;
+ UINT32 iicstat;
+ UINT32 iicadd;
+ UINT32 iicds;
+ UINT32 iiclc;
+} s3c24xx_iic_regs_t;
+
+typedef struct
+{
+ UINT32 iiscon;
+ UINT32 iismod;
+ UINT32 iispsr;
+ UINT32 iisfcon;
+ UINT32 iisfifo;
+} s3c24xx_iis_regs_t;
+
+typedef struct
+{
+ UINT32 gpacon;
+ UINT32 gpadat;
+ UINT32 pad_08;
+ UINT32 pad_0c;
+ UINT32 gpbbon;
+ UINT32 gpbdat;
+ UINT32 gpbup;
+ UINT32 pad_1c;
+ UINT32 gpccon;
+ UINT32 gpcdat;
+ UINT32 gpcup;
+ UINT32 pad_2c;
+ UINT32 gpdcon;
+ UINT32 gpddat;
+ UINT32 gpdup;
+ UINT32 pad_3c;
+ UINT32 gpecon;
+ UINT32 gpedat;
+ UINT32 gpeup;
+ UINT32 pad_4c;
+ UINT32 gpfcon;
+ UINT32 gpfdat;
+ UINT32 gpfup;
+ UINT32 pad_5c;
+ UINT32 gpgcon;
+ UINT32 gpgdat;
+ UINT32 gpgup;
+ UINT32 pad_6c;
+ UINT32 gphcon;
+ UINT32 gphdat;
+ UINT32 gphup;
+ UINT32 pad_7c;
+ UINT32 misccr;
+ UINT32 dclkcon;
+ UINT32 extint0;
+ UINT32 extint1;
+ UINT32 extint2;
+ UINT32 eintflt0;
+ UINT32 eintflt1;
+ UINT32 eintflt2;
+ UINT32 eintflt3;
+ UINT32 eintmask;
+ UINT32 eintpend;
+ UINT32 gstatus0;
+ UINT32 gstatus1;
+ UINT32 gstatus2;
+ UINT32 gstatus3;
+ UINT32 gstatus4;
+ UINT32 pad_c0;
+ UINT32 pad_c4;
+ UINT32 pad_c8;
+ UINT32 mslcon;
+ UINT32 gpjcon;
+ UINT32 gpjdat;
+ UINT32 gpjup;
+} s3c24xx_gpio_regs_t;
+
+typedef struct
+{
+ UINT32 rtccon;
+ UINT32 ticnt;
+ UINT32 reserved[2];
+ UINT32 rtcalm;
+ UINT32 almsec;
+ UINT32 almmin;
+ UINT32 almhour;
+ UINT32 almday;
+ UINT32 almmon;
+ UINT32 almyear;
+ UINT32 rtcrst;
+ UINT32 bcdsec;
+ UINT32 bcdmin;
+ UINT32 bcdhour;
+ UINT32 bcdday;
+ UINT32 bcddow;
+ UINT32 bcdmon;
+ UINT32 bcdyear;
+} s3c24xx_rtc_regs_t;
+
+typedef struct
+{
+ UINT32 adccon;
+ UINT32 adctsc;
+ UINT32 adcdly;
+ UINT32 adcdat0;
+ UINT32 adcdat1;
+ UINT32 adcupdn;
+} s3c24xx_adc_regs_t;
+
+typedef struct
+{
+ UINT32 spcon;
+ UINT32 spsta;
+ UINT32 sppin;
+ UINT32 sppre;
+ UINT32 sptdat;
+ UINT32 sprdat;
+} s3c24xx_spi_regs_t;
+
+typedef struct
+{
+ UINT32 data[0x44/4];
+} s3c24xx_sdi_regs_t;
+
+typedef struct
+{
+ UINT32 data[0x20/4];
+} s3c24xx_ac97_regs_t;
+
+typedef struct
+{
+ s3c24xx_memcon_regs_t regs;
+} s3c24xx_memcon_t;
+
+typedef struct
+{
+ s3c24xx_usbhost_regs_t regs;
+} s3c24xx_usbhost_t;
+
+typedef struct
+{
+ s3c24xx_irq_regs_t regs;
+ int line_irq, line_fiq;
+} s3c24xx_irq_t;
+
+typedef struct
+{
+ s3c24xx_dma_regs_t regs;
+ emu_timer *timer;
+} s3c24xx_dma_t;
+
+typedef struct
+{
+ s3c24xx_clkpow_regs_t regs;
+} s3c24xx_clkpow_t;
+
+typedef struct
+{
+ s3c24xx_lcd_regs_t regs;
+ emu_timer *timer;
+ bitmap_t *bitmap[2];
+ UINT32 vramaddr_cur;
+ UINT32 vramaddr_max;
+ UINT32 offsize;
+ UINT32 pagewidth_cur;
+ UINT32 pagewidth_max;
+ UINT32 bppmode;
+ UINT32 bswp, hwswp;
+ int vpos, hpos;
+ double framerate;
+ UINT32 tpal;
+ UINT32 hpos_min, hpos_max, vpos_min, vpos_max;
+ UINT32 dma_data, dma_bits;
+} s3c24xx_lcd_t;
+
+typedef struct
+{
+ s3c24xx_lcdpal_regs_t regs;
+} s3c24xx_lcdpal_t;
+
+typedef struct
+{
+ s3c24xx_nand_regs_t regs;
+ UINT8 mecc[4];
+ UINT8 secc[2];
+ int pos;
+} s3c24xx_nand_t;
+
+typedef struct
+{
+ s3c24xx_cam_regs_t regs;
+} s3c24xx_cam_t;
+
+typedef struct
+{
+ s3c24xx_uart_regs_t regs;
+} s3c24xx_uart_t;
+
+typedef struct
+{
+ s3c24xx_pwm_regs_t regs;
+ emu_timer *timer[5];
+ UINT32 cnt[5];
+ UINT32 cmp[5];
+ UINT32 freq[5];
+} s3c24xx_pwm_t;
+
+typedef struct
+{
+ s3c24xx_usbdev_regs_t regs;
+} s3c24xx_usbdev_t;
+
+typedef struct
+{
+ s3c24xx_wdt_regs_t regs;
+ emu_timer *timer;
+} s3c24xx_wdt_t;
+
+typedef struct
+{
+ s3c24xx_iic_regs_t regs;
+ emu_timer *timer;
+ int count;
+} s3c24xx_iic_t;
+
+typedef struct
+{
+ s3c24xx_iis_regs_t regs;
+ emu_timer *timer;
+ UINT16 fifo[16/2];
+ int fifo_index;
+} s3c24xx_iis_t;
+
+typedef struct
+{
+ s3c24xx_gpio_regs_t regs;
+} s3c24xx_gpio_t;
+
+typedef struct
+{
+ s3c24xx_rtc_regs_t regs;
+ emu_timer *timer_tick_count;
+ emu_timer *timer_update;
+} s3c24xx_rtc_t;
+
+typedef struct
+{
+ s3c24xx_adc_regs_t regs;
+} s3c24xx_adc_t;
+
+typedef struct
+{
+ s3c24xx_spi_regs_t regs;
+} s3c24xx_spi_t;
+
+typedef struct
+{
+ s3c24xx_sdi_regs_t regs;
+} s3c24xx_sdi_t;
+
+typedef struct
+{
+ s3c24xx_ac97_regs_t regs;
+} s3c24xx_ac97_t;
+
+typedef struct
+{
+ const s3c2440_interface *iface;
+ s3c24xx_memcon_t memcon;
+ s3c24xx_usbhost_t usbhost;
+ s3c24xx_irq_t irq;
+ s3c24xx_dma_t dma[4];
+ s3c24xx_clkpow_t clkpow;
+ s3c24xx_lcd_t lcd;
+ s3c24xx_lcdpal_t lcdpal;
+ s3c24xx_nand_t nand;
+ s3c24xx_cam_t cam;
+ s3c24xx_uart_t uart[3];
+ s3c24xx_pwm_t pwm;
+ s3c24xx_usbdev_t usbdev;
+ s3c24xx_wdt_t wdt;
+ s3c24xx_iic_t iic;
+ s3c24xx_iis_t iis;
+ s3c24xx_gpio_t gpio;
+ s3c24xx_rtc_t rtc;
+ s3c24xx_adc_t adc;
+ s3c24xx_spi_t spi[2];
+ s3c24xx_sdi_t sdi;
+ s3c24xx_ac97_t ac97;
+} s3c24xx_t;
+
+#endif
diff --git a/trunk/src/emu/machine/s3c24xx.c b/trunk/src/emu/machine/s3c24xx.c
new file mode 100644
index 00000000000..77218904352
--- /dev/null
+++ b/trunk/src/emu/machine/s3c24xx.c
@@ -0,0 +1,3200 @@
+/*******************************************************************************
+
+ Samsung S3C2400 / S3C2410 / S3C2440
+
+*******************************************************************************/
+
+#include "emu.h"
+#include "cpu/arm7/arm7.h"
+#include "cpu/arm7/arm7core.h"
+//#include "includes/s3c24xx.h"
+#include "coreutil.h"
+
+/*******************************************************************************
+ MACROS & CONSTANTS
+*******************************************************************************/
+
+//#define UART_PRINTF
+
+#define CLOCK_MULTIPLIER 1
+
+#define BIT(x,n) (((x)>>(n))&1)
+#define BITS(x,m,n) (((x)>>(n))&(((UINT32)1<<((m)-(n)+1))-1))
+#define CLR_BITS(x,m,n) ((x) & ~((((UINT32)1 << ((m) - (n) + 1)) - 1) << n))
+
+#if defined(DEVICE_S3C2400)
+
+#define S3C24XX_TPAL_GET_TPALEN(x) BIT(x,16)
+#define S3C24XX_TPAL_GET_TPALVAL(x) BITS(x,15,0)
+
+#else
+
+#define S3C24XX_TPAL_GET_TPALEN(x) BIT(x,24)
+#define S3C24XX_TPAL_GET_TPALVAL(x) BITS(x,23,0)
+
+#endif
+
+#define S3C24XX_DCON_GET_TC(x) BITS(x,19,0)
+#define S3C24XX_DCON_GET_DSZ(x) BITS(x,21,20)
+#define S3C24XX_DCON_GET_RELOAD(x) BIT(x,22)
+#define S3C24XX_DCON_GET_SWHWSEL(x) BIT(x,23)
+
+#define S3C24XX_DSTAT_GET_CURR_TC(x) BITS(x,19,0)
+#define S3C24XX_DSTAT_SET_CURR_TC(x,m) (CLR_BITS(x,19,0) | m)
+
+#define S3C24XX_DMASKTRIG_GET_ON_OFF(x) BIT(x,1)
+
+#if defined(DEVICE_S3C2400)
+
+#define S3C24XX_DCON_GET_HWSRCSEL(x) BITS(x,25,24)
+#define S3C24XX_DCON_GET_SERVMODE(x) BIT(x,26)
+#define S3C24XX_DCON_GET_TSZ(x) BIT(x,27)
+#define S3C24XX_DCON_GET_INT(x) BIT(x,28)
+
+#define S3C24XX_DISRC_GET_SADDR(x) BITS(x,28,0)
+
+#define S3C24XX_DIDST_GET_DADDR(x) BITS(x,28,0)
+
+#define S3C24XX_DCSRC_GET_CURR_SRC(x) BITS(x,28,0)
+#define S3C24XX_DCSRC_SET_CURR_SRC(x,m) (CLR_BITS(x,28,0) | m)
+
+#define S3C24XX_DCDST_GET_CURR_DST(x) BITS(x,28,0)
+#define S3C24XX_DCDST_SET_CURR_DST(x,m) (CLR_BITS(x,28,0) | m)
+
+#else
+
+#define S3C24XX_DCON_GET_HWSRCSEL(x) BITS(x,26,24)
+#define S3C24XX_DCON_GET_SERVMODE(x) BIT(x,27)
+#define S3C24XX_DCON_GET_TSZ(x) BIT(x,28)
+#define S3C24XX_DCON_GET_INT(x) BIT(x,29)
+
+#define S3C24XX_DISRC_GET_SADDR(x) BITS(x,30,0)
+
+#define S3C24XX_DIDST_GET_DADDR(x) BITS(x,30,0)
+
+#define S3C24XX_DCSRC_GET_CURR_SRC(x) BITS(x,30,0)
+#define S3C24XX_DCSRC_SET_CURR_SRC(x,m) (CLR_BITS(x,30,0) | m)
+
+#define S3C24XX_DCDST_GET_CURR_DST(x) BITS(x,30,0)
+#define S3C24XX_DCDST_SET_CURR_DST(x,m) (CLR_BITS(x,30,0) | m)
+
+#endif
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+#if defined(DEVICE_S3C2400)
+typedef s3c2400_interface s3c24xx_interface;
+#elif defined(DEVICE_S3C2410)
+typedef s3c2410_interface s3c24xx_interface;
+#elif defined(DEVICE_S3C2440)
+typedef s3c2440_interface s3c24xx_interface;
+#endif
+
+/***************************************************************************
+ PROTOTYPES
+***************************************************************************/
+
+static UINT32 s3c24xx_get_fclk( device_t *device);
+static UINT32 s3c24xx_get_hclk( device_t *device);
+static UINT32 s3c24xx_get_pclk( device_t *device);
+
+static void s3c24xx_dma_request_iis( device_t *device);
+static void s3c24xx_dma_request_pwm( device_t *device);
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE s3c24xx_t *get_token( device_t *device)
+{
+ assert(device != NULL);
+ return (s3c24xx_t *)downcast<legacy_device_base *>(device)->token();
+}
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+/* ... */
+
+static void s3c24xx_reset( device_t *device)
+{
+ fatalerror( "s3c24xx_reset\n");
+}
+
+/* LCD Controller */
+
+static rgb_t s3c24xx_get_color_tft_16( device_t *device, UINT16 data)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ if ((s3c24xx->lcd.regs.lcdcon5 & (1 << 11)) == 0)
+ {
+ UINT8 r, g, b, i;
+ r = (BITS( data, 15, 11) << 3);
+ g = (BITS( data, 10, 6) << 3);
+ b = (BITS( data, 5, 1) << 3);
+ i = BIT( data, 1) << 2;
+ return MAKE_RGB( r | i, g | i, b | i);
+ }
+ else
+ {
+ UINT8 r, g, b;
+ r = BITS( data, 15, 11) << 3;
+ g = BITS( data, 10, 5) << 2;
+ b = BITS( data, 4, 0) << 3;
+ return MAKE_RGB( r, g, b);
+ }
+}
+
+#if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
+
+static rgb_t s3c24xx_get_color_tft_24( device_t *device, UINT32 data)
+{
+ UINT8 r, g, b;
+ r = BITS( data, 23, 16);
+ g = BITS( data, 15, 8);
+ b = BITS( data, 7, 0);
+ return MAKE_RGB( r, g, b);
+}
+
+#endif
+
+static rgb_t s3c24xx_get_color_stn_12( device_t *device, UINT16 data)
+{
+ UINT8 r, g, b;
+ r = BITS( data, 11, 8) << 4;
+ g = BITS( data, 7, 4) << 4;
+ b = BITS( data, 3, 0) << 4;
+ return MAKE_RGB( r, g, b);
+}
+
+static rgb_t s3c24xx_get_color_stn_08( device_t *device, UINT8 data)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT8 r, g, b;
+ r = ((s3c24xx->lcd.regs.redlut >> (BITS( data, 7, 5) << 2)) & 0xF) << 4;
+ g = ((s3c24xx->lcd.regs.greenlut >> (BITS( data, 4, 2) << 2)) & 0xF) << 4;
+ b = ((s3c24xx->lcd.regs.bluelut >> (BITS( data, 1, 0) << 2)) & 0xF) << 4;
+ return MAKE_RGB( r, g, b);
+}
+
+static rgb_t s3c24xx_get_color_stn_01( device_t *device, UINT8 data)
+{
+ if ((data & 1) == 0)
+ {
+ return RGB_BLACK;
+ }
+ else
+ {
+ return RGB_WHITE;
+ }
+}
+
+static rgb_t s3c24xx_get_color_stn_02( device_t *device, UINT8 data)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT8 r, g, b;
+ r = g = b = ((s3c24xx->lcd.regs.bluelut >> (BITS( data, 1, 0) << 2)) & 0xF) << 4;
+ return MAKE_RGB( r, g, b);
+}
+
+static rgb_t s3c24xx_get_color_stn_04( device_t *device, UINT8 data)
+{
+ UINT8 r, g, b;
+ r = g = b = BITS( data, 3, 0) << 4;
+ return MAKE_RGB( r, g, b);
+}
+
+static rgb_t s3c24xx_get_color_tpal( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+#if defined(DEVICE_S3C2400)
+ return s3c24xx_get_color_tft_16( device, S3C24XX_TPAL_GET_TPALVAL( s3c24xx->lcd.tpal));
+#else
+ return s3c24xx_get_color_tft_24( device, S3C24XX_TPAL_GET_TPALVAL( s3c24xx->lcd.tpal));
+#endif
+}
+
+static void s3c24xx_lcd_dma_reload( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ s3c24xx->lcd.vramaddr_cur = s3c24xx->lcd.regs.lcdsaddr1 << 1;
+ s3c24xx->lcd.vramaddr_max = ((s3c24xx->lcd.regs.lcdsaddr1 & 0xFFE00000) | s3c24xx->lcd.regs.lcdsaddr2) << 1;
+ s3c24xx->lcd.offsize = BITS( s3c24xx->lcd.regs.lcdsaddr3, 21, 11);
+ s3c24xx->lcd.pagewidth_cur = 0;
+ s3c24xx->lcd.pagewidth_max = BITS( s3c24xx->lcd.regs.lcdsaddr3, 10, 0);
+ verboselog( device->machine(), 3, "LCD - vramaddr %08X %08X offsize %08X pagewidth %08X\n", s3c24xx->lcd.vramaddr_cur, s3c24xx->lcd.vramaddr_max, s3c24xx->lcd.offsize, s3c24xx->lcd.pagewidth_max);
+ s3c24xx->lcd.dma_data = 0;
+ s3c24xx->lcd.dma_bits = 0;
+}
+
+static void s3c24xx_lcd_dma_init( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ s3c24xx_lcd_dma_reload( device);
+ s3c24xx->lcd.bppmode = BITS( s3c24xx->lcd.regs.lcdcon1, 4, 1);
+ s3c24xx->lcd.bswp = BIT( s3c24xx->lcd.regs.lcdcon5, 1);
+ s3c24xx->lcd.hwswp = BIT( s3c24xx->lcd.regs.lcdcon5, 0);
+ s3c24xx->lcd.tpal = s3c24xx->lcd.regs.tpal;
+ verboselog( device->machine(), 3, "LCD - bppmode %d hwswp %d bswp %d\n", s3c24xx->lcd.bppmode, s3c24xx->lcd.hwswp, s3c24xx->lcd.bswp);
+ s3c24xx->lcd.dma_data = 0;
+ s3c24xx->lcd.dma_bits = 0;
+}
+
+#if 0
+static UINT32 s3c24xx_lcd_dma_read( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ address_space* space = device->machine().device( "maincpu")->memory().space( AS_PROGRAM);
+ UINT8 *vram, data[4];
+ vram = (UINT8 *)space->get_read_ptr( s3c24xx->lcd.vramaddr_cur);
+ for (int i = 0; i < 2; i++)
+ {
+ data[i*2+0] = *vram++;
+ data[i*2+1] = *vram++;
+ s3c24xx->lcd.vramaddr_cur += 2;
+ s3c24xx->lcd.pagewidth_cur++;
+ if (s3c24xx->lcd.pagewidth_cur >= s3c24xx->lcd.pagewidth_max)
+ {
+ s3c24xx->lcd.vramaddr_cur += s3c24xx->lcd.offsize << 1;
+ s3c24xx->lcd.pagewidth_cur = 0;
+ vram = (UINT8 *)space->get_read_ptr( s3c24xx->lcd.vramaddr_cur);
+ }
+ }
+ if (s3c24xx->lcd.hwswp == 0)
+ {
+ if (s3c24xx->lcd.bswp == 0)
+ {
+ return (data[3] << 24) | (data[2] << 16) | (data[1] << 8) | (data[0] << 0);
+ }
+ else
+ {
+ return (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | (data[3] << 0);
+ }
+ }
+ else
+ {
+ if (s3c24xx->lcd.bswp == 0)
+ {
+ return (data[1] << 24) | (data[0] << 16) | (data[3] << 8) | (data[2] << 0);
+ }
+ else
+ {
+ return (data[2] << 24) | (data[3] << 16) | (data[0] << 8) | (data[1] << 0);
+ }
+ }
+}
+#endif
+
+static UINT32 s3c24xx_lcd_dma_read( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ address_space* space = device->machine().device( "maincpu")->memory().space( AS_PROGRAM);
+ UINT8 *vram, data[4];
+ vram = (UINT8 *)space->get_read_ptr( s3c24xx->lcd.vramaddr_cur);
+ for (int i = 0; i < 2; i++)
+ {
+ if (s3c24xx->lcd.hwswp == 0)
+ {
+ if (s3c24xx->lcd.bswp == 0)
+ {
+ if ((s3c24xx->lcd.vramaddr_cur & 2) == 0)
+ {
+ data[i*2+0] = *(vram + 3);
+ data[i*2+1] = *(vram + 2);
+ }
+ else
+ {
+ data[i*2+0] = *(vram - 1);
+ data[i*2+1] = *(vram - 2);
+ }
+ }
+ else
+ {
+ data[i*2+0] = *(vram + 0);
+ data[i*2+1] = *(vram + 1);
+ }
+ }
+ else
+ {
+ if (s3c24xx->lcd.bswp == 0)
+ {
+ data[i*2+0] = *(vram + 1);
+ data[i*2+1] = *(vram + 0);
+ }
+ else
+ {
+ if ((s3c24xx->lcd.vramaddr_cur & 2) == 0)
+ {
+ data[i*2+0] = *(vram + 2);
+ data[i*2+1] = *(vram + 3);
+ }
+ else
+ {
+ data[i*2+0] = *(vram - 2);
+ data[i*2+1] = *(vram - 1);
+ }
+ }
+ }
+ s3c24xx->lcd.vramaddr_cur += 2;
+ s3c24xx->lcd.pagewidth_cur++;
+ if (s3c24xx->lcd.pagewidth_cur >= s3c24xx->lcd.pagewidth_max)
+ {
+ s3c24xx->lcd.vramaddr_cur += s3c24xx->lcd.offsize << 1;
+ s3c24xx->lcd.pagewidth_cur = 0;
+ vram = (UINT8 *)space->get_read_ptr( s3c24xx->lcd.vramaddr_cur);
+ }
+ else
+ {
+ vram += 2;
+ }
+ }
+ if (s3c24xx->iface->lcd.flags & S3C24XX_INTERFACE_LCD_REVERSE)
+ {
+ return (data[3] << 24) | (data[2] << 16) | (data[1] << 8) | (data[0] << 0);
+ }
+ else
+ {
+ return (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | (data[3] << 0);
+ }
+}
+
+static UINT32 s3c24xx_lcd_dma_read_bits( device_t *device, int count)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 data;
+ if (count <= s3c24xx->lcd.dma_bits)
+ {
+ s3c24xx->lcd.dma_bits -= count;
+ data = BITS( s3c24xx->lcd.dma_data, 31, 32 - count);
+ s3c24xx->lcd.dma_data = s3c24xx->lcd.dma_data << count;
+ }
+ else
+ {
+ if (s3c24xx->lcd.dma_bits == 0)
+ {
+ if (count == 32)
+ {
+ data = s3c24xx_lcd_dma_read( device);
+ }
+ else
+ {
+ UINT32 temp = s3c24xx_lcd_dma_read( device);
+ data = BITS( temp, 31, 32 - count);
+ s3c24xx->lcd.dma_data = temp << count;
+ s3c24xx->lcd.dma_bits = 32 - count;
+ }
+ }
+ else
+ {
+ UINT32 temp = s3c24xx_lcd_dma_read( device);
+ data = (s3c24xx->lcd.dma_data >> (32 - count)) | BITS( temp, 31, 32 - (count - s3c24xx->lcd.dma_bits));
+ s3c24xx->lcd.dma_data = temp << (count - s3c24xx->lcd.dma_bits);
+ s3c24xx->lcd.dma_bits = 32 - (count - s3c24xx->lcd.dma_bits);
+ }
+ }
+ return data;
+}
+
+static void s3c24xx_lcd_render_tpal( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ bitmap_t *bitmap = s3c24xx->lcd.bitmap[0];
+ UINT32 color = s3c24xx_get_color_tpal( device);
+ for (int y = s3c24xx->lcd.vpos_min; y <= s3c24xx->lcd.vpos_max; y++)
+ {
+ UINT32 *scanline = BITMAP_ADDR32( bitmap, y, s3c24xx->lcd.hpos_min);
+ for (int x = s3c24xx->lcd.hpos_min; x <= s3c24xx->lcd.hpos_max; x++)
+ {
+ *scanline++ = color;
+ }
+ }
+}
+
+static void s3c24xx_lcd_render_stn_01( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ bitmap_t *bitmap = s3c24xx->lcd.bitmap[0];
+ UINT32 *scanline = BITMAP_ADDR32( bitmap, s3c24xx->lcd.vpos, s3c24xx->lcd.hpos);
+ for (int i = 0; i < 4; i++)
+ {
+ UINT32 data = s3c24xx_lcd_dma_read( device);
+ for (int j = 0; j < 32; j++)
+ {
+ if (s3c24xx->iface->lcd.flags & S3C24XX_INTERFACE_LCD_REVERSE)
+ {
+ *scanline++ = s3c24xx_get_color_stn_01( device, data & 0x01);
+ data = data >> 1;
+ }
+ else
+ {
+ *scanline++ = s3c24xx_get_color_stn_01( device, (data >> 31) & 0x01);
+ data = data << 1;
+ }
+ s3c24xx->lcd.hpos++;
+ if (s3c24xx->lcd.hpos >= s3c24xx->lcd.hpos_min + (s3c24xx->lcd.pagewidth_max << 4))
+ {
+ s3c24xx->lcd.vpos++;
+ if (s3c24xx->lcd.vpos > s3c24xx->lcd.vpos_max) s3c24xx->lcd.vpos = s3c24xx->lcd.vpos_min;
+ s3c24xx->lcd.hpos = s3c24xx->lcd.hpos_min;
+ scanline = BITMAP_ADDR32( bitmap, s3c24xx->lcd.vpos, s3c24xx->lcd.hpos);
+ }
+ }
+ }
+}
+
+static void s3c24xx_lcd_render_stn_02( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ bitmap_t *bitmap = s3c24xx->lcd.bitmap[0];
+ UINT32 *scanline = BITMAP_ADDR32( bitmap, s3c24xx->lcd.vpos, s3c24xx->lcd.hpos);
+ for (int i = 0; i < 4; i++)
+ {
+ UINT32 data = s3c24xx_lcd_dma_read( device);
+ for (int j = 0; j < 16; j++)
+ {
+ *scanline++ = s3c24xx_get_color_stn_02( device, (data >> 30) & 0x03);
+ data = data << 2;
+ s3c24xx->lcd.hpos++;
+ if (s3c24xx->lcd.hpos >= s3c24xx->lcd.hpos_min + (s3c24xx->lcd.pagewidth_max << 3))
+ {
+ s3c24xx->lcd.vpos++;
+ if (s3c24xx->lcd.vpos > s3c24xx->lcd.vpos_max) s3c24xx->lcd.vpos = s3c24xx->lcd.vpos_min;
+ s3c24xx->lcd.hpos = s3c24xx->lcd.hpos_min;
+ scanline = BITMAP_ADDR32( bitmap, s3c24xx->lcd.vpos, s3c24xx->lcd.hpos);
+ }
+ }
+ }
+}
+
+static void s3c24xx_lcd_render_stn_04( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ bitmap_t *bitmap = s3c24xx->lcd.bitmap[0];
+ UINT32 *scanline = BITMAP_ADDR32( bitmap, s3c24xx->lcd.vpos, s3c24xx->lcd.hpos);
+ for (int i = 0; i < 4; i++)
+ {
+ UINT32 data = s3c24xx_lcd_dma_read( device);
+ for (int j = 0; j < 8; j++)
+ {
+ *scanline++ = s3c24xx_get_color_stn_04( device, (data >> 28) & 0x0F);
+ data = data << 4;
+ s3c24xx->lcd.hpos++;
+ if (s3c24xx->lcd.hpos >= s3c24xx->lcd.hpos_min + (s3c24xx->lcd.pagewidth_max << 2))
+ {
+ s3c24xx->lcd.vpos++;
+ if (s3c24xx->lcd.vpos > s3c24xx->lcd.vpos_max) s3c24xx->lcd.vpos = s3c24xx->lcd.vpos_min;
+ s3c24xx->lcd.hpos = s3c24xx->lcd.hpos_min;
+ scanline = BITMAP_ADDR32( bitmap, s3c24xx->lcd.vpos, s3c24xx->lcd.hpos);
+ }
+ }
+ }
+}
+
+static void s3c24xx_lcd_render_stn_08( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ bitmap_t *bitmap = s3c24xx->lcd.bitmap[0];
+ UINT32 *scanline = BITMAP_ADDR32( bitmap, s3c24xx->lcd.vpos, s3c24xx->lcd.hpos);
+ for (int i = 0; i < 4; i++)
+ {
+ UINT32 data = s3c24xx_lcd_dma_read( device);
+ for (int j = 0; j < 4; j++)
+ {
+ *scanline++ = s3c24xx_get_color_stn_08( device, (data >> 24) & 0xFF);
+ data = data << 8;
+ s3c24xx->lcd.hpos++;
+ if (s3c24xx->lcd.hpos >= s3c24xx->lcd.hpos_min + (s3c24xx->lcd.pagewidth_max << 1))
+ {
+ s3c24xx->lcd.vpos++;
+ if (s3c24xx->lcd.vpos > s3c24xx->lcd.vpos_max) s3c24xx->lcd.vpos = s3c24xx->lcd.vpos_min;
+ s3c24xx->lcd.hpos = s3c24xx->lcd.hpos_min;
+ scanline = BITMAP_ADDR32( bitmap, s3c24xx->lcd.vpos, s3c24xx->lcd.hpos);
+ }
+ }
+ }
+}
+
+static void s3c24xx_lcd_render_stn_12_p( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ bitmap_t *bitmap = s3c24xx->lcd.bitmap[0];
+ UINT32 *scanline = BITMAP_ADDR32( bitmap, s3c24xx->lcd.vpos, s3c24xx->lcd.hpos);
+ for (int i = 0; i < 16; i++)
+ {
+ *scanline++ = s3c24xx_get_color_stn_12( device, s3c24xx_lcd_dma_read_bits( device, 12));
+ s3c24xx->lcd.hpos++;
+ if (s3c24xx->lcd.hpos >= s3c24xx->lcd.hpos_min + (s3c24xx->lcd.pagewidth_max * 16 / 12))
+ {
+ s3c24xx->lcd.vpos++;
+ if (s3c24xx->lcd.vpos > s3c24xx->lcd.vpos_max) s3c24xx->lcd.vpos = s3c24xx->lcd.vpos_min;
+ s3c24xx->lcd.hpos = s3c24xx->lcd.hpos_min;
+ scanline = BITMAP_ADDR32( bitmap, s3c24xx->lcd.vpos, s3c24xx->lcd.hpos);
+ }
+ }
+}
+
+static void s3c24xx_lcd_render_stn_12_u( device_t *device) // not tested
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ bitmap_t *bitmap = s3c24xx->lcd.bitmap[0];
+ UINT32 *scanline = BITMAP_ADDR32( bitmap, s3c24xx->lcd.vpos, s3c24xx->lcd.hpos);
+ for (int i = 0; i < 4; i++)
+ {
+ UINT32 data = s3c24xx_lcd_dma_read( device);
+ for (int j = 0; j < 2; j++)
+ {
+ *scanline++ = s3c24xx_get_color_stn_12( device, (data >> 16) & 0x0FFF);
+ data = data << 16;
+ s3c24xx->lcd.hpos++;
+ if (s3c24xx->lcd.hpos >= s3c24xx->lcd.hpos_min + (s3c24xx->lcd.pagewidth_max << 0))
+ {
+ s3c24xx->lcd.vpos++;
+ if (s3c24xx->lcd.vpos > s3c24xx->lcd.vpos_max) s3c24xx->lcd.vpos = s3c24xx->lcd.vpos_min;
+ s3c24xx->lcd.hpos = s3c24xx->lcd.hpos_min;
+ scanline = BITMAP_ADDR32( bitmap, s3c24xx->lcd.vpos, s3c24xx->lcd.hpos);
+ }
+ }
+ }
+}
+
+static void s3c24xx_lcd_render_tft_01( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ bitmap_t *bitmap = s3c24xx->lcd.bitmap[0];
+ UINT32 *scanline = BITMAP_ADDR32( bitmap, s3c24xx->lcd.vpos, s3c24xx->lcd.hpos);
+ for (int i = 0; i < 4; i++)
+ {
+ UINT32 data = s3c24xx_lcd_dma_read( device);
+ for (int j = 0; j < 32; j++)
+ {
+ *scanline++ = palette_get_color( device->machine(), (data >> 31) & 0x01);
+ data = data << 1;
+ s3c24xx->lcd.hpos++;
+ if (s3c24xx->lcd.hpos >= s3c24xx->lcd.hpos_min + (s3c24xx->lcd.pagewidth_max << 4))
+ {
+ s3c24xx->lcd.vpos++;
+ if (s3c24xx->lcd.vpos > s3c24xx->lcd.vpos_max) s3c24xx->lcd.vpos = s3c24xx->lcd.vpos_min;
+ s3c24xx->lcd.hpos = s3c24xx->lcd.hpos_min;
+ scanline = BITMAP_ADDR32( bitmap, s3c24xx->lcd.vpos, s3c24xx->lcd.hpos);
+ }
+ }
+ }
+}
+
+static void s3c24xx_lcd_render_tft_02( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ bitmap_t *bitmap = s3c24xx->lcd.bitmap[0];
+ UINT32 *scanline = BITMAP_ADDR32( bitmap, s3c24xx->lcd.vpos, s3c24xx->lcd.hpos);
+ for (int i = 0; i < 4; i++)
+ {
+ UINT32 data = s3c24xx_lcd_dma_read( device);
+ for (int j = 0; j < 16; j++)
+ {
+ *scanline++ = palette_get_color( device->machine(), (data >> 30) & 0x03);
+ data = data << 2;
+ s3c24xx->lcd.hpos++;
+ if (s3c24xx->lcd.hpos >= s3c24xx->lcd.hpos_min + (s3c24xx->lcd.pagewidth_max << 3))
+ {
+ s3c24xx->lcd.vpos++;
+ if (s3c24xx->lcd.vpos > s3c24xx->lcd.vpos_max) s3c24xx->lcd.vpos = s3c24xx->lcd.vpos_min;
+ s3c24xx->lcd.hpos = s3c24xx->lcd.hpos_min;
+ scanline = BITMAP_ADDR32( bitmap, s3c24xx->lcd.vpos, s3c24xx->lcd.hpos);
+ }
+ }
+ }
+}
+
+static void s3c24xx_lcd_render_tft_04( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ bitmap_t *bitmap = s3c24xx->lcd.bitmap[0];
+ UINT32 *scanline = BITMAP_ADDR32( bitmap, s3c24xx->lcd.vpos, s3c24xx->lcd.hpos);
+ for (int i = 0; i < 4; i++)
+ {
+ UINT32 data = s3c24xx_lcd_dma_read( device);
+ for (int j = 0; j < 8; j++)
+ {
+ *scanline++ = palette_get_color( device->machine(), (data >> 28) & 0x0F);
+ data = data << 4;
+ s3c24xx->lcd.hpos++;
+ if (s3c24xx->lcd.hpos >= s3c24xx->lcd.hpos_min + (s3c24xx->lcd.pagewidth_max << 2))
+ {
+ s3c24xx->lcd.vpos++;
+ if (s3c24xx->lcd.vpos > s3c24xx->lcd.vpos_max) s3c24xx->lcd.vpos = s3c24xx->lcd.vpos_min;
+ s3c24xx->lcd.hpos = s3c24xx->lcd.hpos_min;
+ scanline = BITMAP_ADDR32( bitmap, s3c24xx->lcd.vpos, s3c24xx->lcd.hpos);
+ }
+ }
+ }
+}
+
+static void s3c24xx_lcd_render_tft_08( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ bitmap_t *bitmap = s3c24xx->lcd.bitmap[0];
+ UINT32 *scanline = BITMAP_ADDR32( bitmap, s3c24xx->lcd.vpos, s3c24xx->lcd.hpos);
+ for (int i = 0; i < 4; i++)
+ {
+ UINT32 data = s3c24xx_lcd_dma_read( device);
+ for (int j = 0; j < 4; j++)
+ {
+ *scanline++ = palette_get_color( device->machine(), (data >> 24) & 0xFF);
+ data = data << 8;
+ s3c24xx->lcd.hpos++;
+ if (s3c24xx->lcd.hpos >= s3c24xx->lcd.hpos_min + (s3c24xx->lcd.pagewidth_max << 1))
+ {
+ s3c24xx->lcd.vpos++;
+ if (s3c24xx->lcd.vpos > s3c24xx->lcd.vpos_max) s3c24xx->lcd.vpos = s3c24xx->lcd.vpos_min;
+ s3c24xx->lcd.hpos = s3c24xx->lcd.hpos_min;
+ scanline = BITMAP_ADDR32( bitmap, s3c24xx->lcd.vpos, s3c24xx->lcd.hpos);
+ }
+ }
+ }
+}
+
+static void s3c24xx_lcd_render_tft_16( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ bitmap_t *bitmap = s3c24xx->lcd.bitmap[0];
+ UINT32 *scanline = BITMAP_ADDR32( bitmap, s3c24xx->lcd.vpos, s3c24xx->lcd.hpos);
+ for (int i = 0; i < 4; i++)
+ {
+ UINT32 data = s3c24xx_lcd_dma_read( device);
+ for (int j = 0; j < 2; j++)
+ {
+ *scanline++ = s3c24xx_get_color_tft_16( device, (data >> 16) & 0xFFFF);
+ data = data << 16;
+ s3c24xx->lcd.hpos++;
+ if (s3c24xx->lcd.hpos >= s3c24xx->lcd.hpos_min + (s3c24xx->lcd.pagewidth_max << 0))
+ {
+ s3c24xx->lcd.vpos++;
+ if (s3c24xx->lcd.vpos > s3c24xx->lcd.vpos_max) s3c24xx->lcd.vpos = s3c24xx->lcd.vpos_min;
+ s3c24xx->lcd.hpos = s3c24xx->lcd.hpos_min;
+ scanline = BITMAP_ADDR32( bitmap, s3c24xx->lcd.vpos, s3c24xx->lcd.hpos);
+ }
+ }
+ }
+}
+
+static TIMER_CALLBACK( s3c24xx_lcd_timer_exp )
+{
+ device_t *device = (device_t *)ptr;
+ s3c24xx_t *s3c24xx = get_token( device);
+ screen_device *screen = machine.primary_screen;
+ UINT32 tpalen;
+ verboselog( machine, 2, "LCD timer callback\n");
+ s3c24xx->lcd.vpos = screen->vpos();
+ s3c24xx->lcd.hpos = screen->hpos();
+ verboselog( machine, 3, "LCD - vpos %d hpos %d\n", s3c24xx->lcd.vpos, s3c24xx->lcd.hpos);
+ tpalen = S3C24XX_TPAL_GET_TPALEN( s3c24xx->lcd.tpal);
+ if (tpalen == 0)
+ {
+ if (s3c24xx->lcd.vramaddr_cur >= s3c24xx->lcd.vramaddr_max)
+ {
+ s3c24xx_lcd_dma_reload( device);
+ }
+ verboselog( machine, 3, "LCD - vramaddr %08X\n", s3c24xx->lcd.vramaddr_cur);
+ while (s3c24xx->lcd.vramaddr_cur < s3c24xx->lcd.vramaddr_max)
+ {
+ switch (s3c24xx->lcd.bppmode)
+ {
+ case S3C24XX_BPPMODE_STN_01 : s3c24xx_lcd_render_stn_01( device); break;
+ case S3C24XX_BPPMODE_STN_02 : s3c24xx_lcd_render_stn_02( device); break;
+ case S3C24XX_BPPMODE_STN_04 : s3c24xx_lcd_render_stn_04( device); break;
+ case S3C24XX_BPPMODE_STN_08 : s3c24xx_lcd_render_stn_08( device); break;
+ case S3C24XX_BPPMODE_STN_12_P : s3c24xx_lcd_render_stn_12_p( device); break;
+ case S3C24XX_BPPMODE_STN_12_U : s3c24xx_lcd_render_stn_12_u( device); break;
+ case S3C24XX_BPPMODE_TFT_01 : s3c24xx_lcd_render_tft_01( device); break;
+ case S3C24XX_BPPMODE_TFT_02 : s3c24xx_lcd_render_tft_02( device); break;
+ case S3C24XX_BPPMODE_TFT_04 : s3c24xx_lcd_render_tft_04( device); break;
+ case S3C24XX_BPPMODE_TFT_08 : s3c24xx_lcd_render_tft_08( device); break;
+ case S3C24XX_BPPMODE_TFT_16 : s3c24xx_lcd_render_tft_16( device); break;
+ default : verboselog( machine, 0, "s3c24xx_lcd_timer_exp: bppmode %d not supported\n", s3c24xx->lcd.bppmode); break;
+ }
+ if ((s3c24xx->lcd.vpos == s3c24xx->lcd.vpos_min) && (s3c24xx->lcd.hpos == s3c24xx->lcd.hpos_min)) break;
+ }
+ }
+ else
+ {
+ s3c24xx_lcd_render_tpal( device);
+ }
+ s3c24xx->lcd.timer->adjust( screen->time_until_pos( s3c24xx->lcd.vpos, s3c24xx->lcd.hpos));
+}
+
+static void s3c24xx_video_start( device_t *device, running_machine &machine)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ screen_device *screen = machine.primary_screen;
+ s3c24xx->lcd.bitmap[0] = screen->alloc_compatible_bitmap();
+ s3c24xx->lcd.bitmap[1] = screen->alloc_compatible_bitmap();
+}
+
+static void bitmap_blend( bitmap_t *bitmap_dst, bitmap_t *bitmap_src_1, bitmap_t *bitmap_src_2)
+{
+ for (int y = 0; y < bitmap_dst->height; y++)
+ {
+ UINT32 *line0 = BITMAP_ADDR32( bitmap_src_1, y, 0);
+ UINT32 *line1 = BITMAP_ADDR32( bitmap_src_2, y, 0);
+ UINT32 *line2 = BITMAP_ADDR32( bitmap_dst, y, 0);
+ for (int x = 0; x < bitmap_dst->width; x++)
+ {
+ UINT32 color0 = line0[x];
+ UINT32 color1 = line1[x];
+ UINT16 r0 = (color0 >> 16) & 0x000000ff;
+ UINT16 g0 = (color0 >> 8) & 0x000000ff;
+ UINT16 b0 = (color0 >> 0) & 0x000000ff;
+ UINT16 r1 = (color1 >> 16) & 0x000000ff;
+ UINT16 g1 = (color1 >> 8) & 0x000000ff;
+ UINT16 b1 = (color1 >> 0) & 0x000000ff;
+ UINT8 r = (UINT8)((r0 + r1) >> 1);
+ UINT8 g = (UINT8)((g0 + g1) >> 1);
+ UINT8 b = (UINT8)((b0 + b1) >> 1);
+ line2[x] = (r << 16) | (g << 8) | b;
+ }
+ }
+}
+
+static UINT32 s3c24xx_video_update( device_t *device, screen_device *screen, bitmap_t *bitmap, const rectangle *cliprect)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ if (s3c24xx->lcd.framerate >= 1195)
+ {
+ bitmap_blend( bitmap, s3c24xx->lcd.bitmap[0], s3c24xx->lcd.bitmap[1]);
+ copybitmap( s3c24xx->lcd.bitmap[1], s3c24xx->lcd.bitmap[0], 0, 0, 0, 0, cliprect);
+ }
+ else
+ {
+ copybitmap( bitmap, s3c24xx->lcd.bitmap[0], 0, 0, 0, 0, cliprect);
+ }
+ s3c24xx_lcd_dma_init( device);
+ return 0;
+}
+
+#if defined(DEVICE_S3C2400)
+READ32_DEVICE_HANDLER( s3c2400_lcd_r )
+#elif defined(DEVICE_S3C2410)
+READ32_DEVICE_HANDLER( s3c2410_lcd_r )
+#elif defined(DEVICE_S3C2440)
+READ32_DEVICE_HANDLER( s3c2440_lcd_r )
+#endif
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 data = ((UINT32*)&s3c24xx->lcd.regs)[offset];
+ switch (offset)
+ {
+ case S3C24XX_LCDCON1 :
+ {
+ // make sure line counter is going
+ UINT32 vpos = device->machine().primary_screen->vpos();
+ if (vpos < s3c24xx->lcd.vpos_min) vpos = s3c24xx->lcd.vpos_min;
+ if (vpos > s3c24xx->lcd.vpos_max) vpos = s3c24xx->lcd.vpos_max;
+ data = (data & ~0xFFFC0000) | ((s3c24xx->lcd.vpos_max - vpos) << 18);
+ }
+ break;
+ case S3C24XX_LCDCON5 :
+ {
+ UINT32 vpos = device->machine().primary_screen->vpos();
+ data = data & ~0x00018000;
+ if (vpos < s3c24xx->lcd.vpos_min) data = data | 0x00000000;
+ if (vpos > s3c24xx->lcd.vpos_max) data = data | 0x00018000;
+ // todo: 00 = VSYNC, 01 = BACK Porch, 10 = ACTIVE, 11 = FRONT Porch
+ }
+ break;
+ }
+ verboselog( device->machine(), 9, "(LCD) %08X -> %08X\n", S3C24XX_BASE_LCD + (offset << 2), data);
+ return data;
+}
+
+static void s3c24xx_lcd_configure_tft( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ screen_device *screen = device->machine().primary_screen;
+ UINT32 vspw, vbpd, lineval, vfpd, hspw, hbpd, hfpd, hozval, clkval, hclk;
+ double framerate, vclk;
+ UINT32 width, height;
+ rectangle visarea;
+ verboselog( device->machine(), 5, "s3c24xx_lcd_configure_tft\n");
+ vspw = BITS( s3c24xx->lcd.regs.lcdcon2, 5, 0);
+ vbpd = BITS( s3c24xx->lcd.regs.lcdcon2, 31, 24);
+ lineval = BITS( s3c24xx->lcd.regs.lcdcon2, 23, 14);
+ vfpd = BITS( s3c24xx->lcd.regs.lcdcon2, 13, 6);
+ hspw = BITS( s3c24xx->lcd.regs.lcdcon4, 7, 0);
+ hbpd = BITS( s3c24xx->lcd.regs.lcdcon3, 25, 19);
+ hfpd = BITS( s3c24xx->lcd.regs.lcdcon3, 7, 0);
+ hozval = BITS( s3c24xx->lcd.regs.lcdcon3, 18, 8);
+ clkval = BITS( s3c24xx->lcd.regs.lcdcon1, 17, 8);
+ hclk = s3c24xx_get_hclk( device);
+ verboselog( device->machine(), 3, "LCD - vspw %d vbpd %d lineval %d vfpd %d hspw %d hbpd %d hfpd %d hozval %d clkval %d hclk %d\n", vspw, vbpd, lineval, vfpd, hspw, hbpd, hfpd, hozval, clkval, hclk);
+ vclk = (double)(hclk / ((clkval + 1) * 2));
+ verboselog( device->machine(), 3, "LCD - vclk %f\n", vclk);
+ framerate = vclk / (((vspw + 1) + (vbpd + 1) + (lineval + 1) + (vfpd + 1)) * ((hspw + 1) + (hbpd + 1) + (hozval + 1) + (hfpd + 1)));
+ verboselog( device->machine(), 3, "LCD - framerate %f\n", framerate);
+ s3c24xx->lcd.framerate = framerate;
+ width = (hspw + 1) + (hbpd + 1) + (hozval + 1) + (hfpd + 1);
+ height = (vspw + 1) + (vbpd + 1) + (lineval + 1) + (vfpd + 1);
+ visarea.min_x = (hspw + 1) + (hbpd + 1);
+ visarea.min_y = (vspw + 1) + (vbpd + 1);
+ visarea.max_x = visarea.min_x + (hozval + 1) - 1;
+ visarea.max_y = visarea.min_y + (lineval + 1) - 1;
+ verboselog( device->machine(), 3, "LCD - visarea min_x %d min_y %d max_x %d max_y %d\n", visarea.min_x, visarea.min_y, visarea.max_x, visarea.max_y);
+ verboselog( device->machine(), 3, "video_screen_configure %d %d %f\n", width, height, s3c24xx->lcd.framerate);
+ s3c24xx->lcd.hpos_min = (hspw + 1) + (hbpd + 1);
+ s3c24xx->lcd.hpos_max = s3c24xx->lcd.hpos_min + (hozval + 1) - 1;
+ s3c24xx->lcd.vpos_min = (vspw + 1) + (vbpd + 1);
+ s3c24xx->lcd.vpos_max = s3c24xx->lcd.vpos_min + (lineval + 1) - 1;
+ screen->configure( width, height, visarea, HZ_TO_ATTOSECONDS( s3c24xx->lcd.framerate));
+}
+
+static void s3c24xx_lcd_configure_stn( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ screen_device *screen = device->machine().primary_screen;
+ UINT32 pnrmode, bppmode, clkval, lineval, wdly, hozval, lineblank, wlh, hclk;
+ double vclk, framerate;
+ UINT32 width, height;
+ rectangle visarea;
+ verboselog( device->machine(), 5, "s3c24xx_lcd_configure_stn\n");
+ pnrmode = BITS( s3c24xx->lcd.regs.lcdcon1, 6, 5);
+ bppmode = BITS( s3c24xx->lcd.regs.lcdcon1, 4, 1);
+ clkval = BITS( s3c24xx->lcd.regs.lcdcon1, 17, 8);
+ lineval = BITS( s3c24xx->lcd.regs.lcdcon2, 23, 14);
+ wdly = BITS( s3c24xx->lcd.regs.lcdcon3, 20, 19);
+ hozval = BITS( s3c24xx->lcd.regs.lcdcon3, 18, 8);
+ lineblank = BITS( s3c24xx->lcd.regs.lcdcon3, 7, 0);
+ wlh = BITS( s3c24xx->lcd.regs.lcdcon4, 1, 0);
+ hclk = s3c24xx_get_hclk( device);
+ verboselog( device->machine(), 3, "LCD - pnrmode %d bppmode %d clkval %d lineval %d wdly %d hozval %d lineblank %d wlh %d hclk %d\n", pnrmode, bppmode, clkval, lineval, wdly, hozval, lineblank, wlh, hclk);
+ vclk = (double)(hclk / ((clkval + 0) * 2));
+ verboselog( device->machine(), 3, "LCD - vclk %f\n", vclk);
+ framerate = 1 / (((1 / vclk) * (hozval + 1) + (1 / hclk) * ((1 << (4 + wlh)) + (1 << (4 + wdly)) + (lineblank * 8))) * (lineval + 1));
+ verboselog( device->machine(), 3, "LCD - framerate %f\n", framerate);
+ switch (pnrmode)
+ {
+ case S3C24XX_PNRMODE_STN_04_SS : width = ((hozval + 1) * 4); break;
+ case S3C24XX_PNRMODE_STN_04_DS : width = ((hozval + 1) * 4); break;
+ case S3C24XX_PNRMODE_STN_08_SS : width = ((hozval + 1) * 8 / 3); break;
+ default : width = 0; break;
+ }
+ height = lineval + 1;
+ s3c24xx->lcd.framerate = framerate;
+ visarea.min_x = 0;
+ visarea.min_y = 0;
+ visarea.max_x = width - 1;
+ visarea.max_y = height - 1;
+ verboselog( device->machine(), 3, "LCD - visarea min_x %d min_y %d max_x %d max_y %d\n", visarea.min_x, visarea.min_y, visarea.max_x, visarea.max_y);
+ verboselog( device->machine(), 3, "video_screen_configure %d %d %f\n", width, height, s3c24xx->lcd.framerate);
+ s3c24xx->lcd.hpos_min = 0;
+ s3c24xx->lcd.hpos_max = width - 1;
+ s3c24xx->lcd.vpos_min = 0;
+ s3c24xx->lcd.vpos_max = height - 1;
+ screen->configure( width, height, visarea, HZ_TO_ATTOSECONDS( s3c24xx->lcd.framerate));
+}
+
+static void s3c24xx_lcd_configure( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 bppmode;
+ verboselog( device->machine(), 5, "s3c24xx_lcd_configure\n");
+ bppmode = BITS( s3c24xx->lcd.regs.lcdcon1, 4, 1);
+ if ((bppmode & (1 << 3)) == 0)
+ {
+ s3c24xx_lcd_configure_stn( device);
+ }
+ else
+ {
+ s3c24xx_lcd_configure_tft( device);
+ }
+}
+
+static void s3c24xx_lcd_start( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ screen_device *screen = device->machine().primary_screen;
+ verboselog( device->machine(), 1, "LCD start\n");
+ s3c24xx_lcd_configure( device);
+ s3c24xx_lcd_dma_init( device);
+ s3c24xx->lcd.timer->adjust( screen->time_until_pos( s3c24xx->lcd.vpos_min, s3c24xx->lcd.hpos_min));
+}
+
+static void s3c24xx_lcd_stop( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ verboselog( device->machine(), 1, "LCD stop\n");
+ s3c24xx->lcd.timer->adjust( attotime::never);
+}
+
+static void s3c24xx_lcd_recalc( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ if (s3c24xx->lcd.regs.lcdcon1 & (1 << 0))
+ {
+ s3c24xx_lcd_start( device);
+ }
+ else
+ {
+ s3c24xx_lcd_stop( device);
+ }
+}
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_lcd_w )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 old_value = ((UINT32*)&s3c24xx->lcd.regs)[offset];
+ verboselog( device->machine(), 9, "(LCD) %08X <- %08X\n", S3C24XX_BASE_LCD + (offset << 2), data);
+ COMBINE_DATA(&((UINT32*)&s3c24xx->lcd.regs)[offset]);
+ switch (offset)
+ {
+ case S3C24XX_LCDCON1 :
+ {
+ if ((old_value & (1 << 0)) != (data & (1 << 0)))
+ {
+ s3c24xx_lcd_recalc( device);
+ }
+ }
+ break;
+ }
+}
+
+/* LCD Palette */
+
+static READ32_DEVICE_HANDLER( s3c24xx_lcd_palette_r )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 data = s3c24xx->lcdpal.regs.data[offset];
+ verboselog( device->machine(), 9, "(LCD) %08X -> %08X\n", S3C24XX_BASE_LCDPAL + (offset << 2), data);
+ return data;
+}
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_lcd_palette_w )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ verboselog( device->machine(), 9, "(LCD) %08X <- %08X\n", S3C24XX_BASE_LCDPAL + (offset << 2), data);
+ COMBINE_DATA(&s3c24xx->lcdpal.regs.data[offset]);
+ if (mem_mask != 0xffffffff)
+ {
+ verboselog( device->machine(), 0, "s3c24xx_lcd_palette_w: unknown mask %08x\n", mem_mask);
+ }
+ palette_set_color( device->machine(), offset, s3c24xx_get_color_tft_16( device, data & 0xFFFF));
+}
+
+/* Clock & Power Management */
+
+static UINT32 s3c24xx_get_fclk( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 data, mdiv, pdiv, sdiv;
+ data = s3c24xx->clkpow.regs.mpllcon;
+ mdiv = BITS( data, 19, 12);
+ pdiv = BITS( data, 9, 4);
+ sdiv = BITS( data, 1, 0);
+#if defined(DEVICE_S3C2400) || defined(DEVICE_S3C2410)
+ return (UINT32)((double)(1 * (mdiv + 8) * device->clock()) / (double)((pdiv + 2) * (1 << sdiv)));
+#else
+ return (UINT32)((double)(2 * (mdiv + 8) * device->clock()) / (double)((pdiv + 2) * (1 << sdiv)));
+#endif
+}
+
+static UINT32 s3c24xx_get_hclk( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+#if defined(DEVICE_S3C2400) || defined(DEVICE_S3C2410)
+ return s3c24xx_get_fclk( device) / (BIT( s3c24xx->clkpow.regs.clkdivn, 1) + 1);
+#else
+ switch (BITS( s3c24xx->clkpow.regs.clkdivn, 2, 1))
+ {
+ case 0 : return s3c24xx_get_fclk( device) / 1;
+ case 1 : return s3c24xx_get_fclk( device) / 2;
+ case 2 : return s3c24xx_get_fclk( device) / (4 * (BIT( s3c24xx->clkpow.regs.camdivn, 9) + 1));
+ case 3 : return s3c24xx_get_fclk( device) / (3 * (BIT( s3c24xx->clkpow.regs.camdivn, 8) + 1));
+ }
+ return 0;
+#endif
+}
+
+static UINT32 s3c24xx_get_pclk( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ return s3c24xx_get_hclk( device) / (1 << BIT( s3c24xx->clkpow.regs.clkdivn, 0));
+}
+
+static READ32_DEVICE_HANDLER( s3c24xx_clkpow_r )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 data = ((UINT32*)&s3c24xx->clkpow.regs)[offset];
+ verboselog( device->machine(), 9, "(CLKPOW) %08X -> %08X\n", S3C24XX_BASE_CLKPOW + (offset << 2), data);
+ return data;
+}
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_clkpow_w )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ verboselog( device->machine(), 9, "(CLKPOW) %08X <- %08X\n", S3C24XX_BASE_CLKPOW + (offset << 2), data);
+ COMBINE_DATA(&((UINT32*)&s3c24xx->clkpow.regs)[offset]);
+ switch (offset)
+ {
+ case S3C24XX_MPLLCON :
+ {
+ verboselog( device->machine(), 5, "CLKPOW - fclk %d hclk %d pclk %d\n", s3c24xx_get_fclk( device), s3c24xx_get_hclk( device), s3c24xx_get_pclk( device));
+ device->machine().device( "maincpu")->set_unscaled_clock(s3c24xx_get_fclk( device) * CLOCK_MULTIPLIER);
+ }
+ break;
+ }
+}
+
+/* Interrupt Controller */
+
+static void s3c24xx_check_pending_irq( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 temp;
+ // normal irq
+ temp = (s3c24xx->irq.regs.srcpnd & ~s3c24xx->irq.regs.intmsk) & ~s3c24xx->irq.regs.intmod;
+ if (temp != 0)
+ {
+ UINT32 int_type = 0;
+ while ((temp & 1) == 0)
+ {
+ int_type++;
+ temp = temp >> 1;
+ }
+ s3c24xx->irq.regs.intpnd |= (1 << int_type);
+ s3c24xx->irq.regs.intoffset = int_type;
+ if (s3c24xx->irq.line_irq != ASSERT_LINE)
+ {
+ cputag_set_input_line( device->machine(), "maincpu", ARM7_IRQ_LINE, ASSERT_LINE);
+ s3c24xx->irq.line_irq = ASSERT_LINE;
+ }
+ }
+ else
+ {
+ if (s3c24xx->irq.line_irq != CLEAR_LINE)
+ {
+ cputag_set_input_line( device->machine(), "maincpu", ARM7_IRQ_LINE, CLEAR_LINE);
+ s3c24xx->irq.line_irq = CLEAR_LINE;
+ }
+ }
+ // fast irq
+ temp = (s3c24xx->irq.regs.srcpnd & ~s3c24xx->irq.regs.intmsk) & s3c24xx->irq.regs.intmod;
+ if (temp != 0)
+ {
+ UINT32 int_type = 0;
+ while ((temp & 1) == 0)
+ {
+ int_type++;
+ temp = temp >> 1;
+ }
+ if (s3c24xx->irq.line_fiq != ASSERT_LINE)
+ {
+ cputag_set_input_line( device->machine(), "maincpu", ARM7_FIRQ_LINE, ASSERT_LINE);
+ s3c24xx->irq.line_fiq = ASSERT_LINE;
+ }
+ }
+ else
+ {
+ if (s3c24xx->irq.line_fiq != CLEAR_LINE)
+ {
+ cputag_set_input_line( device->machine(), "maincpu", ARM7_FIRQ_LINE, CLEAR_LINE);
+ s3c24xx->irq.line_fiq = CLEAR_LINE;
+ }
+ }
+}
+
+static void s3c24xx_request_irq( device_t *device, UINT32 int_type)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ verboselog( device->machine(), 5, "request irq %d\n", int_type);
+ s3c24xx->irq.regs.srcpnd |= (1 << int_type);
+ s3c24xx_check_pending_irq( device);
+}
+
+#if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
+
+static void s3c24xx_check_pending_subirq( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 temp = s3c24xx->irq.regs.subsrcpnd & ~s3c24xx->irq.regs.intsubmsk;
+ if (temp != 0)
+ {
+ UINT32 int_type = 0;
+ while ((temp & 1) == 0)
+ {
+ int_type++;
+ temp = temp >> 1;
+ }
+ s3c24xx_request_irq( device, MAP_SUBINT_TO_INT[int_type]);
+ }
+}
+
+ATTR_UNUSED static void s3c24xx_request_subirq( device_t *device, UINT32 int_type)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ verboselog( device->machine(), 5, "request subirq %d\n", int_type);
+ s3c24xx->irq.regs.subsrcpnd |= (1 << int_type);
+ s3c24xx_check_pending_subirq( device);
+}
+
+static void s3c24xx_check_pending_eint( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 temp = s3c24xx->gpio.regs.eintpend & ~s3c24xx->gpio.regs.eintmask;
+ if (temp != 0)
+ {
+ UINT32 int_type = 0;
+ while ((temp & 1) == 0)
+ {
+ int_type++;
+ temp = temp >> 1;
+ }
+ if (int_type < 8)
+ {
+ s3c24xx_request_irq( device, S3C24XX_INT_EINT4_7);
+ }
+ else
+ {
+ s3c24xx_request_irq( device, S3C24XX_INT_EINT8_23);
+ }
+ }
+}
+
+ATTR_UNUSED static void s3c24xx_request_eint( device_t *device, UINT32 number)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ verboselog( device->machine(), 5, "request external interrupt %d\n", number);
+ if (number < 4)
+ {
+ s3c24xx_request_irq( device, S3C24XX_INT_EINT0 + number);
+ }
+ else
+ {
+ s3c24xx->gpio.regs.eintpend |= (1 << number);
+ s3c24xx_check_pending_eint( device);
+ }
+}
+
+#endif
+
+static READ32_DEVICE_HANDLER( s3c24xx_irq_r )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 data = ((UINT32*)&s3c24xx->irq.regs)[offset];
+ verboselog( device->machine(), 9, "(IRQ) %08X -> %08X\n", S3C24XX_BASE_INT + (offset << 2), data);
+ return data;
+}
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_irq_w )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 old_value = ((UINT32*)&s3c24xx->irq.regs)[offset];
+ verboselog( device->machine(), 9, "(IRQ) %08X <- %08X\n", S3C24XX_BASE_INT + (offset << 2), data);
+ COMBINE_DATA(&((UINT32*)&s3c24xx->irq.regs)[offset]);
+ switch (offset)
+ {
+ case S3C24XX_SRCPND :
+ {
+ s3c24xx->irq.regs.srcpnd = (old_value & ~data); // clear only the bit positions of SRCPND corresponding to those set to one in the data
+ s3c24xx_check_pending_irq( device);
+ }
+ break;
+ case S3C24XX_INTMSK :
+ {
+ s3c24xx_check_pending_irq( device);
+ }
+ break;
+ case S3C24XX_INTPND :
+ {
+ s3c24xx->irq.regs.intpnd = (old_value & ~data); // clear only the bit positions of INTPND corresponding to those set to one in the data
+ }
+ break;
+#if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
+ case S3C24XX_SUBSRCPND :
+ {
+ s3c24xx->irq.regs.subsrcpnd = (old_value & ~data); // clear only the bit positions of SRCPND corresponding to those set to one in the data
+ s3c24xx_check_pending_subirq( device);
+ }
+ break;
+ case S3C24XX_INTSUBMSK :
+ {
+ s3c24xx_check_pending_subirq( device);
+ }
+ break;
+#endif
+ }
+}
+
+/* PWM Timer */
+
+static UINT16 s3c24xx_pwm_calc_observation( device_t *device, int ch)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ double timeleft, x1, x2;
+ UINT32 cnto;
+ timeleft = s3c24xx->pwm.timer[ch]->remaining( ).as_double();
+// printf( "timeleft %f freq %d cntb %d cmpb %d\n", timeleft, s3c24xx->pwm.freq[ch], s3c24xx->pwm.cnt[ch], s3c24xx->pwm.cmp[ch]);
+ x1 = 1 / ((double)s3c24xx->pwm.freq[ch] / (s3c24xx->pwm.cnt[ch]- s3c24xx->pwm.cmp[ch] + 1));
+ x2 = x1 / timeleft;
+// printf( "x1 %f\n", x1);
+ cnto = s3c24xx->pwm.cmp[ch] + ((s3c24xx->pwm.cnt[ch]- s3c24xx->pwm.cmp[ch]) / x2);
+// printf( "cnto %d\n", cnto);
+ return cnto;
+}
+
+static READ32_DEVICE_HANDLER( s3c24xx_pwm_r )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 data = ((UINT32*)&s3c24xx->pwm.regs)[offset];
+ switch (offset)
+ {
+ case S3C24XX_TCNTO0 :
+ {
+ data = (data & ~0x0000FFFF) | s3c24xx_pwm_calc_observation( device, 0);
+ }
+ break;
+ case S3C24XX_TCNTO1 :
+ {
+ data = (data & ~0x0000FFFF) | s3c24xx_pwm_calc_observation( device, 1);
+ }
+ break;
+ case S3C24XX_TCNTO2 :
+ {
+ data = (data & ~0x0000FFFF) | s3c24xx_pwm_calc_observation( device, 2);
+ }
+ break;
+ case S3C24XX_TCNTO3 :
+ {
+ data = (data & ~0x0000FFFF) | s3c24xx_pwm_calc_observation( device, 3);
+ }
+ break;
+ case S3C24XX_TCNTO4 :
+ {
+ data = (data & ~0x0000FFFF) | s3c24xx_pwm_calc_observation( device, 4);
+ }
+ break;
+ }
+ verboselog( device->machine(), 9, "(PWM) %08X -> %08X\n", S3C24XX_BASE_PWM + (offset << 2), data);
+ return data;
+}
+
+static void s3c24xx_pwm_start( device_t *device, int timer)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ const int mux_table[] = { 2, 4, 8, 16};
+ const int prescaler_shift[] = { 0, 0, 8, 8, 8};
+ const int mux_shift[] = { 0, 4, 8, 12, 16};
+ UINT32 pclk, prescaler, mux, cnt, cmp, auto_reload;
+ double freq, hz;
+ verboselog( device->machine(), 1, "PWM %d start\n", timer);
+ pclk = s3c24xx_get_pclk( device);
+ prescaler = (s3c24xx->pwm.regs.tcfg0 >> prescaler_shift[timer]) & 0xFF;
+ mux = (s3c24xx->pwm.regs.tcfg1 >> mux_shift[timer]) & 0x0F;
+ if (mux < 4)
+ {
+ freq = (double)pclk / (prescaler + 1) / mux_table[mux];
+ }
+ else
+ {
+ // todo
+ freq = (double)pclk / (prescaler + 1) / 1;
+ }
+ switch (timer)
+ {
+ case 0 :
+ {
+ cnt = BITS( s3c24xx->pwm.regs.tcntb0, 15, 0);
+ cmp = BITS( s3c24xx->pwm.regs.tcmpb0, 15, 0);
+ auto_reload = BIT( s3c24xx->pwm.regs.tcon, 3);
+ }
+ break;
+ case 1 :
+ {
+ cnt = BITS( s3c24xx->pwm.regs.tcntb1, 15, 0);
+ cmp = BITS( s3c24xx->pwm.regs.tcmpb1, 15, 0);
+ auto_reload = BIT( s3c24xx->pwm.regs.tcon, 11);
+ }
+ break;
+ case 2 :
+ {
+ cnt = BITS( s3c24xx->pwm.regs.tcntb2, 15, 0);
+ cmp = BITS( s3c24xx->pwm.regs.tcmpb2, 15, 0);
+ auto_reload = BIT( s3c24xx->pwm.regs.tcon, 15);
+ }
+ break;
+ case 3 :
+ {
+ cnt = BITS( s3c24xx->pwm.regs.tcntb3, 15, 0);
+ cmp = BITS( s3c24xx->pwm.regs.tcmpb3, 15, 0);
+ auto_reload = BIT( s3c24xx->pwm.regs.tcon, 19);
+ }
+ break;
+ case 4 :
+ {
+ cnt = BITS( s3c24xx->pwm.regs.tcntb4, 15, 0);
+ cmp = 0;
+ auto_reload = BIT( s3c24xx->pwm.regs.tcon, 22);
+ }
+ break;
+ default :
+ {
+ cnt = cmp = auto_reload = 0;
+ }
+ break;
+ }
+// hz = freq / (cnt - cmp + 1);
+ if (cnt < 2)
+ {
+ hz = freq;
+ }
+ else
+ {
+ hz = freq / cnt;
+ }
+ verboselog( device->machine(), 5, "PWM %d - pclk=%d prescaler=%d div=%d freq=%f cnt=%d cmp=%d auto_reload=%d hz=%f\n", timer, pclk, prescaler, mux_table[mux], freq, cnt, cmp, auto_reload, hz);
+ s3c24xx->pwm.cnt[timer] = cnt;
+ s3c24xx->pwm.cmp[timer] = cmp;
+ s3c24xx->pwm.freq[timer] = freq;
+ if (auto_reload)
+ {
+ s3c24xx->pwm.timer[timer]->adjust( attotime::from_hz( hz), timer, attotime::from_hz( hz));
+ }
+ else
+ {
+ s3c24xx->pwm.timer[timer]->adjust( attotime::from_hz( hz), timer);
+ }
+}
+
+static void s3c24xx_pwm_stop( device_t *device, int timer)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ verboselog( device->machine(), 1, "PWM %d stop\n", timer);
+ s3c24xx->pwm.timer[timer]->adjust( attotime::never);
+}
+
+static void s3c24xx_pwm_recalc( device_t *device, int timer)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ const int tcon_shift[] = { 0, 8, 12, 16, 20};
+ if (s3c24xx->pwm.regs.tcon & (1 << tcon_shift[timer]))
+ {
+ s3c24xx_pwm_start( device, timer);
+ }
+ else
+ {
+ s3c24xx_pwm_stop( device, timer);
+ }
+}
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_pwm_w )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 old_value = ((UINT32*)&s3c24xx->pwm.regs)[offset];
+ verboselog( device->machine(), 9, "(PWM) %08X <- %08X\n", S3C24XX_BASE_PWM + (offset << 2), data);
+ COMBINE_DATA(&((UINT32*)&s3c24xx->pwm.regs)[offset]);
+ switch (offset)
+ {
+ case S3C24XX_TCON :
+ {
+ if ((data & (1 << 0)) != (old_value & (1 << 0)))
+ {
+ s3c24xx_pwm_recalc( device, 0);
+ }
+ if ((data & (1 << 8)) != (old_value & (1 << 8)))
+ {
+ s3c24xx_pwm_recalc( device, 1);
+ }
+ if ((data & (1 << 12)) != (old_value & (1 << 12)))
+ {
+ s3c24xx_pwm_recalc( device, 2);
+ }
+ if ((data & (1 << 16)) != (old_value & (1 << 16)))
+ {
+ s3c24xx_pwm_recalc( device, 3);
+ }
+ if ((data & (1 << 20)) != (old_value & (1 << 20)))
+ {
+ s3c24xx_pwm_recalc( device, 4);
+ }
+ }
+ break;
+ }
+}
+
+static TIMER_CALLBACK( s3c24xx_pwm_timer_exp )
+{
+ device_t *device = (device_t *)ptr;
+ s3c24xx_t *s3c24xx = get_token( device);
+ int ch = param;
+ const int ch_int[] = { S3C24XX_INT_TIMER0, S3C24XX_INT_TIMER1, S3C24XX_INT_TIMER2, S3C24XX_INT_TIMER3, S3C24XX_INT_TIMER4 };
+ verboselog( machine, 2, "PWM %d timer callback\n", ch);
+ if (BITS( s3c24xx->pwm.regs.tcfg1, 23, 20) == (ch + 1))
+ {
+ s3c24xx_dma_request_pwm( device);
+ }
+ else
+ {
+ s3c24xx_request_irq( device, ch_int[ch]);
+ }
+}
+
+/* DMA */
+
+static void s3c24xx_dma_reload( device_t *device, int ch)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ s3c24xx_dma_regs_t *regs = &s3c24xx->dma[ch].regs;
+ regs->dstat = S3C24XX_DSTAT_SET_CURR_TC( regs->dstat, S3C24XX_DCON_GET_TC( regs->dcon));
+ regs->dcsrc = S3C24XX_DCSRC_SET_CURR_SRC( regs->dcsrc, S3C24XX_DISRC_GET_SADDR( regs->disrc));
+ regs->dcdst = S3C24XX_DCDST_SET_CURR_DST( regs->dcdst, S3C24XX_DIDST_GET_DADDR( regs->didst));
+}
+
+static void s3c24xx_dma_trigger( device_t *device, int ch)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ s3c24xx_dma_regs_t *regs = &s3c24xx->dma[ch].regs;
+ UINT32 curr_tc, curr_src, curr_dst;
+ address_space *space = device->machine().device( "maincpu")->memory().space( AS_PROGRAM);
+ int dsz, inc_src, inc_dst, servmode, tsz;
+ const UINT32 ch_int[] = { S3C24XX_INT_DMA0, S3C24XX_INT_DMA1, S3C24XX_INT_DMA2, S3C24XX_INT_DMA3};
+ verboselog( device->machine(), 5, "DMA %d trigger\n", ch);
+ curr_tc = S3C24XX_DSTAT_GET_CURR_TC( regs->dstat);
+ dsz = S3C24XX_DCON_GET_DSZ( regs->dcon);
+ curr_src = S3C24XX_DCSRC_GET_CURR_SRC( regs->dcsrc);
+ curr_dst = S3C24XX_DCDST_GET_CURR_DST( regs->dcdst);
+ servmode = S3C24XX_DCON_GET_SERVMODE( regs->dcon);
+ tsz = S3C24XX_DCON_GET_TSZ( regs->dcon);
+#if defined(DEVICE_S3C2400)
+ inc_src = BIT( regs->disrc, 29);
+ inc_dst = BIT( regs->didst, 29);
+#else
+ inc_src = BIT( regs->disrcc, 0);
+ inc_dst = BIT( regs->didstc, 0);
+#endif
+ verboselog( device->machine(), 5, "DMA %d - curr_src %08X curr_dst %08X curr_tc %d dsz %d\n", ch, curr_src, curr_dst, curr_tc, dsz);
+ while (curr_tc > 0)
+ {
+ curr_tc--;
+ for (int i = 0; i < 1 << (tsz << 1); i++)
+ {
+ switch (dsz)
+ {
+ case 0 : space->write_byte( curr_dst, space->read_byte( curr_src)); break;
+ case 1 : space->write_word( curr_dst, space->read_word( curr_src)); break;
+ case 2 : space->write_dword( curr_dst, space->read_dword( curr_src)); break;
+ }
+ if (inc_src == 0) curr_src += (1 << dsz);
+ if (inc_dst == 0) curr_dst += (1 << dsz);
+ }
+ if (servmode == 0) break;
+ }
+ regs->dcsrc = S3C24XX_DCSRC_SET_CURR_SRC( regs->dcsrc, curr_src);
+ regs->dcdst = S3C24XX_DCDST_SET_CURR_DST( regs->dcdst, curr_dst);
+ regs->dstat = S3C24XX_DSTAT_SET_CURR_TC( regs->dstat, curr_tc);
+ if (curr_tc == 0)
+ {
+ if (S3C24XX_DCON_GET_RELOAD( regs->dcon) == 0)
+ {
+ s3c24xx_dma_reload( device, ch);
+ }
+ else
+ {
+ regs->dmasktrig &= ~(1 << 1); // clear on/off
+ }
+ if (S3C24XX_DCON_GET_INT( regs->dcon) != 0)
+ {
+ s3c24xx_request_irq( device, ch_int[ch]);
+ }
+ }
+}
+
+static void s3c24xx_dma_request_iis( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ s3c24xx_dma_regs_t *regs = &s3c24xx->dma[2].regs;
+ verboselog( device->machine(), 5, "s3c24xx_dma_request_iis\n");
+ if ((S3C24XX_DMASKTRIG_GET_ON_OFF( regs->dmasktrig) != 0) && (S3C24XX_DCON_GET_SWHWSEL( regs->dcon) != 0) && (S3C24XX_DCON_GET_HWSRCSEL( regs->dcon) == 0))
+ {
+ s3c24xx_dma_trigger( device, 2);
+ }
+}
+
+static void s3c24xx_dma_request_pwm( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ verboselog( device->machine(), 5, "s3c24xx_dma_request_pwm\n");
+ for (int i = 0; i < 4; i++)
+ {
+ if (i != 1)
+ {
+ s3c24xx_dma_regs_t *regs = &s3c24xx->dma[i].regs;
+ if ((S3C24XX_DMASKTRIG_GET_ON_OFF( regs->dmasktrig) != 0) && (S3C24XX_DCON_GET_SWHWSEL( regs->dcon) != 0) && (S3C24XX_DCON_GET_HWSRCSEL( regs->dcon) == 3))
+ {
+ s3c24xx_dma_trigger( device, i);
+ }
+ }
+ }
+}
+
+static void s3c24xx_dma_start( device_t *device, int ch)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 addr_src, addr_dst, tc;
+ s3c24xx_dma_regs_t *regs = &s3c24xx->dma[ch].regs;
+ UINT32 dsz, tsz, reload;
+ int inc_src, inc_dst, _int, servmode, swhwsel, hwsrcsel;
+ verboselog( device->machine(), 1, "DMA %d start\n", ch);
+ addr_src = S3C24XX_DISRC_GET_SADDR( regs->disrc);
+ addr_dst = S3C24XX_DIDST_GET_DADDR( regs->didst);
+ tc = S3C24XX_DCON_GET_TC( regs->dcon);
+ _int = S3C24XX_DCON_GET_INT( regs->dcon);
+ servmode = S3C24XX_DCON_GET_SERVMODE( regs->dcon);
+ hwsrcsel = S3C24XX_DCON_GET_HWSRCSEL( regs->dcon);
+ swhwsel = S3C24XX_DCON_GET_SWHWSEL( regs->dcon);
+ reload = S3C24XX_DCON_GET_RELOAD( regs->dcon);
+ dsz = S3C24XX_DCON_GET_DSZ( regs->dcon);
+ tsz = S3C24XX_DCON_GET_TSZ( regs->dcon);
+#if defined(DEVICE_S3C2400)
+ inc_src = BIT( regs->disrc, 29);
+ inc_dst = BIT( regs->didst, 29);
+#else
+ inc_src = BIT( regs->disrcc, 0);
+ inc_dst = BIT( regs->didstc, 0);
+#endif
+ verboselog( device->machine(), 5, "DMA %d - addr_src %08X inc_src %d addr_dst %08X inc_dst %d int %d tsz %d servmode %d hwsrcsel %d swhwsel %d reload %d dsz %d tc %d\n", ch, addr_src, inc_src, addr_dst, inc_dst, _int, tsz, servmode, hwsrcsel, swhwsel, reload, dsz, tc);
+ verboselog( device->machine(), 5, "DMA %d - copy %08X bytes from %08X (%s) to %08X (%s)\n", ch, (tc << dsz) << (tsz << 1), addr_src, inc_src ? "fix" : "inc", addr_dst, inc_dst ? "fix" : "inc");
+ s3c24xx_dma_reload( device, ch);
+ if (swhwsel == 0)
+ {
+ s3c24xx_dma_trigger( device, ch);
+ }
+}
+
+static void s3c24xx_dma_stop( device_t *device, int ch)
+{
+ verboselog( device->machine(), 1, "DMA %d stop\n", ch);
+}
+
+static void s3c24xx_dma_recalc( device_t *device, int ch)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ if ((s3c24xx->dma[ch].regs.dmasktrig & (1 << 1)) != 0)
+ {
+ s3c24xx_dma_start( device, ch);
+ }
+ else
+ {
+ s3c24xx_dma_stop( device, ch);
+ }
+}
+
+static UINT32 s3c24xx_dma_r( device_t *device, UINT32 ch, UINT32 offset)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ return ((UINT32*)&s3c24xx->dma[ch].regs)[offset];
+}
+
+static void s3c24xx_dma_w( device_t *device, UINT32 ch, UINT32 offset, UINT32 data, UINT32 mem_mask)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 old_value = ((UINT32*)&s3c24xx->dma[ch].regs)[offset];
+ COMBINE_DATA(&((UINT32*)&s3c24xx->dma[ch].regs)[offset]);
+ switch (offset)
+ {
+ case S3C24XX_DCON :
+ {
+ #if 0 // is this code necessary ???
+ if ((data & (1 << 22)) != 0) // reload
+ {
+ s3c24xx_dma_regs_t *regs = &s3c24xx->dma[ch].regs;
+ regs->dmasktrig &= ~(1 << 1); // clear on/off
+ }
+ #endif
+ }
+ break;
+ case S3C24XX_DMASKTRIG :
+ {
+ if ((old_value & (1 << 1)) != (data & (1 << 1)))
+ {
+ s3c24xx_dma_recalc( device, ch);
+ }
+ }
+ break;
+ }
+}
+
+static READ32_DEVICE_HANDLER( s3c24xx_dma_0_r )
+{
+ UINT32 data = s3c24xx_dma_r( device, 0, offset);
+ verboselog( device->machine(), 9, "(DMA 0) %08X -> %08X\n", S3C24XX_BASE_DMA_0 + (offset << 2), data);
+ return data;
+}
+
+static READ32_DEVICE_HANDLER( s3c24xx_dma_1_r )
+{
+ UINT32 data = s3c24xx_dma_r( device, 1, offset);
+ verboselog( device->machine(), 9, "(DMA 1) %08X -> %08X\n", S3C24XX_BASE_DMA_1 + (offset << 2), data);
+ return data;
+}
+
+static READ32_DEVICE_HANDLER( s3c24xx_dma_2_r )
+{
+ UINT32 data = s3c24xx_dma_r( device, 2, offset);
+ verboselog( device->machine(), 9, "(DMA 2) %08X -> %08X\n", S3C24XX_BASE_DMA_2 + (offset << 2), data);
+ return data;
+}
+
+static READ32_DEVICE_HANDLER( s3c24xx_dma_3_r )
+{
+ UINT32 data = s3c24xx_dma_r( device, 3, offset);
+ verboselog( device->machine(), 9, "(DMA 3) %08X -> %08X\n", S3C24XX_BASE_DMA_3 + (offset << 2), data);
+ return data;
+}
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_dma_0_w )
+{
+ verboselog( device->machine(), 9, "(DMA 0) %08X <- %08X\n", S3C24XX_BASE_DMA_0 + (offset << 2), data);
+ s3c24xx_dma_w( device, 0, offset, data, mem_mask);
+}
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_dma_1_w )
+{
+ verboselog( device->machine(), 9, "(DMA 1) %08X <- %08X\n", S3C24XX_BASE_DMA_1 + (offset << 2), data);
+ s3c24xx_dma_w( device, 1, offset, data, mem_mask);
+}
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_dma_2_w )
+{
+ verboselog( device->machine(), 9, "(DMA 2) %08X <- %08X\n", S3C24XX_BASE_DMA_2 + (offset << 2), data);
+ s3c24xx_dma_w( device, 2, offset, data, mem_mask);
+}
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_dma_3_w )
+{
+ verboselog( device->machine(), 9, "(DMA 3) %08X <- %08X\n", S3C24XX_BASE_DMA_3 + (offset << 2), data);
+ s3c24xx_dma_w( device, 3, offset, data, mem_mask);
+}
+
+static TIMER_CALLBACK( s3c24xx_dma_timer_exp )
+{
+ int ch = param;
+ verboselog( machine, 2, "DMA %d timer callback\n", ch);
+}
+
+/* I/O Port */
+
+INLINE UINT32 iface_gpio_port_r( device_t *device, int port)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ if (s3c24xx->iface->gpio.port_r)
+ {
+ return (s3c24xx->iface->gpio.port_r)( device, port);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+INLINE void iface_gpio_port_w( device_t *device, int port, UINT32 data)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ if (s3c24xx->iface->gpio.port_w)
+ {
+ (s3c24xx->iface->gpio.port_w)( device, port, data);
+ }
+}
+
+static READ32_DEVICE_HANDLER( s3c24xx_gpio_r )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 data = ((UINT32*)&s3c24xx->gpio.regs)[offset];
+ switch (offset)
+ {
+ case S3C24XX_GPADAT :
+ {
+ data = iface_gpio_port_r( device, S3C24XX_GPIO_PORT_A) & S3C24XX_GPADAT_MASK;
+ }
+ break;
+ case S3C24XX_GPBDAT :
+ {
+ data = iface_gpio_port_r( device, S3C24XX_GPIO_PORT_B) & S3C24XX_GPBDAT_MASK;
+ }
+ break;
+ case S3C24XX_GPCDAT :
+ {
+ data = iface_gpio_port_r( device, S3C24XX_GPIO_PORT_C) & S3C24XX_GPCDAT_MASK;
+ }
+ break;
+ case S3C24XX_GPDDAT :
+ {
+ data = iface_gpio_port_r( device, S3C24XX_GPIO_PORT_D) & S3C24XX_GPDDAT_MASK;
+ }
+ break;
+ case S3C24XX_GPEDAT :
+ {
+ data = iface_gpio_port_r( device, S3C24XX_GPIO_PORT_E) & S3C24XX_GPEDAT_MASK;
+ }
+ break;
+ case S3C24XX_GPFDAT :
+ {
+ data = iface_gpio_port_r( device, S3C24XX_GPIO_PORT_F) & S3C24XX_GPFDAT_MASK;
+ }
+ break;
+ case S3C24XX_GPGDAT :
+ {
+ data = iface_gpio_port_r( device, S3C24XX_GPIO_PORT_G) & S3C24XX_GPGDAT_MASK;
+ }
+ break;
+#if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
+ case S3C24XX_GPHDAT :
+ {
+ data = iface_gpio_port_r( device, S3C24XX_GPIO_PORT_H) & S3C24XX_GPHDAT_MASK;
+ }
+ break;
+#endif
+#if defined(DEVICE_S3C2440)
+ case S3C24XX_GPJDAT :
+ {
+ data = iface_gpio_port_r( device, S3C24XX_GPIO_PORT_J) & S3C24XX_GPJDAT_MASK;
+ }
+ break;
+#endif
+ }
+ verboselog( device->machine(), 9, "(GPIO) %08X -> %08X\n", S3C24XX_BASE_GPIO + (offset << 2), data);
+ return data;
+}
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_gpio_w )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+#if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
+ UINT32 old_value = ((UINT32*)&s3c24xx->gpio.regs)[offset];
+#endif
+ verboselog( device->machine(), 9, "(GPIO) %08X <- %08X\n", S3C24XX_BASE_GPIO + (offset << 2), data);
+ COMBINE_DATA(&((UINT32*)&s3c24xx->gpio.regs)[offset]);
+ switch (offset)
+ {
+ case S3C24XX_GPADAT :
+ {
+ iface_gpio_port_w( device, S3C24XX_GPIO_PORT_A, data & S3C24XX_GPADAT_MASK);
+ }
+ break;
+ case S3C24XX_GPBDAT :
+ {
+ iface_gpio_port_w( device, S3C24XX_GPIO_PORT_B, data & S3C24XX_GPBDAT_MASK);
+ }
+ break;
+ case S3C24XX_GPCDAT :
+ {
+ iface_gpio_port_w( device, S3C24XX_GPIO_PORT_C, data & S3C24XX_GPCDAT_MASK);
+ }
+ break;
+ case S3C24XX_GPDDAT :
+ {
+ iface_gpio_port_w( device, S3C24XX_GPIO_PORT_D, data & S3C24XX_GPDDAT_MASK);
+ }
+ break;
+ case S3C24XX_GPEDAT :
+ {
+ iface_gpio_port_w( device, S3C24XX_GPIO_PORT_E, data & S3C24XX_GPEDAT_MASK);
+ }
+ break;
+ case S3C24XX_GPFDAT :
+ {
+ iface_gpio_port_w( device, S3C24XX_GPIO_PORT_F, data & S3C24XX_GPFDAT_MASK);
+ }
+ break;
+ case S3C24XX_GPGDAT :
+ {
+ iface_gpio_port_w( device, S3C24XX_GPIO_PORT_G, data & S3C24XX_GPGDAT_MASK);
+ }
+ break;
+#if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
+ case S3C24XX_GPHDAT :
+ {
+ iface_gpio_port_w( device, S3C24XX_GPIO_PORT_H, data & S3C24XX_GPHDAT_MASK);
+ }
+ break;
+ case S3C24XX_EINTPEND :
+ {
+ s3c24xx->gpio.regs.eintpend = (old_value & ~data);
+ s3c24xx_check_pending_eint( device);
+ }
+ break;
+ case S3C24XX_EINTMASK :
+ {
+ s3c24xx_check_pending_eint( device);
+ }
+ break;
+#endif
+#if defined(DEVICE_S3C2440)
+ case S3C24XX_GPJDAT :
+ {
+ iface_gpio_port_w( device, S3C24XX_GPIO_PORT_J, data & S3C24XX_GPJDAT_MASK);
+ }
+ break;
+#endif
+ }
+}
+
+/* Memory Controller */
+
+static READ32_DEVICE_HANDLER( s3c24xx_memcon_r )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 data = s3c24xx->memcon.regs.data[offset];
+ verboselog( device->machine(), 9, "(MEMCON) %08X -> %08X\n", S3C24XX_BASE_MEMCON + (offset << 2), data);
+ return data;
+}
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_memcon_w )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ verboselog( device->machine(), 9, "(MEMCON) %08X <- %08X\n", S3C24XX_BASE_MEMCON + (offset << 2), data);
+ COMBINE_DATA(&s3c24xx->memcon.regs.data[offset]);
+}
+
+/* USB Host Controller */
+
+static READ32_DEVICE_HANDLER( s3c24xx_usb_host_r )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 data = s3c24xx->usbhost.regs.data[offset];
+ switch (offset)
+ {
+ // HcCommandStatus
+ case 0x08 / 4 :
+ {
+ data = data & ~(1 << 0); // [bit 0] HostControllerReset
+ }
+ break;
+ }
+ verboselog( device->machine(), 9, "(USB H) %08X -> %08X\n", S3C24XX_BASE_USBHOST + (offset << 2), data);
+ return data;
+}
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_usb_host_w )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ verboselog( device->machine(), 9, "(USB H) %08X <- %08X\n", S3C24XX_BASE_USBHOST + (offset << 2), data);
+ COMBINE_DATA(&s3c24xx->usbhost.regs.data[offset]);
+}
+
+/* UART */
+
+static UINT32 s3c24xx_uart_r( device_t *device, UINT32 ch, UINT32 offset)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 data = ((UINT32*)&s3c24xx->uart[ch].regs)[offset];
+ switch (offset)
+ {
+ case S3C24XX_UTRSTAT :
+ {
+ data = (data & ~0x00000006) | 0x00000004 | 0x00000002; // [bit 2] Transmitter empty / [bit 1] Transmit buffer empty
+ }
+ break;
+ case S3C24XX_URXH :
+ {
+ UINT8 rxdata = data & 0xFF;
+ verboselog( device->machine(), 5, "UART %d read %02X (%c)\n", ch, rxdata, ((rxdata >= 32) && (rxdata < 128)) ? (char)rxdata : '?');
+ s3c24xx->uart[ch].regs.utrstat &= ~1; // [bit 0] Receive buffer data ready
+ }
+ break;
+ }
+ return data;
+}
+
+static void s3c24xx_uart_w( device_t *device, UINT32 ch, UINT32 offset, UINT32 data, UINT32 mem_mask)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ COMBINE_DATA(&((UINT32*)&s3c24xx->uart[ch].regs)[offset]);
+ switch (offset)
+ {
+ case S3C24XX_UTXH :
+ {
+ UINT8 txdata = data & 0xFF;
+ verboselog( device->machine(), 5, "UART %d write %02X (%c)\n", ch, txdata, ((txdata >= 32) && (txdata < 128)) ? (char)txdata : '?');
+#ifdef UART_PRINTF
+ printf( "%c", ((txdata >= 32) && (txdata < 128)) ? (char)txdata : '?');
+#endif
+ }
+ break;
+ }
+}
+
+static READ32_DEVICE_HANDLER( s3c24xx_uart_0_r )
+{
+ UINT32 data = s3c24xx_uart_r( device, 0, offset);
+// verboselog( device->machine(), 9, "(UART 0) %08X -> %08X\n", S3C24XX_BASE_UART_0 + (offset << 2), data);
+ return data;
+}
+
+static READ32_DEVICE_HANDLER( s3c24xx_uart_1_r )
+{
+ UINT32 data = s3c24xx_uart_r( device, 1, offset);
+// verboselog( device->machine(), 9, "(UART 1) %08X -> %08X\n", S3C24XX_BASE_UART_1 + (offset << 2), data);
+ return data;
+}
+
+#if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
+
+static READ32_DEVICE_HANDLER( s3c24xx_uart_2_r )
+{
+ UINT32 data = s3c24xx_uart_r( device, 2, offset);
+// verboselog( device->machine(), 9, "(UART 2) %08X -> %08X\n", S3C24XX_BASE_UART_2 + (offset << 2), data);
+ return data;
+}
+
+#endif
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_uart_0_w )
+{
+// verboselog( device->machine(), 9, "(UART 0) %08X <- %08X\n", S3C24XX_BASE_UART_0 + (offset << 2), data);
+ s3c24xx_uart_w( device, 0, offset, data, mem_mask);
+}
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_uart_1_w )
+{
+// verboselog( device->machine(), 9, "(UART 1) %08X <- %08X\n", S3C24XX_BASE_UART_1 + (offset << 2), data);
+ s3c24xx_uart_w( device, 1, offset, data, mem_mask);
+}
+
+#if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_uart_2_w )
+{
+// verboselog( device->machine(), 9, "(UART 2) %08X <- %08X\n", S3C24XX_BASE_UART_2 + (offset << 2), data);
+ s3c24xx_uart_w( device, 2, offset, data, mem_mask);
+}
+
+#endif
+
+static void s3c24xx_uart_fifo_w( device_t *device, int uart, UINT8 data)
+{
+// printf( "s3c24xx_uart_fifo_w (%c)\n", data);
+ s3c24xx_t *s3c24xx = get_token( device);
+ s3c24xx->uart[uart].regs.urxh = data;
+ s3c24xx->uart[uart].regs.utrstat |= 1; // [bit 0] Receive buffer data ready
+}
+
+/* USB Device */
+
+static READ32_DEVICE_HANDLER( s3c24xx_usb_device_r )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 data = s3c24xx->usbdev.regs.data[offset];
+ verboselog( device->machine(), 9, "(USB D) %08X -> %08X\n", S3C24XX_BASE_USBDEV + (offset << 2), data);
+ return data;
+}
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_usb_device_w )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ verboselog( device->machine(), 9, "(USB D) %08X <- %08X\n", S3C24XX_BASE_USBDEV + (offset << 2), data);
+ COMBINE_DATA(&s3c24xx->usbdev.regs.data[offset]);
+}
+
+/* Watchdog Timer */
+
+#if defined(DEVICE_S3C2410)
+
+static UINT16 s3c24xx_wdt_calc_current_count( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ double timeleft, x1, x2;
+ UINT32 cnt;
+ timeleft = s3c24xx->wdt.timer->remaining( ).as_double();
+// printf( "timeleft %f freq %d cnt %d\n", timeleft, s3c24xx->wdt.freq, s3c24xx->wdt.cnt);
+ x1 = 1 / ((double)s3c24xx->wdt.freq / s3c24xx->wdt.cnt);
+ x2 = x1 / timeleft;
+// printf( "x1 %f\n", x1);
+ cnt = s3c24xx->wdt.cnt / x2;
+// printf( "cnt %d\n", cnt);
+ return cnt;
+}
+
+#else
+
+static UINT16 s3c24xx_wdt_calc_current_count( device_t *device)
+{
+ return 0;
+}
+
+#endif
+
+static READ32_DEVICE_HANDLER( s3c24xx_wdt_r )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 data = ((UINT32*)&s3c24xx->wdt.regs)[offset];
+ switch (offset)
+ {
+ case S3C24XX_WTCNT :
+ {
+ // is wdt active?
+ if ((s3c24xx->wdt.regs.wtcon & (1 << 5)) != 0)
+ {
+ data = s3c24xx_wdt_calc_current_count( device);
+ }
+ }
+ break;
+ }
+ verboselog( device->machine(), 9, "(WDT) %08X -> %08X\n", S3C24XX_BASE_WDT + (offset << 2), data);
+ return data;
+}
+
+static void s3c24xx_wdt_start( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 pclk, prescaler, clock;
+ double freq, hz;
+ verboselog( device->machine(), 1, "WDT start\n");
+ pclk = s3c24xx_get_pclk( device);
+ prescaler = BITS( s3c24xx->wdt.regs.wtcon, 15, 8);
+ clock = 16 << BITS( s3c24xx->wdt.regs.wtcon, 4, 3);
+ freq = (double)pclk / (prescaler + 1) / clock;
+ hz = freq / s3c24xx->wdt.regs.wtcnt;
+ verboselog( device->machine(), 5, "WDT pclk %d prescaler %d clock %d freq %f hz %f\n", pclk, prescaler, clock, freq, hz);
+ s3c24xx->wdt.timer->adjust( attotime::from_hz( hz), 0, attotime::from_hz( hz));
+#if defined(DEVICE_S3C2410)
+ s3c24xx->wdt.freq = freq;
+ s3c24xx->wdt.cnt = s3c24xx->wdt.regs.wtcnt;
+#endif
+}
+
+static void s3c24xx_wdt_stop( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ verboselog( device->machine(), 1, "WDT stop\n");
+ s3c24xx->wdt.regs.wtcnt = s3c24xx_wdt_calc_current_count( device);
+ s3c24xx->wdt.timer->adjust( attotime::never);
+}
+
+static void s3c24xx_wdt_recalc( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ if ((s3c24xx->wdt.regs.wtcon & (1 << 5)) != 0)
+ {
+ s3c24xx_wdt_start( device);
+ }
+ else
+ {
+ s3c24xx_wdt_stop( device);
+ }
+}
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_wdt_w )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 old_value = ((UINT32*)&s3c24xx->wdt.regs)[offset];
+ verboselog( device->machine(), 9, "(WDT) %08X <- %08X\n", S3C24XX_BASE_WDT + (offset << 2), data);
+ COMBINE_DATA(&((UINT32*)&s3c24xx->wdt.regs)[offset]);
+ switch (offset)
+ {
+ case S3C24XX_WTCON :
+ {
+ if ((data & (1 << 5)) != (old_value & (1 << 5)))
+ {
+ s3c24xx_wdt_recalc( device);
+ }
+ }
+ break;
+ }
+}
+
+static TIMER_CALLBACK( s3c24xx_wdt_timer_exp )
+{
+ device_t *device = (device_t *)ptr;
+ s3c24xx_t *s3c24xx = get_token( device);
+ verboselog( machine, 2, "WDT timer callback\n");
+ if ((s3c24xx->wdt.regs.wtcon & (1 << 2)) != 0)
+ {
+#if defined(DEVICE_S3C2400) || defined(DEVICE_S3C2410)
+ s3c24xx_request_irq( device, S3C24XX_INT_WDT);
+#else
+ s3c24xx_request_subirq( device, S3C24XX_SUBINT_WDT);
+#endif
+ }
+ if ((s3c24xx->wdt.regs.wtcon & (1 << 0)) != 0)
+ {
+ s3c24xx_reset( device);
+ }
+}
+
+/* IIC */
+
+INLINE void iface_i2c_scl_w( device_t *device, int state)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ if (s3c24xx->iface->i2c.scl_w)
+ {
+ (s3c24xx->iface->i2c.scl_w)( device, state);
+ }
+}
+
+INLINE void iface_i2c_sda_w( device_t *device, int state)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ if (s3c24xx->iface->i2c.sda_w)
+ {
+ (s3c24xx->iface->i2c.sda_w)( device, state);
+ }
+}
+
+INLINE int iface_i2c_sda_r( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ if (s3c24xx->iface->i2c.sda_r)
+ {
+ return (s3c24xx->iface->i2c.sda_r)( device);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static void i2c_send_start( device_t *device)
+{
+ verboselog( device->machine(), 5, "i2c_send_start\n");
+ iface_i2c_sda_w( device, 1);
+ iface_i2c_scl_w( device, 1);
+ iface_i2c_sda_w( device, 0);
+ iface_i2c_scl_w( device, 0);
+}
+
+static void i2c_send_stop( device_t *device)
+{
+ verboselog( device->machine(), 5, "i2c_send_stop\n");
+ iface_i2c_sda_w( device, 0);
+ iface_i2c_scl_w( device, 1);
+ iface_i2c_sda_w( device, 1);
+ iface_i2c_scl_w( device, 0);
+}
+
+static UINT8 i2c_receive_byte( device_t *device, int ack)
+{
+ UINT8 data = 0;
+ verboselog( device->machine(), 5, "i2c_receive_byte ...\n");
+ iface_i2c_sda_w( device, 1);
+ for (int i = 0; i < 8; i++)
+ {
+ iface_i2c_scl_w( device, 1);
+ data = (data << 1) + (iface_i2c_sda_r( device) ? 1 : 0);
+ iface_i2c_scl_w( device, 0);
+ }
+ verboselog( device->machine(), 5, "recv data %02X\n", data);
+ verboselog( device->machine(), 5, "send ack %d\n", ack);
+ iface_i2c_sda_w( device, ack ? 0 : 1);
+ iface_i2c_scl_w( device, 1);
+ iface_i2c_scl_w( device, 0);
+ return data;
+}
+
+static int i2c_send_byte( device_t *device, UINT8 data)
+{
+ int ack;
+ verboselog( device->machine(), 5, "i2c_send_byte ...\n");
+ verboselog( device->machine(), 5, "send data %02X\n", data);
+ for (int i = 0; i < 8; i++)
+ {
+ iface_i2c_sda_w( device, (data & 0x80) ? 1 : 0);
+ data = data << 1;
+ iface_i2c_scl_w( device, 1);
+ iface_i2c_scl_w( device, 0);
+ }
+ iface_i2c_sda_w( device, 1); // ack bit
+ iface_i2c_scl_w( device, 1);
+ ack = iface_i2c_sda_r( device);
+ verboselog( device->machine(), 5, "recv ack %d\n", ack);
+ iface_i2c_scl_w( device, 0);
+ return ack;
+}
+
+static void iic_start( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ int mode_selection;
+ verboselog( device->machine(), 1, "IIC start\n");
+ i2c_send_start( device);
+ mode_selection = BITS( s3c24xx->iic.regs.iicstat, 7, 6);
+ switch (mode_selection)
+ {
+ case 2 : i2c_send_byte( device, s3c24xx->iic.regs.iicds | 0x01); break;
+ case 3 : i2c_send_byte( device, s3c24xx->iic.regs.iicds & 0xFE); break;
+ }
+ s3c24xx->iic.timer->adjust( attotime::from_usec( 1));
+}
+
+static void iic_stop( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ verboselog( device->machine(), 1, "IIC stop\n");
+ i2c_send_stop( device);
+ s3c24xx->iic.timer->adjust( attotime::never);
+}
+
+static void iic_resume( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ int mode_selection;
+ verboselog( device->machine(), 1, "IIC resume\n");
+ mode_selection = BITS( s3c24xx->iic.regs.iicstat, 7, 6);
+ switch (mode_selection)
+ {
+ case 2 : s3c24xx->iic.regs.iicds = i2c_receive_byte( device, BIT( s3c24xx->iic.regs.iiccon, 7)); break;
+ case 3 : i2c_send_byte( device, s3c24xx->iic.regs.iicds & 0xFF); break;
+ }
+ s3c24xx->iic.timer->adjust( attotime::from_usec( 1));
+}
+
+static READ32_DEVICE_HANDLER( s3c24xx_iic_r )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 data = ((UINT32*)&s3c24xx->iic.regs)[offset];
+ switch (offset)
+ {
+ case S3C24XX_IICSTAT :
+ {
+ data = data & ~0x0000000F;
+ }
+ break;
+ }
+ verboselog( device->machine(), 9, "(IIC) %08X -> %08X\n", S3C24XX_BASE_IIC + (offset << 2), data);
+ return data;
+}
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_iic_w )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 old_value = ((UINT32*)&s3c24xx->iic.regs)[offset];
+ verboselog( device->machine(), 9, "(IIC) %08X <- %08X\n", S3C24XX_BASE_IIC + (offset << 2), data);
+ COMBINE_DATA(&((UINT32*)&s3c24xx->iic.regs)[offset]);
+ switch (offset)
+ {
+ case S3C24XX_IICCON :
+ {
+ int interrupt_pending_flag;
+#if 0
+ const int div_table[] = { 16, 512};
+ int enable_interrupt, transmit_clock_value, tx_clock_source_selection
+ double clock;
+ transmit_clock_value = (data >> 0) & 0xF;
+ tx_clock_source_selection = (data >> 6) & 1;
+ enable_interrupt = (data >> 5) & 1;
+ clock = (double)s3c24xx_get_pclk( device) / div_table[tx_clock_source_selection] / (transmit_clock_value + 1);
+#endif
+ interrupt_pending_flag = BIT( old_value, 4);
+ if (interrupt_pending_flag != 0)
+ {
+ interrupt_pending_flag = BIT( data, 4);
+ if (interrupt_pending_flag == 0)
+ {
+ int start_stop_condition;
+ start_stop_condition = BIT( s3c24xx->iic.regs.iicstat, 5);
+ if (start_stop_condition != 0)
+ {
+ if (s3c24xx->iic.count == 0)
+ {
+ iic_start( device);
+
+ }
+ else
+ {
+ iic_resume( device);
+ }
+ }
+ else
+ {
+ iic_stop( device);
+ }
+ }
+ }
+ }
+ break;
+ case S3C24XX_IICSTAT :
+ {
+ int interrupt_pending_flag;
+ s3c24xx->iic.count = 0;
+ interrupt_pending_flag = BIT( s3c24xx->iic.regs.iiccon, 4);
+ if (interrupt_pending_flag == 0)
+ {
+ int start_stop_condition;
+ start_stop_condition = BIT( data, 5);
+ if (start_stop_condition != 0)
+ {
+ if (s3c24xx->iic.count == 0)
+ {
+ iic_start( device);
+
+ }
+ else
+ {
+ iic_resume( device);
+ }
+ }
+ else
+ {
+ iic_stop( device);
+ }
+ }
+ }
+ break;
+ }
+}
+
+static TIMER_CALLBACK( s3c24xx_iic_timer_exp )
+{
+ device_t *device = (device_t *)ptr;
+ s3c24xx_t *s3c24xx = get_token( device);
+ int enable_interrupt;
+ verboselog( machine, 2, "IIC timer callback\n");
+ s3c24xx->iic.count++;
+ enable_interrupt = BIT( s3c24xx->iic.regs.iiccon, 5);
+ if (enable_interrupt)
+ {
+ s3c24xx->iic.regs.iiccon |= (1 << 4); // [bit 4] interrupt is pending
+ s3c24xx_request_irq( device, S3C24XX_INT_IIC);
+ }
+}
+
+/* IIS */
+
+INLINE void iface_i2s_data_w( device_t *device, int ch, UINT16 data)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ if (s3c24xx->iface->i2s.data_w)
+ {
+ (s3c24xx->iface->i2s.data_w)( device, ch, data, 0);
+ }
+}
+
+static void s3c24xx_iis_start( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ const UINT32 codeclk_table[] = { 256, 384};
+ double freq;
+ int pclk, prescaler_enable, prescaler_control_a, prescaler_control_b, codeclk;
+ verboselog( device->machine(), 1, "IIS start\n");
+ prescaler_enable = BIT( s3c24xx->iis.regs.iiscon, 1);
+ prescaler_control_a = BITS( s3c24xx->iis.regs.iispsr, 9, 5);
+ prescaler_control_b = BITS( s3c24xx->iis.regs.iispsr, 4, 0);
+ codeclk = BIT( s3c24xx->iis.regs.iismod, 2);
+ pclk = s3c24xx_get_pclk( device);
+ freq = ((double)pclk / (prescaler_control_a + 1) / codeclk_table[codeclk]) * 2; // why do I have to multiply by two?
+ verboselog( device->machine(), 5, "IIS - pclk %d psc_enable %d psc_a %d psc_b %d codeclk %d freq %f\n", pclk, prescaler_enable, prescaler_control_a, prescaler_control_b, codeclk_table[codeclk], freq);
+ s3c24xx->iis.timer->adjust( attotime::from_hz( freq), 0, attotime::from_hz( freq));
+}
+
+static void s3c24xx_iis_stop( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ verboselog( device->machine(), 1, "IIS stop\n");
+ s3c24xx->iis.timer->adjust( attotime::never);
+}
+
+static void s3c24xx_iis_recalc( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ if ((s3c24xx->iis.regs.iiscon & (1 << 0)) != 0)
+ {
+ s3c24xx_iis_start( device);
+ }
+ else
+ {
+ s3c24xx_iis_stop( device);
+ }
+}
+
+static READ32_DEVICE_HANDLER( s3c24xx_iis_r )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 data = ((UINT32*)&s3c24xx->iis.regs)[offset];
+#if 0
+ switch (offset)
+ {
+ case S3C24XX_IISCON :
+ {
+ data = data & ~1; // hack for mp3 player
+ }
+ break;
+ }
+#endif
+ verboselog( device->machine(), 9, "(IIS) %08X -> %08X\n", S3C24XX_BASE_IIS + (offset << 2), data);
+ return data;
+}
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_iis_w )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 old_value = ((UINT32*)&s3c24xx->iis.regs)[offset];
+ verboselog( device->machine(), 9, "(IIS) %08X <- %08X\n", S3C24XX_BASE_IIS + (offset << 2), data);
+ COMBINE_DATA(&((UINT32*)&s3c24xx->iis.regs)[offset]);
+ switch (offset)
+ {
+ case S3C24XX_IISCON :
+ {
+ if ((old_value & (1 << 0)) != (data & (1 << 0)))
+ {
+ s3c24xx_iis_recalc( device);
+ }
+ }
+ break;
+ case S3C24XX_IISFIFO :
+ {
+ if (ACCESSING_BITS_16_31)
+ {
+ s3c24xx->iis.fifo[s3c24xx->iis.fifo_index++] = BITS( data, 31, 16);
+ }
+ if (ACCESSING_BITS_0_15)
+ {
+ s3c24xx->iis.fifo[s3c24xx->iis.fifo_index++] = BITS( data, 15, 0);
+ }
+ if (s3c24xx->iis.fifo_index == 2)
+ {
+ s3c24xx->iis.fifo_index = 0;
+ iface_i2s_data_w( device, 0, s3c24xx->iis.fifo[0]);
+ iface_i2s_data_w( device, 1, s3c24xx->iis.fifo[1]);
+ }
+ }
+ break;
+ }
+}
+
+static TIMER_CALLBACK( s3c24xx_iis_timer_exp )
+{
+ device_t *device = (device_t *)ptr;
+ verboselog( machine, 2, "IIS timer callback\n");
+ s3c24xx_dma_request_iis( device);
+}
+
+/* RTC */
+
+static void s3c24xx_rtc_init( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ s3c24xx->rtc.regs.bcdsec = dec_2_bcd( 0);
+ s3c24xx->rtc.regs.bcdmin = dec_2_bcd( 0);
+ s3c24xx->rtc.regs.bcdhour = dec_2_bcd( 0);
+ s3c24xx->rtc.regs.bcdday = dec_2_bcd( 1);
+ s3c24xx->rtc.regs.bcddow = dec_2_bcd( 1);
+ s3c24xx->rtc.regs.bcdmon = dec_2_bcd( 1);
+ s3c24xx->rtc.regs.bcdyear = dec_2_bcd( 4);
+}
+
+static READ32_DEVICE_HANDLER( s3c24xx_rtc_r )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 data = ((UINT32*)&s3c24xx->rtc.regs)[offset];
+ verboselog( device->machine(), 9, "(RTC) %08X -> %08X\n", S3C24XX_BASE_RTC + (offset << 2), data);
+ return data;
+}
+
+static void s3c24xx_rtc_recalc( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ if (s3c24xx->rtc.regs.ticnt & (1 << 7))
+ {
+ UINT32 ttc;
+ double freq;
+ ttc = BITS( s3c24xx->rtc.regs.ticnt, 6, 0);
+ freq = 128 / (ttc + 1);
+// printf( "ttc %d freq %f\n", ttc, freq);
+ s3c24xx->rtc.timer_tick_count->adjust( attotime::from_hz( freq), 0, attotime::from_hz( freq));
+ }
+ else
+ {
+ s3c24xx->rtc.timer_tick_count->adjust( attotime::never);
+ }
+}
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_rtc_w )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ verboselog( device->machine(), 9, "(RTC) %08X <- %08X\n", S3C24XX_BASE_RTC + (offset << 2), data);
+ COMBINE_DATA(&((UINT32*)&s3c24xx->rtc.regs)[offset]);
+ switch (offset)
+ {
+ case S3C24XX_TICNT :
+ {
+ s3c24xx_rtc_recalc( device);
+ }
+ break;
+ }
+}
+
+static TIMER_CALLBACK( s3c24xx_rtc_timer_tick_count_exp )
+{
+ device_t *device = (device_t *)ptr;
+ verboselog( machine, 2, "RTC timer callback (tick count)\n");
+ s3c24xx_request_irq( device, S3C24XX_INT_TICK);
+}
+
+static void s3c24xx_rtc_update( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 bcdday_max;
+ // increase second
+ s3c24xx->rtc.regs.bcdsec = bcd_adjust( s3c24xx->rtc.regs.bcdsec + 1);
+ if (s3c24xx->rtc.regs.bcdsec >= 0x60)
+ {
+ s3c24xx->rtc.regs.bcdsec = 0;
+ // increase minute
+ s3c24xx->rtc.regs.bcdmin = bcd_adjust( s3c24xx->rtc.regs.bcdmin + 1);
+ if (s3c24xx->rtc.regs.bcdmin >= 0x60)
+ {
+ s3c24xx->rtc.regs.bcdmin = 0;
+ // increase hour
+ s3c24xx->rtc.regs.bcdhour = bcd_adjust( s3c24xx->rtc.regs.bcdhour + 1);
+ if (s3c24xx->rtc.regs.bcdhour >= 0x24)
+ {
+ s3c24xx->rtc.regs.bcdhour = 0;
+ // increase day-of-week
+ s3c24xx->rtc.regs.bcddow = (s3c24xx->rtc.regs.bcddow % 7) + 1;
+ // increase day
+ s3c24xx->rtc.regs.bcdday = bcd_adjust( s3c24xx->rtc.regs.bcdday + 1);
+ bcdday_max = dec_2_bcd( gregorian_days_in_month( bcd_2_dec( s3c24xx->rtc.regs.bcdmon), bcd_2_dec( s3c24xx->rtc.regs.bcdyear) + 2000));
+ if (s3c24xx->rtc.regs.bcdday > bcdday_max)
+ {
+ s3c24xx->rtc.regs.bcdday = 1;
+ // increase month
+ s3c24xx->rtc.regs.bcdmon = bcd_adjust( s3c24xx->rtc.regs.bcdmon + 1);
+ if (s3c24xx->rtc.regs.bcdmon >= 0x12)
+ {
+ s3c24xx->rtc.regs.bcdmon = 1;
+ // increase year
+ s3c24xx->rtc.regs.bcdyear = bcd_adjust( s3c24xx->rtc.regs.bcdyear + 1);
+ if (s3c24xx->rtc.regs.bcdyear >= 0x100)
+ {
+ s3c24xx->rtc.regs.bcdyear = 0;
+ }
+ }
+ }
+ }
+ }
+ }
+ verboselog( device->machine(), 5, "RTC - %04d/%02d/%02d %02d:%02d:%02d\n", bcd_2_dec( s3c24xx->rtc.regs.bcdyear) + 2000, bcd_2_dec( s3c24xx->rtc.regs.bcdmon), bcd_2_dec( s3c24xx->rtc.regs.bcdday), bcd_2_dec( s3c24xx->rtc.regs.bcdhour), bcd_2_dec( s3c24xx->rtc.regs.bcdmin), bcd_2_dec( s3c24xx->rtc.regs.bcdsec));
+}
+
+static void s3c24xx_rtc_check_alarm( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ if (s3c24xx->rtc.regs.rtcalm & 0x40)
+ {
+ int isalarm = 1;
+ isalarm = isalarm && (((s3c24xx->rtc.regs.rtcalm & 0x20) == 0) || (s3c24xx->rtc.regs.almyear == s3c24xx->rtc.regs.bcdyear));
+ isalarm = isalarm && (((s3c24xx->rtc.regs.rtcalm & 0x10) == 0) || (s3c24xx->rtc.regs.almmon == s3c24xx->rtc.regs.bcdmon));
+ isalarm = isalarm && (((s3c24xx->rtc.regs.rtcalm & 0x08) == 0) || (s3c24xx->rtc.regs.almday == s3c24xx->rtc.regs.bcdday));
+ isalarm = isalarm && (((s3c24xx->rtc.regs.rtcalm & 0x04) == 0) || (s3c24xx->rtc.regs.almhour == s3c24xx->rtc.regs.bcdhour));
+ isalarm = isalarm && (((s3c24xx->rtc.regs.rtcalm & 0x02) == 0) || (s3c24xx->rtc.regs.almmin == s3c24xx->rtc.regs.bcdmin));
+ isalarm = isalarm && (((s3c24xx->rtc.regs.rtcalm & 0x01) == 0) || (s3c24xx->rtc.regs.almsec == s3c24xx->rtc.regs.bcdsec));
+ if (isalarm != 0)
+ {
+ s3c24xx_request_irq( device, S3C24XX_INT_RTC);
+ }
+ }
+}
+
+static TIMER_CALLBACK( s3c24xx_rtc_timer_update_exp )
+{
+ device_t *device = (device_t *)ptr;
+ verboselog( machine, 2, "RTC timer callback (update)\n");
+ s3c24xx_rtc_update( device);
+ s3c24xx_rtc_check_alarm( device);
+}
+
+/* A/D Converter */
+
+static UINT32 iface_adc_data_r( device_t *device, int ch)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ if (s3c24xx->iface->adc.data_r)
+ {
+ return (s3c24xx->iface->adc.data_r)( device, ch, 0);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static READ32_DEVICE_HANDLER( s3c24xx_adc_r )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 data = ((UINT32*)&s3c24xx->adc.regs)[offset];
+ switch (offset)
+ {
+#if defined(DEVICE_S3C2400)
+ case S3C24XX_ADCDAT :
+ {
+ data = (data & ~0x3FF) | (iface_adc_data_r( device, 0) & 0x3FF);
+ }
+ break;
+#else
+ case S3C24XX_ADCDAT0 :
+ {
+ data = (data & ~0x3FF) | (iface_adc_data_r( device, 0) & 0x3FF);
+ }
+ break;
+ case S3C24XX_ADCDAT1 :
+ {
+ data = (data & ~0x3FF) | (iface_adc_data_r( device, 1) & 0x3FF);
+ }
+ break;
+#endif
+ }
+ verboselog( device->machine(), 9, "(ADC) %08X -> %08X\n", S3C24XX_BASE_ADC + (offset << 2), data);
+ return data;
+}
+
+static void s3c24xx_adc_start( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ verboselog( device->machine(), 1, "ADC start\n");
+ s3c24xx->adc.regs.adccon &= ~(1 << 0); // A/D conversion is completed
+ s3c24xx->adc.regs.adccon |= (1 << 15); // End of A/D conversion
+}
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_adc_w )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 old_value = ((UINT32*)&s3c24xx->adc.regs)[offset];
+ verboselog( device->machine(), 9, "(ADC) %08X <- %08X\n", S3C24XX_BASE_ADC + (offset << 2), data);
+ COMBINE_DATA(&((UINT32*)&s3c24xx->adc.regs)[offset]);
+ switch (offset)
+ {
+ case S3C24XX_ADCCON :
+ {
+ if (((old_value & (1 << 0)) == 0) && ((data & (1 << 0)) != 0))
+ {
+ s3c24xx_adc_start( device);
+ }
+ }
+ break;
+ }
+}
+
+#if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
+
+static void s3c24xx_touch_screen( device_t *device, int state)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ s3c24xx->adc.regs.adcdat0 = ((state ? 0 : 1) << 15);
+ s3c24xx->adc.regs.adcdat1 = ((state ? 0 : 1) << 15);
+ s3c24xx_request_subirq( device, S3C24XX_SUBINT_TC);
+}
+
+#endif
+
+/* SPI */
+
+static UINT32 s3c24xx_spi_r( device_t *device, UINT32 ch, UINT32 offset)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 data = ((UINT32*)&s3c24xx->spi[ch].regs)[offset];
+ switch (offset)
+ {
+ case S3C24XX_SPSTA :
+ {
+ data = data | (1 << 0); // [bit 0] Transfer Ready Flag
+ }
+ break;
+ }
+ return data;
+}
+
+static void s3c24xx_spi_w( device_t *device, UINT32 ch, UINT32 offset, UINT32 data, UINT32 mem_mask)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ COMBINE_DATA(&((UINT32*)&s3c24xx->spi[ch].regs)[offset]);
+}
+
+static READ32_DEVICE_HANDLER( s3c24xx_spi_0_r )
+{
+ UINT32 data = s3c24xx_spi_r( device, 0, offset);
+ verboselog( device->machine(), 9, "(SPI 0) %08X -> %08X\n", S3C24XX_BASE_SPI_0 + (offset << 2), data);
+ return data;
+}
+
+#if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
+
+static READ32_DEVICE_HANDLER( s3c24xx_spi_1_r )
+{
+ UINT32 data = s3c24xx_spi_r( device, 1, offset);
+ verboselog( device->machine(), 9, "(SPI 1) %08X -> %08X\n", S3C24XX_BASE_SPI_1 + (offset << 2), data);
+ return data;
+}
+
+#endif
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_spi_0_w )
+{
+ verboselog( device->machine(), 9, "(SPI 0) %08X <- %08X\n", S3C24XX_BASE_SPI_0 + (offset << 2), data);
+ s3c24xx_spi_w( device, 0, offset, data, mem_mask);
+}
+
+#if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_spi_1_w )
+{
+ verboselog( device->machine(), 9, "(SPI 1) %08X <- %08X\n", S3C24XX_BASE_SPI_1 + (offset << 2), data);
+ s3c24xx_spi_w( device, 1, offset, data, mem_mask);
+}
+
+#endif
+
+/* MMC Interface */
+
+#if defined(DEVICE_S3C2400)
+
+static READ32_DEVICE_HANDLER( s3c24xx_mmc_r )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 data = s3c24xx->mmc.regs.data[offset];
+ verboselog( device->machine(), 9, "(MMC) %08X -> %08X\n", S3C24XX_BASE_MMC + (offset << 2), data);
+ return data;
+}
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_mmc_w )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ verboselog( device->machine(), 9, "(MMC) %08X <- %08X\n", S3C24XX_BASE_MMC + (offset << 2), data);
+ COMBINE_DATA(&s3c24xx->mmc.regs.data[offset]);
+}
+
+#endif
+
+/* SD Interface */
+
+#if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
+
+static READ32_DEVICE_HANDLER( s3c24xx_sdi_r )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 data = s3c24xx->sdi.regs.data[offset];
+ verboselog( device->machine(), 9, "(SDI) %08X -> %08X\n", S3C24XX_BASE_SDI + (offset << 2), data);
+ return data;
+}
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_sdi_w )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ verboselog( device->machine(), 9, "(SDI) %08X <- %08X\n", S3C24XX_BASE_SDI + (offset << 2), data);
+ COMBINE_DATA(&s3c24xx->sdi.regs.data[offset]);
+}
+
+#endif
+
+/* NAND Flash */
+
+#if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
+
+INLINE void iface_nand_command_w( device_t *device, UINT8 data)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ if (s3c24xx->iface->nand.command_w)
+ {
+ (s3c24xx->iface->nand.command_w)( device, 0, data);
+ }
+}
+
+INLINE void iface_nand_address_w( device_t *device, UINT8 data)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ if (s3c24xx->iface->nand.address_w)
+ {
+ (s3c24xx->iface->nand.address_w)( device, 0, data);
+ }
+}
+
+INLINE UINT8 iface_nand_data_r( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ if (s3c24xx->iface->nand.data_r)
+ {
+ return (s3c24xx->iface->nand.data_r)( device, 0);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+INLINE void iface_nand_data_w( device_t *device, UINT8 data)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ if (s3c24xx->iface->nand.data_w)
+ {
+ (s3c24xx->iface->nand.data_w)( device, 0, data);
+ }
+}
+
+static void nand_update_mecc( UINT8 *ecc, int pos, UINT8 data)
+{
+ int bit[8];
+ UINT8 temp;
+ bit[0] = (data >> 0) & 1;
+ bit[1] = (data >> 1) & 1;
+ bit[2] = (data >> 2) & 1;
+ bit[3] = (data >> 3) & 1;
+ bit[4] = (data >> 4) & 1;
+ bit[5] = (data >> 5) & 1;
+ bit[6] = (data >> 6) & 1;
+ bit[7] = (data >> 7) & 1;
+ // column parity
+ ecc[2] ^= ((bit[6] ^ bit[4] ^ bit[2] ^ bit[0]) << 2);
+ ecc[2] ^= ((bit[7] ^ bit[5] ^ bit[3] ^ bit[1]) << 3);
+ ecc[2] ^= ((bit[5] ^ bit[4] ^ bit[1] ^ bit[0]) << 4);
+ ecc[2] ^= ((bit[7] ^ bit[6] ^ bit[3] ^ bit[2]) << 5);
+ ecc[2] ^= ((bit[3] ^ bit[2] ^ bit[1] ^ bit[0]) << 6);
+ ecc[2] ^= ((bit[7] ^ bit[6] ^ bit[5] ^ bit[4]) << 7);
+ // line parity
+ temp = bit[7] ^ bit[6] ^ bit[5] ^ bit[4] ^ bit[3] ^ bit[2] ^ bit[1] ^ bit[0];
+ if (pos & 0x001) ecc[0] ^= (temp << 1); else ecc[0] ^= (temp << 0);
+ if (pos & 0x002) ecc[0] ^= (temp << 3); else ecc[0] ^= (temp << 2);
+ if (pos & 0x004) ecc[0] ^= (temp << 5); else ecc[0] ^= (temp << 4);
+ if (pos & 0x008) ecc[0] ^= (temp << 7); else ecc[0] ^= (temp << 6);
+ if (pos & 0x010) ecc[1] ^= (temp << 1); else ecc[1] ^= (temp << 0);
+ if (pos & 0x020) ecc[1] ^= (temp << 3); else ecc[1] ^= (temp << 2);
+ if (pos & 0x040) ecc[1] ^= (temp << 5); else ecc[1] ^= (temp << 4);
+ if (pos & 0x080) ecc[1] ^= (temp << 7); else ecc[1] ^= (temp << 6);
+ if (pos & 0x100) ecc[2] ^= (temp << 1); else ecc[2] ^= (temp << 0);
+ if (pos & 0x200) ecc[3] ^= (temp << 5); else ecc[3] ^= (temp << 4);
+ if (pos & 0x400) ecc[3] ^= (temp << 7); else ecc[3] ^= (temp << 6);
+}
+
+#if defined(DEVICE_S3C2440)
+
+static void nand_update_secc( UINT8 *ecc, int pos, UINT8 data)
+{
+ int bit[8];
+ UINT8 temp;
+ bit[0] = (data >> 0) & 1;
+ bit[1] = (data >> 1) & 1;
+ bit[2] = (data >> 2) & 1;
+ bit[3] = (data >> 3) & 1;
+ bit[4] = (data >> 4) & 1;
+ bit[5] = (data >> 5) & 1;
+ bit[6] = (data >> 6) & 1;
+ bit[7] = (data >> 7) & 1;
+ // column parity
+ ecc[1] ^= ((bit[6] ^ bit[4] ^ bit[2] ^ bit[0]) << 6);
+ ecc[1] ^= ((bit[7] ^ bit[5] ^ bit[3] ^ bit[1]) << 7);
+ ecc[0] ^= ((bit[5] ^ bit[4] ^ bit[1] ^ bit[0]) << 0);
+ ecc[0] ^= ((bit[7] ^ bit[6] ^ bit[3] ^ bit[2]) << 1);
+ ecc[0] ^= ((bit[3] ^ bit[2] ^ bit[1] ^ bit[0]) << 2);
+ ecc[0] ^= ((bit[7] ^ bit[6] ^ bit[5] ^ bit[4]) << 3);
+ // line parity
+ temp = bit[7] ^ bit[6] ^ bit[5] ^ bit[4] ^ bit[3] ^ bit[2] ^ bit[1] ^ bit[0];
+ if (pos & 0x001) ecc[0] ^= (temp << 5); else ecc[0] ^= (temp << 4);
+ if (pos & 0x002) ecc[0] ^= (temp << 7); else ecc[0] ^= (temp << 6);
+ if (pos & 0x004) ecc[1] ^= (temp << 3); else ecc[1] ^= (temp << 2);
+ if (pos & 0x008) ecc[1] ^= (temp << 5); else ecc[1] ^= (temp << 4);
+}
+
+#endif
+
+static void s3c24xx_nand_update_ecc( device_t *device, UINT8 data)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT8 temp[4];
+#if defined(DEVICE_S3C2410)
+ temp[0] = s3c24xx->nand.mecc[0];
+ temp[1] = s3c24xx->nand.mecc[1];
+ temp[2] = s3c24xx->nand.mecc[2];
+ nand_update_mecc( s3c24xx->nand.mecc, s3c24xx->nand.pos++, data);
+ verboselog( device->machine(), 5, "NAND - MECC %03X - %02X %02X %02X -> %02X %02X %02X\n", s3c24xx->nand.pos - 1, temp[0], temp[1], temp[2], s3c24xx->nand.mecc[0], s3c24xx->nand.mecc[1], s3c24xx->nand.mecc[2]);
+ if (s3c24xx->nand.pos == 512) s3c24xx->nand.pos = 0;
+#else
+ if ((s3c24xx->nand.regs.nfcont & (1 << 5)) == 0)
+ {
+ temp[0] = s3c24xx->nand.mecc[0];
+ temp[1] = s3c24xx->nand.mecc[1];
+ temp[2] = s3c24xx->nand.mecc[2];
+ temp[3] = s3c24xx->nand.mecc[3];
+ nand_update_mecc( s3c24xx->nand.mecc, s3c24xx->nand.pos++, data);
+ verboselog( device->machine(), 5, "NAND - MECC %03X - %02X %02X %02X %02X -> %02X %02X %02X %02X\n", s3c24xx->nand.pos - 1, temp[0], temp[1], temp[2], temp[3], s3c24xx->nand.mecc[0], s3c24xx->nand.mecc[1], s3c24xx->nand.mecc[2], s3c24xx->nand.mecc[3]);
+ if (s3c24xx->nand.pos == 2048) s3c24xx->nand.pos = 0;
+ }
+ if ((s3c24xx->nand.regs.nfcont & (1 << 6)) == 0)
+ {
+ temp[0] = s3c24xx->nand.secc[0];
+ temp[1] = s3c24xx->nand.secc[1];
+ nand_update_secc( s3c24xx->nand.secc, s3c24xx->nand.pos++, data);
+ verboselog( device->machine(), 5, "NAND - SECC %02X - %02X %02X -> %02X %02X\n", s3c24xx->nand.pos - 1, temp[0], temp[1], s3c24xx->nand.secc[0], s3c24xx->nand.secc[1]);
+ if (s3c24xx->nand.pos == 16) s3c24xx->nand.pos = 0;
+ }
+#endif
+}
+
+static void s3c24xx_nand_command_w( device_t *device, UINT8 data)
+{
+ verboselog( device->machine(), 5, "NAND write command %02X\n", data);
+ iface_nand_command_w( device, data);
+}
+
+static void s3c24xx_nand_address_w( device_t *device, UINT8 data)
+{
+ verboselog( device->machine(), 5, "NAND write address %02X\n", data);
+ iface_nand_address_w( device, data);
+}
+
+static UINT8 s3c24xx_nand_data_r( device_t *device)
+{
+ UINT8 data = iface_nand_data_r( device);
+ verboselog( device->machine(), 5, "NAND data read %02X\n", data);
+ s3c24xx_nand_update_ecc( device, data);
+ return data;
+}
+
+static void s3c24xx_nand_data_w( device_t *device, UINT8 data)
+{
+ verboselog( device->machine(), 5, "NAND write data %02X\n", data);
+ iface_nand_data_w( device, data);
+ s3c24xx_nand_update_ecc( device, data);
+}
+
+static READ32_DEVICE_HANDLER( s3c24xx_nand_r )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 data = ((UINT32*)&s3c24xx->nand.regs)[offset];
+ switch (offset)
+ {
+ case S3C24XX_NFDATA :
+ {
+ data = 0;
+ if ((mem_mask & 0x000000FF) != 0) data = data | (s3c24xx_nand_data_r( device) << 0);
+ if ((mem_mask & 0x0000FF00) != 0) data = data | (s3c24xx_nand_data_r( device) << 8);
+ if ((mem_mask & 0x00FF0000) != 0) data = data | (s3c24xx_nand_data_r( device) << 16);
+ if ((mem_mask & 0xFF000000) != 0) data = data | (s3c24xx_nand_data_r( device) << 24);
+ }
+ break;
+#if defined(DEVICE_S3C2410)
+ case S3C24XX_NFECC :
+ {
+ data = (s3c24xx->nand.mecc[2] << 16) | (s3c24xx->nand.mecc[1] << 8) | (s3c24xx->nand.mecc[0] << 0);
+ //data = 0xFFFFFFFF;
+ }
+ break;
+#endif
+#if defined(DEVICE_S3C2440)
+ case S3C24XX_NFMECC0 :
+ {
+
+ data = (s3c24xx->nand.mecc[3] << 24) | (s3c24xx->nand.mecc[2] << 16) | (s3c24xx->nand.mecc[1] << 8) | (s3c24xx->nand.mecc[0] << 0);
+ }
+ break;
+ case S3C24XX_NFSECC :
+ {
+ data = (s3c24xx->nand.secc[1] << 8) | (s3c24xx->nand.secc[0] << 0);
+ }
+ break;
+ case S3C24XX_NFESTAT0 :
+ {
+ data &= ~0x000000F; // no main/spare ECC errors
+ }
+ break;
+ case S3C24XX_NFESTAT1 :
+ {
+ data &= ~0x000000F; // no main/spare ECC errors
+ }
+ break;
+#endif
+ }
+ verboselog( device->machine(), 9, "(NAND) %08X -> %08X (%08X)\n", S3C24XX_BASE_NAND + (offset << 2), data, mem_mask);
+ return data;
+}
+
+static void s3c24xx_nand_init_ecc( device_t *device)
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ verboselog( device->machine(), 5, "NAND - init ecc\n");
+#if defined(DEVICE_S3C2410)
+ s3c24xx->nand.mecc[0] = 0;
+ s3c24xx->nand.mecc[1] = 0;
+ s3c24xx->nand.mecc[2] = 0;
+#else
+ s3c24xx->nand.mecc[0] = 0;
+ s3c24xx->nand.mecc[1] = 0;
+ s3c24xx->nand.mecc[2] = 0;
+ s3c24xx->nand.mecc[3] = 0;
+ s3c24xx->nand.secc[0] = 0;
+ s3c24xx->nand.secc[1] = 0;
+#endif
+ s3c24xx->nand.pos = 0;
+}
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_nand_w )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 old_value = ((UINT32*)&s3c24xx->nand.regs)[offset];
+ verboselog( device->machine(), 9, "(NAND) %08X <- %08X\n", S3C24XX_BASE_NAND + (offset << 2), data);
+ COMBINE_DATA(&((UINT32*)&s3c24xx->nand.regs)[offset]);
+ switch (offset)
+ {
+#if defined(DEVICE_S3C2410)
+ case S3C24XX_NFCONF :
+ {
+ if ((data & (1 << 12)) != 0)
+ {
+ s3c24xx_nand_init_ecc( device);
+ }
+ }
+ break;
+#endif
+#if defined(DEVICE_S3C2440)
+ case S3C24XX_NFCONT :
+ {
+ if ((data & (1 << 4)) != 0)
+ {
+ s3c24xx_nand_init_ecc( device);
+ }
+ }
+ break;
+#endif
+ case S3C24XX_NFSTAT :
+ {
+ s3c24xx->nand.regs.nfstat = (s3c24xx->nand.regs.nfstat & ~0x03) | (old_value & 0x03);
+#if defined(DEVICE_S3C2440)
+ if ((data & (1 << 2)) != 0)
+ {
+ s3c24xx->nand.regs.nfstat &= ~(1 << 2); // "RnB_TransDetect, to clear this value write 1"
+ }
+#endif
+ }
+ break;
+ case S3C24XX_NFCMD :
+ {
+ s3c24xx_nand_command_w( device, data);
+ }
+ break;
+ case S3C24XX_NFADDR :
+ {
+ s3c24xx_nand_address_w( device, data);
+ }
+ break;
+ case S3C24XX_NFDATA :
+ {
+ if ((mem_mask & 0x000000FF) != 0) s3c24xx_nand_data_w( device, (data >> 0) & 0xFF);
+ if ((mem_mask & 0x0000FF00) != 0) s3c24xx_nand_data_w( device, (data >> 8) & 0xFF);
+ if ((mem_mask & 0x00FF0000) != 0) s3c24xx_nand_data_w( device, (data >> 16) & 0xFF);
+ if ((mem_mask & 0xFF000000) != 0) s3c24xx_nand_data_w( device, (data >> 24) & 0xFF);
+ }
+ break;
+ }
+}
+
+ATTR_UNUSED static WRITE_LINE_DEVICE_HANDLER( s3c24xx_pin_frnb_w )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+#if defined(DEVICE_S3C2440)
+ if ((BIT( s3c24xx->nand.regs.nfstat, 0) == 0) && (state != 0))
+ {
+ s3c24xx->nand.regs.nfstat |= (1 << 2);
+ if (BIT( s3c24xx->nand.regs.nfcont, 9) != 0)
+ {
+ s3c24xx_request_irq( device, S3C24XX_INT_NFCON);
+ }
+ }
+#endif
+ if (state == 0)
+ {
+ s3c24xx->nand.regs.nfstat &= ~(1 << 0);
+ }
+ else
+ {
+ s3c24xx->nand.regs.nfstat |= (1 << 0);
+ }
+}
+
+#endif
+
+/* Camera Interface */
+
+#if defined(DEVICE_S3C2440)
+
+static READ32_DEVICE_HANDLER( s3c24xx_cam_r )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 data = s3c24xx->cam.regs.data[offset];
+ verboselog( device->machine(), 9, "(CAM) %08X -> %08X\n", S3C24XX_BASE_CAM + (offset << 2), data);
+ return data;
+}
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_cam_w )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ verboselog( device->machine(), 9, "(CAM) %08X <- %08X\n", S3C24XX_BASE_CAM + (offset << 2), data);
+ COMBINE_DATA(&s3c24xx->cam.regs.data[offset]);
+}
+
+#endif
+
+/* AC97 Interface */
+
+#if defined(DEVICE_S3C2440)
+
+static READ32_DEVICE_HANDLER( s3c24xx_ac97_r )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ UINT32 data = s3c24xx->ac97.regs.data[offset];
+ verboselog( device->machine(), 9, "(AC97) %08X -> %08X\n", S3C24XX_BASE_AC97 + (offset << 2), data);
+ return data;
+}
+
+static WRITE32_DEVICE_HANDLER( s3c24xx_ac97_w )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ verboselog( device->machine(), 9, "(AC97) %08X <- %08X\n", S3C24XX_BASE_AC97 + (offset << 2), data);
+ COMBINE_DATA(&s3c24xx->ac97.regs.data[offset]);
+}
+
+#endif
+
+// ...
+
+static DEVICE_RESET( s3c24xx )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ s3c24xx->iis.fifo_index = 0;
+// s3c24xx->iic.data_index = 0;
+#if defined(DEVICE_S3C2410) || defined(DEVICE_S3C2440)
+ s3c24xx->gpio.regs.gstatus2 = 0x00000001; // Boot is caused by power on reset
+#endif
+ s3c24xx->irq.line_irq = s3c24xx->irq.line_fiq = CLEAR_LINE;
+}
+
+static DEVICE_START( s3c24xx )
+{
+ s3c24xx_t *s3c24xx = get_token( device);
+ s3c24xx->iface = (const s3c24xx_interface *)device->static_config();
+ for (int i = 0; i < 5; i++) s3c24xx->pwm.timer[i] = device->machine().scheduler().timer_alloc( FUNC(s3c24xx_pwm_timer_exp), (void*)device);
+ for (int i = 0; i < 4; i++) s3c24xx->dma[i].timer = device->machine().scheduler().timer_alloc( FUNC(s3c24xx_dma_timer_exp), (void*)device);
+ s3c24xx->iic.timer = device->machine().scheduler().timer_alloc( FUNC(s3c24xx_iic_timer_exp), (void*)device);
+ s3c24xx->iis.timer = device->machine().scheduler().timer_alloc( FUNC(s3c24xx_iis_timer_exp), (void*)device);
+ s3c24xx->lcd.timer = device->machine().scheduler().timer_alloc( FUNC(s3c24xx_lcd_timer_exp), (void*)device);
+ s3c24xx->rtc.timer_tick_count = device->machine().scheduler().timer_alloc( FUNC(s3c24xx_rtc_timer_tick_count_exp), (void*)device);
+ s3c24xx->rtc.timer_update = device->machine().scheduler().timer_alloc( FUNC(s3c24xx_rtc_timer_update_exp), (void*)device);
+ s3c24xx->wdt.timer = device->machine().scheduler().timer_alloc( FUNC(s3c24xx_wdt_timer_exp), (void*)device);
+ s3c24xx->rtc.timer_update->adjust( attotime::from_msec( 1000), 0, attotime::from_msec( 1000));
+ s3c24xx_rtc_init( device);
+}
+
+static DEVICE_GET_INFO( s3c24xx )
+{
+ switch ( state )
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(s3c24xx_t); break;
+ case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break;
+// case DEVINFO_INT_CLASS: info->i = DEVICE_CLASS_PERIPHERAL; break;
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(s3c24xx); break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(s3c24xx); break;
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "S3C24XX"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.00"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright the MESS Team"); break;
+ }
+}
diff --git a/trunk/src/emu/machine/scsi.c b/trunk/src/emu/machine/scsi.c
new file mode 100644
index 00000000000..9506bb1fe0a
--- /dev/null
+++ b/trunk/src/emu/machine/scsi.c
@@ -0,0 +1,159 @@
+#include "emu.h"
+#include "scsi.h"
+
+void SCSIAllocInstance( running_machine &machine, const SCSIClass *scsiClass, SCSIInstance **instance, const char *diskregion )
+{
+ SCSIAllocInstanceParams params;
+ params.instance = NULL;
+ params.diskregion = diskregion;
+ params.m_machine = &machine;
+ scsiClass->dispatch( SCSIOP_ALLOC_INSTANCE, (void *)scsiClass, 0, &params );
+ *instance = params.instance;
+}
+
+void SCSIDeleteInstance( SCSIInstance *instance )
+{
+ if (instance)
+ {
+ instance->scsiClass->dispatch( SCSIOP_DELETE_INSTANCE, instance, 0, NULL );
+ }
+}
+
+void SCSISetDevice( SCSIInstance *instance, void *device )
+{
+ if (instance)
+ {
+ instance->scsiClass->dispatch( SCSIOP_SET_DEVICE, instance, 0, device );
+ }
+}
+
+void SCSIGetDevice( SCSIInstance *instance, void **device )
+{
+ if (instance)
+ {
+ instance->scsiClass->dispatch( SCSIOP_GET_DEVICE, instance, 0, device );
+ }
+}
+
+void SCSIReset( SCSIInstance *instance )
+{
+ if (instance)
+ {
+ instance->scsiClass->dispatch( SCSIOP_RESET_DEVICE, instance, 0, NULL );
+ }
+}
+
+void SCSIExecCommand( SCSIInstance *instance, int *resultLength )
+{
+ if (instance)
+ {
+ *resultLength = instance->scsiClass->dispatch( SCSIOP_EXEC_COMMAND, instance, 0, NULL );
+ }
+}
+
+void SCSISetCommand( SCSIInstance *instance, UINT8 *command, int commandLength )
+{
+ if (instance)
+ {
+ instance->scsiClass->dispatch( SCSIOP_SET_COMMAND, instance, commandLength, command );
+ }
+}
+
+void SCSIGetCommand( SCSIInstance *instance, UINT8 **command, int *commandLength )
+{
+ if (instance)
+ {
+ *commandLength = instance->scsiClass->dispatch( SCSIOP_GET_COMMAND, instance, 0, command );
+ }
+}
+
+void SCSIWriteData( SCSIInstance *instance, void *data, int dataLength )
+{
+ if (instance)
+ {
+ instance->scsiClass->dispatch( SCSIOP_WRITE_DATA, instance, dataLength, data );
+ }
+}
+
+void SCSIReadData( SCSIInstance *instance, void *data, int dataLength )
+{
+ if (instance)
+ {
+ instance->scsiClass->dispatch( SCSIOP_READ_DATA, instance, dataLength, data );
+ }
+}
+
+void SCSISetPhase( SCSIInstance *instance, int phase )
+{
+ if (instance)
+ {
+ instance->scsiClass->dispatch( SCSIOP_SET_PHASE, instance, phase, NULL );
+ }
+}
+
+void SCSIGetPhase( SCSIInstance *instance, int *phase )
+{
+ if (instance)
+ {
+ *phase = instance->scsiClass->dispatch( SCSIOP_GET_PHASE, instance, 0, NULL );
+ }
+}
+
+int SCSIBase( const SCSIClass *scsiClass, int operation, void *file, INT64 intparm, UINT8 *ptrparm )
+{
+ return scsiClass->baseClass->dispatch( operation, file, intparm, ptrparm );
+}
+
+SCSIInstance *SCSIMalloc( running_machine &machine, const SCSIClass *scsiClass )
+{
+ SCSIInstance *scsiInstance = (SCSIInstance *)auto_alloc_array(machine, UINT8, SCSISizeof( scsiClass ));
+ scsiInstance->scsiClass = scsiClass;
+ scsiInstance->m_machine = &machine;
+ return scsiInstance;
+}
+
+void *SCSIThis( const SCSIClass *scsiClass, SCSIInstance *instance )
+{
+ if( instance != NULL )
+ {
+ int sizeofBase = sizeof( SCSIInstance );
+
+ while( scsiClass->baseClass != NULL )
+ {
+ scsiClass = scsiClass->baseClass;
+ sizeofBase += scsiClass->sizeofData;
+ }
+
+ return ( (UINT8*)instance ) + sizeofBase;
+ }
+
+ return NULL;
+}
+
+int SCSISizeof( const SCSIClass *scsiClass )
+{
+ int sizeofData = sizeof( SCSIInstance );
+
+ while( scsiClass != NULL )
+ {
+ sizeofData += scsiClass->sizeofData;
+ scsiClass = scsiClass->baseClass;
+ }
+
+ return sizeofData;
+}
+
+int SCSILengthFromUINT8( UINT8 *length )
+{
+ if( *length == 0 )
+ {
+ return 256;
+ }
+
+ return *length;
+}
+
+int SCSILengthFromUINT16( UINT8 *length )
+{
+ return ( *(length) << 8 ) | *(length + 1 );
+}
diff --git a/trunk/src/emu/machine/scsi.h b/trunk/src/emu/machine/scsi.h
new file mode 100644
index 00000000000..b040e32230a
--- /dev/null
+++ b/trunk/src/emu/machine/scsi.h
@@ -0,0 +1,113 @@
+/***************************************************************************
+
+ scsi.h - Header which defines the interface between SCSI device handlers
+ and SCSI interfaces.
+
+***************************************************************************/
+
+#ifndef _SCSI_H_
+#define _SCSI_H_
+
+
+typedef int (*pSCSIDispatch)( int operation, void *file, INT64 intparm, void *ptrparm );
+
+typedef struct _SCSIClass
+{
+ const struct _SCSIClass *baseClass;
+ pSCSIDispatch dispatch;
+ int sizeofData;
+} SCSIClass;
+
+typedef struct
+{
+ running_machine &machine() const { assert(m_machine != NULL); return *m_machine; }
+ const SCSIClass *scsiClass;
+ running_machine *m_machine;
+} SCSIInstance;
+
+typedef struct
+{
+ running_machine &machine() const { assert(m_machine != NULL); return *m_machine; }
+ SCSIInstance *instance;
+ const char *diskregion;
+ running_machine *m_machine;
+} SCSIAllocInstanceParams;
+
+// commands accepted by a SCSI device's dispatch handler
+enum
+{
+ SCSIOP_EXEC_COMMAND = 0, // execute a command packet
+ SCSIOP_SET_COMMAND, // set a command packet
+ SCSIOP_GET_COMMAND, // get a command packet
+ SCSIOP_READ_DATA, // data transfer from the device
+ SCSIOP_WRITE_DATA, // data transfer to the device
+ SCSIOP_ALLOC_INSTANCE, // allocate an instance of the device
+ SCSIOP_DELETE_INSTANCE, // delete an instance of the device
+ SCSIOP_GET_DEVICE, // get the device's internal device (CDROM or HDD pointer)
+ SCSIOP_SET_DEVICE, // set the device's internal device (CDROM or HDD pointer)
+ SCSIOP_RESET_DEVICE, // reset the device
+ SCSIOP_SET_PHASE,
+ SCSIOP_GET_PHASE,
+};
+
+typedef struct scsiconfigitem
+{
+ int scsiID;
+ const char *diskregion;
+ const SCSIClass *scsiClass;
+} SCSIConfigItem;
+
+#define SCSI_MAX_DEVICES (16)
+
+typedef struct scsiconfigtable
+{
+ int devs_present;
+ const SCSIConfigItem devices[SCSI_MAX_DEVICES];
+} SCSIConfigTable;
+
+// SCSI IDs
+enum
+{
+ SCSI_ID_0 = 0,
+ SCSI_ID_1,
+ SCSI_ID_2,
+ SCSI_ID_3,
+ SCSI_ID_4,
+ SCSI_ID_5,
+ SCSI_ID_6,
+ SCSI_ID_7
+};
+
+
+#define SCSI_PHASE_DATAOUT ( 0 )
+#define SCSI_PHASE_DATAIN ( 1 )
+#define SCSI_PHASE_COMMAND ( 2 )
+#define SCSI_PHASE_STATUS ( 3 )
+#define SCSI_PHASE_MESSAGE_OUT ( 6 )
+#define SCSI_PHASE_MESSAGE_IN ( 7 )
+
+extern void SCSIAllocInstance( running_machine &machine, const SCSIClass *scsiClass, SCSIInstance **instance, const char *diskregion );
+extern void SCSIDeleteInstance( SCSIInstance *instance );
+extern void SCSISetDevice( SCSIInstance *instance, void *device );
+extern void SCSIGetDevice( SCSIInstance *instance, void **device );
+extern void SCSIReset( SCSIInstance *instance );
+extern void SCSISetCommand( SCSIInstance *instance, UINT8 *command, int commandLength );
+extern void SCSIGetCommand( SCSIInstance *instance, UINT8 **command, int *commandLength );
+extern void SCSIExecCommand( SCSIInstance *instance, int *resultLength );
+extern void SCSIWriteData( SCSIInstance *instance, void *data, int dataLength );
+extern void SCSIReadData( SCSIInstance *instance, void *data, int dataLength );
+extern void SCSISetPhase( SCSIInstance *instance, int phase );
+extern void SCSIGetPhase( SCSIInstance *instance, int *phase );
+
+extern SCSIInstance *SCSIMalloc( running_machine &machine, const SCSIClass *scsiClass );
+extern int SCSIBase( const SCSIClass *scsiClass, int operation, void *file, INT64 intparm, UINT8 *ptrparm );
+extern void *SCSIThis( const SCSIClass *scsiClass, SCSIInstance *instance );
+extern int SCSISizeof( const SCSIClass *scsiClass );
+extern int SCSILengthFromUINT8( UINT8 *length );
+extern int SCSILengthFromUINT16( UINT8 *length );
+
+#endif
+
+// include these here to avoid changing the drivers.
+#include "machine/scsicd.h"
+#include "machine/scsihd.h"
diff --git a/trunk/src/emu/machine/scsicd.c b/trunk/src/emu/machine/scsicd.c
new file mode 100644
index 00000000000..9b1d53c37f9
--- /dev/null
+++ b/trunk/src/emu/machine/scsicd.c
@@ -0,0 +1,775 @@
+/***************************************************************************
+
+ scsicd.c - Implementation of a SCSI CD-ROM device, using MAME's cdrom.c primitives
+
+***************************************************************************/
+
+#include "emu.h"
+#include "scsidev.h"
+#include "cdrom.h"
+#include "sound/cdda.h"
+#include "imagedev/chd_cd.h"
+#include "scsicd.h"
+
+typedef struct
+{
+ UINT32 lba;
+ UINT32 blocks;
+ UINT32 last_lba;
+ UINT32 bytes_per_sector;
+ UINT32 num_subblocks;
+ UINT32 cur_subblock;
+ UINT32 play_err_flag;
+ cdrom_file *cdrom;
+ bool is_file;
+} SCSICd;
+
+static void phys_frame_to_msf(int phys_frame, int *m, int *s, int *f)
+{
+ *m = phys_frame / (60*75);
+ phys_frame -= (*m * 60 * 75);
+ *s = phys_frame / 75;
+ *f = phys_frame % 75;
+}
+
+
+// scsicd_exec_command
+//
+// Execute a SCSI command.
+
+static int scsicd_exec_command( SCSIInstance *scsiInstance, UINT8 *statusCode )
+{
+ UINT8 *command;
+ int commandLength;
+ SCSICd *our_this = (SCSICd *)SCSIThis( &SCSIClassCDROM, scsiInstance );
+
+ cdrom_file *cdrom = our_this->cdrom;
+ device_t *cdda;
+ int trk;
+
+ SCSIGetCommand( scsiInstance, &command, &commandLength );
+
+ switch ( command[0] )
+ {
+ case 0x03: // REQUEST SENSE
+ SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
+ return SCSILengthFromUINT8( &command[ 4 ] );
+
+ case 0x12: // INQUIRY
+ logerror("SCSICD: REQUEST SENSE\n");
+ SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
+ return SCSILengthFromUINT8( &command[ 4 ] );
+
+ case 0x15: // MODE SELECT(6)
+ logerror("SCSICD: MODE SELECT(6) length %x control %x\n", command[4], command[5]);
+ SCSISetPhase( scsiInstance, SCSI_PHASE_DATAOUT );
+ return SCSILengthFromUINT8( &command[ 4 ] );
+
+ case 0x1a: // MODE SENSE(6)
+ SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
+ return SCSILengthFromUINT8( &command[ 4 ] );
+
+ case 0x1b: // START STOP UNIT
+ cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
+ if (cdda != NULL)
+ {
+ cdda_stop_audio(cdda);
+ }
+ SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
+ return 0;
+
+ case 0x1e: // PREVENT ALLOW MEDIUM REMOVAL
+ SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
+ return 0;
+
+ case 0x25: // READ CAPACITY
+ SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
+ return 8;
+
+ case 0x28: // READ(10)
+
+ our_this->lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
+ our_this->blocks = SCSILengthFromUINT16( &command[7] );
+
+ logerror("SCSICD: READ(10) at LBA %x for %d blocks (%d bytes)\n", our_this->lba, our_this->blocks, our_this->blocks * our_this->bytes_per_sector);
+
+ if (our_this->num_subblocks > 1)
+ {
+ our_this->cur_subblock = our_this->lba % our_this->num_subblocks;
+ our_this->lba /= our_this->num_subblocks;
+ }
+ else
+ {
+ our_this->cur_subblock = 0;
+ }
+
+ cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
+ if (cdda != NULL)
+ {
+ cdda_stop_audio(cdda);
+ }
+
+ SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
+ return our_this->blocks * our_this->bytes_per_sector;
+
+ case 0x42: // READ SUB-CHANNEL
+// logerror("SCSICD: READ SUB-CHANNEL type %d\n", command[3]);
+ SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
+ return SCSILengthFromUINT16( &command[ 7 ] );
+
+ case 0x43: // READ TOC
+ {
+ int start_trk = command[6];
+ int end_trk = cdrom_get_last_track(cdrom);
+ int length;
+ int allocation_length = SCSILengthFromUINT16( &command[ 7 ] );
+
+ if( start_trk == 0 )
+ {
+ start_trk = 1;
+ }
+ if( start_trk == 0xaa )
+ {
+ end_trk = start_trk;
+ }
+
+ length = 4 + ( 8 * ( ( end_trk - start_trk ) + 1 ) );
+ if( length > allocation_length )
+ {
+ length = allocation_length;
+ }
+ else if( length < 4 )
+ {
+ length = 4;
+ }
+
+ cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
+ if (cdda != NULL)
+ {
+ cdda_stop_audio(cdda);
+ }
+
+ SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
+ return length;
+ }
+ case 0x45: // PLAY AUDIO(10)
+ our_this->lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
+ our_this->blocks = SCSILengthFromUINT16( &command[7] );
+
+ // special cases: lba of 0 means MSF of 00:02:00
+ if (our_this->lba == 0)
+ {
+ our_this->lba = 150;
+ }
+ else if (our_this->lba == 0xffffffff)
+ {
+ logerror("SCSICD: play audio from current not implemented!\n");
+ }
+
+ logerror("SCSICD: PLAY AUDIO(10) at LBA %x for %x blocks\n", our_this->lba, our_this->blocks);
+
+ trk = cdrom_get_track(cdrom, our_this->lba);
+
+ if (cdrom_get_track_type(cdrom, trk) == CD_TRACK_AUDIO)
+ {
+ our_this->play_err_flag = 0;
+ cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
+ if (cdda != NULL)
+ cdda_start_audio(cdda, our_this->lba, our_this->blocks);
+ }
+ else
+ {
+ logerror("SCSICD: track is NOT audio!\n");
+ our_this->play_err_flag = 1;
+ }
+
+ SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
+ return 0;
+
+ case 0x48: // PLAY AUDIO TRACK/INDEX
+ // be careful: tracks here are zero-based, but the SCSI command
+ // uses the real CD track number which is 1-based!
+ our_this->lba = cdrom_get_track_start(cdrom, command[4]-1);
+ our_this->blocks = cdrom_get_track_start(cdrom, command[7]-1) - our_this->lba;
+ if (command[4] > command[7])
+ {
+ our_this->blocks = 0;
+ }
+
+ if (command[4] == command[7])
+ {
+ our_this->blocks = cdrom_get_track_start(cdrom, command[4]) - our_this->lba;
+ }
+
+ if (our_this->blocks && cdrom)
+ {
+ cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
+ if (cdda != NULL)
+ cdda_start_audio(cdda, our_this->lba, our_this->blocks);
+ }
+
+ logerror("SCSICD: PLAY AUDIO T/I: strk %d idx %d etrk %d idx %d frames %d\n", command[4], command[5], command[7], command[8], our_this->blocks);
+ SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
+ return 0;
+
+ case 0x4b: // PAUSE/RESUME
+ if (cdrom)
+ {
+ cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
+ if (cdda != NULL)
+ cdda_pause_audio(cdda, (command[8] & 0x01) ^ 0x01);
+ }
+
+ logerror("SCSICD: PAUSE/RESUME: %s\n", command[8]&1 ? "RESUME" : "PAUSE");
+ SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
+ return 0;
+
+ case 0x55: // MODE SELECT(10)
+ logerror("SCSICD: MODE SELECT length %x control %x\n", command[7]<<8 | command[8], command[1]);
+ SCSISetPhase( scsiInstance, SCSI_PHASE_DATAOUT );
+ return SCSILengthFromUINT16( &command[ 7 ] );
+
+ case 0x5a: // MODE SENSE(10)
+ SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
+ return SCSILengthFromUINT16( &command[ 7 ] );
+
+ case 0xa5: // PLAY AUDIO(12)
+ our_this->lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
+ our_this->blocks = command[6]<<24 | command[7]<<16 | command[8]<<8 | command[9];
+
+ // special cases: lba of 0 means MSF of 00:02:00
+ if (our_this->lba == 0)
+ {
+ our_this->lba = 150;
+ }
+ else if (our_this->lba == 0xffffffff)
+ {
+ logerror("SCSICD: play audio from current not implemented!\n");
+ }
+
+ logerror("SCSICD: PLAY AUDIO(12) at LBA %x for %x blocks\n", our_this->lba, our_this->blocks);
+
+ trk = cdrom_get_track(cdrom, our_this->lba);
+
+ if (cdrom_get_track_type(cdrom, trk) == CD_TRACK_AUDIO)
+ {
+ our_this->play_err_flag = 0;
+ cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
+ if (cdda != NULL)
+ cdda_start_audio(cdda, our_this->lba, our_this->blocks);
+ }
+ else
+ {
+ logerror("SCSICD: track is NOT audio!\n");
+ our_this->play_err_flag = 1;
+ }
+ SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
+ return 0;
+
+ case 0xa8: // READ(12)
+ our_this->lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
+ our_this->blocks = command[7]<<16 | command[8]<<8 | command[9];
+
+ logerror("SCSICD: READ(12) at LBA %x for %x blocks (%x bytes)\n", our_this->lba, our_this->blocks, our_this->blocks * our_this->bytes_per_sector);
+
+ if (our_this->num_subblocks > 1)
+ {
+ our_this->cur_subblock = our_this->lba % our_this->num_subblocks;
+ our_this->lba /= our_this->num_subblocks;
+ }
+ else
+ {
+ our_this->cur_subblock = 0;
+ }
+
+ cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
+ if (cdda != NULL)
+ {
+ cdda_stop_audio(cdda);
+ }
+
+ SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
+ return our_this->blocks * our_this->bytes_per_sector;
+
+ case 0xbb: // SET CD SPEED
+ logerror("SCSICD: SET CD SPEED to %d kbytes/sec.\n", command[2]<<8 | command[3]);
+ SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
+ return 0;
+
+ default:
+ return SCSIBase( &SCSIClassCDROM, SCSIOP_EXEC_COMMAND, scsiInstance, 0, NULL );
+ }
+}
+
+// scsicd_read_data
+//
+// Read data from the device resulting from the execution of a command
+
+static void scsicd_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataLength )
+{
+ UINT8 *command;
+ int commandLength;
+ SCSICd *our_this = (SCSICd *)SCSIThis( &SCSIClassCDROM, scsiInstance );
+
+ int i;
+ UINT32 last_phys_frame;
+ cdrom_file *cdrom = our_this->cdrom;
+ UINT32 temp;
+ UINT8 tmp_buffer[2048];
+ device_t *cdda;
+
+ SCSIGetCommand( scsiInstance, &command, &commandLength );
+
+ switch ( command[0] )
+ {
+ case 0x03: // REQUEST SENSE
+ logerror("SCSICD: Reading REQUEST SENSE data\n");
+
+ memset( data, 0, dataLength );
+
+ data[0] = 0x71; // deferred error
+
+ cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
+ if (cdda != NULL && cdda_audio_active(cdda))
+ {
+ data[12] = 0x00;
+ data[13] = 0x11; // AUDIO PLAY OPERATION IN PROGRESS
+ }
+ else if (our_this->play_err_flag)
+ {
+ our_this->play_err_flag = 0;
+ data[12] = 0x64; // ILLEGAL MODE FOR THIS TRACK
+ data[13] = 0x00;
+ }
+ // (else 00/00 means no error to report)
+ break;
+
+ case 0x12: // INQUIRY
+ memset( data, 0, dataLength );
+ data[0] = 0x05; // device is present, device is CD/DVD (MMC-3)
+ data[1] = 0x80; // media is removable
+ data[2] = 0x05; // device complies with SPC-3 standard
+ data[3] = 0x02; // response data format = SPC-3 standard
+ // some Konami games freak out if this isn't "Sony", so we'll lie
+ // this is the actual drive on my Nagano '98 board
+ strcpy((char *)&data[8], "Sony");
+ strcpy((char *)&data[16], "CDU-76S");
+ strcpy((char *)&data[32], "1.0");
+ break;
+
+ case 0x25: // READ CAPACITY
+ logerror("SCSICD: READ CAPACITY\n");
+
+ temp = cdrom_get_track_start(cdrom, 0xaa);
+ temp--; // return the last used block on the disc
+
+ data[0] = (temp>>24) & 0xff;
+ data[1] = (temp>>16) & 0xff;
+ data[2] = (temp>>8) & 0xff;
+ data[3] = (temp & 0xff);
+ data[4] = 0;
+ data[5] = 0;
+ data[6] = (our_this->bytes_per_sector>>8)&0xff;
+ data[7] = (our_this->bytes_per_sector & 0xff);
+ break;
+
+ case 0x28: // READ(10)
+ case 0xa8: // READ(12)
+ logerror("SCSICD: read %x dataLength, \n", dataLength);
+ if ((our_this->cdrom) && (our_this->blocks))
+ {
+ while (dataLength > 0)
+ {
+ if (!cdrom_read_data(our_this->cdrom, our_this->lba, tmp_buffer, CD_TRACK_MODE1))
+ {
+ logerror("SCSICD: CD read error!\n");
+ }
+
+ logerror("True LBA: %d, buffer half: %d\n", our_this->lba, our_this->cur_subblock * our_this->bytes_per_sector);
+
+ memcpy(data, &tmp_buffer[our_this->cur_subblock * our_this->bytes_per_sector], our_this->bytes_per_sector);
+
+ our_this->cur_subblock++;
+ if (our_this->cur_subblock >= our_this->num_subblocks)
+ {
+ our_this->cur_subblock = 0;
+
+ our_this->lba++;
+ our_this->blocks--;
+ }
+
+ our_this->last_lba = our_this->lba;
+ dataLength -= our_this->bytes_per_sector;
+ data += our_this->bytes_per_sector;
+ }
+ }
+ break;
+
+ case 0x42: // READ SUB-CHANNEL
+ switch (command[3])
+ {
+ case 1: // return current position
+ {
+ int audio_active;
+ int msf;
+
+ if (!cdrom)
+ {
+ return;
+ }
+
+ logerror("SCSICD: READ SUB-CHANNEL Time = %x, SUBQ = %x\n", command[1], command[2]);
+
+ msf = command[1] & 0x2;
+
+ cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
+ audio_active = cdda != NULL && cdda_audio_active(cdda);
+ if (audio_active)
+ {
+ if (cdda_audio_paused(cdda))
+ {
+ data[1] = 0x12; // audio is paused
+ }
+ else
+ {
+ data[1] = 0x11; // audio in progress
+ }
+ }
+ else
+ {
+ if (cdda != NULL && cdda_audio_ended(cdda))
+ {
+ data[1] = 0x13; // ended successfully
+ }
+ else
+ {
+// data[1] = 0x14; // stopped due to error
+ data[1] = 0x15; // No current audio status to return
+ }
+ }
+
+ // if audio is playing, get the latest LBA from the CDROM layer
+ if (audio_active)
+ {
+ our_this->last_lba = cdda_get_audio_lba(cdda);
+ }
+ else
+ {
+ our_this->last_lba = 0;
+ }
+
+ data[2] = 0;
+ data[3] = 12; // data length
+ data[4] = 0x01; // sub-channel format code
+ data[5] = 0x10 | (audio_active ? 0 : 4);
+ data[6] = cdrom_get_track(cdrom, our_this->last_lba) + 1; // track
+ data[7] = 0; // index
+
+ last_phys_frame = our_this->last_lba;
+
+ if (msf)
+ {
+ int m,s,f;
+ phys_frame_to_msf(last_phys_frame, &m, &s, &f);
+ data[8] = 0;
+ data[9] = m;
+ data[10] = s;
+ data[11] = f;
+ }
+ else
+ {
+ data[8] = last_phys_frame>>24;
+ data[9] = (last_phys_frame>>16)&0xff;
+ data[10] = (last_phys_frame>>8)&0xff;
+ data[11] = last_phys_frame&0xff;
+ }
+
+ last_phys_frame -= cdrom_get_track_start(cdrom, data[6] - 1);
+
+ if (msf)
+ {
+ int m,s,f;
+ phys_frame_to_msf(last_phys_frame, &m, &s, &f);
+ data[12] = 0;
+ data[13] = m;
+ data[14] = s;
+ data[15] = f;
+ }
+ else
+ {
+ data[12] = last_phys_frame>>24;
+ data[13] = (last_phys_frame>>16)&0xff;
+ data[14] = (last_phys_frame>>8)&0xff;
+ data[15] = last_phys_frame&0xff;
+ }
+ break;
+ }
+ default:
+ logerror("SCSICD: Unknown subchannel type %d requested\n", command[3]);
+ }
+ break;
+
+ case 0x43: // READ TOC
+ /*
+ Track numbers are problematic here: 0 = lead-in, 0xaa = lead-out.
+ That makes sense in terms of how real-world CDs are referred to, but
+ our internal routines for tracks use "0" as track 1. That probably
+ should be fixed...
+ */
+ logerror("SCSICD: READ TOC, format = %d time=%d\n", command[2]&0xf,(command[1]>>1)&1);
+ switch (command[2] & 0x0f)
+ {
+ case 0: // normal
+ {
+ int start_trk;
+ int end_trk;
+ int len;
+ int in_len;
+ int dptr;
+ UINT32 tstart;
+
+ start_trk = command[6];
+ if( start_trk == 0 )
+ {
+ start_trk = 1;
+ }
+
+ end_trk = cdrom_get_last_track(cdrom);
+ len = (end_trk * 8) + 2;
+
+ // the returned TOC DATA LENGTH must be the full amount,
+ // regardless of how much we're able to pass back due to in_len
+ dptr = 0;
+ data[dptr++] = (len>>8) & 0xff;
+ data[dptr++] = (len & 0xff);
+ data[dptr++] = 1;
+ data[dptr++] = end_trk;
+
+ if( start_trk == 0xaa )
+ {
+ end_trk = 0xaa;
+ }
+
+ in_len = command[7]<<8 | command[8];
+
+ for (i = start_trk; i <= end_trk; i++)
+ {
+ int cdrom_track = i;
+ if( cdrom_track != 0xaa )
+ {
+ cdrom_track--;
+ }
+
+ if( dptr >= in_len )
+ {
+ break;
+ }
+
+ data[dptr++] = 0;
+ data[dptr++] = cdrom_get_adr_control(cdrom, cdrom_track);
+ data[dptr++] = i;
+ data[dptr++] = 0;
+
+ tstart = cdrom_get_track_start(cdrom, cdrom_track);
+ if ((command[1]&2)>>1)
+ tstart = lba_to_msf(tstart);
+ data[dptr++] = (tstart>>24) & 0xff;
+ data[dptr++] = (tstart>>16) & 0xff;
+ data[dptr++] = (tstart>>8) & 0xff;
+ data[dptr++] = (tstart & 0xff);
+ }
+ }
+ break;
+ default:
+ logerror("SCSICD: Unhandled READ TOC format %d\n", command[2]&0xf);
+ break;
+ }
+ break;
+
+ case 0x1a: // MODE SENSE(6)
+ case 0x5a: // MODE SENSE(10)
+ logerror("SCSICD: MODE SENSE page code = %x, PC = %x\n", command[2] & 0x3f, (command[2]&0xc0)>>6);
+
+ switch (command[2] & 0x3f)
+ {
+ case 0xe: // CD Audio control page
+ data[0] = 0x8e; // page E, parameter is savable
+ data[1] = 0x0e; // page length
+ data[2] = 0x04; // IMMED = 1, SOTC = 0
+ data[3] = data[4] = data[5] = data[6] = data[7] = 0; // reserved
+
+ // connect each audio channel to 1 output port
+ data[8] = 1;
+ data[10] = 2;
+ data[12] = 4;
+ data[14] = 8;
+
+ // indicate max volume
+ data[9] = data[11] = data[13] = data[15] = 0xff;
+ break;
+
+ default:
+ logerror("SCSICD: MODE SENSE unknown page %x\n", command[2] & 0x3f);
+ break;
+ }
+ break;
+
+ default:
+ SCSIBase( &SCSIClassCDROM, SCSIOP_READ_DATA, scsiInstance, dataLength, data );
+ break;
+ }
+}
+
+// scsicd_write_data
+//
+// Write data to the CD-ROM device as part of the execution of a command
+
+static void scsicd_write_data( SCSIInstance *scsiInstance, UINT8 *data, int dataLength )
+{
+ UINT8 *command;
+ int commandLength;
+ SCSICd *our_this = (SCSICd *)SCSIThis( &SCSIClassCDROM, scsiInstance );
+ SCSIGetCommand( scsiInstance, &command, &commandLength );
+
+ switch (command[ 0 ])
+ {
+ case 0x15: // MODE SELECT(6)
+ case 0x55: // MODE SELECT(10)
+ logerror("SCSICD: MODE SELECT page %x\n", data[0] & 0x3f);
+
+ switch (data[0] & 0x3f)
+ {
+ case 0x0: // vendor-specific
+ // check for SGI extension to force 512-byte blocks
+ if ((data[3] == 8) && (data[10] == 2))
+ {
+ logerror("SCSICD: Experimental SGI 512-byte block extension enabled\n");
+
+ our_this->bytes_per_sector = 512;
+ our_this->num_subblocks = 4;
+ }
+ else
+ {
+ logerror("SCSICD: Unknown vendor-specific page!\n");
+ }
+ break;
+
+ case 0xe: // audio page
+ logerror("Ch 0 route: %x vol: %x\n", data[8], data[9]);
+ logerror("Ch 1 route: %x vol: %x\n", data[10], data[11]);
+ logerror("Ch 2 route: %x vol: %x\n", data[12], data[13]);
+ logerror("Ch 3 route: %x vol: %x\n", data[14], data[15]);
+ break;
+ }
+ break;
+
+ default:
+ SCSIBase( &SCSIClassCDROM, SCSIOP_WRITE_DATA, scsiInstance, dataLength, data );
+ break;
+ }
+}
+
+static void scsicd_alloc_instance( SCSIInstance *scsiInstance, const char *diskregion )
+{
+ running_machine &machine = scsiInstance->machine();
+ SCSICd *our_this = (SCSICd *)SCSIThis( &SCSIClassCDROM, scsiInstance );
+
+ our_this->lba = 0;
+ our_this->blocks = 0;
+ our_this->last_lba = 0;
+ our_this->bytes_per_sector = 2048;
+ our_this->num_subblocks = 1;
+ our_this->cur_subblock = 0;
+ our_this->play_err_flag = 0;
+
+ state_save_register_item( machine, "scsicd", diskregion, 0, our_this->lba );
+ state_save_register_item( machine, "scsicd", diskregion, 0, our_this->blocks );
+ state_save_register_item( machine, "scsicd", diskregion, 0, our_this->last_lba );
+ state_save_register_item( machine, "scsicd", diskregion, 0, our_this->bytes_per_sector );
+ state_save_register_item( machine, "scsicd", diskregion, 0, our_this->num_subblocks );
+ state_save_register_item( machine, "scsicd", diskregion, 0, our_this->cur_subblock );
+ state_save_register_item( machine, "scsicd", diskregion, 0, our_this->play_err_flag );
+
+ if (machine.device( diskregion )) {
+ our_this->is_file = TRUE;
+ cdrom_image_device *cdrom = machine.device<cdrom_image_device>(diskregion);
+ our_this->cdrom = cdrom->get_cdrom_file();
+ } else {
+ our_this->is_file = FALSE;
+ our_this->cdrom = cdrom_open(get_disk_handle( machine, diskregion ));
+ }
+
+ if (!our_this->cdrom)
+ {
+ logerror("SCSICD: no CD found!\n");
+ }
+}
+
+static void scsicd_delete_instance( SCSIInstance *scsiInstance )
+{
+ SCSICd *our_this = (SCSICd *)SCSIThis( &SCSIClassCDROM, scsiInstance );
+ if (!our_this->is_file) {
+ if( our_this->cdrom )
+ {
+ cdrom_close( our_this->cdrom );
+ }
+ }
+}
+
+static void scsicd_get_device( SCSIInstance *scsiInstance, cdrom_file **cdrom )
+{
+ SCSICd *our_this = (SCSICd *)SCSIThis( &SCSIClassCDROM, scsiInstance );
+ *cdrom = our_this->cdrom;
+}
+
+static void scsicd_set_device( SCSIInstance *scsiInstance, cdrom_file *cdrom )
+{
+ SCSICd *our_this = (SCSICd *)SCSIThis( &SCSIClassCDROM, scsiInstance );
+ our_this->cdrom = cdrom;
+}
+
+static int scsicd_dispatch(int operation, void *file, INT64 intparm, void *ptrparm)
+{
+ SCSIAllocInstanceParams *params;
+
+ switch (operation)
+ {
+ case SCSIOP_EXEC_COMMAND:
+ return scsicd_exec_command( (SCSIInstance *)file, (UINT8 *)ptrparm );
+
+ case SCSIOP_READ_DATA:
+ scsicd_read_data( (SCSIInstance *)file, (UINT8 *)ptrparm, intparm );
+ return 0;
+
+ case SCSIOP_WRITE_DATA:
+ scsicd_write_data( (SCSIInstance *)file, (UINT8 *)ptrparm, intparm );
+ return 0;
+
+ case SCSIOP_ALLOC_INSTANCE:
+ params = (SCSIAllocInstanceParams *)ptrparm;
+ SCSIBase( &SCSIClassCDROM, operation, (SCSIInstance *)file, intparm, (UINT8 *)ptrparm );
+ scsicd_alloc_instance( params->instance, params->diskregion );
+ return 0;
+
+ case SCSIOP_DELETE_INSTANCE:
+ scsicd_delete_instance( (SCSIInstance *)file );
+ break;
+
+ case SCSIOP_GET_DEVICE:
+ scsicd_get_device( (SCSIInstance *)file, (cdrom_file **)ptrparm );
+ return 0;
+
+ case SCSIOP_SET_DEVICE:
+ scsicd_set_device( (SCSIInstance *)file, (cdrom_file *)ptrparm );
+ return 0;
+ }
+
+ return SCSIBase( &SCSIClassCDROM, operation, (SCSIInstance *)file, intparm, (UINT8 *)ptrparm );
+}
+
+const SCSIClass SCSIClassCDROM =
+{
+ &SCSIClassDevice,
+ scsicd_dispatch,
+ sizeof( SCSICd )
+};
diff --git a/trunk/src/emu/machine/scsicd.h b/trunk/src/emu/machine/scsicd.h
new file mode 100644
index 00000000000..67998398631
--- /dev/null
+++ b/trunk/src/emu/machine/scsicd.h
@@ -0,0 +1,17 @@
+/***************************************************************************
+
+ scsicd.h
+
+***************************************************************************/
+
+#ifndef _SCSICD_H_
+#define _SCSICD_H_
+
+#include "machine/scsi.h"
+
+// CD-ROM handler
+extern const SCSIClass SCSIClassCDROM;
+#define SCSI_DEVICE_CDROM &SCSIClassCDROM
+
+#endif
+
diff --git a/trunk/src/emu/machine/scsidev.c b/trunk/src/emu/machine/scsidev.c
new file mode 100644
index 00000000000..c20f8f23ac8
--- /dev/null
+++ b/trunk/src/emu/machine/scsidev.c
@@ -0,0 +1,160 @@
+/***************************************************************************
+
+ scsidev.c - Base class for scsi devices.
+
+***************************************************************************/
+
+#include "emu.h"
+ #include "scsidev.h"
+
+typedef struct
+{
+ UINT8 command[16];
+ int commandLength;
+ int phase;
+} SCSIDev;
+
+static int scsidev_exec_command( SCSIInstance *scsiInstance, UINT8 *statusCode )
+{
+ UINT8 *command;
+ int commandLength;
+// SCSIDev *our_this = (SCSIDev *)SCSIThis( &SCSIClassDevice, scsiInstance );
+ SCSIGetCommand( scsiInstance, &command, &commandLength );
+
+ switch( command[ 0 ] )
+ {
+ case 0x00: // TEST UNIT READY
+ SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
+ return 0;
+
+ default:
+ logerror( "%s: SCSIDEV unknown command %02x\n", scsiInstance->machine().describe_context(), command[ 0 ] );
+ return 0;
+ }
+}
+
+static void scsidev_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataLength )
+{
+ UINT8 *command;
+ int commandLength;
+// SCSIDev *our_this = (SCSIDev *)SCSIThis( &SCSIClassDevice, scsiInstance );
+ SCSIGetCommand( scsiInstance, &command, &commandLength );
+
+ switch( command[ 0 ] )
+ {
+ default:
+ logerror( "%s: SCSIDEV unknown read %02x\n", scsiInstance->machine().describe_context(), command[ 0 ] );
+ break;
+ }
+}
+
+static void scsidev_write_data( SCSIInstance *scsiInstance, UINT8 *data, int dataLength )
+{
+ UINT8 *command;
+ int commandLength;
+// SCSIDev *our_this = (SCSIDev *)SCSIThis( &SCSIClassDevice, scsiInstance );
+ SCSIGetCommand( scsiInstance, &command, &commandLength );
+
+ switch( command[ 0 ] )
+ {
+ default:
+ logerror( "%s: SCSIDEV unknown write %02x\n", scsiInstance->machine().describe_context(), command[ 0 ] );
+ break;
+ }
+}
+
+static void scsidev_set_phase( SCSIInstance *scsiInstance, int phase )
+{
+ SCSIDev *our_this = (SCSIDev *)SCSIThis( &SCSIClassDevice, scsiInstance );
+ our_this->phase = phase;
+}
+
+static int scsidev_get_phase( SCSIInstance *scsiInstance )
+{
+ SCSIDev *our_this = (SCSIDev *)SCSIThis( &SCSIClassDevice, scsiInstance );
+ return our_this->phase;
+}
+
+static void scsidev_set_command( SCSIInstance *scsiInstance, void *command, int commandLength )
+{
+ SCSIDev *our_this = (SCSIDev *)SCSIThis( &SCSIClassDevice, scsiInstance );
+
+ if( commandLength > sizeof( our_this->command ) )
+ {
+ /// TODO: output an error.
+ return;
+ }
+
+ memcpy( our_this->command, command, commandLength );
+ our_this->commandLength = commandLength;
+
+ SCSISetPhase( scsiInstance, SCSI_PHASE_COMMAND );
+}
+
+static int scsidev_get_command( SCSIInstance *scsiInstance, void **command )
+{
+ SCSIDev *our_this = (SCSIDev *)SCSIThis( &SCSIClassDevice, scsiInstance );
+ *command = our_this->command;
+ return our_this->commandLength;
+}
+
+static void scsidev_alloc_instance( SCSIInstance *scsiInstance, const char *diskregion )
+{
+ running_machine &machine = scsiInstance->machine();
+ SCSIDev *our_this = (SCSIDev *)SCSIThis( &SCSIClassDevice, scsiInstance );
+
+ state_save_register_item_array( machine, "scsidev", diskregion, 0, our_this->command );
+ state_save_register_item( machine, "scsidev", diskregion, 0, our_this->commandLength );
+ state_save_register_item( machine, "scsidev", diskregion, 0, our_this->phase );
+}
+
+static int scsidev_dispatch( int operation, void *file, INT64 intparm, void *ptrparm )
+{
+ SCSIAllocInstanceParams *params;
+
+ switch( operation )
+ {
+ case SCSIOP_EXEC_COMMAND:
+ return scsidev_exec_command( (SCSIInstance *)file, (UINT8 *)ptrparm );
+
+ case SCSIOP_READ_DATA:
+ scsidev_read_data( (SCSIInstance *)file, (UINT8 *)ptrparm, intparm );
+ break;
+
+ case SCSIOP_WRITE_DATA:
+ scsidev_write_data( (SCSIInstance *)file, (UINT8 *)ptrparm, intparm );
+ break;
+
+ case SCSIOP_SET_PHASE:
+ scsidev_set_phase( (SCSIInstance *)file, intparm );
+ return 0;
+
+ case SCSIOP_GET_PHASE:
+ return scsidev_get_phase( (SCSIInstance *)file );
+
+ case SCSIOP_SET_COMMAND:
+ scsidev_set_command( (SCSIInstance *)file, (UINT8 *)ptrparm, intparm );
+ return 0;
+
+ case SCSIOP_GET_COMMAND:
+ return scsidev_get_command( (SCSIInstance *)file, (void **)ptrparm );
+
+ case SCSIOP_ALLOC_INSTANCE:
+ params = (SCSIAllocInstanceParams *)ptrparm;
+ params->instance = SCSIMalloc( params->machine(), (const SCSIClass *)file );
+ scsidev_alloc_instance( params->instance, params->diskregion );
+ return 0;
+
+ case SCSIOP_DELETE_INSTANCE:
+ auto_free( ((SCSIInstance *)file)->machine(), file );
+ return 0;
+ }
+ return 0;
+}
+
+const SCSIClass SCSIClassDevice =
+{
+ NULL,
+ scsidev_dispatch,
+ sizeof( SCSIDev )
+};
diff --git a/trunk/src/emu/machine/scsidev.h b/trunk/src/emu/machine/scsidev.h
new file mode 100644
index 00000000000..984ab7f818e
--- /dev/null
+++ b/trunk/src/emu/machine/scsidev.h
@@ -0,0 +1,15 @@
+/***************************************************************************
+
+ scsidev.h
+
+***************************************************************************/
+
+#ifndef _SCSIDEV_H_
+#define _SCSIDEV_H_
+
+#include "machine/scsi.h"
+
+// base handler
+extern const SCSIClass SCSIClassDevice;
+
+#endif
diff --git a/trunk/src/emu/machine/scsihd.c b/trunk/src/emu/machine/scsihd.c
new file mode 100644
index 00000000000..283937dcdd6
--- /dev/null
+++ b/trunk/src/emu/machine/scsihd.c
@@ -0,0 +1,338 @@
+/***************************************************************************
+
+ scsihd.c - Implementation of a SCSI hard disk drive
+
+***************************************************************************/
+
+#include "emu.h"
+#include "scsidev.h"
+#include "harddisk.h"
+#include "imagedev/harddriv.h"
+#include "scsihd.h"
+
+typedef struct
+{
+ UINT32 lba;
+ UINT32 blocks;
+ hard_disk_file *disk;
+ bool is_file;
+} SCSIHd;
+
+
+// scsihd_exec_command
+
+static int scsihd_exec_command( SCSIInstance *scsiInstance, UINT8 *statusCode )
+{
+ UINT8 *command;
+ int commandLength;
+ SCSIHd *our_this = (SCSIHd *)SCSIThis( &SCSIClassHARDDISK, scsiInstance );
+ SCSIGetCommand( scsiInstance, &command, &commandLength );
+
+ switch ( command[0] )
+ {
+ case 0x03: // REQUEST SENSE
+ SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
+ return SCSILengthFromUINT8( &command[ 4 ] );
+
+ case 0x04: // FORMAT UNIT
+ SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
+ return 0;
+
+ case 0x08: // READ(6)
+ our_this->lba = (command[1]&0x1f)<<16 | command[2]<<8 | command[3];
+ our_this->blocks = SCSILengthFromUINT8( &command[4] );
+
+ logerror("SCSIHD: READ at LBA %x for %x blocks\n", our_this->lba, our_this->blocks);
+
+ SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
+ return our_this->blocks * 512;
+
+ case 0x0a: // WRITE(6)
+ our_this->lba = (command[1]&0x1f)<<16 | command[2]<<8 | command[3];
+ our_this->blocks = SCSILengthFromUINT8( &command[4] );
+
+ logerror("SCSIHD: WRITE to LBA %x for %x blocks\n", our_this->lba, our_this->blocks);
+
+ SCSISetPhase( scsiInstance, SCSI_PHASE_DATAOUT );
+ return our_this->blocks * 512;
+
+ case 0x12: // INQUIRY
+ SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
+ return SCSILengthFromUINT8( &command[ 4 ] );
+
+ case 0x15: // MODE SELECT (used to set CDDA volume)
+ logerror("SCSIHD: MODE SELECT length %x control %x\n", command[4], command[5]);
+ SCSISetPhase( scsiInstance, SCSI_PHASE_DATAOUT );
+ return SCSILengthFromUINT8( &command[ 4 ] );
+
+ case 0x1a: // MODE SENSE(6)
+ SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
+ return SCSILengthFromUINT8( &command[ 4 ] );
+
+ case 0x25: // READ CAPACITY
+ SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
+ return 8;
+
+ case 0x28: // READ(10)
+ our_this->lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
+ our_this->blocks = SCSILengthFromUINT16( &command[7] );
+
+ logerror("SCSIHD: READ at LBA %x for %x blocks\n", our_this->lba, our_this->blocks);
+
+ SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
+ return our_this->blocks * 512;
+
+ case 0x2a: // WRITE (10)
+ our_this->lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
+ our_this->blocks = SCSILengthFromUINT16( &command[7] );
+
+ logerror("SCSIHD: WRITE to LBA %x for %x blocks\n", our_this->lba, our_this->blocks);
+
+ SCSISetPhase( scsiInstance, SCSI_PHASE_DATAOUT );
+
+ return our_this->blocks * 512;
+
+ case 0xa8: // READ(12)
+ our_this->lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
+ our_this->blocks = command[6]<<24 | command[7]<<16 | command[8]<<8 | command[9];
+
+ logerror("SCSIHD: READ at LBA %x for %x blocks\n", our_this->lba, our_this->blocks);
+
+ SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
+ return our_this->blocks * 512;
+
+ default:
+ return SCSIBase( &SCSIClassHARDDISK, SCSIOP_EXEC_COMMAND, scsiInstance, 0, NULL );
+ }
+}
+
+static void scsihd_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataLength )
+{
+ int i;
+ UINT8 *command;
+ int commandLength;
+ SCSIHd *our_this = (SCSIHd *)SCSIThis( &SCSIClassHARDDISK, scsiInstance );
+ SCSIGetCommand( scsiInstance, &command, &commandLength );
+
+ // if we're a drive without a disk, return all zeroes
+ if (!our_this->disk)
+ {
+ memset(data, 0, dataLength);
+ return;
+ }
+
+ switch ( command[0] )
+ {
+ case 0x03: // REQUEST SENSE
+ data[0] = 0x80; // valid sense
+ for (i = 1; i < 12; i++)
+ {
+ data[i] = 0;
+ }
+ break;
+
+ case 0x12: // INQUIRY
+ memset( data, 0, dataLength );
+ data[0] = 0x00; // device is direct-access (e.g. hard disk)
+ data[1] = 0x00; // media is not removable
+ data[2] = 0x05; // device complies with SPC-3 standard
+ data[3] = 0x02; // response data format = SPC-3 standard
+ // Apple HD SC setup utility needs to see this
+ strcpy((char *)&data[8], " SEAGATE");
+ strcpy((char *)&data[16], " ST225N");
+ strcpy((char *)&data[32], "1.0");
+ break;
+
+ case 0x1a: // MODE SENSE (6 byte)
+ // special Apple ID page. this is a vendor-specific page,
+ // so unless collisions occur there should be no need
+ // to change it.
+ if ((command[2] & 0x3f) == 0x30)
+ {
+ memset(data, 0, 40);
+ data[0] = 0x14;
+ strcpy((char *)&data[14], "APPLE COMPUTER, INC.");
+ }
+ break;
+
+ case 0x08: // READ(6)
+ case 0x28: // READ(10)
+ case 0xa8: // READ(12)
+ if ((our_this->disk) && (our_this->blocks))
+ {
+ while (dataLength > 0)
+ {
+ if (!hard_disk_read(our_this->disk, our_this->lba, data))
+ {
+ logerror("SCSIHD: HD read error!\n");
+ }
+ our_this->lba++;
+ our_this->blocks--;
+ dataLength -= 512;
+ data += 512;
+ }
+ }
+ break;
+
+
+ case 0x25: // READ CAPACITY
+ {
+ hard_disk_info *info;
+ UINT32 temp;
+
+ info = hard_disk_get_info(our_this->disk);
+
+ logerror("SCSIHD: READ CAPACITY\n");
+
+ // get # of sectors
+ temp = info->cylinders * info->heads * info->sectors;
+ temp--;
+
+ data[0] = (temp>>24) & 0xff;
+ data[1] = (temp>>16) & 0xff;
+ data[2] = (temp>>8) & 0xff;
+ data[3] = (temp & 0xff);
+ data[4] = (info->sectorbytes>>24)&0xff;
+ data[5] = (info->sectorbytes>>16)&0xff;
+ data[6] = (info->sectorbytes>>8)&0xff;
+ data[7] = (info->sectorbytes & 0xff);
+ }
+ break;
+
+ default:
+ SCSIBase( &SCSIClassHARDDISK, SCSIOP_READ_DATA, scsiInstance, dataLength, data );
+ break;
+ }
+}
+
+static void scsihd_write_data( SCSIInstance *scsiInstance, UINT8 *data, int dataLength )
+{
+ UINT8 *command;
+ int commandLength;
+ SCSIHd *our_this = (SCSIHd *)SCSIThis( &SCSIClassHARDDISK, scsiInstance );
+ SCSIGetCommand( scsiInstance, &command, &commandLength );
+
+ if (!our_this->disk)
+ {
+ return;
+ }
+
+ switch ( command[0] )
+ {
+ case 0x0a: // WRITE(6)
+ case 0x2a: // WRITE(10)
+ if ((our_this->disk) && (our_this->blocks))
+ {
+ while (dataLength > 0)
+ {
+ if (!hard_disk_write(our_this->disk, our_this->lba, data))
+ {
+ logerror("SCSIHD: HD write error!\n");
+ }
+ our_this->lba++;
+ our_this->blocks--;
+ dataLength -= 512;
+ data += 512;
+ }
+ }
+ break;
+
+ default:
+ SCSIBase( &SCSIClassHARDDISK, SCSIOP_WRITE_DATA, scsiInstance, dataLength, data );
+ break;
+ }
+}
+
+static void scsihd_alloc_instance( SCSIInstance *scsiInstance, const char *diskregion )
+{
+ running_machine &machine = scsiInstance->machine();
+ SCSIHd *our_this = (SCSIHd *)SCSIThis( &SCSIClassHARDDISK, scsiInstance );
+
+ our_this->lba = 0;
+ our_this->blocks = 0;
+
+ state_save_register_item( machine, "scsihd", diskregion, 0, our_this->lba );
+ state_save_register_item( machine, "scsihd", diskregion, 0, our_this->blocks );
+
+ if (machine.device( diskregion )) {
+ our_this->is_file = TRUE;
+ our_this->disk = machine.device<harddisk_image_device>(diskregion)->get_hard_disk_file();
+ } else {
+ our_this->is_file = FALSE;
+ our_this->disk = hard_disk_open(get_disk_handle( machine, diskregion ));
+ }
+
+ if (!our_this->disk)
+ {
+ logerror("SCSIHD: no HD found!\n");
+ }
+}
+
+static void scsihd_delete_instance( SCSIInstance *scsiInstance )
+{
+ SCSIHd *our_this = (SCSIHd *)SCSIThis( &SCSIClassHARDDISK, scsiInstance );
+ if (!our_this->is_file) {
+ if( our_this->disk )
+ {
+ hard_disk_close( our_this->disk );
+ }
+ }
+}
+
+static void scsihd_get_device( SCSIInstance *scsiInstance, hard_disk_file **disk )
+{
+ SCSIHd *our_this = (SCSIHd *)SCSIThis( &SCSIClassHARDDISK, scsiInstance );
+ *disk = our_this->disk;
+}
+
+static void scsihd_set_device( SCSIInstance *scsiInstance, hard_disk_file *disk )
+{
+ SCSIHd *our_this = (SCSIHd *)SCSIThis( &SCSIClassHARDDISK, scsiInstance );
+ our_this->disk = disk;
+}
+
+static int scsihd_dispatch(int operation, void *file, INT64 intparm, void *ptrparm)
+{
+ SCSIAllocInstanceParams *params;
+
+ switch (operation)
+ {
+ case SCSIOP_EXEC_COMMAND:
+ return scsihd_exec_command( (SCSIInstance *)file, (UINT8 *)ptrparm );
+
+ case SCSIOP_READ_DATA:
+ scsihd_read_data( (SCSIInstance *)file, (UINT8 *)ptrparm, intparm );
+ return 0;
+
+ case SCSIOP_WRITE_DATA:
+ scsihd_write_data( (SCSIInstance *)file, (UINT8 *)ptrparm, intparm );
+ return 0;
+
+ case SCSIOP_ALLOC_INSTANCE:
+ params = (SCSIAllocInstanceParams *)ptrparm;
+ SCSIBase( &SCSIClassHARDDISK, operation, (SCSIInstance *)file, intparm, (UINT8 *)ptrparm );
+ scsihd_alloc_instance( params->instance, params->diskregion );
+ return 0;
+
+ case SCSIOP_DELETE_INSTANCE:
+ scsihd_delete_instance( (SCSIInstance *)file );
+ break;
+
+ case SCSIOP_GET_DEVICE:
+ scsihd_get_device( (SCSIInstance *)file, (hard_disk_file **)ptrparm );
+ return 0;
+
+ case SCSIOP_SET_DEVICE:
+ scsihd_set_device( (SCSIInstance *)file, (hard_disk_file *)ptrparm );
+ return 0;
+ }
+
+ return SCSIBase( &SCSIClassHARDDISK, operation, (SCSIInstance *)file, intparm, (UINT8 *)ptrparm );
+}
+
+const SCSIClass SCSIClassHARDDISK =
+{
+ &SCSIClassDevice,
+ scsihd_dispatch,
+ sizeof( SCSIHd )
+};
diff --git a/trunk/src/emu/machine/scsihd.h b/trunk/src/emu/machine/scsihd.h
new file mode 100644
index 00000000000..f4549926655
--- /dev/null
+++ b/trunk/src/emu/machine/scsihd.h
@@ -0,0 +1,16 @@
+/***************************************************************************
+
+ scsihd.h
+
+***************************************************************************/
+
+#ifndef _SCSIHD_H_
+#define _SCSIHD_H_
+
+#include "machine/scsi.h"
+
+// CD-ROM handler
+extern const SCSIClass SCSIClassHARDDISK;
+#define SCSI_DEVICE_HARDDISK &SCSIClassHARDDISK
+
+#endif
diff --git a/trunk/src/emu/machine/secflash.c b/trunk/src/emu/machine/secflash.c
new file mode 100644
index 00000000000..0744d86660b
--- /dev/null
+++ b/trunk/src/emu/machine/secflash.c
@@ -0,0 +1,74 @@
+#include "emu.h"
+#include "machine/secflash.h"
+
+device_secure_serial_flash::device_secure_serial_flash(const machine_config &mconfig,
+ device_type type,
+ const char *name, const char *tag,
+ device_t *owner, UINT32 clock) :
+ device_t(mconfig, type, name, tag, owner, clock),
+ device_nvram_interface(mconfig, *this)
+{
+}
+
+void device_secure_serial_flash::device_start()
+{
+ save_item(NAME(cs));
+ save_item(NAME(rst));
+ save_item(NAME(scl));
+ save_item(NAME(sdaw));
+ save_item(NAME(sdar));
+}
+
+void device_secure_serial_flash::device_reset()
+{
+ cs = rst = scl = sdaw = sdar = false;
+}
+
+void device_secure_serial_flash::cs_w(bool _cs)
+{
+ if(cs == _cs)
+ return;
+ cs = _cs;
+ if(cs)
+ cs_1();
+ else
+ cs_0();
+}
+
+void device_secure_serial_flash::rst_w(bool _rst)
+{
+ if(rst == _rst)
+ return;
+ rst = _rst;
+ if(rst)
+ rst_1();
+ else
+ rst_0();
+}
+
+void device_secure_serial_flash::scl_w(bool _scl)
+{
+ if(scl == _scl)
+ return;
+ scl = _scl;
+ if(scl)
+ scl_1();
+ else
+ scl_0();
+}
+
+void device_secure_serial_flash::sda_w(bool _sda)
+{
+ if(sdaw == _sda)
+ return;
+ sdaw = _sda;
+ if(sdaw)
+ sda_1();
+ else
+ sda_0();
+}
+
+bool device_secure_serial_flash::sda_r()
+{
+ return cs ? true : sdar;
+}
diff --git a/trunk/src/emu/machine/secflash.h b/trunk/src/emu/machine/secflash.h
new file mode 100644
index 00000000000..907238a2bd1
--- /dev/null
+++ b/trunk/src/emu/machine/secflash.h
@@ -0,0 +1,35 @@
+// Common interface for all secure serial flashes
+
+#ifndef __SECFLASH_H__
+#define __SECFLASH_H__
+
+#include "emu.h"
+
+class device_secure_serial_flash : public device_t,
+ public device_nvram_interface
+{
+public:
+ void cs_w(bool cs);
+ void rst_w(bool rst);
+ void scl_w(bool scl);
+ void sda_w(bool sda);
+ bool sda_r();
+
+protected:
+ bool cs, rst, scl, sdaw, sdar;
+
+ virtual void cs_0() = 0;
+ virtual void cs_1() = 0;
+ virtual void rst_0() = 0;
+ virtual void rst_1() = 0;
+ virtual void scl_0() = 0;
+ virtual void scl_1() = 0;
+ virtual void sda_0() = 0;
+ virtual void sda_1() = 0;
+
+ device_secure_serial_flash(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
+ virtual void device_start();
+ virtual void device_reset();
+};
+
+#endif
diff --git a/trunk/src/emu/machine/smc91c9x.c b/trunk/src/emu/machine/smc91c9x.c
new file mode 100644
index 00000000000..3c9670ae52a
--- /dev/null
+++ b/trunk/src/emu/machine/smc91c9x.c
@@ -0,0 +1,637 @@
+/*************************************************************************
+
+ SMC91C9X ethernet controller implementation
+
+ by Aaron Giles
+
+***************************************************************************
+
+ Notes:
+ * only loopback mode really works
+
+**************************************************************************/
+
+#include "emu.h"
+#include "smc91c9x.h"
+
+
+
+/***************************************************************************
+ DEBUGGING
+***************************************************************************/
+
+#define LOG_ETHERNET (0)
+#define DISPLAY_STATS (0)
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define ETHER_BUFFER_SIZE (2048)
+#define ETHER_RX_BUFFERS (4)
+
+/* Ethernet registers - bank 0 */
+#define EREG_TCR (0*8 + 0)
+#define EREG_EPH_STATUS (0*8 + 1)
+#define EREG_RCR (0*8 + 2)
+#define EREG_COUNTER (0*8 + 3)
+#define EREG_MIR (0*8 + 4)
+#define EREG_MCR (0*8 + 5)
+#define EREG_BANK (0*8 + 7)
+
+/* Ethernet registers - bank 1 */
+#define EREG_CONFIG (1*8 + 0)
+#define EREG_BASE (1*8 + 1)
+#define EREG_IA0_1 (1*8 + 2)
+#define EREG_IA2_3 (1*8 + 3)
+#define EREG_IA4_5 (1*8 + 4)
+#define EREG_GENERAL_PURP (1*8 + 5)
+#define EREG_CONTROL (1*8 + 6)
+
+/* Ethernet registers - bank 2 */
+#define EREG_MMU_COMMAND (2*8 + 0)
+#define EREG_PNR_ARR (2*8 + 1)
+#define EREG_FIFO_PORTS (2*8 + 2)
+#define EREG_POINTER (2*8 + 3)
+#define EREG_DATA_0 (2*8 + 4)
+#define EREG_DATA_1 (2*8 + 5)
+#define EREG_INTERRUPT (2*8 + 6)
+
+/* Ethernet registers - bank 3 */
+#define EREG_MT0_1 (3*8 + 0)
+#define EREG_MT2_3 (3*8 + 1)
+#define EREG_MT4_5 (3*8 + 2)
+#define EREG_MT6_7 (3*8 + 3)
+#define EREG_MGMT (3*8 + 4)
+#define EREG_REVISION (3*8 + 5)
+#define EREG_ERCV (3*8 + 6)
+
+/* Ethernet MMU commands */
+#define ECMD_NOP 0
+#define ECMD_ALLOCATE 1
+#define ECMD_RESET_MMU 2
+#define ECMD_REMOVE 3
+#define ECMD_REMOVE_RELEASE 4
+#define ECMD_RELEASE_PACKET 5
+#define ECMD_ENQUEUE_PACKET 6
+#define ECMD_RESET_FIFOS 7
+
+/* Ethernet interrupt bits */
+#define EINT_RCV 0x01
+#define EINT_TX 0x02
+#define EINT_TX_EMPTY 0x04
+#define EINT_ALLOC 0x08
+#define EINT_RX_OVRN 0x10
+#define EINT_EPH 0x20
+#define EINT_ERCV 0x40
+
+/* Ethernet register names */
+static const char *const ethernet_regname[64] =
+{
+ "TCR", "EPH STATUS", "RCR", "COUNTER", "MIR", "MCR", "(0.6)", "BANK",
+ "CONFIG", "BASE", "IA0-1", "IA2-3", "IA4-5", "GENERAL PURPOSE", "CONTROL", "BANK",
+ "MMU COMMAND", "PNR ARR", "FIFO PORTS", "POINTER", "DATA", "DATA", "INTERRUPT", "BANK",
+ "MT0-1", "MT2-3", "MT4-5", "MT6-7", "MGMT", "REVISION", "ERCV", "BANK",
+ "(4.0)", "(4.1)", "(4.2)", "(4.3)", "(4.4)", "(4.5)", "(4.6)", "BANK",
+ "(5.0)", "(5.1)", "(5.2)", "(5.3)", "(5.4)", "(5.5)", "(5.6)", "BANK",
+ "(6.0)", "(6.1)", "(6.2)", "(6.3)", "(6.4)", "(6.5)", "(6.6)", "BANK",
+ "(7.0)", "(7.1)", "(7.2)", "(7.3)", "(7.4)", "(7.5)", "(7.6)", "BANK"
+};
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _smc91c9x_state smc91c9x_state;
+struct _smc91c9x_state
+{
+ device_t *device;
+ smc91c9x_irq_func irq_handler;
+
+ /* raw register data and masks */
+ UINT16 reg[64];
+ UINT16 regmask[64];
+
+ /* IRQ information */
+ UINT8 irq_state;
+
+ /* allocate information */
+ UINT8 alloc_count;
+
+ /* transmit/receive FIFOs */
+ UINT8 fifo_count;
+ UINT8 rx[ETHER_BUFFER_SIZE * ETHER_RX_BUFFERS];
+ UINT8 tx[ETHER_BUFFER_SIZE];
+
+ /* counters */
+ UINT32 sent;
+ UINT32 recd;
+};
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void update_ethernet_irq(smc91c9x_state *smc);
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ get_safe_token - makes sure that the passed
+ in device is, in fact, an IDE controller
+-------------------------------------------------*/
+
+INLINE smc91c9x_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == SMC91C94 || device->type() == SMC91C96);
+
+ return (smc91c9x_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+
+/***************************************************************************
+ INTERNAL HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ update_ethernet_irq - update the IRQ state
+-------------------------------------------------*/
+
+static void update_ethernet_irq(smc91c9x_state *smc)
+{
+ UINT8 mask = smc->reg[EREG_INTERRUPT] >> 8;
+ UINT8 state = smc->reg[EREG_INTERRUPT] & 0xff;
+
+ /* update the IRQ state */
+ smc->irq_state = ((mask & state) != 0);
+ if (smc->irq_handler != NULL)
+ (*smc->irq_handler)(smc->device, smc->irq_state ? ASSERT_LINE : CLEAR_LINE);
+}
+
+
+/*-------------------------------------------------
+ update_stats - draw statistics
+-------------------------------------------------*/
+
+static void update_stats(smc91c9x_state *smc)
+{
+ if (DISPLAY_STATS)
+ popmessage("Sent:%d Rec'd:%d", smc->sent, smc->recd);
+}
+
+
+/*-------------------------------------------------
+ finish_enqueue - complete an enqueued packet
+-------------------------------------------------*/
+
+static void finish_enqueue(smc91c9x_state *smc, int param)
+{
+ int is_broadcast = (smc->tx[4] == 0xff && smc->tx[5] == 0xff && smc->tx[6] == 0xff &&
+ smc->tx[7] == 0xff && smc->tx[8] == 0xff && smc->tx[9] == 0xff);
+
+ /* update the EPH register and stuff it in the first transmit word */
+ smc->reg[EREG_EPH_STATUS] = 0x0001;
+ if (is_broadcast)
+ smc->reg[EREG_EPH_STATUS] |= 0x0040;
+ smc->tx[0] = smc->reg[EREG_EPH_STATUS];
+ smc->tx[1] = smc->reg[EREG_EPH_STATUS] >> 8;
+
+ /* signal a transmit interrupt and mark the transmit buffer empty */
+ smc->reg[EREG_INTERRUPT] |= EINT_TX;
+ smc->reg[EREG_INTERRUPT] |= EINT_TX_EMPTY;
+ smc->reg[EREG_FIFO_PORTS] |= 0x0080;
+ smc->sent++;
+ update_stats(smc);
+
+ /* loopback? */
+ if (smc->reg[EREG_TCR] & 0x2002)
+ if (smc->fifo_count < ETHER_RX_BUFFERS)
+ {
+ int buffer_len = ((smc->tx[3] << 8) | smc->tx[2]) & 0x7ff;
+ UINT8 *packet = &smc->rx[smc->fifo_count++ * ETHER_BUFFER_SIZE];
+ int packet_len;
+
+ /* compute the packet length */
+ packet_len = buffer_len - 6;
+ if (packet[buffer_len - 1] & 0x20)
+ packet_len++;
+
+ /* build up the packet */
+ packet[0] = 0x0000;
+ packet[1] = 0x0000;
+ packet[2] = buffer_len;
+ packet[3] = buffer_len >> 8;
+ memcpy(&packet[4], &smc->tx[4], 6);
+ memcpy(&packet[10], &smc->tx[10], 6);
+ memcpy(&packet[16], &smc->tx[16], buffer_len - 16);
+
+ /* set the broadcast flag */
+ if (is_broadcast)
+ packet[1] |= 0x40;
+
+ /* pad? */
+ if (smc->reg[EREG_TCR & 0x0080])
+ if (packet_len < 64)
+ {
+ memset(&packet[buffer_len], 0, 64+6 - buffer_len);
+ packet[buffer_len - 1] = 0;
+ buffer_len = 64+6;
+ packet[2] = buffer_len;
+ packet[3] = buffer_len >> 8;
+ }
+
+ /* signal a receive */
+ smc->reg[EREG_INTERRUPT] |= EINT_RCV;
+ smc->reg[EREG_FIFO_PORTS] &= ~0x8000;
+ }
+ update_ethernet_irq(smc);
+}
+
+
+/*-------------------------------------------------
+ process_command - handle MMU commands
+-------------------------------------------------*/
+
+static void process_command(smc91c9x_state *smc, UINT16 data)
+{
+ switch ((data >> 5) & 7)
+ {
+ case ECMD_NOP:
+ if (LOG_ETHERNET)
+ logerror(" NOP\n");
+ break;
+
+ case ECMD_ALLOCATE:
+ if (LOG_ETHERNET)
+ logerror(" ALLOCATE MEMORY FOR TX (%d)\n", (data & 7));
+ smc->reg[EREG_PNR_ARR] &= ~0xff00;
+ smc->reg[EREG_PNR_ARR] |= smc->alloc_count++ << 8;
+ smc->reg[EREG_INTERRUPT] |= 0x0008;
+ update_ethernet_irq(smc);
+ break;
+
+ case ECMD_RESET_MMU:
+ if (LOG_ETHERNET)
+ logerror(" RESET MMU\n");
+ break;
+
+ case ECMD_REMOVE:
+ if (LOG_ETHERNET)
+ logerror(" REMOVE FRAME FROM RX FIFO\n");
+ break;
+
+ case ECMD_REMOVE_RELEASE:
+ if (LOG_ETHERNET)
+ logerror(" REMOVE AND RELEASE FRAME FROM RX FIFO\n");
+ smc->reg[EREG_INTERRUPT] &= ~EINT_RCV;
+ if (smc->fifo_count > 0)
+ smc->fifo_count--;
+ if (smc->fifo_count > 0)
+ {
+ memmove(&smc->rx[0], &smc->rx[ETHER_BUFFER_SIZE], smc->fifo_count * ETHER_BUFFER_SIZE);
+ smc->reg[EREG_INTERRUPT] |= EINT_RCV;
+ smc->reg[EREG_FIFO_PORTS] &= ~0x8000;
+ }
+ else
+ smc->reg[EREG_FIFO_PORTS] |= 0x8000;
+ update_ethernet_irq(smc);
+ smc->recd++;
+ update_stats(smc);
+ break;
+
+ case ECMD_RELEASE_PACKET:
+ if (LOG_ETHERNET)
+ logerror(" RELEASE SPECIFIC PACKET\n");
+ break;
+
+ case ECMD_ENQUEUE_PACKET:
+ if (LOG_ETHERNET)
+ logerror(" ENQUEUE TX PACKET\n");
+ finish_enqueue(smc, 0);
+ break;
+
+ case ECMD_RESET_FIFOS:
+ if (LOG_ETHERNET)
+ logerror(" RESET TX FIFOS\n");
+ break;
+ }
+ smc->reg[EREG_MMU_COMMAND] &= ~0x0001;
+}
+
+
+
+/***************************************************************************
+ CORE READ/WRITE HANDLERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ smc91c9x_r - handle a read from the device
+-------------------------------------------------*/
+
+READ16_DEVICE_HANDLER( smc91c9x_r )
+{
+ smc91c9x_state *smc = get_safe_token(device);
+ UINT32 result = ~0;
+
+ /* determine the effective register */
+ offset %= 8;
+ if (offset != EREG_BANK)
+ offset += 8 * (smc->reg[EREG_BANK] & 7);
+ result = smc->reg[offset];
+
+ switch (offset)
+ {
+ case EREG_PNR_ARR:
+ if (ACCESSING_BITS_8_15)
+ {
+ smc->reg[EREG_INTERRUPT] &= ~0x0008;
+ update_ethernet_irq(smc);
+ }
+ break;
+
+ case EREG_DATA_0: /* data register */
+ case EREG_DATA_1: /* data register */
+ {
+ UINT8 *buffer = (smc->reg[EREG_POINTER] & 0x8000) ? smc->rx : smc->tx;
+ int addr = smc->reg[EREG_POINTER] & 0x7ff;
+ result = buffer[addr++];
+ if (ACCESSING_BITS_8_15)
+ result |= buffer[addr++] << 8;
+ if (smc->reg[EREG_POINTER] & 0x4000)
+ smc->reg[EREG_POINTER] = (smc->reg[EREG_POINTER] & ~0x7ff) | (addr & 0x7ff);
+ break;
+ }
+ }
+
+ if (LOG_ETHERNET && offset != EREG_BANK)
+ logerror("%s:smc91c9x_r(%s) = %04X & %04X\n", device->machine().describe_context(), ethernet_regname[offset], result, mem_mask);
+ return result;
+}
+
+
+/*-------------------------------------------------
+ smc91c9x_w - handle a write to the device
+-------------------------------------------------*/
+
+WRITE16_DEVICE_HANDLER( smc91c9x_w )
+{
+ smc91c9x_state *smc = get_safe_token(device);
+// UINT16 olddata;
+
+ /* determine the effective register */
+ offset %= 8;
+ if (offset != EREG_BANK)
+ offset += 8 * (smc->reg[EREG_BANK] & 7);
+
+ /* update the data generically */
+// olddata = smc->reg[offset];
+ mem_mask &= smc->regmask[offset];
+ COMBINE_DATA(&smc->reg[offset]);
+
+ if (LOG_ETHERNET && offset != 7)
+ logerror("%s:smc91c9x_w(%s) = %04X & %04X\n", device->machine().describe_context(), ethernet_regname[offset], data, mem_mask);
+
+ /* handle it */
+ switch (offset)
+ {
+ case EREG_TCR: /* transmit control register */
+ if (LOG_ETHERNET)
+ {
+ if (data & 0x2000) logerror(" EPH LOOP\n");
+ if (data & 0x1000) logerror(" STP SQET\n");
+ if (data & 0x0800) logerror(" FDUPLX\n");
+ if (data & 0x0400) logerror(" MON_CSN\n");
+ if (data & 0x0100) logerror(" NOCRC\n");
+ if (data & 0x0080) logerror(" PAD_EN\n");
+ if (data & 0x0004) logerror(" FORCOL\n");
+ if (data & 0x0002) logerror(" LOOP\n");
+ if (data & 0x0001) logerror(" TXENA\n");
+ }
+ break;
+
+ case EREG_RCR: /* receive control register */
+ if (LOG_ETHERNET)
+ {
+ if (data & 0x8000) device->reset();
+ if (data & 0x8000) logerror(" SOFT RST\n");
+ if (data & 0x4000) logerror(" FILT_CAR\n");
+ if (data & 0x0200) logerror(" STRIP CRC\n");
+ if (data & 0x0100) logerror(" RXEN\n");
+ if (data & 0x0004) logerror(" ALMUL\n");
+ if (data & 0x0002) logerror(" PRMS\n");
+ if (data & 0x0001) logerror(" RX_ABORT\n");
+ }
+ break;
+
+ case EREG_CONFIG: /* configuration register */
+ if (LOG_ETHERNET)
+ {
+ if (data & 0x1000) logerror(" NO WAIT\n");
+ if (data & 0x0400) logerror(" FULL STEP\n");
+ if (data & 0x0200) logerror(" SET SQLCH\n");
+ if (data & 0x0100) logerror(" AUI SELECT\n");
+ if (data & 0x0080) logerror(" 16 BIT\n");
+ if (data & 0x0040) logerror(" DIS LINK\n");
+ if (data & 0x0004) logerror(" INT SEL1\n");
+ if (data & 0x0002) logerror(" INT SEL0\n");
+ }
+ break;
+
+ case EREG_BASE: /* base address register */
+ if (LOG_ETHERNET)
+ {
+ logerror(" base = $%04X\n", (data & 0xe000) | ((data & 0x1f00) >> 3));
+ logerror(" romsize = %d\n", ((data & 0xc0) >> 6));
+ logerror(" romaddr = $%05X\n", ((data & 0x3e) << 13));
+ }
+ break;
+
+ case EREG_CONTROL: /* control register */
+ if (LOG_ETHERNET)
+ {
+ if (data & 0x4000) logerror(" RCV_BAD\n");
+ if (data & 0x2000) logerror(" PWRDN\n");
+ if (data & 0x0800) logerror(" AUTO RELEASE\n");
+ if (data & 0x0080) logerror(" LE ENABLE\n");
+ if (data & 0x0040) logerror(" CR ENABLE\n");
+ if (data & 0x0020) logerror(" TE ENABLE\n");
+ if (data & 0x0004) logerror(" EEPROM SELECT\n");
+ if (data & 0x0002) logerror(" RELOAD\n");
+ if (data & 0x0001) logerror(" STORE\n");
+ }
+ break;
+
+ case EREG_MMU_COMMAND: /* command register */
+ process_command(smc, data);
+ break;
+
+ case EREG_DATA_0: /* data register */
+ case EREG_DATA_1: /* data register */
+ {
+ UINT8 *buffer = (smc->reg[EREG_POINTER] & 0x8000) ? smc->rx : smc->tx;
+ int addr = smc->reg[EREG_POINTER] & 0x7ff;
+ buffer[addr++] = data;
+ if (ACCESSING_BITS_8_15)
+ buffer[addr++] = data >> 8;
+ if (smc->reg[EREG_POINTER] & 0x4000)
+ smc->reg[EREG_POINTER] = (smc->reg[EREG_POINTER] & ~0x7ff) | (addr & 0x7ff);
+ break;
+ }
+
+ case EREG_INTERRUPT:
+ smc->reg[EREG_INTERRUPT] &= ~(data & 0x56);
+ update_ethernet_irq(smc);
+ break;
+ }
+}
+
+
+
+/***************************************************************************
+ DEVICE INTERFACE
+***************************************************************************/
+
+/*-------------------------------------------------
+ device start callback
+-------------------------------------------------*/
+
+static DEVICE_START( smc91c9x )
+{
+ const smc91c9x_config *config = (const smc91c9x_config *)downcast<const legacy_device_base *>(device)->inline_config();
+ smc91c9x_state *smc = get_safe_token(device);
+
+ /* validate some basic stuff */
+ assert(device != NULL);
+ assert(device->static_config() == NULL);
+ assert(downcast<const legacy_device_base *>(device)->inline_config() != NULL);
+
+ /* store a pointer back to the device */
+ smc->device = device;
+ smc->irq_handler = config->interrupt;
+
+ /* register ide states */
+ device->save_item(NAME(smc->reg));
+ device->save_item(NAME(smc->regmask));
+ device->save_item(NAME(smc->irq_state));
+ device->save_item(NAME(smc->alloc_count));
+ device->save_item(NAME(smc->fifo_count));
+ device->save_item(NAME(smc->rx));
+ device->save_item(NAME(smc->tx));
+ device->save_item(NAME(smc->sent));
+ device->save_item(NAME(smc->recd));
+}
+
+
+/*-------------------------------------------------
+ device reset callback
+-------------------------------------------------*/
+
+static DEVICE_RESET( smc91c9x )
+{
+ smc91c9x_state *smc = get_safe_token(device);
+
+ memset(smc->reg, 0, sizeof(smc->reg));
+ memset(smc->regmask, 0, sizeof(smc->regmask));
+ smc->irq_state = 0;
+ smc->alloc_count = 0;
+ smc->fifo_count = 0;
+ smc->sent = 0;
+ smc->recd = 0;
+
+ smc->reg[EREG_TCR] = 0x0000; smc->regmask[EREG_TCR] = 0x3d87;
+ smc->reg[EREG_EPH_STATUS] = 0x0000; smc->regmask[EREG_EPH_STATUS] = 0x0000;
+ smc->reg[EREG_RCR] = 0x0000; smc->regmask[EREG_RCR] = 0xc307;
+ smc->reg[EREG_COUNTER] = 0x0000; smc->regmask[EREG_COUNTER] = 0x0000;
+ smc->reg[EREG_MIR] = 0x1212; smc->regmask[EREG_MIR] = 0x0000;
+ smc->reg[EREG_MCR] = 0x3300; smc->regmask[EREG_MCR] = 0x00ff;
+ smc->reg[EREG_BANK] = 0x3300; smc->regmask[EREG_BANK] = 0x0007;
+
+ smc->reg[EREG_CONFIG] = 0x0030; smc->regmask[EREG_CONFIG] = 0x17c6;
+ smc->reg[EREG_BASE] = 0x1866; smc->regmask[EREG_BASE] = 0xfffe;
+ smc->reg[EREG_IA0_1] = 0x0000; smc->regmask[EREG_IA0_1] = 0xffff;
+ smc->reg[EREG_IA2_3] = 0x0000; smc->regmask[EREG_IA2_3] = 0xffff;
+ smc->reg[EREG_IA4_5] = 0x0000; smc->regmask[EREG_IA4_5] = 0xffff;
+ smc->reg[EREG_GENERAL_PURP] = 0x0000; smc->regmask[EREG_GENERAL_PURP] = 0xffff;
+ smc->reg[EREG_CONTROL] = 0x0100; smc->regmask[EREG_CONTROL] = 0x68e7;
+
+ smc->reg[EREG_MMU_COMMAND] = 0x0000; smc->regmask[EREG_MMU_COMMAND] = 0x00e7;
+ smc->reg[EREG_PNR_ARR] = 0x8000; smc->regmask[EREG_PNR_ARR] = 0x00ff;
+ smc->reg[EREG_FIFO_PORTS] = 0x8080; smc->regmask[EREG_FIFO_PORTS] = 0x0000;
+ smc->reg[EREG_POINTER] = 0x0000; smc->regmask[EREG_POINTER] = 0xf7ff;
+ smc->reg[EREG_DATA_0] = 0x0000; smc->regmask[EREG_DATA_0] = 0xffff;
+ smc->reg[EREG_DATA_1] = 0x0000; smc->regmask[EREG_DATA_1] = 0xffff;
+ smc->reg[EREG_INTERRUPT] = 0x0004; smc->regmask[EREG_INTERRUPT] = 0x7f00;
+
+ smc->reg[EREG_MT0_1] = 0x0000; smc->regmask[EREG_MT0_1] = 0xffff;
+ smc->reg[EREG_MT2_3] = 0x0000; smc->regmask[EREG_MT2_3] = 0xffff;
+ smc->reg[EREG_MT4_5] = 0x0000; smc->regmask[EREG_MT4_5] = 0xffff;
+ smc->reg[EREG_MT6_7] = 0x0000; smc->regmask[EREG_MT6_7] = 0xffff;
+ smc->reg[EREG_MGMT] = 0x3030; smc->regmask[EREG_MGMT] = 0x0f0f;
+ smc->reg[EREG_REVISION] = 0x3340; smc->regmask[EREG_REVISION] = 0x0000;
+ smc->reg[EREG_ERCV] = 0x331f; smc->regmask[EREG_ERCV] = 0x009f;
+
+ update_ethernet_irq(smc);
+}
+
+
+/*-------------------------------------------------
+ device get info callback
+-------------------------------------------------*/
+
+static DEVICE_GET_INFO( smc91c9x )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(smc91c9x_state); break;
+ case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = sizeof(smc91c9x_config); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(smc91c9x); break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(smc91c9x);break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: /* provided by subclasses */ break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "SMC91C9X Ethernet Controller");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;
+ }
+}
+
+DEVICE_GET_INFO( smc91c94 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "SMC91C94"); break;
+ default: DEVICE_GET_INFO_CALL(smc91c9x); break;
+ }
+}
+
+DEVICE_GET_INFO( smc91c96 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "SMC91C96"); break;
+ default: DEVICE_GET_INFO_CALL(smc91c9x); break;
+ }
+}
+
+
+DEFINE_LEGACY_DEVICE(SMC91C94, smc91c94);
+DEFINE_LEGACY_DEVICE(SMC91C96, smc91c96);
+
diff --git a/trunk/src/emu/machine/smc91c9x.h b/trunk/src/emu/machine/smc91c9x.h
new file mode 100644
index 00000000000..7a3f9de3505
--- /dev/null
+++ b/trunk/src/emu/machine/smc91c9x.h
@@ -0,0 +1,57 @@
+/*************************************************************************
+
+ SMC91C9X ethernet controller implementation
+
+ by Aaron Giles
+
+**************************************************************************/
+
+#ifndef __SMC91C9X__
+#define __SMC91C9X__
+
+#include "devlegcy.h"
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef void (*smc91c9x_irq_func)(device_t *device, int state);
+
+
+typedef struct _smc91c9x_config smc91c9x_config;
+struct _smc91c9x_config
+{
+ smc91c9x_irq_func interrupt;
+};
+
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_SMC91C94_ADD(_tag, _callback) \
+ MCFG_DEVICE_ADD(_tag, SMC91C94, 0) \
+ MCFG_DEVICE_CONFIG_DATAPTR(smc91c9x_config, interrupt, _callback)
+
+#define MCFG_SMC91C96_ADD(_tag, _callback) \
+ MCFG_DEVICE_ADD(_tag, SMC91C96, 0) \
+ MCFG_DEVICE_CONFIG_DATAPTR(smc91c9x_config, interrupt, _callback)
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+READ16_DEVICE_HANDLER( smc91c9x_r );
+WRITE16_DEVICE_HANDLER( smc91c9x_w );
+
+
+/* ----- device interface ----- */
+
+DECLARE_LEGACY_DEVICE(SMC91C94, smc91c94);
+DECLARE_LEGACY_DEVICE(SMC91C96, smc91c96);
+
+#endif
diff --git a/trunk/src/emu/machine/timekpr.c b/trunk/src/emu/machine/timekpr.c
new file mode 100644
index 00000000000..eb7c9737d62
--- /dev/null
+++ b/trunk/src/emu/machine/timekpr.c
@@ -0,0 +1,446 @@
+/***************************************************************************
+
+ timekpr.h
+
+ Various ST Microelectronics timekeeper SRAM implementations:
+ - M48T02
+ - M48T35
+ - M48T37
+ - M48T58
+ - MK48T08
+
+***************************************************************************/
+
+#include "emu.h"
+#include "machine/timekpr.h"
+
+
+// device type definition
+const device_type M48T02 = &device_creator<m48t02_device>;
+const device_type M48T35 = &device_creator<m48t35_device>;
+const device_type M48T37 = &device_creator<m48t37_device>;
+const device_type M48T58 = &device_creator<m48t58_device>;
+const device_type MK48T08 = &device_creator<mk48t08_device>;
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define MASK_SECONDS ( 0x7f )
+#define MASK_MINUTES ( 0x7f )
+#define MASK_HOURS ( 0x3f )
+#define MASK_DAY ( 0x07 )
+#define MASK_DATE ( 0x3f )
+#define MASK_MONTH ( 0x1f )
+#define MASK_YEAR ( 0xff )
+#define MASK_CENTURY ( 0xff )
+
+#define CONTROL_W ( 0x80 )
+#define CONTROL_R ( 0x40 )
+#define CONTROL_S ( 0x20 ) /* not emulated */
+#define CONTROL_CALIBRATION ( 0x1f ) /* not emulated */
+
+#define SECONDS_ST ( 0x80 )
+
+#define DAY_FT ( 0x40 ) /* M48T37 - not emulated */
+#define DAY_CEB ( 0x20 ) /* M48T35/M48T58 */
+#define DAY_CB ( 0x10 ) /* M48T35/M48T58 */
+
+#define DATE_BLE ( 0x80 ) /* M48T58: not emulated */
+#define DATE_BL ( 0x40 ) /* M48T58: not emulated */
+
+#define FLAGS_BL ( 0x10 ) /* MK48T08/M48T37: not emulated */
+#define FLAGS_AF ( 0x40 ) /* M48T37: not emulated */
+#define FLAGS_WDF ( 0x80 ) /* M48T37: not emulated */
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE UINT8 make_bcd(UINT8 data)
+{
+ return ( ( ( data / 10 ) % 10 ) << 4 ) + ( data % 10 );
+}
+
+INLINE UINT8 from_bcd( UINT8 data )
+{
+ return ( ( ( data >> 4 ) & 15 ) * 10 ) + ( data & 15 );
+}
+
+static int inc_bcd( UINT8 *data, int mask, int min, int max )
+{
+ int bcd;
+ int carry;
+
+ bcd = ( *( data ) + 1 ) & mask;
+ carry = 0;
+
+ if( ( bcd & 0x0f ) > 9 )
+ {
+ bcd &= 0xf0;
+ bcd += 0x10;
+ if( bcd > max )
+ {
+ bcd = min;
+ carry = 1;
+ }
+ }
+
+ *( data ) = ( *( data ) & ~mask ) | ( bcd & mask );
+ return carry;
+}
+
+static void counter_to_ram( UINT8 *data, int offset, int counter )
+{
+ if( offset >= 0 )
+ {
+ data[ offset ] = counter;
+ }
+}
+
+static int counter_from_ram( UINT8 *data, int offset )
+{
+ if( offset >= 0 )
+ {
+ return data[ offset ];
+ }
+ return 0;
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// timekeeper_device_config - constructor
+//-------------------------------------------------
+
+timekeeper_device::timekeeper_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, type, name, tag, owner, clock),
+ device_nvram_interface(mconfig, *this)
+{
+
+}
+
+m48t02_device::m48t02_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : timekeeper_device(mconfig, M48T02, "M48T02", tag, owner, clock)
+{
+ m_offset_control = 0x7f8;
+ m_offset_seconds = 0x7f9;
+ m_offset_minutes = 0x7fa;
+ m_offset_hours = 0x7fb;
+ m_offset_day = 0x7fc;
+ m_offset_date = 0x7fd;
+ m_offset_month = 0x7fe;
+ m_offset_year = 0x7ff;
+ m_offset_century = -1;
+ m_offset_flags = -1;
+ m_size = 0x800;
+}
+
+m48t35_device::m48t35_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : timekeeper_device(mconfig, M48T35, "M48T35", tag, owner, clock)
+{
+ m_offset_control = 0x7ff8;
+ m_offset_seconds = 0x7ff9;
+ m_offset_minutes = 0x7ffa;
+ m_offset_hours = 0x7ffb;
+ m_offset_day = 0x7ffc;
+ m_offset_date = 0x7ffd;
+ m_offset_month = 0x7ffe;
+ m_offset_year = 0x7fff;
+ m_offset_century = -1;
+ m_offset_flags = -1;
+ m_size = 0x8000;
+}
+
+m48t37_device::m48t37_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : timekeeper_device(mconfig, M48T37, "M48T37", tag, owner, clock)
+{
+ m_offset_control = 0x7ff8;
+ m_offset_seconds = 0x7ff9;
+ m_offset_minutes = 0x7ffa;
+ m_offset_hours = 0x7ffb;
+ m_offset_day = 0x7ffc;
+ m_offset_date = 0x7ffd;
+ m_offset_month = 0x7ffe;
+ m_offset_year = 0x7fff;
+ m_offset_century = 0x7ff1;
+ m_offset_flags = 0x7ff0;
+ m_size = 0x8000;
+}
+
+m48t58_device::m48t58_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : timekeeper_device(mconfig, M48T58, "M48T58", tag, owner, clock)
+{
+ m_offset_control = 0x1ff8;
+ m_offset_seconds = 0x1ff9;
+ m_offset_minutes = 0x1ffa;
+ m_offset_hours = 0x1ffb;
+ m_offset_day = 0x1ffc;
+ m_offset_date = 0x1ffd;
+ m_offset_month = 0x1ffe;
+ m_offset_year = 0x1fff;
+ m_offset_century = -1;
+ m_offset_flags = -1;
+ m_size = 0x2000;
+}
+
+mk48t08_device::mk48t08_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : timekeeper_device(mconfig, MK48T08, "MK48T08", tag, owner, clock)
+{
+ m_offset_control = 0x1ff8;
+ m_offset_seconds = 0x1ff9;
+ m_offset_minutes = 0x1ffa;
+ m_offset_hours = 0x1ffb;
+ m_offset_day = 0x1ffc;
+ m_offset_date = 0x1ffd;
+ m_offset_month = 0x1ffe;
+ m_offset_year = 0x1fff;
+ m_offset_century = 0x1ff1;
+ m_offset_flags = 0x1ff0;
+ m_size = 0x2000;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void timekeeper_device::device_start()
+{
+ system_time systime;
+
+ /* validate some basic stuff */
+ assert(this != NULL);
+
+ machine().base_datetime(systime);
+
+ m_control = 0;
+ m_seconds = make_bcd( systime.local_time.second );
+ m_minutes = make_bcd( systime.local_time.minute );
+ m_hours = make_bcd( systime.local_time.hour );
+ m_day = make_bcd( systime.local_time.weekday + 1 );
+ m_date = make_bcd( systime.local_time.mday );
+ m_month = make_bcd( systime.local_time.month + 1 );
+ m_year = make_bcd( systime.local_time.year % 100 );
+ m_century = make_bcd( systime.local_time.year / 100 );
+ m_data = auto_alloc_array( machine(), UINT8, m_size );
+
+ m_default_data = *region();
+ if (m_default_data)
+ {
+ assert( region()->bytes() == m_size );
+ }
+
+ save_item( NAME(m_control) );
+ save_item( NAME(m_seconds) );
+ save_item( NAME(m_minutes) );
+ save_item( NAME(m_hours) );
+ save_item( NAME(m_day) );
+ save_item( NAME(m_date) );
+ save_item( NAME(m_month) );
+ save_item( NAME(m_year) );
+ save_item( NAME(m_century) );
+ save_pointer( NAME(m_data), m_size );
+
+ emu_timer *timer = timer_alloc();
+ timer->adjust(attotime::from_seconds(1), 0, attotime::from_seconds(1));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void timekeeper_device::device_reset() { }
+
+void timekeeper_device::counters_to_ram()
+{
+ counter_to_ram( m_data, m_offset_control, m_control );
+ counter_to_ram( m_data, m_offset_seconds, m_seconds );
+ counter_to_ram( m_data, m_offset_minutes, m_minutes );
+ counter_to_ram( m_data, m_offset_hours, m_hours );
+ counter_to_ram( m_data, m_offset_day, m_day );
+ counter_to_ram( m_data, m_offset_date, m_date );
+ counter_to_ram( m_data, m_offset_month, m_month );
+ counter_to_ram( m_data, m_offset_year, m_year );
+ counter_to_ram( m_data, m_offset_century, m_century );
+}
+
+void timekeeper_device::counters_from_ram()
+{
+ m_control = counter_from_ram( m_data, m_offset_control );
+ m_seconds = counter_from_ram( m_data, m_offset_seconds );
+ m_minutes = counter_from_ram( m_data, m_offset_minutes );
+ m_hours = counter_from_ram( m_data, m_offset_hours );
+ m_day = counter_from_ram( m_data, m_offset_day );
+ m_date = counter_from_ram( m_data, m_offset_date );
+ m_month = counter_from_ram( m_data, m_offset_month );
+ m_year = counter_from_ram( m_data, m_offset_year );
+ m_century = counter_from_ram( m_data, m_offset_century );
+}
+
+void timekeeper_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ if( ( m_seconds & SECONDS_ST ) != 0 ||
+ ( m_control & CONTROL_W ) != 0 )
+ {
+ return;
+ }
+
+ int carry = inc_bcd( &m_seconds, MASK_SECONDS, 0x00, 0x59 );
+ if( carry )
+ {
+ carry = inc_bcd( &m_minutes, MASK_MINUTES, 0x00, 0x59 );
+ }
+ if( carry )
+ {
+ carry = inc_bcd( &m_hours, MASK_HOURS, 0x00, 0x23 );
+ }
+
+ if( carry )
+ {
+ UINT8 maxdays;
+ static const UINT8 daysinmonth[] = { 0x31, 0x28, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x30, 0x31, 0x30, 0x31 };
+
+ inc_bcd( &m_day, MASK_DAY, 0x01, 0x07 );
+
+ UINT8 month = from_bcd( m_month );
+ UINT8 year = from_bcd( m_year );
+
+ if( month == 2 && ( year % 4 ) == 0 )
+ {
+ maxdays = 0x29;
+ }
+ else if( month >= 1 && month <= 12 )
+ {
+ maxdays = daysinmonth[ month - 1 ];
+ }
+ else
+ {
+ maxdays = 0x31;
+ }
+
+ carry = inc_bcd( &m_date, MASK_DATE, 0x01, maxdays );
+ }
+ if( carry )
+ {
+ carry = inc_bcd( &m_month, MASK_MONTH, 0x01, 0x12 );
+ }
+ if( carry )
+ {
+ carry = inc_bcd( &m_year, MASK_YEAR, 0x00, 0x99 );
+ }
+ if( carry )
+ {
+ carry = inc_bcd( &m_century, MASK_CENTURY, 0x00, 0x99 );
+
+ if( type() == M48T35 ||
+ type() == M48T58 )
+ {
+ if( ( m_day & DAY_CEB ) != 0 )
+ {
+ m_day ^= DAY_CB;
+ }
+ }
+ }
+
+ if( ( m_control & CONTROL_R ) == 0 )
+ {
+ counters_to_ram();
+ }
+}
+
+void timekeeper_device::write(UINT16 offset, UINT8 data)
+{
+ if( offset == m_offset_control )
+ {
+ if( ( m_control & CONTROL_W ) != 0 &&
+ ( data & CONTROL_W ) == 0 )
+ {
+ counters_from_ram();
+ }
+ m_control = data;
+ }
+ else if( offset == m_offset_day )
+ {
+ if( type() == M48T35 ||
+ type() == M48T58 )
+ {
+ m_day = ( m_day & ~DAY_CEB ) | ( data & DAY_CEB );
+ }
+ }
+
+ m_data[ offset ] = data;
+}
+
+UINT8 timekeeper_device::read(UINT16 offset)
+{
+ UINT8 result = m_data[ offset ];
+ if( offset == m_offset_date && type() == M48T58 )
+ {
+ result &= ~DATE_BL;
+ }
+ else if( offset == m_offset_flags && (type() == MK48T08 || type() == M48T37) )
+ {
+ result = 0;
+ }
+ return result;
+}
+
+//-------------------------------------------------
+// nvram_default - called to initialize NVRAM to
+// its default state
+//-------------------------------------------------
+
+void timekeeper_device::nvram_default()
+{
+ if( m_default_data != NULL )
+ {
+ memcpy( m_data, m_default_data, m_size );
+ }
+ else
+ {
+ memset( m_data, 0xff, m_size );
+ }
+
+ if ( m_offset_flags >= 0 )
+ m_data[ m_offset_flags ] = 0;
+ counters_to_ram();
+}
+
+
+//-------------------------------------------------
+// nvram_read - called to read NVRAM from the
+// .nv file
+//-------------------------------------------------
+
+void timekeeper_device::nvram_read(emu_file &file)
+{
+ file.read( m_data, m_size );
+
+ counters_to_ram();
+}
+
+
+//-------------------------------------------------
+// nvram_write - called to write NVRAM to the
+// .nv file
+//-------------------------------------------------
+
+void timekeeper_device::nvram_write(emu_file &file)
+{
+ file.write( m_data, m_size );
+}
+
+
+
+/***************************************************************************
+ TRAMPOLINES
+***************************************************************************/
+
+WRITE8_DEVICE_HANDLER( timekeeper_w ) { downcast<timekeeper_device *>(device)->write(offset, data); }
+READ8_DEVICE_HANDLER( timekeeper_r ) { return downcast<timekeeper_device*>(device)->read(offset); }
+
diff --git a/trunk/src/emu/machine/timekpr.h b/trunk/src/emu/machine/timekpr.h
new file mode 100644
index 00000000000..4dd5cb64aa8
--- /dev/null
+++ b/trunk/src/emu/machine/timekpr.h
@@ -0,0 +1,160 @@
+/***************************************************************************
+
+ timekpr.h
+
+ Various ST Microelectronics timekeeper SRAM implementations:
+ - M48T02
+ - M48T35
+ - M48T37
+ - M48T58
+ - MK48T08
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __TIMEKPR_H__
+#define __TIMEKPR_H__
+
+#include "emu.h"
+#include "devhelpr.h"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_M48T02_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, M48T02, 0)
+
+#define MCFG_M48T35_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, M48T35, 0)
+
+#define MCFG_M48T37_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, M48T37, 0)
+
+#define MCFG_M48T58_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, M48T58, 0)
+
+#define MCFG_MK48T08_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, MK48T08, 0)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> timekeeper_config
+
+struct timekeeper_config
+{
+ const UINT8 *m_data;
+};
+
+
+// ======================> timekeeper_device
+
+class timekeeper_device : public device_t,
+ public device_nvram_interface
+{
+protected:
+ // construction/destruction
+ timekeeper_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
+
+public:
+ void write(UINT16 offset, UINT8 data);
+ UINT8 read(UINT16 offset);
+
+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_nvram_interface overrides
+ virtual void nvram_default();
+ virtual void nvram_read(emu_file &file);
+ virtual void nvram_write(emu_file &file);
+
+private:
+ void counters_to_ram();
+ void counters_from_ram();
+
+ // internal state
+ UINT8 m_control;
+ UINT8 m_seconds;
+ UINT8 m_minutes;
+ UINT8 m_hours;
+ UINT8 m_day;
+ UINT8 m_date;
+ UINT8 m_month;
+ UINT8 m_year;
+ UINT8 m_century;
+
+ UINT8 *m_data;
+ UINT8 *m_default_data;
+
+protected:
+ int m_size;
+ int m_offset_control;
+ int m_offset_seconds;
+ int m_offset_minutes;
+ int m_offset_hours;
+ int m_offset_day;
+ int m_offset_date;
+ int m_offset_month;
+ int m_offset_year;
+ int m_offset_century;
+ int m_offset_flags;
+};
+
+class m48t02_device : public timekeeper_device
+{
+public:
+ m48t02_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class m48t35_device : public timekeeper_device
+{
+public:
+ m48t35_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class m48t37_device : public timekeeper_device
+{
+public:
+ m48t37_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class m48t58_device : public timekeeper_device
+{
+public:
+ m48t58_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class mk48t08_device : public timekeeper_device
+{
+public:
+ mk48t08_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+// device type definition
+extern const device_type M48T02;
+extern const device_type M48T35;
+extern const device_type M48T37;
+extern const device_type M48T58;
+extern const device_type MK48T08;
+
+
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+WRITE8_DEVICE_HANDLER( timekeeper_w );
+READ8_DEVICE_HANDLER( timekeeper_r );
+
+#endif // __TIMEKPR_H__
diff --git a/trunk/src/emu/machine/tmp68301.c b/trunk/src/emu/machine/tmp68301.c
new file mode 100644
index 00000000000..369cf9949e5
--- /dev/null
+++ b/trunk/src/emu/machine/tmp68301.c
@@ -0,0 +1,189 @@
+/***************************************************************************
+
+ TMP68301 basic emulation + Interrupt Handling
+
+ The Toshiba TMP68301 is a 68HC000 + serial I/O, parallel I/O,
+ 3 timers, address decoder, wait generator, interrupt controller,
+ all integrated in a single chip.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "machine/tmp68301.h"
+
+static UINT16 tmp68301_regs[0x400];
+
+static UINT8 tmp68301_IE[3]; // 3 External Interrupt Lines
+static emu_timer *tmp68301_timer[3]; // 3 Timers
+
+static int tmp68301_irq_vector[8];
+
+static void tmp68301_update_timer( running_machine &machine, int i );
+
+static IRQ_CALLBACK(tmp68301_irq_callback)
+{
+ int vector = tmp68301_irq_vector[irqline];
+// logerror("%s: irq callback returns %04X for level %x\n",machine.describe_context(),vector,int_level);
+ return vector;
+}
+
+static TIMER_CALLBACK( tmp68301_timer_callback )
+{
+ int i = param;
+ UINT16 TCR = tmp68301_regs[(0x200 + i * 0x20)/2];
+ UINT16 IMR = tmp68301_regs[0x94/2]; // Interrupt Mask Register (IMR)
+ UINT16 ICR = tmp68301_regs[0x8e/2+i]; // Interrupt Controller Register (ICR7..9)
+ UINT16 IVNR = tmp68301_regs[0x9a/2]; // Interrupt Vector Number Register (IVNR)
+
+// logerror("s: callback timer %04X, j = %d\n",machine.describe_context(),i,tcount);
+
+ if ( (TCR & 0x0004) && // INT
+ !(IMR & (0x100<<i))
+ )
+ {
+ int level = ICR & 0x0007;
+
+ // Interrupt Vector Number Register (IVNR)
+ tmp68301_irq_vector[level] = IVNR & 0x00e0;
+ tmp68301_irq_vector[level] += 4+i;
+
+ device_set_input_line(machine.firstcpu,level,HOLD_LINE);
+ }
+
+ if (TCR & 0x0080) // N/1
+ {
+ // Repeat
+ tmp68301_update_timer(machine, i);
+ }
+ else
+ {
+ // One Shot
+ }
+}
+
+static void tmp68301_update_timer( running_machine &machine, int i )
+{
+ UINT16 TCR = tmp68301_regs[(0x200 + i * 0x20)/2];
+ UINT16 MAX1 = tmp68301_regs[(0x204 + i * 0x20)/2];
+ UINT16 MAX2 = tmp68301_regs[(0x206 + i * 0x20)/2];
+
+ int max = 0;
+ attotime duration = attotime::zero;
+
+ tmp68301_timer[i]->adjust(attotime::never,i);
+
+ // timers 1&2 only
+ switch( (TCR & 0x0030)>>4 ) // MR2..1
+ {
+ case 1:
+ max = MAX1;
+ break;
+ case 2:
+ max = MAX2;
+ break;
+ }
+
+ switch ( (TCR & 0xc000)>>14 ) // CK2..1
+ {
+ case 0: // System clock (CLK)
+ if (max)
+ {
+ int scale = (TCR & 0x3c00)>>10; // P4..1
+ if (scale > 8) scale = 8;
+ duration = attotime::from_hz(machine.firstcpu->unscaled_clock()) * ((1 << scale) * max);
+ }
+ break;
+ }
+
+// logerror("%s: TMP68301 Timer %d, duration %lf, max %04X\n",machine.describe_context(),i,duration,max);
+
+ if (!(TCR & 0x0002)) // CS
+ {
+ if (duration != attotime::zero)
+ tmp68301_timer[i]->adjust(duration,i);
+ else
+ logerror("%s: TMP68301 error, timer %d duration is 0\n",machine.describe_context(),i);
+ }
+}
+
+MACHINE_START( tmp68301 )
+{
+ int i;
+ for (i = 0; i < 3; i++)
+ tmp68301_timer[i] = machine.scheduler().timer_alloc(FUNC(tmp68301_timer_callback));
+}
+
+MACHINE_RESET( tmp68301 )
+{
+ int i;
+
+ for (i = 0; i < 3; i++)
+ tmp68301_IE[i] = 0;
+
+ device_set_irq_callback(machine.firstcpu, tmp68301_irq_callback);
+}
+
+/* Update the IRQ state based on all possible causes */
+static void update_irq_state(running_machine &machine)
+{
+ int i;
+
+ /* Take care of external interrupts */
+
+ UINT16 IMR = tmp68301_regs[0x94/2]; // Interrupt Mask Register (IMR)
+ UINT16 IVNR = tmp68301_regs[0x9a/2]; // Interrupt Vector Number Register (IVNR)
+
+ for (i = 0; i < 3; i++)
+ {
+ if ( (tmp68301_IE[i]) &&
+ !(IMR & (1<<i))
+ )
+ {
+ UINT16 ICR = tmp68301_regs[0x80/2+i]; // Interrupt Controller Register (ICR0..2)
+
+ // Interrupt Controller Register (ICR0..2)
+ int level = ICR & 0x0007;
+
+ // Interrupt Vector Number Register (IVNR)
+ tmp68301_irq_vector[level] = IVNR & 0x00e0;
+ tmp68301_irq_vector[level] += i;
+
+ tmp68301_IE[i] = 0; // Interrupts are edge triggerred
+
+ device_set_input_line(machine.firstcpu,level,HOLD_LINE);
+ }
+ }
+}
+
+READ16_HANDLER( tmp68301_regs_r )
+{
+ return tmp68301_regs[offset];
+}
+
+WRITE16_HANDLER( tmp68301_regs_w )
+{
+ COMBINE_DATA(&tmp68301_regs[offset]);
+
+ if (!ACCESSING_BITS_0_7) return;
+
+// logerror("CPU #0 PC %06X: TMP68301 Reg %04X<-%04X & %04X\n",cpu_get_pc(&space->device()),offset*2,data,mem_mask^0xffff);
+
+ switch( offset * 2 )
+ {
+ // Timers
+ case 0x200:
+ case 0x220:
+ case 0x240:
+ {
+ int i = ((offset*2) >> 5) & 3;
+
+ tmp68301_update_timer( space->machine(), i );
+ }
+ break;
+ }
+}
+
+void tmp68301_external_interrupt_0(running_machine &machine) { tmp68301_IE[0] = 1; update_irq_state(machine); }
+void tmp68301_external_interrupt_1(running_machine &machine) { tmp68301_IE[1] = 1; update_irq_state(machine); }
+void tmp68301_external_interrupt_2(running_machine &machine) { tmp68301_IE[2] = 1; update_irq_state(machine); }
+
diff --git a/trunk/src/emu/machine/tmp68301.h b/trunk/src/emu/machine/tmp68301.h
new file mode 100644
index 00000000000..c83c249c839
--- /dev/null
+++ b/trunk/src/emu/machine/tmp68301.h
@@ -0,0 +1,17 @@
+#ifndef TMP68301_H
+#define TMP68301_H
+
+// Machine init
+MACHINE_START( tmp68301 );
+MACHINE_RESET( tmp68301 );
+
+// Hardware Registers
+READ16_HANDLER( tmp68301_regs_r );
+WRITE16_HANDLER( tmp68301_regs_w );
+
+// Interrupts
+void tmp68301_external_interrupt_0(running_machine &machine);
+void tmp68301_external_interrupt_1(running_machine &machine);
+void tmp68301_external_interrupt_2(running_machine &machine);
+
+#endif
diff --git a/trunk/src/emu/machine/tms6100.c b/trunk/src/emu/machine/tms6100.c
new file mode 100644
index 00000000000..8bbb2e08202
--- /dev/null
+++ b/trunk/src/emu/machine/tms6100.c
@@ -0,0 +1,282 @@
+/**********************************************************************************************
+
+ TMS6100 simulator
+
+ Written for MAME by Couriersud
+
+ Todo:
+ - implement CS
+ - implement 4 bit mode (mask programmed)
+ - implement chip addressing (0-15 mask programmed)
+
+ TMS6100:
+
+ +-----------------+
+ VDD | 1 28 | NC
+ NC | 2 27 | NC
+ DATA/ADD1 | 3 26 | NC
+ DATA/ADD2 | 4 25 | NC
+ DATA/ADD4 | 5 24 | NC
+ DATA/ADD8 | 6 23 | NC
+ CLK | 7 22 | NC
+ NC | 8 21 | NC
+ NC | 9 20 | NC
+ M0 | 10 19 | NC
+ M1 | 11 18 | NC
+ NC | 12 17 | NC
+ /CS | 13 16 | NC
+ VSS | 14 15 | NC
+ +-----------------+
+
+ M58819 (from radarscope schematics):
+
+ +-----------------+
+ AD0 | 1 40 | AD1
+ GND | 2 39 | AD2
+ -5V | 3 38 | AD3
+ A0 | 4 37 | AD4
+ NC | 5 36 | AD5
+ NC | 6 35 | AD6
+ A1 | 7 34 | AD7
+ A2 | 8 33 | AD8
+ A3 | 9 32 | AD9
+ CLK | 10 31 | AD10
+ NC | 11 30 | AD11
+ -5V | 12 29 | AD12
+ C0 | 13 28 | NC
+ C1 | 14 27 | NC
+ NC | 15 26 | I7
+ NC | 16 25 | NC
+ +5V | 17 24 | I6
+ I0 | 18 23 | I5
+ I1 | 19 22 | I4
+ I2 | 20 21 | I3
+ +-----------------+
+
+ The M58819 is used as an interface to external speech eproms.
+ NC pins may have a function, although they are not connected in
+ radarscope.
+
+***********************************************************************************************/
+
+#include "emu.h"
+#include "tms6100.h"
+
+#define VERBOSE (0)
+
+#if VERBOSE
+#define LOG(x) logerror x
+#else
+#define LOG(x)
+#endif
+
+#define TMS6100_READ_PENDING 0x01
+#define TMS6100_NEXT_READ_IS_DUMMY 0x02
+
+typedef struct _tms6100_state tms6100_state;
+struct _tms6100_state
+{
+ /* Rom interface */
+ UINT32 address;
+ UINT32 address_latch;
+ UINT8 loadptr;
+ UINT8 m0;
+ UINT8 m1;
+ UINT8 addr_bits;
+ UINT8 clock;
+ UINT8 data;
+ UINT8 state;
+
+ const UINT8 *rom;
+
+ device_t *device;
+
+#if 0
+ const tms5110_interface *intf;
+#endif
+};
+
+/**********************************************************************************************
+
+ get_safe_token -- get tms6100_state
+
+***********************************************************************************************/
+
+INLINE tms6100_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == TMS6100 ||
+ device->type() == M58819);
+ return (tms6100_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+/**********************************************************************************************
+
+ register_save_states -- register state vars for saving
+
+***********************************************************************************************/
+
+static void register_for_save_states(tms6100_state *tms)
+{
+ tms->device->save_item(NAME(tms->addr_bits));
+ tms->device->save_item(NAME(tms->address));
+ tms->device->save_item(NAME(tms->address_latch));
+ tms->device->save_item(NAME(tms->data));
+ tms->device->save_item(NAME(tms->loadptr));
+ tms->device->save_item(NAME(tms->m0));
+ tms->device->save_item(NAME(tms->m1));
+ tms->device->save_item(NAME(tms->state));
+}
+
+/******************************************************************************
+
+ DEVICE_START( tms6100 ) -- allocate buffers and reset the 6100
+
+******************************************************************************/
+
+static DEVICE_START( tms6100 )
+{
+ //static const tms5110_interface dummy = { 0 };
+ tms6100_state *tms = get_safe_token(device);
+
+ assert_always(tms != NULL, "Error creating TMS6100 chip");
+
+ //tms->intf = device->static_config ? (const tms5110_interface *)device->static_config : &dummy;
+ tms->rom = *device->region();
+
+ tms->device = device;
+
+ register_for_save_states(tms);
+}
+
+static DEVICE_START( m58819 )
+{
+ //tms6100_state *tms = get_safe_token(device);
+ DEVICE_START_CALL( tms6100 );
+ //tms5110_set_variant(tms, TMS5110_IS_5100);
+}
+
+static DEVICE_RESET( tms6100 )
+{
+ tms6100_state *tms = get_safe_token(device);
+
+ /* initialize the chip */
+ tms->addr_bits = 0;
+ tms->address = 0;
+ tms->address_latch = 0;
+ tms->loadptr = 0;
+ tms->m0 = 0;
+ tms->m1 = 0;
+ tms->state = 0;
+ tms->clock = 0;
+ tms->data = 0;
+}
+
+WRITE_LINE_DEVICE_HANDLER( tms6100_m0_w )
+{
+ tms6100_state *tms = get_safe_token(device);
+ if (state != tms->m0)
+ tms->m0 = state;
+}
+
+WRITE_LINE_DEVICE_HANDLER( tms6100_m1_w )
+{
+ tms6100_state *tms = get_safe_token(device);
+ if (state != tms->m1)
+ tms->m1 = state;
+}
+
+WRITE_LINE_DEVICE_HANDLER( tms6100_romclock_w )
+{
+ tms6100_state *tms = get_safe_token(device);
+
+ /* process on falling edge */
+ if (tms->clock && !state)
+ {
+ switch ((tms->m1<<1) | tms->m0)
+ {
+ case 0x00:
+ /* NOP in datasheet, not really ... */
+ if (tms->state & TMS6100_READ_PENDING)
+ {
+ if (tms->state & TMS6100_NEXT_READ_IS_DUMMY)
+ {
+ tms->address = (tms->address_latch << 3);
+ tms->address_latch = 0;
+ tms->loadptr = 0;
+ tms->state &= ~TMS6100_NEXT_READ_IS_DUMMY;
+ LOG(("loaded address %08x\n", tms->address));
+ }
+ else
+ {
+ /* read bit at address */
+ tms->data = (tms->rom[tms->address >> 3] >> ((tms->address & 0x07) ^ 0x07)) & 1;
+ tms->address++;
+ }
+ tms->state &= ~TMS6100_READ_PENDING;
+ }
+ break;
+ case 0x01:
+ /* READ */
+ tms->state |= TMS6100_READ_PENDING;
+ break;
+ case 0x02:
+ /* LOAD ADDRESS */
+ tms->state |= TMS6100_NEXT_READ_IS_DUMMY;
+ tms->address_latch |= (tms->addr_bits << tms->loadptr);
+ LOG(("loaded address latch %08x\n", tms->address_latch));
+ tms->loadptr += 4;
+ break;
+ case 0x03:
+ /* READ AND BRANCH */
+ if (tms->state & TMS6100_NEXT_READ_IS_DUMMY)
+ {
+ tms->state &= ~TMS6100_NEXT_READ_IS_DUMMY; // clear - no dummy read according to datasheet
+ LOG(("loaded address latch %08x\n", tms->address_latch));
+ tms->address = tms->rom[tms->address_latch] | (tms->rom[tms->address_latch+1]<<8);
+ tms->address &= 0x3fff; // 14 bits
+ LOG(("loaded indirect address %04x\n", tms->address));
+ tms->address = (tms->address << 3);
+ tms->address_latch = 0;
+ tms->loadptr = 0;
+ }
+ break;
+ }
+ }
+ tms->clock = state;
+}
+
+WRITE8_DEVICE_HANDLER( tms6100_addr_w )
+{
+ tms6100_state *tms = get_safe_token(device);
+ if (data != tms->addr_bits)
+ tms->addr_bits = data;
+}
+
+READ_LINE_DEVICE_HANDLER( tms6100_data_r )
+{
+ tms6100_state *tms = get_safe_token(device);
+
+ return tms->data;
+}
+
+/*-------------------------------------------------
+ TMS 6100 device definition
+-------------------------------------------------*/
+
+static const char DEVTEMPLATE_SOURCE[] = __FILE__;
+
+#define DEVTEMPLATE_ID(p,s) p##tms6100##s
+#define DEVTEMPLATE_FEATURES DT_HAS_START | DT_HAS_RESET
+#define DEVTEMPLATE_NAME "TMS6100"
+#define DEVTEMPLATE_FAMILY "TI Speech"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##m58819##s
+#define DEVTEMPLATE_DERIVED_FEATURES DT_HAS_START
+#define DEVTEMPLATE_DERIVED_NAME "M58819"
+#include "devtempl.h"
+
+
+DEFINE_LEGACY_DEVICE(TMS6100, tms6100);
+DEFINE_LEGACY_DEVICE(M58819, m58819);
diff --git a/trunk/src/emu/machine/tms6100.h b/trunk/src/emu/machine/tms6100.h
new file mode 100644
index 00000000000..bd6a1919d20
--- /dev/null
+++ b/trunk/src/emu/machine/tms6100.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#ifndef __TMS6100_H__
+#define __TMS6100_H__
+
+#include "devlegcy.h"
+
+/* TMS 6100 memory controller */
+
+WRITE_LINE_DEVICE_HANDLER( tms6100_m0_w );
+WRITE_LINE_DEVICE_HANDLER( tms6100_m1_w );
+WRITE_LINE_DEVICE_HANDLER( tms6100_romclock_w );
+WRITE8_DEVICE_HANDLER( tms6100_addr_w );
+
+READ_LINE_DEVICE_HANDLER( tms6100_data_r );
+
+DECLARE_LEGACY_DEVICE(TMS6100, tms6100);
+DECLARE_LEGACY_DEVICE(M58819, m58819);
+
+#endif /* __TMS6100_H__ */
diff --git a/trunk/src/emu/machine/upd1990a.c b/trunk/src/emu/machine/upd1990a.c
new file mode 100644
index 00000000000..51b60011107
--- /dev/null
+++ b/trunk/src/emu/machine/upd1990a.c
@@ -0,0 +1,526 @@
+/**********************************************************************
+
+ NEC uPD1990AC Serial I/O Calendar & Clock emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+/*
+
+ TODO:
+
+ - test mode
+
+*/
+
+#include "upd1990a.h"
+
+
+// device type definition
+const device_type UPD1990A = &device_creator<upd1990a_device>;
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+
+// operating modes
+enum
+{
+ MODE_REGISTER_HOLD = 0,
+ MODE_SHIFT,
+ MODE_TIME_SET,
+ MODE_TIME_READ,
+ MODE_TP_64HZ_SET,
+ MODE_TP_256HZ_SET,
+ MODE_TP_2048HZ_SET,
+ MODE_TEST
+};
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// convert_to_bcd -
+//-------------------------------------------------
+
+inline UINT8 upd1990a_device::convert_to_bcd(int val)
+{
+ return ((val / 10) << 4) | (val % 10);
+}
+
+
+//-------------------------------------------------
+// bcd_to_integer -
+//-------------------------------------------------
+
+inline int upd1990a_device::bcd_to_integer(UINT8 val)
+{
+ return (((val & 0xf0) >> 4) * 10) + (val & 0x0f);
+}
+
+
+//-------------------------------------------------
+// advance_seconds -
+//-------------------------------------------------
+
+inline void upd1990a_device::advance_seconds()
+{
+ static const int days_per_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+ int seconds = bcd_to_integer(m_time_counter[0]);
+ int minutes = bcd_to_integer(m_time_counter[1]);
+ int hours = bcd_to_integer(m_time_counter[2]);
+ int days = bcd_to_integer(m_time_counter[3]);
+ int day_of_week = m_time_counter[4] & 0x0f;
+ int month = (m_time_counter[4] & 0xf0) >> 4;
+
+ seconds++;
+
+ if (seconds > 59)
+ {
+ seconds = 0;
+ minutes++;
+ }
+
+ if (minutes > 59)
+ {
+ minutes = 0;
+ hours++;
+ }
+
+ if (hours > 23)
+ {
+ hours = 0;
+ days++;
+ day_of_week++;
+ }
+
+ if (day_of_week > 6)
+ {
+ day_of_week++;
+ }
+
+ if (days > days_per_month[month - 1])
+ {
+ days = 1;
+ month++;
+ }
+
+ if (month > 12)
+ {
+ month = 1;
+ }
+
+ m_time_counter[0] = convert_to_bcd(seconds);
+ m_time_counter[1] = convert_to_bcd(minutes);
+ m_time_counter[2] = convert_to_bcd(hours);
+ m_time_counter[3] = convert_to_bcd(days);
+ m_time_counter[4] = (month << 4) | day_of_week;
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// upd1990a_device - constructor
+//-------------------------------------------------
+
+upd1990a_device::upd1990a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, UPD1990A, "uPD1990A", tag, owner, clock),
+ device_rtc_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void upd1990a_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const upd1990a_interface *intf = reinterpret_cast<const upd1990a_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<upd1990a_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_out_data_cb, 0, sizeof(m_out_data_cb));
+ memset(&m_out_tp_cb, 0, sizeof(m_out_tp_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void upd1990a_device::device_start()
+{
+ // resolve callbacks
+ m_out_data_func.resolve(m_out_data_cb, *this);
+ m_out_tp_func.resolve(m_out_tp_cb, *this);
+
+ // allocate timers
+ m_timer_clock = timer_alloc(TIMER_CLOCK);
+ m_timer_clock->adjust(attotime::from_hz(clock() / 32768), 0, attotime::from_hz(clock() / 32768));
+ m_timer_tp = timer_alloc(TIMER_TP);
+ m_timer_data_out = timer_alloc(TIMER_DATA_OUT);
+
+ // state saving
+ save_item(NAME(m_time_counter));
+ save_item(NAME(m_shift_reg));
+ save_item(NAME(m_oe));
+ save_item(NAME(m_cs));
+ save_item(NAME(m_stb));
+ save_item(NAME(m_data_in));
+ save_item(NAME(m_data_out));
+ save_item(NAME(m_c));
+ save_item(NAME(m_clk));
+ save_item(NAME(m_tp));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void upd1990a_device::device_reset()
+{
+ system_time curtime, *systime = &curtime;
+
+ machine().current_datetime(curtime);
+
+ // HACK: load time counter from system time
+ m_time_counter[0] = convert_to_bcd(systime->local_time.second);
+ m_time_counter[1] = convert_to_bcd(systime->local_time.minute);
+ m_time_counter[2] = convert_to_bcd(systime->local_time.hour);
+ m_time_counter[3] = convert_to_bcd(systime->local_time.mday);
+ m_time_counter[4] = systime->local_time.weekday;
+ m_time_counter[4] |= (systime->local_time.month + 1) << 4;
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void upd1990a_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case TIMER_CLOCK:
+ advance_seconds();
+ break;
+
+ case TIMER_TP:
+ m_tp = !m_tp;
+
+ if (LOG) logerror("uPD1990A '%s' TP %u\n", tag(), m_tp);
+
+ m_out_tp_func(m_tp);
+ break;
+
+ case TIMER_DATA_OUT:
+ m_data_out = !m_data_out;
+
+ if (LOG) logerror("uPD1990A '%s' DATA OUT TICK %u\n", tag(), m_data_out);
+
+ m_out_data_func(m_data_out);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// rtc_set_time - called to initialize the RTC to
+// a known state
+//-------------------------------------------------
+
+void upd1990a_device::rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second)
+{
+ m_time_counter[0] = convert_to_bcd(second);
+ m_time_counter[1] = convert_to_bcd(minute);
+ m_time_counter[2] = convert_to_bcd(hour);
+ m_time_counter[3] = convert_to_bcd(day);
+ m_time_counter[4] = (month << 4) | day_of_week;
+}
+
+
+//-------------------------------------------------
+// oe_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( upd1990a_device::oe_w )
+{
+ if (LOG) logerror("uPD1990A '%s' OE %u\n", tag(), state);
+
+ m_oe = state;
+}
+
+
+//-------------------------------------------------
+// cs_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( upd1990a_device::cs_w )
+{
+ if (LOG) logerror("uPD1990A '%s' CS %u\n", tag(), state);
+
+ m_cs = state;
+}
+
+
+//-------------------------------------------------
+// stb_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( upd1990a_device::stb_w )
+{
+ if (LOG) logerror("uPD1990A '%s' STB %u\n", tag(), state);
+
+ m_stb = state;
+
+ if (m_cs && m_stb && !m_clk)
+ {
+ switch (m_c)
+ {
+ case MODE_REGISTER_HOLD:
+ if (LOG) logerror("uPD1990A '%s' Register Hold Mode\n", tag());
+
+ /* enable time counter */
+ m_timer_clock->enable(1);
+
+ /* 1 Hz data out pulse */
+ m_data_out = 1;
+ m_timer_data_out->adjust(attotime::zero, 0, attotime::from_hz(1*2));
+
+ /* 64 Hz time pulse */
+ m_timer_tp->adjust(attotime::zero, 0, attotime::from_hz(64*2));
+ break;
+
+ case MODE_SHIFT:
+ if (LOG) logerror("uPD1990A '%s' Shift Mode\n", tag());
+
+ /* enable time counter */
+ m_timer_clock->enable(1);
+
+ /* disable data out pulse */
+ m_timer_data_out->enable(0);
+
+ /* output LSB of shift register */
+ m_data_out = BIT(m_shift_reg[0], 0);
+ m_out_data_func(m_data_out);
+
+ /* 32 Hz time pulse */
+ m_timer_tp->adjust(attotime::zero, 0, attotime::from_hz(32*2));
+ break;
+
+ case MODE_TIME_SET:
+ if (LOG) logerror("uPD1990A '%s' Time Set Mode\n", tag());
+ if (LOG) logerror("uPD1990A '%s' Shift Register %02x%02x%02x%02x%02x\n", tag(), m_shift_reg[4], m_shift_reg[3], m_shift_reg[2], m_shift_reg[1], m_shift_reg[0]);
+
+ /* disable time counter */
+ m_timer_clock->enable(0);
+
+ /* disable data out pulse */
+ m_timer_data_out->enable(0);
+
+ /* output LSB of shift register */
+ m_data_out = BIT(m_shift_reg[0], 0);
+ m_out_data_func(m_data_out);
+
+ /* load shift register data into time counter */
+ for (int i = 0; i < 5; i++)
+ {
+ m_time_counter[i] = m_shift_reg[i];
+ }
+
+ /* 32 Hz time pulse */
+ m_timer_tp->adjust(attotime::zero, 0, attotime::from_hz(32*2));
+ break;
+
+ case MODE_TIME_READ:
+ if (LOG) logerror("uPD1990A '%s' Time Read Mode\n", tag());
+
+ /* enable time counter */
+ m_timer_clock->enable(1);
+
+ /* load time counter data into shift register */
+ for (int i = 0; i < 5; i++)
+ {
+ m_shift_reg[i] = m_time_counter[i];
+ }
+
+ if (LOG) logerror("uPD1990A '%s' Shift Register %02x%02x%02x%02x%02x\n", tag(), m_shift_reg[4], m_shift_reg[3], m_shift_reg[2], m_shift_reg[1], m_shift_reg[0]);
+
+ /* 512 Hz data out pulse */
+ m_data_out = 1;
+ m_timer_data_out->adjust(attotime::zero, 0, attotime::from_hz(512*2));
+
+ /* 32 Hz time pulse */
+ m_timer_tp->adjust(attotime::zero, 0, attotime::from_hz(32*2));
+ break;
+
+ case MODE_TP_64HZ_SET:
+ if (LOG) logerror("uPD1990A '%s' TP = 64 Hz Set Mode\n", tag());
+
+ /* 64 Hz time pulse */
+ m_timer_tp->adjust(attotime::zero, 0, attotime::from_hz(64*2));
+ break;
+
+ case MODE_TP_256HZ_SET:
+ if (LOG) logerror("uPD1990A '%s' TP = 256 Hz Set Mode\n", tag());
+
+ /* 256 Hz time pulse */
+ m_timer_tp->adjust(attotime::zero, 0, attotime::from_hz(256*2));
+ break;
+
+ case MODE_TP_2048HZ_SET:
+ if (LOG) logerror("uPD1990A '%s' TP = 2048 Hz Set Mode\n", tag());
+
+ /* 2048 Hz time pulse */
+ m_timer_tp->adjust(attotime::zero, 0, attotime::from_hz(2048*2));
+ break;
+
+ case MODE_TEST:
+ if (LOG) logerror("uPD1990A '%s' Test Mode not supported!\n", tag());
+
+ if (m_oe)
+ {
+ /* time counter is advanced at 1024 Hz from "Second" counter input */
+ }
+ else
+ {
+ /* each counter is advanced at 1024 Hz in parallel, overflow carry does not affect next counter */
+ }
+
+ break;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// clk_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( upd1990a_device::clk_w )
+{
+ if (LOG) logerror("uPD1990A '%s' CLK %u\n", tag(), state);
+
+ if (!m_clk && state) // rising edge
+ {
+ if (m_c == MODE_SHIFT)
+ {
+ m_shift_reg[0] >>= 1;
+ m_shift_reg[0] |= (BIT(m_shift_reg[1], 0) << 7);
+
+ m_shift_reg[1] >>= 1;
+ m_shift_reg[1] |= (BIT(m_shift_reg[2], 0) << 7);
+
+ m_shift_reg[2] >>= 1;
+ m_shift_reg[2] |= (BIT(m_shift_reg[3], 0) << 7);
+
+ m_shift_reg[3] >>= 1;
+ m_shift_reg[3] |= (BIT(m_shift_reg[4], 0) << 7);
+
+ m_shift_reg[4] >>= 1;
+ m_shift_reg[4] |= (m_data_in << 7);
+
+ if (m_oe)
+ {
+ m_data_out = BIT(m_shift_reg[0], 0);
+
+ if (LOG) logerror("uPD1990A '%s' DATA OUT %u\n", tag(), m_data_out);
+
+ m_out_data_func(m_data_out);
+ }
+ }
+ }
+
+ m_clk = state;
+}
+
+
+//-------------------------------------------------
+// c0_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( upd1990a_device::c0_w )
+{
+ if (LOG) logerror("uPD1990A '%s' C0 %u\n", tag(), state);
+
+ m_c = (m_c & 0x06) | state;
+}
+
+
+//-------------------------------------------------
+// c1_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( upd1990a_device::c1_w )
+{
+ if (LOG) logerror("uPD1990A '%s' C1 %u\n", tag(), state);
+
+ m_c = (m_c & 0x05) | (state << 1);
+}
+
+
+//-------------------------------------------------
+// c2_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( upd1990a_device::c2_w )
+{
+ if (LOG) logerror("uPD1990A '%s' C2 %u\n", tag(), state);
+
+ m_c = (m_c & 0x03) | (state << 2);
+}
+
+
+//-------------------------------------------------
+// data_in_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( upd1990a_device::data_in_w )
+{
+ if (LOG) logerror("uPD1990A '%s' DATA IN %u\n", tag(), state);
+
+ m_data_in = state;
+}
+
+
+//-------------------------------------------------
+// data_out_r -
+//-------------------------------------------------
+
+READ_LINE_MEMBER( upd1990a_device::data_out_r )
+{
+ return m_data_out;
+}
+
+
+//-------------------------------------------------
+// tp_r -
+//-------------------------------------------------
+
+READ_LINE_MEMBER( upd1990a_device::tp_r )
+{
+ return m_tp;
+}
diff --git a/trunk/src/emu/machine/upd1990a.h b/trunk/src/emu/machine/upd1990a.h
new file mode 100644
index 00000000000..2a6654424bc
--- /dev/null
+++ b/trunk/src/emu/machine/upd1990a.h
@@ -0,0 +1,131 @@
+/**********************************************************************
+
+ NEC uPD1990AC Serial I/O Calendar & Clock emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ C2 1 |* \_/ | 14 Vdd
+ C1 2 | | 13 XTAL
+ C0 3 | | 12 _XTAL
+ STB 4 | uPD1990AC | 11 OUT ENBL
+ CS 5 | | 10 TP
+ DATA IN 6 | | 9 DATA OUT
+ GND 7 |_____________| 8 CLK
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __UPD1990A__
+#define __UPD1990A__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_UPD1990A_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD((_tag), UPD1990A, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define UPD1990A_INTERFACE(name) \
+ const upd1990a_interface (name) =
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> upd1990a_interface
+
+struct upd1990a_interface
+{
+ devcb_write_line m_out_data_cb;
+ devcb_write_line m_out_tp_cb;
+};
+
+
+
+// ======================> upd1990a_device
+
+class upd1990a_device : public device_t,
+ public device_rtc_interface,
+ public upd1990a_interface
+{
+public:
+ // construction/destruction
+ upd1990a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_WRITE_LINE_MEMBER( oe_w );
+ DECLARE_WRITE_LINE_MEMBER( cs_w );
+ DECLARE_WRITE_LINE_MEMBER( stb_w );
+ DECLARE_WRITE_LINE_MEMBER( clk_w );
+ DECLARE_WRITE_LINE_MEMBER( c0_w );
+ DECLARE_WRITE_LINE_MEMBER( c1_w );
+ DECLARE_WRITE_LINE_MEMBER( c2_w );
+ DECLARE_WRITE_LINE_MEMBER( data_in_w );
+ DECLARE_READ_LINE_MEMBER( data_out_r );
+ DECLARE_READ_LINE_MEMBER( tp_r );
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+ // device_rtc_interface overrides
+ virtual void rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second);
+ virtual bool rtc_is_year_2000_compliant() { return false; }
+
+private:
+ inline UINT8 convert_to_bcd(int val);
+ inline int bcd_to_integer(UINT8 val);
+ inline void advance_seconds();
+
+ static const device_timer_id TIMER_CLOCK = 0;
+ static const device_timer_id TIMER_TP = 1;
+ static const device_timer_id TIMER_DATA_OUT = 2;
+
+ devcb_resolved_write_line m_out_data_func;
+ devcb_resolved_write_line m_out_tp_func;
+
+ UINT8 m_time_counter[5]; // time counter
+ UINT8 m_shift_reg[5]; // shift register
+
+ int m_oe; // output enable
+ int m_cs; // chip select
+ int m_stb; // strobe
+ int m_data_in; // data in
+ int m_data_out; // data out
+ int m_c; // command
+ int m_clk; // shift clock
+ int m_tp; // time pulse
+
+ // timers
+ emu_timer *m_timer_clock;
+ emu_timer *m_timer_tp;
+ emu_timer *m_timer_data_out;
+};
+
+
+// device type definition
+extern const device_type UPD1990A;
+
+
+
+#endif
diff --git a/trunk/src/emu/machine/upd4701.c b/trunk/src/emu/machine/upd4701.c
new file mode 100644
index 00000000000..10e47dc0a62
--- /dev/null
+++ b/trunk/src/emu/machine/upd4701.c
@@ -0,0 +1,317 @@
+/***************************************************************************
+
+ NEC uPD4701
+
+ Incremental Encoder Control
+
+ 2009-06 Converted to be a device
+
+***************************************************************************/
+
+#include "emu.h"
+#include "upd4701.h"
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _upd4701_state upd4701_state;
+struct _upd4701_state
+{
+ int cs;
+ int xy;
+ int ul;
+ int resetx;
+ int resety;
+ int latchx;
+ int latchy;
+ int startx;
+ int starty;
+ int x;
+ int y;
+ int switches;
+ int latchswitches;
+ int cf;
+};
+
+/* x,y increments can be 12bit (see MASK_COUNTER), hence we need a couple of
+16bit handlers in the following */
+
+#define MASK_SWITCHES ( 7 )
+#define MASK_COUNTER ( 0xfff )
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE upd4701_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert((device->type() == UPD4701));
+ return (upd4701_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ upd4701_ul_w
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER( upd4701_ul_w )
+{
+ upd4701_state *upd4701 = get_safe_token(device);
+ upd4701->ul = data;
+}
+
+/*-------------------------------------------------
+ upd4701_xy_w
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER( upd4701_xy_w )
+{
+ upd4701_state *upd4701 = get_safe_token(device);
+ upd4701->xy = data;
+}
+
+/*-------------------------------------------------
+ upd4701_cs_w
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER( upd4701_cs_w )
+{
+ upd4701_state *upd4701 = get_safe_token(device);
+
+ if (data != upd4701->cs)
+ {
+ upd4701->cs = data;
+
+ if (!upd4701->cs)
+ {
+ upd4701->latchx = (upd4701->x - upd4701->startx) & MASK_COUNTER;
+ upd4701->latchy = (upd4701->y - upd4701->starty) & MASK_COUNTER;
+
+ upd4701->latchswitches = (~upd4701->switches) & MASK_SWITCHES;
+ if (upd4701->latchswitches != 0)
+ {
+ upd4701->latchswitches |= 8;
+ }
+
+ upd4701->cf = 1;
+ }
+ }
+}
+
+/*-------------------------------------------------
+ upd4701_resetx_w
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER( upd4701_resetx_w )
+{
+ upd4701_state *upd4701 = get_safe_token(device);
+
+ if (upd4701->resetx != data)
+ {
+ upd4701->resetx = data;
+
+ if (upd4701->resetx)
+ {
+ upd4701->startx = upd4701->x;
+ }
+ }
+}
+
+/*-------------------------------------------------
+ upd4701_resety_w
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER( upd4701_resety_w )
+{
+ upd4701_state *upd4701 = get_safe_token(device);
+
+ if (upd4701->resety != data)
+ {
+ upd4701->resety = data;
+
+ if (upd4701->resety)
+ {
+ upd4701->starty = upd4701->y;
+ }
+ }
+}
+
+/*-------------------------------------------------
+ upd4701_x_add
+-------------------------------------------------*/
+
+WRITE16_DEVICE_HANDLER( upd4701_x_add )
+{
+ upd4701_state *upd4701 = get_safe_token(device);
+
+ if (!upd4701->resetx && data != 0)
+ {
+ upd4701->x += data;
+
+ if (upd4701->cs)
+ {
+ upd4701->cf = 0;
+ }
+ }
+}
+
+/*-------------------------------------------------
+ upd4701_y_add
+-------------------------------------------------*/
+
+WRITE16_DEVICE_HANDLER( upd4701_y_add )
+{
+ upd4701_state *upd4701 = get_safe_token(device);
+
+ if (!upd4701->resety && data != 0)
+ {
+ upd4701->y += data;
+
+ if (upd4701->cs)
+ {
+ upd4701->cf = 0;
+ }
+ }
+}
+
+/*-------------------------------------------------
+ upd4701_switches_set
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER( upd4701_switches_set )
+{
+ upd4701_state *upd4701 = get_safe_token(device);
+ upd4701->switches = data;
+}
+
+/*-------------------------------------------------
+ upd4701_d_r
+-------------------------------------------------*/
+
+READ16_DEVICE_HANDLER( upd4701_d_r )
+{
+ upd4701_state *upd4701 = get_safe_token(device);
+ int data;
+
+ if (upd4701->cs)
+ {
+ return 0xff;
+ }
+
+ if (upd4701->xy)
+ {
+ data = upd4701->latchy;
+ }
+ else
+ {
+ data = upd4701->latchx;
+ }
+
+ data |= upd4701->latchswitches << 12;
+
+ if (upd4701->ul)
+ {
+ return data >> 8;
+ }
+ else
+ {
+ return data & 0xff;
+ }
+}
+
+/*-------------------------------------------------
+ upd4701_sf_r
+-------------------------------------------------*/
+
+READ8_DEVICE_HANDLER( upd4701_sf_r )
+{
+ upd4701_state *upd4701 = get_safe_token(device);
+
+ if ((upd4701->switches & MASK_SWITCHES) != MASK_SWITCHES)
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+/*-------------------------------------------------
+ upd4701_cf_r
+-------------------------------------------------*/
+
+READ8_DEVICE_HANDLER( upd4701_cf_r )
+{
+ upd4701_state *upd4701 = get_safe_token(device);
+ return upd4701->cf;
+}
+
+/*-------------------------------------------------
+ DEVICE_START( upd4701 )
+-------------------------------------------------*/
+
+static DEVICE_START( upd4701 )
+{
+ upd4701_state *upd4701 = get_safe_token(device);
+
+ /* register for state saving */
+ device->save_item(NAME(upd4701->cs));
+ device->save_item(NAME(upd4701->xy));
+ device->save_item(NAME(upd4701->ul));
+ device->save_item(NAME(upd4701->resetx));
+ device->save_item(NAME(upd4701->resety));
+ device->save_item(NAME(upd4701->latchx));
+ device->save_item(NAME(upd4701->latchy));
+ device->save_item(NAME(upd4701->startx));
+ device->save_item(NAME(upd4701->starty));
+ device->save_item(NAME(upd4701->x));
+ device->save_item(NAME(upd4701->y));
+ device->save_item(NAME(upd4701->switches));
+ device->save_item(NAME(upd4701->latchswitches));
+ device->save_item(NAME(upd4701->cf));
+}
+
+/*-------------------------------------------------
+ DEVICE_RESET( upd4701 )
+-------------------------------------------------*/
+
+static DEVICE_RESET( upd4701 )
+{
+ upd4701_state *upd4701 = get_safe_token(device);
+
+ upd4701->cs = 1;
+ upd4701->xy = 0;
+ upd4701->ul = 0;
+ upd4701->resetx = 0;
+ upd4701->resety = 0;
+ upd4701->latchx = 0;
+ upd4701->latchy = 0;
+ upd4701->startx = 0;
+ upd4701->starty = 0;
+ upd4701->x = 0;
+ upd4701->y = 0;
+ upd4701->switches = 0;
+ upd4701->latchswitches = 0;
+ upd4701->cf = 1;
+}
+
+/*-------------------------------------------------
+ device definition
+-------------------------------------------------*/
+
+static const char DEVTEMPLATE_SOURCE[] = __FILE__;
+
+#define DEVTEMPLATE_ID(p,s) p##upd4701##s
+#define DEVTEMPLATE_FEATURES DT_HAS_START | DT_HAS_RESET
+#define DEVTEMPLATE_NAME "NEC uPD4701 Encoder"
+#define DEVTEMPLATE_FAMILY "NEC uPD4701 Encoder"
+#include "devtempl.h"
+
+
+DEFINE_LEGACY_DEVICE(UPD4701, upd4701);
diff --git a/trunk/src/emu/machine/upd4701.h b/trunk/src/emu/machine/upd4701.h
new file mode 100644
index 00000000000..fd4059fd983
--- /dev/null
+++ b/trunk/src/emu/machine/upd4701.h
@@ -0,0 +1,42 @@
+/***************************************************************************
+
+ NEC uPD4701
+
+ Incremental Encoder Control
+
+***************************************************************************/
+
+#ifndef __UPD4701_H__
+#define __UPD4701_H__
+
+#include "devlegcy.h"
+
+/***************************************************************************
+ MACROS / CONSTANTS
+***************************************************************************/
+
+DECLARE_LEGACY_DEVICE(UPD4701, upd4701);
+
+#define MCFG_UPD4701_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, UPD4701, 0)
+
+
+/***************************************************************************
+ PROTOTYPES
+***************************************************************************/
+
+extern WRITE8_DEVICE_HANDLER( upd4701_cs_w );
+extern WRITE8_DEVICE_HANDLER( upd4701_xy_w );
+extern WRITE8_DEVICE_HANDLER( upd4701_ul_w );
+extern WRITE8_DEVICE_HANDLER( upd4701_resetx_w );
+extern WRITE8_DEVICE_HANDLER( upd4701_resety_w );
+extern WRITE16_DEVICE_HANDLER( upd4701_x_add );
+extern WRITE16_DEVICE_HANDLER( upd4701_y_add );
+extern WRITE8_DEVICE_HANDLER( upd4701_switches_set );
+
+extern READ16_DEVICE_HANDLER( upd4701_d_r );
+extern READ8_DEVICE_HANDLER( upd4701_cf_r );
+extern READ8_DEVICE_HANDLER( upd4701_sf_r );
+
+
+#endif /* __UPD4701_H__ */
diff --git a/trunk/src/emu/machine/upd7201.c b/trunk/src/emu/machine/upd7201.c
new file mode 100644
index 00000000000..d86eb9b81d5
--- /dev/null
+++ b/trunk/src/emu/machine/upd7201.c
@@ -0,0 +1,332 @@
+/**********************************************************************
+
+ NEC uPD7201 Multiprotocol Serial Communications Controller
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+/*
+
+ TODO:
+
+ - this is a clone of Intel 8274?
+ - everything
+
+*/
+
+#include "emu.h"
+#include "upd7201.h"
+#include "machine/devhelpr.h"
+
+
+// device type definition
+const device_type UPD7201 = &device_creator<upd7201_device>;
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+
+enum
+{
+ CHANNEL_A = 0,
+ CHANNEL_B
+};
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// receive -
+//-------------------------------------------------
+
+inline void upd7201_device::receive(int channel)
+{
+}
+
+
+//-------------------------------------------------
+// transmit -
+//-------------------------------------------------
+
+inline void upd7201_device::transmit(int channel)
+{
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// upd7201_device - constructor
+//-------------------------------------------------
+
+upd7201_device::upd7201_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, UPD7201, "UPD7201", tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void upd7201_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const upd7201_interface *intf = reinterpret_cast<const upd7201_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<upd7201_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_out_int_cb, 0, sizeof(m_out_int_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void upd7201_device::device_start()
+{
+ // resolve callbacks
+ m_out_int_func.resolve(m_out_int_cb, *this);
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void upd7201_device::device_reset()
+{
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void upd7201_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case TIMER_RX_A:
+ receive(CHANNEL_A);
+ break;
+
+ case TIMER_TX_A:
+ transmit(CHANNEL_A);
+ break;
+
+ case TIMER_RX_B:
+ receive(CHANNEL_B);
+ break;
+
+ case TIMER_TX_B:
+ transmit(CHANNEL_B);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// cd_ba_r -
+//-------------------------------------------------
+
+READ8_MEMBER( upd7201_device::cd_ba_r )
+{
+ return 0;
+}
+
+
+//-------------------------------------------------
+// cd_ba_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( upd7201_device::cd_ba_w )
+{
+}
+
+
+//-------------------------------------------------
+// ba_cd_r -
+//-------------------------------------------------
+
+READ8_MEMBER( upd7201_device::ba_cd_r )
+{
+ return 0;
+}
+
+
+//-------------------------------------------------
+// ba_cd_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( upd7201_device::ba_cd_w )
+{
+}
+
+
+//-------------------------------------------------
+// intak_r -
+//-------------------------------------------------
+
+READ8_MEMBER( upd7201_device::intak_r )
+{
+ return 0;
+}
+
+
+//-------------------------------------------------
+// synca_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( upd7201_device::synca_w )
+{
+}
+
+
+//-------------------------------------------------
+// syncb_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( upd7201_device::syncb_w )
+{
+}
+
+
+//-------------------------------------------------
+// ctsa_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( upd7201_device::ctsa_w )
+{
+}
+
+
+//-------------------------------------------------
+// ctsb_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( upd7201_device::ctsb_w )
+{
+}
+
+
+//-------------------------------------------------
+// dtra_r -
+//-------------------------------------------------
+
+READ_LINE_MEMBER( upd7201_device::dtra_r )
+{
+ return 0;
+}
+
+
+//-------------------------------------------------
+// dtrb_r -
+//-------------------------------------------------
+
+READ_LINE_MEMBER( upd7201_device::dtrb_r )
+{
+ return 0;
+}
+
+
+//-------------------------------------------------
+// hai_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( upd7201_device::hai_w )
+{
+}
+
+
+//-------------------------------------------------
+// rxda_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( upd7201_device::rxda_w )
+{
+}
+
+
+//-------------------------------------------------
+// txda_r -
+//-------------------------------------------------
+
+READ_LINE_MEMBER( upd7201_device::txda_r )
+{
+ return 0;
+}
+
+
+//-------------------------------------------------
+// rxdb_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( upd7201_device::rxdb_w )
+{
+}
+
+
+//-------------------------------------------------
+// txdb_r -
+//-------------------------------------------------
+
+READ_LINE_MEMBER( upd7201_device::txdb_r )
+{
+ return 0;
+}
+
+
+//-------------------------------------------------
+// rxca_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( upd7201_device::rxca_w )
+{
+}
+
+
+//-------------------------------------------------
+// rxcb_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( upd7201_device::rxcb_w )
+{
+}
+
+
+//-------------------------------------------------
+// txca_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( upd7201_device::txca_w )
+{
+}
+
+
+//-------------------------------------------------
+// txcb_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( upd7201_device::txcb_w )
+{
+}
diff --git a/trunk/src/emu/machine/upd7201.h b/trunk/src/emu/machine/upd7201.h
new file mode 100644
index 00000000000..90d65d53f7d
--- /dev/null
+++ b/trunk/src/emu/machine/upd7201.h
@@ -0,0 +1,151 @@
+/**********************************************************************
+
+ NEC uPD7201 Multiprotocol Serial Communications Controller
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ CLK 1 |* \_/ | 40 Vcc
+ _RESET 2 | | 39 _CTSA
+ _DCDA 3 | | 38 _RTSA
+ _RxCB 4 | | 37 TxDA
+ _DCDB 5 | | 36 _TxCA
+ _CTSB 6 | | 35 _RxCA
+ _TxCB 7 | | 34 RxDA
+ TxDB 8 | | 33 _SYNCA
+ RxDB 9 | | 32 _WAITA/DRQRxA
+ _RTSB/_SYNCB 10 | UPD7201 | 31 _DTRA/_HAO
+ _WAITB/_DRQTxA 11 | | 30 _PRO/DRQTxB
+ D7 12 | | 29 _PRI/DRQRxB
+ D6 13 | | 28 _INT
+ D5 14 | | 27 _INTAK
+ D4 15 | | 26 _DTRB/_HAI
+ D3 16 | | 25 B/_A
+ D2 17 | | 24 C/_D
+ D1 18 | | 23 _CS
+ D0 19 | | 22 _RD
+ Vss 20 |_____________| 21 _WR
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __UPD7201__
+#define __UPD7201__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_UPD7201_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD((_tag), UPD7201, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define UPD7201_INTERFACE(name) \
+ const upd7201_interface (name) =
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> upd7201_interface
+
+struct upd7201_interface
+{
+ devcb_write_line m_out_int_cb;
+
+ struct
+ {
+ int m_rx_clock;
+ int m_tx_clock;
+
+ devcb_write_line m_out_drqrx_cb;
+ devcb_write_line m_out_drqtx_cb;
+
+ devcb_read_line m_in_rxd_cb;
+ devcb_write_line m_out_txd_cb;
+
+ devcb_read_line m_in_cts_cb;
+ devcb_read_line m_in_dcd_cb;
+ devcb_write_line m_out_rts_cb;
+ devcb_write_line m_out_dtr_cb;
+
+ devcb_write_line m_out_wait_cb;
+ devcb_write_line m_out_sync_cb;
+ } m_channel[2];
+};
+
+
+
+// ======================> upd7201_device
+
+class upd7201_device : public device_t,
+ public upd7201_interface
+{
+public:
+ // construction/destruction
+ upd7201_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_READ8_MEMBER( cd_ba_r );
+ DECLARE_WRITE8_MEMBER( cd_ba_w );
+ DECLARE_READ8_MEMBER( ba_cd_r );
+ DECLARE_WRITE8_MEMBER( ba_cd_w );
+
+ DECLARE_READ8_MEMBER( intak_r );
+
+ DECLARE_WRITE_LINE_MEMBER( synca_w );
+ DECLARE_WRITE_LINE_MEMBER( syncb_w );
+ DECLARE_WRITE_LINE_MEMBER( ctsa_w );
+ DECLARE_WRITE_LINE_MEMBER( ctsb_w );
+ DECLARE_READ_LINE_MEMBER( dtra_r );
+ DECLARE_READ_LINE_MEMBER( dtrb_r );
+ DECLARE_WRITE_LINE_MEMBER( hai_w );
+ DECLARE_WRITE_LINE_MEMBER( rxda_w );
+ DECLARE_READ_LINE_MEMBER( txda_r );
+ DECLARE_WRITE_LINE_MEMBER( rxdb_w );
+ DECLARE_READ_LINE_MEMBER( txdb_r );
+ DECLARE_WRITE_LINE_MEMBER( rxca_w );
+ DECLARE_WRITE_LINE_MEMBER( rxcb_w );
+ DECLARE_WRITE_LINE_MEMBER( txca_w );
+ DECLARE_WRITE_LINE_MEMBER( txcb_w );
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int m_param, void *ptr);
+
+private:
+ static const device_timer_id TIMER_RX_A = 0;
+ static const device_timer_id TIMER_TX_A = 1;
+ static const device_timer_id TIMER_RX_B = 2;
+ static const device_timer_id TIMER_TX_B = 3;
+
+ inline void receive(int channel);
+ inline void transmit(int channel);
+
+ devcb_resolved_write_line m_out_int_func;
+
+ // timers
+ emu_timer *m_rx_a_timer;
+ emu_timer *m_tx_a_timer;
+ emu_timer *m_rx_b_timer;
+ emu_timer *m_tx_b_timer;
+};
+
+
+// device type definition
+extern const device_type UPD7201;
+
+
+
+#endif
diff --git a/trunk/src/emu/machine/wd17xx.c b/trunk/src/emu/machine/wd17xx.c
new file mode 100644
index 00000000000..8403d6e8183
--- /dev/null
+++ b/trunk/src/emu/machine/wd17xx.c
@@ -0,0 +1,2264 @@
+/***************************************************************************
+
+ wd17xx.c
+
+ Implementations of the Western Digital 17xx and 27xx families of
+ floppy disk controllers
+
+
+ Models:
+
+ DAL DD Side Clock Remark
+ ---------------------------------------------------------
+ FD1771 1 or 2 MHz First model
+ FD1781 x 1 or 2 MHz
+ FD1791 x 1 or 2 MHz
+ FD1792 1 or 2 MHz
+ FD1793 x x 1 or 2 MHz
+ FD1794 x 1 or 2 MHz
+ FD1795 x x 1 or 2 MHz
+ FD1797 x x x 1 or 2 MHz
+ FD1761 x 1 MHz
+ FD1762 1 MHz ?
+ FD1763 x x 1 MHz
+ FD1764 x 1 MHz ?
+ FD1765 x x 1 MHz
+ FD1767 x x x 1 MHz
+ WD2791 x 1 or 2 MHz Internal data separator
+ WD2793 x x 1 or 2 MHz Internal data separator
+ WD2795 x x 1 or 2 MHz Internal data separator
+ WD2797 x x x 1 or 2 MHz Internal data separator
+ WD1770 x x 8 MHz Motor On signal
+ WD1772 x x 8 MHz Motor On signal, Faster stepping rates
+ WD1773 x x 8 MHz Enable precomp line
+
+ Notes: - In general, later models include all features of earlier models
+ - DAL: Data access lines, x = TRUE; otherwise inverted
+ - DD: Double density support
+ - Side: Has side select support
+ - ?: Unknown if it really exists
+
+ Clones:
+
+ - SMC FD179x
+ - Fujitsu MB8876 -> FD1791, MB8877 -> FD1793
+ - VLSI VL177x
+
+
+ Changelog:
+
+ Kevin Thacker
+ - Removed disk image code and replaced it with floppy drive functions.
+ Any disc image is now useable with this code.
+ - Fixed write protect
+
+ 2005-Apr-16 P.Harvey-Smith:
+ - Increased the delay in wd17xx_timed_read_sector_request and
+ wd17xx_timed_write_sector_request, to 40us to more closely match
+ what happens on the real hardware, this has fixed the NitrOS9 boot
+ problems.
+
+ 2007-Nov-01 Wilbert Pol:
+ Needed these changes to get the MB8877 for Osborne-1 to work:
+ - Added support for multiple record read
+ - Changed the wd17xx_read_id to not return after DATADONEDELAY, but
+ the host should read the id data through the data register. This
+ was accomplished by making this change in the wd17xx_read_id
+ function:
+ - wd17xx_complete_command(device, DELAY_DATADONE);
+ + wd17xx_set_data_request();
+
+ 2009-May-10 Robbbert:
+ Further change to get the Kaypro II to work
+ - When wd17xx_read_id has generated the 6 data bytes, it should make
+ an IRQ and turn off the busy status. The timing for Osborne is
+ critical, it must be between 300 and 700 usec, I've settled on 400.
+ The Kaypro doesn't care timewise, but the busy flag must turn off
+ sometime or it hangs.
+ - w->status |= STA_2_BUSY;
+ + wd17xx_set_busy(device, attotime::from_usec(400));
+
+ 2009-June-4 Roberto Lavarone:
+ - Initial support for wd1771
+ - Added simulation of head loaded feedback from drive
+ - Bugfix: busy flag was cleared too early
+
+ 2009-June-21 Robbbert:
+ - The Bugfix above, while valid, caused the Osborne1 to fail. This
+ is because the delay must not exceed 14usec (found by extensive testing).
+ - The minimum delay is 1usec, need by z80netf while formatting a disk.
+ - http://www.bannister.org/forums/ubbthreads.php?ubb=showflat&Number=50889#Post50889
+ explains the problems, testing done, and the test procedure for the z80netf.
+ - Thus, the delay is set to 10usec, and all the disks I have (not many)
+ seem to work.
+ - Note to anyone who wants to change something: Make sure that the
+ Osborne1 boots up! It is extremely sensitive to timing!
+ - For testing only: The osborne1 rom can be patched to make it much
+ more stable, by changing the byte at 0x0da7 from 0x28 to 0x18.
+
+ 2009-June-25 Robbbert:
+ - Turns out kayproii not working, 10usec is too short.. but 11usec is ok.
+ Setting it to 12usec.
+ Really, this whole thing needs a complete rewrite.
+
+ 2009-July-08 Roberto Lavarone:
+ - Fixed a bug in head load flag handling: einstein and samcoupe now working again
+
+ 2009-September-30 Robbbert:
+ - Modified what status flags are returned after a Forced Interrupt,
+ to allow Microbee to boot CP/M.
+
+ 2010-Jan-31 Phill Harvey-Smith
+ - The above bugfixes for the Kaypro/Osborne1 have borked the booting on the Dragon
+ Alpha. The Alpha it seems needs a delay of ay least 17us or the NMI generated by
+ INTRQ happens too early and doen't break out of the read/write bytes loops.
+
+ I have made the delay settable by calling wd17xx_set_complete_command_delay, and
+ let it default to 12us, as required above, so that the Dragon Alpha works again.
+ This hopefully should not break the other machines.
+
+ This should probably be considdered a minor hack but it does seem to work !
+
+ 2010-02-04 Phill Harvey-Smith
+ - Added multiple sector write as the RM Nimbus needs it.
+
+ 2010-March-22 Curt Coder:
+ - Implemented immediate and index pulse interrupts.
+
+ 2010-Dec-31 Phill Harvey-Smith
+ - Copied multi-sector write code from r7263, for some reason this had been
+ silently removed, but is required for the rmnimbus driver.
+
+ 2011-Mar-08 Phill Harvey-Smith
+ - Triggering intrq now clears the DRQ bit in the status as well as the busy bit.
+ Execution of the READ_DAM command now correctly sets w->command.
+
+ 2011-Apr-01 Curt Coder
+ - Set complete command delay to 16 usec (DD) / 32 usec (SD) and removed
+ the external delay setting hack.
+
+ 2011-Jun-24 Curt Coder
+ - Added device types for all known variants, and enforced inverted DAL lines.
+
+ TODO:
+ - What happens if a track is read that doesn't have any id's on it?
+ (e.g. unformatted disc)
+ - Rewrite into a C++ device
+
+***************************************************************************/
+
+
+#include "emu.h"
+#include "formats/imageutl.h"
+#include "machine/wd17xx.h"
+#include "imagedev/flopdrv.h"
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define VERBOSE 0 /* General logging */
+#define VERBOSE_DATA 0 /* Logging of each byte during read and write */
+
+#define DELAY_ERROR 3
+#define DELAY_NOTREADY 1
+#define DELAY_DATADONE 3
+
+#define TYPE_I 1
+#define TYPE_II 2
+#define TYPE_III 3
+#define TYPE_IV 4
+
+#define FDC_STEP_RATE 0x03 /* Type I additional flags */
+#define FDC_STEP_VERIFY 0x04 /* verify track number */
+#define FDC_STEP_HDLOAD 0x08 /* load head */
+#define FDC_STEP_UPDATE 0x10 /* update track register */
+
+#define FDC_RESTORE 0x00 /* Type I commands */
+#define FDC_SEEK 0x10
+#define FDC_STEP 0x20
+#define FDC_STEP_IN 0x40
+#define FDC_STEP_OUT 0x60
+
+#define FDC_MASK_TYPE_I (FDC_STEP_HDLOAD|FDC_STEP_VERIFY|FDC_STEP_RATE)
+
+/* Type I commands status */
+#define STA_1_BUSY 0x01 /* controller is busy */
+#define STA_1_IPL 0x02 /* index pulse */
+#define STA_1_TRACK0 0x04 /* track 0 detected */
+#define STA_1_CRC_ERR 0x08 /* CRC error */
+#define STA_1_SEEK_ERR 0x10 /* seek error */
+#define STA_1_HD_LOADED 0x20 /* head loaded */
+#define STA_1_WRITE_PRO 0x40 /* floppy is write protected */
+#define STA_1_NOT_READY 0x80 /* drive not ready */
+#define STA_1_MOTOR_ON 0x80 /* status of the Motor On output (WD1770 and WD1772 only) */
+
+/* Type II and III additional flags */
+#define FDC_DELETED_AM 0x01 /* read/write deleted address mark */
+#define FDC_SIDE_CMP_T 0x02 /* side compare track data */
+#define FDC_15MS_DELAY 0x04 /* delay 15ms before command */
+#define FDC_SIDE_CMP_S 0x08 /* side compare sector data */
+#define FDC_MULTI_REC 0x10 /* only for type II commands */
+
+/* Type II commands */
+#define FDC_READ_SEC 0x80 /* read sector */
+#define FDC_WRITE_SEC 0xA0 /* write sector */
+
+#define FDC_MASK_TYPE_II (FDC_MULTI_REC|FDC_SIDE_CMP_S|FDC_15MS_DELAY|FDC_SIDE_CMP_T|FDC_DELETED_AM)
+
+/* Type II commands status */
+#define STA_2_BUSY 0x01
+#define STA_2_DRQ 0x02
+#define STA_2_LOST_DAT 0x04
+#define STA_2_CRC_ERR 0x08
+#define STA_2_REC_N_FND 0x10
+#define STA_2_REC_TYPE 0x20
+#define STA_2_WRITE_PRO 0x40
+#define STA_2_NOT_READY 0x80
+
+#define FDC_MASK_TYPE_III (FDC_SIDE_CMP_S|FDC_15MS_DELAY|FDC_SIDE_CMP_T|FDC_DELETED_AM)
+
+/* Type III commands */
+#define FDC_READ_DAM 0xc0 /* read data address mark */
+#define FDC_READ_TRK 0xe0 /* read track */
+#define FDC_WRITE_TRK 0xf0 /* write track (format) */
+
+/* Type IV additional flags */
+#define FDC_IM0 0x01 /* interrupt mode 0 */
+#define FDC_IM1 0x02 /* interrupt mode 1 */
+#define FDC_IM2 0x04 /* interrupt mode 2 */
+#define FDC_IM3 0x08 /* interrupt mode 3 */
+
+#define FDC_MASK_TYPE_IV (FDC_IM3|FDC_IM2|FDC_IM1|FDC_IM0)
+
+/* Type IV commands */
+#define FDC_FORCE_INT 0xd0 /* force interrupt */
+
+/* structure describing a double density track */
+#define TRKSIZE_DD 6144
+#if 0
+static const UINT8 track_DD[][2] = {
+ {16, 0x4e}, /* 16 * 4E (track lead in) */
+ { 8, 0x00}, /* 8 * 00 (pre DAM) */
+ { 3, 0xf5}, /* 3 * F5 (clear CRC) */
+
+ { 1, 0xfe}, /* *** sector *** FE (DAM) */
+ { 1, 0x80}, /* 4 bytes track,head,sector,seclen */
+ { 1, 0xf7}, /* 1 * F7 (CRC) */
+ {22, 0x4e}, /* 22 * 4E (sector lead in) */
+ {12, 0x00}, /* 12 * 00 (pre AM) */
+ { 3, 0xf5}, /* 3 * F5 (clear CRC) */
+ { 1, 0xfb}, /* 1 * FB (AM) */
+ { 1, 0x81}, /* x bytes sector data */
+ { 1, 0xf7}, /* 1 * F7 (CRC) */
+ {16, 0x4e}, /* 16 * 4E (sector lead out) */
+ { 8, 0x00}, /* 8 * 00 (post sector) */
+ { 0, 0x00}, /* end of data */
+};
+#endif
+
+/* structure describing a single density track */
+#define TRKSIZE_SD 3172
+#if 0
+static const UINT8 track_SD[][2] = {
+ {16, 0xff}, /* 16 * FF (track lead in) */
+ { 8, 0x00}, /* 8 * 00 (pre DAM) */
+ { 1, 0xfc}, /* 1 * FC (clear CRC) */
+
+ {11, 0xff}, /* *** sector *** 11 * FF */
+ { 6, 0x00}, /* 6 * 00 (pre DAM) */
+ { 1, 0xfe}, /* 1 * FE (DAM) */
+ { 1, 0x80}, /* 4 bytes track,head,sector,seclen */
+ { 1, 0xf7}, /* 1 * F7 (CRC) */
+ {10, 0xff}, /* 10 * FF (sector lead in) */
+ { 4, 0x00}, /* 4 * 00 (pre AM) */
+ { 1, 0xfb}, /* 1 * FB (AM) */
+ { 1, 0x81}, /* x bytes sector data */
+ { 1, 0xf7}, /* 1 * F7 (CRC) */
+ { 0, 0x00}, /* end of data */
+};
+#endif
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _wd1770_state wd1770_state;
+struct _wd1770_state
+{
+ /* callbacks */
+ devcb_resolved_read_line in_dden_func;
+ devcb_resolved_write_line out_intrq_func;
+ devcb_resolved_write_line out_drq_func;
+
+ /* input lines */
+ int mr; /* master reset */
+ int rdy; /* ready, enable precomp */
+ int tr00; /* track 00 */
+ int idx; /* index */
+ int wprt; /* write protect */
+ int dden; /* double density */
+
+ /* output lines */
+ int mo; /* motor on */
+ int dirc; /* direction */
+ int drq; /* data request */
+ int intrq; /* interrupt request */
+
+ /* register */
+ UINT8 data_shift;
+ UINT8 data;
+ UINT8 track;
+ UINT8 sector;
+ UINT8 command;
+ UINT8 status;
+ UINT8 interrupt;
+
+ int stepping_rate[4]; /* track stepping rate in ms */
+
+ unsigned short crc; /* Holds the current CRC value for write_track CRC calculation */
+ int crc_active; /* Flag indicating that CRC calculation in write_track is active. */
+
+ UINT8 track_reg; /* value of track register */
+ UINT8 command_type; /* last command type */
+ UINT8 head; /* current head # */
+
+ UINT8 read_cmd; /* last read command issued */
+ UINT8 write_cmd; /* last write command issued */
+ INT8 direction; /* last step direction */
+ UINT8 last_command_data; /* last command data */
+
+ UINT8 status_drq; /* status register data request bit */
+ UINT8 busy_count; /* how long to keep busy bit set */
+
+ UINT8 buffer[6144]; /* I/O buffer (holds up to a whole track) */
+ UINT32 data_offset; /* offset into I/O buffer */
+ INT32 data_count; /* transfer count from/into I/O buffer */
+
+ UINT8 *fmt_sector_data[256]; /* pointer to data after formatting a track */
+
+ UINT8 dam_list[256][4]; /* list of data address marks while formatting */
+ int dam_data[256]; /* offset to data inside buffer while formatting */
+ int dam_cnt; /* valid number of entries in the dam_list */
+ UINT16 sector_length; /* sector length (byte) */
+
+ UINT8 ddam; /* ddam of sector found - used when reading */
+ UINT8 sector_data_id;
+ int data_direction;
+
+ int hld_count; /* head loaded counter */
+
+ /* timers to delay execution/completion of commands */
+ emu_timer *timer_cmd, *timer_data, *timer_rs, *timer_ws;
+
+ /* this is the drive currently selected */
+ device_t *drive;
+
+ /* this is the head currently selected */
+ UINT8 hd;
+
+ /* pause time when writing/reading sector */
+ int pause_time;
+
+ /* Were we busy when we received a FORCE_INT command */
+ UINT8 was_busy;
+
+ /* Pointer to interface */
+ const wd17xx_interface *intf;
+};
+
+
+/***************************************************************************
+ DEFAULT INTERFACES
+***************************************************************************/
+
+const wd17xx_interface default_wd17xx_interface =
+{
+ DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, { FLOPPY_0, FLOPPY_1, FLOPPY_2, FLOPPY_3}
+};
+
+const wd17xx_interface default_wd17xx_interface_2_drives =
+{
+ DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, { FLOPPY_0, FLOPPY_1, NULL, NULL}
+};
+
+
+/***************************************************************************
+ PROTOTYPES
+***************************************************************************/
+
+static void wd17xx_complete_command(device_t *device, int delay);
+static void wd17xx_timed_data_request(device_t *device);
+static int wd17xx_locate_sector(device_t *device);
+static void wd17xx_timed_read_sector_request(device_t *device);
+
+
+/*****************************************************************************
+ INLINE FUNCTIONS
+*****************************************************************************/
+
+INLINE wd1770_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == FD1771 || device->type() == FD1781 ||
+ device->type() == FD1791 || device->type() == FD1792 || device->type() == FD1793 || device->type() == FD1794 || device->type() == FD1795 || device->type() == FD1797 ||
+ device->type() == FD1761 || device->type() == FD1762 || device->type() == FD1763 || device->type() == FD1764 || device->type() == FD1765 || device->type() == FD1767 ||
+ device->type() == WD2791 || device->type() == WD2793 || device->type() == WD2795 || device->type() == WD2797 ||
+ device->type() == WD1770 || device->type() == WD1772 || device->type() == WD1773 ||
+ device->type() == MB8866 || device->type() == MB8876 || device->type() == MB8877);
+
+ return (wd1770_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+/***************************************************************************
+ HELPER FUNCTIONS
+***************************************************************************/
+
+static int wd17xx_has_dal(device_t *device)
+{
+ return (device->type() == FD1793 || device->type() == FD1794 || device->type() == FD1797 ||
+ device->type() == FD1763 || device->type() == FD1764 || device->type() == FD1767 ||
+ device->type() == WD1770 || device->type() == WD1772 || device->type() == WD1773 ||
+ device->type() == WD2793 || device->type() == WD2797 ||
+ device->type() == MB8877);
+}
+
+static int wd17xx_is_sd_only(device_t *device)
+{
+ return (device->type() == FD1771 || device->type() == FD1792 || device->type() == FD1794 || device->type() == FD1762 || device->type() == FD1764);
+}
+
+static int wd17xx_has_side_select(device_t *device)
+{
+ return (device->type() == FD1795 || device->type() == FD1797 ||
+ device->type() == FD1765 || device->type() == FD1767 ||
+ device->type() == WD2795 || device->type() == WD2797);
+}
+
+static int wd17xx_dden(device_t *device)
+{
+ wd1770_state *w = get_safe_token(device);
+
+ if (!w->in_dden_func.isnull())
+ return w->in_dden_func();
+ else
+ return w->dden;
+}
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+/* clear a data request */
+static void wd17xx_clear_drq(device_t *device)
+{
+ wd1770_state *w = get_safe_token(device);
+
+ w->status &= ~STA_2_DRQ;
+
+ w->drq = CLEAR_LINE;
+ w->out_drq_func(w->drq);
+}
+
+/* set data request */
+static void wd17xx_set_drq(device_t *device)
+{
+ wd1770_state *w = get_safe_token(device);
+
+ if (w->status & STA_2_DRQ)
+ w->status |= STA_2_LOST_DAT;
+
+ w->status |= STA_2_DRQ;
+
+ w->drq = ASSERT_LINE;
+ w->out_drq_func(w->drq);
+}
+
+/* clear interrupt request */
+static void wd17xx_clear_intrq(device_t *device)
+{
+ wd1770_state *w = get_safe_token(device);
+
+ w->intrq = CLEAR_LINE;
+ w->out_intrq_func(w->intrq);
+}
+
+/* set interrupt request */
+static void wd17xx_set_intrq(device_t *device)
+{
+ wd1770_state *w = get_safe_token(device);
+
+ w->status &= ~STA_2_BUSY;
+ w->status &= ~STA_2_DRQ;
+
+ w->intrq = ASSERT_LINE;
+ w->out_intrq_func(w->intrq);
+}
+
+/* set intrq after delay */
+static TIMER_CALLBACK( wd17xx_command_callback )
+{
+ device_t *device = (device_t *)ptr;
+ wd1770_state *w = get_safe_token(device);
+
+ if (w->last_command_data != FDC_FORCE_INT)
+ {
+ wd17xx_set_intrq(device);
+ }
+}
+
+/* write next byte to data register and set drq */
+static TIMER_CALLBACK( wd17xx_data_callback )
+{
+ device_t *device = (device_t *)ptr;
+ wd1770_state *w = get_safe_token(device);
+
+ /* check if this is a write command */
+ if( (w->command_type == TYPE_II && w->command == FDC_WRITE_SEC) ||
+ (w->command_type == TYPE_III && w->command == FDC_WRITE_TRK) )
+ {
+ /* we are ready for new data */
+ wd17xx_set_drq(device);
+
+ return;
+ }
+
+ /* any bytes remaining? */
+ if (w->data_count >= 1)
+ {
+ /* yes */
+ w->data = w->buffer[w->data_offset++];
+
+ if (VERBOSE_DATA)
+ logerror("wd17xx_data_callback: $%02X (data_count %d)\n", w->data, w->data_count);
+
+ wd17xx_set_drq(device);
+
+ /* any bytes remaining? */
+ if (--w->data_count < 1)
+ {
+ /* no */
+ w->data_offset = 0;
+
+ /* clear ddam type */
+ w->status &=~STA_2_REC_TYPE;
+
+ /* read a sector with ddam set? */
+ if (w->command_type == TYPE_II && w->ddam != 0)
+ {
+ /* set it */
+ w->status |= STA_2_REC_TYPE;
+ }
+
+ /* check if we should handle the next sector for a multi record read */
+ if (w->command_type == TYPE_II && w->command == FDC_READ_SEC && (w->read_cmd & 0x10))
+ {
+ if (VERBOSE)
+ logerror("wd17xx_data_callback: multi sector read\n");
+
+ if (w->sector == 0xff)
+ w->sector = 0x01;
+ else
+ w->sector++;
+
+ wd17xx_timed_read_sector_request(device);
+ }
+ else
+ {
+ /* Delay the INTRQ 3 byte times because we need to read two CRC bytes and
+ compare them with a calculated CRC */
+ wd17xx_complete_command(device, DELAY_DATADONE);
+
+ if (VERBOSE)
+ logerror("wd17xx_data_callback: data read completed\n");
+ }
+ }
+ else
+ {
+ /* requeue us for more data */
+ w->timer_data->adjust(attotime::from_usec(wd17xx_dden(device) ? 128 : 32));
+ }
+ }
+ else
+ {
+ logerror("wd17xx_data_callback: (no new data) $%02X (data_count %d)\n", w->data, w->data_count);
+ }
+}
+
+
+static void wd17xx_set_busy(device_t *device, attotime duration)
+{
+ wd1770_state *w = get_safe_token(device);
+
+ w->status |= STA_1_BUSY;
+
+ w->timer_cmd->adjust(duration);
+}
+
+
+/* BUSY COUNT DOESN'T WORK PROPERLY! */
+
+static void wd17xx_command_restore(device_t *device)
+{
+ wd1770_state *w = get_safe_token(device);
+ UINT8 step_counter;
+
+ if (w->drive == NULL)
+ return;
+
+ step_counter = 255;
+
+#if 0
+ w->status |= STA_1_BUSY;
+#endif
+
+ /* setup step direction */
+ w->direction = -1;
+
+ w->command_type = TYPE_I;
+
+ /* reset busy count */
+ w->busy_count = 0;
+
+ if (1) // image_slotexists(w->drive) : FIXME
+ {
+ /* keep stepping until track 0 is received or 255 steps have been done */
+ while (floppy_tk00_r(w->drive) && (step_counter != 0))
+ {
+ /* update time to simulate seek time busy signal */
+ w->busy_count++;
+ floppy_drive_seek(w->drive, w->direction);
+ step_counter--;
+ }
+ }
+
+ /* update track reg */
+ w->track = 0;
+#if 0
+ /* simulate seek time busy signal */
+ w->busy_count = 0; //w->busy_count * ((w->data & FDC_STEP_RATE) + 1);
+
+ /* when command completes set irq */
+ wd17xx_set_intrq(device);
+#endif
+ wd17xx_set_busy(device, attotime::from_usec(100));
+}
+
+/*
+ Write an entire track. Formats which do not define a write_track
+ function pointer will cause a silent return.
+ What is written to the image depends on the selected format. Sector
+ dumps have to extract the sectors in the track, while track dumps
+ may directly write the bytes.
+ (The if-part below may thus be removed.)
+*/
+static void write_track(device_t *device)
+{
+ wd1770_state *w = get_safe_token(device);
+ floppy_image_legacy *floppy;
+#if 0
+ int i;
+ for (i=0;i+4<w->data_offset;)
+ {
+ if (w->buffer[i]==0xfe)
+ {
+ /* got address mark */
+ int track = w->buffer[i+1];
+ int side = w->buffer[i+2];
+ int sector = w->buffer[i+3];
+ //int len = w->buffer[i+4];
+ int filler = 0xe5; /* IBM and Thomson */
+ int density = w->density;
+ floppy_drive_format_sector(w->drive,side,sector,track,
+ w->hd,sector,density?1:0,filler);
+ i += 128; /* at least... */
+ }
+ else
+ i++;
+ }
+#endif
+
+ /* Get the size in bytes of the current track. For real hardware this
+ may vary per system in small degree, and there even for each track
+ and head, so we should not assume a fixed value here.
+ As we are using a buffered track writing, we have to find out how long
+ the track will become. The only object which can tell us is the
+ selected format.
+ */
+ w->data_count = 0;
+ floppy = flopimg_get_image(w->drive);
+ if (floppy != NULL)
+ w->data_count = floppy_get_track_size(floppy, w->hd, w->track);
+
+ if (w->data_count==0)
+ {
+ if (wd17xx_is_sd_only(device))
+ w->data_count = TRKSIZE_SD;
+ else
+ w->data_count = wd17xx_dden(device) ? TRKSIZE_SD : TRKSIZE_DD;
+ }
+
+ floppy_drive_write_track_data_info_buffer( w->drive, w->hd, (char *)w->buffer, &(w->data_count) );
+
+ w->data_offset = 0;
+
+ wd17xx_set_drq(device);
+ w->status |= STA_2_BUSY;
+ w->busy_count = 0;
+}
+
+/*
+ Read an entire track. It is up to the format to deliver the data. Sector
+ dumps may be required to fantasize the missing track bytes, while track
+ dumps can directly deliver them.
+ (The if-part below may thus be removed.)
+*/
+static void read_track(device_t *device)
+{
+ wd1770_state *w = get_safe_token(device);
+ floppy_image_legacy *floppy;
+#if 0
+ UINT8 *psrc; /* pointer to track format structure */
+ UINT8 *pdst; /* pointer to track buffer */
+ int cnt; /* number of bytes to fill in */
+ UINT16 crc; /* id or data CRC */
+ UINT8 d; /* data */
+ UINT8 t = w->track; /* track of DAM */
+ UINT8 h = w->head; /* head of DAM */
+ UINT8 s = w->sector_dam; /* sector of DAM */
+ UINT16 l = w->sector_length; /* sector length of DAM */
+ int i;
+
+ for (i = 0; i < w->sec_per_track; i++)
+ {
+ w->dam_list[i][0] = t;
+ w->dam_list[i][1] = h;
+ w->dam_list[i][2] = i;
+ w->dam_list[i][3] = l >> 8;
+ }
+
+ pdst = w->buffer;
+
+ if (w->density)
+ {
+ psrc = track_DD[0]; /* double density track format */
+ cnt = TRKSIZE_DD;
+ }
+ else
+ {
+ psrc = track_SD[0]; /* single density track format */
+ cnt = TRKSIZE_SD;
+ }
+
+ while (cnt > 0)
+ {
+ if (psrc[0] == 0) /* no more track format info ? */
+ {
+ if (w->dam_cnt < w->sec_per_track) /* but more DAM info ? */
+ {
+ if (w->density)/* DD track ? */
+ psrc = track_DD[3];
+ else
+ psrc = track_SD[3];
+ }
+ }
+
+ if (psrc[0] != 0) /* more track format info ? */
+ {
+ cnt -= psrc[0]; /* subtract size */
+ d = psrc[1];
+
+ if (d == 0xf5) /* clear CRC ? */
+ {
+ crc = 0xffff;
+ d = 0xa1; /* store A1 */
+ }
+
+ for (i = 0; i < *psrc; i++)
+ *pdst++ = d; /* fill data */
+
+ if (d == 0xf7) /* store CRC ? */
+ {
+ pdst--; /* go back one byte */
+ *pdst++ = crc & 255; /* put CRC low */
+ *pdst++ = crc / 256; /* put CRC high */
+ cnt -= 1; /* count one more byte */
+ }
+ else if (d == 0xfe)/* address mark ? */
+ {
+ crc = 0xffff; /* reset CRC */
+ }
+ else if (d == 0x80)/* sector ID ? */
+ {
+ pdst--; /* go back one byte */
+ t = *pdst++ = w->dam_list[w->dam_cnt][0]; /* track number */
+ h = *pdst++ = w->dam_list[w->dam_cnt][1]; /* head number */
+ s = *pdst++ = w->dam_list[w->dam_cnt][2]; /* sector number */
+ l = *pdst++ = w->dam_list[w->dam_cnt][3]; /* sector length code */
+ w->dam_cnt++;
+ crc = ccitt_crc16_one(crc, t); /* build CRC */
+ crc = ccitt_crc16_one(crc, h); /* build CRC */
+ crc = ccitt_crc16_one(crc, s); /* build CRC */
+ crc = ccitt_crc16_one(crc, l); /* build CRC */
+ l = (l == 0) ? 128 : l << 8;
+ }
+ else if (d == 0xfb)// data address mark ?
+ {
+ crc = 0xffff; // reset CRC
+ }
+ else if (d == 0x81)// sector DATA ?
+ {
+ pdst--; /* go back one byte */
+ if (seek(w, t, h, s) == 0)
+ {
+ if (mame_fread(w->image_file, pdst, l) != l)
+ {
+ w->status = STA_2_CRC_ERR;
+ return;
+ }
+ }
+ else
+ {
+ w->status = STA_2_REC_N_FND;
+ return;
+ }
+ for (i = 0; i < l; i++) // build CRC of all data
+ crc = ccitt_crc16_one(crc, *pdst++);
+ cnt -= l;
+ }
+ psrc += 2;
+ }
+ else
+ {
+ *pdst++ = 0xff; /* fill track */
+ cnt--; /* until end */
+ }
+ }
+#endif
+ /* Determine the track size. We cannot allow different sizes in this
+ design (see above, write_track). */
+ w->data_count = 0;
+ floppy = flopimg_get_image(w->drive);
+ if (floppy != NULL)
+ w->data_count = floppy_get_track_size(floppy, w->hd, w->track);
+
+ if (w->data_count==0)
+ {
+ if (wd17xx_is_sd_only(device))
+ w->data_count = TRKSIZE_SD;
+ else
+ w->data_count = wd17xx_dden(device) ? TRKSIZE_SD : TRKSIZE_DD;
+ }
+
+ floppy_drive_read_track_data_info_buffer( w->drive, w->hd, (char *)w->buffer, &(w->data_count) );
+
+ w->data_offset = 0;
+
+ wd17xx_set_drq(device);
+ w->status |= STA_2_BUSY;
+ w->busy_count = 0;
+}
+
+
+/* read the next data address mark */
+static void wd17xx_read_id(device_t *device)
+{
+ chrn_id id;
+ wd1770_state *w = get_safe_token(device);
+
+ w->status &= ~(STA_2_CRC_ERR | STA_2_REC_N_FND);
+
+ /* get next id from disc */
+ if (floppy_drive_get_next_id(w->drive, w->hd, &id))
+ {
+ UINT16 crc = 0xffff;
+
+ w->data_offset = 0;
+ w->data_count = 6;
+
+ /* for MFM */
+ /* crc includes 3x0x0a1, and 1x0x0fe (id mark) */
+ crc = ccitt_crc16_one(crc,0x0a1);
+ crc = ccitt_crc16_one(crc,0x0a1);
+ crc = ccitt_crc16_one(crc,0x0a1);
+ crc = ccitt_crc16_one(crc,0x0fe);
+
+ w->buffer[0] = id.C;
+ w->buffer[1] = id.H;
+ w->buffer[2] = id.R;
+ w->buffer[3] = id.N;
+ crc = ccitt_crc16_one(crc, w->buffer[0]);
+ crc = ccitt_crc16_one(crc, w->buffer[1]);
+ crc = ccitt_crc16_one(crc, w->buffer[2]);
+ crc = ccitt_crc16_one(crc, w->buffer[3]);
+ /* crc is stored hi-byte followed by lo-byte */
+ w->buffer[4] = crc>>8;
+ w->buffer[5] = crc & 255;
+
+ w->sector = id.C;
+
+ if (VERBOSE)
+ logerror("wd17xx_read_id: read id succeeded.\n");
+
+ wd17xx_timed_data_request(device);
+ }
+ else
+ {
+ /* record not found */
+ w->status |= STA_2_REC_N_FND;
+ //w->sector = w->track;
+ if (VERBOSE)
+ logerror("wd17xx_read_id: read id failed\n");
+
+ wd17xx_complete_command(device, DELAY_ERROR);
+ }
+}
+
+
+
+void wd17xx_index_pulse_callback(device_t *controller, device_t *img, int state)
+{
+ wd1770_state *w = get_safe_token(controller);
+
+ if (img != w->drive)
+ return;
+
+ w->idx = state;
+
+ if (!state && w->idx && BIT(w->interrupt, 2))
+ wd17xx_set_intrq(controller);
+
+ if (w->hld_count)
+ w->hld_count--;
+}
+
+
+
+static int wd17xx_locate_sector(device_t *device)
+{
+ UINT8 revolution_count;
+ chrn_id id;
+ wd1770_state *w = get_safe_token(device);
+
+ revolution_count = 0;
+
+ w->status &= ~STA_2_REC_N_FND;
+
+ while (revolution_count!=4)
+ {
+ if (floppy_drive_get_next_id(w->drive, w->hd, &id))
+ {
+ /* compare track */
+ if (id.C == w->track)
+ {
+ /* compare head, if we were asked to */
+ if (!wd17xx_has_side_select(device) || (id.H == w->head) || (w->head == (UINT8) ~0))
+ {
+ /* compare id */
+ if (id.R == w->sector)
+ {
+ w->sector_length = 1<<(id.N+7);
+ w->sector_data_id = id.data_id;
+ /* get ddam status */
+ w->ddam = id.flags & ID_FLAG_DELETED_DATA;
+ /* got record type here */
+ if (VERBOSE)
+ logerror("sector found! C:$%02x H:$%02x R:$%02x N:$%02x%s\n", id.C, id.H, id.R, id.N, w->ddam ? " DDAM" : "");
+ return 1;
+ }
+ }
+ }
+ }
+
+ /* index set? */
+ if (floppy_drive_get_flag_state(w->drive, FLOPPY_DRIVE_INDEX))
+ {
+ /* update revolution count */
+ revolution_count++;
+ }
+ }
+ return 0;
+}
+
+
+static int wd17xx_find_sector(device_t *device)
+{
+ wd1770_state *w = get_safe_token(device);
+ if ( wd17xx_locate_sector(device) )
+ {
+ return 1;
+ }
+
+ /* record not found */
+ w->status |= STA_2_REC_N_FND;
+
+ if (VERBOSE)
+ logerror("track %d sector %d not found!\n", w->track, w->sector);
+
+ wd17xx_complete_command(device, DELAY_ERROR);
+
+ return 0;
+}
+
+
+
+/* read a sector */
+static void wd17xx_read_sector(device_t *device)
+{
+ wd1770_state *w = get_safe_token(device);
+ w->data_offset = 0;
+
+ /* side compare? */
+ if (w->read_cmd & 0x02)
+ w->head = (w->read_cmd & 0x08) ? 1 : 0;
+ else
+ w->head = ~0;
+
+ if (wd17xx_find_sector(device))
+ {
+ w->data_count = w->sector_length;
+
+ /* read data */
+ floppy_drive_read_sector_data(w->drive, w->hd, w->sector_data_id, (char *)w->buffer, w->sector_length);
+
+ wd17xx_timed_data_request(device);
+
+ w->status |= STA_2_BUSY;
+ w->busy_count = 0;
+ }
+}
+
+
+/* called on error, or when command is actually completed */
+/* KT - I have used a timer for systems that use interrupt driven transfers.
+A interrupt occurs after the last byte has been read. If it occurs at the time
+when the last byte has been read it causes problems - same byte read again
+or bytes missed */
+/* TJL - I have add a parameter to allow the emulation to specify the delay
+*/
+static void wd17xx_complete_command(device_t *device, int delay)
+{
+ wd1770_state *w = get_safe_token(device);
+
+ w->data_count = 0;
+
+ w->hld_count = 2;
+
+ /* set new timer */
+ int usecs = wd17xx_dden(device) ? 32 : 16;
+ w->timer_cmd->adjust(attotime::from_usec(usecs));
+
+ /* Kill onshot read/write sector timers */
+ w->timer_rs->adjust(attotime::never);
+ w->timer_ws->adjust(attotime::never);
+}
+
+
+
+static void wd17xx_write_sector(device_t *device)
+{
+ wd1770_state *w = get_safe_token(device);
+ /* at this point, the disc is write enabled, and data
+ * has been transfered into our buffer - now write it to
+ * the disc image or to the real disc
+ */
+
+ /* side compare? */
+ if (w->write_cmd & 0x02)
+ w->head = (w->write_cmd & 0x08) ? 1 : 0;
+ else
+ w->head = ~0;
+
+ /* find sector */
+ if (wd17xx_find_sector(device))
+ {
+ w->data_count = w->sector_length;
+
+ /* write data */
+ floppy_drive_write_sector_data(w->drive, w->hd, w->sector_data_id, (char *)w->buffer, w->sector_length, w->write_cmd & 0x01);
+ }
+}
+
+
+
+/* verify the seek operation by looking for a id that has a matching track value */
+static void wd17xx_verify_seek(device_t *device)
+{
+ UINT8 revolution_count;
+ chrn_id id;
+ wd1770_state *w = get_safe_token(device);
+
+ revolution_count = 0;
+
+ if (VERBOSE)
+ logerror("doing seek verify\n");
+
+ w->status &= ~STA_1_SEEK_ERR;
+
+ /* must be found within 5 revolutions otherwise error */
+ while (revolution_count!=5)
+ {
+ if (floppy_drive_get_next_id(w->drive, w->hd, &id))
+ {
+ /* compare track */
+ if (id.C == w->track)
+ {
+ if (VERBOSE)
+ logerror("seek verify succeeded!\n");
+ return;
+ }
+ }
+
+ /* index set? */
+ if (floppy_drive_get_flag_state(w->drive, FLOPPY_DRIVE_INDEX))
+ {
+ /* update revolution count */
+ revolution_count++;
+ }
+ }
+
+ w->status |= STA_1_SEEK_ERR;
+
+ if (VERBOSE)
+ logerror("failed seek verify!\n");
+}
+
+
+
+/* callback to initiate read sector */
+static TIMER_CALLBACK( wd17xx_read_sector_callback )
+{
+ device_t *device = (device_t *)ptr;
+ wd1770_state *w = get_safe_token(device);
+
+ /* ok, start that read! */
+
+ if (VERBOSE)
+ logerror("wd179x: Read Sector callback.\n");
+
+ if (!floppy_drive_get_flag_state(w->drive, FLOPPY_DRIVE_READY))
+ wd17xx_complete_command(device, DELAY_NOTREADY);
+ else
+ wd17xx_read_sector(device);
+}
+
+
+
+/* callback to initiate write sector */
+static TIMER_CALLBACK( wd17xx_write_sector_callback )
+{
+ device_t *device = (device_t *)ptr;
+ wd1770_state *w = get_safe_token(device);
+
+ /* ok, start that write! */
+
+ if (VERBOSE)
+ logerror("wd179x: Write Sector callback.\n");
+
+ if (!floppy_drive_get_flag_state(w->drive, FLOPPY_DRIVE_READY))
+ wd17xx_complete_command(device, DELAY_NOTREADY);
+ else
+ {
+
+ /* drive write protected? */
+ if (floppy_wpt_r(w->drive) == CLEAR_LINE)
+ {
+ w->status |= STA_2_WRITE_PRO;
+
+ wd17xx_complete_command(device, DELAY_ERROR);
+ }
+ else
+ {
+ /* side compare? */
+ if (w->write_cmd & 0x02)
+ w->head = (w->write_cmd & 0x08) ? 1 : 0;
+ else
+ w->head = ~0;
+
+ /* attempt to find it first before getting data from cpu */
+ if (wd17xx_find_sector(device))
+ {
+ /* request data */
+ w->data_offset = 0;
+ w->data_count = w->sector_length;
+
+ wd17xx_set_drq(device);
+
+ w->status |= STA_2_BUSY;
+ w->busy_count = 0;
+ }
+ }
+ }
+}
+
+
+
+/* setup a timed data request - data request will be triggered in a few usecs time */
+static void wd17xx_timed_data_request(device_t *device)
+{
+ wd1770_state *w = get_safe_token(device);
+
+ /* set new timer */
+ w->timer_data->adjust(attotime::from_usec(wd17xx_dden(device) ? 128 : 32));
+}
+
+
+
+/* setup a timed read sector - read sector will be triggered in a few usecs time */
+static void wd17xx_timed_read_sector_request(device_t *device)
+{
+ wd1770_state *w = get_safe_token(device);
+
+ /* set new timer */
+ w->timer_rs->adjust(attotime::from_usec(w->pause_time));
+}
+
+
+
+/* setup a timed write sector - write sector will be triggered in a few usecs time */
+static void wd17xx_timed_write_sector_request(device_t *device)
+{
+ wd1770_state *w = get_safe_token(device);
+
+ /* set new timer */
+ w->timer_ws->adjust(attotime::from_usec(w->pause_time));
+}
+
+
+/***************************************************************************
+ INTERFACE
+***************************************************************************/
+
+/* use this to determine which drive is controlled by WD */
+void wd17xx_set_drive(device_t *device, UINT8 drive)
+{
+ wd1770_state *w = get_safe_token(device);
+
+ if (VERBOSE)
+ logerror("wd17xx_set_drive: $%02x\n", drive);
+
+ if (w->intf->floppy_drive_tags[drive] != NULL)
+ {
+ if (device->owner() != NULL) {
+ w->drive = device->owner()->subdevice(w->intf->floppy_drive_tags[drive]);
+ if (w->drive == NULL) {
+ w->drive = device->machine().device(w->intf->floppy_drive_tags[drive]);
+ }
+ }
+ else
+ w->drive = device->machine().device(w->intf->floppy_drive_tags[drive]);
+ }
+}
+
+void wd17xx_set_side(device_t *device, UINT8 head)
+{
+ wd1770_state *w = get_safe_token(device);
+
+ if (VERBOSE)
+ {
+ if (head != w->hd)
+ logerror("wd17xx_set_side: $%02x\n", head);
+ }
+
+ w->hd = head;
+}
+
+void wd17xx_set_pause_time(device_t *device, int usec)
+{
+ wd1770_state *w = get_safe_token(device);
+ w->pause_time = usec;
+}
+
+
+/***************************************************************************
+ DEVICE HANDLERS
+***************************************************************************/
+
+/* master reset */
+WRITE_LINE_DEVICE_HANDLER( wd17xx_mr_w )
+{
+ wd1770_state *w = get_safe_token(device);
+
+ /* reset device when going from high to low */
+ if (w->mr && state == CLEAR_LINE)
+ {
+ w->command = 0x03;
+ w->status &= ~STA_1_NOT_READY; /* ? */
+ }
+
+ /* execute restore command when going from low to high */
+ if (w->mr == CLEAR_LINE && state)
+ {
+ wd17xx_command_restore(device);
+ w->sector = 0x01;
+ }
+
+ w->mr = state;
+}
+
+/* ready and enable precomp (1773 only) */
+WRITE_LINE_DEVICE_HANDLER( wd17xx_rdy_w )
+{
+ wd1770_state *w = get_safe_token(device);
+ w->rdy = state;
+}
+
+/* motor on, 1770 and 1772 only */
+READ_LINE_DEVICE_HANDLER( wd17xx_mo_r )
+{
+ wd1770_state *w = get_safe_token(device);
+ return w->mo;
+}
+
+/* track zero */
+WRITE_LINE_DEVICE_HANDLER( wd17xx_tr00_w )
+{
+ wd1770_state *w = get_safe_token(device);
+ w->tr00 = state;
+}
+
+/* index pulse */
+WRITE_LINE_DEVICE_HANDLER( wd17xx_idx_w )
+{
+ wd1770_state *w = get_safe_token(device);
+ w->idx = state;
+
+ if (!state && w->idx && BIT(w->interrupt, 2))
+ wd17xx_set_intrq(device);
+}
+
+/* write protect status */
+WRITE_LINE_DEVICE_HANDLER( wd17xx_wprt_w )
+{
+ wd1770_state *w = get_safe_token(device);
+ w->wprt = state;
+}
+
+/* double density enable */
+WRITE_LINE_DEVICE_HANDLER( wd17xx_dden_w )
+{
+ wd1770_state *w = get_safe_token(device);
+
+ /* not supported on FD1771, FD1792, FD1794, FD1762 and FD1764 */
+ if (wd17xx_is_sd_only(device))
+ fatalerror("wd17xx_dden_w: double density input not supported on this model!");
+ else if (!w->in_dden_func.isnull())
+ logerror("wd17xx_dden_w: write has no effect because a read handler is already defined!\n");
+ else
+ w->dden = state;
+}
+
+/* data request */
+READ_LINE_DEVICE_HANDLER( wd17xx_drq_r )
+{
+ wd1770_state *w = get_safe_token(device);
+ return w->drq;
+}
+
+/* interrupt request */
+READ_LINE_DEVICE_HANDLER( wd17xx_intrq_r )
+{
+ wd1770_state *w = get_safe_token(device);
+ return w->intrq;
+}
+
+/* read the FDC status register. This clears IRQ line too */
+READ8_DEVICE_HANDLER( wd17xx_status_r )
+{
+ wd1770_state *w = get_safe_token(device);
+ int result;
+
+ if (!BIT(w->interrupt, 3))
+ {
+ wd17xx_clear_intrq(device);
+ }
+
+ /* bit 7, 'not ready' or 'motor on' */
+ if (device->type() == WD1770 || device->type() == WD1772)
+ {
+ w->status &= ~STA_1_MOTOR_ON;
+ w->status |= w->mo << 7;
+ }
+ else
+ {
+ w->status &= ~STA_1_NOT_READY;
+ if (!floppy_drive_get_flag_state(w->drive, FLOPPY_DRIVE_READY))
+ w->status |= STA_1_NOT_READY;
+ }
+
+ result = w->status;
+
+ /* type 1 command or force int command? */
+ if ((w->command_type==TYPE_I) || (w->command_type==TYPE_IV && ! w->was_busy))
+ {
+ result &= ~(STA_1_IPL | STA_1_TRACK0);
+
+ /* bit 1, index pulse */
+ result |= w->idx << 1;
+
+ /* bit 2, track 0 state, inverted */
+ result |= !floppy_tk00_r(w->drive) << 2;
+
+ if (w->command_type==TYPE_I)
+ {
+ if (w->hld_count)
+ w->status |= STA_1_HD_LOADED;
+ else
+ w->status &= ~ STA_1_HD_LOADED;
+ }
+
+ /* bit 6, write protect, inverted */
+ result |= !floppy_wpt_r(w->drive) << 6;
+ }
+
+ /* eventually set data request bit */
+// w->status |= w->status_drq;
+
+ if (VERBOSE)
+ {
+ if (w->data_count < 4)
+ logerror("%s: wd17xx_status_r: $%02X (data_count %d)\n", device->machine().describe_context(), result, w->data_count);
+ }
+
+ return result ^ (wd17xx_has_dal(device) ? 0 : 0xff);
+}
+
+/* read the FDC track register */
+READ8_DEVICE_HANDLER( wd17xx_track_r )
+{
+ wd1770_state *w = get_safe_token(device);
+
+ if (VERBOSE)
+ logerror("%s: wd17xx_track_r: $%02X\n", device->machine().describe_context(), w->track);
+
+ return w->track ^ (wd17xx_has_dal(device) ? 0 : 0xff);
+}
+
+/* read the FDC sector register */
+READ8_DEVICE_HANDLER( wd17xx_sector_r )
+{
+ wd1770_state *w = get_safe_token(device);
+
+ if (VERBOSE)
+ logerror("%s: wd17xx_sector_r: $%02X\n", device->machine().describe_context(), w->sector);
+
+ return w->sector ^ (wd17xx_has_dal(device) ? 0 : 0xff);
+}
+
+/* read the FDC data register */
+READ8_DEVICE_HANDLER( wd17xx_data_r )
+{
+ wd1770_state *w = get_safe_token(device);
+
+ if (VERBOSE_DATA)
+ logerror("%s: wd17xx_data_r: %02x\n", device->machine().describe_context(), w->data);
+
+ /* clear data request */
+ wd17xx_clear_drq(device);
+
+ return w->data ^ (wd17xx_has_dal(device) ? 0 : 0xff);
+}
+
+/* write the FDC command register */
+WRITE8_DEVICE_HANDLER( wd17xx_command_w )
+{
+ wd1770_state *w = get_safe_token(device);
+ if (!wd17xx_has_dal(device)) data ^= 0xff;
+
+ w->last_command_data = data;
+
+ /* only the WD1770 and WD1772 have a 'motor on' line */
+ if (device->type() == WD1770 || device->type() == WD1772)
+ {
+ w->mo = ASSERT_LINE;
+ floppy_mon_w(w->drive, CLEAR_LINE);
+ }
+
+ floppy_drive_set_ready_state(w->drive, 1,0);
+
+ if (!BIT(w->interrupt, 3))
+ {
+ wd17xx_clear_intrq(device);
+ }
+
+ /* clear write protected. On read sector, read track and read dam, write protected bit is clear */
+ w->status &= ~((1<<6) | (1<<5) | (1<<4));
+
+ if ((data & ~FDC_MASK_TYPE_IV) == FDC_FORCE_INT)
+ {
+ if (VERBOSE)
+ logerror("%s: wd17xx_command_w $%02X FORCE_INT (data_count %d)\n", device->machine().describe_context(), data, w->data_count);
+
+ w->data_count = 0;
+ w->data_offset = 0;
+ w->was_busy = w->status & STA_2_BUSY;
+ w->status &= ~STA_2_BUSY;
+
+ wd17xx_clear_drq(device);
+
+ if (!BIT(w->interrupt, 3) && BIT(data, 3))
+ {
+ /* set immediate interrupt */
+ wd17xx_set_intrq(device);
+ }
+
+ if (BIT(w->interrupt, 3))
+ {
+ if (data == FDC_FORCE_INT)
+ {
+ /* clear immediate interrupt */
+ w->interrupt = data & 0x0f;
+ }
+ else
+ {
+ /* keep immediate interrupt */
+ w->interrupt = 0x08 | (data & 0x07);
+ }
+ }
+ else
+ {
+ w->interrupt = data & 0x0f;
+ }
+
+ /* terminate command */
+ wd17xx_complete_command(device, DELAY_ERROR);
+
+ w->busy_count = 0;
+ w->command_type = TYPE_IV;
+ return;
+ }
+
+ if (data & 0x80)
+ {
+ /*w->status_ipl = 0;*/
+
+ if ((data & ~FDC_MASK_TYPE_II) == FDC_READ_SEC)
+ {
+ if (VERBOSE)
+ {
+ logerror("%s: wd17xx_command_w $%02X READ_SEC (", device->machine().describe_context(), data);
+ logerror("cmd=%02X, trk=%02X, sec=%02X, dat=%02X)\n",w->command,w->track,w->sector,w->data);
+ }
+ w->read_cmd = data;
+ w->command = data & ~FDC_MASK_TYPE_II;
+ w->command_type = TYPE_II;
+ w->status &= ~STA_2_LOST_DAT;
+ w->status |= STA_2_BUSY;
+ wd17xx_clear_drq(device);
+
+ wd17xx_timed_read_sector_request(device);
+
+ return;
+ }
+
+ if ((data & ~FDC_MASK_TYPE_II) == FDC_WRITE_SEC)
+ {
+ if (VERBOSE)
+ {
+ logerror("%s: wd17xx_command_w $%02X WRITE_SEC (", device->machine().describe_context(), data);
+ logerror("cmd=%02X, trk=%02X, sec=%02X, dat=%02X)\n",w->command,w->track,w->sector,w->data);
+ }
+
+ w->write_cmd = data;
+ w->command = data & ~FDC_MASK_TYPE_II;
+ w->command_type = TYPE_II;
+ w->status &= ~STA_2_LOST_DAT;
+ w->status |= STA_2_BUSY;
+ wd17xx_clear_drq(device);
+
+ wd17xx_timed_write_sector_request(device);
+
+ return;
+ }
+
+ if ((data & ~FDC_MASK_TYPE_III) == FDC_READ_TRK)
+ {
+ if (VERBOSE)
+ logerror("%s: wd17xx_command_w $%02X READ_TRK\n", device->machine().describe_context(), data);
+
+ w->command = data & ~FDC_MASK_TYPE_III;
+ w->command_type = TYPE_III;
+ w->status &= ~STA_2_LOST_DAT;
+ wd17xx_clear_drq(device);
+#if 1
+// w->status = seek(w, w->track, w->head, w->sector);
+ if (w->status == 0)
+ read_track(device);
+#endif
+ return;
+ }
+
+ if ((data & ~FDC_MASK_TYPE_III) == FDC_WRITE_TRK)
+ {
+ if (VERBOSE)
+ logerror("%s: wd17xx_command_w $%02X WRITE_TRK\n", device->machine().describe_context(), data);
+
+ w->command_type = TYPE_III;
+ w->status &= ~STA_2_LOST_DAT;
+ wd17xx_clear_drq(device);
+
+ if (!floppy_drive_get_flag_state(w->drive, FLOPPY_DRIVE_READY))
+ {
+ wd17xx_complete_command(device, DELAY_NOTREADY);
+ }
+ else
+ {
+
+ /* drive write protected? */
+ if (floppy_wpt_r(w->drive) == CLEAR_LINE)
+ {
+ /* yes */
+ w->status |= STA_2_WRITE_PRO;
+ /* quit command */
+ wd17xx_complete_command(device, DELAY_ERROR);
+ }
+ else
+ {
+ w->command = data & ~FDC_MASK_TYPE_III;
+ w->data_offset = 0;
+ if (wd17xx_is_sd_only(device))
+ w->data_count = TRKSIZE_SD;
+ else
+ w->data_count = wd17xx_dden(device) ? TRKSIZE_SD : TRKSIZE_DD;
+
+ wd17xx_set_drq(device);
+ w->status |= STA_2_BUSY;
+ w->busy_count = 0;
+ }
+ }
+ return;
+ }
+
+ if ((data & ~FDC_MASK_TYPE_III) == FDC_READ_DAM)
+ {
+ if (VERBOSE)
+ logerror("%s: wd17xx_command_w $%02X READ_DAM\n", device->machine().describe_context(), data);
+
+ w->command_type = TYPE_III;
+ w->command = data & ~FDC_MASK_TYPE_III;
+ w->status &= ~STA_2_LOST_DAT;
+ w->status |= STA_2_BUSY;
+
+ wd17xx_clear_drq(device);
+
+ if (floppy_drive_get_flag_state(w->drive, FLOPPY_DRIVE_READY))
+ wd17xx_read_id(device);
+ else
+ wd17xx_complete_command(device, DELAY_NOTREADY);
+
+ return;
+ }
+
+ if (VERBOSE)
+ logerror("%s: wd17xx_command_w $%02X unknown\n", device->machine().describe_context(), data);
+
+ return;
+ }
+
+ w->status |= STA_1_BUSY;
+
+ /* clear CRC error */
+ w->status &=~STA_1_CRC_ERR;
+
+ if ((data & ~FDC_MASK_TYPE_I) == FDC_RESTORE)
+ {
+ if (VERBOSE)
+ logerror("%s: wd17xx_command_w $%02X RESTORE\n", device->machine().describe_context(), data);
+
+ wd17xx_command_restore(device);
+ }
+
+ if ((data & ~FDC_MASK_TYPE_I) == FDC_SEEK)
+ {
+ UINT8 newtrack;
+
+ if (VERBOSE)
+ logerror("old track: $%02x new track: $%02x\n", w->track, w->data);
+ w->command_type = TYPE_I;
+
+ /* setup step direction */
+ if (w->track < w->data)
+ {
+ if (VERBOSE)
+ logerror("direction: +1\n");
+
+ w->direction = 1;
+ }
+ else if (w->track > w->data)
+ {
+ if (VERBOSE)
+ logerror("direction: -1\n");
+
+ w->direction = -1;
+ }
+
+ newtrack = w->data;
+ if (VERBOSE)
+ logerror("%s: wd17xx_command_w $%02X SEEK (data_reg is $%02X)\n", device->machine().describe_context(), data, newtrack);
+
+ /* reset busy count */
+ w->busy_count = 0;
+
+ /* keep stepping until reached track programmed */
+ while (w->track != newtrack)
+ {
+ /* update time to simulate seek time busy signal */
+ w->busy_count++;
+
+ /* update track reg */
+ w->track += w->direction;
+
+ floppy_drive_seek(w->drive, w->direction);
+ }
+
+ /* simulate seek time busy signal */
+ w->busy_count = 0; //w->busy_count * ((data & FDC_STEP_RATE) + 1);
+#if 0
+ wd17xx_set_intrq(device);
+#endif
+ wd17xx_set_busy(device, attotime::from_usec(100));
+
+ }
+
+ if ((data & ~(FDC_STEP_UPDATE | FDC_MASK_TYPE_I)) == FDC_STEP)
+ {
+ if (VERBOSE)
+ logerror("%s: wd17xx_command_w $%02X STEP dir %+d\n", device->machine().describe_context(), data, w->direction);
+
+ w->command_type = TYPE_I;
+ /* if it is a real floppy, issue a step command */
+ /* simulate seek time busy signal */
+ w->busy_count = 0; //((data & FDC_STEP_RATE) + 1);
+
+ floppy_drive_seek(w->drive, w->direction);
+
+ if (data & FDC_STEP_UPDATE)
+ w->track += w->direction;
+
+#if 0
+ wd17xx_set_intrq(device);
+#endif
+ wd17xx_set_busy(device, attotime::from_usec(100));
+
+
+ }
+
+ if ((data & ~(FDC_STEP_UPDATE | FDC_MASK_TYPE_I)) == FDC_STEP_IN)
+ {
+ if (VERBOSE)
+ logerror("%s: wd17xx_command_w $%02X STEP_IN\n", device->machine().describe_context(), data);
+
+ w->command_type = TYPE_I;
+ w->direction = +1;
+ /* simulate seek time busy signal */
+ w->busy_count = 0; //((data & FDC_STEP_RATE) + 1);
+
+ floppy_drive_seek(w->drive, w->direction);
+
+ if (data & FDC_STEP_UPDATE)
+ w->track += w->direction;
+#if 0
+ wd17xx_set_intrq(device);
+#endif
+ wd17xx_set_busy(device, attotime::from_usec(100));
+
+ }
+
+ if ((data & ~(FDC_STEP_UPDATE | FDC_MASK_TYPE_I)) == FDC_STEP_OUT)
+ {
+ if (VERBOSE)
+ logerror("%s: wd17xx_command_w $%02X STEP_OUT\n", device->machine().describe_context(), data);
+
+ w->command_type = TYPE_I;
+ w->direction = -1;
+ /* simulate seek time busy signal */
+ w->busy_count = 0; //((data & FDC_STEP_RATE) + 1);
+
+ /* for now only allows a single drive to be selected */
+ floppy_drive_seek(w->drive, w->direction);
+
+ if (data & FDC_STEP_UPDATE)
+ w->track += w->direction;
+
+#if 0
+ wd17xx_set_intrq(device);
+#endif
+ wd17xx_set_busy(device, attotime::from_usec(100));
+ }
+
+ if (w->command_type == TYPE_I)
+ {
+ /* 0 is enable spin up sequence, 1 is disable spin up sequence */
+ if ((data & FDC_STEP_HDLOAD)==0)
+ {
+ w->status |= STA_1_HD_LOADED;
+ w->hld_count = 2;
+ }
+ else
+ w->status &= ~STA_1_HD_LOADED;
+
+ if (data & FDC_STEP_VERIFY)
+ {
+ /* verify seek */
+ wd17xx_verify_seek(device);
+ }
+ }
+}
+
+/* write the FDC track register */
+WRITE8_DEVICE_HANDLER( wd17xx_track_w )
+{
+ wd1770_state *w = get_safe_token(device);
+ if (!wd17xx_has_dal(device)) data ^= 0xff;
+
+ w->track = data;
+
+ if (VERBOSE)
+ logerror("%s: wd17xx_track_w $%02X\n", device->machine().describe_context(), data);
+}
+
+/* write the FDC sector register */
+WRITE8_DEVICE_HANDLER( wd17xx_sector_w )
+{
+ wd1770_state *w = get_safe_token(device);
+ if (!wd17xx_has_dal(device)) data ^= 0xff;
+
+ w->sector = data;
+
+ if (VERBOSE)
+ logerror("%s: wd17xx_sector_w $%02X\n", device->machine().describe_context(), data);
+}
+
+/* write the FDC data register */
+WRITE8_DEVICE_HANDLER( wd17xx_data_w )
+{
+ wd1770_state *w = get_safe_token(device);
+ if (!wd17xx_has_dal(device)) data ^= 0xff;
+
+ if (w->data_count > 0)
+ {
+ wd17xx_clear_drq(device);
+
+ /* put byte into buffer */
+ if (VERBOSE_DATA)
+ logerror("wd17xx_info buffered data: $%02X at offset %d.\n", data, w->data_offset);
+
+ w->buffer[w->data_offset++] = data;
+
+ if (--w->data_count < 1)
+ {
+ if (w->command == FDC_WRITE_TRK)
+ write_track(device);
+ else
+ wd17xx_write_sector(device);
+
+ w->data_offset = 0;
+
+ /* Check we should handle the next sector for a multi record write */
+ if ( w->command_type == TYPE_II && w->command == FDC_WRITE_SEC && ( w->write_cmd & FDC_MULTI_REC ) )
+ {
+ w->sector++;
+ if (wd17xx_locate_sector(device))
+ {
+ w->data_count = w->sector_length;
+
+ w->status |= STA_2_BUSY;
+ w->busy_count = 0;
+
+ wd17xx_timed_data_request(device);
+ }
+ }
+ else
+ {
+ wd17xx_complete_command(device, DELAY_DATADONE);
+ if (VERBOSE)
+ logerror("wd17xx_data_w(): multi data write completed\n");
+ }
+// wd17xx_complete_command(device, DELAY_DATADONE);
+ }
+ else
+ {
+ if (w->command == FDC_WRITE_TRK)
+ {
+ /* Process special data values according to WD17xx specification.
+ Note that as CRC values take up two bytes which are written on
+ every 0xf7 byte, this will cause the actual image to
+ grow larger than what was written from the system. So we need
+ to take the value of data_offset when writing the track.
+ */
+ if (wd17xx_dden(device))
+ {
+ switch (data)
+ {
+ case 0xf5:
+ case 0xf6:
+ /* not allowed in FM. */
+ /* Take back the last write. */
+ w->data_offset--;
+ break;
+ case 0xf7:
+ /* Take back the last write. */
+ w->data_offset--;
+ /* write two crc bytes */
+ w->buffer[w->data_offset++] = (w->crc>>8)&0xff;
+ w->buffer[w->data_offset++] = (w->crc&0xff);
+ w->crc_active = FALSE;
+ break;
+ case 0xf8:
+ case 0xf9:
+ case 0xfa:
+ case 0xfb:
+ case 0xfe:
+ /* Preset crc */
+ w->crc = 0xffff;
+ /* AM is included in the CRC */
+ w->crc = ccitt_crc16_one(w->crc, data);
+ w->crc_active = TRUE;
+ break;
+ case 0xfc:
+ /* Write index mark. No effect here as we do not store clock patterns.
+ Maybe later. */
+ break;
+ case 0xfd:
+ /* Just write, don't use for CRC. */
+ break;
+ default:
+ /* Byte already written. */
+ if (w->crc_active)
+ w->crc = ccitt_crc16_one(w->crc, data);
+ }
+ }
+ else /* MFM */
+ {
+ switch (data)
+ {
+ case 0xf5:
+ /* Take back the last write. */
+ w->data_offset--;
+ /* Write a1 */
+ w->buffer[w->data_offset++] = 0xa1;
+ /* Preset CRC */
+ w->crc = 0xffff;
+ w->crc_active = TRUE;
+ break;
+ case 0xf6:
+ /* Take back the last write. */
+ w->data_offset--;
+ /* Write c2 */
+ w->buffer[w->data_offset++] = 0xc2;
+ break;
+ case 0xf7:
+ /* Take back the last write. */
+ w->data_offset--;
+ /* write two crc bytes */
+ w->buffer[w->data_offset++] = (w->crc>>8)&0xff;
+ w->buffer[w->data_offset++] = (w->crc&0xff);
+ w->crc_active = FALSE;
+ break;
+ case 0xf8:
+ case 0xf9:
+ case 0xfa:
+ case 0xfb:
+ case 0xfc:
+ case 0xfd:
+ /* Just write, don't use for CRC. */
+ break;
+ case 0xfe:
+ /* AM is included in the CRC */
+ if (w->crc_active)
+ w->crc = ccitt_crc16_one(w->crc, data);
+ break;
+ default:
+ /* Byte already written. */
+ if (w->crc_active)
+ w->crc = ccitt_crc16_one(w->crc, data);
+ }
+ }
+ }
+ /* yes... setup a timed data request */
+ wd17xx_timed_data_request(device);
+ }
+ }
+ else
+ {
+ if (VERBOSE)
+ logerror("%s: wd17xx_data_w $%02X\n", device->machine().describe_context(), data);
+ }
+ w->data = data;
+}
+
+READ8_DEVICE_HANDLER( wd17xx_r )
+{
+ UINT8 data = 0;
+
+ switch (offset & 0x03)
+ {
+ case 0: data = wd17xx_status_r(device, 0); break;
+ case 1: data = wd17xx_track_r(device, 0); break;
+ case 2: data = wd17xx_sector_r(device, 0); break;
+ case 3: data = wd17xx_data_r(device, 0); break;
+ }
+
+ return data;
+}
+
+WRITE8_DEVICE_HANDLER( wd17xx_w )
+{
+ switch (offset & 0x03)
+ {
+ case 0: wd17xx_command_w(device, 0, data); break;
+ case 1: wd17xx_track_w(device, 0, data); break;
+ case 2: wd17xx_sector_w(device, 0, data); break;
+ case 3: wd17xx_data_w(device, 0, data); break;
+ }
+}
+
+
+/***************************************************************************
+ MAME DEVICE INTERFACE
+***************************************************************************/
+
+static DEVICE_START( wd1770 )
+{
+ wd1770_state *w = get_safe_token(device);
+
+ assert(device->static_config() != NULL);
+
+ w->intf = (const wd17xx_interface*)device->static_config();
+
+ w->status = STA_1_TRACK0;
+ w->pause_time = 1000;
+
+ /* allocate timers */
+ w->timer_cmd = device->machine().scheduler().timer_alloc(FUNC(wd17xx_command_callback), (void *)device);
+ w->timer_data = device->machine().scheduler().timer_alloc(FUNC(wd17xx_data_callback), (void *)device);
+ w->timer_rs = device->machine().scheduler().timer_alloc(FUNC(wd17xx_read_sector_callback), (void *)device);
+ w->timer_ws = device->machine().scheduler().timer_alloc(FUNC(wd17xx_write_sector_callback), (void *)device);
+
+ /* resolve callbacks */
+ w->in_dden_func.resolve(w->intf->in_dden_func, *device);
+ w->out_intrq_func.resolve(w->intf->out_intrq_func, *device);
+ w->out_drq_func.resolve(w->intf->out_drq_func, *device);
+
+ /* stepping rate depends on the clock */
+ w->stepping_rate[0] = 6;
+ w->stepping_rate[1] = 12;
+ w->stepping_rate[2] = 20;
+ w->stepping_rate[3] = 30;
+}
+
+static DEVICE_START( wd1772 )
+{
+ wd1770_state *w = get_safe_token(device);
+
+ DEVICE_START_CALL(wd1770);
+
+ /* the 1772 has faster track stepping rates */
+ w->stepping_rate[0] = 6;
+ w->stepping_rate[1] = 12;
+ w->stepping_rate[2] = 2;
+ w->stepping_rate[3] = 3;
+}
+
+static DEVICE_RESET( wd1770 )
+{
+ wd1770_state *w = get_safe_token(device);
+ int i;
+
+ /* set the default state of some input lines */
+ w->mr = ASSERT_LINE;
+ w->wprt = ASSERT_LINE;
+ w->dden = ASSERT_LINE;
+
+ for (i = 0; i < 4; i++)
+ {
+ if(w->intf->floppy_drive_tags[i]!=NULL) {
+ device_t *img = NULL;
+
+ if (device->owner() != NULL)
+ img = device->owner()->subdevice(w->intf->floppy_drive_tags[i]);
+ if (img == NULL) {
+ img = device->machine().device(w->intf->floppy_drive_tags[i]);
+ }
+
+ else
+ img = device->machine().device(w->intf->floppy_drive_tags[i]);
+
+ if (img!=NULL) {
+ floppy_drive_set_controller(img,device);
+ floppy_drive_set_index_pulse_callback(img, wd17xx_index_pulse_callback);
+ floppy_drive_set_rpm( img, 300.);
+ }
+ }
+ }
+
+ wd17xx_set_drive(device, 0);
+
+ w->hd = 0;
+ w->hld_count = 0;
+ w->sector = 1;
+ wd17xx_command_restore(device);
+}
+
+void wd17xx_reset(device_t *device)
+{
+ DEVICE_RESET_CALL( wd1770 );
+}
+
+
+/***************************************************************************
+ DEVICE GETINFO
+***************************************************************************/
+
+static const char DEVTEMPLATE_SOURCE[] = __FILE__;
+
+#define DEVTEMPLATE_ID(p,s) p##wd1770##s
+#define DEVTEMPLATE_FEATURES DT_HAS_START | DT_HAS_RESET
+#define DEVTEMPLATE_NAME "WD1770"
+#define DEVTEMPLATE_FAMILY "WD17xx"
+#define DEVTEMPLATE_VERSION "1.0"
+#define DEVTEMPLATE_CREDITS "Copyright MESS Team"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##fd1771##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "FD1771"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##fd1781##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "FD1781"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##fd1791##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "FD1791"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##fd1792##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "FD1792"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##fd1793##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "FD1793"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##fd1794##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "FD1794"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##fd1795##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "FD1795"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##fd1797##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "FD1797"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##fd1761##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "FD1761"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##fd1762##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "FD1762"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##fd1763##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "FD1763"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##fd1764##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "FD1764"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##fd1765##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "FD1765"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##fd1767##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "FD1767"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##wd2791##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "WD2791"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##wd2793##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "WD2793"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##wd2795##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "WD2795"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##wd2797##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "WD2797"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##wd1772##s
+#define DEVTEMPLATE_DERIVED_FEATURES DT_HAS_START
+#define DEVTEMPLATE_DERIVED_NAME "WD1772"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##wd1773##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "WD1773"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##mb8866##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "MB8866"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##mb8876##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "MB8876"
+#include "devtempl.h"
+
+#define DEVTEMPLATE_DERIVED_ID(p,s) p##mb8877##s
+#define DEVTEMPLATE_DERIVED_FEATURES 0
+#define DEVTEMPLATE_DERIVED_NAME "MB8877"
+#include "devtempl.h"
+
+DEFINE_LEGACY_DEVICE(FD1771, fd1771);
+DEFINE_LEGACY_DEVICE(FD1781, fd1781);
+DEFINE_LEGACY_DEVICE(FD1791, fd1791);
+DEFINE_LEGACY_DEVICE(FD1792, fd1792);
+DEFINE_LEGACY_DEVICE(FD1793, fd1793);
+DEFINE_LEGACY_DEVICE(FD1794, fd1794);
+DEFINE_LEGACY_DEVICE(FD1795, fd1795);
+DEFINE_LEGACY_DEVICE(FD1797, fd1797);
+DEFINE_LEGACY_DEVICE(FD1761, fd1761);
+DEFINE_LEGACY_DEVICE(FD1762, fd1762);
+DEFINE_LEGACY_DEVICE(FD1763, fd1763);
+DEFINE_LEGACY_DEVICE(FD1764, fd1764);
+DEFINE_LEGACY_DEVICE(FD1765, fd1765);
+DEFINE_LEGACY_DEVICE(FD1767, fd1767);
+DEFINE_LEGACY_DEVICE(WD2791, wd2791);
+DEFINE_LEGACY_DEVICE(WD2793, wd2793);
+DEFINE_LEGACY_DEVICE(WD2795, wd2795);
+DEFINE_LEGACY_DEVICE(WD2797, wd2797);
+DEFINE_LEGACY_DEVICE(WD1770, wd1770);
+DEFINE_LEGACY_DEVICE(WD1772, wd1772);
+DEFINE_LEGACY_DEVICE(WD1773, wd1773);
+DEFINE_LEGACY_DEVICE(MB8866, mb8866);
+DEFINE_LEGACY_DEVICE(MB8876, mb8876);
+DEFINE_LEGACY_DEVICE(MB8877, mb8877);
diff --git a/trunk/src/emu/machine/wd17xx.h b/trunk/src/emu/machine/wd17xx.h
new file mode 100644
index 00000000000..4a24afe6b10
--- /dev/null
+++ b/trunk/src/emu/machine/wd17xx.h
@@ -0,0 +1,198 @@
+/*********************************************************************
+
+ wd17xx.h
+
+ Implementations of the Western Digital 17xx and 27xx families of
+ floppy disk controllers
+
+*********************************************************************/
+
+#ifndef __WD17XX_H__
+#define __WD17XX_H__
+
+#include "devcb.h"
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+DECLARE_LEGACY_DEVICE(FD1771, fd1771);
+DECLARE_LEGACY_DEVICE(FD1781, fd1781);
+DECLARE_LEGACY_DEVICE(FD1791, fd1791);
+DECLARE_LEGACY_DEVICE(FD1792, fd1792);
+DECLARE_LEGACY_DEVICE(FD1793, fd1793);
+DECLARE_LEGACY_DEVICE(FD1794, fd1794);
+DECLARE_LEGACY_DEVICE(FD1795, fd1795);
+DECLARE_LEGACY_DEVICE(FD1797, fd1797);
+DECLARE_LEGACY_DEVICE(FD1761, fd1761);
+DECLARE_LEGACY_DEVICE(FD1762, fd1762);
+DECLARE_LEGACY_DEVICE(FD1763, fd1763);
+DECLARE_LEGACY_DEVICE(FD1764, fd1764);
+DECLARE_LEGACY_DEVICE(FD1765, fd1765);
+DECLARE_LEGACY_DEVICE(FD1767, fd1767);
+DECLARE_LEGACY_DEVICE(WD2791, wd2791);
+DECLARE_LEGACY_DEVICE(WD2793, wd2793);
+DECLARE_LEGACY_DEVICE(WD2795, wd2795);
+DECLARE_LEGACY_DEVICE(WD2797, wd2797);
+DECLARE_LEGACY_DEVICE(WD1770, wd1770);
+DECLARE_LEGACY_DEVICE(WD1772, wd1772);
+DECLARE_LEGACY_DEVICE(WD1773, wd1773);
+DECLARE_LEGACY_DEVICE(MB8866, mb8866);
+DECLARE_LEGACY_DEVICE(MB8876, mb8876);
+DECLARE_LEGACY_DEVICE(MB8877, mb8877);
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/* Interface */
+typedef struct _wd17xx_interface wd17xx_interface;
+struct _wd17xx_interface
+{
+ devcb_read_line in_dden_func;
+ devcb_write_line out_intrq_func;
+ devcb_write_line out_drq_func;
+ const char *floppy_drive_tags[4];
+};
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+void wd17xx_reset(device_t *device);
+
+/* the following are not strictly part of the wd179x hardware/emulation
+but will be put here for now until the flopdrv code has been finalised more */
+void wd17xx_set_drive(device_t *device, UINT8); /* set drive wd179x is accessing */
+void wd17xx_set_side(device_t *device, UINT8); /* set side wd179x is accessing */
+
+void wd17xx_set_pause_time(device_t *device, int usec); /* default is 40 usec if not set */
+void wd17xx_index_pulse_callback(device_t *controller, device_t *img, int state);
+
+READ8_DEVICE_HANDLER( wd17xx_status_r );
+READ8_DEVICE_HANDLER( wd17xx_track_r );
+READ8_DEVICE_HANDLER( wd17xx_sector_r );
+READ8_DEVICE_HANDLER( wd17xx_data_r );
+
+WRITE8_DEVICE_HANDLER( wd17xx_command_w );
+WRITE8_DEVICE_HANDLER( wd17xx_track_w );
+WRITE8_DEVICE_HANDLER( wd17xx_sector_w );
+WRITE8_DEVICE_HANDLER( wd17xx_data_w );
+
+READ8_DEVICE_HANDLER( wd17xx_r );
+WRITE8_DEVICE_HANDLER( wd17xx_w );
+
+WRITE_LINE_DEVICE_HANDLER( wd17xx_mr_w );
+WRITE_LINE_DEVICE_HANDLER( wd17xx_rdy_w );
+READ_LINE_DEVICE_HANDLER( wd17xx_mo_r );
+WRITE_LINE_DEVICE_HANDLER( wd17xx_tr00_w );
+WRITE_LINE_DEVICE_HANDLER( wd17xx_idx_w );
+WRITE_LINE_DEVICE_HANDLER( wd17xx_wprt_w );
+WRITE_LINE_DEVICE_HANDLER( wd17xx_dden_w );
+READ_LINE_DEVICE_HANDLER( wd17xx_drq_r );
+READ_LINE_DEVICE_HANDLER( wd17xx_intrq_r );
+
+extern const wd17xx_interface default_wd17xx_interface;
+extern const wd17xx_interface default_wd17xx_interface_2_drives;
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+***************************************************************************/
+
+#define MCFG_FD1771_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, FD1771, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_FD1781_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, FD1781, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_FD1791_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, FD1791, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_FD1792_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, FD1792, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_FD1793_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, FD1793, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_FD1794_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, FD1794, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_FD1795_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, FD1795, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_FD1797_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, FD1797, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_FD1761_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, FD1761, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_FD1762_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, FD1762, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_FD1763_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, FD1763, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_FD1764_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, FD1764, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_FD1765_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, FD1765, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_FD1767_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, FD1767, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_WD2793_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, WD2793, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_WD2795_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, WD2795, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_WD2797_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, WD2797, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_WD1770_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, WD1770, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_WD1772_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, WD1772, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_WD1773_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, WD1773, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_MB8866_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, MB8866, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_MB8876_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, MB8876, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define MCFG_MB8877_ADD(_tag, _intrf) \
+ MCFG_DEVICE_ADD(_tag, MB8877, 0) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#endif /* __WD17XX_H__ */
diff --git a/trunk/src/emu/machine/wd33c93.c b/trunk/src/emu/machine/wd33c93.c
new file mode 100644
index 00000000000..4beca1d0780
--- /dev/null
+++ b/trunk/src/emu/machine/wd33c93.c
@@ -0,0 +1,877 @@
+/*
+ * wd33c93.c
+ *
+ * WD/AMD 33c93 SCSI controller, as seen in
+ * early PCs, some MSX add-ons, NEC PC-88, and SGI
+ * Indigo, Indigo2, and Indy systems.
+ *
+ * References:
+ * WD 33c93 manual
+ * NetBSD 33c93 driver
+ *
+ */
+
+#include "emu.h"
+#include "wd33c93.h"
+
+#define VERBOSE 0
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+static SCSIInstance *devices[8]; // SCSI IDs 0-7
+static const struct WD33C93interface *intf;
+
+/* wd register names */
+#define WD_OWN_ID 0x00
+#define WD_CONTROL 0x01
+#define WD_TIMEOUT_PERIOD 0x02
+#define WD_CDB_1 0x03
+#define WD_CDB_2 0x04
+#define WD_CDB_3 0x05
+#define WD_CDB_4 0x06
+#define WD_CDB_5 0x07
+#define WD_CDB_6 0x08
+#define WD_CDB_7 0x09
+#define WD_CDB_8 0x0a
+#define WD_CDB_9 0x0b
+#define WD_CDB_10 0x0c
+#define WD_CDB_11 0x0d
+#define WD_CDB_12 0x0e
+#define WD_TARGET_LUN 0x0f
+#define WD_COMMAND_PHASE 0x10
+#define WD_SYNCHRONOUS_TRANSFER 0x11
+#define WD_TRANSFER_COUNT_MSB 0x12
+#define WD_TRANSFER_COUNT 0x13
+#define WD_TRANSFER_COUNT_LSB 0x14
+#define WD_DESTINATION_ID 0x15
+#define WD_SOURCE_ID 0x16
+#define WD_SCSI_STATUS 0x17
+#define WD_COMMAND 0x18
+#define WD_DATA 0x19
+#define WD_QUEUE_TAG 0x1a
+#define WD_AUXILIARY_STATUS 0x1f
+
+/* WD commands */
+#define WD_CMD_RESET 0x00
+#define WD_CMD_ABORT 0x01
+#define WD_CMD_ASSERT_ATN 0x02
+#define WD_CMD_NEGATE_ACK 0x03
+#define WD_CMD_DISCONNECT 0x04
+#define WD_CMD_RESELECT 0x05
+#define WD_CMD_SEL_ATN 0x06
+#define WD_CMD_SEL 0x07
+#define WD_CMD_SEL_ATN_XFER 0x08
+#define WD_CMD_SEL_XFER 0x09
+#define WD_CMD_RESEL_RECEIVE 0x0a
+#define WD_CMD_RESEL_SEND 0x0b
+#define WD_CMD_WAIT_SEL_RECEIVE 0x0c
+#define WD_CMD_SSCC 0x0d
+#define WD_CMD_SND_DISC 0x0e
+#define WD_CMD_SET_IDI 0x0f
+#define WD_CMD_RCV_CMD 0x10
+#define WD_CMD_RCV_DATA 0x11
+#define WD_CMD_RCV_MSG_OUT 0x12
+#define WD_CMD_RCV 0x13
+#define WD_CMD_SND_STATUS 0x14
+#define WD_CMD_SND_DATA 0x15
+#define WD_CMD_SND_MSG_IN 0x16
+#define WD_CMD_SND 0x17
+#define WD_CMD_TRANS_ADDR 0x18
+#define WD_CMD_XFER_PAD 0x19
+#define WD_CMD_TRANS_INFO 0x20
+#define WD_CMD_TRANSFER_PAD 0x21
+#define WD_CMD_SBT_MODE 0x80
+
+/* ASR register */
+#define ASR_INT 0x80
+#define ASR_LCI 0x40
+#define ASR_BSY 0x20
+#define ASR_CIP 0x10
+#define ASR_PE 0x02
+#define ASR_DBR 0x01
+
+/* SCSI Bus Phases */
+#define PHS_DATA_OUT 0x00
+#define PHS_DATA_IN 0x01
+#define PHS_COMMAND 0x02
+#define PHS_STATUS 0x03
+#define PHS_MESS_OUT 0x06
+#define PHS_MESS_IN 0x07
+
+/* Command Status Register definitions */
+
+ /* reset state interrupts */
+#define CSR_RESET 0x00
+#define CSR_RESET_AF 0x01
+
+ /* successful completion interrupts */
+#define CSR_RESELECT 0x10
+#define CSR_SELECT 0x11
+#define CSR_SEL_XFER_DONE 0x16
+#define CSR_XFER_DONE 0x18
+
+ /* paused or aborted interrupts */
+#define CSR_MSGIN 0x20
+#define CSR_SDP 0x21
+#define CSR_SEL_ABORT 0x22
+#define CSR_RESEL_ABORT 0x25
+#define CSR_RESEL_ABORT_AM 0x27
+#define CSR_ABORT 0x28
+
+ /* terminated interrupts */
+#define CSR_INVALID 0x40
+#define CSR_UNEXP_DISC 0x41
+#define CSR_TIMEOUT 0x42
+#define CSR_PARITY 0x43
+#define CSR_PARITY_ATN 0x44
+#define CSR_BAD_STATUS 0x45
+#define CSR_UNEXP 0x48
+
+ /* service required interrupts */
+#define CSR_RESEL 0x80
+#define CSR_RESEL_AM 0x81
+#define CSR_DISC 0x85
+#define CSR_SRV_REQ 0x88
+
+ /* Own ID/CDB Size register */
+#define OWNID_EAF 0x08
+#define OWNID_EHP 0x10
+#define OWNID_RAF 0x20
+#define OWNID_FS_8 0x00
+#define OWNID_FS_12 0x40
+#define OWNID_FS_16 0x80
+
+ /* Control register */
+#define CTRL_HSP 0x01
+#define CTRL_HA 0x02
+#define CTRL_IDI 0x04
+#define CTRL_EDI 0x08
+#define CTRL_HHP 0x10
+#define CTRL_POLLED 0x00
+#define CTRL_BURST 0x20
+#define CTRL_BUS 0x40
+#define CTRL_DMA 0x80
+
+ /* Synchronous Transfer Register */
+#define STR_FSS 0x80
+
+ /* Destination ID register */
+#define DSTID_DPD 0x40
+#define DATA_OUT_DIR 0
+#define DATA_IN_DIR 1
+#define DSTID_SCC 0x80
+
+ /* Source ID register */
+#define SRCID_MASK 0x07
+#define SRCID_SIV 0x08
+#define SRCID_DSP 0x20
+#define SRCID_ES 0x40
+#define SRCID_ER 0x80
+
+/* command handler definition */
+typedef void (*cmd_handler)(running_machine &machine);
+#define CMD_HANDLER(name) void name(running_machine &machine)
+
+#define TEMP_INPUT_LEN 262144
+#define FIFO_SIZE 12
+
+/* internal controller data definition */
+typedef struct
+{
+ UINT8 sasr;
+ UINT8 regs[WD_AUXILIARY_STATUS+1];
+ UINT8 fifo[FIFO_SIZE];
+ int fifo_pos;
+ UINT8 *temp_input;
+ int temp_input_pos;
+ UINT8 busphase;
+ UINT8 identify;
+ int read_pending;
+ emu_timer *cmd_timer;
+} _wd33c93_data;
+
+/* local instance of controller data */
+static _wd33c93_data scsi_data;
+
+
+/* convernience functions */
+static UINT8 wd33c93_getunit( void )
+{
+ /* return the destination unit id */
+ return scsi_data.regs[WD_DESTINATION_ID] & SRCID_MASK;
+}
+
+static void wd33c93_set_xfer_count( int count )
+{
+ /* set the count */
+ scsi_data.regs[ WD_TRANSFER_COUNT_LSB ] = count & 0xff;
+ scsi_data.regs[ WD_TRANSFER_COUNT ] = ( count >> 8 ) & 0xff;
+ scsi_data.regs[ WD_TRANSFER_COUNT_MSB ] = ( count >> 16 ) & 0xff;
+}
+
+static int wd33c93_get_xfer_count( void )
+{
+ /* get the count */
+ int count = scsi_data.regs[ WD_TRANSFER_COUNT_MSB ];
+
+ count <<= 8;
+ count |= scsi_data.regs[ WD_TRANSFER_COUNT ];
+ count <<= 8;
+ count |= scsi_data.regs[ WD_TRANSFER_COUNT_LSB ];
+
+ return count;
+}
+
+static void wd33c93_read_data(int bytes, UINT8 *pData)
+{
+ UINT8 unit = wd33c93_getunit();
+
+ if ( devices[unit] )
+ {
+ SCSIReadData( devices[unit], pData, bytes );
+ }
+ else
+ {
+ logerror("wd33c93: request for unknown device SCSI ID %d\n", unit);
+ }
+}
+
+static void wd33c93_complete_immediate( running_machine &machine, int status )
+{
+ /* reset our timer */
+ scsi_data.cmd_timer->reset( );
+
+ /* set the new status */
+ scsi_data.regs[WD_SCSI_STATUS] = status & 0xff;
+
+ /* set interrupt pending */
+ scsi_data.regs[WD_AUXILIARY_STATUS] |= ASR_INT;
+
+ /* check for error conditions */
+ if ( wd33c93_get_xfer_count() > 0 )
+ {
+ /* set data buffer ready */
+ scsi_data.regs[WD_AUXILIARY_STATUS] |= ASR_DBR;
+ }
+ else
+ {
+ /* clear data buffer ready */
+ scsi_data.regs[WD_AUXILIARY_STATUS] &= ~ASR_DBR;
+ }
+
+ /* clear command in progress and bus busy */
+ scsi_data.regs[WD_AUXILIARY_STATUS] &= ~(ASR_CIP | ASR_BSY);
+
+ /* if we have a callback, call it */
+ if (intf && intf->irq_callback)
+ {
+ intf->irq_callback(machine, 1);
+ }
+}
+
+static TIMER_CALLBACK(wd33c93_complete_cb)
+{
+ wd33c93_complete_immediate( machine, param );
+}
+
+static TIMER_CALLBACK(wd33c93_service_request)
+{
+ /* issue a message out request */
+ wd33c93_complete_immediate(machine, CSR_SRV_REQ | scsi_data.busphase);
+}
+
+static TIMER_CALLBACK(wd33c93_deassert_cip)
+{
+ scsi_data.regs[WD_AUXILIARY_STATUS] &= ~ASR_CIP;
+}
+
+static void wd33c93_complete_cmd( UINT8 status )
+{
+ /* fire off a timer to complete the command */
+ scsi_data.cmd_timer->adjust( attotime::from_usec(1), status );
+}
+
+/* command handlers */
+static CMD_HANDLER( wd33c93_invalid_cmd )
+{
+ logerror( "%s:Unknown/Unimplemented SCSI controller command: %02x\n", machine.describe_context(), scsi_data.regs[WD_COMMAND] );
+
+ /* complete the command */
+ wd33c93_complete_cmd( CSR_INVALID );
+}
+
+static CMD_HANDLER( wd33c93_reset_cmd )
+{
+ int advanced = 0;
+
+ /* see if it wants us to reset with advanced features */
+ if ( scsi_data.regs[WD_OWN_ID] & OWNID_EAF )
+ {
+ advanced = 1;
+ }
+
+ /* clear out all registers */
+ memset( scsi_data.regs, 0, sizeof( scsi_data.regs ) );
+
+ /* complete the command */
+ wd33c93_complete_cmd(advanced ? CSR_RESET_AF : CSR_RESET);
+}
+
+static CMD_HANDLER( wd33c93_abort_cmd )
+{
+ /* complete the command */
+ wd33c93_complete_cmd(CSR_ABORT);
+}
+
+static CMD_HANDLER( wd33c93_disconnect_cmd )
+{
+ /* complete the command */
+ scsi_data.regs[WD_AUXILIARY_STATUS] &= ~(ASR_CIP | ASR_BSY);
+}
+
+static CMD_HANDLER( wd33c93_select_cmd )
+{
+ UINT8 unit = wd33c93_getunit();
+ UINT8 newstatus;
+
+ /* see if we can select that device */
+ if ( devices[unit] )
+ {
+ /* device is available - signal selection done */
+ newstatus = CSR_SELECT;
+
+ /* determine the next bus phase depending on the command */
+ if ( (scsi_data.regs[WD_COMMAND] & 0x7f) == WD_CMD_SEL_ATN )
+ {
+ /* /ATN asserted during select: Move to Message Out Phase to read identify */
+ scsi_data.busphase = PHS_MESS_OUT;
+ }
+ else
+ {
+ /* No /ATN asserted: Move to Command Phase */
+ scsi_data.busphase = PHS_COMMAND;
+ }
+
+ /* queue up a service request out in the future */
+ machine.scheduler().timer_set( attotime::from_usec(50), FUNC(wd33c93_service_request ));
+ }
+ else
+ {
+ /* device is not available */
+ newstatus = CSR_TIMEOUT;
+ }
+
+ /* complete the command */
+ wd33c93_complete_cmd(newstatus);
+}
+
+static CMD_HANDLER( wd33c93_selectxfer_cmd )
+{
+ UINT8 unit = wd33c93_getunit();
+ UINT8 newstatus;
+
+ /* see if we can select that device */
+ if ( devices[unit] )
+ {
+ if ( scsi_data.regs[WD_COMMAND_PHASE] < 0x45 )
+ {
+ /* device is available */
+ int xfercount;
+ int phase;
+
+ /* do the request */
+ SCSISetCommand( devices[unit], &scsi_data.regs[WD_CDB_1], 12 );
+ SCSIExecCommand( devices[unit], &xfercount );
+ SCSIGetPhase( devices[unit], &phase );
+
+ /* set transfer count */
+ if ( wd33c93_get_xfer_count() > TEMP_INPUT_LEN )
+ {
+ logerror( "WD33C93: Transfer count too big. Please increase TEMP_INPUT_LEN (size=%d)\n", wd33c93_get_xfer_count() );
+ wd33c93_set_xfer_count( TEMP_INPUT_LEN );
+ }
+
+ switch( phase )
+ {
+ case SCSI_PHASE_DATAIN:
+ scsi_data.read_pending = 1;
+ break;
+ }
+ }
+
+ if ( scsi_data.read_pending )
+ {
+ int len = TEMP_INPUT_LEN;
+
+ if ( wd33c93_get_xfer_count() < len ) len = wd33c93_get_xfer_count();
+
+ memset( &scsi_data.temp_input[0], 0, TEMP_INPUT_LEN );
+ wd33c93_read_data( len, &scsi_data.temp_input[0] );
+ scsi_data.temp_input_pos = 0;
+ scsi_data.read_pending = 0;
+ }
+
+ scsi_data.regs[WD_TARGET_LUN] = 0;
+ scsi_data.regs[WD_CONTROL] |= CTRL_EDI;
+ scsi_data.regs[WD_COMMAND_PHASE] = 0x60;
+
+ /* signal transfer ready */
+ newstatus = CSR_SEL_XFER_DONE;
+
+ /* if allowed disconnect, queue a service request */
+ if ( scsi_data.identify & 0x40 )
+ {
+ /* queue disconnect message in */
+ scsi_data.busphase = PHS_MESS_IN;
+
+ /* queue up a service request out in the future */
+ machine.scheduler().timer_set( attotime::from_msec(50), FUNC(wd33c93_service_request ));
+ }
+ }
+ else
+ {
+ /* device is not available */
+ newstatus = CSR_TIMEOUT;
+
+ wd33c93_set_xfer_count( 0 );
+ }
+
+ /* complete the command */
+ wd33c93_complete_cmd(newstatus);
+}
+
+static CMD_HANDLER( wd33c93_negate_ack )
+{
+ logerror( "WD33C93: ACK Negated\n" );
+
+ /* complete the command */
+ scsi_data.regs[WD_AUXILIARY_STATUS] &= ~(ASR_CIP | ASR_BSY);
+}
+
+static CMD_HANDLER( wd33c93_xferinfo_cmd )
+{
+ /* make the buffer available right away */
+ scsi_data.regs[WD_AUXILIARY_STATUS] |= ASR_DBR;
+ scsi_data.regs[WD_AUXILIARY_STATUS] |= ASR_CIP;
+
+ /* the command will be completed once the data is transferred */
+ machine.scheduler().timer_set( attotime::from_msec(1), FUNC(wd33c93_deassert_cip ));
+}
+
+/* Command handlers */
+static const cmd_handler wd33c93_cmds[0x22] =
+{
+ &wd33c93_reset_cmd, /* 0x00 - WD_CMD_RESET */
+ &wd33c93_abort_cmd, /* 0x01 - WD_CMD_ABORT */
+ &wd33c93_invalid_cmd, /* 0x02 - WD_CMD_ASSERT_ATN (uninmplemented) */
+ &wd33c93_negate_ack, /* 0x03 - WD_CMD_NEGATE_ACK */
+ &wd33c93_disconnect_cmd,/* 0x04 - WD_CMD_DISCONNECT */
+ &wd33c93_invalid_cmd, /* 0x05 - WD_CMD_RESELECT (uninmplemented) */
+ &wd33c93_select_cmd, /* 0x06 - WD_CMD_SEL_ATN */
+ &wd33c93_select_cmd, /* 0x07 - WD_CMD_SEL */
+ &wd33c93_selectxfer_cmd,/* 0x08 - WD_CMD_SEL_ATN_XFER */
+ &wd33c93_selectxfer_cmd,/* 0x09 - WD_CMD_SEL_XFER */
+ &wd33c93_invalid_cmd, /* 0x0a - WD_CMD_RESEL_RECEIVE (uninmplemented) */
+ &wd33c93_invalid_cmd, /* 0x0b - WD_CMD_RESEL_SEND (uninmplemented) */
+ &wd33c93_invalid_cmd, /* 0x0c - WD_CMD_WAIT_SEL_RECEIVE (uninmplemented) */
+ &wd33c93_invalid_cmd, /* 0x0d - WD_CMD_SSCC (uninmplemented) */
+ &wd33c93_invalid_cmd, /* 0x0e - WD_CMD_SND_DISC (uninmplemented) */
+ &wd33c93_invalid_cmd, /* 0x0f - WD_CMD_SET_IDI (uninmplemented) */
+ &wd33c93_invalid_cmd, /* 0x10 - WD_CMD_RCV_CMD (uninmplemented) */
+ &wd33c93_invalid_cmd, /* 0x11 - WD_CMD_RCV_DATA (uninmplemented) */
+ &wd33c93_invalid_cmd, /* 0x12 - WD_CMD_RCV_MSG_OUT (uninmplemented) */
+ &wd33c93_invalid_cmd, /* 0x13 - WD_CMD_RCV (uninmplemented) */
+ &wd33c93_invalid_cmd, /* 0x14 - WD_CMD_SND_STATUS (uninmplemented) */
+ &wd33c93_invalid_cmd, /* 0x15 - WD_CMD_SND_DATA (uninmplemented) */
+ &wd33c93_invalid_cmd, /* 0x16 - WD_CMD_SND_MSG_IN (uninmplemented) */
+ &wd33c93_invalid_cmd, /* 0x17 - WD_CMD_SND (uninmplemented) */
+ &wd33c93_invalid_cmd, /* 0x18 - WD_CMD_TRANS_ADDR (uninmplemented) */
+ &wd33c93_invalid_cmd, /* 0x19 - WD_CMD_XFER_PAD (uninmplemented) */
+ &wd33c93_invalid_cmd, /* 0x1a - invalid */
+ &wd33c93_invalid_cmd, /* 0x1b - invalid */
+ &wd33c93_invalid_cmd, /* 0x1c - invalid */
+ &wd33c93_invalid_cmd, /* 0x1d - invalid */
+ &wd33c93_invalid_cmd, /* 0x1e - invalid */
+ &wd33c93_invalid_cmd, /* 0x1f - invalid */
+ &wd33c93_xferinfo_cmd, /* 0x20 - WD_CMD_TRANS_INFO) */
+ &wd33c93_invalid_cmd /* 0x21 - WD_CMD_TRANSFER_PAD (uninmplemented) */
+};
+
+/* Handle pending commands */
+static void wd33c93_command( running_machine &machine )
+{
+ /* get the command */
+ UINT8 cmd = scsi_data.regs[WD_COMMAND];
+
+ /* check if its within valid bounds */
+ if ( (cmd & 0x7F) > WD_CMD_TRANSFER_PAD )
+ {
+ wd33c93_invalid_cmd(machine);
+ return;
+ }
+
+ /* call the command handler */
+ (*wd33c93_cmds[cmd & 0x7F])(machine);
+}
+
+WRITE8_HANDLER(wd33c93_w)
+{
+ switch( offset )
+ {
+ case 0:
+ {
+ /* update register select */
+ scsi_data.sasr = data & 0x1f;
+ }
+ break;
+
+ case 1:
+ {
+ LOG(( "WD33C93: PC=%08x - Write REG=%02x, data = %02x\n", cpu_get_pc(&space->device()), scsi_data.sasr, data ));
+
+ /* update the register */
+ scsi_data.regs[scsi_data.sasr] = data;
+
+ /* if we receive a command, schedule to process it */
+ if ( scsi_data.sasr == WD_COMMAND )
+ {
+ LOG(( "WDC33C93: PC=%08x - Executing command %08x - unit %d\n", cpu_get_pc(&space->device()), data, wd33c93_getunit() ));
+
+ /* signal we're processing it */
+ scsi_data.regs[WD_AUXILIARY_STATUS] |= ASR_CIP;
+
+ /* process the command */
+ wd33c93_command(space->machine());
+ }
+ else if ( scsi_data.sasr == WD_CDB_1 )
+ {
+ scsi_data.regs[WD_COMMAND_PHASE] = 0;
+ }
+ else if ( scsi_data.sasr == WD_DATA )
+ {
+ /* if data was written, and we have a count, send to device */
+ int count = wd33c93_get_xfer_count();
+
+ if ( scsi_data.regs[WD_COMMAND] & 0x80 )
+ count = 1;
+
+ if ( count-- > 0 )
+ {
+ /* write to FIFO */
+ if ( scsi_data.fifo_pos < FIFO_SIZE )
+ {
+ scsi_data.fifo[scsi_data.fifo_pos++] = data;
+ }
+
+ /* update count */
+ wd33c93_set_xfer_count( count );
+
+ /* if we're done with the write, see where we're at */
+ if ( count == 0 )
+ {
+ scsi_data.regs[WD_AUXILIARY_STATUS] |= ASR_INT;
+ scsi_data.regs[WD_AUXILIARY_STATUS] &= ~ASR_DBR;
+
+ switch( scsi_data.busphase )
+ {
+ case PHS_MESS_OUT:
+ {
+ /* reset fifo */
+ scsi_data.fifo_pos = 0;
+
+ /* Message out phase. Data is probably SCSI Identify. Move to command phase. */
+ scsi_data.busphase = PHS_COMMAND;
+
+ scsi_data.identify = scsi_data.fifo[0];
+ }
+ break;
+
+ case PHS_COMMAND:
+ {
+ UINT8 unit = wd33c93_getunit();
+ int xfercount;
+ int phase;
+
+ /* Execute the command. Depending on the command, we'll move to data in or out */
+ SCSISetCommand( devices[unit], &scsi_data.fifo[0], 12 );
+ SCSIExecCommand( devices[unit], &xfercount );
+ SCSIGetPhase( devices[unit], &phase );
+
+ /* reset fifo */
+ scsi_data.fifo_pos = 0;
+
+ /* set the new count */
+ wd33c93_set_xfer_count( xfercount );
+
+ switch( phase )
+ {
+ case SCSI_PHASE_STATUS:
+ scsi_data.busphase = PHS_STATUS;
+ break;
+
+ case SCSI_PHASE_DATAIN:
+ scsi_data.busphase = PHS_DATA_IN;
+ scsi_data.read_pending = 1;
+ break;
+
+ case SCSI_PHASE_DATAOUT:
+ scsi_data.busphase = PHS_DATA_OUT;
+ break;
+ }
+ }
+ break;
+
+ case PHS_DATA_OUT:
+ {
+ /* write data out to device */
+ wd33c93_write_data( scsi_data.fifo_pos, scsi_data.fifo );
+
+ /* reset fifo */
+ scsi_data.fifo_pos = 0;
+
+ /* move to status phase */
+ scsi_data.busphase = PHS_STATUS;
+ }
+ break;
+ }
+
+ /* complete the command */
+ wd33c93_complete_immediate(space->machine(), CSR_XFER_DONE | scsi_data.busphase);
+ }
+ }
+ else
+ {
+ logerror( "WD33C93: Sending data to device with transfer count = 0!. Ignoring...\n" );
+ }
+ }
+
+ /* auto-increment register select if not on special registers */
+ if ( scsi_data.sasr != WD_COMMAND && scsi_data.sasr != WD_DATA && scsi_data.sasr != WD_AUXILIARY_STATUS )
+ {
+ scsi_data.sasr = ( scsi_data.sasr + 1 ) & 0x1f;
+ }
+ }
+ break;
+
+ default:
+ {
+ logerror( "WD33C93: Write to invalid offset %d (data=%02x)\n", offset, data );
+ }
+ break;
+ }
+}
+
+READ8_HANDLER(wd33c93_r)
+{
+ switch( offset )
+ {
+ case 0:
+ {
+ /* read aux status */
+ return scsi_data.regs[WD_AUXILIARY_STATUS];
+ }
+ break;
+
+ case 1:
+ {
+ UINT8 ret;
+
+ /* if reading status, clear irq flag */
+ if ( scsi_data.sasr == WD_SCSI_STATUS )
+ {
+ scsi_data.regs[WD_AUXILIARY_STATUS] &= ~ASR_INT;
+
+ if (intf && intf->irq_callback)
+ {
+ intf->irq_callback(space->machine(), 0);
+ }
+
+ LOG(( "WD33C93: PC=%08x - Status read (%02x)\n", cpu_get_pc(&space->device()), scsi_data.regs[WD_SCSI_STATUS] ));
+ }
+ else if ( scsi_data.sasr == WD_DATA )
+ {
+ /* we're going to be doing synchronous reads */
+
+ /* get the transfer count */
+ int count = wd33c93_get_xfer_count();
+
+ /* initialize the return value */
+ scsi_data.regs[WD_DATA] = 0;
+
+ if ( count <= 0 && scsi_data.busphase == PHS_MESS_IN )
+ {
+ /* move to disconnect */
+ wd33c93_complete_cmd(CSR_DISC);
+ }
+ else if ( count == 1 && scsi_data.busphase == PHS_STATUS )
+ {
+ /* update the count */
+ wd33c93_set_xfer_count( 0 );
+
+ /* move to message in phase */
+ scsi_data.busphase = PHS_MESS_IN;
+
+ /* complete the command */
+ wd33c93_complete_cmd(CSR_XFER_DONE | scsi_data.busphase);
+ }
+ else if ( count-- > 0 ) /* make sure we still have data to send */
+ {
+ if ( scsi_data.read_pending )
+ {
+ int len = TEMP_INPUT_LEN;
+
+ if ( (count+1) < len ) len = count+1;
+ wd33c93_read_data( len, &scsi_data.temp_input[0] );
+ scsi_data.temp_input_pos = 0;
+ scsi_data.read_pending = 0;
+ }
+
+ scsi_data.regs[WD_AUXILIARY_STATUS] &= ~ASR_INT;
+
+ /* read in one byte */
+ if ( scsi_data.temp_input_pos < TEMP_INPUT_LEN )
+ scsi_data.regs[WD_DATA] = scsi_data.temp_input[scsi_data.temp_input_pos++];
+
+ /* update the count */
+ wd33c93_set_xfer_count( count );
+
+ /* transfer finished, see where we're at */
+ if ( count == 0 )
+ {
+ if ( scsi_data.regs[WD_COMMAND_PHASE] != 0x60 )
+ {
+ /* move to status phase */
+ scsi_data.busphase = PHS_STATUS;
+
+ /* complete the command */
+ wd33c93_complete_cmd(CSR_XFER_DONE | scsi_data.busphase);
+ }
+ else
+ {
+ scsi_data.regs[WD_AUXILIARY_STATUS] |= ASR_INT;
+ scsi_data.regs[WD_AUXILIARY_STATUS] &= ~ASR_DBR;
+ }
+ }
+ }
+ }
+
+ LOG(( "WD33C93: PC=%08x - Data read (%02x)\n", cpu_get_pc(&space->device()), scsi_data.regs[WD_DATA] ));
+
+ /* get the register value */
+ ret = scsi_data.regs[scsi_data.sasr];
+
+ /* auto-increment register select if not on special registers */
+ if ( scsi_data.sasr != WD_COMMAND && scsi_data.sasr != WD_DATA && scsi_data.sasr != WD_AUXILIARY_STATUS )
+ {
+ scsi_data.sasr = ( scsi_data.sasr + 1 ) & 0x1f;
+ }
+
+ return ret;
+ }
+
+ default:
+ {
+ logerror( "WD33C93: Read from invalid offset %d\n", offset );
+ }
+ break;
+ }
+
+ return 0;
+}
+
+void wd33c93_init( running_machine &machine, const struct WD33C93interface *interface )
+{
+ int i;
+
+ // save interface pointer for later
+ intf = interface;
+
+ memset(&scsi_data, 0, sizeof(scsi_data));
+ memset(devices, 0, sizeof(devices));
+
+ // try to open the devices
+ for (i = 0; i < interface->scsidevs->devs_present; i++)
+ {
+ SCSIAllocInstance( machine, interface->scsidevs->devices[i].scsiClass, &devices[interface->scsidevs->devices[i].scsiID], interface->scsidevs->devices[i].diskregion );
+ }
+
+ /* allocate a timer for commands */
+ scsi_data.cmd_timer = machine.scheduler().timer_alloc(FUNC(wd33c93_complete_cb));
+
+ scsi_data.temp_input = auto_alloc_array( machine, UINT8, TEMP_INPUT_LEN );
+
+// state_save_register_item_array(machine, "wd33c93", NULL, 0, scsi_data);
+}
+
+void wd33c93_exit( const struct WD33C93interface *interface )
+{
+ int i;
+
+ for (i = 0; i < interface->scsidevs->devs_present; i++)
+ {
+ SCSIDeleteInstance( devices[interface->scsidevs->devices[i].scsiID] );
+ }
+}
+
+void wd33c93_get_dma_data( int bytes, UINT8 *pData )
+{
+ int len = bytes;
+
+ if ( len >= wd33c93_get_xfer_count() )
+ len = wd33c93_get_xfer_count();
+
+ if ( len == 0 )
+ return;
+
+ if ( (scsi_data.temp_input_pos+len) >= TEMP_INPUT_LEN )
+ {
+ logerror( "Reading past end of buffer, increase TEMP_INPUT_LEN size\n" );
+ len = TEMP_INPUT_LEN - len;
+ }
+
+ assert(len);
+
+ memcpy( pData, &scsi_data.temp_input[scsi_data.temp_input_pos], len );
+
+ scsi_data.temp_input_pos += len;
+ len = wd33c93_get_xfer_count() - len;
+ wd33c93_set_xfer_count(len);
+}
+
+void wd33c93_write_data(int bytes, UINT8 *pData)
+{
+ UINT8 unit = wd33c93_getunit();
+
+ if (devices[unit])
+ {
+ SCSIWriteData( devices[unit], pData, bytes );
+ }
+ else
+ {
+ logerror("wd33c93: request for unknown device SCSI ID %d\n", unit);
+ }
+}
+
+void *wd33c93_get_device(int id)
+{
+ void *ret;
+
+ if (devices[id])
+ {
+ SCSIGetDevice( devices[id], &ret );
+ return ret;
+ }
+
+ return NULL;
+}
+
+void wd33c93_clear_dma(void)
+{
+ /* indicate DMA completed by clearing the transfer count */
+ wd33c93_set_xfer_count(0);
+ scsi_data.regs[WD_AUXILIARY_STATUS] &= ~ASR_DBR;
+}
+
+int wd33c93_get_dma_count(void)
+{
+ return wd33c93_get_xfer_count();
+}
diff --git a/trunk/src/emu/machine/wd33c93.h b/trunk/src/emu/machine/wd33c93.h
new file mode 100644
index 00000000000..2804019dbbc
--- /dev/null
+++ b/trunk/src/emu/machine/wd33c93.h
@@ -0,0 +1,27 @@
+/*
+ * wd33c93.h
+ *
+ */
+
+#ifndef _WD33C93_H_
+#define _WD33C93_H_
+
+#include "machine/scsi.h"
+
+struct WD33C93interface
+{
+ const SCSIConfigTable *scsidevs; /* SCSI devices */
+ void (*irq_callback)(running_machine &machine, int state); /* irq callback */
+};
+
+extern void wd33c93_init( running_machine &machine, const struct WD33C93interface *interface );
+extern void wd33c93_exit( const struct WD33C93interface *interface );
+extern void wd33c93_get_dma_data(int bytes, UINT8 *pData);
+extern void wd33c93_write_data(int bytes, UINT8 *pData);
+extern void *wd33c93_get_device(int id);
+extern void wd33c93_clear_dma(void);
+extern int wd33c93_get_dma_count(void);
+extern READ8_HANDLER(wd33c93_r);
+extern WRITE8_HANDLER(wd33c93_w);
+
+#endif
diff --git a/trunk/src/emu/machine/x2212.c b/trunk/src/emu/machine/x2212.c
new file mode 100644
index 00000000000..a20a8321a54
--- /dev/null
+++ b/trunk/src/emu/machine/x2212.c
@@ -0,0 +1,227 @@
+/***************************************************************************
+
+ x2212.c
+
+ Xicor X2212 256 x 4 bit Nonvolatile Static RAM.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "machine/x2212.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+static ADDRESS_MAP_START( x2212_sram_map, AS_0, 8 )
+ AM_RANGE(0x0000, 0x00ff) AM_RAM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( x2212_e2prom_map, AS_1, 8 )
+ AM_RANGE(0x0000, 0x00ff) AM_RAM
+ADDRESS_MAP_END
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type X2212 = &device_creator<x2212_device>;
+
+//-------------------------------------------------
+// x2212_device - constructor
+//-------------------------------------------------
+
+x2212_device::x2212_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, X2212, "X2212", tag, owner, clock),
+ device_memory_interface(mconfig, *this),
+ device_nvram_interface(mconfig, *this),
+ m_auto_save(false),
+ m_sram_space_config("SRAM", ENDIANNESS_BIG, 8, 8, 0, *ADDRESS_MAP_NAME(x2212_sram_map)),
+ m_e2prom_space_config("E2PROM", ENDIANNESS_BIG, 8, 8, 0, *ADDRESS_MAP_NAME(x2212_e2prom_map)),
+ m_store(false),
+ m_array_recall(false)
+{
+}
+
+
+//-------------------------------------------------
+// static_set_auto_save - configuration helper
+// to set the auto-save flag
+//-------------------------------------------------
+
+void x2212_device::static_set_auto_save(device_t &device)
+{
+ downcast<x2212_device &>(device).m_auto_save = true;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void x2212_device::device_start()
+{
+ save_item(NAME(m_store));
+ save_item(NAME(m_array_recall));
+
+ m_sram = m_addrspace[0];
+ m_e2prom = m_addrspace[1];
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return a description of
+// any address spaces owned by this device
+//-------------------------------------------------
+
+const address_space_config *x2212_device::memory_space_config(address_spacenum spacenum) const
+{
+ return (spacenum == 0) ? &m_sram_space_config : (spacenum == 1) ? &m_e2prom_space_config : NULL;
+}
+
+
+//-------------------------------------------------
+// nvram_default - called to initialize NVRAM to
+// its default state
+//-------------------------------------------------
+
+void x2212_device::nvram_default()
+{
+ // default to all-0xff
+ for (int byte = 0; byte < SIZE_DATA; byte++)
+ {
+ m_sram->write_byte(byte, 0xff);
+ m_e2prom->write_byte(byte, 0xff);
+ }
+
+ // populate from a memory region if present
+ if (m_region != NULL)
+ {
+ if (m_region->bytes() != SIZE_DATA)
+ fatalerror("x2212 region '%s' wrong size (expected size = 0x100)", tag());
+ if (m_region->width() != 1)
+ fatalerror("x2212 region '%s' needs to be an 8-bit region", tag());
+
+ for (int byte = 0; byte < SIZE_DATA; byte++)
+ m_e2prom->write_byte(byte, m_region->u8(byte));
+ }
+}
+
+
+//-------------------------------------------------
+// nvram_read - called to read NVRAM from the
+// .nv file
+//-------------------------------------------------
+
+void x2212_device::nvram_read(emu_file &file)
+{
+ UINT8 buffer[SIZE_DATA];
+ file.read(buffer, sizeof(buffer));
+ for (int byte = 0; byte < SIZE_DATA; byte++)
+ {
+ m_sram->write_byte(byte, 0xff);
+ m_e2prom->write_byte(byte, buffer[byte]);
+ }
+}
+
+
+//-------------------------------------------------
+// nvram_write - called to write NVRAM to the
+// .nv file
+//-------------------------------------------------
+
+void x2212_device::nvram_write(emu_file &file)
+{
+ // auto-save causes an implicit store prior to exiting (writing)
+ if (m_auto_save)
+ store();
+
+ UINT8 buffer[SIZE_DATA];
+ for (int byte = 0; byte < SIZE_DATA; byte++)
+ buffer[byte] = m_e2prom->read_byte(byte);
+ file.write(buffer, sizeof(buffer));
+}
+
+
+
+//**************************************************************************
+// INTERNAL HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// store - store data from live RAM into the
+// EEPROM
+//-------------------------------------------------
+
+void x2212_device::store()
+{
+ for (int byte = 0; byte < SIZE_DATA; byte++)
+ m_e2prom->write_byte(byte, m_sram->read_byte(byte));
+}
+
+
+//-------------------------------------------------
+// recall - fetch data from the EEPROM into live
+// RAM
+//-------------------------------------------------
+
+void x2212_device::recall()
+{
+ for (int byte = 0; byte < SIZE_DATA; byte++)
+ m_sram->write_byte(byte, m_e2prom->read_byte(byte));
+}
+
+
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+//-------------------------------------------------
+// write - store to the live RAM
+//-------------------------------------------------
+
+WRITE8_MEMBER( x2212_device::write )
+{
+ m_sram->write_byte(offset, data & 0x0f);
+}
+
+
+//-------------------------------------------------
+// read - read from the live RAM
+//-------------------------------------------------
+
+READ8_MEMBER( x2212_device::read )
+{
+ return (m_sram->read_byte(offset) & 0x0f) | (space.unmap() & 0xf0);
+}
+
+
+//-------------------------------------------------
+// store - set the state of the store line
+// (active high)
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( x2212_device::store )
+{
+ if (state != 0 && !m_store)
+ store();
+ m_store = (state != 0);
+}
+
+
+//-------------------------------------------------
+// recall - set the state of the recall line
+// (active high)
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( x2212_device::recall )
+{
+ if (state != 0 && !m_array_recall)
+ recall();
+ m_array_recall = (state != 0);
+}
diff --git a/trunk/src/emu/machine/x2212.h b/trunk/src/emu/machine/x2212.h
new file mode 100644
index 00000000000..bebc5590baf
--- /dev/null
+++ b/trunk/src/emu/machine/x2212.h
@@ -0,0 +1,94 @@
+/***************************************************************************
+
+ x2212.h
+
+ Xicor X2212 256 x 4 bit Nonvolatile Static RAM.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __X2212_H__
+#define __X2212_H__
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_X2212_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, X2212, 0) \
+
+// some systems (like many early Atari games) wire up the /STORE signal
+// to fire on power-down, effectively creating an "auto-save" functionality
+#define MCFG_X2212_ADD_AUTOSAVE(_tag) \
+ MCFG_DEVICE_ADD(_tag, X2212, 0) \
+ x2212_device::static_set_auto_save(*device); \
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> x2212_device
+
+class x2212_device : public device_t,
+ public device_memory_interface,
+ public device_nvram_interface
+{
+public:
+ // construction/destruction
+ x2212_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // inline configuration helpers
+ static void static_set_auto_save(device_t &device);
+
+ // I/O operations
+ DECLARE_READ8_MEMBER( read );
+ DECLARE_WRITE8_MEMBER( write );
+
+ DECLARE_WRITE_LINE_MEMBER( store );
+ DECLARE_WRITE_LINE_MEMBER( recall );
+
+protected:
+ // internal helpers
+ void store();
+ void recall();
+
+ // device-level overrides
+ virtual void device_start();
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
+
+ // device_nvram_interface overrides
+ virtual void nvram_default();
+ virtual void nvram_read(emu_file &file);
+ virtual void nvram_write(emu_file &file);
+
+ static const int SIZE_DATA = 0x100;
+
+ // configuration state
+ bool m_auto_save;
+
+ // device-specific configuration
+ address_space_config m_sram_space_config;
+ address_space_config m_e2prom_space_config;
+
+ // internal state
+ address_space * m_sram;
+ address_space * m_e2prom;
+
+ bool m_store;
+ bool m_array_recall;
+};
+
+
+// device type definition
+extern const device_type X2212;
+
+
+#endif
diff --git a/trunk/src/emu/machine/x76f041.c b/trunk/src/emu/machine/x76f041.c
new file mode 100644
index 00000000000..a3ee45df84d
--- /dev/null
+++ b/trunk/src/emu/machine/x76f041.c
@@ -0,0 +1,416 @@
+/*
+ * x76f041.c
+ *
+ * Secure SerialFlash
+ *
+ * The X76F041 is a Password Access Security Supervisor, containing four 128 x 8 bit SecureFlash arrays.
+ * Access can be controlled by three 64-bit programmable passwords, one for read operations, one for write
+ * operations and one for device configuration.
+ *
+ * The data sheet has an incorrect diagrams for sequential read with password, there shouldn't be an extra address after the 0xc0 command.
+ *
+ */
+
+#include "emu.h"
+#include "machine/x76f041.h"
+
+#define VERBOSE_LEVEL 0
+
+inline void ATTR_PRINTF(3,4) x76f041_device::verboselog(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("x76f041 %s %s: %s", tag(), machine().describe_context(), buf);
+ }
+}
+
+// device type definition
+const device_type X76F041 = &device_creator<x76f041_device>;
+
+x76f041_device::x76f041_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_secure_serial_flash(mconfig, X76F041, "X76F041", tag, owner, clock)
+{
+}
+
+void x76f041_device::device_start()
+{
+ device_secure_serial_flash::device_start();
+ save_item(NAME(state));
+ save_item(NAME(shift));
+ save_item(NAME(bit));
+ save_item(NAME(byte));
+ save_item(NAME(command));
+ save_item(NAME(address));
+ save_item(NAME(write_buffer));
+ save_item(NAME(response_to_reset));
+ save_item(NAME(write_password));
+ save_item(NAME(read_password));
+ save_item(NAME(configuration_password));
+ save_item(NAME(configuration_registers));
+ save_item(NAME(data));
+}
+
+void x76f041_device::device_reset()
+{
+ device_secure_serial_flash::device_reset();
+ state = STATE_STOP;
+ shift = 0;
+ bit = 0;
+ byte = 0;
+ command = 0;
+ address = 0;
+ memset(write_buffer, 0, SIZE_WRITE_BUFFER);
+}
+
+void x76f041_device::nvram_default()
+{
+ // region always wins
+ if(m_region)
+ {
+ // Ensure the size is correct though
+ if(m_region->bytes() != SIZE_RESPONSE_TO_RESET+SIZE_WRITE_PASSWORD+
+ SIZE_READ_PASSWORD+SIZE_CONFIGURATION_PASSWORD+SIZE_CONFIGURATION_REGISTERS+SIZE_DATA)
+ logerror("X76F041: Wrong region length for initialization data, expected 0x%x, got 0x%x\n",
+ SIZE_RESPONSE_TO_RESET+SIZE_WRITE_PASSWORD+
+ SIZE_READ_PASSWORD+SIZE_CONFIGURATION_PASSWORD+SIZE_CONFIGURATION_REGISTERS+SIZE_DATA,
+ m_region->bytes());
+ else {
+ UINT8 *rb = m_region->base();
+ int offset = 0;
+ memcpy(response_to_reset, rb + offset, SIZE_RESPONSE_TO_RESET); offset += SIZE_RESPONSE_TO_RESET;
+ memcpy(write_password, rb + offset, SIZE_WRITE_PASSWORD); offset += SIZE_WRITE_PASSWORD;
+ memcpy(read_password, rb + offset, SIZE_READ_PASSWORD); offset += SIZE_READ_PASSWORD;
+ memcpy(configuration_password, rb + offset, SIZE_CONFIGURATION_PASSWORD); offset += SIZE_CONFIGURATION_PASSWORD;
+ memcpy(configuration_registers, rb + offset, SIZE_CONFIGURATION_REGISTERS); offset += SIZE_CONFIGURATION_REGISTERS;
+ memcpy(data, rb + offset, SIZE_DATA); offset += SIZE_DATA;
+ return;
+ }
+ }
+
+ // That chip isn't really usable without the passwords, so bitch
+ // if there's no region
+ logerror("X76F041: Warning, no default data provided, chip is unusable.\n");
+ memset(response_to_reset, 0, SIZE_RESPONSE_TO_RESET);
+ memset(write_password, 0, SIZE_WRITE_PASSWORD);
+ memset(read_password, 0, SIZE_READ_PASSWORD);
+ memset(configuration_password, 0, SIZE_CONFIGURATION_PASSWORD);
+ memset(configuration_registers, 0, SIZE_CONFIGURATION_REGISTERS);
+ memset(data, 0, SIZE_DATA);
+}
+
+void x76f041_device::cs_0()
+{
+ /* enable chip */
+ state = STATE_STOP;
+}
+
+void x76f041_device::cs_1()
+{
+ /* disable chip */
+ state = STATE_STOP;
+ /* high impendence? */
+ sdar = false;
+}
+
+void x76f041_device::rst_0()
+{
+}
+
+void x76f041_device::rst_1()
+{
+ if(!cs) {
+ verboselog(1, "goto response to reset\n");
+ state = STATE_RESPONSE_TO_RESET;
+ bit = 0;
+ byte = 0;
+ }
+}
+
+UINT8 *x76f041_device::password()
+{
+ switch(command & 0xe0) {
+ case COMMAND_WRITE:
+ return write_password;
+ case COMMAND_READ:
+ return read_password;
+ default:
+ return configuration_password;
+ }
+}
+
+void x76f041_device::password_ok()
+{
+ switch(command & 0xe0) {
+ case COMMAND_WRITE:
+ state = STATE_WRITE_DATA;
+ break;
+ case COMMAND_READ:
+ state = STATE_READ_DATA;
+ break;
+ case COMMAND_WRITE_USE_CONFIGURATION_PASSWORD:
+ state = STATE_WRITE_DATA;
+ break;
+ case COMMAND_READ_USE_CONFIGURATION_PASSWORD:
+ state = STATE_READ_DATA;
+ break;
+ case COMMAND_CONFIGURATION:
+ switch( address ) {
+ case CONFIGURATION_PROGRAM_WRITE_PASSWORD:
+ break;
+ case CONFIGURATION_PROGRAM_READ_PASSWORD:
+ break;
+ case CONFIGURATION_PROGRAM_CONFIGURATION_PASSWORD:
+ break;
+ case CONFIGURATION_RESET_WRITE_PASSWORD:
+ break;
+ case CONFIGURATION_RESET_READ_PASSWORD:
+ break;
+ case CONFIGURATION_PROGRAM_CONFIGURATION_REGISTERS:
+ state = STATE_WRITE_CONFIGURATION_REGISTERS;
+ byte = 0;
+ break;
+ case CONFIGURATION_READ_CONFIGURATION_REGISTERS:
+ state = STATE_READ_CONFIGURATION_REGISTERS;
+ byte = 0;
+ break;
+ case CONFIGURATION_MASS_PROGRAM:
+ break;
+ case CONFIGURATION_MASS_ERASE:
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void x76f041_device::load_address()
+{
+ /* todo: handle other bcr bits */
+ int bcr;
+
+ address = shift;
+
+ verboselog(1, "-> address: %02x\n", address);
+
+ if(!(command & 1 ))
+ bcr = configuration_registers[CONFIG_BCR1];
+ else
+ bcr = configuration_registers[CONFIG_BCR2];
+
+ if(address & 0x80)
+ bcr >>= 4;
+
+ if(((command & 0xe0) == COMMAND_READ && (bcr & BCR_Z) && (bcr & BCR_T)) ||
+ ((command & 0xe0) == COMMAND_WRITE && (bcr & BCR_Z))) {
+ /* todo: find out when this is really checked. */
+ verboselog(1, "command not allowed\n");
+ state = STATE_STOP;
+ sdar = false;
+
+ } else if(((command & 0xe0) == COMMAND_WRITE && !(bcr & BCR_X)) ||
+ ((command & 0xe0) == COMMAND_READ && !(bcr & BCR_Y))) {
+ verboselog(1, "password not required\n");
+ password_ok();
+
+ } else {
+ verboselog(1, "send password\n");
+ state = STATE_LOAD_PASSWORD;
+ byte = 0;
+ }
+}
+
+int x76f041_device::data_offset()
+{
+ int block_offset = ((command & 1) << 8) + address;
+
+ // TODO: confirm block_start doesn't wrap.
+
+ return (block_offset & 0x180) | ((block_offset + byte) & 0x7f);
+}
+
+void x76f041_device::scl_0()
+{
+ if(!cs) {
+ switch(state) {
+ case STATE_RESPONSE_TO_RESET:
+ sdar = (response_to_reset[byte] >> bit) & 1;
+ verboselog(2, "in response to reset %d (%d/%d)\n", sdar, byte, bit);
+ bit++;
+ if(bit == 8) {
+ bit = 0;
+ byte++;
+ if( byte == 4 )
+ byte = 0;
+ }
+ break;
+ }
+ }
+}
+
+void x76f041_device::scl_1()
+{
+ if(!cs) {
+ switch(state) {
+ case STATE_STOP:
+ break;
+ case STATE_RESPONSE_TO_RESET:
+ break;
+ case STATE_LOAD_COMMAND:
+ case STATE_LOAD_ADDRESS:
+ case STATE_LOAD_PASSWORD:
+ case STATE_VERIFY_PASSWORD:
+ case STATE_WRITE_DATA:
+ case STATE_WRITE_CONFIGURATION_REGISTERS:
+ if(bit < 8) {
+ verboselog(2, "clock\n");
+ shift <<= 1;
+ if(sdaw)
+ shift |= 1;
+ bit++;
+ } else {
+ sdar = false;
+
+ switch(state) {
+ case STATE_LOAD_COMMAND:
+ command = shift;
+ verboselog(1, "-> command: %02x\n", command);
+ /* todo: verify command is valid? */
+ state = STATE_LOAD_ADDRESS;
+ break;
+ case STATE_LOAD_ADDRESS:
+ load_address();
+ break;
+ case STATE_LOAD_PASSWORD:
+ verboselog(1, "-> password: %02x\n", shift );
+ write_buffer[byte++] = shift;
+ if(byte == SIZE_WRITE_BUFFER)
+ state = STATE_VERIFY_PASSWORD;
+ break;
+ case STATE_VERIFY_PASSWORD:
+ verboselog(1, "-> verify password: %02x\n", shift);
+ /* todo: this should probably be handled as a command */
+ if(shift == 0xc0) {
+ /* todo: this should take 10ms before it returns ok. */
+ if(!memcmp(password(), write_buffer, SIZE_WRITE_BUFFER))
+ password_ok();
+ else
+ sdar = true;
+ }
+ break;
+ case STATE_WRITE_DATA:
+ verboselog(1, "-> data: %02x\n", shift);
+ write_buffer[byte++] = shift;
+ if(byte == SIZE_WRITE_BUFFER) {
+ for(byte = 0; byte < SIZE_WRITE_BUFFER; byte++)
+ data[data_offset()] = write_buffer[byte];
+ byte = 0;
+ verboselog(1, "data flushed\n");
+ }
+ break;
+ case STATE_WRITE_CONFIGURATION_REGISTERS:
+ verboselog(1, "-> configuration register: %02x\n", shift);
+ /* todo: write after all bytes received? */
+ configuration_registers[byte++] = shift;
+ if(byte == SIZE_CONFIGURATION_REGISTERS)
+ byte = 0;
+ break;
+ }
+
+ bit = 0;
+ shift = 0;
+ }
+ break;
+ case STATE_READ_DATA:
+ case STATE_READ_CONFIGURATION_REGISTERS:
+ if(bit < 8) {
+ if(bit == 0) {
+ switch(state) {
+ case STATE_READ_DATA:
+ shift = data[data_offset()];
+ verboselog(1, "<- data: %02x\n", shift);
+ break;
+ case STATE_READ_CONFIGURATION_REGISTERS:
+ shift = configuration_registers[byte & 7];
+ verboselog(1, "<- configuration register: %02x\n", shift );
+ break;
+ }
+ }
+ sdar = ( shift >> 7 ) & 1;
+ shift <<= 1;
+ bit++;
+ } else {
+ bit = 0;
+ sdar = false;
+ if(!sdaw) {
+ verboselog(2, "ack <-\n");
+ byte++;
+ } else {
+ verboselog(2, "nak <-\n");
+ }
+ }
+ break;
+ }
+ }
+}
+
+void x76f041_device::sda_0()
+{
+ if(!cs && scl) {
+ switch(state) {
+ case STATE_STOP:
+ verboselog(1, "goto start (1)\n");
+ state = STATE_LOAD_COMMAND;
+ break;
+ case STATE_LOAD_PASSWORD:
+ /* todo: this will be the 0xc0 command, but it's not handled as a command yet. */
+ verboselog(1, "goto start (2)\n");
+ break;
+ case STATE_READ_DATA:
+ verboselog(1, "goto load address\n");
+ state = STATE_LOAD_ADDRESS;
+ break;
+ default:
+ verboselog(1, "skipped start (default)\n");
+ break;
+ }
+
+ bit = 0;
+ byte = 0;
+ shift = 0;
+ sdar = false;
+ }
+}
+
+void x76f041_device::sda_1()
+{
+ if(!cs && scl) {
+ verboselog(1, "goto stop\n");
+ state = STATE_STOP;
+ sdar = false;
+ }
+}
+
+void x76f041_device::nvram_read(emu_file &file)
+{
+ file.read(response_to_reset, SIZE_RESPONSE_TO_RESET);
+ file.read(write_password, SIZE_WRITE_PASSWORD);
+ file.read(read_password, SIZE_READ_PASSWORD);
+ file.read(configuration_password, SIZE_CONFIGURATION_PASSWORD);
+ file.read(configuration_registers, SIZE_CONFIGURATION_REGISTERS);
+ file.read(data, SIZE_DATA);
+}
+
+void x76f041_device::nvram_write(emu_file &file)
+{
+ file.write(response_to_reset, SIZE_RESPONSE_TO_RESET);
+ file.write(write_password, SIZE_WRITE_PASSWORD);
+ file.write(read_password, SIZE_READ_PASSWORD);
+ file.write(configuration_password, SIZE_CONFIGURATION_PASSWORD);
+ file.write(configuration_registers, SIZE_CONFIGURATION_REGISTERS);
+ file.write(data, SIZE_DATA);
+}
diff --git a/trunk/src/emu/machine/x76f041.h b/trunk/src/emu/machine/x76f041.h
new file mode 100644
index 00000000000..70df0bf8fe3
--- /dev/null
+++ b/trunk/src/emu/machine/x76f041.h
@@ -0,0 +1,116 @@
+/*
+ * x76f041.h
+ *
+ * Secure SerialFlash
+ *
+ */
+
+#ifndef __X76F041_H__
+#define __X76F041_H__
+
+#define MCFG_X76F041_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, X76F041, 0)
+
+#include "machine/secflash.h"
+
+class x76f041_device : public device_secure_serial_flash
+{
+public:
+ // construction/destruction
+ x76f041_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_nvram_interface overrides
+ virtual void nvram_default();
+ virtual void nvram_read(emu_file &file);
+ virtual void nvram_write(emu_file &file);
+
+ // device_secure_serial_flash implementations
+ virtual void cs_0();
+ virtual void cs_1();
+ virtual void rst_0();
+ virtual void rst_1();
+ virtual void scl_0();
+ virtual void scl_1();
+ virtual void sda_0();
+ virtual void sda_1();
+
+ // internal state
+ enum {
+ SIZE_WRITE_BUFFER = 8,
+ SIZE_RESPONSE_TO_RESET = 4,
+ SIZE_WRITE_PASSWORD = 8,
+ SIZE_READ_PASSWORD = 8,
+ SIZE_CONFIGURATION_PASSWORD = 8,
+ SIZE_CONFIGURATION_REGISTERS = 8,
+ SIZE_DATA = 512,
+
+ CONFIG_BCR1 = 0,
+ CONFIG_BCR2 = 1,
+ CONFIG_CR = 2,
+ CONFIG_RR = 3,
+ CONFIG_RC = 4,
+
+ BCR_X = 8,
+ BCR_Y = 4,
+ BCR_Z = 2,
+ BCR_T = 1,
+
+ COMMAND_WRITE = 0x00,
+ COMMAND_READ = 0x20,
+ COMMAND_WRITE_USE_CONFIGURATION_PASSWORD = 0x40,
+ COMMAND_READ_USE_CONFIGURATION_PASSWORD = 0x60,
+ COMMAND_CONFIGURATION = 0x80,
+
+ CONFIGURATION_PROGRAM_WRITE_PASSWORD = 0x00,
+ CONFIGURATION_PROGRAM_READ_PASSWORD = 0x10,
+ CONFIGURATION_PROGRAM_CONFIGURATION_PASSWORD = 0x20,
+ CONFIGURATION_RESET_WRITE_PASSWORD = 0x30,
+ CONFIGURATION_RESET_READ_PASSWORD = 0x40,
+ CONFIGURATION_PROGRAM_CONFIGURATION_REGISTERS = 0x50,
+ CONFIGURATION_READ_CONFIGURATION_REGISTERS = 0x60,
+ CONFIGURATION_MASS_PROGRAM = 0x70,
+ CONFIGURATION_MASS_ERASE = 0x80
+ };
+
+ enum {
+ STATE_STOP,
+ STATE_RESPONSE_TO_RESET,
+ STATE_LOAD_COMMAND,
+ STATE_LOAD_ADDRESS,
+ STATE_LOAD_PASSWORD,
+ STATE_VERIFY_PASSWORD,
+ STATE_READ_DATA,
+ STATE_WRITE_DATA,
+ STATE_READ_CONFIGURATION_REGISTERS,
+ STATE_WRITE_CONFIGURATION_REGISTERS
+ };
+
+ int state, bit, byte, address;
+ UINT8 command, shift;
+ UINT8 write_buffer[SIZE_WRITE_BUFFER];
+ UINT8 response_to_reset[SIZE_RESPONSE_TO_RESET];
+ UINT8 write_password[SIZE_WRITE_PASSWORD];
+ UINT8 read_password[SIZE_READ_PASSWORD];
+ UINT8 configuration_password[SIZE_CONFIGURATION_PASSWORD];
+ UINT8 configuration_registers[SIZE_CONFIGURATION_REGISTERS];
+ UINT8 data[SIZE_DATA];
+
+ UINT8 *password();
+ void password_ok();
+ void load_address();
+ int data_offset();
+
+private:
+ inline void ATTR_PRINTF(3,4) verboselog(int n_level, const char *s_fmt, ...);
+};
+
+
+// device type definition
+extern const device_type X76F041;
+
+#endif
diff --git a/trunk/src/emu/machine/x76f100.c b/trunk/src/emu/machine/x76f100.c
new file mode 100644
index 00000000000..c6f4d3a01a5
--- /dev/null
+++ b/trunk/src/emu/machine/x76f100.c
@@ -0,0 +1,328 @@
+/*
+ * x76f100.c
+ *
+ * Secure SerialFlash
+ *
+ * The X76F100 is a Password Access Security Supervisor, containing one 896-bit Secure SerialFlash array.
+ * Access to the memory array can be controlled by two 64-bit passwords. These passwords protect read and
+ * write operations of the memory array.
+ *
+ */
+
+#include "emu.h"
+#include "machine/x76f100.h"
+
+#define VERBOSE_LEVEL 0
+
+inline void ATTR_PRINTF(3,4) x76f100_device::verboselog(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("x76f100 %s %s: %s", tag(), machine().describe_context(), buf);
+ }
+}
+
+// device type definition
+const device_type X76F100 = &device_creator<x76f100_device>;
+
+x76f100_device::x76f100_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_secure_serial_flash(mconfig, X76F100, "X76F100", tag, owner, clock)
+{
+}
+
+void x76f100_device::device_start()
+{
+ device_secure_serial_flash::device_start();
+ save_item(NAME(state));
+ save_item(NAME(shift));
+ save_item(NAME(bit));
+ save_item(NAME(byte));
+ save_item(NAME(command));
+ save_item(NAME(write_buffer));
+ save_item(NAME(response_to_reset));
+ save_item(NAME(write_password));
+ save_item(NAME(read_password));
+ save_item(NAME(data));
+}
+
+void x76f100_device::device_reset()
+{
+ device_secure_serial_flash::device_reset();
+ state = STATE_STOP;
+ shift = 0;
+ bit = 0;
+ byte = 0;
+ command = 0;
+ memset(write_buffer, 0, SIZE_WRITE_BUFFER);
+}
+
+void x76f100_device::nvram_default()
+{
+ // region always wins
+ if(m_region)
+ {
+ // Ensure the size is correct though
+ if(m_region->bytes() != SIZE_RESPONSE_TO_RESET+SIZE_WRITE_PASSWORD+SIZE_READ_PASSWORD+SIZE_DATA)
+ logerror("x76f100 %s: Wrong region length for initialization data, expected 0x%x, got 0x%x\n",
+ tag(),
+ SIZE_RESPONSE_TO_RESET+SIZE_WRITE_PASSWORD+SIZE_READ_PASSWORD+SIZE_DATA,
+ m_region->bytes());
+ else {
+ UINT8 *rb = m_region->base();
+ int offset = 0;
+ memcpy(response_to_reset, rb + offset, SIZE_RESPONSE_TO_RESET); offset += SIZE_RESPONSE_TO_RESET;
+ memcpy(write_password, rb + offset, SIZE_WRITE_PASSWORD); offset += SIZE_WRITE_PASSWORD;
+ memcpy(read_password, rb + offset, SIZE_READ_PASSWORD); offset += SIZE_READ_PASSWORD;
+ memcpy(data, rb + offset, SIZE_DATA); offset += SIZE_DATA;
+ return;
+ }
+ }
+
+ // That chip isn't really usable without the passwords, so bitch
+ // if there's no region
+ logerror("x76f100 %s: Warning, no default data provided, chip is unusable.\n", tag());
+ memset(response_to_reset, 0, SIZE_RESPONSE_TO_RESET);
+ memset(write_password, 0, SIZE_WRITE_PASSWORD);
+ memset(read_password, 0, SIZE_READ_PASSWORD);
+ memset(data, 0, SIZE_DATA);
+}
+
+void x76f100_device::cs_0()
+{
+ /* enable chip */
+ state = STATE_STOP;
+}
+
+void x76f100_device::cs_1()
+{
+ /* disable chip */
+ state = STATE_STOP;
+ /* high impendence? */
+ sdar = 0;
+}
+
+void x76f100_device::rst_0()
+{
+}
+
+void x76f100_device::rst_1()
+{
+ if(!cs) {
+ verboselog(1, "goto response to reset\n");
+ state = STATE_RESPONSE_TO_RESET;
+ bit = 0;
+ byte = 0;
+ }
+}
+
+UINT8 *x76f100_device::password()
+{
+ if((command & 0xe1) == COMMAND_READ)
+ {
+ return read_password;
+ }
+
+ return write_password;
+}
+
+void x76f100_device::password_ok()
+{
+ if((command & 0xe1) == COMMAND_READ)
+ {
+ state = STATE_READ_DATA;
+ }
+ else if((command & 0xe1) == COMMAND_WRITE)
+ {
+ state = STATE_WRITE_DATA;
+ }
+ else
+ {
+ /* TODO: */
+ }
+}
+
+int x76f100_device::data_offset()
+{
+ int block_offset = (command >> 1) & 0x0f;
+
+ return block_offset * SIZE_WRITE_BUFFER + byte;
+}
+
+void x76f100_device::scl_0()
+{
+ if(cs)
+ return;
+
+ switch(state) {
+ case STATE_RESPONSE_TO_RESET:
+ if(bit == 0) {
+ shift = response_to_reset[byte];
+ verboselog(1, "<- response_to_reset[%d]: %02x\n", byte, shift);
+ }
+
+ sdar = shift & 1;
+ shift >>= 1;
+ bit++;
+
+ if(bit == 8) {
+ bit = 0;
+ byte++;
+ if(byte == 4)
+ byte = 0;
+ }
+ break;
+ }
+}
+
+void x76f100_device::scl_1()
+{
+ if(cs)
+ return;
+
+ switch(state) {
+ case STATE_RESPONSE_TO_RESET:
+ break;
+
+ case STATE_LOAD_COMMAND:
+ case STATE_LOAD_PASSWORD:
+ case STATE_VERIFY_PASSWORD:
+ case STATE_WRITE_DATA:
+ if(bit < 8) {
+ verboselog(2, "clock\n");
+ shift <<= 1;
+ if(sdaw)
+ shift |= 1;
+ bit++;
+ } else {
+ switch(state) {
+ case STATE_LOAD_COMMAND:
+ verboselog(1, "-> command: %02x\n", command);
+ sdar = false;
+ command = shift;
+ /* todo: verify command is valid? */
+ state = STATE_LOAD_PASSWORD;
+ bit = 0;
+ shift = 0;
+ break;
+
+ case STATE_LOAD_PASSWORD:
+ verboselog(1, "-> password: %02x\n", shift);
+ sdar = false;
+ write_buffer[byte++] = shift;
+ if(byte == SIZE_WRITE_BUFFER)
+ state = STATE_VERIFY_PASSWORD;
+ bit = 0;
+ shift = 0;
+ break;
+
+ case STATE_VERIFY_PASSWORD:
+ verboselog(1, "-> verify password: %02x\n", shift);
+ sdar = false;
+ /* todo: this should probably be handled as a command */
+ if(shift == COMMAND_ACK_PASSWORD) {
+ /* todo: this should take 10ms before it returns ok. */
+ if(!memcmp(password(), write_buffer, SIZE_WRITE_BUFFER))
+ password_ok();
+ else
+ sdar = true;
+ }
+ bit = 0;
+ shift = 0;
+ break;
+
+ case STATE_WRITE_DATA:
+ verboselog(1, "-> data: %02x\n", shift );
+ sdar = false;
+ write_buffer[byte++] = shift;
+ if(byte == SIZE_WRITE_BUFFER) {
+ for(byte = 0; byte < SIZE_WRITE_BUFFER; byte++)
+ data[data_offset()] = write_buffer[byte];
+ byte = 0;
+ }
+ bit = 0;
+ shift = 0;
+ break;
+ }
+ }
+ break;
+
+ case STATE_READ_DATA:
+ if(bit < 8) {
+ if(bit == 0) {
+ shift = data[data_offset()];
+ verboselog(1, "<- data: %02x\n", shift );
+ }
+ sdar = (shift >> 7) & 1;
+ shift <<= 1;
+ bit++;
+ } else {
+ bit = 0;
+ sdar = false;
+ if(!sdaw) {
+ verboselog(2, "ack <-\n");
+ byte++;
+ } else {
+ verboselog(2, "nak <-\n");
+ }
+ }
+ break;
+ }
+}
+
+void x76f100_device::sda_0()
+{
+ if(cs || !scl)
+ return;
+
+ switch(state) {
+ case STATE_STOP:
+ state = STATE_LOAD_COMMAND;
+ break;
+
+ case STATE_LOAD_PASSWORD:
+ /* todo: this will be the 0xc0 command, but it's not handled as a command yet. */
+ break;
+
+ case STATE_READ_DATA:
+ // c->state = STATE_LOAD_ADDRESS;
+ break;
+
+ default:
+ break;
+ }
+
+ bit = 0;
+ byte = 0;
+ shift = 0;
+ sdar = false;
+}
+
+void x76f100_device::sda_1()
+{
+ if(cs || !scl)
+ return;
+
+ state = STATE_STOP;
+ sdar = false;
+}
+
+void x76f100_device::nvram_read(emu_file &file)
+{
+ file.read(response_to_reset, SIZE_RESPONSE_TO_RESET);
+ file.read(write_password, SIZE_WRITE_PASSWORD);
+ file.read(read_password, SIZE_READ_PASSWORD);
+ file.read(data, SIZE_DATA);
+}
+
+void x76f100_device::nvram_write(emu_file &file)
+{
+ file.write(response_to_reset, SIZE_RESPONSE_TO_RESET);
+ file.write(write_password, SIZE_WRITE_PASSWORD);
+ file.write(read_password, SIZE_READ_PASSWORD);
+ file.write(data, SIZE_DATA);
+}
diff --git a/trunk/src/emu/machine/x76f100.h b/trunk/src/emu/machine/x76f100.h
new file mode 100644
index 00000000000..0eab9d26347
--- /dev/null
+++ b/trunk/src/emu/machine/x76f100.h
@@ -0,0 +1,87 @@
+/*
+ * x76f100.h
+ *
+ * Secure SerialFlash
+ *
+ */
+
+#ifndef __X76F100_H__
+#define __X76F100_H__
+
+#define MCFG_X76F100_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, X76F100, 0)
+
+#include "machine/secflash.h"
+
+class x76f100_device : public device_secure_serial_flash
+{
+public:
+ // construction/destruction
+ x76f100_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_nvram_interface overrides
+ virtual void nvram_default();
+ virtual void nvram_read(emu_file &file);
+ virtual void nvram_write(emu_file &file);
+
+ // device_secure_serial_flash implementations
+ virtual void cs_0();
+ virtual void cs_1();
+ virtual void rst_0();
+ virtual void rst_1();
+ virtual void scl_0();
+ virtual void scl_1();
+ virtual void sda_0();
+ virtual void sda_1();
+
+ // internal state
+ enum {
+ SIZE_WRITE_BUFFER = 8,
+ SIZE_RESPONSE_TO_RESET = 4,
+ SIZE_WRITE_PASSWORD = 8,
+ SIZE_READ_PASSWORD = 8,
+ SIZE_DATA = 112,
+
+ COMMAND_WRITE = 0x80,
+ COMMAND_READ = 0x81,
+ COMMAND_CHANGE_WRITE_PASSWORD = 0xfc,
+ COMMAND_CHANGE_READ_PASSWORD = 0xfe,
+ COMMAND_ACK_PASSWORD = 0x55
+ };
+
+ enum {
+ STATE_STOP,
+ STATE_RESPONSE_TO_RESET,
+ STATE_LOAD_COMMAND,
+ STATE_LOAD_PASSWORD,
+ STATE_VERIFY_PASSWORD,
+ STATE_READ_DATA,
+ STATE_WRITE_DATA
+ };
+
+ int state, bit, byte;
+ UINT8 command, shift;
+ UINT8 write_buffer[SIZE_WRITE_BUFFER];
+ UINT8 response_to_reset[SIZE_RESPONSE_TO_RESET];
+ UINT8 write_password[SIZE_WRITE_PASSWORD];
+ UINT8 read_password[SIZE_READ_PASSWORD];
+ UINT8 data[SIZE_DATA];
+
+ UINT8 *password();
+ void password_ok();
+ int data_offset();
+
+private:
+ inline void ATTR_PRINTF(3,4) verboselog(int n_level, const char *s_fmt, ...);
+};
+
+
+// device type definition
+extern const device_type X76F100;
+
+#endif
diff --git a/trunk/src/emu/machine/z80ctc.c b/trunk/src/emu/machine/z80ctc.c
new file mode 100644
index 00000000000..3b66cfcaf41
--- /dev/null
+++ b/trunk/src/emu/machine/z80ctc.c
@@ -0,0 +1,526 @@
+/***************************************************************************
+
+ Z80 CTC (Z8430) implementation
+
+ based on original version (c) 1997, Tatsuyuki Satoh
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "z80ctc.h"
+#include "cpu/z80/z80.h"
+#include "cpu/z80/z80daisy.h"
+
+
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define VERBOSE 0
+
+#define VPRINTF(x) do { if (VERBOSE) logerror x; } while (0)
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// these are the bits of the incoming commands to the CTC
+const int INTERRUPT = 0x80;
+const int INTERRUPT_ON = 0x80;
+const int INTERRUPT_OFF = 0x00;
+
+const int MODE = 0x40;
+const int MODE_TIMER = 0x00;
+const int MODE_COUNTER = 0x40;
+
+const int PRESCALER = 0x20;
+const int PRESCALER_256 = 0x20;
+const int PRESCALER_16 = 0x00;
+
+const int EDGE = 0x10;
+const int EDGE_FALLING = 0x00;
+const int EDGE_RISING = 0x10;
+
+const int TRIGGER = 0x08;
+const int TRIGGER_AUTO = 0x00;
+const int TRIGGER_CLOCK = 0x08;
+
+const int CONSTANT = 0x04;
+const int CONSTANT_LOAD = 0x04;
+const int CONSTANT_NONE = 0x00;
+
+const int RESET = 0x02;
+const int RESET_CONTINUE = 0x00;
+const int RESET_ACTIVE = 0x02;
+
+const int CONTROL = 0x01;
+const int CONTROL_VECTOR = 0x00;
+const int CONTROL_WORD = 0x01;
+
+// these extra bits help us keep things accurate
+const int WAITING_FOR_TRIG = 0x100;
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type Z80CTC = &device_creator<z80ctc_device>;
+
+//-------------------------------------------------
+// z80ctc_device - constructor
+//-------------------------------------------------
+
+z80ctc_device::z80ctc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, Z80CTC, "Zilog Z80 CTC", tag, owner, clock),
+ device_z80daisy_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void z80ctc_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const z80ctc_interface *intf = reinterpret_cast<const z80ctc_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<z80ctc_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ m_notimer = 0;
+ memset(&m_intr_cb, 0, sizeof(m_intr_cb));
+ memset(&m_zc0_cb, 0, sizeof(m_zc0_cb));
+ memset(&m_zc1_cb, 0, sizeof(m_zc1_cb));
+ memset(&m_zc2_cb, 0, sizeof(m_zc2_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void z80ctc_device::device_start()
+{
+ m_period16 = attotime::from_hz(m_clock) * 16;
+ m_period256 = attotime::from_hz(m_clock) * 256;
+
+ // resolve callbacks
+ m_intr.resolve(m_intr_cb, *this);
+
+ // start each channel
+ devcb_write_line nullcb = DEVCB_NULL;
+ m_channel[0].start(this, 0, (m_notimer & NOTIMER_0) != 0, m_zc0_cb);
+ m_channel[1].start(this, 1, (m_notimer & NOTIMER_1) != 0, m_zc1_cb);
+ m_channel[2].start(this, 2, (m_notimer & NOTIMER_2) != 0, m_zc2_cb);
+ m_channel[3].start(this, 3, (m_notimer & NOTIMER_3) != 0, nullcb);
+
+ // register for save states
+ save_item(NAME(m_vector));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void z80ctc_device::device_reset()
+{
+ // reset each channel
+ m_channel[0].reset();
+ m_channel[1].reset();
+ m_channel[2].reset();
+ m_channel[3].reset();
+
+ // check for interrupts
+ interrupt_check();
+ VPRINTF(("CTC Reset\n"));
+}
+
+
+
+//**************************************************************************
+// DAISY CHAIN INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// z80daisy_irq_state - return the overall IRQ
+// state for this device
+//-------------------------------------------------
+
+int z80ctc_device::z80daisy_irq_state()
+{
+ VPRINTF(("CTC IRQ state = %d%d%d%d\n", m_channel[0].m_int_state, m_channel[1].m_int_state, m_channel[2].m_int_state, m_channel[3].m_int_state));
+
+ // loop over all channels
+ int state = 0;
+ for (int ch = 0; ch < 4; ch++)
+ {
+ ctc_channel &channel = m_channel[ch];
+
+ // if we're servicing a request, don't indicate more interrupts
+ if (channel.m_int_state & Z80_DAISY_IEO)
+ {
+ state |= Z80_DAISY_IEO;
+ break;
+ }
+ state |= channel.m_int_state;
+ }
+
+ return state;
+}
+
+
+//-------------------------------------------------
+// z80daisy_irq_ack - acknowledge an IRQ and
+// return the appropriate vector
+//-------------------------------------------------
+
+int z80ctc_device::z80daisy_irq_ack()
+{
+ // loop over all channels
+ for (int ch = 0; ch < 4; ch++)
+ {
+ ctc_channel &channel = m_channel[ch];
+
+ // find the first channel with an interrupt requested
+ if (channel.m_int_state & Z80_DAISY_INT)
+ {
+ VPRINTF(("CTC IRQAck ch%d\n", ch));
+
+ // clear interrupt, switch to the IEO state, and update the IRQs
+ channel.m_int_state = Z80_DAISY_IEO;
+ interrupt_check();
+ return m_vector + ch * 2;
+ }
+ }
+
+ logerror("z80ctc_irq_ack: failed to find an interrupt to ack!\n");
+ return m_vector;
+}
+
+
+//-------------------------------------------------
+// z80daisy_irq_reti - clear the interrupt
+// pending state to allow other interrupts through
+//-------------------------------------------------
+
+void z80ctc_device::z80daisy_irq_reti()
+{
+ // loop over all channels
+ for (int ch = 0; ch < 4; ch++)
+ {
+ ctc_channel &channel = m_channel[ch];
+
+ // find the first channel with an IEO pending
+ if (channel.m_int_state & Z80_DAISY_IEO)
+ {
+ VPRINTF(("CTC IRQReti ch%d\n", ch));
+
+ // clear the IEO state and update the IRQs
+ channel.m_int_state &= ~Z80_DAISY_IEO;
+ interrupt_check();
+ return;
+ }
+ }
+
+ logerror("z80ctc_irq_reti: failed to find an interrupt to clear IEO on!\n");
+}
+
+
+
+//**************************************************************************
+// INTERNAL STATE MANAGEMENT
+//**************************************************************************
+
+//-------------------------------------------------
+// interrupt_check - look for pending interrupts
+// and update the line
+//-------------------------------------------------
+
+void z80ctc_device::interrupt_check()
+{
+ int state = (z80daisy_irq_state() & Z80_DAISY_INT) ? ASSERT_LINE : CLEAR_LINE;
+ m_intr(state);
+}
+
+
+
+//*************************************************************************
+// CTC CHANNELS
+//**************************************************************************
+
+//-------------------------------------------------
+// ctc_channel - constructor
+//-------------------------------------------------
+
+z80ctc_device::ctc_channel::ctc_channel()
+ : m_notimer(false),
+ m_mode(0),
+ m_tconst(0),
+ m_down(0),
+ m_extclk(0),
+ m_timer(NULL),
+ m_int_state(0)
+{
+ memset(&m_zc, 0, sizeof(m_zc));
+}
+
+
+//-------------------------------------------------
+// start - set up at device start time
+//-------------------------------------------------
+
+void z80ctc_device::ctc_channel::start(z80ctc_device *device, int index, bool notimer, const devcb_write_line &write_line)
+{
+ // initialize state
+ m_device = device;
+ m_index = index;
+ m_zc.resolve(write_line, *m_device);
+ m_notimer = notimer;
+ m_timer = m_device->machine().scheduler().timer_alloc(FUNC(static_timer_callback), this);
+
+ // register for save states
+ m_device->save_item(NAME(m_mode), m_index);
+ m_device->save_item(NAME(m_tconst), m_index);
+ m_device->save_item(NAME(m_down), m_index);
+ m_device->save_item(NAME(m_extclk), m_index);
+ m_device->save_item(NAME(m_int_state), m_index);
+}
+
+
+//-------------------------------------------------
+// reset - reset the channel
+//-------------------------------------------------
+
+void z80ctc_device::ctc_channel::reset()
+{
+ m_mode = RESET_ACTIVE;
+ m_tconst = 0x100;
+ m_timer->adjust(attotime::never);
+ m_int_state = 0;
+}
+
+
+//-------------------------------------------------
+// period - return the current channel's period
+//-------------------------------------------------
+
+attotime z80ctc_device::ctc_channel::period() const
+{
+ // if reset active, no period
+ if ((m_mode & RESET) == RESET_ACTIVE)
+ return attotime::zero;
+
+ // if counter mode, no real period
+ if ((m_mode & MODE) == MODE_COUNTER)
+ {
+ logerror("CTC %d is CounterMode : Can't calculate period\n", m_index);
+ return attotime::zero;
+ }
+
+ // compute the period
+ attotime period = ((m_mode & PRESCALER) == PRESCALER_16) ? m_device->m_period16 : m_device->m_period256;
+ return period * m_tconst;
+}
+
+
+//-------------------------------------------------
+// read - read the channel's state
+//-------------------------------------------------
+
+UINT8 z80ctc_device::ctc_channel::read()
+{
+ // if we're in counter mode, just return the count
+ if ((m_mode & MODE) == MODE_COUNTER || (m_mode & WAITING_FOR_TRIG))
+ return m_down;
+
+ // else compute the down counter value
+ else
+ {
+ attotime period = ((m_mode & PRESCALER) == PRESCALER_16) ? m_device->m_period16 : m_device->m_period256;
+
+ VPRINTF(("CTC clock %f\n",ATTOSECONDS_TO_HZ(period.attoseconds)));
+
+ if (m_timer != NULL)
+ return ((int)(m_timer->remaining().as_double() / period.as_double()) + 1) & 0xff;
+ else
+ return 0;
+ }
+}
+
+
+//-------------------------------------------------
+// write - handle writes to a channel
+//-------------------------------------------------
+
+void z80ctc_device::ctc_channel::write(UINT8 data)
+{
+ // if we're waiting for a time constant, this is it
+ if ((m_mode & CONSTANT) == CONSTANT_LOAD)
+ {
+ VPRINTF(("CTC ch.%d constant = %02x\n", m_index, data));
+
+ // set the time constant (0 -> 0x100)
+ m_tconst = data ? data : 0x100;
+
+ // clear the internal mode -- we're no longer waiting
+ m_mode &= ~CONSTANT;
+
+ // also clear the reset, since the constant gets it going again
+ m_mode &= ~RESET;
+
+ // if we're in timer mode....
+ if ((m_mode & MODE) == MODE_TIMER)
+ {
+ // if we're triggering on the time constant, reset the down counter now
+ if ((m_mode & TRIGGER) == TRIGGER_AUTO)
+ {
+ if (!m_notimer)
+ {
+ attotime curperiod = period();
+ m_timer->adjust(curperiod, m_index, curperiod);
+ }
+ else
+ m_timer->adjust(attotime::never);
+ }
+
+ // else set the bit indicating that we're waiting for the appropriate trigger
+ else
+ m_mode |= WAITING_FOR_TRIG;
+ }
+
+ // also set the down counter in case we're clocking externally
+ m_down = m_tconst;
+ }
+
+ // if we're writing the interrupt vector, handle it specially
+#if 0 /* Tatsuyuki Satoh changes */
+ // The 'Z80family handbook' wrote,
+ // interrupt vector is able to set for even channel (0 or 2)
+ else if ((data & CONTROL) == CONTROL_VECTOR && (m_index & 1) == 0)
+#else
+ else if ((data & CONTROL) == CONTROL_VECTOR && m_index == 0)
+#endif
+ {
+ m_device->m_vector = data & 0xf8;
+ logerror("CTC Vector = %02x\n", m_device->m_vector);
+ }
+
+ // this must be a control word
+ else if ((data & CONTROL) == CONTROL_WORD)
+ {
+ // set the new mode
+ m_mode = data;
+ VPRINTF(("CTC ch.%d mode = %02x\n", m_index, data));
+
+ // if we're being reset, clear out any pending timers for this channel
+ if ((data & RESET) == RESET_ACTIVE)
+ {
+ m_timer->adjust(attotime::never);
+ // note that we don't clear the interrupt state here!
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// trigger - clock this channel and handle any
+// side-effects
+//-------------------------------------------------
+
+void z80ctc_device::ctc_channel::trigger(UINT8 data)
+{
+ // normalize data
+ data = data ? 1 : 0;
+
+ // see if the trigger value has changed
+ if (data != m_extclk)
+ {
+ m_extclk = data;
+
+ // see if this is the active edge of the trigger
+ if (((m_mode & EDGE) == EDGE_RISING && data) || ((m_mode & EDGE) == EDGE_FALLING && !data))
+ {
+ // if we're waiting for a trigger, start the timer
+ if ((m_mode & WAITING_FOR_TRIG) && (m_mode & MODE) == MODE_TIMER)
+ {
+ if (!m_notimer)
+ {
+ attotime curperiod = period();
+ VPRINTF(("CTC period %s\n", curperiod.as_string()));
+ m_timer->adjust(curperiod, m_index, curperiod);
+ }
+ else
+ {
+ VPRINTF(("CTC disabled\n"));
+ m_timer->adjust(attotime::never);
+ }
+ }
+
+ // we're no longer waiting
+ m_mode &= ~WAITING_FOR_TRIG;
+
+ // if we're clocking externally, decrement the count
+ if ((m_mode & MODE) == MODE_COUNTER)
+ {
+ // if we hit zero, do the same thing as for a timer interrupt
+ if (--m_down == 0)
+ timer_callback();
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// trigger - clock this channel and handle any
+// side-effects
+//-------------------------------------------------
+
+void z80ctc_device::ctc_channel::timer_callback()
+{
+ // down counter has reached zero - see if we should interrupt
+ if ((m_mode & INTERRUPT) == INTERRUPT_ON)
+ {
+ m_int_state |= Z80_DAISY_INT;
+ VPRINTF(("CTC timer ch%d\n", m_index));
+ m_device->interrupt_check();
+ }
+
+ // generate the clock pulse
+ m_zc(1);
+ m_zc(0);
+
+ // reset the down counter
+ m_down = m_tconst;
+}
+
+
+
+//**************************************************************************
+// GLOBAL STUBS
+//**************************************************************************
+
+WRITE8_DEVICE_HANDLER( z80ctc_w ) { downcast<z80ctc_device *>(device)->write(offset & 3, data); }
+READ8_DEVICE_HANDLER( z80ctc_r ) { return downcast<z80ctc_device *>(device)->read(offset & 3); }
+
+WRITE_LINE_DEVICE_HANDLER( z80ctc_trg0_w ) { downcast<z80ctc_device *>(device)->trigger(0, state); }
+WRITE_LINE_DEVICE_HANDLER( z80ctc_trg1_w ) { downcast<z80ctc_device *>(device)->trigger(1, state); }
+WRITE_LINE_DEVICE_HANDLER( z80ctc_trg2_w ) { downcast<z80ctc_device *>(device)->trigger(2, state); }
+WRITE_LINE_DEVICE_HANDLER( z80ctc_trg3_w ) { downcast<z80ctc_device *>(device)->trigger(3, state); }
diff --git a/trunk/src/emu/machine/z80ctc.h b/trunk/src/emu/machine/z80ctc.h
new file mode 100644
index 00000000000..4ffd3395ff4
--- /dev/null
+++ b/trunk/src/emu/machine/z80ctc.h
@@ -0,0 +1,168 @@
+/***************************************************************************
+
+ Z80 CTC (Z8430) implementation
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+****************************************************************************
+ _____ _____
+ D4 1 |* \_/ | 28 D3
+ D5 2 | | 27 D2
+ D6 3 | | 26 D1
+ D7 4 | | 25 D0
+ GND 5 | | 24 +5V
+ _RD 6 | | 23 CLK/TRG0
+ ZC/TOO 7 | Z80-CTC | 22 CLK/TRG1
+ ZC/TO1 8 | | 21 CLK/TRG2
+ ZC/TO2 9 | | 20 CLK/TRG3
+ _IORQ 10 | | 19 CS1
+ IEO 11 | | 18 CS0
+ _INT 12 | | 17 _RESET
+ IEI 13 | | 16 _CE
+ _M1 14 |_____________| 15 CLK
+
+***************************************************************************/
+
+#ifndef __Z80CTC_H__
+#define __Z80CTC_H__
+
+#include "cpu/z80/z80daisy.h"
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+const int NOTIMER_0 = (1<<0);
+const int NOTIMER_1 = (1<<1);
+const int NOTIMER_2 = (1<<2);
+const int NOTIMER_3 = (1<<3);
+
+
+
+//**************************************************************************
+// DEVICE CONFIGURATION MACROS
+//**************************************************************************
+
+#define Z80CTC_INTERFACE(name) \
+ const z80ctc_interface (name)=
+
+
+#define MCFG_Z80CTC_ADD(_tag, _clock, _intrf) \
+ MCFG_DEVICE_ADD(_tag, Z80CTC, _clock) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> z80ctc_interface
+
+struct z80ctc_interface
+{
+ UINT8 m_notimer; // timer disabler mask
+ devcb_write_line m_intr_cb; // callback when change interrupt status
+ devcb_write_line m_zc0_cb; // ZC/TO0 callback
+ devcb_write_line m_zc1_cb; // ZC/TO1 callback
+ devcb_write_line m_zc2_cb; // ZC/TO2 callback
+};
+
+
+
+// ======================> z80ctc_device
+
+class z80ctc_device : public device_t,
+ public device_z80daisy_interface,
+ public z80ctc_interface
+{
+public:
+ // construction/destruction
+ z80ctc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // state getters
+ attotime period(int ch) const { return m_channel[ch].period(); }
+
+ // I/O operations
+ UINT8 read(int ch) { return m_channel[ch].read(); }
+ void write(int ch, UINT8 data) { m_channel[ch].write(data); }
+ void trigger(int ch, UINT8 data) { m_channel[ch].trigger(data); }
+
+private:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+
+ // z80daisy_interface overrides
+ virtual int z80daisy_irq_state();
+ virtual int z80daisy_irq_ack();
+ virtual void z80daisy_irq_reti();
+
+ // internal helpers
+ void interrupt_check();
+ void timercallback(int chanindex);
+
+ // a single channel within the CTC
+ class ctc_channel
+ {
+ public:
+ ctc_channel();
+
+ void start(z80ctc_device *device, int index, bool notimer, const devcb_write_line &write_line);
+ void reset();
+
+ UINT8 read();
+ void write(UINT8 data);
+
+ attotime period() const;
+ void trigger(UINT8 data);
+ void timer_callback();
+
+ z80ctc_device * m_device; // pointer back to our device
+ int m_index; // our channel index
+ devcb_resolved_write_line m_zc; // zero crossing callbacks
+ bool m_notimer; // timer disabled?
+ UINT16 m_mode; // current mode
+ UINT16 m_tconst; // time constant
+ UINT16 m_down; // down counter (clock mode only)
+ UINT8 m_extclk; // current signal from the external clock
+ emu_timer * m_timer; // array of active timers
+ UINT8 m_int_state; // interrupt status (for daisy chain)
+
+ private:
+ static TIMER_CALLBACK( static_timer_callback ) { reinterpret_cast<z80ctc_device::ctc_channel *>(ptr)->timer_callback(); }
+ };
+
+ // internal state
+ devcb_resolved_write_line m_intr; // interrupt callback
+
+ UINT8 m_vector; // interrupt vector
+ attotime m_period16; // 16/system clock
+ attotime m_period256; // 256/system clock
+ ctc_channel m_channel[4]; // data for each channel
+};
+
+
+// device type definition
+extern const device_type Z80CTC;
+
+
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+WRITE8_DEVICE_HANDLER( z80ctc_w );
+READ8_DEVICE_HANDLER( z80ctc_r );
+
+WRITE_LINE_DEVICE_HANDLER( z80ctc_trg0_w );
+WRITE_LINE_DEVICE_HANDLER( z80ctc_trg1_w );
+WRITE_LINE_DEVICE_HANDLER( z80ctc_trg2_w );
+WRITE_LINE_DEVICE_HANDLER( z80ctc_trg3_w );
+
+
+#endif
diff --git a/trunk/src/emu/machine/z80dart.c b/trunk/src/emu/machine/z80dart.c
new file mode 100644
index 00000000000..e964cb4b5a2
--- /dev/null
+++ b/trunk/src/emu/machine/z80dart.c
@@ -0,0 +1,1471 @@
+/***************************************************************************
+
+ Z80 DART Dual Asynchronous Receiver/Transmitter emulation
+
+ Copyright (c) 2008, The MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+ The z80dart/z80sio itself is based on an older intel serial chip, the i8274 MPSC
+ (see http://doc.chipfind.ru/pdf/intel/8274.pdf), which also has almost identical
+ behavior, except lacks the interrupt daisy chaining and has its own interrupt/dma
+ scheme which uses write register 2 on channel A, that register which is unused on
+ the z80dart and z80sio.
+
+***************************************************************************/
+
+/*
+
+ TODO:
+
+ - break detection
+ - wr0 reset tx interrupt pending
+ - wait/ready
+ - 1.5 stop bits
+ - synchronous mode (Z80-SIO/1,2)
+ - SDLC mode (Z80-SIO/1,2)
+
+*/
+
+#include "emu.h"
+#include "z80dart.h"
+#include "cpu/z80/z80.h"
+#include "cpu/z80/z80daisy.h"
+
+
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+enum
+{
+ CHANNEL_A = 0,
+ CHANNEL_B
+};
+
+enum
+{
+ STATE_START = 0,
+ STATE_DATA,
+ STATE_PARITY,
+ STATE_STOP,
+ STATE_STOP2
+};
+
+enum
+{
+ INT_TRANSMIT = 0,
+ INT_EXTERNAL,
+ INT_RECEIVE,
+ INT_SPECIAL
+};
+
+const int RR0_RX_CHAR_AVAILABLE = 0x01;
+const int RR0_INTERRUPT_PENDING = 0x02;
+const int RR0_TX_BUFFER_EMPTY = 0x04;
+const int RR0_DCD = 0x08;
+const int RR0_RI = 0x10;
+const int RR0_SYNC_HUNT = 0x10; // not supported
+const int RR0_CTS = 0x20;
+const int RR0_TX_UNDERRUN = 0x40; // not supported
+const int RR0_BREAK_ABORT = 0x80; // not supported
+
+const int RR1_ALL_SENT = 0x01;
+const int RR1_RESIDUE_CODE_MASK = 0x0e; // not supported
+const int RR1_PARITY_ERROR = 0x10;
+const int RR1_RX_OVERRUN_ERROR = 0x20;
+const int RR1_CRC_FRAMING_ERROR = 0x40;
+const int RR1_END_OF_FRAME = 0x80; // not supported
+
+const int WR0_REGISTER_MASK = 0x07;
+const int WR0_COMMAND_MASK = 0x38;
+const int WR0_NULL = 0x00;
+const int WR0_SEND_ABORT = 0x08; // not supported
+const int WR0_RESET_EXT_STATUS = 0x10;
+const int WR0_CHANNEL_RESET = 0x18;
+const int WR0_ENABLE_INT_NEXT_RX = 0x20;
+const int WR0_RESET_TX_INT = 0x28; // not supported
+const int WR0_ERROR_RESET = 0x30;
+const int WR0_RETURN_FROM_INT = 0x38; // not supported
+const int WR0_CRC_RESET_CODE_MASK = 0xc0; // not supported
+const int WR0_CRC_RESET_NULL = 0x00; // not supported
+const int WR0_CRC_RESET_RX = 0x40; // not supported
+const int WR0_CRC_RESET_TX = 0x80; // not supported
+const int WR0_CRC_RESET_TX_UNDERRUN = 0xc0; // not supported
+
+const int WR1_EXT_INT_ENABLE = 0x01;
+const int WR1_TX_INT_ENABLE = 0x02;
+const int WR1_STATUS_VECTOR = 0x04;
+const int WR1_RX_INT_MODE_MASK = 0x18;
+const int WR1_RX_INT_DISABLE = 0x00;
+const int WR1_RX_INT_FIRST = 0x08;
+const int WR1_RX_INT_ALL_PARITY = 0x10; // not supported
+const int WR1_RX_INT_ALL = 0x18;
+const int WR1_WRDY_ON_RX_TX = 0x20; // not supported
+const int WR1_WRDY_FUNCTION = 0x40; // not supported
+const int WR1_WRDY_ENABLE = 0x80; // not supported
+
+const int WR3_RX_ENABLE = 0x01;
+const int WR3_SYNC_CHAR_LOAD_INHIBIT= 0x02; // not supported
+const int WR3_ADDRESS_SEARCH_MODE = 0x04; // not supported
+const int WR3_RX_CRC_ENABLE = 0x08; // not supported
+const int WR3_ENTER_HUNT_PHASE = 0x10; // not supported
+const int WR3_AUTO_ENABLES = 0x20;
+const int WR3_RX_WORD_LENGTH_MASK = 0xc0;
+const int WR3_RX_WORD_LENGTH_5 = 0x00;
+const int WR3_RX_WORD_LENGTH_7 = 0x40;
+const int WR3_RX_WORD_LENGTH_6 = 0x80;
+const int WR3_RX_WORD_LENGTH_8 = 0xc0;
+
+const int WR4_PARITY_ENABLE = 0x01; // not supported
+const int WR4_PARITY_EVEN = 0x02; // not supported
+const int WR4_STOP_BITS_MASK = 0x0c;
+const int WR4_STOP_BITS_1 = 0x04;
+const int WR4_STOP_BITS_1_5 = 0x08; // not supported
+const int WR4_STOP_BITS_2 = 0x0c;
+const int WR4_SYNC_MODE_MASK = 0x30; // not supported
+const int WR4_SYNC_MODE_8_BIT = 0x00; // not supported
+const int WR4_SYNC_MODE_16_BIT = 0x10; // not supported
+const int WR4_SYNC_MODE_SDLC = 0x20; // not supported
+const int WR4_SYNC_MODE_EXT = 0x30; // not supported
+const int WR4_CLOCK_RATE_MASK = 0xc0;
+const int WR4_CLOCK_RATE_X1 = 0x00;
+const int WR4_CLOCK_RATE_X16 = 0x40;
+const int WR4_CLOCK_RATE_X32 = 0x80;
+const int WR4_CLOCK_RATE_X64 = 0xc0;
+
+const int WR5_TX_CRC_ENABLE = 0x01; // not supported
+const int WR5_RTS = 0x02;
+const int WR5_CRC16 = 0x04; // not supported
+const int WR5_TX_ENABLE = 0x08;
+const int WR5_SEND_BREAK = 0x10;
+const int WR5_TX_WORD_LENGTH_MASK = 0x60;
+const int WR5_TX_WORD_LENGTH_5 = 0x00;
+const int WR5_TX_WORD_LENGTH_6 = 0x40;
+const int WR5_TX_WORD_LENGTH_7 = 0x20;
+const int WR5_TX_WORD_LENGTH_8 = 0x60;
+const int WR5_DTR = 0x80;
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+#define RXD \
+ m_in_rxd_func()
+
+#define TXD(_state) \
+ m_out_txd_func(_state)
+
+#define RTS(_state) \
+ m_out_rts_func(_state)
+
+#define DTR(_state) \
+ m_out_dtr_func(_state)
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type Z80DART = &device_creator<z80dart_device>;
+const device_type Z80SIO0 = &device_creator<z80dart_device>;
+const device_type Z80SIO1 = &device_creator<z80dart_device>;
+const device_type Z80SIO2 = &device_creator<z80dart_device>;
+const device_type Z80SIO3 = &device_creator<z80dart_device>;
+const device_type Z80SIO4 = &device_creator<z80dart_device>;
+
+//-------------------------------------------------
+// z80dart_device - constructor
+//-------------------------------------------------
+
+z80dart_device::z80dart_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, Z80DART, "Zilog Z80 DART", tag, owner, clock),
+ device_z80daisy_interface(mconfig, *this)
+{
+ for (int i = 0; i < 8; i++)
+ m_int_state[i] = 0;
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void z80dart_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const z80dart_interface *intf = reinterpret_cast<const z80dart_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<z80dart_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ m_rx_clock_a = m_tx_clock_a = m_rx_clock_b = m_tx_clock_b = 0;
+ memset(&m_in_rxda_cb, 0, sizeof(m_in_rxda_cb));
+ memset(&m_out_txda_cb, 0, sizeof(m_out_txda_cb));
+ memset(&m_out_dtra_cb, 0, sizeof(m_out_dtra_cb));
+ memset(&m_out_rtsa_cb, 0, sizeof(m_out_rtsa_cb));
+ memset(&m_out_wrdya_cb, 0, sizeof(m_out_wrdya_cb));
+ memset(&m_out_synca_cb, 0, sizeof(m_out_synca_cb));
+ memset(&m_in_rxdb_cb, 0, sizeof(m_in_rxdb_cb));
+ memset(&m_out_txdb_cb, 0, sizeof(m_out_txdb_cb));
+ memset(&m_out_dtrb_cb, 0, sizeof(m_out_dtrb_cb));
+ memset(&m_out_rtsb_cb, 0, sizeof(m_out_rtsb_cb));
+ memset(&m_out_wrdyb_cb, 0, sizeof(m_out_wrdyb_cb));
+ memset(&m_out_syncb_cb, 0, sizeof(m_out_syncb_cb));
+ memset(&m_out_int_cb, 0, sizeof(m_out_int_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void z80dart_device::device_start()
+{
+ // resolve callbacks
+ m_out_int_func.resolve(m_out_int_cb, *this);
+
+ m_channel[CHANNEL_A].start(this, CHANNEL_A, m_in_rxda_cb, m_out_txda_cb, m_out_dtra_cb, m_out_rtsa_cb, m_out_wrdya_cb, m_out_synca_cb);
+ m_channel[CHANNEL_B].start(this, CHANNEL_B, m_in_rxdb_cb, m_out_txdb_cb, m_out_dtrb_cb, m_out_rtsb_cb, m_out_wrdyb_cb, m_out_syncb_cb);
+
+ if (m_rx_clock_a != 0)
+ {
+ // allocate channel A receive timer
+ m_rxca_timer = machine().scheduler().timer_alloc(FUNC(dart_channel::static_rxc_tick), (void *)&m_channel[CHANNEL_A]);
+ m_rxca_timer->adjust(attotime::zero, 0, attotime::from_hz(m_rx_clock_a));
+ }
+
+ if (m_tx_clock_a != 0)
+ {
+ // allocate channel A transmit timer
+ m_txca_timer = machine().scheduler().timer_alloc(FUNC(dart_channel::static_txc_tick), (void *)&m_channel[CHANNEL_A]);
+ m_txca_timer->adjust(attotime::zero, 0, attotime::from_hz(m_tx_clock_a));
+ }
+
+ if (m_rx_clock_b != 0)
+ {
+ // allocate channel B receive timer
+ m_rxcb_timer = machine().scheduler().timer_alloc(FUNC(dart_channel::static_rxc_tick), (void *)&m_channel[CHANNEL_B]);
+ m_rxcb_timer->adjust(attotime::zero, 0, attotime::from_hz(m_rx_clock_b));
+ }
+
+ if (m_tx_clock_b != 0)
+ {
+ // allocate channel B transmit timer
+ m_txcb_timer = machine().scheduler().timer_alloc(FUNC(dart_channel::static_txc_tick), (void *)&m_channel[CHANNEL_B]);
+ m_txcb_timer->adjust(attotime::zero, 0, attotime::from_hz(m_tx_clock_b));
+ }
+
+ save_item(NAME(m_int_state));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void z80dart_device::device_reset()
+{
+ LOG(("Z80DART \"%s\" Reset\n", tag()));
+
+ for (int channel = CHANNEL_A; channel <= CHANNEL_B; channel++)
+ {
+ m_channel[channel].reset();
+ }
+
+ check_interrupts();
+}
+
+
+
+//**************************************************************************
+// DAISY CHAIN INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// z80daisy_irq_state - get interrupt status
+//-------------------------------------------------
+
+int z80dart_device::z80daisy_irq_state()
+{
+ int state = 0;
+ int i;
+
+ LOG(("Z80DART \"%s\" : Interrupt State A:%d%d%d%d B:%d%d%d%d\n", tag(),
+ m_int_state[0], m_int_state[1], m_int_state[2], m_int_state[3],
+ m_int_state[4], m_int_state[5], m_int_state[6], m_int_state[7]));
+
+ // loop over all interrupt sources
+ for (i = 0; i < 8; i++)
+ {
+ // if we're servicing a request, don't indicate more interrupts
+ if (m_int_state[i] & Z80_DAISY_IEO)
+ {
+ state |= Z80_DAISY_IEO;
+ break;
+ }
+ state |= m_int_state[i];
+ }
+
+ LOG(("Z80DART \"%s\" : Interrupt State %u\n", tag(), state));
+
+ return state;
+}
+
+
+//-------------------------------------------------
+// z80daisy_irq_ack - interrupt acknowledge
+//-------------------------------------------------
+
+int z80dart_device::z80daisy_irq_ack()
+{
+ int i;
+
+ LOG(("Z80DART \"%s\" Interrupt Acknowledge\n", tag()));
+
+ // loop over all interrupt sources
+ for (i = 0; i < 8; i++)
+ {
+ // find the first channel with an interrupt requested
+ if (m_int_state[i] & Z80_DAISY_INT)
+ {
+ // clear interrupt, switch to the IEO state, and update the IRQs
+ m_int_state[i] = Z80_DAISY_IEO;
+ m_channel[CHANNEL_A].m_rr[0] &= ~RR0_INTERRUPT_PENDING;
+ check_interrupts();
+
+ LOG(("Z80DART \"%s\" : Interrupt Acknowledge Vector %02x\n", tag(), m_channel[CHANNEL_B].m_rr[2]));
+
+ return m_channel[CHANNEL_B].m_rr[2];
+ }
+ }
+
+ logerror("z80dart_irq_ack: failed to find an interrupt to ack!\n");
+
+ return m_channel[CHANNEL_B].m_rr[2];
+}
+
+
+//-------------------------------------------------
+// z80daisy_irq_reti - return from interrupt
+//-------------------------------------------------
+
+void z80dart_device::z80daisy_irq_reti()
+{
+ int i;
+
+ LOG(("Z80DART \"%s\" Return from Interrupt\n", tag()));
+
+ // loop over all interrupt sources
+ for (i = 0; i < 8; i++)
+ {
+ // find the first channel with an IEO pending
+ if (m_int_state[i] & Z80_DAISY_IEO)
+ {
+ // clear the IEO state and update the IRQs
+ m_int_state[i] &= ~Z80_DAISY_IEO;
+ check_interrupts();
+ return;
+ }
+ }
+
+ logerror("z80dart_irq_reti: failed to find an interrupt to clear IEO on!\n");
+}
+
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+//-------------------------------------------------
+// check_interrupts - control interrupt line
+//-------------------------------------------------
+
+void z80dart_device::check_interrupts()
+{
+ int state = (z80daisy_irq_state() & Z80_DAISY_INT) ? ASSERT_LINE : CLEAR_LINE;
+ m_out_int_func(state);
+}
+
+
+//-------------------------------------------------
+// take_interrupt - trigger interrupt
+//-------------------------------------------------
+
+void z80dart_device::take_interrupt(int priority)
+{
+ m_int_state[priority] |= Z80_DAISY_INT;
+ m_channel[CHANNEL_A].m_rr[0] |= RR0_INTERRUPT_PENDING;
+
+ // check for interrupt
+ check_interrupts();
+}
+
+
+
+//**************************************************************************
+// DART CHANNEL
+//**************************************************************************
+
+//-------------------------------------------------
+// dart_channel - constructor
+//-------------------------------------------------
+
+z80dart_device::dart_channel::dart_channel()
+ : m_rx_shift(0),
+ m_rx_error(0),
+ m_rx_fifo(0),
+ m_rx_clock(0),
+ m_rx_state(0),
+ m_rx_bits(0),
+ m_rx_first(0),
+ m_rx_parity(0),
+ m_rx_break(0),
+ m_rx_rr0_latch(0),
+ m_ri(0),
+ m_cts(0),
+ m_dcd(0),
+ m_tx_data(0),
+ m_tx_shift(0),
+ m_tx_clock(0),
+ m_tx_state(0),
+ m_tx_bits(0),
+ m_tx_parity(0),
+ m_dtr(0),
+ m_rts(0),
+ m_sync(0)
+{
+ memset(&m_in_rxd_func, 0, sizeof(m_in_rxd_func));
+ memset(&m_out_txd_func, 0, sizeof(m_out_txd_func));
+ memset(&m_out_dtr_func, 0, sizeof(m_out_dtr_func));
+ memset(&m_out_rts_func, 0, sizeof(m_out_rts_func));
+ memset(&m_out_wrdy_func, 0, sizeof(m_out_wrdy_func));
+ memset(&m_rr, 0, sizeof(m_rr));
+ memset(&m_wr, 0, sizeof(m_wr));
+ memset(&m_rx_data_fifo, 0, sizeof(m_rx_data_fifo));
+ memset(&m_rx_error_fifo, 0, sizeof(m_rx_error_fifo));
+}
+
+
+//-------------------------------------------------
+// start - channel startup
+//-------------------------------------------------
+
+void z80dart_device::dart_channel::start(z80dart_device *device, int index, const devcb_read_line &in_rxd, const devcb_write_line &out_txd, const devcb_write_line &out_dtr, const devcb_write_line &out_rts, const devcb_write_line &out_wrdy, const devcb_write_line &out_sync)
+{
+ m_index = index;
+ m_device = device;
+
+ m_in_rxd_func.resolve(in_rxd, *m_device);
+ m_out_txd_func.resolve(out_txd, *m_device);
+ m_out_dtr_func.resolve(out_dtr, *m_device);
+ m_out_rts_func.resolve(out_rts, *m_device);
+ m_out_wrdy_func.resolve(out_wrdy, *m_device);
+ m_out_sync_func.resolve(out_sync, *m_device);
+
+ m_device->save_item(NAME(m_rr), m_index);
+ m_device->save_item(NAME(m_wr), m_index);
+ m_device->save_item(NAME(m_rx_data_fifo), m_index);
+ m_device->save_item(NAME(m_rx_error_fifo), m_index);
+ m_device->save_item(NAME(m_rx_shift), m_index);
+ m_device->save_item(NAME(m_rx_error), m_index);
+ m_device->save_item(NAME(m_rx_fifo), m_index);
+ m_device->save_item(NAME(m_rx_clock), m_index);
+ m_device->save_item(NAME(m_rx_state), m_index);
+ m_device->save_item(NAME(m_rx_bits), m_index);
+ m_device->save_item(NAME(m_rx_first), m_index);
+ m_device->save_item(NAME(m_rx_parity), m_index);
+ m_device->save_item(NAME(m_rx_break), m_index);
+ m_device->save_item(NAME(m_rx_rr0_latch), m_index);
+ m_device->save_item(NAME(m_ri), m_index);
+ m_device->save_item(NAME(m_cts), m_index);
+ m_device->save_item(NAME(m_dcd), m_index);
+ m_device->save_item(NAME(m_tx_data), m_index);
+ m_device->save_item(NAME(m_tx_shift), m_index);
+ m_device->save_item(NAME(m_tx_clock), m_index);
+ m_device->save_item(NAME(m_tx_state), m_index);
+ m_device->save_item(NAME(m_tx_bits), m_index);
+ m_device->save_item(NAME(m_tx_parity), m_index);
+ m_device->save_item(NAME(m_dtr), m_index);
+ m_device->save_item(NAME(m_rts), m_index);
+ m_device->save_item(NAME(m_sync), m_index);
+}
+
+
+//-------------------------------------------------
+// take_interrupt - trigger interrupt
+//-------------------------------------------------
+
+void z80dart_device::dart_channel::take_interrupt(int level)
+{
+ UINT8 vector = m_device->m_channel[CHANNEL_B].m_wr[2];
+ int priority = (m_index << 2) | level;
+
+ LOG(("Z80DART \"%s\" Channel %c : Interrupt Request %u\n", m_device->tag(), 'A' + m_index, level));
+
+ if ((m_index == CHANNEL_B) && (m_wr[1] & WR1_STATUS_VECTOR))
+ {
+ // status affects vector
+ vector = (m_wr[2] & 0xf1) | (!m_index << 3) | (level << 1);
+ }
+
+ // update vector register
+ m_device->m_channel[CHANNEL_B].m_rr[2] = vector;
+
+ // trigger interrupt
+ m_device->take_interrupt(priority);
+}
+
+
+//-------------------------------------------------
+// get_clock_mode - get clock divisor
+//-------------------------------------------------
+
+int z80dart_device::dart_channel::get_clock_mode()
+{
+ int clocks = 1;
+
+ switch (m_wr[4] & WR4_CLOCK_RATE_MASK)
+ {
+ case WR4_CLOCK_RATE_X1: clocks = 1; break;
+ case WR4_CLOCK_RATE_X16: clocks = 16; break;
+ case WR4_CLOCK_RATE_X32: clocks = 32; break;
+ case WR4_CLOCK_RATE_X64: clocks = 64; break;
+ }
+
+ return clocks;
+}
+
+
+//-------------------------------------------------
+// get_stop_bits - get number of stop bits
+//-------------------------------------------------
+
+float z80dart_device::dart_channel::get_stop_bits()
+{
+ float bits = 1;
+
+ switch (m_wr[4] & WR4_STOP_BITS_MASK)
+ {
+ case WR4_STOP_BITS_1: bits = 1; break;
+ case WR4_STOP_BITS_1_5: bits = 1.5; break;
+ case WR4_STOP_BITS_2: bits = 2; break;
+ }
+
+ return bits;
+}
+
+
+//-------------------------------------------------
+// get_rx_word_length - get receive word length
+//-------------------------------------------------
+
+int z80dart_device::dart_channel::get_rx_word_length()
+{
+ int bits = 5;
+
+ switch (m_wr[3] & WR3_RX_WORD_LENGTH_MASK)
+ {
+ case WR3_RX_WORD_LENGTH_5: bits = 5; break;
+ case WR3_RX_WORD_LENGTH_6: bits = 6; break;
+ case WR3_RX_WORD_LENGTH_7: bits = 7; break;
+ case WR3_RX_WORD_LENGTH_8: bits = 8; break;
+ }
+
+ return bits;
+}
+
+
+//-------------------------------------------------
+// get_tx_word_length - get transmit word length
+//-------------------------------------------------
+
+int z80dart_device::dart_channel::get_tx_word_length()
+{
+ int bits = 5;
+
+ switch (m_wr[5] & WR5_TX_WORD_LENGTH_MASK)
+ {
+ case WR5_TX_WORD_LENGTH_5: bits = 5; break;
+ case WR5_TX_WORD_LENGTH_6: bits = 6; break;
+ case WR5_TX_WORD_LENGTH_7: bits = 7; break;
+ case WR5_TX_WORD_LENGTH_8: bits = 8; break;
+ }
+
+ return bits;
+}
+
+
+//-------------------------------------------------
+// reset - reset channel status
+//-------------------------------------------------
+
+void z80dart_device::dart_channel::reset()
+{
+ // disable receiver
+ m_wr[3] &= ~WR3_RX_ENABLE;
+ m_rx_state = STATE_START;
+
+ // disable transmitter
+ m_wr[5] &= ~WR5_TX_ENABLE;
+ m_tx_state = STATE_START;
+
+ // reset external lines
+ RTS(1);
+ DTR(1);
+
+ if (m_index == CHANNEL_A)
+ {
+ // reset interrupt logic
+ int i;
+
+ for (i = 0; i < 8; i++)
+ {
+ m_device->m_int_state[i] = 0;
+ }
+
+ m_device->check_interrupts();
+ }
+}
+
+
+//-------------------------------------------------
+// detect_start_bit - detect start bit
+//-------------------------------------------------
+
+int z80dart_device::dart_channel::detect_start_bit()
+{
+ if (!(m_wr[3] & WR3_RX_ENABLE)) return 0;
+
+ return !RXD;
+}
+
+
+//-------------------------------------------------
+// shift_data_in - shift in serial data
+//-------------------------------------------------
+
+void z80dart_device::dart_channel::shift_data_in()
+{
+ if (m_rx_bits < 8)
+ {
+ int rxd = RXD;
+
+ m_rx_shift >>= 1;
+ m_rx_shift = (rxd << 7) | (m_rx_shift & 0x7f);
+ m_rx_parity ^= rxd;
+ m_rx_bits++;
+ }
+}
+
+
+//-------------------------------------------------
+// character_completed - check if complete
+// data word has been transferred
+//-------------------------------------------------
+
+bool z80dart_device::dart_channel::character_completed()
+{
+ return m_rx_bits == get_rx_word_length();
+}
+
+
+//-------------------------------------------------
+// detect_parity_error - detect parity error
+//-------------------------------------------------
+
+void z80dart_device::dart_channel::detect_parity_error()
+{
+ int parity = (m_wr[1] & WR4_PARITY_EVEN) ? 1 : 0;
+
+ if (RXD != (m_rx_parity ^ parity))
+ {
+ // parity error detected
+ m_rx_error |= RR1_PARITY_ERROR;
+
+ switch (m_wr[1] & WR1_RX_INT_MODE_MASK)
+ {
+ case WR1_RX_INT_FIRST:
+ if (!m_rx_first)
+ {
+ take_interrupt(INT_SPECIAL);
+ }
+ break;
+
+ case WR1_RX_INT_ALL_PARITY:
+ take_interrupt(INT_SPECIAL);
+ break;
+
+ case WR1_RX_INT_ALL:
+ take_interrupt(INT_RECEIVE);
+ break;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// detect_framing_error - detect framing error
+//-------------------------------------------------
+
+void z80dart_device::dart_channel::detect_framing_error()
+{
+ if (!RXD)
+ {
+ // framing error detected
+ m_rx_error |= RR1_CRC_FRAMING_ERROR;
+
+ switch (m_wr[1] & WR1_RX_INT_MODE_MASK)
+ {
+ case WR1_RX_INT_FIRST:
+ if (!m_rx_first)
+ {
+ take_interrupt(INT_SPECIAL);
+ }
+ break;
+
+ case WR1_RX_INT_ALL_PARITY:
+ case WR1_RX_INT_ALL:
+ take_interrupt(INT_SPECIAL);
+ break;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// receive - receive serial data
+//-------------------------------------------------
+
+void z80dart_device::dart_channel::receive()
+{
+ float stop_bits = get_stop_bits();
+
+ switch (m_rx_state)
+ {
+ case STATE_START:
+ // check for start bit
+ if (detect_start_bit())
+ {
+ // start bit detected
+ m_rx_shift = 0;
+ m_rx_error = 0;
+ m_rx_bits = 0;
+ m_rx_parity = 0;
+
+ // next bit is a data bit
+ m_rx_state = STATE_DATA;
+ }
+ break;
+
+ case STATE_DATA:
+ // shift bit into shift register
+ shift_data_in();
+
+ if (character_completed())
+ {
+ // all data bits received
+ if (m_wr[4] & WR4_PARITY_ENABLE)
+ {
+ // next bit is the parity bit
+ m_rx_state = STATE_PARITY;
+ }
+ else
+ {
+ // next bit is a STOP bit
+ if (stop_bits == 1)
+ m_rx_state = STATE_STOP2;
+ else
+ m_rx_state = STATE_STOP;
+ }
+ }
+ break;
+
+ case STATE_PARITY:
+ // shift bit into shift register
+ shift_data_in();
+
+ // check for parity error
+ detect_parity_error();
+
+ // next bit is a STOP bit
+ if (stop_bits == 1)
+ m_rx_state = STATE_STOP2;
+ else
+ m_rx_state = STATE_STOP;
+ break;
+
+ case STATE_STOP:
+ // shift bit into shift register
+ shift_data_in();
+
+ // check for framing error
+ detect_framing_error();
+
+ // next bit is the second STOP bit
+ m_rx_state = STATE_STOP2;
+ break;
+
+ case STATE_STOP2:
+ // shift bit into shift register
+ shift_data_in();
+
+ // check for framing error
+ detect_framing_error();
+
+ // store data into FIFO
+ receive_data(m_rx_shift);
+
+ // next bit is the START bit
+ m_rx_state = STATE_START;
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// transmit - transmit serial data
+//-------------------------------------------------
+
+void z80dart_device::dart_channel::transmit()
+{
+ int word_length = get_tx_word_length();
+ float stop_bits = get_stop_bits();
+
+ switch (m_tx_state)
+ {
+ case STATE_START:
+ if ((m_wr[5] & WR5_TX_ENABLE) && !(m_rr[0] & RR0_TX_BUFFER_EMPTY))
+ {
+ // transmit start bit
+ TXD(0);
+
+ m_tx_bits = 0;
+ m_tx_shift = m_tx_data;
+
+ // empty transmit buffer
+ m_rr[0] |= RR0_TX_BUFFER_EMPTY;
+
+ if (m_wr[1] & WR1_TX_INT_ENABLE)
+ take_interrupt(INT_TRANSMIT);
+
+ m_tx_state = STATE_DATA;
+ }
+ else if (m_wr[5] & WR5_SEND_BREAK)
+ {
+ // transmit break
+ TXD(0);
+ }
+ else
+ {
+ // transmit marking line
+ TXD(1);
+ }
+
+ break;
+
+ case STATE_DATA:
+ // transmit data bit
+ TXD(BIT(m_tx_shift, 0));
+
+ // shift data
+ m_tx_shift >>= 1;
+ m_tx_bits++;
+
+ if (m_tx_bits == word_length)
+ {
+ if (m_wr[4] & WR4_PARITY_ENABLE)
+ m_tx_state = STATE_PARITY;
+ else
+ {
+ if (stop_bits == 1)
+ m_tx_state = STATE_STOP2;
+ else
+ m_tx_state = STATE_STOP;
+ }
+ }
+ break;
+
+ case STATE_PARITY:
+ // TODO: calculate parity
+ if (stop_bits == 1)
+ m_tx_state = STATE_STOP2;
+ else
+ m_tx_state = STATE_STOP;
+ break;
+
+ case STATE_STOP:
+ // transmit stop bit
+ TXD(1);
+
+ m_tx_state = STATE_STOP2;
+ break;
+
+ case STATE_STOP2:
+ // transmit stop bit
+ TXD(1);
+
+ // if transmit buffer is empty
+ if (m_rr[0] & RR0_TX_BUFFER_EMPTY)
+ {
+ // then all characters have been sent
+ m_rr[1] |= RR1_ALL_SENT;
+
+ // when the RTS bit is reset, the _RTS output goes high after the transmitter empties
+ if (!m_rts)
+ RTS(1);
+ }
+
+ m_tx_state = STATE_START;
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// control_read - read control register
+//-------------------------------------------------
+
+UINT8 z80dart_device::dart_channel::control_read()
+{
+ UINT8 data = 0;
+
+ int reg = m_wr[0] & WR0_REGISTER_MASK;
+
+ if (reg != 0)
+ {
+ // mask out register index
+ m_wr[0] &= ~WR0_REGISTER_MASK;
+ }
+
+ switch (reg)
+ {
+ case 0:
+ case 1:
+ data = m_rr[reg];
+ break;
+
+ case 2:
+ // channel B only
+ if (m_index == CHANNEL_B)
+ data = m_rr[reg];
+ break;
+ }
+
+ LOG(("Z80DART \"%s\" Channel %c : Control Register Read '%02x'\n", m_device->tag(), 'A' + m_index, data));
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// control_write - write control register
+//-------------------------------------------------
+
+void z80dart_device::dart_channel::control_write(UINT8 data)
+{
+ int reg = m_wr[0] & WR0_REGISTER_MASK;
+
+ LOG(("Z80DART \"%s\" Channel %c : Control Register Write '%02x'\n", m_device->tag(), 'A' + m_index, data));
+
+ // write data to selected register
+ m_wr[reg] = data;
+
+ if (reg != 0)
+ {
+ // mask out register index
+ m_wr[0] &= ~WR0_REGISTER_MASK;
+ }
+
+ switch (reg)
+ {
+ case 0:
+ switch (data & WR0_COMMAND_MASK)
+ {
+ case WR0_NULL:
+ LOG(("Z80DART \"%s\" Channel %c : Null\n", m_device->tag(), 'A' + m_index));
+ break;
+
+ case WR0_SEND_ABORT:
+ LOG(("Z80DART \"%s\" Channel %c : Send Abort\n", m_device->tag(), 'A' + m_index));
+ logerror("Z80DART \"%s\" Channel %c : unsupported command: Send Abort\n", m_device->tag(), 'A' + m_index);
+ break;
+
+ case WR0_RESET_EXT_STATUS:
+ // reset external/status interrupt
+ m_rr[0] &= ~(RR0_DCD | RR0_RI | RR0_CTS | RR0_BREAK_ABORT);
+
+ if (!m_dcd) m_rr[0] |= RR0_DCD;
+ if (m_ri) m_rr[0] |= RR0_RI;
+ if (m_cts) m_rr[0] |= RR0_CTS;
+
+ m_rx_rr0_latch = 0;
+
+ LOG(("Z80DART \"%s\" Channel %c : Reset External/Status Interrupt\n", m_device->tag(), 'A' + m_index));
+ break;
+
+ case WR0_CHANNEL_RESET:
+ // channel reset
+ LOG(("Z80DART \"%s\" Channel %c : Channel Reset\n", m_device->tag(), 'A' + m_index));
+ reset();
+ break;
+
+ case WR0_ENABLE_INT_NEXT_RX:
+ // enable interrupt on next receive character
+ LOG(("Z80DART \"%s\" Channel %c : Enable Interrupt on Next Received Character\n", m_device->tag(), 'A' + m_index));
+ m_rx_first = 1;
+ break;
+
+ case WR0_RESET_TX_INT:
+ // reset transmitter interrupt pending
+ LOG(("Z80DART \"%s\" Channel %c : Reset Transmitter Interrupt Pending\n", m_device->tag(), 'A' + m_index));
+ logerror("Z80DART \"%s\" Channel %c : unsupported command: Reset Transmitter Interrupt Pending\n", m_device->tag(), 'A' + m_index);
+ break;
+
+ case WR0_ERROR_RESET:
+ // error reset
+ LOG(("Z80DART \"%s\" Channel %c : Error Reset\n", m_device->tag(), 'A' + m_index));
+ m_rr[1] &= ~(RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR);
+ break;
+
+ case WR0_RETURN_FROM_INT:
+ // return from interrupt
+ LOG(("Z80DART \"%s\" Channel %c : Return from Interrupt\n", m_device->tag(), 'A' + m_index));
+ m_device->z80daisy_irq_reti();
+ break;
+ }
+ break;
+
+ case 1:
+ LOG(("Z80DART \"%s\" Channel %c : External Interrupt Enable %u\n", m_device->tag(), 'A' + m_index, (data & WR1_EXT_INT_ENABLE) ? 1 : 0));
+ LOG(("Z80DART \"%s\" Channel %c : Transmit Interrupt Enable %u\n", m_device->tag(), 'A' + m_index, (data & WR1_TX_INT_ENABLE) ? 1 : 0));
+ LOG(("Z80DART \"%s\" Channel %c : Status Affects Vector %u\n", m_device->tag(), 'A' + m_index, (data & WR1_STATUS_VECTOR) ? 1 : 0));
+ LOG(("Z80DART \"%s\" Channel %c : Wait/Ready Enable %u\n", m_device->tag(), 'A' + m_index, (data & WR1_WRDY_ENABLE) ? 1 : 0));
+ LOG(("Z80DART \"%s\" Channel %c : Wait/Ready Function %s\n", m_device->tag(), 'A' + m_index, (data & WR1_WRDY_FUNCTION) ? "Ready" : "Wait"));
+ LOG(("Z80DART \"%s\" Channel %c : Wait/Ready on %s\n", m_device->tag(), 'A' + m_index, (data & WR1_WRDY_ON_RX_TX) ? "Receive" : "Transmit"));
+
+ switch (data & WR1_RX_INT_MODE_MASK)
+ {
+ case WR1_RX_INT_DISABLE:
+ LOG(("Z80DART \"%s\" Channel %c : Receiver Interrupt Disabled\n", m_device->tag(), 'A' + m_index));
+ break;
+
+ case WR1_RX_INT_FIRST:
+ LOG(("Z80DART \"%s\" Channel %c : Receiver Interrupt on First Character\n", m_device->tag(), 'A' + m_index));
+ break;
+
+ case WR1_RX_INT_ALL_PARITY:
+ LOG(("Z80DART \"%s\" Channel %c : Receiver Interrupt on All Characters, Parity Affects Vector\n", m_device->tag(), 'A' + m_index));
+ break;
+
+ case WR1_RX_INT_ALL:
+ LOG(("Z80DART \"%s\" Channel %c : Receiver Interrupt on All Characters\n", m_device->tag(), 'A' + m_index));
+ break;
+ }
+
+ m_device->check_interrupts();
+ break;
+
+ case 2:
+ // interrupt vector
+ if (m_index == CHANNEL_B)
+ m_rr[2] = ( m_rr[2] & 0x0e ) | ( m_wr[2] & 0xF1);;
+
+ m_device->check_interrupts();
+ LOG(("Z80DART \"%s\" Channel %c : Interrupt Vector %02x\n", m_device->tag(), 'A' + m_index, data));
+ break;
+
+ case 3:
+ LOG(("Z80DART \"%s\" Channel %c : Receiver Enable %u\n", m_device->tag(), 'A' + m_index, (data & WR3_RX_ENABLE) ? 1 : 0));
+ LOG(("Z80DART \"%s\" Channel %c : Auto Enables %u\n", m_device->tag(), 'A' + m_index, (data & WR3_AUTO_ENABLES) ? 1 : 0));
+ LOG(("Z80DART \"%s\" Channel %c : Receiver Bits/Character %u\n", m_device->tag(), 'A' + m_index, get_rx_word_length()));
+ break;
+
+ case 4:
+ LOG(("Z80DART \"%s\" Channel %c : Parity Enable %u\n", m_device->tag(), 'A' + m_index, (data & WR4_PARITY_ENABLE) ? 1 : 0));
+ LOG(("Z80DART \"%s\" Channel %c : Parity %s\n", m_device->tag(), 'A' + m_index, (data & WR4_PARITY_EVEN) ? "Even" : "Odd"));
+ LOG(("Z80DART \"%s\" Channel %c : Stop Bits %f\n", m_device->tag(), 'A' + m_index, get_stop_bits()));
+ LOG(("Z80DART \"%s\" Channel %c : Clock Mode %uX\n", m_device->tag(), 'A' + m_index, get_clock_mode()));
+ break;
+
+ case 5:
+ LOG(("Z80DART \"%s\" Channel %c : Transmitter Enable %u\n", m_device->tag(), 'A' + m_index, (data & WR5_TX_ENABLE) ? 1 : 0));
+ LOG(("Z80DART \"%s\" Channel %c : Transmitter Bits/Character %u\n", m_device->tag(), 'A' + m_index, get_tx_word_length()));
+ LOG(("Z80DART \"%s\" Channel %c : Send Break %u\n", m_device->tag(), 'A' + m_index, (data & WR5_SEND_BREAK) ? 1 : 0));
+ LOG(("Z80DART \"%s\" Channel %c : Request to Send %u\n", m_device->tag(), 'A' + m_index, (data & WR5_RTS) ? 1 : 0));
+ LOG(("Z80DART \"%s\" Channel %c : Data Terminal Ready %u\n", m_device->tag(), 'A' + m_index, (data & WR5_DTR) ? 1 : 0));
+
+ if (data & WR5_RTS)
+ {
+ // when the RTS bit is set, the _RTS output goes low
+ RTS(0);
+
+ m_rts = 1;
+ }
+ else
+ {
+ // when the RTS bit is reset, the _RTS output goes high after the transmitter empties
+ m_rts = 0;
+ }
+
+ // data terminal ready output follows the state programmed into the DTR bit*/
+ m_dtr = (data & WR5_DTR) ? 0 : 1;
+ DTR(m_dtr);
+ break;
+
+ case 6:
+ LOG(("Z80DART \"%s\" Channel %c : Transmit Sync %02x\n", m_device->tag(), 'A' + m_index, data));
+ m_sync = (m_sync & 0xff00) | data;
+ break;
+
+ case 7:
+ LOG(("Z80DART \"%s\" Channel %c : Receive Sync %02x\n", m_device->tag(), 'A' + m_index, data));
+ m_sync = (data << 8) | (m_sync & 0xff);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// data_read - read data register
+//-------------------------------------------------
+
+UINT8 z80dart_device::dart_channel::data_read()
+{
+ UINT8 data = 0;
+
+ if (m_rx_fifo >= 0)
+ {
+ // load data from the FIFO
+ data = m_rx_data_fifo[m_rx_fifo];
+
+ // load error status from the FIFO, retain overrun and parity errors
+ m_rr[1] = (m_rr[1] & (RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR)) | m_rx_error_fifo[m_rx_fifo];
+
+ // decrease FIFO pointer
+ m_rx_fifo--;
+
+ if (m_rx_fifo < 0)
+ {
+ // no more characters available in the FIFO
+ m_rr[0] &= ~ RR0_RX_CHAR_AVAILABLE;
+ }
+ }
+
+ LOG(("Z80DART \"%s\" Channel %c : Data Register Read '%02x'\n", m_device->tag(), 'A' + m_index, data));
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// data_write - write data register
+//-------------------------------------------------
+
+void z80dart_device::dart_channel::data_write(UINT8 data)
+{
+ m_tx_data = data;
+
+ m_rr[0] &= ~RR0_TX_BUFFER_EMPTY;
+ m_rr[1] &= ~RR1_ALL_SENT;
+
+ LOG(("Z80DART \"%s\" Channel %c : Data Register Write '%02x'\n", m_device->tag(), 'A' + m_index, data));
+}
+
+
+//-------------------------------------------------
+// receive_data - receive data word
+//-------------------------------------------------
+
+void z80dart_device::dart_channel::receive_data(UINT8 data)
+{
+ LOG(("Z80DART \"%s\" Channel %c : Receive Data Byte '%02x'\n", m_device->tag(), 'A' + m_index, data));
+
+ if (m_rx_fifo == 2)
+ {
+ // receive overrun error detected
+ m_rx_error |= RR1_RX_OVERRUN_ERROR;
+
+ switch (m_wr[1] & WR1_RX_INT_MODE_MASK)
+ {
+ case WR1_RX_INT_FIRST:
+ if (!m_rx_first)
+ {
+ take_interrupt(INT_SPECIAL);
+ }
+ break;
+
+ case WR1_RX_INT_ALL_PARITY:
+ case WR1_RX_INT_ALL:
+ take_interrupt(INT_SPECIAL);
+ break;
+ }
+ }
+ else
+ {
+ m_rx_fifo++;
+ }
+
+ // store received character and error status into FIFO
+ m_rx_data_fifo[m_rx_fifo] = data;
+ m_rx_error_fifo[m_rx_fifo] = m_rx_error;
+
+ m_rr[0] |= RR0_RX_CHAR_AVAILABLE;
+
+ // receive interrupt
+ switch (m_wr[1] & WR1_RX_INT_MODE_MASK)
+ {
+ case WR1_RX_INT_FIRST:
+ if (m_rx_first)
+ {
+ take_interrupt(INT_RECEIVE);
+
+ m_rx_first = 0;
+ }
+ break;
+
+ case WR1_RX_INT_ALL_PARITY:
+ case WR1_RX_INT_ALL:
+ take_interrupt(INT_RECEIVE);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// cts_w - clear to send handler
+//-------------------------------------------------
+
+void z80dart_device::dart_channel::cts_w(int state)
+{
+ LOG(("Z80DART \"%s\" Channel %c : CTS %u\n", m_device->tag(), 'A' + m_index, state));
+
+ if (m_cts != state)
+ {
+ // enable transmitter if in auto enables mode
+ if (!state)
+ if (m_wr[3] & WR3_AUTO_ENABLES)
+ m_wr[5] |= WR5_TX_ENABLE;
+
+ // set clear to send
+ m_cts = state;
+
+ if (!m_rx_rr0_latch)
+ {
+ if (!m_cts)
+ m_rr[0] |= RR0_CTS;
+ else
+ m_rr[0] &= ~RR0_CTS;
+
+ // trigger interrupt
+ if (m_wr[1] & WR1_EXT_INT_ENABLE)
+ {
+ // trigger interrupt
+ take_interrupt(INT_EXTERNAL);
+
+ // latch read register 0
+ m_rx_rr0_latch = 1;
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// dcd_w - data carrier detected handler
+//-------------------------------------------------
+
+void z80dart_device::dart_channel::dcd_w(int state)
+{
+ LOG(("Z80DART \"%s\" Channel %c : DCD %u\n", m_device->tag(), 'A' + m_index, state));
+
+ if (m_dcd != state)
+ {
+ // enable receiver if in auto enables mode
+ if (!state)
+ if (m_wr[3] & WR3_AUTO_ENABLES)
+ m_wr[3] |= WR3_RX_ENABLE;
+
+ // set data carrier detect
+ m_dcd = state;
+
+ if (!m_rx_rr0_latch)
+ {
+ if (m_dcd)
+ m_rr[0] |= RR0_DCD;
+ else
+ m_rr[0] &= ~RR0_DCD;
+
+ if (m_wr[1] & WR1_EXT_INT_ENABLE)
+ {
+ // trigger interrupt
+ take_interrupt(INT_EXTERNAL);
+
+ // latch read register 0
+ m_rx_rr0_latch = 1;
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// ri_w - ring indicator handler
+//-------------------------------------------------
+
+void z80dart_device::dart_channel::ri_w(int state)
+{
+ LOG(("Z80DART \"%s\" Channel %c : RI %u\n", m_device->tag(), 'A' + m_index, state));
+
+ if (m_ri != state)
+ {
+ // set ring indicator state
+ m_ri = state;
+
+ if (!m_rx_rr0_latch)
+ {
+ if (m_ri)
+ m_rr[0] |= RR0_RI;
+ else
+ m_rr[0] &= ~RR0_RI;
+
+ if (m_wr[1] & WR1_EXT_INT_ENABLE)
+ {
+ // trigger interrupt
+ take_interrupt(INT_EXTERNAL);
+
+ // latch read register 0
+ m_rx_rr0_latch = 1;
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// sync_w - sync handler
+//-------------------------------------------------
+
+void z80dart_device::dart_channel::sync_w(int state)
+{
+ LOG(("Z80DART \"%s\" Channel %c : SYNC %u\n", m_device->tag(), 'A' + m_index, state));
+}
+
+
+//-------------------------------------------------
+// rx_w - receive clock
+//-------------------------------------------------
+
+void z80dart_device::dart_channel::rx_w(int state)
+{
+ int clocks = get_clock_mode();
+
+ if (!state) return;
+
+ LOG(("Z80DART \"%s\" Channel %c : Receiver Clock Pulse\n", m_device->tag(), m_index + 'A'));
+
+ m_rx_clock++;
+ if (m_rx_clock == clocks)
+ {
+ m_rx_clock = 0;
+ receive();
+ }
+}
+
+
+//-------------------------------------------------
+// tx_w - transmit clock
+//-------------------------------------------------
+
+void z80dart_device::dart_channel::tx_w(int state)
+{
+ int clocks = get_clock_mode();
+
+ if (!state) return;
+
+ LOG(("Z80DART \"%s\" Channel %c : Transmitter Clock Pulse\n", m_device->tag(), m_index + 'A'));
+
+ m_tx_clock++;
+ if (m_tx_clock == clocks)
+ {
+ m_tx_clock = 0;
+ transmit();
+ }
+}
+
+
+
+//**************************************************************************
+// GLOBAL STUBS
+//**************************************************************************
+
+READ8_DEVICE_HANDLER( z80dart_c_r ) { return downcast<z80dart_device *>(device)->control_read(offset & 1); }
+READ8_DEVICE_HANDLER( z80dart_d_r ) { return downcast<z80dart_device *>(device)->data_read(offset & 1); }
+
+WRITE8_DEVICE_HANDLER( z80dart_c_w ) { downcast<z80dart_device *>(device)->control_write(offset & 1, data); }
+WRITE8_DEVICE_HANDLER( z80dart_d_w ) { downcast<z80dart_device *>(device)->data_write(offset & 1, data); }
+
+WRITE_LINE_DEVICE_HANDLER( z80dart_ctsa_w ) { downcast<z80dart_device *>(device)->cts_w(CHANNEL_A, state); }
+WRITE_LINE_DEVICE_HANDLER( z80dart_ctsb_w ) { downcast<z80dart_device *>(device)->cts_w(CHANNEL_B, state); }
+WRITE_LINE_DEVICE_HANDLER( z80dart_dcda_w ) { downcast<z80dart_device *>(device)->dcd_w(CHANNEL_A, state); }
+WRITE_LINE_DEVICE_HANDLER( z80dart_dcdb_w ) { downcast<z80dart_device *>(device)->dcd_w(CHANNEL_B, state); }
+WRITE_LINE_DEVICE_HANDLER( z80dart_ria_w ) { downcast<z80dart_device *>(device)->ri_w(CHANNEL_A, state); }
+WRITE_LINE_DEVICE_HANDLER( z80dart_rib_w ) { downcast<z80dart_device *>(device)->ri_w(CHANNEL_B, state); }
+WRITE_LINE_DEVICE_HANDLER( z80dart_synca_w ) { downcast<z80dart_device *>(device)->sync_w(CHANNEL_A, state); }
+WRITE_LINE_DEVICE_HANDLER( z80dart_syncb_w ) { downcast<z80dart_device *>(device)->sync_w(CHANNEL_B, state); }
+
+WRITE_LINE_DEVICE_HANDLER( z80dart_rxca_w ) { downcast<z80dart_device *>(device)->rx_w(CHANNEL_A, state); }
+WRITE_LINE_DEVICE_HANDLER( z80dart_txca_w ) { downcast<z80dart_device *>(device)->tx_w(CHANNEL_A, state); }
+WRITE_LINE_DEVICE_HANDLER( z80dart_rxcb_w ) { downcast<z80dart_device *>(device)->rx_w(CHANNEL_B, state); }
+WRITE_LINE_DEVICE_HANDLER( z80dart_txcb_w ) { downcast<z80dart_device *>(device)->tx_w(CHANNEL_B, state); }
+WRITE_LINE_DEVICE_HANDLER( z80dart_rxtxcb_w ) { downcast<z80dart_device *>(device)->rx_w(CHANNEL_B, state); downcast<z80dart_device *>(device)->tx_w(CHANNEL_B, state); }
+
+READ8_DEVICE_HANDLER( z80dart_cd_ba_r )
+{
+ return (offset & 2) ? z80dart_c_r(device, offset & 1) : z80dart_d_r(device, offset & 1);
+}
+
+WRITE8_DEVICE_HANDLER( z80dart_cd_ba_w )
+{
+ if (offset & 2)
+ z80dart_c_w(device, offset & 1, data);
+ else
+ z80dart_d_w(device, offset & 1, data);
+}
+
+READ8_DEVICE_HANDLER( z80dart_ba_cd_r )
+{
+ int channel = BIT(offset, 1);
+
+ return (offset & 1) ? z80dart_c_r(device, channel) : z80dart_d_r(device, channel);
+}
+
+WRITE8_DEVICE_HANDLER( z80dart_ba_cd_w )
+{
+ int channel = BIT(offset, 1);
+
+ if (offset & 1)
+ z80dart_c_w(device, channel, data);
+ else
+ z80dart_d_w(device, channel, data);
+}
diff --git a/trunk/src/emu/machine/z80dart.h b/trunk/src/emu/machine/z80dart.h
new file mode 100644
index 00000000000..805c9427f0d
--- /dev/null
+++ b/trunk/src/emu/machine/z80dart.h
@@ -0,0 +1,378 @@
+/***************************************************************************
+
+ Z80 DART Dual Asynchronous Receiver/Transmitter implementation
+
+ Copyright (c) 2008, The MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+****************************************************************************
+ _____ _____
+ D1 1 |* \_/ | 40 D0
+ D3 2 | | 39 D2
+ D5 3 | | 38 D4
+ D7 4 | | 37 D6
+ _INT 5 | | 36 _IORQ
+ IEI 6 | | 35 _CE
+ IEO 7 | | 34 B/_A
+ _M1 8 | | 33 C/_D
+ Vdd 9 | | 32 _RD
+ _W/RDYA 10 | Z80-DART | 31 GND
+ _RIA 11 | | 30 _W/RDYB
+ RxDA 12 | | 29 _RIB
+ _RxCA 13 | | 28 RxDB
+ _TxCA 14 | | 27 _RxTxCB
+ TxDA 15 | | 26 TxDB
+ _DTRA 16 | | 25 _DTRB
+ _RTSA 17 | | 24 _RTSB
+ _CTSA 18 | | 23 _CTSB
+ _DCDA 19 | | 22 _DCDB
+ CLK 20 |_____________| 21 _RESET
+
+ _____ _____
+ D1 1 |* \_/ | 40 D0
+ D3 2 | | 39 D2
+ D5 3 | | 38 D4
+ D7 4 | | 37 D6
+ _INT 5 | | 36 _IORQ
+ IEI 6 | | 35 _CE
+ IEO 7 | | 34 B/_A
+ _M1 8 | | 33 C/_D
+ Vdd 9 | | 32 _RD
+ _W/RDYA 10 | Z80-SIO/0 | 31 GND
+ _SYNCA 11 | | 30 _W/RDYB
+ RxDA 12 | | 29 _SYNCB
+ _RxCA 13 | | 28 RxDB
+ _TxCA 14 | | 27 _RxTxCB
+ TxDA 15 | | 26 TxDB
+ _DTRA 16 | | 25 _DTRB
+ _RTSA 17 | | 24 _RTSB
+ _CTSA 18 | | 23 _CTSB
+ _DCDA 19 | | 22 _DCDB
+ CLK 20 |_____________| 21 _RESET
+
+ _____ _____
+ D1 1 |* \_/ | 40 D0
+ D3 2 | | 39 D2
+ D5 3 | | 38 D4
+ D7 4 | | 37 D6
+ _INT 5 | | 36 _IORQ
+ IEI 6 | | 35 _CE
+ IEO 7 | | 34 B/_A
+ _M1 8 | | 33 C/_D
+ Vdd 9 | | 32 _RD
+ _W/RDYA 10 | Z80-SIO/1 | 31 GND
+ _SYNCA 11 | | 30 _W/RDYB
+ RxDA 12 | | 29 _SYNCB
+ _RxCA 13 | | 28 RxDB
+ _TxCA 14 | | 27 _RxCB
+ TxDA 15 | | 26 _TxCB
+ _DTRA 16 | | 25 TxDB
+ _RTSA 17 | | 24 _RTSB
+ _CTSA 18 | | 23 _CTSB
+ _DCDA 19 | | 22 _DCDB
+ CLK 20 |_____________| 21 _RESET
+
+ _____ _____
+ D1 1 |* \_/ | 40 D0
+ D3 2 | | 39 D2
+ D5 3 | | 38 D4
+ D7 4 | | 37 D6
+ _INT 5 | | 36 _IORQ
+ IEI 6 | | 35 _CE
+ IEO 7 | | 34 B/_A
+ _M1 8 | | 33 C/_D
+ Vdd 9 | | 32 _RD
+ _W/RDYA 10 | Z80-SIO/2 | 31 GND
+ _SYNCA 11 | | 30 _W/RDYB
+ RxDA 12 | | 29 _RxDB
+ _RxCA 13 | | 28 _RxCB
+ _TxCA 14 | | 27 _TxCB
+ TxDA 15 | | 26 TxDB
+ _DTRA 16 | | 25 _DTRB
+ _RTSA 17 | | 24 _RTSB
+ _CTSA 18 | | 23 _CTSB
+ _DCDA 19 | | 22 _DCDB
+ CLK 20 |_____________| 21 _RESET
+
+***************************************************************************/
+
+#ifndef __Z80DART_H__
+#define __Z80DART_H__
+
+#include "cpu/z80/z80daisy.h"
+
+
+
+//**************************************************************************
+// DEVICE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_Z80DART_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD(_tag, Z80DART, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MCFG_Z80SIO0_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD(_tag, Z80SIO0, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MCFG_Z80SIO1_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD(_tag, Z80SIO1, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MCFG_Z80SIO2_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD(_tag, Z80SIO2, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MCFG_Z80SIO3_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD(_tag, Z80SIO3, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MCFG_Z80SIO4_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD(_tag, Z80SIO4, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MCFG_Z80DART_REMOVE(_tag) \
+ MCFG_DEVICE_REMOVE(_tag)
+
+#define Z80DART_INTERFACE(_name) \
+ const z80dart_interface (_name) =
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> z80dart_interface
+
+struct z80dart_interface
+{
+ int m_rx_clock_a; // channel A receive clock
+ int m_tx_clock_a; // channel A transmit clock
+ int m_rx_clock_b; // channel B receive clock
+ int m_tx_clock_b; // channel B transmit clock
+
+ devcb_read_line m_in_rxda_cb;
+ devcb_write_line m_out_txda_cb;
+ devcb_write_line m_out_dtra_cb;
+ devcb_write_line m_out_rtsa_cb;
+ devcb_write_line m_out_wrdya_cb;
+ devcb_write_line m_out_synca_cb;
+
+ devcb_read_line m_in_rxdb_cb;
+ devcb_write_line m_out_txdb_cb;
+ devcb_write_line m_out_dtrb_cb;
+ devcb_write_line m_out_rtsb_cb;
+ devcb_write_line m_out_wrdyb_cb;
+ devcb_write_line m_out_syncb_cb;
+
+ devcb_write_line m_out_int_cb;
+};
+
+
+
+// ======================> z80dart_device
+
+class z80dart_device : public device_t,
+ public device_z80daisy_interface,
+ public z80dart_interface
+{
+ friend class dart_channel;
+
+public:
+ // construction/destruction
+ z80dart_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // control register access
+ UINT8 control_read(int which) { return m_channel[which].control_read(); }
+ void control_write(int which, UINT8 data) { return m_channel[which].control_write(data); }
+
+ // data register access
+ UINT8 data_read(int which) { return m_channel[which].data_read(); }
+ void data_write(int which, UINT8 data) { return m_channel[which].data_write(data); }
+
+ // put data on the input lines
+ void receive_data(int which, UINT8 data) { m_channel[which].receive_data(data); }
+
+ // control line access
+ void cts_w(int which, int state) { m_channel[which].cts_w(state); }
+ void dcd_w(int which, int state) { m_channel[which].dcd_w(state); }
+ void ri_w(int which, int state) { m_channel[which].ri_w(state); }
+ void rx_w(int which, int state) { m_channel[which].rx_w(state); }
+ void tx_w(int which, int state) { m_channel[which].tx_w(state); }
+ void sync_w(int which, int state) { m_channel[which].sync_w(state); }
+
+private:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_z80daisy_interface overrides
+ virtual int z80daisy_irq_state();
+ virtual int z80daisy_irq_ack();
+ virtual void z80daisy_irq_reti();
+
+ // internal interrupt management
+ void check_interrupts();
+ void take_interrupt(int priority);
+
+ // a single channel on the DART
+ class dart_channel
+ {
+ friend class z80dart_device;
+
+ public:
+ dart_channel();
+
+ void start(z80dart_device *device, int index, const devcb_read_line &in_rxd, const devcb_write_line &out_txd, const devcb_write_line &out_dtr, const devcb_write_line &out_rts, const devcb_write_line &out_wrdy, const devcb_write_line &out_sync);
+ void reset();
+
+ UINT8 control_read();
+ void control_write(UINT8 data);
+
+ UINT8 data_read();
+ void data_write(UINT8 data);
+
+ void receive_data(UINT8 data);
+
+ void cts_w(int state);
+ void dcd_w(int state);
+ void ri_w(int state);
+ void rx_w(int state);
+ void tx_w(int state);
+ void sync_w(int state);
+
+ private:
+ void take_interrupt(int level);
+ int get_clock_mode();
+ float get_stop_bits();
+ int get_rx_word_length();
+ int get_tx_word_length();
+ int detect_start_bit();
+ void shift_data_in();
+ bool character_completed();
+ void detect_parity_error();
+ void detect_framing_error();
+ void receive();
+ void transmit();
+
+ static TIMER_CALLBACK( static_rxc_tick ) { reinterpret_cast<dart_channel *>(ptr)->rx_w(1); }
+ static TIMER_CALLBACK( static_txc_tick ) { reinterpret_cast<dart_channel *>(ptr)->tx_w(1); }
+
+ z80dart_device *m_device;
+ int m_index;
+
+ devcb_resolved_read_line m_in_rxd_func;
+ devcb_resolved_write_line m_out_txd_func;
+ devcb_resolved_write_line m_out_dtr_func;
+ devcb_resolved_write_line m_out_rts_func;
+ devcb_resolved_write_line m_out_wrdy_func;
+ devcb_resolved_write_line m_out_sync_func;
+
+ // register state
+ UINT8 m_rr[3]; // read register
+ UINT8 m_wr[6]; // write register
+
+ // receiver state
+ UINT8 m_rx_data_fifo[3]; // receive data FIFO
+ UINT8 m_rx_error_fifo[3]; // receive error FIFO
+ UINT8 m_rx_shift; // 8-bit receive shift register
+ UINT8 m_rx_error; // current receive error
+ int m_rx_fifo; // receive FIFO pointer
+
+ int m_rx_clock; // receive clock pulse count
+ int m_rx_state; // receive state
+ int m_rx_bits; // bits received
+ int m_rx_first; // first character received
+ int m_rx_parity; // received data parity
+ int m_rx_break; // receive break condition
+ UINT8 m_rx_rr0_latch; // read register 0 latched
+
+ int m_ri; // ring indicator latch
+ int m_cts; // clear to send latch
+ int m_dcd; // data carrier detect latch
+
+ // transmitter state
+ UINT8 m_tx_data; // transmit data register
+ UINT8 m_tx_shift; // transmit shift register
+
+ int m_tx_clock; // transmit clock pulse count
+ int m_tx_state; // transmit state
+ int m_tx_bits; // bits transmitted
+ int m_tx_parity; // transmitted data parity
+
+ int m_dtr; // data terminal ready
+ int m_rts; // request to send
+
+ // synchronous state
+ UINT16 m_sync; // sync character
+ };
+
+ // internal state
+ devcb_resolved_write_line m_out_int_func;
+ dart_channel m_channel[2]; // channels
+ int m_int_state[8]; // interrupt state
+
+ // timers
+ emu_timer * m_rxca_timer;
+ emu_timer * m_txca_timer;
+ emu_timer * m_rxcb_timer;
+ emu_timer * m_txcb_timer;
+};
+
+
+// device type definition
+extern const device_type Z80DART;
+extern const device_type Z80SIO0;
+extern const device_type Z80SIO1;
+extern const device_type Z80SIO2;
+extern const device_type Z80SIO3;
+extern const device_type Z80SIO4;
+
+
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+// register access
+READ8_DEVICE_HANDLER( z80dart_cd_ba_r );
+WRITE8_DEVICE_HANDLER( z80dart_cd_ba_w );
+
+READ8_DEVICE_HANDLER( z80dart_ba_cd_r );
+WRITE8_DEVICE_HANDLER( z80dart_ba_cd_w );
+
+// control register access
+WRITE8_DEVICE_HANDLER( z80dart_c_w );
+READ8_DEVICE_HANDLER( z80dart_c_r );
+
+// data register access
+WRITE8_DEVICE_HANDLER( z80dart_d_w );
+READ8_DEVICE_HANDLER( z80dart_d_r );
+
+// serial clocks
+WRITE_LINE_DEVICE_HANDLER( z80dart_rxca_w );
+WRITE_LINE_DEVICE_HANDLER( z80dart_txca_w );
+WRITE_LINE_DEVICE_HANDLER( z80dart_rxcb_w );
+WRITE_LINE_DEVICE_HANDLER( z80dart_txcb_w );
+WRITE_LINE_DEVICE_HANDLER( z80dart_rxtxcb_w );
+
+// ring indicator
+WRITE_LINE_DEVICE_HANDLER( z80dart_ria_w );
+WRITE_LINE_DEVICE_HANDLER( z80dart_rib_w );
+
+// data carrier detected
+WRITE_LINE_DEVICE_HANDLER( z80dart_dcda_w );
+WRITE_LINE_DEVICE_HANDLER( z80dart_dcdb_w );
+
+// clear to send
+WRITE_LINE_DEVICE_HANDLER( z80dart_ctsa_w );
+WRITE_LINE_DEVICE_HANDLER( z80dart_ctsb_w );
+
+// sync
+WRITE_LINE_DEVICE_HANDLER( z80dart_synca_w );
+WRITE_LINE_DEVICE_HANDLER( z80dart_syncb_w );
+
+#endif
diff --git a/trunk/src/emu/machine/z80dma.c b/trunk/src/emu/machine/z80dma.c
new file mode 100644
index 00000000000..de3132285fd
--- /dev/null
+++ b/trunk/src/emu/machine/z80dma.c
@@ -0,0 +1,887 @@
+/**********************************************************************
+
+ Z80 DMA interface and emulation
+
+ For datasheet http://www.zilog.com/docs/z80/ps0179.pdf
+
+ 2008/01 couriersud
+
+ - architecture copied from 8257 DMA
+ - significant changes to implementation
+ - This is only a minimum implementation to support dkong3 and mario drivers
+ - Only memory to memory is tested!
+
+ TODO:
+ - reset command (C3) is handled improperly
+ - rewrite to match documentation
+ - implement missing features
+ - implement more asserts
+ - implement a INPUT_LINE_BUSREQ for Z80. As a workaround,
+ HALT is used. This implies burst mode.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "memconv.h"
+#include "z80dma.h"
+#include "cpu/z80/z80daisy.h"
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+enum
+{
+ INT_RDY = 0,
+ INT_MATCH,
+ INT_END_OF_BLOCK,
+ INT_MATCH_END_OF_BLOCK
+};
+
+const int COMMAND_RESET = 0xc3;
+const int COMMAND_RESET_PORT_A_TIMING = 0xc7;
+const int COMMAND_RESET_PORT_B_TIMING = 0xcb;
+const int COMMAND_LOAD = 0xcf;
+const int COMMAND_CONTINUE = 0xd3;
+const int COMMAND_DISABLE_INTERRUPTS = 0xaf;
+const int COMMAND_ENABLE_INTERRUPTS = 0xab;
+const int COMMAND_RESET_AND_DISABLE_INTERRUPTS = 0xa3;
+const int COMMAND_ENABLE_AFTER_RETI = 0xb7;
+const int COMMAND_READ_STATUS_BYTE = 0xbf;
+const int COMMAND_REINITIALIZE_STATUS_BYTE = 0x8b;
+const int COMMAND_INITIATE_READ_SEQUENCE = 0xa7;
+const int COMMAND_FORCE_READY = 0xb3;
+const int COMMAND_ENABLE_DMA = 0x87;
+const int COMMAND_DISABLE_DMA = 0x83;
+const int COMMAND_READ_MASK_FOLLOWS = 0xbb;
+
+const int TM_TRANSFER = 0x01;
+const int TM_SEARCH = 0x02;
+const int TM_SEARCH_TRANSFER = 0x03;
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+#define LOG 0
+#define DMA_LOG 0
+
+#define REGNUM(_m, _s) (((_m)<<3) + (_s))
+#define GET_REGNUM(_r) (&(_r) - &(WR0))
+#define REG(_m, _s) m_regs[REGNUM(_m,_s)]
+#define WR0 REG(0, 0)
+#define WR1 REG(1, 0)
+#define WR2 REG(2, 0)
+#define WR3 REG(3, 0)
+#define WR4 REG(4, 0)
+#define WR5 REG(5, 0)
+#define WR6 REG(6, 0)
+
+#define PORTA_ADDRESS_L REG(0,1)
+#define PORTA_ADDRESS_H REG(0,2)
+
+#define BLOCKLEN_L REG(0,3)
+#define BLOCKLEN_H REG(0,4)
+
+#define PORTA_TIMING REG(1,1)
+#define PORTB_TIMING REG(2,1)
+
+#define MASK_BYTE REG(3,1)
+#define MATCH_BYTE REG(3,2)
+
+#define PORTB_ADDRESS_L REG(4,1)
+#define PORTB_ADDRESS_H REG(4,2)
+#define INTERRUPT_CTRL REG(4,3)
+#define INTERRUPT_VECTOR REG(4,4)
+#define PULSE_CTRL REG(4,5)
+
+#define READ_MASK REG(6,1)
+
+#define PORTA_ADDRESS ((PORTA_ADDRESS_H<<8) | PORTA_ADDRESS_L)
+#define PORTB_ADDRESS ((PORTB_ADDRESS_H<<8) | PORTB_ADDRESS_L)
+#define BLOCKLEN ((BLOCKLEN_H<<8) | BLOCKLEN_L)
+
+#define PORTA_INC (WR1 & 0x10)
+#define PORTB_INC (WR2 & 0x10)
+#define PORTA_FIXED (((WR1 >> 4) & 0x02) == 0x02)
+#define PORTB_FIXED (((WR2 >> 4) & 0x02) == 0x02)
+#define PORTA_MEMORY (((WR1 >> 3) & 0x01) == 0x00)
+#define PORTB_MEMORY (((WR2 >> 3) & 0x01) == 0x00)
+
+#define PORTA_CYCLE_LEN (4-(PORTA_TIMING & 0x03))
+#define PORTB_CYCLE_LEN (4-(PORTB_TIMING & 0x03))
+
+#define PORTA_IS_SOURCE ((WR0 >> 2) & 0x01)
+#define PORTB_IS_SOURCE (!PORTA_IS_SOURCE)
+#define TRANSFER_MODE (WR0 & 0x03)
+
+#define MATCH_F_SET (m_status &= ~0x10)
+#define MATCH_F_CLEAR (m_status |= 0x10)
+#define EOB_F_SET (m_status &= ~0x20)
+#define EOB_F_CLEAR (m_status |= 0x20)
+
+#define READY_ACTIVE_HIGH ((WR5>>3) & 0x01)
+
+#define INTERRUPT_ENABLE (WR3 & 0x20)
+#define INT_ON_MATCH (INTERRUPT_CTRL & 0x01)
+#define INT_ON_END_OF_BLOCK (INTERRUPT_CTRL & 0x02)
+#define INT_ON_READY (INTERRUPT_CTRL & 0x40)
+#define STATUS_AFFECTS_VECTOR (INTERRUPT_CTRL & 0x20)
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type Z80DMA = &device_creator<z80dma_device>;
+
+//-------------------------------------------------
+// z80dma_device - constructor
+//-------------------------------------------------
+
+z80dma_device::z80dma_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, Z80DMA, "Z8410", tag, owner, clock),
+ device_z80daisy_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void z80dma_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const z80dma_interface *intf = reinterpret_cast<const z80dma_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<z80dma_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_out_busreq_cb, 0, sizeof(m_out_busreq_cb));
+ memset(&m_out_int_cb, 0, sizeof(m_out_int_cb));
+ memset(&m_out_bao_cb, 0, sizeof(m_out_bao_cb));
+ memset(&m_in_mreq_cb, 0, sizeof(m_in_mreq_cb));
+ memset(&m_out_mreq_cb, 0, sizeof(m_out_mreq_cb));
+ memset(&m_in_iorq_cb, 0, sizeof(m_in_iorq_cb));
+ memset(&m_out_iorq_cb, 0, sizeof(m_out_iorq_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void z80dma_device::device_start()
+{
+ // resolve callbacks
+ m_out_busreq_func.resolve(m_out_busreq_cb, *this);
+ m_out_int_func.resolve(m_out_int_cb, *this);
+ m_out_bao_func.resolve(m_out_bao_cb, *this);
+ m_in_mreq_func.resolve(m_in_mreq_cb, *this);
+ m_out_mreq_func.resolve(m_out_mreq_cb, *this);
+ m_in_iorq_func.resolve(m_in_iorq_cb, *this);
+ m_out_iorq_func.resolve(m_out_iorq_cb, *this);
+
+ // allocate timer
+ m_timer = machine().scheduler().timer_alloc(FUNC(static_timerproc), (void *)this);
+
+ // register for state saving
+ save_item(NAME(m_regs));
+ save_item(NAME(m_regs_follow));
+ save_item(NAME(m_num_follow));
+ save_item(NAME(m_cur_follow));
+ save_item(NAME(m_status));
+ save_item(NAME(m_dma_enabled));
+ save_item(NAME(m_vector));
+ save_item(NAME(m_ip));
+ save_item(NAME(m_ius));
+ save_item(NAME(m_addressA));
+ save_item(NAME(m_addressB));
+ save_item(NAME(m_count));
+ save_item(NAME(m_rdy));
+ save_item(NAME(m_force_ready));
+ save_item(NAME(m_is_read));
+ save_item(NAME(m_cur_cycle));
+ save_item(NAME(m_latch));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void z80dma_device::device_reset()
+{
+ m_status = 0;
+ m_rdy = 0;
+ m_force_ready = 0;
+ m_num_follow = 0;
+ m_dma_enabled = 0;
+ m_read_num_follow = m_read_cur_follow = 0;
+ m_reset_pointer = 0;
+
+ // disable interrupts
+ WR3 &= ~0x20;
+ m_ip = 0;
+ m_ius = 0;
+ m_vector = 0;
+
+ update_status();
+}
+
+
+
+//**************************************************************************
+// DAISY CHAIN INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// z80daisy_irq_state - return the overall IRQ
+// state for this device
+//-------------------------------------------------
+
+int z80dma_device::z80daisy_irq_state()
+{
+ int state = 0;
+
+ if (m_ip)
+ {
+ // interrupt pending
+ state = Z80_DAISY_INT;
+ }
+ else if (m_ius)
+ {
+ // interrupt under service
+ state = Z80_DAISY_IEO;
+ }
+
+ if (LOG) logerror("Z80DMA '%s' Interrupt State: %u\n", tag(), state);
+
+ return state;
+}
+
+
+//-------------------------------------------------
+// z80daisy_irq_ack - acknowledge an IRQ and
+// return the appropriate vector
+//-------------------------------------------------
+
+int z80dma_device::z80daisy_irq_ack()
+{
+ if (m_ip)
+ {
+ if (LOG) logerror("Z80DMA '%s' Interrupt Acknowledge\n", tag());
+
+ // clear interrupt pending flag
+ m_ip = 0;
+ interrupt_check();
+
+ // set interrupt under service flag
+ m_ius = 1;
+
+ // disable DMA
+ m_dma_enabled = 0;
+
+ return m_vector;
+ }
+
+ logerror("z80dma_irq_ack: failed to find an interrupt to ack!\n");
+
+ return 0;
+}
+
+
+//-------------------------------------------------
+// z80daisy_irq_reti - clear the interrupt
+// pending state to allow other interrupts through
+//-------------------------------------------------
+
+void z80dma_device::z80daisy_irq_reti()
+{
+ if (m_ius)
+ {
+ if (LOG) logerror("Z80DMA '%s' Return from Interrupt\n", tag());
+
+ // clear interrupt under service flag
+ m_ius = 0;
+ interrupt_check();
+
+ return;
+ }
+
+ logerror("z80dma_irq_reti: failed to find an interrupt to clear IEO on!\n");
+}
+
+
+
+//**************************************************************************
+// INTERNAL STATE MANAGEMENT
+//**************************************************************************
+
+//-------------------------------------------------
+// is_ready - ready for DMA transfer?
+//-------------------------------------------------
+
+int z80dma_device::is_ready()
+{
+ return (m_force_ready) || (m_rdy == READY_ACTIVE_HIGH);
+}
+
+
+//-------------------------------------------------
+// interrupt_check - update IRQ line state
+//-------------------------------------------------
+
+void z80dma_device::interrupt_check()
+{
+ m_out_int_func(m_ip ? ASSERT_LINE : CLEAR_LINE);
+}
+
+
+//-------------------------------------------------
+// trigger_interrupt - trigger DMA interrupt
+//-------------------------------------------------
+
+void z80dma_device::trigger_interrupt(int level)
+{
+ if (!m_ius && INTERRUPT_ENABLE)
+ {
+ // set interrupt pending flag
+ m_ip = 1;
+
+ // set interrupt vector
+ if (STATUS_AFFECTS_VECTOR)
+ {
+ m_vector = (INTERRUPT_VECTOR & 0xf9) | (level << 1);
+ }
+ else
+ {
+ m_vector = INTERRUPT_VECTOR;
+ }
+
+ m_status &= ~0x08;
+
+ if (LOG) logerror("Z80DMA '%s' Interrupt Pending\n", tag());
+
+ interrupt_check();
+ }
+}
+
+
+//-------------------------------------------------
+// do_read - perform DMA read
+//-------------------------------------------------
+
+void z80dma_device::do_read()
+{
+ UINT8 mode;
+
+ mode = TRANSFER_MODE;
+ switch(mode) {
+ case TM_TRANSFER:
+ case TM_SEARCH:
+ if (PORTA_IS_SOURCE)
+ {
+ if (PORTA_MEMORY)
+ m_latch = m_in_mreq_func(m_addressA);
+ else
+ m_latch = m_in_iorq_func(m_addressA);
+
+ if (DMA_LOG) logerror("Z80DMA '%s' A src: %04x %s -> data: %02x\n", tag(), m_addressA, PORTA_MEMORY ? "mem" : "i/o", m_latch);
+ }
+ else
+ {
+ if (PORTB_MEMORY)
+ m_latch = m_in_mreq_func(m_addressB);
+ else
+ m_latch = m_in_iorq_func(m_addressB);
+
+ if (DMA_LOG) logerror("Z80DMA '%s' B src: %04x %s -> data: %02x\n", tag(), m_addressB, PORTB_MEMORY ? "mem" : "i/o", m_latch);
+ }
+ break;
+ case TM_SEARCH_TRANSFER:
+ fatalerror("z80dma_do_operation: unhandled search & transfer mode !\n");
+ break;
+ default:
+ logerror("z80dma_do_operation: invalid mode %d!\n", mode);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// do_write - perform DMA write
+//-------------------------------------------------
+
+int z80dma_device::do_write()
+{
+ int done = 0;
+ UINT8 mode;
+
+ mode = TRANSFER_MODE;
+ if (m_count == 0x0000)
+ {
+ //FIXME: Any signal here
+ }
+ switch(mode) {
+ case TM_TRANSFER:
+ if (PORTA_IS_SOURCE)
+ {
+ if (PORTB_MEMORY)
+ m_out_mreq_func(m_addressB, m_latch);
+ else
+ m_out_iorq_func(m_addressB, m_latch);
+
+ if (DMA_LOG) logerror("Z80DMA '%s' B dst: %04x %s\n", tag(), m_addressB, PORTB_MEMORY ? "mem" : "i/o");
+ }
+ else
+ {
+ if (PORTA_MEMORY)
+ m_out_mreq_func(m_addressA, m_latch);
+ else
+ m_out_iorq_func(m_addressA, m_latch);
+
+ if (DMA_LOG) logerror("Z80DMA '%s' A dst: %04x %s\n", tag(), m_addressA, PORTA_MEMORY ? "mem" : "i/o");
+ }
+
+ break;
+
+ case TM_SEARCH:
+ {
+ UINT8 load_byte,match_byte;
+ load_byte = m_latch | MASK_BYTE;
+ match_byte = MATCH_BYTE | MASK_BYTE;
+ //if (LOG) logerror("%02x %02x\n",load_byte,match_byte));
+ if (load_byte == match_byte)
+ {
+ if (INT_ON_MATCH)
+ {
+ trigger_interrupt(INT_MATCH);
+ }
+ }
+
+ }
+ break;
+
+ case TM_SEARCH_TRANSFER:
+ fatalerror("z80dma_do_operation: unhandled search & transfer mode !\n");
+ break;
+
+ default:
+ logerror("z80dma_do_operation: invalid mode %d!\n", mode);
+ break;
+ }
+
+ m_addressA += PORTA_FIXED ? 0 : PORTA_INC ? 1 : -1;
+ m_addressB += PORTB_FIXED ? 0 : PORTB_INC ? 1 : -1;
+
+ m_count--;
+ done = (m_count == 0xFFFF); //correct?
+
+ if (done)
+ {
+ //FIXME: interrupt ?
+ }
+ return done;
+}
+
+
+//-------------------------------------------------
+// timerproc
+//-------------------------------------------------
+
+void z80dma_device::timerproc()
+{
+ int done;
+
+ if (--m_cur_cycle)
+ {
+ return;
+ }
+
+ if (m_is_read && !is_ready()) return;
+
+ if (m_is_read)
+ {
+ /* TODO: there's a nasty recursion bug with Alpha for Sharp X1 Turbo on the transfers with this function! */
+ do_read();
+ done = 0;
+ m_is_read = false;
+ m_cur_cycle = (PORTA_IS_SOURCE ? PORTA_CYCLE_LEN : PORTB_CYCLE_LEN);
+ }
+ else
+ {
+ done = do_write();
+ m_is_read = true;
+ m_cur_cycle = (PORTB_IS_SOURCE ? PORTA_CYCLE_LEN : PORTB_CYCLE_LEN);
+ }
+
+ if (done)
+ {
+ m_dma_enabled = 0; //FIXME: Correct?
+ m_status = 0x09;
+
+ m_status |= !is_ready() << 1; // ready line status
+
+ if(TRANSFER_MODE == TM_TRANSFER) m_status |= 0x10; // no match found
+
+ update_status();
+ if (LOG) logerror("Z80DMA '%s' End of Block\n", tag());
+
+ if (INT_ON_END_OF_BLOCK)
+ {
+ trigger_interrupt(INT_END_OF_BLOCK);
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// update_status - update DMA status
+//-------------------------------------------------
+
+void z80dma_device::update_status()
+{
+ UINT16 pending_transfer;
+ attotime next;
+
+ // no transfer is active right now; is there a transfer pending right now?
+ pending_transfer = is_ready() & m_dma_enabled;
+
+ if (pending_transfer)
+ {
+ m_is_read = true;
+ m_cur_cycle = (PORTA_IS_SOURCE ? PORTA_CYCLE_LEN : PORTB_CYCLE_LEN);
+ next = attotime::from_hz(clock());
+ m_timer->adjust(
+ attotime::zero,
+ 0,
+ // 1 byte transferred in 4 clock cycles
+ next);
+ }
+ else
+ {
+ if (m_is_read)
+ {
+ // no transfers active right now
+ m_timer->reset();
+ }
+ }
+
+ // set the busreq line
+ m_out_busreq_func(pending_transfer ? ASSERT_LINE : CLEAR_LINE);
+}
+
+
+
+//**************************************************************************
+// READ/WRITE INTERFACES
+//**************************************************************************
+
+//-------------------------------------------------
+// read - register read
+//-------------------------------------------------
+
+UINT8 z80dma_device::read()
+{
+ UINT8 res;
+
+ if(m_read_num_follow == 0) /* TODO: should return the status, but let me know WHAT uses this first */
+ fatalerror("Z80DMA '%s' Read without anything setted into stack", tag());
+
+ res = m_read_regs_follow[m_read_cur_follow];
+ m_read_cur_follow++;
+
+ if(m_read_cur_follow >= m_read_num_follow)
+ m_read_cur_follow = 0;
+
+ if (LOG) logerror("Z80DMA '%s' Read %02x\n", tag(), res);
+
+ return res;
+}
+
+
+//-------------------------------------------------
+// write - register write
+//-------------------------------------------------
+
+void z80dma_device::write(UINT8 data)
+{
+ if (LOG) logerror("Z80DMA '%s' Write %02x\n", tag(), data);
+
+ if (m_num_follow == 0)
+ {
+ m_reset_pointer = 0;
+
+ if ((data & 0x87) == 0) // WR2
+ {
+ WR2 = data;
+ if (data & 0x40)
+ m_regs_follow[m_num_follow++] = GET_REGNUM(PORTB_TIMING);
+ }
+ else if ((data & 0x87) == 0x04) // WR1
+ {
+ WR1 = data;
+ if (data & 0x40)
+ m_regs_follow[m_num_follow++] = GET_REGNUM(PORTA_TIMING);
+ }
+ else if ((data & 0x80) == 0) // WR0
+ {
+ WR0 = data;
+ if (data & 0x08)
+ m_regs_follow[m_num_follow++] = GET_REGNUM(PORTA_ADDRESS_L);
+ if (data & 0x10)
+ m_regs_follow[m_num_follow++] = GET_REGNUM(PORTA_ADDRESS_H);
+ if (data & 0x20)
+ m_regs_follow[m_num_follow++] = GET_REGNUM(BLOCKLEN_L);
+ if (data & 0x40)
+ m_regs_follow[m_num_follow++] = GET_REGNUM(BLOCKLEN_H);
+ }
+ else if ((data & 0x83) == 0x80) // WR3
+ {
+ WR3 = data;
+ if (data & 0x08)
+ m_regs_follow[m_num_follow++] = GET_REGNUM(MASK_BYTE);
+ if (data & 0x10)
+ m_regs_follow[m_num_follow++] = GET_REGNUM(MATCH_BYTE);
+ }
+ else if ((data & 0x83) == 0x81) // WR4
+ {
+ WR4 = data;
+ if (data & 0x04)
+ m_regs_follow[m_num_follow++] = GET_REGNUM(PORTB_ADDRESS_L);
+ if (data & 0x08)
+ m_regs_follow[m_num_follow++] = GET_REGNUM(PORTB_ADDRESS_H);
+ if (data & 0x10)
+ m_regs_follow[m_num_follow++] = GET_REGNUM(INTERRUPT_CTRL);
+ }
+ else if ((data & 0xC7) == 0x82) // WR5
+ {
+ WR5 = data;
+ }
+ else if ((data & 0x83) == 0x83) // WR6
+ {
+ m_dma_enabled = 0;
+
+ WR6 = data;
+
+ switch (data)
+ {
+ case COMMAND_ENABLE_AFTER_RETI:
+ fatalerror("Z80DMA '%s' Unimplemented WR6 command %02x", tag(), data);
+ break;
+ case COMMAND_READ_STATUS_BYTE:
+ if (LOG) logerror("Z80DMA '%s' CMD Read status Byte\n", tag());
+ READ_MASK = 1;
+ m_read_regs_follow[m_read_num_follow++] = m_status;
+ break;
+ case COMMAND_RESET_AND_DISABLE_INTERRUPTS:
+ WR3 &= ~0x20;
+ m_ip = 0;
+ m_ius = 0;
+ m_force_ready = 0;
+ m_status |= 0x08;
+ break;
+ case COMMAND_INITIATE_READ_SEQUENCE:
+ if (LOG) logerror("Z80DMA '%s' Initiate Read Sequence\n", tag());
+ m_read_cur_follow = m_read_num_follow = 0;
+ if(READ_MASK & 0x01) { m_read_regs_follow[m_read_num_follow++] = m_status; }
+ if(READ_MASK & 0x02) { m_read_regs_follow[m_read_num_follow++] = m_count & 0xff; } //byte counter (low)
+ if(READ_MASK & 0x04) { m_read_regs_follow[m_read_num_follow++] = m_count >> 8; } //byte counter (high)
+ if(READ_MASK & 0x08) { m_read_regs_follow[m_read_num_follow++] = m_addressA & 0xff; } //port A address (low)
+ if(READ_MASK & 0x10) { m_read_regs_follow[m_read_num_follow++] = m_addressA >> 8; } //port A address (high)
+ if(READ_MASK & 0x20) { m_read_regs_follow[m_read_num_follow++] = m_addressB & 0xff; } //port B address (low)
+ if(READ_MASK & 0x40) { m_read_regs_follow[m_read_num_follow++] = m_addressB >> 8; } //port B address (high)
+ break;
+ case COMMAND_RESET:
+ if (LOG) logerror("Z80DMA '%s' Reset\n", tag());
+ m_dma_enabled = 0;
+ m_force_ready = 0;
+ m_ip = 0;
+ m_ius = 0;
+ interrupt_check();
+ // Needs six reset commands to reset the DMA
+ {
+ UINT8 WRi;
+
+ for(WRi=0;WRi<7;WRi++)
+ REG(WRi,m_reset_pointer) = 0;
+
+ m_reset_pointer++;
+ if(m_reset_pointer >= 6) { m_reset_pointer = 0; }
+ }
+ m_status = 0x38;
+ break;
+ case COMMAND_LOAD:
+ m_force_ready = 0;
+ m_addressA = PORTA_ADDRESS;
+ m_addressB = PORTB_ADDRESS;
+ m_count = BLOCKLEN;
+ m_status |= 0x30;
+
+ if (LOG) logerror("Z80DMA '%s' Load A: %x B: %x N: %x\n", tag(), m_addressA, m_addressB, m_count);
+ break;
+ case COMMAND_DISABLE_DMA:
+ if (LOG) logerror("Z80DMA '%s' Disable DMA\n", tag());
+ m_dma_enabled = 0;
+ break;
+ case COMMAND_ENABLE_DMA:
+ if (LOG) logerror("Z80DMA '%s' Enable DMA\n", tag());
+ m_dma_enabled = 1;
+ update_status();
+ break;
+ case COMMAND_READ_MASK_FOLLOWS:
+ if (LOG) logerror("Z80DMA '%s' Set Read Mask\n", tag());
+ m_regs_follow[m_num_follow++] = GET_REGNUM(READ_MASK);
+ break;
+ case COMMAND_CONTINUE:
+ if (LOG) logerror("Z80DMA '%s' Continue\n", tag());
+ m_count = BLOCKLEN;
+ m_dma_enabled = 1;
+ //"match not found" & "end of block" status flags zeroed here
+ m_status |= 0x30;
+ break;
+ case COMMAND_RESET_PORT_A_TIMING:
+ if (LOG) logerror("Z80DMA '%s' Reset Port A Timing\n", tag());
+ PORTA_TIMING = 0;
+ break;
+ case COMMAND_RESET_PORT_B_TIMING:
+ if (LOG) logerror("Z80DMA '%s' Reset Port B Timing\n", tag());
+ PORTB_TIMING = 0;
+ break;
+ case COMMAND_FORCE_READY:
+ if (LOG) logerror("Z80DMA '%s' Force Ready\n", tag());
+ m_force_ready = 1;
+ update_status();
+ break;
+ case COMMAND_ENABLE_INTERRUPTS:
+ if (LOG) logerror("Z80DMA '%s' Enable IRQ\n", tag());
+ WR3 |= 0x20;
+ break;
+ case COMMAND_DISABLE_INTERRUPTS:
+ if (LOG) logerror("Z80DMA '%s' Disable IRQ\n", tag());
+ WR3 &= ~0x20;
+ break;
+ case COMMAND_REINITIALIZE_STATUS_BYTE:
+ if (LOG) logerror("Z80DMA '%s' Reinitialize status byte\n", tag());
+ m_status |= 0x30;
+ m_ip = 0;
+ break;
+ case 0xFB:
+ if (LOG) logerror("Z80DMA '%s' undocumented command triggered 0x%02X!\n", tag(), data);
+ break;
+ default:
+ fatalerror("Z80DMA '%s' Unknown WR6 command %02x", tag(), data);
+ }
+ }
+ else if(data == 0x8e) //newtype on Sharp X1, unknown purpose
+ printf("Z80DMA '%s' Unknown base register %02x\n", tag(), data);
+ else
+ fatalerror("Z80DMA '%s' Unknown base register %02x", tag(), data);
+ m_cur_follow = 0;
+ }
+ else
+ {
+ int nreg = m_regs_follow[m_cur_follow];
+ m_regs[nreg] = data;
+ m_cur_follow++;
+ if (m_cur_follow>=m_num_follow)
+ m_num_follow = 0;
+ if (nreg == REGNUM(4,3))
+ {
+ m_num_follow=0;
+ if (data & 0x08)
+ m_regs_follow[m_num_follow++] = GET_REGNUM(PULSE_CTRL);
+ if (data & 0x10)
+ m_regs_follow[m_num_follow++] = GET_REGNUM(INTERRUPT_VECTOR);
+ m_cur_follow = 0;
+ }
+ else if(m_regs_follow[m_num_follow] == GET_REGNUM(READ_MASK))
+ {
+ m_read_cur_follow = m_read_num_follow = 0;
+
+ if(READ_MASK & 0x01) { m_read_regs_follow[m_read_num_follow++] = m_status; }
+ if(READ_MASK & 0x02) { m_read_regs_follow[m_read_num_follow++] = m_count & 0xff; } //byte counter (low)
+ if(READ_MASK & 0x04) { m_read_regs_follow[m_read_num_follow++] = m_count >> 8; } //byte counter (high)
+ if(READ_MASK & 0x08) { m_read_regs_follow[m_read_num_follow++] = m_addressA & 0xff; } //port A address (low)
+ if(READ_MASK & 0x10) { m_read_regs_follow[m_read_num_follow++] = m_addressA >> 8; } //port A address (high)
+ if(READ_MASK & 0x20) { m_read_regs_follow[m_read_num_follow++] = m_addressB & 0xff; } //port B address (low)
+ if(READ_MASK & 0x40) { m_read_regs_follow[m_read_num_follow++] = m_addressB >> 8; } //port B address (high)
+ }
+
+ m_reset_pointer++;
+ if(m_reset_pointer >= 6) { m_reset_pointer = 0; }
+ }
+}
+
+
+//-------------------------------------------------
+// rdy_write_callback - deferred RDY signal write
+//-------------------------------------------------
+
+void z80dma_device::rdy_write_callback(int state)
+{
+ // normalize state
+ m_rdy = state;
+ m_status = (m_status & 0xFD) | (!is_ready() << 1);
+
+ update_status();
+
+ if (is_ready() && INT_ON_READY)
+ {
+ trigger_interrupt(INT_RDY);
+ }
+}
+
+
+//-------------------------------------------------
+// rdy_w - ready input
+//-------------------------------------------------
+
+void z80dma_device::rdy_w(int state)
+{
+ if (LOG) logerror("Z80DMA '%s' RDY: %d Active High: %d\n", tag(), state, READY_ACTIVE_HIGH);
+ machine().scheduler().synchronize(FUNC(static_rdy_write_callback), state, (void *)this);
+}
+
+
+//-------------------------------------------------
+// wait_w - wait input
+//-------------------------------------------------
+
+void z80dma_device::wait_w(int state)
+{
+}
+
+
+//-------------------------------------------------
+// bai_w - bus acknowledge input
+//-------------------------------------------------
+
+void z80dma_device::bai_w(int state)
+{
+}
+
+
+
+//**************************************************************************
+// GLOBAL STUBS
+//**************************************************************************
+
+READ8_DEVICE_HANDLER( z80dma_r ) { return downcast<z80dma_device *>(device)->read(); }
+WRITE8_DEVICE_HANDLER( z80dma_w ) { downcast<z80dma_device *>(device)->write(data); }
+
+WRITE_LINE_DEVICE_HANDLER( z80dma_rdy_w ) { downcast<z80dma_device *>(device)->rdy_w(state); }
+WRITE_LINE_DEVICE_HANDLER( z80dma_wait_w ) { downcast<z80dma_device *>(device)->wait_w(state); }
+WRITE_LINE_DEVICE_HANDLER( z80dma_bai_w ) { downcast<z80dma_device *>(device)->bai_w(state); }
diff --git a/trunk/src/emu/machine/z80dma.h b/trunk/src/emu/machine/z80dma.h
new file mode 100644
index 00000000000..252c25a137b
--- /dev/null
+++ b/trunk/src/emu/machine/z80dma.h
@@ -0,0 +1,181 @@
+/***************************************************************************
+
+ Zilog Z80 DMA Direct Memory Access Controller emulation
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+****************************************************************************
+ _____ _____
+ A5 1 |* \_/ | 40 A6
+ A4 2 | | 39 A7
+ A3 3 | | 38 IEI
+ A2 4 | | 37 _INT/_PULSE
+ A1 5 | | 36 IEO
+ A0 6 | | 35 D0
+ CLK 7 | | 34 D1
+ _WR 8 | | 33 D2
+ _RD 9 | | 32 D3
+ _IORQ 10 | Z8410 | 31 D4
+ +5V 11 | | 30 GND
+ _MREQ 12 | | 29 D5
+ _BAO 13 | | 28 D6
+ _BAI 14 | | 27 D7
+ _BUSREQ 15 | | 26 _M1
+ _CE/_WAIT 16 | | 25 RDY
+ A15 17 | | 24 A8
+ A14 18 | | 23 A9
+ A13 19 | | 22 A10
+ A12 20 |_____________| 21 A11
+
+***************************************************************************/
+
+#ifndef __Z80DMA__
+#define __Z80DMA__
+
+#include "cpu/z80/z80daisy.h"
+
+
+//**************************************************************************
+// DEVICE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_Z80DMA_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD(_tag, Z80DMA, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define Z80DMA_INTERFACE(_name) \
+ const z80dma_interface (_name) =
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> z80dma_interface
+
+struct z80dma_interface
+{
+ devcb_write_line m_out_busreq_cb;
+ devcb_write_line m_out_int_cb;
+ devcb_write_line m_out_bao_cb;
+
+ // memory accessors
+ devcb_read8 m_in_mreq_cb;
+ devcb_write8 m_out_mreq_cb;
+
+ // I/O accessors
+ devcb_read8 m_in_iorq_cb;
+ devcb_write8 m_out_iorq_cb;
+};
+
+
+
+// ======================> z80dma_device
+
+class z80dma_device : public device_t,
+ public device_z80daisy_interface,
+ public z80dma_interface
+{
+public:
+ // construction/destruction
+ z80dma_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ UINT8 read();
+ void write(UINT8 data);
+
+ void rdy_w(int state);
+ void wait_w(int state);
+ void bai_w(int state);
+
+private:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_z80daisy_interface overrides
+ virtual int z80daisy_irq_state();
+ virtual int z80daisy_irq_ack();
+ virtual void z80daisy_irq_reti();
+
+ // internal helpers
+ int is_ready();
+ void interrupt_check();
+ void trigger_interrupt(int level);
+ void do_read();
+ int do_write();
+
+ static TIMER_CALLBACK( static_timerproc ) { reinterpret_cast<z80dma_device *>(ptr)->timerproc(); }
+ void timerproc();
+
+ void update_status();
+
+ static TIMER_CALLBACK( static_rdy_write_callback ) { reinterpret_cast<z80dma_device *>(ptr)->rdy_write_callback(param); }
+ void rdy_write_callback(int state);
+
+ // internal state
+ devcb_resolved_write_line m_out_busreq_func;
+ devcb_resolved_write_line m_out_int_func;
+ devcb_resolved_write_line m_out_bao_func;
+ devcb_resolved_read8 m_in_mreq_func;
+ devcb_resolved_write8 m_out_mreq_func;
+ devcb_resolved_read8 m_in_iorq_func;
+ devcb_resolved_write8 m_out_iorq_func;
+
+ emu_timer *m_timer;
+
+ UINT16 m_regs[(6<<3)+1+1];
+ UINT8 m_num_follow;
+ UINT8 m_cur_follow;
+ UINT8 m_regs_follow[4];
+ UINT8 m_read_num_follow;
+ UINT8 m_read_cur_follow;
+ UINT8 m_read_regs_follow[7];
+ UINT8 m_status;
+ UINT8 m_dma_enabled;
+
+ UINT16 m_addressA;
+ UINT16 m_addressB;
+ UINT16 m_count;
+
+ int m_rdy;
+ int m_force_ready;
+ UINT8 m_reset_pointer;
+
+ bool m_is_read;
+ UINT8 m_cur_cycle;
+ UINT8 m_latch;
+
+ // interrupts
+ int m_ip; // interrupt pending
+ int m_ius; // interrupt under service
+ UINT8 m_vector; // interrupt vector
+};
+
+
+// device type definition
+extern const device_type Z80DMA;
+
+
+
+//**************************************************************************
+// FUNCTION PROTOTYPES
+//**************************************************************************
+
+// register access
+READ8_DEVICE_HANDLER( z80dma_r );
+WRITE8_DEVICE_HANDLER( z80dma_w );
+
+// ready
+WRITE_LINE_DEVICE_HANDLER( z80dma_rdy_w );
+
+// wait
+WRITE_LINE_DEVICE_HANDLER( z80dma_wait_w );
+
+// bus acknowledge in
+WRITE_LINE_DEVICE_HANDLER( z80dma_bai_w );
+
+#endif
diff --git a/trunk/src/emu/machine/z80pio.c b/trunk/src/emu/machine/z80pio.c
new file mode 100644
index 00000000000..51e53b06219
--- /dev/null
+++ b/trunk/src/emu/machine/z80pio.c
@@ -0,0 +1,844 @@
+/***************************************************************************
+
+ Zilog Z80 Parallel Input/Output Controller implementation
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "z80pio.h"
+#include "cpu/z80/z80daisy.h"
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+enum
+{
+ MODE_OUTPUT = 0,
+ MODE_INPUT,
+ MODE_BIDIRECTIONAL,
+ MODE_BIT_CONTROL
+};
+
+enum
+{
+ ANY = 0,
+ IOR,
+ MASK
+};
+
+const int ICW_ENABLE_INT = 0x80;
+const int ICW_AND_OR = 0x40;
+const int ICW_AND = 0x40;
+const int ICW_OR = 0x00;
+const int ICW_HIGH_LOW = 0x20;
+const int ICW_HIGH = 0x20;
+const int ICW_LOW = 0x00;
+const int ICW_MASK_FOLLOWS = 0x10;
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type Z80PIO = &device_creator<z80pio_device>;
+
+//-------------------------------------------------
+// z80pio_device - constructor
+//-------------------------------------------------
+
+z80pio_device::z80pio_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, Z80PIO, "Z8420", tag, owner, clock),
+ device_z80daisy_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void z80pio_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const z80pio_interface *intf = reinterpret_cast<const z80pio_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<z80pio_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_out_int_cb, 0, sizeof(m_out_int_cb));
+ memset(&m_in_pa_cb, 0, sizeof(m_in_pa_cb));
+ memset(&m_out_pa_cb, 0, sizeof(m_out_pa_cb));
+ memset(&m_out_ardy_cb, 0, sizeof(m_out_ardy_cb));
+ memset(&m_in_pb_cb, 0, sizeof(m_in_pb_cb));
+ memset(&m_out_pb_cb, 0, sizeof(m_out_pb_cb));
+ memset(&m_out_brdy_cb, 0, sizeof(m_out_brdy_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void z80pio_device::device_start()
+{
+ m_port[PORT_A].start(this, PORT_A, m_in_pa_cb, m_out_pa_cb, m_out_ardy_cb);
+ m_port[PORT_B].start(this, PORT_B, m_in_pb_cb, m_out_pb_cb, m_out_brdy_cb);
+
+ // resolve callbacks
+ m_out_int_func.resolve(m_out_int_cb, *this);
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void z80pio_device::device_reset()
+{
+ // loop over ports
+ for (int index = PORT_A; index < PORT_COUNT; index++)
+ m_port[index].reset();
+}
+
+
+
+//**************************************************************************
+// DAISY CHAIN INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// z80daisy_irq_state - return the overall IRQ
+// state for this device
+//-------------------------------------------------
+
+int z80pio_device::z80daisy_irq_state()
+{
+ int state = 0;
+
+ for (int index = PORT_A; index < PORT_COUNT; index++)
+ {
+ pio_port &port = m_port[index];
+
+ if (port.m_ius)
+ {
+ // interrupt under service
+ return Z80_DAISY_IEO;
+ }
+ else if (port.m_ie && port.m_ip)
+ {
+ // interrupt pending
+ state = Z80_DAISY_INT;
+ }
+ }
+
+ return state;
+}
+
+
+//-------------------------------------------------
+// z80daisy_irq_ack - acknowledge an IRQ and
+// return the appropriate vector
+//-------------------------------------------------
+
+int z80pio_device::z80daisy_irq_ack()
+{
+ for (int index = PORT_A; index < PORT_COUNT; index++)
+ {
+ pio_port &port = m_port[index];
+
+ if (port.m_ip)
+ {
+ if (LOG) logerror("Z80PIO '%s' Interrupt Acknowledge\n", tag());
+
+ // clear interrupt pending flag
+ port.m_ip = false;
+
+ // set interrupt under service flag
+ port.m_ius = true;
+
+ check_interrupts();
+
+ return port.m_vector;
+ }
+ }
+
+ logerror("z80pio_irq_ack: failed to find an interrupt to ack!\n");
+
+ return 0;
+}
+
+
+//-------------------------------------------------
+// z80daisy_irq_reti - clear the interrupt
+// pending state to allow other interrupts through
+//-------------------------------------------------
+
+void z80pio_device::z80daisy_irq_reti()
+{
+ for (int index = PORT_A; index < PORT_COUNT; index++)
+ {
+ pio_port &port = m_port[index];
+
+ if (port.m_ius)
+ {
+ if (LOG) logerror("Z80PIO '%s' Return from Interrupt\n", tag());
+
+ // clear interrupt under service flag
+ port.m_ius = false;
+ check_interrupts();
+
+ return;
+ }
+ }
+
+ logerror("z80pio_irq_reti: failed to find an interrupt to clear IEO on!\n");
+}
+
+
+
+//**************************************************************************
+// DEVICE-LEVEL IMPLEMENTATION
+//**************************************************************************
+
+//-------------------------------------------------
+// control_read - control register read
+//-------------------------------------------------
+
+UINT8 z80pio_device::control_read()
+{
+ return (m_port[PORT_A].m_icw & 0xc0) | (m_port[PORT_B].m_icw >> 4);
+}
+
+
+//-------------------------------------------------
+// check_interrupts - update the interrupt state
+// over all ports
+//-------------------------------------------------
+
+void z80pio_device::check_interrupts()
+{
+ int state = CLEAR_LINE;
+
+ for (int index = PORT_A; index < PORT_COUNT; index++)
+ if (m_port[index].interrupt_signalled())
+ state = ASSERT_LINE;
+
+ m_out_int_func(state);
+}
+
+
+
+//**************************************************************************
+// PORT-LEVEL IMPLEMENTATION
+//**************************************************************************
+
+//-------------------------------------------------
+// pio_port - constructor
+//-------------------------------------------------
+
+z80pio_device::pio_port::pio_port()
+ : m_device(NULL),
+ m_index(0),
+ m_mode(0),
+ m_next_control_word(0),
+ m_input(0),
+ m_output(0),
+ m_ior(0),
+ m_rdy(false),
+ m_stb(false),
+ m_ie(false),
+ m_ip(false),
+ m_ius(false),
+ m_icw(0),
+ m_vector(0),
+ m_mask(0),
+ m_match(false)
+{
+ memset(&m_in_p_func, 0, sizeof(m_in_p_func));
+ memset(&m_out_p_func, 0, sizeof(m_out_p_func));
+ memset(&m_out_rdy_func, 0, sizeof(m_out_rdy_func));
+}
+
+
+//-------------------------------------------------
+// start - set up a port during device startup
+//-------------------------------------------------
+
+void z80pio_device::pio_port::start(z80pio_device *device, int index, const devcb_read8 &infunc, const devcb_write8 &outfunc, const devcb_write_line &rdyfunc)
+{
+ m_device = device;
+ m_index = index;
+
+ // resolve callbacks
+ m_in_p_func.resolve(infunc, *m_device);
+ m_out_p_func.resolve(outfunc, *m_device);
+ m_out_rdy_func.resolve(rdyfunc, *m_device);
+
+ // register for state saving
+ m_device->save_item(NAME(m_mode), m_index);
+ m_device->save_item(NAME(m_next_control_word), m_index);
+ m_device->save_item(NAME(m_input), m_index);
+ m_device->save_item(NAME(m_output), m_index);
+ m_device->save_item(NAME(m_ior), m_index);
+ m_device->save_item(NAME(m_rdy), m_index);
+ m_device->save_item(NAME(m_stb), m_index);
+ m_device->save_item(NAME(m_ie), m_index);
+ m_device->save_item(NAME(m_ip), m_index);
+ m_device->save_item(NAME(m_ius), m_index);
+ m_device->save_item(NAME(m_icw), m_index);
+ m_device->save_item(NAME(m_vector), m_index);
+ m_device->save_item(NAME(m_mask), m_index);
+ m_device->save_item(NAME(m_match), m_index);
+}
+
+
+//-------------------------------------------------
+// reset - reset a port during device reset
+//-------------------------------------------------
+
+void z80pio_device::pio_port::reset()
+{
+ // set mode 1
+ set_mode(MODE_INPUT);
+
+ // reset interrupt enable flip-flops
+ m_icw &= ~ICW_ENABLE_INT;
+ m_ie = false;
+ m_ip = false;
+ m_ius = false;
+ m_match = false;
+
+ // reset all bits of the data I/O register
+ m_ior = 0;
+
+ // set all bits of the mask control register
+ m_mask = 0xff;
+
+ // reset output register
+ m_output = 0;
+
+ // clear ready line
+ set_rdy(false);
+}
+
+
+//-------------------------------------------------
+// interrupt_signalled - return true if an
+// interrupt is signalled
+//-------------------------------------------------
+
+bool z80pio_device::pio_port::interrupt_signalled()
+{
+ if (m_mode == MODE_BIT_CONTROL)
+ {
+ // fetch input data (ignore output lines)
+ UINT8 data = (m_input & m_ior) | (m_output & ~m_ior);
+ UINT8 mask = ~m_mask;
+ bool match = false;
+
+ data &= mask;
+
+ if ((m_icw & 0x60) == 0 && data != mask) match = true;
+ else if ((m_icw & 0x60) == 0x20 && data != 0) match = true;
+ else if ((m_icw & 0x60) == 0x40 && data == 0) match = true;
+ else if ((m_icw & 0x60) == 0x60 && data == mask) match = true;
+
+ if (!m_match && match)
+ {
+ // trigger interrupt
+ m_ip = true;
+ if (LOG) logerror("Z80PIO '%s' Port %c Interrupt Pending\n", m_device->tag(), 'A' + m_index);
+ }
+
+ m_match = match;
+ }
+
+ return (m_ie && m_ip && !m_ius);
+}
+
+
+//-------------------------------------------------
+// trigger_interrupt - trigger an interrupt from
+// this port
+//-------------------------------------------------
+
+void z80pio_device::pio_port::trigger_interrupt()
+{
+ m_ip = true;
+ if (LOG) logerror("Z80PIO '%s' Port %c Interrupt Pending\n", m_device->tag(), 'A' + m_index);
+
+ check_interrupts();
+}
+
+
+//-------------------------------------------------
+// set_rdy - set the port's RDY line
+//-------------------------------------------------
+
+void z80pio_device::pio_port::set_rdy(bool state)
+{
+ if (m_rdy == state) return;
+
+ if (LOG) logerror("Z80PIO '%s' Port %c Ready: %u\n", m_device->tag(), 'A' + m_index, state);
+
+ m_rdy = state;
+ m_out_rdy_func(state);
+}
+
+
+//-------------------------------------------------
+// set_mode - set the port's mode
+//-------------------------------------------------
+
+void z80pio_device::pio_port::set_mode(int mode)
+{
+ if (LOG) logerror("Z80PIO '%s' Port %c Mode: %u\n", m_device->tag(), 'A' + m_index, mode);
+
+ switch (mode)
+ {
+ case MODE_OUTPUT:
+ // enable data output
+ m_out_p_func(0, m_output);
+
+ // assert ready line
+ set_rdy(true);
+
+ // set mode register
+ m_mode = mode;
+ break;
+
+ case MODE_INPUT:
+ // set mode register
+ m_mode = mode;
+ break;
+
+ case MODE_BIDIRECTIONAL:
+ if (m_index == PORT_B)
+ {
+ logerror("Z80PIO '%s' Port %c Invalid Mode: %u!\n", m_device->tag(), 'A' + m_index, mode);
+ }
+ else
+ {
+ // set mode register
+ m_mode = mode;
+ }
+ break;
+
+ case MODE_BIT_CONTROL:
+ if ((m_index == PORT_A) || (m_device->m_port[PORT_A].m_mode != MODE_BIDIRECTIONAL))
+ {
+ // clear ready line
+ set_rdy(false);
+ }
+
+ // disable interrupts until IOR is written
+ m_ie = false;
+ check_interrupts();
+
+ // set logic equation to false
+ m_match = false;
+
+ // next word is I/O register
+ m_next_control_word = IOR;
+
+ // set mode register
+ m_mode = mode;
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// strobe - strobe data in/out of the port
+//-------------------------------------------------
+
+void z80pio_device::pio_port::strobe(bool state)
+{
+ if (LOG) logerror("Z80PIO '%s' Port %c Strobe: %u\n", m_device->tag(), 'A' + m_index, state);
+
+ if (m_device->m_port[PORT_A].m_mode == MODE_BIDIRECTIONAL)
+ {
+ if (m_rdy) // port ready
+ {
+ if (m_stb && !state) // falling edge
+ {
+ if (m_index == PORT_A)
+ m_out_p_func(0, m_output);
+ else
+ m_device->m_port[PORT_A].m_input = m_device->m_port[PORT_A].m_in_p_func(0);
+ }
+ else if (!m_stb && state) // rising edge
+ {
+ trigger_interrupt();
+
+ // clear ready line
+ set_rdy(false);
+ }
+ }
+ }
+ else
+ {
+ switch (m_mode)
+ {
+ case MODE_OUTPUT:
+ if (m_rdy)
+ {
+ if (!m_stb && state) // rising edge
+ {
+ trigger_interrupt();
+
+ // clear ready line
+ set_rdy(false);
+ }
+ }
+ break;
+
+ case MODE_INPUT:
+ if (!state)
+ {
+ // input port data
+ m_input = m_in_p_func(0);
+ }
+ else if (!m_stb && state) // rising edge
+ {
+ trigger_interrupt();
+
+ // clear ready line
+ set_rdy(false);
+ }
+ break;
+ }
+ }
+
+ m_stb = state;
+}
+
+
+//-------------------------------------------------
+// read - port I/O read
+//-------------------------------------------------
+
+UINT8 z80pio_device::pio_port::read()
+{
+ UINT8 data = 0xff;
+
+ switch (m_mode)
+ {
+ case MODE_OUTPUT:
+ data = m_output;
+ break;
+
+ case MODE_BIDIRECTIONAL:
+ if (m_index == PORT_A)
+ data = m_output;
+ break;
+
+ case MODE_BIT_CONTROL:
+ data = m_ior | (m_output & (m_ior ^ 0xff));
+ break;
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// write - port I/O write
+//-------------------------------------------------
+
+void z80pio_device::pio_port::write(UINT8 data)
+{
+ if (m_mode == MODE_BIT_CONTROL)
+ {
+ // latch data
+ m_input = data;
+ check_interrupts();
+ }
+}
+
+
+//-------------------------------------------------
+// control_write - control register write
+//-------------------------------------------------
+
+void z80pio_device::pio_port::control_write(UINT8 data)
+{
+ switch (m_next_control_word)
+ {
+ case ANY:
+ if (!BIT(data, 0))
+ {
+ // load interrupt vector
+ m_vector = data;
+ if (LOG) logerror("Z80PIO '%s' Port %c Interrupt Vector: %02x\n", m_device->tag(), 'A' + m_index, data);
+
+ // set interrupt enable
+ m_icw |= ICW_ENABLE_INT;
+ m_ie = true;
+ check_interrupts();
+ }
+ else
+ {
+ switch (data & 0x0f)
+ {
+ case 0x0f: // select operating mode
+ set_mode(data >> 6);
+ break;
+
+ case 0x07: // set interrupt control word
+ m_icw = data;
+
+ if (LOG)
+ {
+ logerror("Z80PIO '%s' Port %c Interrupt Enable: %u\n", m_device->tag(), 'A' + m_index, BIT(data, 7));
+ logerror("Z80PIO '%s' Port %c Logic: %s\n", m_device->tag(), 'A' + m_index, BIT(data, 6) ? "AND" : "OR");
+ logerror("Z80PIO '%s' Port %c Active %s\n", m_device->tag(), 'A' + m_index, BIT(data, 5) ? "High" : "Low");
+ logerror("Z80PIO '%s' Port %c Mask Follows: %u\n", m_device->tag(), 'A' + m_index, BIT(data, 4));
+ }
+
+ if (m_icw & ICW_MASK_FOLLOWS)
+ {
+ // disable interrupts until mask is written
+ m_ie = false;
+
+ // reset pending interrupts
+ m_ip = false;
+ check_interrupts();
+
+ // set logic equation to false
+ m_match = false;
+
+ // next word is mask control
+ m_next_control_word = MASK;
+ }
+ break;
+
+ case 0x03: // set interrupt enable flip-flop
+ m_icw = (data & 0x80) | (m_icw & 0x7f);
+ if (LOG) logerror("Z80PIO '%s' Port %c Interrupt Enable: %u\n", m_device->tag(), 'A' + m_index, BIT(data, 7));
+
+ // set interrupt enable
+ m_ie = BIT(m_icw, 7) ? true : false;
+ check_interrupts();
+ break;
+
+ default:
+ logerror("Z80PIO '%s' Port %c Invalid Control Word: %02x!\n", m_device->tag(), 'A' + m_index, data);
+ }
+ }
+ break;
+
+ case IOR: // data direction register
+ m_ior = data;
+ if (LOG) logerror("Z80PIO '%s' Port %c IOR: %02x\n", m_device->tag(), 'A' + m_index, data);
+
+ // set interrupt enable
+ m_ie = BIT(m_icw, 7) ? true : false;
+ check_interrupts();
+
+ // next word is any
+ m_next_control_word = ANY;
+ break;
+
+ case MASK: // interrupt mask
+ m_mask = data;
+ if (LOG) logerror("Z80PIO '%s' Port %c Mask: %02x\n", m_device->tag(), 'A' + m_index, data);
+
+ // set interrupt enable
+ m_ie = BIT(m_icw, 7) ? true : false;
+ check_interrupts();
+
+ // next word is any
+ m_next_control_word = ANY;
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// data_read - data register read
+//-------------------------------------------------
+
+UINT8 z80pio_device::pio_port::data_read()
+{
+ UINT8 data = 0;
+
+ switch (m_mode)
+ {
+ case MODE_OUTPUT:
+ data = m_output;
+ break;
+
+ case MODE_INPUT:
+ if (!m_stb)
+ {
+ // input port data
+ m_input = m_in_p_func(0);
+ }
+
+ data = m_input;
+
+ // clear ready line
+ set_rdy(false);
+
+ // assert ready line
+ set_rdy(true);
+ break;
+
+ case MODE_BIDIRECTIONAL:
+ data = m_input;
+
+ // clear ready line
+ m_device->m_port[PORT_B].set_rdy(false);
+
+ // assert ready line
+ m_device->m_port[PORT_B].set_rdy(true);
+ break;
+
+ case MODE_BIT_CONTROL:
+ // input port data
+ m_input = m_in_p_func(0);
+
+ data = (m_input & m_ior) | (m_output & (m_ior ^ 0xff));
+ break;
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// data_write - data register write
+//-------------------------------------------------
+
+void z80pio_device::pio_port::data_write(UINT8 data)
+{
+ switch (m_mode)
+ {
+ case MODE_OUTPUT:
+ // clear ready line
+ set_rdy(false);
+
+ // latch output data
+ m_output = data;
+
+ // output data to port
+ m_out_p_func(0, data);
+
+ // assert ready line
+ set_rdy(true);
+ break;
+
+ case MODE_INPUT:
+ // latch output data
+ m_output = data;
+ break;
+
+ case MODE_BIDIRECTIONAL:
+ // clear ready line
+ set_rdy(false);
+
+ // latch output data
+ m_output = data;
+
+ if (!m_stb)
+ {
+ // output data to port
+ m_out_p_func(0, data);
+ }
+
+ // assert ready line
+ set_rdy(true);
+ break;
+
+ case MODE_BIT_CONTROL:
+ // latch output data
+ m_output = data;
+
+ // output data to port
+ m_out_p_func(0, m_ior | (m_output & (m_ior ^ 0xff)));
+ break;
+ }
+}
+
+
+
+//**************************************************************************
+// GLOBAL STUBS
+//**************************************************************************
+
+READ8_DEVICE_HANDLER( z80pio_c_r ) { return downcast<z80pio_device *>(device)->control_read(); }
+WRITE8_DEVICE_HANDLER( z80pio_c_w ) { downcast<z80pio_device *>(device)->control_write(offset & 1, data); }
+
+READ8_DEVICE_HANDLER( z80pio_d_r ) { return downcast<z80pio_device *>(device)->data_read(offset & 1); }
+WRITE8_DEVICE_HANDLER( z80pio_d_w ) { downcast<z80pio_device *>(device)->data_write(offset & 1, data); }
+
+READ_LINE_DEVICE_HANDLER( z80pio_ardy_r ) { return downcast<z80pio_device *>(device)->rdy(z80pio_device::PORT_A); }
+READ_LINE_DEVICE_HANDLER( z80pio_brdy_r ) { return downcast<z80pio_device *>(device)->rdy(z80pio_device::PORT_B); }
+
+WRITE_LINE_DEVICE_HANDLER( z80pio_astb_w ) { downcast<z80pio_device *>(device)->strobe(z80pio_device::PORT_A, state ? true : false); }
+WRITE_LINE_DEVICE_HANDLER( z80pio_bstb_w ) { downcast<z80pio_device *>(device)->strobe(z80pio_device::PORT_B, state ? true : false); }
+
+READ8_DEVICE_HANDLER( z80pio_pa_r ) { return downcast<z80pio_device *>(device)->port_read(z80pio_device::PORT_A); }
+READ8_DEVICE_HANDLER( z80pio_pb_r ) { return downcast<z80pio_device *>(device)->port_read(z80pio_device::PORT_B); }
+
+WRITE8_DEVICE_HANDLER( z80pio_pa_w ) { downcast<z80pio_device *>(device)->port_write(z80pio_device::PORT_A, data); }
+WRITE8_DEVICE_HANDLER( z80pio_pb_w ) { downcast<z80pio_device *>(device)->port_write(z80pio_device::PORT_B, data); }
+
+//-------------------------------------------------
+// z80pio_cd_ba_r - register read
+//-------------------------------------------------
+
+READ8_DEVICE_HANDLER( z80pio_cd_ba_r )
+{
+ int index = BIT(offset, 0);
+
+ return BIT(offset, 1) ? z80pio_c_r(device, index) : z80pio_d_r(device, index);
+}
+
+//-------------------------------------------------
+// z80pio_cd_ba_w - register write
+//-------------------------------------------------
+
+WRITE8_DEVICE_HANDLER( z80pio_cd_ba_w )
+{
+ int index = BIT(offset, 0);
+
+ BIT(offset, 1) ? z80pio_c_w(device, index, data) : z80pio_d_w(device, index, data);
+}
+
+//-------------------------------------------------
+// z80pio_ba_cd_r - register read
+//-------------------------------------------------
+
+READ8_DEVICE_HANDLER( z80pio_ba_cd_r )
+{
+ int index = BIT(offset, 1);
+
+ return BIT(offset, 0) ? z80pio_c_r(device, index) : z80pio_d_r(device, index);
+}
+
+//-------------------------------------------------
+// z80pio_ba_cd_w - register write
+//-------------------------------------------------
+
+WRITE8_DEVICE_HANDLER( z80pio_ba_cd_w )
+{
+ int index = BIT(offset, 1);
+
+ BIT(offset, 0) ? z80pio_c_w(device, index, data) : z80pio_d_w(device, index, data);
+}
diff --git a/trunk/src/emu/machine/z80pio.h b/trunk/src/emu/machine/z80pio.h
new file mode 100644
index 00000000000..4a2df0bb03e
--- /dev/null
+++ b/trunk/src/emu/machine/z80pio.h
@@ -0,0 +1,221 @@
+/***************************************************************************
+
+ Zilog Z80 Parallel Input/Output Controller implementation
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************
+ _____ _____
+ D2 1 |* \_/ | 40 D3
+ D7 2 | | 39 D4
+ D6 3 | | 38 D5
+ _CE 4 | | 37 _M1
+ C/_D 5 | | 36 _IORQ
+ B/_A 6 | | 35 RD
+ PA7 7 | | 34 PB7
+ PA6 8 | | 33 PB6
+ PA5 9 | | 32 PB5
+ PA4 10 | Z8420 | 31 PB4
+ GND 11 | | 30 PB3
+ PA3 12 | | 29 PB2
+ PA2 13 | | 28 PB1
+ PA1 14 | | 27 PB0
+ PA0 15 | | 26 +5V
+ _ASTB 16 | | 25 CLK
+ _BSTB 17 | | 24 IEI
+ ARDY 18 | | 23 _INT
+ D0 19 | | 22 IEO
+ D1 20 |_____________| 21 BRDY
+
+***************************************************************************/
+
+#ifndef __Z80PIO__
+#define __Z80PIO__
+
+#include "cpu/z80/z80daisy.h"
+
+
+//**************************************************************************
+// DEVICE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_Z80PIO_ADD(_tag, _clock, _intrf) \
+ MCFG_DEVICE_ADD(_tag, Z80PIO, _clock) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define Z80PIO_INTERFACE(_name) \
+ const z80pio_interface (_name) =
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> z80pio_interface
+
+struct z80pio_interface
+{
+ devcb_write_line m_out_int_cb;
+
+ devcb_read8 m_in_pa_cb;
+ devcb_write8 m_out_pa_cb;
+ devcb_write_line m_out_ardy_cb;
+
+ devcb_read8 m_in_pb_cb;
+ devcb_write8 m_out_pb_cb;
+ devcb_write_line m_out_brdy_cb;
+};
+
+
+
+// ======================> z80pio_device
+
+class z80pio_device : public device_t,
+ public device_z80daisy_interface,
+ public z80pio_interface
+{
+public:
+ enum
+ {
+ PORT_A = 0,
+ PORT_B,
+ PORT_COUNT
+ };
+
+ // construction/destruction
+ z80pio_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // I/O line access
+ int rdy(int which) { return m_port[which].rdy(); }
+ void strobe(int which, bool state) { m_port[which].strobe(state); }
+
+ // control register I/O
+ UINT8 control_read();
+ void control_write(int offset, UINT8 data) { m_port[offset & 1].control_write(data); }
+
+ // data register I/O
+ UINT8 data_read(int offset) { return m_port[offset & 1].data_read(); }
+ void data_write(int offset, UINT8 data) { m_port[offset & 1].data_write(data); }
+
+ // port I/O
+ UINT8 port_read(int offset) { return m_port[offset & 1].read(); }
+ void port_write(int offset, UINT8 data) { m_port[offset & 1].write(data); }
+
+private:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_z80daisy_interface overrides
+ virtual int z80daisy_irq_state();
+ virtual int z80daisy_irq_ack();
+ virtual void z80daisy_irq_reti();
+
+ // internal helpers
+ void check_interrupts();
+
+ // a single PIO port
+ class pio_port
+ {
+ friend class z80pio_device;
+
+ public:
+ pio_port();
+
+ void start(z80pio_device *device, int index, const devcb_read8 &infunc, const devcb_write8 &outfunc, const devcb_write_line &rdyfunc);
+ void reset();
+
+ bool interrupt_signalled();
+ void trigger_interrupt();
+
+ int rdy() const { return m_rdy; }
+ void set_rdy(bool state);
+ void set_mode(int mode);
+ void strobe(bool state);
+
+ UINT8 read();
+ void write(UINT8 data);
+
+ void control_write(UINT8 data);
+
+ UINT8 data_read();
+ void data_write(UINT8 data);
+
+ private:
+ void check_interrupts() { m_device->check_interrupts(); }
+
+ z80pio_device * m_device;
+ int m_index;
+
+ devcb_resolved_read8 m_in_p_func;
+ devcb_resolved_write8 m_out_p_func;
+ devcb_resolved_write_line m_out_rdy_func;
+
+ int m_mode; // mode register
+ int m_next_control_word; // next control word
+ UINT8 m_input; // input latch
+ UINT8 m_output; // output latch
+ UINT8 m_ior; // input/output register
+ bool m_rdy; // ready
+ bool m_stb; // strobe
+
+ // interrupts
+ bool m_ie; // interrupt enabled
+ bool m_ip; // interrupt pending
+ bool m_ius; // interrupt under service
+ UINT8 m_icw; // interrupt control word
+ UINT8 m_vector; // interrupt vector
+ UINT8 m_mask; // interrupt mask
+ bool m_match; // logic equation match
+ };
+
+ // internal state
+ pio_port m_port[2];
+ devcb_resolved_write_line m_out_int_func;
+};
+
+
+// device type definition
+extern const device_type Z80PIO;
+
+
+
+//**************************************************************************
+// FUNCTION PROTOTYPES
+//**************************************************************************
+
+// control register access
+READ8_DEVICE_HANDLER( z80pio_c_r );
+WRITE8_DEVICE_HANDLER( z80pio_c_w );
+
+// data register access
+READ8_DEVICE_HANDLER( z80pio_d_r );
+WRITE8_DEVICE_HANDLER( z80pio_d_w );
+
+// register access
+READ8_DEVICE_HANDLER( z80pio_cd_ba_r );
+WRITE8_DEVICE_HANDLER( z80pio_cd_ba_w );
+
+READ8_DEVICE_HANDLER( z80pio_ba_cd_r );
+WRITE8_DEVICE_HANDLER( z80pio_ba_cd_w );
+
+// port access
+READ8_DEVICE_HANDLER( z80pio_pa_r );
+WRITE8_DEVICE_HANDLER( z80pio_pa_w );
+
+READ8_DEVICE_HANDLER( z80pio_pb_r );
+WRITE8_DEVICE_HANDLER( z80pio_pb_w );
+
+// ready
+READ_LINE_DEVICE_HANDLER( z80pio_ardy_r );
+READ_LINE_DEVICE_HANDLER( z80pio_brdy_r );
+
+// strobe
+WRITE_LINE_DEVICE_HANDLER( z80pio_astb_w );
+WRITE_LINE_DEVICE_HANDLER( z80pio_bstb_w );
+
+#endif
diff --git a/trunk/src/emu/machine/z80sio.c b/trunk/src/emu/machine/z80sio.c
new file mode 100644
index 00000000000..8ddcd54806a
--- /dev/null
+++ b/trunk/src/emu/machine/z80sio.c
@@ -0,0 +1,865 @@
+/***************************************************************************
+
+ Z80 SIO (Z8440) implementation
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "z80sio.h"
+#include "cpu/z80/z80.h"
+#include "cpu/z80/z80daisy.h"
+
+
+// device type definition
+const device_type Z80SIO = &device_creator<z80sio_device>;
+
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define VERBOSE 0
+
+#define VPRINTF(x) do { if (VERBOSE) logerror x; } while (0)
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// interrupt states
+const int INT_TRANSMIT = 0x00; // not confirmed
+const int INT_STATUS = 0x01;
+const int INT_RECEIVE = 0x02;
+const int INT_ERROR = 0x03;
+
+const int INT_CHB_TRANSMIT = 0 + INT_TRANSMIT;
+const int INT_CHB_STATUS = 0 + INT_STATUS;
+const int INT_CHB_RECEIVE = 0 + INT_RECEIVE;
+const int INT_CHB_ERROR = 0 + INT_ERROR;
+const int INT_CHA_TRANSMIT = 4 + INT_TRANSMIT;
+const int INT_CHA_STATUS = 4 + INT_STATUS;
+const int INT_CHA_RECEIVE = 4 + INT_RECEIVE;
+const int INT_CHA_ERROR = 4 + INT_ERROR;
+
+// SIO write register 0
+const int SIO_WR0_RESET_MASK = 0xc0; // D7-D6: Reset control
+const int SIO_WR0_RESET_NULL = 0x00; // 00 = NULL code
+const int SIO_WR0_RESET_RX_CRC = 0x40; // 01 = Reset Rx CRC checker
+const int SIO_WR0_RESET_TX_CRC = 0x80; // 10 = Reset Tx CRC generator
+const int SIO_WR0_RESET_TX_LATCH = 0xc0; // 11 = Reset Tx Underrun/EOM latch
+const int SIO_WR0_COMMAND_MASK = 0x38; // D5-D3: Command
+const int SIO_WR0_COMMAND_NULL = 0x00; // 000 = NULL code
+const int SIO_WR0_COMMAND_SET_ABORT = 0x08; // 001 = Set abort (SDLC)
+const int SIO_WR0_COMMAND_RES_STATUS_INT = 0x10; // 010 = reset ext/status interrupts
+const int SIO_WR0_COMMAND_CH_RESET = 0x18; // 011 = Channel reset
+const int SIO_WR0_COMMAND_ENA_RX_INT = 0x20; // 100 = Enable int on next Rx character
+const int SIO_WR0_COMMAND_RES_TX_INT = 0x28; // 101 = Reset Tx int pending
+const int SIO_WR0_COMMAND_RES_ERROR = 0x30; // 110 = Error reset
+const int SIO_WR0_COMMAND_RETI = 0x38; // 111 = Return from int (CH-A only)
+const int SIO_WR0_REGISTER_MASK = 0x07; // D2-D0: Register select (0-7)
+
+// SIO write register 1
+const int SIO_WR1_READY_WAIT_ENA = 0x80; // D7 = READY/WAIT enable
+const int SIO_WR1_READY_WAIT_FUNCTION = 0x40; // D6 = READY/WAIT function
+const int SIO_WR1_READY_WAIT_ON_RT = 0x20; // D5 = READY/WAIT on R/T
+const int SIO_WR1_RXINT_MASK = 0x18; // D4-D3 = Rx int control
+const int SIO_WR1_RXINT_DISABLE = 0x00; // 00 = Rx int disable
+const int SIO_WR1_RXINT_FIRST = 0x08; // 01 = Rx int on first character
+const int SIO_WR1_RXINT_ALL_PARITY = 0x10; // 10 = int on all Rx characters (parity affects vector)
+const int SIO_WR1_RXINT_ALL_NOPARITY = 0x18; // 11 = int on all Rx characters (parity ignored)
+const int SIO_WR1_STATUS_AFFECTS_VECTOR = 0x04; // D2 = Status affects vector (CH-B only)
+const int SIO_WR1_TXINT_ENABLE = 0x02; // D1 = Tx int enable
+const int SIO_WR1_STATUSINT_ENABLE = 0x01; // D0 = Ext int enable
+
+// SIO write register 2 (CH-B only)
+const int SIO_WR2_INT_VECTOR_MASK = 0xff; // D7-D0 = interrupt vector
+
+// SIO write register 3
+const int SIO_WR3_RX_DATABITS_MASK = 0xc0; // D7-D6 = Rx Data bits
+const int SIO_WR3_RX_DATABITS_5 = 0x00; // 00 = Rx 5 bits/character
+const int SIO_WR3_RX_DATABITS_7 = 0x40; // 01 = Rx 7 bits/character
+const int SIO_WR3_RX_DATABITS_6 = 0x80; // 10 = Rx 6 bits/character
+const int SIO_WR3_RX_DATABITS_8 = 0xc0; // 11 = Rx 8 bits/character
+const int SIO_WR3_AUTO_ENABLES = 0x20; // D5 = Auto enables
+const int SIO_WR3_ENTER_HUNT_PHASE = 0x10; // D4 = Enter hunt phase
+const int SIO_WR3_RX_CRC_ENABLE = 0x08; // D3 = Rx CRC enable
+const int SIO_WR3_ADDR_SEARCH_MODE = 0x04; // D2 = Address search mode (SDLC)
+const int SIO_WR3_SYNC_LOAD_INHIBIT = 0x02; // D1 = Sync character load inhibit
+const int SIO_WR3_RX_ENABLE = 0x01; // D0 = Rx enable
+
+// SIO write register 4
+const int SIO_WR4_CLOCK_MODE_MASK = 0xc0; // D7-D6 = Clock mode
+const int SIO_WR4_CLOCK_MODE_x1 = 0x00; // 00 = x1 clock mode
+const int SIO_WR4_CLOCK_MODE_x16 = 0x40; // 01 = x16 clock mode
+const int SIO_WR4_CLOCK_MODE_x32 = 0x80; // 10 = x32 clock mode
+const int SIO_WR4_CLOCK_MODE_x64 = 0xc0; // 11 = x64 clock mode
+const int SIO_WR4_SYNC_MODE_MASK = 0x30; // D5-D4 = Sync mode
+const int SIO_WR4_SYNC_MODE_8BIT = 0x00; // 00 = 8 bit sync character
+const int SIO_WR4_SYNC_MODE_16BIT = 0x10; // 01 = 16 bit sync character
+const int SIO_WR4_SYNC_MODE_SDLC = 0x20; // 10 = SDLC mode (01111110 flag)
+const int SIO_WR4_SYNC_MODE_EXTERNAL = 0x30; // 11 = External sync mode
+const int SIO_WR4_STOPBITS_MASK = 0x0c; // D3-D2 = Stop bits
+const int SIO_WR4_STOPBITS_SYNC = 0x00; // 00 = Sync modes enable
+const int SIO_WR4_STOPBITS_1 = 0x04; // 01 = 1 stop bit/character
+const int SIO_WR4_STOPBITS_15 = 0x08; // 10 = 1.5 stop bits/character
+const int SIO_WR4_STOPBITS_2 = 0x0c; // 11 = 2 stop bits/character
+const int SIO_WR4_PARITY_EVEN = 0x02; // D1 = Parity even/odd
+const int SIO_WR4_PARITY_ENABLE = 0x01; // D0 = Parity enable
+
+// SIO write register 5
+const int SIO_WR5_DTR = 0x80; // D7 = DTR
+const int SIO_WR5_TX_DATABITS_MASK = 0x60; // D6-D5 = Tx Data bits
+const int SIO_WR5_TX_DATABITS_5 = 0x00; // 00 = Tx 5 bits/character
+const int SIO_WR5_TX_DATABITS_7 = 0x20; // 01 = Tx 7 bits/character
+const int SIO_WR5_TX_DATABITS_6 = 0x40; // 10 = Tx 6 bits/character
+const int SIO_WR5_TX_DATABITS_8 = 0x60; // 11 = Tx 8 bits/character
+const int SIO_WR5_SEND_BREAK = 0x10; // D4 = Send break
+const int SIO_WR5_TX_ENABLE = 0x08; // D3 = Tx Enable
+const int SIO_WR5_CRC16_SDLC = 0x04; // D2 = CRC-16/SDLC
+const int SIO_WR5_RTS = 0x02; // D1 = RTS
+const int SIO_WR5_TX_CRC_ENABLE = 0x01; // D0 = Tx CRC enable
+
+// SIO write register 6
+const int SIO_WR6_SYNC_7_0_MASK = 0xff; // D7-D0 = Sync bits 7-0
+
+// SIO write register 7
+const int SIO_WR7_SYNC_15_8_MASK = 0xff; // D7-D0 = Sync bits 15-8
+
+// SIO read register 0
+const int SIO_RR0_BREAK_ABORT = 0x80; // D7 = Break/abort
+const int SIO_RR0_TX_UNDERRUN = 0x40; // D6 = Tx underrun/EOM
+const int SIO_RR0_CTS = 0x20; // D5 = CTS
+const int SIO_RR0_SYNC_HUNT = 0x10; // D4 = Sync/hunt
+const int SIO_RR0_DCD = 0x08; // D3 = DCD
+const int SIO_RR0_TX_BUFFER_EMPTY = 0x04; // D2 = Tx buffer empty
+const int SIO_RR0_INT_PENDING = 0x02; // D1 = int pending (CH-A only)
+const int SIO_RR0_RX_CHAR_AVAILABLE = 0x01; // D0 = Rx character available
+
+// SIO read register 1
+const int SIO_RR1_END_OF_FRAME = 0x80; // D7 = End of frame (SDLC)
+const int SIO_RR1_CRC_FRAMING_ERROR = 0x40; // D6 = CRC/Framing error
+const int SIO_RR1_RX_OVERRUN_ERROR = 0x20; // D5 = Rx overrun error
+const int SIO_RR1_PARITY_ERROR = 0x10; // D4 = Parity error
+const int SIO_RR1_IFIELD_BITS_MASK = 0x0e; // D3-D1 = I field bits
+ // 100 = 0 in prev, 3 in 2nd prev
+ // 010 = 0 in prev, 4 in 2nd prev
+ // 110 = 0 in prev, 5 in 2nd prev
+ // 001 = 0 in prev, 6 in 2nd prev
+ // 101 = 0 in prev, 7 in 2nd prev
+ // 011 = 0 in prev, 8 in 2nd prev
+ // 111 = 1 in prev, 8 in 2nd prev
+ // 000 = 2 in prev, 8 in 2nd prev
+const int SIO_RR1_ALL_SENT = 0x01; // D0 = All sent
+
+// SIO read register 2 (CH-B only)
+const int SIO_RR2_VECTOR_MASK = 0xff; // D7-D0 = Interrupt vector
+
+
+const UINT8 z80sio_device::k_int_priority[] =
+{
+ INT_CHA_RECEIVE,
+ INT_CHA_TRANSMIT,
+ INT_CHA_STATUS,
+ INT_CHA_ERROR,
+ INT_CHB_RECEIVE,
+ INT_CHB_TRANSMIT,
+ INT_CHB_STATUS,
+ INT_CHB_ERROR
+};
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+
+/*
+
+ Interrupt priorities:
+ Ch A receive
+ Ch A transmit
+ Ch A external/status
+ Ch B receive
+ Ch B transmit
+ Ch B external/status
+
+
+ Initial configuration (both channels):
+ 005D:sio_reg_w(0,4) = 44
+ 01 = x16 clock mode
+ 00 = 8 bit sync character
+ 01 = 1 stop bit/character
+ Parity odd
+ Parity disabled
+
+ 005D:sio_reg_w(0,3) = C1
+ 11 = Rx 8 bits/character
+ No auto enables
+ No enter hunt phase
+ No Rx CRC enable
+ No address search mode
+ No sync character load inhibit
+ Rx enable
+
+ 005D:sio_reg_w(0,5) = 68
+ DTR = 0
+ 11 = Tx 8 bits/character
+ No send break
+ Tx enable
+ SDLC
+ No RTS
+ No CRC enable
+
+ 005D:sio_reg_w(0,2) = 40
+ Vector = 0x40
+
+ 005D:sio_reg_w(0,1) = 1D
+ No READY/WAIT
+ No READY/WAIT function
+ No READY/WAIT on R/T
+ 11 = int on all Rx characters (parity ignored)
+ Status affects vector
+ No Tx int enable
+ Ext int enable
+
+*/
+
+
+//**************************************************************************
+// INLINE FUNCTIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// update_interrupt_state - update the interrupt
+// state to the external world
+//-------------------------------------------------
+
+inline void z80sio_device::update_interrupt_state()
+{
+ // if we have a callback, update it with the current state
+ if (m_irq_cb != NULL)
+ (*m_irq_cb)(this, (z80daisy_irq_state() & Z80_DAISY_INT) ? ASSERT_LINE : CLEAR_LINE);
+}
+
+
+//-------------------------------------------------
+// set_interrupt - set the given interrupt state
+// on this channel and update the overall device
+// state
+//-------------------------------------------------
+
+inline void z80sio_device::sio_channel::set_interrupt(int type)
+{
+ int inum = (this == &m_device->m_channel[0] ? 4 : 0) + type;
+ m_device->m_int_state[inum] = Z80_DAISY_INT;
+ m_device->update_interrupt_state();
+}
+
+
+//-------------------------------------------------
+// clear_interrupt - clear the given interrupt
+// state on this channel and update the overall
+// device state
+//-------------------------------------------------
+
+inline void z80sio_device::sio_channel::clear_interrupt(int type)
+{
+ int inum = (this == &m_device->m_channel[0] ? 4 : 0) + type;
+ m_device->m_int_state[inum] &= ~Z80_DAISY_INT;
+ m_device->update_interrupt_state();
+}
+
+
+//-------------------------------------------------
+// compute_time_per_character - compute the
+// serial clocking period
+//-------------------------------------------------
+
+inline attotime z80sio_device::sio_channel::compute_time_per_character()
+{
+ // fix me -- should compute properly and include data, stop, parity bit
+ return attotime::from_hz(9600) * 10;
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// z80sio_device - constructor
+//-------------------------------------------------
+
+z80sio_device::z80sio_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, Z80SIO, "Zilog Z80 SIO", tag, owner, clock),
+ device_z80daisy_interface(mconfig, *this)
+{
+ for (int i = 0; i < 8; i++)
+ m_int_state[i] = 0;
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void z80sio_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const z80sio_interface *intf = reinterpret_cast<const z80sio_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<z80sio_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ m_irq_cb = NULL;
+ m_dtr_changed_cb = NULL;
+ m_rts_changed_cb = NULL;
+ m_break_changed_cb = NULL;
+ m_transmit_cb = NULL;
+ m_receive_poll_cb = NULL;
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void z80sio_device::device_start()
+{
+ m_channel[0].start(this, 0);
+ m_channel[1].start(this, 1);
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void z80sio_device::device_reset()
+{
+ // loop over channels
+ for (int ch = 0; ch < 2; ch++)
+ m_channel[ch].reset();
+}
+
+
+
+//**************************************************************************
+// DAISY CHAIN INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// z80daisy_irq_state - return the overall IRQ
+// state for this device
+//-------------------------------------------------
+
+int z80sio_device::z80daisy_irq_state()
+{
+ int state = 0;
+
+ VPRINTF(("sio IRQ state = B:%d%d%d%d A:%d%d%d%d\n",
+ m_int_state[0], m_int_state[1], m_int_state[2], m_int_state[3],
+ m_int_state[4], m_int_state[5], m_int_state[6], m_int_state[7]));
+
+ // loop over all interrupt sources
+ for (int irqsource = 0; irqsource < 8; irqsource++)
+ {
+ int inum = k_int_priority[irqsource];
+
+ // if we're servicing a request, don't indicate more interrupts
+ if (m_int_state[inum] & Z80_DAISY_IEO)
+ {
+ state |= Z80_DAISY_IEO;
+ break;
+ }
+ state |= m_int_state[inum];
+ }
+
+ return state;
+}
+
+
+//-------------------------------------------------
+// z80daisy_irq_ack - acknowledge an IRQ and
+// return the appropriate vector
+//-------------------------------------------------
+
+int z80sio_device::z80daisy_irq_ack()
+{
+ // loop over all interrupt sources
+ for (int irqsource = 0; irqsource < 8; irqsource++)
+ {
+ int inum = k_int_priority[irqsource];
+
+ // find the first channel with an interrupt requested
+ if (m_int_state[inum] & Z80_DAISY_INT)
+ {
+ VPRINTF(("sio IRQAck %d\n", inum));
+
+ // clear interrupt, switch to the IEO state, and update the IRQs
+ m_int_state[inum] = Z80_DAISY_IEO;
+ update_interrupt_state();
+ return m_channel[1].m_regs[2] + inum * 2;
+ }
+ }
+
+ logerror("z80sio_irq_ack: failed to find an interrupt to ack!\n");
+ return m_channel[1].m_regs[2];
+}
+
+
+//-------------------------------------------------
+// z80daisy_irq_reti - clear the interrupt
+// pending state to allow other interrupts through
+//-------------------------------------------------
+
+void z80sio_device::z80daisy_irq_reti()
+{
+ // loop over all interrupt sources
+ for (int irqsource = 0; irqsource < 8; irqsource++)
+ {
+ int inum = k_int_priority[irqsource];
+
+ // find the first channel with an IEO pending
+ if (m_int_state[inum] & Z80_DAISY_IEO)
+ {
+ VPRINTF(("sio IRQReti %d\n", inum));
+
+ // clear the IEO state and update the IRQs
+ m_int_state[inum] &= ~Z80_DAISY_IEO;
+ update_interrupt_state();
+ return;
+ }
+ }
+
+ logerror("z80sio_irq_reti: failed to find an interrupt to clear IEO on!\n");
+}
+
+
+
+//**************************************************************************
+// SIO CHANNEL
+//**************************************************************************
+
+//-------------------------------------------------
+// sio_channel - constructor
+//-------------------------------------------------
+
+z80sio_device::sio_channel::sio_channel()
+ : m_device(NULL),
+ m_index(0),
+ m_inbuf(-1),
+ m_outbuf(-1),
+ m_int_on_next_rx(false),
+ m_receive_timer(NULL),
+ m_receive_inptr(0),
+ m_receive_outptr(0)
+{
+ memset(m_regs, 0, sizeof(m_regs));
+ memset(m_status, 0, sizeof(m_status));
+ memset(m_receive_buffer, 0, sizeof(m_receive_buffer));
+}
+
+
+//-------------------------------------------------
+// start - channel-specific startup
+//-------------------------------------------------
+
+void z80sio_device::sio_channel::start(z80sio_device *device, int index)
+{
+ m_device = device;
+ m_index = index;
+ m_receive_timer = device->machine().scheduler().timer_alloc(FUNC(static_serial_callback), this);
+}
+
+
+//-------------------------------------------------
+// reset - reset a single SIO channel
+//-------------------------------------------------
+
+void z80sio_device::sio_channel::reset()
+{
+ m_status[0] = SIO_RR0_TX_BUFFER_EMPTY;
+ m_status[1] = 0x00;
+ m_status[2] = 0x00;
+ m_int_on_next_rx = false;
+ m_outbuf = -1;
+
+ // reset interrupts
+ clear_interrupt(INT_TRANSMIT);
+ clear_interrupt(INT_STATUS);
+ clear_interrupt(INT_RECEIVE);
+ clear_interrupt(INT_ERROR);
+
+ // start the receive timer running
+ attotime tpc = compute_time_per_character();
+ m_receive_timer->adjust(tpc, 0, tpc);
+}
+
+
+//-------------------------------------------------
+// control_write - write to a control register
+//-------------------------------------------------
+
+void z80sio_device::sio_channel::control_write(UINT8 data)
+{
+ int regnum = m_regs[0] & 7;
+
+ if (regnum != 0 || (regnum & 0xf8) != 0)
+ VPRINTF(("%s:sio_reg_w(%c,%d) = %02X\n", m_device->machine().describe_context(), 'A' + m_index, regnum, data));
+
+ // write a new value to the selected register
+ UINT8 old = m_regs[regnum];
+ m_regs[regnum] = data;
+
+ // clear the register number for the next write
+ if (regnum != 0)
+ m_regs[0] &= ~7;
+
+ // switch off the register for live state changes
+ switch (regnum)
+ {
+ // SIO write register 0
+ case 0:
+ switch (data & SIO_WR0_COMMAND_MASK)
+ {
+ case SIO_WR0_COMMAND_CH_RESET:
+ VPRINTF(("%s:SIO reset channel %c\n", m_device->machine().describe_context(), 'A' + m_index));
+ reset();
+ break;
+
+ case SIO_WR0_COMMAND_RES_STATUS_INT:
+ clear_interrupt(INT_STATUS);
+ break;
+
+ case SIO_WR0_COMMAND_ENA_RX_INT:
+ m_int_on_next_rx = true;
+ m_device->update_interrupt_state();
+ break;
+
+ case SIO_WR0_COMMAND_RES_TX_INT:
+ clear_interrupt(INT_TRANSMIT);
+ break;
+
+ case SIO_WR0_COMMAND_RES_ERROR:
+ clear_interrupt(INT_ERROR);
+ break;
+ }
+ break;
+
+ // SIO write register 1
+ case 1:
+ m_device->update_interrupt_state();
+ break;
+
+ // SIO write register 5
+ case 5:
+ if (((old ^ data) & SIO_WR5_DTR) && m_device->m_dtr_changed_cb)
+ (*m_device->m_dtr_changed_cb)(m_device, m_index, (data & SIO_WR5_DTR) != 0);
+ if (((old ^ data) & SIO_WR5_SEND_BREAK) && m_device->m_break_changed_cb)
+ (*m_device->m_break_changed_cb)(m_device, m_index, (data & SIO_WR5_SEND_BREAK) != 0);
+ if (((old ^ data) & SIO_WR5_RTS) && m_device->m_rts_changed_cb)
+ (*m_device->m_rts_changed_cb)(m_device, m_index, (data & SIO_WR5_RTS) != 0);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// control_read - read from a control register
+//-------------------------------------------------
+
+UINT8 z80sio_device::sio_channel::control_read()
+{
+ int regnum = m_regs[0] & 7;
+ UINT8 result = m_status[regnum];
+
+ // switch off the register for live state changes
+ switch (regnum)
+ {
+ // SIO read register 0
+ case 0:
+ result &= ~SIO_RR0_INT_PENDING;
+ if (m_device->z80daisy_irq_state() & Z80_DAISY_INT)
+ result |= SIO_RR0_INT_PENDING;
+ break;
+ }
+
+ VPRINTF(("%s:sio_reg_r(%c,%d) = %02x\n", m_device->machine().describe_context(), 'A' + m_index, regnum, m_status[regnum]));
+
+ return m_status[regnum];
+}
+
+
+//-------------------------------------------------
+// data_write - write to a data register
+//-------------------------------------------------
+
+void z80sio_device::sio_channel::data_write(UINT8 data)
+{
+ VPRINTF(("%s:sio_data_w(%c) = %02X\n", m_device->machine().describe_context(), 'A' + m_index, data));
+
+ // if tx not enabled, just ignore it
+ if (!(m_regs[5] & SIO_WR5_TX_ENABLE))
+ return;
+
+ // update the status register
+ m_status[0] &= ~SIO_RR0_TX_BUFFER_EMPTY;
+
+ // reset the transmit interrupt
+ clear_interrupt(INT_TRANSMIT);
+
+ // stash the character
+ m_outbuf = data;
+}
+
+
+//-------------------------------------------------
+// data_read - read from a data register
+//-------------------------------------------------
+
+UINT8 z80sio_device::sio_channel::data_read()
+{
+ // update the status register
+ m_status[0] &= ~SIO_RR0_RX_CHAR_AVAILABLE;
+
+ // reset the receive interrupt
+ clear_interrupt(INT_RECEIVE);
+
+ VPRINTF(("%s:sio_data_r(%c) = %02X\n", m_device->machine().describe_context(), 'A' + m_index, m_inbuf));
+
+ return m_inbuf;
+}
+
+
+//-------------------------------------------------
+// dtr - return the state of the DTR line
+//-------------------------------------------------
+
+int z80sio_device::sio_channel::dtr()
+{
+ return ((m_regs[5] & SIO_WR5_DTR) != 0);
+}
+
+
+//-------------------------------------------------
+// rts - return the state of the RTS line
+//-------------------------------------------------
+
+int z80sio_device::sio_channel::rts()
+{
+ return ((m_regs[5] & SIO_WR5_RTS) != 0);
+}
+
+
+//-------------------------------------------------
+// set_cts - set the state of the CTS line
+//-------------------------------------------------
+
+void z80sio_device::sio_channel::set_cts(int state)
+{
+ m_device->machine().scheduler().synchronize(FUNC(static_change_input_line), (SIO_RR0_CTS << 1) + (state != 0), this);
+}
+
+
+//-------------------------------------------------
+// set_dcd - set the state of the DCD line
+//-------------------------------------------------
+
+void z80sio_device::sio_channel::set_dcd(int state)
+{
+ m_device->machine().scheduler().synchronize(FUNC(static_change_input_line), (SIO_RR0_DCD << 1) + (state != 0), this);
+}
+
+
+//-------------------------------------------------
+// receive_data - receive data on the input lines
+//-------------------------------------------------
+
+void z80sio_device::sio_channel::receive_data(int data)
+{
+ // put it on the queue
+ int newinptr = (m_receive_inptr + 1) % ARRAY_LENGTH(m_receive_buffer);
+ if (newinptr != m_receive_outptr)
+ {
+ m_receive_buffer[m_receive_inptr] = data;
+ m_receive_inptr = newinptr;
+ }
+ else
+ logerror("z80sio_receive_data: buffer overrun\n");
+}
+
+
+//-------------------------------------------------
+// change_input_line - generically change the
+// state of an input line; designed to be called
+// from a timer callback
+//-------------------------------------------------
+
+void z80sio_device::sio_channel::change_input_line(int line, int state)
+{
+ VPRINTF(("sio_change_input_line(%c, %s) = %d\n", 'A' + m_index, (line == SIO_RR0_CTS) ? "CTS" : "DCD", state));
+
+ // remember the old value
+ UINT8 old = m_status[0];
+
+ // set the bit in the status register
+ m_status[0] &= ~line;
+ if (state)
+ m_status[0] |= line;
+
+ // if state change interrupts are enabled, signal
+ if (((old ^ m_status[0]) & line) && (m_regs[1] & SIO_WR1_STATUSINT_ENABLE))
+ set_interrupt(INT_STATUS);
+}
+
+
+//-------------------------------------------------
+// serial_callback - callback to pump
+// data through
+//-------------------------------------------------
+
+void z80sio_device::sio_channel::serial_callback()
+{
+ int data = -1;
+
+ // first perform any outstanding transmits
+ if (m_outbuf != -1)
+ {
+ VPRINTF(("serial_callback(%c): Transmitting %02x\n", 'A' + m_index, m_outbuf));
+
+ // actually transmit the character
+ if (m_device->m_transmit_cb != NULL)
+ (*m_device->m_transmit_cb)(m_device, m_index, m_outbuf);
+
+ // update the status register
+ m_status[0] |= SIO_RR0_TX_BUFFER_EMPTY;
+
+ // set the transmit buffer empty interrupt if enabled
+ if (m_regs[1] & SIO_WR1_TXINT_ENABLE)
+ set_interrupt(INT_TRANSMIT);
+
+ // reset the output buffer
+ m_outbuf = -1;
+ }
+
+ // ask the polling callback if there is data to receive
+ if (m_device->m_receive_poll_cb != NULL)
+ data = (*m_device->m_receive_poll_cb)(m_device, m_index);
+
+ // if we have buffered data, pull it
+ if (m_receive_inptr != m_receive_outptr)
+ {
+ data = m_receive_buffer[m_receive_outptr];
+ m_receive_outptr = (m_receive_outptr + 1) % ARRAY_LENGTH(m_receive_buffer);
+ }
+
+ // if we have data, receive it
+ if (data != -1)
+ {
+ VPRINTF(("serial_callback(%c): Receiving %02x\n", 'A' + m_index, data));
+
+ // if rx not enabled, just ignore it
+ if (!(m_regs[3] & SIO_WR3_RX_ENABLE))
+ {
+ VPRINTF((" (ignored because receive is disabled)\n"));
+ return;
+ }
+
+ // stash the data and update the status
+ m_inbuf = data;
+ m_status[0] |= SIO_RR0_RX_CHAR_AVAILABLE;
+
+ // update our interrupt state
+ switch (m_regs[1] & SIO_WR1_RXINT_MASK)
+ {
+ case SIO_WR1_RXINT_FIRST:
+ if (!m_int_on_next_rx)
+ break;
+
+ case SIO_WR1_RXINT_ALL_NOPARITY:
+ case SIO_WR1_RXINT_ALL_PARITY:
+ set_interrupt(INT_RECEIVE);
+ break;
+ }
+ m_int_on_next_rx = false;
+ }
+}
+
+
+
+//**************************************************************************
+// GLOBAL STUBS
+//**************************************************************************
+
+WRITE8_DEVICE_HANDLER( z80sio_c_w ) { downcast<z80sio_device *>(device)->control_write(offset & 1, data); }
+WRITE8_DEVICE_HANDLER( z80sio_d_w ) { downcast<z80sio_device *>(device)->data_write(offset & 1, data); }
+READ8_DEVICE_HANDLER( z80sio_c_r ) { return downcast<z80sio_device *>(device)->control_read(offset & 1); }
+READ8_DEVICE_HANDLER( z80sio_d_r ) { return downcast<z80sio_device *>(device)->data_read(offset & 1); }
+
+READ8_DEVICE_HANDLER( z80sio_get_dtr ) { return downcast<z80sio_device *>(device)->dtr(offset & 1); }
+READ8_DEVICE_HANDLER( z80sio_get_rts ) { return downcast<z80sio_device *>(device)->rts(offset & 1); }
+
+WRITE8_DEVICE_HANDLER( z80sio_set_cts ) { downcast<z80sio_device *>(device)->set_cts(offset & 1, data); }
+WRITE8_DEVICE_HANDLER( z80sio_set_dcd ) { downcast<z80sio_device *>(device)->set_dcd(offset & 1, data); }
+WRITE8_DEVICE_HANDLER( z80sio_receive_data ) { downcast<z80sio_device *>(device)->receive_data(offset & 1, data); }
+
+READ8_DEVICE_HANDLER( z80sio_cd_ba_r )
+{
+ switch (offset & 3)
+ {
+ case 0: return z80sio_d_r(device, 0);
+ case 1: return z80sio_d_r(device, 1);
+ case 2: return z80sio_c_r(device, 0);
+ case 3: return z80sio_c_r(device, 1);
+ }
+
+ return 0xff;
+}
+
+WRITE8_DEVICE_HANDLER( z80sio_cd_ba_w )
+{
+ switch (offset & 3)
+ {
+ case 0: z80sio_d_w(device, 0, data); break;
+ case 1: z80sio_d_w(device, 1, data); break;
+ case 2: z80sio_c_w(device, 0, data); break;
+ case 3: z80sio_c_w(device, 1, data); break;
+ }
+}
+
+READ8_DEVICE_HANDLER( z80sio_ba_cd_r )
+{
+ switch (offset & 3)
+ {
+ case 0: return z80sio_d_r(device, 0);
+ case 1: return z80sio_c_r(device, 0);
+ case 2: return z80sio_d_r(device, 1);
+ case 3: return z80sio_c_r(device, 1);
+ }
+
+ return 0xff;
+}
+
+WRITE8_DEVICE_HANDLER( z80sio_ba_cd_w )
+{
+ switch (offset & 3)
+ {
+ case 0: z80sio_d_w(device, 0, data); break;
+ case 1: z80sio_c_w(device, 0, data); break;
+ case 2: z80sio_d_w(device, 1, data); break;
+ case 3: z80sio_c_w(device, 1, data); break;
+ }
+}
diff --git a/trunk/src/emu/machine/z80sio.h b/trunk/src/emu/machine/z80sio.h
new file mode 100644
index 00000000000..c1141251036
--- /dev/null
+++ b/trunk/src/emu/machine/z80sio.h
@@ -0,0 +1,174 @@
+/***************************************************************************
+
+ Z80 SIO (Z8440) implementation
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#ifndef __Z80SIO_H__
+#define __Z80SIO_H__
+
+#include "cpu/z80/z80daisy.h"
+
+
+//**************************************************************************
+// DEVICE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_Z80SIO_ADD(_tag, _clock, _intrf) \
+ MCFG_DEVICE_ADD(_tag, Z80SIO, _clock) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> z80sio_interface
+
+struct z80sio_interface
+{
+ void (*m_irq_cb)(device_t *device, int state);
+ write8_device_func m_dtr_changed_cb;
+ write8_device_func m_rts_changed_cb;
+ write8_device_func m_break_changed_cb;
+ write8_device_func m_transmit_cb;
+ int (*m_receive_poll_cb)(device_t *device, int channel);
+};
+
+
+
+// ======================> z80sio_device
+
+class z80sio_device : public device_t,
+ public device_z80daisy_interface,
+ public z80sio_interface
+{
+public:
+ // construction/destruction
+ z80sio_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // control register I/O
+ UINT8 control_read(int ch) { return m_channel[ch].control_read(); }
+ void control_write(int ch, UINT8 data) { m_channel[ch].control_write(data); }
+
+ // data register I/O
+ UINT8 data_read(int ch) { return m_channel[ch].data_read(); }
+ void data_write(int ch, UINT8 data) { m_channel[ch].data_write(data); }
+
+ // communication line I/O
+ int dtr(int ch) { return m_channel[ch].dtr(); }
+ int rts(int ch) { return m_channel[ch].rts(); }
+ void set_cts(int ch, int state) { m_channel[ch].set_cts(state); }
+ void set_dcd(int ch, int state) { m_channel[ch].set_dcd(state); }
+ void receive_data(int ch, int data) { m_channel[ch].receive_data(data); }
+
+private:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_z80daisy_interface overrides
+ virtual int z80daisy_irq_state();
+ virtual int z80daisy_irq_ack();
+ virtual void z80daisy_irq_reti();
+
+ // internal helpers
+ void update_interrupt_state();
+
+ // a single SIO channel
+ class sio_channel
+ {
+ public:
+ sio_channel();
+
+ void start(z80sio_device *device, int index);
+ void reset();
+
+ UINT8 control_read();
+ UINT8 data_read();
+ void control_write(UINT8 data);
+ void data_write(UINT8 data);
+
+ int dtr();
+ int rts();
+ void set_cts(int state);
+ void set_dcd(int state);
+ void receive_data(int data);
+
+ private:
+ void set_interrupt(int type);
+ void clear_interrupt(int type);
+ attotime compute_time_per_character();
+
+ static TIMER_CALLBACK( static_change_input_line ) { reinterpret_cast<sio_channel *>(ptr)->change_input_line(param >> 1, param & 1); }
+ void change_input_line(int line, int state);
+
+ static TIMER_CALLBACK( static_serial_callback ) { reinterpret_cast<sio_channel *>(ptr)->serial_callback(); }
+ void serial_callback();
+
+ public:
+ UINT8 m_regs[8]; // 8 writeable registers
+
+ private:
+ z80sio_device *m_device; // pointer back to our device
+ int m_index; // our channel index
+ UINT8 m_status[4]; // 3 readable registers
+ int m_inbuf; // input buffer
+ int m_outbuf; // output buffer
+ bool m_int_on_next_rx; // interrupt on next rx?
+ emu_timer * m_receive_timer; // timer to clock data in
+ UINT8 m_receive_buffer[16]; // buffer for incoming data
+ UINT8 m_receive_inptr; // index of data coming in
+ UINT8 m_receive_outptr; // index of data going out
+ };
+
+ // internal state
+ sio_channel m_channel[2]; // 2 channels
+ UINT8 m_int_state[8]; // interrupt states
+
+ static const UINT8 k_int_priority[];
+};
+
+
+// device type definition
+extern const device_type Z80SIO;
+
+
+
+//**************************************************************************
+// CONTROL/DATA REGISTER READ/WRITE
+//**************************************************************************
+
+// register access (A1=C/_D A0=B/_A)
+READ8_DEVICE_HANDLER( z80sio_cd_ba_r );
+WRITE8_DEVICE_HANDLER( z80sio_cd_ba_w );
+
+// register access (A1=B/_A A0=C/_D)
+READ8_DEVICE_HANDLER( z80sio_ba_cd_r );
+WRITE8_DEVICE_HANDLER( z80sio_ba_cd_w );
+
+WRITE8_DEVICE_HANDLER( z80sio_c_w );
+READ8_DEVICE_HANDLER( z80sio_c_r );
+
+WRITE8_DEVICE_HANDLER( z80sio_d_w );
+READ8_DEVICE_HANDLER( z80sio_d_r );
+
+
+//**************************************************************************
+// CONTROL LINE READ/WRITE
+//**************************************************************************
+
+READ8_DEVICE_HANDLER( z80sio_get_dtr );
+READ8_DEVICE_HANDLER( z80sio_get_rts );
+WRITE8_DEVICE_HANDLER( z80sio_set_cts );
+WRITE8_DEVICE_HANDLER( z80sio_set_dcd );
+WRITE8_DEVICE_HANDLER( z80sio_receive_data );
+
+
+#endif
diff --git a/trunk/src/emu/machine/z80sti.c b/trunk/src/emu/machine/z80sti.c
new file mode 100644
index 00000000000..33647b1748a
--- /dev/null
+++ b/trunk/src/emu/machine/z80sti.c
@@ -0,0 +1,756 @@
+/***************************************************************************
+
+ Mostek MK3801 Serial Timer Interrupt Controller (Z80-STI) emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+/*
+
+ TODO:
+
+ - timers (other than delay mode)
+ - serial I/O
+ - reset behavior
+
+*/
+
+#include "emu.h"
+#include "z80sti.h"
+#include "cpu/z80/z80.h"
+#include "cpu/z80/z80daisy.h"
+
+
+
+// device type definition
+const device_type Z80STI = &device_creator<z80sti_device>;
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// registers
+enum
+{
+ Z80STI_REGISTER_IR = 0,
+ Z80STI_REGISTER_GPIP,
+ Z80STI_REGISTER_IPRB,
+ Z80STI_REGISTER_IPRA,
+ Z80STI_REGISTER_ISRB,
+ Z80STI_REGISTER_ISRA,
+ Z80STI_REGISTER_IMRB,
+ Z80STI_REGISTER_IMRA,
+ Z80STI_REGISTER_PVR,
+ Z80STI_REGISTER_TABC,
+ Z80STI_REGISTER_TBDR,
+ Z80STI_REGISTER_TADR,
+ Z80STI_REGISTER_UCR,
+ Z80STI_REGISTER_RSR,
+ Z80STI_REGISTER_TSR,
+ Z80STI_REGISTER_UDR
+};
+
+// variable registers
+enum
+{
+ Z80STI_REGISTER_IR_SCR = 0,
+ Z80STI_REGISTER_IR_TDDR,
+ Z80STI_REGISTER_IR_TCDR,
+ Z80STI_REGISTER_IR_AER,
+ Z80STI_REGISTER_IR_IERB,
+ Z80STI_REGISTER_IR_IERA,
+ Z80STI_REGISTER_IR_DDR,
+ Z80STI_REGISTER_IR_TCDC
+};
+
+// timers
+enum
+{
+ TIMER_A = 0,
+ TIMER_B,
+ TIMER_C,
+ TIMER_D,
+ TIMER_COUNT
+};
+
+// interrupt levels
+enum
+{
+ Z80STI_IR_P0 = 0,
+ Z80STI_IR_P1,
+ Z80STI_IR_P2,
+ Z80STI_IR_P3,
+ Z80STI_IR_TD,
+ Z80STI_IR_TC,
+ Z80STI_IR_P4,
+ Z80STI_IR_P5,
+ Z80STI_IR_TB,
+ Z80STI_IR_XE,
+ Z80STI_IR_XB,
+ Z80STI_IR_RE,
+ Z80STI_IR_RB,
+ Z80STI_IR_TA,
+ Z80STI_IR_P6,
+ Z80STI_IR_P7
+};
+
+// timer C/D control register
+const int Z80STI_TCDC_TARS = 0x80;
+const int Z80STI_TCDC_TBRS = 0x08;
+
+// interrupt vector register
+const int Z80STI_PVR_ISE = 0x08;
+const int Z80STI_PVR_VR4 = 0x10;
+
+// general purpose I/O interrupt levels
+static const int INT_LEVEL_GPIP[] =
+{
+ Z80STI_IR_P0, Z80STI_IR_P1, Z80STI_IR_P2, Z80STI_IR_P3, Z80STI_IR_P4, Z80STI_IR_P5, Z80STI_IR_P6, Z80STI_IR_P7
+};
+
+// timer interrupt levels
+static const int INT_LEVEL_TIMER[] =
+{
+ Z80STI_IR_TA, Z80STI_IR_TB, Z80STI_IR_TC, Z80STI_IR_TD
+};
+
+// interrupt vectors
+static const UINT8 INT_VECTOR[] =
+{
+ 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
+ 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e
+};
+
+// timer prescaler divisors
+static const int PRESCALER[] = { 0, 4, 10, 16, 50, 64, 100, 200 };
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// z80sti_device - constructor
+//-------------------------------------------------
+
+z80sti_device::z80sti_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, Z80STI, "Mostek MK3801", tag, owner, clock),
+ device_z80daisy_interface(mconfig, *this),
+ m_gpip(0),
+ m_aer(0),
+ m_ier(0),
+ m_ipr(0),
+ m_isr(0),
+ m_imr(0)
+{
+ for (int i = 0; i < 16; i++)
+ {
+ m_int_state[i] = 0;
+ }
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void z80sti_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const z80sti_interface *intf = reinterpret_cast<const z80sti_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<z80sti_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ m_rx_clock = m_tx_clock = 0;
+ memset(&m_out_int_cb, 0, sizeof(m_out_int_cb));
+ memset(&m_in_gpio_cb, 0, sizeof(m_in_gpio_cb));
+ memset(&m_out_gpio_cb, 0, sizeof(m_out_gpio_cb));
+ memset(&m_in_si_cb, 0, sizeof(m_in_si_cb));
+ memset(&m_out_so_cb, 0, sizeof(m_out_so_cb));
+ memset(&m_out_tao_cb, 0, sizeof(m_out_tao_cb));
+ memset(&m_out_tbo_cb, 0, sizeof(m_out_tbo_cb));
+ memset(&m_out_tco_cb, 0, sizeof(m_out_tco_cb));
+ memset(&m_out_tdo_cb, 0, sizeof(m_out_tdo_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void z80sti_device::device_start()
+{
+ // resolve callbacks
+ m_in_gpio_func.resolve(m_in_gpio_cb, *this);
+ m_out_gpio_func.resolve(m_out_gpio_cb, *this);
+ m_in_si_func.resolve(m_in_si_cb, *this);
+ m_out_so_func.resolve(m_out_so_cb, *this);
+ m_out_timer_func[TIMER_A].resolve(m_out_tao_cb, *this);
+ m_out_timer_func[TIMER_B].resolve(m_out_tbo_cb, *this);
+ m_out_timer_func[TIMER_C].resolve(m_out_tco_cb, *this);
+ m_out_timer_func[TIMER_D].resolve(m_out_tdo_cb, *this);
+ m_out_int_func.resolve(m_out_int_cb, *this);
+
+ // create the counter timers
+ m_timer[TIMER_A] = machine().scheduler().timer_alloc(FUNC(static_timer_count), (void *)this);
+ m_timer[TIMER_B] = machine().scheduler().timer_alloc(FUNC(static_timer_count), (void *)this);
+ m_timer[TIMER_C] = machine().scheduler().timer_alloc(FUNC(static_timer_count), (void *)this);
+ m_timer[TIMER_D] = machine().scheduler().timer_alloc(FUNC(static_timer_count), (void *)this);
+
+ // create serial receive clock timer
+ if (m_rx_clock > 0)
+ {
+ m_rx_timer = machine().scheduler().timer_alloc(FUNC(static_rx_tick), (void *)this);
+ m_rx_timer->adjust(attotime::zero, 0, attotime::from_hz(m_rx_clock));
+ }
+
+ // create serial transmit clock timer
+ if (m_tx_clock > 0)
+ {
+ m_tx_timer = machine().scheduler().timer_alloc(FUNC(static_tx_tick), (void *)this);
+ m_tx_timer->adjust(attotime::zero, 0, attotime::from_hz(m_tx_clock));
+ }
+
+ // register for state saving
+ save_item(NAME(m_gpip));
+ save_item(NAME(m_aer));
+ save_item(NAME(m_ddr));
+ save_item(NAME(m_ier));
+ save_item(NAME(m_ipr));
+ save_item(NAME(m_isr));
+ save_item(NAME(m_imr));
+ save_item(NAME(m_pvr));
+ save_item(NAME(m_int_state));
+ save_item(NAME(m_tabc));
+ save_item(NAME(m_tcdc));
+ save_item(NAME(m_tdr));
+ save_item(NAME(m_tmc));
+ save_item(NAME(m_to));
+ save_item(NAME(m_scr));
+ save_item(NAME(m_ucr));
+ save_item(NAME(m_rsr));
+ save_item(NAME(m_tsr));
+ save_item(NAME(m_udr));
+
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void z80sti_device::device_reset()
+{
+}
+
+
+
+//**************************************************************************
+// DAISY CHAIN INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// z80daisy_irq_state - get interrupt status
+//-------------------------------------------------
+
+int z80sti_device::z80daisy_irq_state()
+{
+ int state = 0, i;
+
+ // loop over all interrupt sources
+ for (i = 15; i >= 0; i--)
+ {
+ // if we're servicing a request, don't indicate more interrupts
+ if (m_int_state[i] & Z80_DAISY_IEO)
+ {
+ state |= Z80_DAISY_IEO;
+ break;
+ }
+
+ if (BIT(m_imr, i))
+ {
+ state |= m_int_state[i];
+ }
+ }
+
+ LOG(("Z80STI '%s' Interrupt State: %u\n", tag(), state));
+
+ return state;
+}
+
+
+//-------------------------------------------------
+// z80daisy_irq_ack - interrupt acknowledge
+//-------------------------------------------------
+
+int z80sti_device::z80daisy_irq_ack()
+{
+ int i;
+
+ // loop over all interrupt sources
+ for (i = 15; i >= 0; i--)
+ {
+ // find the first channel with an interrupt requested
+ if (m_int_state[i] & Z80_DAISY_INT)
+ {
+ UINT8 vector = (m_pvr & 0xe0) | INT_VECTOR[i];
+
+ // clear interrupt, switch to the IEO state, and update the IRQs
+ m_int_state[i] = Z80_DAISY_IEO;
+
+ // clear interrupt pending register bit
+ m_ipr &= ~(1 << i);
+
+ // set interrupt in-service register bit
+ m_isr |= (1 << i);
+
+ check_interrupts();
+
+ LOG(("Z80STI '%s' Interrupt Acknowledge Vector: %02x\n", tag(), vector));
+
+ return vector;
+ }
+ }
+
+ logerror("z80sti_irq_ack: failed to find an interrupt to ack!\n");
+
+ return 0;
+}
+
+
+//-------------------------------------------------
+// z80daisy_irq_reti - return from interrupt
+//-------------------------------------------------
+
+void z80sti_device::z80daisy_irq_reti()
+{
+ int i;
+
+ LOG(("Z80STI '%s' Return from Interrupt\n", tag()));
+
+ // loop over all interrupt sources
+ for (i = 15; i >= 0; i--)
+ {
+ // find the first channel with an IEO pending
+ if (m_int_state[i] & Z80_DAISY_IEO)
+ {
+ // clear the IEO state and update the IRQs
+ m_int_state[i] &= ~Z80_DAISY_IEO;
+
+ // clear interrupt in-service register bit
+ m_isr &= ~(1 << i);
+
+ check_interrupts();
+ return;
+ }
+ }
+
+ logerror("z80sti_irq_reti: failed to find an interrupt to clear IEO on!\n");
+}
+
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+//-------------------------------------------------
+// check_interrupts - set the interrupt request
+// line state
+//-------------------------------------------------
+
+void z80sti_device::check_interrupts()
+{
+ if (m_ipr & m_imr)
+ {
+ m_out_int_func(ASSERT_LINE);
+ }
+ else
+ {
+ m_out_int_func(CLEAR_LINE);
+ }
+}
+
+
+//-------------------------------------------------
+// take_interrupt - mark an interrupt pending
+//-------------------------------------------------
+
+void z80sti_device::take_interrupt(int level)
+{
+ // set interrupt pending register bit
+ m_ipr |= 1 << level;
+
+ // trigger interrupt
+ m_int_state[level] |= Z80_DAISY_INT;
+
+ check_interrupts();
+}
+
+
+//-------------------------------------------------
+// serial_receive - receive serial bit
+//-------------------------------------------------
+
+void z80sti_device::serial_receive()
+{
+}
+
+
+//-------------------------------------------------
+// serial_transmit - transmit serial bit
+//-------------------------------------------------
+
+void z80sti_device::serial_transmit()
+{
+}
+
+
+//-------------------------------------------------
+// read - register read
+//-------------------------------------------------
+
+UINT8 z80sti_device::read(offs_t offset)
+{
+ switch (offset & 0x0f)
+ {
+ case Z80STI_REGISTER_IR:
+ switch (m_pvr & 0x07)
+ {
+ case Z80STI_REGISTER_IR_SCR: return m_scr;
+ case Z80STI_REGISTER_IR_TDDR: return m_tmc[TIMER_D];
+ case Z80STI_REGISTER_IR_TCDR: return m_tmc[TIMER_C];
+ case Z80STI_REGISTER_IR_AER: return m_aer;
+ case Z80STI_REGISTER_IR_IERB: return m_ier & 0xff;
+ case Z80STI_REGISTER_IR_IERA: return m_ier >> 8;
+ case Z80STI_REGISTER_IR_DDR: return m_ddr;
+ case Z80STI_REGISTER_IR_TCDC: return m_tcdc;
+ }
+ break;
+
+ case Z80STI_REGISTER_GPIP: m_gpip = (m_in_gpio_func(0) & ~m_ddr) | (m_gpip & m_ddr); return m_gpip;
+ case Z80STI_REGISTER_IPRB: return m_ipr & 0xff;
+ case Z80STI_REGISTER_IPRA: return m_ipr >> 8;
+ case Z80STI_REGISTER_ISRB: return m_isr & 0xff;
+ case Z80STI_REGISTER_ISRA: return m_isr >> 8;
+ case Z80STI_REGISTER_IMRB: return m_imr & 0xff;
+ case Z80STI_REGISTER_IMRA: return m_imr >> 8;
+ case Z80STI_REGISTER_PVR: return m_pvr;
+ case Z80STI_REGISTER_TABC: return m_tabc;
+ case Z80STI_REGISTER_TBDR: return m_tmc[TIMER_B];
+ case Z80STI_REGISTER_TADR: return m_tmc[TIMER_A];
+ case Z80STI_REGISTER_UCR: return m_ucr;
+ case Z80STI_REGISTER_RSR: return m_rsr;
+ case Z80STI_REGISTER_TSR: return m_tsr;
+ case Z80STI_REGISTER_UDR: return m_udr;
+ }
+
+ return 0;
+}
+
+
+//-------------------------------------------------
+// write - register write
+//-------------------------------------------------
+
+void z80sti_device::write(offs_t offset, UINT8 data)
+{
+ switch (offset & 0x0f)
+ {
+ case Z80STI_REGISTER_IR:
+ switch (m_pvr & 0x07)
+ {
+ case Z80STI_REGISTER_IR_SCR:
+ LOG(("Z80STI '%s' Sync Character Register: %x\n", tag(), data));
+ m_scr = data;
+ break;
+
+ case Z80STI_REGISTER_IR_TDDR:
+ LOG(("Z80STI '%s' Timer D Data Register: %x\n", tag(), data));
+ m_tdr[TIMER_D] = data;
+ break;
+
+ case Z80STI_REGISTER_IR_TCDR:
+ LOG(("Z80STI '%s' Timer C Data Register: %x\n", tag(), data));
+ m_tdr[TIMER_C] = data;
+ break;
+
+ case Z80STI_REGISTER_IR_AER:
+ LOG(("Z80STI '%s' Active Edge Register: %x\n", tag(), data));
+ m_aer = data;
+ break;
+
+ case Z80STI_REGISTER_IR_IERB:
+ LOG(("Z80STI '%s' Interrupt Enable Register B: %x\n", tag(), data));
+ m_ier = (m_ier & 0xff00) | data;
+ check_interrupts();
+ break;
+
+ case Z80STI_REGISTER_IR_IERA:
+ LOG(("Z80STI '%s' Interrupt Enable Register A: %x\n", tag(), data));
+ m_ier = (data << 8) | (m_ier & 0xff);
+ check_interrupts();
+ break;
+
+ case Z80STI_REGISTER_IR_DDR:
+ LOG(("Z80STI '%s' Data Direction Register: %x\n", tag(), data));
+ m_ddr = data;
+ break;
+
+ case Z80STI_REGISTER_IR_TCDC:
+ {
+ int tcc = PRESCALER[(data >> 4) & 0x07];
+ int tdc = PRESCALER[data & 0x07];
+
+ m_tcdc = data;
+
+ LOG(("Z80STI '%s' Timer C Prescaler: %u\n", tag(), tcc));
+ LOG(("Z80STI '%s' Timer D Prescaler: %u\n", tag(), tdc));
+
+ if (tcc)
+ m_timer[TIMER_C]->adjust(attotime::from_hz(clock() / tcc), TIMER_C, attotime::from_hz(clock() / tcc));
+ else
+ m_timer[TIMER_C]->enable(false);
+
+ if (tdc)
+ m_timer[TIMER_D]->adjust(attotime::from_hz(clock() / tdc), TIMER_D, attotime::from_hz(clock() / tdc));
+ else
+ m_timer[TIMER_D]->enable(false);
+
+ if (BIT(data, 7))
+ {
+ LOG(("Z80STI '%s' Timer A Reset\n", tag()));
+ m_to[TIMER_A] = 0;
+
+ m_out_timer_func[TIMER_A](m_to[TIMER_A]);
+ }
+
+ if (BIT(data, 3))
+ {
+ LOG(("Z80STI '%s' Timer B Reset\n", tag()));
+ m_to[TIMER_B] = 0;
+
+ m_out_timer_func[TIMER_B](m_to[TIMER_B]);
+ }
+ }
+ break;
+ }
+ break;
+
+ case Z80STI_REGISTER_GPIP:
+ LOG(("Z80STI '%s' General Purpose I/O Register: %x\n", tag(), data));
+ m_gpip = data & m_ddr;
+ m_out_gpio_func(0, m_gpip);
+ break;
+
+ case Z80STI_REGISTER_IPRB:
+ {
+ int i;
+ LOG(("Z80STI '%s' Interrupt Pending Register B: %x\n", tag(), data));
+ m_ipr &= (m_ipr & 0xff00) | data;
+
+ for (i = 0; i < 16; i++)
+ {
+ if (!BIT(m_ipr, i) && (m_int_state[i] == Z80_DAISY_INT)) m_int_state[i] = 0;
+ }
+
+ check_interrupts();
+ }
+ break;
+
+ case Z80STI_REGISTER_IPRA:
+ {
+ int i;
+ LOG(("Z80STI '%s' Interrupt Pending Register A: %x\n", tag(), data));
+ m_ipr &= (data << 8) | (m_ipr & 0xff);
+
+ for (i = 0; i < 16; i++)
+ {
+ if (!BIT(m_ipr, i) && (m_int_state[i] == Z80_DAISY_INT)) m_int_state[i] = 0;
+ }
+
+ check_interrupts();
+ }
+ break;
+
+ case Z80STI_REGISTER_ISRB:
+ LOG(("Z80STI '%s' Interrupt In-Service Register B: %x\n", tag(), data));
+ m_isr &= (m_isr & 0xff00) | data;
+ break;
+
+ case Z80STI_REGISTER_ISRA:
+ LOG(("Z80STI '%s' Interrupt In-Service Register A: %x\n", tag(), data));
+ m_isr &= (data << 8) | (m_isr & 0xff);
+ break;
+
+ case Z80STI_REGISTER_IMRB:
+ LOG(("Z80STI '%s' Interrupt Mask Register B: %x\n", tag(), data));
+ m_imr = (m_imr & 0xff00) | data;
+ m_isr &= m_imr;
+ check_interrupts();
+ break;
+
+ case Z80STI_REGISTER_IMRA:
+ LOG(("Z80STI '%s' Interrupt Mask Register A: %x\n", tag(), data));
+ m_imr = (data << 8) | (m_imr & 0xff);
+ m_isr &= m_imr;
+ check_interrupts();
+ break;
+
+ case Z80STI_REGISTER_PVR:
+ LOG(("Z80STI '%s' Interrupt Vector: %02x\n", tag(), data & 0xe0));
+ LOG(("Z80STI '%s' IR Address: %01x\n", tag(), data & 0x07));
+ m_pvr = data;
+ break;
+
+ case Z80STI_REGISTER_TABC:
+ {
+ int tac = PRESCALER[(data >> 4) & 0x07];
+ int tbc = PRESCALER[data & 0x07];
+
+ m_tabc = data;
+
+ LOG(("Z80STI '%s' Timer A Prescaler: %u\n", tag(), tac));
+ LOG(("Z80STI '%s' Timer B Prescaler: %u\n", tag(), tbc));
+
+ if (tac)
+ m_timer[TIMER_A]->adjust(attotime::from_hz(clock() / tac), TIMER_A, attotime::from_hz(clock() / tac));
+ else
+ m_timer[TIMER_A]->enable(false);
+
+ if (tbc)
+ m_timer[TIMER_B]->adjust(attotime::from_hz(clock() / tbc), TIMER_B, attotime::from_hz(clock() / tbc));
+ else
+ m_timer[TIMER_B]->enable(false);
+ }
+ break;
+
+ case Z80STI_REGISTER_TBDR:
+ LOG(("Z80STI '%s' Timer B Data Register: %x\n", tag(), data));
+ m_tdr[TIMER_B] = data;
+ break;
+
+ case Z80STI_REGISTER_TADR:
+ LOG(("Z80STI '%s' Timer A Data Register: %x\n", tag(), data));
+ m_tdr[TIMER_A] = data;
+ break;
+#if 0
+ case Z80STI_REGISTER_UCR:
+ m_ucr = data;
+ break;
+
+ case Z80STI_REGISTER_RSR:
+ m_rsr = data;
+ break;
+
+ case Z80STI_REGISTER_TSR:
+ m_tsr = data;
+ break;
+
+ case Z80STI_REGISTER_UDR:
+ m_udr = data;
+ break;
+#endif
+ default:
+ LOG(("Z80STI '%s' Unsupported Register %x\n", tag(), offset & 0x0f));
+ }
+}
+
+
+//-------------------------------------------------
+// timer_count - timer count down
+//-------------------------------------------------
+
+void z80sti_device::timer_count(int index)
+{
+ if (m_tmc[index] == 0x01)
+ {
+ //LOG(("Z80STI '%s' Timer %c Expired\n", tag(), 'A' + index));
+
+ // toggle timer output signal
+ m_to[index] = !m_to[index];
+
+ m_out_timer_func[index](m_to[index]);
+
+ if (m_ier & (1 << INT_LEVEL_TIMER[index]))
+ {
+ LOG(("Z80STI '%s' Interrupt Pending for Timer %c\n", tag(), 'A' + index));
+
+ // signal timer elapsed interrupt
+ take_interrupt(INT_LEVEL_TIMER[index]);
+ }
+
+ // load timer main counter
+ m_tmc[index] = m_tdr[index];
+ }
+ else
+ {
+ // count down
+ m_tmc[index]--;
+ }
+}
+
+
+//-------------------------------------------------
+// gpip_input - GPIP input line write
+//-------------------------------------------------
+
+void z80sti_device::gpip_input(int bit, int state)
+{
+ int aer = BIT(m_aer, bit);
+ int old_state = BIT(m_gpip, bit);
+
+ if ((old_state ^ aer) && !(state ^ aer))
+ {
+ LOG(("Z80STI '%s' Edge Transition Detected on Bit: %u\n", tag(), bit));
+
+ if (m_ier & (1 << INT_LEVEL_GPIP[bit]))
+ {
+ LOG(("Z80STI '%s' Interrupt Pending for P%u\n", tag(), bit));
+
+ take_interrupt(INT_LEVEL_GPIP[bit]);
+ }
+ }
+
+ m_gpip = (m_gpip & ~(1 << bit)) | (state << bit);
+}
+
+
+
+//**************************************************************************
+// GLOBAL STUBS
+//**************************************************************************
+
+READ8_DEVICE_HANDLER( z80sti_r ) { return downcast<z80sti_device *>(device)->read(offset); }
+WRITE8_DEVICE_HANDLER( z80sti_w ) { downcast<z80sti_device *>(device)->write(offset, data); }
+
+WRITE_LINE_DEVICE_HANDLER( z80sti_rc_w ) { if (state) downcast<z80sti_device *>(device)->serial_receive(); }
+WRITE_LINE_DEVICE_HANDLER( z80sti_tc_w ) { if (state) downcast<z80sti_device *>(device)->serial_transmit(); }
+
+WRITE_LINE_DEVICE_HANDLER( z80sti_i0_w ) { downcast<z80sti_device *>(device)->gpip_input(0, state); }
+WRITE_LINE_DEVICE_HANDLER( z80sti_i1_w ) { downcast<z80sti_device *>(device)->gpip_input(1, state); }
+WRITE_LINE_DEVICE_HANDLER( z80sti_i2_w ) { downcast<z80sti_device *>(device)->gpip_input(2, state); }
+WRITE_LINE_DEVICE_HANDLER( z80sti_i3_w ) { downcast<z80sti_device *>(device)->gpip_input(3, state); }
+WRITE_LINE_DEVICE_HANDLER( z80sti_i4_w ) { downcast<z80sti_device *>(device)->gpip_input(4, state); }
+WRITE_LINE_DEVICE_HANDLER( z80sti_i5_w ) { downcast<z80sti_device *>(device)->gpip_input(5, state); }
+WRITE_LINE_DEVICE_HANDLER( z80sti_i6_w ) { downcast<z80sti_device *>(device)->gpip_input(6, state); }
+WRITE_LINE_DEVICE_HANDLER( z80sti_i7_w ) { downcast<z80sti_device *>(device)->gpip_input(7, state); }
diff --git a/trunk/src/emu/machine/z80sti.h b/trunk/src/emu/machine/z80sti.h
new file mode 100644
index 00000000000..e316949c038
--- /dev/null
+++ b/trunk/src/emu/machine/z80sti.h
@@ -0,0 +1,206 @@
+/**********************************************************************
+
+ Mostek MK3801 Serial Timer Interrupt Controller (Z80-STI) emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ TAO 1 |* \_/ | 40 Vcc
+ TBO 2 | | 39 RC
+ TCO 3 | | 38 SI
+ TDO 4 | | 37 SO
+ TCK 5 | | 36 TC
+ _M1 6 | | 35 A0
+ _RES 7 | | 34 A1
+ I0 8 | | 33 A2
+ I1 9 | | 32 A3
+ I2 10 | MK3801 | 31 _WR
+ I3 11 | Z80-STI | 30 _CE
+ I4 12 | | 29 _RD
+ I5 13 | | 28 D7
+ I6 14 | | 27 D6
+ I7 15 | | 26 D5
+ IEI 16 | | 25 D4
+ _INT 17 | | 24 D3
+ IEO 18 | | 23 D2
+ _IORQ 19 | | 22 D1
+ Vss 20 |_____________| 21 D0
+
+**********************************************************************/
+
+#ifndef __Z80STI__
+#define __Z80STI__
+
+#include "cpu/z80/z80daisy.h"
+
+
+//**************************************************************************
+// DEVICE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_Z80STI_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD((_tag), Z80STI, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define Z80STI_INTERFACE(name) const z80sti_interface (name) =
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> z80sti_interface
+
+struct z80sti_interface
+{
+ int m_rx_clock; // serial receive clock
+ int m_tx_clock; // serial transmit clock
+
+ // this gets called on each change of the _INT pin (pin 17)
+ devcb_write_line m_out_int_cb;
+
+ // this is called on each read of the GPIO pins
+ devcb_read8 m_in_gpio_cb;
+
+ // this is called on each write of the GPIO pins
+ devcb_write8 m_out_gpio_cb;
+
+ // this gets called for each read of the SI pin (pin 38)
+ devcb_read_line m_in_si_cb;
+
+ // this gets called for each change of the SO pin (pin 37)
+ devcb_write_line m_out_so_cb;
+
+ // this gets called for each change of the TAO pin (pin 1)
+ devcb_write_line m_out_tao_cb;
+
+ // this gets called for each change of the TBO pin (pin 2)
+ devcb_write_line m_out_tbo_cb;
+
+ // this gets called for each change of the TCO pin (pin 3)
+ devcb_write_line m_out_tco_cb;
+
+ // this gets called for each change of the TDO pin (pin 4)
+ devcb_write_line m_out_tdo_cb;
+};
+
+
+
+// ======================> z80sti_device
+
+class z80sti_device : public device_t,
+ public device_z80daisy_interface,
+ public z80sti_interface
+{
+public:
+ // construction/destruction
+ z80sti_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // I/O accessors
+ UINT8 read(offs_t offset);
+ void write(offs_t offset, UINT8 data);
+
+ // communication I/O
+ void serial_receive();
+ void serial_transmit();
+ void gpip_input(int bit, int state);
+
+private:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_z80daisy_interface overrides
+ virtual int z80daisy_irq_state();
+ virtual int z80daisy_irq_ack();
+ virtual void z80daisy_irq_reti();
+
+ // internal helpers
+ void check_interrupts();
+ void take_interrupt(int level);
+
+ void timer_count(int index);
+
+ static TIMER_CALLBACK( static_rx_tick ) { reinterpret_cast<z80sti_device *>(ptr)->serial_receive(); }
+ static TIMER_CALLBACK( static_tx_tick ) { reinterpret_cast<z80sti_device *>(ptr)->serial_transmit(); }
+
+ static TIMER_CALLBACK( static_timer_count ) { reinterpret_cast<z80sti_device *>(ptr)->timer_count(param); }
+
+ // device callbacks
+ devcb_resolved_read8 m_in_gpio_func;
+ devcb_resolved_write8 m_out_gpio_func;
+ devcb_resolved_read_line m_in_si_func;
+ devcb_resolved_write_line m_out_so_func;
+ devcb_resolved_write_line m_out_timer_func[4];
+ devcb_resolved_write_line m_out_int_func;
+
+ // I/O state
+ UINT8 m_gpip; // general purpose I/O register
+ UINT8 m_aer; // active edge register
+ UINT8 m_ddr; // data direction register
+
+ // interrupt state
+ UINT16 m_ier; // interrupt enable register
+ UINT16 m_ipr; // interrupt pending register
+ UINT16 m_isr; // interrupt in-service register
+ UINT16 m_imr; // interrupt mask register
+ UINT8 m_pvr; // interrupt vector register
+ int m_int_state[16]; // interrupt state
+
+ // timer state
+ UINT8 m_tabc; // timer A/B control register
+ UINT8 m_tcdc; // timer C/D control register
+ UINT8 m_tdr[4]; // timer data registers
+ UINT8 m_tmc[4]; // timer main counters
+ int m_to[4]; // timer out latch
+
+ // serial state
+ UINT8 m_scr; // synchronous character register
+ UINT8 m_ucr; // USART control register
+ UINT8 m_tsr; // transmitter status register
+ UINT8 m_rsr; // receiver status register
+ UINT8 m_udr; // USART data register
+
+ // timers
+ emu_timer *m_timer[4]; // counter timers
+ emu_timer *m_rx_timer; // serial receive timer
+ emu_timer *m_tx_timer; // serial transmit timer
+};
+
+
+// device type definition
+extern const device_type Z80STI;
+
+
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+// register access
+READ8_DEVICE_HANDLER( z80sti_r );
+WRITE8_DEVICE_HANDLER( z80sti_w );
+
+// receive clock
+WRITE_LINE_DEVICE_HANDLER( z80sti_rc_w );
+
+// transmit clock
+WRITE_LINE_DEVICE_HANDLER( z80sti_tc_w );
+
+// GPIP input lines
+WRITE_LINE_DEVICE_HANDLER( z80sti_i0_w );
+WRITE_LINE_DEVICE_HANDLER( z80sti_i1_w );
+WRITE_LINE_DEVICE_HANDLER( z80sti_i2_w );
+WRITE_LINE_DEVICE_HANDLER( z80sti_i3_w );
+WRITE_LINE_DEVICE_HANDLER( z80sti_i4_w );
+WRITE_LINE_DEVICE_HANDLER( z80sti_i5_w );
+WRITE_LINE_DEVICE_HANDLER( z80sti_i6_w );
+WRITE_LINE_DEVICE_HANDLER( z80sti_i7_w );
+
+
+#endif
diff --git a/trunk/src/emu/machine/z8536.c b/trunk/src/emu/machine/z8536.c
new file mode 100644
index 00000000000..979dce43e91
--- /dev/null
+++ b/trunk/src/emu/machine/z8536.c
@@ -0,0 +1,596 @@
+/**********************************************************************
+
+ Zilog Z8536 Counter/Timer and Parallel I/O emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "z8536.h"
+#include "machine/devhelpr.h"
+
+
+// device type definition
+const device_type Z8536 = &device_creator<z8536_device>;
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+// states
+enum
+{
+ STATE_RESET = -1,
+ STATE_0,
+ STATE_1
+};
+
+
+// ports
+enum
+{
+ PORT_C = 0,
+ PORT_B,
+ PORT_A,
+ CONTROL
+};
+
+
+// registers
+enum
+{
+ MASTER_INTERRUPT_CONTROL = 0,
+ MASTER_CONFIGURATION_CONTROL,
+ PORT_A_INTERRUPT_VECTOR,
+ PORT_B_INTERRUPT_VECTOR,
+ COUNTER_TIMER_INTERRUPT_VECTOR,
+ PORT_C_DATA_PATH_POLARITY,
+ PORT_C_DATA_DIRECTION,
+ PORT_C_SPECIAL_IO_CONTROL,
+ PORT_A_COMMAND_AND_STATUS,
+ PORT_B_COMMAND_AND_STATUS,
+ COUNTER_TIMER_1_COMMAND_AND_STATUS,
+ COUNTER_TIMER_2_COMMAND_AND_STATUS,
+ COUNTER_TIMER_3_COMMAND_AND_STATUS,
+ PORT_A_DATA,
+ PORT_B_DATA,
+ PORT_C_DATA,
+ COUNTER_TIMER_1_CURRENT_COUNT_MS_BYTE,
+ COUNTER_TIMER_1_CURRENT_COUNT_LS_BYTE,
+ COUNTER_TIMER_2_CURRENT_COUNT_MS_BYTE,
+ COUNTER_TIMER_2_CURRENT_COUNT_LS_BYTE,
+ COUNTER_TIMER_3_CURRENT_COUNT_MS_BYTE,
+ COUNTER_TIMER_3_CURRENT_COUNT_LS_BYTE,
+ COUNTER_TIMER_1_TIME_CONSTANT_MS_BYTE,
+ COUNTER_TIMER_1_TIME_CONSTANT_LS_BYTE,
+ COUNTER_TIMER_2_TIME_CONSTANT_MS_BYTE,
+ COUNTER_TIMER_2_TIME_CONSTANT_LS_BYTE,
+ COUNTER_TIMER_3_TIME_CONSTANT_MS_BYTE,
+ COUNTER_TIMER_3_TIME_CONSTANT_LS_BYTE,
+ COUNTER_TIMER_1_MODE_SPECIFICATION,
+ COUNTER_TIMER_2_MODE_SPECIFICATION,
+ COUNTER_TIMER_3_MODE_SPECIFICATION,
+ CURRENT_VECTOR,
+ PORT_A_MODE_SPECIFICATION,
+ PORT_A_HANDSHAKE_SPECIFICATION,
+ PORT_A_DATA_PATH_POLARITY,
+ PORT_A_DATA_DIRECTION,
+ PORT_A_SPECIAL_IO_CONTROL,
+ PORT_A_PATTERN_POLARITY,
+ PORT_A_PATTERN_TRANSITION,
+ PORT_A_PATTERN_MASK,
+ PORT_B_MODE_SPECIFICATION,
+ PORT_B_HANDSHAKE_SPECIFICATION,
+ PORT_B_DATA_PATH_POLARITY,
+ PORT_B_DATA_DIRECTION,
+ PORT_B_SPECIAL_IO_CONTROL,
+ PORT_B_PATTERN_POLARITY,
+ PORT_B_PATTERN_TRANSITION,
+ PORT_B_PATTERN_MASK
+};
+
+
+// counter/timer link control
+enum
+{
+ LC_INDEPENDENT = 0,
+ LC_CT1_GATES_CT2,
+ LC_CT1_TRIGGERS_CT2,
+ LC_CT1_COUNTS_CT2
+};
+
+
+// port type select
+enum
+{
+ PTS_BIT = 0,
+ PTS_INPUT,
+ PTS_OUTPUT,
+ PTS_BIDIRECTIONAL
+};
+
+
+// pattern mode specification
+enum
+{
+ PMS_DISABLE = 0,
+ PMS_AND,
+ PMS_OR,
+ PMS_VECTOR
+};
+
+
+// handshake specification
+enum
+{
+ HTS_INTERLOCKED = 0,
+ HTS_STROBED,
+ HTS_PULSED,
+ HTS_3_WIRE
+};
+
+
+// request/wait specification
+enum
+{
+ RWS_DISABLED = 0,
+ RWS_OUTPUT_WAIT,
+ RWS_INPUT_WAIT = 3,
+ RWS_SPECIAL_REQUEST,
+ RWS_OUTPUT_REQUEST,
+ RWS_INPUT_REQUEST = 7
+};
+
+
+// pattern specification
+enum
+{
+ BIT_MASKED_OFF = 0,
+ ANY_TRANSITION,
+ ZERO = 4,
+ ONE,
+ ONE_TO_ZERO,
+ ZERO_TO_ONE
+};
+
+
+// output duty cycle
+enum
+{
+ DCS_PULSE,
+ DCS_ONE_SHOT,
+ DCS_SQUARE_WAVE,
+ DCS_DO_NOT_USE
+};
+
+
+// master interrupt control register
+#define MICR_RESET 0x01 // reset
+#define MICR_RJA 0x02 // right justified address
+#define MICR_CT_VIS 0x04 // counter/timer vector includes status
+#define MICR_PB_VIS 0x08 // port B vector includes status
+#define MICR_PA_VIS 0x10 // port A vector includes status
+#define MICR_NV 0x20 // no vector
+#define MICR_DLC 0x40 // disable lower chain
+#define MICR_MIE 0x80 // master interrupt enable
+
+
+// master configuration control register
+#define MCCR_LC_MASK 0x03 // counter/timer link controls
+#define MCCR_PAE 0x04 // port A enable
+#define MCCR_PLC 0x08 // port link control
+#define MCCR_PCE_CT3E 0x10 // port C and counter/timer 3 enable
+#define MCCR_CT2E 0x20 // counter/timer 2 enable
+#define MCCR_CT1E 0x40 // counter/timer 1 enable
+#define MCCR_PBE 0x80 // port B enable
+
+
+// port mode specification registers
+#define PMS_LPM 0x01 // latch on pattern match
+#define PMS_PMS_MASK 0x06 // pattern mode specification
+#define PMS_IMO 0x08 // interrupt on match only
+#define PMS_SB 0x10 // single buffer
+#define PMS_ITB 0x20 // interrupt on two bytes
+#define PMS_PTS_MASK 0xc0 // port type select
+
+
+// port handshake specification registers
+#define PHS_DTS_MASK 0x07 // deskew time specification
+#define PHS_RWS_MASK 0x38 // request/wait specification
+#define PHS_HTS_MASK 0xc0 // handshake type specification
+
+
+// port command and status registers
+#define PCS_IOE 0x01 // interrupt on error
+#define PCS_PMF 0x02 // pattern match flag (read only)
+#define PCS_IRF 0x04 // input register full (read only)
+#define PCS_ORE 0x08 // output register empty (read only)
+#define PCS_ERR 0x10 // interrupt error (read only)
+#define PCS_IP 0x20 // interrupt pending
+#define PCS_IE 0x40 // interrupt enable
+#define PCS_IUS 0x80 // interrupt under service
+
+
+// counter/timer mode specification registers
+#define CTMS_DCS_MASK 0x03 // output duty cycle
+#define CTMS_REB 0x04 // retrigger enable bit
+#define CTMS_EDE 0x08 // external gate enable
+#define CTMS_ETE 0x10 // external trigger enable
+#define CTMS_ECE 0x20 // external count enable
+#define CTMS_EOE 0x40 // external output enable
+#define CTMS_CSC 0x80 // continuous single cycle
+
+
+// counter/timer command and status registers
+#define CTCS_CIP 0x01 // count in progress (read only)
+#define CTCS_TCB 0x02 // trigger command bit (write only - read returns 0)
+#define CTCS_GCB 0x04 // gate command bit
+#define CTCS_RCC 0x08 // read counter control (read/set only - cleared by reading CCR LSB)
+#define CTCS_ERR 0x10 // interrupt error (read only)
+#define CTCS_IP 0x20 // interrupt pending
+#define CTCS_IE 0x40 // interrupt enable
+#define CTCS_IUS 0x80 // interrupt under service
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// read_register - read from register
+//-------------------------------------------------
+
+inline UINT8 z8536_device::read_register(offs_t offset)
+{
+ UINT8 data = 0;
+
+ data = m_register[offset]; // HACK
+
+ switch (offset)
+ {
+ case PORT_A_DATA:
+ data = m_in_pa_func(0);
+ break;
+
+ case PORT_B_DATA:
+ data = m_in_pb_func(0);
+ break;
+
+ case PORT_C_DATA:
+ data = 0xf0 | (m_in_pc_func(0) & 0x0f);
+ break;
+
+ default:
+ logerror("Z8536 '%s' Unimplemented read from register %u\n", tag(), offset);
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// read_register - masked read from register
+//-------------------------------------------------
+
+inline UINT8 z8536_device::read_register(offs_t offset, UINT8 mask)
+{
+ return read_register(offset) & mask;
+}
+
+
+//-------------------------------------------------
+// write_register - write to register
+//-------------------------------------------------
+
+inline void z8536_device::write_register(offs_t offset, UINT8 data)
+{
+ switch (offset)
+ {
+ case MASTER_INTERRUPT_CONTROL:
+ if (data & MICR_RESET)
+ {
+ device_reset();
+ }
+ else if (m_state == STATE_RESET)
+ {
+ m_state = STATE_0;
+ }
+ break;
+
+ case PORT_A_DATA:
+ m_out_pa_func(0, data);
+ break;
+
+ case PORT_B_DATA:
+ m_out_pb_func(0, data);
+ break;
+
+ case PORT_C_DATA:
+ {
+ UINT8 mask = (data & 0xf0) | (data >> 4);
+
+ m_output[PORT_C] = (m_output[PORT_C] & mask) | ((data & 0x0f) & (mask ^ 0xff));
+
+ m_out_pc_func(0, m_output[PORT_C]);
+ }
+ break;
+
+ default:
+ logerror("Z8536 '%s' Unimplemented write %02x to register %u\n", tag(), data, offset);
+ }
+
+ m_register[offset] = data; // HACK
+}
+
+
+//-------------------------------------------------
+// write_register - masked write to register
+//-------------------------------------------------
+
+inline void z8536_device::write_register(offs_t offset, UINT8 data, UINT8 mask)
+{
+ UINT8 combined_data = (data & mask) | (m_register[offset] & (mask ^ 0xff));
+
+ write_register(offset, combined_data);
+}
+
+
+//-------------------------------------------------
+// count -
+//-------------------------------------------------
+
+inline void z8536_device::count(device_timer_id id)
+{
+}
+
+
+//-------------------------------------------------
+// trigger -
+//-------------------------------------------------
+
+inline void z8536_device::trigger(device_timer_id id)
+{
+}
+
+
+//-------------------------------------------------
+// gate -
+//-------------------------------------------------
+
+inline void z8536_device::gate(device_timer_id id)
+{
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// z8536_device - constructor
+//-------------------------------------------------
+
+z8536_device::z8536_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, Z8536, "Zilog Z8536", tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void z8536_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const z8536_interface *intf = reinterpret_cast<const z8536_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<z8536_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_out_int_cb, 0, sizeof(m_out_int_cb));
+ memset(&m_in_pa_cb, 0, sizeof(m_in_pa_cb));
+ memset(&m_out_pa_cb, 0, sizeof(m_out_pa_cb));
+ memset(&m_in_pb_cb, 0, sizeof(m_in_pb_cb));
+ memset(&m_out_pb_cb, 0, sizeof(m_out_pb_cb));
+ memset(&m_in_pc_cb, 0, sizeof(m_in_pc_cb));
+ memset(&m_out_pc_cb, 0, sizeof(m_out_pc_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void z8536_device::device_start()
+{
+ // allocate timers
+ m_timer[TIMER_1] = timer_alloc(TIMER_1);
+ m_timer[TIMER_2] = timer_alloc(TIMER_2);
+ m_timer[TIMER_3] = timer_alloc(TIMER_3);
+
+ // resolve callbacks
+ m_out_int_func.resolve(m_out_int_cb, *this);
+ m_in_pa_func.resolve(m_in_pa_cb, *this);
+ m_out_pa_func.resolve(m_out_pa_cb, *this);
+ m_in_pb_func.resolve(m_in_pb_cb, *this);
+ m_out_pb_func.resolve(m_out_pb_cb, *this);
+ m_in_pc_func.resolve(m_in_pc_cb, *this);
+ m_out_pc_func.resolve(m_out_pc_cb, *this);
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific reset
+//-------------------------------------------------
+
+void z8536_device::device_reset()
+{
+ m_state = STATE_RESET;
+
+ for (int i = 0; i < 48; i++)
+ {
+ m_register[i] = 0;
+ }
+
+ m_register[MASTER_INTERRUPT_CONTROL] = MICR_RESET;
+ m_pointer = 0;
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void z8536_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case TIMER_1:
+ count(TIMER_1);
+ break;
+
+ case TIMER_2:
+ count(TIMER_2);
+ break;
+
+ case TIMER_3:
+ count(TIMER_3);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// read - register read
+//-------------------------------------------------
+
+READ8_MEMBER( z8536_device::read )
+{
+ UINT8 data = 0;
+
+ if (m_state == STATE_RESET)
+ {
+ // read RESET bit
+ data = read_register(m_pointer, 0x01);
+ }
+ else
+ {
+ switch (offset & 0x03)
+ {
+ case PORT_C:
+ data = read_register(PORT_C_DATA);
+ break;
+
+ case PORT_B:
+ data = read_register(PORT_B_DATA);
+ break;
+
+ case PORT_A:
+ data = read_register(PORT_A_DATA);
+ break;
+
+ case CONTROL:
+ switch (m_state)
+ {
+ case STATE_1:
+ m_state = STATE_0;
+ // fallthru
+ case STATE_0:
+ data = read_register(m_pointer);
+ break;
+ }
+ break;
+ }
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// write - register write
+//-------------------------------------------------
+
+WRITE8_MEMBER( z8536_device::write )
+{
+ if (m_state == STATE_RESET)
+ {
+ // write RESET bit
+ write_register(m_pointer, data, 0x01);
+ }
+ else
+ {
+ switch (offset & 0x03)
+ {
+ case PORT_C:
+ write_register(PORT_C_DATA, data);
+ break;
+
+ case PORT_B:
+ write_register(PORT_B_DATA, data);
+ break;
+
+ case PORT_A:
+ write_register(PORT_A_DATA, data);
+ break;
+
+ case CONTROL:
+ switch (m_state)
+ {
+ case STATE_0:
+ m_pointer = data;
+ m_state = STATE_1;
+ break;
+
+ case STATE_1:
+ write_register(m_pointer, data);
+ m_state = STATE_0;
+ }
+ break;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// intack_w - interrupt acknowledge
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( z8536_device::intack_w )
+{
+}
+
+
+//-------------------------------------------------
+// pb*_w - port B bits 0-7 write
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( z8536_device::pb0_w ) { }
+WRITE_LINE_MEMBER( z8536_device::pb1_w ) { }
+WRITE_LINE_MEMBER( z8536_device::pb2_w ) { }
+WRITE_LINE_MEMBER( z8536_device::pb3_w ) { }
+WRITE_LINE_MEMBER( z8536_device::pb4_w ) { }
+WRITE_LINE_MEMBER( z8536_device::pb5_w ) { }
+WRITE_LINE_MEMBER( z8536_device::pb6_w ) { }
+WRITE_LINE_MEMBER( z8536_device::pb7_w ) { }
+
+
+//-------------------------------------------------
+// pc*_w - port C bits 0-3 write
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( z8536_device::pc0_w ) { }
+WRITE_LINE_MEMBER( z8536_device::pc1_w ) { }
+WRITE_LINE_MEMBER( z8536_device::pc2_w ) { }
+WRITE_LINE_MEMBER( z8536_device::pc3_w ) { }
diff --git a/trunk/src/emu/machine/z8536.h b/trunk/src/emu/machine/z8536.h
new file mode 100644
index 00000000000..10862269ade
--- /dev/null
+++ b/trunk/src/emu/machine/z8536.h
@@ -0,0 +1,159 @@
+/**********************************************************************
+
+ Zilog Z8536 Counter/Timer and Parallel I/O emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ D4 1 |* \_/ | 40 D3
+ D5 2 | | 39 D2
+ D6 3 | | 38 D1
+ D7 4 | | 37 D0
+ _RD 5 | | 36 _CE
+ _WR 6 | | 35 A1
+ GND 7 | | 34 A0
+ PB0 8 | | 33 PA0
+ PB1 9 | | 32 PA1
+ PB2 10 | Z8536 | 31 PA2
+ PB3 11 | | 30 PA3
+ PB4 12 | | 29 PA4
+ PB5 13 | | 28 PA5
+ PB6 14 | | 27 PA6
+ PB7 15 | | 26 PA7
+ PCLK 16 | | 25 _INTACK
+ IEI 17 | | 24 _INT
+ IEO 18 | | 23 +5 V
+ PC0 19 | | 22 PC3
+ PC1 20 |_____________| 21 PC2
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __Z8536__
+#define __Z8536__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_Z8536_ADD(_tag, _clock, _intrf) \
+ MCFG_DEVICE_ADD(_tag, Z8536, _clock) \
+ MCFG_DEVICE_CONFIG(_intrf)
+
+#define Z8536_INTERFACE(name) \
+ const z8536_interface (name)=
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> z8536_interface
+
+struct z8536_interface
+{
+ devcb_write_line m_out_int_cb;
+
+ devcb_read8 m_in_pa_cb;
+ devcb_write8 m_out_pa_cb;
+
+ devcb_read8 m_in_pb_cb;
+ devcb_write8 m_out_pb_cb;
+
+ devcb_read8 m_in_pc_cb;
+ devcb_write8 m_out_pc_cb;
+};
+
+
+// ======================> z8536_device
+
+class z8536_device : public device_t,
+ public z8536_interface
+{
+public:
+ // construction/destruction
+ z8536_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_READ8_MEMBER( read );
+ DECLARE_WRITE8_MEMBER( write );
+
+ DECLARE_WRITE_LINE_MEMBER( intack_w );
+
+ DECLARE_WRITE_LINE_MEMBER( pb0_w );
+ DECLARE_WRITE_LINE_MEMBER( pb1_w );
+ DECLARE_WRITE_LINE_MEMBER( pb2_w );
+ DECLARE_WRITE_LINE_MEMBER( pb3_w );
+ DECLARE_WRITE_LINE_MEMBER( pb4_w );
+ DECLARE_WRITE_LINE_MEMBER( pb5_w );
+ DECLARE_WRITE_LINE_MEMBER( pb6_w );
+ DECLARE_WRITE_LINE_MEMBER( pb7_w );
+ DECLARE_WRITE_LINE_MEMBER( pc0_w );
+ DECLARE_WRITE_LINE_MEMBER( pc1_w );
+ DECLARE_WRITE_LINE_MEMBER( pc2_w );
+ DECLARE_WRITE_LINE_MEMBER( pc3_w );
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+private:
+ static const device_timer_id TIMER_1 = 0;
+ static const device_timer_id TIMER_2 = 1;
+ static const device_timer_id TIMER_3 = 2;
+
+ inline UINT8 read_register(offs_t offset);
+ inline UINT8 read_register(offs_t offset, UINT8 mask);
+ inline void write_register(offs_t offset, UINT8 data);
+ inline void write_register(offs_t offset, UINT8 data, UINT8 mask);
+
+ inline void count(device_timer_id id);
+ inline void trigger(device_timer_id id);
+ inline void gate(device_timer_id id);
+
+ devcb_resolved_write_line m_out_int_func;
+
+ devcb_resolved_read8 m_in_pa_func;
+ devcb_resolved_write8 m_out_pa_func;
+
+ devcb_resolved_read8 m_in_pb_func;
+ devcb_resolved_write8 m_out_pb_func;
+
+ devcb_resolved_read8 m_in_pc_func;
+ devcb_resolved_write8 m_out_pc_func;
+
+ int m_state;
+ UINT8 m_register[48];
+ UINT8 m_pointer;
+ UINT8 m_input[3];
+ UINT8 m_output[3];
+ UINT8 m_buffer[3];
+
+ // timers
+ emu_timer *m_timer[3];
+};
+
+
+// device type definition
+extern const device_type Z8536;
+
+
+
+#endif
diff --git a/trunk/src/emu/mame.c b/trunk/src/emu/mame.c
new file mode 100644
index 00000000000..c867895d805
--- /dev/null
+++ b/trunk/src/emu/mame.c
@@ -0,0 +1,439 @@
+/***************************************************************************
+
+ mame.c
+
+ Controls execution of the core MAME system.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+****************************************************************************
+
+ Since there has been confusion in the past over the order of
+ initialization and other such things, here it is, all spelled out
+ as of January, 2008:
+
+ main()
+ - does platform-specific init
+ - calls mame_execute() [mame.c]
+
+ mame_execute() [mame.c]
+ - calls mame_validitychecks() [validity.c] to perform validity checks on all compiled drivers
+ - begins resource tracking (level 1)
+ - calls create_machine [mame.c] to initialize the running_machine structure
+ - calls init_machine() [mame.c]
+
+ init_machine() [mame.c]
+ - calls fileio_init() [fileio.c] to initialize file I/O info
+ - calls config_init() [config.c] to initialize configuration system
+ - calls input_init() [input.c] to initialize the input system
+ - calls output_init() [output.c] to initialize the output system
+ - calls state_init() [state.c] to initialize save state system
+ - calls state_save_allow_registration() [state.c] to allow registrations
+ - calls palette_init() [palette.c] to initialize palette system
+ - calls render_init() [render.c] to initialize the rendering system
+ - calls ui_init() [ui.c] to initialize the user interface
+ - calls generic_machine_init() [machine/generic.c] to initialize generic machine structures
+ - calls generic_video_init() [video/generic.c] to initialize generic video structures
+ - calls generic_sound_init() [audio/generic.c] to initialize generic sound structures
+ - calls timer_init() [timer.c] to reset the timer system
+ - calls osd_init() [osdepend.h] to do platform-specific initialization
+ - calls input_port_init() [inptport.c] to set up the input ports
+ - calls rom_init() [romload.c] to load the game's ROMs
+ - calls memory_init() [memory.c] to process the game's memory maps
+ - calls watchdog_init() [watchdog.c] to initialize the watchdog system
+ - calls the driver's DRIVER_INIT callback
+ - calls device_list_start() [devintrf.c] to start any devices
+ - calls video_init() [video.c] to start the video system
+ - calls tilemap_init() [tilemap.c] to start the tilemap system
+ - calls crosshair_init() [crsshair.c] to configure the crosshairs
+ - calls sound_init() [sound.c] to start the audio system
+ - calls debugger_init() [debugger.c] to set up the debugger
+ - calls the driver's MACHINE_START, SOUND_START, and VIDEO_START callbacks
+ - calls cheat_init() [cheat.c] to initialize the cheat system
+ - calls image_init() [image.c] to initialize the image system
+
+ - calls config_load_settings() [config.c] to load the configuration file
+ - calls nvram_load [machine/generic.c] to load NVRAM
+ - calls ui_display_startup_screens() [ui.c] to display the the startup screens
+ - begins resource tracking (level 2)
+ - calls soft_reset() [mame.c] to reset all systems
+
+ -------------------( at this point, we're up and running )----------------------
+
+ - calls scheduler->timeslice() [schedule.c] over and over until we exit
+ - ends resource tracking (level 2), freeing all auto_mallocs and timers
+ - calls the nvram_save() [machine/generic.c] to save NVRAM
+ - calls config_save_settings() [config.c] to save the game's configuration
+ - calls all registered exit routines [mame.c]
+ - ends resource tracking (level 1), freeing all auto_mallocs and timers
+
+ - exits the program
+
+***************************************************************************/
+
+#include "emu.h"
+#include "emuopts.h"
+#include "osdepend.h"
+#include "config.h"
+#include "debugger.h"
+#include "image.h"
+#include "profiler.h"
+#include "render.h"
+#include "cheat.h"
+#include "ui.h"
+#include "uimenu.h"
+#include "uiinput.h"
+#include "crsshair.h"
+#include "validity.h"
+#include "debug/debugcon.h"
+
+#include <time.h>
+
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+/* started empty? */
+static bool started_empty;
+
+static bool print_verbose = false;
+
+static running_machine *global_machine;
+
+/* output channels */
+static output_callback_func output_cb[OUTPUT_CHANNEL_COUNT];
+static void *output_cb_param[OUTPUT_CHANNEL_COUNT];
+
+/***************************************************************************
+ CORE IMPLEMENTATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ mame_is_valid_machine - return true if the
+ given machine is valid
+-------------------------------------------------*/
+
+int mame_is_valid_machine(running_machine &machine)
+{
+ return (&machine == global_machine);
+}
+
+
+/*-------------------------------------------------
+ mame_execute - run the core emulation
+-------------------------------------------------*/
+
+int mame_execute(emu_options &options, osd_interface &osd)
+{
+ bool firstgame = true;
+ bool firstrun = true;
+
+ // extract the verbose printing option
+ if (options.verbose())
+ print_verbose = true;
+
+ // loop across multiple hard resets
+ bool exit_pending = false;
+ int error = MAMERR_NONE;
+ while (error == MAMERR_NONE && !exit_pending)
+ {
+ // if no driver, use the internal empty driver
+ const game_driver *system = options.system();
+ if (system == NULL)
+ {
+ system = &GAME_NAME(___empty);
+ if (firstgame)
+ started_empty = true;
+ }
+
+ // otherwise, perform validity checks before anything else
+ else
+ validate_drivers(options, system);
+
+ firstgame = false;
+
+ // parse any INI files as the first thing
+ if (options.read_config())
+ {
+ options.revert(OPTION_PRIORITY_INI);
+ astring errors;
+ options.parse_standard_inis(errors);
+ }
+
+ // create the machine configuration
+ machine_config config(*system, options);
+
+ // create the machine structure and driver
+ running_machine machine(config, osd, started_empty);
+
+ // looooong term: remove this
+ global_machine = &machine;
+
+ // run the machine
+ error = machine.run(firstrun);
+ firstrun = false;
+
+ // check the state of the machine
+ if (machine.new_driver_pending())
+ {
+ options.set_system_name(machine.new_driver_name());
+ firstrun = true;
+ }
+ if (machine.exit_pending())
+ exit_pending = true;
+
+ // machine will go away when we exit scope
+ global_machine = NULL;
+ }
+
+ // return an error
+ return error;
+}
+
+
+/***************************************************************************
+ OUTPUT MANAGEMENT
+***************************************************************************/
+
+/*-------------------------------------------------
+ mame_set_output_channel - configure an output
+ channel
+-------------------------------------------------*/
+
+void mame_set_output_channel(output_channel channel, output_callback_func callback, void *param, output_callback_func *prevcb, void **prevparam)
+{
+ assert(channel < OUTPUT_CHANNEL_COUNT);
+ assert(callback != NULL);
+
+ /* return the originals if requested */
+ if (prevcb != NULL)
+ *prevcb = output_cb[channel];
+ if (prevparam != NULL)
+ *prevparam = output_cb_param[channel];
+
+ /* set the new ones */
+ output_cb[channel] = callback;
+ output_cb_param[channel] = param;
+}
+
+
+/*-------------------------------------------------
+ mame_file_output_callback - default callback
+ for file output
+-------------------------------------------------*/
+
+void mame_file_output_callback(void *param, const char *format, va_list argptr)
+{
+ vfprintf((FILE *)param, format, argptr);
+}
+
+
+/*-------------------------------------------------
+ mame_null_output_callback - default callback
+ for no output
+-------------------------------------------------*/
+
+void mame_null_output_callback(void *param, const char *format, va_list argptr)
+{
+}
+
+
+/*-------------------------------------------------
+ mame_printf_error - output an error to the
+ appropriate callback
+-------------------------------------------------*/
+
+void mame_printf_error(const char *format, ...)
+{
+ va_list argptr;
+
+ /* by default, we go to stderr */
+ if (output_cb[OUTPUT_CHANNEL_ERROR] == NULL)
+ {
+ output_cb[OUTPUT_CHANNEL_ERROR] = mame_file_output_callback;
+ output_cb_param[OUTPUT_CHANNEL_ERROR] = stderr;
+ }
+
+ /* do the output */
+ va_start(argptr, format);
+ (*output_cb[OUTPUT_CHANNEL_ERROR])(output_cb_param[OUTPUT_CHANNEL_ERROR], format, argptr);
+ va_end(argptr);
+}
+
+
+/*-------------------------------------------------
+ mame_printf_warning - output a warning to the
+ appropriate callback
+-------------------------------------------------*/
+
+void mame_printf_warning(const char *format, ...)
+{
+ va_list argptr;
+
+ /* by default, we go to stderr */
+ if (output_cb[OUTPUT_CHANNEL_WARNING] == NULL)
+ {
+ output_cb[OUTPUT_CHANNEL_WARNING] = mame_file_output_callback;
+ output_cb_param[OUTPUT_CHANNEL_WARNING] = stderr;
+ }
+
+ /* do the output */
+ va_start(argptr, format);
+ (*output_cb[OUTPUT_CHANNEL_WARNING])(output_cb_param[OUTPUT_CHANNEL_WARNING], format, argptr);
+ va_end(argptr);
+}
+
+
+/*-------------------------------------------------
+ mame_printf_info - output info text to the
+ appropriate callback
+-------------------------------------------------*/
+
+void mame_printf_info(const char *format, ...)
+{
+ va_list argptr;
+
+ /* by default, we go to stdout */
+ if (output_cb[OUTPUT_CHANNEL_INFO] == NULL)
+ {
+ output_cb[OUTPUT_CHANNEL_INFO] = mame_file_output_callback;
+ output_cb_param[OUTPUT_CHANNEL_INFO] = stdout;
+ }
+
+ /* do the output */
+ va_start(argptr, format);
+ (*output_cb[OUTPUT_CHANNEL_INFO])(output_cb_param[OUTPUT_CHANNEL_INFO], format, argptr);
+ va_end(argptr);
+}
+
+
+/*-------------------------------------------------
+ mame_printf_verbose - output verbose text to
+ the appropriate callback
+-------------------------------------------------*/
+
+void mame_printf_verbose(const char *format, ...)
+{
+ va_list argptr;
+
+ /* if we're not verbose, skip it */
+ if (!print_verbose)
+ return;
+
+ /* by default, we go to stdout */
+ if (output_cb[OUTPUT_CHANNEL_VERBOSE] == NULL)
+ {
+ output_cb[OUTPUT_CHANNEL_VERBOSE] = mame_file_output_callback;
+ output_cb_param[OUTPUT_CHANNEL_VERBOSE] = stdout;
+ }
+
+ /* do the output */
+ va_start(argptr, format);
+ (*output_cb[OUTPUT_CHANNEL_VERBOSE])(output_cb_param[OUTPUT_CHANNEL_VERBOSE], format, argptr);
+ va_end(argptr);
+}
+
+
+/*-------------------------------------------------
+ mame_printf_debug - output debug text to the
+ appropriate callback
+-------------------------------------------------*/
+
+void mame_printf_debug(const char *format, ...)
+{
+ va_list argptr;
+
+ /* by default, we go to stderr */
+ if (output_cb[OUTPUT_CHANNEL_DEBUG] == NULL)
+ {
+#ifdef MAME_DEBUG
+ output_cb[OUTPUT_CHANNEL_DEBUG] = mame_file_output_callback;
+ output_cb_param[OUTPUT_CHANNEL_DEBUG] = stdout;
+#else
+ output_cb[OUTPUT_CHANNEL_DEBUG] = mame_null_output_callback;
+ output_cb_param[OUTPUT_CHANNEL_DEBUG] = NULL;
+#endif
+ }
+
+ /* do the output */
+ va_start(argptr, format);
+ (*output_cb[OUTPUT_CHANNEL_DEBUG])(output_cb_param[OUTPUT_CHANNEL_DEBUG], format, argptr);
+ va_end(argptr);
+}
+
+
+/*-------------------------------------------------
+ mame_printf_log - output log text to the
+ appropriate callback
+-------------------------------------------------*/
+
+#ifdef UNUSED_FUNCTION
+void mame_printf_log(const char *format, ...)
+{
+ va_list argptr;
+
+ /* by default, we go to stderr */
+ if (output_cb[OUTPUT_CHANNEL_LOG] == NULL)
+ {
+ output_cb[OUTPUT_CHANNEL_LOG] = mame_file_output_callback;
+ output_cb_param[OUTPUT_CHANNEL_LOG] = stderr;
+ }
+
+ /* do the output */
+ va_start(argptr, format);
+ (*output_cb[OUTPUT_CHANNEL_LOG])(output_cb_param[OUTPUT_CHANNEL_LOG], format, argptr);
+ va_end(argptr);
+}
+#endif
+
+
+/***************************************************************************
+ MISCELLANEOUS
+***************************************************************************/
+
+/*-------------------------------------------------
+ popmessage - pop up a user-visible message
+-------------------------------------------------*/
+
+void CLIB_DECL popmessage(const char *format, ...)
+{
+ // if the format is NULL, it is a signal to clear the popmessage
+ if (format == NULL)
+ ui_popup_time(0, " ");
+
+ // otherwise, generate the buffer and call the UI to display the message
+ else
+ {
+ astring temp;
+ va_list arg;
+
+ // dump to the buffer
+ va_start(arg, format);
+ temp.vprintf(format, arg);
+ va_end(arg);
+
+ // pop it in the UI
+ ui_popup_time(temp.len() / 40 + 2, "%s", temp.cstr());
+ }
+}
+
+
+/*-------------------------------------------------
+ logerror - log to the debugger and any other
+ OSD-defined output streams
+-------------------------------------------------*/
+
+void CLIB_DECL logerror(const char *format, ...)
+{
+ if (global_machine != NULL)
+ {
+ va_list arg;
+ va_start(arg, format);
+ global_machine->vlogerror(format, arg);
+ va_end(arg);
+ }
+}
+
diff --git a/trunk/src/emu/mame.h b/trunk/src/emu/mame.h
new file mode 100644
index 00000000000..081b1e7a421
--- /dev/null
+++ b/trunk/src/emu/mame.h
@@ -0,0 +1,166 @@
+/***************************************************************************
+
+ mame.h
+
+ Controls execution of the core MAME system.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __EMU_H__
+#error Dont include this file directly; include emu.h instead.
+#endif
+
+#ifndef __MAME_H__
+#define __MAME_H__
+
+#include <time.h>
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// return values from run_game
+enum
+{
+ MAMERR_NONE = 0, /* no error */
+ MAMERR_FAILED_VALIDITY = 1, /* failed validity checks */
+ MAMERR_MISSING_FILES = 2, /* missing files */
+ MAMERR_FATALERROR = 3, /* some other fatal error */
+ MAMERR_DEVICE = 4, /* device initialization error (MESS-specific) */
+ MAMERR_NO_SUCH_GAME = 5, /* game was specified but doesn't exist */
+ MAMERR_INVALID_CONFIG = 6, /* some sort of error in configuration */
+ MAMERR_IDENT_NONROMS = 7, /* identified all non-ROM files */
+ MAMERR_IDENT_PARTIAL = 8, /* identified some files but not all */
+ MAMERR_IDENT_NONE = 9 /* identified no files */
+};
+
+
+// MESS vs. MAME abstractions
+#ifndef MESS
+#define APPNAME "MAME"
+#define APPNAME_LOWER "mame"
+#define CONFIGNAME "mame"
+#define APPLONGNAME "M.A.M.E."
+#define FULLLONGNAME "Multiple Arcade Machine Emulator"
+#define CAPGAMENOUN "GAME"
+#define CAPSTARTGAMENOUN "Game"
+#define GAMENOUN "game"
+#define GAMESNOUN "games"
+#define COPYRIGHT "Copyright Nicola Salmoria\nand the MAME team\nhttp://mamedev.org"
+#define COPYRIGHT_INFO "Copyright Nicola Salmoria and the MAME team"
+#define DISCLAIMER "MAME is an emulator: it reproduces, more or less faithfully, the behaviour of\n" \
+ "several arcade machines. But hardware is useless without software, so an image\n" \
+ "of the ROMs which run on that hardware is required. Such ROMs, like any other\n" \
+ "commercial software, are copyrighted material and it is therefore illegal to\n" \
+ "use them if you don't own the original arcade machine. Needless to say, ROMs\n" \
+ "are not distributed together with MAME. Distribution of MAME together with ROM\n" \
+ "images is a violation of copyright law and should be promptly reported to the\n" \
+ "authors so that appropriate legal action can be taken.\n"
+#define USAGE "Usage: %s [%s] [options]"
+#define XML_ROOT "mame"
+#define XML_TOP "game"
+#define STATE_MAGIC_NUM 'M', 'A', 'M', 'E', 'S', 'A', 'V', 'E'
+#else
+#define APPNAME "MESS"
+#define APPNAME_LOWER "mess"
+#define CONFIGNAME "mess"
+#define APPLONGNAME "M.E.S.S."
+#define FULLLONGNAME "Multi Emulator Super System"
+#define CAPGAMENOUN "SYSTEM"
+#define CAPSTARTGAMENOUN "System"
+#define GAMENOUN "system"
+#define GAMESNOUN "systems"
+#define COPYRIGHT "Copyright the MESS team\nhttp://mess.org"
+#define COPYRIGHT_INFO "Copyright the MESS team\n\n" \
+ "MESS is based on MAME Source code\n" \
+ "Copyright Nicola Salmoria and the MAME team"
+#define DISCLAIMER "MESS is an emulator: it reproduces, more or less faithfully, the behaviour of\n"\
+ "several computer and console systems. But hardware is useless without software\n" \
+ "so a file dump of the ROM, cartridges, discs, and cassettes which run on that\n" \
+ "hardware is required. Such files, like any other commercial software, are\n" \
+ "copyrighted material and it is therefore illegal to use them if you don't own\n" \
+ "the original media from which the files are derived. Needless to say, these\n" \
+ "files are not distributed together with MESS. Distribution of MESS together\n" \
+ "with these files is a violation of copyright law and should be promptly\n" \
+ "reported to the authors so that appropriate legal action can be taken.\n"
+#define USAGE "Usage: %s [%s] [media] [software] [options]"
+#define XML_ROOT "mess"
+#define XML_TOP "machine"
+#define STATE_MAGIC_NUM 'M', 'E', 'S', 'S', 'S', 'A', 'V', 'E'
+#endif
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// output channel callback
+typedef void (*output_callback_func)(void *param, const char *format, va_list argptr);
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+extern const char build_version[];
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+
+/* ----- core system management ----- */
+
+/* execute as configured by the OPTION_SYSTEMNAME option on the specified options */
+int mame_execute(emu_options &options, osd_interface &osd);
+
+/* return true if the given machine is valid */
+int mame_is_valid_machine(running_machine &machine);
+
+
+
+/* ----- output management ----- */
+
+/* set the output handler for a channel, returns the current one */
+void mame_set_output_channel(output_channel channel, output_callback_func callback, void *param, output_callback_func *prevcb, void **prevparam);
+
+/* built-in default callbacks */
+void mame_file_output_callback(void *param, const char *format, va_list argptr);
+void mame_null_output_callback(void *param, const char *format, va_list argptr);
+
+/* calls to be used by the code */
+void mame_printf_error(const char *format, ...) ATTR_PRINTF(1,2);
+void mame_printf_warning(const char *format, ...) ATTR_PRINTF(1,2);
+void mame_printf_info(const char *format, ...) ATTR_PRINTF(1,2);
+void mame_printf_verbose(const char *format, ...) ATTR_PRINTF(1,2);
+void mame_printf_debug(const char *format, ...) ATTR_PRINTF(1,2);
+
+/* discourage the use of printf directly */
+/* sadly, can't do this because of the ATTR_PRINTF under GCC */
+/*
+#undef printf
+#define printf !MUST_USE_MAME_PRINTF_*_CALLS_WITHIN_THE_CORE!
+*/
+
+
+/* ----- miscellaneous bits & pieces ----- */
+
+// pop-up a user visible message
+void CLIB_DECL popmessage(const char *format,...) ATTR_PRINTF(1,2);
+
+// log to the standard error.log file
+void CLIB_DECL logerror(const char *format,...) ATTR_PRINTF(1,2);
+
+
+#endif /* __MAME_H__ */
diff --git a/trunk/src/emu/mconfig.c b/trunk/src/emu/mconfig.c
new file mode 100644
index 00000000000..70df85c5436
--- /dev/null
+++ b/trunk/src/emu/mconfig.c
@@ -0,0 +1,224 @@
+/***************************************************************************
+
+ mconfig.c
+
+ Machine configuration macros and 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 <ctype.h>
+
+
+//**************************************************************************
+// MACHINE CONFIGURATIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// machine_config - constructor
+//-------------------------------------------------
+
+machine_config::machine_config(const game_driver &gamedrv, emu_options &options)
+ : m_minimum_quantum(attotime::zero),
+ m_perfect_cpu_quantum(NULL),
+ m_watchdog_vblank_count(0),
+ m_watchdog_time(attotime::zero),
+ m_nvram_handler(NULL),
+ m_memcard_handler(NULL),
+ m_video_attributes(0),
+ m_gfxdecodeinfo(NULL),
+ m_total_colors(0),
+ m_default_layout(NULL),
+ m_gamedrv(gamedrv),
+ m_options(options)
+{
+ // construct the config
+ (*gamedrv.machine_config)(*this, NULL);
+
+ // intialize slot devices - make sure that any required devices have been allocated
+ device_slot_interface *slot = NULL;
+ for (bool gotone = m_devicelist.first(slot); gotone; gotone = slot->next(slot))
+ {
+ const slot_interface *intf = slot->get_slot_interfaces();
+ if (intf != NULL)
+ {
+ device_t &owner = slot->device();
+ const char *selval = options.value(owner.tag());
+ if (!options.exists(owner.tag()))
+ selval = slot->get_default_card(devicelist(), options);
+
+ if (selval != NULL)
+ for (int i = 0; intf[i].name != NULL; i++)
+ if (strcmp(selval, intf[i].name) == 0) {
+ device_t *new_dev = device_add(&owner, intf[i].name, intf[i].devtype, 0);
+ if (!options.exists(owner.tag()))
+ device_t::static_set_input_default(*new_dev, slot->input_ports_defaults());
+ }
+ }
+ }
+
+ // when finished, set the game driver
+ device_t *root = m_devicelist.find("root");
+ if (root == NULL)
+ throw emu_fatalerror("Machine configuration missing driver_device");
+ driver_device::static_set_game(*root, gamedrv);
+
+ // then notify all devices that their configuration is complete
+ for (device_t *device = m_devicelist.first(); device != NULL; device = device->next())
+ if (!device->configured())
+ device->config_complete();
+}
+
+
+//-------------------------------------------------
+// ~machine_config - destructor
+//-------------------------------------------------
+
+machine_config::~machine_config()
+{
+}
+
+
+//-------------------------------------------------
+// first_screen - return a pointer to the first
+// screen device
+//-------------------------------------------------
+
+screen_device *machine_config::first_screen() const
+{
+ return downcast<screen_device *>(m_devicelist.first(SCREEN));
+}
+
+
+//-------------------------------------------------
+// device_add_subdevices - helper to add
+// devices owned by the device
+//-------------------------------------------------
+
+void machine_config::device_add_subdevices(device_t *device)
+{
+ machine_config_constructor additions = device->machine_config_additions();
+ if (additions != NULL)
+ (*additions)(*this, device);
+}
+
+
+//-------------------------------------------------
+// device_remove_subdevices - helper to remove
+// devices owned by the device
+//-------------------------------------------------
+
+void machine_config::device_remove_subdevices(const device_t *device)
+{
+ if (device != NULL)
+ {
+ device_t *sub_device = m_devicelist.first();
+ while (sub_device != NULL)
+ {
+ if (sub_device->owner() == device)
+ device_remove_subdevices(sub_device);
+
+ device_t *next_device = sub_device->next();
+
+ if (sub_device->owner() == device)
+ m_devicelist.remove(*sub_device);
+
+ sub_device = next_device;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// device_add - configuration helper to add a
+// new device
+//-------------------------------------------------
+
+device_t *machine_config::device_add(device_t *owner, const char *tag, device_type type, UINT32 clock)
+{
+ astring tempstring;
+ const char *fulltag = owner->subtag(tempstring, tag);
+ device_t *device = &m_devicelist.append(fulltag, *(*type)(*this, fulltag, owner, clock));
+ device_add_subdevices(device);
+ return device;
+}
+
+
+//-------------------------------------------------
+// device_replace - configuration helper to
+// replace one device with a new device
+//-------------------------------------------------
+
+device_t *machine_config::device_replace(device_t *owner, const char *tag, device_type type, UINT32 clock)
+{
+ astring tempstring;
+ const char *fulltag = owner->subtag(tempstring, tag);
+ device_remove_subdevices(m_devicelist.find(fulltag));
+ device_t *device = &m_devicelist.replace_and_remove(fulltag, *(*type)(*this, fulltag, owner, clock));
+ device_add_subdevices(device);
+ return device;
+}
+
+
+//-------------------------------------------------
+// device_remove - configuration helper to
+// remove a device
+//-------------------------------------------------
+
+device_t *machine_config::device_remove(device_t *owner, const char *tag)
+{
+ astring tempstring;
+ const char *fulltag = owner->subtag(tempstring, tag);
+ device_t *device=m_devicelist.find(fulltag);
+ device_remove_subdevices(device);
+ m_devicelist.remove(*device);
+ return NULL;
+}
+
+
+//-------------------------------------------------
+// device_find - configuration helper to
+// locate a device
+//-------------------------------------------------
+
+device_t *machine_config::device_find(device_t *owner, const char *tag)
+{
+ astring tempstring;
+ const char *fulltag = owner->subtag(tempstring, tag);
+ device_t *device = m_devicelist.find(fulltag);
+ if (device == NULL)
+ throw emu_fatalerror("Unable to find device: tag=%s\n", fulltag);
+ return device;
+}
diff --git a/trunk/src/emu/mconfig.h b/trunk/src/emu/mconfig.h
new file mode 100644
index 00000000000..e9f6a5192e0
--- /dev/null
+++ b/trunk/src/emu/mconfig.h
@@ -0,0 +1,310 @@
+/***************************************************************************
+
+ mconfig.h
+
+ Machine configuration macros and 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 __EMU_H__
+#error Dont include this file directly; include emu.h instead.
+#endif
+
+#ifndef __MCONFIG_H__
+#define __MCONFIG_H__
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// by convention, tags should all lowercase and between 2-15 characters
+#define MIN_TAG_LENGTH 2
+#define MAX_TAG_LENGTH 15
+
+
+
+// ----- flags for video_attributes -----
+
+// should VIDEO_UPDATE by called at the start of VBLANK or at the end?
+#define VIDEO_UPDATE_BEFORE_VBLANK 0x0000
+#define VIDEO_UPDATE_AFTER_VBLANK 0x0004
+
+// indicates VIDEO_UPDATE will add container bits its
+#define VIDEO_SELF_RENDER 0x0008
+
+// automatically extend the palette creating a darker copy for shadows
+#define VIDEO_HAS_SHADOWS 0x0010
+
+// automatically extend the palette creating a brighter copy for highlights
+#define VIDEO_HAS_HIGHLIGHTS 0x0020
+
+// Mish 181099: See comments in video/generic.c for details
+#define VIDEO_BUFFERS_SPRITERAM 0x0040
+
+// force VIDEO_UPDATE to be called even for skipped frames
+#define VIDEO_ALWAYS_UPDATE 0x0080
+
+// calls VIDEO_UPDATE for every visible scanline, even for skipped frames
+#define VIDEO_UPDATE_SCANLINE 0x0100
+
+
+
+#define NVRAM_HANDLER_NAME(name) nvram_handler_##name
+#define NVRAM_HANDLER(name) void NVRAM_HANDLER_NAME(name)(running_machine &machine, emu_file *file, int read_or_write)
+#define NVRAM_HANDLER_CALL(name) NVRAM_HANDLER_NAME(name)(machine, file, read_or_write)
+
+#define MEMCARD_HANDLER_NAME(name) memcard_handler_##name
+#define MEMCARD_HANDLER(name) void MEMCARD_HANDLER_NAME(name)(running_machine &machine, emu_file &file, int action)
+#define MEMCARD_HANDLER_CALL(name) MEMCARD_HANDLER_NAME(name)(machine, file, action)
+
+
+// NULL versions
+#define nvram_handler_0 NULL
+#define memcard_handler_0 NULL
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// forward references
+struct gfx_decode_entry;
+class driver_device;
+class screen_device;
+
+
+
+// various callback functions
+typedef void (*nvram_handler_func)(running_machine &machine, emu_file *file, int read_or_write);
+typedef void (*memcard_handler_func)(running_machine &machine, emu_file &file, int action);
+
+
+
+// ======================> machine_config
+
+// machine configuration definition
+class machine_config
+{
+ DISABLE_COPYING(machine_config);
+
+ friend class running_machine;
+
+public:
+ // construction/destruction
+ machine_config(const game_driver &gamedrv, emu_options &options);
+ ~machine_config();
+
+ // getters
+ const game_driver &gamedrv() const { return m_gamedrv; }
+ const device_list &devicelist() const { return m_devicelist; }
+ const device_t *first_device() const { return m_devicelist.first(); }
+ screen_device *first_screen() const;
+ emu_options &options() const { return m_options; }
+
+ // public state
+ attotime m_minimum_quantum; // minimum scheduling quantum
+ const char * m_perfect_cpu_quantum; // tag of CPU to use for "perfect" scheduling
+ INT32 m_watchdog_vblank_count; // number of VBLANKs until the watchdog kills us
+ attotime m_watchdog_time; // length of time until the watchdog kills us
+
+ nvram_handler_func m_nvram_handler; // NVRAM save/load callback
+ memcard_handler_func m_memcard_handler; // memory card save/load callback
+
+ UINT32 m_video_attributes; // flags describing the video system
+ const gfx_decode_entry *m_gfxdecodeinfo; // pointer to array of graphics decoding information
+ UINT32 m_total_colors; // total number of colors in the palette
+ const char * m_default_layout; // default layout for this machine
+
+ // helpers during configuration; not for general use
+ device_t *device_add(device_t *owner, const char *tag, device_type type, UINT32 clock);
+ device_t *device_replace(device_t *owner, const char *tag, device_type type, UINT32 clock);
+ device_t *device_remove(device_t *owner, const char *tag);
+ device_t *device_find(device_t *owner, const char *tag);
+
+private:
+ void device_add_subdevices(device_t *device);
+ void device_remove_subdevices(const device_t *device);
+
+ const game_driver & m_gamedrv;
+ emu_options & m_options;
+ device_list m_devicelist; // list of device configs
+};
+
+
+
+//**************************************************************************
+// MACHINE CONFIG MACROS
+//**************************************************************************
+
+// start/end tags for the machine driver
+#define MACHINE_CONFIG_NAME(_name) construct_machine_config_##_name
+
+#define MACHINE_CONFIG_START(_name, _class) \
+device_t *MACHINE_CONFIG_NAME(_name)(machine_config &config, device_t *owner) \
+{ \
+ device_t *device = NULL; \
+ const char *tag; \
+ astring tempstring; \
+ (void)device; \
+ (void)tag; \
+ if (owner == NULL) owner = config.device_add(NULL, "root", &driver_device_creator<_class>, 0); \
+
+#define MACHINE_CONFIG_FRAGMENT(_name) \
+device_t *MACHINE_CONFIG_NAME(_name)(machine_config &config, device_t *owner) \
+{ \
+ device_t *device = NULL; \
+ const char *tag; \
+ astring tempstring; \
+ (void)device; \
+ (void)tag; \
+ assert(owner != NULL); \
+
+#define MACHINE_CONFIG_DERIVED(_name, _base) \
+device_t *MACHINE_CONFIG_NAME(_name)(machine_config &config, device_t *owner) \
+{ \
+ device_t *device = NULL; \
+ const char *tag; \
+ astring tempstring; \
+ (void)device; \
+ (void)tag; \
+ owner = MACHINE_CONFIG_NAME(_base)(config, owner); \
+ assert(owner != NULL); \
+
+#define MACHINE_CONFIG_DERIVED_CLASS(_name, _base, _class) \
+device_t *MACHINE_CONFIG_NAME(_name)(machine_config &config, device_t *owner) \
+{ \
+ device_t *device = NULL; \
+ const char *tag; \
+ astring tempstring; \
+ (void)device; \
+ (void)tag; \
+ if (owner == NULL) owner = config.device_add(NULL, "root", &driver_device_creator<_class>, 0); \
+ owner = MACHINE_CONFIG_NAME(_base)(config, owner); \
+
+#define MACHINE_CONFIG_END \
+ return owner; \
+}
+
+// use this to declare external references to a machine driver
+#define MACHINE_CONFIG_EXTERN(_name) \
+ extern device_t *MACHINE_CONFIG_NAME(_name)(machine_config &config, device_t *owner)
+
+
+// importing data from other machine drivers
+#define MCFG_FRAGMENT_ADD(_name) \
+ MACHINE_CONFIG_NAME(_name)(config, owner);
+
+
+// core parameters
+#define MCFG_QUANTUM_TIME(_time) \
+ config.m_minimum_quantum = _time; \
+
+#define MCFG_QUANTUM_PERFECT_CPU(_cputag) \
+ config.m_perfect_cpu_quantum = _cputag; \
+
+#define MCFG_WATCHDOG_VBLANK_INIT(_count) \
+ config.m_watchdog_vblank_count = _count; \
+
+#define MCFG_WATCHDOG_TIME_INIT(_time) \
+ config.m_watchdog_time = _time; \
+
+
+// core functions
+#define MCFG_NVRAM_HANDLER(_func) \
+ config.m_nvram_handler = NVRAM_HANDLER_NAME(_func); \
+
+#define MCFG_MEMCARD_HANDLER(_func) \
+ config.m_memcard_handler = MEMCARD_HANDLER_NAME(_func); \
+
+
+// core video parameters
+#define MCFG_VIDEO_ATTRIBUTES(_flags) \
+ config.m_video_attributes = _flags; \
+
+#define MCFG_GFXDECODE(_gfx) \
+ config.m_gfxdecodeinfo = GFXDECODE_NAME(_gfx); \
+
+#define MCFG_PALETTE_LENGTH(_length) \
+ config.m_total_colors = _length; \
+
+#define MCFG_DEFAULT_LAYOUT(_layout) \
+ config.m_default_layout = &(_layout)[0]; \
+
+
+// core machine functions
+#define MCFG_MACHINE_START(_func) \
+ driver_device::static_set_callback(*owner, driver_device::CB_MACHINE_START, MACHINE_START_NAME(_func)); \
+
+#define MCFG_MACHINE_RESET(_func) \
+ driver_device::static_set_callback(*owner, driver_device::CB_MACHINE_RESET, MACHINE_RESET_NAME(_func)); \
+
+
+// core sound functions
+#define MCFG_SOUND_START(_func) \
+ driver_device::static_set_callback(*owner, driver_device::CB_SOUND_START, SOUND_START_NAME(_func)); \
+
+#define MCFG_SOUND_RESET(_func) \
+ driver_device::static_set_callback(*owner, driver_device::CB_SOUND_RESET, SOUND_RESET_NAME(_func)); \
+
+
+// core video functions
+#define MCFG_PALETTE_INIT(_func) \
+ driver_device::static_set_palette_init(*owner, PALETTE_INIT_NAME(_func)); \
+
+#define MCFG_VIDEO_START(_func) \
+ driver_device::static_set_callback(*owner, driver_device::CB_VIDEO_START, VIDEO_START_NAME(_func)); \
+
+#define MCFG_VIDEO_RESET(_func) \
+ driver_device::static_set_callback(*owner, driver_device::CB_VIDEO_RESET, VIDEO_RESET_NAME(_func)); \
+
+
+// add/remove devices
+#define MCFG_DEVICE_ADD(_tag, _type, _clock) \
+ device = config.device_add(owner, _tag, _type, _clock); \
+
+#define MCFG_DEVICE_REPLACE(_tag, _type, _clock) \
+ device = config.device_replace(owner, _tag, _type, _clock); \
+
+#define MCFG_DEVICE_REMOVE(_tag) \
+ device = config.device_remove(owner, _tag); \
+
+#define MCFG_DEVICE_MODIFY(_tag) \
+ device = config.device_find(owner, _tag); \
+
+
+#endif /* __MCONFIG_H__ */
diff --git a/trunk/src/emu/memconv.h b/trunk/src/emu/memconv.h
new file mode 100644
index 00000000000..c802126ac55
--- /dev/null
+++ b/trunk/src/emu/memconv.h
@@ -0,0 +1,1020 @@
+/***************************************************************************
+
+ memconv.h
+
+ Functions which help convert between different handlers.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+****************************************************************************
+
+ ***** VERY IMPORTANT NOTICE *****
+
+ These functions and macros are provided to facilitate the mapping
+ of devices on cpus with different data bus widths.
+ Devices should be implemented using their native data bus width,
+ since that ensures that read/write operations are kept atomic.
+ If we discover you have abused the functionality presented in this
+ file, you *will* be publicly humiliated and your code submission
+ will probably not be accepted. Seriously, please do not abuse these
+ functions/macros.
+
+****************************************************************************
+
+ Conversions supported:
+
+ CW = CPU Data Bus Width in bits
+ CBO = CPU Byte Order
+ DW = Device Data Bus Width in bits
+ DBO = Device Byte Order
+
+ CW | CBO | DW | DBO | Functions to use
+ ---+--------+----+--------+-----------------------------------------------------------
+ 16 | Big | 8 | N/A | read16be_with_read8_handler,write16be_with_write8_handler
+ 16 | Little | 8 | N/A | read16le_with_read8_handler,write16le_with_write8_handler
+ ---+--------+----+--------+-----------------------------------------------------------
+ 32 | Big | 8 | N/A | read32be_with_read8_handler,write32be_with_write8_handler
+ 32 | Little | 8 | N/A | read32le_with_read8_handler,write32le_with_write8_handler
+ 32 | Big | 16 | Big | read32be_with_16be_handler,write32be_with_16be_handler
+ 32 | Little | 16 | Little | read32le_with_16le_handler,write32le_with_16le_handler
+ 32 | Big | 16 | Little | read32be_with_16le_handler,write32be_with_16le_handler
+ 32 | Little | 16 | Big | read32le_with_16be_handler,write32le_with_16be_handler
+ ---+--------+----+--------+-----------------------------------------------------------
+ 64 | Big | 8 | N/A | read64be_with_read8_handler,write64be_with_write8_handler
+ 64 | Little | 8 | N/A | read64le_with_read8_handler,write64le_with_write8_handler
+ 64 | Big | 16 | Big | read64be_with_16be_handler,write64be_with_16be_handler
+ 64 | Little | 16 | Little | read64le_with_16le_handler,write64le_with_16le_handler
+ 64 | Big | 16 | Little | read64be_with_16le_handler,write64be_with_16le_handler
+ 64 | Little | 16 | Big | read64le_with_16be_handler,write64le_with_16be_handler
+ 64 | Big | 32 | Big | read64be_with_32be_handler,write64be_with_32be_handler
+ 64 | Little | 32 | Little | read64le_with_32le_handler,write64le_with_32le_handler
+ 64 | Big | 32 | Little | read64be_with_32le_handler,write64be_with_32le_handler
+ 64 | Little | 32 | Big | read64le_with_32be_handler,write64le_with_32be_handler
+
+ You can also find at the bottom of this file a few convernient
+ macros that will create the stub read and/or write handlers for
+ the most common mappings, that will use the functions above.
+ Here's an example on how to use them: Say you have a 8 bit device
+ whose handlers are device8_r and device8_w, and you want to connect
+ it to a 16 bit, big endian cpu. We'll say the device is mapped on
+ the least significant byte of the data bus (LSB).
+
+ In your driver, you would add:
+
+ READWRITE8TO16BE_LSB( device16, device8_r, device8_w )
+
+ which will create two 16 bit memory handlers, one for read, called
+ device16_r, and one for write, called device16_w, with the proper
+ mapping.
+
+ then in the MEMORY_MAP you would specify:
+
+ AM_RANGE(0x000000, 0x0000ff) AM_READWRITE( device16_r, device16_w )
+
+ And that is all. Your device should be mapped properly.
+ If you need to do custom mappings, or a mapping that is not currently
+ supported in this file, you can always write the stub yourself, and
+ call the above functions to invoke the base handlers.
+
+***************************************************************************/
+
+/*************************************
+ *
+ * 16-bit BE using 8-bit handlers
+ *
+ *************************************/
+
+INLINE UINT16 read16be_with_read8_handler(read8_space_func handler, address_space *space, offs_t offset, UINT16 mem_mask)
+{
+ UINT16 result = 0;
+ if (ACCESSING_BITS_8_15)
+ result |= ((UINT16)(*handler)(space, offset * 2 + 0)) << 8;
+ if (ACCESSING_BITS_0_7)
+ result |= ((UINT16)(*handler)(space, offset * 2 + 1)) << 0;
+ return result;
+}
+
+
+INLINE void write16be_with_write8_handler(write8_space_func handler, address_space *space, offs_t offset, UINT16 data, UINT16 mem_mask)
+{
+ if (ACCESSING_BITS_8_15)
+ (*handler)(space, offset * 2 + 0, data >> 8);
+ if (ACCESSING_BITS_0_7)
+ (*handler)(space, offset * 2 + 1, data >> 0);
+}
+
+
+/*************************************
+ *
+ * 16-bit LE using 8-bit handlers
+ *
+ *************************************/
+
+INLINE UINT16 read16le_with_read8_handler(read8_space_func handler, address_space *space, offs_t offset, UINT16 mem_mask)
+{
+ UINT16 result = 0;
+ if (ACCESSING_BITS_0_7)
+ result |= ((UINT16) (*handler)(space, offset * 2 + 0)) << 0;
+ if (ACCESSING_BITS_8_15)
+ result |= ((UINT16) (*handler)(space, offset * 2 + 1)) << 8;
+ return result;
+}
+
+
+INLINE void write16le_with_write8_handler(write8_space_func handler, address_space *space, offs_t offset, UINT16 data, UINT16 mem_mask)
+{
+ if (ACCESSING_BITS_0_7)
+ (*handler)(space, offset * 2 + 0, data >> 0);
+ if (ACCESSING_BITS_8_15)
+ (*handler)(space, offset * 2 + 1, data >> 8);
+}
+
+
+/*************************************
+ *
+ * 32-bit BE using 8-bit handlers
+ *
+ *************************************/
+
+INLINE UINT32 read32be_with_read8_handler(read8_space_func handler, address_space *space, offs_t offset, UINT32 mem_mask)
+{
+ UINT32 result = 0;
+ if (ACCESSING_BITS_16_31)
+ result |= read16be_with_read8_handler(handler, space, offset * 2 + 0, mem_mask >> 16) << 16;
+ if (ACCESSING_BITS_0_15)
+ result |= read16be_with_read8_handler(handler, space, offset * 2 + 1, mem_mask) << 0;
+ return result;
+}
+
+
+INLINE void write32be_with_write8_handler(write8_space_func handler, address_space *space, offs_t offset, UINT32 data, UINT32 mem_mask)
+{
+ if (ACCESSING_BITS_16_31)
+ write16be_with_write8_handler(handler, space, offset * 2 + 0, data >> 16, mem_mask >> 16);
+ if (ACCESSING_BITS_0_15)
+ write16be_with_write8_handler(handler, space, offset * 2 + 1, data, mem_mask);
+}
+
+
+/*************************************
+ *
+ * 32-bit LE using 8-bit handlers
+ *
+ *************************************/
+
+INLINE UINT32 read32le_with_read8_handler(read8_space_func handler, address_space *space, offs_t offset, UINT32 mem_mask)
+{
+ UINT32 result = 0;
+ if (ACCESSING_BITS_0_15)
+ result |= read16le_with_read8_handler(handler, space, offset * 2 + 0, mem_mask) << 0;
+ if (ACCESSING_BITS_16_31)
+ result |= read16le_with_read8_handler(handler, space, offset * 2 + 1, mem_mask >> 16) << 16;
+ return result;
+}
+
+
+INLINE void write32le_with_write8_handler(write8_space_func handler, address_space *space, offs_t offset, UINT32 data, UINT32 mem_mask)
+{
+ if (ACCESSING_BITS_0_15)
+ write16le_with_write8_handler(handler, space, offset * 2 + 0, data, mem_mask);
+ if (ACCESSING_BITS_16_31)
+ write16le_with_write8_handler(handler, space, offset * 2 + 1, data >> 16, mem_mask >> 16);
+}
+
+
+/*************************************
+ *
+ * 32-bit BE using 16-bit BE handlers
+ *
+ *************************************/
+
+INLINE UINT32 read32be_with_16be_handler(read16_space_func handler, address_space *space, offs_t offset, UINT32 mem_mask)
+{
+ UINT32 result = 0;
+ if (ACCESSING_BITS_16_31)
+ result |= (*handler)(space, offset * 2 + 0, mem_mask >> 16) << 16;
+ if (ACCESSING_BITS_0_15)
+ result |= (*handler)(space, offset * 2 + 1, mem_mask) << 0;
+ return result;
+}
+
+
+INLINE void write32be_with_16be_handler(write16_space_func handler, address_space *space, offs_t offset, UINT32 data, UINT32 mem_mask)
+{
+ if (ACCESSING_BITS_16_31)
+ (*handler)(space, offset * 2 + 0, data >> 16, mem_mask >> 16);
+ if (ACCESSING_BITS_0_15)
+ (*handler)(space, offset * 2 + 1, data, mem_mask);
+}
+
+
+/*************************************
+ *
+ * 32-bit LE using 16-bit LE handlers
+ *
+ *************************************/
+
+INLINE UINT32 read32le_with_16le_handler(read16_space_func handler, address_space *space, offs_t offset, UINT32 mem_mask)
+{
+ UINT32 result = 0;
+ if (ACCESSING_BITS_0_15)
+ result |= (*handler)(space, offset * 2 + 0, mem_mask) << 0;
+ if (ACCESSING_BITS_16_31)
+ result |= (*handler)(space, offset * 2 + 1, mem_mask >> 16) << 16;
+ return result;
+}
+
+
+INLINE void write32le_with_16le_handler(write16_space_func handler, address_space *space, offs_t offset, UINT32 data, UINT32 mem_mask)
+{
+ if (ACCESSING_BITS_0_15)
+ (*handler)(space, offset * 2 + 0, data, mem_mask);
+ if (ACCESSING_BITS_16_31)
+ (*handler)(space, offset * 2 + 1, data >> 16, mem_mask >> 16);
+}
+
+
+/*************************************
+ *
+ * 32-bit BE using 16-bit LE handlers
+ *
+ *************************************/
+
+INLINE UINT32 read32be_with_16le_handler(read16_space_func handler, address_space *space, offs_t offset, UINT32 mem_mask)
+{
+ UINT32 result = 0;
+ mem_mask = FLIPENDIAN_INT32(mem_mask);
+ result = read32le_with_16le_handler(handler, space, offset, mem_mask);
+ return FLIPENDIAN_INT32(result);
+}
+
+
+INLINE void write32be_with_16le_handler(write16_space_func handler, address_space *space, offs_t offset, UINT32 data, UINT32 mem_mask)
+{
+ data = FLIPENDIAN_INT32(data);
+ mem_mask = FLIPENDIAN_INT32(mem_mask);
+ write32le_with_16le_handler(handler, space, offset, data, mem_mask);
+}
+
+
+/*************************************
+ *
+ * 32-bit LE using 16-bit BE handlers
+ *
+ *************************************/
+
+INLINE UINT32 read32le_with_16be_handler(read16_space_func handler, address_space *space, offs_t offset, UINT32 mem_mask)
+{
+ UINT32 result = 0;
+ mem_mask = FLIPENDIAN_INT32(mem_mask);
+ result = read32be_with_16be_handler(handler, space, offset, mem_mask);
+ return FLIPENDIAN_INT32(result);
+}
+
+
+INLINE void write32le_with_16be_handler(write16_space_func handler, address_space *space, offs_t offset, UINT32 data, UINT32 mem_mask)
+{
+ data = FLIPENDIAN_INT32(data);
+ mem_mask = FLIPENDIAN_INT32(mem_mask);
+ write32be_with_16be_handler(handler, space, offset, data, mem_mask);
+}
+
+
+/*************************************
+ *
+ * 64-bit BE using 8-bit handlers
+ *
+ *************************************/
+
+INLINE UINT64 read64be_with_read8_handler(read8_space_func handler, address_space *space, offs_t offset, UINT64 mem_mask)
+{
+ UINT64 result = 0;
+ if (ACCESSING_BITS_32_63)
+ result |= (UINT64)read32be_with_read8_handler(handler, space, offset * 2 + 0, mem_mask >> 32) << 32;
+ if (ACCESSING_BITS_0_31)
+ result |= (UINT64)read32be_with_read8_handler(handler, space, offset * 2 + 1, mem_mask) << 0;
+ return result;
+}
+
+
+INLINE void write64be_with_write8_handler(write8_space_func handler, address_space *space, offs_t offset, UINT64 data, UINT64 mem_mask)
+{
+ if (ACCESSING_BITS_32_63)
+ write32be_with_write8_handler(handler, space, offset * 2 + 0, data >> 32, mem_mask >> 32);
+ if (ACCESSING_BITS_0_31)
+ write32be_with_write8_handler(handler, space, offset * 2 + 1, data, mem_mask);
+}
+
+
+/*************************************
+ *
+ * 64-bit LE using 8-bit handlers
+ *
+ *************************************/
+
+INLINE UINT64 read64le_with_read8_handler(read8_space_func handler, address_space *space, offs_t offset, UINT64 mem_mask)
+{
+ UINT64 result = 0;
+ if (ACCESSING_BITS_0_31)
+ result |= (UINT64)read32le_with_read8_handler(handler, space, offset * 2 + 0, mem_mask >> 0) << 0;
+ if (ACCESSING_BITS_32_63)
+ result |= (UINT64)read32le_with_read8_handler(handler, space, offset * 2 + 1, mem_mask >> 32) << 32;
+ return result;
+}
+
+
+INLINE void write64le_with_write8_handler(write8_space_func handler, address_space *space, offs_t offset, UINT64 data, UINT64 mem_mask)
+{
+ if (ACCESSING_BITS_0_31)
+ write32le_with_write8_handler(handler, space, offset * 2 + 0, data >> 0, mem_mask >> 0);
+ if (ACCESSING_BITS_32_63)
+ write32le_with_write8_handler(handler, space, offset * 2 + 1, data >> 32, mem_mask >> 32);
+}
+
+
+/*************************************
+ *
+ * 64-bit BE using 16-bit BE handlers
+ *
+ *************************************/
+
+INLINE UINT32 read64be_with_16be_handler(read16_space_func handler, address_space *space, offs_t offset, UINT64 mem_mask)
+{
+ UINT64 result = 0;
+ if (ACCESSING_BITS_32_63)
+ result |= (UINT64)read32be_with_16be_handler(handler, space, offset * 2 + 0, mem_mask >> 32) << 32;
+ if (ACCESSING_BITS_0_31)
+ result |= (UINT64)read32be_with_16be_handler(handler, space, offset * 2 + 1, mem_mask >> 0) << 0;
+ return result;
+}
+
+
+INLINE void write64be_with_16be_handler(write16_space_func handler, address_space *space, offs_t offset, UINT64 data, UINT64 mem_mask)
+{
+ if (ACCESSING_BITS_32_63)
+ write32be_with_16be_handler(handler, space, offset * 2 + 0, data >> 32, mem_mask >> 32);
+ if (ACCESSING_BITS_0_31)
+ write32be_with_16be_handler(handler, space, offset * 2 + 1, data >> 0, mem_mask >> 0);
+}
+
+
+/*************************************
+ *
+ * 64-bit LE using 16-bit LE handlers
+ *
+ *************************************/
+
+INLINE UINT32 read64le_with_16le_handler(read16_space_func handler, address_space *space, offs_t offset, UINT64 mem_mask)
+{
+ UINT64 result = 0;
+ if (ACCESSING_BITS_0_31)
+ result |= (UINT64)read32le_with_16le_handler(handler, space, offset * 2 + 0, mem_mask >> 0) << 0;
+ if (ACCESSING_BITS_32_63)
+ result |= (UINT64)read32le_with_16le_handler(handler, space, offset * 2 + 1, mem_mask >> 32) << 32;
+ return result;
+}
+
+
+INLINE void write64le_with_16le_handler(write16_space_func handler, address_space *space, offs_t offset, UINT64 data, UINT64 mem_mask)
+{
+ if (ACCESSING_BITS_0_31)
+ write32le_with_16le_handler(handler, space, offset * 2 + 0, data >> 0, mem_mask >> 0);
+ if (ACCESSING_BITS_32_63)
+ write32le_with_16le_handler(handler, space, offset * 2 + 1, data >> 32, mem_mask >> 32);
+}
+
+
+/*************************************
+ *
+ * 64-bit BE using 16-bit LE handlers
+ *
+ *************************************/
+
+INLINE UINT32 read64be_with_16le_handler(read16_space_func handler, address_space *space, offs_t offset, UINT64 mem_mask)
+{
+ UINT64 result = 0;
+ if (ACCESSING_BITS_32_63)
+ result |= (UINT64)read32be_with_16le_handler(handler, space, offset * 2 + 0, mem_mask >> 32) << 32;
+ if (ACCESSING_BITS_0_31)
+ result |= (UINT64)read32be_with_16le_handler(handler, space, offset * 2 + 1, mem_mask >> 0) << 0;
+ return result;
+}
+
+
+INLINE void write64be_with_16le_handler(write16_space_func handler, address_space *space, offs_t offset, UINT64 data, UINT64 mem_mask)
+{
+ if (ACCESSING_BITS_32_63)
+ write32be_with_16le_handler(handler, space, offset * 2 + 0, data >> 32, mem_mask >> 32);
+ if (ACCESSING_BITS_0_31)
+ write32be_with_16le_handler(handler, space, offset * 2 + 1, data >> 0, mem_mask >> 0);
+}
+
+
+/*************************************
+ *
+ * 64-bit LE using 16-bit BE handlers
+ *
+ *************************************/
+
+INLINE UINT32 read64le_with_16be_handler(read16_space_func handler, address_space *space, offs_t offset, UINT64 mem_mask)
+{
+ UINT64 result = 0;
+ if (ACCESSING_BITS_0_31)
+ result |= (UINT64)read32le_with_16be_handler(handler, space, offset * 2 + 0, mem_mask >> 0) << 0;
+ if (ACCESSING_BITS_32_63)
+ result |= (UINT64)read32le_with_16be_handler(handler, space, offset * 2 + 1, mem_mask >> 32) << 32;
+ return result;
+}
+
+
+INLINE void write64le_with_16be_handler(write16_space_func handler, address_space *space, offs_t offset, UINT64 data, UINT64 mem_mask)
+{
+ if (ACCESSING_BITS_0_31)
+ write32le_with_16be_handler(handler, space, offset * 2 + 0, data >> 0, mem_mask >> 0);
+ if (ACCESSING_BITS_32_63)
+ write32le_with_16be_handler(handler, space, offset * 2 + 1, data >> 32, mem_mask >> 32);
+}
+
+
+/*************************************
+ *
+ * 64-bit BE using 32-bit BE handlers
+ *
+ *************************************/
+
+INLINE UINT64 read64be_with_32be_handler(read32_space_func handler, address_space *space, offs_t offset, UINT64 mem_mask)
+{
+ UINT64 result = 0;
+ if (ACCESSING_BITS_32_63)
+ result |= (UINT64)(*handler)(space, offset * 2 + 0, mem_mask >> 32) << 32;
+ if (ACCESSING_BITS_0_31)
+ result |= (UINT64)(*handler)(space, offset * 2 + 1, mem_mask >> 0) << 0;
+ return result;
+}
+
+
+INLINE void write64be_with_32be_handler(write32_space_func handler, address_space *space, offs_t offset, UINT64 data, UINT64 mem_mask)
+{
+ if (ACCESSING_BITS_32_63)
+ (*handler)(space, offset * 2 + 0, data >> 32, mem_mask >> 32);
+ if (ACCESSING_BITS_0_31)
+ (*handler)(space, offset * 2 + 1, data >> 0, mem_mask >> 0);
+}
+
+
+/*************************************
+ *
+ * 64-bit LE using 32-bit LE handlers
+ *
+ *************************************/
+
+INLINE UINT64 read64le_with_32le_handler(read32_space_func handler, address_space *space, offs_t offset, UINT64 mem_mask)
+{
+ UINT64 result = 0;
+ if (ACCESSING_BITS_0_31)
+ result |= (UINT64)(*handler)(space, offset * 2 + 0, mem_mask >> 0) << 0;
+ if (ACCESSING_BITS_32_63)
+ result |= (UINT64)(*handler)(space, offset * 2 + 1, mem_mask >> 32) << 32;
+ return result;
+}
+
+
+INLINE void write64le_with_32le_handler(write32_space_func handler, address_space *space, offs_t offset, UINT64 data, UINT64 mem_mask)
+{
+ if (ACCESSING_BITS_0_31)
+ (*handler)(space, offset * 2 + 0, data >> 0, mem_mask >> 0);
+ if (ACCESSING_BITS_32_63)
+ (*handler)(space, offset * 2 + 1, data >> 32, mem_mask >> 32);
+}
+
+
+/*************************************
+ *
+ * 64-bit BE using 32-bit LE handlers
+ *
+ *************************************/
+
+INLINE UINT64 read64be_with_32le_handler(read32_space_func handler, address_space *space, offs_t offset, UINT64 mem_mask)
+{
+ UINT64 result;
+ mem_mask = FLIPENDIAN_INT64(mem_mask);
+ result = read64le_with_32le_handler(handler, space, offset, mem_mask);
+ return FLIPENDIAN_INT64(result);
+}
+
+
+INLINE void write64be_with_32le_handler(write32_space_func handler, address_space *space, offs_t offset, UINT64 data, UINT64 mem_mask)
+{
+ data = FLIPENDIAN_INT64(data);
+ mem_mask = FLIPENDIAN_INT64(mem_mask);
+ write64le_with_32le_handler(handler, space, offset, data, mem_mask);
+}
+
+
+/*************************************
+ *
+ * 64-bit LE using 32-bit BE handlers
+ *
+ *************************************/
+
+INLINE UINT64 read64le_with_32be_handler(read32_space_func handler, address_space *space, offs_t offset, UINT64 mem_mask)
+{
+ UINT64 result;
+ mem_mask = FLIPENDIAN_INT64(mem_mask);
+ result = read64be_with_32be_handler(handler, space, offset, mem_mask);
+ return FLIPENDIAN_INT64(result);
+}
+
+
+INLINE void write64le_with_32be_handler(write32_space_func handler, address_space *space, offs_t offset, UINT64 data, UINT64 mem_mask)
+{
+ data = FLIPENDIAN_INT64(data);
+ mem_mask = FLIPENDIAN_INT64(mem_mask);
+ write64be_with_32be_handler(handler, space, offset, data, mem_mask);
+}
+
+
+
+/**************************************************************************
+
+ Utility macros
+
+**************************************************************************/
+
+#define READ_TEMPLATE(bits, name, handler, func) \
+READ##bits##_HANDLER( name##_r ) \
+{ \
+ return func(handler, space, offset, mem_mask); \
+}
+
+#define READ_TEMPLATE_COND(bits, name, handler, func, cond) \
+READ##bits##_HANDLER( name##_r ) \
+{ \
+ if (cond) \
+ return func(handler, space, offset, mem_mask); \
+ return 0; \
+}
+
+#define WRITE_TEMPLATE(bits, name, handler, func) \
+WRITE##bits##_HANDLER( name##_w ) \
+{ \
+ func(handler, space, offset, data, mem_mask); \
+}
+
+#define WRITE_TEMPLATE_COND(bits, name, handler, func, cond) \
+WRITE##bits##_HANDLER( name##_w ) \
+{ \
+ if (cond) \
+ func(handler, space, offset, data, mem_mask); \
+}
+
+
+
+/**************************************************************************
+
+ Generic conversions macros
+
+**************************************************************************/
+
+
+/*************************************
+ * 8->16be, 1:1 mapping
+ ************************************/
+
+#define READ8TO16BE( name, read8 ) \
+READ_TEMPLATE( 16, name, read8, read16be_with_read8_handler )
+
+
+#define WRITE8TO16BE( name, write8 ) \
+WRITE_TEMPLATE( 16, name, write8, write16be_with_write8_handler )
+
+
+#define READWRITE8TO16BE( name, read8, write8 ) \
+READ8TO16BE(name,read8) \
+WRITE8TO16BE(name,write8)
+
+
+/*************************************
+ * 8->16le, 1:1 mapping
+ ************************************/
+
+#define READ8TO16LE( name, read8 ) \
+READ_TEMPLATE( 16, name, read8, read16le_with_read8_handler )
+
+
+#define WRITE8TO16LE( name, write8 ) \
+WRITE_TEMPLATE( 16, name, write8, write16le_with_write8_handler )
+
+
+#define READWRITE8TO16LE( name, read8, write8 ) \
+READ8TO16LE(name,read8) \
+WRITE8TO16LE(name,write8)
+
+
+/*************************************
+ * 8->16be, MSB mapping
+ ************************************/
+
+#define READ8TO16BE_MSB( name, read8 ) \
+READ_TEMPLATE_COND( 16, name, read8, read16be_with_read8_handler, ACCESSING_BITS_8_15 )
+
+
+#define WRITE8TO16BE_MSB( name, write8 ) \
+WRITE_TEMPLATE_COND( 16, name, write8, write16be_with_write8_handler, ACCESSING_BITS_8_15 )
+
+
+#define READWRITE8TO16BE_MSB( name, read8, write8 ) \
+READ8TO16BE_MSB(name,read8) \
+WRITE8TO16BE_MSB(name,write8)
+
+
+/*************************************
+ * 8->16le, MSB mapping
+ ************************************/
+
+#define READ8TO16LE_MSB( name, read8 ) \
+READ_TEMPLATE_COND( 16, name, read8, read16le_with_read8_handler, ACCESSING_BITS_8_15 )
+
+
+#define WRITE8TO16LE_MSB( name, write8 ) \
+WRITE_TEMPLATE_COND( 16, name, write8, write16le_with_write8_handler, ACCESSING_BITS_8_15 )
+
+
+#define READWRITE8TO16LE_MSB( name, read8, write8 ) \
+READ8TO16LE_MSB(name,read8) \
+WRITE8TO16LE_MSB(name,write8)
+
+
+/*************************************
+ * 8->16be, LSB mapping
+ ************************************/
+
+#define READ8TO16BE_LSB( name, read8 ) \
+READ_TEMPLATE_COND( 16, name, read8, read16be_with_read8_handler, ACCESSING_BITS_0_7 )
+
+
+#define WRITE8TO16BE_LSB( name, write8 ) \
+WRITE_TEMPLATE_COND( 16, name, write8, write16be_with_write8_handler, ACCESSING_BITS_0_7 )
+
+
+#define READWRITE8TO16BE_LSB( name, read8, write8 ) \
+READ8TO16BE_LSB(name,read8) \
+WRITE8TO16BE_LSB(name,write8)
+
+
+/*************************************
+ * 8->16le, LSB mapping
+ ************************************/
+
+#define READ8TO16LE_LSB( name, read8 ) \
+READ_TEMPLATE_COND( 16, name, read8, read16le_with_read8_handler, ACCESSING_BITS_0_7 )
+
+
+#define WRITE8TO16LE_LSB( name, write8 ) \
+WRITE_TEMPLATE_COND( 16, name, write8, write16le_with_write8_handler, ACCESSING_BITS_0_7 )
+
+
+#define READWRITE8TO16LE_LSB( name, read8, write8 ) \
+READ8TO16LE_LSB(name,read8) \
+WRITE8TO16LE_LSB(name,write8)
+
+
+/*************************************
+ * 8->32be, 1:1 mapping
+ ************************************/
+
+#define READ8TO32BE( name, read8 ) \
+READ_TEMPLATE( 32, name, read8, read32be_with_read8_handler )
+
+
+#define WRITE8TO32BE( name, write8 ) \
+WRITE_TEMPLATE( 32, name, write8, write32be_with_write8_handler )
+
+
+#define READWRITE8TO32BE( name, read8, write8 ) \
+READ8TO32BE(name,read8) \
+WRITE8TO32BE(name,write8)
+
+
+/*************************************
+ * 8->32le, 1:1 mapping
+ ************************************/
+
+#define READ8TO32LE( name, read8 ) \
+READ_TEMPLATE( 32, name, read8, read32le_with_read8_handler )
+
+
+#define WRITE8TO32LE( name, write8 ) \
+WRITE_TEMPLATE( 32, name, write8, write32le_with_write8_handler )
+
+
+#define READWRITE8TO32LE( name, read8, write8 ) \
+READ8TO32LE(name,read8) \
+WRITE8TO32LE(name,write8)
+
+
+/*************************************
+ * 8->32be, MSB mapping
+ ************************************/
+
+#define READ8TO32BE_MSB( name, read8 ) \
+READ_TEMPLATE_COND( 32, name, read8, read32be_with_read8_handler, ACCESSING_BITS_24_31 )
+
+
+#define WRITE8TO32BE_MSB( name, write8 ) \
+WRITE_TEMPLATE_COND( 32, name, write8, write32be_with_write8_handler, ACCESSING_BITS_24_31 )
+
+
+#define READWRITE8TO32BE_MSB( name, read8, write8 ) \
+READ8TO32BE_MSB(name,read8) \
+WRITE8TO32BE_MSB(name,write8)
+
+
+/*************************************
+ * 8->32le, MSB mapping
+ ************************************/
+
+#define READ8TO32LE_MSB( name, read8 ) \
+READ_TEMPLATE_COND( 32, name, read8, read32le_with_read8_handler, ACCESSING_BITS_24_31 )
+
+
+#define WRITE8TO32LE_MSB( name, write8 ) \
+WRITE_TEMPLATE_COND( 32, name, write8, write32le_with_write8_handler, ACCESSING_BITS_24_31 )
+
+
+#define READWRITE8TO32LE_MSB( name, read8, write8 ) \
+READ8TO32LE_MSB(name,read8) \
+WRITE8TO32LE_MSB(name,write8)
+
+
+/*************************************
+ * 8->32be, LSB mapping
+ ************************************/
+
+#define READ8TO32BE_LSB( name, read8 ) \
+READ_TEMPLATE_COND( 32, name, read8, read32be_with_read8_handler, ACCESSING_BITS_0_7 )
+
+
+#define WRITE8TO32BE_LSB( name, write8 ) \
+WRITE_TEMPLATE_COND( 32, name, write8, write32be_with_write8_handler, ACCESSING_BITS_0_7 )
+
+
+#define READWRITE8TO32BE_LSB( name, read8, write8 ) \
+READ8TO32BE_LSB(name,read8) \
+WRITE8TO32BE_LSB(name,write8)
+
+
+/*************************************
+ * 8->32le, LSB mapping
+ ************************************/
+
+#define READ8TO32LE_LSB( name, read8 ) \
+READ_TEMPLATE_COND( 32, name, read8, read32le_with_read8_handler, ACCESSING_BITS_0_7 )
+
+
+#define WRITE8TO32LE_LSB( name, write8 ) \
+WRITE_TEMPLATE_COND( 32, name, write8, write32le_with_write8_handler, ACCESSING_BITS_0_7 )
+
+
+#define READWRITE8TO32LE_LSB( name, read8, write8 ) \
+READ8TO32LE_LSB(name,read8) \
+WRITE8TO32LE_LSB(name,write8)
+
+
+/*************************************
+ * 8->64be, 1:1 mapping
+ ************************************/
+
+#define READ8TO64BE( name, read8 ) \
+READ_TEMPLATE( 64, name, read8, read64be_with_read8_handler )
+
+
+#define WRITE8TO64BE( name, write8 ) \
+WRITE_TEMPLATE( 64, name, write8, write64be_with_write8_handler )
+
+
+#define READWRITE8TO64BE( name, read8, write8 ) \
+READ8TO64BE(name,read8) \
+WRITE8TO64BE(name,write8)
+
+
+/*************************************
+ * 8->64le, 1:1 mapping
+ ************************************/
+
+#define READ8TO64LE( name, read8 ) \
+READ_TEMPLATE( 64, name, read8, read64le_with_read8_handler )
+
+
+#define WRITE8TO64LE( name, write8 ) \
+WRITE_TEMPLATE( 64, name, write8, write64le_with_write8_handler )
+
+
+#define READWRITE8TO64LE( name, read8, write8 ) \
+READ8TO64LE(name,read8) \
+WRITE8TO64LE(name,write8)
+
+
+/*************************************
+ * 16be->32be, 1:1 mapping
+ *************************************/
+
+#define READ16BETO32BE( name, read16 ) \
+READ_TEMPLATE( 32, name, read16, read32be_with_16be_handler )
+
+
+#define WRITE16BETO32BE( name, write16 ) \
+WRITE_TEMPLATE( 32, name, write16, write32be_with_16be_handler )
+
+
+#define READWRITE16BETO32BE( name, read16, write16 ) \
+READ16BETO32BE(name,read16) \
+WRITE16BETO32BE(name,write16)
+
+
+/*************************************
+ * 16le->32be, 1:1 mapping
+ *************************************/
+
+#define READ16LETO32BE( name, read16 ) \
+READ_TEMPLATE( 32, name, read16, read32be_with_16le_handler )
+
+
+#define WRITE16LETO32BE( name, write16 ) \
+WRITE_TEMPLATE( 32, name, write16, write32be_with_16le_handler )
+
+
+#define READWRITE16LETO32BE( name, read16, write16 ) \
+READ16LETO32BE(name,read16) \
+WRITE16LETO32BE(name,write16)
+
+
+/*************************************
+ * 16be->32le, 1:1 mapping
+ *************************************/
+
+#define READ16BETO32LE( name, read16 ) \
+READ_TEMPLATE( 32, name, read16, read32le_with_16be_handler )
+
+
+#define WRITE16BETO32LE( name, write16 ) \
+WRITE_TEMPLATE( 32, name, write16, write32le_with_16be_handler )
+
+
+#define READWRITE16BETO32LE( name, read16, write16 ) \
+READ16BETO32LE(name,read16) \
+WRITE16BETO32LE(name,write16)
+
+
+/*************************************
+ * 16le->32le, 1:1 mapping
+ *************************************/
+
+#define READ16LETO32LE( name, read16 ) \
+READ_TEMPLATE( 32, name, read16, read32le_with_16le_handler )
+
+
+#define WRITE16LETO32LE( name, write16 ) \
+WRITE_TEMPLATE( 32, name, write16, write32le_with_16le_handler )
+
+
+#define READWRITE16LETO32LE( name, read16, write16 ) \
+READ16LETO32LE(name,read16) \
+WRITE16LETO32LE(name,write16)
+
+
+/*************************************
+ * 16be->32be, MSW mapping
+ *************************************/
+
+#define READ16BETO32BE_MSW( name, read16 ) \
+READ_TEMPLATE_COND( 32, name, read16, read32be_with_16be_handler, ACCESSING_BITS_16_31 )
+
+
+#define WRITE16BETO32BE_MSW( name, write16 ) \
+WRITE_TEMPLATE_COND( 32, name, write16, write32be_with_16be_handler, ACCESSING_BITS_16_31 )
+
+
+#define READWRITE16BETO32BE_MSW( name, read16, write16 ) \
+READ16BETO32BE_MSW(name,read16) \
+WRITE16BETO32BE_MSW(name,write16)
+
+
+/*************************************
+ * 16le->32be, MSW mapping
+ *************************************/
+
+#define READ16LETO32BE_MSW( name, read16 ) \
+READ_TEMPLATE_COND( 32, name, read16, read32be_with_16le_handler, ACCESSING_BITS_16_31 )
+
+
+#define WRITE16LETO32BE_MSW( name, write16 ) \
+WRITE_TEMPLATE_COND( 32, name, write16, write32be_with_16le_handler, ACCESSING_BITS_16_31 )
+
+
+#define READWRITE16LETO32BE_MSW( name, read16, write16 ) \
+READ16LETO32BE_MSW(name,read16) \
+WRITE16LETO32BE_MSW(name,write16)
+
+
+/*************************************
+ * 16be->32le, MSW mapping
+ *************************************/
+
+#define READ16BETO32LE_MSW( name, read16 ) \
+READ_TEMPLATE_COND( 32, name, read16, read32le_with_16be_handler, ACCESSING_BITS_16_31 )
+
+
+#define WRITE16BETO32LE_MSW( name, write16 ) \
+WRITE_TEMPLATE_COND( 32, name, write16, write32le_with_16be_handler, ACCESSING_BITS_16_31 )
+
+
+#define READWRITE16BETO32LE_MSW( name, read16, write16 ) \
+READ16BETO32LE_MSW(name,read16) \
+WRITE16BETO32LE_MSW(name,write16)
+
+
+/*************************************
+ * 16le->32le, MSW mapping
+ *************************************/
+
+#define READ16LETO32LE_MSW( name, read16 ) \
+READ_TEMPLATE_COND( 32, name, read16, read32le_with_16le_handler, ACCESSING_BITS_16_31 )
+
+
+#define WRITE16LETO32LE_MSW( name, write16 ) \
+WRITE_TEMPLATE_COND( 32, name, write16, write32le_with_16le_handler, ACCESSING_BITS_16_31 )
+
+
+#define READWRITE16LETO32LE_MSW( name, read16, write16 ) \
+READ16LETO32LE_MSW(name,read16) \
+WRITE16LETO32LE_MSW(name,write16)
+
+/*************************************
+ * 16be->32be, LSW mapping
+ *************************************/
+
+#define READ16BETO32BE_LSW( name, read16 ) \
+READ_TEMPLATE_COND( 32, name, read16, read32be_with_16be_handler, ACCESSING_BITS_0_15 )
+
+
+#define WRITE16BETO32BE_LSW( name, write16 ) \
+WRITE_TEMPLATE_COND( 32, name, write16, write32be_with_16be_handler, ACCESSING_BITS_0_15 )
+
+
+#define READWRITE16BETO32BE_LSW( name, read16, write16 ) \
+READ16BETO32BE_LSW(name,read16) \
+WRITE16BETO32BE_LSW(name,write16)
+
+
+/*************************************
+ * 16le->32be, LSW mapping
+ *************************************/
+
+#define READ16LETO32BE_LSW( name, read16 ) \
+READ_TEMPLATE_COND( 32, name, read16, read32be_with_16le_handler, ACCESSING_BITS_0_15 )
+
+
+#define WRITE16LETO32BE_LSW( name, write16 ) \
+WRITE_TEMPLATE_COND( 32, name, write16, write32be_with_16le_handler, ACCESSING_BITS_0_15 )
+
+
+#define READWRITE16LETO32BE_LSW( name, read16, write16 ) \
+READ16LETO32BE_LSW(name,read16) \
+WRITE16LETO32BE_LSW(name,write16)
+
+
+/*************************************
+ * 16be->32le, LSW mapping
+ *************************************/
+
+#define READ16BETO32LE_LSW( name, read16 ) \
+READ_TEMPLATE_COND( 32, name, read16, read32le_with_16be_handler, ACCESSING_BITS_0_15 )
+
+
+#define WRITE16BETO32LE_LSW( name, write16 ) \
+WRITE_TEMPLATE_COND( 32, name, write16, write32le_with_16be_handler, ACCESSING_BITS_0_15 )
+
+
+#define READWRITE16BETO32LE_LSW( name, read16, write16 ) \
+READ16BETO32LE_LSW(name,read16) \
+WRITE16BETO32LE_LSW(name,write16)
+
+
+/*************************************
+ * 16le->32le, LSW mapping
+ *************************************/
+
+#define READ16LETO32LE_LSW( name, read16 ) \
+READ_TEMPLATE_COND( 32, name, read16, read32le_with_16le_handler, ACCESSING_BITS_0_15 )
+
+
+#define WRITE16LETO32LE_LSW( name, write16 ) \
+WRITE_TEMPLATE_COND( 32, name, write16, write32le_with_16le_handler, ACCESSING_BITS_0_15 )
+
+
+#define READWRITE16LETO32LE_LSW( name, read16, write16 ) \
+READ16LETO32LE_LSW(name,read16) \
+WRITE16LETO32LE_LSW(name,write16)
+
diff --git a/trunk/src/emu/memory.c b/trunk/src/emu/memory.c
new file mode 100644
index 00000000000..81080771ab7
--- /dev/null
+++ b/trunk/src/emu/memory.c
@@ -0,0 +1,5868 @@
+/***************************************************************************
+
+ memory.c
+
+ Functions which handle device memory access.
+
+****************************************************************************
+
+ 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.
+
+****************************************************************************
+
+ Basic theory of memory handling:
+
+ An address with up to 32 bits is passed to a memory handler. First,
+ an address mask is applied to the address, removing unused bits.
+
+ Next, the address is broken into two halves, an upper half and a
+ lower half. The number of bits in each half can be controlled via
+ the macros in LEVEL1_BITS and LEVEL2_BITS, but they default to the
+ upper 18 bits and the lower 14 bits.
+
+ The upper half is then used as an index into a lookup table of bytes.
+ If the value pulled from the table is between SUBTABLE_BASE and 255,
+ then the lower half of the address is needed to resolve the final
+ handler. In this case, the value from the table is combined with the
+ lower address bits to form an index into a subtable.
+
+ The final result of the lookup is a value from 0 to SUBTABLE_BASE - 1.
+ These values correspond to memory handlers. The lower numbered
+ handlers (from 0 through STATIC_COUNT - 1) are fixed handlers and refer
+ to either memory banks or other special cases. The remaining handlers
+ (from STATIC_COUNT through SUBTABLE_BASE - 1) are dynamically
+ allocated to driver-specified handlers.
+
+ Thus, table entries fall into these categories:
+
+ 0 .. STATIC_COUNT - 1 = fixed handlers
+ STATIC_COUNT .. SUBTABLE_BASE - 1 = driver-specific handlers
+ SUBTABLE_BASE .. 255 = need to look up lower bits in subtable
+
+ Caveats:
+
+ * If your driver executes an opcode which crosses a bank-switched
+ boundary, it will pull the wrong data out of memory. Although not
+ a common case, you may need to revert to memcpy to work around this.
+ See machine/tnzs.c for an example.
+
+ To do:
+
+ - Add local banks for RAM/ROM to reduce pressure on banking
+ - Always mirror everything out to 32 bits so we don't have to mask the address?
+ - Add the ability to start with another memory map and modify it
+ - Add fourth memory space for encrypted opcodes
+ - Automatically mirror program space into data space if no data space
+ - Get rid of opcode/data separation by using address spaces?
+ - Add support for internal addressing (maybe just accessors - see TMS3202x)
+
+****************************************************************************
+
+ Address map fields and restrictions:
+
+ AM_RANGE(start, end)
+ Specifies a range of consecutive addresses beginning with 'start' and
+ ending with 'end' inclusive. An address hits in this bucket if the
+ 'address' >= 'start' and 'address' <= 'end'.
+
+ AM_MASK(mask)
+ Specifies a mask for the addresses in the current bucket. This mask
+ is applied after a positive hit in the bucket specified by AM_RANGE
+ or AM_SPACE, and is computed before accessing the RAM or calling
+ through to the read/write handler. If you use AM_MIRROR, below, the
+ mask is ANDed implicitly with the logical NOT of the mirror. The
+ mask specified by this macro is ANDed against any implicit masks.
+
+ AM_MIRROR(mirror)
+ Specifies mirror addresses for the given bucket. The current bucket
+ is mapped repeatedly according to the mirror mask, once where each
+ mirror bit is 0, and once where it is 1. For example, a 'mirror'
+ value of 0x14000 would map the bucket at 0x00000, 0x04000, 0x10000,
+ and 0x14000.
+
+ AM_ROM
+ Specifies that this bucket contains ROM data by attaching an
+ internal read handler. If this address space describes the first
+ address space for a device, and if there is a region whose name
+ matches the device's name, and if the bucket start/end range is
+ within the bounds of that region, then this bucket will automatically
+ map to the memory contained in that region.
+
+ AM_RAM
+ AM_READONLY
+ AM_WRITEONLY
+ Specifies that this bucket contains RAM data by attaching internal
+ read and/or write handlers. Memory is automatically allocated to back
+ this area. AM_RAM maps both reads and writes, while AM_READONLY only
+ maps reads and AM_WRITEONLY only maps writes.
+
+ AM_NOP
+ AM_READNOP
+ AM_WRITENOP
+ Specifies that reads and/or writes in this bucket are unmapped, but
+ that accesses to them should not be logged. AM_NOP unmaps both reads
+ and writes, while AM_READNOP only unmaps reads, and AM_WRITENOP only
+ unmaps writes.
+
+ AM_UNMAP
+ Specifies that both reads and writes in thus bucket are unmapeed,
+ and that accesses to them should be logged. There is rarely a need
+ for this, as the entire address space is initialized to behave this
+ way by default.
+
+ AM_READ_BANK(tag)
+ AM_WRITE_BANK(tag)
+ AM_READWRITE_BANK(tag)
+ Specifies that reads and/or writes in this bucket map to a memory
+ bank with the provided 'tag'. The actual memory this bank points to
+ can be later controlled via the same tag.
+
+ AM_READ(read)
+ AM_WRITE(write)
+ AM_READWRITE(read, write)
+ Specifies read and/or write handler callbacks for this bucket. All
+ reads and writes in this bucket will trigger a call to the provided
+ functions.
+
+ AM_DEVREAD(tag, read)
+ AM_DEVWRITE(tag, read)
+ AM_DEVREADWRITE(tag, read)
+ Specifies a device-specific read and/or write handler for this
+ bucket, automatically bound to the device specified by the provided
+ 'tag'.
+
+ AM_READ_PORT(tag)
+ AM_WRITE_PORT(tag)
+ AM_READWRITE_PORT(tag)
+ Specifies that read and/or write accesses in this bucket will map
+ to the I/O port with the provided 'tag'. An internal read/write
+ handler is set up to handle this mapping.
+
+ AM_REGION(class, tag, offs)
+ Only useful if used in conjunction with AM_ROM, AM_RAM, or
+ AM_READ/WRITE_BANK. By default, memory is allocated to back each
+ bucket. By specifying AM_REGION, you can tell the memory system to
+ point the base of the memory backing this bucket to a given memory
+ 'region' at the specified 'offs' instead of allocating it.
+
+ AM_SHARE(tag)
+ Similar to AM_REGION, this specifies that the memory backing the
+ current bucket is shared with other buckets. The first bucket to
+ specify the share 'tag' will use its memory as backing for all
+ future buckets that specify AM_SHARE with the same 'tag'.
+
+ AM_BASE(base)
+ Specifies a pointer to a pointer to the base of the memory backing
+ the current bucket.
+
+ AM_SIZE(size)
+ Specifies a pointer to a size_t variable which will be filled in
+ with the size, in bytes, of the current bucket.
+
+ AM_BASE_MEMBER(struct, basefield)
+ AM_SIZE_MEMBER(struct, sizefield)
+ Specifies a field within a given struct as where to store the base
+ or size of the current bucket. The struct is assumed to be hanging
+ off of the machine.driver_data pointer.
+
+ AM_BASE_GENERIC(basefield)
+ AM_SIZE_GENERIC(sizefield)
+ Specifies a field within the global generic_pointers struct as
+ where to store the base or size of the current bucket. The global
+ generic_pointer struct lives in machine.generic.
+
+***************************************************************************/
+
+#include <list>
+#include <map>
+
+#include "emu.h"
+#include "profiler.h"
+#include "debug/debugcpu.h"
+
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define MEM_DUMP (0)
+#define VERBOSE (0)
+#define TEST_HANDLER (0)
+
+#define VPRINTF(x) do { if (VERBOSE) printf x; } while (0)
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// banking constants
+const int BANK_ENTRY_UNSPECIFIED = -1;
+
+// other address map constants
+const int MEMORY_BLOCK_CHUNK = 65536; // minimum chunk size of allocated memory blocks
+
+// static data access handler constants
+enum
+{
+ STATIC_INVALID = 0, // invalid - should never be used
+ STATIC_BANK1 = 1, // first memory bank
+ STATIC_BANKMAX = 124, // last memory bank
+ STATIC_NOP, // NOP - reads = unmapped value; writes = no-op
+ STATIC_UNMAP, // unmapped - same as NOP except we log errors
+ STATIC_WATCHPOINT, // watchpoint - used internally
+ STATIC_COUNT // total number of static handlers
+};
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> memory_block
+
+// a memory block is a chunk of RAM associated with a range of memory in a device's address space
+class memory_block
+{
+ DISABLE_COPYING(memory_block);
+
+ friend class simple_list<memory_block>;
+ friend resource_pool_object<memory_block>::~resource_pool_object();
+
+public:
+ // construction/destruction
+ memory_block(address_space &space, offs_t bytestart, offs_t byteend, void *memory = NULL);
+ ~memory_block();
+
+ // getters
+ running_machine &machine() const { return m_machine; }
+ memory_block *next() const { return m_next; }
+ offs_t bytestart() const { return m_bytestart; }
+ offs_t byteend() const { return m_byteend; }
+ UINT8 *data() const { return m_data; }
+
+ // is the given range contained by this memory block?
+ bool contains(address_space &space, offs_t bytestart, offs_t byteend) const
+ {
+ return (&space == &m_space && m_bytestart <= bytestart && m_byteend >= byteend);
+ }
+
+private:
+ // internal state
+ memory_block * m_next; // next memory block in the list
+ running_machine & m_machine; // need the machine to free our memory
+ address_space & m_space; // which address space are we associated with?
+ offs_t m_bytestart, m_byteend; // byte-normalized start/end for verifying a match
+ UINT8 * m_data; // pointer to the data for this block
+ UINT8 * m_allocated; // pointer to the actually allocated block
+};
+
+
+// ======================> memory_bank
+
+// a memory bank is a global pointer to memory that can be shared across devices and changed dynamically
+class memory_bank
+{
+ friend class simple_list<memory_bank>;
+ friend resource_pool_object<memory_bank>::~resource_pool_object();
+
+ // a bank reference is an entry in a list of address spaces that reference a given bank
+ class bank_reference
+ {
+ friend class simple_list<bank_reference>;
+ friend resource_pool_object<bank_reference>::~resource_pool_object();
+
+ public:
+ // construction/destruction
+ bank_reference(address_space &space, read_or_write readorwrite)
+ : m_next(NULL),
+ m_space(space),
+ m_readorwrite(readorwrite) { }
+
+ // getters
+ bank_reference *next() const { return m_next; }
+ address_space &space() const { return m_space; }
+
+ // does this reference match the space+read/write combination?
+ bool matches(address_space &space, read_or_write readorwrite) const
+ {
+ return (&space == &m_space && (readorwrite == ROW_READWRITE || readorwrite == m_readorwrite));
+ }
+
+ private:
+ // internal state
+ bank_reference * m_next; // link to the next reference
+ address_space & m_space; // address space that references us
+ read_or_write m_readorwrite; // used for read or write?
+ };
+
+ // a bank_entry contains a raw and decrypted pointer
+ struct bank_entry
+ {
+ UINT8 * m_raw;
+ UINT8 * m_decrypted;
+ };
+
+public:
+ // construction/destruction
+ memory_bank(address_space &space, int index, offs_t bytestart, offs_t byteend, const char *tag = NULL);
+ ~memory_bank();
+
+ // getters
+ memory_bank *next() const { return m_next; }
+ running_machine &machine() const { return m_machine; }
+ int index() const { return m_index; }
+ int entry() const { return m_curentry; }
+ bool anonymous() const { return m_anonymous; }
+ offs_t bytestart() const { return m_bytestart; }
+ void *base() const { return *m_baseptr; }
+ void *base_decrypted() const { return *m_basedptr; }
+ const char *tag() const { return m_tag; }
+ const char *name() const { return m_name; }
+
+ // compare a range against our range
+ bool matches_exactly(offs_t bytestart, offs_t byteend) const { return (m_bytestart == bytestart && m_byteend == byteend); }
+ bool fully_covers(offs_t bytestart, offs_t byteend) const { return (m_bytestart <= bytestart && m_byteend >= byteend); }
+ bool is_covered_by(offs_t bytestart, offs_t byteend) const { return (m_bytestart >= bytestart && m_byteend <= byteend); }
+ bool straddles(offs_t bytestart, offs_t byteend) const { return (m_bytestart < byteend && m_byteend > bytestart); }
+
+ // track and verify address space references to this bank
+ bool references_space(address_space &space, read_or_write readorwrite) const;
+ void add_reference(address_space &space, read_or_write readorwrite);
+
+ // set the base explicitly
+ void set_base(void *base);
+ void set_base_decrypted(void *base);
+
+ // configure and set entries
+ void configure(int entrynum, void *base);
+ void configure_decrypted(int entrynum, void *base);
+ void set_entry(int entrynum);
+
+private:
+ // internal helpers
+ void invalidate_references();
+ void expand_entries(int entrynum);
+
+ // internal state
+ memory_bank * m_next; // next bank in sequence
+ running_machine & m_machine; // need the machine to free our memory
+ UINT8 ** m_baseptr; // pointer to our base pointer in the global array
+ UINT8 ** m_basedptr; // same for the decrypted base pointer
+ UINT8 m_index; // array index for this handler
+ bool m_anonymous; // are we anonymous or explicit?
+ offs_t m_bytestart; // byte-adjusted start offset
+ offs_t m_byteend; // byte-adjusted end offset
+ int m_curentry; // current entry
+ bank_entry * m_entry; // array of entries (dynamically allocated)
+ int m_entry_count; // number of allocated entries
+ astring m_name; // friendly name for this bank
+ astring m_tag; // tag for this bank
+ simple_list<bank_reference> m_reflist; // linked list of address spaces referencing this bank
+};
+
+
+// ======================> memory_share
+
+// a memory share contains information about shared memory region
+class memory_share
+{
+public:
+ // construction/destruction
+ memory_share(size_t size, void *ptr = NULL)
+ : m_ptr(ptr),
+ m_size(size) { }
+
+ // getters
+ void *ptr() const { return m_ptr; }
+ size_t size() const { return m_size; }
+
+ // setters
+ void set_ptr(void *ptr) { m_ptr = ptr; }
+
+private:
+ // internal state
+ void * m_ptr; // pointer to the memory backing the region
+ size_t m_size; // size of the shared region
+};
+
+
+// ======================> handler_entry
+
+// a handler entry contains information about a memory handler
+class handler_entry
+{
+ DISABLE_COPYING(handler_entry);
+
+protected:
+ // construction/destruction
+ handler_entry(UINT8 width, endianness_t endianness, UINT8 **rambaseptr);
+ virtual ~handler_entry();
+
+public:
+ // getters
+ bool populated() const { return m_populated; }
+ offs_t bytestart() const { return m_bytestart; }
+ offs_t byteend() const { return m_byteend; }
+ offs_t bytemask() const { return m_bytemask; }
+ virtual const char *name() const = 0;
+ virtual const char *subunit_name(int entry) const = 0;
+ void description(char *buffer) const;
+
+ virtual void copy(handler_entry *entry);
+
+ // return offset within the range referenced by this handler
+ offs_t byteoffset(offs_t byteaddress) const { return (byteaddress - m_bytestart) & m_bytemask; }
+
+ // return a pointer to the backing RAM at the given offset
+ UINT8 *ramptr(offs_t offset = 0) const { return *m_rambaseptr + offset; }
+
+ // see if we are an exact match to the given parameters
+ bool matches_exactly(offs_t bytestart, offs_t byteend, offs_t bytemask) const
+ {
+ return (m_populated && m_bytestart == bytestart && m_byteend == byteend && m_bytemask == bytemask);
+ }
+
+ // get the start/end address with the given mirror
+ void mirrored_start_end(offs_t byteaddress, offs_t &start, offs_t &end) const
+ {
+ offs_t mirrorbits = (byteaddress - m_bytestart) & ~m_bytemask;
+ start = m_bytestart | mirrorbits;
+ end = m_byteend | mirrorbits;
+ }
+
+ // configure the handler addresses, and mark as populated
+ void configure(offs_t bytestart, offs_t byteend, offs_t bytemask)
+ {
+ if (m_populated && m_subunits)
+ reconfigure_subunits(bytestart);
+ m_populated = true;
+ m_bytestart = bytestart;
+ m_byteend = byteend;
+ m_bytemask = bytemask;
+ }
+
+ // reconfigure the subunits on a base address change
+ void reconfigure_subunits(offs_t bytestart);
+
+ // depopulate an handler
+ void deconfigure()
+ {
+ m_populated = false;
+ m_subunits = 0;
+ }
+
+ // apply a global mask
+ void apply_mask(offs_t bytemask) { m_bytemask &= bytemask; }
+
+ void clear_conflicting_subunits(UINT64 handlermask);
+ bool overriden_by_mask(UINT64 handlermask);
+
+protected:
+ // Subunit description information
+ struct subunit_info
+ {
+ UINT32 m_mask; // mask (ff, ffff or ffffffff)
+ UINT32 m_offset; // offset to add to the address
+ UINT32 m_multiplier; // multiplier to the pre-split address
+ UINT8 m_size; // size (8, 16 or 32)
+ UINT8 m_shift; // shift of the subunit
+ };
+
+ // internal helpers
+ void configure_subunits(UINT64 handlermask, int handlerbits, int &start_slot, int &end_slot);
+ virtual void remove_subunit(int entry) = 0;
+
+ // internal state
+ bool m_populated; // populated?
+ UINT8 m_datawidth;
+ endianness_t m_endianness;
+ offs_t m_bytestart; // byte-adjusted start address for handler
+ offs_t m_byteend; // byte-adjusted end address for handler
+ offs_t m_bytemask; // byte-adjusted mask against the final address
+ UINT8 ** m_rambaseptr; // pointer to the bank base
+ UINT8 m_subunits; // for width stubs, the number of subunits
+ subunit_info m_subunit_infos[8]; // for width stubs, the associated subunit info
+ UINT64 m_invsubmask; // inverted mask of the populated subunits
+};
+
+
+// ======================> handler_entry_read
+
+// a read-access-specific extension of handler_entry
+class handler_entry_read : public handler_entry
+{
+public:
+ // combination of unions to hold legacy objects and callbacks
+ struct legacy_info
+ {
+ union
+ {
+ address_space * space;
+ device_t * device;
+ } object;
+
+ union
+ {
+ read8_space_func space8;
+ read16_space_func space16;
+ read32_space_func space32;
+ read64_space_func space64;
+ read8_device_func device8;
+ read16_device_func device16;
+ read32_device_func device32;
+ read64_device_func device64;
+ } handler;
+ };
+
+ struct access_handler
+ {
+ // Constructors mean you can't union them
+ read8_delegate r8;
+ read16_delegate r16;
+ read32_delegate r32;
+ read64_delegate r64;
+ };
+
+ // construction/destruction
+ handler_entry_read(UINT8 width, endianness_t endianness, UINT8 **rambaseptr)
+ : handler_entry(width, endianness, rambaseptr)
+ {
+ memset(&m_legacy_info, 0, sizeof(m_legacy_info));
+ }
+
+ virtual void copy(handler_entry *entry);
+
+ // getters
+ virtual const char *name() const;
+ virtual const char *subunit_name(int entry) const;
+
+ // configure delegate callbacks
+ void set_delegate(read8_delegate delegate, UINT64 mask = 0, const legacy_info *info = 0);
+ void set_delegate(read16_delegate delegate, UINT64 mask = 0, const legacy_info *info = 0);
+ void set_delegate(read32_delegate delegate, UINT64 mask = 0, const legacy_info *info = 0);
+ void set_delegate(read64_delegate delegate, UINT64 mask = 0, const legacy_info *info = 0);
+
+ // configure legacy address space functions
+ void set_legacy_func(address_space &space, read8_space_func func, const char *name, UINT64 mask = 0);
+ void set_legacy_func(address_space &space, read16_space_func func, const char *name, UINT64 mask = 0);
+ void set_legacy_func(address_space &space, read32_space_func func, const char *name, UINT64 mask = 0);
+ void set_legacy_func(address_space &space, read64_space_func func, const char *name, UINT64 mask = 0);
+
+ // configure legacy device functions
+ void set_legacy_func(device_t &device, read8_device_func func, const char *name, UINT64 mask = 0);
+ void set_legacy_func(device_t &device, read16_device_func func, const char *name, UINT64 mask = 0);
+ void set_legacy_func(device_t &device, read32_device_func func, const char *name, UINT64 mask = 0);
+ void set_legacy_func(device_t &device, read64_device_func func, const char *name, UINT64 mask = 0);
+
+ // configure I/O port access
+ void set_ioport(const input_port_config &ioport);
+
+ // read via the underlying delegates
+ UINT8 read8(address_space &space, offs_t offset, UINT8 mask) const { return m_read.r8(space, offset, mask); }
+ UINT16 read16(address_space &space, offs_t offset, UINT16 mask) const { return m_read.r16(space, offset, mask); }
+ UINT32 read32(address_space &space, offs_t offset, UINT32 mask) const { return m_read.r32(space, offset, mask); }
+ UINT64 read64(address_space &space, offs_t offset, UINT64 mask) const { return m_read.r64(space, offset, mask); }
+
+private:
+ // stubs for converting between address sizes
+ UINT16 read_stub_16(address_space &space, offs_t offset, UINT16 mask);
+ UINT32 read_stub_32(address_space &space, offs_t offset, UINT32 mask);
+ UINT64 read_stub_64(address_space &space, offs_t offset, UINT64 mask);
+
+ // stubs for calling legacy read handlers
+ UINT8 read_stub_legacy(address_space &space, offs_t offset, UINT8 mask);
+ UINT16 read_stub_legacy(address_space &space, offs_t offset, UINT16 mask);
+ UINT32 read_stub_legacy(address_space &space, offs_t offset, UINT32 mask);
+ UINT64 read_stub_legacy(address_space &space, offs_t offset, UINT64 mask);
+
+ // stubs for reading I/O ports
+ template<typename _UintType>
+ _UintType read_stub_ioport(address_space &space, offs_t offset, _UintType mask) { return input_port_read_direct(m_ioport); }
+
+ // internal helper
+ virtual void remove_subunit(int entry);
+
+ // internal state
+ access_handler m_read;
+ access_handler m_subread[8];
+ const input_port_config * m_ioport;
+
+ bool m_sub_is_legacy[8];
+ legacy_info m_legacy_info;
+ legacy_info m_sublegacy_info[8];
+};
+
+
+// ======================> handler_entry_write
+
+// a write-access-specific extension of handler_entry
+class handler_entry_write : public handler_entry
+{
+public:
+ // combination of unions to hold legacy objects and callbacks
+ struct legacy_info
+ {
+ union
+ {
+ address_space * space;
+ device_t * device;
+ } object;
+
+ union
+ {
+ write8_space_func space8;
+ write16_space_func space16;
+ write32_space_func space32;
+ write64_space_func space64;
+ write8_device_func device8;
+ write16_device_func device16;
+ write32_device_func device32;
+ write64_device_func device64;
+ } handler;
+ };
+
+ struct access_handler
+ {
+ // Constructors mean you can't union them
+ write8_delegate w8;
+ write16_delegate w16;
+ write32_delegate w32;
+ write64_delegate w64;
+ };
+
+ // construction/destruction
+ handler_entry_write(UINT8 width, endianness_t endianness, UINT8 **rambaseptr)
+ : handler_entry(width, endianness, rambaseptr)
+ {
+ memset(&m_legacy_info, 0, sizeof(m_legacy_info));
+ }
+
+ virtual void copy(handler_entry *entry);
+
+ // getters
+ virtual const char *name() const;
+ virtual const char *subunit_name(int entry) const;
+
+ // configure delegate callbacks
+ void set_delegate(write8_delegate delegate, UINT64 mask = 0, const legacy_info *info = 0);
+ void set_delegate(write16_delegate delegate, UINT64 mask = 0, const legacy_info *info = 0);
+ void set_delegate(write32_delegate delegate, UINT64 mask = 0, const legacy_info *info = 0);
+ void set_delegate(write64_delegate delegate, UINT64 mask = 0, const legacy_info *info = 0);
+
+ // configure legacy address space functions
+ void set_legacy_func(address_space &space, write8_space_func func, const char *name, UINT64 mask = 0);
+ void set_legacy_func(address_space &space, write16_space_func func, const char *name, UINT64 mask = 0);
+ void set_legacy_func(address_space &space, write32_space_func func, const char *name, UINT64 mask = 0);
+ void set_legacy_func(address_space &space, write64_space_func func, const char *name, UINT64 mask = 0);
+
+ // configure legacy device functions
+ void set_legacy_func(device_t &device, write8_device_func func, const char *name, UINT64 mask = 0);
+ void set_legacy_func(device_t &device, write16_device_func func, const char *name, UINT64 mask = 0);
+ void set_legacy_func(device_t &device, write32_device_func func, const char *name, UINT64 mask = 0);
+ void set_legacy_func(device_t &device, write64_device_func func, const char *name, UINT64 mask = 0);
+
+ // configure I/O port access
+ void set_ioport(const input_port_config &ioport);
+
+ // write via the underlying delegates
+ void write8(address_space &space, offs_t offset, UINT8 data, UINT8 mask) const { m_write.w8(space, offset, data, mask); }
+ void write16(address_space &space, offs_t offset, UINT16 data, UINT16 mask) const { m_write.w16(space, offset, data, mask); }
+ void write32(address_space &space, offs_t offset, UINT32 data, UINT32 mask) const { m_write.w32(space, offset, data, mask); }
+ void write64(address_space &space, offs_t offset, UINT64 data, UINT64 mask) const { m_write.w64(space, offset, data, mask); }
+
+private:
+ // stubs for converting between address sizes
+ void write_stub_16(address_space &space, offs_t offset, UINT16 data, UINT16 mask);
+ void write_stub_32(address_space &space, offs_t offset, UINT32 data, UINT32 mask);
+ void write_stub_64(address_space &space, offs_t offset, UINT64 data, UINT64 mask);
+
+ // stubs for calling legacy write handlers
+ void write_stub_legacy(address_space &space, offs_t offset, UINT8 data, UINT8 mask);
+ void write_stub_legacy(address_space &space, offs_t offset, UINT16 data, UINT16 mask);
+ void write_stub_legacy(address_space &space, offs_t offset, UINT32 data, UINT32 mask);
+ void write_stub_legacy(address_space &space, offs_t offset, UINT64 data, UINT64 mask);
+
+ // stubs for writing I/O ports
+ template<typename _UintType>
+ void write_stub_ioport(address_space &space, offs_t offset, _UintType data, _UintType mask) { input_port_write_direct(m_ioport, data, mask); }
+
+ // internal helper
+ virtual void remove_subunit(int entry);
+
+ // internal state
+ access_handler m_write;
+ access_handler m_subwrite[8];
+ const input_port_config * m_ioport;
+
+ bool m_sub_is_legacy[8];
+ legacy_info m_legacy_info;
+ legacy_info m_sublegacy_info[8];
+};
+
+// ======================> handler_entry_proxy
+
+// A proxy class that contains an handler_entry_read or _write and forwards the setter calls
+
+template<typename _HandlerEntry>
+class handler_entry_proxy
+{
+public:
+ handler_entry_proxy(const std::list<_HandlerEntry *> &_handlers, UINT64 _mask) : handlers(_handlers), mask(_mask) {}
+ handler_entry_proxy(const handler_entry_proxy<_HandlerEntry> &hep) : handlers(hep.handlers), mask(hep.mask) {}
+
+ // forward delegate callbacks configuration
+ template<typename _delegate> void set_delegate(_delegate delegate) const {
+ for (typename std::list<_HandlerEntry *>::const_iterator i = handlers.begin(); i != handlers.end(); i++)
+ (*i)->set_delegate(delegate, mask);
+ }
+
+ // forward legacy address space functions configuration
+ template<typename _func> void set_legacy_func(address_space &space, _func func, const char *name) const {
+ for (typename std::list<_HandlerEntry *>::const_iterator i = handlers.begin(); i != handlers.end(); i++)
+ (*i)->set_legacy_func(space, func, name, mask);
+ }
+
+ // forward legacy device functions configuration
+ template<typename _func> void set_legacy_func(device_t &device, _func func, const char *name) const {
+ for (typename std::list<_HandlerEntry *>::const_iterator i = handlers.begin(); i != handlers.end(); i++)
+ (*i)->set_legacy_func(device, func, name, mask);
+ }
+
+ // forward I/O port access configuration
+ void set_ioport(const input_port_config &ioport) const {
+ for (typename std::list<_HandlerEntry *>::const_iterator i = handlers.begin(); i != handlers.end(); i++)
+ (*i)->set_ioport(ioport);
+ }
+
+private:
+ std::list<_HandlerEntry *> handlers;
+ UINT64 mask;
+};
+
+
+// ======================> address_table
+
+// address_table contains information about read/write accesses within an address space
+class address_table
+{
+ // address map lookup table definitions
+ static const int LEVEL1_BITS = 18; // number of address bits in the level 1 table
+ static const int LEVEL2_BITS = 32 - LEVEL1_BITS; // number of address bits in the level 2 table
+ static const int SUBTABLE_COUNT = 64; // number of slots reserved for subtables
+ static const int SUBTABLE_BASE = 256 - SUBTABLE_COUNT; // first index of a subtable
+ static const int ENTRY_COUNT = SUBTABLE_BASE; // number of legitimate (non-subtable) entries
+ static const int SUBTABLE_ALLOC = 8; // number of subtables to allocate at a time
+
+ inline int level2_bits() const { return m_large ? LEVEL2_BITS : 0; }
+
+public:
+ // construction/destruction
+ address_table(address_space &space, bool large);
+ virtual ~address_table();
+
+ // getters
+ virtual handler_entry &handler(UINT32 index) const = 0;
+ bool watchpoints_enabled() const { return (m_live_lookup == s_watchpoint_table); }
+
+ // address lookups
+ UINT32 lookup_live(offs_t byteaddress) const { return m_large ? lookup_live_large(byteaddress) : lookup_live_small(byteaddress); }
+ UINT32 lookup_live_small(offs_t byteaddress) const { return m_live_lookup[byteaddress]; }
+
+ UINT32 lookup_live_large(offs_t byteaddress) const
+ {
+ UINT32 entry = m_live_lookup[level1_index_large(byteaddress)];
+ if (entry >= SUBTABLE_BASE)
+ entry = m_live_lookup[level2_index_large(entry, byteaddress)];
+ return entry;
+ }
+
+ UINT32 lookup(offs_t byteaddress) const
+ {
+ UINT32 entry = m_live_lookup[level1_index(byteaddress)];
+ if (entry >= SUBTABLE_BASE)
+ entry = m_live_lookup[level2_index(entry, byteaddress)];
+ return entry;
+ }
+
+ // enable watchpoints by swapping in the watchpoint table
+ void enable_watchpoints(bool enable = true) { m_live_lookup = enable ? s_watchpoint_table : m_table; }
+
+ // table mapping helpers
+ void map_range(offs_t bytestart, offs_t byteend, offs_t bytemask, offs_t bytemirror, UINT8 staticentry);
+ void setup_range(offs_t bytestart, offs_t byteend, offs_t bytemask, offs_t bytemirror, UINT64 mask, std::list<UINT32> &entries);
+ UINT8 derive_range(offs_t byteaddress, offs_t &bytestart, offs_t &byteend) const;
+
+ // misc helpers
+ void mask_all_handlers(offs_t mask);
+ const char *handler_name(UINT8 entry) const;
+
+protected:
+ // determine table indexes based on the address
+ UINT32 level1_index_large(offs_t address) const { return address >> LEVEL2_BITS; }
+ UINT32 level2_index_large(UINT8 l1entry, offs_t address) const { return (1 << LEVEL1_BITS) + ((l1entry - SUBTABLE_BASE) << LEVEL2_BITS) + (address & ((1 << LEVEL2_BITS) - 1)); }
+ UINT32 level1_index(offs_t address) const { return m_large ? level1_index_large(address) : address; }
+ UINT32 level2_index(UINT8 l1entry, offs_t address) const { return m_large ? level2_index_large(l1entry, address) : 0; }
+
+ // table population/depopulation
+ void populate_range_mirrored(offs_t bytestart, offs_t byteend, offs_t bytemirror, UINT8 handler);
+ void populate_range(offs_t bytestart, offs_t byteend, UINT8 handler);
+
+ // subtable management
+ UINT8 subtable_alloc();
+ void subtable_realloc(UINT8 subentry);
+ int subtable_merge();
+ void subtable_release(UINT8 subentry);
+ UINT8 *subtable_open(offs_t l1index);
+ void subtable_close(offs_t l1index);
+ UINT8 *subtable_ptr(UINT8 entry) { return &m_table[level2_index(entry, 0)]; }
+
+ // internal state
+ UINT8 * m_table; // pointer to base of table
+ UINT8 * m_live_lookup; // current lookup
+ address_space & m_space; // pointer back to the space
+ bool m_large; // large memory model?
+
+ // subtable_data is an internal class with information about each subtable
+ class subtable_data
+ {
+ public:
+ subtable_data()
+ : m_checksum_valid(false),
+ m_checksum(0),
+ m_usecount(0) { }
+
+ bool m_checksum_valid; // is the checksum valid
+ UINT32 m_checksum; // checksum over all the bytes
+ UINT32 m_usecount; // number of times this has been used
+ };
+ subtable_data * m_subtable; // info about each subtable
+ UINT8 m_subtable_alloc; // number of subtables allocated
+
+ // static global read-only watchpoint table
+ static UINT8 s_watchpoint_table[1 << LEVEL1_BITS];
+
+private:
+ int handler_refcount[SUBTABLE_BASE-STATIC_COUNT];
+ UINT8 handler_next_free[SUBTABLE_BASE-STATIC_COUNT];
+ UINT8 handler_free;
+ UINT8 get_free_handler();
+ void verify_reference_counts();
+ void setup_range_solid(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, std::list<UINT32> &entries);
+ void setup_range_masked(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, UINT64 mask, std::list<UINT32> &entries);
+
+ void handler_ref(UINT8 entry, int count)
+ {
+ assert(entry < SUBTABLE_BASE);
+ if (entry >= STATIC_COUNT)
+ handler_refcount[entry - STATIC_COUNT] += count;
+ }
+
+ void handler_unref(UINT8 entry)
+ {
+ assert(entry < SUBTABLE_BASE);
+ if (entry >= STATIC_COUNT)
+ if (! --handler_refcount[entry - STATIC_COUNT])
+ {
+ handler(entry).deconfigure();
+ handler_next_free[entry - STATIC_COUNT] = handler_free;
+ handler_free = entry;
+ }
+ }
+};
+
+
+// ======================> address_table_read
+
+// read access-specific version of an address table
+class address_table_read : public address_table
+{
+public:
+ // construction/destruction
+ address_table_read(address_space &space, bool large);
+ virtual ~address_table_read();
+
+ // getters
+ virtual handler_entry &handler(UINT32 index) const;
+ handler_entry_read &handler_read(UINT32 index) const { assert(index < ARRAY_LENGTH(m_handlers)); return *m_handlers[index]; }
+
+ // range getter
+ handler_entry_proxy<handler_entry_read> handler_map_range(offs_t bytestart, offs_t byteend, offs_t bytemask, offs_t bytemirror, UINT64 mask = 0) {
+ std::list<UINT32> entries;
+ setup_range(bytestart, byteend, bytemask, bytemirror, mask, entries);
+ std::list<handler_entry_read *> handlers;
+ for (std::list<UINT32>::const_iterator i = entries.begin(); i != entries.end(); i++)
+ handlers.push_back(&handler_read(*i));
+ return handler_entry_proxy<handler_entry_read>(handlers, mask);
+ }
+
+private:
+ // internal unmapped handler
+ template<typename _UintType>
+ _UintType unmap_r(address_space &space, offs_t offset, _UintType mask)
+ {
+ if (m_space.log_unmap() && !m_space.debugger_access())
+ logerror("%s: unmapped %s memory read from %s & %s\n",
+ m_space.machine().describe_context(), m_space.name(),
+ core_i64_hex_format(m_space.byte_to_address(offset * sizeof(_UintType)), m_space.addrchars()),
+ core_i64_hex_format(mask, 2 * sizeof(_UintType)));
+ return m_space.unmap();
+ }
+
+ // internal no-op handler
+ template<typename _UintType>
+ _UintType nop_r(address_space &space, offs_t offset, _UintType mask)
+ {
+ return m_space.unmap();
+ }
+
+ // internal watchpoint handler
+ template<typename _UintType>
+ _UintType watchpoint_r(address_space &space, offs_t offset, _UintType mask)
+ {
+ m_space.device().debug()->memory_read_hook(m_space, offset * sizeof(_UintType), mask);
+
+ UINT8 *oldtable = m_live_lookup;
+ m_live_lookup = m_table;
+ _UintType result;
+ if (sizeof(_UintType) == 1) result = m_space.read_byte(offset);
+ if (sizeof(_UintType) == 2) result = m_space.read_word(offset << 1, mask);
+ if (sizeof(_UintType) == 4) result = m_space.read_dword(offset << 2, mask);
+ if (sizeof(_UintType) == 8) result = m_space.read_qword(offset << 3, mask);
+ m_live_lookup = oldtable;
+ return result;
+ }
+
+ // internal state
+ handler_entry_read * m_handlers[256]; // array of user-installed handlers
+};
+
+
+// ======================> address_table_write
+
+// write access-specific version of an address table
+class address_table_write : public address_table
+{
+public:
+ // construction/destruction
+ address_table_write(address_space &space, bool large);
+ virtual ~address_table_write();
+
+ // getters
+ virtual handler_entry &handler(UINT32 index) const;
+ handler_entry_write &handler_write(UINT32 index) const { assert(index < ARRAY_LENGTH(m_handlers)); return *m_handlers[index]; }
+
+ // range getter
+ handler_entry_proxy<handler_entry_write> handler_map_range(offs_t bytestart, offs_t byteend, offs_t bytemask, offs_t bytemirror, UINT64 mask = 0) {
+ std::list<UINT32> entries;
+ setup_range(bytestart, byteend, bytemask, bytemirror, mask, entries);
+ std::list<handler_entry_write *> handlers;
+ for (std::list<UINT32>::const_iterator i = entries.begin(); i != entries.end(); i++)
+ handlers.push_back(&handler_write(*i));
+ return handler_entry_proxy<handler_entry_write>(handlers, mask);
+ }
+
+private:
+ // internal handlers
+ template<typename _UintType>
+ void unmap_w(address_space &space, offs_t offset, _UintType data, _UintType mask)
+ {
+ if (m_space.log_unmap() && !m_space.debugger_access())
+ logerror("%s: unmapped %s memory write to %s = %s & %s\n",
+ m_space.machine().describe_context(), m_space.name(),
+ core_i64_hex_format(m_space.byte_to_address(offset * sizeof(_UintType)), m_space.addrchars()),
+ core_i64_hex_format(data, 2 * sizeof(_UintType)),
+ core_i64_hex_format(mask, 2 * sizeof(_UintType)));
+ }
+
+ template<typename _UintType>
+ void nop_w(address_space &space, offs_t offset, _UintType data, _UintType mask)
+ {
+ }
+
+ template<typename _UintType>
+ void watchpoint_w(address_space &space, offs_t offset, _UintType data, _UintType mask)
+ {
+ m_space.device().debug()->memory_write_hook(m_space, offset * sizeof(_UintType), data, mask);
+
+ UINT8 *oldtable = m_live_lookup;
+ m_live_lookup = m_table;
+ if (sizeof(_UintType) == 1) m_space.write_byte(offset, data);
+ if (sizeof(_UintType) == 2) m_space.write_word(offset << 1, data, mask);
+ if (sizeof(_UintType) == 4) m_space.write_dword(offset << 2, data, mask);
+ if (sizeof(_UintType) == 8) m_space.write_qword(offset << 3, data, mask);
+ m_live_lookup = oldtable;
+ }
+
+ // internal state
+ handler_entry_write * m_handlers[256]; // array of user-installed handlers
+};
+
+
+// ======================> address_space_specific
+
+// this is a derived class of address_space with specific width, endianness, and table size
+template<typename _NativeType, endianness_t _Endian, bool _Large>
+class address_space_specific : public address_space
+{
+ typedef address_space_specific<_NativeType, _Endian, _Large> this_type;
+
+ // constants describing the native size
+ static const UINT32 NATIVE_BYTES = sizeof(_NativeType);
+ static const UINT32 NATIVE_MASK = NATIVE_BYTES - 1;
+ static const UINT32 NATIVE_BITS = 8 * NATIVE_BYTES;
+
+ // helpers to simplify core code
+ UINT32 read_lookup(offs_t byteaddress) const { return _Large ? m_read.lookup_live_large(byteaddress) : m_read.lookup_live_small(byteaddress); }
+ UINT32 write_lookup(offs_t byteaddress) const { return _Large ? m_write.lookup_live_large(byteaddress) : m_write.lookup_live_small(byteaddress); }
+
+public:
+ // construction/destruction
+ address_space_specific(device_memory_interface &memory, address_spacenum spacenum)
+ : address_space(memory, spacenum, _Large),
+ m_read(*this, _Large),
+ m_write(*this, _Large)
+ {
+#if (TEST_HANDLER)
+ // test code to verify the read/write handlers are touching the correct bits
+ // and returning the correct results
+
+ // install some dummy RAM for the first 16 bytes with well-known values
+ UINT8 buffer[16];
+ for (int index = 0; index < 16; index++)
+ buffer[index ^ ((_Endian == ENDIANNESS_NATIVE) ? 0 : (data_width()/8 - 1))] = index * 0x11;
+ install_ram_generic(0x00, 0x0f, 0x0f, 0, ROW_READWRITE, buffer);
+ printf("\n\naddress_space(%d, %s, %s)\n", NATIVE_BITS, (_Endian == ENDIANNESS_LITTLE) ? "little" : "big", _Large ? "large" : "small");
+
+ // walk through the first 8 addresses
+ for (int address = 0; address < 8; address++)
+ {
+ // determine expected values
+ UINT64 expected64 = ((UINT64)((address + ((_Endian == ENDIANNESS_LITTLE) ? 7 : 0)) * 0x11) << 56) |
+ ((UINT64)((address + ((_Endian == ENDIANNESS_LITTLE) ? 6 : 1)) * 0x11) << 48) |
+ ((UINT64)((address + ((_Endian == ENDIANNESS_LITTLE) ? 5 : 2)) * 0x11) << 40) |
+ ((UINT64)((address + ((_Endian == ENDIANNESS_LITTLE) ? 4 : 3)) * 0x11) << 32) |
+ ((UINT64)((address + ((_Endian == ENDIANNESS_LITTLE) ? 3 : 4)) * 0x11) << 24) |
+ ((UINT64)((address + ((_Endian == ENDIANNESS_LITTLE) ? 2 : 5)) * 0x11) << 16) |
+ ((UINT64)((address + ((_Endian == ENDIANNESS_LITTLE) ? 1 : 6)) * 0x11) << 8) |
+ ((UINT64)((address + ((_Endian == ENDIANNESS_LITTLE) ? 0 : 7)) * 0x11) << 0);
+ UINT32 expected32 = (_Endian == ENDIANNESS_LITTLE) ? expected64 : (expected64 >> 32);
+ UINT16 expected16 = (_Endian == ENDIANNESS_LITTLE) ? expected32 : (expected32 >> 16);
+ UINT8 expected8 = (_Endian == ENDIANNESS_LITTLE) ? expected16 : (expected16 >> 8);
+
+ UINT64 result64;
+ UINT32 result32;
+ UINT16 result16;
+ UINT8 result8;
+
+ // validate byte accesses
+ printf("\nAddress %d\n", address);
+ printf(" read_byte = "); printf("%02X\n", result8 = read_byte(address)); assert(result8 == expected8);
+
+ // validate word accesses (if aligned)
+ if (address % 2 == 0) { printf(" read_word = "); printf("%04X\n", result16 = read_word(address)); assert(result16 == expected16); }
+ if (address % 2 == 0) { printf(" read_word (0xff00) = "); printf("%04X\n", result16 = read_word(address, 0xff00)); assert((result16 & 0xff00) == (expected16 & 0xff00)); }
+ if (address % 2 == 0) { printf(" (0x00ff) = "); printf("%04X\n", result16 = read_word(address, 0x00ff)); assert((result16 & 0x00ff) == (expected16 & 0x00ff)); }
+
+ // validate unaligned word accesses
+ printf(" read_word_unaligned = "); printf("%04X\n", result16 = read_word_unaligned(address)); assert(result16 == expected16);
+ printf(" read_word_unaligned (0xff00) = "); printf("%04X\n", result16 = read_word_unaligned(address, 0xff00)); assert((result16 & 0xff00) == (expected16 & 0xff00));
+ printf(" (0x00ff) = "); printf("%04X\n", result16 = read_word_unaligned(address, 0x00ff)); assert((result16 & 0x00ff) == (expected16 & 0x00ff));
+
+ // validate dword acceses (if aligned)
+ if (address % 4 == 0) { printf(" read_dword = "); printf("%08X\n", result32 = read_dword(address)); assert(result32 == expected32); }
+ if (address % 4 == 0) { printf(" read_dword (0xff000000) = "); printf("%08X\n", result32 = read_dword(address, 0xff000000)); assert((result32 & 0xff000000) == (expected32 & 0xff000000)); }
+ if (address % 4 == 0) { printf(" (0x00ff0000) = "); printf("%08X\n", result32 = read_dword(address, 0x00ff0000)); assert((result32 & 0x00ff0000) == (expected32 & 0x00ff0000)); }
+ if (address % 4 == 0) { printf(" (0x0000ff00) = "); printf("%08X\n", result32 = read_dword(address, 0x0000ff00)); assert((result32 & 0x0000ff00) == (expected32 & 0x0000ff00)); }
+ if (address % 4 == 0) { printf(" (0x000000ff) = "); printf("%08X\n", result32 = read_dword(address, 0x000000ff)); assert((result32 & 0x000000ff) == (expected32 & 0x000000ff)); }
+ if (address % 4 == 0) { printf(" (0xffff0000) = "); printf("%08X\n", result32 = read_dword(address, 0xffff0000)); assert((result32 & 0xffff0000) == (expected32 & 0xffff0000)); }
+ if (address % 4 == 0) { printf(" (0x0000ffff) = "); printf("%08X\n", result32 = read_dword(address, 0x0000ffff)); assert((result32 & 0x0000ffff) == (expected32 & 0x0000ffff)); }
+ if (address % 4 == 0) { printf(" (0xffffff00) = "); printf("%08X\n", result32 = read_dword(address, 0xffffff00)); assert((result32 & 0xffffff00) == (expected32 & 0xffffff00)); }
+ if (address % 4 == 0) { printf(" (0x00ffffff) = "); printf("%08X\n", result32 = read_dword(address, 0x00ffffff)); assert((result32 & 0x00ffffff) == (expected32 & 0x00ffffff)); }
+
+ // validate unaligned dword accesses
+ printf(" read_dword_unaligned = "); printf("%08X\n", result32 = read_dword_unaligned(address)); assert(result32 == expected32);
+ printf(" read_dword_unaligned (0xff000000) = "); printf("%08X\n", result32 = read_dword_unaligned(address, 0xff000000)); assert((result32 & 0xff000000) == (expected32 & 0xff000000));
+ printf(" (0x00ff0000) = "); printf("%08X\n", result32 = read_dword_unaligned(address, 0x00ff0000)); assert((result32 & 0x00ff0000) == (expected32 & 0x00ff0000));
+ printf(" (0x0000ff00) = "); printf("%08X\n", result32 = read_dword_unaligned(address, 0x0000ff00)); assert((result32 & 0x0000ff00) == (expected32 & 0x0000ff00));
+ printf(" (0x000000ff) = "); printf("%08X\n", result32 = read_dword_unaligned(address, 0x000000ff)); assert((result32 & 0x000000ff) == (expected32 & 0x000000ff));
+ printf(" (0xffff0000) = "); printf("%08X\n", result32 = read_dword_unaligned(address, 0xffff0000)); assert((result32 & 0xffff0000) == (expected32 & 0xffff0000));
+ printf(" (0x0000ffff) = "); printf("%08X\n", result32 = read_dword_unaligned(address, 0x0000ffff)); assert((result32 & 0x0000ffff) == (expected32 & 0x0000ffff));
+ printf(" (0xffffff00) = "); printf("%08X\n", result32 = read_dword_unaligned(address, 0xffffff00)); assert((result32 & 0xffffff00) == (expected32 & 0xffffff00));
+ printf(" (0x00ffffff) = "); printf("%08X\n", result32 = read_dword_unaligned(address, 0x00ffffff)); assert((result32 & 0x00ffffff) == (expected32 & 0x00ffffff));
+
+ // validate qword acceses (if aligned)
+ if (address % 8 == 0) { printf(" read_qword = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address), 16)); assert(result64 == expected64); }
+ if (address % 8 == 0) { printf(" read_qword (0xff00000000000000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0xff00000000000000)), 16)); assert((result64 & U64(0xff00000000000000)) == (expected64 & U64(0xff00000000000000))); }
+ if (address % 8 == 0) { printf(" (0x00ff000000000000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0x00ff000000000000)), 16)); assert((result64 & U64(0x00ff000000000000)) == (expected64 & U64(0x00ff000000000000))); }
+ if (address % 8 == 0) { printf(" (0x0000ff0000000000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0x0000ff0000000000)), 16)); assert((result64 & U64(0x0000ff0000000000)) == (expected64 & U64(0x0000ff0000000000))); }
+ if (address % 8 == 0) { printf(" (0x000000ff00000000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0x000000ff00000000)), 16)); assert((result64 & U64(0x000000ff00000000)) == (expected64 & U64(0x000000ff00000000))); }
+ if (address % 8 == 0) { printf(" (0x00000000ff000000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0x00000000ff000000)), 16)); assert((result64 & U64(0x00000000ff000000)) == (expected64 & U64(0x00000000ff000000))); }
+ if (address % 8 == 0) { printf(" (0x0000000000ff0000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0x0000000000ff0000)), 16)); assert((result64 & U64(0x0000000000ff0000)) == (expected64 & U64(0x0000000000ff0000))); }
+ if (address % 8 == 0) { printf(" (0x000000000000ff00) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0x000000000000ff00)), 16)); assert((result64 & U64(0x000000000000ff00)) == (expected64 & U64(0x000000000000ff00))); }
+ if (address % 8 == 0) { printf(" (0x00000000000000ff) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0x00000000000000ff)), 16)); assert((result64 & U64(0x00000000000000ff)) == (expected64 & U64(0x00000000000000ff))); }
+ if (address % 8 == 0) { printf(" (0xffff000000000000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0xffff000000000000)), 16)); assert((result64 & U64(0xffff000000000000)) == (expected64 & U64(0xffff000000000000))); }
+ if (address % 8 == 0) { printf(" (0x0000ffff00000000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0x0000ffff00000000)), 16)); assert((result64 & U64(0x0000ffff00000000)) == (expected64 & U64(0x0000ffff00000000))); }
+ if (address % 8 == 0) { printf(" (0x00000000ffff0000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0x00000000ffff0000)), 16)); assert((result64 & U64(0x00000000ffff0000)) == (expected64 & U64(0x00000000ffff0000))); }
+ if (address % 8 == 0) { printf(" (0x000000000000ffff) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0x000000000000ffff)), 16)); assert((result64 & U64(0x000000000000ffff)) == (expected64 & U64(0x000000000000ffff))); }
+ if (address % 8 == 0) { printf(" (0xffffff0000000000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0xffffff0000000000)), 16)); assert((result64 & U64(0xffffff0000000000)) == (expected64 & U64(0xffffff0000000000))); }
+ if (address % 8 == 0) { printf(" (0x0000ffffff000000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0x0000ffffff000000)), 16)); assert((result64 & U64(0x0000ffffff000000)) == (expected64 & U64(0x0000ffffff000000))); }
+ if (address % 8 == 0) { printf(" (0x000000ffffff0000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0x000000ffffff0000)), 16)); assert((result64 & U64(0x000000ffffff0000)) == (expected64 & U64(0x000000ffffff0000))); }
+ if (address % 8 == 0) { printf(" (0x0000000000ffffff) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0x0000000000ffffff)), 16)); assert((result64 & U64(0x0000000000ffffff)) == (expected64 & U64(0x0000000000ffffff))); }
+ if (address % 8 == 0) { printf(" (0xffffffff00000000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0xffffffff00000000)), 16)); assert((result64 & U64(0xffffffff00000000)) == (expected64 & U64(0xffffffff00000000))); }
+ if (address % 8 == 0) { printf(" (0x00ffffffff000000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0x00ffffffff000000)), 16)); assert((result64 & U64(0x00ffffffff000000)) == (expected64 & U64(0x00ffffffff000000))); }
+ if (address % 8 == 0) { printf(" (0x0000ffffffff0000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0x0000ffffffff0000)), 16)); assert((result64 & U64(0x0000ffffffff0000)) == (expected64 & U64(0x0000ffffffff0000))); }
+ if (address % 8 == 0) { printf(" (0x000000ffffffff00) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0x000000ffffffff00)), 16)); assert((result64 & U64(0x000000ffffffff00)) == (expected64 & U64(0x000000ffffffff00))); }
+ if (address % 8 == 0) { printf(" (0x00000000ffffffff) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0x00000000ffffffff)), 16)); assert((result64 & U64(0x00000000ffffffff)) == (expected64 & U64(0x00000000ffffffff))); }
+ if (address % 8 == 0) { printf(" (0xffffffffff000000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0xffffffffff000000)), 16)); assert((result64 & U64(0xffffffffff000000)) == (expected64 & U64(0xffffffffff000000))); }
+ if (address % 8 == 0) { printf(" (0x00ffffffffff0000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0x00ffffffffff0000)), 16)); assert((result64 & U64(0x00ffffffffff0000)) == (expected64 & U64(0x00ffffffffff0000))); }
+ if (address % 8 == 0) { printf(" (0x0000ffffffffff00) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0x0000ffffffffff00)), 16)); assert((result64 & U64(0x0000ffffffffff00)) == (expected64 & U64(0x0000ffffffffff00))); }
+ if (address % 8 == 0) { printf(" (0x000000ffffffffff) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0x000000ffffffffff)), 16)); assert((result64 & U64(0x000000ffffffffff)) == (expected64 & U64(0x000000ffffffffff))); }
+ if (address % 8 == 0) { printf(" (0xffffffffffff0000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0xffffffffffff0000)), 16)); assert((result64 & U64(0xffffffffffff0000)) == (expected64 & U64(0xffffffffffff0000))); }
+ if (address % 8 == 0) { printf(" (0x00ffffffffffff00) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0x00ffffffffffff00)), 16)); assert((result64 & U64(0x00ffffffffffff00)) == (expected64 & U64(0x00ffffffffffff00))); }
+ if (address % 8 == 0) { printf(" (0x0000ffffffffffff) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0x0000ffffffffffff)), 16)); assert((result64 & U64(0x0000ffffffffffff)) == (expected64 & U64(0x0000ffffffffffff))); }
+ if (address % 8 == 0) { printf(" (0xffffffffffffff00) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0xffffffffffffff00)), 16)); assert((result64 & U64(0xffffffffffffff00)) == (expected64 & U64(0xffffffffffffff00))); }
+ if (address % 8 == 0) { printf(" (0x00ffffffffffffff) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword(address, U64(0x00ffffffffffffff)), 16)); assert((result64 & U64(0x00ffffffffffffff)) == (expected64 & U64(0x00ffffffffffffff))); }
+
+ // validate unaligned qword accesses
+ printf(" read_qword_unaligned = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address), 16)); assert(result64 == expected64);
+ printf(" read_qword_unaligned (0xff00000000000000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0xff00000000000000)), 16)); assert((result64 & U64(0xff00000000000000)) == (expected64 & U64(0xff00000000000000)));
+ printf(" (0x00ff000000000000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0x00ff000000000000)), 16)); assert((result64 & U64(0x00ff000000000000)) == (expected64 & U64(0x00ff000000000000)));
+ printf(" (0x0000ff0000000000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0x0000ff0000000000)), 16)); assert((result64 & U64(0x0000ff0000000000)) == (expected64 & U64(0x0000ff0000000000)));
+ printf(" (0x000000ff00000000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0x000000ff00000000)), 16)); assert((result64 & U64(0x000000ff00000000)) == (expected64 & U64(0x000000ff00000000)));
+ printf(" (0x00000000ff000000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0x00000000ff000000)), 16)); assert((result64 & U64(0x00000000ff000000)) == (expected64 & U64(0x00000000ff000000)));
+ printf(" (0x0000000000ff0000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0x0000000000ff0000)), 16)); assert((result64 & U64(0x0000000000ff0000)) == (expected64 & U64(0x0000000000ff0000)));
+ printf(" (0x000000000000ff00) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0x000000000000ff00)), 16)); assert((result64 & U64(0x000000000000ff00)) == (expected64 & U64(0x000000000000ff00)));
+ printf(" (0x00000000000000ff) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0x00000000000000ff)), 16)); assert((result64 & U64(0x00000000000000ff)) == (expected64 & U64(0x00000000000000ff)));
+ printf(" (0xffff000000000000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0xffff000000000000)), 16)); assert((result64 & U64(0xffff000000000000)) == (expected64 & U64(0xffff000000000000)));
+ printf(" (0x0000ffff00000000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0x0000ffff00000000)), 16)); assert((result64 & U64(0x0000ffff00000000)) == (expected64 & U64(0x0000ffff00000000)));
+ printf(" (0x00000000ffff0000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0x00000000ffff0000)), 16)); assert((result64 & U64(0x00000000ffff0000)) == (expected64 & U64(0x00000000ffff0000)));
+ printf(" (0x000000000000ffff) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0x000000000000ffff)), 16)); assert((result64 & U64(0x000000000000ffff)) == (expected64 & U64(0x000000000000ffff)));
+ printf(" (0xffffff0000000000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0xffffff0000000000)), 16)); assert((result64 & U64(0xffffff0000000000)) == (expected64 & U64(0xffffff0000000000)));
+ printf(" (0x0000ffffff000000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0x0000ffffff000000)), 16)); assert((result64 & U64(0x0000ffffff000000)) == (expected64 & U64(0x0000ffffff000000)));
+ printf(" (0x000000ffffff0000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0x000000ffffff0000)), 16)); assert((result64 & U64(0x000000ffffff0000)) == (expected64 & U64(0x000000ffffff0000)));
+ printf(" (0x0000000000ffffff) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0x0000000000ffffff)), 16)); assert((result64 & U64(0x0000000000ffffff)) == (expected64 & U64(0x0000000000ffffff)));
+ printf(" (0xffffffff00000000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0xffffffff00000000)), 16)); assert((result64 & U64(0xffffffff00000000)) == (expected64 & U64(0xffffffff00000000)));
+ printf(" (0x00ffffffff000000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0x00ffffffff000000)), 16)); assert((result64 & U64(0x00ffffffff000000)) == (expected64 & U64(0x00ffffffff000000)));
+ printf(" (0x0000ffffffff0000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0x0000ffffffff0000)), 16)); assert((result64 & U64(0x0000ffffffff0000)) == (expected64 & U64(0x0000ffffffff0000)));
+ printf(" (0x000000ffffffff00) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0x000000ffffffff00)), 16)); assert((result64 & U64(0x000000ffffffff00)) == (expected64 & U64(0x000000ffffffff00)));
+ printf(" (0x00000000ffffffff) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0x00000000ffffffff)), 16)); assert((result64 & U64(0x00000000ffffffff)) == (expected64 & U64(0x00000000ffffffff)));
+ printf(" (0xffffffffff000000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0xffffffffff000000)), 16)); assert((result64 & U64(0xffffffffff000000)) == (expected64 & U64(0xffffffffff000000)));
+ printf(" (0x00ffffffffff0000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0x00ffffffffff0000)), 16)); assert((result64 & U64(0x00ffffffffff0000)) == (expected64 & U64(0x00ffffffffff0000)));
+ printf(" (0x0000ffffffffff00) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0x0000ffffffffff00)), 16)); assert((result64 & U64(0x0000ffffffffff00)) == (expected64 & U64(0x0000ffffffffff00)));
+ printf(" (0x000000ffffffffff) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0x000000ffffffffff)), 16)); assert((result64 & U64(0x000000ffffffffff)) == (expected64 & U64(0x000000ffffffffff)));
+ printf(" (0xffffffffffff0000) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0xffffffffffff0000)), 16)); assert((result64 & U64(0xffffffffffff0000)) == (expected64 & U64(0xffffffffffff0000)));
+ printf(" (0x00ffffffffffff00) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0x00ffffffffffff00)), 16)); assert((result64 & U64(0x00ffffffffffff00)) == (expected64 & U64(0x00ffffffffffff00)));
+ printf(" (0x0000ffffffffffff) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0x0000ffffffffffff)), 16)); assert((result64 & U64(0x0000ffffffffffff)) == (expected64 & U64(0x0000ffffffffffff)));
+ printf(" (0xffffffffffffff00) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0xffffffffffffff00)), 16)); assert((result64 & U64(0xffffffffffffff00)) == (expected64 & U64(0xffffffffffffff00)));
+ printf(" (0x00ffffffffffffff) = "); printf("%s\n", core_i64_hex_format(result64 = read_qword_unaligned(address, U64(0x00ffffffffffffff)), 16)); assert((result64 & U64(0x00ffffffffffffff)) == (expected64 & U64(0x00ffffffffffffff)));
+ }
+#endif
+ }
+
+ // accessors
+ virtual address_table_read &read() { return m_read; }
+ virtual address_table_write &write() { return m_write; }
+
+ // watchpoint control
+ virtual void enable_read_watchpoints(bool enable = true) { m_read.enable_watchpoints(enable); }
+ virtual void enable_write_watchpoints(bool enable = true) { m_write.enable_watchpoints(enable); }
+
+ // generate accessor table
+ virtual void accessors(data_accessors &accessors) const
+ {
+ accessors.read_byte = reinterpret_cast<UINT8 (*)(address_space *, offs_t)>(&read_byte_static);
+ accessors.read_word = reinterpret_cast<UINT16 (*)(address_space *, offs_t)>(&read_word_static);
+ accessors.read_word_masked = reinterpret_cast<UINT16 (*)(address_space *, offs_t, UINT16)>(&read_word_masked_static);
+ accessors.read_dword = reinterpret_cast<UINT32 (*)(address_space *, offs_t)>(&read_dword_static);
+ accessors.read_dword_masked = reinterpret_cast<UINT32 (*)(address_space *, offs_t, UINT32)>(&read_dword_masked_static);
+ accessors.read_qword = reinterpret_cast<UINT64 (*)(address_space *, offs_t)>(&read_qword_static);
+ accessors.read_qword_masked = reinterpret_cast<UINT64 (*)(address_space *, offs_t, UINT64)>(&read_qword_masked_static);
+ accessors.write_byte = reinterpret_cast<void (*)(address_space *, offs_t, UINT8)>(&write_byte_static);
+ accessors.write_word = reinterpret_cast<void (*)(address_space *, offs_t, UINT16)>(&write_word_static);
+ accessors.write_word_masked = reinterpret_cast<void (*)(address_space *, offs_t, UINT16, UINT16)>(&write_word_masked_static);
+ accessors.write_dword = reinterpret_cast<void (*)(address_space *, offs_t, UINT32)>(&write_dword_static);
+ accessors.write_dword_masked = reinterpret_cast<void (*)(address_space *, offs_t, UINT32, UINT32)>(&write_dword_masked_static);
+ accessors.write_qword = reinterpret_cast<void (*)(address_space *, offs_t, UINT64)>(&write_qword_static);
+ accessors.write_qword_masked = reinterpret_cast<void (*)(address_space *, offs_t, UINT64, UINT64)>(&write_qword_masked_static);
+ }
+
+ // return a pointer to the read bank, or NULL if none
+ virtual void *get_read_ptr(offs_t byteaddress)
+ {
+ // perform the lookup
+ byteaddress &= m_bytemask;
+ UINT32 entry = read_lookup(byteaddress);
+ const handler_entry_read &handler = m_read.handler_read(entry);
+
+ // 8-bit case: RAM/ROM
+ if (entry > STATIC_BANKMAX)
+ return NULL;
+ return handler.ramptr(handler.byteoffset(byteaddress));
+ }
+
+ // return a pointer to the write bank, or NULL if none
+ virtual void *get_write_ptr(offs_t byteaddress)
+ {
+ // perform the lookup
+ byteaddress &= m_bytemask;
+ UINT32 entry = read_lookup(byteaddress);
+ const handler_entry_write &handler = m_write.handler_write(entry);
+
+ // 8-bit case: RAM/ROM
+ if (entry > STATIC_BANKMAX)
+ return NULL;
+ return handler.ramptr(handler.byteoffset(byteaddress));
+ }
+
+ // native read
+ _NativeType read_native(offs_t offset, _NativeType mask)
+ {
+ g_profiler.start(PROFILER_MEMREAD);
+
+ if (TEST_HANDLER) printf("[r%X,%s]", offset, core_i64_hex_format(mask, sizeof(_NativeType) * 2));
+
+ // look up the handler
+ offs_t byteaddress = offset & m_bytemask;
+ UINT32 entry = read_lookup(byteaddress);
+ const handler_entry_read &handler = m_read.handler_read(entry);
+
+ // either read directly from RAM, or call the delegate
+ offset = handler.byteoffset(byteaddress);
+ _NativeType result;
+ if (entry <= STATIC_BANKMAX) result = *reinterpret_cast<_NativeType *>(handler.ramptr(offset));
+ else if (sizeof(_NativeType) == 1) result = handler.read8(*this, offset, mask);
+ else if (sizeof(_NativeType) == 2) result = handler.read16(*this, offset >> 1, mask);
+ else if (sizeof(_NativeType) == 4) result = handler.read32(*this, offset >> 2, mask);
+ else if (sizeof(_NativeType) == 8) result = handler.read64(*this, offset >> 3, mask);
+
+ g_profiler.stop();
+ return result;
+ }
+
+ // mask-less native read
+ _NativeType read_native(offs_t offset)
+ {
+ g_profiler.start(PROFILER_MEMREAD);
+
+ if (TEST_HANDLER) printf("[r%X]", offset);
+
+ // look up the handler
+ offs_t byteaddress = offset & m_bytemask;
+ UINT32 entry = read_lookup(byteaddress);
+ const handler_entry_read &handler = m_read.handler_read(entry);
+
+ // either read directly from RAM, or call the delegate
+ offset = handler.byteoffset(byteaddress);
+ _NativeType result;
+ if (entry <= STATIC_BANKMAX) result = *reinterpret_cast<_NativeType *>(handler.ramptr(offset));
+ else if (sizeof(_NativeType) == 1) result = handler.read8(*this, offset, 0xff);
+ else if (sizeof(_NativeType) == 2) result = handler.read16(*this, offset >> 1, 0xffff);
+ else if (sizeof(_NativeType) == 4) result = handler.read32(*this, offset >> 2, 0xffffffff);
+ else if (sizeof(_NativeType) == 8) result = handler.read64(*this, offset >> 3, U64(0xffffffffffffffff));
+
+ g_profiler.stop();
+ return result;
+ }
+
+ // native write
+ void write_native(offs_t offset, _NativeType data, _NativeType mask)
+ {
+ g_profiler.start(PROFILER_MEMWRITE);
+
+ // look up the handler
+ offs_t byteaddress = offset & m_bytemask;
+ UINT32 entry = write_lookup(byteaddress);
+ const handler_entry_write &handler = m_write.handler_write(entry);
+
+ // either write directly to RAM, or call the delegate
+ offset = handler.byteoffset(byteaddress);
+ if (entry <= STATIC_BANKMAX)
+ {
+ _NativeType *dest = reinterpret_cast<_NativeType *>(handler.ramptr(offset));
+ *dest = (*dest & ~mask) | (data & mask);
+ }
+ else if (sizeof(_NativeType) == 1) handler.write8(*this, offset, data, mask);
+ else if (sizeof(_NativeType) == 2) handler.write16(*this, offset >> 1, data, mask);
+ else if (sizeof(_NativeType) == 4) handler.write32(*this, offset >> 2, data, mask);
+ else if (sizeof(_NativeType) == 8) handler.write64(*this, offset >> 3, data, mask);
+
+ g_profiler.stop();
+ }
+
+ // mask-less native write
+ void write_native(offs_t offset, _NativeType data)
+ {
+ g_profiler.start(PROFILER_MEMWRITE);
+
+ // look up the handler
+ offs_t byteaddress = offset & m_bytemask;
+ UINT32 entry = write_lookup(byteaddress);
+ const handler_entry_write &handler = m_write.handler_write(entry);
+
+ // either write directly to RAM, or call the delegate
+ offset = handler.byteoffset(byteaddress);
+ if (entry <= STATIC_BANKMAX) *reinterpret_cast<_NativeType *>(handler.ramptr(offset)) = data;
+ else if (sizeof(_NativeType) == 1) handler.write8(*this, offset, data, 0xff);
+ else if (sizeof(_NativeType) == 2) handler.write16(*this, offset >> 1, data, 0xffff);
+ else if (sizeof(_NativeType) == 4) handler.write32(*this, offset >> 2, data, 0xffffffff);
+ else if (sizeof(_NativeType) == 8) handler.write64(*this, offset >> 3, data, U64(0xffffffffffffffff));
+
+ g_profiler.stop();
+ }
+
+ // generic direct read
+ template<typename _TargetType, bool _Aligned>
+ _TargetType read_direct(offs_t address, _TargetType mask)
+ {
+ const UINT32 TARGET_BYTES = sizeof(_TargetType);
+ const UINT32 TARGET_BITS = 8 * TARGET_BYTES;
+
+ // equal to native size and aligned; simple pass-through to the native reader
+ if (NATIVE_BYTES == TARGET_BYTES && (_Aligned || (address & NATIVE_MASK) == 0))
+ return read_native(address & ~NATIVE_MASK, mask);
+
+ // if native size is larger, see if we can do a single masked read (guaranteed if we're aligned)
+ if (NATIVE_BYTES > TARGET_BYTES)
+ {
+ UINT32 offsbits = 8 * (address & (NATIVE_BYTES - (_Aligned ? TARGET_BYTES : 1)));
+ if (_Aligned || (offsbits + TARGET_BITS <= NATIVE_BITS))
+ {
+ if (_Endian != ENDIANNESS_LITTLE) offsbits = NATIVE_BITS - TARGET_BITS - offsbits;
+ return read_native(address & ~NATIVE_MASK, (_NativeType)mask << offsbits) >> offsbits;
+ }
+ }
+
+ // determine our alignment against the native boundaries, and mask the address
+ UINT32 offsbits = 8 * (address & (NATIVE_BYTES - 1));
+ address &= ~NATIVE_MASK;
+
+ // if we're here, and native size is larger or equal to the target, we need exactly 2 reads
+ if (NATIVE_BYTES >= TARGET_BYTES)
+ {
+ // little-endian case
+ if (_Endian == ENDIANNESS_LITTLE)
+ {
+ // read lower bits from lower address
+ _TargetType result = 0;
+ _NativeType curmask = (_NativeType)mask << offsbits;
+ if (curmask != 0) result = read_native(address, curmask) >> offsbits;
+
+ // read upper bits from upper address
+ offsbits = NATIVE_BITS - offsbits;
+ curmask = mask >> offsbits;
+ if (curmask != 0) result |= read_native(address + NATIVE_BYTES, curmask) << offsbits;
+ return result;
+ }
+
+ // big-endian case
+ else
+ {
+ // left-justify the mask to the target type
+ const UINT32 LEFT_JUSTIFY_TARGET_TO_NATIVE_SHIFT = ((NATIVE_BITS >= TARGET_BITS) ? (NATIVE_BITS - TARGET_BITS) : 0);
+ _NativeType result = 0;
+ _NativeType ljmask = (_NativeType)mask << LEFT_JUSTIFY_TARGET_TO_NATIVE_SHIFT;
+ _NativeType curmask = ljmask >> offsbits;
+
+ // read upper bits from lower address
+ if (curmask != 0) result = read_native(address, curmask) << offsbits;
+ offsbits = NATIVE_BITS - offsbits;
+
+ // read lower bits from upper address
+ curmask = ljmask << offsbits;
+ if (curmask != 0) result |= read_native(address + NATIVE_BYTES, curmask) >> offsbits;
+
+ // return the un-justified result
+ return result >> LEFT_JUSTIFY_TARGET_TO_NATIVE_SHIFT;
+ }
+ }
+
+ // if we're here, then we have 2 or more reads needed to get our final result
+ else
+ {
+ // compute the maximum number of loops; we do it this way so that there are
+ // a fixed number of loops for the compiler to unroll if it desires
+ const UINT32 MAX_SPLITS_MINUS_ONE = TARGET_BYTES / NATIVE_BYTES - 1;
+ _TargetType result = 0;
+
+ // little-endian case
+ if (_Endian == ENDIANNESS_LITTLE)
+ {
+ // read lowest bits from first address
+ _NativeType curmask = mask << offsbits;
+ if (curmask != 0) result = read_native(address, curmask) >> offsbits;
+
+ // read middle bits from subsequent addresses
+ offsbits = NATIVE_BITS - offsbits;
+ for (UINT32 index = 0; index < MAX_SPLITS_MINUS_ONE; index++)
+ {
+ address += NATIVE_BYTES;
+ curmask = mask >> offsbits;
+ if (curmask != 0) result |= (_TargetType)read_native(address, curmask) << offsbits;
+ offsbits += NATIVE_BITS;
+ }
+
+ // if we're not aligned and we still have bits left, read uppermost bits from last address
+ if (!_Aligned && offsbits < TARGET_BITS)
+ {
+ curmask = mask >> offsbits;
+ if (curmask != 0) result |= (_TargetType)read_native(address + NATIVE_BYTES, curmask) << offsbits;
+ }
+ }
+
+ // big-endian case
+ else
+ {
+ // read highest bits from first address
+ offsbits = TARGET_BITS - (NATIVE_BITS - offsbits);
+ _NativeType curmask = mask >> offsbits;
+ if (curmask != 0) result = (_TargetType)read_native(address, curmask) << offsbits;
+
+ // read middle bits from subsequent addresses
+ for (UINT32 index = 0; index < MAX_SPLITS_MINUS_ONE; index++)
+ {
+ offsbits -= NATIVE_BITS;
+ address += NATIVE_BYTES;
+ curmask = mask >> offsbits;
+ if (curmask != 0) result |= (_TargetType)read_native(address, curmask) << offsbits;
+ }
+
+ // if we're not aligned and we still have bits left, read lowermost bits from the last address
+ if (!_Aligned && offsbits != 0)
+ {
+ offsbits = NATIVE_BITS - offsbits;
+ curmask = mask << offsbits;
+ if (curmask != 0) result |= read_native(address + NATIVE_BYTES, curmask) >> offsbits;
+ }
+ }
+ return result;
+ }
+ }
+
+ // generic direct write
+ template<typename _TargetType, bool _Aligned>
+ void write_direct(offs_t address, _TargetType data, _TargetType mask)
+ {
+ const UINT32 TARGET_BYTES = sizeof(_TargetType);
+ const UINT32 TARGET_BITS = 8 * TARGET_BYTES;
+
+ // equal to native size and aligned; simple pass-through to the native writer
+ if (NATIVE_BYTES == TARGET_BYTES && (_Aligned || (address & NATIVE_MASK) == 0))
+ return write_native(address & ~NATIVE_MASK, data, mask);
+
+ // if native size is larger, see if we can do a single masked write (guaranteed if we're aligned)
+ if (NATIVE_BYTES > TARGET_BYTES)
+ {
+ UINT32 offsbits = 8 * (address & (NATIVE_BYTES - (_Aligned ? TARGET_BYTES : 1)));
+ if (_Aligned || (offsbits + TARGET_BITS <= NATIVE_BITS))
+ {
+ if (_Endian != ENDIANNESS_LITTLE) offsbits = NATIVE_BITS - TARGET_BITS - offsbits;
+ return write_native(address & ~NATIVE_MASK, (_NativeType)data << offsbits, (_NativeType)mask << offsbits);
+ }
+ }
+
+ // determine our alignment against the native boundaries, and mask the address
+ UINT32 offsbits = 8 * (address & (NATIVE_BYTES - 1));
+ address &= ~NATIVE_MASK;
+
+ // if we're here, and native size is larger or equal to the target, we need exactly 2 writes
+ if (NATIVE_BYTES >= TARGET_BYTES)
+ {
+ // little-endian case
+ if (_Endian == ENDIANNESS_LITTLE)
+ {
+ // write lower bits to lower address
+ _NativeType curmask = (_NativeType)mask << offsbits;
+ if (curmask != 0) write_native(address, (_NativeType)data << offsbits, curmask);
+
+ // write upper bits to upper address
+ offsbits = NATIVE_BITS - offsbits;
+ curmask = mask >> offsbits;
+ if (curmask != 0) write_native(address + NATIVE_BYTES, data >> offsbits, curmask);
+ }
+
+ // big-endian case
+ else
+ {
+ // left-justify the mask and data to the target type
+ const UINT32 LEFT_JUSTIFY_TARGET_TO_NATIVE_SHIFT = ((NATIVE_BITS >= TARGET_BITS) ? (NATIVE_BITS - TARGET_BITS) : 0);
+ _NativeType ljdata = (_NativeType)data << LEFT_JUSTIFY_TARGET_TO_NATIVE_SHIFT;
+ _NativeType ljmask = (_NativeType)mask << LEFT_JUSTIFY_TARGET_TO_NATIVE_SHIFT;
+
+ // write upper bits to lower address
+ _NativeType curmask = ljmask >> offsbits;
+ if (curmask != 0) write_native(address, ljdata >> offsbits, curmask);
+
+ // write lower bits to upper address
+ offsbits = NATIVE_BITS - offsbits;
+ curmask = ljmask << offsbits;
+ if (curmask != 0) write_native(address + NATIVE_BYTES, ljdata << offsbits, curmask);
+ }
+ }
+
+ // if we're here, then we have 2 or more writes needed to get our final result
+ else
+ {
+ // compute the maximum number of loops; we do it this way so that there are
+ // a fixed number of loops for the compiler to unroll if it desires
+ const UINT32 MAX_SPLITS_MINUS_ONE = TARGET_BYTES / NATIVE_BYTES - 1;
+
+ // little-endian case
+ if (_Endian == ENDIANNESS_LITTLE)
+ {
+ // write lowest bits to first address
+ _NativeType curmask = mask << offsbits;
+ if (curmask != 0) write_native(address, data << offsbits, curmask);
+
+ // write middle bits to subsequent addresses
+ offsbits = NATIVE_BITS - offsbits;
+ for (UINT32 index = 0; index < MAX_SPLITS_MINUS_ONE; index++)
+ {
+ address += NATIVE_BYTES;
+ curmask = mask >> offsbits;
+ if (curmask != 0) write_native(address, data >> offsbits, curmask);
+ offsbits += NATIVE_BITS;
+ }
+
+ // if we're not aligned and we still have bits left, write uppermost bits to last address
+ if (!_Aligned && offsbits < TARGET_BITS)
+ {
+ curmask = mask >> offsbits;
+ if (curmask != 0) write_native(address + NATIVE_BYTES, data >> offsbits, curmask);
+ }
+ }
+
+ // big-endian case
+ else
+ {
+ // write highest bits to first address
+ offsbits = TARGET_BITS - (NATIVE_BITS - offsbits);
+ _NativeType curmask = mask >> offsbits;
+ if (curmask != 0) write_native(address, data >> offsbits, curmask);
+
+ // write middle bits to subsequent addresses
+ for (UINT32 index = 0; index < MAX_SPLITS_MINUS_ONE; index++)
+ {
+ offsbits -= NATIVE_BITS;
+ address += NATIVE_BYTES;
+ curmask = mask >> offsbits;
+ if (curmask != 0) write_native(address, data >> offsbits, curmask);
+ }
+
+ // if we're not aligned and we still have bits left, write lowermost bits to the last address
+ if (!_Aligned && offsbits != 0)
+ {
+ offsbits = NATIVE_BITS - offsbits;
+ curmask = mask << offsbits;
+ if (curmask != 0) write_native(address + NATIVE_BYTES, data << offsbits, curmask);
+ }
+ }
+ }
+ }
+
+ // virtual access to these functions
+ UINT8 read_byte(offs_t address) { return (NATIVE_BITS == 8) ? read_native(address & ~NATIVE_MASK) : read_direct<UINT8, true>(address, 0xff); }
+ UINT16 read_word(offs_t address) { return (NATIVE_BITS == 16) ? read_native(address & ~NATIVE_MASK) : read_direct<UINT16, true>(address, 0xffff); }
+ UINT16 read_word(offs_t address, UINT16 mask) { return read_direct<UINT16, true>(address, mask); }
+ UINT16 read_word_unaligned(offs_t address) { return read_direct<UINT16, false>(address, 0xffff); }
+ UINT16 read_word_unaligned(offs_t address, UINT16 mask) { return read_direct<UINT16, false>(address, mask); }
+ UINT32 read_dword(offs_t address) { return (NATIVE_BITS == 32) ? read_native(address & ~NATIVE_MASK) : read_direct<UINT32, true>(address, 0xffffffff); }
+ UINT32 read_dword(offs_t address, UINT32 mask) { return read_direct<UINT32, true>(address, mask); }
+ UINT32 read_dword_unaligned(offs_t address) { return read_direct<UINT32, false>(address, 0xffffffff); }
+ UINT32 read_dword_unaligned(offs_t address, UINT32 mask) { return read_direct<UINT32, false>(address, mask); }
+ UINT64 read_qword(offs_t address) { return (NATIVE_BITS == 64) ? read_native(address & ~NATIVE_MASK) : read_direct<UINT64, true>(address, U64(0xffffffffffffffff)); }
+ UINT64 read_qword(offs_t address, UINT64 mask) { return read_direct<UINT64, true>(address, mask); }
+ UINT64 read_qword_unaligned(offs_t address) { return read_direct<UINT64, false>(address, U64(0xffffffffffffffff)); }
+ UINT64 read_qword_unaligned(offs_t address, UINT64 mask) { return read_direct<UINT64, false>(address, mask); }
+
+ void write_byte(offs_t address, UINT8 data) { if (NATIVE_BITS == 8) write_native(address & ~NATIVE_MASK, data); else write_direct<UINT8, true>(address, data, 0xff); }
+ void write_word(offs_t address, UINT16 data) { if (NATIVE_BITS == 16) write_native(address & ~NATIVE_MASK, data); else write_direct<UINT16, true>(address, data, 0xffff); }
+ void write_word(offs_t address, UINT16 data, UINT16 mask) { write_direct<UINT16, true>(address, data, mask); }
+ void write_word_unaligned(offs_t address, UINT16 data) { write_direct<UINT16, false>(address, data, 0xffff); }
+ void write_word_unaligned(offs_t address, UINT16 data, UINT16 mask) { write_direct<UINT16, false>(address, data, mask); }
+ void write_dword(offs_t address, UINT32 data) { if (NATIVE_BITS == 32) write_native(address & ~NATIVE_MASK, data); else write_direct<UINT32, true>(address, data, 0xffffffff); }
+ void write_dword(offs_t address, UINT32 data, UINT32 mask) { write_direct<UINT32, true>(address, data, mask); }
+ void write_dword_unaligned(offs_t address, UINT32 data) { write_direct<UINT32, false>(address, data, 0xffffffff); }
+ void write_dword_unaligned(offs_t address, UINT32 data, UINT32 mask) { write_direct<UINT32, false>(address, data, mask); }
+ void write_qword(offs_t address, UINT64 data) { if (NATIVE_BITS == 64) write_native(address & ~NATIVE_MASK, data); else write_direct<UINT64, true>(address, data, U64(0xffffffffffffffff)); }
+ void write_qword(offs_t address, UINT64 data, UINT64 mask) { write_direct<UINT64, true>(address, data, mask); }
+ void write_qword_unaligned(offs_t address, UINT64 data) { write_direct<UINT64, false>(address, data, U64(0xffffffffffffffff)); }
+ void write_qword_unaligned(offs_t address, UINT64 data, UINT64 mask) { write_direct<UINT64, false>(address, data, mask); }
+
+ // static access to these functions
+ static UINT8 read_byte_static(this_type *space, offs_t address) { return (NATIVE_BITS == 8) ? space->read_native(address & ~NATIVE_MASK) : space->read_direct<UINT8, true>(address, 0xff); }
+ static UINT16 read_word_static(this_type *space, offs_t address) { return (NATIVE_BITS == 16) ? space->read_native(address & ~NATIVE_MASK) : space->read_direct<UINT16, true>(address, 0xffff); }
+ static UINT16 read_word_masked_static(this_type *space, offs_t address, UINT16 mask) { return space->read_direct<UINT16, true>(address, mask); }
+ static UINT32 read_dword_static(this_type *space, offs_t address) { return (NATIVE_BITS == 32) ? space->read_native(address & ~NATIVE_MASK) : space->read_direct<UINT32, true>(address, 0xffffffff); }
+ static UINT32 read_dword_masked_static(this_type *space, offs_t address, UINT32 mask) { return space->read_direct<UINT32, true>(address, mask); }
+ static UINT64 read_qword_static(this_type *space, offs_t address) { return (NATIVE_BITS == 64) ? space->read_native(address & ~NATIVE_MASK) : space->read_direct<UINT64, true>(address, U64(0xffffffffffffffff)); }
+ static UINT64 read_qword_masked_static(this_type *space, offs_t address, UINT64 mask) { return space->read_direct<UINT64, true>(address, mask); }
+ static void write_byte_static(this_type *space, offs_t address, UINT8 data) { if (NATIVE_BITS == 8) space->write_native(address & ~NATIVE_MASK, data); else space->write_direct<UINT8, true>(address, data, 0xff); }
+ static void write_word_static(this_type *space, offs_t address, UINT16 data) { if (NATIVE_BITS == 16) space->write_native(address & ~NATIVE_MASK, data); else space->write_direct<UINT16, true>(address, data, 0xffff); }
+ static void write_word_masked_static(this_type *space, offs_t address, UINT16 data, UINT16 mask) { space->write_direct<UINT16, true>(address, data, mask); }
+ static void write_dword_static(this_type *space, offs_t address, UINT32 data) { if (NATIVE_BITS == 32) space->write_native(address & ~NATIVE_MASK, data); else space->write_direct<UINT32, true>(address, data, 0xffffffff); }
+ static void write_dword_masked_static(this_type *space, offs_t address, UINT32 data, UINT32 mask) { space->write_direct<UINT32, true>(address, data, mask); }
+ static void write_qword_static(this_type *space, offs_t address, UINT64 data) { if (NATIVE_BITS == 64) space->write_native(address & ~NATIVE_MASK, data); else space->write_direct<UINT64, true>(address, data, U64(0xffffffffffffffff)); }
+ static void write_qword_masked_static(this_type *space, offs_t address, UINT64 data, UINT64 mask) { space->write_direct<UINT64, true>(address, data, mask); }
+
+ address_table_read m_read; // memory read lookup table
+ address_table_write m_write; // memory write lookup table
+};
+
+typedef address_space_specific<UINT8, ENDIANNESS_LITTLE, false> address_space_8le_small;
+typedef address_space_specific<UINT8, ENDIANNESS_BIG, false> address_space_8be_small;
+typedef address_space_specific<UINT16, ENDIANNESS_LITTLE, false> address_space_16le_small;
+typedef address_space_specific<UINT16, ENDIANNESS_BIG, false> address_space_16be_small;
+typedef address_space_specific<UINT32, ENDIANNESS_LITTLE, false> address_space_32le_small;
+typedef address_space_specific<UINT32, ENDIANNESS_BIG, false> address_space_32be_small;
+typedef address_space_specific<UINT64, ENDIANNESS_LITTLE, false> address_space_64le_small;
+typedef address_space_specific<UINT64, ENDIANNESS_BIG, false> address_space_64be_small;
+
+typedef address_space_specific<UINT8, ENDIANNESS_LITTLE, true> address_space_8le_large;
+typedef address_space_specific<UINT8, ENDIANNESS_BIG, true> address_space_8be_large;
+typedef address_space_specific<UINT16, ENDIANNESS_LITTLE, true> address_space_16le_large;
+typedef address_space_specific<UINT16, ENDIANNESS_BIG, true> address_space_16be_large;
+typedef address_space_specific<UINT32, ENDIANNESS_LITTLE, true> address_space_32le_large;
+typedef address_space_specific<UINT32, ENDIANNESS_BIG, true> address_space_32be_large;
+typedef address_space_specific<UINT64, ENDIANNESS_LITTLE, true> address_space_64le_large;
+typedef address_space_specific<UINT64, ENDIANNESS_BIG, true> address_space_64be_large;
+
+
+// ======================> _memory_private
+
+// holds internal state for the memory system
+struct _memory_private
+{
+ bool initialized; // have we completed initialization?
+
+ UINT8 * bank_ptr[STATIC_COUNT]; // array of bank pointers
+ UINT8 * bankd_ptr[STATIC_COUNT]; // array of decrypted bank pointers
+
+ simple_list<address_space> spacelist; // list of address spaces
+ simple_list<memory_block> blocklist; // head of the list of memory blocks
+
+ simple_list<memory_bank> banklist; // data gathered for each bank
+ tagmap_t<memory_bank *> bankmap; // map for fast bank lookups
+ UINT8 banknext; // next bank to allocate
+
+ tagmap_t<memory_share *> sharemap; // map for share lookups
+};
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// global watchpoint table
+UINT8 address_table::s_watchpoint_table[1 << LEVEL1_BITS];
+
+
+
+//**************************************************************************
+// FUNCTION PROTOTYPES
+//**************************************************************************
+
+// banking helpers
+static void bank_reattach(running_machine &machine);
+
+// debugging
+static void generate_memdump(running_machine &machine);
+
+
+
+//**************************************************************************
+// CORE SYSTEM OPERATIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// memory_init - initialize the memory system
+//-------------------------------------------------
+
+void memory_init(running_machine &machine)
+{
+ // allocate our private data
+ memory_private *memdata = machine.memory_data = auto_alloc_clear(machine, memory_private);
+ memdata->banknext = STATIC_BANK1;
+
+ // loop over devices and spaces within each device
+ device_memory_interface *memory = NULL;
+ for (bool gotone = machine.devicelist().first(memory); gotone; gotone = memory->next(memory))
+ for (address_spacenum spacenum = AS_0; spacenum < ADDRESS_SPACES; spacenum++)
+ {
+ // if there is a configuration for this space, we need an address space
+ const address_space_config *spaceconfig = memory->space_config(spacenum);
+ if (spaceconfig != NULL)
+ memdata->spacelist.append(address_space::allocate(machine, *spaceconfig, *memory, spacenum));
+ }
+
+ // construct and preprocess the address_map for each space
+ for (address_space *space = memdata->spacelist.first(); space != NULL; space = space->next())
+ space->prepare_map();
+
+ // create the handlers from the resulting address maps
+ for (address_space *space = memdata->spacelist.first(); space != NULL; space = space->next())
+ space->populate_from_map();
+
+ // allocate memory needed to back each address space
+ for (address_space *space = memdata->spacelist.first(); space != NULL; space = space->next())
+ space->allocate_memory();
+
+ // find all the allocated pointers
+ for (address_space *space = memdata->spacelist.first(); space != NULL; space = space->next())
+ space->locate_memory();
+
+ // register a callback to reset banks when reloading state
+ machine.save().register_postload(save_prepost_delegate(FUNC(bank_reattach), &machine));
+
+ // dump the final memory configuration
+ generate_memdump(machine);
+
+ // we are now initialized
+ memdata->initialized = true;
+}
+
+address_space *memory_nonspecific_space(running_machine &machine)
+{
+ memory_private *memdata = machine.memory_data;
+ return memdata->spacelist.first();
+}
+
+
+
+//**************************************************************************
+// MEMORY BANKING
+//**************************************************************************
+
+//-------------------------------------------------
+// memory_configure_bank - configure the
+// addresses for a bank
+//-------------------------------------------------
+
+void memory_configure_bank(running_machine &machine, const char *tag, int startentry, int numentries, void *base, offs_t stride)
+{
+ // validation checks
+ memory_bank *bank = machine.memory_data->bankmap.find_hash_only(tag);
+ if (bank == NULL)
+ fatalerror("memory_configure_bank called for unknown bank '%s'", tag);
+ if (base == NULL)
+ fatalerror("memory_configure_bank called NULL base");
+
+ // fill in the requested bank entries (backwards to improve allocation)
+ for (int entrynum = startentry + numentries - 1; entrynum >= startentry; entrynum--)
+ bank->configure(entrynum, reinterpret_cast<UINT8 *>(base) + (entrynum - startentry) * stride);
+}
+
+
+//-------------------------------------------------
+// memory_configure_bank - configure the
+// addresses for a bank
+//-------------------------------------------------
+
+void memory_configure_bank(device_t *device, const char *tag, int startentry, int numentries, void *base, offs_t stride)
+{
+ astring tempstring;
+ memory_configure_bank(device->machine(), device->subtag(tempstring, tag), startentry, numentries, base, stride);
+}
+
+
+//-------------------------------------------------
+// memory_configure_bank_decrypted - configure
+// the decrypted addresses for a bank
+//-------------------------------------------------
+
+void memory_configure_bank_decrypted(running_machine &machine, const char *tag, int startentry, int numentries, void *base, offs_t stride)
+{
+ // validation checks
+ memory_bank *bank = machine.memory_data->bankmap.find_hash_only(tag);
+ if (bank == NULL)
+ fatalerror("memory_configure_bank_decrypted called for unknown bank '%s'", tag);
+ if (base == NULL)
+ fatalerror("memory_configure_bank_decrypted called NULL base");
+
+ // fill in the requested bank entries (backwards to improve allocation)
+ for (int entrynum = startentry + numentries - 1; entrynum >= startentry; entrynum--)
+ bank->configure_decrypted(entrynum, reinterpret_cast<UINT8 *>(base) + (entrynum - startentry) * stride);
+}
+
+
+//-------------------------------------------------
+// memory_configure_bank_decrypted - configure
+// the decrypted addresses for a bank
+//-------------------------------------------------
+
+void memory_configure_bank_decrypted(device_t *device, const char *tag, int startentry, int numentries, void *base, offs_t stride)
+{
+ astring tempstring;
+ memory_configure_bank_decrypted(device->machine(), device->subtag(tempstring, tag), startentry, numentries, base, stride);
+}
+
+
+//-------------------------------------------------
+// memory_set_bank - select one pre-configured
+// entry to be the new bank base
+//-------------------------------------------------
+
+void memory_set_bank(running_machine &machine, const char *tag, int entrynum)
+{
+ // validation checks
+ memory_bank *bank = machine.memory_data->bankmap.find_hash_only(tag);
+ if (bank == NULL)
+ fatalerror("memory_set_bank called for unknown bank '%s'", tag);
+
+ // set the base
+ bank->set_entry(entrynum);
+}
+
+
+//-------------------------------------------------
+// memory_set_bank - select one pre-configured
+// entry to be the new bank base
+//-------------------------------------------------
+
+void memory_set_bank(device_t *device, const char *tag, int entrynum)
+{
+ astring tempstring;
+ memory_set_bank(device->machine(), device->subtag(tempstring, tag), entrynum);
+}
+
+
+//-------------------------------------------------
+// memory_get_bank - return the currently
+// selected bank
+//-------------------------------------------------
+
+int memory_get_bank(running_machine &machine, const char *tag)
+{
+ // validation checks
+ memory_bank *bank = machine.memory_data->bankmap.find_hash_only(tag);
+ if (bank == NULL)
+ fatalerror("memory_get_bank called for unknown bank '%s'", tag);
+
+ // return the current entry
+ return bank->entry();
+}
+
+
+//-------------------------------------------------
+// memory_get_bank - return the currently
+// selected bank
+//-------------------------------------------------
+
+int memory_get_bank(device_t *device, const char *tag)
+{
+ astring tempstring;
+ return memory_get_bank(device->machine(), device->subtag(tempstring, tag));
+}
+
+
+//-------------------------------------------------
+// memory_set_bankptr - set the base of a bank
+//-------------------------------------------------
+
+void memory_set_bankptr(running_machine &machine, const char *tag, void *base)
+{
+ // validation checks
+ memory_bank *bank = machine.memory_data->bankmap.find_hash_only(tag);
+ if (bank == NULL)
+ throw emu_fatalerror("memory_set_bankptr called for unknown bank '%s'", tag);
+
+ // set the base
+ bank->set_base(base);
+}
+
+
+//-------------------------------------------------
+// memory_set_bankptr - set the base of a bank
+//-------------------------------------------------
+
+void memory_set_bankptr(device_t *device, const char *tag, void *base)
+{
+ astring tempstring;
+ return memory_set_bankptr(device->machine(), device->subtag(tempstring, tag), base);
+}
+
+
+//-------------------------------------------------
+// memory_get_shared - get a pointer to a shared
+// memory region by tag
+//-------------------------------------------------
+
+void *memory_get_shared(running_machine &machine, const char *tag)
+{
+ size_t size;
+ return memory_get_shared(machine, tag, size);
+}
+
+void *memory_get_shared(running_machine &machine, const char *tag, size_t &length)
+{
+ memory_share *share = machine.memory_data->sharemap.find(tag);
+ if (share == NULL)
+ return NULL;
+ length = share->size();
+ return share->ptr();
+}
+
+
+//-------------------------------------------------
+// memory_dump - dump the internal memory tables
+// to the given file
+//-------------------------------------------------
+
+void memory_dump(running_machine &machine, FILE *file)
+{
+ // skip if we can't open the file
+ if (file == NULL)
+ return;
+
+ // loop over address spaces
+ for (address_space *space = machine.memory_data->spacelist.first(); space != NULL; space = space->next())
+ {
+ fprintf(file, "\n\n"
+ "====================================================\n"
+ "Device '%s' %s address space read handler dump\n"
+ "====================================================\n", space->device().tag(), space->name());
+ space->dump_map(file, ROW_READ);
+
+ fprintf(file, "\n\n"
+ "====================================================\n"
+ "Device '%s' %s address space write handler dump\n"
+ "====================================================\n", space->device().tag(), space->name());
+ space->dump_map(file, ROW_WRITE);
+ }
+}
+
+
+//-------------------------------------------------
+// generate_memdump - internal memory dump
+//-------------------------------------------------
+
+static void generate_memdump(running_machine &machine)
+{
+ if (MEM_DUMP)
+ {
+ FILE *file = fopen("memdump.log", "w");
+ if (file)
+ {
+ memory_dump(machine, file);
+ fclose(file);
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// bank_reattach - reconnect banks after a load
+//-------------------------------------------------
+
+static void bank_reattach(running_machine &machine)
+{
+ // for each non-anonymous bank, explicitly reset its entry
+ for (memory_bank *bank = machine.memory_data->banklist.first(); bank != NULL; bank = bank->next())
+ if (!bank->anonymous() && bank->entry() != BANK_ENTRY_UNSPECIFIED)
+ bank->set_entry(bank->entry());
+}
+
+
+
+//**************************************************************************
+// ADDRESS SPACE
+//**************************************************************************
+
+//-------------------------------------------------
+// address_space - constructor
+//-------------------------------------------------
+
+address_space::address_space(device_memory_interface &memory, address_spacenum spacenum, bool large)
+ : m_next(NULL),
+ m_config(*memory.space_config(spacenum)),
+ m_device(memory.device()),
+ m_map(NULL),
+ m_addrmask(0xffffffffUL >> (32 - m_config.m_addrbus_width)),
+ m_bytemask(address_to_byte_end(m_addrmask)),
+ m_logaddrmask(0xffffffffUL >> (32 - m_config.m_logaddr_width)),
+ m_logbytemask(address_to_byte_end(m_logaddrmask)),
+ m_unmap(0),
+ m_spacenum(spacenum),
+ m_debugger_access(false),
+ m_log_unmap(true),
+ m_direct(*auto_alloc(memory.device().machine(), direct_read_data(*this))),
+ m_name(memory.space_config(spacenum)->name()),
+ m_addrchars((m_config.m_addrbus_width + 3) / 4),
+ m_logaddrchars((m_config.m_logaddr_width + 3) / 4),
+ m_machine(memory.device().machine())
+{
+ // notify the device
+ memory.set_address_space(spacenum, *this);
+}
+
+
+//-------------------------------------------------
+// ~address_space - destructor
+//-------------------------------------------------
+
+address_space::~address_space()
+{
+ global_free(&m_direct);
+ global_free(m_map);
+}
+
+
+//-------------------------------------------------
+// allocate - static smart allocator of subtypes
+//-------------------------------------------------
+
+address_space &address_space::allocate(running_machine &machine, const address_space_config &config, device_memory_interface &memory, address_spacenum spacenum)
+{
+ // allocate one of the appropriate type
+ bool large = (config.addr2byte_end(0xffffffffUL >> (32 - config.m_addrbus_width)) >= (1 << 18));
+
+ switch (config.data_width())
+ {
+ case 8:
+ if (config.endianness() == ENDIANNESS_LITTLE)
+ {
+ if (large)
+ return *auto_alloc(machine, address_space_8le_large(memory, spacenum));
+ else
+ return *auto_alloc(machine, address_space_8le_small(memory, spacenum));
+ }
+ else
+ {
+ if (large)
+ return *auto_alloc(machine, address_space_8be_large(memory, spacenum));
+ else
+ return *auto_alloc(machine, address_space_8be_small(memory, spacenum));
+ }
+
+ case 16:
+ if (config.endianness() == ENDIANNESS_LITTLE)
+ {
+ if (large)
+ return *auto_alloc(machine, address_space_16le_large(memory, spacenum));
+ else
+ return *auto_alloc(machine, address_space_16le_small(memory, spacenum));
+ }
+ else
+ {
+ if (large)
+ return *auto_alloc(machine, address_space_16be_large(memory, spacenum));
+ else
+ return *auto_alloc(machine, address_space_16be_small(memory, spacenum));
+ }
+
+ case 32:
+ if (config.endianness() == ENDIANNESS_LITTLE)
+ {
+ if (large)
+ return *auto_alloc(machine, address_space_32le_large(memory, spacenum));
+ else
+ return *auto_alloc(machine, address_space_32le_small(memory, spacenum));
+ }
+ else
+ {
+ if (large)
+ return *auto_alloc(machine, address_space_32be_large(memory, spacenum));
+ else
+ return *auto_alloc(machine, address_space_32be_small(memory, spacenum));
+ }
+
+ case 64:
+ if (config.endianness() == ENDIANNESS_LITTLE)
+ {
+ if (large)
+ return *auto_alloc(machine, address_space_64le_large(memory, spacenum));
+ else
+ return *auto_alloc(machine, address_space_64le_small(memory, spacenum));
+ }
+ else
+ {
+ if (large)
+ return *auto_alloc(machine, address_space_64be_large(memory, spacenum));
+ else
+ return *auto_alloc(machine, address_space_64be_small(memory, spacenum));
+ }
+ }
+ throw emu_fatalerror("Invalid width %d specified for address_space::allocate", config.data_width());
+}
+
+
+//-------------------------------------------------
+// adjust_addresses - adjust addresses for a
+// given address space in a standard fashion
+//-------------------------------------------------
+
+inline void address_space::adjust_addresses(offs_t &start, offs_t &end, offs_t &mask, offs_t &mirror)
+{
+ // adjust start/end/mask values
+ if (mask == 0)
+ mask = m_addrmask & ~mirror;
+ else
+ mask &= m_addrmask;
+ start &= ~mirror & m_addrmask;
+ end &= ~mirror & m_addrmask;
+
+ // adjust to byte values
+ start = address_to_byte(start);
+ end = address_to_byte_end(end);
+ mask = address_to_byte_end(mask);
+ mirror = address_to_byte(mirror);
+}
+
+
+//-------------------------------------------------
+// prepare_map - allocate the address map and
+// walk through it to find implicit memory regions
+// and identify shared regions
+//-------------------------------------------------
+
+void address_space::prepare_map()
+{
+ const memory_region *devregion = (m_spacenum == AS_0) ? machine().region(m_device.tag()) : NULL;
+ UINT32 devregionsize = (devregion != NULL) ? devregion->bytes() : 0;
+
+ // allocate the address map
+ m_map = global_alloc(address_map(m_device, m_spacenum));
+
+ // merge in the submaps
+ m_map->uplift_submaps(machine(), m_device, endianness());
+
+ // extract global parameters specified by the map
+ m_unmap = (m_map->m_unmapval == 0) ? 0 : ~0;
+ if (m_map->m_globalmask != 0)
+ {
+ m_addrmask = m_map->m_globalmask;
+ m_bytemask = address_to_byte_end(m_addrmask);
+ }
+
+ // make a pass over the address map, adjusting for the device and getting memory pointers
+ for (address_map_entry *entry = m_map->m_entrylist.first(); entry != NULL; entry = entry->next())
+ {
+ // computed adjusted addresses first
+ entry->m_bytestart = entry->m_addrstart;
+ entry->m_byteend = entry->m_addrend;
+ entry->m_bytemirror = entry->m_addrmirror;
+ entry->m_bytemask = entry->m_addrmask;
+ adjust_addresses(entry->m_bytestart, entry->m_byteend, entry->m_bytemask, entry->m_bytemirror);
+
+ // if we have a share entry, add it to our map
+ if (entry->m_share != NULL && machine().memory_data->sharemap.find(entry->m_share) == NULL)
+ {
+ VPRINTF(("Creating share '%s' of length 0x%X\n", entry->m_share, entry->m_byteend + 1 - entry->m_bytestart));
+ memory_share *share = auto_alloc(machine(), memory_share(entry->m_byteend + 1 - entry->m_bytestart));
+ machine().memory_data->sharemap.add(entry->m_share, share, false);
+ }
+
+ // if this is a ROM handler without a specified region, attach it to the implicit region
+ if (m_spacenum == AS_0 && entry->m_read.m_type == AMH_ROM && entry->m_region == NULL)
+ {
+ // make sure it fits within the memory region before doing so, however
+ if (entry->m_byteend < devregionsize)
+ {
+ entry->m_region = m_device.tag();
+ entry->m_rgnoffs = entry->m_bytestart;
+ }
+ }
+
+ // validate adjusted addresses against implicit regions
+ if (entry->m_region != NULL && entry->m_share == NULL && entry->m_baseptr == NULL)
+ {
+ astring regiontag;
+ if (strchr(entry->m_region,':')) {
+ regiontag = entry->m_region;
+ } else {
+ m_device.siblingtag(regiontag, entry->m_region);
+ }
+ const memory_region *region = machine().region(regiontag.cstr());
+ if (region == NULL)
+ fatalerror("Error: device '%s' %s space memory map entry %X-%X references non-existant region \"%s\"", m_device.tag(), m_name, entry->m_addrstart, entry->m_addrend, entry->m_region);
+
+ // validate the region
+ if (entry->m_rgnoffs + (entry->m_byteend - entry->m_bytestart + 1) > region->bytes())
+ fatalerror("Error: device '%s' %s space memory map entry %X-%X extends beyond region \"%s\" size (%X)", m_device.tag(), m_name, entry->m_addrstart, entry->m_addrend, entry->m_region, region->bytes());
+ }
+
+ // convert any region-relative entries to their memory pointers
+ if (entry->m_region != NULL) {
+ astring regiontag;
+ if (strchr(entry->m_region,':')) {
+ regiontag = entry->m_region;
+ } else {
+ m_device.siblingtag(regiontag, entry->m_region);
+ }
+ entry->m_memory = machine().region(regiontag.cstr())->base() + entry->m_rgnoffs;
+ }
+ }
+
+ // now loop over all the handlers and enforce the address mask
+ read().mask_all_handlers(m_bytemask);
+ write().mask_all_handlers(m_bytemask);
+}
+
+
+//-------------------------------------------------
+// populate_from_map - walk the map in reverse
+// order and install the appropriate handler for
+// each case
+//-------------------------------------------------
+
+void address_space::populate_from_map()
+{
+ // no map, nothing to do
+ if (m_map == NULL)
+ return;
+
+ // install the handlers, using the original, unadjusted memory map
+ const address_map_entry *last_entry = NULL;
+ while (last_entry != m_map->m_entrylist.first())
+ {
+ // find the entry before the last one we processed
+ const address_map_entry *entry;
+ for (entry = m_map->m_entrylist.first(); entry->next() != last_entry; entry = entry->next()) ;
+ last_entry = entry;
+
+ // map both read and write halves
+ populate_map_entry(*entry, ROW_READ);
+ populate_map_entry(*entry, ROW_WRITE);
+ }
+}
+
+
+//-------------------------------------------------
+// populate_map_entry - map a single read or
+// write entry based on information from an
+// address map entry
+//-------------------------------------------------
+
+void address_space::populate_map_entry(const address_map_entry &entry, read_or_write readorwrite)
+{
+ const map_handler_data &data = (readorwrite == ROW_READ) ? entry.m_read : entry.m_write;
+ device_t *device;
+
+ // based on the handler type, alter the bits, name, funcptr, and object
+ switch (data.m_type)
+ {
+ case AMH_NONE:
+ return;
+
+ case AMH_ROM:
+ // writes to ROM are no-ops
+ if (readorwrite == ROW_WRITE)
+ return;
+ // fall through to the RAM case otherwise
+
+ case AMH_RAM:
+ install_ram_generic(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, readorwrite, NULL);
+ break;
+
+ case AMH_NOP:
+ unmap_generic(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, readorwrite, true);
+ break;
+
+ case AMH_UNMAP:
+ unmap_generic(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, readorwrite, false);
+ break;
+
+ case AMH_DEVICE_DELEGATE:
+ device = machine().device(data.m_tag);
+ if (device == NULL)
+ throw emu_fatalerror("Attempted to map a non-existent device '%s' in space %s of device '%s'\n", data.m_tag, m_name, m_device.tag());
+
+ if (readorwrite == ROW_READ)
+ switch (data.m_bits)
+ {
+ case 8: install_read_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, read8_delegate(entry.m_rproto8, *device), data.m_mask); break;
+ case 16: install_read_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, read16_delegate(entry.m_rproto16, *device), data.m_mask); break;
+ case 32: install_read_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, read32_delegate(entry.m_rproto32, *device), data.m_mask); break;
+ case 64: install_read_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, read64_delegate(entry.m_rproto64, *device), data.m_mask); break;
+ }
+ else
+ switch (data.m_bits)
+ {
+ case 8: install_write_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, write8_delegate(entry.m_wproto8, *device), data.m_mask); break;
+ case 16: install_write_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, write16_delegate(entry.m_wproto16, *device), data.m_mask); break;
+ case 32: install_write_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, write32_delegate(entry.m_wproto32, *device), data.m_mask); break;
+ case 64: install_write_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, write64_delegate(entry.m_wproto64, *device), data.m_mask); break;
+ }
+ break;
+
+ case AMH_LEGACY_SPACE_HANDLER:
+ if (readorwrite == ROW_READ)
+ switch (data.m_bits)
+ {
+ case 8: install_legacy_read_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_rspace8, data.m_name, data.m_mask); break;
+ case 16: install_legacy_read_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_rspace16, data.m_name, data.m_mask); break;
+ case 32: install_legacy_read_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_rspace32, data.m_name, data.m_mask); break;
+ case 64: install_legacy_read_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_rspace64, data.m_name, data.m_mask); break;
+ }
+ else
+ switch (data.m_bits)
+ {
+ case 8: install_legacy_write_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_wspace8, data.m_name, data.m_mask); break;
+ case 16: install_legacy_write_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_wspace16, data.m_name, data.m_mask); break;
+ case 32: install_legacy_write_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_wspace32, data.m_name, data.m_mask); break;
+ case 64: install_legacy_write_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_wspace64, data.m_name, data.m_mask); break;
+ }
+ break;
+
+ case AMH_LEGACY_DEVICE_HANDLER:
+ device = machine().device(data.m_tag);
+ if (device == NULL)
+ fatalerror("Attempted to map a non-existent device '%s' in space %s of device '%s'\n", data.m_tag, m_name, m_device.tag());
+
+ if (readorwrite == ROW_READ)
+ switch (data.m_bits)
+ {
+ case 8: install_legacy_read_handler(*device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_rdevice8, data.m_name, data.m_mask); break;
+ case 16: install_legacy_read_handler(*device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_rdevice16, data.m_name, data.m_mask); break;
+ case 32: install_legacy_read_handler(*device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_rdevice32, data.m_name, data.m_mask); break;
+ case 64: install_legacy_read_handler(*device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_rdevice64, data.m_name, data.m_mask); break;
+ }
+ else
+ switch (data.m_bits)
+ {
+ case 8: install_legacy_write_handler(*device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_wdevice8, data.m_name, data.m_mask); break;
+ case 16: install_legacy_write_handler(*device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_wdevice16, data.m_name, data.m_mask); break;
+ case 32: install_legacy_write_handler(*device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_wdevice32, data.m_name, data.m_mask); break;
+ case 64: install_legacy_write_handler(*device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_wdevice64, data.m_name, data.m_mask); break;
+ }
+ break;
+
+ case AMH_PORT:
+ install_readwrite_port(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror,
+ (readorwrite == ROW_READ) ? data.m_tag : NULL,
+ (readorwrite == ROW_WRITE) ? data.m_tag : NULL);
+ break;
+
+ case AMH_BANK:
+ install_bank_generic(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror,
+ (readorwrite == ROW_READ) ? data.m_tag : NULL,
+ (readorwrite == ROW_WRITE) ? data.m_tag : NULL);
+ break;
+
+ case AMH_DEVICE_SUBMAP:
+ throw emu_fatalerror("Internal mapping error: leftover mapping of '%s'.\n", data.m_tag);
+ }
+}
+
+
+//-------------------------------------------------
+// allocate_memory - determine all neighboring
+// address ranges and allocate memory to back
+// them
+//-------------------------------------------------
+
+void address_space::allocate_memory()
+{
+ simple_list<memory_block> &blocklist = machine().memory_data->blocklist;
+
+ // make a first pass over the memory map and track blocks with hardcoded pointers
+ // we do this to make sure they are found by space_find_backing_memory first
+ memory_block *prev_memblock_tail = blocklist.last();
+ for (address_map_entry *entry = m_map->m_entrylist.first(); entry != NULL; entry = entry->next())
+ if (entry->m_memory != NULL)
+ blocklist.append(*auto_alloc(machine(), memory_block(*this, entry->m_bytestart, entry->m_byteend, entry->m_memory)));
+
+ // loop over all blocks just allocated and assign pointers from them
+ address_map_entry *unassigned = NULL;
+ memory_block *first_new_block = (prev_memblock_tail != NULL) ? prev_memblock_tail->next() : blocklist.first();
+ for (memory_block *memblock = first_new_block; memblock != NULL; memblock = memblock->next())
+ unassigned = block_assign_intersecting(memblock->bytestart(), memblock->byteend(), memblock->data());
+
+ // if we don't have an unassigned pointer yet, try to find one
+ if (unassigned == NULL)
+ unassigned = block_assign_intersecting(~0, 0, NULL);
+
+ // loop until we've assigned all memory in this space
+ while (unassigned != NULL)
+ {
+ // work in MEMORY_BLOCK_CHUNK-sized chunks
+ offs_t curblockstart = unassigned->m_bytestart / MEMORY_BLOCK_CHUNK;
+ offs_t curblockend = unassigned->m_byteend / MEMORY_BLOCK_CHUNK;
+
+ // loop while we keep finding unassigned blocks in neighboring MEMORY_BLOCK_CHUNK chunks
+ bool changed;
+ do
+ {
+ changed = false;
+
+ // scan for unmapped blocks in the adjusted map
+ for (address_map_entry *entry = m_map->m_entrylist.first(); entry != NULL; entry = entry->next())
+ if (entry->m_memory == NULL && entry != unassigned && needs_backing_store(entry))
+ {
+ // get block start/end blocks for this block
+ offs_t blockstart = entry->m_bytestart / MEMORY_BLOCK_CHUNK;
+ offs_t blockend = entry->m_byteend / MEMORY_BLOCK_CHUNK;
+
+ // if we intersect or are adjacent, adjust the start/end
+ if (blockstart <= curblockend + 1 && blockend >= curblockstart - 1)
+ {
+ if (blockstart < curblockstart)
+ curblockstart = blockstart, changed = true;
+ if (blockend > curblockend)
+ curblockend = blockend, changed = true;
+ }
+ }
+ } while (changed);
+
+ // we now have a block to allocate; do it
+ offs_t curbytestart = curblockstart * MEMORY_BLOCK_CHUNK;
+ offs_t curbyteend = curblockend * MEMORY_BLOCK_CHUNK + (MEMORY_BLOCK_CHUNK - 1);
+ memory_block &block = blocklist.append(*auto_alloc(machine(), memory_block(*this, curbytestart, curbyteend)));
+
+ // assign memory that intersected the new block
+ unassigned = block_assign_intersecting(curbytestart, curbyteend, block.data());
+ }
+}
+
+
+//-------------------------------------------------
+// locate_memory - find all the requested
+// pointers into the final allocated memory
+//-------------------------------------------------
+
+void address_space::locate_memory()
+{
+ // fill in base/size entries
+ for (const address_map_entry *entry = m_map->m_entrylist.first(); entry != NULL; entry = entry->next())
+ {
+ if (entry->m_baseptr != NULL)
+ *entry->m_baseptr = entry->m_memory;
+ if (entry->m_baseptroffs_plus1 != 0)
+ *(void **)(reinterpret_cast<UINT8 *>(machine().driver_data<void>()) + entry->m_baseptroffs_plus1 - 1) = entry->m_memory;
+ if (entry->m_genbaseptroffs_plus1 != 0)
+ *(void **)((UINT8 *)&machine().generic + entry->m_genbaseptroffs_plus1 - 1) = entry->m_memory;
+ if (entry->m_sizeptr != NULL)
+ *entry->m_sizeptr = entry->m_byteend - entry->m_bytestart + 1;
+ if (entry->m_sizeptroffs_plus1 != 0)
+ *(size_t *)(reinterpret_cast<UINT8 *>(machine().driver_data<void>()) + entry->m_sizeptroffs_plus1 - 1) = entry->m_byteend - entry->m_bytestart + 1;
+ if (entry->m_gensizeptroffs_plus1 != 0)
+ *(size_t *)((UINT8 *)&machine().generic + entry->m_gensizeptroffs_plus1 - 1) = entry->m_byteend - entry->m_bytestart + 1;
+ }
+
+ // once this is done, find the starting bases for the banks
+ for (memory_bank *bank = machine().memory_data->banklist.first(); bank != NULL; bank = bank->next())
+ if (bank->base() == NULL && bank->references_space(*this, ROW_READWRITE))
+ {
+ // set the initial bank pointer
+ for (address_map_entry *entry = m_map->m_entrylist.first(); entry != NULL; entry = entry->next())
+ if (entry->m_bytestart == bank->bytestart() && entry->m_memory != NULL)
+ {
+ bank->set_base(entry->m_memory);
+ VPRINTF(("assigned bank '%s' pointer to memory from range %08X-%08X [%p]\n", bank->tag(), entry->m_addrstart, entry->m_addrend, entry->m_memory));
+ break;
+ }
+
+ // if the entry was set ahead of time, override the automatically found pointer
+ if (!bank->anonymous() && bank->entry() != BANK_ENTRY_UNSPECIFIED)
+ bank->set_entry(bank->entry());
+ }
+}
+
+
+//-------------------------------------------------
+// set_decrypted_region - registers an address
+// range as having a decrypted data pointer
+//-------------------------------------------------
+
+void address_space::set_decrypted_region(offs_t addrstart, offs_t addrend, void *base)
+{
+ offs_t bytestart = address_to_byte(addrstart);
+ offs_t byteend = address_to_byte_end(addrend);
+ bool found = false;
+
+ // loop over banks looking for a match
+ for (memory_bank *bank = machine().memory_data->banklist.first(); bank != NULL; bank = bank->next())
+ {
+ // consider this bank if it is used for reading and matches the address space
+ if (bank->references_space(*this, ROW_READ))
+ {
+ // verify that the provided range fully covers this bank
+ if (bank->is_covered_by(bytestart, byteend))
+ {
+ // set the decrypted pointer for the corresponding memory bank
+ bank->set_base_decrypted(reinterpret_cast<UINT8 *>(base) + bank->bytestart() - bytestart);
+ found = true;
+ }
+
+ // fatal error if the decrypted region straddles the bank
+ else if (bank->straddles(bytestart, byteend))
+ throw emu_fatalerror("memory_set_decrypted_region found straddled region %08X-%08X for device '%s'", bytestart, byteend, m_device.tag());
+ }
+ }
+
+ // fatal error as well if we didn't find any relevant memory banks
+ if (!found)
+ throw emu_fatalerror("memory_set_decrypted_region unable to find matching region %08X-%08X for device '%s'", bytestart, byteend, m_device.tag());
+}
+
+
+//-------------------------------------------------
+// block_assign_intersecting - find all
+// intersecting blocks and assign their pointers
+//-------------------------------------------------
+
+address_map_entry *address_space::block_assign_intersecting(offs_t bytestart, offs_t byteend, UINT8 *base)
+{
+ memory_private *memdata = machine().memory_data;
+ address_map_entry *unassigned = NULL;
+
+ // loop over the adjusted map and assign memory to any blocks we can
+ for (address_map_entry *entry = m_map->m_entrylist.first(); entry != NULL; entry = entry->next())
+ {
+ // if we haven't assigned this block yet, see if we have a mapped shared pointer for it
+ if (entry->m_memory == NULL && entry->m_share != NULL)
+ {
+ memory_share *share = memdata->sharemap.find(entry->m_share);
+ if (share != NULL && share->ptr() != NULL)
+ {
+ entry->m_memory = share->ptr();
+ VPRINTF(("memory range %08X-%08X -> shared_ptr '%s' [%p]\n", entry->m_addrstart, entry->m_addrend, entry->m_share, entry->m_memory));
+ }
+ else
+ {
+ VPRINTF(("memory range %08X-%08X -> shared_ptr '%s' but not found\n", entry->m_addrstart, entry->m_addrend, entry->m_share));
+ }
+ }
+
+ // otherwise, look for a match in this block
+ if (entry->m_memory == NULL && entry->m_bytestart >= bytestart && entry->m_byteend <= byteend)
+ {
+ entry->m_memory = base + (entry->m_bytestart - bytestart);
+ VPRINTF(("memory range %08X-%08X -> found in block from %08X-%08X [%p]\n", entry->m_addrstart, entry->m_addrend, bytestart, byteend, entry->m_memory));
+ }
+
+ // if we're the first match on a shared pointer, assign it now
+ if (entry->m_memory != NULL && entry->m_share != NULL)
+ {
+ memory_share *share = memdata->sharemap.find(entry->m_share);
+ if (share != NULL && share->ptr() == NULL)
+ {
+ share->set_ptr(entry->m_memory);
+ VPRINTF(("setting shared_ptr '%s' = %p\n", entry->m_share, entry->m_memory));
+ }
+ }
+
+ // keep track of the first unassigned entry
+ if (entry->m_memory == NULL && unassigned == NULL && needs_backing_store(entry))
+ unassigned = entry;
+ }
+
+ return unassigned;
+}
+
+
+//-------------------------------------------------
+// get_handler_string - return a string
+// describing the handler at a particular offset
+//-------------------------------------------------
+
+const char *address_space::get_handler_string(read_or_write readorwrite, offs_t byteaddress)
+{
+ if (readorwrite == ROW_READ)
+ return read().handler_name(read().lookup(byteaddress));
+ else
+ return write().handler_name(write().lookup(byteaddress));
+}
+
+
+//-------------------------------------------------
+// dump_map - dump the contents of a single
+// address space
+//-------------------------------------------------
+
+void address_space::dump_map(FILE *file, read_or_write readorwrite)
+{
+ const address_table &table = (readorwrite == ROW_READ) ? static_cast<address_table &>(read()) : static_cast<address_table &>(write());
+
+ // dump generic information
+ fprintf(file, " Address bits = %d\n", m_config.m_addrbus_width);
+ fprintf(file, " Data bits = %d\n", m_config.m_databus_width);
+ fprintf(file, " Address mask = %X\n", m_bytemask);
+ fprintf(file, "\n");
+
+ // iterate over addresses
+ offs_t bytestart, byteend;
+ for (offs_t byteaddress = 0; byteaddress <= m_bytemask; byteaddress = byteend)
+ {
+ UINT8 entry = table.derive_range(byteaddress, bytestart, byteend);
+ fprintf(file, "%08X-%08X = %02X: %s [offset=%08X]\n",
+ bytestart, byteend, entry, table.handler_name(entry), table.handler(entry).bytestart());
+ if (++byteend == 0)
+ break;
+ }
+}
+
+
+//**************************************************************************
+// DYNAMIC ADDRESS SPACE MAPPING
+//**************************************************************************
+
+//-------------------------------------------------
+// unmap - unmap a section of address space
+//-------------------------------------------------
+
+void address_space::unmap_generic(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read_or_write readorwrite, bool quiet)
+{
+ VPRINTF(("address_space::unmap(%s-%s mask=%s mirror=%s, %s, %s)\n",
+ core_i64_hex_format(addrstart, m_addrchars), core_i64_hex_format(addrend, m_addrchars),
+ core_i64_hex_format(addrmask, m_addrchars), core_i64_hex_format(addrmirror, m_addrchars),
+ (readorwrite == ROW_READ) ? "read" : (readorwrite == ROW_WRITE) ? "write" : (readorwrite == ROW_READWRITE) ? "read/write" : "??",
+ quiet ? "quiet" : "normal"));
+
+ // read space
+ if (readorwrite == ROW_READ || readorwrite == ROW_READWRITE)
+ read().map_range(addrstart, addrend, addrmask, addrmirror, quiet ? STATIC_NOP : STATIC_UNMAP);
+
+ // write space
+ if (readorwrite == ROW_WRITE || readorwrite == ROW_READWRITE)
+ write().map_range(addrstart, addrend, addrmask, addrmirror, quiet ? STATIC_NOP : STATIC_UNMAP);
+}
+
+
+//-------------------------------------------------
+// install_readwrite_port - install a new I/O port
+// handler into this address space
+//-------------------------------------------------
+
+void address_space::install_readwrite_port(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, const char *rtag, const char *wtag)
+{
+ VPRINTF(("address_space::install_readwrite_port(%s-%s mask=%s mirror=%s, read=\"%s\" / write=\"%s\")\n",
+ core_i64_hex_format(addrstart, m_addrchars), core_i64_hex_format(addrend, m_addrchars),
+ core_i64_hex_format(addrmask, m_addrchars), core_i64_hex_format(addrmirror, m_addrchars),
+ (rtag != NULL) ? rtag : "(none)", (wtag != NULL) ? wtag : "(none)"));
+
+ // read handler
+ if (rtag != NULL)
+ {
+ // find the port
+ const input_port_config *port = machine().port(rtag);
+ if (port == NULL)
+ throw emu_fatalerror("Attempted to map non-existent port '%s' for read in space %s of device '%s'\n", rtag, m_name, m_device.tag());
+
+ // map the range and set the ioport
+ read().handler_map_range(addrstart, addrend, addrmask, addrmirror).set_ioport(*port);
+ }
+
+ if (wtag != NULL)
+ {
+ // find the port
+ const input_port_config *port = machine().port(wtag);
+ if (port == NULL)
+ fatalerror("Attempted to map non-existent port '%s' for write in space %s of device '%s'\n", wtag, m_name, m_device.tag());
+
+ // map the range and set the ioport
+ write().handler_map_range(addrstart, addrend, addrmask, addrmirror).set_ioport(*port);
+ }
+
+ // update the memory dump
+ generate_memdump(machine());
+}
+
+
+//-------------------------------------------------
+// install_bank_generic - install a range as
+// mapping to a particular bank
+//-------------------------------------------------
+
+void address_space::install_bank_generic(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, const char *rtag, const char *wtag)
+{
+ VPRINTF(("address_space::install_readwrite_bank(%s-%s mask=%s mirror=%s, read=\"%s\" / write=\"%s\")\n",
+ core_i64_hex_format(addrstart, m_addrchars), core_i64_hex_format(addrend, m_addrchars),
+ core_i64_hex_format(addrmask, m_addrchars), core_i64_hex_format(addrmirror, m_addrchars),
+ (rtag != NULL) ? rtag : "(none)", (wtag != NULL) ? wtag : "(none)"));
+
+ // map the read bank
+ if (rtag != NULL)
+ {
+ memory_bank &bank = bank_find_or_allocate(rtag, addrstart, addrend, addrmask, addrmirror, ROW_READ);
+ read().map_range(addrstart, addrend, addrmask, addrmirror, bank.index());
+ }
+
+ // map the write bank
+ if (wtag != NULL)
+ {
+ memory_bank &bank = bank_find_or_allocate(wtag, addrstart, addrend, addrmask, addrmirror, ROW_WRITE);
+ write().map_range(addrstart, addrend, addrmask, addrmirror, bank.index());
+ }
+
+ // update the memory dump
+ generate_memdump(machine());
+}
+
+
+//-------------------------------------------------
+// install_ram_generic - install a simple fixed
+// RAM region into the given address space
+//-------------------------------------------------
+
+void *address_space::install_ram_generic(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read_or_write readorwrite, void *baseptr)
+{
+ memory_private *memdata = machine().memory_data;
+
+ VPRINTF(("address_space::install_ram_generic(%s-%s mask=%s mirror=%s, %s, %p)\n",
+ core_i64_hex_format(addrstart, m_addrchars), core_i64_hex_format(addrend, m_addrchars),
+ core_i64_hex_format(addrmask, m_addrchars), core_i64_hex_format(addrmirror, m_addrchars),
+ (readorwrite == ROW_READ) ? "read" : (readorwrite == ROW_WRITE) ? "write" : (readorwrite == ROW_READWRITE) ? "read/write" : "??",
+ baseptr));
+
+ // map for read
+ if (readorwrite == ROW_READ || readorwrite == ROW_READWRITE)
+ {
+ // find a bank and map it
+ memory_bank &bank = bank_find_or_allocate(NULL, addrstart, addrend, addrmask, addrmirror, ROW_READ);
+ read().map_range(addrstart, addrend, addrmask, addrmirror, bank.index());
+
+ // if we are provided a pointer, set it
+ if (baseptr != NULL)
+ bank.set_base(baseptr);
+
+ // if we don't have a bank pointer yet, try to find one
+ if (bank.base() == NULL)
+ {
+ void *backing = find_backing_memory(addrstart, addrend);
+ if (backing != NULL)
+ bank.set_base(backing);
+ }
+
+ // if we still don't have a pointer, and we're past the initialization phase, allocate a new block
+ if (bank.base() == NULL && memdata->initialized)
+ {
+ if (machine().phase() >= MACHINE_PHASE_RESET)
+ fatalerror("Attempted to call install_ram_generic() after initialization time without a baseptr!");
+ memory_block &block = memdata->blocklist.append(*auto_alloc(machine(), memory_block(*this, address_to_byte(addrstart), address_to_byte_end(addrend))));
+ bank.set_base(block.data());
+ }
+ }
+
+ // map for write
+ if (readorwrite == ROW_WRITE || readorwrite == ROW_READWRITE)
+ {
+ // find a bank and map it
+ memory_bank &bank = bank_find_or_allocate(NULL, addrstart, addrend, addrmask, addrmirror, ROW_WRITE);
+ write().map_range(addrstart, addrend, addrmask, addrmirror, bank.index());
+
+ // if we are provided a pointer, set it
+ if (baseptr != NULL)
+ bank.set_base(baseptr);
+
+ // if we don't have a bank pointer yet, try to find one
+ if (bank.base() == NULL)
+ {
+ void *backing = find_backing_memory(addrstart, addrend);
+ if (backing != NULL)
+ bank.set_base(backing);
+ }
+
+ // if we still don't have a pointer, and we're past the initialization phase, allocate a new block
+ if (bank.base() == NULL && memdata->initialized)
+ {
+ if (machine().phase() >= MACHINE_PHASE_RESET)
+ fatalerror("Attempted to call install_ram_generic() after initialization time without a baseptr!");
+ memory_block &block = memdata->blocklist.append(*auto_alloc(machine(), memory_block(*this, address_to_byte(addrstart), address_to_byte_end(addrend))));
+ bank.set_base(block.data());
+ }
+ }
+
+ return (void *)find_backing_memory(addrstart, addrend);
+}
+
+
+//-------------------------------------------------
+// install_handler - install 8-bit read/write
+// delegate handlers for the space
+//-------------------------------------------------
+
+UINT8 *address_space::install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_delegate handler, UINT64 unitmask)
+{
+ VPRINTF(("address_space::install_read_handler(%s-%s mask=%s mirror=%s, %s, %s)\n",
+ core_i64_hex_format(addrstart, m_addrchars), core_i64_hex_format(addrend, m_addrchars),
+ core_i64_hex_format(addrmask, m_addrchars), core_i64_hex_format(addrmirror, m_addrchars),
+ handler.name(), core_i64_hex_format(unitmask, data_width() / 4)));
+
+ read().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_delegate(handler);
+ generate_memdump(machine());
+ return reinterpret_cast<UINT8 *>(find_backing_memory(addrstart, addrend));
+}
+
+UINT8 *address_space::install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write8_delegate handler, UINT64 unitmask)
+{
+ VPRINTF(("address_space::install_write_handler(%s-%s mask=%s mirror=%s, %s, %s)\n",
+ core_i64_hex_format(addrstart, m_addrchars), core_i64_hex_format(addrend, m_addrchars),
+ core_i64_hex_format(addrmask, m_addrchars), core_i64_hex_format(addrmirror, m_addrchars),
+ handler.name(), core_i64_hex_format(unitmask, data_width() / 4)));
+
+ write().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_delegate(handler);
+ generate_memdump(machine());
+ return reinterpret_cast<UINT8 *>(find_backing_memory(addrstart, addrend));
+}
+
+UINT8 *address_space::install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_delegate rhandler, write8_delegate whandler, UINT64 unitmask)
+{
+ install_read_handler(addrstart, addrend, addrmask, addrmirror, rhandler, unitmask);
+ return install_write_handler(addrstart, addrend, addrmask, addrmirror, whandler, unitmask);
+}
+
+
+//-------------------------------------------------
+// install_legacy_handler - install 8-bit read/
+// write legacy address space handlers for the
+// space
+//-------------------------------------------------
+
+UINT8 *address_space::install_legacy_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_space_func rhandler, const char *rname, UINT64 unitmask)
+{
+ VPRINTF(("address_space::install_legacy_read_handler(%s-%s mask=%s mirror=%s, %s, %s) [read8]\n",
+ core_i64_hex_format(addrstart, m_addrchars), core_i64_hex_format(addrend, m_addrchars),
+ core_i64_hex_format(addrmask, m_addrchars), core_i64_hex_format(addrmirror, m_addrchars),
+ rname, core_i64_hex_format(unitmask, data_width() / 4)));
+
+ read().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_legacy_func(*this, rhandler, rname);
+ generate_memdump(machine());
+ return reinterpret_cast<UINT8 *>(find_backing_memory(addrstart, addrend));
+}
+
+UINT8 *address_space::install_legacy_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write8_space_func whandler, const char *wname, UINT64 unitmask)
+{
+ VPRINTF(("address_space::install_legacy_write_handler(%s-%s mask=%s mirror=%s, %s, %s) [write8]\n",
+ core_i64_hex_format(addrstart, m_addrchars), core_i64_hex_format(addrend, m_addrchars),
+ core_i64_hex_format(addrmask, m_addrchars), core_i64_hex_format(addrmirror, m_addrchars),
+ wname, core_i64_hex_format(unitmask, data_width() / 4)));
+
+ write().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_legacy_func(*this, whandler, wname);
+ generate_memdump(machine());
+ return reinterpret_cast<UINT8 *>(find_backing_memory(addrstart, addrend));
+}
+
+UINT8 *address_space::install_legacy_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_space_func rhandler, const char *rname, write8_space_func whandler, const char *wname, UINT64 unitmask)
+{
+ install_legacy_read_handler(addrstart, addrend, addrmask, addrmirror, rhandler, rname, unitmask);
+ return install_legacy_write_handler(addrstart, addrend, addrmask, addrmirror, whandler, wname, unitmask);
+}
+
+
+//-------------------------------------------------
+// install_legacy_handler - install 8-bit read/
+// write legacy device handlers for the space
+//-------------------------------------------------
+
+UINT8 *address_space::install_legacy_read_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_device_func rhandler, const char *rname, UINT64 unitmask)
+{
+ VPRINTF(("address_space::install_legacy_read_handler(%s-%s mask=%s mirror=%s, %s, %s, \"%s\") [read8]\n",
+ core_i64_hex_format(addrstart, m_addrchars), core_i64_hex_format(addrend, m_addrchars),
+ core_i64_hex_format(addrmask, m_addrchars), core_i64_hex_format(addrmirror, m_addrchars),
+ rname, core_i64_hex_format(unitmask, data_width() / 4), device.tag()));
+
+ read().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_legacy_func(device, rhandler, rname);
+ generate_memdump(machine());
+ return reinterpret_cast<UINT8 *>(find_backing_memory(addrstart, addrend));
+}
+
+UINT8 *address_space::install_legacy_write_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write8_device_func whandler, const char *wname, UINT64 unitmask)
+{
+ VPRINTF(("address_space::install_legacy_write_handler(%s-%s mask=%s mirror=%s, %s, %s, \"%s\") [write8]\n",
+ core_i64_hex_format(addrstart, m_addrchars), core_i64_hex_format(addrend, m_addrchars),
+ core_i64_hex_format(addrmask, m_addrchars), core_i64_hex_format(addrmirror, m_addrchars),
+ wname, core_i64_hex_format(unitmask, data_width() / 4), device.tag()));
+
+ write().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_legacy_func(device, whandler, wname);
+ generate_memdump(machine());
+ return reinterpret_cast<UINT8 *>(find_backing_memory(addrstart, addrend));
+}
+
+UINT8 *address_space::install_legacy_readwrite_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_device_func rhandler, const char *rname, write8_device_func whandler, const char *wname, UINT64 unitmask)
+{
+ install_legacy_read_handler(device, addrstart, addrend, addrmask, addrmirror, rhandler, rname, unitmask);
+ return install_legacy_write_handler(device, addrstart, addrend, addrmask, addrmirror, whandler, wname, unitmask);
+}
+
+
+//-------------------------------------------------
+// install_handler - install 16-bit read/write
+// delegate handlers for the space
+//-------------------------------------------------
+
+UINT16 *address_space::install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_delegate handler, UINT64 unitmask)
+{
+ read().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_delegate(handler);
+ generate_memdump(machine());
+ return reinterpret_cast<UINT16 *>(find_backing_memory(addrstart, addrend));
+}
+
+UINT16 *address_space::install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write16_delegate handler, UINT64 unitmask)
+{
+ write().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_delegate(handler);
+ generate_memdump(machine());
+ return reinterpret_cast<UINT16 *>(find_backing_memory(addrstart, addrend));
+}
+
+UINT16 *address_space::install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_delegate rhandler, write16_delegate whandler, UINT64 unitmask)
+{
+ install_read_handler(addrstart, addrend, addrmask, addrmirror, rhandler, unitmask);
+ return install_write_handler(addrstart, addrend, addrmask, addrmirror, whandler, unitmask);
+}
+
+
+//-------------------------------------------------
+// install_legacy_handler - install 16-bit read/
+// write legacy address space handlers for the
+// space
+//-------------------------------------------------
+
+UINT16 *address_space::install_legacy_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_space_func rhandler, const char *rname, UINT64 unitmask)
+{
+ read().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_legacy_func(*this, rhandler, rname);
+ generate_memdump(machine());
+ return reinterpret_cast<UINT16 *>(find_backing_memory(addrstart, addrend));
+}
+
+UINT16 *address_space::install_legacy_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write16_space_func whandler, const char *wname, UINT64 unitmask)
+{
+ write().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_legacy_func(*this, whandler, wname);
+ generate_memdump(machine());
+ return reinterpret_cast<UINT16 *>(find_backing_memory(addrstart, addrend));
+}
+
+UINT16 *address_space::install_legacy_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_space_func rhandler, const char *rname, write16_space_func whandler, const char *wname, UINT64 unitmask)
+{
+ install_legacy_read_handler(addrstart, addrend, addrmask, addrmirror, rhandler, rname, unitmask);
+ return install_legacy_write_handler(addrstart, addrend, addrmask, addrmirror, whandler, wname, unitmask);
+}
+
+
+//-------------------------------------------------
+// install_legacy_handler - install 16-bit read/
+// write legacy device handlers for the space
+//-------------------------------------------------
+
+UINT16 *address_space::install_legacy_read_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_device_func rhandler, const char *rname, UINT64 unitmask)
+{
+ read().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_legacy_func(device, rhandler, rname);
+ generate_memdump(machine());
+ return reinterpret_cast<UINT16 *>(find_backing_memory(addrstart, addrend));
+}
+
+UINT16 *address_space::install_legacy_write_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write16_device_func whandler, const char *wname, UINT64 unitmask)
+{
+ write().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_legacy_func(device, whandler, wname);
+ generate_memdump(machine());
+ return reinterpret_cast<UINT16 *>(find_backing_memory(addrstart, addrend));
+}
+
+UINT16 *address_space::install_legacy_readwrite_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_device_func rhandler, const char *rname, write16_device_func whandler, const char *wname, UINT64 unitmask)
+{
+ install_legacy_read_handler(device, addrstart, addrend, addrmask, addrmirror, rhandler, rname, unitmask);
+ return install_legacy_write_handler(device, addrstart, addrend, addrmask, addrmirror, whandler, wname, unitmask);
+}
+
+
+//-------------------------------------------------
+// install_handler - install 32-bit read/write
+// delegate handlers for the space
+//-------------------------------------------------
+
+UINT32 *address_space::install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_delegate handler, UINT64 unitmask)
+{
+ read().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_delegate(handler);
+ generate_memdump(machine());
+ return reinterpret_cast<UINT32 *>(find_backing_memory(addrstart, addrend));
+}
+
+UINT32 *address_space::install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write32_delegate handler, UINT64 unitmask)
+{
+ write().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_delegate(handler);
+ generate_memdump(machine());
+ return reinterpret_cast<UINT32 *>(find_backing_memory(addrstart, addrend));
+}
+
+UINT32 *address_space::install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_delegate rhandler, write32_delegate whandler, UINT64 unitmask)
+{
+ install_read_handler(addrstart, addrend, addrmask, addrmirror, rhandler, unitmask);
+ return install_write_handler(addrstart, addrend, addrmask, addrmirror, whandler, unitmask);
+}
+
+
+//-------------------------------------------------
+// install_legacy_handler - install 32-bit read/
+// write legacy address space handlers for the
+// space
+//-------------------------------------------------
+
+UINT32 *address_space::install_legacy_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_space_func rhandler, const char *rname, UINT64 unitmask)
+{
+ read().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_legacy_func(*this, rhandler, rname);
+ generate_memdump(machine());
+ return reinterpret_cast<UINT32 *>(find_backing_memory(addrstart, addrend));
+}
+
+UINT32 *address_space::install_legacy_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write32_space_func whandler, const char *wname, UINT64 unitmask)
+{
+ write().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_legacy_func(*this, whandler, wname);
+ generate_memdump(machine());
+ return reinterpret_cast<UINT32 *>(find_backing_memory(addrstart, addrend));
+}
+
+UINT32 *address_space::install_legacy_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_space_func rhandler, const char *rname, write32_space_func whandler, const char *wname, UINT64 unitmask)
+{
+ install_legacy_read_handler(addrstart, addrend, addrmask, addrmirror, rhandler, rname, unitmask);
+ return install_legacy_write_handler(addrstart, addrend, addrmask, addrmirror, whandler, wname, unitmask);
+}
+
+
+//-------------------------------------------------
+// install_legacy_handler - install 32-bit read/
+// write legacy device handlers for the space
+//-------------------------------------------------
+
+UINT32 *address_space::install_legacy_read_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_device_func rhandler, const char *rname, UINT64 unitmask)
+{
+ read().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_legacy_func(device, rhandler, rname);
+ generate_memdump(machine());
+ return reinterpret_cast<UINT32 *>(find_backing_memory(addrstart, addrend));
+}
+
+UINT32 *address_space::install_legacy_write_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write32_device_func whandler, const char *wname, UINT64 unitmask)
+{
+ write().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_legacy_func(device, whandler, wname);
+ generate_memdump(machine());
+ return reinterpret_cast<UINT32 *>(find_backing_memory(addrstart, addrend));
+}
+
+UINT32 *address_space::install_legacy_readwrite_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_device_func rhandler, const char *rname, write32_device_func whandler, const char *wname, UINT64 unitmask)
+{
+ install_legacy_read_handler(device, addrstart, addrend, addrmask, addrmirror, rhandler, rname, unitmask);
+ return install_legacy_write_handler(device, addrstart, addrend, addrmask, addrmirror, whandler, wname, unitmask);
+}
+
+
+//-------------------------------------------------
+// install_handler64 - install 64-bit read/write
+// delegate handlers for the space
+//-------------------------------------------------
+
+UINT64 *address_space::install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_delegate handler, UINT64 unitmask)
+{
+ read().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_delegate(handler);
+ generate_memdump(machine());
+ return reinterpret_cast<UINT64 *>(find_backing_memory(addrstart, addrend));
+}
+
+UINT64 *address_space::install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write64_delegate handler, UINT64 unitmask)
+{
+ write().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_delegate(handler);
+ generate_memdump(machine());
+ return reinterpret_cast<UINT64 *>(find_backing_memory(addrstart, addrend));
+}
+
+UINT64 *address_space::install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_delegate rhandler, write64_delegate whandler, UINT64 unitmask)
+{
+ install_read_handler(addrstart, addrend, addrmask, addrmirror, rhandler, unitmask);
+ return install_write_handler(addrstart, addrend, addrmask, addrmirror, whandler, unitmask);
+}
+
+
+//-------------------------------------------------
+// install_legacy_handler - install 64-bit read/
+// write legacy address space handlers for the
+// space
+//-------------------------------------------------
+
+UINT64 *address_space::install_legacy_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_space_func rhandler, const char *rname, UINT64 unitmask)
+{
+ read().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_legacy_func(*this, rhandler, rname);
+ generate_memdump(machine());
+ return reinterpret_cast<UINT64 *>(find_backing_memory(addrstart, addrend));
+}
+
+UINT64 *address_space::install_legacy_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write64_space_func whandler, const char *wname, UINT64 unitmask)
+{
+ write().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_legacy_func(*this, whandler, wname);
+ generate_memdump(machine());
+ return reinterpret_cast<UINT64 *>(find_backing_memory(addrstart, addrend));
+}
+
+UINT64 *address_space::install_legacy_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_space_func rhandler, const char *rname, write64_space_func whandler, const char *wname, UINT64 unitmask)
+{
+ install_legacy_read_handler(addrstart, addrend, addrmask, addrmirror, rhandler, rname, unitmask);
+ return install_legacy_write_handler(addrstart, addrend, addrmask, addrmirror, whandler, wname, unitmask);
+}
+
+
+//-------------------------------------------------
+// install_legacy_handler - install 64-bit read/
+// write legacy device handlers for the space
+//-------------------------------------------------
+
+UINT64 *address_space::install_legacy_read_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_device_func rhandler, const char *rname, UINT64 unitmask)
+{
+ read().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_legacy_func(device, rhandler, rname);
+ generate_memdump(machine());
+ return reinterpret_cast<UINT64 *>(find_backing_memory(addrstart, addrend));
+}
+
+UINT64 *address_space::install_legacy_write_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write64_device_func whandler, const char *wname, UINT64 unitmask)
+{
+ write().handler_map_range(addrstart, addrend, addrmask, addrmirror, unitmask).set_legacy_func(device, whandler, wname);
+ generate_memdump(machine());
+ return reinterpret_cast<UINT64 *>(find_backing_memory(addrstart, addrend));
+}
+
+UINT64 *address_space::install_legacy_readwrite_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_device_func rhandler, const char *rname, write64_device_func whandler, const char *wname, UINT64 unitmask)
+{
+ install_legacy_read_handler(device, addrstart, addrend, addrmask, addrmirror, rhandler, rname, unitmask);
+ return install_legacy_write_handler(device, addrstart, addrend, addrmask, addrmirror, whandler, wname, unitmask);
+}
+
+
+
+//**************************************************************************
+// MEMORY MAPPING HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// find_backing_memory - return a pointer to
+// the base of RAM associated with the given
+// device and offset
+//-------------------------------------------------
+
+void *address_space::find_backing_memory(offs_t addrstart, offs_t addrend)
+{
+ offs_t bytestart = address_to_byte(addrstart);
+ offs_t byteend = address_to_byte_end(addrend);
+
+ VPRINTF(("address_space::find_backing_memory('%s',%s,%08X-%08X) -> ", m_device.tag(), m_name, bytestart, byteend));
+
+ if (m_map == NULL)
+ return NULL;
+
+ // look in the address map first
+ for (address_map_entry *entry = m_map->m_entrylist.first(); entry != NULL; entry = entry->next())
+ {
+ offs_t maskstart = bytestart & entry->m_bytemask;
+ offs_t maskend = byteend & entry->m_bytemask;
+ if (entry->m_memory != NULL && maskstart >= entry->m_bytestart && maskend <= entry->m_byteend)
+ {
+ VPRINTF(("found in entry %08X-%08X [%p]\n", entry->m_addrstart, entry->m_addrend, (UINT8 *)entry->m_memory + (maskstart - entry->m_bytestart)));
+ return (UINT8 *)entry->m_memory + (maskstart - entry->m_bytestart);
+ }
+ }
+
+ // if not found there, look in the allocated blocks
+ for (memory_block *block = machine().memory_data->blocklist.first(); block != NULL; block = block->next())
+ if (block->contains(*this, bytestart, byteend))
+ {
+ VPRINTF(("found in allocated memory block %08X-%08X [%p]\n", block->bytestart(), block->byteend(), block->data() + (bytestart - block->bytestart())));
+ return block->data() + bytestart - block->bytestart();
+ }
+
+ VPRINTF(("did not find\n"));
+ return NULL;
+}
+
+
+//-------------------------------------------------
+// space_needs_backing_store - return whether a
+// given memory map entry implies the need of
+// allocating and registering memory
+//-------------------------------------------------
+
+bool address_space::needs_backing_store(const address_map_entry *entry)
+{
+ // if we are asked to provide a base pointer, then yes, we do need backing
+ if (entry->m_baseptr != NULL || entry->m_baseptroffs_plus1 != 0 || entry->m_genbaseptroffs_plus1 != 0)
+ return true;
+
+ // if we are sharing, and we don't have a pointer yet, create one
+ if (entry->m_share != NULL)
+ {
+ memory_share *share = machine().memory_data->sharemap.find(entry->m_share);
+ if (share != NULL && share->ptr() == NULL)
+ return true;
+ }
+
+ // if we're writing to any sort of bank or RAM, then yes, we do need backing
+ if (entry->m_write.m_type == AMH_BANK || entry->m_write.m_type == AMH_RAM)
+ return true;
+
+ // if we're reading from RAM or from ROM outside of address space 0 or its region, then yes, we do need backing
+ const memory_region *region = machine().region(m_device.tag());
+ if (entry->m_read.m_type == AMH_RAM ||
+ (entry->m_read.m_type == AMH_ROM && (m_spacenum != AS_0 || region == NULL || entry->m_addrstart >= region->bytes())))
+ return true;
+
+ // all other cases don't need backing
+ return false;
+}
+
+
+
+//**************************************************************************
+// BANKING HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// bank_find_or_allocate - allocate a new
+// bank, or find an existing one, and return the
+// read/write handler
+//-------------------------------------------------
+
+memory_bank &address_space::bank_find_or_allocate(const char *tag, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read_or_write readorwrite)
+{
+ memory_private *memdata = machine().memory_data;
+
+ // adjust the addresses, handling mirrors and such
+ offs_t bytemirror = addrmirror;
+ offs_t bytestart = addrstart;
+ offs_t bytemask = addrmask;
+ offs_t byteend = addrend;
+ adjust_addresses(bytestart, byteend, bytemask, bytemirror);
+
+ // if this bank is named, look it up
+ memory_bank *bank = NULL;
+ if (tag != NULL)
+ bank = memdata->bankmap.find_hash_only(tag);
+
+ // else try to find an exact match
+ else
+ for (bank = memdata->banklist.first(); bank != NULL; bank = bank->next())
+ if (bank->anonymous() && bank->references_space(*this, ROW_READWRITE) && bank->matches_exactly(bytestart, byteend))
+ break;
+
+ // if we don't have a bank yet, find a free one
+ if (bank == NULL)
+ {
+ // handle failure
+ int banknum = memdata->banknext++;
+ if (banknum > STATIC_BANKMAX)
+ {
+ if (tag != NULL)
+ throw emu_fatalerror("Unable to allocate new bank '%s'", tag);
+ else
+ throw emu_fatalerror("Unable to allocate bank for RAM/ROM area %X-%X\n", bytestart, byteend);
+ }
+
+ // allocate the bank
+ bank = auto_alloc(machine(), memory_bank(*this, banknum, bytestart, byteend, tag));
+ memdata->banklist.append(*bank);
+
+ // for named banks, add to the map and register for save states
+ if (tag != NULL)
+ memdata->bankmap.add_unique_hash(tag, bank, false);
+ }
+
+ // add a reference for this space
+ bank->add_reference(*this, readorwrite);
+ return *bank;
+}
+
+
+
+//**************************************************************************
+// TABLE MANAGEMENT
+//**************************************************************************
+
+//-------------------------------------------------
+// address_table - constructor
+//-------------------------------------------------
+
+address_table::address_table(address_space &space, bool large)
+ : m_table(auto_alloc_array(space.machine(), UINT8, 1 << LEVEL1_BITS)),
+ m_live_lookup(m_table),
+ m_space(space),
+ m_large(large),
+ m_subtable(auto_alloc_array(space.machine(), subtable_data, SUBTABLE_COUNT)),
+ m_subtable_alloc(0)
+{
+ // make our static table all watchpoints
+ if (s_watchpoint_table[0] != STATIC_WATCHPOINT)
+ memset(s_watchpoint_table, STATIC_WATCHPOINT, sizeof(s_watchpoint_table));
+
+ // initialize everything to unmapped
+ memset(m_table, STATIC_UNMAP, 1 << LEVEL1_BITS);
+
+ // initialize the handlers freelist
+ for (int i=0; i != SUBTABLE_BASE-STATIC_COUNT-1; i++)
+ handler_next_free[i] = i+STATIC_COUNT+1;
+ handler_next_free[SUBTABLE_BASE-STATIC_COUNT-1] = STATIC_INVALID;
+ handler_free = STATIC_COUNT;
+
+ // initialize the handlers refcounts
+ memset(handler_refcount, 0, sizeof(handler_refcount));
+}
+
+
+//-------------------------------------------------
+// ~address_table - destructor
+//-------------------------------------------------
+
+address_table::~address_table()
+{
+ auto_free(m_space.machine(), m_table);
+ auto_free(m_space.machine(), m_subtable);
+}
+
+
+//-------------------------------------------------
+// map_range - map a specific entry in the address
+// map
+//-------------------------------------------------
+
+void address_table::map_range(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, UINT8 entry)
+{
+ // convert addresses to bytes
+ offs_t bytestart = addrstart;
+ offs_t byteend = addrend;
+ offs_t bytemask = addrmask;
+ offs_t bytemirror = addrmirror;
+ m_space.adjust_addresses(bytestart, byteend, bytemask, bytemirror);
+
+ // validity checks
+ assert_always(addrstart <= addrend, "address_table::map_range called with start greater than end");
+ assert_always((bytestart & (m_space.data_width() / 8 - 1)) == 0, "address_table::map_range called with misaligned start address");
+ assert_always((byteend & (m_space.data_width() / 8 - 1)) == (m_space.data_width() / 8 - 1), "address_table::map_range called with misaligned end address");
+
+ // configure the entry to our parameters (but not for static non-banked cases)
+ handler_entry &curentry = handler(entry);
+ if (entry <= STATIC_BANKMAX || entry >= STATIC_COUNT)
+ curentry.configure(bytestart, byteend, bytemask);
+
+ // populate it
+ populate_range_mirrored(bytestart, byteend, bytemirror, entry);
+
+ // recompute any direct access on this space if it is a read modification
+ m_space.m_direct.force_update(entry);
+
+ // verify_reference_counts();
+}
+
+UINT8 address_table::get_free_handler()
+{
+ if (handler_free == STATIC_INVALID)
+ throw emu_fatalerror("Out of handler entries in address table");
+
+ UINT8 handler = handler_free;
+ handler_free = handler_next_free[handler - STATIC_COUNT];
+ return handler;
+}
+
+
+//-------------------------------------------------
+// setup_range - finds an appropriate handler entry
+// and requests to populate the address map with
+// it
+//-------------------------------------------------
+
+void address_table::setup_range(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, UINT64 mask, std::list<UINT32> &entries)
+{
+ // Careful, you can't shift by 64 or more
+ UINT64 testmask = (1ULL << (m_space.data_width()-1) << 1) - 1;
+
+ if((mask & testmask) == 0 || (mask & testmask) == testmask)
+ setup_range_solid(addrstart, addrend, addrmask, addrmirror, entries);
+ else
+ setup_range_masked(addrstart, addrend, addrmask, addrmirror, mask, entries);
+}
+
+//-------------------------------------------------
+// setup_range_solid - finds an appropriate handler
+// entry and requests to populate the address map with
+// it. Replace what's there.
+//-------------------------------------------------
+
+void address_table::setup_range_solid(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, std::list<UINT32> &entries)
+{
+ // Grab a free entry
+ UINT8 entry = get_free_handler();
+
+ // Add it in the "to be setup" list
+ entries.push_back(entry);
+
+ // Configure and map it
+ map_range(addrstart, addrend, addrmask, addrmirror, entry);
+}
+
+//-------------------------------------------------
+// setup_range_solid - finds an appropriate handler
+// entry and requests to populate the address map with
+// it. Handle non-overlapping subunits.
+//-------------------------------------------------
+
+namespace {
+ struct subrange {
+ offs_t start, end;
+ subrange(offs_t _start, offs_t _end) : start(_start), end(_end) {}
+ };
+};
+
+void address_table::setup_range_masked(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, UINT64 mask, std::list<UINT32> &entries)
+{
+ // convert addresses to bytes
+ offs_t bytestart = addrstart;
+ offs_t byteend = addrend;
+ offs_t bytemask = addrmask;
+ offs_t bytemirror = addrmirror;
+ m_space.adjust_addresses(bytestart, byteend, bytemask, bytemirror);
+
+ // Validity checks
+ assert_always(addrstart <= addrend, "address_table::setup_range called with start greater than end");
+ assert_always((bytestart & (m_space.data_width() / 8 - 1)) == 0, "address_table::setup_range called with misaligned start address");
+ assert_always((byteend & (m_space.data_width() / 8 - 1)) == (m_space.data_width() / 8 - 1), "address_table::setup_range called with misaligned end address");
+
+ // Scan the memory to see what has to be done
+ std::list<subrange> range_override;
+ std::map<UINT8, std::list<subrange> > range_partial;
+
+ offs_t base_mirror = 0;
+ do
+ {
+ offs_t base_address = base_mirror | bytestart;
+ offs_t end_address = base_mirror | byteend;
+
+ do
+ {
+ offs_t range_start, range_end;
+ UINT8 entry = derive_range(base_address, range_start, range_end);
+ UINT32 stop_address = range_end > end_address ? end_address : range_end;
+
+ if (entry < STATIC_COUNT || handler(entry).overriden_by_mask(mask))
+ range_override.push_back(subrange(base_address, stop_address));
+ else
+ range_partial[entry].push_back(subrange(base_address, stop_address));
+
+ base_address = stop_address + 1;
+ }
+ while (base_address != end_address + 1);
+
+ // Efficient method to go the the next range start given a mirroring mask
+ base_mirror = (base_mirror + 1 + ~bytemirror) & bytemirror;
+ }
+ while (base_mirror);
+
+ // Ranges in range_override must be plain replaced by the new handler
+ if (!range_override.empty())
+ {
+ // Grab a free entry
+ UINT8 entry = get_free_handler();
+
+ // configure the entry to our parameters
+ handler_entry &curentry = handler(entry);
+ curentry.configure(bytestart, byteend, bytemask);
+
+ // Populate it wherever needed
+ for (std::list<subrange>::const_iterator i = range_override.begin(); i != range_override.end(); i++)
+ populate_range(i->start, i->end, entry);
+
+ // Add it in the "to be setup" list
+ entries.push_back(entry);
+
+ // recompute any direct access on this space if it is a read modification
+ m_space.m_direct.force_update(entry);
+ }
+
+ // Ranges in range_partial must duplicated then partially changed
+ if (!range_partial.empty())
+ {
+ for (std::map<UINT8, std::list<subrange> >::const_iterator i = range_partial.begin(); i != range_partial.end(); i++)
+ {
+ // Theorically, if the handler to change matches the
+ // characteristics of ours, we can directly change it. In
+ // practice, it's more complex than that because the
+ // mirroring is not saved, so we're not sure there aren't
+ // mappings on the handler outside of the zones we're
+ // supposed to change. So we won't do the obvious
+ // optimization at this point.
+
+ // Get the original handler
+ handler_entry *base_entry = &handler(i->first);
+
+ // Verify it is compatible enough with ours given what we can
+ // support.
+ if (base_entry->bytemask() != bytemask)
+ throw emu_fatalerror("Handlers on different subunits of the same address with different address masks are not supported.");
+
+ // Grab a new handler and copy it there
+ UINT8 entry = get_free_handler();
+ handler_entry &curentry = handler(entry);
+ curentry.copy(base_entry);
+
+ // Clear the colliding entries
+ curentry.clear_conflicting_subunits(mask);
+
+ // Reconfigure the base addresses
+ curentry.configure(bytestart, byteend, bytemask);
+
+ // Populate it wherever needed
+ for (std::list<subrange>::const_iterator j = i->second.begin(); j != i->second.end(); j++)
+ populate_range(j->start, j->end, entry);
+
+ // Add it in the "to be setup" list
+ entries.push_back(entry);
+
+ // recompute any direct access on this space if it is a read modification
+ m_space.m_direct.force_update(entry);
+ }
+ }
+
+ // verify_reference_counts();
+}
+
+
+//-------------------------------------------------
+// verify_reference_counts - check how much of a
+// hash we've made of things
+//-------------------------------------------------
+
+void address_table::verify_reference_counts()
+{
+ int actual_refcounts[SUBTABLE_BASE-STATIC_COUNT];
+ memset(actual_refcounts, 0, sizeof(actual_refcounts));
+
+ bool subtable_seen[256 - SUBTABLE_BASE];
+ memset(subtable_seen, 0, sizeof(subtable_seen));
+
+ for (int level1 = 0; level1 != 1 << LEVEL1_BITS; level1++)
+ {
+ UINT8 l1_entry = m_table[level1];
+ if (l1_entry >= SUBTABLE_BASE)
+ {
+ assert(m_large);
+ if (subtable_seen[l1_entry - SUBTABLE_BASE])
+ continue;
+
+ subtable_seen[l1_entry - SUBTABLE_BASE] = true;
+ const UINT8 *subtable = subtable_ptr(l1_entry);
+ for (int level2 = 0; level2 != 1 << LEVEL2_BITS; level2++)
+ {
+ UINT8 l2_entry = subtable[level2];
+ assert(l2_entry < SUBTABLE_BASE);
+ if (l2_entry >= STATIC_COUNT)
+ actual_refcounts[l2_entry - STATIC_COUNT]++;
+ }
+ }
+ else if (l1_entry >= STATIC_COUNT)
+ actual_refcounts[l1_entry - STATIC_COUNT]++;
+ }
+
+ if (memcmp(actual_refcounts, handler_refcount, sizeof(handler_refcount)))
+ {
+ logerror("Refcount failure:\n");
+ for(int i = STATIC_COUNT; i != SUBTABLE_BASE; i++)
+ logerror("%02x: %4x .. %4x\n", i, handler_refcount[i-STATIC_COUNT], actual_refcounts[i-STATIC_COUNT]);
+ throw emu_fatalerror("memory.c: refcounts are fucked.\n");
+ }
+}
+
+
+//-------------------------------------------------
+// populate_range - assign a memory handler to a
+// range of addresses
+//-------------------------------------------------
+
+void address_table::populate_range(offs_t bytestart, offs_t byteend, UINT8 handlerindex)
+{
+ offs_t l2mask = (1 << level2_bits()) - 1;
+ offs_t l1start = bytestart >> level2_bits();
+ offs_t l2start = bytestart & l2mask;
+ offs_t l1stop = byteend >> level2_bits();
+ offs_t l2stop = byteend & l2mask;
+
+ // sanity check
+ if (bytestart > byteend)
+ return;
+
+ // handle the starting edge if it's not on a block boundary
+ if (l2start != 0)
+ {
+ UINT8 *subtable = subtable_open(l1start);
+
+ // if the start and stop end within the same block, handle that
+ if (l1start == l1stop)
+ {
+ handler_ref(handlerindex, l2stop-l2start+1);
+ for (int i = l2start; i <= l2stop; i++)
+ {
+ handler_unref(subtable[i]);
+ subtable[i] = handlerindex;
+ }
+ subtable_close(l1start);
+ return;
+ }
+
+ // otherwise, fill until the end
+ handler_ref(handlerindex, l2mask - l2start + 1);
+ for (int i = l2start; i <= l2mask; i++)
+ {
+ handler_unref(subtable[i]);
+ subtable[i] = handlerindex;
+ }
+ subtable_close(l1start);
+ if (l1start != (offs_t)~0)
+ l1start++;
+ }
+
+ // handle the trailing edge if it's not on a block boundary
+ if (l2stop != l2mask)
+ {
+ UINT8 *subtable = subtable_open(l1stop);
+
+ // fill from the beginning
+ handler_ref(handlerindex, l2stop+1);
+ for (int i = 0; i <= l2stop; i++)
+ {
+ handler_unref(subtable[i]);
+ subtable[i] = handlerindex;
+ }
+ subtable_close(l1stop);
+
+ // if the start and stop end within the same block, handle that
+ if (l1start == l1stop)
+ return;
+ if (l1stop != 0)
+ l1stop--;
+ }
+
+ // now fill in the middle tables
+ handler_ref(handlerindex, l1stop - l1start + 1);
+ for (offs_t l1index = l1start; l1index <= l1stop; l1index++)
+ {
+ UINT8 subindex = m_table[l1index];
+
+ // if we have a subtable here, release it
+ if (subindex >= SUBTABLE_BASE)
+ subtable_release(subindex);
+ else
+ handler_unref(subindex);
+ m_table[l1index] = handlerindex;
+ }
+}
+
+
+//-------------------------------------------------
+// populate_range_mirrored - assign a memory
+// handler to a range of addresses including
+// mirrors
+//-------------------------------------------------
+
+void address_table::populate_range_mirrored(offs_t bytestart, offs_t byteend, offs_t bytemirror, UINT8 handlerindex)
+{
+ // determine the mirror bits
+ offs_t lmirrorbits = 0;
+ offs_t lmirrorbit[32];
+ for (int bit = 0; bit < level2_bits(); bit++)
+ if (bytemirror & (1 << bit))
+ lmirrorbit[lmirrorbits++] = 1 << bit;
+
+ offs_t hmirrorbits = 0;
+ offs_t hmirrorbit[32];
+ for (int bit = level2_bits(); bit < 32; bit++)
+ if (bytemirror & (1 << bit))
+ hmirrorbit[hmirrorbits++] = 1 << bit;
+
+ // loop over mirrors in the level 2 table
+ UINT8 prev_entry = STATIC_INVALID;
+ int prev_index = 0;
+ for (offs_t hmirrorcount = 0; hmirrorcount < (1 << hmirrorbits); hmirrorcount++)
+ {
+ // compute the base of this mirror
+ offs_t hmirrorbase = 0;
+ for (int bit = 0; bit < hmirrorbits; bit++)
+ if (hmirrorcount & (1 << bit))
+ hmirrorbase |= hmirrorbit[bit];
+
+ // invalidate any intersecting cached ranges
+ for (offs_t lmirrorcount = 0; lmirrorcount < (1 << lmirrorbits); lmirrorcount++)
+ {
+ // compute the base of this mirror
+ offs_t lmirrorbase = hmirrorbase;
+ for (int bit = 0; bit < lmirrorbits; bit++)
+ if (lmirrorcount & (1 << bit))
+ lmirrorbase |= lmirrorbit[bit];
+ m_space.m_direct.remove_intersecting_ranges(bytestart + lmirrorbase, byteend + lmirrorbase);
+ }
+
+ // if this is not our first time through, and the level 2 entry matches the previous
+ // level 2 entry, just do a quick map and get out; note that this only works for entries
+ // which don't span multiple level 1 table entries
+ int cur_index = level1_index(bytestart + hmirrorbase);
+ if (cur_index == level1_index(byteend + hmirrorbase))
+ {
+ if (hmirrorcount != 0 && prev_entry == m_table[cur_index])
+ {
+ VPRINTF(("Quick mapping subtable at %08X to match subtable at %08X\n", cur_index << level2_bits(), prev_index << level2_bits()));
+
+ // release the subtable if the old value was a subtable
+ if (m_table[cur_index] >= SUBTABLE_BASE)
+ subtable_release(m_table[cur_index]);
+ else
+ handler_unref(m_table[cur_index]);
+
+ // reallocate the subtable if the new value is a subtable
+ if (m_table[prev_index] >= SUBTABLE_BASE)
+ subtable_realloc(m_table[prev_index]);
+ else
+ handler_ref(m_table[prev_index], 1);
+
+ // set the new value and short-circuit the mapping step
+ m_table[cur_index] = m_table[prev_index];
+ continue;
+ }
+ prev_index = cur_index;
+ prev_entry = m_table[cur_index];
+ }
+
+ // loop over mirrors in the level 1 table
+ for (offs_t lmirrorcount = 0; lmirrorcount < (1 << lmirrorbits); lmirrorcount++)
+ {
+ // compute the base of this mirror
+ offs_t lmirrorbase = hmirrorbase;
+ for (int bit = 0; bit < lmirrorbits; bit++)
+ if (lmirrorcount & (1 << bit))
+ lmirrorbase |= lmirrorbit[bit];
+
+ // populate the tables
+ populate_range(bytestart + lmirrorbase, byteend + lmirrorbase, handlerindex);
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// derive_range - look up the entry for a memory
+// range, and then compute the extent of that
+// range based on the lookup tables
+//-------------------------------------------------
+
+UINT8 address_table::derive_range(offs_t byteaddress, offs_t &bytestart, offs_t &byteend) const
+{
+ // look up the initial address to get the entry we care about
+ UINT8 l1entry;
+ UINT8 entry = l1entry = m_table[level1_index(byteaddress)];
+ if (l1entry >= SUBTABLE_BASE)
+ entry = m_table[level2_index(l1entry, byteaddress)];
+
+ // use the bytemask of the entry to set minimum and maximum bounds
+ offs_t minscan, maxscan;
+ handler(entry).mirrored_start_end(byteaddress, minscan, maxscan);
+
+ // first scan backwards to find the start address
+ UINT8 curl1entry = l1entry;
+ UINT8 curentry = entry;
+ bytestart = byteaddress;
+ while (1)
+ {
+ // if we need to scan the subtable, do it
+ if (curentry != curl1entry)
+ {
+ UINT32 minindex = level2_index(curl1entry, 0);
+ UINT32 index;
+
+ // scan backwards from the current address, until the previous entry doesn't match
+ for (index = level2_index(curl1entry, bytestart); index > minindex; index--, bytestart -= 1)
+ if (m_table[index - 1] != entry)
+ break;
+
+ // if we didn't hit the beginning, then we're finished scanning
+ if (index != minindex)
+ break;
+ }
+
+ // move to the beginning of this L1 entry; stop at the minimum address
+ bytestart &= ~((1 << level2_bits()) - 1);
+ if (bytestart <= minscan)
+ break;
+
+ // look up the entry of the byte at the end of the previous L1 entry; if it doesn't match, stop
+ curentry = curl1entry = m_table[level1_index(bytestart - 1)];
+ if (curl1entry >= SUBTABLE_BASE)
+ curentry = m_table[level2_index(curl1entry, bytestart - 1)];
+ if (curentry != entry)
+ break;
+
+ // move into the previous entry and resume searching
+ bytestart -= 1;
+ }
+
+ // then scan forwards to find the end address
+ curl1entry = l1entry;
+ curentry = entry;
+ byteend = byteaddress;
+ while (1)
+ {
+ // if we need to scan the subtable, do it
+ if (curentry != curl1entry)
+ {
+ UINT32 maxindex = level2_index(curl1entry, ~0);
+ UINT32 index;
+
+ // scan forwards from the current address, until the next entry doesn't match
+ for (index = level2_index(curl1entry, byteend); index < maxindex; index++, byteend += 1)
+ if (m_table[index + 1] != entry)
+ break;
+
+ // if we didn't hit the end, then we're finished scanning
+ if (index != maxindex)
+ break;
+ }
+
+ // move to the end of this L1 entry; stop at the maximum address
+ byteend |= (1 << level2_bits()) - 1;
+ if (byteend >= maxscan)
+ break;
+
+ // look up the entry of the byte at the start of the next L1 entry; if it doesn't match, stop
+ curentry = curl1entry = m_table[level1_index(byteend + 1)];
+ if (curl1entry >= SUBTABLE_BASE)
+ curentry = m_table[level2_index(curl1entry, byteend + 1)];
+ if (curentry != entry)
+ break;
+
+ // move into the next entry and resume searching
+ byteend += 1;
+ }
+
+ return entry;
+}
+
+
+//-------------------------------------------------
+// mask_all_handlers - apply a mask to all
+// address handlers
+//-------------------------------------------------
+
+void address_table::mask_all_handlers(offs_t mask)
+{
+ // we don't loop over map entries because the mask applies to static handlers as well
+ for (int entrynum = 0; entrynum < ENTRY_COUNT; entrynum++)
+ handler(entrynum).apply_mask(mask);
+}
+
+
+
+//**************************************************************************
+// SUBTABLE MANAGEMENT
+//**************************************************************************
+
+//-------------------------------------------------
+// subtable_alloc - allocate a fresh subtable
+// and set its usecount to 1
+//-------------------------------------------------
+
+UINT8 address_table::subtable_alloc()
+{
+ // loop
+ while (1)
+ {
+ // find a subtable with a usecount of 0
+ for (UINT8 subindex = 0; subindex < SUBTABLE_COUNT; subindex++)
+ if (m_subtable[subindex].m_usecount == 0)
+ {
+ // if this is past our allocation budget, allocate some more
+ if (subindex >= m_subtable_alloc)
+ {
+ UINT32 oldsize = (1 << LEVEL1_BITS) + (m_subtable_alloc << level2_bits());
+ m_subtable_alloc += SUBTABLE_ALLOC;
+ UINT32 newsize = (1 << LEVEL1_BITS) + (m_subtable_alloc << level2_bits());
+
+ UINT8 *newtable = auto_alloc_array_clear(m_space.machine(), UINT8, newsize);
+ memcpy(newtable, m_table, oldsize);
+ if (m_live_lookup == m_table)
+ m_live_lookup = newtable;
+ auto_free(m_space.machine(), m_table);
+ m_table = newtable;
+ }
+
+ // bump the usecount and return
+ m_subtable[subindex].m_usecount++;
+ return subindex + SUBTABLE_BASE;
+ }
+
+ // merge any subtables we can
+ if (!subtable_merge())
+ fatalerror("Ran out of subtables!");
+ }
+}
+
+
+//-------------------------------------------------
+// subtable_realloc - increment the usecount on
+// a subtable
+//-------------------------------------------------
+
+void address_table::subtable_realloc(UINT8 subentry)
+{
+ UINT8 subindex = subentry - SUBTABLE_BASE;
+
+ // sanity check
+ if (m_subtable[subindex].m_usecount <= 0)
+ fatalerror("Called subtable_realloc on a table with a usecount of 0");
+
+ // increment the usecount
+ m_subtable[subindex].m_usecount++;
+}
+
+
+//-------------------------------------------------
+// subtable_merge - merge any duplicate
+// subtables
+//-------------------------------------------------
+
+int address_table::subtable_merge()
+{
+ int merged = 0;
+ UINT8 subindex;
+
+ VPRINTF(("Merging subtables....\n"));
+
+ // okay, we failed; update all the checksums and merge tables
+ for (subindex = 0; subindex < SUBTABLE_COUNT; subindex++)
+ if (!m_subtable[subindex].m_checksum_valid && m_subtable[subindex].m_usecount != 0)
+ {
+ UINT32 *subtable = reinterpret_cast<UINT32 *>(subtable_ptr(subindex + SUBTABLE_BASE));
+ UINT32 checksum = 0;
+
+ // update the checksum
+ for (int l2index = 0; l2index < (1 << level2_bits())/4; l2index++)
+ checksum += subtable[l2index];
+ m_subtable[subindex].m_checksum = checksum;
+ m_subtable[subindex].m_checksum_valid = true;
+ }
+
+ // see if there's a matching checksum
+ for (subindex = 0; subindex < SUBTABLE_COUNT; subindex++)
+ if (m_subtable[subindex].m_usecount != 0)
+ {
+ UINT8 *subtable = subtable_ptr(subindex + SUBTABLE_BASE);
+ UINT32 checksum = m_subtable[subindex].m_checksum;
+ UINT8 sumindex;
+
+ for (sumindex = subindex + 1; sumindex < SUBTABLE_COUNT; sumindex++)
+ if (m_subtable[sumindex].m_usecount != 0 &&
+ m_subtable[sumindex].m_checksum == checksum &&
+ !memcmp(subtable, subtable_ptr(sumindex + SUBTABLE_BASE), 1 << level2_bits()))
+ {
+ int l1index;
+
+ VPRINTF(("Merging subtable %d and %d....\n", subindex, sumindex));
+
+ // find all the entries in the L1 tables that pointed to the old one, and point them to the merged table
+ for (l1index = 0; l1index <= (0xffffffffUL >> level2_bits()); l1index++)
+ if (m_table[l1index] == sumindex + SUBTABLE_BASE)
+ {
+ subtable_release(sumindex + SUBTABLE_BASE);
+ subtable_realloc(subindex + SUBTABLE_BASE);
+ m_table[l1index] = subindex + SUBTABLE_BASE;
+ merged++;
+ }
+ }
+ }
+
+ return merged;
+}
+
+
+//-------------------------------------------------
+// subtable_release - decrement the usecount on
+// a subtable and free it if we're done
+//-------------------------------------------------
+
+void address_table::subtable_release(UINT8 subentry)
+{
+ UINT8 subindex = subentry - SUBTABLE_BASE;
+
+ // sanity check
+ if (m_subtable[subindex].m_usecount <= 0)
+ fatalerror("Called subtable_release on a table with a usecount of 0");
+
+ // decrement the usecount and clear the checksum if we're at 0
+ // also unref the subhandlers
+ m_subtable[subindex].m_usecount--;
+ if (m_subtable[subindex].m_usecount == 0)
+ {
+ m_subtable[subindex].m_checksum = 0;
+ UINT8 *subtable = subtable_ptr(subentry);
+ for (int i = 0; i < (1 << LEVEL2_BITS); i++)
+ handler_unref(subtable[i]);
+ }
+}
+
+
+//-------------------------------------------------
+// subtable_open - gain access to a subtable for
+// modification
+//-------------------------------------------------
+
+UINT8 *address_table::subtable_open(offs_t l1index)
+{
+ UINT8 subentry = m_table[l1index];
+
+ // if we don't have a subtable yet, allocate a new one
+ if (subentry < SUBTABLE_BASE)
+ {
+ int size = 1 << level2_bits();
+ UINT8 newentry = subtable_alloc();
+ handler_ref(subentry, size-1);
+ memset(subtable_ptr(newentry), subentry, size);
+ m_table[l1index] = newentry;
+ m_subtable[newentry - SUBTABLE_BASE].m_checksum = (subentry + (subentry << 8) + (subentry << 16) + (subentry << 24)) * ((1 << level2_bits())/4);
+ subentry = newentry;
+ }
+
+ // if we're sharing this subtable, we also need to allocate a fresh copy
+ else if (m_subtable[subentry - SUBTABLE_BASE].m_usecount > 1)
+ {
+ UINT8 newentry = subtable_alloc();
+
+ // allocate may cause some additional merging -- look up the subentry again
+ // when we're done; it should still require a split
+ subentry = m_table[l1index];
+ assert(subentry >= SUBTABLE_BASE);
+ assert(m_subtable[subentry - SUBTABLE_BASE].m_usecount > 1);
+
+ int size = 1 << level2_bits();
+ UINT8 *src = subtable_ptr(subentry);
+ for(int i=0; i != size; i++)
+ handler_ref(src[i], 1);
+
+ memcpy(subtable_ptr(newentry), src, size);
+ subtable_release(subentry);
+ m_table[l1index] = newentry;
+ m_subtable[newentry - SUBTABLE_BASE].m_checksum = m_subtable[subentry - SUBTABLE_BASE].m_checksum;
+ subentry = newentry;
+ }
+
+ // mark the table dirty
+ m_subtable[subentry - SUBTABLE_BASE].m_checksum_valid = false;
+
+ // return the pointer to the subtable
+ return subtable_ptr(subentry);
+}
+
+
+//-------------------------------------------------
+// subtable_close - stop access to a subtable
+//-------------------------------------------------
+
+void address_table::subtable_close(offs_t l1index)
+{
+ // defer any merging until we run out of tables
+}
+
+
+//-------------------------------------------------
+// handler_name - return friendly string
+// description of a handler
+//-------------------------------------------------
+
+const char *address_table::handler_name(UINT8 entry) const
+{
+ static const char *const strings[] =
+ {
+ "invalid", "bank 1", "bank 2", "bank 3",
+ "bank 4", "bank 5", "bank 6", "bank 7",
+ "bank 8", "bank 9", "bank 10", "bank 11",
+ "bank 12", "bank 13", "bank 14", "bank 15",
+ "bank 16", "bank 17", "bank 18", "bank 19",
+ "bank 20", "bank 21", "bank 22", "bank 23",
+ "bank 24", "bank 25", "bank 26", "bank 27",
+ "bank 28", "bank 29", "bank 30", "bank 31",
+ "bank 32", "bank 33", "bank 34", "bank 35",
+ "bank 36", "bank 37", "bank 38", "bank 39",
+ "bank 40", "bank 41", "bank 42", "bank 43",
+ "bank 44", "bank 45", "bank 46", "bank 47",
+ "bank 48", "bank 49", "bank 50", "bank 51",
+ "bank 52", "bank 53", "bank 54", "bank 55",
+ "bank 56", "bank 57", "bank 58", "bank 59",
+ "bank 60", "bank 61", "bank 62", "bank 63",
+ "bank 64", "bank 65", "bank 66", "bank 67",
+ "bank 68", "bank 69", "bank 70", "bank 71",
+ "bank 72", "bank 73", "bank 74", "bank 75",
+ "bank 76", "bank 77", "bank 78", "bank 79",
+ "bank 80", "bank 81", "bank 82", "bank 83",
+ "bank 84", "bank 85", "bank 86", "bank 87",
+ "bank 88", "bank 89", "bank 90", "bank 91",
+ "bank 92", "bank 93", "bank 94", "bank 95",
+ "bank 96", "bank 97", "bank 98", "bank 99",
+ "bank 100", "bank 101", "bank 102", "bank 103",
+ "bank 104", "bank 105", "bank 106", "bank 107",
+ "bank 108", "bank 109", "bank 110", "bank 111",
+ "bank 112", "bank 113", "bank 114", "bank 115",
+ "bank 116", "bank 117", "bank 118", "bank 119",
+ "bank 120", "bank 121", "bank 122", "ram",
+ "rom", "nop", "unmapped", "watchpoint"
+ };
+
+ // banks have names
+ if (entry >= STATIC_BANK1 && entry <= STATIC_BANKMAX)
+ for (memory_bank *info = m_space.machine().memory_data->banklist.first(); info != NULL; info = info->next())
+ if (info->index() == entry)
+ return info->name();
+
+ // constant strings for lower entries
+ if (entry < ARRAY_LENGTH(strings))
+ return strings[entry];
+ else
+ {
+ static char desc[4096];
+ handler(entry).description(desc);
+ if (desc[0])
+ return desc;
+ return "???";
+ }
+}
+
+
+//-------------------------------------------------
+// address_table_read - constructor
+//-------------------------------------------------
+
+address_table_read::address_table_read(address_space &space, bool large)
+ : address_table(space, large)
+{
+ // allocate handlers for each entry, prepopulating the bankptrs for banks
+ for (int entrynum = 0; entrynum < ARRAY_LENGTH(m_handlers); entrynum++)
+ {
+ UINT8 **bankptr = (entrynum >= STATIC_BANK1 && entrynum <= STATIC_BANKMAX) ? &space.machine().memory_data->bank_ptr[entrynum] : NULL;
+ m_handlers[entrynum] = auto_alloc(space.machine(), handler_entry_read(space.data_width(), space.endianness(), bankptr));
+ }
+
+ // we have to allocate different object types based on the data bus width
+ switch (space.data_width())
+ {
+ // 8-bit case
+ case 8:
+ m_handlers[STATIC_UNMAP]->set_delegate(read8_delegate(FUNC(address_table_read::unmap_r<UINT8>), this));
+ m_handlers[STATIC_NOP]->set_delegate(read8_delegate(FUNC(address_table_read::nop_r<UINT8>), this));
+ m_handlers[STATIC_WATCHPOINT]->set_delegate(read8_delegate(FUNC(address_table_read::watchpoint_r<UINT8>), this));
+ break;
+
+ // 16-bit case
+ case 16:
+ m_handlers[STATIC_UNMAP]->set_delegate(read16_delegate(FUNC(address_table_read::unmap_r<UINT16>), this));
+ m_handlers[STATIC_NOP]->set_delegate(read16_delegate(FUNC(address_table_read::nop_r<UINT16>), this));
+ m_handlers[STATIC_WATCHPOINT]->set_delegate(read16_delegate(FUNC(address_table_read::watchpoint_r<UINT16>), this));
+ break;
+
+ // 32-bit case
+ case 32:
+ m_handlers[STATIC_UNMAP]->set_delegate(read32_delegate(FUNC(address_table_read::unmap_r<UINT32>), this));
+ m_handlers[STATIC_NOP]->set_delegate(read32_delegate(FUNC(address_table_read::nop_r<UINT32>), this));
+ m_handlers[STATIC_WATCHPOINT]->set_delegate(read32_delegate(FUNC(address_table_read::watchpoint_r<UINT32>), this));
+ break;
+
+ // 64-bit case
+ case 64:
+ m_handlers[STATIC_UNMAP]->set_delegate(read64_delegate(FUNC(address_table_read::unmap_r<UINT64>), this));
+ m_handlers[STATIC_NOP]->set_delegate(read64_delegate(FUNC(address_table_read::nop_r<UINT64>), this));
+ m_handlers[STATIC_WATCHPOINT]->set_delegate(read64_delegate(FUNC(address_table_read::watchpoint_r<UINT64>), this));
+ break;
+ }
+
+ // reset the byte masks on the special handlers to open up the full address space for proper reporting
+ m_handlers[STATIC_UNMAP]->configure(0, space.bytemask(), ~0);
+ m_handlers[STATIC_NOP]->configure(0, space.bytemask(), ~0);
+ m_handlers[STATIC_WATCHPOINT]->configure(0, space.bytemask(), ~0);
+}
+
+
+//-------------------------------------------------
+// address_table_read - destructor
+//-------------------------------------------------
+
+address_table_read::~address_table_read()
+{
+ for (int handnum = 0; handnum < ARRAY_LENGTH(m_handlers); handnum++)
+ auto_free(m_space.machine(), m_handlers[handnum]);
+}
+
+
+//-------------------------------------------------
+// handler - return the generic handler entry for
+// this index
+//-------------------------------------------------
+
+handler_entry &address_table_read::handler(UINT32 index) const
+{
+ assert(index < ARRAY_LENGTH(m_handlers));
+ return *m_handlers[index];
+}
+
+
+//-------------------------------------------------
+// address_table_write - constructor
+//-------------------------------------------------
+
+address_table_write::address_table_write(address_space &space, bool large)
+ : address_table(space, large)
+{
+ // allocate handlers for each entry, prepopulating the bankptrs for banks
+ for (int entrynum = 0; entrynum < ARRAY_LENGTH(m_handlers); entrynum++)
+ {
+ UINT8 **bankptr = (entrynum >= STATIC_BANK1 && entrynum <= STATIC_BANKMAX) ? &space.machine().memory_data->bank_ptr[entrynum] : NULL;
+ m_handlers[entrynum] = auto_alloc(space.machine(), handler_entry_write(space.data_width(), space.endianness(), bankptr));
+ }
+
+ // we have to allocate different object types based on the data bus width
+ switch (space.data_width())
+ {
+ // 8-bit case
+ case 8:
+ m_handlers[STATIC_UNMAP]->set_delegate(write8_delegate(FUNC(address_table_write::unmap_w<UINT8>), this));
+ m_handlers[STATIC_NOP]->set_delegate(write8_delegate(FUNC(address_table_write::nop_w<UINT8>), this));
+ m_handlers[STATIC_WATCHPOINT]->set_delegate(write8_delegate(FUNC(address_table_write::watchpoint_w<UINT8>), this));
+ break;
+
+ // 16-bit case
+ case 16:
+ m_handlers[STATIC_UNMAP]->set_delegate(write16_delegate(FUNC(address_table_write::unmap_w<UINT16>), this));
+ m_handlers[STATIC_NOP]->set_delegate(write16_delegate(FUNC(address_table_write::nop_w<UINT16>), this));
+ m_handlers[STATIC_WATCHPOINT]->set_delegate(write16_delegate(FUNC(address_table_write::watchpoint_w<UINT16>), this));
+ break;
+
+ // 32-bit case
+ case 32:
+ m_handlers[STATIC_UNMAP]->set_delegate(write32_delegate(FUNC(address_table_write::unmap_w<UINT32>), this));
+ m_handlers[STATIC_NOP]->set_delegate(write32_delegate(FUNC(address_table_write::nop_w<UINT32>), this));
+ m_handlers[STATIC_WATCHPOINT]->set_delegate(write32_delegate(FUNC(address_table_write::watchpoint_w<UINT32>), this));
+ break;
+
+ // 64-bit case
+ case 64:
+ m_handlers[STATIC_UNMAP]->set_delegate(write64_delegate(FUNC(address_table_write::unmap_w<UINT64>), this));
+ m_handlers[STATIC_NOP]->set_delegate(write64_delegate(FUNC(address_table_write::nop_w<UINT64>), this));
+ m_handlers[STATIC_WATCHPOINT]->set_delegate(write64_delegate(FUNC(address_table_write::watchpoint_w<UINT64>), this));
+ break;
+ }
+
+ // reset the byte masks on the special handlers to open up the full address space for proper reporting
+ m_handlers[STATIC_UNMAP]->configure(0, space.bytemask(), ~0);
+ m_handlers[STATIC_NOP]->configure(0, space.bytemask(), ~0);
+ m_handlers[STATIC_WATCHPOINT]->configure(0, space.bytemask(), ~0);
+}
+
+
+//-------------------------------------------------
+// address_table_write - destructor
+//-------------------------------------------------
+
+address_table_write::~address_table_write()
+{
+ for (int handnum = 0; handnum < ARRAY_LENGTH(m_handlers); handnum++)
+ auto_free(m_space.machine(), m_handlers[handnum]);
+}
+
+
+//-------------------------------------------------
+// handler - return the generic handler entry for
+// this index
+//-------------------------------------------------
+
+handler_entry &address_table_write::handler(UINT32 index) const
+{
+ assert(index < ARRAY_LENGTH(m_handlers));
+ return *m_handlers[index];
+}
+
+
+
+//**************************************************************************
+// DIRECT MEMORY RANGES
+//**************************************************************************
+
+//-------------------------------------------------
+// direct_read_data - constructor
+//-------------------------------------------------
+
+direct_read_data::direct_read_data(address_space &space)
+ : m_space(space),
+ m_raw(NULL),
+ m_decrypted(NULL),
+ m_bytemask(space.bytemask()),
+ m_bytestart(1),
+ m_byteend(0),
+ m_entry(STATIC_UNMAP)
+{
+}
+
+
+//-------------------------------------------------
+// ~direct_read_data - destructor
+//-------------------------------------------------
+
+direct_read_data::~direct_read_data()
+{
+}
+
+
+//-------------------------------------------------
+// set_direct_region - called by device cores to
+// update the opcode base for the given address
+//-------------------------------------------------
+
+bool direct_read_data::set_direct_region(offs_t &byteaddress)
+{
+ // allow overrides
+ offs_t overrideaddress = byteaddress;
+ if (!m_directupdate.isnull())
+ {
+ overrideaddress = m_directupdate(*this, overrideaddress);
+ if (overrideaddress == ~0)
+ return true;
+
+ byteaddress = overrideaddress;
+ }
+
+ // remove the masked bits (we'll put them back later)
+ offs_t maskedbits = overrideaddress & ~m_bytemask;
+
+ // find or allocate a matching range
+ direct_range *range = find_range(overrideaddress, m_entry);
+
+ // if we don't map to a bank, return FALSE
+ if (m_entry < STATIC_BANK1 || m_entry > STATIC_BANKMAX)
+ {
+ // ensure future updates to land here as well until we get back into a bank
+ m_byteend = 0;
+ m_bytestart = 1;
+ return false;
+ }
+
+ // if no decrypted opcodes, point to the same base
+ UINT8 *base = m_space.machine().memory_data->bank_ptr[m_entry];
+ UINT8 *based = m_space.machine().memory_data->bankd_ptr[m_entry];
+ if (based == NULL)
+ based = base;
+
+ // compute the adjusted base
+ const handler_entry_read &handler = m_space.read().handler_read(m_entry);
+ m_bytemask = handler.bytemask();
+ m_raw = base - (handler.bytestart() & m_bytemask);
+ m_decrypted = based - (handler.bytestart() & m_bytemask);
+ m_bytestart = maskedbits | range->m_bytestart;
+ m_byteend = maskedbits | range->m_byteend;
+ return true;
+}
+
+
+//-------------------------------------------------
+// find_range - find a byte address in a range
+//-------------------------------------------------
+
+direct_read_data::direct_range *direct_read_data::find_range(offs_t byteaddress, UINT8 &entry)
+{
+ // determine which entry
+ byteaddress &= m_space.m_bytemask;
+ entry = m_space.read().lookup_live(byteaddress);
+
+ // scan our table
+ for (direct_range *range = m_rangelist[entry].first(); range != NULL; range = range->next())
+ if (byteaddress >= range->m_bytestart && byteaddress <= range->m_byteend)
+ return range;
+
+ // didn't find out; allocate a new one
+ direct_range *range = m_freerangelist.first();
+ if (range != NULL)
+ m_freerangelist.detach(*range);
+ else
+ range = auto_alloc(m_space.machine(), direct_range);
+
+ // fill in the range
+ m_space.read().derive_range(byteaddress, range->m_bytestart, range->m_byteend);
+ m_rangelist[entry].prepend(*range);
+
+ return range;
+}
+
+
+//-------------------------------------------------
+// remove_intersecting_ranges - remove all cached
+// ranges that intersect the given address range
+//-------------------------------------------------
+
+void direct_read_data::remove_intersecting_ranges(offs_t bytestart, offs_t byteend)
+{
+ // loop over all entries
+ for (int entry = 0; entry < ARRAY_LENGTH(m_rangelist); entry++)
+ {
+ // loop over all ranges in this entry's list
+ direct_range *nextrange;
+ for (direct_range *range = m_rangelist[entry].first(); range != NULL; range = nextrange)
+ {
+ nextrange = range->next();
+
+ // if we intersect, remove and add to the free range list
+ if (bytestart <= range->m_byteend && byteend >= range->m_bytestart)
+ {
+ m_rangelist[entry].detach(*range);
+ m_freerangelist.prepend(*range);
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// set_direct_update - set a custom direct range
+// update callback
+//-------------------------------------------------
+
+direct_update_delegate direct_read_data::set_direct_update(direct_update_delegate function)
+{
+ direct_update_delegate old = m_directupdate;
+ m_directupdate = function;
+ return old;
+}
+
+
+//-------------------------------------------------
+// explicit_configure - explicitly configure
+// the start/end/mask and the pointers from
+// within a custom callback
+//-------------------------------------------------
+
+void direct_read_data::explicit_configure(offs_t bytestart, offs_t byteend, offs_t bytemask, void *raw, void *decrypted)
+{
+ m_bytestart = bytestart;
+ m_byteend = byteend;
+ m_bytemask = bytemask;
+ m_raw = reinterpret_cast<UINT8 *>(raw);
+ m_decrypted = reinterpret_cast<UINT8 *>((decrypted == NULL) ? raw : decrypted);
+ m_raw -= bytestart & bytemask;
+ m_decrypted -= bytestart & bytemask;
+}
+
+
+
+//**************************************************************************
+// MEMORY BLOCK
+//**************************************************************************
+
+//-------------------------------------------------
+// memory_block - constructor
+//-------------------------------------------------
+
+memory_block::memory_block(address_space &space, offs_t bytestart, offs_t byteend, void *memory)
+ : m_next(NULL),
+ m_machine(space.machine()),
+ m_space(space),
+ m_bytestart(bytestart),
+ m_byteend(byteend),
+ m_data(reinterpret_cast<UINT8 *>(memory)),
+ m_allocated(NULL)
+{
+ VPRINTF(("block_allocate('%s',%s,%08X,%08X,%p)\n", space.device().tag(), space.name(), bytestart, byteend, memory));
+
+ // allocate a block if needed
+ if (m_data == NULL)
+ {
+ offs_t length = byteend + 1 - bytestart;
+ if (length < 4096)
+ m_allocated = m_data = auto_alloc_array_clear(space.machine(), UINT8, length);
+ else
+ {
+ m_allocated = auto_alloc_array_clear(space.machine(), UINT8, length + 0xfff);
+ m_data = reinterpret_cast<UINT8 *>((reinterpret_cast<FPTR>(m_allocated) + 0xfff) & ~0xfff);
+ }
+ }
+
+ // register for saving, but only if we're not part of a memory region
+ const memory_region *region;
+ for (region = space.machine().first_region(); region != NULL; region = region->next())
+ if (m_data >= region->base() && (m_data + (byteend - bytestart + 1)) < region->end())
+ {
+ VPRINTF(("skipping save of this memory block as it is covered by a memory region\n"));
+ break;
+ }
+
+ // if we didn't find a match, register
+ if (region == NULL)
+ {
+ int bytes_per_element = space.data_width() / 8;
+ astring name;
+ name.printf("%08x-%08x", bytestart, byteend);
+ space.machine().save().save_memory("memory", space.device().tag(), space.spacenum(), name, m_data, bytes_per_element, (UINT32)(byteend + 1 - bytestart) / bytes_per_element);
+ }
+}
+
+
+//-------------------------------------------------
+// memory_block - destructor
+//-------------------------------------------------
+
+memory_block::~memory_block()
+{
+ if (m_allocated != NULL)
+ auto_free(machine(), m_allocated);
+}
+
+
+
+//**************************************************************************
+// MEMORY BANK
+//**************************************************************************
+
+//-------------------------------------------------
+// memory_bank - constructor
+//-------------------------------------------------
+
+memory_bank::memory_bank(address_space &space, int index, offs_t bytestart, offs_t byteend, const char *tag)
+ : m_next(NULL),
+ m_machine(space.machine()),
+ m_baseptr(&space.machine().memory_data->bank_ptr[index]),
+ m_basedptr(&space.machine().memory_data->bankd_ptr[index]),
+ m_index(index),
+ m_anonymous(tag == NULL),
+ m_bytestart(bytestart),
+ m_byteend(byteend),
+ m_curentry(BANK_ENTRY_UNSPECIFIED),
+ m_entry(NULL),
+ m_entry_count(0)
+{
+ // generate an internal tag if we don't have one
+ if (tag == NULL)
+ {
+ m_tag.printf("~%d~", index);
+ m_name.printf("Internal bank #%d", index);
+ }
+ else
+ {
+ m_tag.cpy(tag);
+ m_name.printf("Bank '%s'", tag);
+ }
+
+ if (!m_anonymous && space.machine().save().registration_allowed())
+ space.machine().save().save_item("memory", m_tag, 0, NAME(m_curentry));
+}
+
+
+//-------------------------------------------------
+// memory_bank - destructor
+//-------------------------------------------------
+
+memory_bank::~memory_bank()
+{
+ auto_free(machine(), m_entry);
+}
+
+
+//-------------------------------------------------
+// references_space - walk the list of references
+// to find a match against the provided space
+// and read/write
+//-------------------------------------------------
+
+bool memory_bank::references_space(address_space &space, read_or_write readorwrite) const
+{
+ for (bank_reference *ref = m_reflist.first(); ref != NULL; ref = ref->next())
+ if (ref->matches(space, readorwrite))
+ return true;
+ return false;
+}
+
+
+//-------------------------------------------------
+// add_reference - add a new reference to the
+// given space
+//-------------------------------------------------
+
+void memory_bank::add_reference(address_space &space, read_or_write readorwrite)
+{
+ // if we already have a reference, skip it
+ if (references_space(space, readorwrite))
+ return;
+ m_reflist.append(*auto_alloc(space.machine(), bank_reference(space, readorwrite)));
+}
+
+
+//-------------------------------------------------
+// invalidate_references - force updates on all
+// referencing address spaces
+//-------------------------------------------------
+
+void memory_bank::invalidate_references()
+{
+ // invalidate all the direct references to any referenced address spaces
+ for (bank_reference *ref = m_reflist.first(); ref != NULL; ref = ref->next())
+ ref->space().direct().force_update();
+}
+
+
+//-------------------------------------------------
+// set_base - set the bank base explicitly
+//-------------------------------------------------
+
+void memory_bank::set_base(void *base)
+{
+ // NULL is not an option
+ if (base == NULL)
+ throw emu_fatalerror("memory_bank::set_base called NULL base");
+
+ // set the base and invalidate any referencing spaces
+ *m_baseptr = reinterpret_cast<UINT8 *>(base);
+ invalidate_references();
+}
+
+
+//-------------------------------------------------
+// set_base_decrypted - set the decrypted base
+// explicitly
+//-------------------------------------------------
+
+void memory_bank::set_base_decrypted(void *base)
+{
+ // NULL is not an option
+ if (base == NULL)
+ throw emu_fatalerror("memory_bank::set_base called NULL base");
+
+ // set the base and invalidate any referencing spaces
+ *m_basedptr = reinterpret_cast<UINT8 *>(base);
+ invalidate_references();
+}
+
+
+//-------------------------------------------------
+// set_entry - set the base to a pre-configured
+// entry
+//-------------------------------------------------
+
+void memory_bank::set_entry(int entrynum)
+{
+ // validate
+ if (m_anonymous)
+ throw emu_fatalerror("memory_bank::set_entry called for anonymous bank");
+ if (entrynum < 0 || entrynum >= m_entry_count)
+ throw emu_fatalerror("memory_bank::set_entry called with out-of-range entry %d", entrynum);
+ if (m_entry[entrynum].m_raw == NULL)
+ throw emu_fatalerror("memory_bank::set_entry called for bank '%s' with invalid bank entry %d", m_tag.cstr(), entrynum);
+
+ // set both raw and decrypted values
+ m_curentry = entrynum;
+ *m_baseptr = m_entry[entrynum].m_raw;
+ *m_basedptr = m_entry[entrynum].m_decrypted;
+
+ // invalidate referencing spaces
+ invalidate_references();
+}
+
+
+//-------------------------------------------------
+// expand_entries - expand the allocated array
+// of entries
+//-------------------------------------------------
+
+void memory_bank::expand_entries(int entrynum)
+{
+ int newcount = entrynum + 1;
+
+ // allocate a new array and copy from the old one; zero out the new entries
+ bank_entry *newentry = auto_alloc_array(machine(), bank_entry, newcount);
+ memcpy(newentry, m_entry, sizeof(m_entry[0]) * m_entry_count);
+ memset(&newentry[m_entry_count], 0, (newcount - m_entry_count) * sizeof(m_entry[0]));
+
+ // free the old array and set the updated values
+ auto_free(machine(), m_entry);
+ m_entry = newentry;
+ m_entry_count = newcount;
+}
+
+
+//-------------------------------------------------
+// configure - configure an entry
+//-------------------------------------------------
+
+void memory_bank::configure(int entrynum, void *base)
+{
+ // must be positive
+ if (entrynum < 0)
+ throw emu_fatalerror("memory_bank::configure called with out-of-range entry %d", entrynum);
+
+ // if we haven't allocated this many entries yet, expand our array
+ if (entrynum >= m_entry_count)
+ expand_entries(entrynum);
+
+ // set the entry
+ m_entry[entrynum].m_raw = reinterpret_cast<UINT8 *>(base);
+
+ // if the bank base is not configured, and we're the first entry, set us up
+ if (*m_baseptr == NULL && entrynum == 0)
+ *m_baseptr = m_entry[entrynum].m_raw;
+}
+
+
+//-------------------------------------------------
+// configure_decrypted - configure a decrypted
+// entry
+//-------------------------------------------------
+
+void memory_bank::configure_decrypted(int entrynum, void *base)
+{
+ // must be positive
+ if (entrynum < 0)
+ throw emu_fatalerror("memory_bank::configure called with out-of-range entry %d", entrynum);
+
+ // if we haven't allocated this many entries yet, expand our array
+ if (entrynum >= m_entry_count)
+ expand_entries(entrynum);
+
+ // set the entry
+ m_entry[entrynum].m_decrypted = reinterpret_cast<UINT8 *>(base);
+
+ // if the bank base is not configured, and we're the first entry, set us up
+ if (*m_basedptr == NULL && entrynum == 0)
+ *m_basedptr = m_entry[entrynum].m_decrypted;
+}
+
+
+
+//**************************************************************************
+// HANDLER ENTRY
+//**************************************************************************
+
+//-------------------------------------------------
+// handler_entry - constructor
+//-------------------------------------------------
+
+handler_entry::handler_entry(UINT8 width, endianness_t endianness, UINT8 **rambaseptr)
+ : m_populated(false),
+ m_datawidth(width),
+ m_endianness(endianness),
+ m_bytestart(0),
+ m_byteend(0),
+ m_bytemask(~0),
+ m_rambaseptr(rambaseptr),
+ m_subunits(0)
+{
+}
+
+
+//-------------------------------------------------
+// ~handler_entry - destructor
+//-------------------------------------------------
+
+handler_entry::~handler_entry()
+{
+}
+
+
+//-------------------------------------------------
+// copy - copy another handler_entry, but only
+// if it is populated and constitutes of one or
+// more subunit handlers
+//-------------------------------------------------
+
+void handler_entry::copy(handler_entry *entry)
+{
+ assert(entry->m_populated);
+ assert(entry->m_subunits);
+ assert(!entry->m_rambaseptr);
+ assert(!m_populated);
+
+ m_populated = true;
+ m_datawidth = entry->m_datawidth;
+ m_endianness = entry->m_endianness;
+ m_bytestart = entry->m_bytestart;
+ m_byteend = entry->m_byteend;
+ m_bytemask = entry->m_bytemask;
+ m_rambaseptr = 0;
+ m_subunits = entry->m_subunits;
+ memcpy(m_subunit_infos, entry->m_subunit_infos, m_subunits*sizeof(subunit_info));
+ m_invsubmask = entry->m_invsubmask;
+}
+
+
+//-------------------------------------------------
+// reconfigure_subunits - reconfigure the subunits
+// to handle a new base address
+//-------------------------------------------------
+void handler_entry::reconfigure_subunits(offs_t bytestart)
+{
+ offs_t delta = bytestart - m_bytestart;
+ for (int i=0; i != m_subunits; i++)
+ m_subunit_infos[i].m_offset -= delta;
+}
+
+
+//-------------------------------------------------
+// configure_subunits - configure the subunits
+// and subshift array to represent the provided
+// mask
+//-------------------------------------------------
+
+void handler_entry::configure_subunits(UINT64 handlermask, int handlerbits, int &start_slot, int &end_slot)
+{
+ UINT64 unitmask = ((UINT64)1 << handlerbits) - 1;
+ assert(handlermask != 0);
+
+ // compute the maximum possible subunits
+ int maxunits = m_datawidth / handlerbits;
+ assert(maxunits > 1);
+ assert(maxunits <= ARRAY_LENGTH(m_subunit_infos));
+
+ int shift_xor_mask = m_endianness == ENDIANNESS_LITTLE ? 0 : maxunits - 1;
+
+ // walk the handlermask to find out how many we have
+ int count = 0;
+ for (int unitnum = 0; unitnum < maxunits; unitnum++)
+ {
+ UINT32 shift = unitnum * handlerbits;
+ UINT32 scanmask = handlermask >> shift;
+ assert((scanmask & unitmask) == 0 || (scanmask & unitmask) == unitmask);
+ if ((scanmask & unitmask) != 0)
+ count++;
+ }
+
+ // fill in the shifts
+ int cur_offset = 0;
+ start_slot = m_subunits;
+ for (int unitnum = 0; unitnum < maxunits; unitnum++)
+ {
+ UINT32 shift = (unitnum^shift_xor_mask) * handlerbits;
+ if (((handlermask >> shift) & unitmask) != 0)
+ {
+ m_subunit_infos[m_subunits].m_mask = unitmask;
+ m_subunit_infos[m_subunits].m_offset = cur_offset++;
+ m_subunit_infos[m_subunits].m_size = handlerbits;
+ m_subunit_infos[m_subunits].m_shift = shift;
+ m_subunit_infos[m_subunits].m_multiplier = count;
+
+ m_subunits++;
+ }
+ }
+ end_slot = m_subunits;
+
+ // compute the inverse mask
+ m_invsubmask = 0;
+ for (int i = 0; i < m_subunits; i++)
+ m_invsubmask |= m_subunit_infos[i].m_mask << m_subunit_infos[i].m_shift;
+ m_invsubmask = ~m_invsubmask;
+}
+
+
+//-------------------------------------------------
+// clear_conflicting_subunits - clear the subunits
+// conflicting with the provided mask
+//-------------------------------------------------
+
+void handler_entry::clear_conflicting_subunits(UINT64 handlermask)
+{
+ // A mask of 0 is in fact an alternative way of saying ~0
+ if (!handlermask)
+ {
+ m_subunits = 0;
+ return;
+ }
+
+ // Start by the end to avoid unnecessary memmoves
+ for (int i=m_subunits-1; i>=0; i--)
+ if (((handlermask >> m_subunit_infos[i].m_shift) & m_subunit_infos[i].m_mask) != 0)
+ {
+ if (i != m_subunits-1)
+ memmove (m_subunit_infos+i, m_subunit_infos+i+1, (m_subunits-i-1)*sizeof(m_subunit_infos[0]));
+ remove_subunit(i);
+ }
+
+ // compute the inverse mask
+ m_invsubmask = 0;
+ for (int i = 0; i < m_subunits; i++)
+ m_invsubmask |= m_subunit_infos[i].m_mask << m_subunit_infos[i].m_shift;
+ m_invsubmask = ~m_invsubmask;
+}
+
+
+//-------------------------------------------------
+// overriden_by_mask - check whether a handler with
+// the provided mask fully overrides everything
+// that's currently present
+//-------------------------------------------------
+
+bool handler_entry::overriden_by_mask(UINT64 handlermask)
+{
+ // A mask of 0 is in fact an alternative way of saying ~0
+ if (!handlermask)
+ return true;
+
+ // If there are no subunits, it's going to override
+ if (!m_subunits)
+ return true;
+
+ // Check whether a subunit would be left
+ for (int i=0; i != m_subunits; i++)
+ if (((handlermask >> m_subunit_infos[i].m_shift) & m_subunit_infos[i].m_mask) == 0)
+ return false;
+
+ return true;
+}
+
+
+//-------------------------------------------------
+// description - build a printable description
+// of the handler
+//-------------------------------------------------
+
+void handler_entry::description(char *buffer) const
+{
+ if (m_subunits)
+ {
+ for (int i=0; i != m_subunits; i++)
+ {
+ if (i)
+ *buffer++ = ' ';
+ buffer += sprintf (buffer, "%d:%d:%x:%d:%s",
+ m_subunit_infos[i].m_size,
+ m_subunit_infos[i].m_shift,
+ m_subunit_infos[i].m_offset,
+ m_subunit_infos[i].m_multiplier,
+ subunit_name(i));
+ }
+ }
+ else
+ strcpy (buffer, name());
+}
+
+
+//**************************************************************************
+// HANDLER ENTRY READ
+//**************************************************************************
+
+//-------------------------------------------------
+// copy - copy another handler_entry, but only
+// if it is populated and constitutes of one or
+// more subunit handlers
+//-------------------------------------------------
+
+void handler_entry_read::copy(handler_entry *entry)
+{
+ handler_entry::copy(entry);
+ handler_entry_read *rentry = static_cast<handler_entry_read *>(entry);
+ m_read = rentry->m_read;
+ memcpy(m_subread, rentry->m_subread, m_subunits*sizeof(access_handler));
+ memcpy(m_sub_is_legacy, rentry->m_sub_is_legacy, m_subunits*sizeof(bool));
+ memcpy(m_sublegacy_info, rentry->m_sublegacy_info, m_subunits*sizeof(legacy_info));
+}
+
+//-------------------------------------------------
+// name - return the handler name, from the
+// appropriately-sized delegate
+//-------------------------------------------------
+
+const char *handler_entry_read::name() const
+{
+ switch (m_datawidth)
+ {
+ case 8: return m_read.r8.name();
+ case 16: return m_read.r16.name();
+ case 32: return m_read.r32.name();
+ case 64: return m_read.r64.name();
+ }
+ return NULL;
+}
+
+//-------------------------------------------------
+// subunit_name - return the handler name, from the
+// appropriately-sized delegate of a subunit
+//-------------------------------------------------
+
+const char *handler_entry_read::subunit_name(int entry) const
+{
+ switch (m_subunit_infos[entry].m_size)
+ {
+ case 8: return m_subread[entry].r8.name();
+ case 16: return m_subread[entry].r16.name();
+ case 32: return m_subread[entry].r32.name();
+ case 64: return m_subread[entry].r64.name();
+ }
+ return NULL;
+}
+
+
+//-------------------------------------------------
+// remove_subunit - delete a subunit specific
+// information and shift up the following ones
+//-------------------------------------------------
+void handler_entry_read::remove_subunit(int entry)
+{
+ int moving = m_subunits - entry - 1;
+ if (moving)
+ {
+ memmove(m_subread+entry, m_subread+entry+1, moving*sizeof(m_subread[0]));
+ memmove(m_sub_is_legacy+entry, m_sub_is_legacy+entry+1, moving*sizeof(m_sub_is_legacy[0]));
+ memmove(m_sublegacy_info+entry, m_sublegacy_info+entry+1, moving*sizeof(m_sublegacy_info[0]));
+ }
+ m_subunits--;
+}
+
+
+//-------------------------------------------------
+// set_delegate - set an 8-bit delegate, and
+// configure a stub if necessary
+//-------------------------------------------------
+
+void handler_entry_read::set_delegate(read8_delegate delegate, UINT64 mask, const legacy_info *info)
+{
+ // error if no object
+ if (!delegate.has_object())
+ throw emu_fatalerror("Attempted to install delegate '%s' without a bound object", delegate.name());
+
+ // make sure this is a valid size
+ assert(m_datawidth >= 8);
+
+ // if mismatched bus width, configure a stub
+ if (m_datawidth != 8)
+ {
+ int start_slot, end_slot;
+ configure_subunits(mask, 8, start_slot, end_slot);
+ if (info)
+ for (int i=start_slot; i != end_slot; i++)
+ {
+ m_sublegacy_info[i] = *info;
+ m_sub_is_legacy[i] = true;
+ }
+ else
+ for (int i=start_slot; i != end_slot; i++)
+ {
+ m_subread[i].r8 = delegate;
+ m_sub_is_legacy[i] = false;
+ }
+ if (m_datawidth == 16)
+ set_delegate(read16_delegate(&handler_entry_read::read_stub_16, delegate.name(), this));
+ else if (m_datawidth == 32)
+ set_delegate(read32_delegate(&handler_entry_read::read_stub_32, delegate.name(), this));
+ else if (m_datawidth == 64)
+ set_delegate(read64_delegate(&handler_entry_read::read_stub_64, delegate.name(), this));
+ }
+ else
+ {
+ m_read.r8 = delegate;
+ if (info)
+ m_legacy_info = *info;
+ }
+}
+
+
+//-------------------------------------------------
+// set_delegate - set a 16-bit delegate, and
+// configure a stub if necessary
+//-------------------------------------------------
+
+void handler_entry_read::set_delegate(read16_delegate delegate, UINT64 mask, const legacy_info *info)
+{
+ // error if no object
+ if (!delegate.has_object())
+ throw emu_fatalerror("Attempted to install delegate '%s' without a bound object", delegate.name());
+
+ // make sure this is a valid size
+ assert(m_datawidth >= 16);
+
+ // if mismatched bus width, configure a stub
+ if (m_datawidth != 16)
+ {
+ int start_slot, end_slot;
+ configure_subunits(mask, 16, start_slot, end_slot);
+ if (info)
+ for (int i=start_slot; i != end_slot; i++)
+ {
+ m_sublegacy_info[i] = *info;
+ m_sub_is_legacy[i] = true;
+ }
+ else
+ for (int i=start_slot; i != end_slot; i++)
+ {
+ m_subread[i].r16 = delegate;
+ m_sub_is_legacy[i] = false;
+ }
+ if (m_datawidth == 32)
+ set_delegate(read32_delegate(&handler_entry_read::read_stub_32, delegate.name(), this));
+ else if (m_datawidth == 64)
+ set_delegate(read64_delegate(&handler_entry_read::read_stub_64, delegate.name(), this));
+ }
+ else
+ {
+ m_read.r16 = delegate;
+ if (info)
+ m_legacy_info = *info;
+ }
+}
+
+
+//-------------------------------------------------
+// set_delegate - set a 32-bit delegate, and
+// configure a stub if necessary
+//-------------------------------------------------
+
+void handler_entry_read::set_delegate(read32_delegate delegate, UINT64 mask, const legacy_info *info)
+{
+ // error if no object
+ if (!delegate.has_object())
+ throw emu_fatalerror("Attempted to install delegate '%s' without a bound object", delegate.name());
+
+ // make sure this is a valid size
+ assert(m_datawidth >= 32);
+
+ // if mismatched bus width, configure a stub
+ if (m_datawidth != 32)
+ {
+ int start_slot, end_slot;
+ configure_subunits(mask, 32, start_slot, end_slot);
+ if (info)
+ for (int i=start_slot; i != end_slot; i++)
+ {
+ m_sublegacy_info[i] = *info;
+ m_sub_is_legacy[i] = true;
+ }
+ else
+ for (int i=start_slot; i != end_slot; i++)
+ {
+ m_subread[i].r32 = delegate;
+ m_sub_is_legacy[i] = false;
+ }
+ if (m_datawidth == 64)
+ set_delegate(read64_delegate(&handler_entry_read::read_stub_64, delegate.name(), this));
+ }
+ else
+ {
+ m_read.r32 = delegate;
+ if (info)
+ m_legacy_info = *info;
+ }
+}
+
+
+//-------------------------------------------------
+// set_delegate - set a 64-bit delegate
+//-------------------------------------------------
+
+void handler_entry_read::set_delegate(read64_delegate delegate, UINT64 mask, const legacy_info *info)
+{
+ // error if no object
+ if (!delegate.has_object())
+ throw emu_fatalerror("Attempted to install delegate '%s' without a bound object", delegate.name());
+
+ // make sure this is a valid size
+ assert(m_datawidth >= 64);
+ m_read.r64 = delegate;
+ if (info)
+ m_legacy_info = *info;
+}
+
+
+//-------------------------------------------------
+// set_legacy_func - configure a legacy address
+// space stub of the appropriate size
+//-------------------------------------------------
+
+void handler_entry_read::set_legacy_func(address_space &space, read8_space_func func, const char *name, UINT64 mask)
+{
+ legacy_info info;
+ info.handler.space8 = func;
+ info.object.space = &space;
+ set_delegate(read8_delegate(&handler_entry_read::read_stub_legacy, name, this), mask, &info);
+}
+
+void handler_entry_read::set_legacy_func(address_space &space, read16_space_func func, const char *name, UINT64 mask)
+{
+ legacy_info info;
+ info.handler.space16 = func;
+ info.object.space = &space;
+ set_delegate(read16_delegate(&handler_entry_read::read_stub_legacy, name, this), mask, &info);
+}
+
+void handler_entry_read::set_legacy_func(address_space &space, read32_space_func func, const char *name, UINT64 mask)
+{
+ legacy_info info;
+ info.handler.space32 = func;
+ info.object.space = &space;
+ set_delegate(read32_delegate(&handler_entry_read::read_stub_legacy, name, this), mask, &info);
+}
+
+void handler_entry_read::set_legacy_func(address_space &space, read64_space_func func, const char *name, UINT64 mask)
+{
+ legacy_info info;
+ info.handler.space64 = func;
+ info.object.space = &space;
+ set_delegate(read64_delegate(&handler_entry_read::read_stub_legacy, name, this), mask, &info);
+}
+
+
+//-------------------------------------------------
+// set_legacy_func - configure a legacy device
+// stub of the appropriate size
+//-------------------------------------------------
+
+void handler_entry_read::set_legacy_func(device_t &device, read8_device_func func, const char *name, UINT64 mask)
+{
+ legacy_info info;
+ info.handler.device8 = func;
+ info.object.device = &device;
+ set_delegate(read8_delegate(&handler_entry_read::read_stub_legacy, name, this), mask, &info);
+}
+
+void handler_entry_read::set_legacy_func(device_t &device, read16_device_func func, const char *name, UINT64 mask)
+{
+ legacy_info info;
+ info.handler.device16 = func;
+ info.object.device = &device;
+ set_delegate(read16_delegate(&handler_entry_read::read_stub_legacy, name, this), mask, &info);
+}
+
+void handler_entry_read::set_legacy_func(device_t &device, read32_device_func func, const char *name, UINT64 mask)
+{
+ legacy_info info;
+ info.handler.device32 = func;
+ info.object.device = &device;
+ set_delegate(read32_delegate(&handler_entry_read::read_stub_legacy, name, this), mask, &info);
+}
+
+void handler_entry_read::set_legacy_func(device_t &device, read64_device_func func, const char *name, UINT64 mask)
+{
+ legacy_info info;
+ info.handler.device64 = func;
+ info.object.device = &device;
+ set_delegate(read64_delegate(&handler_entry_read::read_stub_legacy, name, this), mask, &info);
+}
+
+
+//-------------------------------------------------
+// set_ioport - configure an I/O port read stub
+// of the appropriate size
+//-------------------------------------------------
+
+void handler_entry_read::set_ioport(const input_port_config &ioport)
+{
+ m_ioport = &ioport;
+ if (m_datawidth == 8)
+ set_delegate(read8_delegate(&handler_entry_read::read_stub_ioport<UINT8>, ioport.tag(), this));
+ else if (m_datawidth == 16)
+ set_delegate(read16_delegate(&handler_entry_read::read_stub_ioport<UINT16>, ioport.tag(), this));
+ else if (m_datawidth == 32)
+ set_delegate(read32_delegate(&handler_entry_read::read_stub_ioport<UINT32>, ioport.tag(), this));
+ else if (m_datawidth == 64)
+ set_delegate(read64_delegate(&handler_entry_read::read_stub_ioport<UINT64>, ioport.tag(), this));
+}
+
+
+//-------------------------------------------------
+// read_stub_16 - construct a 16-bit read from
+// 8-bit sources
+//-------------------------------------------------
+
+UINT16 handler_entry_read::read_stub_16(address_space &space, offs_t offset, UINT16 mask)
+{
+ UINT16 result = space.unmap() & m_invsubmask;
+ for (int index = 0; index < m_subunits; index++)
+ {
+ const subunit_info &si = m_subunit_infos[index];
+ UINT32 submask = (mask >> si.m_shift) & si.m_mask;
+ if (submask)
+ {
+ offs_t aoffset = offset * si.m_multiplier + si.m_offset;
+ UINT8 val;
+ if (m_sub_is_legacy[index])
+ val = m_sublegacy_info[index].handler.space8(m_sublegacy_info[index].object.space, aoffset);
+ else
+ val = m_subread[index].r8(space, aoffset, submask);
+ result |= val << si.m_shift;
+ }
+ }
+ return result;
+}
+
+
+//-------------------------------------------------
+// read_stub_32 - construct a 32-bit read from
+// 8-bit and 16-bit sources
+//-------------------------------------------------
+
+UINT32 handler_entry_read::read_stub_32(address_space &space, offs_t offset, UINT32 mask)
+{
+ UINT32 result = space.unmap() & m_invsubmask;
+ for (int index = 0; index < m_subunits; index++)
+ {
+ const subunit_info &si = m_subunit_infos[index];
+ UINT32 submask = (mask >> si.m_shift) & si.m_mask;
+ if (submask)
+ {
+ offs_t aoffset = offset * si.m_multiplier + si.m_offset;
+ UINT16 val = 0;
+ if (m_sub_is_legacy[index])
+ {
+ switch (si.m_size)
+ {
+ case 8:
+ val = m_sublegacy_info[index].handler.space8(m_sublegacy_info[index].object.space, aoffset);
+ break;
+ case 16:
+ val = m_sublegacy_info[index].handler.space16(m_sublegacy_info[index].object.space, aoffset, submask);
+ break;
+ }
+ }
+ else
+ {
+ switch (si.m_size)
+ {
+ case 8:
+ val = m_subread[index].r8(space, aoffset, submask);
+ break;
+ case 16:
+ val = m_subread[index].r16(space, aoffset, submask);
+ break;
+ }
+ }
+ result |= val << si.m_shift;
+ }
+ }
+ return result;
+}
+
+
+//-------------------------------------------------
+// read_stub_64 - construct a 64-bit read from
+// 8-bit, 16-bit and 32-bit sources
+//-------------------------------------------------
+
+UINT64 handler_entry_read::read_stub_64(address_space &space, offs_t offset, UINT64 mask)
+{
+ UINT64 result = space.unmap() & m_invsubmask;
+ for (int index = 0; index < m_subunits; index++)
+ {
+ const subunit_info &si = m_subunit_infos[index];
+ UINT32 submask = (mask >> si.m_shift) & si.m_mask;
+ if (submask)
+ {
+ offs_t aoffset = offset * si.m_multiplier + si.m_offset;
+ UINT32 val = 0;
+ if (m_sub_is_legacy[index])
+ {
+ switch (si.m_size)
+ {
+ case 8:
+ val = m_sublegacy_info[index].handler.space8(m_sublegacy_info[index].object.space, aoffset);
+ break;
+ case 16:
+ val = m_sublegacy_info[index].handler.space16(m_sublegacy_info[index].object.space, aoffset, submask);
+ break;
+ case 32:
+ val = m_sublegacy_info[index].handler.space32(m_sublegacy_info[index].object.space, aoffset, submask);
+ break;
+ }
+ }
+ else
+ {
+ switch (si.m_size)
+ {
+ case 8:
+ val = m_subread[index].r8(space, aoffset, submask);
+ break;
+ case 16:
+ val = m_subread[index].r16(space, aoffset, submask);
+ break;
+ case 32:
+ val = m_subread[index].r32(space, aoffset, submask);
+ break;
+ }
+ }
+ result |= UINT64(val) << si.m_shift;
+ }
+ }
+ return result;
+}
+
+
+//-------------------------------------------------
+// read_stub_legacy - perform a read using legacy
+// handler callbacks
+//-------------------------------------------------
+
+UINT8 handler_entry_read::read_stub_legacy(address_space &space, offs_t offset, UINT8 mask)
+{
+ return m_legacy_info.handler.space8(m_legacy_info.object.space, offset);
+}
+
+UINT16 handler_entry_read::read_stub_legacy(address_space &space, offs_t offset, UINT16 mask)
+{
+ return m_legacy_info.handler.space16(m_legacy_info.object.space, offset, mask);
+}
+
+UINT32 handler_entry_read::read_stub_legacy(address_space &space, offs_t offset, UINT32 mask)
+{
+ return m_legacy_info.handler.space32(m_legacy_info.object.space, offset, mask);
+}
+
+UINT64 handler_entry_read::read_stub_legacy(address_space &space, offs_t offset, UINT64 mask)
+{
+ return m_legacy_info.handler.space64(m_legacy_info.object.space, offset, mask);
+}
+
+
+
+//**************************************************************************
+// HANDLER ENTRY WRITE
+//**************************************************************************
+
+//-------------------------------------------------
+// copy - copy another handler_entry, but only
+// if it is populated and constitutes of one or
+// more subunit handlers
+//-------------------------------------------------
+
+void handler_entry_write::copy(handler_entry *entry)
+{
+ handler_entry::copy(entry);
+ handler_entry_write *wentry = static_cast<handler_entry_write *>(entry);
+ m_write = wentry->m_write;
+ memcpy(m_subwrite, wentry->m_subwrite, m_subunits*sizeof(access_handler));
+ memcpy(m_sub_is_legacy, wentry->m_sub_is_legacy, m_subunits*sizeof(bool));
+ memcpy(m_sublegacy_info, wentry->m_sublegacy_info, m_subunits*sizeof(legacy_info));
+}
+
+//-------------------------------------------------
+// name - return the handler name, from the
+// appropriately-sized delegate
+//-------------------------------------------------
+
+const char *handler_entry_write::name() const
+{
+ switch (m_datawidth)
+ {
+ case 8: return m_write.w8.name();
+ case 16: return m_write.w16.name();
+ case 32: return m_write.w32.name();
+ case 64: return m_write.w64.name();
+ }
+ return NULL;
+}
+
+
+//-------------------------------------------------
+// subunit_name - return the handler name, from the
+// appropriately-sized delegate of a subunit
+//-------------------------------------------------
+
+const char *handler_entry_write::subunit_name(int entry) const
+{
+ switch (m_subunit_infos[entry].m_size)
+ {
+ case 8: return m_subwrite[entry].w8.name();
+ case 16: return m_subwrite[entry].w16.name();
+ case 32: return m_subwrite[entry].w32.name();
+ case 64: return m_subwrite[entry].w64.name();
+ }
+ return NULL;
+}
+
+
+//-------------------------------------------------
+// remove_subunit - delete a subunit specific
+// information and shift up the following ones
+//-------------------------------------------------
+void handler_entry_write::remove_subunit(int entry)
+{
+ int moving = m_subunits - entry - 1;
+ if (moving)
+ {
+ memmove(m_subwrite+entry, m_subwrite+entry+1, moving*sizeof(m_subwrite[0]));
+ memmove(m_sub_is_legacy+entry, m_sub_is_legacy+entry+1, moving*sizeof(m_sub_is_legacy[0]));
+ memmove(m_sublegacy_info+entry, m_sublegacy_info+entry+1, moving*sizeof(m_sublegacy_info[0]));
+ }
+ m_subunits--;
+}
+
+
+//-------------------------------------------------
+// set_delegate - set an 8-bit delegate, and
+// configure a stub if necessary
+//-------------------------------------------------
+
+void handler_entry_write::set_delegate(write8_delegate delegate, UINT64 mask, const legacy_info *info)
+{
+ assert(m_datawidth >= 8);
+
+ // if mismatched bus width, configure a stub
+ if (m_datawidth != 8)
+ {
+ int start_slot, end_slot;
+ configure_subunits(mask, 8, start_slot, end_slot);
+ if (info)
+ for (int i=start_slot; i != end_slot; i++)
+ {
+ m_sublegacy_info[i] = *info;
+ m_sub_is_legacy[i] = true;
+ }
+ else
+ for (int i=start_slot; i != end_slot; i++)
+ {
+ m_subwrite[i].w8 = delegate;
+ m_sub_is_legacy[i] = false;
+ }
+ if (m_datawidth == 16)
+ set_delegate(write16_delegate(&handler_entry_write::write_stub_16, delegate.name(), this));
+ else if (m_datawidth == 32)
+ set_delegate(write32_delegate(&handler_entry_write::write_stub_32, delegate.name(), this));
+ else if (m_datawidth == 64)
+ set_delegate(write64_delegate(&handler_entry_write::write_stub_64, delegate.name(), this));
+ }
+ else
+ {
+ m_write.w8 = delegate;
+ if (info)
+ m_legacy_info = *info;
+ }
+}
+
+
+//-------------------------------------------------
+// set_delegate - set a 16-bit delegate, and
+// configure a stub if necessary
+//-------------------------------------------------
+
+void handler_entry_write::set_delegate(write16_delegate delegate, UINT64 mask, const legacy_info *info)
+{
+ assert(m_datawidth >= 16);
+
+ // if mismatched bus width, configure a stub
+ if (m_datawidth != 16)
+ {
+ int start_slot, end_slot;
+ configure_subunits(mask, 16, start_slot, end_slot);
+ if (info)
+ for (int i=start_slot; i != end_slot; i++)
+ {
+ m_sublegacy_info[i] = *info;
+ m_sub_is_legacy[i] = true;
+ }
+ else
+ for (int i=start_slot; i != end_slot; i++)
+ {
+ m_subwrite[i].w16 = delegate;
+ m_sub_is_legacy[i] = false;
+ }
+ if (m_datawidth == 32)
+ set_delegate(write32_delegate(&handler_entry_write::write_stub_32, delegate.name(), this));
+ else if (m_datawidth == 64)
+ set_delegate(write64_delegate(&handler_entry_write::write_stub_64, delegate.name(), this));
+ }
+ else
+ {
+ m_write.w16 = delegate;
+ if (info)
+ m_legacy_info = *info;
+ }
+}
+
+
+//-------------------------------------------------
+// set_delegate - set a 32-bit delegate, and
+// configure a stub if necessary
+//-------------------------------------------------
+
+void handler_entry_write::set_delegate(write32_delegate delegate, UINT64 mask, const legacy_info *info)
+{
+ assert(m_datawidth >= 32);
+
+ // if mismatched bus width, configure a stub
+ if (m_datawidth != 32)
+ {
+ int start_slot, end_slot;
+ configure_subunits(mask, 32, start_slot, end_slot);
+ if (info)
+ for (int i=start_slot; i != end_slot; i++)
+ {
+ m_sublegacy_info[i] = *info;
+ m_sub_is_legacy[i] = true;
+ }
+ else
+ for (int i=start_slot; i != end_slot; i++)
+ {
+ m_subwrite[i].w32 = delegate;
+ m_sub_is_legacy[i] = false;
+ }
+ if (m_datawidth == 64)
+ set_delegate(write64_delegate(&handler_entry_write::write_stub_64, delegate.name(), this));
+ }
+ else
+ {
+ m_write.w32 = delegate;
+ if (info)
+ m_legacy_info = *info;
+ }
+}
+
+
+//-------------------------------------------------
+// set_delegate - set a 64-bit delegate
+//-------------------------------------------------
+
+void handler_entry_write::set_delegate(write64_delegate delegate, UINT64 mask, const legacy_info *info)
+{
+ assert(m_datawidth >= 64);
+ m_write.w64 = delegate;
+ if (info)
+ m_legacy_info = *info;
+}
+
+
+//-------------------------------------------------
+// set_legacy_func - configure a legacy address
+// space stub of the appropriate size
+//-------------------------------------------------
+
+void handler_entry_write::set_legacy_func(address_space &space, write8_space_func func, const char *name, UINT64 mask)
+{
+ legacy_info info;
+ info.handler.space8 = func;
+ info.object.space = &space;
+ set_delegate(write8_delegate(&handler_entry_write::write_stub_legacy, name, this), mask, &info);
+}
+
+void handler_entry_write::set_legacy_func(address_space &space, write16_space_func func, const char *name, UINT64 mask)
+{
+ legacy_info info;
+ info.handler.space16 = func;
+ info.object.space = &space;
+ set_delegate(write16_delegate(&handler_entry_write::write_stub_legacy, name, this), mask, &info);
+}
+
+void handler_entry_write::set_legacy_func(address_space &space, write32_space_func func, const char *name, UINT64 mask)
+{
+ legacy_info info;
+ info.handler.space32 = func;
+ info.object.space = &space;
+ set_delegate(write32_delegate(&handler_entry_write::write_stub_legacy, name, this), mask, &info);
+}
+
+void handler_entry_write::set_legacy_func(address_space &space, write64_space_func func, const char *name, UINT64 mask)
+{
+ legacy_info info;
+ info.handler.space64 = func;
+ info.object.space = &space;
+ set_delegate(write64_delegate(&handler_entry_write::write_stub_legacy, name, this), mask, &info);
+}
+
+
+//-------------------------------------------------
+// set_legacy_func - configure a legacy device
+// stub of the appropriate size
+//-------------------------------------------------
+
+void handler_entry_write::set_legacy_func(device_t &device, write8_device_func func, const char *name, UINT64 mask)
+{
+ legacy_info info;
+ info.handler.device8 = func;
+ info.object.device = &device;
+ set_delegate(write8_delegate(&handler_entry_write::write_stub_legacy, name, this), mask, &info);
+}
+
+void handler_entry_write::set_legacy_func(device_t &device, write16_device_func func, const char *name, UINT64 mask)
+{
+ legacy_info info;
+ info.handler.device16 = func;
+ info.object.device = &device;
+ set_delegate(write16_delegate(&handler_entry_write::write_stub_legacy, name, this), mask, &info);
+}
+
+void handler_entry_write::set_legacy_func(device_t &device, write32_device_func func, const char *name, UINT64 mask)
+{
+ legacy_info info;
+ info.handler.device32 = func;
+ info.object.device = &device;
+ set_delegate(write32_delegate(&handler_entry_write::write_stub_legacy, name, this), mask, &info);
+}
+
+void handler_entry_write::set_legacy_func(device_t &device, write64_device_func func, const char *name, UINT64 mask)
+{
+ legacy_info info;
+ info.handler.device64 = func;
+ info.object.device = &device;
+ set_delegate(write64_delegate(&handler_entry_write::write_stub_legacy, name, this), mask, &info);
+}
+
+
+//-------------------------------------------------
+// set_ioport - configure an I/O port read stub
+// of the appropriate size
+//-------------------------------------------------
+
+void handler_entry_write::set_ioport(const input_port_config &ioport)
+{
+ m_ioport = &ioport;
+ if (m_datawidth == 8)
+ set_delegate(write8_delegate(&handler_entry_write::write_stub_ioport<UINT8>, ioport.tag(), this));
+ else if (m_datawidth == 16)
+ set_delegate(write16_delegate(&handler_entry_write::write_stub_ioport<UINT16>, ioport.tag(), this));
+ else if (m_datawidth == 32)
+ set_delegate(write32_delegate(&handler_entry_write::write_stub_ioport<UINT32>, ioport.tag(), this));
+ else if (m_datawidth == 64)
+ set_delegate(write64_delegate(&handler_entry_write::write_stub_ioport<UINT64>, ioport.tag(), this));
+}
+
+
+//-------------------------------------------------
+// write_stub_16 - construct a 16-bit write from
+// 8-bit sources
+//-------------------------------------------------
+
+void handler_entry_write::write_stub_16(address_space &space, offs_t offset, UINT16 data, UINT16 mask)
+{
+ for (int index = 0; index < m_subunits; index++)
+ {
+ const subunit_info &si = m_subunit_infos[index];
+ UINT32 submask = (mask >> si.m_shift) & si.m_mask;
+ if (submask)
+ {
+ offs_t aoffset = offset * si.m_multiplier + si.m_offset;
+ UINT8 adata = data >> si.m_shift;
+ if (m_sub_is_legacy[index])
+ m_sublegacy_info[index].handler.space8(m_sublegacy_info[index].object.space, aoffset, adata);
+ else
+ m_subwrite[index].w8(space, aoffset, adata, submask);
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// write_stub_32 - construct a 32-bit write from
+// 8-bit and 16-bit sources
+//-------------------------------------------------
+
+void handler_entry_write::write_stub_32(address_space &space, offs_t offset, UINT32 data, UINT32 mask)
+{
+ for (int index = 0; index < m_subunits; index++)
+ {
+ const subunit_info &si = m_subunit_infos[index];
+ UINT32 submask = (mask >> si.m_shift) & si.m_mask;
+ if (submask)
+ {
+ offs_t aoffset = offset * si.m_multiplier + si.m_offset;
+ UINT16 adata = data >> si.m_shift;
+ if (m_sub_is_legacy[index])
+ {
+ switch (si.m_size)
+ {
+ case 8:
+ m_sublegacy_info[index].handler.space8(m_sublegacy_info[index].object.space, aoffset, adata);
+ break;
+ case 16:
+ m_sublegacy_info[index].handler.space16(m_sublegacy_info[index].object.space, aoffset, adata, submask);
+ break;
+ }
+ }
+ else
+ {
+ switch (si.m_size)
+ {
+ case 8:
+ m_subwrite[index].w8(space, aoffset, adata, submask);
+ break;
+ case 16:
+ m_subwrite[index].w16(space, aoffset, adata, submask);
+ break;
+ }
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// write_stub_64 - construct a 64-bit write from
+// 8-bit, 16-bit and 32-bit sources
+//-------------------------------------------------
+
+void handler_entry_write::write_stub_64(address_space &space, offs_t offset, UINT64 data, UINT64 mask)
+{
+ for (int index = 0; index < m_subunits; index++)
+ {
+ const subunit_info &si = m_subunit_infos[index];
+ UINT32 submask = (mask >> si.m_shift) & si.m_mask;
+ if (submask)
+ {
+ offs_t aoffset = offset * si.m_multiplier + si.m_offset;
+ UINT32 adata = data >> si.m_shift;
+ if (m_sub_is_legacy[index])
+ {
+ switch (si.m_size)
+ {
+ case 8:
+ m_sublegacy_info[index].handler.space8(m_sublegacy_info[index].object.space, aoffset, adata);
+ break;
+ case 16:
+ m_sublegacy_info[index].handler.space16(m_sublegacy_info[index].object.space, aoffset, adata, submask);
+ break;
+ case 32:
+ m_sublegacy_info[index].handler.space32(m_sublegacy_info[index].object.space, aoffset, adata, submask);
+ break;
+ }
+ }
+ else
+ {
+ switch (si.m_size)
+ {
+ case 8:
+ m_subwrite[index].w8(space, aoffset, adata, submask);
+ break;
+ case 16:
+ m_subwrite[index].w16(space, aoffset, adata, submask);
+ break;
+ case 32:
+ m_subwrite[index].w32(space, aoffset, adata, submask);
+ break;
+ }
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// write_stub_legacy - perform a write using
+// legacy handler callbacks
+//-------------------------------------------------
+
+void handler_entry_write::write_stub_legacy(address_space &space, offs_t offset, UINT8 data, UINT8 mask)
+{
+ m_legacy_info.handler.space8(m_legacy_info.object.space, offset, data);
+}
+
+void handler_entry_write::write_stub_legacy(address_space &space, offs_t offset, UINT16 data, UINT16 mask)
+{
+ m_legacy_info.handler.space16(m_legacy_info.object.space, offset, data, mask);
+}
+
+void handler_entry_write::write_stub_legacy(address_space &space, offs_t offset, UINT32 data, UINT32 mask)
+{
+ m_legacy_info.handler.space32(m_legacy_info.object.space, offset, data, mask);
+}
+
+void handler_entry_write::write_stub_legacy(address_space &space, offs_t offset, UINT64 data, UINT64 mask)
+{
+ m_legacy_info.handler.space64(m_legacy_info.object.space, offset, data, mask);
+}
diff --git a/trunk/src/emu/memory.h b/trunk/src/emu/memory.h
new file mode 100644
index 00000000000..ec45c6fb342
--- /dev/null
+++ b/trunk/src/emu/memory.h
@@ -0,0 +1,812 @@
+/***************************************************************************
+
+ memory.h
+
+ Functions which handle device memory accesses.
+
+****************************************************************************
+
+ 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 __MEMORY_H__
+#define __MEMORY_H__
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// address spaces
+enum address_spacenum
+{
+ AS_0, // first address space
+ AS_1, // second address space
+ AS_2, // third address space
+ AS_3, // fourth address space
+ ADDRESS_SPACES, // maximum number of address spaces
+
+ // alternate address space names for common use
+ AS_PROGRAM = AS_0, // program address space
+ AS_DATA = AS_1, // data address space
+ AS_IO = AS_2 // I/O address space
+};
+DECLARE_ENUM_OPERATORS(address_spacenum);
+
+// read or write constants
+enum read_or_write
+{
+ ROW_READ = 1,
+ ROW_WRITE = 2,
+ ROW_READWRITE = 3
+};
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// referenced types from other classes
+class device_memory_interface;
+class device_t;
+struct game_driver;
+
+// forward declarations of classes defined here
+class address_map;
+class address_map_entry;
+class memory_bank;
+class direct_read_data;
+class address_space;
+class address_table;
+class address_table_read;
+class address_table_write;
+
+
+// offsets and addresses are 32-bit (for now...)
+typedef UINT32 offs_t;
+
+// address map constructors are functions that build up an address_map
+typedef void (*address_map_constructor)(address_map &map, const device_t &devconfig);
+
+
+// legacy space read/write handlers
+typedef UINT8 (*read8_space_func) (ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset);
+typedef void (*write8_space_func) (ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT8 data);
+typedef UINT16 (*read16_space_func) (ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 mem_mask);
+typedef void (*write16_space_func)(ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 data, ATTR_UNUSED UINT16 mem_mask);
+typedef UINT32 (*read32_space_func) (ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT32 mem_mask);
+typedef void (*write32_space_func)(ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT32 data, ATTR_UNUSED UINT32 mem_mask);
+typedef UINT64 (*read64_space_func) (ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 mem_mask);
+typedef void (*write64_space_func)(ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 data, ATTR_UNUSED UINT64 mem_mask);
+
+// legacy device read/write handlers
+typedef UINT8 (*read8_device_func) (ATTR_UNUSED device_t *device, ATTR_UNUSED offs_t offset);
+typedef void (*write8_device_func) (ATTR_UNUSED device_t *device, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT8 data);
+typedef UINT16 (*read16_device_func) (ATTR_UNUSED device_t *device, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 mem_mask);
+typedef void (*write16_device_func)(ATTR_UNUSED device_t *device, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 data, ATTR_UNUSED UINT16 mem_mask);
+typedef UINT32 (*read32_device_func) (ATTR_UNUSED device_t *device, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT32 mem_mask);
+typedef void (*write32_device_func)(ATTR_UNUSED device_t *device, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT32 data, ATTR_UNUSED UINT32 mem_mask);
+typedef UINT64 (*read64_device_func) (ATTR_UNUSED device_t *device, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 mem_mask);
+typedef void (*write64_device_func)(ATTR_UNUSED device_t *device, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 data, ATTR_UNUSED UINT64 mem_mask);
+
+
+// struct with function pointers for accessors; use is generally discouraged unless necessary
+struct data_accessors
+{
+ UINT8 (*read_byte)(address_space *space, offs_t byteaddress);
+ UINT16 (*read_word)(address_space *space, offs_t byteaddress);
+ UINT16 (*read_word_masked)(address_space *space, offs_t byteaddress, UINT16 mask);
+ UINT32 (*read_dword)(address_space *space, offs_t byteaddress);
+ UINT32 (*read_dword_masked)(address_space *space, offs_t byteaddress, UINT32 mask);
+ UINT64 (*read_qword)(address_space *space, offs_t byteaddress);
+ UINT64 (*read_qword_masked)(address_space *space, offs_t byteaddress, UINT64 mask);
+
+ void (*write_byte)(address_space *space, offs_t byteaddress, UINT8 data);
+ void (*write_word)(address_space *space, offs_t byteaddress, UINT16 data);
+ void (*write_word_masked)(address_space *space, offs_t byteaddress, UINT16 data, UINT16 mask);
+ void (*write_dword)(address_space *space, offs_t byteaddress, UINT32 data);
+ void (*write_dword_masked)(address_space *space, offs_t byteaddress, UINT32 data, UINT32 mask);
+ void (*write_qword)(address_space *space, offs_t byteaddress, UINT64 data);
+ void (*write_qword_masked)(address_space *space, offs_t byteaddress, UINT64 data, UINT64 mask);
+};
+
+
+// ======================> direct_update_delegate
+
+// direct region update handler
+typedef delegate<offs_t (direct_read_data &, offs_t)> direct_update_delegate;
+
+
+// ======================> read_delegate
+
+// declare delegates for each width
+typedef delegate<UINT8 (address_space &, offs_t, UINT8)> read8_delegate;
+typedef delegate<UINT16 (address_space &, offs_t, UINT16)> read16_delegate;
+typedef delegate<UINT32 (address_space &, offs_t, UINT32)> read32_delegate;
+typedef delegate<UINT64 (address_space &, offs_t, UINT64)> read64_delegate;
+
+
+// ======================> write_delegate
+
+// declare delegates for each width
+typedef delegate<void (address_space &, offs_t, UINT8, UINT8)> write8_delegate;
+typedef delegate<void (address_space &, offs_t, UINT16, UINT16)> write16_delegate;
+typedef delegate<void (address_space &, offs_t, UINT32, UINT32)> write32_delegate;
+typedef delegate<void (address_space &, offs_t, UINT64, UINT64)> write64_delegate;
+
+
+// ======================> direct_read_data
+
+// direct_read_data contains state data for direct read access
+class direct_read_data
+{
+ friend class address_table;
+
+public:
+ // direct_range is an internal class that is part of a list of start/end ranges
+ class direct_range
+ {
+ public:
+ // construction
+ direct_range()
+ : m_next(NULL),
+ m_bytestart(0),
+ m_byteend(~0) { }
+
+ // getters
+ direct_range *next() const { return m_next; }
+
+ // internal state
+ direct_range * m_next; // pointer to the next range in the list
+ offs_t m_bytestart; // starting byte offset of the range
+ offs_t m_byteend; // ending byte offset of the range
+ };
+
+ // construction/destruction
+ direct_read_data(address_space &space);
+ ~direct_read_data();
+
+ // getters
+ address_space &space() const { return m_space; }
+ UINT8 *raw() const { return m_raw; }
+ UINT8 *decrypted() const { return m_decrypted; }
+
+ // see if an address is within bounds, or attempt to update it if not
+ bool address_is_valid(offs_t byteaddress) { return EXPECTED(byteaddress >= m_bytestart && byteaddress <= m_byteend) || set_direct_region(byteaddress); }
+
+ // force a recomputation on the next read
+ void force_update() { m_byteend = 0; m_bytestart = 1; }
+ void force_update(UINT8 if_match) { if (m_entry == if_match) force_update(); }
+
+ // custom update callbacks and configuration
+ direct_update_delegate set_direct_update(direct_update_delegate function);
+ void explicit_configure(offs_t bytestart, offs_t byteend, offs_t bytemask, void *raw, void *decrypted = NULL);
+
+ // accessor methods for reading raw data
+ void *read_raw_ptr(offs_t byteaddress, offs_t directxor = 0);
+ UINT8 read_raw_byte(offs_t byteaddress, offs_t directxor = 0);
+ UINT16 read_raw_word(offs_t byteaddress, offs_t directxor = 0);
+ UINT32 read_raw_dword(offs_t byteaddress, offs_t directxor = 0);
+ UINT64 read_raw_qword(offs_t byteaddress, offs_t directxor = 0);
+
+ // accessor methods for reading decrypted data
+ void *read_decrypted_ptr(offs_t byteaddress, offs_t directxor = 0);
+ UINT8 read_decrypted_byte(offs_t byteaddress, offs_t directxor = 0);
+ UINT16 read_decrypted_word(offs_t byteaddress, offs_t directxor = 0);
+ UINT32 read_decrypted_dword(offs_t byteaddress, offs_t directxor = 0);
+ UINT64 read_decrypted_qword(offs_t byteaddress, offs_t directxor = 0);
+
+private:
+ // internal helpers
+ bool set_direct_region(offs_t &byteaddress);
+ direct_range *find_range(offs_t byteaddress, UINT8 &entry);
+ void remove_intersecting_ranges(offs_t bytestart, offs_t byteend);
+
+ // internal state
+ address_space & m_space;
+ UINT8 * m_raw; // direct access data pointer (raw)
+ UINT8 * m_decrypted; // direct access data pointer (decrypted)
+ offs_t m_bytemask; // byte address mask
+ offs_t m_bytestart; // minimum valid byte address
+ offs_t m_byteend; // maximum valid byte address
+ UINT8 m_entry; // live entry
+ simple_list<direct_range> m_rangelist[256]; // list of ranges for each entry
+ simple_list<direct_range> m_freerangelist; // list of recycled range entries
+ direct_update_delegate m_directupdate; // fast direct-access update callback
+};
+
+
+// ======================> address_space_config
+
+// describes an address space and provides basic functions to map addresses to bytes
+class address_space_config
+{
+public:
+ // construction/destruction
+ address_space_config();
+ address_space_config(const char *name, endianness_t endian, UINT8 datawidth, UINT8 addrwidth, INT8 addrshift = 0, address_map_constructor internal = NULL, address_map_constructor defmap = NULL);
+ address_space_config(const char *name, endianness_t endian, UINT8 datawidth, UINT8 addrwidth, INT8 addrshift, UINT8 logwidth, UINT8 pageshift, address_map_constructor internal = NULL, address_map_constructor defmap = NULL);
+
+ // getters
+ const char *name() const { return m_name; }
+ endianness_t endianness() const { return m_endianness; }
+ int data_width() const { return m_databus_width; }
+ int addr_width() const { return m_addrbus_width; }
+
+ // address-to-byte conversion helpers
+ inline offs_t addr2byte(offs_t address) const { return (m_addrbus_shift < 0) ? (address << -m_addrbus_shift) : (address >> m_addrbus_shift); }
+ inline offs_t addr2byte_end(offs_t address) const { return (m_addrbus_shift < 0) ? ((address << -m_addrbus_shift) | ((1 << -m_addrbus_shift) - 1)) : (address >> m_addrbus_shift); }
+ inline offs_t byte2addr(offs_t address) const { return (m_addrbus_shift > 0) ? (address << m_addrbus_shift) : (address >> -m_addrbus_shift); }
+ inline offs_t byte2addr_end(offs_t address) const { return (m_addrbus_shift > 0) ? ((address << m_addrbus_shift) | ((1 << m_addrbus_shift) - 1)) : (address >> -m_addrbus_shift); }
+
+ // state
+ const char * m_name;
+ endianness_t m_endianness;
+ UINT8 m_databus_width;
+ UINT8 m_addrbus_width;
+ INT8 m_addrbus_shift;
+ UINT8 m_logaddr_width;
+ UINT8 m_page_shift;
+ address_map_constructor m_internal_map;
+ address_map_constructor m_default_map;
+};
+
+
+// ======================> address_space
+
+// address_space holds live information about an address space
+class address_space
+{
+ friend class address_table;
+ friend class address_table_read;
+ friend class address_table_write;
+ friend class direct_read_data;
+ friend class simple_list<address_space>;
+ friend resource_pool_object<address_space>::~resource_pool_object();
+
+protected:
+ // construction/destruction
+ address_space(device_memory_interface &memory, address_spacenum spacenum, bool large);
+ virtual ~address_space();
+
+public:
+ // public allocator
+ static address_space &allocate(running_machine &machine, const address_space_config &config, device_memory_interface &memory, address_spacenum spacenum);
+
+ // getters
+ address_space *next() const { return m_next; }
+ device_t &device() const { return m_device; }
+ running_machine &machine() const { return m_machine; }
+ const char *name() const { return m_name; }
+ address_spacenum spacenum() const { return m_spacenum; }
+ address_map *map() const { return m_map; }
+
+ direct_read_data &direct() const { return m_direct; }
+
+ int data_width() const { return m_config.data_width(); }
+ int addr_width() const { return m_config.addr_width(); }
+ endianness_t endianness() const { return m_config.endianness(); }
+ UINT64 unmap() const { return m_unmap; }
+
+ offs_t addrmask() const { return m_addrmask; }
+ offs_t bytemask() const { return m_bytemask; }
+ UINT8 addrchars() const { return m_addrchars; }
+ offs_t logaddrmask() const { return m_logaddrmask; }
+ offs_t logbytemask() const { return m_logbytemask; }
+ UINT8 logaddrchars() const { return m_logaddrchars; }
+
+ // debug helpers
+ const char *get_handler_string(read_or_write readorwrite, offs_t byteaddress);
+ bool debugger_access() const { return m_debugger_access; }
+ void set_debugger_access(bool debugger) { m_debugger_access = debugger; }
+ bool log_unmap() const { return m_log_unmap; }
+ void set_log_unmap(bool log) { m_log_unmap = log; }
+ void dump_map(FILE *file, read_or_write readorwrite);
+
+ // watchpoint enablers
+ virtual void enable_read_watchpoints(bool enable = true) = 0;
+ virtual void enable_write_watchpoints(bool enable = true) = 0;
+
+ // general accessors
+ virtual void accessors(data_accessors &accessors) const = 0;
+ virtual void *get_read_ptr(offs_t byteaddress) = 0;
+ virtual void *get_write_ptr(offs_t byteaddress) = 0;
+
+ // read accessors
+ virtual UINT8 read_byte(offs_t byteaddress) = 0;
+ virtual UINT16 read_word(offs_t byteaddress) = 0;
+ virtual UINT16 read_word(offs_t byteaddress, UINT16 mask) = 0;
+ virtual UINT16 read_word_unaligned(offs_t byteaddress) = 0;
+ virtual UINT16 read_word_unaligned(offs_t byteaddress, UINT16 mask) = 0;
+ virtual UINT32 read_dword(offs_t byteaddress) = 0;
+ virtual UINT32 read_dword(offs_t byteaddress, UINT32 mask) = 0;
+ virtual UINT32 read_dword_unaligned(offs_t byteaddress) = 0;
+ virtual UINT32 read_dword_unaligned(offs_t byteaddress, UINT32 mask) = 0;
+ virtual UINT64 read_qword(offs_t byteaddress) = 0;
+ virtual UINT64 read_qword(offs_t byteaddress, UINT64 mask) = 0;
+ virtual UINT64 read_qword_unaligned(offs_t byteaddress) = 0;
+ virtual UINT64 read_qword_unaligned(offs_t byteaddress, UINT64 mask) = 0;
+
+ // write accessors
+ virtual void write_byte(offs_t byteaddress, UINT8 data) = 0;
+ virtual void write_word(offs_t byteaddress, UINT16 data) = 0;
+ virtual void write_word(offs_t byteaddress, UINT16 data, UINT16 mask) = 0;
+ virtual void write_word_unaligned(offs_t byteaddress, UINT16 data) = 0;
+ virtual void write_word_unaligned(offs_t byteaddress, UINT16 data, UINT16 mask) = 0;
+ virtual void write_dword(offs_t byteaddress, UINT32 data) = 0;
+ virtual void write_dword(offs_t byteaddress, UINT32 data, UINT32 mask) = 0;
+ virtual void write_dword_unaligned(offs_t byteaddress, UINT32 data) = 0;
+ virtual void write_dword_unaligned(offs_t byteaddress, UINT32 data, UINT32 mask) = 0;
+ virtual void write_qword(offs_t byteaddress, UINT64 data) = 0;
+ virtual void write_qword(offs_t byteaddress, UINT64 data, UINT64 mask) = 0;
+ virtual void write_qword_unaligned(offs_t byteaddress, UINT64 data) = 0;
+ virtual void write_qword_unaligned(offs_t byteaddress, UINT64 data, UINT64 mask) = 0;
+
+ // address-to-byte conversion helpers
+ offs_t address_to_byte(offs_t address) const { return m_config.addr2byte(address); }
+ offs_t address_to_byte_end(offs_t address) const { return m_config.addr2byte_end(address); }
+ offs_t byte_to_address(offs_t address) const { return m_config.byte2addr(address); }
+ offs_t byte_to_address_end(offs_t address) const { return m_config.byte2addr_end(address); }
+
+ // decryption
+ void set_decrypted_region(offs_t addrstart, offs_t addrend, void *base);
+
+ // direct access
+ direct_update_delegate set_direct_update_handler(direct_update_delegate function) { return m_direct.set_direct_update(function); }
+ bool set_direct_region(offs_t &byteaddress);
+
+ // umap ranges (short form)
+ void unmap_read(offs_t addrstart, offs_t addrend) { unmap_read(addrstart, addrend, 0, 0); }
+ void unmap_write(offs_t addrstart, offs_t addrend) { unmap_write(addrstart, addrend, 0, 0); }
+ void unmap_readwrite(offs_t addrstart, offs_t addrend) { unmap_readwrite(addrstart, addrend, 0, 0); }
+ void nop_read(offs_t addrstart, offs_t addrend) { nop_read(addrstart, addrend, 0, 0); }
+ void nop_write(offs_t addrstart, offs_t addrend) { nop_write(addrstart, addrend, 0, 0); }
+ void nop_readwrite(offs_t addrstart, offs_t addrend) { nop_readwrite(addrstart, addrend, 0, 0); }
+
+ // umap ranges (with mirror/mask)
+ void unmap_read(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror) { unmap_generic(addrstart, addrend, addrmask, addrmirror, ROW_READ, false); }
+ void unmap_write(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror) { unmap_generic(addrstart, addrend, addrmask, addrmirror, ROW_WRITE, false); }
+ void unmap_readwrite(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror) { unmap_generic(addrstart, addrend, addrmask, addrmirror, ROW_READWRITE, false); }
+ void nop_read(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror) { unmap_generic(addrstart, addrend, addrmask, addrmirror, ROW_READ, true); }
+ void nop_write(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror) { unmap_generic(addrstart, addrend, addrmask, addrmirror, ROW_WRITE, true); }
+ void nop_readwrite(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror) { unmap_generic(addrstart, addrend, addrmask, addrmirror, ROW_READWRITE, true); }
+
+ // install ports, banks, RAM (short form)
+ void install_read_port(offs_t addrstart, offs_t addrend, const char *rtag) { install_read_port(addrstart, addrend, 0, 0, rtag); }
+ void install_write_port(offs_t addrstart, offs_t addrend, const char *wtag) { install_write_port(addrstart, addrend, 0, 0, wtag); }
+ void install_readwrite_port(offs_t addrstart, offs_t addrend, const char *rtag, const char *wtag) { install_readwrite_port(addrstart, addrend, 0, 0, rtag, wtag); }
+ void install_read_bank(offs_t addrstart, offs_t addrend, const char *tag) { install_read_bank(addrstart, addrend, 0, 0, tag); }
+ void install_write_bank(offs_t addrstart, offs_t addrend, const char *tag) { install_write_bank(addrstart, addrend, 0, 0, tag); }
+ void install_readwrite_bank(offs_t addrstart, offs_t addrend, const char *tag) { install_readwrite_bank(addrstart, addrend, 0, 0, tag); }
+ void *install_rom(offs_t addrstart, offs_t addrend, void *baseptr = NULL) { return install_rom(addrstart, addrend, 0, 0, baseptr); }
+ void *install_writeonly(offs_t addrstart, offs_t addrend, void *baseptr = NULL) { return install_writeonly(addrstart, addrend, 0, 0, baseptr); }
+ void *install_ram(offs_t addrstart, offs_t addrend, void *baseptr = NULL) { return install_ram(addrstart, addrend, 0, 0, baseptr); }
+
+ // install ports, banks, RAM (with mirror/mask)
+ void install_read_port(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, const char *rtag) { install_readwrite_port(addrstart, addrend, addrmask, addrmirror, rtag, NULL); }
+ void install_write_port(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, const char *wtag) { install_readwrite_port(addrstart, addrend, addrmask, addrmirror, NULL, wtag); }
+ void install_readwrite_port(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, const char *rtag, const char *wtag);
+ void install_read_bank(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, const char *tag) { install_bank_generic(addrstart, addrend, addrmask, addrmirror, tag, NULL); }
+ void install_write_bank(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, const char *tag) { install_bank_generic(addrstart, addrend, addrmask, addrmirror, NULL, tag); }
+ void install_readwrite_bank(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, const char *tag) { install_bank_generic(addrstart, addrend, addrmask, addrmirror, tag, tag); }
+ void *install_rom(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, void *baseptr = NULL) { return install_ram_generic(addrstart, addrend, addrmask, addrmirror, ROW_READ, baseptr); }
+ void *install_writeonly(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, void *baseptr = NULL) { return install_ram_generic(addrstart, addrend, addrmask, addrmirror, ROW_WRITE, baseptr); }
+ void *install_ram(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, void *baseptr = NULL) { return install_ram_generic(addrstart, addrend, addrmask, addrmirror, ROW_READWRITE, baseptr); }
+
+ // install new-style delegate handlers (short form)
+ UINT8 *install_read_handler(offs_t addrstart, offs_t addrend, read8_delegate rhandler, UINT64 unitmask = 0) { return install_read_handler(addrstart, addrend, 0, 0, rhandler, unitmask); }
+ UINT8 *install_write_handler(offs_t addrstart, offs_t addrend, write8_delegate whandler, UINT64 unitmask = 0) { return install_write_handler(addrstart, addrend, 0, 0, whandler, unitmask); }
+ UINT8 *install_readwrite_handler(offs_t addrstart, offs_t addrend, read8_delegate rhandler, write8_delegate whandler, UINT64 unitmask = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, rhandler, whandler, unitmask); }
+ UINT16 *install_read_handler(offs_t addrstart, offs_t addrend, read16_delegate rhandler, UINT64 unitmask = 0) { return install_read_handler(addrstart, addrend, 0, 0, rhandler, unitmask); }
+ UINT16 *install_write_handler(offs_t addrstart, offs_t addrend, write16_delegate whandler, UINT64 unitmask = 0) { return install_write_handler(addrstart, addrend, 0, 0, whandler, unitmask); }
+ UINT16 *install_readwrite_handler(offs_t addrstart, offs_t addrend, read16_delegate rhandler, write16_delegate whandler, UINT64 unitmask = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, rhandler, whandler, unitmask); }
+ UINT32 *install_read_handler(offs_t addrstart, offs_t addrend, read32_delegate rhandler, UINT64 unitmask = 0) { return install_read_handler(addrstart, addrend, 0, 0, rhandler, unitmask); }
+ UINT32 *install_write_handler(offs_t addrstart, offs_t addrend, write32_delegate whandler, UINT64 unitmask = 0) { return install_write_handler(addrstart, addrend, 0, 0, whandler, unitmask); }
+ UINT32 *install_readwrite_handler(offs_t addrstart, offs_t addrend, read32_delegate rhandler, write32_delegate whandler, UINT64 unitmask = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, rhandler, whandler, unitmask); }
+ UINT64 *install_read_handler(offs_t addrstart, offs_t addrend, read64_delegate rhandler, UINT64 unitmask = 0) { return install_read_handler(addrstart, addrend, 0, 0, rhandler, unitmask); }
+ UINT64 *install_write_handler(offs_t addrstart, offs_t addrend, write64_delegate whandler, UINT64 unitmask = 0) { return install_write_handler(addrstart, addrend, 0, 0, whandler, unitmask); }
+ UINT64 *install_readwrite_handler(offs_t addrstart, offs_t addrend, read64_delegate rhandler, write64_delegate whandler, UINT64 unitmask = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, rhandler, whandler, unitmask); }
+
+ // install new-style delegate handlers (with mirror/mask)
+ UINT8 *install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_delegate rhandler, UINT64 unitmask = 0);
+ UINT8 *install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write8_delegate whandler, UINT64 unitmask = 0);
+ UINT8 *install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_delegate rhandler, write8_delegate whandler, UINT64 unitmask = 0);
+ UINT16 *install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_delegate rhandler, UINT64 unitmask = 0);
+ UINT16 *install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write16_delegate whandler, UINT64 unitmask = 0);
+ UINT16 *install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_delegate rhandler, write16_delegate whandler, UINT64 unitmask = 0);
+ UINT32 *install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_delegate rhandler, UINT64 unitmask = 0);
+ UINT32 *install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write32_delegate whandler, UINT64 unitmask = 0);
+ UINT32 *install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_delegate rhandler, write32_delegate whandler, UINT64 unitmask = 0);
+ UINT64 *install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_delegate rhandler, UINT64 unitmask = 0);
+ UINT64 *install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write64_delegate whandler, UINT64 unitmask = 0);
+ UINT64 *install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_delegate rhandler, write64_delegate whandler, UINT64 unitmask = 0);
+
+ // install legacy address space handlers (short form)
+ UINT8 *install_legacy_read_handler(offs_t addrstart, offs_t addrend, read8_space_func rhandler, const char *rname, UINT64 unitmask = 0) { return install_legacy_read_handler(addrstart, addrend, 0, 0, rhandler, rname, unitmask); }
+ UINT8 *install_legacy_write_handler(offs_t addrstart, offs_t addrend, write8_space_func whandler, const char *wname, UINT64 unitmask = 0) { return install_legacy_write_handler(addrstart, addrend, 0, 0, whandler, wname, unitmask); }
+ UINT8 *install_legacy_readwrite_handler(offs_t addrstart, offs_t addrend, read8_space_func rhandler, const char *rname, write8_space_func whandler, const char *wname, UINT64 unitmask = 0) { return install_legacy_readwrite_handler(addrstart, addrend, 0, 0, rhandler, rname, whandler, wname, unitmask); }
+ UINT16 *install_legacy_read_handler(offs_t addrstart, offs_t addrend, read16_space_func rhandler, const char *rname, UINT64 unitmask = 0) { return install_legacy_read_handler(addrstart, addrend, 0, 0, rhandler, rname, unitmask); }
+ UINT16 *install_legacy_write_handler(offs_t addrstart, offs_t addrend, write16_space_func whandler, const char *wname, UINT64 unitmask = 0) { return install_legacy_write_handler(addrstart, addrend, 0, 0, whandler, wname, unitmask); }
+ UINT16 *install_legacy_readwrite_handler(offs_t addrstart, offs_t addrend, read16_space_func rhandler, const char *rname, write16_space_func whandler, const char *wname, UINT64 unitmask = 0) { return install_legacy_readwrite_handler(addrstart, addrend, 0, 0, rhandler, rname, whandler, wname, unitmask); }
+ UINT32 *install_legacy_read_handler(offs_t addrstart, offs_t addrend, read32_space_func rhandler, const char *rname, UINT64 unitmask = 0) { return install_legacy_read_handler(addrstart, addrend, 0, 0, rhandler, rname, unitmask); }
+ UINT32 *install_legacy_write_handler(offs_t addrstart, offs_t addrend, write32_space_func whandler, const char *wname, UINT64 unitmask = 0) { return install_legacy_write_handler(addrstart, addrend, 0, 0, whandler, wname, unitmask); }
+ UINT32 *install_legacy_readwrite_handler(offs_t addrstart, offs_t addrend, read32_space_func rhandler, const char *rname, write32_space_func whandler, const char *wname, UINT64 unitmask = 0) { return install_legacy_readwrite_handler(addrstart, addrend, 0, 0, rhandler, rname, whandler, wname, unitmask); }
+ UINT64 *install_legacy_read_handler(offs_t addrstart, offs_t addrend, read64_space_func rhandler, const char *rname, UINT64 unitmask = 0) { return install_legacy_read_handler(addrstart, addrend, 0, 0, rhandler, rname, unitmask); }
+ UINT64 *install_legacy_write_handler(offs_t addrstart, offs_t addrend, write64_space_func whandler, const char *wname, UINT64 unitmask = 0) { return install_legacy_write_handler(addrstart, addrend, 0, 0, whandler, wname, unitmask); }
+ UINT64 *install_legacy_readwrite_handler(offs_t addrstart, offs_t addrend, read64_space_func rhandler, const char *rname, write64_space_func whandler, const char *wname, UINT64 unitmask = 0) { return install_legacy_readwrite_handler(addrstart, addrend, 0, 0, rhandler, rname, whandler, wname, unitmask); }
+
+ // install legacy address space handlers (with mirror/mask)
+ UINT8 *install_legacy_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_space_func rhandler, const char *rname, UINT64 unitmask = 0);
+ UINT8 *install_legacy_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write8_space_func whandler, const char *wname, UINT64 unitmask = 0);
+ UINT8 *install_legacy_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_space_func rhandler, const char *rname, write8_space_func whandler, const char *wname, UINT64 unitmask = 0);
+ UINT16 *install_legacy_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_space_func rhandler, const char *rname, UINT64 unitmask = 0);
+ UINT16 *install_legacy_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write16_space_func whandler, const char *wname, UINT64 unitmask = 0);
+ UINT16 *install_legacy_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_space_func rhandler, const char *rname, write16_space_func whandler, const char *wname, UINT64 unitmask = 0);
+ UINT32 *install_legacy_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_space_func rhandler, const char *rname, UINT64 unitmask = 0);
+ UINT32 *install_legacy_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write32_space_func whandler, const char *wname, UINT64 unitmask = 0);
+ UINT32 *install_legacy_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_space_func rhandler, const char *rname, write32_space_func whandler, const char *wname, UINT64 unitmask = 0);
+ UINT64 *install_legacy_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_space_func rhandler, const char *rname, UINT64 unitmask = 0);
+ UINT64 *install_legacy_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write64_space_func whandler, const char *wname, UINT64 unitmask = 0);
+ UINT64 *install_legacy_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_space_func rhandler, const char *rname, write64_space_func whandler, const char *wname, UINT64 unitmask = 0);
+
+ // install legacy device handlers (short form)
+ UINT8 *install_legacy_read_handler(device_t &device, offs_t addrstart, offs_t addrend, read8_device_func rhandler, const char *rname, UINT64 unitmask = 0) { return install_legacy_read_handler(device, addrstart, addrend, 0, 0, rhandler, rname, unitmask); }
+ UINT8 *install_legacy_write_handler(device_t &device, offs_t addrstart, offs_t addrend, write8_device_func whandler, const char *wname, UINT64 unitmask = 0) { return install_legacy_write_handler(device, addrstart, addrend, 0, 0, whandler, wname, unitmask); }
+ UINT8 *install_legacy_readwrite_handler(device_t &device, offs_t addrstart, offs_t addrend, read8_device_func rhandler, const char *rname, write8_device_func whandler, const char *wname, UINT64 unitmask = 0) { return install_legacy_readwrite_handler(device, addrstart, addrend, 0, 0, rhandler, rname, whandler, wname, unitmask); }
+ UINT16 *install_legacy_read_handler(device_t &device, offs_t addrstart, offs_t addrend, read16_device_func rhandler, const char *rname, UINT64 unitmask = 0) { return install_legacy_read_handler(device, addrstart, addrend, 0, 0, rhandler, rname, unitmask); }
+ UINT16 *install_legacy_write_handler(device_t &device, offs_t addrstart, offs_t addrend, write16_device_func whandler, const char *wname, UINT64 unitmask = 0) { return install_legacy_write_handler(device, addrstart, addrend, 0, 0, whandler, wname, unitmask); }
+ UINT16 *install_legacy_readwrite_handler(device_t &device, offs_t addrstart, offs_t addrend, read16_device_func rhandler, const char *rname, write16_device_func whandler, const char *wname, UINT64 unitmask = 0) { return install_legacy_readwrite_handler(device, addrstart, addrend, 0, 0, rhandler, rname, whandler, wname, unitmask); }
+ UINT32 *install_legacy_read_handler(device_t &device, offs_t addrstart, offs_t addrend, read32_device_func rhandler, const char *rname, UINT64 unitmask = 0) { return install_legacy_read_handler(device, addrstart, addrend, 0, 0, rhandler, rname, unitmask); }
+ UINT32 *install_legacy_write_handler(device_t &device, offs_t addrstart, offs_t addrend, write32_device_func whandler, const char *wname, UINT64 unitmask = 0) { return install_legacy_write_handler(device, addrstart, addrend, 0, 0, whandler, wname, unitmask); }
+ UINT32 *install_legacy_readwrite_handler(device_t &device, offs_t addrstart, offs_t addrend, read32_device_func rhandler, const char *rname, write32_device_func whandler, const char *wname, UINT64 unitmask = 0) { return install_legacy_readwrite_handler(device, addrstart, addrend, 0, 0, rhandler, rname, whandler, wname, unitmask); }
+ UINT64 *install_legacy_read_handler(device_t &device, offs_t addrstart, offs_t addrend, read64_device_func rhandler, const char *rname, UINT64 unitmask = 0) { return install_legacy_read_handler(device, addrstart, addrend, 0, 0, rhandler, rname, unitmask); }
+ UINT64 *install_legacy_write_handler(device_t &device, offs_t addrstart, offs_t addrend, write64_device_func whandler, const char *wname, UINT64 unitmask = 0) { return install_legacy_write_handler(device, addrstart, addrend, 0, 0, whandler, wname, unitmask); }
+ UINT64 *install_legacy_readwrite_handler(device_t &device, offs_t addrstart, offs_t addrend, read64_device_func rhandler, const char *rname, write64_device_func whandler, const char *wname, UINT64 unitmask = 0) { return install_legacy_readwrite_handler(device, addrstart, addrend, 0, 0, rhandler, rname, whandler, wname, unitmask); }
+
+ // install legacy device handlers (with mirror/mask)
+ UINT8 *install_legacy_read_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_device_func rhandler, const char *rname, UINT64 unitmask = 0);
+ UINT8 *install_legacy_write_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write8_device_func whandler, const char *wname, UINT64 unitmask = 0);
+ UINT8 *install_legacy_readwrite_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_device_func rhandler, const char *rname, write8_device_func whandler, const char *wname, UINT64 unitmask = 0);
+ UINT16 *install_legacy_read_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_device_func rhandler, const char *rname, UINT64 unitmask = 0);
+ UINT16 *install_legacy_write_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write16_device_func whandler, const char *wname, UINT64 unitmask = 0);
+ UINT16 *install_legacy_readwrite_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_device_func rhandler, const char *rname, write16_device_func whandler, const char *wname, UINT64 unitmask = 0);
+ UINT32 *install_legacy_read_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_device_func rhandler, const char *rname, UINT64 unitmask = 0);
+ UINT32 *install_legacy_write_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write32_device_func whandler, const char *wname, UINT64 unitmask = 0);
+ UINT32 *install_legacy_readwrite_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_device_func rhandler, const char *rname, write32_device_func whandler, const char *wname, UINT64 unitmask = 0);
+ UINT64 *install_legacy_read_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_device_func rhandler, const char *rname, UINT64 unitmask = 0);
+ UINT64 *install_legacy_write_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write64_device_func whandler, const char *wname, UINT64 unitmask = 0);
+ UINT64 *install_legacy_readwrite_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_device_func rhandler, const char *rname, write64_device_func whandler, const char *wname, UINT64 unitmask = 0);
+
+ // setup
+ void prepare_map();
+ void populate_from_map();
+ void allocate_memory();
+ void locate_memory();
+
+private:
+ // internal helpers
+ virtual address_table_read &read() = 0;
+ virtual address_table_write &write() = 0;
+ void populate_map_entry(const address_map_entry &entry, read_or_write readorwrite);
+ void unmap_generic(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read_or_write readorwrite, bool quiet);
+ void *install_ram_generic(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read_or_write readorwrite, void *baseptr);
+ void install_bank_generic(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, const char *rtag, const char *wtag);
+ void bind_and_install_handler(const address_map_entry &entry, read_or_write readorwrite, device_t *device);
+ void adjust_addresses(offs_t &start, offs_t &end, offs_t &mask, offs_t &mirror);
+ void *find_backing_memory(offs_t addrstart, offs_t addrend);
+ bool needs_backing_store(const address_map_entry *entry);
+ memory_bank &bank_find_or_allocate(const char *tag, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read_or_write readorwrite);
+ address_map_entry *block_assign_intersecting(offs_t bytestart, offs_t byteend, UINT8 *base);
+
+protected:
+ // private state
+ address_space * m_next; // next address space in the global list
+ const address_space_config &m_config; // configuration of this space
+ device_t & m_device; // reference to the owning device
+ address_map * m_map; // original memory map
+ offs_t m_addrmask; // physical address mask
+ offs_t m_bytemask; // byte-converted physical address mask
+ offs_t m_logaddrmask; // logical address mask
+ offs_t m_logbytemask; // byte-converted logical address mask
+ UINT64 m_unmap; // unmapped value
+ address_spacenum m_spacenum; // address space index
+ bool m_debugger_access; // treat accesses as coming from the debugger
+ bool m_log_unmap; // log unmapped accesses in this space?
+ direct_read_data & m_direct; // fast direct-access read info
+ const char * m_name; // friendly name of the address space
+ UINT8 m_addrchars; // number of characters to use for physical addresses
+ UINT8 m_logaddrchars; // number of characters to use for logical addresses
+
+private:
+ running_machine & m_machine; // reference to the owning machine
+};
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+// opcode base adjustment handler function macro
+#define DIRECT_UPDATE_MEMBER(name) offs_t name(ATTR_UNUSED direct_read_data &direct, ATTR_UNUSED offs_t address)
+#define DIRECT_UPDATE_HANDLER(name) offs_t name(ATTR_UNUSED running_machine &machine, ATTR_UNUSED direct_read_data &direct, ATTR_UNUSED offs_t address)
+
+
+// space read/write handler function macros
+#define READ8_HANDLER(name) UINT8 name(ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset)
+#define WRITE8_HANDLER(name) void name(ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT8 data)
+#define READ16_HANDLER(name) UINT16 name(ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 mem_mask)
+#define WRITE16_HANDLER(name) void name(ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 data, ATTR_UNUSED UINT16 mem_mask)
+#define READ32_HANDLER(name) UINT32 name(ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT32 mem_mask)
+#define WRITE32_HANDLER(name) void name(ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT32 data, ATTR_UNUSED UINT32 mem_mask)
+#define READ64_HANDLER(name) UINT64 name(ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 mem_mask)
+#define WRITE64_HANDLER(name) void name(ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 data, ATTR_UNUSED UINT64 mem_mask)
+
+
+// device read/write handler function macros
+#define READ8_DEVICE_HANDLER(name) UINT8 name(ATTR_UNUSED device_t *device, ATTR_UNUSED offs_t offset)
+#define WRITE8_DEVICE_HANDLER(name) void name(ATTR_UNUSED device_t *device, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT8 data)
+#define READ16_DEVICE_HANDLER(name) UINT16 name(ATTR_UNUSED device_t *device, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 mem_mask)
+#define WRITE16_DEVICE_HANDLER(name) void name(ATTR_UNUSED device_t *device, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 data, ATTR_UNUSED UINT16 mem_mask)
+#define READ32_DEVICE_HANDLER(name) UINT32 name(ATTR_UNUSED device_t *device, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT32 mem_mask)
+#define WRITE32_DEVICE_HANDLER(name) void name(ATTR_UNUSED device_t *device, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT32 data, ATTR_UNUSED UINT32 mem_mask)
+#define READ64_DEVICE_HANDLER(name) UINT64 name(ATTR_UNUSED device_t *device, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 mem_mask)
+#define WRITE64_DEVICE_HANDLER(name) void name(ATTR_UNUSED device_t *device, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 data, ATTR_UNUSED UINT64 mem_mask)
+
+
+// space read/write handler function macros
+#define READ8_MEMBER(name) UINT8 name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT8 mem_mask)
+#define WRITE8_MEMBER(name) void name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT8 data, ATTR_UNUSED UINT8 mem_mask)
+#define READ16_MEMBER(name) UINT16 name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 mem_mask)
+#define WRITE16_MEMBER(name) void name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 data, ATTR_UNUSED UINT16 mem_mask)
+#define READ32_MEMBER(name) UINT32 name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT32 mem_mask)
+#define WRITE32_MEMBER(name) void name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT32 data, ATTR_UNUSED UINT32 mem_mask)
+#define READ64_MEMBER(name) UINT64 name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 mem_mask)
+#define WRITE64_MEMBER(name) void name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 data, ATTR_UNUSED UINT64 mem_mask)
+
+#define DECLARE_READ8_MEMBER(name) UINT8 name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT8 mem_mask = 0xff)
+#define DECLARE_WRITE8_MEMBER(name) void name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT8 data, ATTR_UNUSED UINT8 mem_mask = 0xff)
+#define DECLARE_READ16_MEMBER(name) UINT16 name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 mem_mask = 0xffff)
+#define DECLARE_WRITE16_MEMBER(name) void name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 data, ATTR_UNUSED UINT16 mem_mask = 0xffff)
+#define DECLARE_READ32_MEMBER(name) UINT32 name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT32 mem_mask = 0xffffffff)
+#define DECLARE_WRITE32_MEMBER(name) void name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT32 data, ATTR_UNUSED UINT32 mem_mask = 0xffffffff)
+#define DECLARE_READ64_MEMBER(name) UINT64 name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 mem_mask = U64(0xffffffffffffffff))
+#define DECLARE_WRITE64_MEMBER(name) void name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 data, ATTR_UNUSED UINT64 mem_mask = U64(0xffffffffffffffff))
+
+
+// helper macro for merging data with the memory mask
+#define COMBINE_DATA(varptr) (*(varptr) = (*(varptr) & ~mem_mask) | (data & mem_mask))
+
+#define ACCESSING_BITS_0_7 ((mem_mask & 0x000000ff) != 0)
+#define ACCESSING_BITS_8_15 ((mem_mask & 0x0000ff00) != 0)
+#define ACCESSING_BITS_16_23 ((mem_mask & 0x00ff0000) != 0)
+#define ACCESSING_BITS_24_31 ((mem_mask & 0xff000000) != 0)
+#define ACCESSING_BITS_32_39 ((mem_mask & U64(0x000000ff00000000)) != 0)
+#define ACCESSING_BITS_40_47 ((mem_mask & U64(0x0000ff0000000000)) != 0)
+#define ACCESSING_BITS_48_55 ((mem_mask & U64(0x00ff000000000000)) != 0)
+#define ACCESSING_BITS_56_63 ((mem_mask & U64(0xff00000000000000)) != 0)
+
+#define ACCESSING_BITS_0_15 ((mem_mask & 0x0000ffff) != 0)
+#define ACCESSING_BITS_16_31 ((mem_mask & 0xffff0000) != 0)
+#define ACCESSING_BITS_32_47 ((mem_mask & U64(0x0000ffff00000000)) != 0)
+#define ACCESSING_BITS_48_63 ((mem_mask & U64(0xffff000000000000)) != 0)
+
+#define ACCESSING_BITS_0_31 ((mem_mask & 0xffffffff) != 0)
+#define ACCESSING_BITS_32_63 ((mem_mask & U64(0xffffffff00000000)) != 0)
+
+
+// macros for accessing bytes and words within larger chunks
+
+// read/write a byte to a 16-bit space
+#define BYTE_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0))
+#define BYTE_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,1))
+
+// read/write a byte to a 32-bit space
+#define BYTE4_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(3,0))
+#define BYTE4_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,3))
+
+// read/write a word to a 32-bit space
+#define WORD_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(2,0))
+#define WORD_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,2))
+
+// read/write a byte to a 64-bit space
+#define BYTE8_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(7,0))
+#define BYTE8_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,7))
+
+// read/write a word to a 64-bit space
+#define WORD2_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(6,0))
+#define WORD2_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,6))
+
+// read/write a dword to a 64-bit space
+#define DWORD_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(4,0))
+#define DWORD_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,4))
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+extern const char *const address_space_names[ADDRESS_SPACES];
+
+
+
+//**************************************************************************
+// FUNCTION PROTOTYPES FOR CORE MEMORY FUNCTIONS
+//**************************************************************************
+
+// initialize the memory system
+void memory_init(running_machine &machine);
+
+// configure the addresses for a bank
+void memory_configure_bank(running_machine &machine, const char *tag, int startentry, int numentries, void *base, offs_t stride) ATTR_NONNULL(5);
+void memory_configure_bank(device_t *device, const char *tag, int startentry, int numentries, void *base, offs_t stride) ATTR_NONNULL(5);
+
+// configure the decrypted addresses for a bank
+void memory_configure_bank_decrypted(running_machine &machine, const char *tag, int startentry, int numentries, void *base, offs_t stride) ATTR_NONNULL(5);
+void memory_configure_bank_decrypted(device_t *device, const char *tag, int startentry, int numentries, void *base, offs_t stride) ATTR_NONNULL(5);
+
+// select one pre-configured entry to be the new bank base
+void memory_set_bank(running_machine &machine, const char *tag, int entrynum);
+void memory_set_bank(device_t *device, const char *tag, int entrynum);
+
+// return the currently selected bank
+int memory_get_bank(running_machine &machine, const char *tag);
+int memory_get_bank(device_t *device, const char *tag);
+
+// set the absolute address of a bank base
+void memory_set_bankptr(running_machine &machine, const char *tag, void *base) ATTR_NONNULL(3);
+void memory_set_bankptr(device_t *device, const char *tag, void *base) ATTR_NONNULL(3);
+
+// get a pointer to a shared memory region by tag
+void *memory_get_shared(running_machine &machine, const char *tag);
+void *memory_get_shared(running_machine &machine, const char *tag, size_t &length);
+
+// dump the internal memory tables to the given file
+void memory_dump(running_machine &machine, FILE *file);
+
+address_space *memory_nonspecific_space(running_machine &machine);
+
+
+//**************************************************************************
+// INLINE FUNCTIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// read_raw_ptr - return a pointer to valid RAM
+// referenced by the address, or NULL if no RAM
+// backing that address
+//-------------------------------------------------
+
+inline void *direct_read_data::read_raw_ptr(offs_t byteaddress, offs_t directxor)
+{
+ if (address_is_valid(byteaddress))
+ return &m_raw[(byteaddress ^ directxor) & m_bytemask];
+ return NULL;
+}
+
+inline void *direct_read_data::read_decrypted_ptr(offs_t byteaddress, offs_t directxor)
+{
+ if (address_is_valid(byteaddress))
+ return &m_decrypted[(byteaddress ^ directxor) & m_bytemask];
+ return NULL;
+}
+
+
+//-------------------------------------------------
+// read_raw_byte - read a byte via the
+// direct_read_data class
+//-------------------------------------------------
+
+inline UINT8 direct_read_data::read_raw_byte(offs_t byteaddress, offs_t directxor)
+{
+ if (address_is_valid(byteaddress))
+ return m_raw[(byteaddress ^ directxor) & m_bytemask];
+ return m_space.read_byte(byteaddress);
+}
+
+inline UINT8 direct_read_data::read_decrypted_byte(offs_t byteaddress, offs_t directxor)
+{
+ if (address_is_valid(byteaddress))
+ return m_decrypted[(byteaddress ^ directxor) & m_bytemask];
+ return m_space.read_byte(byteaddress);
+}
+
+
+//-------------------------------------------------
+// read_raw_word - read a word via the
+// direct_read_data class
+//-------------------------------------------------
+
+inline UINT16 direct_read_data::read_raw_word(offs_t byteaddress, offs_t directxor)
+{
+ if (address_is_valid(byteaddress))
+ return *reinterpret_cast<UINT16 *>(&m_raw[(byteaddress ^ directxor) & m_bytemask]);
+ return m_space.read_word(byteaddress);
+}
+
+inline UINT16 direct_read_data::read_decrypted_word(offs_t byteaddress, offs_t directxor)
+{
+ if (address_is_valid(byteaddress))
+ return *reinterpret_cast<UINT16 *>(&m_decrypted[(byteaddress ^ directxor) & m_bytemask]);
+ return m_space.read_word(byteaddress);
+}
+
+
+//-------------------------------------------------
+// read_raw_dword - read a dword via the
+// direct_read_data class
+//-------------------------------------------------
+
+inline UINT32 direct_read_data::read_raw_dword(offs_t byteaddress, offs_t directxor)
+{
+ if (address_is_valid(byteaddress))
+ return *reinterpret_cast<UINT32 *>(&m_raw[(byteaddress ^ directxor) & m_bytemask]);
+ return m_space.read_dword(byteaddress);
+}
+
+inline UINT32 direct_read_data::read_decrypted_dword(offs_t byteaddress, offs_t directxor)
+{
+ if (address_is_valid(byteaddress))
+ return *reinterpret_cast<UINT32 *>(&m_decrypted[(byteaddress ^ directxor) & m_bytemask]);
+ return m_space.read_dword(byteaddress);
+}
+
+
+//-------------------------------------------------
+// read_raw_qword - read a qword via the
+// direct_read_data class
+//-------------------------------------------------
+
+inline UINT64 direct_read_data::read_raw_qword(offs_t byteaddress, offs_t directxor)
+{
+ if (address_is_valid(byteaddress))
+ return *reinterpret_cast<UINT64 *>(&m_raw[(byteaddress ^ directxor) & m_bytemask]);
+ return m_space.read_qword(byteaddress);
+}
+
+inline UINT64 direct_read_data::read_decrypted_qword(offs_t byteaddress, offs_t directxor)
+{
+ if (address_is_valid(byteaddress))
+ return *reinterpret_cast<UINT64 *>(&m_decrypted[(byteaddress ^ directxor) & m_bytemask]);
+ return m_space.read_qword(byteaddress);
+}
+
+
+#endif /* __MEMORY_H__ */
diff --git a/trunk/src/emu/output.c b/trunk/src/emu/output.c
new file mode 100644
index 00000000000..14ea5227617
--- /dev/null
+++ b/trunk/src/emu/output.c
@@ -0,0 +1,412 @@
+/***************************************************************************
+
+ output.c
+
+ General purpose output routines.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "emu.h"
+#include <zlib.h>
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define HASH_SIZE 53
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _output_notify output_notify;
+struct _output_notify
+{
+ output_notify * next; /* link to next item */
+ output_notifier_func notifier; /* callback to call */
+ void * param; /* parameter to pass the callback */
+};
+
+
+typedef struct _output_item output_item;
+struct _output_item
+{
+ output_item * next; /* next item in list */
+ const char * name; /* string name of the item */
+ UINT32 hash; /* hash for this item name */
+ UINT32 id; /* unique ID for this item */
+ INT32 value; /* current value */
+ output_notify * notifylist; /* list of notifier callbacks */
+};
+
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+static output_item *itemtable[HASH_SIZE];
+static output_notify *global_notifylist;
+static UINT32 uniqueid = 12345;
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void output_pause(running_machine &machine);
+static void output_resume(running_machine &machine);
+static void output_exit(running_machine &machine);
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ copy_string - make a copy of a string
+-------------------------------------------------*/
+
+INLINE const char *copy_string(const char *string)
+{
+ char *newstring = global_alloc_array(char, strlen(string) + 1);
+ strcpy(newstring, string);
+ return newstring;
+}
+
+
+/*-------------------------------------------------
+ get_hash - return the hash of an output value
+-------------------------------------------------*/
+
+INLINE UINT32 get_hash(const char *string)
+{
+ return crc32(0, (UINT8 *)string, (UINT32)strlen(string));
+}
+
+
+/*-------------------------------------------------
+ find_item - find an item based on a string
+-------------------------------------------------*/
+
+INLINE output_item *find_item(const char *string)
+{
+ UINT32 hash = get_hash(string);
+ output_item *item;
+
+ /* use the hash as a starting point and find an entry */
+ for (item = itemtable[hash % HASH_SIZE]; item != NULL; item = item->next)
+ if (item->hash == hash && strcmp(string, item->name) == 0)
+ return item;
+
+ return NULL;
+}
+
+
+/*-------------------------------------------------
+ create_new_item - create a new item
+-------------------------------------------------*/
+
+INLINE output_item *create_new_item(const char *outname, INT32 value)
+{
+ output_item *item = global_alloc(output_item);
+ UINT32 hash = get_hash(outname);
+
+ /* fill in the data */
+ item->next = itemtable[hash % HASH_SIZE];
+ item->name = copy_string(outname);
+ item->hash = hash;
+ item->id = uniqueid++;
+ item->value = value;
+ item->notifylist = NULL;
+
+ /* add us to the hash table */
+ itemtable[hash % HASH_SIZE] = item;
+ return item;
+}
+
+
+
+/***************************************************************************
+ CORE IMPLEMENTATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ output_init - initialize everything
+-------------------------------------------------*/
+
+void output_init(running_machine &machine)
+{
+ /* add pause callback */
+ machine.add_notifier(MACHINE_NOTIFY_PAUSE, machine_notify_delegate(FUNC(output_pause), &machine));
+ machine.add_notifier(MACHINE_NOTIFY_RESUME, machine_notify_delegate(FUNC(output_resume), &machine));
+
+ /* get a callback when done */
+ machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(output_exit), &machine));
+
+ /* reset the lists */
+ memset(itemtable, 0, sizeof(itemtable));
+ global_notifylist = NULL;
+}
+
+
+/*-------------------------------------------------
+ output_pause - send pause message
+-------------------------------------------------*/
+
+static void output_pause(running_machine &machine)
+{
+ output_set_value("pause", 1);
+}
+
+static void output_resume(running_machine &machine)
+{
+ output_set_value("pause", 0);
+}
+
+
+/*-------------------------------------------------
+ output_exit - cleanup on exit
+-------------------------------------------------*/
+
+static void output_exit(running_machine &machine)
+{
+ output_notify *notify;
+ output_item *item;
+ int hash;
+
+ /* remove all items */
+ for (hash = 0; hash < HASH_SIZE; hash++)
+ for (item = itemtable[hash]; item != NULL; )
+ {
+ output_item *next = item->next;
+
+ /* remove all notifiers */
+ for (notify = item->notifylist; notify != NULL; )
+ {
+ output_notify *next_notify = notify->next;
+ global_free(notify);
+ notify = next_notify;
+ }
+
+ /* free the name and the item */
+ if (item->name != NULL)
+ global_free(item->name);
+ global_free(item);
+ item = next;
+ }
+
+ /* remove all global notifiers */
+ for (notify = global_notifylist; notify != NULL; )
+ {
+ output_notify *next = notify->next;
+ global_free(notify);
+ notify = next;
+ }
+}
+
+
+/*-------------------------------------------------
+ output_set_value - set the value of an output
+-------------------------------------------------*/
+
+void output_set_value(const char *outname, INT32 value)
+{
+ output_item *item = find_item(outname);
+ output_notify *notify;
+ INT32 oldval;
+
+ /* if no item of that name, create a new one and send the item's state */
+ if (item == NULL)
+ {
+ item = create_new_item(outname, value);
+ oldval = value + 1;
+ }
+
+ else
+ {
+ /* set the new value */
+ oldval = item->value;
+ item->value = value;
+ }
+
+ /* if the value is different, signal the notifier */
+ if (oldval != value)
+ {
+ /* call the local notifiers first */
+ for (notify = item->notifylist; notify != NULL; notify = notify->next)
+ (*notify->notifier)(outname, value, notify->param);
+
+ /* call the global notifiers next */
+ for (notify = global_notifylist; notify != NULL; notify = notify->next)
+ (*notify->notifier)(outname, value, notify->param);
+ }
+}
+
+
+/*-------------------------------------------------
+ output_set_indexed_value - set the value of an
+ indexed output
+-------------------------------------------------*/
+
+void output_set_indexed_value(const char *basename, int index, int value)
+{
+ char buffer[100];
+ char *dest = buffer;
+
+ /* copy the string */
+ while (*basename != 0)
+ *dest++ = *basename++;
+
+ /* append the index */
+ if (index >= 1000) *dest++ = '0' + ((index / 1000) % 10);
+ if (index >= 100) *dest++ = '0' + ((index / 100) % 10);
+ if (index >= 10) *dest++ = '0' + ((index / 10) % 10);
+ *dest++ = '0' + (index % 10);
+ *dest++ = 0;
+
+ /* set the value */
+ output_set_value(buffer, value);
+}
+
+
+/*-------------------------------------------------
+ output_get_value - return the value of an
+ output
+-------------------------------------------------*/
+
+INT32 output_get_value(const char *outname)
+{
+ output_item *item = find_item(outname);
+
+ /* if no item, value is 0 */
+ if (item == NULL)
+ return 0;
+ return item->value;
+}
+
+
+/*-------------------------------------------------
+ output_get_indexed_value - get the value of an
+ indexed output
+-------------------------------------------------*/
+
+INT32 output_get_indexed_value(const char *basename, int index)
+{
+ char buffer[100];
+ char *dest = buffer;
+
+ /* copy the string */
+ while (*basename != 0)
+ *dest++ = *basename++;
+
+ /* append the index */
+ if (index >= 1000) *dest++ = '0' + ((index / 1000) % 10);
+ if (index >= 100) *dest++ = '0' + ((index / 100) % 10);
+ if (index >= 10) *dest++ = '0' + ((index / 10) % 10);
+ *dest++ = '0' + (index % 10);
+ *dest++ = 0;
+
+ /* set the value */
+ return output_get_value(buffer);
+}
+
+
+/*-------------------------------------------------
+ output_set_notifier - sets a notifier callback
+ for a particular output, or for all outputs
+ if NULL is specified
+-------------------------------------------------*/
+
+void output_set_notifier(const char *outname, output_notifier_func callback, void *param)
+{
+ output_notify **headptr;
+
+ /* if an item is specified, find it */
+ if (outname != NULL)
+ {
+ output_item *item = find_item(outname);
+
+ /* if no item of that name, create a new one */
+ if (item == NULL)
+ item = create_new_item(outname, 0);
+ headptr = &item->notifylist;
+ }
+
+ /* if no item is specified, we add to the global list */
+ else
+ headptr = &global_notifylist;
+
+ /* find the end of the list and add to it */
+ while (*headptr != NULL)
+ headptr = &(*headptr)->next;
+ *headptr = global_alloc(output_notify);
+
+ /* fill in the new record */
+ (*headptr)->next = NULL;
+ (*headptr)->notifier = callback;
+ (*headptr)->param = param;
+}
+
+
+/*-------------------------------------------------
+ output_notify_all - immediately call the given
+ notifier for all outputs
+-------------------------------------------------*/
+
+void output_notify_all(output_notifier_func callback, void *param)
+{
+ output_item *item;
+ int hash;
+
+ /* remove all items */
+ for (hash = 0; hash < HASH_SIZE; hash++)
+ for (item = itemtable[hash]; item != NULL; item = item->next)
+ (*callback)(item->name, item->value, param);
+}
+
+
+/*-------------------------------------------------
+ output_name_to_id - returns a unique ID for
+ a given name
+-------------------------------------------------*/
+
+UINT32 output_name_to_id(const char *outname)
+{
+ output_item *item = find_item(outname);
+
+ /* if no item, ID is 0 */
+ if (item == NULL)
+ return 0;
+ return item->id;
+}
+
+
+/*-------------------------------------------------
+ output_id_to_name - returns a name that maps
+ to a given unique ID
+-------------------------------------------------*/
+
+const char *output_id_to_name(UINT32 id)
+{
+ output_item *item;
+ int hash;
+
+ /* remove all items */
+ for (hash = 0; hash < HASH_SIZE; hash++)
+ for (item = itemtable[hash]; item != NULL; item = item->next)
+ if (item->id == id)
+ return item->name;
+
+ /* nothing found, return NULL */
+ return NULL;
+}
diff --git a/trunk/src/emu/output.h b/trunk/src/emu/output.h
new file mode 100644
index 00000000000..46b74ea5a92
--- /dev/null
+++ b/trunk/src/emu/output.h
@@ -0,0 +1,99 @@
+/***************************************************************************
+
+ output.h
+
+ General purpose output routines.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __EMU_H__
+#error Dont include this file directly; include emu.h instead.
+#endif
+
+#ifndef __OUTPUT_H__
+#define __OUTPUT_H__
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef void (*output_notifier_func)(const char *outname, INT32 value, void *param);
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+/* core initialization */
+void output_init(running_machine &machine);
+
+/* set the value for a given output */
+void output_set_value(const char *outname, INT32 value);
+
+/* set an indexed value for an output (concatenates basename + index) */
+void output_set_indexed_value(const char *basename, int index, int value);
+
+/* return the current value for a given output */
+INT32 output_get_value(const char *outname);
+
+/* return the current value for a given indexed output */
+INT32 output_get_indexed_value(const char *outname, int index);
+
+/* set a notifier on a particular output, or globally if NULL */
+void output_set_notifier(const char *outname, output_notifier_func callback, void *param);
+
+/* set a notifier on a particular output, or globally if NULL */
+void output_notify_all(output_notifier_func callback, void *param);
+
+/* map a name to a unique ID */
+UINT32 output_name_to_id(const char *outname);
+
+/* map a unique ID back to a name */
+const char *output_id_to_name(UINT32 id);
+
+
+
+/***************************************************************************
+ INLINES
+***************************************************************************/
+
+INLINE void output_set_led_value(int index, int value)
+{
+ output_set_indexed_value("led", index, value ? 1 : 0);
+}
+
+INLINE void output_set_lamp_value(int index, int value)
+{
+ output_set_indexed_value("lamp", index, value);
+}
+
+INLINE void output_set_digit_value(int index, int value)
+{
+ output_set_indexed_value("digit", index, value);
+}
+
+
+INLINE INT32 output_get_led_value(int index)
+{
+ return output_get_indexed_value("led", index);
+}
+
+INLINE INT32 output_get_lamp_value(int index)
+{
+ return output_get_indexed_value("lamp", index);
+}
+
+INLINE INT32 output_get_digit_value(int index)
+{
+ return output_get_indexed_value("digit", index);
+}
+
+
+#endif /* __OUTPUT_H__ */
diff --git a/trunk/src/emu/profiler.c b/trunk/src/emu/profiler.c
new file mode 100644
index 00000000000..c4c6e49a4e1
--- /dev/null
+++ b/trunk/src/emu/profiler.c
@@ -0,0 +1,288 @@
+/***************************************************************************
+
+ profiler.c
+
+ Functions to manage profiling of MAME execution.
+
+****************************************************************************
+
+ 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.
+
+****************************************************************************
+
+ Profiling is scope-based. To start profiling, put a profiler_scope
+ object on the stack. To end profiling, just end the scope:
+
+ {
+ profiler_scope scope(PROFILER_VIDEO);
+
+ your_work_here();
+ }
+
+ the profiler handles a FILO list so calls may be nested.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "profiler.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+struct profile_string
+{
+ int type;
+ const char *string;
+};
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+profiler_state g_profiler;
+
+
+
+//**************************************************************************
+// DUMMY PROFILER STATE
+//**************************************************************************
+
+//-------------------------------------------------
+// dummy_profiler_state - constructor
+//-------------------------------------------------
+
+dummy_profiler_state::dummy_profiler_state()
+{
+}
+
+
+
+//**************************************************************************
+// REAL PROFILER STATE
+//**************************************************************************
+
+//-------------------------------------------------
+// real_profiler_state - constructor
+//-------------------------------------------------
+
+real_profiler_state::real_profiler_state()
+ : m_enabled(false),
+ m_dataready(false),
+ m_filoindex(0),
+ m_dataindex(0)
+{
+ memset(m_filo, 0, sizeof(m_filo));
+ memset(m_data, 0, sizeof(m_data));
+}
+
+
+//-------------------------------------------------
+// real_start - mark the beginning of a
+// profiler entry
+//-------------------------------------------------
+
+void real_profiler_state::real_start(profile_type type)
+{
+ osd_ticks_t curticks = get_profile_ticks();
+
+ // track context switches
+ history_data &data = m_data[m_dataindex];
+ if (type >= PROFILER_DEVICE_FIRST && type <= PROFILER_DEVICE_MAX)
+ data.context_switches++;
+
+ // we're starting a new bucket, begin now
+ int index = m_filoindex++;
+ filo_entry &entry = m_filo[index];
+
+ // fail if we overflow
+ if (index > ARRAY_LENGTH(m_filo))
+ throw emu_fatalerror("Profiler FILO overflow (type = %d)\n", type);
+
+ // if we're nested, stop the previous entry
+ if (index > 0)
+ {
+ filo_entry &preventry = m_filo[index - 1];
+ data.duration[preventry.type] += curticks - preventry.start;
+ }
+
+ // fill in this entry
+ entry.type = type;
+ entry.start = curticks;
+}
+
+
+//-------------------------------------------------
+// real_stop - mark the end of a profiler entry
+//-------------------------------------------------
+
+void real_profiler_state::real_stop()
+{
+ osd_ticks_t curticks = get_profile_ticks();
+
+ // we're ending an existing bucket, update the time
+ if (m_filoindex > 0)
+ {
+ int index = --m_filoindex;
+ filo_entry &entry = m_filo[index];
+
+ // account for the time taken
+ history_data &data = m_data[m_dataindex];
+ data.duration[entry.type] += curticks - entry.start;
+
+ // if we have a previous entry, restart his time now
+ if (index != 0)
+ {
+ filo_entry &preventry = m_filo[index - 1];
+ preventry.start = curticks;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// text - return the current text in an astring
+//-------------------------------------------------
+
+const char *real_profiler_state::text(running_machine &machine, astring &string)
+{
+ static const profile_string names[] =
+ {
+ { PROFILER_DRC_COMPILE, "DRC Compilation" },
+ { PROFILER_MEM_REMAP, "Memory Remapping" },
+ { PROFILER_MEMREAD, "Memory Read" },
+ { PROFILER_MEMWRITE, "Memory Write" },
+ { PROFILER_VIDEO, "Video Update" },
+ { PROFILER_DRAWGFX, "drawgfx" },
+ { PROFILER_COPYBITMAP, "copybitmap" },
+ { PROFILER_TILEMAP_DRAW, "Tilemap Draw" },
+ { PROFILER_TILEMAP_DRAW_ROZ, "Tilemap ROZ Draw" },
+ { PROFILER_TILEMAP_UPDATE, "Tilemap Update" },
+ { PROFILER_BLIT, "OSD Blitting" },
+ { PROFILER_SOUND, "Sound Generation" },
+ { PROFILER_TIMER_CALLBACK, "Timer Callbacks" },
+ { PROFILER_INPUT, "Input Processing" },
+ { PROFILER_MOVIE_REC, "Movie Recording" },
+ { PROFILER_LOGERROR, "Error Logging" },
+ { PROFILER_EXTRA, "Unaccounted/Overhead" },
+ { PROFILER_USER1, "User 1" },
+ { PROFILER_USER2, "User 2" },
+ { PROFILER_USER3, "User 3" },
+ { PROFILER_USER4, "User 4" },
+ { PROFILER_USER5, "User 5" },
+ { PROFILER_USER6, "User 6" },
+ { PROFILER_USER7, "User 7" },
+ { PROFILER_USER8, "User 8" },
+ { PROFILER_PROFILER, "Profiler" },
+ { PROFILER_IDLE, "Idle" }
+ };
+
+ g_profiler.start(PROFILER_PROFILER);
+
+ // compute the total time for all bits, not including profiler or idle
+ UINT64 computed = 0;
+ profile_type curtype;
+ for (curtype = PROFILER_DEVICE_FIRST; curtype < PROFILER_PROFILER; curtype++)
+ for (int curmem = 0; curmem < ARRAY_LENGTH(m_data); curmem++)
+ computed += m_data[curmem].duration[curtype];
+
+ // save that result in normalize, and continue adding the rest
+ UINT64 normalize = computed;
+ for ( ; curtype < PROFILER_TOTAL; curtype++)
+ for (int curmem = 0; curmem < ARRAY_LENGTH(m_data); curmem++)
+ computed += m_data[curmem].duration[curtype];
+
+ // this becomes the total; if we end up with 0 for anything, we were just started, so return empty
+ UINT64 total = computed;
+ string.reset();
+ if (total == 0 || normalize == 0)
+ {
+ g_profiler.stop();
+ return string;
+ }
+
+ // loop over all types and generate the string
+ for (curtype = PROFILER_DEVICE_FIRST; curtype < PROFILER_TOTAL; curtype++)
+ {
+ // determine the accumulated time for this type
+ computed = 0;
+ for (int curmem = 0; curmem < ARRAY_LENGTH(m_data); curmem++)
+ computed += m_data[curmem].duration[curtype];
+
+ // if we have non-zero data and we're ready to display, do it
+ if (m_dataready && computed != 0)
+ {
+ // start with the un-normalized percentage
+ string.catprintf("%02d%% ", (int)((computed * 100 + total/2) / total));
+
+ // followed by the normalized percentage for everything but profiler and idle
+ if (curtype < PROFILER_PROFILER)
+ string.catprintf("%02d%% ", (int)((computed * 100 + normalize/2) / normalize));
+
+ // and then the text
+ if (curtype >= PROFILER_DEVICE_FIRST && curtype <= PROFILER_DEVICE_MAX)
+ string.catprintf("'%s'", machine.devicelist().find(curtype - PROFILER_DEVICE_FIRST)->tag());
+ else
+ for (int nameindex = 0; nameindex < ARRAY_LENGTH(names); nameindex++)
+ if (names[nameindex].type == curtype)
+ {
+ string.cat(names[nameindex].string);
+ break;
+ }
+
+ // followed by a carriage return
+ string.cat("\n");
+ }
+ }
+
+ // followed by context switches
+ if (m_dataready)
+ {
+ int switches = 0;
+ for (int curmem = 0; curmem < ARRAY_LENGTH(m_data); curmem++)
+ switches += m_data[curmem].context_switches;
+ string.catprintf("%d CPU switches\n", switches / (int) ARRAY_LENGTH(m_data));
+ }
+
+ // advance to the next dataset and reset it to 0
+ m_dataindex = (m_dataindex + 1) % ARRAY_LENGTH(m_data);
+ memset(&m_data[m_dataindex], 0, sizeof(m_data[m_dataindex]));
+
+ // we are ready once we have wrapped around
+ if (m_dataindex == 0)
+ m_dataready = true;
+
+ g_profiler.stop();
+ return string;
+}
diff --git a/trunk/src/emu/profiler.h b/trunk/src/emu/profiler.h
new file mode 100644
index 00000000000..29301b8662a
--- /dev/null
+++ b/trunk/src/emu/profiler.h
@@ -0,0 +1,208 @@
+/***************************************************************************
+
+ profiler.h
+
+ Functions to manage profiling of MAME execution.
+
+****************************************************************************
+
+ 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.
+
+****************************************************************************
+
+ Profiling is scope-based. To start profiling, put a profiler_scope
+ object on the stack. To end profiling, just end the scope:
+
+ {
+ profiler_scope scope(PROFILER_VIDEO);
+
+ your_work_here();
+ }
+
+ the profiler handles a FILO list so calls may be nested.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __PROFILER_H__
+#define __PROFILER_H__
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+enum profile_type
+{
+ PROFILER_DEVICE_FIRST = 0,
+ PROFILER_DEVICE_MAX = PROFILER_DEVICE_FIRST + 256,
+ PROFILER_DRC_COMPILE,
+ PROFILER_MEM_REMAP,
+ PROFILER_MEMREAD,
+ PROFILER_MEMWRITE,
+ PROFILER_VIDEO,
+ PROFILER_DRAWGFX,
+ PROFILER_COPYBITMAP,
+ PROFILER_TILEMAP_DRAW,
+ PROFILER_TILEMAP_DRAW_ROZ,
+ PROFILER_TILEMAP_UPDATE,
+ PROFILER_BLIT,
+ PROFILER_SOUND,
+ PROFILER_TIMER_CALLBACK,
+ PROFILER_INPUT, // input.c and inptport.c
+ PROFILER_MOVIE_REC, // movie recording
+ PROFILER_LOGERROR, // logerror
+ PROFILER_EXTRA, // everything else
+
+ // the USER types are available to driver writers to profile
+ // custom sections of the code
+ PROFILER_USER1,
+ PROFILER_USER2,
+ PROFILER_USER3,
+ PROFILER_USER4,
+ PROFILER_USER5,
+ PROFILER_USER6,
+ PROFILER_USER7,
+ PROFILER_USER8,
+
+ PROFILER_PROFILER,
+ PROFILER_IDLE,
+ PROFILER_TOTAL
+};
+DECLARE_ENUM_OPERATORS(profile_type);
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> real_profiler_state
+
+class real_profiler_state
+{
+ friend class profile_scope;
+
+public:
+ // construction/destruction
+ real_profiler_state();
+
+ // getters
+ bool enabled() const { return m_enabled; }
+ const char *text(running_machine &machine, astring &string);
+
+ // enable/disable
+ void enable(bool state = true)
+ {
+ if (state != m_enabled)
+ {
+ m_enabled = state;
+ if (m_enabled)
+ {
+ m_dataready = false;
+ m_filoindex = m_dataindex = 0;
+ }
+ }
+ }
+
+ // start/stop
+ void start(profile_type type) { if (m_enabled) real_start(type); }
+ void stop() { if (m_enabled) real_stop(); }
+
+private:
+ void real_start(profile_type type);
+ void real_stop();
+
+ // an entry in the FILO
+ struct filo_entry
+ {
+ int type; // type of entry
+ osd_ticks_t start; // start time
+ };
+
+ // item in the array of recent states
+ struct history_data
+ {
+ UINT32 context_switches; // number of context switches seen
+ osd_ticks_t duration[PROFILER_TOTAL]; // duration spent in each entry
+ };
+
+ // internal state
+ bool m_enabled; // are we enabled?
+ bool m_dataready; // are we to display the data yet?
+ UINT8 m_filoindex; // current FILO index
+ UINT8 m_dataindex; // current data index
+ filo_entry m_filo[16]; // array of FILO entries
+ history_data m_data[16]; // array of data
+};
+
+
+// ======================> dummy_profiler_state
+
+class dummy_profiler_state
+{
+public:
+ // construction/destruction
+ dummy_profiler_state();
+
+ // getters
+ bool enabled() const { return false; }
+ const char *text(running_machine &machine, astring &string) { return string.cpy(""); }
+
+ // enable/disable
+ void enable(bool state = true) { }
+
+ // start/stop
+ void start(profile_type type) { }
+ void stop() { }
+};
+
+
+// ======================> profiler_state
+
+#ifdef MAME_PROFILER
+typedef real_profiler_state profiler_state;
+#else
+typedef dummy_profiler_state profiler_state;
+#endif
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+extern profiler_state g_profiler;
+
+
+#endif /* __PROFILER_H__ */
diff --git a/trunk/src/emu/render.c b/trunk/src/emu/render.c
new file mode 100644
index 00000000000..5e89fdbc779
--- /dev/null
+++ b/trunk/src/emu/render.c
@@ -0,0 +1,2885 @@
+/***************************************************************************
+
+ render.c
+
+ Core rendering 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.
+
+****************************************************************************
+
+ Windows-specific to-do:
+ * no fallback if we run out of video memory
+
+ Longer-term to do: (once old renderer is gone)
+ * make vector updates asynchronous
+
+****************************************************************************
+
+ Overview of objects:
+
+ render_target -- This represents a final rendering target. It
+ is specified using integer width/height values, can have
+ non-square pixels, and you can specify its rotation. It is
+ what really determines the final rendering details. The OSD
+ layer creates one or more of these to encapsulate the
+ rendering process. Each render_target holds a list of
+ layout_files that it can use for drawing. When rendering, it
+ makes use of both layout_files and render_containers.
+
+ render_container -- Containers are the top of a hierarchy that is
+ not directly related to the objects above. Containers hold
+ high level primitives that are generated at runtime by the
+ video system. They are used currently for each screen and
+ the user interface. These high-level primitives are broken down
+ into low-level primitives at render time.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "emuopts.h"
+#include "render.h"
+#include "rendfont.h"
+#include "rendlay.h"
+#include "rendutil.h"
+#include "config.h"
+#include "xmlfile.h"
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+#define INTERNAL_FLAG_CHAR 0x00000001
+
+enum
+{
+ COMPONENT_TYPE_IMAGE = 0,
+ COMPONENT_TYPE_RECT,
+ COMPONENT_TYPE_DISK,
+ COMPONENT_TYPE_MAX
+};
+
+
+enum
+{
+ CONTAINER_ITEM_LINE = 0,
+ CONTAINER_ITEM_QUAD,
+ CONTAINER_ITEM_MAX
+};
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+#define ISWAP(var1, var2) do { int temp = var1; var1 = var2; var2 = temp; } while (0)
+#define FSWAP(var1, var2) do { float temp = var1; var1 = var2; var2 = temp; } while (0)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// an object_transform is used to track transformations when building an object list
+struct object_transform
+{
+ float xoffs, yoffs; // offset transforms
+ float xscale, yscale; // scale transforms
+ render_color color; // color transform
+ int orientation; // orientation transform
+ bool no_center; // center the container?
+};
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// precomputed UV coordinates for various orientations
+static const render_quad_texuv oriented_texcoords[8] =
+{
+ { { 0,0 }, { 1,0 }, { 0,1 }, { 1,1 } }, // 0
+ { { 1,0 }, { 0,0 }, { 1,1 }, { 0,1 } }, // ORIENTATION_FLIP_X
+ { { 0,1 }, { 1,1 }, { 0,0 }, { 1,0 } }, // ORIENTATION_FLIP_Y
+ { { 1,1 }, { 0,1 }, { 1,0 }, { 0,0 } }, // ORIENTATION_FLIP_X | ORIENTATION_FLIP_Y
+ { { 0,0 }, { 0,1 }, { 1,0 }, { 1,1 } }, // ORIENTATION_SWAP_XY
+ { { 0,1 }, { 0,0 }, { 1,1 }, { 1,0 } }, // ORIENTATION_SWAP_XY | ORIENTATION_FLIP_X
+ { { 1,0 }, { 1,1 }, { 0,0 }, { 0,1 } }, // ORIENTATION_SWAP_XY | ORIENTATION_FLIP_Y
+ { { 1,1 }, { 1,0 }, { 0,1 }, { 0,0 } } // ORIENTATION_SWAP_XY | ORIENTATION_FLIP_X | ORIENTATION_FLIP_Y
+};
+
+// layer orders
+static const int layer_order_standard[] = { ITEM_LAYER_SCREEN, ITEM_LAYER_OVERLAY, ITEM_LAYER_BACKDROP, ITEM_LAYER_BEZEL, ITEM_LAYER_CPANEL, ITEM_LAYER_MARQUEE };
+static const int layer_order_alternate[] = { ITEM_LAYER_BACKDROP, ITEM_LAYER_SCREEN, ITEM_LAYER_OVERLAY, ITEM_LAYER_BEZEL, ITEM_LAYER_CPANEL, ITEM_LAYER_MARQUEE };
+
+
+
+//**************************************************************************
+// INLINE FUNCTIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// apply_orientation - apply orientation to a
+// set of bounds
+//-------------------------------------------------
+
+inline void apply_orientation(render_bounds &bounds, int orientation)
+{
+ // swap first
+ if (orientation & ORIENTATION_SWAP_XY)
+ {
+ FSWAP(bounds.x0, bounds.y0);
+ FSWAP(bounds.x1, bounds.y1);
+ }
+
+ // apply X flip
+ if (orientation & ORIENTATION_FLIP_X)
+ {
+ bounds.x0 = 1.0f - bounds.x0;
+ bounds.x1 = 1.0f - bounds.x1;
+ }
+
+ // apply Y flip
+ if (orientation & ORIENTATION_FLIP_Y)
+ {
+ bounds.y0 = 1.0f - bounds.y0;
+ bounds.y1 = 1.0f - bounds.y1;
+ }
+}
+
+
+//-------------------------------------------------
+// normalize_bounds - normalize bounds so that
+// x0/y0 are less than x1/y1
+//-------------------------------------------------
+
+inline void normalize_bounds(render_bounds &bounds)
+{
+ if (bounds.x0 > bounds.x1)
+ FSWAP(bounds.x0, bounds.x1);
+ if (bounds.y0 > bounds.y1)
+ FSWAP(bounds.y0, bounds.y1);
+}
+
+
+//-------------------------------------------------
+// get_layer_and_blendmode - return the
+// appropriate layer index and blendmode
+//-------------------------------------------------
+
+inline item_layer get_layer_and_blendmode(const layout_view &view, int index, int &blendmode)
+{
+ // if we have multiple backdrop pieces and no overlays, render:
+ // backdrop (add) + screens (add) + bezels (alpha) + cpanels (alpha) + marquees (alpha)
+ // else render:
+ // screens (add) + overlays (RGB multiply) + backdrop (add) + bezels (alpha) + cpanels (alpha) + marquees (alpha)
+
+ const int *layer_order = layer_order_standard;
+ if (view.first_item(ITEM_LAYER_BACKDROP) != NULL && view.first_item(ITEM_LAYER_BACKDROP)->next() != NULL && view.first_item(ITEM_LAYER_OVERLAY) == NULL)
+ layer_order = layer_order_alternate;
+
+ // select the layer
+ int layer = layer_order[index];
+
+ // pick a blendmode
+ if (layer == ITEM_LAYER_SCREEN && layer_order == layer_order_standard)
+ blendmode = -1;
+ else if (layer == ITEM_LAYER_SCREEN || (layer == ITEM_LAYER_BACKDROP && layer_order == layer_order_standard))
+ blendmode = BLENDMODE_ADD;
+ else if (layer == ITEM_LAYER_OVERLAY)
+ blendmode = BLENDMODE_RGB_MULTIPLY;
+ else
+ blendmode = BLENDMODE_ALPHA;
+
+ return item_layer(layer);
+}
+
+
+
+//**************************************************************************
+// RENDER PRIMITIVE
+//**************************************************************************
+
+//-------------------------------------------------
+// reset - reset the state of a primitive after
+// it is re-allocated
+//-------------------------------------------------
+
+void render_primitive::reset()
+{
+ memset(&type, 0, FPTR(&texcoords + 1) - FPTR(&type));
+}
+
+
+
+//**************************************************************************
+// RENDER PRIMITIVE LIST
+//**************************************************************************
+
+//-------------------------------------------------
+// render_primitive_list - constructor
+//-------------------------------------------------
+
+render_primitive_list::render_primitive_list()
+ : m_lock(osd_lock_alloc())
+{
+}
+
+
+//-------------------------------------------------
+// ~render_primitive_list - destructor
+//-------------------------------------------------
+
+render_primitive_list::~render_primitive_list()
+{
+ release_all();
+ osd_lock_free(m_lock);
+}
+
+
+//-------------------------------------------------
+// add_reference - add a new reference
+//-------------------------------------------------
+
+inline void render_primitive_list::add_reference(void *refptr)
+{
+ // skip if we already have one
+ if (has_reference(refptr))
+ return;
+
+ // set the refptr and link us into the list
+ reference *ref = m_reference_allocator.alloc();
+ ref->m_refptr = refptr;
+ m_reflist.append(*ref);
+}
+
+
+//-------------------------------------------------
+// has_reference - find a refptr in a reference
+// list
+//-------------------------------------------------
+
+inline bool render_primitive_list::has_reference(void *refptr) const
+{
+ // skip if we already have one
+ for (reference *ref = m_reflist.first(); ref != NULL; ref = ref->next())
+ if (ref->m_refptr == refptr)
+ return true;
+ return false;
+}
+
+
+//-------------------------------------------------
+// alloc - allocate a new empty primitive
+//-------------------------------------------------
+
+inline render_primitive *render_primitive_list::alloc(render_primitive::primitive_type type)
+{
+ render_primitive *result = m_primitive_allocator.alloc();
+ result->reset();
+ result->type = type;
+ return result;
+}
+
+
+//-------------------------------------------------
+// release_all - release the contents of
+// a render list
+//-------------------------------------------------
+
+void render_primitive_list::release_all()
+{
+ // release all the live items while under the lock
+ acquire_lock();
+ m_primitive_allocator.reclaim_all(m_primlist);
+ m_reference_allocator.reclaim_all(m_reflist);
+ release_lock();
+}
+
+
+//-------------------------------------------------
+// append_or_return - append a primitive to the
+// end of the list, or return it to the free
+// list, based on a flag
+//-------------------------------------------------
+
+void render_primitive_list::append_or_return(render_primitive &prim, bool clipped)
+{
+ if (!clipped)
+ m_primlist.append(prim);
+ else
+ m_primitive_allocator.reclaim(prim);
+}
+
+
+
+//**************************************************************************
+// RENDER TEXTURE
+//**************************************************************************
+
+//-------------------------------------------------
+// render_texture - constructor
+//-------------------------------------------------
+
+render_texture::render_texture()
+ : m_manager(NULL),
+ m_next(NULL),
+ m_bitmap(NULL),
+ m_palette(NULL),
+ m_format(TEXFORMAT_ARGB32),
+ m_scaler(NULL),
+ m_param(NULL),
+ m_curseq(0),
+ m_bcglookup(NULL),
+ m_bcglookup_entries(0)
+{
+ m_sbounds.min_x = m_sbounds.min_y = m_sbounds.max_x = m_sbounds.max_y = 0;
+ memset(m_scaled, 0, sizeof(m_scaled));
+}
+
+
+//-------------------------------------------------
+// ~render_texture - destructor
+//-------------------------------------------------
+
+render_texture::~render_texture()
+{
+ release();
+}
+
+
+//-------------------------------------------------
+// reset - reset the state of a texture after
+// it has been re-allocated
+//-------------------------------------------------
+
+void render_texture::reset(render_manager &manager, texture_scaler_func scaler, void *param)
+{
+ m_manager = &manager;
+ m_scaler = scaler;
+ m_param = param;
+}
+
+
+//-------------------------------------------------
+// release - release resources when we are freed
+//-------------------------------------------------
+
+void render_texture::release()
+{
+ // free all scaled versions
+ for (int scalenum = 0; scalenum < ARRAY_LENGTH(m_scaled); scalenum++)
+ {
+ m_manager->invalidate_all(m_scaled[scalenum].bitmap);
+ auto_free(m_manager->machine(), m_scaled[scalenum].bitmap);
+ m_scaled[scalenum].bitmap = NULL;
+ m_scaled[scalenum].seqid = 0;
+ }
+
+ // invalidate references to the original bitmap as well
+ m_manager->invalidate_all(m_bitmap);
+ m_bitmap = NULL;
+ m_sbounds.min_x = m_sbounds.min_y = m_sbounds.max_x = m_sbounds.max_y = 0;
+ m_format = TEXFORMAT_ARGB32;
+ m_curseq = 0;
+
+ // release palette references
+ if (m_palette != NULL)
+ palette_deref(m_palette);
+ m_palette = NULL;
+
+ // free any B/C/G lookup tables
+ auto_free(m_manager->machine(), m_bcglookup);
+ m_bcglookup = NULL;
+ m_bcglookup_entries = 0;
+}
+
+
+//-------------------------------------------------
+// set_bitmap - set a new source bitmap
+//-------------------------------------------------
+
+void render_texture::set_bitmap(bitmap_t *bitmap, const rectangle *sbounds, int format, palette_t *palette)
+{
+ // ensure we have a valid palette for palettized modes
+ if (format == TEXFORMAT_PALETTE16 || format == TEXFORMAT_PALETTEA16)
+ assert(palette != NULL);
+
+ // invalidate references to the old bitmap
+ if (bitmap != m_bitmap && m_bitmap != NULL)
+ m_manager->invalidate_all(m_bitmap);
+
+ // if the palette is different, adjust references
+ if (palette != m_palette)
+ {
+ if (m_palette != NULL)
+ palette_deref(m_palette);
+ if (palette != NULL)
+ palette_ref(palette);
+ }
+
+ // set the new bitmap/palette
+ m_bitmap = bitmap;
+ m_sbounds.min_x = (sbounds != NULL) ? sbounds->min_x : 0;
+ m_sbounds.min_y = (sbounds != NULL) ? sbounds->min_y : 0;
+ m_sbounds.max_x = (sbounds != NULL) ? sbounds->max_x : (bitmap != NULL) ? bitmap->width : 1000;
+ m_sbounds.max_y = (sbounds != NULL) ? sbounds->max_y : (bitmap != NULL) ? bitmap->height : 1000;
+ m_palette = palette;
+ m_format = format;
+
+ // invalidate all scaled versions
+ for (int scalenum = 0; scalenum < ARRAY_LENGTH(m_scaled); scalenum++)
+ {
+ if (m_scaled[scalenum].bitmap != NULL)
+ {
+ m_manager->invalidate_all(m_scaled[scalenum].bitmap);
+ auto_free(m_manager->machine(), m_scaled[scalenum].bitmap);
+ }
+ m_scaled[scalenum].bitmap = NULL;
+ m_scaled[scalenum].seqid = 0;
+ }
+}
+
+
+//-------------------------------------------------
+// hq_scale - generic high quality resampling
+// scaler
+//-------------------------------------------------
+
+void render_texture::hq_scale(bitmap_t &dest, const bitmap_t &source, const rectangle &sbounds, void *param)
+{
+ render_color color = { 1.0f, 1.0f, 1.0f, 1.0f };
+ render_resample_argb_bitmap_hq(dest.base, dest.rowpixels, dest.width, dest.height, &source, &sbounds, &color);
+}
+
+
+//-------------------------------------------------
+// get_scaled - get a scaled bitmap (if we can)
+//-------------------------------------------------
+
+bool render_texture::get_scaled(UINT32 dwidth, UINT32 dheight, render_texinfo &texinfo, render_primitive_list &primlist)
+{
+ // source width/height come from the source bounds
+ int swidth = m_sbounds.max_x - m_sbounds.min_x;
+ int sheight = m_sbounds.max_y - m_sbounds.min_y;
+
+ // ensure height/width are non-zero
+ if (dwidth < 1) dwidth = 1;
+ if (dheight < 1) dheight = 1;
+
+ // are we scaler-free? if so, just return the source bitmap
+ const rgb_t *palbase = (m_format == TEXFORMAT_PALETTE16 || m_format == TEXFORMAT_PALETTEA16) ? palette_entry_list_adjusted(m_palette) : NULL;
+ if (m_scaler == NULL || (m_bitmap != NULL && swidth == dwidth && sheight == dheight))
+ {
+ // add a reference and set up the source bitmap
+ primlist.add_reference(m_bitmap);
+ UINT8 bpp = (m_format == TEXFORMAT_PALETTE16 || m_format == TEXFORMAT_PALETTEA16 || m_format == TEXFORMAT_RGB15 || m_format == TEXFORMAT_YUY16) ? 16 : 32;
+ texinfo.base = (UINT8 *)m_bitmap->base + (m_sbounds.min_y * m_bitmap->rowpixels + m_sbounds.min_x) * (bpp / 8);
+ texinfo.rowpixels = m_bitmap->rowpixels;
+ texinfo.width = swidth;
+ texinfo.height = sheight;
+ texinfo.palette = palbase;
+ texinfo.seqid = ++m_curseq;
+ return true;
+ }
+
+ // is it a size we already have?
+ scaled_texture *scaled = NULL;
+ int scalenum;
+ for (scalenum = 0; scalenum < ARRAY_LENGTH(m_scaled); scalenum++)
+ {
+ scaled = &m_scaled[scalenum];
+
+ // we need a non-NULL bitmap with matching dest size
+ if (scaled->bitmap != NULL && dwidth == scaled->bitmap->width && dheight == scaled->bitmap->height)
+ break;
+ }
+
+ // did we get one?
+ if (scalenum == ARRAY_LENGTH(m_scaled))
+ {
+ int lowest = -1;
+
+ // didn't find one -- take the entry with the lowest seqnum
+ for (scalenum = 0; scalenum < ARRAY_LENGTH(m_scaled); scalenum++)
+ if ((lowest == -1 || m_scaled[scalenum].seqid < m_scaled[lowest].seqid) && !primlist.has_reference(m_scaled[scalenum].bitmap))
+ lowest = scalenum;
+ assert_always(lowest != -1, "Too many live texture instances!");
+
+ // throw out any existing entries
+ scaled = &m_scaled[lowest];
+ if (scaled->bitmap != NULL)
+ {
+ m_manager->invalidate_all(scaled->bitmap);
+ auto_free(m_manager->machine(), scaled->bitmap);
+ }
+
+ // allocate a new bitmap
+ scaled->bitmap = auto_alloc(m_manager->machine(), bitmap_t(dwidth, dheight, BITMAP_FORMAT_ARGB32));
+ scaled->seqid = ++m_curseq;
+
+ // let the scaler do the work
+ (*m_scaler)(*scaled->bitmap, *m_bitmap, m_sbounds, m_param);
+ }
+
+ // finally fill out the new info
+ primlist.add_reference(scaled->bitmap);
+ texinfo.base = scaled->bitmap->base;
+ texinfo.rowpixels = scaled->bitmap->rowpixels;
+ texinfo.width = dwidth;
+ texinfo.height = dheight;
+ texinfo.palette = palbase;
+ texinfo.seqid = scaled->seqid;
+ return true;
+}
+
+
+//-------------------------------------------------
+// get_adjusted_palette - return the adjusted
+// palette for a texture
+//-------------------------------------------------
+
+const rgb_t *render_texture::get_adjusted_palette(render_container &container)
+{
+ const rgb_t *adjusted;
+ int numentries;
+
+ // override the palette with our adjusted palette
+ switch (m_format)
+ {
+ case TEXFORMAT_PALETTE16:
+ case TEXFORMAT_PALETTEA16:
+
+ // if no adjustment necessary, return the raw palette
+ assert(m_palette != NULL);
+ adjusted = palette_entry_list_adjusted(m_palette);
+ if (!container.has_brightness_contrast_gamma_changes())
+ return adjusted;
+
+ // if this is the machine palette, return our precomputed adjusted palette
+ adjusted = container.bcg_lookup_table(m_format, m_palette);
+ if (adjusted != NULL)
+ return adjusted;
+
+ // otherwise, ensure we have memory allocated and compute the adjusted result ourself
+ numentries = palette_get_num_colors(m_palette) * palette_get_num_groups(m_palette);
+ if (m_bcglookup == NULL || m_bcglookup_entries < numentries)
+ {
+ rgb_t *newlookup = auto_alloc_array(m_manager->machine(), rgb_t, numentries);
+ memcpy(newlookup, m_bcglookup, m_bcglookup_entries * sizeof(rgb_t));
+ auto_free(m_manager->machine(), m_bcglookup);
+ m_bcglookup = newlookup;
+ m_bcglookup_entries = numentries;
+ }
+ for (int index = 0; index < numentries; index++)
+ {
+ UINT8 r = container.apply_brightness_contrast_gamma(RGB_RED(adjusted[index]));
+ UINT8 g = container.apply_brightness_contrast_gamma(RGB_GREEN(adjusted[index]));
+ UINT8 b = container.apply_brightness_contrast_gamma(RGB_BLUE(adjusted[index]));
+ m_bcglookup[index] = MAKE_ARGB(RGB_ALPHA(adjusted[index]), r, g, b);
+ }
+ return m_bcglookup;
+
+ case TEXFORMAT_RGB15:
+
+ // if no adjustment necessary, return NULL
+ if (!container.has_brightness_contrast_gamma_changes() && m_palette == NULL)
+ return NULL;
+
+ // if no palette, return the standard lookups
+ if (m_palette == NULL)
+ return container.bcg_lookup_table(m_format);
+
+ // otherwise, ensure we have memory allocated and compute the adjusted result ourself
+ assert(palette_get_num_colors(m_palette) == 32);
+ adjusted = palette_entry_list_adjusted(m_palette);
+ if (m_bcglookup == NULL || m_bcglookup_entries < 4 * 32)
+ {
+ rgb_t *newlookup = auto_alloc_array(m_manager->machine(), rgb_t, 4 * 32);
+ memcpy(newlookup, m_bcglookup, m_bcglookup_entries * sizeof(rgb_t));
+ auto_free(m_manager->machine(), m_bcglookup);
+ m_bcglookup = newlookup;
+ m_bcglookup_entries = 4 * 32;
+ }
+
+ // otherwise, return the 32-entry BCG lookups
+ for (int index = 0; index < 32; index++)
+ {
+ UINT8 val = container.apply_brightness_contrast_gamma(RGB_GREEN(adjusted[index]));
+ m_bcglookup[0x00 + index] = val << 0;
+ m_bcglookup[0x20 + index] = val << 8;
+ m_bcglookup[0x40 + index] = val << 16;
+ m_bcglookup[0x60 + index] = val << 24;
+ }
+ return m_bcglookup;
+
+ case TEXFORMAT_RGB32:
+ case TEXFORMAT_ARGB32:
+ case TEXFORMAT_YUY16:
+
+ // if no adjustment necessary, return NULL
+ if (!container.has_brightness_contrast_gamma_changes() && m_palette == NULL)
+ return NULL;
+
+ // if no palette, return the standard lookups
+ if (m_palette == NULL)
+ return container.bcg_lookup_table(m_format);
+
+ // otherwise, ensure we have memory allocated and compute the adjusted result ourself
+ assert(palette_get_num_colors(m_palette) == 256);
+ adjusted = palette_entry_list_adjusted(m_palette);
+ if (m_bcglookup == NULL || m_bcglookup_entries < 4 * 256)
+ {
+ rgb_t *newlookup = auto_alloc_array(m_manager->machine(), rgb_t, 4 * 256);
+ memcpy(newlookup, m_bcglookup, m_bcglookup_entries * sizeof(rgb_t));
+ auto_free(m_manager->machine(), m_bcglookup);
+ m_bcglookup = newlookup;
+ m_bcglookup_entries = 4 * 256;
+ }
+
+ // otherwise, return the 32-entry BCG lookups
+ for (int index = 0; index < 256; index++)
+ {
+ UINT8 val = container.apply_brightness_contrast_gamma(RGB_GREEN(adjusted[index]));
+ m_bcglookup[0x000 + index] = val << 0;
+ m_bcglookup[0x100 + index] = val << 8;
+ m_bcglookup[0x200 + index] = val << 16;
+ m_bcglookup[0x300 + index] = val << 24;
+ }
+ return m_bcglookup;
+
+ default:
+ assert(FALSE);
+ }
+
+ return NULL;
+}
+
+
+
+//**************************************************************************
+// RENDER CONTAINER
+//**************************************************************************
+
+//-------------------------------------------------
+// render_container - constructor
+//-------------------------------------------------
+
+render_container::render_container(render_manager &manager, screen_device *screen)
+ : m_next(NULL),
+ m_manager(manager),
+ m_itemlist(manager.machine().respool()),
+ m_item_allocator(manager.machine().respool()),
+ m_screen(screen),
+ m_overlaybitmap(NULL),
+ m_overlaytexture(NULL),
+ m_palclient(NULL)
+{
+ // all palette entries are opaque by default
+ for (int color = 0; color < ARRAY_LENGTH(m_bcglookup); color++)
+ m_bcglookup[color] = MAKE_ARGB(0xff,0x00,0x00,0x00);
+
+ // make sure it is empty
+ empty();
+
+ // if we have a screen, read and apply the options
+ if (screen != NULL)
+ {
+ // set the initial orientation and brightness/contrast/gamma
+ m_user.m_orientation = manager.machine().system().flags & ORIENTATION_MASK;
+ m_user.m_brightness = manager.machine().options().brightness();
+ m_user.m_contrast = manager.machine().options().contrast();
+ m_user.m_gamma = manager.machine().options().gamma();
+ }
+
+ // allocate a client to the main palette
+ if (manager.machine().palette != NULL)
+ m_palclient = palette_client_alloc(manager.machine().palette);
+ recompute_lookups();
+}
+
+
+//-------------------------------------------------
+// ~render_container - destructor
+//-------------------------------------------------
+
+render_container::~render_container()
+{
+ // free all the container items
+ empty();
+
+ // free the overlay texture
+ m_manager.texture_free(m_overlaytexture);
+
+ // release our palette client
+ if (m_palclient != NULL)
+ palette_client_free(m_palclient);
+}
+
+
+//-------------------------------------------------
+// set_overlay - set the overlay bitmap for the
+// container
+//-------------------------------------------------
+
+void render_container::set_overlay(bitmap_t *bitmap)
+{
+ // free any existing texture
+ m_manager.texture_free(m_overlaytexture);
+
+ // set the new data and allocate the texture
+ m_overlaybitmap = bitmap;
+ if (m_overlaybitmap != NULL)
+ {
+ m_overlaytexture = m_manager.texture_alloc(render_container::overlay_scale);
+ m_overlaytexture->set_bitmap(bitmap, NULL, TEXFORMAT_ARGB32);
+ }
+}
+
+
+//-------------------------------------------------
+// set_user_settings - set the current user
+// settings for a container
+//-------------------------------------------------
+
+void render_container::set_user_settings(const user_settings &settings)
+{
+ m_user = settings;
+ recompute_lookups();
+}
+
+
+//-------------------------------------------------
+// add_line - add a line item to this container
+//-------------------------------------------------
+
+void render_container::add_line(float x0, float y0, float x1, float y1, float width, rgb_t argb, UINT32 flags)
+{
+ item &newitem = add_generic(CONTAINER_ITEM_LINE, x0, y0, x1, y1, argb);
+ newitem.m_width = width;
+ newitem.m_flags = flags;
+}
+
+
+//-------------------------------------------------
+// add_quad - add a quad item to this container
+//-------------------------------------------------
+
+void render_container::add_quad(float x0, float y0, float x1, float y1, rgb_t argb, render_texture *texture, UINT32 flags)
+{
+ item &newitem = add_generic(CONTAINER_ITEM_QUAD, x0, y0, x1, y1, argb);
+ newitem.m_texture = texture;
+ newitem.m_flags = flags;
+}
+
+
+//-------------------------------------------------
+// add_char - add a char item to this container
+//-------------------------------------------------
+
+void render_container::add_char(float x0, float y0, float height, float aspect, rgb_t argb, render_font &font, UINT16 ch)
+{
+ // compute the bounds of the character cell and get the texture
+ render_bounds bounds;
+ bounds.x0 = x0;
+ bounds.y0 = y0;
+ render_texture *texture = font.get_char_texture_and_bounds(height, aspect, ch, bounds);
+
+ // add it like a quad
+ item &newitem = add_generic(CONTAINER_ITEM_QUAD, bounds.x0, bounds.y0, bounds.x1, bounds.y1, argb);
+ newitem.m_texture = texture;
+ newitem.m_flags = PRIMFLAG_TEXORIENT(ROT0) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA);
+ newitem.m_internal = INTERNAL_FLAG_CHAR;
+}
+
+
+//-------------------------------------------------
+// apply_brightness_contrast_gamma - apply the
+// container's brightess, contrast, and gamma to
+// an 8-bit value
+//-------------------------------------------------
+
+UINT8 render_container::apply_brightness_contrast_gamma(UINT8 value)
+{
+ return ::apply_brightness_contrast_gamma(value, m_user.m_brightness, m_user.m_contrast, m_user.m_gamma);
+}
+
+
+//-------------------------------------------------
+// apply_brightness_contrast_gamma_fp - apply the
+// container's brightess, contrast, and gamma to
+// a floating-point value
+//-------------------------------------------------
+
+float render_container::apply_brightness_contrast_gamma_fp(float value)
+{
+ return ::apply_brightness_contrast_gamma_fp(value, m_user.m_brightness, m_user.m_contrast, m_user.m_gamma);
+}
+
+
+//-------------------------------------------------
+// bcg_lookup_table - return the appropriate
+// brightness/contrast/gamma lookup table for a
+// given texture mode
+//-------------------------------------------------
+
+const rgb_t *render_container::bcg_lookup_table(int texformat, palette_t *palette)
+{
+ switch (texformat)
+ {
+ case TEXFORMAT_PALETTE16:
+ case TEXFORMAT_PALETTEA16:
+ return (palette != NULL && palette == palette_client_get_palette(m_palclient)) ? m_bcglookup : NULL;
+
+ case TEXFORMAT_RGB15:
+ return m_bcglookup32;
+
+ case TEXFORMAT_RGB32:
+ case TEXFORMAT_ARGB32:
+ case TEXFORMAT_YUY16:
+ return m_bcglookup256;
+
+ default:
+ return NULL;
+ }
+}
+
+
+//-------------------------------------------------
+// overlay_scale - scaler for an overlay
+//-------------------------------------------------
+
+void render_container::overlay_scale(bitmap_t &dest, const bitmap_t &source, const rectangle &sbounds, void *param)
+{
+ // simply replicate the source bitmap over the target
+ for (int y = 0; y < dest.height; y++)
+ {
+ UINT32 *src = (UINT32 *)source.base + (y % source.height) * source.rowpixels;
+ UINT32 *dst = (UINT32 *)dest.base + y * dest.rowpixels;
+ int sx = 0;
+
+ // loop over columns
+ for (int x = 0; x < dest.width; x++)
+ {
+ *dst++ = src[sx++];
+ if (sx >= source.width)
+ sx = 0;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// add_generic - add a generic item to a
+// container
+//-------------------------------------------------
+
+render_container::item &render_container::add_generic(UINT8 type, float x0, float y0, float x1, float y1, rgb_t argb)
+{
+ item *newitem = m_item_allocator.alloc();
+
+ // copy the data into the new item
+ newitem->m_type = type;
+ newitem->m_bounds.x0 = x0;
+ newitem->m_bounds.y0 = y0;
+ newitem->m_bounds.x1 = x1;
+ newitem->m_bounds.y1 = y1;
+ newitem->m_color.r = (float)RGB_RED(argb) * (1.0f / 255.0f);
+ newitem->m_color.g = (float)RGB_GREEN(argb) * (1.0f / 255.0f);
+ newitem->m_color.b = (float)RGB_BLUE(argb) * (1.0f / 255.0f);
+ newitem->m_color.a = (float)RGB_ALPHA(argb) * (1.0f / 255.0f);
+ newitem->m_flags = 0;
+ newitem->m_internal = 0;
+ newitem->m_width = 0;
+ newitem->m_texture = NULL;
+
+ // add the item to the container
+ return m_itemlist.append(*newitem);
+}
+
+
+//-------------------------------------------------
+// recompute_lookups - recompute the lookup table
+// for the render container
+//-------------------------------------------------
+
+void render_container::recompute_lookups()
+{
+ // recompute the 256 entry lookup table
+ for (int i = 0; i < 0x100; i++)
+ {
+ UINT8 adjustedval = apply_brightness_contrast_gamma(i);
+ m_bcglookup256[i + 0x000] = adjustedval << 0;
+ m_bcglookup256[i + 0x100] = adjustedval << 8;
+ m_bcglookup256[i + 0x200] = adjustedval << 16;
+ m_bcglookup256[i + 0x300] = adjustedval << 24;
+ }
+
+ // recompute the 32 entry lookup table
+ for (int i = 0; i < 0x20; i++)
+ {
+ UINT8 adjustedval = apply_brightness_contrast_gamma(pal5bit(i));
+ m_bcglookup32[i + 0x000] = adjustedval << 0;
+ m_bcglookup32[i + 0x020] = adjustedval << 8;
+ m_bcglookup32[i + 0x040] = adjustedval << 16;
+ m_bcglookup32[i + 0x060] = adjustedval << 24;
+ }
+
+ // recompute the palette entries
+ if (m_palclient != NULL)
+ {
+ palette_t *palette = palette_client_get_palette(m_palclient);
+ const pen_t *adjusted_palette = palette_entry_list_adjusted(palette);
+ int colors = palette_get_num_colors(palette) * palette_get_num_groups(palette);
+
+ for (int i = 0; i < colors; i++)
+ {
+ pen_t newval = adjusted_palette[i];
+ m_bcglookup[i] = (newval & 0xff000000) |
+ m_bcglookup256[0x200 + RGB_RED(newval)] |
+ m_bcglookup256[0x100 + RGB_GREEN(newval)] |
+ m_bcglookup256[0x000 + RGB_BLUE(newval)];
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// update_palette - update any dirty palette
+// entries
+//-------------------------------------------------
+
+void render_container::update_palette()
+{
+ // skip if no client
+ if (m_palclient == NULL)
+ return;
+
+ // get the dirty list
+ UINT32 mindirty, maxdirty;
+ const UINT32 *dirty = palette_client_get_dirty_list(m_palclient, &mindirty, &maxdirty);
+
+ // iterate over dirty items and update them
+ if (dirty != NULL)
+ {
+ palette_t *palette = palette_client_get_palette(m_palclient);
+ const pen_t *adjusted_palette = palette_entry_list_adjusted(palette);
+
+ // loop over chunks of 32 entries, since we can quickly examine 32 at a time
+ for (UINT32 entry32 = mindirty / 32; entry32 <= maxdirty / 32; entry32++)
+ {
+ UINT32 dirtybits = dirty[entry32];
+ if (dirtybits != 0)
+
+ // this chunk of 32 has dirty entries; fix them up
+ for (UINT32 entry = 0; entry < 32; entry++)
+ if (dirtybits & (1 << entry))
+ {
+ UINT32 finalentry = entry32 * 32 + entry;
+ rgb_t newval = adjusted_palette[finalentry];
+ m_bcglookup[finalentry] = (newval & 0xff000000) |
+ m_bcglookup256[0x200 + RGB_RED(newval)] |
+ m_bcglookup256[0x100 + RGB_GREEN(newval)] |
+ m_bcglookup256[0x000 + RGB_BLUE(newval)];
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// user_settings - constructor
+//-------------------------------------------------
+
+render_container::user_settings::user_settings()
+ : m_orientation(0),
+ m_brightness(1.0f),
+ m_contrast(1.0f),
+ m_gamma(1.0f),
+ m_xscale(1.0f),
+ m_yscale(1.0f),
+ m_xoffset(0.0f),
+ m_yoffset(0.0f)
+{
+}
+
+
+
+//**************************************************************************
+// RENDER TARGET
+//**************************************************************************
+
+//-------------------------------------------------
+// render_target - constructor
+//-------------------------------------------------
+
+render_target::render_target(render_manager &manager, const char *layoutfile, UINT32 flags)
+ : m_next(NULL),
+ m_manager(manager),
+ m_curview(NULL),
+ m_filelist(*auto_alloc(manager.machine(), simple_list<layout_file>(manager.machine().respool()))),
+ m_flags(flags),
+ m_listindex(0),
+ m_width(640),
+ m_height(480),
+ m_pixel_aspect(0.0f),
+ m_max_refresh(0),
+ m_orientation(0),
+ m_base_view(NULL),
+ m_base_orientation(ROT0),
+ m_maxtexwidth(65536),
+ m_maxtexheight(65536),
+ m_debug_containers(manager.machine().respool())
+{
+ // determine the base layer configuration based on options
+ m_base_layerconfig.set_backdrops_enabled(manager.machine().options().use_backdrops());
+ m_base_layerconfig.set_overlays_enabled(manager.machine().options().use_overlays());
+ m_base_layerconfig.set_bezels_enabled(manager.machine().options().use_bezels());
+ m_base_layerconfig.set_cpanels_enabled(manager.machine().options().use_cpanels());
+ m_base_layerconfig.set_marquees_enabled(manager.machine().options().use_marquees());
+ m_base_layerconfig.set_zoom_to_screen(manager.machine().options().artwork_crop());
+
+ // determine the base orientation based on options
+ m_orientation = ROT0;
+ if (!manager.machine().options().rotate())
+ m_base_orientation = orientation_reverse(manager.machine().system().flags & ORIENTATION_MASK);
+
+ // rotate left/right
+ if (manager.machine().options().ror() || (manager.machine().options().auto_ror() && (manager.machine().system().flags & ORIENTATION_SWAP_XY)))
+ m_base_orientation = orientation_add(ROT90, m_base_orientation);
+ if (manager.machine().options().rol() || (manager.machine().options().auto_rol() && (manager.machine().system().flags & ORIENTATION_SWAP_XY)))
+ m_base_orientation = orientation_add(ROT270, m_base_orientation);
+
+ // flip X/Y
+ if (manager.machine().options().flipx())
+ m_base_orientation ^= ORIENTATION_FLIP_X;
+ if (manager.machine().options().flipy())
+ m_base_orientation ^= ORIENTATION_FLIP_Y;
+
+ // set the orientation and layerconfig equal to the base
+ m_orientation = m_base_orientation;
+ m_layerconfig = m_base_layerconfig;
+
+ // load the layout files
+ load_layout_files(layoutfile, flags & RENDER_CREATE_SINGLE_FILE);
+
+ // set the current view to the first one
+ set_view(0);
+
+ // make us the UI target if there is none
+ if (!hidden() && manager.m_ui_target == NULL)
+ manager.set_ui_target(*this);
+}
+
+
+//-------------------------------------------------
+// ~render_target - destructor
+//-------------------------------------------------
+
+render_target::~render_target()
+{
+ auto_free(m_manager.machine(), &m_filelist);
+}
+
+
+//-------------------------------------------------
+// is_ui_target - return true if this is the
+// UI target
+//-------------------------------------------------
+
+bool render_target::is_ui_target() const
+{
+ return (this == &m_manager.ui_target());
+}
+
+
+//-------------------------------------------------
+// index - return the index of this target
+//-------------------------------------------------
+
+int render_target::index() const
+{
+ return m_manager.m_targetlist.indexof(*this);
+}
+
+
+//-------------------------------------------------
+// set_bounds - set the bounds and pixel aspect
+// of a target
+//-------------------------------------------------
+
+void render_target::set_bounds(INT32 width, INT32 height, float pixel_aspect)
+{
+ m_width = width;
+ m_height = height;
+ m_bounds.x0 = m_bounds.y0 = 0;
+ m_bounds.x1 = (float)width;
+ m_bounds.y1 = (float)height;
+ m_pixel_aspect = pixel_aspect;
+}
+
+
+//-------------------------------------------------
+// set_view - dynamically change the view for
+// a target
+//-------------------------------------------------
+
+void render_target::set_view(int viewindex)
+{
+ layout_view *view = view_by_index(viewindex);
+ if (view != NULL)
+ {
+ m_curview = view;
+ view->recompute(m_layerconfig);
+ }
+}
+
+
+//-------------------------------------------------
+// set_max_texture_size - set the upper bound on
+// the texture size
+//-------------------------------------------------
+
+void render_target::set_max_texture_size(int maxwidth, int maxheight)
+{
+ m_maxtexwidth = maxwidth;
+ m_maxtexheight = maxheight;
+}
+
+
+//-------------------------------------------------
+// configured_view - select a view for this
+// target based on the configuration parameters
+//-------------------------------------------------
+
+int render_target::configured_view(const char *viewname, int targetindex, int numtargets)
+{
+ layout_view *view = NULL;
+ int viewindex;
+
+ // auto view just selects the nth view
+ if (strcmp(viewname, "auto") != 0)
+ {
+ // scan for a matching view name
+ for (view = view_by_index(viewindex = 0); view != NULL; view = view_by_index(++viewindex))
+ if (mame_strnicmp(view->name(), viewname, strlen(viewname)) == 0)
+ break;
+ }
+
+ // if we don't have a match, default to the nth view
+ int scrcount = m_manager.machine().devicelist().count(SCREEN);
+ if (view == NULL && scrcount > 0)
+ {
+ // if we have enough targets to be one per screen, assign in order
+ if (numtargets >= scrcount)
+ {
+ int ourindex = index() % scrcount;
+ screen_device *screen;
+ for (screen = m_manager.machine().first_screen(); screen != NULL; screen = screen->next_screen())
+ if (ourindex-- == 0)
+ break;
+
+ // find the first view with this screen and this screen only
+ for (view = view_by_index(viewindex = 0); view != NULL; view = view_by_index(++viewindex))
+ {
+ const render_screen_list &viewscreens = view->screens();
+ if (viewscreens.count() == 1 && viewscreens.contains(*screen))
+ break;
+ if (viewscreens.count() == 0)
+ {
+ view = NULL;
+ break;
+ }
+ }
+ }
+
+ // otherwise, find the first view that has all the screens
+ if (view == NULL)
+ {
+ for (view = view_by_index(viewindex = 0); view != NULL; view = view_by_index(++viewindex))
+ {
+ const render_screen_list &viewscreens = view->screens();
+ if (viewscreens.count() == 0)
+ break;
+ if (viewscreens.count() >= scrcount)
+ {
+ screen_device *screen;
+ for (screen = m_manager.machine().first_screen(); screen != NULL; screen = screen->next_screen())
+ if (!viewscreens.contains(*screen))
+ break;
+ if (screen == NULL)
+ break;
+ }
+ }
+ }
+ }
+
+ // make sure it's a valid view
+ return (view != NULL) ? view_index(*view) : 0;
+}
+
+
+//-------------------------------------------------
+// view_name - return the name of the given view
+//-------------------------------------------------
+
+const char *render_target::view_name(int viewindex)
+{
+ layout_view *view = view_by_index(viewindex);
+ return (view != NULL) ? view->name() : NULL;
+}
+
+
+//-------------------------------------------------
+// render_target_get_view_screens - return a
+// bitmask of which screens are visible on a
+// given view
+//-------------------------------------------------
+
+const render_screen_list &render_target::view_screens(int viewindex)
+{
+ layout_view *view = view_by_index(viewindex);
+ return (view != NULL) ? view->screens() : s_empty_screen_list;
+}
+
+
+//-------------------------------------------------
+// compute_visible_area - compute the visible
+// area for the given target with the current
+// layout and proposed new parameters
+//-------------------------------------------------
+
+void render_target::compute_visible_area(INT32 target_width, INT32 target_height, float target_pixel_aspect, int target_orientation, INT32 &visible_width, INT32 &visible_height)
+{
+ float width, height;
+ float scale;
+
+ // constrained case
+ if (target_pixel_aspect != 0.0f)
+ {
+ // start with the aspect ratio of the square pixel layout
+ width = m_curview->effective_aspect(m_layerconfig);
+ height = 1.0f;
+
+ // first apply target orientation
+ if (target_orientation & ORIENTATION_SWAP_XY)
+ FSWAP(width, height);
+
+ // apply the target pixel aspect ratio
+ height *= target_pixel_aspect;
+
+ // based on the height/width ratio of the source and target, compute the scale factor
+ if (width / height > (float)target_width / (float)target_height)
+ scale = (float)target_width / width;
+ else
+ scale = (float)target_height / height;
+ }
+
+ // stretch-to-fit case
+ else
+ {
+ width = (float)target_width;
+ height = (float)target_height;
+ scale = 1.0f;
+ }
+
+ // set the final width/height
+ visible_width = render_round_nearest(width * scale);
+ visible_height = render_round_nearest(height * scale);
+}
+
+
+//-------------------------------------------------
+// compute_minimum_size - compute the "minimum"
+// size of a target, which is the smallest bounds
+// that will ensure at least 1 target pixel per
+// source pixel for all included screens
+//-------------------------------------------------
+
+void render_target::compute_minimum_size(INT32 &minwidth, INT32 &minheight)
+{
+ float maxxscale = 1.0f, maxyscale = 1.0f;
+ int screens_considered = 0;
+
+ // early exit in case we are called between device teardown and render teardown
+ if (m_manager.machine().devicelist().count() == 0)
+ {
+ minwidth = 640;
+ minheight = 480;
+ return;
+ }
+
+ if (m_curview == NULL)
+ throw emu_fatalerror("Mandatory artwork is missing");
+
+ // scan the current view for all screens
+ for (item_layer layer = ITEM_LAYER_FIRST; layer < ITEM_LAYER_MAX; layer++)
+
+ // iterate over items in the layer
+ for (layout_view::item *curitem = m_curview->first_item(layer); curitem != NULL; curitem = curitem->next())
+ if (curitem->screen() != NULL)
+ {
+ // use a hard-coded default visible area for vector screens
+ screen_device *screen = curitem->screen();
+ const rectangle vectorvis = { 0, 639, 0, 479 };
+ const rectangle &visarea = (screen->screen_type() == SCREEN_TYPE_VECTOR) ? vectorvis : screen->visible_area();
+
+ // apply target orientation to the bounds
+ render_bounds bounds = curitem->bounds();
+ apply_orientation(bounds, m_orientation);
+ normalize_bounds(bounds);
+
+ // based on the orientation of the screen container, check the bitmap
+ float xscale, yscale;
+ if (!(orientation_add(m_orientation, screen->container().orientation()) & ORIENTATION_SWAP_XY))
+ {
+ xscale = (float)(visarea.max_x + 1 - visarea.min_x) / (bounds.x1 - bounds.x0);
+ yscale = (float)(visarea.max_y + 1 - visarea.min_y) / (bounds.y1 - bounds.y0);
+ }
+ else
+ {
+ xscale = (float)(visarea.max_y + 1 - visarea.min_y) / (bounds.x1 - bounds.x0);
+ yscale = (float)(visarea.max_x + 1 - visarea.min_x) / (bounds.y1 - bounds.y0);
+ }
+
+ // pick the greater
+ maxxscale = MAX(xscale, maxxscale);
+ maxyscale = MAX(yscale, maxyscale);
+ screens_considered++;
+ }
+
+ // if there were no screens considered, pick a nominal default
+ if (screens_considered == 0)
+ {
+ maxxscale = 640.0f;
+ maxyscale = 480.0f;
+ }
+
+ // round up
+ minwidth = render_round_nearest(maxxscale);
+ minheight = render_round_nearest(maxyscale);
+}
+
+
+//-------------------------------------------------
+// get_primitives - return a list of primitives
+// for a given render target
+//-------------------------------------------------
+
+render_primitive_list &render_target::get_primitives()
+{
+ // remember the base values if this is the first frame
+ if (m_base_view == NULL)
+ m_base_view = m_curview;
+
+ // switch to the next primitive list
+ render_primitive_list &list = m_primlist[m_listindex];
+ m_listindex = (m_listindex + 1) % ARRAY_LENGTH(m_primlist);
+ list.acquire_lock();
+
+ // free any previous primitives
+ list.release_all();
+
+ // compute the visible width/height
+ INT32 viswidth, visheight;
+ compute_visible_area(m_width, m_height, m_pixel_aspect, m_orientation, viswidth, visheight);
+
+ // create a root transform for the target
+ object_transform root_xform;
+ root_xform.xoffs = (float)(m_width - viswidth) / 2;
+ root_xform.yoffs = (float)(m_height - visheight) / 2;
+ root_xform.xscale = (float)viswidth;
+ root_xform.yscale = (float)visheight;
+ root_xform.color.r = root_xform.color.g = root_xform.color.b = root_xform.color.a = 1.0f;
+ root_xform.orientation = m_orientation;
+ root_xform.no_center = false;
+
+ // iterate over layers back-to-front, but only if we're running
+ if (m_manager.machine().phase() >= MACHINE_PHASE_RESET)
+ for (item_layer layernum = ITEM_LAYER_FIRST; layernum < ITEM_LAYER_MAX; layernum++)
+ {
+ int blendmode;
+ item_layer layer = get_layer_and_blendmode(*m_curview, layernum, blendmode);
+ if (m_curview->layer_enabled(layer))
+ {
+ // iterate over items in the layer
+ for (layout_view::item *curitem = m_curview->first_item(layer); curitem != NULL; curitem = curitem->next())
+ {
+ // first apply orientation to the bounds
+ render_bounds bounds = curitem->bounds();
+ apply_orientation(bounds, root_xform.orientation);
+ normalize_bounds(bounds);
+
+ // apply the transform to the item
+ object_transform item_xform;
+ item_xform.xoffs = root_xform.xoffs + bounds.x0 * root_xform.xscale;
+ item_xform.yoffs = root_xform.yoffs + bounds.y0 * root_xform.yscale;
+ item_xform.xscale = (bounds.x1 - bounds.x0) * root_xform.xscale;
+ item_xform.yscale = (bounds.y1 - bounds.y0) * root_xform.yscale;
+ item_xform.color.r = curitem->color().r * root_xform.color.r;
+ item_xform.color.g = curitem->color().g * root_xform.color.g;
+ item_xform.color.b = curitem->color().b * root_xform.color.b;
+ item_xform.color.a = curitem->color().a * root_xform.color.a;
+ item_xform.orientation = orientation_add(curitem->orientation(), root_xform.orientation);
+ item_xform.no_center = false;
+
+ // if there is no associated element, it must be a screen element
+ if (curitem->screen() != NULL)
+ add_container_primitives(list, item_xform, curitem->screen()->container(), blendmode);
+ else
+ add_element_primitives(list, item_xform, *curitem->element(), curitem->state(), blendmode);
+ }
+ }
+ }
+
+ // if we are not in the running stage, draw an outer box
+ else
+ {
+ render_primitive *prim = list.alloc(render_primitive::QUAD);
+ set_render_bounds_xy(&prim->bounds, 0.0f, 0.0f, (float)m_width, (float)m_height);
+ set_render_color(&prim->color, 1.0f, 1.0f, 1.0f, 1.0f);
+ prim->texture.base = NULL;
+ prim->flags = PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA);
+ list.append(*prim);
+
+ if (m_width > 1 && m_height > 1)
+ {
+ prim = list.alloc(render_primitive::QUAD);
+ set_render_bounds_xy(&prim->bounds, 1.0f, 1.0f, (float)(m_width - 1), (float)(m_height - 1));
+ set_render_color(&prim->color, 1.0f, 0.0f, 0.0f, 0.0f);
+ prim->texture.base = NULL;
+ prim->flags = PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA);
+ list.append(*prim);
+ }
+ }
+
+ // process the debug containers
+ for (render_container *debug = m_debug_containers.first(); debug != NULL; debug = debug->next())
+ {
+ object_transform ui_xform;
+ ui_xform.xoffs = 0;
+ ui_xform.yoffs = 0;
+ ui_xform.xscale = (float)m_width;
+ ui_xform.yscale = (float)m_height;
+ ui_xform.color.r = ui_xform.color.g = ui_xform.color.b = ui_xform.color.a = 1.0f;
+ ui_xform.color.a = 0.9f;
+ ui_xform.orientation = m_orientation;
+ ui_xform.no_center = true;
+
+ // add UI elements
+ add_container_primitives(list, ui_xform, *debug, BLENDMODE_ALPHA);
+ }
+
+ // process the UI if we are the UI target
+ if (is_ui_target())
+ {
+ // compute the transform for the UI
+ object_transform ui_xform;
+ ui_xform.xoffs = 0;
+ ui_xform.yoffs = 0;
+ ui_xform.xscale = (float) m_width;
+ ui_xform.yscale = (float) m_height;
+ ui_xform.color.r = ui_xform.color.g = ui_xform.color.b = ui_xform.color.a = 1.0f;
+ ui_xform.orientation = m_orientation;
+ ui_xform.no_center = false;
+
+ // add UI elements
+ add_container_primitives(list, ui_xform, m_manager.ui_container(), BLENDMODE_ALPHA);
+ }
+
+ // optimize the list before handing it off
+ add_clear_and_optimize_primitive_list(list);
+ list.release_lock();
+ return list;
+}
+
+
+//-------------------------------------------------
+// map_point_container - attempts to map a point
+// on the specified render_target to the
+// specified container, if possible
+//-------------------------------------------------
+
+bool render_target::map_point_container(INT32 target_x, INT32 target_y, render_container &container, float &container_x, float &container_y)
+{
+ const char *input_tag;
+ UINT32 input_mask;
+ return map_point_internal(target_x, target_y, &container, container_x, container_y, input_tag, input_mask);
+}
+
+
+//-------------------------------------------------
+// map_point_input - attempts to map a point on
+// the specified render_target to the specified
+// container, if possible
+//-------------------------------------------------
+
+bool render_target::map_point_input(INT32 target_x, INT32 target_y, const char *&input_tag, UINT32 &input_mask, float &input_x, float &input_y)
+{
+ return map_point_internal(target_x, target_y, NULL, input_x, input_y, input_tag, input_mask);
+}
+
+
+//-------------------------------------------------
+// invalidate_all - if any of our primitive lists
+// contain a reference to the given pointer,
+// clear them
+//-------------------------------------------------
+
+void render_target::invalidate_all(void *refptr)
+{
+ // iterate through all our primitive lists
+ for (int listnum = 0; listnum < ARRAY_LENGTH(m_primlist); listnum++)
+ {
+ render_primitive_list &list = m_primlist[listnum];
+
+ // if we have a reference to this object, release our list
+ list.acquire_lock();
+ if (list.has_reference(refptr))
+ list.release_all();
+ list.release_lock();
+ }
+}
+
+
+//-------------------------------------------------
+// debug_alloc - allocate a container for a debug
+// view
+//-------------------------------------------------
+
+render_container *render_target::debug_alloc()
+{
+ return &m_debug_containers.append(*m_manager.container_alloc());
+}
+
+
+//-------------------------------------------------
+// debug_free - free a container for a debug view
+//-------------------------------------------------
+
+void render_target::debug_free(render_container &container)
+{
+ m_debug_containers.remove(container);
+}
+
+
+//-------------------------------------------------
+// debug_top - move a debug view container to
+// the top of the list
+//-------------------------------------------------
+
+void render_target::debug_top(render_container &container)
+{
+ m_debug_containers.prepend(m_debug_containers.detach(container));
+}
+
+
+//-------------------------------------------------
+// update_layer_config - recompute after a layer
+// config change
+//-------------------------------------------------
+
+void render_target::update_layer_config()
+{
+ m_curview->recompute(m_layerconfig);
+}
+
+
+//-------------------------------------------------
+// load_layout_files - load layout files for a
+// given render target
+//-------------------------------------------------
+
+void render_target::load_layout_files(const char *layoutfile, bool singlefile)
+{
+ bool have_default = false;
+ // if there's an explicit file, load that first
+ const char *basename = m_manager.machine().basename();
+ if (layoutfile != NULL)
+ have_default |= load_layout_file(basename, layoutfile);
+
+ // if we're only loading this file, we know our final result
+ if (singlefile)
+ return;
+
+ // try to load a file based on the driver name
+ const game_driver &system = m_manager.machine().system();
+ if (!load_layout_file(basename, system.name))
+ have_default |= load_layout_file(basename, "default");
+ else
+ have_default |= true;
+
+ // if a default view has been specified, use that as a fallback
+ if (system.default_layout != NULL)
+ have_default |= load_layout_file(NULL, system.default_layout);
+ if (m_manager.machine().config().m_default_layout != NULL)
+ have_default |= load_layout_file(NULL, m_manager.machine().config().m_default_layout);
+
+ // try to load another file based on the parent driver name
+ int cloneof = driver_list::clone(system);
+ if (cloneof != -1) {
+ if (!load_layout_file(driver_list::driver(cloneof).name, driver_list::driver(cloneof).name))
+ have_default |= load_layout_file(driver_list::driver(cloneof).name, "default");
+ else
+ have_default |= true;
+ }
+ int screens = m_manager.machine().devicelist().count(SCREEN);
+ // now do the built-in layouts for single-screen games
+ if (screens == 1)
+ {
+ if (system.flags & ORIENTATION_SWAP_XY)
+ load_layout_file(NULL, layout_vertical);
+ else
+ load_layout_file(NULL, layout_horizont);
+ assert_always(m_filelist.count() > 0, "Couldn't parse default layout??");
+ }
+ if (!have_default)
+ {
+ if (screens == 0)
+ {
+ load_layout_file(NULL, layout_noscreens);
+ assert_always(m_filelist.count() > 0, "Couldn't parse default layout??");
+ }
+ else
+ if (screens == 2)
+ {
+ load_layout_file(NULL, layout_dualhsxs);
+ assert_always(m_filelist.count() > 0, "Couldn't parse default layout??");
+ }
+ else
+ if (screens == 3)
+ {
+ load_layout_file(NULL, layout_triphsxs);
+ assert_always(m_filelist.count() > 0, "Couldn't parse default layout??");
+ }
+ else
+ if (screens == 4)
+ {
+ load_layout_file(NULL, layout_quadhsxs);
+ assert_always(m_filelist.count() > 0, "Couldn't parse default layout??");
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// load_layout_file - load a single layout file
+// and append it to our list
+//-------------------------------------------------
+
+bool render_target::load_layout_file(const char *dirname, const char *filename)
+{
+ // if the first character of the "file" is an open brace, assume it is an XML string
+ xml_data_node *rootnode;
+ if (filename[0] == '<')
+ rootnode = xml_string_read(filename, NULL);
+
+ // otherwise, assume it is a file
+ else
+ {
+ // build the path and optionally prepend the directory
+ astring fname(filename, ".lay");
+ if (dirname != NULL)
+ fname.ins(0, PATH_SEPARATOR).ins(0, dirname);
+
+ // attempt to open the file; bail if we can't
+ emu_file layoutfile(manager().machine().options().art_path(), OPEN_FLAG_READ);
+ file_error filerr = layoutfile.open(fname);
+ if (filerr != FILERR_NONE)
+ return false;
+
+ // read the file
+ rootnode = xml_file_read(layoutfile, NULL);
+ }
+
+ // if we didn't get a properly-formatted XML file, record a warning and exit
+ if (rootnode == NULL)
+ {
+ if (filename[0] != '<')
+ mame_printf_warning("Improperly formatted XML file '%s', ignoring\n", filename);
+ else
+ mame_printf_warning("Improperly formatted XML string, ignoring\n");
+ return false;
+ }
+
+ // parse and catch any errors
+ bool result = true;
+ try
+ {
+ m_filelist.append(*auto_alloc(m_manager.machine(), layout_file(m_manager.machine(), *rootnode, dirname)));
+ }
+ catch (emu_fatalerror &err)
+ {
+ if (filename[0] != '<')
+ mame_printf_warning("Error in XML file '%s': %s\n", filename, err.string());
+ else
+ mame_printf_warning("Error in XML string: %s", err.string());
+ result = false;
+ }
+
+ // free the root node
+ xml_file_free(rootnode);
+ return result;
+}
+
+
+//-------------------------------------------------
+// add_container_primitives - add primitives
+// based on the container
+//-------------------------------------------------
+
+void render_target::add_container_primitives(render_primitive_list &list, const object_transform &xform, render_container &container, int blendmode)
+{
+ // first update the palette for the container, if it is dirty
+ container.update_palette();
+
+ // compute the clip rect
+ render_bounds cliprect;
+ cliprect.x0 = xform.xoffs;
+ cliprect.y0 = xform.yoffs;
+ cliprect.x1 = xform.xoffs + xform.xscale;
+ cliprect.y1 = xform.yoffs + xform.yscale;
+ sect_render_bounds(&cliprect, &m_bounds);
+
+ // compute the container transform
+ object_transform container_xform;
+ container_xform.orientation = orientation_add(container.orientation(), xform.orientation);
+ {
+ float xscale = (container_xform.orientation & ORIENTATION_SWAP_XY) ? container.yscale() : container.xscale();
+ float yscale = (container_xform.orientation & ORIENTATION_SWAP_XY) ? container.xscale() : container.yscale();
+ float xoffs = (container_xform.orientation & ORIENTATION_SWAP_XY) ? container.yoffset() : container.xoffset();
+ float yoffs = (container_xform.orientation & ORIENTATION_SWAP_XY) ? container.xoffset() : container.yoffset();
+ if (container_xform.orientation & ORIENTATION_FLIP_X) xoffs = -xoffs;
+ if (container_xform.orientation & ORIENTATION_FLIP_Y) yoffs = -yoffs;
+ container_xform.xscale = xform.xscale * xscale;
+ container_xform.yscale = xform.yscale * yscale;
+ if (xform.no_center)
+ {
+ container_xform.xoffs = xform.xscale * (xoffs) + xform.xoffs;
+ container_xform.yoffs = xform.yscale * (yoffs) + xform.yoffs;
+ }
+ else
+ {
+ container_xform.xoffs = xform.xscale * (0.5f - 0.5f * xscale + xoffs) + xform.xoffs;
+ container_xform.yoffs = xform.yscale * (0.5f - 0.5f * yscale + yoffs) + xform.yoffs;
+ }
+ container_xform.color = xform.color;
+ }
+
+ // iterate over elements
+ for (render_container::item *curitem = container.first_item(); curitem != NULL; curitem = curitem->next())
+ {
+ // compute the oriented bounds
+ render_bounds bounds = curitem->bounds();
+ apply_orientation(bounds, container_xform.orientation);
+
+ // allocate the primitive and set the transformed bounds/color data
+ render_primitive *prim = list.alloc(render_primitive::INVALID);
+ prim->bounds.x0 = render_round_nearest(container_xform.xoffs + bounds.x0 * container_xform.xscale);
+ prim->bounds.y0 = render_round_nearest(container_xform.yoffs + bounds.y0 * container_xform.yscale);
+ if (curitem->internal() & INTERNAL_FLAG_CHAR)
+ {
+ prim->bounds.x1 = prim->bounds.x0 + render_round_nearest((bounds.x1 - bounds.x0) * container_xform.xscale);
+ prim->bounds.y1 = prim->bounds.y0 + render_round_nearest((bounds.y1 - bounds.y0) * container_xform.yscale);
+ }
+ else
+ {
+ prim->bounds.x1 = render_round_nearest(container_xform.xoffs + bounds.x1 * container_xform.xscale);
+ prim->bounds.y1 = render_round_nearest(container_xform.yoffs + bounds.y1 * container_xform.yscale);
+ }
+
+ // compute the color of the primitive
+ prim->color.r = container_xform.color.r * curitem->color().r;
+ prim->color.g = container_xform.color.g * curitem->color().g;
+ prim->color.b = container_xform.color.b * curitem->color().b;
+ prim->color.a = container_xform.color.a * curitem->color().a;
+
+ // now switch off the type
+ bool clipped = true;
+ switch (curitem->type())
+ {
+ case CONTAINER_ITEM_LINE:
+ // adjust the color for brightness/contrast/gamma
+ prim->color.a = container.apply_brightness_contrast_gamma_fp(prim->color.a);
+ prim->color.r = container.apply_brightness_contrast_gamma_fp(prim->color.r);
+ prim->color.g = container.apply_brightness_contrast_gamma_fp(prim->color.g);
+ prim->color.b = container.apply_brightness_contrast_gamma_fp(prim->color.b);
+
+ // set the line type
+ prim->type = render_primitive::LINE;
+
+ // scale the width by the minimum of X/Y scale factors
+ prim->width = curitem->width() * MIN(container_xform.xscale, container_xform.yscale);
+ prim->flags = curitem->flags();
+
+ // clip the primitive
+ clipped = render_clip_line(&prim->bounds, &cliprect);
+ break;
+
+ case CONTAINER_ITEM_QUAD:
+ // set the quad type
+ prim->type = render_primitive::QUAD;
+
+ // normalize the bounds
+ normalize_bounds(prim->bounds);
+
+ // get the scaled bitmap and set the resulting palette
+ if (curitem->texture() != NULL)
+ {
+ // determine the final orientation
+ int finalorient = orientation_add(PRIMFLAG_GET_TEXORIENT(curitem->flags()), container_xform.orientation);
+
+ // based on the swap values, get the scaled final texture
+ int width = (finalorient & ORIENTATION_SWAP_XY) ? (prim->bounds.y1 - prim->bounds.y0) : (prim->bounds.x1 - prim->bounds.x0);
+ int height = (finalorient & ORIENTATION_SWAP_XY) ? (prim->bounds.x1 - prim->bounds.x0) : (prim->bounds.y1 - prim->bounds.y0);
+ width = MIN(width, m_maxtexwidth);
+ height = MIN(height, m_maxtexheight);
+ if (curitem->texture()->get_scaled(width, height, prim->texture, list))
+ {
+ // set the palette
+ prim->texture.palette = curitem->texture()->get_adjusted_palette(container);
+
+ // determine UV coordinates and apply clipping
+ prim->texcoords = oriented_texcoords[finalorient];
+ clipped = render_clip_quad(&prim->bounds, &cliprect, &prim->texcoords);
+
+ // apply the final orientation from the quad flags and then build up the final flags
+ prim->flags = (curitem->flags() & ~(PRIMFLAG_TEXORIENT_MASK | PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)) |
+ PRIMFLAG_TEXORIENT(finalorient) |
+ PRIMFLAG_TEXFORMAT(curitem->texture()->format());
+ if (blendmode != -1)
+ prim->flags |= PRIMFLAG_BLENDMODE(blendmode);
+ else
+ prim->flags |= PRIMFLAG_BLENDMODE(PRIMFLAG_GET_BLENDMODE(curitem->flags()));
+ }
+ }
+ else
+ {
+ // adjust the color for brightness/contrast/gamma
+ prim->color.r = container.apply_brightness_contrast_gamma_fp(prim->color.r);
+ prim->color.g = container.apply_brightness_contrast_gamma_fp(prim->color.g);
+ prim->color.b = container.apply_brightness_contrast_gamma_fp(prim->color.b);
+
+ // no texture -- set the basic flags
+ prim->texture.base = NULL;
+ prim->flags = PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA);
+
+ // apply clipping
+ clipped = render_clip_quad(&prim->bounds, &cliprect, NULL);
+ }
+ break;
+ }
+
+ // add to the list or free if we're clipped out
+ list.append_or_return(*prim, clipped);
+ }
+
+ // add the overlay if it exists
+ if (container.overlay() != NULL && m_layerconfig.screen_overlay_enabled())
+ {
+ INT32 width, height;
+
+ // allocate a primitive
+ render_primitive *prim = list.alloc(render_primitive::QUAD);
+ set_render_bounds_wh(&prim->bounds, xform.xoffs, xform.yoffs, xform.xscale, xform.yscale);
+ prim->color = container_xform.color;
+ width = render_round_nearest(prim->bounds.x1) - render_round_nearest(prim->bounds.x0);
+ height = render_round_nearest(prim->bounds.y1) - render_round_nearest(prim->bounds.y0);
+
+ bool got_scaled = container.overlay()->get_scaled(
+ (container_xform.orientation & ORIENTATION_SWAP_XY) ? height : width,
+ (container_xform.orientation & ORIENTATION_SWAP_XY) ? width : height, prim->texture, list);
+ if (got_scaled)
+ {
+ // determine UV coordinates
+ prim->texcoords = oriented_texcoords[container_xform.orientation];
+
+ // set the flags and add it to the list
+ prim->flags = PRIMFLAG_TEXORIENT(container_xform.orientation) |
+ PRIMFLAG_BLENDMODE(BLENDMODE_RGB_MULTIPLY) |
+ PRIMFLAG_TEXFORMAT(container.overlay()->format()) |
+ PRIMFLAG_TEXSHADE(1);
+ }
+ list.append_or_return(*prim, !got_scaled);
+ }
+}
+
+
+//-------------------------------------------------
+// add_element_primitives - add the primitive
+// for an element in the current state
+//-------------------------------------------------
+
+void render_target::add_element_primitives(render_primitive_list &list, const object_transform &xform, layout_element &element, int state, int blendmode)
+{
+ // if we're out of range, bail
+ if (state > element.maxstate())
+ return;
+ if (state < 0)
+ state = 0;
+
+ // get a pointer to the relevant texture
+ render_texture *texture = element.state_texture(state);
+ if (texture != NULL)
+ {
+ render_primitive *prim = list.alloc(render_primitive::QUAD);
+
+ // configure the basics
+ prim->color = xform.color;
+ prim->flags = PRIMFLAG_TEXORIENT(xform.orientation) | PRIMFLAG_BLENDMODE(blendmode) | PRIMFLAG_TEXFORMAT(texture->format());
+
+ // compute the bounds
+ INT32 width = render_round_nearest(xform.xscale);
+ INT32 height = render_round_nearest(xform.yscale);
+ set_render_bounds_wh(&prim->bounds, render_round_nearest(xform.xoffs), render_round_nearest(xform.yoffs), (float) width, (float) height);
+ if (xform.orientation & ORIENTATION_SWAP_XY)
+ ISWAP(width, height);
+ width = MIN(width, m_maxtexwidth);
+ height = MIN(height, m_maxtexheight);
+
+ // get the scaled texture and append it
+ bool clipped = true;
+ if (texture->get_scaled(width, height, prim->texture, list))
+ {
+ // compute the clip rect
+ render_bounds cliprect;
+ cliprect.x0 = render_round_nearest(xform.xoffs);
+ cliprect.y0 = render_round_nearest(xform.yoffs);
+ cliprect.x1 = render_round_nearest(xform.xoffs + xform.xscale);
+ cliprect.y1 = render_round_nearest(xform.yoffs + xform.yscale);
+ sect_render_bounds(&cliprect, &m_bounds);
+
+ // determine UV coordinates and apply clipping
+ prim->texcoords = oriented_texcoords[xform.orientation];
+ clipped = render_clip_quad(&prim->bounds, &cliprect, &prim->texcoords);
+ }
+
+ // add to the list or free if we're clipped out
+ list.append_or_return(*prim, clipped);
+ }
+}
+
+
+//-------------------------------------------------
+// map_point_internal - internal logic for
+// mapping points
+//-------------------------------------------------
+
+bool render_target::map_point_internal(INT32 target_x, INT32 target_y, render_container *container, float &mapped_x, float &mapped_y, const char *&mapped_input_tag, UINT32 &mapped_input_mask)
+{
+ // default to point not mapped
+ mapped_x = -1.0;
+ mapped_y = -1.0;
+ mapped_input_tag = NULL;
+ mapped_input_mask = 0;
+
+ // convert target coordinates to float
+ float target_fx = (float)target_x / m_width;
+ float target_fy = (float)target_y / m_height;
+
+ // explicitly check for the UI container
+ if (container != NULL && container == &m_manager.ui_container())
+ {
+ // this hit test went against the UI container
+ if (target_fx >= 0.0 && target_fx < 1.0 && target_fy >= 0.0 && target_fy < 1.0)
+ {
+ // this point was successfully mapped
+ mapped_x = target_fx;
+ mapped_y = target_fy;
+ return true;
+ }
+ return false;
+ }
+
+ // loop through each layer
+ for (item_layer layernum = ITEM_LAYER_FIRST; layernum < ITEM_LAYER_MAX; layernum++)
+ {
+ int blendmode;
+ item_layer layer = get_layer_and_blendmode(*m_curview, layernum, blendmode);
+ if (m_curview->layer_enabled(layer))
+ {
+ // iterate over items in the layer
+ for (layout_view::item *item = m_curview->first_item(layer); item != NULL; item = item->next())
+ {
+ bool checkit;
+
+ // if we're looking for a particular container, verify that we have the right one
+ if (container != NULL)
+ checkit = (item->screen() != NULL && &item->screen()->container() == container);
+
+ // otherwise, assume we're looking for an input
+ else
+ checkit = item->has_input();
+
+ // this target is worth looking at; now check the point
+ if (checkit && target_fx >= item->bounds().x0 && target_fx < item->bounds().x1 && target_fy >= item->bounds().y0 && target_fy < item->bounds().y1)
+ {
+ // point successfully mapped
+ mapped_x = (target_fx - item->bounds().x0) / (item->bounds().x1 - item->bounds().x0);
+ mapped_y = (target_fy - item->bounds().y0) / (item->bounds().y1 - item->bounds().y0);
+ mapped_input_tag = item->input_tag_and_mask(mapped_input_mask);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+
+//-------------------------------------------------
+// view_name - return the name of the indexed
+// view, or NULL if it doesn't exist
+//-------------------------------------------------
+
+layout_view *render_target::view_by_index(int index) const
+{
+ // scan the list of views within each layout, skipping those that don't apply
+ for (layout_file *file = m_filelist.first(); file != NULL; file = file->next())
+ for (layout_view *view = file->first_view(); view != NULL; view = view->next())
+ if (!(m_flags & RENDER_CREATE_NO_ART) || !view->has_art())
+ if (index-- == 0)
+ return view;
+ return NULL;
+}
+
+
+//-------------------------------------------------
+// view_index - return the index of the given
+// view
+//-------------------------------------------------
+
+int render_target::view_index(layout_view &targetview) const
+{
+ // find the first named match
+ int index = 0;
+
+ // scan the list of views within each layout, skipping those that don't apply
+ for (layout_file *file = m_filelist.first(); file != NULL; file = file->next())
+ for (layout_view *view = file->first_view(); view != NULL; view = view->next())
+ if (!(m_flags & RENDER_CREATE_NO_ART) || !view->has_art())
+ {
+ if (&targetview == view)
+ return index;
+ index++;
+ }
+ return 0;
+}
+
+
+//-------------------------------------------------
+// config_load - process config information
+//-------------------------------------------------
+
+void render_target::config_load(xml_data_node &targetnode)
+{
+ // find the view
+ const char *viewname = xml_get_attribute_string(&targetnode, "view", NULL);
+ if (viewname != NULL)
+ for (int viewnum = 0; viewnum < 1000; viewnum++)
+ {
+ const char *testname = view_name(viewnum);
+ if (testname == NULL)
+ break;
+ if (!strcmp(viewname, testname))
+ {
+ set_view(viewnum);
+ break;
+ }
+ }
+
+ // modify the artwork config
+ int tmpint = xml_get_attribute_int(&targetnode, "backdrops", -1);
+ if (tmpint == 0 || tmpint == 1)
+ set_backdrops_enabled(tmpint);
+
+ tmpint = xml_get_attribute_int(&targetnode, "overlays", -1);
+ if (tmpint == 0 || tmpint == 1)
+ set_overlays_enabled(tmpint);
+
+ tmpint = xml_get_attribute_int(&targetnode, "bezels", -1);
+ if (tmpint == 0 || tmpint == 1)
+ set_bezels_enabled(tmpint);
+
+ tmpint = xml_get_attribute_int(&targetnode, "cpanels", -1);
+ if (tmpint == 0 || tmpint == 1)
+ set_cpanels_enabled(tmpint);
+
+ tmpint = xml_get_attribute_int(&targetnode, "marquees", -1);
+ if (tmpint == 0 || tmpint == 1)
+ set_marquees_enabled(tmpint);
+
+ tmpint = xml_get_attribute_int(&targetnode, "zoom", -1);
+ if (tmpint == 0 || tmpint == 1)
+ set_zoom_to_screen(tmpint);
+
+ // apply orientation
+ tmpint = xml_get_attribute_int(&targetnode, "rotate", -1);
+ if (tmpint != -1)
+ {
+ if (tmpint == 90)
+ tmpint = ROT90;
+ else if (tmpint == 180)
+ tmpint = ROT180;
+ else if (tmpint == 270)
+ tmpint = ROT270;
+ else
+ tmpint = ROT0;
+ set_orientation(orientation_add(tmpint, orientation()));
+
+ // apply the opposite orientation to the UI
+ if (is_ui_target())
+ {
+ render_container::user_settings settings;
+ render_container &ui_container = m_manager.ui_container();
+
+ ui_container.get_user_settings(settings);
+ settings.m_orientation = orientation_add(orientation_reverse(tmpint), settings.m_orientation);
+ ui_container.set_user_settings(settings);
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// config_save - save our configuration, or
+// return false if we are the same as the default
+//-------------------------------------------------
+
+bool render_target::config_save(xml_data_node &targetnode)
+{
+ bool changed = false;
+
+ // output the basics
+ xml_set_attribute_int(&targetnode, "index", index());
+
+ // output the view
+ if (m_curview != m_base_view)
+ {
+ xml_set_attribute(&targetnode, "view", m_curview->name());
+ changed = true;
+ }
+
+ // output the layer config
+ if (m_layerconfig != m_base_layerconfig)
+ {
+ xml_set_attribute_int(&targetnode, "backdrops", m_layerconfig.backdrops_enabled());
+ xml_set_attribute_int(&targetnode, "overlays", m_layerconfig.overlays_enabled());
+ xml_set_attribute_int(&targetnode, "bezels", m_layerconfig.bezels_enabled());
+ xml_set_attribute_int(&targetnode, "cpanels", m_layerconfig.cpanels_enabled());
+ xml_set_attribute_int(&targetnode, "marquees", m_layerconfig.marquees_enabled());
+ xml_set_attribute_int(&targetnode, "zoom", m_layerconfig.zoom_to_screen());
+ changed = true;
+ }
+
+ // output rotation
+ if (m_orientation != m_base_orientation)
+ {
+ int rotate = 0;
+ if (orientation_add(ROT90, m_base_orientation) == m_orientation)
+ rotate = 90;
+ else if (orientation_add(ROT180, m_base_orientation) == m_orientation)
+ rotate = 180;
+ else if (orientation_add(ROT270, m_base_orientation) == m_orientation)
+ rotate = 270;
+ assert(rotate != 0);
+ xml_set_attribute_int(&targetnode, "rotate", rotate);
+ changed = true;
+ }
+
+ return changed;
+}
+
+
+//-------------------------------------------------
+// init_clear_extents - reset the extents list
+//-------------------------------------------------
+
+void render_target::init_clear_extents()
+{
+ m_clear_extents[0] = -m_height;
+ m_clear_extents[1] = 1;
+ m_clear_extents[2] = m_width;
+ m_clear_extent_count = 3;
+}
+
+
+//-------------------------------------------------
+// remove_clear_extent - remove a quad from the
+// list of stuff to clear, unless it overlaps
+// a previous quad
+//-------------------------------------------------
+
+bool render_target::remove_clear_extent(const render_bounds &bounds)
+{
+ INT32 *max = &m_clear_extents[MAX_CLEAR_EXTENTS];
+ INT32 *last = &m_clear_extents[m_clear_extent_count];
+ INT32 *ext = &m_clear_extents[0];
+ INT32 boundsx0 = ceil(bounds.x0);
+ INT32 boundsx1 = floor(bounds.x1);
+ INT32 boundsy0 = ceil(bounds.y0);
+ INT32 boundsy1 = floor(bounds.y1);
+ INT32 y0, y1 = 0;
+
+ // loop over Y extents
+ while (ext < last)
+ {
+ INT32 *linelast;
+
+ // first entry of each line should always be negative
+ assert(ext[0] < 0.0f);
+ y0 = y1;
+ y1 = y0 - ext[0];
+
+ // do we intersect this extent?
+ if (boundsy0 < y1 && boundsy1 > y0)
+ {
+ INT32 *xext;
+ INT32 x0, x1 = 0;
+
+ // split the top
+ if (y0 < boundsy0)
+ {
+ int diff = boundsy0 - y0;
+
+ // make a copy of this extent
+ memmove(&ext[ext[1] + 2], &ext[0], (last - ext) * sizeof(*ext));
+ last += ext[1] + 2;
+ assert_always(last < max, "Ran out of clear extents!\n");
+
+ // split the extent between pieces
+ ext[ext[1] + 2] = -(-ext[0] - diff);
+ ext[0] = -diff;
+
+ // advance to the new extent
+ y0 -= ext[0];
+ ext += ext[1] + 2;
+ y1 = y0 - ext[0];
+ }
+
+ // split the bottom
+ if (y1 > boundsy1)
+ {
+ int diff = y1 - boundsy1;
+
+ // make a copy of this extent
+ memmove(&ext[ext[1] + 2], &ext[0], (last - ext) * sizeof(*ext));
+ last += ext[1] + 2;
+ assert_always(last < max, "Ran out of clear extents!\n");
+
+ // split the extent between pieces
+ ext[ext[1] + 2] = -diff;
+ ext[0] = -(-ext[0] - diff);
+
+ // recompute y1
+ y1 = y0 - ext[0];
+ }
+
+ // now remove the X extent
+ linelast = &ext[ext[1] + 2];
+ xext = &ext[2];
+ while (xext < linelast)
+ {
+ x0 = x1;
+ x1 = x0 + xext[0];
+
+ // do we fully intersect this extent?
+ if (boundsx0 >= x0 && boundsx1 <= x1)
+ {
+ // yes; split it
+ memmove(&xext[2], &xext[0], (last - xext) * sizeof(*xext));
+ last += 2;
+ linelast += 2;
+ assert_always(last < max, "Ran out of clear extents!\n");
+
+ // split this extent into three parts
+ xext[0] = boundsx0 - x0;
+ xext[1] = boundsx1 - boundsx0;
+ xext[2] = x1 - boundsx1;
+
+ // recompute x1
+ x1 = boundsx1;
+ xext += 2;
+ }
+
+ // do we partially intersect this extent?
+ else if (boundsx0 < x1 && boundsx1 > x0)
+ goto abort;
+
+ // advance
+ xext++;
+
+ // do we partially intersect the next extent (which is a non-clear extent)?
+ if (xext < linelast)
+ {
+ x0 = x1;
+ x1 = x0 + xext[0];
+ if (boundsx0 < x1 && boundsx1 > x0)
+ goto abort;
+ xext++;
+ }
+ }
+
+ // update the count
+ ext[1] = linelast - &ext[2];
+ }
+
+ // advance to the next row
+ ext += 2 + ext[1];
+ }
+
+ // update the total count
+ m_clear_extent_count = last - &m_clear_extents[0];
+ return true;
+
+abort:
+ // update the total count even on a failure as we may have split extents
+ m_clear_extent_count = last - &m_clear_extents[0];
+ return false;
+}
+
+
+//-------------------------------------------------
+// add_clear_extents - add the accumulated
+// extents as a series of quads to clear
+//-------------------------------------------------
+
+void render_target::add_clear_extents(render_primitive_list &list)
+{
+ simple_list<render_primitive> clearlist;
+ INT32 *last = &m_clear_extents[m_clear_extent_count];
+ INT32 *ext = &m_clear_extents[0];
+ INT32 y0, y1 = 0;
+
+ // loop over all extents
+ while (ext < last)
+ {
+ INT32 *linelast = &ext[ext[1] + 2];
+ INT32 *xext = &ext[2];
+ INT32 x0, x1 = 0;
+
+ // first entry should always be negative
+ assert(ext[0] < 0);
+ y0 = y1;
+ y1 = y0 - ext[0];
+
+ // now remove the X extent
+ while (xext < linelast)
+ {
+ x0 = x1;
+ x1 = x0 + *xext++;
+
+ // only add entries for non-zero widths
+ if (x1 - x0 > 0)
+ {
+ render_primitive *prim = list.alloc(render_primitive::QUAD);
+ set_render_bounds_xy(&prim->bounds, (float)x0, (float)y0, (float)x1, (float)y1);
+ set_render_color(&prim->color, 1.0f, 0.0f, 0.0f, 0.0f);
+ prim->texture.base = NULL;
+ prim->flags = PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA);
+ clearlist.append(*prim);
+ }
+
+ // skip the non-clearing extent
+ x0 = x1;
+ x1 = x0 + *xext++;
+ }
+
+ // advance to the next part
+ ext += 2 + ext[1];
+ }
+
+ // we know that the first primitive in the list will be the global clip
+ // so we insert the clears immediately after
+ list.m_primlist.prepend_list(clearlist);
+}
+
+
+//-------------------------------------------------
+// add_clear_and_optimize_primitive_list -
+// optimize the primitive list
+//-------------------------------------------------
+
+void render_target::add_clear_and_optimize_primitive_list(render_primitive_list &list)
+{
+ // start with the assumption that we need to clear the whole screen
+ init_clear_extents();
+
+ // scan the list until we hit an intersection quad or a line
+ for (render_primitive *prim = list.first(); prim != NULL; prim = prim->next())
+ {
+ // switch off the type
+ switch (prim->type)
+ {
+ case render_primitive::LINE:
+ goto done;
+
+ case render_primitive::QUAD:
+ {
+ // stop when we hit an alpha texture
+ if (PRIMFLAG_GET_TEXFORMAT(prim->flags) == TEXFORMAT_ARGB32 || PRIMFLAG_GET_TEXFORMAT(prim->flags) == TEXFORMAT_PALETTEA16)
+ goto done;
+
+ // if this quad can't be cleanly removed from the extents list, we're done
+ if (!remove_clear_extent(prim->bounds))
+ goto done;
+
+ // change the blendmode on the first primitive to be NONE
+ if (PRIMFLAG_GET_BLENDMODE(prim->flags) == BLENDMODE_RGB_MULTIPLY)
+ {
+ // RGB multiply will multiply against 0, leaving nothing
+ set_render_color(&prim->color, 1.0f, 0.0f, 0.0f, 0.0f);
+ prim->texture.base = NULL;
+ prim->flags = (prim->flags & ~PRIMFLAG_BLENDMODE_MASK) | PRIMFLAG_BLENDMODE(BLENDMODE_NONE);
+ }
+ else
+ {
+ // for alpha or add modes, we will blend against 0 or add to 0; treat it like none
+ prim->flags = (prim->flags & ~PRIMFLAG_BLENDMODE_MASK) | PRIMFLAG_BLENDMODE(BLENDMODE_NONE);
+ }
+
+ // since alpha is disabled, premultiply the RGB values and reset the alpha to 1.0
+ prim->color.r *= prim->color.a;
+ prim->color.g *= prim->color.a;
+ prim->color.b *= prim->color.a;
+ prim->color.a = 1.0f;
+ break;
+ }
+
+ default:
+ throw emu_fatalerror("Unexpected primitive type");
+ }
+ }
+
+done:
+ // now add the extents to the clear list
+ add_clear_extents(list);
+}
+
+
+
+//**************************************************************************
+// CORE IMPLEMENTATION
+//**************************************************************************
+
+//-------------------------------------------------
+// render_manager - constructor
+//-------------------------------------------------
+
+render_manager::render_manager(running_machine &machine)
+ : m_machine(machine),
+ m_targetlist(machine.respool()),
+ m_ui_target(NULL),
+ m_live_textures(0),
+ m_texture_allocator(machine.respool()),
+ m_ui_container(auto_alloc(machine, render_container(*this))),
+ m_screen_container_list(machine.respool())
+{
+ // register callbacks
+ config_register(machine, "video", config_saveload_delegate(FUNC(render_manager::config_load), this), config_saveload_delegate(FUNC(render_manager::config_save), this));
+
+ // create one container per screen
+ for (screen_device *screen = machine.first_screen(); screen != NULL; screen = screen->next_screen())
+ screen->set_container(*container_alloc(screen));
+}
+
+
+//-------------------------------------------------
+// ~render_manager - destructor
+//-------------------------------------------------
+
+render_manager::~render_manager()
+{
+ // free all the containers since they may own textures
+ container_free(m_ui_container);
+ m_screen_container_list.reset();
+
+ // better not be any outstanding textures when we die
+ assert(m_live_textures == 0);
+}
+
+
+//-------------------------------------------------
+// is_live - return if the screen is 'live'
+//-------------------------------------------------
+
+bool render_manager::is_live(screen_device &screen) const
+{
+ // iterate over all live targets and or together their screen masks
+ for (render_target *target = m_targetlist.first(); target != NULL; target = target->next())
+ if (target->view_screens(target->view()).contains(screen))
+ return true;
+ return false;
+}
+
+
+//-------------------------------------------------
+// max_update_rate - return the smallest maximum
+// update rate across all targets
+//-------------------------------------------------
+
+float render_manager::max_update_rate() const
+{
+ // iterate over all live targets and or together their screen masks
+ float minimum = 0;
+ for (render_target *target = m_targetlist.first(); target != NULL; target = target->next())
+ if (target->max_update_rate() != 0)
+ {
+ if (minimum == 0)
+ minimum = target->max_update_rate();
+ else
+ minimum = MIN(target->max_update_rate(), minimum);
+ }
+
+ return minimum;
+}
+
+
+//-------------------------------------------------
+// target_alloc - allocate a new target
+//-------------------------------------------------
+
+render_target *render_manager::target_alloc(const char *layoutfile, UINT32 flags)
+{
+ return &m_targetlist.append(*auto_alloc(machine(), render_target(*this, layoutfile, flags)));
+}
+
+
+//-------------------------------------------------
+// target_free - free a target
+//-------------------------------------------------
+
+void render_manager::target_free(render_target *target)
+{
+ if (target != NULL)
+ m_targetlist.remove(*target);
+}
+
+
+//-------------------------------------------------
+// target_by_index - get a render_target by index
+//-------------------------------------------------
+
+render_target *render_manager::target_by_index(int index) const
+{
+ // count up the targets until we hit the requested index
+ for (render_target *target = m_targetlist.first(); target != NULL; target = target->next())
+ if (!target->hidden())
+ if (index-- == 0)
+ return target;
+ return NULL;
+}
+
+
+//-------------------------------------------------
+// ui_aspect - return the aspect ratio for UI
+// fonts
+//-------------------------------------------------
+
+float render_manager::ui_aspect()
+{
+ int orient = orientation_add(m_ui_target->orientation(), m_ui_container->orientation());
+
+ // based on the orientation of the target, compute height/width or width/height
+ float aspect;
+ if (!(orient & ORIENTATION_SWAP_XY))
+ aspect = (float)m_ui_target->height() / (float)m_ui_target->width();
+ else
+ aspect = (float)m_ui_target->width() / (float)m_ui_target->height();
+
+ // if we have a valid pixel aspect, apply that and return
+ if (m_ui_target->pixel_aspect() != 0.0f)
+ return aspect / m_ui_target->pixel_aspect();
+
+ // if not, clamp for extreme proportions
+ if (aspect < 0.66f)
+ aspect = 0.66f;
+ if (aspect > 1.5f)
+ aspect = 1.5f;
+ return aspect;
+}
+
+
+//-------------------------------------------------
+// texture_alloc - allocate a new texture
+//-------------------------------------------------
+
+render_texture *render_manager::texture_alloc(texture_scaler_func scaler, void *param)
+{
+ // allocate a new texture and reset it
+ render_texture *tex = m_texture_allocator.alloc();
+ tex->reset(*this, scaler, param);
+ m_live_textures++;
+ return tex;
+}
+
+
+//-------------------------------------------------
+// texture_free - release a texture
+//-------------------------------------------------
+
+void render_manager::texture_free(render_texture *texture)
+{
+ if (texture != NULL)
+ {
+ m_live_textures--;
+ texture->release();
+ }
+ m_texture_allocator.reclaim(texture);
+}
+
+
+//-------------------------------------------------
+// font_alloc - allocate a new font instance
+//-------------------------------------------------
+
+render_font *render_manager::font_alloc(const char *filename)
+{
+ return auto_alloc(machine(), render_font(*this, filename));
+}
+
+
+//-------------------------------------------------
+// font_free - release a font instance
+//-------------------------------------------------
+
+void render_manager::font_free(render_font *font)
+{
+ auto_free(machine(), font);
+}
+
+
+//-------------------------------------------------
+// invalidate_all - remove all refs to a
+// particular reference pointer
+//-------------------------------------------------
+
+void render_manager::invalidate_all(void *refptr)
+{
+ // permit NULL
+ if (refptr == NULL)
+ return;
+
+ // loop over targets
+ for (render_target *target = m_targetlist.first(); target != NULL; target = target->next())
+ target->invalidate_all(refptr);
+}
+
+
+//-------------------------------------------------
+// container_alloc - allocate a new container
+//-------------------------------------------------
+
+render_container *render_manager::container_alloc(screen_device *screen)
+{
+ render_container *container = auto_alloc(machine(), render_container(*this, screen));
+ if (screen != NULL)
+ m_screen_container_list.append(*container);
+ return container;
+}
+
+
+//-------------------------------------------------
+// container_free - release a container
+//-------------------------------------------------
+
+void render_manager::container_free(render_container *container)
+{
+ m_screen_container_list.detach(*container);
+ auto_free(machine(), container);
+}
+
+
+//-------------------------------------------------
+// config_load - read and apply data from the
+// configuration file
+//-------------------------------------------------
+
+void render_manager::config_load(int config_type, xml_data_node *parentnode)
+{
+ // we only care about game files
+ if (config_type != CONFIG_TYPE_GAME)
+ return;
+
+ // might not have any data
+ if (parentnode == NULL)
+ return;
+
+ // check the UI target
+ xml_data_node *uinode = xml_get_sibling(parentnode->child, "interface");
+ if (uinode != NULL)
+ {
+ render_target *target = target_by_index(xml_get_attribute_int(uinode, "target", 0));
+ if (target != NULL)
+ set_ui_target(*target);
+ }
+
+ // iterate over target nodes
+ for (xml_data_node *targetnode = xml_get_sibling(parentnode->child, "target"); targetnode; targetnode = xml_get_sibling(targetnode->next, "target"))
+ {
+ render_target *target = target_by_index(xml_get_attribute_int(targetnode, "index", -1));
+ if (target != NULL)
+ target->config_load(*targetnode);
+ }
+
+ // iterate over screen nodes
+ for (xml_data_node *screennode = xml_get_sibling(parentnode->child, "screen"); screennode; screennode = xml_get_sibling(screennode->next, "screen"))
+ {
+ int index = xml_get_attribute_int(screennode, "index", -1);
+ render_container *container = m_screen_container_list.find(index);
+ render_container::user_settings settings;
+
+ // fetch current settings
+ container->get_user_settings(settings);
+
+ // fetch color controls
+ settings.m_brightness = xml_get_attribute_float(screennode, "brightness", settings.m_brightness);
+ settings.m_contrast = xml_get_attribute_float(screennode, "contrast", settings.m_contrast);
+ settings.m_gamma = xml_get_attribute_float(screennode, "gamma", settings.m_gamma);
+
+ // fetch positioning controls
+ settings.m_xoffset = xml_get_attribute_float(screennode, "hoffset", settings.m_xoffset);
+ settings.m_xscale = xml_get_attribute_float(screennode, "hstretch", settings.m_xscale);
+ settings.m_yoffset = xml_get_attribute_float(screennode, "voffset", settings.m_yoffset);
+ settings.m_yscale = xml_get_attribute_float(screennode, "vstretch", settings.m_yscale);
+
+ // set the new values
+ container->set_user_settings(settings);
+ }
+}
+
+
+//-------------------------------------------------
+// config_save - save data to the configuration
+// file
+//-------------------------------------------------
+
+void render_manager::config_save(int config_type, xml_data_node *parentnode)
+{
+ // we only care about game files
+ if (config_type != CONFIG_TYPE_GAME)
+ return;
+
+ // write out the interface target
+ if (m_ui_target->index() != 0)
+ {
+ // create a node for it
+ xml_data_node *uinode = xml_add_child(parentnode, "interface", NULL);
+ if (uinode != NULL)
+ xml_set_attribute_int(uinode, "target", m_ui_target->index());
+ }
+
+ // iterate over targets
+ for (int targetnum = 0; targetnum < 1000; targetnum++)
+ {
+ // get this target and break when we fail
+ render_target *target = target_by_index(targetnum);
+ if (target == NULL)
+ break;
+
+ // create a node
+ xml_data_node *targetnode = xml_add_child(parentnode, "target", NULL);
+ if (targetnode != NULL && !target->config_save(*targetnode))
+ xml_delete_node(targetnode);
+ }
+
+ // iterate over screen containers
+ int scrnum = 0;
+ for (render_container *container = m_screen_container_list.first(); container != NULL; container = container->next(), scrnum++)
+ {
+ // create a node
+ xml_data_node *screennode = xml_add_child(parentnode, "screen", NULL);
+ if (screennode != NULL)
+ {
+ bool changed = false;
+
+ // output the basics
+ xml_set_attribute_int(screennode, "index", scrnum);
+
+ render_container::user_settings settings;
+ container->get_user_settings(settings);
+
+ // output the color controls
+ if (settings.m_brightness != machine().options().brightness())
+ {
+ xml_set_attribute_float(screennode, "brightness", settings.m_brightness);
+ changed = true;
+ }
+
+ if (settings.m_contrast != machine().options().contrast())
+ {
+ xml_set_attribute_float(screennode, "contrast", settings.m_contrast);
+ changed = true;
+ }
+
+ if (settings.m_gamma != machine().options().gamma())
+ {
+ xml_set_attribute_float(screennode, "gamma", settings.m_gamma);
+ changed = true;
+ }
+
+ // output the positioning controls
+ if (settings.m_xoffset != 0.0f)
+ {
+ xml_set_attribute_float(screennode, "hoffset", settings.m_xoffset);
+ changed = true;
+ }
+
+ if (settings.m_xscale != 1.0f)
+ {
+ xml_set_attribute_float(screennode, "hstretch", settings.m_xscale);
+ changed = true;
+ }
+
+ if (settings.m_yoffset != 0.0f)
+ {
+ xml_set_attribute_float(screennode, "voffset", settings.m_yoffset);
+ changed = true;
+ }
+
+ if (settings.m_yscale != 1.0f)
+ {
+ xml_set_attribute_float(screennode, "vstretch", settings.m_yscale);
+ changed = true;
+ }
+
+ // if nothing changed, kill the node
+ if (!changed)
+ xml_delete_node(screennode);
+ }
+ }
+}
diff --git a/trunk/src/emu/render.h b/trunk/src/emu/render.h
new file mode 100644
index 00000000000..d4679aaae42
--- /dev/null
+++ b/trunk/src/emu/render.h
@@ -0,0 +1,799 @@
+/***************************************************************************
+
+ render.h
+
+ Core rendering routines 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.
+
+****************************************************************************
+
+ Theory of operation
+ -------------------
+
+ A render "target" is described by 5 parameters:
+
+ - width = width, in pixels
+ - height = height, in pixels
+ - bpp = depth, in bits per pixel
+ - orientation = orientation of the target
+ - pixel_aspect = aspect ratio of the pixels
+
+ Width, height, and bpp are self-explanatory. The remaining parameters
+ need some additional explanation.
+
+ Regarding orientation, there are three orientations that need to be
+ dealt with: target orientation, UI orientation, and game orientation.
+ In the current model, the UI orientation tracks the target orientation
+ so that the UI is (in theory) facing the correct direction. The game
+ orientation is specified by the game driver and indicates how the
+ game and artwork are rotated.
+
+ Regarding pixel_aspect, this is the aspect ratio of the individual
+ pixels, not the aspect ratio of the screen. You can determine this by
+ dividing the aspect ratio of the screen by the aspect ratio of the
+ resolution. For example, a 4:3 screen displaying 640x480 gives a
+ pixel aspect ratio of (4/3)/(640/480) = 1.0, meaning the pixels are
+ square. That same screen displaying 1280x1024 would have a pixel
+ aspect ratio of (4/3)/(1280/1024) = 1.06666, meaning the pixels are
+ slightly wider than they are tall.
+
+ Artwork is always assumed to be a 1.0 pixel aspect ratio. The game
+ screens themselves can be variable aspect ratios.
+
+***************************************************************************/
+
+#ifndef __RENDER_H__
+#define __RENDER_H__
+
+#include "osdepend.h"
+
+#include <math.h>
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// texture formats
+enum
+{
+ TEXFORMAT_UNDEFINED = 0, // require a format to be specified
+ TEXFORMAT_PALETTE16, // 16bpp palettized, alpha ignored
+ TEXFORMAT_PALETTEA16, // 16bpp palettized, alpha respected
+ TEXFORMAT_RGB15, // 16bpp 5-5-5 RGB
+ TEXFORMAT_RGB32, // 32bpp 8-8-8 RGB
+ TEXFORMAT_ARGB32, // 32bpp 8-8-8-8 ARGB
+ TEXFORMAT_YUY16 // 16bpp 8-8 Y/Cb, Y/Cr in sequence
+};
+
+// blending modes
+enum
+{
+ BLENDMODE_NONE = 0, // no blending
+ BLENDMODE_ALPHA, // standard alpha blend
+ BLENDMODE_RGB_MULTIPLY, // apply source alpha to source pix, then multiply RGB values
+ BLENDMODE_ADD // apply source alpha to source pix, then add to destination
+};
+
+
+// render creation flags
+const UINT8 RENDER_CREATE_NO_ART = 0x01; // ignore any views that have art in them
+const UINT8 RENDER_CREATE_SINGLE_FILE = 0x02; // only load views from the file specified
+const UINT8 RENDER_CREATE_HIDDEN = 0x04; // don't make this target visible
+
+
+// flags for primitives
+const int PRIMFLAG_TEXORIENT_SHIFT = 0;
+const UINT32 PRIMFLAG_TEXORIENT_MASK = 15 << PRIMFLAG_TEXORIENT_SHIFT;
+
+const int PRIMFLAG_TEXFORMAT_SHIFT = 4;
+const UINT32 PRIMFLAG_TEXFORMAT_MASK = 15 << PRIMFLAG_TEXFORMAT_SHIFT;
+
+const int PRIMFLAG_BLENDMODE_SHIFT = 8;
+const UINT32 PRIMFLAG_BLENDMODE_MASK = 15 << PRIMFLAG_BLENDMODE_SHIFT;
+
+const int PRIMFLAG_ANTIALIAS_SHIFT = 12;
+const UINT32 PRIMFLAG_ANTIALIAS_MASK = 1 << PRIMFLAG_ANTIALIAS_SHIFT;
+
+const int PRIMFLAG_SCREENTEX_SHIFT = 13;
+const UINT32 PRIMFLAG_SCREENTEX_MASK = 1 << PRIMFLAG_SCREENTEX_SHIFT;
+
+const int PRIMFLAG_TEXWRAP_SHIFT = 14;
+const UINT32 PRIMFLAG_TEXWRAP_MASK = 1 << PRIMFLAG_TEXWRAP_SHIFT;
+
+const int PRIMFLAG_TEXSHADE_SHIFT = 15;
+const UINT32 PRIMFLAG_TEXSHADE_MASK = 3 << PRIMFLAG_TEXSHADE_SHIFT;
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+#define PRIMFLAG_TEXORIENT(x) ((x) << PRIMFLAG_TEXORIENT_SHIFT)
+#define PRIMFLAG_GET_TEXORIENT(x) (((x) & PRIMFLAG_TEXORIENT_MASK) >> PRIMFLAG_TEXORIENT_SHIFT)
+
+#define PRIMFLAG_TEXFORMAT(x) ((x) << PRIMFLAG_TEXFORMAT_SHIFT)
+#define PRIMFLAG_GET_TEXFORMAT(x) (((x) & PRIMFLAG_TEXFORMAT_MASK) >> PRIMFLAG_TEXFORMAT_SHIFT)
+
+#define PRIMFLAG_BLENDMODE(x) ((x) << PRIMFLAG_BLENDMODE_SHIFT)
+#define PRIMFLAG_GET_BLENDMODE(x) (((x) & PRIMFLAG_BLENDMODE_MASK) >> PRIMFLAG_BLENDMODE_SHIFT)
+
+#define PRIMFLAG_ANTIALIAS(x) ((x) << PRIMFLAG_ANTIALIAS_SHIFT)
+#define PRIMFLAG_GET_ANTIALIAS(x) (((x) & PRIMFLAG_ANTIALIAS_MASK) >> PRIMFLAG_ANTIALIAS_SHIFT)
+
+#define PRIMFLAG_SCREENTEX(x) ((x) << PRIMFLAG_SCREENTEX_SHIFT)
+#define PRIMFLAG_GET_SCREENTEX(x) (((x) & PRIMFLAG_SCREENTEX_MASK) >> PRIMFLAG_SCREENTEX_SHIFT)
+
+#define PRIMFLAG_TEXWRAP(x) ((x) << PRIMFLAG_TEXWRAP_SHIFT)
+#define PRIMFLAG_GET_TEXWRAP(x) (((x) & PRIMFLAG_TEXWRAP_MASK) >> PRIMFLAG_TEXWRAP_SHIFT)
+
+#define PRIMFLAG_TEXSHADE(x) ((x) << PRIMFLAG_TEXSHADE_SHIFT)
+#define PRIMFLAG_GET_TEXSHADE(x) (((x) & PRIMFLAG_TEXSHADE_MASK) >> PRIMFLAG_TEXSHADE_SHIFT)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// forward definitions
+class device_t;
+class screen_device;
+class render_container;
+class render_manager;
+typedef struct _xml_data_node xml_data_node;
+class render_font;
+struct object_transform;
+class layout_element;
+class layout_view;
+class layout_file;
+
+
+// texture scaling callback
+typedef void (*texture_scaler_func)(bitmap_t &dest, const bitmap_t &source, const rectangle &sbounds, void *param);
+
+
+// render_bounds - floating point bounding rectangle
+struct render_bounds
+{
+ float x0; // leftmost X coordinate
+ float y0; // topmost Y coordinate
+ float x1; // rightmost X coordinate
+ float y1; // bottommost Y coordinate
+};
+
+
+// render_color - floating point set of ARGB values
+struct render_color
+{
+ float a; // alpha component (0.0 = transparent, 1.0 = opaque)
+ float r; // red component (0.0 = none, 1.0 = max)
+ float g; // green component (0.0 = none, 1.0 = max)
+ float b; // blue component (0.0 = none, 1.0 = max)
+};
+
+
+// render_texuv - floating point set of UV texture coordinates
+struct render_texuv
+{
+ float u; // U coodinate (0.0-1.0)
+ float v; // V coordinate (0.0-1.0)
+};
+
+
+// render_quad_texuv - floating point set of UV texture coordinates
+struct render_quad_texuv
+{
+ render_texuv tl; // top-left UV coordinate
+ render_texuv tr; // top-right UV coordinate
+ render_texuv bl; // bottom-left UV coordinate
+ render_texuv br; // bottom-right UV coordinate
+};
+
+
+// render_texinfo - texture information
+struct render_texinfo
+{
+ void * base; // base of the data
+ UINT32 rowpixels; // pixels per row
+ UINT32 width; // width of the image
+ UINT32 height; // height of the image
+ const rgb_t * palette; // palette for PALETTE16 textures, LUTs for RGB15/RGB32
+ UINT32 seqid; // sequence ID
+};
+
+
+// ======================> render_screen_list
+
+// a render_screen_list is a list of screen_devices
+class render_screen_list
+{
+ // screen list item
+ class item
+ {
+ friend class simple_list<item>;
+ friend class render_screen_list;
+
+ public:
+ // construction/destruction
+ item(screen_device &screen)
+ : m_next(NULL),
+ m_screen(screen) { }
+
+ // state
+ item * m_next; // next screen in list
+ screen_device & m_screen; // reference to screen device
+ };
+
+public:
+ // construction/destruction
+ render_screen_list(resource_pool &pool = global_resource_pool)
+ : m_list(pool) { }
+
+ // getters
+ int count() const { return m_list.count(); }
+
+ // operations
+ void add(screen_device &screen) { m_list.append(*pool_alloc(m_list.pool(), item(screen))); }
+ void reset() { m_list.reset(); }
+
+ // query
+ bool contains(screen_device &screen) const
+ {
+ for (item *curitem = m_list.first(); curitem != NULL; curitem = curitem->m_next)
+ if (&curitem->m_screen == &screen) return true;
+ return false;
+ }
+
+private:
+ // internal state
+ simple_list<item> m_list;
+};
+
+
+// ======================> render_layer_config
+
+// render_layer_config - describes the state of layers
+class render_layer_config
+{
+ static const UINT8 ENABLE_BACKDROP = 0x01; // enable backdrop layers
+ static const UINT8 ENABLE_OVERLAY = 0x02; // enable overlay layers
+ static const UINT8 ENABLE_BEZEL = 0x04; // enable bezel layers
+ static const UINT8 ENABLE_CPANEL = 0x08; // enable cpanel layers
+ static const UINT8 ENABLE_MARQUEE = 0x10; // enable marquee layers
+ static const UINT8 ZOOM_TO_SCREEN = 0x20; // zoom to screen area by default
+ static const UINT8 ENABLE_SCREEN_OVERLAY = 0x40; // enable screen overlays
+ static const UINT8 DEFAULT = ENABLE_BACKDROP | ENABLE_OVERLAY | ENABLE_BEZEL | ENABLE_CPANEL | ENABLE_MARQUEE | ENABLE_SCREEN_OVERLAY;
+
+public:
+ render_layer_config()
+ : m_state(DEFAULT) { }
+
+ bool operator==(const render_layer_config &rhs) const { return m_state == rhs.m_state; }
+ bool operator!=(const render_layer_config &rhs) const { return m_state != rhs.m_state; }
+
+ bool backdrops_enabled() const { return ((m_state & ENABLE_BACKDROP) != 0); }
+ bool overlays_enabled() const { return ((m_state & ENABLE_OVERLAY) != 0); }
+ bool bezels_enabled() const { return ((m_state & ENABLE_BEZEL) != 0); }
+ bool cpanels_enabled() const { return ((m_state & ENABLE_CPANEL) != 0); }
+ bool marquees_enabled() const { return ((m_state & ENABLE_MARQUEE) != 0); }
+ bool screen_overlay_enabled() const { return ((m_state & ENABLE_SCREEN_OVERLAY) != 0); }
+ bool zoom_to_screen() const { return ((m_state & ZOOM_TO_SCREEN) != 0); }
+
+ render_layer_config &set_backdrops_enabled(bool enable) { if (enable) m_state |= ENABLE_BACKDROP; else m_state &= ~ENABLE_BACKDROP; return *this; }
+ render_layer_config &set_overlays_enabled(bool enable) { if (enable) m_state |= ENABLE_OVERLAY; else m_state &= ~ENABLE_OVERLAY; return *this; }
+ render_layer_config &set_bezels_enabled(bool enable) { if (enable) m_state |= ENABLE_BEZEL; else m_state &= ~ENABLE_BEZEL; return *this; }
+ render_layer_config &set_cpanels_enabled(bool enable) { if (enable) m_state |= ENABLE_CPANEL; else m_state &= ~ENABLE_CPANEL; return *this; }
+ render_layer_config &set_marquees_enabled(bool enable) { if (enable) m_state |= ENABLE_MARQUEE; else m_state &= ~ENABLE_MARQUEE; return *this; }
+ render_layer_config &set_screen_overlay_enabled(bool enable) { if (enable) m_state |= ENABLE_SCREEN_OVERLAY; else m_state &= ~ENABLE_SCREEN_OVERLAY; return *this; }
+ render_layer_config &set_zoom_to_screen(bool zoom) { if (zoom) m_state |= ZOOM_TO_SCREEN; else m_state &= ~ZOOM_TO_SCREEN; return *this; }
+
+private:
+ UINT8 m_state;
+};
+
+
+// ======================> render_primitive
+
+// render_primitive - a single low-level primitive for the rendering engine
+class render_primitive
+{
+ friend class simple_list<render_primitive>;
+
+public:
+ // render primitive types
+ enum primitive_type
+ {
+ INVALID = 0, // invalid type
+ LINE, // a single line
+ QUAD // a rectilinear quad
+ };
+
+ // getters
+ render_primitive *next() const { return m_next; }
+
+ // reset to prepare for re-use
+ void reset();
+
+ // public state
+ primitive_type type; // type of primitive
+ render_bounds bounds; // bounds or positions
+ render_color color; // RGBA values
+ UINT32 flags; // flags
+ float width; // width (for line primitives)
+ render_texinfo texture; // texture info (for quad primitives)
+ render_quad_texuv texcoords; // texture coordinates (for quad primitives)
+
+private:
+ // internal state
+ render_primitive * m_next; // pointer to next element
+};
+
+
+// ======================> render_primitive_list
+
+// render_primitive_list - an object containing a list head plus a lock
+class render_primitive_list
+{
+ friend class render_target;
+
+ // construction/destruction
+ render_primitive_list();
+ ~render_primitive_list();
+
+public:
+ // getters
+ render_primitive *first() const { return m_primlist.first(); }
+
+ // lock management
+ void acquire_lock() { osd_lock_acquire(m_lock); }
+ void release_lock() { osd_lock_release(m_lock); }
+
+ // reference management
+ void add_reference(void *refptr);
+ bool has_reference(void *refptr) const;
+
+private:
+ // helpers for our friends to manipulate the list
+ render_primitive *alloc(render_primitive::primitive_type type);
+ void release_all();
+ void append(render_primitive &prim) { append_or_return(prim, false); }
+ void append_or_return(render_primitive &prim, bool clipped);
+
+ // a reference is an abstract reference to an internal object of some sort
+ class reference
+ {
+ public:
+ reference *next() const { return m_next; }
+ reference * m_next; // link to the next reference
+ void * m_refptr; // reference pointer
+ };
+
+ // internal state
+ simple_list<render_primitive> m_primlist; // list of primitives
+ simple_list<reference> m_reflist; // list of references
+
+ fixed_allocator<render_primitive> m_primitive_allocator;// allocator for primitives
+ fixed_allocator<reference> m_reference_allocator; // allocator for references
+
+ osd_lock * m_lock; // lock to protect list accesses
+};
+
+
+// ======================> render_texture
+
+// a render_texture is used to track transformations when building an object list
+class render_texture
+{
+ friend resource_pool_object<render_texture>::~resource_pool_object();
+ friend class simple_list<render_texture>;
+ friend class fixed_allocator<render_texture>;
+ friend class render_manager;
+ friend class render_target;
+
+ // construction/destruction
+ render_texture();
+ ~render_texture();
+
+ // reset before re-use
+ void reset(render_manager &manager, texture_scaler_func scaler = NULL, void *param = NULL);
+
+ // release resources when freed
+ void release();
+
+public:
+ // getters
+ int format() const { return m_format; }
+
+ // configure the texture bitmap
+ void set_bitmap(bitmap_t *bitmap, const rectangle *sbounds, int format, palette_t *palette = NULL);
+
+ // generic high-quality bitmap scaler
+ static void hq_scale(bitmap_t &dest, const bitmap_t &source, const rectangle &sbounds, void *param);
+
+private:
+ // internal helpers
+ bool get_scaled(UINT32 dwidth, UINT32 dheight, render_texinfo &texinfo, render_primitive_list &primlist);
+ const rgb_t *get_adjusted_palette(render_container &container);
+
+ static const int MAX_TEXTURE_SCALES = 8;
+
+ // a scaled_texture contains a single scaled entry for a texture
+ struct scaled_texture
+ {
+ bitmap_t * bitmap; // final bitmap
+ UINT32 seqid; // sequence number
+ };
+
+ // internal state
+ render_manager * m_manager; // reference to our manager
+ render_texture * m_next; // next texture (for free list)
+ bitmap_t * m_bitmap; // pointer to the original bitmap
+ rectangle m_sbounds; // source bounds within the bitmap
+ palette_t * m_palette; // palette associated with the texture
+ int m_format; // format of the texture data
+ texture_scaler_func m_scaler; // scaling callback
+ void * m_param; // scaling callback parameter
+ UINT32 m_curseq; // current sequence number
+ scaled_texture m_scaled[MAX_TEXTURE_SCALES];// array of scaled variants of this texture
+ rgb_t * m_bcglookup; // dynamically allocated B/C/G lookup table
+ UINT32 m_bcglookup_entries; // number of B/C/G lookup entries allocated
+};
+
+
+// ======================> render_container
+
+// a render_container holds a list of items and an orientation for the entire collection
+class render_container
+{
+ friend resource_pool_object<render_container>::~resource_pool_object();
+ friend class simple_list<render_container>;
+ friend class render_manager;
+ friend class render_target;
+
+ // construction/destruction
+ render_container(render_manager &manager, screen_device *screen = NULL);
+ ~render_container();
+
+public:
+ // user settings describes the collected user-controllable settings
+ struct user_settings
+ {
+ // construction/destruction
+ user_settings();
+
+ // public state
+ int m_orientation; // orientation
+ float m_brightness; // brightness
+ float m_contrast; // contrast
+ float m_gamma; // gamma
+ float m_xscale; // horizontal scale factor
+ float m_yscale; // vertical scale factor
+ float m_xoffset; // horizontal offset
+ float m_yoffset; // vertical offset
+ };
+
+ // getters
+ render_container *next() const { return m_next; }
+ screen_device *screen() const { return m_screen; }
+ render_manager &manager() const { return m_manager; }
+ render_texture *overlay() const { return m_overlaytexture; }
+ int orientation() const { return m_user.m_orientation; }
+ float xscale() const { return m_user.m_xscale; }
+ float yscale() const { return m_user.m_yscale; }
+ float xoffset() const { return m_user.m_xoffset; }
+ float yoffset() const { return m_user.m_yoffset; }
+ bool is_empty() const { return (m_itemlist.count() == 0); }
+ void get_user_settings(user_settings &settings) const { settings = m_user; }
+
+ // setters
+ void set_overlay(bitmap_t *bitmap);
+ void set_user_settings(const user_settings &settings);
+
+ // empty the item list
+ void empty() { m_item_allocator.reclaim_all(m_itemlist); }
+
+ // add items to the list
+ void add_line(float x0, float y0, float x1, float y1, float width, rgb_t argb, UINT32 flags);
+ void add_quad(float x0, float y0, float x1, float y1, rgb_t argb, render_texture *texture, UINT32 flags);
+ void add_char(float x0, float y0, float height, float aspect, rgb_t argb, render_font &font, UINT16 ch);
+ void add_point(float x0, float y0, float diameter, rgb_t argb, UINT32 flags) { add_line(x0, y0, x0, y0, diameter, argb, flags); }
+ void add_rect(float x0, float y0, float x1, float y1, rgb_t argb, UINT32 flags) { add_quad(x0, y0, x1, y1, argb, NULL, flags); }
+
+ // brightness/contrast/gamma helpers
+ bool has_brightness_contrast_gamma_changes() const { return (m_user.m_brightness != 1.0f || m_user.m_contrast != 1.0f || m_user.m_gamma != 1.0f); }
+ UINT8 apply_brightness_contrast_gamma(UINT8 value);
+ float apply_brightness_contrast_gamma_fp(float value);
+ const rgb_t *bcg_lookup_table(int texformat, palette_t *palette = NULL);
+
+private:
+ // an item describes a high level primitive that is added to a container
+ class item
+ {
+ friend class render_container;
+ friend class simple_list<item>;
+
+ public:
+ // getters
+ item *next() const { return m_next; }
+ UINT8 type() const { return m_type; }
+ const render_bounds &bounds() const { return m_bounds; }
+ const render_color &color() const { return m_color; }
+ UINT32 flags() const { return m_flags; }
+ UINT32 internal() const { return m_internal; }
+ float width() const { return m_width; }
+ render_texture *texture() const { return m_texture; }
+
+ private:
+ // internal state
+ item * m_next; // pointer to the next element in the list
+ UINT8 m_type; // type of element
+ render_bounds m_bounds; // bounds of the element
+ render_color m_color; // RGBA factors
+ UINT32 m_flags; // option flags
+ UINT32 m_internal; // internal flags
+ float m_width; // width of the line (lines only)
+ render_texture * m_texture; // pointer to the source texture (quads only)
+ };
+
+ // generic screen overlay scaler
+ static void overlay_scale(bitmap_t &dest, const bitmap_t &source, const rectangle &sbounds, void *param);
+
+ // internal helpers
+ item *first_item() const { return m_itemlist.first(); }
+ item &add_generic(UINT8 type, float x0, float y0, float x1, float y1, rgb_t argb);
+ void recompute_lookups();
+ void update_palette();
+
+ // internal state
+ render_container * m_next; // the next container in the list
+ render_manager & m_manager; // reference back to the owning manager
+ simple_list<item> m_itemlist; // head of the item list
+ fixed_allocator<item> m_item_allocator; // free container items
+ screen_device * m_screen; // the screen device
+ user_settings m_user; // user settings
+ bitmap_t * m_overlaybitmap; // overlay bitmap
+ render_texture * m_overlaytexture; // overlay texture
+ palette_client * m_palclient; // client to the system palette
+ rgb_t m_bcglookup256[0x400]; // lookup table for brightness/contrast/gamma
+ rgb_t m_bcglookup32[0x80]; // lookup table for brightness/contrast/gamma
+ rgb_t m_bcglookup[0x10000]; // full palette lookup with bcg adjustements
+};
+
+
+// ======================> render_target
+
+// a render_target describes a surface that is being rendered to
+class render_target
+{
+ friend resource_pool_object<render_target>::~resource_pool_object();
+ friend class simple_list<render_target>;
+ friend class render_manager;
+
+ // construction/destruction
+ render_target(render_manager &manager, const char *layoutfile = NULL, UINT32 flags = 0);
+ ~render_target();
+
+public:
+ // getters
+ render_target *next() const { return m_next; }
+ render_manager &manager() const { return m_manager; }
+ UINT32 width() const { return m_width; }
+ UINT32 height() const { return m_height; }
+ float pixel_aspect() const { return m_pixel_aspect; }
+ float max_update_rate() const { return m_max_refresh; }
+ int orientation() const { return m_orientation; }
+ render_layer_config layer_config() const { return m_layerconfig; }
+ int view() const { return view_index(*m_curview); }
+ bool hidden() const { return ((m_flags & RENDER_CREATE_HIDDEN) != 0); }
+ bool is_ui_target() const;
+ int index() const;
+
+ // setters
+ void set_bounds(INT32 width, INT32 height, float pixel_aspect = 0);
+ void set_max_update_rate(float updates_per_second) { m_max_refresh = updates_per_second; }
+ void set_orientation(int orientation) { m_orientation = orientation; }
+ void set_view(int viewindex);
+ void set_max_texture_size(int maxwidth, int maxheight);
+
+ // layer config getters
+ bool backdrops_enabled() const { return m_layerconfig.backdrops_enabled(); }
+ bool overlays_enabled() const { return m_layerconfig.overlays_enabled(); }
+ bool bezels_enabled() const { return m_layerconfig.bezels_enabled(); }
+ bool cpanels_enabled() const { return m_layerconfig.cpanels_enabled(); }
+ bool marquees_enabled() const { return m_layerconfig.marquees_enabled(); }
+ bool screen_overlay_enabled() const { return m_layerconfig.screen_overlay_enabled(); }
+ bool zoom_to_screen() const { return m_layerconfig.zoom_to_screen(); }
+
+ // layer config setters
+ void set_backdrops_enabled(bool enable) { m_layerconfig.set_backdrops_enabled(enable); update_layer_config(); }
+ void set_overlays_enabled(bool enable) { m_layerconfig.set_overlays_enabled(enable); update_layer_config(); }
+ void set_bezels_enabled(bool enable) { m_layerconfig.set_bezels_enabled(enable); update_layer_config(); }
+ void set_cpanels_enabled(bool enable) { m_layerconfig.set_cpanels_enabled(enable); update_layer_config(); }
+ void set_marquees_enabled(bool enable) { m_layerconfig.set_marquees_enabled(enable); update_layer_config(); }
+ void set_screen_overlay_enabled(bool enable) { m_layerconfig.set_screen_overlay_enabled(enable); update_layer_config(); }
+ void set_zoom_to_screen(bool zoom) { m_layerconfig.set_zoom_to_screen(zoom); update_layer_config(); }
+
+ // view configuration helper
+ int configured_view(const char *viewname, int targetindex, int numtargets);
+
+ // view information
+ const char *view_name(int viewindex);
+ const render_screen_list &view_screens(int viewindex);
+
+ // bounds computations
+ void compute_visible_area(INT32 target_width, INT32 target_height, float target_pixel_aspect, int target_orientation, INT32 &visible_width, INT32 &visible_height);
+ void compute_minimum_size(INT32 &minwidth, INT32 &minheight);
+
+ // get a primitive list
+ render_primitive_list &get_primitives();
+
+ // hit testing
+ bool map_point_container(INT32 target_x, INT32 target_y, render_container &container, float &container_x, float &container_y);
+ bool map_point_input(INT32 target_x, INT32 target_y, const char *&input_tag, UINT32 &input_mask, float &input_x, float &input_y);
+
+ // reference tracking
+ void invalidate_all(void *refptr);
+
+ // debug containers
+ render_container *debug_alloc();
+ void debug_free(render_container &container);
+ void debug_top(render_container &container);
+
+private:
+ // internal helpers
+ void update_layer_config();
+ void load_layout_files(const char *layoutfile, bool singlefile);
+ bool load_layout_file(const char *dirname, const char *filename);
+ void add_container_primitives(render_primitive_list &list, const object_transform &xform, render_container &container, int blendmode);
+ void add_element_primitives(render_primitive_list &list, const object_transform &xform, layout_element &element, int state, int blendmode);
+ bool map_point_internal(INT32 target_x, INT32 target_y, render_container *container, float &mapped_x, float &mapped_y, const char *&mapped_input_tag, UINT32 &mapped_input_mask);
+
+ // config callbacks
+ void config_load(xml_data_node &targetnode);
+ bool config_save(xml_data_node &targetnode);
+
+ // view lookups
+ layout_view *view_by_index(int index) const;
+ int view_index(layout_view &view) const;
+
+ // optimized clearing
+ void init_clear_extents();
+ bool remove_clear_extent(const render_bounds &bounds);
+ void add_clear_extents(render_primitive_list &list);
+ void add_clear_and_optimize_primitive_list(render_primitive_list &list);
+
+ // constants
+ static const int NUM_PRIMLISTS = 3;
+ static const int MAX_CLEAR_EXTENTS = 1000;
+
+ // internal state
+ render_target * m_next; // link to next target
+ render_manager & m_manager; // reference to our owning manager
+ layout_view * m_curview; // current view
+ simple_list<layout_file> &m_filelist; // list of layout files
+ UINT32 m_flags; // creation flags
+ render_primitive_list m_primlist[NUM_PRIMLISTS]; // list of primitives
+ int m_listindex; // index of next primlist to use
+ INT32 m_width; // width in pixels
+ INT32 m_height; // height in pixels
+ render_bounds m_bounds; // bounds of the target
+ float m_pixel_aspect; // aspect ratio of individual pixels
+ float m_max_refresh; // maximum refresh rate, 0 or if none
+ int m_orientation; // orientation
+ render_layer_config m_layerconfig; // layer configuration
+ layout_view * m_base_view; // the view at the time of first frame
+ int m_base_orientation; // the orientation at the time of first frame
+ render_layer_config m_base_layerconfig; // the layer configuration at the time of first frame
+ int m_maxtexwidth; // maximum width of a texture
+ int m_maxtexheight; // maximum height of a texture
+ simple_list<render_container> m_debug_containers; // list of debug containers
+ INT32 m_clear_extent_count; // number of clear extents
+ INT32 m_clear_extents[MAX_CLEAR_EXTENTS]; // array of clear extents
+
+ static const render_screen_list s_empty_screen_list;
+};
+
+
+// ======================> render_manager
+
+// contains machine-global information and operations
+class render_manager
+{
+ friend class render_target;
+
+public:
+ // construction/destruction
+ render_manager(running_machine &machine);
+ ~render_manager();
+
+ // getters
+ running_machine &machine() const { return m_machine; }
+
+ // global queries
+ bool is_live(screen_device &screen) const;
+ float max_update_rate() const;
+
+ // targets
+ render_target *target_alloc(const char *layoutfile = NULL, UINT32 flags = 0);
+ void target_free(render_target *target);
+ render_target *first_target() const { return m_targetlist.first(); }
+ render_target *target_by_index(int index) const;
+
+ // UI targets
+ render_target &ui_target() const { assert(m_ui_target != NULL); return *m_ui_target; }
+ void set_ui_target(render_target &target) { m_ui_target = &target; }
+ float ui_aspect();
+
+ // UI containers
+ render_container &ui_container() const { assert(m_ui_container != NULL); return *m_ui_container; }
+
+ // textures
+ render_texture *texture_alloc(texture_scaler_func scaler = NULL, void *param = NULL);
+ void texture_free(render_texture *texture);
+
+ // fonts
+ render_font *font_alloc(const char *filename = NULL);
+ void font_free(render_font *font);
+
+ // reference tracking
+ void invalidate_all(void *refptr);
+
+private:
+ // containers
+ render_container *container_alloc(screen_device *screen = NULL);
+ void container_free(render_container *container);
+
+ // config callbacks
+ void config_load(int config_type, xml_data_node *parentnode);
+ void config_save(int config_type, xml_data_node *parentnode);
+
+ // internal state
+ running_machine & m_machine; // reference back to the machine
+
+ // array of live targets
+ simple_list<render_target> m_targetlist; // list of targets
+ render_target * m_ui_target; // current UI target
+
+ // texture lists
+ UINT32 m_live_textures; // number of live textures
+ fixed_allocator<render_texture> m_texture_allocator;// texture allocator
+
+ // containers for the UI and for screens
+ render_container * m_ui_container; // UI container
+ simple_list<render_container> m_screen_container_list; // list of containers for the screen
+};
+
+
+#endif // __RENDER_H__
diff --git a/trunk/src/emu/rendersw.c b/trunk/src/emu/rendersw.c
new file mode 100644
index 00000000000..31b3a6163af
--- /dev/null
+++ b/trunk/src/emu/rendersw.c
@@ -0,0 +1,2397 @@
+/***************************************************************************
+
+ rendersw.c
+
+ Software-only rasterization system.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+****************************************************************************
+
+ This file is not to be directly compiled. Rather, the OSD code should
+ #define the macros below and then #include this file to generate
+ rasterizers that are optimized for a given output format. See
+ windows/rendsoft.c for an example.
+
+***************************************************************************/
+
+
+
+/***************************************************************************
+ USAGE VERIFICATION
+***************************************************************************/
+
+#if !defined(FUNC_PREFIX)
+#error Must define FUNC_PREFIX!
+#endif
+
+#if !defined(PIXEL_TYPE)
+#error Must define PIXEL_TYPE!
+#endif
+
+#if !defined(SRCSHIFT_R) || !defined(SRCSHIFT_G) || !defined(SRCSHIFT_B)
+#error Must define SRCSHIFT_R/SRCSHIFT_G/SRCSHIFT_B!
+#endif
+
+#if !defined(DSTSHIFT_R) || !defined(DSTSHIFT_G) || !defined(DSTSHIFT_B)
+#error Must define DSTSHIFT_R/DSTSHIFT_G/DSTSHIFT_B!
+#endif
+
+#if !defined(NO_DEST_READ)
+#define NO_DEST_READ 0
+#endif
+
+#if !defined(BILINEAR_FILTER)
+#define BILINEAR_FILTER 0
+#endif
+
+
+
+/***************************************************************************
+ ONE-TIME-ONLY DEFINITIONS
+***************************************************************************/
+
+#ifndef FIRST_TIME
+#define FIRST_TIME
+
+#include "emucore.h"
+#include "eminline.h"
+#include "video/rgbutil.h"
+#include "render.h"
+
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define FSWAP(var1, var2) do { float temp = var1; var1 = var2; var2 = temp; } while (0)
+
+#define Tinten(intensity, col) \
+ MAKE_RGB((RGB_RED(col) * (intensity)) >> 8, (RGB_GREEN(col) * (intensity)) >> 8, (RGB_BLUE(col) * (intensity)) >> 8)
+
+#define IS_OPAQUE(a) (a >= (NO_DEST_READ ? 0.5f : 1.0f))
+#define IS_TRANSPARENT(a) (a < (NO_DEST_READ ? 0.5f : 0.0001f))
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _quad_setup_data quad_setup_data;
+struct _quad_setup_data
+{
+ INT32 dudx, dvdx, dudy, dvdy;
+ INT32 startu, startv;
+ INT32 startx, starty;
+ INT32 endx, endy;
+};
+
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+static UINT32 cosine_table[2049];
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ round_nearest - round to nearest in a
+ predictable way
+-------------------------------------------------*/
+
+INLINE float round_nearest(float f)
+{
+ return floor(f + 0.5f);
+}
+
+
+/*------------------------------------------------------------------------
+ ycc_to_rgb - convert YCC to RGB; the YCC pixel
+ contains Y in the LSB, Cb << 8, and Cr << 16
+ This actually a YCbCr conversion,
+ details my be found in chapter 6.4 ff of
+ http://softwarecommunity.intel.com/isn/downloads/softwareproducts/pdfs/346495.pdf
+ The document also contains the constants below as floats.
+--------------------------------------------------------------------------*/
+
+INLINE UINT8 clamp16_shift8(UINT32 x)
+{
+ return (((INT32) x < 0) ? 0 : (x > 65535 ? 255: x >> 8));
+}
+
+INLINE UINT32 ycc_to_rgb(UINT32 ycc)
+{
+ /* original equations:
+
+ C = Y - 16
+ D = Cb - 128
+ E = Cr - 128
+
+ R = clip(( 298 * C + 409 * E + 128) >> 8)
+ G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8)
+ B = clip(( 298 * C + 516 * D + 128) >> 8)
+
+ R = clip(( 298 * (Y - 16) + 409 * (Cr - 128) + 128) >> 8)
+ G = clip(( 298 * (Y - 16) - 100 * (Cb - 128) - 208 * (Cr - 128) + 128) >> 8)
+ B = clip(( 298 * (Y - 16) + 516 * (Cb - 128) + 128) >> 8)
+
+ R = clip(( 298 * Y - 298 * 16 + 409 * Cr - 409 * 128 + 128) >> 8)
+ G = clip(( 298 * Y - 298 * 16 - 100 * Cb + 100 * 128 - 208 * Cr + 208 * 128 + 128) >> 8)
+ B = clip(( 298 * Y - 298 * 16 + 516 * Cb - 516 * 128 + 128) >> 8)
+
+ R = clip(( 298 * Y - 298 * 16 + 409 * Cr - 409 * 128 + 128) >> 8)
+ G = clip(( 298 * Y - 298 * 16 - 100 * Cb + 100 * 128 - 208 * Cr + 208 * 128 + 128) >> 8)
+ B = clip(( 298 * Y - 298 * 16 + 516 * Cb - 516 * 128 + 128) >> 8)
+
+ Now combine constants:
+
+ R = clip(( 298 * Y + 409 * Cr - 56992) >> 8)
+ G = clip(( 298 * Y - 100 * Cb - 208 * Cr + 34784) >> 8)
+ B = clip(( 298 * Y + 516 * Cb - 70688) >> 8)
+
+ Define common = 298 * y - 56992. This will save one addition
+
+ R = clip(( common + 409 * Cr - 0) >> 8)
+ G = clip(( common - 100 * Cb - 208 * Cr + 91776) >> 8)
+ B = clip(( common + 516 * Cb - 13696) >> 8)
+
+ */
+ UINT8 y = ycc;
+ UINT8 cb = ycc >> 8;
+ UINT8 cr = ycc >> 16;
+ UINT32 r, g, b, common;
+
+ common = 298 * y - 56992;
+ r = (common + 409 * cr);
+ g = (common - 100 * cb - 208 * cr + 91776);
+ b = (common + 516 * cb - 13696);
+
+ /* Now clamp and shift back */
+ return MAKE_RGB(clamp16_shift8(r), clamp16_shift8(g), clamp16_shift8(b));
+}
+
+/*-------------------------------------------------
+ get_texel_palette16_nearest - return the
+ nearest neighbor texel from a palettized
+ 16bpp source
+-------------------------------------------------*/
+
+INLINE UINT32 get_texel_palette16_nearest(const render_texinfo *texture, INT32 curu, INT32 curv)
+{
+ const UINT16 *texbase = (const UINT16 *)texture->base + (curv >> 16) * texture->rowpixels + (curu >> 16);
+ return texture->palette[texbase[0]];
+}
+
+
+/*-------------------------------------------------
+ get_texel_palette16_bilinear - return a
+ bilinear filtered texel from a palettized
+ 16bpp source
+-------------------------------------------------*/
+
+INLINE UINT32 get_texel_palette16_bilinear(const render_texinfo *texture, INT32 curu, INT32 curv)
+{
+ const UINT16 *texbase = (const UINT16 *)texture->base;
+ rgb_t pix00, pix01, pix10, pix11;
+ INT32 u0, u1, v0, v1;
+
+ u0 = curu >> 16;
+ u1 = 1;
+ if (u0 < 0) u0 = u1 = 0;
+ else if (u0 + 1 >= texture->width) u0 = texture->width - 1, u1 = 0;
+ v0 = curv >> 16;
+ v1 = texture->rowpixels;
+ if (v0 < 0) v0 = v1 = 0;
+ else if (v0 + 1 >= texture->height) v0 = texture->height - 1, v1 = 0;
+
+ texbase += v0 * texture->rowpixels + u0;
+
+ pix00 = texture->palette[texbase[0]];
+ pix01 = texture->palette[texbase[u1]];
+ pix10 = texture->palette[texbase[v1]];
+ pix11 = texture->palette[texbase[u1 + v1]];
+ return rgb_bilinear_filter(pix00, pix01, pix10, pix11, curu >> 8, curv >> 8);
+}
+
+
+/*-------------------------------------------------
+ get_texel_palette16a_nearest - return the
+ nearest neighbor texel from a palettized
+ 16bpp source
+-------------------------------------------------*/
+
+INLINE UINT32 get_texel_palette16a_nearest(const render_texinfo *texture, INT32 curu, INT32 curv)
+{
+ const UINT16 *texbase = (const UINT16 *)texture->base + (curv >> 16) * texture->rowpixels + (curu >> 16);
+ return texture->palette[texbase[0]];
+}
+
+
+/*-------------------------------------------------
+ get_texel_palette16a_bilinear - return a
+ bilinear filtered texel from a palettized
+ 16bpp source
+-------------------------------------------------*/
+
+INLINE UINT32 get_texel_palette16a_bilinear(const render_texinfo *texture, INT32 curu, INT32 curv)
+{
+ const UINT16 *texbase = (const UINT16 *)texture->base;
+ rgb_t pix00, pix01, pix10, pix11;
+ INT32 u0, u1, v0, v1;
+
+ u0 = curu >> 16;
+ u1 = 1;
+ if (u0 < 0) u0 = u1 = 0;
+ else if (u0 + 1 >= texture->width) u0 = texture->width - 1, u1 = 0;
+ v0 = curv >> 16;
+ v1 = texture->rowpixels;
+ if (v0 < 0) v0 = v1 = 0;
+ else if (v0 + 1 >= texture->height) v0 = texture->height - 1, v1 = 0;
+
+ texbase += v0 * texture->rowpixels + u0;
+
+ pix00 = texture->palette[texbase[0]];
+ pix01 = texture->palette[texbase[u1]];
+ pix10 = texture->palette[texbase[v1]];
+ pix11 = texture->palette[texbase[u1 + v1]];
+ return rgba_bilinear_filter(pix00, pix01, pix10, pix11, curu >> 8, curv >> 8);
+}
+
+
+/*-------------------------------------------------
+ get_texel_rgb15_nearest - return the
+ nearest neighbor texel from a 15bpp RGB source
+-------------------------------------------------*/
+
+INLINE UINT32 get_texel_rgb15_nearest(const render_texinfo *texture, INT32 curu, INT32 curv)
+{
+ const UINT16 *texbase = (const UINT16 *)texture->base + (curv >> 16) * texture->rowpixels + (curu >> 16);
+ return texbase[0];
+}
+
+
+/*-------------------------------------------------
+ get_texel_rgb15_bilinear - return the
+ bilinear filtered texel from a 15bpp RGB
+ source
+-------------------------------------------------*/
+
+INLINE UINT32 get_texel_rgb15_bilinear(const render_texinfo *texture, INT32 curu, INT32 curv)
+{
+ const UINT16 *texbase = (const UINT16 *)texture->base;
+ rgb_t pix00, pix01, pix10, pix11, filtered;
+ INT32 u0, u1, v0, v1;
+
+ u0 = curu >> 16;
+ u1 = 1;
+ if (u0 < 0) u0 = u1 = 0;
+ else if (u0 + 1 >= texture->width) u0 = texture->width - 1, u1 = 0;
+ v0 = curv >> 16;
+ v1 = texture->rowpixels;
+ if (v0 < 0) v0 = v1 = 0;
+ else if (v0 + 1 >= texture->height) v0 = texture->height - 1, v1 = 0;
+
+ texbase += v0 * texture->rowpixels + u0;
+
+ pix00 = texbase[0];
+ pix01 = texbase[u1];
+ pix10 = texbase[v1];
+ pix11 = texbase[u1 + v1];
+ pix00 = ((pix00 & 0x7fe0) << 6) | (pix00 & 0x1f);
+ pix01 = ((pix01 & 0x7fe0) << 6) | (pix01 & 0x1f);
+ pix10 = ((pix10 & 0x7fe0) << 6) | (pix10 & 0x1f);
+ pix11 = ((pix11 & 0x7fe0) << 6) | (pix11 & 0x1f);
+ filtered = rgb_bilinear_filter(pix00, pix01, pix10, pix11, curu >> 8, curv >> 8);
+ return (filtered & 0x1f) | ((filtered & 0x1ff800) >> 6);
+}
+
+
+/*-------------------------------------------------
+ get_texel_yuy16_nearest - return the
+ nearest neighbor texel from a 16bpp YCbCr
+ source (pixel is returned as Cr-Cb-Y
+-------------------------------------------------*/
+
+INLINE UINT32 get_texel_yuy16_nearest(const render_texinfo *texture, INT32 curu, INT32 curv)
+{
+ const UINT16 *texbase = (const UINT16 *)texture->base + (curv >> 16) * texture->rowpixels + (curu >> 17) * 2;
+ return (texbase[(curu >> 16) & 1] >> 8) | ((texbase[0] & 0xff) << 8) | ((texbase[1] & 0xff) << 16);
+}
+
+
+/*-------------------------------------------------
+ get_texel_yuy16_bilinear - return the
+ nearest neighbor texel from a 16bpp YCbCr
+ source (pixel is returned as Cr-Cb-Y
+-------------------------------------------------*/
+
+INLINE UINT32 get_texel_yuy16_bilinear(const render_texinfo *texture, INT32 curu, INT32 curv)
+{
+ const UINT16 *texbase = (const UINT16 *)texture->base;
+ rgb_t pix00, pix01, pix10, pix11;
+ INT32 u0, u1, v0, v1;
+
+ u0 = curu >> 16;
+ u1 = 1;
+ if (u0 < 0) u0 = u1 = 0;
+ else if (u0 + 1 >= texture->width) u0 = texture->width - 1, u1 = 0;
+ v0 = curv >> 16;
+ v1 = texture->rowpixels;
+ if (v0 < 0) v0 = v1 = 0;
+ else if (v0 + 1 >= texture->height) v0 = texture->height - 1, v1 = 0;
+
+ texbase += v0 * texture->rowpixels + (u0 & ~1);
+
+ if ((curu & 0x10000) == 0)
+ {
+ rgb_t cbcr = ((texbase[0] & 0xff) << 8) | ((texbase[1] & 0xff) << 16);
+ pix00 = (texbase[0] >> 8) | cbcr;
+ pix01 = (texbase[u1] >> 8) | cbcr;
+ cbcr = ((texbase[v1 + 0] & 0xff) << 8) | ((texbase[v1 + 1] & 0xff) << 16);
+ pix10 = (texbase[v1 + 0] >> 8) | cbcr;
+ pix11 = (texbase[v1 + u1] >> 8) | cbcr;
+ }
+ else
+ {
+ rgb_t cbcr = ((texbase[0] & 0xff) << 8) | ((texbase[1] & 0xff) << 16);
+ pix00 = (texbase[1] >> 8) | cbcr;
+ if (u1 != 0)
+ {
+ cbcr = ((texbase[2] & 0xff) << 8) | ((texbase[3] & 0xff) << 16);
+ pix01 = (texbase[2] >> 8) | cbcr;
+ }
+ else
+ pix01 = pix00;
+ cbcr = ((texbase[v1 + 0] & 0xff) << 8) | ((texbase[v1 + 1] & 0xff) << 16);
+ pix10 = (texbase[v1 + 1] >> 8) | cbcr;
+ if (u1 != 0)
+ {
+ cbcr = ((texbase[v1 + 2] & 0xff) << 8) | ((texbase[v1 + 3] & 0xff) << 16);
+ pix11 = (texbase[v1 + 2] >> 8) | cbcr;
+ }
+ else
+ pix11 = pix10;
+ }
+ return rgb_bilinear_filter(pix00, pix01, pix10, pix11, curu >> 8, curv >> 8);
+}
+
+
+/*-------------------------------------------------
+ get_texel_rgb32_nearest - return the
+ nearest neighbor texel from a 32bpp RGB source
+-------------------------------------------------*/
+
+INLINE UINT32 get_texel_rgb32_nearest(const render_texinfo *texture, INT32 curu, INT32 curv)
+{
+ const UINT32 *texbase = (const UINT32 *)texture->base + (curv >> 16) * texture->rowpixels + (curu >> 16);
+ return texbase[0];
+}
+
+
+/*-------------------------------------------------
+ get_texel_rgb32_bilinear - return the
+ bilinear filtered texel from a 32bpp RGB
+ source
+-------------------------------------------------*/
+
+INLINE UINT32 get_texel_rgb32_bilinear(const render_texinfo *texture, INT32 curu, INT32 curv)
+{
+ const UINT32 *texbase = (const UINT32 *)texture->base;
+ rgb_t pix00, pix01, pix10, pix11;
+ INT32 u0, u1, v0, v1;
+
+ u0 = curu >> 16;
+ u1 = 1;
+ if (u0 < 0) u0 = u1 = 0;
+ else if (u0 + 1 >= texture->width) u0 = texture->width - 1, u1 = 0;
+ v0 = curv >> 16;
+ v1 = texture->rowpixels;
+ if (v0 < 0) v0 = v1 = 0;
+ else if (v0 + 1 >= texture->height) v0 = texture->height - 1, v1 = 0;
+
+ texbase += v0 * texture->rowpixels + u0;
+
+ pix00 = texbase[0];
+ pix01 = texbase[u1];
+ pix10 = texbase[v1];
+ pix11 = texbase[u1 + v1];
+ return rgb_bilinear_filter(pix00, pix01, pix10, pix11, curu >> 8, curv >> 8);
+}
+
+
+/*-------------------------------------------------
+ get_texel_argb32_nearest - return the
+ nearest neighbor texel from a 32bpp ARGB
+ source
+-------------------------------------------------*/
+
+INLINE UINT32 get_texel_argb32_nearest(const render_texinfo *texture, INT32 curu, INT32 curv)
+{
+ const UINT32 *texbase = (const UINT32 *)texture->base + (curv >> 16) * texture->rowpixels + (curu >> 16);
+ return texbase[0];
+}
+
+
+/*-------------------------------------------------
+ get_texel_argb32_bilinear - return the
+ bilinear filtered texel from a 32bpp ARGB
+ source
+-------------------------------------------------*/
+
+INLINE UINT32 get_texel_argb32_bilinear(const render_texinfo *texture, INT32 curu, INT32 curv)
+{
+ const UINT32 *texbase = (const UINT32 *)texture->base;
+ rgb_t pix00, pix01, pix10, pix11;
+ INT32 u0, u1, v0, v1;
+
+ u0 = curu >> 16;
+ u1 = 1;
+ if (u0 < 0) u0 = u1 = 0;
+ else if (u0 + 1 >= texture->width) u0 = texture->width - 1, u1 = 0;
+ v0 = curv >> 16;
+ v1 = texture->rowpixels;
+ if (v0 < 0) v0 = v1 = 0;
+ else if (v0 + 1 >= texture->height) v0 = texture->height - 1, v1 = 0;
+
+ texbase += v0 * texture->rowpixels + u0;
+
+ pix00 = texbase[0];
+ pix01 = texbase[u1];
+ pix10 = texbase[v1];
+ pix11 = texbase[u1 + v1];
+ return rgba_bilinear_filter(pix00, pix01, pix10, pix11, curu >> 8, curv >> 8);
+}
+
+
+#endif
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+/* source 15-bit pixels are in MAME standardized format */
+#define SOURCE15_R(pix) (((pix) >> (7 + SRCSHIFT_R)) & (0xf8 >> SRCSHIFT_R))
+#define SOURCE15_G(pix) (((pix) >> (2 + SRCSHIFT_G)) & (0xf8 >> SRCSHIFT_G))
+#if (SRCSHIFT_B < 3)
+#define SOURCE15_B(pix) (((pix) << (3 - SRCSHIFT_B)) & (0xf8 >> SRCSHIFT_B))
+#else
+#define SOURCE15_B(pix) (((pix) >> (SRCSHIFT_B - 3)) & (0xf8 >> SRCSHIFT_B))
+#endif
+
+/* source 32-bit pixels are in MAME standardized format */
+#define SOURCE32_R(pix) (((pix) >> (16 + SRCSHIFT_R)) & (0xff >> SRCSHIFT_R))
+#define SOURCE32_G(pix) (((pix) >> (8 + SRCSHIFT_G)) & (0xff >> SRCSHIFT_G))
+#define SOURCE32_B(pix) (((pix) >> (0 + SRCSHIFT_B)) & (0xff >> SRCSHIFT_B))
+
+/* destination pixels are written based on the values of the macros */
+#define DEST_ASSEMBLE_RGB(r,g,b) (((r) << DSTSHIFT_R) | ((g) << DSTSHIFT_G) | ((b) << DSTSHIFT_B))
+#define DEST_RGB_TO_PIXEL(r,g,b) DEST_ASSEMBLE_RGB((r) >> SRCSHIFT_R, (g) >> SRCSHIFT_G, (b) >> SRCSHIFT_B)
+
+/* destination pixel masks are based on the macros as well */
+#define DEST_R(pix) (((pix) >> DSTSHIFT_R) & (0xff >> SRCSHIFT_R))
+#define DEST_G(pix) (((pix) >> DSTSHIFT_G) & (0xff >> SRCSHIFT_G))
+#define DEST_B(pix) (((pix) >> DSTSHIFT_B) & (0xff >> SRCSHIFT_B))
+
+/* direct 15-bit source to destination pixel conversion */
+#define SOURCE15_TO_DEST(pix) DEST_ASSEMBLE_RGB(SOURCE15_R(pix), SOURCE15_G(pix), SOURCE15_B(pix))
+#ifndef VARIABLE_SHIFT
+#if (SRCSHIFT_R == 3) && (SRCSHIFT_G == 3) && (SRCSHIFT_B == 3) && (DSTSHIFT_R == 10) && (DSTSHIFT_G == 5) && (DSTSHIFT_B == 0)
+#undef SOURCE15_TO_DEST
+#define SOURCE15_TO_DEST(pix) (pix)
+#endif
+#endif
+
+/* direct 32-bit source to destination pixel conversion */
+#define SOURCE32_TO_DEST(pix) DEST_ASSEMBLE_RGB(SOURCE32_R(pix), SOURCE32_G(pix), SOURCE32_B(pix))
+#ifndef VARIABLE_SHIFT
+#if (SRCSHIFT_R == 0) && (SRCSHIFT_G == 0) && (SRCSHIFT_B == 0) && (DSTSHIFT_R == 16) && (DSTSHIFT_G == 8) && (DSTSHIFT_B == 0)
+#undef SOURCE32_TO_DEST
+#define SOURCE32_TO_DEST(pix) (pix)
+#endif
+#endif
+
+/* texel functions */
+#undef GET_TEXEL
+#if BILINEAR_FILTER
+#define GET_TEXEL(type) get_texel_##type##_##bilinear
+#else
+#define GET_TEXEL(type) get_texel_##type##_##nearest
+#endif
+
+
+
+/***************************************************************************
+ LINE RASTERIZERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ draw_aa_pixel - draw an antialiased pixel
+-------------------------------------------------*/
+
+INLINE void FUNC_PREFIX(draw_aa_pixel)(void *dstdata, UINT32 pitch, int x, int y, rgb_t col)
+{
+ UINT32 dpix, dr, dg, db;
+ PIXEL_TYPE *dest;
+
+ dest = (PIXEL_TYPE *)dstdata + y * pitch + x;
+ dpix = NO_DEST_READ ? 0 : *dest;
+ dr = SOURCE32_R(col) + DEST_R(dpix);
+ dg = SOURCE32_G(col) + DEST_G(dpix);
+ db = SOURCE32_B(col) + DEST_B(dpix);
+ dr = (dr | -(dr >> (8 - SRCSHIFT_R))) & (0xff >> SRCSHIFT_R);
+ dg = (dg | -(dg >> (8 - SRCSHIFT_G))) & (0xff >> SRCSHIFT_G);
+ db = (db | -(db >> (8 - SRCSHIFT_B))) & (0xff >> SRCSHIFT_B);
+ *dest = DEST_ASSEMBLE_RGB(dr, dg, db);
+}
+
+
+/*-------------------------------------------------
+ draw_line - draw a line or point
+-------------------------------------------------*/
+
+static void FUNC_PREFIX(draw_line)(const render_primitive *prim, void *dstdata, INT32 width, INT32 height, UINT32 pitch)
+{
+ int dx,dy,sx,sy,cx,cy,bwidth;
+ UINT8 a1;
+ int x1,x2,y1,y2;
+ UINT32 col;
+ int xx,yy;
+ int beam;
+
+ /* compute the start/end coordinates */
+ x1 = (int)(prim->bounds.x0 * 65536.0f);
+ y1 = (int)(prim->bounds.y0 * 65536.0f);
+ x2 = (int)(prim->bounds.x1 * 65536.0f);
+ y2 = (int)(prim->bounds.y1 * 65536.0f);
+
+ /* handle color and intensity */
+ col = MAKE_RGB((int)(255.0f * prim->color.r * prim->color.a), (int)(255.0f * prim->color.g * prim->color.a), (int)(255.0f * prim->color.b * prim->color.a));
+
+ if (PRIMFLAG_GET_ANTIALIAS(prim->flags))
+ {
+ /* build up the cosine table if we haven't yet */
+ if (cosine_table[0] == 0)
+ {
+ int entry;
+ for (entry = 0; entry <= 2048; entry++)
+ cosine_table[entry] = (int)((double)(1.0 / cos(atan((double)(entry) / 2048.0))) * 0x10000000 + 0.5);
+ }
+
+ beam = prim->width * 65536.0f;
+ if (beam < 0x00010000)
+ beam = 0x00010000;
+
+ /* draw an anti-aliased line */
+ dx = abs(x1 - x2);
+ dy = abs(y1 - y2);
+
+ if (dx >= dy)
+ {
+ sx = ((x1 <= x2) ? 1 : -1);
+ sy = (dy == 0) ? 0 : div_32x32_shift(y2 - y1, dx, 16);
+ if (sy < 0)
+ dy--;
+ x1 >>= 16;
+ xx = x2 >> 16;
+ bwidth = mul_32x32_hi(beam << 4, cosine_table[abs(sy) >> 5]);
+ y1 -= bwidth >> 1; /* start back half the diameter */
+ for (;;)
+ {
+ if (x1 >= 0 && x1 < width)
+ {
+ dx = bwidth; /* init diameter of beam */
+ dy = y1 >> 16;
+ if (dy >= 0 && dy < height)
+ FUNC_PREFIX(draw_aa_pixel)(dstdata, pitch, x1, dy, Tinten(0xff & (~y1 >> 8), col));
+ dy++;
+ dx -= 0x10000 - (0xffff & y1); /* take off amount plotted */
+ a1 = (dx >> 8) & 0xff; /* calc remainder pixel */
+ dx >>= 16; /* adjust to pixel (solid) count */
+ while (dx--) /* plot rest of pixels */
+ {
+ if (dy >= 0 && dy < height)
+ FUNC_PREFIX(draw_aa_pixel)(dstdata, pitch, x1, dy, col);
+ dy++;
+ }
+ if (dy >= 0 && dy < height)
+ FUNC_PREFIX(draw_aa_pixel)(dstdata, pitch, x1, dy, Tinten(a1,col));
+ }
+ if (x1 == xx) break;
+ x1 += sx;
+ y1 += sy;
+ }
+ }
+ else
+ {
+ sy = ((y1 <= y2) ? 1: -1);
+ sx = (dx == 0) ? 0 : div_32x32_shift(x2 - x1, dy, 16);
+ if (sx < 0)
+ dx--;
+ y1 >>= 16;
+ yy = y2 >> 16;
+ bwidth = mul_32x32_hi(beam << 4,cosine_table[abs(sx) >> 5]);
+ x1 -= bwidth >> 1; /* start back half the width */
+ for (;;)
+ {
+ if (y1 >= 0 && y1 < height)
+ {
+ dy = bwidth; /* calc diameter of beam */
+ dx = x1 >> 16;
+ if (dx >= 0 && dx < width)
+ FUNC_PREFIX(draw_aa_pixel)(dstdata, pitch, dx, y1, Tinten(0xff & (~x1 >> 8), col));
+ dx++;
+ dy -= 0x10000 - (0xffff & x1); /* take off amount plotted */
+ a1 = (dy >> 8) & 0xff; /* remainder pixel */
+ dy >>= 16; /* adjust to pixel (solid) count */
+ while (dy--) /* plot rest of pixels */
+ {
+ if (dx >= 0 && dx < width)
+ FUNC_PREFIX(draw_aa_pixel)(dstdata, pitch, dx, y1, col);
+ dx++;
+ }
+ if (dx >= 0 && dx < width)
+ FUNC_PREFIX(draw_aa_pixel)(dstdata, pitch, dx, y1, Tinten(a1, col));
+ }
+ if (y1 == yy) break;
+ y1 += sy;
+ x1 += sx;
+ }
+ }
+ }
+ else /* use good old Bresenham for non-antialiasing 980317 BW */
+ {
+ x1 = (x1 + 0x8000) >> 16;
+ y1 = (y1 + 0x8000) >> 16;
+ x2 = (x2 + 0x8000) >> 16;
+ y2 = (y2 + 0x8000) >> 16;
+
+ dx = abs(x1 - x2);
+ dy = abs(y1 - y2);
+ sx = (x1 <= x2) ? 1 : -1;
+ sy = (y1 <= y2) ? 1 : -1;
+ cx = dx / 2;
+ cy = dy / 2;
+
+ if (dx >= dy)
+ {
+ for (;;)
+ {
+ if (x1 >= 0 && x1 < width && y1 >= 0 && y1 < height)
+ FUNC_PREFIX(draw_aa_pixel)(dstdata, pitch, x1, y1, col);
+ if (x1 == x2) break;
+ x1 += sx;
+ cx -= dy;
+ if (cx < 0)
+ {
+ y1 += sy;
+ cx += dx;
+ }
+ }
+ }
+ else
+ {
+ for (;;)
+ {
+ if (x1 >= 0 && x1 < width && y1 >= 0 && y1 < height)
+ FUNC_PREFIX(draw_aa_pixel)(dstdata, pitch, x1, y1, col);
+ if (y1 == y2) break;
+ y1 += sy;
+ cy -= dx;
+ if (cy < 0)
+ {
+ x1 += sx;
+ cy += dy;
+ }
+ }
+ }
+ }
+}
+
+
+
+/***************************************************************************
+ RECT RASTERIZERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ draw_rect - draw a solid rectangle
+-------------------------------------------------*/
+
+static void FUNC_PREFIX(draw_rect)(const render_primitive *prim, void *dstdata, INT32 width, INT32 height, UINT32 pitch)
+{
+ render_bounds fpos = prim->bounds;
+ INT32 startx, starty, endx, endy;
+ INT32 x, y;
+
+ assert(fpos.x0 <= fpos.x1);
+ assert(fpos.y0 <= fpos.y1);
+
+ /* clamp to integers */
+ startx = round_nearest(fpos.x0);
+ starty = round_nearest(fpos.y0);
+ endx = round_nearest(fpos.x1);
+ endy = round_nearest(fpos.y1);
+
+ /* ensure we fit */
+ if (startx < 0) startx = 0;
+ if (startx >= width) startx = width;
+ if (endx < 0) endx = 0;
+ if (endx >= width) endx = width;
+ if (starty < 0) starty = 0;
+ if (starty >= height) starty = height;
+ if (endy < 0) endy = 0;
+ if (endy >= height) endy = height;
+
+ /* bail if nothing left */
+ if (fpos.x0 > fpos.x1 || fpos.y0 > fpos.y1)
+ return;
+
+ /* only support alpha and "none" blendmodes */
+ assert(PRIMFLAG_GET_BLENDMODE(prim->flags) == BLENDMODE_NONE ||
+ PRIMFLAG_GET_BLENDMODE(prim->flags) == BLENDMODE_ALPHA);
+
+ /* fast case: no alpha */
+ if (PRIMFLAG_GET_BLENDMODE(prim->flags) == BLENDMODE_NONE || IS_OPAQUE(prim->color.a))
+ {
+ UINT32 r = (UINT32)(256.0f * prim->color.r);
+ UINT32 g = (UINT32)(256.0f * prim->color.g);
+ UINT32 b = (UINT32)(256.0f * prim->color.b);
+ UINT32 pix;
+
+ /* clamp R,G,B to 0-256 range */
+ if (r > 0xff) { if ((INT32)r < 0) r = 0; else r = 0xff; }
+ if (g > 0xff) { if ((INT32)g < 0) g = 0; else g = 0xff; }
+ if (b > 0xff) { if ((INT32)b < 0) b = 0; else b = 0xff; }
+ pix = DEST_RGB_TO_PIXEL(r, g, b);
+
+ /* loop over rows */
+ for (y = starty; y < endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + startx;
+
+ /* loop over cols */
+ for (x = startx; x < endx; x++)
+ *dest++ = pix;
+ }
+ }
+
+ /* alpha and/or coloring case */
+ else if (!IS_TRANSPARENT(prim->color.a))
+ {
+ UINT32 rmask = DEST_RGB_TO_PIXEL(0xff,0x00,0x00);
+ UINT32 gmask = DEST_RGB_TO_PIXEL(0x00,0xff,0x00);
+ UINT32 bmask = DEST_RGB_TO_PIXEL(0x00,0x00,0xff);
+ UINT32 r = (UINT32)(256.0f * prim->color.r * prim->color.a);
+ UINT32 g = (UINT32)(256.0f * prim->color.g * prim->color.a);
+ UINT32 b = (UINT32)(256.0f * prim->color.b * prim->color.a);
+ UINT32 inva = (UINT32)(256.0f * (1.0f - prim->color.a));
+
+ /* clamp R,G,B and inverse A to 0-256 range */
+ if (r > 0xff) { if ((INT32)r < 0) r = 0; else r = 0xff; }
+ if (g > 0xff) { if ((INT32)g < 0) g = 0; else g = 0xff; }
+ if (b > 0xff) { if ((INT32)b < 0) b = 0; else b = 0xff; }
+ if (inva > 0x100) { if ((INT32)inva < 0) inva = 0; else inva = 0x100; }
+
+ /* pre-shift the RGBA pieces */
+ r = DEST_RGB_TO_PIXEL(r, 0, 0) << 8;
+ g = DEST_RGB_TO_PIXEL(0, g, 0) << 8;
+ b = DEST_RGB_TO_PIXEL(0, 0, b) << 8;
+
+ /* loop over rows */
+ for (y = starty; y < endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + startx;
+
+ /* loop over cols */
+ for (x = startx; x < endx; x++)
+ {
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 dr = (r + ((dpix & rmask) * inva)) & (rmask << 8);
+ UINT32 dg = (g + ((dpix & gmask) * inva)) & (gmask << 8);
+ UINT32 db = (b + ((dpix & bmask) * inva)) & (bmask << 8);
+ *dest++ = (dr | dg | db) >> 8;
+ }
+ }
+ }
+}
+
+
+
+/***************************************************************************
+ 16-BIT PALETTE RASTERIZERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ draw_quad_palette16_none - perform
+ rasterization of a 16bpp palettized texture
+-------------------------------------------------*/
+
+static void FUNC_PREFIX(draw_quad_palette16_none)(const render_primitive *prim, void *dstdata, UINT32 pitch, quad_setup_data *setup)
+{
+ INT32 dudx = setup->dudx;
+ INT32 dvdx = setup->dvdx;
+ INT32 endx = setup->endx;
+ INT32 x, y;
+
+ /* ensure all parameters are valid */
+ assert(prim->texture.palette != NULL);
+
+ /* fast case: no coloring, no alpha */
+ if (prim->color.r >= 1.0f && prim->color.g >= 1.0f && prim->color.b >= 1.0f && IS_OPAQUE(prim->color.a))
+ {
+ /* loop over rows */
+ for (y = setup->starty; y < setup->endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + setup->startx;
+ INT32 curu = setup->startu + (y - setup->starty) * setup->dudy;
+ INT32 curv = setup->startv + (y - setup->starty) * setup->dvdy;
+
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(palette16)(&prim->texture, curu, curv);
+ *dest++ = SOURCE32_TO_DEST(pix);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ }
+
+ /* coloring-only case */
+ else if (IS_OPAQUE(prim->color.a))
+ {
+ UINT32 sr = (UINT32)(256.0f * prim->color.r);
+ UINT32 sg = (UINT32)(256.0f * prim->color.g);
+ UINT32 sb = (UINT32)(256.0f * prim->color.b);
+
+ /* clamp R,G,B to 0-256 range */
+ if (sr > 0x100) { if ((INT32)sr < 0) sr = 0; else sr = 0x100; }
+ if (sg > 0x100) { if ((INT32)sg < 0) sg = 0; else sg = 0x100; }
+ if (sb > 0x100) { if ((INT32)sb < 0) sb = 0; else sb = 0x100; }
+
+ /* loop over rows */
+ for (y = setup->starty; y < setup->endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + setup->startx;
+ INT32 curu = setup->startu + (y - setup->starty) * setup->dudy;
+ INT32 curv = setup->startv + (y - setup->starty) * setup->dvdy;
+
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(palette16)(&prim->texture, curu, curv);
+ UINT32 r = (SOURCE32_R(pix) * sr) >> 8;
+ UINT32 g = (SOURCE32_G(pix) * sg) >> 8;
+ UINT32 b = (SOURCE32_B(pix) * sb) >> 8;
+
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ }
+
+ /* alpha and/or coloring case */
+ else if (!IS_TRANSPARENT(prim->color.a))
+ {
+ UINT32 sr = (UINT32)(256.0f * prim->color.r * prim->color.a);
+ UINT32 sg = (UINT32)(256.0f * prim->color.g * prim->color.a);
+ UINT32 sb = (UINT32)(256.0f * prim->color.b * prim->color.a);
+ UINT32 invsa = (UINT32)(256.0f * (1.0f - prim->color.a));
+
+ /* clamp R,G,B and inverse A to 0-256 range */
+ if (sr > 0x100) { if ((INT32)sr < 0) sr = 0; else sr = 0x100; }
+ if (sg > 0x100) { if ((INT32)sg < 0) sg = 0; else sg = 0x100; }
+ if (sb > 0x100) { if ((INT32)sb < 0) sb = 0; else sb = 0x100; }
+ if (invsa > 0x100) { if ((INT32)invsa < 0) invsa = 0; else invsa = 0x100; }
+
+ /* loop over rows */
+ for (y = setup->starty; y < setup->endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + setup->startx;
+ INT32 curu = setup->startu + (y - setup->starty) * setup->dudy;
+ INT32 curv = setup->startv + (y - setup->starty) * setup->dvdy;
+
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(palette16)(&prim->texture, curu, curv);
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 r = (SOURCE32_R(pix) * sr + DEST_R(dpix) * invsa) >> 8;
+ UINT32 g = (SOURCE32_G(pix) * sg + DEST_G(dpix) * invsa) >> 8;
+ UINT32 b = (SOURCE32_B(pix) * sb + DEST_B(dpix) * invsa) >> 8;
+
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ draw_quad_palette16_add - perform
+ rasterization of a 16bpp palettized texture
+-------------------------------------------------*/
+
+static void FUNC_PREFIX(draw_quad_palette16_add)(const render_primitive *prim, void *dstdata, UINT32 pitch, quad_setup_data *setup)
+{
+ INT32 dudx = setup->dudx;
+ INT32 dvdx = setup->dvdx;
+ INT32 endx = setup->endx;
+ INT32 x, y;
+
+ /* ensure all parameters are valid */
+ assert(prim->texture.palette != NULL);
+
+ /* fast case: no coloring, no alpha */
+ if (prim->color.r >= 1.0f && prim->color.g >= 1.0f && prim->color.b >= 1.0f && IS_OPAQUE(prim->color.a))
+ {
+ /* loop over rows */
+ for (y = setup->starty; y < setup->endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + setup->startx;
+ INT32 curu = setup->startu + (y - setup->starty) * setup->dudy;
+ INT32 curv = setup->startv + (y - setup->starty) * setup->dvdy;
+
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(palette16)(&prim->texture, curu, curv);
+ if ((pix & 0xffffff) != 0)
+ {
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 r = SOURCE32_R(pix) + DEST_R(dpix);
+ UINT32 g = SOURCE32_G(pix) + DEST_G(dpix);
+ UINT32 b = SOURCE32_B(pix) + DEST_B(dpix);
+ r = (r | -(r >> (8 - SRCSHIFT_R))) & (0xff >> SRCSHIFT_R);
+ g = (g | -(g >> (8 - SRCSHIFT_G))) & (0xff >> SRCSHIFT_G);
+ b = (b | -(b >> (8 - SRCSHIFT_B))) & (0xff >> SRCSHIFT_B);
+ *dest = DEST_ASSEMBLE_RGB(r, g, b);
+ }
+ dest++;
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ }
+
+ /* alpha and/or coloring case */
+ else
+ {
+ UINT32 sr = (UINT32)(256.0f * prim->color.r * prim->color.a);
+ UINT32 sg = (UINT32)(256.0f * prim->color.g * prim->color.a);
+ UINT32 sb = (UINT32)(256.0f * prim->color.b * prim->color.a);
+
+ /* clamp R,G,B and inverse A to 0-256 range */
+ if (sr > 0x100) { if ((INT32)sr < 0) sr = 0; else sr = 0x100; }
+ if (sg > 0x100) { if ((INT32)sg < 0) sg = 0; else sg = 0x100; }
+ if (sb > 0x100) { if ((INT32)sb < 0) sb = 0; else sb = 0x100; }
+
+ /* loop over rows */
+ for (y = setup->starty; y < setup->endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + setup->startx;
+ INT32 curu = setup->startu + (y - setup->starty) * setup->dudy;
+ INT32 curv = setup->startv + (y - setup->starty) * setup->dvdy;
+
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(palette16)(&prim->texture, curu, curv);
+ if ((pix & 0xffffff) != 0)
+ {
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 r = ((SOURCE32_R(pix) * sr) >> 8) + DEST_R(dpix);
+ UINT32 g = ((SOURCE32_G(pix) * sg) >> 8) + DEST_G(dpix);
+ UINT32 b = ((SOURCE32_B(pix) * sb) >> 8) + DEST_B(dpix);
+ r = (r | -(r >> (8 - SRCSHIFT_R))) & (0xff >> SRCSHIFT_R);
+ g = (g | -(g >> (8 - SRCSHIFT_G))) & (0xff >> SRCSHIFT_G);
+ b = (b | -(b >> (8 - SRCSHIFT_B))) & (0xff >> SRCSHIFT_B);
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ }
+ }
+}
+
+
+
+/***************************************************************************
+ 16-BIT ALPHA PALETTE RASTERIZERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ draw_quad_palettea16_alpha - perform
+ rasterization using standard alpha blending
+-------------------------------------------------*/
+
+static void FUNC_PREFIX(draw_quad_palettea16_alpha)(const render_primitive *prim, void *dstdata, UINT32 pitch, quad_setup_data *setup)
+{
+ INT32 dudx = setup->dudx;
+ INT32 dvdx = setup->dvdx;
+ INT32 endx = setup->endx;
+ INT32 x, y;
+
+ /* ensure all parameters are valid */
+ assert(prim->texture.palette != NULL);
+
+ /* fast case: no coloring, no alpha */
+ if (prim->color.r >= 1.0f && prim->color.g >= 1.0f && prim->color.b >= 1.0f && IS_OPAQUE(prim->color.a))
+ {
+ /* loop over rows */
+ for (y = setup->starty; y < setup->endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + setup->startx;
+ INT32 curu = setup->startu + (y - setup->starty) * setup->dudy;
+ INT32 curv = setup->startv + (y - setup->starty) * setup->dvdy;
+
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(palette16a)(&prim->texture, curu, curv);
+ UINT32 ta = pix >> 24;
+ if (ta != 0)
+ {
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 invta = 0x100 - ta;
+ UINT32 r = (SOURCE32_R(pix) * ta + DEST_R(dpix) * invta) >> 8;
+ UINT32 g = (SOURCE32_G(pix) * ta + DEST_G(dpix) * invta) >> 8;
+ UINT32 b = (SOURCE32_B(pix) * ta + DEST_B(dpix) * invta) >> 8;
+
+ *dest = DEST_ASSEMBLE_RGB(r, g, b);
+ }
+ dest++;
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ }
+
+ /* alpha and/or coloring case */
+ else
+ {
+ UINT32 sr = (UINT32)(256.0f * prim->color.r);
+ UINT32 sg = (UINT32)(256.0f * prim->color.g);
+ UINT32 sb = (UINT32)(256.0f * prim->color.b);
+ UINT32 sa = (UINT32)(256.0f * prim->color.a);
+
+ /* clamp R,G,B and inverse A to 0-256 range */
+ if (sr > 0x100) { if ((INT32)sr < 0) sr = 0; else sr = 0x100; }
+ if (sg > 0x100) { if ((INT32)sg < 0) sg = 0; else sg = 0x100; }
+ if (sb > 0x100) { if ((INT32)sb < 0) sb = 0; else sb = 0x100; }
+ if (sa > 0x100) { if ((INT32)sa < 0) sa = 0; else sa = 0x100; }
+
+ /* loop over rows */
+ for (y = setup->starty; y < setup->endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + setup->startx;
+ INT32 curu = setup->startu + (y - setup->starty) * setup->dudy;
+ INT32 curv = setup->startv + (y - setup->starty) * setup->dvdy;
+
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(palette16a)(&prim->texture, curu, curv);
+ UINT32 ta = (pix >> 24) * sa;
+ if (ta != 0)
+ {
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 invsta = (0x10000 - ta) << 8;
+ UINT32 r = (SOURCE32_R(pix) * sr * ta + DEST_R(dpix) * invsta) >> 24;
+ UINT32 g = (SOURCE32_G(pix) * sg * ta + DEST_G(dpix) * invsta) >> 24;
+ UINT32 b = (SOURCE32_B(pix) * sb * ta + DEST_B(dpix) * invsta) >> 24;
+
+ *dest = DEST_ASSEMBLE_RGB(r, g, b);
+ }
+ dest++;
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ }
+}
+
+
+
+/***************************************************************************
+ 16-BIT YUY RASTERIZERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ draw_quad_yuy16_none - perform
+ rasterization of a 16bpp YUY image
+-------------------------------------------------*/
+
+static void FUNC_PREFIX(draw_quad_yuy16_none)(const render_primitive *prim, void *dstdata, UINT32 pitch, quad_setup_data *setup)
+{
+ const rgb_t *palbase = prim->texture.palette;
+ INT32 dudx = setup->dudx;
+ INT32 dvdx = setup->dvdx;
+ INT32 endx = setup->endx;
+ INT32 x, y;
+
+ /* fast case: no coloring, no alpha */
+ if (prim->color.r >= 1.0f && prim->color.g >= 1.0f && prim->color.b >= 1.0f && IS_OPAQUE(prim->color.a))
+ {
+ /* loop over rows */
+ for (y = setup->starty; y < setup->endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + setup->startx;
+ INT32 curu = setup->startu + (y - setup->starty) * setup->dudy;
+ INT32 curv = setup->startv + (y - setup->starty) * setup->dvdy;
+
+ /* no lookup case */
+ if (palbase == NULL)
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = ycc_to_rgb(GET_TEXEL(yuy16)(&prim->texture, curu, curv));
+ *dest++ = SOURCE32_TO_DEST(pix);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+
+ /* lookup case */
+ else
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = ycc_to_rgb(GET_TEXEL(yuy16)(&prim->texture, curu, curv));
+ *dest++ = SOURCE32_TO_DEST(pix);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ }
+ }
+
+ /* coloring-only case */
+ else if (IS_OPAQUE(prim->color.a))
+ {
+ UINT32 sr = (UINT32)(256.0f * prim->color.r);
+ UINT32 sg = (UINT32)(256.0f * prim->color.g);
+ UINT32 sb = (UINT32)(256.0f * prim->color.b);
+
+ /* clamp R,G,B to 0-256 range */
+ if (sr > 0x100) { if ((INT32)sr < 0) sr = 0; else sr = 0x100; }
+ if (sg > 0x100) { if ((INT32)sg < 0) sg = 0; else sg = 0x100; }
+ if (sb > 0x100) { if ((INT32)sb < 0) sb = 0; else sb = 0x100; }
+
+ /* loop over rows */
+ for (y = setup->starty; y < setup->endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + setup->startx;
+ INT32 curu = setup->startu + (y - setup->starty) * setup->dudy;
+ INT32 curv = setup->startv + (y - setup->starty) * setup->dvdy;
+
+ /* no lookup case */
+ if (palbase == NULL)
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = ycc_to_rgb(GET_TEXEL(yuy16)(&prim->texture, curu, curv));
+ UINT32 r = (SOURCE32_R(pix) * sr) >> 8;
+ UINT32 g = (SOURCE32_G(pix) * sg) >> 8;
+ UINT32 b = (SOURCE32_B(pix) * sb) >> 8;
+
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+
+ /* lookup case */
+ else
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = ycc_to_rgb(GET_TEXEL(yuy16)(&prim->texture, curu, curv));
+ UINT32 r = (SOURCE32_R(pix) * sr) >> 8;
+ UINT32 g = (SOURCE32_G(pix) * sg) >> 8;
+ UINT32 b = (SOURCE32_B(pix) * sb) >> 8;
+
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ }
+ }
+
+ /* alpha and/or coloring case */
+ else if (!IS_TRANSPARENT(prim->color.a))
+ {
+ UINT32 sr = (UINT32)(256.0f * prim->color.r * prim->color.a);
+ UINT32 sg = (UINT32)(256.0f * prim->color.g * prim->color.a);
+ UINT32 sb = (UINT32)(256.0f * prim->color.b * prim->color.a);
+ UINT32 invsa = (UINT32)(256.0f * (1.0f - prim->color.a));
+
+ /* clamp R,G,B and inverse A to 0-256 range */
+ if (sr > 0x100) { if ((INT32)sr < 0) sr = 0; else sr = 0x100; }
+ if (sg > 0x100) { if ((INT32)sg < 0) sg = 0; else sg = 0x100; }
+ if (sb > 0x100) { if ((INT32)sb < 0) sb = 0; else sb = 0x100; }
+ if (invsa > 0x100) { if ((INT32)invsa < 0) invsa = 0; else invsa = 0x100; }
+
+ /* loop over rows */
+ for (y = setup->starty; y < setup->endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + setup->startx;
+ INT32 curu = setup->startu + (y - setup->starty) * setup->dudy;
+ INT32 curv = setup->startv + (y - setup->starty) * setup->dvdy;
+
+ /* no lookup case */
+ if (palbase == NULL)
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = ycc_to_rgb(GET_TEXEL(yuy16)(&prim->texture, curu, curv));
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 r = (SOURCE32_R(pix) * sr + DEST_R(dpix) * invsa) >> 8;
+ UINT32 g = (SOURCE32_G(pix) * sg + DEST_G(dpix) * invsa) >> 8;
+ UINT32 b = (SOURCE32_B(pix) * sb + DEST_B(dpix) * invsa) >> 8;
+
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+
+ /* lookup case */
+ else
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = ycc_to_rgb(GET_TEXEL(yuy16)(&prim->texture, curu, curv));
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 r = (SOURCE32_R(pix) * sr + DEST_R(dpix) * invsa) >> 8;
+ UINT32 g = (SOURCE32_G(pix) * sg + DEST_G(dpix) * invsa) >> 8;
+ UINT32 b = (SOURCE32_B(pix) * sb + DEST_B(dpix) * invsa) >> 8;
+
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ }
+ }
+}
+
+
+/***************************************************************************
+ 15-BIT RGB QUAD RASTERIZERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ draw_quad_rgb15 - perform rasterization of
+ a 15bpp RGB texture
+-------------------------------------------------*/
+
+static void FUNC_PREFIX(draw_quad_rgb15)(const render_primitive *prim, void *dstdata, UINT32 pitch, quad_setup_data *setup)
+{
+ const rgb_t *palbase = prim->texture.palette;
+ INT32 dudx = setup->dudx;
+ INT32 dvdx = setup->dvdx;
+ INT32 endx = setup->endx;
+ INT32 x, y;
+
+ /* fast case: no coloring, no alpha */
+ if (prim->color.r >= 1.0f && prim->color.g >= 1.0f && prim->color.b >= 1.0f && IS_OPAQUE(prim->color.a))
+ {
+ /* loop over rows */
+ for (y = setup->starty; y < setup->endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + setup->startx;
+ INT32 curu = setup->startu + (y - setup->starty) * setup->dudy;
+ INT32 curv = setup->startv + (y - setup->starty) * setup->dvdy;
+
+ /* no lookup case */
+ if (palbase == NULL)
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(rgb15)(&prim->texture, curu, curv);
+ *dest++ = SOURCE15_TO_DEST(pix);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+
+ /* lookup case */
+ else
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(rgb15)(&prim->texture, curu, curv);
+ UINT32 r = palbase[(pix >> 10) & 0x1f] >> SRCSHIFT_R;
+ UINT32 g = palbase[(pix >> 5) & 0x1f] >> SRCSHIFT_G;
+ UINT32 b = palbase[(pix >> 0) & 0x1f] >> SRCSHIFT_B;
+
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ }
+ }
+
+ /* coloring-only case */
+ else if (IS_OPAQUE(prim->color.a))
+ {
+ UINT32 sr = (UINT32)(256.0f * prim->color.r);
+ UINT32 sg = (UINT32)(256.0f * prim->color.g);
+ UINT32 sb = (UINT32)(256.0f * prim->color.b);
+
+ /* clamp R,G,B to 0-256 range */
+ if (sr > 0x100) { if ((INT32)sr < 0) sr = 0; else sr = 0x100; }
+ if (sg > 0x100) { if ((INT32)sg < 0) sg = 0; else sg = 0x100; }
+ if (sb > 0x100) { if ((INT32)sb < 0) sb = 0; else sb = 0x100; }
+
+ /* loop over rows */
+ for (y = setup->starty; y < setup->endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + setup->startx;
+ INT32 curu = setup->startu + (y - setup->starty) * setup->dudy;
+ INT32 curv = setup->startv + (y - setup->starty) * setup->dvdy;
+
+ /* no lookup case */
+ if (palbase == NULL)
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(rgb15)(&prim->texture, curu, curv);
+ UINT32 r = (SOURCE15_R(pix) * sr) >> 8;
+ UINT32 g = (SOURCE15_G(pix) * sg) >> 8;
+ UINT32 b = (SOURCE15_B(pix) * sb) >> 8;
+
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+
+ /* lookup case */
+ else
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(rgb15)(&prim->texture, curu, curv);
+ UINT32 r = (palbase[(pix >> 10) & 0x1f] * sr) >> (8 + SRCSHIFT_R);
+ UINT32 g = (palbase[(pix >> 5) & 0x1f] * sg) >> (8 + SRCSHIFT_G);
+ UINT32 b = (palbase[(pix >> 0) & 0x1f] * sb) >> (8 + SRCSHIFT_B);
+
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ }
+ }
+
+ /* alpha and/or coloring case */
+ else if (!IS_TRANSPARENT(prim->color.a))
+ {
+ UINT32 sr = (UINT32)(256.0f * prim->color.r * prim->color.a);
+ UINT32 sg = (UINT32)(256.0f * prim->color.g * prim->color.a);
+ UINT32 sb = (UINT32)(256.0f * prim->color.b * prim->color.a);
+ UINT32 invsa = (UINT32)(256.0f * (1.0f - prim->color.a));
+
+ /* clamp R,G,B and inverse A to 0-256 range */
+ if (sr > 0x100) { if ((INT32)sr < 0) sr = 0; else sr = 0x100; }
+ if (sg > 0x100) { if ((INT32)sg < 0) sg = 0; else sg = 0x100; }
+ if (sb > 0x100) { if ((INT32)sb < 0) sb = 0; else sb = 0x100; }
+ if (invsa > 0x100) { if ((INT32)invsa < 0) invsa = 0; else invsa = 0x100; }
+
+ /* loop over rows */
+ for (y = setup->starty; y < setup->endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + setup->startx;
+ INT32 curu = setup->startu + (y - setup->starty) * setup->dudy;
+ INT32 curv = setup->startv + (y - setup->starty) * setup->dvdy;
+
+ /* no lookup case */
+ if (palbase == NULL)
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(rgb15)(&prim->texture, curu, curv);
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 r = (SOURCE15_R(pix) * sr + DEST_R(dpix) * invsa) >> 8;
+ UINT32 g = (SOURCE15_G(pix) * sg + DEST_G(dpix) * invsa) >> 8;
+ UINT32 b = (SOURCE15_B(pix) * sb + DEST_B(dpix) * invsa) >> 8;
+
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+
+ /* lookup case */
+ else
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(rgb15)(&prim->texture, curu, curv);
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 r = ((palbase[(pix >> 10) & 0x1f] >> SRCSHIFT_R) * sr + DEST_R(dpix) * invsa) >> 8;
+ UINT32 g = ((palbase[(pix >> 5) & 0x1f] >> SRCSHIFT_G) * sg + DEST_G(dpix) * invsa) >> 8;
+ UINT32 b = ((palbase[(pix >> 0) & 0x1f] >> SRCSHIFT_B) * sb + DEST_B(dpix) * invsa) >> 8;
+
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ }
+ }
+}
+
+
+
+/***************************************************************************
+ 32-BIT RGB QUAD RASTERIZERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ draw_quad_rgb32 - perform rasterization of
+ a 32bpp RGB texture
+-------------------------------------------------*/
+
+static void FUNC_PREFIX(draw_quad_rgb32)(const render_primitive *prim, void *dstdata, UINT32 pitch, quad_setup_data *setup)
+{
+ const rgb_t *palbase = prim->texture.palette;
+ INT32 dudx = setup->dudx;
+ INT32 dvdx = setup->dvdx;
+ INT32 endx = setup->endx;
+ INT32 x, y;
+
+ /* fast case: no coloring, no alpha */
+ if (prim->color.r >= 1.0f && prim->color.g >= 1.0f && prim->color.b >= 1.0f && IS_OPAQUE(prim->color.a))
+ {
+ /* loop over rows */
+ for (y = setup->starty; y < setup->endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + setup->startx;
+ INT32 curu = setup->startu + (y - setup->starty) * setup->dudy;
+ INT32 curv = setup->startv + (y - setup->starty) * setup->dvdy;
+
+ /* no lookup case */
+ if (palbase == NULL)
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(rgb32)(&prim->texture, curu, curv);
+ *dest++ = SOURCE32_TO_DEST(pix);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+
+ /* lookup case */
+ else
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(rgb32)(&prim->texture, curu, curv);
+ UINT32 r = palbase[(pix >> 16) & 0xff] >> SRCSHIFT_R;
+ UINT32 g = palbase[(pix >> 8) & 0xff] >> SRCSHIFT_G;
+ UINT32 b = palbase[(pix >> 0) & 0xff] >> SRCSHIFT_B;
+
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ }
+ }
+
+ /* coloring-only case */
+ else if (IS_OPAQUE(prim->color.a))
+ {
+ UINT32 sr = (UINT32)(256.0f * prim->color.r);
+ UINT32 sg = (UINT32)(256.0f * prim->color.g);
+ UINT32 sb = (UINT32)(256.0f * prim->color.b);
+
+ /* clamp R,G,B to 0-256 range */
+ if (sr > 0x100) { if ((INT32)sr < 0) sr = 0; else sr = 0x100; }
+ if (sg > 0x100) { if ((INT32)sg < 0) sg = 0; else sg = 0x100; }
+ if (sb > 0x100) { if ((INT32)sb < 0) sb = 0; else sb = 0x100; }
+
+ /* loop over rows */
+ for (y = setup->starty; y < setup->endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + setup->startx;
+ INT32 curu = setup->startu + (y - setup->starty) * setup->dudy;
+ INT32 curv = setup->startv + (y - setup->starty) * setup->dvdy;
+
+ /* no lookup case */
+ if (palbase == NULL)
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(rgb32)(&prim->texture, curu, curv);
+ UINT32 r = (SOURCE32_R(pix) * sr) >> 8;
+ UINT32 g = (SOURCE32_G(pix) * sg) >> 8;
+ UINT32 b = (SOURCE32_B(pix) * sb) >> 8;
+
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+
+ /* lookup case */
+ else
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(rgb32)(&prim->texture, curu, curv);
+ UINT32 r = (palbase[(pix >> 16) & 0xff] * sr) >> (8 + SRCSHIFT_R);
+ UINT32 g = (palbase[(pix >> 8) & 0xff] * sg) >> (8 + SRCSHIFT_G);
+ UINT32 b = (palbase[(pix >> 0) & 0xff] * sb) >> (8 + SRCSHIFT_B);
+
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ }
+ }
+
+ /* alpha and/or coloring case */
+ else if (!IS_TRANSPARENT(prim->color.a))
+ {
+ UINT32 sr = (UINT32)(256.0f * prim->color.r * prim->color.a);
+ UINT32 sg = (UINT32)(256.0f * prim->color.g * prim->color.a);
+ UINT32 sb = (UINT32)(256.0f * prim->color.b * prim->color.a);
+ UINT32 invsa = (UINT32)(256.0f * (1.0f - prim->color.a));
+
+ /* clamp R,G,B and inverse A to 0-256 range */
+ if (sr > 0x100) { if ((INT32)sr < 0) sr = 0; else sr = 0x100; }
+ if (sg > 0x100) { if ((INT32)sg < 0) sg = 0; else sg = 0x100; }
+ if (sb > 0x100) { if ((INT32)sb < 0) sb = 0; else sb = 0x100; }
+ if (invsa > 0x100) { if ((INT32)invsa < 0) invsa = 0; else invsa = 0x100; }
+
+ /* loop over rows */
+ for (y = setup->starty; y < setup->endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + setup->startx;
+ INT32 curu = setup->startu + (y - setup->starty) * setup->dudy;
+ INT32 curv = setup->startv + (y - setup->starty) * setup->dvdy;
+
+ /* no lookup case */
+ if (palbase == NULL)
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(rgb32)(&prim->texture, curu, curv);
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 r = (SOURCE32_R(pix) * sr + DEST_R(dpix) * invsa) >> 8;
+ UINT32 g = (SOURCE32_G(pix) * sg + DEST_G(dpix) * invsa) >> 8;
+ UINT32 b = (SOURCE32_B(pix) * sb + DEST_B(dpix) * invsa) >> 8;
+
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+
+ /* lookup case */
+ else
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(rgb32)(&prim->texture, curu, curv);
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 r = ((palbase[(pix >> 16) & 0xff] >> SRCSHIFT_R) * sr + DEST_R(dpix) * invsa) >> 8;
+ UINT32 g = ((palbase[(pix >> 8) & 0xff] >> SRCSHIFT_G) * sg + DEST_G(dpix) * invsa) >> 8;
+ UINT32 b = ((palbase[(pix >> 0) & 0xff] >> SRCSHIFT_B) * sb + DEST_B(dpix) * invsa) >> 8;
+
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ draw_quad_rgb32_add - perform
+ rasterization by using RGB add
+-------------------------------------------------*/
+
+static void FUNC_PREFIX(draw_quad_rgb32_add)(const render_primitive *prim, void *dstdata, UINT32 pitch, quad_setup_data *setup)
+{
+ const rgb_t *palbase = prim->texture.palette;
+ INT32 dudx = setup->dudx;
+ INT32 dvdx = setup->dvdx;
+ INT32 endx = setup->endx;
+ INT32 x, y;
+
+ /* simply can't do this without reading from the dest */
+ if (NO_DEST_READ)
+ return;
+
+ /* fast case: no coloring, no alpha */
+ if (prim->color.r >= 1.0f && prim->color.g >= 1.0f && prim->color.b >= 1.0f && IS_OPAQUE(prim->color.a))
+ {
+ /* loop over rows */
+ for (y = setup->starty; y < setup->endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + setup->startx;
+ INT32 curu = setup->startu + (y - setup->starty) * setup->dudy;
+ INT32 curv = setup->startv + (y - setup->starty) * setup->dvdy;
+
+ /* no lookup case */
+ if (palbase == NULL)
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(argb32)(&prim->texture, curu, curv);
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 r = SOURCE32_R(pix) + DEST_R(dpix);
+ UINT32 g = SOURCE32_G(pix) + DEST_G(dpix);
+ UINT32 b = SOURCE32_B(pix) + DEST_B(dpix);
+ r = (r | -(r >> (8 - SRCSHIFT_R))) & (0xff >> SRCSHIFT_R);
+ g = (g | -(g >> (8 - SRCSHIFT_G))) & (0xff >> SRCSHIFT_G);
+ b = (b | -(b >> (8 - SRCSHIFT_B))) & (0xff >> SRCSHIFT_B);
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+
+ /* lookup case */
+ else
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(argb32)(&prim->texture, curu, curv);
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 r = (palbase[(pix >> 16) & 0xff] >> SRCSHIFT_R) + DEST_R(dpix);
+ UINT32 g = (palbase[(pix >> 8) & 0xff] >> SRCSHIFT_G) + DEST_G(dpix);
+ UINT32 b = (palbase[(pix >> 0) & 0xff] >> SRCSHIFT_B) + DEST_B(dpix);
+ r = (r | -(r >> (8 - SRCSHIFT_R))) & (0xff >> SRCSHIFT_R);
+ g = (g | -(g >> (8 - SRCSHIFT_G))) & (0xff >> SRCSHIFT_G);
+ b = (b | -(b >> (8 - SRCSHIFT_B))) & (0xff >> SRCSHIFT_B);
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ }
+ }
+
+ /* alpha and/or coloring case */
+ else
+ {
+ UINT32 sr = (UINT32)(256.0f * prim->color.r);
+ UINT32 sg = (UINT32)(256.0f * prim->color.g);
+ UINT32 sb = (UINT32)(256.0f * prim->color.b);
+ UINT32 sa = (UINT32)(256.0f * prim->color.a);
+
+ /* clamp R,G,B and inverse A to 0-256 range */
+ if (sr > 0x100) { if ((INT32)sr < 0) sr = 0; else sr = 0x100; }
+ if (sg > 0x100) { if ((INT32)sg < 0) sg = 0; else sg = 0x100; }
+ if (sb > 0x100) { if ((INT32)sb < 0) sb = 0; else sb = 0x100; }
+ if (sa > 0x100) { if ((INT32)sa < 0) sa = 0; else sa = 0x100; }
+
+ /* loop over rows */
+ for (y = setup->starty; y < setup->endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + setup->startx;
+ INT32 curu = setup->startu + (y - setup->starty) * setup->dudy;
+ INT32 curv = setup->startv + (y - setup->starty) * setup->dvdy;
+
+ /* no lookup case */
+ if (palbase == NULL)
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(argb32)(&prim->texture, curu, curv);
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 r = ((SOURCE32_R(pix) * sr * sa) >> 16) + DEST_R(dpix);
+ UINT32 g = ((SOURCE32_G(pix) * sg * sa) >> 16) + DEST_G(dpix);
+ UINT32 b = ((SOURCE32_B(pix) * sb * sa) >> 16) + DEST_B(dpix);
+ r = (r | -(r >> (8 - SRCSHIFT_R))) & (0xff >> SRCSHIFT_R);
+ g = (g | -(g >> (8 - SRCSHIFT_G))) & (0xff >> SRCSHIFT_G);
+ b = (b | -(b >> (8 - SRCSHIFT_B))) & (0xff >> SRCSHIFT_B);
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+
+ /* lookup case */
+ else
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(argb32)(&prim->texture, curu, curv);
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 r = ((palbase[(pix >> 16) & 0xff] * sr * sa) >> (16 + SRCSHIFT_R)) + DEST_R(dpix);
+ UINT32 g = ((palbase[(pix >> 8) & 0xff] * sr * sa) >> (16 + SRCSHIFT_R)) + DEST_G(dpix);
+ UINT32 b = ((palbase[(pix >> 0) & 0xff] * sr * sa) >> (16 + SRCSHIFT_R)) + DEST_B(dpix);
+ r = (r | -(r >> (8 - SRCSHIFT_R))) & (0xff >> SRCSHIFT_R);
+ g = (g | -(g >> (8 - SRCSHIFT_G))) & (0xff >> SRCSHIFT_G);
+ b = (b | -(b >> (8 - SRCSHIFT_B))) & (0xff >> SRCSHIFT_B);
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ }
+ }
+}
+
+
+
+/***************************************************************************
+ 32-BIT ARGB QUAD RASTERIZERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ draw_quad_argb32_alpha - perform
+ rasterization using standard alpha blending
+-------------------------------------------------*/
+
+static void FUNC_PREFIX(draw_quad_argb32_alpha)(const render_primitive *prim, void *dstdata, UINT32 pitch, quad_setup_data *setup)
+{
+ const rgb_t *palbase = prim->texture.palette;
+ INT32 dudx = setup->dudx;
+ INT32 dvdx = setup->dvdx;
+ INT32 endx = setup->endx;
+ INT32 x, y;
+
+ /* fast case: no coloring, no alpha */
+ if (prim->color.r >= 1.0f && prim->color.g >= 1.0f && prim->color.b >= 1.0f && IS_OPAQUE(prim->color.a))
+ {
+ /* loop over rows */
+ for (y = setup->starty; y < setup->endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + setup->startx;
+ INT32 curu = setup->startu + (y - setup->starty) * setup->dudy;
+ INT32 curv = setup->startv + (y - setup->starty) * setup->dvdy;
+
+ /* no lookup case */
+ if (palbase == NULL)
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(argb32)(&prim->texture, curu, curv);
+ UINT32 ta = pix >> 24;
+ if (ta != 0)
+ {
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 invta = 0x100 - ta;
+ UINT32 r = (SOURCE32_R(pix) * ta + DEST_R(dpix) * invta) >> 8;
+ UINT32 g = (SOURCE32_G(pix) * ta + DEST_G(dpix) * invta) >> 8;
+ UINT32 b = (SOURCE32_B(pix) * ta + DEST_B(dpix) * invta) >> 8;
+
+ *dest = DEST_ASSEMBLE_RGB(r, g, b);
+ }
+ dest++;
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+
+ /* lookup case */
+ else
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(argb32)(&prim->texture, curu, curv);
+ UINT32 ta = pix >> 24;
+ if (ta != 0)
+ {
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 invta = 0x100 - ta;
+ UINT32 r = ((palbase[(pix >> 16) & 0xff] >> SRCSHIFT_R) * ta + DEST_R(dpix) * invta) >> 8;
+ UINT32 g = ((palbase[(pix >> 8) & 0xff] >> SRCSHIFT_G) * ta + DEST_G(dpix) * invta) >> 8;
+ UINT32 b = ((palbase[(pix >> 0) & 0xff] >> SRCSHIFT_B) * ta + DEST_B(dpix) * invta) >> 8;
+
+ *dest = DEST_ASSEMBLE_RGB(r, g, b);
+ }
+ dest++;
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ }
+ }
+
+ /* alpha and/or coloring case */
+ else
+ {
+ UINT32 sr = (UINT32)(256.0f * prim->color.r);
+ UINT32 sg = (UINT32)(256.0f * prim->color.g);
+ UINT32 sb = (UINT32)(256.0f * prim->color.b);
+ UINT32 sa = (UINT32)(256.0f * prim->color.a);
+
+ /* clamp R,G,B and inverse A to 0-256 range */
+ if (sr > 0x100) { if ((INT32)sr < 0) sr = 0; else sr = 0x100; }
+ if (sg > 0x100) { if ((INT32)sg < 0) sg = 0; else sg = 0x100; }
+ if (sb > 0x100) { if ((INT32)sb < 0) sb = 0; else sb = 0x100; }
+ if (sa > 0x100) { if ((INT32)sa < 0) sa = 0; else sa = 0x100; }
+
+ /* loop over rows */
+ for (y = setup->starty; y < setup->endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + setup->startx;
+ INT32 curu = setup->startu + (y - setup->starty) * setup->dudy;
+ INT32 curv = setup->startv + (y - setup->starty) * setup->dvdy;
+
+ /* no lookup case */
+ if (palbase == NULL)
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(argb32)(&prim->texture, curu, curv);
+ UINT32 ta = (pix >> 24) * sa;
+ if (ta != 0)
+ {
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 invsta = (0x10000 - ta) << 8;
+ UINT32 r = (SOURCE32_R(pix) * sr * ta + DEST_R(dpix) * invsta) >> 24;
+ UINT32 g = (SOURCE32_G(pix) * sg * ta + DEST_G(dpix) * invsta) >> 24;
+ UINT32 b = (SOURCE32_B(pix) * sb * ta + DEST_B(dpix) * invsta) >> 24;
+
+ *dest = DEST_ASSEMBLE_RGB(r, g, b);
+ }
+ dest++;
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+
+
+ /* lookup case */
+ else
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(argb32)(&prim->texture, curu, curv);
+ UINT32 ta = (pix >> 24) * sa;
+ if (ta != 0)
+ {
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 invsta = (0x10000 - ta) << 8;
+ UINT32 r = ((palbase[(pix >> 16) & 0xff] >> SRCSHIFT_R) * sr * ta + DEST_R(dpix) * invsta) >> 24;
+ UINT32 g = ((palbase[(pix >> 8) & 0xff] >> SRCSHIFT_G) * sg * ta + DEST_G(dpix) * invsta) >> 24;
+ UINT32 b = ((palbase[(pix >> 0) & 0xff] >> SRCSHIFT_B) * sb * ta + DEST_B(dpix) * invsta) >> 24;
+
+ *dest = DEST_ASSEMBLE_RGB(r, g, b);
+ }
+ dest++;
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ draw_quad_argb32_multiply - perform
+ rasterization using RGB multiply
+-------------------------------------------------*/
+
+static void FUNC_PREFIX(draw_quad_argb32_multiply)(const render_primitive *prim, void *dstdata, UINT32 pitch, quad_setup_data *setup)
+{
+ const rgb_t *palbase = prim->texture.palette;
+ INT32 dudx = setup->dudx;
+ INT32 dvdx = setup->dvdx;
+ INT32 endx = setup->endx;
+ INT32 x, y;
+
+ /* simply can't do this without reading from the dest */
+ if (NO_DEST_READ)
+ return;
+
+ /* fast case: no coloring, no alpha */
+ if (prim->color.r >= 1.0f && prim->color.g >= 1.0f && prim->color.b >= 1.0f && IS_OPAQUE(prim->color.a))
+ {
+ /* loop over rows */
+ for (y = setup->starty; y < setup->endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + setup->startx;
+ INT32 curu = setup->startu + (y - setup->starty) * setup->dudy;
+ INT32 curv = setup->startv + (y - setup->starty) * setup->dvdy;
+
+ /* no lookup case */
+ if (palbase == NULL)
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(argb32)(&prim->texture, curu, curv);
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 r = (SOURCE32_R(pix) * DEST_R(dpix)) >> (8 - SRCSHIFT_R);
+ UINT32 g = (SOURCE32_G(pix) * DEST_G(dpix)) >> (8 - SRCSHIFT_G);
+ UINT32 b = (SOURCE32_B(pix) * DEST_B(dpix)) >> (8 - SRCSHIFT_B);
+
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ else
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(argb32)(&prim->texture, curu, curv);
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 r = (palbase[(pix >> 16) & 0xff] * DEST_R(dpix)) >> 8;
+ UINT32 g = (palbase[(pix >> 8) & 0xff] * DEST_G(dpix)) >> 8;
+ UINT32 b = (palbase[(pix >> 0) & 0xff] * DEST_B(dpix)) >> 8;
+
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ }
+ }
+
+ /* alpha and/or coloring case */
+ else
+ {
+ UINT32 sr = (UINT32)(256.0f * prim->color.r * prim->color.a);
+ UINT32 sg = (UINT32)(256.0f * prim->color.g * prim->color.a);
+ UINT32 sb = (UINT32)(256.0f * prim->color.b * prim->color.a);
+
+ /* clamp R,G,B and inverse A to 0-256 range */
+ if (sr > 0x100) { if ((INT32)sr < 0) sr = 0; else sr = 0x100; }
+ if (sg > 0x100) { if ((INT32)sg < 0) sg = 0; else sg = 0x100; }
+ if (sb > 0x100) { if ((INT32)sb < 0) sb = 0; else sb = 0x100; }
+
+ /* loop over rows */
+ for (y = setup->starty; y < setup->endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + setup->startx;
+ INT32 curu = setup->startu + (y - setup->starty) * setup->dudy;
+ INT32 curv = setup->startv + (y - setup->starty) * setup->dvdy;
+
+ /* no lookup case */
+ if (palbase == NULL)
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(argb32)(&prim->texture, curu, curv);
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 r = (SOURCE32_R(pix) * sr * DEST_R(dpix)) >> (16 - SRCSHIFT_R);
+ UINT32 g = (SOURCE32_G(pix) * sg * DEST_G(dpix)) >> (16 - SRCSHIFT_G);
+ UINT32 b = (SOURCE32_B(pix) * sb * DEST_B(dpix)) >> (16 - SRCSHIFT_B);
+
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ else
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(argb32)(&prim->texture, curu, curv);
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 r = (palbase[(pix >> 16) & 0xff] * sr * DEST_R(dpix)) >> 16;
+ UINT32 g = (palbase[(pix >> 8) & 0xff] * sg * DEST_G(dpix)) >> 16;
+ UINT32 b = (palbase[(pix >> 0) & 0xff] * sb * DEST_B(dpix)) >> 16;
+
+ *dest++ = DEST_ASSEMBLE_RGB(r, g, b);
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ draw_quad_argb32_add - perform
+ rasterization by using RGB add
+-------------------------------------------------*/
+
+static void FUNC_PREFIX(draw_quad_argb32_add)(const render_primitive *prim, void *dstdata, UINT32 pitch, quad_setup_data *setup)
+{
+ const rgb_t *palbase = prim->texture.palette;
+ INT32 dudx = setup->dudx;
+ INT32 dvdx = setup->dvdx;
+ INT32 endx = setup->endx;
+ INT32 x, y;
+
+ /* simply can't do this without reading from the dest */
+ if (NO_DEST_READ)
+ return;
+
+ /* fast case: no coloring, no alpha */
+ if (prim->color.r >= 1.0f && prim->color.g >= 1.0f && prim->color.b >= 1.0f && IS_OPAQUE(prim->color.a))
+ {
+ /* loop over rows */
+ for (y = setup->starty; y < setup->endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + setup->startx;
+ INT32 curu = setup->startu + (y - setup->starty) * setup->dudy;
+ INT32 curv = setup->startv + (y - setup->starty) * setup->dvdy;
+
+ /* no lookup case */
+ if (palbase == NULL)
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(argb32)(&prim->texture, curu, curv);
+ UINT32 ta = pix >> 24;
+ if (ta != 0)
+ {
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 r = ((SOURCE32_R(pix) * ta) >> 8) + DEST_R(dpix);
+ UINT32 g = ((SOURCE32_G(pix) * ta) >> 8) + DEST_G(dpix);
+ UINT32 b = ((SOURCE32_B(pix) * ta) >> 8) + DEST_B(dpix);
+ r = (r | -(r >> (8 - SRCSHIFT_R))) & (0xff >> SRCSHIFT_R);
+ g = (g | -(g >> (8 - SRCSHIFT_G))) & (0xff >> SRCSHIFT_G);
+ b = (b | -(b >> (8 - SRCSHIFT_B))) & (0xff >> SRCSHIFT_B);
+ *dest = DEST_ASSEMBLE_RGB(r, g, b);
+ }
+ dest++;
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+
+ /* lookup case */
+ else
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(argb32)(&prim->texture, curu, curv);
+ UINT32 ta = pix >> 24;
+ if (ta != 0)
+ {
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 r = ((palbase[(pix >> 16) & 0xff] * ta) >> (8 + SRCSHIFT_R)) + DEST_R(dpix);
+ UINT32 g = ((palbase[(pix >> 8) & 0xff] * ta) >> (8 + SRCSHIFT_G)) + DEST_G(dpix);
+ UINT32 b = ((palbase[(pix >> 0) & 0xff] * ta) >> (8 + SRCSHIFT_B)) + DEST_B(dpix);
+ r = (r | -(r >> (8 - SRCSHIFT_R))) & (0xff >> SRCSHIFT_R);
+ g = (g | -(g >> (8 - SRCSHIFT_G))) & (0xff >> SRCSHIFT_G);
+ b = (b | -(b >> (8 - SRCSHIFT_B))) & (0xff >> SRCSHIFT_B);
+ *dest = DEST_ASSEMBLE_RGB(r, g, b);
+ }
+ dest++;
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ }
+ }
+
+ /* alpha and/or coloring case */
+ else
+ {
+ UINT32 sr = (UINT32)(256.0f * prim->color.r);
+ UINT32 sg = (UINT32)(256.0f * prim->color.g);
+ UINT32 sb = (UINT32)(256.0f * prim->color.b);
+ UINT32 sa = (UINT32)(256.0f * prim->color.a);
+
+ /* clamp R,G,B and inverse A to 0-256 range */
+ if (sr > 0x100) { if ((INT32)sr < 0) sr = 0; else sr = 0x100; }
+ if (sg > 0x100) { if ((INT32)sg < 0) sg = 0; else sg = 0x100; }
+ if (sb > 0x100) { if ((INT32)sb < 0) sb = 0; else sb = 0x100; }
+ if (sa > 0x100) { if ((INT32)sa < 0) sa = 0; else sa = 0x100; }
+
+ /* loop over rows */
+ for (y = setup->starty; y < setup->endy; y++)
+ {
+ PIXEL_TYPE *dest = (PIXEL_TYPE *)dstdata + y * pitch + setup->startx;
+ INT32 curu = setup->startu + (y - setup->starty) * setup->dudy;
+ INT32 curv = setup->startv + (y - setup->starty) * setup->dvdy;
+
+ /* no lookup case */
+ if (palbase == NULL)
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(argb32)(&prim->texture, curu, curv);
+ UINT32 ta = (pix >> 24) * sa;
+ if (ta != 0)
+ {
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 r = ((SOURCE32_R(pix) * sr * ta) >> 24) + DEST_R(dpix);
+ UINT32 g = ((SOURCE32_G(pix) * sg * ta) >> 24) + DEST_G(dpix);
+ UINT32 b = ((SOURCE32_B(pix) * sb * ta) >> 24) + DEST_B(dpix);
+ r = (r | -(r >> (8 - SRCSHIFT_R))) & (0xff >> SRCSHIFT_R);
+ g = (g | -(g >> (8 - SRCSHIFT_G))) & (0xff >> SRCSHIFT_G);
+ b = (b | -(b >> (8 - SRCSHIFT_B))) & (0xff >> SRCSHIFT_B);
+ *dest = DEST_ASSEMBLE_RGB(r, g, b);
+ }
+ dest++;
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+
+ /* lookup case */
+ else
+ {
+ /* loop over cols */
+ for (x = setup->startx; x < endx; x++)
+ {
+ UINT32 pix = GET_TEXEL(argb32)(&prim->texture, curu, curv);
+ UINT32 ta = (pix >> 24) * sa;
+ if (ta != 0)
+ {
+ UINT32 dpix = NO_DEST_READ ? 0 : *dest;
+ UINT32 r = ((palbase[(pix >> 16) & 0xff] * sr * ta) >> (24 + SRCSHIFT_R)) + DEST_R(dpix);
+ UINT32 g = ((palbase[(pix >> 8) & 0xff] * sr * ta) >> (24 + SRCSHIFT_R)) + DEST_G(dpix);
+ UINT32 b = ((palbase[(pix >> 0) & 0xff] * sr * ta) >> (24 + SRCSHIFT_R)) + DEST_B(dpix);
+ r = (r | -(r >> (8 - SRCSHIFT_R))) & (0xff >> SRCSHIFT_R);
+ g = (g | -(g >> (8 - SRCSHIFT_G))) & (0xff >> SRCSHIFT_G);
+ b = (b | -(b >> (8 - SRCSHIFT_B))) & (0xff >> SRCSHIFT_B);
+ *dest = DEST_ASSEMBLE_RGB(r, g, b);
+ }
+ dest++;
+ curu += dudx;
+ curv += dvdx;
+ }
+ }
+ }
+ }
+}
+
+
+
+/***************************************************************************
+ CORE QUAD RASTERIZERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ setup_and_draw_textured_quad - perform setup
+ and then dispatch to a texture-mode-specific
+ drawing routine
+-------------------------------------------------*/
+
+static void FUNC_PREFIX(setup_and_draw_textured_quad)(const render_primitive *prim, void *dstdata, INT32 width, INT32 height, UINT32 pitch)
+{
+ float fdudx, fdvdx, fdudy, fdvdy;
+ quad_setup_data setup;
+
+ assert(prim->bounds.x0 <= prim->bounds.x1);
+ assert(prim->bounds.y0 <= prim->bounds.y1);
+
+ /* determine U/V deltas */
+ fdudx = (prim->texcoords.tr.u - prim->texcoords.tl.u) / (prim->bounds.x1 - prim->bounds.x0);
+ fdvdx = (prim->texcoords.tr.v - prim->texcoords.tl.v) / (prim->bounds.x1 - prim->bounds.x0);
+ fdudy = (prim->texcoords.bl.u - prim->texcoords.tl.u) / (prim->bounds.y1 - prim->bounds.y0);
+ fdvdy = (prim->texcoords.bl.v - prim->texcoords.tl.v) / (prim->bounds.y1 - prim->bounds.y0);
+
+ /* clamp to integers */
+ setup.startx = round_nearest(prim->bounds.x0);
+ setup.starty = round_nearest(prim->bounds.y0);
+ setup.endx = round_nearest(prim->bounds.x1);
+ setup.endy = round_nearest(prim->bounds.y1);
+
+ /* ensure we fit */
+ if (setup.startx < 0) setup.startx = 0;
+ if (setup.startx >= width) setup.startx = width;
+ if (setup.endx < 0) setup.endx = 0;
+ if (setup.endx >= width) setup.endx = width;
+ if (setup.starty < 0) setup.starty = 0;
+ if (setup.starty >= height) setup.starty = height;
+ if (setup.endy < 0) setup.endy = 0;
+ if (setup.endy >= height) setup.endy = height;
+
+ /* compute start and delta U,V coordinates now */
+ setup.dudx = round_nearest(65536.0f * (float)prim->texture.width * fdudx);
+ setup.dvdx = round_nearest(65536.0f * (float)prim->texture.height * fdvdx);
+ setup.dudy = round_nearest(65536.0f * (float)prim->texture.width * fdudy);
+ setup.dvdy = round_nearest(65536.0f * (float)prim->texture.height * fdvdy);
+ setup.startu = round_nearest(65536.0f * (float)prim->texture.width * prim->texcoords.tl.u);
+ setup.startv = round_nearest(65536.0f * (float)prim->texture.height * prim->texcoords.tl.v);
+
+ /* advance U/V to the middle of the first texel */
+ setup.startu += (setup.dudx + setup.dudy) / 2;
+ setup.startv += (setup.dvdx + setup.dvdy) / 2;
+
+ /* if we're bilinear filtering, we need to offset u/v by half a texel */
+ if (BILINEAR_FILTER)
+ {
+ setup.startu -= 0x8000;
+ setup.startv -= 0x8000;
+ }
+
+ /* render based on the texture coordinates */
+ switch (prim->flags & (PRIMFLAG_TEXFORMAT_MASK | PRIMFLAG_BLENDMODE_MASK))
+ {
+ case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTE16) | PRIMFLAG_BLENDMODE(BLENDMODE_NONE):
+ case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTE16) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA):
+ FUNC_PREFIX(draw_quad_palette16_none)(prim, dstdata, pitch, &setup);
+ break;
+
+ case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTE16) | PRIMFLAG_BLENDMODE(BLENDMODE_ADD):
+ FUNC_PREFIX(draw_quad_palette16_add)(prim, dstdata, pitch, &setup);
+ break;
+
+ case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTEA16) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA):
+ FUNC_PREFIX(draw_quad_palettea16_alpha)(prim, dstdata, pitch, &setup);
+ break;
+
+ case PRIMFLAG_TEXFORMAT(TEXFORMAT_YUY16) | PRIMFLAG_BLENDMODE(BLENDMODE_NONE):
+ FUNC_PREFIX(draw_quad_yuy16_none)(prim, dstdata, pitch, &setup);
+ break;
+
+ case PRIMFLAG_TEXFORMAT(TEXFORMAT_RGB15) | PRIMFLAG_BLENDMODE(BLENDMODE_NONE):
+ case PRIMFLAG_TEXFORMAT(TEXFORMAT_RGB15) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA):
+ FUNC_PREFIX(draw_quad_rgb15)(prim, dstdata, pitch, &setup);
+ break;
+
+ case PRIMFLAG_TEXFORMAT(TEXFORMAT_RGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_NONE):
+ case PRIMFLAG_TEXFORMAT(TEXFORMAT_RGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA):
+ case PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_NONE):
+ FUNC_PREFIX(draw_quad_rgb32)(prim, dstdata, pitch, &setup);
+ break;
+
+ case PRIMFLAG_TEXFORMAT(TEXFORMAT_RGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_ADD):
+ FUNC_PREFIX(draw_quad_rgb32_add)(prim, dstdata, pitch, &setup);
+ break;
+
+ case PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA):
+ FUNC_PREFIX(draw_quad_argb32_alpha)(prim, dstdata, pitch, &setup);
+ break;
+
+ case PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_RGB_MULTIPLY):
+ FUNC_PREFIX(draw_quad_argb32_multiply)(prim, dstdata, pitch, &setup);
+ break;
+
+ case PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32) | PRIMFLAG_BLENDMODE(BLENDMODE_ADD):
+ FUNC_PREFIX(draw_quad_argb32_add)(prim, dstdata, pitch, &setup);
+ break;
+
+ default:
+ fatalerror("Unknown texformat(%d)/blendmode(%d) combo\n", PRIMFLAG_GET_TEXFORMAT(prim->flags), PRIMFLAG_GET_BLENDMODE(prim->flags));
+ break;
+ }
+}
+
+
+
+/***************************************************************************
+ PRIMARY ENTRY POINT
+***************************************************************************/
+
+/*-------------------------------------------------
+ draw_primitives - draw a series of primitives
+ using a software rasterizer
+-------------------------------------------------*/
+
+static void FUNC_PREFIX(draw_primitives)(const render_primitive_list &primlist, void *dstdata, UINT32 width, UINT32 height, UINT32 pitch)
+{
+ const render_primitive *prim;
+
+ /* loop over the list and render each element */
+ for (prim = primlist.first(); prim != NULL; prim = prim->next())
+ switch (prim->type)
+ {
+ case render_primitive::LINE:
+ FUNC_PREFIX(draw_line)(prim, dstdata, width, height, pitch);
+ break;
+
+ case render_primitive::QUAD:
+ if (!prim->texture.base)
+ FUNC_PREFIX(draw_rect)(prim, dstdata, width, height, pitch);
+ else
+ FUNC_PREFIX(setup_and_draw_textured_quad)(prim, dstdata, width, height, pitch);
+ break;
+
+ default:
+ throw emu_fatalerror("Unexpected render_primitive type");
+ }
+}
+
+
+
+/***************************************************************************
+ MACRO UNDOING
+***************************************************************************/
+
+#undef SOURCE15_R
+#undef SOURCE15_G
+#undef SOURCE15_B
+
+#undef SOURCE32_R
+#undef SOURCE32_G
+#undef SOURCE32_B
+
+#undef DEST_ASSEMBLE_RGB
+#undef DEST_RGB_TO_PIXEL
+
+#undef DEST_R
+#undef DEST_G
+#undef DEST_B
+
+#undef SOURCE15_TO_DEST
+#undef SOURCE32_TO_DEST
+
+#undef FUNC_PREFIX
+#undef PIXEL_TYPE
+
+#undef SRCSHIFT_R
+#undef SRCSHIFT_G
+#undef SRCSHIFT_B
+
+#undef DSTSHIFT_R
+#undef DSTSHIFT_G
+#undef DSTSHIFT_B
+
+#undef NO_DEST_READ
+
+#undef VARIABLE_SHIFT
diff --git a/trunk/src/emu/rendfont.c b/trunk/src/emu/rendfont.c
new file mode 100644
index 00000000000..c96b155d8a5
--- /dev/null
+++ b/trunk/src/emu/rendfont.c
@@ -0,0 +1,816 @@
+/***************************************************************************
+
+ rendfont.c
+
+ Rendering system font 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 "rendfont.h"
+#include "rendutil.h"
+#include "emuopts.h"
+#include "zlib.h"
+
+#include "uismall.fh"
+
+
+//**************************************************************************
+// INLINE FUNCTIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// next_line - return a pointer to the start of
+// the next line
+//-------------------------------------------------
+
+inline const char *next_line(const char *ptr)
+{
+ // scan forward until we hit the end or a carriage return
+ while (*ptr != 13 && *ptr != 10 && *ptr != 0) ptr++;
+
+ // if we hit the end, return NULL
+ if (*ptr == 0)
+ return NULL;
+
+ // eat the trailing linefeed if present
+ if (*++ptr == 10)
+ ptr++;
+ return ptr;
+}
+
+
+//-------------------------------------------------
+// get_char - return a pointer to a character
+// in a font, expanding if necessary
+//-------------------------------------------------
+
+inline render_font::glyph &render_font::get_char(unicode_char chnum)
+{
+ static glyph dummy_glyph;
+
+ // grab the table; if none, return the dummy character
+ glyph *glyphtable = m_glyphs[chnum / 256];
+ if (glyphtable == NULL && m_format == FF_OSD)
+ glyphtable = m_glyphs[chnum / 256] = auto_alloc_array_clear(m_manager.machine(), glyph, 256);
+ if (glyphtable == NULL)
+ return dummy_glyph;
+
+ // if the character isn't generated yet, do it now
+ glyph &gl = glyphtable[chnum % 256];
+ if (gl.bitmap == NULL)
+ char_expand(chnum, gl);
+
+ // return the resulting character
+ return gl;
+}
+
+
+
+//**************************************************************************
+// RENDER FONT
+//**************************************************************************
+
+//-------------------------------------------------
+// render_font - constructor
+//-------------------------------------------------
+
+render_font::render_font(render_manager &manager, const char *filename)
+ : m_manager(manager),
+ m_format(FF_UNKNOWN),
+ m_height(0),
+ m_yoffs(0),
+ m_scale(1.0f),
+ m_rawdata(NULL),
+ m_rawsize(0),
+ m_osdfont(NULL)
+{
+ memset(m_glyphs, 0, sizeof(m_glyphs));
+
+ // if this is an OSD font, we're done
+ if (filename != NULL)
+ {
+ m_osdfont = manager.machine().osd().font_open(filename, m_height);
+ if (m_osdfont != NULL)
+ {
+ m_scale = 1.0f / (float)m_height;
+ m_format = FF_OSD;
+ return;
+ }
+ }
+
+ // if the filename is 'default' default to 'ui.bdf' for backwards compatibility
+ if (filename != NULL && mame_stricmp(filename, "default") == 0)
+ filename = "ui.bdf";
+
+ // attempt to load the cached version of the font first
+ if (filename != NULL && load_cached_bdf(filename))
+ return;
+
+ // load the raw data instead
+ emu_file ramfile(OPEN_FLAG_READ);
+ file_error filerr = ramfile.open_ram(font_uismall, sizeof(font_uismall));
+ if (filerr == FILERR_NONE)
+ load_cached(ramfile, 0);
+}
+
+
+//-------------------------------------------------
+// ~render_font - destructor
+//-------------------------------------------------
+
+render_font::~render_font()
+{
+ // free all the subtables
+ for (int tablenum = 0; tablenum < 256; tablenum++)
+ if (m_glyphs[tablenum] != NULL)
+ {
+ // loop over characters
+ for (int charnum = 0; charnum < 256; charnum++)
+ {
+ glyph &gl = m_glyphs[tablenum][charnum];
+ m_manager.texture_free(gl.texture);
+ auto_free(m_manager.machine(), gl.bitmap);
+ }
+
+ // free the subtable itself
+ auto_free(m_manager.machine(), m_glyphs[tablenum]);
+ }
+
+ // free the raw data and the size itself
+ auto_free(m_manager.machine(), m_rawdata);
+
+ // release the OSD font
+ if (m_osdfont != NULL)
+ m_manager.machine().osd().font_close(m_osdfont);
+}
+
+
+//-------------------------------------------------
+// char_expand - expand the raw data for a
+// character into a bitmap
+//-------------------------------------------------
+
+void render_font::char_expand(unicode_char chnum, glyph &gl)
+{
+ // if we're an OSD font, query the info
+ if (m_format == FF_OSD)
+ {
+ // we set bmwidth to -1 if we've previously queried and failed
+ if (gl.bmwidth == -1)
+ return;
+
+ // attempt to get the font bitmap; if we fail, set bmwidth to -1
+ gl.bitmap = m_manager.machine().osd().font_get_bitmap(m_osdfont, chnum, gl.width, gl.xoffs, gl.yoffs);
+ if (gl.bitmap == NULL)
+ {
+ gl.bmwidth = -1;
+ return;
+ }
+
+ // populate the bmwidth/bmheight fields
+ gl.bmwidth = gl.bitmap->width;
+ gl.bmheight = gl.bitmap->height;
+ }
+
+ // other formats need to parse their data
+ else
+ {
+ // punt if nothing there
+ if (gl.bmwidth == 0 || gl.bmheight == 0 || gl.rawdata == NULL)
+ return;
+
+ // allocate a new bitmap of the size we need
+ gl.bitmap = auto_alloc(m_manager.machine(), bitmap_t(gl.bmwidth, m_height, BITMAP_FORMAT_ARGB32));
+ bitmap_fill(gl.bitmap, NULL, 0);
+
+ // extract the data
+ const char *ptr = gl.rawdata;
+ UINT8 accum = 0, accumbit = 7;
+ for (int y = 0; y < gl.bmheight; y++)
+ {
+ int desty = y + m_height + m_yoffs - gl.yoffs - gl.bmheight;
+ UINT32 *dest = (desty >= 0 && desty < m_height) ? BITMAP_ADDR32(gl.bitmap, desty, 0) : NULL;
+
+ // text format
+ if (m_format == FF_TEXT)
+ {
+ // loop over bytes
+ for (int x = 0; x < gl.bmwidth; x += 4)
+ {
+ // scan for the next hex digit
+ int bits = -1;
+ while (*ptr != 13 && bits == -1)
+ {
+ if (*ptr >= '0' && *ptr <= '9')
+ bits = *ptr++ - '0';
+ else if (*ptr >= 'A' && *ptr <= 'F')
+ bits = *ptr++ - 'A' + 10;
+ else if (*ptr >= 'a' && *ptr <= 'f')
+ bits = *ptr++ - 'a' + 10;
+ else
+ ptr++;
+ }
+
+ // expand the four bits
+ if (dest != NULL)
+ {
+ *dest++ = (bits & 8) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff);
+ *dest++ = (bits & 4) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff);
+ *dest++ = (bits & 2) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff);
+ *dest++ = (bits & 1) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff);
+ }
+ }
+
+ // advance to the next line
+ ptr = next_line(ptr);
+ }
+
+ // cached format
+ else if (m_format == FF_CACHED)
+ {
+ for (int x = 0; x < gl.bmwidth; x++)
+ {
+ if (accumbit == 7)
+ accum = *ptr++;
+ if (dest != NULL)
+ *dest++ = (accum & (1 << accumbit)) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff);
+ accumbit = (accumbit - 1) & 7;
+ }
+ }
+ }
+ }
+
+ // wrap a texture around the bitmap
+ gl.texture = m_manager.texture_alloc(render_texture::hq_scale);
+ gl.texture->set_bitmap(gl.bitmap, NULL, TEXFORMAT_ARGB32);
+}
+
+
+//-------------------------------------------------
+// get_char_texture_and_bounds - return the
+// texture for a character and compute the
+// bounds of the final bitmap
+//-------------------------------------------------
+
+render_texture *render_font::get_char_texture_and_bounds(float height, float aspect, unicode_char chnum, render_bounds &bounds)
+{
+ glyph &gl = get_char(chnum);
+
+ // on entry, assume x0,y0 are the top,left coordinate of the cell and add
+ // the character bounding box to that position
+ float scale = m_scale * height;
+ bounds.x0 += (float)gl.xoffs * scale * aspect;
+
+ // compute x1,y1 from there based on the bitmap size
+ bounds.x1 = bounds.x0 + (float)gl.bmwidth * scale * aspect;
+ bounds.y1 = bounds.y0 + (float)m_height * scale;
+
+ // return the texture
+ return gl.texture;
+}
+
+
+//-------------------------------------------------
+// get_scaled_bitmap_and_bounds - return a
+// scaled bitmap and bounding rect for a char
+//-------------------------------------------------
+
+void render_font::get_scaled_bitmap_and_bounds(bitmap_t &dest, float height, float aspect, unicode_char chnum, rectangle &bounds)
+{
+ glyph &gl = get_char(chnum);
+
+ // on entry, assume x0,y0 are the top,left coordinate of the cell and add
+ // the character bounding box to that position
+ float scale = m_scale * height;
+ bounds.min_x = (float)gl.xoffs * scale * aspect;
+ bounds.min_y = 0;
+
+ // compute x1,y1 from there based on the bitmap size
+ bounds.max_x = bounds.min_x + (float)gl.bmwidth * scale * aspect;
+ bounds.max_y = bounds.min_y + (float)m_height * scale;
+
+ // if the bitmap isn't big enough, bail
+ if (dest.width < bounds.max_x - bounds.min_x || dest.height < bounds.max_y - bounds.min_y)
+ return;
+
+ // if no texture, fill the target
+ if (gl.texture == NULL)
+ {
+ bitmap_fill(&dest, NULL, 0);
+ return;
+ }
+
+ // scale the font
+ INT32 origwidth = dest.width;
+ INT32 origheight = dest.height;
+ dest.width = bounds.max_x - bounds.min_x;
+ dest.height = bounds.max_y - bounds.min_y;
+ rectangle clip;
+ clip.min_x = clip.min_y = 0;
+ clip.max_x = gl.bitmap->width - 1;
+ clip.max_y = gl.bitmap->height - 1;
+ render_texture::hq_scale(dest, *gl.bitmap, clip, NULL);
+ dest.width = origwidth;
+ dest.height = origheight;
+}
+
+
+//-------------------------------------------------
+// char_width - return the width of a character
+// at the given height
+//-------------------------------------------------
+
+float render_font::char_width(float height, float aspect, unicode_char ch)
+{
+ return (float)get_char(ch).width * m_scale * height * aspect;
+}
+
+
+//-------------------------------------------------
+// string_width - return the width of a string
+// at the given height
+//-------------------------------------------------
+
+float render_font::string_width(float height, float aspect, const char *string)
+{
+ // loop over the string and accumulate widths
+ int totwidth = 0;
+ for (const unsigned char *ptr = (const unsigned char *)string; *ptr != 0; ptr++)
+ totwidth += get_char(*ptr).width;
+
+ // scale the final result based on height
+ return (float)totwidth * m_scale * height * aspect;
+}
+
+
+//-------------------------------------------------
+// utf8string_width - return the width of a
+// UTF8-encoded string at the given height
+//-------------------------------------------------
+
+float render_font::utf8string_width(float height, float aspect, const char *utf8string)
+{
+ int length = strlen(utf8string);
+
+ // loop over the string and accumulate widths
+ int count;
+ int totwidth = 0;
+ for (int offset = 0; offset < length; offset += count)
+ {
+ unicode_char uchar;
+ count = uchar_from_utf8(&uchar, utf8string + offset, length - offset);
+ if (count == -1)
+ break;
+ if (uchar < 0x10000)
+ totwidth += get_char(uchar).width;
+ }
+
+ // scale the final result based on height
+ return (float)totwidth * m_scale * height * aspect;
+}
+
+
+//-------------------------------------------------
+// load_cached_bdf - attempt to load a cached
+// version of the BDF font 'filename'; if that
+// fails, fall back on the regular BDF loader
+// and create a new cached version
+//-------------------------------------------------
+
+bool render_font::load_cached_bdf(const char *filename)
+{
+ // first try to open the BDF itself
+ emu_file file(manager().machine().options().font_path(), OPEN_FLAG_READ);
+ file_error filerr = file.open(filename);
+ if (filerr != FILERR_NONE)
+ return false;
+
+ // determine the file size and allocate memory
+ m_rawsize = file.size();
+ char *data = auto_alloc_array_clear(m_manager.machine(), char, m_rawsize + 1);
+
+ // read the first chunk
+ UINT32 bytes = file.read(data, MIN(CACHED_BDF_HASH_SIZE, m_rawsize));
+ if (bytes != MIN(CACHED_BDF_HASH_SIZE, m_rawsize))
+ return false;
+
+ // has the chunk
+ UINT32 hash = crc32(0, (const UINT8 *)data, bytes) ^ (UINT32)m_rawsize;
+
+ // create the cached filename, changing the 'F' to a 'C' on the extension
+ astring cachedname(filename);
+ cachedname.del(cachedname.len() - 3, 3).cat("bdc");
+
+ // attempt to open the cached version of the font
+ {
+ emu_file cachefile(manager().machine().options().font_path(), OPEN_FLAG_READ);
+ filerr = cachefile.open(cachedname);
+ if (filerr == FILERR_NONE)
+ {
+ // if we have a cached version, load it
+ bool result = load_cached(cachefile, hash);
+
+ // if that worked, we're done
+ if (result)
+ {
+ auto_free(m_manager.machine(), data);
+ return true;
+ }
+ }
+ }
+
+ // read in the rest of the font
+ if (bytes < m_rawsize)
+ {
+ UINT32 read = file.read(data + bytes, m_rawsize - bytes);
+ if (read != m_rawsize - bytes)
+ {
+ auto_free(m_manager.machine(), data);
+ return false;
+ }
+ }
+
+ // NULL-terminate the data and attach it to the font
+ data[m_rawsize] = 0;
+ m_rawdata = data;
+
+ // load the BDF
+ bool result = load_bdf();
+
+ // if we loaded okay, create a cached one
+ if (result)
+ save_cached(cachedname, hash);
+
+ // close the file
+ return result;
+}
+
+
+//-------------------------------------------------
+// load_bdf - parse and load a BDF font
+//-------------------------------------------------
+
+bool render_font::load_bdf()
+{
+ // set the format to text
+ m_format = FF_TEXT;
+
+ // first find the FONTBOUNDINGBOX tag
+ const char *ptr;
+ for (ptr = m_rawdata; ptr != NULL; ptr = next_line(ptr))
+ {
+ // we only care about a tiny few fields
+ if (strncmp(ptr, "FONTBOUNDINGBOX ", 16) == 0)
+ {
+ int dummy1, dummy2;
+ if (sscanf(ptr + 16, "%d %d %d %d", &dummy1, &m_height, &dummy2, &m_yoffs) != 4)
+ return false;
+ break;
+ }
+ }
+
+ // compute the scale factor
+ m_scale = 1.0f / (float)m_height;
+
+ // now scan for characters
+ int charcount = 0;
+ for ( ; ptr != NULL; ptr = next_line(ptr))
+ {
+ // stop at ENDFONT
+ if (strncmp(ptr, "ENDFONT", 7) == 0)
+ break;
+
+ // once we hit a STARTCHAR, parse until the end
+ if (strncmp(ptr, "STARTCHAR ", 10) == 0)
+ {
+ int bmwidth = -1, bmheight = -1, xoffs = -1, yoffs = -1;
+ const char *rawdata = NULL;
+ int charnum = -1;
+ int width = -1;
+
+ // scan for interesting per-character tags
+ for ( ; ptr != NULL; ptr = next_line(ptr))
+ {
+ // ENCODING tells us which character
+ if (strncmp(ptr, "ENCODING ", 9) == 0)
+ {
+ if (sscanf(ptr + 9, "%d", &charnum) != 1)
+ return 1;
+ }
+
+ // DWIDTH tells us the width to the next character
+ else if (strncmp(ptr, "DWIDTH ", 7) == 0)
+ {
+ int dummy1;
+ if (sscanf(ptr + 7, "%d %d", &width, &dummy1) != 2)
+ return 1;
+ }
+
+ // BBX tells us the height/width of the bitmap and the offsets
+ else if (strncmp(ptr, "BBX ", 4) == 0)
+ {
+ if (sscanf(ptr + 4, "%d %d %d %d", &bmwidth, &bmheight, &xoffs, &yoffs) != 4)
+ return 1;
+ }
+
+ // BITMAP is the start of the data
+ else if (strncmp(ptr, "BITMAP", 6) == 0)
+ {
+ // stash the raw pointer and scan for the end of the character
+ for (rawdata = ptr = next_line(ptr); ptr != NULL && strncmp(ptr, "ENDCHAR", 7) != 0; ptr = next_line(ptr)) ;
+ break;
+ }
+ }
+
+ // if we have everything, allocate a new character
+ if (charnum >= 0 && charnum < 65536 && rawdata != NULL && bmwidth >= 0 && bmheight >= 0)
+ {
+ // if we don't have a subtable yet, make one
+ if (m_glyphs[charnum / 256] == NULL)
+ m_glyphs[charnum / 256] = auto_alloc_array_clear(m_manager.machine(), glyph, 256);
+
+ // fill in the entry
+ glyph &gl = m_glyphs[charnum / 256][charnum % 256];
+ gl.width = width;
+ gl.bmwidth = bmwidth;
+ gl.bmheight = bmheight;
+ gl.xoffs = xoffs;
+ gl.yoffs = yoffs;
+ gl.rawdata = rawdata;
+ }
+
+ // some progress for big fonts
+ if (++charcount % 256 == 0)
+ mame_printf_warning("Loading BDF font... (%d characters loaded)\n", charcount);
+ }
+ }
+
+ // make sure all the numbers are the same width
+ if (m_glyphs[0] != NULL)
+ {
+ int maxwidth = 0;
+ for (int ch = '0'; ch <= '9'; ch++)
+ if (m_glyphs[0][ch].bmwidth > maxwidth)
+ maxwidth = m_glyphs[0][ch].width;
+ for (int ch = '0'; ch <= '9'; ch++)
+ m_glyphs[0][ch].width = maxwidth;
+ }
+
+ return true;
+}
+
+
+//-------------------------------------------------
+// load_cached - load a font in cached format
+//-------------------------------------------------
+
+bool render_font::load_cached(emu_file &file, UINT32 hash)
+{
+ // get the file size
+ UINT64 filesize = file.size();
+
+ // first read the header
+ UINT8 header[CACHED_HEADER_SIZE];
+ UINT32 bytes_read = file.read(header, CACHED_HEADER_SIZE);
+ if (bytes_read != CACHED_HEADER_SIZE)
+ return false;
+
+ // validate the header
+ if (header[0] != 'f' || header[1] != 'o' || header[2] != 'n' || header[3] != 't')
+ return false;
+ if (header[4] != (UINT8)(hash >> 24) || header[5] != (UINT8)(hash >> 16) || header[6] != (UINT8)(hash >> 8) || header[7] != (UINT8)hash)
+ return false;
+ m_height = (header[8] << 8) | header[9];
+ m_scale = 1.0f / (float)m_height;
+ m_yoffs = (INT16)((header[10] << 8) | header[11]);
+ int numchars = (header[12] << 24) | (header[13] << 16) | (header[14] << 8) | header[15];
+ if (filesize - CACHED_HEADER_SIZE < numchars * CACHED_CHAR_SIZE)
+ return false;
+
+ // now read the rest of the data
+ UINT8 *data = auto_alloc_array(m_manager.machine(), UINT8, filesize - CACHED_HEADER_SIZE);
+ bytes_read = file.read(data, filesize - CACHED_HEADER_SIZE);
+ if (bytes_read != filesize - CACHED_HEADER_SIZE)
+ {
+ auto_free(m_manager.machine(), data);
+ return false;
+ }
+
+ // extract the data from the data
+ UINT64 offset = numchars * CACHED_CHAR_SIZE;
+ for (int chindex = 0; chindex < numchars; chindex++)
+ {
+ const UINT8 *info = &data[chindex * CACHED_CHAR_SIZE];
+ int chnum = (info[0] << 8) | info[1];
+
+ // if we don't have a subtable yet, make one
+ if (m_glyphs[chnum / 256] == NULL)
+ m_glyphs[chnum / 256] = auto_alloc_array_clear(m_manager.machine(), glyph, 256);
+
+ // fill in the entry
+ glyph &gl = m_glyphs[chnum / 256][chnum % 256];
+ gl.width = (info[2] << 8) | info[3];
+ gl.xoffs = (INT16)((info[4] << 8) | info[5]);
+ gl.yoffs = (INT16)((info[6] << 8) | info[7]);
+ gl.bmwidth = (info[8] << 8) | info[9];
+ gl.bmheight = (info[10] << 8) | info[11];
+ gl.rawdata = (char *)data + offset;
+
+ // advance the offset past the character
+ offset += (gl.bmwidth * gl.bmheight + 7) / 8;
+ if (offset > filesize - CACHED_HEADER_SIZE)
+ {
+ auto_free(m_manager.machine(), data);
+ return false;
+ }
+ }
+
+ // reuse the chartable as a temporary buffer
+ m_format = FF_CACHED;
+ m_rawdata = (char *)data;
+ return true;
+}
+
+
+//-------------------------------------------------
+// save_cached - save a font in cached format
+//-------------------------------------------------
+
+bool render_font::save_cached(const char *filename, UINT32 hash)
+{
+ mame_printf_warning("Generating cached BDF font...\n");
+
+ // attempt to open the file
+ emu_file file(manager().machine().options().font_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE);
+ file_error filerr = file.open(filename);
+ if (filerr != FILERR_NONE)
+ return false;
+
+ // determine the number of characters
+ int numchars = 0;
+ for (int chnum = 0; chnum < 65536; chnum++)
+ {
+ glyph *chtable = m_glyphs[chnum / 256];
+ if (chtable != NULL)
+ {
+ glyph &gl = chtable[chnum % 256];
+ if (gl.width > 0)
+ numchars++;
+ }
+ }
+
+ UINT8 *chartable = NULL;
+ UINT8 *tempbuffer = NULL;
+ try
+ {
+ // allocate an array to hold the character data
+ chartable = auto_alloc_array_clear(m_manager.machine(), UINT8, numchars * CACHED_CHAR_SIZE);
+
+ // allocate a temp buffer to compress into
+ tempbuffer = auto_alloc_array(m_manager.machine(), UINT8, 65536);
+
+ // write the header
+ UINT8 *dest = tempbuffer;
+ *dest++ = 'f';
+ *dest++ = 'o';
+ *dest++ = 'n';
+ *dest++ = 't';
+ *dest++ = hash >> 24;
+ *dest++ = hash >> 16;
+ *dest++ = hash >> 8;
+ *dest++ = hash & 0xff;
+ *dest++ = m_height >> 8;
+ *dest++ = m_height & 0xff;
+ *dest++ = m_yoffs >> 8;
+ *dest++ = m_yoffs & 0xff;
+ *dest++ = numchars >> 24;
+ *dest++ = numchars >> 16;
+ *dest++ = numchars >> 8;
+ *dest++ = numchars & 0xff;
+ assert(dest - tempbuffer == CACHED_HEADER_SIZE);
+ UINT32 bytes_written = file.write(tempbuffer, dest - tempbuffer);
+ if (bytes_written != dest - tempbuffer)
+ throw emu_fatalerror("Error writing cached file");
+
+ // write the empty table to the beginning of the file
+ bytes_written = file.write(chartable, numchars * CACHED_CHAR_SIZE);
+ if (bytes_written != numchars * CACHED_CHAR_SIZE)
+ throw emu_fatalerror("Error writing cached file");
+
+ // loop over all characters
+ int tableindex = 0;
+ for (int chnum = 0; chnum < 65536; chnum++)
+ {
+ glyph &gl = get_char(chnum);
+ if (gl.width > 0)
+ {
+ // write out a bit-compressed bitmap if we have one
+ if (gl.bitmap != NULL)
+ {
+ // write the data to the tempbuffer
+ dest = tempbuffer;
+ UINT8 accum = 0;
+ UINT8 accbit = 7;
+
+ // bit-encode the character data
+ for (int y = 0; y < gl.bmheight; y++)
+ {
+ int desty = y + m_height + m_yoffs - gl.yoffs - gl.bmheight;
+ const UINT32 *src = (desty >= 0 && desty < m_height) ? BITMAP_ADDR32(gl.bitmap, desty, 0) : NULL;
+ for (int x = 0; x < gl.bmwidth; x++)
+ {
+ if (src != NULL && RGB_ALPHA(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 = file.write(tempbuffer, dest - tempbuffer);
+ if (bytes_written != dest - tempbuffer)
+ throw emu_fatalerror("Error writing cached file");
+
+ // free the bitmap and texture
+ m_manager.texture_free(gl.texture);
+ auto_free(m_manager.machine(), gl.bitmap);
+ gl.texture = NULL;
+ gl.bitmap = NULL;
+ }
+
+ // compute the table entry
+ dest = &chartable[tableindex++ * CACHED_CHAR_SIZE];
+ *dest++ = chnum >> 8;
+ *dest++ = chnum & 0xff;
+ *dest++ = gl.width >> 8;
+ *dest++ = gl.width & 0xff;
+ *dest++ = gl.xoffs >> 8;
+ *dest++ = gl.xoffs & 0xff;
+ *dest++ = gl.yoffs >> 8;
+ *dest++ = gl.yoffs & 0xff;
+ *dest++ = gl.bmwidth >> 8;
+ *dest++ = gl.bmwidth & 0xff;
+ *dest++ = gl.bmheight >> 8;
+ *dest++ = gl.bmheight & 0xff;
+ }
+ }
+
+ // seek back to the beginning and rewrite the table
+ file.seek(CACHED_HEADER_SIZE, SEEK_SET);
+ bytes_written = file.write(chartable, numchars * CACHED_CHAR_SIZE);
+ if (bytes_written != numchars * CACHED_CHAR_SIZE)
+ throw emu_fatalerror("Error writing cached file");
+
+ // all done
+ auto_free(m_manager.machine(), tempbuffer);
+ auto_free(m_manager.machine(), chartable);
+ return true;
+ }
+ catch (...)
+ {
+ file.remove_on_close();
+ auto_free(m_manager.machine(), tempbuffer);
+ auto_free(m_manager.machine(), chartable);
+ return false;
+ }
+}
diff --git a/trunk/src/emu/rendfont.h b/trunk/src/emu/rendfont.h
new file mode 100644
index 00000000000..8d8ad66a450
--- /dev/null
+++ b/trunk/src/emu/rendfont.h
@@ -0,0 +1,125 @@
+/***************************************************************************
+
+ rendfont.h
+
+ Rendering system font 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.
+
+***************************************************************************/
+
+#ifndef __RENDFONT_H__
+#define __RENDFONT_H__
+
+#include "render.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> render_font
+
+// a render_font describes and provides an interface to a font
+class render_font
+{
+ friend class render_manager;
+ friend resource_pool_object<render_font>::~resource_pool_object();
+
+ // construction/destruction
+ render_font(render_manager &manager, const char *filename);
+ virtual ~render_font();
+
+public:
+ // getters
+ render_manager &manager() const { return m_manager; }
+
+ // size queries
+ INT32 pixel_height() const { return m_height; }
+ float char_width(float height, float aspect, unicode_char ch);
+ float string_width(float height, float aspect, const char *string);
+ float utf8string_width(float height, float aspect, const char *utf8string);
+
+ // texture/bitmap queries
+ render_texture *get_char_texture_and_bounds(float height, float aspect, unicode_char ch, render_bounds &bounds);
+ void get_scaled_bitmap_and_bounds(bitmap_t &dest, float height, float aspect, unicode_char chnum, rectangle &bounds);
+
+private:
+ // a glyph describes a single glyph
+ class glyph
+ {
+ public:
+ 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
+ const char * rawdata; // pointer to the raw data for this one
+ bitmap_t * bitmap; // pointer to the bitmap containing the raw data
+ render_texture * texture; // pointer to a texture for rendering and sizing
+ };
+
+ // internal format
+ enum format
+ {
+ FF_UNKNOWN,
+ FF_TEXT,
+ FF_CACHED,
+ FF_OSD
+ };
+
+ // helpers
+ glyph &get_char(unicode_char chnum);
+ void char_expand(unicode_char chnum, glyph &ch);
+ bool load_cached_bdf(const char *filename);
+ bool load_bdf();
+ bool load_cached(emu_file &file, UINT32 hash);
+ bool save_cached(const char *filename, UINT32 hash);
+
+ // internal state
+ render_manager & m_manager;
+ format m_format; // format of font data
+ int m_height; // height of the font, from ascent to descent
+ int m_yoffs; // y offset from baseline to descent
+ float m_scale; // 1 / height precomputed
+ glyph * m_glyphs[256]; // array of glyph subtables
+ const char * m_rawdata; // pointer to the raw data for the font
+ UINT64 m_rawsize; // size of the raw font data
+ osd_font m_osdfont; // handle to the OSD font
+
+ // constants
+ static const int CACHED_CHAR_SIZE = 12;
+ static const int CACHED_HEADER_SIZE = 16;
+ static const int CACHED_BDF_HASH_SIZE = 1024;
+};
+
+
+#endif /* __RENDFONT_H__ */
diff --git a/trunk/src/emu/rendlay.c b/trunk/src/emu/rendlay.c
new file mode 100644
index 00000000000..773589969c0
--- /dev/null
+++ b/trunk/src/emu/rendlay.c
@@ -0,0 +1,1984 @@
+/***************************************************************************
+
+ rendlay.c
+
+ Core rendering layout parser and manager.
+
+****************************************************************************
+
+ 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.
+
+****************************************************************************
+
+ Overview of objects:
+
+ layout_file -- A layout_file comprises a list of elements and a
+ list of views. The elements are reusable items that the views
+ reference.
+
+ layout_view -- A layout_view describes a single view within a
+ layout_file. The view is described using arbitrary coordinates
+ that are scaled to fit within the render target. Pixels within
+ a view are assumed to be square.
+
+ view_item -- Each view has four lists of view_items, one for each
+ "layer." Each view item is specified using floating point
+ coordinates in arbitrary units, and is assumed to have square
+ pixels. Each view item can control its orientation independently.
+ Each item can also have an optional name, and can be set at
+ runtime into different "states", which control how the embedded
+ elements are displayed.
+
+ layout_element -- A layout_element is a description of a piece of
+ visible artwork. Most view_items (except for those in the screen
+ layer) have exactly one layout_element which describes the
+ contents of the item. Elements are separate from items because
+ they can be re-used multiple times within a layout. Even though
+ an element can contain a number of components, they are treated
+ as if they were a single bitmap.
+
+ element_component -- Each layout_element contains one or more
+ components. Each component can describe either an image or
+ a rectangle/disk primitive. Each component also has a "state"
+ associated with it, which controls whether or not the component
+ is visible (if the owning item has the same state, it is
+ visible).
+
+***************************************************************************/
+
+#include <ctype.h>
+
+#include "emu.h"
+#include "emuopts.h"
+#include "render.h"
+#include "rendfont.h"
+#include "rendlay.h"
+#include "rendutil.h"
+#include "output.h"
+#include "xmlfile.h"
+#include "png.h"
+
+
+
+/***************************************************************************
+ STANDARD LAYOUTS
+***************************************************************************/
+
+// screenless layouts
+#include "noscreens.lh"
+
+// single screen layouts
+#include "horizont.lh"
+#include "vertical.lh"
+
+// dual screen layouts
+#include "dualhsxs.lh"
+#include "dualhovu.lh"
+#include "dualhuov.lh"
+
+// triple screen layouts
+#include "triphsxs.lh"
+
+// quad screen layouts
+#include "quadhsxs.lh"
+
+// generic color overlay layouts
+#include "ho20ffff.lh"
+#include "ho2eff2e.lh"
+#include "ho4f893d.lh"
+#include "ho88ffff.lh"
+#include "hoa0a0ff.lh"
+#include "hoffe457.lh"
+#include "voffff20.lh"
+#include "hoffff20.lh"
+
+// LCD screen layouts
+#include "lcd.lh"
+#include "lcd_rot.lh"
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+const int LAYOUT_VERSION = 2;
+
+enum
+{
+ LINE_CAP_NONE = 0,
+ LINE_CAP_START = 1,
+ LINE_CAP_END = 2
+};
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const render_screen_list render_target::s_empty_screen_list;
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// gcd - compute the greatest common divisor (GCD)
+// of two integers using the Euclidean algorithm
+//-------------------------------------------------
+
+inline int gcd(int a, int b)
+{
+ while (b != 0)
+ {
+ int t = b;
+ b = a % b;
+ a = t;
+ }
+ return a;
+}
+
+
+//-------------------------------------------------
+// reduce_fraction - reduce a fraction by
+// dividing out common factors
+//-------------------------------------------------
+
+inline void reduce_fraction(int &num, int &den)
+{
+ // search the greatest common divisor
+ int div = gcd(num, den);
+
+ // reduce the fraction if a common divisor has been found
+ if (div > 1)
+ {
+ num /= div;
+ den /= div;
+ }
+}
+
+
+
+//**************************************************************************
+// SHARED PARSING HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// get_variable_value - compute the value of
+// a variable in an XML attribute
+//-------------------------------------------------
+
+static int get_variable_value(running_machine &machine, const char *string, char **outputptr)
+{
+ char temp[100];
+
+ // screen 0 parameters
+ for (const screen_device *device = machine.first_screen(); device != NULL; device = device->next_screen())
+ {
+ int scrnum = machine.devicelist().indexof(SCREEN, device->tag());
+
+ // native X aspect factor
+ sprintf(temp, "~scr%dnativexaspect~", scrnum);
+ if (!strncmp(string, temp, strlen(temp)))
+ {
+ int num = device->visible_area().max_x + 1 - device->visible_area().min_x;
+ int den = device->visible_area().max_y + 1 - device->visible_area().min_y;
+ reduce_fraction(num, den);
+ *outputptr += sprintf(*outputptr, "%d", num);
+ return strlen(temp);
+ }
+
+ // native Y aspect factor
+ sprintf(temp, "~scr%dnativeyaspect~", scrnum);
+ if (!strncmp(string, temp, strlen(temp)))
+ {
+ int num = device->visible_area().max_x + 1 - device->visible_area().min_x;
+ int den = device->visible_area().max_y + 1 - device->visible_area().min_y;
+ reduce_fraction(num, den);
+ *outputptr += sprintf(*outputptr, "%d", den);
+ return strlen(temp);
+ }
+
+ // native width
+ sprintf(temp, "~scr%dwidth~", scrnum);
+ if (!strncmp(string, temp, strlen(temp)))
+ {
+ *outputptr += sprintf(*outputptr, "%d", device->visible_area().max_x + 1 - device->visible_area().min_x);
+ return strlen(temp);
+ }
+
+ // native height
+ sprintf(temp, "~scr%dheight~", scrnum);
+ if (!strncmp(string, temp, strlen(temp)))
+ {
+ *outputptr += sprintf(*outputptr, "%d", device->visible_area().max_y + 1 - device->visible_area().min_y);
+ return strlen(temp);
+ }
+ }
+
+ // default: copy the first character and continue
+ **outputptr = *string;
+ *outputptr += 1;
+ return 1;
+}
+
+
+//-------------------------------------------------
+// xml_get_attribute_string_with_subst - analog
+// to xml_get_attribute_string but with variable
+// substitution
+//-------------------------------------------------
+
+static const char *xml_get_attribute_string_with_subst(running_machine &machine, xml_data_node &node, const char *attribute, const char *defvalue)
+{
+ const char *str = xml_get_attribute_string(&node, attribute, NULL);
+ static char buffer[1000];
+
+ // if nothing, just return the default
+ if (str == NULL)
+ return defvalue;
+
+ // if no tildes, don't worry
+ if (strchr(str, '~') == NULL)
+ return str;
+
+ // make a copy of the string, doing substitutions along the way
+ const char *s;
+ char *d;
+ for (s = str, d = buffer; *s != 0; )
+ {
+ // if not a variable, just copy
+ if (*s != '~')
+ *d++ = *s++;
+
+ // extract the variable
+ else
+ s += get_variable_value(machine, s, &d);
+ }
+ *d = 0;
+ return buffer;
+}
+
+
+//-------------------------------------------------
+// xml_get_attribute_int_with_subst - analog
+// to xml_get_attribute_int but with variable
+// substitution
+//-------------------------------------------------
+
+static int xml_get_attribute_int_with_subst(running_machine &machine, xml_data_node &node, const char *attribute, int defvalue)
+{
+ const char *string = xml_get_attribute_string_with_subst(machine, node, attribute, NULL);
+ int value;
+
+ if (string == NULL)
+ return defvalue;
+ if (string[0] == '$')
+ return (sscanf(&string[1], "%X", &value) == 1) ? value : defvalue;
+ if (string[0] == '0' && string[1] == 'x')
+ return (sscanf(&string[2], "%X", &value) == 1) ? value : defvalue;
+ if (string[0] == '#')
+ return (sscanf(&string[1], "%d", &value) == 1) ? value : defvalue;
+ return (sscanf(&string[0], "%d", &value) == 1) ? value : defvalue;
+}
+
+
+//-------------------------------------------------
+// xml_get_attribute_float_with_subst - analog
+// to xml_get_attribute_float but with variable
+// substitution
+//-------------------------------------------------
+
+static float xml_get_attribute_float_with_subst(running_machine &machine, xml_data_node &node, const char *attribute, float defvalue)
+{
+ const char *string = xml_get_attribute_string_with_subst(machine, node, attribute, NULL);
+ float value;
+
+ if (string == NULL || sscanf(string, "%f", &value) != 1)
+ return defvalue;
+ return value;
+}
+
+
+//-------------------------------------------------
+// parse_bounds - parse a bounds XML node
+//-------------------------------------------------
+
+void parse_bounds(running_machine &machine, xml_data_node *boundsnode, render_bounds &bounds)
+{
+ // skip if nothing
+ if (boundsnode == NULL)
+ {
+ bounds.x0 = bounds.y0 = 0.0f;
+ bounds.x1 = bounds.y1 = 1.0f;
+ return;
+ }
+
+ // parse out the data
+ if (xml_get_attribute(boundsnode, "left") != NULL)
+ {
+ // left/right/top/bottom format
+ bounds.x0 = xml_get_attribute_float_with_subst(machine, *boundsnode, "left", 0.0f);
+ bounds.x1 = xml_get_attribute_float_with_subst(machine, *boundsnode, "right", 1.0f);
+ bounds.y0 = xml_get_attribute_float_with_subst(machine, *boundsnode, "top", 0.0f);
+ bounds.y1 = xml_get_attribute_float_with_subst(machine, *boundsnode, "bottom", 1.0f);
+ }
+ else if (xml_get_attribute(boundsnode, "x") != NULL)
+ {
+ // x/y/width/height format
+ bounds.x0 = xml_get_attribute_float_with_subst(machine, *boundsnode, "x", 0.0f);
+ bounds.x1 = bounds.x0 + xml_get_attribute_float_with_subst(machine, *boundsnode, "width", 1.0f);
+ bounds.y0 = xml_get_attribute_float_with_subst(machine, *boundsnode, "y", 0.0f);
+ bounds.y1 = bounds.y0 + xml_get_attribute_float_with_subst(machine, *boundsnode, "height", 1.0f);
+ }
+ else
+ throw emu_fatalerror("Illegal bounds value in XML");
+
+ // check for errors
+ if (bounds.x0 > bounds.x1 || bounds.y0 > bounds.y1)
+ throw emu_fatalerror("Illegal bounds value in XML: (%f-%f)-(%f-%f)", bounds.x0, bounds.x1, bounds.y0, bounds.y1);
+}
+
+
+//-------------------------------------------------
+// parse_color - parse a color XML node
+//-------------------------------------------------
+
+void parse_color(running_machine &machine, xml_data_node *colornode, render_color &color)
+{
+ // skip if nothing
+ if (colornode == NULL)
+ {
+ color.r = color.g = color.b = color.a = 1.0f;
+ return;
+ }
+
+ // parse out the data
+ color.r = xml_get_attribute_float_with_subst(machine, *colornode, "red", 1.0);
+ color.g = xml_get_attribute_float_with_subst(machine, *colornode, "green", 1.0);
+ color.b = xml_get_attribute_float_with_subst(machine, *colornode, "blue", 1.0);
+ color.a = xml_get_attribute_float_with_subst(machine, *colornode, "alpha", 1.0);
+
+ // check for errors
+ if (color.r < 0.0 || color.r > 1.0 || color.g < 0.0 || color.g > 1.0 ||
+ color.b < 0.0 || color.b > 1.0 || color.a < 0.0 || color.a > 1.0)
+ throw emu_fatalerror("Illegal ARGB color value in XML: %f,%f,%f,%f", color.r, color.g, color.b, color.a);
+}
+
+
+//-------------------------------------------------
+// parse_orientation - parse an orientation XML
+// node
+//-------------------------------------------------
+
+static void parse_orientation(running_machine &machine, xml_data_node *orientnode, int &orientation)
+{
+ // skip if nothing
+ if (orientnode == NULL)
+ {
+ orientation = ROT0;
+ return;
+ }
+
+ // parse out the data
+ int rotate = xml_get_attribute_int_with_subst(machine, *orientnode, "rotate", 0);
+ switch (rotate)
+ {
+ case 0: orientation = ROT0; break;
+ case 90: orientation = ROT90; break;
+ case 180: orientation = ROT180; break;
+ case 270: orientation = ROT270; break;
+ default: throw emu_fatalerror("Invalid rotation in XML orientation node: %d", rotate); break;
+ }
+ if (strcmp("yes", xml_get_attribute_string_with_subst(machine, *orientnode, "swapxy", "no")) == 0)
+ orientation ^= ORIENTATION_SWAP_XY;
+ if (strcmp("yes", xml_get_attribute_string_with_subst(machine, *orientnode, "flipx", "no")) == 0)
+ orientation ^= ORIENTATION_FLIP_X;
+ if (strcmp("yes", xml_get_attribute_string_with_subst(machine, *orientnode, "flipy", "no")) == 0)
+ orientation ^= ORIENTATION_FLIP_Y;
+}
+
+
+
+//**************************************************************************
+// LAYOUT ELEMENT
+//**************************************************************************
+
+//-------------------------------------------------
+// layout_element - constructor
+//-------------------------------------------------
+
+layout_element::layout_element(running_machine &machine, xml_data_node &elemnode, const char *dirname)
+ : m_next(NULL),
+ m_machine(machine),
+ m_complist(machine.respool()),
+ m_defstate(0),
+ m_maxstate(0),
+ m_elemtex(NULL)
+{
+ // extract the name
+ const char *name = xml_get_attribute_string_with_subst(machine, elemnode, "name", NULL);
+ if (name == NULL)
+ throw emu_fatalerror("All layout elements must have a name!\n");
+ m_name = name;
+
+ // get the default state
+ m_defstate = xml_get_attribute_int_with_subst(machine, elemnode, "defstate", -1);
+
+ // parse components in order
+ bool first = true;
+ render_bounds bounds = { 0 };
+ for (xml_data_node *compnode = elemnode.child; compnode != NULL; compnode = compnode->next)
+ {
+ // allocate a new component
+ component &newcomp = m_complist.append(*auto_alloc(machine, component(machine, *compnode, dirname)));
+
+ // accumulate bounds
+ if (first)
+ bounds = newcomp.m_bounds;
+ else
+ union_render_bounds(&bounds, &newcomp.m_bounds);
+ first = false;
+
+ // determine the maximum state
+ if (newcomp.m_state > m_maxstate)
+ m_maxstate = newcomp.m_state;
+ if (newcomp.m_type == component::CTYPE_LED7SEG)
+ m_maxstate = 255;
+ if (newcomp.m_type == component::CTYPE_LED14SEG)
+ m_maxstate = 16383;
+ if (newcomp.m_type == component::CTYPE_LED14SEGSC || newcomp.m_type == component::CTYPE_LED16SEG)
+ m_maxstate = 65535;
+ if (newcomp.m_type == component::CTYPE_LED16SEGSC)
+ m_maxstate = 262143;
+ if (newcomp.m_type == component::CTYPE_DOTMATRIX)
+ m_maxstate = 255;
+ }
+
+ // determine the scale/offset for normalization
+ float xoffs = bounds.x0;
+ float yoffs = bounds.y0;
+ float xscale = 1.0f / (bounds.x1 - bounds.x0);
+ float yscale = 1.0f / (bounds.y1 - bounds.y0);
+
+ // normalize all the component bounds
+ for (component *curcomp = m_complist.first(); curcomp != NULL; curcomp = curcomp->next())
+ {
+ curcomp->m_bounds.x0 = (curcomp->m_bounds.x0 - xoffs) * xscale;
+ curcomp->m_bounds.x1 = (curcomp->m_bounds.x1 - xoffs) * xscale;
+ curcomp->m_bounds.y0 = (curcomp->m_bounds.y0 - yoffs) * yscale;
+ curcomp->m_bounds.y1 = (curcomp->m_bounds.y1 - yoffs) * yscale;
+ }
+
+ // allocate an array of element textures for the states
+ m_elemtex = auto_alloc_array(machine, texture, m_maxstate + 1);
+}
+
+
+//-------------------------------------------------
+// ~layout_element - destructor
+//-------------------------------------------------
+
+layout_element::~layout_element()
+{
+ // loop over all states and free their textures
+ auto_free(machine(), m_elemtex);
+}
+
+
+//-------------------------------------------------
+// state_texture - return a pointer to a
+// render_texture for the given state, allocating
+// one if needed
+//-------------------------------------------------
+
+render_texture *layout_element::state_texture(int state)
+{
+ assert(state <= m_maxstate);
+ if (m_elemtex[state].m_texture == NULL)
+ {
+ m_elemtex[state].m_element = this;
+ m_elemtex[state].m_state = state;
+ m_elemtex[state].m_texture = machine().render().texture_alloc(element_scale, &m_elemtex[state]);
+ }
+ return m_elemtex[state].m_texture;
+}
+
+
+//-------------------------------------------------
+// element_scale - scale an element by rendering
+// all the components at the appropriate
+// resolution
+//-------------------------------------------------
+
+void layout_element::element_scale(bitmap_t &dest, const bitmap_t &source, const rectangle &sbounds, void *param)
+{
+ texture *elemtex = (texture *)param;
+
+ // iterate over components that are part of the current state
+ for (component *curcomp = elemtex->m_element->m_complist.first(); curcomp != NULL; curcomp = curcomp->next())
+ if (curcomp->m_state == -1 || curcomp->m_state == elemtex->m_state)
+ {
+ // get the local scaled bounds
+ rectangle bounds;
+ bounds.min_x = render_round_nearest(curcomp->bounds().x0 * dest.width);
+ bounds.min_y = render_round_nearest(curcomp->bounds().y0 * dest.height);
+ bounds.max_x = render_round_nearest(curcomp->bounds().x1 * dest.width);
+ bounds.max_y = render_round_nearest(curcomp->bounds().y1 * dest.height);
+
+ // based on the component type, add to the texture
+ curcomp->draw(elemtex->m_element->machine(), dest, bounds, elemtex->m_state);
+ }
+}
+
+
+//**************************************************************************
+// LAYOUT ELEMENT TEXTURE
+//**************************************************************************
+
+//-------------------------------------------------
+// texture - constructor
+//-------------------------------------------------
+
+layout_element::texture::texture()
+ : m_element(NULL),
+ m_texture(NULL),
+ m_state(0)
+{
+}
+
+
+//-------------------------------------------------
+// ~texture - destructor
+//-------------------------------------------------
+
+layout_element::texture::~texture()
+{
+ if (m_element != NULL)
+ m_element->machine().render().texture_free(m_texture);
+}
+
+
+
+//**************************************************************************
+// LAYOUT ELEMENT COMPONENT
+//**************************************************************************
+
+//-------------------------------------------------
+// component - constructor
+//-------------------------------------------------
+
+layout_element::component::component(running_machine &machine, xml_data_node &compnode, const char *dirname)
+ : m_next(NULL),
+ m_type(CTYPE_INVALID),
+ m_state(0),
+ m_bitmap(NULL),
+ m_file(NULL),
+ m_hasalpha(false)
+{
+ // fetch common data
+ m_state = xml_get_attribute_int_with_subst(machine, compnode, "state", -1);
+ parse_bounds(machine, xml_get_sibling(compnode.child, "bounds"), m_bounds);
+ parse_color(machine, xml_get_sibling(compnode.child, "color"), m_color);
+
+ // image nodes
+ if (strcmp(compnode.name, "image") == 0)
+ {
+ m_type = CTYPE_IMAGE;
+ m_dirname = dirname;
+ m_imagefile = xml_get_attribute_string_with_subst(machine, compnode, "file", "");
+ m_alphafile = xml_get_attribute_string_with_subst(machine, compnode, "alphafile", "");
+ m_file = global_alloc(emu_file(machine.options().art_path(), OPEN_FLAG_READ));
+ }
+
+ // text nodes
+ else if (strcmp(compnode.name, "text") == 0)
+ {
+ m_type = CTYPE_TEXT;
+ m_string = xml_get_attribute_string_with_subst(machine, compnode, "string", "");
+ }
+
+ // dotmatrix nodes
+ else if (strcmp(compnode.name, "dotmatrix") == 0)
+ m_type = CTYPE_DOTMATRIX;
+
+ // led7seg nodes
+ else if (strcmp(compnode.name, "led7seg") == 0)
+ m_type = CTYPE_LED7SEG;
+
+ // led14seg nodes
+ else if (strcmp(compnode.name, "led14seg") == 0)
+ m_type = CTYPE_LED14SEG;
+
+ // led14segsc nodes
+ else if (strcmp(compnode.name, "led14segsc") == 0)
+ m_type = CTYPE_LED14SEGSC;
+
+ // led16seg nodes
+ else if (strcmp(compnode.name, "led16seg") == 0)
+ m_type = CTYPE_LED16SEG;
+
+ // led16segsc nodes
+ else if (strcmp(compnode.name, "led16segsc") == 0)
+ m_type = CTYPE_LED16SEGSC;
+
+ // rect nodes
+ else if (strcmp(compnode.name, "rect") == 0)
+ m_type = CTYPE_RECT;
+
+ // disk nodes
+ else if (strcmp(compnode.name, "disk") == 0)
+ m_type = CTYPE_DISK;
+
+ // error otherwise
+ else
+ throw emu_fatalerror("Unknown element component: %s", compnode.name);
+}
+
+
+//-------------------------------------------------
+// ~component - destructor
+//-------------------------------------------------
+
+layout_element::component::~component()
+{
+ global_free(m_file);
+ global_free(m_bitmap);
+}
+
+
+//-------------------------------------------------
+// draw - draw a component
+//-------------------------------------------------
+
+void layout_element::component::draw(running_machine &machine, bitmap_t &dest, const rectangle &bounds, int state)
+{
+ switch (m_type)
+ {
+ case CTYPE_IMAGE:
+ if (m_bitmap == NULL)
+ m_bitmap = load_bitmap();
+ render_resample_argb_bitmap_hq(
+ BITMAP_ADDR32(&dest, bounds.min_y, bounds.min_x),
+ dest.rowpixels,
+ bounds.max_x - bounds.min_x,
+ bounds.max_y - bounds.min_y,
+ m_bitmap, NULL, &m_color);
+ break;
+
+ case CTYPE_RECT:
+ draw_rect(dest, bounds);
+ break;
+
+ case CTYPE_DISK:
+ draw_disk(dest, bounds);
+ break;
+
+ case CTYPE_TEXT:
+ draw_text(machine, dest, bounds);
+ break;
+
+ case CTYPE_LED7SEG:
+ draw_led7seg(dest, bounds, state);
+ break;
+
+ case CTYPE_LED14SEG:
+ draw_led14seg(dest, bounds, state);
+ break;
+
+ case CTYPE_LED16SEG:
+ draw_led16seg(dest, bounds, state);
+ break;
+
+ case CTYPE_LED14SEGSC:
+ draw_led14segsc(dest, bounds, state);
+ break;
+
+ case CTYPE_LED16SEGSC:
+ draw_led16segsc(dest, bounds, state);
+ break;
+
+ case CTYPE_DOTMATRIX:
+ draw_dotmatrix(dest, bounds, state);
+ break;
+
+ default:
+ throw emu_fatalerror("Unknown component type requested draw()");
+ }
+}
+
+
+//-------------------------------------------------
+// draw_rect - draw a rectangle in the specified
+// color
+//-------------------------------------------------
+
+void layout_element::component::draw_rect(bitmap_t &dest, const rectangle &bounds)
+{
+ // compute premultiplied colors
+ UINT32 r = m_color.r * m_color.a * 255.0;
+ UINT32 g = m_color.g * m_color.a * 255.0;
+ UINT32 b = m_color.b * m_color.a * 255.0;
+ UINT32 inva = (1.0f - m_color.a) * 255.0;
+
+ // iterate over X and Y
+ for (UINT32 y = bounds.min_y; y < bounds.max_y; y++)
+ for (UINT32 x = bounds.min_x; x < bounds.max_x; x++)
+ {
+ UINT32 finalr = r;
+ UINT32 finalg = g;
+ UINT32 finalb = b;
+
+ // if we're translucent, add in the destination pixel contribution
+ if (inva > 0)
+ {
+ UINT32 dpix = *BITMAP_ADDR32(&dest, y, x);
+ finalr += (RGB_RED(dpix) * inva) >> 8;
+ finalg += (RGB_GREEN(dpix) * inva) >> 8;
+ finalb += (RGB_BLUE(dpix) * inva) >> 8;
+ }
+
+ // store the target pixel, dividing the RGBA values by the overall scale factor
+ *BITMAP_ADDR32(&dest, y, x) = MAKE_ARGB(0xff, finalr, finalg, finalb);
+ }
+}
+
+
+//-------------------------------------------------
+// draw_disk - draw an ellipse in the specified
+// color
+//-------------------------------------------------
+
+void layout_element::component::draw_disk(bitmap_t &dest, const rectangle &bounds)
+{
+ // compute premultiplied colors
+ UINT32 r = m_color.r * m_color.a * 255.0;
+ UINT32 g = m_color.g * m_color.a * 255.0;
+ UINT32 b = m_color.b * m_color.a * 255.0;
+ UINT32 inva = (1.0f - m_color.a) * 255.0;
+
+ // find the center
+ float xcenter = (float)(bounds.min_x + bounds.max_x) * 0.5f;
+ float ycenter = (float)(bounds.min_y + bounds.max_y) * 0.5f;
+ float xradius = (float)(bounds.max_x - bounds.min_x) * 0.5f;
+ float yradius = (float)(bounds.max_y - bounds.min_y) * 0.5f;
+ float ooyradius2 = 1.0f / (yradius * yradius);
+
+ // iterate over y
+ for (UINT32 y = bounds.min_y; y < bounds.max_y; y++)
+ {
+ float ycoord = ycenter - ((float)y + 0.5f);
+ float xval = xradius * sqrt(1.0f - (ycoord * ycoord) * ooyradius2);
+
+ // compute left/right coordinates
+ INT32 left = (INT32)(xcenter - xval + 0.5f);
+ INT32 right = (INT32)(xcenter + xval + 0.5f);
+
+ // draw this scanline
+ for (UINT32 x = left; x < right; x++)
+ {
+ UINT32 finalr = r;
+ UINT32 finalg = g;
+ UINT32 finalb = b;
+
+ // if we're translucent, add in the destination pixel contribution
+ if (inva > 0)
+ {
+ UINT32 dpix = *BITMAP_ADDR32(&dest, y, x);
+ finalr += (RGB_RED(dpix) * inva) >> 8;
+ finalg += (RGB_GREEN(dpix) * inva) >> 8;
+ finalb += (RGB_BLUE(dpix) * inva) >> 8;
+ }
+
+ // store the target pixel, dividing the RGBA values by the overall scale factor
+ *BITMAP_ADDR32(&dest, y, x) = MAKE_ARGB(0xff, finalr, finalg, finalb);
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// draw_text - draw text in the specified color
+//-------------------------------------------------
+
+void layout_element::component::draw_text(running_machine &machine, bitmap_t &dest, const rectangle &bounds)
+{
+ // compute premultiplied colors
+ UINT32 r = m_color.r * 255.0;
+ UINT32 g = m_color.g * 255.0;
+ UINT32 b = m_color.b * 255.0;
+ UINT32 a = m_color.a * 255.0;
+
+ // get the width of the string
+ render_font *font = machine.render().font_alloc("default");
+ float aspect = 1.0f;
+ INT32 width;
+ while (1)
+ {
+ width = font->string_width(bounds.max_y - bounds.min_y, aspect, m_string);
+ if (width < bounds.max_x - bounds.min_x)
+ break;
+ aspect *= 0.9f;
+ }
+ INT32 curx = bounds.min_x + (bounds.max_x - bounds.min_x - width) / 2;
+
+ // allocate a temporary bitmap
+ bitmap_t *tempbitmap = global_alloc(bitmap_t(dest.width, dest.height, BITMAP_FORMAT_ARGB32));
+
+ // loop over characters
+ for (const char *s = m_string; *s != 0; s++)
+ {
+ // get the font bitmap
+ rectangle chbounds;
+ font->get_scaled_bitmap_and_bounds(*tempbitmap, bounds.max_y - bounds.min_y, aspect, *s, chbounds);
+
+ // copy the data into the target
+ for (int y = 0; y < chbounds.max_y - chbounds.min_y; y++)
+ {
+ int effy = bounds.min_y + y;
+ if (effy >= bounds.min_y && effy <= bounds.max_y)
+ {
+ UINT32 *src = BITMAP_ADDR32(tempbitmap, y, 0);
+ UINT32 *d = BITMAP_ADDR32(&dest, effy, 0);
+ for (int x = 0; x < chbounds.max_x - chbounds.min_x; x++)
+ {
+ int effx = curx + x + chbounds.min_x;
+ if (effx >= bounds.min_x && effx <= bounds.max_x)
+ {
+ UINT32 spix = RGB_ALPHA(src[x]);
+ if (spix != 0)
+ {
+ UINT32 dpix = d[effx];
+ UINT32 ta = (a * (spix + 1)) >> 8;
+ UINT32 tr = (r * ta + RGB_RED(dpix) * (0x100 - ta)) >> 8;
+ UINT32 tg = (g * ta + RGB_GREEN(dpix) * (0x100 - ta)) >> 8;
+ UINT32 tb = (b * ta + RGB_BLUE(dpix) * (0x100 - ta)) >> 8;
+ d[effx] = MAKE_ARGB(0xff, tr, tg, tb);
+ }
+ }
+ }
+ }
+ }
+
+ // advance in the X direction
+ curx += font->char_width(bounds.max_y - bounds.min_y, aspect, *s);
+ }
+
+ // free the temporary bitmap and font
+ global_free(tempbitmap);
+ machine.render().font_free(font);
+}
+
+
+//-------------------------------------------------
+// load_bitmap - load a PNG file with artwork for
+// a component
+//-------------------------------------------------
+
+bitmap_t *layout_element::component::load_bitmap()
+{
+ // load the basic bitmap
+ assert(m_file != NULL);
+ bitmap_t *bitmap = render_load_png(*m_file, m_dirname, m_imagefile, NULL, &m_hasalpha);
+ if (bitmap != NULL && m_alphafile)
+
+ // load the alpha bitmap if specified
+ if (render_load_png(*m_file, m_dirname, m_alphafile, bitmap, &m_hasalpha) == NULL)
+ {
+ global_free(bitmap);
+ bitmap = NULL;
+ }
+
+ // if we can't load the bitmap, allocate a dummy one and report an error
+ if (bitmap == NULL)
+ {
+ // draw some stripes in the bitmap
+ bitmap = global_alloc(bitmap_t(100, 100, BITMAP_FORMAT_ARGB32));
+ bitmap_fill(bitmap, NULL, 0);
+ for (int step = 0; step < 100; step += 25)
+ for (int line = 0; line < 100; line++)
+ *BITMAP_ADDR32(bitmap, (step + line) % 100, line % 100) = MAKE_ARGB(0xff,0xff,0xff,0xff);
+
+ // log an error
+ if (!m_alphafile)
+ mame_printf_warning("Unable to load component bitmap '%s'", m_imagefile.cstr());
+ else
+ mame_printf_warning("Unable to load component bitmap '%s'/'%s'", m_imagefile.cstr(), m_alphafile.cstr());
+ }
+
+ return bitmap;
+}
+
+
+//-------------------------------------------------
+// draw_led7seg - draw a 7-segment LCD
+//-------------------------------------------------
+
+void layout_element::component::draw_led7seg(bitmap_t &dest, const rectangle &bounds, int pattern)
+{
+ const rgb_t onpen = MAKE_ARGB(0xff,0xff,0xff,0xff);
+ const rgb_t offpen = MAKE_ARGB(0xff,0x20,0x20,0x20);
+
+ // sizes for computation
+ int bmwidth = 250;
+ int bmheight = 400;
+ int segwidth = 40;
+ int skewwidth = 40;
+
+ // allocate a temporary bitmap for drawing
+ bitmap_t *tempbitmap = global_alloc(bitmap_t(bmwidth + skewwidth, bmheight, BITMAP_FORMAT_ARGB32));
+ bitmap_fill(tempbitmap, NULL, MAKE_ARGB(0xff,0x00,0x00,0x00));
+
+ // top bar
+ draw_segment_horizontal(*tempbitmap, 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, 0 + segwidth/2, segwidth, (pattern & (1 << 0)) ? onpen : offpen);
+
+ // top-right bar
+ draw_segment_vertical(*tempbitmap, 0 + 2*segwidth/3, bmheight/2 - segwidth/3, bmwidth - segwidth/2, segwidth, (pattern & (1 << 1)) ? onpen : offpen);
+
+ // bottom-right bar
+ draw_segment_vertical(*tempbitmap, bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, bmwidth - segwidth/2, segwidth, (pattern & (1 << 2)) ? onpen : offpen);
+
+ // bottom bar
+ draw_segment_horizontal(*tempbitmap, 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, bmheight - segwidth/2, segwidth, (pattern & (1 << 3)) ? onpen : offpen);
+
+ // bottom-left bar
+ draw_segment_vertical(*tempbitmap, bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, 0 + segwidth/2, segwidth, (pattern & (1 << 4)) ? onpen : offpen);
+
+ // top-left bar
+ draw_segment_vertical(*tempbitmap, 0 + 2*segwidth/3, bmheight/2 - segwidth/3, 0 + segwidth/2, segwidth, (pattern & (1 << 5)) ? onpen : offpen);
+
+ // middle bar
+ draw_segment_horizontal(*tempbitmap, 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, bmheight/2, segwidth, (pattern & (1 << 6)) ? onpen : offpen);
+
+ // apply skew
+ apply_skew(*tempbitmap, 40);
+
+ // decimal point
+ draw_segment_decimal(*tempbitmap, bmwidth + segwidth/2, bmheight - segwidth/2, segwidth, (pattern & (1 << 7)) ? onpen : offpen);
+
+ // resample to the target size
+ render_resample_argb_bitmap_hq(dest.base, dest.rowpixels, dest.width, dest.height, tempbitmap, NULL, &m_color);
+
+ global_free(tempbitmap);
+}
+
+
+//-------------------------------------------------
+// draw_led14seg - draw a 14-segment LCD
+//-------------------------------------------------
+
+void layout_element::component::draw_led14seg(bitmap_t &dest, const rectangle &bounds, int pattern)
+{
+ const rgb_t onpen = MAKE_ARGB(0xff, 0xff, 0xff, 0xff);
+ const rgb_t offpen = MAKE_ARGB(0xff, 0x20, 0x20, 0x20);
+
+ // sizes for computation
+ int bmwidth = 250;
+ int bmheight = 400;
+ int segwidth = 40;
+ int skewwidth = 40;
+
+ // allocate a temporary bitmap for drawing
+ bitmap_t *tempbitmap = global_alloc(bitmap_t(bmwidth + skewwidth, bmheight, BITMAP_FORMAT_ARGB32));
+ bitmap_fill(tempbitmap, NULL, MAKE_ARGB(0xff, 0x00, 0x00, 0x00));
+
+ // top bar
+ draw_segment_horizontal(*tempbitmap,
+ 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, 0 + segwidth/2,
+ segwidth, (pattern & (1 << 0)) ? onpen : offpen);
+
+ // right-top bar
+ draw_segment_vertical(*tempbitmap,
+ 0 + 2*segwidth/3, bmheight/2 - segwidth/3, bmwidth - segwidth/2,
+ segwidth, (pattern & (1 << 1)) ? onpen : offpen);
+
+ // right-bottom bar
+ draw_segment_vertical(*tempbitmap,
+ bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, bmwidth - segwidth/2,
+ segwidth, (pattern & (1 << 2)) ? onpen : offpen);
+
+ // bottom bar
+ draw_segment_horizontal(*tempbitmap,
+ 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, bmheight - segwidth/2,
+ segwidth, (pattern & (1 << 3)) ? onpen : offpen);
+
+ // left-bottom bar
+ draw_segment_vertical(*tempbitmap,
+ bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, 0 + segwidth/2,
+ segwidth, (pattern & (1 << 4)) ? onpen : offpen);
+
+ // left-top bar
+ draw_segment_vertical(*tempbitmap,
+ 0 + 2*segwidth/3, bmheight/2 - segwidth/3, 0 + segwidth/2,
+ segwidth, (pattern & (1 << 5)) ? onpen : offpen);
+
+ // horizontal-middle-left bar
+ draw_segment_horizontal_caps(*tempbitmap,
+ 0 + 2*segwidth/3, bmwidth/2 - segwidth/10, bmheight/2,
+ segwidth, LINE_CAP_START, (pattern & (1 << 6)) ? onpen : offpen);
+
+ // horizontal-middle-right bar
+ draw_segment_horizontal_caps(*tempbitmap,
+ 0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, bmheight/2,
+ segwidth, LINE_CAP_END, (pattern & (1 << 7)) ? onpen : offpen);
+
+ // vertical-middle-top bar
+ draw_segment_vertical_caps(*tempbitmap,
+ 0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3, bmwidth/2,
+ segwidth, LINE_CAP_NONE, (pattern & (1 << 8)) ? onpen : offpen);
+
+ // vertical-middle-bottom bar
+ draw_segment_vertical_caps(*tempbitmap,
+ bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3, bmwidth/2,
+ segwidth, LINE_CAP_NONE, (pattern & (1 << 9)) ? onpen : offpen);
+
+ // diagonal-left-bottom bar
+ draw_segment_diagonal_1(*tempbitmap,
+ 0 + segwidth + segwidth/5, bmwidth/2 - segwidth/2 - segwidth/5,
+ bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3,
+ segwidth, (pattern & (1 << 10)) ? onpen : offpen);
+
+ // diagonal-left-top bar
+ draw_segment_diagonal_2(*tempbitmap,
+ 0 + segwidth + segwidth/5, bmwidth/2 - segwidth/2 - segwidth/5,
+ 0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3,
+ segwidth, (pattern & (1 << 11)) ? onpen : offpen);
+
+ // diagonal-right-top bar
+ draw_segment_diagonal_1(*tempbitmap,
+ bmwidth/2 + segwidth/2 + segwidth/5, bmwidth - segwidth - segwidth/5,
+ 0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3,
+ segwidth, (pattern & (1 << 12)) ? onpen : offpen);
+
+ // diagonal-right-bottom bar
+ draw_segment_diagonal_2(*tempbitmap,
+ bmwidth/2 + segwidth/2 + segwidth/5, bmwidth - segwidth - segwidth/5,
+ bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3,
+ segwidth, (pattern & (1 << 13)) ? onpen : offpen);
+
+ // apply skew
+ apply_skew(*tempbitmap, 40);
+
+ // resample to the target size
+ render_resample_argb_bitmap_hq(dest.base, dest.rowpixels, dest.width, dest.height, tempbitmap, NULL, &m_color);
+
+ global_free(tempbitmap);
+}
+
+
+//-------------------------------------------------
+// draw_led14segsc - draw a 14-segment LCD with
+// semicolon (2 extra segments)
+//-------------------------------------------------
+
+void layout_element::component::draw_led14segsc(bitmap_t &dest, const rectangle &bounds, int pattern)
+{
+ const rgb_t onpen = MAKE_ARGB(0xff, 0xff, 0xff, 0xff);
+ const rgb_t offpen = MAKE_ARGB(0xff, 0x20, 0x20, 0x20);
+
+ // sizes for computation
+ int bmwidth = 250;
+ int bmheight = 400;
+ int segwidth = 40;
+ int skewwidth = 40;
+
+ // allocate a temporary bitmap for drawing, adding some extra space for the tail
+ bitmap_t *tempbitmap = global_alloc(bitmap_t(bmwidth + skewwidth, bmheight + segwidth, BITMAP_FORMAT_ARGB32));
+ bitmap_fill(tempbitmap, NULL, MAKE_ARGB(0xff, 0x00, 0x00, 0x00));
+
+ // top bar
+ draw_segment_horizontal(*tempbitmap,
+ 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, 0 + segwidth/2,
+ segwidth, (pattern & (1 << 0)) ? onpen : offpen);
+
+ // right-top bar
+ draw_segment_vertical(*tempbitmap,
+ 0 + 2*segwidth/3, bmheight/2 - segwidth/3, bmwidth - segwidth/2,
+ segwidth, (pattern & (1 << 1)) ? onpen : offpen);
+
+ // right-bottom bar
+ draw_segment_vertical(*tempbitmap,
+ bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, bmwidth - segwidth/2,
+ segwidth, (pattern & (1 << 2)) ? onpen : offpen);
+
+ // bottom bar
+ draw_segment_horizontal(*tempbitmap,
+ 0 + 2*segwidth/3, bmwidth - 2*segwidth/3, bmheight - segwidth/2,
+ segwidth, (pattern & (1 << 3)) ? onpen : offpen);
+
+ // left-bottom bar
+ draw_segment_vertical(*tempbitmap,
+ bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, 0 + segwidth/2,
+ segwidth, (pattern & (1 << 4)) ? onpen : offpen);
+
+ // left-top bar
+ draw_segment_vertical(*tempbitmap,
+ 0 + 2*segwidth/3, bmheight/2 - segwidth/3, 0 + segwidth/2,
+ segwidth, (pattern & (1 << 5)) ? onpen : offpen);
+
+ // horizontal-middle-left bar
+ draw_segment_horizontal_caps(*tempbitmap,
+ 0 + 2*segwidth/3, bmwidth/2 - segwidth/10, bmheight/2,
+ segwidth, LINE_CAP_START, (pattern & (1 << 6)) ? onpen : offpen);
+
+ // horizontal-middle-right bar
+ draw_segment_horizontal_caps(*tempbitmap,
+ 0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, bmheight/2,
+ segwidth, LINE_CAP_END, (pattern & (1 << 7)) ? onpen : offpen);
+
+ // vertical-middle-top bar
+ draw_segment_vertical_caps(*tempbitmap,
+ 0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3, bmwidth/2,
+ segwidth, LINE_CAP_NONE, (pattern & (1 << 8)) ? onpen : offpen);
+
+ // vertical-middle-bottom bar
+ draw_segment_vertical_caps(*tempbitmap,
+ bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3, bmwidth/2,
+ segwidth, LINE_CAP_NONE, (pattern & (1 << 9)) ? onpen : offpen);
+
+ // diagonal-left-bottom bar
+ draw_segment_diagonal_1(*tempbitmap,
+ 0 + segwidth + segwidth/5, bmwidth/2 - segwidth/2 - segwidth/5,
+ bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3,
+ segwidth, (pattern & (1 << 10)) ? onpen : offpen);
+
+ // diagonal-left-top bar
+ draw_segment_diagonal_2(*tempbitmap,
+ 0 + segwidth + segwidth/5, bmwidth/2 - segwidth/2 - segwidth/5,
+ 0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3,
+ segwidth, (pattern & (1 << 11)) ? onpen : offpen);
+
+ // diagonal-right-top bar
+ draw_segment_diagonal_1(*tempbitmap,
+ bmwidth/2 + segwidth/2 + segwidth/5, bmwidth - segwidth - segwidth/5,
+ 0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3,
+ segwidth, (pattern & (1 << 12)) ? onpen : offpen);
+
+ // diagonal-right-bottom bar
+ draw_segment_diagonal_2(*tempbitmap,
+ bmwidth/2 + segwidth/2 + segwidth/5, bmwidth - segwidth - segwidth/5,
+ bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3,
+ segwidth, (pattern & (1 << 13)) ? onpen : offpen);
+
+ // apply skew
+ apply_skew(*tempbitmap, 40);
+
+ // comma tail
+ draw_segment_diagonal_1(*tempbitmap,
+ bmwidth - (segwidth/2), bmwidth + segwidth,
+ bmheight - (segwidth), bmheight + segwidth*1.5,
+ segwidth/2, (pattern & (1 << 15)) ? onpen : offpen);
+
+ // decimal point
+ draw_segment_decimal(*tempbitmap, bmwidth + segwidth/2, bmheight - segwidth/2, segwidth, (pattern & (1 << 14)) ? onpen : offpen);
+
+ // resample to the target size
+ render_resample_argb_bitmap_hq(dest.base, dest.rowpixels, dest.width, dest.height, tempbitmap, NULL, &m_color);
+
+ global_free(tempbitmap);
+}
+
+
+//-------------------------------------------------
+// draw_led16seg - draw a 16-segment LCD
+//-------------------------------------------------
+
+void layout_element::component::draw_led16seg(bitmap_t &dest, const rectangle &bounds, int pattern)
+{
+ const rgb_t onpen = MAKE_ARGB(0xff, 0xff, 0xff, 0xff);
+ const rgb_t offpen = MAKE_ARGB(0xff, 0x20, 0x20, 0x20);
+
+ // sizes for computation
+ int bmwidth = 250;
+ int bmheight = 400;
+ int segwidth = 40;
+ int skewwidth = 40;
+
+ // allocate a temporary bitmap for drawing
+ bitmap_t *tempbitmap = global_alloc(bitmap_t(bmwidth + skewwidth, bmheight, BITMAP_FORMAT_ARGB32));
+ bitmap_fill(tempbitmap, NULL, MAKE_ARGB(0xff, 0x00, 0x00, 0x00));
+
+ // top-left bar
+ draw_segment_horizontal_caps(*tempbitmap,
+ 0 + 2*segwidth/3, bmwidth/2 - segwidth/10, 0 + segwidth/2,
+ segwidth, LINE_CAP_START, (pattern & (1 << 0)) ? onpen : offpen);
+
+ // top-right bar
+ draw_segment_horizontal_caps(*tempbitmap,
+ 0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, 0 + segwidth/2,
+ segwidth, LINE_CAP_END, (pattern & (1 << 1)) ? onpen : offpen);
+
+ // right-top bar
+ draw_segment_vertical(*tempbitmap,
+ 0 + 2*segwidth/3, bmheight/2 - segwidth/3, bmwidth - segwidth/2,
+ segwidth, (pattern & (1 << 2)) ? onpen : offpen);
+
+ // right-bottom bar
+ draw_segment_vertical(*tempbitmap,
+ bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, bmwidth - segwidth/2,
+ segwidth, (pattern & (1 << 3)) ? onpen : offpen);
+
+ // bottom-right bar
+ draw_segment_horizontal_caps(*tempbitmap,
+ 0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, bmheight - segwidth/2,
+ segwidth, LINE_CAP_END, (pattern & (1 << 4)) ? onpen : offpen);
+
+ // bottom-left bar
+ draw_segment_horizontal_caps(*tempbitmap,
+ 0 + 2*segwidth/3, bmwidth/2 - segwidth/10, bmheight - segwidth/2,
+ segwidth, LINE_CAP_START, (pattern & (1 << 5)) ? onpen : offpen);
+
+ // left-bottom bar
+ draw_segment_vertical(*tempbitmap,
+ bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, 0 + segwidth/2,
+ segwidth, (pattern & (1 << 6)) ? onpen : offpen);
+
+ // left-top bar
+ draw_segment_vertical(*tempbitmap,
+ 0 + 2*segwidth/3, bmheight/2 - segwidth/3, 0 + segwidth/2,
+ segwidth, (pattern & (1 << 7)) ? onpen : offpen);
+
+ // horizontal-middle-left bar
+ draw_segment_horizontal_caps(*tempbitmap,
+ 0 + 2*segwidth/3, bmwidth/2 - segwidth/10, bmheight/2,
+ segwidth, LINE_CAP_START, (pattern & (1 << 8)) ? onpen : offpen);
+
+ // horizontal-middle-right bar
+ draw_segment_horizontal_caps(*tempbitmap,
+ 0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, bmheight/2,
+ segwidth, LINE_CAP_END, (pattern & (1 << 9)) ? onpen : offpen);
+
+ // vertical-middle-top bar
+ draw_segment_vertical_caps(*tempbitmap,
+ 0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3, bmwidth/2,
+ segwidth, LINE_CAP_NONE, (pattern & (1 << 10)) ? onpen : offpen);
+
+ // vertical-middle-bottom bar
+ draw_segment_vertical_caps(*tempbitmap,
+ bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3, bmwidth/2,
+ segwidth, LINE_CAP_NONE, (pattern & (1 << 11)) ? onpen : offpen);
+
+ // diagonal-left-bottom bar
+ draw_segment_diagonal_1(*tempbitmap,
+ 0 + segwidth + segwidth/5, bmwidth/2 - segwidth/2 - segwidth/5,
+ bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3,
+ segwidth, (pattern & (1 << 12)) ? onpen : offpen);
+
+ // diagonal-left-top bar
+ draw_segment_diagonal_2(*tempbitmap,
+ 0 + segwidth + segwidth/5, bmwidth/2 - segwidth/2 - segwidth/5,
+ 0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3,
+ segwidth, (pattern & (1 << 13)) ? onpen : offpen);
+
+ // diagonal-right-top bar
+ draw_segment_diagonal_1(*tempbitmap,
+ bmwidth/2 + segwidth/2 + segwidth/5, bmwidth - segwidth - segwidth/5,
+ 0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3,
+ segwidth, (pattern & (1 << 14)) ? onpen : offpen);
+
+ // diagonal-right-bottom bar
+ draw_segment_diagonal_2(*tempbitmap,
+ bmwidth/2 + segwidth/2 + segwidth/5, bmwidth - segwidth - segwidth/5,
+ bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3,
+ segwidth, (pattern & (1 << 15)) ? onpen : offpen);
+
+ // apply skew
+ apply_skew(*tempbitmap, 40);
+
+ // resample to the target size
+ render_resample_argb_bitmap_hq(dest.base, dest.rowpixels, dest.width, dest.height, tempbitmap, NULL, &m_color);
+
+ global_free(tempbitmap);
+}
+
+
+//-------------------------------------------------
+// draw_led16segsc - draw a 16-segment LCD with
+// semicolon (2 extra segments)
+//-------------------------------------------------
+
+void layout_element::component::draw_led16segsc(bitmap_t &dest, const rectangle &bounds, int pattern)
+{
+ const rgb_t onpen = MAKE_ARGB(0xff, 0xff, 0xff, 0xff);
+ const rgb_t offpen = MAKE_ARGB(0xff, 0x20, 0x20, 0x20);
+
+ // sizes for computation
+ int bmwidth = 250;
+ int bmheight = 400;
+ int segwidth = 40;
+ int skewwidth = 40;
+
+ // allocate a temporary bitmap for drawing
+ bitmap_t *tempbitmap = global_alloc(bitmap_t(bmwidth + skewwidth, bmheight + segwidth, BITMAP_FORMAT_ARGB32));
+ bitmap_fill(tempbitmap, NULL, MAKE_ARGB(0xff, 0x00, 0x00, 0x00));
+
+ // top-left bar
+ draw_segment_horizontal_caps(*tempbitmap,
+ 0 + 2*segwidth/3, bmwidth/2 - segwidth/10, 0 + segwidth/2,
+ segwidth, LINE_CAP_START, (pattern & (1 << 0)) ? onpen : offpen);
+
+ // top-right bar
+ draw_segment_horizontal_caps(*tempbitmap,
+ 0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, 0 + segwidth/2,
+ segwidth, LINE_CAP_END, (pattern & (1 << 1)) ? onpen : offpen);
+
+ // right-top bar
+ draw_segment_vertical(*tempbitmap,
+ 0 + 2*segwidth/3, bmheight/2 - segwidth/3, bmwidth - segwidth/2,
+ segwidth, (pattern & (1 << 2)) ? onpen : offpen);
+
+ // right-bottom bar
+ draw_segment_vertical(*tempbitmap,
+ bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, bmwidth - segwidth/2,
+ segwidth, (pattern & (1 << 3)) ? onpen : offpen);
+
+ // bottom-right bar
+ draw_segment_horizontal_caps(*tempbitmap,
+ 0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, bmheight - segwidth/2,
+ segwidth, LINE_CAP_END, (pattern & (1 << 4)) ? onpen : offpen);
+
+ // bottom-left bar
+ draw_segment_horizontal_caps(*tempbitmap,
+ 0 + 2*segwidth/3, bmwidth/2 - segwidth/10, bmheight - segwidth/2,
+ segwidth, LINE_CAP_START, (pattern & (1 << 5)) ? onpen : offpen);
+
+ // left-bottom bar
+ draw_segment_vertical(*tempbitmap,
+ bmheight/2 + segwidth/3, bmheight - 2*segwidth/3, 0 + segwidth/2,
+ segwidth, (pattern & (1 << 6)) ? onpen : offpen);
+
+ // left-top bar
+ draw_segment_vertical(*tempbitmap,
+ 0 + 2*segwidth/3, bmheight/2 - segwidth/3, 0 + segwidth/2,
+ segwidth, (pattern & (1 << 7)) ? onpen : offpen);
+
+ // horizontal-middle-left bar
+ draw_segment_horizontal_caps(*tempbitmap,
+ 0 + 2*segwidth/3, bmwidth/2 - segwidth/10, bmheight/2,
+ segwidth, LINE_CAP_START, (pattern & (1 << 8)) ? onpen : offpen);
+
+ // horizontal-middle-right bar
+ draw_segment_horizontal_caps(*tempbitmap,
+ 0 + bmwidth/2 + segwidth/10, bmwidth - 2*segwidth/3, bmheight/2,
+ segwidth, LINE_CAP_END, (pattern & (1 << 9)) ? onpen : offpen);
+
+ // vertical-middle-top bar
+ draw_segment_vertical_caps(*tempbitmap,
+ 0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3, bmwidth/2,
+ segwidth, LINE_CAP_NONE, (pattern & (1 << 10)) ? onpen : offpen);
+
+ // vertical-middle-bottom bar
+ draw_segment_vertical_caps(*tempbitmap,
+ bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3, bmwidth/2,
+ segwidth, LINE_CAP_NONE, (pattern & (1 << 11)) ? onpen : offpen);
+
+ // diagonal-left-bottom bar
+ draw_segment_diagonal_1(*tempbitmap,
+ 0 + segwidth + segwidth/5, bmwidth/2 - segwidth/2 - segwidth/5,
+ bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3,
+ segwidth, (pattern & (1 << 12)) ? onpen : offpen);
+
+ // diagonal-left-top bar
+ draw_segment_diagonal_2(*tempbitmap,
+ 0 + segwidth + segwidth/5, bmwidth/2 - segwidth/2 - segwidth/5,
+ 0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3,
+ segwidth, (pattern & (1 << 13)) ? onpen : offpen);
+
+ // diagonal-right-top bar
+ draw_segment_diagonal_1(*tempbitmap,
+ bmwidth/2 + segwidth/2 + segwidth/5, bmwidth - segwidth - segwidth/5,
+ 0 + segwidth + segwidth/3, bmheight/2 - segwidth/2 - segwidth/3,
+ segwidth, (pattern & (1 << 14)) ? onpen : offpen);
+
+ // diagonal-right-bottom bar
+ draw_segment_diagonal_2(*tempbitmap,
+ bmwidth/2 + segwidth/2 + segwidth/5, bmwidth - segwidth - segwidth/5,
+ bmheight/2 + segwidth/2 + segwidth/3, bmheight - segwidth - segwidth/3,
+ segwidth, (pattern & (1 << 15)) ? onpen : offpen);
+
+ // comma tail
+ draw_segment_diagonal_1(*tempbitmap,
+ bmwidth - (segwidth/2), bmwidth + segwidth,
+ bmheight - (segwidth), bmheight + segwidth*1.5,
+ segwidth/2, (pattern & (1 << 17)) ? onpen : offpen);
+
+ // decimal point (draw last for priority)
+ draw_segment_decimal(*tempbitmap, bmwidth + segwidth/2, bmheight - segwidth/2, segwidth, (pattern & (1 << 16)) ? onpen : offpen);
+
+ // apply skew
+ apply_skew(*tempbitmap, 40);
+
+ // resample to the target size
+ render_resample_argb_bitmap_hq(dest.base, dest.rowpixels, dest.width, dest.height, tempbitmap, NULL, &m_color);
+
+ global_free(tempbitmap);
+}
+
+
+//-------------------------------------------------
+// draw_dotmatrix - draw a row of 8 dots for a
+// dotmatrix
+//-------------------------------------------------
+
+void layout_element::component::draw_dotmatrix(bitmap_t &dest, const rectangle &bounds, int pattern)
+{
+ const rgb_t onpen = MAKE_ARGB(0xff, 0xff, 0xff, 0xff);
+ const rgb_t offpen = MAKE_ARGB(0xff, 0x20, 0x20, 0x20);
+
+ // sizes for computation
+ int bmwidth = 2000;
+ int bmheight = 300;
+ int dotwidth = 250;
+
+ // allocate a temporary bitmap for drawing
+ bitmap_t *tempbitmap = global_alloc(bitmap_t(bmwidth, bmheight, BITMAP_FORMAT_ARGB32));
+ bitmap_fill(tempbitmap, NULL, MAKE_ARGB(0xff, 0x00, 0x00, 0x00));
+
+ for (int i = 0; i < 8; i++)
+ draw_segment_decimal(*tempbitmap, ((dotwidth/2 )+ (i * dotwidth)), bmheight/2, dotwidth, (pattern & (1 << i))?onpen:offpen);
+
+ // resample to the target size
+ render_resample_argb_bitmap_hq(dest.base, dest.rowpixels, dest.width, dest.height, tempbitmap, NULL, &m_color);
+
+ global_free(tempbitmap);
+}
+
+
+//-------------------------------------------------
+// draw_segment_horizontal_caps - draw a
+// horizontal LED segment with definable end
+// and start points
+//-------------------------------------------------
+
+void layout_element::component::draw_segment_horizontal_caps(bitmap_t &dest, int minx, int maxx, int midy, int width, int caps, rgb_t color)
+{
+ // loop over the width of the segment
+ for (int y = 0; y < width / 2; y++)
+ {
+ UINT32 *d0 = BITMAP_ADDR32(&dest, midy - y, 0);
+ UINT32 *d1 = BITMAP_ADDR32(&dest, midy + y, 0);
+ int ty = (y < width / 8) ? width / 8 : y;
+
+ // loop over the length of the segment
+ for (int x = minx + ((caps & LINE_CAP_START) ? ty : 0); x < maxx - ((caps & LINE_CAP_END) ? ty : 0); x++)
+ d0[x] = d1[x] = color;
+ }
+}
+
+
+//-------------------------------------------------
+// draw_segment_horizontal - draw a horizontal
+// LED segment
+//-------------------------------------------------
+
+void layout_element::component::draw_segment_horizontal(bitmap_t &dest, int minx, int maxx, int midy, int width, rgb_t color)
+{
+ draw_segment_horizontal_caps(dest, minx, maxx, midy, width, LINE_CAP_START | LINE_CAP_END, color);
+}
+
+
+//-------------------------------------------------
+// draw_segment_vertical_caps - draw a
+// vertical LED segment with definable end
+// and start points
+//-------------------------------------------------
+
+void layout_element::component::draw_segment_vertical_caps(bitmap_t &dest, int miny, int maxy, int midx, int width, int caps, rgb_t color)
+{
+ // loop over the width of the segment
+ for (int x = 0; x < width / 2; x++)
+ {
+ UINT32 *d0 = BITMAP_ADDR32(&dest, 0, midx - x);
+ UINT32 *d1 = BITMAP_ADDR32(&dest, 0, midx + x);
+ int tx = (x < width / 8) ? width / 8 : x;
+
+ // loop over the length of the segment
+ for (int y = miny + ((caps & LINE_CAP_START) ? tx : 0); y < maxy - ((caps & LINE_CAP_END) ? tx : 0); y++)
+ d0[y * dest.rowpixels] = d1[y * dest.rowpixels] = color;
+ }
+}
+
+
+//-------------------------------------------------
+// draw_segment_vertical - draw a vertical
+// LED segment
+//-------------------------------------------------
+
+void layout_element::component::draw_segment_vertical(bitmap_t &dest, int miny, int maxy, int midx, int width, rgb_t color)
+{
+ draw_segment_vertical_caps(dest, miny, maxy, midx, width, LINE_CAP_START | LINE_CAP_END, color);
+}
+
+
+//-------------------------------------------------
+// draw_segment_diagonal_1 - draw a diagonal
+// LED segment that looks like this: /
+//-------------------------------------------------
+
+void layout_element::component::draw_segment_diagonal_1(bitmap_t &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color)
+{
+ // compute parameters
+ width *= 1.5;
+ float ratio = (maxy - miny - width) / (float)(maxx - minx);
+
+ // draw line
+ for (int x = minx; x < maxx; x++)
+ if (x >= 0 && x < dest.width)
+ {
+ UINT32 *d = BITMAP_ADDR32(&dest, 0, x);
+ int step = (x - minx) * ratio;
+
+ for (int y = maxy - width - step; y < maxy - step; y++)
+ if (y >= 0 && y < dest.height)
+ d[y * dest.rowpixels] = color;
+ }
+}
+
+
+//-------------------------------------------------
+// draw_segment_diagonal_2 - draw a diagonal
+// LED segment that looks like this:
+//-------------------------------------------------
+
+void layout_element::component::draw_segment_diagonal_2(bitmap_t &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color)
+{
+ // compute parameters
+ width *= 1.5;
+ float ratio = (maxy - miny - width) / (float)(maxx - minx);
+
+ // draw line
+ for (int x = minx; x < maxx; x++)
+ if (x >= 0 && x < dest.width)
+ {
+ UINT32 *d = BITMAP_ADDR32(&dest, 0, x);
+ int step = (x - minx) * ratio;
+
+ for (int y = miny + step; y < miny + step + width; y++)
+ if (y >= 0 && y < dest.height)
+ d[y * dest.rowpixels] = color;
+ }
+}
+
+
+//-------------------------------------------------
+// draw_segment_decimal - draw a decimal point
+//-------------------------------------------------
+
+void layout_element::component::draw_segment_decimal(bitmap_t &dest, int midx, int midy, int width, rgb_t color)
+{
+ // compute parameters
+ width /= 2;
+ float ooradius2 = 1.0f / (float)(width * width);
+
+ // iterate over y
+ for (UINT32 y = 0; y <= width; y++)
+ {
+ UINT32 *d0 = BITMAP_ADDR32(&dest, midy - y, 0);
+ UINT32 *d1 = BITMAP_ADDR32(&dest, midy + y, 0);
+ float xval = width * sqrt(1.0f - (float)(y * y) * ooradius2);
+ INT32 left, right;
+
+ // compute left/right coordinates
+ left = midx - (INT32)(xval + 0.5f);
+ right = midx + (INT32)(xval + 0.5f);
+
+ // draw this scanline
+ for (UINT32 x = left; x < right; x++)
+ d0[x] = d1[x] = color;
+ }
+}
+
+
+//-------------------------------------------------
+// draw_segment_comma - draw a comma tail
+//-------------------------------------------------
+
+void layout_element::component::draw_segment_comma(bitmap_t &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color)
+{
+ // compute parameters
+ width *= 1.5;
+ float ratio = (maxy - miny - width) / (float)(maxx - minx);
+
+ // draw line
+ for (int x = minx; x < maxx; x++)
+ {
+ UINT32 *d = BITMAP_ADDR32(&dest, 0, x);
+ int step = (x - minx) * ratio;
+
+ for (int y = maxy; y < maxy - width - step; y--)
+ d[y * dest.rowpixels] = color;
+ }
+}
+
+
+//-------------------------------------------------
+// apply_skew - apply skew to a bitmap_t
+//-------------------------------------------------
+
+void layout_element::component::apply_skew(bitmap_t &dest, int skewwidth)
+{
+ for (int y = 0; y < dest.height; y++)
+ {
+ UINT32 *destrow = BITMAP_ADDR32(&dest, y, 0);
+ int offs = skewwidth * (dest.height - y) / dest.height;
+ for (int x = dest.width - skewwidth - 1; x >= 0; x--)
+ destrow[x + offs] = destrow[x];
+ for (int x = 0; x < offs; x++)
+ destrow[x] = 0;
+ }
+}
+
+
+
+//**************************************************************************
+// LAYOUT VIEW
+//**************************************************************************
+
+//-------------------------------------------------
+// layout_view - constructor
+//-------------------------------------------------
+
+layout_view::layout_view(running_machine &machine, xml_data_node &viewnode, simple_list<layout_element> &elemlist)
+ : m_next(NULL),
+ m_aspect(1.0f),
+ m_scraspect(1.0f),
+ m_screens(machine.respool()),
+ m_backdrop_list(machine.respool()),
+ m_screen_list(machine.respool()),
+ m_overlay_list(machine.respool()),
+ m_bezel_list(machine.respool()),
+ m_cpanel_list(machine.respool()),
+ m_marquee_list(machine.respool())
+{
+ // allocate a copy of the name
+ m_name = xml_get_attribute_string_with_subst(machine, viewnode, "name", "");
+
+ // if we have a bounds item, load it
+ xml_data_node *boundsnode = xml_get_sibling(viewnode.child, "bounds");
+ m_expbounds.x0 = m_expbounds.y0 = m_expbounds.x1 = m_expbounds.y1 = 0;
+ if (boundsnode != NULL)
+ parse_bounds(machine, xml_get_sibling(boundsnode, "bounds"), m_expbounds);
+
+ // load backdrop items
+ for (xml_data_node *itemnode = xml_get_sibling(viewnode.child, "backdrop"); itemnode != NULL; itemnode = xml_get_sibling(itemnode->next, "backdrop"))
+ m_backdrop_list.append(*auto_alloc(machine, item(machine, *itemnode, elemlist)));
+
+ // load screen items
+ for (xml_data_node *itemnode = xml_get_sibling(viewnode.child, "screen"); itemnode != NULL; itemnode = xml_get_sibling(itemnode->next, "screen"))
+ m_screen_list.append(*auto_alloc(machine, item(machine, *itemnode, elemlist)));
+
+ // load overlay items
+ for (xml_data_node *itemnode = xml_get_sibling(viewnode.child, "overlay"); itemnode != NULL; itemnode = xml_get_sibling(itemnode->next, "overlay"))
+ m_overlay_list.append(*auto_alloc(machine, item(machine, *itemnode, elemlist)));
+
+ // load bezel items
+ for (xml_data_node *itemnode = xml_get_sibling(viewnode.child, "bezel"); itemnode != NULL; itemnode = xml_get_sibling(itemnode->next, "bezel"))
+ m_bezel_list.append(*auto_alloc(machine, item(machine, *itemnode, elemlist)));
+
+ // load cpanel items
+ for (xml_data_node *itemnode = xml_get_sibling(viewnode.child, "cpanel"); itemnode != NULL; itemnode = xml_get_sibling(itemnode->next, "cpanel"))
+ m_cpanel_list.append(*auto_alloc(machine, item(machine, *itemnode, elemlist)));
+
+ // load marquee items
+ for (xml_data_node *itemnode = xml_get_sibling(viewnode.child, "marquee"); itemnode != NULL; itemnode = xml_get_sibling(itemnode->next, "marquee"))
+ m_marquee_list.append(*auto_alloc(machine, item(machine, *itemnode, elemlist)));
+
+ // recompute the data for the view based on a default layer config
+ recompute(render_layer_config());
+}
+
+
+//-------------------------------------------------
+// layout_view - destructor
+//-------------------------------------------------
+
+layout_view::~layout_view()
+{
+}
+
+
+//-------------------------------------------------
+// first_item - return the first item in the
+// appropriate list
+//-------------------------------------------------
+
+layout_view::item *layout_view::first_item(item_layer layer) const
+{
+ switch (layer)
+ {
+ case ITEM_LAYER_BACKDROP: return m_backdrop_list.first();
+ case ITEM_LAYER_SCREEN: return m_screen_list.first();
+ case ITEM_LAYER_OVERLAY: return m_overlay_list.first();
+ case ITEM_LAYER_BEZEL: return m_bezel_list.first();
+ case ITEM_LAYER_CPANEL: return m_cpanel_list.first();
+ case ITEM_LAYER_MARQUEE: return m_marquee_list.first();
+ default: return NULL;
+ }
+}
+
+
+//-------------------------------------------------
+// recompute - recompute the bounds and aspect
+// ratio of a view and all of its contained items
+//-------------------------------------------------
+
+void layout_view::recompute(render_layer_config layerconfig)
+{
+ // reset the bounds
+ m_bounds.x0 = m_bounds.y0 = m_bounds.x1 = m_bounds.y1 = 0.0f;
+ m_scrbounds.x0 = m_scrbounds.y0 = m_scrbounds.x1 = m_scrbounds.y1 = 0.0f;
+ m_screens.reset();
+
+ // loop over all layers
+ bool first = true;
+ bool scrfirst = true;
+ for (item_layer layer = ITEM_LAYER_FIRST; layer < ITEM_LAYER_MAX; layer++)
+ {
+ // determine if this layer should be visible
+ switch (layer)
+ {
+ case ITEM_LAYER_BACKDROP: m_layenabled[layer] = layerconfig.backdrops_enabled(); break;
+ case ITEM_LAYER_OVERLAY: m_layenabled[layer] = layerconfig.overlays_enabled(); break;
+ case ITEM_LAYER_BEZEL: m_layenabled[layer] = layerconfig.bezels_enabled(); break;
+ case ITEM_LAYER_CPANEL: m_layenabled[layer] = layerconfig.cpanels_enabled(); break;
+ case ITEM_LAYER_MARQUEE: m_layenabled[layer] = layerconfig.marquees_enabled(); break;
+ default: m_layenabled[layer] = true; break;
+ }
+
+ // only do it if requested
+ if (m_layenabled[layer])
+ for (item *curitem = first_item(layer); curitem != NULL; curitem = curitem->next())
+ {
+ // accumulate bounds
+ if (first)
+ m_bounds = curitem->m_rawbounds;
+ else
+ union_render_bounds(&m_bounds, &curitem->m_rawbounds);
+ first = false;
+
+ // accumulate screen bounds
+ if (curitem->m_screen != NULL)
+ {
+ if (scrfirst)
+ m_scrbounds = curitem->m_rawbounds;
+ else
+ union_render_bounds(&m_scrbounds, &curitem->m_rawbounds);
+ scrfirst = false;
+
+ // accumulate the screens in use while we're scanning
+ m_screens.add(*curitem->m_screen);
+ }
+ }
+ }
+
+ // if we have an explicit bounds, override it
+ if (m_expbounds.x1 > m_expbounds.x0)
+ m_bounds = m_expbounds;
+
+ // compute the aspect ratio of the view
+ m_aspect = (m_bounds.x1 - m_bounds.x0) / (m_bounds.y1 - m_bounds.y0);
+ m_scraspect = (m_scrbounds.x1 - m_scrbounds.x0) / (m_scrbounds.y1 - m_scrbounds.y0);
+
+ // if we're handling things normally, the target bounds are (0,0)-(1,1)
+ render_bounds target_bounds;
+ if (!layerconfig.zoom_to_screen() || m_screens.count() == 0)
+ {
+ target_bounds.x0 = target_bounds.y0 = 0.0f;
+ target_bounds.x1 = target_bounds.y1 = 1.0f;
+ }
+
+ // if we're cropping, we want the screen area to fill (0,0)-(1,1)
+ else
+ {
+ float targwidth = (m_bounds.x1 - m_bounds.x0) / (m_scrbounds.x1 - m_scrbounds.x0);
+ float targheight = (m_bounds.y1 - m_bounds.y0) / (m_scrbounds.y1 - m_scrbounds.y0);
+ target_bounds.x0 = (m_bounds.x0 - m_scrbounds.x0) / (m_bounds.x1 - m_bounds.x0) * targwidth;
+ target_bounds.y0 = (m_bounds.y0 - m_scrbounds.y0) / (m_bounds.y1 - m_bounds.y0) * targheight;
+ target_bounds.x1 = target_bounds.x0 + targwidth;
+ target_bounds.y1 = target_bounds.y0 + targheight;
+ }
+
+ // determine the scale/offset for normalization
+ float xoffs = m_bounds.x0;
+ float yoffs = m_bounds.y0;
+ float xscale = (target_bounds.x1 - target_bounds.x0) / (m_bounds.x1 - m_bounds.x0);
+ float yscale = (target_bounds.y1 - target_bounds.y0) / (m_bounds.y1 - m_bounds.y0);
+
+ // normalize all the item bounds
+ for (item_layer layer = ITEM_LAYER_FIRST; layer < ITEM_LAYER_MAX; layer++)
+ for (item *curitem = first_item(layer); curitem != NULL; curitem = curitem->next())
+ {
+ curitem->m_bounds.x0 = target_bounds.x0 + (curitem->m_rawbounds.x0 - xoffs) * xscale;
+ curitem->m_bounds.x1 = target_bounds.x0 + (curitem->m_rawbounds.x1 - xoffs) * xscale;
+ curitem->m_bounds.y0 = target_bounds.y0 + (curitem->m_rawbounds.y0 - yoffs) * yscale;
+ curitem->m_bounds.y1 = target_bounds.y0 + (curitem->m_rawbounds.y1 - yoffs) * yscale;
+ }
+}
+
+
+
+//**************************************************************************
+// LAYOUT VIEW ITEM
+//**************************************************************************
+
+//-------------------------------------------------
+// item - constructor
+//-------------------------------------------------
+
+layout_view::item::item(running_machine &machine, xml_data_node &itemnode, simple_list<layout_element> &elemlist)
+ : m_next(NULL),
+ m_element(NULL),
+ m_input_mask(0),
+ m_screen(NULL),
+ m_orientation(ROT0)
+{
+ // allocate a copy of the output name
+ m_output_name = xml_get_attribute_string_with_subst(machine, itemnode, "name", "");
+
+ // allocate a copy of the input tag
+ m_input_tag = xml_get_attribute_string_with_subst(machine, itemnode, "inputtag", "");
+
+ // find the associated element
+ const char *name = xml_get_attribute_string_with_subst(machine, itemnode, "element", NULL);
+ if (name != NULL)
+ {
+ // search the list of elements for a match
+ for (m_element = elemlist.first(); m_element != NULL; m_element = m_element->next())
+ if (strcmp(name, m_element->name()) == 0)
+ break;
+
+ // error if not found
+ if (m_element == NULL)
+ throw emu_fatalerror("Unable to find layout element %s", name);
+ }
+
+ // fetch common data
+ int index = xml_get_attribute_int_with_subst(machine, itemnode, "index", -1);
+ if (index != -1)
+ m_screen = downcast<screen_device *>(machine.devicelist().find(SCREEN, index));
+ m_input_mask = xml_get_attribute_int_with_subst(machine, itemnode, "inputmask", 0);
+ if (m_output_name[0] != 0 && m_element != NULL)
+ output_set_value(m_output_name, m_element->default_state());
+ parse_bounds(machine, xml_get_sibling(itemnode.child, "bounds"), m_rawbounds);
+ parse_color(machine, xml_get_sibling(itemnode.child, "color"), m_color);
+ parse_orientation(machine, xml_get_sibling(itemnode.child, "orientation"), m_orientation);
+
+ // sanity checks
+ if (strcmp(itemnode.name, "screen") == 0)
+ {
+ if (m_screen == NULL)
+ throw emu_fatalerror("Layout references invalid screen index %d", index);
+ }
+ else
+ {
+ if (m_element == NULL)
+ throw emu_fatalerror("Layout item of type %s require an element tag", itemnode.name);
+ }
+}
+
+
+//-------------------------------------------------
+// item - destructor
+//-------------------------------------------------
+
+layout_view::item::~item()
+{
+}
+
+
+//-------------------------------------------------
+// state - fetch state based on configured source
+//-------------------------------------------------
+
+int layout_view::item::state() const
+{
+ int state = 0;
+
+ assert(m_element != NULL);
+
+ // if configured to an output, fetch the output value
+ if (m_output_name[0] != 0)
+ state = output_get_value(m_output_name);
+
+ // if configured to an input, fetch the input value
+ else if (m_input_tag[0] != 0)
+ {
+ const input_field_config *field = input_field_by_tag_and_mask(m_element->machine().m_portlist, m_input_tag, m_input_mask);
+ if (field != NULL)
+ state = ((input_port_read_safe(m_element->machine(), m_input_tag, 0) ^ field->defvalue) & m_input_mask) ? 1 : 0;
+ }
+ return state;
+}
+
+
+
+//**************************************************************************
+// LAYOUT FILE
+//**************************************************************************
+
+//-------------------------------------------------
+// layout_file - constructor
+//-------------------------------------------------
+
+layout_file::layout_file(running_machine &machine, xml_data_node &rootnode, const char *dirname)
+ : m_next(NULL),
+ m_elemlist(machine.respool()),
+ m_viewlist(machine.respool())
+{
+ // find the layout node
+ xml_data_node *mamelayoutnode = xml_get_sibling(rootnode.child, "mamelayout");
+ if (mamelayoutnode == NULL)
+ throw emu_fatalerror("Invalid XML file: missing mamelayout node");
+
+ // validate the config data version
+ int version = xml_get_attribute_int(mamelayoutnode, "version", 0);
+ if (version != LAYOUT_VERSION)
+ throw emu_fatalerror("Invalid XML file: unsupported version");
+
+ // parse all the elements
+ for (xml_data_node *elemnode = xml_get_sibling(mamelayoutnode->child, "element"); elemnode != NULL; elemnode = xml_get_sibling(elemnode->next, "element"))
+ m_elemlist.append(*auto_alloc(machine, layout_element(machine, *elemnode, dirname)));
+
+ // parse all the views
+ for (xml_data_node *viewnode = xml_get_sibling(mamelayoutnode->child, "view"); viewnode != NULL; viewnode = xml_get_sibling(viewnode->next, "view"))
+ m_viewlist.append(*auto_alloc(machine, layout_view(machine, *viewnode, m_elemlist)));
+}
+
+
+//-------------------------------------------------
+// ~layout_file - destructor
+//-------------------------------------------------
+
+layout_file::~layout_file()
+{
+}
diff --git a/trunk/src/emu/rendlay.h b/trunk/src/emu/rendlay.h
new file mode 100644
index 00000000000..a52ca46205f
--- /dev/null
+++ b/trunk/src/emu/rendlay.h
@@ -0,0 +1,336 @@
+/***************************************************************************
+
+ rendlay.h
+
+ Core rendering layout parser and manager.
+
+****************************************************************************
+
+ 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.
+
+***************************************************************************/
+
+#ifndef __RENDLAY_H__
+#define __RENDLAY_H__
+
+#include "render.h"
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+enum item_layer
+{
+ ITEM_LAYER_FIRST = 0,
+ ITEM_LAYER_BACKDROP = ITEM_LAYER_FIRST,
+ ITEM_LAYER_SCREEN,
+ ITEM_LAYER_OVERLAY,
+ ITEM_LAYER_BEZEL,
+ ITEM_LAYER_CPANEL,
+ ITEM_LAYER_MARQUEE,
+ ITEM_LAYER_MAX
+};
+DECLARE_ENUM_OPERATORS(item_layer);
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> layout_element
+
+// a layout_element is a single named element, which may have multiple components
+class layout_element
+{
+ friend class simple_list<layout_element>;
+
+public:
+ // construction/destruction
+ layout_element(running_machine &machine, xml_data_node &elemnode, const char *dirname);
+ virtual ~layout_element();
+
+ // getters
+ layout_element *next() const { return m_next; }
+ const char *name() const { return m_name; }
+ running_machine &machine() const { return m_machine; }
+ int default_state() const { return m_defstate; }
+ int maxstate() const { return m_maxstate; }
+ render_texture *state_texture(int state);
+
+private:
+ // a component represents an image, rectangle, or disk in an element
+ class component
+ {
+ friend class layout_element;
+ friend class simple_list<component>;
+
+ public:
+ // construction/destruction
+ component(running_machine &machine, xml_data_node &compnode, const char *dirname);
+ ~component();
+
+ // getters
+ component *next() const { return m_next; }
+ const render_bounds &bounds() const { return m_bounds; }
+
+ // operations
+ void draw(running_machine &machine, bitmap_t &dest, const rectangle &bounds, int state);
+
+ private:
+ // component types
+ enum component_type
+ {
+ CTYPE_INVALID = 0,
+ CTYPE_IMAGE,
+ CTYPE_RECT,
+ CTYPE_DISK,
+ CTYPE_TEXT,
+ CTYPE_LED7SEG,
+ CTYPE_LED14SEG,
+ CTYPE_LED16SEG,
+ CTYPE_LED14SEGSC,
+ CTYPE_LED16SEGSC,
+ CTYPE_DOTMATRIX,
+ CTYPE_MAX
+ };
+
+ // helpers
+ void draw_rect(bitmap_t &dest, const rectangle &bounds);
+ void draw_disk(bitmap_t &dest, const rectangle &bounds);
+ void draw_text(running_machine &machine, bitmap_t &dest, const rectangle &bounds);
+ bitmap_t *load_bitmap();
+ void draw_led7seg(bitmap_t &dest, const rectangle &bounds, int pattern);
+ void draw_led14seg(bitmap_t &dest, const rectangle &bounds, int pattern);
+ void draw_led14segsc(bitmap_t &dest, const rectangle &bounds, int pattern);
+ void draw_led16seg(bitmap_t &dest, const rectangle &bounds, int pattern);
+ void draw_led16segsc(bitmap_t &dest, const rectangle &bounds, int pattern);
+ void draw_dotmatrix(bitmap_t &dest, const rectangle &bounds, int pattern);
+ void draw_segment_horizontal_caps(bitmap_t &dest, int minx, int maxx, int midy, int width, int caps, rgb_t color);
+ void draw_segment_horizontal(bitmap_t &dest, int minx, int maxx, int midy, int width, rgb_t color);
+ void draw_segment_vertical_caps(bitmap_t &dest, int miny, int maxy, int midx, int width, int caps, rgb_t color);
+ void draw_segment_vertical(bitmap_t &dest, int miny, int maxy, int midx, int width, rgb_t color);
+ void draw_segment_diagonal_1(bitmap_t &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color);
+ void draw_segment_diagonal_2(bitmap_t &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color);
+ void draw_segment_decimal(bitmap_t &dest, int midx, int midy, int width, rgb_t color);
+ void draw_segment_comma(bitmap_t &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color);
+ void apply_skew(bitmap_t &dest, int skewwidth);
+
+ // internal state
+ component * m_next; // link to next component
+ component_type m_type; // type of component
+ int m_state; // state where this component is visible (-1 means all states)
+ render_bounds m_bounds; // bounds of the element
+ render_color m_color; // color of the element
+ astring m_string; // string for text components
+ bitmap_t * m_bitmap; // source bitmap for images
+ astring m_dirname; // directory name of image file (for lazy loading)
+ emu_file * m_file; // file object for reading image/alpha files
+ astring m_imagefile; // name of the image file (for lazy loading)
+ astring m_alphafile; // name of the alpha file (for lazy loading)
+ bool m_hasalpha; // is there any alpha component present?
+ };
+
+ // a texture encapsulates a texture for a given element in a given state
+ class texture
+ {
+ public:
+ texture();
+ ~texture();
+
+ layout_element * m_element; // pointer back to the element
+ render_texture * m_texture; // texture for this state
+ int m_state; // associated state number
+ };
+
+ // internal helpers
+ static void element_scale(bitmap_t &dest, const bitmap_t &source, const rectangle &sbounds, void *param);
+
+ // internal state
+ layout_element * m_next; // link to next element
+ running_machine & m_machine; // reference to the owning machine
+ astring m_name; // name of this element
+ simple_list<component> m_complist; // list of components
+ int m_defstate; // default state of this element
+ int m_maxstate; // maximum state value for all components
+ texture * m_elemtex; // array of element textures used for managing the scaled bitmaps
+};
+
+
+// ======================> layout_view
+
+// a layout_view encapsulates a named list of items
+class layout_view
+{
+ friend class simple_list<layout_view>;
+
+public:
+ // an item is a single backdrop, screen, overlay, bezel, cpanel, or marquee item
+ class item
+ {
+ friend class layout_view;
+ friend class simple_list<item>;
+
+ public:
+ // construction/destruction
+ item(running_machine &machine, xml_data_node &itemnode, simple_list<layout_element> &elemlist);
+ virtual ~item();
+
+ // getters
+ item *next() const { return m_next; }
+ layout_element *element() const { return m_element; }
+ screen_device *screen() { return m_screen; }
+ const render_bounds &bounds() const { return m_bounds; }
+ const render_color &color() const { return m_color; }
+ int orientation() const { return m_orientation; }
+ render_container *screen_container(running_machine &machine) const { return (m_screen != NULL) ? &m_screen->container() : NULL; }
+ bool has_input() const { return bool(m_input_tag); }
+ const char *input_tag_and_mask(UINT32 &mask) const { mask = m_input_mask; return m_input_tag; }
+
+ // fetch state based on configured source
+ int state() const;
+
+ private:
+ // internal state
+ item * m_next; // link to next item
+ layout_element * m_element; // pointer to the associated element (non-screens only)
+ astring m_output_name; // name of this item
+ astring m_input_tag; // input tag of this item
+ UINT32 m_input_mask; // input mask of this item
+ screen_device * m_screen; // pointer to screen
+ int m_orientation; // orientation of this item
+ render_bounds m_bounds; // bounds of the item
+ render_bounds m_rawbounds; // raw (original) bounds of the item
+ render_color m_color; // color of the item
+ };
+
+ // construction/destruction
+ layout_view(running_machine &machine, xml_data_node &viewnode, simple_list<layout_element> &elemlist);
+ virtual ~layout_view();
+
+ // getters
+ layout_view *next() const { return m_next; }
+ item *first_item(item_layer layer) const;
+ const char *name() const { return m_name; }
+ const render_screen_list &screens() const { return m_screens; }
+ bool layer_enabled(item_layer layer) const { return m_layenabled[layer]; }
+
+ //
+ bool has_art() const { return (m_backdrop_list.count() + m_overlay_list.count() + m_bezel_list.count() + m_cpanel_list.count() + m_marquee_list.count() != 0); }
+ float effective_aspect(render_layer_config config) const { return (config.zoom_to_screen() && m_screens.count() != 0) ? m_scraspect : m_aspect; }
+
+ // operations
+ void recompute(render_layer_config layerconfig);
+
+private:
+ // internal state
+ layout_view * m_next; // pointer to next layout in the list
+ astring m_name; // name of the layout
+ float m_aspect; // X/Y of the layout
+ float m_scraspect; // X/Y of the screen areas
+ render_screen_list m_screens; // list of active screens
+ render_bounds m_bounds; // computed bounds of the view
+ render_bounds m_scrbounds; // computed bounds of the screens within the view
+ render_bounds m_expbounds; // explicit bounds of the view
+ bool m_layenabled[ITEM_LAYER_MAX]; // is this layer enabled?
+ simple_list<item> m_backdrop_list; // list of backdrop items
+ simple_list<item> m_screen_list; // list of screen items
+ simple_list<item> m_overlay_list; // list of overlay items
+ simple_list<item> m_bezel_list; // list of bezel items
+ simple_list<item> m_cpanel_list; // list of marquee items
+ simple_list<item> m_marquee_list; // list of marquee items
+};
+
+
+// ======================> layout_file
+
+// a layout_file consists of a list of elements and a list of views
+class layout_file
+{
+ friend class simple_list<layout_file>;
+
+public:
+ // construction/destruction
+ layout_file(running_machine &machine, xml_data_node &rootnode, const char *dirname);
+ virtual ~layout_file();
+
+ // getters
+ layout_file *next() const { return m_next; }
+ layout_element *first_element() const { return m_elemlist.first(); }
+ layout_view *first_view() const { return m_viewlist.first(); }
+
+private:
+ // internal state
+ layout_file * m_next; // pointer to the next file in the list
+ simple_list<layout_element> m_elemlist; // list of shared layout elements
+ simple_list<layout_view> m_viewlist; // list of views
+};
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// no screens layouts
+extern const char layout_noscreens[]; // for screenless systems
+
+// single screen layouts
+extern const char layout_horizont[]; // horizontal 4:3 screens
+extern const char layout_vertical[]; // vertical 4:3 screens
+
+// dual screen layouts
+extern const char layout_dualhsxs[]; // dual 4:3 screens side-by-side
+extern const char layout_dualhovu[]; // dual 4:3 screens above and below
+extern const char layout_dualhuov[]; // dual 4:3 screens below and above
+
+// triple screen layouts
+extern const char layout_triphsxs[]; // triple 4:3 screens side-by-side
+
+// quad screen layouts
+extern const char layout_quadhsxs[]; // quad 4:3 screens side-by-side
+
+// generic color overlay layouts
+extern const char layout_ho20ffff[]; // horizontal 4:3 with 20,FF,FF color overlay
+extern const char layout_ho2eff2e[]; // horizontal 4:3 with 2E,FF,2E color overlay
+extern const char layout_ho4f893d[]; // horizontal 4:3 with 4F,89,3D color overlay
+extern const char layout_ho88ffff[]; // horizontal 4:3 with 88,FF,FF color overlay
+extern const char layout_hoa0a0ff[]; // horizontal 4:3 with A0,A0,FF color overlay
+extern const char layout_hoffe457[]; // horizontal 4:3 with FF,E4,57 color overlay
+extern const char layout_hoffff20[]; // horizontal 4:3 with FF,FF,20 color overlay
+extern const char layout_voffff20[]; // vertical 4:3 with FF,FF,20 color overlay
+
+// LCD screen layouts
+extern const char layout_lcd[]; // generic 1:1 lcd screen layout
+extern const char layout_lcd_rot[]; // same, for use with ROT90 or ROT270
+
+#endif // __RENDLAY_H__
diff --git a/trunk/src/emu/rendutil.c b/trunk/src/emu/rendutil.c
new file mode 100644
index 00000000000..bb8b414907d
--- /dev/null
+++ b/trunk/src/emu/rendutil.c
@@ -0,0 +1,770 @@
+/***************************************************************************
+
+ rendutil.c
+
+ Core rendering utilities.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "render.h"
+#include "rendutil.h"
+#include "png.h"
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+/* utilities */
+static void resample_argb_bitmap_average(UINT32 *dest, UINT32 drowpixels, UINT32 dwidth, UINT32 dheight, const UINT32 *source, UINT32 srowpixels, UINT32 swidth, UINT32 sheight, const render_color *color, UINT32 dx, UINT32 dy);
+static void resample_argb_bitmap_bilinear(UINT32 *dest, UINT32 drowpixels, UINT32 dwidth, UINT32 dheight, const UINT32 *source, UINT32 srowpixels, UINT32 swidth, UINT32 sheight, const render_color *color, UINT32 dx, UINT32 dy);
+static void copy_png_to_bitmap(bitmap_t *bitmap, const png_info *png, bool *hasalpha);
+static void copy_png_alpha_to_bitmap(bitmap_t *bitmap, const png_info *png, bool *hasalpha);
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ compute_brightness - compute the effective
+ brightness for an RGB pixel
+-------------------------------------------------*/
+
+INLINE UINT8 compute_brightness(rgb_t rgb)
+{
+ return (RGB_RED(rgb) * 222 + RGB_GREEN(rgb) * 707 + RGB_BLUE(rgb) * 71) / 1000;
+}
+
+
+
+/***************************************************************************
+ RENDER UTILITIES
+***************************************************************************/
+
+/*-------------------------------------------------
+ render_resample_argb_bitmap_hq - perform a high
+ quality resampling of a texture
+-------------------------------------------------*/
+
+void render_resample_argb_bitmap_hq(void *dest, UINT32 drowpixels, UINT32 dwidth, UINT32 dheight, const bitmap_t *source, const rectangle *orig_sbounds, const render_color *color)
+{
+ UINT32 swidth, sheight;
+ const UINT32 *sbase;
+ rectangle sbounds;
+ UINT32 dx, dy;
+
+ if (dwidth == 0 || dheight == 0)
+ return;
+
+ /* compute the real source bounds */
+ if (orig_sbounds != NULL)
+ sbounds = *orig_sbounds;
+ else
+ {
+ sbounds.min_x = sbounds.min_y = 0;
+ sbounds.max_x = source->width;
+ sbounds.max_y = source->height;
+ }
+
+ /* adjust the source base */
+ sbase = (const UINT32 *)source->base + sbounds.min_y * source->rowpixels + sbounds.min_x;
+
+ /* determine the steppings */
+ swidth = sbounds.max_x - sbounds.min_x;
+ sheight = sbounds.max_y - sbounds.min_y;
+ dx = (swidth << 12) / dwidth;
+ dy = (sheight << 12) / dheight;
+
+ /* if the source is higher res than the target, use full averaging */
+ if (dx > 0x1000 || dy > 0x1000)
+ resample_argb_bitmap_average((UINT32 *)dest, drowpixels, dwidth, dheight, sbase, source->rowpixels, swidth, sheight, color, dx, dy);
+ else
+ resample_argb_bitmap_bilinear((UINT32 *)dest, drowpixels, dwidth, dheight, sbase, source->rowpixels, swidth, sheight, color, dx, dy);
+}
+
+
+/*-------------------------------------------------
+ resample_argb_bitmap_average - resample a texture
+ by performing a true weighted average over
+ all contributing pixels
+-------------------------------------------------*/
+
+static void resample_argb_bitmap_average(UINT32 *dest, UINT32 drowpixels, UINT32 dwidth, UINT32 dheight, const UINT32 *source, UINT32 srowpixels, UINT32 swidth, UINT32 sheight, const render_color *color, UINT32 dx, UINT32 dy)
+{
+ UINT64 sumscale = (UINT64)dx * (UINT64)dy;
+ UINT32 r, g, b, a;
+ UINT32 x, y;
+
+ /* precompute premultiplied R/G/B/A factors */
+ r = color->r * color->a * 256.0;
+ g = color->g * color->a * 256.0;
+ b = color->b * color->a * 256.0;
+ a = color->a * 256.0;
+
+ /* loop over the target vertically */
+ for (y = 0; y < dheight; y++)
+ {
+ UINT32 starty = y * dy;
+
+ /* loop over the target horizontally */
+ for (x = 0; x < dwidth; x++)
+ {
+ UINT64 sumr = 0, sumg = 0, sumb = 0, suma = 0;
+ UINT32 startx = x * dx;
+ UINT32 xchunk, ychunk;
+ UINT32 curx, cury;
+
+ UINT32 yremaining = dy;
+
+ /* accumulate all source pixels that contribute to this pixel */
+ for (cury = starty; yremaining; cury += ychunk)
+ {
+ UINT32 xremaining = dx;
+
+ /* determine the Y contribution, clamping to the amount remaining */
+ ychunk = 0x1000 - (cury & 0xfff);
+ if (ychunk > yremaining)
+ ychunk = yremaining;
+ yremaining -= ychunk;
+
+ /* loop over all source pixels in the X direction */
+ for (curx = startx; xremaining; curx += xchunk)
+ {
+ UINT32 factor;
+ UINT32 pix;
+
+ /* determine the X contribution, clamping to the amount remaining */
+ xchunk = 0x1000 - (curx & 0xfff);
+ if (xchunk > xremaining)
+ xchunk = xremaining;
+ xremaining -= xchunk;
+
+ /* total contribution = x * y */
+ factor = xchunk * ychunk;
+
+ /* fetch the source pixel */
+ pix = source[(cury >> 12) * srowpixels + (curx >> 12)];
+
+ /* accumulate the RGBA values */
+ sumr += factor * RGB_RED(pix);
+ sumg += factor * RGB_GREEN(pix);
+ sumb += factor * RGB_BLUE(pix);
+ suma += factor * RGB_ALPHA(pix);
+ }
+ }
+
+ /* apply scaling */
+ suma = (suma / sumscale) * a / 256;
+ sumr = (sumr / sumscale) * r / 256;
+ sumg = (sumg / sumscale) * g / 256;
+ sumb = (sumb / sumscale) * b / 256;
+
+ /* if we're translucent, add in the destination pixel contribution */
+ if (a < 256)
+ {
+ UINT32 dpix = dest[y * drowpixels + x];
+ suma += RGB_ALPHA(dpix) * (256 - a);
+ sumr += RGB_RED(dpix) * (256 - a);
+ sumg += RGB_GREEN(dpix) * (256 - a);
+ sumb += RGB_BLUE(dpix) * (256 - a);
+ }
+
+ /* store the target pixel, dividing the RGBA values by the overall scale factor */
+ dest[y * drowpixels + x] = MAKE_ARGB(suma, sumr, sumg, sumb);
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ resample_argb_bitmap_bilinear - perform texture
+ sampling via a bilinear filter
+-------------------------------------------------*/
+
+static void resample_argb_bitmap_bilinear(UINT32 *dest, UINT32 drowpixels, UINT32 dwidth, UINT32 dheight, const UINT32 *source, UINT32 srowpixels, UINT32 swidth, UINT32 sheight, const render_color *color, UINT32 dx, UINT32 dy)
+{
+ UINT32 maxx = swidth << 12, maxy = sheight << 12;
+ UINT32 r, g, b, a;
+ UINT32 x, y;
+
+ /* precompute premultiplied R/G/B/A factors */
+ r = color->r * color->a * 256.0;
+ g = color->g * color->a * 256.0;
+ b = color->b * color->a * 256.0;
+ a = color->a * 256.0;
+
+ /* loop over the target vertically */
+ for (y = 0; y < dheight; y++)
+ {
+ UINT32 starty = y * dy;
+
+ /* loop over the target horizontally */
+ for (x = 0; x < dwidth; x++)
+ {
+ UINT32 startx = x * dx;
+ UINT32 pix0, pix1, pix2, pix3;
+ UINT32 sumr, sumg, sumb, suma;
+ UINT32 nextx, nexty;
+ UINT32 curx, cury;
+ UINT32 factor;
+
+ /* adjust start to the center; note that this math will tend to produce */
+ /* negative results on the first pixel, which is why we clamp below */
+ curx = startx + dx / 2 - 0x800;
+ cury = starty + dy / 2 - 0x800;
+
+ /* compute the neighboring pixel */
+ nextx = curx + 0x1000;
+ nexty = cury + 0x1000;
+
+ /* fetch the four relevant pixels */
+ pix0 = pix1 = pix2 = pix3 = 0;
+ if ((INT32)cury >= 0 && cury < maxy && (INT32)curx >= 0 && curx < maxx)
+ pix0 = source[(cury >> 12) * srowpixels + (curx >> 12)];
+ if ((INT32)cury >= 0 && cury < maxy && (INT32)nextx >= 0 && nextx < maxx)
+ pix1 = source[(cury >> 12) * srowpixels + (nextx >> 12)];
+ if ((INT32)nexty >= 0 && nexty < maxy && (INT32)curx >= 0 && curx < maxx)
+ pix2 = source[(nexty >> 12) * srowpixels + (curx >> 12)];
+ if ((INT32)nexty >= 0 && nexty < maxy && (INT32)nextx >= 0 && nextx < maxx)
+ pix3 = source[(nexty >> 12) * srowpixels + (nextx >> 12)];
+
+ /* compute the x/y scaling factors */
+ curx &= 0xfff;
+ cury &= 0xfff;
+
+ /* contributions from pixel 0 (top,left) */
+ factor = (0x1000 - curx) * (0x1000 - cury);
+ sumr = factor * RGB_RED(pix0);
+ sumg = factor * RGB_GREEN(pix0);
+ sumb = factor * RGB_BLUE(pix0);
+ suma = factor * RGB_ALPHA(pix0);
+
+ /* contributions from pixel 1 (top,right) */
+ factor = curx * (0x1000 - cury);
+ sumr += factor * RGB_RED(pix1);
+ sumg += factor * RGB_GREEN(pix1);
+ sumb += factor * RGB_BLUE(pix1);
+ suma += factor * RGB_ALPHA(pix1);
+
+ /* contributions from pixel 2 (bottom,left) */
+ factor = (0x1000 - curx) * cury;
+ sumr += factor * RGB_RED(pix2);
+ sumg += factor * RGB_GREEN(pix2);
+ sumb += factor * RGB_BLUE(pix2);
+ suma += factor * RGB_ALPHA(pix2);
+
+ /* contributions from pixel 3 (bottom,right) */
+ factor = curx * cury;
+ sumr += factor * RGB_RED(pix3);
+ sumg += factor * RGB_GREEN(pix3);
+ sumb += factor * RGB_BLUE(pix3);
+ suma += factor * RGB_ALPHA(pix3);
+
+ /* apply scaling */
+ suma = (suma >> 24) * a / 256;
+ sumr = (sumr >> 24) * r / 256;
+ sumg = (sumg >> 24) * g / 256;
+ sumb = (sumb >> 24) * b / 256;
+
+ /* if we're translucent, add in the destination pixel contribution */
+ if (a < 256)
+ {
+ UINT32 dpix = dest[y * drowpixels + x];
+ suma += RGB_ALPHA(dpix) * (256 - a);
+ sumr += RGB_RED(dpix) * (256 - a);
+ sumg += RGB_GREEN(dpix) * (256 - a);
+ sumb += RGB_BLUE(dpix) * (256 - a);
+ }
+
+ /* store the target pixel, dividing the RGBA values by the overall scale factor */
+ dest[y * drowpixels + x] = MAKE_ARGB(suma, sumr, sumg, sumb);
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ render_clip_line - clip a line to a rectangle
+-------------------------------------------------*/
+
+int render_clip_line(render_bounds *bounds, const render_bounds *clip)
+{
+ /* loop until we get a final result */
+ while (1)
+ {
+ UINT8 code0 = 0, code1 = 0;
+ UINT8 thiscode;
+ float x, y;
+
+ /* compute Cohen Sutherland bits for first coordinate */
+ if (bounds->y0 > clip->y1)
+ code0 |= 1;
+ if (bounds->y0 < clip->y0)
+ code0 |= 2;
+ if (bounds->x0 > clip->x1)
+ code0 |= 4;
+ if (bounds->x0 < clip->x0)
+ code0 |= 8;
+
+ /* compute Cohen Sutherland bits for second coordinate */
+ if (bounds->y1 > clip->y1)
+ code1 |= 1;
+ if (bounds->y1 < clip->y0)
+ code1 |= 2;
+ if (bounds->x1 > clip->x1)
+ code1 |= 4;
+ if (bounds->x1 < clip->x0)
+ code1 |= 8;
+
+ /* trivial accept: just return FALSE */
+ if ((code0 | code1) == 0)
+ return FALSE;
+
+ /* trivial reject: just return TRUE */
+ if ((code0 & code1) != 0)
+ return TRUE;
+
+ /* fix one of the OOB cases */
+ thiscode = code0 ? code0 : code1;
+
+ /* off the bottom */
+ if (thiscode & 1)
+ {
+ x = bounds->x0 + (bounds->x1 - bounds->x0) * (clip->y1 - bounds->y0) / (bounds->y1 - bounds->y0);
+ y = clip->y1;
+ }
+
+ /* off the top */
+ else if (thiscode & 2)
+ {
+ x = bounds->x0 + (bounds->x1 - bounds->x0) * (clip->y0 - bounds->y0) / (bounds->y1 - bounds->y0);
+ y = clip->y0;
+ }
+
+ /* off the right */
+ else if (thiscode & 4)
+ {
+ y = bounds->y0 + (bounds->y1 - bounds->y0) * (clip->x1 - bounds->x0) / (bounds->x1 - bounds->x0);
+ x = clip->x1;
+ }
+
+ /* off the left */
+ else
+ {
+ y = bounds->y0 + (bounds->y1 - bounds->y0) * (clip->x0 - bounds->x0) / (bounds->x1 - bounds->x0);
+ x = clip->x0;
+ }
+
+ /* fix the appropriate coordinate */
+ if (thiscode == code0)
+ {
+ bounds->x0 = x;
+ bounds->y0 = y;
+ }
+ else
+ {
+ bounds->x1 = x;
+ bounds->y1 = y;
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ render_clip_quad - clip a quad to a rectangle
+-------------------------------------------------*/
+
+int render_clip_quad(render_bounds *bounds, const render_bounds *clip, render_quad_texuv *texcoords)
+{
+ /* ensure our assumptions about the bounds are correct */
+ assert(bounds->x0 <= bounds->x1);
+ assert(bounds->y0 <= bounds->y1);
+
+ /* trivial reject */
+ if (bounds->y1 < clip->y0)
+ return TRUE;
+ if (bounds->y0 > clip->y1)
+ return TRUE;
+ if (bounds->x1 < clip->x0)
+ return TRUE;
+ if (bounds->x0 > clip->x1)
+ return TRUE;
+
+ /* clip top (x0,y0)-(x1,y1) */
+ if (bounds->y0 < clip->y0)
+ {
+ float frac = (clip->y0 - bounds->y0) / (bounds->y1 - bounds->y0);
+ bounds->y0 = clip->y0;
+ if (texcoords != NULL)
+ {
+ texcoords->tl.u += (texcoords->bl.u - texcoords->tl.u) * frac;
+ texcoords->tl.v += (texcoords->bl.v - texcoords->tl.v) * frac;
+ texcoords->tr.u += (texcoords->br.u - texcoords->tr.u) * frac;
+ texcoords->tr.v += (texcoords->br.v - texcoords->tr.v) * frac;
+ }
+ }
+
+ /* clip bottom (x3,y3)-(x2,y2) */
+ if (bounds->y1 > clip->y1)
+ {
+ float frac = (bounds->y1 - clip->y1) / (bounds->y1 - bounds->y0);
+ bounds->y1 = clip->y1;
+ if (texcoords != NULL)
+ {
+ texcoords->bl.u -= (texcoords->bl.u - texcoords->tl.u) * frac;
+ texcoords->bl.v -= (texcoords->bl.v - texcoords->tl.v) * frac;
+ texcoords->br.u -= (texcoords->br.u - texcoords->tr.u) * frac;
+ texcoords->br.v -= (texcoords->br.v - texcoords->tr.v) * frac;
+ }
+ }
+
+ /* clip left (x0,y0)-(x3,y3) */
+ if (bounds->x0 < clip->x0)
+ {
+ float frac = (clip->x0 - bounds->x0) / (bounds->x1 - bounds->x0);
+ bounds->x0 = clip->x0;
+ if (texcoords != NULL)
+ {
+ texcoords->tl.u += (texcoords->tr.u - texcoords->tl.u) * frac;
+ texcoords->tl.v += (texcoords->tr.v - texcoords->tl.v) * frac;
+ texcoords->bl.u += (texcoords->br.u - texcoords->bl.u) * frac;
+ texcoords->bl.v += (texcoords->br.v - texcoords->bl.v) * frac;
+ }
+ }
+
+ /* clip right (x1,y1)-(x2,y2) */
+ if (bounds->x1 > clip->x1)
+ {
+ float frac = (bounds->x1 - clip->x1) / (bounds->x1 - bounds->x0);
+ bounds->x1 = clip->x1;
+ if (texcoords != NULL)
+ {
+ texcoords->tr.u -= (texcoords->tr.u - texcoords->tl.u) * frac;
+ texcoords->tr.v -= (texcoords->tr.v - texcoords->tl.v) * frac;
+ texcoords->br.u -= (texcoords->br.u - texcoords->bl.u) * frac;
+ texcoords->br.v -= (texcoords->br.v - texcoords->bl.v) * frac;
+ }
+ }
+ return FALSE;
+}
+
+
+/*-------------------------------------------------
+ render_line_to_quad - convert a line and a
+ width to four points
+-------------------------------------------------*/
+
+void render_line_to_quad(const render_bounds *bounds, float width, render_bounds *bounds0, render_bounds *bounds1)
+{
+ render_bounds modbounds = *bounds;
+ float unitx, unity;
+
+ /*
+ High-level logic -- due to math optimizations, this info is lost below.
+
+ Imagine a thick line of width (w), drawn from (p0) to (p1), with a unit
+ vector (u) indicating the direction from (p0) to (p1).
+
+ B C
+ +---------------- ... ------------------+
+ | ^ |
+ | | |
+ | | |
+ * (p0) ------------> (w)| * (p1)
+ | (u) | |
+ | | |
+ | v |
+ +---------------- ... ------------------+
+ A D
+
+ To convert this into a quad, we need to compute the four points A, B, C
+ and D.
+
+ Starting with point A. We first multiply the unit vector by 0.5w and then
+ rotate the result 90 degrees. Thus, we have:
+
+ A.x = p0.x + 0.5 * w * u.x * cos(90) - 0.5 * w * u.y * sin(90)
+ A.y = p0.y + 0.5 * w * u.x * sin(90) + 0.5 * w * u.y * cos(90)
+
+ Conveniently, sin(90) = 1, and cos(90) = 0, so this simplifies to:
+
+ A.x = p0.x - 0.5 * w * u.y
+ A.y = p0.y + 0.5 * w * u.x
+
+ Working clockwise around the polygon, the same fallout happens all around as
+ we rotate the unit vector by -90 (B), -90 (C), and 90 (D) degrees:
+
+ B.x = p0.x + 0.5 * w * u.y
+ B.y = p0.y - 0.5 * w * u.x
+
+ C.x = p1.x - 0.5 * w * u.y
+ C.y = p1.y + 0.5 * w * u.x
+
+ D.x = p1.x + 0.5 * w * u.y
+ D.y = p1.y - 0.5 * w * u.x
+ */
+
+ /* we only care about the half-width */
+ width *= 0.5f;
+
+ /* compute a vector from point 0 to point 1 */
+ unitx = modbounds.x1 - modbounds.x0;
+ unity = modbounds.y1 - modbounds.y0;
+
+ /* points just use a +1/+1 unit vector; this gives a nice diamond pattern */
+ if (unitx == 0 && unity == 0)
+ {
+ unitx = unity = 0.70710678f * width;
+ modbounds.x0 -= 0.5f * unitx;
+ modbounds.y0 -= 0.5f * unity;
+ modbounds.x1 += 0.5f * unitx;
+ modbounds.y1 += 0.5f * unity;
+ }
+
+ /* lines need to be divided by their length */
+ else
+ {
+ /* prescale unitx and unity by the half-width */
+ float invlength = width / sqrt(unitx * unitx + unity * unity);
+ unitx *= invlength;
+ unity *= invlength;
+ }
+
+ /* rotate the unit vector by 90 degrees and add to point 0 */
+ bounds0->x0 = modbounds.x0 - unity;
+ bounds0->y0 = modbounds.y0 + unitx;
+
+ /* rotate the unit vector by -90 degrees and add to point 0 */
+ bounds0->x1 = modbounds.x0 + unity;
+ bounds0->y1 = modbounds.y0 - unitx;
+
+ /* rotate the unit vector by 90 degrees and add to point 1 */
+ bounds1->x0 = modbounds.x1 - unity;
+ bounds1->y0 = modbounds.y1 + unitx;
+
+ /* rotate the unit vector by -09 degrees and add to point 1 */
+ bounds1->x1 = modbounds.x1 + unity;
+ bounds1->y1 = modbounds.y1 - unitx;
+}
+
+
+/*-------------------------------------------------
+ render_load_png - load a PNG file into a
+ bitmap_t
+-------------------------------------------------*/
+
+bitmap_t *render_load_png(emu_file &file, const char *dirname, const char *filename, bitmap_t *alphadest, bool *hasalpha)
+{
+ bitmap_t *bitmap = NULL;
+ png_info png;
+ png_error result;
+
+ /* open the file */
+ astring fname;
+ if (dirname == NULL)
+ fname.cpy(filename);
+ else
+ fname.cpy(dirname).cat(PATH_SEPARATOR).cat(filename);
+ file_error filerr = file.open(fname);
+ if (filerr != FILERR_NONE)
+ return NULL;
+
+ /* read the PNG data */
+ result = png_read_file(file, &png);
+ file.close();
+ if (result != PNGERR_NONE)
+ return NULL;
+
+ /* verify we can handle this PNG */
+ if (png.bit_depth > 8)
+ {
+ logerror("%s: Unsupported bit depth %d (8 bit max)\n", filename, png.bit_depth);
+ png_free(&png);
+ return NULL;
+ }
+ if (png.interlace_method != 0)
+ {
+ logerror("%s: Interlace unsupported\n", filename);
+ png_free(&png);
+ return NULL;
+ }
+ if (png.color_type != 0 && png.color_type != 3 && png.color_type != 2 && png.color_type != 6)
+ {
+ logerror("%s: Unsupported color type %d\n", filename, png.color_type);
+ png_free(&png);
+ return NULL;
+ }
+
+ /* if less than 8 bits, upsample */
+ png_expand_buffer_8bit(&png);
+
+ /* non-alpha case */
+ if (alphadest == NULL)
+ {
+ bitmap = global_alloc(bitmap_t(png.width, png.height, BITMAP_FORMAT_ARGB32));
+ if (bitmap != NULL)
+ copy_png_to_bitmap(bitmap, &png, hasalpha);
+ }
+
+ /* alpha case */
+ else
+ {
+ if (png.width == alphadest->width && png.height == alphadest->height)
+ {
+ bitmap = alphadest;
+ copy_png_alpha_to_bitmap(bitmap, &png, hasalpha);
+ }
+ }
+
+ /* free PNG data */
+ png_free(&png);
+ return bitmap;
+}
+
+
+/*-------------------------------------------------
+ copy_png_to_bitmap - copy the PNG data to a
+ bitmap
+-------------------------------------------------*/
+
+static void copy_png_to_bitmap(bitmap_t *bitmap, const png_info *png, bool *hasalpha)
+{
+ UINT8 accumalpha = 0xff;
+ UINT8 *src;
+ int x, y;
+
+ /* handle 8bpp palettized case */
+ if (png->color_type == 3)
+ {
+ /* loop over width/height */
+ src = png->image;
+ for (y = 0; y < png->height; y++)
+ for (x = 0; x < png->width; x++, src++)
+ {
+ /* determine alpha and expand to 32bpp */
+ UINT8 alpha = (*src < png->num_trans) ? png->trans[*src] : 0xff;
+ accumalpha &= alpha;
+ *BITMAP_ADDR32(bitmap, y, x) = MAKE_ARGB(alpha, png->palette[*src * 3], png->palette[*src * 3 + 1], png->palette[*src * 3 + 2]);
+ }
+ }
+
+ /* handle 8bpp grayscale case */
+ else if (png->color_type == 0)
+ {
+ /* loop over width/height */
+ src = png->image;
+ for (y = 0; y < png->height; y++)
+ for (x = 0; x < png->width; x++, src++)
+ *BITMAP_ADDR32(bitmap, y, x) = MAKE_ARGB(0xff, *src, *src, *src);
+ }
+
+ /* handle 32bpp non-alpha case */
+ else if (png->color_type == 2)
+ {
+ /* loop over width/height */
+ src = png->image;
+ for (y = 0; y < png->height; y++)
+ for (x = 0; x < png->width; x++, src += 3)
+ *BITMAP_ADDR32(bitmap, y, x) = MAKE_ARGB(0xff, src[0], src[1], src[2]);
+ }
+
+ /* handle 32bpp alpha case */
+ else
+ {
+ /* loop over width/height */
+ src = png->image;
+ for (y = 0; y < png->height; y++)
+ for (x = 0; x < png->width; x++, src += 4)
+ {
+ accumalpha &= src[3];
+ *BITMAP_ADDR32(bitmap, y, x) = MAKE_ARGB(src[3], src[0], src[1], src[2]);
+ }
+ }
+
+ /* set the hasalpha flag */
+ if (hasalpha != NULL)
+ *hasalpha = (accumalpha != 0xff);
+}
+
+
+/*-------------------------------------------------
+ copy_png_alpha_to_bitmap - copy the PNG data
+ to the alpha channel of a bitmap
+-------------------------------------------------*/
+
+static void copy_png_alpha_to_bitmap(bitmap_t *bitmap, const png_info *png, bool *hasalpha)
+{
+ UINT8 accumalpha = 0xff;
+ UINT8 *src;
+ int x, y;
+
+ /* handle 8bpp palettized case */
+ if (png->color_type == 3)
+ {
+ /* loop over width/height */
+ src = png->image;
+ for (y = 0; y < png->height; y++)
+ for (x = 0; x < png->width; x++, src++)
+ {
+ rgb_t pixel = *BITMAP_ADDR32(bitmap, y, x);
+ UINT8 alpha = compute_brightness(MAKE_RGB(png->palette[*src * 3], png->palette[*src * 3 + 1], png->palette[*src * 3 + 2]));
+ accumalpha &= alpha;
+ *BITMAP_ADDR32(bitmap, y, x) = MAKE_ARGB(alpha, RGB_RED(pixel), RGB_GREEN(pixel), RGB_BLUE(pixel));
+ }
+ }
+
+ /* handle 8bpp grayscale case */
+ else if (png->color_type == 0)
+ {
+ /* loop over width/height */
+ src = png->image;
+ for (y = 0; y < png->height; y++)
+ for (x = 0; x < png->width; x++, src++)
+ {
+ rgb_t pixel = *BITMAP_ADDR32(bitmap, y, x);
+ accumalpha &= *src;
+ *BITMAP_ADDR32(bitmap, y, x) = MAKE_ARGB(*src, RGB_RED(pixel), RGB_GREEN(pixel), RGB_BLUE(pixel));
+ }
+ }
+
+ /* handle 32bpp non-alpha case */
+ else if (png->color_type == 2)
+ {
+ /* loop over width/height */
+ src = png->image;
+ for (y = 0; y < png->height; y++)
+ for (x = 0; x < png->width; x++, src += 3)
+ {
+ rgb_t pixel = *BITMAP_ADDR32(bitmap, y, x);
+ UINT8 alpha = compute_brightness(MAKE_RGB(src[0], src[1], src[2]));
+ accumalpha &= alpha;
+ *BITMAP_ADDR32(bitmap, y, x) = MAKE_ARGB(alpha, RGB_RED(pixel), RGB_GREEN(pixel), RGB_BLUE(pixel));
+ }
+ }
+
+ /* handle 32bpp alpha case */
+ else
+ {
+ /* loop over width/height */
+ src = png->image;
+ for (y = 0; y < png->height; y++)
+ for (x = 0; x < png->width; x++, src += 4)
+ {
+ rgb_t pixel = *BITMAP_ADDR32(bitmap, y, x);
+ UINT8 alpha = compute_brightness(MAKE_RGB(src[0], src[1], src[2]));
+ accumalpha &= alpha;
+ *BITMAP_ADDR32(bitmap, y, x) = MAKE_ARGB(alpha, RGB_RED(pixel), RGB_GREEN(pixel), RGB_BLUE(pixel));
+ }
+ }
+
+ /* set the hasalpha flag */
+ if (hasalpha != NULL)
+ *hasalpha = (accumalpha != 0xff);
+}
diff --git a/trunk/src/emu/rendutil.h b/trunk/src/emu/rendutil.h
new file mode 100644
index 00000000000..8e7b012f126
--- /dev/null
+++ b/trunk/src/emu/rendutil.h
@@ -0,0 +1,203 @@
+/***************************************************************************
+
+ rendutil.h
+
+ Core rendering utilities.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#ifndef __RENDUTIL_H__
+#define __RENDUTIL_H__
+
+#include "osdepend.h"
+#include "render.h"
+
+#include <math.h>
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+/* ----- render utilities ----- */
+
+void render_resample_argb_bitmap_hq(void *dest, UINT32 drowpixels, UINT32 dwidth, UINT32 dheight, const bitmap_t *source, const rectangle *sbounds, const render_color *color);
+int render_clip_line(render_bounds *bounds, const render_bounds *clip);
+int render_clip_quad(render_bounds *bounds, const render_bounds *clip, render_quad_texuv *texcoords);
+void render_line_to_quad(const render_bounds *bounds, float width, render_bounds *bounds0, render_bounds *bounds1);
+bitmap_t *render_load_png(emu_file &file, const char *dirname, const char *filename, bitmap_t *alphadest, bool *hasalpha);
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ render_round_nearest - floating point
+ round-to-nearest
+-------------------------------------------------*/
+
+INLINE float render_round_nearest(float f)
+{
+ return floor(f + 0.5f);
+}
+
+
+/*-------------------------------------------------
+ set_render_bounds_xy - cleaner way to set the
+ bounds
+-------------------------------------------------*/
+
+INLINE void set_render_bounds_xy(render_bounds *bounds, float x0, float y0, float x1, float y1)
+{
+ bounds->x0 = x0;
+ bounds->y0 = y0;
+ bounds->x1 = x1;
+ bounds->y1 = y1;
+}
+
+
+/*-------------------------------------------------
+ set_render_bounds_wh - cleaner way to set the
+ bounds
+-------------------------------------------------*/
+
+INLINE void set_render_bounds_wh(render_bounds *bounds, float x0, float y0, float width, float height)
+{
+ bounds->x0 = x0;
+ bounds->y0 = y0;
+ bounds->x1 = x0 + width;
+ bounds->y1 = y0 + height;
+}
+
+
+/*-------------------------------------------------
+ sect_render_bounds - compute the intersection
+ of two render_bounds
+-------------------------------------------------*/
+
+INLINE void sect_render_bounds(render_bounds *dest, const render_bounds *src)
+{
+ dest->x0 = (dest->x0 > src->x0) ? dest->x0 : src->x0;
+ dest->x1 = (dest->x1 < src->x1) ? dest->x1 : src->x1;
+ dest->y0 = (dest->y0 > src->y0) ? dest->y0 : src->y0;
+ dest->y1 = (dest->y1 < src->y1) ? dest->y1 : src->y1;
+}
+
+
+/*-------------------------------------------------
+ union_render_bounds - compute the union of two
+ render_bounds
+-------------------------------------------------*/
+
+INLINE void union_render_bounds(render_bounds *dest, const render_bounds *src)
+{
+ dest->x0 = (dest->x0 < src->x0) ? dest->x0 : src->x0;
+ dest->x1 = (dest->x1 > src->x1) ? dest->x1 : src->x1;
+ dest->y0 = (dest->y0 < src->y0) ? dest->y0 : src->y0;
+ dest->y1 = (dest->y1 > src->y1) ? dest->y1 : src->y1;
+}
+
+
+/*-------------------------------------------------
+ set_render_color - cleaner way to set a color
+-------------------------------------------------*/
+
+INLINE void set_render_color(render_color *color, float a, float r, float g, float b)
+{
+ color->a = a;
+ color->r = r;
+ color->g = g;
+ color->b = b;
+}
+
+
+/*-------------------------------------------------
+ orientation_swap_flips - swap the X and Y
+ flip flags
+-------------------------------------------------*/
+
+INLINE int orientation_swap_flips(int orientation)
+{
+ return (orientation & ORIENTATION_SWAP_XY) |
+ ((orientation & ORIENTATION_FLIP_X) ? ORIENTATION_FLIP_Y : 0) |
+ ((orientation & ORIENTATION_FLIP_Y) ? ORIENTATION_FLIP_X : 0);
+}
+
+
+/*-------------------------------------------------
+ orientation_reverse - compute the orientation
+ that will undo another orientation
+-------------------------------------------------*/
+
+INLINE int orientation_reverse(int orientation)
+{
+ /* if not swapping X/Y, then just apply the same transform to reverse */
+ if (!(orientation & ORIENTATION_SWAP_XY))
+ return orientation;
+
+ /* if swapping X/Y, then swap X/Y flip bits to get the reverse */
+ else
+ return orientation_swap_flips(orientation);
+}
+
+
+/*-------------------------------------------------
+ orientation_add - compute effective orientation
+ after applying two subsequent orientations
+-------------------------------------------------*/
+
+INLINE int orientation_add(int orientation1, int orientation2)
+{
+ /* if the 2nd transform doesn't swap, just XOR together */
+ if (!(orientation2 & ORIENTATION_SWAP_XY))
+ return orientation1 ^ orientation2;
+
+ /* otherwise, we need to effectively swap the flip bits on the first transform */
+ else
+ return orientation_swap_flips(orientation1) ^ orientation2;
+}
+
+
+/*-------------------------------------------------
+ apply_brightness_contrast_gamma_fp - apply
+ brightness, contrast, and gamma controls to
+ a single RGB component
+-------------------------------------------------*/
+
+INLINE float apply_brightness_contrast_gamma_fp(float srcval, float brightness, float contrast, float gamma)
+{
+ /* first apply gamma */
+ srcval = pow(srcval, 1.0f / gamma);
+
+ /* then contrast/brightness */
+ srcval = (srcval * contrast) + brightness - 1.0f;
+
+ /* clamp and return */
+ if (srcval < 0.0f)
+ srcval = 0.0f;
+ if (srcval > 1.0f)
+ srcval = 1.0f;
+ return srcval;
+}
+
+
+/*-------------------------------------------------
+ apply_brightness_contrast_gamma - apply
+ brightness, contrast, and gamma controls to
+ a single RGB component
+-------------------------------------------------*/
+
+INLINE UINT8 apply_brightness_contrast_gamma(UINT8 src, float brightness, float contrast, float gamma)
+{
+ float srcval = (float)src * (1.0f / 255.0f);
+ float result = apply_brightness_contrast_gamma_fp(srcval, brightness, contrast, gamma);
+ return (UINT8)(result * 255.0f);
+}
+
+
+#endif /* __RENDUTIL_H__ */
diff --git a/trunk/src/emu/romload.c b/trunk/src/emu/romload.c
new file mode 100644
index 00000000000..caf568a1bd8
--- /dev/null
+++ b/trunk/src/emu/romload.c
@@ -0,0 +1,1604 @@
+/*********************************************************************
+
+ romload.c
+
+ ROM loading functions.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "emuopts.h"
+#include "hash.h"
+#include "png.h"
+#include "harddisk.h"
+#include "config.h"
+#include "ui.h"
+
+
+#define LOG_LOAD 0
+#define LOG(x) do { if (LOG_LOAD) debugload x; } while(0)
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define TEMPBUFFER_MAX_SIZE (1024 * 1024 * 1024)
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _open_chd open_chd;
+struct _open_chd
+{
+ open_chd * next; /* pointer to next in the list */
+ const char * region; /* disk region we came from */
+ chd_file * origchd; /* handle to the original CHD */
+ emu_file * origfile; /* file handle to the original CHD file */
+ chd_file * diffchd; /* handle to the diff CHD */
+ emu_file * difffile; /* file handle to the diff CHD file */
+};
+
+
+typedef struct _romload_private rom_load_data;
+struct _romload_private
+{
+ running_machine &machine() const { assert(m_machine != NULL); return *m_machine; }
+
+ running_machine *m_machine; /* machine object where needed */
+ int system_bios; /* the system BIOS we wish to load */
+ int default_bios; /* the default system BIOS */
+
+ int warnings; /* warning count during processing */
+ int knownbad; /* BAD_DUMP/NO_DUMP count during processing */
+ int errors; /* error count during processing */
+
+ int romsloaded; /* current ROMs loaded count */
+ int romstotal; /* total number of ROMs to read */
+ UINT32 romsloadedsize; /* total size of ROMs loaded so far */
+ UINT32 romstotalsize; /* total size of ROMs to read */
+
+ emu_file * file; /* current file */
+ open_chd * chd_list; /* disks */
+ open_chd ** chd_list_tailptr;
+
+ memory_region * region; /* info about current region */
+
+ astring errorstring; /* error string */
+};
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void rom_exit(running_machine &machine);
+
+/***************************************************************************
+ HELPERS (also used by devimage.c)
+ ***************************************************************************/
+
+file_error common_process_file(emu_options &options, const char *location, const char *ext, const rom_entry *romp, emu_file **image_file)
+{
+ *image_file = global_alloc(emu_file(options.media_path(), OPEN_FLAG_READ));
+ file_error filerr;
+
+ if (location != NULL && strcmp(location, "") != 0)
+ filerr = (*image_file)->open(location, PATH_SEPARATOR, ROM_GETNAME(romp), ext);
+ else
+ filerr = (*image_file)->open(ROM_GETNAME(romp), ext);
+
+ if (filerr != FILERR_NONE)
+ {
+ global_free(*image_file);
+ *image_file = NULL;
+ }
+ return filerr;
+}
+
+file_error common_process_file(emu_options &options, const char *location, bool has_crc, UINT32 crc, const rom_entry *romp, emu_file **image_file)
+{
+ *image_file = global_alloc(emu_file(options.media_path(), OPEN_FLAG_READ));
+ file_error filerr;
+
+ if (has_crc)
+ filerr = (*image_file)->open(location, PATH_SEPARATOR, ROM_GETNAME(romp), crc);
+ else
+ filerr = (*image_file)->open(location, PATH_SEPARATOR, ROM_GETNAME(romp));
+
+ if (filerr != FILERR_NONE)
+ {
+ global_free(*image_file);
+ *image_file = NULL;
+ }
+ return filerr;
+}
+
+
+/***************************************************************************
+ HARD DISK HANDLING
+***************************************************************************/
+
+/*-------------------------------------------------
+ get_disk_handle - return a pointer to the
+ CHD file associated with the given region
+-------------------------------------------------*/
+
+chd_file *get_disk_handle(running_machine &machine, const char *region)
+{
+ open_chd *curdisk;
+
+ for (curdisk = machine.romload_data->chd_list; curdisk != NULL; curdisk = curdisk->next)
+ if (strcmp(curdisk->region, region) == 0)
+ return (curdisk->diffchd != NULL) ? curdisk->diffchd : curdisk->origchd;
+ return NULL;
+}
+
+
+/*-------------------------------------------------
+ add_disk_handle - add a disk to the to the
+ list of CHD files
+-------------------------------------------------*/
+
+static void add_disk_handle(running_machine &machine, open_chd *chd)
+{
+ romload_private *romload_data = machine.romload_data;
+
+ *romload_data->chd_list_tailptr = auto_alloc(machine, open_chd);
+ **romload_data->chd_list_tailptr = *chd;
+ romload_data->chd_list_tailptr = &(*romload_data->chd_list_tailptr)->next;
+}
+
+
+/*-------------------------------------------------
+ set_disk_handle - set a pointer to the CHD
+ file associated with the given region
+-------------------------------------------------*/
+
+void set_disk_handle(running_machine &machine, const char *region, emu_file &file, chd_file &chdfile)
+{
+ open_chd chd = { 0 };
+
+ /* note the region we are in */
+ chd.region = region;
+ chd.origchd = &chdfile;
+ chd.origfile = &file;
+
+ /* we're okay, add to the list of disks */
+ add_disk_handle(machine, &chd);
+}
+
+
+
+/***************************************************************************
+ ROM LOADING
+***************************************************************************/
+
+/*-------------------------------------------------
+ rom_first_source - return pointer to first ROM
+ source
+-------------------------------------------------*/
+
+const rom_source *rom_first_source(const machine_config &config)
+{
+ /* look through devices */
+ for (const device_t *device = config.devicelist().first(); device != NULL; device = device->next())
+ if (device->rom_region() != NULL)
+ return device;
+
+ return NULL;
+}
+
+
+/*-------------------------------------------------
+ rom_next_source - return pointer to next ROM
+ source
+-------------------------------------------------*/
+
+const rom_source *rom_next_source(const rom_source &previous)
+{
+ /* look for further devices with ROM definitions */
+ for (const device_t *device = previous.next(); device != NULL; device = device->next())
+ if (device->rom_region() != NULL)
+ return (rom_source *)device;
+
+ return NULL;
+}
+
+
+/*-------------------------------------------------
+ rom_first_region - return pointer to first ROM
+ region
+-------------------------------------------------*/
+
+const rom_entry *rom_first_region(const rom_source &source)
+{
+ const rom_entry *romp = source.rom_region();
+ return (romp != NULL && !ROMENTRY_ISEND(romp)) ? romp : NULL;
+}
+
+
+/*-------------------------------------------------
+ rom_next_region - return pointer to next ROM
+ region
+-------------------------------------------------*/
+
+const rom_entry *rom_next_region(const rom_entry *romp)
+{
+ romp++;
+ while (!ROMENTRY_ISREGIONEND(romp))
+ romp++;
+ return ROMENTRY_ISEND(romp) ? NULL : romp;
+}
+
+
+/*-------------------------------------------------
+ rom_first_file - return pointer to first ROM
+ file
+-------------------------------------------------*/
+
+const rom_entry *rom_first_file(const rom_entry *romp)
+{
+ romp++;
+ while (!ROMENTRY_ISFILE(romp) && !ROMENTRY_ISREGIONEND(romp))
+ romp++;
+ return ROMENTRY_ISREGIONEND(romp) ? NULL : romp;
+}
+
+
+/*-------------------------------------------------
+ rom_next_file - return pointer to next ROM
+ file
+-------------------------------------------------*/
+
+const rom_entry *rom_next_file(const rom_entry *romp)
+{
+ romp++;
+ while (!ROMENTRY_ISFILE(romp) && !ROMENTRY_ISREGIONEND(romp))
+ romp++;
+ return ROMENTRY_ISREGIONEND(romp) ? NULL : romp;
+}
+
+
+/*-------------------------------------------------
+ rom_region_name - return the appropriate name
+ for a rom region
+-------------------------------------------------*/
+
+astring &rom_region_name(astring &result, const game_driver *drv, const rom_source *source, const rom_entry *romp)
+{
+ return source->subtag(result, ROMREGION_GETTAG(romp));
+}
+
+
+/*-------------------------------------------------
+ rom_file_size - return the expected size of a
+ file given the ROM description
+-------------------------------------------------*/
+
+UINT32 rom_file_size(const rom_entry *romp)
+{
+ UINT32 maxlength = 0;
+
+ /* loop until we run out of reloads */
+ do
+ {
+ UINT32 curlength;
+
+ /* loop until we run out of continues/ignores */
+ curlength = ROM_GETLENGTH(romp++);
+ while (ROMENTRY_ISCONTINUE(romp) || ROMENTRY_ISIGNORE(romp))
+ curlength += ROM_GETLENGTH(romp++);
+
+ /* track the maximum length */
+ maxlength = MAX(maxlength, curlength);
+ }
+ while (ROMENTRY_ISRELOAD(romp));
+
+ return maxlength;
+}
+
+
+/*-------------------------------------------------
+ debugload - log data to a file
+-------------------------------------------------*/
+
+static void CLIB_DECL ATTR_PRINTF(1,2) debugload(const char *string, ...)
+{
+ static int opened;
+ va_list arg;
+ FILE *f;
+
+ f = fopen("romload.log", opened++ ? "a" : "w");
+ if (f)
+ {
+ va_start(arg, string);
+ vfprintf(f, string, arg);
+ va_end(arg);
+ fclose(f);
+ }
+}
+
+
+/*-------------------------------------------------
+ determine_bios_rom - determine system_bios
+ from SystemBios structure and OPTION_BIOS
+-------------------------------------------------*/
+
+static void determine_bios_rom(rom_load_data *romdata)
+{
+ const char *specbios = romdata->machine().options().bios();
+ const char *defaultname = NULL;
+ const rom_entry *rom;
+ int default_no = 1;
+ int bios_count = 0;
+
+ romdata->system_bios = 0;
+
+ for (const rom_source *source = rom_first_source(romdata->machine().config()); source != NULL; source = rom_next_source(*source))
+ {
+ /* first determine the default BIOS name */
+ for (rom = source->rom_region(); !ROMENTRY_ISEND(rom); rom++)
+ if (ROMENTRY_ISDEFAULT_BIOS(rom))
+ defaultname = ROM_GETNAME(rom);
+
+ /* look for a BIOS with a matching name */
+ for (rom = source->rom_region(); !ROMENTRY_ISEND(rom); rom++)
+ if (ROMENTRY_ISSYSTEM_BIOS(rom))
+ {
+ const char *biosname = ROM_GETNAME(rom);
+ int bios_flags = ROM_GETBIOSFLAGS(rom);
+ char bios_number[20];
+
+ /* Allow '-bios n' to still be used */
+ sprintf(bios_number, "%d", bios_flags - 1);
+ if (mame_stricmp(bios_number, specbios) == 0 || mame_stricmp(biosname, specbios) == 0)
+ romdata->system_bios = bios_flags;
+ if (defaultname != NULL && mame_stricmp(biosname, defaultname) == 0)
+ default_no = bios_flags;
+ bios_count++;
+ }
+
+ /* if none found, use the default */
+ if (romdata->system_bios == 0 && bios_count > 0)
+ {
+ /* if we got neither an empty string nor 'default' then warn the user */
+ if (specbios[0] != 0 && strcmp(specbios, "default") != 0 && romdata != NULL)
+ {
+ romdata->errorstring.catprintf("%s: invalid bios\n", specbios);
+ romdata->warnings++;
+ }
+
+ /* set to default */
+ romdata->system_bios = default_no;
+ }
+ romdata->default_bios = default_no;
+ LOG(("Using System BIOS: %d\n", romdata->system_bios));
+ }
+}
+
+
+/*-------------------------------------------------
+ count_roms - counts the total number of ROMs
+ that will need to be loaded
+-------------------------------------------------*/
+
+static void count_roms(rom_load_data *romdata)
+{
+ const rom_entry *region, *rom;
+ const rom_source *source;
+
+ /* start with 0 */
+ romdata->romstotal = 0;
+ romdata->romstotalsize = 0;
+
+ /* loop over regions, then over files */
+ for (source = rom_first_source(romdata->machine().config()); source != NULL; source = rom_next_source(*source))
+ for (region = rom_first_region(*source); region != NULL; region = rom_next_region(region))
+ for (rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom))
+ if (ROM_GETBIOSFLAGS(rom) == 0 || ROM_GETBIOSFLAGS(rom) == romdata->system_bios)
+ {
+ romdata->romstotal++;
+ romdata->romstotalsize += rom_file_size(rom);
+ }
+}
+
+
+/*-------------------------------------------------
+ fill_random - fills an area of memory with
+ random data
+-------------------------------------------------*/
+
+static void fill_random(running_machine &machine, UINT8 *base, UINT32 length)
+{
+ while (length--)
+ *base++ = machine.rand();
+}
+
+
+/*-------------------------------------------------
+ handle_missing_file - handles error generation
+ for missing files
+-------------------------------------------------*/
+
+static void handle_missing_file(rom_load_data *romdata, const rom_entry *romp)
+{
+ /* optional files are okay */
+ if (ROM_ISOPTIONAL(romp))
+ {
+ romdata->errorstring.catprintf("OPTIONAL %s NOT FOUND\n", ROM_GETNAME(romp));
+ romdata->warnings++;
+ }
+
+ /* no good dumps are okay */
+ else if (hash_collection(ROM_GETHASHDATA(romp)).flag(hash_collection::FLAG_NO_DUMP))
+ {
+ romdata->errorstring.catprintf("%s NOT FOUND (NO GOOD DUMP KNOWN)\n", ROM_GETNAME(romp));
+ romdata->knownbad++;
+ }
+
+ /* anything else is bad */
+ else
+ {
+ romdata->errorstring.catprintf("%s NOT FOUND\n", ROM_GETNAME(romp));
+ romdata->errors++;
+ }
+}
+
+
+/*-------------------------------------------------
+ dump_wrong_and_correct_checksums - dump an
+ error message containing the wrong and the
+ correct checksums for a given ROM
+-------------------------------------------------*/
+
+static void dump_wrong_and_correct_checksums(rom_load_data *romdata, const hash_collection &hashes, const hash_collection &acthashes)
+{
+ astring tempstr;
+ romdata->errorstring.catprintf(" EXPECTED: %s\n", hashes.macro_string(tempstr));
+ romdata->errorstring.catprintf(" FOUND: %s\n", acthashes.macro_string(tempstr));
+
+ // warn about any ill-formed hashes
+ for (hash_base *hash = hashes.first(); hash != NULL; hash = hash->next())
+ if (hash->parse_error())
+ {
+ romdata->errorstring.catprintf("\tInvalid %s checksum treated as 0 (check leading zeros)\n", hash->name());
+ romdata->warnings++;
+ }
+}
+
+
+/*-------------------------------------------------
+ verify_length_and_hash - verify the length
+ and hash signatures of a file
+-------------------------------------------------*/
+
+static void verify_length_and_hash(rom_load_data *romdata, const char *name, UINT32 explength, const hash_collection &hashes)
+{
+ /* we've already complained if there is no file */
+ if (romdata->file == NULL)
+ return;
+
+ /* verify length */
+ UINT32 actlength = romdata->file->size();
+ if (explength != actlength)
+ {
+ romdata->errorstring.catprintf("%s WRONG LENGTH (expected: %08x found: %08x)\n", name, explength, actlength);
+ romdata->warnings++;
+ }
+
+ /* If there is no good dump known, write it */
+ astring tempstr;
+ hash_collection &acthashes = romdata->file->hashes(hashes.hash_types(tempstr));
+ if (hashes.flag(hash_collection::FLAG_NO_DUMP))
+ {
+ romdata->errorstring.catprintf("%s NO GOOD DUMP KNOWN\n", name);
+ romdata->knownbad++;
+ }
+ /* verify checksums */
+ else if (hashes != acthashes)
+ {
+ /* otherwise, it's just bad */
+ romdata->errorstring.catprintf("%s WRONG CHECKSUMS:\n", name);
+ dump_wrong_and_correct_checksums(romdata, hashes, acthashes);
+ romdata->warnings++;
+ }
+ /* If it matches, but it is actually a bad dump, write it */
+ else if (hashes.flag(hash_collection::FLAG_BAD_DUMP))
+ {
+ romdata->errorstring.catprintf("%s ROM NEEDS REDUMP\n",name);
+ romdata->knownbad++;
+ }
+}
+
+
+/*-------------------------------------------------
+ display_loading_rom_message - display
+ messages about ROM loading to the user
+-------------------------------------------------*/
+
+static void display_loading_rom_message(rom_load_data *romdata, const char *name)
+{
+ char buffer[200];
+
+ // 2010-04, FP - FIXME: in MESS, load_software_part_region sometimes calls this with romstotalsize = 0!
+ // as a temp workaround, I added a check for romstotalsize !=0.
+ if (name != NULL && romdata->romstotalsize)
+ sprintf(buffer, "Loading (%d%%)", (UINT32)(100 * (UINT64)romdata->romsloadedsize / (UINT64)romdata->romstotalsize));
+ else
+ sprintf(buffer, "Loading Complete");
+
+ ui_set_startup_text(romdata->machine(), buffer, FALSE);
+}
+
+
+/*-------------------------------------------------
+ display_rom_load_results - display the final
+ results of ROM loading
+-------------------------------------------------*/
+
+static void display_rom_load_results(rom_load_data *romdata)
+{
+ /* final status display */
+ display_loading_rom_message(romdata, NULL);
+
+ /* if we had errors, they are fatal */
+ if (romdata->errors != 0)
+ {
+ /* create the error message and exit fatally */
+ mame_printf_error("%s", romdata->errorstring.cstr());
+ fatalerror_exitcode(romdata->machine(), MAMERR_MISSING_FILES, "ERROR: required files are missing, the "GAMENOUN" cannot be run.");
+ }
+
+ /* if we had warnings, output them, but continue */
+ if ((romdata-> warnings) || (romdata->knownbad))
+ {
+ romdata->errorstring.cat("WARNING: the "GAMENOUN" might not run correctly.");
+ mame_printf_warning("%s\n", romdata->errorstring.cstr());
+ }
+}
+
+
+/*-------------------------------------------------
+ region_post_process - post-process a region,
+ byte swapping and inverting data as necessary
+-------------------------------------------------*/
+
+static void region_post_process(rom_load_data *romdata, const char *rgntag, bool invert)
+{
+ const memory_region *region = romdata->machine().region(rgntag);
+ UINT8 *base;
+ int i, j;
+
+ // do nothing if no region
+ if (region == NULL)
+ return;
+
+ LOG(("+ datawidth=%d little=%d\n", region->width(), region->endianness() == ENDIANNESS_LITTLE));
+
+ /* if the region is inverted, do that now */
+ if (invert)
+ {
+ LOG(("+ Inverting region\n"));
+ for (i = 0, base = region->base(); i < region->bytes(); i++)
+ *base++ ^= 0xff;
+ }
+
+ /* swap the endianness if we need to */
+ if (region->width() > 1 && region->endianness() != ENDIANNESS_NATIVE)
+ {
+ LOG(("+ Byte swapping region\n"));
+ int datawidth = region->width();
+ for (i = 0, base = region->base(); i < region->bytes(); i += datawidth)
+ {
+ UINT8 temp[8];
+ memcpy(temp, base, datawidth);
+ for (j = datawidth - 1; j >= 0; j--)
+ *base++ = temp[j];
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ open_rom_file - open a ROM file, searching
+ up the parent and loading by checksum
+-------------------------------------------------*/
+
+static int open_rom_file(rom_load_data *romdata, const char *regiontag, const rom_entry *romp)
+{
+ file_error filerr = FILERR_NOT_FOUND;
+ UINT32 romsize = rom_file_size(romp);
+
+ /* update status display */
+ display_loading_rom_message(romdata, ROM_GETNAME(romp));
+
+ /* extract CRC to use for searching */
+ UINT32 crc = 0;
+ bool has_crc = hash_collection(ROM_GETHASHDATA(romp)).crc(crc);
+
+ /* attempt reading up the chain through the parents. It automatically also
+ attempts any kind of load by checksum supported by the archives. */
+ romdata->file = NULL;
+ for (int drv = driver_list::find(romdata->machine().system()); romdata->file == NULL && drv != -1; drv = driver_list::clone(drv))
+ filerr = common_process_file(romdata->machine().options(), driver_list::driver(drv).name, has_crc, crc, romp, &romdata->file);
+
+ /* if the region is load by name, load the ROM from there */
+ if (romdata->file == NULL && regiontag != NULL)
+ {
+ // check if we are dealing with softwarelists. if so, locationtag
+ // is actually a concatenation of: listname + setname + parentname
+ // separated by '%' (parentname being present only for clones)
+ astring tag1(regiontag), tag2, tag3, tag4, tag5;
+ bool is_list = FALSE;
+ bool has_parent = FALSE;
+
+ int separator1 = tag1.chr(0, '%');
+ if (separator1 != -1)
+ {
+ is_list = TRUE;
+
+ // we are loading through softlists, split the listname from the regiontag
+ tag4.cpysubstr(tag1, separator1 + 1, tag1.len() - separator1 + 1);
+ tag1.del(separator1, tag1.len() - separator1);
+ tag1.cat(PATH_SEPARATOR);
+
+ // check if we are loading a clone (if this is the case also tag1 have a separator '%')
+ int separator2 = tag4.chr(0, '%');
+ if (separator2 != -1)
+ {
+ has_parent = TRUE;
+
+ // we are loading a clone through softlists, split the setname from the parentname
+ tag5.cpysubstr(tag4, separator2 + 1, tag4.len() - separator2 + 1);
+ tag4.del(separator2, tag4.len() - separator2);
+ }
+
+ // prepare locations where we have to load from: list/parentname & list/clonename
+ astring swlist(tag1.cstr());
+ tag2.cpy(swlist.cat(tag4));
+ if (has_parent)
+ {
+ swlist.cpy(tag1);
+ tag3.cpy(swlist.cat(tag5));
+ }
+ }
+
+ if (tag5.chr(0, '%') != -1)
+ fatalerror("We do not support clones of clones!\n");
+
+ // try to load from the available location(s):
+ // - if we are not using lists, we have regiontag only;
+ // - if we are using lists, we have: list/clonename, list/parentname, clonename, parentname
+ if (!is_list)
+ filerr = common_process_file(romdata->machine().options(), tag1.cstr(), has_crc, crc, romp, &romdata->file);
+ else
+ {
+ // try to load from list/setname
+ if ((romdata->file == NULL) && (tag2.cstr() != NULL))
+ filerr = common_process_file(romdata->machine().options(), tag2.cstr(), has_crc, crc, romp, &romdata->file);
+ // try to load from list/parentname
+ if ((romdata->file == NULL) && has_parent && (tag3.cstr() != NULL))
+ filerr = common_process_file(romdata->machine().options(), tag3.cstr(), has_crc, crc, romp, &romdata->file);
+ // try to load from setname
+ if ((romdata->file == NULL) && (tag4.cstr() != NULL))
+ filerr = common_process_file(romdata->machine().options(), tag4.cstr(), has_crc, crc, romp, &romdata->file);
+ // try to load from parentname
+ if ((romdata->file == NULL) && has_parent && (tag5.cstr() != NULL))
+ filerr = common_process_file(romdata->machine().options(), tag5.cstr(), has_crc, crc, romp, &romdata->file);
+ }
+ }
+
+ /* update counters */
+ romdata->romsloaded++;
+ romdata->romsloadedsize += romsize;
+
+ /* return the result */
+ return (filerr == FILERR_NONE);
+}
+
+
+/*-------------------------------------------------
+ rom_fread - cheesy fread that fills with
+ random data for a NULL file
+-------------------------------------------------*/
+
+static int rom_fread(rom_load_data *romdata, UINT8 *buffer, int length)
+{
+ /* files just pass through */
+ if (romdata->file != NULL)
+ return romdata->file->read(buffer, length);
+
+ /* otherwise, fill with randomness */
+ else
+ fill_random(romdata->machine(), buffer, length);
+
+ return length;
+}
+
+
+/*-------------------------------------------------
+ read_rom_data - read ROM data for a single
+ entry
+-------------------------------------------------*/
+
+static int read_rom_data(rom_load_data *romdata, const rom_entry *romp)
+{
+ int datashift = ROM_GETBITSHIFT(romp);
+ int datamask = ((1 << ROM_GETBITWIDTH(romp)) - 1) << datashift;
+ int numbytes = ROM_GETLENGTH(romp);
+ int groupsize = ROM_GETGROUPSIZE(romp);
+ int skip = ROM_GETSKIPCOUNT(romp);
+ int reversed = ROM_ISREVERSED(romp);
+ int numgroups = (numbytes + groupsize - 1) / groupsize;
+ UINT8 *base = romdata->region->base() + ROM_GETOFFSET(romp);
+ UINT32 tempbufsize;
+ UINT8 *tempbuf;
+ int i;
+
+ LOG(("Loading ROM data: offs=%X len=%X mask=%02X group=%d skip=%d reverse=%d\n", ROM_GETOFFSET(romp), numbytes, datamask, groupsize, skip, reversed));
+
+ /* make sure the length was an even multiple of the group size */
+ if (numbytes % groupsize != 0)
+ mame_printf_warning("Warning in RomModule definition: %s length not an even multiple of group size\n", ROM_GETNAME(romp));
+
+ /* make sure we only fill within the region space */
+ if (ROM_GETOFFSET(romp) + numgroups * groupsize + (numgroups - 1) * skip > romdata->region->bytes())
+ fatalerror("Error in RomModule definition: %s out of memory region space\n", ROM_GETNAME(romp));
+
+ /* make sure the length was valid */
+ if (numbytes == 0)
+ fatalerror("Error in RomModule definition: %s has an invalid length\n", ROM_GETNAME(romp));
+
+ /* special case for simple loads */
+ if (datamask == 0xff && (groupsize == 1 || !reversed) && skip == 0)
+ return rom_fread(romdata, base, numbytes);
+
+ /* use a temporary buffer for complex loads */
+ tempbufsize = MIN(TEMPBUFFER_MAX_SIZE, numbytes);
+ tempbuf = auto_alloc_array(romdata->machine(), UINT8, tempbufsize);
+
+ /* chunky reads for complex loads */
+ skip += groupsize;
+ while (numbytes > 0)
+ {
+ int evengroupcount = (tempbufsize / groupsize) * groupsize;
+ int bytesleft = (numbytes > evengroupcount) ? evengroupcount : numbytes;
+ UINT8 *bufptr = tempbuf;
+
+ /* read as much as we can */
+ LOG((" Reading %X bytes into buffer\n", bytesleft));
+ if (rom_fread(romdata, bufptr, bytesleft) != bytesleft)
+ {
+ auto_free(romdata->machine(), tempbuf);
+ return 0;
+ }
+ numbytes -= bytesleft;
+
+ LOG((" Copying to %p\n", base));
+
+ /* unmasked cases */
+ if (datamask == 0xff)
+ {
+ /* non-grouped data */
+ if (groupsize == 1)
+ for (i = 0; i < bytesleft; i++, base += skip)
+ *base = *bufptr++;
+
+ /* grouped data -- non-reversed case */
+ else if (!reversed)
+ while (bytesleft)
+ {
+ for (i = 0; i < groupsize && bytesleft; i++, bytesleft--)
+ base[i] = *bufptr++;
+ base += skip;
+ }
+
+ /* grouped data -- reversed case */
+ else
+ while (bytesleft)
+ {
+ for (i = groupsize - 1; i >= 0 && bytesleft; i--, bytesleft--)
+ base[i] = *bufptr++;
+ base += skip;
+ }
+ }
+
+ /* masked cases */
+ else
+ {
+ /* non-grouped data */
+ if (groupsize == 1)
+ for (i = 0; i < bytesleft; i++, base += skip)
+ *base = (*base & ~datamask) | ((*bufptr++ << datashift) & datamask);
+
+ /* grouped data -- non-reversed case */
+ else if (!reversed)
+ while (bytesleft)
+ {
+ for (i = 0; i < groupsize && bytesleft; i++, bytesleft--)
+ base[i] = (base[i] & ~datamask) | ((*bufptr++ << datashift) & datamask);
+ base += skip;
+ }
+
+ /* grouped data -- reversed case */
+ else
+ while (bytesleft)
+ {
+ for (i = groupsize - 1; i >= 0 && bytesleft; i--, bytesleft--)
+ base[i] = (base[i] & ~datamask) | ((*bufptr++ << datashift) & datamask);
+ base += skip;
+ }
+ }
+ }
+ auto_free(romdata->machine(), tempbuf);
+
+ LOG((" All done\n"));
+ return ROM_GETLENGTH(romp);
+}
+
+
+/*-------------------------------------------------
+ fill_rom_data - fill a region of ROM space
+-------------------------------------------------*/
+
+static void fill_rom_data(rom_load_data *romdata, const rom_entry *romp)
+{
+ UINT32 numbytes = ROM_GETLENGTH(romp);
+ UINT8 *base = romdata->region->base() + ROM_GETOFFSET(romp);
+
+ /* make sure we fill within the region space */
+ if (ROM_GETOFFSET(romp) + numbytes > romdata->region->bytes())
+ fatalerror("Error in RomModule definition: FILL out of memory region space\n");
+
+ /* make sure the length was valid */
+ if (numbytes == 0)
+ fatalerror("Error in RomModule definition: FILL has an invalid length\n");
+
+ /* fill the data (filling value is stored in place of the hashdata) */
+ memset(base, (FPTR)ROM_GETHASHDATA(romp) & 0xff, numbytes);
+}
+
+
+/*-------------------------------------------------
+ copy_rom_data - copy a region of ROM space
+-------------------------------------------------*/
+
+static void copy_rom_data(rom_load_data *romdata, const rom_entry *romp)
+{
+ UINT8 *base = romdata->region->base() + ROM_GETOFFSET(romp);
+ const char *srcrgntag = ROM_GETNAME(romp);
+ UINT32 numbytes = ROM_GETLENGTH(romp);
+ UINT32 srcoffs = (FPTR)ROM_GETHASHDATA(romp); /* srcoffset in place of hashdata */
+
+ /* make sure we copy within the region space */
+ if (ROM_GETOFFSET(romp) + numbytes > romdata->region->bytes())
+ fatalerror("Error in RomModule definition: COPY out of target memory region space\n");
+
+ /* make sure the length was valid */
+ if (numbytes == 0)
+ fatalerror("Error in RomModule definition: COPY has an invalid length\n");
+
+ /* make sure the source was valid */
+ const memory_region *region = romdata->machine().region(srcrgntag);
+ if (region == NULL)
+ fatalerror("Error in RomModule definition: COPY from an invalid region\n");
+
+ /* make sure we find within the region space */
+ if (srcoffs + numbytes > region->bytes())
+ fatalerror("Error in RomModule definition: COPY out of source memory region space\n");
+
+ /* fill the data */
+ memcpy(base, region->base() + srcoffs, numbytes);
+}
+
+
+/*-------------------------------------------------
+ process_rom_entries - process all ROM entries
+ for a region
+-------------------------------------------------*/
+
+static void process_rom_entries(rom_load_data *romdata, const char *regiontag, const rom_entry *romp)
+{
+ UINT32 lastflags = 0;
+
+ /* loop until we hit the end of this region */
+ while (!ROMENTRY_ISREGIONEND(romp))
+ {
+ /* if this is a continue entry, it's invalid */
+ if (ROMENTRY_ISCONTINUE(romp))
+ fatalerror("Error in RomModule definition: ROM_CONTINUE not preceded by ROM_LOAD\n");
+
+ /* if this is an ignore entry, it's invalid */
+ if (ROMENTRY_ISIGNORE(romp))
+ fatalerror("Error in RomModule definition: ROM_IGNORE not preceded by ROM_LOAD\n");
+
+ /* if this is a reload entry, it's invalid */
+ if (ROMENTRY_ISRELOAD(romp))
+ fatalerror("Error in RomModule definition: ROM_RELOAD not preceded by ROM_LOAD\n");
+
+ /* handle fills */
+ if (ROMENTRY_ISFILL(romp))
+ fill_rom_data(romdata, romp++);
+
+ /* handle copies */
+ else if (ROMENTRY_ISCOPY(romp))
+ copy_rom_data(romdata, romp++);
+
+ /* handle files */
+ else if (ROMENTRY_ISFILE(romp))
+ {
+ int irrelevantbios = (ROM_GETBIOSFLAGS(romp) != 0 && ROM_GETBIOSFLAGS(romp) != romdata->system_bios);
+ const rom_entry *baserom = romp;
+ int explength = 0;
+
+ /* open the file if it is a non-BIOS or matches the current BIOS */
+ LOG(("Opening ROM file: %s\n", ROM_GETNAME(romp)));
+ if (!irrelevantbios && !open_rom_file(romdata, regiontag, romp))
+ handle_missing_file(romdata, romp);
+
+ /* loop until we run out of reloads */
+ do
+ {
+ /* loop until we run out of continues/ignores */
+ do
+ {
+ rom_entry modified_romp = *romp++;
+ //int readresult;
+
+ /* handle flag inheritance */
+ if (!ROM_INHERITSFLAGS(&modified_romp))
+ lastflags = modified_romp._flags;
+ else
+ modified_romp._flags = (modified_romp._flags & ~ROM_INHERITEDFLAGS) | lastflags;
+
+ explength += ROM_GETLENGTH(&modified_romp);
+
+ /* attempt to read using the modified entry */
+ if (!ROMENTRY_ISIGNORE(&modified_romp) && !irrelevantbios)
+ /*readresult = */read_rom_data(romdata, &modified_romp);
+ }
+ while (ROMENTRY_ISCONTINUE(romp) || ROMENTRY_ISIGNORE(romp));
+
+ /* if this was the first use of this file, verify the length and CRC */
+ if (baserom)
+ {
+ LOG(("Verifying length (%X) and checksums\n", explength));
+ verify_length_and_hash(romdata, ROM_GETNAME(baserom), explength, hash_collection(ROM_GETHASHDATA(baserom)));
+ LOG(("Verify finished\n"));
+ }
+
+ /* reseek to the start and clear the baserom so we don't reverify */
+ if (romdata->file != NULL)
+ romdata->file->seek(0, SEEK_SET);
+ baserom = NULL;
+ explength = 0;
+ }
+ while (ROMENTRY_ISRELOAD(romp));
+
+ /* close the file */
+ if (romdata->file != NULL)
+ {
+ LOG(("Closing ROM file\n"));
+ global_free(romdata->file);
+ romdata->file = NULL;
+ }
+ }
+ else
+ {
+ romp++; /* something else; skip */
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ open_disk_image - open a disk image,
+ searching up the parent and loading by
+ checksum
+-------------------------------------------------*/
+
+chd_error open_disk_image(emu_options &options, const game_driver *gamedrv, const rom_entry *romp, emu_file **image_file, chd_file **image_chd, const char *locationtag)
+{
+ const rom_entry *region, *rom;
+ const rom_source *source;
+ file_error filerr;
+ chd_error err;
+
+ *image_file = NULL;
+ *image_chd = NULL;
+
+ /* attempt to open the properly named file, scanning up through parent directories */
+ filerr = FILERR_NOT_FOUND;
+ for (int searchdrv = driver_list::find(*gamedrv); searchdrv != -1 && filerr != FILERR_NONE; searchdrv = driver_list::clone(searchdrv))
+ filerr = common_process_file(options, driver_list::driver(searchdrv).name, ".chd", romp, image_file);
+
+ if (filerr != FILERR_NONE)
+ filerr = common_process_file(options, NULL, ".chd", romp, image_file);
+
+ /* look for the disk in the locationtag too */
+ if (filerr != FILERR_NONE && locationtag != NULL)
+ {
+ // check if we are dealing with softwarelists. if so, locationtag
+ // is actually a concatenation of: listname + setname + parentname
+ // separated by '%' (parentname being present only for clones)
+ astring tag1(locationtag), tag2, tag3, tag4, tag5;
+ bool is_list = FALSE;
+ bool has_parent = FALSE;
+
+ int separator1 = tag1.chr(0, '%');
+ if (separator1 != -1)
+ {
+ is_list = TRUE;
+
+ // we are loading through softlists, split the listname from the regiontag
+ tag4.cpysubstr(tag1, separator1 + 1, tag1.len() - separator1 + 1);
+ tag1.del(separator1, tag1.len() - separator1);
+ tag1.cat(PATH_SEPARATOR);
+
+ // check if we are loading a clone (if this is the case also tag1 have a separator '%')
+ int separator2 = tag4.chr(0, '%');
+ if (separator2 != -1)
+ {
+ has_parent = TRUE;
+
+ // we are loading a clone through softlists, split the setname from the parentname
+ tag5.cpysubstr(tag4, separator2 + 1, tag4.len() - separator2 + 1);
+ tag4.del(separator2, tag4.len() - separator2);
+ }
+
+ // prepare locations where we have to load from: list/parentname (if any) & list/clonename
+ astring swlist(tag1.cstr());
+ tag2.cpy(swlist.cat(tag4));
+ if (has_parent)
+ {
+ swlist.cpy(tag1);
+ tag3.cpy(swlist.cat(tag5));
+ }
+ }
+
+ if (tag5.chr(0, '%') != -1)
+ fatalerror("We do not support clones of clones!\n");
+
+ // try to load from the available location(s):
+ // - if we are not using lists, we have locationtag only;
+ // - if we are using lists, we have: list/clonename, list/parentname, clonename, parentname
+ if (!is_list)
+ filerr = common_process_file(options, locationtag, ".chd", romp, image_file);
+ else
+ {
+ // try to load from list/setname
+ if ((filerr != FILERR_NONE) && (tag2.cstr() != NULL))
+ filerr = common_process_file(options, tag2.cstr(), ".chd", romp, image_file);
+ // try to load from list/parentname (if any)
+ if ((filerr != FILERR_NONE) && has_parent && (tag3.cstr() != NULL))
+ filerr = common_process_file(options, tag3.cstr(), ".chd", romp, image_file);
+ // try to load from setname
+ if ((filerr != FILERR_NONE) && (tag4.cstr() != NULL))
+ filerr = common_process_file(options, tag4.cstr(), ".chd", romp, image_file);
+ // try to load from parentname (if any)
+ if ((filerr != FILERR_NONE) && has_parent && (tag5.cstr() != NULL))
+ filerr = common_process_file(options, tag5.cstr(), ".chd", romp, image_file);
+ // only for CHD we also try to load from list/
+ if ((filerr != FILERR_NONE) && (tag1.cstr() != NULL))
+ {
+ tag1.del(tag1.len() - 1, 1); // remove the PATH_SEPARATOR
+ filerr = common_process_file(options, tag1.cstr(), ".chd", romp, image_file);
+ }
+ }
+ }
+
+ /* did the file open succeed? */
+ if (filerr == FILERR_NONE)
+ {
+ /* try to open the CHD */
+ err = chd_open_file(**image_file, CHD_OPEN_READ, NULL, image_chd);
+ if (err == CHDERR_NONE)
+ return err;
+
+ /* close the file on failure */
+ global_free(*image_file);
+ *image_file = NULL;
+ }
+ else
+ err = CHDERR_FILE_NOT_FOUND;
+
+ /* otherwise, look at our parents for a CHD with an identical checksum */
+ /* and try to open that */
+ hash_collection romphashes(ROM_GETHASHDATA(romp));
+ for (int drv = driver_list::find(*gamedrv); drv != -1; drv = driver_list::clone(drv))
+ {
+ machine_config config(driver_list::driver(drv), options);
+ for (source = rom_first_source(config); source != NULL; source = rom_next_source(*source))
+ for (region = rom_first_region(*source); region != NULL; region = rom_next_region(region))
+ if (ROMREGION_ISDISKDATA(region))
+ for (rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom))
+
+ /* look for a differing name but with the same hash data */
+ if (strcmp(ROM_GETNAME(romp), ROM_GETNAME(rom)) != 0 &&
+ romphashes == hash_collection(ROM_GETHASHDATA(rom)))
+ {
+ /* attempt to open the properly named file, scanning up through parent directories */
+ filerr = FILERR_NOT_FOUND;
+ for (int searchdrv = drv; searchdrv != -1 && filerr != FILERR_NONE; searchdrv = driver_list::clone(searchdrv))
+ filerr = common_process_file(options, driver_list::driver(searchdrv).name, ".chd", rom, image_file);
+
+ if (filerr != FILERR_NONE)
+ filerr = common_process_file(options, NULL, ".chd", rom, image_file);
+
+ /* did the file open succeed? */
+ if (filerr == FILERR_NONE)
+ {
+ /* try to open the CHD */
+ err = chd_open_file(**image_file, CHD_OPEN_READ, NULL, image_chd);
+ if (err == CHDERR_NONE)
+ return err;
+
+ /* close the file on failure */
+ global_free(*image_file);
+ *image_file = NULL;
+ }
+ }
+ }
+
+ return err;
+}
+
+
+/*-------------------------------------------------
+ open_disk_diff - open a DISK diff file
+-------------------------------------------------*/
+
+static chd_error open_disk_diff(emu_options &options, const rom_entry *romp, chd_file *source, emu_file **diff_file, chd_file **diff_chd)
+{
+ astring fname(ROM_GETNAME(romp), ".dif");
+ chd_error err;
+
+ *diff_file = NULL;
+ *diff_chd = NULL;
+
+ /* try to open the diff */
+ LOG(("Opening differencing image file: %s\n", fname.cstr()));
+ *diff_file = global_alloc(emu_file(options.diff_directory(), OPEN_FLAG_READ | OPEN_FLAG_WRITE));
+ file_error filerr = (*diff_file)->open(fname);
+ if (filerr != FILERR_NONE)
+ {
+ /* didn't work; try creating it instead */
+ LOG(("Creating differencing image: %s\n", fname.cstr()));
+ (*diff_file)->set_openflags(OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ filerr = (*diff_file)->open(fname);
+ if (filerr != FILERR_NONE)
+ {
+ err = CHDERR_FILE_NOT_FOUND;
+ goto done;
+ }
+
+ /* create the CHD */
+ err = chd_create_file(**diff_file, 0, 0, CHDCOMPRESSION_NONE, source);
+ if (err != CHDERR_NONE)
+ goto done;
+ }
+
+ LOG(("Opening differencing image file: %s\n", fname.cstr()));
+ err = chd_open_file(**diff_file, CHD_OPEN_READWRITE, source, diff_chd);
+ if (err != CHDERR_NONE)
+ goto done;
+
+done:
+ if ((err != CHDERR_NONE) && (*diff_file != NULL))
+ {
+ global_free(*diff_file);
+ *diff_file = NULL;
+ }
+ return err;
+}
+
+
+/*-------------------------------------------------
+ process_disk_entries - process all disk entries
+ for a region
+-------------------------------------------------*/
+
+static void process_disk_entries(rom_load_data *romdata, const char *regiontag, const rom_entry *romp, const char *locationtag)
+{
+ /* loop until we hit the end of this region */
+ for ( ; !ROMENTRY_ISREGIONEND(romp); romp++)
+ {
+ /* handle files */
+ if (ROMENTRY_ISFILE(romp))
+ {
+ hash_collection hashes(ROM_GETHASHDATA(romp));
+ open_chd chd = { 0 };
+ chd_header header;
+ chd_error err;
+
+ /* note the region we are in */
+ chd.region = regiontag;
+
+ /* make the filename of the source */
+ astring filename(ROM_GETNAME(romp), ".chd");
+
+ /* first open the source drive */
+ LOG(("Opening disk image: %s\n", filename.cstr()));
+ err = open_disk_image(romdata->machine().options(), &romdata->machine().system(), romp, &chd.origfile, &chd.origchd, locationtag);
+ if (err != CHDERR_NONE)
+ {
+ if (err == CHDERR_FILE_NOT_FOUND)
+ romdata->errorstring.catprintf("%s NOT FOUND\n", filename.cstr());
+ else
+ romdata->errorstring.catprintf("%s CHD ERROR: %s\n", filename.cstr(), chd_error_string(err));
+
+ /* if this is NO_DUMP, keep going, though the system may not be able to handle it */
+ if (hashes.flag(hash_collection::FLAG_NO_DUMP))
+ romdata->knownbad++;
+ else if (DISK_ISOPTIONAL(romp))
+ romdata->warnings++;
+ else
+ romdata->errors++;
+ continue;
+ }
+
+ /* get the header and extract the SHA1 */
+ header = *chd_get_header(chd.origchd);
+ hash_collection acthashes;
+ acthashes.add_from_buffer(hash_collection::HASH_SHA1, header.sha1, sizeof(header.sha1));
+
+ /* verify the hash */
+ if (hashes != acthashes)
+ {
+ romdata->errorstring.catprintf("%s WRONG CHECKSUMS:\n", filename.cstr());
+ dump_wrong_and_correct_checksums(romdata, hashes, acthashes);
+ romdata->warnings++;
+ }
+ else if (hashes.flag(hash_collection::FLAG_BAD_DUMP))
+ {
+ romdata->errorstring.catprintf("%s CHD NEEDS REDUMP\n", filename.cstr());
+ romdata->knownbad++;
+ }
+
+ /* if not read-only, make the diff file */
+ if (!DISK_ISREADONLY(romp))
+ {
+ /* try to open or create the diff */
+ err = open_disk_diff(romdata->machine().options(), romp, chd.origchd, &chd.difffile, &chd.diffchd);
+ if (err != CHDERR_NONE)
+ {
+ romdata->errorstring.catprintf("%s DIFF CHD ERROR: %s\n", filename.cstr(), chd_error_string(err));
+ romdata->errors++;
+ continue;
+ }
+ }
+
+ /* we're okay, add to the list of disks */
+ LOG(("Assigning to handle %d\n", DISK_GETINDEX(romp)));
+ add_disk_handle(romdata->machine(), &chd);
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ normalize_flags_for_device - modify the region
+ flags for the given device
+-------------------------------------------------*/
+
+static void normalize_flags_for_device(running_machine &machine, const char *rgntag, UINT8 &width, endianness_t &endian)
+{
+ device_t *device = machine.device(rgntag);
+ device_memory_interface *memory;
+ if (device->interface(memory))
+ {
+ const address_space_config *spaceconfig = memory->space_config();
+ if (spaceconfig != NULL)
+ {
+ int buswidth;
+
+ /* set the endianness */
+ if (spaceconfig->m_endianness == ENDIANNESS_LITTLE)
+ endian = ENDIANNESS_LITTLE;
+ else
+ endian = ENDIANNESS_BIG;
+
+ /* set the width */
+ buswidth = spaceconfig->m_databus_width;
+ if (buswidth <= 8)
+ width = 1;
+ else if (buswidth <= 16)
+ width = 2;
+ else if (buswidth <= 32)
+ width = 4;
+ else
+ width = 8;
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ load_software_part_region - load a software part
+
+ This is used by MESS when loading a piece of
+ software. The code should be merged with
+ process_region_list or updated to use a slight
+ more general process_region_list.
+-------------------------------------------------*/
+
+void load_software_part_region(device_t *device, char *swlist, char *swname, rom_entry *start_region)
+{
+ astring locationtag(swlist), breakstr("%");
+ rom_load_data *romdata = device->machine().romload_data;
+ const rom_entry *region;
+ astring regiontag;
+
+ // attempt reading up the chain through the parents and create a locationtag astring in the format
+ // " swlist % clonename % parentname "
+ // open_rom_file contains the code to split the elements and to create paths to load from
+
+ software_list *software_list_ptr = software_list_open(device->machine().options(), swlist, FALSE, NULL);
+ if (software_list_ptr)
+ {
+ locationtag.cat(breakstr);
+
+ for (software_info *swinfo = software_list_find(software_list_ptr, swname, NULL); swinfo != NULL; )
+ {
+ {
+ astring tmp(swinfo->shortname);
+ locationtag.cat(tmp);
+ locationtag.cat(breakstr);
+ // printf("%s\n", locationtag.cstr());
+ }
+ const char *parentname = software_get_clone(device->machine().options(), swlist, swinfo->shortname);
+ if (parentname != NULL)
+ swinfo = software_list_find(software_list_ptr, parentname, NULL);
+ else
+ swinfo = NULL;
+ }
+ // strip the final '%'
+ locationtag.del(locationtag.len() - 1, 1);
+ software_list_close(software_list_ptr);
+ }
+
+ /* Make sure we are passed a device */
+ assert(device != NULL);
+
+ romdata->errorstring.reset();
+
+ if (software_get_support(device->machine().options(), swlist, swname) == SOFTWARE_SUPPORTED_PARTIAL)
+ {
+ romdata->errorstring.catprintf("WARNING: support for software %s (in list %s) is only partial\n", swname, swlist);
+ romdata->warnings++;
+ }
+ if (software_get_support(device->machine().options(), swlist, swname) == SOFTWARE_SUPPORTED_NO)
+ {
+ romdata->errorstring.catprintf("WARNING: support for software %s (in list %s) is only preliminary\n", swname, swlist);
+ romdata->warnings++;
+ }
+
+ /* loop until we hit the end */
+ for (region = start_region; region != NULL; region = rom_next_region(region))
+ {
+ UINT32 regionlength = ROMREGION_GETLENGTH(region);
+
+ device->subtag(regiontag, ROMREGION_GETTAG(region));
+ LOG(("Processing region \"%s\" (length=%X)\n", regiontag.cstr(), regionlength));
+
+ /* the first entry must be a region */
+ assert(ROMENTRY_ISREGION(region));
+
+ /* if this is a device region, override with the device width and endianness */
+ endianness_t endianness = ROMREGION_ISBIGENDIAN(region) ? ENDIANNESS_BIG : ENDIANNESS_LITTLE;
+ UINT8 width = ROMREGION_GETWIDTH(region) / 8;
+ const memory_region *memregion = romdata->machine().region(regiontag);
+ if (memregion != NULL)
+ {
+ if (romdata->machine().device(regiontag) != NULL)
+ normalize_flags_for_device(romdata->machine(), regiontag, width, endianness);
+
+ /* clear old region (todo: should be moved to an image unload function) */
+ romdata->machine().region_free(memregion->name());
+ }
+
+ /* remember the base and length */
+ romdata->region = romdata->machine().region_alloc(regiontag, regionlength, width, endianness);
+ LOG(("Allocated %X bytes @ %p\n", romdata->region->bytes(), romdata->region->base()));
+
+ /* clear the region if it's requested */
+ if (ROMREGION_ISERASE(region))
+ memset(romdata->region->base(), ROMREGION_GETERASEVAL(region), romdata->region->bytes());
+
+ /* or if it's sufficiently small (<= 4MB) */
+ else if (romdata->region->bytes() <= 0x400000)
+ memset(romdata->region->base(), 0, romdata->region->bytes());
+
+#ifdef MAME_DEBUG
+ /* if we're debugging, fill region with random data to catch errors */
+ else
+ fill_random(romdata->machine(), romdata->region->base(), romdata->region->bytes());
+#endif
+
+ /* now process the entries in the region */
+ if (ROMREGION_ISROMDATA(region))
+ process_rom_entries(romdata, locationtag, region + 1);
+ else if (ROMREGION_ISDISKDATA(region))
+ process_disk_entries(romdata, core_strdup(regiontag.cstr()), region + 1, locationtag);
+ }
+
+ /* now go back and post-process all the regions */
+ for (region = start_region; region != NULL; region = rom_next_region(region)) {
+ device->subtag(regiontag, ROMREGION_GETTAG(region));
+ region_post_process(romdata, regiontag.cstr(), ROMREGION_ISINVERTED(region));
+ }
+
+ /* display the results and exit */
+ display_rom_load_results(romdata);
+}
+
+
+/*-------------------------------------------------
+ process_region_list - process a region list
+-------------------------------------------------*/
+
+static void process_region_list(rom_load_data *romdata)
+{
+ astring regiontag;
+ const rom_source *source;
+ const rom_entry *region;
+
+ /* loop until we hit the end */
+ for (source = rom_first_source(romdata->machine().config()); source != NULL; source = rom_next_source(*source))
+ for (region = rom_first_region(*source); region != NULL; region = rom_next_region(region))
+ {
+ UINT32 regionlength = ROMREGION_GETLENGTH(region);
+
+ rom_region_name(regiontag, &romdata->machine().system(), source, region);
+ LOG(("Processing region \"%s\" (length=%X)\n", regiontag.cstr(), regionlength));
+
+ /* the first entry must be a region */
+ assert(ROMENTRY_ISREGION(region));
+
+ if (ROMREGION_ISROMDATA(region))
+ {
+ /* if this is a device region, override with the device width and endianness */
+ UINT8 width = ROMREGION_GETWIDTH(region) / 8;
+ endianness_t endianness = ROMREGION_ISBIGENDIAN(region) ? ENDIANNESS_BIG : ENDIANNESS_LITTLE;
+ if (romdata->machine().device(regiontag) != NULL)
+ normalize_flags_for_device(romdata->machine(), regiontag, width, endianness);
+
+ /* remember the base and length */
+ romdata->region = romdata->machine().region_alloc(regiontag, regionlength, width, endianness);
+ LOG(("Allocated %X bytes @ %p\n", romdata->region->bytes(), romdata->region->base()));
+
+ /* clear the region if it's requested */
+ if (ROMREGION_ISERASE(region))
+ memset(romdata->region->base(), ROMREGION_GETERASEVAL(region), romdata->region->bytes());
+
+ /* or if it's sufficiently small (<= 4MB) */
+ else if (romdata->region->bytes() <= 0x400000)
+ memset(romdata->region->base(), 0, romdata->region->bytes());
+
+#ifdef MAME_DEBUG
+ /* if we're debugging, fill region with random data to catch errors */
+ else
+ fill_random(romdata->machine(), romdata->region->base(), romdata->region->bytes());
+#endif
+
+ /* now process the entries in the region */
+ process_rom_entries(romdata, (source->shortname()!=NULL) ? source->shortname() : NULL, region + 1);
+ }
+ else if (ROMREGION_ISDISKDATA(region))
+ process_disk_entries(romdata, ROMREGION_GETTAG(region), region + 1, NULL);
+ }
+
+ /* now go back and post-process all the regions */
+ for (source = rom_first_source(romdata->machine().config()); source != NULL; source = rom_next_source(*source))
+ for (region = rom_first_region(*source); region != NULL; region = rom_next_region(region)) {
+ rom_region_name(regiontag, &romdata->machine().system(), source, region);
+ region_post_process(romdata, regiontag, ROMREGION_ISINVERTED(region));
+ }
+}
+
+
+/*-------------------------------------------------
+ rom_init - load the ROMs and open the disk
+ images associated with the given machine
+-------------------------------------------------*/
+
+void rom_init(running_machine &machine)
+{
+ rom_load_data *romdata;
+
+ /* allocate private data */
+ machine.romload_data = romdata = auto_alloc_clear(machine, romload_private);
+
+ /* make sure we get called back on the way out */
+ machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(rom_exit), &machine));
+
+ /* reset the romdata struct */
+ romdata->m_machine = &machine;
+
+ /* figure out which BIOS we are using */
+ determine_bios_rom(romdata);
+
+ /* count the total number of ROMs */
+ count_roms(romdata);
+
+ /* reset the disk list */
+ romdata->chd_list = NULL;
+ romdata->chd_list_tailptr = &machine.romload_data->chd_list;
+
+ /* process the ROM entries we were passed */
+ process_region_list(romdata);
+
+ /* display the results and exit */
+ display_rom_load_results(romdata);
+}
+
+
+/*-------------------------------------------------
+ rom_exit - clean up after ourselves
+-------------------------------------------------*/
+
+static void rom_exit(running_machine &machine)
+{
+ open_chd *curchd;
+
+ /* close all hard drives */
+ for (curchd = machine.romload_data->chd_list; curchd != NULL; curchd = curchd->next)
+ {
+ if (curchd->diffchd != NULL)
+ chd_close(curchd->diffchd);
+ if (curchd->difffile != NULL)
+ global_free(curchd->difffile);
+ if (curchd->origchd != NULL)
+ chd_close(curchd->origchd);
+ if (curchd->origfile != NULL)
+ global_free(curchd->origfile);
+ }
+}
+
+
+/*-------------------------------------------------
+ rom_load_warnings - return the number of
+ warnings we generated
+-------------------------------------------------*/
+
+int rom_load_warnings(running_machine &machine)
+{
+ return machine.romload_data->warnings;
+}
+
+
+/*-------------------------------------------------
+ rom_load_knownbad - return the number of
+ BAD_DUMP/NO_DUMP warnings we generated
+-------------------------------------------------*/
+
+int rom_load_knownbad(running_machine &machine)
+{
+ return machine.romload_data->knownbad;
+}
+
+
+/*-------------------------------------------------
+ rom_system_bios - return id of selected bios
+-------------------------------------------------*/
+
+int rom_system_bios(running_machine &machine)
+{
+ return machine.romload_data->system_bios;
+}
+
+/*-------------------------------------------------
+ rom_default_bios - return id of default bios
+-------------------------------------------------*/
+
+int rom_default_bios(running_machine &machine)
+{
+ return machine.romload_data->default_bios;
+}
diff --git a/trunk/src/emu/romload.h b/trunk/src/emu/romload.h
new file mode 100644
index 00000000000..77cc35d0626
--- /dev/null
+++ b/trunk/src/emu/romload.h
@@ -0,0 +1,328 @@
+/*********************************************************************
+
+ romload.h
+
+ ROM loading functions.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+#pragma once
+
+#ifndef __EMU_H__
+#error Dont include this file directly; include emu.h instead.
+#endif
+
+#ifndef __ROMLOAD_H__
+#define __ROMLOAD_H__
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* ----- type constants ----- */
+#define ROMENTRY_TYPEMASK 0x0000000f /* type of entry */
+enum
+{
+ ROMENTRYTYPE_ROM = 0, /* this entry is an actual ROM definition */
+ ROMENTRYTYPE_REGION, /* this entry marks the start of a region */
+ ROMENTRYTYPE_END, /* this entry marks the end of a region */
+ ROMENTRYTYPE_RELOAD, /* this entry reloads the previous ROM */
+ ROMENTRYTYPE_CONTINUE, /* this entry continues loading the previous ROM */
+ ROMENTRYTYPE_FILL, /* this entry fills an area with a constant value */
+ ROMENTRYTYPE_COPY, /* this entry copies data from another region/offset */
+ ROMENTRYTYPE_CARTRIDGE, /* this entry specifies a cartridge (MESS) */
+ ROMENTRYTYPE_IGNORE, /* this entry continues loading the previous ROM but throws the data away */
+ ROMENTRYTYPE_SYSTEM_BIOS, /* this entry specifies a bios */
+ ROMENTRYTYPE_DEFAULT_BIOS, /* this entry specifies a default bios */
+ ROMENTRYTYPE_COUNT
+};
+
+/* ----- per-region constants ----- */
+#define ROMREGION_WIDTHMASK 0x00000300 /* native width of region, as power of 2 */
+#define ROMREGION_8BIT 0x00000000 /* (non-CPU regions only) */
+#define ROMREGION_16BIT 0x00000100
+#define ROMREGION_32BIT 0x00000200
+#define ROMREGION_64BIT 0x00000300
+
+#define ROMREGION_ENDIANMASK 0x00000400 /* endianness of the region */
+#define ROMREGION_LE 0x00000000 /* (non-CPU regions only) */
+#define ROMREGION_BE 0x00000400
+
+#define ROMREGION_INVERTMASK 0x00000800 /* invert the bits of the region */
+#define ROMREGION_NOINVERT 0x00000000
+#define ROMREGION_INVERT 0x00000800
+
+#define ROMREGION_ERASEMASK 0x00002000 /* erase the region before loading */
+#define ROMREGION_NOERASE 0x00000000
+#define ROMREGION_ERASE 0x00002000
+
+#define ROMREGION_DATATYPEMASK 0x00004000 /* type of region (ROM versus disk) */
+#define ROMREGION_DATATYPEROM 0x00000000
+#define ROMREGION_DATATYPEDISK 0x00004000
+
+#define ROMREGION_ERASEVALMASK 0x00ff0000 /* value to erase the region to */
+#define ROMREGION_ERASEVAL(x) ((((x) & 0xff) << 16) | ROMREGION_ERASE)
+#define ROMREGION_ERASE00 ROMREGION_ERASEVAL(0)
+#define ROMREGION_ERASEFF ROMREGION_ERASEVAL(0xff)
+
+
+/* ----- per-ROM constants ----- */
+#define DISK_READONLYMASK 0x00000010 /* is the disk read-only? */
+#define DISK_READWRITE 0x00000000
+#define DISK_READONLY 0x00000010
+
+#define ROM_OPTIONALMASK 0x00000020 /* optional - won't hurt if it's not there */
+#define ROM_REQUIRED 0x00000000
+#define ROM_OPTIONAL 0x00000020
+
+#define ROM_REVERSEMASK 0x00000040 /* reverse the byte order within a group */
+#define ROM_NOREVERSE 0x00000000
+#define ROM_REVERSE 0x00000040
+
+#define ROM_INHERITFLAGSMASK 0x00000080 /* inherit all flags from previous definition */
+#define ROM_INHERITFLAGS 0x00000080
+
+#define ROM_GROUPMASK 0x00000f00 /* load data in groups of this size + 1 */
+#define ROM_GROUPSIZE(n) ((((n) - 1) & 15) << 8)
+#define ROM_GROUPBYTE ROM_GROUPSIZE(1)
+#define ROM_GROUPWORD ROM_GROUPSIZE(2)
+#define ROM_GROUPDWORD ROM_GROUPSIZE(4)
+
+#define ROM_SKIPMASK 0x0000f000 /* skip this many bytes after each group */
+#define ROM_SKIP(n) (((n) & 15) << 12)
+#define ROM_NOSKIP ROM_SKIP(0)
+
+#define ROM_BITWIDTHMASK 0x000f0000 /* width of data in bits */
+#define ROM_BITWIDTH(n) (((n) & 15) << 16)
+#define ROM_NIBBLE ROM_BITWIDTH(4)
+#define ROM_FULLBYTE ROM_BITWIDTH(8)
+
+#define ROM_BITSHIFTMASK 0x00f00000 /* left-shift count for the bits */
+#define ROM_BITSHIFT(n) (((n) & 15) << 20)
+#define ROM_NOSHIFT ROM_BITSHIFT(0)
+#define ROM_SHIFT_NIBBLE_LO ROM_BITSHIFT(0)
+#define ROM_SHIFT_NIBBLE_HI ROM_BITSHIFT(4)
+
+#define ROM_BIOSFLAGSMASK 0xff000000 /* only loaded if value matches global bios value */
+#define ROM_BIOS(n) (((n) & 255) << 24)
+
+#define ROM_INHERITEDFLAGS (ROM_GROUPMASK | ROM_SKIPMASK | ROM_REVERSEMASK | ROM_BITWIDTHMASK | ROM_BITSHIFTMASK | ROM_BIOSFLAGSMASK)
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+class machine_config;
+class emu_options;
+
+typedef device_t rom_source;
+
+
+struct rom_entry
+{
+ const char * _name; /* name of the file to load */
+ const char * _hashdata; /* hashing informations (checksums) */
+ UINT32 _offset; /* offset to load it to */
+ UINT32 _length; /* length of the file */
+ UINT32 _flags; /* flags */
+};
+
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+/* ----- per-entry macros ----- */
+#define ROMENTRY_GETTYPE(r) ((r)->_flags & ROMENTRY_TYPEMASK)
+#define ROMENTRY_ISSPECIAL(r) (ROMENTRY_GETTYPE(r) != ROMENTRYTYPE_ROM)
+#define ROMENTRY_ISFILE(r) (ROMENTRY_GETTYPE(r) == ROMENTRYTYPE_ROM)
+#define ROMENTRY_ISREGION(r) (ROMENTRY_GETTYPE(r) == ROMENTRYTYPE_REGION)
+#define ROMENTRY_ISEND(r) (ROMENTRY_GETTYPE(r) == ROMENTRYTYPE_END)
+#define ROMENTRY_ISRELOAD(r) (ROMENTRY_GETTYPE(r) == ROMENTRYTYPE_RELOAD)
+#define ROMENTRY_ISCONTINUE(r) (ROMENTRY_GETTYPE(r) == ROMENTRYTYPE_CONTINUE)
+#define ROMENTRY_ISFILL(r) (ROMENTRY_GETTYPE(r) == ROMENTRYTYPE_FILL)
+#define ROMENTRY_ISCOPY(r) (ROMENTRY_GETTYPE(r) == ROMENTRYTYPE_COPY)
+#define ROMENTRY_ISIGNORE(r) (ROMENTRY_GETTYPE(r) == ROMENTRYTYPE_IGNORE)
+#define ROMENTRY_ISSYSTEM_BIOS(r) (ROMENTRY_GETTYPE(r) == ROMENTRYTYPE_SYSTEM_BIOS)
+#define ROMENTRY_ISDEFAULT_BIOS(r) (ROMENTRY_GETTYPE(r) == ROMENTRYTYPE_DEFAULT_BIOS)
+#define ROMENTRY_ISREGIONEND(r) (ROMENTRY_ISREGION(r) || ROMENTRY_ISEND(r))
+
+/* ----- per-region macros ----- */
+#define ROMREGION_GETTAG(r) ((r)->_name)
+#define ROMREGION_GETLENGTH(r) ((r)->_length)
+#define ROMREGION_GETFLAGS(r) ((r)->_flags)
+#define ROMREGION_GETWIDTH(r) (8 << ((ROMREGION_GETFLAGS(r) & ROMREGION_WIDTHMASK) >> 8))
+#define ROMREGION_ISLITTLEENDIAN(r) ((ROMREGION_GETFLAGS(r) & ROMREGION_ENDIANMASK) == ROMREGION_LE)
+#define ROMREGION_ISBIGENDIAN(r) ((ROMREGION_GETFLAGS(r) & ROMREGION_ENDIANMASK) == ROMREGION_BE)
+#define ROMREGION_ISINVERTED(r) ((ROMREGION_GETFLAGS(r) & ROMREGION_INVERTMASK) == ROMREGION_INVERT)
+#define ROMREGION_ISERASE(r) ((ROMREGION_GETFLAGS(r) & ROMREGION_ERASEMASK) == ROMREGION_ERASE)
+#define ROMREGION_GETERASEVAL(r) ((ROMREGION_GETFLAGS(r) & ROMREGION_ERASEVALMASK) >> 16)
+#define ROMREGION_GETDATATYPE(r) (ROMREGION_GETFLAGS(r) & ROMREGION_DATATYPEMASK)
+#define ROMREGION_ISROMDATA(r) (ROMREGION_GETDATATYPE(r) == ROMREGION_DATATYPEROM)
+#define ROMREGION_ISDISKDATA(r) (ROMREGION_GETDATATYPE(r) == ROMREGION_DATATYPEDISK)
+
+
+/* ----- per-ROM macros ----- */
+#define ROM_GETNAME(r) ((r)->_name)
+#define ROM_SAFEGETNAME(r) (ROMENTRY_ISFILL(r) ? "fill" : ROMENTRY_ISCOPY(r) ? "copy" : ROM_GETNAME(r))
+#define ROM_GETOFFSET(r) ((r)->_offset)
+#define ROM_GETLENGTH(r) ((r)->_length)
+#define ROM_GETFLAGS(r) ((r)->_flags)
+#define ROM_GETHASHDATA(r) ((r)->_hashdata)
+#define ROM_ISOPTIONAL(r) ((ROM_GETFLAGS(r) & ROM_OPTIONALMASK) == ROM_OPTIONAL)
+#define ROM_GETGROUPSIZE(r) (((ROM_GETFLAGS(r) & ROM_GROUPMASK) >> 8) + 1)
+#define ROM_GETSKIPCOUNT(r) ((ROM_GETFLAGS(r) & ROM_SKIPMASK) >> 12)
+#define ROM_ISREVERSED(r) ((ROM_GETFLAGS(r) & ROM_REVERSEMASK) == ROM_REVERSE)
+#define ROM_GETBITWIDTH(r) (((ROM_GETFLAGS(r) & ROM_BITWIDTHMASK) >> 16) + 8 * ((ROM_GETFLAGS(r) & ROM_BITWIDTHMASK) == 0))
+#define ROM_GETBITSHIFT(r) ((ROM_GETFLAGS(r) & ROM_BITSHIFTMASK) >> 20)
+#define ROM_INHERITSFLAGS(r) ((ROM_GETFLAGS(r) & ROM_INHERITFLAGSMASK) == ROM_INHERITFLAGS)
+#define ROM_GETBIOSFLAGS(r) ((ROM_GETFLAGS(r) & ROM_BIOSFLAGSMASK) >> 24)
+
+
+/* ----- per-disk macros ----- */
+#define DISK_GETINDEX(r) ((r)->_offset)
+#define DISK_ISREADONLY(r) ((ROM_GETFLAGS(r) & DISK_READONLYMASK) == DISK_READONLY)
+#define DISK_ISOPTIONAL(r) ((ROM_GETFLAGS(r) & ROM_OPTIONALMASK) == ROM_OPTIONAL)
+
+
+/* ----- start/stop macros ----- */
+#define ROM_NAME(name) rom_##name
+#define ROM_START(name) static const rom_entry ROM_NAME(name)[] = {
+#define ROM_END { NULL, NULL, 0, 0, ROMENTRYTYPE_END } };
+
+
+/* ----- ROM region macros ----- */
+#define ROM_REGION(length,tag,flags) { tag, NULL, 0, length, ROMENTRYTYPE_REGION | (flags) },
+#define ROM_REGION16_LE(length,tag,flags) ROM_REGION(length, tag, (flags) | ROMREGION_16BIT | ROMREGION_LE)
+#define ROM_REGION16_BE(length,tag,flags) ROM_REGION(length, tag, (flags) | ROMREGION_16BIT | ROMREGION_BE)
+#define ROM_REGION32_LE(length,tag,flags) ROM_REGION(length, tag, (flags) | ROMREGION_32BIT | ROMREGION_LE)
+#define ROM_REGION32_BE(length,tag,flags) ROM_REGION(length, tag, (flags) | ROMREGION_32BIT | ROMREGION_BE)
+#define ROM_REGION64_LE(length,tag,flags) ROM_REGION(length, tag, (flags) | ROMREGION_64BIT | ROMREGION_LE)
+#define ROM_REGION64_BE(length,tag,flags) ROM_REGION(length, tag, (flags) | ROMREGION_64BIT | ROMREGION_BE)
+
+
+/* ----- core ROM loading macros ----- */
+#define ROMX_LOAD(name,offset,length,hash,flags) { name, hash, offset, length, ROMENTRYTYPE_ROM | (flags) },
+#define ROM_LOAD(name,offset,length,hash) ROMX_LOAD(name, offset, length, hash, 0)
+#define ROM_LOAD_OPTIONAL(name,offset,length,hash) ROMX_LOAD(name, offset, length, hash, ROM_OPTIONAL)
+
+
+/* ----- specialized loading macros ----- */
+#define ROM_LOAD_NIB_HIGH(name,offset,length,hash) ROMX_LOAD(name, offset, length, hash, ROM_NIBBLE | ROM_SHIFT_NIBBLE_HI)
+#define ROM_LOAD_NIB_LOW(name,offset,length,hash) ROMX_LOAD(name, offset, length, hash, ROM_NIBBLE | ROM_SHIFT_NIBBLE_LO)
+#define ROM_LOAD16_BYTE(name,offset,length,hash) ROMX_LOAD(name, offset, length, hash, ROM_SKIP(1))
+#define ROM_LOAD16_WORD(name,offset,length,hash) ROM_LOAD(name, offset, length, hash)
+#define ROM_LOAD16_WORD_SWAP(name,offset,length,hash) ROMX_LOAD(name, offset, length, hash, ROM_GROUPWORD | ROM_REVERSE)
+#define ROM_LOAD32_BYTE(name,offset,length,hash) ROMX_LOAD(name, offset, length, hash, ROM_SKIP(3))
+#define ROM_LOAD32_WORD(name,offset,length,hash) ROMX_LOAD(name, offset, length, hash, ROM_GROUPWORD | ROM_SKIP(2))
+#define ROM_LOAD32_WORD_SWAP(name,offset,length,hash) ROMX_LOAD(name, offset, length, hash, ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2))
+#define ROM_LOAD32_DWORD(name,offset,length,hash) ROMX_LOAD(name, offset, length, hash, ROM_GROUPDWORD)
+#define ROM_LOAD64_WORD(name,offset,length,hash) ROMX_LOAD(name, offset, length, hash, ROM_GROUPWORD | ROM_SKIP(6))
+#define ROM_LOAD64_WORD_SWAP(name,offset,length,hash) ROMX_LOAD(name, offset, length, hash, ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(6))
+
+
+/* ----- ROM_RELOAD related macros ----- */
+#define ROM_RELOAD(offset,length) { NULL, NULL, offset, length, ROMENTRYTYPE_RELOAD | ROM_INHERITFLAGS },
+#define ROM_RELOAD_PLAIN(offset,length) { NULL, NULL, offset, length, ROMENTRYTYPE_RELOAD },
+
+/* ----- additional ROM-related macros ----- */
+#define ROM_CONTINUE(offset,length) { NULL, NULL, offset, length, ROMENTRYTYPE_CONTINUE | ROM_INHERITFLAGS },
+#define ROM_IGNORE(length) { NULL, NULL, 0, length, ROMENTRYTYPE_IGNORE | ROM_INHERITFLAGS },
+#define ROM_FILL(offset,length,value) { NULL, (const char *)value, offset, length, ROMENTRYTYPE_FILL },
+#define ROM_COPY(srctag,srcoffs,offset,length) { srctag, (const char *)srcoffs, offset, length, ROMENTRYTYPE_COPY },
+
+
+/* ----- system BIOS macros ----- */
+#define ROM_SYSTEM_BIOS(value,name,description) { name, description, 0, 0, ROMENTRYTYPE_SYSTEM_BIOS | ROM_BIOS(value+1) },
+#define ROM_DEFAULT_BIOS(name) { name, NULL, 0, 0, ROMENTRYTYPE_DEFAULT_BIOS },
+
+
+/* ----- disk loading macros ----- */
+#define DISK_REGION(tag) ROM_REGION(1, tag, ROMREGION_DATATYPEDISK)
+#define DISK_IMAGE(name,idx,hash) ROMX_LOAD(name, idx, 0, hash, DISK_READWRITE)
+#define DISK_IMAGE_READONLY(name,idx,hash) ROMX_LOAD(name, idx, 0, hash, DISK_READONLY)
+#define DISK_IMAGE_READONLY_OPTIONAL(name,idx,hash) ROMX_LOAD(name, idx, 0, hash, DISK_READONLY | ROM_OPTIONAL)
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+
+/* ----- ROM processing ----- */
+
+/* load the ROMs and open the disk images associated with the given machine */
+void rom_init(running_machine &machine);
+
+/* return the number of warnings we generated */
+int rom_load_warnings(running_machine &machine);
+
+/* return the number of BAD_DUMP/NO_DUMP warnings we generated */
+int rom_load_knownbad(running_machine &machine);
+
+/* return id of selected bios */
+int rom_system_bios(running_machine &machine);
+
+/* return id of default bios */
+int rom_default_bios(running_machine &machine);
+
+/* ----- Helpers ----- */
+
+file_error common_process_file(emu_options &options, const char *location, const char *ext, const rom_entry *romp, emu_file **image_file);
+file_error common_process_file(emu_options &options, const char *location, bool has_crc, UINT32 crc, const rom_entry *romp, emu_file **image_file);
+
+
+/* ----- ROM iteration ----- */
+
+/* return pointer to first ROM source */
+const rom_source *rom_first_source(const machine_config &config);
+
+/* return pointer to next ROM source */
+const rom_source *rom_next_source(const rom_source &previous);
+
+/* return pointer to the first ROM region within a source */
+const rom_entry *rom_first_region(const rom_source &romp);
+
+/* return pointer to the next ROM region within a source */
+const rom_entry *rom_next_region(const rom_entry *romp);
+
+/* return pointer to the first ROM file within a region */
+const rom_entry *rom_first_file(const rom_entry *romp);
+
+/* return pointer to the next ROM file within a region */
+const rom_entry *rom_next_file(const rom_entry *romp);
+
+/* return TRUE if the given rom_source refers to the game driver itself */
+int rom_source_is_gamedrv(const game_driver *drv, const rom_source *source);
+
+/* return the expected size of a file given the ROM description */
+UINT32 rom_file_size(const rom_entry *romp);
+
+/* return the appropriate name for a rom region */
+astring &rom_region_name(astring &result, const game_driver *drv, const rom_source *source, const rom_entry *romp);
+
+
+
+/* ----- disk handling ----- */
+
+/* open a disk image, searching up the parent and loading by checksum */
+chd_error open_disk_image(emu_options &options, const game_driver *gamedrv, const rom_entry *romp, emu_file **image_file, chd_file **image_chd,const char *locationtag);
+
+/* return a pointer to the CHD file associated with the given region */
+chd_file *get_disk_handle(running_machine &machine, const char *region);
+
+/* set a pointer to the CHD file associated with the given region */
+void set_disk_handle(running_machine &machine, const char *region, emu_file &file, chd_file &chdfile);
+
+void load_software_part_region(device_t *device, char *swlist, char *swname, rom_entry *start_region);
+
+#endif /* __ROMLOAD_H__ */
diff --git a/trunk/src/emu/save.c b/trunk/src/emu/save.c
new file mode 100644
index 00000000000..32bc56f1d3a
--- /dev/null
+++ b/trunk/src/emu/save.c
@@ -0,0 +1,484 @@
+/***************************************************************************
+
+ save.c
+
+ Save state management 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.
+
+****************************************************************************
+
+ Save state file format:
+
+ 00..07 'MAMESAVE'
+ 08 Format version (this is format 2)
+ 09 Flags
+ 0A..1B Game name padded with \0
+ 1C..1F Signature
+ 20..end Save game data (compressed)
+
+ Data is always written as native-endian.
+ Data is converted from the endiannness it was written upon load.
+
+***************************************************************************/
+
+#include "emu.h"
+
+#include <zlib.h>
+
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+const int SAVE_VERSION = 2;
+const int HEADER_SIZE = 32;
+
+// Available flags
+enum
+{
+ SS_MSB_FIRST = 0x02
+};
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const char save_manager::s_magic_num[8] = { STATE_MAGIC_NUM };
+
+//**************************************************************************
+// INITIALIZATION
+//**************************************************************************
+
+//-------------------------------------------------
+// save_manager - constructor
+//-------------------------------------------------
+
+save_manager::save_manager(running_machine &machine)
+ : m_machine(machine),
+ m_reg_allowed(true),
+ m_illegal_regs(0),
+ m_entry_list(machine.respool()),
+ m_presave_list(machine.respool()),
+ m_postload_list(machine.respool())
+{
+}
+
+
+//-------------------------------------------------
+// allow_registration - allow/disallow
+// registrations to happen
+//-------------------------------------------------
+
+void save_manager::allow_registration(bool allowed)
+{
+ // allow/deny registration
+ m_reg_allowed = allowed;
+ if (!allowed)
+ dump_registry();
+}
+
+
+//-------------------------------------------------
+// indexed_item - return an item with the given
+// index
+//-------------------------------------------------
+
+const char *save_manager::indexed_item(int index, void *&base, UINT32 &valsize, UINT32 &valcount) const
+{
+ state_entry *entry = m_entry_list.find(index);
+ if (entry == NULL)
+ return NULL;
+
+ base = entry->m_data;
+ valsize = entry->m_typesize;
+ valcount = entry->m_typecount;
+
+ return entry->m_name;
+}
+
+
+//-------------------------------------------------
+// register_presave - register a pre-save
+// function callback
+//-------------------------------------------------
+
+void save_manager::register_presave(save_prepost_delegate func)
+{
+ // check for invalid timing
+ if (!m_reg_allowed)
+ fatalerror("Attempt to register callback function after state registration is closed!");
+
+ // scan for duplicates and push through to the end
+ for (state_callback *cb = m_presave_list.first(); cb != NULL; cb = cb->next())
+ if (cb->m_func == func)
+ fatalerror("Duplicate save state function (%s/%s)", cb->m_func.name(), func.name());
+
+ // allocate a new entry
+ m_presave_list.append(*auto_alloc(machine(), state_callback(func)));
+}
+
+
+//-------------------------------------------------
+// state_save_register_postload -
+// register a post-load function callback
+//-------------------------------------------------
+
+void save_manager::register_postload(save_prepost_delegate func)
+{
+ // check for invalid timing
+ if (!m_reg_allowed)
+ fatalerror("Attempt to register callback function after state registration is closed!");
+
+ // scan for duplicates and push through to the end
+ for (state_callback *cb = m_postload_list.first(); cb != NULL; cb = cb->next())
+ if (cb->m_func == func)
+ fatalerror("Duplicate save state function (%s/%s)", cb->m_func.name(), func.name());
+
+ // allocate a new entry
+ m_postload_list.append(*auto_alloc(machine(), state_callback(func)));
+}
+
+
+//-------------------------------------------------
+// save_memory - register an array of data in
+// memory
+//-------------------------------------------------
+
+void save_manager::save_memory(const char *module, const char *tag, UINT32 index, const char *name, void *val, UINT32 valsize, UINT32 valcount)
+{
+ assert(valsize == 1 || valsize == 2 || valsize == 4 || valsize == 8);
+
+ // check for invalid timing
+ if (!m_reg_allowed)
+ {
+ logerror("Attempt to register save state entry after state registration is closed!\nModule %s tag %s name %s\n", module, tag, name);
+ if (machine().system().flags & GAME_SUPPORTS_SAVE)
+ fatalerror("Attempt to register save state entry after state registration is closed!\nModule %s tag %s name %s\n", module, tag, name);
+ m_illegal_regs++;
+ return;
+ }
+
+ // create the full name
+ astring totalname;
+ if (tag != NULL)
+ totalname.printf("%s/%s/%X/%s", module, tag, index, name);
+ else
+ totalname.printf("%s/%X/%s", module, index, name);
+
+ // look for duplicates and an entry to insert in front of
+ state_entry *insert_after = NULL;
+ for (state_entry *entry = m_entry_list.first(); entry != NULL; entry = entry->next())
+ {
+ // stop when we find an entry whose name is after ours
+ if (entry->m_name > totalname)
+ break;
+ insert_after = entry;
+
+ // error if we are equal
+ if (entry->m_name == totalname)
+ fatalerror("Duplicate save state registration entry (%s)", totalname.cstr());
+ }
+
+ // insert us into the list
+ m_entry_list.insert_after(*auto_alloc(machine(), state_entry(val, totalname, valsize, valcount)), insert_after);
+}
+
+
+//-------------------------------------------------
+// check_file - check if a file is a valid save
+// state
+//-------------------------------------------------
+
+save_error save_manager::check_file(running_machine &machine, emu_file &file, const char *gamename, void (CLIB_DECL *errormsg)(const char *fmt, ...))
+{
+ // if we want to validate the signature, compute it
+ UINT32 sig = 0;
+ sig = machine.save().signature();
+
+ // seek to the beginning and read the header
+ file.compress(FCOMPRESS_NONE);
+ file.seek(0, SEEK_SET);
+ UINT8 header[HEADER_SIZE];
+ if (file.read(header, sizeof(header)) != sizeof(header))
+ {
+ if (errormsg != NULL)
+ (*errormsg)("Could not read " APPNAME " save file header");
+ return STATERR_READ_ERROR;
+ }
+
+ // let the generic header check work out the rest
+ return validate_header(header, gamename, sig, errormsg, "");
+}
+
+
+//-------------------------------------------------
+// read_file - read the data from a file
+//-------------------------------------------------
+
+save_error save_manager::read_file(emu_file &file)
+{
+ // if we have illegal registrations, return an error
+ if (m_illegal_regs > 0)
+ return STATERR_ILLEGAL_REGISTRATIONS;
+
+ // read the header and turn on compression for the rest of the file
+ file.compress(FCOMPRESS_NONE);
+ file.seek(0, SEEK_SET);
+ UINT8 header[HEADER_SIZE];
+ if (file.read(header, sizeof(header)) != sizeof(header))
+ return STATERR_READ_ERROR;
+ file.compress(FCOMPRESS_MEDIUM);
+
+ // verify the header and report an error if it doesn't match
+ UINT32 sig = signature();
+ if (validate_header(header, machine().system().name, sig, popmessage, "Error: ") != STATERR_NONE)
+ return STATERR_INVALID_HEADER;
+
+ // determine whether or not to flip the data when done
+ bool flip = NATIVE_ENDIAN_VALUE_LE_BE((header[9] & SS_MSB_FIRST) != 0, (header[9] & SS_MSB_FIRST) == 0);
+
+ // read all the data, flipping if necessary
+ for (state_entry *entry = m_entry_list.first(); entry != NULL; entry = entry->next())
+ {
+ UINT32 totalsize = entry->m_typesize * entry->m_typecount;
+ if (file.read(entry->m_data, totalsize) != totalsize)
+ return STATERR_READ_ERROR;
+
+ // handle flipping
+ if (flip)
+ entry->flip_data();
+ }
+
+ // call the post-load functions
+ for (state_callback *func = m_postload_list.first(); func != NULL; func = func->next())
+ func->m_func();
+
+ return STATERR_NONE;
+}
+
+
+//-------------------------------------------------
+// write_file - writes the data to a file
+//-------------------------------------------------
+
+save_error save_manager::write_file(emu_file &file)
+{
+ // if we have illegal registrations, return an error
+ if (m_illegal_regs > 0)
+ return STATERR_ILLEGAL_REGISTRATIONS;
+
+ // generate the header
+ UINT8 header[HEADER_SIZE];
+ memcpy(&header[0], s_magic_num, 8);
+ header[8] = SAVE_VERSION;
+ header[9] = NATIVE_ENDIAN_VALUE_LE_BE(0, SS_MSB_FIRST);
+ strncpy((char *)&header[0x0a], machine().system().name, 0x1c - 0x0a);
+ UINT32 sig = signature();
+ *(UINT32 *)&header[0x1c] = LITTLE_ENDIANIZE_INT32(sig);
+
+ // write the header and turn on compression for the rest of the file
+ file.compress(FCOMPRESS_NONE);
+ file.seek(0, SEEK_SET);
+ if (file.write(header, sizeof(header)) != sizeof(header))
+ return STATERR_WRITE_ERROR;
+ file.compress(FCOMPRESS_MEDIUM);
+
+ // call the pre-save functions
+ for (state_callback *func = m_presave_list.first(); func != NULL; func = func->next())
+ func->m_func();
+
+ // then write all the data
+ for (state_entry *entry = m_entry_list.first(); entry != NULL; entry = entry->next())
+ {
+ UINT32 totalsize = entry->m_typesize * entry->m_typecount;
+ if (file.write(entry->m_data, totalsize) != totalsize)
+ return STATERR_WRITE_ERROR;
+ }
+ return STATERR_NONE;
+}
+
+
+//-------------------------------------------------
+// signature - compute the signature, which
+// is a CRC over the structure of the data
+//-------------------------------------------------
+
+UINT32 save_manager::signature() const
+{
+ // iterate over entries
+ UINT32 crc = 0;
+ for (state_entry *entry = m_entry_list.first(); entry != NULL; entry = entry->next())
+ {
+ // add the entry name to the CRC
+ crc = crc32(crc, (UINT8 *)entry->m_name.cstr(), entry->m_name.len());
+
+ // add the type and size to the CRC
+ UINT32 temp[2];
+ temp[0] = LITTLE_ENDIANIZE_INT32(entry->m_typecount);
+ temp[1] = LITTLE_ENDIANIZE_INT32(entry->m_typesize);
+ crc = crc32(crc, (UINT8 *)&temp[0], sizeof(temp));
+ }
+ return crc;
+}
+
+
+//-------------------------------------------------
+// dump_registry - dump the registry to the
+// logfile
+//-------------------------------------------------
+
+void save_manager::dump_registry() const
+{
+ for (state_entry *entry = m_entry_list.first(); entry != NULL; entry = entry->next())
+ LOG(("%s: %d x %d\n", entry->m_name.cstr(), entry->m_typesize, entry->m_typecount));
+}
+
+
+//-------------------------------------------------
+// validate_header - validate the data in the
+// header
+//-------------------------------------------------
+
+save_error save_manager::validate_header(const UINT8 *header, const char *gamename, UINT32 signature,
+ void (CLIB_DECL *errormsg)(const char *fmt, ...), const char *error_prefix)
+{
+ // check magic number
+ if (memcmp(header, s_magic_num, 8))
+ {
+ if (errormsg != NULL)
+ (*errormsg)("%sThis is not a " APPNAME " save file", error_prefix);
+ return STATERR_INVALID_HEADER;
+ }
+
+ // check save state version
+ if (header[8] != SAVE_VERSION)
+ {
+ if (errormsg != NULL)
+ (*errormsg)("%sWrong version in save file (version %d, expected %d)", error_prefix, header[8], SAVE_VERSION);
+ return STATERR_INVALID_HEADER;
+ }
+
+ // check gamename, if we were asked to
+ if (gamename != NULL && strncmp(gamename, (const char *)&header[0x0a], 0x1c - 0x0a))
+ {
+ if (errormsg != NULL)
+ (*errormsg)("%s'File is not a valid savestate file for game '%s'.", error_prefix, gamename);
+ return STATERR_INVALID_HEADER;
+ }
+
+ // check signature, if we were asked to
+ if (signature != 0)
+ {
+ UINT32 rawsig = *(UINT32 *)&header[0x1c];
+ if (signature != LITTLE_ENDIANIZE_INT32(rawsig))
+ {
+ if (errormsg != NULL)
+ (*errormsg)("%sIncompatible save file (signature %08x, expected %08x)", error_prefix, LITTLE_ENDIANIZE_INT32(rawsig), signature);
+ return STATERR_INVALID_HEADER;
+ }
+ }
+ return STATERR_NONE;
+}
+
+
+//-------------------------------------------------
+// state_callback - constructor
+//-------------------------------------------------
+
+save_manager::state_callback::state_callback(save_prepost_delegate callback)
+ : m_next(NULL),
+ m_func(callback)
+{
+}
+
+
+//-------------------------------------------------
+// state_entry - constructor
+//-------------------------------------------------
+
+save_manager::state_entry::state_entry(void *data, const char *name, UINT8 size, UINT32 count)
+ : m_next(NULL),
+ m_data(data),
+ m_name(name),
+ m_typesize(size),
+ m_typecount(count),
+ m_offset(0)
+{
+}
+
+
+//-------------------------------------------------
+// flip_data - reverse the endianness of a
+// block of data
+//-------------------------------------------------
+
+void save_manager::state_entry::flip_data()
+{
+ UINT16 *data16;
+ UINT32 *data32;
+ UINT64 *data64;
+ int count;
+
+ switch (m_typesize)
+ {
+ case 2:
+ data16 = (UINT16 *)m_data;
+ for (count = 0; count < m_typecount; count++)
+ data16[count] = FLIPENDIAN_INT16(data16[count]);
+ break;
+
+ case 4:
+ data32 = (UINT32 *)m_data;
+ for (count = 0; count < m_typecount; count++)
+ data32[count] = FLIPENDIAN_INT32(data32[count]);
+ break;
+
+ case 8:
+ data64 = (UINT64 *)m_data;
+ for (count = 0; count < m_typecount; count++)
+ data64[count] = FLIPENDIAN_INT64(data64[count]);
+ break;
+ }
+}
diff --git a/trunk/src/emu/save.h b/trunk/src/emu/save.h
new file mode 100644
index 00000000000..4af38458080
--- /dev/null
+++ b/trunk/src/emu/save.h
@@ -0,0 +1,293 @@
+/***************************************************************************
+
+ save.h
+
+ Save state management 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 __EMU_H__
+#error Dont include this file directly; include emu.h instead.
+#endif
+
+#ifndef __SAVE_H__
+#define __SAVE_H__
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+enum save_error
+{
+ STATERR_NONE,
+ STATERR_ILLEGAL_REGISTRATIONS,
+ STATERR_INVALID_HEADER,
+ STATERR_READ_ERROR,
+ STATERR_WRITE_ERROR
+};
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+// callback delegate for presave/postload
+typedef delegate<void ()> save_prepost_delegate;
+
+
+// use this to declare a given type is a simple, non-pointer type that can be
+// saved; in general, this is intended only to be used for specific enum types
+// defined by your device
+#define ALLOW_SAVE_TYPE(TYPE) template<> struct save_manager::type_checker<TYPE> { static const bool is_atom = true; static const bool is_pointer = false; }
+
+
+
+// register items with explicit tags
+#define state_save_register_item(_mach, _mod, _tag, _index, _val) \
+ (_mach).save().save_item(_mod, _tag, _index, _val, #_val)
+
+#define state_save_register_item_pointer(_mach, _mod, _tag, _index, _val, _count) \
+ (_mach).save().save_pointer(_mod, _tag, _index, _val, #_val, _count)
+
+#define state_save_register_item_array(_mach, _mod, _tag, _index, _val) \
+ (_mach).save().save_item(_mod, _tag, _index, _val, #_val)
+
+#define state_save_register_item_2d_array(_mach, _mod, _tag, _index, _val) \
+ (_mach).save().save_item(_mod, _tag, _index, _val, #_val)
+
+#define state_save_register_item_bitmap(_mach, _mod, _tag, _index, _val) \
+ (_mach).save().save_item(_mod, _tag, _index, *(_val), #_val)
+
+
+
+// register global items
+#define state_save_register_global(_mach, _val) \
+ (_mach).save().save_item(_val, #_val)
+
+#define state_save_register_global_pointer(_mach, _val, _count) \
+ (_mach).save().save_pointer(_val, #_val, _count)
+
+#define state_save_register_global_array(_mach, _val) \
+ (_mach).save().save_item(_val, #_val)
+
+#define state_save_register_global_2d_array(_mach, _val) \
+ (_mach).save().save_item(_val, #_val)
+
+#define state_save_register_global_bitmap(_mach, _val) \
+ (_mach).save().save_item(*(_val), #_val)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class save_manager
+{
+ // type_checker is a set of templates to identify valid save types
+ template<typename _ItemType> struct type_checker { static const bool is_atom = false; static const bool is_pointer = false; };
+ template<typename _ItemType> struct type_checker<_ItemType*> { static const bool is_atom = false; static const bool is_pointer = true; };
+
+public:
+ // construction/destruction
+ save_manager(running_machine &machine);
+
+ // getters
+ running_machine &machine() const { return m_machine; }
+ int registration_count() const { return m_entry_list.count(); }
+ bool registration_allowed() const { return m_reg_allowed; }
+
+ // registration control
+ void allow_registration(bool allowed = true);
+ const char *indexed_item(int index, void *&base, UINT32 &valsize, UINT32 &valcount) const;
+
+ // function registration
+ void register_presave(save_prepost_delegate func);
+ void register_postload(save_prepost_delegate func);
+
+ // generic memory registration
+ void save_memory(const char *module, const char *tag, UINT32 index, const char *name, void *val, UINT32 valsize, UINT32 valcount = 1);
+
+ // templatized wrapper for general objects
+ template<typename _ItemType>
+ void save_item(const char *module, const char *tag, int index, _ItemType &value, const char *valname)
+ {
+ if (type_checker<_ItemType>::is_pointer) throw emu_fatalerror("Called save_item on a pointer with no count!");
+ if (!type_checker<_ItemType>::is_atom) throw emu_fatalerror("Called save_item on a non-fundamental type!");
+ save_memory(module, tag, index, valname, &value, sizeof(value));
+ }
+
+ // templatized wrapper for 1-dimensional arrays
+ template<typename _ItemType, std::size_t N>
+ void save_item(const char *module, const char *tag, int index, _ItemType (&value)[N], const char *valname)
+ {
+ if (!type_checker<_ItemType>::is_atom) throw emu_fatalerror("Called save_item on a non-fundamental type!");
+ save_memory(module, tag, index, valname, &value[0], sizeof(value[0]), N);
+ }
+
+ // templatized wrapper for 2-dimensional arrays
+ template<typename _ItemType, std::size_t M, std::size_t N>
+ void save_item(const char *module, const char *tag, int index, _ItemType (&value)[M][N], const char *valname)
+ {
+ if (!type_checker<_ItemType>::is_atom) throw emu_fatalerror("Called save_item on a non-fundamental type!");
+ save_memory(module, tag, index, valname, &value[0][0], sizeof(value[0][0]), M * N);
+ }
+
+ // templatized wrapper for pointers
+ template<typename _ItemType>
+ void save_pointer(const char *module, const char *tag, int index, _ItemType *value, const char *valname, UINT32 count)
+ {
+ if (!type_checker<_ItemType>::is_atom) throw emu_fatalerror("Called save_item on a non-fundamental type!");
+ save_memory(module, tag, index, valname, value, sizeof(*value), count);
+ }
+
+ // global memory registration
+ template<typename _ItemType>
+ void save_item(_ItemType &value, const char *valname, int index = 0) { save_item("global", NULL, index, value, valname); }
+ template<typename _ItemType>
+ void save_pointer(_ItemType *value, const char *valname, UINT32 count, int index = 0) { save_pointer("global", NULL, index, value, valname, count); }
+
+ // file processing
+ static save_error check_file(running_machine &machine, emu_file &file, const char *gamename, void (CLIB_DECL *errormsg)(const char *fmt, ...));
+ save_error write_file(emu_file &file);
+ save_error read_file(emu_file &file);
+
+private:
+ // internal helpers
+ UINT32 signature() const;
+ void dump_registry() const;
+ static save_error validate_header(const UINT8 *header, const char *gamename, UINT32 signature, void (CLIB_DECL *errormsg)(const char *fmt, ...), const char *error_prefix);
+
+ // state callback item
+ class state_callback
+ {
+ public:
+ // construction/destruction
+ state_callback(save_prepost_delegate callback);
+
+ // getters
+ state_callback *next() const { return m_next; }
+
+ // state
+ state_callback * m_next; // pointer to next entry
+ save_prepost_delegate m_func; // delegate
+ };
+
+ class state_entry
+ {
+ public:
+ // construction/destruction
+ state_entry(void *data, const char *name, UINT8 size, UINT32 count);
+
+ // getters
+ state_entry *next() const { return m_next; }
+
+ // helpers
+ void flip_data();
+
+ // state
+ state_entry * m_next; // pointer to next entry
+ void * m_data; // pointer to the memory to save/restore
+ astring m_name; // full name
+ UINT8 m_typesize; // size of the raw data type
+ UINT32 m_typecount; // number of items
+ UINT32 m_offset; // offset within the final structure
+ };
+
+ // internal state
+ running_machine & m_machine; // reference to our machine
+ bool m_reg_allowed; // are registrations allowed?
+ int m_illegal_regs; // number of illegal registrations
+
+ simple_list<state_entry> m_entry_list; // list of reigstered entries
+ simple_list<state_callback> m_presave_list; // list of pre-save functions
+ simple_list<state_callback> m_postload_list; // list of post-load functions
+
+ static const char s_magic_num[8]; // magic number for header
+};
+
+
+// template specializations to enumerate the fundamental atomic types you are allowed to save
+ALLOW_SAVE_TYPE(bool);
+ALLOW_SAVE_TYPE(INT8);
+ALLOW_SAVE_TYPE(UINT8);
+ALLOW_SAVE_TYPE(INT16);
+ALLOW_SAVE_TYPE(UINT16);
+ALLOW_SAVE_TYPE(INT32);
+ALLOW_SAVE_TYPE(UINT32);
+ALLOW_SAVE_TYPE(INT64);
+ALLOW_SAVE_TYPE(UINT64);
+ALLOW_SAVE_TYPE(PAIR);
+ALLOW_SAVE_TYPE(PAIR64);
+ALLOW_SAVE_TYPE(float);
+ALLOW_SAVE_TYPE(double);
+ALLOW_SAVE_TYPE(endianness_t);
+
+
+
+//**************************************************************************
+// INLINE FUNCTIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// save_item - specialized save_item for bitmaps
+//-------------------------------------------------
+
+template<>
+inline void save_manager::save_item(const char *module, const char *tag, int index, bitmap_t &value, const char *name)
+{
+ save_memory(module, tag, index, name, value.base, value.bpp / 8, value.rowpixels * value.height);
+}
+
+
+//-------------------------------------------------
+// save_item - specialized save_item for attotimes
+//-------------------------------------------------
+
+template<>
+inline void save_manager::save_item(const char *module, const char *tag, int index, attotime &value, const char *name)
+{
+ astring tempstr(name, ".attoseconds");
+ save_memory(module, tag, index, tempstr, &value.attoseconds, sizeof(value.attoseconds));
+ tempstr.cpy(name).cat(".seconds");
+ save_memory(module, tag, index, tempstr, &value.seconds, sizeof(value.seconds));
+}
+
+
+#endif /* __SAVE_H__ */
diff --git a/trunk/src/emu/schedule.c b/trunk/src/emu/schedule.c
new file mode 100644
index 00000000000..b8ce9f74a85
--- /dev/null
+++ b/trunk/src/emu/schedule.c
@@ -0,0 +1,991 @@
+/***************************************************************************
+
+ schedule.c
+
+ Core device execution and scheduling engine.
+
+****************************************************************************
+
+ 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 "profiler.h"
+#include "debugger.h"
+
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// internal trigger IDs
+enum
+{
+ TRIGGER_INT = -2000,
+ TRIGGER_YIELDTIME = -3000,
+ TRIGGER_SUSPENDTIME = -4000
+};
+
+
+
+//**************************************************************************
+// EMU TIMER
+//**************************************************************************
+
+//-------------------------------------------------
+// emu_timer - constructor
+//-------------------------------------------------
+
+emu_timer::emu_timer()
+ : m_machine(NULL),
+ m_next(NULL),
+ m_prev(NULL),
+ m_param(0),
+ m_ptr(NULL),
+ m_enabled(false),
+ m_temporary(false),
+ m_period(attotime::zero),
+ m_start(attotime::zero),
+ m_expire(attotime::never),
+ m_device(NULL),
+ m_id(0)
+{
+}
+
+
+//-------------------------------------------------
+// ~emu_timer - destructor
+//-------------------------------------------------
+
+emu_timer::~emu_timer()
+{
+}
+
+
+//-------------------------------------------------
+// init - completely initialize the state when
+// re-allocated as a non-device timer
+//-------------------------------------------------
+
+emu_timer &emu_timer::init(running_machine &machine, timer_expired_delegate callback, void *ptr, bool temporary)
+{
+ // ensure the entire timer state is clean
+ m_machine = &machine;
+ m_next = NULL;
+ m_prev = NULL;
+ m_callback = callback;
+ m_param = 0;
+ m_ptr = ptr;
+ m_enabled = false;
+ m_temporary = temporary;
+ m_period = attotime::never;
+ m_start = machine.time();
+ m_expire = attotime::never;
+ m_device = NULL;
+ m_id = 0;
+
+ // if we're not temporary, register ourselves with the save state system
+ if (!m_temporary)
+ register_save();
+
+ // insert into the list
+ machine.scheduler().timer_list_insert(*this);
+ return *this;
+}
+
+
+//-------------------------------------------------
+// init - completely initialize the state when
+// re-allocated as a device timer
+//-------------------------------------------------
+
+emu_timer &emu_timer::init(device_t &device, device_timer_id id, void *ptr, bool temporary)
+{
+ // ensure the entire timer state is clean
+ m_machine = &device.machine();
+ m_next = NULL;
+ m_prev = NULL;
+ m_callback = timer_expired_delegate();
+ m_param = 0;
+ m_ptr = ptr;
+ m_enabled = false;
+ m_temporary = temporary;
+ m_period = attotime::never;
+ m_start = machine().time();
+ m_expire = attotime::never;
+ m_device = &device;
+ m_id = id;
+
+ // if we're not temporary, register ourselves with the save state system
+ if (!m_temporary)
+ register_save();
+
+ // insert into the list
+ machine().scheduler().timer_list_insert(*this);
+ return *this;
+}
+
+
+//-------------------------------------------------
+// release - release us from the global list
+// management when deallocating
+//-------------------------------------------------
+
+emu_timer &emu_timer::release()
+{
+ // unhook us from the global list
+ machine().scheduler().timer_list_remove(*this);
+ return *this;
+}
+
+
+//-------------------------------------------------
+// enable - enable/disable a timer
+//-------------------------------------------------
+
+bool emu_timer::enable(bool enable)
+{
+ // reschedule only if the state has changed
+ bool old = m_enabled;
+ if (old != enable)
+ {
+ // set the enable flag
+ m_enabled = enable;
+
+ // remove the timer and insert back into the list
+ machine().scheduler().timer_list_remove(*this);
+ machine().scheduler().timer_list_insert(*this);
+ }
+ return old;
+}
+
+
+//-------------------------------------------------
+// adjust - adjust the time when this timer will
+// fire and specify a period for subsequent
+// firings
+//-------------------------------------------------
+
+void emu_timer::adjust(attotime start_delay, INT32 param, attotime period)
+{
+ // if this is the callback timer, mark it modified
+ device_scheduler &scheduler = machine().scheduler();
+ if (scheduler.m_callback_timer == this)
+ scheduler.m_callback_timer_modified = true;
+
+ // compute the time of the next firing and insert into the list
+ m_param = param;
+ m_enabled = true;
+
+ // clamp negative times to 0
+ if (start_delay.seconds < 0)
+ start_delay = attotime::zero;
+
+ // set the start and expire times
+ m_start = scheduler.time();
+ m_expire = m_start + start_delay;
+ m_period = period;
+
+ // remove and re-insert the timer in its new order
+ scheduler.timer_list_remove(*this);
+ scheduler.timer_list_insert(*this);
+
+ // if this was inserted as the head, abort the current timeslice and resync
+ if (this == scheduler.first_timer())
+ scheduler.abort_timeslice();
+}
+
+
+//-------------------------------------------------
+// elapsed - return the amount of time since the
+// timer was started
+//-------------------------------------------------
+
+attotime emu_timer::elapsed() const
+{
+ return machine().time() - m_start;
+}
+
+
+//-------------------------------------------------
+// remaining - return the amount of time
+// remaining until the timer expires
+//-------------------------------------------------
+
+attotime emu_timer::remaining() const
+{
+ return m_expire - machine().time();
+}
+
+
+//-------------------------------------------------
+// register_save - register ourself with the save
+// state system
+//-------------------------------------------------
+
+void emu_timer::register_save()
+{
+ // determine our instance number and name
+ int index = 0;
+ astring name;
+
+ // for non-device timers, it is an index based on the callback function name
+ if (m_device == NULL)
+ {
+ name = m_callback.name();
+ for (emu_timer *curtimer = machine().scheduler().first_timer(); curtimer != NULL; curtimer = curtimer->next())
+ if (!curtimer->m_temporary && curtimer->m_device == NULL && strcmp(curtimer->m_callback.name(), m_callback.name()) == 0)
+ index++;
+ }
+
+ // for device timers, it is an index based on the device and timer ID
+ else
+ {
+ name.printf("%s/%d", m_device->tag(), m_id);
+ for (emu_timer *curtimer = machine().scheduler().first_timer(); curtimer != NULL; curtimer = curtimer->next())
+ if (!curtimer->m_temporary && curtimer->m_device != NULL && curtimer->m_device == m_device && curtimer->m_id == m_id)
+ index++;
+ }
+
+ // save the bits
+ machine().save().save_item("timer", name, index, NAME(m_param));
+ machine().save().save_item("timer", name, index, NAME(m_enabled));
+ machine().save().save_item("timer", name, index, NAME(m_period));
+ machine().save().save_item("timer", name, index, NAME(m_start));
+ machine().save().save_item("timer", name, index, NAME(m_expire));
+}
+
+
+//-------------------------------------------------
+// schedule_next_period - schedule the next
+// period
+//-------------------------------------------------
+
+void emu_timer::schedule_next_period()
+{
+ // advance by one period
+ m_start = m_expire;
+ m_expire += m_period;
+
+ // remove and re-insert us
+ device_scheduler &scheduler = machine().scheduler();
+ scheduler.timer_list_remove(*this);
+ scheduler.timer_list_insert(*this);
+}
+
+
+//-------------------------------------------------
+// dump - dump internal state to a single output
+// line in the error log
+//-------------------------------------------------
+
+void emu_timer::dump() const
+{
+ logerror("%p: en=%d temp=%d exp=%15s start=%15s per=%15s param=%d ptr=%p", this, m_enabled, m_temporary, m_expire.as_string(), m_start.as_string(), m_period.as_string(), m_param, m_ptr);
+ if (m_device == NULL)
+ logerror(" cb=%s\n", m_callback.name());
+ else
+ logerror(" dev=%s id=%d\n", m_device->tag(), m_id);
+}
+
+
+
+//**************************************************************************
+// DEVICE SCHEDULER
+//**************************************************************************
+
+//-------------------------------------------------
+// device_scheduler - constructor
+//-------------------------------------------------
+
+device_scheduler::device_scheduler(running_machine &machine) :
+ m_machine(machine),
+ m_executing_device(NULL),
+ m_execute_list(NULL),
+ m_basetime(attotime::zero),
+ m_cothread(co_active()),
+ m_timer_list(NULL),
+ m_timer_allocator(machine.respool()),
+ m_callback_timer(NULL),
+ m_callback_timer_modified(false),
+ m_callback_timer_expire_time(attotime::zero),
+ m_quantum_list(machine.respool()),
+ m_quantum_allocator(machine.respool()),
+ m_quantum_minimum(ATTOSECONDS_IN_NSEC(1) / 1000)
+{
+ // append a single never-expiring timer so there is always one in the list
+ m_timer_list = &m_timer_allocator.alloc()->init(machine, timer_expired_delegate(), NULL, true);
+ m_timer_list->adjust(attotime::never);
+
+ // register global states
+ machine.save().save_item(NAME(m_basetime));
+ machine.save().register_presave(save_prepost_delegate(FUNC(device_scheduler::presave), this));
+ machine.save().register_postload(save_prepost_delegate(FUNC(device_scheduler::postload), this));
+}
+
+
+//-------------------------------------------------
+// device_scheduler - destructor
+//-------------------------------------------------
+
+device_scheduler::~device_scheduler()
+{
+ // remove all timers
+ while (m_timer_list != NULL)
+ m_timer_allocator.reclaim(m_timer_list->release());
+}
+
+
+//-------------------------------------------------
+// time - return the current time
+//-------------------------------------------------
+
+attotime device_scheduler::time() const
+{
+ // if we're currently in a callback, use the timer's expiration time as a base
+ if (m_callback_timer != NULL)
+ return m_callback_timer_expire_time;
+
+ // if we're executing as a particular CPU, use its local time as a base
+ // otherwise, return the global base time
+ return (m_executing_device != NULL) ? m_executing_device->local_time() : m_basetime;
+}
+
+
+//-------------------------------------------------
+// can_save - return true if it's safe to save
+// (i.e., no temporary timers outstanding)
+//-------------------------------------------------
+
+bool device_scheduler::can_save() const
+{
+ // if any live temporary timers exit, fail
+ for (emu_timer *timer = m_timer_list; timer != NULL; timer = timer->next())
+ if (timer->m_temporary && timer->expire() != attotime::never)
+ {
+ logerror("Failed save state attempt due to anonymous timers:\n");
+ dump_timers();
+ return false;
+ }
+
+ // otherwise, we're good
+ return true;
+}
+
+
+//-------------------------------------------------
+// timeslice - execute all devices for a single
+// timeslice
+//-------------------------------------------------
+
+void device_scheduler::timeslice()
+{
+ bool call_debugger = ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0);
+
+ // build the execution list if we don't have one yet
+ if (m_execute_list == NULL)
+ rebuild_execute_list();
+
+ // execute timers
+ execute_timers();
+
+ // loop until we hit the next timer
+ while (m_basetime < m_timer_list->m_expire)
+ {
+ // by default, assume our target is the end of the next quantum
+ attotime target = m_basetime + attotime(0, m_quantum_list.first()->m_actual);
+
+ // however, if the next timer is going to fire before then, override
+ if (m_timer_list->m_expire < target)
+ target = m_timer_list->m_expire;
+
+ LOG(("------------------\n"));
+ LOG(("cpu_timeslice: target = %s\n", target.as_string()));
+
+ // apply pending suspension changes
+ UINT32 suspendchanged = 0;
+ for (device_execute_interface *exec = m_execute_list; exec != NULL; exec = exec->m_nextexec)
+ {
+ suspendchanged |= exec->m_suspend ^ exec->m_nextsuspend;
+ exec->m_suspend = exec->m_nextsuspend;
+ exec->m_nextsuspend &= ~SUSPEND_REASON_TIMESLICE;
+ exec->m_eatcycles = exec->m_nexteatcycles;
+ }
+
+ // recompute the execute list if any CPUs changed their suspension state
+ if (suspendchanged != 0)
+ rebuild_execute_list();
+
+ // loop over non-suspended CPUs
+ for (device_execute_interface *exec = m_execute_list; exec != NULL; exec = exec->m_nextexec)
+ {
+ // only process if our target is later than the CPU's current time (coarse check)
+ if (target.seconds >= exec->m_localtime.seconds)
+ {
+ // compute how many attoseconds to execute this CPU
+ attoseconds_t delta = target.attoseconds - exec->m_localtime.attoseconds;
+ if (delta < 0 && target.seconds > exec->m_localtime.seconds)
+ delta += ATTOSECONDS_PER_SECOND;
+ assert(delta == (target - exec->m_localtime).as_attoseconds());
+
+ // if we have enough for at least 1 cycle, do the math
+ if (delta >= exec->m_attoseconds_per_cycle)
+ {
+ // compute how many cycles we want to execute
+ int ran = exec->m_cycles_running = divu_64x32((UINT64)delta >> exec->m_divshift, exec->m_divisor);
+ LOG((" cpu '%s': %d cycles\n", exec->device().tag(), exec->m_cycles_running));
+
+ // if we're not suspended, actually execute
+ if (exec->m_suspend == 0)
+ {
+ g_profiler.start(exec->m_profiler);
+
+ // note that this global variable cycles_stolen can be modified
+ // via the call to cpu_execute
+ exec->m_cycles_stolen = 0;
+ m_executing_device = exec;
+ *exec->m_icountptr = exec->m_cycles_running;
+ if (!call_debugger)
+ exec->run();
+ else
+ {
+ debugger_start_cpu_hook(&exec->device(), target);
+ exec->run();
+ debugger_stop_cpu_hook(&exec->device());
+ }
+
+ // adjust for any cycles we took back
+ assert(ran >= *exec->m_icountptr);
+ ran -= *exec->m_icountptr;
+ assert(ran >= exec->m_cycles_stolen);
+ ran -= exec->m_cycles_stolen;
+ g_profiler.stop();
+ }
+
+ // account for these cycles
+ exec->m_totalcycles += ran;
+
+ // update the local time for this CPU
+ exec->m_localtime += attotime(0, exec->m_attoseconds_per_cycle * ran);
+ LOG((" %d ran, %d total, time = %s\n", ran, (INT32)exec->m_totalcycles, exec->m_localtime.as_string()));
+
+ // if the new local CPU time is less than our target, move the target up, but not before the base
+ if (exec->m_localtime < target)
+ {
+ assert(exec->m_localtime < target);
+ target = max(exec->m_localtime, m_basetime);
+ LOG((" (new target)\n"));
+ }
+ }
+ }
+ }
+ m_executing_device = NULL;
+
+ // update the base time
+ m_basetime = target;
+ }
+}
+
+
+//-------------------------------------------------
+// abort_timeslice - abort execution for the
+// current timeslice
+//-------------------------------------------------
+
+void device_scheduler::abort_timeslice()
+{
+ if (m_executing_device != NULL)
+ m_executing_device->abort_timeslice();
+}
+
+
+//-------------------------------------------------
+// trigger - generate a global trigger
+//-------------------------------------------------
+
+void device_scheduler::trigger(int trigid, attotime after)
+{
+ // ensure we have a list of executing devices
+ if (m_execute_list == NULL)
+ rebuild_execute_list();
+
+ // if we have a non-zero time, schedule a timer
+ if (after != attotime::zero)
+ timer_set(after, timer_expired_delegate(FUNC(device_scheduler::timed_trigger), this), trigid);
+
+ // send the trigger to everyone who cares
+ else
+ for (device_execute_interface *exec = m_execute_list; exec != NULL; exec = exec->m_nextexec)
+ exec->trigger(trigid);
+}
+
+
+//-------------------------------------------------
+// boost_interleave - temporarily boosts the
+// interleave factor
+//-------------------------------------------------
+
+void device_scheduler::boost_interleave(attotime timeslice_time, attotime boost_duration)
+{
+ // ignore timeslices > 1 second
+ if (timeslice_time.seconds > 0)
+ return;
+ add_scheduling_quantum(timeslice_time, boost_duration);
+}
+
+
+//-------------------------------------------------
+// timer_alloc - allocate a global non-device
+// timer and return a pointer
+//-------------------------------------------------
+
+emu_timer *device_scheduler::timer_alloc(timer_expired_delegate callback, void *ptr)
+{
+ return &m_timer_allocator.alloc()->init(machine(), callback, ptr, false);
+}
+
+
+//-------------------------------------------------
+// timer_set - allocate an anonymous non-device
+// timer and set it to go off after the given
+// amount of time
+//-------------------------------------------------
+
+void device_scheduler::timer_set(attotime duration, timer_expired_delegate callback, int param, void *ptr)
+{
+ m_timer_allocator.alloc()->init(machine(), callback, ptr, true).adjust(duration, param);
+}
+
+
+//-------------------------------------------------
+// timer_pulse - allocate an anonymous non-device
+// timer and set it to go off at the given
+// frequency
+//-------------------------------------------------
+
+void device_scheduler::timer_pulse(attotime period, timer_expired_delegate callback, int param, void *ptr)
+{
+ m_timer_allocator.alloc()->init(machine(), callback, ptr, false).adjust(period, param, period);
+}
+
+
+//-------------------------------------------------
+// timer_alloc - allocate a global device timer
+// and return a pointer
+//-------------------------------------------------
+
+emu_timer *device_scheduler::timer_alloc(device_t &device, device_timer_id id, void *ptr)
+{
+ return &m_timer_allocator.alloc()->init(device, id, ptr, false);
+}
+
+
+//-------------------------------------------------
+// timer_set - allocate an anonymous device timer
+// and set it to go off after the given amount of
+// time
+//-------------------------------------------------
+
+void device_scheduler::timer_set(attotime duration, device_t &device, device_timer_id id, int param, void *ptr)
+{
+ m_timer_allocator.alloc()->init(device, id, ptr, true).adjust(duration, param);
+}
+
+
+//-------------------------------------------------
+// eat_all_cycles - eat a ton of cycles on all
+// CPUs to force a quick exit
+//-------------------------------------------------
+
+void device_scheduler::eat_all_cycles()
+{
+ for (device_execute_interface *exec = m_execute_list; exec != NULL; exec = exec->m_nextexec)
+ exec->eat_cycles(1000000000);
+}
+
+
+//-------------------------------------------------
+// timed_trigger - generate a trigger after a
+// given amount of time
+//-------------------------------------------------
+
+void device_scheduler::timed_trigger(void *ptr, INT32 param)
+{
+ trigger(param);
+}
+
+
+//-------------------------------------------------
+// presave - before creating a save state
+//-------------------------------------------------
+
+void device_scheduler::presave()
+{
+ // report the timer state after a log
+ logerror("Prior to saving state:\n");
+ dump_timers();
+}
+
+
+//-------------------------------------------------
+// postload - after loading a save state
+//-------------------------------------------------
+
+void device_scheduler::postload()
+{
+ // remove all timers and make a private list of permanent ones
+ simple_list<emu_timer> private_list;
+ while (m_timer_list != NULL)
+ {
+ emu_timer &timer = *m_timer_list;
+
+ // temporary timers go away entirely (except our special never-expiring one)
+ if (timer.m_temporary && timer.expire() != attotime::never)
+ m_timer_allocator.reclaim(timer.release());
+
+ // permanent ones get added to our private list
+ else
+ private_list.append(timer_list_remove(timer));
+ }
+
+ // now re-insert them; this effectively re-sorts them by time
+ emu_timer *timer;
+ while ((timer = private_list.detach_head()) != NULL)
+ timer_list_insert(*timer);
+
+ // report the timer state after a log
+ logerror("After resetting/reordering timers:\n");
+ dump_timers();
+}
+
+
+//-------------------------------------------------
+// compute_perfect_interleave - compute the
+// "perfect" interleave interval
+//-------------------------------------------------
+
+void device_scheduler::compute_perfect_interleave()
+{
+ // ensure we have a list of executing devices
+ if (m_execute_list == NULL)
+ rebuild_execute_list();
+
+ // start with the first one
+ device_execute_interface *first = m_execute_list;
+ if (first != NULL)
+ {
+ // start with a huge time factor and find the 2nd smallest cycle time
+ attoseconds_t smallest = first->minimum_quantum();
+ attoseconds_t perfect = ATTOSECONDS_PER_SECOND - 1;
+ for (device_execute_interface *exec = first->m_nextexec; exec != NULL; exec = exec->m_nextexec)
+ {
+ // find the 2nd smallest cycle interval
+ attoseconds_t curquantum = exec->minimum_quantum();
+ if (curquantum < smallest)
+ {
+ perfect = smallest;
+ smallest = curquantum;
+ }
+ else if (curquantum < perfect)
+ perfect = curquantum;
+ }
+
+ // if this is a new minimum quantum, apply it
+ if (m_quantum_minimum != perfect)
+ {
+ // adjust all the actuals; this doesn't affect the current
+ m_quantum_minimum = perfect;
+ for (quantum_slot *quant = m_quantum_list.first(); quant != NULL; quant = quant->next())
+ quant->m_actual = MAX(quant->m_requested, m_quantum_minimum);
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// rebuild_execute_list - rebuild the list of
+// executing CPUs, moving suspended CPUs to the
+// end
+//-------------------------------------------------
+
+void device_scheduler::rebuild_execute_list()
+{
+ // if we haven't yet set a scheduling quantum, do it now
+ if (m_quantum_list.first() == NULL)
+ {
+ // set the core scheduling quantum
+ attotime min_quantum = machine().config().m_minimum_quantum;
+
+ // if none specified default to 60Hz
+ if (min_quantum == attotime::zero)
+ min_quantum = attotime::from_hz(60);
+
+ // if the configuration specifies a device to make perfect, pick that as the minimum
+ if (machine().config().m_perfect_cpu_quantum != NULL)
+ {
+ device_t *device = machine().device(machine().config().m_perfect_cpu_quantum);
+ if (device == NULL)
+ fatalerror("Device '%s' specified for perfect interleave is not present!", machine().config().m_perfect_cpu_quantum);
+
+ device_execute_interface *exec;
+ if (!device->interface(exec))
+ fatalerror("Device '%s' specified for perfect interleave is not an executing device!", machine().config().m_perfect_cpu_quantum);
+
+ min_quantum = min(attotime(0, exec->minimum_quantum()), min_quantum);
+ }
+
+ // make sure it's no higher than 60Hz
+ min_quantum = min(min_quantum, attotime::from_hz(60));
+
+ // inform the timer system of our decision
+ add_scheduling_quantum(min_quantum, attotime::never);
+ }
+
+ // start with an empty list
+ device_execute_interface **active_tailptr = &m_execute_list;
+ *active_tailptr = NULL;
+
+ // also make an empty list of suspended devices
+ device_execute_interface *suspend_list = NULL;
+ device_execute_interface **suspend_tailptr = &suspend_list;
+
+ // iterate over all devices
+ device_execute_interface *exec = NULL;
+ for (bool gotone = machine().devicelist().first(exec); gotone; gotone = exec->next(exec))
+ {
+ // append to the appropriate list
+ exec->m_nextexec = NULL;
+ if (exec->m_suspend == 0)
+ {
+ *active_tailptr = exec;
+ active_tailptr = &exec->m_nextexec;
+ }
+ else
+ {
+ *suspend_tailptr = exec;
+ suspend_tailptr = &exec->m_nextexec;
+ }
+ }
+
+ // append the suspend list to the end of the active list
+ *active_tailptr = suspend_list;
+}
+
+
+//-------------------------------------------------
+// timer_list_insert - insert a new timer into
+// the list at the appropriate location
+//-------------------------------------------------
+
+emu_timer &device_scheduler::timer_list_insert(emu_timer &timer)
+{
+ // disabled timers sort to the end
+ attotime expire = timer.m_enabled ? timer.m_expire : attotime::never;
+
+ // loop over the timer list
+ emu_timer *prevtimer = NULL;
+ for (emu_timer *curtimer = m_timer_list; curtimer != NULL; prevtimer = curtimer, curtimer = curtimer->next())
+ {
+ // if the current list entry expires after us, we should be inserted before it
+ if (curtimer->m_expire > expire)
+ {
+ // link the new guy in before the current list entry
+ timer.m_prev = curtimer->m_prev;
+ timer.m_next = curtimer;
+
+ if (curtimer->m_prev != NULL)
+ curtimer->m_prev->m_next = &timer;
+ else
+ m_timer_list = &timer;
+
+ curtimer->m_prev = &timer;
+ return timer;
+ }
+ }
+
+ // need to insert after the last one
+ if (prevtimer != NULL)
+ prevtimer->m_next = &timer;
+ else
+ m_timer_list = &timer;
+
+ timer.m_prev = prevtimer;
+ timer.m_next = NULL;
+ return timer;
+}
+
+
+//-------------------------------------------------
+// timer_list_remove - remove a timer from the
+// linked list
+//-------------------------------------------------
+
+emu_timer &device_scheduler::timer_list_remove(emu_timer &timer)
+{
+ // remove it from the list
+ if (timer.m_prev != NULL)
+ timer.m_prev->m_next = timer.m_next;
+ else
+ m_timer_list = timer.m_next;
+
+ if (timer.m_next != NULL)
+ timer.m_next->m_prev = timer.m_prev;
+
+ return timer;
+}
+
+
+//-------------------------------------------------
+// execute_timers - execute timers and update
+// scheduling quanta
+//-------------------------------------------------
+
+void device_scheduler::execute_timers()
+{
+ // if the current quantum has expired, find a new one
+ while (m_basetime >= m_quantum_list.first()->m_expire)
+ m_quantum_allocator.reclaim(m_quantum_list.detach_head());
+
+ LOG(("timer_set_global_time: new=%s head->expire=%s\n", m_basetime.as_string(), m_timer_list->m_expire.as_string()));
+
+ // now process any timers that are overdue
+ while (m_timer_list->m_expire <= m_basetime)
+ {
+ // if this is a one-shot timer, disable it now
+ emu_timer &timer = *m_timer_list;
+ bool was_enabled = timer.m_enabled;
+ if (timer.m_period == attotime::zero || timer.m_period == attotime::never)
+ timer.m_enabled = false;
+
+ // set the global state of which callback we're in
+ m_callback_timer_modified = false;
+ m_callback_timer = &timer;
+ m_callback_timer_expire_time = timer.m_expire;
+
+ // call the callback
+ if (was_enabled)
+ {
+ g_profiler.start(PROFILER_TIMER_CALLBACK);
+
+ if (timer.m_device != NULL)
+ timer.m_device->timer_expired(timer, timer.m_id, timer.m_param, timer.m_ptr);
+ else if (!timer.m_callback.isnull())
+ timer.m_callback(timer.m_ptr, timer.m_param);
+
+ g_profiler.stop();
+ }
+
+ // clear the callback timer global
+ m_callback_timer = NULL;
+
+ // reset or remove the timer, but only if it wasn't modified during the callback
+ if (!m_callback_timer_modified)
+ {
+ // if the timer is temporary, remove it now
+ if (timer.m_temporary)
+ m_timer_allocator.reclaim(timer.release());
+
+ // otherwise, reschedule it
+ else
+ timer.schedule_next_period();
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// add_scheduling_quantum - add a scheduling
+// quantum; the smallest active one is the one
+// that is in use
+//-------------------------------------------------
+
+void device_scheduler::add_scheduling_quantum(attotime quantum, attotime duration)
+{
+ assert(quantum.seconds == 0);
+
+ attotime curtime = time();
+ attotime expire = curtime + duration;
+
+ // figure out where to insert ourselves, expiring any quanta that are out-of-date
+ quantum_slot *insert_after = NULL;
+ quantum_slot *next;
+ for (quantum_slot *quant = m_quantum_list.first(); quant != NULL; quant = next)
+ {
+ // if this quantum is expired, nuke it
+ next = quant->next();
+ if (curtime >= quant->m_expire)
+ m_quantum_allocator.reclaim(m_quantum_list.detach(*quant));
+
+ // if this quantum is shorter than us, we need to be inserted afterwards
+ else if (quant->m_requested <= quantum.attoseconds)
+ insert_after = quant;
+ }
+
+ // if we found an exact match, just take the maximum expiry time
+ if (insert_after != NULL && insert_after->m_requested == quantum.attoseconds)
+ insert_after->m_expire = max(insert_after->m_expire, expire);
+
+ // otherwise, allocate a new quantum and insert it after the one we picked
+ else
+ {
+ quantum_slot &quant = *m_quantum_allocator.alloc();
+ quant.m_requested = quantum.attoseconds;
+ quant.m_actual = MAX(quantum.attoseconds, m_quantum_minimum);
+ quant.m_expire = expire;
+ m_quantum_list.insert_after(quant, insert_after);
+ }
+}
+
+
+//-------------------------------------------------
+// dump_timers - dump the current timer state
+//-------------------------------------------------
+
+void device_scheduler::dump_timers() const
+{
+ logerror("=============================================\n");
+ logerror("Timer Dump: Time = %15s\n", time().as_string());
+ for (emu_timer *timer = first_timer(); timer != NULL; timer = timer->next())
+ timer->dump();
+ logerror("=============================================\n");
+}
+
+
diff --git a/trunk/src/emu/schedule.h b/trunk/src/emu/schedule.h
new file mode 100644
index 00000000000..61a48a35e18
--- /dev/null
+++ b/trunk/src/emu/schedule.h
@@ -0,0 +1,243 @@
+/***************************************************************************
+
+ schedule.h
+
+ Core device execution and scheduling engine.
+
+****************************************************************************
+
+ 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 __SCHEDULE_H__
+#define __SCHEDULE_H__
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+// macro for the RC time constant on a 74LS123 with C > 1000pF
+// R is in ohms, C is in farads
+#define TIME_OF_74LS123(r,c) (0.45 * (double)(r) * (double)(c))
+
+// macros for the RC time constant on a 555 timer IC
+// R is in ohms, C is in farads
+#define PERIOD_OF_555_MONOSTABLE_NSEC(r,c) ((attoseconds_t)(1100000000 * (double)(r) * (double)(c)))
+#define PERIOD_OF_555_ASTABLE_NSEC(r1,r2,c) ((attoseconds_t)( 693000000 * ((double)(r1) + 2.0 * (double)(r2)) * (double)(c)))
+#define PERIOD_OF_555_MONOSTABLE(r,c) attotime::from_nsec(PERIOD_OF_555_MONOSTABLE_NSEC(r,c))
+#define PERIOD_OF_555_ASTABLE(r1,r2,c) attotime::from_nsec(PERIOD_OF_555_ASTABLE_NSEC(r1,r2,c))
+
+#define TIMER_CALLBACK(name) void name(running_machine &machine, void *ptr, int param)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// timer callbacks look like this
+typedef delegate<void (void *, INT32)> timer_expired_delegate;
+
+// old-skool callbacks are like this
+typedef void (*timer_expired_func)(running_machine &machine, void *ptr, INT32 param);
+
+
+// ======================> emu_timer
+
+class emu_timer
+{
+ friend class device_scheduler;
+ friend class simple_list<emu_timer>;
+ friend class fixed_allocator<emu_timer>;
+ friend class resource_pool_object<emu_timer>;
+
+ // construction/destruction
+ emu_timer();
+ ~emu_timer();
+
+ // allocation and re-use
+ emu_timer &init(running_machine &machine, timer_expired_delegate callback, void *ptr, bool temporary);
+ emu_timer &init(device_t &device, device_timer_id id, void *ptr, bool temporary);
+ emu_timer &release();
+
+public:
+ // getters
+ emu_timer *next() const { return m_next; }
+ running_machine &machine() const { assert(m_machine != NULL); return *m_machine; }
+ bool enabled() const { return m_enabled; }
+ int param() const { return m_param; }
+ void *ptr() const { return m_ptr; }
+
+ // setters
+ bool enable(bool enable = true);
+ void set_param(int param) { m_param = param; }
+ void set_ptr(void *ptr) { m_ptr = ptr; }
+
+ // control
+ void reset(attotime duration = attotime::never) { adjust(duration, m_param, m_period); }
+ void adjust(attotime duration, INT32 param = 0, attotime periodicity = attotime::never);
+
+ // timing queries
+ attotime elapsed() const;
+ attotime remaining() const;
+ attotime start() const { return m_start; }
+ attotime expire() const { return m_expire; }
+
+private:
+ // internal helpers
+ void register_save();
+ void schedule_next_period();
+ void dump() const;
+
+ // internal state
+ running_machine * m_machine; // reference to the owning machine
+ emu_timer * m_next; // next timer in order in the list
+ emu_timer * m_prev; // previous timer in order in the list
+ timer_expired_delegate m_callback; // callback function
+ INT32 m_param; // integer parameter
+ void * m_ptr; // pointer parameter
+ bool m_enabled; // is the timer enabled?
+ bool m_temporary; // is the timer temporary?
+ attotime m_period; // the repeat frequency of the timer
+ attotime m_start; // time when the timer was started
+ attotime m_expire; // time when the timer will expire
+ device_t * m_device; // for device timers, a pointer to the device
+ device_timer_id m_id; // for device timers, the ID of the timer
+};
+
+
+// ======================> device_scheduler
+
+class device_scheduler
+{
+ friend class device_execute_interface;
+ friend class emu_timer;
+
+public:
+ // construction/destruction
+ device_scheduler(running_machine &machine);
+ ~device_scheduler();
+
+ // getters
+ running_machine &machine() const { return m_machine; }
+ attotime time() const;
+ emu_timer *first_timer() const { return m_timer_list; }
+ device_execute_interface *currently_executing() const { return m_executing_device; }
+ bool can_save() const;
+
+ // execution
+ void timeslice();
+ void abort_timeslice();
+ void trigger(int trigid, attotime after = attotime::zero);
+ void boost_interleave(attotime timeslice_time, attotime boost_duration);
+ void make_active() { m_cothread.make_active(); }
+
+ // timers, specified by callback/name
+ emu_timer *timer_alloc(timer_expired_delegate callback, void *ptr = NULL);
+ void timer_set(attotime duration, timer_expired_delegate callback, int param = 0, void *ptr = NULL);
+ void timer_pulse(attotime period, timer_expired_delegate callback, int param = 0, void *ptr = NULL);
+ void synchronize(timer_expired_delegate callback = timer_expired_delegate(), int param = 0, void *ptr = NULL) { timer_set(attotime::zero, callback, param, ptr); }
+
+ // timers with old-skool callbacks
+ emu_timer *timer_alloc(timer_expired_func callback, const char *name, void *ptr = NULL) { return timer_alloc(timer_expired_delegate(callback, name, &machine()), ptr); }
+ void timer_set(attotime duration, timer_expired_func callback, const char *name, int param = 0, void *ptr = NULL) { timer_set(duration, timer_expired_delegate(callback, name, &machine()), param, ptr); }
+ void timer_pulse(attotime period, timer_expired_func callback, const char *name, int param = 0, void *ptr = NULL) { timer_pulse(period, timer_expired_delegate(callback, name, &machine()), param, ptr); }
+ void synchronize(timer_expired_func callback, const char *name = NULL, int param = 0, void *ptr = NULL) { timer_set(attotime::zero, callback, name, param, ptr); }
+
+ // timers, specified by device/id; generally devices should use the device_t methods instead
+ emu_timer *timer_alloc(device_t &device, device_timer_id id = 0, void *ptr = NULL);
+ void timer_set(attotime duration, device_t &device, device_timer_id id = 0, int param = 0, void *ptr = NULL);
+
+ // debugging
+ void dump_timers() const;
+
+ // for emergencies only!
+ void eat_all_cycles();
+
+private:
+ // callbacks
+ void timed_trigger(void *ptr, INT32 param);
+ void presave();
+ void postload();
+
+ // scheduling helpers
+ void compute_perfect_interleave();
+ void rebuild_execute_list();
+ void add_scheduling_quantum(attotime quantum, attotime duration);
+
+ // timer helpers
+ emu_timer &timer_list_insert(emu_timer &timer);
+ emu_timer &timer_list_remove(emu_timer &timer);
+ void execute_timers();
+
+ // internal state
+ running_machine & m_machine; // reference to our machine
+ device_execute_interface * m_executing_device; // pointer to currently executing device
+ device_execute_interface * m_execute_list; // list of devices to be executed
+ attotime m_basetime; // global basetime; everything moves forward from here
+ cothread m_cothread; // core scheduler thread
+
+ // list of active timers
+ emu_timer * m_timer_list; // head of the active list
+ fixed_allocator<emu_timer> m_timer_allocator; // allocator for timers
+
+ // other internal states
+ emu_timer * m_callback_timer; // pointer to the current callback timer
+ bool m_callback_timer_modified; // true if the current callback timer was modified
+ attotime m_callback_timer_expire_time; // the original expiration time
+
+ // scheduling quanta
+ class quantum_slot
+ {
+ friend class simple_list<quantum_slot>;
+
+ public:
+ quantum_slot *next() const { return m_next; }
+
+ quantum_slot * m_next;
+ attoseconds_t m_actual; // actual duration of the quantum
+ attoseconds_t m_requested; // duration of the requested quantum
+ attotime m_expire; // absolute expiration time of this quantum
+ };
+ simple_list<quantum_slot> m_quantum_list; // list of active quanta
+ fixed_allocator<quantum_slot> m_quantum_allocator; // allocator for quanta
+ attoseconds_t m_quantum_minimum; // duration of minimum quantum
+};
+
+
+#endif // __SCHEDULE_H__ */
diff --git a/trunk/src/emu/screen.c b/trunk/src/emu/screen.c
new file mode 100644
index 00000000000..0089399dc38
--- /dev/null
+++ b/trunk/src/emu/screen.c
@@ -0,0 +1,1096 @@
+/***************************************************************************
+
+ screen.c
+
+ Core MAME screen device.
+
+****************************************************************************
+
+ 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 "png.h"
+#include "rendutil.h"
+
+
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define VERBOSE (0)
+#define LOG_PARTIAL_UPDATES(x) do { if (VERBOSE) logerror x; } while (0)
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+const device_type SCREEN = &device_creator<screen_device>;
+
+const attotime screen_device::DEFAULT_FRAME_PERIOD(attotime::from_hz(DEFAULT_FRAME_RATE));
+
+
+
+//**************************************************************************
+// SCREEN DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// screen_device - constructor
+//-------------------------------------------------
+
+screen_device::screen_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, SCREEN, "Video Screen", tag, owner, clock),
+ m_type(SCREEN_TYPE_RASTER),
+ m_oldstyle_vblank_supplied(false),
+ m_refresh(0),
+ m_vblank(0),
+ m_format(BITMAP_FORMAT_INVALID),
+ m_xoffset(0.0f),
+ m_yoffset(0.0f),
+ m_xscale(1.0f),
+ m_yscale(1.0f),
+ m_screen_update(NULL),
+ m_screen_eof(NULL),
+ m_container(NULL),
+ m_width(100),
+ m_height(100),
+ m_burnin(NULL),
+ m_curbitmap(0),
+ m_curtexture(0),
+ m_texture_format(0),
+ m_changed(true),
+ m_last_partial_scan(0),
+ m_screen_overlay_bitmap(NULL),
+ m_frame_period(DEFAULT_FRAME_PERIOD.as_attoseconds()),
+ m_scantime(1),
+ m_pixeltime(1),
+ m_vblank_period(0),
+ m_vblank_start_time(attotime::zero),
+ m_vblank_end_time(attotime::zero),
+ m_vblank_begin_timer(NULL),
+ m_vblank_end_timer(NULL),
+ m_scanline0_timer(NULL),
+ m_scanline_timer(NULL),
+ m_frame_number(0),
+ m_partial_updates_this_frame(0)
+{
+ m_visarea.min_x = m_visarea.min_y = 0;
+ m_visarea.max_x = m_width - 1;
+ m_visarea.max_y = m_height - 1;
+ memset(m_texture, 0, sizeof(m_texture));
+ memset(m_bitmap, 0, sizeof(m_bitmap));
+}
+
+
+//-------------------------------------------------
+// ~screen_device - destructor
+//-------------------------------------------------
+
+screen_device::~screen_device()
+{
+}
+
+
+//-------------------------------------------------
+// static_set_format - configuration helper
+// to set the bitmap format
+//-------------------------------------------------
+
+void screen_device::static_set_format(device_t &device, bitmap_format format)
+{
+ screen_device &screen = downcast<screen_device &>(device);
+ screen.m_format = format;
+}
+
+
+//-------------------------------------------------
+// static_set_type - configuration helper
+// to set the screen type
+//-------------------------------------------------
+
+void screen_device::static_set_type(device_t &device, screen_type_enum type)
+{
+ screen_device &screen = downcast<screen_device &>(device);
+ screen.m_type = type;
+}
+
+
+//-------------------------------------------------
+// static_set_raw - configuration helper
+// to set the raw screen parameters
+//-------------------------------------------------
+
+void screen_device::static_set_raw(device_t &device, UINT32 pixclock, UINT16 htotal, UINT16 hbend, UINT16 hbstart, UINT16 vtotal, UINT16 vbend, UINT16 vbstart)
+{
+ screen_device &screen = downcast<screen_device &>(device);
+ screen.m_refresh = HZ_TO_ATTOSECONDS(pixclock) * htotal * vtotal;
+ screen.m_vblank = screen.m_refresh / vtotal * (vtotal - (vbstart - vbend));
+ screen.m_width = htotal;
+ screen.m_height = vtotal;
+ screen.m_visarea.min_x = hbend;
+ screen.m_visarea.max_x = hbstart - 1;
+ screen.m_visarea.min_y = vbend;
+ screen.m_visarea.max_y = vbstart - 1;
+}
+
+
+//-------------------------------------------------
+// static_set_refresh - configuration helper
+// to set the refresh rate
+//-------------------------------------------------
+
+void screen_device::static_set_refresh(device_t &device, attoseconds_t rate)
+{
+ screen_device &screen = downcast<screen_device &>(device);
+ screen.m_refresh = rate;
+}
+
+
+//-------------------------------------------------
+// static_set_vblank_time - configuration helper
+// to set the VBLANK duration
+//-------------------------------------------------
+
+void screen_device::static_set_vblank_time(device_t &device, attoseconds_t time)
+{
+ screen_device &screen = downcast<screen_device &>(device);
+ screen.m_vblank = time;
+ screen.m_oldstyle_vblank_supplied = true;
+}
+
+
+//-------------------------------------------------
+// static_set_size - configuration helper to set
+// the width/height of the screen
+//-------------------------------------------------
+
+void screen_device::static_set_size(device_t &device, UINT16 width, UINT16 height)
+{
+ screen_device &screen = downcast<screen_device &>(device);
+ screen.m_width = width;
+ screen.m_height = height;
+}
+
+
+//-------------------------------------------------
+// static_set_visarea - configuration helper to
+// set the visible area of the screen
+//-------------------------------------------------
+
+void screen_device::static_set_visarea(device_t &device, INT16 minx, INT16 maxx, INT16 miny, INT16 maxy)
+{
+ screen_device &screen = downcast<screen_device &>(device);
+ screen.m_visarea.min_x = minx;
+ screen.m_visarea.max_x = maxx;
+ screen.m_visarea.min_y = miny;
+ screen.m_visarea.max_y = maxy;
+}
+
+
+//-------------------------------------------------
+// static_set_default_position - configuration
+// helper to set the default position and scale
+// factors for the screen
+//-------------------------------------------------
+
+void screen_device::static_set_default_position(device_t &device, double xscale, double xoffs, double yscale, double yoffs)
+{
+ screen_device &screen = downcast<screen_device &>(device);
+ screen.m_xscale = xscale;
+ screen.m_xoffset = xoffs;
+ screen.m_yscale = yscale;
+ screen.m_yoffset = yoffs;
+}
+
+
+//-------------------------------------------------
+// static_set_screen_update - set the legacy
+// screen update callback in the device
+// configuration
+//-------------------------------------------------
+
+void screen_device::static_set_screen_update(device_t &device, screen_update_func callback)
+{
+ downcast<screen_device &>(device).m_screen_update = callback;
+}
+
+
+//-------------------------------------------------
+// static_set_screen_eof - set the legacy
+// screen eof callback in the device
+// configuration
+//-------------------------------------------------
+
+void screen_device::static_set_screen_eof(device_t &device, screen_eof_func callback)
+{
+ downcast<screen_device &>(device).m_screen_eof = callback;
+}
+
+
+//-------------------------------------------------
+// device_validity_check - verify device
+// configuration
+//-------------------------------------------------
+
+bool screen_device::device_validity_check(emu_options &options, const game_driver &driver) const
+{
+ bool error = false;
+
+ // sanity check dimensions
+ if (m_width <= 0 || m_height <= 0)
+ {
+ mame_printf_error("%s: %s screen '%s' has invalid display dimensions\n", driver.source_file, driver.name, tag());
+ error = true;
+ }
+
+ // sanity check display area
+ if (m_type != SCREEN_TYPE_VECTOR)
+ {
+ if ((m_visarea.max_x < m_visarea.min_x) ||
+ (m_visarea.max_y < m_visarea.min_y) ||
+ (m_visarea.max_x >= m_width) ||
+ (m_visarea.max_y >= m_height))
+ {
+ mame_printf_error("%s: %s screen '%s' has an invalid display area\n", driver.source_file, driver.name, tag());
+ error = true;
+ }
+
+ // sanity check screen formats
+ if (m_format != BITMAP_FORMAT_INDEXED16 &&
+ m_format != BITMAP_FORMAT_RGB15 &&
+ m_format != BITMAP_FORMAT_RGB32)
+ {
+ mame_printf_error("%s: %s screen '%s' has unsupported format\n", driver.source_file, driver.name, tag());
+ error = true;
+ }
+ }
+
+ // check for zero frame rate
+ if (m_refresh == 0)
+ {
+ mame_printf_error("%s: %s screen '%s' has a zero refresh rate\n", driver.source_file, driver.name, tag());
+ error = true;
+ }
+ return error;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void screen_device::device_start()
+{
+ // configure the default cliparea
+ render_container::user_settings settings;
+ m_container->get_user_settings(settings);
+ settings.m_xoffset = m_xoffset;
+ settings.m_yoffset = m_yoffset;
+ settings.m_xscale = m_xscale;
+ settings.m_yscale = m_yscale;
+ m_container->set_user_settings(settings);
+
+ // allocate the VBLANK timers
+ m_vblank_begin_timer = machine().scheduler().timer_alloc(FUNC(static_vblank_begin_callback), (void *)this);
+ m_vblank_end_timer = machine().scheduler().timer_alloc(FUNC(static_vblank_end_callback), (void *)this);
+
+ // allocate a timer to reset partial updates
+ m_scanline0_timer = machine().scheduler().timer_alloc(FUNC(static_scanline0_callback), (void *)this);
+
+ // allocate a timer to generate per-scanline updates
+ if ((machine().config().m_video_attributes & VIDEO_UPDATE_SCANLINE) != 0)
+ m_scanline_timer = machine().scheduler().timer_alloc(FUNC(static_scanline_update_callback), (void *)this);
+
+ // configure the screen with the default parameters
+ configure(m_width, m_height, m_visarea, m_refresh);
+
+ // reset VBLANK timing
+ m_vblank_start_time = attotime::zero;
+ m_vblank_end_time = attotime(0, m_vblank_period);
+
+ // start the timer to generate per-scanline updates
+ if ((machine().config().m_video_attributes & VIDEO_UPDATE_SCANLINE) != 0)
+ m_scanline_timer->adjust(time_until_pos(0));
+
+ // create burn-in bitmap
+ if (machine().options().burnin())
+ {
+ int width, height;
+ if (sscanf(machine().options().snap_size(), "%dx%d", &width, &height) != 2 || width == 0 || height == 0)
+ width = height = 300;
+ m_burnin = auto_alloc(machine(), bitmap_t(width, height, BITMAP_FORMAT_INDEXED64));
+ if (m_burnin == NULL)
+ fatalerror("Error allocating burn-in bitmap for screen at (%dx%d)\n", width, height);
+ bitmap_fill(m_burnin, NULL, 0);
+ }
+
+ // load the effect overlay
+ const char *overname = machine().options().effect();
+ if (overname != NULL && strcmp(overname, "none") != 0)
+ load_effect_overlay(overname);
+
+ // register items for saving
+ save_item(NAME(m_width));
+ save_item(NAME(m_height));
+ save_item(NAME(m_visarea.min_x));
+ save_item(NAME(m_visarea.min_y));
+ save_item(NAME(m_visarea.max_x));
+ save_item(NAME(m_visarea.max_y));
+ save_item(NAME(m_last_partial_scan));
+ save_item(NAME(m_frame_period));
+ save_item(NAME(m_scantime));
+ save_item(NAME(m_pixeltime));
+ save_item(NAME(m_vblank_period));
+ save_item(NAME(m_vblank_start_time));
+ save_item(NAME(m_vblank_end_time));
+ save_item(NAME(m_frame_number));
+}
+
+
+//-------------------------------------------------
+// device_stop - clean up before the machine goes
+// away
+//-------------------------------------------------
+
+void screen_device::device_stop()
+{
+ machine().render().texture_free(m_texture[0]);
+ machine().render().texture_free(m_texture[1]);
+ if (m_burnin != NULL)
+ finalize_burnin();
+ global_free(m_screen_overlay_bitmap);
+}
+
+
+//-------------------------------------------------
+// device_post_load - device-specific update
+// after a save state is loaded
+//-------------------------------------------------
+
+void screen_device::device_post_load()
+{
+ realloc_screen_bitmaps();
+}
+
+
+//-------------------------------------------------
+// configure - configure screen parameters
+//-------------------------------------------------
+
+void screen_device::configure(int width, int height, const rectangle &visarea, attoseconds_t frame_period)
+{
+ // validate arguments
+ assert(width > 0);
+ assert(height > 0);
+ assert(visarea.min_x >= 0);
+ assert(visarea.min_y >= 0);
+ assert(m_type == SCREEN_TYPE_VECTOR || visarea.min_x < width);
+ assert(m_type == SCREEN_TYPE_VECTOR || visarea.min_y < height);
+ assert(frame_period > 0);
+
+ // fill in the new parameters
+ m_width = width;
+ m_height = height;
+ m_visarea = visarea;
+
+ // reallocate bitmap if necessary
+ realloc_screen_bitmaps();
+
+ // compute timing parameters
+ m_frame_period = frame_period;
+ m_scantime = frame_period / height;
+ m_pixeltime = frame_period / (height * width);
+
+ // if there has been no VBLANK time specified in the MACHINE_DRIVER, compute it now
+ // from the visible area, otherwise just used the supplied value
+ if (m_vblank == 0 && !m_oldstyle_vblank_supplied)
+ m_vblank_period = m_scantime * (height - (visarea.max_y + 1 - visarea.min_y));
+ else
+ m_vblank_period = m_vblank;
+
+ // if we are on scanline 0 already, reset the update timer immediately
+ // otherwise, defer until the next scanline 0
+ if (vpos() == 0)
+ m_scanline0_timer->adjust(attotime::zero);
+ else
+ m_scanline0_timer->adjust(time_until_pos(0));
+
+ // start the VBLANK timer
+ m_vblank_begin_timer->adjust(time_until_vblank_start());
+
+ // adjust speed if necessary
+ machine().video().update_refresh_speed();
+}
+
+
+//-------------------------------------------------
+// reset_origin - reset the timing such that the
+// given (x,y) occurs at the current time
+//-------------------------------------------------
+
+void screen_device::reset_origin(int beamy, int beamx)
+{
+ // compute the effective VBLANK start/end times
+ attotime curtime = machine().time();
+ m_vblank_end_time = curtime - attotime(0, beamy * m_scantime + beamx * m_pixeltime);
+ m_vblank_start_time = m_vblank_end_time - attotime(0, m_vblank_period);
+
+ // if we are resetting relative to (0,0) == VBLANK end, call the
+ // scanline 0 timer by hand now; otherwise, adjust it for the future
+ if (beamy == 0 && beamx == 0)
+ scanline0_callback();
+ else
+ m_scanline0_timer->adjust(time_until_pos(0));
+
+ // if we are resetting relative to (visarea.max_y + 1, 0) == VBLANK start,
+ // call the VBLANK start timer now; otherwise, adjust it for the future
+ if (beamy == m_visarea.max_y + 1 && beamx == 0)
+ vblank_begin_callback();
+ else
+ m_vblank_begin_timer->adjust(time_until_vblank_start());
+}
+
+
+//-------------------------------------------------
+// realloc_screen_bitmaps - reallocate bitmaps
+// and textures as necessary
+//-------------------------------------------------
+
+void screen_device::realloc_screen_bitmaps()
+{
+ if (m_type == SCREEN_TYPE_VECTOR)
+ return;
+
+ int curwidth = 0, curheight = 0;
+
+ // extract the current width/height from the bitmap
+ if (m_bitmap[0] != NULL)
+ {
+ curwidth = m_bitmap[0]->width;
+ curheight = m_bitmap[0]->height;
+ }
+
+ // if we're too small to contain this width/height, reallocate our bitmaps and textures
+ if (m_width > curwidth || m_height > curheight)
+ {
+ // free what we have currently
+ machine().render().texture_free(m_texture[0]);
+ machine().render().texture_free(m_texture[1]);
+ auto_free(machine(), m_bitmap[0]);
+ auto_free(machine(), m_bitmap[1]);
+
+ // compute new width/height
+ curwidth = MAX(m_width, curwidth);
+ curheight = MAX(m_height, curheight);
+
+ // choose the texture format - convert the screen format to a texture format
+ palette_t *palette = NULL;
+ switch (m_format)
+ {
+ case BITMAP_FORMAT_INDEXED16: m_texture_format = TEXFORMAT_PALETTE16; palette = machine().palette; break;
+ case BITMAP_FORMAT_RGB15: m_texture_format = TEXFORMAT_RGB15; palette = NULL; break;
+ case BITMAP_FORMAT_RGB32: m_texture_format = TEXFORMAT_RGB32; palette = NULL; break;
+ default: fatalerror("Invalid bitmap format!"); break;
+ }
+
+ // allocate bitmaps
+ m_bitmap[0] = auto_alloc(machine(), bitmap_t(curwidth, curheight, m_format));
+ bitmap_set_palette(m_bitmap[0], machine().palette);
+ m_bitmap[1] = auto_alloc(machine(), bitmap_t(curwidth, curheight, m_format));
+ bitmap_set_palette(m_bitmap[1], machine().palette);
+
+ // allocate textures
+ m_texture[0] = machine().render().texture_alloc();
+ m_texture[0]->set_bitmap(m_bitmap[0], &m_visarea, m_texture_format, palette);
+ m_texture[1] = machine().render().texture_alloc();
+ m_texture[1]->set_bitmap(m_bitmap[1], &m_visarea, m_texture_format, palette);
+ }
+}
+
+
+//-------------------------------------------------
+// set_visible_area - just set the visible area
+//-------------------------------------------------
+
+void screen_device::set_visible_area(int min_x, int max_x, int min_y, int max_y)
+{
+ // validate arguments
+ assert(min_x >= 0);
+ assert(min_y >= 0);
+ assert(min_x < max_x);
+ assert(min_y < max_y);
+
+ rectangle visarea;
+ visarea.min_x = min_x;
+ visarea.max_x = max_x;
+ visarea.min_y = min_y;
+ visarea.max_y = max_y;
+
+ configure(m_width, m_height, visarea, m_frame_period);
+}
+
+
+//-------------------------------------------------
+// update_partial - perform a partial update from
+// the last scanline up to and including the
+// specified scanline
+//-----------------------------------------------*/
+
+bool screen_device::update_partial(int scanline)
+{
+ // validate arguments
+ assert(scanline >= 0);
+
+ LOG_PARTIAL_UPDATES(("Partial: update_partial(%s, %d): ", tag(), scanline));
+
+ // these two checks only apply if we're allowed to skip frames
+ if (!(machine().config().m_video_attributes & VIDEO_ALWAYS_UPDATE))
+ {
+ // if skipping this frame, bail
+ if (machine().video().skip_this_frame())
+ {
+ LOG_PARTIAL_UPDATES(("skipped due to frameskipping\n"));
+ return FALSE;
+ }
+
+ // skip if this screen is not visible anywhere
+ if (!machine().render().is_live(*this))
+ {
+ LOG_PARTIAL_UPDATES(("skipped because screen not live\n"));
+ return FALSE;
+ }
+ }
+
+ // skip if less than the lowest so far
+ if (scanline < m_last_partial_scan)
+ {
+ LOG_PARTIAL_UPDATES(("skipped because less than previous\n"));
+ return FALSE;
+ }
+
+ // set the start/end scanlines
+ rectangle clip = m_visarea;
+ if (m_last_partial_scan > clip.min_y)
+ clip.min_y = m_last_partial_scan;
+ if (scanline < clip.max_y)
+ clip.max_y = scanline;
+
+ // render if necessary
+ bool result = false;
+ if (clip.min_y <= clip.max_y)
+ {
+ UINT32 flags = UPDATE_HAS_NOT_CHANGED;
+
+ g_profiler.start(PROFILER_VIDEO);
+ LOG_PARTIAL_UPDATES(("updating %d-%d\n", clip.min_y, clip.max_y));
+
+ flags = screen_update(*m_bitmap[m_curbitmap], clip);
+ m_partial_updates_this_frame++;
+ g_profiler.stop();
+
+ // if we modified the bitmap, we have to commit
+ m_changed |= ~flags & UPDATE_HAS_NOT_CHANGED;
+ result = true;
+ }
+
+ // remember where we left off
+ m_last_partial_scan = scanline + 1;
+ return result;
+}
+
+
+//-------------------------------------------------
+// update_now - perform an update from the last
+// beam position up to the current beam position
+//-------------------------------------------------
+
+void screen_device::update_now()
+{
+ int current_vpos = vpos();
+ int current_hpos = hpos();
+
+ // since we can currently update only at the scanline
+ // level, we are trying to do the right thing by
+ // updating including the current scanline, only if the
+ // beam is past the halfway point horizontally.
+ // If the beam is in the first half of the scanline,
+ // we only update up to the previous scanline.
+ // This minimizes the number of pixels that might be drawn
+ // incorrectly until we support a pixel level granularity
+ if (current_hpos < (m_width / 2) && current_vpos > 0)
+ current_vpos = current_vpos - 1;
+
+ update_partial(current_vpos);
+}
+
+
+//-------------------------------------------------
+// vpos - returns the current vertical position
+// of the beam
+//-------------------------------------------------
+
+int screen_device::vpos() const
+{
+ attoseconds_t delta = (machine().time() - m_vblank_start_time).as_attoseconds();
+ int vpos;
+
+ // round to the nearest pixel
+ delta += m_pixeltime / 2;
+
+ // compute the v position relative to the start of VBLANK
+ vpos = delta / m_scantime;
+
+ // adjust for the fact that VBLANK starts at the bottom of the visible area
+ return (m_visarea.max_y + 1 + vpos) % m_height;
+}
+
+
+//-------------------------------------------------
+// hpos - returns the current horizontal position
+// of the beam
+//-------------------------------------------------
+
+int screen_device::hpos() const
+{
+ attoseconds_t delta = (machine().time() - m_vblank_start_time).as_attoseconds();
+
+ // round to the nearest pixel
+ delta += m_pixeltime / 2;
+
+ // compute the v position relative to the start of VBLANK
+ int vpos = delta / m_scantime;
+
+ // subtract that from the total time
+ delta -= vpos * m_scantime;
+
+ // return the pixel offset from the start of this scanline
+ return delta / m_pixeltime;
+}
+
+
+//-------------------------------------------------
+// time_until_pos - returns the amount of time
+// remaining until the beam is at the given
+// hpos,vpos
+//-------------------------------------------------
+
+attotime screen_device::time_until_pos(int vpos, int hpos) const
+{
+ // validate arguments
+ assert(vpos >= 0);
+ assert(hpos >= 0);
+
+ // since we measure time relative to VBLANK, compute the scanline offset from VBLANK
+ vpos += m_height - (m_visarea.max_y + 1);
+ vpos %= m_height;
+
+ // compute the delta for the given X,Y position
+ attoseconds_t targetdelta = (attoseconds_t)vpos * m_scantime + (attoseconds_t)hpos * m_pixeltime;
+
+ // if we're past that time (within 1/2 of a pixel), head to the next frame
+ attoseconds_t curdelta = (machine().time() - m_vblank_start_time).as_attoseconds();
+ if (targetdelta <= curdelta + m_pixeltime / 2)
+ targetdelta += m_frame_period;
+ while (targetdelta <= curdelta)
+ targetdelta += m_frame_period;
+
+ // return the difference
+ return attotime(0, targetdelta - curdelta);
+}
+
+
+//-------------------------------------------------
+// time_until_vblank_end - returns the amount of
+// time remaining until the end of the current
+// VBLANK (if in progress) or the end of the next
+// VBLANK
+//-------------------------------------------------
+
+attotime screen_device::time_until_vblank_end() const
+{
+ // if we are in the VBLANK region, compute the time until the end of the current VBLANK period
+ attotime target_time = m_vblank_end_time;
+ if (!vblank())
+ target_time += attotime(0, m_frame_period);
+ return target_time - machine().time();
+}
+
+
+//-------------------------------------------------
+// register_vblank_callback - registers a VBLANK
+// callback
+//-------------------------------------------------
+
+void screen_device::register_vblank_callback(vblank_state_delegate vblank_callback)
+{
+ // validate arguments
+ assert(!vblank_callback.isnull());
+
+ // check if we already have this callback registered
+ callback_item *item;
+ for (item = m_callback_list.first(); item != NULL; item = item->next())
+ if (item->m_callback == vblank_callback)
+ break;
+
+ // if not found, register
+ if (item == NULL)
+ m_callback_list.append(*global_alloc(callback_item(vblank_callback)));
+}
+
+
+//-------------------------------------------------
+// vblank_begin_callback - call any external
+// callbacks to signal the VBLANK period has begun
+//-------------------------------------------------
+
+void screen_device::vblank_begin_callback()
+{
+ // reset the starting VBLANK time
+ m_vblank_start_time = machine().time();
+ m_vblank_end_time = m_vblank_start_time + attotime(0, m_vblank_period);
+
+ // call the screen specific callbacks
+ for (callback_item *item = m_callback_list.first(); item != NULL; item = item->next())
+ item->m_callback(*this, true);
+
+ // if this is the primary screen and we need to update now
+ if (this == machine().primary_screen && !(machine().config().m_video_attributes & VIDEO_UPDATE_AFTER_VBLANK))
+ machine().video().frame_update();
+
+ // reset the VBLANK start timer for the next frame
+ m_vblank_begin_timer->adjust(time_until_vblank_start());
+
+ // if no VBLANK period, call the VBLANK end callback immedietely, otherwise reset the timer
+ if (m_vblank_period == 0)
+ vblank_end_callback();
+ else
+ m_vblank_end_timer->adjust(time_until_vblank_end());
+}
+
+
+//-------------------------------------------------
+// vblank_end_callback - call any external
+// callbacks to signal the VBLANK period has ended
+//-------------------------------------------------
+
+void screen_device::vblank_end_callback()
+{
+ // call the screen specific callbacks
+ for (callback_item *item = m_callback_list.first(); item != NULL; item = item->next())
+ item->m_callback(*this, false);
+
+ // if this is the primary screen and we need to update now
+ if (this == machine().primary_screen && (machine().config().m_video_attributes & VIDEO_UPDATE_AFTER_VBLANK))
+ machine().video().frame_update();
+
+ // increment the frame number counter
+ m_frame_number++;
+}
+
+
+//-------------------------------------------------
+// scanline0_callback - reset partial updates
+// for a screen
+//-------------------------------------------------
+
+void screen_device::scanline0_callback()
+{
+ // reset partial updates
+ m_last_partial_scan = 0;
+ m_partial_updates_this_frame = 0;
+
+ m_scanline0_timer->adjust(time_until_pos(0));
+}
+
+
+//-------------------------------------------------
+// scanline_update_callback - perform partial
+// updates on each scanline
+//-------------------------------------------------
+
+void screen_device::scanline_update_callback(int scanline)
+{
+ // force a partial update to the current scanline
+ update_partial(scanline);
+
+ // compute the next visible scanline
+ scanline++;
+ if (scanline > m_visarea.max_y)
+ scanline = m_visarea.min_y;
+ m_scanline_timer->adjust(time_until_pos(scanline), scanline);
+}
+
+
+//-------------------------------------------------
+// update_quads - set up the quads for this
+// screen
+//-------------------------------------------------
+
+bool screen_device::update_quads()
+{
+ // only update if live
+ if (machine().render().is_live(*this))
+ {
+ // only update if empty and not a vector game; otherwise assume the driver did it directly
+ if (m_type != SCREEN_TYPE_VECTOR && (machine().config().m_video_attributes & VIDEO_SELF_RENDER) == 0)
+ {
+ // if we're not skipping the frame and if the screen actually changed, then update the texture
+ if (!machine().video().skip_this_frame() && m_changed)
+ {
+ rectangle fixedvis = m_visarea;
+ fixedvis.max_x++;
+ fixedvis.max_y++;
+
+ palette_t *palette = (m_texture_format == TEXFORMAT_PALETTE16) ? machine().palette : NULL;
+ m_texture[m_curbitmap]->set_bitmap(m_bitmap[m_curbitmap], &fixedvis, m_texture_format, palette);
+
+ m_curtexture = m_curbitmap;
+ m_curbitmap = 1 - m_curbitmap;
+ }
+
+ // create an empty container with a single quad
+ m_container->empty();
+ m_container->add_quad(0.0f, 0.0f, 1.0f, 1.0f, MAKE_ARGB(0xff,0xff,0xff,0xff), m_texture[m_curtexture], PRIMFLAG_BLENDMODE(BLENDMODE_NONE) | PRIMFLAG_SCREENTEX(1));
+ }
+ }
+
+ // reset the screen changed flags
+ bool result = m_changed;
+ m_changed = false;
+ return result;
+}
+
+
+//-------------------------------------------------
+// update_burnin - update the burnin bitmap
+//-------------------------------------------------
+
+void screen_device::update_burnin()
+{
+#undef rand
+ if (m_burnin == NULL)
+ return;
+
+ bitmap_t *srcbitmap = m_bitmap[m_curtexture];
+ if (srcbitmap == NULL)
+ return;
+
+ int srcwidth = srcbitmap->width;
+ int srcheight = srcbitmap->height;
+ int dstwidth = m_burnin->width;
+ int dstheight = m_burnin->height;
+ int xstep = (srcwidth << 16) / dstwidth;
+ int ystep = (srcheight << 16) / dstheight;
+ int xstart = ((UINT32)rand() % 32767) * xstep / 32767;
+ int ystart = ((UINT32)rand() % 32767) * ystep / 32767;
+ int srcx, srcy;
+ int x, y;
+
+ // iterate over rows in the destination
+ for (y = 0, srcy = ystart; y < dstheight; y++, srcy += ystep)
+ {
+ UINT64 *dst = BITMAP_ADDR64(m_burnin, y, 0);
+
+ // handle the 16-bit palettized case
+ if (srcbitmap->format == BITMAP_FORMAT_INDEXED16)
+ {
+ const UINT16 *src = BITMAP_ADDR16(srcbitmap, srcy >> 16, 0);
+ const rgb_t *palette = palette_entry_list_adjusted(machine().palette);
+ for (x = 0, srcx = xstart; x < dstwidth; x++, srcx += xstep)
+ {
+ rgb_t pixel = palette[src[srcx >> 16]];
+ dst[x] += RGB_GREEN(pixel) + RGB_RED(pixel) + RGB_BLUE(pixel);
+ }
+ }
+
+ // handle the 15-bit RGB case
+ else if (srcbitmap->format == BITMAP_FORMAT_RGB15)
+ {
+ const UINT16 *src = BITMAP_ADDR16(srcbitmap, srcy >> 16, 0);
+ for (x = 0, srcx = xstart; x < dstwidth; x++, srcx += xstep)
+ {
+ rgb15_t pixel = src[srcx >> 16];
+ dst[x] += ((pixel >> 10) & 0x1f) + ((pixel >> 5) & 0x1f) + ((pixel >> 0) & 0x1f);
+ }
+ }
+
+ // handle the 32-bit RGB case
+ else if (srcbitmap->format == BITMAP_FORMAT_RGB32)
+ {
+ const UINT32 *src = BITMAP_ADDR32(srcbitmap, srcy >> 16, 0);
+ for (x = 0, srcx = xstart; x < dstwidth; x++, srcx += xstep)
+ {
+ rgb_t pixel = src[srcx >> 16];
+ dst[x] += RGB_GREEN(pixel) + RGB_RED(pixel) + RGB_BLUE(pixel);
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// finalize_burnin - finalize the burnin bitmap
+//-------------------------------------------------
+
+void screen_device::finalize_burnin()
+{
+ if (m_burnin == NULL)
+ return;
+
+ // compute the scaled visible region
+ rectangle scaledvis;
+ scaledvis.min_x = m_visarea.min_x * m_burnin->width / m_width;
+ scaledvis.max_x = m_visarea.max_x * m_burnin->width / m_width;
+ scaledvis.min_y = m_visarea.min_y * m_burnin->height / m_height;
+ scaledvis.max_y = m_visarea.max_y * m_burnin->height / m_height;
+
+ // wrap a bitmap around the subregion we care about
+ bitmap_t *finalmap = auto_alloc(machine(), bitmap_t(scaledvis.max_x + 1 - scaledvis.min_x,
+ scaledvis.max_y + 1 - scaledvis.min_y,
+ BITMAP_FORMAT_ARGB32));
+
+ int srcwidth = m_burnin->width;
+ int srcheight = m_burnin->height;
+ int dstwidth = finalmap->width;
+ int dstheight = finalmap->height;
+ int xstep = (srcwidth << 16) / dstwidth;
+ int ystep = (srcheight << 16) / dstheight;
+
+ // find the maximum value
+ UINT64 minval = ~(UINT64)0;
+ UINT64 maxval = 0;
+ for (int y = 0; y < srcheight; y++)
+ {
+ UINT64 *src = BITMAP_ADDR64(m_burnin, y, 0);
+ for (int x = 0; x < srcwidth; x++)
+ {
+ minval = MIN(minval, src[x]);
+ maxval = MAX(maxval, src[x]);
+ }
+ }
+
+ if (minval == maxval)
+ return;
+
+ // now normalize and convert to RGB
+ for (int y = 0, srcy = 0; y < dstheight; y++, srcy += ystep)
+ {
+ UINT64 *src = BITMAP_ADDR64(m_burnin, srcy >> 16, 0);
+ UINT32 *dst = BITMAP_ADDR32(finalmap, y, 0);
+ for (int x = 0, srcx = 0; x < dstwidth; x++, srcx += xstep)
+ {
+ int brightness = (UINT64)(maxval - src[srcx >> 16]) * 255 / (maxval - minval);
+ dst[x] = MAKE_ARGB(0xff, brightness, brightness, brightness);
+ }
+ }
+
+ // write the final PNG
+
+ // compute the name and create the file
+ emu_file file(machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ file_error filerr = file.open(machine().basename(), PATH_SEPARATOR "burnin-", tag(), ".png") ;
+ if (filerr == FILERR_NONE)
+ {
+ png_info pnginfo = { 0 };
+// png_error pngerr;
+ char text[256];
+
+ // add two text entries describing the image
+ sprintf(text, APPNAME " %s", build_version);
+ png_add_text(&pnginfo, "Software", text);
+ sprintf(text, "%s %s", machine().system().manufacturer, machine().system().description);
+ png_add_text(&pnginfo, "System", text);
+
+ // now do the actual work
+ png_write_bitmap(file, &pnginfo, finalmap, 0, NULL);
+
+ // free any data allocated
+ png_free(&pnginfo);
+ }
+}
+
+
+//-------------------------------------------------
+// finalize_burnin - finalize the burnin bitmap
+//-------------------------------------------------
+
+void screen_device::load_effect_overlay(const char *filename)
+{
+ // ensure that there is a .png extension
+ astring fullname(filename);
+ int extension = fullname.rchr(0, '.');
+ if (extension != -1)
+ fullname.del(extension, -1);
+ fullname.cat(".png");
+
+ // load the file
+ emu_file file(machine().options().art_path(), OPEN_FLAG_READ);
+ m_screen_overlay_bitmap = render_load_png(file, NULL, fullname, NULL, NULL);
+ if (m_screen_overlay_bitmap != NULL)
+ m_container->set_overlay(m_screen_overlay_bitmap);
+ else
+ mame_printf_warning("Unable to load effect PNG file '%s'\n", fullname.cstr());
+}
+
+//-------------------------------------------------
+// screen_update - default implementation which
+// calls to the legacy screen_update function
+//-------------------------------------------------
+
+bool screen_device::screen_update(bitmap_t &bitmap, const rectangle &cliprect)
+{
+ if (m_screen_update != NULL) {
+ return (*m_screen_update)(this, &bitmap, &cliprect);
+ } else {
+ machine().driver_data<driver_device>()->screen_update(*this, bitmap, cliprect);
+ }
+ return 0;
+}
+
+//-------------------------------------------------
+// screen_eof - default implementation which
+// calls to the legacy screen_update function
+//-------------------------------------------------
+
+void screen_device::screen_eof()
+{
+ if (m_screen_eof != NULL) {
+ return (*m_screen_eof)(this, machine());
+ } else {
+ machine().driver_data<driver_device>()->screen_eof();
+ }
+}
diff --git a/trunk/src/emu/screen.h b/trunk/src/emu/screen.h
new file mode 100644
index 00000000000..18a202d4269
--- /dev/null
+++ b/trunk/src/emu/screen.h
@@ -0,0 +1,305 @@
+/***************************************************************************
+
+ screen.h
+
+ Core MAME screen device.
+
+****************************************************************************
+
+ 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 __SCREEN_H__
+#define __SCREEN_H__
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// screen types
+enum screen_type_enum
+{
+ SCREEN_TYPE_INVALID = 0,
+ SCREEN_TYPE_RASTER,
+ SCREEN_TYPE_VECTOR,
+ SCREEN_TYPE_LCD
+};
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// forward references
+class render_texture;
+class screen_device;
+
+
+// callback that is called to notify of a change in the VBLANK state
+typedef delegate<void (screen_device &, bool)> vblank_state_delegate;
+
+typedef UINT32 (*screen_update_func)(screen_device *screen, bitmap_t *bitmap, const rectangle *cliprect);
+typedef void (*screen_eof_func)(screen_device *screen, running_machine &machine);
+
+
+// ======================> screen_device
+
+class screen_device : public device_t
+{
+ friend class render_manager;
+
+public:
+ // construction/destruction
+ screen_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ ~screen_device();
+
+ // configuration readers
+ screen_type_enum screen_type() const { return m_type; }
+ int width() const { return m_width; }
+ int height() const { return m_height; }
+ const rectangle &visible_area() const { return m_visarea; }
+ bool oldstyle_vblank_supplied() const { return m_oldstyle_vblank_supplied; }
+ attoseconds_t refresh_attoseconds() const { return m_refresh; }
+ attoseconds_t vblank_attoseconds() const { return m_vblank; }
+ bitmap_format format() const { return m_format; }
+ float xoffset() const { return m_xoffset; }
+ float yoffset() const { return m_yoffset; }
+ float xscale() const { return m_xscale; }
+ float yscale() const { return m_yscale; }
+ bool have_screen_update() const { return m_screen_update != NULL; }
+
+ // inline configuration helpers
+ static void static_set_format(device_t &device, bitmap_format format);
+ static void static_set_type(device_t &device, screen_type_enum type);
+ static void static_set_raw(device_t &device, UINT32 pixclock, UINT16 htotal, UINT16 hbend, UINT16 hbstart, UINT16 vtotal, UINT16 vbend, UINT16 vbstart);
+ static void static_set_refresh(device_t &device, attoseconds_t rate);
+ static void static_set_vblank_time(device_t &device, attoseconds_t time);
+ static void static_set_size(device_t &device, UINT16 width, UINT16 height);
+ static void static_set_visarea(device_t &device, INT16 minx, INT16 maxx, INT16 miny, INT16 maxy);
+ static void static_set_default_position(device_t &device, double xscale, double xoffs, double yscale, double yoffs);
+ static void static_set_screen_update(device_t &device, screen_update_func callback);
+ static void static_set_screen_eof(device_t &device, screen_eof_func callback);
+
+ // information getters
+ screen_device *next_screen() const { return downcast<screen_device *>(typenext()); }
+ render_container &container() const { assert(m_container != NULL); return *m_container; }
+ bool screen_update(bitmap_t &bitmap, const rectangle &cliprect);
+ void screen_eof();
+
+ // dynamic configuration
+ void configure(int width, int height, const rectangle &visarea, attoseconds_t frame_period);
+ void reset_origin(int beamy = 0, int beamx = 0);
+ void set_visible_area(int min_x, int max_x, int min_y, int max_y);
+
+ // beam positioning and state
+ int vpos() const;
+ int hpos() const;
+ bool vblank() const { return (machine().time() < m_vblank_end_time); }
+ bool hblank() const { int curpos = hpos(); return (curpos < m_visarea.min_x || curpos > m_visarea.max_x); }
+
+ // timing
+ attotime time_until_pos(int vpos, int hpos = 0) const;
+ attotime time_until_vblank_start() const { return time_until_pos(m_visarea.max_y + 1); }
+ attotime time_until_vblank_end() const;
+ attotime time_until_update() const { return (machine().config().m_video_attributes & VIDEO_UPDATE_AFTER_VBLANK) ? time_until_vblank_end() : time_until_vblank_start(); }
+ attotime scan_period() const { return attotime(0, m_scantime); }
+ attotime frame_period() const { return (this == NULL) ? DEFAULT_FRAME_PERIOD : attotime(0, m_frame_period); };
+ UINT64 frame_number() const { return m_frame_number; }
+ int partial_updates() const { return m_partial_updates_this_frame; }
+
+ // updating
+ bool update_partial(int scanline);
+ void update_now();
+
+ // additional helpers
+ void register_vblank_callback(vblank_state_delegate vblank_callback);
+ bitmap_t *alloc_compatible_bitmap(int width = 0, int height = 0) { return auto_bitmap_alloc(machine(), (width == 0) ? m_width : width, (height == 0) ? m_height : height, format()); }
+
+ // internal to the video system
+ bool update_quads();
+ void update_burnin();
+
+ // globally accessible constants
+ static const int DEFAULT_FRAME_RATE = 60;
+ static const attotime DEFAULT_FRAME_PERIOD;
+
+private:
+ // device-level overrides
+ virtual bool device_validity_check(emu_options &options, const game_driver &driver) const;
+ virtual void device_start();
+ virtual void device_stop();
+ virtual void device_post_load();
+
+ // internal helpers
+ void set_container(render_container &container) { m_container = &container; }
+ void realloc_screen_bitmaps();
+
+ static TIMER_CALLBACK( static_vblank_begin_callback ) { reinterpret_cast<screen_device *>(ptr)->vblank_begin_callback(); }
+ void vblank_begin_callback();
+
+ static TIMER_CALLBACK( static_vblank_end_callback ) { reinterpret_cast<screen_device *>(ptr)->vblank_end_callback(); }
+ void vblank_end_callback();
+
+ static TIMER_CALLBACK( static_scanline0_callback ) { reinterpret_cast<screen_device *>(ptr)->scanline0_callback(); }
+public: // temporary
+ void scanline0_callback();
+private:
+
+ static TIMER_CALLBACK( static_scanline_update_callback ) { reinterpret_cast<screen_device *>(ptr)->scanline_update_callback(param); }
+ void scanline_update_callback(int scanline);
+
+ void finalize_burnin();
+ void load_effect_overlay(const char *filename);
+
+ // inline configuration data
+ screen_type_enum m_type; // type of screen
+ bool m_oldstyle_vblank_supplied; // MCFG_SCREEN_VBLANK_TIME macro used
+ attoseconds_t m_refresh; // default refresh period
+ attoseconds_t m_vblank; // duration of a VBLANK
+ bitmap_format m_format; // bitmap format
+ float m_xoffset, m_yoffset; // default X/Y offsets
+ float m_xscale, m_yscale; // default X/Y scale factor
+ screen_update_func m_screen_update; // screen update callback
+ screen_eof_func m_screen_eof; // screen eof callback
+
+ // internal state
+ render_container * m_container; // pointer to our container
+
+ // dimensions
+ int m_width; // current width (HTOTAL)
+ int m_height; // current height (VTOTAL)
+ rectangle m_visarea; // current visible area (HBLANK end/start, VBLANK end/start)
+
+ // textures and bitmaps
+ render_texture * m_texture[2]; // 2x textures for the screen bitmap
+ bitmap_t * m_bitmap[2]; // 2x bitmaps for rendering
+ bitmap_t * m_burnin; // burn-in bitmap
+ UINT8 m_curbitmap; // current bitmap index
+ UINT8 m_curtexture; // current texture index
+ INT32 m_texture_format; // texture format of bitmap for this screen
+ bool m_changed; // has this bitmap changed?
+ INT32 m_last_partial_scan; // scanline of last partial update
+ bitmap_t * m_screen_overlay_bitmap; // screen overlay bitmap
+
+ // screen timing
+ attoseconds_t m_frame_period; // attoseconds per frame
+ attoseconds_t m_scantime; // attoseconds per scanline
+ attoseconds_t m_pixeltime; // attoseconds per pixel
+ attoseconds_t m_vblank_period; // attoseconds per VBLANK period
+ attotime m_vblank_start_time; // time of last VBLANK start
+ attotime m_vblank_end_time; // time of last VBLANK end
+ emu_timer * m_vblank_begin_timer; // timer to signal VBLANK start
+ emu_timer * m_vblank_end_timer; // timer to signal VBLANK end
+ emu_timer * m_scanline0_timer; // scanline 0 timer
+ emu_timer * m_scanline_timer; // scanline timer
+ UINT64 m_frame_number; // the current frame number
+ UINT32 m_partial_updates_this_frame;// partial update counter this frame
+
+ class callback_item
+ {
+ public:
+ callback_item(vblank_state_delegate callback)
+ : m_next(NULL),
+ m_callback(callback) { }
+ callback_item *next() const { return m_next; }
+
+ callback_item * m_next;
+ vblank_state_delegate m_callback;
+ };
+ simple_list<callback_item> m_callback_list; // list of VBLANK callbacks
+};
+
+// device type definition
+extern const device_type SCREEN;
+
+
+
+//**************************************************************************
+// SCREEN DEVICE CONFIGURATION MACROS
+//**************************************************************************
+
+#define SCREEN_UPDATE_NAME(name) screen_update_##name
+#define SCREEN_UPDATE(name) UINT32 SCREEN_UPDATE_NAME(name)(screen_device *screen, bitmap_t *bitmap, const rectangle *cliprect)
+#define SCREEN_UPDATE_CALL(name) SCREEN_UPDATE_NAME(name)(screen, bitmap, cliprect)
+
+#define SCREEN_EOF_NAME(name) screen_eof_##name
+#define SCREEN_EOF(name) void SCREEN_EOF_NAME(name)(screen_device *screen, running_machine &machine)
+#define SCREEN_EOF_CALL(name) SCREEN_EOF_NAME(name)(screen, machine)
+
+#define screen_eof_0 NULL
+
+#define MCFG_SCREEN_ADD(_tag, _type) \
+ MCFG_DEVICE_ADD(_tag, SCREEN, 0) \
+ MCFG_SCREEN_TYPE(_type) \
+
+#define MCFG_SCREEN_MODIFY(_tag) \
+ MCFG_DEVICE_MODIFY(_tag)
+
+#define MCFG_SCREEN_FORMAT(_format) \
+ screen_device::static_set_format(*device, _format); \
+
+#define MCFG_SCREEN_TYPE(_type) \
+ screen_device::static_set_type(*device, SCREEN_TYPE_##_type); \
+
+#define MCFG_SCREEN_RAW_PARAMS(_pixclock, _htotal, _hbend, _hbstart, _vtotal, _vbend, _vbstart) \
+ screen_device::static_set_raw(*device, _pixclock, _htotal, _hbend, _hbstart, _vtotal, _vbend, _vbstart);
+
+#define MCFG_SCREEN_REFRESH_RATE(_rate) \
+ screen_device::static_set_refresh(*device, HZ_TO_ATTOSECONDS(_rate)); \
+
+#define MCFG_SCREEN_VBLANK_TIME(_time) \
+ screen_device::static_set_vblank_time(*device, _time); \
+
+#define MCFG_SCREEN_SIZE(_width, _height) \
+ screen_device::static_set_size(*device, _width, _height); \
+
+#define MCFG_SCREEN_VISIBLE_AREA(_minx, _maxx, _miny, _maxy) \
+ screen_device::static_set_visarea(*device, _minx, _maxx, _miny, _maxy); \
+
+#define MCFG_SCREEN_DEFAULT_POSITION(_xscale, _xoffs, _yscale, _yoffs) \
+ screen_device::static_set_default_position(*device, _xscale, _xoffs, _yscale, _yoffs); \
+
+#define MCFG_SCREEN_UPDATE(_func) \
+ screen_device::static_set_screen_update(*device, SCREEN_UPDATE_NAME(_func)); \
+
+#define MCFG_SCREEN_EOF(_func) \
+ screen_device::static_set_screen_eof(*device, SCREEN_EOF_NAME(_func)); \
+
+
+#endif /* __SCREEN_H__ */
diff --git a/trunk/src/emu/softlist.c b/trunk/src/emu/softlist.c
new file mode 100644
index 00000000000..157c6d1e4fa
--- /dev/null
+++ b/trunk/src/emu/softlist.c
@@ -0,0 +1,1858 @@
+/***************************************************************************
+
+ softlist.c
+
+ Software list construction helpers.
+
+
+***************************************************************************/
+
+#include "emu.h"
+#include "pool.h"
+#include "emuopts.h"
+#include "hash.h"
+#include "softlist.h"
+
+#include <ctype.h>
+
+typedef tagmap_t<software_info *> softlist_map;
+
+/***************************************************************************
+ EXPAT INTERFACES
+***************************************************************************/
+
+/*-------------------------------------------------
+ expat_malloc/expat_realloc/expat_free -
+ wrappers for memory allocation functions so
+ that they pass through out memory tracking
+ systems
+-------------------------------------------------*/
+
+static void *expat_malloc(size_t size)
+{
+ return global_alloc_array_clear(UINT8,size);
+}
+
+static void *expat_realloc(void *ptr, size_t size)
+{
+ if (ptr) global_free(ptr);
+ return global_alloc_array_clear(UINT8,size);
+}
+
+static void expat_free(void *ptr)
+{
+ global_free(ptr);
+}
+
+
+/*-------------------------------------------------
+ parse_error
+-------------------------------------------------*/
+
+INLINE void ATTR_PRINTF(2,3) parse_error(parse_state *state, const char *fmt, ...)
+{
+ char buf[256];
+ va_list va;
+
+ if (state->error_proc)
+ {
+ va_start(va, fmt);
+ vsnprintf(buf, ARRAY_LENGTH(buf), fmt, va);
+ va_end(va);
+ (*state->error_proc)(buf);
+ }
+}
+
+
+/*-------------------------------------------------
+ unknown_tag
+-------------------------------------------------*/
+
+INLINE void unknown_tag(parse_state *state, const char *tagname)
+{
+ parse_error(state, "[%lu:%lu]: Unknown tag: %s\n",
+ XML_GetCurrentLineNumber(state->parser),
+ XML_GetCurrentColumnNumber(state->parser),
+ tagname);
+}
+
+
+
+/*-------------------------------------------------
+ unknown_attribute
+-------------------------------------------------*/
+
+INLINE void unknown_attribute(parse_state *state, const char *attrname)
+{
+ parse_error(state, "[%lu:%lu]: Unknown attribute: %s\n",
+ XML_GetCurrentLineNumber(state->parser),
+ XML_GetCurrentColumnNumber(state->parser),
+ attrname);
+}
+
+
+
+/*-------------------------------------------------
+ unknown_attribute_value
+-------------------------------------------------*/
+
+INLINE void unknown_attribute_value(parse_state *state,
+ const char *attrname, const char *attrvalue)
+{
+ parse_error(state, "[%lu:%lu]: Unknown attribute value: %s\n",
+ XML_GetCurrentLineNumber(state->parser),
+ XML_GetCurrentColumnNumber(state->parser),
+ attrvalue);
+}
+
+
+/*-------------------------------------------------
+ software_name_split
+ helper; splits a software_list:software:part
+ string into separate software_list, software,
+ and part strings.
+
+ str1:str2:str3 => swlist_name - str1, swname - str2, swpart - str3
+ str1:str2 => swlist_name - NULL, swname - str1, swpart - str2
+ str1 => swlist_name - NULL, swname - str1, swpart - NULL
+
+ swlist_namem, swnane and swpart will be global_alloc'ed
+ from the global pool. So they should be global_free'ed
+ when they are not used anymore.
+-------------------------------------------------*/
+
+#define global_strdup(s) strcpy(global_alloc_array(char, strlen(s) + 1), s)
+
+static void software_name_split(const char *swlist_swname, char **swlist_name, char **swname, char **swpart )
+{
+ const char *split_1st_loc = strchr( swlist_swname, ':' );
+ const char *split_2nd_loc = ( split_1st_loc ) ? strchr( split_1st_loc + 1, ':' ) : NULL;
+
+ *swlist_name = NULL;
+ *swname = NULL;
+ *swpart = NULL;
+
+ if ( split_1st_loc )
+ {
+ if ( split_2nd_loc )
+ {
+ int size = split_1st_loc - swlist_swname;
+ *swlist_name = global_alloc_array_clear(char,size+1);
+ memcpy( *swlist_name, swlist_swname, size );
+
+ size = split_2nd_loc - ( split_1st_loc + 1 );
+ *swname = global_alloc_array_clear(char,size+1);
+ memcpy( *swname, split_1st_loc + 1, size );
+
+ size = strlen( swlist_swname ) - ( split_2nd_loc + 1 - swlist_swname );
+ *swpart = global_alloc_array_clear(char,size+1);
+ memcpy( *swpart, split_2nd_loc + 1, size );
+ }
+ else
+ {
+ int size = split_1st_loc - swlist_swname;
+ *swname = global_alloc_array_clear(char,size+1);
+ memcpy( *swname, swlist_swname, size );
+
+ size = strlen( swlist_swname ) - ( split_1st_loc + 1 - swlist_swname );
+ *swpart = global_alloc_array_clear(char,size+1);
+ memcpy( *swpart, split_1st_loc + 1, size );
+ }
+ }
+ else
+ {
+ *swname = global_strdup(swlist_swname);
+ }
+}
+
+
+/*-------------------------------------------------
+ add_rom_entry
+-------------------------------------------------*/
+
+static void add_rom_entry(software_list *swlist, const char *name, const char *hashdata, UINT32 offset, UINT32 length, UINT32 flags)
+{
+ software_part *part = &swlist->softinfo->partdata[swlist->current_part_entry-1];
+ struct rom_entry *entry = &part->romdata[swlist->current_rom_entry];
+
+ entry->_name = name;
+ entry->_hashdata = hashdata;
+ entry->_offset = offset;
+ entry->_length = length;
+ entry->_flags = flags;
+
+ swlist->current_rom_entry += 1;
+
+ if ( swlist->current_rom_entry >= swlist->rom_entries )
+ {
+ struct rom_entry *new_entries;
+
+ swlist->rom_entries += 10;
+ new_entries = (struct rom_entry *)pool_realloc_lib(swlist->pool, part->romdata, swlist->rom_entries * sizeof(struct rom_entry) );
+
+ if ( new_entries )
+ {
+ part->romdata = new_entries;
+ }
+ else
+ {
+ /* Allocation error */
+ swlist->current_rom_entry -= 1;
+ }
+ }
+}
+
+/*-------------------------------------------------
+ add_feature
+-------------------------------------------------*/
+
+static void add_feature(software_list *swlist, char *feature_name, char *feature_value)
+{
+ software_part *part = &swlist->softinfo->partdata[swlist->current_part_entry-1];
+ feature_list *new_entry;
+
+ /* First allocate the new entry */
+ new_entry = (feature_list *)pool_malloc_lib(swlist->pool, sizeof(feature_list) );
+
+ if ( new_entry )
+ {
+ new_entry->next = NULL;
+ new_entry->name = feature_name;
+ new_entry->value = feature_value ? feature_value : feature_name;
+
+ /* Add new feature to end of feature list */
+ if ( part->featurelist )
+ {
+ feature_list *list = part->featurelist;
+ while ( list->next != NULL )
+ {
+ list = list->next;
+ }
+ list->next = new_entry;
+ }
+ else
+ {
+ part->featurelist = new_entry;
+ }
+ }
+ else
+ {
+ /* Unable to allocate memory */
+ }
+}
+
+/*-------------------------------------------------
+ add_info (same as add_feature, but its target
+ is softinfo->shared_info)
+ -------------------------------------------------*/
+
+static void add_info(software_list *swlist, char *feature_name, char *feature_value)
+{
+ software_info *info = swlist->softinfo;
+ feature_list *new_entry;
+
+ /* First allocate the new entry */
+ new_entry = (feature_list *)pool_malloc_lib(swlist->pool, sizeof(feature_list) );
+
+ if ( new_entry )
+ {
+ new_entry->next = NULL;
+ new_entry->name = feature_name;
+ new_entry->value = feature_value ? feature_value : feature_name;
+
+ /* Add new feature to end of feature list */
+ if ( info->shared_info )
+ {
+ feature_list *list = info->shared_info;
+ while ( list->next != NULL )
+ {
+ list = list->next;
+ }
+ list->next = new_entry;
+ }
+ else
+ {
+ info->shared_info = new_entry;
+ }
+ }
+ else
+ {
+ /* Unable to allocate memory */
+ }
+}
+
+/*-------------------------------------------------
+ add_software_part
+-------------------------------------------------*/
+
+static void add_software_part(software_list *swlist, const char *name, const char *interface)
+{
+ software_part *part = &swlist->softinfo->partdata[swlist->current_part_entry];
+
+ part->name = name;
+ part->interface_ = interface;
+ part->featurelist = NULL;
+ part->romdata = NULL;
+
+ swlist->current_part_entry += 1;
+
+ if ( swlist->current_part_entry >= swlist->part_entries )
+ {
+ software_part *new_parts;
+
+ swlist->part_entries += 2;
+ new_parts = (software_part *)pool_realloc_lib(swlist->pool, swlist->softinfo->partdata, swlist->part_entries * sizeof(software_part) );
+
+ if ( new_parts )
+ {
+ swlist->softinfo->partdata = new_parts;
+ }
+ else
+ {
+ /* Allocation error */
+ swlist->current_part_entry -= 1;
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ start_handler
+-------------------------------------------------*/
+
+static void start_handler(void *data, const char *tagname, const char **attributes)
+{
+ software_list *swlist = (software_list *) data;
+ char **text_dest;
+
+ switch(swlist->state.pos)
+ {
+ case POS_ROOT:
+ if (!strcmp(tagname, "softwarelist"))
+ {
+ for( ; attributes[0]; attributes += 2 )
+ {
+ if ( ! strcmp(attributes[0], "name" ) )
+ {
+ }
+ if ( ! strcmp(attributes[0], "description" ) )
+ {
+ swlist->description = (const char *)pool_malloc_lib(swlist->pool, (strlen(attributes[1]) + 1) * sizeof(char));
+ if (!swlist->description)
+ return;
+
+ strcpy((char *)swlist->description, attributes[1]);
+ }
+ }
+ }
+ else
+ {
+ unknown_tag(&swlist->state, tagname);
+ }
+ break;
+
+ case POS_MAIN:
+ if ( !strcmp( tagname, "software" ) )
+ {
+ const char *name = NULL;
+ const char *parent = NULL;
+ const char *supported = NULL;
+
+ for ( ; attributes[0]; attributes += 2 )
+ {
+ if ( !strcmp( attributes[0], "name" ) )
+ {
+ name = attributes[1];
+ }
+ if ( !strcmp( attributes[0], "cloneof" ) )
+ {
+ parent = attributes[1];
+ }
+ if ( !strcmp( attributes[0], "supported" ) )
+ {
+ supported = attributes[1];
+ }
+ }
+
+ if ( name )
+ {
+ struct software_info *elem = (struct software_info *)pool_malloc_lib(swlist->pool,sizeof(struct software_info));
+
+ if ( !elem )
+ return;
+
+ /* Clear element and add element to list */
+ memset(elem,0,sizeof(struct software_info));
+
+ /* Allocate space to hold the shortname and copy the short name */
+ elem->shortname = (const char*)pool_malloc_lib(swlist->pool, ( strlen( name ) + 1 ) * sizeof(char) );
+
+ if ( ! elem->shortname )
+ return;
+
+ strcpy( (char *)elem->shortname, name );
+
+ /* Allocate space to hold the parentname and copy the parent name */
+ if (parent)
+ {
+ elem->parentname = (const char*)pool_malloc_lib(swlist->pool, ( strlen(parent) + 1 ) * sizeof(char) );
+ strcpy((char *)elem->parentname, parent);
+ }
+
+ /* Allocate initial space to hold part information */
+ swlist->part_entries = 2;
+ swlist->current_part_entry = 0;
+ elem->partdata = (software_part *)pool_malloc_lib(swlist->pool, swlist->part_entries * sizeof(software_part) );
+ if ( !elem->partdata )
+ return;
+ elem->shared_info = (feature_list *)pool_malloc_lib(swlist->pool, sizeof(feature_list) );
+ if ( !elem->shared_info )
+ return;
+ else
+ {
+ elem->shared_info->next = (feature_list *)pool_malloc_lib(swlist->pool, sizeof(feature_list) );
+ elem->shared_info->next = NULL;
+ elem->shared_info->name = NULL;
+ elem->shared_info->value = NULL;
+ }
+
+ /* Handle the supported flag */
+ elem->supported = SOFTWARE_SUPPORTED_YES;
+ if ( supported && ! strcmp( supported, "partial" ) )
+ elem->supported = SOFTWARE_SUPPORTED_PARTIAL;
+ if ( supported && ! strcmp( supported, "no" ) )
+ elem->supported = SOFTWARE_SUPPORTED_NO;
+
+ /* Add the entry to the end of the list */
+ if ( swlist->software_info_list == NULL )
+ {
+ swlist->software_info_list = elem;
+ swlist->current_software_info = elem;
+ }
+ else
+ {
+ swlist->current_software_info->next = elem;
+ swlist->current_software_info = elem;
+ }
+
+ /* Quick lookup for setting software information */
+ swlist->softinfo = swlist->current_software_info;
+ }
+ else
+ {
+ swlist->softinfo = NULL;
+ }
+ }
+ else
+ {
+ unknown_tag(&swlist->state, tagname);
+ }
+ break;
+
+ case POS_SOFT:
+ text_dest = NULL;
+
+ if (!strcmp(tagname, "description"))
+ text_dest = (char **) &swlist->softinfo->longname;
+ else if (!strcmp(tagname, "year"))
+ text_dest = (char **) &swlist->softinfo->year;
+ else if (!strcmp(tagname, "publisher"))
+ text_dest = (char **) &swlist->softinfo->publisher;
+ else if (!strcmp(tagname, "info"))
+ {
+ // the "info" field (containing info about actual developers, etc.) is not currently stored.
+ // full support will be added, but for the moment frontend have to get this info from the xml directly
+ }
+ else if (!strcmp(tagname, "sharedfeat"))
+ {
+ const char *str_feature_name = NULL;
+ const char *str_feature_value = NULL;
+
+ for ( ; attributes[0]; attributes += 2 )
+ {
+ if ( !strcmp( attributes[0], "name" ) )
+ str_feature_name = attributes[1];
+
+ if ( !strcmp( attributes[0], "value" ) )
+ str_feature_value = attributes[1];
+ }
+
+ /* Prepare for adding feature to feature list */
+ if ( str_feature_name && swlist->softinfo )
+ {
+ char *name = (char *)pool_malloc_lib(swlist->pool, ( strlen( str_feature_name ) + 1 ) * sizeof(char) );
+ char *value = NULL;
+
+ if ( !name )
+ return;
+
+ strcpy( name, str_feature_name );
+
+ if ( str_feature_value )
+ {
+ value = (char *)pool_malloc_lib(swlist->pool, ( strlen( str_feature_value ) + 1 ) * sizeof(char) );
+
+ if ( !value )
+ return;
+
+ strcpy( value, str_feature_value );
+ }
+
+ add_info( swlist, name, value );
+ }
+ }
+ else if ( !strcmp(tagname, "part" ) )
+ {
+ const char *str_name = NULL;
+ const char *str_interface = NULL;
+
+ for ( ; attributes[0]; attributes += 2 )
+ {
+ if ( !strcmp( attributes[0], "name" ) )
+ str_name = attributes[1];
+
+ if ( !strcmp( attributes[0], "interface" ) )
+ str_interface = attributes[1];
+ }
+
+ if ( str_name && str_interface )
+ {
+ if ( swlist->softinfo )
+ {
+ char *name = (char *)pool_malloc_lib(swlist->pool, ( strlen( str_name ) + 1 ) * sizeof(char) );
+ char *interface = (char *)pool_malloc_lib(swlist->pool, ( strlen( str_interface ) + 1 ) * sizeof(char) );
+
+ if ( !name || !interface )
+ return;
+
+ strcpy( name, str_name );
+ strcpy( interface, str_interface );
+
+ add_software_part( swlist, name, interface );
+
+ /* Allocate initial space to hold the rom information */
+ swlist->rom_entries = 3;
+ swlist->current_rom_entry = 0;
+ swlist->softinfo->partdata[swlist->current_part_entry-1].romdata = (struct rom_entry *)pool_malloc_lib(swlist->pool, swlist->rom_entries * sizeof(struct rom_entry));
+ if ( ! swlist->softinfo->partdata[swlist->current_part_entry-1].romdata )
+ return;
+ }
+ }
+ else
+ {
+ /* Incomplete/incorrect part definition */
+ }
+ }
+ else
+ unknown_tag(&swlist->state, tagname);
+
+ if (text_dest && swlist->softinfo)
+ swlist->state.text_dest = text_dest;
+ break;
+
+ case POS_PART:
+ if (!strcmp(tagname, "dataarea"))
+ {
+ const char *str_name = NULL;
+ const char *str_size = NULL;
+
+ for ( ; attributes[0]; attributes += 2 )
+ {
+ if ( !strcmp( attributes[0], "name" ) )
+ str_name = attributes[1];
+
+ if ( !strcmp( attributes[0], "size") )
+ str_size = attributes[1];
+ }
+ if ( str_name && str_size )
+ {
+ if ( swlist->softinfo )
+ {
+ UINT32 length = strtol( str_size, NULL, 0 );
+ char *s = (char *)pool_malloc_lib(swlist->pool, ( strlen( str_name ) + 1 ) * sizeof(char) );
+
+ if ( !s )
+ return;
+
+ strcpy( s, str_name );
+
+ /* ROM_REGION( length, "name", flags ) */
+ add_rom_entry( swlist, s, NULL, 0, length, ROMENTRYTYPE_REGION );
+ }
+ }
+ else
+ {
+ /* Missing dataarea name or size */
+ }
+ }
+ else if (!strcmp(tagname, "diskarea"))
+ {
+ const char *str_name = NULL;
+
+ for ( ; attributes[0]; attributes += 2 )
+ {
+ if ( !strcmp( attributes[0], "name" ) )
+ str_name = attributes[1];
+ }
+ if ( str_name )
+ {
+ if ( swlist->softinfo )
+ {
+ char *s = (char *)pool_malloc_lib(swlist->pool, ( strlen( str_name ) + 1 ) * sizeof(char) );
+
+ if ( !s )
+ return;
+
+ strcpy( s, str_name );
+
+ /* ROM_REGION( length, "name", flags ) */
+ add_rom_entry( swlist, s, NULL, 0, 1, ROMENTRYTYPE_REGION | ROMREGION_DATATYPEDISK);
+ }
+ }
+ else
+ {
+ /* Missing dataarea name or size */
+ }
+ }
+ else if ( !strcmp(tagname, "feature") )
+ {
+ const char *str_feature_name = NULL;
+ const char *str_feature_value = NULL;
+
+ for ( ; attributes[0]; attributes += 2 )
+ {
+ if ( !strcmp( attributes[0], "name" ) )
+ str_feature_name = attributes[1];
+
+ if ( !strcmp( attributes[0], "value" ) )
+ str_feature_value = attributes[1];
+ }
+
+ /* Prepare for adding feature to feature list */
+ if ( str_feature_name && swlist->softinfo )
+ {
+ char *name = (char *)pool_malloc_lib(swlist->pool, ( strlen( str_feature_name ) + 1 ) * sizeof(char) );
+ char *value = NULL;
+
+ if ( !name )
+ return;
+
+ strcpy( name, str_feature_name );
+
+ if ( str_feature_value )
+ {
+ value = (char *)pool_malloc_lib(swlist->pool, ( strlen( str_feature_value ) + 1 ) * sizeof(char) );
+
+ if ( !value )
+ return;
+
+ strcpy( value, str_feature_value );
+ }
+
+ add_feature( swlist, name, value );
+ }
+ }
+ else
+ unknown_tag( &swlist->state, tagname );
+ break;
+
+ case POS_DATA:
+ if (!strcmp(tagname, "rom"))
+ {
+ const char *str_name = NULL;
+ const char *str_size = NULL;
+ const char *str_crc = NULL;
+ const char *str_sha1 = NULL;
+ const char *str_offset = NULL;
+ const char *str_value = NULL;
+ const char *str_status = NULL;
+ const char *str_loadflag = NULL;
+
+ for ( ; attributes[0]; attributes += 2 )
+ {
+ if ( !strcmp( attributes[0], "name" ) )
+ str_name = attributes[1];
+ if ( !strcmp( attributes[0], "size" ) )
+ str_size = attributes[1];
+ if ( !strcmp( attributes[0], "crc" ) )
+ str_crc = attributes[1];
+ if ( !strcmp( attributes[0], "sha1" ) )
+ str_sha1 = attributes[1];
+ if ( !strcmp( attributes[0], "offset" ) )
+ str_offset = attributes[1];
+ if ( !strcmp( attributes[0], "value" ) )
+ str_value = attributes[1];
+ if ( !strcmp( attributes[0], "status" ) )
+ str_status = attributes[1];
+ if ( !strcmp( attributes[0], "loadflag" ) )
+ str_loadflag = attributes[1];
+ }
+ if ( swlist->softinfo )
+ {
+ if ( str_size && str_offset )
+ {
+ UINT32 length = strtol( str_size, NULL, 0 );
+ UINT32 offset = strtol( str_offset, NULL, 0 );
+
+ if ( str_loadflag && !strcmp(str_loadflag, "reload") )
+ {
+ /* Handle 'reload' loadflag */
+ add_rom_entry( swlist, NULL, NULL, offset, length, ROMENTRYTYPE_RELOAD | ROM_INHERITFLAGS );
+ }
+ else if ( str_loadflag && !strcmp(str_loadflag, "reload_plain") )
+ {
+ /* Handle 'reload_plain' loadflag */
+ add_rom_entry( swlist, NULL, NULL, offset, length, ROMENTRYTYPE_RELOAD);
+ }
+ else if ( str_loadflag && !strcmp(str_loadflag, "continue") )
+ {
+ /* Handle 'continue' loadflag */
+ add_rom_entry( swlist, NULL, NULL, offset, length, ROMENTRYTYPE_CONTINUE | ROM_INHERITFLAGS );
+ }
+ else if ( str_loadflag && !strcmp(str_loadflag, "fill") )
+ {
+ /* Handle 'fill' loadflag */
+ add_rom_entry( swlist, NULL, (const char*)(FPTR)atoi(str_value), offset, length, ROMENTRYTYPE_FILL );
+ }
+ else
+ {
+ if ( str_name && str_crc && str_sha1 )
+ {
+ char *s_name = (char *)pool_malloc_lib(swlist->pool, ( strlen( str_name ) + 1 ) * sizeof(char) );
+ char *hashdata = (char *)pool_malloc_lib( swlist->pool, sizeof(char) * ( strlen(str_crc) + strlen(str_sha1) + 7 + 4 ) );
+ int baddump = ( str_status && !strcmp(str_status, "baddump") ) ? 1 : 0;
+ int nodump = ( str_status && !strcmp(str_status, "nodump" ) ) ? 1 : 0;
+ int romflags = 0;
+
+ if ( !s_name || !hashdata )
+ return;
+
+ strcpy( s_name, str_name );
+ sprintf( hashdata, "%c%s%c%s%s", hash_collection::HASH_CRC, str_crc, hash_collection::HASH_SHA1, str_sha1, ( nodump ? NO_DUMP : ( baddump ? BAD_DUMP : "" ) ) );
+
+ /* Handle loadflag attribute */
+ if ( str_loadflag && !strcmp(str_loadflag, "load16_word_swap") )
+ romflags = ROM_GROUPWORD | ROM_REVERSE;
+ else if ( str_loadflag && !strcmp(str_loadflag, "load16_byte") )
+ romflags = ROM_SKIP(1);
+ else if ( str_loadflag && !strcmp(str_loadflag, "load32_word_swap") )
+ romflags = ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2);
+ else if ( str_loadflag && !strcmp(str_loadflag, "load32_word") )
+ romflags = ROM_GROUPWORD | ROM_SKIP(2);
+
+ /* ROM_LOAD( name, offset, length, hash ) */
+ add_rom_entry( swlist, s_name, hashdata, offset, length, ROMENTRYTYPE_ROM | romflags );
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Missing name, size, crc, sha1, or offset */
+ }
+ }
+ else
+ if (!strcmp(tagname, "disk"))
+ {
+ const char *str_name = NULL;
+ const char *str_sha1 = NULL;
+ const char *str_status = NULL;
+ const char *str_writeable = NULL;
+
+ for ( ; attributes[0]; attributes += 2 )
+ {
+ if ( !strcmp( attributes[0], "name" ) )
+ str_name = attributes[1];
+ if ( !strcmp( attributes[0], "sha1" ) )
+ str_sha1 = attributes[1];
+ if ( !strcmp( attributes[0], "status" ) )
+ str_status = attributes[1];
+ if ( !strcmp( attributes[0], "writeable" ) )
+ str_writeable = attributes[1];
+ }
+ if ( swlist->softinfo )
+ {
+ if ( str_name && str_sha1 )
+ {
+ char *s_name = (char *)pool_malloc_lib(swlist->pool, ( strlen( str_name ) + 1 ) * sizeof(char) );
+ char *hashdata = (char *)pool_malloc_lib( swlist->pool, sizeof(char) * ( strlen(str_sha1) + 7 + 4 ) );
+ int baddump = ( str_status && !strcmp(str_status, "baddump") ) ? 1 : 0;
+ int nodump = ( str_status && !strcmp(str_status, "nodump" ) ) ? 1 : 0;
+ int writeable = ( str_writeable && !strcmp(str_writeable, "yes" ) ) ? 1 : 0;
+
+ if ( !s_name || !hashdata )
+ return;
+
+ strcpy( s_name, str_name );
+ sprintf( hashdata, "%c%s%s", hash_collection::HASH_SHA1, str_sha1, ( nodump ? NO_DUMP : ( baddump ? BAD_DUMP : "" ) ) );
+
+ add_rom_entry( swlist, s_name, hashdata, 0, 0, ROMENTRYTYPE_ROM | (writeable ? DISK_READWRITE : DISK_READONLY ) );
+ }
+ }
+ }
+ else
+ unknown_tag(&swlist->state, tagname);
+ break;
+ }
+ swlist->state.pos = (softlist_parse_position) (swlist->state.pos + 1);
+}
+
+/*-------------------------------------------------
+ end_handler
+-------------------------------------------------*/
+
+static void end_handler(void *data, const char *name)
+{
+ software_list *swlist = (software_list *) data;
+ swlist->state.text_dest = NULL;
+
+ swlist->state.pos = (softlist_parse_position) (swlist->state.pos - 1);
+ switch(swlist->state.pos)
+ {
+ case POS_ROOT:
+ break;
+
+ case POS_SOFT:
+ if ( ! strcmp( name, "part" ) && swlist->softinfo )
+ {
+ /* ROM_END */
+ add_rom_entry( swlist, NULL, NULL, 0, 0, ROMENTRYTYPE_END );
+ }
+ break;
+
+ case POS_MAIN:
+ if ( swlist->softinfo )
+ {
+ add_software_part( swlist, NULL, NULL );
+ }
+ break;
+
+ case POS_PART:
+ /* Add shared_info inherited from the software_info level, if any */
+ if ( swlist->softinfo && swlist->softinfo->shared_info )
+ {
+ feature_list *list = swlist->softinfo->shared_info;
+
+ while( list->next )
+ {
+ add_feature( swlist, list->next->name, list->next->value );
+ list = list->next;
+ }
+ }
+ break;
+
+ case POS_DATA:
+ break;
+ }
+}
+
+
+/*-------------------------------------------------
+ data_handler
+-------------------------------------------------*/
+
+static void data_handler(void *data, const XML_Char *s, int len)
+{
+ software_list *swlist = (software_list *) data;
+ int text_len;
+ char *text;
+
+ if (swlist->state.text_dest)
+ {
+ text = *swlist->state.text_dest;
+
+ text_len = text ? strlen(text) : 0;
+ text = (char*)pool_realloc_lib(swlist->pool, text, text_len + len + 1);
+ if (!text)
+ return;
+
+ memcpy(&text[text_len], s, len);
+ text[text_len + len] = '\0';
+ *swlist->state.text_dest = text;
+ }
+}
+
+
+/*-------------------------------------------------
+ software_list_get_count
+ -------------------------------------------------*/
+
+static int software_list_get_count(software_list *swlist)
+{
+ int count = 0;
+
+ for (software_info *swinfo = software_list_find(swlist, "*", NULL); swinfo != NULL; swinfo = software_list_find(swlist, "*", swinfo))
+ count++;
+
+ return count;
+}
+
+
+/*-------------------------------------------------
+ software_get_clone - retrive name string of the
+ parent software, if any
+ -------------------------------------------------*/
+
+const char *software_get_clone(emu_options &options, char *swlist, const char *swname)
+{
+ software_list *software_list_ptr = software_list_open(options, swlist, FALSE, NULL);
+ const char *retval = NULL;
+ if (software_list_ptr)
+ {
+ software_info *tmp = software_list_find(software_list_ptr, swname, NULL);
+ retval = core_strdup(tmp->parentname);
+ software_list_close(software_list_ptr);
+ }
+
+ return retval;
+}
+
+
+/*-------------------------------------------------
+ software_get_support - retrive support state of
+ the software
+ -------------------------------------------------*/
+
+UINT32 software_get_support(emu_options &options, char *swlist, const char *swname)
+{
+ software_list *software_list_ptr = software_list_open(options, swlist, FALSE, NULL);
+ UINT32 retval = 0;
+
+ if (software_list_ptr)
+ {
+ software_info *tmp = software_list_find(software_list_ptr, swname, NULL);
+ retval = tmp->supported;
+ software_list_close(software_list_ptr);
+ }
+
+ return retval;
+}
+
+
+/*-------------------------------------------------
+ software_list_parse
+-------------------------------------------------*/
+
+void software_list_parse(software_list *swlist,
+ void (*error_proc)(const char *message),
+ void *param)
+{
+ char buf[1024];
+ UINT32 len;
+ XML_Memory_Handling_Suite memcallbacks;
+
+ swlist->file->seek(0, SEEK_SET);
+
+ memset(&swlist->state, 0, sizeof(swlist->state));
+ swlist->state.error_proc = error_proc;
+ swlist->state.param = param;
+
+ /* create the XML parser */
+ memcallbacks.malloc_fcn = expat_malloc;
+ memcallbacks.realloc_fcn = expat_realloc;
+ memcallbacks.free_fcn = expat_free;
+ swlist->state.parser = XML_ParserCreate_MM(NULL, &memcallbacks, NULL);
+ if (!swlist->state.parser)
+ goto done;
+
+ XML_SetUserData(swlist->state.parser, swlist);
+ XML_SetElementHandler(swlist->state.parser, start_handler, end_handler);
+ XML_SetCharacterDataHandler(swlist->state.parser, data_handler);
+
+ while(!swlist->state.done)
+ {
+ len = swlist->file->read(buf, sizeof(buf));
+ swlist->state.done = swlist->file->eof();
+ if (XML_Parse(swlist->state.parser, buf, len, swlist->state.done) == XML_STATUS_ERROR)
+ {
+ parse_error(&swlist->state, "[%lu:%lu]: %s\n",
+ XML_GetCurrentLineNumber(swlist->state.parser),
+ XML_GetCurrentColumnNumber(swlist->state.parser),
+ XML_ErrorString(XML_GetErrorCode(swlist->state.parser)));
+ goto done;
+ }
+ }
+
+done:
+ if (swlist->state.parser)
+ XML_ParserFree(swlist->state.parser);
+ swlist->state.parser = NULL;
+ swlist->current_software_info = swlist->software_info_list;
+ swlist->list_entries = software_list_get_count(swlist);
+}
+
+
+/*-------------------------------------------------
+ software_list_open
+-------------------------------------------------*/
+
+software_list *software_list_open(emu_options &options, const char *listname, int is_preload,
+ void (*error_proc)(const char *message))
+{
+ software_list *swlist = NULL;
+ object_pool *pool = NULL;
+ file_error filerr;
+
+ /* create a pool for this software list file */
+ pool = pool_alloc_lib(error_proc);
+ if (!pool)
+ goto error;
+
+ /* allocate space for this software list file */
+ swlist = (software_list *) pool_malloc_lib(pool, sizeof(*swlist));
+ if (!swlist)
+ goto error;
+
+ /* set up the software_list structure */
+ memset(swlist, 0, sizeof(*swlist));
+ swlist->pool = pool;
+ swlist->error_proc = error_proc;
+
+ /* open a file */
+ swlist->file = global_alloc(emu_file(options.hash_path(), OPEN_FLAG_READ));
+ filerr = swlist->file->open(listname, ".xml");
+ if (filerr != FILERR_NONE)
+ goto error;
+
+ if (is_preload)
+ {
+ software_list_parse(swlist, swlist->error_proc, NULL);
+ swlist->current_software_info = NULL;
+ }
+
+ return swlist;
+
+error:
+ if (swlist != NULL)
+ software_list_close(swlist);
+ return NULL;
+}
+
+
+/*-------------------------------------------------
+ software_list_close
+-------------------------------------------------*/
+
+void software_list_close(software_list *swlist)
+{
+ if (swlist == NULL)
+ return;
+
+ if (swlist->file != NULL)
+ global_free(swlist->file);
+ pool_free_lib(swlist->pool);
+}
+
+
+/*-------------------------------------------------
+ software_list_get_description
+ -------------------------------------------------*/
+
+const char *software_list_get_description(software_list *swlist)
+{
+ return swlist->description;
+}
+
+
+/*-------------------------------------------------
+ software_list_find_by_number
+ -------------------------------------------------*/
+
+INLINE software_info *software_list_find_by_number(software_list *swlist, int number)
+{
+ int length = swlist->list_entries;
+ if (number > length)
+ return NULL;
+
+ software_info *cur_info = software_list_find(swlist, "*", NULL);
+
+ for (int count = 0; count < number; count++)
+ cur_info = software_list_find(swlist, "*", cur_info);
+
+ return cur_info;
+}
+
+
+/*-------------------------------------------------
+ softlist_penalty_compare (borrowed from driver.c)
+ -------------------------------------------------*/
+
+static int softlist_penalty_compare(const char *source, const char *target)
+{
+ int gaps = 1;
+ int last = TRUE;
+
+ /* scan the strings */
+ for ( ; *source && *target; target++)
+ {
+ /* do a case insensitive match */
+ int match = (tolower((UINT8)*source) == tolower((UINT8)*target));
+
+ /* if we matched, advance the source */
+ if (match)
+ source++;
+
+ /* if the match state changed, count gaps */
+ if (match != last)
+ {
+ last = match;
+ if (!match)
+ gaps++;
+ }
+ }
+
+ /* penalty if short string does not completely fit in */
+ for ( ; *source; source++)
+ gaps++;
+
+ /* if we matched perfectly, gaps == 0 */
+ if (gaps == 1 && *source == 0 && *target == 0)
+ gaps = 0;
+
+ return gaps;
+}
+
+
+/*-------------------------------------------------
+ software_list_find_approx_matches
+ -------------------------------------------------*/
+
+void software_list_find_approx_matches(software_list *swlist, const char *name, int matches, software_info **list, const char* interface)
+{
+#undef rand
+
+ int matchnum;
+ int *penalty;
+
+ /* if no name, return */
+ if (name == NULL || name[0] == 0)
+ return;
+
+ /* allocate some temp memory */
+ penalty = global_alloc_array(int, matches);
+
+ /* initialize everyone's states */
+ for (matchnum = 0; matchnum < matches; matchnum++)
+ {
+ penalty[matchnum] = 9999;
+ list[matchnum] = NULL;
+ }
+
+ for (software_info *swinfo = software_list_find(swlist, "*", NULL); swinfo != NULL; swinfo = software_list_find(swlist, "*", swinfo))
+ {
+ int curpenalty, tmp;
+ software_info *candidate = swinfo;
+
+ software_part *part = software_find_part(swinfo, NULL, NULL);
+ if (interface==NULL || !strcmp(interface, part->interface_))
+ {
+
+ /* pick the best match between driver name and description */
+ curpenalty = softlist_penalty_compare(name, candidate->longname);
+ tmp = softlist_penalty_compare(name, candidate->shortname);
+ curpenalty = MIN(curpenalty, tmp);
+
+ /* insert into the sorted table of matches */
+ for (matchnum = matches - 1; matchnum >= 0; matchnum--)
+ {
+ /* stop if we're worse than the current entry */
+ if (curpenalty >= penalty[matchnum])
+ break;
+
+ /* as long as this isn't the last entry, bump this one down */
+ if (matchnum < matches - 1)
+ {
+ penalty[matchnum + 1] = penalty[matchnum];
+ list[matchnum + 1] = list[matchnum];
+ }
+ list[matchnum] = candidate;
+ penalty[matchnum] = curpenalty;
+ }
+ }
+ }
+
+ /* free our temp memory */
+ global_free(penalty);
+}
+
+
+/*-------------------------------------------------
+ software_list_find
+-------------------------------------------------*/
+
+software_info *software_list_find(software_list *swlist, const char *look_for, software_info *prev)
+{
+ if (swlist == NULL)
+ return NULL;
+
+ if (look_for == NULL)
+ return NULL;
+
+ /* If we haven't read in the xml file yet, then do it now */
+ if ( ! swlist->software_info_list )
+ software_list_parse( swlist, swlist->error_proc, NULL );
+
+ for ( prev = prev ? prev->next : swlist->software_info_list; prev; prev = prev->next )
+ {
+ if ( !mame_strwildcmp( look_for, prev->shortname ) )
+ break;
+ }
+
+ return prev;
+}
+
+
+/*-------------------------------------------------
+ software_find_romdata (for validation purposes)
+ -------------------------------------------------*/
+
+static struct rom_entry *software_find_romdata(software_part *swpart, const char *dataname)
+{
+ struct rom_entry *data = swpart ? swpart->romdata : NULL;
+
+ /* If no dataname supplied, then we just return the first entry */
+ if (data)
+ {
+ while(data && data->_name)
+ {
+ if (dataname)
+ {
+ if (!strcmp(dataname, data->_name))
+ {
+ break;
+ }
+ }
+ /* No specific dataname supplied, return the first rom_entry */
+ else
+ break;
+
+ data++;
+ }
+ }
+
+ if (!data->_name)
+ data = NULL;
+
+ return data;
+}
+
+
+/*-------------------------------------------------
+ software_romdata_next (for validation purposes)
+ -------------------------------------------------*/
+
+static struct rom_entry *software_romdata_next(struct rom_entry *romdata)
+{
+ if (romdata && romdata->_name)
+ {
+ romdata++;
+ }
+ else
+ romdata = NULL;
+
+ return romdata;
+}
+
+
+/*-------------------------------------------------
+ software_find_part
+-------------------------------------------------*/
+
+software_part *software_find_part(software_info *sw, const char *partname, const char *interface)
+{
+ software_part *part = sw ? sw->partdata : NULL;
+
+ /* If neither partname nor interface supplied, then we just return the first entry */
+ if ( partname || interface )
+ {
+ while( part && part->name )
+ {
+ if ( partname )
+ {
+ if ( !strcmp(partname, part->name ) )
+ {
+ if ( interface )
+ {
+ if ( !strcmp(interface, part->interface_) )
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* No specific partname supplied, find the first match based on interface */
+ if ( interface )
+ {
+ if ( !strcmp(interface, part->interface_) )
+ {
+ break;
+ }
+ }
+ }
+ part++;
+ }
+ }
+
+ if ( ! part->name )
+ part = NULL;
+
+ return part;
+}
+
+
+/*-------------------------------------------------
+ software_part_next
+-------------------------------------------------*/
+
+software_part *software_part_next(software_part *part)
+{
+ if ( part && part->name )
+ {
+ part++;
+ }
+
+ if ( ! part->name )
+ part = NULL;
+
+ return part;
+}
+
+/*-------------------------------------------------
+ software_display_matches
+-------------------------------------------------*/
+
+void software_display_matches(const device_list &devlist,emu_options &options, const char *interface ,const char *name)
+{
+ // check if there is at least a software list
+ if (devlist.first(SOFTWARE_LIST))
+ {
+ mame_printf_error("\n\"%s\" approximately matches the following\n"
+ "supported software items (best match first):\n\n", name);
+ }
+
+ for (device_t *swlists = devlist.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(options, swlist->list_name[i], FALSE, NULL);
+
+ if (list)
+ {
+ software_info *matches[10] = { 0 };
+ int softnum;
+
+ software_list_parse(list, list->error_proc, NULL);
+ // get the top 5 approximate matches for the selected device interface (i.e. only carts for cartslot, etc.)
+ software_list_find_approx_matches(list, name, ARRAY_LENGTH(matches), matches, interface);
+
+ if (matches[0] != 0)
+ {
+ if (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM)
+ mame_printf_error("* Software list \"%s\" (%s) matches: \n", swlist->list_name[i], software_list_get_description(list));
+ else
+ mame_printf_error("* Compatible software list \"%s\" (%s) matches: \n", swlist->list_name[i], software_list_get_description(list));
+
+ // print them out
+ for (softnum = 0; softnum < ARRAY_LENGTH(matches); softnum++)
+ if (matches[softnum] != NULL)
+ mame_printf_error("%-18s%s\n", matches[softnum]->shortname, matches[softnum]->longname);
+
+ mame_printf_error("\n");
+ }
+ software_list_close(list);
+ }
+ }
+ }
+ }
+}
+
+static void find_software_item(const device_list &devlist, emu_options &options, const device_image_interface *image, const char *path, software_list **software_list_ptr, software_info **software_info_ptr,software_part **software_part_ptr, const char **sw_list_name)
+{
+ char *swlist_name, *swname, *swpart; //, *swname_bckp;
+ *software_list_ptr = NULL;
+ *software_info_ptr = NULL;
+ *software_part_ptr = NULL;
+
+ /* Split full software name into software list name and short software name */
+ software_name_split(path, &swlist_name, &swname, &swpart );
+// swname_bckp = swname;
+
+ const char *interface = image->image_interface();
+
+ if ( swlist_name )
+ {
+ /* Try to open the software list xml file explicitly named by the user */
+ *software_list_ptr = software_list_open( options, swlist_name, FALSE, NULL );
+
+ if ( *software_list_ptr )
+ {
+ *software_info_ptr = software_list_find( *software_list_ptr, swname, NULL );
+
+ if ( *software_info_ptr )
+ {
+ *software_part_ptr = software_find_part( *software_info_ptr, swpart, interface );
+ }
+ }
+ }
+ else
+ {
+ /* Loop through all the software lists named in the driver */
+ for (device_t *swlists = devlist.first(SOFTWARE_LIST); swlists != NULL; swlists = swlists->typenext())
+ {
+ if ( swlists )
+ {
+
+ software_list_config *swlist = (software_list_config *)downcast<const legacy_device_base *>(swlists)->inline_config();
+ UINT32 i = DEVINFO_STR_SWLIST_0;
+
+ while ( ! *software_part_ptr && i <= DEVINFO_STR_SWLIST_MAX )
+ {
+ swlist_name = swlist->list_name[i-DEVINFO_STR_SWLIST_0];
+
+ if ( swlist_name && *swlist_name && (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM))
+ {
+ if ( *software_list_ptr )
+ {
+ software_list_close( *software_list_ptr );
+ }
+
+ *software_list_ptr = software_list_open( options, swlist_name, FALSE, NULL );
+
+ if ( software_list_ptr )
+ {
+ *software_info_ptr = software_list_find( *software_list_ptr, swname, NULL );
+
+ if ( *software_info_ptr )
+ {
+ *software_part_ptr = software_find_part( *software_info_ptr, swpart, interface );
+ }
+ }
+ }
+ i++;
+ }
+ }
+ }
+
+ /* If not found try to load the software list using the driver name */
+ if ( ! *software_part_ptr )
+ {
+ swlist_name = (char *)options.system()->name;
+
+ if ( *software_list_ptr )
+ {
+ software_list_close( *software_list_ptr );
+ }
+
+ *software_list_ptr = software_list_open( options, swlist_name, FALSE, NULL );
+
+ if ( *software_list_ptr )
+ {
+ *software_info_ptr = software_list_find( *software_list_ptr, swname, NULL );
+
+ if ( *software_info_ptr )
+ {
+ *software_part_ptr = software_find_part( *software_info_ptr, swpart, interface );
+ }
+ }
+ }
+
+ /* If not found try to load the software list using the software name as software */
+ /* list name and software part name as software name. */
+ if ( ! *software_part_ptr )
+ {
+ swlist_name = swname;
+ swname = swpart;
+ swpart = NULL;
+
+ if ( *software_list_ptr )
+ {
+ software_list_close( *software_list_ptr );
+ }
+
+ *software_list_ptr = software_list_open( options, swlist_name, FALSE, NULL );
+
+ if ( software_list_ptr )
+ {
+ *software_info_ptr = software_list_find( *software_list_ptr, swname, NULL );
+
+ if ( *software_info_ptr )
+ {
+ *software_part_ptr = software_find_part( *software_info_ptr, swpart, interface );
+ }
+
+ if ( ! *software_part_ptr )
+ {
+ software_list_close( *software_list_ptr );
+ *software_list_ptr = NULL;
+ }
+ }
+ }
+ }
+ *sw_list_name = global_strdup(swlist_name);
+
+ global_free( swlist_name );
+ global_free( swname );
+ global_free( swpart );
+}
+
+/*-------------------------------------------------
+ load_software_part
+
+ Load a software part for a device. The part to
+ load is determined by the "path", software lists
+ configured for a driver, and the interface
+ supported by the device.
+
+ returns true if the software could be loaded,
+ false otherwise. If the software could be loaded
+ sw_info and sw_part are also set.
+-------------------------------------------------*/
+
+bool load_software_part(emu_options &options, device_image_interface *image, const char *path, software_info **sw_info, software_part **sw_part, char **full_sw_name)
+{
+ software_list *software_list_ptr = NULL;
+ software_info *software_info_ptr = NULL;
+ software_part *software_part_ptr = NULL;
+ const char *swlist_name = NULL;
+
+ bool result = false;
+ *sw_info = NULL;
+ *sw_part = NULL;
+
+ find_software_item(image->device().machine().devicelist(), options, image, path, &software_list_ptr, &software_info_ptr, &software_part_ptr, &swlist_name);
+
+ // if no match has been found, we suggest similar shortnames
+ if (software_info_ptr == NULL)
+ {
+ software_display_matches(image->device().machine().devicelist(),image->device().machine().options(), image->image_interface(), path);
+ }
+
+ if ( software_part_ptr )
+ {
+ /* Load the software part */
+ try {
+ result = image->call_softlist_load((char *)swlist_name, (char *)software_info_ptr->shortname, software_part_ptr->romdata );
+ }
+ catch (emu_fatalerror &fatal)
+ {
+ software_list_close( software_list_ptr );
+ global_free(swlist_name);
+ throw fatal;
+ }
+
+ /* Create a copy of the software and part information */
+ *sw_info = auto_alloc_clear( image->device().machine(), software_info );
+ (*sw_info)->shortname = auto_strdup( image->device().machine(), software_info_ptr->shortname );
+ (*sw_info)->longname = auto_strdup( image->device().machine(), software_info_ptr->longname );
+ if ( software_info_ptr->year )
+ (*sw_info)->year = auto_strdup( image->device().machine(), software_info_ptr->year );
+ if ( software_info_ptr->publisher )
+ (*sw_info)->publisher = auto_strdup( image->device().machine(), software_info_ptr->publisher );
+
+ *sw_part = auto_alloc_clear( image->device().machine(), software_part );
+ (*sw_part)->name = auto_strdup( image->device().machine(), software_part_ptr->name );
+ if ( software_part_ptr->interface_ )
+ (*sw_part)->interface_ = auto_strdup( image->device().machine(), software_part_ptr->interface_ );
+
+ if ( software_part_ptr->featurelist )
+ {
+ feature_list *list = software_part_ptr->featurelist;
+ feature_list *new_list = auto_alloc_clear( image->device().machine(), feature_list );
+
+ (*sw_part)->featurelist = new_list;
+
+ new_list->name = auto_strdup( image->device().machine(), list->name );
+ new_list->value = auto_strdup( image->device().machine(), list->value );
+
+ list = list->next;
+
+ while( list )
+ {
+ new_list->next = auto_alloc_clear( image->device().machine(), feature_list );
+ new_list = new_list->next;
+ new_list->name = auto_strdup( image->device().machine(), list->name );
+ new_list->value = auto_strdup( image->device().machine(), list->value );
+
+ list = list->next;
+ }
+
+ new_list->next = NULL;
+ }
+
+ /* Tell the world which part we actually loaded */
+ *full_sw_name = auto_alloc_array( image->device().machine(), char, strlen(swlist_name) + strlen(software_info_ptr->shortname) + strlen(software_part_ptr->name) + 3 );
+ sprintf( *full_sw_name, "%s:%s:%s", swlist_name, software_info_ptr->shortname, software_part_ptr->name );
+ }
+
+ /* Close the software list if it's still open */
+ if ( software_list_ptr )
+ {
+ software_list_close( software_list_ptr );
+ software_info_ptr = NULL;
+ software_list_ptr = NULL;
+ }
+ global_free(swlist_name);
+ return result;
+}
+
+
+/*-------------------------------------------------
+ software_part_get_feature
+ -------------------------------------------------*/
+
+const char *software_part_get_feature(software_part *part, const char *feature_name)
+{
+ feature_list *feature;
+
+ if (part == NULL)
+ return NULL;
+
+ for (feature = part->featurelist; feature; feature = feature->next)
+ {
+ if (!strcmp(feature->name, feature_name))
+ return feature->value;
+ }
+
+ return NULL;
+
+}
+
+/*-------------------------------------------------
+ software_get_default_slot
+ -------------------------------------------------*/
+
+ const char *software_get_default_slot(const device_list &devlist, emu_options &options, const device_image_interface *image, const char *default_card, const char* default_card_slot)
+{
+ const char* retVal = default_card;
+ const char* path = options.value(image->instance_name());
+ software_list *software_list_ptr = NULL;
+ software_info *software_info_ptr = NULL;
+ software_part *software_part_ptr = NULL;
+ const char *swlist_name = NULL;
+
+ if (strlen(path)>0) {
+ retVal = default_card_slot;
+ find_software_item(devlist, options, image, path, &software_list_ptr, &software_info_ptr, &software_part_ptr, &swlist_name);
+ if (software_part_ptr!=NULL) {
+ const char *slot = software_part_get_feature(software_part_ptr, "slot");
+ if (slot!=NULL) {
+ retVal = core_strdup(slot);
+ }
+ }
+ software_list_close(software_list_ptr);
+ global_free(swlist_name);
+ }
+ return retVal;
+}
+
+/***************************************************************************
+ DEVICE INTERFACE
+***************************************************************************/
+
+
+static DEVICE_START( software_list )
+{
+}
+
+static DEVICE_VALIDITY_CHECK( software_list )
+{
+ software_list_config *swlist = (software_list_config *)downcast<const legacy_device_base *>(device)->inline_config();
+ int error = FALSE;
+ softlist_map names;
+ softlist_map descriptions;
+
+ enum { NAME_LEN_PARENT = 8, NAME_LEN_CLONE = 16 };
+
+ for (int i = 0; i < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; i++)
+ {
+ if (swlist->list_name[i])
+ {
+ software_list *list = software_list_open(options, swlist->list_name[i], FALSE, NULL);
+
+ /* if no .xml list is found, then return (this happens e.g. if you moved/renamed the xml list) */
+ if (list == NULL)
+ return FALSE;
+
+ for (software_info *swinfo = software_list_find(list, "*", NULL); swinfo != NULL; swinfo = software_list_find(list, "*", swinfo))
+ {
+ const char *s;
+ int is_clone = 0;
+
+ /* First, check if the xml got corrupted: */
+
+ /* Did we lost any description? */
+ if (swinfo->longname == NULL)
+ {
+ mame_printf_error("%s: %s has no description\n", swlist->list_name[i], swinfo->shortname);
+ return TRUE;
+ }
+
+ /* Did we lost any year? */
+ if (swinfo->year == NULL)
+ {
+ mame_printf_error("%s: %s has no year\n", swlist->list_name[i], swinfo->shortname);
+ return TRUE;
+ }
+
+ /* Did we lost any publisher? */
+ if (swinfo->publisher == NULL)
+ {
+ mame_printf_error("%s: %s has no publisher\n", swlist->list_name[i], swinfo->shortname);
+ return TRUE;
+ }
+
+ /* Second, since the xml is fine, run additional checks: */
+
+ /* check for duplicate names */
+ if (names.add(swinfo->shortname, swinfo, FALSE) == TMERR_DUPLICATE)
+ {
+ software_info *match = names.find(swinfo->shortname);
+ mame_printf_error("%s: %s is a duplicate name (%s)\n", swlist->list_name[i], swinfo->shortname, match->shortname);
+ error = TRUE;
+ }
+
+ /* check for duplicate descriptions */
+ if (descriptions.add(swinfo->longname, swinfo, FALSE) == TMERR_DUPLICATE)
+ {
+ software_info *match = names.find(swinfo->shortname);
+ mame_printf_error("%s: %s is a duplicate description (%s)\n", swlist->list_name[i], swinfo->longname, match->longname);
+ error = TRUE;
+ }
+
+ if (swinfo->parentname != NULL)
+ {
+ is_clone = 1;
+
+ if (strcmp(swinfo->parentname, swinfo->shortname) == 0)
+ {
+ mame_printf_error("%s: %s is set as a clone of itself\n", swlist->list_name[i], swinfo->shortname);
+ error = TRUE;
+ break;
+ }
+
+ /* make sure the parent exists */
+ software_info *swinfo2 = software_list_find(list, swinfo->parentname, NULL );
+
+ if (!swinfo2)
+ {
+ mame_printf_error("%s: parent '%s' software for '%s' not found\n", swlist->list_name[i], swinfo->parentname, swinfo->shortname);
+ error = TRUE;
+ }
+ else
+ {
+ if (swinfo2->parentname != NULL)
+ {
+ mame_printf_error("%s: %s is a clone of a clone\n", swlist->list_name[i], swinfo->shortname);
+ error = TRUE;
+ }
+ }
+ }
+
+ /* make sure the driver name is 8 chars or less */
+ if ((is_clone && strlen(swinfo->shortname) > NAME_LEN_CLONE) || ((!is_clone) && strlen(swinfo->shortname) > NAME_LEN_PARENT))
+ {
+ mame_printf_error("%s: %s %s driver name must be %d characters or less\n", swlist->list_name[i], swinfo->shortname,
+ is_clone ? "clone" : "parent", is_clone ? NAME_LEN_CLONE : NAME_LEN_PARENT);
+ error = TRUE;
+ }
+
+ /* make sure the year is only digits, '?' or '+' */
+ for (s = swinfo->year; *s; s++)
+ if (!isdigit((UINT8)*s) && *s != '?' && *s != '+')
+ {
+ mame_printf_error("%s: %s has an invalid year '%s'\n", swlist->list_name[i], swinfo->shortname, swinfo->year);
+ error = TRUE;
+ break;
+ }
+
+ for (software_part *swpart = software_find_part(swinfo, NULL, NULL); swpart != NULL; swpart = software_part_next(swpart))
+ {
+ if (swpart->interface_ == NULL)
+ {
+ mame_printf_error("%s: %s has a part (%s) without interface\n", swlist->list_name[i], swinfo->shortname, swpart->name);
+ error = TRUE;
+ }
+
+ if (software_find_romdata(swpart, NULL) == NULL)
+ {
+ mame_printf_error("%s: %s has a part (%s) with no data\n", swlist->list_name[i], swinfo->shortname, swpart->name);
+ error = TRUE;
+ }
+
+ for (struct rom_entry *swdata = software_find_romdata(swpart, NULL); swdata != NULL; swdata = software_romdata_next(swdata))
+ {
+ struct rom_entry *data = swdata;
+
+ if (data->_name && data->_hashdata)
+ {
+ const char *str;
+
+ /* make sure it's all lowercase */
+ for (str = data->_name; *str; str++)
+ if (tolower((UINT8)*str) != *str)
+ {
+ mame_printf_error("%s: %s has upper case ROM name %s\n", swlist->list_name[i], swinfo->shortname, data->_name);
+ error = TRUE;
+ break;
+ }
+
+ /* make sure the hash is valid */
+ hash_collection hashes;
+ if (!hashes.from_internal_string(data->_hashdata))
+ {
+ mame_printf_error("%s: %s has rom '%s' with an invalid hash string '%s'\n", swlist->list_name[i], swinfo->shortname, data->_name, data->_hashdata);
+ error = TRUE;
+ }
+ }
+ }
+ }
+ }
+
+ software_list_close(list);
+ }
+ }
+ return error;
+}
+
+DEVICE_GET_INFO( software_list )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = 1; break;
+ case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = sizeof(software_list_config); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( software_list ); break;
+ case DEVINFO_FCT_STOP: /* Nothing */ break;
+ case DEVINFO_FCT_VALIDITY_CHECK: info->p = (void*)DEVICE_VALIDITY_CHECK_NAME( software_list ); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Software lists"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Software lists"); 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 MESS Team"); break;
+ }
+
+ if ( state >= DEVINFO_STR_SWLIST_0 && state <= DEVINFO_STR_SWLIST_MAX )
+ {
+ software_list_config *config = (software_list_config *)downcast<const legacy_device_base *>(device)->inline_config();
+
+ if ( config->list_name[ state - DEVINFO_STR_SWLIST_0 ] )
+ strcpy(info->s, config->list_name[ state - DEVINFO_STR_SWLIST_0 ]);
+ }
+}
+
+
+DEFINE_LEGACY_DEVICE(SOFTWARE_LIST, software_list);
diff --git a/trunk/src/emu/softlist.h b/trunk/src/emu/softlist.h
new file mode 100644
index 00000000000..a36dd737058
--- /dev/null
+++ b/trunk/src/emu/softlist.h
@@ -0,0 +1,172 @@
+/*********************************************************************
+
+ softlist.h
+
+ Software and software list information.
+
+*********************************************************************/
+
+#ifndef __SOFTLIST_H_
+#define __SOFTLIST_H_
+
+#include "uimenu.h"
+#include "expat.h"
+#include "pool.h"
+
+
+/*********************************************************************
+
+ Internal structures and XML file handling
+
+*********************************************************************/
+
+/* Replace this with list<string>? */
+struct feature_list
+{
+ feature_list *next;
+ char *name;
+ char *value;
+};
+
+struct software_part
+{
+ const char *name;
+ const char *interface_;
+ feature_list *featurelist;
+ struct rom_entry *romdata;
+};
+
+
+/* The software info struct holds basic software information. */
+struct software_info
+{
+ const char *shortname;
+ const char *longname;
+ const char *parentname;
+ const char *year; // Copyright year on title screen, actual release dates can be tracked in external resources
+ const char *publisher;
+ feature_list *other_info; // Here we store info like developer, serial #, etc. which belong to the software entry as a whole
+ feature_list *shared_info; // Here we store info like TV standard compatibility, or add-on requirements, etc. which get inherited
+ // by each part of this software entry (after loading these are stored in partdata->featurelist)
+ UINT32 supported;
+ software_part *partdata;
+ struct software_info *next; // Used internally
+};
+
+
+enum softlist_parse_position
+{
+ POS_ROOT,
+ POS_MAIN,
+ POS_SOFT,
+ POS_PART,
+ POS_DATA
+};
+
+
+typedef struct _parse_state parse_state;
+struct _parse_state
+{
+ XML_Parser parser;
+ int done;
+
+ void (*error_proc)(const char *message);
+ void *param;
+
+ enum softlist_parse_position pos;
+ char **text_dest;
+};
+
+
+typedef struct _software_list software_list;
+struct _software_list
+{
+ emu_file *file;
+ object_pool *pool;
+ parse_state state;
+ const char *description;
+ struct software_info *software_info_list;
+ struct software_info *current_software_info;
+ software_info *softinfo;
+ const char *look_for;
+ int part_entries;
+ int current_part_entry;
+ int rom_entries;
+ int current_rom_entry;
+ void (*error_proc)(const char *message);
+ int list_entries;
+};
+
+/* Handling a software list */
+software_list *software_list_open(emu_options &options, const char *listname, int is_preload, void (*error_proc)(const char *message));
+void software_list_close(software_list *swlist);
+software_info *software_list_find(software_list *swlist, const char *look_for, software_info *prev);
+const char *software_list_get_description(software_list *swlist);
+void software_list_parse(software_list *swlist, void (*error_proc)(const char *message), void *param);
+
+software_part *software_find_part(software_info *sw, const char *partname, const char *interface_);
+software_part *software_part_next(software_part *part);
+
+/* helpers */
+const char *software_get_clone(emu_options &options, char *swlist, const char *swname);
+UINT32 software_get_support(emu_options &options, char *swlist, const char *swname);
+const char *software_part_get_feature(software_part *part, const char *feature_name);
+
+bool load_software_part(emu_options &options, device_image_interface *image, const char *path, software_info **sw_info, software_part **sw_part, char **full_sw_name);
+
+void software_display_matches(const device_list &devlist, emu_options &options,const char *interface,const char *swname_bckp);
+
+const char *software_get_default_slot(const device_list &devlist, emu_options &options, const device_image_interface *image, const char *default_card, const char* default_card_slot);
+
+/*********************************************************************
+
+ Driver software list configuration
+
+*********************************************************************/
+DECLARE_LEGACY_DEVICE(SOFTWARE_LIST, software_list);
+
+#define SOFTWARE_SUPPORTED_YES 0
+#define SOFTWARE_SUPPORTED_PARTIAL 1
+#define SOFTWARE_SUPPORTED_NO 2
+
+
+#define SOFTWARE_LIST_CONFIG_SIZE 10
+
+
+typedef struct _software_list_config software_list_config;
+struct _software_list_config
+{
+ char *list_name[SOFTWARE_LIST_CONFIG_SIZE];
+ UINT32 list_type;
+};
+
+
+#define DEVINFO_STR_SWLIST_0 (DEVINFO_STR_DEVICE_SPECIFIC+0)
+#define DEVINFO_STR_SWLIST_MAX (DEVINFO_STR_SWLIST_0 + SOFTWARE_LIST_CONFIG_SIZE - 1)
+
+#define SOFTWARE_LIST_ORIGINAL_SYSTEM 0
+#define SOFTWARE_LIST_COMPATIBLE_SYSTEM 1
+
+#define MCFG_SOFTWARE_LIST_CONFIG(_idx,_list,_list_type) \
+ MCFG_DEVICE_CONFIG_DATAPTR_ARRAY(software_list_config, list_name, _idx, _list) \
+ MCFG_DEVICE_CONFIG_DATA32(software_list_config, list_type, _list_type)
+
+#define MCFG_SOFTWARE_LIST_ADD( _tag, _list ) \
+ MCFG_DEVICE_ADD( _tag, SOFTWARE_LIST, 0 ) \
+ MCFG_SOFTWARE_LIST_CONFIG(0,_list, SOFTWARE_LIST_ORIGINAL_SYSTEM)
+
+
+#define MCFG_SOFTWARE_LIST_COMPATIBLE_ADD( _tag, _list ) \
+ MCFG_DEVICE_ADD( _tag, SOFTWARE_LIST, 0 ) \
+ MCFG_SOFTWARE_LIST_CONFIG(0,_list, SOFTWARE_LIST_COMPATIBLE_SYSTEM)
+
+
+#define MCFG_SOFTWARE_LIST_MODIFY( _tag, _list ) \
+ MCFG_DEVICE_MODIFY( _tag ) \
+ MCFG_SOFTWARE_LIST_CONFIG(0,_list, SOFTWARE_LIST_ORIGINAL_SYSTEM)
+
+#define MCFG_SOFTWARE_LIST_COMPATIBLE_MODIFY( _tag, _list ) \
+ MCFG_DEVICE_MODIFY( _tag ) \
+ MCFG_SOFTWARE_LIST_CONFIG(0,_list, SOFTWARE_LIST_COMPATIBLE_SYSTEM)
+
+#endif
diff --git a/trunk/src/emu/sound.c b/trunk/src/emu/sound.c
new file mode 100644
index 00000000000..0586b6a72e8
--- /dev/null
+++ b/trunk/src/emu/sound.c
@@ -0,0 +1,1067 @@
+/***************************************************************************
+
+ sound.c
+
+ Core sound functions and 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"
+#include "emuopts.h"
+#include "osdepend.h"
+#include "config.h"
+#include "profiler.h"
+#include "sound/wavwrite.h"
+
+
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define VERBOSE (0)
+
+#define VPRINTF(x) do { if (VERBOSE) mame_printf_debug x; } while (0)
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const attotime sound_manager::STREAMS_UPDATE_ATTOTIME = attotime::from_hz(STREAMS_UPDATE_FREQUENCY);
+
+
+
+//**************************************************************************
+// INITIALIZATION
+//**************************************************************************
+
+//-------------------------------------------------
+// sound_stream - constructor
+//-------------------------------------------------
+
+sound_stream::sound_stream(device_t &device, int inputs, int outputs, int sample_rate, void *param, stream_update_func callback)
+ : m_device(device),
+ m_next(NULL),
+ m_sample_rate(sample_rate),
+ m_new_sample_rate(0),
+ m_attoseconds_per_sample(0),
+ m_max_samples_per_update(0),
+ m_inputs(inputs),
+ m_input((inputs == 0) ? NULL : auto_alloc_array_clear(device.machine(), stream_input, inputs)),
+ m_input_array((inputs == 0) ? NULL : auto_alloc_array_clear(device.machine(), stream_sample_t *, inputs)),
+ m_resample_bufalloc(0),
+ m_outputs(outputs),
+ m_output((outputs == 0) ? NULL : auto_alloc_array_clear(device.machine(), stream_output, outputs)),
+ m_output_array((outputs == 0) ? NULL : auto_alloc_array_clear(device.machine(), stream_sample_t *, outputs)),
+ m_output_bufalloc(0),
+ m_output_sampindex(0),
+ m_output_update_sampindex(0),
+ m_output_base_sampindex(0),
+ m_callback(callback),
+ m_param(param)
+{
+ // get the device's sound interface
+ device_sound_interface *sound;
+ if (!device.interface(sound))
+ throw emu_fatalerror("Attempted to create a sound_stream with a non-sound device");
+
+ // this is also the implicit parameter if we are using our internal stub
+ if (m_callback == &sound_stream::device_stream_update_stub)
+ m_param = sound;
+
+ // create a unique tag for saving
+ astring state_tag;
+ state_tag.printf("%d", m_device.machine().sound().m_stream_list.count());
+ m_device.machine().save().save_item("stream", state_tag, 0, NAME(m_sample_rate));
+ m_device.machine().save().register_postload(save_prepost_delegate(FUNC(sound_stream::postload), this));
+
+ // save the gain of each input and output
+ for (int inputnum = 0; inputnum < m_inputs; inputnum++)
+ m_device.machine().save().save_item("stream", state_tag, inputnum, NAME(m_input[inputnum].m_gain));
+ for (int outputnum = 0; outputnum < m_outputs; outputnum++)
+ {
+ m_output[outputnum].m_stream = this;
+ m_device.machine().save().save_item("stream", state_tag, outputnum, NAME(m_output[outputnum].m_gain));
+ }
+
+ // force an update to the sample rates; this will cause everything to be recomputed
+ // and will generate the initial resample buffers for our inputs
+ recompute_sample_rate_data();
+
+ // set up the initial output buffer positions now that we have data
+ m_output_base_sampindex = -m_max_samples_per_update;
+}
+
+
+//-------------------------------------------------
+// sample_time - return the emulation time of the
+// next sample to be generated on the stream
+//-------------------------------------------------
+
+attotime sound_stream::sample_time() const
+{
+ return attotime(m_device.machine().sound().last_update().seconds, 0) + attotime(0, m_output_sampindex * m_attoseconds_per_sample);
+}
+
+
+//-------------------------------------------------
+// input_gain - return the input gain on a
+// given stream's input
+//-------------------------------------------------
+
+float sound_stream::input_gain(int inputnum) const
+{
+ assert(inputnum >= 0 && inputnum < m_inputs);
+ return float(m_input[inputnum].m_gain) / 256.0f;
+}
+
+
+//-------------------------------------------------
+// initial_input_gain - return the original input
+// gain on a given stream's input
+//-------------------------------------------------
+
+float sound_stream::initial_input_gain(int inputnum) const
+{
+ assert(inputnum >= 0 && inputnum < m_inputs);
+ return float(m_input[inputnum].m_initial_gain) / 256.0f;
+}
+
+
+//-------------------------------------------------
+// input_name - return the original input gain
+// on a given stream's input
+//-------------------------------------------------
+
+const char *sound_stream::input_name(int inputnum, astring &string) const
+{
+ // start with our device name and tag
+ assert(inputnum >= 0 && inputnum < m_inputs);
+ string.printf("%s '%s': ", m_device.name(), m_device.tag());
+
+ // if we have a source, indicate where the sound comes from by device name and tag
+ if (m_input[inputnum].m_source != NULL && m_input[inputnum].m_source->m_stream != NULL)
+ {
+ device_t &source = m_input[inputnum].m_source->m_stream->device();
+ string.catprintf("%s '%s'", source.name(), source.tag());
+
+ // get the sound interface; if there is more than 1 output we need to figure out which one
+ device_sound_interface *sound;
+ if (source.interface(sound) && sound->outputs() > 1)
+ {
+ // iterate over outputs until we find the stream that matches our source
+ // then look for a match on the output number
+ sound_stream *outstream;
+ int streamoutputnum;
+ for (int outputnum = 0; (outstream = sound->output_to_stream_output(outputnum, streamoutputnum)) != NULL; outputnum++)
+ if (outstream == m_input[inputnum].m_source->m_stream && m_input[inputnum].m_source == &outstream->m_output[streamoutputnum])
+ {
+ string.catprintf(" Ch.%d", outputnum);
+ break;
+ }
+ }
+ }
+ return string;
+}
+
+
+//-------------------------------------------------
+// output_gain - return the output gain on a
+// given stream's output
+//-------------------------------------------------
+
+float sound_stream::output_gain(int outputnum) const
+{
+ assert(outputnum >= 0 && outputnum < m_outputs);
+ return float(m_output[outputnum].m_gain) / 256.0f;
+}
+
+
+//-------------------------------------------------
+// set_input - configure a stream's input
+//-------------------------------------------------
+
+void sound_stream::set_input(int index, sound_stream *input_stream, int output_index, float gain)
+{
+ VPRINTF(("stream_set_input(%p, '%s', %d, %p, %d, %f)\n", this, m_device.tag(), index, input_stream, output_index, gain));
+
+ // make sure it's a valid input
+ if (index >= m_inputs)
+ fatalerror("Fatal error: stream_set_input attempted to configure non-existant input %d (%d max)", index, m_inputs);
+
+ // make sure it's a valid output
+ if (input_stream != NULL && output_index >= input_stream->m_outputs)
+ fatalerror("Fatal error: stream_set_input attempted to use a non-existant output %d (%d max)", output_index, m_outputs);
+
+ // if this input is already wired, update the dependent info
+ stream_input &input = m_input[index];
+ if (input.m_source != NULL)
+ input.m_source->m_dependents--;
+
+ // wire it up
+ input.m_source = (input_stream != NULL) ? &input_stream->m_output[output_index] : NULL;
+ input.m_gain = input.m_initial_gain = int(0x100 * gain);
+
+ // update the dependent info
+ if (input.m_source != NULL)
+ input.m_source->m_dependents++;
+
+ // update sample rates now that we know the input
+ recompute_sample_rate_data();
+}
+
+
+//-------------------------------------------------
+// update - force a stream to update to
+// the current emulated time
+//-------------------------------------------------
+
+void sound_stream::update()
+{
+ // determine the number of samples since the start of this second
+ attotime time = m_device.machine().time();
+ INT32 update_sampindex = INT32(time.attoseconds / m_attoseconds_per_sample);
+
+ // if we're ahead of the last update, then adjust upwards
+ attotime last_update = m_device.machine().sound().last_update();
+ if (time.seconds > last_update.seconds)
+ {
+ assert(time.seconds == last_update.seconds + 1);
+ update_sampindex += m_sample_rate;
+ }
+
+ // if we're behind the last update, then adjust downwards
+ if (time.seconds < last_update.seconds)
+ {
+ assert(time.seconds == last_update.seconds - 1);
+ update_sampindex -= m_sample_rate;
+ }
+
+ // generate samples to get us up to the appropriate time
+ g_profiler.start(PROFILER_SOUND);
+ assert(m_output_sampindex - m_output_base_sampindex >= 0);
+ assert(update_sampindex - m_output_base_sampindex <= m_output_bufalloc);
+ generate_samples(update_sampindex - m_output_sampindex);
+ g_profiler.stop();
+
+ // remember this info for next time
+ m_output_sampindex = update_sampindex;
+}
+
+
+//-------------------------------------------------
+// output_since_last_update - return a pointer to
+// the output buffer and the number of samples
+// since the last global update
+//-------------------------------------------------
+
+const stream_sample_t *sound_stream::output_since_last_update(int outputnum, int &numsamples)
+{
+ // force an update on the stream
+ update();
+
+ // compute the number of samples and a pointer to the output buffer
+ numsamples = m_output_sampindex - m_output_update_sampindex;
+ return m_output[outputnum].m_buffer + (m_output_update_sampindex - m_output_base_sampindex);
+}
+
+
+//-------------------------------------------------
+// set_sample_rate - set the sample rate on a
+// given stream
+//-------------------------------------------------
+
+void sound_stream::set_sample_rate(int new_rate)
+{
+ // we will update this on the next global update
+ if (new_rate != sample_rate())
+ m_new_sample_rate = new_rate;
+}
+
+
+//-------------------------------------------------
+// set_input_gain - set the input gain on a
+// given stream's input
+//-------------------------------------------------
+
+void sound_stream::set_input_gain(int inputnum, float gain)
+{
+ update();
+ assert(inputnum >= 0 && inputnum < m_inputs);
+ m_input[inputnum].m_gain = int(0x100 * gain);
+}
+
+
+//-------------------------------------------------
+// set_output_gain - set the output gain on a
+// given stream's output
+//-------------------------------------------------
+
+void sound_stream::set_output_gain(int outputnum, float gain)
+{
+ update();
+ assert(outputnum >= 0 && outputnum < m_outputs);
+ m_output[outputnum].m_gain = int(0x100 * gain);
+}
+
+
+//-------------------------------------------------
+// update_with_accounting - do a regular update,
+// but also do periodic accounting
+//-------------------------------------------------
+
+void sound_stream::update_with_accounting(bool second_tick)
+{
+ // do the normal update
+ update();
+
+ // if we've ticked over another second, adjust all the counters that are relative to
+ // the current second
+ INT32 output_bufindex = m_output_sampindex - m_output_base_sampindex;
+ if (second_tick)
+ {
+ m_output_sampindex -= m_sample_rate;
+ m_output_base_sampindex -= m_sample_rate;
+ }
+
+ // note our current output sample
+ m_output_update_sampindex = m_output_sampindex;
+
+ // if we don't have enough output buffer space to hold two updates' worth of samples,
+ // we need to shuffle things down
+ if (m_output_bufalloc - output_bufindex < 2 * m_max_samples_per_update)
+ {
+ INT32 samples_to_lose = output_bufindex - m_max_samples_per_update;
+ if (samples_to_lose > 0)
+ {
+ // if we have samples to move, do so for each output
+ if (output_bufindex > 0)
+ for (int outputnum = 0; outputnum < m_outputs; outputnum++)
+ {
+ stream_output &output = m_output[outputnum];
+ memmove(&output.m_buffer[0], &output.m_buffer[samples_to_lose], sizeof(output.m_buffer[0]) * (output_bufindex - samples_to_lose));
+ }
+
+ // update the base position
+ m_output_base_sampindex += samples_to_lose;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// apply_sample_rate_changes - if there is a
+// pending sample rate change, apply it now
+//-------------------------------------------------
+
+void sound_stream::apply_sample_rate_changes()
+{
+ // skip if nothing to do
+ if (m_new_sample_rate == 0)
+ return;
+
+ // update to the new rate and remember the old rate
+ UINT32 old_rate = m_sample_rate;
+ m_sample_rate = m_new_sample_rate;
+ m_new_sample_rate = 0;
+
+ // recompute all the data
+ recompute_sample_rate_data();
+
+ // reset our sample indexes to the current time
+ m_output_sampindex = (INT64)m_output_sampindex * (INT64)m_sample_rate / old_rate;
+ m_output_update_sampindex = (INT64)m_output_update_sampindex * (INT64)m_sample_rate / old_rate;
+ m_output_base_sampindex = m_output_sampindex - m_max_samples_per_update;
+
+ // clear out the buffer
+ for (int outputnum = 0; outputnum < m_outputs; outputnum++)
+ memset(m_output[outputnum].m_buffer, 0, m_max_samples_per_update * sizeof(m_output[outputnum].m_buffer[0]));
+}
+
+
+//-------------------------------------------------
+// device_stream_update_stub - stub callback for
+// passing through to modern devices
+//-------------------------------------------------
+
+STREAM_UPDATE( sound_stream::device_stream_update_stub )
+{
+ device_sound_interface *sound = reinterpret_cast<device_sound_interface *>(param);
+ sound->sound_stream_update(*stream, inputs, outputs, samples);
+}
+
+
+//-------------------------------------------------
+// recompute_sample_rate_data - recompute sample
+// rate data, and all streams that are affected
+// by this stream
+//-------------------------------------------------
+
+void sound_stream::recompute_sample_rate_data()
+{
+ // recompute the timing parameters
+ attoseconds_t update_attoseconds = m_device.machine().sound().update_attoseconds();
+ m_attoseconds_per_sample = ATTOSECONDS_PER_SECOND / m_sample_rate;
+ m_max_samples_per_update = (update_attoseconds + m_attoseconds_per_sample - 1) / m_attoseconds_per_sample;
+
+ // update resample and output buffer sizes
+ allocate_resample_buffers();
+ allocate_output_buffers();
+
+ // iterate over each input
+ for (int inputnum = 0; inputnum < m_inputs; inputnum++)
+ {
+ // if we have a source, see if its sample rate changed
+ stream_input &input = m_input[inputnum];
+ if (input.m_source != NULL)
+ {
+ // okay, we have a new sample rate; recompute the latency to be the maximum
+ // sample period between us and our input
+ attoseconds_t new_attosecs_per_sample = ATTOSECONDS_PER_SECOND / input.m_source->m_stream->m_sample_rate;
+ attoseconds_t latency = MAX(new_attosecs_per_sample, m_attoseconds_per_sample);
+
+ // if the input stream's sample rate is lower, we will use linear interpolation
+ // this requires an extra sample from the source
+ if (input.m_source->m_stream->m_sample_rate < m_sample_rate)
+ latency += new_attosecs_per_sample;
+
+ // if our sample rates match exactly, we don't need any latency
+ else if (input.m_source->m_stream->m_sample_rate == m_sample_rate)
+ latency = 0;
+
+ // we generally don't want to tweak the latency, so we just keep the greatest
+ // one we've computed thus far
+ input.m_latency_attoseconds = MAX(input.m_latency_attoseconds, latency);
+ assert(input.m_latency_attoseconds < update_attoseconds);
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// allocate_resample_buffers - recompute the
+// resample buffer sizes and expand if necessary
+//-------------------------------------------------
+
+void sound_stream::allocate_resample_buffers()
+{
+ // compute the target number of samples
+ INT32 bufsize = 2 * m_max_samples_per_update;
+
+ // if we don't have enough room, allocate more
+ if (m_resample_bufalloc < bufsize)
+ {
+ // this becomes the new allocation size
+ int oldsize = m_resample_bufalloc;
+ m_resample_bufalloc = bufsize;
+
+ // iterate over outputs and realloc their buffers
+ for (int inputnum = 0; inputnum < m_inputs; inputnum++)
+ {
+ stream_input &input = m_input[inputnum];
+ stream_sample_t *newbuffer = auto_alloc_array(m_device.machine(), stream_sample_t, m_resample_bufalloc);
+ memcpy(newbuffer, input.m_resample, oldsize * sizeof(stream_sample_t));
+ auto_free(m_device.machine(), input.m_resample);
+ input.m_resample = newbuffer;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// allocate_output_buffers - recompute the
+// output buffer sizes and expand if necessary
+//-------------------------------------------------
+
+void sound_stream::allocate_output_buffers()
+{
+ // if we don't have enough room, allocate more
+ INT32 bufsize = OUTPUT_BUFFER_UPDATES * m_max_samples_per_update;
+ if (m_output_bufalloc < bufsize)
+ {
+ // this becomes the new allocation size
+ int oldsize = m_output_bufalloc;
+ m_output_bufalloc = bufsize;
+
+ // iterate over outputs and realloc their buffers
+ for (int outputnum = 0; outputnum < m_outputs; outputnum++)
+ {
+ stream_output &output = m_output[outputnum];
+ stream_sample_t *newbuffer = auto_alloc_array(m_device.machine(), stream_sample_t, m_output_bufalloc);
+ memcpy(newbuffer, output.m_buffer, oldsize * sizeof(stream_sample_t));
+ memset(newbuffer + oldsize, 0, (m_output_bufalloc - oldsize) * sizeof(stream_sample_t));
+ auto_free(m_device.machine(), output.m_buffer);
+ output.m_buffer = newbuffer;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// postload - save/restore callback
+//-------------------------------------------------
+
+void sound_stream::postload()
+{
+ // recompute the same rate information
+ recompute_sample_rate_data();
+
+ // make sure our output buffers are fully cleared
+ for (int outputnum = 0; outputnum < m_outputs; outputnum++)
+ memset(m_output[outputnum].m_buffer, 0, m_output_bufalloc * sizeof(m_output[outputnum].m_buffer[0]));
+
+ // recompute the sample indexes to make sense
+ m_output_sampindex = m_device.machine().sound().last_update().attoseconds / m_attoseconds_per_sample;
+ m_output_update_sampindex = m_output_sampindex;
+ m_output_base_sampindex = m_output_sampindex - m_max_samples_per_update;
+}
+
+
+//-------------------------------------------------
+// generate_samples - generate the requested
+// number of samples for a stream, making sure
+// all inputs have the appropriate number of
+// samples generated
+//-------------------------------------------------
+
+void sound_stream::generate_samples(int samples)
+{
+ // if we're already there, skip it
+ if (samples <= 0)
+ return;
+
+ VPRINTF(("generate_samples(%p, %d)\n", this, samples));
+
+ // ensure all inputs are up to date and generate resampled data
+ for (int inputnum = 0; inputnum < m_inputs; inputnum++)
+ {
+ // update the stream to the current time
+ stream_input &input = m_input[inputnum];
+ if (input.m_source != NULL)
+ input.m_source->m_stream->update();
+
+ // generate the resampled data
+ m_input_array[inputnum] = generate_resampled_data(input, samples);
+ }
+
+ // loop over all outputs and compute the output pointer
+ for (int outputnum = 0; outputnum < m_outputs; outputnum++)
+ {
+ stream_output &output = m_output[outputnum];
+ m_output_array[outputnum] = output.m_buffer + (m_output_sampindex - m_output_base_sampindex);
+ }
+
+ // run the callback
+ VPRINTF((" callback(%p, %d)\n", this, samples));
+ (*m_callback)(&m_device, this, m_param, m_input_array, m_output_array, samples);
+ VPRINTF((" callback done\n"));
+}
+
+
+//-------------------------------------------------
+// generate_resampled_data - generate the
+// resample buffer for a given input
+//-------------------------------------------------
+
+stream_sample_t *sound_stream::generate_resampled_data(stream_input &input, UINT32 numsamples)
+{
+ // if we don't have an output to pull data from, generate silence
+ stream_sample_t *dest = input.m_resample;
+ if (input.m_source == NULL)
+ {
+ memset(dest, 0, numsamples * sizeof(*dest));
+ return input.m_resample;
+ }
+
+ // grab data from the output
+ stream_output &output = *input.m_source;
+ sound_stream &input_stream = *output.m_stream;
+ int gain = (input.m_gain * output.m_gain) >> 8;
+
+ // determine the time at which the current sample begins, accounting for the
+ // latency we calculated between the input and output streams
+ attoseconds_t basetime = m_output_sampindex * m_attoseconds_per_sample - input.m_latency_attoseconds;
+
+ // now convert that time into a sample in the input stream
+ INT32 basesample;
+ if (basetime >= 0)
+ basesample = basetime / input_stream.m_attoseconds_per_sample;
+ else
+ basesample = -(-basetime / input_stream.m_attoseconds_per_sample) - 1;
+
+ // compute a source pointer to the first sample
+ assert(basesample >= input_stream.m_output_base_sampindex);
+ stream_sample_t *source = output.m_buffer + (basesample - input_stream.m_output_base_sampindex);
+
+ // determine the current fraction of a sample
+ UINT32 basefrac = (basetime - basesample * input_stream.m_attoseconds_per_sample) / ((input_stream.m_attoseconds_per_sample + FRAC_ONE - 1) >> FRAC_BITS);
+ assert(basefrac >= 0);
+ assert(basefrac < FRAC_ONE);
+
+ // compute the stepping fraction
+ UINT32 step = ((UINT64)input_stream.m_sample_rate << FRAC_BITS) / m_sample_rate;
+
+ // if we have equal sample rates, we just need to copy
+ if (step == FRAC_ONE)
+ {
+ while (numsamples--)
+ {
+ // compute the sample
+ stream_sample_t sample = *source++;
+ *dest++ = (sample * gain) >> 8;
+ }
+ }
+
+ // input is undersampled: point sample except where our sample period covers a boundary
+ else if (step < FRAC_ONE)
+ {
+ while (numsamples != 0)
+ {
+ // fill in with point samples until we hit a boundary
+ int nextfrac;
+ while ((nextfrac = basefrac + step) < FRAC_ONE && numsamples--)
+ {
+ *dest++ = (source[0] * gain) >> 8;
+ basefrac = nextfrac;
+ }
+
+ // if we're done, we're done
+ if ((INT32)numsamples-- < 0)
+ break;
+
+ // compute starting and ending fractional positions
+ int startfrac = basefrac >> (FRAC_BITS - 12);
+ int endfrac = nextfrac >> (FRAC_BITS - 12);
+
+ // blend between the two samples accordingly
+ stream_sample_t sample = (source[0] * (0x1000 - startfrac) + source[1] * (endfrac - 0x1000)) / (endfrac - startfrac);
+ *dest++ = (sample * gain) >> 8;
+
+ // advance
+ basefrac = nextfrac & FRAC_MASK;
+ source++;
+ }
+ }
+
+ // input is oversampled: sum the energy
+ else
+ {
+ // use 8 bits to allow some extra headroom
+ int smallstep = step >> (FRAC_BITS - 8);
+ while (numsamples--)
+ {
+ int remainder = smallstep;
+ int tpos = 0;
+
+ // compute the sample
+ int scale = (FRAC_ONE - basefrac) >> (FRAC_BITS - 8);
+ stream_sample_t sample = source[tpos++] * scale;
+ remainder -= scale;
+ while (remainder > 0x100)
+ {
+ sample += source[tpos++] * 0x100;
+ remainder -= 0x100;
+ }
+ sample += source[tpos] * remainder;
+ sample /= smallstep;
+
+ *dest++ = (sample * gain) >> 8;
+
+ // advance
+ basefrac += step;
+ source += basefrac >> FRAC_BITS;
+ basefrac &= FRAC_MASK;
+ }
+ }
+
+ return input.m_resample;
+}
+
+
+
+//**************************************************************************
+// STREAM INPUT
+//**************************************************************************
+
+//-------------------------------------------------
+// stream_input - constructor
+//-------------------------------------------------
+
+sound_stream::stream_input::stream_input()
+ : m_source(NULL),
+ m_resample(NULL),
+ m_bufsize(0),
+ m_bufalloc(0),
+ m_latency_attoseconds(0),
+ m_gain(0x100),
+ m_initial_gain(0x100)
+{
+}
+
+
+
+//**************************************************************************
+// STREAM OUTPUT
+//**************************************************************************
+
+//-------------------------------------------------
+// stream_output - constructor
+//-------------------------------------------------
+
+sound_stream::stream_output::stream_output()
+ : m_buffer(NULL),
+ m_dependents(0),
+ m_gain(0x100)
+{
+}
+
+
+
+//**************************************************************************
+// SOUND MANAGER
+//**************************************************************************
+
+//-------------------------------------------------
+// sound_manager - constructor
+//-------------------------------------------------
+
+sound_manager::sound_manager(running_machine &machine)
+ : m_machine(machine),
+ m_update_timer(machine.scheduler().timer_alloc(FUNC(update_static), this)),
+ m_finalmix_leftover(0),
+ m_finalmix(NULL),
+ m_leftmix(NULL),
+ m_rightmix(NULL),
+ m_muted(0),
+ m_attenuation(0),
+ m_nosound_mode(!machine.options().sound()),
+ m_wavfile(NULL),
+ m_stream_list(machine.respool()),
+ m_update_attoseconds(STREAMS_UPDATE_ATTOTIME.attoseconds),
+ m_last_update(attotime::zero)
+{
+ // get filename for WAV file or AVI file if specified
+ const char *wavfile = machine.options().wav_write();
+ const char *avifile = machine.options().avi_write();
+
+ // handle -nosound and lower sample rate if not recording WAV or AVI
+ if (m_nosound_mode && wavfile[0] == 0 && avifile[0] == 0)
+ machine.m_sample_rate = 11025;
+
+ // count the speakers
+ VPRINTF(("total speakers = %d\n", machine.devicelist().count(SPEAKER)));
+
+ // allocate memory for mix buffers
+ m_leftmix = auto_alloc_array(machine, INT32, machine.sample_rate());
+ m_rightmix = auto_alloc_array(machine, INT32, machine.sample_rate());
+ m_finalmix = auto_alloc_array(machine, INT16, machine.sample_rate());
+
+ // open the output WAV file if specified
+ if (wavfile[0] != 0)
+ m_wavfile = wav_open(wavfile, machine.sample_rate(), 2);
+
+ // register callbacks
+ config_register(machine, "mixer", config_saveload_delegate(FUNC(sound_manager::config_load), this), config_saveload_delegate(FUNC(sound_manager::config_save), this));
+ machine.add_notifier(MACHINE_NOTIFY_PAUSE, machine_notify_delegate(FUNC(sound_manager::pause), this));
+ machine.add_notifier(MACHINE_NOTIFY_RESUME, machine_notify_delegate(FUNC(sound_manager::resume), this));
+ machine.add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(FUNC(sound_manager::reset), this));
+
+ // register global states
+ state_save_register_global(machine, m_last_update);
+
+ // set the starting attenuation
+ set_attenuation(machine.options().volume());
+
+ // start the periodic update flushing timer
+ m_update_timer->adjust(STREAMS_UPDATE_ATTOTIME, 0, STREAMS_UPDATE_ATTOTIME);
+}
+
+
+//-------------------------------------------------
+// sound_manager - destructor
+//-------------------------------------------------
+
+sound_manager::~sound_manager()
+{
+ // close any open WAV file
+ if (m_wavfile != NULL)
+ wav_close(m_wavfile);
+ m_wavfile = NULL;
+}
+
+
+//-------------------------------------------------
+// stream_alloc - allocate a new stream
+//-------------------------------------------------
+
+sound_stream *sound_manager::stream_alloc(device_t &device, int inputs, int outputs, int sample_rate, void *param, sound_stream::stream_update_func callback)
+{
+ if (callback != NULL)
+ return &m_stream_list.append(*auto_alloc(device.machine(), sound_stream(device, inputs, outputs, sample_rate, param, callback)));
+ else
+ return &m_stream_list.append(*auto_alloc(device.machine(), sound_stream(device, inputs, outputs, sample_rate)));
+}
+
+
+//-------------------------------------------------
+// set_attenuation - set the global volume
+//-------------------------------------------------
+
+void sound_manager::set_attenuation(int attenuation)
+{
+ m_attenuation = attenuation;
+ machine().osd().set_mastervolume(m_muted ? -32 : m_attenuation);
+}
+
+
+//-------------------------------------------------
+// indexed_speaker_input - return the speaker
+// device and input index of the global speaker
+// input
+//-------------------------------------------------
+
+bool sound_manager::indexed_speaker_input(int index, speaker_input &info) const
+{
+ // scan through the speakers until we find the indexed input
+ for (info.speaker = downcast<speaker_device *>(machine().devicelist().first(SPEAKER)); info.speaker != NULL; info.speaker = info.speaker->next_speaker())
+ {
+ if (index < info.speaker->inputs())
+ {
+ info.stream = info.speaker->input_to_stream_input(index, info.inputnum);
+ assert(info.stream != NULL);
+ return true;
+ }
+ index -= info.speaker->inputs();
+ }
+
+ // didn't locate
+ return false;
+}
+
+
+//-------------------------------------------------
+// mute - mute sound output
+//-------------------------------------------------
+
+void sound_manager::mute(bool mute, UINT8 reason)
+{
+ if (mute)
+ m_muted |= reason;
+ else
+ m_muted &= ~reason;
+ set_attenuation(m_attenuation);
+}
+
+
+//-------------------------------------------------
+// reset - reset all sound chips
+//-------------------------------------------------
+
+void sound_manager::reset()
+{
+ // reset all the sound chips
+ device_sound_interface *sound = NULL;
+ for (bool gotone = machine().devicelist().first(sound); gotone; gotone = sound->next(sound))
+ sound->device().reset();
+}
+
+
+//-------------------------------------------------
+// pause - pause sound output
+//-------------------------------------------------
+
+void sound_manager::pause()
+{
+ mute(true, MUTE_REASON_PAUSE);
+}
+
+
+//-------------------------------------------------
+// resume - resume sound output
+//-------------------------------------------------
+
+void sound_manager::resume()
+{
+ mute(false, MUTE_REASON_PAUSE);
+}
+
+
+//-------------------------------------------------
+// config_load - read and apply data from the
+// configuration file
+//-------------------------------------------------
+
+void sound_manager::config_load(int config_type, xml_data_node *parentnode)
+{
+ // we only care about game files
+ if (config_type != CONFIG_TYPE_GAME)
+ return;
+
+ // might not have any data
+ if (parentnode == NULL)
+ return;
+
+ // iterate over channel nodes
+ for (xml_data_node *channelnode = xml_get_sibling(parentnode->child, "channel"); channelnode != NULL; channelnode = xml_get_sibling(channelnode->next, "channel"))
+ {
+ speaker_input info;
+ if (indexed_speaker_input(xml_get_attribute_int(channelnode, "index", -1), info))
+ {
+ float defvol = xml_get_attribute_float(channelnode, "defvol", -1000.0);
+ float newvol = xml_get_attribute_float(channelnode, "newvol", -1000.0);
+ if (fabs(defvol - info.stream->initial_input_gain(info.inputnum)) < 1e-6 && newvol != -1000.0)
+ info.stream->set_input_gain(info.inputnum, newvol);
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// config_save - save data to the configuration
+// file
+//-------------------------------------------------
+
+void sound_manager::config_save(int config_type, xml_data_node *parentnode)
+{
+ // we only care about game files
+ if (config_type != CONFIG_TYPE_GAME)
+ return;
+
+ // iterate over mixer channels
+ if (parentnode != NULL)
+ for (int mixernum = 0; ; mixernum++)
+ {
+ speaker_input info;
+ if (!indexed_speaker_input(mixernum, info))
+ break;
+ float defvol = info.stream->initial_input_gain(info.inputnum);
+ float newvol = info.stream->input_gain(info.inputnum);
+
+ if (defvol != newvol)
+ {
+ xml_data_node *channelnode = xml_add_child(parentnode, "channel", NULL);
+ if (channelnode != NULL)
+ {
+ xml_set_attribute_int(channelnode, "index", mixernum);
+ xml_set_attribute_float(channelnode, "defvol", defvol);
+ xml_set_attribute_float(channelnode, "newvol", newvol);
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// update - mix everything down to its final form
+// and send it to the OSD layer
+//-------------------------------------------------
+
+void sound_manager::update()
+{
+ VPRINTF(("sound_update\n"));
+
+ g_profiler.start(PROFILER_SOUND);
+
+ // force all the speaker streams to generate the proper number of samples
+ int samples_this_update = 0;
+ for (speaker_device *speaker = downcast<speaker_device *>(machine().devicelist().first(SPEAKER)); speaker != NULL; speaker = speaker->next_speaker())
+ speaker->mix(m_leftmix, m_rightmix, samples_this_update, (m_muted & MUTE_REASON_SYSTEM));
+
+ // now downmix the final result
+ UINT32 finalmix_step = machine().video().speed_factor();
+ UINT32 finalmix_offset = 0;
+ INT16 *finalmix = m_finalmix;
+ int sample;
+ for (sample = m_finalmix_leftover; sample < samples_this_update * 1000; sample += finalmix_step)
+ {
+ int sampindex = sample / 1000;
+
+ // clamp the left side
+ INT32 samp = m_leftmix[sampindex];
+ if (samp < -32768)
+ samp = -32768;
+ else if (samp > 32767)
+ samp = 32767;
+ finalmix[finalmix_offset++] = samp;
+
+ // clamp the right side
+ samp = m_rightmix[sampindex];
+ if (samp < -32768)
+ samp = -32768;
+ else if (samp > 32767)
+ samp = 32767;
+ finalmix[finalmix_offset++] = samp;
+ }
+ m_finalmix_leftover = sample - samples_this_update * 1000;
+
+ // play the result
+ if (finalmix_offset > 0)
+ {
+ if (!m_nosound_mode)
+ machine().osd().update_audio_stream(finalmix, finalmix_offset / 2);
+ machine().video().add_sound_to_recording(finalmix, finalmix_offset / 2);
+ if (m_wavfile != NULL)
+ wav_add_data_16(m_wavfile, finalmix, finalmix_offset);
+ }
+
+ // see if we ticked over to the next second
+ attotime curtime = machine().time();
+ bool second_tick = false;
+ if (curtime.seconds != m_last_update.seconds)
+ {
+ assert(curtime.seconds == m_last_update.seconds + 1);
+ second_tick = true;
+ }
+
+ // iterate over all the streams and update them
+ for (sound_stream *stream = m_stream_list.first(); stream != NULL; stream = stream->next())
+ stream->update_with_accounting(second_tick);
+
+ // remember the update time
+ m_last_update = curtime;
+
+ // update sample rates if they have changed
+ for (sound_stream *stream = m_stream_list.first(); stream != NULL; stream = stream->next())
+ stream->apply_sample_rate_changes();
+
+ g_profiler.stop();
+}
diff --git a/trunk/src/emu/sound.h b/trunk/src/emu/sound.h
new file mode 100644
index 00000000000..03f6b8ec98c
--- /dev/null
+++ b/trunk/src/emu/sound.h
@@ -0,0 +1,276 @@
+/***************************************************************************
+
+ sound.h
+
+ Core sound interface functions and 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 __SOUND_H__
+#define __SOUND_H__
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+#define STREAM_UPDATE(name) void name(device_t *device, sound_stream *stream, void *param, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// forward references
+class speaker_device;
+typedef struct _wav_file wav_file;
+
+
+// structure describing an indexed speaker
+struct speaker_input
+{
+ speaker_device * speaker; // owning device
+ sound_stream * stream; // stream within the device
+ int inputnum; // input on the stream
+};
+
+
+// ======================> sound_stream
+
+class sound_stream
+{
+ friend class simple_list<sound_stream>;
+ friend class sound_manager;
+
+ typedef void (*stream_update_func)(device_t *device, sound_stream *stream, void *param, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
+
+ // stream output class
+ class stream_output
+ {
+ public:
+ // construction/destruction
+ stream_output();
+
+ // internal state
+ sound_stream * m_stream; // owning stream
+ stream_sample_t * m_buffer; // output buffer
+ int m_dependents; // number of dependents
+ INT16 m_gain; // gain to apply to the output
+ };
+
+ // stream input class
+ class stream_input
+ {
+ public:
+ // construction/destruction
+ stream_input();
+
+ // internal state
+ stream_output * m_source; // pointer to the sound_output for this source
+ stream_sample_t * m_resample; // buffer for resampling to the stream's sample rate
+ UINT32 m_bufsize; // size of output buffer, in samples
+ UINT32 m_bufalloc; // allocated size of output buffer, in samples
+ attoseconds_t m_latency_attoseconds; // latency between this stream and the input stream
+ INT16 m_gain; // gain to apply to this input
+ INT16 m_initial_gain; // initial gain supplied at creation
+ };
+
+ // constants
+ static const int OUTPUT_BUFFER_UPDATES = 5;
+ static const UINT32 FRAC_BITS = 22;
+ static const UINT32 FRAC_ONE = 1 << FRAC_BITS;
+ static const UINT32 FRAC_MASK = FRAC_ONE - 1;
+
+ // construction/destruction
+ sound_stream(device_t &device, int inputs, int outputs, int sample_rate, void *param = NULL, stream_update_func callback = &sound_stream::device_stream_update_stub);
+
+public:
+ // getters
+ sound_stream *next() const { return m_next; }
+ device_t &device() const { return m_device; }
+ int sample_rate() const { return (m_new_sample_rate != 0) ? m_new_sample_rate : m_sample_rate; }
+ attotime sample_time() const;
+ attotime sample_period() const { return attotime(0, m_attoseconds_per_sample); }
+ int input_count() const { return m_inputs; }
+ int output_count() const { return m_outputs; }
+ float input_gain(int inputnum) const;
+ float initial_input_gain(int inputnum) const;
+ const char *input_name(int inputnum, astring &string) const;
+ float output_gain(int outputnum) const;
+
+ // operations
+ void set_input(int inputnum, sound_stream *input_stream, int outputnum = 0, float gain = 1.0f);
+ void update();
+ const stream_sample_t *output_since_last_update(int outputnum, int &numsamples);
+
+ // timing
+ void set_sample_rate(int sample_rate);
+ void set_input_gain(int inputnum, float gain);
+ void set_output_gain(int outputnum, float gain);
+
+private:
+ // helpers called by our friends only
+ void update_with_accounting(bool second_tick);
+ void apply_sample_rate_changes();
+
+ // internal helpers
+ static STREAM_UPDATE( device_stream_update_stub );
+ void recompute_sample_rate_data();
+ void allocate_resample_buffers();
+ void allocate_output_buffers();
+ void postload();
+ void generate_samples(int samples);
+ stream_sample_t *generate_resampled_data(stream_input &input, UINT32 numsamples);
+
+ // linking information
+ device_t & m_device; // owning device
+ sound_stream * m_next; // next stream in the chain
+
+ // general information
+ UINT32 m_sample_rate; // sample rate of this stream
+ UINT32 m_new_sample_rate; // newly-set sample rate for the stream
+
+ // timing information
+ attoseconds_t m_attoseconds_per_sample;// number of attoseconds per sample
+ INT32 m_max_samples_per_update;// maximum samples per update
+
+ // input information
+ int m_inputs; // number of inputs
+ stream_input * m_input; // list of streams we directly depend upon
+ stream_sample_t ** m_input_array; // array of inputs for passing to the callback
+
+ // resample buffer information
+ UINT32 m_resample_bufalloc; // allocated size of each resample buffer
+
+ // output information
+ int m_outputs; // number of outputs
+ stream_output * m_output; // list of streams which directly depend upon us
+ stream_sample_t ** m_output_array; // array of outputs for passing to the callback
+
+ // output buffer information
+ UINT32 m_output_bufalloc; // allocated size of each output buffer
+ INT32 m_output_sampindex; // current position within each output buffer
+ INT32 m_output_update_sampindex;// position at time of last global update
+ INT32 m_output_base_sampindex;// sample at base of buffer, relative to the current emulated second
+
+ // callback information
+ stream_update_func m_callback; // callback function
+ void * m_param; // callback function parameter
+};
+
+
+// ======================> sound_manager
+
+class sound_manager
+{
+ friend class sound_stream;
+
+ // reasons for muting
+ static const UINT8 MUTE_REASON_PAUSE = 0x01;
+ static const UINT8 MUTE_REASON_UI = 0x02;
+ static const UINT8 MUTE_REASON_DEBUGGER = 0x04;
+ static const UINT8 MUTE_REASON_SYSTEM = 0x08;
+
+ // stream updates
+ static const attotime STREAMS_UPDATE_ATTOTIME;
+
+public:
+ static const int STREAMS_UPDATE_FREQUENCY = 50;
+
+ // construction/destruction
+ sound_manager(running_machine &machine);
+ ~sound_manager();
+
+ // getters
+ running_machine &machine() const { return m_machine; }
+ int attenuation() const { return m_attenuation; }
+ sound_stream *first_stream() const { return m_stream_list.first(); }
+ attotime last_update() const { return m_last_update; }
+ attoseconds_t update_attoseconds() const { return m_update_attoseconds; }
+
+ // stream creation
+ sound_stream *stream_alloc(device_t &device, int inputs, int outputs, int sample_rate, void *param = NULL, sound_stream::stream_update_func callback = NULL);
+
+ // global controls
+ void set_attenuation(int attenuation);
+ void ui_mute(bool turn_off = true) { mute(turn_off, MUTE_REASON_UI); }
+ void debugger_mute(bool turn_off = true) { mute(turn_off, MUTE_REASON_DEBUGGER); }
+ void system_mute(bool turn_off = true) { mute(turn_off, MUTE_REASON_SYSTEM); }
+ void system_enable(bool turn_on = true) { mute(!turn_on, MUTE_REASON_SYSTEM); }
+
+ // user gain controls
+ bool indexed_speaker_input(int index, speaker_input &info) const;
+
+private:
+ // internal helpers
+ void mute(bool mute, UINT8 reason);
+ void reset();
+ void pause();
+ void resume();
+ void config_load(int config_type, xml_data_node *parentnode);
+ void config_save(int config_type, xml_data_node *parentnode);
+
+ static TIMER_CALLBACK( update_static ) { reinterpret_cast<sound_manager *>(ptr)->update(); }
+ void update();
+
+ // internal state
+ running_machine & m_machine; // reference to our machine
+ emu_timer * m_update_timer; // timer to drive periodic updates
+
+ UINT32 m_finalmix_leftover;
+ INT16 * m_finalmix;
+ INT32 * m_leftmix;
+ INT32 * m_rightmix;
+
+ UINT8 m_muted;
+ int m_attenuation;
+ int m_nosound_mode;
+
+ wav_file * m_wavfile;
+
+ // streams data
+ simple_list<sound_stream> m_stream_list; // list of streams
+ attoseconds_t m_update_attoseconds; // attoseconds between global updates
+ attotime m_last_update; // last update time
+};
+
+
+#endif /* __SOUND_H__ */
diff --git a/trunk/src/emu/sound/2151intf.c b/trunk/src/emu/sound/2151intf.c
new file mode 100644
index 00000000000..94526decd34
--- /dev/null
+++ b/trunk/src/emu/sound/2151intf.c
@@ -0,0 +1,135 @@
+/***************************************************************************
+
+ 2151intf.c
+
+ Support interface YM2151(OPM)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "fm.h"
+#include "2151intf.h"
+#include "ym2151.h"
+
+
+typedef struct _ym2151_state ym2151_state;
+struct _ym2151_state
+{
+ sound_stream * stream;
+ emu_timer * timer[2];
+ void * chip;
+ UINT8 lastreg;
+ const ym2151_interface *intf;
+};
+
+
+INLINE ym2151_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == YM2151);
+ return (ym2151_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+static STREAM_UPDATE( ym2151_update )
+{
+ ym2151_state *info = (ym2151_state *)param;
+ ym2151_update_one(info->chip, outputs, samples);
+}
+
+
+static DEVICE_START( ym2151 )
+{
+ static const ym2151_interface dummy = { 0 };
+ ym2151_state *info = get_safe_token(device);
+ int rate;
+
+ info->intf = device->static_config() ? (const ym2151_interface *)device->static_config() : &dummy;
+
+ rate = device->clock()/64;
+
+ /* stream setup */
+ info->stream = device->machine().sound().stream_alloc(*device,0,2,rate,info,ym2151_update);
+
+ info->chip = ym2151_init(device,device->clock(),rate);
+ assert_always(info->chip != NULL, "Error creating YM2151 chip");
+
+ ym2151_set_irq_handler(info->chip,info->intf->irqhandler);
+ ym2151_set_port_write_handler(info->chip,info->intf->portwritehandler);
+}
+
+
+static DEVICE_STOP( ym2151 )
+{
+ ym2151_state *info = get_safe_token(device);
+ ym2151_shutdown(info->chip);
+}
+
+static DEVICE_RESET( ym2151 )
+{
+ ym2151_state *info = get_safe_token(device);
+ ym2151_reset_chip(info->chip);
+}
+
+
+READ8_DEVICE_HANDLER( ym2151_r )
+{
+ ym2151_state *token = get_safe_token(device);
+
+ if (offset & 1)
+ {
+ token->stream->update();
+ return ym2151_read_status(token->chip);
+ }
+ else
+ return 0xff; /* confirmed on a real YM2151 */
+}
+
+WRITE8_DEVICE_HANDLER( ym2151_w )
+{
+ ym2151_state *token = get_safe_token(device);
+
+ if (offset & 1)
+ {
+ token->stream->update();
+ ym2151_write_reg(token->chip, token->lastreg, data);
+ }
+ else
+ token->lastreg = data;
+}
+
+
+READ8_DEVICE_HANDLER( ym2151_status_port_r ) { return ym2151_r(device, 1); }
+
+WRITE8_DEVICE_HANDLER( ym2151_register_port_w ) { ym2151_w(device, 0, data); }
+WRITE8_DEVICE_HANDLER( ym2151_data_port_w ) { ym2151_w(device, 1, data); }
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+DEVICE_GET_INFO( ym2151 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(ym2151_state); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( ym2151 ); break;
+ case DEVINFO_FCT_STOP: info->stop = DEVICE_STOP_NAME( ym2151 ); break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME( ym2151 ); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "YM2151"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Yamaha FM"); 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;
+ }
+}
+
+
+DEFINE_LEGACY_SOUND_DEVICE(YM2151, ym2151);
diff --git a/trunk/src/emu/sound/2151intf.h b/trunk/src/emu/sound/2151intf.h
new file mode 100644
index 00000000000..b3b0c32e069
--- /dev/null
+++ b/trunk/src/emu/sound/2151intf.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#ifndef __2151INTF_H__
+#define __2151INTF_H__
+
+#include "devlegcy.h"
+
+typedef struct _ym2151_interface ym2151_interface;
+struct _ym2151_interface
+{
+ void (*irqhandler)(device_t *device, int irq);
+ write8_device_func portwritehandler;
+};
+
+READ8_DEVICE_HANDLER( ym2151_r );
+WRITE8_DEVICE_HANDLER( ym2151_w );
+
+READ8_DEVICE_HANDLER( ym2151_status_port_r );
+WRITE8_DEVICE_HANDLER( ym2151_register_port_w );
+WRITE8_DEVICE_HANDLER( ym2151_data_port_w );
+
+DECLARE_LEGACY_SOUND_DEVICE(YM2151, ym2151);
+
+#endif /* __2151INTF_H__ */
diff --git a/trunk/src/emu/sound/2203intf.c b/trunk/src/emu/sound/2203intf.c
new file mode 100644
index 00000000000..7a60892da78
--- /dev/null
+++ b/trunk/src/emu/sound/2203intf.c
@@ -0,0 +1,209 @@
+#include "emu.h"
+#include "2203intf.h"
+#include "fm.h"
+
+
+typedef struct _ym2203_state ym2203_state;
+struct _ym2203_state
+{
+ sound_stream * stream;
+ emu_timer * timer[2];
+ void * chip;
+ void * psg;
+ const ym2203_interface *intf;
+ device_t *device;
+};
+
+
+INLINE ym2203_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == YM2203);
+ return (ym2203_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+static void psg_set_clock(void *param, int clock)
+{
+ ym2203_state *info = (ym2203_state *)param;
+ ay8910_set_clock_ym(info->psg, clock);
+}
+
+static void psg_write(void *param, int address, int data)
+{
+ ym2203_state *info = (ym2203_state *)param;
+ ay8910_write_ym(info->psg, address, data);
+}
+
+static int psg_read(void *param)
+{
+ ym2203_state *info = (ym2203_state *)param;
+ return ay8910_read_ym(info->psg);
+}
+
+static void psg_reset(void *param)
+{
+ ym2203_state *info = (ym2203_state *)param;
+ ay8910_reset_ym(info->psg);
+}
+
+static const ssg_callbacks psgintf =
+{
+ psg_set_clock,
+ psg_write,
+ psg_read,
+ psg_reset
+};
+
+/* IRQ Handler */
+static void IRQHandler(void *param,int irq)
+{
+ ym2203_state *info = (ym2203_state *)param;
+ if (info->intf->handler != NULL)
+ (*info->intf->handler)(info->device, irq);
+}
+
+/* Timer overflow callback from timer.c */
+static TIMER_CALLBACK( timer_callback_2203_0 )
+{
+ ym2203_state *info = (ym2203_state *)ptr;
+ ym2203_timer_over(info->chip,0);
+}
+
+static TIMER_CALLBACK( timer_callback_2203_1 )
+{
+ ym2203_state *info = (ym2203_state *)ptr;
+ ym2203_timer_over(info->chip,1);
+}
+
+/* update request from fm.c */
+void ym2203_update_request(void *param)
+{
+ ym2203_state *info = (ym2203_state *)param;
+ info->stream->update();
+}
+
+
+static void timer_handler(void *param,int c,int count,int clock)
+{
+ ym2203_state *info = (ym2203_state *)param;
+ if( count == 0 )
+ { /* Reset FM Timer */
+ info->timer[c]->enable(false);
+ }
+ else
+ { /* Start FM Timer */
+ attotime period = attotime::from_hz(clock) * count;
+ if (!info->timer[c]->enable(true))
+ info->timer[c]->adjust(period);
+ }
+}
+
+static STREAM_UPDATE( ym2203_stream_update )
+{
+ ym2203_state *info = (ym2203_state *)param;
+ ym2203_update_one(info->chip, outputs[0], samples);
+}
+
+
+static void ym2203_intf_postload (ym2203_state *info)
+{
+ ym2203_postload(info->chip);
+}
+
+
+static DEVICE_START( ym2203 )
+{
+ static const ym2203_interface generic_2203 =
+ {
+ {
+ AY8910_LEGACY_OUTPUT,
+ AY8910_DEFAULT_LOADS,
+ DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_NULL
+ },
+ NULL
+ };
+ const ym2203_interface *intf = device->static_config() ? (const ym2203_interface *)device->static_config() : &generic_2203;
+ ym2203_state *info = get_safe_token(device);
+ int rate = device->clock()/72; /* ??? */
+
+ info->intf = intf;
+ info->device = device;
+ info->psg = ay8910_start_ym(NULL, YM2203, device, device->clock(), &intf->ay8910_intf);
+ assert_always(info->psg != NULL, "Error creating YM2203/AY8910 chip");
+
+ /* Timer Handler set */
+ info->timer[0] = device->machine().scheduler().timer_alloc(FUNC(timer_callback_2203_0), info);
+ info->timer[1] = device->machine().scheduler().timer_alloc(FUNC(timer_callback_2203_1), info);
+
+ /* stream system initialize */
+ info->stream = device->machine().sound().stream_alloc(*device,0,1,rate,info,ym2203_stream_update);
+
+ /* Initialize FM emurator */
+ info->chip = ym2203_init(info,device,device->clock(),rate,timer_handler,IRQHandler,&psgintf);
+ assert_always(info->chip != NULL, "Error creating YM2203 chip");
+
+ device->machine().save().register_postload(save_prepost_delegate(FUNC(ym2203_intf_postload), info));
+}
+
+static DEVICE_STOP( ym2203 )
+{
+ ym2203_state *info = get_safe_token(device);
+ ym2203_shutdown(info->chip);
+ ay8910_stop_ym(info->psg);
+}
+
+static DEVICE_RESET( ym2203 )
+{
+ ym2203_state *info = get_safe_token(device);
+ ym2203_reset_chip(info->chip);
+}
+
+
+
+READ8_DEVICE_HANDLER( ym2203_r )
+{
+ ym2203_state *info = get_safe_token(device);
+ return ym2203_read(info->chip, offset & 1);
+}
+
+WRITE8_DEVICE_HANDLER( ym2203_w )
+{
+ ym2203_state *info = get_safe_token(device);
+ ym2203_write(info->chip, offset & 1, data);
+}
+
+
+READ8_DEVICE_HANDLER( ym2203_status_port_r ) { return ym2203_r(device, 0); }
+READ8_DEVICE_HANDLER( ym2203_read_port_r ) { return ym2203_r(device, 1); }
+WRITE8_DEVICE_HANDLER( ym2203_control_port_w ) { ym2203_w(device, 0, data); }
+WRITE8_DEVICE_HANDLER( ym2203_write_port_w ) { ym2203_w(device, 1, data); }
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+DEVICE_GET_INFO( ym2203 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(ym2203_state); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( ym2203 ); break;
+ case DEVINFO_FCT_STOP: info->stop = DEVICE_STOP_NAME( ym2203 ); break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME( ym2203 ); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "YM2203"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Yamaha FM"); 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;
+ }
+}
+
+
+DEFINE_LEGACY_SOUND_DEVICE(YM2203, ym2203);
diff --git a/trunk/src/emu/sound/2203intf.h b/trunk/src/emu/sound/2203intf.h
new file mode 100644
index 00000000000..1d055cbb775
--- /dev/null
+++ b/trunk/src/emu/sound/2203intf.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#ifndef __2203INTF_H__
+#define __2203INTF_H__
+
+#include "devlegcy.h"
+
+#include "ay8910.h"
+
+void ym2203_update_request(void *param);
+
+typedef struct _ym2203_interface ym2203_interface;
+struct _ym2203_interface
+{
+ const ay8910_interface ay8910_intf;
+ void (*handler)(device_t *device, int irq);
+};
+
+READ8_DEVICE_HANDLER( ym2203_r );
+WRITE8_DEVICE_HANDLER( ym2203_w );
+
+READ8_DEVICE_HANDLER( ym2203_status_port_r );
+READ8_DEVICE_HANDLER( ym2203_read_port_r );
+WRITE8_DEVICE_HANDLER( ym2203_control_port_w );
+WRITE8_DEVICE_HANDLER( ym2203_write_port_w );
+
+DECLARE_LEGACY_SOUND_DEVICE(YM2203, ym2203);
+
+#endif /* __2203INTF_H__ */
diff --git a/trunk/src/emu/sound/2413intf.c b/trunk/src/emu/sound/2413intf.c
new file mode 100644
index 00000000000..ab4c738a1dc
--- /dev/null
+++ b/trunk/src/emu/sound/2413intf.c
@@ -0,0 +1,145 @@
+/****************************************************************
+
+ MAME / MESS functions
+
+****************************************************************/
+
+#include "emu.h"
+#include "ym2413.h"
+#include "2413intf.h"
+
+
+/* for stream system */
+typedef struct _ym2413_state ym2413_state;
+struct _ym2413_state
+{
+ sound_stream * stream;
+ void * chip;
+};
+
+
+INLINE ym2413_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == YM2413);
+ return (ym2413_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+#ifdef UNUSED_FUNCTION
+void YM2413DAC_update(int chip,stream_sample_t **inputs, stream_sample_t **_buffer,int length)
+{
+ INT16 *buffer = _buffer[0];
+ static int out = 0;
+
+ if ( ym2413[chip].reg[0x0F] & 0x01 )
+ {
+ out = ((ym2413[chip].reg[0x10] & 0xF0) << 7);
+ }
+ while (length--) *(buffer++) = out;
+}
+#endif
+
+static STREAM_UPDATE( ym2413_stream_update )
+{
+ ym2413_state *info = (ym2413_state *)param;
+ ym2413_update_one(info->chip, outputs, samples);
+}
+
+static void _stream_update(void *param, int interval)
+{
+ ym2413_state *info = (ym2413_state *)param;
+ info->stream->update();
+}
+
+static DEVICE_START( ym2413 )
+{
+ ym2413_state *info = get_safe_token(device);
+ int rate = device->clock()/72;
+
+ /* emulator create */
+ info->chip = ym2413_init(device, device->clock(), rate);
+ assert_always(info->chip != NULL, "Error creating YM2413 chip");
+
+ /* stream system initialize */
+ info->stream = device->machine().sound().stream_alloc(*device,0,2,rate,info,ym2413_stream_update);
+
+ ym2413_set_update_handler(info->chip, _stream_update, info);
+
+
+
+
+#if 0
+ int i, tst;
+ char name[40];
+
+ num = intf->num;
+
+ tst = YM3812_sh_start (msound);
+ if (tst)
+ return 1;
+
+ for (i=0;i<num;i++)
+ {
+ ym2413_reset (i);
+
+ ym2413[i].DAC_stream = device->machine().sound().stream_alloc(*device, 0, 1, device->clock()/72, i, YM2413DAC_update);
+
+ if (ym2413[i].DAC_stream == -1)
+ return 1;
+ }
+ return 0;
+#endif
+
+}
+
+static DEVICE_STOP( ym2413 )
+{
+ ym2413_state *info = get_safe_token(device);
+ ym2413_shutdown(info->chip);
+}
+
+static DEVICE_RESET( ym2413 )
+{
+ ym2413_state *info = get_safe_token(device);
+ ym2413_reset_chip(info->chip);
+}
+
+
+WRITE8_DEVICE_HANDLER( ym2413_w )
+{
+ ym2413_state *info = get_safe_token(device);
+ ym2413_write(info->chip, offset & 1, data);
+}
+
+WRITE8_DEVICE_HANDLER( ym2413_register_port_w ) { ym2413_w(device, 0, data); }
+WRITE8_DEVICE_HANDLER( ym2413_data_port_w ) { ym2413_w(device, 1, data); }
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+DEVICE_GET_INFO( ym2413 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(ym2413_state); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( ym2413 ); break;
+ case DEVINFO_FCT_STOP: info->stop = DEVICE_STOP_NAME( ym2413 ); break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME( ym2413 ); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "YM2413"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Yamaha FM"); 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;
+ }
+}
+
+
+DEFINE_LEGACY_SOUND_DEVICE(YM2413, ym2413);
diff --git a/trunk/src/emu/sound/2413intf.h b/trunk/src/emu/sound/2413intf.h
new file mode 100644
index 00000000000..6ffaa0cc035
--- /dev/null
+++ b/trunk/src/emu/sound/2413intf.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#ifndef __2413INTF_H__
+#define __2413INTF_H__
+
+#include "devlegcy.h"
+
+WRITE8_DEVICE_HANDLER( ym2413_w );
+
+WRITE8_DEVICE_HANDLER( ym2413_register_port_w );
+WRITE8_DEVICE_HANDLER( ym2413_data_port_w );
+
+DECLARE_LEGACY_SOUND_DEVICE(YM2413, ym2413);
+
+#endif /* __2413INTF_H__ */
diff --git a/trunk/src/emu/sound/2608intf.c b/trunk/src/emu/sound/2608intf.c
new file mode 100644
index 00000000000..85351acb165
--- /dev/null
+++ b/trunk/src/emu/sound/2608intf.c
@@ -0,0 +1,235 @@
+/***************************************************************************
+
+ 2608intf.c
+
+ The YM2608 emulator supports up to 2 chips.
+ Each chip has the following connections:
+ - Status Read / Control Write A
+ - Port Read / Data Write A
+ - Control Write B
+ - Data Write B
+
+***************************************************************************/
+
+#include "emu.h"
+#include "ay8910.h"
+#include "2608intf.h"
+#include "fm.h"
+
+typedef struct _ym2608_state ym2608_state;
+struct _ym2608_state
+{
+ sound_stream * stream;
+ emu_timer * timer[2];
+ void * chip;
+ void * psg;
+ const ym2608_interface *intf;
+ device_t *device;
+};
+
+
+INLINE ym2608_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == YM2608);
+ return (ym2608_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+
+static void psg_set_clock(void *param, int clock)
+{
+ ym2608_state *info = (ym2608_state *)param;
+ ay8910_set_clock_ym(info->psg, clock);
+}
+
+static void psg_write(void *param, int address, int data)
+{
+ ym2608_state *info = (ym2608_state *)param;
+ ay8910_write_ym(info->psg, address, data);
+}
+
+static int psg_read(void *param)
+{
+ ym2608_state *info = (ym2608_state *)param;
+ return ay8910_read_ym(info->psg);
+}
+
+static void psg_reset(void *param)
+{
+ ym2608_state *info = (ym2608_state *)param;
+ ay8910_reset_ym(info->psg);
+}
+
+static const ssg_callbacks psgintf =
+{
+ psg_set_clock,
+ psg_write,
+ psg_read,
+ psg_reset
+};
+
+
+/* IRQ Handler */
+static void IRQHandler(void *param,int irq)
+{
+ ym2608_state *info = (ym2608_state *)param;
+ if(info->intf->handler) info->intf->handler(info->device, irq);
+}
+
+/* Timer overflow callback from timer.c */
+static TIMER_CALLBACK( timer_callback_2608_0 )
+{
+ ym2608_state *info = (ym2608_state *)ptr;
+ ym2608_timer_over(info->chip,0);
+}
+
+static TIMER_CALLBACK( timer_callback_2608_1 )
+{
+ ym2608_state *info = (ym2608_state *)ptr;
+ ym2608_timer_over(info->chip,1);
+}
+
+static void timer_handler(void *param,int c,int count,int clock)
+{
+ ym2608_state *info = (ym2608_state *)param;
+ if( count == 0 )
+ { /* Reset FM Timer */
+ info->timer[c]->enable(false);
+ }
+ else
+ { /* Start FM Timer */
+ attotime period = attotime::from_hz(clock) * count;
+ if (!info->timer[c]->enable(true))
+ info->timer[c]->adjust(period);
+ }
+}
+
+/* update request from fm.c */
+void ym2608_update_request(void *param)
+{
+ ym2608_state *info = (ym2608_state *)param;
+ info->stream->update();
+}
+
+static STREAM_UPDATE( ym2608_stream_update )
+{
+ ym2608_state *info = (ym2608_state *)param;
+ ym2608_update_one(info->chip, outputs, samples);
+}
+
+
+static void ym2608_intf_postload(ym2608_state *info)
+{
+ ym2608_postload(info->chip);
+}
+
+
+static DEVICE_START( ym2608 )
+{
+ static const ym2608_interface generic_2608 =
+ {
+ {
+ AY8910_LEGACY_OUTPUT | AY8910_SINGLE_OUTPUT,
+ AY8910_DEFAULT_LOADS,
+ DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_NULL
+ },
+ NULL
+ };
+ const ym2608_interface *intf = device->static_config() ? (const ym2608_interface *)device->static_config() : &generic_2608;
+ int rate = device->clock()/72;
+ void *pcmbufa;
+ int pcmsizea;
+
+ ym2608_state *info = get_safe_token(device);
+
+ info->intf = intf;
+ info->device = device;
+
+ /* FIXME: Force to use simgle output */
+ info->psg = ay8910_start_ym(NULL, YM2608, device, device->clock(), &intf->ay8910_intf);
+ assert_always(info->psg != NULL, "Error creating YM2608/AY8910 chip");
+
+ /* Timer Handler set */
+ info->timer[0] = device->machine().scheduler().timer_alloc(FUNC(timer_callback_2608_0), info);
+ info->timer[1] = device->machine().scheduler().timer_alloc(FUNC(timer_callback_2608_1), info);
+
+ /* stream system initialize */
+ info->stream = device->machine().sound().stream_alloc(*device,0,2,rate,info,ym2608_stream_update);
+ /* setup adpcm buffers */
+ pcmbufa = *device->region();
+ pcmsizea = device->region()->bytes();
+
+ /* initialize YM2608 */
+ info->chip = ym2608_init(info,device,device->clock(),rate,
+ pcmbufa,pcmsizea,
+ timer_handler,IRQHandler,&psgintf);
+ assert_always(info->chip != NULL, "Error creating YM2608 chip");
+
+ device->machine().save().register_postload(save_prepost_delegate(FUNC(ym2608_intf_postload), info));
+}
+
+static DEVICE_STOP( ym2608 )
+{
+ ym2608_state *info = get_safe_token(device);
+ ym2608_shutdown(info->chip);
+ ay8910_stop_ym(info->psg);
+}
+
+static DEVICE_RESET( ym2608 )
+{
+ ym2608_state *info = get_safe_token(device);
+ ym2608_reset_chip(info->chip);
+}
+
+
+READ8_DEVICE_HANDLER( ym2608_r )
+{
+ ym2608_state *info = get_safe_token(device);
+ return ym2608_read(info->chip, offset & 3);
+}
+
+WRITE8_DEVICE_HANDLER( ym2608_w )
+{
+ ym2608_state *info = get_safe_token(device);
+ ym2608_write(info->chip, offset & 3, data);
+}
+
+READ8_DEVICE_HANDLER( ym2608_read_port_r ) { return ym2608_r(device, 1); }
+READ8_DEVICE_HANDLER( ym2608_status_port_a_r ) { return ym2608_r(device, 0); }
+READ8_DEVICE_HANDLER( ym2608_status_port_b_r ) { return ym2608_r(device, 2); }
+
+WRITE8_DEVICE_HANDLER( ym2608_control_port_a_w ) { ym2608_w(device, 0, data); }
+WRITE8_DEVICE_HANDLER( ym2608_control_port_b_w ) { ym2608_w(device, 2, data); }
+WRITE8_DEVICE_HANDLER( ym2608_data_port_a_w ) { ym2608_w(device, 1, data); }
+WRITE8_DEVICE_HANDLER( ym2608_data_port_b_w ) { ym2608_w(device, 3, data); }
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+DEVICE_GET_INFO( ym2608 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(ym2608_state); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( ym2608 ); break;
+ case DEVINFO_FCT_STOP: info->stop = DEVICE_STOP_NAME( ym2608 ); break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME( ym2608 ); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "YM2608"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Yamaha FM"); 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;
+ }
+}
+
+
+DEFINE_LEGACY_SOUND_DEVICE(YM2608, ym2608);
diff --git a/trunk/src/emu/sound/2608intf.h b/trunk/src/emu/sound/2608intf.h
new file mode 100644
index 00000000000..8a8fb65dc26
--- /dev/null
+++ b/trunk/src/emu/sound/2608intf.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#ifndef __2608INTF_H__
+#define __2608INTF_H__
+
+#include "devlegcy.h"
+
+#include "fm.h"
+#include "ay8910.h"
+
+void ym2608_update_request(void *param);
+
+typedef struct _ym2608_interface ym2608_interface;
+struct _ym2608_interface
+{
+ const ay8910_interface ay8910_intf;
+ void ( *handler )( device_t *device, int irq ); /* IRQ handler for the YM2608 */
+};
+
+READ8_DEVICE_HANDLER( ym2608_r );
+WRITE8_DEVICE_HANDLER( ym2608_w );
+
+READ8_DEVICE_HANDLER( ym2608_read_port_r );
+READ8_DEVICE_HANDLER( ym2608_status_port_a_r );
+READ8_DEVICE_HANDLER( ym2608_status_port_b_r );
+
+WRITE8_DEVICE_HANDLER( ym2608_control_port_a_w );
+WRITE8_DEVICE_HANDLER( ym2608_control_port_b_w );
+WRITE8_DEVICE_HANDLER( ym2608_data_port_a_w );
+WRITE8_DEVICE_HANDLER( ym2608_data_port_b_w );
+
+DECLARE_LEGACY_SOUND_DEVICE(YM2608, ym2608);
+
+#endif /* __2608INTF_H__ */
diff --git a/trunk/src/emu/sound/2610intf.c b/trunk/src/emu/sound/2610intf.c
new file mode 100644
index 00000000000..3c13dfda578
--- /dev/null
+++ b/trunk/src/emu/sound/2610intf.c
@@ -0,0 +1,260 @@
+/***************************************************************************
+
+ 2610intf.c
+
+ The YM2610 emulator supports up to 2 chips.
+ Each chip has the following connections:
+ - Status Read / Control Write A
+ - Port Read / Data Write A
+ - Control Write B
+ - Data Write B
+
+***************************************************************************/
+
+#include "emu.h"
+#include "ay8910.h"
+#include "2610intf.h"
+#include "fm.h"
+
+typedef struct _ym2610_state ym2610_state;
+struct _ym2610_state
+{
+ sound_stream * stream;
+ emu_timer * timer[2];
+ void * chip;
+ void * psg;
+ const ym2610_interface *intf;
+ device_t *device;
+};
+
+
+INLINE ym2610_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == YM2610 || device->type() == YM2610B);
+ return (ym2610_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+static void psg_set_clock(void *param, int clock)
+{
+ ym2610_state *info = (ym2610_state *)param;
+ ay8910_set_clock_ym(info->psg, clock);
+}
+
+static void psg_write(void *param, int address, int data)
+{
+ ym2610_state *info = (ym2610_state *)param;
+ ay8910_write_ym(info->psg, address, data);
+}
+
+static int psg_read(void *param)
+{
+ ym2610_state *info = (ym2610_state *)param;
+ return ay8910_read_ym(info->psg);
+}
+
+static void psg_reset(void *param)
+{
+ ym2610_state *info = (ym2610_state *)param;
+ ay8910_reset_ym(info->psg);
+}
+
+static const ssg_callbacks psgintf =
+{
+ psg_set_clock,
+ psg_write,
+ psg_read,
+ psg_reset
+};
+
+/*------------------------- TM2610 -------------------------------*/
+/* IRQ Handler */
+static void IRQHandler(void *param,int irq)
+{
+ ym2610_state *info = (ym2610_state *)param;
+ if(info->intf->handler) info->intf->handler(info->device, irq);
+}
+
+/* Timer overflow callback from timer.c */
+static TIMER_CALLBACK( timer_callback_0 )
+{
+ ym2610_state *info = (ym2610_state *)ptr;
+ ym2610_timer_over(info->chip,0);
+}
+
+static TIMER_CALLBACK( timer_callback_1 )
+{
+ ym2610_state *info = (ym2610_state *)ptr;
+ ym2610_timer_over(info->chip,1);
+}
+
+static void timer_handler(void *param,int c,int count,int clock)
+{
+ ym2610_state *info = (ym2610_state *)param;
+ if( count == 0 )
+ { /* Reset FM Timer */
+ info->timer[c]->enable(false);
+ }
+ else
+ { /* Start FM Timer */
+ attotime period = attotime::from_hz(clock) * count;
+
+ if (!info->timer[c]->enable(true))
+ info->timer[c]->adjust(period);
+ }
+}
+
+/* update request from fm.c */
+void ym2610_update_request(void *param)
+{
+ ym2610_state *info = (ym2610_state *)param;
+ info->stream->update();
+}
+
+
+static STREAM_UPDATE( ym2610_stream_update )
+{
+ ym2610_state *info = (ym2610_state *)param;
+ ym2610_update_one(info->chip, outputs, samples);
+}
+
+static STREAM_UPDATE( ym2610b_stream_update )
+{
+ ym2610_state *info = (ym2610_state *)param;
+ ym2610b_update_one(info->chip, outputs, samples);
+}
+
+
+static void ym2610_intf_postload(ym2610_state *info)
+{
+ ym2610_postload(info->chip);
+}
+
+
+static DEVICE_START( ym2610 )
+{
+ static const ym2610_interface generic_2610 = { 0 };
+ static const ay8910_interface generic_ay8910 =
+ {
+ AY8910_LEGACY_OUTPUT | AY8910_SINGLE_OUTPUT,
+ AY8910_DEFAULT_LOADS,
+ DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_NULL
+ };
+ const ym2610_interface *intf = device->static_config() ? (const ym2610_interface *)device->static_config() : &generic_2610;
+ int rate = device->clock()/72;
+ void *pcmbufa,*pcmbufb;
+ int pcmsizea,pcmsizeb;
+ ym2610_state *info = get_safe_token(device);
+ astring name;
+ device_type type = device->type();
+
+ info->intf = intf;
+ info->device = device;
+ info->psg = ay8910_start_ym(NULL, device->type(), device, device->clock(), &generic_ay8910);
+ assert_always(info->psg != NULL, "Error creating YM2610/AY8910 chip");
+
+ /* Timer Handler set */
+ info->timer[0] = device->machine().scheduler().timer_alloc(FUNC(timer_callback_0), info);
+ info->timer[1] = device->machine().scheduler().timer_alloc(FUNC(timer_callback_1), info);
+
+ /* stream system initialize */
+ info->stream = device->machine().sound().stream_alloc(*device,0,2,rate,info,(type == YM2610) ? ym2610_stream_update : ym2610b_stream_update);
+ /* setup adpcm buffers */
+ pcmbufa = *device->region();
+ pcmsizea = device->region()->bytes();
+ name.printf("%s.deltat", device->tag());
+ pcmbufb = (void *)(device->machine().region(name)->base());
+ pcmsizeb = device->machine().region(name)->bytes();
+ if (pcmbufb == NULL || pcmsizeb == 0)
+ {
+ pcmbufb = pcmbufa;
+ pcmsizeb = pcmsizea;
+ }
+
+ /**** initialize YM2610 ****/
+ info->chip = ym2610_init(info,device,device->clock(),rate,
+ pcmbufa,pcmsizea,pcmbufb,pcmsizeb,
+ timer_handler,IRQHandler,&psgintf);
+ assert_always(info->chip != NULL, "Error creating YM2610 chip");
+
+ device->machine().save().register_postload(save_prepost_delegate(FUNC(ym2610_intf_postload), info));
+}
+
+static DEVICE_STOP( ym2610 )
+{
+ ym2610_state *info = get_safe_token(device);
+ ym2610_shutdown(info->chip);
+ ay8910_stop_ym(info->psg);
+}
+
+static DEVICE_RESET( ym2610 )
+{
+ ym2610_state *info = get_safe_token(device);
+ ym2610_reset_chip(info->chip);
+}
+
+
+READ8_DEVICE_HANDLER( ym2610_r )
+{
+ ym2610_state *info = get_safe_token(device);
+ return ym2610_read(info->chip, offset & 3);
+}
+
+WRITE8_DEVICE_HANDLER( ym2610_w )
+{
+ ym2610_state *info = get_safe_token(device);
+ ym2610_write(info->chip, offset & 3, data);
+}
+
+
+READ8_DEVICE_HANDLER( ym2610_status_port_a_r ) { return ym2610_r(device, 0); }
+READ8_DEVICE_HANDLER( ym2610_status_port_b_r ) { return ym2610_r(device, 2); }
+READ8_DEVICE_HANDLER( ym2610_read_port_r ) { return ym2610_r(device, 1); }
+
+WRITE8_DEVICE_HANDLER( ym2610_control_port_a_w ) { ym2610_w(device, 0, data); }
+WRITE8_DEVICE_HANDLER( ym2610_control_port_b_w ) { ym2610_w(device, 2, data); }
+WRITE8_DEVICE_HANDLER( ym2610_data_port_a_w ) { ym2610_w(device, 1, data); }
+WRITE8_DEVICE_HANDLER( ym2610_data_port_b_w ) { ym2610_w(device, 3, data); }
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+DEVICE_GET_INFO( ym2610 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(ym2610_state); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( ym2610 ); break;
+ case DEVINFO_FCT_STOP: info->stop = DEVICE_STOP_NAME( ym2610 ); break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME( ym2610 ); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "YM2610"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Yamaha FM"); 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;
+ }
+}
+
+DEVICE_GET_INFO( ym2610b )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "YM2610B"); break;
+
+ default: DEVICE_GET_INFO_CALL(ym2610); break;
+ }
+}
+
+
+DEFINE_LEGACY_SOUND_DEVICE(YM2610, ym2610);
+DEFINE_LEGACY_SOUND_DEVICE(YM2610B, ym2610b);
diff --git a/trunk/src/emu/sound/2610intf.h b/trunk/src/emu/sound/2610intf.h
new file mode 100644
index 00000000000..d7a02856638
--- /dev/null
+++ b/trunk/src/emu/sound/2610intf.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#ifndef __2610INTF_H__
+#define __2610INTF_H__
+
+#include "devlegcy.h"
+#include "fm.h"
+
+
+void ym2610_update_request(void *param);
+
+typedef struct _ym2610_interface ym2610_interface;
+struct _ym2610_interface
+{
+ void ( *handler )( device_t *device, int irq ); /* IRQ handler for the YM2610 */
+};
+
+READ8_DEVICE_HANDLER( ym2610_r );
+WRITE8_DEVICE_HANDLER( ym2610_w );
+
+READ8_DEVICE_HANDLER( ym2610_status_port_a_r );
+READ8_DEVICE_HANDLER( ym2610_status_port_b_r );
+READ8_DEVICE_HANDLER( ym2610_read_port_r );
+
+WRITE8_DEVICE_HANDLER( ym2610_control_port_a_w );
+WRITE8_DEVICE_HANDLER( ym2610_control_port_b_w );
+WRITE8_DEVICE_HANDLER( ym2610_data_port_a_w );
+WRITE8_DEVICE_HANDLER( ym2610_data_port_b_w );
+
+
+DECLARE_LEGACY_SOUND_DEVICE(YM2610, ym2610);
+DECLARE_LEGACY_SOUND_DEVICE(YM2610B, ym2610b);
+
+#endif /* __2610INTF_H__ */
diff --git a/trunk/src/emu/sound/2612intf.c b/trunk/src/emu/sound/2612intf.c
new file mode 100644
index 00000000000..f6d95ad0452
--- /dev/null
+++ b/trunk/src/emu/sound/2612intf.c
@@ -0,0 +1,202 @@
+/***************************************************************************
+
+ 2612intf.c
+
+ The YM2612 emulator supports up to 2 chips.
+ Each chip has the following connections:
+ - Status Read / Control Write A
+ - Port Read / Data Write A
+ - Control Write B
+ - Data Write B
+
+***************************************************************************/
+
+#include "emu.h"
+#include "sound/fm.h"
+#include "sound/2612intf.h"
+
+
+typedef struct _ym2612_state ym2612_state;
+struct _ym2612_state
+{
+ sound_stream * stream;
+ emu_timer * timer[2];
+ void * chip;
+ const ym2612_interface *intf;
+ device_t *device;
+};
+
+
+INLINE ym2612_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == YM2612 || device->type() == YM3438);
+ return (ym2612_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+
+/*------------------------- TM2612 -------------------------------*/
+/* IRQ Handler */
+static void IRQHandler(void *param,int irq)
+{
+ ym2612_state *info = (ym2612_state *)param;
+ if(info->intf->handler) info->intf->handler(info->device, irq);
+}
+
+/* Timer overflow callback from timer.c */
+static TIMER_CALLBACK( timer_callback_2612_0 )
+{
+ ym2612_state *info = (ym2612_state *)ptr;
+ ym2612_timer_over(info->chip,0);
+}
+
+static TIMER_CALLBACK( timer_callback_2612_1 )
+{
+ ym2612_state *info = (ym2612_state *)ptr;
+ ym2612_timer_over(info->chip,1);
+}
+
+static void timer_handler(void *param,int c,int count,int clock)
+{
+ ym2612_state *info = (ym2612_state *)param;
+ if( count == 0 )
+ { /* Reset FM Timer */
+ info->timer[c]->enable(false);
+ }
+ else
+ { /* Start FM Timer */
+ attotime period = attotime::from_hz(clock) * count;
+ if (!info->timer[c]->enable(1))
+ info->timer[c]->adjust(period);
+ }
+}
+
+/* update request from fm.c */
+void ym2612_update_request(void *param)
+{
+ ym2612_state *info = (ym2612_state *)param;
+ info->stream->update();
+}
+
+/***********************************************************/
+/* YM2612 */
+/***********************************************************/
+
+static STREAM_UPDATE( ym2612_stream_update )
+{
+ ym2612_state *info = (ym2612_state *)param;
+ ym2612_update_one(info->chip, outputs, samples);
+}
+
+
+static void ym2612_intf_postload(ym2612_state *info)
+{
+ ym2612_postload(info->chip);
+}
+
+
+static DEVICE_START( ym2612 )
+{
+ static const ym2612_interface dummy = { 0 };
+ ym2612_state *info = get_safe_token(device);
+ int rate = device->clock()/72;
+
+ info->intf = device->static_config() ? (const ym2612_interface *)device->static_config() : &dummy;
+ info->device = device;
+
+ /* FM init */
+ /* Timer Handler set */
+ info->timer[0] = device->machine().scheduler().timer_alloc(FUNC(timer_callback_2612_0), info);
+ info->timer[1] = device->machine().scheduler().timer_alloc(FUNC(timer_callback_2612_1), info);
+
+ /* stream system initialize */
+ info->stream = device->machine().sound().stream_alloc(*device,0,2,rate,info,ym2612_stream_update);
+
+ /**** initialize YM2612 ****/
+ info->chip = ym2612_init(info,device,device->clock(),rate,timer_handler,IRQHandler);
+ assert_always(info->chip != NULL, "Error creating YM2612 chip");
+
+ device->machine().save().register_postload(save_prepost_delegate(FUNC(ym2612_intf_postload), info));
+}
+
+
+static DEVICE_STOP( ym2612 )
+{
+ ym2612_state *info = get_safe_token(device);
+ ym2612_shutdown(info->chip);
+}
+
+static DEVICE_RESET( ym2612 )
+{
+ ym2612_state *info = get_safe_token(device);
+ ym2612_reset_chip(info->chip);
+}
+
+
+READ8_DEVICE_HANDLER( ym2612_r )
+{
+ ym2612_state *info = get_safe_token(device);
+ return ym2612_read(info->chip, offset & 3);
+}
+
+WRITE8_DEVICE_HANDLER( ym2612_w )
+{
+ ym2612_state *info = get_safe_token(device);
+ ym2612_write(info->chip, offset & 3, data);
+}
+
+
+READ8_DEVICE_HANDLER( ym2612_status_port_a_r ) { return ym2612_r(device, 0); }
+READ8_DEVICE_HANDLER( ym2612_status_port_b_r ) { return ym2612_r(device, 2); }
+READ8_DEVICE_HANDLER( ym2612_data_port_a_r ) { return ym2612_r(device, 1); }
+READ8_DEVICE_HANDLER( ym2612_data_port_b_r ) { return ym2612_r(device, 3); }
+
+WRITE8_DEVICE_HANDLER( ym2612_control_port_a_w ) { ym2612_w(device, 0, data); }
+WRITE8_DEVICE_HANDLER( ym2612_control_port_b_w ) { ym2612_w(device, 2, data); }
+WRITE8_DEVICE_HANDLER( ym2612_data_port_a_w ) { ym2612_w(device, 1, data); }
+WRITE8_DEVICE_HANDLER( ym2612_data_port_b_w ) { ym2612_w(device, 3, data); }
+
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+DEVICE_GET_INFO( ym2612 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(ym2612_state); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( ym2612 ); break;
+ case DEVINFO_FCT_STOP: info->stop = DEVICE_STOP_NAME( ym2612 ); break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME( ym2612 ); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "YM2612"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Yamaha FM"); 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;
+ }
+}
+
+
+DEVICE_GET_INFO( ym3438 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "YM3438"); break;
+
+ default: DEVICE_GET_INFO_CALL(ym2612); break;
+ }
+}
+
+
+DEFINE_LEGACY_SOUND_DEVICE(YM2612, ym2612);
+DEFINE_LEGACY_SOUND_DEVICE(YM3438, ym3438);
diff --git a/trunk/src/emu/sound/2612intf.h b/trunk/src/emu/sound/2612intf.h
new file mode 100644
index 00000000000..61a9294e484
--- /dev/null
+++ b/trunk/src/emu/sound/2612intf.h
@@ -0,0 +1,56 @@
+#pragma once
+
+#ifndef __2612INTF_H__
+#define __2612INTF_H__
+
+#include "devlegcy.h"
+
+void ym2612_update_request(void *param);
+
+typedef struct _ym2612_interface ym2612_interface;
+struct _ym2612_interface
+{
+ void (*handler)(device_t *device, int irq);
+};
+
+READ8_DEVICE_HANDLER( ym2612_r );
+WRITE8_DEVICE_HANDLER( ym2612_w );
+
+READ8_DEVICE_HANDLER( ym2612_status_port_a_r );
+READ8_DEVICE_HANDLER( ym2612_status_port_b_r );
+READ8_DEVICE_HANDLER( ym2612_data_port_a_r );
+READ8_DEVICE_HANDLER( ym2612_data_port_b_r );
+
+WRITE8_DEVICE_HANDLER( ym2612_control_port_a_w );
+WRITE8_DEVICE_HANDLER( ym2612_control_port_b_w );
+WRITE8_DEVICE_HANDLER( ym2612_data_port_a_w );
+WRITE8_DEVICE_HANDLER( ym2612_data_port_b_w );
+
+
+DECLARE_LEGACY_SOUND_DEVICE(YM2612, ym2612);
+
+
+typedef struct _ym3438_interface ym3438_interface;
+struct _ym3438_interface
+{
+ void (*handler)(device_t *device, int irq);
+};
+
+
+#define ym3438_r ym2612_r
+#define ym3438_w ym2612_w
+
+#define ym3438_status_port_a_r ym2612_status_port_a_r
+#define ym3438_status_port_b_r ym2612_status_port_b_r
+#define ym3438_data_port_a_r ym2612_data_port_a_r
+#define ym3438_data_port_b_r ym2612_data_port_b_r
+
+#define ym3438_control_port_a_w ym2612_control_port_a_w
+#define ym3438_control_port_b_w ym2612_control_port_b_w
+#define ym3438_data_port_a_w ym2612_data_port_a_w
+#define ym3438_data_port_b_w ym2612_data_port_b_w
+
+
+DECLARE_LEGACY_SOUND_DEVICE(YM3438, ym3438);
+
+#endif /* __2612INTF_H__ */
diff --git a/trunk/src/emu/sound/262intf.c b/trunk/src/emu/sound/262intf.c
new file mode 100644
index 00000000000..de329c7eaf9
--- /dev/null
+++ b/trunk/src/emu/sound/262intf.c
@@ -0,0 +1,161 @@
+/***************************************************************************
+
+ 262intf.c
+
+ MAME interface for YMF262 (OPL3) emulator
+
+***************************************************************************/
+#include "emu.h"
+#include "262intf.h"
+#include "ymf262.h"
+
+
+typedef struct _ymf262_state ymf262_state;
+struct _ymf262_state
+{
+ sound_stream * stream;
+ emu_timer * timer[2];
+ void * chip;
+ const ymf262_interface *intf;
+ device_t *device;
+};
+
+
+INLINE ymf262_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == YMF262);
+ return (ymf262_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+
+
+static void IRQHandler_262(void *param,int irq)
+{
+ ymf262_state *info = (ymf262_state *)param;
+ if (info->intf->handler) (info->intf->handler)(info->device, irq);
+}
+
+static TIMER_CALLBACK( timer_callback_262_0 )
+{
+ ymf262_state *info = (ymf262_state *)ptr;
+ ymf262_timer_over(info->chip, 0);
+}
+
+static TIMER_CALLBACK( timer_callback_262_1 )
+{
+ ymf262_state *info = (ymf262_state *)ptr;
+ ymf262_timer_over(info->chip, 1);
+}
+
+static void timer_handler_262(void *param,int timer, attotime period)
+{
+ ymf262_state *info = (ymf262_state *)param;
+ if( period == attotime::zero )
+ { /* Reset FM Timer */
+ info->timer[timer]->enable(false);
+ }
+ else
+ { /* Start FM Timer */
+ info->timer[timer]->adjust(period);
+ }
+}
+
+static STREAM_UPDATE( ymf262_stream_update )
+{
+ ymf262_state *info = (ymf262_state *)param;
+ ymf262_update_one(info->chip, outputs, samples);
+}
+
+static void _stream_update(void *param, int interval)
+{
+ ymf262_state *info = (ymf262_state *)param;
+ info->stream->update();
+}
+
+
+static DEVICE_START( ymf262 )
+{
+ static const ymf262_interface dummy = { 0 };
+ ymf262_state *info = get_safe_token(device);
+ int rate = device->clock()/288;
+
+ info->intf = device->static_config() ? (const ymf262_interface *)device->static_config() : &dummy;
+ info->device = device;
+
+ /* stream system initialize */
+ info->chip = ymf262_init(device,device->clock(),rate);
+ assert_always(info->chip != NULL, "Error creating YMF262 chip");
+
+ info->stream = device->machine().sound().stream_alloc(*device,0,4,rate,info,ymf262_stream_update);
+
+ /* YMF262 setup */
+ ymf262_set_timer_handler (info->chip, timer_handler_262, info);
+ ymf262_set_irq_handler (info->chip, IRQHandler_262, info);
+ ymf262_set_update_handler(info->chip, _stream_update, info);
+
+ info->timer[0] = device->machine().scheduler().timer_alloc(FUNC(timer_callback_262_0), info);
+ info->timer[1] = device->machine().scheduler().timer_alloc(FUNC(timer_callback_262_1), info);
+}
+
+static DEVICE_STOP( ymf262 )
+{
+ ymf262_state *info = get_safe_token(device);
+ ymf262_shutdown(info->chip);
+}
+
+/* reset */
+static DEVICE_RESET( ymf262 )
+{
+ ymf262_state *info = get_safe_token(device);
+ ymf262_reset_chip(info->chip);
+}
+
+
+READ8_DEVICE_HANDLER( ymf262_r )
+{
+ ymf262_state *info = get_safe_token(device);
+ return ymf262_read(info->chip, offset & 3);
+}
+
+WRITE8_DEVICE_HANDLER( ymf262_w )
+{
+ ymf262_state *info = get_safe_token(device);
+ ymf262_write(info->chip, offset & 3, data);
+}
+
+READ8_DEVICE_HANDLER ( ymf262_status_r ) { return ymf262_r(device, 0); }
+WRITE8_DEVICE_HANDLER( ymf262_register_a_w ) { ymf262_w(device, 0, data); }
+WRITE8_DEVICE_HANDLER( ymf262_register_b_w ) { ymf262_w(device, 2, data); }
+WRITE8_DEVICE_HANDLER( ymf262_data_a_w ) { ymf262_w(device, 1, data); }
+WRITE8_DEVICE_HANDLER( ymf262_data_b_w ) { ymf262_w(device, 3, data); }
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+DEVICE_GET_INFO( ymf262 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(ymf262_state); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( ymf262 ); break;
+ case DEVINFO_FCT_STOP: info->stop = DEVICE_STOP_NAME( ymf262 ); break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME( ymf262 ); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "YMF262"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Yamaha FM"); 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;
+ }
+}
+
+
+DEFINE_LEGACY_SOUND_DEVICE(YMF262, ymf262);
diff --git a/trunk/src/emu/sound/262intf.h b/trunk/src/emu/sound/262intf.h
new file mode 100644
index 00000000000..a458273ae47
--- /dev/null
+++ b/trunk/src/emu/sound/262intf.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#ifndef __262INTF_H__
+#define __262INTF_H__
+
+#include "devlegcy.h"
+
+
+typedef struct _ymf262_interface ymf262_interface;
+struct _ymf262_interface
+{
+ void (*handler)(device_t *device, int irq);
+};
+
+
+READ8_DEVICE_HANDLER( ymf262_r );
+WRITE8_DEVICE_HANDLER( ymf262_w );
+
+READ8_DEVICE_HANDLER ( ymf262_status_r );
+WRITE8_DEVICE_HANDLER( ymf262_register_a_w );
+WRITE8_DEVICE_HANDLER( ymf262_register_b_w );
+WRITE8_DEVICE_HANDLER( ymf262_data_a_w );
+WRITE8_DEVICE_HANDLER( ymf262_data_b_w );
+
+
+DECLARE_LEGACY_SOUND_DEVICE(YMF262, ymf262);
+
+#endif /* __262INTF_H__ */
diff --git a/trunk/src/emu/sound/3526intf.c b/trunk/src/emu/sound/3526intf.c
new file mode 100644
index 00000000000..861dbc78a40
--- /dev/null
+++ b/trunk/src/emu/sound/3526intf.c
@@ -0,0 +1,169 @@
+/******************************************************************************
+* FILE
+* Yamaha 3812 emulator interface - MAME VERSION
+*
+* CREATED BY
+* Ernesto Corvi
+*
+* UPDATE LOG
+* JB 28-04-2002 Fixed simultaneous usage of all three different chip types.
+* Used real sample rate when resample filter is active.
+* AAT 12-28-2001 Protected Y8950 from accessing unmapped port and keyboard handlers.
+* CHS 1999-01-09 Fixes new ym3812 emulation interface.
+* CHS 1998-10-23 Mame streaming sound chip update
+* EC 1998 Created Interface
+*
+* NOTES
+*
+******************************************************************************/
+#include "emu.h"
+#include "3526intf.h"
+#include "fm.h"
+#include "sound/fmopl.h"
+
+
+typedef struct _ym3526_state ym3526_state;
+struct _ym3526_state
+{
+ sound_stream * stream;
+ emu_timer * timer[2];
+ void * chip;
+ const ym3526_interface *intf;
+ device_t *device;
+};
+
+
+INLINE ym3526_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == YM3526);
+ return (ym3526_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+/* IRQ Handler */
+static void IRQHandler(void *param,int irq)
+{
+ ym3526_state *info = (ym3526_state *)param;
+ if (info->intf->handler) (info->intf->handler)(info->device, irq ? ASSERT_LINE : CLEAR_LINE);
+}
+/* Timer overflow callback from timer.c */
+static TIMER_CALLBACK( timer_callback_0 )
+{
+ ym3526_state *info = (ym3526_state *)ptr;
+ ym3526_timer_over(info->chip,0);
+}
+static TIMER_CALLBACK( timer_callback_1 )
+{
+ ym3526_state *info = (ym3526_state *)ptr;
+ ym3526_timer_over(info->chip,1);
+}
+/* TimerHandler from fm.c */
+static void TimerHandler(void *param,int c,attotime period)
+{
+ ym3526_state *info = (ym3526_state *)param;
+ if( period == attotime::zero )
+ { /* Reset FM Timer */
+ info->timer[c]->enable(false);
+ }
+ else
+ { /* Start FM Timer */
+ info->timer[c]->adjust(period);
+ }
+}
+
+
+static STREAM_UPDATE( ym3526_stream_update )
+{
+ ym3526_state *info = (ym3526_state *)param;
+ ym3526_update_one(info->chip, outputs[0], samples);
+}
+
+static void _stream_update(void *param, int interval)
+{
+ ym3526_state *info = (ym3526_state *)param;
+ info->stream->update();
+}
+
+
+static DEVICE_START( ym3526 )
+{
+ static const ym3526_interface dummy = { 0 };
+ ym3526_state *info = get_safe_token(device);
+ int rate = device->clock()/72;
+
+ info->intf = device->static_config() ? (const ym3526_interface *)device->static_config() : &dummy;
+ info->device = device;
+
+ /* stream system initialize */
+ info->chip = ym3526_init(device,device->clock(),rate);
+ assert_always(info->chip != NULL, "Error creating YM3526 chip");
+
+ info->stream = device->machine().sound().stream_alloc(*device,0,1,rate,info,ym3526_stream_update);
+ /* YM3526 setup */
+ ym3526_set_timer_handler (info->chip, TimerHandler, info);
+ ym3526_set_irq_handler (info->chip, IRQHandler, info);
+ ym3526_set_update_handler(info->chip, _stream_update, info);
+
+ info->timer[0] = device->machine().scheduler().timer_alloc(FUNC(timer_callback_0), info);
+ info->timer[1] = device->machine().scheduler().timer_alloc(FUNC(timer_callback_1), info);
+}
+
+static DEVICE_STOP( ym3526 )
+{
+ ym3526_state *info = get_safe_token(device);
+ ym3526_shutdown(info->chip);
+}
+
+static DEVICE_RESET( ym3526 )
+{
+ ym3526_state *info = get_safe_token(device);
+ ym3526_reset_chip(info->chip);
+}
+
+
+READ8_DEVICE_HANDLER( ym3526_r )
+{
+ ym3526_state *info = get_safe_token(device);
+ return ym3526_read(info->chip, offset & 1);
+}
+
+WRITE8_DEVICE_HANDLER( ym3526_w )
+{
+ ym3526_state *info = get_safe_token(device);
+ ym3526_write(info->chip, offset & 1, data);
+}
+
+READ8_DEVICE_HANDLER( ym3526_status_port_r ) { return ym3526_r(device, 0); }
+READ8_DEVICE_HANDLER( ym3526_read_port_r ) { return ym3526_r(device, 1); }
+WRITE8_DEVICE_HANDLER( ym3526_control_port_w ) { ym3526_w(device, 0, data); }
+WRITE8_DEVICE_HANDLER( ym3526_write_port_w ) { ym3526_w(device, 1, data); }
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+DEVICE_GET_INFO( ym3526 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(ym3526_state); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( ym3526 ); break;
+ case DEVINFO_FCT_STOP: info->stop = DEVICE_STOP_NAME( ym3526 ); break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME( ym3526 ); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "YM3526"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Yamaha FM"); 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;
+ }
+}
+
+
+DEFINE_LEGACY_SOUND_DEVICE(YM3526, ym3526);
diff --git a/trunk/src/emu/sound/3526intf.h b/trunk/src/emu/sound/3526intf.h
new file mode 100644
index 00000000000..69df7a67731
--- /dev/null
+++ b/trunk/src/emu/sound/3526intf.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#ifndef __3526INTF_H__
+#define __3526INTF_H__
+
+#include "devlegcy.h"
+
+typedef struct _ym3526_interface ym3526_interface;
+struct _ym3526_interface
+{
+ void (*handler)(device_t *device, int linestate);
+};
+
+READ8_DEVICE_HANDLER( ym3526_r );
+WRITE8_DEVICE_HANDLER( ym3526_w );
+
+READ8_DEVICE_HANDLER( ym3526_status_port_r );
+READ8_DEVICE_HANDLER( ym3526_read_port_r );
+WRITE8_DEVICE_HANDLER( ym3526_control_port_w );
+WRITE8_DEVICE_HANDLER( ym3526_write_port_w );
+
+DECLARE_LEGACY_SOUND_DEVICE(YM3526, ym3526);
+
+#endif /* __3526INTF_H__ */
diff --git a/trunk/src/emu/sound/3812intf.c b/trunk/src/emu/sound/3812intf.c
new file mode 100644
index 00000000000..25d97861131
--- /dev/null
+++ b/trunk/src/emu/sound/3812intf.c
@@ -0,0 +1,170 @@
+/******************************************************************************
+* FILE
+* Yamaha 3812 emulator interface - MAME VERSION
+*
+* CREATED BY
+* Ernesto Corvi
+*
+* UPDATE LOG
+* JB 28-04-2002 Fixed simultaneous usage of all three different chip types.
+* Used real sample rate when resample filter is active.
+* AAT 12-28-2001 Protected Y8950 from accessing unmapped port and keyboard handlers.
+* CHS 1999-01-09 Fixes new ym3812 emulation interface.
+* CHS 1998-10-23 Mame streaming sound chip update
+* EC 1998 Created Interface
+*
+* NOTES
+*
+******************************************************************************/
+#include "emu.h"
+#include "3812intf.h"
+#include "fm.h"
+#include "sound/fmopl.h"
+
+
+typedef struct _ym3812_state ym3812_state;
+struct _ym3812_state
+{
+ sound_stream * stream;
+ emu_timer * timer[2];
+ void * chip;
+ const ym3812_interface *intf;
+ device_t *device;
+};
+
+
+INLINE ym3812_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == YM3812);
+ return (ym3812_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+
+static void IRQHandler(void *param,int irq)
+{
+ ym3812_state *info = (ym3812_state *)param;
+ if (info->intf->handler) (info->intf->handler)(info->device, irq ? ASSERT_LINE : CLEAR_LINE);
+}
+static TIMER_CALLBACK( timer_callback_0 )
+{
+ ym3812_state *info = (ym3812_state *)ptr;
+ ym3812_timer_over(info->chip,0);
+}
+
+static TIMER_CALLBACK( timer_callback_1 )
+{
+ ym3812_state *info = (ym3812_state *)ptr;
+ ym3812_timer_over(info->chip,1);
+}
+
+static void TimerHandler(void *param,int c,attotime period)
+{
+ ym3812_state *info = (ym3812_state *)param;
+ if( period == attotime::zero )
+ { /* Reset FM Timer */
+ info->timer[c]->enable(false);
+ }
+ else
+ { /* Start FM Timer */
+ info->timer[c]->adjust(period);
+ }
+}
+
+
+static STREAM_UPDATE( ym3812_stream_update )
+{
+ ym3812_state *info = (ym3812_state *)param;
+ ym3812_update_one(info->chip, outputs[0], samples);
+}
+
+static void _stream_update(void * param, int interval)
+{
+ ym3812_state *info = (ym3812_state *)param;
+ info->stream->update();
+}
+
+
+static DEVICE_START( ym3812 )
+{
+ static const ym3812_interface dummy = { 0 };
+ ym3812_state *info = get_safe_token(device);
+ int rate = device->clock()/72;
+
+ info->intf = device->static_config() ? (const ym3812_interface *)device->static_config() : &dummy;
+ info->device = device;
+
+ /* stream system initialize */
+ info->chip = ym3812_init(device,device->clock(),rate);
+ assert_always(info->chip != NULL, "Error creating YM3812 chip");
+
+ info->stream = device->machine().sound().stream_alloc(*device,0,1,rate,info,ym3812_stream_update);
+
+ /* YM3812 setup */
+ ym3812_set_timer_handler (info->chip, TimerHandler, info);
+ ym3812_set_irq_handler (info->chip, IRQHandler, info);
+ ym3812_set_update_handler(info->chip, _stream_update, info);
+
+ info->timer[0] = device->machine().scheduler().timer_alloc(FUNC(timer_callback_0), info);
+ info->timer[1] = device->machine().scheduler().timer_alloc(FUNC(timer_callback_1), info);
+}
+
+static DEVICE_STOP( ym3812 )
+{
+ ym3812_state *info = get_safe_token(device);
+ ym3812_shutdown(info->chip);
+}
+
+static DEVICE_RESET( ym3812 )
+{
+ ym3812_state *info = get_safe_token(device);
+ ym3812_reset_chip(info->chip);
+}
+
+
+READ8_DEVICE_HANDLER( ym3812_r )
+{
+ ym3812_state *info = get_safe_token(device);
+ return ym3812_read(info->chip, offset & 1);
+}
+
+WRITE8_DEVICE_HANDLER( ym3812_w )
+{
+ ym3812_state *info = get_safe_token(device);
+ ym3812_write(info->chip, offset & 1, data);
+}
+
+READ8_DEVICE_HANDLER( ym3812_status_port_r ) { return ym3812_r(device, 0); }
+READ8_DEVICE_HANDLER( ym3812_read_port_r ) { return ym3812_r(device, 1); }
+WRITE8_DEVICE_HANDLER( ym3812_control_port_w ) { ym3812_w(device, 0, data); }
+WRITE8_DEVICE_HANDLER( ym3812_write_port_w ) { ym3812_w(device, 1, data); }
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+DEVICE_GET_INFO( ym3812 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(ym3812_state); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( ym3812 ); break;
+ case DEVINFO_FCT_STOP: info->stop = DEVICE_STOP_NAME( ym3812 ); break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME( ym3812 ); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "YM3812"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Yamaha FM"); 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;
+ }
+}
+
+
+DEFINE_LEGACY_SOUND_DEVICE(YM3812, ym3812);
diff --git a/trunk/src/emu/sound/3812intf.h b/trunk/src/emu/sound/3812intf.h
new file mode 100644
index 00000000000..0ef383e3416
--- /dev/null
+++ b/trunk/src/emu/sound/3812intf.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#ifndef __3812INTF_H__
+#define __3812INTF_H__
+
+#include "devlegcy.h"
+
+typedef struct _ym3812_interface ym3812_interface;
+struct _ym3812_interface
+{
+ void (*handler)(device_t *device, int linestate);
+};
+
+READ8_DEVICE_HANDLER( ym3812_r );
+WRITE8_DEVICE_HANDLER( ym3812_w );
+
+READ8_DEVICE_HANDLER( ym3812_status_port_r );
+READ8_DEVICE_HANDLER( ym3812_read_port_r );
+WRITE8_DEVICE_HANDLER( ym3812_control_port_w );
+WRITE8_DEVICE_HANDLER( ym3812_write_port_w );
+
+DECLARE_LEGACY_SOUND_DEVICE(YM3812, ym3812);
+
+#endif /* __3812INTF_H__ */
diff --git a/trunk/src/emu/sound/8950intf.c b/trunk/src/emu/sound/8950intf.c
new file mode 100644
index 00000000000..aa75ef39a69
--- /dev/null
+++ b/trunk/src/emu/sound/8950intf.c
@@ -0,0 +1,203 @@
+/******************************************************************************
+* FILE
+* Yamaha 3812 emulator interface - MAME VERSION
+*
+* CREATED BY
+* Ernesto Corvi
+*
+* UPDATE LOG
+* JB 28-04-2002 Fixed simultaneous usage of all three different chip types.
+* Used real sample rate when resample filter is active.
+* AAT 12-28-2001 Protected Y8950 from accessing unmapped port and keyboard handlers.
+* CHS 1999-01-09 Fixes new ym3812 emulation interface.
+* CHS 1998-10-23 Mame streaming sound chip update
+* EC 1998 Created Interface
+*
+* NOTES
+*
+******************************************************************************/
+#include "emu.h"
+#include "8950intf.h"
+#include "fm.h"
+#include "sound/fmopl.h"
+
+
+typedef struct _y8950_state y8950_state;
+struct _y8950_state
+{
+ sound_stream * stream;
+ emu_timer * timer[2];
+ void * chip;
+ const y8950_interface *intf;
+ device_t *device;
+};
+
+
+INLINE y8950_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == Y8950);
+ return (y8950_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+static void IRQHandler(void *param,int irq)
+{
+ y8950_state *info = (y8950_state *)param;
+ if (info->intf->handler) (info->intf->handler)(info->device, irq ? ASSERT_LINE : CLEAR_LINE);
+}
+static TIMER_CALLBACK( timer_callback_0 )
+{
+ y8950_state *info = (y8950_state *)ptr;
+ y8950_timer_over(info->chip,0);
+}
+static TIMER_CALLBACK( timer_callback_1 )
+{
+ y8950_state *info = (y8950_state *)ptr;
+ y8950_timer_over(info->chip,1);
+}
+static void TimerHandler(void *param,int c,attotime period)
+{
+ y8950_state *info = (y8950_state *)param;
+ if( period == attotime::zero )
+ { /* Reset FM Timer */
+ info->timer[c]->enable(false);
+ }
+ else
+ { /* Start FM Timer */
+ info->timer[c]->adjust(period);
+ }
+}
+
+
+static unsigned char Y8950PortHandler_r(void *param)
+{
+ y8950_state *info = (y8950_state *)param;
+ if (info->intf->portread)
+ return info->intf->portread(info->device,0);
+ return 0;
+}
+
+static void Y8950PortHandler_w(void *param,unsigned char data)
+{
+ y8950_state *info = (y8950_state *)param;
+ if (info->intf->portwrite)
+ info->intf->portwrite(info->device,0,data);
+}
+
+static unsigned char Y8950KeyboardHandler_r(void *param)
+{
+ y8950_state *info = (y8950_state *)param;
+ if (info->intf->keyboardread)
+ return info->intf->keyboardread(info->device,0);
+ return 0;
+}
+
+static void Y8950KeyboardHandler_w(void *param,unsigned char data)
+{
+ y8950_state *info = (y8950_state *)param;
+ if (info->intf->keyboardwrite)
+ info->intf->keyboardwrite(info->device,0,data);
+}
+
+static STREAM_UPDATE( y8950_stream_update )
+{
+ y8950_state *info = (y8950_state *)param;
+ y8950_update_one(info->chip, outputs[0], samples);
+}
+
+static void _stream_update(void *param, int interval)
+{
+ y8950_state *info = (y8950_state *)param;
+ info->stream->update();
+}
+
+
+static DEVICE_START( y8950 )
+{
+ static const y8950_interface dummy = { 0 };
+ y8950_state *info = get_safe_token(device);
+ int rate = device->clock()/72;
+
+ info->intf = device->static_config() ? (const y8950_interface *)device->static_config() : &dummy;
+ info->device = device;
+
+ /* stream system initialize */
+ info->chip = y8950_init(device,device->clock(),rate);
+ assert_always(info->chip != NULL, "Error creating Y8950 chip");
+
+ /* ADPCM ROM data */
+ y8950_set_delta_t_memory(info->chip, *device->region(), device->region()->bytes());
+
+ info->stream = device->machine().sound().stream_alloc(*device,0,1,rate,info,y8950_stream_update);
+ /* port and keyboard handler */
+ y8950_set_port_handler(info->chip, Y8950PortHandler_w, Y8950PortHandler_r, info);
+ y8950_set_keyboard_handler(info->chip, Y8950KeyboardHandler_w, Y8950KeyboardHandler_r, info);
+
+ /* Y8950 setup */
+ y8950_set_timer_handler (info->chip, TimerHandler, info);
+ y8950_set_irq_handler (info->chip, IRQHandler, info);
+ y8950_set_update_handler(info->chip, _stream_update, info);
+
+ info->timer[0] = device->machine().scheduler().timer_alloc(FUNC(timer_callback_0), info);
+ info->timer[1] = device->machine().scheduler().timer_alloc(FUNC(timer_callback_1), info);
+}
+
+static DEVICE_STOP( y8950 )
+{
+ y8950_state *info = get_safe_token(device);
+ y8950_shutdown(info->chip);
+}
+
+static DEVICE_RESET( y8950 )
+{
+ y8950_state *info = get_safe_token(device);
+ y8950_reset_chip(info->chip);
+}
+
+
+READ8_DEVICE_HANDLER( y8950_r )
+{
+ y8950_state *info = get_safe_token(device);
+ return y8950_read(info->chip, offset & 1);
+}
+
+WRITE8_DEVICE_HANDLER( y8950_w )
+{
+ y8950_state *info = get_safe_token(device);
+ y8950_write(info->chip, offset & 1, data);
+}
+
+READ8_DEVICE_HANDLER( y8950_status_port_r ) { return y8950_r(device, 0); }
+READ8_DEVICE_HANDLER( y8950_read_port_r ) { return y8950_r(device, 1); }
+WRITE8_DEVICE_HANDLER( y8950_control_port_w ) { y8950_w(device, 0, data); }
+WRITE8_DEVICE_HANDLER( y8950_write_port_w ) { y8950_w(device, 1, data); }
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+DEVICE_GET_INFO( y8950 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(y8950_state); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( y8950 ); break;
+ case DEVINFO_FCT_STOP: info->stop = DEVICE_STOP_NAME( y8950 ); break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME( y8950 ); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Y8950"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Yamaha FM"); 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;
+ }
+}
+
+
+DEFINE_LEGACY_SOUND_DEVICE(Y8950, y8950);
diff --git a/trunk/src/emu/sound/8950intf.h b/trunk/src/emu/sound/8950intf.h
new file mode 100644
index 00000000000..eab9d8208d7
--- /dev/null
+++ b/trunk/src/emu/sound/8950intf.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#ifndef __8950INTF_H__
+#define __8950INTF_H__
+
+#include "devlegcy.h"
+
+typedef struct _y8950_interface y8950_interface;
+struct _y8950_interface
+{
+ void (*handler)(device_t *device, int linestate);
+
+ read8_device_func keyboardread;
+ write8_device_func keyboardwrite;
+ read8_device_func portread;
+ write8_device_func portwrite;
+};
+
+READ8_DEVICE_HANDLER( y8950_r );
+WRITE8_DEVICE_HANDLER( y8950_w );
+
+READ8_DEVICE_HANDLER( y8950_status_port_r );
+READ8_DEVICE_HANDLER( y8950_read_port_r );
+WRITE8_DEVICE_HANDLER( y8950_control_port_w );
+WRITE8_DEVICE_HANDLER( y8950_write_port_w );
+
+DECLARE_LEGACY_SOUND_DEVICE(Y8950, y8950);
+
+#endif /* __8950INTF_H__ */
diff --git a/trunk/src/emu/sound/aica.c b/trunk/src/emu/sound/aica.c
new file mode 100644
index 00000000000..2694452f00f
--- /dev/null
+++ b/trunk/src/emu/sound/aica.c
@@ -0,0 +1,1367 @@
+/*
+ Sega/Yamaha AICA emulation
+ By ElSemi, kingshriek, Deunan Knute, and R. Belmont
+
+ This is effectively a 64-voice SCSP, with the following differences:
+ - No FM mode
+ - A third sample format (ADPCM) has been added
+ - Some minor other tweeks (no EGHOLD, slighly more capable DSP)
+*/
+
+#include "emu.h"
+#include "aica.h"
+#include "aicadsp.h"
+
+#define ICLIP16(x) (x<-32768)?-32768:((x>32767)?32767:x)
+
+#define SHIFT 12
+#define FIX(v) ((UINT32) ((float) (1<<SHIFT)*(v)))
+
+#define EG_SHIFT 16
+
+// include the LFO handling code
+#include "aicalfo.c"
+
+/*
+ AICA features 64 programmable slots
+ that can generate PCM and ADPCM (from ROM/RAM) sound
+*/
+
+//SLOT PARAMETERS
+#define KEYONEX(slot) ((slot->udata.data[0x0]>>0x0)&0x8000)
+#define KEYONB(slot) ((slot->udata.data[0x0]>>0x0)&0x4000)
+#define SSCTL(slot) ((slot->udata.data[0x0]>>0xA)&0x0001)
+#define LPCTL(slot) ((slot->udata.data[0x0]>>0x9)&0x0001)
+#define PCMS(slot) ((slot->udata.data[0x0]>>0x7)&0x0003)
+
+#define SA(slot) (((slot->udata.data[0x0]&0x7F)<<16)|(slot->udata.data[0x4/2]))
+
+#define LSA(slot) (slot->udata.data[0x8/2])
+
+#define LEA(slot) (slot->udata.data[0xc/2])
+
+#define D2R(slot) ((slot->udata.data[0x10/2]>>0xB)&0x001F)
+#define D1R(slot) ((slot->udata.data[0x10/2]>>0x6)&0x001F)
+#define AR(slot) ((slot->udata.data[0x10/2]>>0x0)&0x001F)
+
+#define LPSLNK(slot) ((slot->udata.data[0x14/2]>>0x0)&0x4000)
+#define KRS(slot) ((slot->udata.data[0x14/2]>>0xA)&0x000F)
+#define DL(slot) ((slot->udata.data[0x14/2]>>0x5)&0x001F)
+#define RR(slot) ((slot->udata.data[0x14/2]>>0x0)&0x001F)
+
+#define TL(slot) ((slot->udata.data[0x28/2]>>0x8)&0x00FF)
+
+#define OCT(slot) ((slot->udata.data[0x18/2]>>0xB)&0x000F)
+#define FNS(slot) ((slot->udata.data[0x18/2]>>0x0)&0x03FF)
+
+#define LFORE(slot) ((slot->udata.data[0x1c/2]>>0x0)&0x8000)
+#define LFOF(slot) ((slot->udata.data[0x1c/2]>>0xA)&0x001F)
+#define PLFOWS(slot) ((slot->udata.data[0x1c/2]>>0x8)&0x0003)
+#define PLFOS(slot) ((slot->udata.data[0x1c/2]>>0x5)&0x0007)
+#define ALFOWS(slot) ((slot->udata.data[0x1c/2]>>0x3)&0x0003)
+#define ALFOS(slot) ((slot->udata.data[0x1c/2]>>0x0)&0x0007)
+
+#define ISEL(slot) ((slot->udata.data[0x20/2]>>0x0)&0x000F)
+#define IMXL(slot) ((slot->udata.data[0x20/2]>>0x4)&0x000F)
+
+#define DISDL(slot) ((slot->udata.data[0x24/2]>>0x8)&0x000F)
+#define DIPAN(slot) ((slot->udata.data[0x24/2]>>0x0)&0x001F)
+
+#define EFSDL(slot) ((AICA->EFSPAN[slot*4]>>8)&0x000f)
+#define EFPAN(slot) ((AICA->EFSPAN[slot*4]>>0)&0x001f)
+
+//Envelope times in ms
+static const double ARTimes[64]={100000/*infinity*/,100000/*infinity*/,8100.0,6900.0,6000.0,4800.0,4000.0,3400.0,3000.0,2400.0,2000.0,1700.0,1500.0,
+ 1200.0,1000.0,860.0,760.0,600.0,500.0,430.0,380.0,300.0,250.0,220.0,190.0,150.0,130.0,110.0,95.0,
+ 76.0,63.0,55.0,47.0,38.0,31.0,27.0,24.0,19.0,15.0,13.0,12.0,9.4,7.9,6.8,6.0,4.7,3.8,3.4,3.0,2.4,
+ 2.0,1.8,1.6,1.3,1.1,0.93,0.85,0.65,0.53,0.44,0.40,0.35,0.0,0.0};
+static const double DRTimes[64]={100000/*infinity*/,100000/*infinity*/,118200.0,101300.0,88600.0,70900.0,59100.0,50700.0,44300.0,35500.0,29600.0,25300.0,22200.0,17700.0,
+ 14800.0,12700.0,11100.0,8900.0,7400.0,6300.0,5500.0,4400.0,3700.0,3200.0,2800.0,2200.0,1800.0,1600.0,1400.0,1100.0,
+ 920.0,790.0,690.0,550.0,460.0,390.0,340.0,270.0,230.0,200.0,170.0,140.0,110.0,98.0,85.0,68.0,57.0,49.0,43.0,34.0,
+ 28.0,25.0,22.0,18.0,14.0,12.0,11.0,8.5,7.1,6.1,5.4,4.3,3.6,3.1};
+static INT32 EG_TABLE[0x400];
+
+typedef enum {ATTACK,DECAY1,DECAY2,RELEASE} _STATE;
+struct _EG
+{
+ int volume; //
+ _STATE state;
+ int step;
+ //step vals
+ int AR; //Attack
+ int D1R; //Decay1
+ int D2R; //Decay2
+ int RR; //Release
+
+ int DL; //Decay level
+ UINT8 LPLINK;
+};
+
+struct _SLOT
+{
+ union
+ {
+ UINT16 data[0x40]; //only 0x1a bytes used
+ UINT8 datab[0x80];
+ } udata;
+ UINT8 active; //this slot is currently playing
+ UINT8 *base; //samples base address
+ UINT32 prv_addr; // previous play address (for ADPCM)
+ UINT32 cur_addr; //current play address (24.8)
+ UINT32 nxt_addr; //next play address
+ UINT32 step; //pitch step (24.8)
+ UINT8 Backwards; //the wave is playing backwards
+ struct _EG EG; //Envelope
+ struct _LFO PLFO; //Phase LFO
+ struct _LFO ALFO; //Amplitude LFO
+ int slot;
+ int cur_sample; //current ADPCM sample
+ int cur_quant; //current ADPCM step
+ int curstep;
+ int cur_lpquant, cur_lpsample, cur_lpstep;
+ UINT8 *adbase, *adlpbase;
+ UINT8 lpend;
+};
+
+
+#define MEM4B(aica) ((aica->udata.data[0]>>0x0)&0x0200)
+#define DAC18B(aica) ((aica->udata.data[0]>>0x0)&0x0100)
+#define MVOL(aica) ((aica->udata.data[0]>>0x0)&0x000F)
+#define RBL(aica) ((aica->udata.data[2]>>0xD)&0x0003)
+#define RBP(aica) ((aica->udata.data[2]>>0x0)&0x0fff)
+#define MOFULL(aica) ((aica->udata.data[4]>>0x0)&0x1000)
+#define MOEMPTY(aica) ((aica->udata.data[4]>>0x0)&0x0800)
+#define MIOVF(aica) ((aica->udata.data[4]>>0x0)&0x0400)
+#define MIFULL(aica) ((aica->udata.data[4]>>0x0)&0x0200)
+#define MIEMPTY(aica) ((aica->udata.data[4]>>0x0)&0x0100)
+
+#define AFSEL(aica) ((aica->udata.data[0xc/2]>>0x0)&0x4000)
+#define MSLC(aica) ((aica->udata.data[0xc/2]>>0x8)&0x3F)
+
+#define SCILV0(aica) ((aica->udata.data[0xa8/2]>>0x0)&0xff)
+#define SCILV1(aica) ((aica->udata.data[0xac/2]>>0x0)&0xff)
+#define SCILV2(aica) ((aica->udata.data[0xb0/2]>>0x0)&0xff)
+
+#define MCIEB(aica) ((aica->udata.data[0xb4/2]>>0x0)&0xff)
+#define MCIPD(aica) ((aica->udata.data[0xb8/2]>>0x0)&0xff)
+#define MCIRE(aica) ((aica->udata.data[0xbc/2]>>0x0)&0xff)
+
+#define SCIEX0 0
+#define SCIEX1 1
+#define SCIEX2 2
+#define SCIMID 3
+#define SCIDMA 4
+#define SCIIRQ 5
+#define SCITMA 6
+#define SCITMB 7
+
+typedef struct _AICA aica_state;
+struct _AICA
+{
+ union
+ {
+ UINT16 data[0xc0/2];
+ UINT8 datab[0xc0];
+ } udata;
+ UINT16 IRQL, IRQR;
+ UINT16 EFSPAN[0x48];
+ struct _SLOT Slots[64];
+ signed short RINGBUF[64];
+ unsigned char BUFPTR;
+ unsigned char *AICARAM;
+ UINT32 AICARAM_LENGTH, RAM_MASK, RAM_MASK16;
+ char Master;
+ void (*IntARMCB)(device_t *device, int irq);
+ sound_stream * stream;
+
+ INT32 *buffertmpl, *buffertmpr;
+
+ UINT32 IrqTimA;
+ UINT32 IrqTimBC;
+ UINT32 IrqMidi;
+
+ UINT8 MidiOutW,MidiOutR;
+ UINT8 MidiStack[16];
+ UINT8 MidiW,MidiR;
+
+ int LPANTABLE[0x20000];
+ int RPANTABLE[0x20000];
+
+ int TimPris[3];
+ int TimCnt[3];
+
+ // timers
+ emu_timer *timerA, *timerB, *timerC;
+
+ // DMA stuff
+ UINT32 aica_dmea;
+ UINT16 aica_drga;
+ UINT16 aica_dtlg;
+
+ int ARTABLE[64], DRTABLE[64];
+
+ struct _AICADSP DSP;
+ device_t *device;
+};
+
+static const float SDLT[16]={-1000000.0,-42.0,-39.0,-36.0,-33.0,-30.0,-27.0,-24.0,-21.0,-18.0,-15.0,-12.0,-9.0,-6.0,-3.0,0.0};
+
+static stream_sample_t *bufferl;
+static stream_sample_t *bufferr;
+
+static int length;
+
+static signed short *RBUFDST; //this points to where the sample will be stored in the RingBuf
+
+INLINE aica_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == AICA);
+ return (aica_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+static unsigned char DecodeSCI(aica_state *AICA, unsigned char irq)
+{
+ unsigned char SCI=0;
+ unsigned char v;
+ v=(SCILV0((AICA))&(1<<irq))?1:0;
+ SCI|=v;
+ v=(SCILV1((AICA))&(1<<irq))?1:0;
+ SCI|=v<<1;
+ v=(SCILV2((AICA))&(1<<irq))?1:0;
+ SCI|=v<<2;
+ return SCI;
+}
+
+static void ResetInterrupts(aica_state *AICA)
+{
+#if 0
+ UINT32 reset = AICA->udata.data[0xa4/2];
+
+ if (reset & 0x40)
+ AICA->IntARMCB(AICA->device, -AICA->IrqTimA);
+ if (reset & 0x180)
+ AICA->IntARMCB(AICA->device, -AICA->IrqTimBC);
+#endif
+}
+
+static void CheckPendingIRQ(aica_state *AICA)
+{
+ UINT32 pend=AICA->udata.data[0xa0/2];
+ UINT32 en=AICA->udata.data[0x9c/2];
+
+ if(AICA->MidiW!=AICA->MidiR)
+ {
+ AICA->IRQL = AICA->IrqMidi;
+ AICA->IntARMCB(AICA->device, 1);
+ return;
+ }
+ if(!pend)
+ return;
+ if(pend&0x40)
+ if(en&0x40)
+ {
+ AICA->IRQL = AICA->IrqTimA;
+ AICA->IntARMCB(AICA->device, 1);
+ return;
+ }
+ if(pend&0x80)
+ if(en&0x80)
+ {
+ AICA->IRQL = AICA->IrqTimBC;
+ AICA->IntARMCB(AICA->device, 1);
+ return;
+ }
+ if(pend&0x100)
+ if(en&0x100)
+ {
+ AICA->IRQL = AICA->IrqTimBC;
+ AICA->IntARMCB(AICA->device, 1);
+ return;
+ }
+}
+
+static TIMER_CALLBACK( timerA_cb )
+{
+ aica_state *AICA = (aica_state *)ptr;
+
+ AICA->TimCnt[0] = 0xFFFF;
+ AICA->udata.data[0xa0/2]|=0x40;
+ AICA->udata.data[0x90/2]&=0xff00;
+ AICA->udata.data[0x90/2]|=AICA->TimCnt[0]>>8;
+
+ CheckPendingIRQ(AICA);
+}
+
+static TIMER_CALLBACK( timerB_cb )
+{
+ aica_state *AICA = (aica_state *)ptr;
+
+ AICA->TimCnt[1] = 0xFFFF;
+ AICA->udata.data[0xa0/2]|=0x80;
+ AICA->udata.data[0x94/2]&=0xff00;
+ AICA->udata.data[0x94/2]|=AICA->TimCnt[1]>>8;
+
+ CheckPendingIRQ(AICA);
+}
+
+static TIMER_CALLBACK( timerC_cb )
+{
+ aica_state *AICA = (aica_state *)ptr;
+
+ AICA->TimCnt[2] = 0xFFFF;
+ AICA->udata.data[0xa0/2]|=0x100;
+ AICA->udata.data[0x98/2]&=0xff00;
+ AICA->udata.data[0x98/2]|=AICA->TimCnt[2]>>8;
+
+ CheckPendingIRQ(AICA);
+}
+
+static int Get_AR(aica_state *AICA,int base,int R)
+{
+ int Rate=base+(R<<1);
+ if(Rate>63) Rate=63;
+ if(Rate<0) Rate=0;
+ return AICA->ARTABLE[Rate];
+}
+
+static int Get_DR(aica_state *AICA,int base,int R)
+{
+ int Rate=base+(R<<1);
+ if(Rate>63) Rate=63;
+ if(Rate<0) Rate=0;
+ return AICA->DRTABLE[Rate];
+}
+
+static int Get_RR(aica_state *AICA,int base,int R)
+{
+ int Rate=base+(R<<1);
+ if(Rate>63) Rate=63;
+ if(Rate<0) Rate=0;
+ return AICA->DRTABLE[Rate];
+}
+
+static void Compute_EG(aica_state *AICA,struct _SLOT *slot)
+{
+ int octave=(OCT(slot)^8)-8;
+ int rate;
+ if(KRS(slot)!=0xf)
+ rate=octave+2*KRS(slot)+((FNS(slot)>>9)&1);
+ else
+ rate=0; //rate=((FNS(slot)>>9)&1);
+
+ slot->EG.volume=0x17f<<EG_SHIFT;
+ slot->EG.AR=Get_AR(AICA,rate,AR(slot));
+ slot->EG.D1R=Get_DR(AICA,rate,D1R(slot));
+ slot->EG.D2R=Get_DR(AICA,rate,D2R(slot));
+ slot->EG.RR=Get_RR(AICA,rate,RR(slot));
+ slot->EG.DL=0x1f-DL(slot);
+}
+
+static void AICA_StopSlot(struct _SLOT *slot,int keyoff);
+
+static int EG_Update(struct _SLOT *slot)
+{
+ switch(slot->EG.state)
+ {
+ case ATTACK:
+ slot->EG.volume+=slot->EG.AR;
+ if(slot->EG.volume>=(0x3ff<<EG_SHIFT))
+ {
+ if (!LPSLNK(slot) && slot->EG.D1R)
+ {
+ slot->EG.state=DECAY1;
+ if(slot->EG.D1R>=(1024<<EG_SHIFT) && slot->EG.D2R) //Skip DECAY1, go directly to DECAY2
+ slot->EG.state=DECAY2;
+ }
+ slot->EG.volume=0x3ff<<EG_SHIFT;
+ }
+ break;
+ case DECAY1:
+ slot->EG.volume-=slot->EG.D1R;
+ if(slot->EG.volume<=0)
+ slot->EG.volume=0;
+ if(slot->EG.volume>>(EG_SHIFT+5)<=slot->EG.DL)
+ slot->EG.state=DECAY2;
+ break;
+ case DECAY2:
+ if(D2R(slot)==0)
+ return (slot->EG.volume>>EG_SHIFT)<<(SHIFT-10);
+ slot->EG.volume-=slot->EG.D2R;
+ if(slot->EG.volume<=0)
+ slot->EG.volume=0;
+
+ break;
+ case RELEASE:
+ slot->EG.volume-=slot->EG.RR;
+ if(slot->EG.volume<=0)
+ {
+ slot->EG.volume=0;
+ AICA_StopSlot(slot,0);
+// slot->EG.volume=0x17f<<EG_SHIFT;
+// slot->EG.state=ATTACK;
+ }
+ break;
+ default:
+ return 1<<SHIFT;
+ }
+ return (slot->EG.volume>>EG_SHIFT)<<(SHIFT-10);
+}
+
+static UINT32 AICA_Step(struct _SLOT *slot)
+{
+ int octave=(OCT(slot)^8)-8+SHIFT-10;
+ UINT32 Fn=FNS(slot) + (0x400);
+ if (octave >= 0)
+ Fn<<=octave;
+ else
+ Fn>>=-octave;
+ return Fn;
+}
+
+
+static void Compute_LFO(struct _SLOT *slot)
+{
+ if(PLFOS(slot)!=0)
+ AICALFO_ComputeStep(&(slot->PLFO),LFOF(slot),PLFOWS(slot),PLFOS(slot),0);
+ if(ALFOS(slot)!=0)
+ AICALFO_ComputeStep(&(slot->ALFO),LFOF(slot),ALFOWS(slot),ALFOS(slot),1);
+}
+
+#define ADPCMSHIFT 8
+#define ADFIX(f) (int) ((float) f*(float) (1<<ADPCMSHIFT))
+
+static const int TableQuant[8]={ADFIX(0.8984375),ADFIX(0.8984375),ADFIX(0.8984375),ADFIX(0.8984375),ADFIX(1.19921875),ADFIX(1.59765625),ADFIX(2.0),ADFIX(2.3984375)};
+static const int quant_mul[16]= { 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15};
+
+static void InitADPCM(int *PrevSignal, int *PrevQuant)
+{
+ *PrevSignal=0;
+ *PrevQuant=0x7f;
+}
+
+INLINE signed short DecodeADPCM(int *PrevSignal, unsigned char Delta, int *PrevQuant)
+{
+ int x = *PrevQuant * quant_mul [Delta & 15];
+ x = *PrevSignal + ((int)(x + ((UINT32)x >> 29)) >> 3);
+ *PrevSignal=ICLIP16(x);
+ *PrevQuant=(*PrevQuant*TableQuant[Delta&7])>>ADPCMSHIFT;
+ *PrevQuant=(*PrevQuant<0x7f)?0x7f:((*PrevQuant>0x6000)?0x6000:*PrevQuant);
+ return *PrevSignal;
+}
+
+static void AICA_StartSlot(aica_state *AICA, struct _SLOT *slot)
+{
+ UINT64 start_offset;
+
+ slot->active=1;
+ slot->Backwards=0;
+ slot->cur_addr=0; slot->nxt_addr=1<<SHIFT; slot->prv_addr=-1;
+ start_offset = SA(slot); // AICA can play 16-bit samples from any boundry
+ slot->base=&AICA->AICARAM[start_offset];
+ slot->step=AICA_Step(slot);
+ Compute_EG(AICA,slot);
+ slot->EG.state=ATTACK;
+ slot->EG.volume=0x17f<<EG_SHIFT;
+ Compute_LFO(slot);
+
+ if (PCMS(slot) >= 2)
+ {
+ slot->curstep = 0;
+ slot->adbase = (unsigned char *) (AICA->AICARAM+((SA(slot))&0x7fffff));
+ InitADPCM(&(slot->cur_sample), &(slot->cur_quant));
+ InitADPCM(&(slot->cur_lpsample), &(slot->cur_lpquant));
+
+ // on real hardware this creates undefined behavior.
+ if (LSA(slot) > LEA(slot))
+ {
+ slot->udata.data[0xc/2] = 0xffff;
+ }
+ }
+}
+
+static void AICA_StopSlot(struct _SLOT *slot,int keyoff)
+{
+ if(keyoff /*&& slot->EG.state!=RELEASE*/)
+ {
+ slot->EG.state=RELEASE;
+ }
+ else
+ {
+ slot->active=0;
+ slot->lpend = 1;
+ }
+ slot->udata.data[0]&=~0x4000;
+}
+
+#define log_base_2(n) (log((float) n)/log((float) 2))
+
+static void AICA_Init(device_t *device, aica_state *AICA, const aica_interface *intf)
+{
+ int i;
+
+ AICA->device = device;
+ AICA->IrqTimA = AICA->IrqTimBC = AICA->IrqMidi = 0;
+ AICA->MidiR=AICA->MidiW=0;
+ AICA->MidiOutR=AICA->MidiOutW=0;
+
+ // get AICA RAM
+ {
+ AICA->Master = intf->master;
+
+ AICA->AICARAM = *device->region();
+ if (AICA->AICARAM)
+ {
+ AICA->AICARAM += intf->roffset;
+ AICA->AICARAM_LENGTH = device->region()->bytes();
+ AICA->RAM_MASK = AICA->AICARAM_LENGTH-1;
+ AICA->RAM_MASK16 = AICA->RAM_MASK & 0x7ffffe;
+ AICA->DSP.AICARAM = (UINT16 *)AICA->AICARAM;
+ AICA->DSP.AICARAM_LENGTH = AICA->AICARAM_LENGTH/2;
+ }
+ }
+
+ AICA->timerA = device->machine().scheduler().timer_alloc(FUNC(timerA_cb), AICA);
+ AICA->timerB = device->machine().scheduler().timer_alloc(FUNC(timerB_cb), AICA);
+ AICA->timerC = device->machine().scheduler().timer_alloc(FUNC(timerC_cb), AICA);
+
+ for(i=0;i<0x400;++i)
+ {
+ float envDB=((float)(3*(i-0x3ff)))/32.0;
+ float scale=(float)(1<<SHIFT);
+ EG_TABLE[i]=(INT32)(pow(10.0,envDB/20.0)*scale);
+ }
+
+ for(i=0;i<0x20000;++i)
+ {
+ int iTL =(i>>0x0)&0xff;
+ int iPAN=(i>>0x8)&0x1f;
+ int iSDL=(i>>0xD)&0x0F;
+ float TL=1.0;
+ float SegaDB=0;
+ float fSDL=1.0;
+ float PAN=1.0;
+ float LPAN,RPAN;
+
+ if(iTL&0x01) SegaDB-=0.4f;
+ if(iTL&0x02) SegaDB-=0.8f;
+ if(iTL&0x04) SegaDB-=1.5f;
+ if(iTL&0x08) SegaDB-=3.0f;
+ if(iTL&0x10) SegaDB-=6.0f;
+ if(iTL&0x20) SegaDB-=12.0f;
+ if(iTL&0x40) SegaDB-=24.0f;
+ if(iTL&0x80) SegaDB-=48.0f;
+
+ TL=pow(10.0,SegaDB/20.0);
+
+ SegaDB=0;
+ if(iPAN&0x1) SegaDB-=3.0f;
+ if(iPAN&0x2) SegaDB-=6.0f;
+ if(iPAN&0x4) SegaDB-=12.0f;
+ if(iPAN&0x8) SegaDB-=24.0f;
+
+ if((iPAN&0xf)==0xf) PAN=0.0;
+ else PAN=pow(10.0,SegaDB/20.0);
+
+ if(iPAN<0x10)
+ {
+ LPAN=PAN;
+ RPAN=1.0;
+ }
+ else
+ {
+ RPAN=PAN;
+ LPAN=1.0;
+ }
+
+ if(iSDL)
+ fSDL=pow(10.0,(SDLT[iSDL])/20.0);
+ else
+ fSDL=0.0;
+
+ AICA->LPANTABLE[i]=FIX((4.0*LPAN*TL*fSDL));
+ AICA->RPANTABLE[i]=FIX((4.0*RPAN*TL*fSDL));
+ }
+
+ AICA->ARTABLE[0]=AICA->DRTABLE[0]=0; //Infinite time
+ AICA->ARTABLE[1]=AICA->DRTABLE[1]=0; //Infinite time
+ for(i=2;i<64;++i)
+ {
+ double t,step,scale;
+ t=ARTimes[i]; //In ms
+ if(t!=0.0)
+ {
+ step=(1023*1000.0)/((float) 44100.0f*t);
+ scale=(double) (1<<EG_SHIFT);
+ AICA->ARTABLE[i]=(int) (step*scale);
+ }
+ else
+ AICA->ARTABLE[i]=1024<<EG_SHIFT;
+
+ t=DRTimes[i]; //In ms
+ step=(1023*1000.0)/((float) 44100.0f*t);
+ scale=(double) (1<<EG_SHIFT);
+ AICA->DRTABLE[i]=(int) (step*scale);
+ }
+
+ // make sure all the slots are off
+ for(i=0;i<64;++i)
+ {
+ AICA->Slots[i].slot=i;
+ AICA->Slots[i].active=0;
+ AICA->Slots[i].base=NULL;
+ AICA->Slots[i].EG.state=RELEASE;
+ AICA->Slots[i].lpend=1;
+ }
+
+ AICALFO_Init(device->machine());
+ AICA->buffertmpl=auto_alloc_array_clear(device->machine(), signed int, 44100);
+ AICA->buffertmpr=auto_alloc_array_clear(device->machine(), signed int, 44100);
+
+ // no "pend"
+ AICA[0].udata.data[0xa0/2] = 0;
+ //AICA[1].udata.data[0x20/2] = 0;
+ AICA->TimCnt[0] = 0xffff;
+ AICA->TimCnt[1] = 0xffff;
+ AICA->TimCnt[2] = 0xffff;
+}
+
+static void AICA_UpdateSlotReg(aica_state *AICA,int s,int r)
+{
+ struct _SLOT *slot=AICA->Slots+s;
+ int sl;
+ switch(r&0x7f)
+ {
+ case 0:
+ case 1:
+ if(KEYONEX(slot))
+ {
+ for(sl=0;sl<64;++sl)
+ {
+ struct _SLOT *s2=AICA->Slots+sl;
+ {
+ if(KEYONB(s2) && s2->EG.state==RELEASE/*&& !s2->active*/)
+ {
+ s2->lpend = 0;
+ AICA_StartSlot(AICA, s2);
+ #if 0
+ printf("StartSlot[%02X]: SSCTL %01X SA %06X LSA %04X LEA %04X PCMS %01X LPCTL %01X\n",sl,SSCTL(s2),SA(s2),LSA(s2),LEA(s2),PCMS(s2),LPCTL(s2));
+ printf(" AR %02X D1R %02X D2R %02X RR %02X DL %02X KRS %01X LPSLNK %01X\n",AR(s2),D1R(s2),D2R(s2),RR(s2),DL(s2),KRS(s2),LPSLNK(s2)>>14);
+ printf(" TL %02X OCT %01X FNS %03X\n",TL(s2),OCT(s2),FNS(s2));
+ printf(" LFORE %01X LFOF %02X ALFOWS %01X ALFOS %01X PLFOWS %01X PLFOS %01X\n",LFORE(s2),LFOF(s2),ALFOWS(s2),ALFOS(s2),PLFOWS(s2),PLFOS(s2));
+ printf(" IMXL %01X ISEL %01X DISDL %01X DIPAN %02X\n",IMXL(s2),ISEL(s2),DISDL(s2),DIPAN(s2));
+ printf("\n");
+ fflush(stdout);
+ #endif
+ }
+ if(!KEYONB(s2) /*&& s2->active*/)
+ {
+ AICA_StopSlot(s2,1);
+ }
+ }
+ }
+ slot->udata.data[0]&=~0x8000;
+ }
+ break;
+ case 0x18:
+ case 0x19:
+ slot->step=AICA_Step(slot);
+ break;
+ case 0x14:
+ case 0x15:
+ slot->EG.RR=Get_RR(AICA,0,RR(slot));
+ slot->EG.DL=0x1f-DL(slot);
+ break;
+ case 0x1c:
+ case 0x1d:
+ Compute_LFO(slot);
+ break;
+ case 0x24:
+// printf("[%02d]: %x to DISDL/DIPAN (PC=%x)\n", s, slot->udata.data[0x24/2], arm7_get_register(15));
+ break;
+ }
+}
+
+static void AICA_UpdateReg(aica_state *AICA, int reg)
+{
+ switch(reg&0xff)
+ {
+ case 0x4:
+ case 0x5:
+ {
+ unsigned int v=RBL(AICA);
+ AICA->DSP.RBP=RBP(AICA);
+ if(v==0)
+ AICA->DSP.RBL=8*1024;
+ else if(v==1)
+ AICA->DSP.RBL=16*1024;
+ else if(v==2)
+ AICA->DSP.RBL=32*1024;
+ else if(v==3)
+ AICA->DSP.RBL=64*1024;
+ }
+ break;
+ case 0x8:
+ case 0x9:
+ aica_midi_in(AICA->device, 0, AICA->udata.data[0x8/2]&0xff, 0xffff);
+ break;
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ break;
+ case 0x90:
+ case 0x91:
+ if(AICA->Master)
+ {
+ UINT32 time;
+
+ AICA->TimPris[0]=1<<((AICA->udata.data[0x90/2]>>8)&0x7);
+ AICA->TimCnt[0]=(AICA->udata.data[0x90/2]&0xff)<<8;
+
+ if ((AICA->udata.data[0x90/2]&0xff) != 255)
+ {
+ time = (44100 / AICA->TimPris[0]) / (255-(AICA->udata.data[0x90/2]&0xff));
+ if (time)
+ {
+ AICA->timerA->adjust(attotime::from_hz(time));
+ }
+ }
+ }
+ break;
+ case 0x94:
+ case 0x95:
+ if(AICA->Master)
+ {
+ UINT32 time;
+
+ AICA->TimPris[1]=1<<((AICA->udata.data[0x94/2]>>8)&0x7);
+ AICA->TimCnt[1]=(AICA->udata.data[0x94/2]&0xff)<<8;
+
+ if ((AICA->udata.data[0x94/2]&0xff) != 255)
+ {
+ time = (44100 / AICA->TimPris[1]) / (255-(AICA->udata.data[0x94/2]&0xff));
+ if (time)
+ {
+ AICA->timerB->adjust(attotime::from_hz(time));
+ }
+ }
+ }
+ break;
+ case 0x98:
+ case 0x99:
+ if(AICA->Master)
+ {
+ UINT32 time;
+
+ AICA->TimPris[2]=1<<((AICA->udata.data[0x98/2]>>8)&0x7);
+ AICA->TimCnt[2]=(AICA->udata.data[0x98/2]&0xff)<<8;
+
+ if ((AICA->udata.data[0x98/2]&0xff) != 255)
+ {
+ time = (44100 / AICA->TimPris[2]) / (255-(AICA->udata.data[0x98/2]&0xff));
+ if (time)
+ {
+ AICA->timerC->adjust(attotime::from_hz(time));
+ }
+ }
+ }
+ break;
+ case 0xa4: //SCIRE
+ case 0xa5:
+
+ if(AICA->Master)
+ {
+ AICA->udata.data[0xa0/2] &= ~AICA->udata.data[0xa4/2];
+ ResetInterrupts(AICA);
+
+ // behavior from real hardware (SCSP, assumed to carry over): if you SCIRE a timer that's expired,
+ // it'll immediately pop up again
+ if (AICA->TimCnt[0] >= 0xff00)
+ {
+ AICA->udata.data[0xa0/2] |= 0x40;
+ }
+ if (AICA->TimCnt[1] >= 0xff00)
+ {
+ AICA->udata.data[0xa0/2] |= 0x80;
+ }
+ if (AICA->TimCnt[2] >= 0xff00)
+ {
+ AICA->udata.data[0xa0/2] |= 0x100;
+ }
+ }
+ break;
+ case 0xa8:
+ case 0xa9:
+ case 0xac:
+ case 0xad:
+ case 0xb0:
+ case 0xb1:
+ if(AICA->Master)
+ {
+ AICA->IrqTimA=DecodeSCI(AICA,SCITMA);
+ AICA->IrqTimBC=DecodeSCI(AICA,SCITMB);
+ AICA->IrqMidi=DecodeSCI(AICA,SCIMID);
+ }
+ break;
+
+ case 0xb4:
+ case 0xb5:
+ case 0xb6:
+ case 0xb7:
+ if (MCIEB(AICA) & 0x20)
+ {
+ logerror("AICA: Interrupt requested on SH-4!\n");
+ }
+ break;
+ }
+}
+
+static void AICA_UpdateSlotRegR(aica_state *AICA, int slot,int reg)
+{
+
+}
+
+static void AICA_UpdateRegR(aica_state *AICA, int reg)
+{
+ switch(reg&0xff)
+ {
+ case 8:
+ case 9:
+ {
+ unsigned short v=AICA->udata.data[0x8/2];
+ v&=0xff00;
+ v|=AICA->MidiStack[AICA->MidiR];
+ AICA->IntARMCB(AICA->device, 0); // cancel the IRQ
+ if(AICA->MidiR!=AICA->MidiW)
+ {
+ ++AICA->MidiR;
+ AICA->MidiR&=15;
+ }
+ AICA->udata.data[0x8/2]=v;
+ }
+ break;
+
+ case 0x10: // LP check
+ case 0x11:
+ {
+ int slotnum = MSLC(AICA);
+ struct _SLOT *slot=AICA->Slots + slotnum;
+ UINT16 LP = 0;
+ if (!(AFSEL(AICA)))
+ {
+ UINT16 SGC;
+ int EG;
+
+ LP = slot->lpend ? 0x8000 : 0x0000;
+ slot->lpend = 0;
+ SGC = (slot->EG.state << 13) & 0x6000;
+ EG = slot->active ? slot->EG.volume : 0;
+ EG >>= (EG_SHIFT - 13);
+ EG = 0x1FFF - EG;
+ if (EG < 0) EG = 0;
+
+ AICA->udata.data[0x10/2] = (EG & 0x1FF8) | SGC | LP;
+ }
+ else
+ {
+ LP = slot->lpend ? 0x8000 : 0x0000;
+ AICA->udata.data[0x10/2] = LP;
+ }
+ }
+ break;
+
+ case 0x14: // CA (slot address)
+ case 0x15:
+ {
+ int slotnum = MSLC(AICA);
+ struct _SLOT *slot=AICA->Slots+slotnum;
+ unsigned int CA = 0;
+
+ if (PCMS(slot) == 0) // 16-bit samples
+ {
+ CA = (slot->cur_addr>>(SHIFT-1))&AICA->RAM_MASK16;
+ }
+ else // 8-bit PCM and 4-bit ADPCM
+ {
+ CA = (slot->cur_addr>>SHIFT)&AICA->RAM_MASK;
+ }
+
+ AICA->udata.data[0x14/2] = CA;
+ }
+ break;
+ }
+}
+
+static void AICA_w16(aica_state *AICA,unsigned int addr,unsigned short val)
+{
+ addr&=0xffff;
+ if(addr<0x2000)
+ {
+ int slot=addr/0x80;
+ addr&=0x7f;
+// printf("%x to slot %d offset %x\n", val, slot, addr);
+ *((unsigned short *) (AICA->Slots[slot].udata.datab+(addr))) = val;
+ AICA_UpdateSlotReg(AICA,slot,addr&0x7f);
+ }
+ else if (addr < 0x2800)
+ {
+ if (addr <= 0x2044)
+ {
+// printf("%x to EFSxx slot %d (addr %x)\n", val, (addr-0x2000)/4, addr&0x7f);
+ AICA->EFSPAN[addr&0x7f] = val;
+ }
+ }
+ else if(addr<0x3000)
+ {
+ if (addr < 0x28be)
+ {
+// printf("%x to AICA global @ %x\n", val, addr & 0xff);
+ *((unsigned short *) (AICA->udata.datab+((addr&0xff)))) = val;
+ AICA_UpdateReg(AICA, addr&0xff);
+ }
+ else if (addr == 0x2d00)
+ {
+ AICA->IRQL = val;
+ }
+ else if (addr == 0x2d04)
+ {
+ AICA->IRQR = val;
+
+ if (val)
+ {
+ AICA->IntARMCB(AICA->device, 0);
+ }
+ }
+ }
+ else
+ {
+ //DSP
+ if(addr<0x3200) //COEF
+ *((unsigned short *) (AICA->DSP.COEF+(addr-0x3000)/2))=val;
+ else if(addr<0x3400)
+ *((unsigned short *) (AICA->DSP.MADRS+(addr-0x3200)/2))=val;
+ else if(addr<0x3c00)
+ {
+ *((unsigned short *) (AICA->DSP.MPRO+(addr-0x3400)/2))=val;
+
+ if (addr == 0x3bfe)
+ {
+ aica_dsp_start(&AICA->DSP);
+ }
+ }
+ }
+}
+
+static unsigned short AICA_r16(aica_state *AICA, unsigned int addr)
+{
+ unsigned short v=0;
+ addr&=0xffff;
+ if(addr<0x2000)
+ {
+ int slot=addr/0x80;
+ addr&=0x7f;
+ AICA_UpdateSlotRegR(AICA, slot,addr&0x7f);
+ v=*((unsigned short *) (AICA->Slots[slot].udata.datab+(addr)));
+ }
+ else if(addr<0x3000)
+ {
+ if (addr <= 0x2044)
+ {
+ v = AICA->EFSPAN[addr&0x7f];
+ }
+ else if (addr < 0x28be)
+ {
+ AICA_UpdateRegR(AICA, addr&0xff);
+ v= *((unsigned short *) (AICA->udata.datab+((addr&0xff))));
+ if((addr&0xfffe)==0x2810) AICA->udata.data[0x10/2] &= 0x7FFF; // reset LP on read
+ }
+ else if (addr == 0x2d00)
+ {
+ return AICA->IRQL;
+ }
+ else if (addr == 0x2d04)
+ {
+ return AICA->IRQR;
+ }
+ }
+// else if (addr<0x700)
+// v=AICA->RINGBUF[(addr-0x600)/2];
+ return v;
+}
+
+
+#define REVSIGN(v) ((~v)+1)
+
+#ifdef UNUSED_FUNCTION
+static void AICA_TimersAddTicks(aica_state *AICA, int ticks)
+{
+ if(AICA->TimCnt[0]<=0xff00)
+ {
+ AICA->TimCnt[0] += ticks << (8-((AICA->udata.data[0x18/2]>>8)&0x7));
+ if (AICA->TimCnt[0] > 0xFF00)
+ {
+ AICA->TimCnt[0] = 0xFFFF;
+ AICA->udata.data[0xa0/2]|=0x40;
+ }
+ AICA->udata.data[0x90/2]&=0xff00;
+ AICA->udata.data[0x90/2]|=AICA->TimCnt[0]>>8;
+ }
+
+ if(AICA->TimCnt[1]<=0xff00)
+ {
+ AICA->TimCnt[1] += ticks << (8-((AICA->udata.data[0x1a/2]>>8)&0x7));
+ if (AICA->TimCnt[1] > 0xFF00)
+ {
+ AICA->TimCnt[1] = 0xFFFF;
+ AICA->udata.data[0xa0/2]|=0x80;
+ }
+ AICA->udata.data[0x94/2]&=0xff00;
+ AICA->udata.data[0x94/2]|=AICA->TimCnt[1]>>8;
+ }
+
+ if(AICA->TimCnt[2]<=0xff00)
+ {
+ AICA->TimCnt[2] += ticks << (8-((AICA->udata.data[0x1c/2]>>8)&0x7));
+ if (AICA->TimCnt[2] > 0xFF00)
+ {
+ AICA->TimCnt[2] = 0xFFFF;
+ AICA->udata.data[0xa0/2]|=0x100;
+ }
+ AICA->udata.data[0x98/2]&=0xff00;
+ AICA->udata.data[0x98/2]|=AICA->TimCnt[2]>>8;
+ }
+}
+#endif
+
+INLINE INT32 AICA_UpdateSlot(aica_state *AICA, struct _SLOT *slot)
+{
+ INT32 sample;
+ int step=slot->step;
+ UINT32 addr1,addr2,addr_select; // current and next sample addresses
+ UINT32 *addr[2] = {&addr1, &addr2}; // used for linear interpolation
+ UINT32 *slot_addr[2] = {&(slot->cur_addr), &(slot->nxt_addr)}; //
+
+ if(SSCTL(slot)!=0) //no FM or noise yet
+ return 0;
+
+ if(PLFOS(slot)!=0)
+ {
+ step=step*AICAPLFO_Step(&(slot->PLFO));
+ step>>=SHIFT;
+ }
+
+ if(PCMS(slot) == 1)
+ {
+ addr1=slot->cur_addr>>SHIFT;
+ addr2=slot->nxt_addr>>SHIFT;
+ }
+ else if(PCMS(slot) == 0)
+ {
+ addr1=(slot->cur_addr>>(SHIFT-1))&AICA->RAM_MASK16;
+ addr2=(slot->nxt_addr>>(SHIFT-1))&AICA->RAM_MASK16;
+ }
+ else
+ {
+ addr1=slot->cur_addr>>SHIFT;
+ addr2=slot->nxt_addr>>SHIFT;
+ }
+
+ if(PCMS(slot) == 1) // 8-bit signed
+ {
+ INT8 *p1=(signed char *) (AICA->AICARAM+(((SA(slot)+addr1))&AICA->RAM_MASK));
+ INT8 *p2=(signed char *) (AICA->AICARAM+(((SA(slot)+addr2))&AICA->RAM_MASK));
+ INT32 s;
+ INT32 fpart=slot->cur_addr&((1<<SHIFT)-1);
+ s=(int) (p1[0]<<8)*((1<<SHIFT)-fpart)+(int) (p2[0]<<8)*fpart;
+ sample=(s>>SHIFT);
+ }
+ else if (PCMS(slot) == 0) //16 bit signed
+ {
+ UINT8 *p1=(UINT8 *) (AICA->AICARAM+((SA(slot)+addr1)&AICA->RAM_MASK));
+ UINT8 *p2=(UINT8 *) (AICA->AICARAM+((SA(slot)+addr2)&AICA->RAM_MASK));
+ INT32 s;
+ INT32 fpart=slot->cur_addr&((1<<SHIFT)-1);
+ s=(int) ((INT16)(p1[0] | (p1[1]<<8)))*((1<<SHIFT)-fpart)+(int) ((INT16)(p2[0] | (p2[1]<<8)))*fpart;
+ sample=(s>>SHIFT);
+ }
+ else // 4-bit ADPCM
+ {
+ UINT8 *base= slot->adbase;
+ INT32 s;
+ int cur_sample; //current ADPCM sample
+ int nxt_sample; //next ADPCM sample
+ INT32 fpart=slot->cur_addr&((1<<SHIFT)-1);
+ UINT32 steps_to_go = addr2, curstep = slot->curstep;
+
+ if (slot->adbase)
+ {
+ cur_sample = slot->cur_sample; // may already contains current decoded sample
+
+ // seek to the interpolation sample
+ while (curstep < steps_to_go)
+ {
+ int shift1 = 4 & (curstep << 2);
+ unsigned char delta1 = (*base>>shift1)&0xf;
+ DecodeADPCM(&(slot->cur_sample),delta1,&(slot->cur_quant));
+ if (!(++curstep & 1))
+ base++;
+ if (curstep == addr1)
+ cur_sample = slot->cur_sample;
+ if (curstep == LSA(slot))
+ {
+ slot->cur_lpsample = slot->cur_sample;
+ slot->cur_lpquant = slot->cur_quant;
+ }
+ }
+ nxt_sample = slot->cur_sample;
+
+ slot->adbase = base;
+ slot->curstep = curstep;
+
+ s=(int)cur_sample*((1<<SHIFT)-fpart)+(int)nxt_sample*fpart;
+ }
+ else
+ {
+ s = 0;
+ }
+
+ sample=(s>>SHIFT);
+ }
+
+ slot->prv_addr=slot->cur_addr;
+ slot->cur_addr+=step;
+ slot->nxt_addr=slot->cur_addr+(1<<SHIFT);
+
+ addr1=slot->cur_addr>>SHIFT;
+ addr2=slot->nxt_addr>>SHIFT;
+
+ if(addr1>=LSA(slot))
+ {
+ if(LPSLNK(slot) && slot->EG.state==ATTACK && slot->EG.D1R)
+ slot->EG.state = DECAY1;
+ }
+
+ for (addr_select=0; addr_select<2; addr_select++)
+ {
+ INT32 rem_addr;
+ switch(LPCTL(slot))
+ {
+ case 0: //no loop
+ if(*addr[addr_select]>=LSA(slot) && *addr[addr_select]>=LEA(slot))
+ {
+ AICA_StopSlot(slot,0);
+ }
+ break;
+ case 1: //normal loop
+ if(*addr[addr_select]>=LEA(slot))
+ {
+ slot->lpend = 1;
+ rem_addr = *slot_addr[addr_select] - (LEA(slot)<<SHIFT);
+ *slot_addr[addr_select]=(LSA(slot)<<SHIFT) + rem_addr;
+
+ if(PCMS(slot)>=2)
+ {
+ // restore the state @ LSA - the sampler will naturally walk to (LSA + remainder)
+ slot->adbase = &AICA->AICARAM[SA(slot)+(LSA(slot)/2)];
+ slot->curstep = LSA(slot);
+ if (PCMS(slot) == 2)
+ {
+ slot->cur_sample = slot->cur_lpsample;
+ slot->cur_quant = slot->cur_lpquant;
+ }
+
+// printf("Looping: slot_addr %x LSA %x LEA %x step %x base %x\n", *slot_addr[addr_select]>>SHIFT, LSA(slot), LEA(slot), slot->curstep, slot->adbase);
+ }
+ }
+ break;
+ }
+ }
+
+ if(ALFOS(slot)!=0)
+ {
+ sample=sample*AICAALFO_Step(&(slot->ALFO));
+ sample>>=SHIFT;
+ }
+
+ if(slot->EG.state==ATTACK)
+ sample=(sample*EG_Update(slot))>>SHIFT;
+ else
+ sample=(sample*EG_TABLE[EG_Update(slot)>>(SHIFT-10)])>>SHIFT;
+
+ return sample;
+}
+
+static void AICA_DoMasterSamples(aica_state *AICA, int nsamples)
+{
+ stream_sample_t *bufr,*bufl;
+ int sl, s, i;
+
+ bufr=bufferr;
+ bufl=bufferl;
+
+ for(s=0;s<nsamples;++s)
+ {
+ INT32 smpl, smpr;
+
+ smpl = smpr = 0;
+
+ // mix slots' direct output
+ for(sl=0;sl<64;++sl)
+ {
+ struct _SLOT *slot=AICA->Slots+sl;
+ RBUFDST=AICA->RINGBUF+AICA->BUFPTR;
+ if(AICA->Slots[sl].active)
+ {
+ unsigned int Enc;
+ signed int sample;
+
+ sample=AICA_UpdateSlot(AICA, slot);
+
+ Enc=((TL(slot))<<0x0)|((IMXL(slot))<<0xd);
+ aica_dsp_setsample(&AICA->DSP,(sample*AICA->LPANTABLE[Enc])>>(SHIFT-2),ISEL(slot),IMXL(slot));
+ Enc=((TL(slot))<<0x0)|((DIPAN(slot))<<0x8)|((DISDL(slot))<<0xd);
+ {
+ smpl+=(sample*AICA->LPANTABLE[Enc])>>SHIFT;
+ smpr+=(sample*AICA->RPANTABLE[Enc])>>SHIFT;
+ }
+ }
+
+ AICA->BUFPTR&=63;
+ }
+
+ // process the DSP
+ aica_dsp_step(&AICA->DSP);
+
+ // mix DSP output
+ for(i=0;i<16;++i)
+ {
+ if(EFSDL(i))
+ {
+ unsigned int Enc=((EFPAN(i))<<0x8)|((EFSDL(i))<<0xd);
+ smpl+=(AICA->DSP.EFREG[i]*AICA->LPANTABLE[Enc])>>SHIFT;
+ smpr+=(AICA->DSP.EFREG[i]*AICA->RPANTABLE[Enc])>>SHIFT;
+ }
+ }
+
+ *bufl++ = ICLIP16(smpl>>3);
+ *bufr++ = ICLIP16(smpr>>3);
+ }
+}
+
+#ifdef UNUSED_FUNCTION
+static int AICA_IRQCB(void *param)
+{
+ CheckPendingIRQ(param);
+ return -1;
+}
+#endif
+
+static STREAM_UPDATE( AICA_Update )
+{
+ aica_state *AICA = (aica_state *)param;
+ bufferl = outputs[0];
+ bufferr = outputs[1];
+ length = samples;
+ AICA_DoMasterSamples(AICA, samples);
+}
+
+static DEVICE_START( aica )
+{
+ const aica_interface *intf;
+
+ aica_state *AICA = get_safe_token(device);
+
+ intf = (const aica_interface *)device->static_config();
+
+ // init the emulation
+ AICA_Init(device, AICA, intf);
+
+ // set up the IRQ callbacks
+ {
+ AICA->IntARMCB = intf->irq_callback;
+
+ AICA->stream = device->machine().sound().stream_alloc(*device, 0, 2, 44100, AICA, AICA_Update);
+ }
+}
+
+static DEVICE_STOP( aica )
+{
+}
+
+void aica_set_ram_base(device_t *device, void *base, int size)
+{
+ aica_state *AICA = get_safe_token(device);
+ if (AICA)
+ {
+ AICA->AICARAM = (unsigned char *)base;
+ AICA->AICARAM_LENGTH = size;
+ AICA->RAM_MASK = AICA->AICARAM_LENGTH-1;
+ AICA->RAM_MASK16 = AICA->RAM_MASK & 0x7ffffe;
+ AICA->DSP.AICARAM = (UINT16 *)base;
+ AICA->DSP.AICARAM_LENGTH = size;
+ }
+}
+
+READ16_DEVICE_HANDLER( aica_r )
+{
+ aica_state *AICA = get_safe_token(device);
+ return AICA_r16(AICA, offset*2);
+}
+
+WRITE16_DEVICE_HANDLER( aica_w )
+{
+ aica_state *AICA = get_safe_token(device);
+ UINT16 tmp;
+
+ tmp = AICA_r16(AICA, offset*2);
+ COMBINE_DATA(&tmp);
+ AICA_w16(AICA, offset*2, tmp);
+}
+
+WRITE16_DEVICE_HANDLER( aica_midi_in )
+{
+ aica_state *AICA = get_safe_token(device);
+ AICA->MidiStack[AICA->MidiW++]=data;
+ AICA->MidiW &= 15;
+}
+
+READ16_DEVICE_HANDLER( aica_midi_out_r )
+{
+ aica_state *AICA = get_safe_token(device);
+ unsigned char val;
+
+ val=AICA->MidiStack[AICA->MidiR++];
+ AICA->MidiR&=7;
+ return val;
+}
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+DEVICE_GET_INFO( aica )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(aica_state); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( aica ); break;
+ case DEVINFO_FCT_STOP: info->start = DEVICE_STOP_NAME( aica ); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "AICA"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Sega/Yamaha custom"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0.1"); 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;
+ }
+}
+
+
+
+DEFINE_LEGACY_SOUND_DEVICE(AICA, aica);
diff --git a/trunk/src/emu/sound/aica.h b/trunk/src/emu/sound/aica.h
new file mode 100644
index 00000000000..cacee5de1cd
--- /dev/null
+++ b/trunk/src/emu/sound/aica.h
@@ -0,0 +1,31 @@
+/*
+
+ Sega/Yamaha AICA emulation
+*/
+
+#ifndef __AICA_H__
+#define __AICA_H__
+
+#include "devlegcy.h"
+
+typedef struct _aica_interface aica_interface;
+struct _aica_interface
+{
+ int master;
+ int roffset; /* offset in the region */
+ void (*irq_callback)(device_t *device, int state); /* irq callback */
+};
+
+void aica_set_ram_base(device_t *device, void *base, int size);
+
+// AICA register access
+READ16_DEVICE_HANDLER( aica_r );
+WRITE16_DEVICE_HANDLER( aica_w );
+
+// MIDI I/O access
+WRITE16_DEVICE_HANDLER( aica_midi_in );
+READ16_DEVICE_HANDLER( aica_midi_out_r );
+
+DECLARE_LEGACY_SOUND_DEVICE(AICA, aica);
+
+#endif /* __AICA_H__ */
diff --git a/trunk/src/emu/sound/aicadsp.c b/trunk/src/emu/sound/aicadsp.c
new file mode 100644
index 00000000000..8c5f6635995
--- /dev/null
+++ b/trunk/src/emu/sound/aicadsp.c
@@ -0,0 +1,350 @@
+#include "emu.h"
+#include "aica.h"
+#include "aicadsp.h"
+
+static UINT16 PACK(INT32 val)
+{
+ UINT32 temp;
+ int sign,exponent,k;
+
+ sign = (val >> 23) & 0x1;
+ temp = (val ^ (val << 1)) & 0xFFFFFF;
+ exponent = 0;
+ for (k=0; k<12; k++)
+ {
+ if (temp & 0x800000)
+ break;
+ temp <<= 1;
+ exponent += 1;
+ }
+ if (exponent < 12)
+ val = (val << exponent) & 0x3FFFFF;
+ else
+ val <<= 11;
+ val >>= 11;
+ val &= 0x7FF;
+ val |= sign << 15;
+ val |= exponent << 11;
+
+ return (UINT16)val;
+}
+
+static INT32 UNPACK(UINT16 val)
+{
+ int sign,exponent,mantissa;
+ INT32 uval;
+
+ sign = (val >> 15) & 0x1;
+ exponent = (val >> 11) & 0xF;
+ mantissa = val & 0x7FF;
+ uval = mantissa << 11;
+ if (exponent > 11)
+ {
+ exponent = 11;
+ uval |= sign << 22;
+ }
+ else
+ uval |= (sign ^ 1) << 22;
+ uval |= sign << 23;
+ uval <<= 8;
+ uval >>= 8;
+ uval >>= exponent;
+
+ return uval;
+}
+
+void aica_dsp_init(struct _AICADSP *DSP)
+{
+ memset(DSP,0,sizeof(struct _AICADSP));
+ DSP->RBL=0x8000;
+ DSP->Stopped=1;
+}
+
+void aica_dsp_step(struct _AICADSP *DSP)
+{
+ INT32 ACC=0; //26 bit
+ INT32 SHIFTED=0; //24 bit
+ INT32 X=0; //24 bit
+ INT32 Y=0; //13 bit
+ INT32 B=0; //26 bit
+ INT32 INPUTS=0; //24 bit
+ INT32 MEMVAL=0;
+ INT32 FRC_REG=0; //13 bit
+ INT32 Y_REG=0; //24 bit
+ UINT32 ADDR=0;
+ UINT32 ADRS_REG=0; //13 bit
+ int step;
+
+ if(DSP->Stopped)
+ return;
+
+ memset(DSP->EFREG,0,2*16);
+#if 0
+ int dump=0;
+ FILE *f=NULL;
+ if(dump)
+ f=fopen("dsp.txt","wt");
+#endif
+ for(step=0;step</*128*/DSP->LastStep;++step)
+ {
+ UINT16 *IPtr=DSP->MPRO+step*8;
+
+// if(IPtr[0]==0 && IPtr[1]==0 && IPtr[2]==0 && IPtr[3]==0)
+// break;
+
+ UINT32 TRA=(IPtr[0]>>9)&0x7F;
+ UINT32 TWT=(IPtr[0]>>8)&0x01;
+ UINT32 TWA=(IPtr[0]>>1)&0x7F;
+
+ UINT32 XSEL=(IPtr[2]>>15)&0x01;
+ UINT32 YSEL=(IPtr[2]>>13)&0x03;
+ UINT32 IRA=(IPtr[2]>>7)&0x3F;
+ UINT32 IWT=(IPtr[2]>>6)&0x01;
+ UINT32 IWA=(IPtr[2]>>1)&0x1F;
+
+ UINT32 TABLE=(IPtr[4]>>15)&0x01;
+ UINT32 MWT=(IPtr[4]>>14)&0x01;
+ UINT32 MRD=(IPtr[4]>>13)&0x01;
+ UINT32 EWT=(IPtr[4]>>12)&0x01;
+ UINT32 EWA=(IPtr[4]>>8)&0x0F;
+ UINT32 ADRL=(IPtr[4]>>7)&0x01;
+ UINT32 FRCL=(IPtr[4]>>6)&0x01;
+ UINT32 SHIFT=(IPtr[4]>>4)&0x03;
+ UINT32 YRL=(IPtr[4]>>3)&0x01;
+ UINT32 NEGB=(IPtr[4]>>2)&0x01;
+ UINT32 ZERO=(IPtr[4]>>1)&0x01;
+ UINT32 BSEL=(IPtr[4]>>0)&0x01;
+
+ UINT32 NOFL=(IPtr[6]>>15)&1; //????
+ UINT32 COEF=step;
+
+ UINT32 MASA=(IPtr[6]>>9)&0x1f; //???
+ UINT32 ADREB=(IPtr[6]>>8)&0x1;
+ UINT32 NXADR=(IPtr[6]>>7)&0x1;
+
+ INT64 v;
+
+ //operations are done at 24 bit precision
+#if 0
+ if(MASA)
+ int a=1;
+ if(NOFL)
+ int a=1;
+
+// int dump=0;
+
+ if(f)
+ {
+#define DUMP(v) fprintf(f," " #v ": %04X",v);
+
+ fprintf(f,"%d: ",step);
+ DUMP(ACC);
+ DUMP(SHIFTED);
+ DUMP(X);
+ DUMP(Y);
+ DUMP(B);
+ DUMP(INPUTS);
+ DUMP(MEMVAL);
+ DUMP(FRC_REG);
+ DUMP(Y_REG);
+ DUMP(ADDR);
+ DUMP(ADRS_REG);
+ fprintf(f,"\n");
+ }
+#endif
+ //INPUTS RW
+ assert(IRA<0x32);
+ if(IRA<=0x1f)
+ INPUTS=DSP->MEMS[IRA];
+ else if(IRA<=0x2F)
+ INPUTS=DSP->MIXS[IRA-0x20]<<4; //MIXS is 20 bit
+ else if(IRA<=0x31)
+ INPUTS=0;
+
+ INPUTS<<=8;
+ INPUTS>>=8;
+ //if(INPUTS&0x00800000)
+ // INPUTS|=0xFF000000;
+
+ if(IWT)
+ {
+ DSP->MEMS[IWA]=MEMVAL; //MEMVAL was selected in previous MRD
+ if(IRA==IWA)
+ INPUTS=MEMVAL;
+ }
+
+ //Operand sel
+ //B
+ if(!ZERO)
+ {
+ if(BSEL)
+ B=ACC;
+ else
+ {
+ B=DSP->TEMP[(TRA+DSP->DEC)&0x7F];
+ B<<=8;
+ B>>=8;
+ //if(B&0x00800000)
+ // B|=0xFF000000; //Sign extend
+ }
+ if(NEGB)
+ B=0-B;
+ }
+ else
+ B=0;
+
+ //X
+ if(XSEL)
+ X=INPUTS;
+ else
+ {
+ X=DSP->TEMP[(TRA+DSP->DEC)&0x7F];
+ X<<=8;
+ X>>=8;
+ //if(X&0x00800000)
+ // X|=0xFF000000;
+ }
+
+ //Y
+ if(YSEL==0)
+ Y=FRC_REG;
+ else if(YSEL==1)
+ Y=DSP->COEF[COEF<<1]>>3; //COEF is 16 bits
+ else if(YSEL==2)
+ Y=(Y_REG>>11)&0x1FFF;
+ else if(YSEL==3)
+ Y=(Y_REG>>4)&0x0FFF;
+
+ if(YRL)
+ Y_REG=INPUTS;
+
+ //Shifter
+ if(SHIFT==0)
+ {
+ SHIFTED=ACC;
+ if(SHIFTED>0x007FFFFF)
+ SHIFTED=0x007FFFFF;
+ if(SHIFTED<(-0x00800000))
+ SHIFTED=-0x00800000;
+ }
+ else if(SHIFT==1)
+ {
+ SHIFTED=ACC*2;
+ if(SHIFTED>0x007FFFFF)
+ SHIFTED=0x007FFFFF;
+ if(SHIFTED<(-0x00800000))
+ SHIFTED=-0x00800000;
+ }
+ else if(SHIFT==2)
+ {
+ SHIFTED=ACC*2;
+ SHIFTED<<=8;
+ SHIFTED>>=8;
+ //SHIFTED&=0x00FFFFFF;
+ //if(SHIFTED&0x00800000)
+ // SHIFTED|=0xFF000000;
+ }
+ else if(SHIFT==3)
+ {
+ SHIFTED=ACC;
+ SHIFTED<<=8;
+ SHIFTED>>=8;
+ //SHIFTED&=0x00FFFFFF;
+ //if(SHIFTED&0x00800000)
+ // SHIFTED|=0xFF000000;
+ }
+
+ //ACCUM
+ Y<<=19;
+ Y>>=19;
+ //if(Y&0x1000)
+ // Y|=0xFFFFF000;
+
+ v=(((INT64) X*(INT64) Y)>>12);
+ ACC=(int) v+B;
+
+ if(TWT)
+ DSP->TEMP[(TWA+DSP->DEC)&0x7F]=SHIFTED;
+
+ if(FRCL)
+ {
+ if(SHIFT==3)
+ FRC_REG=SHIFTED&0x0FFF;
+ else
+ FRC_REG=(SHIFTED>>11)&0x1FFF;
+ }
+
+ if(MRD || MWT)
+ //if(0)
+ {
+ ADDR=DSP->MADRS[MASA<<1];
+ if(!TABLE)
+ ADDR+=DSP->DEC;
+ if(ADREB)
+ ADDR+=ADRS_REG&0x0FFF;
+ if(NXADR)
+ ADDR++;
+ if(!TABLE)
+ ADDR&=DSP->RBL-1;
+ else
+ ADDR&=0xFFFF;
+ //ADDR<<=1;
+ //ADDR+=DSP->RBP<<13;
+ //MEMVAL=DSP->AICARAM[ADDR>>1];
+ ADDR+=DSP->RBP<<10;
+ if(MRD && (step&1)) //memory only allowed on odd? DoA inserts NOPs on even
+ {
+ if(NOFL)
+ MEMVAL=DSP->AICARAM[ADDR]<<8;
+ else
+ MEMVAL=UNPACK(DSP->AICARAM[ADDR]);
+ }
+ if(MWT && (step&1))
+ {
+ if(NOFL)
+ DSP->AICARAM[ADDR]=SHIFTED>>8;
+ else
+ DSP->AICARAM[ADDR]=PACK(SHIFTED);
+ }
+ }
+
+ if(ADRL)
+ {
+ if(SHIFT==3)
+ ADRS_REG=(SHIFTED>>12)&0xFFF;
+ else
+ ADRS_REG=(INPUTS>>16);
+ }
+
+ if(EWT)
+ DSP->EFREG[EWA]+=SHIFTED>>8;
+
+ }
+ --DSP->DEC;
+ memset(DSP->MIXS,0,4*16);
+// if(f)
+// fclose(f);
+}
+
+void aica_dsp_setsample(struct _AICADSP *DSP,INT32 sample,int SEL,int MXL)
+{
+ //DSP->MIXS[SEL]+=sample<<(MXL+1)/*7*/;
+ DSP->MIXS[SEL]+=sample;
+// if(MXL)
+// int a=1;
+}
+
+void aica_dsp_start(struct _AICADSP *DSP)
+{
+ int i;
+ DSP->Stopped=0;
+ for(i=127;i>=0;--i)
+ {
+ UINT16 *IPtr=DSP->MPRO+i*8;
+
+ if(IPtr[0]!=0 || IPtr[2]!=0 || IPtr[4]!=0 || IPtr[6]!=0)
+ break;
+ }
+ DSP->LastStep=i+1;
+
+}
diff --git a/trunk/src/emu/sound/aicadsp.h b/trunk/src/emu/sound/aicadsp.h
new file mode 100644
index 00000000000..9f256d68773
--- /dev/null
+++ b/trunk/src/emu/sound/aicadsp.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#ifndef __AICADSP_H__
+#define __AICADSP_H__
+
+//the DSP Context
+struct _AICADSP
+{
+//Config
+ UINT16 *AICARAM;
+ UINT32 AICARAM_LENGTH;
+ UINT32 RBP; //Ring buf pointer
+ UINT32 RBL; //Delay ram (Ring buffer) size in words
+
+//context
+
+ INT16 COEF[128*2]; //16 bit signed
+ UINT16 MADRS[64*2]; //offsets (in words), 16 bit
+ UINT16 MPRO[128*4*2*2]; //128 steps 64 bit
+ INT32 TEMP[128]; //TEMP regs,24 bit signed
+ INT32 MEMS[32]; //MEMS regs,24 bit signed
+ UINT32 DEC;
+
+//input
+ INT32 MIXS[16]; //MIXS, 24 bit signed
+ INT16 EXTS[2]; //External inputs (CDDA) 16 bit signed
+
+//output
+ INT16 EFREG[16]; //EFREG, 16 bit signed
+
+ int Stopped;
+ int LastStep;
+};
+
+void aica_dsp_init(struct _AICADSP *DSP);
+void aica_dsp_setsample(struct _AICADSP *DSP, INT32 sample, INT32 SEL, INT32 MXL);
+void aica_dsp_step(struct _AICADSP *DSP);
+void aica_dsp_start(struct _AICADSP *DSP);
+
+#endif /* __AICADSP_H__ */
diff --git a/trunk/src/emu/sound/aicalfo.c b/trunk/src/emu/sound/aicalfo.c
new file mode 100644
index 00000000000..f992ea29a2d
--- /dev/null
+++ b/trunk/src/emu/sound/aicalfo.c
@@ -0,0 +1,159 @@
+/*
+ AICA LFO handling
+
+ Part of the AICA emulator package.
+ (not compiled directly, #included from aica.c)
+
+ By ElSemi, kingshriek, Deunan Knute, and R. Belmont
+*/
+
+#define LFO_SHIFT 8
+
+struct _LFO
+{
+ unsigned short phase;
+ UINT32 phase_step;
+ int *table;
+ int *scale;
+};
+
+#define LFIX(v) ((unsigned int) ((float) (1<<LFO_SHIFT)*(v)))
+
+//Convert DB to multiply amplitude
+#define DB(v) LFIX(pow(10.0,v/20.0))
+
+//Convert cents to step increment
+#define CENTS(v) LFIX(pow(2.0,v/1200.0))
+
+static int PLFO_TRI[256],PLFO_SQR[256],PLFO_SAW[256],PLFO_NOI[256];
+static int ALFO_TRI[256],ALFO_SQR[256],ALFO_SAW[256],ALFO_NOI[256];
+static const float LFOFreq[32]={0.17f,0.19f,0.23f,0.27f,0.34f,0.39f,0.45f,0.55f,0.68f,0.78f,0.92f,1.10f,1.39f,1.60f,1.87f,2.27f,
+ 2.87f,3.31f,3.92f,4.79f,6.15f,7.18f,8.60f,10.8f,14.4f,17.2f,21.5f,28.7f,43.1f,57.4f,86.1f,172.3f};
+static const float ASCALE[8]={0.0f,0.4f,0.8f,1.5f,3.0f,6.0f,12.0f,24.0f};
+static const float PSCALE[8]={0.0f,7.0f,13.5f,27.0f,55.0f,112.0f,230.0f,494.0f};
+static int PSCALES[8][256];
+static int ASCALES[8][256];
+
+static void AICALFO_Init(running_machine &machine)
+{
+ int i,s;
+ for(i=0;i<256;++i)
+ {
+ int a,p;
+// float TL;
+ //Saw
+ a=255-i;
+ if(i<128)
+ p=i;
+ else
+ p=i-256;
+ ALFO_SAW[i]=a;
+ PLFO_SAW[i]=p;
+
+ //Square
+ if(i<128)
+ {
+ a=255;
+ p=127;
+ }
+ else
+ {
+ a=0;
+ p=-128;
+ }
+ ALFO_SQR[i]=a;
+ PLFO_SQR[i]=p;
+
+ //Tri
+ if(i<128)
+ a=255-(i*2);
+ else
+ a=(i*2)-256;
+ if(i<64)
+ p=i*2;
+ else if(i<128)
+ p=255-i*2;
+ else if(i<192)
+ p=256-i*2;
+ else
+ p=i*2-511;
+ ALFO_TRI[i]=a;
+ PLFO_TRI[i]=p;
+
+ //noise
+ //a=lfo_noise[i];
+ a=machine.rand()&0xff;
+ p=128-a;
+ ALFO_NOI[i]=a;
+ PLFO_NOI[i]=p;
+ }
+
+ for(s=0;s<8;++s)
+ {
+ float limit=PSCALE[s];
+ for(i=-128;i<128;++i)
+ {
+ PSCALES[s][i+128]=CENTS(((limit*(float) i)/128.0));
+ }
+ limit=-ASCALE[s];
+ for(i=0;i<256;++i)
+ {
+ ASCALES[s][i]=DB(((limit*(float) i)/256.0));
+ }
+ }
+}
+
+INLINE signed int AICAPLFO_Step(struct _LFO *LFO)
+{
+ int p;
+
+ LFO->phase+=LFO->phase_step;
+#if LFO_SHIFT!=8
+ LFO->phase&=(1<<(LFO_SHIFT+8))-1;
+#endif
+ p=LFO->table[LFO->phase>>LFO_SHIFT];
+ p=LFO->scale[p+128];
+ return p<<(SHIFT-LFO_SHIFT);
+}
+
+INLINE signed int AICAALFO_Step(struct _LFO *LFO)
+{
+ int p;
+ LFO->phase+=LFO->phase_step;
+#if LFO_SHIFT!=8
+ LFO->phase&=(1<<(LFO_SHIFT+8))-1;
+#endif
+ p=LFO->table[LFO->phase>>LFO_SHIFT];
+ p=LFO->scale[p];
+ return p<<(SHIFT-LFO_SHIFT);
+}
+
+static void AICALFO_ComputeStep(struct _LFO *LFO,UINT32 LFOF,UINT32 LFOWS,UINT32 LFOS,int ALFO)
+{
+ float step=(float) LFOFreq[LFOF]*256.0/(float)44100.0;
+ LFO->phase_step=(unsigned int) ((float) (1<<LFO_SHIFT)*step);
+ if(ALFO)
+ {
+ switch(LFOWS)
+ {
+ case 0: LFO->table=ALFO_SAW; break;
+ case 1: LFO->table=ALFO_SQR; break;
+ case 2: LFO->table=ALFO_TRI; break;
+ case 3: LFO->table=ALFO_NOI; break;
+ default: printf("Unknown ALFO %d\n", LFOWS);
+ }
+ LFO->scale=ASCALES[LFOS];
+ }
+ else
+ {
+ switch(LFOWS)
+ {
+ case 0: LFO->table=PLFO_SAW; break;
+ case 1: LFO->table=PLFO_SQR; break;
+ case 2: LFO->table=PLFO_TRI; break;
+ case 3: LFO->table=PLFO_NOI; break;
+ default: printf("Unknown PLFO %d\n", LFOWS);
+ }
+ LFO->scale=PSCALES[LFOS];
+ }
+}
diff --git a/trunk/src/emu/sound/asc.c b/trunk/src/emu/sound/asc.c
new file mode 100644
index 00000000000..4d2707cbd7f
--- /dev/null
+++ b/trunk/src/emu/sound/asc.c
@@ -0,0 +1,616 @@
+/***************************************************************************
+
+ asc.c
+
+ Apple Sound Chip (ASC) 344S0063
+ Enhanced Apple Sound Chip (EASC) 343S1063
+
+ Emulation by R. Belmont
+
+ Registers:
+ 0x800: VERSION
+ 0x801: MODE (1=FIFO mode, 2=wavetable mode)
+ 0x802: CONTROL (bit 0=analog or PWM output, 1=stereo/mono, 7=processing time exceeded)
+ 0x803: FIFO MODE (bit 7=clear FIFO, bit 1="non-ROM companding", bit 0="ROM companding")
+ 0x804: FIFO IRQ STATUS (bit 0=ch A 1/2 full, 1=ch A full, 2=ch B 1/2 full, 3=ch B full)
+ 0x805: WAVETABLE CONTROL (bits 0-3 wavetables 0-3 start)
+ 0x806: VOLUME (bits 2-4 = 3 bit internal ASC volume, bits 5-7 = volume control sent to Sony sound chip)
+ 0x807: CLOCK RATE (0 = Mac 22257 Hz, 1 = undefined, 2 = 22050 Hz, 3 = 44100 Hz)
+ 0x80a: PLAY REC A
+ 0x80f: TEST (bits 6-7 = digital test, bits 4-5 = analog test)
+ 0x810: WAVETABLE 0 PHASE (big-endian 9.15 fixed-point, only 24 bits valid)
+ 0x814: WAVETABLE 0 INCREMENT (big-endian 9.15 fixed-point, only 24 bits valid)
+ 0x818: WAVETABLE 1 PHASE
+ 0x81C: WAVETABLE 1 INCREMENT
+ 0x820: WAVETABLE 2 PHASE
+ 0x824: WAVETABLE 2 INCREMENT
+ 0x828: WAVETABLE 3 PHASE
+ 0x82C: WAVETABLE 3 INCREMENT
+
+***************************************************************************/
+
+#include "emu.h"
+#include "asc.h"
+
+// device type definition
+const device_type ASC = &device_creator<asc_device>;
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// asc_device - constructor
+//-------------------------------------------------
+
+asc_device::asc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, ASC, "ASC", tag, owner, clock),
+ device_sound_interface(mconfig, *this),
+ m_chip_type(0),
+ m_irq_cb(NULL)
+{
+}
+
+
+//-------------------------------------------------
+// static_set_type - configuration helper to set
+// the chip type
+//-------------------------------------------------
+
+void asc_device::static_set_type(device_t &device, int type)
+{
+ asc_device &asc = downcast<asc_device &>(device);
+ asc.m_chip_type = type;
+}
+
+//-------------------------------------------------
+// static_set_type - configuration helper to set
+// the IRQ callback
+//-------------------------------------------------
+
+
+void asc_device::static_set_irqf(device_t &device, void (*irqf)(device_t *device, int state))
+{
+ asc_device &asc = downcast<asc_device &>(device);
+ asc.m_irq_cb = irqf;
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void asc_device::device_start()
+{
+ // create the stream
+ m_stream = machine().sound().stream_alloc(*this, 0, 2, 22257, this);
+
+ memset(m_regs, 0, sizeof(m_regs));
+
+ m_timer = timer_alloc(0, NULL);
+
+ save_item(NAME(m_fifo_a_rdptr));
+ save_item(NAME(m_fifo_b_rdptr));
+ save_item(NAME(m_fifo_a_wrptr));
+ save_item(NAME(m_fifo_b_wrptr));
+ save_item(NAME(m_fifo_cap_a));
+ save_item(NAME(m_fifo_cap_b));
+ save_item(NAME(m_fifo_a));
+ save_item(NAME(m_fifo_b));
+ save_item(NAME(m_regs));
+ save_item(NAME(m_phase));
+ save_item(NAME(m_incr));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void asc_device::device_reset()
+{
+ m_stream->update();
+
+ memset(m_regs, 0, sizeof(m_regs));
+ memset(m_fifo_a, 0, sizeof(m_fifo_a));
+ memset(m_fifo_b, 0, sizeof(m_fifo_b));
+ memset(m_phase, 0, sizeof(m_phase));
+ memset(m_incr, 0, sizeof(m_incr));
+
+ m_fifo_a_rdptr = m_fifo_b_rdptr = 0;
+ m_fifo_a_wrptr = m_fifo_b_wrptr = 0;
+ m_fifo_cap_a = m_fifo_cap_b = 0;
+}
+
+//-------------------------------------------------
+// device_timer - called when our device timer expires
+//-------------------------------------------------
+
+void asc_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
+{
+ m_stream->update();
+}
+
+//-------------------------------------------------
+// sound_stream_update - handle update requests for
+// our sound stream
+//-------------------------------------------------
+
+void asc_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+{
+ stream_sample_t *outL, *outR;
+ int i, ch;
+ static UINT32 wtoffs[2] = { 0, 0x200 };
+
+ outL = outputs[0];
+ outR = outputs[1];
+
+ switch (m_regs[R_MODE-0x800] & 3)
+ {
+ case 0: // chip off
+ for (i = 0; i < samples; i++)
+ {
+ outL[i] = outR[i] = 0;
+ }
+ break;
+
+ case 1: // FIFO mode
+ for (i = 0; i < samples; i++)
+ {
+ INT8 smpll, smplr;
+
+ smpll = (INT8)m_fifo_a[m_fifo_a_rdptr]^0x80;
+ smplr = (INT8)m_fifo_b[m_fifo_b_rdptr]^0x80;
+
+ // don't advance the sample pointer if there are no more samples
+ if (m_fifo_cap_a)
+ {
+ m_fifo_a_rdptr++;
+ m_fifo_a_rdptr &= 0x3ff;
+ m_fifo_cap_a--;
+ }
+
+ if (m_fifo_cap_b)
+ {
+ m_fifo_b_rdptr++;
+ m_fifo_b_rdptr &= 0x3ff;
+ m_fifo_cap_b--;
+ }
+
+ switch (m_chip_type)
+ {
+ case ASC_TYPE_SONORA:
+ if (m_fifo_cap_a < 0x200)
+ {
+ m_regs[R_FIFOSTAT-0x800] |= 0x4; // fifo less than half full
+ m_regs[R_FIFOSTAT-0x800] |= 0x8; // just pass the damn test
+ if (m_irq_cb)
+ {
+ m_irq_cb(this, 1);
+ }
+ }
+ break;
+
+ default:
+ if (m_fifo_cap_a == 0x1ff)
+ {
+ m_regs[R_FIFOSTAT-0x800] |= 1; // fifo A half-empty
+ if (m_irq_cb)
+ {
+ m_irq_cb(this, 1);
+ }
+ }
+ else if (m_fifo_cap_a == 0x1) // fifo A fully empty
+ {
+ m_regs[R_FIFOSTAT-0x800] |= 2; // fifo A empty
+ if (m_irq_cb)
+ {
+ m_irq_cb(this, 1);
+ }
+ }
+
+ if (m_fifo_cap_b == 0x1ff)
+ {
+ m_regs[R_FIFOSTAT-0x800] |= 4; // fifo B half-empty
+ if (m_irq_cb)
+ {
+ m_irq_cb(this, 1);
+ }
+ }
+ else if (m_fifo_cap_b == 0x1) // fifo B fully empty
+ {
+ m_regs[R_FIFOSTAT-0x800] |= 8; // fifo B empty
+ if (m_irq_cb)
+ {
+ m_irq_cb(this, 1);
+ }
+ }
+ break;
+ }
+
+ outL[i] = smpll * 64;
+ outR[i] = smplr * 64;
+ }
+ break;
+
+ case 2: // wavetable mode
+ for (i = 0; i < samples; i++)
+ {
+ INT32 mixL, mixR;
+ INT8 smpl;
+
+ mixL = mixR = 0;
+
+ // update channel pointers
+ for (ch = 0; ch < 4; ch++)
+ {
+ m_phase[ch] += m_incr[ch];
+
+ if (ch < 2)
+ {
+ smpl = (INT8)m_fifo_a[((m_phase[ch]>>15)&0x1ff) + wtoffs[ch&1]];
+ }
+ else
+ {
+ smpl = (INT8)m_fifo_b[((m_phase[ch]>>15)&0x1ff) + wtoffs[ch&1]];
+ }
+
+ smpl ^= 0x80;
+ mixL += smpl*256;
+ mixR += smpl*256;
+ }
+
+ outL[i] = mixL>>2;
+ outR[i] = mixR>>2;
+ }
+ break;
+ }
+
+// printf("rdA %04x rdB %04x wrA %04x wrB %04x (capA %04x B %04x)\n", m_fifo_a_rdptr, m_fifo_b_rdptr, m_fifo_a_wrptr, m_fifo_b_wrptr, m_fifo_cap_a, m_fifo_cap_b);
+}
+
+//-------------------------------------------------
+// read - read from the chip's registers and internal RAM
+//-------------------------------------------------
+
+READ8_MEMBER( asc_device::read )
+{
+ UINT8 rv;
+
+// printf("ASC: read at %x\n", offset);
+
+ // not sure what actually happens when the CPU reads the FIFO...
+ if (offset < 0x400)
+ {
+ return m_fifo_a[offset];
+ }
+ else if (offset < 0x800)
+ {
+ return m_fifo_b[offset-0x400];
+ }
+ else
+ {
+ m_stream->update();
+ switch (offset)
+ {
+ case R_VERSION:
+ switch (m_chip_type)
+ {
+ case ASC_TYPE_ASC:
+ return 0;
+
+ case ASC_TYPE_V8:
+ case ASC_TYPE_EAGLE:
+ case ASC_TYPE_SPICE:
+ case ASC_TYPE_VASP:
+ return 0xe8;
+
+ case ASC_TYPE_SONORA:
+ return 0xbc;
+
+ default: // return the actual register value
+ break;
+ }
+ break;
+
+ case R_MODE:
+ switch (m_chip_type)
+ {
+ case ASC_TYPE_V8:
+ case ASC_TYPE_EAGLE:
+ case ASC_TYPE_SPICE:
+ case ASC_TYPE_VASP:
+ return 1;
+
+ default:
+ break;
+ }
+ break;
+
+ case R_CONTROL:
+ switch (m_chip_type)
+ {
+ case ASC_TYPE_V8:
+ case ASC_TYPE_EAGLE:
+ case ASC_TYPE_SPICE:
+ case ASC_TYPE_VASP:
+ return 1;
+
+ default:
+ break;
+ }
+ break;
+
+ case R_FIFOSTAT:
+ if (m_chip_type == ASC_TYPE_V8)
+ {
+ rv = 3;
+ }
+ else
+ {
+ rv = m_regs[R_FIFOSTAT-0x800];
+ }
+
+// printf("Read FIFO stat = %02x\n", rv);
+
+ // reading this register clears all bits
+ m_regs[R_FIFOSTAT-0x800] = 0;
+
+ // reading this clears interrupts
+ if (m_irq_cb)
+ {
+ m_irq_cb(this, 0);
+ }
+
+ return rv;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ // WT inc/phase registers - rebuild from "live" copies"
+ if ((offset >= 0x810) && (offset <= 0x82f))
+ {
+ m_regs[0x11] = m_phase[0]>>16;
+ m_regs[0x12] = m_phase[0]>>8;
+ m_regs[0x13] = m_phase[0];
+ m_regs[0x15] = m_incr[0]>>16;
+ m_regs[0x16] = m_incr[0]>>8;
+ m_regs[0x17] = m_incr[0];
+
+ m_regs[0x19] = m_phase[1]>>16;
+ m_regs[0x1a] = m_phase[1]>>8;
+ m_regs[0x1b] = m_phase[1];
+ m_regs[0x1d] = m_incr[1]>>16;
+ m_regs[0x1e] = m_incr[1]>>8;
+ m_regs[0x1f] = m_incr[1];
+
+ m_regs[0x21] = m_phase[2]>>16;
+ m_regs[0x22] = m_phase[2]>>8;
+ m_regs[0x23] = m_phase[2];
+ m_regs[0x25] = m_incr[2]>>16;
+ m_regs[0x26] = m_incr[2]>>8;
+ m_regs[0x27] = m_incr[2];
+
+ m_regs[0x29] = m_phase[3]>>16;
+ m_regs[0x2a] = m_phase[3]>>8;
+ m_regs[0x2b] = m_phase[3];
+ m_regs[0x2d] = m_incr[3]>>16;
+ m_regs[0x2e] = m_incr[3]>>8;
+ m_regs[0x2f] = m_incr[3];
+ }
+
+ return m_regs[offset-0x800];
+}
+
+//-------------------------------------------------
+// write - write to the chip's registers and internal RAM
+//-------------------------------------------------
+
+WRITE8_MEMBER( asc_device::write )
+{
+// printf("ASC: write %02x to %x\n", data, offset);
+
+ if (offset < 0x400)
+ {
+ if (m_regs[R_MODE-0x800] == 1)
+ {
+ m_fifo_a[m_fifo_a_wrptr++] = data;
+ m_fifo_cap_a++;
+
+ if (m_fifo_cap_a == 0x3ff)
+ {
+ m_regs[R_FIFOSTAT-0x800] |= 2; // fifo A full
+ }
+
+ m_fifo_a_wrptr &= 0x3ff;
+ }
+ else
+ {
+ m_fifo_a[offset] = data;
+ }
+ }
+ else if (offset < 0x800)
+ {
+ if (m_regs[R_MODE-0x800] == 1)
+ {
+ m_fifo_b[m_fifo_b_wrptr++] = data;
+ m_fifo_cap_b++;
+
+ if (m_fifo_cap_b == 0x3ff)
+ {
+ m_regs[R_FIFOSTAT-0x800] |= 8; // fifo B full
+ }
+
+ m_fifo_b_wrptr &= 0x3ff;
+ }
+ else
+ {
+ m_fifo_b[offset-0x400] = data;
+ }
+ }
+ else
+ {
+// printf("ASC: %02x to %x (was %x)\n", data, offset, m_regs[offset-0x800]);
+
+ m_stream->update();
+ switch (offset)
+ {
+ case R_MODE:
+ data &= 3; // only bits 0 and 1 can be written
+
+ if (data != m_regs[R_MODE-0x800])
+ {
+ m_fifo_a_rdptr = m_fifo_b_rdptr = 0;
+ m_fifo_a_wrptr = m_fifo_b_wrptr = 0;
+ m_fifo_cap_a = m_fifo_cap_b = 0;
+
+ if (data != 0)
+ {
+ m_timer->adjust(attotime::zero, 0, attotime::from_hz(22257/4));
+ }
+ else
+ {
+ m_timer->adjust(attotime::never);
+ }
+ }
+ break;
+
+ case R_FIFOMODE:
+ if (data & 0x80)
+ {
+ m_fifo_a_rdptr = m_fifo_b_rdptr = 0;
+ m_fifo_a_wrptr = m_fifo_b_wrptr = 0;
+ m_fifo_cap_a = m_fifo_cap_b = 0;
+ }
+ break;
+
+ case R_WTCONTROL:
+// printf("One-shot wavetable %02x\n", data);
+ break;
+
+ case 0x811:
+ m_phase[0] &= 0x00ffff;
+ m_phase[0] |= data<<16;
+ break;
+
+ case 0x812:
+ m_phase[0] &= 0xff00ff;
+ m_phase[0] |= data<<8;
+ break;
+
+ case 0x813:
+ m_phase[0] &= 0xffff00;
+ m_phase[0] |= data;
+ break;
+
+ case 0x815:
+ m_incr[0] &= 0x00ffff;
+ m_incr[0] |= data<<16;
+ break;
+
+ case 0x816:
+ m_incr[0] &= 0xff00ff;
+ m_incr[0] |= data<<8;
+ break;
+
+ case 0x817:
+ m_incr[0] &= 0xffff00;
+ m_incr[0] |= data;
+ break;
+
+ case 0x819:
+ m_phase[1] &= 0x00ffff;
+ m_phase[1] |= data<<16;
+ break;
+
+ case 0x81a:
+ m_phase[1] &= 0xff00ff;
+ m_phase[1] |= data<<8;
+ break;
+
+ case 0x81b:
+ m_phase[1] &= 0xffff00;
+ m_phase[1] |= data;
+ break;
+
+ case 0x81d:
+ m_incr[1] &= 0x00ffff;
+ m_incr[1] |= data<<16;
+ break;
+
+ case 0x81e:
+ m_incr[1] &= 0xff00ff;
+ m_incr[1] |= data<<8;
+ break;
+
+ case 0x81f:
+ m_incr[1] &= 0xffff00;
+ m_incr[1] |= data;
+ break;
+
+ case 0x821:
+ m_phase[2] &= 0x00ffff;
+ m_phase[2] |= data<<16;
+ break;
+
+ case 0x822:
+ m_phase[2] &= 0xff00ff;
+ m_phase[2] |= data<<8;
+ break;
+
+ case 0x823:
+ m_phase[2] &= 0xffff00;
+ m_phase[2] |= data;
+ break;
+
+ case 0x825:
+ m_incr[2] &= 0x00ffff;
+ m_incr[2] |= data<<16;
+ break;
+
+ case 0x826:
+ m_incr[2] &= 0xff00ff;
+ m_incr[2] |= data<<8;
+ break;
+
+ case 0x827:
+ m_incr[2] &= 0xffff00;
+ m_incr[2] |= data;
+ break;
+
+ case 0x829:
+ m_phase[3] &= 0x00ffff;
+ m_phase[3] |= data<<16;
+ break;
+
+ case 0x82a:
+ m_phase[3] &= 0xff00ff;
+ m_phase[3] |= data<<8;
+ break;
+
+ case 0x82b:
+ m_phase[3] &= 0xffff00;
+ m_phase[3] |= data;
+ break;
+
+ case 0x82d:
+ m_incr[3] &= 0x00ffff;
+ m_incr[3] |= data<<16;
+ break;
+
+ case 0x82e:
+ m_incr[3] &= 0xff00ff;
+ m_incr[3] |= data<<8;
+ break;
+
+ case 0x82f:
+ m_incr[3] &= 0xffff00;
+ m_incr[3] |= data;
+ break;
+ }
+
+ m_regs[offset-0x800] = data;
+ }
+}
diff --git a/trunk/src/emu/sound/asc.h b/trunk/src/emu/sound/asc.h
new file mode 100644
index 00000000000..147edc0e93d
--- /dev/null
+++ b/trunk/src/emu/sound/asc.h
@@ -0,0 +1,131 @@
+/***************************************************************************
+
+ asc.h
+
+ Apple Sound Chip (ASC) 344S0063
+ Enhanced Apple Sound Chip (EASC) 343S1063
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __ASC_H__
+#define __ASC_H__
+
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// chip behavior types
+enum
+{
+ ASC_TYPE_ASC = 0, // original discrete Apple Sound Chip
+ ASC_TYPE_EASC = 1, // discrete Enhanced Apple Sound Chip
+ ASC_TYPE_V8 = 2, // Subset of ASC included in the V8 ASIC (LC/LCII)
+ ASC_TYPE_EAGLE = 3, // Subset of ASC included in the Eagle ASIC (Classic II)
+ ASC_TYPE_SPICE = 4, // Subset of ASC included in the Spice ASIC (Color Classic)
+ ASC_TYPE_SONORA = 5, // Subset of ASC included in the Sonora ASIC (LCIII)
+ ASC_TYPE_VASP = 6, // Subset of ASC included in the VASP ASIC (IIvx/IIvi)
+ ASC_TYPE_ARDBEG = 7 // Subset of ASC included in the Ardbeg ASIC (LC520)
+};
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_ASC_ADD(_tag, _clock, _type, _irqf) \
+ MCFG_DEVICE_ADD(_tag, ASC, _clock) \
+ MCFG_ASC_TYPE(_type) \
+ MCFG_IRQ_FUNC(_irqf)
+
+#define MCFG_ASC_REPLACE(_tag, _clock, _type, _irqf) \
+ MCFG_DEVICE_REPLACE(_tag, ASC, _clock) \
+ MCFG_ASC_TYPE(_type) \
+ MCFG_IRQ_FUNC(_irqf)
+
+#define MCFG_ASC_TYPE(_type) \
+ asc_device::static_set_type(*device, _type); \
+
+#define MCFG_IRQ_FUNC(_irqf) \
+ asc_device::static_set_irqf(*device, _irqf); \
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> asc_device
+
+class asc_device : public device_t, public device_sound_interface
+{
+public:
+ // construction/destruction
+ asc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // inline configuration helpers
+ static void static_set_type(device_t &device, int type);
+ static void static_set_irqf(device_t &device, void (*irqf)(device_t *device, int state));
+
+ DECLARE_READ8_MEMBER(read);
+ DECLARE_WRITE8_MEMBER(write);
+
+ sound_stream *m_stream;
+
+protected:
+ enum
+ {
+ R_VERSION = 0x800,
+ R_MODE,
+ R_CONTROL,
+ R_FIFOMODE,
+ R_FIFOSTAT,
+ R_WTCONTROL,
+ R_VOLUME,
+ R_CLOCK,
+ R_REG8,
+ R_REG9,
+ R_PLAYRECA,
+ R_REGB,
+ R_REGC,
+ R_REGD,
+ R_REGE,
+ R_TEST
+ };
+
+ // 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);
+
+ virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
+
+ // inline data
+ UINT8 m_chip_type;
+ void (*m_irq_cb)(device_t *device, int state);
+
+ UINT8 m_fifo_a[0x400];
+ UINT8 m_fifo_b[0x400];
+
+ UINT8 m_regs[0x800];
+
+ UINT32 m_phase[4], m_incr[4];
+
+ int m_fifo_a_rdptr, m_fifo_b_rdptr;
+ int m_fifo_a_wrptr, m_fifo_b_wrptr;
+ int m_fifo_cap_a, m_fifo_cap_b;
+
+ emu_timer *m_timer;
+};
+
+
+// device type definition
+extern const device_type ASC;
+
+
+#endif /* __ASC_H__ */
+
diff --git a/trunk/src/emu/sound/astrocde.c b/trunk/src/emu/sound/astrocde.c
new file mode 100644
index 00000000000..3ae7112fb7a
--- /dev/null
+++ b/trunk/src/emu/sound/astrocde.c
@@ -0,0 +1,334 @@
+/***********************************************************
+
+ Astrocade custom 'IO' chip sound chip driver
+ Aaron Giles
+ based on original work by Frank Palazzolo
+
+************************************************************
+
+ Register Map
+ ============
+
+ Register 0:
+ D7..D0: Master oscillator frequency
+
+ Register 1:
+ D7..D0: Tone generator A frequency
+
+ Register 2:
+ D7..D0: Tone generator B frequency
+
+ Register 3:
+ D7..D0: Tone generator C frequency
+
+ Register 4:
+ D7..D6: Vibrato speed
+ D5..D0: Vibrato depth
+
+ Register 5:
+ D5: Noise AM enable
+ D4: Mux source (0=vibrato, 1=noise)
+ D3..D0: Tone generator C volume
+
+ Register 6:
+ D7..D4: Tone generator B volume
+ D3..D0: Tone generator A volume
+
+ Register 7:
+ D7..D0: Noise volume
+
+***********************************************************/
+
+#include "emu.h"
+#include "astrocde.h"
+
+
+typedef struct _astrocade_state astrocade_state;
+struct _astrocade_state
+{
+ sound_stream *stream; /* sound stream */
+
+ UINT8 reg[8]; /* 8 control registers */
+
+ UINT8 master_count; /* current master oscillator count */
+ UINT16 vibrato_clock; /* current vibrato clock */
+
+ UINT8 noise_clock; /* current noise generator clock */
+ UINT16 noise_state; /* current noise LFSR state */
+
+ UINT8 a_count; /* current tone generator A count */
+ UINT8 a_state; /* current tone generator A state */
+
+ UINT8 b_count; /* current tone generator B count */
+ UINT8 b_state; /* current tone generator B state */
+
+ UINT8 c_count; /* current tone generator C count */
+ UINT8 c_state; /* current tone generator C state */
+
+ UINT8 bitswap[256]; /* bitswap table */
+};
+
+
+INLINE astrocade_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == ASTROCADE);
+ return (astrocade_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+
+/*************************************
+ *
+ * Core sound update
+ *
+ *************************************/
+
+static STREAM_UPDATE( astrocade_update )
+{
+ astrocade_state *chip = (astrocade_state *)param;
+ stream_sample_t *dest = outputs[0];
+ UINT16 noise_state;
+ UINT8 master_count;
+ UINT8 noise_clock;
+
+ /* load some locals */
+ master_count = chip->master_count;
+ noise_clock = chip->noise_clock;
+ noise_state = chip->noise_state;
+
+ /* loop over samples */
+ while (samples > 0)
+ {
+ stream_sample_t cursample = 0;
+ int samples_this_time;
+ int samp;
+
+ /* compute the number of cycles until the next master oscillator reset */
+ /* or until the next noise boundary */
+ samples_this_time = MIN(samples, 256 - master_count);
+ samples_this_time = MIN(samples_this_time, 64 - noise_clock);
+ samples -= samples_this_time;
+
+ /* sum the output of the tone generators */
+ if (chip->a_state)
+ cursample += chip->reg[6] & 0x0f;
+ if (chip->b_state)
+ cursample += chip->reg[6] >> 4;
+ if (chip->c_state)
+ cursample += chip->reg[5] & 0x0f;
+
+ /* add in the noise if it is enabled, based on the top bit of the LFSR */
+ if ((chip->reg[5] & 0x20) && (noise_state & 0x4000))
+ cursample += chip->reg[7] >> 4;
+
+ /* scale to max and output */
+ cursample = cursample * 32767 / 60;
+ for (samp = 0; samp < samples_this_time; samp++)
+ *dest++ = cursample;
+
+ /* clock the noise; a 2-bit counter clocks a 4-bit counter which clocks the LFSR */
+ noise_clock += samples_this_time;
+ if (noise_clock >= 64)
+ {
+ /* update the noise state; this is a 15-bit LFSR with feedback from */
+ /* the XOR of the top two bits */
+ noise_state = (noise_state << 1) | (~((noise_state >> 14) ^ (noise_state >> 13)) & 1);
+ noise_clock -= 64;
+
+ /* the same clock also controls the vibrato clock, which is a 13-bit counter */
+ chip->vibrato_clock++;
+ }
+
+ /* clock the master oscillator; this is an 8-bit up counter */
+ master_count += samples_this_time;
+ if (master_count == 0)
+ {
+ /* reload based on mux value -- the value from the register is negative logic */
+ master_count = ~chip->reg[0];
+
+ /* mux value 0 means reload based on the vibrato control */
+ if ((chip->reg[5] & 0x10) == 0)
+ {
+ /* vibrato speed (register 4 bits 6-7) selects one of the top 4 bits */
+ /* of the 13-bit vibrato clock to use (0=highest freq, 3=lowest) */
+ if (!((chip->vibrato_clock >> (chip->reg[4] >> 6)) & 0x0200))
+ {
+ /* if the bit is clear, we add the vibrato volume to the counter */
+ master_count += chip->reg[4] & 0x3f;
+ }
+ }
+
+ /* mux value 1 means reload based on the noise control */
+ else
+ {
+ /* the top 8 bits of the noise LFSR are ANDed with the noise volume */
+ /* register and added to the count */
+ master_count += chip->bitswap[(noise_state >> 7) & 0xff] & chip->reg[7];
+ }
+
+ /* clock tone A */
+ if (++chip->a_count == 0)
+ {
+ chip->a_state ^= 1;
+ chip->a_count = ~chip->reg[1];
+ }
+
+ /* clock tone B */
+ if (++chip->b_count == 0)
+ {
+ chip->b_state ^= 1;
+ chip->b_count = ~chip->reg[2];
+ }
+
+ /* clock tone C */
+ if (++chip->c_count == 0)
+ {
+ chip->c_state ^= 1;
+ chip->c_count = ~chip->reg[3];
+ }
+ }
+ }
+
+ /* put back the locals */
+ chip->master_count = master_count;
+ chip->noise_clock = noise_clock;
+ chip->noise_state = noise_state;
+}
+
+
+
+/*************************************
+ *
+ * Chip reset
+ *
+ *************************************/
+
+static DEVICE_RESET( astrocade )
+{
+ astrocade_state *chip = get_safe_token(device);
+
+ memset(chip->reg, 0, sizeof(chip->reg));
+
+ chip->master_count = 0;
+ chip->vibrato_clock = 0;
+
+ chip->noise_clock = 0;
+ chip->noise_state = 0;
+
+ chip->a_count = 0;
+ chip->a_state = 0;
+
+ chip->b_count = 0;
+ chip->b_state = 0;
+
+ chip->c_count = 0;
+ chip->c_state = 0;
+}
+
+
+/*************************************
+ *
+ * Save state registration
+ *
+ *************************************/
+
+static void astrocade_state_save_register(astrocade_state *chip, device_t *device)
+{
+ device->save_item(NAME(chip->reg));
+
+ device->save_item(NAME(chip->master_count));
+ device->save_item(NAME(chip->vibrato_clock));
+
+ device->save_item(NAME(chip->noise_clock));
+ device->save_item(NAME(chip->noise_state));
+
+ device->save_item(NAME(chip->a_count));
+ device->save_item(NAME(chip->a_state));
+
+ device->save_item(NAME(chip->b_count));
+ device->save_item(NAME(chip->b_state));
+
+ device->save_item(NAME(chip->c_count));
+ device->save_item(NAME(chip->c_state));
+}
+
+
+
+/*************************************
+ *
+ * Chip initialization
+ *
+ *************************************/
+
+static DEVICE_START( astrocade )
+{
+ astrocade_state *chip = get_safe_token(device);
+ int i;
+
+ /* generate a bitswap table for the noise */
+ for (i = 0; i < 256; i++)
+ chip->bitswap[i] = BITSWAP8(i, 0,1,2,3,4,5,6,7);
+
+ /* allocate a stream for output */
+ chip->stream = device->machine().sound().stream_alloc(*device, 0, 1, device->clock(), chip, astrocade_update);
+
+ /* reset state */
+ DEVICE_RESET_CALL(astrocade);
+ astrocade_state_save_register(chip, device);
+}
+
+
+
+/*************************************
+ *
+ * Sound write accessors
+ *
+ *************************************/
+
+WRITE8_DEVICE_HANDLER( astrocade_sound_w )
+{
+ astrocade_state *chip = get_safe_token(device);
+
+ if ((offset & 8) != 0)
+ offset = (offset >> 8) & 7;
+ else
+ offset &= 7;
+
+ /* update */
+ chip->stream->update();
+
+ /* stash the new register value */
+ chip->reg[offset & 7] = data;
+}
+
+
+
+/*************************************
+ *
+ * Get/set info callbacks
+ *
+ *************************************/
+
+DEVICE_GET_INFO( astrocade )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(astrocade_state); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( astrocade ); break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME( astrocade ); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Astrocade"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Bally"); 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 Nicola Salmoria and the MAME Team"); break;
+ }
+}
+
+
+DEFINE_LEGACY_SOUND_DEVICE(ASTROCADE, astrocade);
diff --git a/trunk/src/emu/sound/astrocde.h b/trunk/src/emu/sound/astrocde.h
new file mode 100644
index 00000000000..afcf03d18e1
--- /dev/null
+++ b/trunk/src/emu/sound/astrocde.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#ifndef __ASTROCDE_H__
+#define __ASTROCDE_H__
+
+#include "devlegcy.h"
+
+WRITE8_DEVICE_HANDLER( astrocade_sound_w );
+
+DECLARE_LEGACY_SOUND_DEVICE(ASTROCADE, astrocade);
+
+#endif /* __ASTROCDE_H__ */
diff --git a/trunk/src/emu/sound/awacs.c b/trunk/src/emu/sound/awacs.c
new file mode 100644
index 00000000000..fda9f1ae8b6
--- /dev/null
+++ b/trunk/src/emu/sound/awacs.c
@@ -0,0 +1,175 @@
+/***************************************************************************
+
+ awacs.c
+
+ AWACS/Singer style 16-bit audio I/O for '040 and PowerPC Macs
+
+ Emulation by R. Belmont
+
+***************************************************************************/
+
+#include "emu.h"
+#include "awacs.h"
+
+// device type definition
+const device_type AWACS = &device_creator<awacs_device>;
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// awacs_device - constructor
+//-------------------------------------------------
+
+awacs_device::awacs_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, AWACS, "AWACS", tag, owner, clock),
+ device_sound_interface(mconfig, *this)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void awacs_device::device_start()
+{
+ // create the stream
+ m_stream = machine().sound().stream_alloc(*this, 0, 2, 22050, this);
+
+ memset(m_regs, 0, sizeof(m_regs));
+
+ m_timer = timer_alloc(0, NULL);
+
+ save_item(NAME(m_play_ptr));
+ save_item(NAME(m_buffer_size));
+ save_item(NAME(m_playback_enable));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void awacs_device::device_reset()
+{
+ m_stream->update();
+
+ memset(m_regs, 0, sizeof(m_regs));
+
+ m_play_ptr = 0;
+ m_buffer_size = 0;
+ m_playback_enable = false;
+ m_dma_space = NULL;
+ m_dma_offset_0 = m_dma_offset_1 = 0;
+ m_buffer_num = 0;
+}
+
+//-------------------------------------------------
+// device_timer - called when our device timer expires
+//-------------------------------------------------
+
+void awacs_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
+{
+ m_stream->update();
+}
+
+//-------------------------------------------------
+// sound_stream_update - handle update requests for
+// our sound stream
+//-------------------------------------------------
+
+void awacs_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+{
+ stream_sample_t *outL, *outR;
+ int offset = (m_buffer_num == 0) ? m_dma_offset_0 : m_dma_offset_1;
+
+ outL = outputs[0];
+ outR = outputs[1];
+
+ if (m_playback_enable)
+ {
+ for (int i = 0; i < samples; i++)
+ {
+ outL[i] = (INT16)m_dma_space->read_word(offset + m_play_ptr);
+ outR[i] = (INT16)m_dma_space->read_word(offset + m_play_ptr + 2);
+ m_play_ptr += 4;
+ }
+
+ // out of buffer?
+ if (m_play_ptr >= m_buffer_size)
+ {
+ UINT8 bufflag[2] = { 0x40, 0x80 };
+
+ m_regs[0x18] |= bufflag[m_buffer_num];
+ m_buffer_num ^= 1;
+ m_play_ptr = 0;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < samples; i++)
+ {
+ outL[i] = 0;
+ outR[i] = 0;
+ }
+ }
+}
+
+//-------------------------------------------------
+// read - read from the chip's registers and internal RAM
+//-------------------------------------------------
+
+READ8_MEMBER( awacs_device::read )
+{
+ return m_regs[offset];
+}
+
+//-------------------------------------------------
+// write - write to the chip's registers and internal RAM
+//-------------------------------------------------
+
+WRITE8_MEMBER( awacs_device::write )
+{
+ switch (offset)
+ {
+ case 0x8:
+ case 0x9:
+ m_regs[offset] = data;
+ m_buffer_size = (m_regs[8]<<6) | (m_regs[9]>>2);
+// printf("buffer size = %x samples, %x bytes\n", m_buffer_size, m_buffer_size*4);
+ m_buffer_size *= 4; // samples * 16 bits * stereo
+ break;
+
+ case 0x10:
+ {
+ static const int rates[4] = { 22100, 29400, 44100, 22100 };
+ m_stream->set_sample_rate(rates[(data>>1)&3]);
+// printf("rate %d, enable: %d\n", rates[(data>>1)&3], data & 1);
+ m_playback_enable = (data & 1) ? true : false;
+
+ if (m_playback_enable && !(m_regs[0x10]&1))
+ {
+ m_play_ptr = 0;
+ m_buffer_num = 0;
+ }
+ }
+ break;
+
+ case 0x18:
+ m_regs[offset] &= 0xf0;
+ m_regs[offset] |= (data & 0x0f);
+ m_regs[offset] &= ~(data & 0xf0);
+ return;
+ }
+
+ m_regs[offset] = data;
+}
+
+void awacs_device::set_dma_base(address_space *space, int offset0, int offset1)
+{
+ m_dma_space = space;
+ m_dma_offset_0 = offset0;
+ m_dma_offset_1 = offset1;
+}
+
diff --git a/trunk/src/emu/sound/awacs.h b/trunk/src/emu/sound/awacs.h
new file mode 100644
index 00000000000..de6e521ef70
--- /dev/null
+++ b/trunk/src/emu/sound/awacs.h
@@ -0,0 +1,76 @@
+/***************************************************************************
+
+ awacs.h
+
+ AWACS/Singer style 16-bit audio I/O for '040 and PowerPC Macs
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __AWACS_H__
+#define __AWACS_H__
+
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_AWACS_ADD(_tag, _clock) \
+ MCFG_DEVICE_ADD(_tag, AWACS, _clock)
+
+#define MCFG_AWACS_REPLACE(_tag, _clock) \
+ MCFG_DEVICE_REPLACE(_tag, AWACS, _clock)
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> awacs_device
+
+class awacs_device : public device_t, public device_sound_interface
+{
+public:
+ // construction/destruction
+ awacs_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_READ8_MEMBER(read);
+ DECLARE_WRITE8_MEMBER(write);
+
+ void set_dma_base(address_space *space, int offset0, int offset1);
+
+ sound_stream *m_stream;
+
+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);
+
+ virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
+
+ // inline data
+ UINT8 m_regs[0x100];
+
+ int m_play_ptr, m_buffer_size, m_buffer_num;
+ bool m_playback_enable;
+
+ address_space *m_dma_space;
+ int m_dma_offset_0, m_dma_offset_1;
+
+ emu_timer *m_timer;
+};
+
+
+// device type definition
+extern const device_type AWACS;
+
+
+#endif /* __AWACS_H__ */
+
diff --git a/trunk/src/emu/sound/ay8910.c b/trunk/src/emu/sound/ay8910.c
new file mode 100644
index 00000000000..8e285771b3c
--- /dev/null
+++ b/trunk/src/emu/sound/ay8910.c
@@ -0,0 +1,1097 @@
+/***************************************************************************
+
+ ay8910.c
+
+ Emulation of the AY-3-8910 / YM2149 sound chip.
+
+ Based on various code snippets by Ville Hallik, Michael Cuddy,
+ Tatsuyuki Satoh, Fabrice Frances, Nicola Salmoria.
+
+ Mostly rewritten by couriersud in 2008
+
+ Games using ADSR: gyruss
+
+ A list with more games using ADSR can be found here:
+ http://mametesters.org/view.php?id=3043
+
+ TODO:
+ * The AY8930 has an extended mode which is currently
+ not emulated.
+ * The YMZ284 only has one 1 output channel (mixed chan A,B,C).
+ This should be forced.
+ * YM2610 & YM2608 will need a separate flag in their config structures
+ to distinguish between legacy and discrete mode.
+
+ The rewrite also introduces a generic model for the DAC. This model is
+ not perfect, but allows channel mixing based on a parametrized approach.
+ This model also allows to factor in different loads on individual channels.
+ If a better model is developped in the future or better measurements are
+ available, the driver should be easy to change. The model is described
+ later.
+
+ In order to not break hundreds of existing drivers by default the flag
+ AY8910_LEGACY_OUTPUT is used by drivers not changed to take into account the
+ new model. All outputs are normalized to the old output range (i.e. 0 .. 7ffff).
+ In the case of channel mixing, output range is 0...3 * 7fff.
+
+ The main difference between the AY-3-8910 and the YM2149 is, that the
+ AY-3-8910 datasheet mentions, that fixed volume level 0, which is set by
+ registers 8 to 10 is "channel off". The YM2149 mentions, that the generated
+ signal has a 2V DC component. This is confirmed by measurements. The approach
+ taken here is to assume the 2V DC offset for all outputs for the YM2149.
+ For the AY-3-8910, an offset is used if envelope is active for a channel.
+ This is backed by oscilloscope pictures from the datasheet. If a fixed volume
+ is set, i.e. enveloppe is disabled, the output voltage is set to 0V. Recordings
+ I found on the web for gyruss indicate, that the AY-3-8910 offset should
+ be around 0.2V. This will also make sound levels more compatible with
+ user observations for scramble.
+
+ The Model:
+ 5V 5V
+ | |
+ / |
+ Volume Level x >---| Z
+ > Z Pullup Resistor RU
+ | Z
+ Z |
+ Rx Z |
+ Z |
+ | |
+ '-----+--------> >---+----> Output signal
+ | |
+ Z Z
+ Pulldown RD Z Z Load RL
+ Z Z
+ | |
+ GND GND
+
+Each Volume level x will select a different resistor Rx. Measurements from fpgaarcade.com
+where used to calibrate channel mixing for the YM2149. This was done using
+a least square approach using a fixed RL of 1K Ohm.
+
+For the AY measurements cited in e.g. openmsx as "Hacker Kay" for a single
+channel were taken. These were normalized to 0 ... 65535 and consequently
+adapted to an offset of 0.2V and a VPP of 1.3V. These measurements are in
+line e.g. with the formula used by pcmenc for the volume: vol(i) = exp(i/2-7.5).
+
+The following is documentation from the code moved here and amended to reflect
+the changes done:
+
+Careful studies of the chip output prove that the chip counts up from 0
+until the counter becomes greater or equal to the period. This is an
+important difference when the program is rapidly changing the period to
+modulate the sound. This is worthwhile noting, since the datasheets
+say, that the chip counts down.
+Also, note that period = 0 is the same as period = 1. This is mentioned
+in the YM2203 data sheets. However, this does NOT apply to the Envelope
+period. In that case, period = 0 is half as period = 1.
+
+Envelope shapes:
+ C AtAlH
+ 0 0 x x \___
+ 0 1 x x /___
+ 1 0 0 0 \\\\
+ 1 0 0 1 \___
+ 1 0 1 0 \/\/
+ 1 0 1 1 \```
+ 1 1 0 0 ////
+ 1 1 0 1 /```
+ 1 1 1 0 /\/\
+ 1 1 1 1 /___
+
+The envelope counter on the AY-3-8910 has 16 steps. On the YM2149 it
+has twice the steps, happening twice as fast.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "ay8910.h"
+
+/*************************************
+ *
+ * Defines
+ *
+ *************************************/
+
+#define ENABLE_REGISTER_TEST (0) /* Enable preprogrammed registers */
+
+#define MAX_OUTPUT 0x7fff
+#define NUM_CHANNELS 3
+
+/* register id's */
+#define AY_AFINE (0)
+#define AY_ACOARSE (1)
+#define AY_BFINE (2)
+#define AY_BCOARSE (3)
+#define AY_CFINE (4)
+#define AY_CCOARSE (5)
+#define AY_NOISEPER (6)
+#define AY_ENABLE (7)
+#define AY_AVOL (8)
+#define AY_BVOL (9)
+#define AY_CVOL (10)
+#define AY_EFINE (11)
+#define AY_ECOARSE (12)
+#define AY_ESHAPE (13)
+
+#define AY_PORTA (14)
+#define AY_PORTB (15)
+
+#define NOISE_ENABLEQ(_psg, _chan) (((_psg)->regs[AY_ENABLE] >> (3 + _chan)) & 1)
+#define TONE_ENABLEQ(_psg, _chan) (((_psg)->regs[AY_ENABLE] >> (_chan)) & 1)
+#define TONE_PERIOD(_psg, _chan) ( (_psg)->regs[(_chan) << 1] | (((_psg)->regs[((_chan) << 1) | 1] & 0x0f) << 8) )
+#define NOISE_PERIOD(_psg) ( (_psg)->regs[AY_NOISEPER] & 0x1f)
+#define TONE_VOLUME(_psg, _chan) ( (_psg)->regs[AY_AVOL + (_chan)] & 0x0f)
+#define TONE_ENVELOPE(_psg, _chan) (((_psg)->regs[AY_AVOL + (_chan)] >> 4) & 1)
+#define ENVELOPE_PERIOD(_psg) (((_psg)->regs[AY_EFINE] | ((_psg)->regs[AY_ECOARSE]<<8)))
+
+/*************************************
+ *
+ * Type definitions
+ *
+ *************************************/
+
+typedef struct _ay_ym_param ay_ym_param;
+struct _ay_ym_param
+{
+ double r_up;
+ double r_down;
+ int res_count;
+ double res[32];
+};
+
+typedef struct _ay8910_context ay8910_context;
+struct _ay8910_context
+{
+ device_t *device;
+ int streams;
+ int ready;
+ sound_stream *channel;
+ const ay8910_interface *intf;
+ INT32 register_latch;
+ UINT8 regs[16];
+ INT32 last_enable;
+ INT32 count[NUM_CHANNELS];
+ UINT8 output[NUM_CHANNELS];
+ UINT8 output_noise;
+ INT32 count_noise;
+ INT32 count_env;
+ INT8 env_step;
+ UINT32 env_volume;
+ UINT8 hold,alternate,attack,holding;
+ INT32 rng;
+ UINT8 env_step_mask;
+ /* init parameters ... */
+ int step;
+ int zero_is_off;
+ UINT8 vol_enabled[NUM_CHANNELS];
+ const ay_ym_param *par;
+ const ay_ym_param *par_env;
+ INT32 vol_table[NUM_CHANNELS][16];
+ INT32 env_table[NUM_CHANNELS][32];
+ INT32 vol3d_table[8*32*32*32];
+ devcb_resolved_read8 portAread;
+ devcb_resolved_read8 portBread;
+ devcb_resolved_write8 portAwrite;
+ devcb_resolved_write8 portBwrite;
+};
+
+INLINE ay8910_context *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == AY8910 ||
+ device->type() == AY8912 ||
+ device->type() == AY8913 ||
+ device->type() == AY8930 ||
+ device->type() == YM2149 ||
+ device->type() == YM3439 ||
+ device->type() == YMZ284 ||
+ device->type() == YMZ294);
+ return (ay8910_context *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+/*************************************
+ *
+ * Static
+ *
+ *************************************/
+
+static const ay_ym_param ym2149_param =
+{
+ 630, 801,
+ 16,
+ { 73770, 37586, 27458, 21451, 15864, 12371, 8922, 6796,
+ 4763, 3521, 2403, 1737, 1123, 762, 438, 251 },
+};
+
+static const ay_ym_param ym2149_param_env =
+{
+ 630, 801,
+ 32,
+ { 103350, 73770, 52657, 37586, 32125, 27458, 24269, 21451,
+ 18447, 15864, 14009, 12371, 10506, 8922, 7787, 6796,
+ 5689, 4763, 4095, 3521, 2909, 2403, 2043, 1737,
+ 1397, 1123, 925, 762, 578, 438, 332, 251 },
+};
+
+#if 0
+/* RL = 1000, Hacker Kay normalized, 2.1V to 3.2V */
+static const ay_ym_param ay8910_param =
+{
+ 664, 913,
+ 16,
+ { 85785, 34227, 26986, 20398, 14886, 10588, 7810, 4856,
+ 4120, 2512, 1737, 1335, 1005, 747, 586, 451 },
+};
+
+/*
+ * RL = 3000, Hacker Kay normalized pattern, 1.5V to 2.8V
+ * These values correspond with guesses based on Gyruss schematics
+ * They work well with scramble as well.
+ */
+static const ay_ym_param ay8910_param =
+{
+ 930, 454,
+ 16,
+ { 85066, 34179, 27027, 20603, 15046, 10724, 7922, 4935,
+ 4189, 2557, 1772, 1363, 1028, 766, 602, 464 },
+};
+
+/*
+ * RL = 1000, Hacker Kay normalized pattern, 0.75V to 2.05V
+ * These values correspond with guesses based on Gyruss schematics
+ * They work well with scramble as well.
+ */
+static const ay_ym_param ay8910_param =
+{
+ 1371, 313,
+ 16,
+ { 93399, 33289, 25808, 19285, 13940, 9846, 7237, 4493,
+ 3814, 2337, 1629, 1263, 962, 727, 580, 458 },
+};
+
+/*
+ * RL = 1000, Hacker Kay normalized pattern, 0.2V to 1.5V
+ */
+static const ay_ym_param ay8910_param =
+{
+ 5806, 300,
+ 16,
+ { 118996, 42698, 33105, 24770, 17925, 12678, 9331, 5807,
+ 4936, 3038, 2129, 1658, 1271, 969, 781, 623 }
+};
+#endif
+
+/*
+ * RL = 2000, Based on Matthew Westcott's measurements from Dec 2001.
+ * -------------------------------------------------------------------
+ *
+ * http://groups.google.com/group/comp.sys.sinclair/browse_thread/thread/fb3091da4c4caf26/d5959a800cda0b5e?lnk=gst&q=Matthew+Westcott#d5959a800cda0b5e
+ * After what Russell mentioned a couple of weeks back about the lack of
+ * publicised measurements of AY chip volumes - I've finally got round to
+ * making these readings, and I'm placing them in the public domain - so
+ * anyone's welcome to use them in emulators or anything else.
+
+ * To make the readings, I set up the chip to produce a constant voltage on
+ * channel C (setting bits 2 and 5 of register 6), and varied the amplitude
+ * (the low 4 bits of register 10). The voltages were measured between the
+ * channel C output (pin 1) and ground (pin 6).
+ *
+ * Level Voltage
+ * 0 1.147
+ * 1 1.162
+ * 2 1.169
+ * 3 1.178
+ * 4 1.192
+ * 5 1.213
+ * 6 1.238
+ * 7 1.299
+ * 8 1.336
+ * 9 1.457
+ * 10 1.573
+ * 11 1.707
+ * 12 1.882
+ * 13 2.06
+ * 14 2.32
+ * 15 2.58
+ * -------------------------------------------------------------------
+ *
+ * The ZX spectrum output circuit was modelled in SwitcherCAD and
+ * the resistor values below create the voltage levels above.
+ * RD was measured on a real chip to be 8m Ohm, RU was 0.8m Ohm.
+ */
+
+static const ay_ym_param ay8910_param =
+{
+ 800000, 8000000,
+ 16,
+ { 15950, 15350, 15090, 14760, 14275, 13620, 12890, 11370,
+ 10600, 8590, 7190, 5985, 4820, 3945, 3017, 2345 }
+};
+
+/*************************************
+ *
+ * Inline
+ *
+ *************************************/
+
+INLINE void build_3D_table(double rl, const ay_ym_param *par, const ay_ym_param *par_env, int normalize, double factor, int zero_is_off, INT32 *tab)
+{
+ int j, j1, j2, j3, e, indx;
+ double rt, rw, n;
+ double min = 10.0, max = 0.0;
+ double *temp;
+
+ temp = global_alloc_array(double, 8*32*32*32);
+
+ for (e=0; e < 8; e++)
+ for (j1=0; j1 < 32; j1++)
+ for (j2=0; j2 < 32; j2++)
+ for (j3=0; j3 < 32; j3++)
+ {
+ if (zero_is_off)
+ {
+ n = (j1 != 0 || (e & 0x01)) ? 1 : 0;
+ n += (j2 != 0 || (e & 0x02)) ? 1 : 0;
+ n += (j3 != 0 || (e & 0x04)) ? 1 : 0;
+ }
+ else
+ n = 3.0;
+
+ rt = n / par->r_up + 3.0 / par->r_down + 1.0 / rl;
+ rw = n / par->r_up;
+
+ rw += 1.0 / ( (e & 0x01) ? par_env->res[j1] : par->res[j1]);
+ rt += 1.0 / ( (e & 0x01) ? par_env->res[j1] : par->res[j1]);
+ rw += 1.0 / ( (e & 0x02) ? par_env->res[j2] : par->res[j2]);
+ rt += 1.0 / ( (e & 0x02) ? par_env->res[j2] : par->res[j2]);
+ rw += 1.0 / ( (e & 0x04) ? par_env->res[j3] : par->res[j3]);
+ rt += 1.0 / ( (e & 0x04) ? par_env->res[j3] : par->res[j3]);
+
+ indx = (e << 15) | (j3<<10) | (j2<<5) | j1;
+ temp[indx] = rw / rt;
+ if (temp[indx] < min)
+ min = temp[indx];
+ if (temp[indx] > max)
+ max = temp[indx];
+ }
+
+ if (normalize)
+ {
+ for (j=0; j < 32*32*32*8; j++)
+ tab[j] = MAX_OUTPUT * (((temp[j] - min)/(max-min))) * factor;
+ }
+ else
+ {
+ for (j=0; j < 32*32*32*8; j++)
+ tab[j] = MAX_OUTPUT * temp[j];
+ }
+
+ /* for (e=0;e<16;e++) printf("%d %d\n",e<<10, tab[e<<10]); */
+
+ global_free(temp);
+}
+
+INLINE void build_single_table(double rl, const ay_ym_param *par, int normalize, INT32 *tab, int zero_is_off)
+{
+ int j;
+ double rt, rw = 0;
+ double temp[32], min=10.0, max=0.0;
+
+ for (j=0; j < par->res_count; j++)
+ {
+ rt = 1.0 / par->r_down + 1.0 / rl;
+
+ rw = 1.0 / par->res[j];
+ rt += 1.0 / par->res[j];
+
+ if (!(zero_is_off && j == 0))
+ {
+ rw += 1.0 / par->r_up;
+ rt += 1.0 / par->r_up;
+ }
+
+ temp[j] = rw / rt;
+ if (temp[j] < min)
+ min = temp[j];
+ if (temp[j] > max)
+ max = temp[j];
+ }
+ if (normalize)
+ {
+ for (j=0; j < par->res_count; j++)
+ tab[j] = MAX_OUTPUT * (((temp[j] - min)/(max-min)) - 0.25) * 0.5;
+ }
+ else
+ {
+ for (j=0; j < par->res_count; j++)
+ tab[j] = MAX_OUTPUT * temp[j];
+ }
+
+}
+
+INLINE UINT16 mix_3D(ay8910_context *psg)
+{
+ int indx = 0, chan;
+
+ for (chan = 0; chan < NUM_CHANNELS; chan++)
+ if (TONE_ENVELOPE(psg, chan))
+ {
+ indx |= (1 << (chan+15)) | ( psg->vol_enabled[chan] ? psg->env_volume << (chan*5) : 0);
+ }
+ else
+ {
+ indx |= (psg->vol_enabled[chan] ? TONE_VOLUME(psg, chan) << (chan*5) : 0);
+ }
+ return psg->vol3d_table[indx];
+}
+
+/*************************************
+ *
+ * Static functions
+ *
+ *************************************/
+
+static void ay8910_write_reg(ay8910_context *psg, int r, int v)
+{
+ //if (r >= 11 && r <= 13 ) printf("%d %x %02x\n", PSG->index, r, v);
+ psg->regs[r] = v;
+
+ switch( r )
+ {
+ case AY_AFINE:
+ case AY_ACOARSE:
+ case AY_BFINE:
+ case AY_BCOARSE:
+ case AY_CFINE:
+ case AY_CCOARSE:
+ case AY_NOISEPER:
+ case AY_AVOL:
+ case AY_BVOL:
+ case AY_CVOL:
+ case AY_EFINE:
+ /* No action required */
+ break;
+ case AY_ECOARSE:
+ #ifdef MAME_DEBUG
+ if ( (v & 0x0f) > 0)
+ popmessage("ECoarse");
+ #endif
+ /* No action required */
+ break;
+ case AY_ENABLE:
+ if ((psg->last_enable == -1) ||
+ ((psg->last_enable & 0x40) != (psg->regs[AY_ENABLE] & 0x40)))
+ {
+ /* write out 0xff if port set to input */
+ psg->portAwrite(0, (psg->regs[AY_ENABLE] & 0x40) ? psg->regs[AY_PORTA] : 0xff);
+ }
+
+ if ((psg->last_enable == -1) ||
+ ((psg->last_enable & 0x80) != (psg->regs[AY_ENABLE] & 0x80)))
+ {
+ /* write out 0xff if port set to input */
+ psg->portBwrite(0, (psg->regs[AY_ENABLE] & 0x80) ? psg->regs[AY_PORTB] : 0xff);
+ }
+
+ psg->last_enable = psg->regs[AY_ENABLE];
+ break;
+ case AY_ESHAPE:
+ #ifdef MAME_DEBUG
+ if ( (v & 0x0f) > 0)
+ popmessage("EShape");
+ #endif
+ psg->attack = (psg->regs[AY_ESHAPE] & 0x04) ? psg->env_step_mask : 0x00;
+ if ((psg->regs[AY_ESHAPE] & 0x08) == 0)
+ {
+ /* if Continue = 0, map the shape to the equivalent one which has Continue = 1 */
+ psg->hold = 1;
+ psg->alternate = psg->attack;
+ }
+ else
+ {
+ psg->hold = psg->regs[AY_ESHAPE] & 0x01;
+ psg->alternate = psg->regs[AY_ESHAPE] & 0x02;
+ }
+ psg->env_step = psg->env_step_mask;
+ psg->holding = 0;
+ psg->env_volume = (psg->env_step ^ psg->attack);
+ break;
+ case AY_PORTA:
+ if (psg->regs[AY_ENABLE] & 0x40)
+ {
+ if (!psg->portAwrite.isnull())
+ psg->portAwrite(0, psg->regs[AY_PORTA]);
+ else
+ logerror("warning - write %02x to 8910 '%s' Port A\n",psg->regs[AY_PORTA],psg->device->tag());
+ }
+ else
+ {
+ logerror("warning: write to 8910 '%s' Port A set as input - ignored\n",psg->device->tag());
+ }
+ break;
+ case AY_PORTB:
+ if (psg->regs[AY_ENABLE] & 0x80)
+ {
+ if (!psg->portBwrite.isnull())
+ psg->portBwrite(0, psg->regs[AY_PORTB]);
+ else
+ logerror("warning - write %02x to 8910 '%s' Port B\n",psg->regs[AY_PORTB],psg->device->tag());
+ }
+ else
+ {
+ logerror("warning: write to 8910 '%s' Port B set as input - ignored\n",psg->device->tag());
+ }
+ break;
+ }
+}
+
+static STREAM_UPDATE( ay8910_update )
+{
+ ay8910_context *psg = (ay8910_context *)param;
+ stream_sample_t *buf[NUM_CHANNELS];
+ int chan;
+
+ buf[0] = outputs[0];
+ buf[1] = NULL;
+ buf[2] = NULL;
+ if (psg->streams == NUM_CHANNELS)
+ {
+ buf[1] = outputs[1];
+ buf[2] = outputs[2];
+ }
+
+ /* hack to prevent us from hanging when starting filtered outputs */
+ if (!psg->ready)
+ {
+ for (chan = 0; chan < NUM_CHANNELS; chan++)
+ if (buf[chan] != NULL)
+ memset(buf[chan], 0, samples * sizeof(*buf[chan]));
+ }
+
+ /* The 8910 has three outputs, each output is the mix of one of the three */
+ /* tone generators and of the (single) noise generator. The two are mixed */
+ /* BEFORE going into the DAC. The formula to mix each channel is: */
+ /* (ToneOn | ToneDisable) & (NoiseOn | NoiseDisable). */
+ /* Note that this means that if both tone and noise are disabled, the output */
+ /* is 1, not 0, and can be modulated changing the volume. */
+
+ /* buffering loop */
+ while (samples)
+ {
+ for (chan = 0; chan < NUM_CHANNELS; chan++)
+ {
+ psg->count[chan]++;
+ if (psg->count[chan] >= TONE_PERIOD(psg, chan))
+ {
+ psg->output[chan] ^= 1;
+ psg->count[chan] = 0;;
+ }
+ }
+
+ psg->count_noise++;
+ if (psg->count_noise >= NOISE_PERIOD(psg))
+ {
+ /* Is noise output going to change? */
+ if ((psg->rng + 1) & 2) /* (bit0^bit1)? */
+ {
+ psg->output_noise ^= 1;
+ }
+
+ /* The Random Number Generator of the 8910 is a 17-bit shift */
+ /* register. The input to the shift register is bit0 XOR bit3 */
+ /* (bit0 is the output). This was verified on AY-3-8910 and YM2149 chips. */
+
+ /* The following is a fast way to compute bit17 = bit0^bit3. */
+ /* Instead of doing all the logic operations, we only check */
+ /* bit0, relying on the fact that after three shifts of the */
+ /* register, what now is bit3 will become bit0, and will */
+ /* invert, if necessary, bit14, which previously was bit17. */
+ if (psg->rng & 1)
+ psg->rng ^= 0x24000; /* This version is called the "Galois configuration". */
+ psg->rng >>= 1;
+ psg->count_noise = 0;
+ }
+
+ for (chan = 0; chan < NUM_CHANNELS; chan++)
+ {
+ psg->vol_enabled[chan] = (psg->output[chan] | TONE_ENABLEQ(psg, chan)) & (psg->output_noise | NOISE_ENABLEQ(psg, chan));
+ }
+
+ /* update envelope */
+ if (psg->holding == 0)
+ {
+ psg->count_env++;
+ if (psg->count_env >= ENVELOPE_PERIOD(psg) * psg->step )
+ {
+ psg->count_env = 0;
+ psg->env_step--;
+
+ /* check envelope current position */
+ if (psg->env_step < 0)
+ {
+ if (psg->hold)
+ {
+ if (psg->alternate)
+ psg->attack ^= psg->env_step_mask;
+ psg->holding = 1;
+ psg->env_step = 0;
+ }
+ else
+ {
+ /* if CountEnv has looped an odd number of times (usually 1), */
+ /* invert the output. */
+ if (psg->alternate && (psg->env_step & (psg->env_step_mask + 1)))
+ psg->attack ^= psg->env_step_mask;
+
+ psg->env_step &= psg->env_step_mask;
+ }
+ }
+
+ }
+ }
+ psg->env_volume = (psg->env_step ^ psg->attack);
+
+ if (psg->streams == 3)
+ {
+ for (chan = 0; chan < NUM_CHANNELS; chan++)
+ if (TONE_ENVELOPE(psg,chan))
+ {
+ /* Envolope has no "off" state */
+ *(buf[chan]++) = psg->env_table[chan][psg->vol_enabled[chan] ? psg->env_volume : 0];
+ }
+ else
+ {
+ *(buf[chan]++) = psg->vol_table[chan][psg->vol_enabled[chan] ? TONE_VOLUME(psg, chan) : 0];
+ }
+ }
+ else
+ {
+ *(buf[0]++) = mix_3D(psg);
+#if 0
+ *(buf[0]) = ( vol_enabled[0] * psg->vol_table[psg->Vol[0]]
+ + vol_enabled[1] * psg->vol_table[psg->Vol[1]]
+ + vol_enabled[2] * psg->vol_table[psg->Vol[2]]) / psg->step;
+#endif
+ }
+ samples--;
+ }
+}
+
+static void build_mixer_table(ay8910_context *psg)
+{
+ int normalize = 0;
+ int chan;
+
+ if ((psg->intf->flags & AY8910_LEGACY_OUTPUT) != 0)
+ {
+ logerror("AY-3-8910/YM2149 using legacy output levels!\n");
+ normalize = 1;
+ }
+
+ for (chan=0; chan < NUM_CHANNELS; chan++)
+ {
+ build_single_table(psg->intf->res_load[chan], psg->par, normalize, psg->vol_table[chan], psg->zero_is_off);
+ build_single_table(psg->intf->res_load[chan], psg->par_env, normalize, psg->env_table[chan], 0);
+ }
+ /*
+ * The previous implementation added all three channels up instead of averaging them.
+ * The factor of 3 will force the same levels if normalizing is used.
+ */
+ build_3D_table(psg->intf->res_load[0], psg->par, psg->par_env, normalize, 3, psg->zero_is_off, psg->vol3d_table);
+}
+
+static void ay8910_statesave(ay8910_context *psg, device_t *device)
+{
+ device->save_item(NAME(psg->register_latch));
+ device->save_item(NAME(psg->regs));
+ device->save_item(NAME(psg->last_enable));
+
+ device->save_item(NAME(psg->count));
+ device->save_item(NAME(psg->count_noise));
+ device->save_item(NAME(psg->count_env));
+
+ device->save_item(NAME(psg->env_volume));
+
+ device->save_item(NAME(psg->output));
+ device->save_item(NAME(psg->output_noise));
+
+ device->save_item(NAME(psg->env_step));
+ device->save_item(NAME(psg->hold));
+ device->save_item(NAME(psg->alternate));
+ device->save_item(NAME(psg->attack));
+ device->save_item(NAME(psg->holding));
+ device->save_item(NAME(psg->rng));
+}
+
+/*************************************
+ *
+ * Public functions
+ *
+ * used by e.g. YM2203, YM2210 ...
+ *
+ *************************************/
+
+void *ay8910_start_ym(void *infoptr, device_type chip_type, device_t *device, int clock, const ay8910_interface *intf)
+{
+ ay8910_context *info = (ay8910_context *)infoptr;
+
+ if (info == NULL)
+ info = auto_alloc_clear(device->machine(), ay8910_context);
+
+ info->device = device;
+ info->intf = intf;
+ info->portAread.resolve(intf->portAread, *device);
+ info->portBread.resolve(intf->portBread, *device);
+ info->portAwrite.resolve(intf->portAwrite, *device);
+ info->portBwrite.resolve(intf->portBwrite, *device);
+ if ((info->intf->flags & AY8910_SINGLE_OUTPUT) != 0)
+ {
+ logerror("AY-3-8910/YM2149 using single output!\n");
+ info->streams = 1;
+ }
+ else
+ info->streams = 3;
+
+ if (chip_type == AY8910 || chip_type == AY8930)
+ {
+ info->step = 2;
+ info->par = &ay8910_param;
+ info->par_env = &ay8910_param;
+ info->zero_is_off = 0; /* FIXME: Remove after verification that off=vol(0) */
+ info->env_step_mask = 0x0F;
+ }
+ else
+ {
+ info->step = 1;
+ info->par = &ym2149_param;
+ info->par_env = &ym2149_param_env;
+ info->zero_is_off = 0;
+ info->env_step_mask = 0x1F;
+ }
+
+ build_mixer_table(info);
+
+ /* The envelope is pacing twice as fast for the YM2149 as for the AY-3-8910, */
+ /* This handled by the step parameter. Consequently we use a divider of 8 here. */
+ info->channel = device->machine().sound().stream_alloc(*device, 0, info->streams, device->clock() / 8, info, ay8910_update);
+
+ ay8910_set_clock_ym(info,device->clock());
+ ay8910_statesave(info, device);
+
+ return info;
+}
+
+void ay8910_stop_ym(void *chip)
+{
+}
+
+void ay8910_reset_ym(void *chip)
+{
+ ay8910_context *psg = (ay8910_context *)chip;
+ int i;
+
+ psg->register_latch = 0;
+ psg->rng = 1;
+ psg->output[0] = 0;
+ psg->output[1] = 0;
+ psg->output[2] = 0;
+ psg->count[0] = 0;
+ psg->count[1] = 0;
+ psg->count[2] = 0;
+ psg->count_noise = 0;
+ psg->count_env = 0;
+ psg->output_noise = 0x01;
+ psg->last_enable = -1; /* force a write */
+ for (i = 0;i < AY_PORTA;i++)
+ ay8910_write_reg(psg,i,0);
+ psg->ready = 1;
+#if ENABLE_REGISTER_TEST
+ ay8910_write_reg(psg, AY_AFINE, 0);
+ ay8910_write_reg(psg, AY_ACOARSE, 1);
+ ay8910_write_reg(psg, AY_BFINE, 0);
+ ay8910_write_reg(psg, AY_BCOARSE, 2);
+ ay8910_write_reg(psg, AY_CFINE, 0);
+ ay8910_write_reg(psg, AY_CCOARSE, 4);
+ //#define AY_NOISEPER (6)
+ ay8910_write_reg(psg, AY_ENABLE, ~7);
+ ay8910_write_reg(psg, AY_AVOL, 10);
+ ay8910_write_reg(psg, AY_BVOL, 10);
+ ay8910_write_reg(psg, AY_CVOL, 10);
+ //#define AY_EFINE (11)
+ //#define AY_ECOARSE (12)
+ //#define AY_ESHAPE (13)
+#endif
+}
+
+void ay8910_set_volume(device_t *device,int channel,int volume)
+{
+ ay8910_context *psg = get_safe_token(device);
+ int ch;
+
+ for (ch = 0; ch < psg->streams; ch++)
+ if (channel == ch || psg->streams == 1 || channel == ALL_8910_CHANNELS)
+ psg->channel->set_output_gain(ch, volume / 100.0);
+}
+
+void ay8910_set_clock_ym(void *chip, int clock)
+{
+ ay8910_context *psg = (ay8910_context *)chip;
+ psg->channel->set_sample_rate( clock / 8 );
+}
+
+void ay8910_write_ym(void *chip, int addr, int data)
+{
+ ay8910_context *psg = (ay8910_context *)chip;
+
+ if (addr & 1)
+ { /* Data port */
+ int r = psg->register_latch;
+
+ if (r > 15) return;
+ if (r == AY_ESHAPE || psg->regs[r] != data)
+ {
+ /* update the output buffer before changing the register */
+ psg->channel->update();
+ }
+
+ ay8910_write_reg(psg,r,data);
+ }
+ else
+ { /* Register port */
+ psg->register_latch = data & 0x0f;
+ }
+}
+
+int ay8910_read_ym(void *chip)
+{
+ ay8910_context *psg = (ay8910_context *)chip;
+ device_type chip_type = psg->device->type();
+ int r = psg->register_latch;
+
+ if (r > 15) return 0;
+
+ /* There are no state dependent register in the AY8910! */
+ /* psg->channel->update(); */
+
+ switch (r)
+ {
+ case AY_PORTA:
+ if ((psg->regs[AY_ENABLE] & 0x40) != 0)
+ logerror("warning: read from 8910 '%s' Port A set as output\n",psg->device->tag());
+ /*
+ even if the port is set as output, we still need to return the external
+ data. Some games, like kidniki, need this to work.
+ */
+ if (!psg->portAread.isnull())
+ psg->regs[AY_PORTA] = psg->portAread(0);
+ else
+ logerror("%s: warning - read 8910 '%s' Port A\n",psg->device->machine().describe_context(),psg->device->tag());
+ break;
+ case AY_PORTB:
+ if ((psg->regs[AY_ENABLE] & 0x80) != 0)
+ logerror("warning: read from 8910 '%s' Port B set as output\n",psg->device->tag());
+ if (!psg->portBread.isnull())
+ psg->regs[AY_PORTB] = psg->portBread(0);
+ else
+ logerror("%s: warning - read 8910 '%s' Port B\n",psg->device->machine().describe_context(),psg->device->tag());
+ break;
+ }
+
+ /* Depending on chip type, unused bits in registers may or may not be accessible.
+ Untested chips are assumed to regard them as 'ram'
+ Tested and confirmed on hardware:
+ - AY-3-8910: inaccessible bits (see masks below) read back as 0
+ - YM2149: no anomaly
+ */
+ if (chip_type == AY8910) {
+ const UINT8 mask[0x10]={
+ 0xff,0x0f,0xff,0x0f,0xff,0x0f,0x1f,0xff,0x1f,0x1f,0x1f,0xff,0xff,0x0f,0xff,0xff
+ };
+
+ return psg->regs[r] & mask[r];
+ }
+ else return psg->regs[r];
+}
+
+/*************************************
+ *
+ * Sound Interface
+ *
+ *************************************/
+
+static DEVICE_START( ay8910 )
+{
+ static const ay8910_interface generic_ay8910 =
+ {
+ AY8910_LEGACY_OUTPUT,
+ AY8910_DEFAULT_LOADS,
+ DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_NULL
+ };
+ const ay8910_interface *intf = (device->static_config() ? (const ay8910_interface *)device->static_config() : &generic_ay8910);
+ ay8910_start_ym(get_safe_token(device), AY8910, device, device->clock(), intf);
+}
+
+static DEVICE_START( ym2149 )
+{
+ static const ay8910_interface generic_ay8910 =
+ {
+ AY8910_LEGACY_OUTPUT,
+ AY8910_DEFAULT_LOADS,
+ DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_NULL
+ };
+ const ay8910_interface *intf = (device->static_config() ? (const ay8910_interface *)device->static_config() : &generic_ay8910);
+ ay8910_start_ym(get_safe_token(device), YM2149, device, device->clock(), intf);
+}
+
+static DEVICE_STOP( ay8910 )
+{
+ ay8910_stop_ym(get_safe_token(device));
+}
+
+static DEVICE_RESET( ay8910 )
+{
+ ay8910_reset_ym(get_safe_token(device));
+}
+
+DEVICE_GET_INFO( ay8910 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(ay8910_context); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( ay8910 ); break;
+ case DEVINFO_FCT_STOP: info->stop = DEVICE_STOP_NAME( ay8910 ); break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME( ay8910 ); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "AY-3-8910A"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "PSG"); 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;
+ }
+}
+
+DEVICE_GET_INFO( ay8912 )
+{
+ switch (state)
+ {
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( ay8910 ); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "AY-3-8912A"); break;
+ default: DEVICE_GET_INFO_CALL(ay8910); break;
+ }
+}
+
+DEVICE_GET_INFO( ay8913 )
+{
+ switch (state)
+ {
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( ay8910 ); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "AY-3-8913A"); break;
+ default: DEVICE_GET_INFO_CALL(ay8910); break;
+ }
+}
+
+DEVICE_GET_INFO( ay8930 )
+{
+ switch (state)
+ {
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( ay8910 ); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "AY8930"); break;
+ default: DEVICE_GET_INFO_CALL(ay8910); break;
+ }
+}
+
+DEVICE_GET_INFO( ym2149 )
+{
+ switch (state)
+ {
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( ym2149 ); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "YM2149"); break;
+ default: DEVICE_GET_INFO_CALL(ay8910); break;
+ }
+}
+
+DEVICE_GET_INFO( ym3439 )
+{
+ switch (state)
+ {
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( ym2149 ); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "YM3439"); break;
+ default: DEVICE_GET_INFO_CALL(ay8910); break;
+ }
+}
+
+DEVICE_GET_INFO( ymz284 )
+{
+ switch (state)
+ {
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( ym2149 ); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "YMZ284"); break;
+ default: DEVICE_GET_INFO_CALL(ay8910); break;
+ }
+}
+
+DEVICE_GET_INFO( ymz294 )
+{
+ switch (state)
+ {
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( ym2149 ); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "YMZ294"); break;
+ default: DEVICE_GET_INFO_CALL(ay8910); break;
+ }
+}
+
+/*************************************
+ *
+ * Read/Write Handlers
+ *
+ *************************************/
+
+READ8_DEVICE_HANDLER( ay8910_r )
+{
+ return ay8910_read_ym(get_safe_token(device));
+}
+
+WRITE8_DEVICE_HANDLER( ay8910_data_address_w )
+{
+ /* note that directly connecting BC1 to A0 puts data on 0 and address on 1 */
+ ay8910_write_ym(get_safe_token(device), ~offset & 1, data);
+}
+
+WRITE8_DEVICE_HANDLER( ay8910_address_data_w )
+{
+ ay8910_write_ym(get_safe_token(device), offset & 1, data);
+}
+
+WRITE8_DEVICE_HANDLER( ay8910_address_w )
+{
+#if ENABLE_REGISTER_TEST
+ return;
+#else
+ ay8910_data_address_w(device, 1, data);
+#endif
+}
+
+WRITE8_DEVICE_HANDLER( ay8910_data_w )
+{
+#if ENABLE_REGISTER_TEST
+ return;
+#else
+ ay8910_data_address_w(device, 0, data);
+#endif
+}
+
+
+DEFINE_LEGACY_SOUND_DEVICE(AY8910, ay8910);
+DEFINE_LEGACY_SOUND_DEVICE(AY8912, ay8912);
+DEFINE_LEGACY_SOUND_DEVICE(AY8913, ay8913);
+DEFINE_LEGACY_SOUND_DEVICE(AY8930, ay8930);
+DEFINE_LEGACY_SOUND_DEVICE(YM2149, ym2149);
+DEFINE_LEGACY_SOUND_DEVICE(YM3439, ym3439);
+DEFINE_LEGACY_SOUND_DEVICE(YMZ284, ymz284);
+DEFINE_LEGACY_SOUND_DEVICE(YMZ294, ymz294);
diff --git a/trunk/src/emu/sound/ay8910.h b/trunk/src/emu/sound/ay8910.h
new file mode 100644
index 00000000000..3eff1808fe3
--- /dev/null
+++ b/trunk/src/emu/sound/ay8910.h
@@ -0,0 +1,110 @@
+#pragma once
+
+#ifndef __AY8910_H__
+#define __AY8910_H__
+
+#include "devlegcy.h"
+
+/*
+AY-3-8910A: 2 I/O ports
+AY-3-8912A: 1 I/O port
+AY-3-8913A: 0 I/O port
+AY8930: upper compatible with 8910.
+In extended mode, it has higher resolution and duty ratio setting
+YM2149: higher resolution
+YM3439: same as 2149
+YMZ284: 0 I/O port, different clock divider
+YMZ294: 0 I/O port
+*/
+
+#define ALL_8910_CHANNELS -1
+
+/* Internal resistance at Volume level 7. */
+
+#define AY8910_INTERNAL_RESISTANCE (356)
+#define YM2149_INTERNAL_RESISTANCE (353)
+
+/*
+ * Default values for resistor loads.
+ * The macro should be used in AY8910interface if
+ * the real values are unknown.
+ */
+#define AY8910_DEFAULT_LOADS {1000, 1000, 1000}
+
+/*
+ * The following is used by all drivers not reviewed yet.
+ * This will like the old behaviour, output between
+ * 0 and 7FFF
+ */
+#define AY8910_LEGACY_OUTPUT (1)
+
+/*
+ * Specifing the next define will simulate the special
+ * cross channel mixing if outputs are tied together.
+ * The driver will only provide one stream in this case.
+ */
+#define AY8910_SINGLE_OUTPUT (2)
+
+/*
+ * The follwoing define is the default behaviour.
+ * Output level 0 is 0V and 7ffff corresponds to 5V.
+ * Use this to specify that a discrete mixing stage
+ * follows.
+ */
+#define AY8910_DISCRETE_OUTPUT (4)
+
+/*
+ * The follwoing define causes the driver to output
+ * raw volume levels, i.e. 0 .. 15 and 0..31.
+ * This is intended to be used in a subsequent
+ * mixing modul (i.e. mpatrol ties 6 channels from
+ * AY-3-8910 together). Do not use it now.
+ */
+/* TODO: implement mixing module */
+#define AY8910_RAW_OUTPUT (8)
+
+typedef struct _ay8910_interface ay8910_interface;
+struct _ay8910_interface
+{
+ int flags; /* Flags */
+ int res_load[3]; /* Load on channel in ohms */
+ devcb_read8 portAread;
+ devcb_read8 portBread;
+ devcb_write8 portAwrite;
+ devcb_write8 portBwrite;
+};
+
+
+void ay8910_set_volume(device_t *device,int channel,int volume);
+
+READ8_DEVICE_HANDLER( ay8910_r );
+WRITE8_DEVICE_HANDLER( ay8910_address_w );
+WRITE8_DEVICE_HANDLER( ay8910_data_w );
+
+/* use this when BC1 == A0; here, BC1=0 selects 'data' and BC1=1 selects 'latch address' */
+WRITE8_DEVICE_HANDLER( ay8910_data_address_w );
+
+/* use this when BC1 == !A0; here, BC1=0 selects 'latch address' and BC1=1 selects 'data' */
+WRITE8_DEVICE_HANDLER( ay8910_address_data_w );
+
+
+/*********** An interface for SSG of YM2203 ***********/
+
+void *ay8910_start_ym(void *infoptr, device_type chip_type, device_t *device, int clock, const ay8910_interface *intf);
+
+void ay8910_stop_ym(void *chip);
+void ay8910_reset_ym(void *chip);
+void ay8910_set_clock_ym(void *chip, int clock);
+void ay8910_write_ym(void *chip, int addr, int data);
+int ay8910_read_ym(void *chip);
+
+DECLARE_LEGACY_SOUND_DEVICE(AY8910, ay8910);
+DECLARE_LEGACY_SOUND_DEVICE(AY8912, ay8912);
+DECLARE_LEGACY_SOUND_DEVICE(AY8913, ay8913);
+DECLARE_LEGACY_SOUND_DEVICE(AY8930, ay8930);
+DECLARE_LEGACY_SOUND_DEVICE(YM2149, ym2149);
+DECLARE_LEGACY_SOUND_DEVICE(YM3439, ym3439);
+DECLARE_LEGACY_SOUND_DEVICE(YMZ284, ymz284);
+DECLARE_LEGACY_SOUND_DEVICE(YMZ294, ymz294);
+
+#endif /* __AY8910_H__ */
diff --git a/trunk/src/emu/sound/beep.c b/trunk/src/emu/sound/beep.c
new file mode 100644
index 00000000000..fc5f9d5e124
--- /dev/null
+++ b/trunk/src/emu/sound/beep.c
@@ -0,0 +1,192 @@
+/***************************************************************************
+
+ beep.c
+
+ This is used for computers/systems which can only output a constant tone.
+ This tone can be turned on and off.
+ e.g. PCW and PCW16 computer systems
+ KT - 25-Jun-2000
+
+ Sound handler
+
+****************************************************************************/
+
+#include "emu.h"
+#include "sound/beep.h"
+
+
+#define BEEP_RATE 48000
+
+typedef struct _beep_state beep_state;
+struct _beep_state
+{
+ sound_stream *stream; /* stream number */
+ int enable; /* enable beep */
+ int frequency; /* set frequency - this can be changed using the appropiate function */
+ int incr; /* initial wave state */
+ INT16 signal; /* current signal */
+};
+
+
+INLINE beep_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == BEEP);
+ return (beep_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+
+/*************************************
+ *
+ * Stream updater
+ *
+ *************************************/
+
+static STREAM_UPDATE( beep_sound_update )
+{
+ beep_state *bs = (beep_state *) param;
+ stream_sample_t *buffer = outputs[0];
+ INT16 signal = bs->signal;
+ int clock = 0, rate = BEEP_RATE / 2;
+
+ /* get progress through wave */
+ int incr = bs->incr;
+
+ if (bs->frequency > 0)
+ clock = bs->frequency;
+
+ /* if we're not enabled, just fill with 0 */
+ if ( !bs->enable || clock == 0 )
+ {
+ memset( buffer, 0, samples * sizeof(*buffer) );
+ return;
+ }
+
+ /* fill in the sample */
+ while( samples-- > 0 )
+ {
+ *buffer++ = signal;
+ incr -= clock;
+ while( incr < 0 )
+ {
+ incr += rate;
+ signal = -signal;
+ }
+ }
+
+ /* store progress through wave */
+ bs->incr = incr;
+ bs->signal = signal;
+}
+
+
+
+/*************************************
+ *
+ * Sound handler start
+ *
+ *************************************/
+
+static DEVICE_START( beep )
+{
+ beep_state *pBeep = get_safe_token(device);
+
+ pBeep->stream = device->machine().sound().stream_alloc(*device, 0, 1, BEEP_RATE, pBeep, beep_sound_update );
+ pBeep->enable = 0;
+ pBeep->frequency = 3250;
+ pBeep->incr = 0;
+ pBeep->signal = 0x07fff;
+}
+
+
+
+/*************************************
+ *
+ * changing state to on from off will restart tone
+ *
+ *************************************/
+
+void beep_set_state(device_t *device, int on)
+{
+ beep_state *info = get_safe_token(device);
+
+ /* only update if new state is not the same as old state */
+ if (info->enable == on)
+ return;
+
+ info->stream->update();
+
+ info->enable = on;
+ /* restart wave from beginning */
+ info->incr = 0;
+ info->signal = 0x07fff;
+}
+
+
+
+/*************************************
+ *
+ * setting new frequency starts from beginning
+ *
+ *************************************/
+
+void beep_set_frequency(device_t *device,int frequency)
+{
+ beep_state *info = get_safe_token(device);
+
+ if (info->frequency == frequency)
+ return;
+
+ info->stream->update();
+ info->frequency = frequency;
+ info->signal = 0x07fff;
+ info->incr = 0;
+}
+
+
+
+/*************************************
+ *
+ * change a channel volume
+ *
+ *************************************/
+
+void beep_set_volume(device_t *device, int volume)
+{
+ beep_state *info = get_safe_token(device);
+
+ info->stream->update();
+
+ volume = 100 * volume / 7;
+
+ downcast<beep_device *>(device)->set_output_gain(0, volume);
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+DEVICE_GET_INFO( beep )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(beep_state); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( beep ); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Beep"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Beep"); 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 The MESS Team"); break;
+ }
+}
+
+
+DEFINE_LEGACY_SOUND_DEVICE(BEEP, beep);
diff --git a/trunk/src/emu/sound/beep.h b/trunk/src/emu/sound/beep.h
new file mode 100644
index 00000000000..62a31952554
--- /dev/null
+++ b/trunk/src/emu/sound/beep.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#ifndef __BEEP_H__
+#define __BEEP_H__
+
+#include "devlegcy.h"
+
+#define BEEPER_TAG "beeper"
+
+void beep_set_state(device_t *device, int on);
+void beep_set_frequency(device_t *device, int frequency);
+void beep_set_volume(device_t *device, int volume);
+
+DECLARE_LEGACY_SOUND_DEVICE(BEEP, beep);
+
+#endif /* __BEEP_H__ */
diff --git a/trunk/src/emu/sound/bsmt2000.c b/trunk/src/emu/sound/bsmt2000.c
new file mode 100644
index 00000000000..44510fd6bb4
--- /dev/null
+++ b/trunk/src/emu/sound/bsmt2000.c
@@ -0,0 +1,391 @@
+/***************************************************************************
+
+ bsmt2000.c
+
+ BSMT2000 device 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.
+
+****************************************************************************
+
+ Chip is actually a TMS320C15 DSP with embedded mask rom
+ Trivia: BSMT stands for "Brian Schmidt's Mouse Trap"
+
+***************************************************************************/
+#define ADDRESS_MAP_MODERN
+
+#include "emu.h"
+#include "bsmt2000.h"
+
+
+// device type definition
+const device_type BSMT2000 = &device_creator<bsmt2000_device>;
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// program map for the DSP (points to internal ROM)
+static ADDRESS_MAP_START( tms_program_map, AS_PROGRAM, 16, bsmt2000_device)
+ ADDRESS_MAP_UNMAP_HIGH
+ AM_RANGE(0x000, 0xfff) AM_ROM
+ADDRESS_MAP_END
+
+
+// I/O map for the DSP
+static ADDRESS_MAP_START( tms_io_map, AS_IO, 16, bsmt2000_device)
+ AM_RANGE(0, 0) AM_READWRITE(tms_register_r, tms_rom_addr_w)
+ AM_RANGE(1, 1) AM_READWRITE(tms_data_r, tms_rom_bank_w)
+ AM_RANGE(2, 2) AM_READ(tms_rom_r)
+ AM_RANGE(3, 3) AM_WRITE(tms_left_w)
+ AM_RANGE(7, 7) AM_WRITE(tms_right_w)
+ AM_RANGE(TMS32010_BIO, TMS32010_BIO) AM_READ(tms_write_pending_r)
+ADDRESS_MAP_END
+
+
+// machine fragment
+static MACHINE_CONFIG_FRAGMENT( bsmt2000 )
+ MCFG_CPU_ADD("bsmt2000", TMS32015, DERIVED_CLOCK(1,1))
+ MCFG_CPU_PROGRAM_MAP(tms_program_map)
+ // data map is internal to the CPU
+ MCFG_CPU_IO_MAP(tms_io_map)
+MACHINE_CONFIG_END
+
+
+// default address map for the external memory interface
+// the BSMT can address a full 32 bits but typically only 24 are used
+static ADDRESS_MAP_START( bsmt2000, AS_0, 8, bsmt2000_device)
+ AM_RANGE(0x00000, 0xffffff) AM_ROM
+ADDRESS_MAP_END
+
+
+// ROM definition for the BSMT2000 program ROM
+ROM_START( bsmt2000 )
+ ROM_REGION( 0x2000, "bsmt2000", 0 )
+ ROM_LOAD16_WORD( "bsmt2000.bin", 0x0000, 0x2000, CRC(c2a265af) SHA1(6ec9eb038fb8eb842c5482aebe1d149daf49f2e6) )
+ROM_END
+
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bsmt2000_device - constructor
+//-------------------------------------------------
+
+//-------------------------------------------------
+// bsmt2000_device - constructor
+//-------------------------------------------------
+
+bsmt2000_device::bsmt2000_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, BSMT2000, "BSMT2000", "bsmt2000", tag, owner, clock),
+ device_sound_interface(mconfig, *this),
+ device_memory_interface(mconfig, *this),
+ m_space_config("samples", ENDIANNESS_LITTLE, 8, 32, 0, NULL, *ADDRESS_MAP_NAME(bsmt2000)),
+ m_ready_callback(NULL),
+ m_stream(NULL),
+ m_direct(NULL),
+ m_cpu(NULL),
+ m_register_select(0),
+ m_write_data(0),
+ m_rom_address(0),
+ m_rom_bank(0),
+ m_left_data(0),
+ m_right_data(0),
+ m_write_pending(false)
+{
+}
+
+
+//-------------------------------------------------
+// static_set_ready_callback - configuration
+// helper to set the ready callback
+//-------------------------------------------------
+
+void bsmt2000_device::static_set_ready_callback(device_t &device, ready_callback callback)
+{
+ bsmt2000_device &bsmt = downcast<bsmt2000_device &>(device);
+ bsmt.m_ready_callback = callback;
+}
+
+
+//-------------------------------------------------
+// rom_region - return a pointer to the device's
+// internal ROM region
+//-------------------------------------------------
+
+const rom_entry *bsmt2000_device::device_rom_region() const
+{
+ return ROM_NAME( bsmt2000 );
+}
+
+
+//-------------------------------------------------
+// machine_config_additions - return a pointer to
+// the device's machine fragment
+//-------------------------------------------------
+
+machine_config_constructor bsmt2000_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( bsmt2000 );
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bsmt2000_device::device_start()
+{
+ // find our CPU
+ m_cpu = downcast<tms32015_device*>(subdevice("bsmt2000"));
+
+ // find our direct access
+ m_direct = &space()->direct();
+
+ // create the stream; BSMT typically runs at 24MHz and writes to a DAC, so
+ // in theory we should generate a 24MHz stream, but that's certainly overkill
+ // internally at 24MHz the max output sample rate is 32kHz
+ // divided by 128 gives us 6x the max output rate which is plenty for oversampling
+ m_stream = machine().sound().stream_alloc(*this, 0, 2, clock() / 128);
+
+ // register for save states
+ save_item(NAME(m_register_select));
+ save_item(NAME(m_write_data));
+ save_item(NAME(m_rom_address));
+ save_item(NAME(m_rom_bank));
+ save_item(NAME(m_left_data));
+ save_item(NAME(m_right_data));
+ save_item(NAME(m_write_pending));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void bsmt2000_device::device_reset()
+{
+ synchronize(TIMER_ID_RESET);
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return a description of
+// any address spaces owned by this device
+//-------------------------------------------------
+
+const address_space_config *bsmt2000_device::memory_space_config(address_spacenum spacenum) const
+{
+ return (spacenum == 0) ? &m_space_config : NULL;
+}
+
+
+//-------------------------------------------------
+// device_timer - handle deferred writes and
+// resets as a timer callback
+//-------------------------------------------------
+
+void bsmt2000_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ // deferred reset
+ case TIMER_ID_RESET:
+ m_stream->update();
+ m_cpu->reset();
+ break;
+
+ // deferred register write
+ case TIMER_ID_REG_WRITE:
+ m_register_select = param & 0xffff;
+ break;
+
+ // deferred data write
+ case TIMER_ID_DATA_WRITE:
+ m_write_data = param & 0xffff;
+ if (m_write_pending) logerror("BSMT2000: Missed data\n");
+ m_write_pending = true;
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// sound_stream_update - handle update requests
+// for our sound stream
+//-------------------------------------------------
+
+void bsmt2000_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+{
+ // just fill with current left/right values
+ for (int samp = 0; samp < samples; samp++)
+ {
+ outputs[0][samp] = m_left_data * 16;
+ outputs[1][samp] = m_right_data * 16;
+ }
+}
+
+
+//-------------------------------------------------
+// read_status - return the write pending status
+//-------------------------------------------------
+
+UINT16 bsmt2000_device::read_status()
+{
+ return m_write_pending ? 0 : 1;
+}
+
+
+//-------------------------------------------------
+// write_reg - handle writes to the BSMT2000
+// register select interface
+//-------------------------------------------------
+
+void bsmt2000_device::write_reg(UINT16 data)
+{
+ synchronize(TIMER_ID_REG_WRITE, data);
+}
+
+
+//-------------------------------------------------
+// write_data - handle writes to the BSMT2000
+// data port
+//-------------------------------------------------
+
+void bsmt2000_device::write_data(UINT16 data)
+{
+ synchronize(TIMER_ID_DATA_WRITE, data);
+
+ // boost the interleave on a write so that the caller detects the status more accurately
+ machine().scheduler().boost_interleave(attotime::from_usec(1), attotime::from_usec(10));
+}
+
+
+//-------------------------------------------------
+// tms_register_r - return the value written to
+// the register select port
+//-------------------------------------------------
+
+READ16_MEMBER( bsmt2000_device::tms_register_r )
+{
+ return m_register_select;
+}
+
+
+//-------------------------------------------------
+// tms_data_r - return the value written to the
+// data port
+//-------------------------------------------------
+
+READ16_MEMBER( bsmt2000_device::tms_data_r )
+{
+ // also implicitly clear the write pending flag
+ m_write_pending = false;
+ if (m_ready_callback != NULL)
+ (*m_ready_callback)(*this);
+ return m_write_data;
+}
+
+
+//-------------------------------------------------
+// tms_rom_r - read a byte from the currently
+// selected ROM bank and address
+//-------------------------------------------------
+
+READ16_MEMBER( bsmt2000_device::tms_rom_r )
+{
+ // underlying logic assumes this is a sign-extended value
+ return (INT8)m_direct->read_raw_byte((m_rom_bank << 16) + m_rom_address);
+}
+
+
+//-------------------------------------------------
+// tms_rom_addr_w - selects which byte within the
+// current ROM bank to access
+//-------------------------------------------------
+
+WRITE16_MEMBER( bsmt2000_device::tms_rom_addr_w )
+{
+ m_rom_address = data;
+}
+
+
+//-------------------------------------------------
+// tms_rom_bank_w - selects which bank of ROM to
+// access
+//-------------------------------------------------
+
+WRITE16_MEMBER( bsmt2000_device::tms_rom_bank_w )
+{
+ m_rom_bank = data;
+}
+
+
+//-------------------------------------------------
+// tms_left_w - handle writes to the left channel
+// DAC
+//-------------------------------------------------
+
+WRITE16_MEMBER( bsmt2000_device::tms_left_w )
+{
+ m_stream->update();
+ m_left_data = data;
+}
+
+
+//-------------------------------------------------
+// tms_right_w - handle writes to the right
+// channel DAC
+//-------------------------------------------------
+
+WRITE16_MEMBER( bsmt2000_device::tms_right_w )
+{
+ m_stream->update();
+ m_right_data = data;
+}
+
+
+//-------------------------------------------------
+// tms_write_pending_r - return whether a write
+// is pending; this data is fed into the BIO line
+// on the TMS32015
+//-------------------------------------------------
+
+READ16_MEMBER( bsmt2000_device::tms_write_pending_r )
+{
+ return m_write_pending ? 1 : 0;
+}
diff --git a/trunk/src/emu/sound/bsmt2000.h b/trunk/src/emu/sound/bsmt2000.h
new file mode 100644
index 00000000000..33228c3bec4
--- /dev/null
+++ b/trunk/src/emu/sound/bsmt2000.h
@@ -0,0 +1,146 @@
+/***************************************************************************
+
+ bsmt2000.h
+
+ BSMT2000 device 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 __BSMT2000_H__
+#define __BSMT2000_H__
+
+#include "cpu/tms32010/tms32010.h"
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_BSMT2000_ADD(_tag, _clock) \
+ MCFG_DEVICE_ADD(_tag, BSMT2000, _clock) \
+
+#define MCFG_BSMT2000_REPLACE(_tag, _clock) \
+ MCFG_DEVICE_REPLACE(_tag, BSMT2000, _clock) \
+
+#define MCFG_BSMT2000_READY_CALLBACK(_callback) \
+ bsmt2000_device::static_set_ready_callback(*device, _callback); \
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bsmt2000_device;
+
+
+// ======================> bsmt2000_device
+
+class bsmt2000_device : public device_t,
+ public device_sound_interface,
+ public device_memory_interface
+{
+ typedef void (*ready_callback)(bsmt2000_device &device);
+
+public:
+ // construction/destruction
+ bsmt2000_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // inline configuration helpers
+ static void static_set_ready_callback(device_t &device, ready_callback callback);
+
+ // public interface
+ UINT16 read_status();
+ void write_reg(UINT16 data);
+ void write_data(UINT16 data);
+
+protected:
+ // device-level overrides
+ const rom_entry *device_rom_region() const;
+ machine_config_constructor device_mconfig_additions() const;
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
+
+ // device_sound_interface overrides
+ virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
+
+public:
+ // internal TMS I/O callbacks
+ DECLARE_READ16_MEMBER( tms_register_r );
+ DECLARE_READ16_MEMBER( tms_data_r );
+ DECLARE_READ16_MEMBER( tms_rom_r );
+ DECLARE_WRITE16_MEMBER( tms_rom_addr_w );
+ DECLARE_WRITE16_MEMBER( tms_rom_bank_w );
+ DECLARE_WRITE16_MEMBER( tms_left_w );
+ DECLARE_WRITE16_MEMBER( tms_right_w );
+ DECLARE_READ16_MEMBER( tms_write_pending_r );
+
+private:
+ // timers
+ enum
+ {
+ TIMER_ID_RESET,
+ TIMER_ID_REG_WRITE,
+ TIMER_ID_DATA_WRITE
+ };
+
+ // configuration state
+ const address_space_config m_space_config;
+ ready_callback m_ready_callback;
+
+ // internal state
+ sound_stream * m_stream;
+ direct_read_data * m_direct;
+ tms32015_device * m_cpu;
+ UINT16 m_register_select;
+ UINT16 m_write_data;
+ UINT16 m_rom_address;
+ UINT16 m_rom_bank;
+ INT16 m_left_data;
+ INT16 m_right_data;
+ bool m_write_pending;
+};
+
+
+// device type definition
+extern const device_type BSMT2000;
+
+
+#endif /* __BSMT2000_H__ */
diff --git a/trunk/src/emu/sound/c140.c b/trunk/src/emu/sound/c140.c
new file mode 100644
index 00000000000..8638635db0f
--- /dev/null
+++ b/trunk/src/emu/sound/c140.c
@@ -0,0 +1,528 @@
+/*
+C140.c
+
+Simulator based on AMUSE sources.
+The C140 sound chip is used by Namco System 2 and System 21
+The 219 ASIC (which incorporates a modified C140) is used by Namco NA-1 and NA-2
+This chip controls 24 channels (C140) or 16 (219) of PCM.
+16 bytes are associated with each channel.
+Channels can be 8 bit signed PCM, or 12 bit signed PCM.
+
+Timer behavior is not yet handled.
+
+Unmapped registers:
+ 0x1f8:timer interval? (Nx0.1 ms)
+ 0x1fa:irq ack? timer restart?
+ 0x1fe:timer switch?(0:off 1:on)
+
+--------------
+
+ ASIC "219" notes
+
+ On the 219 ASIC used on NA-1 and NA-2, the high registers have the following
+ meaning instead:
+ 0x1f7: bank for voices 0-3
+ 0x1f1: bank for voices 4-7
+ 0x1f3: bank for voices 8-11
+ 0x1f5: bank for voices 12-15
+
+ Some games (bkrtmaq, xday2) write to 0x1fd for voices 12-15 instead. Probably the bank registers
+ mirror at 1f8, in which case 1ff is also 0-3, 1f9 is also 4-7, 1fb is also 8-11, and 1fd is also 12-15.
+
+ Each bank is 0x20000 (128k), and the voice addresses on the 219 are all multiplied by 2.
+ Additionally, the 219's base pitch is the same as the C352's (42667). But these changes
+ are IMO not sufficient to make this a separate file - all the other registers are
+ fully compatible.
+
+ Finally, the 219 only has 16 voices.
+*/
+/*
+ 2000.06.26 CAB fixed compressed pcm playback
+ 2002.07.20 R.Belmont added support for multiple banking types
+ 2006.01.08 R.Belmont added support for NA-1/2 "219" derivative
+*/
+
+
+#include "emu.h"
+#include "c140.h"
+
+#define MAX_VOICE 24
+
+struct voice_registers
+{
+ UINT8 volume_right;
+ UINT8 volume_left;
+ UINT8 frequency_msb;
+ UINT8 frequency_lsb;
+ UINT8 bank;
+ UINT8 mode;
+ UINT8 start_msb;
+ UINT8 start_lsb;
+ UINT8 end_msb;
+ UINT8 end_lsb;
+ UINT8 loop_msb;
+ UINT8 loop_lsb;
+ UINT8 reserved[4];
+};
+
+typedef struct
+{
+ long ptoffset;
+ long pos;
+ long key;
+ //--work
+ long lastdt;
+ long prevdt;
+ long dltdt;
+ //--reg
+ long rvol;
+ long lvol;
+ long frequency;
+ long bank;
+ long mode;
+
+ long sample_start;
+ long sample_end;
+ long sample_loop;
+} VOICE;
+
+typedef struct _c140_state c140_state;
+struct _c140_state
+{
+ int sample_rate;
+ sound_stream *stream;
+ int banking_type;
+ /* internal buffers */
+ INT16 *mixer_buffer_left;
+ INT16 *mixer_buffer_right;
+
+ int baserate;
+ void *pRom;
+ UINT8 REG[0x200];
+
+ INT16 pcmtbl[8]; //2000.06.26 CAB
+
+ VOICE voi[MAX_VOICE];
+};
+
+INLINE c140_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == C140);
+ return (c140_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+static void init_voice( VOICE *v )
+{
+ v->key=0;
+ v->ptoffset=0;
+ v->rvol=0;
+ v->lvol=0;
+ v->frequency=0;
+ v->bank=0;
+ v->mode=0;
+ v->sample_start=0;
+ v->sample_end=0;
+ v->sample_loop=0;
+}
+READ8_DEVICE_HANDLER( c140_r )
+{
+ c140_state *info = get_safe_token(device);
+ offset&=0x1ff;
+ return info->REG[offset];
+}
+
+/*
+ find_sample: compute the actual address of a sample given it's
+ address and banking registers, as well as the board type.
+
+ I suspect in "real life" this works like the Sega MultiPCM where the banking
+ is done by a small PAL or GAL external to the sound chip, which can be switched
+ per-game or at least per-PCB revision as addressing range needs grow.
+ */
+static long find_sample(c140_state *info, long adrs, long bank, int voice)
+{
+ long newadr = 0;
+
+ static const INT16 asic219banks[4] = { 0x1f7, 0x1f1, 0x1f3, 0x1f5 };
+
+ adrs=(bank<<16)+adrs;
+
+ switch (info->banking_type)
+ {
+ case C140_TYPE_SYSTEM2:
+ // System 2 banking
+ newadr = ((adrs&0x200000)>>2)|(adrs&0x7ffff);
+ break;
+
+ case C140_TYPE_SYSTEM21_A:
+ // System 21 type A (simple) banking.
+ // similar to System 2's.
+ newadr = ((adrs&0x300000)>>1)+(adrs&0x7ffff);
+ break;
+
+ case C140_TYPE_SYSTEM21_B:
+ // System 21 type B (chip select) banking
+
+ // get base address of sample inside the bank
+ newadr = ((adrs&0x100000)>>2) + (adrs&0x3ffff);
+
+ // now add the starting bank offsets based on the 2
+ // chip select bits.
+ // 0x40000 picks individual 512k ROMs
+ if (adrs & 0x40000)
+ {
+ newadr += 0x80000;
+ }
+
+ // and 0x200000 which group of chips...
+ if (adrs & 0x200000)
+ {
+ newadr += 0x100000;
+ }
+ break;
+
+ case C140_TYPE_ASIC219:
+ // ASIC219's banking is fairly simple
+ newadr = ((info->REG[asic219banks[voice/4]]&0x3) * 0x20000) + adrs;
+ break;
+ }
+
+ return (newadr);
+}
+WRITE8_DEVICE_HANDLER( c140_w )
+{
+ c140_state *info = get_safe_token(device);
+ info->stream->update();
+
+ offset&=0x1ff;
+
+ // mirror the bank registers on the 219, fixes bkrtmaq (and probably xday2 based on notes in the HLE)
+ if ((offset >= 0x1f8) && (info->banking_type == C140_TYPE_ASIC219))
+ {
+ offset -= 8;
+ }
+
+ info->REG[offset]=data;
+ if( offset<0x180 )
+ {
+ VOICE *v = &info->voi[offset>>4];
+
+ if( (offset&0xf)==0x5 )
+ {
+ if( data&0x80 )
+ {
+ const struct voice_registers *vreg = (struct voice_registers *) &info->REG[offset&0x1f0];
+ v->key=1;
+ v->ptoffset=0;
+ v->pos=0;
+ v->lastdt=0;
+ v->prevdt=0;
+ v->dltdt=0;
+ v->bank = vreg->bank;
+ v->mode = data;
+
+ // on the 219 asic, addresses are in words
+ if (info->banking_type == C140_TYPE_ASIC219)
+ {
+ v->sample_loop = (vreg->loop_msb*256 + vreg->loop_lsb)*2;
+ v->sample_start = (vreg->start_msb*256 + vreg->start_lsb)*2;
+ v->sample_end = (vreg->end_msb*256 + vreg->end_lsb)*2;
+
+ #if 0
+ logerror("219: play v %d mode %02x start %x loop %x end %x\n",
+ offset>>4, v->mode,
+ find_sample(info, v->sample_start, v->bank, offset>>4),
+ find_sample(info, v->sample_loop, v->bank, offset>>4),
+ find_sample(info, v->sample_end, v->bank, offset>>4));
+ #endif
+ }
+ else
+ {
+ v->sample_loop = vreg->loop_msb*256 + vreg->loop_lsb;
+ v->sample_start = vreg->start_msb*256 + vreg->start_lsb;
+ v->sample_end = vreg->end_msb*256 + vreg->end_lsb;
+ }
+ }
+ else
+ {
+ v->key=0;
+ }
+ }
+ }
+}
+
+void c140_set_base(device_t *device, void *base)
+{
+ c140_state *info = get_safe_token(device);
+ info->pRom = base;
+}
+
+INLINE int limit(INT32 in)
+{
+ if(in>0x7fff) return 0x7fff;
+ else if(in<-0x8000) return -0x8000;
+ return in;
+}
+
+static STREAM_UPDATE( update_stereo )
+{
+ c140_state *info = (c140_state *)param;
+ int i,j;
+
+ INT32 rvol,lvol;
+ INT32 dt;
+ INT32 sdt;
+ INT32 st,ed,sz;
+
+ INT8 *pSampleData;
+ INT32 frequency,delta,offset,pos;
+ INT32 cnt, voicecnt;
+ INT32 lastdt,prevdt,dltdt;
+ float pbase=(float)info->baserate*2.0 / (float)info->sample_rate;
+
+ INT16 *lmix, *rmix;
+
+ if(samples>info->sample_rate) samples=info->sample_rate;
+
+ /* zap the contents of the mixer buffer */
+ memset(info->mixer_buffer_left, 0, samples * sizeof(INT16));
+ memset(info->mixer_buffer_right, 0, samples * sizeof(INT16));
+
+ /* get the number of voices to update */
+ voicecnt = (info->banking_type == C140_TYPE_ASIC219) ? 16 : 24;
+
+ //--- audio update
+ for( i=0;i<voicecnt;i++ )
+ {
+ VOICE *v = &info->voi[i];
+ const struct voice_registers *vreg = (struct voice_registers *)&info->REG[i*16];
+
+ if( v->key )
+ {
+ frequency= vreg->frequency_msb*256 + vreg->frequency_lsb;
+
+ /* Abort voice if no frequency value set */
+ if(frequency==0) continue;
+
+ /* Delta = frequency * ((8MHz/374)*2 / sample rate) */
+ delta=(long)((float)frequency * pbase);
+
+ /* Calculate left/right channel volumes */
+ lvol=(vreg->volume_left*32)/MAX_VOICE; //32ch -> 24ch
+ rvol=(vreg->volume_right*32)/MAX_VOICE;
+
+ /* Set mixer outputs base pointers */
+ lmix = info->mixer_buffer_left;
+ rmix = info->mixer_buffer_right;
+
+ /* Retrieve sample start/end and calculate size */
+ st=v->sample_start;
+ ed=v->sample_end;
+ sz=ed-st;
+
+ /* Retrieve base pointer to the sample data */
+ pSampleData=(signed char*)((FPTR)info->pRom + find_sample(info, st, v->bank, i));
+
+ /* Fetch back previous data pointers */
+ offset=v->ptoffset;
+ pos=v->pos;
+ lastdt=v->lastdt;
+ prevdt=v->prevdt;
+ dltdt=v->dltdt;
+
+ /* Switch on data type - compressed PCM is only for C140 */
+ if ((v->mode&8) && (info->banking_type != C140_TYPE_ASIC219))
+ {
+ //compressed PCM (maybe correct...)
+ /* Loop for enough to fill sample buffer as requested */
+ for(j=0;j<samples;j++)
+ {
+ offset += delta;
+ cnt = (offset>>16)&0x7fff;
+ offset &= 0xffff;
+ pos+=cnt;
+ //for(;cnt>0;cnt--)
+ {
+ /* Check for the end of the sample */
+ if(pos >= sz)
+ {
+ /* Check if its a looping sample, either stop or loop */
+ if(v->mode&0x10)
+ {
+ pos = (v->sample_loop - st);
+ }
+ else
+ {
+ v->key=0;
+ break;
+ }
+ }
+
+ /* Read the chosen sample byte */
+ dt=pSampleData[pos];
+
+ /* decompress to 13bit range */ //2000.06.26 CAB
+ sdt=dt>>3; //signed
+ if(sdt<0) sdt = (sdt<<(dt&7)) - info->pcmtbl[dt&7];
+ else sdt = (sdt<<(dt&7)) + info->pcmtbl[dt&7];
+
+ prevdt=lastdt;
+ lastdt=sdt;
+ dltdt=(lastdt - prevdt);
+ }
+
+ /* Caclulate the sample value */
+ dt=((dltdt*offset)>>16)+prevdt;
+
+ /* Write the data to the sample buffers */
+ *lmix++ +=(dt*lvol)>>(5+5);
+ *rmix++ +=(dt*rvol)>>(5+5);
+ }
+ }
+ else
+ {
+ /* linear 8bit signed PCM */
+ for(j=0;j<samples;j++)
+ {
+ offset += delta;
+ cnt = (offset>>16)&0x7fff;
+ offset &= 0xffff;
+ pos += cnt;
+ /* Check for the end of the sample */
+ if(pos >= sz)
+ {
+ /* Check if its a looping sample, either stop or loop */
+ if( v->mode&0x10 )
+ {
+ pos = (v->sample_loop - st);
+ }
+ else
+ {
+ v->key=0;
+ break;
+ }
+ }
+
+ if( cnt )
+ {
+ prevdt=lastdt;
+
+ if (info->banking_type == C140_TYPE_ASIC219)
+ {
+ lastdt = pSampleData[BYTE_XOR_BE(pos)];
+
+ // Sign + magnitude format
+ if ((v->mode & 0x01) && (lastdt & 0x80))
+ lastdt = -(lastdt & 0x7f);
+
+ // Sign flip
+ if (v->mode & 0x40)
+ lastdt = -lastdt;
+ }
+ else
+ {
+ lastdt=pSampleData[pos];
+ }
+
+ dltdt = (lastdt - prevdt);
+ }
+
+ /* Caclulate the sample value */
+ dt=((dltdt*offset)>>16)+prevdt;
+
+ /* Write the data to the sample buffers */
+ *lmix++ +=(dt*lvol)>>5;
+ *rmix++ +=(dt*rvol)>>5;
+ }
+ }
+
+ /* Save positional data for next callback */
+ v->ptoffset=offset;
+ v->pos=pos;
+ v->lastdt=lastdt;
+ v->prevdt=prevdt;
+ v->dltdt=dltdt;
+ }
+ }
+
+ /* render to MAME's stream buffer */
+ lmix = info->mixer_buffer_left;
+ rmix = info->mixer_buffer_right;
+ {
+ stream_sample_t *dest1 = outputs[0];
+ stream_sample_t *dest2 = outputs[1];
+ for (i = 0; i < samples; i++)
+ {
+ *dest1++ = limit(8*(*lmix++));
+ *dest2++ = limit(8*(*rmix++));
+ }
+ }
+}
+
+static DEVICE_START( c140 )
+{
+ const c140_interface *intf = (const c140_interface *)device->static_config();
+ c140_state *info = get_safe_token(device);
+
+ info->sample_rate=info->baserate=device->clock();
+
+ info->banking_type = intf->banking_type;
+
+ info->stream = device->machine().sound().stream_alloc(*device,0,2,info->sample_rate,info,update_stereo);
+
+ info->pRom=*device->region();
+
+ /* make decompress pcm table */ //2000.06.26 CAB
+ {
+ int i;
+ INT32 segbase=0;
+ for(i=0;i<8;i++)
+ {
+ info->pcmtbl[i]=segbase; //segment base value
+ segbase += 16<<i;
+ }
+ }
+
+ memset(info->REG,0,sizeof(info->REG));
+ {
+ int i;
+ for(i=0;i<MAX_VOICE;i++) init_voice( &info->voi[i] );
+ }
+
+ /* allocate a pair of buffers to mix into - 1 second's worth should be more than enough */
+ info->mixer_buffer_left = auto_alloc_array(device->machine(), INT16, 2 * info->sample_rate);
+ info->mixer_buffer_right = info->mixer_buffer_left + info->sample_rate;
+}
+
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+DEVICE_GET_INFO( c140 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(c140_state); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( c140 ); break;
+ case DEVINFO_FCT_STOP: /* nothing */ break;
+ case DEVINFO_FCT_RESET: /* nothing */ break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "C140"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Namco PCM"); 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;
+ }
+}
+
+
+DEFINE_LEGACY_SOUND_DEVICE(C140, c140);
diff --git a/trunk/src/emu/sound/c140.h b/trunk/src/emu/sound/c140.h
new file mode 100644
index 00000000000..05f1dbdc12a
--- /dev/null
+++ b/trunk/src/emu/sound/c140.h
@@ -0,0 +1,30 @@
+/* C140.h */
+
+#pragma once
+
+#ifndef __C140_H__
+#define __C140_H__
+
+#include "devlegcy.h"
+
+READ8_DEVICE_HANDLER( c140_r );
+WRITE8_DEVICE_HANDLER( c140_w );
+
+void c140_set_base(device_t *device, void *base);
+
+enum
+{
+ C140_TYPE_SYSTEM2,
+ C140_TYPE_SYSTEM21_A,
+ C140_TYPE_SYSTEM21_B,
+ C140_TYPE_ASIC219
+};
+
+typedef struct _c140_interface c140_interface;
+struct _c140_interface {
+ int banking_type;
+};
+
+DECLARE_LEGACY_SOUND_DEVICE(C140, c140);
+
+#endif /* __C140_H__ */
diff --git a/trunk/src/emu/sound/c352.c b/trunk/src/emu/sound/c352.c
new file mode 100644
index 00000000000..032943c035f
--- /dev/null
+++ b/trunk/src/emu/sound/c352.c
@@ -0,0 +1,527 @@
+/*
+ c352.c - Namco C352 custom PCM chip emulation
+ v1.2
+ By R. Belmont
+ Additional code by cync and the hoot development team
+
+ Thanks to Cap of VivaNonno for info and The_Author for preliminary reverse-engineering
+
+ Chip specs:
+ 32 voices
+ Supports 8-bit linear and 8-bit muLaw samples
+ Output: digital, 16 bit, 4 channels
+ Output sample rate is the input clock / 384.
+ */
+
+#include "emu.h"
+#include "c352.h"
+
+#define VERBOSE (0)
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+// device type definition
+const device_type C352 = &device_creator<c352_device>;
+
+// default address map
+static ADDRESS_MAP_START( c352, AS_0, 8 )
+ AM_RANGE(0x000000, 0xffffff) AM_ROM
+ADDRESS_MAP_END
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// c352_device - constructor
+//-------------------------------------------------
+
+c352_device::c352_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, C352, "C352", tag, owner, clock),
+ device_sound_interface(mconfig, *this),
+ device_memory_interface(mconfig, *this),
+ m_space_config("samples", ENDIANNESS_LITTLE, 8, 24, 0, NULL, *ADDRESS_MAP_NAME(c352))
+{
+}
+
+//-------------------------------------------------
+// memory_space_config - return a description of
+// any address spaces owned by this device
+//-------------------------------------------------
+
+const address_space_config *c352_device::memory_space_config(address_spacenum spacenum) const
+{
+ return (spacenum == 0) ? &m_space_config : NULL;
+}
+
+// noise generator
+int c352_device::get_mseq_bit()
+{
+ unsigned int mask = (1 << (7 - 1));
+ unsigned int reg = m_mseq_reg;
+ unsigned int bit = reg & (1 << (17 - 1));
+
+ if (bit)
+ {
+ reg = ((reg ^ mask) << 1) | 1;
+ }
+ else
+ {
+ reg = reg << 1;
+ }
+
+ m_mseq_reg = reg;
+
+ return (reg & 1);
+}
+
+void c352_device::mix_one_channel(unsigned long ch, long sample_count)
+{
+ int i;
+
+ signed short sample, nextsample;
+ signed short noisebuf;
+ UINT16 noisecnt;
+ INT32 frequency, delta, offset, cnt, flag;
+ UINT32 bank;
+ UINT32 pos;
+
+ frequency = m_c352_ch[ch].pitch;
+ delta=frequency;
+
+ pos = m_c352_ch[ch].current_addr; // sample pointer
+ offset = m_c352_ch[ch].pos; // 16.16 fixed-point offset into the sample
+ flag = m_c352_ch[ch].flag;
+ bank = m_c352_ch[ch].bank << 16;
+
+ noisecnt = m_c352_ch[ch].noisecnt;
+ noisebuf = m_c352_ch[ch].noisebuf;
+
+ for(i = 0 ; (i < sample_count) && (flag & C352_FLG_BUSY) ; i++)
+ {
+ offset += delta;
+ cnt = (offset>>16)&0x7fff;
+ if (cnt) // if there is a whole sample part, chop it off now that it's been applied
+ {
+ offset &= 0xffff;
+ }
+
+ if (pos > 0x1000000)
+ {
+ m_c352_ch[ch].flag &= ~C352_FLG_BUSY;
+ return;
+ }
+
+ sample = (char)m_direct->read_raw_byte(pos);
+ nextsample = (char)m_direct->read_raw_byte(pos+cnt);
+
+ // sample is muLaw, not 8-bit linear (Fighting Layer uses this extensively)
+ if (flag & C352_FLG_MULAW)
+ {
+ sample = m_mulaw_table[(unsigned char)sample];
+ nextsample = m_mulaw_table[(unsigned char)nextsample];
+ }
+ else
+ {
+ sample <<= 8;
+ nextsample <<= 8;
+ }
+
+ // play noise instead of sample data
+ if (flag & C352_FLG_NOISE)
+ {
+ int noise_level = 0x8000;
+ sample = m_c352_ch[ch].noise = (m_c352_ch[ch].noise << 1) | get_mseq_bit();
+ sample = (sample & (noise_level - 1)) - (noise_level >> 1);
+ if (sample > 0x7f)
+ {
+ sample = 0x7f;
+ }
+ else if (sample < 0)
+ {
+ sample = 0xff;
+ }
+ sample = m_mulaw_table[(unsigned char)sample];
+
+ if ( (pos+cnt) == pos )
+ {
+ noisebuf += sample;
+ noisecnt++;
+ sample = noisebuf / noisecnt;
+ }
+ else
+ {
+ if ( noisecnt )
+ {
+ sample = noisebuf / noisecnt;
+ }
+ else
+ {
+ sample = m_mulaw_table[0x7f]; // Nearest sound(s) is here.
+ }
+ noisebuf = 0;
+ noisecnt = ( flag & C352_FLG_FILTER ) ? 0 : 1;
+ }
+ }
+
+ // apply linear interpolation
+ if ( (flag & (C352_FLG_FILTER | C352_FLG_NOISE)) == 0 )
+ {
+ sample = (short)(sample + ((nextsample-sample) * (((double)(0x0000ffff&offset) )/0x10000)));
+ }
+
+ if ( flag & C352_FLG_PHASEFL )
+ {
+ m_channel_l[i] += ((-sample * m_c352_ch[ch].vol_l)>>8);
+ }
+ else
+ {
+ m_channel_l[i] += ((sample * m_c352_ch[ch].vol_l)>>8);
+ }
+
+ if ( flag & C352_FLG_PHASEFR )
+ {
+ m_channel_r[i] += ((-sample * m_c352_ch[ch].vol_r)>>8);
+ }
+ else
+ {
+ m_channel_r[i] += ((sample * m_c352_ch[ch].vol_r)>>8);
+ }
+
+ if ( flag & C352_FLG_PHASERL )
+ {
+ m_channel_l2[i] += ((-sample * m_c352_ch[ch].vol_l2)>>8);
+ }
+ else
+ {
+ m_channel_l2[i] += ((sample * m_c352_ch[ch].vol_l2)>>8);
+ }
+ m_channel_r2[i] += ((sample * m_c352_ch[ch].vol_r2)>>8);
+
+ if ( (flag & C352_FLG_REVERSE) && (flag & C352_FLG_LOOP) )
+ {
+ if ( !(flag & C352_FLG_LDIR) )
+ {
+ pos += cnt;
+ if (
+ (((pos&0xFFFF) > m_c352_ch[ch].end_addr) && ((pos&0xFFFF) < m_c352_ch[ch].start) && (m_c352_ch[ch].start > m_c352_ch[ch].end_addr) ) ||
+ (((pos&0xFFFF) > m_c352_ch[ch].end_addr) && ((pos&0xFFFF) > m_c352_ch[ch].start) && (m_c352_ch[ch].start < m_c352_ch[ch].end_addr) ) ||
+ ((pos > (bank|0xFFFF)) && (m_c352_ch[ch].end_addr == 0xFFFF))
+ )
+ {
+ m_c352_ch[ch].flag |= C352_FLG_LDIR;
+ m_c352_ch[ch].flag |= C352_FLG_LOOPHIST;
+ }
+ }
+ else
+ {
+ pos -= cnt;
+ if (
+ (((pos&0xFFFF) < m_c352_ch[ch].repeat) && ((pos&0xFFFF) < m_c352_ch[ch].end_addr) && (m_c352_ch[ch].end_addr > m_c352_ch[ch].start) ) ||
+ (((pos&0xFFFF) < m_c352_ch[ch].repeat) && ((pos&0xFFFF) > m_c352_ch[ch].end_addr) && (m_c352_ch[ch].end_addr < m_c352_ch[ch].start) ) ||
+ ((pos < bank) && (m_c352_ch[ch].repeat == 0x0000))
+ )
+ {
+ m_c352_ch[ch].flag &= ~C352_FLG_LDIR;
+ m_c352_ch[ch].flag |= C352_FLG_LOOPHIST;
+ }
+ }
+ }
+ else if ( flag & C352_FLG_REVERSE )
+ {
+ pos -= cnt;
+ if (
+ (((pos&0xFFFF) < m_c352_ch[ch].end_addr) && ((pos&0xFFFF) < m_c352_ch[ch].start) && (m_c352_ch[ch].start > m_c352_ch[ch].end_addr) ) ||
+ (((pos&0xFFFF) < m_c352_ch[ch].end_addr) && ((pos&0xFFFF) > m_c352_ch[ch].start) && (m_c352_ch[ch].start < m_c352_ch[ch].end_addr) ) ||
+ ((pos < bank) && (m_c352_ch[ch].end_addr == 0x0000))
+ )
+ {
+ if ( (flag & C352_FLG_LINK) && (flag & C352_FLG_LOOP) )
+ {
+ m_c352_ch[ch].bank = m_c352_ch[ch].start_addr & 0xFF;
+ m_c352_ch[ch].start_addr = m_c352_ch[ch].repeat_addr;
+ m_c352_ch[ch].start = m_c352_ch[ch].start_addr;
+ m_c352_ch[ch].repeat = m_c352_ch[ch].repeat_addr;
+ pos = (m_c352_ch[ch].bank<<16) + m_c352_ch[ch].start_addr;
+ m_c352_ch[ch].flag |= C352_FLG_LOOPHIST;
+ }
+ else if (flag & C352_FLG_LOOP)
+ {
+ pos = (pos & 0xFF0000) + m_c352_ch[ch].repeat;
+ m_c352_ch[ch].flag |= C352_FLG_LOOPHIST;
+ }
+ else
+ {
+ m_c352_ch[ch].flag |= C352_FLG_KEYOFF;
+ m_c352_ch[ch].flag &= ~C352_FLG_BUSY;
+ return;
+ }
+ }
+ } else {
+ pos += cnt;
+ if (
+ (((pos&0xFFFF) > m_c352_ch[ch].end_addr) && ((pos&0xFFFF) < m_c352_ch[ch].start) && (m_c352_ch[ch].start > m_c352_ch[ch].end_addr) ) ||
+ (((pos&0xFFFF) > m_c352_ch[ch].end_addr) && ((pos&0xFFFF) > m_c352_ch[ch].start) && (m_c352_ch[ch].start < m_c352_ch[ch].end_addr) ) ||
+ ((pos > (bank|0xFFFF)) && (m_c352_ch[ch].end_addr == 0xFFFF))
+ )
+ {
+ if ( (flag & C352_FLG_LINK) && (flag & C352_FLG_LOOP) )
+ {
+ m_c352_ch[ch].bank = m_c352_ch[ch].start_addr & 0xFF;
+ m_c352_ch[ch].start_addr = m_c352_ch[ch].repeat_addr;
+ m_c352_ch[ch].start = m_c352_ch[ch].start_addr;
+ m_c352_ch[ch].repeat = m_c352_ch[ch].repeat_addr;
+ pos = (m_c352_ch[ch].bank<<16) + m_c352_ch[ch].start_addr;
+ m_c352_ch[ch].flag |= C352_FLG_LOOPHIST;
+ }
+ else if (flag & C352_FLG_LOOP)
+ {
+ pos = (pos & 0xFF0000) + m_c352_ch[ch].repeat;
+ m_c352_ch[ch].flag |= C352_FLG_LOOPHIST;
+ }
+ else
+ {
+ m_c352_ch[ch].flag |= C352_FLG_KEYOFF;
+ m_c352_ch[ch].flag &= ~C352_FLG_BUSY;
+ return;
+ }
+ }
+ }
+ }
+
+ m_c352_ch[ch].noisecnt = noisecnt;
+ m_c352_ch[ch].noisebuf = noisebuf;
+ m_c352_ch[ch].pos = offset;
+ m_c352_ch[ch].current_addr = pos;
+}
+
+
+void c352_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+{
+ int i, j;
+ stream_sample_t *bufferl = outputs[0];
+ stream_sample_t *bufferr = outputs[1];
+ stream_sample_t *bufferl2 = outputs[2];
+ stream_sample_t *bufferr2 = outputs[3];
+
+ for(i = 0 ; i < samples ; i++)
+ {
+ m_channel_l[i] = m_channel_r[i] = m_channel_l2[i] = m_channel_r2[i] = 0;
+ }
+
+ for (j = 0 ; j < 32 ; j++)
+ {
+ mix_one_channel(j, samples);
+ }
+
+ for(i = 0 ; i < samples ; i++)
+ {
+ *bufferl++ = (short) (m_channel_l[i] >>3);
+ *bufferr++ = (short) (m_channel_r[i] >>3);
+ *bufferl2++ = (short) (m_channel_l2[i] >>3);
+ *bufferr2++ = (short) (m_channel_r2[i] >>3);
+ }
+}
+
+unsigned short c352_device::read_reg16(unsigned long address)
+{
+ unsigned long chan;
+ unsigned short val;
+
+ m_stream->update();
+
+ chan = (address >> 4) & 0xfff;
+ if (chan > 31)
+ {
+ val = 0;
+ }
+ else
+ {
+ if ((address & 0xf) == 6)
+ {
+ val = m_c352_ch[chan].flag;
+ }
+ else
+ {
+ val = 0;
+ }
+ }
+ return val;
+}
+
+void c352_device::write_reg16(unsigned long address, unsigned short val)
+{
+ unsigned long chan;
+ int i;
+
+ m_stream->update();
+
+ chan = (address >> 4) & 0xfff;
+
+ if ( address >= 0x400 )
+ {
+ switch(address)
+ {
+ case 0x404: // execute key-ons/offs
+ for ( i = 0 ; i <= 31 ; i++ )
+ {
+ if ( m_c352_ch[i].flag & C352_FLG_KEYON )
+ {
+ m_c352_ch[i].current_addr = (m_c352_ch[i].bank << 16) + m_c352_ch[i].start_addr;
+ m_c352_ch[i].start = m_c352_ch[i].start_addr;
+ m_c352_ch[i].repeat = m_c352_ch[i].repeat_addr;
+ m_c352_ch[i].noisebuf = 0;
+ m_c352_ch[i].noisecnt = 0;
+ m_c352_ch[i].flag &= ~(C352_FLG_KEYON | C352_FLG_LOOPHIST);
+ m_c352_ch[i].flag |= C352_FLG_BUSY;
+ }
+ else if ( m_c352_ch[i].flag & C352_FLG_KEYOFF )
+ {
+ m_c352_ch[i].flag &= ~C352_FLG_BUSY;
+ m_c352_ch[i].flag &= ~(C352_FLG_KEYOFF);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return;
+ }
+
+ if (chan > 31)
+ {
+ LOG(("C352 CTRL %08lx %04x\n", address, val));
+ return;
+ }
+ switch(address & 0xf)
+ {
+ case 0x0:
+ // volumes (output 1)
+ LOG(("CH %02ld LVOL %02x RVOL %02x\n", chan, val & 0xff, val >> 8));
+ m_c352_ch[chan].vol_l = val & 0xff;
+ m_c352_ch[chan].vol_r = val >> 8;
+ break;
+
+ case 0x2:
+ // volumes (output 2)
+ LOG(("CH %02ld RLVOL %02x RRVOL %02x\n", chan, val & 0xff, val >> 8));
+ m_c352_ch[chan].vol_l2 = val & 0xff;
+ m_c352_ch[chan].vol_r2 = val >> 8;
+ break;
+
+ case 0x4:
+ // pitch
+ LOG(("CH %02ld PITCH %04x\n", chan, val));
+ m_c352_ch[chan].pitch = val;
+ break;
+
+ case 0x6:
+ // flags
+ LOG(("CH %02ld FLAG %02x\n", chan, val));
+ m_c352_ch[chan].flag = val;
+ break;
+
+ case 0x8:
+ // bank (bits 16-31 of address);
+ m_c352_ch[chan].bank = val & 0xff;
+ LOG(("CH %02ld BANK %02x", chan, m_c352_ch[chan].bank));
+ break;
+
+ case 0xa:
+ // start address
+ LOG(("CH %02ld SADDR %04x\n", chan, val));
+ m_c352_ch[chan].start_addr = val;
+ break;
+
+ case 0xc:
+ // end address
+ LOG(("CH %02ld EADDR %04x\n", chan, val));
+ m_c352_ch[chan].end_addr = val;
+ break;
+
+ case 0xe:
+ // loop address
+ LOG(("CH %02ld LADDR %04x\n", chan, val));
+ m_c352_ch[chan].repeat_addr = val;
+ break;
+
+ default:
+ LOG(("CH %02ld UNKN %01lx %04x", chan, address & 0xf, val));
+ break;
+ }
+}
+
+void c352_device::device_start()
+{
+ int i;
+ double x_max = 32752.0;
+ double y_max = 127.0;
+ double u = 10.0;
+
+ // find our direct access
+ m_direct = &space()->direct();
+
+ m_sample_rate_base = clock() / 192;
+
+ m_stream = machine().sound().stream_alloc(*this, 0, 4, m_sample_rate_base, this);
+
+ // generate mulaw table for mulaw format samples
+ for (i = 0; i < 256; i++)
+ {
+ double y = (double) (i & 0x7f);
+ double x = (exp (y / y_max * log (1.0 + u)) - 1.0) * x_max / u;
+
+ if (i & 0x80)
+ {
+ x = -x;
+ }
+ m_mulaw_table[i] = (short)x;
+ }
+
+ // register save state info
+ for (i = 0; i < 32; i++)
+ {
+ save_item(NAME(m_c352_ch[i].vol_l), i);
+ save_item(NAME(m_c352_ch[i].vol_r), i);
+ save_item(NAME(m_c352_ch[i].vol_l2), i);
+ save_item(NAME(m_c352_ch[i].vol_r2), i);
+ save_item(NAME(m_c352_ch[i].bank), i);
+ save_item(NAME(m_c352_ch[i].noise), i);
+ save_item(NAME(m_c352_ch[i].noisebuf), i);
+ save_item(NAME(m_c352_ch[i].noisecnt), i);
+ save_item(NAME(m_c352_ch[i].pitch), i);
+ save_item(NAME(m_c352_ch[i].start_addr), i);
+ save_item(NAME(m_c352_ch[i].end_addr), i);
+ save_item(NAME(m_c352_ch[i].repeat_addr), i);
+ save_item(NAME(m_c352_ch[i].flag), i);
+ save_item(NAME(m_c352_ch[i].start), i);
+ save_item(NAME(m_c352_ch[i].repeat), i);
+ save_item(NAME(m_c352_ch[i].current_addr), i);
+ save_item(NAME(m_c352_ch[i].pos), i);
+ }
+}
+
+void c352_device::device_reset()
+{
+ // clear all channels states
+ memset(m_c352_ch, 0, sizeof(c352_ch_t)*32);
+
+ // init noise generator
+ m_mseq_reg = 0x12345678;
+}
+
+READ16_MEMBER( c352_device::read )
+{
+ return(read_reg16(offset*2));
+}
+
+WRITE16_MEMBER( c352_device::write )
+{
+ if (mem_mask == 0xffff)
+ {
+ write_reg16(offset*2, data);
+ }
+ else
+ {
+ logerror("C352: byte-wide write unsupported at this time!\n");
+ }
+}
diff --git a/trunk/src/emu/sound/c352.h b/trunk/src/emu/sound/c352.h
new file mode 100644
index 00000000000..7a018bd845b
--- /dev/null
+++ b/trunk/src/emu/sound/c352.h
@@ -0,0 +1,112 @@
+#pragma once
+
+#ifndef __C352_H__
+#define __C352_H__
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_C352_ADD(_tag, _clock) \
+ MCFG_DEVICE_ADD(_tag, C352, _clock)
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> asc_device
+
+class c352_device : public device_t,
+ public device_sound_interface,
+ public device_memory_interface
+{
+public:
+ // construction/destruction
+ c352_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_READ16_MEMBER(read);
+ DECLARE_WRITE16_MEMBER(write);
+
+ sound_stream *m_stream;
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_sound_interface overrides
+ virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
+
+ const address_space_config m_space_config;
+
+private:
+ enum {
+ C352_FLG_BUSY = 0x8000, // channel is busy
+ C352_FLG_KEYON = 0x4000, // Keyon
+ C352_FLG_KEYOFF = 0x2000, // Keyoff
+ C352_FLG_LOOPTRG = 0x1000, // Loop Trigger
+ C352_FLG_LOOPHIST = 0x0800, // Loop History
+ C352_FLG_FM = 0x0400, // Frequency Modulation
+ C352_FLG_PHASERL = 0x0200, // Rear Left invert phase 180 degrees
+ C352_FLG_PHASEFL = 0x0100, // Front Left invert phase 180 degrees
+ C352_FLG_PHASEFR = 0x0080, // invert phase 180 degrees (e.g. flip sign of sample)
+ C352_FLG_LDIR = 0x0040, // loop direction
+ C352_FLG_LINK = 0x0020, // "long-format" sample (can't loop, not sure what else it means)
+ C352_FLG_NOISE = 0x0010, // play noise instead of sample
+ C352_FLG_MULAW = 0x0008, // sample is mulaw instead of linear 8-bit PCM
+ C352_FLG_FILTER = 0x0004, // don't apply filter
+ C352_FLG_REVLOOP = 0x0003, // loop backwards
+ C352_FLG_LOOP = 0x0002, // loop forward
+ C352_FLG_REVERSE = 0x0001, // play sample backwards
+ };
+
+ typedef struct
+ {
+ UINT8 vol_l;
+ UINT8 vol_r;
+ UINT8 vol_l2;
+ UINT8 vol_r2;
+ UINT8 bank;
+ INT16 noise;
+ INT16 noisebuf;
+ UINT16 noisecnt;
+ UINT16 pitch;
+ UINT16 start_addr;
+ UINT16 end_addr;
+ UINT16 repeat_addr;
+ UINT32 flag;
+
+ UINT16 start;
+ UINT16 repeat;
+ UINT32 current_addr;
+ UINT32 pos;
+ } c352_ch_t;
+
+ c352_ch_t m_c352_ch[32];
+ int m_sample_rate_base;
+
+ long m_channel_l[2048*2];
+ long m_channel_r[2048*2];
+ long m_channel_l2[2048*2];
+ long m_channel_r2[2048*2];
+
+ short m_mulaw_table[256];
+ unsigned int m_mseq_reg;
+ direct_read_data *m_direct;
+
+ // private functions
+ int get_mseq_bit(void);
+ void mix_one_channel(unsigned long ch, long sample_count);
+ unsigned short read_reg16(unsigned long address);
+ void write_reg16(unsigned long address, unsigned short val);
+};
+
+
+// device type definition
+extern const device_type C352;
+
+#endif /* __C352_H__ */
+
diff --git a/trunk/src/emu/sound/c6280.c b/trunk/src/emu/sound/c6280.c
new file mode 100644
index 00000000000..27b6812aa6f
--- /dev/null
+++ b/trunk/src/emu/sound/c6280.c
@@ -0,0 +1,375 @@
+/*
+ HuC6280 sound chip emulator
+ by Charles MacDonald
+ E-mail: cgfm2@hotmail.com
+ WWW: http://cgfm2.emuviews.com
+
+ Thanks to:
+
+ - Paul Clifford for his PSG documentation.
+ - Richard Bannister for the TGEmu-specific sound updating code.
+ - http://www.uspto.gov for the PSG patents.
+ - All contributors to the tghack-list.
+
+ Changes:
+
+ (03/30/2003)
+ - Removed TGEmu specific code and added support functions for MAME.
+ - Modified setup code to handle multiple chips with different clock and
+ volume settings.
+
+ Missing features / things to do:
+
+ - Add LFO support. But do any games actually use it?
+
+ - Add shared index for waveform playback and sample writes. Almost every
+ game will reset the index prior to playback so this isn't an issue.
+
+ - While the noise emulation is complete, the data for the pseudo-random
+ bitstream is calculated by machine.rand() and is not a representation of what
+ the actual hardware does.
+
+ For some background on Hudson Soft's C62 chipset:
+
+ - http://www.hudsonsoft.net/ww/about/about.html
+ - http://www.hudson.co.jp/corp/eng/coinfo/history.html
+
+ Legal information:
+
+ Copyright Charles MacDonald
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "emu.h"
+#include "c6280.h"
+
+typedef struct {
+ UINT16 frequency;
+ UINT8 control;
+ UINT8 balance;
+ UINT8 waveform[32];
+ UINT8 index;
+ INT16 dda;
+ UINT8 noise_control;
+ UINT32 noise_counter;
+ UINT32 counter;
+} t_channel;
+
+typedef struct {
+ sound_stream *stream;
+ device_t *device;
+ device_t *cpudevice;
+ UINT8 select;
+ UINT8 balance;
+ UINT8 lfo_frequency;
+ UINT8 lfo_control;
+ t_channel channel[8];
+ INT16 volume_table[32];
+ UINT32 noise_freq_tab[32];
+ UINT32 wave_freq_tab[4096];
+} c6280_t;
+
+INLINE c6280_t *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == C6280);
+ return (c6280_t *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+/* only needed for io_buffer */
+#include "cpu/h6280/h6280.h"
+
+
+static void c6280_init(device_t *device, c6280_t *p, double clk, double rate)
+{
+ const c6280_interface *intf = (const c6280_interface *)device->static_config();
+ int i;
+ double step;
+
+ /* Loudest volume level for table */
+ double level = 65535.0 / 6.0 / 32.0;
+
+ /* Clear context */
+ memset(p, 0, sizeof(c6280_t));
+
+ p->device = device;
+ p->cpudevice = device->machine().device(intf->cpu);
+ if (p->cpudevice == NULL)
+ fatalerror("c6280_init: no CPU found with tag of '%s'\n", device->tag());
+
+ /* Make waveform frequency table */
+ for(i = 0; i < 4096; i += 1)
+ {
+ step = ((clk / rate) * 4096) / (i+1);
+ p->wave_freq_tab[(1 + i) & 0xFFF] = (UINT32)step;
+ }
+
+ /* Make noise frequency table */
+ for(i = 0; i < 32; i += 1)
+ {
+ step = ((clk / rate) * 32) / (i+1);
+ p->noise_freq_tab[i] = (UINT32)step;
+ }
+
+ /* Make volume table */
+ /* PSG has 48dB volume range spread over 32 steps */
+ step = 48.0 / 32.0;
+ for(i = 0; i < 31; i++)
+ {
+ p->volume_table[i] = (UINT16)level;
+ level /= pow(10.0, step / 20.0);
+ }
+ p->volume_table[31] = 0;
+}
+
+
+static void c6280_write(c6280_t *p, int offset, int data)
+{
+ t_channel *q = &p->channel[p->select];
+
+ /* Update stream */
+ p->stream->update();
+
+ switch(offset & 0x0F)
+ {
+ case 0x00: /* Channel select */
+ p->select = data & 0x07;
+ break;
+
+ case 0x01: /* Global balance */
+ p->balance = data;
+ break;
+
+ case 0x02: /* Channel frequency (LSB) */
+ q->frequency = (q->frequency & 0x0F00) | data;
+ q->frequency &= 0x0FFF;
+ break;
+
+ case 0x03: /* Channel frequency (MSB) */
+ q->frequency = (q->frequency & 0x00FF) | (data << 8);
+ q->frequency &= 0x0FFF;
+ break;
+
+ case 0x04: /* Channel control (key-on, DDA mode, volume) */
+
+ /* 1-to-0 transition of DDA bit resets waveform index */
+ if((q->control & 0x40) && ((data & 0x40) == 0))
+ {
+ q->index = 0;
+ }
+ q->control = data;
+ break;
+
+ case 0x05: /* Channel balance */
+ q->balance = data;
+ break;
+
+ case 0x06: /* Channel waveform data */
+
+ switch(q->control & 0xC0)
+ {
+ case 0x00:
+ q->waveform[q->index & 0x1F] = data & 0x1F;
+ q->index = (q->index + 1) & 0x1F;
+ break;
+
+ case 0x40:
+ break;
+
+ case 0x80:
+ q->waveform[q->index & 0x1F] = data & 0x1F;
+ q->index = (q->index + 1) & 0x1F;
+ break;
+
+ case 0xC0:
+ q->dda = data & 0x1F;
+ break;
+ }
+
+ break;
+
+ case 0x07: /* Noise control (enable, frequency) */
+ q->noise_control = data;
+ break;
+
+ case 0x08: /* LFO frequency */
+ p->lfo_frequency = data;
+ break;
+
+ case 0x09: /* LFO control (enable, mode) */
+ p->lfo_control = data;
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+static STREAM_UPDATE( c6280_update )
+{
+ static const int scale_tab[] = {
+ 0x00, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
+ 0x10, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F
+ };
+ int ch;
+ int i;
+ c6280_t *p = (c6280_t *)param;
+
+ int lmal = (p->balance >> 4) & 0x0F;
+ int rmal = (p->balance >> 0) & 0x0F;
+ int vll, vlr;
+
+ lmal = scale_tab[lmal];
+ rmal = scale_tab[rmal];
+
+ /* Clear buffer */
+ for(i = 0; i < samples; i++)
+ {
+ outputs[0][i] = 0;
+ outputs[1][i] = 0;
+ }
+
+ for(ch = 0; ch < 6; ch++)
+ {
+ /* Only look at enabled channels */
+ if(p->channel[ch].control & 0x80)
+ {
+ int lal = (p->channel[ch].balance >> 4) & 0x0F;
+ int ral = (p->channel[ch].balance >> 0) & 0x0F;
+ int al = p->channel[ch].control & 0x1F;
+
+ lal = scale_tab[lal];
+ ral = scale_tab[ral];
+
+ /* Calculate volume just as the patent says */
+ vll = (0x1F - lal) + (0x1F - al) + (0x1F - lmal);
+ if(vll > 0x1F) vll = 0x1F;
+
+ vlr = (0x1F - ral) + (0x1F - al) + (0x1F - rmal);
+ if(vlr > 0x1F) vlr = 0x1F;
+
+ vll = p->volume_table[vll];
+ vlr = p->volume_table[vlr];
+
+ /* Check channel mode */
+ if((ch >= 4) && (p->channel[ch].noise_control & 0x80))
+ {
+ /* Noise mode */
+ UINT32 step = p->noise_freq_tab[(p->channel[ch].noise_control & 0x1F) ^ 0x1F];
+ for(i = 0; i < samples; i += 1)
+ {
+ static int data = 0;
+ p->channel[ch].noise_counter += step;
+ if(p->channel[ch].noise_counter >= 0x800)
+ {
+ data = (p->device->machine().rand() & 1) ? 0x1F : 0;
+ }
+ p->channel[ch].noise_counter &= 0x7FF;
+ outputs[0][i] += (INT16)(vll * (data - 16));
+ outputs[1][i] += (INT16)(vlr * (data - 16));
+ }
+ }
+ else
+ if(p->channel[ch].control & 0x40)
+ {
+ /* DDA mode */
+ for(i = 0; i < samples; i++)
+ {
+ outputs[0][i] += (INT16)(vll * (p->channel[ch].dda - 16));
+ outputs[1][i] += (INT16)(vlr * (p->channel[ch].dda - 16));
+ }
+ }
+ else
+ {
+ /* Waveform mode */
+ UINT32 step = p->wave_freq_tab[p->channel[ch].frequency];
+ for(i = 0; i < samples; i += 1)
+ {
+ int offset;
+ INT16 data;
+ offset = (p->channel[ch].counter >> 12) & 0x1F;
+ p->channel[ch].counter += step;
+ p->channel[ch].counter &= 0x1FFFF;
+ data = p->channel[ch].waveform[offset];
+ outputs[0][i] += (INT16)(vll * (data - 16));
+ outputs[1][i] += (INT16)(vlr * (data - 16));
+ }
+ }
+ }
+ }
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* MAME specific code */
+/*--------------------------------------------------------------------------*/
+
+static DEVICE_START( c6280 )
+{
+ int rate = device->clock()/16;
+ c6280_t *info = get_safe_token(device);
+
+ /* Initialize PSG emulator */
+ c6280_init(device, info, device->clock(), rate);
+
+ /* Create stereo stream */
+ info->stream = device->machine().sound().stream_alloc(*device, 0, 2, rate, info, c6280_update);
+}
+
+READ8_DEVICE_HANDLER( c6280_r )
+{
+ c6280_t *info = get_safe_token(device);
+ return h6280io_get_buffer(info->cpudevice);
+}
+
+WRITE8_DEVICE_HANDLER( c6280_w )
+{
+ c6280_t *info = get_safe_token(device);
+ h6280io_set_buffer(info->cpudevice, data);
+ c6280_write(info, offset, data);
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+DEVICE_GET_INFO( c6280 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(c6280_t); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( c6280 ); break;
+ case DEVINFO_FCT_STOP: /* nothing */ break;
+ case DEVINFO_FCT_RESET: /* nothing */ 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, "????"); 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;
+ }
+}
+
+
+DEFINE_LEGACY_SOUND_DEVICE(C6280, c6280);
diff --git a/trunk/src/emu/sound/c6280.h b/trunk/src/emu/sound/c6280.h
new file mode 100644
index 00000000000..fe61983268c
--- /dev/null
+++ b/trunk/src/emu/sound/c6280.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#ifndef __C6280_H__
+#define __C6280_H__
+
+#include "devlegcy.h"
+
+typedef struct _c6280_interface c6280_interface;
+struct _c6280_interface
+{
+ const char * cpu;
+};
+
+/* Function prototypes */
+WRITE8_DEVICE_HANDLER( c6280_w );
+READ8_DEVICE_HANDLER( c6280_r );
+
+DECLARE_LEGACY_SOUND_DEVICE(C6280, c6280);
+
+#endif /* __C6280_H__ */
diff --git a/trunk/src/emu/sound/cdda.c b/trunk/src/emu/sound/cdda.c
new file mode 100644
index 00000000000..a6987051d63
--- /dev/null
+++ b/trunk/src/emu/sound/cdda.c
@@ -0,0 +1,346 @@
+/*
+ CD-DA "Red Book" audio sound hardware handler
+ Relies on the actual CD logic and reading in cdrom.c.
+*/
+
+#include "emu.h"
+#include "cdrom.h"
+#include "cdda.h"
+
+typedef struct _cdda_info cdda_info;
+struct _cdda_info
+{
+ sound_stream * stream;
+ cdrom_file * disc;
+
+ INT8 audio_playing, audio_pause, audio_ended_normally;
+ UINT32 audio_lba, audio_length;
+
+ UINT8 * audio_cache;
+ UINT32 audio_samples;
+ UINT32 audio_bptr;
+};
+
+INLINE cdda_info *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == CDDA);
+ return (cdda_info *)downcast<legacy_device_base *>(device)->token();
+}
+
+#define MAX_SECTORS ( 4 )
+
+static void get_audio_data(cdda_info *info, stream_sample_t *bufL, stream_sample_t *bufR, UINT32 samples_wanted);
+
+
+/*-------------------------------------------------
+ cdda_update - stream update callback
+-------------------------------------------------*/
+
+static STREAM_UPDATE( cdda_update )
+{
+ cdda_info *info = (cdda_info *)param;
+ get_audio_data(info, &outputs[0][0], &outputs[1][0], samples);
+}
+
+
+/*-------------------------------------------------
+ DEVICE_START( cdda ) - audio start callback
+-------------------------------------------------*/
+
+static DEVICE_START( cdda )
+{
+ //const struct CDDAinterface *intf;
+ cdda_info *info = get_safe_token(device);
+
+ /* allocate an audio cache */
+ info->audio_cache = auto_alloc_array( device->machine(), UINT8, CD_MAX_SECTOR_DATA * MAX_SECTORS );
+
+ //intf = (const struct CDDAinterface *)device->static_config();
+
+ info->stream = device->machine().sound().stream_alloc(*device, 0, 2, 44100, info, cdda_update);
+
+ device->save_item( NAME(info->audio_playing) );
+ device->save_item( NAME(info->audio_pause) );
+ device->save_item( NAME(info->audio_ended_normally) );
+ device->save_item( NAME(info->audio_lba) );
+ device->save_item( NAME(info->audio_length) );
+ device->save_pointer( NAME(info->audio_cache), CD_MAX_SECTOR_DATA * MAX_SECTORS );
+ device->save_item( NAME(info->audio_samples) );
+ device->save_item( NAME(info->audio_bptr) );
+}
+
+
+/*-------------------------------------------------
+ cdda_set_cdrom - set the CD-ROM file for the
+ given CDDA stream
+-------------------------------------------------*/
+
+void cdda_set_cdrom(device_t *device, void *file)
+{
+ cdda_info *info = get_safe_token(device);
+ info->disc = (cdrom_file *)file;
+}
+
+
+/*-------------------------------------------------
+ cdda_from_cdrom - find the CDDA stream
+ that references the given CD-ROM file
+-------------------------------------------------*/
+
+device_t *cdda_from_cdrom(running_machine &machine, void *file)
+{
+ device_sound_interface *sound = NULL;
+
+ for (bool gotone = machine.devicelist().first(sound); gotone; gotone = sound->next(sound))
+ if (sound->device().type() == CDDA)
+ {
+ cdda_info *info = get_safe_token(*sound);
+ if (info->disc == file)
+ return *sound;
+ }
+
+ return NULL;
+}
+
+
+/*-------------------------------------------------
+ cdda_start_audio - begin playback of a Red
+ Book audio track
+-------------------------------------------------*/
+
+void cdda_start_audio(device_t *device, UINT32 startlba, UINT32 numblocks)
+{
+ cdda_info *info = get_safe_token(device);
+
+ info->stream->update();
+ info->audio_playing = TRUE;
+ info->audio_pause = FALSE;
+ info->audio_ended_normally = FALSE;
+ info->audio_lba = startlba;
+ info->audio_length = numblocks;
+}
+
+
+/*-------------------------------------------------
+ cdda_stop_audio - stop playback of a Red Book
+ audio track
+-------------------------------------------------*/
+
+void cdda_stop_audio(device_t *device)
+{
+ cdda_info *info = get_safe_token(device);
+
+ info->stream->update();
+ info->audio_playing = FALSE;
+ info->audio_ended_normally = TRUE;
+}
+
+
+/*-------------------------------------------------
+ cdda_pause_audio - pause/unpause playback of
+ a Red Book audio track
+-------------------------------------------------*/
+
+void cdda_pause_audio(device_t *device, int pause)
+{
+ cdda_info *info = get_safe_token(device);
+
+ info->stream->update();
+ info->audio_pause = pause;
+}
+
+
+/*-------------------------------------------------
+ cdda_get_audio_lba - returns the current LBA
+ (physical sector) during Red Book playback
+-------------------------------------------------*/
+
+UINT32 cdda_get_audio_lba(device_t *device)
+{
+ cdda_info *info = get_safe_token(device);
+
+ info->stream->update();
+ return info->audio_lba;
+}
+
+
+/*-------------------------------------------------
+ cdda_audio_active - returns Red Book audio
+ playback status
+-------------------------------------------------*/
+
+int cdda_audio_active(device_t *device)
+{
+ cdda_info *info = get_safe_token(device);
+
+ info->stream->update();
+ return info->audio_playing;
+}
+
+
+/*-------------------------------------------------
+ cdda_audio_paused - returns if Red Book
+ playback is paused
+-------------------------------------------------*/
+
+int cdda_audio_paused(device_t *device)
+{
+ cdda_info *info = get_safe_token(device);
+ return info->audio_pause;
+}
+
+
+/*-------------------------------------------------
+ cdda_audio_ended - returns if a Red Book
+ track reached it's natural end
+-------------------------------------------------*/
+
+int cdda_audio_ended(device_t *device)
+{
+ cdda_info *info = get_safe_token(device);
+ return info->audio_ended_normally;
+}
+
+
+/*-------------------------------------------------
+ get_audio_data - reads Red Book data off
+ the disc if playback is in progress and
+ converts it to 2 16-bit 44.1 kHz streams
+-------------------------------------------------*/
+
+static void get_audio_data(cdda_info *info, stream_sample_t *bufL, stream_sample_t *bufR, UINT32 samples_wanted)
+{
+ int i, sectoread, remaining;
+ INT16 *audio_cache = (INT16 *) info->audio_cache;
+
+ /* if no file, audio not playing, audio paused, or out of disc data,
+ just zero fill */
+ if (!info->disc || !info->audio_playing || info->audio_pause || (!info->audio_length && !info->audio_samples))
+ {
+ if( info->disc && info->audio_playing && !info->audio_pause && !info->audio_length )
+ {
+ info->audio_playing = FALSE;
+ info->audio_ended_normally = TRUE;
+ }
+
+ memset(bufL, 0, sizeof(stream_sample_t)*samples_wanted);
+ memset(bufR, 0, sizeof(stream_sample_t)*samples_wanted);
+ return;
+ }
+
+ /* if we've got enough samples, just feed 'em out */
+ if (samples_wanted <= info->audio_samples)
+ {
+ for (i = 0; i < samples_wanted; i++)
+ {
+ *bufL++ = audio_cache[ info->audio_bptr++ ];
+ *bufR++ = audio_cache[ info->audio_bptr++ ];
+ }
+
+ info->audio_samples -= samples_wanted;
+ return;
+ }
+
+ /* we don't have enough, so first feed what we've got */
+ for (i = 0; i < info->audio_samples; i++)
+ {
+ *bufL++ = audio_cache[ info->audio_bptr++ ];
+ *bufR++ = audio_cache[ info->audio_bptr++ ];
+ }
+
+ /* remember how much left for later */
+ remaining = samples_wanted - info->audio_samples;
+
+ /* reset the buffer and get what we can from the disc */
+ info->audio_samples = 0;
+ if (info->audio_length >= MAX_SECTORS)
+ {
+ sectoread = MAX_SECTORS;
+ }
+ else
+ {
+ sectoread = info->audio_length;
+ }
+
+ for (i = 0; i < sectoread; i++)
+ {
+ cdrom_read_data(info->disc, info->audio_lba, &info->audio_cache[CD_MAX_SECTOR_DATA*i], CD_TRACK_AUDIO);
+
+ info->audio_lba++;
+ }
+
+ info->audio_samples = (CD_MAX_SECTOR_DATA*sectoread)/4;
+ info->audio_length -= sectoread;
+
+ /* CD-DA data on the disc is big-endian, flip if we're not */
+ if (ENDIANNESS_NATIVE == ENDIANNESS_LITTLE)
+ {
+ for( i = 0; i < info->audio_samples * 2; i++ )
+ {
+ audio_cache[ i ] = BIG_ENDIANIZE_INT16( audio_cache[ i ] );
+ }
+ }
+
+ /* reset feedout ptr */
+ info->audio_bptr = 0;
+
+ /* we've got data, feed it out by calling ourselves recursively */
+ get_audio_data(info, bufL, bufR, remaining);
+}
+
+/*-------------------------------------------------
+ cdda_set_volume - sets CD-DA volume level
+ for both speakers, used for fade in/out effects
+-------------------------------------------------*/
+
+void cdda_set_volume(device_t *device,int volume)
+{
+ cdda_info *cdda = get_safe_token(device);
+
+ cdda->stream->set_output_gain(0,volume / 100.0);
+ cdda->stream->set_output_gain(1,volume / 100.0);
+}
+
+/*-------------------------------------------------
+ cdda_set_channel_volume - sets CD-DA volume level
+ for either speaker, used for fade in/out effects
+-------------------------------------------------*/
+
+void cdda_set_channel_volume(device_t *device, int channel, int volume)
+{
+ cdda_info *cdda = get_safe_token(device);
+
+ if(channel == 0)
+ cdda->stream->set_output_gain(0,volume / 100.0);
+ if(channel == 1)
+ cdda->stream->set_output_gain(1,volume / 100.0);
+}
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+DEVICE_GET_INFO( cdda )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(cdda_info); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( cdda ); break;
+ case DEVINFO_FCT_STOP: /* nothing */ break;
+ case DEVINFO_FCT_RESET: /* nothing */ break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "CD/DA"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "CD Audio"); 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;
+ }
+}
+
+
+DEFINE_LEGACY_SOUND_DEVICE(CDDA, cdda);
diff --git a/trunk/src/emu/sound/cdda.h b/trunk/src/emu/sound/cdda.h
new file mode 100644
index 00000000000..0c9c605978b
--- /dev/null
+++ b/trunk/src/emu/sound/cdda.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#ifndef __CDDA_H__
+#define __CDDA_H__
+
+#include "devlegcy.h"
+
+void cdda_set_cdrom(device_t *device, void *file);
+device_t *cdda_from_cdrom(running_machine &machine, void *file);
+
+void cdda_start_audio(device_t *device, UINT32 startlba, UINT32 numblocks);
+void cdda_stop_audio(device_t *device);
+void cdda_pause_audio(device_t *device, int pause);
+void cdda_set_volume(device_t *device, int volume);
+void cdda_set_channel_volume(device_t *device, int channel, int volume);
+
+UINT32 cdda_get_audio_lba(device_t *device);
+int cdda_audio_active(device_t *device);
+int cdda_audio_paused(device_t *device);
+int cdda_audio_ended(device_t *device);
+
+DECLARE_LEGACY_SOUND_DEVICE(CDDA, cdda);
+
+#endif /* __CDDA_H__ */
diff --git a/trunk/src/emu/sound/cdp1863.c b/trunk/src/emu/sound/cdp1863.c
new file mode 100644
index 00000000000..a89b7cb6c1f
--- /dev/null
+++ b/trunk/src/emu/sound/cdp1863.c
@@ -0,0 +1,199 @@
+/**********************************************************************
+
+ RCA CDP1863 CMOS 8-Bit Programmable Frequency Generator emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+/*
+
+ TODO:
+
+ - what happens if you connect both clocks?
+
+*/
+
+#include "cdp1863.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+
+#define CDP1863_DEFAULT_LATCH 0x35
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// devices
+const device_type CDP1863 = &device_creator<cdp1863_device>;
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// cdp1863_device - constructor
+//-------------------------------------------------
+
+cdp1863_device::cdp1863_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, CDP1863, "CDP1863", tag, owner, clock),
+ device_sound_interface(mconfig, *this),
+ m_stream(NULL),
+ m_clock1(clock),
+ m_clock2(0)
+{
+}
+
+
+//-------------------------------------------------
+// static_set_config - configuration helper
+//-------------------------------------------------
+
+void cdp1863_device::static_set_config(device_t &device, int clock2)
+{
+ cdp1863_device &cdp1863 = downcast<cdp1863_device &>(device);
+
+ cdp1863.m_clock2 = clock2;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void cdp1863_device::device_start()
+{
+ // create sound stream
+ m_stream = machine().sound().stream_alloc(*this, 0, 1, machine().sample_rate());
+
+ // register for state saving
+ save_item(NAME(m_clock1));
+ save_item(NAME(m_clock2));
+ save_item(NAME(m_oe));
+ save_item(NAME(m_latch));
+ save_item(NAME(m_signal));
+ save_item(NAME(m_incr));
+}
+
+
+//-------------------------------------------------
+// sound_stream_update - handle update requests for
+// our sound stream
+//-------------------------------------------------
+
+void cdp1863_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+{
+ // reset the output stream
+ memset(outputs[0], 0, samples * sizeof(*outputs[0]));
+
+ INT16 signal = m_signal;
+ stream_sample_t *buffer = outputs[0];
+
+ memset( buffer, 0, samples * sizeof(*buffer) );
+
+ if (m_oe)
+ {
+ double frequency;
+ int rate = machine().sample_rate() / 2;
+
+ // get progress through wave
+ int incr = m_incr;
+
+ if (m_clock1 > 0)
+ {
+ // CLK1 is pre-divided by 4
+ frequency = m_clock1 / 4 / (m_latch + 1) / 2;
+ }
+ else
+ {
+ // CLK2 is pre-divided by 8
+ frequency = m_clock2 / 8 / (m_latch + 1) / 2;
+ }
+
+ if (signal < 0)
+ {
+ signal = -0x7fff;
+ }
+ else
+ {
+ signal = 0x7fff;
+ }
+
+ while( samples-- > 0 )
+ {
+ *buffer++ = signal;
+ incr -= frequency;
+ while( incr < 0 )
+ {
+ incr += rate;
+ signal = -signal;
+ }
+ }
+
+ // store progress through wave
+ m_incr = incr;
+ m_signal = signal;
+ }
+}
+
+
+//-------------------------------------------------
+// str_w - latch write
+//-------------------------------------------------
+
+WRITE8_MEMBER( cdp1863_device::str_w )
+{
+ m_latch = data;
+}
+
+
+//-------------------------------------------------
+// str_w - latch write
+//-------------------------------------------------
+
+void cdp1863_device::str_w(UINT8 data)
+{
+ m_latch = data;
+}
+
+
+//-------------------------------------------------
+// oe_w - output enable write
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( cdp1863_device::oe_w )
+{
+ m_oe = state;
+}
+
+
+//-------------------------------------------------
+// set_clk1 - set clock 1
+//-------------------------------------------------
+
+void cdp1863_device::set_clk1(int clock)
+{
+ m_clock1 = clock;
+}
+
+
+//-------------------------------------------------
+// set_clk2 - set clock 2
+//-------------------------------------------------
+
+void cdp1863_device::set_clk2(int clock)
+{
+ m_clock2 = clock;
+}
diff --git a/trunk/src/emu/sound/cdp1863.h b/trunk/src/emu/sound/cdp1863.h
new file mode 100644
index 00000000000..89cafea2bf2
--- /dev/null
+++ b/trunk/src/emu/sound/cdp1863.h
@@ -0,0 +1,90 @@
+/**********************************************************************
+
+ RCA CDP1863 CMOS 8-Bit Programmable Frequency Generator emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ _RESET 1 |* \_/ | 16 Vdd
+ CLK 2 2 | | 15 OE
+ CLK 1 3 | | 14 OUT
+ STR 4 | CDP1863 | 13 DO7
+ DI0 5 | | 12 DI6
+ DI1 6 | | 11 DI5
+ DI2 7 | | 10 DI4
+ Vss 8 |_____________| 9 DI3
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __CDP1863__
+#define __CDP1863__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_CDP1863_ADD(_tag, _clock, _clock2) \
+ MCFG_DEVICE_ADD(_tag, CDP1863, _clock) \
+ cdp1863_device::static_set_config(*device, _clock2);
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> cdp1863_device
+
+class cdp1863_device : public device_t,
+ public device_sound_interface
+{
+public:
+ // construction/destruction
+ cdp1863_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // inline configuration helpers
+ static void static_set_config(device_t &device, int clock2);
+
+ DECLARE_WRITE8_MEMBER( str_w );
+ void str_w(UINT8 data);
+
+ DECLARE_WRITE_LINE_MEMBER( oe_w );
+
+ void set_clk1(int clock);
+ void set_clk2(int clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+
+ // internal callbacks
+ virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
+
+private:
+ sound_stream *m_stream;
+
+ int m_clock1; // clock 1
+ int m_clock2; // clock 2
+
+ // sound state
+ int m_oe; // output enable
+ int m_latch; // sound latch
+ INT16 m_signal; // current signal
+ int m_incr; // initial wave state
+};
+
+
+// device type definition
+extern const device_type CDP1863;
+
+
+
+#endif
diff --git a/trunk/src/emu/sound/cdp1864.c b/trunk/src/emu/sound/cdp1864.c
new file mode 100644
index 00000000000..7fdd811c02d
--- /dev/null
+++ b/trunk/src/emu/sound/cdp1864.c
@@ -0,0 +1,484 @@
+/**********************************************************************
+
+ RCA CDP1864C COS/MOS PAL Compatible Color TV Interface
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+/*
+
+ TODO:
+
+ - interlace mode
+ - PAL output, currently using RGB
+ - cpu synchronization
+
+ SC1 and SC0 are used to provide CDP1864C-to-CPU synchronization for a jitter-free display.
+ During every horizontal sync the CDP1864C samples SC0 and SC1 for SC0 = 1 and SC1 = 0
+ (CDP1800 execute state). Detection of a fetch cycle causes the CDP1864C to skip cycles to
+ attain synchronization. (i.e. picture moves 8 pixels to the right)
+
+*/
+
+
+#include "emu.h"
+#include "cdp1864.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define CDP1864_DEFAULT_LATCH 0x35
+
+#define CDP1864_CYCLES_DMA_START 2*8
+#define CDP1864_CYCLES_DMA_ACTIVE 8*8
+#define CDP1864_CYCLES_DMA_WAIT 6*8
+
+static const int CDP1864_BACKGROUND_COLOR_SEQUENCE[] = { 2, 0, 1, 4 };
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// devices
+const device_type CDP1864 = &device_creator<cdp1864_device>;
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// initialize_palette -
+//-------------------------------------------------
+
+inline void cdp1864_device::initialize_palette()
+{
+ double res_total = m_res_r + m_res_g + m_res_b + m_res_bkg;
+
+ int weight_r = (m_res_r / res_total) * 100;
+ int weight_g = (m_res_g / res_total) * 100;
+ int weight_b = (m_res_b / res_total) * 100;
+ int weight_bkg = (m_res_bkg / res_total) * 100;
+
+ for (int i = 0; i < 16; i++)
+ {
+ int luma = 0;
+
+ luma += (i & 4) ? weight_r : 0;
+ luma += (i & 1) ? weight_g : 0;
+ luma += (i & 2) ? weight_b : 0;
+ luma += (i & 8) ? 0 : weight_bkg;
+
+ luma = (luma * 0xff) / 100;
+
+ int r = (i & 4) ? luma : 0;
+ int g = (i & 1) ? luma : 0;
+ int b = (i & 2) ? luma : 0;
+
+ palette_set_color_rgb(machine(), i, r, g, b);
+ }
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// cdp1864_device - constructor
+//-------------------------------------------------
+
+cdp1864_device::cdp1864_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, CDP1864, "CDP1864", tag, owner, clock),
+ device_sound_interface(mconfig, *this),
+ m_disp(0),
+ m_dmaout(0),
+ m_bgcolor(0),
+ m_con(0),
+ m_aoe(0),
+ m_latch(CDP1864_DEFAULT_LATCH)
+{
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void cdp1864_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const cdp1864_interface *intf = reinterpret_cast<const cdp1864_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<cdp1864_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_in_inlace_cb, 0, sizeof(m_in_inlace_cb));
+ memset(&m_in_rdata_cb, 0, sizeof(m_in_rdata_cb));
+ memset(&m_in_bdata_cb, 0, sizeof(m_in_bdata_cb));
+ memset(&m_in_gdata_cb, 0, sizeof(m_in_gdata_cb));
+ memset(&m_out_int_cb, 0, sizeof(m_out_int_cb));
+ memset(&m_out_dmao_cb, 0, sizeof(m_out_dmao_cb));
+ memset(&m_out_efx_cb, 0, sizeof(m_out_efx_cb));
+ memset(&m_out_hsync_cb, 0, sizeof(m_out_hsync_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void cdp1864_device::device_start()
+{
+ // resolve callbacks
+ m_in_inlace_func.resolve(m_in_inlace_cb, *this);
+ m_in_rdata_func.resolve(m_in_rdata_cb, *this);
+ m_in_bdata_func.resolve(m_in_bdata_cb, *this);
+ m_in_gdata_func.resolve(m_in_gdata_cb, *this);
+ m_out_int_func.resolve(m_out_int_cb, *this);
+ m_out_dmao_func.resolve(m_out_dmao_cb, *this);
+ m_out_efx_func.resolve(m_out_efx_cb, *this);
+ m_out_hsync_func.resolve(m_out_hsync_cb, *this);
+
+ // initialize palette
+ initialize_palette();
+
+ // create sound stream
+ m_stream = machine().sound().stream_alloc(*this, 0, 1, machine().sample_rate());
+
+ // allocate timers
+ m_int_timer = timer_alloc(TIMER_INT);
+ m_efx_timer = timer_alloc(TIMER_EFX);
+ m_dma_timer = timer_alloc(TIMER_DMA);
+ m_hsync_timer = timer_alloc(TIMER_HSYNC);
+
+ // find devices
+ m_cpu = machine().device<cpu_device>(m_cpu_tag);
+ m_screen = machine().device<screen_device>(m_screen_tag);
+ m_bitmap = auto_bitmap_alloc(machine(), m_screen->width(), m_screen->height(), m_screen->format());
+
+ // register for state saving
+ save_item(NAME(m_disp));
+ save_item(NAME(m_dmaout));
+ save_item(NAME(m_bgcolor));
+ save_item(NAME(m_con));
+ save_item(NAME(m_aoe));
+ save_item(NAME(m_latch));
+ save_item(NAME(m_signal));
+ save_item(NAME(m_incr));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void cdp1864_device::device_reset()
+{
+ m_int_timer->adjust(m_screen->time_until_pos(CDP1864_SCANLINE_INT_START, 0));
+ m_efx_timer->adjust(m_screen->time_until_pos(CDP1864_SCANLINE_EFX_TOP_START, 0));
+ m_dma_timer->adjust(m_cpu->cycles_to_attotime(CDP1864_CYCLES_DMA_START));
+
+ m_disp = 0;
+ m_dmaout = 0;
+
+ m_out_int_func(CLEAR_LINE);
+ m_out_dmao_func(CLEAR_LINE);
+ m_out_efx_func(CLEAR_LINE);
+}
+
+
+//-------------------------------------------------
+// device_timer - handle timer events
+//-------------------------------------------------
+
+void cdp1864_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ int scanline = m_screen->vpos();
+
+ switch (id)
+ {
+ case TIMER_INT:
+ if (scanline == CDP1864_SCANLINE_INT_START)
+ {
+ if (m_disp)
+ {
+ m_out_int_func(ASSERT_LINE);
+ }
+
+ m_int_timer->adjust(m_screen->time_until_pos( CDP1864_SCANLINE_INT_END, 0));
+ }
+ else
+ {
+ if (m_disp)
+ {
+ m_out_int_func(CLEAR_LINE);
+ }
+
+ m_int_timer->adjust(m_screen->time_until_pos(CDP1864_SCANLINE_INT_START, 0));
+ }
+ break;
+
+ case TIMER_EFX:
+ switch (scanline)
+ {
+ case CDP1864_SCANLINE_EFX_TOP_START:
+ m_out_efx_func(ASSERT_LINE);
+ m_efx_timer->adjust(m_screen->time_until_pos(CDP1864_SCANLINE_EFX_TOP_END, 0));
+ break;
+
+ case CDP1864_SCANLINE_EFX_TOP_END:
+ m_out_efx_func(CLEAR_LINE);
+ m_efx_timer->adjust(m_screen->time_until_pos(CDP1864_SCANLINE_EFX_BOTTOM_START, 0));
+ break;
+
+ case CDP1864_SCANLINE_EFX_BOTTOM_START:
+ m_out_efx_func(ASSERT_LINE);
+ m_efx_timer->adjust(m_screen->time_until_pos(CDP1864_SCANLINE_EFX_BOTTOM_END, 0));
+ break;
+
+ case CDP1864_SCANLINE_EFX_BOTTOM_END:
+ m_out_efx_func(CLEAR_LINE);
+ m_efx_timer->adjust(m_screen->time_until_pos(CDP1864_SCANLINE_EFX_TOP_START, 0));
+ break;
+ }
+ break;
+
+ case TIMER_DMA:
+ if (m_dmaout)
+ {
+ if (m_disp)
+ {
+ if (scanline >= CDP1864_SCANLINE_DISPLAY_START && scanline < CDP1864_SCANLINE_DISPLAY_END)
+ {
+ m_out_dmao_func(CLEAR_LINE);
+ }
+ }
+
+ m_dma_timer->adjust(m_cpu->cycles_to_attotime(CDP1864_CYCLES_DMA_WAIT));
+
+ m_dmaout = 0;
+ }
+ else
+ {
+ if (m_disp)
+ {
+ if (scanline >= CDP1864_SCANLINE_DISPLAY_START && scanline < CDP1864_SCANLINE_DISPLAY_END)
+ {
+ m_out_dmao_func(ASSERT_LINE);
+ }
+ }
+
+ m_dma_timer->adjust(m_cpu->cycles_to_attotime(CDP1864_CYCLES_DMA_ACTIVE));
+
+ m_dmaout = 1;
+ }
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// sound_stream_update - handle update requests for
+// our sound stream
+//-------------------------------------------------
+
+void cdp1864_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+{
+ // reset the output stream
+ memset(outputs[0], 0, samples * sizeof(*outputs[0]));
+
+ INT16 signal = m_signal;
+ stream_sample_t *buffer = outputs[0];
+
+ memset( buffer, 0, samples * sizeof(*buffer) );
+
+ if (m_aoe)
+ {
+ double frequency = m_cpu->unscaled_clock() / 8 / 4 / (m_latch + 1) / 2;
+ int rate = machine().sample_rate() / 2;
+
+ /* get progress through wave */
+ int incr = m_incr;
+
+ if (signal < 0)
+ {
+ signal = -0x7fff;
+ }
+ else
+ {
+ signal = 0x7fff;
+ }
+
+ while( samples-- > 0 )
+ {
+ *buffer++ = signal;
+ incr -= frequency;
+ while( incr < 0 )
+ {
+ incr += rate;
+ signal = -signal;
+ }
+ }
+
+ /* store progress through wave */
+ m_incr = incr;
+ m_signal = signal;
+ }
+}
+
+
+//-------------------------------------------------
+// dispon_r -
+//-------------------------------------------------
+
+READ8_MEMBER( cdp1864_device::dispon_r )
+{
+ m_disp = 1;
+
+ return 0xff;
+}
+
+
+//-------------------------------------------------
+// dispoff_r -
+//-------------------------------------------------
+
+READ8_MEMBER( cdp1864_device::dispoff_r )
+{
+ m_disp = 0;
+
+ m_out_int_func(CLEAR_LINE);
+ m_out_dmao_func(CLEAR_LINE);
+
+ return 0xff;
+}
+
+
+//-------------------------------------------------
+// step_bgcolor_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( cdp1864_device::step_bgcolor_w )
+{
+ m_disp = 1;
+
+ m_bgcolor++;
+
+ if (m_bgcolor > 3)
+ {
+ m_bgcolor = 0;
+ }
+}
+
+
+//-------------------------------------------------
+// tone_latch_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( cdp1864_device::tone_latch_w )
+{
+ m_latch = data;
+}
+
+
+//-------------------------------------------------
+// dma_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( cdp1864_device::dma_w )
+{
+ int rdata = 1, bdata = 1, gdata = 1;
+ int sx = m_screen->hpos() + 4;
+ int y = m_screen->vpos();
+
+ if (!m_con)
+ {
+ rdata = m_in_rdata_func();
+ bdata = m_in_bdata_func();
+ gdata = m_in_gdata_func();
+ }
+
+ for (int x = 0; x < 8; x++)
+ {
+ int color = CDP1864_BACKGROUND_COLOR_SEQUENCE[m_bgcolor] + 8;
+
+ if (BIT(data, 7))
+ {
+ color = (gdata << 2) | (bdata << 1) | rdata;
+ }
+
+ *BITMAP_ADDR16(m_bitmap, y, sx + x) = color;
+
+ data <<= 1;
+ }
+}
+
+
+//-------------------------------------------------
+// con_w - color on write
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( cdp1864_device::con_w )
+{
+ if (!state)
+ {
+ m_con = 0;
+ }
+}
+
+
+//-------------------------------------------------
+// aoe_w - audio output enable write
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( cdp1864_device::aoe_w )
+{
+ if (!state)
+ {
+ m_latch = CDP1864_DEFAULT_LATCH;
+ }
+
+ m_aoe = state;
+}
+
+
+//-------------------------------------------------
+// evs_w - external vertical sync write
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( cdp1864_device::evs_w )
+{
+}
+
+
+//-------------------------------------------------
+// update_screen -
+//-------------------------------------------------
+
+void cdp1864_device::update_screen(bitmap_t *bitmap, const rectangle *cliprect)
+{
+ if (m_disp)
+ {
+ copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
+ bitmap_fill(m_bitmap, cliprect, CDP1864_BACKGROUND_COLOR_SEQUENCE[m_bgcolor] + 8);
+ }
+ else
+ {
+ bitmap_fill(bitmap, cliprect, get_black_pen(machine()));
+ }
+}
diff --git a/trunk/src/emu/sound/cdp1864.h b/trunk/src/emu/sound/cdp1864.h
new file mode 100644
index 00000000000..09d6d9d161f
--- /dev/null
+++ b/trunk/src/emu/sound/cdp1864.h
@@ -0,0 +1,218 @@
+/**********************************************************************
+
+ RCA CDP1864C COS/MOS PAL Compatible Color TV Interface
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ INLACE 1 |* \_/ | 40 Vdd
+ CLK IN_ 2 | | 39 AUD
+ CLR OUT_ 3 | | 38 CLR IN_
+ AOE 4 | | 37 DMA0_
+ SC1 5 | | 36 INT_
+ SC0 6 | | 35 TPA
+ MRD_ 7 | | 34 TPB
+ BUS 7 8 | | 33 EVS
+ BUS 6 9 | | 32 V SYNC
+ BUS 5 10 | CDP1864 | 31 H SYNC
+ BUS 4 11 | | 30 C SYNC_
+ BUS 3 12 | | 29 RED
+ BUS 2 13 | | 28 BLUE
+ BUS 1 14 | | 27 GREEN
+ BUS 0 15 | | 26 BCK GND_
+ CON_ 16 | | 25 BURST
+ N2 17 | | 24 ALT
+ EF_ 18 | | 23 R DATA
+ N0 19 | | 22 G DATA
+ Vss 20 |_____________| 21 B DATA
+
+
+ http://homepage.mac.com/ruske/cosmacelf/cdp1864.pdf
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __CDP1864__
+#define __CDP1864__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define CDP1864_CLOCK XTAL_1_75MHz
+
+#define CDP1864_VISIBLE_COLUMNS 64
+#define CDP1864_VISIBLE_LINES 192
+
+#define CDP1864_HBLANK_END 1 * 8
+#define CDP1864_HBLANK_START 13 * 8
+#define CDP1864_HSYNC_START 0 * 8
+#define CDP1864_HSYNC_END 1 * 8
+#define CDP1864_SCREEN_START 4 * 8
+#define CDP1864_SCREEN_END 12 * 8
+#define CDP1864_SCREEN_WIDTH 14 * 8
+
+#define CDP1864_TOTAL_SCANLINES 312
+
+#define CDP1864_SCANLINE_VBLANK_START CDP1864_TOTAL_SCANLINES - 4
+#define CDP1864_SCANLINE_VBLANK_END 20
+#define CDP1864_SCANLINE_VSYNC_START 0
+#define CDP1864_SCANLINE_VSYNC_END 4
+#define CDP1864_SCANLINE_DISPLAY_START 60 // ???
+#define CDP1864_SCANLINE_DISPLAY_END CDP1864_SCANLINE_DISPLAY_START + CDP1864_VISIBLE_LINES
+#define CDP1864_SCANLINE_INT_START CDP1864_SCANLINE_DISPLAY_START - 2
+#define CDP1864_SCANLINE_INT_END CDP1864_SCANLINE_DISPLAY_START
+#define CDP1864_SCANLINE_EFX_TOP_START CDP1864_SCANLINE_DISPLAY_START - 4
+#define CDP1864_SCANLINE_EFX_TOP_END CDP1864_SCANLINE_DISPLAY_START
+#define CDP1864_SCANLINE_EFX_BOTTOM_START CDP1864_SCANLINE_DISPLAY_END - 4
+#define CDP1864_SCANLINE_EFX_BOTTOM_END CDP1864_SCANLINE_DISPLAY_END
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_CDP1864_ADD(_tag, _clock, _config) \
+ MCFG_SOUND_ADD(_tag, CDP1864, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+
+#define MCFG_CDP1864_SCREEN_ADD(_tag, _clock) \
+ MCFG_SCREEN_ADD(_tag, RASTER) \
+ MCFG_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) \
+ MCFG_SCREEN_RAW_PARAMS(_clock, CDP1864_SCREEN_WIDTH, CDP1864_HBLANK_END, CDP1864_HBLANK_START, CDP1864_TOTAL_SCANLINES, CDP1864_SCANLINE_VBLANK_END, CDP1864_SCANLINE_VBLANK_START)
+
+
+#define CDP1864_INTERFACE(name) \
+ const cdp1864_interface (name) =
+
+
+#define CDP1864_NON_INTERLACED \
+ DEVCB_LINE_VCC
+
+
+#define CDP1864_INTERLACED \
+ DEVCB_LINE_GND
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> cdp1864_interface
+
+struct cdp1864_interface
+{
+ const char *m_cpu_tag;
+ const char *m_screen_tag;
+
+ devcb_read_line m_in_inlace_cb;
+
+ devcb_read_line m_in_rdata_cb;
+ devcb_read_line m_in_bdata_cb;
+ devcb_read_line m_in_gdata_cb;
+
+ devcb_write_line m_out_int_cb;
+ devcb_write_line m_out_dmao_cb;
+ devcb_write_line m_out_efx_cb;
+ devcb_write_line m_out_hsync_cb;
+
+ double m_res_r; // red output resistor value
+ double m_res_g; // green output resistor value
+ double m_res_b; // blue output resistor value
+ double m_res_bkg; // background output resistor value
+};
+
+
+
+// ======================> cdp1864_device
+
+class cdp1864_device : public device_t,
+ public device_sound_interface,
+ public cdp1864_interface
+{
+public:
+ // construction/destruction
+ cdp1864_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_READ8_MEMBER( dispon_r );
+ DECLARE_READ8_MEMBER( dispoff_r );
+
+ DECLARE_WRITE8_MEMBER( step_bgcolor_w );
+ DECLARE_WRITE8_MEMBER( tone_latch_w );
+
+ DECLARE_WRITE8_MEMBER( dma_w );
+
+ DECLARE_WRITE_LINE_MEMBER( con_w );
+ DECLARE_WRITE_LINE_MEMBER( aoe_w );
+ DECLARE_WRITE_LINE_MEMBER( evs_w );
+
+ void update_screen(bitmap_t *bitmap, const rectangle *cliprect);
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+ // internal callbacks
+ virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
+
+private:
+ inline void initialize_palette();
+
+ static const device_timer_id TIMER_INT = 0;
+ static const device_timer_id TIMER_EFX = 1;
+ static const device_timer_id TIMER_DMA = 2;
+ static const device_timer_id TIMER_HSYNC = 3;
+
+ devcb_resolved_read_line m_in_inlace_func;
+ devcb_resolved_read_line m_in_rdata_func;
+ devcb_resolved_read_line m_in_bdata_func;
+ devcb_resolved_read_line m_in_gdata_func;
+ devcb_resolved_write_line m_out_int_func;
+ devcb_resolved_write_line m_out_dmao_func;
+ devcb_resolved_write_line m_out_efx_func;
+ devcb_resolved_write_line m_out_hsync_func;
+
+ cpu_device *m_cpu;
+ screen_device *m_screen; // screen
+ bitmap_t *m_bitmap; // bitmap
+ sound_stream *m_stream; // sound output
+
+ // video state
+ int m_disp; // display on
+ int m_dmaout; // DMA request active
+ int m_bgcolor; // background color
+ int m_con; // color on
+
+ // sound state
+ int m_aoe; // audio on
+ int m_latch; // sound latch
+ INT16 m_signal; // current signal
+ int m_incr; // initial wave state
+
+ // timers
+ emu_timer *m_int_timer;
+ emu_timer *m_efx_timer;
+ emu_timer *m_dma_timer;
+ emu_timer *m_hsync_timer;
+};
+
+
+// device type definition
+extern const device_type CDP1864;
+
+
+
+#endif
diff --git a/trunk/src/emu/sound/cdp1869.c b/trunk/src/emu/sound/cdp1869.c
new file mode 100644
index 00000000000..5387abdf30a
--- /dev/null
+++ b/trunk/src/emu/sound/cdp1869.c
@@ -0,0 +1,976 @@
+/**********************************************************************
+
+ RCA CDP1869/1870/1876 Video Interface System (VIS) emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+/*
+
+ TODO:
+
+ - white noise
+ - scanline based update
+ - CMSEL output
+
+*/
+
+#include "emu.h"
+#include "cdp1869.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+#define CDP1869_WEIGHT_RED 30 // % of max luminance
+#define CDP1869_WEIGHT_GREEN 59
+#define CDP1869_WEIGHT_BLUE 11
+
+#define CDP1869_COLUMNS_HALF 20
+#define CDP1869_COLUMNS_FULL 40
+#define CDP1869_ROWS_HALF 12
+#define CDP1869_ROWS_FULL_PAL 25
+#define CDP1869_ROWS_FULL_NTSC 24
+
+enum
+{
+ CDB0 = 0,
+ CDB1,
+ CDB2,
+ CDB3,
+ CDB4,
+ CDB5,
+ CCB0,
+ CCB1
+};
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+const device_type CDP1869 = &device_creator<cdp1869_device>;
+
+// default address map
+static ADDRESS_MAP_START( cdp1869, AS_0, 8 )
+ AM_RANGE(0x000, 0x7ff) AM_RAM
+ADDRESS_MAP_END
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// is_ntsc - is device in NTSC mode
+//-------------------------------------------------
+
+inline bool cdp1869_device::is_ntsc()
+{
+ return m_in_pal_ntsc_func() ? false : true;
+}
+
+
+//-------------------------------------------------
+// read_page_ram_byte - read a page RAM byte at
+// the given address
+//-------------------------------------------------
+
+inline UINT8 cdp1869_device::read_page_ram_byte(offs_t pma)
+{
+ return space()->read_byte(pma);
+}
+
+
+//-------------------------------------------------
+// write_page_ram_byte - write a page RAM byte at
+// the given address
+//-------------------------------------------------
+
+inline void cdp1869_device::write_page_ram_byte(offs_t pma, UINT8 data)
+{
+ space()->write_byte(pma, data);
+}
+
+
+//-------------------------------------------------
+// read_char_ram_byte - read a char RAM byte at
+// the given address
+//-------------------------------------------------
+
+inline UINT8 cdp1869_device::read_char_ram_byte(offs_t pma, offs_t cma, UINT8 pmd)
+{
+ UINT8 data = 0;
+
+ if (m_in_char_ram_func != NULL)
+ {
+ data = m_in_char_ram_func(this, pma, cma, pmd);
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// write_char_ram_byte - write a char RAM byte at
+// the given address
+//-------------------------------------------------
+
+inline void cdp1869_device::write_char_ram_byte(offs_t pma, offs_t cma, UINT8 pmd, UINT8 data)
+{
+ if (m_out_char_ram_func != NULL)
+ {
+ m_out_char_ram_func(this, pma, cma, pmd, data);
+ }
+}
+
+
+//-------------------------------------------------
+// read_pcb - read page control bit
+//-------------------------------------------------
+
+inline int cdp1869_device::read_pcb(offs_t pma, offs_t cma, UINT8 pmd)
+{
+ int pcb = 0;
+
+ if (m_in_pcb_func != NULL)
+ {
+ pcb = m_in_pcb_func(this, pma, cma, pmd);
+ }
+
+ return pcb;
+}
+
+
+//-------------------------------------------------
+// update_prd_changed_timer -
+//-------------------------------------------------
+
+inline void cdp1869_device::update_prd_changed_timer()
+{
+ int start = CDP1869_SCANLINE_PREDISPLAY_START_PAL;
+ int end = CDP1869_SCANLINE_PREDISPLAY_END_PAL;
+ int next_state;
+ int scanline = m_screen->vpos();
+ int next_scanline;
+
+ if (is_ntsc())
+ {
+ start = CDP1869_SCANLINE_PREDISPLAY_START_NTSC;
+ end = CDP1869_SCANLINE_PREDISPLAY_END_NTSC;
+ }
+
+ if (scanline < start)
+ {
+ next_scanline = start;
+ next_state = ASSERT_LINE;
+ }
+ else if (scanline < end)
+ {
+ next_scanline = end;
+ next_state = CLEAR_LINE;
+ }
+ else
+ {
+ next_scanline = start;
+ next_state = ASSERT_LINE;
+ }
+
+ if (m_dispoff)
+ {
+ next_state = CLEAR_LINE;
+ }
+
+ attotime duration = m_screen->time_until_pos(next_scanline);
+ m_prd_timer->adjust(duration, next_state);
+}
+
+
+//-------------------------------------------------
+// get_rgb - get RGB value
+//-------------------------------------------------
+
+inline rgb_t cdp1869_device::get_rgb(int i, int c, int l)
+{
+ int luma = 0, r, g, b;
+
+ luma += (l & 4) ? CDP1869_WEIGHT_RED : 0;
+ luma += (l & 1) ? CDP1869_WEIGHT_GREEN : 0;
+ luma += (l & 2) ? CDP1869_WEIGHT_BLUE : 0;
+
+ luma = (luma * 0xff) / 100;
+
+ r = (c & 4) ? luma : 0;
+ g = (c & 1) ? luma : 0;
+ b = (c & 2) ? luma : 0;
+
+ return MAKE_RGB(r, g, b);
+}
+
+
+//-------------------------------------------------
+// get_lines - get number of character lines
+//-------------------------------------------------
+
+inline int cdp1869_device::get_lines()
+{
+ if (m_line16 && !m_dblpage)
+ {
+ return 16;
+ }
+ else if (!m_line9)
+ {
+ return 9;
+ }
+ else
+ {
+ return 8;
+ }
+}
+
+
+//-------------------------------------------------
+// get_pmemsize - get page memory size
+//-------------------------------------------------
+
+inline UINT16 cdp1869_device::get_pmemsize(int cols, int rows)
+{
+ int pmemsize = cols * rows;
+
+ if (m_dblpage) pmemsize *= 2;
+ if (m_line16) pmemsize *= 2;
+
+ return pmemsize;
+}
+
+
+//-------------------------------------------------
+// get_pma - get page memory address
+//-------------------------------------------------
+
+inline UINT16 cdp1869_device::get_pma()
+{
+ if (m_dblpage)
+ {
+ return m_pma;
+ }
+ else
+ {
+ return m_pma & 0x3ff;
+ }
+}
+
+
+//-------------------------------------------------
+// get_pen - get pen for color bits
+//-------------------------------------------------
+
+inline int cdp1869_device::get_pen(int ccb0, int ccb1, int pcb)
+{
+ int r = 0, g = 0, b = 0;
+
+ switch (m_col)
+ {
+ case 0:
+ r = ccb0;
+ b = ccb1;
+ g = pcb;
+ break;
+
+ case 1:
+ r = ccb0;
+ b = pcb;
+ g = ccb1;
+ break;
+
+ case 2:
+ case 3:
+ r = pcb;
+ b = ccb0;
+ g = ccb1;
+ break;
+ }
+
+ int color = (r << 2) + (b << 1) + g;
+
+ if (m_cfc)
+ {
+ return color + ((m_bkg + 1) * 8);
+ }
+ else
+ {
+ return color;
+ }
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// cdp1869_device - constructor
+//-------------------------------------------------
+
+cdp1869_device::cdp1869_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, CDP1869, "RCA CDP1869", tag, owner, clock),
+ device_sound_interface(mconfig, *this),
+ device_memory_interface(mconfig, *this),
+ m_stream(NULL),
+ m_space_config("pageram", ENDIANNESS_LITTLE, 8, 11, 0, NULL, *ADDRESS_MAP_NAME(cdp1869))
+{
+
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void cdp1869_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const cdp1869_interface *intf = reinterpret_cast<const cdp1869_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<cdp1869_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&in_pal_ntsc_cb, 0, sizeof(in_pal_ntsc_cb));
+ memset(&out_prd_cb, 0, sizeof(out_prd_cb));
+ in_pcb_cb = NULL;
+ in_char_ram_cb = NULL;
+ out_char_ram_cb = NULL;
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void cdp1869_device::device_start()
+{
+ // get the screen device
+ m_screen = machine().device<screen_device>(screen_tag);
+ assert(m_screen != NULL);
+
+ // resolve callbacks
+ m_in_pal_ntsc_func.resolve(in_pal_ntsc_cb, *this);
+ m_out_prd_func.resolve(out_prd_cb, *this);
+ m_in_pcb_func = in_pcb_cb;
+ m_in_char_ram_func = in_char_ram_cb;
+ m_out_char_ram_func = out_char_ram_cb;
+
+ // allocate timers
+ m_prd_timer = timer_alloc();
+ update_prd_changed_timer();
+
+ // initialize palette
+ initialize_palette();
+
+ // create sound stream
+ m_stream = machine().sound().stream_alloc(*this, 0, 1, machine().sample_rate());
+
+ // register for state saving
+ save_item(NAME(m_prd));
+ save_item(NAME(m_dispoff));
+ save_item(NAME(m_fresvert));
+ save_item(NAME(m_freshorz));
+ save_item(NAME(m_cmem));
+ save_item(NAME(m_dblpage));
+ save_item(NAME(m_line16));
+ save_item(NAME(m_line9));
+ save_item(NAME(m_cfc));
+ save_item(NAME(m_col));
+ save_item(NAME(m_bkg));
+ save_item(NAME(m_pma));
+ save_item(NAME(m_hma));
+ save_item(NAME(m_signal));
+ save_item(NAME(m_incr));
+ save_item(NAME(m_toneoff));
+ save_item(NAME(m_wnoff));
+ save_item(NAME(m_tonediv));
+ save_item(NAME(m_tonefreq));
+ save_item(NAME(m_toneamp));
+ save_item(NAME(m_wnfreq));
+ save_item(NAME(m_wnamp));
+}
+
+
+//-------------------------------------------------
+// device_post_load - device-specific post-load
+//-------------------------------------------------
+
+void cdp1869_device::device_post_load()
+{
+ update_prd_changed_timer();
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void cdp1869_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ m_out_prd_func(param);
+ m_prd = param;
+
+ update_prd_changed_timer();
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return a description of
+// any address spaces owned by this device
+//-------------------------------------------------
+
+const address_space_config *cdp1869_device::memory_space_config(address_spacenum spacenum) const
+{
+ return (spacenum == 0) ? &m_space_config : NULL;
+}
+
+
+//-------------------------------------------------
+// initialize_palette - initialize palette
+//-------------------------------------------------
+
+void cdp1869_device::initialize_palette()
+{
+ // color-on-color display (CFC=0)
+ int i;
+
+ for (i = 0; i < 8; i++)
+ {
+ palette_set_color(machine(), i, get_rgb(i, i, 15));
+ }
+
+ // tone-on-tone display (CFC=1)
+ for (int c = 0; c < 8; c++)
+ {
+ for (int l = 0; l < 8; l++)
+ {
+ palette_set_color(machine(), i, get_rgb(i, c, l));
+ i++;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// sound_stream_update - handle update requests for
+// our sound stream
+//-------------------------------------------------
+
+void cdp1869_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+{
+ // reset the output stream
+ memset(outputs[0], 0, samples * sizeof(*outputs[0]));
+
+ INT16 signal = m_signal;
+ stream_sample_t *buffer = outputs[0];
+
+ if (!m_toneoff && m_toneamp)
+ {
+ double frequency = (clock() / 2) / (512 >> m_tonefreq) / (m_tonediv + 1);
+// double amplitude = m_toneamp * ((0.78*5) / 15);
+
+ int rate = machine().sample_rate() / 2;
+
+ /* get progress through wave */
+ int incr = m_incr;
+
+ if (signal < 0)
+ {
+ signal = -(m_toneamp * (0x07fff / 15));
+ }
+ else
+ {
+ signal = m_toneamp * (0x07fff / 15);
+ }
+
+ while( samples-- > 0 )
+ {
+ *buffer++ = signal;
+ incr -= frequency;
+ while( incr < 0 )
+ {
+ incr += rate;
+ signal = -signal;
+ }
+ }
+
+ /* store progress through wave */
+ m_incr = incr;
+ m_signal = signal;
+ }
+/*
+ if (!m_wnoff)
+ {
+ double amplitude = m_wnamp * ((0.78*5) / 15);
+
+ for (int wndiv = 0; wndiv < 128; wndiv++)
+ {
+ double frequency = (clock() / 2) / (4096 >> m_wnfreq) / (wndiv + 1):
+
+ sum_square_wave(buffer, frequency, amplitude);
+ }
+ }
+*/
+
+}
+
+
+//-------------------------------------------------
+// draw_line - draw character line
+//-------------------------------------------------
+
+void cdp1869_device::draw_line(bitmap_t *bitmap, const rectangle *rect, int x, int y, UINT8 data, int color)
+{
+ int i;
+
+ data <<= 2;
+
+ for (i = 0; i < CDP1869_CHAR_WIDTH; i++)
+ {
+ if (data & 0x80)
+ {
+ *BITMAP_ADDR16(bitmap, y, x) = color;
+
+ if (!m_fresvert)
+ {
+ *BITMAP_ADDR16(bitmap, y + 1, x) = color;
+ }
+
+ if (!m_freshorz)
+ {
+ *BITMAP_ADDR16(bitmap, y, x + 1) = color;
+
+ if (!m_fresvert)
+ {
+ *BITMAP_ADDR16(bitmap, y + 1, x + 1) = color;
+ }
+ }
+ }
+
+ if (!m_freshorz)
+ {
+ x++;
+ }
+
+ x++;
+
+ data <<= 1;
+ }
+}
+
+
+//-------------------------------------------------
+// draw_char - draw character
+//-------------------------------------------------
+
+void cdp1869_device::draw_char(bitmap_t *bitmap, const rectangle *rect, int x, int y, UINT16 pma)
+{
+ UINT8 pmd = read_page_ram_byte(pma);
+
+ for (UINT8 cma = 0; cma < get_lines(); cma++)
+ {
+ UINT8 data = read_char_ram_byte(pma, cma, pmd);
+
+ int ccb0 = BIT(data, CCB0);
+ int ccb1 = BIT(data, CCB1);
+ int pcb = read_pcb(pma, cma, pmd);
+
+ int color = get_pen(ccb0, ccb1, pcb);
+
+ draw_line(bitmap, rect, rect->min_x + x, rect->min_y + y, data, color);
+
+ y++;
+
+ if (!m_fresvert)
+ {
+ y++;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// out3_w - register 3 write
+//-------------------------------------------------
+
+WRITE8_MEMBER( cdp1869_device::out3_w )
+{
+ /*
+ bit description
+
+ 0 bkg green
+ 1 bkg blue
+ 2 bkg red
+ 3 cfc
+ 4 disp off
+ 5 colb0
+ 6 colb1
+ 7 fres horz
+ */
+
+ m_bkg = data & 0x07;
+ m_cfc = BIT(data, 3);
+ m_dispoff = BIT(data, 4);
+ m_col = (data & 0x60) >> 5;
+ m_freshorz = BIT(data, 7);
+}
+
+
+//-------------------------------------------------
+// out4_w - register 4 write
+//-------------------------------------------------
+
+WRITE8_MEMBER( cdp1869_device::out4_w )
+{
+ /*
+ bit description
+
+ 0 tone amp 2^0
+ 1 tone amp 2^1
+ 2 tone amp 2^2
+ 3 tone amp 2^3
+ 4 tone freq sel0
+ 5 tone freq sel1
+ 6 tone freq sel2
+ 7 tone off
+ 8 tone / 2^0
+ 9 tone / 2^1
+ 10 tone / 2^2
+ 11 tone / 2^3
+ 12 tone / 2^4
+ 13 tone / 2^5
+ 14 tone / 2^6
+ 15 always 0
+ */
+
+ m_toneamp = offset & 0x0f;
+ m_tonefreq = (offset & 0x70) >> 4;
+ m_toneoff = BIT(offset, 7);
+ m_tonediv = (offset & 0x7f00) >> 8;
+
+ m_stream->update();
+}
+
+
+//-------------------------------------------------
+// out5_w - register 5 write
+//-------------------------------------------------
+
+WRITE8_MEMBER( cdp1869_device::out5_w )
+{
+ /*
+ bit description
+
+ 0 cmem access mode
+ 1 x
+ 2 x
+ 3 9-line
+ 4 x
+ 5 16 line hi-res
+ 6 double page
+ 7 fres vert
+ 8 wn amp 2^0
+ 9 wn amp 2^1
+ 10 wn amp 2^2
+ 11 wn amp 2^3
+ 12 wn freq sel0
+ 13 wn freq sel1
+ 14 wn freq sel2
+ 15 wn off
+ */
+
+ m_cmem = BIT(offset, 0);
+ m_line9 = BIT(offset, 3);
+ m_line16 = BIT(offset, 5);
+ m_dblpage = BIT(offset, 6);
+ m_fresvert = BIT(offset, 7);
+ m_wnamp = (offset & 0x0f00) >> 8;
+ m_wnfreq = (offset & 0x7000) >> 12;
+ m_wnoff = BIT(offset, 15);
+
+ m_stream->update();
+
+ if (m_cmem)
+ {
+ m_pma = offset;
+ }
+ else
+ {
+ m_pma = 0;
+ }
+}
+
+
+//-------------------------------------------------
+// out6_w - register 6 write
+//-------------------------------------------------
+
+WRITE8_MEMBER( cdp1869_device::out6_w )
+{
+ /*
+ bit description
+
+ 0 pma0 reg
+ 1 pma1 reg
+ 2 pma2 reg
+ 3 pma3 reg
+ 4 pma4 reg
+ 5 pma5 reg
+ 6 pma6 reg
+ 7 pma7 reg
+ 8 pma8 reg
+ 9 pma9 reg
+ 10 pma10 reg
+ 11 x
+ 12 x
+ 13 x
+ 14 x
+ 15 x
+ */
+
+ m_pma = offset & 0x7ff;
+}
+
+
+//-------------------------------------------------
+// out7_w - register 7 write
+//-------------------------------------------------
+
+WRITE8_MEMBER( cdp1869_device::out7_w )
+{
+ /*
+ bit description
+
+ 0 x
+ 1 x
+ 2 hma2 reg
+ 3 hma3 reg
+ 4 hma4 reg
+ 5 hma5 reg
+ 6 hma6 reg
+ 7 hma7 reg
+ 8 hma8 reg
+ 9 hma9 reg
+ 10 hma10 reg
+ 11 x
+ 12 x
+ 13 x
+ 14 x
+ 15 x
+ */
+
+ m_hma = offset & 0x7fc;
+}
+
+
+//-------------------------------------------------
+// char_ram_r - character RAM read
+//-------------------------------------------------
+
+READ8_MEMBER( cdp1869_device::char_ram_r )
+{
+ UINT8 cma = offset & 0x0f;
+ UINT16 pma;
+
+ if (m_cmem)
+ {
+ pma = get_pma();
+ }
+ else
+ {
+ pma = offset;
+ }
+
+ if (m_dblpage)
+ {
+ cma &= 0x07;
+ }
+
+ UINT8 pmd = read_page_ram_byte(pma);
+
+ return read_char_ram_byte(pma, cma, pmd);
+}
+
+
+//-------------------------------------------------
+// char_ram_w - character RAM write
+//-------------------------------------------------
+
+WRITE8_MEMBER( cdp1869_device::char_ram_w )
+{
+ UINT8 cma = offset & 0x0f;
+ UINT16 pma;
+
+ if (m_cmem)
+ {
+ pma = get_pma();
+ }
+ else
+ {
+ pma = offset;
+ }
+
+ if (m_dblpage)
+ {
+ cma &= 0x07;
+ }
+
+ UINT8 pmd = read_page_ram_byte(pma);
+
+ write_char_ram_byte(pma, cma, pmd, data);
+}
+
+
+//-------------------------------------------------
+// page_ram_r - page RAM read
+//-------------------------------------------------
+
+READ8_MEMBER( cdp1869_device::page_ram_r )
+{
+ UINT16 pma;
+
+ if (m_cmem)
+ {
+ pma = get_pma();
+ }
+ else
+ {
+ pma = offset;
+ }
+
+ return read_page_ram_byte(pma);
+}
+
+
+//-------------------------------------------------
+// page_ram_w - page RAM write
+//-------------------------------------------------
+
+WRITE8_MEMBER( cdp1869_device::page_ram_w )
+{
+ UINT16 pma;
+
+ if (m_cmem)
+ {
+ pma = get_pma();
+ }
+ else
+ {
+ pma = offset;
+ }
+
+ write_page_ram_byte(pma, data);
+}
+
+
+//-------------------------------------------------
+// page_ram_w - predisplay
+//-------------------------------------------------
+
+READ_LINE_MEMBER( cdp1869_device::predisplay_r )
+{
+ return m_prd;
+}
+
+
+//-------------------------------------------------
+// pal_ntsc_r - PAL/NTSC
+//-------------------------------------------------
+
+READ_LINE_MEMBER( cdp1869_device::pal_ntsc_r )
+{
+ return m_in_pal_ntsc_func();
+}
+
+
+//-------------------------------------------------
+// update_screen - update screen
+//-------------------------------------------------
+
+void cdp1869_device::update_screen(bitmap_t *bitmap, const rectangle *cliprect)
+{
+ rectangle screen_rect, outer;
+
+ if (is_ntsc())
+ {
+ outer.min_x = CDP1869_HBLANK_END;
+ outer.max_x = CDP1869_HBLANK_START - 1;
+ outer.min_y = CDP1869_SCANLINE_VBLANK_END_NTSC;
+ outer.max_y = CDP1869_SCANLINE_VBLANK_START_NTSC - 1;
+ screen_rect.min_x = CDP1869_SCREEN_START_NTSC;
+ screen_rect.max_x = CDP1869_SCREEN_END - 1;
+ screen_rect.min_y = CDP1869_SCANLINE_DISPLAY_START_NTSC;
+ screen_rect.max_y = CDP1869_SCANLINE_DISPLAY_END_NTSC - 1;
+ }
+ else
+ {
+ outer.min_x = CDP1869_HBLANK_END;
+ outer.max_x = CDP1869_HBLANK_START - 1;
+ outer.min_y = CDP1869_SCANLINE_VBLANK_END_PAL;
+ outer.max_y = CDP1869_SCANLINE_VBLANK_START_PAL - 1;
+ screen_rect.min_x = CDP1869_SCREEN_START_PAL;
+ screen_rect.max_x = CDP1869_SCREEN_END - 1;
+ screen_rect.min_y = CDP1869_SCANLINE_DISPLAY_START_PAL;
+ screen_rect.max_y = CDP1869_SCANLINE_DISPLAY_END_PAL - 1;
+ }
+
+ sect_rect(&outer, cliprect);
+ bitmap_fill(bitmap, &outer, m_bkg);
+
+ if (!m_dispoff)
+ {
+ int width = CDP1869_CHAR_WIDTH;
+ int height = get_lines();
+
+ if (!m_freshorz)
+ {
+ width *= 2;
+ }
+
+ if (!m_fresvert)
+ {
+ height *= 2;
+ }
+
+ int cols = m_freshorz ? CDP1869_COLUMNS_FULL : CDP1869_COLUMNS_HALF;
+ int rows = (screen_rect.max_y - screen_rect.min_y + 1) / height;
+
+ UINT16 pmemsize = get_pmemsize(cols, rows);
+ UINT16 addr = m_hma;
+
+ for (int sy = 0; sy < rows; sy++)
+ {
+ for (int sx = 0; sx < cols; sx++)
+ {
+ int x = sx * width;
+ int y = sy * height;
+
+ draw_char(bitmap, &screen_rect, x, y, addr);
+
+ addr++;
+
+ if (addr == pmemsize) addr = 0;
+ }
+ }
+ }
+}
diff --git a/trunk/src/emu/sound/cdp1869.h b/trunk/src/emu/sound/cdp1869.h
new file mode 100644
index 00000000000..6aacb0515fd
--- /dev/null
+++ b/trunk/src/emu/sound/cdp1869.h
@@ -0,0 +1,313 @@
+/**********************************************************************
+
+ RCA CDP1869/1870/1876 Video Interface System (VIS) emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ TPA 1 |* \_/ | 40 Vdd
+ TPB 2 | | 39 PMSEL
+ _MRD 3 | | 38 _PMWR
+ _MWR 4 | | 37 CMSEL
+ MA0/8 5 | | 36 _CMWR
+ MA1/9 6 | | 35 PMA0
+ MA2/10 7 | | 34 PMA1
+ MA3/11 8 | | 33 PMA2
+ MA4/12 9 | | 32 PMA3
+ MA5/13 10 | | 31 PMA4
+ MA6/14 11 | CDP1869 | 30 PMA5
+ MA7/15 12 | | 29 PMA6
+ N0 13 | | 28 PMA7
+ N1 14 | | 27 PMA8
+ N2 15 | | 26 PMA9
+ _H SYNC 16 | | 25 CMA3/PMA10
+ _DISPLAY 17 | | 24 CMA2
+ _ADDRSTB 18 | | 23 CMA1
+ SOUND 19 | | 22 CMA0
+ Vss 20 |_____________| 21 _N=3
+
+ _____ _____
+ _PREDISPLAY 1 |* \_/ | 40 Vdd
+ _DISPLAY 2 | | 39 PAL/_NTSC
+ PCB 3 | | 38 CPUCLK
+ CCB1 4 | | 37 XTAL (DOT)
+ BUS7 5 | | 36 _XTAL (DOT)
+ CCB0 6 | | 35 _ADDRSTB
+ BUS6 7 | | 34 _MRD
+ CDB5 8 | | 33 TPB
+ BUS5 9 | | 32 CMSEL
+ CDB4 10 | | 31 BURST
+ BUS4 11 | CDP1870 | 30 _H SYNC
+ CDB3 12 | | 29 _COMPSYNC
+ BUS3 13 | | 28 LUM
+ CDB2 14 | | 27 PAL CHROM
+ BUS2 15 | | 26 NTSC CHROM
+ CDB1 16 | | 25 _XTAL (CHROM)
+ BUS1 17 | | 24 XTAL (CHROM)
+ CDB0 18 | | 23 _EMS
+ BUS0 19 | | 22 _EVS
+ Vss 20 |_____________| 21 _N=3
+
+ _____ _____
+ _PREDISPLAY 1 |* \_/ | 40 Vdd
+ _DISPLAY 2 | | 39 PAL/_NTSC
+ PCB 3 | | 38 CPUCLK
+ CCB1 4 | | 37 XTAL (DOT)
+ BUS7 5 | | 36 _XTAL (DOT)
+ CCB0 6 | | 35 _ADDRSTB
+ BUS6 7 | | 34 _MRD
+ CDB5 8 | | 33 TPB
+ BUS5 9 | | 32 CMSEL
+ CDB4 10 | | 31 BURST
+ BUS4 11 | CDP1876 | 30 _H SYNC
+ CDB3 12 | | 29 _COMPSYNC
+ BUS3 13 | | 28 RED
+ CDB2 14 | | 27 BLUE
+ BUS2 15 | | 26 GREEN
+ CDB1 16 | | 25 _XTAL (CHROM)
+ BUS1 17 | | 24 XTAL (CHROM)
+ CDB0 18 | | 23 _EMS
+ BUS0 19 | | 22 _EVS
+ Vss 20 |_____________| 21 _N=3
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __CDP1869__
+#define __CDP1869__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define CDP1869_DOT_CLK_PAL (float)XTAL_5_626MHz
+#define CDP1869_DOT_CLK_NTSC (float)XTAL_5_67MHz
+#define CDP1869_COLOR_CLK_PAL (float)XTAL_8_867236MHz
+#define CDP1869_COLOR_CLK_NTSC (float)XTAL_7_15909MHz
+
+#define CDP1869_CPU_CLK_PAL (CDP1869_DOT_CLK_PAL / 2)
+#define CDP1869_CPU_CLK_NTSC (CDP1869_DOT_CLK_NTSC / 2)
+
+#define CDP1869_CHAR_WIDTH 6
+
+#define CDP1869_HSYNC_START (56 * CDP1869_CHAR_WIDTH)
+#define CDP1869_HSYNC_END (60 * CDP1869_CHAR_WIDTH)
+#define CDP1869_HBLANK_START (54 * CDP1869_CHAR_WIDTH)
+#define CDP1869_HBLANK_END ( 5 * CDP1869_CHAR_WIDTH)
+#define CDP1869_SCREEN_START_PAL ( 9 * CDP1869_CHAR_WIDTH)
+#define CDP1869_SCREEN_START_NTSC (10 * CDP1869_CHAR_WIDTH)
+#define CDP1869_SCREEN_START (10 * CDP1869_CHAR_WIDTH)
+#define CDP1869_SCREEN_END (50 * CDP1869_CHAR_WIDTH)
+#define CDP1869_SCREEN_WIDTH (60 * CDP1869_CHAR_WIDTH)
+
+#define CDP1869_TOTAL_SCANLINES_PAL 312
+#define CDP1869_SCANLINE_VBLANK_START_PAL 304
+#define CDP1869_SCANLINE_VBLANK_END_PAL 10
+#define CDP1869_SCANLINE_VSYNC_START_PAL 308
+#define CDP1869_SCANLINE_VSYNC_END_PAL 312
+#define CDP1869_SCANLINE_DISPLAY_START_PAL 44
+#define CDP1869_SCANLINE_DISPLAY_END_PAL 260
+#define CDP1869_SCANLINE_PREDISPLAY_START_PAL 43
+#define CDP1869_SCANLINE_PREDISPLAY_END_PAL 260
+#define CDP1869_VISIBLE_SCANLINES_PAL (CDP1869_SCANLINE_DISPLAY_END_PAL - CDP1869_SCANLINE_DISPLAY_START_PAL)
+
+#define CDP1869_TOTAL_SCANLINES_NTSC 262
+#define CDP1869_SCANLINE_VBLANK_START_NTSC 252
+#define CDP1869_SCANLINE_VBLANK_END_NTSC 10
+#define CDP1869_SCANLINE_VSYNC_START_NTSC 258
+#define CDP1869_SCANLINE_VSYNC_END_NTSC 262
+#define CDP1869_SCANLINE_DISPLAY_START_NTSC 36
+#define CDP1869_SCANLINE_DISPLAY_END_NTSC 228
+#define CDP1869_SCANLINE_PREDISPLAY_START_NTSC 35
+#define CDP1869_SCANLINE_PREDISPLAY_END_NTSC 228
+#define CDP1869_VISIBLE_SCANLINES_NTSC (CDP1869_SCANLINE_DISPLAY_END_NTSC - CDP1869_SCANLINE_DISPLAY_START_NTSC)
+
+#define CDP1869_PALETTE_LENGTH 8+64
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_CDP1869_ADD(_tag, _pixclock, _config, _map) \
+ MCFG_DEVICE_ADD(_tag, CDP1869, _pixclock) \
+ MCFG_DEVICE_CONFIG(_config) \
+ MCFG_DEVICE_ADDRESS_MAP(AS_0, _map)
+
+#define MCFG_CDP1869_SCREEN_PAL_ADD(_tag, _clock) \
+ MCFG_SCREEN_ADD(_tag, RASTER) \
+ MCFG_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) \
+ MCFG_SCREEN_RAW_PARAMS(_clock, CDP1869_SCREEN_WIDTH, CDP1869_HBLANK_END, CDP1869_HBLANK_START, CDP1869_TOTAL_SCANLINES_PAL, CDP1869_SCANLINE_VBLANK_END_PAL, CDP1869_SCANLINE_VBLANK_START_PAL) \
+ MCFG_PALETTE_LENGTH(8+64)
+
+#define MCFG_CDP1869_SCREEN_NTSC_ADD(_tag, _clock) \
+ MCFG_SCREEN_ADD(_tag, RASTER) \
+ MCFG_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) \
+ MCFG_SCREEN_RAW_PARAMS(_clock, CDP1869_SCREEN_WIDTH, CDP1869_HBLANK_END, CDP1869_HBLANK_START, CDP1869_TOTAL_SCANLINES_NTSC, CDP1869_SCANLINE_VBLANK_END_NTSC, CDP1869_SCANLINE_VBLANK_START_NTSC) \
+ MCFG_PALETTE_LENGTH(8+64)
+
+#define CDP1869_INTERFACE(_name) \
+ const cdp1869_interface (_name) =
+
+#define CDP1869_CHAR_RAM_READ(name) UINT8 name(device_t *device, UINT16 pma, UINT8 cma, UINT8 pmd)
+#define CDP1869_CHAR_RAM_WRITE(name) void name(device_t *device, UINT16 pma, UINT8 cma, UINT8 pmd, UINT8 data)
+#define CDP1869_PCB_READ(name) int name(device_t *device, UINT16 pma, UINT8 cma, UINT8 pmd)
+
+#define CDP1869_PAL \
+ DEVCB_LINE_VCC
+
+#define CDP1869_NTSC \
+ DEVCB_LINE_GND
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+typedef UINT8 (*cdp1869_char_ram_read_func)(device_t *device, UINT16 pma, UINT8 cma, UINT8 pmd);
+typedef void (*cdp1869_char_ram_write_func)(device_t *device, UINT16 pma, UINT8 cma, UINT8 pmd, UINT8 data);
+typedef int (*cdp1869_pcb_read_func)(device_t *device, UINT16 pma, UINT8 cma, UINT8 pmd);
+
+
+// ======================> cdp1869_interface
+
+struct cdp1869_interface
+{
+ const char *screen_tag; // screen we are acting on
+
+ // pixel clock of the chip is the device clock
+ int color_clock; // the chroma clock of the chip
+
+ // screen format
+ devcb_read_line in_pal_ntsc_cb;
+
+ // page memory color bit read function
+ cdp1869_pcb_read_func in_pcb_cb;
+
+ // character memory read function
+ cdp1869_char_ram_read_func in_char_ram_cb;
+
+ // character memory write function
+ cdp1869_char_ram_write_func out_char_ram_cb;
+
+ // if specified, this gets called for every change of the predisplay pin (CDP1870/76 pin 1)
+ devcb_write_line out_prd_cb;
+};
+
+
+
+// ======================> cdp1869_device
+
+class cdp1869_device : public device_t,
+ public device_sound_interface,
+ public device_memory_interface,
+ public cdp1869_interface
+{
+public:
+ // construction/destruction
+ cdp1869_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ DECLARE_WRITE8_MEMBER( out3_w );
+ DECLARE_WRITE8_MEMBER( out4_w );
+ DECLARE_WRITE8_MEMBER( out5_w );
+ DECLARE_WRITE8_MEMBER( out6_w );
+ DECLARE_WRITE8_MEMBER( out7_w );
+
+ DECLARE_READ8_MEMBER( char_ram_r );
+ DECLARE_WRITE8_MEMBER( char_ram_w );
+
+ DECLARE_READ8_MEMBER( page_ram_r );
+ DECLARE_WRITE8_MEMBER( page_ram_w );
+
+ DECLARE_READ_LINE_MEMBER( predisplay_r );
+ DECLARE_READ_LINE_MEMBER( pal_ntsc_r );
+
+ void update_screen(bitmap_t *bitmap, const rectangle *cliprect);
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_post_load();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
+
+ // device_sound_interface callbacks
+ virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
+
+ inline bool is_ntsc();
+ inline UINT8 read_page_ram_byte(offs_t address);
+ inline void write_page_ram_byte(offs_t address, UINT8 data);
+ inline UINT8 read_char_ram_byte(offs_t pma, offs_t cma, UINT8 pmd);
+ inline void write_char_ram_byte(offs_t pma, offs_t cma, UINT8 pmd, UINT8 data);
+ inline int read_pcb(offs_t pma, offs_t cma, UINT8 pmd);
+ inline void update_prd_changed_timer();
+ inline rgb_t get_rgb(int i, int c, int l);
+ inline int get_lines();
+ inline UINT16 get_pmemsize(int cols, int rows);
+ inline UINT16 get_pma();
+ inline int get_pen(int ccb0, int ccb1, int pcb);
+
+ void initialize_palette();
+ void draw_line(bitmap_t *bitmap, const rectangle *rect, int x, int y, UINT8 data, int color);
+ void draw_char(bitmap_t *bitmap, const rectangle *rect, int x, int y, UINT16 pma);
+
+private:
+ devcb_resolved_read_line m_in_pal_ntsc_func;
+ devcb_resolved_write_line m_out_prd_func;
+ cdp1869_pcb_read_func m_in_pcb_func;
+ cdp1869_char_ram_read_func m_in_char_ram_func;
+ cdp1869_char_ram_write_func m_out_char_ram_func;
+
+ screen_device *m_screen;
+ address_space *m_page_ram;
+ emu_timer *m_prd_timer;
+ sound_stream *m_stream;
+
+ // video state
+ int m_prd; // predisplay
+ int m_dispoff; // display off
+ int m_fresvert; // full resolution vertical
+ int m_freshorz; // full resolution horizontal
+ int m_cmem; // character memory access mode
+ int m_dblpage; // double page mode
+ int m_line16; // 16-line hi-res mode
+ int m_line9; // 9 line mode
+ int m_cfc; // color format control
+ UINT8 m_col; // character color control
+ UINT8 m_bkg; // background color
+ UINT16 m_pma; // page memory address
+ UINT16 m_hma; // home memory address
+
+ // sound state
+ INT16 m_signal; // current signal
+ int m_incr; // initial wave state
+ int m_toneoff; // tone off
+ int m_wnoff; // white noise off
+ UINT8 m_tonediv; // tone divisor
+ UINT8 m_tonefreq; // tone range select
+ UINT8 m_toneamp; // tone output amplitude
+ UINT8 m_wnfreq; // white noise range select
+ UINT8 m_wnamp; // white noise output amplitude
+
+ const address_space_config m_space_config;
+};
+
+
+// device type definition
+extern const device_type CDP1869;
+
+
+
+#endif
diff --git a/trunk/src/emu/sound/cem3394.c b/trunk/src/emu/sound/cem3394.c
new file mode 100644
index 00000000000..c264bb8e614
--- /dev/null
+++ b/trunk/src/emu/sound/cem3394.c
@@ -0,0 +1,589 @@
+/***************************************************************************
+
+ CEM3394 sound driver.
+
+ This driver handles CEM-3394 analog synth chip. Very crudely.
+
+ Still to do:
+ - adjust the overall volume when multiple waves are being generated
+ - filter internal sound
+ - support resonance (don't understand how it works)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "cem3394.h"
+
+
+
+/* waveform generation parameters */
+#define ENABLE_PULSE 1
+#define ENABLE_TRIANGLE 1
+#define ENABLE_SAWTOOTH 1
+#define ENABLE_EXTERNAL 1
+
+
+/* pulse shaping parameters */
+/* examples: */
+/* hat trick - skidding ice sounds too loud if minimum width is too big */
+/* snake pit - melody during first level too soft if minimum width is too small */
+/* snake pit - bonus counter at the end of level */
+/* snacks'n jaxson - laugh at end of level is too soft if minimum width is too small */
+
+#define LIMIT_WIDTH 1
+#define MINIMUM_WIDTH 0.25
+#define MAXIMUM_WIDTH 0.75
+
+
+/********************************************************************************
+
+ From the datasheet:
+
+ CEM3394_VCO_FREQUENCY:
+ -4.0 ... +4.0
+ -0.75 V/octave
+ f = exp(V) * 431.894
+
+ CEM3394_MODULATION_AMOUNT
+ 0.0 ... +3.5
+ 0.0 == 0.01 x frequency
+ 3.5 == 2.00 x frequency
+
+ CEM3394_WAVE_SELECT
+ -0.5 ... -0.2 == triangle
+ +0.9 ... +1.5 == triangle + sawtooth
+ +2.3 ... +3.9 == sawtooth
+
+ CEM3394_PULSE_WIDTH
+ 0.0 ... +2.0
+ 0.0 == 0% duty cycle
+ +2.0 == 100% duty cycle
+
+ CEM3394_MIXER_BALANCE
+ -4.0 ... +4.0
+ 0.0 both at -6dB
+ -20 dB/V
+
+ CEM3394_FILTER_RESONANCE
+ 0.0 ... +2.5
+ 0.0 == no resonance
+ +2.5 == oscillation
+
+ CEM3394_FILTER_FREQENCY
+ -3.0 ... +4.0
+ -0.375 V/octave
+ 0.0 == 1300Hz
+
+ CEM3394_FINAL_GAIN
+ 0.0 ... +4.0
+ -20 dB/V
+ 0.0 == -90dB
+ 4.0 == 0dB
+
+ Square wave output = 160 (average is constant regardless of duty cycle)
+ Sawtooth output = 200
+ Triangle output = 250
+ Sawtooth + triangle output = 330
+ Maximum output = 400
+
+********************************************************************************/
+
+
+/* various waveforms */
+#define WAVE_TRIANGLE 1
+#define WAVE_SAWTOOTH 2
+#define WAVE_PULSE 4
+
+/* keep lots of fractional bits */
+#define FRACTION_BITS 28
+#define FRACTION_ONE (1 << FRACTION_BITS)
+#define FRACTION_ONE_D ((double)(1 << FRACTION_BITS))
+#define FRACTION_MASK (FRACTION_ONE - 1)
+#define FRACTION_MULT(a,b) (((a) >> (FRACTION_BITS / 2)) * ((b) >> (FRACTION_BITS - FRACTION_BITS / 2)))
+
+
+/* this structure defines the parameters for a channel */
+typedef struct _cem3394_state cem3394_state;
+struct _cem3394_state
+{
+ sound_stream * stream; /* our stream */
+ void (*external)(device_t *, int, short *);/* callback to generate external samples */
+ double vco_zero_freq; /* frequency of VCO at 0.0V */
+ double filter_zero_freq; /* frequency of filter at 0.0V */
+
+ double values[8]; /* raw values of registers */
+ UINT8 wave_select; /* flags which waveforms are enabled */
+
+ UINT32 volume; /* linear overall volume (0-256) */
+ UINT32 mixer_internal; /* linear internal volume (0-256) */
+ UINT32 mixer_external; /* linear external volume (0-256) */
+
+ UINT32 position; /* current VCO frequency position (0.FRACTION_BITS) */
+ UINT32 step; /* per-sample VCO step (0.FRACTION_BITS) */
+
+ UINT32 filter_position; /* current filter frequency position (0.FRACTION_BITS) */
+ UINT32 filter_step; /* per-sample filter step (0.FRACTION_BITS) */
+ UINT32 modulation_depth; /* fraction of total by which we modulate (0.FRACTION_BITS) */
+ INT16 last_ext; /* last external sample we read */
+
+ UINT32 pulse_width; /* fractional pulse width (0.FRACTION_BITS) */
+
+ double inv_sample_rate;
+ int sample_rate;
+ device_t *device;
+
+ INT16 *mixer_buffer;
+ INT16 *external_buffer;
+};
+
+
+INLINE cem3394_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == CEM3394);
+ return (cem3394_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+/* generate sound to the mix buffer in mono */
+static STREAM_UPDATE( cem3394_update )
+{
+ cem3394_state *chip = (cem3394_state *)param;
+ int int_volume = (chip->volume * chip->mixer_internal) / 256;
+ int ext_volume = (chip->volume * chip->mixer_external) / 256;
+ UINT32 step = chip->step, position, end_position = 0;
+ stream_sample_t *buffer = outputs[0];
+ INT16 *mix, *ext;
+ int i;
+
+ /* external volume is effectively 0 if no external function */
+ if (!chip->external || !ENABLE_EXTERNAL)
+ ext_volume = 0;
+
+ /* adjust the volume for the filter */
+ if (step > chip->filter_step)
+ int_volume /= step - chip->filter_step;
+
+ /* bail if nothing's going on */
+ if (int_volume == 0 && ext_volume == 0)
+ {
+ memset(buffer, 0, sizeof(*buffer) * samples);
+ return;
+ }
+
+ /* if there's external stuff, fetch and process it now */
+ if (ext_volume != 0)
+ {
+ UINT32 fposition = chip->filter_position, fstep = chip->filter_step, depth;
+ INT16 last_ext = chip->last_ext;
+
+ /* fetch the external data */
+ (*chip->external)(chip->device, samples, chip->external_buffer);
+
+ /* compute the modulation depth, and adjust fstep to the maximum frequency */
+ /* we lop off 13 bits of depth so that we can multiply by stepadjust, below, */
+ /* which has 13 bits of precision */
+ depth = FRACTION_MULT(fstep, chip->modulation_depth);
+ fstep += depth;
+ depth >>= 13;
+
+ /* "apply" the filter: note this is pretty cheesy; it basically just downsamples the
+ external sample to filter_freq by allowing only 2 transitions for every cycle */
+ for (i = 0, ext = chip->external_buffer, position = chip->position; i < samples; i++, ext++)
+ {
+ UINT32 newposition;
+ INT32 stepadjust;
+
+ /* update the position and compute the adjustment from a triangle wave */
+ if (position & (1 << (FRACTION_BITS - 1)))
+ stepadjust = 0x2000 - ((position >> (FRACTION_BITS - 14)) & 0x1fff);
+ else
+ stepadjust = (position >> (FRACTION_BITS - 14)) & 0x1fff;
+ position += step;
+
+ /* if we cross a half-step boundary, allow the next byte of the external input */
+ newposition = fposition + fstep - (stepadjust * depth);
+ if ((newposition ^ fposition) & ~(FRACTION_MASK >> 1))
+ last_ext = *ext;
+ else
+ *ext = last_ext;
+ fposition = newposition & FRACTION_MASK;
+ }
+
+ /* update the final filter values */
+ chip->filter_position = fposition;
+ chip->last_ext = last_ext;
+ }
+
+ /* if there's internal stuff, generate it */
+ if (int_volume != 0)
+ {
+ if (chip->wave_select == 0 && !ext_volume)
+ logerror("%f V didn't cut it\n", chip->values[CEM3394_WAVE_SELECT]);
+
+ /* handle the pulse component; it maxes out at 0x1932, which is 27% smaller than */
+ /* the sawtooth (since the value is constant, this is the best place to have an */
+ /* odd value for volume) */
+ if (ENABLE_PULSE && (chip->wave_select & WAVE_PULSE))
+ {
+ UINT32 pulse_width = chip->pulse_width;
+
+ /* if the width is wider than the step, we're guaranteed to hit it once per cycle */
+ if (pulse_width >= step)
+ {
+ for (i = 0, mix = chip->mixer_buffer, position = chip->position; i < samples; i++, mix++)
+ {
+ if (position < pulse_width)
+ *mix = 0x1932;
+ else
+ *mix = 0x0000;
+ position = (position + step) & FRACTION_MASK;
+ }
+ }
+
+ /* otherwise, we compute a volume and watch for cycle boundary crossings */
+ else
+ {
+ INT16 volume = 0x1932 * pulse_width / step;
+ for (i = 0, mix = chip->mixer_buffer, position = chip->position; i < samples; i++, mix++)
+ {
+ UINT32 newposition = position + step;
+ if ((newposition ^ position) & ~FRACTION_MASK)
+ *mix = volume;
+ else
+ *mix = 0x0000;
+ position = newposition & FRACTION_MASK;
+ }
+ }
+ end_position = position;
+ }
+
+ /* otherwise, clear the mixing buffer */
+ else
+ memset(chip->mixer_buffer, 0, sizeof(INT16) * samples);
+
+ /* handle the sawtooth component; it maxes out at 0x2000, which is 27% larger */
+ /* than the pulse */
+ if (ENABLE_SAWTOOTH && (chip->wave_select & WAVE_SAWTOOTH))
+ {
+ for (i = 0, mix = chip->mixer_buffer, position = chip->position; i < samples; i++, mix++)
+ {
+ *mix += ((position >> (FRACTION_BITS - 14)) & 0x3fff) - 0x2000;
+ position += step;
+ }
+ end_position = position & FRACTION_MASK;
+ }
+
+ /* handle the triangle component; it maxes out at 0x2800, which is 25% larger */
+ /* than the sawtooth (should be 27% according to the specs, but 25% saves us */
+ /* a multiplication) */
+ if (ENABLE_TRIANGLE && (chip->wave_select & WAVE_TRIANGLE))
+ {
+ for (i = 0, mix = chip->mixer_buffer, position = chip->position; i < samples; i++, mix++)
+ {
+ INT16 value;
+ if (position & (1 << (FRACTION_BITS - 1)))
+ value = 0x2000 - ((position >> (FRACTION_BITS - 14)) & 0x1fff);
+ else
+ value = (position >> (FRACTION_BITS - 14)) & 0x1fff;
+ *mix += value + (value >> 2);
+ position += step;
+ }
+ end_position = position & FRACTION_MASK;
+ }
+
+ /* update the final position */
+ chip->position = end_position;
+ }
+
+ /* mix it down */
+ mix = chip->mixer_buffer;
+ ext = chip->external_buffer;
+ {
+ /* internal + external */
+ if (ext_volume != 0 && int_volume != 0)
+ {
+ for (i = 0; i < samples; i++, mix++, ext++)
+ *buffer++ = (*mix * int_volume + *ext * ext_volume) / 128;
+ }
+ /* internal only */
+ else if (int_volume != 0)
+ {
+ for (i = 0; i < samples; i++, mix++)
+ *buffer++ = *mix * int_volume / 128;
+ }
+ /* external only */
+ else
+ {
+ for (i = 0; i < samples; i++, ext++)
+ *buffer++ = *ext * ext_volume / 128;
+ }
+ }
+}
+
+
+static DEVICE_START( cem3394 )
+{
+ const cem3394_interface *intf = (const cem3394_interface *)device->static_config();
+ cem3394_state *chip = get_safe_token(device);
+
+ chip->device = device;
+
+ /* copy global parameters */
+ chip->sample_rate = CEM3394_SAMPLE_RATE;
+ chip->inv_sample_rate = 1.0 / (double)chip->sample_rate;
+
+ /* allocate stream channels, 1 per chip */
+ chip->stream = device->machine().sound().stream_alloc(*device, 0, 1, chip->sample_rate, chip, cem3394_update);
+ chip->external = intf->external;
+ chip->vco_zero_freq = intf->vco_zero_freq;
+ chip->filter_zero_freq = intf->filter_zero_freq;
+
+ /* allocate memory for a mixer buffer and external buffer (1 second should do it!) */
+ chip->mixer_buffer = auto_alloc_array(device->machine(), INT16, chip->sample_rate);
+ chip->external_buffer = auto_alloc_array(device->machine(), INT16, chip->sample_rate);
+
+ device->save_item(NAME(chip->values));
+ device->save_item(NAME(chip->wave_select));
+ device->save_item(NAME(chip->volume));
+ device->save_item(NAME(chip->mixer_internal));
+ device->save_item(NAME(chip->mixer_external));
+ device->save_item(NAME(chip->position));
+ device->save_item(NAME(chip->step));
+ device->save_item(NAME(chip->filter_position));
+ device->save_item(NAME(chip->filter_step));
+ device->save_item(NAME(chip->modulation_depth));
+ device->save_item(NAME(chip->last_ext));
+ device->save_item(NAME(chip->pulse_width));
+}
+
+
+INLINE double compute_db(double voltage)
+{
+ /* assumes 0.0 == full off, 4.0 == full on, with linear taper, as described in the datasheet */
+
+ /* above 4.0, maximum volume */
+ if (voltage >= 4.0)
+ return 0.0;
+
+ /* below 0.0, minimum volume */
+ else if (voltage <= 0.0)
+ return 90.0;
+
+ /* between 2.5 and 4.0, linear from 20dB to 0dB */
+ else if (voltage >= 2.5)
+ return (4.0 - voltage) * (1.0 / 1.5) * 20.0;
+
+ /* between 0.0 and 2.5, exponential to 20dB */
+ else
+ {
+ double temp = 20.0 * pow(2.0, 2.5 - voltage);
+ if (temp < 90.0) return 90.0;
+ else return temp;
+ }
+}
+
+
+INLINE UINT32 compute_db_volume(double voltage)
+{
+ double temp;
+
+ /* assumes 0.0 == full off, 4.0 == full on, with linear taper, as described in the datasheet */
+
+ /* above 4.0, maximum volume */
+ if (voltage >= 4.0)
+ return 256;
+
+ /* below 0.0, minimum volume */
+ else if (voltage <= 0.0)
+ return 0;
+
+ /* between 2.5 and 4.0, linear from 20dB to 0dB */
+ else if (voltage >= 2.5)
+ temp = (4.0 - voltage) * (1.0 / 1.5) * 20.0;
+
+ /* between 0.0 and 2.5, exponential to 20dB */
+ else
+ {
+ temp = 20.0 * pow(2.0, 2.5 - voltage);
+ if (temp < 50.0) return 0;
+ }
+
+ /* convert from dB to volume and return */
+ return (UINT32)(256.0 * pow(0.891251, temp));
+}
+
+
+void cem3394_set_voltage(device_t *device, int input, double voltage)
+{
+ cem3394_state *chip = get_safe_token(device);
+ double temp;
+
+ /* don't do anything if no change */
+ if (voltage == chip->values[input])
+ return;
+ chip->values[input] = voltage;
+
+ /* update the stream first */
+ chip->stream->update();
+
+ /* switch off the input */
+ switch (input)
+ {
+ /* frequency varies from -4.0 to +4.0, at 0.75V/octave */
+ case CEM3394_VCO_FREQUENCY:
+ temp = chip->vco_zero_freq * pow(2.0, -voltage * (1.0 / 0.75));
+ chip->step = (UINT32)(temp * chip->inv_sample_rate * FRACTION_ONE_D);
+ break;
+
+ /* wave select determines triangle/sawtooth enable */
+ case CEM3394_WAVE_SELECT:
+ chip->wave_select &= ~(WAVE_TRIANGLE | WAVE_SAWTOOTH);
+ if (voltage >= -0.5 && voltage <= -0.2)
+ chip->wave_select |= WAVE_TRIANGLE;
+ else if (voltage >= 0.9 && voltage <= 1.5)
+ chip->wave_select |= WAVE_TRIANGLE | WAVE_SAWTOOTH;
+ else if (voltage >= 2.3 && voltage <= 3.9)
+ chip->wave_select |= WAVE_SAWTOOTH;
+ break;
+
+ /* pulse width determines duty cycle; 0.0 means 0%, 2.0 means 100% */
+ case CEM3394_PULSE_WIDTH:
+ if (voltage < 0.0)
+ {
+ chip->pulse_width = 0;
+ chip->wave_select &= ~WAVE_PULSE;
+ }
+ else
+ {
+ temp = voltage * 0.5;
+ if (LIMIT_WIDTH)
+ temp = MINIMUM_WIDTH + (MAXIMUM_WIDTH - MINIMUM_WIDTH) * temp;
+ chip->pulse_width = (UINT32)(temp * FRACTION_ONE_D);
+ chip->wave_select |= WAVE_PULSE;
+ }
+ break;
+
+ /* final gain is pretty self-explanatory; 0.0 means ~90dB, 4.0 means 0dB */
+ case CEM3394_FINAL_GAIN:
+ chip->volume = compute_db_volume(voltage);
+ break;
+
+ /* mixer balance is a pan between the external input and the internal input */
+ /* 0.0 is equal parts of both; positive values favor external, negative favor internal */
+ case CEM3394_MIXER_BALANCE:
+ if (voltage >= 0.0)
+ {
+ chip->mixer_internal = compute_db_volume(3.55 - voltage);
+ chip->mixer_external = compute_db_volume(3.55 + 0.45 * (voltage * 0.25));
+ }
+ else
+ {
+ chip->mixer_internal = compute_db_volume(3.55 - 0.45 * (voltage * 0.25));
+ chip->mixer_external = compute_db_volume(3.55 + voltage);
+ }
+ break;
+
+ /* filter frequency varies from -4.0 to +4.0, at 0.375V/octave */
+ case CEM3394_FILTER_FREQENCY:
+ temp = chip->filter_zero_freq * pow(2.0, -voltage * (1.0 / 0.375));
+ chip->filter_step = (UINT32)(temp * chip->inv_sample_rate * FRACTION_ONE_D);
+ break;
+
+ /* modulation depth is 0.01 at 0V and 2.0 at 3.5V; how it grows from one to the other */
+ /* is still unclear at this point */
+ case CEM3394_MODULATION_AMOUNT:
+ if (voltage < 0.0)
+ chip->modulation_depth = (UINT32)(0.01 * FRACTION_ONE_D);
+ else if (voltage > 3.5)
+ chip->modulation_depth = (UINT32)(2.00 * FRACTION_ONE_D);
+ else
+ chip->modulation_depth = (UINT32)(((voltage * (1.0 / 3.5)) * 1.99 + 0.01) * FRACTION_ONE_D);
+ break;
+
+ /* this is not yet implemented */
+ case CEM3394_FILTER_RESONANCE:
+ break;
+ }
+}
+
+
+double cem3394_get_parameter(device_t *device, int input)
+{
+ cem3394_state *chip = get_safe_token(device);
+ double voltage = chip->values[input];
+
+ switch (input)
+ {
+ case CEM3394_VCO_FREQUENCY:
+ return chip->vco_zero_freq * pow(2.0, -voltage * (1.0 / 0.75));
+
+ case CEM3394_WAVE_SELECT:
+ return voltage;
+
+ case CEM3394_PULSE_WIDTH:
+ if (voltage <= 0.0)
+ return 0.0;
+ else if (voltage >= 2.0)
+ return 1.0;
+ else
+ return voltage * 0.5;
+
+ case CEM3394_FINAL_GAIN:
+ return compute_db(voltage);
+
+ case CEM3394_MIXER_BALANCE:
+ return voltage * 0.25;
+
+ case CEM3394_MODULATION_AMOUNT:
+ if (voltage < 0.0)
+ return 0.01;
+ else if (voltage > 3.5)
+ return 2.0;
+ else
+ return (voltage * (1.0 / 3.5)) * 1.99 + 0.01;
+
+ case CEM3394_FILTER_RESONANCE:
+ if (voltage < 0.0)
+ return 0.0;
+ else if (voltage > 2.5)
+ return 1.0;
+ else
+ return voltage * (1.0 / 2.5);
+
+ case CEM3394_FILTER_FREQENCY:
+ return chip->filter_zero_freq * pow(2.0, -voltage * (1.0 / 0.375));
+ }
+ return 0.0;
+}
+
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+DEVICE_GET_INFO( cem3394 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(cem3394_state); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( cem3394 ); break;
+ case DEVINFO_FCT_STOP: /* nothing */ break;
+ case DEVINFO_FCT_RESET: /* nothing */ break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "CEM3394"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Analog Synth"); 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;
+ }
+}
+
+
+DEFINE_LEGACY_SOUND_DEVICE(CEM3394, cem3394);
diff --git a/trunk/src/emu/sound/cem3394.h b/trunk/src/emu/sound/cem3394.h
new file mode 100644
index 00000000000..450e80ef670
--- /dev/null
+++ b/trunk/src/emu/sound/cem3394.h
@@ -0,0 +1,50 @@
+#pragma once
+
+#ifndef __CEM3394_H__
+#define __CEM3394_H__
+
+#include "devlegcy.h"
+
+
+#define CEM3394_SAMPLE_RATE (44100*4)
+
+
+/* interface */
+typedef struct _cem3394_interface cem3394_interface;
+struct _cem3394_interface
+{
+ double vco_zero_freq; /* frequency at 0V for VCO */
+ double filter_zero_freq; /* frequency at 0V for filter */
+ void (*external)(device_t *, int, short *);/* external input source */
+};
+
+/* inputs */
+enum
+{
+ CEM3394_VCO_FREQUENCY = 0,
+ CEM3394_MODULATION_AMOUNT,
+ CEM3394_WAVE_SELECT,
+ CEM3394_PULSE_WIDTH,
+ CEM3394_MIXER_BALANCE,
+ CEM3394_FILTER_RESONANCE,
+ CEM3394_FILTER_FREQENCY,
+ CEM3394_FINAL_GAIN
+};
+
+/* set the voltage going to a particular parameter */
+void cem3394_set_voltage(device_t *device, int input, double voltage);
+
+/* get the translated parameter associated with the given input as follows:
+ CEM3394_VCO_FREQUENCY: frequency in Hz
+ CEM3394_MODULATION_AMOUNT: scale factor, 0.0 to 2.0
+ CEM3394_WAVE_SELECT: voltage from this line
+ CEM3394_PULSE_WIDTH: width fraction, from 0.0 to 1.0
+ CEM3394_MIXER_BALANCE: balance, from -1.0 to 1.0
+ CEM3394_FILTER_RESONANCE: resonance, from 0.0 to 1.0
+ CEM3394_FILTER_FREQENCY: frequency, in Hz
+ CEM3394_FINAL_GAIN: gain, in dB */
+double cem3394_get_parameter(device_t *device, int input);
+
+DECLARE_LEGACY_SOUND_DEVICE(CEM3394, cem3394);
+
+#endif /* __CEM3394_H__ */
diff --git a/trunk/src/emu/sound/dac.c b/trunk/src/emu/sound/dac.c
new file mode 100644
index 00000000000..57b5171cc22
--- /dev/null
+++ b/trunk/src/emu/sound/dac.c
@@ -0,0 +1,159 @@
+#include "emu.h"
+#include "dac.h"
+
+
+/* default to 4x oversampling */
+#define DEFAULT_SAMPLE_RATE (48000 * 4)
+
+
+typedef struct _dac_state dac_state;
+struct _dac_state
+{
+ sound_stream *channel;
+ INT16 output;
+ INT16 UnsignedVolTable[256];
+ INT16 SignedVolTable[256];
+};
+
+
+INLINE dac_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == DAC);
+ return (dac_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+static STREAM_UPDATE( DAC_update )
+{
+ dac_state *info = (dac_state *)param;
+ stream_sample_t *buffer = outputs[0];
+ INT16 out = info->output;
+
+ while (samples--) *(buffer++) = out;
+}
+
+
+void dac_data_w(device_t *device, UINT8 data)
+{
+ dac_state *info = get_safe_token(device);
+ INT16 out = info->UnsignedVolTable[data];
+
+ if (info->output != out)
+ {
+ /* update the output buffer before changing the registers */
+ info->channel->update();
+ info->output = out;
+ }
+}
+
+
+void dac_signed_data_w(device_t *device, UINT8 data)
+{
+ dac_state *info = get_safe_token(device);
+ INT16 out = info->SignedVolTable[data];
+
+ if (info->output != out)
+ {
+ /* update the output buffer before changing the registers */
+ info->channel->update();
+ info->output = out;
+ }
+}
+
+
+void dac_data_16_w(device_t *device, UINT16 data)
+{
+ dac_state *info = get_safe_token(device);
+ INT16 out = data >> 1; /* range 0..32767 */
+
+ if (info->output != out)
+ {
+ /* update the output buffer before changing the registers */
+ info->channel->update();
+ info->output = out;
+ }
+}
+
+
+void dac_signed_data_16_w(device_t *device, UINT16 data)
+{
+ dac_state *info = get_safe_token(device);
+ INT16 out = (INT32)data - (INT32)0x08000; /* range -32768..32767 */
+ /* casts avoid potential overflow on some ABIs */
+
+ if (info->output != out)
+ {
+ /* update the output buffer before changing the registers */
+ info->channel->update();
+ info->output = out;
+ }
+}
+
+
+static void DAC_build_voltable(dac_state *info)
+{
+ int i;
+
+ /* build volume table (linear) */
+ for (i = 0;i < 256;i++)
+ {
+ info->UnsignedVolTable[i] = i * 0x101 / 2; /* range 0..32767 */
+ info->SignedVolTable[i] = i * 0x101 - 0x8000; /* range -32768..32767 */
+ }
+}
+
+
+static DEVICE_START( dac )
+{
+ dac_state *info = get_safe_token(device);
+
+ DAC_build_voltable(info);
+
+ info->channel = device->machine().sound().stream_alloc(*device,0,1,device->clock() ? device->clock() : DEFAULT_SAMPLE_RATE,info,DAC_update);
+ info->output = 0;
+
+ device->save_item(NAME(info->output));
+}
+
+
+
+WRITE8_DEVICE_HANDLER( dac_w )
+{
+ dac_data_w(device, data);
+}
+
+WRITE8_DEVICE_HANDLER( dac_signed_w )
+{
+ dac_signed_data_w(device, data);
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+DEVICE_GET_INFO( dac )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(dac_state); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( dac ); break;
+ case DEVINFO_FCT_STOP: /* nothing */ break;
+ case DEVINFO_FCT_RESET: /* nothing */ break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "DAC"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "DAC"); 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;
+ }
+}
+
+
+DEFINE_LEGACY_SOUND_DEVICE(DAC, dac);
diff --git a/trunk/src/emu/sound/dac.h b/trunk/src/emu/sound/dac.h
new file mode 100644
index 00000000000..1429a2e5643
--- /dev/null
+++ b/trunk/src/emu/sound/dac.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#ifndef __DAC_H__
+#define __DAC_H__
+
+#include "devlegcy.h"
+
+void dac_data_w(device_t *device, UINT8 data) ATTR_NONNULL(1);
+void dac_signed_data_w(device_t *device, UINT8 data) ATTR_NONNULL(1);
+void dac_data_16_w(device_t *device, UINT16 data) ATTR_NONNULL(1);
+void dac_signed_data_16_w(device_t *device, UINT16 data) ATTR_NONNULL(1);
+
+WRITE8_DEVICE_HANDLER( dac_w );
+WRITE8_DEVICE_HANDLER( dac_signed_w );
+
+DECLARE_LEGACY_SOUND_DEVICE(DAC, dac);
+
+#endif /* __DAC_H__ */
diff --git a/trunk/src/emu/sound/digitalk.c b/trunk/src/emu/sound/digitalk.c
new file mode 100644
index 00000000000..25948e43fab
--- /dev/null
+++ b/trunk/src/emu/sound/digitalk.c
@@ -0,0 +1,708 @@
+#include "emu.h"
+#include "digitalk.h"
+
+/*
+ National Semiconductor's Digitalker, also known as MM54104.
+
+This is a sample decompression chip where the codec is very
+specialized for speech.
+
+ - Driver history
+
+The history of this driver is a little strange. The real
+reverse-engineering work has been done by Kevin Horton
+(single-stepping the chip and everything) with assistance by Lord
+Nightmare who had done the work (with help from Mr. Horton) on the tsi
+s14001a, a predecessor of the digitalker. Mr. Horton was not
+interested in publishing his findings, but provided full-rate
+resynthesized samples for the game scorpion. This driver is the
+result of analyzing these samples.
+
+
+ - The Chip
+
+Pinout from chipdir, added there by Agustin Yado. Added rompwr.
+Package is DIP40. Standard osc is 4MHz, maximum is 5Mhz.
+
+ +--()--+
+ osc in | 1 40| vdd
+ osc out | 2 39| speech out
+ cs | 3 38| adr 13
+ wr | 4 37| adr 12
+ rompwr | 5 36| adr 11
+ intr | 6 35| adr 10
+ cms | 7 34| adr 9
+ d0 | 8 33| adr 8
+ d1 | 9 32| adr 7
+ d2 |10 31| adr 6
+ d3 |11 30| adr 5
+ d4 |12 29| adr 4
+ d5 |13 28| adr 3
+ d6 |14 27| adr 2
+ d7 |15 26| adr 1
+ rdata 0 |16 25| adr 0
+ rdata 1 |17 24| rdata 7
+ rdata 2 |18 23| rdata 6
+ rdata 3 |19 22| rdata 5
+ vss |20 21| rdata 4
+ +------+
+
+Pin functions, excerpt from
+http://www.ski.org/Rehab/sktf/vol06no1Winter1985.html, slightly modified
+"Smith-Kettlewell Technical File, Vol 6, No 1, winter 1985"
+
+ On the controller chip, pin 40 is VCC, while pin 20 is ground. VCC
+ for this chip is between 7 and 11 VDC, and pin 40 is bypassed to
+ pin 20 by 0.1uF. Maximum current is listed at 45mA.
+
+ Pin 3 is called "Chip Select Not," and can be taken high to "open"
+ the input address and control lines. This is used in cases where
+ the Digitalker is connected to a computer bus, and the address
+ lines need to be floated while the bus is doing something else. In
+ other words, taking pin 3 high makes the Digitalker turn a deaf
+ ear to all of its inputs.
+
+ Pin 4 is "Write Not," and, as mentioned before, is brought low to
+ load an address into the controller, then brought high again to
+ start speech. In other words, this is the pin by which you
+ "trigger" the Digitalker.
+
+ Pin 5 is "Not ROM-Power Enable," an output which can be used to
+ control the power to the ROM's. This is used in cases of battery
+ supply where current drain is important; the ROM's will have their
+ power controlled by the controller.
+
+ Pin 6 is the "Interrupt Output," (equivalent to the "Busy Line" of
+ the old TSI Speech Board); this line goes low when an address is
+ loaded into the chip, then goes high again when speech is
+ finished. This signal can be used to control the driver circuitry
+ (or other controlling device), in which case it tells the driver
+ to "Hold the phone!" while the speech is running. Pin 7 is called
+ "CMS," and its state controls the action of the "Write Not"
+ line. With pin 7 low, the operation of pin 4 is as described. If
+ pin 7 is brought high, raising pin 4 high after loading an address
+ serves only to reset the interrupt and does not start speech. This
+ facility is probably intended for use where the interrupt line
+ really controls the hardware interrupt of a computer, and where
+ the program taking care of the interrupt may not have another word
+ to say every time the Digitalker is finished. I have found no
+ particular use for pin 7, and I simply ground it for normal
+ operation.
+
+ Pins 8 through 15 are the eight input address lines, with pin 8
+ being the most significant BIT and pin 15 being least
+ significant. These address lines are "active high." They should
+ never be left open. They are TTL-compatible; this means that logic
+ low is ground and logic high is plus 5VDC. (Actually, being MOS
+ inputs, you can take them as high as the VCC on the controller,
+ but a 5V supply is required for the ROM's anyhow -- it's there if
+ you want to use 5V.)
+
+ Pins 16 through 24 are the eight data lines which bring data from
+ the ROMs to the controller, with pin 16 being called "ROM Data
+ 1," and pin 24 being "ROM Data 8."
+
+ Pins 25 through 38 are the fourteen address lines which select
+ location in the ROM's to be read by the controller. Pin 25 is
+ "Address 0," pin 38 is "Address 13."
+
+
+ - Codec
+
+The codec stems from the standard model for voiced speech generation:
+a stream of impulses at the pitch frequency followed by an
+articulation filter. Both of those are considered slowly varying.
+
+ pitch filter voiced sound
+ |||||||||| * /\/\ = ~~~~
+
+The first compression effect is by forcing the filter to be
+zero-phase. That makes the periods perfectly symmetrical around the
+pitch pulse. The voiced speech is as a result extracted as a number
+of symmetric periods, centered on the pitch pulses.
+
+Following that, two quantizations are done. First, the pitch
+frequency is quantized to one of 32 values (see pitch_vals), going
+from ~80 to 200Hz. Then the volume is selected among 8 possible
+values in an exponential scale, and the amplitudes are quantized as a
+4-bit signed value. The period is time-warped to make it exactly 128
+samples long.
+
+The next step of the compression is to select which harnomics will be
+kept. The choices are to keep only the even ones or only the odd
+ones. Dropping half the harmonics allow to encode the period in only
+32 samples, using the fact that a period, for a zero-phase-at-center,
+half-harmonics signal, looks like:
+
+ even harmonics: /\/\ odd harmonics: _/\_
+
+Where / = block of 32 samples
+ \ = same block reversed
+ _ = 32 zeroes
+
+So we're left with 32 4-bit samples to encode, which is done using a
+2-bit adpcm. The adaptative part is done by using a fixed 16-deltas
+table indexed by the current and the previous encoded value.
+
+Added to all that is the possibility of repeating such a period while
+increasing or decreasing the pitch frequency.
+
+
+For non-voiced speech or non-speech an alternative mode is available
+where an equivalent period cutting, frequency and amplitude
+quantization is done, but the whole 128 samples are adpcm-encoded.
+
+
+Finally, silent zones are compressed specifically by storing their
+lenghts.
+
+
+Decoding is simpler. The 128-samples waveform is decoded using the
+adpcm data and mirroring/zeroing as needed in the voiced case. The
+pitch is taken into account by modulating a 1MHz (clock/4) signal at
+the pitch frequency multiplied by 128. pitch_vals in is practice this
+modulation interval, hence its 128us base unit to compute the pitch
+period.
+
+
+ - Rom organization
+
+The rom starts with a vector of 16-bits little endian values which are
+the addresses of the segments table for the samples. The segments data
+is a vector of 24-bits little-endian values organized as such:
+
+ adr+2 adr+1 adr
+ MMAAAAAA AAAAAAAA ERRRSSSS
+
+ M: Segment base waveforms compression mode (0-3)
+ A: Segment base waveforms data address (0-16383)
+ R: Repeat count (1-8)
+ S: Number of waveforms (1-16)
+ E: Last segment of the sample (flag)
+
+Decoding stops after having decoded a segment with the E bit set. A
+final 8.192ms silence is systematically added.
+
+A == 0 means silence. Duration is 5.12ms*(R+1)*(S+1), or in other
+terms a full decode of all-zero waveforms at maximal pitch frequency
+(pitch code 31).
+
+
+A != 0 means sound. The sound data starts at that offset. The
+encoding method is selected with M:
+
+ 0: odd-harmonics voiced mode
+ 2: even-harmonics voiced mode
+ 3: unvoiced/non-speech mode
+
+Mode 1 is not supported because it is not present in the available
+samples, hence unknown.
+
+
+ Voiced mode (9 bytes/waveform):
+
+ VVVPPPPP AAAAAAAAx8 - First waveform
+ VVVDCCCC AAAAAAAAx8 - Following waveforms
+
+V: Volume (first index in pcm_levels)
+P: Pitch index
+A: adpcm data
+D: Pitch index change direction (0=increase, 1=decrease)
+C: Pitch index maximum change
+
+The waveforms are encoded with a 2-bit adpcm, lowest pair of bits
+first. Deltas are a size-16 vector, indexed with the previous adpcm
+value in bits 0&1 and the current in bits 2&3. Voiced speech modes
+use table delta1 and initial "previous" value 2.
+
+Each waveform is repeated R times at volume V. First waveform has
+fixed pitch P. Subsequent waveforms change the pitch index by 1 every
+repeat (including the first) up to a change of C. D indicates whether
+it's an increment or a decrement.
+
+
+ Unvoiced mode (33 bytes/waveform):
+
+ VVVPPPPP AAAAAAAAx32 - All waveforms
+
+V: Volume (first index in pcm_levels)
+P: Pitch index
+A: adpcm data
+
+Adpcm encoding is identical but using delta2 table and an initial
+value of 1. Every waveform is played consecutively and the adpcm
+previous value or dac level is not reset between waveforms. The
+complete set of waveforms is repeated R times.
+
+*/
+
+
+typedef struct {
+ const UINT8 *rom;
+ device_t *device;
+ sound_stream *stream;
+
+ // Port/lines state
+ UINT8 data, cs, cms, wr, intr;
+
+ // Current decoding state
+ UINT16 bpos, apos;
+ UINT8 mode, cur_segment, cur_repeat, segments, repeats;
+ UINT8 prev_pitch, pitch, pitch_pos;
+ UINT8 stop_after, cur_dac, cur_bits;
+
+ // Zero-range size
+ UINT32 zero_count; // 0 for done
+
+ // Waveform and current index in it
+ UINT8 dac_index; // 128 for done
+ INT16 dac[128];
+
+} digitalker;
+
+// Quantized intensity values, first index is the volume, second the
+// intensity (positive half only, real value goes -8..7)
+static const short pcm_levels[8][8] = {
+ { 473, 945, 1418, 1890, 2363, 2835, 3308, 3781 },
+ { 655, 1310, 1966, 2621, 3276, 3931, 4586, 5242 },
+ { 925, 1851, 2776, 3702, 4627, 5553, 6478, 7404 },
+ { 1249, 2498, 3747, 4996, 6245, 7494, 8743, 9992 },
+ { 1638, 3276, 4914, 6552, 8190, 9828, 11466, 13104 },
+ { 2252, 4504, 6757, 9009, 11261, 13514, 15766, 18018 },
+ { 2989, 5979, 8968, 11957, 14947, 17936, 20925, 23915 },
+ { 4095, 8190, 12285, 16380, 20475, 24570, 28665, 32760 },
+};
+
+static const int delta1[16] = { -4, -4, -1, -1, -2, -2, 0, 0, 0, 0, 2, 2, 1, 1, 4, 4 };
+static const int delta2[16] = { 0, -1, -2, -3, 1, 0, -1, -2, 2, 1, 0, -1, 3, 2, 1, 0 };
+
+// Frequency quantizations, values are in units of 128us.
+
+static const int pitch_vals[32] = {
+ 97, 95, 92, 89, 87, 84, 82, 80, 77, 75, 73, 71, 69, 67, 65, 63,
+ 61, 60, 58, 56, 55, 53, 52, 50, 49, 48, 46, 45, 43, 42, 41, 40
+};
+
+
+INLINE digitalker *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == DIGITALKER);
+ return (digitalker *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+static void digitalker_write(digitalker *dg, UINT8 *adr, UINT8 vol, INT8 dac)
+{
+ INT16 v;
+ dac &= 15;
+ if(dac >= 9)
+ v = -pcm_levels[vol][15-dac];
+ else if(dac)
+ v = pcm_levels[vol][dac-1];
+ else
+ v = 0;
+ dg->dac[(*adr)++] = v;
+}
+
+static UINT8 digitalker_pitch_next(UINT8 val, UINT8 prev, int step)
+{
+ int delta, nv;
+
+ delta = val & 0xf;
+ if(delta > step + 1)
+ delta = step + 1;
+ if(val & 0x10)
+ delta = -delta;
+
+ nv = prev + delta;
+ if(nv < 0)
+ nv = 0;
+ else if(nv > 31)
+ nv = 31;
+ return nv;
+}
+
+static void digitalker_set_intr(digitalker *dg, UINT8 intr)
+{
+ dg->intr = intr;
+}
+
+static void digitalker_start_command(digitalker *dg, UINT8 cmd)
+{
+ dg->bpos = ((dg->rom[cmd*2] << 8) | dg->rom[cmd*2+1]) & 0x3fff;
+ dg->cur_segment = dg->segments = dg->cur_repeat = dg->repeats = 0;
+ dg->dac_index = 128;
+ dg->zero_count = 0;
+ digitalker_set_intr(dg, 0);
+}
+
+static void digitalker_step_mode_0(digitalker *dg)
+{
+ INT8 dac = 0;
+ int i, k, l;
+ UINT8 wpos = 0;
+ UINT8 h = dg->rom[dg->apos];
+ UINT16 bits = 0x80;
+ UINT8 vol = h >> 5;
+ UINT8 pitch_id = dg->cur_segment ? digitalker_pitch_next(h, dg->prev_pitch, dg->cur_repeat) : h & 0x1f;
+
+ dg->pitch = pitch_vals[pitch_id];
+
+ for(i=0; i<32; i++)
+ dg->dac[wpos++] = 0;
+
+ for(k=1; k != 9; k++) {
+ bits |= dg->rom[dg->apos+k] << 8;
+ for(l=0; l<4; l++) {
+ dac += delta1[(bits >> (6+2*l)) & 15];
+ digitalker_write(dg, &wpos, vol, dac);
+ }
+ bits >>= 8;
+ }
+
+ digitalker_write(dg, &wpos, vol, dac);
+
+ for(k=7; k >= 0; k--) {
+ bits = (bits << 8) | (k ? dg->rom[dg->apos+k] : 0x80);
+ for(l=3; l>=0; l--) {
+ dac -= delta1[(bits >> (6+2*l)) & 15];
+ digitalker_write(dg, &wpos, vol, dac);
+ }
+ }
+
+ for(i=0; i<31; i++)
+ dg->dac[wpos++] = 0;
+
+ dg->cur_repeat++;
+ if(dg->cur_repeat == dg->repeats) {
+ dg->apos += 9;
+ dg->prev_pitch = pitch_id;
+ dg->cur_repeat = 0;
+ dg->cur_segment++;
+ }
+}
+
+static void digitalker_step_mode_1(digitalker *dg)
+{
+ logerror("Digitalker mode 1 unsupported");
+ dg->zero_count = 1;
+ dg->cur_segment = dg->segments;
+}
+
+static void digitalker_step_mode_2(digitalker *dg)
+{
+ INT8 dac = 0;
+ int k, l;
+ UINT8 wpos=0;
+ UINT8 h = dg->rom[dg->apos];
+ UINT16 bits = 0x80;
+ UINT8 vol = h >> 5;
+ UINT8 pitch_id = dg->cur_segment ? digitalker_pitch_next(h, dg->prev_pitch, dg->cur_repeat) : h & 0x1f;
+
+ dg->pitch = pitch_vals[pitch_id];
+
+ for(k=1; k != 9; k++) {
+ bits |= dg->rom[dg->apos+k] << 8;
+ for(l=0; l<4; l++) {
+ dac += delta1[(bits >> (6+2*l)) & 15];
+ digitalker_write(dg, &wpos, vol, dac);
+ }
+ bits >>= 8;
+ }
+
+ digitalker_write(dg, &wpos, vol, dac);
+
+ for(k=7; k >= 0; k--) {
+ int limit = k ? 0 : 1;
+ bits = (bits << 8) | (k ? dg->rom[dg->apos+k] : 0x80);
+ for(l=3; l>=limit; l--) {
+ dac -= delta1[(bits >> (6+2*l)) & 15];
+ digitalker_write(dg, &wpos, vol, dac);
+ }
+ }
+
+ digitalker_write(dg, &wpos, vol, dac);
+
+ for(k=1; k != 9; k++) {
+ int start = k == 1 ? 1 : 0;
+ bits |= dg->rom[dg->apos+k] << 8;
+ for(l=start; l<4; l++) {
+ dac += delta1[(bits >> (6+2*l)) & 15];
+ digitalker_write(dg, &wpos, vol, dac);
+ }
+ bits >>= 8;
+ }
+
+ digitalker_write(dg, &wpos, vol, dac);
+
+ for(k=7; k >= 0; k--) {
+ int limit = k ? 0 : 1;
+ bits = (bits << 8) | (k ? dg->rom[dg->apos+k] : 0x80);
+ for(l=3; l>=limit; l--) {
+ dac -= delta1[(bits >> (6+2*l)) & 15];
+ digitalker_write(dg, &wpos, vol, dac);
+ }
+ }
+
+ dg->cur_repeat++;
+ if(dg->cur_repeat == dg->repeats) {
+ dg->apos += 9;
+ dg->prev_pitch = pitch_id;
+ dg->cur_repeat = 0;
+ dg->cur_segment++;
+ }
+}
+
+static void digitalker_step_mode_3(digitalker *dg)
+{
+ UINT8 h = dg->rom[dg->apos];
+ UINT8 vol = h >> 5;
+ UINT16 bits;
+ UINT8 dac, apos, wpos;
+ int k, l;
+
+ dg->pitch = pitch_vals[h & 0x1f];
+ if(dg->cur_segment == 0 && dg->cur_repeat == 0) {
+ dg->cur_bits = 0x40;
+ dg->cur_dac = 0;
+ }
+ bits = dg->cur_bits;
+ dac = 0;
+
+ apos = dg->apos + 1 + 32*dg->cur_segment;
+ wpos = 0;
+ for(k=0; k != 32; k++) {
+ bits |= dg->rom[apos++] << 8;
+ for(l=0; l<4; l++) {
+ dac += delta2[(bits >> (6+2*l)) & 15];
+ digitalker_write(dg, &wpos, vol, dac);
+ }
+ bits >>= 8;
+ }
+
+ dg->cur_bits = bits;
+ dg->cur_dac = dac;
+
+ dg->cur_segment++;
+ if(dg->cur_segment == dg->segments) {
+ dg->cur_segment = 0;
+ dg->cur_repeat++;
+ }
+}
+
+static void digitalker_step(digitalker *dg)
+{
+ if(dg->cur_segment == dg->segments || dg->cur_repeat == dg->repeats) {
+ if(dg->stop_after == 0 && dg->bpos == 0xffff)
+ return;
+ if(dg->stop_after == 0) {
+ UINT8 v1 = dg->rom[dg->bpos++];
+ UINT8 v2 = dg->rom[dg->bpos++];
+ UINT8 v3 = dg->rom[dg->bpos++];
+ dg->apos = v2 | ((v3 << 8) & 0x3f00);
+ dg->segments = (v1 & 15) + 1;
+ dg->repeats = ((v1 >> 4) & 7) + 1;
+ dg->mode = (v3 >> 6) & 3;
+ dg->stop_after = (v1 & 0x80) != 0;
+
+ dg->cur_segment = 0;
+ dg->cur_repeat = 0;
+
+ if(!dg->apos) {
+ dg->zero_count = 40*128*dg->segments*dg->repeats;
+ dg->segments = 0;
+ dg->repeats = 0;
+ return;
+ }
+ } else if(dg->stop_after == 1) {
+ dg->bpos = 0xffff;
+ dg->zero_count = 81920;
+ dg->stop_after = 2;
+ dg->cur_segment = 0;
+ dg->cur_repeat = 0;
+ dg->segments = 0;
+ dg->repeats = 0;
+ } else {
+ dg->stop_after = 0;
+ digitalker_set_intr(dg, 1);
+ }
+ }
+
+ switch(dg->mode) {
+ case 0: digitalker_step_mode_0(dg); break;
+ case 1: digitalker_step_mode_1(dg); break;
+ case 2: digitalker_step_mode_2(dg); break;
+ case 3: digitalker_step_mode_3(dg); break;
+ }
+ if(!dg->zero_count)
+ dg->dac_index = 0;
+}
+
+static STREAM_UPDATE(digitalker_update)
+{
+ digitalker *dg = (digitalker *)param;
+ stream_sample_t *sout = outputs[0];
+ int cpos = 0;
+ while(cpos != samples) {
+ if(dg->zero_count == 0 && dg->dac_index == 128)
+ digitalker_step(dg);
+
+ if(dg->zero_count) {
+ int n = samples - cpos;
+ int i;
+ if(n > dg->zero_count)
+ n = dg->zero_count;
+ for(i=0; i != n; i++)
+ sout[cpos++] = 0;
+ dg->zero_count -= n;
+
+ } else if(dg->dac_index != 128) {
+ while(cpos != samples && dg->dac_index != 128) {
+ short v = dg->dac[dg->dac_index];
+ int pp = dg->pitch_pos;
+ while(cpos != samples && pp != dg->pitch) {
+ sout[cpos++] = v;
+ pp++;
+ }
+ if(pp == dg->pitch) {
+ pp = 0;
+ dg->dac_index++;
+ }
+ dg->pitch_pos = pp;
+ }
+
+ } else {
+ while(cpos != samples)
+ sout[cpos++] = 0;
+ }
+ }
+}
+
+static void digitalker_cs_w(digitalker *dg, int line)
+{
+ UINT8 cs = line == ASSERT_LINE ? 1 : 0;
+ if(cs == dg->cs)
+ return;
+ dg->cs = cs;
+ if(cs)
+ return;
+ if(!dg->wr) {
+ if(dg->cms)
+ digitalker_set_intr(dg, 1);
+ else
+ digitalker_start_command(dg, dg->data);
+ }
+}
+
+static void digitalker_cms_w(digitalker *dg, int line)
+{
+ dg->cms = line == ASSERT_LINE ? 1 : 0;
+}
+
+static void digitalker_wr_w(digitalker *dg, int line)
+{
+ UINT8 wr = line == ASSERT_LINE ? 1 : 0;
+ if(wr == dg->wr)
+ return;
+ dg->wr = wr;
+ if(wr || dg->cs)
+ return;
+ if(dg->cms)
+ digitalker_set_intr(dg, 1);
+ else
+ digitalker_start_command(dg, dg->data);
+}
+
+static int digitalker_intr_r(digitalker *dg)
+{
+ return dg->intr ? ASSERT_LINE : CLEAR_LINE;
+}
+
+static void digitalker_register_for_save(digitalker *dg)
+{
+ dg->device->save_item(NAME(dg->data));
+ dg->device->save_item(NAME(dg->cs));
+ dg->device->save_item(NAME(dg->cms));
+ dg->device->save_item(NAME(dg->wr));
+ dg->device->save_item(NAME(dg->intr));
+ dg->device->save_item(NAME(dg->bpos));
+ dg->device->save_item(NAME(dg->apos));
+ dg->device->save_item(NAME(dg->mode));
+ dg->device->save_item(NAME(dg->cur_segment));
+ dg->device->save_item(NAME(dg->cur_repeat));
+ dg->device->save_item(NAME(dg->segments));
+ dg->device->save_item(NAME(dg->repeats));
+ dg->device->save_item(NAME(dg->prev_pitch));
+ dg->device->save_item(NAME(dg->pitch));
+ dg->device->save_item(NAME(dg->pitch_pos));
+ dg->device->save_item(NAME(dg->stop_after));
+ dg->device->save_item(NAME(dg->cur_dac));
+ dg->device->save_item(NAME(dg->cur_bits));
+ dg->device->save_item(NAME(dg->zero_count));
+ dg->device->save_item(NAME(dg->dac_index));
+ dg->device->save_item(NAME(dg->dac));
+}
+
+static DEVICE_START(digitalker)
+{
+ digitalker *dg = get_safe_token(device);
+ dg->device = device;
+ dg->rom = device->machine().region(device->tag())->base();
+ dg->stream = device->machine().sound().stream_alloc(*device, 0, 1, device->clock()/4, dg, digitalker_update);
+ dg->dac_index = 128;
+ dg->data = 0xff;
+ dg->cs = dg->cms = dg->wr = 1;
+ dg->bpos = 0xffff;
+ digitalker_set_intr(dg, 1);
+
+ digitalker_register_for_save(dg);
+}
+
+DEVICE_GET_INFO(digitalker)
+{
+ switch(state) {
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(digitalker); break;
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(digitalker); break;
+ case DEVINFO_FCT_STOP: break;
+ case DEVINFO_FCT_RESET: break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "Digitalker"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "National Semiconductor"); 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 Olivier Galibert"); break;
+ }
+}
+
+void digitalker_0_cs_w(device_t *device, int line)
+{
+ digitalker *dg = get_safe_token(device);
+ digitalker_cs_w(dg, line);
+}
+
+void digitalker_0_cms_w(device_t *device, int line)
+{
+ digitalker *dg = get_safe_token(device);
+ digitalker_cms_w(dg, line);
+}
+
+void digitalker_0_wr_w(device_t *device, int line)
+{
+ digitalker *dg = get_safe_token(device);
+ digitalker_wr_w(dg, line);
+}
+
+int digitalker_0_intr_r(device_t *device)
+{
+ digitalker *dg = get_safe_token(device);
+ return digitalker_intr_r(dg);
+}
+
+WRITE8_DEVICE_HANDLER( digitalker_data_w )
+{
+ digitalker *dg = get_safe_token(device);
+ dg->data = data;
+}
+
+
+DEFINE_LEGACY_SOUND_DEVICE(DIGITALKER, digitalker);
diff --git a/trunk/src/emu/sound/digitalk.h b/trunk/src/emu/sound/digitalk.h
new file mode 100644
index 00000000000..0a5f232d5e9
--- /dev/null
+++ b/trunk/src/emu/sound/digitalk.h
@@ -0,0 +1,14 @@
+#ifndef _DIGITALKER_H_
+#define _DIGITALKER_H_
+
+#include "devlegcy.h"
+
+void digitalker_0_cs_w(device_t *device, int line);
+void digitalker_0_cms_w(device_t *device, int line);
+void digitalker_0_wr_w(device_t *device, int line);
+int digitalker_0_intr_r(device_t *device);
+WRITE8_DEVICE_HANDLER(digitalker_data_w);
+
+DECLARE_LEGACY_SOUND_DEVICE(DIGITALKER, digitalker);
+
+#endif
diff --git a/trunk/src/emu/sound/disc_cls.h b/trunk/src/emu/sound/disc_cls.h
new file mode 100644
index 00000000000..e6be420716f
--- /dev/null
+++ b/trunk/src/emu/sound/disc_cls.h
@@ -0,0 +1,257 @@
+#pragma once
+
+#ifndef __DISC_CLS_H__
+#define __DISC_CLS_H__
+
+/***********************************************************************
+ *
+ * MAME - Discrete sound system emulation library
+ *
+ * Written by Keith Wilkins (mame@esplexo.co.uk)
+ *
+ * (c) K.Wilkins 2000
+ *
+ * Coding started in November 2000
+ *
+ * Additions/bugfix February 2003 - D.Renaud, F.Palazzolo, K.Wilkins
+ * Discrete parallel tasks 2009 - Couriersud
+ * Discrete classes 2010 - Couriersud
+ *
+ ***********************************************************************/
+
+#define DISCRETE_CLASS_NAME(_name) discrete_ ## _name ## _node
+
+#define DISCRETE_CLASS_INPUT(_name, _num) inline double _name (void) { return *(m_input[_num]); }
+
+#define DISCRETE_CLASS_CONSTRUCTOR(_name, _base) \
+ public: \
+ DISCRETE_CLASS_NAME(_name)() \
+ : DISCRETE_CLASS_NAME(_base)() { }
+
+#define DISCRETE_CLASS_DESTRUCTOR(_name) \
+ public: \
+ virtual ~ DISCRETE_CLASS_NAME(_name)(void) { }
+
+#define DISCRETE_CLASS_STEP_RESET(_name, _maxout, _priv) \
+class DISCRETE_CLASS_NAME(_name): public discrete_base_node, public discrete_step_interface \
+{ \
+ DISCRETE_CLASS_CONSTRUCTOR(_name, base) \
+ DISCRETE_CLASS_DESTRUCTOR(_name) \
+public: \
+ void step(void); \
+ void reset(void); \
+ int max_output(void) { return _maxout; } \
+private: \
+ _priv \
+}
+
+#define DISCRETE_CLASS_STEP(_name, _maxout, _priv) \
+class DISCRETE_CLASS_NAME(_name): public discrete_base_node, public discrete_step_interface \
+{ \
+ DISCRETE_CLASS_CONSTRUCTOR(_name, base) \
+ DISCRETE_CLASS_DESTRUCTOR(_name) \
+public: \
+ void step(void); \
+ void reset(void) { this->step(); } \
+ int max_output(void) { return _maxout; } \
+private: \
+ _priv \
+}
+
+#define DISCRETE_CLASS_RESET(_name, _maxout) \
+class DISCRETE_CLASS_NAME(_name): public discrete_base_node \
+{ \
+ DISCRETE_CLASS_CONSTRUCTOR(_name, base) \
+ DISCRETE_CLASS_DESTRUCTOR(_name) \
+public: \
+ void reset(void); \
+ int max_output(void) { return _maxout; } \
+}
+
+#define DISCRETE_CLASS(_name, _maxout, _priv) \
+class DISCRETE_CLASS_NAME(_name): public discrete_base_node, public discrete_step_interface \
+{ \
+ DISCRETE_CLASS_DESTRUCTOR(_name) \
+ DISCRETE_CLASS_CONSTRUCTOR(_name, base) \
+public: \
+ void step(void); \
+ void reset(void); \
+ void start(void); \
+ void stop(void); \
+ int max_output(void) { return _maxout; } \
+private: \
+ _priv \
+}
+
+class DISCRETE_CLASS_NAME(special): public discrete_base_node
+{
+ DISCRETE_CLASS_CONSTRUCTOR(special, base)
+ DISCRETE_CLASS_DESTRUCTOR(special)
+public:
+ int max_output(void) { return 0; }
+};
+
+class DISCRETE_CLASS_NAME(unimplemented): public discrete_base_node
+{
+ DISCRETE_CLASS_CONSTRUCTOR(unimplemented, base)
+ DISCRETE_CLASS_DESTRUCTOR(unimplemented)
+public:
+ int max_output(void) { return 0; }
+};
+
+/*************************************
+ *
+ * disc_sys.c
+ *
+ *************************************/
+
+class DISCRETE_CLASS_NAME(dso_output): public discrete_base_node,
+ public discrete_sound_output_interface,
+ public discrete_step_interface
+{
+ DISCRETE_CLASS_CONSTRUCTOR(dso_output, base)
+ DISCRETE_CLASS_DESTRUCTOR(dso_output)
+public:
+ void step(void) {
+ /* Add gain to the output and put into the buffers */
+ /* Clipping will be handled by the main sound system */
+ double val = DISCRETE_INPUT(0) * DISCRETE_INPUT(1);
+ *m_ptr++ = val;
+ }
+ int max_output(void) { return 0; }
+ void set_output_ptr(stream_sample_t *ptr) { m_ptr = ptr; }
+private:
+ stream_sample_t *m_ptr;
+};
+
+DISCRETE_CLASS(dso_csvlog, 0,
+ FILE *m_csv_file;
+ INT64 m_sample_num;
+ char m_name[32];
+);
+
+DISCRETE_CLASS(dso_wavlog, 0,
+ wav_file *m_wavfile;
+ char m_name[32];
+);
+
+/*************************************
+ *
+ * disc_inp.c
+ *
+ *************************************/
+
+class DISCRETE_CLASS_NAME(dss_adjustment): public discrete_base_node, public discrete_step_interface
+{
+ DISCRETE_CLASS_CONSTRUCTOR(dss_adjustment, base)
+ DISCRETE_CLASS_DESTRUCTOR(dss_adjustment)
+public:
+ void step(void);
+ void reset(void);
+private:
+ const input_port_config *m_port;
+ INT32 m_lastpval;
+ INT32 m_pmin;
+ double m_pscale;
+ double m_min;
+ double m_scale;
+};
+
+DISCRETE_CLASS_RESET(dss_constant, 1);
+
+class DISCRETE_CLASS_NAME(dss_input_data): public discrete_base_node, public discrete_input_interface
+{
+ DISCRETE_CLASS_DESTRUCTOR(dss_input_data)
+ DISCRETE_CLASS_CONSTRUCTOR(dss_input_data, base)
+public:
+ void reset(void);
+ void input_write(int sub_node, UINT8 data );
+private:
+ double m_gain; /* node gain */
+ double m_offset; /* node offset */
+ UINT8 m_data; /* data written */
+};
+
+class DISCRETE_CLASS_NAME(dss_input_logic): public discrete_base_node, public discrete_input_interface
+{
+ DISCRETE_CLASS_CONSTRUCTOR(dss_input_logic, base)
+ DISCRETE_CLASS_DESTRUCTOR(dss_input_logic)
+public:
+ void reset(void);
+ void input_write(int sub_node, UINT8 data );
+private:
+ double m_gain; /* node gain */
+ double m_offset; /* node offset */
+ UINT8 m_data; /* data written */
+};
+
+class DISCRETE_CLASS_NAME(dss_input_not): public discrete_base_node, public discrete_input_interface
+{
+ DISCRETE_CLASS_CONSTRUCTOR(dss_input_not, base)
+ DISCRETE_CLASS_DESTRUCTOR(dss_input_not)
+public:
+ void reset(void);
+ void input_write(int sub_node, UINT8 data );
+private:
+ double m_gain; /* node gain */
+ double m_offset; /* node offset */
+ UINT8 m_data; /* data written */
+};
+
+class DISCRETE_CLASS_NAME(dss_input_pulse): public discrete_base_node, public discrete_input_interface, public discrete_step_interface
+{
+ DISCRETE_CLASS_CONSTRUCTOR(dss_input_pulse, base)
+ DISCRETE_CLASS_DESTRUCTOR(dss_input_pulse)
+public:
+ void step(void);
+ void reset(void);
+ void input_write(int sub_node, UINT8 data );
+private:
+ double m_gain; /* node gain */
+ double m_offset; /* node offset */
+ UINT8 m_data; /* data written */
+};
+
+class DISCRETE_CLASS_NAME(dss_input_stream): public discrete_base_node, public discrete_input_interface, public discrete_step_interface
+{
+ DISCRETE_CLASS_CONSTRUCTOR(dss_input_stream, base)
+ DISCRETE_CLASS_DESTRUCTOR(dss_input_stream)
+public:
+ void step(void);
+ void reset(void);
+ void start(void);
+ void input_write(int sub_node, UINT8 data );
+ virtual bool is_buffered(void) { return false; }
+
+ /* This is called by discrete_sound_device */
+ void stream_start(void);
+
+//protected:
+ UINT32 m_stream_in_number;
+ stream_sample_t *m_ptr; /* current in ptr for stream */
+private:
+ static STREAM_UPDATE( static_stream_generate );
+ void stream_generate(stream_sample_t **inputs, stream_sample_t **outputs, int samples);
+
+ double m_gain; /* node gain */
+ double m_offset; /* node offset */
+ UINT8 m_data; /* data written */
+ UINT8 m_is_buffered;
+ /* the buffer stream */
+ sound_stream *m_buffer_stream;
+};
+
+class DISCRETE_CLASS_NAME(dss_input_buffer): public DISCRETE_CLASS_NAME(dss_input_stream)
+{
+ DISCRETE_CLASS_CONSTRUCTOR(dss_input_buffer, dss_input_stream)
+ DISCRETE_CLASS_DESTRUCTOR(dss_input_buffer)
+public:
+ bool is_buffered(void) { return true; }
+};
+
+#include "disc_wav.h"
+#include "disc_mth.h"
+#include "disc_flt.h"
+#include "disc_dev.h"
+
+#endif /* __DISCRETE_H__ */
diff --git a/trunk/src/emu/sound/disc_dev.c b/trunk/src/emu/sound/disc_dev.c
new file mode 100644
index 00000000000..a2bdb054889
--- /dev/null
+++ b/trunk/src/emu/sound/disc_dev.c
@@ -0,0 +1,1774 @@
+/************************************************************************
+ *
+ * MAME - Discrete sound system emulation library
+ *
+ * Written by Keith Wilkins (mame@dysfunction.demon.co.uk)
+ *
+ * (c) K.Wilkins 2000
+ * (c) D.Renaud 2003-2004
+ *
+ ************************************************************************
+ *
+ * DSD_555_ASTBL - NE555 Simulation - Astable mode
+ * DSD_555_MSTBL - NE555 Simulation - Monostable mode
+ * DSD_555_CC - NE555 Constant Current VCO
+ * DSD_555_VCO1 - Op-Amp linear ramp based 555 VCO
+ * DSD_566 - NE566 Simulation
+ * DSD_LS624 - 74LS624/629 Simulation
+ *
+ ************************************************************************
+ *
+ * You will notice that the code for a lot of these routines are similar.
+ * I tried to make a common charging routine, but there are too many
+ * minor differences that affect each module.
+ *
+ ************************************************************************/
+
+#define DEFAULT_555_BLEED_R RES_M(10)
+
+/************************************************************************
+ *
+ * DSD_555_ASTBL - - 555 Astable simulation
+ *
+ * input[0] - Reset value
+ * input[1] - R1 value
+ * input[2] - R2 value
+ * input[3] - C value
+ * input[4] - Control Voltage value
+ *
+ * also passed discrete_555_desc structure
+ *
+ * Jan 2004, D Renaud.
+ ************************************************************************/
+#define DSD_555_ASTBL__RESET (! DISCRETE_INPUT(0))
+#define DSD_555_ASTBL__R1 DISCRETE_INPUT(1)
+#define DSD_555_ASTBL__R2 DISCRETE_INPUT(2)
+#define DSD_555_ASTBL__C DISCRETE_INPUT(3)
+#define DSD_555_ASTBL__CTRLV DISCRETE_INPUT(4)
+
+/* bit mask of the above RC inputs */
+#define DSD_555_ASTBL_RC_MASK 0x0e
+
+/* charge/discharge constants */
+#define DSD_555_ASTBL_T_RC_BLEED (DEFAULT_555_BLEED_R * DSD_555_ASTBL__C)
+/* Use quick charge if specified. */
+#define DSD_555_ASTBL_T_RC_CHARGE ((DSD_555_ASTBL__R1 + ((info->options & DISC_555_ASTABLE_HAS_FAST_CHARGE_DIODE) ? 0 : DSD_555_ASTBL__R2)) * DSD_555_ASTBL__C)
+#define DSD_555_ASTBL_T_RC_DISCHARGE (DSD_555_ASTBL__R2 * DSD_555_ASTBL__C)
+
+DISCRETE_STEP(dsd_555_astbl)
+{
+ DISCRETE_DECLARE_INFO(discrete_555_desc)
+
+ int count_f = 0;
+ int count_r = 0;
+ double dt; /* change in time */
+ double x_time = 0; /* time since change happened */
+ double v_cap = m_cap_voltage; /* Current voltage on capacitor, before dt */
+ double v_cap_next = 0; /* Voltage on capacitor, after dt */
+ double v_charge, exponent = 0;
+ UINT8 flip_flop = m_flip_flop;
+ UINT8 update_exponent = 0;
+ double v_out = 0.0;
+
+ /* put commonly used stuff in local variables for speed */
+ double threshold = m_threshold;
+ double trigger = m_trigger;
+
+ if(DSD_555_ASTBL__RESET)
+ {
+ /* We are in RESET */
+ set_output(0, 0);
+ m_flip_flop = 1;
+ m_cap_voltage = 0;
+ return;
+ }
+
+ /* Check: if the Control Voltage node is connected. */
+ if (m_use_ctrlv)
+ {
+ /* If CV is less then .25V, the circuit will oscillate way out of range.
+ * So we will just ignore it when it happens. */
+ if (DSD_555_ASTBL__CTRLV < .25) return;
+ /* If it is a node then calculate thresholds based on Control Voltage */
+ threshold = DSD_555_ASTBL__CTRLV;
+ trigger = DSD_555_ASTBL__CTRLV / 2.0;
+ /* Since the thresholds may have changed we need to update the FF */
+ if (v_cap >= threshold)
+ {
+ flip_flop = 0;
+ count_f++;
+ }
+ else
+ if (v_cap <= trigger)
+ {
+ flip_flop = 1;
+ count_r++;
+ }
+ }
+
+ /* get the v_charge and update each step if it is a node */
+ if (m_v_charge_node != NULL)
+ {
+ v_charge = *m_v_charge_node;
+ if (info->options & DISC_555_ASTABLE_HAS_FAST_CHARGE_DIODE) v_charge -= 0.5;
+ }
+ else
+ v_charge = m_v_charge;
+
+
+ /* Calculate future capacitor voltage.
+ * ref@ http://www.physics.rutgers.edu/ugrad/205/capacitance.html
+ * The formulas from the ref pages have been modified to reflect that we are stepping the change.
+ * dt = time of sample (1/sample frequency)
+ * VC = Voltage across capacitor
+ * VC' = Future voltage across capacitor
+ * Vc = Voltage change
+ * Vr = is the voltage across the resistor. For charging it is Vcc - VC. Discharging it is VC - 0.
+ * R = R1+R2 (for charging) R = R2 for discharging.
+ * Vc = Vr*(1-exp(-dt/(R*C)))
+ * VC' = VC + Vc (for charging) VC' = VC - Vc for discharging.
+ *
+ * We will also need to calculate the amount of time we overshoot the thresholds
+ * dt = amount of time we overshot
+ * Vc = voltage change overshoot
+ * dt = R*C(log(1/(1-(Vc/Vr))))
+ */
+
+ dt = this->sample_time();
+
+ /* Sometimes a switching network is used to setup the capacitance.
+ * These may select no capacitor, causing oscillation to stop.
+ */
+ if (DSD_555_ASTBL__C == 0)
+ {
+ flip_flop = 1;
+ /* The voltage goes high because the cap circuit is open. */
+ v_cap_next = v_charge;
+ v_cap = v_charge;
+ m_cap_voltage = 0;
+ }
+ else
+ {
+ /* Update charge contstants and exponents if nodes changed */
+ if (m_has_rc_nodes && (DSD_555_ASTBL__R1 != m_last_r1 || DSD_555_ASTBL__C != m_last_c || DSD_555_ASTBL__R2 != m_last_r2))
+ {
+ m_t_rc_bleed = DSD_555_ASTBL_T_RC_BLEED;
+ m_t_rc_charge = DSD_555_ASTBL_T_RC_CHARGE;
+ m_t_rc_discharge = DSD_555_ASTBL_T_RC_DISCHARGE;
+ m_exp_bleed = RC_CHARGE_EXP(m_t_rc_bleed);
+ m_exp_charge = RC_CHARGE_EXP(m_t_rc_charge);
+ m_exp_discharge = RC_CHARGE_EXP(m_t_rc_discharge);
+ m_last_r1 = DSD_555_ASTBL__R1;
+ m_last_r2 = DSD_555_ASTBL__R2;
+ m_last_c = DSD_555_ASTBL__C;
+ }
+ /* Keep looping until all toggling in time sample is used up. */
+ do
+ {
+ if (flip_flop)
+ {
+ if (DSD_555_ASTBL__R1 == 0)
+ {
+ /* Oscillation disabled because there is no longer any charge resistor. */
+ /* Bleed the cap due to circuit losses. */
+ if (update_exponent)
+ exponent = RC_CHARGE_EXP_DT(m_t_rc_bleed, dt);
+ else
+ exponent = m_exp_bleed;
+ v_cap_next = v_cap - (v_cap * exponent);
+ dt = 0;
+ }
+ else
+ {
+ /* Charging */
+ if (update_exponent)
+ exponent = RC_CHARGE_EXP_DT(m_t_rc_charge, dt);
+ else
+ exponent = m_exp_charge;
+ v_cap_next = v_cap + ((v_charge - v_cap) * exponent);
+ dt = 0;
+
+ /* has it charged past upper limit? */
+ if (v_cap_next >= threshold)
+ {
+ /* calculate the overshoot time */
+ dt = m_t_rc_charge * log(1.0 / (1.0 - ((v_cap_next - threshold) / (v_charge - v_cap))));
+ x_time = dt;
+ v_cap_next = threshold;
+ flip_flop = 0;
+ count_f++;
+ update_exponent = 1;
+ }
+ }
+ }
+ else
+ {
+ /* Discharging */
+ if(DSD_555_ASTBL__R2 != 0)
+ {
+ if (update_exponent)
+ exponent = RC_CHARGE_EXP_DT(m_t_rc_discharge, dt);
+ else
+ exponent = m_exp_discharge;
+ v_cap_next = v_cap - (v_cap * exponent);
+ dt = 0;
+ }
+ else
+ {
+ /* no discharge resistor so we immediately discharge */
+ v_cap_next = trigger;
+ }
+
+ /* has it discharged past lower limit? */
+ if (v_cap_next <= trigger)
+ {
+ /* calculate the overshoot time */
+ if (v_cap_next < trigger)
+ dt = m_t_rc_discharge * log(1.0 / (1.0 - ((trigger - v_cap_next) / v_cap)));
+ x_time = dt;
+ v_cap_next = trigger;
+ flip_flop = 1;
+ count_r++;
+ update_exponent = 1;
+ }
+ }
+ v_cap = v_cap_next;
+ } while(dt);
+
+ m_cap_voltage = v_cap;
+ }
+
+ /* Convert last switch time to a ratio */
+ x_time = x_time / this->sample_time();
+
+ switch (m_output_type)
+ {
+ case DISC_555_OUT_SQW:
+ if (count_f + count_r >= 2)
+ /* force at least 1 toggle */
+ v_out = m_flip_flop ? 0 : m_v_out_high;
+ else
+ v_out = flip_flop * m_v_out_high;
+ v_out += m_ac_shift;
+ break;
+ case DISC_555_OUT_CAP:
+ v_out = v_cap;
+ /* Fake it to AC if needed */
+ if (m_output_is_ac)
+ v_out -= threshold * 3.0 /4.0;
+ break;
+ case DISC_555_OUT_ENERGY:
+ if (x_time == 0) x_time = 1.0;
+ v_out = m_v_out_high * (flip_flop ? x_time : (1.0 - x_time));
+ v_out += m_ac_shift;
+ break;
+ case DISC_555_OUT_LOGIC_X:
+ v_out = flip_flop + x_time;
+ break;
+ case DISC_555_OUT_COUNT_F_X:
+ v_out = count_f ? count_f + x_time : count_f;
+ break;
+ case DISC_555_OUT_COUNT_R_X:
+ v_out = count_r ? count_r + x_time : count_r;
+ break;
+ case DISC_555_OUT_COUNT_F:
+ v_out = count_f;
+ break;
+ case DISC_555_OUT_COUNT_R:
+ v_out = count_r;
+ break;
+ }
+ set_output(0, v_out);
+ m_flip_flop = flip_flop;
+}
+
+DISCRETE_RESET(dsd_555_astbl)
+{
+ DISCRETE_DECLARE_INFO(discrete_555_desc)
+
+ m_use_ctrlv = (this->input_is_node() >> 4) & 1;
+ m_output_type = info->options & DISC_555_OUT_MASK;
+
+ /* Use the defaults or supplied values. */
+ m_v_out_high = (info->v_out_high == DEFAULT_555_HIGH) ? info->v_pos - 1.2 : info->v_out_high;
+
+ /* setup v_charge or node */
+ m_v_charge_node = m_device->node_output_ptr(info->v_charge);
+ if (m_v_charge_node == NULL)
+ {
+ m_v_charge = (info->v_charge == DEFAULT_555_CHARGE) ? info->v_pos : info->v_charge;
+
+ if (info->options & DISC_555_ASTABLE_HAS_FAST_CHARGE_DIODE) m_v_charge -= 0.5;
+ }
+
+ if ((DSD_555_ASTBL__CTRLV != -1) && !m_use_ctrlv)
+ {
+ /* Setup based on supplied Control Voltage static value */
+ m_threshold = DSD_555_ASTBL__CTRLV;
+ m_trigger = DSD_555_ASTBL__CTRLV / 2.0;
+ }
+ else
+ {
+ /* Setup based on v_pos power source */
+ m_threshold = info->v_pos * 2.0 / 3.0;
+ m_trigger = info->v_pos / 3.0;
+ }
+
+ /* optimization if none of the values are nodes */
+ m_has_rc_nodes = 0;
+ if (this->input_is_node() & DSD_555_ASTBL_RC_MASK)
+ m_has_rc_nodes = 1;
+ else
+ {
+ m_t_rc_bleed = DSD_555_ASTBL_T_RC_BLEED;
+ m_exp_bleed = RC_CHARGE_EXP(m_t_rc_bleed);
+ m_t_rc_charge = DSD_555_ASTBL_T_RC_CHARGE;
+ m_exp_charge = RC_CHARGE_EXP(m_t_rc_charge);
+ m_t_rc_discharge = DSD_555_ASTBL_T_RC_DISCHARGE;
+ m_exp_discharge = RC_CHARGE_EXP(m_t_rc_discharge);
+ }
+
+ m_output_is_ac = info->options & DISC_555_OUT_AC;
+ /* Calculate DC shift needed to make squarewave waveform AC */
+ m_ac_shift = m_output_is_ac ? -m_v_out_high / 2.0 : 0;
+
+ m_flip_flop = 1;
+ m_cap_voltage = 0;
+
+ /* Step to set the output */
+ this->step();
+}
+
+
+/************************************************************************
+ *
+ * DSD_555_MSTBL - 555 Monostable simulation
+ *
+ * input[0] - Reset value
+ * input[1] - Trigger input
+ * input[2] - R2 value
+ * input[3] - C value
+ *
+ * also passed discrete_555_desc structure
+ *
+ * Oct 2004, D Renaud.
+ ************************************************************************/
+#define DSD_555_MSTBL__RESET (! DISCRETE_INPUT(0))
+#define DSD_555_MSTBL__TRIGGER DISCRETE_INPUT(1)
+#define DSD_555_MSTBL__R DISCRETE_INPUT(2)
+#define DSD_555_MSTBL__C DISCRETE_INPUT(3)
+
+/* bit mask of the above RC inputs */
+#define DSD_555_MSTBL_RC_MASK 0x0c
+
+DISCRETE_STEP(dsd_555_mstbl)
+{
+ DISCRETE_DECLARE_INFO(discrete_555_desc)
+
+ double v_cap; /* Current voltage on capacitor, before dt */
+ double x_time = 0; /* time since change happened */
+ double dt, exponent;
+ double out = 0;
+ int trigger = 0;
+ int trigger_type;
+ int update_exponent = m_has_rc_nodes;
+ int flip_flop;
+
+ if(UNEXPECTED(DSD_555_MSTBL__RESET))
+ {
+ /* We are in RESET */
+ set_output(0, 0);
+ m_flip_flop = 0;
+ m_cap_voltage = 0;
+ return;
+ }
+
+ dt = this->sample_time();
+ flip_flop = m_flip_flop;
+ trigger_type = info->options;
+ v_cap = m_cap_voltage;
+
+ switch (trigger_type & DSD_555_TRIGGER_TYPE_MASK)
+ {
+ case DISC_555_TRIGGER_IS_LOGIC:
+ trigger = ((int)DSD_555_MSTBL__TRIGGER) ? 0 : 1;
+ if (UNEXPECTED(trigger))
+ x_time = 1.0 - DSD_555_MSTBL__TRIGGER;
+ break;
+ case DISC_555_TRIGGER_IS_VOLTAGE:
+ trigger = (int)(DSD_555_MSTBL__TRIGGER < m_trigger);
+ break;
+ case DISC_555_TRIGGER_IS_COUNT:
+ trigger = (int)DSD_555_MSTBL__TRIGGER;
+ if (UNEXPECTED(trigger))
+ x_time = DSD_555_MSTBL__TRIGGER - trigger;
+ break;
+ }
+
+ if (UNEXPECTED(trigger && !flip_flop && x_time != 0))
+ {
+ /* adjust sample to after trigger */
+ update_exponent = 1;
+ dt *= x_time;
+ }
+ x_time = 0;
+
+ if ((trigger_type & DISC_555_TRIGGER_DISCHARGES_CAP) && trigger)
+ m_cap_voltage = 0;
+
+ /* Wait for trigger */
+ if (UNEXPECTED(!flip_flop && trigger))
+ {
+ flip_flop = 1;
+ m_flip_flop = 1;
+ }
+
+ if (flip_flop)
+ {
+ /* Sometimes a switching network is used to setup the capacitance.
+ * These may select 'no' capacitor, causing oscillation to stop.
+ */
+ if (UNEXPECTED(DSD_555_MSTBL__C == 0))
+ {
+ /* The trigger voltage goes high because the cap circuit is open.
+ * and the cap discharges */
+ v_cap = info->v_pos; /* needed for cap output type */
+ m_cap_voltage = 0;
+
+ if (!trigger)
+ {
+ flip_flop = 0;
+ m_flip_flop = 0;
+ }
+ }
+ else
+ {
+ /* Charging */
+ double v_diff = m_v_charge - v_cap;
+
+ if (UNEXPECTED(update_exponent))
+ exponent = RC_CHARGE_EXP_DT(DSD_555_MSTBL__R * DSD_555_MSTBL__C, dt);
+ else
+ exponent = m_exp_charge;
+ v_cap += v_diff * exponent;
+
+ /* Has it charged past upper limit? */
+ /* If trigger is still enabled, then we keep charging,
+ * regardless of threshold. */
+ if (UNEXPECTED((v_cap >= m_threshold) && !trigger))
+ {
+ dt = DSD_555_MSTBL__R * DSD_555_MSTBL__C * log(1.0 / (1.0 - ((v_cap - m_threshold) / v_diff)));
+ x_time = 1.0 - dt / this->sample_time();
+ v_cap = 0;
+ flip_flop = 0;
+ m_flip_flop = 0;
+ }
+ m_cap_voltage = v_cap;
+ }
+ }
+
+ switch (m_output_type)
+ {
+ case DISC_555_OUT_SQW:
+ out = flip_flop * m_v_out_high - m_ac_shift;
+ break;
+ case DISC_555_OUT_CAP:
+ if (x_time > 0)
+ out = v_cap * x_time;
+ else
+ out = v_cap;
+
+ out -= m_ac_shift;
+ break;
+ case DISC_555_OUT_ENERGY:
+ if (x_time > 0)
+ out = m_v_out_high * x_time;
+ else if (flip_flop)
+ out = m_v_out_high;
+ else
+ out = 0;
+
+ out -= m_ac_shift;
+ break;
+ }
+ set_output(0, out);
+}
+
+DISCRETE_RESET(dsd_555_mstbl)
+{
+ DISCRETE_DECLARE_INFO(discrete_555_desc)
+
+ m_output_type = info->options & DISC_555_OUT_MASK;
+ if ((m_output_type == DISC_555_OUT_COUNT_F) || (m_output_type == DISC_555_OUT_COUNT_R))
+ {
+ m_device->discrete_log("Invalid Output type in NODE_%d.\n", this->index());
+ m_output_type = DISC_555_OUT_SQW;
+ }
+
+ /* Use the defaults or supplied values. */
+ m_v_out_high = (info->v_out_high == DEFAULT_555_HIGH) ? info->v_pos - 1.2 : info->v_out_high;
+ m_v_charge = (info->v_charge == DEFAULT_555_CHARGE) ? info->v_pos : info->v_charge;
+
+ /* Setup based on v_pos power source */
+ m_threshold = info->v_pos * 2.0 / 3.0;
+ m_trigger = info->v_pos / 3.0;
+
+ /* Calculate DC shift needed to make waveform AC */
+ if (info->options & DISC_555_OUT_AC)
+ {
+ if (m_output_type == DISC_555_OUT_CAP)
+ m_ac_shift = m_threshold * 3.0 /4.0;
+ else
+ m_ac_shift = m_v_out_high / 2.0;
+ }
+ else
+ m_ac_shift = 0;
+
+ m_trig_is_logic = (info->options & DISC_555_TRIGGER_IS_VOLTAGE) ? 0: 1;
+ m_trig_discharges_cap = (info->options & DISC_555_TRIGGER_DISCHARGES_CAP) ? 1: 0;
+
+ m_flip_flop = 0;
+ m_cap_voltage = 0;
+
+ /* optimization if none of the values are nodes */
+ m_has_rc_nodes = 0;
+ if (this->input_is_node() & DSD_555_MSTBL_RC_MASK)
+ m_has_rc_nodes = 1;
+ else
+ m_exp_charge = RC_CHARGE_EXP(DSD_555_MSTBL__R * DSD_555_MSTBL__C);
+
+ set_output(0, 0);
+}
+
+
+/************************************************************************
+ *
+ * DSD_555_CC - Usage of node_description values
+ *
+ * input[0] - Reset input value
+ * input[1] - Voltage input for Constant current source.
+ * input[2] - R value to set CC current.
+ * input[3] - C value
+ * input[4] - rBias value
+ * input[5] - rGnd value
+ * input[6] - rDischarge value
+ *
+ * also passed discrete_555_cc_desc structure
+ *
+ * Mar 2004, D Renaud.
+ ************************************************************************/
+#define DSD_555_CC__RESET (! DISCRETE_INPUT(0))
+#define DSD_555_CC__VIN DISCRETE_INPUT(1)
+#define DSD_555_CC__R DISCRETE_INPUT(2)
+#define DSD_555_CC__C DISCRETE_INPUT(3)
+#define DSD_555_CC__RBIAS DISCRETE_INPUT(4)
+#define DSD_555_CC__RGND DISCRETE_INPUT(5)
+#define DSD_555_CC__RDIS DISCRETE_INPUT(6)
+
+/* bit mask of the above RC inputs not including DSD_555_CC__R */
+#define DSD_555_CC_RC_MASK 0x78
+
+/* charge/discharge constants */
+#define DSD_555_CC_T_RC_BLEED (DEFAULT_555_BLEED_R * DSD_555_CC__C)
+#define DSD_555_CC_T_RC_DISCHARGE_01 (DSD_555_CC__RDIS * DSD_555_CC__C)
+#define DSD_555_CC_T_RC_DISCHARGE_NO_I (DSD_555_CC__RGND * DSD_555_CC__C)
+#define DSD_555_CC_T_RC_CHARGE (r_charge * DSD_555_CC__C)
+#define DSD_555_CC_T_RC_DISCHARGE (r_discharge * DSD_555_CC__C)
+
+
+DISCRETE_STEP(dsd_555_cc)
+{
+ DISCRETE_DECLARE_INFO(discrete_555_cc_desc)
+
+ int count_f = 0;
+ int count_r = 0;
+ double i; /* Charging current created by vIn */
+ double r_charge = 0; /* Equivalent charging resistor */
+ double r_discharge = 0; /* Equivalent discharging resistor */
+ double vi = 0; /* Equivalent voltage from current source */
+ double v_bias = 0; /* Equivalent voltage from bias voltage */
+ double v = 0; /* Equivalent voltage total from current source and bias circuit if used */
+ double dt; /* change in time */
+ double x_time = 0; /* time since change happened */
+ double t_rc ; /* RC time constant */
+ double v_cap; /* Current voltage on capacitor, before dt */
+ double v_cap_next = 0; /* Voltage on capacitor, after dt */
+ double v_vcharge_limit; /* vIn and the junction voltage limit the max charging voltage from i */
+ double r_temp; /* play thing */
+ double exponent;
+ UINT8 update_exponent, update_t_rc;
+ UINT8 flip_flop = m_flip_flop;
+
+ double v_out = 0;
+
+
+ if (UNEXPECTED(DSD_555_CC__RESET))
+ {
+ /* We are in RESET */
+ set_output(0, 0);
+ m_flip_flop = 1;
+ m_cap_voltage = 0;
+ return;
+ }
+
+ dt = this->sample_time(); /* Change in time */
+ v_cap = m_cap_voltage; /* Set to voltage before change */
+ v_vcharge_limit = DSD_555_CC__VIN + info->v_cc_junction; /* the max v_cap can be and still be charged by i */
+ /* Calculate charging current */
+ i = (m_v_cc_source - v_vcharge_limit) / DSD_555_CC__R;
+ if ( i < 0) i = 0;
+
+ if (info->options & DISCRETE_555_CC_TO_CAP)
+ {
+ vi = i * DSD_555_CC__RDIS;
+ }
+ else
+ {
+ switch (m_type) /* see dsd_555_cc_reset for descriptions */
+ {
+ case 1:
+ r_discharge = DSD_555_CC__RDIS;
+ case 0:
+ break;
+ case 3:
+ r_discharge = RES_2_PARALLEL(DSD_555_CC__RDIS, DSD_555_CC__RGND);
+ case 2:
+ r_charge = DSD_555_CC__RGND;
+ vi = i * r_charge;
+ break;
+ case 4:
+ r_charge = DSD_555_CC__RBIAS;
+ vi = i * r_charge;
+ v_bias = info->v_pos;
+ break;
+ case 5:
+ r_charge = DSD_555_CC__RBIAS + DSD_555_CC__RDIS;
+ vi = i * DSD_555_CC__RBIAS;
+ v_bias = info->v_pos;
+ r_discharge = DSD_555_CC__RDIS;
+ break;
+ case 6:
+ r_charge = RES_2_PARALLEL(DSD_555_CC__RBIAS, DSD_555_CC__RGND);
+ vi = i * r_charge;
+ v_bias = info->v_pos * RES_VOLTAGE_DIVIDER(DSD_555_CC__RGND, DSD_555_CC__RBIAS);
+ break;
+ case 7:
+ r_temp = DSD_555_CC__RBIAS + DSD_555_CC__RDIS;
+ r_charge = RES_2_PARALLEL(r_temp, DSD_555_CC__RGND);
+ r_temp += DSD_555_CC__RGND;
+ r_temp = DSD_555_CC__RGND / r_temp; /* now has voltage divider ratio, not resistance */
+ vi = i * DSD_555_CC__RBIAS * r_temp;
+ v_bias = info->v_pos * r_temp;
+ r_discharge = RES_2_PARALLEL(DSD_555_CC__RGND, DSD_555_CC__RDIS);
+ break;
+ }
+ }
+
+ /* Keep looping until all toggling in time sample is used up. */
+ update_t_rc = m_has_rc_nodes;
+ update_exponent = update_t_rc;
+ do
+ {
+ if (m_type <= 1)
+ {
+ /* Standard constant current charge */
+ if (flip_flop)
+ {
+ if (i == 0)
+ {
+ /* No charging current, so we have to discharge the cap
+ * due to cap and circuit losses.
+ */
+ if (update_exponent)
+ {
+ t_rc = DSD_555_CC_T_RC_BLEED;
+ exponent = RC_CHARGE_EXP_DT(t_rc, dt);
+ }
+ else
+ exponent = m_exp_bleed;
+ v_cap_next = v_cap - (v_cap * exponent);
+ dt = 0;
+ }
+ else
+ {
+ /* Charging */
+ /* iC=C*dv/dt works out to dv=iC*dt/C */
+ v_cap_next = v_cap + (i * dt / DSD_555_CC__C);
+ /* Yes, if the cap voltage has reached the max voltage it can,
+ * and the 555 threshold has not been reached, then oscillation stops.
+ * This is the way the actual electronics works.
+ * This is why you never play with the pots after being factory adjusted
+ * to work in the proper range. */
+ if (v_cap_next > v_vcharge_limit) v_cap_next = v_vcharge_limit;
+ dt = 0;
+
+ /* has it charged past upper limit? */
+ if (v_cap_next >= m_threshold)
+ {
+ /* calculate the overshoot time */
+ dt = DSD_555_CC__C * (v_cap_next - m_threshold) / i;
+ x_time = dt;
+ v_cap_next = m_threshold;
+ flip_flop = 0;
+ count_f++;
+ update_exponent = 1;
+ }
+ }
+ }
+ else if (DSD_555_CC__RDIS != 0)
+ {
+ /* Discharging */
+ if (update_t_rc)
+ t_rc = DSD_555_CC_T_RC_DISCHARGE_01;
+ else
+ t_rc = m_t_rc_discharge_01;
+ if (update_exponent)
+ exponent = RC_CHARGE_EXP_DT(t_rc, dt);
+ else
+ exponent = m_exp_discharge_01;
+
+ if (info->options & DISCRETE_555_CC_TO_CAP)
+ {
+ /* Asteroids - Special Case */
+ /* Charging in discharge mode */
+ /* If the cap voltage is past the current source charging limit
+ * then only the bias voltage will charge the cap. */
+ v = (v_cap < v_vcharge_limit) ? vi : v_vcharge_limit;
+ v_cap_next = v_cap + ((v - v_cap) * exponent);
+ }
+ else
+ {
+ v_cap_next = v_cap - (v_cap * exponent);
+ }
+
+ dt = 0;
+ /* has it discharged past lower limit? */
+ if (v_cap_next <= m_trigger)
+ {
+ dt = t_rc * log(1.0 / (1.0 - ((m_trigger - v_cap_next) / v_cap)));
+ x_time = dt;
+ v_cap_next = m_trigger;
+ flip_flop = 1;
+ count_r++;
+ update_exponent = 1;
+ }
+ }
+ else /* Immediate discharge. No change in dt. */
+ {
+ x_time = dt;
+ v_cap_next = m_trigger;
+ flip_flop = 1;
+ count_r++;
+ }
+ }
+ else
+ {
+ /* The constant current gets changed to a voltage due to a load resistor. */
+ if (flip_flop)
+ {
+ if ((i == 0) && (DSD_555_CC__RBIAS == 0))
+ {
+ /* No charging current, so we have to discharge the cap
+ * due to rGnd.
+ */
+ if (update_t_rc)
+ t_rc = DSD_555_CC_T_RC_DISCHARGE_NO_I;
+ else
+ t_rc = m_t_rc_discharge_no_i;
+ if (update_exponent)
+ exponent = RC_CHARGE_EXP_DT(t_rc, dt);
+ else
+ exponent = m_exp_discharge_no_i;
+
+ v_cap_next = v_cap - (v_cap * exponent);
+ dt = 0;
+ }
+ else
+ {
+ /* Charging */
+ /* If the cap voltage is past the current source charging limit
+ * then only the bias voltage will charge the cap. */
+ v = v_bias;
+ if (v_cap < v_vcharge_limit) v += vi;
+ else if (m_type <= 3) v = v_vcharge_limit;
+
+ if (update_t_rc)
+ t_rc = DSD_555_CC_T_RC_CHARGE;
+ else
+ t_rc = m_t_rc_charge;
+ if (update_exponent)
+ exponent = RC_CHARGE_EXP_DT(t_rc, dt);
+ else
+ exponent = m_exp_charge;
+
+ v_cap_next = v_cap + ((v - v_cap) * exponent);
+ dt = 0;
+
+ /* has it charged past upper limit? */
+ if (v_cap_next >= m_threshold)
+ {
+ /* calculate the overshoot time */
+ dt = t_rc * log(1.0 / (1.0 - ((v_cap_next - m_threshold) / (v - v_cap))));
+ x_time = dt;
+ v_cap_next = m_threshold;
+ flip_flop = 0;
+ count_f++;
+ update_exponent = 1;
+ }
+ }
+ }
+ else /* Discharging */
+ if (r_discharge)
+ {
+ if (update_t_rc)
+ t_rc = DSD_555_CC_T_RC_DISCHARGE;
+ else
+ t_rc = m_t_rc_discharge;
+ if (update_exponent)
+ exponent = RC_CHARGE_EXP_DT(t_rc, dt);
+ else
+ exponent = m_exp_discharge;
+
+ v_cap_next = v_cap - (v_cap * exponent);
+ dt = 0;
+
+ /* has it discharged past lower limit? */
+ if (v_cap_next <= m_trigger)
+ {
+ /* calculate the overshoot time */
+ dt = t_rc * log(1.0 / (1.0 - ((m_trigger - v_cap_next) / v_cap)));
+ x_time = dt;
+ v_cap_next = m_trigger;
+ flip_flop = 1;
+ count_r++;
+ update_exponent = 1;
+ }
+ }
+ else /* Immediate discharge. No change in dt. */
+ {
+ x_time = dt;
+ v_cap_next = m_trigger;
+ flip_flop = 1;
+ count_r++;
+ }
+ }
+ v_cap = v_cap_next;
+ } while(dt);
+
+ m_cap_voltage = v_cap;
+
+ /* Convert last switch time to a ratio */
+ x_time = x_time / this->sample_time();
+
+ switch (m_output_type)
+ {
+ case DISC_555_OUT_SQW:
+ if (count_f + count_r >= 2)
+ /* force at least 1 toggle */
+ v_out = m_flip_flop ? 0 : m_v_out_high;
+ else
+ v_out = flip_flop * m_v_out_high;
+ /* Fake it to AC if needed */
+ v_out += m_ac_shift;
+ break;
+ case DISC_555_OUT_CAP:
+ v_out = v_cap + m_ac_shift;
+ break;
+ case DISC_555_OUT_ENERGY:
+ if (x_time == 0) x_time = 1.0;
+ v_out = m_v_out_high * (flip_flop ? x_time : (1.0 - x_time));
+ v_out += m_ac_shift;
+ break;
+ case DISC_555_OUT_LOGIC_X:
+ v_out = flip_flop + x_time;
+ break;
+ case DISC_555_OUT_COUNT_F_X:
+ v_out = count_f ? count_f + x_time : count_f;
+ break;
+ case DISC_555_OUT_COUNT_R_X:
+ v_out = count_r ? count_r + x_time : count_r;
+ break;
+ case DISC_555_OUT_COUNT_F:
+ v_out = count_f;
+ break;
+ case DISC_555_OUT_COUNT_R:
+ v_out = count_r;
+ break;
+ }
+ set_output(0, v_out);
+ m_flip_flop = flip_flop;
+}
+
+DISCRETE_RESET(dsd_555_cc)
+{
+ DISCRETE_DECLARE_INFO(discrete_555_cc_desc)
+
+ double r_temp, r_discharge = 0, r_charge = 0;
+
+ m_flip_flop = 1;
+ m_cap_voltage = 0;
+
+ m_output_type = info->options & DISC_555_OUT_MASK;
+
+ /* Use the defaults or supplied values. */
+ m_v_out_high = (info->v_out_high == DEFAULT_555_HIGH) ? info->v_pos - 1.2 : info->v_out_high;
+ m_v_cc_source = (info->v_cc_source == DEFAULT_555_CC_SOURCE) ? info->v_pos : info->v_cc_source;
+
+ /* Setup based on v_pos power source */
+ m_threshold = info->v_pos * 2.0 / 3.0;
+ m_trigger = info->v_pos / 3.0;
+
+ m_output_is_ac = info->options & DISC_555_OUT_AC;
+ /* Calculate DC shift needed to make squarewave waveform AC */
+ m_ac_shift = m_output_is_ac ? -m_v_out_high / 2.0 : 0;
+
+ /* There are 8 different types of basic oscillators
+ * depending on the resistors used. We will determine
+ * the type of circuit at reset, because the ciruit type
+ * is constant. See Below.
+ */
+ m_type = (DSD_555_CC__RDIS > 0) | ((DSD_555_CC__RGND > 0) << 1) | ((DSD_555_CC__RBIAS > 0) << 2);
+
+ /* optimization if none of the values are nodes */
+ m_has_rc_nodes = 0;
+ if (this->input_is_node() & DSD_555_CC_RC_MASK)
+ m_has_rc_nodes = 1;
+ else
+ {
+ switch (m_type) /* see dsd_555_cc_reset for descriptions */
+ {
+ case 1:
+ r_discharge = DSD_555_CC__RDIS;
+ case 0:
+ break;
+ case 3:
+ r_discharge = RES_2_PARALLEL(DSD_555_CC__RDIS, DSD_555_CC__RGND);
+ case 2:
+ r_charge = DSD_555_CC__RGND;
+ break;
+ case 4:
+ r_charge = DSD_555_CC__RBIAS;
+ break;
+ case 5:
+ r_charge = DSD_555_CC__RBIAS + DSD_555_CC__RDIS;
+ r_discharge = DSD_555_CC__RDIS;
+ break;
+ case 6:
+ r_charge = RES_2_PARALLEL(DSD_555_CC__RBIAS, DSD_555_CC__RGND);
+ break;
+ case 7:
+ r_temp = DSD_555_CC__RBIAS + DSD_555_CC__RDIS;
+ r_charge = RES_2_PARALLEL(r_temp, DSD_555_CC__RGND);
+ r_discharge = RES_2_PARALLEL(DSD_555_CC__RGND, DSD_555_CC__RDIS);
+ break;
+ }
+
+ m_exp_bleed = RC_CHARGE_EXP(DSD_555_CC_T_RC_BLEED);
+ m_t_rc_discharge_01 = DSD_555_CC_T_RC_DISCHARGE_01;
+ m_exp_discharge_01 = RC_CHARGE_EXP(m_t_rc_discharge_01);
+ m_t_rc_discharge_no_i = DSD_555_CC_T_RC_DISCHARGE_NO_I;
+ m_exp_discharge_no_i = RC_CHARGE_EXP(m_t_rc_discharge_no_i);
+ m_t_rc_charge = DSD_555_CC_T_RC_CHARGE;
+ m_exp_charge = RC_CHARGE_EXP(m_t_rc_charge);
+ m_t_rc_discharge = DSD_555_CC_T_RC_DISCHARGE;
+ m_exp_discharge = RC_CHARGE_EXP(m_t_rc_discharge);
+ }
+
+ /* Step to set the output */
+ this->step();
+
+ /*
+ * TYPES:
+ * Note: These are equivalent circuits shown without the 555 circuitry.
+ * See the schematic in src\sound\discrete.h for full hookup info.
+ *
+ * DISCRETE_555_CC_TO_DISCHARGE_PIN
+ * When the CC source is connected to the discharge pin, it allows the
+ * circuit to charge when the 555 is in charge mode. But when in discharge
+ * mode, the CC source is grounded, disabling it's effect.
+ *
+ * [0]
+ * No resistors. Straight constant current charge of capacitor.
+ * When there is not any charge current, the cap will bleed off.
+ * Once the lower threshold(trigger) is reached, the output will
+ * go high but the cap will continue to discharge due to losses.
+ * .------+---> cap_voltage CHARGING:
+ * | | dv (change in voltage) compared to dt (change in time in seconds).
+ * .---. --- dv = i * dt / C; where i is current in amps and C is capacitance in farads.
+ * | i | --- C cap_voltage = cap_voltage + dv
+ * '---' |
+ * | | DISCHARGING:
+ * gnd gnd instantaneous
+ *
+ * [1]
+ * Same as type 1 but with rDischarge. rDischarge has no effect on the charge rate because
+ * of the constant current source i.
+ * When there is not any charge current, the cap will bleed off.
+ * Once the lower threshold(trigger) is reached, the output will
+ * go high but the cap will continue to discharge due to losses.
+ * .----ZZZ-----+---> cap_voltage CHARGING:
+ * | rDischarge | dv (change in voltage) compared to dt (change in time in seconds).
+ * .---. --- dv = i * dt / C; where i is current in amps and C is capacitance in farads.
+ * | i | --- C cap_voltage = cap_voltage + dv
+ * '---' |
+ * | | DISCHARGING:
+ * gnd gnd through rDischarge
+ *
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * !!!!! IMPORTANT NOTE ABOUT TYPES 3 - 7 !!!!!
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ *
+ * From here on in all the circuits have either an rBias or rGnd resistor.
+ * This converts the constant current into a voltage source.
+ * So all the remaining circuit types will be converted to this circuit.
+ * When discharging, rBias is out of the equation because the 555 is grounding the circuit
+ * after that point.
+ *
+ * .------------. Rc Rc is the equivilent circuit resistance.
+ * | v |----ZZZZ---+---> cap_voltage v is the equivilent circuit voltage.
+ * | | |
+ * '------------' --- Then the standard RC charging formula applies.
+ * | --- C
+ * | | NOTE: All the following types are converted to Rc and v values.
+ * gnd gnd
+ *
+ * [2]
+ * When there is not any charge current, the cap will bleed off.
+ * Once the lower threshold(trigger) is reached, the output will
+ * go high but the cap will continue to discharge due to rGnd.
+ * .-------+------+------> cap_voltage CHARGING:
+ * | | | v = vi = i * rGnd
+ * .---. --- Z Rc = rGnd
+ * | i | --- C Z rGnd
+ * '---' | | DISCHARGING:
+ * | | | instantaneous
+ * gnd gnd gnd
+ *
+ * [3]
+ * When there is not any charge current, the cap will bleed off.
+ * Once the lower threshold(trigger) is reached, the output will
+ * go high but the cap will continue to discharge due to rGnd.
+ * .----ZZZ-----+------+------> cap_voltage CHARGING:
+ * | rDischarge | | v = vi = i * rGnd
+ * .---. --- Z Rc = rGnd
+ * | i | --- C Z rGnd
+ * '---' | | DISCHARGING:
+ * | | | through rDischarge || rGnd ( || means in parallel)
+ * gnd gnd gnd
+ *
+ * [4]
+ * .---ZZZ---+------------+-------------> cap_voltage CHARGING:
+ * | rBias | | Rc = rBias
+ * .-------. .---. --- vi = i * rBias
+ * | vBias | | i | --- C v = vBias + vi
+ * '-------' '---' |
+ * | | | DISCHARGING:
+ * gnd gnd gnd instantaneous
+ *
+ * [5]
+ * .---ZZZ---+----ZZZ-----+-------------> cap_voltage CHARGING:
+ * | rBias | rDischarge | Rc = rBias + rDischarge
+ * .-------. .---. --- vi = i * rBias
+ * | vBias | | i | --- C v = vBias + vi
+ * '-------' '---' |
+ * | | | DISCHARGING:
+ * gnd gnd gnd through rDischarge
+ *
+ * [6]
+ * .---ZZZ---+------------+------+------> cap_voltage CHARGING:
+ * | rBias | | | Rc = rBias || rGnd
+ * .-------. .---. --- Z vi = i * Rc
+ * | vBias | | i | --- C Z rGnd v = vBias * (rGnd / (rBias + rGnd)) + vi
+ * '-------' '---' | |
+ * | | | | DISCHARGING:
+ * gnd gnd gnd gnd instantaneous
+ *
+ * [7]
+ * .---ZZZ---+----ZZZ-----+------+------> cap_voltage CHARGING:
+ * | rBias | rDischarge | | Rc = (rBias + rDischarge) || rGnd
+ * .-------. .---. --- Z vi = i * rBias * (rGnd / (rBias + rDischarge + rGnd))
+ * | vBias | | i | --- C Z rGnd v = vBias * (rGnd / (rBias + rDischarge + rGnd)) + vi
+ * '-------' '---' | |
+ * | | | | DISCHARGING:
+ * gnd gnd gnd gnd through rDischarge || rGnd
+ */
+
+ /*
+ * DISCRETE_555_CC_TO_CAP
+ *
+ * When the CC source is connected to the capacitor, it allows the
+ * current to charge the cap while it is in discharge mode, slowing the
+ * discharge. So in charge mode it charges linearly from the constant
+ * current cource. But when in discharge mode it behaves like circuit
+ * type 2 above.
+ * .-------+------+------> cap_voltage CHARGING:
+ * | | | dv = i * dt / C
+ * .---. --- Z cap_voltage = cap_voltage + dv
+ * | i | --- C Z rDischarge
+ * '---' | | DISCHARGING:
+ * | | | v = vi = i * rGnd
+ * gnd gnd discharge Rc = rDischarge
+ */
+}
+
+
+/************************************************************************
+ *
+ * DSD_555_VCO1 - Usage of node_description values
+ *
+ * input[0] - Reset input value
+ * input[1] - Modulation Voltage (Vin1)
+ * input[2] - Control Voltage (Vin2)
+ *
+ * also passed discrete_5555_vco1_desc structure
+ *
+ * Apr 2006, D Renaud.
+ ************************************************************************/
+#define DSD_555_VCO1__RESET DISCRETE_INPUT(0) /* reset active low */
+#define DSD_555_VCO1__VIN1 DISCRETE_INPUT(1)
+#define DSD_555_VCO1__VIN2 DISCRETE_INPUT(2)
+
+DISCRETE_STEP(dsd_555_vco1)
+{
+ DISCRETE_DECLARE_INFO(discrete_555_vco1_desc)
+
+ int count_f = 0;
+ int count_r = 0;
+ double dt; /* change in time */
+ double x_time = 0; /* time since change happened */
+ double v_cap; /* Current voltage on capacitor, before dt */
+ double v_cap_next = 0; /* Voltage on capacitor, after dt */
+
+ double v_out = 0;
+
+ dt = this->sample_time(); /* Change in time */
+ v_cap = m_cap_voltage;
+
+ /* Check: if the Control Voltage node is connected. */
+ if (m_ctrlv_is_node && DSD_555_VCO1__RESET) /* reset active low */
+ {
+ /* If CV is less then .25V, the circuit will oscillate way out of range.
+ * So we will just ignore it when it happens. */
+ if (DSD_555_VCO1__VIN2 < .25) return;
+ /* If it is a node then calculate thresholds based on Control Voltage */
+ m_threshold = DSD_555_VCO1__VIN2;
+ m_trigger = DSD_555_VCO1__VIN2 / 2.0;
+ /* Since the thresholds may have changed we need to update the FF */
+ if (v_cap >= m_threshold)
+ {
+ x_time = dt;
+ m_flip_flop = 0;
+ count_f++;
+ }
+ else
+ if (v_cap <= m_trigger)
+ {
+ x_time = dt;
+ m_flip_flop = 1;
+ count_r++;
+ }
+ }
+
+ /* Keep looping until all toggling in time sample is used up. */
+ do
+ {
+ if (m_flip_flop)
+ {
+ /* if we are in reset then toggle f/f and discharge */
+ if (!DSD_555_VCO1__RESET) /* reset active low */
+ {
+ m_flip_flop = 0;
+ count_f++;
+ }
+ else
+ {
+ /* Charging */
+ /* iC=C*dv/dt works out to dv=iC*dt/C */
+ v_cap_next = v_cap + (m_i_charge * dt / info->c);
+ dt = 0;
+
+ /* has it charged past upper limit? */
+ if (v_cap_next >= m_threshold)
+ {
+ /* calculate the overshoot time */
+ dt = info->c * (v_cap_next - m_threshold) / m_i_charge;
+ v_cap = m_threshold;
+ x_time = dt;
+ m_flip_flop = 0;
+ count_f++;
+ }
+ }
+ }
+ else
+ {
+ /* Discharging */
+ /* iC=C*dv/dt works out to dv=iC*dt/C */
+ v_cap_next = v_cap - (m_i_discharge * dt / info->c);
+
+ /* if we are in reset, then the cap can discharge to 0 */
+ if (!DSD_555_VCO1__RESET) /* reset active low */
+ {
+ if (v_cap_next < 0) v_cap_next = 0;
+ dt = 0;
+ }
+ else
+ {
+ /* if we are out of reset and the cap voltage is less then
+ * the lower threshold, toggle f/f and start charging */
+ if (v_cap <= m_trigger)
+ {
+ if (m_flip_flop == 0)
+ {
+ /* don't need to track x_time here */
+ m_flip_flop = 1;
+ count_r++;
+ }
+ }
+ else
+ {
+ dt = 0;
+ /* has it discharged past lower limit? */
+ if (v_cap_next <= m_trigger)
+ {
+ /* calculate the overshoot time */
+ dt = info->c * (v_cap_next - m_trigger) / m_i_discharge;
+ v_cap = m_trigger;
+ x_time = dt;
+ m_flip_flop = 1;
+ count_r++;
+ }
+ }
+ }
+ }
+ } while(dt);
+
+ m_cap_voltage = v_cap_next;
+
+ /* Convert last switch time to a ratio. No x_time in reset. */
+ x_time = x_time / this->sample_time();
+ if (!DSD_555_VCO1__RESET) x_time = 0;
+
+ switch (m_output_type)
+ {
+ case DISC_555_OUT_SQW:
+ v_out = m_flip_flop * m_v_out_high + m_ac_shift;
+ break;
+ case DISC_555_OUT_CAP:
+ v_out = v_cap_next;
+ /* Fake it to AC if needed */
+ if (m_output_is_ac)
+ v_out -= m_threshold * 3.0 /4.0;
+ break;
+ case DISC_555_OUT_ENERGY:
+ if (x_time == 0) x_time = 1.0;
+ v_out = m_v_out_high * (m_flip_flop ? x_time : (1.0 - x_time));
+ v_out += m_ac_shift;
+ break;
+ case DISC_555_OUT_LOGIC_X:
+ v_out = m_flip_flop + x_time;
+ break;
+ case DISC_555_OUT_COUNT_F_X:
+ v_out = count_f ? count_f + x_time : count_f;
+ break;
+ case DISC_555_OUT_COUNT_R_X:
+ v_out = count_r ? count_r + x_time : count_r;
+ break;
+ case DISC_555_OUT_COUNT_F:
+ v_out = count_f;
+ break;
+ case DISC_555_OUT_COUNT_R:
+ v_out = count_r;
+ break;
+ }
+ set_output(0, v_out);
+}
+
+DISCRETE_RESET(dsd_555_vco1)
+{
+ DISCRETE_DECLARE_INFO(discrete_555_vco1_desc)
+
+ double v_ratio_r3, v_ratio_r4_1, r_in_1;
+
+ m_output_type = info->options & DISC_555_OUT_MASK;
+ m_output_is_ac = info->options & DISC_555_OUT_AC;
+
+ /* Setup op-amp parameters */
+
+ /* The voltage at op-amp +in is always a fixed ratio of the modulation voltage. */
+ v_ratio_r3 = info->r3 / (info->r2 + info->r3); /* +in voltage */
+ /* The voltage at op-amp -in is 1 of 2 fixed ratios of the modulation voltage,
+ * based on the 555 Flip-Flop state. */
+ /* If the FF is 0, then only R1 is connected allowing the full modulation volatge to pass. */
+ /* v_ratio_r4_0 = 1 */
+ /* If the FF is 1, then R1 & R4 make a voltage divider similar to R2 & R3 */
+ v_ratio_r4_1 = info->r4 / (info->r1 + info->r4); /* -in voltage */
+ /* the input resistance to the op amp depends on the FF state */
+ /* r_in_0 = info->r1 when FF = 0 */
+ r_in_1 = 1.0 / (1.0 / info->r1 + 1.0 / info->r4); /* input resistance when r4 switched in */
+
+ /* Now that we know the voltages entering the op amp and the resistance for the
+ * FF states, we can predetermine the ratios for the charge/discharge currents. */
+ m_i_discharge = (1 - v_ratio_r3) / info->r1;
+ m_i_charge = (v_ratio_r3 - v_ratio_r4_1) / r_in_1;
+
+ /* the cap starts off discharged */
+ m_cap_voltage = 0;
+
+ /* Setup 555 parameters */
+
+ /* There is no charge on the cap so the 555 goes high at init. */
+ m_flip_flop = 1;
+ m_ctrlv_is_node = (this->input_is_node() >> 2) & 1;
+ m_v_out_high = (info->v_out_high == DEFAULT_555_HIGH) ? info->v_pos - 1.2 : info->v_out_high;
+
+ /* Calculate 555 thresholds.
+ * If the Control Voltage is a node, then the thresholds will be calculated each step.
+ * If the Control Voltage is a fixed voltage, then the thresholds will be calculated
+ * from that. Otherwise we will use thresholds based on v_pos. */
+ if (!m_ctrlv_is_node && (DSD_555_VCO1__VIN2 != -1))
+ {
+ /* Setup based on supplied Control Voltage static value */
+ m_threshold = DSD_555_VCO1__VIN2;
+ m_trigger = DSD_555_VCO1__VIN2 / 2.0;
+ }
+ else
+ {
+ /* Setup based on v_pos power source */
+ m_threshold = info->v_pos * 2.0 / 3.0;
+ m_trigger = info->v_pos / 3.0;
+ }
+
+ /* Calculate DC shift needed to make squarewave waveform AC */
+ m_ac_shift = m_output_is_ac ? -m_v_out_high / 2.0 : 0;
+}
+
+
+/************************************************************************
+ *
+ * DSD_566 - Usage of node_description values
+ *
+ * Mar 2004, D Renaud. updated Sept 2009
+ *
+ * The data sheets for this are no where near correct.
+ * This simulation is based on the internal schematic and testing of
+ * a real Signetics IC.
+ *
+ * The 566 is a constant current based VCO. If you change R, that affects
+ * the charge/discharge rate. A constant current source will charge the
+ * cap linearly. Of course due to the transistors there will be some
+ * non-linear areas at the ends of the Vmod range. As the Vmod voltage
+ * drops from Vcharge, the frequency generated increases.
+ *
+ * The Triangle (pin 4) output is just a buffered version of the cap
+ * charge. It is about 1.35 higher then the cap voltage.
+ * The Square (pin 3) output starts low as the cap voltages rises.
+ * Once a threshold is reached, the cap starts to discharge, and the
+ * Square output goes high. The Square high output is about 1V less then
+ * B+. Unloaded it is .75V less. With a 4.7k pull-down resistor, it
+ * is 1.06V less. So I will simulate at 1V less. The Square low voltage
+ * is non-linear so I will use a table. The cap toggle thresholds vary
+ * depending on B+, so they will be simulated with a table.
+ *
+ * The data sheets show Vmod should be no less then 3/4*B+. In reality
+ * you can go to close to 1/2*B+ before you lose linearity. Below 1/2,
+ * oscillation stops. When Vmod is 0V to 0.1V less then B+, it also
+ * loses linearity, and stops oscillating when >= B+. This is because
+ * there is no voltage difference to create a current source.
+ *
+ * The current source is dependant on the voltage difference between B+
+ * and Vmod. Due to transistor action, it is not 100%, but this formula
+ * gives a good approximation:
+ * I = ((B+ - Vmod - 0.1) * 0.95) / R
+ * You can test the current VS modulation function by using 10k for R
+ * and replace C with a 10k resistor. Then you can monitor the voltage
+ * on pin 7 to work out the current. I=V/R. It will start to oscillate
+ * when in the cap threshold range.
+ *
+ * When Vmod drops below the stable range, the current source no longer
+ * functions properly. Technically this is out of the range specified
+ * for the IC. Of course old games used this range anyways, so we need
+ * to know how the real IC behaves. When Vmod drops below the stable range,
+ * the charge current is stops dropping instead of increasing, while the
+ * discharge current still functions. This means the frequency generated
+ * starts to drop as the voltage lowers, instead of the normal increase
+ * in frequency.
+ *
+ ************************************************************************/
+#define DSD_566__VMOD DISCRETE_INPUT(0)
+#define DSD_566__R DISCRETE_INPUT(1)
+#define DSD_566__C DISCRETE_INPUT(2)
+#define DSD_566__VPOS DISCRETE_INPUT(3)
+#define DSD_566__VNEG DISCRETE_INPUT(4)
+#define DSD_566__VCHARGE DISCRETE_INPUT(5)
+#define DSD_566__OPTIONS DISCRETE_INPUT(6)
+
+
+static const struct
+{
+ double c_high[6];
+ double c_low[6];
+ double sqr_low[6];
+ double osc_stable[6];
+ double osc_stop[6];
+} ne566 =
+{
+ /* 10 10.5 11 11.5 12 13 14 15 B+ */
+ {3.364, /*3.784,*/ 4.259, /*4.552,*/ 4.888, 5.384, 5.896, 6.416}, /* c_high */
+ {1.940, /*2.100,*/ 2.276, /*2.404,*/ 2.580, 2.880, 3.180, 3.488}, /* c_low */
+ {4.352, /*4.144,*/ 4.080, /*4.260,*/ 4.500, 4.960, 5.456, 5.940}, /* sqr_low */
+ {4.885, /*5.316,*/ 5.772, /*6.075,*/ 6.335, 6.912, 7.492, 7.945}, /* osc_stable */
+ {4.495, /*4.895,*/ 5.343, /*5.703,*/ 5.997, 6.507, 7.016, 7.518} /* osc_stop */
+};
+
+DISCRETE_STEP(dsd_566)
+{
+ double i = 0; /* Charging current created by vIn */
+ double i_rise; /* non-linear rise charge current */
+ double dt; /* change in time */
+ double x_time = 0;
+ double v_cap; /* Current voltage on capacitor, before dt */
+ int count_f = 0, count_r = 0;
+
+ double v_out = 0.0;
+
+ dt = this->sample_time(); /* Change in time */
+ v_cap = m_cap_voltage; /* Set to voltage before change */
+
+ /* Calculate charging current if it is in range */
+ if (EXPECTED(DSD_566__VMOD > m_v_osc_stop))
+ {
+ double v_charge = DSD_566__VCHARGE - DSD_566__VMOD - 0.1;
+ if (v_charge > 0)
+ {
+ i = (v_charge * .95) / DSD_566__R;
+ if (DSD_566__VMOD < m_v_osc_stable)
+ {
+ /* no where near correct calculation of non linear range */
+ i_rise = ((DSD_566__VCHARGE - m_v_osc_stable - 0.1) * .95) / DSD_566__R;
+ i_rise *= 1.0 - (m_v_osc_stable - DSD_566__VMOD) / (m_v_osc_stable - m_v_osc_stop);
+ }
+ else
+ i_rise = i;
+ }
+ else
+ return;
+ }
+ else return;
+
+ /* Keep looping until all toggling in this time sample is used up. */
+ do
+ {
+ if (m_flip_flop)
+ {
+ /* Discharging */
+ v_cap -= i * dt / DSD_566__C;
+ dt = 0;
+
+ /* has it discharged past lower limit? */
+ if (UNEXPECTED(v_cap < m_threshold_low))
+ {
+ /* calculate the overshoot time */
+ dt = DSD_566__C * (m_threshold_low - v_cap) / i;
+ v_cap = m_threshold_low;
+ m_flip_flop = 0;
+ count_f++;
+ x_time = dt;
+ }
+ }
+ else
+ {
+ /* Charging */
+ /* iC=C*dv/dt works out to dv=iC*dt/C */
+ v_cap += i_rise * dt / DSD_566__C;
+ dt = 0;
+ /* Yes, if the cap voltage has reached the max voltage it can,
+ * and the 566 threshold has not been reached, then oscillation stops.
+ * This is the way the actual electronics works.
+ * This is why you never play with the pots after being factory adjusted
+ * to work in the proper range. */
+ if (UNEXPECTED(v_cap > DSD_566__VMOD)) v_cap = DSD_566__VMOD;
+
+ /* has it charged past upper limit? */
+ if (UNEXPECTED(v_cap > m_threshold_high))
+ {
+ /* calculate the overshoot time */
+ dt = DSD_566__C * (v_cap - m_threshold_high) / i;
+ v_cap = m_threshold_high;
+ m_flip_flop = 1;
+ count_r++;
+ x_time = dt;
+ }
+ }
+ } while(dt);
+
+ m_cap_voltage = v_cap;
+
+ /* Convert last switch time to a ratio */
+ x_time /= this->sample_time();
+
+ switch (m_out_type)
+ {
+ case DISC_566_OUT_SQUARE:
+ v_out = m_flip_flop ? m_v_sqr_high : m_v_sqr_low;
+ if (m_fake_ac)
+ v_out += m_ac_shift;
+ break;
+ case DISC_566_OUT_ENERGY:
+ if (x_time == 0) x_time = 1.0;
+ v_out = m_v_sqr_low + m_v_sqr_diff * (m_flip_flop ? x_time : (1.0 - x_time));
+ if (m_fake_ac)
+ v_out += m_ac_shift;
+ break;
+ case DISC_566_OUT_LOGIC:
+ v_out = m_flip_flop;
+ break;
+ case DISC_566_OUT_TRIANGLE:
+ v_out = v_cap;
+ if (m_fake_ac)
+ v_out += m_ac_shift;
+ break;
+ case DISC_566_OUT_COUNT_F_X:
+ v_out = count_f ? count_f + x_time : count_f;
+ break;
+ case DISC_566_OUT_COUNT_R_X:
+ v_out = count_r ? count_r + x_time : count_r;
+ break;
+ case DISC_566_OUT_COUNT_F:
+ v_out = count_f;
+ break;
+ case DISC_566_OUT_COUNT_R:
+ v_out = count_r;
+ break;
+ }
+ set_output(0, v_out);
+}
+
+DISCRETE_RESET(dsd_566)
+{
+ int v_int;
+ double v_float;
+
+ m_out_type = (int)DSD_566__OPTIONS & DISC_566_OUT_MASK;
+ m_fake_ac = (int)DSD_566__OPTIONS & DISC_566_OUT_AC;
+
+ if (DSD_566__VNEG >= DSD_566__VPOS)
+ fatalerror("[v_neg >= v_pos] in NODE_%d!\n", this->index());
+
+ v_float = DSD_566__VPOS - DSD_566__VNEG;
+ v_int = (int)v_float;
+ if ( v_float < 10 || v_float > 15 )
+ fatalerror("v_neg and/or v_pos out of range in NODE_%d\n", this->index());
+ if ( v_float != v_int )
+ /* fatal for now. */
+ fatalerror("Power should be integer in NODE_%d\n", this->index());
+
+ m_flip_flop = 0;
+ m_cap_voltage = 0;
+
+ v_int -= 10;
+ m_threshold_high = ne566.c_high[v_int] + DSD_566__VNEG;
+ m_threshold_low = ne566.c_low[v_int] + DSD_566__VNEG;
+ m_v_sqr_high = DSD_566__VPOS - 1;
+ m_v_sqr_low = ne566.sqr_low[v_int] + DSD_566__VNEG;
+ m_v_sqr_diff = m_v_sqr_high - m_v_sqr_low;
+ m_v_osc_stable = ne566.osc_stable[v_int] + DSD_566__VNEG;
+ m_v_osc_stop = ne566.osc_stop[v_int] + DSD_566__VNEG;
+
+ m_ac_shift = 0;
+ if (m_fake_ac)
+ {
+ if (m_out_type == DISC_566_OUT_TRIANGLE)
+ m_ac_shift = (m_threshold_high - m_threshold_low) / 2 - m_threshold_high;
+ else
+ m_ac_shift = m_v_sqr_diff / 2 - m_v_sqr_high;
+ }
+
+ /* Step the output */
+ this->step();
+}
+
+
+/************************************************************************
+ *
+ * DSD_LS624 - Usage of node_description values
+ *
+ * Dec 2007, Couriersud based on data sheet
+ * Oct 2009, complete re-write based on IC testing
+ ************************************************************************/
+#define DSD_LS624__ENABLE DISCRETE_INPUT(0)
+#define DSD_LS624__VMOD DISCRETE_INPUT(1)
+#define DSD_LS624__VRNG DISCRETE_INPUT(2)
+#define DSD_LS624__C DISCRETE_INPUT(3)
+#define DSD_LS624__R_FREQ_IN DISCRETE_INPUT(4)
+#define DSD_LS624__C_FREQ_IN DISCRETE_INPUT(5)
+#define DSD_LS624__R_RNG_IN DISCRETE_INPUT(6)
+#define DSD_LS624__OUTTYPE DISCRETE_INPUT(7)
+
+#define LS624_R_EXT 600.0 /* as specified in data sheet */
+#define LS624_OUT_HIGH 4.5 /* measured */
+#define LS624_IN_R RES_K(90) /* measured & 70K + 20k per data sheet */
+
+/*
+ * The 74LS624 series are constant current based VCOs. The Freq Control voltage
+ * modulates the current source. The current is created from Rext, which is
+ * internally fixed at 600 ohms for all devices except the 74LS628 which has
+ * external connections. The current source linearly discharges the cap voltage.
+ * The cap starts with 0V charge across it. One side is connected to a fixed voltage
+ * bias circuit. The other side is charged negatively from the current source until
+ * a certain low threshold is reached. Once this threshold is reached, the output
+ * toggles state and the pins on the cap reverse in respect to the charge/bias hookup.
+ * This starts the one side of the cap to be at bias, and the other side of the cap is
+ * now at bias + the charge on the cap which is bias - threshold.
+ * Y = 0; CX1 = bias; CX2 = charge
+ * Y = 1; CX1 = charge; CX2 = bias
+ * The Range voltage adjusts the threshold voltage. The higher the Range voltage,
+ * the lower the threshold voltage, the longer the cap can charge, the lower the frequency.
+ *
+ * In a perfect world it would work like this:
+ * The current is based on the mysterious Rext mentioned in the data sheet.
+ * I = (VfreqControl * 20k/90k) / Rext
+ * where Rext = 600 ohms or external Rext on a 74LS628
+ * The Freq Control has an input impedance of approximately 90k, so any input resistance
+ * connected to the Freq Control pin works as a voltage divider.
+ * I = (VfreqControl * 20k/(90k + RfreqControlIn)) / Rext
+ * That gives us a change in voltage on the cap of
+ * dV = I / sampleRate / C_inFarads
+ *
+ * Unfortunately the chip does not behave linearly do to internal interactions,
+ * so I have just worked out the formula (using zunzun.com) of FreqControl and
+ * range to frequency out for a fixed cap value of 0.1uf. Other cap values can just
+ * scale from that. From the freq, we calculate the time of 1/2 cycle using 1/Freq/2.
+ * Then just use that to toggle a waveform.
+ */
+
+
+DISCRETE_STEP(dsd_ls624)
+{
+ double x_time = 0;
+ double freq, t1;
+ double v_freq_2, v_freq_3, v_freq_4;
+ double t_used = m_t_used;
+ double dt = this->sample_time();;
+ double v_freq = DSD_LS624__VMOD;
+ double v_rng = DSD_LS624__VRNG;
+ int count_f = 0, count_r = 0;
+
+ /* coefficients */
+ const double k1 = 1.9904769024796283E+03;
+ const double k2 = 1.2070059213983407E+03;
+ const double k3 = 1.3266985579561108E+03;
+ const double k4 = -1.5500979825922698E+02;
+ const double k5 = 2.8184536266938172E+00;
+ const double k6 = -2.3503421582744556E+02;
+ const double k7 = -3.3836786704527788E+02;
+ const double k8 = -1.3569136703258670E+02;
+ const double k9 = 2.9914575453819188E+00;
+ const double k10 = 1.6855569086173170E+00;
+
+ if (UNEXPECTED(DSD_LS624__ENABLE == 0))
+ return;
+
+ /* scale due to input resistance */
+ v_freq *= m_v_freq_scale;
+ v_rng *= m_v_rng_scale;
+
+ /* apply cap if needed */
+ if (m_has_freq_in_cap)
+ {
+ m_v_cap_freq_in += (v_freq - m_v_cap_freq_in) * m_exponent;
+ v_freq = m_v_cap_freq_in;
+ }
+
+ /* Polyfunctional3D_model created by zunzun.com using sum of squared absolute error */
+ v_freq_2 = v_freq * v_freq;
+ v_freq_3 = v_freq_2 * v_freq;
+ v_freq_4 = v_freq_3 * v_freq;
+ freq = k1;
+ freq += k2 * v_freq;
+ freq += k3 * v_freq_2;
+ freq += k4 * v_freq_3;
+ freq += k5 * v_freq_4;
+ freq += k6 * v_rng;
+ freq += k7 * v_rng * v_freq;
+ freq += k8 * v_rng * v_freq_2;
+ freq += k9 * v_rng * v_freq_3;
+ freq += k10 * v_rng * v_freq_4;
+
+ freq *= CAP_U(0.1) / DSD_LS624__C;
+
+ t1 = 0.5 / freq ;
+ t_used += this->sample_time();
+ do
+ {
+ dt = 0;
+ if (t_used > t1)
+ {
+ /* calculate the overshoot time */
+ t_used -= t1;
+ m_flip_flop ^= 1;
+ if (m_flip_flop)
+ count_r++;
+ else
+ count_f++;
+ /* fix up any frequency increase change errors */
+ while(t_used > this->sample_time())
+ t_used -= this->sample_time();
+ x_time = t_used;
+ dt = t_used;
+ }
+ }while(dt);
+
+ m_t_used = t_used;
+
+ /* Convert last switch time to a ratio */
+ x_time = x_time / this->sample_time();
+
+ switch (m_out_type)
+ {
+ case DISC_LS624_OUT_LOGIC_X:
+ set_output(0, m_flip_flop + x_time);
+ break;
+ case DISC_LS624_OUT_COUNT_F_X:
+ set_output(0, count_f ? count_f + x_time : count_f);
+ break;
+ case DISC_LS624_OUT_COUNT_R_X:
+ set_output(0, count_r ? count_r + x_time : count_r);
+ break;
+ case DISC_LS624_OUT_COUNT_F:
+ set_output(0, count_f);
+ break;
+ case DISC_LS624_OUT_COUNT_R:
+ set_output(0, count_r);
+ break;
+ case DISC_LS624_OUT_ENERGY:
+ if (x_time == 0) x_time = 1.0;
+ set_output(0, LS624_OUT_HIGH * (m_flip_flop ? x_time : (1.0 - x_time)));
+ break;
+ case DISC_LS624_OUT_LOGIC:
+ set_output(0, m_flip_flop);
+ break;
+ case DISC_LS624_OUT_SQUARE:
+ set_output(0, m_flip_flop ? LS624_OUT_HIGH : 0);
+ break;
+ }
+}
+
+DISCRETE_RESET(dsd_ls624)
+{
+ m_out_type = (int)DSD_LS624__OUTTYPE;
+
+ m_flip_flop = 0;
+ m_t_used = 0;
+ m_v_freq_scale = LS624_IN_R / (DSD_LS624__R_FREQ_IN + LS624_IN_R);
+ m_v_rng_scale = LS624_IN_R / (DSD_LS624__R_RNG_IN + LS624_IN_R);
+ if (DSD_LS624__C_FREQ_IN > 0)
+ {
+ m_has_freq_in_cap = 1;
+ m_exponent = RC_CHARGE_EXP(RES_2_PARALLEL(DSD_LS624__R_FREQ_IN, LS624_IN_R) * DSD_LS624__C_FREQ_IN);
+ m_v_cap_freq_in = 0;
+ }
+ else
+ m_has_freq_in_cap = 0;
+
+ set_output(0, 0);
+}
diff --git a/trunk/src/emu/sound/disc_dev.h b/trunk/src/emu/sound/disc_dev.h
new file mode 100644
index 00000000000..1915a47233b
--- /dev/null
+++ b/trunk/src/emu/sound/disc_dev.h
@@ -0,0 +1,127 @@
+#pragma once
+
+#ifndef __DISC_DEV_H__
+#define __DISC_DEV_H__
+
+/***********************************************************************
+ *
+ * MAME - Discrete sound system emulation library
+ *
+ * Written by Keith Wilkins (mame@esplexo.co.uk)
+ *
+ * (c) K.Wilkins 2000
+ *
+ * Coding started in November 2000
+ *
+ * Additions/bugfix February 2003 - D.Renaud, F.Palazzolo, K.Wilkins
+ * Discrete parallel tasks 2009 - Couriersud
+ * Discrete classes 2010 - Couriersud
+ *
+ ***********************************************************************/
+
+#include "discrete.h"
+
+DISCRETE_CLASS_STEP_RESET(dsd_555_astbl, 1,
+ int m_use_ctrlv;
+ int m_output_type;
+ int m_output_is_ac;
+ double m_ac_shift; /* DC shift needed to make waveform ac */
+ int m_flip_flop; /* 555 flip/flop output state */
+ double m_cap_voltage; /* voltage on cap */
+ double m_threshold;
+ double m_trigger;
+ double m_v_out_high; /* Logic 1 voltage level */
+ double m_v_charge;
+ const double * m_v_charge_node; /* point to output of node */
+ int m_has_rc_nodes;
+ double m_exp_bleed;
+ double m_exp_charge;
+ double m_exp_discharge;
+ double m_t_rc_bleed;
+ double m_t_rc_charge;
+ double m_t_rc_discharge;
+ double m_last_r1;
+ double m_last_r2;
+ double m_last_c;
+);
+
+DISCRETE_CLASS_STEP_RESET(dsd_555_mstbl, 1,
+ int m_trig_is_logic;
+ int m_trig_discharges_cap;
+ int m_output_type;
+ double m_ac_shift; /* DC shift needed to make waveform ac */
+ int m_flip_flop; /* 555 flip/flop output state */
+ int m_has_rc_nodes;
+ double m_exp_charge;
+ double m_cap_voltage; /* voltage on cap */
+ double m_threshold;
+ double m_trigger;
+ double m_v_out_high; /* Logic 1 voltage level */
+ double m_v_charge;
+);
+
+DISCRETE_CLASS_STEP_RESET(dsd_555_cc, 1,
+ unsigned int m_type; /* type of 555cc circuit */
+ int m_output_type;
+ int m_output_is_ac;
+ double m_ac_shift; /* DC shift needed to make waveform ac */
+ int m_flip_flop; /* 555 flip/flop output state */
+ double m_cap_voltage; /* voltage on cap */
+ double m_threshold;
+ double m_trigger;
+ double m_v_out_high; /* Logic 1 voltage level */
+ double m_v_cc_source;
+ int m_has_rc_nodes;
+ double m_exp_bleed;
+ double m_exp_charge;
+ double m_exp_discharge;
+ double m_exp_discharge_01;
+ double m_exp_discharge_no_i;
+ double m_t_rc_charge;
+ double m_t_rc_discharge;
+ double m_t_rc_discharge_01;
+ double m_t_rc_discharge_no_i;
+);
+
+DISCRETE_CLASS_STEP_RESET(dsd_555_vco1, 1,
+ int m_ctrlv_is_node;
+ int m_output_type;
+ int m_output_is_ac;
+ double m_ac_shift; /* DC shift needed to make waveform ac */
+ int m_flip_flop; /* flip/flop output state */
+ double m_v_out_high; /* 555 high voltage */
+ double m_threshold; /* falling threshold */
+ double m_trigger; /* rising threshold */
+ double m_i_charge; /* charge current */
+ double m_i_discharge; /* discharge current */
+ double m_cap_voltage; /* current capacitor voltage */
+);
+
+DISCRETE_CLASS_STEP_RESET(dsd_566, 1,
+ unsigned int m_state[2]; /* keeps track of excess flip_flop changes during the current step */
+ int m_flip_flop; /* 566 flip/flop output state */
+ double m_cap_voltage; /* voltage on cap */
+ double m_v_sqr_low; /* voltage for a squarewave at low */
+ double m_v_sqr_high; /* voltage for a squarewave at high */
+ double m_v_sqr_diff;
+ double m_threshold_low; /* falling threshold */
+ double m_threshold_high; /* rising threshold */
+ double m_ac_shift; /* used to fake AC */
+ double m_v_osc_stable;
+ double m_v_osc_stop;
+ int m_fake_ac;
+ int m_out_type;
+);
+
+DISCRETE_CLASS_STEP_RESET(dsd_ls624, 1,
+ double m_exponent;
+ double m_t_used;
+ double m_v_cap_freq_in;
+ double m_v_freq_scale;
+ double m_v_rng_scale;
+ int m_flip_flop;
+ int m_has_freq_in_cap;
+ int m_out_type;
+);
+
+#endif /* __DISC_WAV_H__ */
diff --git a/trunk/src/emu/sound/disc_flt.c b/trunk/src/emu/sound/disc_flt.c
new file mode 100644
index 00000000000..36fa0626636
--- /dev/null
+++ b/trunk/src/emu/sound/disc_flt.c
@@ -0,0 +1,1436 @@
+/************************************************************************
+ *
+ * MAME - Discrete sound system emulation library
+ *
+ * Written by Keith Wilkins (mame@esplexo.co.uk)
+ *
+ * (c) K.Wilkins 2000
+ *
+ ***********************************************************************
+ *
+ * DST_CRFILTER - Simple CR filter & also highpass filter
+ * DST_FILTER1 - Generic 1st order filter
+ * DST_FILTER2 - Generic 2nd order filter
+ * DST_OP_AMP_FILT - Op Amp filter circuits
+ * DST_RC_CIRCUIT_1 - RC charge/discharge circuit
+ * DST_RCDISC - Simple discharging RC
+ * DST_RCDISC2 - Simple charge R1/C, discharge R0/C
+ * DST_RCDISC3 - Simple charge R1/c, discharge R0*R1/(R0+R1)/C
+ * DST_RCDISC4 - Various charge/discharge circuits
+ * DST_RCDISC5 - Diode in series with R//C
+ * DST_RCDISC_MOD - RC triggered by logic and modulated
+ * DST_RCFILTER - Simple RC filter & also lowpass filter
+ * DST_RCFILTER_SW - Usage of node_description values for switchable RC filter
+ * DST_RCINTEGRATE - Two diode inputs, transistor and a R/C charge
+ * discharge network
+ * DST_SALLEN_KEY - Sallen-Key filter circuit
+ *
+ ************************************************************************/
+
+
+/************************************************************************
+ *
+ * DST_CRFILTER - Usage of node_description values for CR filter
+ *
+ * input[0] - Enable input value
+ * input[1] - input value
+ * input[2] - Resistor value (initialization only)
+ * input[3] - Capacitor Value (initialization only)
+ * input[4] - Voltage reference. Usually 0V.
+ *
+ ************************************************************************/
+#define DST_CRFILTER__IN DISCRETE_INPUT(0)
+#define DST_CRFILTER__R DISCRETE_INPUT(1)
+#define DST_CRFILTER__C DISCRETE_INPUT(2)
+#define DST_CRFILTER__VREF DISCRETE_INPUT(3)
+
+DISCRETE_STEP(dst_crfilter)
+{
+ if (UNEXPECTED(m_has_rc_nodes))
+ {
+ double rc = DST_CRFILTER__R * DST_CRFILTER__C;
+ if (rc != m_rc)
+ {
+ m_rc = rc;
+ m_exponent = RC_CHARGE_EXP(rc);
+ }
+ }
+
+ double v_out = DST_CRFILTER__IN - m_vCap;
+ double v_diff = v_out - DST_CRFILTER__VREF;
+ set_output(0, v_out);
+ m_vCap += v_diff * m_exponent;
+}
+
+DISCRETE_RESET(dst_crfilter)
+{
+ m_has_rc_nodes = this->input_is_node() & 0x6;
+ m_rc = DST_CRFILTER__R * DST_CRFILTER__C;
+ m_exponent = RC_CHARGE_EXP(m_rc);
+ m_vCap = 0;
+ set_output(0, DST_CRFILTER__IN);
+}
+
+
+/************************************************************************
+ *
+ * DST_FILTER1 - Generic 1st order filter
+ *
+ * input[0] - Enable input value
+ * input[1] - input value
+ * input[2] - Frequency value (initialization only)
+ * input[3] - Filter type (initialization only)
+ *
+ ************************************************************************/
+#define DST_FILTER1__ENABLE DISCRETE_INPUT(0)
+#define DST_FILTER1__IN DISCRETE_INPUT(1)
+#define DST_FILTER1__FREQ DISCRETE_INPUT(2)
+#define DST_FILTER1__TYPE DISCRETE_INPUT(3)
+
+static void calculate_filter1_coefficients(discrete_base_node *node, double fc, double type,
+ struct discrete_filter_coeff &coeff)
+{
+ double den, w, two_over_T;
+
+ /* calculate digital filter coefficents */
+ /*w = 2.0*M_PI*fc; no pre-warping */
+ w = node->sample_rate()*2.0*tan(M_PI*fc/node->sample_rate()); /* pre-warping */
+ two_over_T = 2.0*node->sample_rate();
+
+ den = w + two_over_T;
+ coeff.a1 = (w - two_over_T)/den;
+ if (type == DISC_FILTER_LOWPASS)
+ {
+ coeff.b0 = coeff.b1 = w/den;
+ }
+ else if (type == DISC_FILTER_HIGHPASS)
+ {
+ coeff.b0 = two_over_T/den;
+ coeff.b1 = -(coeff.b0);
+ }
+ else
+ {
+ /* FIXME: reenable */
+ //node->m_device->discrete_log("calculate_filter1_coefficients() - Invalid filter type for 1st order filter.");
+ }
+}
+
+DISCRETE_STEP(dst_filter1)
+{
+ double gain = 1.0;
+ double v_out;
+
+ if (DST_FILTER1__ENABLE == 0.0)
+ {
+ gain = 0.0;
+ }
+
+ v_out = -m_fc.a1*m_fc.y1 + m_fc.b0*gain*DST_FILTER1__IN + m_fc.b1*m_fc.x1;
+
+ m_fc.x1 = gain*DST_FILTER1__IN;
+ m_fc.y1 = v_out;
+ set_output(0, v_out);
+}
+
+DISCRETE_RESET(dst_filter1)
+{
+ calculate_filter1_coefficients(this, DST_FILTER1__FREQ, DST_FILTER1__TYPE, m_fc);
+ set_output(0, 0);
+}
+
+
+/************************************************************************
+ *
+ * DST_FILTER2 - Generic 2nd order filter
+ *
+ * input[0] - Enable input value
+ * input[1] - input value
+ * input[2] - Frequency value (initialization only)
+ * input[3] - Damping value (initialization only)
+ * input[4] - Filter type (initialization only)
+ *
+ ************************************************************************/
+#define DST_FILTER2__ENABLE DISCRETE_INPUT(0)
+#define DST_FILTER2__IN DISCRETE_INPUT(1)
+#define DST_FILTER2__FREQ DISCRETE_INPUT(2)
+#define DST_FILTER2__DAMP DISCRETE_INPUT(3)
+#define DST_FILTER2__TYPE DISCRETE_INPUT(4)
+
+static void calculate_filter2_coefficients(discrete_base_node *node,
+ double fc, double d, double type,
+ struct discrete_filter_coeff &coeff)
+{
+ double w; /* cutoff freq, in radians/sec */
+ double w_squared;
+ double den; /* temp variable */
+ double two_over_T = 2 * node->sample_rate();
+ double two_over_T_squared = two_over_T * two_over_T;
+
+ /* calculate digital filter coefficents */
+ /*w = 2.0*M_PI*fc; no pre-warping */
+ w = node->sample_rate() * 2.0 * tan(M_PI * fc / node->sample_rate()); /* pre-warping */
+ w_squared = w * w;
+
+ den = two_over_T_squared + d*w*two_over_T + w_squared;
+
+ coeff.a1 = 2.0 * (-two_over_T_squared + w_squared) / den;
+ coeff.a2 = (two_over_T_squared - d * w * two_over_T + w_squared) / den;
+
+ if (type == DISC_FILTER_LOWPASS)
+ {
+ coeff.b0 = coeff.b2 = w_squared/den;
+ coeff.b1 = 2.0 * (coeff.b0);
+ }
+ else if (type == DISC_FILTER_BANDPASS)
+ {
+ coeff.b0 = d * w * two_over_T / den;
+ coeff.b1 = 0.0;
+ coeff.b2 = -(coeff.b0);
+ }
+ else if (type == DISC_FILTER_HIGHPASS)
+ {
+ coeff.b0 = coeff.b2 = two_over_T_squared / den;
+ coeff.b1 = -2.0 * (coeff.b0);
+ }
+ else
+ {
+ /* FIXME: reenable */
+ //node->device->discrete_log("calculate_filter2_coefficients() - Invalid filter type for 2nd order filter.");
+ }
+}
+
+DISCRETE_STEP(dst_filter2)
+{
+ double gain = 1.0;
+ double v_out;
+
+ if (DST_FILTER2__ENABLE == 0.0)
+ {
+ gain = 0.0;
+ }
+
+ v_out = -m_fc.a1 * m_fc.y1 - m_fc.a2 * m_fc.y2 +
+ m_fc.b0 * gain * DST_FILTER2__IN + m_fc.b1 * m_fc.x1 + m_fc.b2 * m_fc.x2;
+
+ m_fc.x2 = m_fc.x1;
+ m_fc.x1 = gain * DST_FILTER2__IN;
+ m_fc.y2 = m_fc.y1;
+ m_fc.y1 = v_out;
+ set_output(0, v_out);
+}
+
+DISCRETE_RESET(dst_filter2)
+{
+ calculate_filter2_coefficients(this, DST_FILTER2__FREQ, DST_FILTER2__DAMP, DST_FILTER2__TYPE,
+ m_fc);
+ set_output(0, 0);
+}
+
+
+/************************************************************************
+ *
+ * DST_OP_AMP_FILT - Op Amp filter circuit RC filter
+ *
+ * input[0] - Enable input value
+ * input[1] - IN0 node
+ * input[2] - IN1 node
+ * input[3] - Filter Type
+ *
+ * also passed discrete_op_amp_filt_info structure
+ *
+ * Mar 2004, D Renaud.
+ ************************************************************************/
+#define DST_OP_AMP_FILT__ENABLE DISCRETE_INPUT(0)
+#define DST_OP_AMP_FILT__INP1 DISCRETE_INPUT(1)
+#define DST_OP_AMP_FILT__INP2 DISCRETE_INPUT(2)
+#define DST_OP_AMP_FILT__TYPE DISCRETE_INPUT(3)
+
+DISCRETE_STEP(dst_op_amp_filt)
+{
+ DISCRETE_DECLARE_INFO(discrete_op_amp_filt_info)
+ double v_out = 0;
+
+ double i, v = 0;
+
+ if (DST_OP_AMP_FILT__ENABLE)
+ {
+ if (m_is_norton)
+ {
+ v = DST_OP_AMP_FILT__INP1 - OP_AMP_NORTON_VBE;
+ if (v < 0) v = 0;
+ }
+ else
+ {
+ /* Millman the input voltages. */
+ i = m_iFixed;
+ switch (m_type)
+ {
+ case DISC_OP_AMP_FILTER_IS_LOW_PASS_1_A:
+ i += (DST_OP_AMP_FILT__INP1 - DST_OP_AMP_FILT__INP2) / info->r1;
+ if (info->r2 != 0)
+ i += (m_vP - DST_OP_AMP_FILT__INP2) / info->r2;
+ if (info->r3 != 0)
+ i += (m_vN - DST_OP_AMP_FILT__INP2) / info->r3;
+ break;
+ default:
+ i += (DST_OP_AMP_FILT__INP1 - m_vRef) / info->r1;
+ if (info->r2 != 0)
+ i += (DST_OP_AMP_FILT__INP2 - m_vRef) / info->r2;
+ break;
+ }
+ v = i * m_rTotal;
+ }
+
+ switch (m_type)
+ {
+ case DISC_OP_AMP_FILTER_IS_LOW_PASS_1:
+ m_vC1 += (v - m_vC1) * m_exponentC1;
+ v_out = m_vC1 * m_gain + info->vRef;
+ break;
+
+ case DISC_OP_AMP_FILTER_IS_LOW_PASS_1_A:
+ m_vC1 += (v - m_vC1) * m_exponentC1;
+ v_out = m_vC1 * m_gain + DST_OP_AMP_FILT__INP2;
+ break;
+
+ case DISC_OP_AMP_FILTER_IS_HIGH_PASS_1:
+ v_out = (v - m_vC1) * m_gain + info->vRef;
+ m_vC1 += (v - m_vC1) * m_exponentC1;
+ break;
+
+ case DISC_OP_AMP_FILTER_IS_BAND_PASS_1:
+ v_out = (v - m_vC2);
+ m_vC2 += (v - m_vC2) * m_exponentC2;
+ m_vC1 += (v_out - m_vC1) * m_exponentC1;
+ v_out = m_vC1 * m_gain + info->vRef;
+ break;
+
+ case DISC_OP_AMP_FILTER_IS_BAND_PASS_0 | DISC_OP_AMP_IS_NORTON:
+ m_vC1 += (v - m_vC1) * m_exponentC1;
+ m_vC2 += (m_vC1 - m_vC2) * m_exponentC2;
+ v = m_vC2;
+ v_out = v - m_vC3;
+ m_vC3 += (v - m_vC3) * m_exponentC3;
+ i = v_out / m_rTotal;
+ v_out = (m_iFixed - i) * info->rF;
+ break;
+
+ case DISC_OP_AMP_FILTER_IS_HIGH_PASS_0 | DISC_OP_AMP_IS_NORTON:
+ v_out = v - m_vC1;
+ m_vC1 += (v - m_vC1) * m_exponentC1;
+ i = v_out / m_rTotal;
+ v_out = (m_iFixed - i) * info->rF;
+ break;
+
+ case DISC_OP_AMP_FILTER_IS_BAND_PASS_1M:
+ case DISC_OP_AMP_FILTER_IS_BAND_PASS_1M | DISC_OP_AMP_IS_NORTON:
+ v_out = -m_fc.a1 * m_fc.y1 - m_fc.a2 * m_fc.y2 +
+ m_fc.b0 * v + m_fc.b1 * m_fc.x1 + m_fc.b2 * m_fc.x2 +
+ m_vRef;
+ m_fc.x2 = m_fc.x1;
+ m_fc.x1 = v;
+ m_fc.y2 = m_fc.y1;
+ break;
+ }
+
+ /* Clip the output to the voltage rails.
+ * This way we get the original distortion in all it's glory.
+ */
+ if (v_out > m_vP) v_out = m_vP;
+ if (v_out < m_vN) v_out = m_vN;
+ m_fc.y1 = v_out - m_vRef;
+ set_output(0, v_out);
+ }
+ else
+ set_output(0, 0);
+
+}
+
+DISCRETE_RESET(dst_op_amp_filt)
+{
+ DISCRETE_DECLARE_INFO(discrete_op_amp_filt_info)
+
+ /* Convert the passed filter type into an int for easy use. */
+ m_type = (int)DST_OP_AMP_FILT__TYPE & DISC_OP_AMP_FILTER_TYPE_MASK;
+ m_is_norton = (int)DST_OP_AMP_FILT__TYPE & DISC_OP_AMP_IS_NORTON;
+
+ if (m_is_norton)
+ {
+ m_vRef = 0;
+ m_rTotal = info->r1;
+ if (m_type == (DISC_OP_AMP_FILTER_IS_BAND_PASS_0 | DISC_OP_AMP_IS_NORTON))
+ m_rTotal += info->r2 + info->r3;
+
+ /* Setup the current to the + input. */
+ m_iFixed = (info->vP - OP_AMP_NORTON_VBE) / info->r4;
+
+ /* Set the output max. */
+ m_vP = info->vP - OP_AMP_NORTON_VBE;
+ m_vN = info->vN;
+ }
+ else
+ {
+ m_vRef = info->vRef;
+ /* Set the output max. */
+ m_vP = info->vP - OP_AMP_VP_RAIL_OFFSET;
+ m_vN = info->vN;
+
+ /* Work out the input resistance. It is all input and bias resistors in parallel. */
+ m_rTotal = 1.0 / info->r1; /* There has to be an R1. Otherwise the table is wrong. */
+ if (info->r2 != 0) m_rTotal += 1.0 / info->r2;
+ if (info->r3 != 0) m_rTotal += 1.0 / info->r3;
+ m_rTotal = 1.0 / m_rTotal;
+
+ m_iFixed = 0;
+
+ m_rRatio = info->rF / (m_rTotal + info->rF);
+ m_gain = -info->rF / m_rTotal;
+ }
+
+ switch (m_type)
+ {
+ case DISC_OP_AMP_FILTER_IS_LOW_PASS_1:
+ case DISC_OP_AMP_FILTER_IS_LOW_PASS_1_A:
+ m_exponentC1 = RC_CHARGE_EXP(info->rF * info->c1);
+ m_exponentC2 = 0;
+ break;
+ case DISC_OP_AMP_FILTER_IS_HIGH_PASS_1:
+ m_exponentC1 = RC_CHARGE_EXP(m_rTotal * info->c1);
+ m_exponentC2 = 0;
+ break;
+ case DISC_OP_AMP_FILTER_IS_BAND_PASS_1:
+ m_exponentC1 = RC_CHARGE_EXP(info->rF * info->c1);
+ m_exponentC2 = RC_CHARGE_EXP(m_rTotal * info->c2);
+ break;
+ case DISC_OP_AMP_FILTER_IS_BAND_PASS_1M | DISC_OP_AMP_IS_NORTON:
+ if (info->r2 == 0)
+ m_rTotal = info->r1;
+ else
+ m_rTotal = RES_2_PARALLEL(info->r1, info->r2);
+ case DISC_OP_AMP_FILTER_IS_BAND_PASS_1M:
+ {
+ double fc = 1.0 / (2 * M_PI * sqrt(m_rTotal * info->rF * info->c1 * info->c2));
+ double d = (info->c1 + info->c2) / sqrt(info->rF / m_rTotal * info->c1 * info->c2);
+ double gain = -info->rF / m_rTotal * info->c2 / (info->c1 + info->c2);
+
+ calculate_filter2_coefficients(this, fc, d, DISC_FILTER_BANDPASS, m_fc);
+ m_fc.b0 *= gain;
+ m_fc.b1 *= gain;
+ m_fc.b2 *= gain;
+
+ if (m_is_norton)
+ m_vRef = (info->vP - OP_AMP_NORTON_VBE) / info->r3 * info->rF;
+ else
+ m_vRef = info->vRef;
+
+ break;
+ }
+ case DISC_OP_AMP_FILTER_IS_BAND_PASS_0 | DISC_OP_AMP_IS_NORTON:
+ m_exponentC1 = RC_CHARGE_EXP(RES_2_PARALLEL(info->r1, info->r2 + info->r3 + info->r4) * info->c1);
+ m_exponentC2 = RC_CHARGE_EXP(RES_2_PARALLEL(info->r1 + info->r2, info->r3 + info->r4) * info->c2);
+ m_exponentC3 = RC_CHARGE_EXP((info->r1 + info->r2 + info->r3 + info->r4) * info->c3);
+ break;
+ case DISC_OP_AMP_FILTER_IS_HIGH_PASS_0 | DISC_OP_AMP_IS_NORTON:
+ m_exponentC1 = RC_CHARGE_EXP(info->r1 * info->c1);
+ break;
+ }
+
+ /* At startup there is no charge on the caps and output is 0V in relation to vRef. */
+ m_vC1 = 0;
+ m_vC1b = 0;
+ m_vC2 = 0;
+ m_vC3 = 0;
+
+ set_output(0, info->vRef);
+}
+
+
+/************************************************************************
+ *
+ * DST_RC_CIRCUIT_1 - RC charge/discharge circuit
+ *
+ ************************************************************************/
+#define DST_RC_CIRCUIT_1__IN0 DISCRETE_INPUT(0)
+#define DST_RC_CIRCUIT_1__IN1 DISCRETE_INPUT(1)
+#define DST_RC_CIRCUIT_1__R DISCRETE_INPUT(2)
+#define DST_RC_CIRCUIT_1__C DISCRETE_INPUT(3)
+
+#define CD4066_R_ON 270
+
+DISCRETE_STEP( dst_rc_circuit_1 )
+{
+ if (DST_RC_CIRCUIT_1__IN0 == 0)
+ if (DST_RC_CIRCUIT_1__IN1 == 0)
+ /* cap is floating and does not change charge */
+ /* output is pulled to ground */
+ set_output(0, 0);
+ else
+ {
+ /* cap is discharged */
+ m_v_cap -= m_v_cap * m_exp_2;
+ set_output(0, m_v_cap * m_v_drop);
+ }
+ else
+ if (DST_RC_CIRCUIT_1__IN1 == 0)
+ {
+ /* cap is charged */
+ m_v_cap += (5.0 - m_v_cap) * m_exp_1;
+ /* output is pulled to ground */
+ set_output(0, 0);
+ }
+ else
+ {
+ /* cap is charged slightly less */
+ m_v_cap += (m_v_charge_1_2 - m_v_cap) * m_exp_1_2;
+ set_output(0, m_v_cap * m_v_drop);
+ }
+}
+
+DISCRETE_RESET( dst_rc_circuit_1 )
+{
+ /* the charging voltage across the cap based on in2*/
+ m_v_drop = RES_VOLTAGE_DIVIDER(CD4066_R_ON, CD4066_R_ON + DST_RC_CIRCUIT_1__R);
+ m_v_charge_1_2 = 5.0 * m_v_drop;
+ m_v_cap = 0;
+
+ /* precalculate charging exponents */
+ /* discharge cap - in1 = 0, in2 = 1*/
+ m_exp_2 = RC_CHARGE_EXP((CD4066_R_ON + DST_RC_CIRCUIT_1__R) * DST_RC_CIRCUIT_1__C);
+ /* charge cap - in1 = 1, in2 = 0 */
+ m_exp_1 = RC_CHARGE_EXP(CD4066_R_ON * DST_RC_CIRCUIT_1__C);
+ /* charge cap - in1 = 1, in2 = 1 */
+ m_exp_1_2 = RC_CHARGE_EXP(RES_2_PARALLEL(CD4066_R_ON, CD4066_R_ON + DST_RC_CIRCUIT_1__R) * DST_RC_CIRCUIT_1__C);
+
+ /* starts at 0 until cap starts charging */
+ set_output(0, 0);
+}
+
+/************************************************************************
+ *
+ * DST_RCDISC - Usage of node_description values for RC discharge
+ * (inverse slope of DST_RCFILTER)
+ *
+ * input[0] - Enable input value
+ * input[1] - input value
+ * input[2] - Resistor value (initialization only)
+ * input[3] - Capacitor Value (initialization only)
+ *
+ ************************************************************************/
+#define DST_RCDISC__ENABLE DISCRETE_INPUT(0)
+#define DST_RCDISC__IN DISCRETE_INPUT(1)
+#define DST_RCDISC__R DISCRETE_INPUT(2)
+#define DST_RCDISC__C DISCRETE_INPUT(3)
+
+DISCRETE_STEP(dst_rcdisc)
+{
+ switch (m_state)
+ {
+ case 0: /* waiting for trigger */
+ if(DST_RCDISC__ENABLE)
+ {
+ m_state = 1;
+ m_t = 0;
+ }
+ set_output(0, 0);
+ break;
+
+ case 1:
+ if (DST_RCDISC__ENABLE)
+ {
+ set_output(0, DST_RCDISC__IN * exp(m_t / m_exponent0));
+ m_t += this->sample_time();
+ } else
+ {
+ m_state = 0;
+ }
+ }
+}
+
+DISCRETE_RESET(dst_rcdisc)
+{
+ set_output(0, 0);
+
+ m_state = 0;
+ m_t = 0;
+ m_exponent0=-1.0 * DST_RCDISC__R * DST_RCDISC__C;
+}
+
+
+/************************************************************************
+ *
+ * DST_RCDISC2 - Usage of node_description values for RC discharge
+ * Has switchable charge resistor/input
+ *
+ * input[0] - Switch input value
+ * input[1] - input[0] value
+ * input[2] - Resistor0 value (initialization only)
+ * input[3] - input[1] value
+ * input[4] - Resistor1 value (initialization only)
+ * input[5] - Capacitor Value (initialization only)
+ *
+ ************************************************************************/
+#define DST_RCDISC2__ENABLE DISCRETE_INPUT(0)
+#define DST_RCDISC2__IN0 DISCRETE_INPUT(1)
+#define DST_RCDISC2__R0 DISCRETE_INPUT(2)
+#define DST_RCDISC2__IN1 DISCRETE_INPUT(3)
+#define DST_RCDISC2__R1 DISCRETE_INPUT(4)
+#define DST_RCDISC2__C DISCRETE_INPUT(5)
+
+DISCRETE_STEP(dst_rcdisc2)
+{
+ double diff;
+
+ /* Works differently to other as we are always on, no enable */
+ /* exponential based in difference between input/output */
+
+ diff = ((DST_RCDISC2__ENABLE == 0) ? DST_RCDISC2__IN0 : DST_RCDISC2__IN1) - m_v_out;
+ diff = diff - (diff * ((DST_RCDISC2__ENABLE == 0) ? m_exponent0 : m_exponent1));
+ m_v_out += diff;
+ set_output(0, m_v_out);
+}
+
+DISCRETE_RESET(dst_rcdisc2)
+{
+ m_v_out = 0;
+
+ m_state = 0;
+ m_t = 0;
+ m_exponent0 = RC_DISCHARGE_EXP(DST_RCDISC2__R0 * DST_RCDISC2__C);
+ m_exponent1 = RC_DISCHARGE_EXP(DST_RCDISC2__R1 * DST_RCDISC2__C);
+}
+
+/************************************************************************
+ *
+ * DST_RCDISC3 - Usage of node_description values for RC discharge
+ *
+ *
+ * input[0] - Enable
+ * input[1] - input value
+ * input[2] - Resistor0 value (initialization only)
+ * input[4] - Resistor1 value (initialization only)
+ * input[5] - Capacitor Value (initialization only)
+ * input[6] - Diode Junction voltage (initialization only)
+ *
+ ************************************************************************/
+#define DST_RCDISC3__ENABLE DISCRETE_INPUT(0)
+#define DST_RCDISC3__IN DISCRETE_INPUT(1)
+#define DST_RCDISC3__R1 DISCRETE_INPUT(2)
+#define DST_RCDISC3__R2 DISCRETE_INPUT(3)
+#define DST_RCDISC3__C DISCRETE_INPUT(4)
+#define DST_RCDISC3__DJV DISCRETE_INPUT(5)
+
+DISCRETE_STEP(dst_rcdisc3)
+{
+ double diff;
+
+ /* Exponential based in difference between input/output */
+
+ if(DST_RCDISC3__ENABLE)
+ {
+ diff = DST_RCDISC3__IN - m_v_out;
+ if (m_v_diode > 0)
+ {
+ if (diff > 0)
+ {
+ diff = diff * m_exponent0;
+ }
+ else if (diff < -m_v_diode)
+ {
+ diff = diff * m_exponent1;
+ }
+ else
+ {
+ diff = diff * m_exponent0;
+ }
+ }
+ else
+ {
+ if (diff < 0)
+ {
+ diff = diff * m_exponent0;
+ }
+ else if (diff > -m_v_diode)
+ {
+ diff = diff * m_exponent1;
+ }
+ else
+ {
+ diff = diff * m_exponent0;
+ }
+ }
+ m_v_out += diff;
+ set_output(0, m_v_out);
+ }
+ else
+ {
+ set_output(0, 0);
+ }
+}
+
+DISCRETE_RESET(dst_rcdisc3)
+{
+ m_v_out = 0;
+
+ m_state = 0;
+ m_t = 0;
+ m_v_diode = DST_RCDISC3__DJV;
+ m_exponent0 = RC_CHARGE_EXP(DST_RCDISC3__R1 * DST_RCDISC3__C);
+ m_exponent1 = RC_CHARGE_EXP(RES_2_PARALLEL(DST_RCDISC3__R1, DST_RCDISC3__R2) * DST_RCDISC3__C);
+}
+
+
+/************************************************************************
+ *
+ * DST_RCDISC4 - Various charge/discharge circuits
+ *
+ * input[0] - Enable input value
+ * input[1] - input value
+ * input[2] - R1 Resistor value (initialization only)
+ * input[2] - R2 Resistor value (initialization only)
+ * input[4] - C1 Capacitor Value (initialization only)
+ * input[4] - vP power source (initialization only)
+ * input[4] - circuit type (initialization only)
+ *
+ ************************************************************************/
+#define DST_RCDISC4__ENABLE DISCRETE_INPUT(0)
+#define DST_RCDISC4__IN DISCRETE_INPUT(1)
+#define DST_RCDISC4__R1 DISCRETE_INPUT(2)
+#define DST_RCDISC4__R2 DISCRETE_INPUT(3)
+#define DST_RCDISC4__R3 DISCRETE_INPUT(4)
+#define DST_RCDISC4__C1 DISCRETE_INPUT(5)
+#define DST_RCDISC4__VP DISCRETE_INPUT(6)
+#define DST_RCDISC4__TYPE DISCRETE_INPUT(7)
+
+DISCRETE_STEP(dst_rcdisc4)
+{
+ int inp1 = (DST_RCDISC4__IN == 0) ? 0 : 1;
+ double v_out = 0;
+
+ if (DST_RCDISC4__ENABLE == 0)
+ {
+ set_output(0, 0);
+ return;
+ }
+
+ switch (m_type)
+ {
+ case 1:
+ case 3:
+ m_vC1 += ((m_v[inp1] - m_vC1) * m_exp[inp1]);
+ v_out = m_vC1;
+ break;
+ }
+
+ /* clip output */
+ if (v_out > m_max_out) v_out = m_max_out;
+ if (v_out < 0) v_out = 0;
+ set_output(0, v_out);
+}
+
+DISCRETE_RESET( dst_rcdisc4)
+{
+ double v, i, r, rT;
+
+ m_type = 0;
+ /* some error checking. */
+ if (DST_RCDISC4__R1 <= 0 || DST_RCDISC4__R2 <= 0 || DST_RCDISC4__C1 <= 0 || (DST_RCDISC4__R3 <= 0 && m_type == 1))
+ {
+ m_device->discrete_log("Invalid component values in NODE_%d.\n", this->index());
+ return;
+ }
+ if (DST_RCDISC4__VP < 3)
+ {
+ m_device->discrete_log("vP must be >= 3V in NODE_%d.\n", this->index());
+ return;
+ }
+ if (DST_RCDISC4__TYPE < 1 || DST_RCDISC4__TYPE > 3)
+ {
+ m_device->discrete_log("Invalid circuit type in NODE_%d.\n", this->index());
+ return;
+ }
+
+ m_vC1 = 0;
+ /* store type as integer */
+ m_type = (int)DST_RCDISC4__TYPE;
+ /* setup the maximum op-amp output. */
+ m_max_out = DST_RCDISC4__VP - OP_AMP_VP_RAIL_OFFSET;
+
+ switch (m_type)
+ {
+ case 1:
+ /* We will simulate this as a voltage divider with 2 states depending
+ * on the input. But we have to take the diodes into account.
+ */
+ v = DST_RCDISC4__VP - .5; /* diode drop */
+
+ /* When the input is 1, both R1 & R3 are basically in parallel. */
+ r = RES_2_PARALLEL(DST_RCDISC4__R1, DST_RCDISC4__R3);
+ rT = DST_RCDISC4__R2 + r;
+ i = v / rT;
+ m_v[1] = i * r + .5;
+ rT = RES_2_PARALLEL(DST_RCDISC4__R2, r);
+ m_exp[1] = RC_CHARGE_EXP(rT * DST_RCDISC4__C1);
+
+ /* When the input is 0, R1 is out of circuit. */
+ rT = DST_RCDISC4__R2 + DST_RCDISC4__R3;
+ i = v / rT;
+ m_v[0] = i * DST_RCDISC4__R3 + .5;
+ rT = RES_2_PARALLEL(DST_RCDISC4__R2, DST_RCDISC4__R3);
+ m_exp[0] = RC_CHARGE_EXP(rT * DST_RCDISC4__C1);
+ break;
+
+ case 3:
+ /* We will simulate this as a voltage divider with 2 states depending
+ * on the input. The 1k pullup is in parallel with the internal TTL
+ * resistance, so we will just use .5k in series with R1.
+ */
+ r = 500.0 + DST_RCDISC4__R1;
+ m_v[1] = RES_VOLTAGE_DIVIDER(r, DST_RCDISC4__R2) * (5.0 - 0.5);
+ rT = RES_2_PARALLEL(r, DST_RCDISC4__R2);
+ m_exp[1] = RC_CHARGE_EXP(rT * DST_RCDISC4__C1);
+
+ /* When the input is 0, R1 is out of circuit. */
+ m_v[0] = 0;
+ m_exp[0] = RC_CHARGE_EXP(DST_RCDISC4__R2 * DST_RCDISC4__C1);
+ break;
+ }
+}
+
+/************************************************************************
+ *
+ * DST_RCDISC5 - Diode in series with R//C
+ *
+ * input[0] - Enable input value
+ * input[1] - input value
+ * input[2] - Resistor value (initialization only)
+ * input[3] - Capacitor Value (initialization only)
+ *
+ ************************************************************************/
+#define DST_RCDISC5__ENABLE DISCRETE_INPUT(0)
+#define DST_RCDISC5__IN DISCRETE_INPUT(1)
+#define DST_RCDISC5__R DISCRETE_INPUT(2)
+#define DST_RCDISC5__C DISCRETE_INPUT(3)
+
+DISCRETE_STEP( dst_rcdisc5)
+{
+ double diff,u;
+
+ /* Exponential based in difference between input/output */
+
+ u = DST_RCDISC5__IN - 0.7; /* Diode drop */
+ if( u < 0)
+ u = 0;
+
+ diff = u - m_v_cap;
+
+ if(DST_RCDISC5__ENABLE)
+ {
+ if(diff < 0)
+ diff = diff * m_exponent0;
+
+ m_v_cap += diff;
+ set_output(0, m_v_cap);
+ }
+ else
+ {
+ if(diff > 0)
+ m_v_cap = u;
+
+ set_output(0, 0);
+ }
+}
+
+DISCRETE_RESET( dst_rcdisc5)
+{
+ set_output(0, 0);
+
+ m_state = 0;
+ m_t = 0;
+ m_v_cap = 0;
+ m_exponent0 = RC_CHARGE_EXP(DST_RCDISC5__R * DST_RCDISC5__C);
+}
+
+
+/************************************************************************
+ *
+ * DST_RCDISC_MOD - RC triggered by logic and modulated
+ *
+ * input[0] - Enable input value
+ * input[1] - input value 1
+ * input[2] - input value 2
+ * input[3] - Resistor 1 value (initialization only)
+ * input[4] - Resistor 2 value (initialization only)
+ * input[5] - Resistor 3 value (initialization only)
+ * input[6] - Resistor 4 value (initialization only)
+ * input[7] - Capacitor Value (initialization only)
+ * input[8] - Voltage Value (initialization only)
+ *
+ ************************************************************************/
+#define DST_RCDISC_MOD__IN1 DISCRETE_INPUT(0)
+#define DST_RCDISC_MOD__IN2 DISCRETE_INPUT(1)
+#define DST_RCDISC_MOD__R1 DISCRETE_INPUT(2)
+#define DST_RCDISC_MOD__R2 DISCRETE_INPUT(3)
+#define DST_RCDISC_MOD__R3 DISCRETE_INPUT(4)
+#define DST_RCDISC_MOD__R4 DISCRETE_INPUT(5)
+#define DST_RCDISC_MOD__C DISCRETE_INPUT(6)
+#define DST_RCDISC_MOD__VP DISCRETE_INPUT(7)
+
+DISCRETE_STEP(dst_rcdisc_mod)
+{
+ double diff, v_cap, u, vD;
+ int mod_state, mod1_state, mod2_state;
+
+ /* Exponential based in difference between input/output */
+ v_cap = m_v_cap;
+
+ mod1_state = DST_RCDISC_MOD__IN1 > 0.5;
+ mod2_state = DST_RCDISC_MOD__IN2 > 0.6;
+ mod_state = (mod2_state << 1) + mod1_state;
+
+ u = mod1_state ? 0 : DST_RCDISC_MOD__VP;
+ /* Clamp */
+ diff = u - v_cap;
+ vD = diff * m_vd_gain[mod_state];
+ if (vD < -0.6)
+ {
+ diff = u + 0.6 - v_cap;
+ diff -= diff * m_exp_low[mod1_state];
+ v_cap += diff;
+ set_output(0, mod2_state ? 0 : -0.6);
+ }
+ else
+ {
+ diff -= diff * m_exp_high[mod_state];
+ v_cap += diff;
+ /* neglecting current through R3 drawn by next8 node */
+ set_output(0, mod2_state ? 0: (u - v_cap) * m_gain[mod1_state]);
+ }
+ m_v_cap = v_cap;
+}
+
+DISCRETE_RESET(dst_rcdisc_mod)
+{
+ double rc[2], rc2[2];
+
+ /* pre-calculate fixed values */
+ /* DST_RCDISC_MOD__IN1 <= 0.5 */
+ rc[0] = DST_RCDISC_MOD__R1 + DST_RCDISC_MOD__R2;
+ if (rc[0] < 1) rc[0] = 1;
+ m_exp_low[0] = RC_DISCHARGE_EXP(DST_RCDISC_MOD__C * rc[0]);
+ m_gain[0] = RES_VOLTAGE_DIVIDER(rc[0], DST_RCDISC_MOD__R4);
+ /* DST_RCDISC_MOD__IN1 > 0.5 */
+ rc[1] = DST_RCDISC_MOD__R2;
+ if (rc[1] < 1) rc[1] = 1;
+ m_exp_low[1] = RC_DISCHARGE_EXP(DST_RCDISC_MOD__C * rc[1]);
+ m_gain[1] = RES_VOLTAGE_DIVIDER(rc[1], DST_RCDISC_MOD__R4);
+ /* DST_RCDISC_MOD__IN2 <= 0.6 */
+ rc2[0] = DST_RCDISC_MOD__R4;
+ /* DST_RCDISC_MOD__IN2 > 0.6 */
+ rc2[1] = RES_2_PARALLEL(DST_RCDISC_MOD__R3, DST_RCDISC_MOD__R4);
+ /* DST_RCDISC_MOD__IN1 <= 0.5 && DST_RCDISC_MOD__IN2 <= 0.6 */
+ m_exp_high[0] = RC_DISCHARGE_EXP(DST_RCDISC_MOD__C * (rc[0] + rc2[0]));
+ m_vd_gain[0] = RES_VOLTAGE_DIVIDER(rc[0], rc2[0]);
+ /* DST_RCDISC_MOD__IN1 > 0.5 && DST_RCDISC_MOD__IN2 <= 0.6 */
+ m_exp_high[1] = RC_DISCHARGE_EXP(DST_RCDISC_MOD__C * (rc[1] + rc2[0]));
+ m_vd_gain[1] = RES_VOLTAGE_DIVIDER(rc[1], rc2[0]);
+ /* DST_RCDISC_MOD__IN1 <= 0.5 && DST_RCDISC_MOD__IN2 > 0.6 */
+ m_exp_high[2] = RC_DISCHARGE_EXP(DST_RCDISC_MOD__C * (rc[0] + rc2[1]));
+ m_vd_gain[2] = RES_VOLTAGE_DIVIDER(rc[0], rc2[1]);
+ /* DST_RCDISC_MOD__IN1 > 0.5 && DST_RCDISC_MOD__IN2 > 0.6 */
+ m_exp_high[3] = RC_DISCHARGE_EXP(DST_RCDISC_MOD__C * (rc[1] + rc2[1]));
+ m_vd_gain[3] = RES_VOLTAGE_DIVIDER(rc[1], rc2[1]);
+
+ m_v_cap = 0;
+ set_output(0, 0);
+}
+
+/************************************************************************
+ *
+ * DST_RCFILTER - Usage of node_description values for RC filter
+ *
+ * input[0] - Enable input value
+ * input[1] - input value
+ * input[2] - Resistor value (initialization only)
+ * input[3] - Capacitor Value (initialization only)
+ * input[4] - Voltage reference. Usually 0V.
+ *
+ ************************************************************************/
+#define DST_RCFILTER__VIN DISCRETE_INPUT(0)
+#define DST_RCFILTER__R DISCRETE_INPUT(1)
+#define DST_RCFILTER__C DISCRETE_INPUT(2)
+#define DST_RCFILTER__VREF DISCRETE_INPUT(3)
+
+DISCRETE_STEP(dst_rcfilter)
+{
+ if (EXPECTED(m_is_fast))
+ m_v_out += ((DST_RCFILTER__VIN - m_v_out) * m_exponent);
+ else
+ {
+ if (UNEXPECTED(m_has_rc_nodes))
+ {
+ double rc = DST_RCFILTER__R * DST_RCFILTER__C;
+ if (rc != m_rc)
+ {
+ m_rc = rc;
+ m_exponent = RC_CHARGE_EXP(rc);
+ }
+ }
+
+ /************************************************************************/
+ /* Next Value = PREV + (INPUT_VALUE - PREV)*(1-(EXP(-TIMEDELTA/RC))) */
+ /************************************************************************/
+
+ m_vCap += ((DST_RCFILTER__VIN - m_v_out) * m_exponent);
+ m_v_out = m_vCap + DST_RCFILTER__VREF;
+ }
+ set_output(0, m_v_out);
+}
+
+
+DISCRETE_RESET(dst_rcfilter)
+{
+ m_has_rc_nodes = this->input_is_node() & 0x6;
+ m_rc = DST_RCFILTER__R * DST_RCFILTER__C;
+ m_exponent = RC_CHARGE_EXP(m_rc);
+ m_vCap = 0;
+ m_v_out = 0;
+ /* FIXME --> we really need another class here */
+ if (!m_has_rc_nodes && DST_RCFILTER__VREF == 0)
+ m_is_fast = 1;
+ else
+ m_is_fast = 0;
+}
+
+/************************************************************************
+ *
+ * DST_RCFILTER_SW - Usage of node_description values for switchable RC filter
+ *
+ * input[0] - Enable input value
+ * input[1] - input value
+ * input[2] - Resistor value (initialization only)
+ * input[3] - Capacitor Value (initialization only)
+ * input[4] - Voltage reference. Usually 0V.
+ *
+ ************************************************************************/
+#define DST_RCFILTER_SW__ENABLE DISCRETE_INPUT(0)
+#define DST_RCFILTER_SW__VIN DISCRETE_INPUT(1)
+#define DST_RCFILTER_SW__SWITCH DISCRETE_INPUT(2)
+#define DST_RCFILTER_SW__R DISCRETE_INPUT(3)
+#define DST_RCFILTER_SW__C(x) DISCRETE_INPUT(4+x)
+
+/* 74HC4066 : 15
+ * 74VHC4066 : 15
+ * UTC4066 : 270 @ 5VCC, 80 @ 15VCC
+ * CD4066BC : 270 (Fairchild)
+ *
+ * The choice below makes scramble sound about "right". For future error reports,
+ * we need the exact type of switch and at which voltage (5, 12?) it is operated.
+ */
+#define CD4066_ON_RES (40)
+
+// FIXME: This needs optimization !
+DISCRETE_STEP(dst_rcfilter_sw)
+{
+ int i;
+ int bits = (int)DST_RCFILTER_SW__SWITCH;
+ double us = 0;
+ double vIn = DST_RCFILTER_SW__VIN;
+ double v_out;
+
+ if (EXPECTED(DST_RCFILTER_SW__ENABLE))
+ {
+ switch (bits)
+ {
+ case 0:
+ v_out = vIn;
+ break;
+ case 1:
+ m_vCap[0] += (vIn - m_vCap[0]) * m_exp0;
+ v_out = m_vCap[0] + (vIn - m_vCap[0]) * m_factor;
+ break;
+ case 2:
+ m_vCap[1] += (vIn - m_vCap[1]) * m_exp1;
+ v_out = m_vCap[1] + (vIn - m_vCap[1]) * m_factor;
+ break;
+ default:
+ for (i = 0; i < 4; i++)
+ {
+ if (( bits & (1 << i)) != 0)
+ us += m_vCap[i];
+ }
+ v_out = m_f1[bits] * vIn + m_f2[bits] * us;
+ for (i = 0; i < 4; i++)
+ {
+ if (( bits & (1 << i)) != 0)
+ m_vCap[i] += (v_out - m_vCap[i]) * m_exp[i];
+ }
+ }
+ set_output(0, v_out);
+ }
+ else
+ {
+ set_output(0, 0);
+ }
+}
+
+DISCRETE_RESET(dst_rcfilter_sw)
+{
+ int i, bits;
+
+ for (i = 0; i < 4; i++)
+ {
+ m_vCap[i] = 0;
+ m_exp[i] = RC_CHARGE_EXP( CD4066_ON_RES * DST_RCFILTER_SW__C(i));
+ }
+
+ for (bits=0; bits < 15; bits++)
+ {
+ double rs = 0;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (( bits & (1 << i)) != 0)
+ rs += DST_RCFILTER_SW__R;
+ }
+ m_f1[bits] = RES_VOLTAGE_DIVIDER(rs, CD4066_ON_RES);
+ m_f2[bits] = DST_RCFILTER_SW__R / (CD4066_ON_RES + rs);
+ }
+
+
+ /* fast cases */
+ m_exp0 = RC_CHARGE_EXP((CD4066_ON_RES + DST_RCFILTER_SW__R) * DST_RCFILTER_SW__C(0));
+ m_exp1 = RC_CHARGE_EXP((CD4066_ON_RES + DST_RCFILTER_SW__R) * DST_RCFILTER_SW__C(1));
+ m_factor = RES_VOLTAGE_DIVIDER(DST_RCFILTER_SW__R, CD4066_ON_RES);
+
+ set_output(0, 0);
+}
+
+
+/************************************************************************
+ *
+ * DST_RCINTEGRATE - Two diode inputs, transistor and a R/C charge
+ * discharge network
+ *
+ * input[0] - Enable input value
+ * input[1] - input value 1
+ * input[2] - input value 2
+ * input[3] - Resistor 1 value (initialization only)
+ * input[4] - Resistor 2 value (initialization only)
+ * input[5] - Capacitor Value (initialization only)
+ *
+ ************************************************************************/
+#define DST_RCINTEGRATE__IN1 DISCRETE_INPUT(0)
+#define DST_RCINTEGRATE__R1 DISCRETE_INPUT(1)
+#define DST_RCINTEGRATE__R2 DISCRETE_INPUT(2)
+#define DST_RCINTEGRATE__R3 DISCRETE_INPUT(3)
+#define DST_RCINTEGRATE__C DISCRETE_INPUT(4)
+#define DST_RCINTEGRATE__VP DISCRETE_INPUT(5)
+#define DST_RCINTEGRATE__TYPE DISCRETE_INPUT(6)
+
+/* Ebers-Moll large signal model
+ * Couriersud:
+ * The implementation avoids all iterative approaches in order not to burn cycles
+ * We will calculate Ic from vBE and use this as an indication where to go.
+ * The implementation may oscillate if you change the weighting factors at the
+ * end.
+ *
+ * This implementation is not perfect, but does it's job in dkong'
+ */
+
+/* reverse saturation current */
+#define IES 7e-15
+#define ALPHAT 0.99
+#define KT 0.026
+#define EM_IC(x) (ALPHAT * IES * exp( (x) / KT - 1.0 ))
+
+DISCRETE_STEP( dst_rcintegrate)
+{
+ double diff, u, iQ, iQc, iC, RG, vE;
+ double vP;
+
+ u = DST_RCINTEGRATE__IN1;
+ vP = DST_RCINTEGRATE__VP;
+
+ if ( u - 0.7 < m_vCap * m_gain_r1_r2)
+ {
+ /* discharge .... */
+ diff = 0.0 - m_vCap;
+ iC = m_c_exp1 * diff; /* iC */
+ diff -= diff * m_exp_exponent1;
+ m_vCap += diff;
+ iQ = 0;
+ vE = m_vCap * m_gain_r1_r2;
+ RG = vE / iC;
+ }
+ else
+ {
+ /* charging */
+ diff = (vP - m_vCE) * m_f - m_vCap;
+ iC = 0.0 - m_c_exp0 * diff; /* iC */
+ diff -= diff * m_exp_exponent0;
+ m_vCap += diff;
+ iQ = iC + (iC * DST_RCINTEGRATE__R1 + m_vCap) / DST_RCINTEGRATE__R2;
+ RG = (vP - m_vCE) / iQ;
+ vE = (RG - DST_RCINTEGRATE__R3) / RG * (vP - m_vCE);
+ }
+
+
+ u = DST_RCINTEGRATE__IN1;
+ if (u > 0.7 + vE)
+ {
+ vE = u - 0.7;
+ //iQc = EM_IC(u - vE);
+ iQc = m_EM_IC_0_7;
+ }
+ else
+ iQc = EM_IC(u - vE);
+
+ m_vCE = MIN(vP - 0.1, vP - RG * iQc);
+
+ /* Avoid oscillations
+ * The method tends to largely overshoot - no wonder without
+ * iterative solution approximation
+ */
+
+ m_vCE = MAX(m_vCE, 0.1 );
+ m_vCE = 0.1 * m_vCE + 0.9 * (vP - vE - iQ * DST_RCINTEGRATE__R3);
+
+ switch (m_type)
+ {
+ case DISC_RC_INTEGRATE_TYPE1:
+ set_output(0, m_vCap);
+ break;
+ case DISC_RC_INTEGRATE_TYPE2:
+ set_output(0, vE);
+ break;
+ case DISC_RC_INTEGRATE_TYPE3:
+ set_output(0, MAX(0, vP - iQ * DST_RCINTEGRATE__R3));
+ break;
+ }
+}
+
+DISCRETE_RESET(dst_rcintegrate)
+{
+ double r;
+ double dt = this->sample_time();
+
+ m_type = DST_RCINTEGRATE__TYPE;
+
+ m_vCap = 0;
+ m_vCE = 0;
+
+ /* pre-calculate fixed values */
+ m_gain_r1_r2 = RES_VOLTAGE_DIVIDER(DST_RCINTEGRATE__R1, DST_RCINTEGRATE__R2);
+
+ r = DST_RCINTEGRATE__R1 / DST_RCINTEGRATE__R2 * DST_RCINTEGRATE__R3 + DST_RCINTEGRATE__R1 + DST_RCINTEGRATE__R3;
+
+ m_f = RES_VOLTAGE_DIVIDER(DST_RCINTEGRATE__R3, DST_RCINTEGRATE__R2);
+ m_exponent0 = -1.0 * r * m_f * DST_RCINTEGRATE__C;
+ m_exponent1 = -1.0 * (DST_RCINTEGRATE__R1 + DST_RCINTEGRATE__R2) * DST_RCINTEGRATE__C;
+ m_exp_exponent0 = exp(dt / m_exponent0);
+ m_exp_exponent1 = exp(dt / m_exponent1);
+ m_c_exp0 = DST_RCINTEGRATE__C / m_exponent0 * m_exp_exponent0;
+ m_c_exp1 = DST_RCINTEGRATE__C / m_exponent1 * m_exp_exponent1;
+
+ m_EM_IC_0_7 = EM_IC(0.7);
+
+ set_output(0, 0);
+}
+
+/************************************************************************
+ *
+ * DST_SALLEN_KEY - Sallen-Key filter circuit
+ *
+ * input[0] - Enable input value
+ * input[1] - IN0 node
+ * input[3] - Filter Type
+ *
+ * also passed discrete_op_amp_filt_info structure
+ *
+ * 2008, couriersud
+ ************************************************************************/
+#define DST_SALLEN_KEY__ENABLE DISCRETE_INPUT(0)
+#define DST_SALLEN_KEY__INP0 DISCRETE_INPUT(1)
+#define DST_SALLEN_KEY__TYPE DISCRETE_INPUT(2)
+
+DISCRETE_STEP(dst_sallen_key)
+{
+ double gain = 1.0;
+ double v_out;
+
+ if (DST_SALLEN_KEY__ENABLE == 0.0)
+ {
+ gain = 0.0;
+ }
+
+ v_out = -m_fc.a1 * m_fc.y1 - m_fc.a2 * m_fc.y2 +
+ m_fc.b0 * gain * DST_SALLEN_KEY__INP0 + m_fc.b1 * m_fc.x1 + m_fc.b2 * m_fc.x2;
+
+ m_fc.x2 = m_fc.x1;
+ m_fc.x1 = gain * DST_SALLEN_KEY__INP0;
+ m_fc.y2 = m_fc.y1;
+ m_fc.y1 = v_out;
+ set_output(0, v_out);
+}
+
+DISCRETE_RESET(dst_sallen_key)
+{
+ DISCRETE_DECLARE_INFO(discrete_op_amp_filt_info)
+
+ double freq, q;
+
+ switch ((int) DST_SALLEN_KEY__TYPE)
+ {
+ case DISC_SALLEN_KEY_LOW_PASS:
+ freq = 1.0 / ( 2.0 * M_PI * sqrt(info->c1 * info->c2 * info->r1 * info->r2));
+ q = sqrt(info->c1 * info->c2 * info->r1 * info->r2) / (info->c2 * (info->r1 + info->r2));
+ break;
+ default:
+ fatalerror("Unknown sallen key filter type");
+ }
+
+ calculate_filter2_coefficients(this, freq, 1.0 / q, DISC_FILTER_LOWPASS, m_fc);
+ set_output(0, 0);
+}
+
+
+/* !!!!!!!!!!! NEW FILTERS for testing !!!!!!!!!!!!!!!!!!!!! */
+
+
+/************************************************************************
+ *
+ * DST_RCFILTERN - Usage of node_description values for RC filter
+ *
+ * input[0] - Enable input value
+ * input[1] - input value
+ * input[2] - Resistor value (initialization only)
+ * input[3] - Capacitor Value (initialization only)
+ *
+ ************************************************************************/
+#define DST_RCFILTERN__ENABLE DISCRETE_INPUT(0)
+#define DST_RCFILTERN__IN DISCRETE_INPUT(1)
+#define DST_RCFILTERN__R DISCRETE_INPUT(2)
+#define DST_RCFILTERN__C DISCRETE_INPUT(3)
+
+#if 0
+DISCRETE_RESET(dst_rcfilterN)
+{
+#if 0
+ double f=1.0/(2*M_PI* DST_RCFILTERN__R * DST_RCFILTERN__C);
+
+/* !!!!!!!!!!!!!! CAN'T CHEAT LIKE THIS !!!!!!!!!!!!!!!! */
+/* Put this stuff in a context */
+
+ this->m_input[2] = f;
+ this->m_input[3] = DISC_FILTER_LOWPASS;
+
+ /* Use first order filter */
+ dst_filter1_reset(node);
+#endif
+}
+#endif
+
+/************************************************************************
+ *
+ * DST_RCDISCN - Usage of node_description values for RC discharge
+ * (inverse slope of DST_RCFILTER)
+ *
+ * input[0] - Enable input value
+ * input[1] - input value
+ * input[2] - Resistor value (initialization only)
+ * input[3] - Capacitor Value (initialization only)
+ *
+ ************************************************************************/
+#define DST_RCDISCN__ENABLE DISCRETE_INPUT(0)
+#define DST_RCDISCN__IN DISCRETE_INPUT(1)
+#define DST_RCDISCN__R DISCRETE_INPUT(2)
+#define DST_RCDISCN__C DISCRETE_INPUT(3)
+
+DISCRETE_RESET(dst_rcdiscN)
+{
+#if 0
+ double f = 1.0 / (2 * M_PI * DST_RCDISCN__R * DST_RCDISCN__C);
+
+/* !!!!!!!!!!!!!! CAN'T CHEAT LIKE THIS !!!!!!!!!!!!!!!! */
+/* Put this stuff in a context */
+
+ this->m_input[2] = f;
+ this->m_input[3] = DISC_FILTER_LOWPASS;
+
+ /* Use first order filter */
+ dst_filter1_reset(node);
+#endif
+}
+
+DISCRETE_STEP(dst_rcdiscN)
+{
+ double gain = 1.0;
+ double v_out;
+
+ if (DST_RCDISCN__ENABLE == 0.0)
+ {
+ gain = 0.0;
+ }
+
+ /* A rise in the input signal results in an instant charge, */
+ /* else discharge through the RC to zero */
+ if (gain* DST_RCDISCN__IN > m_x1)
+ v_out = gain* DST_RCDISCN__IN;
+ else
+ v_out = -m_a1*m_y1;
+
+ m_x1 = gain* DST_RCDISCN__IN;
+ m_y1 = v_out;
+ set_output(0, v_out);
+}
+
+
+/************************************************************************
+ *
+ * DST_RCDISC2N - Usage of node_description values for RC discharge
+ * Has switchable charge resistor/input
+ *
+ * input[0] - Switch input value
+ * input[1] - input[0] value
+ * input[2] - Resistor0 value (initialization only)
+ * input[3] - input[1] value
+ * input[4] - Resistor1 value (initialization only)
+ * input[5] - Capacitor Value (initialization only)
+ *
+ ************************************************************************/
+#define DST_RCDISC2N__ENABLE DISCRETE_INPUT(0)
+#define DST_RCDISC2N__IN0 DISCRETE_INPUT(1)
+#define DST_RCDISC2N__R0 DISCRETE_INPUT(2)
+#define DST_RCDISC2N__IN1 DISCRETE_INPUT(3)
+#define DST_RCDISC2N__R1 DISCRETE_INPUT(4)
+#define DST_RCDISC2N__C DISCRETE_INPUT(5)
+
+
+DISCRETE_STEP(dst_rcdisc2N)
+{
+ double inp = ((DST_RCDISC2N__ENABLE == 0) ? DST_RCDISC2N__IN0 : DST_RCDISC2N__IN1);
+ double v_out;
+
+ if (DST_RCDISC2N__ENABLE == 0)
+ v_out = -m_fc0.a1*m_y1 + m_fc0.b0*inp + m_fc0.b1 * m_x1;
+ else
+ v_out = -m_fc1.a1*m_y1 + m_fc1.b0*inp + m_fc1.b1*m_x1;
+
+ m_x1 = inp;
+ m_y1 = v_out;
+ set_output(0, v_out);
+}
+
+DISCRETE_RESET(dst_rcdisc2N)
+{
+ double f1,f2;
+
+ f1 = 1.0 / (2 * M_PI * DST_RCDISC2N__R0 * DST_RCDISC2N__C);
+ f2 = 1.0 / (2 * M_PI * DST_RCDISC2N__R1 * DST_RCDISC2N__C);
+
+ calculate_filter1_coefficients(this, f1, DISC_FILTER_LOWPASS, m_fc0);
+ calculate_filter1_coefficients(this, f2, DISC_FILTER_LOWPASS, m_fc1);
+
+ /* Initialize the object */
+ set_output(0, 0);
+}
diff --git a/trunk/src/emu/sound/disc_flt.h b/trunk/src/emu/sound/disc_flt.h
new file mode 100644
index 00000000000..3a62857a8b7
--- /dev/null
+++ b/trunk/src/emu/sound/disc_flt.h
@@ -0,0 +1,178 @@
+#pragma once
+
+#ifndef __DISC_FLTH__
+#define __DISC_FLT_H__
+
+/***********************************************************************
+ *
+ * MAME - Discrete sound system emulation library
+ *
+ * Written by Keith Wilkins (mame@esplexo.co.uk)
+ *
+ * (c) K.Wilkins 2000
+ *
+ * Coding started in November 2000
+ *
+ * Additions/bugfix February 2003 - D.Renaud, F.Palazzolo, K.Wilkins
+ * Discrete parallel tasks 2009 - Couriersud
+ * Discrete classes 2010 - Couriersud
+ *
+ ***********************************************************************/
+
+#include "discrete.h"
+
+struct discrete_filter_coeff
+{
+ double x1, x2; /* x[k-1], x[k-2], previous 2 input values */
+ double y1, y2; /* y[k-1], y[k-2], previous 2 output values */
+ double a1, a2; /* digital filter coefficients, denominator */
+ double b0, b1, b2; /* digital filter coefficients, numerator */
+};
+
+
+DISCRETE_CLASS_STEP_RESET(dst_filter1, 1,
+ /* uses x1, y1, a1, b0, b1 */
+ struct discrete_filter_coeff m_fc;
+);
+
+DISCRETE_CLASS_STEP_RESET(dst_filter2, 1,
+ struct discrete_filter_coeff m_fc;
+);
+
+DISCRETE_CLASS_STEP_RESET(dst_sallen_key, 1,
+ struct discrete_filter_coeff m_fc;
+);
+
+DISCRETE_CLASS_STEP_RESET(dst_crfilter, 1,
+ double m_vCap;
+ double m_rc;
+ double m_exponent;
+ UINT8 m_has_rc_nodes;
+ UINT8 m_is_fast;
+);
+
+DISCRETE_CLASS_STEP_RESET(dst_op_amp_filt, 1,
+ int m_type; /* What kind of filter */
+ int m_is_norton; /* 1 = Norton op-amps */
+ double m_vRef;
+ double m_vP;
+ double m_vN;
+ double m_rTotal; /* All input resistance in parallel. */
+ double m_iFixed; /* Current supplied by r3 & r4 if used. */
+ double m_exponentC1;
+ double m_exponentC2;
+ double m_exponentC3;
+ double m_rRatio; /* divide ratio of resistance network */
+ double m_vC1; /* Charge on C1 */
+ double m_vC1b; /* Charge on C1, part of C1 charge if needed */
+ double m_vC2; /* Charge on C2 */
+ double m_vC3; /* Charge on C2 */
+ double m_gain; /* Gain of the filter */
+ struct discrete_filter_coeff m_fc;
+);
+
+DISCRETE_CLASS_STEP_RESET(dst_rc_circuit_1, 1,
+ double m_v_cap;
+ double m_v_charge_1_2;
+ double m_v_drop;
+ double m_exp_1;
+ double m_exp_1_2;
+ double m_exp_2;
+);
+
+DISCRETE_CLASS_STEP_RESET(dst_rcdisc, 1,
+ int m_state;
+ double m_t; /* time */
+ double m_exponent0;
+);
+
+DISCRETE_CLASS_STEP_RESET(dst_rcdisc2, 1,
+ int m_state;
+ double m_v_out;
+ double m_t; /* time */
+ double m_exponent0;
+ double m_exponent1;
+);
+
+DISCRETE_CLASS_STEP_RESET(dst_rcdisc3, 1,
+ int m_state;
+ double m_v_out;
+ double m_t; /* time */
+ double m_exponent0;
+ double m_exponent1;
+ double m_v_diode; /* rcdisc3 */
+);
+
+DISCRETE_CLASS_STEP_RESET(dst_rcdisc4, 1,
+ int m_type;
+ double m_max_out;
+ double m_vC1;
+ double m_v[2];
+ double m_exp[2];
+);
+
+DISCRETE_CLASS_STEP_RESET(dst_rcdisc5, 1,
+ int m_state;
+ double m_t; /* time */
+ double m_exponent0;
+ double m_v_cap; /* rcdisc5 */
+);
+
+DISCRETE_CLASS_STEP_RESET(dst_rcintegrate, 1,
+ int m_type;
+ double m_gain_r1_r2;
+ double m_f; /* r2,r3 gain */
+ double m_vCap;
+ double m_vCE;
+ double m_exponent0;
+ double m_exponent1;
+ double m_exp_exponent0;
+ double m_exp_exponent1;
+ double m_c_exp0;
+ double m_c_exp1;
+ double m_EM_IC_0_7;
+);
+
+DISCRETE_CLASS_STEP_RESET(dst_rcdisc_mod, 1,
+ double m_v_cap;
+ double m_exp_low[2];
+ double m_exp_high[4];
+ double m_gain[2];
+ double m_vd_gain[4];
+);
+
+DISCRETE_CLASS_STEP_RESET(dst_rcfilter, 1,
+ double m_v_out;
+ double m_vCap;
+ double m_rc;
+ double m_exponent;
+ UINT8 m_has_rc_nodes;
+ UINT8 m_is_fast;
+);
+
+DISCRETE_CLASS_STEP_RESET(dst_rcfilter_sw, 1,
+ double m_vCap[4];
+ double m_exp[4];
+ double m_exp0; /* fast case bit 0 */
+ double m_exp1; /* fast case bit 1 */
+ double m_factor; /* fast case */
+ double m_f1[16];
+ double m_f2[16];
+);
+
+DISCRETE_CLASS_STEP_RESET(dst_rcdiscN, 1,
+ double m_x1; /* x[k-1], previous input value */
+ double m_y1; /* y[k-1], previous output value */
+ double m_a1; /* digital filter coefficients, denominator */
+ double m_b[2]; /* digital filter coefficients, numerator */
+);
+
+DISCRETE_CLASS_STEP_RESET(dst_rcdisc2N, 1,
+ struct discrete_filter_coeff m_fc0;
+ struct discrete_filter_coeff m_fc1;
+ double m_x1;
+ double m_y1;
+);
+
+
+#endif /* __DISC_FLT_H__ */
diff --git a/trunk/src/emu/sound/disc_inp.c b/trunk/src/emu/sound/disc_inp.c
new file mode 100644
index 00000000000..d2e09bcd7e0
--- /dev/null
+++ b/trunk/src/emu/sound/disc_inp.c
@@ -0,0 +1,341 @@
+/************************************************************************
+ *
+ * MAME - Discrete sound system emulation library
+ *
+ * Written by Keith Wilkins (mame@esplexo.co.uk)
+ *
+ * (c) K.Wilkins 2000
+ *
+ ***********************************************************************
+ *
+ * DSS_ADJUSTMENT - UI Mapped adjustable input
+ * DSS_CONSTANT - Node based constant - Do we need this ???
+ * DSS_INPUT_x - Input devices
+ * DSS_INPUT_STREAM - Connects external streams to the discrete system
+ *
+ ************************************************************************/
+
+
+#define DSS_INPUT__GAIN DISCRETE_INPUT(0)
+#define DSS_INPUT__OFFSET DISCRETE_INPUT(1)
+#define DSS_INPUT__INIT DISCRETE_INPUT(2)
+
+READ8_DEVICE_HANDLER(discrete_sound_r)
+{
+ discrete_device *disc_device = downcast<discrete_device *>(device);
+ return disc_device->read( *disc_device->machine().firstcpu->space(), offset, 0xff);
+}
+
+
+WRITE8_DEVICE_HANDLER(discrete_sound_w)
+{
+ discrete_device *disc_device = downcast<discrete_device *>(device);
+ disc_device->write(*disc_device->machine().firstcpu->space(), offset, data, 0xff);
+}
+
+/************************************************************************
+ *
+ * DSS_ADJUSTMENT - UI Adjustable constant node to emulate trimmers
+ *
+ * input[0] - Enable
+ * input[1] - Minimum value
+ * input[2] - Maximum value
+ * input[3] - Log/Linear 0=Linear !0=Log
+ * input[4] - Input Port number
+ * input[5] -
+ * input[6] -
+ *
+ ************************************************************************/
+#define DSS_ADJUSTMENT__MIN DISCRETE_INPUT(0)
+#define DSS_ADJUSTMENT__MAX DISCRETE_INPUT(1)
+#define DSS_ADJUSTMENT__LOG DISCRETE_INPUT(2)
+#define DSS_ADJUSTMENT__PORT DISCRETE_INPUT(3)
+#define DSS_ADJUSTMENT__PMIN DISCRETE_INPUT(4)
+#define DSS_ADJUSTMENT__PMAX DISCRETE_INPUT(5)
+
+DISCRETE_STEP(dss_adjustment)
+{
+ INT32 rawportval = input_port_read_direct(m_port);
+
+ /* only recompute if the value changed from last time */
+ if (UNEXPECTED(rawportval != m_lastpval))
+ {
+ double portval = (double)(rawportval - m_pmin) * m_pscale;
+ double scaledval = portval * m_scale + m_min;
+
+ m_lastpval = rawportval;
+ if (DSS_ADJUSTMENT__LOG == 0)
+ set_output(0, scaledval);
+ else
+ set_output(0, pow(10, scaledval));
+ }
+}
+
+DISCRETE_RESET(dss_adjustment)
+{
+ double min, max;
+
+ m_port = m_device->machine().m_portlist.find((const char *)this->custom_data());
+ if (m_port == NULL)
+ fatalerror("DISCRETE_ADJUSTMENT - NODE_%d has invalid tag", this->index());
+
+ m_lastpval = 0x7fffffff;
+ m_pmin = DSS_ADJUSTMENT__PMIN;
+ m_pscale = 1.0 / (double)(DSS_ADJUSTMENT__PMAX - DSS_ADJUSTMENT__PMIN);
+
+ /* linear scale */
+ if (DSS_ADJUSTMENT__LOG == 0)
+ {
+ m_min = DSS_ADJUSTMENT__MIN;
+ m_scale = DSS_ADJUSTMENT__MAX - DSS_ADJUSTMENT__MIN;
+ }
+
+ /* logarithmic scale */
+ else
+ {
+ /* force minimum and maximum to be > 0 */
+ min = (DSS_ADJUSTMENT__MIN > 0) ? DSS_ADJUSTMENT__MIN : 1;
+ max = (DSS_ADJUSTMENT__MAX > 0) ? DSS_ADJUSTMENT__MAX : 1;
+ m_min = log10(min);
+ m_scale = log10(max) - log10(min);
+ }
+
+ this->step();
+}
+
+
+/************************************************************************
+ *
+ * DSS_CONSTANT - This is a constant.
+ *
+ * input[0] - Constant value
+ *
+ ************************************************************************/
+#define DSS_CONSTANT__INIT DISCRETE_INPUT(0)
+
+DISCRETE_RESET(dss_constant)
+{
+ set_output(0, DSS_CONSTANT__INIT);
+}
+
+
+/************************************************************************
+ *
+ * DSS_INPUT_x - Receives input from discrete_sound_w
+ *
+ * input[0] - Gain value
+ * input[1] - Offset value
+ * input[2] - Starting Position
+ * input[3] - Current data value
+ *
+ ************************************************************************/
+
+DISCRETE_RESET(dss_input_data)
+{
+ m_gain = DSS_INPUT__GAIN;
+ m_offset = DSS_INPUT__OFFSET;
+
+ m_data = DSS_INPUT__INIT;
+ set_output(0, m_data * m_gain + m_offset);
+}
+
+void DISCRETE_CLASS_FUNC(dss_input_data, input_write)(int sub_node, UINT8 data )
+{
+ UINT8 new_data = 0;
+
+ new_data = data;
+
+ if (m_data != new_data)
+ {
+ /* Bring the system up to now */
+ m_device->update_to_current_time();
+
+ m_data = new_data;
+
+ /* Update the node output here so we don't have to do it each step */
+ set_output(0, m_data * m_gain + m_offset);
+ }
+}
+
+DISCRETE_RESET(dss_input_logic)
+{
+ m_gain = DSS_INPUT__GAIN;
+ m_offset = DSS_INPUT__OFFSET;
+
+ m_data = (DSS_INPUT__INIT == 0) ? 0 : 1;
+ set_output(0, m_data * m_gain + m_offset);
+}
+
+void DISCRETE_CLASS_FUNC(dss_input_logic, input_write)(int sub_node, UINT8 data )
+{
+ UINT8 new_data = 0;
+
+ new_data = data ? 1 : 0;
+
+ if (m_data != new_data)
+ {
+ /* Bring the system up to now */
+ m_device->update_to_current_time();
+
+ m_data = new_data;
+
+ /* Update the node output here so we don't have to do it each step */
+ set_output(0, m_data * m_gain + m_offset);
+ }
+}
+
+DISCRETE_RESET(dss_input_not)
+{
+ m_gain = DSS_INPUT__GAIN;
+ m_offset = DSS_INPUT__OFFSET;
+
+ m_data = (DSS_INPUT__INIT == 0) ? 1 : 0;
+ set_output(0, m_data * m_gain + m_offset);
+}
+
+void DISCRETE_CLASS_FUNC(dss_input_not, input_write)(int sub_node, UINT8 data )
+{
+ UINT8 new_data = 0;
+
+ new_data = data ? 0 : 1;
+
+ if (m_data != new_data)
+ {
+ /* Bring the system up to now */
+ m_device->update_to_current_time();
+
+ m_data = new_data;
+
+ /* Update the node output here so we don't have to do it each step */
+ set_output(0, m_data * m_gain + m_offset);
+ }
+}
+
+DISCRETE_STEP(dss_input_pulse)
+{
+ /* Set a valid output */
+ set_output(0, m_data);
+ /* Reset the input to default for the next cycle */
+ /* node order is now important */
+ m_data = DSS_INPUT__INIT;
+}
+
+DISCRETE_RESET(dss_input_pulse)
+{
+ m_data = (DSS_INPUT__INIT == 0) ? 0 : 1;
+ set_output(0, m_data);
+}
+
+void DISCRETE_CLASS_FUNC(dss_input_pulse, input_write)(int sub_node, UINT8 data )
+{
+ UINT8 new_data = 0;
+
+ new_data = data ? 1 : 0;
+
+ if (m_data != new_data)
+ {
+ /* Bring the system up to now */
+ m_device->update_to_current_time();
+ m_data = new_data;
+ }
+}
+
+/************************************************************************
+ *
+ * DSS_INPUT_STREAM - Receives input from a routed stream
+ *
+ * input[0] - Input stream number
+ * input[1] - Gain value
+ * input[2] - Offset value
+ *
+ ************************************************************************/
+#define DSS_INPUT_STREAM__STREAM DISCRETE_INPUT(0)
+#define DSS_INPUT_STREAM__GAIN DISCRETE_INPUT(1)
+#define DSS_INPUT_STREAM__OFFSET DISCRETE_INPUT(2)
+
+STREAM_UPDATE( discrete_dss_input_stream_node::static_stream_generate )
+{
+ reinterpret_cast<discrete_dss_input_stream_node *>(param)->stream_generate(inputs, outputs, samples);
+}
+
+void discrete_dss_input_stream_node::stream_generate(stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+{
+ stream_sample_t *ptr = outputs[0];
+ int samplenum = samples;
+
+ while (samplenum-- > 0)
+ *(ptr++) = m_data;
+}
+DISCRETE_STEP(dss_input_stream)
+{
+ /* the context pointer is set to point to the current input stream data in discrete_stream_update */
+ if (EXPECTED(m_ptr))
+ {
+ set_output(0, (*m_ptr) * m_gain + m_offset);
+ m_ptr++;
+ }
+ else
+ set_output(0, 0);
+}
+
+DISCRETE_RESET(dss_input_stream)
+{
+ m_ptr = NULL;
+ m_data = 0;
+}
+
+void DISCRETE_CLASS_FUNC(dss_input_stream, input_write)(int sub_node, UINT8 data )
+{
+ UINT8 new_data = 0;
+
+ new_data = data;
+
+ if (m_data != new_data)
+ {
+ if (m_is_buffered)
+ {
+ /* Bring the system up to now */
+ m_buffer_stream->update();
+
+ m_data = new_data;
+ }
+ else
+ {
+ /* Bring the system up to now */
+ m_device->update_to_current_time();
+
+ m_data = new_data;
+
+ /* Update the node output here so we don't have to do it each step */
+ set_output(0, new_data * m_gain + m_offset);
+ }
+ }
+}
+
+DISCRETE_START(dss_input_stream)
+{
+ discrete_base_node::start();
+
+ /* Stream out number is set during start */
+ m_stream_in_number = DSS_INPUT_STREAM__STREAM;
+ m_gain = DSS_INPUT_STREAM__GAIN;
+ m_offset = DSS_INPUT_STREAM__OFFSET;
+ m_ptr = NULL;
+
+ m_is_buffered = is_buffered();
+ m_buffer_stream = NULL;
+}
+
+void DISCRETE_CLASS_NAME(dss_input_stream)::stream_start(void)
+{
+ if (m_is_buffered)
+ {
+ /* stream_buffered input only supported for sound devices */
+ discrete_sound_device *snd_device = downcast<discrete_sound_device *>(m_device);
+ //assert(DSS_INPUT_STREAM__STREAM < snd_device->m_input_stream_list.count());
+
+ m_buffer_stream = m_device->machine().sound().stream_alloc(*snd_device, 0, 1, this->sample_rate(), this, static_stream_generate);
+
+ snd_device->get_stream()->set_input(m_stream_in_number, m_buffer_stream);
+ }
+}
diff --git a/trunk/src/emu/sound/disc_mth.c b/trunk/src/emu/sound/disc_mth.c
new file mode 100644
index 00000000000..4fe5b39d310
--- /dev/null
+++ b/trunk/src/emu/sound/disc_mth.c
@@ -0,0 +1,2771 @@
+/************************************************************************
+ *
+ * MAME - Discrete sound system emulation library
+ *
+ * Written by Keith Wilkins (mame@esplexo.co.uk)
+ *
+ * (c) K.Wilkins 2000
+ * (c) D.Renaud 2003-2004
+ *
+ ************************************************************************
+ *
+ * DST_ADDDER - Multichannel adder
+ * DST_BITS_DECODE - Decode Bits from input node
+ * DST_CLAMP - Simple signal clamping circuit
+ * DST_COMP_ADDER - Selectable parallel component circuit
+ * DST_DAC_R1 - R1 Ladder DAC with cap filtering
+ * DST_DIODE_MIX - Diode mixer
+ * DST_DIVIDE - Division function
+ * DST_GAIN - Gain Factor
+ * DST_INTEGRATE - Integration circuits
+ * DST_LOGIC_INV - Logic level invertor
+ * DST_LOGIC_AND - Logic AND gate 4 input
+ * DST_LOGIC_NAND - Logic NAND gate 4 input
+ * DST_LOGIC_OR - Logic OR gate 4 input
+ * DST_LOGIC_NOR - Logic NOR gate 4 input
+ * DST_LOGIC_XOR - Logic XOR gate 2 input
+ * DST_LOGIC_NXOR - Logic NXOR gate 2 input
+ * DST_LOGIC_DFF - Logic D-type flip/flop
+ * DST_LOGIC_JKFF - Logic JK-type flip/flop
+ * DST_LOGIC_SHIFT - Logic Shift Register
+ * DST_LOOKUP_TABLE - Return value from lookup table
+ * DST_MIXER - Final Mixer Stage
+ * DST_MULTIPLEX - 1 of x Multiplexer/switch
+ * DST_ONESHOT - One shot pulse generator
+ * DST_RAMP - Ramp up/down
+ * DST_SAMPHOLD - Sample & Hold Implementation
+ * DST_SWITCH - Switch implementation
+ * DST_ASWITCH - Analog switch
+ * DST_TRANSFORM - Multiple math functions
+ * DST_OP_AMP - Op Amp circuits
+ * DST_OP_AMP_1SHT - Op Amp One Shot
+ * DST_TVCA_OP_AMP - Triggered op amp voltage controlled amplifier
+ * DST_XTIME_BUFFER - Buffer/Invertor gate implementation using X_TIME
+ * DST_XTIME_AND - AND/NAND gate implementation using X_TIME
+ * DST_XTIME_OR - OR/NOR gate implementation using X_TIME
+ * DST_XTIME_XOR - XOR/XNOR gate implementation using X_TIME
+ *
+ ************************************************************************/
+
+#include <float.h>
+
+
+
+/************************************************************************
+ *
+ * DST_ADDER - This is a 4 channel input adder with enable function
+ *
+ * input[0] - Enable input value
+ * input[1] - Channel0 input value
+ * input[2] - Channel1 input value
+ * input[3] - Channel2 input value
+ * input[4] - Channel3 input value
+ *
+ ************************************************************************/
+#define DST_ADDER__ENABLE DISCRETE_INPUT(0)
+#define DST_ADDER__IN0 DISCRETE_INPUT(1)
+#define DST_ADDER__IN1 DISCRETE_INPUT(2)
+#define DST_ADDER__IN2 DISCRETE_INPUT(3)
+#define DST_ADDER__IN3 DISCRETE_INPUT(4)
+
+DISCRETE_STEP(dst_adder)
+{
+ if(DST_ADDER__ENABLE)
+ {
+ set_output(0, DST_ADDER__IN0 + DST_ADDER__IN1 + DST_ADDER__IN2 + DST_ADDER__IN3);
+ }
+ else
+ {
+ set_output(0, 0);
+ }
+}
+
+
+/************************************************************************
+ *
+ * DST_COMP_ADDER - Selectable parallel component adder
+ *
+ * input[0] - Bit Select
+ *
+ * Also passed discrete_comp_adder_table structure
+ *
+ * Mar 2004, D Renaud.
+ ************************************************************************/
+#define DST_COMP_ADDER__SELECT DISCRETE_INPUT(0)
+
+DISCRETE_STEP(dst_comp_adder)
+{
+ int select;
+
+ select = (int)DST_COMP_ADDER__SELECT;
+ assert(select < 256);
+ set_output(0, m_total[select]);
+}
+
+DISCRETE_RESET(dst_comp_adder)
+{
+ DISCRETE_DECLARE_INFO(discrete_comp_adder_table)
+
+ int i, bit;
+ int bit_length = info->length;
+
+ assert(bit_length <= 8);
+
+ /* pre-calculate all possible values to speed up step routine */
+ for(i = 0; i < 256; i++)
+ {
+ switch (info->type)
+ {
+ case DISC_COMP_P_CAPACITOR:
+ m_total[i] = info->cDefault;
+ for(bit = 0; bit < bit_length; bit++)
+ {
+ if (i & (1 << bit))
+ m_total[i] += info->c[bit];
+ }
+ break;
+ case DISC_COMP_P_RESISTOR:
+ m_total[i] = (info->cDefault != 0) ? 1.0 / info->cDefault : 0;
+ for(bit = 0; bit < bit_length; bit++)
+ {
+ if ((i & (1 << bit)) && (info->c[bit] != 0))
+ m_total[i] += 1.0 / info->c[bit];
+ }
+ if (m_total[i] != 0)
+ m_total[i] = 1.0 / m_total[i];
+ break;
+ }
+ }
+ set_output(0, m_total[0]);
+}
+
+/************************************************************************
+ *
+ * DST_CLAMP - Simple signal clamping circuit
+ *
+ * input[0] - Input value
+ * input[1] - Minimum value